pax_global_header00006660000000000000000000000064147042010560014511gustar00rootroot0000000000000052 comment=e3d4084720f6047b8338a0855e345aa5c3c3c8f2 cryptography-primitives-1.0.0/000077500000000000000000000000001470420105600164335ustar00rootroot00000000000000cryptography-primitives-1.0.0/.clang-format000066400000000000000000000022171470420105600210100ustar00rootroot00000000000000 #=============================================================================== # Copyright (C) 2022 Intel Corporation # # 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. # #=============================================================================== BasedOnStyle: WebKit AlignAfterOpenBracket: Align AlignConsecutiveAssignments: true AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false BinPackArguments: false BinPackParameters: false BreakBeforeBinaryOperators: None ColumnLimit: 150 ContinuationIndentWidth: 3 IndentWidth: 3 MaxEmptyLinesToKeep: 3 PointerAlignment: Right SortIncludes: false cryptography-primitives-1.0.0/.clang-tidy000066400000000000000000000016421470420105600204720ustar00rootroot00000000000000#=============================================================================== # Copyright (C) 2024 Intel Corporation # # 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. # #=============================================================================== Checks: ' -*, bugprone-infinite-loop, misc-header-include-cycle, readability-duplicate-include' HeaderFilterRegex: '.*(/include/ipp/|/sources/ippcp/|/examples/).*' cryptography-primitives-1.0.0/.gitattributes000066400000000000000000000012521470420105600213260ustar00rootroot00000000000000# Set the default behavior, in case people don't have core.autocrlf set. * text=auto # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. *.c text *.h text *.cpp text *.def text *.rc text *.i text *.sh text *.csh text *.mk text *.java text *.csv text *.lst text # Declare files that will always have CRLF line endings on checkout. *.sln text eol=crlf *.bat text eol=crlf # Declare files that will always have LF line endings on checkout. *.py text eol=lf # Denote all files that are truly binary and should not be modified. *.png binary *.jpg binary *.lib binary *.dll binary *.dylib binary *.so binary *.a binary cryptography-primitives-1.0.0/.gitignore000066400000000000000000000007131470420105600204240ustar00rootroot00000000000000# Common certs and secrets *.pem *.pgp *.gpg *.key *.crt ## Common Linux files ## # Backup or temp files *~ *.pyc *.obj .idea __pycache__/ _build .vscode doc/source/nocp-parameters.xml nocp-parameters.xml # temporary files if a process still has a handle open of a deleted file .fuse_hidden* ## Common Mac files ## .DS_Store .AppleDouble .LSOverride ._* ## Common Windows files ## Thumbs.db Thumbs.db:encryptable ehthumbs.db ehthumbs_vista.db *.lnk cryptography-primitives-1.0.0/BUILD.md000066400000000000000000000411671470420105600176250ustar00rootroot00000000000000# How to Build Intel® Cryptography Primitives Library - [Software Requirements](#software-requirements) - [Common tools](#common-tools) - [Linux* OS](#linux-os) - [Windows* OS](#windows-os) - [macOS*](#macos) - [Building Intel® Cryptography Primitives Library on Linux\* OS](#building-intel-cryptography-primitives-library-on-linux-os) - [Building Intel® Cryptography Primitives Library on Windows\* OS](#building-intel-cryptography-primitives-library-on-windows-os) - [Building Intel® Cryptography Primitives Library on macOS\*](#building-intel-cryptography-primitives-library-on-macos) - [CMake Build Options](#cmake-build-options) - [Common for all operating systems](#common-for-all-operating-systems) - [Windows\* OS](#windows-os) - [Linux\* OS](#linux-os) - [CMake Commands FAQ](#cmake-commands-faq) - [How to build a 32-bit library?](#how-to-build-a-32-bit-library) - [How to build a 64-bit generic library without any CPU-specific optimizations?](#how-to-build-a-64-bit-generic-library-without-any-cpu-specific-optimizations) - [How to build two libraries with optimizations for Intel® Advanced Vector Extensions 2 and Intel® Advanced Vector Extensions 512 instruction sets?](#how-to-build-two-libraries-with-optimizations-for-intel-advanced-vector-extensions-2-and-intel-advanced-vector-extensions-512-instruction-sets) - [How to build a library to work in a kernel space?](#how-to-build-a-library-to-work-in-a-kernel-space) - [Incorporating Intel® Cryptography Primitives Library sources into custom build system](#incorporating-intel-cryptography-primitives-library-sources-into-custom-build-system) ## Software Requirements ### Common tools - [CMake\*](https://cmake.org/download) 3.18 or higher - Python 3.8.1 - The Netwide Assembler (NASM) 2.16.02 - OpenSSL\* 3.0.8 or higher **OR** BoringSSL* [45cf810d](https://github.com/google/boringssl/archive/45cf810dbdbd767f09f8cb0b0fcccd342c39041f.tar.gz) **OR** Tongsuo* 8.3.3 ### Linux* OS - [Common tools](#common-tools) - Intel® oneAPI DPC++/C++ Compiler latest for Linux\* OS - GCC 8.5 - GCC 11.4 - GCC 14.1 - Clang 9.0 - Clang 12.0 - Clang 16.0 - GNU binutils 2.32 > **NOTE:** [CMake\*](https://cmake.org/download) 3.22 or higher is required to build using Intel® oneAPI DPC++/C++ Compiler. ### Windows* OS - [Common tools](#common-tools) - Intel® oneAPI DPC++/C++ Compiler latest for Windows\* OS - Microsoft Visual C++ Compiler\* version 19.29 provided by Microsoft Visual Studio\* 2019 version 16.11 - Microsoft Visual C++ Compiler\* version 19.30 provided by Microsoft Visual Studio\* 2022 version 17.11 > **NOTE:** [CMake\*](https://cmake.org/download) 3.21 or higher is required to build using Microsoft Visual Studio\* 2022. > **NOTE:** [CMake\*](https://cmake.org/download) 3.22 or higher is required to build using Intel® oneAPI DPC++/C++ Compiler. ### macOS* - [Common tools](#common-tools) - Intel® C++ Compiler Classic 2021.9 for macOS\* ## Building Intel® Cryptography Primitives Library on Linux\* OS The software was validated on: - Red Hat\* Enterprise Linux\* 8 To build the Intel® Cryptography Primitives Library on Linux\* OS, complete the following steps: 1. Clone the source code from GitHub\* as follows: ``` bash git clone --recursive https://github.com/intel/ipp-crypto ``` 2. Set the environment for one of the supported C/C++ compilers. *example for Intel® oneAPI DPC++/C++ Compiler:* ```bash source /opt/intel/oneapi/setvars.sh intel64 ``` For details, refer to the [Intel® oneAPI DPC++/C++ Compiler Developer Guide and Reference](https://www.intel.com/content/www/us/en/docs/dpcpp-cpp-compiler/developer-guide-reference/current/specifying-the-location-of-compiler-components.html). 3. Run CMake\* in the command line. *Examples*: for Intel® oneAPI DPC++/C++ Compiler: ``` bash CC=icx CXX=icpx cmake CMakeLists.txt -B_build -DARCH=intel64 ``` For GCC: ``` bash CC=gcc CXX=g++ cmake CMakeLists.txt -B_build -DARCH=intel64 ``` For the complete list of supported CMake options, refer to the [CMake Build Options](#cmake-build-options) section. 4. Navigate to the build folder specified in the CMake command line and start the build: ```bash cd _build make all ``` You can find the built libraries in the `/.build//lib` directory. ## Building Intel® Cryptography Primitives Library on Windows\* OS The software was validated on: - Windows Server\* 2019 To build the Intel® Cryptography Primitives Library on Windows* OS, complete the following steps: 1. Clone the source code from GitHub\* as follows: ``` bash git clone --recursive https://github.com/intel/ipp-crypto ``` 2. Set the environment variables for one of the supported C/C++ compilers. For Intel® oneAPI DPC++/C++ Compiler instructions, refer to the [Intel® oneAPI DPC++/C++ Compiler Developer Guide and Reference](https://www.intel.com/content/www/us/en/docs/dpcpp-cpp-compiler/developer-guide-reference/current/specifying-the-location-of-compiler-components.html). For MSVC* Compiler, refer to [Use the MSVC toolset from the command line](https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-160). 3. Run CMake\* in the command line. *Examples*: For Intel® oneAPI DPC++/C++ Compiler and Visual Studio\* 2019: ``` bash cmake CMakeLists.txt -B_build -G"Visual Studio 16 2019" -T"Intel C++ Compiler 2024" -Ax64 ``` For MSVC\* Compiler and Visual Studio\* 2019: ``` bash cmake CMakeLists.txt -B_build -G"Visual Studio 16 2019" -Ax64 ``` For the complete list of supported CMake options, please refer to the [CMake Build Options](#cmake-build-options) section. 4. Navigate to the build folder, specified in the CMake command line and start build either from Visual Studio\* or in the command line. *Build from command line:* ```bash cmake --build . --parallel 4 --target ALL_BUILD --config Release ``` *Build from Visual Studio\*:* Open the Microsoft Visual Studio\* solution `Intel(R) IPP Crypto.sln`, choose project (build target) from the Solution Explorer and run the build. ## Building Intel® Cryptography Primitives Library on macOS\* > **NOTE:** Intel® Cryptography Primitives Library stopped macOS\* validation and maintenance based on the announcement in the [Intel® Integrated Performance Primitives Cryptography (Intel® IPP Cryptography) 2021.9 release notes](https://www.intel.com/content/www/us/en/developer/articles/release-notes/release-notes-for-oneapi-integrated-performance-primitives.html#inpage-nav-3-1).\ The Intel® IPP Cryptography 2021.10 release is the last release validated on macOS\* 12.0.\ For further macOS\* testing and maintenance we are relying on contributions from the community. For more details, see [Contributing Rules](./CONTRIBUTING.md). To build the Intel® Cryptography Primitives Library on macOS\*, complete the following steps: 1. Clone the source code from GitHub\* as follows: ``` bash git clone --recursive https://github.com/intel/ipp-crypto ``` 2. Set the environment variables for one of the supported C/C++ compilers. *Example for Intel® Compiler:* ```bash source /opt/intel/bin/compilervars.sh intel64 ``` For details, refer to the [Intel® C++ Compiler Developer Guide and Reference](https://www.intel.com/content/www/us/en/docs/cpp-compiler/developer-guide-reference/current/specifying-the-location-of-compiler-components.html) 3. Run CMake\* in the command line. *Examples*: For Intel® C++ Compiler: ``` bash CC=icc CXX=icpc cmake CMakeLists.txt -B_build -DARCH=intel64 ``` For the complete list of supported CMake options, refer to the [CMake Build Options](#cmake-build-options) section. 4. Navigate to the build folder specified in the CMake command line and start the build: ```bash cd _build make all ``` You can find the built libraries in the `/.build//lib` directory. ## CMake Build Options ### Common for all operating systems - `-B` - defines the build directory. This is the directory where CMake puts the generated Microsoft Visual Studio\* solution or makefiles. - `-DARCH=` - on Linux* OS and macOS*, defines the target architecture for the build of the Intel® Cryptography Primitives Library. > **NOTE:** On Windows* OS, use `-G`/`-A` instead. See the description of these options [below](#windows-os-1). > **NOTE:** Due to the significant shift in the industry towards 64-bit architecture, the support of 32-bit libraries is deprecated in the Intel® IPP Cryptography 2021.9 release and targeted to be removed after one year deprecation notice period. - `-DMERGED_BLD:BOOL=` - optional. Defines the configuration of the Intel® Cryptography Primitives Library to build: - `-DMERGED_BLD:BOOL=on`: default configuration. It includes the following steps: - Build of a dispatched static library with all available optimizations - Build of a dispatched dynamic library with all available optimizations - Generation of the single-CPU headers (for details, refer to [this](./OVERVIEW.md) section) - `-DMERGED_BLD:BOOL=off`: build of one static library per optimization; build of one dynamic library per optimization. - `-DPLATFORM_LIST=""` - optional, works only if `-DMERGED_BLD:BOOL=off` is set. Sets target platforms for the code to be compiled. See the supported platforms list [here](./OVERVIEW.md). - Example for Linux\* OS and the IA-32 architecture: `-DPLATFORM_LIST="w7;s8;p8;g9;h9"` - Example for Linux\* OS and the Intel® 64 architecture: `-DPLATFORM_LIST="m7;n8;y8;e9;l9;k0;k1"` - `-DNO_CRYPTO_MB:BOOL=TRUE` - optional, turns off the build of [Crypto Multi Buffer library](./sources/ippcp/crypto_mb/Readme.md) and, as a consequence, removes all dependencies on OpenSSL library. - `-DTONGSUO:BOOL=on`, `-DBORINGSSL:BOOL=on` - required only if forks of OpenSSL library are used to resolve OpenSSL dependencies - Tongsuo and BoringSSL respectively. These flags make sense when [Crypto Multi Buffer library](./sources/ippcp/crypto_mb/Readme.md) is built. > **NOTE:** -DBABASSL:BOOL=on flag is deprecated and targeted to be removed in the future releases. Please use -DTONGSUO:BOOL=on instead.\*. - `-DIPPCP_CUSTOM_BUILD=""` - optional, works only if `-DMERGED_BLD:BOOL=off` is set, i.e. only for 1CPU libraries. Enables the CPU feature dispatching mask at compile-time based on the provided list. - Currently supported by the library custom features dispatching: 1. Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) code-path enabling: `IPPCP_AES_ON;IPPCP_CLMUL_ON` 2. Intel® Advanced Vector Extensions 512 (Intel® AVX-512) / Intel® Advanced Vector Extensions 2 (Intel® AVX2) vector extensions of Intel® AES New Instructions (Intel® AES-NI) code-paths enabling: `IPPCP_VAES_ON;IPPCP_VCLMUL_ON`. - Example: `-DIPPCP_CUSTOM_BUILD="IPPCP_AES_ON;IPPCP_CLMUL_ON"` - this combination enables Intel® AES-NI in all 1CPU libraries, which contains this code path. - Example of using a combination of CPU features: `-DIPPCP_CUSTOM_BUILD="IPPCP_AES_ON;IPPCP_CLMUL_ON;IPPCP_VAES_ON;IPPCP_VCLMUL_ON"` - in this combination the highest available feature in each 1CPU library will be enabled (e.g. for `"y8"` it’s Intel® AES-NI, for `"l9"` it's Intel® AVX2 VAES, and for `"k1"` - Intel® AVX-512 VAES) - `-DIPPCP_FIPS_MODE:BOOL=` - optional. Regulates the build of FIPS-compliant Intel® Cryptography Primitives Library. - `-DIPPCP_FIPS_MODE:BOOL=on`: enables all FIPS-compliance changes in Intel® Cryptography Primitives Library. - `-DIPPCP_FIPS_MODE:BOOL=off`: default configuration. Intel® Cryptography Primitives Library build with such option is not FIPS-compliant. - `-DIPPCP_SELFTEST_USE_MALLOC:BOOL=` - optional. Enables internal memory allocation and release using `malloc()` and `free()` functions inside Intel® Cryptography Primitives Library selftests. - `-DIPPCP_SELFTEST_USE_MALLOC:BOOL=on`: memory management is held by FIPS selftests, all processing APIs should be called with input parameters equal to `NULL`. - `-DIPPCP_SELFTEST_USE_MALLOC:BOOL=off`: default configuration. Memory management is held by customer's application, all processing APIs should be called with work buffers of the valid length. - `-DMBX_FIPS_MODE:BOOL=` - optional. Regulates the build of FIPS-compliant Crypto Multi-buffer Library. - `-DMBX_FIPS_MODE:BOOL=on`: enables all FIPS-compliance changes in Crypto Multi-buffer Library. - `-DMBX_FIPS_MODE:BOOL=off`: default configuration. Crypto Multi-buffer Library build with such option is not FIPS-compliant. - `-DFIPS_CUSTOM_IPPCP_API_HEADER=` - optional flag which allows to use FIPS self-tests with IPPCP API with a different prefix to support capabilities of the custom dispatcher generated by Custom Library Tool (Please, note that it is only intended for a very specific use case of [Custom Library](./OVERVIEW.md/#static-library-with-custom-functionality)).The header should contain redefinitions of IPPCP public API, e.g. `#define ippcpGetLibVersion custom_prefix_ippcpGetLibVersion`. The flag is applicable only when IPPCP FIPS mode is enabled (`-DIPPCP_FIPS_MODE:BOOL=on`). ### Windows\* OS - `-G""` - defines the native build system CMake will generate from the input files. Refer to CMake [documentation](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators) for the Visual Studio\* generators options. - `-A` - for Visual Studio\* 2019+, defines the target architecture for the build of the Intel® Cryptography Primitives Library. - `-T` - defines the compiler for building. For example, to use Intel® oneAPI DPC++/C++ Compiler, specify `-T"Intel C++ Compiler 2024"`. > **NOTE:** Refer to CMake [documentation](https://cmake.org/cmake/help/latest/manual/ccmake.1.html) for more information on these options. ### Linux\* OS - `-DNONPIC_LIB:BOOL=` - optional. Defines whether the built library is position-dependent or not. - `-DNONPIC_LIB:BOOL=off:` default. Position-independent code. - `-DNONPIC_LIB:BOOL=on:` position-dependent code. ## CMake Commands FAQ ### How to build a 64-bit generic library without any CPU-specific optimizations? `cmake CMakeLists.txt -B_build -DARCH=intel64 -DMERGED_BLD:BOOL=off -DPLATFORM_LIST=mx` ### How to build two libraries with optimizations for Intel® Advanced Vector Extensions 2 and Intel® Advanced Vector Extensions 512 instruction sets? `cmake CMakeLists.txt -B_build -DARCH=intel64 -DMERGED_BLD:BOOL=off -DPLATFORM_LIST="l9;k0"` ### How to build a library to work in a kernel space? `cmake CMakeLists.txt -B_build -DARCH=intel64 -DNONPIC_LIB:BOOL=on` ### How to specify path to OpenSSL\* `cmake CMakeLists.txt -B_build -DARCH=intel64 -DOPENSSL_INCLUDE_DIR=/path/to/openssl/include -DOPENSSL_LIBRARIES=/path/to/openssl/lib -DOPENSSL_ROOT_DIR=/path/to/openssl` ## Incorporating Intel® Cryptography Primitives Library sources into custom build system You can include Intel® Cryptography Primitives Library sources into some arbitrary project's CMake build system and build them with it. Here is the minimal working example: ``` bash cmake_minimum_required(VERSION 3.18) project("test_proj") # `crypto` is the repository root folder of Intel® Cryptography Primitives Library add_subdirectory(crypto) include_directories(crypto/include) # 'main.cpp' is some arbitrary project's source file add_executable("test_proj" main.cpp) # `ippcp_s` is the target name of static library in the Intel® Cryptography Primitives Library build system. # This static library will be built automatically, when you build your project. target_link_libraries("test_proj" "ippcp_s") ``` Also you can use the CMake module to find the Intel® Cryptography Primitives Library installed on the system. The module location is `examples/FindIPPCrypto.cmake` and here is the example of its usage: ``` bash find_package(IPPCrypto REQUIRED MODULE) if (NOT IPPCRYPTO_FOUND) message(FATAL_ERROR "No Intel® Cryptography Primitives Library found on the system.") endif() # If Intel® Cryptography Primitives Library is found, the following variables will be defined: # `IPPCRYPTO_LIBRARIES` - static library name # `IPPCRYPTO_INCLUDE_DIRS` - path to Intel® Cryptography Primitives Library headers # `IPPCRYPTO_ROOT_DIR` - library root dir (a folder with 'include' and 'lib' directories) ``` ### How to run Intel® IPP Cryptography with clang-tidy? `CC=clang CXX=clang++ cmake CMakeLists.txt -B_build -DARCH=intel64 -DCRYPTO_USE_CLANG_TIDY:BOOL=on`cryptography-primitives-1.0.0/CHANGELOG.md000066400000000000000000000320721470420105600202500ustar00rootroot00000000000000# Intel® Cryptography Primitives Library This is a list of notable changes to Intel® Cryptography Primitives Library, in reverse chronological order. ## Intel(R) Cryptography Primitives Library 1.0.0 - Intel® Integrated Performance Primitives Cryptography (Intel® IPP Cryptography) was renamed to Intel(R) Cryptography Primitives Library. - Added IPPCP SM3 hash algorithm optimization with the new instruction set (SM3-NI) for Lunar Lake and Arrow Lake CPUs. - Added Intel® AVX-IFMA RSA implementation to Crypto Multi buffer library. - Fixed bug in IceLake optimization (`k1` branch) of ECDSA signature function caused by incorrect processing of R and S component's size and sign. - Added FIPS selftest for Leighton-Micali Hash-Based Signatures(LMS) verification algorithm. - Added examples for SM3 Hash / LMS post-quantum verification / NIST Curve P-256 ECDSA signature generation algorithms. - Changed `-DBABASSL:BOOL=on` CMake build option to `-DTONGSUO:BOOL=on` for Tongsuo library. - Removed API that were deprecated in Intel® Integrated Performance Primitives Cryptography 2020 Update1. More details can be found in [DEPRECATION_NOTES.md](./DEPRECATION_NOTES.md). Please note that `ippsHash` API still remain in the library. - Removed support for SSSE3(`s8` for ia32 and `n8` for intel64) and AVX(`g9` for ia32 and `e9` for intel64) code-paths. Execution was moved to SSE3(`w7` for ia32 and `m7` for intel64) and SSE4.2(`p8` for ia32 and `y8` for intel64) respectively. There is still the possibility to use 1cpu headers and 1cpu libraries without breaking change for 1 year but some performance drops are expected. ## Intel(R) IPP Cryptography 2021.12.1 - Added `FIPS_CUSTOM_IPPCP_API_HEADER` build flag to support FIPS self-tests for a specific use case when Custom Library Tool is used with custom prefix for IPPCP API. ## Intel(R) IPP Cryptography 2021.12 - Added single-buffer implementation of Leighton-Micali Hash-Based Signatures(LMS) algorithm, verification part. - Added support of Clang 16.0 compiler for Linux. - Added examples of AES-GCM Encryption/Decryption usage. - AES-GCM algorithm with Intel® Advanced Vector Extensions 2 (Intel® AVX2) vector extensions of Intel® AES New Instructions (Intel® AES-NI) was optimized. ## Intel(R) IPP Cryptography 2021.11 - Minimal supported BoringSSL version was increased to [45cf810d](https://github.com/google/boringssl/archive/45cf810dbdbd767f09f8cb0b0fcccd342c39041f.tar.gz) tag. ## Intel(R) IPP Cryptography 2021.10 - Added the verification part of eXtended Merkle Signature Scheme (XMSS) algorithm. - Added FIPS-compliance mode for the library. More information can be found in the [Intel(R) IPP Cryptography FIPS Guide](./README_FIPS.md). ## Intel(R) IPP Cryptography 2021.9 - Added optimized RSA-2048 code for multi-buffer (8 buffers) Intel® AVX-512 implementation. - Added Intel® Advanced Vector Extensions 2 (Intel® AVX2) vector extensions of Intel® AES New Instructions (Intel® AES-NI) optimization for AES-GCM algorithm. - Changed the minimal supported OpenSSL version to 3.0.8 since 1.1.1 is not supported since September 2023. - Raised the minimal CMake version to 3.18 since this is the minimal version that supports OpenSSL 3.0.8: https://cmake.org/cmake/help/latest/module/FindOpenSSL.html. ## Intel(R) IPP Cryptography 2021.8 - Crypto Multi-buffer library was extended with XTS mode of SM4 algorithm. ## Intel(R) IPP Cryptography 2021.7.1 - Added re-initialization API for AES-GCM context - ippsAES_GCMReinit. The use-case of this function is very specific, please, refer to the documentation for more details. ## Intel(R) IPP Cryptography 2021.7 - Mitigation for Frequency Throttling Side-Channel Attack ([Frequency Throttling Side Channel Software Guidance for Cryptography Implementations](https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/frequency-throttling-side-channel-guidance.html)) was added for ECB, CMAC and GCM modes of AES (for more details refer to ippsAESSetupNoise, ippsAES_GCMSetupNoise and ippsAES_CMACSetupNoise). - Crypto Multi-buffer library was extended with CCM and GCM modes of SM4 algorithm. - In Crypto Multi-buffer library in-place mode of executing (when pa_out == pa_inp) was fixed for SM4 CBC and CFB modes. - New API that updates pointer to IppsHashMethod context inside the IppsHashState_rmf state was added (please, refer to ippsHashStateMethodSet_ API). - ippsHMAC_Pack(_rmf), ippsHMAC_Unpack(_rmf) APIs were fixed - context id is set up properly now during the packing-unpacking process. ## Intel(R) IPP Cryptography 2021.6 - EC cryptography functionality for the NIST curves p256r1, p384r1, p521r1 and SM2 curve was enabled with Intel® Advanced Vector Extensions 512 (Intel® AVX-512) IFMA instructions. - EC cryptography functionality input parameters checking was improved by adding keys boundaries check. - AES-GCM input parameters checking was improved by adding input text boundary check. - An issue in AES-CTR Intel® Advanced Vector Extensions 512 (Intel® AVX-512) code path related to handling of last partial block was fixed. - The ability to build Intel® IPP Cryptography library and Crypto Multi buffer library with Microsoft Visual C++ Compiler\* version 19.30 provided by Microsoft Visual Studio\* 2022 version 17.0 was added. ## Intel(R) IPP Cryptography 2021.5 - AES-GCM small packets processing was optimized for Intel® Advanced Vector Extensions 512 (Intel® AVX-512) code path. - The ability to build Intel® IPP Cryptography library and Crypto Multi buffer library with GCC\* 10, GCC\* 11, Clang\* 9, Clang\* 12 and Intel® C++ Compiler Classic 2021.3 was added. - The ability to build Crypto Multi buffer library with OpenSSL\* 3.0 was added. ## Intel(R) IPP Cryptography 2021.4 - Crypto Multi buffer library was extended with ECB, CBC, CTR, OFB and CFB modes of SM4 algorithm. - Crypto Multi buffer library was extended with EC SM2 public key generation, ECDHE and ECDSA (Sign and Verify) algorithms. - Crypto Multi buffer library extended with ECDSA Ed25519 verify algorithm. - Crypto Multi buffer library extended with modular exponent algorithm. ## Intel(R) IPP Cryptography 2021.3 - Enabled ECDSA Ed25519sign crypto multi buffer API within Intel® IPP Cryptography for 3rd Generation Intel® Xeon® Processor Scalable and 10th Gen Intel® Core™ Processors. - Enabled RSA single buffer 3k, 4k within Intel® IPP Cryptography for 3rd Generation Intel® Xeon® Processor Scalable and 10th Gen Intel® Core™ Processors. - Fixed Intel® IPP Cryptography AES-GCM decryption incorrect tag issue while dispatching on processors supported with Intel® Advanced Vector Extensions 512 (Intel® AVX-512). ## Intel(R) IPP Cryptography 2021.2 - Crypto Multi buffer library was extended with ECDSA (Sign) and ECDHE for the NIST curves p521r1. - Added ECDSA verify with new Instruction Set Architecture(ISA) for the NIST curve p384r1, p256r1 and p521r1. - Added SM3 multi buffer with new Instruction Set Architecture(ISA). - Added new Intel® IPP Cryptography pre-defined hash algorithm APIs ippsHashMethodGetSize and ippsHashMethodInit. - RSA-2048 decryption (CRT) was enabled for Intel(R) Microarchitecture Code Named Ice Lake. - Crypto Multi buffer library was extended with ECDSA (Sign) and ECDHE for the NIST curves p256r1 and p384r1. - Fixed a build issue that affect build of the Intel(R) IPP Cryptography library with MSVC\* compiler on Windows\* OS. - Duplicated APIs of HASH, HMAC, MGF, RSA, ECCP functionality were marked as deprecated. For more information see [Deprecation notes](./DEPRECATION_NOTES.md) - Added examples demonstrating usage of SMS4-CBC encryption and decryption. ## Intel(R) IPP Cryptography 2020 Update 3 - Refactoring of Crypto Multi buffer library, added build and installation of crypto_mb dynamic library and CPU features detection. - Added multi buffer implementation of AES-CFB optimized with Intel(R) AES New Instructions (Intel(R) AES-NI) and vector extensions of Intel(R) AES New Instructions (Intel(R) AES-NI) instruction sets. - Fixed compatibility issue with x64 ABI (restored non-volatile registers after function call in Intel® Advanced Vector Extensions (Intel® AVX)/Intel® Advanced Vector Extensions 2 (Intel® AVX2) assembly code). - Updated Intel IPP Custom Library Tool. ## Intel(R) IPP Cryptography 2020 Update 2 - AES-GCM algorithm was optimized for Intel(R) Microarchitecture Code Named Cascade Lake with Intel(R) AES New Instructions (Intel(R) AES-NI). - Crypto Multi buffer library installation instructions update. The Readme file of Crypto Multi buffer Library was updated by information about possible installation fails in specific environment. - Position Independent Execution (PIE) option was added to Crypto Multi buffer Library build scripts. - AES-XTS optimization for Intel(R) Microarchitecture Code Named Ice Lake with vector extensions of Intel(R) AES New Instructions (Intel(R) AES-NI) was improved. - SM4-ECB, SM4-CBC and SM4-CTR were enabled for Intel(R) Microarchitecture Code Named Ice Lake with Intel(R) Advanced Vector Extensions 512 (Intel(R) AVX-512) GFNI instructions. - Added support of Clang 9.0 for Linux and Clang 11.0 for MacOS compilers. - Added example of RSA Multi Buffer Encryption/Decryption usage. - The library was enabled with Intel® Control-Flow Enforcement Technology (Intel® CET) on Linux and Windows. - Changed API of ippsGFpECSignDSA, ippsGFpECSignNR and ippsGFpECSignSM2 functions: const-ness requirement of private ephemeral keys is removed and now the ephemeral keys are cleaned up after signing. ## Intel(R) IPP Cryptography 2020 Update 1 - Added RSA IFMA Muti-buffer Library. - Added RSA PSS multi buffer signature generation and verification. - Added RSA PKCS#1 v1.5 multi buffer signature generation and verification. - Removed Android support. Use Linux libraries instead. - Fixed all build warnings for supported GCC\* and MSVC\* compilers. - Assembler sources were migrated to NASM\* assembler. ## Intel(R) IPP Cryptography 2020 - Added RSA multi buffer encryption and decryption. - Added Intel(R) IPP Cryptography library examples: AES-CTR, RSA-OAEP, RSA-PSS. - Fixed code generation for kernel code model in Linux* Intel(R) 64 non-PIC builds. - Fixes in Intel IPP Custom Library Tool. - Added Microsoft\* Visual Studio\* 2019 build support. - A dynamic dispatcher library and a set of CPU-optimized dynamic libraries were replaced by a single merged dynamic library with an internal dispatcher. - Removed deprecated multi-threaded version of the library. - Removed Supplemental Streaming SIMD Extensions 3 (SSSE3) support on macOS. ## Intel(R) IPP Cryptography 2019 Update 5 - 1024, 2048, 3072 and 4096 bit RSA were enabled with AVX512 IFMA instructions. - AES-GCM was enabled with vector extensions of Intel(R) AES New Instructions (Intel(R) AES-NI). - AES-XTS was enabled with vector extensions of Intel(R) AES New Instructions (Intel(R) AES-NI). - Fixed GCC\* and MSVC\* builds of IA32 generic CPU code (pure C) with -DMERGED_BLD:BOOL=off option. - Added single-CPU headers generation. - Aligned structure of the build output directory across all supported operation systems. - AES-CFB was enabled with vector extensions of Intel(R) AES New Instructions (Intel(R) AES-NI). - ippsGFpECGetPointOctString and ippsGFpECSetPointOctString now support elliptic curves over both prime and extended finite fields. - Added the ability to build the Intel(R) IPP Cryptography library with GCC\* 8.2. ## Intel(R) IPP Cryptography 2019 Update 4 - AES-ECB, AES-CBC and AES-CTR were enabled with vector extensions of Intel(R) AES New Instructions (Intel(R) AES-NI). - Improved optimization of Intel(R) AES-NI based CMAC. - Added the ippsGFpGetInfo function, which returns information about a finite field. - Added the ippsHashGetInfo_rmf function, which returns information about a hash algorithm. - Fixed selection of CPU-specific code in dynamic/shared libraries. ## Intel(R) IPP Cryptography 2019 Update 3 - Added the ability to build the Intel(R) IPP Cryptography library with the Intel(R) C++ Compiler 19. - Added Intel IPP Custom Library Tool based on Python. ## Intel(R) IPP Cryptography 2019 Update 1 - Added the ability to build the Intel(R) IPP Cryptography library with the Microsoft\* Visual C++ Compiler 2017. - Added the new SM2 encryption scheme. - Changed the range of the message being signed or verified by EC and DLP. - Deprecated the ARCFour functionality. - Fixed a potential security problem in the signing functions over elliptic curves. - Fixed a potential security problem in the key expansion function for AES Encryption. - Fixed a potential security problem in the AES-CTR cipher functions. - Fixed a potential security problem in the AES-GCM cipher functions. - Fixed a potential security problem in the DLP signing and key generation functions. - Fixed minor issues with DLP functions. - Fixed some of the compilation warnings observed when building the static dispatcher on Windows\* OS. ------------------------------------------------------------------------ Intel is a trademark of Intel Corporation or its subsidiaries in the U.S. and/or other countries. \* Other names and brands may be claimed as the property of others. cryptography-primitives-1.0.0/CMakeLists.txt000066400000000000000000000220541470420105600211760ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # cmake_minimum_required(VERSION 3.12) include("${CMAKE_CURRENT_SOURCE_DIR}/sources/cmake/ippcp-utils.cmake") ippcp_getlibversion("${CMAKE_CURRENT_SOURCE_DIR}/include/ippcpversion.h") if ((NOT DEFINED IPPCP_VERSION_MAJOR) OR (NOT DEFINED IPPCP_VERSION_MINOR) OR (NOT DEFINED IPPCP_VERSION_UPDATE) OR (NOT DEFINED IPPCP_INTERFACE_VERSION_MAJOR) OR (NOT DEFINED IPPCP_INTERFACE_VERSION_MINOR)) message(WARNING "Cannot parse version from ippcpversion.h file. The project might be corrupted.") endif() set(PROJECT_FULL_NAME "Intel® Cryptography Primitives Library") set(PROJECT_VERSION ${IPPCP_VERSION}) set(LIB_NAME ippcp) set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) cmake_policy(SET CMP0042 NEW) cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0068 NEW) if("${CMAKE_GENERATOR}" STREQUAL "NMake Makefiles") if(NOT(C_COMPILER STREQUAL "")) set(CMAKE_C_COMPILER ${C_COMPILER}) endif() if(NOT(CXX_COMPILER STREQUAL "")) set(CMAKE_CXX_COMPILER ${CXX_COMPILER}) endif() endif() project(${PROJECT_FULL_NAME} VERSION ${PROJECT_VERSION} LANGUAGES C CXX) if("${CMAKE_BUILD_TYPE}" STREQUAL "") message(STATUS "CMAKE_BUILD_TYPE is unset, defaulting to Release") set(CMAKE_BUILD_TYPE "Release") endif() find_package(Python REQUIRED) if(WIN32 AND (${CMAKE_GENERATOR} MATCHES "Visual Studio")) if(CMAKE_GENERATOR_PLATFORM) # VS 2019+ -A param if(${CMAKE_GENERATOR_PLATFORM} MATCHES "x64") set(ARCH intel64) else() set(ARCH ia32) endif() else() if(${CMAKE_GENERATOR} MATCHES "Win64") # old way of platform setting for VS set(ARCH intel64) else() set(ARCH ia32) endif() endif() else() if (NOT "${ARCH}" STREQUAL "intel64" AND NOT "${ARCH}" STREQUAL "ia32") message(FATAL_ERROR "Please, set the ARCH parameter to ia32 or intel64") endif() endif(WIN32 AND (${CMAKE_GENERATOR} MATCHES "Visual Studio")) if ((NOT NONPIC_LIB) AND (NOT CODE_COVERAGE)) set(DYNAMIC_LIB ON) else() set(DYNAMIC_LIB OFF) endif() if("${MERGED_BLD}" STREQUAL "") set(MERGED_BLD ON) endif() # Set default installation directories if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if (UNIX) set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/intel/ippcp_${PROJECT_VERSION}" CACHE PATH "..." FORCE) else() set(CMAKE_INSTALL_PREFIX "c:/Program Files (x86)/IntelSWTools/ippcp_${PROJECT_VERSION}" CACHE PATH "..." FORCE) endif() endif() set(IPP_CRYPTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}") set(IPP_CRYPTO_INCLUDE_DIR "${IPP_CRYPTO_DIR}/include") set(IPP_CRYPTO_SOURCES_INCLUDE_DIR "${IPP_CRYPTO_DIR}/sources/include") set(IPP_CRYPTO_SOURCES_DIR "${IPP_CRYPTO_DIR}/sources/ippcp") set(IPP_CRYPTO_DISPATCHER_DIR "${IPP_CRYPTO_DIR}/sources/dispatcher") set(TOOLS_DIR "${IPP_CRYPTO_DIR}/tools") if(NOT CMAKE_OUTPUT_DIR) set(CMAKE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/.build") endif() message (STATUS "CMAKE_VERSION ......................... " ${CMAKE_VERSION}) if(UNIX AND NOT APPLE) if(NONPIC_LIB) message (STATUS "NONPIC_LIB ............................ on") else() message (STATUS "NONPIC_LIB ............................ off") endif() else() set(${NONPIC_LIB} false) endif(UNIX AND NOT APPLE) set(NONPIC_SUBDIRECTORY "") if(NONPIC_LIB) set(NONPIC_SUBDIRECTORY "/nonpic") endif() foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/lib${NONPIC_SUBDIRECTORY}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/lib${NONPIC_SUBDIRECTORY}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/lib${NONPIC_SUBDIRECTORY}") endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) if(${CMAKE_BUILD_TYPE} STREQUAL "Release") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE}") endif() if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG}") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG}") endif() if (CRYPTO_USE_CLANG_TIDY AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "12.0.0") find_program(DO_CLANG_TIDY NAMES clang-tidy) set(CMAKE_CXX_CLANG_TIDY ${DO_CLANG_TIDY}) set(CMAKE_C_CLANG_TIDY ${DO_CLANG_TIDY}) endif () message (STATUS "PROJECT ............................... " ${PROJECT_FULL_NAME}) message (STATUS "CMAKE_BINARY_DIR ...................... " ${CMAKE_BINARY_DIR}) message (STATUS "CMAKE_OUTPUT_DIR ...................... " ${CMAKE_OUTPUT_DIR}) message (STATUS "CMAKE_SOURCE_DIR ...................... " ${CMAKE_SOURCE_DIR}) message (STATUS "IPP_CRYPTO_DIR ........................ " ${IPP_CRYPTO_DIR}) message (STATUS "CMAKE_GENERATOR ....................... " ${CMAKE_GENERATOR}) message (STATUS "CMAKE_C_COMPILER_ID ................... " ${CMAKE_C_COMPILER_ID}) message (STATUS "CMAKE_CXX_COMPILER_ID ................. " ${CMAKE_CXX_COMPILER_ID}) message (STATUS "IPP_CRYPTO_INCLUDE_DIR ................ " ${IPP_CRYPTO_INCLUDE_DIR}) message (STATUS "IPP_CRYPTO_SOURCES_INCLUDE_DIR ........ " ${IPP_CRYPTO_SOURCES_INCLUDE_DIR}) message (STATUS "IPP_CRYPTO_SOURCES_DIR ................ " ${IPP_CRYPTO_SOURCES_DIR}) message (STATUS "ARCH .................................. " ${ARCH}) message (STATUS "DYNAMIC_LIB ........................... " ${DYNAMIC_LIB}) message (STATUS "CMAKE_INSTALL_PREFIX .................. " ${CMAKE_INSTALL_PREFIX}) if(CRYPTO_USE_CLANG_TIDY) message (STATUS "CLANG_TIDY ............................ on") else() message (STATUS "CLANG_TIDY ............................ off") endif() if(Python_Interpreter_FOUND) message (STATUS "PYTHON_VERSION_STRING ................. " ${Python_VERSION}) else() message (STATUS "PYTHON_VERSION_STRING ................. Python not found" ) endif() if(MERGED_BLD) message (STATUS "MERGED_BLD ............................ on") else() message (STATUS "MERGED_BLD ............................ off") endif() option(BUILD_EXAMPLES "Build examples" OFF) if(BUILD_EXAMPLES) message (STATUS "BUILD_EXAMPLES ........................ on") else() message (STATUS "BUILD_EXAMPLES ........................ off") endif() # Build with sanitizers set(SANITIZERS OFF) if(BUILD_WITH_SANITIZERS AND UNIX AND ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" AND ${CMAKE_CXX_COMPILER_VERSION} VERSION_GREATER_EQUAL "12.0.0") set(ASAN OFF) set(UBSAN OFF) set(MSAN OFF) if("${BUILD_WITH_SANITIZERS}" MATCHES "address") set(ASAN ON) list(APPEND PRINT_TYPES_OF_SANITIZERS_LIST "address") endif() if("${BUILD_WITH_SANITIZERS}" MATCHES "undefined") set(UBSAN ON) list(APPEND PRINT_TYPES_OF_SANITIZERS_LIST "undefined") endif() if("${BUILD_WITH_SANITIZERS}" MATCHES "memory") set(MSAN ON) list(APPEND PRINT_TYPES_OF_SANITIZERS_LIST "memory") endif() if((ASAN OR UBSAN) AND MSAN) message (FATAL_ERROR "Can not use address | undefined sanitizers with memory sanitizer") endif() if(ASAN OR UBSAN OR MSAN) set(SANITIZERS ON) endif() endif() if(SANITIZERS) list(JOIN PRINT_TYPES_OF_SANITIZERS_LIST "," PRINT_TYPES_OF_SANITIZERS_STRING) message (STATUS "BUILD_WITH_SANITIZERS ................. on (${PRINT_TYPES_OF_SANITIZERS_STRING})") else() message (STATUS "BUILD_WITH_SANITIZERS ................. off - use -DBUILD_WITH_SANITIZERS=[memory,address,undefined] with CLANG compiler to enable this option") endif(SANITIZERS) if((UNIX) AND (NOT APPLE)) set(LINUX ON) else() set(LINUX OFF) endif() add_subdirectory(sources/ippcp) if (NOT (CRYPTO_USE_CLANG_TIDY)) if(EXISTS "${IPP_CRYPTO_DIR}/tests/") add_subdirectory(tests) endif() if(EXISTS "${IPP_CRYPTO_DIR}/perf_tests/") add_subdirectory(perf_tests) endif() endif() if(BUILD_EXAMPLES) # This helps to organize examples projects structure in IDE by folders set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMakeTargets") add_subdirectory(examples) endif() cryptography-primitives-1.0.0/CONST_TIME_EXECUTION_TESTING.md000066400000000000000000000434621470420105600233120ustar00rootroot00000000000000# Scope of the Constant-time execution testing of Intel® Cryptography Primitives Library - [General information](#general) - [Scope for ippcp library](#ippcp) - [Scope for crypto_mb library](#cryptomb) ## General information
- Testing is conducted under Linux for 64-bit Intel® Cryptography Primitives Library built with the compilers listed in [Build](./BUILD.md). - Tested platforms: m7, y8, l9, k0, k1 (see the supported platforms list [here](./OVERVIEW.md#target-optimization-codes-in-function-names)). - Testing scope described below is guaranteed to pass for **`release`** branches. This is not guaranteed for the **`develop`** branch ([branches description](./OVERVIEW.md#branches-description)) - Information about Pin-Based Constant Execution Checker can be found [here](https://github.com/intel/pin_based_cec) ## ippcp library
| Tested Function | Parameters | | :----------------------: | :----------------------------------------------------------------------------------------: | | ippsAESEncryptCBC | Different key length:
128, 192, 256 bits | | ippsAESDecryptCBC | Different key length:
128, 192, 256 bits | | ippsAESEncryptCBC_CS1 | Different key length:
128, 192, 256 bits | | ippsAESDecryptCBC_CS1 | Different key length:
128, 192, 256 bits | | ippsAESEncryptCBC_CS2 | Different key length:
128, 192, 256 bits | | ippsAESDecryptCBC_CS2 | Different key length:
128, 192, 256 bits | | ippsAESEncryptCBC_CS3 | Different key length:
128, 192, 256 bits | | ippsAESDecryptCBC_CS3 | Different key length:
128, 192, 256 bits | | ippsAES_CCMEncrypt | Different key length:
128, 192, 256 bits | | ippsAES_CCMDecrypt | Different key length:
128, 192, 256 bits | | ippsAESEncryptCFB | Different key length:
128, 192, 256 bits | | ippsAESDecryptCFB | Different key length:
128, 192, 256 bits | | ippsAES_CMACUpdate | Different key length:
128, 192, 256 bits | | ippsAES_CMACFinal | Different key length:
128, 192, 256 bits | | ippsAESEncryptCTR | Different key length:
128, 192, 256 bits | | ippsAESDecryptCTR | Different key length:
128, 192, 256 bits | | ippsAESEncryptECB | Different key length:
128, 192, 256 bits | | ippsAESDecryptECB | Different key length:
128, 192, 256 bits | | ippsAES_GCMEncrypt | Different key length:
128, 192, 256 bits | | ippsAES_GCMDecrypt | Different key length:
128, 192, 256 bits | | ippsAES_GCMStart | Different key length:
128, 192, 256 bits | | ippsAESEncryptOFB | Different key length:
128, 192, 256 bits | | ippsAESDecryptOFB | Different key length:
128, 192, 256 bits | | ippsAES_S2V_CMAC | Different key length:
128, 192, 256 bits | | ippsAESSetKey | Different key length:
128, 192, 256 bits | | ippsAES_SIVEncrypt | Different key length:
128, 192, 256 bits | | ippsAES_SIVDecrypt | Different key length:
128, 192, 256 bits | | ippsAES_XTSEncrypt | Different key length:
256, 512 bits | | ippsAES_XTSDecrypt | Different key length:
256, 512 bits | | ippsAESEncryptXTS_Direct | Different key length:
256, 512 bits | | ippsAESDecryptXTS_Direct | Different key length:
256, 512 bits | | ippsCmp_BN | - | | ippsDLPPublicKey | - | | ippsDLPSharedSecretDH | - | | ippsGFpAdd | - | | ippsGFpAdd_PE | - | | ippsGFpConj | - | | ippsGFpECAddPoint | Different curves:
p256r1, p384r1, p521r1 | | ippsGFpECMulPoint | Different curves:
p224r1, p256r1, p384r1 | | ippsGFpECNegPoint | Different curves:
p256r1, p384r1, p521r1 | | ippsGFpECPublicKey | Different curves:
p256r1, p384r1, p521r1 | | ippsGFpECSharedSecretDH | Different curves:
p256r1, p384r1, p521r1 | | ippsGFpECSharedSecretDHC | Different curves:
p256r1, p384r1, p521r1 | | ippsGFpECSignDSA | Different curves:
p256r1, p384r1 | | ippsGFpECSignNR | Different curves:
p256r1, p384r1 | | ippsGFpECSignSM2 | - | | ippsGFpECESStart_SM2 | - | | ippsGFpECESEncrypt_SM2 | - | | ippsGFpECESDecrypt_SM2 | - | | ippsGFpECESFinal_SM2 | - | | ippsGFpExp | - | | ippsGFpInv | - | | ippsGFpMul | - | | ippsGFpMul_PE | - | | ippsGFpMultiExp | - | | ippsGFpNeg | - | | ippsGFpSqr | - | | ippsGFpSub | - | | ippsGFpSub_PE | - | | ippsHMACInit_rmf | Different hashes:
sha1, sha256, sha224, sha384, sha512,
sha512-256, sha512-224, sm3 | | ippsRSA_Decrypt | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsRSADecrypt_OAEP | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsRSADecrypt_OAEP_rmf | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsRSASign_PKCS1v15 | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsRSASign_PKCS1v15_rmf | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsRSASign_PSS | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsRSASign_PSS_rmf | Different key types and key length:
key type 1, 512 bits
key type 2, 512 bits | | ippsSMS4EncryptCBC | - | | ippsSMS4DecryptCBC | - | | ippsSMS4EncryptCBC_CS1 | - | | ippsSMS4DecryptCBC_CS1 | - | | ippsSMS4EncryptCBC_CS2 | - | | ippsSMS4DecryptCBC_CS2 | - | | ippsSMS4EncryptCBC_CS3 | - | | ippsSMS4DecryptCBC_CS3 | - | | ippsSMS4_CCMEncrypt | - | | ippsSMS4_CCMDecrypt | - | | ippsSMS4EncryptCFB | - | | ippsSMS4DecryptCFB | - | | ippsSMS4EncryptCTR | - | | ippsSMS4DecryptCTR | - | | ippsSMS4EncryptECB | - | | ippsSMS4DecryptECB | - | | ippsSMS4EncryptOFB | - | | ippsSMS4DecryptOFB | - | | ippsSMS4SetKey | - | ## crypto_mb library
| Function | Parameters | | :--------------------------------------: | :---------------------------------------------------: | | mbx_nistp256_ecpublic_key_mb8 | projective coordinates
affine coordinates | | mbx_nistp384_ecpublic_key_mb8 | projective coordinates
affine coordinates | | mbx_nistp521_ecpublic_key_mb8 | projective coordinates
affine coordinates | | mbx_sm2_ecpublic_key_mb8 | projective coordinates
affine coordinates | | mbx_nistp256_ecdh_mb8 | projective coordinates
affine coordinates | | mbx_nistp384_ecdh_mb8 | projective coordinates
affine coordinates | | mbx_nistp521_ecdh_mb8 | projective coordinates
affine coordinates | | mbx_nistp256_ecdsa_sign_mb8 | - | | mbx_nistp384_ecdsa_sign_mb8 | - | | mbx_nistp521_ecdsa_sign_mb8 | - | | mbx_nistp256_ecdsa_sign_setup_mb8 | - | | mbx_nistp384_ecdsa_sign_setup_mb8 | - | | mbx_nistp521_ecdsa_sign_setup_mb8 | - | | mbx_nistp256_ecdsa_sign_complete_mb8 | - | | mbx_nistp384_ecdsa_sign_complete_mb8 | - | | mbx_nistp521_ecdsa_sign_complete_mb8 | - | | mbx_nistp256_ecpublic_key_ssl_mb8 | projective coordinates
affine coordinates | | mbx_nistp384_ecpublic_key_ssl_mb8 | projective coordinates
affine coordinates | | mbx_nistp521_ecpublic_key_ssl_mb8 | projective coordinates
affine coordinates | | mbx_sm2_ecpublic_key_ssl_mb8 | projective coordinates
affine coordinates | | mbx_nistp256_ecdh_ssl_mb8 | projective coordinates
affine coordinates | | mbx_nistp384_ecdh_ssl_mb8 | projective coordinates
affine coordinates | | mbx_nistp521_ecdh_ssl_mb8 | projective coordinates
affine coordinates | | mbx_nistp256_ecdsa_sign_ssl_mb8 | - | | mbx_nistp384_ecdsa_sign_ssl_mb8 | - | | mbx_nistp521_ecdsa_sign_ssl_mb8 | - | | mbx_nistp256_ecdsa_sign_setup_ssl_mb8 | - | | mbx_nistp384_ecdsa_sign_setup_ssl_mb8 | - | | mbx_nistp521_ecdsa_sign_setup_ssl_mb8 | - | | mbx_nistp256_ecdsa_sign_complete_ssl_mb8 | - | | mbx_nistp384_ecdsa_sign_complete_ssl_mb8 | - | | mbx_nistp521_ecdsa_sign_complete_ssl_mb8 | - | | mbx_ed25519_public_key_mb8 | - | | mbx_ed25519_sign_mb8 | - | | mbx_rsa_private_mb8 | Different key length:
1024, 2048, 3072, 4096 bits | | mbx_rsa_private_crt_mb8 | Different key length:
1024, 2048, 3072, 4096 bits | | mbx_rsa_private_ssl_mb8 | Different key length:
1024, 2048, 3072, 4096 bits | | mbx_rsa_private_crt_ssl_mb8 | Different key length:
1024, 2048, 3072, 4096 bits | | mbx_sm2_ecdsa_sign_mb8 | - | | mbx_sm2_ecdsa_sign_ssl_mb8 | - | | mbx_sm4_encrypt_ecb_mb16 | - | | mbx_sm4_decrypt_ecb_mb16 | - | | mbx_sm4_encrypt_cbc_mb16 | - | | mbx_sm4_decrypt_cbc_mb16 | - | | mbx_sm4_encrypt_ctr128_mb16 | - | | mbx_sm4_encrypt_ofb_mb16 | - | | mbx_sm4_encrypt_cfb128_mb16 | - | | mbx_sm4_decrypt_cfb128_mb16 | - | | mbx_sm4_xts_encrypt_mb16 | - | | mbx_sm4_xts_decrypt_mb16 | - | | mbx_sm4_ccm_init_mb16 | - | | mbx_sm4_ccm_update_aad_mb16 | - | | mbx_sm4_ccm_encrypt_mb16 | - | | mbx_sm4_ccm_decrypt_mb16 | - | | mbx_sm4_ccm_get_tag_mb16 | - | | mbx_sm4_gcm_init_mb16 | - | | mbx_sm4_gcm_update_iv_mb16 | - | | mbx_sm4_gcm_update_aad_mb16 | - | | mbx_sm4_gcm_encrypt_mb16 | - | | mbx_sm4_gcm_decrypt_mb16 | - | | mbx_sm4_gcm_get_tag_mb16 | - | | mbx_x25519_public_key_mb8 | - | | mbx_x25519_mb8 | - | cryptography-primitives-1.0.0/CONTRIBUTING.md000066400000000000000000000103551470420105600206700ustar00rootroot00000000000000Intel® Cryptography Primitives Library Contribution Rules ========================================================= ## How to Contribute We welcome community contributions to Intel® Cryptography Primitives Library! If you have an idea how to improve the product: - Let us know via [GitHub* Issues](https://github.com/intel/ipp-crypto/issues). - Send your proposal directly via [pull request](https://github.com/intel/ipp-crypto/pulls). ## Intel® Cryptography Primitives Library repository scheme Intel® Cryptography Primitives Library supports two repositories that are named as "Public Repository" and "Inner Repository". Privately hosted "Inner Repository" is required for extensive internal testing and experimental features development. Existing automation guarantees regular synchronization of repositories.
  +-------------+                     +------------+
  | Public Repo |        regular      | Inner Repo |
  | ----------- |    synchronization  |  --------  |       +----------+
  |    rev.1    | <------------------ |    rev.1   |       | internal |
  |    rev.2    |   bunch of changes  |    rev.2   |-----> | testing  |
  |    rev.3    |                     |    rev.3   |       +----------+
  +-------------+                     +------------+
## License Intel® Cryptography Primitives Library is licensed under the terms in LICENSE . By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. ## Developer Certification of Origin (DCO) We encourage you to use Signed-off-by feature to comply with [Developer Certification of Origin (DCO)](https://developercertificate.org/). The name in the commit message Signed-off-by line and your email must match the change authorship information. Make sure your .gitconfig is set up correctly so you can use `git commit -s` for signing your commits: `git config --global user.name "Kris Smith"` `git config --global user.email Kris.Smith@company.com` ## Contribution Flow - Contributor creates fork from develop, commits the changes into the created branch, opens a PR and requests a review. - Contributor applies feedback provided by Intel® Cryptography Primitives Library repository maintainer in opened PR. - Intel® Cryptography Primitives Library repository maintainer must ensure that the code is safe for internal execution, get code into inner repository and run private testing. - Intel® Cryptography Primitives Library repository maintainer merges the changes "as is" from inner repository, when private testing is passed. > **Note** > Original PR is closed because merging PRs on the external GitHub repo isn't supported. - Contributions will be available in the "Public repository", once the nearest cycle of synchronization from "Inner Repository" to "Public Repository" happens.

  +-----------------+
  |   Public Repo   |
  |   -----------   |
  |   PR is open    |
  |       |         |
  |       |         |
  |       |         |                      +--------------------+
  |  Code Review    |                      |     Inner Repo     |
  |   has passed    |                      |      ---------     |
  |       |         |  PR is cherry-picked |    Heavy private   |
  |       |---------|----------------------|->     testing      |
  |       |         |   to "Inner Repo"    |          |         |
  |  PR is closed   |                      |          |         |
  +-----------------+                      |  Cherry-picked PR  |
                                           |     is merged      |
                                           |  to "Inner Repo"   |
                                           +--------------------+

## Pull Request Checklist Before sending your pull requests, ensure that: - Intel® Cryptography Primitives Library builds successfully with proposed changes using one of the compilers listed in [Build](./BUILD.md). Please specify which exact compiler was used. - Relevant documentation are added (for example CHANDELOG.md, README.md etc) - For new features make sure that - All new files are covered by copyrights. - All new internal functions are documented in comments. - Relevant examples are added(if required). cryptography-primitives-1.0.0/DEPRECATION_NOTES.md000066400000000000000000000467471470420105600215040ustar00rootroot00000000000000# Deprecated API in Intel® Cryptography Primitives Library This document describes deprecated API in different Intel® Cryptography Primitives Library versions and recommendations for transition. The deprecated API means it is obsolete and will be removed in one of future Intel® Cryptography Primitives Library releases. If you have any concerns, please use the following link for opening a ticket and providing feedback: ## Intel® Cryptography Primitives Library v1.0.0 ### Service Functions | Deprecated | Recommended replacement | | :------------------------------------------------ | :------------------------------------------------------------: | | ippcpGetNumThreads | N/A | | ippcpGetEnabledNumThreads | N/A | | ippcpSetNumThreads | N/A | | ippcpGetLibVersion | cryptoGetLibVersion | ### Deprecated Optimizations The code paths n8/s8 (Intel® SSSE3) and g9/e9 (Intel® AVX) are deprecated and removed from the merged build of Intel® Cryptography Primitives Library, lower optimizations are used instead. 1cpu headers are still available for all code paths. These branches can also be built as 1cpu libraries if specified in the platform list, e.g. `-DMERGED_BLD:BOOL=off -DPLATFORM_LIST=s8;e9`. ## Intel® Integrated Performance Primitives Cryptography (Intel® IPP Cryptography) 2020 Update1 (branch [ipp-crypto_2020_update1](https://github.com/intel/ipp-crypto/tree/ipp-crypto_2020_update1)) ### Hash Functionality | Deprecated | Recommended replacement | | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------: | | ippsSHA1GetSize
ippsSHA224GetSize
ippsSHA256GetSize
ippsSHA384GetSize
ippsSHA512GetSize
ippsSM3GetSize
ippsMD5GetSize | ippsHashGetSize_rmf | | ippsSHA1Init
ippsSHA224Init
ippsSHA256Init
ippsSHA384Init
ippsSHA512Init
ippsSM3Init
ippsMD5Init | ippsHashInit_rmf \* | | ippsSHA1Duplicate
ippsSHA224Duplicate
ippsSHA256Duplicate
ippsSHA384Duplicate
ippsSHA512Duplicate
ippsSM3Duplicate
ippsMD5Duplicate | ippsHashDuplicate_rmf | | ippsSHA1Pack, ippsSHA1Unpack
ippsSHA224Pack, ippsSHA224Unpack
ippsSHA256Pack, ippsSHA256Unpack
ippsSHA384Pack, ippsSHA384Unpack
ippsSHA512Pack, ippsSHA512Unpack
ippsSM3Pack, ippsSM3Unpack
ippsMD5Pack, ippsMD5Unpack | ippsHashPack_rmf,
ippsHashUnpack_rmf | | ippsSHA1Update, ippsSHA1GetTag, ippsSHA1Final
ippsSHA224Update, ippsSHA224GetTag, ippsSHA224Final
ippsSHA256Update, ippsSHA256GetTag, ippsSHA256Final
ippsSHA384Update, ippsSHA384GetTag, ippsSHA384Final
ippsSHA512Update, ippsSHA512GetTag, ippsSHA512Final
ippsSM3Update, ippsSM3GetTag, ippsSM3Final
ippsMD5Update, ippsMD5GetTag, ippsMD5Final | ippsHashUpdate_rmf,
ippsHashGetTag_rmf,
ippsHashFinal_rmf | | ippsSHA1MessageDigest
ippsSHA224MessageDigest
ippsSHA256MessageDigest
ippsSHA384MessageDigest
ippsSHA512MessageDigest
ippsSM3MessageDigest
ippsMD5MessageDigest | ippsHashMessage_rmf \* | | ippsHashGetSize | ippsHashGetSize_rmf | | ippsHashInit \*\* | ippsHashInit_rmf \* | | ippsHashDuplicate | ippsHashDuplicate_rmf | | ippsHashPack, ippsHashUnpack | ippsHashPack_rmf, ippsHashUnpack_rmf | | ippsHashUpdate, ippsHashGetTag,ippsHashFinal | ippsHashUpdate_rmf,ippsHashGetTag_rmf,ippsHashFinal_rmf | | ippsHashMessage \*\* | ippsHashMessage_rmf \* | >\* To choose hash algorithm, specify [IppsHashMethod parameter](#ippshashalgid-to-ippshashmethod-parameter-map) >\*\* IppsHashAlgId parameter used in ippsHMAC_Init and in ippsHMAC_Message for choosing hash algorithm is deprecated (see Recommended replacement column for alternative in [IppsHashAlgId to IppsHashMethod Parameter Map](#ippshashalgid-to-ippshashmethod-parameter-map) ### Keyed HMAC Functionality | Deprecated | Recommended replacement | | :------------------------------------------------ | :------------------------------------------------------------: | | ippsHMAC_GetSize | ippsHMAC_GetSize_rmf | | ippsHMAC_Init \*\* | ippsHMAC_Init_rmf \* | | ippsHMAC_Pack, ippsHMAC_Unack, ippsHMAC_Duplicate | ippsHMAC_Pack_rmf, ippsHMAC_Unpack_rmf, ippsHMAC_Duplicate_rmf | | ippsHMAC_Update, ippsHMAC_Final, ippsHMAC_GetTag | ippsHMAC_Update_rmf, ippsHMAC_Final_rmf, ippsHMAC_GetTag_rmf | | ippsHMAC_Message \*\* | ippsHMAC_Message_rmf \* | >\* To choose hash algorithm, specify [IppsHashMethod parameter](#ippshashalgid-to-ippshashmethod-parameter-map) >\*\* IppsHashAlgId parameter used in 'ippsHMAC_Init' and in ippsHMAC_Message for choosing hash algorithm is deprecated (see Recommended replacement column for alternative in [IppsHashAlgId to IppsHashMethod Parameter Map](#ippshashalgid-to-ippshashmethod-parameter-map) ### MGF Functionality | Deprecated | Recommended replacement | | :--------------- | :---------------------: | | ippsHMAC_GetSize | ippsHMAC_GetSize_rmf | ### RSA Encryption and Signature Schemes | Deprecated | Recommended replacement | | :------------------------------------------- | :--------------------------------------------------: | | ippsRSAEncrypt_OAEP, ippsRSADecrypt_OAEP | ippsRSAEncrypt_OAEP_rmf, ippsRSADecrypt_OAEP_rmf | | ippsRSASign_PSS, ippsRSAVerify_PSS | ippsRSASign_PSS_rmf, ippsRSAVerify_PSS_rmf | | ippsRSASign_PKCS1v15, ippsRSAVerify_PKCS1v15 | ippsRSASign_PKCS1v15_rmf, ippsRSAVerify_PKCS1v15_rmf | ### Elliptic Curve Cryptography (ECC) | Deprecated | Recommended replacement | | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | | ippsECCPGetSize
ippsECCPGetSizeStd128r1
ippsECCPGetSizeStd128r2
ippsECCPGetSizeStd192r1
ippsECCPGetSizeStd224r1
ippsECCPGetSizeStd256r1
ippsECCPGetSizeStd384r1
ippsECCPGetSizeStd521r1
ippsECCPGetSizeStdSM2 | ippsGFpECGetSize | | ippsECCPInit
ippsECCPInitStd128r1
ippsECCPInitStd128r2
ippsECCPInitStd192r1
ippsECCPInitStd224r1
ippsECCPInitStd256r1
ippsECCPInitStd384r1
ippsECCPInitStd521r1
ippsECCPInitStdSM2 | ippsGFpECInitStd \*
* ippsGFpECInitStd functions provides both initialization
and set up standard EC set of parameters | | ippsECCPSet | ippsGFpECSet | | ippsECCPSetStd | ippsGFpECInitStd \*
* ippsGFpECInitStd functions provides both initialization
and set up standard EC set of parameters | | ippsECCPSetStd128r1
ippsECCPSetStd128r2
ippsECCPSetStd192r1
ippsECCPSetStd224r1
ippsECCPSetStd256r1
ippsECCPSetStd384r1
ippsECCPSetStd521r1
ippsECCPSetStdSM2 | ippsGFpECInitStd128r1
ippsGFpECInitStd128r2
ippsGFpECInitStd192r1
ippsGFpECInitStd224r1
ippsGFpECInitStd256r1
ippsGFpECInitStd384r1
ippsGFpECInitStd521r1
ippsGFpECInitStdSM2 | | ippsECCPBindGxyTblStd192r1
ippsECCPBindGxyTblStd224r1
ippsECCPBindGxyTblStd256r1
ippsECCPBindGxyTblStd384r1
ippsECCPBindGxyTblStd521r1
ippsECCPBindGxyTblStdSM2 | ippsGFpECBindGxyTblStd192r1
ippsGFpECBindGxyTblStd224r1
ippsGFpECBindGxyTblStd256r1
ippsGFpECBindGxyTblStd384r1
ippsGFpECBindGxyTblStd521r1
ippsGFpECBindGxyTblStdSM2 | | ippsECCPGet
ippsECCPGetOrderBitSize
ippsECCPValidate
ippsECCPPointGetSize, ippsECCPPointInit
ippsECCPSetPointAtInfinity
ippsECCPSetPoint,ippsECCPGetPoint
ippsECCPCheckPoint
ippsECCPComparePoint
ippsECCPNegativePoint
ippsECCPAddPoint
ippsECCPMulPointScalar | ippsGFpECGet
ippsGFpECGetSubgroup
ippsGFpECVerify
ippsGFpECPointGetSize, ippsGFpECPointInit
ippsGFpECSetPointAtInfinity
ippsGFpECSetPointRegular,ippsGFpECGetPointRegular
ippsGFpECTstPoint
ippsGFpECCmpPoint
ippsGFpECNegPoint
ippsGFpECAddPoint
ippsGFpECMulPoint | | ippsECCPGenKeyPair
ippsECCPPublicKey
ippsECCPValidateKeyPair
ippsECCPSetKeyPair | ippsGFpECPrivateKey
ippsGFpECPublicKey
ippsGFpECTstKeyPair
n/a | | ippsECCPSharedSecretDH
ippsECCPSharedSecretDHC | ippsGFpECSharedSecretDH
ippsGFpECSharedSecretDHC | | ippsECCPSignDSA
ippsECCPVerifyDSA
ippsECCPSignNR
ippsECCPVerifyNR
ippsECCPSignSM2
ippsECCPVerifySM2 | ippsGFpECSignDSA
ippsGFpECVerifyDSA
ippsGFpECSignNR
ippsGFpECVerifyNR
ippsGFpECSignSM2
ippsGFpECVerifySM2 | ### IppsHashAlgId to IppsHashMethod Parameter Map | Algorithm | IppsHashAlgId (deprecated) | IppsHashMethod (recommended) | Notes | | :--------: | :------------------------: | :---------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------: | | SHA1 | ippsHashAlg_SHA1 | ippsHashMethod_SHA1
ippsHashMethod_SHA1_NI
ippsHashMethod_SHA1_TT | Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) not supported
Intel SHA-NI only supported
Automatic switch on Intel SHA-NI, if possible (tick-tock) | | SHA224 | ippsHashAlg_SHA224 | ippsHashMethod_SHA224
ippsHashMethod_SHA224_NI
ippsHashMethod_SHA224_TT | Intel SHA-NI not supported
Intel SHA-NI only supported
Automatic switch on Intel SHA-NI, if possible supported | | SHA256 | ippsHashAlg_SHA256 | ippsHashMethod_SHA256
ippsHashMethod_SHA256_NI
ippsHashMethod_SHA256_TT | Intel SHA-NI not supported
Intel SHA-NI only supported
Automatic switch on Intel SHA-NI, if possible supported | | SHA384 | ippsHashAlg_SHA384 | ippsHashMethod_SHA384 | - | | SHA512 | ippsHashAgl_SHA512 | ippsHashMethod_SHA512 | - | | SM3 | ippsHashAlg_SM3 | ippsHashMethod_SM3 | - | | MD5 | ippsHashAlg_MD5 | ippsHashMethod_MD5 | - | | SHA512-224 | ippsHashAlg_SHA512_224 | ippsHashMethod_SHA512_224 | - | | SHA512-256 | ippsHashAlg_SHA512_256 | ippsHashMethod_SHA512_256 | - | cryptography-primitives-1.0.0/LICENSE000066400000000000000000000236721470420105600174520ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS cryptography-primitives-1.0.0/OVERVIEW.md000066400000000000000000000467351470420105600202420ustar00rootroot00000000000000# Intel® Cryptography Primitives Library Overview - [Repository Structure](#repository-structure) - [Branches Description](#branches-description) - [Dispatcher](#dispatcher) - [CPU Dispatching](#cpu-dispatching) - [Target Optimization Codes in Function Names](#target-optimization-codes-in-function-names) - [CPU Feature Dispatching](#cpu-feature-dispatching) - [How to Avoid Dispatcher in All CPUs Static Library](#how-to-avoid-dispatcher-in-all-cpus-static-library) - [Library Configurations](#library-configurations) - [Linkage Mode](#linkage-mode) - [Code Position](#code-position) - [Target Instruction Set Architecture (ISA)](#target-instruction-set-architecture-isa) - [All CPUs Library](#all-cpus-library) - [Specific ISA Library](#specific-isa-library) - [Choosing specific ISA from the All CPUs Static Library](#choosing-specific-isa-from-the-all-cpus-static-library) - [Functionality](#functionality) - [Static Library with Custom functionality](#static-library-with-custom-functionality) - [Dynamic Library with Custom functionality](#dynamic-library-with-custom-functionality) [sha256-dispatching]: ./data/images/README-pictures-0-dispatcher.png "Intel® Cryptography Primitives Library function dispatching scheme" [library configurations]: ./data/images/README-pictures-1-library-configurations.png "Library configurations picture" [build targets]: ./data/images/README-pictures-1a-build-targets.png "Build targets picture" [merged library]: ./data/images/README-pictures-2-merged-library.png "Merged library scheme" [CPU-specific libraries]: ./data/images/README-pictures-3-cpu-specific-libraries.png "CPU-specific libraries scheme" [link-with-merged-library]: ./data/images/README-pictures-4a-1CPU.png "Link with Merged Library picture" [1cpu-link-with-merged-library]: ./data/images/README-pictures-4b-1CPU.png "1CPU link with Merged Library picture" ## Repository Structure ``` bash ├── data/images ├── examples < Examples of the library usage ├── include < Public headers ├── sources │   ├── cmake < OS-specific CMake files │   │   ├── linux │   │   ├── macosx │   │   └── windows │   ├── dispatcher < CPU dispatcher generator │   ├── gen_cpu_spc_header < Single CPU headers generator │   ├── include < Internal headers │   └── ippcp < C-sources │   ├── asm_ia32 < IA-32 Assembler sources │   ├── asm_intel64 < Intel® 64 Assembler sources │   ├── crypto_mb < Sources of the Crypto Multi-buffer library │   ├── fips_cert │   ├── gfpec │   ├── hash │   ├── lms │   └── xmss ├── tools | └── ipp_custom_library_tool_python < Custom Library Tool ├── .clang-format ├── .clang-tidy ├── BUILD.md ├── CHANGELOG.md ├── CMakeLists.txt < Main CMake file ├── CONST_TIME_EXECUTION_TESTING.md < Information about security testing ├── CONTRIBUTING.md ├── DEPRECATION_NOTES.md ├── LICENSE ├── OVERVIEW.md ├── README.md ├── README_FIPS.md < FIPS compliance guide ├── SECURITY.md ├── SUPPORT.md └── THIRD-PARTY-PROGRAMS.txt ``` ### Branches Description - `develop` - snapshots of the library under active development. Contains code that may not be fully functional and that Intel may substantially modify in development of a production version. - `ipp_crypto_` - source code of the official production release ``. ## Dispatcher ### CPU Dispatching For the best performance, Intel® Cryptography Primitives Library uses multiple implementations of each function, optimized for various CPUs, and the [library version targeted for any CPU](#all-cpus-library) contains all of these implementations. With the dispatcher, the library detects an available CPU in a runtime and chooses the best for the current hardware version of a function. The process of dispatching is transparent and you can always call a generic function as illustrated at the picture below. ```mermaid flowchart LR classDef class1 fill:#0054AE, stroke:none, color:#FFFFFF function["ippsAES_GCMEncrypt()"]:::class1 %% Subgraph for Merged Library subgraph ML[**Merged Library**] dispatcher["Dispatcher"]:::class1 m7["m7_ippsAES_GCMEncrypt()"]:::class1 y8["y8_ippsAES_GCMEncrypt()"]:::class1 l9["l9_ippsAES_GCMEncrypt()"]:::class1 k0["k0_ippsAES_GCMEncrypt()"]:::class1 k1["k1_ippsAES_GCMEncrypt()"]:::class1 %% Connections dispatcher == SSE3==> m7 dispatcher == SSSE4.2 ==> y8 dispatcher == AVX2 ==> l9 dispatcher == AVX512 (formerly codenamed SkyLake) ==> k0 dispatcher == AVX512 (formerly codenamed IceLake) ==> k1 end style ML fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF function ==> dispatcher linkStyle 0,1,2,3,4,5 stroke:#FFE500 ``` The prefix before the function name ("m7_", "y8_", etc) is a naming convention for the function implementations that are included in the [library with dispatcher](#all-cpus-library). It refers to the CPU instruction set for which the function is optimized (for all available prefixes see the [table](#target-optimization-codes-in-function-names) below). The dispatcher is designed to add no performance overhead when the library is initialized, in other words, when CPU features are detected. You can initialize the library either explicitly in advance by calling the dedicated function [ippcpInit()](https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-reference/current/init.html) or it will be done implicitly during the first call of any function of the library. By default, the dispatcher chooses the most appropriate optimization for the current hardware, but it is possible to apply the user-chosen one using the [ippcpSetCpuFeatures()](https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-guide-oneapi/current/support-functions.html) function. #### Target Optimization Codes in Function Names | IA-32 Intel® architecture | Intel® 64 architecture | Meaning | | ------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------ | | px | mx | Generic code without hardware specific optimizations suitable for any CPU | | w7 | - | Optimized for processors with Intel® Streaming SIMD Extensions 2 (Intel® SSE2) | | - | m7 | Optimized for processors with Intel® SSE3 | | p8 | y8 | Optimized for processors with Intel® SSE4.2 | | h9 | l9 | Optimized for processors with Intel® Advanced Vector Extensions 2 (Intel® AVX2) | | - | k0 | Optimized for processors with Intel® Advanced Vector Extensions 512 (Intel® AVX-512) (formerly codenamed SkyLake) | | - | k1 | Optimized for processors with Intel® Advanced Vector Extensions 512 (Intel® AVX-512) (formerly codenamed IceLake) | > **NOTE:** Due to the significant shift in the industry towards 64-bit architecture, the support of 32-bit libraries is deprecated in the Intel® Integrated Performance Primitives Cryptography (Intel® IPP Cryptography) 2021.9 release. No new features (only critical security fixes) are targeted for 32-bit libraries and testing scope is limited by Linux OS & Clang compiler. ### CPU Feature Dispatching Besides CPU dispatching that lets the library choose the general instruction set targeted implementation (for example, Intel SSE4.2, Intel AVX-512, and others), there is more granular dispatching that allows configuring usage of particular CPU features within a single instruction set. For example, Intel AVX-512 instruction set contains a VAES (AES Vector Extensions) feature subset, but not all CPUs that have Intel AVX-512 on board support VAES, so the library can automatically detect it in a runtime and enable corresponding optimizations if the feature subset is available. List of CPU feature subsets that the library has special optimizations for: - Intel ADX (ADCX, ADOX) - Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) - Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) - RDRAND - RDSEED - CLMUL - Intel AVX-512/AVX2 VAES - Intel AVX-512 IFMA - Intel AVX-512 GFNI - SM3-NI > **NOTE:** For some features there is also an opportunity to force their dispatching inside the 1CPU libraries manually during the compile time. For more information please, refer to [common for all operating systems CMake build options](./BUILD.md/#common-for-all-operating-systems). ### How to Avoid Dispatcher in All CPUs Static Library To leave only specific ISA when linking with an [All CPUs Static Library](#all-cpus-library) and drop dispatcher, please refer to [this section](#choosing-specific-isa-from-the-all-cpus-static-library). ## Library Configurations The Intel® Cryptography Primitives Library supports configurations by: 1) [*Linkage Mode*](#linkage-mode): to produce a static or dynamic library 2) [*Code Position*](#code-position): to make position independent code (PIC) or non-PIC library 3) *Target Instruction Set Architecture (ISA)*: - [All CPUs Library](#all-cpus-library) - [Specific Instruction Set (ISA) Targeted Library](#specific-isa-library) - [Choosing specific ISA from the All CPUs Static Library](#choosing-specific-isa-from-the-all-cpus-static-library) 4) *Functionality*: - [Library with All functionality](#functionality) - [Static Library with Custom functionality](#static-library-with-custom-functionality) - [Dynamic Library with Custom functionality](#dynamic-library-with-custom-functionality) All possible configuration combinations are shown in the picture below. ```mermaid flowchart %% Style for classes classDef class1 fill:#0054AE, stroke:none, color:#FFFFFF classDef class2 fill:#0054AE, stroke:none, color:#FFFFFF library["Intel® Cryptography Primitives Library"]:::class1 %% Subgraph for the picture subgraph base[" "] subgraph first["Link type "] Static:::class2 Dynamic:::class2 end subgraph second["Position Independent Code"] non-PIC:::class2 PIC:::class2 end subgraph third["Dispatcher"] allCPU["All CPU + Disptacher"]:::class2 singleCPU[Single CPU]:::class2 end subgraph forth["Library Components"] customFunc["Custom Functionality"]:::class2 allFunc["All Functionality"]:::class2 end %% Connections library ==> Static library ==> Dynamic Static ==> non-PIC Static & Dynamic ==> PIC second ==> third allCPU ==> customFunc singleCPU & allCPU ==> allFunc end %% Style for subgraphs style first fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style second fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style third fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style forth fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF linkStyle 0,1,2,3,4,5,6,7,8 stroke:#FFE500 style base fill:none, stroke:#15BCEF, stroke-width:3px ``` ### Linkage Mode The build system is designed to create a dynamic library from the static one, so both build targets for dynamic and static libraries are always generated during CMake phase. The corresponding build target names for the libraries are shown at the picture below (same target names can be used on Linux* OS in the `make` command as well). ![Build targets picture][build targets] ### Code Position Be default, the Intel® Cryptography Primitives Library is built with the [Position Independent Code (PIC)](https://en.wikipedia.org/wiki/Position-independent_code) option. But on Linux* OS, when the library is supposed to work in kernel space, it is possible to compile the static library in a non-PIC mode. For more information about build options, refer to the [Linux* OS build options](./BUILD.md). ### Target Instruction Set Architecture (ISA) #### All CPUs Library Each function of the library is built in several instances with optimizations for each supported instruction set (see example for the `func2` function in green). Those functions instances are all included into a single library along with the [dispatcher](#dispatcher) that lets the library choose right function instance depending on current CPU. Such library build is called a merged library build. ```mermaid flowchart TD %% Style for classes classDef class1 fill:#0054AE, stroke:none, color:#FFFFFF, font-size:16pt classDef class2 fill:#0054AE, stroke:none, color:#FFFFFF, font-size:12pt subgraph base[" "] Dispatcher["Dispatcher"]:::class1 subgraph m7_graph["SSE3 version"] m7_1["m7_func1"]:::class2 m7_2["m7_func2"]:::class2 m7_3["m7_<...>"]:::class2 m7_4["m7_funcN"]:::class2 end subgraph y8_graph["SSE4.2 version"] y8_1["y8_func1"]:::class2 y8_2["y8_func2"]:::class2 y8_3["y8_<...>"]:::class2 y8_4["y8_funcN"]:::class2 end subgraph l9_graph["AVX2 version"] l9_1["l9_func1"]:::class2 l9_2["l9_func2"]:::class2 l9_3["l9_<...>"]:::class2 l9_4["l9_funcN"]:::class2 end subgraph k0_graph["AVX512 k0 version"] k0_1["k0_func1"]:::class2 k0_2["k0_func2"]:::class2 k0_3["k0_<...>"]:::class2 k0_4["k0_funcN"]:::class2 end subgraph k1_graph["AVX512 k1 version"] k1_1["k1_func1"]:::class2 k1_2["k1_func2"]:::class2 k1_3["k1_<...>"]:::class2 k1_4["k1_funcN"]:::class2 end Dispatcher ~~~ m7_graph Dispatcher ~~~ y8_graph Dispatcher ~~~ l9_graph Dispatcher ~~~ k0_graph Dispatcher ~~~ k1_graph end %% Style for subgraphs style m7_graph fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style y8_graph fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style l9_graph fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style k0_graph fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style k1_graph fill:#15BCEF, stroke:#15BCEF, color:#FFFFFF style base fill:none, stroke:#15BCEF, stroke-width:3px, color:#0054AE, font-size:16pt ``` The advantage of this configuration is that the library works on any CPU. CMake build option: `-DMERGED_BLD:BOOL=on` #### Specific ISA Library The build system produces several separate libraries each optimized for its own instruction set. In this case, there is no need in [CPU dispatcher](#cpu-dispatching), so the dispatcher is not included, although [features dispatching](#cpu-feature-dispatching) within a single instruction set is in place. To specify for what instruction set targeted libraries must be produced, use the `PLATFORM_LIST` CMake variable. It contains semicolon-delimited list of CPU codes (for the complete list of codes see the table in [this](#target-optimization-codes-in-function-names) section). > **NOTE:** Platforms n8 (optimized for processors with Supplemental Streaming SIMD Extensions 3 (SSSE3)) and e9 (optimized for processors with Intel® Advanced Vector Extensions (Intel® AVX)) have been deprecated but are still supported in the specific ISA library build. Support for these platforms is targeted to be removed in a future release. For example, to create two libraries - one with SSE4.2 optimizations and another with Intel AVX-512 optimizations, specify `-DPLATFORM_LIST="y8;k0"`. ![CPU specific libraries picture][CPU-specific libraries] The advantage of this configuration is that libraries that contain function versions optimized for only one instruction set have much smaller footprint size than a big merged library. But the price of this advantage is that such libraries only work on a CPU that supports a corresponding instruction set. CMake build options: `-DMERGED_BLD:BOOL=off -DPLATFORM_LIST=""` #### Choosing specific ISA from the All CPUs Static Library When application is being statically linked with All CPUs Static Library, it receives functions implementations for all instruction sets with corresponding [dispatcher](#dispatcher) routines. This works well when CPU, where an application is going to work, is unknown. ![Link with Merged Library picture][link-with-merged-library] But when target CPU is defined, it is possible to take from the static library only required instruction set implementations and avoid [dispatcher](#dispatcher) inclusion. ![1CPU link with Merged Library picture][1cpu-link-with-merged-library] For this purpose, there are several CPU-specific headers (each targets a specific CPU optimization) generated during the merged library build. They are located in the `/.build//include/autogen` directory. To enable linking of CPU-specific versions of the library functions, include the appropriate header from the directory above before the primary library header `ippcp.h`. It is important to ensure that both processor and operating system supports full capabilities of the target processor. ### Functionality By default, Intel® Cryptography Primitives Library (both static and dynamic libraries) contain all functionality that exists in the product. But when footprint size matters, the library can contain only required functionality and have no unused code. #### Static Library with Custom functionality With the static linking having only required functionality in the library is not so actual as leaving only those parts of a library that are used by application, is automatically managed by linker. Considering Intel® Cryptography Primitives Library design that implies minimal internal dependencies, the application linked with the static Intel® Cryptography Primitives Library contains only relevant library functionality, and has minimal footprint size. #### Dynamic Library with Custom functionality To build your own dynamic library containing only the functionality that is necessary for your application, you can use the Intel® IPP Custom Library Tool - a Python tool that consumes pre-built merged (all CPUs) static library to produce a tiny dynamic library. The tool is located in the `tools/ipp_custom_library_tool_python` directory. Please refer to the [tool documentation](https://www.intel.com/content/www/us/en/docs/ipp/developer-guide-reference/current/ipp-custom-library-tool.html) for more information. cryptography-primitives-1.0.0/README.md000066400000000000000000000105411470420105600177130ustar00rootroot00000000000000# Intel® Cryptography Primitives Library [Build Instructions](./BUILD.md) | [Contributing Guide](#how-to-contribute) | [Documentation](#documentation) | [Get Help](#get-help) | [Intel IPP Product Page](https://www.intel.com/content/www/us/en/developer/tools/oneapi/ipp.html) Intel® Cryptography Primitives Library is a secure, fast and lightweight library of building blocks for cryptography, highly-optimized for various Intel® CPUs. ## Key Features The library provides a comprehensive set of routines commonly used for cryptographic operations, including: - Symmetric Cryptography Primitive Functions: - AES (ECB, CBC, CTR, OFB, CFB, XTS, GCM, CCM, SIV) - SM4 (ECB, CBC, CTR, OFB, CFB, CCM) - TDES (ECB, CBC, CTR, OFB, CFB) - RC4 - One-Way Hash Primitives: - SHA-1, SHA-224, SHA-256, SHA-384, SHA-512 - MD5 - SM3 - Data Authentication Primitive Functions: - HMAC - AES-CMAC - Public Key Cryptography Functions: - RSA, RSA-OAEP, RSA-PKCS_v15, RSA-PSS - DLP, DLP-DSA, DLP-DH - ECC (NIST curves), ECDSA, ECDH, EC-SM2 - Multi-buffer RSA, ECDSA, ECDH, x25519, SM2, SM3, SM4, etc - Finite Field Arithmetic Functions - Big Number Integer Arithmetic Functions - PRNG/TRNG and Prime Numbers Generation - Hash-based signature algorithms ## Reasons to Use Intel® Cryptography Primitives Library - Security (constant-time execution for secret processing functions) - Designed for the small footprint size - Optimized for different Intel CPUs and instruction set architectures (including hardware cryptography instructions support): - Intel® Streaming SIMD Extensions 2 (Intel® SSE2) - Intel® SSE3 - Intel® SSE4.2 - Intel® Advanced Vector Extensions (Intel® AVX) - Intel® Advanced Vector Extensions 2 (Intel® AVX2) - Intel® Advanced Vector Extensions 512 (Intel® AVX-512) - Configurable CPU dispatching for the best performance - Kernel mode compatibility - Thread-safe design ## FIPS 140 Compliance Intel® Cryptography Primitives Library supports building blocks (self-tests, services) for FIPS 140-3 compliance. See [FIPS](./README_FIPS.md) document for details. ## Installation [How to Get and Build the Intel® Cryptography Primitives Library](./BUILD.md) ## Documentation - [Introduction to Intel® Cryptography Primitives Library](./OVERVIEW.md) - [Introduction to Crypto Multi-buffer Library](./sources/ippcp/crypto_mb/Readme.md) - [Intel® Cryptography Primitives Library Build Instructions](./BUILD.md) - [Intel® Integrated Performance Primitives Release Notes](https://www.intel.com/content/www/us/en/developer/articles/release-notes/release-notes-for-oneapi-integrated-performance-primitives.html) - [Developer Guide and Reference for Intel® Cryptography Primitives Library](https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-guide-reference/current/overview.htmll) - [Intel® Integrated Performance Primitives Documentation](https://www.intel.com/content/www/us/en/developer/tools/oneapi/ipp-documentation.html) ## Branches Description - `develop` - snapshots of the library under active development. Contains code that may not be fully functional and that Intel may substantially modify in development of a production version. - `ipp_crypto_` - source code of the official production release ``. ## How to Contribute See [Contributing](./CONTRIBUTING.md) document for details about contribution process. ### License Intel® Cryptography Primitives Library is licensed under Apache License, Version 2.0. By contributing to the project, you agree to the license and copyright terms therein and release your contribution under these terms. ## Certification Intel® Integrated Performance Primitives Cryptography (Intel® IPP Cryptography) 2021.10 release is validated for FIPS-140-3 (Security Requirements for Cryptographic Modules) compliance and has the following CAVP (Cryptographic Algorithm Validation Program) certificates: - [Intel® Crypto Multi-buffer Library](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/details?product=17987) - [Intel® Cryptography Primitives Library optimized for Intel® AVX2 ISA](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/details?product=17988) - [Intel® Cryptography Primitives Library optimized for Intel® AVX512 ISA](https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/details?product=17989) cryptography-primitives-1.0.0/README_FIPS.md000066400000000000000000000524561470420105600205470ustar00rootroot00000000000000# Intel(R) Cryptography Primitives Library FIPS ## What is FIPS 140? FIPS (Federal Information Processing Standard) 140 series are U.S. government computer security standards that specify requirements for cryptography modules. The latest version is FIPS 140-3 (ISO standard 19790). ### Who needs FIPS 140? The National Institute of Standards and Technology (NIST) issues the 140 Publication Series to coordinate the requirements and standards for cryptographic modules which include HW, SW, and/or FW components for use by **departments and agencies of the U.S. government**. In U.S., government agencies desiring to deploy cryptographic modules should confirm that the module they are using has a valid FIPS 140 certificate. The Government of Canada also recommends the use of FIPS 140 validated cryptographic modules in unclassified applications of its departments. In addition, **in recent years FIPS 140 has become a more and more popular requirement in financial and health care sectors as well**. ## FIPS-Certified vs FIPS-Compliant FIPS 140-3 defines 4 security levels (from level 1 - the easiest to level 4 - the most stringent). In general, software may be certified at up to level 2. Intel® Cryptography Primitives Library provides building blocks of FIPS-mode API (such as self-tests, FIPS-approved functionality status query) which can help the end users to fulfill FIPS level 1 requirements. Please, refer to [Covered Algorithms](#covered-algorithms) section for the full list of FIPS-Approved API which are covered with the selftests. > NOTE: Intel® Cryptography Primitives Library is not **FIPS-Certified** on its own but **FIPS-Compliant**: that means Intel® Cryptography Primitives Library releases will have Cryptographic Algorithm Validation Program (CAVP) testing and certification done but don't have full Cryptographic Module Validation Program certificate as the context of the usage of Intel® Cryptography Primitives Library's high-performant primitives depends on a more high-level application. For the results of CAVP testing please refer to [Certification](./README.md#Certification) chapter. Intel® Cryptography Primitives Library may be built in FIPS-mode with IPPCP_FIPS_MODE=on configuration for ippcp and MBX_FIPS_MODE=on for crypto_MB (see details in [Build section](#build)). Application, which uses Intel® Cryptography Primitives Library may be **FIPS-Certified** by matching FIPS 140 requirement and obtaining NIST certificate or also be **FIPS-Compliant** for their own customers. Please, refer to [Level 1 Specific Requirements](#level-1-specific-requirements) for the detailed description of what is done on Intel® Cryptography Primitives Library-side and what should be done by a more high-level application. ### Level 1 Specific Requirements | # | Requirement | Note | |---|-------------|------| | 1 |Provide service to output module's name / identifier and version to User | Intel® Cryptography Primitives Library provides such functionality via ippcpGetLibVersion() API for IPPCP and mbx_getversion() API for crypto_MB | | 2 |For every service, output to the user whether it is a FIPS-approved service or not | Intel® Cryptography Primitives Library provides such functionality via [ippcp_is_fips_approved_func](#api-for-an-indicator-if-a-function-is-fips-approved) for ippcp and [mbx_is_fips_approved_func](#crypto-multi-buffer-library-api-for-an-indicator-if-a-function-is-fips-approved) for crypto_MB | | 3 |Zeroize unprotected keys using manual/procedural destruction method | **User's application effort required** | | 4 |Run integrity selftest at power on for SW component | **User's application effort required** | | 5 | Run known-answer or comparison or fault-detection selftest for individual crypto algorithms before first use | Intel® Cryptography Primitives Library provides [fips_selftest_ippcp API](#covered-algorithms) to run selftests. User's application should call them before the first use of algorithm (see [Example](#example-of-api-usage)) | | 6 | Run pairwise consistency selftest for newly generated RSA/ECC keypair | Intel® Cryptography Primitives Library provides [fips_selftest_ippcp API](#covered-algorithms) to run selftests | | 7 | Module to guarantee uniqueness of GCM key + IV | **User's application effort required** | | 8 | Module to guarantee XTS key1 != key2 | Intel® Cryptography Primitives Library-side check | | 9 | (non-production) Extract raw noise source output samples of RBG for quality analysis | DBRNG is currently out of the cryptography boundary | | 10| (non-production) Run crypto algorithm testing with NIST-generated vectors | Done offline by Intel® Cryptography Primitives Library for the [covered algorithms](#covered-algorithms) | For the implementation details about the steps in [Level 1 Specific Requirements](#level-1-specific-requirements) specified as **User's application effort required** please refer to the [Implementation Guidance for FIPS 140-3 and the Cryptographic Module Validation Program](https://csrc.nist.gov/csrc/media/Projects/cryptographic-module-validation-program/documents/fips%20140-3/FIPS%20140-3%20IG.pdf) by the National Institute of Standards and Technology. ## Cryptographic boundary ### Intel® Cryptography Primitives Library Structure Diagram ![Intel® Cryptography Primitives Library Architecture](./data/images/README_FIPS-pictures-0-ippcp_architecture.png) 1. Intel® Cryptography Primitives Library uses special structures (Spec and States) to store context information and provides service functions to work with context (e.g. Initialization). > Note: Application responsible for the life-cycle of context. All memory allocations and sanitizing happens on application side (including #3 in [Level 1 Specific Requirements](#level-1-specific-requirements)). 2. Cryptographic Algorithms API (both FIPS-Compliant and not FIPS Compliant). 3. FIPS Self-tests API and service to query if algorithm is FIPS-Compliant (API for #2, #5, #6 in [Level 1 Specific Requirements](#level-1-specific-requirements)). 4. Version information (API for #1 in [Level 1 Specific Requirements](#level-1-specific-requirements)), Dispatcher control. 5. Intel® Cryptography Primitives Library chooses the optimal code path depending on hardware features and application settings (via Dispatcher control API). 6. The algorithms may have multiple code branches for different hardware architecture and different compilation flags may be used to achieve better performance. Refer to [Covered Algorithms](#covered-algorithms) section to check which algorithms are within the cryptographic boundary. > Note: For #10 in [Level 1 Specific Requirements](#level-1-specific-requirements) Intel® Cryptography Primitives Library tests all code-paths and algorithms modes as the implementation may vary depending on the target hardware. ## Intel® Cryptography Primitives Library Usage in the FIPS-mode ### Build CMake flag -DIPPCP_FIPS_MODE:BOOL=on should be used to build ippcp library and -DMBX_FIPS_MODE:BOOL=on for crypto_MB in FIPS-mode. These modes enable extra API for self-tests and FIPS-support query (see [covered algorithms](#covered-algorithms) for the details). Selftests can be build in two modes - with internal memory allocation or without it. Configuration example for ippcp with Intel® oneAPI DPC++/C++ Compiler: `CC=icx CXX=icpx cmake CMakeLists.txt -B_build -DARCH=intel64 -DIPPCP_FIPS_MODE:BOOL=on [-DIPPCP_SELFTEST_USE_MALLOC:BOOL=on]` > Note: selftests with internal memory allocation uses malloc, which introduces a c runtime dependency. To avoid the dependency, use IPPCP_SELFTEST_USE_MALLOC:BOOL=off or do not specify it as this as the default. In this case, all self-tests will require external memory allocation. Configuration example for crypto_MB with GCC: `CC=gcc CXX=g++ cmake CMakeLists.txt -B_build -DARCH=intel64 -DMBX_FIPS_MODE:BOOL=on` ### Example of API Usage #### Intel® Cryptography Primitives Library Example ```cpp //------ FIPS-required part // 1. check that the function is FIPS-approved: if(!ippcp_is_fips_approved_func(AESEncryptCBC)) { return -1; // cannot use this function in FIPS mode. } // 2. Run the Selftest fips_test_status selftest_status = IPPCP_ALGO_SELFTEST_OK; // Query buffer size for the test and allocate it (it can be done on Intel® Cryptography Primitives Library side with IPPCP_SELFTEST_USE_MALLOC=on) int BuffSize = 0; selftest_status += fips_selftest_ippsAESEncryptDecrypt_get_size(&BuffSize); std::vector pBuff(BuffSize); // Run the test selftest_status += fips_selftest_ippsAESEncryptCBC(pBuff.data()); // Check selftest status if (IPPCP_ALGO_SELFTEST_OK != selftest_status) { return -1; // selftest is not successful -> cannot use this function in FIPS mode. } //------ FIPS-required part ends (only needed before the first use of algorithm) //------ Common Intel® Cryptography Primitives Library usage // ... IppStatus status = ippsAESEncryptCBC(plain, cipher, block_size, pAES, cipherV); // ... ``` #### Crypto Multi-buffer Library Example ```cpp //------ FIPS-required part // 1. check that the function is FIPS-approved: if(!mbx_is_fips_approved_func(nistp256_ecdh_mb8)) { return -1; // cannot use this function in FIPS mode. } // 2. Run the Selftest if (fips_selftest_mbx_nistp256_ecdh_mb8() != MBX_ALGO_SELFTEST_OK) { return -1; // selftest is not successful -> cannot use this function in FIPS mode. } //------ FIPS-required part ends (only needed before the first use of algorithm) //------ Common Crypto Multi-buffer Library usage // ... mbx_nistp256_ecdh_mb8(sharedAB, prvA, pubBx, pubBy, pubBz_curr, 0); mbx_nistp256_ecdh_mb8(sharedBA, prvB, pubAx, pubAy, pubAz_curr, 0); // ... ``` ### Covered Algorithms #### Intel® Cryptography Primitives Library Each API from the list is covered with the selftest fips_selftest_ipps available in Intel® Cryptography Primitives Library build in FIPS mode. ##### AES ```cpp fips_test_status fips_selftest_ippsAESEncryptDecrypt_get_size (int *pBuffSize); fips_test_status fips_selftest_ippsAESEncryptCBC (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptCBC (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESEncryptCBC_CS1 (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESEncryptCBC_CS2 (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESEncryptCBC_CS3 (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptCBC_CS1 (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptCBC_CS2 (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptCBC_CS3 (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESEncryptCFB (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptCFB (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESEncryptOFB (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptOFB (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESEncryptCTR (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAESDecryptCTR (Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsAESEncryptDecrypt_get_size`. ```cpp fips_test_status fips_selftest_ippsAESEncryptDecryptCCM_get_size (int *pBuffSize); fips_test_status fips_selftest_ippsAES_CCMEncrypt (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAES_CCMDecrypt (Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsAESEncryptDecryptCCM_get_size`. ```cpp fips_test_status fips_selftest_ippsAES_GCM_get_size (int *pBufferSize); fips_test_status fips_selftest_ippsAES_GCMEncrypt (Ipp8u *pBuffer); fips_test_status fips_selftest_ippsAES_GCMDecrypt (Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsAES_GCM_get_size`. ```cpp fips_test_status fips_selftest_ippsAES_CMAC_get_size (int *pBuffSize); fips_test_status fips_selftest_ippsAES_CMACUpdate (Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsAES_CMAC_get_size`. ##### RSA Encrypt/Decrypt ```cpp fips_test_status fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys (int *pKeysBufferSize); fips_test_status fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size (int *pBufferSize Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSAEncrypt_OAEP_rmf (Ipp8u *pBuffer Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSADecrypt_OAEP_rmf (Ipp8u *pBuffer Ipp8u *pKeysBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size` and `pKeysBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys`. ##### Hash ```cpp fips_test_status fips_selftest_ippsHash_rmf_get_size (int *pBuffSize); fips_test_status fips_selftest_ippsHashUpdate_rmf (IppHashAlgId hashAlgId, Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsHash_rmf_get_size`. ```cpp fips_test_status fips_selftest_ippsHashMessage_rmf (IppHashAlgId hashAlgId); ``` ##### HMAC ```cpp fips_test_status fips_selftest_ippsHMAC_rmf_get_size (int *pBuffSize); fips_test_status fips_selftest_ippsHMACUpdate_rmf (Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsHMAC_rmf_get_size`. ```cpp fips_test_status fips_selftest_ippsHMACMessage_rmf (void); ``` ##### RSA sign/verify ```cpp fips_test_status fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys (int *pKeysBufferSize); fips_test_status fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size (int *pBufferSize Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSASign_PKCS1v15_rmf (Ipp8u *pBuffer Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSAVerify_PKCS1v15_rmf (Ipp8u *pBuffer Ipp8u *pKeysBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size` and `pKeysBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys`. ```cpp fips_test_status fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys (int *pKeysBufferSize); fips_test_status fips_selftest_ippsRSASignVerify_PSS_rmf_get_size (int *pBufferSize Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSASign_PSS_rmf (Ipp8u *pBuffer Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSAVerify_PSS_rmf (Ipp8u *pBuffer Ipp8u *pKeysBuffer); fips_test_status fips_selftest_ippsRSA_GenerateKeys (Ipp8u *pBuffer Ipp8u *pKeysBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsRSASignVerify_PSS_rmf_get_size` and `pKeysBuffer` is the valid buffer for selftest of of size indicated by `fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys`. ##### ECDSA sign/verify ```cpp fips_test_status fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff (int *pGFpBuffSize); fips_test_status fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff (int *pGFpECBuffSize Ipp8u *pGFpBuff); fips_test_status fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff (int *pDataBuffSize Ipp8u *pGFpBuff Ipp8u *pGFpECBuff); fips_test_status fips_selftest_ippsGFpECSignDSA (Ipp8u *pGFpBuff Ipp8u *pGFpECBuff Ipp8u *pDataBuff); fips_test_status fips_selftest_ippsGFpECVerifyDSA (Ipp8u *pGFpBuff Ipp8u *pGFpECBuff Ipp8u *pDataBuff); fips_test_status fips_selftest_ippsGFpECPublicKey (Ipp8u *pGFpBuff Ipp8u *pGFpECBuff Ipp8u *pDataBuff); fips_test_status fips_selftest_ippsGFpECPrivateKey (Ipp8u *pGFpBuff Ipp8u *pGFpECBuff Ipp8u *pDataBuff); fips_test_status fips_selftest_ippsGFpECSharedSecretDH (Ipp8u *pGFpBuff Ipp8u *pGFpECBuff Ipp8u *pDataBuff); ``` , where `pGFpBuff` is the valid buffer for selftest of size indicated by `fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff`, `pGFpECBuff` is the valid buffer for selftest of size indicated by `fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff` and `pDataBuff` is the valid buffer for selftest of size indicated by `fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff`. ##### LMS verify ```cpp fips_test_status fips_selftest_ippsLMSVerify_get_size (int *pBuffSize); fips_test_status fips_selftest_ippsLMSVerify (Ipp8u *pBuffer); ``` , where `pBuffer` is the valid buffer for selftest of size indicated by `fips_selftest_ippsLMSVerify_get_size`. ##### API for an indicator if a function is FIPS-approved ```cpp func_fips_approved ippcp_is_fips_approved_func(enum FIPS_IPPCP_FUNC function); ``` Which APIs are **not** supported by this query: - auxiliary API regulating code dispatching process or general library settings (ippcpGetCpuFeatures, ippcpSetNumThreads, ippcpGetStatusString, ippcpGetLibVersion, etc.) - API to work with IPPCP-specific context (ippsInit, ippsSetKey, ippsGetSize, ippsReset, ippsDuplicate, ippsSet* etc.) - API implementing the base mathematic functions, which are not defined as a cryptographic algorithm (ippsAdd_BN, ippsMul_BN, ippsGFpNeg, etc) - deprecated API For the exact list of the supported symbols please, refer to `FIPS_IPPCP_FUNC` enumerator in [include/ippcp/fips_cert.h](./include/ippcp/fips_cert.h). #### Crypto Multi-buffer Library ##### Elliptic Curves ```cpp fips_test_status fips_selftest_mbx_nistp256_ecpublic_key_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecpublic_key_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecpublic_key_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdh_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdh_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdh_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdsa_verify_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdsa_verify_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdsa_verify_mb8(void); fips_test_status fips_selftest_mbx_ed25519_public_key_mb8(void); fips_test_status fips_selftest_mbx_ed25519_sign_mb8(void); fips_test_status fips_selftest_mbx_ed25519_verify_mb8(void); fips_test_status fips_selftest_mbx_x25519_public_key_mb8(void); fips_test_status fips_selftest_mbx_x25519_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecpublic_key_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecpublic_key_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecpublic_key_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdh_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdh_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdh_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp256_ecdsa_verify_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp384_ecdsa_verify_ssl_mb8(void); fips_test_status fips_selftest_mbx_nistp521_ecdsa_verify_ssl_mb8(void); ``` ##### RSA ```cpp fips_test_status fips_selftest_mbx_rsa1k_public_mb8(void); fips_test_status fips_selftest_mbx_rsa2k_public_mb8(void); fips_test_status fips_selftest_mbx_rsa3k_public_mb8(void); fips_test_status fips_selftest_mbx_rsa4k_public_mb8(void); fips_test_status fips_selftest_mbx_rsa1k_private_mb8(void); fips_test_status fips_selftest_mbx_rsa2k_private_mb8(void); fips_test_status fips_selftest_mbx_rsa3k_private_mb8(void); fips_test_status fips_selftest_mbx_rsa4k_private_mb8(void); fips_test_status fips_selftest_mbx_rsa1k_private_crt_mb8(void); fips_test_status fips_selftest_mbx_rsa2k_private_crt_mb8(void); fips_test_status fips_selftest_mbx_rsa3k_private_crt_mb8(void); fips_test_status fips_selftest_mbx_rsa4k_private_crt_mb8(void); fips_test_status fips_selftest_mbx_rsa1k_public_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa2k_public_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa3k_public_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa4k_public_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa1k_private_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa2k_private_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa3k_private_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa4k_private_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa1k_private_crt_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa2k_private_crt_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa3k_private_crt_ssl_mb8(void); fips_test_status fips_selftest_mbx_rsa4k_private_crt_ssl_mb8(void); ``` ##### Crypto Multi-buffer Library API for an indicator if a function is FIPS-approved ```cpp func_fips_approved mbx_is_fips_approved_func(enum FIPS_CRYPTO_MB_FUNC function); ``` For the exact list of the supported symbols please, refer to `FIPS_CRYPTO_MB_FUNC` enumerator in [include/crypto_mb/fips_cert.h](./sources/ippcp/crypto_mb/include/crypto_mb/fips_cert.h). cryptography-primitives-1.0.0/SECURITY.md000066400000000000000000000010671470420105600202300ustar00rootroot00000000000000# Security Policy ## Reporting a Security Vulnerability Visit [https://intel.com/security](https://intel.com/security) for information on how to report security vulnerabilities. **Do not report any security vulnerability as a regular issue in this repository.** Include the following information in your report: - Description of the security problem - Steps to reproduce - Expected behavior - Environment where the problem is reproduced: OS, compiler (including version), versions of ippcp / crypto_mb libraries - Any additional information that may be relevant cryptography-primitives-1.0.0/SUPPORT.md000066400000000000000000000003731470420105600201340ustar00rootroot00000000000000# Support Submit your support needs to the [GitHub issues page](https://github.com/intel/ipp-crypto/issues). Refer to GitHub's [Creating an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/creating-an-issue) for instructions. cryptography-primitives-1.0.0/THIRD-PARTY-PROGRAMS.txt000066400000000000000000000045101470420105600221730ustar00rootroot00000000000000Intel(R) Cryptography Primitives Library Third Party Programs File This file contains the list of third party software (“third party programs”) contained in the Intel software and their required notices and/or license terms. This third party software, even if included with the distribution of the Intel software, may be governed by separate license terms, including without limitation, third party license terms, other Intel software license terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the “third-party-programs.txt” or other similarly-named text file. Third party programs and their corresponding required notices and/or license terms are listed below. ------------------------------------------------------------- 1. Intel(R) Multi-Buffer Crypto for IPSec Library Copyright (c) 2012-2021, Intel Corporation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Intel Corporation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.cryptography-primitives-1.0.0/data/000077500000000000000000000000001470420105600173445ustar00rootroot00000000000000cryptography-primitives-1.0.0/data/images/000077500000000000000000000000001470420105600206115ustar00rootroot00000000000000cryptography-primitives-1.0.0/data/images/README-pictures-0-dispatcher.png000066400000000000000000000242431470420105600263760ustar00rootroot00000000000000PNG  IHDRKsRGBgAMA a pHYsod(8IDATx^ouO}SKyq Bh$C hM+(̖]%) U8J+22MƕMɒs%ݳ a̝;.:4>* =+o~Bt'/n!ҷ|us/TNTA+>A7P@UZ z Tj*-P@UZ z TjVŏ>|KcWh߼˟_m PK*?+o~79?u9 ͻߵ+ P7~M*bmg"+2iZN _ɓG7.ˇ*UA=[2 P)'PTUPQ rPߡ*h:_ߧj[?x_Z~n Fw$%Э_sjWMw\[Lt8ꁎ`h$D6/ŧ,lUZPEGlQI:ownp LTF6E6!1KL&r#ϧ r/`$~ze VNN;`ƀ*@-5*T1Tйsu&PepL>ͨ.2]s)/KB<\:DHxX4 АдMr8fON p:T ZE9ZLsgw><TT1+8\YX402gy(WͧW߼{Gv]3d#)L5qqxr2MCNB5x^ztAhCͥNlAlלT\ H*S(FECވ_Uĕ*ڢ97XglnٕiTKoQra$Em]}_r=E{#ʍo 7Tb ٜE?YPE}xUHʍ)k]se5nk{\Ot8ZplZ`hA^X;ۗرYܩlUҥz'#'Om1TqUe@H&(PD2@@P"Dʀ*L&7PPTd2*2 E$ TU("Z l@B ǟ"GjX*@-P@U[ P T@o*@-P@U(⵷C'&Tj*L&7im Bd"zUe@H&(PD2@@P"Dʀ*L&7PPTd2*2 E$('Girg{><TTUL?{v%&l78<9&g$:n{QQԏ\6X'ϸH*S(Fވ_-ʘ U,,]][;uup9Cze]֤Ag\dօ꠫tg ULwM8uxoxCYȋoIlSE@@3{뫶lj`ceW& s/EɅLfS7FU SMi:q7FSMB.&7(18xq2X> ڠ+GUh0*2V_|6Ů55W[WWWI*>|cW"k[j)Z8UY+Mh6U^ SØeh:A+۸ --UQpmZT1Z%eнڮÕRLfYrZkT!J}׹wR*QET[o}h3{h<8UeDCx;8knj*۹0ɬ AWP=*aqRŵ(0Dߒ&HB*2F dUAߢxWqo}tը*C.Y]YߌT?w{9L V'F2yf*MͪU)f_S7h[qGӭPK\gKeOqbqñ/##maslN*|@{ck Qc7O^E#)W7NM*KvbUxharK ҫ"F2b-j)^LW NJg~(ʱ,7| `a=v'6 L`i63m3\($㦫@@#REml'>oǨ0zUdcUl-͒\r. _EQДMPEt 5yYUYJ(p۸W C5F>X> ڠ+GUh0*2YRAx`W jdmp[$=L B. ~)bBDSݵpK9!k m֦ +`GT0fW,vl*d\TEQj9PPhTa.$* *Ul߈B,]OL'V65h&֨B^/s?Fk uԢhT*[ߌk}rib/#lTfLaQ9v*o+(ZW*Ua^m6gV6ԅ?,kʨ,Ħ9{&+Ʀ:DQؖ*hHH!6},t4΄(Q`f/Րtk{[6y^a 6Չ@@Q(Lݱ=VP>Lf[uZpdzSǏ>|W#di{cPEN2D^[ė8G!j5ux鋯Ef#??z_rUzPEN2L*~q_2+*rD@ƘU|Ҽ"'LDo dVU$g+*rD@ƘUE ;#uPEN2@3@vXTL&7P2L*OCu}XnRTL&7P2L*jc{Hx]yl*PHrݙVU$'(U(~bzhpvv-5Aͯ k%)/?{WէŧPԌ[o _*I"e\ANQ-џQAPKb*"=S3nU|iKѡ !fA **7T>nfthhQ¥[jw 7(6U/`Z8Awjc?KϗQG w]k*7cR4RcvG.aRup%.ub;g \t7Asw_hZ[nwoǫ^ȫB 4U!_wvj^/%` bADRsyX7P?b3'>! P#Uv;xkn 4pd^e'ƭ_)%?\ޤgD0_<([͚С??dUdMWNM9E<+q,4*d\TE갨lP, ~u*l<9)* nRTL&7P2L*[{il@9d"zU c̴"H&Q.npU c̴|V zv%&W">|"b)wzC 5~"6kyl?ԡ9g d޻ aBϾRTqo}unap,,7`k}:7[A.d2")]}*"=mt@Ƙ94cVHN ~bgsn9\^ \d ? i ŋjbk3;a[W;&;X;ISœ#Q~k,MUK;^͝Dza^ݜլ]2^0LCu*\׻I2GB`1'B/JEQ?•gԉm4&CFwVȖ}9|t MW[3uQ=7]- %+2[ lKpA.3pq2Io/\_bADGhTDRy4L0 doMna 'K[ ѨnY!y+k)ved .͹3(ϐO]ި x>|L/%†4ݥZnKD-mtա +ќE(Ihø@7q/qT!*:V[UeBjX 鯊>1taߊ/l·wI' Ǥ߫`L%$9š]d̃z(B7iδW[UtL湒 |L@PP*L&7PPTd2*2.MiRV@9d"zUe\P'Fs)q5@9d"zUe\H$S. d2*2.§Ȼ>b{I&(B(T1.Dʸ*@cᵷCaUZ.XT*@-P@U[ P T@o*@-P@Z8GOGگD*@-P"^|.2~Q' Tj*L&7im Bd"zUe@H&(PD2@@P"Dʀ*L&7PPTd2*2 E$ٖk)p!w@@PŴ]I&-AoOH7Yb:ip*z`/*TښK=H*S(F!HFj{ ^Y<\YX]oZu.Nխ她yϽ oH&-Vb*\Y=]S/@]0#h|c[TAh@@}R `s~yi~Ǭ63rs?m:f*80l jbksw!n^ h)B.&7(18xgH[zxS3ɴUmL*PRݼx<0=l НDza^ݜլhaB'U#̶RIeP4Rc r,K J*{|`o=޳mjDTQ<#[ߛ=3st'7] T1 h&e|aUl-̽g꒿l5"IcJ 'WmvE"T:W,rq:KW~xM?L'a䃌U m82UDzDN-PPԪ]y ? $UDLD:\R2m'.qZnKD-m֦ + j*r2W[\ ێm\T얖(Eg]*2 ~4O|xtpTez𪐒`lK Jg#T!J}m_)Ķ"j ]E?W,/2FevT/cE =}bH v|=}w1 g{Vc|Y`l-r9=Ao_hl*Cem) 6hcѧ,bK7HQ%xFa{]S! e*:@g(/w3A2) QK?xHʀ*L#-8G!v,(PD2@@P"Dʀ*L&7PPTd2*2 E$ TU("LDo Bd"zUe@Zx]`D@UZ z Tj*-P@UZ z Tj*3B دD*@-P"D?U("LDo Bd"zUe@H&(PD2@@P"Dʀ*L&7PPTd2*2icLf)'Gi#ҝOڝCawZR9PPT1mYw~t_uA2FJ{;K"Ónx֘NQ =^6q Fԏ\6X'cu[)CcvQmoįUeGW~J, WsM_5 .ql'[a0fd@gKoQra$YJ^U:S=Oz ULwM8atxoxCYȋoIlSE@@Q `s~yi~Ǭ63r^m Ulne\_7soȅLf)BSEEnampGtMw4pPT6ōAǍX7eGnG؜ʮYZu(cjUw?뷾z7lx 4wMM LЃ`w5tRq2p4%˫)mBU i.3?(TJ2":{g|զxF7?+A{4g?N">nZT1x;.xHm-̽}U|s6(bky['^E2Hs"T:W,rq*,E\qP?bj>]"Dz2UDzDN'T1)_Ϡ>C>rwF!fyĻgLf)M%5T(G DZiԦ + Ge Wg1ȶceU!* 7@Qj9PPF/TO*`89vO UxӪXx`U$`,֩PmMsT.g˼}FPBlK*JR)/&Ahe [2 (o~*13puky]-ﮨUrջEfbН+F]PBBy?`y!s=ӝɄ̜W:<}~ӿ3C2o ᨁK5`$6r G ]XY}rdGc! U4T-CE q*JPQB4T8 %i(!NCE q*JPQB2ڶmWT4X8wȯؕ!z\fWdkB˩fke,1zmHRM$h[ZcWؒu4RԇnM$qzmR93'[[z=B֥sdB-Dόd< ; "U&E=]b&y3!8D2&`\?yBыn-jCLkEAEIPQ~]鳡Kg!Pf K&=&blVT4T+}Jeb)`͖ 7 E .Hjp6Ʈ4x[ :a{ˡe +!Rt4(RܲE(8~NkVT4(vCf¼s̼cNfx?{/P4"LixZQPQOxS"2%qxsΠn+jVT8 %i(!NCE q*JPQB4T8 %i(!NCEI9t? hl"ۃpEsk?gWFH%Ư^jD{reT4NU$o|ѧ}D^HrPQi܇JQ,U$SFb=gGؠrg,Sqa`Zof$3ġ63ß\UOen!wb$0hc~y ?z krkX0v{3T4`󙦫-"U@cx61T4ç]A L[oZcͱE L_{ƲQ3{z3zp=y_^N :JEDj<~ -Xp>xrsrOc(ꢜ;T5^Ř*aWlP,0sϙ [ >pFGyxXn< ..YЭaT4&R~rqCм5Z[8Ԇ@iEQ0кDcB܎XW:'hئS58 93[GnkShPPWXQ[:jmqb:𙦫V#b}yF+:6k3 L)4J:ei UE*?O+1ܬpt3\XxZ/BuQE=.)8P66ռjVQ_~1i䄨|rvmHQ<"'$O_yŕx\ywO4]8:_#ygc{s?q$R{ӫX޹NvYSG,B* w*^A( x01BW I+qAAԋx1Ґuq<@Y%u 3sT!\Q<*e0A +\Qh=Z;7yhad)nr/=ߊ)H+ /GT!$xabNꓯrtgc;>}=k['-_6][DIIg?|E/Ge[GSn|Ez9Z?Iы~˺~ì.QD k`JRtv)a,$:nݶ2R&HwH?[)\Ql]h!ÙVFԂu!RNg&gF})ڐF۽ʯJ-C  luq":k^TJt=)ڒ]/7 M5)'NSEzhaaﰫcY_JsVx9jk ?/zؔMa9:h\&SxR It=Ntɰ@ZmtE}9 \C^65ARo75!lsf"S÷Q?1{c)Z.R+Ya9&Dס4)T'z86?tMEcrJE]U>A>ԓ8@J)FzYrٶ8EcrZn$(rNL>I`U{oep9 \k/6W4&%+Ft+q3#PQiԑיrҨ*ZPQiPQaPQiPQaPQiPQaPQiPQaPQiPQaPQG|hoCڬIZ\j@ZV So`?Ux^Vz'f%c]*:ǬMȕ8?--E5Oo}?w2y~^6Vѧ23fP _wLiLQt7wG5ya`zlvQA㙦ꜙlDe<`3 shx.6o] 99o5{x5@i%W5:sI3#wEJ *Z@oMWy 6J *l/^6 2"*QQiAEW;)>8#TTZPѤBM,+{唊J *xT)(z3z[>I hġ¯F-҂&4``!TTZPFnu-3N5->r kqS_l{wCm'}2zxJ`~GR^~h%c(J~U%1oڦ⧢{ [WYG9zqp7LlnD#\QY) V~$4_',lN$_⅔%4)ZEX (ب&ݩM>B^ F%4qiעK((RH8}2.ɊF 'T`Խg=!YQ,_Ȧ€OipE%44>J((P%TfZ6kT+ )K/I *zmlor6|~f2AZ(INt[kŖ*bIbRnD{TÙVF|κHJUtv!TC?WBѡB:R** ** ** ** ** ** ** ** ** ** ** ** ** ** *Z C9ܴ!~WDzYnHs]k@}+L-/m-jym]/{YO[f4*L`ElC6/1j "˸= YV'93m_KhR2U"xIZN5w(,"tqKS&*L*/#IfSx쉤6ě0i*ITԻ,"4}2;6}ITԙO`xxg~:n 4T8 %iJUl󑯻#ա7j]T +)IS]#K5wLeWceL'Z+fsƦ$Euv!g[TC?gZ)<1V p=79keTu0404040404040RtWDPpnm[6+* $*A ,hCc.[3+ޜ3oH?`6P+EՐ vdžwJptwmT$&yg.XV?mCߦ#<uyՏ5-OIΏ%PGӽ탪2HQܤJ`φ`\BZao&I~ V6MrXr=3tQ n9f3  ݭM/fr}ᑶ{C2?6pGB-~ q>OIW紐_#6Z;vPEq>E_ag4C{|o > |Dևʄj՛Vo{#m˷A>=fEhpEc{)a!JamTFo!8h@DBO|_Xߪ-*ZkBUԭ\l TTut40404040h ȡnkeRQ=Ե1 K5:Qׯ^zh北?NXAJ(:3.^mGB:aO ۯh71dmJ 0H|ՙ. <|E%)kSRw4h_TFp쪵$'8hm|E<ښۇ$qPQi<7=/S]V84(xtITT/8M.TTF5Ԃ -֞$PQiE﹣ QKC!e4oz?xY1UZ')O:TT/Drj}; )4P!UF 鞧?M}-7}]xJiN;1 :G=KunPӅNvqb&C][NK*D*jba徵G1??Nu@qV&pN(:$?4EQTFK Z1Q`a{HY&^xWcBeV(ae>/.6`OO҂*P-6u"*W'cJ**- []C;'cA?z >/6**-ץQWg_\PQiAE]*jG$&f0SeJ^**-h+*lDEMVrbRcRoT4z}6XN(g^HBWQ(z ȭEҊuO]x~YOs3^ҐKHG&),?S<È7]$wO<_ o ʦ(ϯ Up掰5Z \UTucδ4JS SVi <#\xJGb&q]=CwNcaG/^V+c t?nH2 Pt6n^N?W)*~Pg6rmLQےb9 QJUEUOG?fU8z!A55 2lmּTɋ͠㦢 4٧*/M[WT:Nt͏ sס.)avH ӯV},T ȝC1MKSWזEE[ozǻ;%|^? gkFQMc C, ۟˶wqQQ˙;4٧*/MG\4MSeE'P )M1A;y 4 >Ue=Ί6/\EptE=n gݩv){kh˭OST_Q `Cѷ"i**@YyPQW(ҡҠ Ҡ Ҡ Ҡ Ҡ Ҡ¨? ʜ39B:NWD6Q&_uKj7je*J T8 %i(!NCE q*JPQB4Tъ/ݾY{BjV}kBH TwTw!E [9D<IENDB`cryptography-primitives-1.0.0/data/images/README-pictures-1a-build-targets.png000066400000000000000000004063701470420105600271650ustar00rootroot00000000000000PNG  IHDRsRGBgAMA a pHYsodIDATx^|׵&++Ro_$MA'v̲d-FKYZ1k,3̬Zv؎9ܹss4jZOC}L?cԦo9` ϭI ) nMm~:SB;ySN 6MmϜ4LT|EG5N?uFs܃ ^gSيU mC%W3]J`#Mmπľ\׭W]pzŪ}cf%0,٥lE_׮ڴj7o}v,_EXv̹k\+1eV9tئ;զʀ2Fì)@Rx@AȀaȶ]?x's]?sbyvc aE0B照h4 )5Z⒘#]f!v|k\ǀöxK4FPYk0]QR`))vpZ߯,ZZ :U,,+hPqk'دۺ|譛W4ÝJ#Єq߸tc5l٦?=Vϼjߡ\3JmV:O_O\IīU ъnNCbW<XůPޠQ?+lϦ͈dCkQ}EAfw(GVKǮٵ#ceo-9*?!7@Yֈ ht呃 `V5cd}*iFӐמ~ٲiGKYL?1iLf rIø;V 1~w$y 7q_?)#!Ol;~n=3ɯh}vЦef?v#q[aݛ}6j#^Ϗ2߁,;~cW:hKXxB:Njx[?uVm:-_uSܺ~be{}t`йZTf_D#G*Nh//!mm: BJB9MqpA9@Mq?4?[H^GAC!&:t~9戦=&t2s/>4+մsזpH#xK!&q4L_ܺ?LnixGǡX5B?{~^/h |Lݧ݅?|ү;@~ï_ i, Ұ ,BKÊ`uXаziS4aC`Ӱ*i?y e f;mcG445NK03m3l_ì^(ME΅jسyj_kf(= 1c.i@wOljΝA>a߯!aH2gE|x+O6hjPo.z?d3̎b5LDԧ/3AEeW~GY^j٪ṳ>xvt#dK`odBAKɂqX#CRR1]Kt7Het4o`OzvjAMɔkf X/6kOkVMQM#eTҀXA0 M&W$w|@Y̳vl8?zFC¦=p'sk<`5&S)Inp#f,>nBO4NPƁ=?5ŻLI1#(Xԫ̞ǥ7ˋ7QT^;k/B^Dr/, 4P[n? 姕lQ_Kx,C1] f ~o1i< ȁ4̅2PҘ׃y@w#;$ 8~ǸU{$z[zJTz@hZip4ƭJM+4k$z4ƭpE< D[y=h&-x:JlҪz4?ZHz m Xq+@8t*4 G< 4z׃!S&$`4(P9++E4 &aih$@p4l iXp4? JiԱIH"g3uơs"1[˶d=AkaL3R\ACl2}â'a'?:zMpSj*7m}3df׍^OY  iY1;7B<'2egPA˶Z^N=_JkMxi^Z👈II2Gs/1~7 ɦEÈ0Kiqq |/x2/2LCpwd0x9^tj0XÕspk/naܰ>F ^}l,  gFʬF= HÉWY=m4Ux@*i%IZ?yC4 !iୠidEҨ{?H#4CTҨGV:$z:X6d4$`W,;l ܕ~(z.E ʓ̢w5V-ndNL3E1TJ2`.yN6Wg lvƝ_ݧLP/'Mؙ@lղ20kԍѰͪ?S>Dž>ωIhZ6r3!^/nSXz } LZh"' g f@<&%f ]# K)+?Phx l'bɸVȇtʸOʸO0yH+}qSqSqSqSdn4x@>*>^1U1U1U1U1U1!ntz}}aAW9ihYq_d1xxծg6}sFlC'r( UjaZDZ)pb̚xٳA|ǴU#xӁ]"r8k#w2b9Fx^IߍjE.HkF~oث;+Mh!" [&t9h:!g"?b/@C7Y6T?#(Գpxf5F$ hě$&৷9\J[tЈJgbyBTӄȧY_LG $z&>K:tn}P`׭2 HzXJix4<4xL?4kg!iԡX5 {iXp4i$aO?Zds-+_Vh- ߱ifOSwt|5&ǧ("_6hyٙ`L0t6:̸ʑ͚^;"@09ï7C =1k~u{; %i !AVxП>FÖyC|@a.!$OrJpo9>Z72ko[6%A۴jX~n])>8xgX&X?IhP78%յ$_Ґxi,5FjMZ{g{FoFL]+3qWljaK^ }*5BPHgεmN+V?}ܯ(K"}vr_ ԣl&h`\qom,qٷ#kK}OYE [\0R@i?sm_J"< B5c%YU|v b-FLl\r_:`%ׯgbV 14B(;StTh:Y#ԳXYulaWg>ϋ!;ۚP۷ؾƓ>_Ah]u6mܞ-Lj؍ gFMզ6afXBc]FcݺԦ6}ͣO]}8\H*ԦoPXT`1i,oQbςBfrԦoqY g`7{<Sz|cǺLZ%RX,Q /$#\t.WdrUccfή .c }l>' ~ Fco`ZaغE\)j WϓF?-^aʬoKjXV`#;L$B*n*as ZFXʵs4efB{#he >ԠgN  AzY`U *ċ4ϗ tvvuvv@zzf<*}Hc.PRg-{uv< zCtJ]^Zl}XuΝNPz@2R9NX3JaϏ4JG=GKFtFOט&OhQ{y J~-? [@H@ XGG7trDWeggϞ;s̉'n޼YRR&*劘kG 3QQǎO?c[[;8'z@je}j ᛛquuAXvYˠ?@g|PC}}S " 8>>>عs6`/]Pi&lwUADh#i<9J"QH-a}{(}0 00hAA'-걱IҰ"6Ka3gN_t+ oǎ&"l"`@Zt.qzfzjLTVòjq4{{mڴi= lg>ksC@)pƫ~K>;V j%@z} /..Nv'hYyU({9~IYVYt3u/>k1ufI Ç )1GZ`WC' |$)d4ZZ0kmm'gӳnZu}SRuux< 2ԩW._9ɓ.\Jm>"\Hx=.]lll3܊رPLMy+zww pXy@^q<;0888Ɯ a|^{IATU՞;߯g wuP&)\16]L x:s xCO>@;wtƈ\w^Z#ظA3Tw5[0 `:Jy0zΜ9 εkׯ_wXVV}{ܹKv_[wuLOEFF۟|`bb61A99y;vl ɐy};B@焹j|Z>px[911 SuuvXJHٵ:?022 RpPC:`˖ŌJ'4$Ja/pܹs9 &\Ww@P`__go_;X_'D+q@< a2lࡠ-s7HECрS`dd85E^VAڑh3==ӛZY\`gf(]]},. ^Off6c);;o˖Ν?{ٳgQK E{={J>}͟:;%%?yorw#-T5șj|Z>J  H WG$܀ h##@Hr{{uttauP"c!566lmmPFآ8}62)((r*VM34!Wz?ШԬ޽}}C`McCKwW_lLWHIs">pHP 77o:**}EfJTo'%hCp xG67_HA<,WFC8bRSvYYQf ^چlono(2$Abjj 0mY%ȃsxAA 2?qٮ.LsXX ړ>7`,>EfffFFF9UtGt_tyva ݿf```ii (u8:^] ?" =@@b͛9vyhY3o3ೳ޻lA0IR}==}813k:u4@?$$ 2#Hݍ=}0El߾ pM}8V|ɮ] U8le`o[oz{RC?6:jY")lPb ԯY>p C7BY#lZ+zZIqtQp|f@%SQQ .e'd0`4P f@guONV@SRR ~J:l>-! I834*}vvrgB m6Ajjނv۷/6-:e#c䢭G >߀2 dHj@ hPqk fllRZpex"OqQ)FH{p1J>MHjs,`` Z D_5xl׃U{><}Ξ=?22(޺]h~ *}i o ~,0KÄx]4>E7oj REgˋleeΝãr' DDDtr}>Qy-z=z6m(̅Xڃ,*}`e؂ [\Mo@΂& fXNCC3p=HV~qL HFp}4bD#!s=o1kLT5 } 0`<7Fe$8hjkkZ{, '욀a'щѧ-M ͍M]~XkL,߻>Uu`]FFDCd2,!_Iuuen"z>,d̖5o}`b GMo@Wa,Tc2(0/Fj|>iy>83G.^>}?Ԉm@ UUY{/ 5vl)mD.kuentvfvv͛7ZG<0@OqQ7wb ؃ނ+D^ECQN8\ZO=澎׳hr(XILLp80رcgpeA:HY_|~o2< !A _ ],\PW^^Y5 Hˊ-3>.\rSc+o?s/1sufr)}qUppVFFNu5>11xe| ia?="`+3c};mښۺ kUC0&&|?t0y*z>hdTfQQ%lΥKkjjjW6<%NMyyձc~ .`>Tpp(]u#J+W^t 鳖=yZzb3]0R 5 gKmРD0XVeöhe:۸3V!fQjej<ykٲEI}zF7N0Xjqϵ-n2[g3>Q~dz}l|G鳖1I M1@-3 [I0UأZ3l֣,eT~󓕚>_=e2},KŚ9qn >=* j>,>jSۓ5 NKyLۛ 勹j<)!D{2HmjvDlB>aDUy&<+Id$LJ5,[` ?u!$2Ԧ6}mhu.>cb 6Zj IMRHMz.%Ht:}| ๓>j%%%rDkчO%Oγ_633T&M䉑A"]V)ШX̜럤p9"i|B%D̹y~bb:qlH!eS78NJT ruwxF'N ")Q@(hb+  013Vo]>EJxL,+FWŸ ghY<!2v@t¢C N*ˈS,ΡN  `1ӖA$cGcTt9C"džGfs95<ߧQe4CfUqg:Cȸ/"%z|ZFƩM$ ɱxEH<#sH%)>9Cwzf>,4*OOOMMM"qɽBLܓ_҉k. 7z%ܙ{)#v1inI")He\rsCDC,ZCGVT3 hٴ8Sl.Ar|On`l3u)]^tƂd\*.B+^(s*/4:~eDE }ā ܛjހ1\~Tdâ4!dddA; bvvvʒ.{{7o޸qаT$Q.5 G8GL2Sx7 '$7M:4P}ϸQ=8TU} n^bqKuV&:z$T BcL(U}=j'R>SŞ(}3| iQP[`NOI}0W<P=2> I)BwdЧ\e.^a."Ǜ2B2;)RO`HJKg|Hzy|N}"NS{z;%uS_Cڗ߻>> lYw[dtR3'l/׬Ag͜,lyĊp|EVLFJ9F]ÙoH"AH( {%=uEpǻ%şIb)sñaZ'ٿ(}D^ޢQ2q˦j=cjj 177OMMMOO σVLokc]EKwOO[N\`PhyGLNuOooOE¥FFu:D3 9 xm\PHbQMwwwa#RL&Qxob1F"TSU0ߘy\W_Htq-d6gF4M3e<Zdy8+8cyT{DWSLGYPSz7Ɠ*m3;M}'V+%2L!xbz'hv~I՝=ݝ~xPoM+ !na]mIwVIdJX~'ZEr.+'#q޸ma dlZϬ덌=gmZH\2= X MD*}UIY㸜3MJqQxϼz{{=IMG\%ZqGoJZQ'B,OTgG!#uj=ﯭ}w֒>*D8R#~U֋(%}Zj}SR҇1\Mmzc>Sߴeɬ޾qMmz|VB}Q~WmjS۷g,Ԧo=[\⩥Z/ۅQKKjZOG}\ߊ&rIRYGhqoooYYYT^^N$rIRYG(`mm7(..^Q!H_9 0W":6BCK"LࣉǬGXX[,Uɒr%u `qEI%Oq ˄/JW$2%BpfAIA~윯XR!~\q"KR-=qvv~7{}wY^@gWtOQH_&@8;P5LQ8,<>m&qXjĞ!2{*:FdЅV΂,saB>6Rׂ:ғ3{%ߔSK`@vBäuVLs9,Xk~vڽID$h#yYhffaW@ L**HLLMLϭemzTYFEBHO8ze&1}ihLddr9%DƺVM`L깤ݱc,,,L֖;V(g]/:u_wAI[T WӒGTeR24'@/8b3~Ճ$6? p[Bž*o蟦߹Tb[<+b`'ұz{/:NzR(tb)sEly,C1K}ݻoo?*A={>Љ+B#aa={~W tY"Pa24OnL1Ӿe3›;v|ѐN ?ߚu';ri6ThR?\`o͑.>хõ 𖜐D29X_.= 'sIKrr2Z^& 1&1K*e$6=qWD4J A *AH"onpsO ;p_Kc QߋQR"HHxb $NzJXBS4k}P^ )|o- J4$h,Opr7S\6ineyyZ8g73B?}TpǗ;om\ϠO~|5 5}.ustKEb!sC)Hc &c qdiLpG,LKDw 0 [΅*-Q$BOō崶NMI-V]2q9Zm\2.(>'FD2#1~7Wf* 6?;tCc:A! F'YҾ I !Nt1+^<=DFFdRE2_e2XtZ, AB¥gu#["d*rE&T!_ ˛QOY!$ gl- ͧn2C52RZ $7 M6|IH@ dq.55)6)ONmHl-yIqpd1> l3'o't٦ Zl7C EN8h>$.wD e<3Ï.Er% Pٻvsx@r"w; %R 63^XU_QT]>6&:&v v~,)n[G(m7\ЍalO 0=}^ؕe[Z4m3RS&q Sw?<2 OJaCm%%B03P ɩ&aQdo[kC  k*5*22*k#KrTWE dE7ٵoUیY6o"5&22"ccbmo2 2!L&+,-$t: Ci+L@o osFIB}w m@&&A;UA`[|sS\-qDk4{=?tG9BIG_9G?} ĒEpolF4a;\:yO@3udg*ɴ8^<1I29jәFlϡ\>aa#< ,T E8@abc1LdM:ӴxMדGD(u8I's AF ۄ-zιc^ߣK\ }KV6m߶cҞfi}a\}ũ/?;vЗ6'HeBfWV >G>DHl>?⥻xh;YuR:Կw]g';U6wG5|6>v# A*ukPJ ѿq̹s.蹥4dr=v޿apHt7Ov+8=Gu7'WC j(ŀY}qK]{]Q+ʐȅ37^3941&ץ@A={^v!μM>Cv.9];|\rOOྒྷ6 k vb(dYה~3x:'uUo1C1aV6"s'M^pAε怠3EVlED_ȁwtZgp&|s5縴̴D[Y7MH֟XNQV3~mvnSf$)xNQQ<mϘg ؤ;y'.6ѳD |bwS1@E -sۻ*QkKs{+ܾEzxm6B6Q}mYxm6BdQp&'>|@0xq@1HHzN>'Tx8x%.=ƙJ3L2!浄_:gQ緆jr+1HJOsjjO}"?]XnxkOlHPF,r7Њ$)u؇dht]rEw~CG!-}ǩ 8:ij'K~T!f0hЇ'hP/e^3|wa/C!}aMz1t>m84)VoIiB.sqCHID+v}fS;Dm~3{pZ&qsZY A`R$MP$M*K>=S6F}rһl)ڂxi'O8vvTxͧgG@L7bLE(=p÷g/K8mH$@+\B+ Yy :.D[%2o ~}BJ( +tY +Vbңћv18m 6s­#l7 *f4S:/}Ȃt cΜ:zaHaS^--Bhq`cٖw4)G8Rfq}p\a5_lhC[yj&@=rck}DV}:!$~Ajp^Nu ':tF}|82ۀ)X!B8/yN]c:mv9wF B'\2gBTG/oZhVc8Dș,N7MN Tt7ӸB>WNbE"}3x}} '`BXƚ5=#*R9Quc较GDGɍ{8BǴ"N&0*x.Y`2H{{SBύ"G̬ &UEY^<;"_z@n~I&b%}D\T/}}) q8'YEm&O18 &ǜ+X)WO DƌX#JC_\``"ʩKC\L{ =@H7s+Dsw7]NgZ:Bv3GO 4aG4$h7ZaqNH=+yIdYA1N'pk]Ϝ?kopGJIy|(vB9r⚙Cp\]v4g"쮳7-Y.7G}& {T`'}uR7O{{mRzB =AX1g{k ws>5#4ZS/YD߫ MuDNڗNBdkg9r wg!-3:kAA3Om"6ez(G:2#&;oq<ܫwQG.u?uSQ1AQÌ:b91]g4]^KL\˗J XMǟ^)&vw:.6ᶎm8zOE|\̶zwkC-ljǥ$gee߿E%+Kt P̞KL0槫cM ,.!gGˣLJ|\.9qؑC'lbayH5H(Spƚ}4K @]w;9tSB! =pQ&kDL4F=t;vX7rr&VGM{HAH}{״/C9\ 6z::<4$1{6,ؽKTK>rb# sSnLWL_16⊘>f,dڟ6C"X"BHl yٳΟ;{,n!hr޿CJћltǟVj߬PrY/)>X` '!k]=}wv;}MjSc *2C =$W}uPg@+}"(##RuI-cU>S-1MQboW&ږtƐ7VXd2wyjZ8K.Cޙ,S3_~j30#|B$rOf,,y'We`kIATdo\bK&7dbAn>]!}sK@dNN?,SuA#M,t ]dг}g8Mx@"%zg Jb=ipʻ}2z"TCbT_HD0U}r f{J,HI|X_`X<ӓ^%cTLcU@408/”>:O.  IilkL/fEb1';"'(9kQC`gryw*\Ujxz-H$_NIIy"'f l,5!h5;#L$cYg#%)qH 9풖yR@a '6ZQU ֻ/vψY6FڷO|:c/qw`{gϹNƻbn_}KKGﴎ[_,lI477u|aQ*cvU'[ug/_eta_z718u~f71jU{''n58}3Wb[\QsFE>ӟt {%6PA#2Y53~Q 9x%KK9G1jͮ'B1f>^[_ת&v̳Zm'UV_-༶p3Últ3:q܉|ץtxNOmjg?y̹K/_^MESR\OC.:-3s6 券Ag&XR(sbXdm?r+.jZ5O}|.G<zv1[]a=7\.޽{K/JCC#>>~ET Yj_|Hr5!XP;X\*>]~G kƾP T*k vy62d:/Ovj; 87op͎jFM"w_]W!*S:v?qiDF;< '#9WMbK۴Z j%Nu繐j!A݋qNƨΗ{>zƎZj}szn 4\VccD"QZW|ܑ2kYN_Y|>7PFjK"ubm)5l*'XSw"w(_8HD@ˠ2Eg!OZG%/􎞅g2A$E^Eїb"ej~E\_rHT7E}ZOE/} XH nst /N6$y{9:\ܲ_ڝQֳEPh6hȷѦ@kFNsnfYIY%SB*3SKT#X ѷv&ˋtӃꈾ5+MmϘ#fNƄŰ^Ԧoa OޔAâY1 l3-AmjSZfՉu'İ@ܰA9QWNZ+HsةaԶ1{ a(\ZL2|J~3~)wdp,i4gњ&\w5ZWe֪׌PƋ i.&2KrB%f曣aԼV-m!GS1h<2|-Gk{<C\"7\h=Z [40F}X0ZDun)ɋٷ>ƭ9_DCǨ1|Qbr_;ԳԽz$'ycV_75>e}}铺SG;dժa&dϾ2};2&ogbրV:ӖdJq؇8^ߗ566w{Nu+V=[ҐVe0wRZ3k/9SzD[Bu䡀˩vNӶWOi&w{CҢ2=o1ݜ=joI*]U x 2kRodY KIīqcPKTOB? WI|$ޏXAN4 :G/eD3 qʽsiwm&d}.>]!kk{ײl' Kwlf߱->yMϜ ɘ0io7bRh)ѽJJߚw31}, q? {U®oK6Ola\U6?EI1JY} }ϮbcJœ>ȬSq™N$\p[A0!I?w ʅsn=VKԶAǠ%9J1>(c>X_ZUwɏ>޽1â3h &i';V*1ȥd,F ҎJ%\qE1b6ZOr8] yQe WmP3~sRqݮㇶ~26~٦㧎b<}~6]!OߤZ y&綗08`>!LhGNQN"_cƺ`?EM@bD r{^ IFN/4qeID7Bh0w|96qg$`g;NCZm֦=!P'O  A_N y^͓ O|HSm>l)Jr ~bU[Oyٴm۶ۑ,66}pv#D L r֡]j j$"Sp(;:g=)ʨ3YA_ E°@n*ĕ4_h"ЇJ9lӆ9SF3vSb~fٹWŒ^N\/lnx2[͌S TczB*H0D3 ͇F:|?v:Tf{>M;ֳ<3i}gzތw|\>;F PrճVsjB`2cpjIN jp[ ~H+>ATOޅqJu-jEOW[+ @Pgv -;ѣ6m eMW۹¾ߤwde@~>IlT!,m3> Md~u?h۵Y(IJz^A(c2mJ(Fe~m?*}{=B:OyS%ҡY{?v6S) 1J;^ }Z5hORhLcVӠ͠vH8S o2:,l\_\vI ۍ^xI!^cLLF\'ok8*,v ;2<Pd~}|ژ& rϬs􊒪@z+ dKM_k4Jպ>PI&E&䱤 $hcGM1;9͎?X%25>ۛER}Qdgmp H;wIb6 .)hk 5?I1.$ "S>?`*T"}pgCz8E"dSϡ+d*Aa.Ac-(}>Ϻ_y.|bə Ev b>O^TdN\H7\=`*8l+)GTTdBb?cLHK]AHQ" +{hMVL&vǍZj8)+٩ݿtJ(V qXH9l)ێl>VF$!=%h3)et-O)&c. n}N$mp!VH#cvJd[U})xIny,iqXѽWRpl*9\q7|֭[_? M cj|_!!"-|\\4+BмT¡ih5AӰ4kT>{ۄBQg_BO|Ƴ n˺+}q'i/ƨ3k#?Q􀭠vyf&$9rdӦMvvAl%A܇Ci濳t~>τPN\1)Xuޫf,'6 K[2Wf!1,ҼolDݞ[^qʮ_e|UEIjcDaWM[_rݚ:u+Eb ߹wWԍJi跿? 1OڄZИy݌W%{T05={7l/Wޓsy";oH@CRz_g_y=QǨթ|!m9X7E7b ƕr^׾ch|"0}F[35?"藒q<f[)m( 9/8}ǸYj8(!TR"p5VdLZ_O"4B>%qF+>6 vecjr[\(2gÃXл|b] *|7EU2S~`l]Hu/#']I }o%\*#4ڿo?tfַiǽE nD)3wP B-Zcl֯uʹw+# U=cpƭF wnM 耘;rg\J'v 9?5؍3%Ҩ7;V5ڷ>mq5PacdքWU+-n~sNOe:C'Aٱx A"@`dC,8c,Aͫvb}NӃElIn [bct9Plea=3v`Þ\A&jjڠz,CiՑlŖ@+vx,@G%ۨlžA#Vꢁ۲5ڷ>` @?Y!imbrz*{ëz#Uj, 79]^W`1? DeU=d5xzn+%S[:^~$z~]oblھ^{!1]Ohumwm[Z+zu>Uڞ[{]LQzƍ iY jSֲgbtjYԦoLc BVygO:BPx$ L!ۈ!{n>ã,1$|V9ϧP(6Ua ޢ@p1-] u5UddCdD0n' ѯ>T}Br0Eu>3Wr 6t AL\ %¥sG - r5b>TH ,# DPR7&X !gD\Lc փU,N"-h,!}`Y?:䔷.oCԷ>R400D&=Tk%eޯ8`zjC*KXؾ1D|@@nw3726Y:8&MF8 i*{"16rc'Qn=Ydi``hlf}vF$Vt*H;Kc}c ۻ$E. In3@ȥv4O3Ԯ/Sc#s[.@L 0327uiJ94./$y#JPg^SG1k~*ֿ{f(l:(B(Ye DbtMvXv6˄n`ODt745u(+ސ:_:ם#\! uҶNm Ia(o5/𶖶LU/LKK.YUq@E;Y>rZ+Tx>2Rm۰݆6L4:*/Ls_z3K`zVVMD 8v'_!s2P}Kz7^Թ[3T -1:Z&ffffTXkgB+gC3ı{{#X5#xĚPKMm3ss5p1}"E~:>3әcuCǩ}.R?V&%|aB2a2wAWP:s.}$h,ڡN G^Y frP©%M3^|%Cs'.y5MLV_ *'IKwgC 1j- As}/^~aO. <~c`z7td*bTJ%=x!v|*Nv,rƿKow)8{La>v %2wޕC8ə=vUjBt7*#R?<=K$m?AE]q+DzdJG(c3"ϳSwk("J;ǭLp D$nj7 *2̓PkIG)ٝi)Jh ۙX؉P`hi K||>Ҹ(]mk= %!}D"+z|7LJp퀼nr8iFj7nAܦue }SBj腠#"";VSSkD9{4HCmx7M6!6|wm*}P `xs. Ƕ[%C>?4E*2o,W*@ȕۯwL2@ qdR24C4ӏ/!ObQ>R$[G2X%MݼyDZb" ꢍvk=;Z_ZkRD&Kow+<;o[y5>Ua;칝džAk!!Ȩ_$:kkE!muX)3AǬX(_} (\@FM< NTWgc|̒dyf+~.6_e8V녠@'%%*=x`CCT 'h/(;qyKl\lppq֡2쉼O8Kr+>b+Z&F1u$*[PG6Njb2=agx򐀀}im,!vs)^*2/YKN7|{Ӂ M n833tm=SkǬ~h,6ԸXX&&?ضdبZ[ r8nBX[9wglkyi֭&9+?Ǧf~5#By{46ӟ^[|aʭU z".gIK"!gFv6fh(}yAX*7bW%@%ΔYn94Q >?BؑWk/E M\*:suk-0F7k`~6|z+yBM̶}\#2W5I)Ɏk#ZА{Y\>dVnA @dK~D=4iz=H pZ2L|}-5Ml|( $Oss13%BZp56΀(Ql_> ,.lz-Mα:i/uO2ܧe#sQ=Q-[?b.hYEKƻ _mg>t*˄r%nITqr±p-P=q:;ѻdpɨϞwܱi20 4H'fltY!S?|ީ@9,ϵ0;c 6]7e%i?F;CoKk? qt?H |-@G;c9T駽I/}:Rs3-Pq -G^K3im8_187YZ⭯xwS59i uy\yz7lx( UHS /ձu;fAp)iE=A8q.++ir-A('';2*{{\|X}U ۅ<Ӗ#7uM tut &=o k18/N?viNxO1]r[Zz::]ri syl%GUJ}M8u[c`ݿY=?]=)(vٳC!d ѐ^D&(9{iX+W"OV pMwmkt|ߵK Pշ.#f2,6K-gtYͽ^׽}n}WwTER>s>T tֱM@*sCMōKG!T<$QphM8 @.цknikpSPE ^>IC 3ps/r ÑS͠VѺ  3 c_!Rg;++ƻ __|a%@eA.NvvvvvI T|SRR<0KǪe й(9,њ tw(d2|]* G ~Fw[LӌædL08 w2{JHL(`kmW7FKZl|iRYNRѓpfPTmH;n^S(e ubDkql~<칱O'e:ۺޭɄ'Xk`lHsQ|Q/MnCJc$! h+GFy+b1P;31}%;?d{ԑ´@ yb1A$=r1?҃Л|)dB5pxlF[;wu \P T@#k[Ŋ'-`]_,k4CPRH)q426Bօ⨮_ D](@n}'-Fh4T=栭Ȓrޟc}Gq^ @j<]}w چȺ(JOmmD&54.&6b'<*G 4|HDl*!nӊ'*!8E㋇XُeZ> z8Xy)Rwi2 Z67"G׿z+bۓ#y,KeMlد\+_6 }_ ϸK5( =_yAֻqzDS{lh@u5Uha^(@%XI8[~=9=T<}R",Ӈ֠cUзU *,0xX"f.hٲh΍W aTYtmo,,`:[`s1,\jQE.E- o@ )2,\ԃ|,z e~AHm\뺚n_}*R.pA9ڠ* Hf,F5KTz(Є> JM^P.֭<6JXo_|)@YNZ˪6M?h6hYSWOV \Ʈ\Q_EO>ȥX|4/@F4RIjq?>t3e'T퍠e Z&<*^#P.ajc#"(Tgs>&IIɤKefx4r]ַTgIׅAE={ !ۢ'>*vUgkeUUHYRϒ!7/ּt\^U鳄+U#@d񫼋8lr{t[[bB=mK )ܡaxw0O*ZߐV,Bz?SzC&طU , Z)ևͅ -Y(ӊeՃΏٞ\|cY բ5,֌4VZ}(}b]J}%Bf@H wړ͙j`2Y,`Hǫi㸧BϦkC~N(Y5zj} >+~| 'fD\.׷B**sו@$nh z ӡN2YhL6gڏ6Ѷ>\eB:҂,ͼ )En#7*T"Ϣn>YHލx}ǘMա'AyҒxc{f"887MLLF}f lt×*=n7_t=jr67yP]jF.f.\UGe|?k״b[8*q`<#ro\(e E&FQ* FC靫ԍogrҹW/^sU߼'B6ǡ燄o{W߿EPqsnS҇GńE>lұ W37߈X Ct{ -o9&7q&ZӓcC#o׎c?|=Zo9q]ַv2vYv2OyyF!w#͍mzG0twu|WHMGϢ/ӟ4%%eE0"xXDmt{4.YզZ($Daч^`657?_.mÇ:ij8!1|cޙm,wVmqa&Vw&}E:-ZNYC&&_b3AvO)qεu(;zգG(DNƼ@GP27PJ(μU[SMt Ft,E=}|sZ ŨdgP׬rMK{'7흇\{g͞N{S 3^كsHTqsU 9djO:~pB;; ,B.7Ilg#_tl6׿/W_Ј_k% 8ɺ@|Hjf'̈~'\frC3Z-/!oco>QeW9n9]J Mn"2.DȮO4]yXQD0U7TBcV#ЇXbCgz y\1W.J~ыׯ]vq+G*s.9r%ۇ&,jp`eB'OX'uDbwg m?~ʥ/|L'q L)od^Dl'O_|݊X]KWn]٩j\kς]տ,1z@h%H$)K/N-qJD6zؙ=VK/HO7fy{2p2)g2ј_[91۲Zg[&ZZg[F䳂6^~a!w+G<mʄTP*K}C :gzʢC"k8\}ZO\_ }9?6_HnnQx>VԿ%R_akzr.T0ͨL?5GWa&(ZHJѦzhS]}QF=hppt<,B:{mYhޒ4OD^A$Rryi2^5za T Obȣ"*2{{]zOzq>K%pYDgi Z^2%5,:[FLʒ-}<r2By&_="ꛣcb{)\P,K #$C,u"IE^Xg^ցP~K1_Wԯ:V-2 ZJ9ݢ-Y5}RQFK;OHWܟ(K>KbdzcjQ=CY2@2zRtѻY_}.(zbktk,XrW>ZoDT9Գz:y7"8;bI%%sfɃUApCoRK-Ч @mO,2G/ o>B`XJ ("i\D]p=A^&`rEc^ R>jm\[yZ^4\xe7AHDmll6FD$Ԛ nKב*CUy2sk &OJә ׃{[O\(_dggolE}&|'X9kTг&}k IFZ9~Rp4'He@;y>fWPuj(zQ^POࣘ TCIgpj1d8莩cx\JziFHc9m иؘ9j0z!y=_?7Fh_E(jjQH*iy/_(SLY]t`:gh۟8uESv3=yF;7Olz=6L|DsE oDg- m@:dsW ڰ+:n AFy]{@db\t\Rj,5]ۗ\ *q!z-x/+++ g?O_~ /`g&j|9F !t~ ܟʥA#:}]z6}'rgEFm08P4~yT=֋o?}LfiiiJJJ̴ reu3}$l7"(߈8=^;bՙ{;z;̊Ɇ{7ܻN{VEj?|m+B5|zA폼@hK؆߈(Go g.Lݡt-RWXcJK`bTs^j\TdFU}eU?K©&ȋ+j̺8X֋o?}GoMbm 48eR}B*BoY'|U}Z/ـbZKZj=QK-QK-QK-QK-YSk Ud%\ &QHİqdU|o^#-|HYL.\P"%'(Iy(H./ɤ[\+RpE :|^SZlQ*HRtA @ؽU}=Ehxw_Yl@YogA;f]caāitXayp&Knfْ'~!_$fO\d37Kȓ#.{/nϞ];_3oe(dR<"{vm?m/CwzSvlzIh#k AX`{IsYYR$T&ӓda;=ƺR+/"o.0>5cVA8nV pkTn//K4^[;ݻJ@Hw[SMN)Bb(E%v̰DRK鳊>ЌEEE"h蓪<֣|-~)y.G9<)%`h&.Ƌlusșq@ryiDK w"hq4 f ">g-m42R+Z,DhKR`pjFzkg|X @QgS2 +z Xs9m绩Iyc5A:%@fXu!yt]V%@GFZYhZ5cCuQ!pL H=5 3 vsC7 eB"Ero!}!BE#.!ii)c՜V#KڵFVrߙ~wclS5 Xyz#:tԩ'On@}npxown޽{˖-a.Cg,:JI> ьG-sG( r=x8DHDǞOEf%be~P@pK "EL4|x'p'\uCTu$ bSFIH,kMH dzIcSg4dlk+I3 Jgy"zoUMfrZZT_p;w<)/Qkʹ:U YD\1wX0N׈o rp=Ԍ70!] C#k0e|Mjx'䡇7HD#݌ഠ!6CK^mQ(.ZxU}: mVq Ǣ1ȁ# zFHv?c]G| ˄OOQ Hs[MBTZ>O7f7D[~jrwvL NeBS3G}ۗHYbmaI26rԱ//_o18`נGe鞲'spڿAU]ηl3l-}zL]Ӈw>trxPcӋ N=zZt3u N^v.xtbusZQޱC (qg0Dc =])(sn$B+Ybό8:oϮ7 SZ"9wΓ7R c)Ρ=v lLLoW-RͿ[wn.PpKӬ7v:{m,dup(E>wn߾MXroo̿{>3K(? BW3~)r&tObk˹[mf^7 HIgmU&'+>莾'm"bI |%6 Է6-6/$,Ԗ-'c(voo·7}r:⃂ Nl߹s6>&j,4$/^tMna' Ŝf?}Kz A=Q>s2/73۶_)dM_[ #k Y_w2Oh+9+mwNj|a"=ȨLU@|Y߈Hq彣4a'&m1#@|ԅ!eCsRX2vW^O]Hg@}:vAm۶Z8ΰw->#mmǏSSS뭬#hN[uM3>9 yy^fuΚ{= al[&8βg>;7?~o~|>2)1l &e2sljb 'i$.Fʃݰ*,ʺfnV4)2qzkY cRaP ʳbCM xPZZ܉Kwܫ홛]XM(ϬgGK*bQF sb|n_MmW2|m jfJD.7C8ӝumtfX?>iVIm6_ͫi!ДˁS?Aw1TO}8"g\4).v R",osMHOɯϕnXfES*\G}_\L)LsyKv'C G}z_ sqմJu켁_b:w:fvg;A #ѧK8Zgk~]A;#'.YYB'cS’K"\g̙st8F RJz.ub': NONf:FPu ]aX&_lJƳ ZѶY5}V"} 9εk׮\244$<¾0j'['I |{뭷7H5<<i}l>H#rbpԹ7gΝ9?$g uݱ~/WD;7/=i%ϒsL߫?}%7sKQCsTw$ :!^̹<1brlx? ۱CJTΏ#J0^x-[>4Fŗmxvqizk(tk{wvQR%)}Of@NB N?-6<-jBυ۷m=sǡ6=ϺbhzK MnIv8 M|(,OZq0G>es 6L._{XeT9랾)E.;"}`mobYT0+ý}2'vZdN"ݶ;ⶾCHPkt'Y|4Ν!`Mӑ($M~y7pF玟E*xYJCV<*]>~VTa.ço;\ Bw዗.{絓n# .G"'3G/tg:]>{~}ݖllW2ڤtOTЧngXپo~yxp/^MW||ɍ7 R[3h--͕U6ַokڵ> o_>6#qBf{.XG'fdvL! ?^ϦDR`;։I)΄I\O·3xreBx+R->:1{*u]ƽ?18ws}vfYAA(bDErT%Zĕsy}sZ *vi}g,j5S[5)JM_ɂ@VsI#uϷ0 LVZs?o{$U$<'{ȥLl$\jVȳ5u_!J;Q=Pr-)(nN\kz>GS˨gIQ 3dZ<4Xs-Ս5?k{wt6;8M7)7'hx0ɃO3ffL, 'kЮݻ&'&k?#F Nǰ >:bEDŒi o{'b)Tc781w5'SnSp$*1}*AV8lM~!x~<^<;Ynx@! &x܋<knep%u[g .=TAܸ]z װ~fpeCZ͟. tJmfǚ=Q0+E|2R(}΅Hkfr{wS1-vg5S^?˙}i]#[hX)kuSnɛo)YS3ζeCL~Dv{7$u@T9u؇ZOkim}iȍJ@B=ֹh+ 6kq{wJiiR# 1}@R.vII}$֫-N=l}q,\\*q͋X'*C6ǭY{&J=zXȉgK <VmaSߴ|V[Vh@[JXgZ:Ƈ3t)Kc!]Vj/sXSR`pQ5_cgbhiifQԌ*+x 'Oǵfb:LFx%PD3]ְyuO:enqKC#6ǏX)&?ttiFo%<׉flq>s)ODb6vzaLn5n@&30x#аOE؇(&4qyM#n D͉_>_ | xddQ}*V'E*!W8T+5\ p>~6p9#S*Bxuuu_z3 $\H[<čy鱱5-S"sps}c+TP,䱱sRvE\*qU:xPW[m<݄\:fՋz61YĹnu0dB6qMuUMs(z<|D-іjj_/16qqU:]'@|r1__]oxr5xk}m}mMus*Ku55Uͽ8[ >|!91.ZoLvI{sr&RtxgMe"B^^U9\l!4)əux,lk/U+ Y_|z—'gp :>>gId<5Hb/vs Ǥ`'&斈,P2R0 O&jHҵL>4wh>\d:Ň; o_7" e;ŗ>L&?z%تJͯ6&2s)!OTWGVܳ)$-cpI%v/S A֓%@b@t)!$4HnVxdPʵ/9h@YH?~8Ǖ Z .y/ \87h{oPH\6WcpU I WJ%v랑Eћ P)C޴7 J34j3P/\fӔ&_8W0;? nZ?OpK=h ͩ<)76BgⓖJw;;+`PotglobR~Sky:@}0t=w541g{B[bűOT}{"8x~z"LyhKV';7`rh !\ )XM#X JEd2?`kb9B|,XA2oA8vg;e߭`;b}> 1pVL"K4KRB w}z4r'+Z @5h0o?@6b`m"hC~>(مd2Ai> #7UaUטP2y]Lf/!mm(KepvrGDHy8Q!#04B$0M2$[=p0pZ5'C;J*IyW6I@ [697VXR]=Hdo>tRHڰ~ա9B\c6%Vӽ\&  koh@qیsW/\VH*.v,{DA/]TJ-~F sJ\{gdo]}چŻ:D,+SrpQBNaxGgգ$iȭ؞_HڔseB`q c-,sȒw~6R947 G~nmbv8-U >0hϟyam8 `e{ER>OK!Wȩ ^ې"?9Mnn ޾&*mc8 6d>r3%uϑ !פkX](*~^_x̿etms{C,>_{`j-5D2>j~ֆ4I߃6]0H $BKJ|ga+ `L)KcCÓ4++[)dK&jؽ-xL{PP|pj!=5MnZܼ۟meގ훖V5` G.7gvp9ˎ),C]eB64mC???''' FBmì,_?_+++SSSoo`4% [P,.U:e4 چʖktG."(MV\.!bK>6܈qr%{fͭAmnCZ !`>#( @,G*. hտ{ɓ14#$lc¥bKV@נd)8ikz}ˇ2>H /ckɴ@h t)( } ]E |r.?thT,p!iAJX<##bWS>nj-65utjIV1)D>6)Y}]#/N ˝d` jg h G^,;oXh"]➍P@‘o7W>/^?qDMM K;>cn^n_}}ٳgnnV!"-i,P_oIUjb4>4 5 P[ΚyĜ;jjp̝~Mw))'O7\r1122LJ8|W_oN^\Ѹ_IqCFF]t5gȳrbt#kg*9dgOy$&] =apn^T*U{y9:޿tƍX"SfJSOǟo-̌ܿz-H.mchjjl[7P׋'9{ܳasŞte6MY9/Gdϰ;sC,}:E(Z:&&&{${koӬ<2&hS ]Ȑ Q rSeaYB˕-L @GN6\.*h]%_ D E;bc}F^^YWW⳵ <_rqq{TBB~KKhTimL3xJ.dxVYۚ}$A( -n1(ZRϳ:y:Eu^]<W_m}Y{3eu] /u6_O}&V1c%gew6s}82#dd)ϻbt*h]}Ch pi߰+1}Ϟ+($<&~aѵ QR%ѕ k=`k]\)!_8~gtb3Yd2cFKb<^mMFREv5k ή 6o;G9ڟ{f#x?/;[zFr˞&W7䄟MNy#&+%."̃n6qv ̨z;;,x~T[tu:{D^i#ϣmvrI)J7|a~s`eA&Yچ3kw=+SvGk 9>[zg(t|u'G#FzkC7N6ƖGlr^NEx J\j&;d 8tj9})!u%+QL}MvM[1G2ẔkKM91pNSj{CA1^ms=}$=aY`crhj\k?|mtTk+֑GkLRk"%֘WX>9;R[\8!9fw%CjacqT|.33*. d a)Jp;8]cR/=N*FC*f%`nb{mR?$MGVXq7jLohgG,w9Gچq/gZґnej]C3 'm67[Z$Na[oa^4ST0-[Xym]$\|ÇQQQKKK^`+hffG9r3($hqaچFچEnNgU5uwv` rleMLNcswچFYa}=Dېچ'(՚d}dz|Z#;޺>ӄ\[o:;;z'VhR7]{pKꆶv/&vOGcdPD^Nu iohoQ6)b߾y7RKIsm⢋N0H®#9(ɗNf'imm$ nΏakh @mdqy kJ$u#Oڞ^$pW; \r'Htc#j05Cm(/)׷2/\{TSZxB>Մ{|obиs-,hچ[Q1[!ЈP0>|>Zچ[ OomX㓜6,ުm 8qЌM==Sdچ姁VzxJΚL/z&,DvvT]p pkrF$G6 چ )=6>Tu,Q2Gb *11Fϥ#P<059+t+]g)r] b9Wp:7ΩG$4Y %2Lu+m"Eϭ@mX~[mXu > $ !y0D',MeP@F -c`{qDhH|庂2)82(h+6F/4fAHhlsX[6| K7 %*51%R~-"c8l-DY+|FguO%B-G6Z=qk \kt*ǂdZ{H5D\\g >&<>}0U\n Z$Okjiilnnu Kbߛ抄'滍MM9x*Ĺ4ӔW VP&#,>bp٪LGwkt;ۅfF'N9_hC '+MϷ01t9%?9clfjĩ DB!O5[8q)Rn†HKmmglg| /&Y˟sF'9!T-#v'8P9pp|NRɋmz&Rp}9u~odX4c_ u&~:KziwhBٴ"_# tn}rT*Oٵc-!FJj]nIz&gu TꥲPHD :UV5bR_saϤ شYINWK (ú--#'l6T]mY239yg l\lKBhL "^%Y|0aаOgI|qTrcf3^Qd2%e ul"˧O`l TC4~RD{,,fQy`Џ1~nSPE`wvuM-l0y Mq+ X:_( (ZJqkn^cC&L!\YOuuuQ}C/i(؉4DlDO'{` MBz'qEb!Exo{@C]fI 8\*z훷}s$KFLw}gx ÒԵ鎷=x]|4?dBaq 4M¯h0mT2z~KmoA$YB/` HhДhZzEzLʱ(,S ־U:3za3.`Ѩ%8 bLۚK*B̛u(ZHZ\s,W,_XX^#R>=zmhOAў6p.@Hl:qdr@ rPLֿHlv@A>:?m}z@QC}]oڻ)ԕPצq4~ Af(<|T^^VU!k69\|:";e{m ߚoUD+ (r(ɀ["`Zx`(m #nkʅtU*y<^vqFv6%(`GRҎ+#h`g[2"yPp+jf-ndb8@GPW)$[ DBx @[ ${ƃb-!QPUs3R6djF054Θ`,BsO(4JpfRtl|ݶBL!Xp;U6o`+$PQ| =EbY~l=P+KpA,gpddjCmO^ h!NY[G#Rɘ5d?sy' ;' B;a@<<b9B|,c wc}v:a_<ޟ6v|bGO %~ *DZDvo `Z' )]ApL~? 9_;=HhA0RAޖe%UaW^QQYloUUGTаT{0 qhj} `ܧd0RCV& 7*BVj Q56RTtϡfjO/q쏵 $0qk$?Ȗ& (!":H4I>`#,][ U@ \ 9lDiroo}hcF }phиgsLlϝ+qw&ˢ05FzJE*ˌ7 _Yߕy4;2Rwc D_:zl|ltY7=h4#rR6pBɛ|~:.-j?(<.:m&Z*T&\nOxf%7y+ˏ,~{zN/_mð0''zJаF],5=d?|)@whB ;6HKA{npm Ԧpm2MVM2)`1ay0\S )Qd, 75  canEVi`F> }X(|~M] ŨWw"jj5C~3#V&0'RZƅviGPjntRwjͤQGtjMԫ9jzLNrùȴkUBR {V+"V%I2Lyl0L4>---Ǐ$:}XfffzzzS>J/ⱻ :dbp۵{.U>m[ڋy VfFV%Ji5ػ7= O\kjkbvT5W=)05xERKݷ!`*mgijy jn6QPGAy a6@_d`JJḬ9`Z |DWwj<% SV&k}ӳt9W"4_qثo*~A縼N޾} xٙ0R40[0l_+-/ڼ,-xy\ZQuloB 1V"_ԄSљϦʎxdfb&3,3ly=joZnQ/SoȼY?'xokОcc㎎m4Zŭ͸贷DEE(L mC++w=~oa*oeV4 |8FcXO3 BU_>|$</\<-NxgV um.H ~}3.q>i,K#/M1nij s!E,tS(*>W5{Z}+%~w%6>d2̙3X,4O>2T"0X:;;ݻwffʪ}Y!s2 >:|UQJ CjM7KckQF^׆?\P D*)/< 7L}Ed 6nc$r)?:hv.8}ÉO1\Z-c_eXyM? Ʈ7: \Z[xXZ'f%(a[lyw%I磗>HËǧ&fDJX{?&Qʹ;!ǒ'z91֧.j>f80tIPG1 sVWa[ٺ+ǠKxv(lfjjrrbFf9աqV]BNm27rcVL+I)oɄi sX*Ϣ,_3?X}FaY{^ZCf;B.JܯJ ?f*Ýsf@ 8h-}JNdx@b=p`" X٩)iiI_LOΣ1T($Ĕsi7^%,÷DcX.qS37rn*U#S+&Nɽ o/eULv%^-j[GR>% /Ν[[[|G$ }߾}{@FSSQ5۱4}+t=NǞ~otHgNuGp ~S }LW*cpYľB50VGYxPx9J j*CbAd!Li=i[\|[ yQ~P"Q]TI4Tyt-V&&NTf-,wߊ0 ;x9FU>Gw'ٱQwJjt0Ӑz58xR+?[x%w*kK@CpB}1\+4Eג܊=j{Q>$vN = vbɌVBw1 } rpp-WbC]tjG\A]kmȷH}}=J5DEn$~H EB_,$5+dp HP9-*&وPu-w=:nS^^9 "ΛUS>?_coo m8.cjY@} JQ>z⮵}ҍ49hqH@p Q$3_=d~P7/+FuLvHW8<^ 2r@& `2ݫoo`heksZQcEMrlc}!N>53 0੆}ZE଍G}kbɋ/25};$z|kl{O֩X}#CVr (@*W˝q𨝕wtpr#M%N7]7JPgɰ̒{a;q'Z`X+TڂoO⩵}"/"Yq*[vߏDt;AP= EC#ܯn>)oqVXog~~p@W'Ѹ$7>/_F#rzX}b﷣U{']-Y[o< Y?R0տt<#{{-.,(r:V}BNpt#לꞁ, \E4ܺɩͤ4ša5 ONNN8t_Y\#q48L[ZXS؅ё]D'=4 U)aSH5 P]%0dE\=6֑V#%&jvh *d􄐘j4 , 0m1"sw@86ʗOI &qCfI 3> HNXPpIF(4:?) AVuЖ 24\{RPl;7_aPBF>v`}~8c#_`}~(+s?vya;c~2۸ޕםͥDrW}Dp5|1vxqhdu}I0Hyme6q^$Qh`;>8* 8H]\%%O?_ﺾޓ~k9 W9\sxk۱VYl +^'Vp}w3}ii*J]!t$/3ix9la٬|}`8bi4 @A &Ogv{}—==={U%`W6qn? av Iv>_>=\actP8fWy3061@ Ͼo;`__Bmw%ԕA6b>!8T x9M`R6]_#й|KBN 5pѼ̐([/>}4Vz_y.Lʫ7Y[+-ԵIZ}:/۟+a*c?Cn9+t\*[V;쳃8E777@:}??>"`0VW[/,=Yzy,pʘ,'4\!K21I>=snD,~.虂<oPT#tzLL׿[[[?"Hgcn/]~/q1 ۱OG̊)D)»Et|ӥSs9GӫgPCдg3}|>[[[bl63sM)KY~}_\QtʭTBw;}Fƺ'l£fzuÃl]ovl{xH̡cncgm~RS {Gk94A-=yme B/H*1KhL$28[0v~!s|6Ϧm U/TN'۔Clg~ap^H$d;>;쳃`;u>;~'䷅X"K?sh['Gay, k3dǦ6'a"ddOH$6ꐀEu@O~ ")_KЯ?I|K@~0%۰]ࠖOÁwg{⡡!N6*>{y[QS̿īF?B$riD'FpMiw7 yL.8,m88B6 e1 +8̊g}~{8ڋi<^`EVchI4hDhBdD|)@6\BI>}6`vlp k AR2XFoݏ>*$ƬCn!g+Tj5sUnAhN!%n= 5GJpAm;X$$WiMk^ ÏWzu p!7(IZH}R@[[іMR6 M=OT o@rj5,<,ZˊBsT* 0䅍o,iC@$+ !w_/ Go7SՀ~dޘT[9MQ`.( HT~GY^pO+;|cggvM@@iا6rul9<:VVV 2a_'Ϛ~׾ʐ( .P 8:s\Ha "T<8&2œX|EotNOr 8 "qsK\,?&@8"S ' | 2F!tA A |#R8'G9z &co>gz/SJCyn}HԊ񶾹$6X6 ~YbRS\暇ÕVX%ݼ-D"Wrqg lOx;^g:3?MuKm.셷OL.%ITiR\L5,>ܭsp7AD2~+䠁+ J%;w?vI+M9j_ w&TsgnXٷ[۰],^3'$ON2jy>=݃Xf?G˔2BV lt*2O[8p`c^ܜv?{Wά* wߋs3ܵk׷nUbZsFbIWcAj舌U.$ ǟ owmWrt}vn$Sgd9y1=B1v,Cz{@VlIg2f6Uao~2WS\mL "ah,$?_Dшݾ}а]T(mO@>ZF941 4%WʘL6#7&xZ&5_]nн oaS#νbh?kso<'4<"A83䜯qdݺXȡ} #Tʹ>7bGlx`k79VƖezs^7Fot\E)k 339~֙=RTUfТٷo\سPo (N; !Yb%vvcvB1x2nɿZ<b7e{ZVr>473r;tAZ!cuEzpR,D(!1E̼]t~ݞ0Ųn^9m lvoܣ,#RyrJUCGNEX0g$g 'v[y:9!+4wsD^2_w՚SdRrṰnjׇ+>)u ?O8PX7Nm[=s7SxZcilKĂ)P*aS>1;$+yuPO\m!4$B6 >(>33B|}JP 311d1<888@cPi4jepvr0jF=]{&7Y\VC0$jx쨹΁o dbcsnAVpU1RV i_IuGW8y4B; Phdޝ{_0637158-RO\Y%S+Y/ϟ0;T1M3b2|/ZXw~CʛN9t8.b]Xdٲۻ{t͚ ]b{c5uyd]ЌyKU`sMu8[}z γvIoW$Ƚ>Cy6wꁷiLpL(q>Wቹ,6L!I~/豣33Q5>3Gʙ/wb &W$pIUgt=ZeK$;g똕\'ϻcx1]0pg=^uOu[(t>㚓IVar5'R LW(S'*-2ް6m>b(9WNsE~"K]xz-|E,I8AǨ$MAޚܬzZ;ךV<.ėy%dB{}z/yI7*]=R.KAĝSng;탰k,C\Փ`BLI 5P3a3h`>`Y\X/}@3Nin} &n>U* AfND"~>'?dEP~(t9ߘz:],KusH{D[ŗGJO!>\2P.9LO$%ߞ^, >Cלzc7Zx%5QsWk,7fFU,B}Jj5;]8:%3aEY<hF}*%qd*tiOdLɸH6"d;AFTYödJYGl5{Dvbp&%kVqϧY#g {ar-Rsz9BK%͏?'<-ue#ϼ.P+'>DcVV(|q[JJ *mg`}VƗ G|yPhd:UW_wlr#`3ٌK=]"U  ZmG{[?KeR1I_)Bc0\ @Sh1*") Ǧ3V"Xl 6[ 㑗+t=B!S$VÔȅJeIF"BGk}Cϱ9 =6X4"lL ~'ZD"Sl llYR$`IgS5H) fsdg$@J~"ZDQ[s{`)Y-nPL'Q85 3! #g@ Y<tKs.Dͤ"@ A<B +x8=< 8tƦȒfp+(Cy ; 䉻à+0l `6⋤/Y20@$h 8-Y6ObA T0}ЇȈCŃ1 u #`md lO8|Ygz[[O) O=ZQ{?|y,FN(۬z3Zp $ [hb:3mݖ˕|Ri^;clRk}!E*Uj1UvV87 ؒl"ɵ @i<{hdþAp&䍊c+ҴE@w6*nF}ka@]b`%| [3"l FE63Uc3oLTJ̎G>)585pmᖂH"=@ }}~9Λ8d0RL`sn5#Z`Vl;y}?z6cs46ʂo<>AarpIE߈m GÞL2x쓀FA~vS<#PiNGN;S%})VPqG$=wyD#BUF_n׋ ?@hLOE̟4>f:gtвZl;</pK|b}KΟ4<5{-X&i>'ug?H" (1LK?b)I,-,O.H$SHm Ә-'[^SEX%Py;oZ| p&5kϟ?O` )[IxЛ^L(GPxR6%%h#mCBUuA\ ) :Qq>.6r#:W6<Q+SېäR]|<^L$͏=$L.hgorǙO~_R>ݸ(Vk43~^D*OsbДxv$Q pۋsvd4Cmx :aA\Ŭ{vIx\NpXlG ȹ Xw}}o.I @EL}R,66"EhA(fp$kRH&jJbk 5QHn\HoT8nY Z[kФGM} m`Kģ״چMWC mCgl= G)uܨ m2m\.BvX2wIDATSZ)J&(*Rx|R5Di VO)TΤL ̭}!=_8.333''8}4b!zzzLLLLMM*i2Ƌ||nu!چR^GX6y}.yyŅ91B!ILbOïOϯ }3Qy:FDʣ`@ x" F/-P<!RX *ȠSKs3s+dLODdWwH•HK\CgpL"6K`qh:u">yoPtJڍ__h}$:y$ >qIq'N433upp` wjN.\IńEb}葤3qaG#Cs3uCi6|0,H*e涼㎝zs M:6H203Ա>ޭظjm!87kZĽd0g9C ~ \mvoA'LIbGa#.w*5z3+%gb$眵Nf6U=+T2ċܿ.Z7Pmp:zMVSF*2}}s,BռX)AˌM hBUePr߃ 8q>r ԿPʒ"_vvSVpwb=,<^xn|KRpᒯvۥ^y+/9|Xew}0ҕ~m?ۧ$J6]2z/%%%|_# 'bOINy_|:3l|u}*S*pM;nLwkB|O^>>h4JV|Z۰58ImȧL5M7<[xs՜Rzɜ(>35&/`[Biz1~.vn]1:ToΤ+B Җi`!~4VTFx_kc^˽J=تmx+e1uy'x6"4580zMgPX5iތ9zbϽA˦` 07D͘O5v3,;tۭhg$`pXT۳H]Dy۽ӭeK@-$!x)B S D}+3>g ?R0x:%w[G!bW''_ߊ (l yF`Ke5Aotq%ꄳ窖X/OJϸd9"'r]51=]zxJ!4΋r6q5 kAc)|zqqȇ!6rkPԭ砜$̧˘ 'EdqE T[bSQ7jFȀ-l->p4ޥl/"N>nP<pJӉG!9ohBru)lnta:Ay+ $=<GdI`\v`|a\bbclmmnWW'R)ߧm(uݽ1οy=~XeKJ>i,n[P0U5,CWrs)QXU:^ag0]2_gpmaוc٥kjffjoq>Wjm Z ZVW[.9?og 2bP]Sc}MG6`ow)}s*ǂ4pYWanu9y{ƩiU7'p]^C?Ǡ ,Y}"ۑ a'oŒ[9 e3ђ{ev-Eohez@aKUP6Iz{&JH.Z~[K`_C{v) GMkJ ; E^f+r LԄؠDBI̫= ­wyho/T3dB?؜|J =J2ݻgn+/Œ7ke3=.5XW\,ws`W,ۈ P %+S ݒV᭮{yUcT`^썆uz5V؂tH\aӢ`[ƣa"T׎^x:F½0ՉZl e_y£.4{ ƿ~sX}:9I%zU{#rb9\JZp No5r/^rxpZuА7 :/{fxCKUbL-'raJOHD|.E(S3[%":Wl >}? L0mc:yy~n.z>O=r,ѥJ cމ4jî?N:Q=V{&ozMѱko@mÆ.00g9hu-֫6O͎v?KugϢ?cP֪L/5O/,RDEUp(|'6~ymj\548=wi(im(]]kX˽3JI{gËt,2КvsjmĀjhC'RDbtاK38,۔ŅWEqUhJXU[8rPъ䢙g.j /G9O%J\vvֳmXY6WXHj\SzXٲ9"-UF;p,b ԵdG+[ˋ3\"ԴǎEz=ۿ {б]@oJJR}rdT8;S瞴r\ 㪇sO[QSh8v;nx$m/:iU־zs9>!(=ZQ΂cgT }$NfO1ry3$R!y(J//D=:,T Bgz;80#Q<' 崮2*=]#{m/w\ ?p7om7JJDe=uBTf/}/| bf7Nx_+x2 *+BlTw%N>%<' >m՞ s:}Ε *BymO 56551,~XUYCTYSn7-TJfwA 7,p TEݵ&Y}Ի?y O޶5?aR*ԣݜN8;/ tb8ЮOA15DRoL1:k`x*U*dE/ zz@ 4Sr*Qˇ bpUp?z4ST:|]]XA!emjwbV r>U1R@j'd= o8? 7GچtvЀr`.xR$MDĀ p:s}1MWdav͗ ࢃ+|!Um'Pxf3O mSnbJM ]( K|YGc /> )_9E) UwM\y.MCF*hrx4fs(ww[Sn(WTyK~'䞍H7}IH]`Lj5em]-en 0=wmf.{`8?6K܆-D\5X׻a$خT$L&fS C% W&P ߰lf[CAkBMi77-}5hetU0V#kG 1Ei-Ҵ ![c7"RuSV  G \?!-e#Y1}덗b˦wƒƏ_ 3V մ % %s(4lUfi/#QJδAv:ɕ8r1yj80zV+8C;E"s>? > nqh ^~ׁ Ct^~vi[ǁxy~!Xlߊ}l g7'?7_ B;[u|{&@Kmq~Azc}vv@GҿD.*R~ݥ7$ ]"!CG]Why<EZ"IS*rM_"T *!ݟ w24t5~)ZEH,Ss\lj+W'pflئȏHz8T,^vp ߋl/o޼YYYAb"{Md7N^=~c=h~%WHfT(ЖW,?CZ!Jfwx.Bs50KxĵYSXQT?lA< g|_ GY[^Py?V./ lH#}"8,ks T2 3!UoS!1 }AE3ÃC:O6MR999ǓHmZ\$b Jdؠh%6%%\bG^%?IېyO\y ';)N5o|g~ .s #v ;y-KiC,*aQ)wǘ0>Q? b?Qu&n^.N>Mv5Fg45<xH}I KeKjNaDXb%"_ ʄs%Ik=S kFWld"^ƒ܏8\f#OFpVca;754265q>_;EK1vg.pppӟH>ˣ5eAl.g3Y+l T,`xv`Uȁj7 M pAքvAH0'L "چbzhj*`*)vs쁖 )?ϓ|zPp ЛM0\{u,?1qHŚI'Y&Dtq hJzYd dm,PqQ6nR@v0X9Y_c MAVQ&pjCC7GjN"'҈677/##h6;aiݻZXX..1nmC>r˿wjJe"*j|xo`hlg`IlP"ec4< G'Lp؅2;=<44:gIye*0|.$ Q1C#K4чچ|,(oht ˖+ZZZ C?0F L@_!@H*t-bQG0Y6ni@\FpݱM^s"6yuٝZ޳E I\^e(wROXNί9<:=?0J֔}>}f_Z]^ԬLBH,M-Xb)ŮNM,b $"'Q=7OyWϓ.Y֔ȫý(,p $ 8y,][/x^1L:f #ȸĥ>yMS5'MY9=T HUGXYL{In^7l!psiFo&*E"!0mEnÙs~{de70𰎉mWktۭC:mգuTT»y~ ؇_`υ[^L݇}2^@hW,9hL|9}-dsqOࠕ*GF<|Ltc`$h_#'c\O={?ǟW{=qQ'$j){yN)u^*y Ɩ I|:y3ȿozᚐq .|]}^_-pJ$Wc"Br7G NsE\}Oz8ĩ7?<3IXX1 ޽Đ[mjYyUzs76WYfc2ȯtvgRMtL*2̂˖lbETJm}6oUmnIG9gy=m_G\hb$pj|h{d/5!4`چsOL//Bgh| Tҏ#o@ OpwLn[8@ּ*D,z8 ǵJ.({xj)?= PDɬZ40Gs!em~dh__N:}4#2 Ӄ9sqf@ 3YÖ+w{.Z+DZdNMmx4 Ty::dA)rh@CWL!-L T96Aqi535xŝX{u7dVgZSb:-TNzy:HQ!oC")OU  7ه`JP\},G=]p>Ϟ+ᱱavj=6n[G,Y.wR7Z"!0>S!(}td@)/_"455 B EmOcINNvuu\D-:99鵶,Fچ 36=diavȱ*[ ~_+ȕ̃c j 26IϽp)RKD[i L<P3޼6\ro -05>j چNh.Y֎E(2O&!N^е07<(mؖals-ޮH۰g}8RKz:>gjV՜ /i0:R~#({ꬣe06Q?tIh}x5N{.W^4ہ3|UnVI݈M[״zQL08rI|4{#LntG-}w0m }뀁Ej .Ŀ>8KLLtuur?>b , I;59 möfqӈ=oq;0c31C}3ZXB1kWV AmC (mx쳈ɤ[.G^N<;g{J_,O~83)" >{}>'VOs]ɻ`JV(մZ]RhTȽ! ̿o@X.=z8p^^ O?.W [RRsjr&aHg.J=]1%ޞI9s3y#)y L:T `5OUe۹c.hzkJ!} )WjqfEPoi GIShv}m4??hZ gv9#0AN/uhmƌ$.ALbZ8[cWǬ8@*JQIs'=#cKb}>ѾfՔ({Ð}ςBCM g| ݊vHk:8\l|ݩK6>4ޒi ];{ry>!}f ֭^z味m٢`kO;Y40>7ޮM]ʸVvIRG7;y>V)QIgvA Ž`[2H,S[S, Bit~śr2:|aRjJʕ22ɧ7ȶZh67@f6}/`X: >0HٵؒV[nK]ZLŃm1-یF67> lo 5;Mw`лH|HwjF{s `i"zHȻdaKw-;^*?hH%hvA2 ͇mHüLen}; 5!Q( m9b^,ڽ_; |>W`m:MА_}ʃ&6kv3{/#_ `ڼ`;u>rG^n L%߯j`&va"-S imduNax޶Uޭy!a@}m#~,*pUP>ʗ+P(WvRRDCi=T:aG}g?PCVBE\ۭR!zTk~(`30dX#aB8mв^j*#s/_L&*\(i!/om(3 pj 9,H;ll,IF$t M` *l8B uL"ǻ^~20Li#Y8pq'ҲX*0 !g(HKPо`sCf}菃@ (L~2eB*E^Z9nT*Chh(S(O@XTV+8mOƼosaX#]&,TMZw k|hj%ߝ!{E  i <;ҘYE3Er%vDԅG=?FP0k3K hmhܙbwb r42K 6\/KFF|ҰO5m8474<ꢯ8Fچyx6S%Ї0%PP"0BA!p_T.hT/d0`jWqihd3:eUTV($GzIp*&K1␩QE'bdmo$2yl| Ѧ/{_VsDTGZ1mz`> |GjnH*چ[vC͍qm!v+ࣀZ9UH2dyyeaa 좪⃃+qj‹'j3ѧ/@W!;*kx}P1%4 y gTAH6AC@3(t)wpt8 g ƀz@P \y# ɛ]? lh @"GNP`&ɃΕM  v;.Utg&>Za>7o JJJh6;až}vރB6 y=0BdWͭ$.uywKD.XLۖ%*mH\޶[aH9o[^7&,콅cɵ=O|^GI^`1%3,Yd1̒fgF#YJ^{鮪nu֩ՍY4n=6$4RO]ue%8{6ڕQmCDL@gs&~omzJUWUVV5vb~8G 1e3dum] [5+0@G`si~drqyshƠQ kS Kpmc`2F[oErwюfRE3mkGT^i׫%2m .fV,OgkZ Zjm]rIsI*FamPw[*X('&%n>>2;7 H ߞXo]iyٜ]խZ; ѩ tXCS+c$8fqibjr,2::=\QY=z){sm 5u#+G4T-2#\;\[S'gq dWsMEeUOFmvPPю9(͞wmz-/}\GDD|:Ϝ/>,yyih?~Ν;jjjzzU};8 چdQFL okKJ KȈXD'>2-^:{e.l޻$-Lu],fU?R@I;c&66ꁾʳn_q]#g3-ďaIՁ'b$]VL|KL̈P_IjEW dyx繂v=S*B}碖[xO'FRڒ̘`e𼪂Xmo$R5ϙ?{C%Z x8s ;Z#[RK7ݿ)eV:9"7ܻ!kr@KvԹ#mb'gW+Xq8åE?EdͤN5UŸEvP+`!͗FfWdx;bR]Iv#w'cyKkiFMt4EUu͍$bf1 [Tp(@Egm L&4F&y#`0,t [oZ/&ɘͰ7~%d Uhg.NZRKF党),TSQ{s)j+rV۫72F[#IGC1v} DŽMpc91'nYs E$il8qXyWt'y.>6~jܼy<>_~.%''yT Uyb چ7u1:aA5U׻S|2M#Z6`b{: TzճSbw扄&kS!iF'U4o`w-G?4_aPStH#چԒ'wWGzbZS"<@b6' ]Z+_5+PS ӊT:vf:ګ2_Y(\^$bZ*+jڧwlLmM9  p6KI>tš򲲺%N\>fta K.' 𣌑SUY^LugpH+5e}LF~ {WI@PI֞ფZԺ,e˨ۤMײueZ;:Sec;O9Z mtϚMV2͚1V5(ŧzn s(L5-|J5o09[72{6ek|5䆰UTg&F\%{\OSU>]e\#an۔krX!-\C.y&k QYuIRۏ_#TTT444DG!Fnn55RRRׯ_/))<}PmMm8-{O>y@\A+¢Jis~ŮL'%g5WKկAa;-5R{pm1U': {E\hQal6u{Oޝ;^h-q0~&mg?+R"7U*nW5<uQҴ/?meJ߾u놬O{?AIF9{xk3j͆ak G%z/~7d Bp G: Nq# oc"^\eh=>Rn!vƍj8vn"QZ8?6XZf3m:3#W7<{x~H1t>lL_ֳ[7o!&du\ F)xE%kߺ9I  +xEE:%)gڸDîJ |w29QrN1+XW95Oܒ6á7_s9Kν7?ygy8ء٧-`rg}W6QIW>ↆrC$Bmtn[!>BmVBRo7*6)8}=el94djშ]f쏇>{@opB>lyrӣ 7PJPp\SF rچ?JBC^tz(gX۰9X[ÜmA`3X}f|Zq S!ډCWys@SXPaG󜤡!\.\bK*B5ELM E 4BOw2WI셊#qd ׸?!"ЉԂRzbpæ +*&ϗ߾.poo 錫m87ff`Q.4amӸAJ]NyS5X*hd#swT :쎟Ϸ11HCIP_8bvl/V;*Z oMD)k9o pu A7.4Kdr4 n5 \ "b&}@CxrIXsҾ {&的~|C!E!၄m2}Ⱥ9|+f H94}`2bPϟLOO??>XZ@/_D444f s_s9Frӻ(@5 `ptWol}oIdc3 ¢dg"چEjچ+&_Kt9 㯤#w6WLQ90+@Eb9jLzݧq5M;,lV"_ې]Z>aL#zj+sR]2Jcll E2Ohxd7WzHy9!;Ɣ7Uohg@- a:r`qCW/sg$YFإ|[oCH~um?kjDHTB z,nԲ9[cVWyqlg9MṆOR!qKT7>n' pw1vɮ O¿Zk: ;`ܳpjvAģH@>7EWW7**Bg Lэ? 9e| NMgiR<})*\XoMEكGEܣc,T\ R 2WE a@ײݝX=mV8vHd7t<mC 3g˨iLrMG,N'e?聐f H<O$# rShLdiO*6)ty JߗT3ʚ00 OyF PXԽن0G޿+eU~X`v<3W&ܴspyZޖ3r8BS4kܣ/؅*YլptDMQ iF c{&Ϗ rHar3enޖwNH-mw&9Hﶚsafsh- έ[4ܒ)@ &%% OFИ /+?xftC yMV|h.XXNH͛GK)Swj Fmi`Eg -WK9ņ8SaA`@ Pp#X[X%^$JxYxچ*A80J'`Ae`G€A½9'؇5G  AniO$q2׀\ÆCSs'n_`.T,c zNA>9< އJc[~5EkJGquW-wE/Etv} ɽ%@ K|hN(ɯ??9P7\um}Ȼx ؍k}Tȹ )!(,Ȝ"VؖVٗ[BӼRۢ}* xRzh6N_C fӌx޻f =WৢKRwW=BM:n7Aj';y͠`Jg#Eux ,ctOpqq1)\ +BY26(N0 >x\pStkRQԼyP*gd #.th/$*}ePFvg2CʠX4`Ԝ,:؎SX8>;|wB!GzL柾>jټnr23-fmL E/zb۴DCזfj+)]DpEW?|`ֳrr"/{D\\δ0o^ـ|s"^!71zExOwx}+ Sks7WK%.qp>oĻ: <ۯep>oU/dh鮎L5LJZL4?w18)gxc>u 6MF`ñb:6TaB n8u88Dh} 222׮_nhᡦ*tpxԑ_"`8CR e~*lA[l|0mH6zx([eʣϏ^z6@֯>R#$i߇N%O t0 LW<d0Nc2"kY+tT6qI`snF-{L貒bc@k4Kq&cl-|hl$%vوatt @C@(چRRoݺu?G 8 $"a}gzG؜l[Xo,)-j?> r{AbCqAn^I"zTIXh++^`0+cuy]8(w෗J4dfTmb׆W m UlʹdefT43DXkHevVaU>uw:;++axh{avq"33ahA؇bRY I|cgOU_n=-RzR+Fh:t@Rk` aVV%}PmÝě}a`ccO޾}[__ʲ Z@o6G69~{WN˭jaRNe nt\{SgO%d#;w֊,fcRJL'vЯN'wثJ++H+Tro6IxTNԄʊˈ>JY!Guv[Y]J>nZݽ~]ij-uG ''BBB\[v鸹[ pnpLS#)'zL8[A`쏔("jffi%MxXصbI\Jsz⁘K. Up8W.)m 4t'*!he޷?ܖ.i/jk+M6:RR2Š؝`&&XZC AcrѡF!4QAFOhDld) R |әN^+#PO: N+׵"ۃWy JɪvMzkhƀ맄K9|A ܹzQmC&V:,_=?ibjru;+W%O:j6r_+}bUZ?~հA4*F^FWW寲XB|Zvd@mƪqDqEQfՎ$%cXW 1*ɢkS-dQI^lL$媄[3C\-4nV';mw]-:k$s1B|2n-QfKOm3r#}TuMZ@ 4M>ce.rJ8+(IPuUVC]8:Wіl#; qgJ1Jڹ h>MGZ#~Eɷ.Iұy?<:J#m4e'yiYdU .ch4TwH׵}U:rD;|>Pr3R[CJ9&4XDD ҍ ϫMPl]K'K9|)e`'++@ -fFNqIi z^xqƍ  gav[)c Zquz-؞]L>_n--LV멊gXw8W#8 X9zӺ,2KcI y>?:Jff&YYېF (*C / چSzMTux>yV[|}*|S-z/f^W ܅`-ꊈk.8`n8>zݼ!7`j{?t&aI㩲Uu0kwAZrX}8qvvsgh9,sm\b /$cw1XlWM3Ғ}^JkÓ( e^/ĕ=bs zV -*i)#u9m2NlՅ &edw'hIGu,>j(z,fi(|`Wr}{"uJ(ϯ+yfFZj*/q03MAZߨgmQw2D?JO/o)Ȋ q3la;CY<7uLRuZN~+?gkơG26i%):r;CK fi#Mbf8HK6jȩEKwѺ+lҿ9]!$h\<3gܭa#&/)͔U L˭^sv,xiyyQ pu-*-/m_;ep>du+'bL|w}QZfOT3BT]7uXfoc```нo3xI>s0LdnچcTH'&,oW6>F>'؇L%}~C{2V6rJ/dU;Ita隴z\/@f2@% &iH?RPZp"eh,-BFY;yHFA#KU^+%95oS{#F R2JJAZ u+d=SgV ~SUVždo%-LE+σ&[)lbTS)I ªf-nb[%|)'@Zȋ4X!Ѫ5&n:-=c{OF(,|s#!5G؃*|.*!*X=y`r2%/(AT6ݗLDBB䉼}d NfGt⭩LJSTzNv&s5UÇO-ꠅr^'5σq#tMrg;mQ?R54XڏnCe:ߋ'NԌ &9iq'lP|S6yUfө.2벯몐ǁ4_ͷ=&2C7ӚK\  6 ' up)Q}|g u$p[dC\4tXpe:9%5--==59)ft.FƉq`3Y 6xP=C#R/ʝB_19_]+v6< N`CF'"(R@.xyck04Bwr byd79l%>օevŧzF RRۢ*̓Sچ FYCīrq f+$[6R,} NPģ0eR/$Tc;z`ٶЗ_)&Ru+]vQ5q-k\al%xΟR@̀d.UYGNs>E\渟 Fc2l6(h `;ڿdxKys"mXOQ%xxEA;n`;'*cÛ! _6I!ĎO.K? F_p>b%No5o_~adK\sK\_}C^"ar`o`, GaB^X)B٥1pX`atA *l`%[<dxP~n8L;=7 'GFΫFj!ɱY4w%ނ>0u1"hLZQNFJSqc5tÔ RBVTb_4|ehZ[{%S:"v{*gy(t`qd``}vdr%)~A@Rq ]5=X?p5+*&6:*1w,^q8\92ܮW3 @h yk(UxCZhno;.so}䄅'&&.F@tM r8ƺqOf5ډtA$yYK}M ɇL^ 4rLl^8)60{Ѻ_NHĂ2A2Զ(1J"|.wG0_e_̆tR{yP.ǂT;sYN_HjNC_OsV/s5 FPv[T<]p5TDz?_죬g\P1˛n,//STTʏ1UՕk+xƅaGK R0 Fw~Z nMz^鶉@@@uGpX@* x=DA 8 :]J4.)dl7TQоSI*P7?.&>m w>$:F*L*0ᒄȈhQL {E#a.&`czi:*2*)zxHH4S|'CL6p+':"""v fg8J+ H8p; cۨ q{nfrD:#Z^BۇҝmCV^upFg9{8U%t7/;:<bO?E FFF***o}fڦ3fffB ;}`/7\s-) S]m-eɇ6bȔooH4TbxϵDZKII+G4oW~}]FJ_CU^۪qK8n3z#@E(m5=z6!)ҺG R%c;I/4^ɿ.fUy }iGWC=Lşy:9 V/ğzjRH®$]L#j|UԴ=3$5eԍlsF} :\%-*s8Y'm TU9K m[wxpw,f+PYMWG饱٫"cy*QY=kwC/FX]TlAV}wCӹJMV*pYiȔkc} `*pirA2'%g<ɫnԻ>YYY`X@o߮=J<oes?qv~GF>8}xLкߺ;pl6^oSMVSTȡxjc=+~@'kN{$~GF#̧h~vC#1++%N{HKS0kc1" Wf_JGm-~~M3]{]gR5/ܛ4y*>vpW5 A?W&j.Q5c;ۛJyjkLTzQJ\7]a&.n)B 3:izi *쓙YZZ*** v xln[c&~ ">..X=UUrrrW\,_X-0y3oS_,8tyJn}ň#F;]JJPѱpe{\S~M Pv3Xr`B%y i`O"RHu1i 3,@ { y6TS&H4yg>Z!me^SM>XȴLf>avͭii(vLKi(+)z lxyUnV\p}ӍLl?f!q~:q&C[3glDlf[sipz8[o ʈ?ytrR.VLzaأw2rn^=5 0pYͫN(@JqtN\#g7 TT3Ӛ̩ܞci 3m ݱ`ûfDg-~Ӿ&l@3Uھp* Oˣ\D[x.>> pp)6?gNY[}#\_HGׯoi8DDG(k\ǒY[*/^{;8u~C\=82}KF z# Lt=#nPX`&ս.j^?*\%4$X;ȱݵ _ٚLDx?d͉D/dbg &ce(]> F|.0GTj?Gj3C],uk9"K%GXcu+Pwn K]:I#_4g>,1!!4p}nyil42 >gK0ʡC/|UҳrH{`meRQY3cOcS wml5t5Uzp$Fef5e4#[wo:Zkh b&lpVSVHjED*OX ,؝o2PаL jY?tǑt稆[M1:=\$j dя} hO7{i޵ =ȥƥPΏvCDV9=2;x]'&Z`i开9,'SRZxfL-5+k%OwD$ld"+<4%DZ>Hm)'zϨɚ©Z˟Nձ(9ΥUnUn 엷6uzVUίfouz9`:肍mR5o*k Ы"aJ,BN(Pu'XWCQIEUEYInL.H{Z>Xpq(cv.,jwqcM-dnd뽡4<A"x@0Dv*g:xև#M,/>w֩gn0]#DP5m"ut {DVncŐeAĝT:aw--ywyh2!q=?!@MLsdhug0((y:d+M& >\ %y7p @HY'hTaz$y6$| jSo}[q ğ|4 n/1D$%~ &gYB xN4]t>6 >',/И9vljplNo?'=p #r)F8H0K,d_Њ_}^ y)NòJ}cl:\=8, opϼ%΍3fõd-g(}x64BA3$gh%AM%^#9&i9'p+t}y`.8>d2^x( 6^<:[1=;2{8?g" _/HKh;J#"clww7捯9=r^\IE.BbpD@t! - #Opܽp1w P9݆yDƵN7,{LLB}PY6}g|^v{_I~9]S\Wd23339% QlYZ[YS!fIRouGy>:s Se }d{~ 7ߑ[ѷp{â_oJp쎖&6noOwwሯ_ڵ3ǚsjF Tp m3-; 2l ` 2I)_R` =T׾Fr_\Գˡ7We@ q)Jٽοv{ImOdiii]zf_FuX`iooS9T"@bBBZd74->iQi;q^Iuӻ\JFKzY.pS=Hӗi 3,Z'M/DDKv&x@`pRQ#А F&l[|RSCS-~/X2d'w};`uEa59)U&rkzñ8 g*/e =;VWLjs~ |yZ 6nï}T֧c``gihh:Tu}lƪGZ[TTT~??ߜܜYN:ɸӜfA6?j3D(<Ȇ|($p\ q17p3/&y~0l`*6/ ,:tc|'#A87*٠Jo8ǧ0Lh# لYpG4l`R̯%sهL&k|%]ʖBfg(!eפm`uY۠Y F O'R؇` fRt BEE*`@m<5AnwMz^p.?m!i `lSeW^g@>@#t8;֞jơLD;h@ӳq&%|\|XQUU$))d2o>5cEEgem- LuuTg(gF7S8oKYD1=*4f"հGhq᪈/|+a?i ^ٿ|틀|b0,7+q$}&4tuOմ}Rd5ZT/{Ħ-qYwbzVz:J\3jё)aFu lm,mg6V'-CdX ĥ:H74pQހD h[Pp%RӷI'X링݀V6埻󘋕/̊6"'%yiXBM Novx0֘o֩3y=nj!uܛ]g(yΝ2A=~6&>N7>}AOe]{8ߗ6JL;)áO )D=."ou^TYTrǝۏ4RW~,XUNBEHZ-#5;}'׸7$.ѿҗRm% hƣ%3Rdw x[>yFܕU!v|;+wBx%k*n1Q5.YP?fdt(`@t( f{6>@GPTb" fk:LOGptJzu>]l3LJ'FGUAڼhxg+#F*76~b d faGMM  QQь󏾣3T6@$BnngBbBNNҏ? ̥R·&g$TX) |ai^wL#B(N8LYl@ 5Si^|q WLܩw1CJ} BڰCQi 34/;*)t ^5u }OZ5Qk}U9vGaj}LX_O_W5fpe4:} :f)RZ&"1@+BRښ^%S p'@WM^U!imM3'߲iQNs-;cG{*rsZ8ze?NjcUk1ovA_}#?Zdr9§>zzzBBB T*هR/~7:U}^ ?ksF ۤS? DVv}>{`cYEO<>ЍAi=:oQx`*zr<  w:Bۮ3 6)%B7p,:v\X}5ɀhRT!Mޝ϶06aF:l䵎`/U2kc)f՛mtiR7 AEW@=/3=@1Y^GNKY:cw6c}w$\شX weՀ>ڜh:Ks7>(>o!~'߫ },HE >J!r> [[۠23}cE l}-%$d#f霞BrFv>r1G4v8X^T+g{#86TLn^PX=(߇8^n(tWIsY93[Ōflf+sau5\دquNXJ;T-\/-KwwV> : q;IF zwh4f=E_ohlp#d|㍔?Wtw,B'3;ߺ0ޔU3{^Ohl`q 66o4{xXY,9=iRS%ԧ(hXhZẀ_XQK=9˳ω'xcM|68w׬ D? IavɫBbs~dQH+L"*fxN'}ELX:b=W6s1Lhdkecjogܽ!îRg1BKKG qy@L,}`)\q410.*OiEQZ=y״~Hg3ȸ}?3x#(t~oDܪzB! a0{)-8|[ҶJ"0CvvYl~embelZ4]ֱFlZ Rm>(f`нDB7b#(Ym+ XiOl;0 `MNXšՇk$v÷E7݄A܃_}Q`py-M;Ck6GozxxxaB$ֹ<,#55w%;H|-ٝў'9r} 0Tb2Oe2&0Lgv߇200&}"3l:+VƦÃ]<=r{17,:`u;7)PQ>6}.4* k`7pHZZ<*ǎd>hg/ZLߟ9Rl u:0Ps2 ,a?YI<~2s"ZN[暿>e.d;0pJƫFkjx[-8Hm mYa ;K;uۂ P`D+p330244046oY?JeT?#5y v.JXkw*q4יߵ l>|q o2 o}77'6PB;{;5$Wv-Q$)}^kdf& Ep,PS\s>Ȥ (.@ņ3 װᜭ 5*:QմK_}NKK{b- 7 5Θk~Z 5^"BjWe[gK\eA@6#8o%\_"sMćemȁ>sK*kd2|xxH a؋J4OŴ`zxhwb'om=bZ;\'Ǽ/mxdIE<@ykpDO t[^:n h)"T2ߘNqbOqهd&&&Xh oy*buJKxc}P w i mG D/S.$){9k[c;GҹrYB$0$5v[_Z.~3_%RZ``Md;XY9VΓZCI_'8,z/_n<+V㦖4diii}7@c ?AmC mCچ{龡-s{h8ŕo̲gp@p=Z:Ÿ`.ҽiT q3X#t7_mGZjιbq}}p.100죢;y^գ5M51?K||9 !0eQhHD=4(m}T1ʆ^>Zc#fT#oo۲t&)E01 J[ゅYȱݿF#af|$U<ˠ,'@UH{g:=Kpk]@2he _;LՅ8\EG!XmF#/fzɨ?-i[N9xA^jKұ䜢K/}t}444cbb$$$IP?w>mԜCzgzaw_czD]D!-Ĵ0?+C"nɓE-lRW +m)=A6qm+X!Fs,m20|ܞYr,#Q }Isq]99C\GGNDεp@1{<m,kY,e7Wj06+#ԵPlZ_at4`PPILTQ" O}PmC`xyy455nTPPr劳s|||tLtDD8ުmț>xOmӻvPQ3{ן9dn9 o#U5C#skB?<2wzx[7RS!s :~$^SM\CQ_yamici,~[Į͞'6E#UFV^^n^k yxC2({u2#zqGߕs4'㤿VǓo%7[{Ncl:f\Dfu="(k@D\5Ӟ=yϋ0p},&h.Nܪ숅vFm7nPTT/!>|mCeo}@6Rjs|goRWoi>Gϝ=3>ὗаt8q+ܦց_]gC"]tpRyq&ֲc0EvWz76 PAmhϥ> b^g:`mun~?jV-94ݠu&T7FY=P/$COY"ޓ=ځŸQ6!g6%.ò_ג Q -!Jccc?WInZ9 gZf6VI_!! %}[[+GYx !Qh? cޮv֎2*#* d*~kτ6%]$}{o8LGjf#GCR7:{N}.~<L6"炢;<N<\S<>y =8g):CzUZZ QdSچچo6mj_ŲCEmm]OHh@Ap Tg8OFcG 0$*i>v|?$(ñ% W'!_hm/W'7/]ag)-$J_3鸭َC&I63sҋ[m;n޴.>pΛg9R7s-!,oYogt>s4GBG2!P( ؄,YQ Ƴb [ݴ %3bcljnaannai..%{hC-hĀ> yMπ>ळfZpz3gZ,PC`LY Pq2}N.洞ԝ)_sb[g6Ml (y<<}H[(=Pf`:/O(OCCuwFEXҩMSmQmQ-mт[`ZXHW|G+ەؾچ 6qwtpwptY;";w :ij@qkYa)ozS#]Zf$) OfP@D;GwNo}qY74l6&Y '. v`_"\Mw|t4$>,3]Ɓ2ObkZ^J-)y[G7:mx "4#WrHtHP`wnoq, ,BsL:v1YX4)udagY@qF'fHG}M}ެm̥x{y7mK7`p,(sSy.pMCKGsq aк =^+7Nx8Y@eqfGЮ,Op~sOQ#Y*{ǯpM""ӸMo cO6uЌ+x3J!߿C6ky ;f%N.r[Xͯ/5?p&Y<5p;>l~SVJ gJd\{t\`(!B!ړYhe@yeyĕZʿ<}_N4aه O`~KKcx~+iRH!ZІX%~}.v|@a؋JW5pLk kAu 䶄7ׯClϪ;CRU^;DIg)O.*3< Ñy,(.6xGX~TS27}/ |@aXQQQyyyL&}xkv%u8I;|-ޝ!iYk©dُ.&Ph4:}H6cL!k { VVXZ/?~0(sʡ%"-Vhٺ%@wy55 qK51p;C=Xj4q(#Wi'w"5Lbj8i*$ kR[+֧qdikkg555.D@hIm?mH=Sې?TPҵyaJ[ 1y,.kXֻ4kE$ > PѣxEH& `|egpddƠwdhɼa gYM-WCmY3$4@[͞0y--k}M%=٭loM E3ۗe^7@CܼK죯EE Y@}l&jJdee^jck4>1F$!ΧmcxNW ]ې6[PlLf|m ڒFY;x4(t~oDºfA:X-XqHb»WIgr9&$΂+-O=kԓ&C ;Odb۷Bto8q:5ePK3|=<]J{(9uWAUSBYnS15 ח6͡EYm{Փhdt_:xOd>!!!iii9;QA ڿImC8˓6_XޱpXiNkju1|S>G`2鳵^~m3l ^jD7.#RZ*#\m uMe-^I|&.ͅ Jgt؛imȫg,f2C]>sgw&-WtR ÑĆDckmnG?P>w L@S}m-[Ua}<}Th1-HȜ dB^b {͙',!@1ĝ !MF=/(DO[OzQlce=B_ 2Y\MaBM)9K ޑf̡O8˸6kD׵T9' _;r9>111`'((ɓ' vk>Φtee~'77Ux8L8՛^ZyHydضAty]@kۏ,S:@"~8AG](wwE|-n?! Ǒe-w7w# -75w }ic^=n"a[*J1{+M`ýLURwr]4U@dVWGttHpch%}(4&ysWV:~ X13mQj^ЧӺ5Eh#,)X? k'VUf4̋7 MIzi]]=^oJ 4SM~ Ž]e7 F-2?j.^SgTѣG }o>چv#?]0' 79"ŴRNiB"i8C q8t#=f#Pߧ 98;kx4nCEd7WېK%%JfvJ6/^T~gd $ֵ`rUC e\oie̓"X9^̄ FTXGVWp clNȈGS#] t5\ziU:`Wz2u_<@Z[ٯ|'O7Ţ-=ձ0SWPRU(^3?"i(]ť̬=)/ >(> ,)߫ zUrrDee%p.y}UW_ .(--}Ukkk@hO8l6ID#m6780A mެmxXmI|)mCXuRmFy{#dws ĒɢȠ ?HۻiS;Xx|}Vm%RUlq#xh[Y_?_Ĝ|ϋ`b ʥY'30[5Nr$ j1;n/>'f`}wه7 St!t&8=0ظaxH=n:y_} {71깥6هm>6}%|Oޭ~yO%Dh4xܽwI-w%啚`E;i~2}R5|̽$ DXSy>@1VZT?gy^5-l\Uՙ452g;Dsid3^g2I.uMŻF!mv z^gz^?y=Rekum*+|nw,^;HkF8̥Y<?Mه G}Вt2oVdH.\~$qHl--/B >!벲~7izk>{BYHKfZ HIjjl_%9&7/e5ttu"~B45 eoKnp`{ ʶ01Uq!BmCn> ՙk R{CRYESK4}k'TWEM㹺Q&7[(mYrM,\4Lmn#z^ԍsωW8>o:>v }Lflll^^(3 \mCƱ?؇چgjwnX!"vN~>cx*Io{/rrOf`@v|aWH7?&,78~wz#Mǿ   j\ӎ \qD̶e㰘éʡu< jEO4gUo4EFx{5Mld׌n?" ͤmfbq:8vw١5*[2<==SGаSM8~֗Qa-M<;/N>h ql>|q o o}({7mb˂ J2t(rsN34ηګ"ilI mՊ'mCn6α7SUzR[7iq0DWMCdjjĶn} BO_0Lh'@O=8Fr@>aܒ7z^ld"8E)mk( ]s=ݽ vΔO f}2wO9p k)luZ3DvmZ 5Gl…dP0] sCJgLx vFJjqij=O® WN}nZ&~i95G9!R,A2H߰ pP_ 觜24/!52tSߢm_R9~ȗ1joQe-|CGzA *{fv0d`43 N7~woy?K1u eq ,|4ȃ|-{₱#|@9h9]F>?_}N9i%~d..緁>ԟmȦ#=;̟s&-)O^nkSK]?>w1; {J**Ʈz_Q+*j}@y(u8?j5N0V "H3Nd!ڭ{ZqC* `?3|mÓe.>@C!?6~}X,*]a}aA`~ؗs} 3;[onwdXg2LEٸLP GTbyA),SmUE5U2C(4*PfѾS?րqF-ͫ |GU%y9U=MN\ܟu4SkT5jRvg奤խ|&0B(D+}B.tCoΎ[!K(dikkO*))a0" 4YPOSHاr(D gj†O=N˩\9$,mC+$NW"޵TP ` TCK1hSce{2tX|:P"hnzixjR&ZچhgyzEcM+dO}??g'4>Ӻƺq|WPmCVmÙ WM誺' UEܡm<Ř*/ 7SSv*Ytqqv*2r ; B?KCUuҩC'vGFxc ,c:0+#:Y)6{^OdР!n{/nIk 7JX*wT0)\S,Nhׅiy P LwFjO<ӈ۳C5P焉'ÏP`L@۰ft Bc<xeȡOź9dO}چ>/mX5=]ZZX  !Qo6)lյwʝq * Wn_qV2kY#ɦf^11ѕG&yǫwS7|mUqd"v ^V&8U||\}-ѻ{ j}Pm2?Yĉ7hMFyA@6Fh!0 {s䅌ky*My۵ 7Z̕Sf8?mx&.cTUXXچ,l?s`k72!F3ϛ/s'Sj.8.Á4 ):/u2kh z}=nPNCW9^}+aм <Pjt7}b;k=5̇q$F/Wۥ52@e+HDO]Auڥ E#Nh+eEq{yi7d-ĞK$Ъ1t)u5U,7J}$ÇGǸ:`..&K(( ۊK%%%#fdl413^nSV VG ηyچ%S{ۘZ1mYWmG :Tpj.6*ZmTDbF~*FnOdG;[=QHʄ:fTA>ZΉL vmjkzr eBCtHʿQW_}VWWwu 4R~;믾shޑq^ 塌k}0-9MCmu'Q: xel.L[J]PWou[ڷvf~b9o]o?myʝ?5O2U\di6?~DP(qQҹ}0+(T:`WD7s<چf߫Cgz_~CA}]ې?^eh. C|ϫ-Jm(y5EijrϜ)Q:,%xNUZj8h[Ii]3Y.%||b죥777_t9SAo \UM\3<TA\?kt>RPQ°gWz>WTZw =WWS"eV> Ǜ#2ߗb"XͫyjLOrSd!ۋr*CnO$%iٖn hWʘh(d|M=yyy99%mfht2>jE<\^?XچF;l < [aIYyLjCg;F =PYR*;19/|hΟ>%RZZz`>Ec#t 4<}Wچڦ/DX#<:+=6&ivD;2:3-66y@& 9/M>$;Ť'-H7 6m#+%>2*6)c O=ͦ˛6d&q6+g Oee%&wm!,T;HIDR_E2=-o“$lOy.H/vg%%%.v4Q53S6 nӆ,&}w7&**.-~h狍 SMP~g$2"<2~pÝ x: {^4XšXλF^G>&%օIeN%Vj_TT%n| E/¹̡8ɫٓ(jCex`QPmCi)95#gmû2+Њ)42q DGYRJV^NVFN^)vԃNKT|!-+/++#ָ<2wS̾@pb&h`Rd :F#gh"§>aD2A)An3-&=@ Y ")P>xd5Vt-9`!%||J~m)GVGJmxpvzia|CP{ `1]+' [\ ۟CacmCRgnFRLl\B||\|Bb. h.g%ā\_brŴ Aѽ߬! >ZW0M8.cwLצA9+t[glԵ mC74kֆk[FdHqRhBc]~FbsK\'>܃ 8~K6q>888xiLZ_vOUAmܪ+~]1+-.w(ٜg@E9 nG2G! t2!>.8L^yCb{Eho}" q(!;I/#dei1i׊<\-[ʊ&IM˝YݼQSx*ؐ`RԣLKiiIRA[mD HT^{4Yz3U!왬SL8B7OsfؔƴWvIDz?}.U?.><\>" 4ymhag{ SXd*r!h}m~`y^PkQ坥)=+6ctJ02; ֱ|Zך-氄Bq#z_HE` Ad(Kyg&%G !"i8n-XB^_fϖY0qψsT-6IyL_0!s1.緁>zzz=RPPHKKA-OJ177~:2KK2SچAK`34xSt^pӱl〈ԍ_k6`VsLLp*­_UMNntt 7f k<gC$c6g,e}[>j~C]STK6v4Iڦܕ4V3d;/q$ euuJwB34oOt^7|-p1Ɵ6O:L1K] 2,l`,xc`QyY&Ƣ0c5g"besBGLW}Rֹ{״ )J¢/dj )|Z3:e؉4uWkd`PhxGN>X)vTߕa杗 +#)ؼrB"/z m% ˨dNqi|B? USaqJRh PYh6w>6(4&ik4WBVn{8QG}XlZvvV.?xd⟔X(cG#Q/bRrZ'Vp⫆٩,"MX`-ܓ n8>*$isza{uq_ *^_mQv).Jrti_Kc5Y/+0N& Jz#!*ԁHHc:W5V< @=ݒ=0̼x،PTl>KӢd^q/;N,ljO PL7YhFǣhNd_} n[`i?MLLu>L~{G;9 _+[LB[d&d:O}Lաd߳HZZj+X: a@}FO5,:Ƥ#ٹy~vTR!띙fr`Қ3T,B93L>7d>__|s  }7?668V>Odچ"$CiR(c ?)\ lB]y=X} m0!qO0n)66T,N#жO6s]6a?t:CIټ`baÍq}"Rp>6?*F@lUƶ,~TKlG*̵+B % Rͮ{t`ѷF86XWO"#ʹGy drB|9%_Lyc)dP^y8tp BXo+}%YeC42x$f1ace|aWF{v!hσE$Tn ss|8ҿ.q5dg saܒ%#H g_ F232K: [j^7ۖ^нLoc'?$lՒrQъo샠D;6[g2A:h%8}_crF9 B /8{( VL> @ \z%'[Z?1o)Z,󣟾xMd3 `h*灴G$\I1@%S77AGEsq1b/|*׹4Bw⋧"EKJn_" s]P==SIc2 ;8>"5#!H['J.?e9N> P%mWi)6֧&'rzlTȝm3`wbOi|ܷF}SsD{뜯g ؇w}n)-: ރݓtHۿ>o9aAMEs R? 6;!C M#;z'vpT{&DDZ8F!2mE3Ix_0q3΁>HK8}NzI7T~9,A9UHǞx7`A z>ZDOπ\ü6#kO@`3IIm]:Hhr(Y  n#9vKHXxh% mXP5151kf}{1 s me"U1d3fUm\2M7_@&-Ş=~*,,",,,%ּ% e؜|D}ٚd#pbkۜx[D06( ٓBھP]J(V{ X@ͽ۷MO*YŮ;nj;eNSqwx*%|\|@YRSS/J@puh0ױo x O)Jk븓)rS w@A7MCvC$upsGґ\^DT[UEYiEUEQ+;w'F䚩 ͬZ~gS!'r,Vx܃ ^9]Z>~`&0]QR{UW{{~v}gØ@2(% PP$ ( T@ 9t9Wuo74Ag~NUݺuow=խz_taQqIq^ƻI9hŰ bJBbëV.x 'E]9]דm,tzHd`Jx^~.sQu\oqUPe ZX|s9r䈣cBB 6T ŧpq`eeŋ;:A/!THtBPH9 >":1\ X]i.'73ek[CQWv{ܴ)Լabσ Y,κ[hgcmٳJLLV]샭s;{n߾gMm5f~}k zPRY.)YK#/R/NO[&0 X U76ݷ?$K fzdu49Zm(.t~ 6TuP-,zs{pfACmcjIn63:arE b F wU>#KKI|\Z-Z w[YPKII144VG۰ôwnݺ55-/^(p::bg 5ާf^|QT6%LE{mYE~G=-`ʨ58^UTVGckBvmiV&u3̥چ̖h+WYe X{GsBmvs0}VRS $"6yǙ x_TSA~s,GB` 'τTG72F^9l='G^^U[ѭ5؉{#FDPlpR愈>{82գd$ȡkx58QJ.RImO p8WH3eJ$ឫT$F8ۯTNsJV* LQQi]5Gd|} j G*z{{WP?W=7ԃm 6<|!pjsz'Սqzr u3\Ok/5:yj(ƭ5>vVz%9OF4K.هj8`=mW.,$=,JQ!Ϥn:o>u3o/m?Ep3ς+N!=!IL O~4ȁ/L3n9o.la [k˽F+pCvDCE#.Wǜgjzǜ<^x-dnf?Y0T}@d'vfbmouR}"yޫT rcC]J*cca׭/EG=V=7Zf$e pUOCg jƪ+T Pm/jC8 N\,1N \&4 jI5KkӘs|ߖ}Ν;~ӧOwvv~![CCC/\8 / tAd>tXz?6چ? Ju=ƱwSgR`vÓ8\)sL6Yn6'JfO>o"rR68DF[!f tbM|{;kYx>SKKqN[d us&y'qaw^wvv;y117ӖyPR$ٴ̸G.E},m!N7Ty{LiIe](iۤ>2΁H# i7l5J2 mH}r<*^>tn^ :EXMG  {:walj{)$-or'4iqeqz4j/۲ϕ+Wuttg35هΠ 6P ݻcǎ6|J~$mR*3uzPrKPeX?} 攠 8>o2gb7uc LR-x}3sZxᙋ_!FuhKdbq/.'5V }Mᆫ®%5,g4i%@nRFӵfߖ}.^hnnݽ.POQ_c@gw˶m^yM?mpVy=?b}!#fz?(%GO?tⰙf[edL! cS0cbH.i}dfu [%R]tU8-qNL4tj`Z3-䂀U Ddd'8r}0{#^T ţػe\;ݷX mqݐ}W~98̣[̬O'-kjbuƉWNV[ BF|{㳦Y33wT@j'jgQSC8RU 1)aʦ >]9Ϯw$/c#Cj}xFJ]LݺgsOfـ(moG֬y =2}~']Wv%2JdE!|I0aBY`+ ,K*խzw |&>hc@B jچ,/o{b83rdmUP__QQ58G'Nw6U~,-螤uawr*+\DN 95`Z " .qk` yXj{ )ec;pD %|D}Q&%ux\6s`!!NctV~mh]CJ,meeek\e=FJ.<\iW06?훢pixLǒ⏵mx>p@.犥bucpB_=4*X=kYduveY ʯ}DzNaUq <_j,eO7 XCQ Y5,j\!I&K=Mn&f_zNo?\zr,"V깤e{|6<}DRB@aa򪏊4ZG:چoD  @jLD^k!cSs}[)e5}"N3&{-,,ijR:˔ȶ[0ti5T/)(F""6@uԃO(Q[dz/Hi '#C $<9 C4S!W(匡W\澔_@1^bI4XQ'AXhaMQ5u>פeAjsۈ ,jGߢׂo>_m( Hĉvu| pm9 asfOuOhP&LT!͗mK  NamcCEmCUL j* o׈"syx1@ qSmu-=tg_Vwp~+|[z"#( :7j#ew7)Z*= b1Mf*Vz4O1Z@"T>_{[A oK YtB1-X>ӳBhρ?. D|rK@4gSs3~| ~/zUŶb[G`juqJY:|ŒΗhچB2Q^C2rܝ[>1Vw>: * 8Ayc\p8uD!a4>wkjbؙ3fUz!)ظƸ Gp5Ֆ⥻{GLMx@$W0޵n SwRTc咍57d Ciӆ$d/rss_Vep_ni/_?lsE[x6wP}Eo:+j-,LD>T䐽raQIe+;)l!_q~}_0Ob).O@.r(*.d[{X"!#a}AE~`CuV<K j(>,)/=6Qf_?MA43Xv[>m*/P?i,ZhH*gϏlAh̞MqNBp+=oz-sZ% "sgIVgJ?aͦ0UYOoP0jhIs`Y>Zg6*`0/ۍ"91Q| Kb-5D<5s\\\[[Çcbbl68Ugf;~044455ٴiSuM\!c6]'G2'=prnqT!IU^=ѵT }>uXWQ/7)#^=Cs Ɣ\3<\ ƺ{.<xϢ5ĞN:xh o8f@&G1BbQ滒]#\:RJUenflx`<[|L秿MV1-!ҝjajgqt|=;{}|(#EF>%,L$k7DR8ܒy%@YX}=RK8)M?h}gB(&KtZBńc.],%5=.aT)$u,Y"! x捾~VV {&CC ۼy۬!C;Rѧ MHhWE۽Y-:cɩQ-EmEƧ1һv٥m-óLζI͹ǍtkyrΎ6eS@mCJOw\)z8$)sNxa|k䒧 gB%SFf2\WjC]Ym#j[nm%qZ]4z f7gY5GRGA*JtG3wjPK>Tlh= U>2Ր{ uԞ 'cP5,O3)K[(cnX?[MiON%GpZ|O||<˗/9sfhhH*]"}(ttJP]x@M{Fr/i:V6BmC,#USp'7)&B}{6㡶!-ﺁOrmCvgc =lP\A>,rQq!}u`yU ՙ Dgp4g*ƞyPwXV+g6 uNG???2=huar{ A(ET\uic#}~ܲSO瀝KrgXP_wӱtt g}k(dR[q']KVg<.+d"B)-KsOOgPo %q~!ܹsAAA`c``_ς!vlthx088 wp(Qy>h/ ކW׎=x7HV(2B5m8ޟ}ig A}D8Mee)梶!K,v;fe7y N>g#چb*G^]{PKl(̼dt#"(F'PVR!L9*$[g(sL3/x2)s4N Mmmm]X2a鸏P"3o'#(a$=.GbsS[W$Ϗv6= 7I]=KG*IB}}#R*+-o|l +_] ;2bn|*Y!ʕ+_^k cӦMϛ75~B۰居MpRmg"UL.Db}GriR>хUtSH&FG[kRc%o]7OeK<; x`=&s##Ύ47y!@8"t nSQ=fn/zYP+IBy-UVugP855123띢h6]%u)&sn.(d\u*i$aR~ldiǙ{kUH_oq΋dH,Ml@oZ 4:!WoΦS%.PVB!g_^Ld!ĚάdLM۷8$EnKa!a-l 'J---_mӝss׏?ǀxB+Ccg,-dPt^UoG[8#I%}c {:;p.螠e\p_'hqk(ֆڇvwNPyPrP/K{ >We&e3q:;2Kq9l4G`@=C.A&G'GE%tw؉f1D ~HlPGk+(B,,TjV =Y\&0ӡe'AGà MNy"c@s&Hyp5NZ|O~UlR`dwY;gǣOsNY2ZǗHe͏@փ ~>EA>}Qԯxǚaso52NcLpbBEg W}`[~[u/goFy3(W!7_fV 3;; LkD!z}:5b:Ho2]^uo5Rkީ46gubXwaX,~زN \nHy / dcH | ?2\X7=XQ 'ɁY4<{. '4weyIo} E@@@HH\/I< /k xw|WB$O LNOL 4;2qҹΠg%wO]| #i"+O)e,DgחpA=dXd/qli*"*:QF"=ɾw=va3Z( O uv;L@ Z2Tk'%r9}!m/ ]U †b5RuCg-Y*ʒr`1N@=䪬Z|{|O+&&f+(Xݾ*B_?gl !OM#7ڡTAiD@`B `b@w+Q H*1%!w" Jx6xlz~">Γ"5"PP"' Ž]pB>LKmje"2!=}Cu ei٭09K/BڸۅЗjo}@$϶=8o?^rJP$xP0ܞn  $+NX;=2i|``M.;R5$СCFFFG6KeϨA_{#>gXLC0"; a`qo.D!.h2",2 5Qr1ǞS †B|Gɧm 16,v$BpLRt_61D:43lL@`z5 (cM3O`q)e]pEj1'pL{QzLA(-&nL;)'-&)JJg6 Vp 7k RKJ3C_!lkPkQY]/^=zÇt:}(Vcmflllbbb``cǎʪ  ڧ Ebiw'YDpQq9D!?yh/FB|1.'ގ{ߏ8= .$=u2ܵ.f&X=>g$=AP#U x#@ 2O!'R0uq/tLLMY#%s1 R&r?R)$BYק~&zƖײ!&;~o$0 -qΦF؏1 IDAT{v=l*f > G9(c$Chh'p"pTUl@B| 2d*25\g G}uJ.~%^6`+Rz䪄 3c򱢄г~ʿG9@xςaffxUG۰OܦMrrd[7+*K>.X`"6GBeh3gS9TygΟچ"k&`K{Buc>13p(OZSt|d86Dju^:^(7yӵ.]'),߆#B_IY{)eWBi{`o{vݣYgQ0@7O` q.:\)c9K'NuNňJ\C3sS]#WzGDۙDJa==;/v?حPHcl޵}˿ev ;הRuU Tu7ڴ>+k.T .`<%;\T>NhwU76T>\5*چfJ|WBn0]#m L t|,]T']uR4UxL$>;yQ8Ķ/UU%\2G =?D[wi*l}n-aLvΙ=LR@eIb3}vId̩pW0c#cLqZV3"$bpLEaB쯧bF=ql_͇䐓~>>X.a|CĎOv%>y* T6ߚuy8a,1+TRң:k}@=P'M\r}||FGGe2Zb.`Qeoo۷c@vnh/YD;m6<}ß|aU5ʔwFӵzۃ݌ܞ׍1%W.f!{\5Cu T+ SL<8̘+s.~10!ko~i,11y]w{"ȃ;f15ݩgb蓊cw@(s 6]d|lM.}Ƴ Υ 7?mwiG)EWOg.Î o]ӆXkJܡ[ϛA>.Aȥ[sX }J^j+ xS;o5vbڝzU&w|qMfkB yoK |….|JhVVVvuuIuQ`|ߜ6A!A"IL:C,y]5R rjچ,BHKQ zI(oF< #7yԩ񑡡a 7slb3:X4*BPQ0X9(0%0@\'8zY#d.@bcbi>}.O iȡm*ё9j͆aED ɑaXlxtl[A rQKfPdh6}~bppph ‡_Xt2a@ E">2=40 9{8>ʍwj[Ʃe\)*[ >\. `K=M$EY -HbFrN.\${1ю[>]$'G'R/0wC8nK& D$U58~?Krr x1V;u MnN)JS8B0wyHnr' _ Cx s4P$ҦJ#~XFb \<)HmU2P2(EKnùJXTP3hDʪy2>Px\\†=^0/mw>*~{1 $4A"ׅ4AҘx&eL  Y(hȩWK t A۰6QFmAn3Y^x4;2b/YX+#_8 6S ^nT|gk QT*!eOi OiLYLXTs\$SϣLa)*Ҋ 迨:E a哀W5R^H0z5죅Zl 죅Zl 죅Zl 죅Zl 죅Zl 죅Zl 죅Zl 죅Zl 죅Zl 죅Zl 죅Zl #B -P(^ n-YG -RXݘe;IENDB`cryptography-primitives-1.0.0/data/images/README-pictures-2-merged-library.png000066400000000000000000000347321470420105600271630ustar00rootroot00000000000000PNG  IHDResRGBgAMA a pHYsod9oIDATx^ͯeye#F7Oȃx,Dn$ K_t&,Ӗ @Kc\nA ]N?^{解jժUU~{'=3RJ)Nz?^y?~oJ)RDzc٩{(""""'o/S""""ۣvJDDDd)QhDDDDFvJDDDdکp_v\Woδɵڏ᧷~ݝ~{҇/|^~ԝHldx?֓H8m姹+^+. U?>}.ԃ!П W- R >w ?)}ɡ&?ފ<~[8*lɼZEbL)Oݝ?|x_`HkUNŋ]:{剗a돽~ť>$zQ{]ܻ÷ԝlL ׳0j}}۩<;9,D)R|olɼZE>=NF<%v'""[کq{KaMxv__\2.? 7Fkx.?}(v*ԡfw~`Cq3;+y۝썾ዧ\ٚv xoG߷GA5Ni;qpFLָS=}!`]xS?,;9~6d,+.AOg2շoS{C4 -sLz6R)udYDD:[)>j}+J[qe)4^-_$q|5)ךes):VK/ ncE3(N&1;57+}r'Sȳ}j:c("VЇM];a'UKy_q ο &oa#Q!"X;%y'iQv EaR/(-^yĻ_IW#]w@&r-~U_0׌/*V45 ocTޟ% (e'kYvrjA>%0(sVߒ{H}nqE)y.f2)q?>1m<+n욈6v* V\*n_ $7eCp6_>=/ϊȇpky\'q]!Hܘ\ъFx_\Evexn 6q]ߩ0v e''JfbYvrjA9'VR@SFVDSƃQ.Qh; N4K;c) O C翬ID޹8:W\UD1^raһ>@͜(0dV V4R\b9N ƪvm^~eN O;Q'VE<9oyʨ"J20dP i6҇4!KDD=֓\K8|یMHz,%8xQ_D`B*t5*#P1Q.$)NFx,Dy|Sōwf(=C~]=BGv mpuk-:ǃy_q '%O[5Tf8e8p'qlvK/\C0ma8{ũ4a)kx WOoqS<u fDv'#h_NܝadlݠaxE~a(B]$Nd+ŔhD9}}""""mvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDF|CRJ7:-wO')RJMO}nGNuG""""eYvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJD΍/n}yW~?tagccݹNy=JzQv~~BwC._;4H )vJDapQrdOsd9)vJDNnpT bIz N q)U?/\~:ډcj-'^zW *ʩjrJaS4~iVSȥKҭ?rp_FMS"wv #Badh8QK=֓=:\5ʣ>E$xn2<.ůq4Dj^Orƥ+&I;%"`7(Px9k 3 ˒ |+gN2(}Wo-"r6#iDdy}Wq*O(I|5P)異0F?Z';uqZ\h1a^t1Jv BEy]"r#iDdx  Fq 3?w˿fT3)OTNϿ$*E 1I1ʟGUjF-ԿKD2)iS~$"͢NHhDunlAݹHchDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDFvJDDDd)QhDDDDF/=RJ)Xg@;%"""2 픈(ST?TKx.޾UQA[ļÇ,ګ._ 7(*w_8eK 0 B(N.Q{!I]>di={鱢ڟv1ϿLQGO=Y}$B5NYijp!liPw"'ԝ;C ;CMN_u'g_ .Sf2 &I;uhꢝv"کNUG;5SuNE;UT hکhꢝvSNMT]SuNUD;کh&v.کh*jTuSA;UT]SNv:کv.کhZ@;Ujvo/wsOo'wQ'¡l'S7|/~(Ň\DIoIWя)zsϹ:8QZ{k])e;SDZC@ͼ5 OZ@pS1$N?SX&3Á'VNXioT(B*4ܕe5w ;4 vlHع7Q*pp>o?֓J^~S<겔fRɆv /Ȇҝ,,$Gl#ļOˌ؉8BB),0z܈6Kq4y: i̽NQlTr*{^Ws5>J3AFjs "TN('Y魹RP1mr?~rcRo4.`$\0:Qڔ8xI8D)'ML $u;A0L<Q4wSBOM>i9ޗHzĐiipc>!*pkSOs%W: ̱XDA1('P^kxXF|s#BDjB>Ht6p Z`ѥ>Qeq[znBD`jbBAhNy( y9(6耈PB™FDwLnjft Q!F(igvbArKFJSIrY4)1wug/uW %4tY(M>.E Bݟ$4>IH.I$zH G3_{' 9,|5H?cHrLGD };Eq@2Ųa t&A'9t)M,6 "L^8eP9eōū(W 19M=ύxa犱COylI0Lov&mɨAf H~>pܷS+BXA%@BH&h(ųˉf8riKVdsK.›8%\bQ+]AH4 _EXY Jj^~0"nc4U|dp:v,ަ,$B3XO0SMԏӀNj%!)|ԉ~9MVW$xb1Nbea81cD_0`i| q̚NPHt 0UH-Q?oNx0P(ґCyW Շtp5D}:Y4Mf NPRbiZ_IX0$1{f+%+xbp)qOK HWi!} C5$/n瘒:Ub z֝atD #(āGvs,mG<}g8*n)gJ\pRntK X 0d’U-& !!".4CE-б|)#LzAYajd+Z( 23;EY 4 )Bw b*xS#qH>g|TQ>- ̿e2>j@pR$bҨ*%d{,h3*ЇH XNBkq;$qWvz(<9̥(-BJ"Ip5'iMqS-5N;))$ʋWugTUJ@i,p5xƁECg3.,vbtq0Ij"|1/?nD$BT#1ܨ@!ɯύ *u!yo0lcpD2N'r3!dC1 uGTWo^ s3|-tcYBC^)ȄSRxź VĐq/m)Mo1]In _KY `>08@B9tHJ^a0ey|Ak윓)-'Ss6Ss_ .SvJvvj"hꢝv"کNUG;5SuNE;UT hکhꢝvSNMT]SuNUD;کh&v.کh*jTuSA;UT]SNv:کv.کhZ@;UDNE;UTES-vj"hꢝv"کNUG;5SuNE;UT hکhꢝvSNMT]SuNUD;کh&v.کh*jTuSA;UT]SNv:کv.کhZ@;UDNE;UTES-vj"hꢝv"کNUG;5SuNE;UT hکhꢝvSթiHo%la=0rkk⯝v8n`UjکZ8SPd֯;/.UTOj;ӷSmǿY;+w>r(<|Pv~\Y8B'٩K_vMw,'wKmuv* Iøȣ]?tvj? ;uyB`Z>OةDLmBg)žXo~1ǚ'GlCS,F6< '5oSyg[yG;v2|ЁةbZom+S}k$y3,7ffqYY󉒎gIƣGSqp>#\䓚S 0~4ߚC ۩b}";G:DLNuQ2Q:jj~7Hg3 l۩^p8[*y4m#/|g ǿ);5):cx?vࣁ|PvjFoRNў`q&,[)KbD:5vvGǂ SUmXsvj[픇k@{]Ŀ};f'o"> q,tv/O,Ory7ԡ٩О"Z4'|)bL{@vnQk|Pv*f!uX8{vj)K<s>C̺A#&:_Άvh'c75g_AĄߖ|YN⿿ߺj N.ZS3nYOUcv,=;u|ZSgMک&ԙSxؒ~poAi&P;6Ԥ&کIT"vj ۩j۩#SSN .TEiJ;U]کSե(T]iK;ՂSSvS+TuiZvj NUvSu.T NMAکNUvSեjAک)H;U]کNՕvS-i;:a=05N欝[)[)ٜ.,/͚v{}+C%lao7sS# }WlaGBTB']Yح|s5~] sv%laxZ}ة+}Sj 5(Յl [)b d.}qM;u`"{SŃ2]Ȗ?yx>ԏ?S2.dKN6K $ . ugS/Tui*J;UWکN .TEiJ;U]کSե(T]iK;ՂSSvS+TuiZvj NUvSu.T NMAکNUvSեjAکt֯|ޥj5ISmv7k?/ O7ԤpOSxkdw8Snaة,' n"ة0QO>hv |SG.S_= SI_zrծ?brГqy=;Zld#zԔv*l7?e nqAb]h=DLN"ڍDqLPlщrˎY󉒎g9GG;3͞nlnu>`(uȣ|RSv5ۏfr[S.\ j? >ESMGjNq0 19Jımj@٩yG!exaD&"IҹkB*\~nŠ-Q{v4eӈ<#ַS #]aoN@vi;Oq;Rю'a;5]LMT,sD +SNT?8!sc=ȣo~Gs>{O8M٩yH$K h\[S|ZS3+ǞS`q&,[)K5kxRwYED:5vvGewva9+tS}rLyGv*S2;|PNE|fϖeHhVgPY_Yʧ풔oCSG[GzjSvj> Cy|T>zwjN2+gN⛂~2e`ΧCk9[ة 6D 0K}NejNͿʷ ǿ-;87xjv nϛjNqL =g@8fj?SgT٩gjN55kΎSgNgNaKNHC-oԤ&کIT"vj :L;5)5ّNکoZvj NUvSu.T NMAکNUvSեjAک)H;U]کNՕvS-H;5iK;UQکNUvi Tui*J;UWکN .TEiJ;U]کԴJoo]'V]Ԗ*?>B-c57w캣9ة[_^gN]kd~WGOfÇ7?&aة,' ."Pvj?;u vZSt0vjv㲰'd =|ұ'ɻNKsl^6~:hIGD>m;5n^'%Gv~'@,FV.&f>~gw#"5c^x%rˎY󉒎gIƣܹx%꼝efVSq|7^"Ֆ'cWh,",DyVECw$l~Tm8N5<ͣ?ϲr0x"hs,GdzwwZHN3)o'(_T?iB 1G%˃?o$Oj)" L: )Q܎‚c:[ƿe;@J1C ۩"ǭ"AG:\LNu2T:jj~7Hg%yg:߲PNgctiK+'˾lL;ةyH$vOTǥ}MPvj"K;|řSlbg̓}m'W>n>`aOҒΚ۩اv-;̭v5ğo;I۩Lyt?SDc1buCQ$HhVgЬE|;g}y:gʟ~.y閁oCSH.ծ#?"Im):iO=ةR4D0v%GةJKvT<2Qa٩YSO,P:|t#e,m; ~7lv6ǥ?Ԗ~Cvj`iמ.ࣦTǥ=l8fݶ!v3٩3YTcv3u5eΠڴSgJMک33n0%'ނNM$~ٷ#פhvjRGftvjR۩)ooΔvNMP~;ՂSSvS+TuiZvj NUvSu.T NMAکNUvSեjAک)H;U]کNՕvS-H;5iK;UQکNUvi Tui*J;UWکNQ;wNR؅l [))jPڏ[ة/n/E-ak;P[,`,6}uV--슭쐭 DNE;UTES-vj"hꢝv"کNUG;5SuNE;UT hکhꢝvSNMT]SuNUD;کh&v.کh*jTuSA;UT]SNv:کv.کhZ@;UDNE;UTES-/nSg/=.s;u j"څzڅڟv?-=P)ij2 PnSzm2/ګ>.s;[\U{U]_,*w_8e :/UTS{BNHB;%"""2 픈(S""""NB;%"""2 픈(S""""NB;%"""2Nݾ/=SRJ)u"=~[+Lc0IENDB`cryptography-primitives-1.0.0/data/images/README-pictures-3-cpu-specific-libraries.png000066400000000000000000000130111470420105600305660ustar00rootroot00000000000000PNG  IHDR  x)sRGBgAMA a pHYsodIDATx^ϋיe5dd 0(0h qdqLر0 l!HN<_]ԩsNH=B>Gzo_y/=[%ʩg孿1Ojnݿ?Gϓ 6^I ?8SK=;^ x0XXcRc+Zl2`e.Zl2`e.Zl2`o~Qyg35uK:8;UU+7ߨ-Zc|Y%Ts]0]o}ߨ ”/1րqˀV/8HpAvރ.:V̯]>x遲 <{GR { jv0uH};l[ZA)ywgU›#J\%\{ar@k1\2wBR)"$|Ur}Q\BtTNH% Zg I;\ܫViF=#=F)on}r-6y)|)&*K\s ĄzӞip!LDh=L2v5 ƥ|_"yaXKaR4PeX,D_$]}P n'&K'ў^d50,94})ϛl@k(:&!;D ) ࡍL\-l *gL1]hs]%TrLR# 2w@}Qt'J5taF`D Xv.JnUUdKb%-")8eA%`  BhF˥ b9 OjFM> lIq#*sZ\6j4Hmr q+`,k"_Q2ieŻMENyR&5̊򩅤̍ U!eƧ/g)R 0;'"T0bD,jn(]t!(NWe*H3G%38+#]Ċ q L4MHs H_#7I%Aw^StJz>5_mxܳr1`".*3%x=գT/xMerP{@1 sVw#\ ]⧧;kWl==SITJ"ڒx]&`4 )uڈ4F 7*: ()bm$O[L9,gDrox)4r$&U/YW1tȠ3̈́p $g? 3@/\֊鍀29"P6/8zBx]uB0j!0s:b.TL4h3Ej#0kZ0vڗ+k!FlD2%BF(>6 iG(0I3ֽ\/12K^t!e}C)x Wݹӌmfյ"`x,K,hP{^C,CଭQ. a&%UV 1@YYˀ XjˀV_N|*C7ö~^z,va״TGR`6W?߆G8]Ń+Ybht 6.P?o_ +>*E,O]?%~ 2]k妴dXoM"|fğ2 X̾\VxDo Q$*))yB!B9"D$6" Zy7uQec)\~eXv`&zT6껺*.J.I#I,6kBF_~'C%>H=F9fH%H_\:0e\+L) ՀPսU4`q!]Hi͕b-jDeVihκ ї˅SS#)QQU`g* hjg#Ͷ{Ԙ Ȋ.]q6X@@\9FN 9꘹5Xcl*32@E3f %jBսK)2It(3rFXUg `ǗoM Q)Ba܂85ꀩqL7T=*5fZܰʈJMxW!#ЋBW1QrgpzUŷS---*ހ'Kp,A05o6h'f T.-хiL S8 3z`22J̓YɊc׊qeAXQV! eQzUսUjL #Z[*+E#Dj!&/Q_4,c|Tΰ|Eܚ/>bK!n>k,TEd@Vupr~CǦ- k*Lܚ"eŭl@AS`ۢUvuoU\^#x Bx#qB(C7ճ$HG)]9s=r̐DD40ԓ;,U_Sk3"k.@GSOF NЗ#DXlqoJX2CBJ@itի#V$*.xˈ2 cLD$9Ζo4,bUF0)0 EbLa<6c/$BB]5l.|u I_@^z`=SeƮC,ƩN($_ꪯ$Ptuz)D7V-OgLGO$nʀZkڔ eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀ], eRˀm^O*ɀwoo=|u62``}|/^U1!a.*=d6l, X:L6`l2ـd[gSxt|T6t>`g?ݿsV/}ɍ\Ԩ؄iΣ/0/T07 o[ؔ6)0p4/V-<+\ȹSpZm1{€MuO`G !lly?H|A27M&'N E L;`ʙ[G HY=qj7"`%Oi[CQvgkÎ'8=qS1흻uf1HT{' X),)ـeKg, X&t6`lـeKg,'_ްWZt[Zwս&a.X2`Kg, X&t6`lـeK-kwfSƩl6`<}~zkε*O߫dN mlB{4σ#gO>F\Anpض)퉓LaIUY_pV-<+\ȹQGA0Fc' T vp.zFY0H ؤĩ|Xڀ %|ĩ"8ٺ+a*<+C{~AFrlJ0`'Ld, X&t6`lـeKg, X&t+G{E_g,{ULd֥OUhc}xi-xڈ ؆=`UwLgbCl6`l2ـd, X:L6`l2ـd, X:L6`l2ـd, X:L6`ݼRYe~eKg[X7l2Ot6`lـeKg, X&t6`lـeK֥al.Ii]}|/0fg5k]Y:_Փ{C"Z񬬽KxrX۰偾qZLμW1!at6`lـeKg,gt|TBt8`g?ݿsVyBɇ/pxóڀ{aQ`+s(?rإ/ V6iƊG!tUaP>y<+\ȹQ83`v9rVCQs&1.`e<τzFr_S)3zZ*`~`͝`z6{XѠr`= >3J`eg^H1WFxu6ݖl )N h{,KcPFb)1ӒYQ#ZSϔ*APչƘu2*V!ʟ?:8.bѡ`9VfTݜb$\ i$$7gcBH80}uCw@@DToF'-|B`"^#Y=F1*#gb #  h$7x0[K@rXD>p٭n$#3}Xn8;i1"(1#KyN^sXVF9V;EU"tMĕ\h^ alBz/ 6}_xw$(W#xwqM*Q&ZӬ# yBaIZ9%6N!EFJL>0z؍DpzёT7[`<@L[=.^Gh0;ގN+u\GHC (^Bp+ӨA8JCo\IX΁Äa+3Q/2v(!$a1i s+Q#ڛb5U4c }zAE.EW$508ՉKr1qKyC/.^9zbW5I f 84(qb&h0 abV h-$ >Ϯ;'sD{٥v]r1 IwDtzՁ `*nrUaiF"hW1P3`Ru-j$BP(f#z5VbpꀥΣpGQ_eGK6$U3l|I\t Omc\&&#'qBADn\PcVۍh tGt, ۪ +;a`_4.# E!a: (m";ՊD9!Ƀϛ#GbD<fD7/o R6pSV5w6KWp06xb6.#CA_L+t}=uG  <*#.Rp`}9&Ĭ\v U'Lc}/B P %k"n$(1ċyXbUPQFEW(&*Q` (Mt}#&}(͖E 3$fxbwŭ7˙Js^LmSTw Eac!jvqTL78ԃEb6DhLD=(FEcJ+N?E'ɳxx5 ԠC/mVhbXѻo8x%~a 3<(G0`cx   !5+5AaJg:#AXjEy{(/dM`$M>LE/Nh$$ I\3HOo}H+8Aw~u:FWbZ(y~э(B UcV]ڏˮZm0jE >h(G;Q(t EUValF4[EyMt`5\_/ab+Lc)Ep> 1xr+!)F/٧W\Τ':`,e])4a>!~10GѢL$+^0+ Պ՚–PXP݄bZImjj}kQ`-. ub$"fԃaXMܭa bZ+և(h$4A# x /b+tA!XR &P-iP uB&DǏigŴZHqZ$<-]ĭ0!Wߘe6 !bFBI48@ʿe_G_cT L /IJp&dB,҃Fբ4@B\] mÄ UVb:vh$4A#٥+!׭Q X@7]^[zIt3"F#Q#QW@"/U~:z9dGb,dvq2HmQ삱E7HFBIɪkYJ &"Qhoj$bLB#٨ſjFWY/c$ƽ#jXEU=u (9aH!B#YU&f~IL«WQ7:u @,R蛄3`%X'F#ۋmE'q `KP٦;Xn Qcg0FCk%FBIjJۀ$)zۡ&_=7<`ctΞ[ P_Q.% 1buةPu}`[ԌwUZQ\9B!$F]4 FBIj[;/03*Z,44ڮ+]Ù4..1L*:Qy !$Yh$i_^x[]m)Hm FBIIzPr !$Yh$kx]WL@e-", DaozS/_q/q@$m$oeT- z B[=lA kHbT=4IÓ~I(pDFNN߸\"i>.B'iFBII:Y~keʧdl8x>ceh$d~$ɟ7lI2H!B#I?|uBxv]I~O1H!B#I?_vrQݭń,",45!+Nb?;2ѥFBIɚ䕋 u?a~&BFV$ G/杭,4"+Do~&3BFw$a$Gj[ h$d! _:G?|CF^eb>$-ӠBF~h$ӈH 0@h$kI6 N70 jg+,[\$&h$i7RZ{ h$4A#Iˏrt O늜!Ct#YX-zaq mog0H/܀_3&g3Oݪ+g>wXΐ$n$8gaDIzଢ଼ W*9+rU<}yWHD1,28 0r̷U;ܠ;WYf#QXqa $m3K{YaF!l?rg h$ ä,4 J֢&9U#n#S 0$C[\Ag,g< v]HI04L]Wq߷_ΐF0Ld2.>QWRoeZWd+>3C~9Rg_ip֒qYHI04Ls7L 6< s`Ϫ?ǽr&u,?~.+HmHI04LO%313<9765?EҢ[0bKuojbM*1 Wja$rӍ>. ؗ(=h$ $I?7& vp_4 0]R}FbZl"tkI *1 >RCl+8Rۊ1$s 0 FY?6+gJb_;7oU~xB卅 (`*<4ЍYWgjr&: LpF0{h$*xO>NBrn "01^f_qBh&g4#yh$iOoz(L8r{5]3{:Kf5C#puo4uș0J!-t5@Fڰy^e}8}el.ngI2ճ~̠Y]dl90o㏽<ܚ:#E7X& 7LB#p&f^S0]SnD Xx2Ah(\~>Bf)F`$AXQ1uj ;N`w!l0%b6Hh=(l2auX+^gnpvQ@]pB$L_րt~H,y (KTլvaV34̇_x:ș,# %#j3: (MWk/X A$U0e `C`=h\*$Մm VRmp֪V6*7BYH2GT=3Y6$grU1mA7+&>ЩcrTJ,kFnO`r#)Q = sFS qvjŬKW0IC#$`~Htr FB-Z9Bo#GצFn@c4D `[:bO#a04̇=1ȥ6*IʵhZ c07wa62JH>TUMͺqjGVyhHT[qD zd>DNyO vRխjnC%LöVsjCZԀC( ,]!1jAی$HB~"$ d8i-5I:0I+j ".JR:@EvfXNc׷Z\ٯ5m ֮C4 ʡd8w'6Jx i-qG8uH^(D•R~ܸ2*Fpl@-ə>oݑF¤m{LE zd8o]qKx_{KPvtKΐF¬1v5 $oGH*?LC2 0^ $9U\wcgF0Ld2 K}Zz_q"HI04L7[6: / rd4a $M$K?*?ge4a $cA7*<~IŽEu^@@h$ $IK6c:@]̄F0Ld,_^Hw|IB#a&H2=co&g<3*9 H@#a&H2H4df+I&A#a&H2pOo!aC#@"\yW6*#$á0 `h$ #^70 `h$7ʛ]2T pr^ΓF0Ld'j:]-gDYc7s 0 F9<Α=c[;W|s 0 F9T̓ xHI04BH 0 `h$B#a&H!)FĝGs]Gbzh$B#a td񓞱9 _Y4>*4BH 0iFGbA;F !$HB#Th$A#a SB/4OFBI4&H< !$mHB#Th$A#a SB/4OFBI4&HҞyfa\,57Mc[%4BHڠ0%FR=-?j]o^ӧ=Fa\j0 ^*) P4:d*`ߩjm_G%B[Y.xPvp]D0! lZTm_14BHڠ0eH3AA|#yǿ43B4qi͌f!q4BHڠ0%N#z9Zn50޵X~`meu%@5B ycMEK[l ]Wpu{ahwczbMl$xhh, i$^C#!  _`$#3F>V'*zU@)-""ZB`m"hˠn!JdҐ,Sr<툤F$#˅լ6E5gFBI4&\hk~;a[U~T Eь$ԡp}@;sm0zlkT#P*Fڍ$T.o ; 0Re9rNH2Oսaod-4&E6nv5wFM'n{[X!PU#[I(B`[*KHݹ5Hj1j$.d1%4 gM0?@qZh$L(x9FTP3`wO&bMBhHȫ.l7צmenZU#B(?:aC#" PNe-4&ljuf$>R3}Ap) tAZ$Z3ԫXYV? 6Ie*QCD""_kӎ:th*hMЊb $CPNe-4&l:[:həoLofKV$H2 TB#aO7־{i$1\A#7jqF!HHT( %ښ:Ҹn4k:F¤54 FB?@9HH=вpCx@#Sd4ʩF„x˻':jB[3Sd4ʩF„M~ QH#Th$Dr*k0ּtQH<I@#!QZh$K#F9B#Th$B}trʩF˜1n1#Z|BޛdqTx1!Vc/yY$š4C/ c;3sS W29c|Th$i#.#W~,oGjqɶ(Ac|xd}SxXf>8p9H[>0HFF28JL\8}-u.h$L(}  IڈHQr3O`B.XeFzD0//@G %F9Ä $mn$X oTg`-&6?ɲ\3brs@%5F"u^[AmW;cLEa٭|/VfԉfET{/aD ^>W+5`Z(|ȩFl+>x-n%}*ޅm1:YbBFƉl,yB 5Yc[Uj1^s]Rםe/+ 4]\)ASTB#aE`$Fa6JHFF]P4c 7EvgQn7QNkF6JPt1;5,Ӫڙqq 9ܩhL_cผ扃ؑP1!y) #|$$4,@.QW݊Ÿ"^TjeQ_TwF"*0)P/6A|BOVCsV\/LH9Hnx*4L YZNo|W^Cq (74J`EEDFl+QF̹vWik|FʩF~ Sd851mumc[D$f$BI@#n~SdQDӊolh5^1ř̚FJK,V@aQW_KrIx4<}Fj$Vg y stOb!/p:[E׻k-fONx_D" a9=<~BD7T,;UsHoHF*91# >i$IT#߬? QD4Ν*=`C  ɹF6Rf$3+記L #{#*4O%u^wyuo]N*H#Eprvv 1uzѢj]3膁 bZTjb&b0!7 ΝZx7vq}Bd I3q.c*zN'}DFD,"F;~Pm{+ns^!Qp=.^9"tXGu-,'|"5d#ս/BzU8xX`%;θlrxX KPGB>TwlkTm+i2Sr*kf"ݣ7Hh$JHww m;<==}yw/uy!y$^ 8}MSY $7|B[Q.nS_h$JR{0 um'<ӴkiiI\đg4Sr*kf\{c7|Uq>#Q=ʻ'wT67F⩄3HD~_c_}:55cJIHHTNɩFq" >_k0dۃ3\ O lD|vI!%|#5Nܪd;%InE}Fqt>HF՝?`|B"nRRJI,HHNZNe-4܌ыu߼镽 /l+ 𪍧H&ow?Z`e 4tr*kf^$G:j|om\~KuDu$IӧM1q5Frv}_?r%q/]~ݻ>]YYDFBZNe-4tYW:K&E MD"on)He7ye5LYQ%#TdK<͟˻w+**JKKΎ.5>>k7@#!QA-I^ӧ=Fa\j0 ^*) P4:dvem;5< DYh+=ewH.hvahU^$#U>,za[ߌ5uTyH_/dށ|}g>?mC˗/ ZO[YYn"C#!QA-#AԈG1wKC=Z`,D>͟HlI^D}%/5l*nĴA#qH<FS[_kgog~uݖ&):{^ nHHTA˩%Fb%V\_jk A4# &l ]WpupFxm|fED~󍍍SSSK7ύ8/QNe-k6F:`ы;smemh EpajjUe5Hep ; 0Re9r3V~/K֗uw*Hdh$JFz?ɓ'KKKm#9qҥKmmmp TֲWmZǮ*ָRPStx# Ah>:"HBG\vkU`#P*ks!u[^L E>-H<Č@/ Pu':tff&Dr*kY;[RȃX}K KE tXAGUVm`#T$!q=PDD3-#W ֦uаU КRE[J[vT6m*n߸B#T6_/--pN;wgrrDFB?@9Ho] %xBlv&yDc=ͥvzΣ `fq b$+++3\DdҒk׮uvv]h$᠑PNe-4$ Wi_H[:*1ܲz0jx0QDMRXc{O:u;wHHT(51fգɯzi)ݕ`b1HFop7vU]|}ddd~~Dr*kft#m}@cph\:)5aHT#0kwݿn'N\x͛|NZdh$$*SY $7 Rm+xK~oSTb|g<@$F#i7\DǏpBKKI8x`mLÆY~?@9Hr3 omtvk$]痗Ϸc/Lo4n ;vL0$.^s{^.S Ina$M-DD_~u)0: =z>|$I8"?Yx'ʟo,SY $74ĸUݕF$o$Cs(#ijj룑D Ywx> 򽷃Er*kI\7\/ {4ak$܍#qJ#N7yED^ʻzȑFId:K3I(dbkjaɜ1#yGeQ4d;ka$eee HI(ጄɖl8I8z{ ;IH"Yϟoer#B#Uv{ ,;IHƦ Dgi~i4PYρl׀ݣt!.w<~XHc{Yڳg='1~ X j$a# Yθ%K ti 1eF=I~s5nbZͩFދR`$Ct\M%cU (C誵:~xckG B[Y/#Fb?{zF#qFWW${,$*9zjrq{!44N]FqX A|I :Ha;7`BsH`$bp *B۾\/-@t`[֎1ph)gB$o$O<1>B*H_##ٳtA{k:/<`ؾMޙ[jSf`{*1۸HьD׺ +)._%Ơ>jA6viH)9@40I<î!B¡lל#)1+ ѣ4$o$g F DAFg U?0+71 uPyP#o0}Sg0Q )kv{TUM3or -*Rh$!h$WK[.o>HH$ع:IC !vuf yzVYeWp6ұNhl9B+$HlKv$ "GΪɡCJJJ]F#LF"Aڵ隐F X+oF>C3Q l2,@`580KA #qQ 7 V6 ZDF $-zjc/w Eb@mDlBo\A f;DӮF2c1GVH:,s|||iiFʪ ykVm,TuF^U-A{a$Rea==M[wXm_I(4x[Gj$FحCьD߿] UA!h*$l6j$T=zگmhj60PmAnVHv8v̙ZIdRe$a>mX`Bkl BPABJg` #`*7@>,*pҌжjo#o.`k7kGчg<IR{H:Xd:hF 4h.^<%HK? vzk-VkkX"эB0DD3,"W jG:.lj&!1IRsVaL'1"p4783B# A#H6n)* I:oagaeۯYN̪>}FԜA\ӓdc{ 44$[\WHQ6bA#I vH t a${$yduuu[[Ça$$Ҟ $?^큖4FŕF❤H: yǏjmm{1 Ҟ $?̾>(4B#NRb$/5:">fffeeFgiφFuf`&=iF$o$0 xGo."e_iYYY}}}OO$=I~ֽ:6^er>x7ǏT7\DWm³gC# ϺgR{oO-=d<@$v#yɥ|gG]3W\ѿn 73tD_jii$Nxlh$!Yr .WƃH7`[I'''y Ҟ $?^c7.$#B<n 9ps.֑y~؀giφFu߼W~;I6z8+w;755o,HBμ{y+;IFg Q˵w0=I~֙Oqx')4_^/,I$Ҟ $? _;vv+;I-۾<ۼW|۷o/ڍgiφFuoqF❤H@ŭ}Z>0LoT}U1qRxlh$!YgDJ|me m=x$4}m_Ξvɮ枞J YCy9q*44F-?2M#HRk$-..B5>:37"ϫ+MLL()=%>U}OUJ_l.m~41)D_j³HK[Y㳚(h$L"IHTHD]**!WЃ%@k"N#7 *wƔ3w )ihщ9b?oQ~s,--rrIMxFnl8z* g5KC#QHD蝺i}H] UA!h*$l6 ]p }[{=n6^.l4a$ۂݎ1CJڊ* |uޭQCMrNxn~BǷw, DA#aI2Fi:rI\I&.^<_"K܍$6`n:^[S;(T$T"zՓEjYCDžBmΨg)YXXooo~#5z{^I݋-C̷i6vz,]{ϿnFW@fCV0IHy;ZEYkb# F{|__tsTNch-YR_ͪLc\Wndt8dI U3}AXH?Hz_azzzddƍJ/+7J m;ǯ4w˛a!(@6(`ovJ~!;[9(~wg0Y1f 6#蘡`W_}Ux/(%yp˧N\wOapdWԯDꛚO|Yz`eݮz[V˯"9HDB#Ni$.Tf(Kz{{\rl%;;pYw'o]XGi0`J@s/d`羣_Qx,]T߼(HBHH4 @~W ONNwwwߺu^RRV.S)j?Rۋ}Hɇ{`'?ܹuҐ#=~y>-%w.H&Б G $qH,///,,LLL+5>ٳg=Ɂ οĦ-/l5_;%RH`Zh$ $Bxɓ'OVVVu5{͛7_~ʕrɩSN<N]U_6,̵|W_/ MwR\i8"9HI0kh$5dbP___gg۷[ZZa'W^(+++))r/[6~QGɺ =QϿ꾿yOÓ-qӊH`Zh$ $57&`oo/Ν;7olnnv .?ܹsQN8qر>_yO_fe*/]5T`w?`_l-QhD.HH`Zh$ $1&^%dttthhGJ[[[KKKSSS]]pK.UUUq3g(M9~ѣG9+xI ݧϫ>{[quOs40IyK9Z?|׳74aFPjⴓ9qeG@___ww7ݻ 7nܨr S)))9}tqq1dɓW;&pߡ!.B_:֮Jb6"Wy>o߾C}ZoG;BFc$hg9v÷=ꎑTO7Uw5VHih$ 0 &Di'eqqq~~~vvvzzZ8Ç{{{:::ܹMyojjrڵ˗.\PQQ!ܹsZΜ9#Ee0@F|gGo"{=pU.?Б~/G?ˁ[[hwՇLՋzF"0 `Ht%("Q єJgg{477CY녵 qrp/RLyy7`k^~"GxPɉ?|Gn[KqF #1^ wFbEr*kH^>NC 0v7'PtG14E(Sy葐W WXܽ{W˭[/7oބ~=ʋ];O&\.rEj+Yy7oVcR7T0 ÄK6i()YYXXP233LLL(q2<<,e``@ EqE5{>wܹsׯ_oii`󆻗"8j=$=ںKy R=VNh:v=44abOn+RRHI #}@Y%.](vݳr=z/7"7nhmm耋rz"m][50#~eSqvVȻ'[Y#%/~&C# A#a&䰑D@zT]Ȋpw7|vŧ > )..vOHggr Y=$=4W\790w{d6+)iFa&Bsj$q!E/>W^---=uԙ3g/_\WWWp} #);Tプu4#"}XB#QpmZ0 ÄKx4BI=4p@2gggOf{0\S>("3O# ߏ80 Ä +@#g&YZZoOOOͩk4cϻsH;u_>k(oi6_pWَ~hzh$&/0Ld28.vh$:MǏQ(E"soS mK[^*hx!SV2:?FOC3B#l,yV9a"V<}ءD!DY yHm8lMh,YϒߎVOq3bl뚜^xY*4k0 96ӇIxH"bs|z|ܻ'[h$NHNe-эqg0I$׌ea iHYH~FTB#a&šT{39n HZ5L51)mn`Z1@[a}76N4#Bg֊aH"[G7zF"HH}`{OIId]UU'X$ 0IFi$>FTB#a&HҀ7ɯk"4'X$ 0IFFm|tS 0I [w_Zh$6bWԺՔdpUlÔX:2 E3[Ujmi :|zp HҀǍ0 5BTfM<#AɞZH$ x22՜CaOX;՚m2LFFh$0 f;Kr54kq:4]V"{q`}0wy2QuZ"@,-&C#I4D |/4Ks541~ܵ6zJ,•hwQ8~%JGK& aW„܎J`(E. ~:v!a2/44@#yu_{H HNe-d$XMvƖ7Ly)zl+^\A`:\Vy6l{jB(U`И6{=dNh$iFroιᑩ!Hl$f$5` WnM  v*G=D^\:xQ,жiðah,Du\AY n:1LfFV-4h@(t!PPֽ}:ThJi<y=J"Lkj4r Mk\M5K(Hl׍FD8Kہ_/rΈH^Dk:F)w*5Lըz\ LiF]L#K[ez\j.7wAkU~'B#lh$6qg%5F_kb h."cv+tVC, q-V,]ejeMj]G7mc6HgC#;㚺NBJDvMY/,q4/^+FW-@ 'wickv (Ue5#QThڑB7S&B#lh$6qgtlS2ׁ{:F"EV9VTHV!v8c9*PHJ01&d}Кh,l[cHlH=n i# *B3l٢BRPSYE xD. ΢#"!Rc5H6X5$L dmIH:z(|s?2;rb7.wn߾{gkn}sO훁]| *eb A`ؠ0"u .HbP&Pڝ/ C @5V+kGa&L(#""_ o- Vp[h$kKFroB#,Ч!WrHj P_j{jv{{UsQB#A#aqRFwœf!6;I44%i#{@Mׄ4F1!epOma_`UMgZk58 6G8GoT~Vlh\S-44iu0tQi7}A Ss4eU$p#CP3֕yᦦVAo- E@;5fEXmOglC_IHlH#כԑH dmI= 45Fj kP$R Cp*V uLR{ .lHGRB`B#A#aT6[%hx'4%Y# HPD4հ5DRD#Nh$kKjd*t5Dΐ&e`444oy@FH֖ ǝA .BwB#Y[h$ ?LSwˆ F!B#Nh$k ijǝ@JBFHgC#sWpټ^#(?%6>"44@#lh$6qrnX7 0$ H< ~ܽwO4 Fh$ ?MϷz èHijݛt cFh$ ?̖ҦrQgrgn!6>*44@#lh$6q`.5o>d_^>6^er>x}gC#=Ǝ(߯H#Ah$iFHll*tFFHgC#oHɚC#lh$6qNƭ߯i$4FH< ~ܽ wB#Ysh$ ?ISw[Gx`<;H]AA#IgC#G~ÅFb$?=Kͱ=gZ{{FWVVxIŭ}D\HH< ~ܽ?.4$ty1?w?[`x|\˞_N<ːhHL?ǟLOB#A#$4$a!H/WVVYzTؠ|_wHYgG|Z?<6;;+R 4#4'X$דHFrA!'_4^o,--8HH`Zh$N2?K#N"Dc$*/\XXDFbFTB#t ܥ_]x%dxepܿPؓ,SY Ļ~!"/5RAHFru_|`|BbϿYw,//SJ\wFbEr*kx4-mȡх fwH&:7^/w_}~}^|kddR ]񱡑`Zh$M?߿ʖRkdKFiS>aLx #q=ӿ·~^,**:qđcǷ8ϣ;;;3U?0>YFu:" ]Y^p;`$Ó-]E<͟˻ RGtRUUUeeeyyyii]S"l0/, DJ#^x !=Bb_M,P_x'.o߾߼}nݺoܸqs_Xu'yֻV?-[˻jFH-=,5V{wx}W}Qh{`˥v).`'jwHz7 RK>:Ç{{{߿'G{5ީ8vjjjqq;R2H\q#y}Ep\dxjqza8d IHbj|jpwH_+~R_տ=5ѵ8}ÆD,1\ׇnhƒ0/FRV3H4OuFFۍCVؠdi\:mPE_XC#N89[ktg]YYR@P&'j?;TGl]KtOӡbs%F?3p~b^K]cS!c飹!/WD͍HlH4N#9v×_7 D#4$V# & g@tgw޽{_#r*l9Z=z,gx_yޡЯ l>azHǿ}M\yFbF1$.Ө[Vc ;Hk6Gt/K$1]'_骹=?: ;Ao $}ƃfF6Qxx}G#)o9 I0Mō6UE_~چF$o$}.--@J:::3[7WgWw+G14E sٸm@ۜF""uY^#k7gB#A#Fs7{C#NRe$CJС %>T|ZuN2o S\;YAYG g$"YrA/1#Fm=(Bh$6h$Ye$_YU|.C&q]qN VR1If$@ E"TԜuiX@:0"~GyIߺX{sH|n[5>i|c%{hC?4=44Ґ30Y29gM7MW^#p7{|g<@%^#=1=hwwwKKKŚM~gG 3F /;Դ[N=#ꥂ2tdK8)H<}oZTR\htU%zZ4$DYh+=mBF7D% r0KsW'Nbf/Ğ(){Q__߭[nܸq/F}"  RřѾ;w455K.\PZZ?|y>p?K~u۫_ȝ~ӊ$T֒iF #2Jp5Ē ;Zn^n!JdҐ,S%.k%Wz)`u8wY |7//O,om|D1u~~~rrÇׯ_t%%%ş>_>bw?-q_7?]x2G:iEh$NHNe-7Fzŋp誅tؑ0zܯ(Ue5#q;д#n$栈QjM 7r`$7K#%###\vE_̋x~·;dkG&rAJ[^ ɩ%KD[+`$bA; XyG%hvc'N#+ꌑn׼uz*k_C#NVHKxG&~vr…ϗBPO< G9zДO/ʐ/W5볽?ٽ7za]_t_o9Hcn ڞӊ_{w{pfoh$Ljc٢w-TE&bͺ(n$rQpn>:"v'N#`40-3x/ϺgT!w#^8777555yaww{`'---7nܨrJuu5 RRRria*'N;v rȑ =lS,E䷻Ή*a3ғ>]wރ~ZoG;BFc$hg[p6+Sͫ;FR=TiX!2֠db}1kai ý_  :beZ] $ c$BD=k>ոK p1H_ ݦ=j6IbB#Ni$%O!,d~~~fffrrR`___WWWGGǝ;w(>rڵʥK.^XUUUYYyyʹs,gϞ9sF (**cf<q;/l_~~}S#?/_W?̗7N8SAD^ ޯ9Ջ DFyG.hb8#NuC>𧾣饂meL#No$xP1jdvvvzzZ0Д{T!+~X__e~:rU˗/0!1… P ،f#c$ GQny @b L ;vn?쿭m/ݶr㒍wg/5 Lܧ`Zh$uI2B[.90Ru4!wVFۉ; efffjj 2>>.LeddDJ𕞞(ݻw.or3$477Ce@Sh hhhIOv}Xw^םׯpZUy˻}QՐMōi$X$2&эqJ,C&Pww F#(AEhb%+bLE XJ_PxRЧ!̦[M2ܿn@!絼*1.~ E%w.)ɥ'?K?ݯ3wSG]$KcqCk!;4#1z@8BZ] Befff!7 /m_qvo.)?m=2} ̏-T, [H y5$Kc zCkZUsqR,N8M@\j)7u{/W׭3%?LIh_4HI(LսO}= 9x`aa).=~e )p=43C&ɩ9^k=U8H.FbF{a p)7_ U4KLz,%]$'S~XNUkY`ӶUe{Rq[3k$q!%ŤH7U׵]zٳ'O,**Rh._plm;Gէza$}j|𒷎tD$Kj$HJ\W:"JPZFK'~{oгa%5hD?hM8mM5J4HlI񈑬 'ONutt]xJ]icpls #=ј'eoh$6h$YpF %FHh* պ֗FhFL#܅ uoNAkC"I'!F\&&&z{{~ݻwŸHнM%l ʝߝliC\C#A#҄3$JDU^k]Z1۸Hzb]DDV6l D= 6}T[ ֶ%F[͘M*4U2;; tvvvuu=x@]|Aw 䞑ׇLQy-4'CI&wxTbcغ)7#iUXBsAŵ'^W0#L41[.d6ba5#..8*4mEa9(ȄC#YUąř1;==ьn>~1#yh|~Vhcb+g?Lv%Jh;f3nwd#"`Vu3U(WDU6.`c$9_Bh"soSظp$Z׀ͣOs\ndn|84#44\M7Iv>"A?lǻX"p4YH$VH ]pQH[Sj#&/ [K=e$m#M-[J^PT|䚼ױ; +ƶٛB#A#{C2+ ^GN7jAdGP[k:u'4(#""F4Xs@_"zqF YSF20tӅ6kO*YZD8"9HxP'Fh;raG$5#i$]T/FTB#aZm2ch$DNH֖T{39n HZ5L519J#1"9H'$#aV=4%%F21ׅ>3>7֊aH"[G7 D@#a@Gǯch$ dmId]J|U'X$ #|C#Nh$k7c=)H`Zh$L(GwB#Y[i$H&H`Zh$L(PB#Nh$kg$0 ɩF %4FxHac{:ٛC4@#a~C ?-&'7FxH:[^?hEDn=4-fo&4@#abqCkȄFH Ϻ]6#)o6>>E^@#ab~CɅf[h$ dm 8uFB#4oFPB<i$ dm\Wph$X$ k:[~/tg 4FHu_*h`Zh$LL7.n*nL7=3 8i,/f;:ɄFH=swhfoh$ =uA5i|4׺$Ӟ~0XvN}(B萭yhcRP,VVz*봭)A- nzm%B#126sgzafoh$ kJ|>KVHPtK4?HyЅz%56EXNpS 2hvdh$k  ɩFKfSn$աڻR 3تĿ$>] 1N5# &E㺂:L=}zPڬ(HhCmp-O*4FbFTB#a𒩅׊~n$Vzb]DDV6l` ]D, }q~P"bAʄҐ,S%.k%Wn1xh$k  ɩF$٥Ep 1# u+ f T# ZKPNp(XXǾ@*4mEa9(B#Y[h$F`$ˏ7͍ xErD0ڨ8`;o+3UUVͫ?"*P]HJ01o@#122uszazja.720hq"44&\Rl$zn~ZvD뉃~ZߵPȒF]%B/\FGDB;u1'B#lh$6qg%F(%Acpyjb}1k!%FjLVZhkL'7^.<)HgC#;.3wޑ s=$HgC#;.5}AXHTQi$k ijǝ L#aV74FHl΄ ;-4φFbw&\h$ dmx643B#Nh$kK\F>+y?/rHwB#Y[2&C#4FFH B#4FFH B#4Fdqebglm|Dh$i Yzaevcɳ[j^?~,{;X* xܝb!;э`qa o^;H!H:V3N: 0Δ*'4BHb2V?0 .d !$q !$ !$MH!B !$MH!Hs 0{G?Y' 7jrBg$50 N#n#V3b'n#?B7z~B"@#! !$h$@#!$h$dBR 4BHjBFBI 4BH2H!FBI !$5H!@#! !$h$@#!$h$dBR 4BHjBFBI 4BH2H!FBI !$5H!@#! !$h$@#!$h$dBR 4BHjBFBbbozS/_q/q@ 4m +K+A#!$HHTh$dBR 4BHjBFBI 4BH2H!FBI !$5H!@#! !$h$@#!$h$dBR 4BHjBFBI 4BH2g$6n^0J' 7h$g$3?03uH!H!$ah$H!iFB&h$H!iFB&h$H#y9q`YlC!Eaf5„9wIENDB`cryptography-primitives-1.0.0/data/images/README-pictures-4b-1CPU.png000066400000000000000000001062061470420105600251260ustar00rootroot00000000000000PNG  IHDRsRGBgAMA a pHYsodIDATx^WW 4Ys9gNo3xvuWRewUꪲݶ]m[.d/% ٺXB7!!!n H@ @B!@;_cθI&2~z+;vd&>#2!JXfX֘BHȆg_x`0/Rz!aƒɁ?yAʄL49|y*BB BP>!BP>!BP>!BP>!BP>!BP>!BP>!BP>!Bzcjnn,t0'<(!9@7)hReٞE7 |!/|oIGd oH=bCj7*1*~K+~bozwiat{a*'߰}< YP>!BQ@TmY "_Fz+-DH,ヾ܆3E4֟Q*ă@bVĠO=B.T!`=#m0~6;|̀AȁL#MDFIJ>ikkY_xjnk| cUv!s-ɶ ` (!Q;"jEC&IOxkzji򁿪l7։Uf hO`Ao !BB!sHEr> LgGGU' F#Xy:U0@=H1[&p*q6)3pa{>f' :LQm`V!C ǣ襦h MG)BAd8ϵpd/|DƲ#$6ȣhTrg ҡ[=E\Hve_,yAz#>/ 34Q8d=Ȃ,4_$rO7BX%ff,-.C|sAYIxMR>!`@ReWd}y+q4Qtm;EBFDȲ'zs|@XP7։qbGHH5j]tRҳ Y-9r<Ŝqw2jF.AW, `C3$>21`2*s.8G'W8%BR7!$t) HI IB@ N*^jJ"P>GRSn(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(AY!(!Q@[ "鹖E{Cu|l`0~sG;ٵ!0uщ΁,Aev4XK|bz_Shȱ021e,~4wD?eb0#/cWUǂz9R$! ~!B%Ⱦo>50ʡ{ )³/ >IcX@H%! 䅭GU9=HcsA 5HUW̖Gʑ_UO3Ǜzdw$:ϩ4hQo90Y&%-StVq_AP>!B ЎԳm[dA$Q|tr|`I@4||UȂH{R*UdGwo3i U6["\xO8!n@e1U3Ñ{h6C6|@˰AgVa{eGalSMX%O@(T|;\;q*U!5D>nkn`A\yX!V`Y6b f dsOpl.Vr(V  beHX .BQR2BM{"|BRuk`l*+24d%cܔ |DzVM3u'xgop|_||p\VA UbllCGPv1;>=(Lds9]ԏXP>!Bx81+L5ۊnVԐiu;Oʔ> Qc,ʙjՋgmZf $|͞yn@^$dL$2`p\C&~&8(<,PO~xdy%ٜAyP>ɮmVxzſI56ͬzb!'`}bH4y bY)ҹH9*IJ]aHڑeYCeIa2pol",,o8t8vtJ?,`S6|B2!|cMs⭝g$"I5O4B||@AjdYlZį)DA!=TezFQ-efJꁡLoluA+TbF>/ﰘ9 |RaUi952(hp3#-OV%sfF?U<>n,Ǟ.(T |7E_0UYMm;wIyP>!ZkxA :%KUV V>8B~-YBHS>qVfhsq8K*ᔏ4ڥsU|BR%~U_+ud`tw rM\ 6]u|a㗯br#xj _V(T |+]³/@%` ,asH6ѿHbÑ)[ XyK10//+BHP>ſI4 ȗAYBf]| o8t<$2=AIG຦!IqSMXe̎;crYX <@Z)˨AΊkMD5Ǹd[i(z${‚b8X*pW~x7H3l#Âe D,]!kǏ6?SrtկT!} "!;\{}yNf>iU='V! ,#׊%&zsOei9 zCvG`kP~ ks2ZI0fnGCh610':fZ!$U&ȇ*1+R#b͍,[HĂɚP,"&,l\1@tYVIΖrd Vcb*yL`-'`G39xW!$U&]c뿭RL? Ԉ~O!2=Va|n'r8|U&~ftYҳqD_1w!GWY61f2]*P>" gG5$lM>BY'#>$yRN" IWUԅY V/6#Cc-%1|$ig%#[-}zP_rIr|`08.Q&&ҌA Vq7 a#l_Zmɳ"^:w@N5$XLl<^N m)˺gt@=]G[| 6:dYWÂ=ack>ܛ`fϔfYÉrFB2~BE^Dt4V$&! A` R# zE2Ws[A*3BUJ!$@-V=f ĽSYE!d 6 IĿ'x4(T ||{CU1~UvtRHbP>*!UNŦAU iKA*?jAI !fn,G2!$UB(Zk JYBHP>#uL*!k-uL*ᔏ/NF"wT![d P>!NHGVX|vek@ J8 , $*_-dת!|]z6`8o ᔏo<3%|v`07sf՛?'G'_LB gH$*"'`ݶnp$ Bd|2[d0B +'HRP>!+DFx'{X r$E7a0 Tod|kc ,F м3'fT!N{$)(T| ]_zc X90 i"{ mƯ0;*3~UJ'd+^UHl<^W뿹grŵ.,g6BHP>{R?4;|),詎ޡUtgyC;t"XvL9@PН,_eZ0Y P~ݚE72N-^UsG2!$U(߹{]?z! c$cKo/rNU4xM^~\&zu;O"٩v,`>=zi]uETڣ /RpAw 2 ɤ_MB/m2 ,Kf*BHP>U! ʐ YF^4\t50=bi8)NzA%PDăn_(y5(]a$=tĜh*,ݢEd0iԿԜzSzWv7Ⱥny,^ВeYlv*G` _pRnȗ֪Pm߀<>}58 !CQ>49/ +o T!yt RoJ'7rO86A W@ĔndCs)w\庫 ^bYl)IJރ񿱿ㇸ@_tTS>UA>eEVh@>16؃7/ Ys ՝yTh؈]Kwco.(,*k V$˰(N~ o ) <#U묌e-& *$xfK`, X_eP:T"^ς?J/X U\  @DfzF%t˟S+ll[wz΋|J.Un 80Py1B/? \%HDNE֓H$ZѹfP RyZ`2ile:qk 4J=6S~b84 /eoh,{D؋!LZ[$'/AIǢNVn>E*LAIǢp#_=yyTS*LAIǢk/m+Ox oyO2!$U(h;ٵ*8IԉĿSsuBU *D?:WeZWU>T[f<BHP>䃃:U!$xK#|BR $b`s,Y%P>!BH^v `U43!$U(eɺmñhy221]uP>!BHd/;HxB #)xm.N[dC #)"w8QAIGR X­nI&A #Y PU+d׶t BHP>'$P>!BH]N *dy<=_0a@*%+Z(T|,7VşB c >|cyU1뿭J&$à|BR4~*$@]{̗H;҃*,74b0GmHVBHP>F[f|t] K|BR4kB3@$|BR4N7vo+ !_ !BHP>FS/B{ @*pbſQS{ BHP>R9X\H8|BRd+%,lP>!BX2RX> ֥ iTSK^~|KYUKAfvӌ0ă?R> 8)Q?B8֣57z 7]P A I6FbGucՄoi{ $ #{[T!1Dd6KЂg7i 60mC(:&3:F]uEHP>HP>冧]: /◧`p]$(+Lci8)95$||'(nFnUH 3Z݊k](6| jn`C>8Cw̢|LLm]d*4cwk[U!1LE3<_ȩ*ưY- %K+ٻʕ$$ ##,g=3X8|IF>]As 3KL\v:2ÎY=*{0Xl yޘe7DK>4 L [9VpP>U>AФ#E/%FOCDg󐃸0tI^r$DT)qJkۙXJQc`JuD>pa滋zqu Dz >f矼U [Ih|$hzvnk]#EG,YITj<&0#;W V\AFc{wXF?q5$>hq]Yp2^>bjq*k|ĭB\  ĔZ" $h?nbVcr]':mm^ڻR@\h*@>dD"V1Hy S>n)V׿HP>ߴKݴ?P>"hröX; 0?K?:Ggl#e"=!S(^77K>!6AX>^˙n#+ۏD(ė{vHN|$ ]iGe4gXrbad(DݚGaD#?kJG9qjffuаUl 0[ 2Q޿p*G@~6TH&B N}ӑmBajxVX'" cŦAUG'[pmí^GfC p))D5 AH6.c9X\UBn_`(dom}uG“:XѠ|,!e/NF"wT -$c| F'm_{G^?ЂJGxvNV\3ӍۊB ׺"V*̂A(S?@OP>Ny'#Գΐ7{U0|'(%_rOdSs3QP>7m?oWx( G O}>@>"WH&B K=T9GxFCKpHy#c 8[xQ~{ǀ~RCj|ɮ [N 1J/=ErI@ N9P/L.0B OWO?F:FzTd(GCϊ:TĠ|BAb ϼxfA I !$)(DA $(Ä}*AI HR~%<^(|\O$SBHRP>.|'(C;*϶$}+GxAI;PSy}h{mUHGxAI;r۹s O( !$P>B P$|'(C)nW^_( !$S>Ʀ摓!\gŋ%_.)A tC- <YqʥGxAI; ?HR #ζ V|Kϑ( !$P>2310HR4~1Qs['{ddjP>!iᐏ3 0UN'汩zGxAI; ||VPnQ{ײbWgn #V&ƳIEg4:n*|\!ڑS뾷k0T9 g>BHYQ'^GeRa?AJ)ȳ ;s 5n֗5,b): x؝_G!m Z3ȇߥwj+n|j t;|BΚ@![r"nd{ܨpνTGp""N ŬM7n<o̲tFMajbx.*{ rZA1oAOP>!iiɇV*]!i|iXJH ]hlm؀ k"C\W0܃Xr 5K>j?.e=/xnZ9P>BHY!U̾VhW![ŰE$cZ;{c|bS><(W#\D{GRGxAI;O%zVf;Ggl#e"{CB|v7ssckVhƨ]w@ <s O^nn;vnٖA$ GxAI;OS'<*9JVWڕ r40FfRzS؃DXRɍ#B|F5{3:vh*6L?E@~tWe,:vVT>R냻gZ!q""vmg-+$j!$)(iEB=46ttrnSe !$)|0=|wNGTN4ۺWB $#3Ô3 hS话?L#!$(|df*m/ Qd)%, !$)(ms߱63vnB{R:0YAI Gf;atM3T@B>'P!?)#SC=P>!IAI]JUg!$))7G?)as9EI]JUg!$)) YlJN PϺ?BHRS>ȚIU*TPz|B:<5q_vo|+HUȓ0;P,[/+B( y|BFF'^?ВMn*Էs<hARzWx۠Nvʽr eWB^ P>!IA)#B yHV鑏rvQf tdu:b{Ӽکm,Ugav^}G|g$y3dPG蕧`h|M|8:90s![v$ǝ:z0gFR&qaH^ P>!IA/]$i*S5r!RogJ4\߳rh6ÎUb!a6_/EEK"zh)=IO\|Bj:sU{h{u"r"ՙL0tI^^TH, `IZL{j\'VLY)!.cP.n7_g1PP3:9ZvsRwup*3vh|y|rb*;ъ+Ȏ̍0@/ڏsT xUg=H|V+p6M|ĭ6#Aկ?BHRP>NW.9>^yڻR['U sVi#LAy\7-:s+,C:wXC $#-!IA u4t=THE>Vv}p\C7#ND C $X${ȇ90!(KJ;RO?BHRP>Dc_N]*,Ә`bnFN|*ԳgE#Tu(|8PϺ?BHRP>HC3hYSGB=P>!IA NCPz|BA- ͽSo綺-U&G6b*μP>!IA Q~{۽qY|<(@ =46-[ξr|B,N;#XpދȀ8n!$-P>+O<^ (B2A Qy}h{=*~?n وA ,C? !_lD|B Y3 hXsF Gx_[G#B0ׇ^jtǯ^|ڝg%cHq+;Y*]E[ܪ%FL>[;sm/_ .mG?7y#U' (y(dq=zh)-)[eągެ9L6Nv>AㆇѺvG8zP}Za4zS}G|g`0ݝk}=[#hvſ絹{ _wqD^ݫ=# [mJOl뒤D!&/o|DcOE&Ijih*lP#KkrQK}#N8 I%,ݣusŬ?&ɉ95=,WDY&LMQJbF^I2P>HP>QyOw@߶ ,D3b|.DTZep2i{VZZ 5j;CVyg}qt2mR*F RأM|ki1/]M jo BMDd1($Y(dK 9W-2$l+YagtU4Ð9$zUz}ėS!.NHb*S9zPbmfݧ3S><JICT)\Ơ\ B9n#~RlG_!'-/)hm~`R"^#4IY9D>k*X|rb*/w]mdn!HЏ^a$DEtsXj[Ưڵ~#nIWI6N4ƾYvw!%o8(P>HP>ʑ|uA'iWGM|H`cf_+ɇl sT֘cZ`AzKV{ʇ1I׹t 6_^K3It/E7DnOLN:tDH\AAV$V6S C>޳R5Ձtl)Q50Tcnߏ 50x?.й1.5 \p8ϑ32~Y\JPh]AAVȝ*Z9[mbˁG6nQMت[;ͣ[>bcS =XFfR7ZeIjlʍAasCQjޒިf&1B#'?ґ3;t/)P>HP>ʑ|Vv}p\C7#NDO~7a?/s۶; qZ!Q핯/VUpg;*Z?WfP>HP>ʑ>@&aCxeN=~zv0rayݮg_o??~ĉ.}d\;͑(o7%''Pn>O?F5w˝o/}| ]sO}(碔E9{>}ԩS'Okw"M>GwN^^5yZ"LyYDdd|rvvVDdN$%}cjAyw<$Ho*OeY9(7~~_^?r.͛7+u'TmmmQZZZFinn>XC|rcK._xZsy.b-gΜY@SQDP&|w_oſƒ+,k@DTwuLOO5"kn:$)8аQwnPUˏ[>Vނ?P崂|9˲;][P>AUݑmY?zO~xJ D{;wzzzo߾u֭Ύq˵k .PH$"S \줤Dɓ%2k?}b$m/mҐwwu\=455%e̫CѪ$qx4= wlV,3nDq9>T`v|jy5FN{-m۽K0= &AV|l92R##uN/ \uХM¬2S\,=YhG؉CM%mmm---ZJjkkM#)..9ȱc}}]%뿩XyOO]?;h ҪcK+xIu`f: ,aQw;@xK| % IjE#}r͜,yfx|NqJ%e"+bG(GV|-P+K!uK%MeY'q1ME;؉&Kݻ'R#y6rёSN8q"//@"<߲l;sZCqhG鑠|YuXFy 숎 :.L tdtlA]aJG]cβ;UCajPZDmQ) :/|n-~GA +#䑸|xްT!I&%SPL5^"Ri$]]]#uuuϟ8{"{so[o;ΥQDuo0qbuOC&>KQfܗJ3TCSO_%"s ٖ!1ۧ&Ў-e4Z@FGDzVDU-gG;Zi È 0s G*qh]R|nmá|B cBY#.r}"---/_Ir-"3?JB^λ2b^`I$ g8rɇeYH䵤ʩtH_(M>UВhi!;=HDw<;XC*á|0B|xF\$~9~^SDN:?-H*|ѣGrEȊ)ȢYgMR_,+JYUN.B x6ɇtjM(P>!Ís4?I455UUU={(%e-w;}Q*Ƴ hĉ6xJ2'lԛWQ4@8JCh"9oP>!$Á"椈tvvE"겲ӧO9^_}s 􌍍MNZYV  rQ$2Q@-Y _k04lT[ǣ~t~Hd+S>tWZ{ȸw*_r_pJ(TH0YTDFFF߿+!͗.]:s`!qOO9"˵,gۧ=ldC_v*Yy:]S,~-6 H{[Gˇ@=z{ݾ}ƍW^mhhpX_ycgC/ws"ojI Y@.55@B,JūBf`%Xw'ɶ Ȅ  nIG@͋=99C>v=}-H$ LMEAhd AY4lDPT_$v] ;{ $G+*xKڠ|B2? 32wlmmmllpBYYپ]07 7ܘ 4H$rŊg[^qN ,+$h7 NHC-DN~핉K.UUU~}m/lksࠜYHzCR݉[ !HhC# bk׮566VWW,.cvQ˗ۻGFF4Ka B (5 b: tww_~.\?}݉^¶ՅN0 d|BȹDOOO{{(Ⱦّr7tܾkN$$YVN>; j7|xbMWEP;wTWW+u{B?ݍ5lѣħ@($YVN>p\e`0_~#SAfggEA߿prい/<ׇIwBHY-ȉ_u؆g||JWwσ9C B (iD+̌\\[[iNOvچ;^nl%`OP>HP>!G 2== qFSSɳ_۹/w6F% wI!dU@X?1 ݭ/^ܒ{aK%uݓK@?S ,BȪ|h A>|qʕ "woNNN/A|d|BVqfhhB]P>HP>!c):L\|y/z۰ A_iS~뜚£GwcpOtww,][0=e}IU!Ȧj7 Ūr 6>%Q#Bk_ BA{UAlЫ0BptC%vޤl,Ҏ=,C8/|NaiyyP>Vs ddd]z9k?nݺeǃB>ҳ*@H3~C^KE%:G_ip[[m(xig,ހP)]dI/H3h Qd8[!Xn|`$Y[;5 c1@;::J/4cx,NΡgA* q*e(1![k;*eZX _Uv9 -e`ݕ]0BU*| ՝yR#7`A,<"`sXOM($ؼmIBK/BxG*b5V_y/tcJ9qB&Dz?%w6/Ot\SWW;?ӷrZŬ8^ !QV|H%nW]##!SH+Y1FSe־-{0xWIR^F3 AS7vs5 #1???55ow^˵Eo m^x.*'? W|dŕ~BH:w+Uwɨ-qX熂gE}A KЭLDK [yjߑjK D, 5z̄]#~P>Vz7@ /_~: f||\v@+ŧ|2^2q#r~DާzY1Ձ)rPt? ,A 95`ǑJ%!ɤAn,}T̢4O= o{7?/W444tvvCeoOƪIX,z@D yG!@+! ̹}-zs\Qݙ'J0`3пLK7 MkMd$ҧ{@^Э<8u 5lz #ꅐ5 ˂<-FGG#sFpd.jmm1ϼU! U0! <2I B:U_pF@̙3===7ruu<ˌ0>̑)O(kGI<,&iyX-E٨{9toz2ɏKă񾾾WS/~]WPPP[[] !-HY]K1nb'd '57U`47q vb$)N9S'Oŵ-?vy_|SXZ^HHPa. zh"w5%''I|O_[o xg]lU|cAY|DXڮylstkj▏zŪpʁU7JگTZn8VE>c~~J+6: # ^ɪ_ݑ !dU|orE@Ć2llű[ OX& 1a0 ճuL6U WG_J<$:#1BBȪf"d>CSI::U𓏘CpmAM"ڛ 61Mt^Ƃ#[2*nݎlˍ=x)U Eg@N3cCOP *d売&6b5:ugxriuǮ222ε;/|BV5 mOXx0uO>,0j{-[jRܩ"yQ5Gcjn<ïhrXEÎlD|Bm YYB !t[J+TvC>ޣwg`-ڧI|{ cHf/ʺs>K||{7巼AUP>!k~.k5O<~aOOOӕ7}!~AUP>!kL~mcP#|h-ROXaG:R&qaS !dU#H}}=,ܢ:|X*`{+$-m𬴴@jC>Y`S+c1R!Z#RcSE00U3 lX+Bok(X‚{~ppW\xbee/.&sHZt}ė g'r cNTKujs O>ܝ=˞aEq+Bv,BTXH˝:G6J%zVf;6dU.G\asz#^7gD5FemC_X[oO3#sЪznpdQMlOxTFsݧ,oFjW6۾t FfRzS 1<7Gٿuټ-jffuаUl 0Z|Bk-BUn03/1 C߇6&ֽA,s(Fa]=+J, BcEXpǦnq\M{Drk,ԑ(@Q>!k5!Qs2_?0þ 僑QA 1[DKy'Me_*!k5]'"Vay[E`d@P>!k E]( !dKRީSOO7[%)`*(d1;drv{xv|0AVF*z?)a!Գ".Yoӑ9<5 ?6FB=-b>,~ޑ اzC O GB=-bzF! Vw yjP>BYgռE6Ώv܍.Q$ x~Y{A O GB=,aw-辯5ۦ|fsdSH>r"{Y>1|#Tu"$ms[* ؒ6oMW|$ 僬(AUgݟE"|!LfD#tCѕ堙YJW36zG ƖU=I-CXNpx^͂|d|#Tu.HT!d v&pZڻ6I@Q0}K0d5$cw@Hpx^AAFf#΂,kit]͒C=$%Ѽh}:r|O3+ȇTzw_ #hC0=ks_:۫Jy5[,PwԖW_`dv|Xk9|JGڙBGdSew2zb2=f5!`|8nV8#sA2aNcWď$y6[,GBb'/|N\P>S#a%>ţs 3;Lݏgաx!vۀS>dOX1=&񻋆Aٽ*h0%ڕ?oVvMvɗ5s+ӫL,FurS+e9nSW>zG(ewy6 & ޑ :pA OȇyARg0*]f1FAx<LDUZ:$#ܣyPvbq2v|0B\P>éG84l|pW5̻Jba+;,⺲=*lHcʇޜ#\Z÷U˝SOl j?僬4grzq񩕒ϏᕧC@\h*@>dDw[E;{ =46YX H,wyLg;_Yl.&r40FQX) IF>9qZewՔ%J8ԾY-oUxRR|G.ZSflki =IO1G\#僬rGpĉH ^ P>V'Puwmk {qя1G\#僬N}xz pjN$(\>z|Nwf@AJ1G2 PG\#eAVszz1?P/(O'ʇϾ9& |$m6Gʢe'Kߺ`-]EfF Y9rzs~Vԁײ) " " n`W棌=iPj6Cns;PIRL"q7k9* hF~dݠuڍN;R#{thw6!كFboNvw5[AVɷs[e93ՙ[P<P>6'ldk.h+׼eT9K# ^V%80DdMFױ Y w Q( NPNalf|rVbǰb˩bՑWUl,#λvu24 Ҝix!vˇvxLFyPvoWF>X Y N4 #Tu2[>\DQf<QxVqX[9-Dvͼ(P>LU v3 N#@FYW0#UimfݭܣyPv6 ۜLY18=C|eés[ #Tu2F>bqo!:ވ#Igj?8Q̇NJtb,X?wec4>͡!+k.^[vS>S,;巷WGB=QPUkc#/f5:qc!XTm5v U,l l0^$)f'XGP>"mUJ3y\`xɚ%Qjػ_Ȼ!mټwdNXYҹgkcsKXE0}C9 sĮy9r$;<\aGp<Aڛ:sKY."w<.z˒5tM_י?|[c>wG%s 3>ClcEcD;>_RRFB;vsP].(dYx<9U&d1|8c+ΜTC[o2رrrrrm G=zXP'N285B˹|vovUazIIC0zYp/s% n? ظ3zâ2i!3H2Q!b!*D)'D&$=4 744466655]|9477_z6vv7n܌y+ As;6vlǮo^o0BS;GFFSFƄF=f~eh|F}|*ԳȲʇvW>x}S]Ðs"0 8uTQQٳgE,Ο?/VQ__/J!>@v횘A)N(}}} <K F n|iv{@d$?-_ a`mbbbzzz%X5x?僤}#T@C>v-sr[ߔg|!gd=zT$CO`aWVV^Ȍʕ+Hmmm23ѡB|޽{"bbƣH:1o] #T@+W~ 7IUV[r8x Ç xFQQQIIIiisD2jkk!2{hmm~:t  =EBB|!nu@BO' W]Qz6F9uAZ/n80T OkP.($mx޺GB=끤K>>[ݓoz=ծ6123.]DdCKFOOiZ/L&%bV L"8A=L ;ݻwڵ:Xի8(w^9Cz|BuA҃߭k|*ԳH*1;pbo*׵o~Sy;ۧ#77WΤYrH$L| aFooorĔ k"*nD ulOq88:&QvlУ{s{?pd#Fx僤[AUg=%G͍%8/UM;ٳ';;[.=rGqqqYYYUUUmmmCClUlGf5D5d>Y 3_DBcQRP*9@‘vׁ IPz Kޑ:"UVſlsCNVVVB84|m<|P\! QԈ&?G۰EVT-8 ?Vw%FfǖWo/̪ IݺPz I“=mpٳ!׍$ǹsΟ?___D A=m}$2 CMHQK8 |TYڭk) |L&o}֙:ϭ<ի7nܸ}vooBY$#~}o;h x^^^aaٳgϟ?pU8GOOO0cbbbjj !T(C B K'[BPK|pąP@}ax_j3,suuuH}}}pǏ;&9(B B K$[9H[L*rǏֿݱhGqrϳw<#]P>HP>RHֵDc#C jo>iPz5yr[_wۗ#HP>RHֵ@4L_E/P |6CSXC0~oǏ 9rcǎko*Sthz 2 ƇϷըPP>Hⷮ5<&@3 y1Qt_x#ImGHֵܒƟuHR>B~ df^رcEEEUUUMMM7n7vIY>_rg1VPJ<ܺfe7| 5N!l*!E@Ug=[DO26LpߺVPz /̿wȑK.uttٖ9!򑱡qZ-jh䣤u{a!ԳE|O??),,~zG8AHؠ|x72.wgY MCm 0[FzƠ9u x}?VǏ///onn{\aJ $T ^GeRa3yv$nr |NTXm\KC,!"ֵ5ZD"_%d -esشpuփi@![@|X{ܨs F"~wK -qaHb.zOɜ޷s[-!Ko*}vw{>7?iuukj{BHhXaަ "smLx!vˇvxLFyPvoyh0$m:Yp~Sw?m{ݯ> Bj9${U< ayC\T^ܟvS[PϺ?oYeG9} $̬.VztYÚ*z؀j]FxyHΘ]IR>1Xuʇȓ <xFl#=c_ꎦ]NET|*ԳC!7g988899ɫ= 3S'<*^1M" nOث$ٗ465 MaHO2!!tmz6%Д% 'ojx< wryh$ūP) ޓӎ:u/: = 3B>0tpeF!q"d|n}eWewФMGB=>@&^uơ_-..wj붢w'MՖAX9c*A5T@&B&hB?{JUg Y!s#G={`q?{.U%t)u7N^ jv.#TuM9Ců벳;V^^[gGƆC>x69TjGB=> 26mN:sK.|Xm_#2R Cvةm,ߣUga\Al#}5_wJt\j^ǯ*Y!ZKA]Roi[/7Y EEE.]*ٷ#!' ?ײbV²|vfztMU5 Bk؃A:ST0׉Uim,$IJ+F3G1ՐAz o/9}tCCCA~!Y>Z!?F'C|vo8tx&]ԃ_%pd8G^FbC<5x -[{891TBԋE壸T?C{%!$P>.p"v1s3t|H`pv6CarP~=$ ,=#퐀|ϛR>!Gx[xQ~O% tB4k%{V갦:у-%W>VA'MtxN=ki {|455Q>!# 8~7,).6I=>O/閄Fxˇ=/bLoBѭ6a<ȇ8`ߒZk5G/P2xC;$(7UHRpĉH:B=^@&ε8C”‹(@ ?ds:2 ɰaN$(yʇ}?|{|\|A(dJzֽ-|9sQt S>!b?( { Ð+WP>!(p#Tu/ 9CB䣴4|S> 9#ً?( {ɓ;0t )Pzֽ#GP>!&GRP>BY"@>}Gٳͧ/Q>!$? *z?)a!ԳE|lܙ(++z*c_ B ^$xFHxm!8zGqC(ăE/|tgoo?U3q vHlޕ8w\KK "P>7/HK=Q/\sh;v1w_' BBwGGBb*nR/oF!kGEEŵk4Q>! =gو(^ 6!u;~xeeK/_G P>H P>BnϷU߿???7n8{聋zUBHH|Ep_Ay8[׷8p\1!P>8.pދȏlqHBP>Bǥ[#Б@nnnIIIcc;w*D P>Hb^-pd#GG||o8Cgjݫ[޽{Um'5WB($Q#{_ݽݑ(Qz9tTե r)I3 r[T( ?CT /wMkjj:::_;r_~%ė;۷///obbӹMB$L!Qjo~C -a:b8GTw}-5| !"+.'ϘbhkV={:tԩڛ7oOMMwS>!A C,Dsg|DB$a']dvcJs!SC>Y{< ahxݛmhl7Sp;VVVD޽;>>>;;[-D 14·de+JE*5άhtMU5`MHZ",u0l"s1Iq=(o}iSm<( skM&f3GqyM]`j"M XP>H$,ԋX|IJ}rd,{#A?F{hoOuPek/tȇsc'z_~fǡCN$ 1C9*k7*[IR>Njf>Fϵ&:>?y8qܹs/_}ԔɖA($i9bo+)\vtmaMu [JT|900 9T$)zȇȗ? =CW^Q G@;yhϞ=?{ٯvn>y$̣shhsssB@ I|`ٞ{6#|8//_>xիWo߾6yP>!A&}aCP>t^9rO_~_Ǐ?߿O< 8sLEEE]]\V_;22cy!D|YDZM/~??nUUUuuuMMŋ/_lQ9>>>55%y(Am>~y-7ny]ׯ߸quΝ|qf}مy!D||*_FY_Ͽ7Gk֊"P>HP>B]m?{ ;򷧮윚m/,,dU9Q/(AR? =rbEfѷ!D|q#Tqm/TC (||HP>BBHP>HeFPB|BAf~auI|X܄z)C $,ȗxI0B6>Q/h@ $(|B BHz|BAIBHP>!AI!$=P>! B !$A(@ $(|B Gug\ _~"$!0`xƮ w~B|BH*P>!BP>!BP>!BP>!Brqkz6`f¬zA{`0xWm !|BBˢB@ !$A(@ $(|B BHz|BAIBHP>!AI!$=P>! B !$A(@ $(|B BHz|BAIBHP>!AI!$=P>! B !$A(@ $(|B BHz|BAbo?f/=q7 aAIIK +y׸A $$g>ȢP>! B !$A(@ $(|B BHz|BAIBHP>!AI!$=P>! B !$A(@ $(IN>vn|b >3Ҧ,|B>0 ;P>!BrA!KA(A(A(A(A|_\lX[,՝y H{u{!$GIIENDB`cryptography-primitives-1.0.0/data/images/README_FIPS-pictures-0-ippcp_architecture.png000066400000000000000000003237561470420105600307610ustar00rootroot00000000000000PNG  IHDR(+sRGBgAMA a pHYs%%IR$IDATx^{Vt^9ef&dLzuz;[;nٲ,V$.Y^md$\A(iKwb H͵ *TPB *B6PB *TP¡] *TPB%*TPB *Tp(aWB *TP"C *TPB !JUPB *TP®B *TPBEv*TPB *B8PB *TP¡] *TPB%*TPB *Tp(aWB *TP"C *TPB !JUPB *TP®B *TPBEG U7SNLᥴR!m9CV( BP(bpSO؍RVO]T2@C&,4t#$߉R ZiӉ`m,mkeQŦZ3_}0= 5? .kNmֹ9ɲhpy!S(ape{RhžTzk"{-p͗ߤѮs[1a3&?A)gF;?F5.[{8HxcF}z}_y͐7NbȒGyDA`D\c}\<'y8\9_<g'O S( [dŻc7%t$Z:gWČ{W(m>C/)1]AuMޒ;t0Er3ᗤ!خH,X /VBn'n‹/x!mx/Fv^ĭe P(+|~}]WޒY.QX 1?Fݧ*\+sNFQyMo=t=a܈l+X!bB̍-B_/0˸\ /VB2 ^98v^ƭ N݄q+x!7C) Ey">;p,ILN3Av|6[+nSVq!Np&}Yg\#FX1m+fL9nj!3[ \ /fRn'n‹/x)gamx/F OP(/wen;>æ;*xo$П?FOQku F΍bnD[!DcFE-ꀑs#h/f2n'n˸ɵ2 ^98v^ȭ \ /VRnS(p,i%6(,_N.d;wes=sbnDȵ[1!Fu mQuF8v^ȭ N݄q+x!7k7E ^Mx/fpr&"n/V?BIF" ˜LϜl[iɞu7D8uwEs#}!ܾm+VLOQ)B]u!Ern@e ^ȭMx!rN݆r+x)7l7e Rn/f?Bi/7'ʜ& {{:>y08J9Gm;r313[˸X /fBn'n‹/x!7k7Espb6˸OP(f CwdvW]|Nγ77(Yu9ʹF9X17" Vȭs#~:[:#h/VRn'n  Vȭ N݄q+x)7k7 ^ B1+,m_[-n7\vԧDE*w{ԁsؔt $.a+F\[ʸbnoQr Q]#Fv^e N݄q+x!7k7Esh2}Z :N7yH2nu_Juk7e ^ B19u}t`kD|5>p7e]]X9ÈV9`[ rndv:#Fv^ȭ N݆r3x!l7e ^Є[?5ӧax!NeBbozo{ lܛG,}1Arƿ-v!x\=#>@[cokt }mP(>PxSr?\;}iKJ9l+X!bB̍Q7ȵ[2n/Vpr&-Vpb&r3q*L9 y~ _^Qr:j|(T(oC/Gl4):%쯯-\d]jNر-H\Jk{i%a .HP`wAEd[xY][ش.%W4vrI9n/@oJP |?!k_tu ~WK %{l:F扎s[NP(B Gzyw @=Y 3Q,댘sb! Vƭs#~:[:#v ^ȭF݆r+x1mx!r3860h ztvϗrDrVD 1w%K^7*Bw{RQ&)AhJ-A.~v%nW?ݔnߝ"`y~E'}5Q@ZC!h1 X^!|٠xb7EUb7x5, ߿ ~Ij&>s rB%Εc2nGž,?S[YQ:+K.1H9+F\[ʸbnSmʺ2wMօQ1[2n#pb6 X / NDsNo|g8L.z!:/{zuDžL?Fbٸkab9`DD3mraG[e/9z1۞ dӉdNj\J1L{ǀ^+;2!Iy-Rqzc Rpą8O4a2lV&+/K.h~ (XP(9~}n,Ylc렵V̍ߣXA0H9+B` 1uF̍i 2n/Vpr&[K` /VBn^)!WkeH]mCرҬ_AG:l\اuMAxr&q2;R'㥜k44_[ܣG|^J}|s ̄5zach]8j1Jzq1!.1@ B1 ABZan$󝶟ɓ_H&@HX9È9+F!T͘3.D x!7q+8v^ƭ N݄q+x!7(v)/[;6mIR6&z2 ;$Y|) qn<q[oj] &m;® %m/fL 8Hnkˌ.$FajEHk팠Wqrk&Oy}/ @[ltvBP4H9P#n$@{SBWt=)`܈l+X!bB̍x Ⱥq7{9^ȭ N݆r3x!7k7ePeфtbȡl|kk>\/ BH-!5aohj#zݚyێoo!dt1f5ND: z4};^_LFa*m)EoG|3Ž}5uAB.j0kP(3ɢ䯴nG`.>1ilf!f2np%vE5+Q[ \ /p)M_^)(<2y\Q9rOat=cd;#\j+q!﬎ɹR!r1kaW> &Q1o_'{.-/_BP$lCc潭rӣdہs=)7s#B`܌ 1[օ\* Qp ` /fRn'n˸/x1g1SvOTPmׯ˺RbZB2M/Tۼd;GmMر&;Ό#Ja_c<'"yt,mh̤#^MaGJ?EܐKm:s cX B+;Ie $‹.XA`+B`܊ 172D] (e ^98v^ĭ`dPJw5ez98w̉^&1)>PR=>M&h]JA\K!aUl#z{Q[*]Ib$]Y3X6V+#\jKlDG[=)C[IJ \`ю{%i !}Yg]A9X1m+fL9_`&@| "v^ N݄r+x17l7 ^0 w̉%ms>Bi.F׵ eB'lq{N9A_nNB<^EvlAl7,KM$?ҌVŽɅ eNЃr]@HnNn$(7\=о3(rcY^^B/ψc…[{+aW(sg6걻:ϾMH9,u!V2nNx۔u!׮ɺ uQe ^ƭMxrN݄q_BnQ^\\ws3P#rݮj/Cgz7ҥ*ٳSUcdkŽAvhݿFblj ;̪}XoStF,]8& "E9UPv8qF$ɶW LJоWcs/B1A'VJT1b_$zܕ+>QHwm9Kשּ:`]sV΍r+s̨[#Fv^ȭ N݄q+x)7l7espw,oK}=Ɖ9TV+{ׄN\(:>=+[Xih2AUnN-n<3)n5L.S'',W$>Q]rU \-ҍE㲚v_>쾐/1{D؊LJۭ`*RoPuG`|&TҷEZ b_w:=Hcz6 B1v$L֎ QuV5dہs=sbnD|YʸB[ԁuF8v^ƭ N݄q+x!7k7E ^mx3']^qBJ;[ n H& !K}wRVY}#']Ǔ-Ldb`/zmVP(f;~u;zk0֋ ɶ +z R!VBnu.;$e]HT spr6[K\ /E](`s.[ËOP(.1<1nGŽ/! S5;Er3ᗤ!׮I:"s([˸X /fBn'n2Xr38v^} IaOv^e P( =#`aG|S,;劬rsV̍r+tru 5Y"d=Rn/fp&r38v^ƭ M%켐[ OP(AB+k{xb,T5XAÈV̍q+&܈ߢ.:˹F̍0˸X /VBn'n‹/x!mxr34ܹem*z^ƭ P( ,n;4Q ˑrs#sr3&Ĝ#uF8v^ N݄r+x)7l7e ^02 ^98v^e P(i^~pE1 5J9+z17J9l3XB'z<{mʺkD]Hx:/V2n'n˸spb6[ \ / N݄r+e P(ibT|br'sĭ+Ž@c̐ʹV0rns#B` !~:튨kwEv^ȭ N݄q+x)7k7espr6[ \ /VBnS( 4T+( L}dV+z)`܈k+XbB̸̍ -ꌔs0[ ` /VRɵ" ^Mxr38v^ƭe P(_xfؘ"Xᚰ#e5¶uV}1!Fu!u^0rn@e ^ƭMxrN݆q_Rɵ2 ^Mx!r3ğBP(fY޼wT ^*쿋/?F^Dr!V2nń QwWm7 ^Mxr38v^ĭ N݄q_B2n/V?BP 5-tZpU5ik0b!V2nńu!Er#n˸[ Bn/\ /VRn'n˸ɵBn/f?BP0yl, z:uaG(_*Qʹ!VBnqu DܷF΍$-x!7q+8v^ƭड़kespr6[K` /VRnS( H|l=+{+ĒGPq#VVLs_ҁk+XbB̍-@ۢn-댔3p[ \ /VRn'n‹" ^98v^e P(L}WTP%nMOM!dzAڻzGYAÊ9l3XbB̍xMY횬 -ꀗsv^ƭ N݄r+x)me 2n/fpr&[ OP(!z/V3_\e{&xUa4aG`Br菟+ŬV9`[ BKҁlDϢΉ2n/fpb&r38vo/\ /fx˸/ğBP(Bw̭rAvC! 5wtl_օ`[ :9w:[:# h/VRn'n  2n/fpr&r38v^ȭ P(mߝB-' wtGЅ]Y=51]΋!V2nń[ԅ\CyA˹d/f2n'n˸ɵ2 ^98vo/fpr&[ OP(!FZQdfbڄQG+RRN"tYs!댘a$ x!r38v^ N݄q_Rn'n˸/x)mx!7r+ğBP(B4)N~y~9MCbŴ ;_~UXgh{T^kKYbBʍxJ pD]v2n/Vpr&[K9'n˸ɵ"n/fmxq+ğBP(B^h]0ZuɜvabD՝zfk"=5zwu m:C7k:.;.B]u Dܷ^=`D x!7q+8v^ƭ N݄q_RɵBn/fp&[ OP(3 V5STj=m:CoC}sC'緈'UhČ rw)1ZV`]Zw8vɧdёk%<BJmsmn&b)q 7ϩ`r8 nMQ5y΋̶U҉PK'BZUPB .R#C *Tu ahB %;PBY]Ŝ %;PBYwZtLPbnJUPBŬ }~v*TP15ޤ*ṰP>C *Tu [U®bΆJUPBŬ V#ߠᶉ*ṰP>C *Tu Svs4PnƞPg(4S~Ek[)ut5JP(3̾[cN ;ޠawq2hB*b;XQaEBn#va%.Bn'ᶃ0[ [/7g dիn 'ɡ/Nx gis t;Pt_ ^|V#-]?u8rے(s&B;>DnߧזGѶSr('ہŠ:`.K+vp;EHEvf+Xv!U/N)(t;Sʭ}Y=.$l/ND9;0~e5ѷIX7r:k}~ǬvT`SI|)sO(h +pBQہpaV :l+n!{>:/N)$t;s38a_OjP@_8AxqI72(> +iٞTYyi %;fnWěOfrh +e:#va%.BnÜu [ɺNC^ /8aK!)p/‰rKSxY7 ?xW]A;,B Y#ɺd鍒M(ȉX/逕r#B݀q+ E?!vt !Nl+n!ۙF Y[IrKx yYrSJL˶Sxv'ȡ/ہ=rlp],P>#dG#O,g% XI%QBq_0nV">(o'ᶃ4 [v.Fg^KS8Ixv //"5tϼV‹8Qx^RG_ND)H%;BZQdd9}+Y +`$.A?!v.Q/,~/+`>׊R|/g: p;Pn'HqQد=K]{A{@Ol/N$9e;xt>zn꟰ %;BV1E#2fBjil6R3XQہu!np9જ0 ʹFJ:'W\TŤcZR|(6c!ǮJYW?+e?OˬxmY}%4=N;Sm/=.y>W5?ݔ l=(x;o1'싯=O ^o$9e;xvd]z!Ly,&B ~),/-I1i h+^:(vFɸ8aH0:|*NH^Hg&k{=V¾dzyVHg!eϟ^_m,;?ya#)RAFQh%-^#RO,?1&/!7C:`y& lsvNC^‹%aMx 'ɡ/ہK%Hu>_:/2}}~G {g&E w <_BG5l Apɵ2'q"n !FaCO,J!9͓`Vyr+]HBƱdDWڋDۍDztkf^s%B'.4:ʼn:,nRϯγy5K88\Tuy {:D2kfy& m/aD9nN'젮m6l/ND9;xN9^/ӹsu:C !ht4mrWYI^3/ꀓqKan腝pi6 {}ˠ2=FIag6z%}Bƭ]K}ѸT+b/a^xiluMѣ}x0]>̀_e}#ߝktERn^ؑtKjpQ(}:\{$:0cFuMŃB!t +CevH5R 衆|o;'yș )XV*&A#E{B1An ڤYLyB!p{!p|~]`XurH'~^`KJKJ^<7 }uJqyɹm=0e^.KY!h:{*ڳg#]REG&^<xNY-q_mCJ֪;3LJwIU\>L]-}9 :!!c3"$z\ԻF黝r;?FSX\| m]r v1y%Zc)EcW򢥺_y.<9&E_H:a6xn12ebU[ ԖI+lxZ:6 x 'vH9Il{e;xv'ɡ/ہKp&wTd| ~ik'֪1c3@Ľ*\YIeEpBnI6͒!\ XH1Ah{.q=W!Ӑl,ӄQ^s,k U #uB1~zwʋPZ#scsַ 8ҝ FaDzJv{S΁rv<'I31^DRe6~@'"qao'~IuV^I {Fmp/Ir Sxv'׫`;f~t9aǕ(r%^m^+FPB'VƄvzyeR Y23a_.V A1ڡw ;"??΢Kѕ8d +a7@kzݵVWi<ȏ-@u@m֣ &쯉˺Vi$.@Z&LvCj˞oyf^R-SpCO8>BΏ$T*^ov6 'CEvom6#oǿTΤc,qqh=xf8WeH21ѷ=w{\uGVf(a1>yS׋/ZNƭ`%nE]Hs" 17JQD/z4aG;/c @ =25 MR BIq[؅0ip M6;JWIsaIkX+og~Akw{$R8Y %@Mzۗ߯al5!9H+qUWRb>Z}A<>pH@y2!x{|qOvWȵ6í^ؑ H$ln_?01 }xSoKSxNLؓ*#p/Ir(-ځHC8Y;]@V[}~Ǵ ;N^Ha Vҁ|,uB/)H؅0nB)1R!m(zm[؅t(T܏_.  +zc>b&Q\y !S5P VE˞dTѧhŽ@^@x~^3Yk ;D 0߇\P༃,W7|w' GeNƹ*1fŽǒ`nŠ^q]ɬ, zŽ%#-_\(?ߞn'N'VFy^r( w /$uc㿔lGȄ JwL 9)7u%vyQ[qx qS1CXJ=%H9Av!v0u ](Omv`'vNzxr]a'r/BW&Z_RdE+`"$,ӄЫnl%4Z[Nqq|2mc^qD<ǽD ;DMt:E_!c<&FіV!k~Nb-޳ ;81ޫd_xV x 'LV\j Sxv'ɡ/ہ8Q?P4dhnA͏/3wbntJ]f^YAr35a&,CE#B :$Ȕ!MŌ " tT$!v!vu Z_. M!IGC2=ԛsIo2_ g0 )$NŽ(AO6~A1&Xu!٨|"j.m1(E s@[mx}xUM>%l#OZ+54)g]숺OalQ]v!x ZB>-YpU~<&E&;X=1QJ^ 7Є}žT[%8cl]y؟~[^{c++ ..E#߻|ݯoè:YkhWq̨}1v :HѶ/H &n;&Jsn znXaŖ_Rv NC^o$9>7ݞ4aEC ; .'V:`܈uVȭ0ȷ?n![0): OXCwu<b^ԁk'KD'@ wʞu"!g)u 0{) V%);/Gu`.}Y&L5]2?Xɻn&Bn<c10ԈA^صnVOCJ~L1n &jӣ'o_8nzc. 1 t;P[[‰r(U}rލKf,_OGȟtJ]u 9PX ]4+Nf$4KF[cpe/D=y540 p)Fn(iwxuvDY:x2pNg3aSzA2'‹p t 'ȡ'vx)\(7}~GЄn1wv!묀e:`$.A> S,[ԁki6l75Spn"s=v^0.مݲ )1ݓe=3%HBN?^/t%t;Lo ]xv'ʡ/܁˷p*p""(a4a,jXp;n!JpaΈn dϺ)#n}._FC)J t 0ɸ$sLk]V#˥b@-~Np/,i5*9-d[G)>| l;n'p pw*dY}~GЄWH-ꀕp̼2n#va%.BnÜu ۹ Ҭ&"rmɈ2v]8vrZ7T O蜐Im#|$Rn \7xt^&+P u (OUrl3aY|R3"$B.Z|y:{j~NC^oD9 4IE'ɛ_(aaO)hѪԫK:`܈f7`e F ]ć?!t !Nl+n!;D}9t;Pn'/F9 isgXH¦ \/fQtܣ(lNosY[_qM_8Ax^Ir(KSd<{@Vr2 @6E"nDqvVȭ`$f` Bન!fB:`$B瞬NC^˷< ӹBa 9-G< u/{'36QHhNj8Qx^Pnxb U {ZQM袤^+F4 +`$.A!v3p;u|#3/N)$p;ny&]wyH5Xua}@N1tYgŜCs2n#va%.Bn/@ȵ0[ [ϲKSxv 'ʡ/N_8qI:JiEĿi5O DY_zPҒ-Sjm7^ʎI 'ɡ/N $t;sרտJw.옱čR%`.Bnᶃk! VBu p;n'p @"i[d#ߠZLدimԻ2gk/pp x 'ɡ/Ns_ӹd/pUs;B9 /s#Bq_0nV _Xvn;xk'il=.>ܕPo'/$ ZI\!!ЃaSaF>`݅~s x;Po'2nWDJn(a᪰-LӨ"$ivVƭ0ȷ]X!JlUIB`Mp;t`pA{˶S8Axv /N$9D]OSo=hk\-{usPf]Z2~שN/z8Ix^Pn'/E(m | ;rYu_H6'㾘yYgeۅp;iV"JցA時o'NC^K8I8Q) x.Z(9:~R0ND9;xNC^˷}>v(}~kHXFeB9!7c:#va.Bnᶃ.d VBsQAUPn/$s 5ҭC+#.&A%逗mNC^KSğ$n5&F:P>5aG>D %t;EH\u VDsY7?0<^Ir( Sxv'ʡ'V`k/z&+^4z/[rjo] w /$ t;n?02tڛDI ׄ}ю{DnNX)([]Xf`)B}-B VBu)(t;n9Td.ѴLTbt&/{D)Qb_J݀Pn'/;YMW-ߡ}~k·^*ětu ہpt;A\u VB|h:uH$k8Ixv /Ir( ?}K=$vVN4D^Ir(KSxv3eL[M}~+žSA&wYsyYge F ]4+NmuJ[v.Fg^K8Ixv/ND9)ͽ {"nuQʊ3Ay^Pn'ges %;\M'q͕sTn! St[5X;A`n%nKS8Ixv/N$99SߔNā6}ϮOܞPnNC^ Sğ_du߿ ª.q:pE1~>E]3μVȭ`$f` Bન!fB:`$BU5$t;o$9;d bnőԵ 'ȡ/N $t;n??}FI-u(a/4rJrsQ(pn!JpaΈ:L 0t;np ^PnxZslIr( w /$p;n'>^\ak {C 0*N6N+Bq+ +vt;EH/xQB VBH3Qۅ晀nNC^8Ix^'d 2YQxv /ND9)/`H]ſC N(=1ev:`$E?!vpM54 [Vp;Pn'NCo^9FљmdFz06Lv / p;n'?W<6N%;i WY(pn!Jt[ԁki6l7L #3/N)$t;o$9T)c]Vы:XXJL w NC^KSğf6қ?%;3˔Q^94+V0nV"Xvn;LVBHH ^uk8Ixv / r(v "%-9+ƿ9晀@_8Axv/NAm5z"^P>#`a?|(s!΁ʸ/ +v/x;AH\u VBsY7?0<^‰r(Kxv'ʡ/N_F>/K[GcXynx^PntzF/S. %;qkaV­`.| ::JJkrK)"~C;Ngц@}+ޖJ_lQ( Ey>pv"rk*-ڙJ+ÙTCW )=JʩZh`pPS!Ϝk7 >'[QtKKY5V\}lZ^:`$.w+޶~jlꤼj ɡcW3ćK:}92BP(f ˣuߧ? ߗF/fը ȫ!CplL't;EM;CB__~2K-P>#`a_[>Vƭ`^^*.bq:ޞFO, BP(kRegٺq*.ĉټ:b3-P>#`a_'ʘ=}1@mP@Gd҇R BP(3kRhL -408L?ae 7<|Lשּy(a/y~9%N`E Fֶn-(.gW?+ B1[xiy }16Ȥ̼2jkdŜCҹ-P>asp` F;"DҲĵ,z'% BPv^XB[Nf|ꡇcBZ5FǞЂ JUXƌ ;+`$.-]BK闣Tzy+ BZ7]Ekni YQP®N̘2n#vi^УU\P( UAw7YY.쬌p; On҂MMP( bnT9_jYD ;1mΊ/ K[{ŧcuBP(5oIqy+s<(aWa'EYpW.ʥU5U(sI-UKF2J{)*֟,^\IhԒpS~ 敕DWֱ<(aWa'*쬌p;@1;iAq z)[+[ᣧE}}*r)mT>BĶmRڋjW P(SBZ x t]"n#v^)E;TB1餦Qʯꧮ1`cWMמ(ZOVCi˹J% <ɣv/N ;+V0nMzt>S*'[{p"k!؏N{êY ;neP®P#kTNOK%*kʸEuPNok?|ubkxLl{](do̫/a_?U®PCPq۩,JU W}??h}54ƽ  iJ&;Q.sُF{v_NhS®PS6ϢZKvvbzp;{5jjhי JճPG/Va?w7dS{C*oW̘\ F^c J*覇Rra72] B1OAz=iT^^N?`]ag$.޲vR=zy+?dPe<|B3jb$ n_d{M{Ihy@utZ?W˶J{eOt+aWa'+oQF䨞ubho={JCfNׄ}* ,zPR B1AOtrz] ;N:-qRtj%f7SfaRaE)EF*y9<)Ej3z<=TES9,_T5Gu,5SAIy]6y6eݠ|]1'DzGJU q+ {GLY>{(d B`n߾N_oIw*}zF'5つGO75 ;~3d̛qm04l}FFxlxЊ'<_0ȊB]1rk5JU؉vϑ_TNmV늹'4?|zvsoQ%_GVЁN-E]ȷmQt^9tK:d ^/q_xAt ],=OȋR(ڿZEY%|r{ן];5WKB3S(1@2n%*D]||z{ P& þ4jl[=D}:'1ӫɸ^'VᎨ^5Ccͽ`B3w>bk澇BNJ;})53ysK蕵Wh_hgb)N5%;d72xk))l+Wa_d ave-Q5boe_өmjP=@HOIv$w/Q7pKҧC9/3+ct٣QM_^ƊZ^礰?vRe ӿ|þ)4' )fCcTږG[{{vs'LT*gJU ]|̜"z{JQn0y r?ZKS=ֽꡙb)BCSyQt:dF'doQ- Nge:/cՄ)6/ʜ. | K~9N.NV9t >!:B+ȋwҗgZ:FG[|>oW~8^\Ǟ Nt vv=a_IhjbL&6ի!!"ꮤ :/逗t/xIN}K:%p"n/ޢw~<>:Q >8^N%6O ;Ù@gJ}s}BGigl870b\)7~yh-XI S*nͤNI/bωO[ڜ],*aWa'fDP]LlT f-LI>zԁ^u/Q.zsې(~ v 1\ֽE&J{c)Ꞥ9&'zxIEp2n/Nȭt=#<,ӕu#z.Cj%߷?T  RbVI+ٙtGO'Y]&{ڟ]Ĝk?l'JU؉iv4Jzq)P(f i{9bs=B}H:#s9_SA7[h|c%4{IsQtɸϞܲ9mml뭉w䌲 m!*꼠N} "3"g&=h~ʪAOUuN lԘo/CgP_v6һBD9BO&=IUޞ1\GS]&Fq8q=S3*f1_SNFEn _!OV9e[t5Fv Ӟ^_ yVI;}(.uOYׄᄼU\DؗJ7Ct(DQogy[\ CaŴHn; |#j)R6EKģS7װ8imЫT2'AǠ-sɥjs焿\Q'{ NMN(aWa'*Fa05@[O'B1+X,?ڻun"B9|IK1֪h+u#'켤oQo+aHגH)zI׃c)_5RMS'T\-5ݔ#tɸ/xIޒqmQq*\brn[ ,m&⺜l}1cLHcO<F+?k`|ʼnԶiꫥvtUTA ;4ag:ZK b"8.FwdCgX[Qt:Lyz8vkk{}<߽K8Yohڦ)u}b? )vļcn$۫BC )U #:%mCƊt/ںy@VVI,wJ9[}ˠ8\CJ |X/e1wǨ ;swȶȥtK u>z}E}T2'fϑQЛ;*1шxvdJjfHIT$4 yqM}2u/_G3n|UH}nEXH~cz` KR(.yvvuag\zy+g?~M*ۣsuVҁx[!=F uG=&Anx9Yt^-{-!:Y$H)Cdn?#w~l|yMz2WhŽU!VF_nj~W2-ߛJo ӷ%2orɞt{kװl ǃ2~ۙ\:"xo8G/z:p&F?ng5M>zю{OtNJYa;G@QB%-J=r|wgQxj|FT|.]B.g=T ;ᚰ`AW ݊W?}yN{Յsu 7DG=E?Ųɺ&4.TNܜHKQ(Wȷt K{U4&]QӫˢM-ngOhj侲J;tt;Ir:GO13j`DF/ߛBgʞt߾ R=(lq<~.r8F<8)zaG?DSxŽcFIW95a?^*D4gR1"񛭉BsOa,=oWАh ;5VV(Bʱ+o -{\}@9aCFr&;m4_pa)O ;{P 5?FPlyM!kT(_Xiv_kMP3-<=_vSCScvva@kh4W(f \&'J %Y)YimʒHYܮ a_H`KǐNSS!/ƻ2\s.e]rTOasMiۚk:O.y,vf4Rlf#MqqHaGj^vq #EC/`ӎb@kV)眰o ;OZ/;zٖ('E_ː&cd4:|EOk#v8F价6 x&j1#ⱝhg}_>F,={˫QvC3GUL426U_aǹPG tY=_(aWa'fLkjU P(QH`@SI$Tun&!ZT'8n O k\տKJӝB5)^Kw>{ QʁCzȔ]q]/>b*욠K?9N^@ڿܜ .<d/:zÁ4~:%!Y׷Rdrm?'X#YMͬk ߶?a,,on`r`"|F+ư7=\s[ӼWGu>":t=o|ѯ.ƞ/ KgDNcvvbƄ^\Ɵ lRPŧ_!>exɺA5 DwUC+SH CCQ2?^2#%&,KqB*!FaolBnv<~Kw=4)Ye܎#W=[\Ž^59 ñl@Et"zr\W 2u Th`pak is*^ST#.h|%-G {h:@}eX.Tu|_YBҵu Ugͯt1bR]*W1>!\~K./Y΋:rMا5aov c+hot9T!Ay{e;.tVipY7U\ݡ{uRk_p񄔘k2>d*(h#&ERf50PWO_D7=JCy[ߓ.sk{dĜf@I-=SPEb=^qcae?u zI׃򍸀0t=(kyfqcfny焘O+. Wudžs8\06E,2Fϻ&(͘^ܦ3՛Ǎ <']KL#nNŋ6:ıZ8$ڐ2|n Fy撰vQ\e:Ndl)!Fy|ynz{WW a_u z&/vh9]1cIagDu`c*Bm˺`g#FA7rZTǦu܈&vD} oQK>zA/L/`<]iȯNyOGn_z.Ņ]S"J‹ST)O,{&Ã.ڗEhl'uz~Q˾f*{v"wQGX ;a +^̒q'B1v_Έ{FGݖ{I:/ꜘs`TT/\'S!+^/q_xIt wDt OQwE[4i__pA˭:}Nmtf,9 7E=޿!KrG Ẕ̌er*4j|.+ԓ@dt ^'V:d ^5Ep2 ^5Y r˴.M{T֑î8Uw%%;8Ņv"K %*{® 3!<&MRn>Ί;8!7tٓq+xA%p2n/N}K:AQ?>hS_|x&S3ZŽ3[uz=<[2d/t4L ȣ!Zp@b.f1vEdͦOܦuROen ;)Gn0e}n&eoLV&Zv~iG|+7I]=KƦ a*%*woa:qJ bv {}ˠ˲nt !{ԁsQ^G/:%]c:D̜?K Oj#nݗ.Y/idיtm؊t(u r3-ˉvDiK4_+mϦ=ɋ{Rұ~p(>*~0yP&hEVw[ѲRT3_mΤ}Lzד;aee {<'V(aWa'.FQׄD b3.ў.s9ۥxM }1W\tM[&zJPǞљ- ̘?-|mi1ӽyr6gi_/SkM=#3kzqj]\ kKvlK؅+Sk MYEp2 ^/ꀓq_xIu9.cBO\9ۅ}{WTޑˮw3%383&=q*E%zs25( 17ဢ4:xoqkJ_ m?*^>=}=gU®b.GPL(aWv<]?nް- K:%p" ^/q+xA%}p_1D]cLgI0ik!z)Tc )+)b :p'VuK:p_ԍ`yCv-RM{xE7-00~1vaoN9?`ktJ iJs8m 5%M ;ƗcλP^sKq[d[cPRᯰ'x>8Θj[b {~)aW15atѡ]1фA/Iu!߶EKyQd ^/逓q+xAN} :p" ^5ܓu^5+FޑT>BB3k(CcY89.ޛM9z ?@ȣa)jlW)S]z,)-b#i9ƒ_ٳɚȓ;v_Y.t ;N})1=ǔa׉JKae{:f֛Nԃ.3XmE=KSS) G V XȂ2|n1,{4}lv_#L0ipn)ƻ;ڋ>)QyAK <_ZkiW"9 m3[j~y68t<蕃cqUׅ.`'-:З\oS2(1-KBEpBnxFWC . ND|]1a}BWAYr+/񅙨PY RI Ua]~.wʞXN@2t3a`/dۣ@r4'q1%DL#xP6572e*;-,$N]-5[r\l]U$,$n<$~߽B.&VΪ9#j?<^.E}cT=e JUpQ'D&J/aCѦbJλ F1}+FqnZ\XF^[ -\v=P3mur|7f/.JUP®P8dR[{:k=}#t];@U4|v"AzLI[u1.J]\ iQ®NKEk9N2c*x6ȶvE (aW1cz]'.JM$nU( ȅJZJvE (aW1cz}B\(aWv}򜇬g$*ߟҕ}t]ovE (aW1#®#J/aםZ:/z \ȯ] "sTz={IwJPOZSeQ®"4a7 %َ.Hm pV( X[ ?VަG}('%mY2(aWp]؍bvl13Y[葪 PH>yH3~GO5 'W'Ҙ/VW~WFt]E05a˸+f;^.d}HYH aL^Aa^-K`e{״2U1u/d-q~j鯥5j';)g߃nV+mDqFyZW/=UtXѾ喝-SVkKGT]⵮:d,ڝk`sLcЈ$/R A8nP*6za?)8 $p ?bi$V]_gx_`LVnao: whWZq>Y?OOi[W< F(aW( {{o'JY~(@|S1ޮWuM:{YGNC/{c*=IaXGmlHYDuW mxB>,d?X+9ǯ:mq_ұumz<ޤ%TԚ>aon I1@Z6{JU#+G .?~(;d^ :zC|Rљ/7Uү)?;=^B얰G?/OfB‚LJɭx㱢-. FeٓnSfC8e ~EKoꯑm4#\v*=-{=M>p jqSkd^ `BWE|@tr.YL+gL<nW_XGkD"zQzcq)F(aW(2%Ó^\Diuw` ;zfr촜aR[ ;+Jr:kԻSF}ɽ]~VHJoIž#'2vtλ )WwҝwyMIr?#B_m5 ? A{2&Rs^ ͱ +; .I]#C*A c}xa DŽ)J68iksn&E;]+Hhm@r#)^C<7xy8nτޒ:௰~N?ZH}H(x/e7ܥwlbϋD `v!FayDY:e&wp+N\D'kŽf#M[:P//+%hOt>wZ8=~b+.My8&lVqkqjo_*. G~8qaG϶6PseܝTS.}RyG:^[9ax#g\kJXH5=-6UO}"Fmskx}S7qс6~&=9Y Y 'm^+i>sෟe91(aWP®P8d)z܇r0 ;xJV "nk®f;=Bd{*I ?p3sr\4I߭bݾ..s/iG[ ſ9aG~8I^L-xqLq_D ~2c|`&VW0}etD^pWnp<裳G][ P®"13>:{w轷Gυ)f3>z&-z8zvq2Z&-R5aח/ 6Fayȉք9\p0,(Q 3~FNsv@Ko)xw[csž^-H/s0vp@wqJ3aǾq>5doclgî1ŽA܅F ^\MCvPaK9D_7Ҳ %I9 (aW~a>קoߤETB=m驡pQq^uPjXߐFs>;UbPA؋reo&w(聅i~,o3hXJlh״ ;^r&SR4p_Qޑ'ea\^m٠Z& y]씶e #C?z'^* ڸq#cBUس- T5_G]f/V9@⮠9bimr"/';P®"1}>!3-<>y>Rcy=VT9JwJzBV;Bǒ[rvŖRSC!*m<:1>z==\N+ʅ]:`a&Ťc@"z0b'6"u$6R RPX~_n ;j(Ȼ*$b*-Y x+:rq!nK XexWWؑ Añb$;-v<丣=J>;2>Uek /8BU%~HZFrt^|P1k8$^Sblvvk[؟]B/G*Хo1t7+hAݥ*KC.j ;7#E p(lu:WFqK@Kɝ25^b-zQ‡^Hm98FJ)"+\=8 Ezwow⣶yBlQ=6BoH>Z5$m=ZJ "{"I_%i%2!( TÉ,9.d?R6?G}J[Lj_Np-3V(.z+-Ӈ.&P[,pUp[@ `Dp]'zY a܆4Q>+.gwq1ûO7j)ƞ7_ƲS8aIKJ'هYR%승vs>OO)gl2eȔ񋐇Brӧ:20ƶil'45:4 Ж; ~сfsHzq'#(vT%QВLqJ{r(aWF+B}t ?H͟DSOYhsvw,ramlWO>)ؑri.{t}{=WCY7:v|;7Δ#񡢵 ]dB9ϑ?:>OKuIk99,E].QT:pZ tcW=~KDYjʰZLk i_^C)7|?=WE hj5;8MNd| |~ X]1P®"Ꮀ_vN͘a:!L2F%@Mz0OϢM{GuX fST+=F~^ixH{^:?֧PF] XFZm*mfQ® (aWpM9)7ѴNU4H02}]ߑM'%NO7*ݣe_oW \{ H{}/-yu[ qY}=) \)Q2X.#ŽҎPh鵴֧;w!x"UauK. N^7P®"1h` s gLKu0 %4nҨx=*?Ĕ5Sma5OldyFN5]b'F+(o4ۈkſoؽO3v ~4 MO|@ץh ^BV~9[*{[qPRWI1͛te@!_ul=&g26 PR 51>!B1_(mˤ녇h ]n+?]%QA쳊Ц灜zWl#-X))E#:X*o/TҶF:N%ÓǔTI |O/Þ3v ;/޹Cg%Д $R=i-^2^o>ˢZ `ȪUd@f11rvF~U/t>e]HZjx \e.bY2^t_EhF6 '$~{}Z$*/Ov%*Av^Ѝ[4=g f?tQG;r۹N)nOF/˲o/I58c:W!j͊l%MۺYIJWDzWPjG D؟_GKί2vߊ!O|WY0w_ϟ*9/bC+v%*. ;/9)J̦:PB? Yu>+-;թcqOSx~ro?>>a>(g| ls"Eg'Ӈ6 dvWr:$Y#V) 7`ΏE `΋J1]w~c5HJtc$WVp?F^;GKdt ;D]c`djr>n8~1BzX@*8Eet'u 4}ž#Ӊv%!t@ы::Y;1#qT7HOG_Q&#q& _m`]/z(4K* hxlT,dž&/`YSavR0 ڍu#([t]E0b} cthnVĤ?V J5n(*nM" d` ڕ- E {&mG9H|^k+񎝤(zm9|FWQP®gwT}YG:>ŗ|O;>Maov^ԁ&7$"lʠI'%RzxUSO& z tHm}TrΗoѾ%r5̞m/N}u6o&iLRQk(>B;~î u l4PEXn0ѳVe/kϣn9Ξ/Ӂvr+YJm=0 WΘF9cV9F[i5/qvoAt-d~IP(B₲.Sؖ ʾ`N#<{n3`EW,+bL;~5yq{2űiHGؑ'N[t]E0}agC Ba!/nKSv^ԁ^ԇŹyZDusP6<#tXj꣧_|d!Z ;RnZs뿲i39_љO: >VGVxE4ʼym_Vw~No~*.˚5"*~MAy*Ǚ7<' al/VFi鏘_a$|-7-}{LJU#vFʭP®S9J_=S0C**h羰/UKC}3PB8SBGi2sEc_s9ۼvQuwr>ڝ= Fi[XN=T]BJOѺQv;0e%eRCos4}r&ZM7P}^9۩MXu7USfCطayL.g? fֶ ֘P_a6O ~!윔[]afQwP"/2[˺iT_<5B1H8[J׶fI\t)o؊KZA{ ԣbϣwyJL91lNc9YNwzO:*GK`FqR#ZH|>"^1AN]-CXNX$%ȴcR:\PF'3hH{Dǧq:k m;漰7]0L"rn#%X]܌ɏޡ1!|/c%șFm Ͳevy">tgҮwo}A^pt">?xO;zgPe@` ;'~,SMC uэ]9Rao"%3Cέ@e8n/{N{5MwO?Ԁ<￷T K_bp {nS~ڳiw)LWx #=ÏSSbbvЛQ;)1ZF;f3&{Φӳ̉sA3#h;񀏙NV0TR"v?Tӆ^VSFx}2&7UKFeيOTd>I@:&Z{ D=T E̳%sEѓ7r)nFS dYʵQH1nl`|o[/SSaߓFz, Ua~ ; -{Щ[(jqa{m ۟e\ ;1c~b&=?`.=9rc;!oqb#|_ϊ6s)ls2#Ze^Glv܇4@{gӍZV)=ŽOO'WsǡP~ͧ*qέ3WҪQI[=zٌKTkM."$r^o?WN„$b~}ݡ."LnS2__Žj/[4vǵѳRxc3. 6Q[qJJU؉av沰Ȧݞ~{t}u&h{(Lk#})cuտ>WAvJ_zjK!)B1_K?O 1Ц[ꏔTNY q⣲Ղ7^k<#dbPrM+U+vYڙRjo 18T÷6 ;z7|"ZUߐp1o_Žm\_a_^+'\ia_3::tL%*Č و9%͕tXZ w}wzZɓ񟁑tG+9ZtfսtZ=CKӴ1a/IjyMGYioSYjǬU}><'R >O{>۠íyӳWcʊL)Oku=fsQA?ڙA>-.puǠP'ΔRuO32ׄ vi)m@=zn1eT6qS]B[>_, /o'%1/NCCb8ߟPj]Lv-y2X:٦6~*Sα UL ө0C ;1c~5?`:}v)Ȓ}./\h[O|],ڂN-ۿ7oRsED)aGe2Ԋ$\v4 }7uSwː M9*ۨA+@űq#|/ݧ  >+r(ǖ$IRtHU;c pnM y Աm&ܟ'.<*t$gmփ(x#-NyG %rux/L ?\]1aK-戰 DȬ~yD*z!-z!h)1H59cm-羽 iǷj%{)1s@̓Ǭ f>mAl^\:㹺+V~_ӯ_Rw{ | *2{dMz'ܟcCS<~r*aWa'fL؋je)M?ə+mתvB67znI%'&h¾H)m L!_)ju5҆(;FV8s_+ݼ @ $=dlǹs<1T05-t,a{4N{ÀTw(s r4έyo.xW固ɶBYM7vfmQYd&gިynYUd/szj=!~1΍3 [M?.tM9e+>ƦfZ]1aoW'Lw{܉beN7@~6z!:=K1 G[g_ /}ibZc<ș6KYXm :ur_ޘN5y}kJ9>x(rm[&ʼn( U\hi}t[^imrnȔ_*AV҅rZ)h4;צG%Ph:m<%_/V+q`%HoEvvT  >Ǒzosa~F mzk2oVn绷hH9/vRΊ YcP> rZ9Žy99^dvvbƄɓ[j/\P"6h՗tѶF\um/a«]|/dk18W!]XgV%LjylܛK[^RUzڑ{in㪰x:}@wߡu(s6 EmYV'59yG<4+=8~{wOLur܅`ф}DxrmcR6:N3䅓~χ~E~}C| ;8&E:ǭS>6G.H;zWR[L +,:&+3&mݴL&{»t ;R;0 S+x]HVg -Oѻ)(xzdEERWj>n%hmvTAEc &C=;uKp3Uh hi$$W>[QEgdW3[Ž_H6Hq/Pǭ۠F-$H?Ѓxyz$kcȶ@v8}Є3vS N'c=nk=Xn|/h`-!,OyNQo&ƧaϹU#)al=Vsk!8V&߼L iTSg^C ;1>2:N_'LC6.nYFNjhPIeܘݳ4Y7(a{ELCУ'QNTXHVI~CקIϋtCoT)-KmGy7zձ . beO*nVu\Zd圼ZYMU;2N[O؟J 5vT=ܗK]U&ΌSsDR*PkXܚd:.#^c{)XpGF&xzMQc6cH1]tWnǯ)S_.K" ,U ϭoDLx?@N{niv~IaG~@ ;1®ɺFfV6?eSb҆Ǘ$P{gJDo_{W@諈 G5qEtvk뭀EthYZC';L Wؑ:6}b`*'yEH**츏 j E;n;vc.3SŽ]1Y]p]9)"5"(yJV-욨k UJvo}L{AaG%M1^C%C2 m-x#f+de)KiQ_aG=s |F x ,~x9SNO.Kj@nK{Has1Co2jrLnysE[Wk¾7i 7_=I3%"shh JU wr!+vkwץ' (aWXᖰ+[1(7?>!x >yd@g#|# Il{X;rڡ!E[rWF5cŽ[J/8ΣtNq1q_";.20xS8AېXv{TsEQ9 ##sMC:3(<]-8@Qe{*')6WZ,K)4ޥ[m{h/[]Jwzr?7Pf} =x<#aΓRIӔ㔙WVPzv!=yʑvvbƅtv[B-r'3&]k^UL?FAѝPuJ۳B+\i{_:^~*V\m҈f݅#k{[}}}n(kϡC?E/M*n2ӭha|@aBvF~:&j̄:A5P®N̸Q**w{ٕ+pSػa=Q${]V%.PL7)l)|s<;͌'q_(d)F~M&fA-p\#\5afo\QUHK)^u5*h1I*;[K0X/;B ;1) bU9BIpCT20)ꏟLqt]Y݄b>UCչ:n3IJ73>ڷ*:g 5>yHV^vLt$=!1V]љGh[ܗ[qI.yp4qƳ6hGǜvvbt=t,,}C8A =P-p2n;Â0)uڢNYy_1Gxfk"sL 6-nLā+sSbV\!7kꯖ} g_v#g{2\A61SAsW ǸmfIk2Ռ{{%k9'ߙ$&*U\;>y 1MHiAmZׅDv `L4v7]í6~ @uߝLu)lI[Ǚrp~›%&/,M9qvv"K}Cl08nϣk[34\M&7WtLH+uc%4Rv`i=U"'cVx6WP™R9|<*{Y!/c/LJZv[WaeԗvSx͸cP( 3'lK&Nc|ç2Ռ{Yfj AYҖIӶ/LH[)&sӞłhݯeE{ľ| ; uzaU`v&,"`Y qBEt %2;m>%j癰vv"H-v.o-~W][(5~OKYJ6^|49" }KFS3%Z"eܐrѸ+[NIYS09/'IT.+:u]jRhKw y|B}%]xgAxK)GzǡPuJgE{ ,KΰIK 81؀sN8䜓'眳ù+gZR59gYki -m/?Dپ˱2bvTy~/3t:eygWVoXgK'zŽ-y,%Z#DL5ŭRE}V3nfZI!I쎰{=7ghVحdX*ɨgߋ W;}nPVA8/zfߣ);QY3 01Hoe#n3kc,cK8 PHJɡ~a+S&}|*I5Uw%w>DYE7w,#? Ž7~ԣ,~K zn{zvM__@TڷwPyvetujlu3 U髫Ԧ~aܡ/7n >Soα)̻J/}?M9ߟK? mr(6'HeG(K8n%z_Nf |qpʦUo\C['zы~lemͽz?zwwQ?-`}ʋ̹3 7'׸{hglg$*x{wgg"?Q7q,pǂ{O0^E̩:26&z~zl o.=J\E2D^Lڢ[zO<ԹwT]IDnPZ^Me+&\?v!} }K'hH~{<Ŝngh;a,hya=8N>W4z U fIl]E/$O|Z{XY7 oji%H 綛SAȃM90KScl.$ TԘC?\t> fKN8Pap*VI7CIЦy| '32ӫXSu}~~K  ^ ;@tbu]T'QsCcvoN1DURua 'eU #yza{~\O/+af@<KR٠qTI/~ns'iɵt'l)^ a_Mmap+젥CLEʸ7 fy+TѠOnS$ᖖr 8n}K[Siѿ Hsuʼozov<#ˢz73ъWNy}M }ГAW2^+Ru0>:X:Iy`/P1qWB80mHoR RPޢs߆Ou3-=#%ߥξv.>&ޓq\VzkAYcr8Zap#.윘Vg+O0^.YS WҎYX}{]{ܻ>scy'PY[} ;1qcv/ԗ \HG?.*6}NM}''ųVq^r1?FvVۊG* 8{mG:$԰~!t$ Ҽ8z<3k0v_w7ƫmt"e;IWdO6:Fm_/I>4gc1K}ܟTA]IsB,>|O޹Ķ$VJ0 Ӓb=L)gpja }z3auApFә) D%Ĉ;'CiAW{T qE8Ѽ/ы3»d5$Y%oͺHSߣ&Au3G!L2mG*ʳ0Z;GAREaJ(+g75wJ!9a$yqV:@ MK]IU9f:q91_.mq)L hɛgiI灞9fYuA %,:Fׇg&ua̰t{,.J6"N", TT5I!I\nS)7\ӯSn߄A +vS`FǾnGA;[L$`Ⱥ0f92<v 'Ằs&}}`@O.Sm n, 6NPI=G/OsgUP׌{̔wq;Tإ޳ 0K$d4oθ>u YQRZ +K8 ׄpOvo\HO߹@{WPNte. ̖|̿OLuG|)i_Цct?ꚻ!c~J+hriΟ欋7g]&U߬{ wXh:{Y`s,XwÙ4,_~ahlWؕ@Sܡ'w)`0 c/WESJJ \gKEeVXn_>B{QcL2}Uɷ]]4Ӯ۟ =;"=dG>/-CvdXvawWuO:"Io0VqcY_$K81+%UTⰤ]裝>@-_[()5{`̈K81/=T^YG{$ӫs(C]` vx=H 0apc^{z=T6ѽdhi4[)AX t>O៺1"NbL !V[)6)lB*@];&CgRCcV0uWn[D;N?U镅q춡 s)lK't1SsXy D%ĘvNQS@'ҏb]/͋wץG;-X}"6}ۘN/1'Ѵd"WTPG<"NbL;'N+(y|alڒx=+t+|@] wW펧dJh".$"Z9fNV].o,7#0RK8 w[΋P$9R;TxN#^/ޡr$Kw(*'t=XAr+} AD]ID $Gp^ 'ɑ/Á rKw(*gD)oG XI7x{ H".$"@y*$G p /ޡr$ p{p *t5KSԘoQj3 4"Nb r$p{p)*t'ɑ/ܡKwQG}׷ީRRi;A@]I (Gp^ 'ɑ/ÁIrKw(*'}w}5~ Aa;8IxxN#^CP$9;xdTv7/>W,S8 qK8v^ 'xfzXTJ əDQ1G1 Lx֟Ifѥ vA& )K%T@== NÍKw(RiDZ5&C.E?E ?? 0yav4*&~Qhs;cЅ/Z5D%DP0zk['%&gЦh"  ʌߣ܍ɧ~VD]I,t!xݪFJHͧGKc & KϥPiYu"NEaP0ܼ|~,^W(AApɲh|+jjkY."N%a`{(XEe1SAAXzcE"[*})>ܚI|-S?κT=q~G=_Tv 'n:#^ɷ  7W'yܴ&C@ԾOe_k8OʠGXv '1nuPYUC;dP  `s&M>Y2Ig+^bnl&uuw>TD%ĨU гD,(S2 "oJIH{ad|(@=_EI"#.$F\9QYp3EzAA7W*YWkߙk,%g>D%Ĉ ;'fe+s|+  S^[JϺ\_W펧e;E]I]997yֳri2  O:gn\/n^[v"d^EێScS3+NapavNЭ5Ӂsl  /ISa9GsK{޿tAzNapavNHL+  8y1^ SjyGNui_+kd "NUa<fX/  S\`0 {k#X=f{6ucC]]I"[sB~JHʠJ  !2+]ʵ>x$z:[C.ϳ,zqvs:?!5aolj-G  NyQ6`Cf)~}Lx(˾v D%Ĩ {iy}L\A!tۍUI96aO{z zӴؑM-p|agƘG}_3"NbԄ=1~A{,ܕMOԙJWcJ/j_g7\O6 0z8'SHM=t#>VUMU,լ&f^_Ⱦe;⨡Gȃ!.$FMwLW^Ţ]9s+V`B@=O(3-b.sk9|6_)۳vs BdW6`Ԇ巰 e+.raojnEalb>%m0_}0_~nꡏWxNt9eD5e]s .^O߯b!. =f߫-)/jm&%NTr a/,.~aaHK?Eӱە:M vB]tN Г^O}R~mH938c.`o.3Dutvf0D%Ĩ{R/0^&==5ߏ?^KګN%ꄺdwކ<~^݆8=ѿwk%٤OاI/Л?mY5^x:<=hyz ay :WA7g<>+zqǓ Zkg B/̎ԅ4'f;|Dيt }\`&⨩"NbT=.!ޘA{8vUTѯn9[3i:;R@?Bji@V{⵬jreԡ$X@L-ɞv[ARcuGO^ﻨS?o\g9SCEȊrzQ~s/ø0a輽6k3U}HͽeJL1jlw\3~G 74 ~0D%{|",3¸_,٥q@ta#opN޶o8+Zcgy=\Ġ'T< P|_Ž}2K}'OI|qM xXIݏh(1ZgBt> ƫkqSvvc>z9^u y¾h> rhzTS|Sv '1*DϕvA/8SYk^Zۭ!d7i5>j;ޯA l1h|8J]aOLɢIKDaL|fYs1!dƟ:?r#yP=buyY]OWc'o'l\0cʼnB#U|FvA譵)x zoc&\vO D%Ĩ{bz  9Zd+zhw#O9m1s!UuH^5C^}c'q7?)a׉c 4_k0\E!|4rjNa 1T[|Sv '1*^UUCse = aXiߘ>4S0G,uba*FX: 5Okѳ"i/YbZ,C1E❔ZYZ뺵hvB'5kouhc=`N}р ;-TREk8YHYj^E!|hL8OPd埝;_&8A]I76"0^0)/f:p)N瘅GFUy!}h|Hb:-Slڼ6\yl\1YM|;^~z:uϓ; Z8kT.cv>n, "~5e؃Pl+SJƈ {_c{DێL&`GA ~( QOo;/,U+X(g̻ ))% u!.$FL!fS ] 2J_[@oJH5x#&mҫ*^⨪ڳSD%D؅*eUɲ*  vAŹ1zce"&Izi~_`}dMMrAA;`@ʸD%D~;:SeAa̰t{g"v '1ćv:w#HAAlYMiY  "NbW Z:h8W9AAFIK)6>Yg".$FXyQ7SQYC;{ ]At~:uvw>TD% ;/v`3גeiA!BG,Eǧ)W~Ϻa<t?.~XGasGA!ܼ67V쌣z)+ޡ".$$켄ǔW@ҫsJ$ .>ZMgSUMD%D^RhTk/M/͏ח&Ы9~ΓIT\RB]=lpQ;T Y7qok Z?_W0A&/(1ea"-g:MږEvlhB=G:K2Dy" 2}}4OIiJK8vNԭ=ں&*,.|r,l)kcZߜE/+ cYQGcEqZXEuߍi -Zȭ2nH3k+O$J_]@//b,\%C[>^WZ_-MB*.wfqa u76RIiedPlR&݋I{Qt?*N1tj"Nѷ2coc)#_y0޻LݛIKѦstzݺA"{ t7: E< Kz0D%Ĩ ;'n?LȹFGOz(~!̅ GO~pn[c֨ T|&e9>=p\qqq1~`ΉB-]ӥ@X? s)*x'ʑ/ݡ/Ak*{ur\qn֩;U+e'qd`]/5G҂3E!_@ tڋ9#dmTr=k}E!4D%ĸv^/Cp4x /ݡKwﯾOl a!WK!^Iwu 4 DJ r/5PjE0zfZQE˫xy-!HM5]ش<.}^:촚~c\K^dyF(zJ\a,i`JJvYlkB!.$Ɲ=;T8I]8ڠa%N-`ܾtp5PWXiJcu0x=xR0kMIjD fyXMMq>M_ܦZ7̜,UAWc\Rг.=Ř=Qպ's{jr^p1݂# 1,F]}2 M_>^10apJy^C*#jT H;;x3b"w 'iX=J{!V߮'$uRo~%mzCȏ1ӊ>PcNvG=uӫn>@9u~ZNJ=8 xV}щAH^{s71@ϼJG>g"AwKtYyWt v '1./ݡ`={Hs(}O+i~xl  W֧;L.Y=H[@ϟc t$I)_c ٨ s׵i> wl UgHZyT/$;)껏z}3 +xlpG=+0OGotzlCUHliSNARՀ\c k Ӟr"NbL ;/Áb'ZU%ǜ|^CE䧸Z;DvF9dhp"Fb{. +mb`!BD0@'\}3~na|W_Uu ʹJ}+=0y|k!=Q6{w EtBbԡ28MY̦6{e}Hf2}kq<Ϧֳ"Nb ;/ܡ‹w(p=@+u<>Cy w/ܡ~X0'_&f:RW\wLϤ!AAinprE2z'W]*?oU^iZʑ%B&63ѫ ;Nfu[v jgz^n0 Rlp1'tTÁ|7Wu\Ta.{r4Ho/mD%Ęv^/ݡ`葤[F`q=e;_CEh%fN3SZ mӣb^b L+\gz'KHT> ,]>J2i=Ґ]u==Hkpqc iϖ{ύvB !HQmƱt2rur/]D%Ęv^/C{?p*%-I@@T; ^ʪҹIXb=m[EkI=n Nq䓢w@>z'?!;zKypg3>rݓ N*r-6@?.swd̈Pqꏛa `/+w~0v3 <-}zEq8ÅV5FOkCny_œbwk zڐF~5]l*<~3Q 9L 6~!=Yўѝf]upB͠'gFo<|T}WʴHsӓnnӮp͡OTv f֙q@_`񨤲v=`\A0'R cv 'pPy %Dc(PqCeTvRtai:_GT(0:+x Xwn+\<v'NA9SbjH5չ.љv:0V'YI2UU{g,4њ9'AgsV1Cho#r/}0ap)p^ '# d6M0n6:RN|HUA3fb { or2tҋ=<FZ'z;2#qe70^w+19Ͼ@^f`}i/6i\OԵHAœSfm yT%JF[?.>y^3nD |a .$"Jy*fi-]/nMS'QʮkR>P'lҟ7+h:i`5LYFR0Hr!m|܉p!ܠ-G[B[VzقAhw6͸iӬ;(/D>"N""KPyS'Jm{Tl;ޭr Y.BF'굌c*Gʐz|~բY8ABX}37Po= 2';d8H3<Q G} N㮀1 zڄ#;#o@]I=4{zZ ҋh9_>ݼ-\xOޟ2y_8IdвilEnjSEU 0TYBnЊ ]x,=_Buߍtr+)*3iTgsg2=Y#8Hi=wݯJTתd]=56PgWrћ.S]Is=Q}}gdӭ)XG7Wc迋Qcg#%93pK&wc:K2<^^K/Ή̍o? +KscIzX9>ݖAo/aXuU>htvy1xzkM2{n2aGxt\<|)} oE-kbhX6&Sfv>wtRND%Ĉ ;'N:=nIK??FʿgܧpWqgq^Yw $dí_izg]2k :^_W>I0w8ĿgS˿g>PmQn|fߣW*YG6Co5Y}G>x]za}zyAQo&(OJl6 ?`Pe•U(bU4'WW?~57D%Ĉ ;'ChxzuN*Wߠg&Ԩ҂4i[ @=X-Գ(N?2,su"翿117gqƖ0~KO{W^,߇zYKl6z܇Ӯ__}﮲e ]*k1e\7[F74t#n2*4A wRmgb^3`@'Zm[IXl+Ut'zIDyTI'n>%k-Gg\YЮYtj>]zPGu8p G1{|cᮕAq?ł:^`c#[lg<;=Yz>B0 f>羽B)!rMm2Я8~̥!c@et$%0;uVN~-K'gUyo Z'Q9/,;菱 :]AT[-G A+k5Q:n>A߭Cn^7lYF(_]'(;3s> ixz=L5j-zXBu]ܭ&j6C-zL; 1HGA˗nG5gq@#VWMfG#}L?;1_{`s5Ytr 3q4 | C98 =J_?v| |gq+wMg:I'Wb >o=mLܮ3c ́~#Zz]ߖԃ'OC zjo;zQއ.QUM5,osY[[OsEOX2B껩+XY;)oOYZFYc-).PVL9ϖe$tOEӽ4uLY"N",>XCҲ藽ln㛳W5ܸƖ<"yw"Vkm9f{H׳tc?z Y1$+ב83ݣcIs(qG0'MqT㏣i.Zrgt-ԧ-c끪zШ(mIu\1ۦ-<]D)Mw6V=0ׁ@e{;!´t^1{T>mA{ӤaK^7|Qʼݶ{|DIDAT1,=XփQ?YHwE_;˗mx`ז&+>ܚI?ݑ0f ϱ>E3T][>{"NUaȡEII4}oE N>oWml6[}k틪fn+%wr6ַ< s~o's:<;"}k\1 v8CNau8!JH(.!oz{y|;ij+˩ꤍ7*B 1-ԦIckV@n.`}9ϕrc쎣H4 EnDZ04c9{>zФym;8;O뮖ѵFi XhփZUnιx@sS/5uY;0Re6;W:^˽ە2/l(ﮀe=)k`E[cx#l+2Bay=!Ef*)-S}="Na?5|aR3iƆ8.0?)bOl[;Q`椱V j:i-l|rlܘp +ߑi7<DZS`q9cDԹ8aw7G) Wʃҁ,z𰺓m7mʏ zf#>hog&;ۤw3N, .69ݴf^ڷYpr+;ҍe[ޑq0vl$bt #-Y:uuz a}XNTp)f0,3 ^0<䆴%rOMwޯKrrr3`]grv^'`| 펣G''8'M3?cmoSrvݰU>m3.}vطeC#_׃vM?1]I;wؖQTj.k;p V],{yM͔oy{/FyY:|;mv_^1iojic?SD%DSԕ nz~ٗs'7bF-=66yz_/>UKyZFSؑ bgձs81'LIs8'L3o>y"c9"e4~'GWAM9\)uH#Kɭ(kky67J)>L?v8-o6oy^֘q%7߇oז(YƒHys͠c ulBQ]I{ή^y?ޘ7fCC)lco4On}gɬV ]/H8ŅW'M1 |=p4 -rԳ(D&}wޞ}IOg:zЪK,lʆn: - \ԃ Y~ܴk[PFyg*ct5ASރen.Cn;\~7ek f-iOw+kOGSvAPE%( 1bl#3S.ІS|ۡ؜ssCe)=nhG׃Vvɢi^i`h~A {#[FY[܁^,3uԨ^?^ =xaQN;ymoԱszU͖ǽcIl_ͥʎգ=ܾ~a+&21"NbW 2 hƆϷa@C먱u.xs'6D`~SC;ؚZl=N*ZZ?Y7 Ǒ4WeݧxXMgS_\1T"IZGsr z,:aa {q,z=WuZ26_JR6:H:77J*ўb,:ڜpՃ {FA#[|YۗwB07'_25W(AaJ :sHO_{ɕ *lφzͼapP54}`K8 W}՞D:kwn4+b`=4W- Ykl([C;7Ƞ# h:&ux:rp8aI8Z vOO\E=|D6z``Ckh_Ѻ- iɜu}KH®=XmշuZ6 _ҩ+t2}qt5,,N؄}V>Mt`Xq f3(yUM;W+epKΗ7(+:K[\(+";-?oW^n9Z "yck̀!hdoƗɪa}cE1J/ZVBuɧuSX X%6ƧJ|Kf֓1&#3pd# } J&DiZG̒+ 0<mٶj˜CQȠt 6Ul;A8OY;?q!}/@F=p8^ȥ8%-Xu`8U[ |NJ ;Rۜ/65#lnX]]ue]ԥ9Uu.jn|:v88Y=Db7:҅%b[V%\y`sϣVߎ,ŏ&W> ̓O_E'nХ}O#NE ^_F C؇zrip%jL)Q+4(WNćL]D -tV!}۔zہ [I7NPWkEՀBo'V~ǜ%/k=#x;!km\#1\"MzPǁc8x z`Y#8#ѣne,[? u-k>i^ߔ4_8_6tM$zh[,%z}d)UQ=}WMCў!wM7R]w߳6FQ}r6ϠVZdAHn-kKy#%Cq!G٢JPnh3 Koҹ{:!=fzΡ+y]KQմP=.Z{q2 狻X&^Шًse5\%/Ή̻nOکq6cf<Ͼ#^[~ڽ;m.B}bǰW DS\JGa%>nhCzEImPkapU}2T!< AO!whp!U y/O?GM®^ W+nQtznrm R=p{tp D?J:33ҽfƂL9$z{a k饞'l1!͎`pVkaSt[c rDNP_17##\ŕ QŽzWB7E;z3B?mC,}I㬼!!V? C(oKQM=gll7X_alj|rXYꣲn#nBÕvUn09Y70ch0 JHuH6#*н>qz޸%Vah[ciP ѨK-;fa羣#P=q7W\F[cvHkuϻŽFZ̋ߟJF%R<ΗE ;qprٍDZUi[UvXzI;0؋ -䕶C}bǰ|0ꀔ8vu Žr! .YC1WbY؟RTZ5}uiGu#nH޴_E=' A1͢nGLGH{;|nǺTTI [Noja+ٚI/ΎS:m}GU C6o[ΕoWEͽQFwk ց`-yx=ׯvO8XL"1%MAڜ^~;ʗvUFY'L8e9Dq\v;Ǟ˥zܲzoQT=>u@Qw HA4o~Ym7M-E?)TQ߭_y !: /u@Sivk0u¾v_@=@3M`=Ogc<愽ɦ;Fkawyݷ a7ͤ7 7R'qv :SrKՅzQ_PmĴ``,uν7b'|%^;em :?VMN>EOP)Ďa ;O+C s+hL/͓U##tA1"]N+ZhΟz̎X=ҿJ5FEa/qľW}PE+.H'LO|&[r4daP=z?^HM=Tأm6sScU> i)&]?N̝{wHvG1 UoC؟RIuj=}-ڳiU4uysn0꽉z5f$)a1 {(m-kG۩+u>T؃d0VGߵc8?,OTy#jlUkS ƱIѓ'ZڍcµpdaǀSǍ' VfN=HV!~ؖ4]G8>z`>cp<-BexY Bў!ӞA[zԬ3؆ f^W\yۜOygطAY߬osp|Y༃qh(܃xNaGG;籃Ow%Χi;F7Vv s 嗷c7Zma1laN9oubT7 Ck`nlC<Ħ9Q#{Ҵ;p|Hvl#VJ}y!3"~5'K8>!}ې]L؜G C az CfawrpRޞ^u#)Nzهhza&}th=X wĎa ;zz^iH}ˈu?mZ>\ckБHd ; H0}c A$ {㩼ں\rnt .=:z<+0Oޘu}fP[ {Ε5}YsE"avKN΋[Xs4hg?;]]gԿĎa ;L{U7fJJ_G[D;Hv;q!'MHv|L/6gЋ^- ]w팢6zI^\ i1{8b*}_)c+u> %6_r\-yYjH2 AWԃ {-=v[qQ,.l?7R]gѯ` _ KoC}b+ŽiLoh<Y|b .xkl`mhQ*Nqx'L8h,foS0b_G멲ǛL.̇.=~FpLӈuO U5+&}PC_DX:Ӥ"זZحC_a7Z־na1}U'xmo=DИIʭ秞:[aኰ7Ia5{FSmDIsaͧBL ]VFKёϾ]EǕg$:›d;HzX/;pطeC:X"Ta,k'=X{cy_LFO䭿 wN2 ƬbX Ws:㼞{ڸرl^—[NZ༡llwI.'+.^\*` Ue=F>)a 7gS=B>YMiHȥ;髕Hڠ!>aG 62vd+?_@ 1C؃5 nv}XJ7bUJYzJ?}\LUM/<( M *hoVÅG5܉ p'6|'29ix{>~;ߟ *kRn}>m:NfӬQzJZo WY(7^c ~XO.nIh`=a0a {z@^i 3SZ |EC.Ni|XVR~O\X<7ߟwE/u.ۙa UUؗ`y<̹DrǯV'Eo3XU-Y0cچX v/4VAc{x9  o46szH ?E]EƜ*,-Kb֚$Ǣ^E{O'}n+`wgC8 "cCر&F-Z 13TqÃq%7H]dA7+xb!!㱊jŭ^`[˚+}rdOZp67z]_.5f<-x O)k]9)/z a?r-__p4 .TZӮΖ-a7P)nj2(ГƊDzy!1/3q~!>5aGP sClvt;q-wbN.enlԐh_X 3Dq|{ke>A ;w8! 1;$3 ,cwzy|crK%mJB($`Ǚ^`UحemWX-=H~*S15e7(&mwm=zߜuQ![ ;f1ǁQQn3c;.fS7>ab~܎HplgU E.p4D'v&yЬ ten=Gg!N[^tܒrꩴvdquy:qDؑ ^m]}'|tHv㠤ωy<">1 k%)D'_}pK,+l=HnCγYz15vR7?Ji!LJP@W'm5gmLVR[۝=sZr=+HiB} b @>zWŽ n]yb:YqGapq4%dc,U+|RoB}bŽg;2dsٵ7ɉ ؋mrB&(!ߝ{P 1 98{HNl+v'PUIiJ %c5ɸEd zgD6Z(a[*;uN9]A 7+obڦW" \ҭE9@`'"* sGK{}-%^1wDն7nrg1?_ z}`=A7hَx}wx'Ӓ9%O]wUaG /T'@utѥ)" ;6:=sT0'oUiѶ8?yP'Ecqzonp !ԃA+N9ACYf RqCh 8a@رR!PBi܎q9c6wo 43=]YF;p7) ;aNVhkOyCѮתv(o㽠vj0wPt@Q&ʍ%,;A7@/='F "/cvŽ k}ڐ.Ǜ82 ʁ |WIR9 ; zvq DyE%-6Nonl؀Q )knSkG@h|;Bxww.}m fI38yo^g&?%}qt~ #doyrׁRmЎ@ ^W42vwYmB?%p dBO.rԃ^t]_@bގp>1@j:uzT͜b' cr=lH)Wc Dm6wSPIUyOp]qUFL'@dѷ?P546L`D?a?zA {()1x:qq|F̽ a 8?D}zf(ο`"FBіo s!>ua)?tj4Zis\W'-ֿ5<'7E[N?n}b#E)9~s&FE zhnz*[#ſR!z Ǒ;LhW]+l cL>Vt"Nz@VaU zlLe )^&+م?ٞW<=H1C Rmm݃*=`B6/n63<7[V,u4=,ԯ~eﺪ_Θ=E K+؂7Яu8L]sg_+Hܶy/߭Žmz/6w QG\َ%n2;$] \ ";\vB披|`;ibr zIЛ;;ZHRym[8 =8adX˪cxuR -\ aTBÏָͪunOT|f{HƁ'ʫ=11H GSq[ӮLg'CplԊ]/S owuuFd^+kІZ*W<fߠW9yw Xe `,b#Uq=ro8|-_ q;!\q  Edv\`"^S;.O]nld1߉G9iMaaG g eX0Sjji[iid;9+ӗ*zjܿ,\452'+&Ej'l@;)b~h.hC0ڽ8y>)=`zЎD9ȣ>q pኁUŌ$:J=gNy`0;z~ ̠8? 7Y}Ig_ҋ*n!MI:R0\r莂gש35#W[Oey7.kn`si@RT9)5/>eO]})v*KG)Vl12g;.<1rMYE .00c8f iYX|hY(WO";&q(\3+͠siذܷUqғI}?"yfgljo㈹=qA0o?^cdN>mˤ $+z M?9sJsvY@iL#W~ aQِz ;w(!>#lŽLޚr.ğG(=շwУجNгii`{g癨=Tu\ :N[h;yNa}&ѳ)~ChEJ R+Ky?:z> קƬ N_M+)hۑB}bG؄ϼWNs*VkjT!^VW\Er BE/?TnE nMd>_zCb`'n??*ȕ<}',V6@jf0#r#Kp;仳ڻz'h`fy{SWtyCP߸?#Hl0DX+hZ+bsO? ^ݗIW[=ZO#0sb'Nj|3_Ʃ)ߤ羻JϪD0 NJc&u{Wyh( M5-N~7&p]?ߞe)A7Ҩ]I`6\apB}bG؅3#f L/ĽN\Mcb靟ي& bƿ(:)*CU7է.~^O?U[wu0Ss!u::Ue1itRKɿDӇҽ: L ^[OoHdab9k~}4~XM3WA|54)ӣn3 w=amx!>#nCMu;{j꨸*> 0a8U@cVW_*eAn=-uMf(D'v?~N*秞KQ%C 4v=b}vAPL7;K%ĎQv#Τg>EWc^9ԏ -Ya_zN]wh_'R# .2bM}ez3s3G!(}¾L1 P{lg'i.Fy4M#MiGA }Aٗnrz$!>#b+Kz 0\ؗK9' }Af3c#FGM>MOg)")|d:W!O5/wh҂z '?I4y-d+ B0. AZ5;2? WGF6D'vD_O_.I|\Ac~>p> GGw?9ݟL]ё+숶>Z;3,m:rIEzH]g 櫕R=nB}bGD ;:q!9"+SwA|I=|s WH+۔U8\Oxa7"&M/~LVUJ&`R,ar_. (loޡ}{6Ϡv";ƌqZkpU=p 뮕;}uߞv_A&6Ս]L6=)a=JέSFNOsSjj ߩkP\f [Au>ÎŔ}A`9zl9u3JybtgKsZJOWŽ4uzT,^wV* cuy=t8A`EH=O9MKwSzA#v=VOwnFh}4Td{[Di TE}&3 ~ZEaDJ)6ѳQ@u͑$D'v{a7Vẅ́rZ_q^vVW^9Dю3Yzp cK7u>b!A9f9wX=v竺SNӤhˉ J-hn=m<Ď #U8]U濯Ѫ=t/{s/ȣҿ6}0 }&M.3-+J}uų 9o MYs>]|U痧g>;&-vW4m|zt|IKHH.lΧYMG|#&aϬ/P.n GbMZvc:o ES+ߡ HasN${<=OY#% s/v?9' ۳'NS{PIHH/;*h">̫^u0 {sW-~ͦ† V"c*ӆn?(T0`Tw'>#j?lȺ,7UKBBB½x)%ߢŗ>^qkS#ߎ'#LϿCR㱳PoKHHLiYInPj=ǜl6z.V%$$"3z\^H=޽ ӧOZ>af)׻X v 1O>15Rmld>ߛkCv$OsNǖ;mJHHH 7 RY3OHs{ .%J{5D]нc3D%$$\ |bVܗGEB/ {FGDUmE?^_o/Щ05 #!!xG-de, 5v ;ǯy9gEJaq/ś_{'K4H[TRYEBBb]f2 $ؒ+\>۔S+c9D%$$l`AM=mbo}xfT =Y 2?a_s+݃n)5x_]bĘɾ>;  'a O?X@-c=D%$$| W'}ns۶ݫҽ>Yy,u~h""䵰H?eN@N{cG$$$$F'*Z 0;G%wx v q}?;?{p Q}% ̕~+8+Nz_Mbĸ Ͼf~@lQAR%$$$F3ПwgBU׾~|!.!!1f~v;ΧFBB"A Ӽ[uʨ>[bĸz~vN|OEz%!!!YT~siϒ!.!!1㧴f~v3믕IXD_ZU¢ID}>C]BBb\FwZt>@V NBB"H7ޙA3N>[Tڔ[bĸ-S;~;bڼ{IHHHDvץOexv qsg_{'!!1v34Tn!.!!1ɓ?;?=zmkwo^8 sϽI Uޭ="N؛{)ӫԭB|"JhxA!xxs*MڞEnNdAtm?CI{fm#,Oi|Pd[KZiŨ {'TPBLօ [* T^A`)t4;LJ&;ZഴG]-uCs:@WPy4d{KOPy޾?HjG̿dH= '!IxytАP?0!x14ۄѥW)x:MYsޜu^$W7RbTA)zw_<}SDTV/@ v(&` :PVPnǐ$(vE OdQMx/vpr&rT^ă 9'n‹x xA6WQIw+e7.O #!FT؛t=C~sJ TQI7pCԁJl'rn"vbnE v X!$Vܣ`&J]u'n y x)l7< 2 ^Mx/vp&r;ԏ BXV3wKo?>IfSrь6XI۳/+5Du sbnE v X!W̭ Yԕ\^}`$ x@pr&rN݆`B2^Mx/vA.E]~B[ԣaY_&-F,N dBhܗuV0bns%؁`sj:P"J:#n y x!k< 2^Mx/\ /vB#0VoQ t:va?z^-KKw:+f1J9l;XI;u%׮ɺ.ꀓk7e<spb6r;8v^ X /e#0*X7^vVO96aGɛSNӟӨs܊:` #VX1;B8Ǩ:P#Fέ0x 8v^K\ /ड़k< B^~A"rc TM2k_ߞ-2_ԇ!롉:pWY17H9+V\@xʐE(v[:# d/N݄@Bn'n‹x x!*nËx0x!k7e^~A"C:*Z62anԳ`#g QɺXA7È`(@x܊;u%خɺx9‰pe<l7<spr6r;8v^ƃK` /#bNHuam_+oSIe{xDrHu%NPVPnǨ:P"3q;8v^N݄`Bn'n‹x0x!mx@A1]a}zg%Qp]^t6؟`B2^M S*ͪۚ.G/RjsEAS6wETׄ'7+oQM]'+N +v +f1Š9@B[ΈF݀@Bn'n y x),hU|L-渘ڈq1`CzQ &_r;x)*n8nw^̭pr6;%PUͼ@Sܡhawezni}L;BՍ]B ЦMG>+\zzv):vp''Q[Qrm+J_I㢮D x!@pr&rk{i9_QeACsK\srnr;b6FвPHN)Y5 [t&U#6>Y|]]dҋ4V0ϰ8wXcpn hp=\ ٵk¾lG<72Uv2:PV0bns+J y s!ꀕp'(.ꀗsv^e<\ /vRn'N8 ]zP oi=퓕5+fx)m|Eܗ_%|ӱt˶Lyvp6>ݛc|W~E?g, 'n>ԏB :n hЭeh pMؑz;r;BuP֕`;s9l;XW̭ Yԁ:"@IxpYgl7<2^)K8?)u&݇fzsE}rte;/vpb&mBn'nbqxYhZЫʹV ԏ d6ϫ'\IO뜘s&#,sV̭(+vxŜcȲ;K# h/vBN݄@Rn'CmV{G ~}Eܗ}Ҫ))O2)y Nz*jndˎNWQg4؛6AmCJE]櫿}f1RǠ@ mbNŨm5N%Qolfmx?-My-{:;fUg;zcST5z1,0oУ󰼕7?N؎E<ި_ƟЋꔘB%y)7V%V$u{}z1z?\dϵrJtw gn3ߘvN ~^^A7; ғ\*%fQhr΁p UѪڀ/3Oҏ]-w^;;0{s ϥ5z޻u@ni M^}[sc^{W}㻃8 5J7.6&W -ߗ~_O͒cj秞]gXA7M:#s(@xʐE(v[:#h/N݄`ba9l:>'vrv%l@ؿ.2D}u9Rg0;Q7B@0=a?ӱՅB*I,/ԫ6ռ vSޘsؕGaoyE񘝰" w_).lx.ޛ8~8@:8S6 ](5Vw|qA&6HCp'a ;fX1~:`"s(+P'OQuD<3bnEIM8d@BN_ƃKh'FЕ<;aP aG!jo̢nyv`7Q<盕5(l=SŽSȢYȝ]ܬ{q_(Že䐛 IN\t k,'o4Ҟs9R1uz>}9{0'6U1"zJ pTx yx?׼?_))I֜vonjH1\ۑm-M R}[܎a 툉:PVXV̭(A+vFh/v2N݄@Bn'nƸGRuc5;IŽtpmOF_Cθ}YJN asE*nSR͋?/j7x*f*by_3~xƔvNq"1W%=xm pCqS4YPE=Hu0&96CGƿ0$vˉ =a aǬ%H4@3;⿘UG؏{zq`v\DX5w(rc?%݊S^~s^OTǐ r1|#- #?@j WJNؑqQ؎l3 DAE[cq_ưT7tIcXԁ:Ax s Yҁ: "+>x/vpr&A{R[u4 Aؿ\qKT@ZΩۅzz@`F4-kwJW2+zGJ^Σg<;(%nS/3$ԏ*3Li  ;Ŀ_Qb; {zei<~lA>=fAy7/@1;f|.鿋1OԪ5;a_SƋ1o m" .ኰ/`8u%CtsRΡ;B xuPx x!mrnGW~,O=΋:9&r!m4\wcy_cjFǿ ;42އU 9 ],1~%O33d:T (練c\=M19ꡀ.^HY^p9\~@ꭋ9b~Y Av`޻JAyFy1a!I y ܗuV0rns%؁`s IԁlD+ΈB^Mx/vp&ہ@!QvHfe1H 0r=rBbkC 0ߟ9)oL/]`mT4L/Q" Go/W#M'x/xR9zT[Vax$M?9f`(7r!r4|5{V28C`QxO{Hؤysw9``,T:s; }i`*{x$U_|'޼B 1qduGݤJ%ߙ8V ;\Hw S\wi8lcNyb>qwceRH-~hsYzߍrǑ1_9VoG_))^BCQW/N4>X/Ą^n|΁VexR.56<+Xp\O=j3)w2~Zl)Lk:zE.pb)u5̏p fޟiSտ܍a ^8STQu_Yg%@IX97c@bnEu XCurYQgm7<ɵ2^Mxs D=D,ci1U6o`HAs[sЋA}nG5j:fv WS1 $+Ȣ ^ob>}n#wߨUUp  ĝAu;-층I,e]ISXA7ÈV̭(+P'9_Qw(J]uurMv^ y 8v^K9'n y xAl;8a;s;r6_ T4tl9M.<( +vAR!᮪1laohdMQJ J%خH,X /vBn'n‹x0x! Cv^ă 9'n˸ퟲ7qV o+1>  d`⁺n1laG`u$ aĜs+J y Lrnf=@ kD<3bB^Mx!/vp&s;8vSae<ɵBAv2Sfgw^֫{VΞ.ߍ)1^XHaOB7ኰW'T  I XA7ÈV̭(+!p:/fx9l7e^ɵ2^Mx/X Mʩ3r;8v^/No36)+󤇛`) Fr '(03v#\v_rn"s(+vxŜc=##댘[a$ x!/vpr6r;8v^K\ /ड़kAAFtR`pk¾|W򫪮rV0bnr%v2Qw(J]u%ᮉx x!'nx x!mx/vpr&r;8v^x ԏ 0B`*\#%&\ᚰ+ ,fqZ+VXA7ȹV̭(+P"1u˹h/v2N݄@Rn'nx0x)mx!/vp&@Aa[ !}3\ᚰhk,}5vM+V\@xʐE(v[:#d/N݄@Bn'n‹x x!k7p'Bn'nx xC i =RpkŽ0 pVa:+_Qw(J]u%E0bpe<l7<spr6sN݄`Rn'n y <GA%n%VЋߟF Wx:yJȪuMY)PVDcTE(wEv^˸X /vBn'nKx0x!k7E<spb6x ԏ 0գ;Up]뚺땷t9+V\@xʐE(v[:#h/N݄`b B^Mx/vpr&r;ԏ 0`iޣ_.HxuaGYL+$Yg܊@2[+`% JăF̭0x 8v^N݄`B2^Mx/vA!ScѵyG""숄:wgitjlvWԁ@B[qCY wΈF݀@Bn'n y x)l7e<ɵ2 ^98v^<GA]ȡ秜D؄'wTzzA7Ê%ׁ`e[1. N݀r;x!'nx x!k7e<ɵ"^J2^~A+Fo?IT~v>TM؍8y^M1TTs Yԁld]xpQHBn/mx!r;8v^ƃK` /Ŝ*ဗr;x!A"&+v%^/Pl]qb{DEßRbVD(@pCYwH9#n y x!k7e<ɵ"^Mx /vXmx/P? B`>Y|&-Je-|0va7>_zޚ}]սQV9ǐe] v8dtF8v^<` /N݄`b B^ʵB^P? BCg{s/ka/hUN#ZG~sJO|wWԁFԕPW@2N݄@B"^Mx/vpr&r;ԏ AtɛkOԬ\q4cD˾$z zJ@52UCumQwK9.r;8v^ƃ9'n y x)l7e<ɵ2^~A]LqU]+-Aͼ@$}S1*Ž i2KߟS?[rCΝ ;u%خɺp˸" ^ME<ɵ2^P? BХ< 1~;X~SK z{w"%FMح^ee%M9MιL߭Cs6Fݣ%h/CeF]cUB W#{^4?Jc2?ɞPH,Ƣв }@]adXxWz v_9h>-K?Oϻg|y9힫v'RTZJ#/"F؍@JRW<ӎYǑ4B 06sq?>{ o83&ời쾂0ޙ{d_{d #OG CcrI8% ,P٪3#]b|4 t֑7ʵ3[+j p~IHH^JW/G-n!.1"|H]Bbtc_*z).!1q,z).!.1"H]Bbtcw2z).!1w:z).!.1"Y4o$.!1#z_a8`Kv v w~kD%$F7T5v э=q+Ĉ v эM";bKv v_oNkD%$F76ޙW/E%$F70wD%D%F$~ ͔v oW/E%$F76ݛ=X'R]B]bDb/ v эnN"z).!.1" v э_n|W/E%$F7ί^KKH, `iD%$F7V]¯^KHn1yNzĈK<˯|*KHDXBzNzĈ‹kD%$F7\W/E%$F7_UҖz).!.1"1;~ w!-.!1H[Ĉso5@"ϿW/E%$F7\xׯ^KKH>_$.!1ƜoKv vOKHnbƬ3Kv vӧO}o$.!1zaW/E%$F/qR]B]"I?KH^<~򈭗">fDأmD%$F/zR]Bbq[/E%D%}ml$.!1zKv ыGlaa{4 EG_+[/E%$F/;z).!.he v ы֞F^KH^t""aJahciv v W.rnRt*m3t7xqխ i>C;HHhꪡ#ISUkhb륝׶!D()?Jr FKw=[/턽vD/Y"ÊGOA9Zvcݰ_q4GpdyEZ}+JOO>nOFv3p@˩ {s#t}}!ԻUB"S%ݠW?uiӽtn9 \`~W?zZH 灵2c_{q׾n\dsvAWGteFb|DHTItsW]4?|A/u^ҘEi|5^+Ymf8tCG?Dr ʦ{-޽éOɮUM-JE%"5Jkw#IZK^bĔ޽<^w: l^S3kc?BB$$$G{o ءi9]p»'m|qžV` Y+D%B OCa'z@E 1žS@sϽE?XUuou{nȵoQa}wOO8j_>/;_.gQ"2oO?3/}QR'E 4;lT6 NBBb0Жs :TΗU+[ sU,)4vIa)p ȹ5ʒ_쿏E!.￟3¬\#f_(vO;fGHjDnC@/)k8cv\$v[['!! u){[_fsY޷ΗYQϷG/ƻ3E$OKm=ˍo 暴Ds},~2mpFv?' ΢vХ`~0>e}KSGcl]suʩMo_[8}!igq sk=H-l)"Ei6zɋg%9>zt޺eQL(1C]µ8mLF c&.x_uq(O [ffT TAjQ/ l}0_ՇJHH '0 Ӭruͯ^s;?P#Ϥ ;D%\ <[@9iX0y;ct!;iCHi+N7&T/Rd Ӽ&1C]x1]96.N/Wn<~N42;y-$H2 ϱu X>lMC\qsNsv-x;pxg믕BnRdv>ﻄXCA/~Si[r EMbbDX³plCñ=QC8Os$Fb|RcY(lXr#m/>[BB"V'@*LQc%D%o<Á)2cr?n4ӧ̴V0#V;ρT-`d!!!Bfv9vI$&RK-ns {\[ o]Ja|k'S7u av% [Yϭ/D%$z;{/["H},Zz:{eĈ&TN׿Z#qlXȻD vGrmGpJV[bYhȮI`$Ȩ%!!1QܘIY$&nKHK~4-4+t3wŞj$m?*!1R>UǙ ?\NV ш{g|ƙ`~n!.1"U_1M~QX5FjGؗ/~_ZbbFg_fJA* e$$$F/=Q %#n! :*[)&N.'2h!8HӏB{<3۝BgҤmhO$T&WL YF5];qV=.-mL U/_us>Bps;EQ 3qeOcmbq&-+!8+'^Etl Zk1T@S+5hPeץޛ1|tcp+B׷gtUTѪ?XWL%lFѥTUIFdꦣziCfd˖Vjhyl4e RUeVMK{s/sJhK[t@z!O=; fOgnRyuKZ/zz1HD%$ їoRvQC!®"-A_yJ*,oUN 6: Fg oÍFTà ת% 3ԉiD} pFnI3-ճZnĖQ&v8nMrNfz OD֠{BAQRFMwMPnq37vuq~uT/\ҷnruьK\/Ad%Jmtgv j\loc0 A5 5:`+7>\Cc'`*xf߅}KSEZ`ܗ}糝˺^Mo}zH~;BYSg]?Yw1y~i:~-2bB {ZAW\Jhx|mxFg5<~X cӎ#i dC/RA%Gx%z ϸes8fl0̹LKSz K魗u&W ^cayR/(,"e #tu1J5>yս D@ÃB8Ф_nq7uFU멶rTxuzlC]\J]=o| Mze5ݖF Uv9 TU:qlFXjx@e}/68%mz~@ 6u늉|nS^ZAgnTEhDyG;p|Ru=ziCfB zPc2`Xi{XުuO_!擿ꥹ.^ ڙӋ G;ÊU":_2a%:6y˹z(s%-3΋85涞sC;{Gyxzo}F;&cFv'QJ38oxШҞzUṆ0V_46XLsWcJiՋu`I ؤ90@2`4>EI Tw?LI~l!1b`i` M.,[l˽b[ŶdI}gt4{f4jsGGsFS?v!A@&5hUJ,:i]Yz3e˸I sKv%eVM/t_?'&.>lXq۴rrA. & mz6GJgi rmeWtW.Z{T^]l=oHzZkM\lE;m%c<a'B,X7i8wd̜\mL\h|h}a#~iU:k>ym b<Ϛeyg!%"FظX ^ '1 h`H`ξcGBі7wsr!+;*-iiM%,@ m26zt2M\wd٩k E:}#F+2Cz3_.fCϰ.loOHK[lYϦHծK?w 4yp[v8R.Rpm fT!ҺNzGgi>]Bt,^٥RZ2'k:5M.'֚R{wsj[g: 'kNWxgiY36(P`[%_f/c6s$ ?Jט a&d{ǐ@d3Vjǜlf7dq1 |_;<9\uE;]Z8( [Co^Һ,Do]]'jf}oH.HEgo4%{4Duac 630/\}3˘l6$p.si3.!-.m`=i2!CNV{{^=N2鲦)w`;V]&2}'l;nWUvZi,rxb3R㉚ϢS'Yeǀlo[sߋ %a<_j^]@Ș\EXCA.2yLgPschrvg:뷝9=9=d46_4,Cc<̔+y-T@N kkIl7Wl?t{ʦeAM&t rPrk(+  uɘX4yOH`Ge. >n\|]Rɽ&﹭ώe|-sQU8~ttKZ򢁀;'\.sv\k^oN\<Cn+ ~]r9f{=TY5ؿ1}M5 [tK[RvZ闕+$S5 a;OE2S[ne_"l=2O&PvZcH'zS񸋢aiůj$ϔ7lcJum.n!e:1|2p\9l[Iz&qWkf-ll[]7;d {~.k[mCoΉ`sٖqtBlμ` aNs 2t&3jg;cBb;5 >pLk';T]mbr"#ĐS-a\u€c6d [l>3}-l{ø#.⁙lEձLvA~tcnZ|ӑ^ipy!m/s;=O*>jה{=һwȵY>;-rMhCe.D6s!eR0Cz{vZ8=waet9#kl+ZEoYwF]%7c 'hąkve g"Z\ \HHţM|vF;`N5~j'^C$=7R -?lW>2ԅ^xyeF3/#!U藗f1g-V3exGӵVx[!1kPOnfR"{(*>/x|%gpE0QLgxB'xNόfhN+B 9[>?Xytc:-;ぴ)7o #n:*"ImWO&Ztل{l2p Lb\Ub|nEn?=t{زN8rˑxbj1}i:=]FҢ\tk1x ]HŜ3zhg+zDУz⺤O9+Dq'۹<cwkM @+y񋷖Jr˯RAFvVcV⺃\{bb54ee4wVSkoN m26zt,U]=2Viѝ32Sf̦oך7>?h;@<q=D򣳷=Nݲ{vw1;ɐ; -T|` p#2x!ӁgԾ}AחeIt|b4*9qkp܎N;]kQB-Hqhs!=-snC' Oü~{7 &Ͼl X^|9M!,Ds't96i3Ilj%5QMfuTiYcĝ1Vb[|1猏vٹ*!1!樬R)uaŸ ߅tP B3܆:C+{☱ qQaL/6v/W]HoG*4vw ?whhP[sTr rRH/KXvzt҄6 7ң#pC6ɟ՚ǤO4ؙ#\4=I!-T|`9gxB52錿"/lo.?l[Yݙ;$Yߝ1n xnF/JPOBqɍq 1uls,3fsE *,;DZvv5cHctKZ-1~a`YiU\|,e1VǨ.`e ӥO_0؝y⁝t*՟}3>x|vqv[IEZЈ'(imfA`fVPz6O;uWo=g'9.)"#K4%w^`,dR\bo~P.FZy c]9سڄ& 0TQ=~k3k 7D};᫟_ {/vi< dMg6Ti!LxBz#CeWRVkad6;!n|3֑q#WkM ,c8.M'N /N!+0c wyz,;dۛ.zC)'Nϻ`%u_ 0tYf+ϐNco\g8MB&2_cH6g*.  `/J&df/40;ŗs,ufL>]r{0nF$5HB%/ >e8Z̐vgܑht贄_se[< X,)j F$OP3g5B'i]L( OtOt2 Gn:p<'i:PM'-EQmtu GKOh]B5c '+L=i3IXdYG:vRY85O0\`i(?IOhBxFk>~ (|j<A1n& hQue9Iy SFv`W]l]*  F6GM'd4> 1t'j:P~)0>v]\Q]t9:m. 0Τ.~`t9͐&2KeeS#Xz|BFb>Dʏ2%R`iFufH>Ua.KC(UO 0308r㉚NxB&gtO)2У2͐L. x.˃v_.m.T]V5O0\`<i!sbg|xJi&a.]|tR&!MBe }v,GMSg9g[*io.:`w꺠g>a 1tGM|m:-Gm ]X9Lj38r%Xt^m={w.+Ĩ.U,R;=-T|`i:gLK('i>! MGͧzyF 2[H{wX;vRuqV_Rw'TKǎ+n[d{Bܳ,k84|3zӁO!GY|kA֛ۧ+_Qqg~9yyőLj3fH> e.ryIV z娸.:ң2Le~gg#P[Q/]myg2i< O48VIOhB|~o}rym;n ?}gFs狄.6UA.+\'liu-6/|զ{@uTr]U0~q5BL܌'i:PxW ;?a3 NkO]‰%,]]BQ107OYjݭvX#UPuY{M*sWP/^jj7ÙOl|b<3|x*.?l >@Z.Zl:ˤ6C Qu,W.t𞥶78-K70}']vf+vUeHPuYlIsW(]TM`xëW 6XJƓtxPdžݭv)Ug4pIW-{`)2͐CT]V'2?J3/]savgU˪dT:BUv0iVݱ],xFg>QDPITw&٥a[ϷSu$v^aC7Qi*;1fm0IӁ#7815(? +v}?&V`}3Ů.a1tY6UʱuYƑUش0 {d֛ӭCRYI}f vX9LOp|b>!3jN}Ct7#%̧BY.(+Ǥ̹zs|Sڠ'֚ͻDwKe h[7j{J U;,)&;]-jb4e>Q)|jXF J3|_?`}o-;W՘6^rD-;3OdhQTAOʆ60s4i`CF7ɵDE=3"$>4{ӤU60&2-bw->oB9';wRUR!q-rMZ0V:x_13?k&< }VJehg\cw&g* W{Lk1Tsv|9;>Y)" "s̛gT wfYx!4+ BP(% BP( E CBP( BQP( BP04+ BP(% BP( E CBP( BQP( BP04+ BP(% BP( E CBP( BQP( BP04+ BP(% BP( E CBP( BQP( BP04+ BP(% BP( E˜ ՕKIENDB`cryptography-primitives-1.0.0/examples/000077500000000000000000000000001470420105600202515ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/CMakeLists.txt000066400000000000000000000124361470420105600230170ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library examples # # List of examples for targets generation set(IPPCP_EXAMPLES # AES-CTR examples aes/aes-256-ctr-encryption.cpp aes/aes-256-ctr-decryption.cpp # AES-GCM examples aes/aes-128-gcm-encryption.cpp aes/aes-128-gcm-decryption.cpp # DSA dsa/dsa-dlp-sha-1-verification.cpp dsa/dsa-dlp-sha-256-verification.cpp # RSA SSA-PSS examples rsa/rsa-3k-pss-sha384-type1-signature.cpp rsa/rsa-1k-pss-sha1-verification.cpp # RSA OAEP examples rsa/rsa-1k-oaep-sha1-encryption.cpp rsa/rsa-1k-oaep-sha1-type2-decryption.cpp # SMS4 examples sms4/sms4-128-cbc-encryption.cpp sms4/sms4-128-cbc-decryption.cpp # Hash examples hash/sm3_hash_rmf.cpp # Post-quantum algorithms examples post-quantum/lms_m32_h5_w8_verification.cpp # Elliptic curve algorithms examples ecdsa/ecdsa-256r1-sign.cpp ) cmake_policy(SET CMP0003 NEW) # Custom target to build ALL examples at once add_custom_target(ippcp_examples_all) set_target_properties(ippcp_examples_all PROPERTIES FOLDER "examples") function(ippcp_define_example out_target source_file category) # Extract file name without directory or longest extension get_filename_component(name "${source_file}" NAME_WE) # Add suffix for nonpic build if (NONPIC_LIB) set(suffix "-nonpic") endif() set(local_target "example_${name}${suffix}") # link additional sources if defined in categoryOptions.cmake set(additional_sources "${category}_CATEGORY_COMMON_SOURCES") add_executable(${local_target} "${source_file}" $<$:${${additional_sources}}>) # Static linking with merged lib is only supported set(LIBRARY_NAMES_LIST ${IPPCP_LIB_MERGED}) ippcp_example_set_build_options(${local_target} "${LIBRARY_NAMES_LIST}") set_target_properties(${local_target} PROPERTIES PROJECT_LABEL "(example) ${name}" # Set name of the target in IDE FOLDER "examples/${category}" # Group projects in solution folder RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_OUTPUT_DIR}/$>/examples" # Set output directory for examples in the build folder RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_OUTPUT_DIR}/$>/examples" COMPILE_DEFINITIONS _NO_IPP_DEPRECATED) # ignore deprecation warnings # Add a single target to build all examples of the same category (e.g. 'make ippcp_examples_aes') set(parent_target ippcp_examples_${category}) if(NOT TARGET ${parent_target}) add_custom_target(${parent_target}) set_target_properties(${parent_target} PROPERTIES FOLDER "examples") if(TARGET ippcp_examples_all) add_dependencies(ippcp_examples_all ${parent_target}) endif() endif() add_dependencies(${parent_target} ${local_target}) set(${out_target} ${local_target} PARENT_SCOPE) endfunction() if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_LIST_DIR) # Build with standalone library cmake_minimum_required(VERSION 3.1) project("Intel Cryptography Primitives Library Examples" CXX) set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) option(BUILD_EXAMPLES "Build examples" ON) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) find_package(IPPCrypto REQUIRED MODULE) if (NOT IPPCRYPTO_FOUND) message(FATAL_ERROR "No Intel Cryptography Primitives Library found on the system. To build examples with pre-built library, please specify -DIPPCRYPTO_ROOT_DIR= option, where is the path to directory that contains include/ and lib/ folders of Intel Cryptography Primitives Library product.") endif() # Define library to link list(GET IPPCRYPTO_LIBRARIES 0 IPPCP_LIB_MERGED) # Define include folder set(IPP_CRYPTO_INCLUDE_DIR ${IPPCRYPTO_INCLUDE_DIRS}) # Define output directory if(NOT CMAKE_OUTPUT_DIR) set(CMAKE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/.build") endif() else() # Build with library sources if(NOT BUILD_EXAMPLES OR NOT MERGED_BLD) message(FATAL_ERROR "Only merged library build is currently supported for Intel Cryptography Primitives Library examples. Use -DMERGED_BLD:BOOL=on options.") endif() endif() include(examplesBuildOptions.cmake) foreach(example_filename ${IPPCP_EXAMPLES}) # Extract example category from its subdirectory get_filename_component(category "${example_filename}" DIRECTORY) # Source additional options that may exist for category include(${category}/categoryOptions.cmake OPTIONAL) ippcp_define_example(example ${example_filename} ${category}) endforeach() cryptography-primitives-1.0.0/examples/FindIPPCrypto.cmake000066400000000000000000000073601470420105600237130ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # library detection routine. # # If found the following variables will be available: # IPPCRYPTO_FOUND # IPPCRYPTO_ROOT_DIR # IPPCRYPTO_INCLUDE_DIRS # IPPCRYPTO_LIBRARIES # include(FindPackageHandleStandardArgs) macro(ippcp_not_found) set(IPPCRYPTO_FOUND OFF) set(IPPCRYPTO_ROOT_DIR "${IPPCRYPTO_ROOT_DIR}" CACHE PATH "Path to Intel Cryptography Primitives Library root directory") return() endmacro() # Try to find Intel Cryptography Primitives Library on the system if root dir is not defined externally if (NOT IPPCRYPTO_ROOT_DIR OR NOT EXISTS "${IPPCRYPTO_ROOT_DIR}/include/ippcp.h") set(ippcp_search_paths ${CMAKE_CURRENT_SOURCE_DIR}/../.build $ENV{IPPCRYPTOROOT}) if(WIN32) list(APPEND ippcp_search_paths $ENV{ProgramFiles\(x86\)}/IntelSWTools/compilers_and_libraries/windows/ippcp $ENV{ProgramFiles\(x86\)}/Intel/oneAPI/ippcp/latest) endif() if(UNIX) list(APPEND ippcp_search_paths /opt/intel/ippcp $ENV{HOME}/intel/ippcp /opt/intel/oneapi/ippcp/latest $ENV{HOME}/intel/oneapi/ippcp/latest) endif() find_path(IPPCRYPTO_ROOT_DIR include/ippcp.h PATHS ${ippcp_search_paths}) endif() set(IPPCRYPTO_INCLUDE_DIRS "${IPPCRYPTO_ROOT_DIR}/include" CACHE PATH "Path to Intel Cryptography Primitives Library include directory" FORCE) # Check found directory if(NOT IPPCRYPTO_ROOT_DIR OR NOT EXISTS "${IPPCRYPTO_ROOT_DIR}" OR NOT EXISTS "${IPPCRYPTO_INCLUDE_DIRS}" OR NOT EXISTS "${IPPCRYPTO_INCLUDE_DIRS}/ippcp.h" ) ippcp_not_found() endif() # Determine ARCH set(IPPCRYPTO_ARCH "ia32") if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8) set(IPPCRYPTO_ARCH "intel64") endif() if(CMAKE_SIZEOF_VOID_P) set(IPPCRYPTO_ARCH "intel64") endif() # Define list of libraries to search set(IPPCP_SUFFIX "") if(WIN32) set(IPPCP_SUFFIX "mt") # static lib on Windows endif() set(ippcp_search_libraries ippcp${IPPCP_SUFFIX}) # Define library search paths (TODO: to handle nonpic libraries) set(ippcp_lib_search_paths "") list(APPEND ippcp_lib_search_paths ${IPPCRYPTO_ROOT_DIR}/lib ${IPPCRYPTO_ROOT_DIR}/lib/${IPPCRYPTO_ARCH}) # Set preferences to look for static libraries only if(WIN32) list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) else() set(CMAKE_FIND_LIBRARY_SUFFIXES .a) endif() foreach(lib ${ippcp_search_libraries}) find_library(${lib} ${lib} ${ippcp_lib_search_paths}) if(NOT ${lib}) ippcp_not_found() endif() list(APPEND IPPCRYPTO_LIBRARIES ${${lib}}) endforeach() list(REMOVE_DUPLICATES IPPCRYPTO_LIBRARIES) message(STATUS "Found Intel Cryptography Primitives Library at: ${IPPCRYPTO_ROOT_DIR}") set(IPPCRYPTO_FOUND ON) set(IPPCRYPTO_ROOT_DIR "${IPPCRYPTO_ROOT_DIR}" CACHE PATH "Path to Intel Cryptography Primitives Library root directory") set(IPPCRYPTO_INCLUDE_DIRS "${IPPCRYPTO_INCLUDE_DIRS}" CACHE PATH "Path to Intel Cryptography Primitives Library include directory") set(IPPCRYPTO_LIBRARIES "${IPPCRYPTO_LIBRARIES}" CACHE STRING "Intel Cryptography Primitives Library libraries") cryptography-primitives-1.0.0/examples/README.md000066400000000000000000000077631470420105600215450ustar00rootroot00000000000000# Building usage examples of Intel® Cryptography Primitives Library ## System requirements - CMake 3.15 ## Build with library sources Only merged library (cmake option `-DMERGED_BLD:BOOL=ON`) builds are supported for the examples. 1. Navigate to the library sources root and run cmake to generate a library build procedure with the `-DBUILD_EXAMPLES:BOOL=ON` option. On Linux\*/macOS\*: `cmake CMakeLists.txt -B_build -DARCH=intel64 -DMERGED_BLD:BOOL=ON -DBUILD_EXAMPLES:BOOL=ON` On Windows\*: `cmake CMakeLists.txt -B_build -G [-T"Intel® C++ Compiler "] -DBUILD_EXAMPLES:BOOL=ON` For the Visual Studio\* generators options, please refer to the CMake help. The toolchain switch is optional, specify it if you want to build the library and examples using Intel® oneAPI DPC++/C++ Compiler. For the list of supported compiler versions or other cmake build options, please refer to the library root [BUILD.md](../BUILD.md) file. 2. On Linux\*/macOS\*, build with `make -j8 `. You can use the following targets: - To build an individual example, use targets started with the *example_* string (like *example_aes-256-ctr-encryption*). - To build all examples of a single specific category, use target *ippcp_examples_\* (like *ippcp_examples_aes*). - To build all examples, use target *ippcp_examples_all*. 3. On Windows\* OS open generated Visual Studio\* solution in the IDE, select the appropriate project (individual example, all examples by category or the whole set of examples) in the *examples* folder of project structure in IDE and run **Build**. To run the build from the command line, open "Developer Command Prompt for VS \" console and run the cmake command: `cmake --build _build --target --config Release`, where '_build' is the path to CMake build directory. ## Build with pre-built library 1. Navigate to the *examples* folder and run the cmake command below. On Linux\*/macOS\*: `cmake CMakeLists.txt -B_build` On Windows\* OS it is required to specify a generator (`-G` option) and optionally a toolchain (`-T` option) to build with Intel® oneAPI DPC++/C++ Compiler. Example: `cmake CMakeLists.txt -B_build -G [-T"Intel C++ Compiler "]` For the Visual Studio\* generators options, please refer to the CMake help. 2. The build system will scan the system for the Intel® Cryptography Primitives Library. If it is found, you’ll see the following message: ``` -- Found Intel® Cryptography Primitives Library at: /home/user/intel/ippcp -- Configuring done ``` If the library is not found automatically, you can specify the path to the library root folder (where the include/ and lib/ directories are located) using the `-DIPPCRYPTO_ROOT_DIR=` option. 3. Run the build process as described in the [Build with library sources](#build-with-library-sources). # How to add a new example into Intel® Cryptography Primitives Library: 1. Choose a category (a folder), where to put the example, and a filename. Use existing folders where applicable. The file name should be as follows: "\-\-\-\.cpp" E.g.: "rsa-1k-oaep-sha1-type2-decryption.cpp" for the example of RSA category. 2. Write an example keeping its source code formatting consistent with other examples as much as possible. The "aes/aes-256-ctr-encryption.cpp" can be used as a reference. 3. Use Doxygen annotations for the file description, global variables and macros. The *main()* function shall not use doxygen annotations inside (otherwise they disappear in the source code section of an example page in the generated documentation). 4. Add the example to the build: open *examples/CMakeLists.txt* file and add the new file to the *IPPCP_EXAMPLES* list. 5. Make sure it can be built using Intel® Cryptography Primitives Library examples build procedure, and it works correctly. You are ready to submit a pull request! cryptography-primitives-1.0.0/examples/aes/000077500000000000000000000000001470420105600210215ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/aes/aes-128-gcm-decryption.cpp000066400000000000000000000124751470420105600255400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 * * \brief AES Galois Counter mode of operation (GCM) example * * This example demonstrates usage of AES block cipher with 128-bit key * run with GCM mode of operation. Decryption scheme. * * The GCM mode of operation is implemented according to the * "NIST Special Publication 800-38D: Recommendation for Block Cipher Modes of * Operation: Galois/Counter Mode (GCM) and GMAC" document: * * https://csrc.nist.gov/pubs/sp/800/38/d/final * */ #include #include "ippcp.h" #include "examples_common.h" /*! Key size in bytes */ static const int KEY_SIZE = 16; /*! Message size in bytes */ static const int MSG_LEN = 60; /*! Initialization vector size in bytes */ static const int IV_LEN = 12; /*! Tag size in bytes */ static const int TAG_LEN = 16; /*! Additional authenticated data size in bytes */ static const int AAD_LEN = 20; /*! 128-bit secret key */ static Ipp8u key128[KEY_SIZE] = { 0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c, 0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08 }; /*! Initialization vector */ static const Ipp8u iv[IV_LEN] = { 0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad, 0xde,0xca,0xf8,0x88 }; /*! Plain text */ static Ipp8u plainText[MSG_LEN] = { 0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5, 0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a, 0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda, 0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72, 0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53, 0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25, 0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57, 0xba,0x63,0x7b,0x39 }; /*! Cipher text */ static Ipp8u cipherText[MSG_LEN] = { 0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24, 0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c, 0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0, 0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e, 0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c, 0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05, 0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97, 0x3d,0x58,0xe0,0x91 }; /*! Tag */ static const Ipp8u tag[TAG_LEN] = { 0x5b,0xc9,0x4f,0xbc,0x32,0x21,0xa5,0xdb, 0x94,0xfa,0xe9,0x5a,0xe7,0x12,0x1a,0x47 }; /*! Additional authenticated data */ static const Ipp8u aad[AAD_LEN] = { 0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef, 0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef, 0xab,0xad,0xda,0xd2 }; /*! Main function */ int main(void) { /* Size of AES-GCM context structure. It will be set up in ippsAES_GCMGetSize(). */ int AESGCMSize = 0; /* Output plain text */ Ipp8u pOutPlainText[MSG_LEN] = {}; /* Output tag */ Ipp8u pOutTag[TAG_LEN] = {}; /* Pointer to AES-GCM context structure */ IppsAES_GCMState* pAESGCMState = 0; /* Internal function status */ IppStatus status = ippStsNoErr; do { /* 1. Get size needed for AES-GCM context structure */ status = ippsAES_GCMGetSize(&AESGCMSize); if (!checkStatus("ippsAES_GCMGetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for AES-GCM context structure */ pAESGCMState = (IppsAES_GCMState*)(new Ipp8u[AESGCMSize]); if (NULL == pAESGCMState) { printf("ERROR: Cannot allocate memory (%d bytes) for AES-GCM state\n", AESGCMSize); return -1; } /* 3. Initialize AES-GCM context */ status = ippsAES_GCMInit(key128, KEY_SIZE, pAESGCMState, AESGCMSize); if (!checkStatus("ippsAES_GCMInit", ippStsNoErr, status)) break; /* 4. Decryption setup */ status = ippsAES_GCMStart(iv, IV_LEN, aad, AAD_LEN, pAESGCMState); if (!checkStatus("ippsAES_GCMStart", ippStsNoErr, status)) break; /* 5.Decryption */ status = ippsAES_GCMDecrypt(cipherText, pOutPlainText, MSG_LEN, pAESGCMState); if (!checkStatus("ippsAES_GCMDecrypt", ippStsNoErr, status)) break; /* 6. Get tag */ status = ippsAES_GCMGetTag(pOutTag, TAG_LEN, pAESGCMState); if (!checkStatus("ippsAES_GCMGetTag", ippStsNoErr, status)) break; /* Compare output to known answer */ if (0 != memcmp(pOutTag, tag, TAG_LEN)) { printf("ERROR: Output tag and reference tag do not match\n"); break; } if (0 != memcmp(pOutPlainText, plainText, MSG_LEN)) { printf("ERROR: Decrypted and plain text do not match\n"); break; } } while (0); /* 7. Remove secret and release resources */ ippsAES_GCMReset(pAESGCMState); if (pAESGCMState) delete [] (Ipp8u*)pAESGCMState; PRINT_EXAMPLE_STATUS("ippsAES_GCMDecrypt", "AES-GCM 128 Decryption", !status) return status; } cryptography-primitives-1.0.0/examples/aes/aes-128-gcm-encryption.cpp000066400000000000000000000125121470420105600255420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 * * \brief AES Galois Counter mode of operation (GCM) example * * This example demonstrates usage of AES block cipher with 128-bit key * run with GCM mode of operation. Encryption scheme. * * The GCM mode of operation is implemented according to the * "NIST Special Publication 800-38D: Recommendation for Block Cipher Modes of * Operation: Galois/Counter Mode (GCM) and GMAC" document: * * https://csrc.nist.gov/pubs/sp/800/38/d/final * */ #include #include "ippcp.h" #include "examples_common.h" /*! Key size in bytes */ static const int KEY_SIZE = 16; /*! Message size in bytes */ static const int MSG_LEN = 60; /*! Initialization vector size in bytes */ static const int IV_LEN = 12; /*! Tag size in bytes */ static const int TAG_LEN = 16; /*! Additional authenticated data size in bytes */ static const int AAD_LEN = 20; /*! 128-bit secret key */ static Ipp8u key128[KEY_SIZE] = { 0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c, 0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08 }; /*! Initialization vector */ static const Ipp8u iv[IV_LEN] = { 0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad, 0xde,0xca,0xf8,0x88 }; /*! Plain text */ static Ipp8u plainText[MSG_LEN] = { 0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5, 0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a, 0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda, 0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72, 0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53, 0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25, 0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57, 0xba,0x63,0x7b,0x39 }; /*! Cipher text */ static Ipp8u cipherText[MSG_LEN] = { 0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24, 0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c, 0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0, 0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e, 0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c, 0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05, 0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97, 0x3d,0x58,0xe0,0x91 }; /*! Tag */ static const Ipp8u tag[TAG_LEN] = { 0x5b,0xc9,0x4f,0xbc,0x32,0x21,0xa5,0xdb, 0x94,0xfa,0xe9,0x5a,0xe7,0x12,0x1a,0x47 }; /*! Additional authenticated data */ static const Ipp8u aad[AAD_LEN] = { 0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef, 0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef, 0xab,0xad,0xda,0xd2 }; /*! Main function */ int main(void) { /* Size of AES-GCM context structure. It will be set up in ippsAES_GCMGetSize(). */ int AESGCMSize = 0; /* Output cipher text */ Ipp8u pOutCipherText[MSG_LEN] = {}; /* Output tag */ Ipp8u pOutTag[TAG_LEN] = {}; /* Pointer to AES-GCM context structure */ IppsAES_GCMState* pAESGCMState = 0; /* Internal function status */ IppStatus status = ippStsNoErr; do { /* 1. Get size needed for AES-GCM context structure */ status = ippsAES_GCMGetSize(&AESGCMSize); if (!checkStatus("ippsAES_GCMGetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for AES-GCM context structure */ pAESGCMState = (IppsAES_GCMState*)(new Ipp8u[AESGCMSize]); if (NULL == pAESGCMState) { printf("ERROR: Cannot allocate memory (%d bytes) for AES-GCM state\n", AESGCMSize); return -1; } /* 3. Initialize AES-GCM context */ status = ippsAES_GCMInit(key128, KEY_SIZE, pAESGCMState, AESGCMSize); if (!checkStatus("ippsAES_GCMInit", ippStsNoErr, status)) break; /* 4. Encryption setup */ status = ippsAES_GCMStart(iv, IV_LEN, aad, AAD_LEN, pAESGCMState); if (!checkStatus("ippsAES_GCMStart", ippStsNoErr, status)) break; /* 5. Encryption */ status = ippsAES_GCMEncrypt(plainText, pOutCipherText, MSG_LEN, pAESGCMState); if (!checkStatus("ippsAES_GCMEncrypt", ippStsNoErr, status)) break; /* 6. Get tag */ status = ippsAES_GCMGetTag(pOutTag, TAG_LEN, pAESGCMState); if (!checkStatus("ippsAES_GCMGetTag", ippStsNoErr, status)) break; /* Compare output to known answer */ if (0 != memcmp(pOutTag, tag, TAG_LEN)) { printf("ERROR: Output tag and reference tag do not match\n"); break; } if (0 != memcmp(pOutCipherText, cipherText, MSG_LEN)) { printf("ERROR: Encrypted and reference messages do not match\n"); break; } } while (0); /* 7. Remove secret and release resources */ ippsAES_GCMReset(pAESGCMState); if (pAESGCMState) delete [] (Ipp8u*)pAESGCMState; PRINT_EXAMPLE_STATUS("ippsAES_GCMEncrypt", "AES-GCM 128 Encryption", !status) return status; } cryptography-primitives-1.0.0/examples/aes/aes-256-ctr-decryption.cpp000066400000000000000000000104061470420105600255540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * * \brief AES Counter mode of operation (CTR) example * * This example demonstrates usage of AES block cipher with 256-bit key * run with CTR mode of operation. Decryption scheme. * * The CTR mode of operation is implemented according to the * "NIST Special Publication 800-38A: Recommendation for Block Cipher Modes of * Operation" document: * * https://csrc.nist.gov/publications/detail/sp/800-38a/final * */ #include #include "ippcp.h" #include "examples_common.h" /*! AES block size in bytes */ static const int AES_BLOCK_SIZE = 16; /*! Key size in bytes */ static const int KEY_SIZE = 32; /*! Message size in bytes */ static const int SRC_LEN = 16; /*! Plain text */ static Ipp8u plainText[SRC_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a }; /*! Cipher text */ static Ipp8u cipherText[SRC_LEN] = { 0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5, 0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28 }; /*! 256-bit secret key */ static Ipp8u key256[KEY_SIZE] = { 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 }; /*! Initial counter for CTR mode. * Size of counter for AES-CTR shall be equal to the size of AES block (16 bytes). */ static Ipp8u initialCounter[AES_BLOCK_SIZE] = { 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; /*! Main function */ int main(void) { /* Length of changeable bits in a counter (can be value starting from 1 till block size 128) */ const Ipp32u counterLen = 128; /* Size of AES context structure. It will be set up in ippsAESGetSize(). */ int ctxSize = 0; Ipp8u pOut[SRC_LEN] = {}; Ipp8u pCounter[AES_BLOCK_SIZE] = {}; /* Internal function status */ IppStatus status = ippStsNoErr; /* Pointer to AES context structure */ IppsAESSpec* pAES = 0; do { /* 1. Get size needed for AES context structure */ status = ippsAESGetSize(&ctxSize); if (!checkStatus("ippsAESGetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for AES context structure */ pAES = (IppsAESSpec*)(new Ipp8u[ctxSize]); if (NULL == pAES) { printf("ERROR: Cannot allocate memory (%d bytes) for AES context\n", ctxSize); return -1; } /* 3. Initialize AES context */ status = ippsAESInit(key256, sizeof(key256), pAES, ctxSize); if (!checkStatus("ippsAESInit", ippStsNoErr, status)) break; /* Initialize counter before decryption. * An updated counter value will be stored here after ippsAESDecryptCTR finishes. */ memcpy(pCounter, initialCounter, sizeof(initialCounter)); /* 4. Decryption */ status = ippsAESDecryptCTR(cipherText, pOut, sizeof(cipherText), pAES, pCounter, counterLen); if (!checkStatus("ippsAESDecryptCTR", ippStsNoErr, status)) break; /* Compare decrypted message and original text */ if (0 != memcmp(pOut, plainText, sizeof(plainText))) { printf("ERROR: Decrypted and plain text messages do not match\n"); break; } } while (0); /* 5. Remove secret and release resources */ ippsAESInit(0, KEY_SIZE, pAES, ctxSize); if (pAES) delete [] (Ipp8u*)pAES; PRINT_EXAMPLE_STATUS("ippsAESDecryptCTR", "AES-CTR 256 Decryption", !status); return status; } cryptography-primitives-1.0.0/examples/aes/aes-256-ctr-encryption.cpp000066400000000000000000000104051470420105600255650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * * \brief AES Counter mode of operation (CTR) example * * This example demonstrates usage of AES block cipher with 256-bit key * run with CTR mode of operation. Encryption scheme. * * The CTR mode of operation is implemented according to the * "NIST Special Publication 800-38A: Recommendation for Block Cipher Modes of * Operation" document: * * https://csrc.nist.gov/publications/detail/sp/800-38a/final * */ #include #include "ippcp.h" #include "examples_common.h" /*! AES block size in bytes */ static const int AES_BLOCK_SIZE = 16; /*! Key size in bytes */ static const int KEY_SIZE = 32; /*! Message size in bytes */ static const int SRC_LEN = 16; /*! Plain text */ static Ipp8u plainText[SRC_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96, 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a }; /*! Cipher text */ static Ipp8u cipherText[SRC_LEN] = { 0x60,0x1e,0xc3,0x13,0x77,0x57,0x89,0xa5, 0xb7,0xa7,0xf5,0x04,0xbb,0xf3,0xd2,0x28 }; /*! 256-bit secret key */ static Ipp8u key256[KEY_SIZE] = { 0x60,0x3d,0xeb,0x10,0x15,0xca,0x71,0xbe, 0x2b,0x73,0xae,0xf0,0x85,0x7d,0x77,0x81, 0x1f,0x35,0x2c,0x07,0x3b,0x61,0x08,0xd7, 0x2d,0x98,0x10,0xa3,0x09,0x14,0xdf,0xf4 }; /*! Initial counter for CTR mode. * Size of counter for AES-CTR shall be equal to the size of AES block (16 bytes). */ static Ipp8u initialCounter[AES_BLOCK_SIZE] = { 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; /*! Main function */ int main(void) { /* Length of changeable bits in a counter (can be value starting from 1 till block size 128) */ const Ipp32u counterLen = 128; /* Size of AES context structure. It will be set up in ippsAESGetSize(). */ int ctxSize = 0; Ipp8u pOut[SRC_LEN] = {}; Ipp8u pCounter[AES_BLOCK_SIZE] = {}; /* Internal function status */ IppStatus status = ippStsNoErr; /* Pointer to AES context structure */ IppsAESSpec* pAES = 0; do { /* 1. Get size needed for AES context structure */ status = ippsAESGetSize(&ctxSize); if (!checkStatus("ippsAESGetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for AES context structure */ pAES = (IppsAESSpec*)(new Ipp8u[ctxSize]); if (NULL == pAES) { printf("ERROR: Cannot allocate memory (%d bytes) for AES context\n", ctxSize); return -1; } /* 3. Initialize AES context */ status = ippsAESInit(key256, sizeof(key256), pAES, ctxSize); if (!checkStatus("ippsAESInit", ippStsNoErr, status)) break; /* Initialize counter before encryption. * An updated counter value will be stored here after ippsAESEncryptCTR finishes. */ memcpy(pCounter, initialCounter, sizeof(initialCounter)); /* 4. Encryption */ status = ippsAESEncryptCTR(plainText, pOut, sizeof(plainText), pAES, pCounter, counterLen); if (!checkStatus("ippsAESEncryptCTR", ippStsNoErr, status)) break; /* Compare encrypted message and reference text */ if (0 != memcmp(pOut, cipherText, sizeof(cipherText))) { printf("ERROR: Encrypted and reference messages do not match\n"); break; } } while (0); /* 5. Remove secret and release resources */ ippsAESInit(0, KEY_SIZE, pAES, ctxSize); if (pAES) delete [] (Ipp8u*)pAES; PRINT_EXAMPLE_STATUS("ippsAESEncryptCTR", "AES-CTR 256 Encryption", !status) return status; } cryptography-primitives-1.0.0/examples/dsa/000077500000000000000000000000001470420105600210205ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/dsa/categoryOptions.cmake000066400000000000000000000015651470420105600252220ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= set(dsa_CATEGORY_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/utils/bignum.cpp ${CMAKE_CURRENT_SOURCE_DIR}/utils/utils.cpp ) cryptography-primitives-1.0.0/examples/dsa/dsa-dlp-sha-1-verification.cpp000066400000000000000000000142051470420105600264410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 * * \brief DSA-DLP verification scheme example * * This example demonstrates message verification according to * DSA-DLP scheme with (L = 1024, N = 160) DSA parameters and SHA-1 hash function. * * The DSA-DLP scheme is implemented according : Digital Signature Standard (DSS) (FIPS PUB 186-4) (July 2013) * * available at: * * http://dx.doi.org/10.6028/NIST.FIPS.186-4. * */ #include #include "bignum.h" #include "examples_common.h" #include "ippcp.h" /*! Parameters DSA-DLP scheme */ static const int L_BIT = 1024; static const int N_BIT = 160; /*! Message size in bytes */ static const int MSG_LEN_BYTE = 6; /*! Message text */ static Ipp8u MSG[MSG_LEN_BYTE] = {0x31, 0x32, 0x33, 0x34, 0x30, 0x30}; /*! The generator of the multiplicative subgroup */ static const BigNumber G( "0x" "0835AA8C358BBF01A1846D1206323FABE408B0E98789FCC6239DA14D4B3F86C2" "76A8F48AA85A59507E620AD1BC745F0F1CBF63EC98C229C2610D77C634D1642E" "404354771655B2D5662F7A45227178CE3430AF0F6B3BB94B52F7F51E97BAD659" "B1BA0684E208BE624C28D82FB1162F18DD9DCE45216461654CF3374624D15A8D"); /*! The modulus p */ static const BigNumber P( "0x" "B34CE9C1E78294D3258473842005D2A48C8C566CFCA8F84C0606F2529B59A6D3" "8AAE071B53BB2167EAA4FC3B01FE176E787E481B6037AAC62CBC3D089799536A" "869FA8CDFEA1E8B1FD2D1CD3A30350859A2CD6B3EC2F9BFBB68BB11B4BBE2ADA" "A18D64A93639543AE5E16293E311C0CF8C8D6E180DF05D08C2FD2D93D570751F"); /*! The order of the generator g */ static const BigNumber Q("0xB90B38BA0A50A43EC6898D3F9B68049777F489B1"); /*! The public key value */ static const BigNumber Y( "0x" "173931DDA31EFF32F24B383091BF77EACDC6EFD557624911D8E9B9DEBF0F256D" "0CFFAC5567B33F6EAAE9D3275BBED7EF9F5F94C4003C959E49A1ED3F58C31B21" "BACCC0ED8840B46145F121B8906D072129BAE01F071947997E8EF760D2D9EA21" "D08A5EB7E89390B21A85664713C549E25FEDA6E9E6C31970866BDFBC8FA981F6"); /*! R digital signature component */ static const BigNumber sigR("0xAA6A258FBF7D90E15614676D377DF8B10E38DB4A"); /*! S digital signature component */ static const BigNumber sigS("0x496D5220B5F67D3532D1F991203BC3523B964C3B"); int main(void) { /*! Internal function status */ IppStatus status = ippStsNoErr; /* Pointer to DSA DLP context structure */ IppsDLPState* pDL = NULL; /* Result verification DSA DLP */ IppDLResult result = ippDLValid; /* Size of DSA-DLP context structure. It will be set up in ippsDLPGetSize(). */ int DLSize = 0; /* Digest size */ const int digestSizeBit = IPP_SHA1_DIGEST_BITSIZE; const int digestSizeByte = digestSizeBit / 8; /* Pointer to the SHA-1 hash method */ const IppsHashMethod* hashMethod = ippsHashMethod_SHA1(); /*! Algorithm */ do { /* 1. Create a digest by message */ /*! Buffer create digest */ Ipp8u md[digestSizeByte] = {}; /*! Create digest by message */ status = ippsHashMessage_rmf(MSG, MSG_LEN_BYTE, md, hashMethod); /*! Check status create digest */ if (ippStsNoErr != status) break; /*! * (!) Allocate BigNumber container for the shrank message digest. * Note, the DSA algorithm uses only leftmost |minSizeDigestBit| bits of the original message digest */ const int minSizeDigestBit = IPP_MIN(N_BIT, digestSizeBit); BigNumber digest(NULL, bitSizeInWords(minSizeDigestBit)); /*! Set digest to BigNumber */ status = ippsSetOctString_BN(md, bitSizeInBytes(minSizeDigestBit), digest); if (ippStsNoErr != status) break; /* 2. Get size needed for DSA DLP context structure */ status = ippsDLPGetSize(L_BIT, N_BIT, &DLSize); if (ippStsNoErr != status) break; /* 3. Allocate memory for DSA DLP context structure */ pDL = (IppsDLPState*)(new Ipp8u[DLSize]); if (NULL == pDL) { printf("ERROR: Cannot allocate memory (%d bytes) for DSA DLP context\n", DLSize); return -1; } /* 4. Initialize DSA DLP context */ status = ippsDLPInit(L_BIT, N_BIT, pDL); if (ippStsNoErr != status) break; /* 5. Set DL Domain Parameters */ status = ippsDLPSet(P, Q, G, pDL); if (ippStsNoErr != status) break; /* 6. Set up Key Pair into the DL context */ status = ippsDLPSetKeyPair(NULL, /* optional Private Key Set */ Y, pDL); if (ippStsNoErr != status) break; /* 7. Verify Signature DSA DLP */ status = ippsDLPVerifyDSA(digest, sigR, sigS, &result, pDL); if (ippStsNoErr != status) break; if (ippDLValid != result) status = ippStsErr; } while (0); /* end Algorithm */ /* 8. Remove secret and release resources */ if (NULL != pDL) delete[](Ipp8u*) pDL; PRINT_EXAMPLE_STATUS("ippsDLPVerifyDSA", "DSA-DLP Verification Hash Method Message SHA-1", ippStsNoErr == status); return status; } cryptography-primitives-1.0.0/examples/dsa/dsa-dlp-sha-256-verification.cpp000066400000000000000000000175771470420105600266340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 * * \brief DSA-DLP verification scheme example * * This example demonstrates message verification according to * DSA-DLP scheme with (L = 3072, N = 256) DSA parameters and SHA-256 hash function. * * The DSA-DLP scheme is implemented according : Digital Signature Standard (DSS) (FIPS PUB 186-4) (July 2013) * * available at: * * http://dx.doi.org/10.6028/NIST.FIPS.186-4. * */ #include #include "bignum.h" #include "examples_common.h" #include "ippcp.h" /*! Parameters DSA-DLP scheme */ static const int L_BIT = 3072; static const int N_BIT = 256; /*! Message size in bytes */ static const int MSG_LEN_BYTE = 6; /*! Message text */ static Ipp8u MSG[MSG_LEN_BYTE] = {0x31, 0x32, 0x33, 0x34, 0x30, 0x30}; /*! The generator of the multiplicative subgroup */ static const BigNumber G( "0x" "6DEA4B8C3FE3AB91E3229FB14C1CFA822915769AF161405F48B7FADFE1EC5D9F" "EC4EF0CFBB2233FFDDFA5A554CFC68C6BC6A0BA30CEF6F51309294E622B58D4F" "ACE00AE9669D9172B15696839ED332AFD906E3F427D85A9AF73562B845BE53A3" "713C0219402A4C208E9B6A6873235E0BC20442E70AB69EDD46E8F3F7D58CB35E" "A3690C673F54CD37377725739F00EBE2B3B53BDAF89DDAC74012F8486BD3F521" "7579B4A303F61BCCC98931FABA969C8C2A27ACB04BC21201EDF9A7F6B42E10F7" "5DD23C3AB073D7290D173EBE6CB1919607BFE2BF0D829A609D8D3CDA7044FF8D" "FBBD463E68C9403A45834EC547A7D4FD5ABC68C5997CDC397120698F879356E0" "E74B62FE1A2938A5D1B486B53A5E0CB875E23A2E834EA563A4A9D4BE44045877" "DF020C30E22E55603F63D74ED2CAFDE18180EC294A7CE263D56EB280562687F6" "1F898F3C7D2B37D7F00250A43CA989DE16FA1AAB7D83E0DBF6AA66EDC36AD79E" "ECFE2F91CFAB6285BA10AE713126F69326540C461E44E45BDF076E4ED8D3E924"); /*! The modulus p */ static const BigNumber P( "0x" "DCD2F71FBA7AEB46AEEA858AB76F2102FA97A953ABCE9D791AA269F0161733AC" "3DF25F5C9DB3448F82846E355E23089614046D42B030298D94F5365D942CBB54" "90E40A1D5E6E577CC646A807F049A1FB42B97A9E64EFA1AA9EF93BB3C7120DDB" "F9C403E580431F1789127F0A64EA7B036EF12D07F02103655D63DDDA3C44AD32" "8F727C1D060FC92E3616976CF11BF1FEEFFF033490D98929252B585CD92C081A" "FCC71DAE6341AE8DD05E62AE297AD2B00560EC94F1F64482816E3AF052FC1DAF" "F0A9BF52034012594D4246036D040FA5E741E693E36B064BEDB224EA1F7C6C86" "171CA8FCFAC98C5DB6E34DAD307C5BFDECE4E578F0E18FCAAEE9D5B330ED69A7" "2D8FDDF878A58A57914247825AE6ED1CB8A6B241EA694B77F843EEE40F1BE90F" "26B26154813647D1E1AF01254CF21CFDD2E9EBA7E431BD8DB6164D05A3D3AE93" "71AF5D0D39A3A9B9F07BA61233C77A6BFC273515FB844DB8FAFD69B559CE844C" "7A3D686EA4991D9FE74CAD560489F3C1DBB4FD171EA8AE7874E302207C02A7B1"); /*! The order of the generator g */ static const BigNumber Q("0xF870D35CA9F84E6ACAD808D6AC35B13EE4073F26EA84FEFE08C4D9A565754037"); /*! The public key value */ static const BigNumber Y( "0x" "7E0062E6F32ECAB1EFFA38391B71A523221D6E97A61F55238F0A623CC42980B9" "87FB22EC6138E8D1C0D36C05D059CA0CA3F1A526A5F67B216341ABCD04105BB8" "EFC9E479C2532F9DEA6CDDFB4F57DE5B9D6964E3D314EB89693A3D57F82B9FF9" "3E0E0D11D72FA4F1BD82BB2B20F1B59547AFF7711DB319D7D06E6964BEB294E4" "4D34C2A21C7AC7CDAC5E91F2F6D183042AFC3644B09837FA2225A074CEB65D49" "9F73CEE04C705C82BB912F97D765D5F9C8CB442019E7DAC1E1CCCCEE990335EA" "3B8C837583595CD4F83169D4787FE4675386D604E8E205B977C7AB2369504282" "54E3B836BD00296257238D22BDA16A722E405DF82029E3384931FB0E4903C3F8" "771FB15708D4CB3238E7B2A68131BE518A08D6EFD483A01537A432046DCBD1FF" "A5FF831E0257B292012D5E1A44C6E32019A6B3AE176A67EDAF12EB27E68FA60A" "05AF4E5448D606C392B4A672B44298B1775A16B9440B131EB0D91CA3FDE1A1E5" "28B5FFFC31FFDF1449169C2F4ABD96809A75FB6C85AE845940C45D5AF8334057"); /*! R digital signature component */ static const BigNumber sigR("0x8C7F9B7F5D53A4D3877185D2EF69B2B3AB16321D996940C2EFCBEF01C0B598B4"); /*! S digital signature component */ static const BigNumber sigS("0x33708B0FD4109873550D02340918EC93E5383D471C9D0A322AA76C2872783CBA"); int main(void) { /*! Internal function status */ IppStatus status = ippStsNoErr; /* Pointer to DSA DLP context structure */ IppsDLPState* pDL = NULL; /* Result verification DSA DLP */ IppDLResult result = ippDLValid; /* Size of DSA-DLP context structure. It will be set up in ippsDLPGetSize(). */ int DLSize = 0; /* Digest size */ const int digestSizeBit = IPP_SHA256_DIGEST_BITSIZE; const int digestSizeByte = digestSizeBit / 8; /* Pointer to the SHA-256 hash method */ const IppsHashMethod* hashMethod = ippsHashMethod_SHA256(); /*! Algorithm */ do { /* 1. Create a digest by message */ /*! Buffer create digest */ Ipp8u md[digestSizeByte] = {}; /*! Create digest by message */ status = ippsHashMessage_rmf(MSG, MSG_LEN_BYTE, md, hashMethod); /*! Check status create digest */ if (ippStsNoErr != status) break; /*! * (!) Allocate BigNumber container for the shrank message digest. * Note, the DSA algorithm uses only leftmost |minSizeDigestBit| bits of the original message digest */ const int minSizeDigestBit = IPP_MIN(N_BIT, digestSizeBit); BigNumber digest(NULL, bitSizeInWords(minSizeDigestBit)); /*! Set digest to BigNumber */ status = ippsSetOctString_BN(md, bitSizeInBytes(minSizeDigestBit), digest); if (ippStsNoErr != status) break; /* 2. Get size needed for DSA DLP context structure */ status = ippsDLPGetSize(L_BIT, N_BIT, &DLSize); if (ippStsNoErr != status) break; /* 3. Allocate memory for DSA DLP context structure */ pDL = (IppsDLPState*)(new Ipp8u[DLSize]); if (NULL == pDL) { printf("ERROR: Cannot allocate memory (%d bytes) for DSA DLP context\n", DLSize); return -1; } /* 4. Initialize DSA DLP context */ status = ippsDLPInit(L_BIT, N_BIT, pDL); if (ippStsNoErr != status) break; /* 5. Set DL Domain Parameters */ status = ippsDLPSet(P, Q, G, pDL); if (ippStsNoErr != status) break; /* 6. Set up Key Pair into the DL context */ status = ippsDLPSetKeyPair(NULL, /* optional Private Key Set */ Y, pDL); if (ippStsNoErr != status) break; /* 7. Verify Signature DSA DLP */ status = ippsDLPVerifyDSA(digest, sigR, sigS, &result, pDL); if (ippStsNoErr != status) break; if (ippDLValid != result) status = ippStsErr; } while (0); /* end Algorithm */ /* 8. Remove secret and release resources */ if (NULL != pDL) delete[](Ipp8u*) pDL; PRINT_EXAMPLE_STATUS("ippsDLPVerifyDSA", "DSA-DLP Verification Hash Method Message SHA-256", ippStsNoErr == status); return status; } cryptography-primitives-1.0.0/examples/ecdsa/000077500000000000000000000000001470420105600213305ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/ecdsa/categoryOptions.cmake000066400000000000000000000015671470420105600255340ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2024 Intel Corporation # # 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. #========================================================================= set(ecdsa_CATEGORY_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/utils/bignum.cpp ${CMAKE_CURRENT_SOURCE_DIR}/utils/utils.cpp ) cryptography-primitives-1.0.0/examples/ecdsa/ecdsa-256r1-sign.cpp000066400000000000000000000133321470420105600246300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 // * // * \brief ECDSA signature example // * // * This example showcases the utilization of the elliptic curve // * digital signature algorithm(ECDSA) over NIST P-256 curve with // * DSA scheme for signature generation. // * // */ #include #include #include #include "ippcp.h" #include "bignum.h" #include "utils.h" #include "examples_common.h" /* Message digest */ static const Ipp8u msg_digest[] = { 0x56,0xec,0x33,0xa1,0xa6,0xe7,0xc4,0xdb,0x77,0x03,0x90,0x1a,0xfb,0x2e,0x1e,0x4e, 0x50,0x09,0xfe,0x04,0x72,0x89,0xc5,0xc2,0x42,0x13,0x6c,0xe3,0xb7,0xf6,0xac,0x44 }; /* Regular and ephemeral private keys */ static const Ipp8u d[] = { 0x64,0xb4,0x72,0xda,0x6d,0xa5,0x54,0xca,0xac,0x3e,0x4e,0x0b,0x13,0xc8,0x44,0x5b, 0x1a,0x77,0xf4,0x59,0xee,0xa8,0x4f,0x1f,0x58,0x8b,0x5f,0x71,0x3d,0x42,0x9b,0x51 }; static const Ipp8u k[] = { 0xde,0x68,0x2a,0x64,0x87,0x07,0x67,0xb9,0x33,0x5d,0x4f,0x82,0x47,0x62,0x4a,0x3b, 0x7f,0x3c,0xe9,0xf9,0x45,0xf2,0x80,0xa2,0x61,0x6a,0x90,0x4b,0xb1,0xbb,0xa1,0x94 }; /* signature */ static const Ipp8u r[] = { 0xac,0xc2,0xc8,0x79,0x6f,0x5e,0xbb,0xca,0x7a,0x5a,0x55,0x6a,0x1f,0x6b,0xfd,0x2a, 0xed,0x27,0x95,0x62,0xd6,0xe3,0x43,0x88,0x5b,0x79,0x14,0xb5,0x61,0x80,0xac,0xf3 }; static const Ipp8u s[] = { 0x03,0x89,0x05,0xcc,0x2a,0xda,0xcd,0x3c,0x5a,0x17,0x6f,0xe9,0x18,0xb2,0x97,0xef, 0x1c,0x37,0xf7,0x2b,0x26,0x76,0x6c,0x78,0xb2,0xa6,0x05,0xca,0x19,0x78,0xf7,0x8b }; static const unsigned int primeBitSize = 256; static const unsigned int ordWordSize = 8; static const unsigned int msgWordSize = 8; static const unsigned int primeWordSize = 8; /*! Main function */ int main(void) { /* Internal function status */ IppStatus status = ippStsNoErr; /* Size of the context of a GF field. It will be set up in ippsGFpGetSize() */ int GFpBuffSize = 0; /* Size of the context of an elliptic curve field. It will be set up in ippsGFpECGetSize() */ int GFpECBuffSize = 0; /* Size of the scratch buffer */ int scratchSize = 0; /* Create integers R and S for the digital signature */ BigNumber bnR(NULL, ordWordSize, ippBigNumPOS); BigNumber bnS(NULL, ordWordSize, ippBigNumPOS); /* Initialize message digest to be digitally signed i.e. encrypted with a private key */ BigNumber bnMsgDigest((const Ipp32u *)msg_digest, msgWordSize, ippBigNumPOS); /* Initialize regular and ephemeral private keys of the signer */ BigNumber bnRegPrivate((const Ipp32u *)d, primeWordSize, ippBigNumPOS); BigNumber bnEphPrivate((const Ipp32u *)k, primeWordSize, ippBigNumPOS); /* Initialize known digital signatures */ BigNumber bnRref((const Ipp32u *)r, ordWordSize, ippBigNumPOS); BigNumber bnSref((const Ipp32u *)s, ordWordSize, ippBigNumPOS); /* 1. Get the size of the context of a GF field */ status = ippsGFpGetSize(primeBitSize, &GFpBuffSize); if (!checkStatus("ippsGFpGetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for the GF field context */ std::vector pGFpBuff(GFpBuffSize); IppsGFpState *pGF = (IppsGFpState *)(pGFpBuff.data()); /* 3. Initialize the context of a prime finite field GF */ status = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if (!checkStatus("ippsGFpInitFixed", ippStsNoErr, status)) return status; /* 4. Get the size of an elliptic curve over the finite field */ status = ippsGFpECGetSize(pGF, &GFpECBuffSize); if (!checkStatus("ippsGFpECGetSize", ippStsNoErr, status)) return status; /* 5. Allocate memory for elliptic curve cryptosystem */ std::vector pGFpECBuff(GFpECBuffSize); IppsGFpECState *pEC = (IppsGFpECState *)(pGFpECBuff.data()); /* 6. Initialize the context for the cryptosystem based on a standard elliptic curve */ status = ippsGFpECInitStd256r1(pGF, pEC); if (!checkStatus("ippsGFpECInitStd256r1", ippStsNoErr, status)) return status; /* 7. Get the size of the scratch buffer */ status = ippsGFpECScratchBufferSize(2, pEC, &scratchSize); if (!checkStatus("ippsGFpECScratchBufferSize", ippStsNoErr, status)) return status; /* 8. Allocate memory for the scratch buffer */ std::vector pScratchBuffer(scratchSize); /* 9. Compute the digital signature over the message digest */ status = ippsGFpECSignDSA(bnMsgDigest, bnRegPrivate, bnEphPrivate, bnR, bnS, pEC, pScratchBuffer.data()); if (!checkStatus("ippsGFpECSignDSA", ippStsNoErr, status)) return status; bool sigFlagErr; /* 10. Validate the generated digest by comparing it to the known one */ sigFlagErr = (bnR == bnRref); sigFlagErr &= (bnS == bnSref); PRINT_EXAMPLE_STATUS("ippsGFpECSignDSA", "ECDSA signature", sigFlagErr) return status; } cryptography-primitives-1.0.0/examples/examplesBuildOptions.cmake000066400000000000000000000102121470420105600254210ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= macro(ippcp_extend_variable target added_value) set("${target}" "${${target}} ${added_value}") endmacro() include_directories( ${IPP_CRYPTO_INCLUDE_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/utils/ ${CMAKE_SYSTEM_INCLUDE_PATH} $<$:$ENV{ROOT}/compiler/include $ENV{ROOT}/compiler/include/icc> # $<$:$ENV{INCLUDE}> ) # Windows if(WIN32) set(LINK_LIB_STATIC_RELEASE libcmt.lib libcpmt.lib) set(LINK_LIB_STATIC_DEBUG libcmtd.lib libcpmtd.lib) # VS2015 or later (added Universal CRT) if (NOT (MSVC_VERSION LESS 1900)) set(LINK_LIB_STATIC_RELEASE ${LINK_LIB_STATIC_RELEASE} libucrt.lib libvcruntime.lib) set(LINK_LIB_STATIC_DEBUG ${LINK_LIB_STATIC_DEBUG} libucrtd.lib libvcruntimed.lib) endif() set(LINK_FLAG_S_ST_WINDOWS "/nologo /NODEFAULTLIB /VERBOSE:SAFESEH /INCREMENTAL:NO /NXCOMPAT /DYNAMICBASE /SUBSYSTEM:CONSOLE") ippcp_extend_variable(CMAKE_CXX_FLAGS "/nologo /W3 /EHa /Zm512 /GS") # Intel compiler-specific option if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "IntelLLVM") ippcp_extend_variable(CMAKE_CXX_FLAGS "-nologo -Qfp-speculation:safe -Qfreestanding") endif() set(OPT_FLAG "/Od") endif(WIN32) if(UNIX) # Common for Linux and macOS set(OPT_FLAG "-O2") if ((${ARCH} MATCHES "ia32") OR (NOT NONPIC_LIB)) ippcp_extend_variable(CMAKE_CXX_FLAGS "-fstack-protector") endif() # Linux if(NOT APPLE) set(LINK_FLAG_S_ST_LINUX "-Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now") if(NOT NONPIC_LIB) ippcp_extend_variable(LINK_FLAG_S_ST_LINUX "-fpie") ippcp_extend_variable(CMAKE_CXX_FLAGS "-fpie -fPIE") else() ippcp_extend_variable(LINK_FLAG_S_ST_LINUX "-no-pie") endif() ippcp_extend_variable(CMAKE_CXX_FLAGS "-Wformat -Wformat-security") ippcp_extend_variable(CMAKE_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2") if(${ARCH} MATCHES "ia32") ippcp_extend_variable(LINK_FLAG_S_ST_LINUX "-m32") ippcp_extend_variable(CMAKE_CXX_FLAGS "-m32") endif() else() # macOS set(LINK_FLAG_S_ST_MACOSX "-mmacosx-version-min=12.0") ippcp_extend_variable(CMAKE_CXX_FLAGS "-fpic") if(${ARCH} MATCHES "ia32") ippcp_extend_variable(CMAKE_CXX_FLAGS "-arch i386") else() ippcp_extend_variable(CMAKE_CXX_FLAGS "-arch x86_64") endif() endif() endif() macro(ippcp_example_set_build_options target link_libraries) if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${target} -static-libgcc -static-libstdc++) endif() target_link_libraries(${target} ${link_libraries}) set_target_properties(${target} PROPERTIES COMPILE_FLAGS ${OPT_FLAG}) if(WIN32) foreach(link ${LINK_LIB_STATIC_DEBUG}) target_link_libraries(${target} debug ${link}) endforeach() foreach(link ${LINK_LIB_STATIC_RELEASE}) target_link_libraries(${target} optimized ${link}) endforeach() set_target_properties(${target} PROPERTIES LINK_FLAGS ${LINK_FLAG_S_ST_WINDOWS}) target_compile_options(${target} PRIVATE $<$:/MTd /Zi> $<$:/MT /Zl>) else() if(NOT APPLE) set_target_properties(${target} PROPERTIES LINK_FLAGS "${LINK_FLAG_S_ST_LINUX}") target_link_libraries(${target} pthread) else() set_target_properties(${target} PROPERTIES LINK_FLAGS ${LINK_FLAG_S_ST_MACOSX}) endif() if(CODE_COVERAGE) target_link_libraries(${target} ipgo) endif() endif() endmacro() cryptography-primitives-1.0.0/examples/hash/000077500000000000000000000000001470420105600211745ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/hash/sm3_hash_rmf.cpp000066400000000000000000000065131470420105600242560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 * * \brief SM3 Hash example * * This example demonstrates usage of Hash algorithms to digest a message by * using SM3 standard. * Reduce Memory Footprint (_rmf) APIs are used in this example. * */ #include #include #include "ippcp.h" #include "examples_common.h" /*! Message text */ const Ipp8u msg[] = "abc"; /*! Known digest to check the results */ const Ipp8u sm3[] = "\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"; /*! Message size in bytes */ const int msg_byte_len = sizeof(msg)-1; int main(void) { /*! Internal function status */ IppStatus status = ippStsNoErr; /*! 1. Get the hash methods which is used */ const IppsHashMethod* hash_method = ippsHashMethod_SM3(); /*! The digest size of the SM3 standard */ Ipp32u hash_size = IPP_SM3_DIGEST_BYTESIZE; /*! The size of the SM3 hash context structure. It will be set up in ippsHashGetSize_rmf(). */ int context_size = 0; /*! 2. Get the size needed for the SM3 hash context structure */ status = ippsHashGetSize_rmf(&context_size); if (!checkStatus("ippsHashGetSize", ippStsNoErr, status)) { return status; } /*! 3. Allocate memory for the SM3 hash context structure */ std::vector context_buffer(context_size); /*! 4. Buffers for the digest and the tag */ Ipp8u output_hash_buffer[IPP_SM3_DIGEST_BYTESIZE]; IppsHashState_rmf* hash_state = (IppsHashState_rmf*)(context_buffer.data()); /*! 5. Initialize the initial SM3 hash context */ status = ippsHashInit_rmf(hash_state, hash_method); if (!checkStatus("ippsHashInit", ippStsNoErr, status)) { return status; } /*! 6. Call HashUpdate function to digest the message of the given length */ /*! This function can be called multiple times for a stream of messages */ status = ippsHashUpdate_rmf(msg, msg_byte_len, hash_state); if (!checkStatus("ippsHashUpdate", ippStsNoErr, status)) { return status; } /*! 7. Complete the computation of the digest value */ status = ippsHashFinal_rmf(output_hash_buffer, hash_state); if (!checkStatus("ippsHashFinal", ippStsNoErr, status)) { return status; } /*! 8. Verify the resulted digest with the known one */ int check = memcmp(output_hash_buffer, sm3, hash_size); if(check != 0) { printf("ERROR: Hash and the reference do not match\n"); status = -1; } PRINT_EXAMPLE_STATUS("ippsHashUpdate_rmf", "SM3 Hash", !status) return status; } cryptography-primitives-1.0.0/examples/post-quantum/000077500000000000000000000000001470420105600227265ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/post-quantum/lms_m32_h5_w8_verification.cpp000066400000000000000000000336401470420105600304700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 * * \brief Leighton-Micali Hash-Based Signatures (LMS) example * * This example demonstrates usage of LMS signatures verification. * * The LMS algorithm is implemented according to the * "Leighton-Micali Hash-Based Signatures" document: * * https://datatracker.ietf.org/doc/html/rfc8554 * */ /*! Define the macro to enable LMS usage */ #define IPPCP_PREVIEW_LMS #include #include "ippcp.h" #include "examples_common.h" /*! Algorithm ID for LMS */ IppsLMSAlgo lmsAlgo = IppsLMSAlgo::LMS_SHA256_M32_H5; //0x00000005 /*! Algorithm ID for OTS (one-time signature) */ IppsLMOTSAlgo lmotsAlgo = IppsLMOTSAlgo::LMOTS_SHA256_N32_W8; //0x00000004 /*! Index of the LMS leaf */ static Ipp32u q = 0x00000009; /*! Pointer to the LMS private key identifier */ static Ipp8u pI[] = { 0x05,0xbd,0x3d,0x90,0xcc,0xa2,0x47,0x08,0xe4,0x20,0x55,0x3e,0x5a,0xf7,0xb9,0xc8 }; /*! Pointer to the LMS public key */ static Ipp8u pK[] = { 0x21,0xf9,0xd9,0x09,0x97,0x11,0xef,0x5b,0x14,0x50,0x0b,0x6a,0x18,0x1e,0x73,0x9e, 0xd3,0x12,0x74,0xdb,0x72,0xac,0xe7,0xcf,0x29,0x32,0x9a,0x45,0xe8,0xde,0x11,0xfe }; /*! Message */ static Ipp8u pMsg[] = { 0x04,0x3d,0x64,0x00,0x10,0x3b,0x16,0x0c,0xf1,0x89,0xb4,0xcf,0xff,0x08,0x06,0xfe, 0xe3,0xe1,0x56,0x7f,0x2c,0x31,0x71,0x0f,0x82,0x84,0x52,0x74,0xf6,0xed,0x23,0x8e, 0x14,0xde,0x4d,0x53,0x99,0x86,0x88,0x99,0xab,0x6b,0xcf,0x00,0x98,0x08,0xb8,0xca, 0x30,0x81,0xed,0x11,0xaa,0x70,0x35,0x52,0x90,0xfd,0x86,0x98,0xd4,0xc1,0x77,0xc1, 0x89,0x4c,0xd8,0xb8,0xd3,0x36,0x7f,0xd0,0xf3,0x00,0xef,0x62,0x83,0x02,0x0d,0x09, 0x1c,0x27,0x35,0x6d,0xaf,0xad,0xdb,0xed,0x96,0x21,0x8a,0x19,0x56,0x7b,0x99,0x9a, 0xcd,0x53,0x02,0xa5,0x11,0xd4,0xf1,0x65,0xef,0x9c,0xbe,0x85,0x5d,0xcc,0x73,0x1b, 0x16,0xdd,0x13,0x6e,0x5c,0x44,0x15,0x8b,0xf1,0xe9,0x8c,0xc5,0x9c,0x6f,0x6c,0xb2 }; /*! Pointer to the C LM-OTS value */ static Ipp8u pC[] = { 0x67,0x79,0x57,0x17,0x51,0x05,0x2c,0xe8,0xfe,0xe9,0x23,0xda,0x26,0xef,0x27,0x1e, 0x62,0xbe,0x08,0x43,0xaa,0xdf,0x7c,0x69,0x19,0x68,0x43,0x32,0x8c,0xb0,0x4e,0x3d }; /*! Pointer to the y LM-OTS value */ static Ipp8u pY[] = { 0x57,0x71,0xa7,0x12,0x2b,0x87,0xf2,0xbd,0x61,0x11,0x9c,0xd4,0x20,0x56,0xec,0x04, 0xc0,0x60,0xbe,0x2a,0xe2,0xc2,0xd6,0x72,0xa8,0x1f,0x1a,0x4a,0x6a,0x76,0xc2,0x4c, 0x01,0xa0,0x69,0x63,0x7f,0x85,0xdd,0xb4,0x5d,0x8d,0x19,0xd7,0xef,0x7c,0xc8,0x9a, 0x47,0xfe,0x1e,0x79,0xfd,0x80,0x65,0x51,0x17,0xed,0xb6,0x3f,0x17,0xd0,0xb6,0xcc, 0x0f,0xca,0xa9,0x28,0xc2,0xef,0x1e,0x41,0x4e,0xf7,0x34,0xa8,0xda,0xfe,0xbc,0x82, 0xdb,0x33,0x3e,0x03,0xba,0x51,0x40,0x6e,0x07,0x6b,0xfc,0x2d,0x3e,0x81,0x30,0x09, 0xd9,0x68,0xa8,0x71,0x00,0xf0,0x33,0xcf,0x0b,0x57,0x04,0xfc,0x4e,0x61,0x8a,0xa5, 0x80,0xa1,0xe0,0x48,0xef,0xc3,0xd5,0x6e,0xe7,0xa2,0xea,0x02,0x14,0xa6,0xfe,0x1f, 0x39,0xa4,0xf2,0xfb,0x61,0x2f,0x44,0xbe,0xde,0xd3,0x73,0x34,0x0e,0x76,0x48,0x27, 0xc5,0xc5,0x8c,0xb9,0x07,0xcd,0x08,0xdd,0xfb,0xde,0x01,0xbb,0x11,0xff,0x3a,0x89, 0xff,0xaa,0xd8,0xcd,0x7c,0x17,0x02,0x71,0x08,0x3c,0xe5,0x0f,0x0f,0xb9,0xea,0xbb, 0xa8,0x9d,0xb6,0x0b,0x00,0x73,0xe7,0xaf,0xc8,0x1e,0x4c,0x6f,0x82,0x4a,0xef,0x09, 0xf8,0xbf,0xc9,0x49,0x67,0x16,0x9b,0xcf,0xa0,0x84,0x76,0x55,0x57,0x41,0x10,0x19, 0x37,0x0b,0x29,0xba,0x0d,0x32,0xa8,0x8e,0x84,0x2c,0x19,0xdf,0x14,0x5a,0x69,0x36, 0x8d,0xf7,0xe1,0x55,0x7d,0x93,0x7a,0xae,0xdb,0x07,0xf6,0xbc,0xda,0xf9,0x78,0xeb, 0x9e,0x50,0xf3,0xc8,0x47,0x38,0x2a,0xd4,0x3b,0xfc,0xc0,0xe0,0xd0,0xbf,0xd8,0x60, 0x46,0x63,0xc7,0xfb,0xa8,0x84,0x45,0x4d,0x23,0x98,0x96,0xd8,0xff,0x8a,0x99,0xa3, 0x34,0xf0,0xd3,0x32,0x22,0xaa,0x15,0xbd,0x47,0x9f,0xcd,0x49,0x52,0x0b,0x5b,0x2d, 0x83,0xd8,0xbf,0x4d,0xbd,0x3d,0x7e,0x9d,0xc8,0x0b,0x62,0x0c,0xc7,0x03,0x45,0x7f, 0x55,0x90,0x35,0xdd,0x1f,0x53,0xdc,0xec,0x0b,0x4d,0x89,0xca,0xb1,0xa3,0xb8,0x87, 0x7b,0x31,0x1c,0x24,0x90,0x44,0x9d,0xf7,0xa6,0x1c,0xf8,0xed,0xf3,0x29,0xd6,0x96, 0x26,0xca,0x42,0x4b,0xdf,0x61,0x00,0x91,0x92,0x08,0x37,0x76,0xbb,0x96,0x9e,0xd5, 0x8d,0x76,0xa9,0x52,0x40,0xdb,0x3f,0xd6,0xec,0xa0,0x06,0x89,0x88,0x11,0x18,0x38, 0xae,0xcb,0xa0,0x71,0xab,0x3b,0x7b,0xe0,0x94,0x30,0x59,0x38,0xaf,0xb0,0x8c,0xdd, 0xf9,0xcd,0xaf,0x82,0x49,0x90,0x29,0xf6,0x24,0x9a,0xa5,0x51,0x1b,0x99,0x45,0x64, 0x13,0x94,0x9e,0x3e,0x4e,0x43,0x40,0x73,0x0d,0x68,0x0b,0x68,0xde,0xb5,0xc9,0xd5, 0xce,0xef,0x7b,0x8b,0x1e,0xd9,0x7e,0xc8,0xa1,0x69,0xb5,0x2b,0xd0,0x54,0xb0,0x53, 0x41,0x9f,0xfa,0x77,0x34,0x55,0xcd,0xf4,0x79,0xa6,0x0d,0x3c,0xc7,0x05,0xd8,0xf2, 0x08,0x48,0x32,0xb7,0x96,0x22,0xb6,0xe5,0xac,0x83,0x06,0xa7,0x68,0x3f,0xea,0x03, 0xcd,0x79,0xe8,0xff,0x54,0xe2,0xf5,0xa0,0x6b,0x69,0xc1,0xca,0xb3,0xd4,0x2b,0x60, 0xa8,0xa8,0xbe,0xcb,0x9e,0x94,0x2e,0xf1,0xfc,0xd7,0x55,0xac,0x08,0xd7,0xc4,0x22, 0x4f,0xf3,0xf5,0xbf,0x49,0xb8,0xf7,0x5f,0xae,0x60,0x92,0xe4,0x3a,0x8f,0x30,0x35, 0x41,0x8c,0xd4,0x03,0x31,0x6c,0x08,0xa8,0x08,0x37,0xb4,0x6c,0x22,0xca,0xa2,0xf7, 0xff,0xc1,0x62,0x49,0xcd,0x5c,0x17,0x25,0xc5,0x4e,0xaa,0x26,0xb9,0xd7,0x72,0xf9, 0x61,0x21,0xbf,0x95,0xda,0xcf,0x30,0x1d,0x42,0x8c,0x9d,0xf4,0x57,0x36,0x25,0xb7, 0xfb,0xfa,0x64,0xba,0x7f,0x3e,0x0d,0x5a,0x72,0xa7,0x8d,0x13,0xf6,0x2d,0x57,0x76, 0xa4,0x61,0x59,0x9d,0x4d,0xd5,0x99,0x0e,0xae,0x73,0x6b,0x6a,0xf1,0x64,0x93,0xf1, 0xa7,0xd0,0xe4,0x4f,0x2b,0x71,0xd9,0x6e,0x0e,0x89,0x28,0x5a,0xec,0xc1,0x15,0x50, 0x81,0x21,0x6c,0xe0,0xba,0xbb,0xce,0x4f,0x4e,0x0b,0x80,0xa1,0x92,0x6a,0xea,0x6a, 0xcb,0x3e,0xa3,0xcb,0x7a,0x23,0x61,0x5d,0x41,0x08,0xba,0xf4,0x51,0x9b,0xf7,0x10, 0x27,0x0e,0x89,0x6b,0x42,0xc5,0x5c,0x3c,0x9e,0x60,0x42,0x43,0x29,0xbf,0xbc,0x8a, 0xd5,0x9f,0x4c,0xa2,0x0b,0x5e,0xbb,0xa4,0x93,0xe0,0xb3,0x9d,0xb9,0x7e,0xc7,0x9b, 0x36,0x2a,0xc7,0x21,0x5e,0x25,0x5d,0xeb,0x74,0x68,0xfd,0xf4,0x0e,0x0f,0x39,0x0c, 0x65,0x0c,0x66,0x51,0x0c,0xf4,0xad,0x9c,0x44,0x94,0x34,0xae,0x25,0x8b,0x56,0x1e, 0x8e,0xc1,0x57,0x29,0xa6,0x90,0x62,0xb8,0xb2,0x8d,0x6c,0x79,0xf4,0x90,0x64,0xd2, 0x4a,0x52,0xe9,0x15,0x95,0xc9,0x3f,0x83,0xc4,0x0f,0xec,0xa2,0x11,0xe2,0x8b,0x50, 0x1f,0x13,0xcc,0x80,0x2f,0x0b,0x36,0x35,0x2c,0x85,0x41,0x79,0xd2,0xce,0x46,0x12, 0xc7,0xf0,0xd3,0x96,0x04,0x4d,0x1c,0x69,0x4f,0x8f,0xe3,0xa0,0x1c,0xe2,0xa8,0x8c, 0xe8,0xd1,0x74,0xca,0x66,0x99,0x1b,0x9d,0x6c,0x50,0x72,0xf2,0xd2,0x01,0x60,0xdf, 0x74,0x81,0xaf,0xbd,0x7a,0xc9,0xd2,0xf7,0x5a,0x7d,0xfe,0x36,0x9c,0x61,0xed,0xc9, 0xfb,0x27,0xbb,0xa3,0xd8,0x71,0x3c,0x57,0x5d,0xdd,0xab,0xcc,0x27,0xc6,0xb9,0x42, 0x9b,0xcb,0x7e,0xec,0xf8,0x53,0x2e,0xf0,0xf4,0xc9,0x46,0x46,0xd8,0x94,0xd6,0xf7, 0x8d,0x64,0xd7,0xba,0xb1,0x39,0x8e,0x7f,0xef,0xfd,0xb0,0xb0,0x31,0x4f,0x43,0x0f, 0xec,0xa8,0x70,0x57,0x3a,0xe3,0x88,0xbc,0xa7,0xd9,0xf9,0x39,0xa4,0xb9,0x91,0x59, 0xc7,0xbf,0xec,0x78,0xa9,0xce,0x33,0x99,0xf3,0x83,0xfa,0xaf,0x59,0xab,0x65,0xc6, 0xe2,0xaa,0x30,0x08,0xd7,0x99,0x71,0x65,0xf1,0xb6,0xfc,0x4f,0xf1,0x68,0xa2,0xd8, 0x61,0x8a,0xe5,0x0f,0x2b,0x60,0xda,0x8d,0xea,0x7e,0xf6,0x2c,0xae,0xeb,0x26,0xae, 0x29,0x5d,0xab,0xc7,0x3f,0x27,0x2c,0x51,0xf1,0x3f,0x22,0x22,0xef,0x52,0x4e,0xcb, 0x70,0xd8,0xba,0x41,0x53,0xb4,0xd9,0xdd,0xdc,0xe8,0xcd,0x7f,0xc1,0xb8,0x2b,0x8e, 0x3b,0x3b,0x86,0xd7,0x4c,0x36,0x69,0xf6,0x31,0xcf,0x37,0xbd,0x16,0xe9,0x2f,0x4f, 0xf9,0x13,0x19,0xf2,0x3b,0x41,0x1c,0x78,0x62,0x9c,0x5f,0x95,0xab,0xdd,0x17,0xe7, 0x2e,0x8f,0x92,0x79,0xe0,0xeb,0xe0,0x49,0x58,0x6d,0x3c,0x26,0xb8,0x5c,0x93,0xb9, 0xd7,0x6e,0xca,0x28,0x70,0x9c,0xbe,0xef,0x08,0x4e,0xe2,0x20,0x3a,0xdb,0x92,0x0b, 0x29,0x2f,0xfd,0xc8,0x3a,0x4a,0x7c,0xa4,0x87,0x6f,0x33,0x8d,0x8e,0x7f,0x51,0x6f, 0xab,0x11,0x42,0xc3,0x75,0xed,0x69,0xb1,0xf1,0x32,0xd8,0xd8,0xe2,0xc2,0x0d,0x52, 0x21,0xad,0x97,0x05,0x60,0x1d,0x43,0x52,0x4c,0xb1,0x61,0x49,0xef,0x2c,0xc1,0xad, 0x4c,0x0c,0xe7,0x1b,0x81,0xc6,0x2f,0x47,0xe2,0xb0,0xe6,0x6c,0xb8,0xd0,0x2d,0xe4, 0x46,0xd2,0x0a,0x13,0xab,0xb3,0xb9,0x13,0x9e,0x41,0xba,0x06,0x2d,0x11,0xe4,0xe6 }; /*! Pointer to the LMS authorization path */ static Ipp8u pAuthPath[] = { 0xc7,0x14,0x06,0x72,0xbf,0x82,0x00,0x91,0xe3,0xd5,0xd6,0x4c,0x2a,0x71,0x21,0x83, 0x3b,0xea,0xb1,0x16,0x74,0xd8,0xae,0x4e,0xe3,0x15,0xe7,0x85,0x4d,0xa7,0xa1,0x00, 0x4b,0x2b,0x7b,0xc6,0xad,0x89,0xa8,0x6c,0xe8,0xf6,0x60,0x22,0x19,0xb9,0xc3,0x37, 0x5b,0xca,0x93,0xf1,0x0e,0xa3,0x2f,0x10,0xfb,0x2f,0x39,0x21,0x1c,0x33,0x78,0xb7, 0x89,0x0f,0x77,0x18,0xe8,0x73,0x04,0x54,0x71,0x08,0x0b,0x86,0x94,0x9e,0xc7,0x55, 0x25,0xb9,0x4a,0xe1,0xbb,0x45,0x06,0x00,0x66,0xdf,0x75,0x17,0x8b,0x0d,0xc3,0xa6, 0x65,0x9a,0x5e,0xc7,0x5d,0xe5,0xc1,0x29,0x1f,0x5f,0xfc,0xcb,0x89,0x84,0x5c,0xfb, 0x7a,0x81,0xe2,0x54,0x05,0xd1,0x90,0xe3,0x7d,0xe4,0x3c,0x9f,0xe2,0xdc,0xd3,0xfd, 0x7e,0x6e,0x72,0xfa,0xc7,0xbe,0xcb,0xd5,0xd0,0x1e,0xc4,0xae,0x48,0x9a,0x92,0x45, 0xc3,0xc2,0xc1,0x06,0x91,0xbe,0x15,0x1f,0xa6,0xa1,0x87,0xbb,0x7c,0x68,0x7b,0xb8 }; int main(void) { /* Internal function status */ IppStatus status = ippStsNoErr; /* Deleter to use in unique_ptr to clean the memory during the object's destruction */ auto toIpp8uDeleter = [] (auto* pData) { delete[] (Ipp8u*)pData; }; const Ipp32s msgLen = sizeof(pMsg); /* Create an algorithm ID to put into the ippsLMS functions */ const IppsLMSAlgoType lmsAlgTypePk = { lmotsAlgo, lmsAlgo }; /* 1. Get the scratch buffer size */ int buffSize; status = ippsLMSBufferGetSize(&buffSize, msgLen, lmsAlgTypePk); if (!checkStatus("ippsLMSBufferGetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for the scratch buffer */ std::unique_ptr pScratchBuffer(new Ipp8u[buffSize]); /* 3. Get the LMS public key state size */ int ippcpPubKeySize; status = ippsLMSPublicKeyStateGetSize(&ippcpPubKeySize, lmsAlgTypePk); if (!checkStatus("ippsLMSPublicKeyStateGetSize", ippStsNoErr, status)) return status; /* 4. Allocate memory for the LMS public key state */ std::unique_ptr pPubKey((IppsLMSPublicKeyState *)(new Ipp8u[ippcpPubKeySize]), toIpp8uDeleter); /* 5. Set the LMS public key */ status = ippsLMSSetPublicKeyState(lmsAlgTypePk, pI, pK, pPubKey.get()); if (!checkStatus("ippsLMSSetPublicKeyState", ippStsNoErr, status)) return status; /* 6. Get the LMS signature state size */ int sigBuffSize; status = ippsLMSSignatureStateGetSize(&sigBuffSize, lmsAlgTypePk); if (!checkStatus("ippsLMSSignatureStateGetSize", ippStsNoErr, status)) return status; /* 7. Allocate memory for the LMS signature buffer */ std::unique_ptr pSignature((IppsLMSSignatureState *)(new Ipp8u[sigBuffSize]), toIpp8uDeleter); /* 8. Set the LMS signature */ status = ippsLMSSetSignatureState(lmsAlgTypePk, q, pC, pY, pAuthPath, pSignature.get()); if (!checkStatus("ippsLMSSetSignatureState", ippStsNoErr, status)) return status; int is_valid = 0; /* 9. Verify the LMS signature */ status = ippsLMSVerify(pMsg, msgLen, pSignature.get(), &is_valid, pPubKey.get(), pScratchBuffer.get()); if (!checkStatus("ippsLMSVerify", ippStsNoErr, status)) return status; PRINT_EXAMPLE_STATUS("ippsLMSVerify", "LMS Verification", 1 == is_valid); return status; } cryptography-primitives-1.0.0/examples/rsa/000077500000000000000000000000001470420105600210365ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/rsa/categoryOptions.cmake000066400000000000000000000015651470420105600252400ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= set(rsa_CATEGORY_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/utils/bignum.cpp ${CMAKE_CURRENT_SOURCE_DIR}/utils/utils.cpp ) cryptography-primitives-1.0.0/examples/rsa/rsa-1k-oaep-sha1-encryption.cpp000066400000000000000000000116411470420105600266070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * * \brief RSA-OAEP encryption scheme usage example. * * This example demonstrates message encryption according to * RSA-OAEP scheme with 1024-bit RSA modulus and SHA-1 hash function. * It uses Reduced Memory Footprint (_rmf) version of the function. * * The RSASSA-OAEP scheme is implemented according to the PKCS#1 v2.1: RSA Cryptography Standard (June 2002), * available at: * * https://tools.ietf.org/html/rfc3447. * */ #include #include "ippcp.h" #include "examples_common.h" #include "bignum.h" /*! 1024-bit RSA Modulus N = P*Q */ static BigNumber N("0xBBF82F090682CE9C2338AC2B9DA871F7368D07EED41043A440D6B6F07454F51FB8DFBAAF035C02AB61EA48CEEB6FCD4876ED520D60E1E" "C4619719D8A5B8B807FAFB8E0A3DFC737723EE6B4B7D93A2584EE6A649D060953748834B2454598394EE0AAB12D7B61A51F527A9A41F6C1" "687FE2537298CA2A8F5946F8E5FD091DBDCB"); /*! Public exponent */ static BigNumber E("0x11"); /*! Plain text source message */ static Ipp8u sourceMessage[] = "\xd4\x36\xe9\x95\x69\xfd\x32\xa7" "\xc8\xa0\x5b\xbc\x90\xd3\x2c\x49"; /*! Seed string of hash size */ static Ipp8u seed[] = "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4" "\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f"; /*! Reference cipher text. Length is equal to RSA modulus size */ static Ipp8u cipherTextRef[] = "\x12\x53\xE0\x4D\xC0\xA5\x39\x7B\xB4\x4A\x7A\xB8\x7E\x9B\xF2\xA0" "\x39\xA3\x3D\x1E\x99\x6F\xC8\x2A\x94\xCC\xD3\x00\x74\xC9\x5D\xF7" "\x63\x72\x20\x17\x06\x9E\x52\x68\xDA\x5D\x1C\x0B\x4F\x87\x2C\xF6" "\x53\xC1\x1D\xF8\x23\x14\xA6\x79\x68\xDF\xEA\xE2\x8D\xEF\x04\xBB" "\x6D\x84\xB1\xC3\x1D\x65\x4A\x19\x70\xE5\x78\x3B\xD6\xEB\x96\xA0" "\x24\xC2\xCA\x2F\x4A\x90\xFE\x9F\x2E\xF5\xC9\xC1\x40\xE5\xBB\x48" "\xDA\x95\x36\xAD\x87\x00\xC8\x4F\xC9\x13\x0A\xDE\xA7\x4E\x55\x8D" "\x51\xA7\x4D\xDF\x85\xD8\xB5\x0D\xE9\x68\x38\xD6\x06\x3E\x09\x55"; /*! Main function */ int main(void) { /* Internal function status */ IppStatus status = ippStsNoErr; /* Size in bits of RSA modulus */ const int bitSizeN = N.BitSize(); /* Size in bits of RSA public exponent */ const int bitSizeE = E.BitSize(); /* Allocate memory for public key. */ int keySize = 0; ippsRSA_GetSizePublicKey(bitSizeN, bitSizeE, &keySize); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)(new Ipp8u[keySize]); ippsRSA_InitPublicKey(bitSizeN, bitSizeE, pPubKey, keySize); /* Allocate memory for cipher text, not less than RSA modulus size. */ int cipherTextLen = bitSizeInBytes(bitSizeN); Ipp8u* pCipherText = new Ipp8u[cipherTextLen]; do { /* Set public key */ status = ippsRSA_SetPublicKey(N, E, pPubKey); if (!checkStatus("ippsRSA_SetPublicKey", ippStsNoErr, status)) break; /* Calculate temporary buffer size */ int pubBufSize = 0; status = ippsRSA_GetBufferSizePublicKey(&pubBufSize, pPubKey); if (!checkStatus("ippsRSA_GetBufferSizePublicKey", ippStsNoErr, status)) break; /* Allocate memory for temporary buffer */ Ipp8u* pScratchBuffer = new Ipp8u[pubBufSize]; /* Encrypt message */ status = ippsRSAEncrypt_OAEP_rmf(sourceMessage, sizeof(sourceMessage)-1, 0 /* optional label associated with the sourceMessage */, 0, /* label length */ seed, pCipherText, pPubKey, ippsHashMethod_SHA1(), pScratchBuffer); if (pScratchBuffer) delete [] pScratchBuffer; if (!checkStatus("ippsRSAEncrypt_OAEP_rmf", ippStsNoErr, status)) break; if (0 != memcmp(cipherTextRef, pCipherText, sizeof(cipherTextRef)-1)) { printf("ERROR: Encrypted and reference messages do not match\n"); status = ippStsErr; } } while (0); PRINT_EXAMPLE_STATUS("ippsRSAEncrypt_OAEP_rmf", "RSA-OAEP 1024 (SHA1) Encryption", ippStsNoErr == status); if (pCipherText) delete [] pCipherText; if (pPubKey) delete [] (Ipp8u*)pPubKey; return status; } cryptography-primitives-1.0.0/examples/rsa/rsa-1k-oaep-sha1-type2-decryption.cpp000066400000000000000000000135331470420105600276400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * * \brief RSA-OAEP decryption scheme usage example. * * This example demonstrates message decryption according to * RSA-OAEP scheme with 1024-bit RSA modulus and SHA-1 hash function. * The private key of Type2 (to be able to apply Chinese Reminder Theorem) is used in this example. * It uses Reduced Memory Footprint (_rmf) version of the function. * * The RSASSA-OAEP scheme is implemented according to the PKCS#1 v2.1: RSA Cryptography Standard (June 2002), * available at: * * https://tools.ietf.org/html/rfc3447. * */ #include #include "ippcp.h" #include "examples_common.h" #include "bignum.h" /*! Prime P factor */ static BigNumber P("0xEECFAE81B1B9B3C908810B10A1B5600199EB9F44AEF4FDA493B81A9E3D84F632" "124EF0236E5D1E3B7E28FAE7AA040A2D5B252176459D1F397541BA2A58FB6599"); /*! Prime Q factor */ static BigNumber Q("0xC97FB1F027F453F6341233EAAAD1D9353F6C42D08866B1D05A0F2035028B9D86" "9840B41666B42E92EA0DA3B43204B5CFCE3352524D0416A5A441E700AF461503"); /*! D mod (p-1) factor */ static BigNumber DP("0x54494CA63EBA0337E4E24023FCD69A5AEB07DDDC0183A4D0AC9B54B051F2B13E" "D9490975EAB77414FF59C1F7692E9A2E202B38FC910A474174ADC93C1F67C981"); /*! D mod (q-1) factor */ static BigNumber DQ("0x471E0290FF0AF0750351B7F878864CA961ADBD3A8A7E991C5C0556A94C3146A7" "F9803F8F6F8AE342E931FD8AE47A220D1B99A495849807FE39F9245A9836DA3D"); /*! Q^-1 mod p factor */ static BigNumber InvQ("0xB06C4FDABB6301198D265BDBAE9423B380F271F73453885093077FCD39E2119F" "C98632154F5883B167A967BF402B4E9E2E0F9656E698EA3666EDFB25798039F7"); /*! Plain text */ static Ipp8u sourceMessageRef[] = "\xd4\x36\xe9\x95\x69\xfd\x32\xa7" "\xc8\xa0\x5b\xbc\x90\xd3\x2c\x49"; /*! Cipher text to decrypt. */ static Ipp8u cipherText[] = "\x12\x53\xE0\x4D\xC0\xA5\x39\x7B\xB4\x4A\x7A\xB8\x7E\x9B\xF2\xA0" "\x39\xA3\x3D\x1E\x99\x6F\xC8\x2A\x94\xCC\xD3\x00\x74\xC9\x5D\xF7" "\x63\x72\x20\x17\x06\x9E\x52\x68\xDA\x5D\x1C\x0B\x4F\x87\x2C\xF6" "\x53\xC1\x1D\xF8\x23\x14\xA6\x79\x68\xDF\xEA\xE2\x8D\xEF\x04\xBB" "\x6D\x84\xB1\xC3\x1D\x65\x4A\x19\x70\xE5\x78\x3B\xD6\xEB\x96\xA0" "\x24\xC2\xCA\x2F\x4A\x90\xFE\x9F\x2E\xF5\xC9\xC1\x40\xE5\xBB\x48" "\xDA\x95\x36\xAD\x87\x00\xC8\x4F\xC9\x13\x0A\xDE\xA7\x4E\x55\x8D" "\x51\xA7\x4D\xDF\x85\xD8\xB5\x0D\xE9\x68\x38\xD6\x06\x3E\x09\x55"; /*! Main function */ int main(void) { /* Internal function status */ IppStatus status = ippStsNoErr; /* Size in bits of P factor */ const int bitSizeP = P.BitSize(); /* Size in bits of Q factor */ const int bitSizeQ = Q.BitSize(); /* Allocate memory for private key. * There are two types of private keys that are supported: Type1 and Type2. * You can choose any of them, depending on your private key representation. * This example uses Type2 key. * For more information, see https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-reference/current/crypto-ref-getsize-public-private1-private2.html */ int keySize = 0; ippsRSA_GetSizePrivateKeyType2(bitSizeP, bitSizeQ, &keySize); IppsRSAPrivateKeyState* pPrvKeyType2 = (IppsRSAPrivateKeyState*)(new Ipp8u [keySize]); ippsRSA_InitPrivateKeyType2(bitSizeP, bitSizeQ, pPrvKeyType2, keySize); /* Allocate memory for decrypted plain text, not less than RSA modulus size. */ int plainTextLen = bitSizeInBytes(bitSizeP + bitSizeQ); Ipp8u* pPlainText = new Ipp8u[plainTextLen]; do { /* Set private key */ status = ippsRSA_SetPrivateKeyType2(P, Q, DP, DQ, InvQ, pPrvKeyType2); if (!checkStatus("ippsRSA_SetPrivateKeyType2", ippStsNoErr, status)) break; /* Calculate temporary buffer size */ int bufSize = 0; status = ippsRSA_GetBufferSizePrivateKey(&bufSize, pPrvKeyType2); if (!checkStatus("ippsRSA_GetBufferSizePrivateKey", ippStsNoErr, status)) break; /* Allocate memory for temporary buffer */ Ipp8u* pScratchBuffer = new Ipp8u[bufSize]; /* Decrypt message */ status = ippsRSADecrypt_OAEP_rmf(cipherText, 0 /* optional label to be associated with the message */, 0, /* label length */ pPlainText, &plainTextLen, pPrvKeyType2, ippsHashMethod_SHA1(), pScratchBuffer); if (pScratchBuffer) delete [] pScratchBuffer; if (!checkStatus("ippsRSADecrypt_OAEP_rmf", ippStsNoErr, status)) break; if (0 != memcmp(sourceMessageRef, pPlainText, sizeof(sourceMessageRef)-1)) { printf("ERROR: Decrypted and plain text messages do not match\n"); status = ippStsErr; } } while (0); PRINT_EXAMPLE_STATUS("ippsRSADecrypt_OAEP_rmf", "RSA-OAEP 1024 (SHA1) Type2 decryption", ippStsNoErr == status) if (pPlainText) delete [] pPlainText; if (pPrvKeyType2) delete [] (Ipp8u*)pPrvKeyType2; return status; } cryptography-primitives-1.0.0/examples/rsa/rsa-1k-pss-sha1-verification.cpp000066400000000000000000000122061470420105600267560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * * \brief RSASSA-PSS verification scheme usage example. * * This example demonstrates message verification according to * RSASSA-PSS scheme with 1024-bit RSA modulus and SHA-1 hash function. * It uses Reduced Memory Footprint (_rmf) version of the function. * * The RSASSA-PSS scheme is implemented according to the PKCS#1 v2.1: RSA Cryptography Standard (June 2002), * available at: * * https://tools.ietf.org/html/rfc3447. * */ #include "ippcp.h" #include "examples_common.h" #include "bignum.h" /*! 1024-bit RSA Modulus N = P*Q */ static BigNumber N("0xA2BA40EE07E3B2BD2F02CE227F36A195024486E49C19CB41BBBDFBBA98B22B0E577C2EEAFFA20D883A76E65E394C69D4" "B3C05A1E8FADDA27EDB2A42BC000FE888B9B32C22D15ADD0CD76B3E7936E19955B220DD17D4EA904B1EC102B2E4DE775" "1222AA99151024C7CB41CC5EA21D00EEB41F7C800834D2C6E06BCE3BCE7EA9A5"); /*! Public exponent */ static BigNumber E("0x10001"); /*! Message to be signed */ static Ipp8u sourceMessage[] = "\x85\x9e\xef\x2f\xd7\x8a\xca\x00\x30\x8b\xdc\x47\x11\x93\xbf\x55" "\xbf\x9d\x78\xdb\x8f\x8a\x67\x2b\x48\x46\x34\xf3\xc9\xc2\x6e\x64" "\x78\xae\x10\x26\x0f\xe0\xdd\x8c\x08\x2e\x53\xa5\x29\x3a\xf2\x17" "\x3c\xd5\x0c\x6d\x5d\x35\x4f\xeb\xf7\x8b\x26\x02\x1c\x25\xc0\x27" "\x12\xe7\x8c\xd4\x69\x4c\x9f\x46\x97\x77\xe4\x51\xe7\xf8\xe9\xe0" "\x4c\xd3\x73\x9c\x6b\xbf\xed\xae\x48\x7f\xb5\x56\x44\xe9\xca\x74" "\xff\x77\xa5\x3c\xb7\x29\x80\x2f\x6e\xd4\xa5\xff\xa8\xba\x15\x98" "\x90\xfc"; /*! Signature to verify */ static Ipp8u signatureRef[] = "\x8d\xaa\x62\x7d\x3d\xe7\x59\x5d\x63\x05\x6c\x7e\xc6\x59\xe5\x44" "\x06\xf1\x06\x10\x12\x8b\xaa\xe8\x21\xc8\xb2\xa0\xf3\x93\x6d\x54" "\xdc\x3b\xdc\xe4\x66\x89\xf6\xb7\x95\x1b\xb1\x8e\x84\x05\x42\x76" "\x97\x18\xd5\x71\x5d\x21\x0d\x85\xef\xbb\x59\x61\x92\x03\x2c\x42" "\xbe\x4c\x29\x97\x2c\x85\x62\x75\xeb\x6d\x5a\x45\xf0\x5f\x51\x87" "\x6f\xc6\x74\x3d\xed\xdd\x28\xca\xec\x9b\xb3\x0e\xa9\x9e\x02\xc3" "\x48\x82\x69\x60\x4f\xe4\x97\xf7\x4c\xcd\x7c\x7f\xca\x16\x71\x89" "\x71\x23\xcb\xd3\x0d\xef\x5d\x54\xa2\xb5\x53\x6a\xd9\x0a\x74\x7e"; /*! Main function */ int main(void) { /* Internal function status */ IppStatus status = ippStsNoErr; /* Size in bits of RSA modulus */ const int bitSizeN = N.BitSize(); /* Size in bits of RSA public exponent */ const int bitSizeE = E.BitSize(); /* Allocate memory for public key. */ int keySize = 0; ippsRSA_GetSizePublicKey(bitSizeN, bitSizeE, &keySize); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)(new Ipp8u[keySize]); ippsRSA_InitPublicKey(bitSizeN, bitSizeE, pPubKey, keySize); if (pPubKey) { do { /* Set public key */ status = ippsRSA_SetPublicKey(N, E, pPubKey); if (!checkStatus("ippsRSA_SetPublicKey", ippStsNoErr, status)) break; /* Calculate temporary buffer size */ int pubBufSize = 0; status = ippsRSA_GetBufferSizePublicKey(&pubBufSize, pPubKey); if (!checkStatus("ippsRSA_GetBufferSizePublicKey", ippStsNoErr, status)) break; Ipp8u* pScratchBuffer = new Ipp8u[pubBufSize]; /* Verify message with use of SHA-1 hash function. The verification result will be placed * into isValid variable. */ int isValid = 0; status = ippsRSAVerify_PSS_rmf(sourceMessage, sizeof(sourceMessage)-1, signatureRef, &isValid, pPubKey, ippsHashMethod_SHA1(), pScratchBuffer); if (pScratchBuffer) delete [] pScratchBuffer; if (!checkStatus("ippsRSAVerify_PSS_rmf", ippStsNoErr, status)) break; /* If isValid is zero, then verification fails */ status = isValid ? ippStsNoErr : ippStsErr; } while (0); } if (pPubKey) delete [] (Ipp8u*)pPubKey; PRINT_EXAMPLE_STATUS("ippsRSAVerify_PSS_rmf", "RSA-PSS 1024 (SHA1) Verification", ippStsNoErr == status); return status; } cryptography-primitives-1.0.0/examples/rsa/rsa-3k-pss-sha384-type1-signature.cpp000066400000000000000000000203521470420105600275160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * * \brief RSASSA-PSS signature generation scheme usage example. * * This example demonstrates message signature generation according to * RSASSA-PSS scheme with 3072-bit RSA modulus and SHA-384 hash function. * It uses Reduced Memory Footprint (_rmf) version of the function. * * The RSASSA-PSS scheme is implemented according to the PKCS#1 v2.1: RSA Cryptography Standard (June 2002), * available at: * * https://tools.ietf.org/html/rfc3447. * */ #include #include "ippcp.h" #include "examples_common.h" #include "bignum.h" /*! 3072-bit RSA Modulus N = P*Q */ BigNumber N("0xA7A1882A7FB896786034D07FB1B9F6327C27BDD7CE6FE39C285AE3B6C34259ADC0DC4F7B9C7DEC3CA4A20D3407339EEDD\ 7A12A421DA18F5954673CAC2FF059156ECC73C6861EC761E6A0F2A5A033A6768C6A42D8B459E1B4932349E84EFD92DF59B45935F3D0E3081\ 7C66201AA99D07AE36C5D74F408D69CC08F044151FF4960E531360CB19077833ADF7BCE77ECFAA133C0CCC63C93B856814569E0B9884EE55\ 4061B9A20AB46C38263C094DAE791AA61A17F8D16F0E85B7E5CE3B067ECE89E20BC4E8F1AE814B276D234E04F4E766F501DA74EA7E3817C2\ 4EA35D016676CECE652B823B051625573CA92757FC720D254ECF1DCBBFD21D98307561ECAAB545480C7C52AD7E9FA6B597F5FE550559C2FE\ 923205AC1761A99737CA02D7B19822E008A8969349C87FB874C81620E38F613C8521F0381FE5BA55B74827DAD3E1CF2AA29C6933629F2B28\ 6AD11BE88FA6436E7E3F64A75E3595290DC0D1CD5EEE7AAAC54959CC53BD5A934A365E72DD81A2BD4FB9A67821BFFEDF2EF2BD94913DE8B"); /*! Public exponent */ BigNumber E("0x1415a7"); /*! Private exponent */ BigNumber D("0x073A5FC4CD642F6113DFFC4F84035CEE3A2B8ACC549703751A1D6A5EAA13487229A58EF7D7A522BB9F4F25510F1AA0F74\ C6A8FC8A5C5BE8B91A674EDE50E92F7E34A90A3C9DA999FFFB1D695E4588F451256C163484C151350CB9C7825A7D910845EE5CF826FECF9A\ 7C0FBBBBA22BB4A531C131D2E7761BA898F002EBEF8AB87218511F81D3266E1EC07A7CA8622514C6DFDC86C67679A2C8F5F031DE9A0C22B5\ A88060B46EE0C64D3B9AF3C0A379BCD9C6A1B51CF6480456D3FD6DEF94CD2A6C171DD3F010E3C9D662BC857208248C94EBCB9FD997B9FF4A\ 7E5FD95558569906525E741D78344F6F6CFDBD59D4FAA52EE3FA964FB7CCCB2D6BE1935D211FE1498217716273939A946081FD8509913FD4\ 7747C5C2F03EFD4D6FC9C6FCFD8402E9F40A0A5B3DE3CA2B3C0FAC9456938FAA6CF2C20E3912E5981C9876D8CA1FF29B87A15EEAE0CCCE3F\ 8A8F1E405091C083B98BCC5FE0D0DEAAE33C67C0394437F0ECCB385B7EFB17AEEBBA8AFAECCA30A2F63EAC8F0AC8F1EACAD85BBCAF3960B"); /*! Reference value of signature */ static const Ipp8u signatureRef[] = "\x96\x87\x11\x5b\xe4\x78\xe4\xb6\x42\xcd\x36\x93\x92\xb9\xdd\x0f\x35\x76\xe7\x04\xaf\x72\x18\xb1\xf9\x4d\x7f\x8f\ \xe7\xf0\x70\x73\xe3\xe8\xe1\x18\x6f\xa7\x68\x97\x7d\x6b\x51\x4e\x51\x34\x59\xf2\x37\x3d\xf6\xec\x52\xe3\xde\x9b\ \xd8\x3f\xcc\x5c\xc3\xe6\xb9\x7f\x8b\x3f\xb5\x34\x16\x3c\x64\xf5\x26\x76\x20\x70\x0e\x9d\x8c\x52\xb3\xdf\x61\xa7\ \xc3\x74\x8e\xf1\x59\xd6\xb3\x90\x89\x5a\xfa\x3a\xf5\x91\x09\xa5\x47\x8d\x01\x6d\x96\xc4\x9f\x68\xdf\xc7\x35\xba\ \x2a\xaf\xd5\x01\x2c\x13\x51\x5e\xd6\x64\x4f\x0d\x41\x09\xc4\x55\x56\xe1\x4a\x38\x21\xe1\xaa\x24\xbe\xb8\xa8\x1a\ \x48\xda\x27\xf1\x31\xde\x84\xf7\xba\x51\x58\x1d\x81\xb8\xff\x31\xba\x92\xb8\xa1\xfd\xe8\x67\xf0\x7e\x32\xe6\xc2\ \x70\x92\x53\x44\x81\x74\xdd\x31\x32\x4d\xbc\x32\xb0\x5f\x07\x58\x7f\x76\xa9\x99\x7d\xec\xb8\x0f\x38\xd8\xc1\x3d\ \x0f\x6e\xb3\xc1\x0e\x3d\x96\xa2\x29\x3f\x74\x64\xf1\xe0\x46\x02\xef\x6e\x84\xc2\xd0\x24\x5d\x7d\xb2\x56\xa6\x7d\ \x13\x2a\x47\xca\xe9\xab\xe0\x6b\x61\xa8\x96\x8f\x50\xa1\x74\x99\x95\xdc\x15\xef\x0d\xcb\x1d\x5f\x59\x59\xe4\xd4\ \x54\xc8\x54\x7b\xbb\x4d\x19\x56\x98\xf4\x84\x61\x7b\xfd\x12\x2a\xca\xae\x2d\x0e\x8c\x76\xd2\x8b\x24\x00\x5a\xb0\ \x3c\xaa\x78\x1e\xa9\x7b\x1c\x4d\x93\x96\xa1\x6f\x79\x98\xee\xe7\xdd\xd9\xde\x4c\xab\xe5\x70\x32\xd9\x43\x8a\x5d\ \x99\xc6\xb3\x4a\x95\x61\x22\x35\x02\x63\xc7\xe9\x98\xbc\x61\xde\xc9\x13\x81\x01\x2e\x68\x6d\x07\x9e\x39\xe9\x6b\ \x1e\xa4\xbf\xdb\x7c\xdf\x63\x0d\xdb\x42\x2c\x6b\x58\x0e\x55\x06\xc9\xcc\x3d\x6c\x10\x0f\x20\x41\xd1\x7c\xea\xaa\ \xa5\x45\x89\x24\x9f\x04\xa1\x37\x0f\xfa\x3b\xf3\xff\x1a\xde\xb8\x90\x68\x86\x98"; /*! Message to be signed */ static const Ipp8u sourceMessage[] = "\x92\x21\xf0\xfe\x91\x15\x84\x35\x54\xd5\x68\x5d\x9f\xe6\x9d\xc4\x9e\x95\xce\xb5\x79\x39\x86\xe4\x28\xb8\xa1\x0b\ \x89\x4c\x01\xd6\xaf\x87\x82\xfd\x7d\x95\x2f\xaf\x74\xc2\xb6\x37\xca\x3b\x19\xda\xbc\x19\xa7\xfe\x25\x9b\x2b\x92\ \x4e\xb3\x63\xa9\x08\xc5\xb3\x68\xf8\xab\x1b\x23\x33\xfc\x67\xc3\x0b\x8e\xa5\x6b\x28\x39\xdc\x5b\xda\xde\xfb\x14\ \xad\xa8\x10\xbc\x3e\x92\xba\xc5\x4e\x2a\xe1\xca\x15\x94\xa4\xb9\xd8\xd1\x93\x37\xbe\x42\x1f\x40\xe0\x67\x4e\x0e\ \x9f\xed\xb4\x3d\x3a\xe8\x9e\x2c\xa0\x5d\x90\xa6\x82\x03\xf2\xc2"; /*! Salt */ static const Ipp8u salt[] = "\x61\xa7\x62\xf8\x96\x8d\x5f\x36\x7e\x2d\xbc\xac\xb4\x02\x16\x53\xdc\x75\x43\x7d\x90\x00\xe3\x16\x9d\x94\x37\x29\ \x70\x38\x37\xa5\xcb\xf4\xde\x62\xbd\xed\xc9\x5f\xd0\xd1\x00\x4e\x84\x75\x14\x52"; /*! Main function */ int main(void) { /* RSA Modulus N = P*Q in bits */ const int RSA_MODULUS = 3072; /* Internal function status */ IppStatus status = ippStsNoErr; /* Size in bits of RSA modulus */ const int bitSizeN = N.BitSize(); /* Size in bits of RSA private exponent */ const int bitSizeD = D.BitSize(); /* Allocate memory for signature. * Size shall be equal to the RSA modulus size. */ const int signatureLen = bitSizeInBytes(RSA_MODULUS); Ipp8u* pSignature = new Ipp8u[signatureLen]; /* Allocate memory private key. * There are two types of private keys that are supported: Type1 and Type2. * You can choose any of them, depending on your private key representation. * This example uses Type1 key. * For more information, see https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-reference/current/crypto-ref-getsize-public-private1-private2.html */ int keySize = 0; ippsRSA_GetSizePrivateKeyType1(bitSizeN, bitSizeD, &keySize); IppsRSAPrivateKeyState* pPrvKeyType1 = (IppsRSAPrivateKeyState*)(new Ipp8u[keySize]); ippsRSA_InitPrivateKeyType1(bitSizeN, bitSizeD, pPrvKeyType1, keySize); if (pPrvKeyType1) { do { /* Set private key */ status = ippsRSA_SetPrivateKeyType1(N, D, pPrvKeyType1); if (!checkStatus("ippsRSA_SetPrivateKeyType1", ippStsNoErr, status)) break; /* Calculate temporary buffer size */ int bufSize = 0; status = ippsRSA_GetBufferSizePrivateKey(&bufSize, pPrvKeyType1); if (!checkStatus("ippsRSA_GetBufferSizePrivateKey", ippStsNoErr, status)) break; Ipp8u* pScratchBuffer = new Ipp8u[bufSize]; /* Sign message with use of SHA384 hash function */ status = ippsRSASign_PSS_rmf(sourceMessage, sizeof(sourceMessage)-1, salt, sizeof(salt)-1, pSignature, pPrvKeyType1, NULL /* public key */, ippsHashMethod_SHA384(), pScratchBuffer); if (pScratchBuffer) delete [] pScratchBuffer; if (!checkStatus("ippsRSASign_PSS_rmf", ippStsNoErr, status)) break; /* Compare signature with expected value */ if (0 != memcmp(signatureRef, pSignature, signatureLen)) { printf("ERROR: Signature and reference value do not match\n"); status = ippStsErr; } } while (0); } if (pPrvKeyType1) delete [] (Ipp8u*)pPrvKeyType1; if (pSignature) delete [] pSignature; PRINT_EXAMPLE_STATUS("ippsRSASign_PSS_rmf", "RSA-PSS 3072 (SHA-384) Type1 Signature", ippStsNoErr == status); return status; } cryptography-primitives-1.0.0/examples/sms4/000077500000000000000000000000001470420105600211375ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/sms4/sms4-128-cbc-decryption.cpp000066400000000000000000000074341470420105600257540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 * * \brief SMS4 Cipher Block Chaining mode of operation (CBC) example * * This example demonstrates usage of SMS4 block cipher * run with CBC mode of operation. Decryption scheme. * * The CBC mode of operation is implemented according to the * "NIST Special Publication 800-38A: Recommendation for Block Cipher Modes of * Operation" document: * * https://csrc.nist.gov/publications/detail/sp/800-38a/final * */ #include #include "ippcp.h" #include "examples_common.h" /*! SMS4 block size in bytes */ static const int SMS4_BLOCK_SIZE = 16; /*! Key size in bytes */ static const int KEY_SIZE = 16; /*! Message size in bytes */ static const int SRC_LEN = 16; /*! Plain text */ static Ipp8u plainText[SRC_LEN] = { 0xAA,0xAA,0xAA,0xAA,0xBB,0xBB,0xBB,0xBB, 0xCC,0xCC,0xCC,0xCC,0xDD,0xDD,0xDD,0xDD }; /*! Cipher text */ static Ipp8u cipherText[SRC_LEN] = { 0x78,0xEB,0xB1,0x1C,0xC4,0x0B,0x0A,0x48, 0x31,0x2A,0xAE,0xB2,0x04,0x02,0x44,0xCB }; /*! 128-bit secret key */ static Ipp8u key[KEY_SIZE] = { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }; /*! Initialization vector for CBC mode. * Size of initialization vector for SMS4-CBC shall be equal to the size of SMS4 block (16 bytes). */ static Ipp8u iv[SMS4_BLOCK_SIZE] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; /*! Main function */ int main(void) { /* Size of SMS4 context structure. It will be set up in ippsSMS4GetSize(). */ int ctxSize = 0; Ipp8u pOut[SRC_LEN] = {}; /* Internal function status */ IppStatus status = ippStsNoErr; /* Pointer to SMS4 context structure */ IppsSMS4Spec* pSMS4 = 0; do { /* 1. Get size needed for SMS4 context structure */ status = ippsSMS4GetSize(&ctxSize); if (!checkStatus("ippsSMS4GetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for SMS4 context structure */ pSMS4 = (IppsSMS4Spec*)(new Ipp8u[ctxSize]); if (NULL == pSMS4) { printf("ERROR: Cannot allocate memory (%d bytes) for SMS4 context\n", ctxSize); return -1; } /* 3. Initialize SMS4 context */ status = ippsSMS4Init(key, sizeof(key), pSMS4, ctxSize); if (!checkStatus("ippsSMS4Init", ippStsNoErr, status)) break; /* 4. Decryption */ status = ippsSMS4DecryptCBC(cipherText, pOut, sizeof(cipherText), pSMS4, iv); if (!checkStatus("ippsSMS4DecryptCBC", ippStsNoErr, status)) break; /* Compare decrypted message and reference text */ if (0 != memcmp(pOut, plainText, sizeof(plainText))) { printf("ERROR: Decrypted and reference messages do not match\n"); break; } } while (0); /* 5. Remove secret and release resources */ ippsSMS4Init(0, KEY_SIZE, pSMS4, ctxSize); if (pSMS4) delete [] (Ipp8u*)pSMS4; PRINT_EXAMPLE_STATUS("ippsSMS4DecryptCBC", "SMS4-CBC Decryption", !status) return status; } cryptography-primitives-1.0.0/examples/sms4/sms4-128-cbc-encryption.cpp000066400000000000000000000074341470420105600257660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 * * \brief SMS4 Cipher Block Chaining mode of operation (CBC) example * * This example demonstrates usage of SMS4 block cipher * run with CBC mode of operation. Encryption scheme. * * The CBC mode of operation is implemented according to the * "NIST Special Publication 800-38A: Recommendation for Block Cipher Modes of * Operation" document: * * https://csrc.nist.gov/publications/detail/sp/800-38a/final * */ #include #include "ippcp.h" #include "examples_common.h" /*! SMS4 block size in bytes */ static const int SMS4_BLOCK_SIZE = 16; /*! Key size in bytes */ static const int KEY_SIZE = 16; /*! Message size in bytes */ static const int SRC_LEN = 16; /*! Plain text */ static Ipp8u plainText[SRC_LEN] = { 0xAA,0xAA,0xAA,0xAA,0xBB,0xBB,0xBB,0xBB, 0xCC,0xCC,0xCC,0xCC,0xDD,0xDD,0xDD,0xDD }; /*! Cipher text */ static Ipp8u cipherText[SRC_LEN] = { 0x78,0xEB,0xB1,0x1C,0xC4,0x0B,0x0A,0x48, 0x31,0x2A,0xAE,0xB2,0x04,0x02,0x44,0xCB }; /*! 128-bit secret key */ static Ipp8u key[KEY_SIZE] = { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10 }; /*! Initialization vector for CBC mode. * Size of initialization vector for SMS4-CBC shall be equal to the size of SMS4 block (16 bytes). */ static Ipp8u iv[SMS4_BLOCK_SIZE] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; /*! Main function */ int main(void) { /* Size of SMS4 context structure. It will be set up in ippsSMS4GetSize(). */ int ctxSize = 0; Ipp8u pOut[SRC_LEN] = {}; /* Internal function status */ IppStatus status = ippStsNoErr; /* Pointer to SMS4 context structure */ IppsSMS4Spec* pSMS4 = 0; do { /* 1. Get size needed for SMS4 context structure */ status = ippsSMS4GetSize(&ctxSize); if (!checkStatus("ippsSMS4GetSize", ippStsNoErr, status)) return status; /* 2. Allocate memory for SMS4 context structure */ pSMS4 = (IppsSMS4Spec*)(new Ipp8u[ctxSize]); if (NULL == pSMS4) { printf("ERROR: Cannot allocate memory (%d bytes) for SMS4 context\n", ctxSize); return -1; } /* 3. Initialize SMS4 context */ status = ippsSMS4Init(key, sizeof(key), pSMS4, ctxSize); if (!checkStatus("ippsSMS4Init", ippStsNoErr, status)) break; /* 4. Encryption */ status = ippsSMS4EncryptCBC(plainText, pOut, sizeof(plainText), pSMS4, iv); if (!checkStatus("ippsSMS4EncryptCBC", ippStsNoErr, status)) break; /* Compare encrypted message and reference text */ if (0 != memcmp(pOut, cipherText, sizeof(cipherText))) { printf("ERROR: Encrypted and reference messages do not match\n"); break; } } while (0); /* 5. Remove secret and release resources */ ippsSMS4Init(0, KEY_SIZE, pSMS4, ctxSize); if (pSMS4) delete [] (Ipp8u*)pSMS4; PRINT_EXAMPLE_STATUS("ippsSMS4EncryptCBC", "SMS4-CBC Encryption", !status) return status; } cryptography-primitives-1.0.0/examples/utils/000077500000000000000000000000001470420105600214115ustar00rootroot00000000000000cryptography-primitives-1.0.0/examples/utils/bignum.cpp000066400000000000000000000220421470420105600233760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "bignum.h" #include #include #include "utils.h" ////////////////////////////////////////////////////////////////////// // // BigNumber // ////////////////////////////////////////////////////////////////////// BigNumber::~BigNumber() { delete [] (Ipp8u*)m_pBN; } bool BigNumber::create(const Ipp32u* pData, int length, IppsBigNumSGN sgn) { int size; ippsBigNumGetSize(length, &size); m_pBN = (IppsBigNumState*)( new Ipp8u[size] ); if(!m_pBN) return false; ippsBigNumInit(length, m_pBN); if (pData) ippsSet_BN(sgn, length, pData, m_pBN); return true; } // // constructors // BigNumber::BigNumber(Ipp32u value) { create(&value, 1, IppsBigNumPOS); } BigNumber::BigNumber(Ipp32s value) { Ipp32s avalue = abs(value); create((Ipp32u*)&avalue, 1, (value<0)? IppsBigNumNEG : IppsBigNumPOS); } BigNumber::BigNumber(const IppsBigNumState* pBN) { IppsBigNumSGN bnSgn; int bnBitLen; Ipp32u* bnData; ippsRef_BN(&bnSgn, &bnBitLen, &bnData, pBN); create(bnData, BITSIZE_WORD(bnBitLen), bnSgn); } BigNumber::BigNumber(const Ipp32u* pData, int length, IppsBigNumSGN sgn) { create(pData, length, sgn); } static char HexDigitList[] = "0123456789ABCDEF"; BigNumber::BigNumber(const char* s) { bool neg = '-' == s[0]; if(neg) s++; bool hex = ('0'==s[0]) && (('x'==s[1]) || ('X'==s[1])); int dataLen; Ipp32u base; if(hex) { s += 2; base = 0x10; dataLen = (int)(strlen_safe(s) + 7)/8; } else { base = 10; dataLen = (int)(strlen_safe(s) + 9)/10; } create(0, dataLen); *(this) = Zero(); while(*s) { char tmp[2] = {s[0],0}; Ipp32u digit = (Ipp32u)strcspn(HexDigitList, tmp); *this = (*this) * base + BigNumber( digit ); s++; } if(neg) (*this) = Zero()- (*this); } BigNumber::BigNumber(const BigNumber& bn) { IppsBigNumSGN bnSgn; int bnBitLen; Ipp32u* bnData; ippsRef_BN(&bnSgn, &bnBitLen, &bnData, bn); create(bnData, BITSIZE_WORD(bnBitLen), bnSgn); } // // set value // void BigNumber::Set(const Ipp32u* pData, int length, IppsBigNumSGN sgn) { ippsSet_BN(sgn, length, pData, BN(*this)); } // // constants // const BigNumber& BigNumber::Zero() { static const BigNumber zero(0); return zero; } const BigNumber& BigNumber::One() { static const BigNumber one(1); return one; } const BigNumber& BigNumber::Two() { static const BigNumber two(2); return two; } // // arithmetic operators // BigNumber& BigNumber::operator =(const BigNumber& bn) { if(this != &bn) { // prevent self copy IppsBigNumSGN bnSgn; int bnBitLen; Ipp32u* bnData; ippsRef_BN(&bnSgn, &bnBitLen, &bnData, bn); delete [] (Ipp8u*)m_pBN; create(bnData, BITSIZE_WORD(bnBitLen), bnSgn); } return *this; } BigNumber& BigNumber::operator += (const BigNumber& bn) { int aBitLen; ippsRef_BN(NULL, &aBitLen, NULL, *this); int bBitLen; ippsRef_BN(NULL, &bBitLen, NULL, bn); int rBitLen = IPP_MAX(aBitLen, bBitLen) + 1; BigNumber result(0, BITSIZE_WORD(rBitLen)); ippsAdd_BN(*this, bn, result); *this = result; return *this; } BigNumber& BigNumber::operator -= (const BigNumber& bn) { int aBitLen; ippsRef_BN(NULL, &aBitLen, NULL, *this); int bBitLen; ippsRef_BN(NULL, &bBitLen, NULL, bn); int rBitLen = IPP_MAX(aBitLen, bBitLen); BigNumber result(0, BITSIZE_WORD(rBitLen)); ippsSub_BN(*this, bn, result); *this = result; return *this; } BigNumber& BigNumber::operator *= (const BigNumber& bn) { int aBitLen; ippsRef_BN(NULL, &aBitLen, NULL, *this); int bBitLen; ippsRef_BN(NULL, &bBitLen, NULL, bn); int rBitLen = aBitLen + bBitLen; BigNumber result(0, BITSIZE_WORD(rBitLen)); ippsMul_BN(*this, bn, result); *this = result; return *this; } BigNumber& BigNumber::operator *= (Ipp32u n) { int aBitLen; ippsRef_BN(NULL, &aBitLen, NULL, *this); BigNumber result(0, BITSIZE_WORD(aBitLen+32)); BigNumber bn(n); ippsMul_BN(*this, bn, result); *this = result; return *this; } BigNumber& BigNumber::operator %= (const BigNumber& bn) { BigNumber remainder(bn); ippsMod_BN(BN(*this), BN(bn), BN(remainder)); *this = remainder; return *this; } BigNumber& BigNumber::operator /= (const BigNumber& bn) { BigNumber quotient(*this); BigNumber remainder(bn); ippsDiv_BN(BN(*this), BN(bn), BN(quotient), BN(remainder)); *this = quotient; return *this; } BigNumber operator + (const BigNumber& a, const BigNumber& b ) { BigNumber r(a); return r += b; } BigNumber operator - (const BigNumber& a, const BigNumber& b ) { BigNumber r(a); return r -= b; } BigNumber operator * (const BigNumber& a, const BigNumber& b ) { BigNumber r(a); return r *= b; } BigNumber operator * (const BigNumber& a, Ipp32u n) { BigNumber r(a); return r *= n; } BigNumber operator / (const BigNumber& a, const BigNumber& b ) { BigNumber q(a); return q /= b; } BigNumber operator % (const BigNumber& a, const BigNumber& b ) { BigNumber r(b); ippsMod_BN(BN(a), BN(b), BN(r)); return r; } // // modulo arithmetic // BigNumber BigNumber::Modulo(const BigNumber& a) const { return a % *this; } BigNumber BigNumber::InverseAdd(const BigNumber& a) const { BigNumber t = Modulo(a); if(t==BigNumber::Zero()) return t; else return *this - t; } BigNumber BigNumber::InverseMul(const BigNumber& a) const { BigNumber r(*this); ippsModInv_BN(BN(a), BN(*this), BN(r)); return r; } BigNumber BigNumber::ModAdd(const BigNumber& a, const BigNumber& b) const { BigNumber r = this->Modulo(a+b); return r; } BigNumber BigNumber::ModSub(const BigNumber& a, const BigNumber& b) const { BigNumber r = this->Modulo(a + this->InverseAdd(b)); return r; } BigNumber BigNumber::ModMul(const BigNumber& a, const BigNumber& b) const { BigNumber r = this->Modulo(a*b); return r; } // // comparison // int BigNumber::compare(const BigNumber &bn) const { Ipp32u result; BigNumber tmp = *this - bn; ippsCmpZero_BN(BN(tmp), &result); return (result==IS_ZERO)? 0 : (result==GREATER_THAN_ZERO)? 1 : -1; } bool operator < (const BigNumber &a, const BigNumber &b) { return a.compare(b) < 0; } bool operator > (const BigNumber &a, const BigNumber &b) { return a.compare(b) > 0; } bool operator == (const BigNumber &a, const BigNumber &b) { return 0 == a.compare(b);} bool operator != (const BigNumber &a, const BigNumber &b) { return 0 != a.compare(b);} // easy tests // bool BigNumber::IsOdd() const { Ipp32u* bnData; ippsRef_BN(NULL, NULL, &bnData, *this); return bnData[0]&1; } // // size of BigNumber // int BigNumber::LSB() const { if( *this == BigNumber::Zero() ) return 0; vector v; num2vec(v); int lsb = 0; vector::iterator i; for(i=v.begin(); i!=v.end(); i++) { Ipp32u x = *i; if(0==x) lsb += 32; else { while(0==(x&1)) { lsb++; x >>= 1; } break; } } return lsb; } int BigNumber::MSB() const { if( *this == BigNumber::Zero() ) return 0; vector v; num2vec(v); int msb = (int)v.size()*32 -1; vector::reverse_iterator i; for(i=v.rbegin(); i!=v.rend(); i++) { Ipp32u x = *i; if(0==x) msb -=32; else { while(!(x&0x80000000)) { msb--; x <<= 1; } break; } } return msb; } int Bit(const vector& v, int n) { return 0 != ( v[n>>5] & (1<<(n&0x1F)) ); } // // conversions and output // void BigNumber::num2vec( vector& v ) const { int bnBitLen; Ipp32u* bnData; ippsRef_BN(NULL, &bnBitLen, &bnData, *this); int len = BITSIZE_WORD(bnBitLen);; for(int n=0; n0; n--) { Ipp32u x = bnData[n-1]; for(int nd=8; nd>0; nd--) { char c = HexDigitList[(x>>(nd-1)*4)&0xF]; s.append(1, c); } } } ostream& operator << ( ostream &os, const BigNumber& a) { string s; a.num2hex(s); os << s.c_str(); return os; } cryptography-primitives-1.0.0/examples/utils/bignum.h000066400000000000000000000076741470420105600230610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ #if !defined _BIGNUMBER_H_ #define _BIGNUMBER_H_ #include "ippcp.h" #include #include #include using namespace std; class BigNumber { public: BigNumber(Ipp32u value=0); BigNumber(Ipp32s value); BigNumber(const IppsBigNumState* pBN); BigNumber(const Ipp32u* pData, int length=1, IppsBigNumSGN sgn=IppsBigNumPOS); BigNumber(const BigNumber& bn); BigNumber(const char *s); virtual ~BigNumber(); // set value void Set(const Ipp32u* pData, int length=1, IppsBigNumSGN sgn=IppsBigNumPOS); // conversion to IppsBigNumState friend IppsBigNumState* BN(const BigNumber& bn) {return bn.m_pBN;} operator IppsBigNumState* () const { return m_pBN; } // some useful constants static const BigNumber& Zero(); static const BigNumber& One(); static const BigNumber& Two(); // arithmetic operators probably need BigNumber& operator = (const BigNumber& bn); BigNumber& operator += (const BigNumber& bn); BigNumber& operator -= (const BigNumber& bn); BigNumber& operator *= (Ipp32u n); BigNumber& operator *= (const BigNumber& bn); BigNumber& operator /= (const BigNumber& bn); BigNumber& operator %= (const BigNumber& bn); friend BigNumber operator + (const BigNumber& a, const BigNumber& b); friend BigNumber operator - (const BigNumber& a, const BigNumber& b); friend BigNumber operator * (const BigNumber& a, const BigNumber& b); friend BigNumber operator * (const BigNumber& a, Ipp32u); friend BigNumber operator % (const BigNumber& a, const BigNumber& b); friend BigNumber operator / (const BigNumber& a, const BigNumber& b); // modulo arithmetic BigNumber Modulo(const BigNumber& a) const; BigNumber ModAdd(const BigNumber& a, const BigNumber& b) const; BigNumber ModSub(const BigNumber& a, const BigNumber& b) const; BigNumber ModMul(const BigNumber& a, const BigNumber& b) const; BigNumber InverseAdd(const BigNumber& a) const; BigNumber InverseMul(const BigNumber& a) const; // comparisons friend bool operator < (const BigNumber& a, const BigNumber& b); friend bool operator > (const BigNumber& a, const BigNumber& b); friend bool operator == (const BigNumber& a, const BigNumber& b); friend bool operator != (const BigNumber& a, const BigNumber& b); friend bool operator <= (const BigNumber& a, const BigNumber& b) {return !(a>b);} friend bool operator >= (const BigNumber& a, const BigNumber& b) {return !(a>5;} friend int Bit(const vector& v, int n); // conversion and output void num2hex( string& s ) const; // convert to hex string void num2vec( vector& v ) const; // convert to 32-bit word vector friend ostream& operator << (ostream& os, const BigNumber& a); protected: bool create(const Ipp32u* pData, int length, IppsBigNumSGN sgn=IppsBigNumPOS); int compare(const BigNumber& ) const; IppsBigNumState* m_pBN; }; // convert bit size into 32-bit words #define BITSIZE_WORD(n) ((((n)+31)>>5)) #endif // _BIGNUMBER_H_ cryptography-primitives-1.0.0/examples/utils/examples_common.h000066400000000000000000000056311470420105600247550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* Intel® Cryptography Primitives Library */ /*! * * \file * \brief Common header for Intel Cryptography Primitives Library examples * */ #ifndef EXAMPLES_COMMON_H_ #define EXAMPLES_COMMON_H_ #include /*! Macro that prints status message depending on condition */ #define PRINT_EXAMPLE_STATUS(function_name, description, success_condition) \ printf("+--------------------------------------------------------------|\n"); \ printf(" Function: %s\n", function_name); \ printf(" Description: %s\n", description); \ if (success_condition) { \ printf(" Status: PASSED!\n"); \ } else { \ printf(" Status: FAILED!\n"); \ } \ printf("+--------------------------------------------------------------|\n"); /*! * Helper function to compare expected and actual function return statuses and display * an error message if those are different. * * \param[in] Function name to display * \param[in] Expected status * \param[in] Actual status * * \return zero if statuses are not equal, otherwise - non-zero value */ inline int checkStatus(const char* funcName, IppStatus expectedStatus, IppStatus status) { if (expectedStatus != status) { printf("%s: unexpected return status\n", funcName); printf("Expected: %s\n", ippcpGetStatusString(expectedStatus)); printf("Received: %s\n", ippcpGetStatusString(status)); return 0; } return 1; } /*! * Helper function to convert bit size into byte size. * * \param[in] Size in bits * * \return size in bytes */ inline int bitSizeInBytes(int nBits) { return (nBits + 7) >> 3; } /*! * Helper function to convert bit size into word size. * * \param[in] Size in bits * * \return size in words */ inline int bitSizeInWords(int nBits) { return (nBits + 31) >> 5; } #endif /* #ifndef EXAMPLES_COMMON_H_ */ cryptography-primitives-1.0.0/examples/utils/requests.cpp000066400000000000000000000025511470420105600237730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * \brief The source file contains the implementation of Request class which simulates a queue in the example of using the multi buffer RSA. * */ #include "bignum.h" #include "requests.h" #include "examples_common.h" /* Allocated memory for cipher and decipher texts is not less than RSA modulus size and source plain text */ Request::Request(const BigNumber& pPlainText, const BigNumber& N, const BigNumber& E, const BigNumber& D) : m_plainText(pPlainText) , m_N(N) , m_E(E) , m_D(D) , m_cipherText(N) , m_decipherText(pPlainText) , m_isCompatible(true) {} Request::~Request(){} cryptography-primitives-1.0.0/examples/utils/requests.h000066400000000000000000000045101470420105600234350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 * \brief The header contains the declaration of Request class which simulates a queue in the example of using the multi buffer RSA. * */ #if !defined _REQUESTS_H_ #define _REQUESTS_H_ #include "bignum.h" class Request { BigNumber m_plainText; BigNumber m_cipherText; BigNumber m_decipherText; BigNumber m_N; BigNumber m_E; BigNumber m_D; bool m_isCompatible; public: Request(const BigNumber& pPlainText, const BigNumber& N, const BigNumber& E, const BigNumber& D); ~Request(); IppsBigNumState* GetPlainText() const { return m_plainText; } IppsBigNumState* GetCipherText() const { return m_cipherText; } IppsBigNumState* GetDecipherText() const { return m_decipherText; } int GetBitSizeN() const { return m_N.BitSize(); } const BigNumber& GetValueN() const { return m_N; } int GetBitSizeE() const { return m_E.BitSize(); } const BigNumber& GetValueE() const { return m_E; } int GetBitSizeD() const { return m_D.BitSize(); } const BigNumber& GetValueD() const { return m_D; } void SetCompatibilityStatus(bool status) { m_isCompatible = status; } bool IsCompatible() const { return m_isCompatible; } }; #endif /* #ifndef _REQUESTS_H_ */ cryptography-primitives-1.0.0/examples/utils/utils.cpp000066400000000000000000000022731470420105600232610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "utils.h" size_t strlen_safe(const char* dest, size_t dmax) { size_t count; /* check null pointer */ if (NULL == dest) { return 0UL; } /* check max equal zero */ if (0UL == dmax) { return 0UL; } /* check dmax > 4Kb */ if (dmax > RSIZE_MAX_STR) { return 0UL; } count = 0UL; while (*dest && dmax) { ++count; --dmax; ++dest; } return count; } cryptography-primitives-1.0.0/examples/utils/utils.h000066400000000000000000000024111470420105600227200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 _UTILS_H_ #define _UTILS_H_ #include #define RSIZE_MAX_STR (4UL << 10) /* 4Kb */ /** * \brief * The strnlen_s function computes the length of the string pointed to by dest. * \param[in] dest pointer to string * \param[in] dmax restricted maximum length. (default 4Kb) * \return size_t * The function returns the string length, excluding the terminating * null character. If dest is NULL, then strnlen_s returns 0. */ size_t strlen_safe(const char* dest, size_t dmax = RSIZE_MAX_STR); #endif // _UTILS_H_ cryptography-primitives-1.0.0/include/000077500000000000000000000000001470420105600200565ustar00rootroot00000000000000cryptography-primitives-1.0.0/include/ippcp.h000066400000000000000000002202411470420105600213430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Intel® Cryptography Primitives Library // */ #if !defined( IPPCP_H__ ) || defined( _OWN_BLDPCS ) #define IPPCP_H__ #ifndef IPPCPDEFS_H__ #include "ippcpdefs.h" #endif #ifdef __cplusplus extern "C" { #endif /* Block of code supporting Visual Studio integration */ #if !defined( IPP_NO_DEFAULT_LIB ) #if defined( _IPP_SEQUENTIAL_DYNAMIC ) #pragma comment( lib, __FILE__ "/../../../" IPPCP_INTEL_LIBS_DIR "ippcp" ) #elif defined( _IPP_SEQUENTIAL_STATIC ) #pragma comment( lib, __FILE__ "/../../../" IPPCP_INTEL_LIBS_DIR "ippcpmt" ) #endif #endif #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) #pragma warning(push) #pragma warning(disable : 4100) // for MSVC, unreferenced parameter #endif /* ///////////////////////////////////////////////////////////////////////////// // Name: ippcpGetLibVersion / CryptoLibraryVersion // Purpose: getting of the library version // Returns: the structure of information about version of Intel Cryptography Primitives Library // Parameters: // // Notes: not necessary to release the returned structure */ #define LIB_VERSION_DEPRECATED "ippcpGetLibVersion API is deprecated and will be removed in one of future Intel® Cryptography Primitives Library releases. \ Please use cryptoGetLibVersion instead." IPP_DEPRECATED(LIB_VERSION_DEPRECATED) \ IPPAPI( const IppLibraryVersion*, ippcpGetLibVersion, (void) ) IPPAPI( const CryptoLibraryVersion*, cryptoGetLibVersion, (void) ) /* // ========================================================= // Symmetric Ciphers // ========================================================= */ /* TDES */ #define TDES_DEPRECATED "This algorithm is considered weak due to known attacks on it. \ The functionality remains in the library, but the implementation will no be longer \ optimized and no security patches will be applied. A more secure alternative is available: AES" IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsDESGetSize,(int *size)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsDESInit,(const Ipp8u* pKey, IppsDESSpec* pCtx)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsDESPack,(const IppsDESSpec* pCtx, Ipp8u* pBuffer)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsDESUnpack,(const Ipp8u* pBuffer, IppsDESSpec* pCtx)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESEncryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, IppsCPPadding padding)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESDecryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, IppsCPPadding padding)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESEncryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsCPPadding padding)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESDecryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsCPPadding padding)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESEncryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsCPPadding padding)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESDecryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsCPPadding padding)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESEncryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pIV)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESDecryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pIV)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESEncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pCtrValue, int ctrNumBitSize)) IPP_DEPRECATED(TDES_DEPRECATED) \ IPPAPI(IppStatus, ippsTDESDecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pCtrValue, int ctrNumBitSize)) /* AES */ IPPAPI(IppStatus, ippsAESGetSize,(int *pSize)) IPPAPI(IppStatus, ippsAESInit,(const Ipp8u* pKey, int keyLen, IppsAESSpec* pCtx, int ctxSize)) IPPAPI(IppStatus, ippsAESSetKey,(const Ipp8u* pKey, int keyLen, IppsAESSpec* pCtx)) IPPAPI(IppStatus, ippsAESPack,(const IppsAESSpec* pCtx, Ipp8u* pBuffer, int bufSize)) IPPAPI(IppStatus, ippsAESUnpack,(const Ipp8u* pBuffer, IppsAESSpec* pCtx, int ctxSize)) #define ECB_DEPRECATED "ECB functionality remains in the library, but it is not safe when used as is. \ It is recommended to use any other mode, for example CBC." IPP_DEPRECATED(ECB_DEPRECATED) \ IPPAPI(IppStatus, ippsAESEncryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx)) IPP_DEPRECATED(ECB_DEPRECATED) \ IPPAPI(IppStatus, ippsAESDecryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx)) IPPAPI(IppStatus, ippsAESEncryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESEncryptCBC_CS1,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESEncryptCBC_CS2,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESEncryptCBC_CS3,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESDecryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESDecryptCBC_CS1,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESDecryptCBC_CS2,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESDecryptCBC_CS3,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESEncryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESDecryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsAESSpec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESEncryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESDecryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV)) IPPAPI(IppStatus, ippsAESEncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) IPPAPI(IppStatus, ippsAESDecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) IPPAPI(IppStatus, ippsAESEncryptXTS_Direct,(const Ipp8u* pSrc, Ipp8u* pDst, int encBitsize, int aesBlkNo, const Ipp8u* pTweakPT, const Ipp8u* pKey, int keyBitsize, int dataUnitBitsize)) IPPAPI(IppStatus, ippsAESDecryptXTS_Direct,(const Ipp8u* pSrc, Ipp8u* pDst, int encBitsize, int aesBlkNo, const Ipp8u* pTweakPT, const Ipp8u* pKey, int keyBitsize, int dataUnitBitsize)) IPPAPI(IppStatus, ippsAESSetupNoise,(Ipp32u noiseLevel, IppsAESSpec* pCtx)) IPPAPI(IppStatus, ippsAES_GCMSetupNoise,(Ipp32u noiseLevel, IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_CMACSetupNoise,(Ipp32u noiseLevel, IppsAES_CMACState* pState)) /* AES multi-buffer functions */ IPPAPI(IppStatus, ippsAES_EncryptCFB16_MB, (const Ipp8u* pSrc[], Ipp8u* pDst[], int len[], const IppsAESSpec* pCtx[], const Ipp8u* pIV[], IppStatus status[], int numBuffers)) /* SMS4 */ IPPAPI(IppStatus, ippsSMS4GetSize,(int *pSize)) IPPAPI(IppStatus, ippsSMS4Init,(const Ipp8u* pKey, int keyLen, IppsSMS4Spec* pCtx, int ctxSize)) IPPAPI(IppStatus, ippsSMS4SetKey,(const Ipp8u* pKey, int keyLen, IppsSMS4Spec* pCtx)) IPP_DEPRECATED(ECB_DEPRECATED) \ IPPAPI(IppStatus, ippsSMS4EncryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx)) IPP_DEPRECATED(ECB_DEPRECATED) \ IPPAPI(IppStatus, ippsSMS4DecryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx)) IPPAPI(IppStatus, ippsSMS4EncryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4EncryptCBC_CS1,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4EncryptCBC_CS2,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4EncryptCBC_CS3,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4DecryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4DecryptCBC_CS1,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4DecryptCBC_CS2,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4DecryptCBC_CS3,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4EncryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4DecryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4EncryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4DecryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV)) IPPAPI(IppStatus, ippsSMS4EncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) IPPAPI(IppStatus, ippsSMS4DecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) /* SMS4-CCM */ IPPAPI(IppStatus, ippsSMS4_CCMGetSize,(int* pSize)) IPPAPI(IppStatus, ippsSMS4_CCMInit,(const Ipp8u* pKey, int keyLen, IppsSMS4_CCMState* pCtx, int ctxSize)) IPPAPI(IppStatus, ippsSMS4_CCMMessageLen,(Ipp64u msgLen, IppsSMS4_CCMState* pCtx)) IPPAPI(IppStatus, ippsSMS4_CCMTagLen,(int tagLen, IppsSMS4_CCMState* pCtx)) IPPAPI(IppStatus, ippsSMS4_CCMStart,(const Ipp8u* pIV, int ivLen, const Ipp8u* pAD, int adLen, IppsSMS4_CCMState* pCtx)) IPPAPI(IppStatus, ippsSMS4_CCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsSMS4_CCMState* pCtx)) IPPAPI(IppStatus, ippsSMS4_CCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsSMS4_CCMState* pCtx)) IPPAPI(IppStatus, ippsSMS4_CCMGetTag,(Ipp8u* pTag, int tagLen, const IppsSMS4_CCMState* pCtx)) /* // ========================================================= // AES based authentication & confidence Primitives // ========================================================= */ /* AES-CCM */ IPPAPI(IppStatus, ippsAES_CCMGetSize,(int* pSize)) IPPAPI(IppStatus, ippsAES_CCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_CCMState* pState, int ctxSize)) IPPAPI(IppStatus, ippsAES_CCMMessageLen,(Ipp64u msgLen, IppsAES_CCMState* pState)) IPPAPI(IppStatus, ippsAES_CCMTagLen,(int tagLen, IppsAES_CCMState* pState)) IPPAPI(IppStatus, ippsAES_CCMStart,(const Ipp8u* pIV, int ivLen, const Ipp8u* pAD, int adLen, IppsAES_CCMState* pState)) IPPAPI(IppStatus, ippsAES_CCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_CCMState* pState)) IPPAPI(IppStatus, ippsAES_CCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_CCMState* pState)) IPPAPI(IppStatus, ippsAES_CCMGetTag,(Ipp8u* pTag, int tagLen, const IppsAES_CCMState* pState)) /* AES-GCM */ IPPAPI(IppStatus, ippsAES_GCMGetSize,(int * pSize)) IPPAPI(IppStatus, ippsAES_GCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_GCMState* pState, int ctxSize)) IPPAPI(IppStatus, ippsAES_GCMReinit,(IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMReset,(IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMProcessIV,(const Ipp8u* pIV, int ivLen, IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMProcessAAD,(const Ipp8u* pAAD, int aadLen, IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMStart,(const Ipp8u* pIV, int ivLen, const Ipp8u* pAAD, int aadLen, IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_GCMState* pState)) IPPAPI(IppStatus, ippsAES_GCMGetTag,(Ipp8u* pDstTag, int tagLen, const IppsAES_GCMState* pState)) /* AES-XTS */ IPPAPI(IppStatus, ippsAES_XTSGetSize,(int * pSize)) IPPAPI(IppStatus, ippsAES_XTSInit,(const Ipp8u* pKey, int keyLen, int duBitsize, IppsAES_XTSSpec* pCtx,int ctxSize)) IPPAPI(IppStatus, ippsAES_XTSEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int bitSizeLen, const IppsAES_XTSSpec* pCtx, const Ipp8u* pTweak, int startCipherBlkNo)) IPPAPI(IppStatus, ippsAES_XTSDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int bitSizeLen, const IppsAES_XTSSpec* pCtx, const Ipp8u* pTweak, int startCipherBlkNo)) /* AES-SIV (RFC 5297) */ IPPAPI(IppStatus, ippsAES_S2V_CMAC,(const Ipp8u* pKey, int keyLen, const Ipp8u* pAD[], const int pADlen[], int numAD, Ipp8u* pV)) IPPAPI(IppStatus, ippsAES_SIVEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, Ipp8u* pSIV, const Ipp8u* pAuthKey, const Ipp8u* pConfKey, int keyLen, const Ipp8u* pAD[], const int pADlen[], int numAD)) IPPAPI(IppStatus, ippsAES_SIVDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int* pAuthPassed, const Ipp8u* pAuthKey, const Ipp8u* pConfKey, int keyLen, const Ipp8u* pAD[], const int pADlen[], int numAD, const Ipp8u* pSIV)) /* AES-CMAC */ IPPAPI(IppStatus, ippsAES_CMACGetSize,(int* pSize)) IPPAPI(IppStatus, ippsAES_CMACInit,(const Ipp8u* pKey, int keyLen, IppsAES_CMACState* pState, int ctxSize)) IPPAPI(IppStatus, ippsAES_CMACUpdate,(const Ipp8u* pSrc, int len, IppsAES_CMACState* pState)) IPPAPI(IppStatus, ippsAES_CMACFinal,(Ipp8u* pMD, int mdLen, IppsAES_CMACState* pState)) IPPAPI(IppStatus, ippsAES_CMACGetTag,(Ipp8u* pMD, int mdLen, const IppsAES_CMACState* pState)) /* // ========================================================= // RC4 Stream Ciphers // ========================================================= */ #define RC4_DEPRECATED "is deprecated. This algorithm is considered weak due to known attacks on it. \ It is obsolete and will be removed in one of the future Intel Cryptography Primitives Library releases." IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourCheckKey, (const Ipp8u *pKey, int keyLen, IppBool* pIsWeak)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourGetSize, (int* pSize)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourInit, (const Ipp8u *pKey, int keyLen, IppsARCFourState *pCtx)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourReset, (IppsARCFourState* pCtx)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourPack,(const IppsARCFourState* pCtx, Ipp8u* pBuffer)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourUnpack,(const Ipp8u* pBuffer, IppsARCFourState* pCtx)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourEncrypt, (const Ipp8u *pSrc, Ipp8u *pDst, int length, IppsARCFourState *pCtx)) IPP_DEPRECATED(RC4_DEPRECATED) \ IPPAPI(IppStatus, ippsARCFourDecrypt, (const Ipp8u *pSrc, Ipp8u *pDst, int length, IppsARCFourState *pCtx)) /* // ========================================================= // One-Way Hash Functions // ========================================================= */ #define SHA1_DEPRECATED "This algorithm is considered weak due to known attacks on it. \ The functionality remains in the library, but the implementation will no be longer \ optimized and no security patches will be applied. A more secure alternative is available: SHA-2" #define MD5_DEPRECATED "This algorithm is considered weak due to known attacks on it. \ The functionality remains in the library, but the implementation will no be longer \ optimized and no security patches will be applied. A more secure alternative is available: SHA-2" /* generalized Hash Primitives */ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashGetSize,(int* pSize)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashInit,(IppsHashState* pState, IppHashAlgId hashAlg)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashPack,(const IppsHashState* pState, Ipp8u* pBuffer, int bufSize)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashUnpack,(const Ipp8u* pBuffer, IppsHashState* pState)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashDuplicate,(const IppsHashState* pSrcState, IppsHashState* pDstState)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashUpdate,(const Ipp8u* pSrc, int len, IppsHashState* pState)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashGetTag,(Ipp8u* pTag, int tagLen, const IppsHashState* pState)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashFinal,(Ipp8u* pMD, IppsHashState* pState)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHashMessage,(const Ipp8u* pMsg, int len, Ipp8u* pMD, IppHashAlgId hashAlg)) /* method based generalized (reduced memory footprint) Hash Primitives */ IPP_DEPRECATED(MD5_DEPRECATED) \ IPPAPI( const IppsHashMethod*, ippsHashMethod_MD5, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SM3, (void) ) IPP_DEPRECATED(SHA1_DEPRECATED) \ IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA1, (void) ) IPP_DEPRECATED(SHA1_DEPRECATED) \ IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA1_NI, (void) ) IPP_DEPRECATED(SHA1_DEPRECATED) \ IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA1_TT, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA256, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA256_NI, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA256_TT, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA224, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA224_NI, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA224_TT, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA512, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA384, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA512_256, (void) ) IPPAPI( const IppsHashMethod*, ippsHashMethod_SHA512_224, (void) ) IPPAPI( IppStatus, ippsHashMethodGetSize, (int* pSize) ) IPP_DEPRECATED(MD5_DEPRECATED) \ IPPAPI( IppStatus, ippsHashMethodSet_MD5, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SM3, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SM3, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPP_DEPRECATED(SHA1_DEPRECATED) \ IPPAPI( IppStatus, ippsHashMethodSet_SHA1, (IppsHashMethod* pMethod) ) IPP_DEPRECATED(SHA1_DEPRECATED) \ IPPAPI( IppStatus, ippsHashMethodSet_SHA1_NI, (IppsHashMethod* pMethod) ) IPP_DEPRECATED(SHA1_DEPRECATED) \ IPPAPI( IppStatus, ippsHashMethodSet_SHA1_TT, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA256, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA256_NI, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA256_TT, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA256, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA256_NI, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA256_TT, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA224, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA224_NI, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA224_TT, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA224, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA224_NI, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA224_TT, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA512, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA384, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA512_256, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashMethodSet_SHA512_224, (IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA512, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA384, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA512_256, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI( IppStatus, ippsHashStateMethodSet_SHA512_224, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) IPPAPI(IppStatus, ippsHashGetSize_rmf,(int* pSize)) IPPAPI(IppStatus, ippsHashInit_rmf,(IppsHashState_rmf* pState, const IppsHashMethod* pMethod)) IPPAPI(IppStatus, ippsHashPack_rmf,(const IppsHashState_rmf* pState, Ipp8u* pBuffer, int bufSize)) IPPAPI(IppStatus, ippsHashUnpack_rmf,(const Ipp8u* pBuffer, IppsHashState_rmf* pState)) IPPAPI(IppStatus, ippsHashDuplicate_rmf,(const IppsHashState_rmf* pSrcState, IppsHashState_rmf* pDstState)) IPPAPI(IppStatus, ippsHashUpdate_rmf,(const Ipp8u* pSrc, int len, IppsHashState_rmf* pState)) IPPAPI(IppStatus, ippsHashGetTag_rmf,(Ipp8u* pMD, int tagLen, const IppsHashState_rmf* pState)) IPPAPI(IppStatus, ippsHashFinal_rmf,(Ipp8u* pMD, IppsHashState_rmf* pState)) IPPAPI(IppStatus, ippsHashMessage_rmf,(const Ipp8u* pMsg, int len, Ipp8u* pMD, const IppsHashMethod* pMethod)) IPPAPI(IppStatus, ippsHashMethodGetInfo,(IppsHashInfo* pInfo, const IppsHashMethod* pMethod)) IPPAPI(IppStatus, ippsHashGetInfo_rmf,(IppsHashInfo* pInfo, const IppsHashState_rmf* pState)) /* general MGF Primitives*/ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsMGF,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, IppHashAlgId hashAlg)) IPPAPI(IppStatus, ippsMGF1_rmf,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, const IppsHashMethod* pMethod)) IPPAPI(IppStatus, ippsMGF2_rmf,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, const IppsHashMethod* pMethod)) /* // ========================================================= // Keyed-Hash Message Authentication Codes // ========================================================= */ /* generalized Keyed HMAC primitives */ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_GetSize,(int* pSize)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Init,(const Ipp8u* pKey, int keyLen, IppsHMACState* pCtx, IppHashAlgId hashAlg)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Pack,(const IppsHMACState* pCtx, Ipp8u* pBuffer, int bufSize)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Unpack,(const Ipp8u* pBuffer, IppsHMACState* pCtx)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Duplicate,(const IppsHMACState* pSrcCtx, IppsHMACState* pDstCtx)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Update,(const Ipp8u* pSrc, int len, IppsHMACState* pCtx)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Final,(Ipp8u* pMD, int mdLen, IppsHMACState* pCtx)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_GetTag,(Ipp8u* pMD, int mdLen, const IppsHMACState* pCtx)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsHMAC_Message,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pKey, int keyLen, Ipp8u* pMD, int mdLen, IppHashAlgId hashAlg)) /* method based generalized (reduced memory footprint) Keyed HMAC primitives */ IPPAPI(IppStatus, ippsHMACGetSize_rmf,(int* pSize)) IPPAPI(IppStatus, ippsHMACInit_rmf,(const Ipp8u* pKey, int keyLen, IppsHMACState_rmf* pCtx, const IppsHashMethod* pMethod)) IPPAPI(IppStatus, ippsHMACPack_rmf,(const IppsHMACState_rmf* pCtx, Ipp8u* pBuffer, int bufSize)) IPPAPI(IppStatus, ippsHMACUnpack_rmf,(const Ipp8u* pBuffer, IppsHMACState_rmf* pCtx)) IPPAPI(IppStatus, ippsHMACDuplicate_rmf,(const IppsHMACState_rmf* pSrcCtx, IppsHMACState_rmf* pDstCtx)) IPPAPI(IppStatus, ippsHMACUpdate_rmf,(const Ipp8u* pSrc, int len, IppsHMACState_rmf* pCtx)) IPPAPI(IppStatus, ippsHMACFinal_rmf,(Ipp8u* pMD, int mdLen, IppsHMACState_rmf* pCtx)) IPPAPI(IppStatus, ippsHMACGetTag_rmf,(Ipp8u* pMD, int mdLen, const IppsHMACState_rmf* pCtx)) IPPAPI(IppStatus, ippsHMACMessage_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pKey, int keyLen, Ipp8u* pMD, int mdLen, const IppsHashMethod* pMethod)) /* // ========================================================= // Big Number Integer Arithmetic // ========================================================= */ /* Signed BigNum Operations */ IPPAPI(IppStatus, ippsBigNumGetSize,(int length, int* pSize)) IPPAPI(IppStatus, ippsBigNumInit,(int length, IppsBigNumState* pBN)) IPPAPI(IppStatus, ippsCmpZero_BN,(const IppsBigNumState* pBN, Ipp32u* pResult)) IPPAPI(IppStatus, ippsCmp_BN,(const IppsBigNumState* pA, const IppsBigNumState* pB, Ipp32u* pResult)) IPPAPI(IppStatus, ippsGetSize_BN,(const IppsBigNumState* pBN, int* pSize)) IPPAPI(IppStatus, ippsSet_BN,(IppsBigNumSGN sgn, int length, const Ipp32u* pData, IppsBigNumState* pBN)) IPPAPI(IppStatus, ippsGet_BN,(IppsBigNumSGN* pSgn, int* pLength, Ipp32u* pData, const IppsBigNumState* pBN)) IPPAPI(IppStatus, ippsRef_BN,(IppsBigNumSGN* pSgn, int* bitSize, Ipp32u** const ppData, const IppsBigNumState* pBN)) IPPAPI(IppStatus, ippsExtGet_BN,(IppsBigNumSGN* pSgn, int* pBitSize, Ipp32u* pData, const IppsBigNumState* pBN)) IPPAPI(IppStatus, ippsAdd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsSub_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsMul_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsMAC_BN_I, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsDiv_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pQ, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsMod_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsGcd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pGCD)) IPPAPI(IppStatus, ippsModInv_BN,(IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pInv)) IPPAPI(IppStatus, ippsSetOctString_BN,(const Ipp8u* pStr, int strLen, IppsBigNumState* pBN)) IPPAPI(IppStatus, ippsGetOctString_BN,(Ipp8u* pStr, int strLen, const IppsBigNumState* pBN)) /* Montgomery Operations */ IPPAPI(IppStatus, ippsMontGetSize,(IppsExpMethod method, int length, int* pSize)) IPPAPI(IppStatus, ippsMontInit,(IppsExpMethod method, int length, IppsMontState* pCtx)) IPPAPI(IppStatus, ippsMontSet,(const Ipp32u* pModulo, int size, IppsMontState* pCtx)) IPPAPI(IppStatus, ippsMontGet,(Ipp32u* pModulo, int* pSize, const IppsMontState* pCtx)) IPPAPI(IppStatus, ippsMontForm,(const IppsBigNumState* pA, IppsMontState* pCtx, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsMontMul, (const IppsBigNumState* pA, const IppsBigNumState* pB, IppsMontState* m, IppsBigNumState* pR)) IPPAPI(IppStatus, ippsMontExp, (const IppsBigNumState* pA, const IppsBigNumState* pE, IppsMontState* m, IppsBigNumState* pR)) /* Pseudo-Random Number Generation */ #define PRNG_DEPRECATED "This algorithm is considered weak since it's based on the outdated FIPS standard(FIPS 186-2). \ The functionality remains in the library, but its implementation is not recommended for use. \ A more secure alternative is available: ippsPRNGenRDRAND and ippsTRNGenRDSEED." IPPAPI(IppStatus, ippsPRNGGetSize,(int* pSize)) IPPAPI(IppStatus, ippsPRNGInit, (int seedBits, IppsPRNGState* pCtx)) IPPAPI(IppStatus, ippsPRNGSetModulus,(const IppsBigNumState* pMod, IppsPRNGState* pCtx)) IPPAPI(IppStatus, ippsPRNGSetH0, (const IppsBigNumState* pH0, IppsPRNGState* pCtx)) IPPAPI(IppStatus, ippsPRNGSetAugment,(const IppsBigNumState* pAug, IppsPRNGState* pCtx)) IPPAPI(IppStatus, ippsPRNGSetSeed, (const IppsBigNumState* pSeed,IppsPRNGState* pCtx)) IPPAPI(IppStatus, ippsPRNGGetSeed, (const IppsPRNGState* pCtx,IppsBigNumState* pSeed)) IPP_DEPRECATED(PRNG_DEPRECATED) \ IPPAPI(IppStatus, ippsPRNGen, (Ipp32u* pRand, int nBits, void* pCtx)) IPP_DEPRECATED(PRNG_DEPRECATED) \ IPPAPI(IppStatus, ippsPRNGen_BN, (IppsBigNumState* pRand, int nBits, void* pCtx)) IPPAPI(IppStatus, ippsPRNGenRDRAND, (Ipp32u* pRand, int nBits, void* pCtx)) IPPAPI(IppStatus, ippsPRNGenRDRAND_BN,(IppsBigNumState* pRand, int nBits, void* pCtx)) IPPAPI(IppStatus, ippsTRNGenRDSEED, (Ipp32u* pRand, int nBits, void* pCtx)) IPPAPI(IppStatus, ippsTRNGenRDSEED_BN,(IppsBigNumState* pRand, int nBits, void* pCtx)) /* Probable Prime Number Generation */ IPPAPI(IppStatus, ippsPrimeGetSize,(int nMaxBits, int* pSize)) IPPAPI(IppStatus, ippsPrimeInit, (int nMaxBits, IppsPrimeState* pCtx)) IPPAPI(IppStatus, ippsPrimeGen, (int nBits, int nTrials, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsPrimeTest,(int nTrials, Ipp32u* pResult, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsPrimeGen_BN,(IppsBigNumState* pPrime, int nBits, int nTrials, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsPrimeTest_BN,(const IppsBigNumState* pPrime, int nTrials, Ipp32u* pResult, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsPrimeGet, (Ipp32u* pPrime, int* pLen, const IppsPrimeState* pCtx)) IPPAPI(IppStatus, ippsPrimeGet_BN,(IppsBigNumState* pPrime, const IppsPrimeState* pCtx)) IPPAPI(IppStatus, ippsPrimeSet, (const Ipp32u* pPrime, int nBits, IppsPrimeState* pCtx)) IPPAPI(IppStatus, ippsPrimeSet_BN,(const IppsBigNumState* pPrime, IppsPrimeState* pCtx)) /* // ========================================================= // RSA Cryptography // ========================================================= */ IPPAPI(IppStatus, ippsRSA_GetSizePublicKey,(int rsaModulusBitSize, int pubicExpBitSize, int* pKeySize)) IPPAPI(IppStatus, ippsRSA_InitPublicKey,(int rsaModulusBitSize, int publicExpBitSize, IppsRSAPublicKeyState* pKey, int keyCtxSize)) IPPAPI(IppStatus, ippsRSA_SetPublicKey,(const IppsBigNumState* pModulus, const IppsBigNumState* pPublicExp, IppsRSAPublicKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetPublicKey,(IppsBigNumState* pModulus, IppsBigNumState* pPublicExp, const IppsRSAPublicKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetSizePrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, int* pKeySize)) IPPAPI(IppStatus, ippsRSA_InitPrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, IppsRSAPrivateKeyState* pKey, int keyCtxSize)) IPPAPI(IppStatus, ippsRSA_SetPrivateKeyType1,(const IppsBigNumState* pModulus, const IppsBigNumState* pPrivateExp, IppsRSAPrivateKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetPrivateKeyType1,(IppsBigNumState* pModulus, IppsBigNumState* pPrivateExp, const IppsRSAPrivateKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetSizePrivateKeyType2,(int factorPbitSize, int factorQbitSize, int* pKeySize)) IPPAPI(IppStatus, ippsRSA_InitPrivateKeyType2,(int factorPbitSize, int factorQbitSize, IppsRSAPrivateKeyState* pKey, int keyCtxSize)) IPPAPI(IppStatus, ippsRSA_SetPrivateKeyType2,(const IppsBigNumState* pFactorP, const IppsBigNumState* pFactorQ, const IppsBigNumState* pCrtExpP, const IppsBigNumState* pCrtExpQ, const IppsBigNumState* pInverseQ, IppsRSAPrivateKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetPrivateKeyType2,(IppsBigNumState* pFactorP, IppsBigNumState* pFactorQ, IppsBigNumState* pCrtExpP, IppsBigNumState* pCrtExpQ, IppsBigNumState* pInverseQ, const IppsRSAPrivateKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetBufferSizePublicKey,(int* pBufferSize, const IppsRSAPublicKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_GetBufferSizePrivateKey,(int* pBufferSize, const IppsRSAPrivateKeyState* pKey)) IPPAPI(IppStatus, ippsRSA_Encrypt,(const IppsBigNumState* pPtxt, IppsBigNumState* pCtxt, const IppsRSAPublicKeyState* pKey, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsRSA_Decrypt,(const IppsBigNumState* pCtxt, IppsBigNumState* pPtxt, const IppsRSAPrivateKeyState* pKey, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsRSA_GenerateKeys,(const IppsBigNumState* pSrcPublicExp, IppsBigNumState* pModulus, IppsBigNumState* pPublicExp, IppsBigNumState* pPrivateExp, IppsRSAPrivateKeyState* pPrivateKeyType2, Ipp8u* pScratchBuffer, int nTrials, IppsPrimeState* pPrimeGen, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsRSA_ValidateKeys,(int* pResult, const IppsRSAPublicKeyState* pPublicKey, const IppsRSAPrivateKeyState* pPrivateKeyType2, const IppsRSAPrivateKeyState* pPrivateKeyType1, Ipp8u* pScratchBuffer, int nTrials, IppsPrimeState* pPrimeGen, IppBitSupplier rndFunc, void* pRndParam)) /* encryption scheme: RSAES-OAEP */ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsRSAEncrypt_OAEP,(const Ipp8u* pSrc, int srcLen, const Ipp8u* pLabel, int labLen, const Ipp8u* pSeed, Ipp8u* pDst, const IppsRSAPublicKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pBuffer)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsRSADecrypt_OAEP,(const Ipp8u* pSrc, const Ipp8u* pLab, int labLen, Ipp8u* pDst, int* pDstLen, const IppsRSAPrivateKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsRSAEncrypt_OAEP_rmf,(const Ipp8u* pSrc, int srcLen, const Ipp8u* pLabel, int labLen, const Ipp8u* pSeed, Ipp8u* pDst, const IppsRSAPublicKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsRSADecrypt_OAEP_rmf,(const Ipp8u* pSrc, const Ipp8u* pLab, int labLen, Ipp8u* pDst, int* pDstLen, const IppsRSAPrivateKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pBuffer)) /* encryption scheme: RSAES-PKCS_v1_5 */ #define PKCS_DEPRECATED "This algorithm is considered weak due to known attacks on it. \ The functionality remains in the library, but the implementation will no be longer \ optimized and no security patches will be applied. A more secure alternative is available: RSA-OAEP" IPP_DEPRECATED(PKCS_DEPRECATED) \ IPPAPI(IppStatus, ippsRSAEncrypt_PKCSv15,(const Ipp8u* pSrc, int srcLen, const Ipp8u* pRndPS, Ipp8u* pDst, const IppsRSAPublicKeyState* pKey, Ipp8u* pBuffer)) IPP_DEPRECATED(PKCS_DEPRECATED) \ IPPAPI(IppStatus, ippsRSADecrypt_PKCSv15,(const Ipp8u* pSrc, Ipp8u* pDst, int* pDstLen, const IppsRSAPrivateKeyState* pKey, Ipp8u* pBuffer)) /* signature scheme : RSA-SSA-PSS */ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsRSASign_PSS,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSalt, int saltLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, IppHashAlgId hashAlg, Ipp8u* pBuffer)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsRSAVerify_PSS,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsRSASign_PSS_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSalt, int saltLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, const IppsHashMethod* pMethod, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsRSAVerify_PSS_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pBuffer)) /* signature scheme : RSA-SSA-PKCS1-v1_5 */ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsRSASign_PKCS1v15,(const Ipp8u* pMsg, int msgLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, IppHashAlgId hashAlg, Ipp8u* pBuffer)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsRSAVerify_PKCS1v15,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsRSASign_PKCS1v15_rmf,(const Ipp8u* pMsg, int msgLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, const IppsHashMethod* pMethod, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsRSAVerify_PKCS1v15_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pBuffer)) /* // ========================================================= // DL Cryptography // ========================================================= */ IPPAPI( const char*, ippsDLGetResultString, (IppDLResult code)) /* Initialization */ IPPAPI(IppStatus, ippsDLPGetSize,(int bitSizeP, int bitSizeR, int* pSize)) IPPAPI(IppStatus, ippsDLPInit, (int bitSizeP, int bitSizeR, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPPack,(const IppsDLPState* pCtx, Ipp8u* pBuffer)) IPPAPI(IppStatus, ippsDLPUnpack,(const Ipp8u* pBuffer, IppsDLPState* pCtx)) /* Set Up and Retrieve Domain Parameters */ IPPAPI(IppStatus, ippsDLPSet,(const IppsBigNumState* pP, const IppsBigNumState* pR, const IppsBigNumState* pG, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPGet,(IppsBigNumState* pP, IppsBigNumState* pR, IppsBigNumState* pG, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPSetDP,(const IppsBigNumState* pDP, IppDLPKeyTag tag, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPGetDP,(IppsBigNumState* pDP, IppDLPKeyTag tag, const IppsDLPState* pCtx)) /* Key Generation, Validation and Set Up */ IPPAPI(IppStatus, ippsDLPGenKeyPair,(IppsBigNumState* pPrvKey, IppsBigNumState* pPubKey, IppsDLPState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsDLPPublicKey, (const IppsBigNumState* pPrvKey, IppsBigNumState* pPubKey, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPValidateKeyPair,(const IppsBigNumState* pPrvKey, const IppsBigNumState* pPubKey, IppDLResult* pResult, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPSetKeyPair,(const IppsBigNumState* pPrvKey, const IppsBigNumState* pPubKey, IppsDLPState* pCtx)) /* Signing/Verifying (DSA version) */ IPPAPI(IppStatus, ippsDLPSignDSA, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pPrvKey, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsDLPState* pCtx)) IPPAPI(IppStatus, ippsDLPVerifyDSA,(const IppsBigNumState* pMsgDigest, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppDLResult* pResult, IppsDLPState* pCtx)) /* Shared Secret Element (DH version) */ IPPAPI(IppStatus, ippsDLPSharedSecretDH,(const IppsBigNumState* pPrvKeyA, const IppsBigNumState* pPubKeyB, IppsBigNumState* pShare, IppsDLPState* pCtx)) /* DSA's parameter Generation and Validation */ IPPAPI(IppStatus, ippsDLPGenerateDSA,(const IppsBigNumState* pSeedIn, int nTrials, IppsDLPState* pCtx, IppsBigNumState* pSeedOut, int* pCounter, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsDLPValidateDSA,(int nTrials, IppDLResult* pResult, IppsDLPState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) /* DH parameter's Generation and Validation */ IPPAPI(IppStatus, ippsDLPGenerateDH,(const IppsBigNumState* pSeedIn, int nTrials, IppsDLPState* pCtx, IppsBigNumState* pSeedOut, int* pCounter, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsDLPValidateDH,(int nTrials, IppDLResult* pResult, IppsDLPState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) /* // ========================================================= // EC Cryptography // ========================================================= */ IPPAPI( const char*, ippsECCGetResultString, (IppECResult code)) /* // GF over prime and its extension */ IPPAPI(IppStatus, ippsGFpGetSize, (int feBitSize, int* pSize)) IPPAPI(IppStatus, ippsGFpInitArbitrary,(const IppsBigNumState* pPrime, int primeBitSize, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpInitFixed,(int primeBitSize, const IppsGFpMethod* pGFpMethod, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpInit, (const IppsBigNumState* pPrime, int primeBitSize, const IppsGFpMethod* pGFpMethod, IppsGFpState* pGFp)) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p192r1, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p224r1, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p256r1, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p384r1, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p521r1, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p256sm2,(void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p256bn, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_p256, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpMethod_pArb, (void) ) IPPAPI(IppStatus, ippsGFpxGetSize,(const IppsGFpState* pGroundGF, int degree, int* pSize)) IPPAPI(IppStatus, ippsGFpxInit, (const IppsGFpState* pGroundGF, int extDeg, const IppsGFpElement* const ppGroundElm[], int nElm, const IppsGFpMethod* pGFpMethod, IppsGFpState* pGFpx)) IPPAPI(IppStatus, ippsGFpxInitBinomial,(const IppsGFpState* pGroundGF, int extDeg, const IppsGFpElement* pGroundElm, const IppsGFpMethod* pGFpMethod, IppsGFpState* pGFpx)) IPPAPI( const IppsGFpMethod*, ippsGFpxMethod_binom2_epid2,(void) ) IPPAPI( const IppsGFpMethod*, ippsGFpxMethod_binom3_epid2,(void) ) IPPAPI( const IppsGFpMethod*, ippsGFpxMethod_binom2, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpxMethod_binom3, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpxMethod_binom, (void) ) IPPAPI( const IppsGFpMethod*, ippsGFpxMethod_com, (void) ) IPPAPI(IppStatus, ippsGFpScratchBufferSize,(int nExponents, int ExpBitSize, const IppsGFpState* pGFp, int* pBufferSize)) IPPAPI(IppStatus, ippsGFpElementGetSize,(const IppsGFpState* pGFp, int* pElementSize)) IPPAPI(IppStatus, ippsGFpElementInit, (const Ipp32u* pA, int lenA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSetElement, (const Ipp32u* pA, int lenA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSetElementRegular,(const IppsBigNumState* pBN, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSetElementOctString,(const Ipp8u* pStr, int strSize, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSetElementRandom,(IppsGFpElement* pR, IppsGFpState* pGFp, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsGFpSetElementHash,(const Ipp8u* pMsg, int msgLen, IppsGFpElement* pElm, IppsGFpState* pGFp, IppHashAlgId hashID)) IPPAPI(IppStatus, ippsGFpSetElementHash_rmf,(const Ipp8u* pMsg, int msgLen, IppsGFpElement* pElm, IppsGFpState* pGFp, const IppsHashMethod* pMethod)) IPPAPI(IppStatus, ippsGFpCpyElement,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpGetElement,(const IppsGFpElement* pA, Ipp32u* pDataA, int lenA, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpGetElementOctString,(const IppsGFpElement* pA, Ipp8u* pStr, int strSize, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpCmpElement,(const IppsGFpElement* pA, const IppsGFpElement* pB, int* pResult, const IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpIsZeroElement,(const IppsGFpElement* pA, int* pResult, const IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpIsUnityElement,(const IppsGFpElement* pA, int* pResult, const IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpConj,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpNeg, (const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpInv, (const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSqrt,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSqr, (const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpAdd, (const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSub, (const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpMul, (const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpExp, (const IppsGFpElement* pA, const IppsBigNumState* pE, IppsGFpElement* pR, IppsGFpState* pGFp, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpMultiExp,(const IppsGFpElement* const ppElmA[], const IppsBigNumState* const ppE[], int nItems, IppsGFpElement* pR, IppsGFpState* pGFp, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpAdd_PE,(const IppsGFpElement* pA, const IppsGFpElement* pParentB, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpSub_PE,(const IppsGFpElement* pA, const IppsGFpElement* pParentB, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpMul_PE,(const IppsGFpElement* pA, const IppsGFpElement* pParentB, IppsGFpElement* pR, IppsGFpState* pGFp)) IPPAPI(IppStatus, ippsGFpGetInfo, (IppsGFpInfo* pInfo, const IppsGFpState* pGFp)) /* ================== */ IPPAPI(IppStatus, ippsGFpECGetSize,(const IppsGFpState* pGFp, int* pSize)) IPPAPI(IppStatus, ippsGFpECInit, (const IppsGFpState* pGFp, const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSet,(const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSetSubgroup,(const IppsGFpElement* pX, const IppsGFpElement* pY, const IppsBigNumState* pOrder, const IppsBigNumState* pCofactor, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd128r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd128r2,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd192r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd224r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd256r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd384r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStd521r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStdSM2, (const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECInitStdBN256,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECBindGxyTblStd192r1,(IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECBindGxyTblStd224r1,(IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECBindGxyTblStd256r1,(IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECBindGxyTblStd384r1,(IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECBindGxyTblStd521r1,(IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECBindGxyTblStdSM2, (IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECGet,(IppsGFpState** const ppGFp, IppsGFpElement* pA, IppsGFpElement* pB, const IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECGetSubgroup,(IppsGFpState** const ppGFp, IppsGFpElement* pX, IppsGFpElement* pY, IppsBigNumState* pOrder,IppsBigNumState* pCofactor, const IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECScratchBufferSize,(int nScalars, const IppsGFpECState* pEC, int* pBufferSize)) IPPAPI(IppStatus, ippsGFpECVerify,(IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECPointGetSize,(const IppsGFpECState* pEC, int* pSize)) IPPAPI(IppStatus, ippsGFpECPointInit, (const IppsGFpElement* pX, const IppsGFpElement* pY, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSetPointAtInfinity,(IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSetPoint,(const IppsGFpElement* pX, const IppsGFpElement* pY, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSetPointRegular,(const IppsBigNumState* pX, const IppsBigNumState* pY, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSetPointRandom,(IppsGFpECPoint* pPoint, IppsGFpECState* pEC, IppBitSupplier rndFunc, void* pRndParam, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECMakePoint,(const IppsGFpElement* pX, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsGFpECSetPointHash,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, IppHashAlgId hashID, Ipp8u* pScratchBuffer)) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI(IppStatus, ippsGFpECSetPointHashBackCompatible,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, IppHashAlgId hashID, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECSetPointHash_rmf,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECSetPointHashBackCompatible_rmf,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECGetPoint,(const IppsGFpECPoint* pPoint, IppsGFpElement* pX, IppsGFpElement* pY, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECGetPointRegular,(const IppsGFpECPoint* pPoint, IppsBigNumState* pX, IppsBigNumState* pY, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECSetPointOctString,(const Ipp8u* pStr, int strLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECGetPointOctString,(const IppsGFpECPoint* pPoint, Ipp8u* pStr, int strLen, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECTstPoint,(const IppsGFpECPoint* pP, IppECResult* pResult, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECTstPointInSubgroup,(const IppsGFpECPoint* pP, IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECCpyPoint,(const IppsGFpECPoint* pA, IppsGFpECPoint* pR, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECCmpPoint,(const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppECResult* pResult, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECNegPoint,(const IppsGFpECPoint* pP, IppsGFpECPoint* pR, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECAddPoint,(const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECPoint* pR, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECMulPoint,(const IppsGFpECPoint* pP, const IppsBigNumState* pN, IppsGFpECPoint* pR, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* keys */ IPPAPI(IppStatus, ippsGFpECPrivateKey,(IppsBigNumState* pPrivate, IppsGFpECState* pEC, IppBitSupplier rndFunc, void* pRndParam)) IPPAPI(IppStatus, ippsGFpECPublicKey,(const IppsBigNumState* pPrivate, IppsGFpECPoint* pPublic, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECTstKeyPair,(const IppsBigNumState* pPrivate, const IppsGFpECPoint* pPublic, IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* DH shared secret */ IPPAPI(IppStatus, ippsGFpECSharedSecretDH,(const IppsBigNumState* pPrivateA, const IppsGFpECPoint* pPublicB, IppsBigNumState* pShare, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECSharedSecretDHC,(const IppsBigNumState* pPrivateA, const IppsGFpECPoint* pPublicB, IppsBigNumState* pShare, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* sign generation/verification of DSA, NR, SM2 */ IPPAPI(IppStatus, ippsGFpECMessageRepresentationSM2, (IppsBigNumState* pMsgDigest, const Ipp8u* pMsg, int msgLen, const Ipp8u* pUserID, int userIDLen, const IppsGFpECPoint* pRegPublic, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECSignDSA, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECVerifyDSA, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECSignNR, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECVerifyNR, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECSignSM2, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECVerifySM2, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* SM2 UserIDHash */ IPPAPI(IppStatus, ippsGFpECUserIDHashSM2, (Ipp8u* pZaDigest, const Ipp8u* pUserID, int userIDLen, const IppsGFpECPoint* pPublicKey, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* SM2 Key Exchange */ IPPAPI(IppStatus, ippsGFpECKeyExchangeSM2_GetSize, (const IppsGFpECState* pEC, int* pSize)) IPPAPI(IppStatus, ippsGFpECKeyExchangeSM2_Init, (IppsGFpECKeyExchangeSM2State* pKE, IppsKeyExchangeRoleSM2 role, IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECKeyExchangeSM2_Setup, (const Ipp8u pZSelf[IPP_SM3_DIGEST_BYTESIZE], const Ipp8u pZPeer[IPP_SM3_DIGEST_BYTESIZE], const IppsGFpECPoint *pPublicKeySelf, const IppsGFpECPoint *pPublicKeyPeer, const IppsGFpECPoint *pEphPublicKeySelf, const IppsGFpECPoint *pEphPublicKeyPeer, IppsGFpECKeyExchangeSM2State *pKE)) IPPAPI(IppStatus, ippsGFpECKeyExchangeSM2_SharedKey, (Ipp8u* pSharedKey, int sharedKeySize, Ipp8u* pSSelf, const IppsBigNumState* pPrvKey, IppsBigNumState* pEphPrvKey, IppsGFpECKeyExchangeSM2State *pKE, Ipp8u* pScratchBuffer)) IPPAPI(IppStatus, ippsGFpECKeyExchangeSM2_Confirm, (const Ipp8u pSPeer[IPP_SM3_DIGEST_BYTESIZE], int* pStatus, IppsGFpECKeyExchangeSM2State* pKE)) /* SM2 Encryption/Decryption */ IPPAPI(IppStatus, ippsGFpECGetInfo_GF,(IppsGFpInfo* pInfo, const IppsGFpECState* pEC)) IPPAPI(IppStatus, ippsGFpECESGetSize_SM2, (const IppsGFpECState* pEC, int* pSize)) IPPAPI(IppStatus, ippsGFpECESInit_SM2, (IppsGFpECState* pEC, IppsECESState_SM2* pState, int avaliableCtxSize)) IPPAPI(IppStatus, ippsGFpECESSetKey_SM2, (const IppsBigNumState* pPrivate, const IppsGFpECPoint* pPublic, IppsECESState_SM2* pState, IppsGFpECState* pEC, Ipp8u* pEcScratchBuffer)) IPPAPI(IppStatus, ippsGFpECESStart_SM2, (IppsECESState_SM2* pState)) IPPAPI(IppStatus, ippsGFpECESEncrypt_SM2, (const Ipp8u* pInput, Ipp8u* pOutput, int dataLen, IppsECESState_SM2* pState)) IPPAPI(IppStatus, ippsGFpECESDecrypt_SM2, (const Ipp8u* pInput, Ipp8u* pOutput, int dataLen, IppsECESState_SM2* pState)) IPPAPI(IppStatus, ippsGFpECESFinal_SM2, (Ipp8u* pTag, int tagLen, IppsECESState_SM2* pState)) IPPAPI(IppStatus, ippsGFpECESGetBuffersSize_SM2, (int* pPublicKeySize, int* pMaximumTagSize, const IppsECESState_SM2* pState)) /* SM2 Encryption/Decryption Extended API */ /* Encryption */ IPPAPI(IppStatus, ippsGFpECEncryptSM2_Ext_EncMsgSize, (const IppsGFpECState *pEC, int ptMsgSize, int *pSize)) IPPAPI(IppStatus, ippsGFpECEncryptSM2_Ext, (Ipp8u *pOut, int maxOutLen, int *pOutSize, const Ipp8u *pInp, int inpLen, const IppsGFpECPoint *pPublicKey, IppsGFpECPoint *pEhpPublicKey, IppsBigNumState *pEphPrvKey, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) /* Decryption */ IPPAPI(IppStatus, ippsGFpECDecryptSM2_Ext_DecMsgSize, (const IppsGFpECState *pEC, int ctMsgSize, int *pSize)) IPPAPI(IppStatus, ippsGFpECDecryptSM2_Ext, (Ipp8u *pOut, int maxOutLen, int *pOutSize, const Ipp8u *pInp, int inpLen, const IppsBigNumState *pPrvKey, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) #ifdef IPPCP_PREVIEW_XMSS /* XMSS */ IPPAPI(IppStatus, ippsXMSSBufferGetSize, (Ipp32s* pSize, Ipp32s maxMessageLength, IppsXMSSAlgo OIDAlgo)) IPPAPI(IppStatus, ippsXMSSPublicKeyStateGetSize, (Ipp32s* pSize, IppsXMSSAlgo OIDAlgo)) IPPAPI(IppStatus, ippsXMSSSignatureStateGetSize, (Ipp32s* pSize, IppsXMSSAlgo OIDAlgo)) IPPAPI(IppStatus, ippsXMSSSetPublicKeyState, (IppsXMSSAlgo OIDAlgo, const Ipp8u* pRoot, const Ipp8u* pSeed, IppsXMSSPublicKeyState* pState)) IPPAPI(IppStatus, ippsXMSSSetSignatureState, (IppsXMSSAlgo OIDAlgo, Ipp32u idx, const Ipp8u* r, const Ipp8u* pOTSSign, const Ipp8u* pAuthPath, IppsXMSSSignatureState* pState)) IPPAPI(IppStatus, ippsXMSSVerify, (const Ipp8u* pMsg, const Ipp32s msgLen, const IppsXMSSSignatureState* pSign, int* pIsSignValid, const IppsXMSSPublicKeyState* pKey, Ipp8u* pBuffer)) #endif // IPPCP_PREVIEW_XMSS #ifdef IPPCP_PREVIEW_LMS IPPAPI(IppStatus, ippsLMSBufferGetSize, (Ipp32s* pSize, Ipp32s maxMessageLength, const IppsLMSAlgoType lmsType)) IPPAPI(IppStatus, ippsLMSSignatureStateGetSize, (Ipp32s* pSize, const IppsLMSAlgoType lmsType)) IPPAPI(IppStatus, ippsLMSPublicKeyStateGetSize, (Ipp32s* pSize, const IppsLMSAlgoType lmsType)) IPPAPI(IppStatus, ippsLMSSetPublicKeyState, (const IppsLMSAlgoType lmsType, const Ipp8u* pI, const Ipp8u* pK, IppsLMSPublicKeyState* pState)) IPPAPI(IppStatus, ippsLMSSetSignatureState, (const IppsLMSAlgoType lmsType, Ipp32u q, const Ipp8u* pC, const Ipp8u* pY, const Ipp8u* pAuthPath, IppsLMSSignatureState* pState)) IPPAPI(IppStatus, ippsLMSVerify, (const Ipp8u* pMsg, const Ipp32s msgLen, const IppsLMSSignatureState* pSign, int* pIsSignValid, const IppsLMSPublicKeyState* pKey, Ipp8u* pBuffer)) #endif // IPPCP_PREVIEW_LMS #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) #pragma warning(pop) #endif #ifdef __cplusplus } #endif #endif /* IPPCP_H__ */ cryptography-primitives-1.0.0/include/ippcp/000077500000000000000000000000001470420105600211715ustar00rootroot00000000000000cryptography-primitives-1.0.0/include/ippcp/fips_cert.h000066400000000000000000000225371470420105600233310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 IPPCP_FIPS_CERT_H #define IPPCP_FIPS_CERT_H #include #include #if defined( __cplusplus ) extern "C" { #endif typedef int fips_test_status; typedef int func_fips_approved; #define IPPCP_ALGO_SELFTEST_OK (0) #define IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR (1) #define IPPCP_ALGO_SELFTEST_KAT_ERR (2) /* Enc/Dec */ IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptDecrypt_get_size, (int *pBuffSize)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptCBC, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptCBC, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptCBC_CS1, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptCBC_CS2, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptCBC_CS3, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptCBC_CS1, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptCBC_CS2, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptCBC_CS3, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptCFB, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptCFB, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptOFB, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptOFB, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptCTR, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESDecryptCTR, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptDecryptCCM_get_size, (int *pBuffSize)) IPPAPI(fips_test_status, fips_selftest_ippsAES_CCMEncrypt, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAES_CCMDecrypt, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAES_GCM_get_size, (int *pBufferSize)) IPPAPI(fips_test_status, fips_selftest_ippsAES_GCMEncrypt, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAES_GCMDecrypt, (Ipp8u *pBuffer)) /* Selftests are disabled for now, since AES-XTS algorithm didn't pass CAVP testing */ // IPPAPI(fips_test_status, fips_selftest_ippsAESEncryptDecryptXTS_get_size, (int *pBuffSize)) // IPPAPI(fips_test_status, fips_selftest_ippsAES_XTSEncrypt, (Ipp8u *pBuffer)) // IPPAPI(fips_test_status, fips_selftest_ippsAES_XTSDecrypt, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsAES_CMAC_get_size, (int *pBuffSize)) IPPAPI(fips_test_status, fips_selftest_ippsAES_CMACUpdate, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys, (int *pKeysBufferSize)) IPPAPI(fips_test_status, fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size, (int *pBufferSize, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSAEncrypt_OAEP_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSADecrypt_OAEP_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) /* Hashes */ IPPAPI(fips_test_status, fips_selftest_ippsHash_rmf_get_size, (int *pBuffSize)) IPPAPI(fips_test_status, fips_selftest_ippsHashUpdate_rmf, (IppHashAlgId hashAlgId, Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsHashMessage_rmf, (IppHashAlgId hashAlgId)) /* HMAC */ IPPAPI(fips_test_status, fips_selftest_ippsHMAC_rmf_get_size, (int *pBuffSize)) IPPAPI(fips_test_status, fips_selftest_ippsHMACUpdate_rmf, (Ipp8u *pBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsHMACMessage_rmf, (void)) /* RSA sign/verify */ IPPAPI(fips_test_status, fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys, (int *pKeysBufferSize)) IPPAPI(fips_test_status, fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size, (int *pBufferSize, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSASign_PKCS1v15_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSAVerify_PKCS1v15_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys, (int *pKeysBufferSize)) IPPAPI(fips_test_status, fips_selftest_ippsRSASignVerify_PSS_rmf_get_size, (int *pBufferSize, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSASign_PSS_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSAVerify_PSS_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) IPPAPI(fips_test_status, fips_selftest_ippsRSA_GenerateKeys, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) /* ECDSA sign/verify */ IPPAPI(fips_test_status, fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff, (int *pGFpBuffSize)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff, (int *pGFpECBuffSize, Ipp8u *pGFpBuff)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff, (int *pDataBuffSize, Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECSignDSA, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECVerifyDSA, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECPublicKey, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECPrivateKey, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) IPPAPI(fips_test_status, fips_selftest_ippsGFpECSharedSecretDH, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) /* LMS */ IPPAPI(fips_test_status, fips_selftest_ippsLMSVerify_get_size, (int *pBufferSize)) IPPAPI(fips_test_status, fips_selftest_ippsLMSVerify, (Ipp8u *pDataBuff)) /* // Enumerator that contains information about FIPS-approved // functions inside the ippcp cryptographic boundary */ enum FIPS_IPPCP_FUNC { /* Approved functions, > 0 */ AESEncryptCBC = 0x1, AESEncryptCBC_CS1, AESEncryptCBC_CS2, AESEncryptCBC_CS3, AESDecryptCBC, AESDecryptCBC_CS1, AESDecryptCBC_CS2, AESDecryptCBC_CS3, AESEncryptCFB, AESDecryptCFB, AESEncryptOFB, AESDecryptOFB, AESEncryptCTR, AESDecryptCTR, AES_CCMEncrypt, AES_CCMDecrypt, AES_CCMStart, AES_CCMGetTag, AES_GCMEncrypt, AES_GCMDecrypt, AES_GCMProcessIV, AES_GCMProcessAAD, AES_GCMStart, AES_GCMGetTag, RSASign_PKCS1v15_rmf, RSAVerify_PKCS1v15_rmf, RSASign_PSS_rmf, RSAVerify_PSS_rmf, RSA_GenerateKeys, GFpECSignDSA, GFpECVerifyDSA, GFpECSharedSecretDH, GFpECPublicKey, GFpECPrivateKey, HashUpdate_rmf, HashGetTag_rmf, HashFinal_rmf, HashMessage_rmf, AES_CMACUpdate, AES_CMACFinal, AES_CMACGetTag, HMACUpdate_rmf, HMACFinal_rmf, HMACGetTag_rmf, HMACMessage_rmf, RSAEncrypt_OAEP_rmf, RSADecrypt_OAEP_rmf, LMSVerify, /* Not approved functions or * FIPS-mode is not yet implemented, < 0 */ SMS4EncryptCBC = -0xFFF, SMS4EncryptCBC_CS1, SMS4EncryptCBC_CS2, SMS4EncryptCBC_CS3, SMS4DecryptCBC, SMS4DecryptCBC_CS1, SMS4DecryptCBC_CS2, SMS4DecryptCBC_CS3, SMS4EncryptCFB, SMS4DecryptCFB, SMS4EncryptOFB, SMS4DecryptOFB, SMS4EncryptCTR, SMS4DecryptCTR, SMS4_CCMStart, SMS4_CCMEncrypt, SMS4_CCMDecrypt, SMS4_CCMGetTag, /* XTS APIs didn't pass CAVP testing */ AES_XTSEncrypt, AES_XTSDecrypt, AESEncryptXTS_Direct, AESDecryptXTS_Direct, MGF1_rmf, MGF2_rmf, AES_EncryptCFB16_MB, AES_S2V_CMAC, AES_SIVEncrypt, AES_SIVDecrypt, PRNGen, PRNGen_BN, PRNGenRDRAND, PRNGenRDRAND_BN, TRNGenRDSEED, TRNGenRDSEED_BN, PrimeGen, PrimeGen_BN, RSA_Encrypt, RSA_Decrypt, DLPGenKeyPair, DLPPublicKey, DLPSignDSA, DLPVerifyDSA, DLPSharedSecretDH, DLPGenerateDSA, DLPGenerateDH, GFpECVerify, GFpECSharedSecretDHC, GFpECSignNR, GFpECVerifyNR, GFpECSignSM2, GFpECVerifySM2, GFpECUserIDHashSM2, GFpECKeyExchangeSM2_SharedKey, GFpECEncryptSM2_Ext, GFpECDecryptSM2_Ext, GFpECESStart_SM2, GFpECESEncrypt_SM2, GFpECESDecrypt_SM2, GFpECESFinal_SM2, XMSSVerify }; /** * \brief * * An indicator if a function is FIPS-approved or not * * \param[in] function member of FIPS_IPPCP_FUNC enumerator * that corresponds to API being checked. * \return func_fips_approved equal to 1 if FIPS-approved algorithm is used * * Example: * Library API FIPS_IPPCP_FUNC * ippsAESEncryptCBC -> AESEncryptCBC * ippsGFpECSignDSA -> GFpECSignDSA * ipps -> * */ IPPAPI(func_fips_approved, ippcp_is_fips_approved_func, (enum FIPS_IPPCP_FUNC function)) #if defined( __cplusplus ) } #endif #endif // IPPCP_FIPS_CERT_H cryptography-primitives-1.0.0/include/ippcpdefs.h000066400000000000000000001177661470420105600222260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2012 Intel Corporation * * 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. *************************************************************************/ /* // // Intel® Cryptography Primitives Library // // Purpose: Basic Types and Macro Definitions // */ #ifndef IPPBASE_H__ #define IPPBASE_H__ #ifdef __cplusplus extern "C" { #endif #if defined (_WIN64) #define IPPCP_INTEL_LIBS_DIR "lib/" #elif defined (_WIN32) #define IPPCP_INTEL_LIBS_DIR "lib32/" #endif #if !defined( IPPAPI ) /* Specify explicit calling convention for public functions */ #if defined( IPP_W32DLL ) && (defined( _WIN32 ) || defined( _WIN64 )) #if defined( _MSC_VER ) || defined( __ICL ) #define IPPAPI( type,name,arg ) \ __declspec(dllimport) type IPP_CALL name arg; #else #define IPPAPI( type,name,arg ) type IPP_CALL name arg; #endif #else #define IPPAPI( type,name,arg ) type IPP_CALL name arg; #endif #endif /* icc 2021 supports short float data type, icx supports _Float16 data type */ #define _FLOAT_16 2 #define _SHORT_FLOAT 1 #define _NO_FLOAT_16 0 #if defined(__INTEL_LLVM_COMPILER) && defined(__AVX512FP16__) # define COMPILER_SUPPORT_SHORT_FLOAT _FLOAT_16 #else # if defined(__INTEL_COMPILER) # if(__INTEL_COMPILER >= 2021) # define COMPILER_SUPPORT_SHORT_FLOAT _SHORT_FLOAT # endif # endif #endif #if !(defined(COMPILER_SUPPORT_SHORT_FLOAT)) # define COMPILER_SUPPORT_SHORT_FLOAT _NO_FLOAT_16 #endif #define OBSOLETE_API "is deprecated. This API is considered obsolete and will be removed in one of future Intel® Cryptography Primitives Library releases. \ Use the following link for opening a ticket and providing feedback: https://supporttickets.intel.com/ if you have concerns." #if !defined(_NO_IPP_DEPRECATED) #if (defined( __ICL ) || defined( __ECL ) || defined(_MSC_VER)) && !defined( _PCS ) && !defined( _PCS_GENSTUBS ) #if( __INTEL_COMPILER >= 1100 ) /* icl 11.0 supports additional comment */ #if( _MSC_VER >= 1400 ) #define IPP_DEPRECATED( comment ) __declspec( deprecated ( comment )) #else #pragma message ("your icl version supports additional comment for deprecated functions but it can't be displayed") #pragma message ("because internal _MSC_VER macro variable setting requires compatibility with MSVC7.1") #pragma message ("use -Qvc8 switch for icl command line to see these additional comments") #define IPP_DEPRECATED( comment ) __declspec( deprecated ) #endif #elif( _MSC_FULL_VER >= 140050727 )&&( !defined( __INTEL_COMPILER ))&&( !defined(__INTEL_LLVM_COMPILER)) /* VS2005 supports additional comment */ #define IPP_DEPRECATED( comment ) __declspec( deprecated ( comment )) #elif( _MSC_VER <= 1200 )&&( !defined( __INTEL_COMPILER ))&&( !defined(__INTEL_LLVM_COMPILER)) /* VS 6 doesn't support deprecation */ #define IPP_DEPRECATED( comment ) #else #define IPP_DEPRECATED( comment ) __declspec( deprecated ) #endif #elif (defined(__ICC) || defined(__ECC) || defined( __GNUC__ )) && !defined( _PCS ) && !defined( _PCS_GENSTUBS ) #if defined( __GNUC__ ) #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 #define IPP_DEPRECATED( message ) __attribute__(( deprecated( message ))) #else #define IPP_DEPRECATED( message ) __attribute__(( deprecated )) #endif #else #define IPP_DEPRECATED( comment ) __attribute__(( deprecated )) #endif #else #define IPP_DEPRECATED( comment ) #endif #else #define IPP_DEPRECATED( comment ) #endif #if (defined( __ICL ) || defined( __ECL ) || defined(_MSC_VER)) #if !defined( IPP_NO_DEFAULT_LIB ) #if ((defined( _IPP_SEQUENTIAL_DYNAMIC ) && !defined( _IPP_SEQUENTIAL_STATIC )) || \ (!defined( _IPP_SEQUENTIAL_DYNAMIC ) && defined( _IPP_SEQUENTIAL_STATIC ))) #elif (!defined( _IPP_SEQUENTIAL_DYNAMIC ) && !defined( _IPP_SEQUENTIAL_STATIC )) #define IPP_NO_DEFAULT_LIB #else #error Illegal combination of _IPP_SEQUENTIAL_DYNAMIC/_IPP_SEQUENTIAL_STATIC, only one definition can be defined #endif #endif #else #define IPP_NO_DEFAULT_LIB #if (defined(_IPP_SEQUENTIAL_DYNAMIC) || defined(_IPP_SEQUENTIAL_STATIC)) #pragma message ("defines _IPP_SEQUENTIAL_DYNAMIC/_IPP_SEQUENTIAL_STATIC do not have any effect in current configuration") #endif #endif #if defined (_MSC_VER) #define IPP_CDECL __cdecl #elif (defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || defined (__GNUC__ ) || defined (__clang__)) && defined (_ARCH_IA32) #define IPP_CDECL __attribute((cdecl)) #else #define IPP_CDECL #endif #if defined( _WIN32 ) || defined( _WIN64 ) #define IPP_STDCALL __stdcall #define IPP_CALL IPP_STDCALL #define IPP_INT64 __int64 #define IPP_UINT64 unsigned __int64 #else #define IPP_STDCALL #define IPP_CALL IPP_CDECL #define IPP_INT64 long long #define IPP_UINT64 unsigned long long #endif #define IPP_COUNT_OF( obj ) (sizeof(obj)/sizeof(obj[0])) #define IPP_PI ( 3.14159265358979323846 ) /* ANSI C does not support M_PI */ #define IPP_2PI ( 6.28318530717958647692 ) /* 2*pi */ #define IPP_PI2 ( 1.57079632679489661923 ) /* pi/2 */ #define IPP_PI4 ( 0.78539816339744830961 ) /* pi/4 */ #define IPP_PI180 ( 0.01745329251994329577 ) /* pi/180 */ #define IPP_RPI ( 0.31830988618379067154 ) /* 1/pi */ #define IPP_SQRT2 ( 1.41421356237309504880 ) /* sqrt(2) */ #define IPP_SQRT3 ( 1.73205080756887729353 ) /* sqrt(3) */ #define IPP_LN2 ( 0.69314718055994530942 ) /* ln(2) */ #define IPP_LN3 ( 1.09861228866810969139 ) /* ln(3) */ #define IPP_E ( 2.71828182845904523536 ) /* e */ #define IPP_RE ( 0.36787944117144232159 ) /* 1/e */ #define IPP_EPS23 ( 1.19209289e-07f ) #define IPP_EPS52 ( 2.2204460492503131e-016 ) #define IPP_MAX_8U ( 0xFF ) #define IPP_MAX_16U ( 0xFFFF ) #define IPP_MAX_32U ( 0xFFFFFFFF ) #define IPP_MIN_8U ( 0 ) #define IPP_MIN_16U ( 0 ) #define IPP_MIN_32U ( 0 ) #define IPP_MIN_8S (-128 ) #define IPP_MAX_8S ( 127 ) #define IPP_MIN_16S (-32768 ) #define IPP_MAX_16S ( 32767 ) #define IPP_MIN_32S (-2147483647 - 1 ) #define IPP_MAX_32S ( 2147483647 ) #define IPP_MIN_64U ( 0 ) #if defined( _WIN32 ) || defined ( _WIN64 ) #define IPP_MAX_64S ( 9223372036854775807i64 ) #define IPP_MIN_64S (-9223372036854775807i64 - 1 ) #define IPP_MAX_64U ( 0xffffffffffffffffL ) /* 18446744073709551615 */ #else #define IPP_MAX_64S ( 9223372036854775807LL ) #define IPP_MIN_64S (-9223372036854775807LL - 1 ) #define IPP_MAX_64U ( 0xffffffffffffffffLL ) /* 18446744073709551615 */ #endif #define IPP_MINABS_32F ( 1.175494351e-38f ) #define IPP_MAXABS_32F ( 3.402823466e+38f ) #define IPP_EPS_32F ( 1.192092890e-07f ) #define IPP_MINABS_64F ( 2.2250738585072014e-308 ) #define IPP_MAXABS_64F ( 1.7976931348623158e+308 ) #define IPP_EPS_64F ( 2.2204460492503131e-016 ) #define IPP_MAX( a, b ) ( ((a) > (b)) ? (a) : (b) ) #define IPP_MIN( a, b ) ( ((a) < (b)) ? (a) : (b) ) #define IPP_ABS( a ) ( ((a) < 0) ? (-(a)) : (a) ) /* IppLibraryVersion is deprecated, please use CryptoLibraryVersion instead */ typedef struct { int major; /* e.g. 1 */ int minor; /* e.g. 2 */ int majorBuild; /* e.g. 3 */ unsigned int revision; /* e.g. 0xf6f5e5bc */ char targetCpu[4]; /* corresponding to Intel® processor */ const char* Name; /* e.g. "ippsw7" */ const char* Version; /* e.g. "v1.2 Beta" */ const char* BuildDate; /* e.g. "Jul 20 99" */ } IppLibraryVersion; typedef struct { int major; /* e.g. 1 */ int minor; /* e.g. 2 */ int patch; /* e.g. 3 */ char targetCpu[4]; /* corresponding to Intel® processor */ const char* name; /* e.g. "ippsw7" */ const char* buildDate; /* e.g. "Jul 20 99" */ const char* strVersion; /* e.g. "v1.2 Beta" */ } CryptoLibraryVersion; typedef unsigned char Ipp8u; typedef unsigned short Ipp16u; typedef unsigned int Ipp32u; typedef signed char Ipp8s; typedef signed short Ipp16s; typedef signed int Ipp32s; typedef float Ipp32f; typedef IPP_INT64 Ipp64s; typedef IPP_UINT64 Ipp64u; typedef double Ipp64f; #if (COMPILER_SUPPORT_SHORT_FLOAT == _FLOAT_16) typedef _Float16 Ipp16f; #endif #if (COMPILER_SUPPORT_SHORT_FLOAT == _SHORT_FLOAT) typedef short float Ipp16f; #endif #if (COMPILER_SUPPORT_SHORT_FLOAT == _NO_FLOAT_16) typedef Ipp16s Ipp16f; #endif typedef struct { Ipp8s re; Ipp8s im; } Ipp8sc; typedef struct { Ipp16s re; Ipp16s im; } Ipp16sc; typedef struct { Ipp16u re; Ipp16u im; } Ipp16uc; typedef struct { Ipp32s re; Ipp32s im; } Ipp32sc; typedef struct { Ipp32f re; Ipp32f im; } Ipp32fc; typedef struct { Ipp64s re; Ipp64s im; } Ipp64sc; typedef struct { Ipp64f re; Ipp64f im; } Ipp64fc; typedef struct { Ipp16f re; Ipp16f im; } Ipp16fc; typedef enum { ippUndef = -1, ipp1u = 0, ipp8u = 1, ipp8uc = 2, ipp8s = 3, ipp8sc = 4, ipp16u = 5, ipp16uc = 6, ipp16s = 7, ipp16sc = 8, ipp32u = 9, ipp32uc = 10, ipp32s = 11, ipp32sc = 12, ipp32f = 13, ipp32fc = 14, ipp64u = 15, ipp64uc = 16, ipp64s = 17, ipp64sc = 18, ipp64f = 19, ipp64fc = 20, ipp16fc = 21 /* This is necessary for TS */ } IppDataType; typedef enum { ippFalse = 0, ippTrue = 1 } IppBool; #ifdef __cplusplus } #endif #endif /* IPPBASE_H__ */ #ifndef IPP_CPU_FEATURES__ #define IPP_CPU_FEATURES__ #define ippCPUID_MMX 0x00000001 /* Intel® architecture with MMX(TM) technology supported */ #define ippCPUID_SSE 0x00000002 /* Intel® Streaming SIMD Extensions (Intel® SSE) instruction set */ #define ippCPUID_SSE2 0x00000004 /* Intel® Streaming SIMD Extensions 2 (Intel® SSE2) instruction set */ #define ippCPUID_SSE3 0x00000008 /* Intel® Streaming SIMD Extensions 3 (Intel® SSE3) instruction set */ #define ippCPUID_SSSE3 0x00000010 /* Supplemental Streaming SIMD Extensions 3 (SSSE3) instruction set */ #define ippCPUID_MOVBE 0x00000020 /* Intel® instruction MOVBE */ #define ippCPUID_SSE41 0x00000040 /* Intel® Streaming SIMD Extensions 4.1 (Intel® SSE4.1) instruction set */ #define ippCPUID_SSE42 0x00000080 /* Intel® Streaming SIMD Extensions 4.2 (Intel® SSE4.2) instruction set */ #define ippCPUID_AVX 0x00000100 /* Intel® Advanced Vector Extensions instruction set */ #define ippAVX_ENABLEDBYOS 0x00000200 /* Intel® Advanced Vector Extensions instruction set is supported by OS */ #define ippCPUID_AES 0x00000400 /* */ #define ippCPUID_CLMUL 0x00000800 /* Intel® instruction PCLMULQDQ */ #define ippCPUID_ABR 0x00001000 /* Reserved */ #define ippCPUID_RDRAND 0x00002000 /* Intel® instruction RDRAND */ #define ippCPUID_F16C 0x00004000 /* Intel® instruction F16C */ #define ippCPUID_AVX2 0x00008000 /* Intel® Advanced Vector Extensions 2 */ #define ippCPUID_ADCOX 0x00010000 /* Intel® instructions ADOX/ADCX */ #define ippCPUID_RDSEED 0x00020000 /* Intel® instruction RDSEED */ #define ippCPUID_PREFETCHW 0x00040000 /* Intel® instruction PREFETCHW */ #define ippCPUID_SHA 0x00080000 /* Intel® Secure Hash Algorithm Extensions */ #define ippCPUID_AVX512F 0x00100000 /* Intel® Advanced Vector Extensions 512 Foundation instruction set */ #define ippCPUID_AVX512CD 0x00200000 /* Intel® Advanced Vector Extensions 512 CD instruction set */ #define ippCPUID_AVX512ER 0x00400000 /* Intel® Advanced Vector Extensions 512 ER instruction set */ #define ippCPUID_AVX512PF 0x00800000 /* Intel® Advanced Vector Extensions 512 PF instruction set */ #define ippCPUID_AVX512BW 0x01000000 /* Intel® Advanced Vector Extensions 512 BW instruction set */ #define ippCPUID_AVX512DQ 0x02000000 /* Intel® Advanced Vector Extensions 512 DQ instruction set */ #define ippCPUID_AVX512VL 0x04000000 /* Intel® Advanced Vector Extensions 512 VL instruction set */ #define ippCPUID_AVX512VBMI 0x08000000 /* Intel® Advanced Vector Extensions 512 Bit Manipulation instructions */ #define ippCPUID_MPX 0x10000000 /* Intel® Memory Protection Extensions */ #define ippCPUID_AVX512_4FMADDPS 0x20000000 /* Intel® Advanced Vector Extensions 512 DL floating-point single precision */ #define ippCPUID_AVX512_4VNNIW 0x40000000 /* Intel® Advanced Vector Extensions 512 DL enhanced word variable precision */ #define ippCPUID_KNC 0x80000000 /* Intel® Xeon Phi(TM) coprocessor */ #if defined( _WIN32 ) || defined ( _WIN64 ) #define INT64_SUFFIX(name) name##L #else #define INT64_SUFFIX(name) name##LL #endif #define ippCPUID_AVX512IFMA INT64_SUFFIX(0x100000000) /* Intel® Advanced Vector Extensions 512 IFMA (PMADD52) instruction set */ #define ippCPUID_NOCHECK INT64_SUFFIX(0x8000000000000000) /* Force ippSetCpuFeatures to set CPU features without check */ #define ippCPUID_GETINFO_A INT64_SUFFIX(0x616f666e69746567) /* Force ippGetCpuFeatures to work as cpuid instruction */ #define ippAVX512_ENABLEDBYOS INT64_SUFFIX(0x200000000) /* Intel® Advanced Vector Extensions 512 is supported by OS */ #define ippCPUID_AVX512GFNI INT64_SUFFIX(0x400000000) /* */ #define ippCPUID_AVX512VAES INT64_SUFFIX(0x800000000) /* */ #define ippCPUID_AVX512VCLMUL INT64_SUFFIX(0x1000000000) /* */ #define ippCPUID_AVX512VBMI2 INT64_SUFFIX(0x2000000000) /* Intel® Advanced Vector Extensions 512 Bit Manipulation instructions 2 */ #define ippCPUID_AVX512_FP16 INT64_SUFFIX(0x1000000000) /* Intel(R) Advanced Vector Extensions 512 16-bit floating point (FP16) instruction set */ #define ippCPUID_AVX2VAES INT64_SUFFIX(0x4000000000) /* Intel® Advanced Vector Extensions 256 Bit Vector AES instructions */ #define ippCPUID_AVX2VCLMUL INT64_SUFFIX(0x8000000000) /* Intel® instruction VPCLMULQDQ */ #define ippCPUID_AVX2SM3 INT64_SUFFIX(0x10000000000) /* Intel® Advanced Vector Extensions 256 Bit SM3_NI instructions */ #define ippCPUID_AVX2SM4 INT64_SUFFIX(0x20000000000) /* Intel® Advanced Vector Extensions 256 Bit SM4_NI instructions */ #define ippCPUID_AVX2SHA512 INT64_SUFFIX(0x40000000000) /* Intel® Advanced Vector Extensions 256 Bit SHA512_NI instructions */ #endif /* IPP_CPU_FEATURES__ */ /* Macros are necessary to build custom Intel® Cryptography Primitives Library static 1cpu library (enable specific features at compile-time) */ #if (!defined(_MERGED_BLD) && defined(IPPCP_CUSTOM_BUILD)) #ifndef IPP_CUSTOM_CPU_FEATURES__ #define IPP_CUSTOM_CPU_FEATURES__ #ifndef IPPCP_AES_ON #define IPPCP_AES_ON (0) #endif #ifndef IPPCP_CLMUL_ON #define IPPCP_CLMUL_ON (0) #endif #ifndef IPPCP_VAES_ON #define IPPCP_VAES_ON (0) #endif #ifndef IPPCP_VCLMUL_ON #define IPPCP_VCLMUL_ON (0) #endif #define IPP_CUSTOM_ENABLED_FEATURES (ippCPUID_AES*IPPCP_AES_ON | ippCPUID_CLMUL*IPPCP_CLMUL_ON | ippCPUID_AVX512VAES*IPPCP_VAES_ON | ippCPUID_AVX512VCLMUL*IPPCP_VCLMUL_ON \ | ippCPUID_AVX2VAES*IPPCP_VAES_ON | ippCPUID_AVX2VCLMUL*IPPCP_VCLMUL_ON) #endif /* IPP_CUSTOM_CPU_FEATURES__ */ #endif /* !defined(_MERGED_BLD) && defined(IPPCP_CUSTOM_BUILD) */ #ifndef IPPSTATUS_H__ #define IPPSTATUS_H__ #ifdef __cplusplus extern "C" { #endif typedef signed int IppStatus; #define ippStsCpuNotSupportedErr -9999 /* The target CPU is not supported. */ #define ippStsUnknownStatusCodeErr -216 /* Unknown status code. */ #define ippStsLoadDynErr -221 /* Error when loading the dynamic library. */ #define ippStsLengthErr -15 /* Incorrect value for string length. */ #define ippStsNotSupportedModeErr -14 /* The requested mode is currently not supported. */ #define ippStsContextMatchErr -13 /* Context parameter does not match the operation. */ #define ippStsScaleRangeErr -12 /* Scale bounds are out of range. */ #define ippStsOutOfRangeErr -11 /* Argument is out of range, or point is outside the image. */ #define ippStsDivByZeroErr -10 /* An attempt to divide by zero. */ #define ippStsMemAllocErr -9 /* Memory allocated for the operation is not enough. */ #define ippStsNullPtrErr -8 /* Null pointer error. */ #define ippStsRangeErr -7 /* Incorrect values for bounds: the lower bound is greater than the upper bound. */ #define ippStsSizeErr -6 /* Incorrect value for data size. */ #define ippStsBadArgErr -5 /* Incorrect arg/param of the function. */ #define ippStsNoMemErr -4 /* Not enough memory for the operation. */ #define ippStsErr -2 /* Unknown/unspecified error */ /* no errors */ #define ippStsNoErr 0 /* No errors. */ /* warnings */ #define ippStsNoOperation 1 /* No operation has been executed. */ #define ippStsDivByZero 2 /* Zero value(s) for the divisor in the Div function. */ #define ippStsWaterfall 43 /* Cannot load required library, waterfall is used. */ #define ippStsFeaturesCombination 51 /* Wrong combination of features. */ #ifdef __cplusplus } #endif #endif /* IPPSTATUS_H__ */ #define ippStsInvalidPoint -1017 /* ippStsInvalidPoint ECC: Invalid point (out of EC).*/ #define ippStsQuadraticNonResidueErr -1016 /* SQRT operation on quadratic non-residue value. */ #define ippStsPointAtInfinity -1015 /* Point at infinity is detected. */ #define ippStsOFBSizeErr -1014 /* Incorrect value for cryptography OFB block size. */ #define ippStsIncompleteContextErr -1013 /* Set up of context is not complete. */ #define ippStsCTRSizeErr -1012 /* Incorrect value for cryptography CTR block size. */ #define ippStsEphemeralKeyErr -1011 /* ECC: Invalid ephemeral key. */ #define ippStsMessageErr -1010 /* ECC: Invalid message digest. */ #define ippStsShareKeyErr -1009 /* ECC: Invalid share key. */ #define ippStsInvalidPrivateKey -1008 /* ECC: Invalid private key. */ #define ippStsOutOfECErr -1007 /* ECC: Point out of EC. */ #define ippStsECCInvalidFlagErr -1006 /* ECC: Invalid Flag. */ #define ippStsUnderRunErr -1005 /* Error in data under run. */ #define ippStsPaddingErr -1004 /* Detected padding error indicates the possible data corruption. */ #define ippStsCFBSizeErr -1003 /* Incorrect value for cryptography CFB block size. */ #define ippStsPaddingSchemeErr -1002 /* Invalid padding scheme. */ #define ippStsBadModulusErr -1001 /* Bad modulus caused a failure in module inversion. */ #define ippStsInsufficientEntropy 25 /* Generation of the prime/key failed due to insufficient entropy in the random seed and stimulus bit string. */ #define ippStsNotSupportedCpu 36 /* The CPU is not supported. */ #define ippStsMbWarning 53 /* Error(s) in statuses array. */ #if (!defined IPPCPDEFS_H__) || defined( _OWN_BLDPCS ) #define IPPCPDEFS_H__ #ifdef __cplusplus extern "C" { #endif #if !defined( _OWN_BLDPCS ) typedef Ipp32u IppAlgId; /* // ========================================================= // Symmetric Ciphers // ========================================================= */ typedef enum { ippPaddingNONE = 0, /*NONE = 0,*/ IppsCPPaddingNONE = 0, ippPaddingPKCS7 = 1, /*PKCS7 = 1,*/ IppsCPPaddingPKCS7 = 1, ippPaddingZEROS = 2, /*ZEROS = 2,*/ IppsCPPaddingZEROS = 2 } IppsPadding, IppsCPPadding; typedef struct _cpDES IppsDESSpec; typedef struct _cpRijndael128 IppsAESSpec; typedef struct _cpRijndael128 IppsRijndael128Spec; typedef struct _cpSMS4 IppsSMS4Spec; /* TDES */ #define DES_BLOCKSIZE (64) /* cipher blocksize (bits) */ #define TDES_BLOCKSIZE DES_BLOCKSIZE #define DES_KEYSIZE (64) /* cipher keysize (bits) */ #define TDES_KEYSIZE DES_KEYSIZE /* AES */ #define IPP_AES_BLOCK_BITSIZE (128) /* cipher blocksizes (bits) */ /* Rijndael */ typedef enum { ippRijndaelKey128 = 128, IppsRijndaelKey128 = 128, /* 128-bit key */ ippRijndaelKey192 = 192, IppsRijndaelKey192 = 192, /* 192-bit key */ ippRijndaelKey256 = 256, IppsRijndaelKey256 = 256 /* 256-bit key */ } IppsRijndaelKeyLength; /* AES-CCM (authentication & confidence) */ typedef struct _cpAES_CCM IppsAES_CCMState; /* AES-GCM (authentication & confidence) */ typedef struct _cpAES_GCM IppsAES_GCMState; /* AES-XTS (confidence) */ typedef struct _cpAES_XTS IppsAES_XTSSpec; /* SMS4-CCM (authentication & confidence) */ typedef struct _cpSMS4_CCM IppsSMS4_CCMState; /* // ========================================================= // ARCFOUR Stream Cipher // ========================================================= */ typedef struct _cpARCfour IppsARCFourState; #define IPP_ARCFOUR_KEYMAX_SIZE (256) /* max key length (bytes) */ #define MAX_ARCFOUR_KEY_LEN IPP_ARCFOUR_KEYMAX_SIZE /* obsolete */ /* // ========================================================= // One-Way Hash Functions // ========================================================= */ typedef enum { ippHashAlg_Unknown, ippHashAlg_SHA1, ippHashAlg_SHA256, ippHashAlg_SHA224, ippHashAlg_SHA512, ippHashAlg_SHA384, ippHashAlg_MD5, ippHashAlg_SM3, ippHashAlg_SHA512_224, ippHashAlg_SHA512_256, ippHashAlg_MaxNo } IppHashAlgId; #define IPP_ALG_HASH_UNKNOWN (ippHashAlg_Unknown) /* unknown */ #define IPP_ALG_HASH_SHA1 (ippHashAlg_SHA1) /* SHA1 */ #define IPP_ALG_HASH_SHA256 (ippHashAlg_SHA256) /* SHA256 */ #define IPP_ALG_HASH_SHA224 (ippHashAlg_SHA224) /* SHA224 or SHA256/224 */ #define IPP_ALG_HASH_SHA512 (ippHashAlg_SHA512) /* SHA512 */ #define IPP_ALG_HASH_SHA384 (ippHashAlg_SHA384) /* SHA384 or SHA512/384 */ #define IPP_ALG_HASH_MD5 (ippHashAlg_MD5) /* MD5 */ #define IPP_ALG_HASH_SM3 (ippHashAlg_SM3) /* SM3 */ #define IPP_ALG_HASH_SHA512_224 (ippHashAlg_SHA512_224) /* SHA512/224 */ #define IPP_ALG_HASH_SHA512_256 (ippHashAlg_SHA512_256) /* SHA512/256 */ #define IPP_ALG_HASH_LIMIT (ippHashAlg_MaxNo) /* hash alg limiter*/ typedef struct _cpSHA1 IppsSHA1State; typedef struct _cpSHA256 IppsSHA256State; typedef struct _cpSHA256 IppsSHA224State; typedef struct _cpSHA512 IppsSHA512State; typedef struct _cpSHA512 IppsSHA384State; typedef struct _cpMD5 IppsMD5State; typedef struct _cpSM3 IppsSM3State; typedef struct _cpHashCtx IppsHashState; typedef struct _cpHashMethod_rmf IppsHashMethod; typedef struct _cpHashCtx_rmf IppsHashState_rmf; #define IPP_SHA1_DIGEST_BITSIZE 160 /* digest size (bits) */ #define IPP_SHA256_DIGEST_BITSIZE 256 #define IPP_SHA224_DIGEST_BITSIZE 224 #define IPP_SHA384_DIGEST_BITSIZE 384 #define IPP_SHA512_DIGEST_BITSIZE 512 #define IPP_MD5_DIGEST_BITSIZE 128 #define IPP_SM3_DIGEST_BITSIZE 256 #define IPP_SHA512_224_DIGEST_BITSIZE 224 #define IPP_SHA512_256_DIGEST_BITSIZE 256 /* // ========================================================= // Keyed-Hash Message Authentication Codes // ========================================================= */ typedef struct _cpHMAC IppsHMACState; typedef struct _cpHMAC IppsHMACSHA1State; typedef struct _cpHMAC IppsHMACSHA256State; typedef struct _cpHMAC IppsHMACSHA224State; typedef struct _cpHMAC IppsHMACSHA384State; typedef struct _cpHMAC IppsHMACSHA512State; typedef struct _cpHMAC IppsHMACMD5State; typedef struct _cpHMAC_rmf IppsHMACState_rmf; /* // ========================================================= // Data Authentication Codes // ========================================================= */ typedef struct _cpAES_CMAC IppsAES_CMACState; /* // ========================================================= // Big Number Integer Arithmetic // ========================================================= */ #define BN_MAXBITSIZE (16*1024) /* bn max size (bits) */ typedef enum { ippBigNumNEG = 0, IppsBigNumNEG = 0, ippBigNumPOS = 1, IppsBigNumPOS = 1 } IppsBigNumSGN; typedef enum { ippBinaryMethod = 0, IppsBinaryMethod = 0, ippSlidingWindows = 1, IppsSlidingWindows = 1 } IppsExpMethod; typedef struct _cpBigNum IppsBigNumState; typedef struct _cpMontgomery IppsMontState; typedef struct _cpPRNG IppsPRNGState; typedef struct _cpPrime IppsPrimeState; /* External Bit Supplier */ typedef IppStatus (IPP_CALL *IppBitSupplier)(Ipp32u* pRand, int nBits, void* pEbsParams); #define IPP_IS_EQ (0) #define IPP_IS_GT (1) #define IPP_IS_LT (2) #define IPP_IS_NE (3) #define IPP_IS_NA (4) #define IPP_IS_PRIME (5) #define IPP_IS_COMPOSITE (6) #define IPP_IS_VALID (7) #define IPP_IS_INVALID (8) #define IPP_IS_INCOMPLETE (9) #define IPP_IS_ATINFINITY (10) #define IS_ZERO IPP_IS_EQ #define GREATER_THAN_ZERO IPP_IS_GT #define LESS_THAN_ZERO IPP_IS_LT #define IS_PRIME IPP_IS_PRIME #define IS_COMPOSITE IPP_IS_COMPOSITE #define IS_VALID_KEY IPP_IS_VALID #define IS_INVALID_KEY IPP_IS_INVALID #define IS_INCOMPLETED_KEY IPP_IS_INCOMPLETE /* // ========================================================= // RSA Cryptography // ========================================================= */ #define MIN_RSA_SIZE (8) #define MAX_RSA_SIZE (16*1024) typedef struct _cpRSA IppsRSAState; /* key types */ typedef enum { ippRSApublic = 0x20000000, IppRSApublic = 0x20000000, ippRSAprivate = 0x40000000, IppRSAprivate = 0x40000000 } IppRSAKeyType; /* key component's tag */ typedef enum { ippRSAkeyN = 0x01, IppRSAkeyN = 0x01, ippRSAkeyE = 0x02, IppRSAkeyE = 0x02, ippRSAkeyD = 0x04, IppRSAkeyD = 0x04, ippRSAkeyP = 0x08, IppRSAkeyP = 0x08, ippRSAkeyQ = 0x10, IppRSAkeyQ = 0x10, ippRSAkeyDp = 0x20, IppRSAkeyDp = 0x20, ippRSAkeyDq = 0x40, IppRSAkeyDq = 0x40, ippRSAkeyQinv = 0x80, IppRSAkeyQinv = 0x80 } IppRSAKeyTag; typedef struct _cpRSA_public_key IppsRSAPublicKeyState; typedef struct _cpRSA_private_key IppsRSAPrivateKeyState; /* // ========================================================= // DL Cryptography // ========================================================= */ #define MIN_DLP_BITSIZE (512) #define MIN_DLP_BITSIZER (160) #define MIN_DLPDH_BITSIZE (512) #define MIN_DLPDH_BITSIZER (160) #define DEF_DLPDH_BITSIZER (160) #define MIN_DLPDSA_BITSIZE (512) #define MAX_DLPDSA_BITSIZE (1024) #define MIN_DLPDSA_BITSIZER (160) #define DEF_DLPDSA_BITSIZER (160) #define MAX_DLPDSA_BITSIZER (160) #define MIN_DLPDSA_SEEDSIZE (160) typedef struct _cpDLP IppsDLPState; /* domain parameter tags */ typedef enum { ippDLPkeyP = 0x01, IppDLPkeyP = 0x01, ippDLPkeyR = 0x02, IppDLPkeyR = 0x02, ippDLPkeyG = 0x04, IppDLPkeyG = 0x04 } IppDLPKeyTag; typedef enum { ippDLValid, /* validation pass successfully */ ippDLBaseIsEven, /* !(P is odd) */ ippDLOrderIsEven, /* !(R is odd) */ ippDLInvalidBaseRange, /* !(2^(L-1) < P < 2^L) */ ippDLInvalidOrderRange, /* !(2^(M-1) < R < 2^M) */ ippDLCompositeBase, ippDLCompositeOrder, ippDLInvalidCofactor, /* !( R|(P-1) ) */ ippDLInvalidGenerator, /* !( G^R == 1 (mod P) ) */ /* !(1 < G < (P-1)) */ ippDLInvalidPrivateKey, /* !(1 < private < (R-1)) */ ippDLInvalidPublicKey, /* !(1 < public <=(P-1)) */ ippDLInvalidKeyPair, /* !(G^private == public */ ippDLInvalidSignature /* invalid signature */ } IppDLResult; /* // ========================================================= // EC Cryptography // ========================================================= */ #define EC_GFP_MAXBITSIZE (1024) /* operation result */ typedef enum { ippECValid, /* validation pass successfully */ ippECCompositeBase, /* field based on composite */ ippECComplicatedBase, /* number of non-zero terms in the polynomial (> PRIME_ARR_MAX) */ ippECIsZeroDiscriminant,/* zero discriminant */ ippECCompositeOrder, /* composite order of base point */ ippECInvalidOrder, /* invalid base point order */ ippECIsWeakMOV, /* weak Meneze-Okamoto-Vanstone reduction attack */ ippECIsWeakSSSA, /* weak Semaev-Smart,Satoh-Araki reduction attack */ ippECIsSupersingular, /* supersingular curve */ ippECInvalidPrivateKey, /* !(0 < Private < order) */ ippECInvalidPublicKey, /* (order*PublicKey != Infinity) */ ippECInvalidKeyPair, /* (Private*BasePoint != PublicKey) */ ippECPointOutOfGroup, /* out of group (order*P != Infinity) */ ippECPointIsAtInfinite, /* point (P=(Px,Py)) at Infinity */ ippECPointIsNotValid, /* point (P=(Px,Py)) out-of EC */ ippECPointIsEqual, /* compared points are equal */ ippECPointIsNotEqual, /* compared points are different */ ippECInvalidSignature /* invalid signature */ } IppECResult; /* domain parameter set/get flags */ typedef enum { ippECarbitrary =0x00000, IppECCArbitrary = 0x00000, /* arbitrary ECC */ ippECPstd = 0x10000, IppECCPStd = 0x10000, /* random (recommended) EC over FG(p): */ ippECPstd112r1 = ippECPstd, IppECCPStd112r1 = IppECCPStd, /* secp112r1 curve */ ippECPstd112r2 = ippECPstd+1, IppECCPStd112r2 = IppECCPStd+1, /* secp112r2 curve */ ippECPstd128r1 = ippECPstd+2, IppECCPStd128r1 = IppECCPStd+2, /* secp128r1 curve */ ippECPstd128r2 = ippECPstd+3, IppECCPStd128r2 = IppECCPStd+3, /* secp128r2 curve */ ippECPstd160r1 = ippECPstd+4, IppECCPStd160r1 = IppECCPStd+4, /* secp160r1 curve */ ippECPstd160r2 = ippECPstd+5, IppECCPStd160r2 = IppECCPStd+5, /* secp160r2 curve */ ippECPstd192r1 = ippECPstd+6, IppECCPStd192r1 = IppECCPStd+6, /* secp192r1 curve */ ippECPstd224r1 = ippECPstd+7, IppECCPStd224r1 = IppECCPStd+7, /* secp224r1 curve */ ippECPstd256r1 = ippECPstd+8, IppECCPStd256r1 = IppECCPStd+8, /* secp256r1 curve */ ippECPstd384r1 = ippECPstd+9, IppECCPStd384r1 = IppECCPStd+9, /* secp384r1 curve */ ippECPstd521r1 = ippECPstd+10, IppECCPStd521r1 = IppECCPStd+10, /* secp521r1 curve */ ippECPstdSM2 = ippECPstd+11, IppECCPStdSM2 = IppECCPStd+11, /* TMP SM2 curve */ ippEC_TPM_SM2_P256= ippECPstd+11, ippEC_TPM_BN_P256 = ippECPstd+12, /* TPM BN_P256 curve */ /* curves over binary finit fields are not supported in Intel® IPP 9.0 */ IppECCBStd = 0x20000, /* random (recommended) EC over FG(2^m): */ IppECCBStd113r1 = IppECCBStd, /* sect113r1 curve */ IppECCBStd113r2 = IppECCBStd+1, /* sect113r2 curve */ IppECCBStd131r1 = IppECCBStd+2, /* sect131r1 curve */ IppECCBStd131r2 = IppECCBStd+3, /* sect131r2 curve */ IppECCBStd163r1 = IppECCBStd+4, /* sect163r1 curve */ IppECCBStd163r2 = IppECCBStd+5, /* sect163r2 curve */ IppECCBStd193r1 = IppECCBStd+6, /* sect193r1 curve */ IppECCBStd193r2 = IppECCBStd+7, /* sect193r2 curve */ IppECCBStd233r1 = IppECCBStd+8, /* sect233r1 curve */ IppECCBStd283r1 = IppECCBStd+9, /* sect283r1 curve */ IppECCBStd409r1 = IppECCBStd+10, /* sect409r1 curve */ IppECCBStd571r1 = IppECCBStd+11, /* sect571r1 curve */ IppECCKStd = 0x40000, /* Koblitz (recommended) EC over FG(2^m): */ IppECCBStd163k1 = IppECCKStd, /* Koblitz 163 curve */ IppECCBStd233k1 = IppECCKStd+1, /* Koblitz 233 curve */ IppECCBStd239k1 = IppECCKStd+2, /* Koblitz 239 curve */ IppECCBStd283k1 = IppECCKStd+3, /* Koblitz 283 curve */ IppECCBStd409k1 = IppECCKStd+4, /* Koblitz 409 curve */ IppECCBStd571k1 = IppECCKStd+5 /* Koblitz 571 curve */ } IppsECType, IppECCType; /* // GF over prime and its extension */ #define IPP_MIN_GF_CHAR (3) /* min characteristic of GF */ #define IPP_MIN_GF_BITSIZE (2) /* min bitsize of element over prime GF */ #define IPP_MAX_GF_BITSIZE (1024) /* max bitsize of element over prime GF */ #define IPP_MIN_GF_EXTDEG (2) /* min GF extension degree */ #define IPP_MAX_GF_EXTDEG (8) /* max GF extension degree */ #define IPP_MAX_EXPONENT_NUM (6) /* max number of exponents, equals to LOG_CACHE_LINE_SIZE */ typedef struct _cpGFpMethod IppsGFpMethod; typedef struct _cpGFp IppsGFpState; typedef struct _cpGFpElement IppsGFpElement; typedef struct _cpGFpEC IppsGFpECState; typedef struct _cpGFpECPoint IppsGFpECPoint; typedef struct _cpGFpEC IppsECCPState; typedef struct _cpGFpECPoint IppsECCPPointState; typedef struct { int hashSize; int msgBlockSize; } IppsHashInfo; typedef struct { //const IppsGFpState* pBasicGF; //const IppsGFpState* pGroundGF; int parentGFdegree; int basicGFdegree; int basicElmBitSize; } IppsGFpInfo; /* SM3 Digest Bytes Size */ #define IPP_SM3_DIGEST_BYTESIZE ((IPP_SM3_DIGEST_BITSIZE + 7) / 8) typedef struct _cpStateECES_SM2 IppsECESState_SM2; typedef enum { ippKESM2Requester = 0xF, /* corresponds to A user/participant */ ippKESM2Responder /* corresponds to B user/participant */ } IppsKeyExchangeRoleSM2; typedef struct _GFpECKeyExchangeSM2 IppsGFpECKeyExchangeSM2State; #endif /* !defined( _OWN_BLDPCS ) */ IPPAPI( IppStatus, ippcpGetCpuFeatures, ( Ipp64u* pFeaturesMask )) IPPAPI( IppStatus, ippcpSetCpuFeatures, ( Ipp64u features )) IPPAPI( Ipp64u, ippcpGetEnabledCpuFeatures, ( void ) ) IPPAPI( IppStatus, ippcpInit,( void )) IPPAPI( const char*, ippcpGetStatusString, ( IppStatus StsCode )) IPPAPI( Ipp64u, ippcpGetCpuClocks, (void) ) /* Threading functions are deprecated in the library */ IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI( IppStatus, ippcpSetNumThreads, ( int numThr )) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI( IppStatus, ippcpGetNumThreads, (int* pNumThr) ) IPP_DEPRECATED(OBSOLETE_API) \ IPPAPI( int, ippcpGetEnabledNumThreads, ( void ) ) /* Defines related to experimental features enabling */ #ifdef IPPCP_PREVIEW_ALL #ifndef IPPCP_PREVIEW_XMSS #define IPPCP_PREVIEW_XMSS (1) #endif #ifndef IPPCP_PREVIEW_LMS #define IPPCP_PREVIEW_LMS (1) #endif #endif /* // ========================================================= // XMSS Algo // ========================================================= */ #ifdef IPPCP_PREVIEW_XMSS typedef enum { reserved = 0, XMSS_SHA2_10_256 = 1, XMSS_SHA2_16_256 = 2, XMSS_SHA2_20_256 = 3, XMSS_SHA2_10_512 = 4, XMSS_SHA2_16_512 = 5, XMSS_SHA2_20_512 = 6 } IppsXMSSAlgo; typedef struct _cpXMSSSignatureState IppsXMSSSignatureState; typedef struct _cpXMSSPublicKeyState IppsXMSSPublicKeyState; #endif // IPPCP_PREVIEW_XMSS /* // ========================================================= // LMS Algo // ========================================================= */ #ifdef IPPCP_PREVIEW_LMS /* Parameters set is based on two articles: * RFC8554 (https://datatracker.ietf.org/doc/html/rfc8554) * https://datatracker.ietf.org/doc/html/draft-fluhrer-lms-more-parm-sets-00 */ typedef enum { LMOTS_SHA256_N32_W1 = 1, LMOTS_SHA256_N32_W2 = 2, LMOTS_SHA256_N32_W4 = 3, LMOTS_SHA256_N32_W8 = 4, LMOTS_SHA256_N24_W1 = 5, LMOTS_SHA256_N24_W2 = 6, LMOTS_SHA256_N24_W4 = 7, LMOTS_SHA256_N24_W8 = 8 } IppsLMOTSAlgo; typedef enum { LMS_SHA256_M32_H5 = 5, LMS_SHA256_M32_H10 = 6, LMS_SHA256_M32_H15 = 7, LMS_SHA256_M32_H20 = 8, LMS_SHA256_M32_H25 = 9, LMS_SHA256_M24_H5 = 10, LMS_SHA256_M24_H10 = 11, LMS_SHA256_M24_H15 = 12, LMS_SHA256_M24_H20 = 13, LMS_SHA256_M24_H25 = 14 } IppsLMSAlgo; typedef struct { IppsLMOTSAlgo lmotsOIDAlgo; IppsLMSAlgo lmsOIDAlgo; } IppsLMSAlgoType; typedef struct _cpLMSSignatureState IppsLMSSignatureState; typedef struct _cpLMSPublicKeyState IppsLMSPublicKeyState; #endif // IPPCP_PREVIEW_LMS #ifdef __cplusplus } #endif #endif /* !defined IPPCPDEFS_H__ || defined( _OWN_BLDPCS ) */ cryptography-primitives-1.0.0/include/ippcpversion.h000077500000000000000000000027641470420105600227640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ /* // // Intel® Cryptography Primitives Library // // Purpose: Describes the Intel® Cryptography Primitives Library version // */ #if !defined( CRYPTOLIBVERSION_H__ ) #define CRYPTOLIBVERSION_H__ #define CRYPTO_LIB_VERSION_MAJOR 1 #define CRYPTO_LIB_VERSION_MINOR 0 #define CRYPTO_LIB_VERSION_PATCH 0 // Major interface version #define CRYPTO_LIB_INTERFACE_VERSION_MAJOR 12 // Minor interface version #define CRYPTO_LIB_INTERFACE_VERSION_MINOR 0 #define CRYPTO_LIB_VERSION_STR STR(CRYPTO_LIB_VERSION_MAJOR) "." STR(CRYPTO_LIB_VERSION_MINOR) "." STR(CRYPTO_LIB_VERSION_PATCH) \ " (" STR(CRYPTO_LIB_INTERFACE_VERSION_MAJOR) "." STR(CRYPTO_LIB_INTERFACE_VERSION_MINOR) ")" #endif /* CRYPTOLIBVERSION_H__ */ cryptography-primitives-1.0.0/include/ippversion.h000066400000000000000000000031661470420105600224330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2001 Intel Corporation * * 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. *************************************************************************/ /* // // Intel® Cryptography Primitives Library // // Purpose: Describes the Intel® Cryptography Primitives Library version // */ #if !defined( IPPVERSION_H__ ) #if !defined(_NO_IPP_DEPRECATED) #pragma message("Header `ippversion.h` is deprecated and will be removed in one of future Intel® Cryptography Primitives Library releases. Please use `ippcpversion.h` instead.") #endif /* !defined(_NO_IPP_DEPRECATED) */ #define IPPVERSION_H__ #define IPP_VERSION_MAJOR 1 #define IPP_VERSION_MINOR 0 #define IPP_VERSION_UPDATE 0 // Major interface version #define IPP_INTERFACE_VERSION_MAJOR 12 // Minor interface version #define IPP_INTERFACE_VERSION_MINOR 0 #define IPP_VERSION_STR STR(IPP_VERSION_MAJOR) "." STR(IPP_VERSION_MINOR) "." STR(IPP_VERSION_UPDATE) " (" STR(IPP_INTERFACE_VERSION_MAJOR) "." STR(IPP_INTERFACE_VERSION_MINOR) " )" #endif /* IPPVERSION_H__ */ cryptography-primitives-1.0.0/sources/000077500000000000000000000000001470420105600201165ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/cmake/000077500000000000000000000000001470420105600211765ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/cmake/CMakeASM_NASMOptions.txt000066400000000000000000000026711470420105600254600ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # if (UNIX) set(CMAKE_ASM_NASM_DEBUG_OPTIONS -g) if (APPLE) set(CMAKE_ASM_NASM_OBJECT_FORMAT macho64) else() if (${ARCH} MATCHES "ia32") set(CMAKE_ASM_NASM_OBJECT_FORMAT elf32) else() set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) endif() endif() else() # Windows if (${ARCH} MATCHES "ia32") set(CMAKE_ASM_NASM_OBJECT_FORMAT win32) # MS extended COFF for Win32 else() set(CMAKE_ASM_NASM_OBJECT_FORMAT win64) endif() endif() set(CMAKE_ASM_NASM_COMPILE_OBJECT " -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o ") set(CMAKE_ASM_NASM_FLAGS_INIT "${LIBRARY_DEFINES}") cryptography-primitives-1.0.0/sources/cmake/ippcp-config-version.cmake.in000066400000000000000000000024071470420105600266510ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # library detection routine (version compatibility rules). # set(PACKAGE_VERSION @IPPCP_INTERFACE_VERSION@) set(PACKAGE_VERSION_EXACT False) set(PACKAGE_VERSION_COMPATIBLE False) if(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT True) set(PACKAGE_VERSION_COMPATIBLE True) endif() if(PACKAGE_FIND_VERSION_MAJOR EQUAL @IPPCP_INTERFACE_VERSION_MAJOR@ AND PACKAGE_FIND_VERSION VERSION_LESS PACKAGE_VERSION) set(PACKAGE_VERSION_COMPATIBLE True) endif() cryptography-primitives-1.0.0/sources/cmake/ippcp-config.cmake.in000066400000000000000000000133111470420105600251620ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library detection routine. # # To use it, add the lines below to your CMakeLists.txt: # find_package(IPPCP REQUIRED) # target_link_libraries(mytarget ${IPPCP_LIBRARIES}) # # List of the variables defined in this file: # IPPCP_FOUND # IPPCP_LIBRARIES - list of all imported targets # # Configuration variables available: # IPPCP_SHARED - set this to True before find_package() to search for shared library. # IPPCP_ARCH - set this to 'ia32' or 'intel64' before find_package() to use library of particular arch # (this variable can be auto-defined) # # Initialize to default values if (NOT IPPCP_LIBRARIES) set(IPPCP_LIBRARIES "") endif() # Determine ARCH if not defined outside if (NOT DEFINED IPPCP_ARCH) set(IPPCP_ARCH "ia32") if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8) set(IPPCP_ARCH "intel64") endif() if(CMAKE_SIZEOF_VOID_P) set(IPPCP_ARCH "intel64") endif() endif() if (NOT IPPCP_FIND_COMPONENTS) set(IPPCP_FIND_COMPONENTS "ippcp") # crypto_mb library is only for intel64 if(${IPPCP_ARCH} MATCHES "intel64") set(IPPCP_BIN_REL_PATH @IPPCP_BIN64_REL_PATH@) set(IPPCP_LIB_REL_PATH @IPPCP_LIB64_REL_PATH@) set(IPPCP_FIND_COMPONENTS "${IPPCP_FIND_COMPONENTS}" "crypto_mb") else() set(IPPCP_BIN_REL_PATH @IPPCP_BIN32_REL_PATH@) set(IPPCP_LIB_REL_PATH @IPPCP_LIB32_REL_PATH@) endif() foreach (_component ${IPPCP_FIND_COMPONENTS}) set(IPPCP_FIND_REQUIRED_${_component} 1) endforeach() endif() if (WIN32) set(_ippcp_library_prefix "") set(_ippcp_static_library_suffix "mt.lib") set(_ippcp_shared_library_suffix ".dll") set(_ippcp_import_library_suffix ".lib") else() set(_ippcp_library_prefix "lib") set(_ippcp_static_library_suffix ".a") if (APPLE) set(_ippcp_shared_library_suffix ".dylib") else() set(_ippcp_shared_library_suffix ".so") endif() set(_ippcp_import_library_suffix "") endif() get_filename_component(_ippcrypto_root "${CMAKE_CURRENT_LIST_DIR}" REALPATH) set(_ippcrypto_root "${_ippcrypto_root}/../../..") macro(add_imported_library_target PATH_TO_LIBRARY PATH_TO_IMPORT_LIB LINKAGE_TYPE) if (EXISTS "${PATH_TO_LIBRARY}") if (NOT TARGET IPPCP::${_component}) add_library(IPPCP::${_component} ${LINKAGE_TYPE} IMPORTED) get_filename_component(_include_dir "${_ippcrypto_root}/@IPPCP_INC_REL_PATH@" REALPATH) if (EXISTS "${_include_dir}") set_target_properties(IPPCP::${_component} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_include_dir}" IMPORTED_LOCATION "${PATH_TO_LIBRARY}") if (WIN32) set_target_properties(IPPCP::${_component} PROPERTIES IMPORTED_IMPLIB "${PATH_TO_IMPORT_LIB}") endif() else() message(WARNING "Include directory does not exist: '${_include_dir}'. Intel Cryptography Primitives Library installation might be broken.") endif() unset(_include_dir) endif() list(APPEND IPPCP_LIBRARIES IPPCP::${_component}) set(IPPCP_${_component}_FOUND 1) elseif (IPPCP_FIND_REQUIRED AND IPPCP_FIND_REQUIRED_${_component}) message(STATUS "Missed required Intel Cryptography Primitives Library component: ${_component}") message(STATUS " library not found:\n ${PATH_TO_LIBRARY}") if (${LINKAGE_TYPE} MATCHES "SHARED") message(STATUS "You may try to search for static library by unsetting IPPCP_SHARED variable.") endif() set(IPPCP_FOUND FALSE) endif() endmacro(add_imported_library_target) foreach (_component ${IPPCP_FIND_COMPONENTS}) set(IPPCP_${_component}_FOUND 0) if (IPPCP_SHARED) set(_ippcp_library_suffix "${_ippcp_shared_library_suffix}") set(_linkage_type "SHARED") else() set(_ippcp_library_suffix "${_ippcp_static_library_suffix}") set(_linkage_type "STATIC") endif() if (WIN32 AND ${_linkage_type} MATCHES "SHARED") get_filename_component(_lib "${_ippcrypto_root}/${IPPCP_BIN_REL_PATH}/${_ippcp_library_prefix}${_component}${_ippcp_library_suffix}" REALPATH) get_filename_component(_imp_lib "${_ippcrypto_root}/${PPCP_LIB_REL_PATH}/${_ippcp_library_prefix}${_component}${_ippcp_import_library_suffix}" REALPATH) else() get_filename_component(_lib "${_ippcrypto_root}/${IPPCP_LIB_REL_PATH}/${_ippcp_library_prefix}${_component}${_ippcp_library_suffix}" REALPATH) set(_imp_lib "") endif() add_imported_library_target("${_lib}" "${_imp_lib}" "${_linkage_type}") endforeach() list(REMOVE_DUPLICATES IPPCP_LIBRARIES) unset(_ippcp_library_prefix) unset(_ippcp_static_library_suffix) unset(_ippcp_shared_library_suffix) unset(_ippcp_import_library_suffix) unset(_ippcp_library_suffix) unset(_linkage_type) unset(_lib) unset(_imp_lib) cryptography-primitives-1.0.0/sources/cmake/ippcp-gen-config.cmake000066400000000000000000000034731470420105600253340ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= set(IPPCP_LIB64_REL_PATH "lib") set(IPPCP_LIB32_REL_PATH "lib32") set(IPPCP_BIN64_REL_PATH "bin") set(IPPCP_BIN32_REL_PATH "bin32") set(IPPCP_INC_REL_PATH "include") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/ippcp-config.cmake.in" "${CMAKE_BINARY_DIR}/ippcp-config.cmake" @ONLY) configure_file("${IPP_CRYPTO_DIR}/sources/cmake/ippcp-config-version.cmake.in" "${CMAKE_BINARY_DIR}/ippcp-config-version.cmake" @ONLY) # Produce pkg-config files include("${IPP_CRYPTO_DIR}/sources/cmake/ippcp-gen-pkg-config.cmake") install(FILES "${CMAKE_BINARY_DIR}/ippcp-config.cmake" "${CMAKE_BINARY_DIR}/ippcp-config-version.cmake" DESTINATION "lib/cmake/ippcp") # FIXME: temporary until infra migrates to a build structure generated by 'make install' foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) file(COPY "${CMAKE_BINARY_DIR}/ippcp-config.cmake" "${CMAKE_BINARY_DIR}/ippcp-config-version.cmake" DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/cmake") endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) cryptography-primitives-1.0.0/sources/cmake/ippcp-gen-pkg-config.cmake000066400000000000000000000144201470420105600261050ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2021 Intel Corporation # # 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. #========================================================================= set(IPPCP_PC_LIB_NAME ippcp) set(CRYPTO_MB_PC_LIB_NAME crypto_mb) set(PREFIX_FOR_PC_FILE "\${pcfiledir}/../..") set(INCDIR_FOR_PC_FILE "\${prefix}/${IPPCP_INC_REL_PATH}") set(ARCH_TYPES "intel64;ia32") if (WIN32) set(STATIC_LIBRARY_PREFIX "") set(STATIC_LIBRARY_SUFFIX "mt.lib") else() set(STATIC_LIBRARY_PREFIX "lib") set(STATIC_LIBRARY_SUFFIX ".a") endif() if (APPLE) set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB_REL_PATH}") set(IPPCP_PC_LIB_NAME ippcp) configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-static.pc.in" "${CMAKE_BINARY_DIR}/ippcp-static-intel64.pc" @ONLY) configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-dynamic.pc.in" "${CMAKE_BINARY_DIR}/ippcp-dynamic-intel64.pc" @ONLY) configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/crypto_mb-static.pc.in" "${CMAKE_BINARY_DIR}/crypto_mb-static-intel64.pc" @ONLY) configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/crypto_mb-dynamic.pc.in" "${CMAKE_BINARY_DIR}/crypto_mb-dynamic-intel64.pc" @ONLY) else() # pkg-config files for ippcp static libs set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-static.pc.in" "${CMAKE_BINARY_DIR}/ippcp-static-intel64.pc" @ONLY) set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB32_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-static.pc.in" "${CMAKE_BINARY_DIR}/ippcp-static-ia32.pc" @ONLY) # Pkg-config file for crypto_mb static lib set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/crypto_mb-static.pc.in" "${CMAKE_BINARY_DIR}/crypto_mb-static-intel64.pc" @ONLY) # pkg-config files for static nonpic libs under Linux and dynamic libs if (WIN32) # ippcp dynamic libs set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_BIN_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-dynamic.pc.in" "${CMAKE_BINARY_DIR}/ippcp-dynamic-intel64.pc" @ONLY) set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_BIN32_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-dynamic.pc.in" "${CMAKE_BINARY_DIR}/ippcp-dynamic-ia32.pc" @ONLY) # crypto_mb dynamic lib set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_BIN_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/crypto_mb-dynamic.pc.in" "${CMAKE_BINARY_DIR}/crypto_mb-dynamic-intel64.pc" @ONLY) # Linux else() # ippcp dynamic and static nonpic libs set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB_REL_PATH}/nonpic") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-static.pc.in" "${CMAKE_BINARY_DIR}/ippcp-static-intel64-nonpic.pc" @ONLY) set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB32_REL_PATH}/nonpic") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-static.pc.in" "${CMAKE_BINARY_DIR}/ippcp-static-ia32-nonpic.pc" @ONLY) set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-dynamic.pc.in" "${CMAKE_BINARY_DIR}/ippcp-dynamic-intel64.pc" @ONLY) set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB32_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/ippcp-dynamic.pc.in" "${CMAKE_BINARY_DIR}/ippcp-dynamic-ia32.pc" @ONLY) # crypto_mb dynamic lib set(LIBDIR_FOR_PC_FILE "\${prefix}/${IPPCP_LIB_REL_PATH}") configure_file("${IPP_CRYPTO_DIR}/sources/cmake/pkg-config/crypto_mb-dynamic.pc.in" "${CMAKE_BINARY_DIR}/crypto_mb-dynamic-intel64.pc" @ONLY) endif(WIN32) endif(APPLE) install(FILES "${CMAKE_BINARY_DIR}/ippcp-static-intel64.pc" "${CMAKE_BINARY_DIR}/ippcp-dynamic-intel64.pc" "${CMAKE_BINARY_DIR}/crypto_mb-static-intel64.pc" "${CMAKE_BINARY_DIR}/crypto_mb-dynamic-intel64.pc" "${CMAKE_BINARY_DIR}/ippcp-static-intel64-nonpic.pc" DESTINATION "lib/pkgconfig" OPTIONAL) install(FILES "${CMAKE_BINARY_DIR}/ippcp-static-ia32.pc" "${CMAKE_BINARY_DIR}/ippcp-dynamic-ia32.pc" "${CMAKE_BINARY_DIR}/ippcp-static-ia32-nonpic.pc" DESTINATION "lib32/pkgconfig" OPTIONAL) # FIXME: temporary until infra migrates to a build structure generated by 'make install' foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) if ("${ARCH}" STREQUAL "intel64") file(COPY "${CMAKE_BINARY_DIR}/ippcp-static-intel64.pc" "${CMAKE_BINARY_DIR}/ippcp-dynamic-intel64.pc" "${CMAKE_BINARY_DIR}/crypto_mb-static-intel64.pc" "${CMAKE_BINARY_DIR}/crypto_mb-dynamic-intel64.pc" DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/pkgconfig") # Linux nonpic libs if(UNIX AND NOT APPLE) file(COPY "${CMAKE_BINARY_DIR}/ippcp-static-intel64-nonpic.pc" DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/pkgconfig") endif(UNIX AND NOT APPLE) else() file(COPY "${CMAKE_BINARY_DIR}/ippcp-static-ia32.pc" "${CMAKE_BINARY_DIR}/ippcp-dynamic-ia32.pc" DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/pkgconfig") # Linux nonpic libs if(UNIX) file(COPY "${CMAKE_BINARY_DIR}/ippcp-static-ia32-nonpic.pc" DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/pkgconfig") endif(UNIX) endif("${ARCH}" STREQUAL "intel64") endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) cryptography-primitives-1.0.0/sources/cmake/ippcp-utils.cmake000066400000000000000000000045601470420105600244560ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= macro(ippcp_getlibversion VERSION_FILE) unset(IPPCP_VERSION_MAJOR) unset(IPPCP_VERSION_MINOR) unset(IPPCP_VERSION_UPDATE) unset(IPPCP_VERSION) unset(IPPCP_INTERFACE_VERSION_MAJOR) unset(IPPCP_INTERFACE_VERSION_MINOR) file(STRINGS "${VERSION_FILE}" FILE_CONTENTS) foreach(LINE ${FILE_CONTENTS}) if ("${LINE}" MATCHES "#define CRYPTO_LIB_VERSION_MAJOR") string(REGEX REPLACE "^#define +CRYPTO_LIB_VERSION_MAJOR +\([0-9]+\).*$" "\\1" IPPCP_VERSION_MAJOR ${LINE}) endif() if ("${LINE}" MATCHES "#define CRYPTO_LIB_VERSION_MINOR") string(REGEX REPLACE "^#define +CRYPTO_LIB_VERSION_MINOR +\([0-9]+\).*$" "\\1" IPPCP_VERSION_MINOR ${LINE}) endif() if ("${LINE}" MATCHES "#define CRYPTO_LIB_VERSION_PATCH") string(REGEX REPLACE "^#define +CRYPTO_LIB_VERSION_PATCH +\([0-9]+\).*$" "\\1" IPPCP_VERSION_UPDATE ${LINE}) endif() if ("${LINE}" MATCHES "#define CRYPTO_LIB_INTERFACE_VERSION_MAJOR") string(REGEX REPLACE "^#define +CRYPTO_LIB_INTERFACE_VERSION_MAJOR +\([0-9]+\).*$" "\\1" IPPCP_INTERFACE_VERSION_MAJOR ${LINE}) endif() if ("${LINE}" MATCHES "#define CRYPTO_LIB_INTERFACE_VERSION_MINOR") string(REGEX REPLACE "^#define +CRYPTO_LIB_INTERFACE_VERSION_MINOR +\([0-9]+\).*$" "\\1" IPPCP_INTERFACE_VERSION_MINOR ${LINE}) endif() endforeach() set(IPPCP_VERSION "${IPPCP_VERSION_MAJOR}.${IPPCP_VERSION_MINOR}.${IPPCP_VERSION_UPDATE}") set(IPPCP_INTERFACE_VERSION "${IPPCP_INTERFACE_VERSION_MAJOR}.${IPPCP_INTERFACE_VERSION_MINOR}") unset(FILE_CONTENTS) endmacro(ippcp_getlibversion) cryptography-primitives-1.0.0/sources/cmake/linux/000077500000000000000000000000001470420105600223355ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/cmake/linux/Clang9.0.0.cmake000066400000000000000000000137411470420105600247560ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2020 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # Security Linker flags set(LINK_FLAG_SECURITY "") # Disallows undefined symbols in object files. Undefined symbols in shared libraries are still allowed set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,defs") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Prevents the compiler from using standard libraries and startup files when linking. set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_SECURITY} -nostdlib") # Dynamically link lib c (libdl is for old apps) set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -Wl,-call_shared,-lc") # Create a shared library set(LINK_FLAG_DYNAMIC_MACOSX "-Wl,-shared") if(${ARCH} MATCHES "ia32") # Tells the compiler to generate code for a specific architecture (32) set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -m32") endif(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_MACOSX "-nostdlib -Wl,-lc") if(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_MACOSX "${LINK_FLAG_PCS_MACOSX} -m32") endif(${ARCH} MATCHES "ia32") # compiler # Enables the use of blocks and entire functions of assembly code within a C or C++ file set(CC_FLAGS_INLINE_ASM_UNIX "-fasm-blocks") # Disables all warning messages set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX} -w") # Tells the compiler to generate code for a specific architecture (32) set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -m32") # EBP is used as a general-purpose register in optimizations set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -fomit-frame-pointer") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") # Tells the compiler to align functions set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-functions=32") # Format string vulnerabilities set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Wformat-security") #Diagnostic flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdouble-promotion -Wshadow -Wunreachable-code -Wpointer-arith -Wuninitialized -Wconversion") # Enable __declspec attribute set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdeclspec") # Variables explicitly initialized with zeros are placed in the BSS section. This can save space in the resulting code set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-zero-initialized-in-bss") # C std set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") if ((${ARCH} MATCHES "ia32") OR (NOT NONPIC_LIB)) # Stack-based Buffer Overrun Detection (only when not nonpic intel64) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") endif() # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcf-protection=full") if(NOT NONPIC_LIB) # Position Independent Execution (PIE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic -fPIC") elseif(NOT ${ARCH} MATCHES "ia32") # NONPIC intel64: specify kernel code model set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=kernel") endif() # When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpack-struct=16") if(${ARCH} MATCHES "ia32") # Stack alignment = 16 bytes set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstack-alignment=4") # 32bit linker command #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Xassembler --32") # Tells the compiler to generate code for a specific architecture (32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") endif(${ARCH} MATCHES "ia32") # Build with sanitizers if(SANITIZERS) include(${CMAKE_SOURCE_DIR}/sources/cmake/linux/SanitizersSettings.cmake) set_sanitizers_flags("C") endif(SANITIZERS) # Optimization level = 3, no-debug definition (turns off asserts), warnings=errors set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG -Werror") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") # DEBUG flags - optimization level = 0, generation GDB information (-g) set (CMAKE_C_FLAGS_DEBUG " -O0 -g") set(w7_opt "${w7_opt} -march=pentium4 -msse2") set(s8_opt "${s8_opt} -march=core2 -mssse3") set(p8_opt "${p8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(g9_opt "${g9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(h9_opt "${h9_opt} -march=haswell -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed") set(m7_opt "${m7_opt} -march=nocona -msse3") set(n8_opt "${n8_opt} -march=core2 -mssse3") set(y8_opt "${y8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(e9_opt "${e9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(l9_opt "${l9_opt} -march=haswell -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed") set(k0_opt "${k0_opt} -march=skylake-avx512") set(k0_opt "${k0_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mpclmul -mrdrnd -mrdseed -madx") set(k1_opt "${k1_opt} -march=icelake-server") set(k1_opt "${k1_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") cryptography-primitives-1.0.0/sources/cmake/linux/GNU8.2.0.cmake000066400000000000000000000131661470420105600243650ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # Security Linker flags set(LINK_FLAG_SECURITY "") # Disallows undefined symbols in object files. Undefined symbols in shared libraries are still allowed set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,defs") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Prevents the compiler from using standard libraries and startup files when linking. set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_SECURITY} -nostdlib") # Dynamically link lib c (libdl is for old apps) set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-call_shared,-lc") # Create a shared library set(LINK_FLAG_DYNAMIC_LINUX "-Wl,-shared") if(${ARCH} MATCHES "ia32") # Tells the compiler to generate code for a specific architecture (32) set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -m32") endif(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_LINUX "${LINK_FLAG_DYNAMIC_LINUX}") # compiler # Enables the use of blocks and entire functions of assembly code within a C or C++ file set(CC_FLAGS_INLINE_ASM_UNIX "-fasm-blocks") # Disables all warning messages set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX} -w") # Tells the compiler to generate code for a specific architecture (32) set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -m32") # EBP is used as a general-purpose register in optimizations set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -fomit-frame-pointer") # Do not use the specified registers in dispatcher compilation set(CC_FLAGS_INLINE_ASM_UNIX_INTEL64 "${CC_FLAGS_INLINE_ASM_UNIX} -ffixed-rdi -ffixed-rsi -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rbp -ffixed-r8 -ffixed-r9 -ffixed-r12 -ffixed-r13 -ffixed-r14 -ffixed-r15") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-functions=32 -falign-loops=32") # Format string vulnerabilities set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Wformat-security") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcf-protection=full") # Prints a report with internal details on the workings of the link-time optimizer set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto-report") # C std set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") if ((${ARCH} MATCHES "ia32") OR (NOT NONPIC_LIB)) # Stack-based Buffer Overrun Detection (only when not nonpic intel64) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") endif() if(NOT NONPIC_LIB) # Position Independent Execution (PIE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic -fPIC") elseif(NOT ${ARCH} MATCHES "ia32") # NONPIC intel64: specify kernel code model set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=kernel") endif() # When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpack-struct=16") if(${ARCH} MATCHES "ia32") # Stack alignment = 16 bytes set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mpreferred-stack-boundary=4") # 32bit linker command set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wa,--32") # Tells the compiler to generate code for a specific architecture (32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") endif(${ARCH} MATCHES "ia32") # Optimization level = 3, no-debug definition (turns off asserts), warnings=errors set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG -Werror") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") set(w7_opt "${w7_opt} -march=pentium4 -msse2") set(s8_opt "${s8_opt} -march=core2 -mssse3") set(p8_opt "${p8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(g9_opt "${g9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(h9_opt "${h9_opt} -march=haswell -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed") set(m7_opt "${m7_opt} -march=nocona -msse3") set(n8_opt "${n8_opt} -march=core2 -mssse3") set(y8_opt "${y8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(e9_opt "${e9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(l9_opt "${l9_opt} -march=haswell -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed") set(k0_opt "${k0_opt} -march=skylake-avx512") set(k0_opt "${k0_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mpclmul -mrdrnd -mrdseed -madx") set(k1_opt "${k1_opt} -march=icelake-server") set(k1_opt "${k1_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") cryptography-primitives-1.0.0/sources/cmake/linux/Intel19.0.0.cmake000066400000000000000000000137511470420105600250670ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # Linker flags # Security Linker flags set(LINK_FLAG_SECURITY "") # Disallows undefined symbols in object files. Undefined symbols in shared libraries are still allowed set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,defs") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Prevents the compiler from using standard libraries and startup files when linking. set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_SECURITY} -nostdlib") # Create a shared library set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-shared") # Dynamically link lib c (libdl is for old apps) set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-call_shared,-lc") if(${ARCH} MATCHES "ia32") # Emulate elf_i386 linker set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-m,elf_i386") endif(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_LINUX "${LINK_FLAG_DYNAMIC_LINUX}") # Compiler flags # Enables the use of blocks and entire functions of assembly code within a C or C++ file set(CC_FLAGS_INLINE_ASM_UNIX "-fasm-blocks") # Disables all warning messages set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX} -w") # Tells the compiler to generate code for a specific architecture (32) set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -m32") # EBP is used as a general-purpose register in optimizations set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -fomit-frame-pointer") # Do not use the specified registers in dispatcher compilation set(CC_FLAGS_INLINE_ASM_UNIX_INTEL64 "${CC_FLAGS_INLINE_ASM_UNIX} -ffixed-rdi -ffixed-rsi -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rbp -ffixed-r8 -ffixed-r9 -ffixed-r12 -ffixed-r13 -ffixed-r14 -ffixed-r15") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") # Determines whether pointer disambiguation is enabled with the restrict qualifier set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -restrict") # Tells the compiler to generate an optimization report set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qopt-report2 -qopt-report-phase:vec") # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-functions=32 -falign-loops=32") # C std and diag settings set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -diag-error 266 -diag-disable 13366") # Security Compiler flags # Stack-based Buffer Overrun Detection if ((${ARCH} MATCHES "ia32") OR (NOT NONPIC_LIB)) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") endif() # Format string vulnerabilities set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Wformat-security") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcf-protection=full") if(NOT NONPIC_LIB) # Position Independent Execution (PIE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic -fPIC") elseif(NOT ${ARCH} MATCHES "ia32") # NONPIC intel64: specify kernel code model set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=kernel") endif() if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -prof-gen:srcpos -prof-dir $ENV{PROF_DATA_DIR}") endif() # Optimization level = 3, no-debug definition (turns off asserts), warning level = 3, treat warnings as errors set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG -w3 -Werror") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") # DEBUG flags Optimization level = 0, generation maximum GDB information (-g3) set (CMAKE_C_FLAGS_DEBUG " -O0 -g3") # Do not include compilation options and version number in the resulting file set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -no-sox") # Alignment for structures on byte boundaries (= 16) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Zp16") # Defines the GNU macros (__GNUC__, __GNUC_MINOR__, and __GNUC_PATCHLEVEL__) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -gcc") if(${ARCH} MATCHES "ia32") # Tells the compiler to not assume any specific stack alignment, but attempt to maintain alignment in case the stack is already aligned. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-stack=maintain-16-byte") # 32bit linker command set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wa,--32") # Do not use assembler to process asm files set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -no-use-asm") # Tells the compiler to generate code for a specific architecture (32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") endif(${ARCH} MATCHES "ia32") set(px_opt "${px_opt} -mia32") set(w7_opt "${w7_opt} -xSSE2") set(s8_opt "${s8_opt} -xATOM_SSSE3 -minstruction=nomovbe") set(p8_opt "${p8_opt} -xATOM_SSE4.2 -minstruction=nomovbe") set(g9_opt "${g9_opt} -xAVX") set(h9_opt "${h9_opt} -xCORE-AVX2") set(mx_opt "${mx_opt} -march=pentium") set(m7_opt "${m7_opt} -xSSE3") set(n8_opt "${n8_opt} -xATOM_SSSE3 -minstruction=nomovbe") set(y8_opt "${y8_opt} -xATOM_SSE4.2 -minstruction=nomovbe") set(e9_opt "${e9_opt} -xAVX") set(l9_opt "${l9_opt} -xCORE-AVX2") set(k0_opt "${k0_opt} -xCORE-AVX512") set(k0_opt "${k0_opt} -qopt-zmm-usage:high") set(k1_opt "${k1_opt} -xCORE-AVX512") set(k1_opt "${k1_opt} -qopt-zmm-usage:high") cryptography-primitives-1.0.0/sources/cmake/linux/IntelLLVM2023.1.0.cmake000066400000000000000000000132461470420105600257170ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2021 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # Linker flags # Security Linker flags set(LINK_FLAG_SECURITY "") # Disallows undefined symbols in object files. Undefined symbols in shared libraries are still allowed set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,defs") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Prevents the compiler from using standard libraries and startup files when linking. set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_SECURITY} -nostdlib") # Create a shared library set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-shared") # Dynamically link lib c (libdl is for old apps) set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-call_shared,-lc") if(${ARCH} MATCHES "ia32") # Emulate elf_i386 linker set(LINK_FLAG_DYNAMIC_LINUX "${LINK_FLAG_DYNAMIC_LINUX} -Wl,-m,elf_i386") endif(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_LINUX "${LINK_FLAG_DYNAMIC_LINUX}") # Compiler flags # Enables the use of blocks and entire functions of assembly code within a C or C++ file set(CC_FLAGS_INLINE_ASM_UNIX "-fasm-blocks") # Disables all warning messages set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX} -w") # Tells the compiler to generate code for a specific architecture (32) set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -m32") # EBP is used as a general-purpose register in optimizations set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -fomit-frame-pointer") # Do not use the specified registers in dispatcher compilation set(CC_FLAGS_INLINE_ASM_UNIX_INTEL64 "${CC_FLAGS_INLINE_ASM_UNIX} -ffixed-rdi -ffixed-rsi -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rbp -ffixed-r8 -ffixed-r9 -ffixed-r12 -ffixed-r13 -ffixed-r14 -ffixed-r15") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-functions=32") # C std and diag settings set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -diag-error 266 -diag-disable 13366") # Security Compiler flags # Stack-based Buffer Overrun Detection if ((${ARCH} MATCHES "ia32") OR (NOT NONPIC_LIB)) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") endif() # Format string vulnerabilities set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Wformat-security -Wunknown-pragmas") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcf-protection=full -O3") if(NOT NONPIC_LIB) # Position Independent Execution (PIE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic -fPIC") elseif(NOT ${ARCH} MATCHES "ia32") # NONPIC intel64: specify kernel code model set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=kernel") endif() if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -prof-gen:srcpos -prof-dir $ENV{PROF_DATA_DIR}") endif() # Optimization level = 3, no-debug definition (turns off asserts), warning level = 3, treat warnings as errors set(CMAKE_C_FLAGS_RELEASE " -Ofast -DNDEBUG -Wall -Wno-unused-function -Werror") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") # Alignment for structures on byte boundaries (= 16) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Zp16") if(${ARCH} MATCHES "ia32") # Tells the compiler to generate code for a specific architecture (32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") endif(${ARCH} MATCHES "ia32") set(px_opt "${px_opt} ") # note: no flags for the default version set(w7_opt "${w7_opt} -msse2") set(s8_opt "${s8_opt} -march=core2 -mssse3") set(p8_opt "${p8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(g9_opt "${g9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(h9_opt "${h9_opt} -march=haswell -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed") set(mx_opt "${mx_opt} ") # note: no flags for the default version set(m7_opt "${m7_opt} -march=nocona -msse3") set(n8_opt "${n8_opt} -march=core2 -mssse3") set(y8_opt "${y8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(e9_opt "${e9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(l9_opt "${l9_opt} -march=haswell -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed") set(k0_opt "${k0_opt} -march=skylake-avx512") set(k0_opt "${k0_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mpclmul -mrdrnd -mrdseed -madx") set(k0_opt "${k0_opt} -mprefer-vector-width=512") set(k1_opt "${k1_opt} -march=icelake-server") set(k1_opt "${k1_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") set(k1_opt "${k1_opt} -mprefer-vector-width=512") cryptography-primitives-1.0.0/sources/cmake/linux/SanitizersSettings.cmake000066400000000000000000000043571470420105600272240ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2022 Intel Corporation # # 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. #========================================================================= function(set_sanitizers_flags lang) if(NOT (${lang} STREQUAL "C") AND NOT (${lang} STREQUAL "CXX")) message (FATAL_ERROR "Invalid function argument. Expected values: \"C\", \"CXX\" ") endif() if(ASAN) list(APPEND TYPES_OF_SANITIZERS_LIST "address") set(FLAGS "${FLAGS} -fno-omit-frame-pointer") endif(ASAN) if(UBSAN) list(APPEND TYPES_OF_SANITIZERS_LIST "undefined,float-divide-by-zero,unsigned-integer-overflow,implicit-conversion") endif(UBSAN) if(MSAN) list(APPEND TYPES_OF_SANITIZERS_LIST "memory") if(${CMAKE_${lang}_COMPILER_VERSION} VERSION_GREATER_EQUAL "13.0.0") set(FLAGS "${FLAGS} -fsanitize-ignorelist=${CMAKE_SOURCE_DIR}/sources/cmake/linux/sanitizers_ignorelist.txt") else() set(FLAGS "${FLAGS} -fsanitize-blacklist=${CMAKE_SOURCE_DIR}/sources/cmake/linux/sanitizers_ignorelist.txt") endif() endif(MSAN) list(JOIN TYPES_OF_SANITIZERS_LIST "," TYPES_OF_SANITIZERS_STRING) set(FLAGS "${FLAGS} -fsanitize=${TYPES_OF_SANITIZERS_STRING}") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${FLAGS}" PARENT_SCOPE) if(${lang} STREQUAL "CXX") # IPP_USE_LIBCXX macro is used in tsstream.h. It is needed to distinguish # libcxx build on Linux from the default platform build as libcxx uses # different streams API than libstdc++. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAGS} -DIPP_USE_LIBCXX -stdlib=libc++ -lc++abi" PARENT_SCOPE) endif() endfunction() cryptography-primitives-1.0.0/sources/cmake/linux/common.cmake000066400000000000000000000023131470420105600246260ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # set(OS_DEFAULT_COMPILER Intel19.0.0) if(${ARCH} MATCHES "ia32") set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -Dlinux -DLINUX32 -D_ARCH_IA32") # 32bit linux else() set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -Dlinux -DLINUX32E -D_ARCH_EM64T") # 64bit linux endif(${ARCH} MATCHES "ia32") if(NOT NONPIC_LIB) set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPP_PIC") endif() #set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DBN_OPENSSL_DISABLE") cryptography-primitives-1.0.0/sources/cmake/linux/sanitizers_ignorelist.txt000066400000000000000000000015411470420105600275310ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2022 Intel Corporation # # 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. #========================================================================= [memory] fun:*cpGetFeatures* fun:*IntelCpu* fun:*ppSetIppEnvironment* src:tests/testlib/* src:perf_tests/perflib/*cryptography-primitives-1.0.0/sources/cmake/macosx/000077500000000000000000000000001470420105600224705ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/cmake/macosx/AppleClang11.0.0.cmake000066400000000000000000000126141470420105600261420ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2020 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # Security Linker flags set(LINK_FLAG_SECURITY "") # Disallows undefined symbols in object files. Undefined symbols in shared libraries are still allowed set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,defs") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Prevents the compiler from using standard libraries and startup files when linking. set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_SECURITY} -nostdlib") # Dynamically link lib c (libdl is for old apps) set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -Wl,-lc") # Create a shared library set(LINK_FLAG_DYNAMIC_MACOSX "-dynamiclib") if(${ARCH} MATCHES "ia32") # Tells the compiler to generate code for a specific architecture (32) set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -m32") endif(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_MACOSX "-nostdlib -Wl,-lc") if(${ARCH} MATCHES "ia32") set(LINK_FLAG_PCS_MACOSX "${LINK_FLAG_PCS_MACOSX} -m32") endif(${ARCH} MATCHES "ia32") # compiler # Enables the use of blocks and entire functions of assembly code within a C or C++ file set(CC_FLAGS_INLINE_ASM_UNIX "-fasm-blocks") # Disables all warning messages set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX} -w") # Tells the compiler to generate code for a specific architecture (32) set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -m32") # EBP is used as a general-purpose register in optimizations set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -fomit-frame-pointer") set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -D_APPLE_CLANG") set(APPLE_CLANG ON) set(APPLE_CLANG ${APPLE_CLANG} PARENT_SCOPE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") # Tells the compiler to align functions set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-functions=32") # Format string vulnerabilities set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Wformat-security") #Diagnostic flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wdouble-promotion -Wshadow -Wunreachable-code -Wpointer-arith -Wuninitialized") # Enable __declspec attribute set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fdeclspec") # Variables explicitly initialized with zeros are placed in the BSS section. This can save space in the resulting code set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-zero-initialized-in-bss") # C std set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") if ((${ARCH} MATCHES "ia32") OR (NOT NONPIC_LIB)) # Stack-based Buffer Overrun Detection (only when not nonpic intel64) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") endif() if(NOT NONPIC_LIB) # Position Independent Execution (PIE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic -fPIC") elseif(NOT ${ARCH} MATCHES "ia32") # NONPIC intel64: specify kernel code model set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mno-red-zone -mcmodel=kernel") endif() # When a value is specified (which must be a small power of two), pack structure members according to this value, representing the maximum alignment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpack-struct=16") if(${ARCH} MATCHES "ia32") # Stack alignment = 16 bytes set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstack-alignment=4") # Tells the compiler to generate code for a specific architecture (32) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") endif(${ARCH} MATCHES "ia32") # Optimization level = 3, no-debug definition (turns off asserts), warnings=errors set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG -Werror") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") set(w7_opt "${w7_opt} -march=pentium4 -msse2") set(s8_opt "${s8_opt} -march=core2 -mssse3") set(p8_opt "${p8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(g9_opt "${g9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(h9_opt "${h9_opt} -march=haswell -mavx2 -maes -mpclmul -msha -mrdrnd -mrdseed") set(m7_opt "${m7_opt} -march=nocona -msse3") set(n8_opt "${n8_opt} -march=core2 -mssse3") set(y8_opt "${y8_opt} -march=nehalem -msse4.2 -maes -mpclmul -msha") set(e9_opt "${e9_opt} -march=sandybridge -mavx -maes -mpclmul -msha -mrdrnd -mrdseed") set(l9_opt "${l9_opt} -march=haswell -mavx2 -maes -mpclmul -msha -mrdrnd -mrdseed") set(k0_opt "${k0_opt} -march=skylake-avx512") set(k0_opt "${k0_opt} -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") cryptography-primitives-1.0.0/sources/cmake/macosx/Intel19.0.0.cmake000066400000000000000000000114161470420105600252160ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # linker # Create a dynamic lib set(LINK_FLAG_DYNAMIC_MACOSX "-Wl,-dynamic") # Alters how symbols are resolved at build time and runtime. # The linker does not record which dylib an external symbol came from, so at runtime dyld again searches all images and uses the first definition it finds. set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -Wl,-flat_namespace") # Automatically adds space for future expansion of load commands such that all paths could expand to MAXPATHLEN. set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -Wl,-headerpad_max_install_names") # This is set to indicate the oldest Mac OS X version that that the output is to be used on. set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -mmacosx-version-min=10.8") # Prevents the compiler from using standard libraries and startup files when linking. set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -nostdlib") # Dynamically link to lib c set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -Wl,-lc") # The architecture for the output file set(LINK_FLAG_DYNAMIC_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX} -Wl,-arch,x86_64") set(LINK_FLAG_PCS_MACOSX "${LINK_FLAG_DYNAMIC_MACOSX}") # compiler # Enables the use of blocks and entire functions of assembly code within a C or C++ file set(CC_FLAGS_INLINE_ASM_UNIX "-fasm-blocks") # Disables all warning messages set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX} -w") # Tells the compiler to generate code for a specific architecture (32) set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -m32") # EBP is used as a general-purpose register in optimizations set(CC_FLAGS_INLINE_ASM_UNIX_IA32 "${CC_FLAGS_INLINE_ASM_UNIX_IA32} -fomit-frame-pointer") # Do not use the specified registers in dispatcher compilation set(CC_FLAGS_INLINE_ASM_UNIX_INTEL64 "${CC_FLAGS_INLINE_ASM_UNIX} -ffixed-rdi -ffixed-rsi -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rbp -ffixed-r8 -ffixed-r9 -ffixed-r12 -ffixed-r13 -ffixed-r14 -ffixed-r15") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") # Determines whether pointer disambiguation is enabled with the restrict qualifier set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -restrict") # Tells the compiler to generate an optimization report set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -qopt-report2 -qopt-report-phase:vec") # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -falign-functions=32 -falign-loops=32") # Other flags set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -diag-error 266 -diag-disable 13366") # Security Compiler flags # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector") # Format string vulnerabilities set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wformat -Wformat-security") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection # NOTE: Intel Compiler does not support CET code generation on macOS #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcf-protection=full") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpic -fPIC") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -prof-gen:srcpos -prof-dir ${PROF_DATA_DIR}") endif() # Optimization level = 3, no-debug definition (turns off asserts), warning level = 3, treat warnings as errors set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG -w3 -Werror") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") # Compile for x64 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -arch_only x86_64") set(w7_opt "${w7_opt} -xSSE2") set(s8_opt "${s8_opt} -xSSE3") set(p8_opt "${p8_opt} -xSSE4.2") set(g9_opt "${g9_opt} -xAVX") set(h9_opt "${h9_opt} -xCORE-AVX2") set(m7_opt "${m7_opt} -xSSE3") set(n8_opt "${n8_opt} -xSSSE3") set(y8_opt "${y8_opt} -xSSE4.2") set(e9_opt "${e9_opt} -xAVX") set(l9_opt "${l9_opt} -xCORE-AVX2") set(k0_opt "${k0_opt} -xCORE-AVX512") set(k0_opt "${k0_opt} -qopt-zmm-usage:high") cryptography-primitives-1.0.0/sources/cmake/macosx/common.cmake000066400000000000000000000017331470420105600247660ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # set(OS_DEFAULT_COMPILER Intel19.0.0) set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPP_PIC -DOSXEM64T -DLINUX32E -D_ARCH_EM64T") #set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DBN_OPENSSL_DISABLE")cryptography-primitives-1.0.0/sources/cmake/os_common.cmake000066400000000000000000000022571470420105600241770ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2023 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # The ability to build custom Intel® Cryptography Primitives Library - enable specific CPU features at compile time if((NOT MERGED_BLD) AND (NOT "${IPPCP_CUSTOM_BUILD}" STREQUAL "")) set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPPCP_CUSTOM_BUILD") foreach(feature ${IPPCP_CUSTOM_BUILD}) set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -D${feature}") endforeach(feature ${IPPCP_CUSTOM_BUILD}) endif() cryptography-primitives-1.0.0/sources/cmake/pkg-config/000077500000000000000000000000001470420105600232225ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/cmake/pkg-config/crypto_mb-dynamic.pc.in000066400000000000000000000022621470420105600275750ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2021 Intel Corporation # # 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. #========================================================================= prefix=@PREFIX_FOR_PC_FILE@ libdir=@LIBDIR_FOR_PC_FILE@ includedir=@INCDIR_FOR_PC_FILE@ Name: Intel® Cryptography Primitives Library Crypto Multi-Buffer Library Description: This library consists of highly-optimized kernels taking advantage of Intel’s multi-buffer processing and Intel® AVX-512 instruction set. URL: https://github.com/intel/ipp-crypto Version: @IPPCP_VERSION@ Libs: -L${libdir} -l@CRYPTO_MB_PC_LIB_NAME@ Cflags: -I${includedir} cryptography-primitives-1.0.0/sources/cmake/pkg-config/crypto_mb-static.pc.in000066400000000000000000000023341470420105600274400ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2021 Intel Corporation # # 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. #========================================================================= prefix=@PREFIX_FOR_PC_FILE@ libdir=@LIBDIR_FOR_PC_FILE@ includedir=@INCDIR_FOR_PC_FILE@ Name: Intel® Cryptography Primitives Library Crypto Multi-Buffer Library Description: This library consists of highly-optimized kernels taking advantage of Intel’s multi-buffer processing and Intel® AVX-512 instruction set. URL: https://github.com/intel/ipp-crypto Version: @IPPCP_VERSION@ Libs: ${libdir}/@STATIC_LIBRARY_PREFIX@@CRYPTO_MB_PC_LIB_NAME@@STATIC_LIBRARY_SUFFIX@ Cflags: -I${includedir} cryptography-primitives-1.0.0/sources/cmake/pkg-config/ippcp-dynamic.pc.in000066400000000000000000000021721470420105600267120ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2021 Intel Corporation # # 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. #========================================================================= prefix=@PREFIX_FOR_PC_FILE@ libdir=@LIBDIR_FOR_PC_FILE@ includedir=@INCDIR_FOR_PC_FILE@ Name: Intel® Cryptography Primitives Library Description: Secure, fast and lightweight library of building blocks for cryptography, highly-optimized for various Intel® CPUs. URL: https://github.com/intel/ipp-crypto Version: @IPPCP_VERSION@ Libs: -L${libdir} -l@IPPCP_PC_LIB_NAME@ Cflags: -I${includedir} cryptography-primitives-1.0.0/sources/cmake/pkg-config/ippcp-static.pc.in000066400000000000000000000022441470420105600265550ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2021 Intel Corporation # # 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. #========================================================================= prefix=@PREFIX_FOR_PC_FILE@ libdir=@LIBDIR_FOR_PC_FILE@ includedir=@INCDIR_FOR_PC_FILE@ Name: Intel® Cryptography Primitives Library Description: Secure, fast and lightweight library of building blocks for cryptography, highly-optimized for various Intel® CPUs. URL: https://github.com/intel/ipp-crypto Version: @IPPCP_VERSION@ Libs: ${libdir}/@STATIC_LIBRARY_PREFIX@@IPPCP_PC_LIB_NAME@@STATIC_LIBRARY_SUFFIX@ Cflags: -I${includedir} cryptography-primitives-1.0.0/sources/cmake/windows/000077500000000000000000000000001470420105600226705ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/cmake/windows/Intel19.0.0.cmake000066400000000000000000000163701470420105600254220ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # linker set(LINK_FLAG_STATIC_WINDOWS "") # Suppresses the display of the copyright banner when the compiler starts up and display of informational messages during compiling. set(LINK_FLAG_DYNAMIC_WINDOWS "/nologo") # Displays information about modules that are incompatible with safe structured exception handling when /SAFESEH isn't specified. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /VERBOSE:SAFESEH") # The /NODEFAULTLIB option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /NODEFAULTLIB") # Disable incremental linking set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /INCREMENTAL:NO") # Indicates that an executable was tested to be compatible with the Windows Data Execution Prevention feature. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /NXCOMPAT") # Specifies whether to generate an executable image that can be randomly rebased at load time. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /DYNAMICBASE") if(${ARCH} MATCHES "ia32") # When /SAFESEH is specified, the linker will only produce an image if it can also produce a table of the image's safe exception handlers. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /SAFESEH") else() # The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /LARGEADDRESSAWARE") # This option modifies the header of an executable image, a .dll file or .exe file, to indicate whether ASLR with 64-bit addresses is supported. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /HIGHENTROPYVA") endif(${ARCH} MATCHES "ia32") # Linker option to mitigate DLL hijacking vulnerability - removes CWD from the DLL search order set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /DEPENDENTLOADFLAG:0x2000") # suppress warning LNK4221: # "This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library" set(LINK_FLAG_STATIC_WINDOWS "${LINK_FLAG_STATIC_WINDOWS} /ignore:4221") set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /ignore:4221") if (MSVC_VERSION LESS_EQUAL 1800) # VS2013 # Link to C runtime, used in dlls set(LINK_LIB_STATIC_RELEASE libcmt) set(LINK_LIB_STATIC_DEBUG libcmtd) else() # Link to universal C runtime and MSVC runtime. Used in dlls. set(LINK_LIB_STATIC_RELEASE libcmt libucrt libvcruntime) set(LINK_LIB_STATIC_DEBUG libcmtd libucrtd libvcruntime) endif() # compiler set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Suppresses the display of the copyright banner when the compiler starts up and display of informational messages during compiling. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qfreestanding") # Removes standard directories from the include file search path. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /X") # Warning level = 4 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") # Changes all warnings to errors. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") # Detect some buffer overruns. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /GS") # Changes a soft diagnostic to an error set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qdiag-error:266") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qdiag-disable:13366") # Align functions set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qfnalign:32") # Align loops set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qalign-loops:32") # Determines whether pointer disambiguation is enabled with the restrict qualifier. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qrestrict") # Specifies alignment for structures on byte boundaries. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zp16") # Optimization report settings. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qopt-report2") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qopt-report-phase:vec") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qopt-report-stdout") # Do not save the compilation options and version number in the executable file set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qsox-") # Separates functions into COMDATs for the linker. This is a deprecated option. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gy") # C std set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qstd=c99") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qcf-protection:full") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qrof-gen:srcpos /Qprof-dir:${PROF_DATA_DIR}") endif() # Causes the application to use the multithread, static version of the run-time library (debug version). set(CMAKE_C_FLAGS_DEBUG "/MTd") # The /Zi option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi") # Turns off all optimizations in the program and speeds compilation. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od") # Debug macro set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /DDEBUG") # Causes the application to use the multithread, static version of the run-time library. set(CMAKE_C_FLAGS_RELEASE "/MT") # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /D_FORTIFY_SOURCE=2") # Omits the default C runtime library name from the .obj file. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zl") # "Maximize Speed". Selects a predefined set of options that affect the size and speed of generated code. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O3") # /Ob2 is included in /O3 # No-debug macro set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /DNDEBUG") # suppress warning #10120: overriding '/O2' with '/O3' # CMake bug: cmake cannot change the property "Optimization" to /O3 in MSVC project set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -wd10120") set(w7_opt "${w7_opt} -QxSSE2") set(s8_opt "${s8_opt} -QxATOM_SSSE3 -Qinstruction=nomovbe") set(p8_opt "${p8_opt} -QxATOM_SSE4.2 -Qinstruction=nomovbe") set(g9_opt "${g9_opt} -QxAVX") set(h9_opt "${h9_opt} -QxCORE-AVX2") set(m7_opt "${m7_opt} -QxSSE3") set(n8_opt "${n8_opt} -QxATOM_SSSE3 -Qinstruction=nomovbe") set(y8_opt "${y8_opt} -QxATOM_SSE4.2 -Qinstruction=nomovbe") set(e9_opt "${e9_opt} -QxAVX") set(l9_opt "${l9_opt} -QxCORE-AVX2") set(k0_opt "${k0_opt} -QxCORE-AVX512") set(k0_opt "${k0_opt} -Qopt-zmm-usage:high") set(k1_opt "${k1_opt} -QxCORE-AVX512") set(k1_opt "${k1_opt} -Qopt-zmm-usage:high") cryptography-primitives-1.0.0/sources/cmake/windows/IntelLLVM2023.1.0.cmake000066400000000000000000000146101470420105600262460ustar00rootroot00000000000000#=============================================================================== # Copyright 2024 Intel Corporation # # 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. #=============================================================================== # # Intel® Cryptography Primitives Library # # linker set(LINK_FLAG_STATIC_WINDOWS "/ignore:4221") # ignore warnings about empty obj files # Suppresses the display of the copyright banner when the compiler starts up and display of informational messages during compiling. set(LINK_FLAG_DYNAMIC_WINDOWS "/nologo") # Displays information about modules that are incompatible with safe structured exception handling when /SAFESEH isn't specified. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /VERBOSE:SAFESEH") # Disable incremental linking set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /INCREMENTAL:NO") # The /NODEFAULTLIB option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /NODEFAULTLIB") # Indicates that an executable was tested to be compatible with the Windows Data Execution Prevention feature. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /NXCOMPAT") # Specifies whether to generate an executable image that can be randomly rebased at load time. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /DYNAMICBASE") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /CETCOMPAT") # Linker option to mitigate DLL hijacking vulnerability - removes CWD from the DLL search order set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /DEPENDENTLOADFLAG:0x2000") if(${ARCH} MATCHES "ia32") # When /SAFESEH is specified, the linker will only produce an image if it can also produce a table of the image's safe exception handlers. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /SAFESEH") else() # The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /LARGEADDRESSAWARE") # This option modifies the header of an executable image, a .dll file or .exe file, to indicate whether ASLR with 64-bit addresses is supported. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /HIGHENTROPYVA") endif(${ARCH} MATCHES "ia32") # Link to universal C runtime and MSVC runtime. Used in dlls. set(LINK_LIB_STATIC_RELEASE libcmt libucrt libvcruntime) set(LINK_LIB_STATIC_DEBUG libcmtd libucrtd libvcruntime) # compiler set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Suppresses the display of the copyright banner when the compiler starts up and display of informational messages during compiling. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo") # Warning level = 4 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4 -Wall -Wformat -Wformat-security -Werror=format-security") # Changes all warnings to errors. #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") # Detects some buffer overruns that overwrite a function's return address, exception handler address, or certain types of parameters. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /GS") # Controls how the members of a structure are packed into memory and specifies the same packing for all structures in a module. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zp16") # Allows the compiler to package individual functions in the form of packaged functions. Smaller resulting size. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gy") # C std set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qstd=c99") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fcf-protection:full") # Suppress some warnings set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wno-null-pointer-arithmetic /Wno-unused-function /Wno-static-in-inline /Qno-intel-lib") # Causes the application to use the multithread, static version of the run-time library (debug version). set(CMAKE_C_FLAGS_DEBUG "/MTd") # The /Zi option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi") # Turns off all optimizations in the program and speeds compilation. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od") # Debug macro set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /DDEBUG") # Causes the application to use the multithread, static version of the run-time library. set(CMAKE_C_FLAGS_RELEASE "/MT") # Omits the default C runtime library name from the .obj file. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zl") # "Maximize Speed". Selects a predefined set of options that affect the size and speed of generated code. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O3") # No-debug macro set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /DNDEBUG") set(w7_opt "${w7_opt} /arch:SSE2") set(s8_opt "${s8_opt} /arch:SSSE3") set(p8_opt "${p8_opt} /arch:SSE4.2 -maes -mpclmul -msha") set(g9_opt "${g9_opt} /arch:AVX -maes -mpclmul -msha -mrdrnd -mrdseed") set(h9_opt "${h9_opt} /arch:AVX2 -maes -mpclmul -msha -mrdrnd -mrdseed -mvaes -mvpclmulqdq") set(m7_opt "${m7_opt} /arch:SSE3") set(n8_opt "${n8_opt} /arch:SSSE3") set(y8_opt "${y8_opt} /arch:SSE4.2 -maes -mpclmul -msha") set(e9_opt "${e9_opt} /arch:AVX -maes -mpclmul -msha -mrdrnd -mrdseed") set(l9_opt "${l9_opt} /arch:CORE-AVX2 -maes -mpclmul -msha -mrdrnd -mrdseed -mvaes -mvpclmulqdq") set(n0_opt "${n0_opt} /arch:CORE-AVX2 -maes -mavx512f -mavx512cd -mavx512pf -mavx512er -mpclmul -msha -mrdrnd -mrdseed") set(k0_opt "${k0_opt} /arch:SKYLAKE-AVX512 -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mpclmul -mrdrnd -mrdseed -madx") set(k1_opt "${k1_opt} /arch:ICELAKE-SERVER -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") cryptography-primitives-1.0.0/sources/cmake/windows/MSVC19.14.cmake000066400000000000000000000134331470420105600250430ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2018 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # # linker set(LINK_FLAG_STATIC_WINDOWS "/ignore:4221") # ignore warnings about empty obj files # Suppresses the display of the copyright banner when the compiler starts up and display of informational messages during compiling. set(LINK_FLAG_DYNAMIC_WINDOWS "/nologo") # Displays information about modules that are incompatible with safe structured exception handling when /SAFESEH isn't specified. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /VERBOSE:SAFESEH") # Disable incremental linking set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /INCREMENTAL:NO") # The /NODEFAULTLIB option tells the linker to remove one or more default libraries from the list of libraries it searches when resolving external references. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /NODEFAULTLIB") # Indicates that an executable was tested to be compatible with the Windows Data Execution Prevention feature. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /NXCOMPAT") # Specifies whether to generate an executable image that can be randomly rebased at load time. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /DYNAMICBASE") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /CETCOMPAT") if(${ARCH} MATCHES "ia32") # When /SAFESEH is specified, the linker will only produce an image if it can also produce a table of the image's safe exception handlers. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /SAFESEH") else() # The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /LARGEADDRESSAWARE") # This option modifies the header of an executable image, a .dll file or .exe file, to indicate whether ASLR with 64-bit addresses is supported. set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /HIGHENTROPYVA") endif(${ARCH} MATCHES "ia32") # Linker option to mitigate DLL hijacking vulnerability - removes CWD from the DLL search order set(LINK_FLAG_DYNAMIC_WINDOWS "${LINK_FLAG_DYNAMIC_WINDOWS} /DEPENDENTLOADFLAG:0x2000") if (MSVC_VERSION LESS_EQUAL 1800) # VS2013 # Link to C runtime, used in dlls set(LINK_LIB_STATIC_RELEASE libcmt) set(LINK_LIB_STATIC_DEBUG libcmtd) else() # Link to universal C runtime and MSVC runtime. Used in dlls. set(LINK_LIB_STATIC_RELEASE libcmt libucrt libvcruntime) set(LINK_LIB_STATIC_DEBUG libcmtd libucrtd libvcruntime) endif() # compiler set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LIBRARY_DEFINES}") # Suppresses the display of the copyright banner when the compiler starts up and display of informational messages during compiling. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo") # Prevents the compiler from searching for include files in directories specified in the PATH and INCLUDE environment variables. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /X") # Warning level = 4 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") # Changes all warnings to errors. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") # Detects some buffer overruns that overwrite a function's return address, exception handler address, or certain types of parameters. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /GS") # Controls how the members of a structure are packed into memory and specifies the same packing for all structures in a module. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zp16") # Allows the compiler to package individual functions in the form of packaged functions. Smaller resulting size. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Gy") # Causes the application to use the multithread, static version of the run-time library (debug version). set(CMAKE_C_FLAGS_DEBUG "/MTd") # The /Zi option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi") # Turns off all optimizations in the program and speeds compilation. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od") # Debug macro set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /DDEBUG") # Causes the application to use the multithread, static version of the run-time library. set(CMAKE_C_FLAGS_RELEASE "/MT") # Omits the default C runtime library name from the .obj file. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zl") # "Maximize Speed". Selects a predefined set of options that affect the size and speed of generated code. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O2") # /Ob2 is included in /O2 # No-debug macro set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /DNDEBUG") # Warnings = errors set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX") set(w7_opt "${w7_opt} /arch:SSE2") set(s8_opt "${s8_opt} /arch:SSE2") set(p8_opt "${p8_opt} /arch:SSE2") set(g9_opt "${g9_opt} /arch:AVX") set(h9_opt "${h9_opt} /arch:AVX2") set(m7_opt "${m7_opt}") set(n8_opt "${n8_opt}") set(y8_opt "${y8_opt}") set(e9_opt "${e9_opt} /arch:AVX") set(l9_opt "${l9_opt} /arch:AVX2") set(k0_opt "${k0_opt} /arch:AVX2") set(k1_opt "${k1_opt} /arch:AVX2") cryptography-primitives-1.0.0/sources/cmake/windows/common.cmake000066400000000000000000000022301470420105600251570ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # set(OS_DEFAULT_COMPILER Intel19.0.0) if(${ARCH} MATCHES "ia32") set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DWIN32 -D_ARCH_IA32") # _WIN32 is defined by a compiler else() set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DWIN32E -D_ARCH_EM64T") # _WIN32 and _WIN64 are defined by a compiler endif(${ARCH} MATCHES "ia32") #set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DBN_OPENSSL_DISABLE")cryptography-primitives-1.0.0/sources/dispatcher/000077500000000000000000000000001470420105600222445ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_common.py000066400000000000000000000043461470420105600257650ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib def readNextFunction(header, curLine, headerID): ## read next function with arguments ## find header ID macros FunName = '' FunArg = '' FunType = '' success = False while (curLine < len(header) and success == False): if not headerID and re.match( '\s*#\s*if\s*!\s*defined\s*\(\s*__IPP', header[curLine]): headerID= re.sub( '.*__IPP', '__IPP', header[curLine] ) headerID= re.sub( "\)", '', headerID) headerID= re.sub( '[\n\s]', '', headerID ) if re.match( '^\s*IPPAPI\s*\(.*', header[curLine] ) : FunStr= header[curLine]; FunStr= re.sub('\n','',FunStr) ## remove EOL symbols while not re.match('.*\)\s*\)\s*$', FunStr): ## concatenate string if string is not completed curLine= curLine+1 FunStr= FunStr+header[curLine] FunStr= re.sub('\n','',FunStr) ## remove EOL symbols FunStr= re.sub('\s+', ' ', FunStr) s= FunStr.split(',') ## Extract function name FunName= s[1] FunName= re.sub('\s', '', FunName) ## Extract function type FunType= re.sub( '.*\(', '', s[0] ) #FunType= re.sub(' ', '', FunType ) ## Extract function arguments FunArg= re.sub('.*\(.*,.+,\s*\(', '(', FunStr) FunArg= re.sub('\)\s*\)', ')', FunArg) success = True curLine = curLine + 1 return {'curLine':curLine, 'FunType':FunType, 'FunName':FunName, 'FunArg':FunArg, 'success':success }cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_lin32.nonpic.py000066400000000000000000000143411470420105600267050ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', required=True, help='Compiler') args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') compiler = args.compiler headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunName = "" FunArg = "" if(compiler == "GNU" or compiler == "Clang" or compiler == "IntelLLVM"): while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files ASM ################################################## ASMDISP= open( os.sep.join([OutDir, "jmp_" + FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] +".asm"]), 'w' ) # Symbol type setting for extern functions initially appeared in version 2.15 ASMDISP.write("%if ((__NASM_MAJOR__ > 2) || ((__NASM_MAJOR__ == 2) && (__NASM_MINOR__ > 14)))\n"); ASMDISP.write(" %xdefine elf_symbol_type :function\n"); ASMDISP.write("%else\n"); ASMDISP.write(" %xdefine elf_symbol_type\n"); ASMDISP.write("%endif\n"); for cpu in cpulist: ASMDISP.write("extern "+cpu+"_"+FunName+"%+elf_symbol_type\n") ASMDISP.write("extern ippcpJumpIndexForMergedLibs\n") ASMDISP.write("extern ippcpInit%+elf_symbol_type\n\n") ASMDISP.write(""" segment .data align 4 dd in_{FunName} arraddr_{FunName}: """.format(FunName=FunName)) size = 4 for cpu in cpulist: size = size + 4 ASMDISP.write(" dd "+cpu+"_"+FunName+"\n") ASMDISP.write(""" segment .text global {FunName}:function ({FunName}.LEnd{FunName} - {FunName}) in_{FunName}: {endbr32} call ippcpInit align 16 {FunName}: {endbr32} mov eax, dword [ippcpJumpIndexForMergedLibs] jmp dword [arraddr_{FunName} + eax*4] .LEnd{FunName}: """.format(FunName=FunName, size=size, endbr32='db 0xf3, 0x0f, 0x1e, 0xfb')) ASMDISP.close() else: while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write("""#include "ippcpdefs.h"\n\n""") DISP.write("typedef void (*IPP_PROC)(void);\n\n") DISP.write("extern int ippcpJumpIndexForMergedLibs;\n") DISP.write("extern IPP_CALL ippcpInit();\n\n") DISP.write("extern IppStatus in_"+FunName+FunArg+";\n") for cpu in cpulist: DISP.write("extern IppStatus "+cpu+"_"+FunName+FunArg+";\n") DISP.write(""" __asm( " .data"); __asm( " .align 4"); __asm( "arraddr:"); __asm( " .long in_{FunName}");""".format(FunName=FunName)) size = 4 for cpu in cpulist: size = size + 4 DISP.write("""\n__asm( " .long {cpu}_{FunName}");""".format(FunName=FunName, cpu=cpu)) DISP.write(""" __asm( " .type arraddr,@object"); __asm( " .size arraddr,{size}"); __asm( " .data");\n""".format(size=size)) DISP.write(""" #undef IPPAPI #define IPPAPI(type,name,arg) __declspec(naked) void name arg IPPAPI(IppStatus, {FunName},{FunArg}) {{ __asm( ".L0: mov ippcpJumpIndexForMergedLibs, %eax"); __asm( "mov (arraddr+4)(,%eax,4), %eax" ); __asm( "jmp *%eax" ); __asm( ".global in_{FunName}" ); __asm( "in_{FunName}:" ); {endbr32} __asm( "call ippcpInit" ); __asm( "jmp .L0" ); }} """.format(FunName=FunName, FunArg=FunArg, endbr32='__asm( ".byte 0xf3, 0x0f, 0x1e, 0xfb" );')) DISP.close() cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_lin32.py000066400000000000000000000152751470420105600254270ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', required=True, help='Compiler') args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') compiler = args.compiler headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunName = "" FunArg = "" if(compiler == "GNU" or compiler == "Clang" or compiler == "IntelLLVM"): while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files ASM ################################################## ASMDISP= open( os.sep.join([OutDir, "jmp_" + FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] +".asm"]), 'w' ) # Symbol type setting for extern functions initially appeared in version 2.15 ASMDISP.write("%if ((__NASM_MAJOR__ > 2) || ((__NASM_MAJOR__ == 2) && (__NASM_MINOR__ > 14)))\n"); ASMDISP.write(" %xdefine elf_symbol_type :function\n"); ASMDISP.write("%else\n"); ASMDISP.write(" %xdefine elf_symbol_type\n"); ASMDISP.write("%endif\n"); for cpu in cpulist: ASMDISP.write("extern "+cpu+"_"+FunName+"%+elf_symbol_type\n") ASMDISP.write("extern ippcpJumpIndexForMergedLibs\n") ASMDISP.write("extern ippcpInit%+elf_symbol_type\n\n") ASMDISP.write(""" segment .data align 4 dd .Lin_{FunName} .Larraddr_{FunName}: """.format(FunName=FunName)) for cpu in cpulist: ASMDISP.write(" dd "+cpu+"_"+FunName+"\n") ASMDISP.write(""" segment .text extern _GLOBAL_OFFSET_TABLE_ global {FunName}:function ({FunName}.LEnd{FunName} - {FunName}) .Lin_{FunName}: {endbr32} push ebx mov ebx, eax call ippcpInit wrt ..plt pop ebx align 16 {FunName}: {endbr32} call .L1 .L1: pop eax add eax, _GLOBAL_OFFSET_TABLE_ + $$ - .L1 wrt ..gotpc mov edx, [eax + ippcpJumpIndexForMergedLibs wrt ..got] mov edx, [edx] jmp dword [eax + edx*4 + .Larraddr_{FunName} wrt ..gotoff] .LEnd{FunName}: """.format(FunName=FunName, endbr32='db 0xf3, 0x0f, 0x1e, 0xfb')) ASMDISP.close() else: while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write("""#include "ippcpdefs.h"\n\n""") DISP.write("typedef void (*IPP_PROC)(void);\n\n") DISP.write("extern int ippcpJumpIndexForMergedLibs;\n") DISP.write("extern IPP_CALL ippcpInit();\n\n") DISP.write("extern IppStatus IPP_CALL in_"+FunName+FunArg+";\n") for cpu in cpulist: DISP.write("extern IppStatus IPP_CALL "+cpu+"_"+FunName+FunArg+";\n") DISP.write(""" __asm( " .data"); __asm( " .align 4"); __asm( "arraddr:"); __asm( " .long in_{FunName}");""".format(FunName=FunName)) size = 4 for cpu in cpulist: size = size + 4 DISP.write("""\n__asm( " .long {cpu}_{FunName}");""".format(FunName=FunName, cpu=cpu)) DISP.write(""" __asm( " .type arraddr,@object"); __asm( " .size arraddr,{size}"); __asm( " .data");\n""".format(size=size)) DISP.write(""" #undef IPPAPI #define IPPAPI(type,name,arg) __declspec(naked) void IPP_CALL name arg __declspec(naked) IPP_PROC {FunName}{FunArg} {{ __asm( ".L0: call .L1"); __asm( ".L1: pop %eax"); __asm( "add $_GLOBAL_OFFSET_TABLE_ - .L1, %eax" ); __asm( "movd ippcpJumpIndexForMergedLibs@GOT(%eax), %xmm0" ); __asm( "movd %xmm0, %edx" ); __asm( "mov (%edx), %edx" ); __asm( "mov (arraddr@GOTOFF+4)(%eax,%edx,4), %edx" ); __asm( "jmp *%edx" ); __asm( ".global in_{FunName}" ); __asm( "in_{FunName}:" ); {endbr32} __asm( "push %ebx" ); __asm( "mov %eax, %ebx" ); __asm( "call ippcpInit@PLT" ); __asm( "pop %ebx" ); __asm( "jmp .L0" ); }} """.format(FunName=FunName, FunArg=FunArg, endbr32='__asm( ".byte 0xf3, 0x0f, 0x1e, 0xfb" );')) DISP.close() cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_lin64.nonpic.py000066400000000000000000000135201470420105600267100ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', required=True, help='Compiler') args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') compiler = args.compiler headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunType = "" FunName = "" FunArg = "" if(compiler == "GNU" or compiler == "Clang" or compiler == "IntelLLVM"): while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files ASM ################################################## ASMDISP= open( os.sep.join([OutDir, "jmp_" + FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] +".asm"]), 'w' ) # Symbol type setting for extern functions initially appeared in version 2.15 ASMDISP.write("%if ((__NASM_MAJOR__ > 2) || ((__NASM_MAJOR__ == 2) && (__NASM_MINOR__ > 14)))\n"); ASMDISP.write(" %xdefine elf_symbol_type :function\n"); ASMDISP.write("%else\n"); ASMDISP.write(" %xdefine elf_symbol_type\n"); ASMDISP.write("%endif\n"); for cpu in cpulist: ASMDISP.write("extern "+cpu+"_"+FunName+"%+elf_symbol_type\n") ASMDISP.write("extern ippcpJumpIndexForMergedLibs\n") ASMDISP.write("extern ippcpSafeInit%+elf_symbol_type\n\n") ASMDISP.write(""" segment .data align 8 dq .Lin_{FunName} .Larraddr_{FunName}: """.format(FunName=FunName)) for cpu in cpulist: ASMDISP.write(" dq "+cpu+"_"+FunName+"\n") ASMDISP.write(""" segment .text global {FunName}:function ({FunName}.LEnd{FunName} - {FunName}) .Lin_{FunName}: {endbr64} call ippcpSafeInit align 16 {FunName}: {endbr64} movsxd rax, dword [ippcpJumpIndexForMergedLibs] lea r11, [rel .Larraddr_{FunName}] mov r11, qword [r11 + rax*8] jmp r11 .LEnd{FunName}: """.format(FunName=FunName, endbr64='db 0xf3, 0x0f, 0x1e, 0xfa')) ASMDISP.close() else: while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write("""#include "ippcp.h"\n\n#pragma warning(disable : 1478 1786) // deprecated\n\n""") DISP.write("typedef "+FunType+" (*IPP_PROC)"+FunArg+";\n\n") DISP.write("extern int ippcpJumpIndexForMergedLibs;\n") DISP.write("extern IppStatus ippcpSafeInit( void );\n\n") DISP.write("extern "+FunType+" in_"+FunName+FunArg+";\n") for cpu in cpulist: DISP.write("extern "+FunType+" "+cpu+"_"+FunName+FunArg+";\n") DISP.write("static IPP_PROC arraddr[] =\n{{\n (IPP_PROC)in_{}".format(FunName)) for cpu in cpulist: DISP.write(",\n (IPP_PROC)"+cpu+"_"+FunName+"") DISP.write("\n};") DISP.write(""" #undef IPPAPI #define IPPAPI(type,name,arg) __declspec(naked) type name arg IPPAPI({FunType}, {FunName},{FunArg}) {{ __asm{{ movsxd rax, dword ptr ippcpJumpIndexForMergedLibs mov rax, qword ptr [8*rax+8+arraddr] jmp rax }} }} IPPAPI({FunType}, in_{FunName},{FunArg}) {{ __asm{{ call ippcpSafeInit lea rax, {FunName} jmp rax }} }} """.format(FunType=FunType, FunName=FunName, FunArg=FunArg)) DISP.close() cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_lin64.py000066400000000000000000000137171470420105600254330ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', required=True, help='Compiler') args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') compiler = args.compiler headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunType = "" FunName = "" FunArg = "" if(compiler == "GNU" or compiler == "Clang" or compiler == "IntelLLVM"): while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files ASM ################################################## ASMDISP= open( os.sep.join([OutDir, "jmp_" + FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] +".asm"]), 'w' ) ASMDISP.write('%include "noexec_stack.inc"\n\n'); # Symbol type setting for extern functions initially appeared in version 2.15 ASMDISP.write("%if ((__NASM_MAJOR__ > 2) || ((__NASM_MAJOR__ == 2) && (__NASM_MINOR__ > 14)))\n"); ASMDISP.write(" %xdefine elf_symbol_type :function\n"); ASMDISP.write("%else\n"); ASMDISP.write(" %xdefine elf_symbol_type\n"); ASMDISP.write("%endif\n"); for cpu in cpulist: ASMDISP.write("extern "+cpu+"_"+FunName+"%+elf_symbol_type\n") ASMDISP.write("extern ippcpJumpIndexForMergedLibs\n") ASMDISP.write("extern ippcpSafeInit%+elf_symbol_type\n\n") ASMDISP.write(""" segment .data align 8 dq .Lin_{FunName} .Larraddr_{FunName}: """.format(FunName=FunName)) for cpu in cpulist: ASMDISP.write(" dq "+cpu+"_"+FunName+"\n") ASMDISP.write(""" segment .text global {FunName}:function ({FunName}.LEnd{FunName} - {FunName}) .Lin_{FunName}: {endbr64} call ippcpSafeInit wrt ..plt align 16 {FunName}: {endbr64} mov rax, qword [rel ippcpJumpIndexForMergedLibs wrt ..gotpc] movsxd rax, dword [rax] lea r11, [rel .Larraddr_{FunName}] mov r11, qword [r11+rax*8] jmp r11 .LEnd{FunName}: """.format(FunName=FunName, endbr64='db 0xf3, 0x0f, 0x1e, 0xfa')) ASMDISP.close() else: while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write("""#include "ippcp.h"\n\n#pragma warning(disable : 1478 1786) // deprecated\n\n""") DISP.write("typedef "+FunType+" (*IPP_PROC)"+FunArg+";\n\n") DISP.write("extern int ippcpJumpIndexForMergedLibs;\n") DISP.write("extern IppStatus ippcpSafeInit( void );\n\n") DISP.write("extern "+FunType+" in_"+FunName+FunArg+";\n") for cpu in cpulist: DISP.write("extern "+FunType+" "+cpu+"_"+FunName+FunArg+";\n") DISP.write("static IPP_PROC arraddr[] =\n{{\n (IPP_PROC)in_{}".format(FunName)) for cpu in cpulist: DISP.write(",\n (IPP_PROC)"+cpu+"_"+FunName+"") DISP.write("\n};") DISP.write(""" #undef IPPAPI #define IPPAPI(type,name,arg) __declspec(naked) type name arg IPPAPI({FunType}, {FunName},{FunArg}) {{ register unsigned long long i __asm__("rax"); i = (unsigned long long)arraddr[ippcpJumpIndexForMergedLibs+1]; _asm{{ jmp rax }} }} IPPAPI({FunType}, in_{FunName},{FunArg}) {{ __asm{{ call ippcpSafeInit mov rax, qword ptr [{FunName}] jmp rax }} }} """.format(FunType=FunType, FunName=FunName, FunArg=FunArg)) DISP.close() cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_mac64.py000066400000000000000000000132031470420105600253770ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', help='Compiler') # is not used args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') compiler = args.compiler headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunType = "" FunName = "" FunArg = "" if(compiler == "AppleClang"): while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files ASM ################################################## ASMDISP= open( os.sep.join([OutDir, "jmp_" + FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] +".asm"]), 'w' ) for cpu in cpulist: ASMDISP.write("extern "+"_"+cpu+"_"+FunName+"\n") ASMDISP.write("extern _ippcpJumpIndexForMergedLibs\n") ASMDISP.write("extern _ippcpSafeInit\n\n") ASMDISP.write(""" segment .data align 8 dq .Lin_{FunName} .Larraddr_{FunName}: """.format(FunName=FunName)) for cpu in cpulist: ASMDISP.write(" dq "+"_"+cpu+"_"+FunName+"\n") ASMDISP.write(""" segment .text global _{FunName} .Lin_{FunName}: {endbr64} call _ippcpSafeInit align 16 _{FunName}: {endbr64} mov rax, qword [rel _ippcpJumpIndexForMergedLibs wrt ..gotpcrel] movsxd rax, dword [rax] lea r11, [rel .Larraddr_{FunName}] mov r11, qword [r11+rax*8] jmp r11 .LEnd{FunName}: """.format(FunName=FunName, endbr64='db 0xf3, 0x0f, 0x1e, 0xfa')) ASMDISP.close() else: while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write("""#include "ippcp.h"\n\n#pragma warning(disable : 1478 1786) // deprecated\n\n""") DISP.write("typedef "+FunType+" (*IPP_PROC)"+FunArg+";\n\n") DISP.write("extern int ippcpJumpIndexForMergedLibs;\n") DISP.write("extern IppStatus ippcpSafeInit( void );\n\n") DISP.write("extern "+FunType+" in_"+FunName+FunArg+";\n") for cpu in cpulist: DISP.write("extern "+FunType+" "+cpu+"_"+FunName+FunArg+";\n") DISP.write("static IPP_PROC arraddr[] =\n{{\n (IPP_PROC)in_{}".format(FunName)) for cpu in cpulist: DISP.write(",\n (IPP_PROC)"+cpu+"_"+FunName+"") DISP.write("\n};") DISP.write(""" #undef IPPAPI #define IPPAPI(type,name,arg) __declspec(naked) type name arg IPPAPI({FunType}, {FunName},{FunArg}) {{ register unsigned long long i __asm__("rax"); i = (unsigned long long)arraddr[ippcpJumpIndexForMergedLibs+1]; __asm{{ jmp rax }} }} IPPAPI({FunType}, in_{FunName},{FunArg}) {{ __asm{{ call ippcpSafeInit mov rax, qword ptr [{FunName}] jmp rax }} }} """.format(FunType=FunType, FunName=FunName, FunArg=FunArg)) DISP.close() cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_win32.py000066400000000000000000000073511470420105600254360ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', help='Compiler') # is not used args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunName = "" FunType = "" FunArg = "" while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write("""#include "ippcpdefs.h" """) DISP.write("\n\ntypedef " + FunType + "(*IPP_PROC)(void);\n\n") DISP.write("extern int ippcpJumpIndexForMergedLibs;\n") DISP.write("extern IppStatus IPP_CALL ippcpInit();\n\n") DISP.write("extern " + FunType + " IPP_CALL in_"+FunName+FunArg+";\n") for cpu in cpulist: DISP.write("extern " + FunType + " IPP_CALL "+cpu+"_"+FunName+FunArg+";\n") DISP.write("static IPP_PROC arraddr[] =\n{{\n (IPP_PROC)in_{}".format(FunName)) for cpu in cpulist: DISP.write(",\n (IPP_PROC)"+cpu+"_"+FunName+"") DISP.write("\n};") DISP.write(""" #ifdef _MSC_VER #pragma warning(disable: 4100) // for MSVC, unreferenced param #endif #undef IPPAPI #define IPPAPI(type,name,arg) __declspec(naked) type __stdcall name arg IPPAPI({FunType}, {FunName},{FunArg}) {{ __asm {{mov eax, dword ptr ippcpJumpIndexForMergedLibs}} __asm {{mov eax, arraddr[eax*4+4]}} __asm {{jmp eax}} }} IPPAPI({FunType}, in_{FunName},{FunArg}) {{ __asm {{call ippcpInit}} __asm {{mov eax, dword ptr ippcpJumpIndexForMergedLibs }} __asm {{mov eax, arraddr[eax*4+4]}} __asm {{jmp eax}} }} """.format(FunType=FunType, FunName=FunName, FunArg=FunArg)) DISP.close() cryptography-primitives-1.0.0/sources/dispatcher/gen_disp_win64.py000066400000000000000000000063001470420105600254340ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Intel Cryptography Primitives Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', help='Compiler') # is not used args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunName = "" FunArg = "" while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] FunArg = result['FunArg'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher files: C file with inline asm ################################################## filename = "jmp_{}_{}".format(FunName, hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8]) DISP= open( os.sep.join([OutDir, filename + ".asm"]), 'w' ) for cpu in cpulist: DISP.write("extern "+cpu+"_"+FunName+"\n") DISP.write("extern ippcpJumpIndexForMergedLibs\n") DISP.write("extern ippcpSafeInit\n\n") DISP.write("segment data\n\n") DISP.write(" DQ in_"+FunName+"\n") DISP.write(FunName+"_arraddr:\n") for cpu in cpulist: DISP.write(" DQ "+cpu+"_"+FunName+"\n") DISP.write(""" segment text global {FunName} in_{FunName}: {endbr64} call ippcpSafeInit align 16 {FunName}: {endbr64} movsxd rax, dword [rel ippcpJumpIndexForMergedLibs] lea r10, [rel {FunName}_arraddr] mov r10, qword [r10+rax*8] jmp r10 """.format(FunName=FunName, endbr64='db 0xf3, 0x0f, 0x1e, 0xfa')) DISP.close() cryptography-primitives-1.0.0/sources/gen_cpu_spc_header/000077500000000000000000000000001470420105600237135ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/gen_cpu_spc_header/gen_cpu_spc_1cpu_header.py000066400000000000000000000056751470420105600310270ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import sys import os import datetime sys.path.append(os.path.join(sys.path[0], '../dispatcher')) from gen_disp_common import readNextFunction Header = sys.argv[1] OutDir = sys.argv[2] Header = os.path.abspath(Header) Filename = "" HDR= open(Header, 'r') h= HDR.readlines() HDR.close() headerID= False FunName = "" if not os.path.exists(OutDir): os.makedirs(OutDir) Filename="ippcp" Filenames=["h9", "p8", "s8", "w7", "e9", "k0", "k1", "l9", "m7", "n8", "y8", "g9"] DeprecatedCodePaths= { "n8" : "m7", # SSSE3 -> SSE3 64-bit "e9" : "y8", # AVX -> SSE4.2 64-bit "s8" : "w7", # SSSE3 -> SSE2 32-bit "g9" : "p8" # AVX -> SSE4.2 32-bit } for name in Filenames: OutFile = os.sep.join([OutDir, Filename + "_"+ name + ".h"]) OUT= open( OutFile, 'w' ) OUT.write("""/******************************************************************************* * Copyright {year} Intel Corporation * * 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. *******************************************************************************/ """.format(year=datetime.datetime.today().year)) if name in DeprecatedCodePaths: OUT.write(f""" #if !defined(_NO_IPP_DEPRECATED) #pragma message (\"code path {name} is deprecated, lower optimizations level {DeprecatedCodePaths[name]} is used\") #endif """) name = DeprecatedCodePaths[name] curLine = 0 isFunctionFound = True while (isFunctionFound): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] isFunctionFound = result['success'] if (isFunctionFound): OUT.write(f"#define {FunName} {name}_{FunName}\n") OUT.close() cryptography-primitives-1.0.0/sources/gen_cpu_spc_header/gen_cpu_spc_header.py000066400000000000000000000045611470420105600300700ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel(R) Cryptography Primitives Library # import sys import os import datetime sys.path.append(os.path.join(sys.path[0], '../dispatcher')) from gen_disp_common import readNextFunction Header = sys.argv[1] OutDir = sys.argv[2] Header = os.path.abspath(Header) Filename = "" HDR= open(Header, 'r') h= HDR.readlines() HDR.close() headerID= False FunName = "" if not os.path.exists(OutDir): os.makedirs(OutDir) Filename = "ippcp_cpuspc" OutFile = os.sep.join([OutDir, Filename + ".h"]) OUT= open( OutFile, 'w' ) OUT.write("""/******************************************************************************* * Copyright {year} Intel Corporation * * 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. *******************************************************************************/ """.format(year=datetime.datetime.today().year)) curLine = 0 isFunctionFound = True while (isFunctionFound): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] isFunctionFound = result['success'] if (isFunctionFound): OUT.write("#define " + FunName + " " + "OWNAPI(" + FunName + ")\n") OUT.close() cryptography-primitives-1.0.0/sources/include/000077500000000000000000000000001470420105600215415ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/include/asmdefs.inc000066400000000000000000000136031470420105600236610ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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 __ASMDEFS_INC__ %define __ASMDEFS_INC__ 1 %include "noexec_stack.inc" %assign _IPP_PX 0 ; pure C-code ia32 %assign _IPP_M5 1 ; Intel(R) Quark(TM) processor - ia32 %assign _IPP_W7 8 ; Intel(R) Streaming SIMD Extensions 2 - ia32 %assign _IPP_T7 16 ; Intel(R) Streaming SIMD Extensions 3 - ia32 %assign _IPP_V8 32 ; Supplemental Streaming SIMD Extensions 3 (SSSE3) %assign _IPP_S8 33 ; SSSE3 + MOVBE instruction - ia32 %assign _IPP_P8 64 ; Intel(R) Streaming SIMD Extensions 4.2 - ia32 %assign _IPP_G9 128 ; Intel(R) Advanced Vector Extensions - ia32 %assign _IPP_H9 256 ; Intel(R) Advanced Vector Extensions 2 - ia32 %assign _IPP_I0 512 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon Phi(TM) processor (formerly Knight Landing) - ia32 %assign _IPP_S0 1024 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon(R) processor (formerly Skylake) - ia32 %assign _IPP32E_PX _IPP_PX ; pure C-code x64 %assign _IPP32E_M7 32 ; Intel(R) Streaming SIMD Extensions 3 - intel64 %assign _IPP32E_U8 64 ; Supplemental Streaming SIMD Extensions 3 (SSSE3) - intel64 %assign _IPP32E_N8 65 ; SSSE3 + MOVBE instruction - intel64 %assign _IPP32E_Y8 128 ; Intel(R) Streaming SIMD Extensions 4.2 - intel64 %assign _IPP32E_E9 256 ; Intel(R) Advanced Vector Extensions - intel64 %assign _IPP32E_L9 512 ; Intel(R) Advanced Vector Extensions 2 - intel64 %assign _IPP32E_K0 2048 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon(R) processor (formerly Skylake) - intel64 %assign _IPP32E_K1 4096 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon(R) processor (formerly Icelake) - intel64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_PX %ifdef _M5 ; Intel(R) Quark(TM) processor - ia32 %assign _IPP _IPP_M5 %elifdef _W7 ; Intel(R) Streaming SIMD Extensions 2 - ia32 %assign _IPP _IPP_W7 %elifdef _T7 ; Intel(R) Streaming SIMD Extensions 3 - ia32 %assign _IPP _IPP_T7 %elifdef _V8 ; Supplemental Streaming SIMD Extensions 3 (SSSE3) %assign _IPP _IPP_V8 %elifdef _S8 ; SSSE3 + MOVBE instruction - ia32 %assign _IPP _IPP_S8 %elifdef _P8 ; Intel(R) Streaming SIMD Extensions 4.2 - ia32 %assign _IPP _IPP_P8 %elifdef _G9 ; Intel(R) Advanced Vector Extensions - ia32 %assign IPP_ALIGN_FACTOR 32 %assign _IPP _IPP_G9 %elifdef _H9 ; Intel(R) Advanced Vector Extensions 2 - ia32 %assign IPP_ALIGN_FACTOR 32 %assign _IPP _IPP_H9 %elifdef _S0 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon(R) processor (formerly Skylake) - ia32 %assign IPP_ALIGN_FACTOR 64 %assign _IPP _IPP_S0 %elifdef _M7 ; Intel(R) Streaming SIMD Extensions 3 - intel64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_M7 %elifdef _U8 ; Supplemental Streaming SIMD Extensions 3 (SSSE3) - intel64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_U8 %elifdef _N8 ; SSSE3 + MOVBE instruction - intel64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_N8 %elifdef _Y8 ; Intel(R) Streaming SIMD Extensions 4.2 - intel64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_Y8 %elifdef _E9 ; Intel(R) Advanced Vector Extensions - intel64 %assign IPP_ALIGN_FACTOR 32 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_E9 %elifdef _L9 ; Intel(R) Advanced Vector Extensions 2 - intel64 %assign IPP_ALIGN_FACTOR 32 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_L9 %elifdef _K0 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon(R) processor (formerly Skylake) - intel64 %assign IPP_ALIGN_FACTOR 64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_K0 %elifdef _K1 ; Intel(R) Advanced Vector Extensions 512 - Intel(R) Xeon(R) processor (formerly Icelake) - intel64 %assign IPP_ALIGN_FACTOR 64 %assign _IPP _IPP_PX %assign _IPP32E _IPP32E_K1 %else %assign _IPP _IPP_PX ; pure C-code %endif %if (_IPP > _IPP_H9) || (_IPP32E > _IPP32E_L9) %assign IPP_ALIGN_FACTOR 64 %elif (_IPP > _IPP_P8) || (_IPP32E > _IPP32E_Y8) %assign IPP_ALIGN_FACTOR 32 %else %assign IPP_ALIGN_FACTOR 16 %endif %ifidn __OUTPUT_FORMAT__, elf32 %assign IPP_BINARY_FORMAT 0 %elifidn __OUTPUT_FORMAT__, elf64 %assign IPP_BINARY_FORMAT 1 %elifidn __OUTPUT_FORMAT__, macho64 %assign IPP_BINARY_FORMAT 2 %elifidn __OUTPUT_FORMAT__, win32 %assign IPP_BINARY_FORMAT 3 %elifidn __OUTPUT_FORMAT__, win64 %assign IPP_BINARY_FORMAT 4 %else %fatal Unsupported output format: __OUTPUT_FORMAT__. Shall be: elf32, elf64, win32, win64, macho64 %endif %ifdef _MERGED_BLD %assign _OWN_MERGED_BLD 1 %endif ; _MERGED_BLD ; data compilation definitions: merged builds shall compile data only as ; part of one single object build to avoid multiple definition warnings at link time %ifndef _MERGED_BLD %assign _IPP_DATA 1 %else %if (_IPP == _IPP_P8) || (_IPP32E == _IPP32E_Y8) %assign _IPP_DATA 1 %endif %endif ; _MERGED_BLD ; Definitions of sizeof(type) %iassign ZWORD_size 64 ; zmm-word %iassign YWORD_size 32 ; ymm-word %iassign OWORD_size 16 ; octo-word %iassign TWORD_size 10 ; ten-bytes word %iassign QWORD_size 8 ; quad-word %iassign DWORD_size 4 ; double-word %iassign WORD_size 2 %iassign BYTE_size 1 %idefine YMMWORD YWORD %idefine XMMWORD OWORD %iassign YMMWORD_size YWORD_size %iassign XMMWORD_size OWORD_size %idefine sizeof(_x_) _x_%+_size %endif ;;;;;;;;;;;;;;;;;;;;;;;;;; End of file "asmdefs.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;; cryptography-primitives-1.0.0/sources/include/dispatcher.h000066400000000000000000000235051470420105600240450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2009 Intel Corporation * * 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. *************************************************************************/ // // Intel® Cryptography Primitives Library // #ifndef __DISPATCHER_H__ #define __DISPATCHER_H__ #if defined( __cplusplus ) extern "C" { #endif /* Intel® Cryptography Primitives Library and CPU features mask fitness. Implemented only for IA32 and Intel64 (emt) */ #if defined( _ARCH_IA32 ) #define M5_FM ( 0 ) #ifdef _IPP_QUARK #define PX_FM ( 0 ) #else #define PX_FM ( ippCPUID_MMX | ippCPUID_SSE ) #endif #define W7_FM ( PX_FM | ippCPUID_SSE2 ) #define V8_FM ( W7_FM | ippCPUID_SSE3 | ippCPUID_SSSE3 ) #define S8_FM ( V8_FM | ippCPUID_MOVBE ) #define P8_FM ( V8_FM | ippCPUID_SSE41 | ippCPUID_SSE42 | ippCPUID_AES | ippCPUID_CLMUL | ippCPUID_SHA ) #define G9_FM ( P8_FM | ippCPUID_AVX | ippAVX_ENABLEDBYOS | ippCPUID_RDRAND | ippCPUID_F16C ) #define H9_FM ( G9_FM | ippCPUID_MOVBE | ippCPUID_AVX2 | ippCPUID_ADCOX | ippCPUID_RDSEED | ippCPUID_PREFETCHW ) #define I0_FM ( H9_FM | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512PF | ippCPUID_AVX512ER | ippAVX512_ENABLEDBYOS ) #define S0_FM ( H9_FM | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512VL | ippCPUID_AVX512BW | ippCPUID_AVX512DQ | ippAVX512_ENABLEDBYOS ) #elif defined (_ARCH_EM64T) #define PX_FM ( ippCPUID_MMX | ippCPUID_SSE | ippCPUID_SSE2 ) #define M7_FM ( PX_FM | ippCPUID_SSE3 ) #define U8_FM ( M7_FM | ippCPUID_SSSE3 ) #define N8_FM ( U8_FM | ippCPUID_MOVBE ) #define Y8_FM ( U8_FM | ippCPUID_SSE41 | ippCPUID_SSE42 | ippCPUID_AES | ippCPUID_CLMUL | ippCPUID_SHA ) #define E9_FM ( Y8_FM | ippCPUID_AVX | ippAVX_ENABLEDBYOS | ippCPUID_RDRAND | ippCPUID_F16C ) #define L9_FM ( E9_FM | ippCPUID_MOVBE | ippCPUID_AVX2 | ippCPUID_ADCOX | ippCPUID_RDSEED | ippCPUID_PREFETCHW ) #define K0_FM ( L9_FM | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512VL | ippCPUID_AVX512BW | ippCPUID_AVX512DQ | ippAVX512_ENABLEDBYOS ) #elif defined (_ARCH_LRB2) #define PX_FM ( ippCPUID_KNC ) #else #error undefined architecture #endif #define PX_MSK ( 0 ) #define MMX_MSK ( ippCPUID_MMX ) #define SSE_MSK ( MMX_MSK | ippCPUID_SSE ) #define SSE2_MSK ( SSE_MSK | ippCPUID_SSE2 ) #define SSE3_MSK ( SSE2_MSK | ippCPUID_SSE3 ) #define SSSE3_MSK ( SSE3_MSK | ippCPUID_SSSE3 ) #define ATOM_MSK ( SSE3_MSK | ippCPUID_SSSE3 | ippCPUID_MOVBE ) #define SSE41_MSK ( SSSE3_MSK | ippCPUID_SSE41 ) #define SSE42_MSK ( SSE41_MSK | ippCPUID_SSE42 ) #define AVX_MSK ( SSE42_MSK | ippCPUID_AVX ) #define AVX2_MSK ( AVX_MSK | ippCPUID_AVX2 ) #define AVX3X_MSK ( AVX2_MSK | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512VL | ippCPUID_AVX512BW | ippCPUID_AVX512DQ ) #define AVX3M_MSK ( AVX2_MSK | ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512PF | ippCPUID_AVX512ER ) #define AVX3I_MSK ( AVX3X_MSK | ippCPUID_SHA | ippCPUID_AVX512VBMI | ippCPUID_AVX512VBMI2 | ippCPUID_AVX512IFMA | ippCPUID_AVX512GFNI | ippCPUID_AVX512VAES | ippCPUID_AVX512VCLMUL ) #if defined( _ARCH_IA32 ) && !defined( OSX32 ) enum lib_enum { LIB_W7=0, LIB_P8=1, LIB_H9=2, LIB_NOMORE }; #define LIB_PX LIB_W7 #elif defined( OSX32 ) enum lib_enum { LIB_P8=0, LIB_H9=1, LIB_NOMORE }; #define LIB_PX LIB_S8 #define LIB_W7 LIB_S8 #elif defined( _ARCH_EM64T ) && !defined( OSXEM64T ) enum lib_enum { LIB_M7=0, LIB_Y8=1, LIB_L9=2, LIB_K0=3, LIB_K1=4, LIB_NOMORE }; #define LIB_PX LIB_M7 #elif defined( OSXEM64T ) enum lib_enum { LIB_Y8=0, LIB_L9=1, LIB_K0=2, LIB_K1=3, LIB_NOMORE }; #define LIB_PX LIB_Y8 #define LIB_M7 LIB_Y8 #define LIB_N8 LIB_Y8 #elif defined( _ARCH_LRB2 ) enum lib_enum { LIB_PX=0, LIB_B2=1, LIB_NOMORE }; #define LIB_MIC LIB_B2 #else #error "lib_enum isn't defined!" #endif #if defined( _ARCH_IA32 ) #if defined( OSX32 ) /* OSX supports starting with Intel® architecture formerly codenamed Penryn only */ #define LIB_MMX LIB_S8 #define LIB_SSE LIB_S8 #define LIB_SSE2 LIB_S8 #define LIB_SSE3 LIB_S8 #define LIB_ATOM LIB_S8 #define LIB_SSSE3 LIB_S8 #define LIB_SSE41 LIB_S8 #define LIB_SSE42 LIB_P8 #define LIB_AVX LIB_G9 #define LIB_AVX2 LIB_H9 #define LIB_AVX3M LIB_H9 /* no ia32 library for Intel® Xeon® Phi(TM) processor (formerly Knight Landing) */ #define LIB_AVX3X LIB_H9 /* no ia32 library for Intel® Xeon® processor (formerly Skylake) */ #define LIB_AVX3I LIB_H9 /* no ia32 library for Intel® Xeon® processor (formerly Icelake) */ #else #define LIB_MMX LIB_W7 #define LIB_SSE LIB_W7 #define LIB_SSE2 LIB_W7 #define LIB_SSE3 LIB_W7 #define LIB_ATOM LIB_S8 #define LIB_SSSE3 LIB_S8 #define LIB_SSE41 LIB_S8 /* P8 is oriented for new Intel Atom® processor (formerly Silvermont) */ #define LIB_SSE42 LIB_P8 #define LIB_AVX LIB_G9 #define LIB_AVX2 LIB_H9 #define LIB_AVX3M LIB_H9 /* no ia32 library for Intel® Xeon® Phi(TM) processor (formerly Knight Landing) */ #define LIB_AVX3X LIB_H9 /* no ia32 library for Intel® Xeon® processor (formerly Skylake) */ #define LIB_AVX3I LIB_H9 /* no ia32 library for Intel® Xeon® processor (formerly Icelake) */ #endif #elif defined (_ARCH_EM64T) #if defined( OSXEM64T ) /* OSX supports starting PNR only */ #define LIB_MMX LIB_N8 #define LIB_SSE LIB_N8 #define LIB_SSE2 LIB_N8 #define LIB_SSE3 LIB_N8 #define LIB_ATOM LIB_N8 #define LIB_SSSE3 LIB_N8 #define LIB_SSE41 LIB_N8 #define LIB_SSE42 LIB_Y8 #define LIB_AVX LIB_E9 #define LIB_AVX2 LIB_L9 #define LIB_AVX3M LIB_L9 /* AVX2 code branch is used for Intel® Xeon® Phi(TM) processor (formerly Knight Landing) */ #define LIB_AVX3X LIB_K0 #define LIB_AVX3I LIB_K1 #else #define LIB_MMX LIB_M7 #define LIB_SSE LIB_M7 #define LIB_SSE2 LIB_M7 #define LIB_SSE3 LIB_M7 #define LIB_ATOM LIB_N8 #define LIB_SSSE3 LIB_N8 #define LIB_SSE41 LIB_N8 /* Y8 is oriented for new Intel Atom® processor (formerly Silvermont) */ #define LIB_SSE42 LIB_Y8 #define LIB_AVX LIB_E9 #define LIB_AVX2 LIB_L9 #define LIB_AVX3M LIB_L9 /* AVX2 code branch is used for Intel® Xeon® Phi(TM) processor (formerly Knight Landing) */ #define LIB_AVX3X LIB_K0 #define LIB_AVX3I LIB_K1 #endif #elif defined (_ARCH_LRB2) #define LIB_MIC LIB_B2 #endif //gres: #if defined( _IPP_DYNAMIC ) #if defined( _PCS ) #if defined( _ARCH_IA32 ) /* Describe Intel CPUs and libraries */ typedef enum{CPU_W7=0, CPU_P8, CPU_H9, CPU_NOMORE} cpu_enum; typedef enum{DLL_W7=0, DLL_P8, DLL_H9, DLL_NOMORE} dll_enum; /* New cpu can use some libraries for old cpu */ static const dll_enum dllUsage[][DLL_NOMORE+1] = { /* DLL_H9, DLL_P8, DLL_W7, DLL_NOMORE */ /*CPU_W7*/ { DLL_W7, DLL_NOMORE }, /*CPU_P8*/ { DLL_P8, DLL_W7, DLL_NOMORE }, /*CPU_H9*/ { DLL_H9, DLL_P8, DLL_W7, DLL_NOMORE } }; #elif defined (_ARCH_EM64T) /* Describe Intel CPUs and libraries */ typedef enum{CPU_M7=0, CPU_Y8, CPU_L9, CPU_K0, CPU_K1, CPU_NOMORE} cpu_enum; typedef enum{DLL_M7=0, DLL_Y8, DLL_L9, DLL_K0, DLL_K1, DLL_NOMORE} dll_enum; /* New cpu can use some libraries for old cpu */ static const dll_enum dllUsage[][DLL_NOMORE+1] = { /* DLL_K1, DLL_K0, DLL_L9, DLL_Y8, DLL_M7, DLL_NOMORE */ /*CPU_M7*/ { DLL_M7, DLL_NOMORE }, /*CPU_Y8*/ { DLL_Y8, DLL_M7, DLL_NOMORE }, /*CPU_L9*/ { DLL_L9, DLL_Y8, DLL_M7, DLL_NOMORE }, /*CPU_K0*/ { DLL_K0, DLL_L9, DLL_Y8, DLL_M7, DLL_NOMORE }, /*CPU_K1*/ { DLL_K1, DLL_K0, DLL_L9, DLL_Y8, DLL_M7, DLL_NOMORE } }; #endif #if defined( _PCS ) /* Names of the Intel libraries which can be loaded */ #if defined ( WIN32 ) static const _TCHAR* dllNames[DLL_NOMORE] = { _T(IPP_LIB_PREFIX()) _T("w7") _T(".dll"), _T(IPP_LIB_PREFIX()) _T("p8") _T(".dll"), _T(IPP_LIB_PREFIX()) _T("h9") _T(".dll") }; #elif defined(LINUX32) static const _TCHAR* dllNames[DLL_NOMORE] = { _T("lib") _T(IPP_LIB_PREFIX()) _T("w7.so"), _T("lib") _T(IPP_LIB_PREFIX()) _T("p8.so"), _T("lib") _T(IPP_LIB_PREFIX()) _T("h9.so") }; #elif defined( OSX32 ) static const _TCHAR* dllNames[DLL_NOMORE] = { _T("lib") _T(IPP_LIB_PREFIX()) _T("p8") _T(".dylib"), _T("lib") _T(IPP_LIB_PREFIX()) _T("h9") _T(".dylib") }; #elif defined( WIN32E ) static const _TCHAR* dllNames[DLL_NOMORE] = { _T(IPP_LIB_PREFIX()) _T("m7") _T(".dll"), _T(IPP_LIB_PREFIX()) _T("y8") _T(".dll"), _T(IPP_LIB_PREFIX()) _T("l9") _T(".dll"), _T(IPP_LIB_PREFIX()) _T("k0") _T(".dll"), _T(IPP_LIB_PREFIX()) _T("k1") _T(".dll") }; #elif defined( OSXEM64T ) static const _TCHAR* dllNames[DLL_NOMORE] = { _T("lib") _T(IPP_LIB_PREFIX()) _T("y8") _T(".dylib"), _T("lib") _T(IPP_LIB_PREFIX()) _T("l9") _T(".dylib"), _T("lib") _T(IPP_LIB_PREFIX()) _T("k0") _T(".dylib"), _T("lib") _T(IPP_LIB_PREFIX()) _T("k1") _T(".dylib") }; #elif defined( LINUX32E ) static const _TCHAR* dllNames[DLL_NOMORE] = { _T("lib") _T(IPP_LIB_PREFIX()) _T("m7.so"), _T("lib") _T(IPP_LIB_PREFIX()) _T("y8.so"), _T("lib") _T(IPP_LIB_PREFIX()) _T("l9.so"), _T("lib") _T(IPP_LIB_PREFIX()) _T("k0.so"), _T("lib") _T(IPP_LIB_PREFIX()) _T("k1.so") }; #endif #endif /* _PCS */ #else /*_IPP_DYNAMIC */ #endif #if defined( __cplusplus ) } #endif #endif /* __DISPATCHER_H__ */ cryptography-primitives-1.0.0/sources/include/fips_cert_internal/000077500000000000000000000000001470420105600254135ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/include/fips_cert_internal/bn_common.h000066400000000000000000000032661470420105600275420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 IPPCP_FIPS_CERT_BN_COMMON_H #define IPPCP_FIPS_CERT_BN_COMMON_H #include /** * \brief * * Performs initialization, sign and value setting for big number. * * Returns ippStsNoErr if both functions returns ippStsNoErr, obtained error status otherwise. * * \param[in] pbn pointer to big number being initialized * \param[in] max_word_len maximum length of integer big number in 32bit size * \param[in] sgn sign of big number * \param[in] pdata pointer to integer big number * \param[in] data_word_len length of integer big number in 32bit size * */ __IPPCP_INLINE IppStatus ippcp_init_set_bn(IppsBigNumState *pbn, int max_word_len, IppsBigNumSGN sgn, const Ipp32u *pdata, int data_word_len) { IppStatus sts; sts = ippsBigNumInit(max_word_len, pbn); if (sts != ippStsNoErr) return sts; sts = ippsSet_BN(sgn, data_word_len, pdata, pbn); return sts; } #endif // IPPCP_FIPS_CERT_BN_COMMON_H cryptography-primitives-1.0.0/sources/include/fips_cert_internal/common.h000066400000000000000000000100311470420105600270470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 IPPCP_FIPS_CERT_COMMON_H #define IPPCP_FIPS_CERT_COMMON_H #include "ippcpdefs.h" #include "pcpbnuimpl.h" #define IPPCP_AES_MSG_BYTE_LEN (64) #define IPPCP_AES_KEY128_BYTE_LEN (16) #define IPPCP_AES_KEY256_BYTE_LEN (32) #define IPPCP_IV128_BYTE_LEN (16) #define IPPCP_AES_ALIGNMENT ((int)sizeof(void *)) #define IPPCP_HASH_ALIGNMENT ((int)sizeof(void *)) #define IPPCP_HMAC_ALIGNMENT ((int)sizeof(void *)) #define IPPCP_GFP_ALIGNMENT ((int)sizeof(void *)) #define IPPCP_BN_ALIGNMENT ((int)sizeof(void*)) #define IPPCP_RSA_ALIGNMENT ((int)sizeof(BNU_CHUNK_T)) // convert bitsize into 32-bit wordsize #define IPPCP_BITSIZE_2_WORDSIZE(N_BITS) (((N_BITS) + 31) >> 5) #define IPPCP_BYTESIZE_2_BITSIZE(N_BYTES) ((N_BYTES) * 8) #define IPPCP_BYTESIZE_2_WORDSIZE(N_BYTES) (((N_BYTES) + 3) >> 2) // Feature of internal memory management #ifdef IPPCP_SELFTEST_USE_MALLOC #include // Internal memory management - free resource #define MEMORY_FREE(pBuffer, memMgmFlag) if(1 == internalMemMgm) { \ free((void*)pBuffer); \ pBuffer = NULL; \ } // If buffer is NULL, allocate memory #define BUF_CHECK_NULL_AND_ALLOC(pBuffer, memMgmFlag, size, ret_sts) \ if(NULL == pBuffer) { \ IPP_BADARG_RET((0 == size), ret_sts) \ memMgmFlag = 1; \ pBuffer = malloc((size_t)size); \ } #else // No memory management inside the test #define MEMORY_FREE(pBuffer, memMgmFlag) (void)internalMemMgm; // Return bad sts if buffer is NULL - we cannot allocate memory // IPPCP_SELFTEST_USE_MALLOC is not defined) #define BUF_CHECK_NULL_AND_ALLOC(pBuffer, memMgmFlag, size, ret_sts) \ (void)internalMemMgm; \ IPP_BADARG_RET((NULL == pBuffer), ret_sts); #endif #define MEMORY_FREE_2(pBuffer1, pBuffer2, memMgmFlag) \ { MEMORY_FREE(pBuffer1, memMgmFlag) \ MEMORY_FREE(pBuffer2, memMgmFlag) } #define MEMORY_FREE_3(pBuffer1, pBuffer2, pBuffer3, memMgmFlag) \ { MEMORY_FREE(pBuffer1, memMgmFlag) \ MEMORY_FREE(pBuffer2, memMgmFlag) \ MEMORY_FREE(pBuffer3, memMgmFlag) } /** * \brief * * Comparison of two byte arrays. * * Compares byte arrays, returns 1 if arrays are equal, 0 otherwise. * * NOTE: This function should not be used for a secure memory comparison (i.e. constant time). * * \param[in] p1 pointer to first byte array * \param[in] p1_byte_len length of first array in bytes * \param[in] p2 pointer to second byte array * \param[in] p2_byte_len length of second array in bytes * */ #define ippcp_is_mem_eq OWNAPI(ippcp_is_mem_eq) IPP_OWN_DECL (int, ippcp_is_mem_eq, (const Ipp8u *p1, Ipp32u p1_byte_len, const Ipp8u *p2, Ipp32u p2_byte_len)) #endif // IPPCP_FIPS_CERT_COMMON_H cryptography-primitives-1.0.0/sources/include/ia_32e.inc000066400000000000000000000371431470420105600233060ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_common.inc" %include "utils.inc" %ifndef __IA_32E_INC__ %define __IA_32E_INC__ 1 %ifndef LINUX32E %ifndef WIN32E %fatal \ LINUX32E or WIN32E - Linux ABI (parameter passing in rdi, rsi, rdx, rcx, r8, r9...) %endif %endif ; Force RIP-relative addressing ; default rel %ifdef LINUX32E %ifdef STACK_ABI %assign IPP_ABI 2 %else %assign IPP_ABI 3 %endif %endif %ifdef WIN32E %ifdef STACK_ABI %assign IPP_ABI 1 %else %assign IPP_ABI 0 %endif %endif ; Decorates function name with appropriate CPU prefix (for the merged library). ; The macro is context-dependent and returns decorated name in the %$decorated_func_name ; context variable along with the decoration length in the %$decoration_length context variable. %macro CPU_PREFIX_DECORATE 1.nolist %ifnctx _CPU_PREFIX_DECORATE_CTX_ %fatal "Not in the context: _CPU_PREFIX_DECORATE_CTX_" %endif ; Add CPU-specific suffix for the dispatched library %ifdef _OWN_MERGED_BLD %if (_IPP32E == _IPP32E_PX) %xdefine %%func_name mx_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_M7) %xdefine %%func_name m7_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_U8) %xdefine %%func_name u8_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_N8) %xdefine %%func_name n8_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_Y8) %xdefine %%func_name y8_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_E9) %xdefine %%func_name e9_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_L9) %xdefine %%func_name l9_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_K0) %xdefine %%func_name k0_%1 %assign %%decoration_length 3 %endif %if (_IPP32E == _IPP32E_K1) %xdefine %%func_name k1_%1 %assign %%decoration_length 3 %endif %else %xdefine %%func_name %1 %assign %%decoration_length 0 %endif %ifndef %%func_name %fatal "CPU_PREFIX_DECORATE: unknown decoration for : _IPP32E = " _IPP32E %endif %xdefine %$decorated_func_name %[%%func_name] %assign %$decoration_length %%decoration_length %endmacro ; Lists of non-volatile registers that needs to be preserved in a function call %define NONVOLATILE_REGS_LIN64_GPR rbx,rbp,r12,r13,r14,r15 %define NONVOLATILE_REGS_WIN64_GPR rbx,rbp,r12,r13,r14,r15,rsi,rdi %define NONVOLATILE_REGS_WIN64_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 %define NONVOLATILE_REGS_WIN64_YMM ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13,ymm14,ymm15 ; Saves non-volatile GPR registers on stack. ; Input - list of used registers. %macro USES_GPR 1+.nolist %assign GPR_FRAME 0 %define GPR_CUR %if (IPP_ABI < 2) ; Win64 %define %%nonvolatile_regs_list %[NONVOLATILE_REGS_WIN64_GPR] %else ; Lin64 %define %%nonvolatile_regs_list %[NONVOLATILE_REGS_LIN64_GPR] %endif BEGIN_INTERSECT INTERSECT {%1},{%%nonvolatile_regs_list} ; List of non-volatile GPR registers in the order they will be pushed on stack %xdefine GPR_CUR %[%$intersection] %assign GPR_FRAME %$cardinality * 8 END_INTERSECT ; Push non-volatile GPRs on stack FOREACH GPR_CUR,{push} %endmacro ; Restore preliminary saved by USES_GPR non-volatile GPR registers from the stack. ; The macro shall be called after function processing. %macro REST_GPR 0.nolist %ifndef GPR_CUR %fatal "REST_GPR: no GPR_CUR defined" %endif ; Pop saved registers from the stack RFOREACH GPR_CUR,{pop} %endmacro ; Saves XMM register on stack (SSE version). ; An offset from RSP, where the register will be saved, shall be provided in the calling context. %macro PUSH_XMM_REG 1.nolist movdqa [rsp + %$rsp_offset], %1 %assign %$rsp_offset %$rsp_offset + 16 %endmacro ; Saves non-volatile XMM registers on stack and allocates stack size for ; local variables if needed. ; Input - list of used registers (can be empty). %macro USES_XMM 0-*.nolist ; LOCAL_FRAME - stack size required for all local variables of the procedure. Shall be defined before USES_XMM macro call if ; local variables are used in the procedure. %ifndef LOCAL_FRAME %assign LOCAL_FRAME 0 %endif ; to align size for local variables size on 16-bytes %assign LOCAL_FRAME (LOCAL_FRAME + 15) & (-16) %assign S_FRAME 0 %define XMM_CUR ; Convert parameters to the list variable if there are arguments %if (%0 > 0) %xdefine %%param_list %1 %rotate 1 %rep %0-1 %xdefine %%param_list %[%%param_list],%1 %rotate 1 %endrep %endif %if (IPP_ABI < 2) ; Win64 %assign %%T_FRAME 0 BEGIN_INTERSECT INTERSECT {%%param_list},{%[NONVOLATILE_REGS_WIN64_XMM]} %define XMM_CUR %[%$intersection] %assign %%T_FRAME %$cardinality * 16 END_INTERSECT ; Adjust offset depending on function frame %if ((%%T_FRAME > 0) || (LOCAL_FRAME > 0)) %assign S_FRAME %%T_FRAME + LOCAL_FRAME %if (((S_FRAME + GPR_FRAME ) & 8) == 0) %assign S_FRAME S_FRAME + 8 %endif %endif ; Allocate space on stack and push XMM registers %if (S_FRAME > 0) sub rsp, S_FRAME %push %?? %assign %$rsp_offset LOCAL_FRAME FOREACH %[XMM_CUR],{PUSH_XMM_REG} %pop %?? %endif %else ; Linux x86_64 ABI does not count MM registers as non-volatile, so they do not need to be ; preserved, so just allocate stack space for local variables and duplicated register parameters if needed. %if (IPP_ABI == 2) ; LINUX32S %assign S_FRAME LOCAL_FRAME + 48 ; 48 = 6 * 8 - stack frame for 6 register inputs %if (((S_FRAME + GPR_FRAME) & 8 ) == 0) %assign S_FRAME S_FRAME + 8 %endif %assign INP_FRAME S_FRAME - 48 ; for Linux32s-key stack-frame for 6 registers inputs %else ; LINUX32E %if (LOCAL_FRAME > 0) %assign S_FRAME LOCAL_FRAME %if (((S_FRAME + GPR_FRAME) & 8 ) == 0) %assign S_FRAME S_FRAME + 8 %endif %endif %endif %if (S_FRAME > 0) sub rsp, S_FRAME %endif %endif %endmacro ; Pop input list of XMM registers from the stack. ; The offset from RSP, where the registers will be taken from, shall be provided in the calling context. %macro POP_XMM_REG 1.nolist movdqa %1, [rsp + %$rsp_offset] %assign %$rsp_offset %$rsp_offset + 16 %endmacro ; Restore preliminary saved by USES_XMM non-volatile XMM registers from the stack. ; The macro shall be called after function processing. %macro REST_XMM 0.nolist %if (IPP_ABI < 2) %if (S_FRAME > 0) %push %?? %assign %$rsp_offset LOCAL_FRAME FOREACH %[XMM_CUR],{POP_XMM_REG} %pop %?? %endif %endif %if (S_FRAME > 0) add rsp, S_FRAME %endif %if (_IPP32E >= _IPP32E_E9) vzeroupper %endif %endmacro ; Saves XMM or YMM register on stack (AVX version). ; An offset from RSP, where the registers will be saved, shall be provided in the calling context. %macro PUSH_XMM_AVX_REG 1.nolist ; Process registers depending on type %defstr %%reg_str %1 ; convert register token to the string %substr %%reg_type %%reg_str 1, 3 ; take first 3 elems of the string %ifidni %%reg_type, 'xmm' vmovdqa oword [rsp + %$rsp_offset], %1 %assign %$rsp_offset %$rsp_offset + 16 %elifidni %%reg_type, 'ymm' vmovdqu ymmword [rsp + %$rsp_offset], %1 %assign %$rsp_offset %$rsp_offset + 32 %else %fatal PUSH_XMM_AVX_REG: inconsistent usage - only XMM/YMM registers supported, found: %%reg_type %endif %endmacro ; Saves non-volatile XMM/YMM registers on stack and allocates stack size for ; local variables if needed (AVX version). ; Input - list of used registers (can be empty). %macro USES_XMM_AVX 0-*.nolist ; LOCAL_FRAME - stack size required for all local variables of the procedure. Shall be defined before USES_XMM macro call if ; local variables are used in the procedure. %ifndef LOCAL_FRAME %assign LOCAL_FRAME 0 %endif ; to align size for local variables size on 16-bytes %assign LOCAL_FRAME (LOCAL_FRAME + 15) & (-16) %assign S_FRAME 0 %define XMM_CUR %define YMM_CUR ; Convert parameters to the list variable if there are arguments %if (%0 > 0) %xdefine %%param_list %1 %rotate 1 %rep %0-1 %xdefine %%param_list %[%%param_list],%1 %rotate 1 %endrep %endif %if (IPP_ABI < 2) ; Win64 %assign %%T_FRAME 0 ; Process XMM registers BEGIN_INTERSECT INTERSECT {%%param_list},{%[NONVOLATILE_REGS_WIN64_XMM]} %define XMM_CUR %[%$intersection] %assign %%T_FRAME %$cardinality * 16 END_INTERSECT ; Process YMM registers BEGIN_INTERSECT INTERSECT {%%param_list},{%[NONVOLATILE_REGS_WIN64_YMM]} %define YMM_CUR %[%$intersection] %assign %%T_FRAME %%T_FRAME + %$cardinality * 32 END_INTERSECT ; Adjust offset depending on function frame %if ((%%T_FRAME > 0) || (LOCAL_FRAME > 0)) %assign S_FRAME %%T_FRAME + LOCAL_FRAME %if (((S_FRAME + GPR_FRAME ) & 8) == 0) %assign S_FRAME S_FRAME + 8 %endif %endif ; Allocate space on stack and push registers %if (S_FRAME > 0) sub rsp, S_FRAME CONCATENATE {%[XMM_CUR]},{%[YMM_CUR]},%%XMM_YMM_CUR %push %?? %assign %$rsp_offset LOCAL_FRAME FOREACH %[%%XMM_YMM_CUR],{PUSH_XMM_AVX_REG} %pop %?? %endif %else ; Linux x86_64 ABI does not count MM registers as non-volatile, so they do not need to be ; preserved, so just allocate stack space for local variables and duplicated register parameters if needed. %if (IPP_ABI == 2) ; LINUX32S %assign S_FRAME LOCAL_FRAME + 48 ; 48 = 6 * 8 - stack frame for 6 register inputs %if (((S_FRAME + GPR_FRAME) & 8 ) == 0) %assign S_FRAME S_FRAME + 8 %endif %assign INP_FRAME S_FRAME - 48 ; for Linux32s-key stack-frame for 6 registers inputs %else ; LINUX32E %if (LOCAL_FRAME > 0) %assign S_FRAME LOCAL_FRAME %if (((S_FRAME + GPR_FRAME) & 8 ) == 0) %assign S_FRAME S_FRAME + 8 %endif %endif %endif %if (S_FRAME > 0) sub rsp, S_FRAME %endif %endif %endmacro ; Pop XMM or YMM register from the stack. ; The offset from RSP, where the registers will be taken from, shall be provided in the calling context. %macro POP_XMM_AVX_REG 1.nolist ; Process registers depending on type %defstr %%reg_str %1 ; convert register token to the string %substr %%reg_type %%reg_str 1, 3 ; take first 3 elems of the string %ifidni %%reg_type, 'xmm' vmovdqa %1, oword [rsp + %$rsp_offset] %assign %$rsp_offset %$rsp_offset + 16 %elifidni %%reg_type, 'ymm' vmovdqu %1, ymmword [rsp + %$rsp_offset] %assign %$rsp_offset %$rsp_offset + 32 %else %fatal POP_XMM_AVX_REG: inconsistent usage - only XMM/YMM registers supported, found: %%reg_type %endif %endmacro ; Restore preliminary saved by USES_XMM_AVX non-volatile XMM/YMM registers from the stack. ; The macro shall be called after function processing. %macro REST_XMM_AVX 0.nolist %if (IPP_ABI < 2) %if (S_FRAME > 0) CONCATENATE {%[XMM_CUR]},{%[YMM_CUR]},%%XMM_YMM_CUR %push %?? %assign %$rsp_offset LOCAL_FRAME FOREACH %[%%XMM_YMM_CUR],{POP_XMM_AVX_REG} %pop %?? %endif %endif %if (S_FRAME > 0) add rsp, S_FRAME %endif vzeroupper %endmacro ; Helper macro to align different ABIs parameters for uniform usage %macro COMP_ABI 1.nolist %if (IPP_ABI == 0) ;; if defined WIN32E %if (%1 > 0) mov rdi, rcx ;; ARG_1 %endif %if (%1 > 1) mov rsi, rdx ;; ARG_2 %endif %if (%1 > 2) mov rdx, r8 ;; ARG_3 %endif %if (%1 > 3) mov rcx, r9 ;; ARG_4 %endif %if (%1 > 4) mov r8, [rsp + S_FRAME + GPR_FRAME + 40] ;; ARG_5 %endif %if (%1 > 5) mov r9, [rsp + S_FRAME + GPR_FRAME + 48] ;; ARG_6 %endif %if (%1 > 6) %assign FIRST_P S_FRAME + GPR_FRAME + 56 ;; ARG_7 %assign ARG_7 S_FRAME + GPR_FRAME + 56 %endif %endif %if (IPP_ABI == 1) ;; if defined WIN32S %assign FIRST_P S_FRAME + GPR_FRAME + 8 %if (%1 > 0) mov [rsp + FIRST_P],rcx %assign ARG_1 FIRST_P %endif %if (%1 > 1) mov [rsp + FIRST_P + 8],rdx %assign ARG_2 ARG_1 + 8 %endif %if (%1 > 2) mov [rsp + FIRST_P + 16],r8 %assign ARG_3 ARG_2 + 8 %endif %if (%1 > 3) mov [rsp + FIRST_P + 24],r9 %assign ARG_4 ARG_3 + 8 %endif %if (%1 > 4) %assign ARG_5 ARG_4 + 8 %endif %if (%1 > 5) %assign ARG_6 ARG_5 + 8 %endif %if (%1 > 6) %assign ARG_7 ARG_6 + 8 ;; ARG_7 %endif %endif %if (IPP_ABI == 2) ;; if defined LINUX32S %assign FIRST_P INP_FRAME %if (%1 > 0) mov [rsp + FIRST_P],rdi %assign ARG_1 FIRST_P %endif %if (%1 > 1) mov [rsp + FIRST_P + 8],rsi %assign ARG_2 ARG_1 + 8 %endif %if (%1 > 2) mov [rsp + FIRST_P + 16],rdx %assign ARG_3 ARG_2 + 8 %endif %if (%1 > 3) mov [rsp + FIRST_P + 24],rcx %assign ARG_4 ARG_3 + 8 %endif %if (%1 > 4) mov [rsp + FIRST_P + 32],r8 %assign ARG_5 ARG_4 + 8 %endif %if (%1 > 5) mov [rsp + FIRST_P + 40],r9 %assign ARG_6 ARG_5 + 8 %endif %if (%1 > 6) %assign ARG_7 S_FRAME+GPR_FRAME+8 %endif %endif %if (IPP_ABI == 3) %if (%1 > 6) ;; ARG_1 = rdi ARG_2 = rsi ARG_3 = rdx ARG_4 = rcx ARG_5 = r8 ARG_6 = r9 %assign FIRST_P S_FRAME + GPR_FRAME + 8 ;; ARG_7 %assign ARG_7 S_FRAME + GPR_FRAME + 8 %endif %endif %if (%1 > 7) %assign ARG_8 ARG_7 + 8 ;; ARG_8 %endif %if (%1 > 8) %assign ARG_9 ARG_8 + 8 ;; ARG_9 %endif %if (%1 > 9) %assign ARG_10 ARG_9 + 8 ;; ARG_10 %endif %if (%1 > 10) %assign ARG_11 ARG_10 + 8 ;; ARG_11 %endif %if (%1 > 11) %assign ARG_12 ARG_11 + 8 ;; ARG_12 %endif %if (%1 > 12) %assign ARG_13 ARG_12 + 8 ;; ARG_13 %endif %if (%1 > 13) %assign ARG_14 ARG_13 + 8 ;; ARG_14 %endif %if (%1 > 14) %assign ARG_15 ARG_14 + 8 ;; ARG_15 %endif %if (%1 > 15) %assign ARG_16 ARG_15 + 8 ;; ARG_16 %endif %if (%1 > 16) %assign ARG_17 ARG_16 + 8 ;; ARG_17 %endif %if (%1 > 17) %assign ARG_18 ARG_17 + 8 ;; ARG_18 %endif %endmacro %macro LD_ADDR 2.nolist %xdefine %%reg %1 %xdefine %%addr %2 %ifdef xxIPP_PIC call %%LABEL %%LABEL: pop %%reg sub %%reg, %%LABEL-%%addr %else lea %%reg, [%%addr] %endif %endmacro %endif cryptography-primitives-1.0.0/sources/include/ia_common.inc000066400000000000000000000141341470420105600242000ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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 __IA_COMMON_INC__ %define __IA_COMMON_INC__ 1 ; use multi-byte nop's sequences to align loops and jmp's when threshold is reached %use smartalign ALIGNMODE p6,16 ; Declares function, sets visibility and binding and adds __cdecl decoration when needed. %macro DECLARE_FUNC 2-3.nolist %xdefine %%func_name %1 %xdefine %%visibility %2 %xdefine %%binding %3 %ifctx _DECLARE_FUNC_CTX_ %fatal "DECLARE_FUNC: already in the context, need to call ENDFUNC" %endif ; Accepted visibility values are PUBLIC and PRIVATE %ifnidni %%visibility, PUBLIC %ifnidni %%visibility, PRIVATE %fatal Function %%func_name visibility is not properly defined. Shall be: PRIVATE or PUBLIC. %endif %endif ; Accepted binding values are WEAK or STRONG (default) %ifnempty %%binding %ifnidni %%binding, WEAK %ifnidni %%binding, STRONG %%fatal Function %%func_name binding is not properly defined. Shall be: WEAK or STRONG. %endif %endif %endif ; Function decoration length %assign %%decoration_length 0 ; The __cdecl calling convention name decoration (to have interoperability with C). ; Only public functions are decorated %ifidni %%visibility, PUBLIC %if ((IPP_BINARY_FORMAT == 2) || (IPP_BINARY_FORMAT == 3)) ; WIN32 or OSXEM64T %xdefine %%func_name _%[%%func_name] %assign %%decoration_length %%decoration_length+1 %endif %endif ; If current macro is called from IPPASM macro, then function might be decorated by CPU-prefix %ifctx _IPPASM_CTX_ %assign %%decoration_length %%decoration_length + %$decoration_length ; %$decoration_length belongs to _IPPASM_CTX_ %endif %push _DECLARE_FUNC_CTX_ ; setup context variables to use in ENDFUNC %xdefine %$func_name_ctx %%func_name %assign %$decoration_length %%decoration_length ; %$decoration_length belongs to _DECLARE_FUNC_CTX_ %ifidn %%visibility, PUBLIC %if (IPP_BINARY_FORMAT < 2) ; LINUX32 or LINUX32E %ifnempty %%binding global %%func_name:function %%binding (%%func_name%+.LEnd_%+%%func_name - %%func_name) %else global %%func_name:function (%%func_name%+.LEnd_%+%%func_name - %%func_name) %endif %else global %%func_name %endif %endif %%func_name: ; CET enabling (macOS not supported) %if ((IPP_BINARY_FORMAT == 0) || (IPP_BINARY_FORMAT == 3)) ; elf32/win32 db 0F3h, 00Fh, 01Eh, 0FBh ; endbr32 %elif ((IPP_BINARY_FORMAT == 1) || (IPP_BINARY_FORMAT == 4)) ; elf64/win64 db 0F3h, 00Fh, 01Eh, 0FAh ; endbr64 %endif %endmacro ; Calls assembler function declared by DECLARE_FUNC ; Default visibility is PRIVATE (affects decoration) %macro CALL_FUNC 1-2.nolist PRIVATE %xdefine %%func_name %1 %xdefine %%visibility %2 ; Accepted visibility values are PUBLIC and PRIVATE %ifnidni %%visibility, PUBLIC %ifnidni %%visibility, PRIVATE %fatal Function %%func_name visibility is not properly defined. Shall be: PRIVATE or PUBLIC. %endif %endif ; __cdecl on WIN32/OSXEM64T obligates to have undersore prefix decoration. ; Only PUBLIC functions are decorated. %ifidni %%visibility, PUBLIC %if ((IPP_BINARY_FORMAT == 2) || (IPP_BINARY_FORMAT == 3)) ; WIN32 or OSXEM64T %xdefine %%func_name _%1 %endif %endif call %%func_name %endmacro ; Declares function decorated by appropriate CPU prefix (for the merged library) ; Default visibility (if not defined) is PUBLIC. %macro IPPASM 1-2.nolist PUBLIC %xdefine %%func_name %1 %xdefine %%visibility %2 %ifctx _IPPASM_CTX_ %fatal "IPPASM: already in the context, need to call ENDFUNC" %endif %push _IPPASM_CTX_ %push _CPU_PREFIX_DECORATE_CTX_ CPU_PREFIX_DECORATE %%func_name %xdefine %%func_name %$decorated_func_name %assign %$$decoration_length %$decoration_length %pop _CPU_PREFIX_DECORATE_CTX_ DECLARE_FUNC %%func_name, %%visibility %endmacro ; Calls assembler function declared by IPPASM ; Default visibility is PRIVATE (affects decoration) %macro CALL_IPPASM 1-2.nolist PRIVATE %xdefine %%func_name %1 %xdefine %%visibility %2 ; Accepted visibility values are PUBLIC and PRIVATE %ifnidni %%visibility, PUBLIC %ifnidni %%visibility, PRIVATE %fatal Function %%func_name visibility is not properly defined. Shall be: PRIVATE or PUBLIC. %endif %endif %push _CPU_PREFIX_DECORATE_CTX_ CPU_PREFIX_DECORATE %%func_name %xdefine %%func_name %$decorated_func_name %pop _CPU_PREFIX_DECORATE_CTX_ CALL_FUNC %%func_name,%%visibility %endmacro ; End function macro - required to be called after IPPASM or DECLARE_FUNC macro invocation. %macro ENDFUNC 1.nolist %xdefine %%func_name %1 %ifnctx _DECLARE_FUNC_CTX_ %fatal "Not in the context: _DECLARE_FUNC_CTX_" %endif ; Cross-check of context variable with macro parameter %defstr %%func_name_str %%func_name %defstr %%func_name_ctx_str %$func_name_ctx %substr %%func_name_ctx_str_not_decorated %%func_name_ctx_str %[%$decoration_length+1],-1 ; remove decoration (first X symbols) %ifnidn %%func_name_str,%%func_name_ctx_str %ifnidn %%func_name_str,%%func_name_ctx_str_not_decorated %fatal ENDFUNC: function name [%%func_name] does match context: [%$func_name_ctx] %endif %endif ; Add local label to be able calculate function size ; Take function name from the context (real declaration name) .LEnd_%+%$func_name_ctx: %pop _DECLARE_FUNC_CTX_ %ifctx _IPPASM_CTX_ %pop _IPPASM_CTX_ %endif %endmacro %endif cryptography-primitives-1.0.0/sources/include/ia_emm.inc000066400000000000000000000064441470420105600234730ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_common.inc" %include "utils.inc" ; Decorates function name with appropriate CPU prefix (for the merged library). ; The macro is context-dependent and returns decorated name in the %$decorated_func_name ; context variable. %macro CPU_PREFIX_DECORATE 1.nolist %ifnctx _CPU_PREFIX_DECORATE_CTX_ %fatal "Not in the context: _CPU_PREFIX_DECORATE_CTX_" %endif ; Add CPU-specific suffix for the dispatched library %ifdef _OWN_MERGED_BLD %if (_IPP == _IPP_PX) %xdefine %%func_name px_%1 %assign %%decoration_length 3 %endif %if (_IPP == _IPP_W7) %xdefine %%func_name w7_%1 %assign %%decoration_length 3 %endif %if (_IPP == _IPP_V8) %xdefine %%func_name v8_%1 %assign %%decoration_length 3 %endif %if (_IPP == _IPP_S8) %xdefine %%func_name s8_%1 %assign %%decoration_length 3 %endif %if (_IPP == _IPP_P8) %xdefine %%func_name p8_%1 %assign %%decoration_length 3 %endif %if (_IPP == _IPP_G9) %xdefine %%func_name g9_%1 %assign %%decoration_length 3 %endif %if (_IPP == _IPP_H9) %xdefine %%func_name h9_%1 %assign %%decoration_length 3 %endif %else %xdefine %%func_name %1 %assign %%decoration_length 0 %endif %ifndef %%func_name %fatal "CPU_PREFIX_DECORATE: unknown decoration for: _IPP = " _IPP %endif %xdefine %$decorated_func_name %[%%func_name] %assign %$decoration_length %%decoration_length %endmacro %define NONVOLATILE_REGS_32_GPR ebp,ebx,esi,edi ; Saves non-volatile GPR registers on stack. ; Input - list of used registers. %macro USES_GPR 1+.nolist %assign LOCAL_FRAME 0 %assign GPR_FRAME 0 %define GPR_CUR BEGIN_INTERSECT INTERSECT {%1},{%[NONVOLATILE_REGS_32_GPR]} ; List of non-volatile GPR registers in the order they will be pushed on stack %xdefine GPR_CUR %$intersection %assign GPR_FRAME %$cardinality * 4 END_INTERSECT ; Push non-volatile GPRs on stack FOREACH GPR_CUR,{push} ; Set up offset of arguments from ESP %assign ARG_1 %[GPR_FRAME + 4] %endmacro ; Restore preliminary saved by USES_GPR non-volatile GPR registers from the stack. ; The macro shall be called after function processing. %macro REST_GPR 0.nolist %ifndef GPR_CUR %fatal "REST_GPR: no GPR_CUR defined" %endif ; Pop saved GPRs from the stack RFOREACH GPR_CUR,{pop} %endmacro %macro LD_ADDR 2.nolist %xdefine %%reg %1 %xdefine %%addr %2 %ifdef IPP_PIC call %%LABEL %%LABEL: pop %%reg sub %%reg, %%LABEL-%%addr %else lea %%reg, [%%addr] %endif %endmacro cryptography-primitives-1.0.0/sources/include/ippres.gen000066400000000000000000000215271470420105600235450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 1999 Intel Corporation * * 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 "winres.h" #define STR2(x) #x #define STR(x) STR2(x) #ifndef _IPP_VERSION #define _IPP_VERSION "" #endif VS_VERSION_INFO VERSIONINFO FILEVERSION VERSION() PRODUCTVERSION VERSION() FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Intel Corporation.\0" VALUE "FileVersion", STR_FILE_VERSION() "\0" VALUE "ProductName", CRYPTO_LIB_NAME() ".\0" VALUE "ProductVersion", STR_VERSION() "\0" VALUE "LegalCopyright", "Copyright (C) 1999-2021, Intel Corporation. All rights reserved.\0" #if defined(_MERGED_BLD) #if defined (WIN32) && !defined (_WIN64) && !defined (WIN32E) VALUE "Comments", "Intel(R) Cryptography Primitives Library. " ".\0" VALUE "FileDescription", IPP_LIB_PREFIX() _IPP_VERSION ".dll is the ia32 " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() _IPP_VERSION ".dll\0" #endif #if defined(WIN32E) VALUE "Comments", CRYPTO_LIB_NAME() ".\0" VALUE "FileDescription", IPP_LIB_PREFIX() _IPP_VERSION ".dll is the intel64 " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() _IPP_VERSION ".dll\0" #endif #else #if defined (_PX) && defined (WIN32) && !defined (_WIN64) && !defined (WIN32E) VALUE "Comments", CRYPTO_LIB_NAME() ". For Intel(R) Pentium(R) processors\0" VALUE "FileDescription", IPP_LIB_PREFIX() "px" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "px" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "px" _IPP_VERSION ".dll\0" #endif #if defined(_PX) && defined(WIN32E) VALUE "Comments", CRYPTO_LIB_NAME() ". For Intel(R) 64 Instruction Set Architecture (ISA) processors\0" VALUE "FileDescription", IPP_LIB_PREFIX() "mx" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "mx" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "mx" _IPP_VERSION ".dll\0" #endif #if defined(_W7) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Streaming SIMD Extensions 2 (SSE2)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "w7" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "w7" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "w7" _IPP_VERSION ".dll\0" #endif #if defined(_P8) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Streaming SIMD Extensions 4.2 (SSE4.2)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "p8" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "p8" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "p8" _IPP_VERSION ".dll\0" #endif #if defined(_G9) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Advanced Vector Extensions (AVX)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "g9" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "g9" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "g9" _IPP_VERSION ".dll\0" #endif #if defined(_H9) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Advanced Vector Extensions 2 (AVX2)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "h9" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "h9" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "h9" _IPP_VERSION ".dll\0" #endif #if defined(_M7) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for Intel(R) 64 Instruction Set Architecture (ISA)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "m7" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "m7" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "m7" _IPP_VERSION ".dll\0" #endif #if defined(_Y8) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Streaming SIMD Extensions 4.2 (SSE4.2)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "y8" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "y8" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "y8" _IPP_VERSION ".dll\0" #endif #if defined(_E9) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Advanced Vector Extensions (AVX)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "e9" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "e9" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "e9" _IPP_VERSION ".dll\0" #endif #if defined(_L9) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with Advanced Vector Extensions 2 (AVX2)\0" VALUE "FileDescription", IPP_LIB_PREFIX() "l9" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "l9" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "l9" _IPP_VERSION ".dll\0" #endif #if defined(_K0) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for processors with AVX512F/CD/BW/DQ/VL support\0" VALUE "FileDescription", IPP_LIB_PREFIX() "k0" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "k0" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "k0" _IPP_VERSION ".dll\0" #endif #if defined(_S8) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for Intel(R) Atom(TM) processor\0" VALUE "FileDescription", IPP_LIB_PREFIX() "s8" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "s8" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "s8" _IPP_VERSION ".dll\0" #endif #if defined(_N8) VALUE "Comments", CRYPTO_LIB_NAME() ". Optimized for Intel(R) Atom(TM) processor\0" VALUE "FileDescription", IPP_LIB_PREFIX() "n8" _IPP_VERSION ".dll is an " CRYPTO_LIB_NAME() " dynamic library\0" VALUE "InternalName", IPP_LIB_PREFIX() "n8" _IPP_VERSION ".dll\0" VALUE "OriginalFilename", IPP_LIB_PREFIX() "n8" _IPP_VERSION ".dll\0" #endif #endif END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END cryptography-primitives-1.0.0/sources/include/ippver.h000066400000000000000000000030221470420105600232140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2001 Intel Corporation * * 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. *************************************************************************/ /* // Intel® Cryptography Primitives Library // // Purpose: Describes the base Intel® Cryptography Primitives Library version // */ #include "ippcpversion.h" #ifndef BASE_VERSION #define BASE_VERSION() CRYPTO_LIB_VERSION_MAJOR,CRYPTO_LIB_VERSION_MINOR,CRYPTO_LIB_VERSION_PATCH #endif #define STR2(x) #x #define STR(x) STR2(x) #ifndef STR_BASE_VERSION #define STR_BASE_VERSION() STR(CRYPTO_LIB_VERSION_MAJOR) "," STR(CRYPTO_LIB_VERSION_MINOR) ", " STR(CRYPTO_LIB_VERSION_PATCH) #endif #ifndef STR_VERSION #ifdef IPP_REVISION #define STR_VERSION() CRYPTO_LIB_VERSION_STR " (r" STR( IPP_REVISION ) ")" #else #define STR_VERSION() CRYPTO_LIB_VERSION_STR #endif #endif /* ////////////////////////////// End of file /////////////////////////////// */ cryptography-primitives-1.0.0/sources/include/lms_internal/000077500000000000000000000000001470420105600242305ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/include/lms_internal/lmots.h000066400000000000000000000102121470420105600255330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 IPPCP_LMOTS_H_ #define IPPCP_LMOTS_H_ #include "owndefs.h" #include "pcptool.h" #include "stateful_sig_common/common.h" /* * LMOTS algorithms params. "Table 1" LMS spec. */ typedef struct { Ipp32u n; Ipp32u w; Ipp32u p; Ipp32u ls; IppsHashMethod* hash_method; } cpLMOTSParams; /* * Standard data format for LMOTS signature * | 4 bytes || n bytes || n bytes || n bytes ||...|| n bytes | * | otssigtype || C || Y[0] || Y[1] ||...|| Y[p-1] | */ typedef struct { IppsLMOTSAlgo _lmotsOIDAlgo; Ipp8u* pC; Ipp8u* pY; } _cpLMOTSSignatureState; /* * Set LMOTS parameters * * Returns: Reason: * ippStsBadArgErr lmotsOIDAlgo > Max value for IppsLMOTSAlgo * lmotsOIDAlgo <= 0 * ippStsNoErr no errors * * Input parameters: * lmotsOIDAlgo id of LMOTS set of parameters * * Output parameters: * params LMOTS parameters (w, p, ls, n, hash_method) */ __IPPCP_INLINE IppStatus setLMOTSParams(IppsLMOTSAlgo lmotsOIDAlgo, cpLMOTSParams* params) { switch (lmotsOIDAlgo) { case LMOTS_SHA256_N32_W1: { params->w = 1; params->p = 265; params->ls = 7; break; } case LMOTS_SHA256_N32_W2: { params->w = 2; params->p = 133; params->ls = 6; break; } case LMOTS_SHA256_N32_W4: { params->w = 4; params->p = 67; params->ls = 4; break; } case LMOTS_SHA256_N32_W8: { params->w = 8; params->p = 34; params->ls = 0; break; } case LMOTS_SHA256_N24_W1: { params->w = 1; params->p = 200; params->ls = 8; break; } case LMOTS_SHA256_N24_W2: { params->w = 2; params->p = 101; params->ls = 6; break; } case LMOTS_SHA256_N24_W4 : { params->w = 4; params->p = 51; params->ls = 4; break; } case LMOTS_SHA256_N24_W8 : { params->w = 8; params->p = 26; params->ls = 0; break; } default: return ippStsBadArgErr; } params->hash_method = (IppsHashMethod*) ippsHashMethod_SHA256_TT(); if(lmotsOIDAlgo <= LMOTS_SHA256_N32_W8) { params->n = 32; } else { params->n = 24; } return ippStsNoErr; } /* * f(S, i, w) is the i-th, w-bit value, if S * is interpreted as a sequence of w-bit values * * Input parameters: * S a string to calculate coef * i output element position * w the length of the output element * * Output parameters: * Target element of a specified length * */ __IPPCP_INLINE Ipp32u cpCoef(Ipp8u* S, Ipp32u i, Ipp32u w) { return ((1 << w) - 1) & ( S[(i * w) / 8] >> (8 - (w * (i % (8 / w)) + w))); } __IPPCP_INLINE Ipp32u cpCksm(Ipp8u* S, cpLMOTSParams lmotsParams) { Ipp32u w = lmotsParams.w; Ipp32u n = lmotsParams.n; Ipp32u ls = lmotsParams.ls; Ipp32u cksmQ = 0; //sum is a 16-bit unsigned integer Ipp32u cksmItrLimit = (8 * n) / w; for (Ipp32u i = 0; i < cksmItrLimit; i++) { cksmQ = cksmQ + ((1 << w) - 1) - cpCoef(S, i, w); } cksmQ = cksmQ << ls; return cksmQ; } #endif /* #ifndef IPPCP_LMOTS_H_ */ cryptography-primitives-1.0.0/sources/include/lms_internal/lms.h000066400000000000000000000072011470420105600251740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 IPPCP_LMS_H_ #define IPPCP_LMS_H_ #include "owndefs.h" #include "owncp.h" #include "lms_internal/lmots.h" #define CP_CKSM_BYTESIZE (2) #define CP_PK_I_BYTESIZE (16) #define CP_LMS_MAX_HASH_BYTESIZE (32) #define CP_SIG_MAX_Y_WORDSIZE (265) /* Constants used to distinguish hashes in the system */ #define D_PBLC (0x8080) #define D_MESG (0x8181) #define D_LEAF (0x8282) #define D_INTR (0x8383) /* LMS algorithms params. "Table 2" LMS spec. */ typedef struct { Ipp32u m; Ipp32u h; IppsHashMethod* hash_method; } cpLMSParams; /* * Standard format of LMS public key: * | u32str(type) || u32str(otstype) || I || T[1] | * | 4 bytes || 4 bytes || 16 bytes || n bytes | */ struct _cpLMSPublicKeyState { Ipp32u _idCtx; // Pub key ctx identifier IppsLMSAlgo lmsOIDAlgo; IppsLMOTSAlgo lmotsOIDAlgo; Ipp8u I[CP_PK_I_BYTESIZE]; Ipp8u* T1; }; /* * Standard data format for LMS signature * | 4 bytes || ... || 4 bytes || n bytes || n bytes ||...|| n bytes | * | q || lmots_sig || lms_sigtype || path[0] || path[1] ||...|| path[h-1] | */ struct _cpLMSSignatureState { Ipp32u _idCtx; // Signature ctx identifier Ipp32u _q; _cpLMOTSSignatureState _lmotsSig; IppsLMSAlgo _lmsOIDAlgo; Ipp8u* _pAuthPath; // path[0] || path[1] ||...|| path[h-1] // C // Y[0] || Y[1] ||...|| Y[p-1] }; /* Defines to handle contexts IDs */ #define CP_LMS_SET_CTX_ID(ctx) ((ctx)->_idCtx = (Ipp32u)idCtxLMS ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define CP_LMS_VALID_CTX_ID(ctx) ((((ctx)->_idCtx) ^ (Ipp32u)IPP_UINT_PTR(ctx)) == (Ipp32u)idCtxLMS) /* * Set LMS parameters * * Returns: Reason: * ippStsBadArgErr lmsOIDAlgo > Max value for IppsLMSAlgo * lmsOIDAlgo < Min value for IppsLMSAlgo * ippStsNoErr no errors * * Input parameters: * lmsOIDAlgo id of LMS set of parameters * * Output parameters: * params LMS parameters (h, m, hash_method) */ __IPPCP_INLINE IppStatus setLMSParams(IppsLMSAlgo lmsOIDAlgo, cpLMSParams* params) { /* Set h */ switch (lmsOIDAlgo % 5) { case 0: { params->h = 5; break; } // LMS_SHA256_M32_H5 and LMS_SHA256_M24_H5 case 1: { params->h = 10; break; } // LMS_SHA256_M32_H10 and LMS_SHA256_M24_H10 case 2: { params->h = 15; break; } // LMS_SHA256_M32_H15 and LMS_SHA256_M24_H15 case 3: { params->h = 20; break; } // LMS_SHA256_M32_H20 and LMS_SHA256_M24_H20 case 4: { params->h = 25; break; } // LMS_SHA256_M32_H25 and LMS_SHA256_M24_H25 default: return ippStsBadArgErr; } if(lmsOIDAlgo <= LMS_SHA256_M32_H25) { params->m = 32; } else { params->m = 24; } params->hash_method = (IppsHashMethod*) ippsHashMethod_SHA256_TT(); return ippStsNoErr; } #endif /* #ifndef IPPCP_LMS_H_ */ cryptography-primitives-1.0.0/sources/include/noexec_stack.inc000066400000000000000000000030021470420105600246750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2024 Intel Corporation ; ; 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. ;========================================================================= ; Non-executable stacks are desirable for security reasons. ; Recent Linux linkers will mark the stack as non-executable ; if and only if all the object files participating in the link ; step declare a properly configured empty "marker" section ; called `.note.GNU-stack`. ; Consider including this file into all the `*.asm` files. %ifndef __NOEXEC_STACK_INC__ %define __NOEXEC_STACK_INC__ 1 ; noexec stack %ifdef LINUX32 %ifndef OSX32 section .note.GNU-stack noalloc noexec nowrite progbits %endif %endif ; noexec stack %ifdef LINUX32E %ifndef OSXEM64T %ifndef _ARCH_KNC section .note.GNU-stack noalloc noexec nowrite progbits %endif %endif %endif %endif ; __NOEXEC_STACK_INC__ ;;;;;;;;;;;;;;;;;;;;;;;;;; End of file "noexec_stack.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;; cryptography-primitives-1.0.0/sources/include/owndefs.h000066400000000000000000000524761470420105600233750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 1999 Intel Corporation * * 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. *************************************************************************/ // // Intel® Cryptography Primitives Library // // Purpose: // Internal definitions // // #ifndef __OWNDEFS_H__ #define __OWNDEFS_H__ #if defined( _VXWORKS ) #include #undef NONE #endif #ifndef IPPCPDEFS_H__ #include "ippcpdefs.h" #endif #if !defined(__IPPCP_INLINE) #if defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) || defined(_MSC_VER) #define __IPPCP_INLINE static __inline #elif defined( __GNUC__ ) #define __IPPCP_INLINE static __inline__ #else #define __IPPCP_INLINE static #endif #endif /*__IPPCP_INLINE*/ /* TODO: to check ICX compiler */ #if !defined(__NOINLINE) #if defined(__INTEL_COMPILER) || defined(_MSC_VER) #define __NOINLINE __declspec(noinline) #elif defined( __GNUC__ ) || defined(__INTEL_LLVM_COMPILER) #define __NOINLINE __attribute__((noinline)) #else #define __NOINLINE #endif #endif /*__NOINLINE*/ #if !defined(__FORCEINLINE) #if defined(_MSC_VER) #define __FORCEINLINE __forceinline #elif defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) || defined( __GNUC__ ) #define __FORCEINLINE __IPPCP_INLINE __attribute__((always_inline)) #else #define __FORCEINLINE #endif #endif /*__FORCEINLINE*/ #if defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) #define __RESTRICT restrict #elif !defined( __RESTRICT ) #define __RESTRICT #endif #if defined( IPP_W32DLL ) #if defined( _MSC_VER ) || defined( __INTEL_COMPILER ) || defined(__INTEL_LLVM_COMPILER) #define IPPDEF(type) __declspec(dllexport) type #else #define IPPDEF(type) type #endif #else #define IPPDEF(type) type #endif /* ia32 */ #define _IPP_PX 0 /* pure C-code */ #define _IPP_M5 1 /* Intel® Quark(TM) processor */ #define _IPP_W7 8 /* Intel® Streaming SIMD Extensions 2 (Intel® SSE2) */ #define _IPP_T7 16 /* Intel® Streaming SIMD Extensions 3 (Intel® SSE3) */ #define _IPP_V8 32 /* Supplemental Streaming SIMD Extensions 3 (SSSE3) */ #define _IPP_S8 33 /* Supplemental Streaming SIMD Extensions 3 (SSSE3) + MOVBE instruction */ #define _IPP_P8 64 /* Intel® Streaming SIMD Extensions 4.2 (Intel® SSE4.2) */ #define _IPP_G9 128 /* Intel® Advanced Vector Extensions (Intel® AVX) */ #define _IPP_H9 256 /* Intel® Advanced Vector Extensions 2 (Intel® AVX2) */ #define _IPP_I0 512 /* Intel® Advanced Vector Extensions 512 (Intel® AVX512) - Intel® Xeon® Phi(TM) Processor (formerly Knights Landing) */ #define _IPP_S0 1024 /* Intel® Advanced Vector Extensions 512 (Intel® AVX512) - Intel® Xeon® Processor (formerly codenamed Skylake) */ /* intel64 */ #define _IPP32E_PX _IPP_PX /* pure C-code */ #define _IPP32E_M7 32 /* Intel® Streaming SIMD Extensions 3 (Intel® SSE3) */ #define _IPP32E_U8 64 /* Supplemental Streaming SIMD Extensions 3 (SSSE3) */ #define _IPP32E_N8 65 /* Supplemental Streaming SIMD Extensions 3 (SSSE3) + MOVBE instruction */ #define _IPP32E_Y8 128 /* Intel® Streaming SIMD Extensions 4.2 (Intel® SSE4.2) */ #define _IPP32E_E9 256 /* Intel® Advanced Vector Extensions (Intel® AVX) */ #define _IPP32E_L9 512 /* Intel® Advanced Vector Extensions 2 (Intel® AVX2) */ #define _IPP32E_K0 2048 /* Intel® Advanced Vector Extensions 512 (Intel® AVX512) - Intel® Xeon® Processor (formerly codenamed Skylake) */ #define _IPP32E_K1 4096 /* Intel® Advanced Vector Extensions 512 (Intel® AVX512) - Intel® Xeon® Processor (formerly codenamed Icelake) */ #if defined(__INTEL_COMPILER) || defined(__INTEL_LLVM_COMPILER) || (_MSC_VER >= 1300) #define __ALIGN8 __declspec (align(8)) #define __ALIGN16 __declspec (align(16)) #define __ALIGN32 __declspec (align(32)) #if !defined(__ALIGN64) #define __ALIGN64 __declspec (align(64)) #endif/*__ALIGN64*/ #elif defined(__GNUC__) || defined(__CLANG__) #define __ALIGN8 __attribute__((aligned(8))) #define __ALIGN16 __attribute__((aligned(16))) #define __ALIGN32 __attribute__((aligned(32))) #if !defined(__ALIGN64) #define __ALIGN64 __attribute__((aligned(64))) #endif/*__ALIGN64*/ #else #error Intel, MS or GNU C compiler required #endif /* ia32 */ #if defined ( _M5 ) /* Intel® Quark(TM) processor */ #define _IPP _IPP_M5 #define _IPP32E _IPP32E_PX #define OWNAPI(name) m5_##name #elif defined( _W7 ) /* Intel® SSE2 */ #define _IPP _IPP_W7 #define _IPP32E _IPP32E_PX #define OWNAPI(name) w7_##name #elif defined( _T7 ) /* Intel® SSE3 */ #define _IPP _IPP_T7 #define _IPP32E _IPP32E_PX #define OWNAPI(name) t7_##name #elif defined( _V8 ) /* SSSE3 */ #define _IPP _IPP_V8 #define _IPP32E _IPP32E_PX #define OWNAPI(name) v8_##name #elif defined( _S8 ) /* SSSE3 + MOVBE instruction */ #define _IPP _IPP_S8 #define _IPP32E _IPP32E_PX #define OWNAPI(name) s8_##name #elif defined( _P8 ) /* Intel® SSE4.2 */ #define _IPP _IPP_P8 #define _IPP32E _IPP32E_PX #define OWNAPI(name) p8_##name #elif defined( _G9 ) /* Intel® AVX */ #define _IPP _IPP_G9 #define _IPP32E _IPP32E_PX #define OWNAPI(name) g9_##name #elif defined( _H9 ) /* Intel® AVX2 */ #define _IPP _IPP_H9 #define _IPP32E _IPP32E_PX #define OWNAPI(name) h9_##name /* intel64 */ #elif defined( _M7 ) /* Intel® SSE3 */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_M7 #define OWNAPI(name) m7_##name #elif defined( _U8 ) /* SSSE3 */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_U8 #define OWNAPI(name) u8_##name #elif defined( _N8 ) /* SSSE3 + MOVBE instruction */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_N8 #define OWNAPI(name) n8_##name #elif defined( _Y8 ) /* Intel® SSE4.2 */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_Y8 #define OWNAPI(name) y8_##name #elif defined( _E9 ) /* Intel® AVX */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_E9 #define OWNAPI(name) e9_##name #elif defined( _L9 ) /* Intel® AVX2 */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_L9 #define OWNAPI(name) l9_##name #elif defined( _K0 ) /* Intel® AVX512 - formerly codenamed Skylake */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_K0 #define OWNAPI(name) k0_##name #elif defined( _K1 ) /* Intel® AVX512 - formerly codenamed Icelake */ #define _IPP _IPP_PX #define _IPP32E _IPP32E_K1 #define OWNAPI(name) k1_##name #else #define _IPP _IPP_PX #define _IPP32E _IPP32E_PX #if defined (_M_AMD64) || defined (__x86_64__) || defined ( _ARCH_EM64T ) #define OWNAPI(name) mx_##name #else #define OWNAPI(name) px_##name #endif #endif #if defined(_MERGED_BLD) #define _OWN_MERGED_BLD #endif #ifndef _OWN_MERGED_BLD #undef OWNAPI #define OWNAPI(name) name #endif /* Force __cdecl calling convention for internal functions declarations */ #define IPP_OWN_DECL(type,name,param) type IPP_CDECL name param ; #define IPP_OWN_DEFN(type,name,param) type IPP_CDECL name param #define IPP_OWN_FUNPTR(type,name,param) typedef type (IPP_CDECL *name) param ; #if defined( IPP_W32DLL ) #if defined( _MSC_VER ) || defined( __INTEL_COMPILER ) || defined(__INTEL_LLVM_COMPILER) #define IPPFUN(type,name,arg) __declspec(dllexport) type IPP_CALL name arg #else #define IPPFUN(type,name,arg) extern type IPP_CALL name arg #endif #else #if defined(LINUX32E) && !defined(IPP_PIC) #define IPPFUN(type,name,arg) __attribute__((force_align_arg_pointer)) extern type IPP_CALL name arg #else #define IPPFUN(type,name,arg) extern type IPP_CALL name arg #endif #endif #define _IPP_ARCH_IA32 1 #define _IPP_ARCH_EM64T 4 #define _IPP_ARCH_LRB 16 #define _IPP_ARCH_LRB2 128 #define _IPP_ARCH_LP64 0 #if defined ( _ARCH_IA32 ) #define _IPP_ARCH _IPP_ARCH_IA32 #elif defined( _ARCH_EM64T ) #define _IPP_ARCH _IPP_ARCH_EM64T #else #if defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) #define _IPP_ARCH _IPP_ARCH_EM64T #else #define _IPP_ARCH _IPP_ARCH_IA32 #endif #endif #if ((_IPP_ARCH == _IPP_ARCH_IA32)) __IPPCP_INLINE Ipp32s IPP_INT_PTR ( const void* ptr ) { union { void* Ptr; Ipp32s Int; } dd; dd.Ptr = (void*)ptr; return dd.Int; } __IPPCP_INLINE Ipp32u IPP_UINT_PTR( const void* ptr ) { union { void* Ptr; Ipp32u Int; } dd; dd.Ptr = (void*)ptr; return dd.Int; } #elif ((_IPP_ARCH == _IPP_ARCH_EM64T) || (_IPP_ARCH == _IPP_ARCH_LRB2)) __IPPCP_INLINE Ipp64s IPP_INT_PTR( const void* ptr ) { union { void* Ptr; Ipp64s Int; } dd; dd.Ptr = (void*)ptr; return dd.Int; } __IPPCP_INLINE Ipp64u IPP_UINT_PTR( const void* ptr ) { union { void* Ptr; Ipp64u Int; } dd; dd.Ptr = (void*)ptr; return dd.Int; } #else #define IPP_INT_PTR( ptr ) ( (long)(ptr) ) #define IPP_UINT_PTR( ptr ) ( (unsigned long)(ptr) ) #endif #define IPP_ALIGN_TYPE(type, align) ((align)/sizeof(type)-1) #define IPP_BYTES_TO_ALIGN(ptr, align) ((~(IPP_INT_PTR(ptr)&((align)-1))+1)&((align)-1)) #define IPP_ALIGNED_PTR(ptr, align) (void*)( (unsigned char*)(ptr) + (IPP_BYTES_TO_ALIGN( ptr, align )) ) #define IPP_ALIGNED_SIZE(size, align) (((size)+(align)-1)&~((align)-1)) #define IPP_MALLOC_ALIGNED_BYTES 64 #define IPP_MALLOC_ALIGNED_8BYTES 8 #define IPP_MALLOC_ALIGNED_16BYTES 16 #define IPP_MALLOC_ALIGNED_32BYTES 32 #define IPP_ALIGNED_ARRAY(align,arrtype,arrname,arrlength)\ char arrname##AlignedArrBuff[sizeof(arrtype)*(arrlength)+IPP_ALIGN_TYPE(char, align)];\ arrtype *arrname = (arrtype*)IPP_ALIGNED_PTR(arrname##AlignedArrBuff,align) #if defined( __cplusplus ) extern "C" { #endif /* ///////////////////////////////////////////////////////////////////////////// Intel® Cryptography Primitives Library Context Identification /////////////////////////////////////////////////////////////////////////// */ #define IPP_CONTEXT( a, b, c, d) \ (int)(((unsigned)(a) << 24) | ((unsigned)(b) << 16) | \ ((unsigned)(c) << 8) | (unsigned)(d)) typedef enum { idCtxUnknown = 0, idCtxDES = IPP_CONTEXT( ' ', 'D', 'E', 'S'), idCtxRijndael = IPP_CONTEXT( ' ', 'R', 'I', 'J'), idCtxSMS4 = IPP_CONTEXT( 'S', 'M', 'S', '4'), idCtxARCFOUR = IPP_CONTEXT( ' ', 'R', 'C', '4'), idCtxSHA1 = IPP_CONTEXT( 'S', 'H', 'S', '1'), idCtxSHA224 = IPP_CONTEXT( 'S', 'H', 'S', '3'), idCtxSHA256 = IPP_CONTEXT( 'S', 'H', 'S', '2'), idCtxSHA384 = IPP_CONTEXT( 'S', 'H', 'S', '4'), idCtxSHA512 = IPP_CONTEXT( 'S', 'H', 'S', '5'), idCtxMD5 = IPP_CONTEXT( ' ', 'M', 'D', '5'), idCtxHMAC = IPP_CONTEXT( 'H', 'M', 'A', 'C'), idCtxBigNum = IPP_CONTEXT( 'B', 'I', 'G', 'N'), idCtxMontgomery = IPP_CONTEXT( 'M', 'O', 'N', 'T'), idCtxPrimeNumber = IPP_CONTEXT( 'P', 'R', 'I', 'M'), idCtxPRNG = IPP_CONTEXT( 'P', 'R', 'N', 'G'), idCtxRSA = IPP_CONTEXT( ' ', 'R', 'S', 'A'), idCtxRSA_PubKey = IPP_CONTEXT( 'R', 'S', 'A', '0'), idCtxRSA_PrvKey1 = IPP_CONTEXT( 'R', 'S', 'A', '1'), idCtxRSA_PrvKey2 = IPP_CONTEXT( 'R', 'S', 'A', '2'), idCtxDSA = IPP_CONTEXT( ' ', 'D', 'S', 'A'), idCtxECCP = IPP_CONTEXT( ' ', 'E', 'C', 'P'), idCtxECCB = IPP_CONTEXT( ' ', 'E', 'C', 'B'), idCtxECCPPoint = IPP_CONTEXT( 'P', 'E', 'C', 'P'), idCtxECCBPoint = IPP_CONTEXT( 'P', 'E', 'C', 'B'), idCtxDH = IPP_CONTEXT( ' ', ' ', 'D', 'H'), idCtxDLP = IPP_CONTEXT( ' ', 'D', 'L', 'P'), idCtxCMAC = IPP_CONTEXT( 'C', 'M', 'A', 'C'), idCtxAESXCBC, idCtxAESCCM, idCtxAESGCM, idCtxGFP, idCtxGFPE, idCtxGFPX, idCtxGFPXE, idCtxGFPXQX, idCtxGFPXQXE, idCtxGFPEC, idCtxGFPPoint, idCtxGFPXEC, idCtxGFPXECPoint, idCtxHash, idCtxSM3, idCtxAESXTS, idxCtxECES_SM2, idCtxGFPECKE, idCtxLMS } IppCtxId; /* ///////////////////////////////////////////////////////////////////////////// Helpers /////////////////////////////////////////////////////////////////////////// */ #define IPP_NOERROR_RET() return ippStsNoErr #define IPP_ERROR_RET( ErrCode ) return (ErrCode) #define IPP_BADARG_RET( expr, ErrCode )\ {if (expr) { IPP_ERROR_RET( ErrCode ); }} #define IPP_BAD_SIZE_RET( n )\ IPP_BADARG_RET( (n)<=0, ippStsSizeErr ) #define IPP_BAD_STEP_RET( n )\ IPP_BADARG_RET( (n)<=0, ippStsStepErr ) #define IPP_BAD_PTR1_RET( ptr )\ IPP_BADARG_RET( NULL==(ptr), ippStsNullPtrErr ) #define IPP_BAD_PTR2_RET( ptr1, ptr2 )\ {IPP_BAD_PTR1_RET( ptr1 ); IPP_BAD_PTR1_RET( ptr2 )} #define IPP_BAD_PTR3_RET( ptr1, ptr2, ptr3 )\ {IPP_BAD_PTR2_RET( ptr1, ptr2 ); IPP_BAD_PTR1_RET( ptr3 )} #define IPP_BAD_PTR4_RET( ptr1, ptr2, ptr3, ptr4 )\ {IPP_BAD_PTR2_RET( ptr1, ptr2 ); IPP_BAD_PTR2_RET( ptr3, ptr4 )} #define IPP_BAD_ISIZE_RET(roi) \ IPP_BADARG_RET( ((roi).width<=0 || (roi).height<=0), ippStsSizeErr) /* ////////////////////////////////////////////////////////////////////////// */ /* internal messages */ #define MSG_LOAD_DLL_ERR (-9700) /* Error at loading of %s library */ #define MSG_NO_DLL (-9701) /* No DLLs were found in the Waterfall procedure */ #define MSG_NO_SHARED (-9702) /* No shared libraries were found in the Waterfall procedure */ /* ////////////////////////////////////////////////////////////////////////// */ typedef union { /* double precision */ Ipp64s hex; Ipp64f fp; } IppFP_64f; typedef union { /* single precision */ Ipp32s hex; Ipp32f fp; } IppFP_32f; /* ////////////////////////////////////////////////////////////////////////// */ /* Define NULL pointer value */ #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif #define IPP_UNREFERENCED_PARAMETER(p) (void)(p) #if defined( _IPP_MARK_LIBRARY ) static char G[] = {73, 80, 80, 71, 101, 110, 117, 105, 110, 101, 243, 193, 210, 207, 215}; #endif /* // endian definition */ #define IPP_LITTLE_ENDIAN (0) #define IPP_BIG_ENDIAN (1) #if defined( _IPP_LE ) #define IPP_ENDIAN IPP_LITTLE_ENDIAN #elif defined( _IPP_BE ) #define IPP_ENDIAN IPP_BIG_ENDIAN #else #if defined( __ARMEB__ ) #define IPP_ENDIAN IPP_BIG_ENDIAN #else #define IPP_ENDIAN IPP_LITTLE_ENDIAN #endif #endif /* ////////////////////////////////////////////////////////////////////////// */ /* intrinsics */ #if (_IPP >= _IPP_W7) || (_IPP32E >= _IPP32E_M7) #if defined(__INTEL_COMPILER) || (_MSC_VER >= 1300) #if (_IPP == _IPP_W7) #if defined(__INTEL_COMPILER) #include "emmintrin.h" #else #undef _W7 #include "emmintrin.h" #define _W7 #endif #define _mm_loadu _mm_loadu_si128 #elif (_IPP32E == _IPP32E_M7) #if defined(__INTEL_COMPILER) #include "pmmintrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER >= 140050110) #include "intrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER < 140050110) #include "emmintrin.h" #define _mm_loadu _mm_loadu_si128 #endif #elif ((_IPP == _IPP_V8) || (_IPP32E == _IPP32E_U8) || (_IPP == _IPP_S8) || (_IPP32E == _IPP32E_N8)) #if defined(__INTEL_COMPILER) #include "tmmintrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER >= 140050110) #include "intrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER < 140050110) #include "emmintrin.h" #define _mm_loadu _mm_loadu_si128 #endif #elif (_IPP == _IPP_P8) || (_IPP32E == _IPP32E_Y8) #if defined(__INTEL_COMPILER) #include "smmintrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER >= 140050110) #include "intrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER < 140050110) #include "emmintrin.h" #define _mm_loadu _mm_loadu_si128 #endif #elif (_IPP >= _IPP_G9) || (_IPP32E >= _IPP32E_E9) #if defined(__INTEL_COMPILER) #include "immintrin.h" #define _mm_loadu _mm_lddqu_si128 #elif (_MSC_FULL_VER >= 160021003) #include "immintrin.h" #define _mm_loadu _mm_lddqu_si128 #endif #endif #endif #if defined(__GNUC__) && !defined(__INTEL_COMPILER) #include "x86intrin.h" #endif #endif // **** intrinsics for bit casting **** #if defined(__INTEL_COMPILER) extern unsigned int __intel_castf32_u32(float val); extern float __intel_castu32_f32(unsigned int val); extern unsigned __int64 __intel_castf64_u64(double val); extern double __intel_castu64_f64(unsigned __int64 val); #define __CAST_32f32u(val) __intel_castf32_u32((Ipp32f)val) #define __CAST_32u32f(val) __intel_castu32_f32((Ipp32u)val) #define __CAST_64f64u(val) __intel_castf64_u64((Ipp64f)val) #define __CAST_64u64f(val) __intel_castu64_f64((Ipp64u)val) #else #define __CAST_32f32u(val) ( *((Ipp32u*)&val) ) #define __CAST_32u32f(val) ( *((Ipp32f*)&val) ) #define __CAST_64f64u(val) ( *((Ipp64u*)&val) ) #define __CAST_64u64f(val) ( *((Ipp64f*)&val) ) #endif // short names for vector registers casting #define _pd2ps _mm_castpd_ps #define _ps2pd _mm_castps_pd #define _pd2pi _mm_castpd_si128 #define _pi2pd _mm_castsi128_pd #define _ps2pi _mm_castps_si128 #define _pi2ps _mm_castsi128_ps #define _ypd2ypi _mm256_castpd_si256 #define _ypi2ypd _mm256_castsi256_pd #define _yps2ypi _mm256_castps_si256 #define _ypi2yps _mm256_castsi256_ps #define _ypd2yps _mm256_castpd_ps #define _yps2ypd _mm256_castps_pd #define _yps2ps _mm256_castps256_ps128 #define _ypi2pi _mm256_castsi256_si128 #define _ypd2pd _mm256_castpd256_pd128 #define _ps2yps _mm256_castps128_ps256 #define _pi2ypi _mm256_castsi128_si256 #define _pd2ypd _mm256_castpd128_pd256 #define _zpd2zpi _mm512_castpd_si512 #define _zpi2zpd _mm512_castsi512_pd #define _zps2zpi _mm512_castps_si512 #define _zpi2zps _mm512_castsi512_ps #define _zpd2zps _mm512_castpd_ps #define _zps2zpd _mm512_castps_pd #define _zps2ps _mm512_castps512_ps128 #define _zpi2pi _mm512_castsi512_si128 #define _zpd2pd _mm512_castpd512_pd128 #define _ps2zps _mm512_castps128_ps512 #define _pi2zpi _mm512_castsi128_si512 #define _pd2zpd _mm512_castpd128_pd512 #define _zps2yps _mm512_castps512_ps256 #define _zpi2ypi _mm512_castsi512_si256 #define _zpd2ypd _mm512_castpd512_pd256 #define _yps2zps _mm512_castps256_ps512 #define _ypi2zpi _mm512_castsi256_si512 #define _ypd2zpd _mm512_castpd256_pd512 #if defined(__INTEL_COMPILER) #define __IVDEP ivdep #else #define __IVDEP message("message :: 'ivdep' is not defined") #endif #if defined( _MERGED_BLD ) #if !defined( _IPP_DYNAMIC ) /* WIN-32, WIN-64 */ #if defined(WIN32) || defined(WIN32E) #if ( defined(_W7) || defined(_M7) ) #define _IPP_DATA 1 #endif #elif defined(linux) /* LIN-32, LIN-64 */ #if ( defined(_W7) || defined(_M7) ) #define _IPP_DATA 1 #endif /* OSX-32, OSX-64 */ #elif defined(OSX32) || defined(OSXEM64T) #if ( defined(_Y8) ) #define _IPP_DATA 1 #endif #endif #endif #else /* compile data unconditionally */ #define _IPP_DATA 1 #endif #if defined( __cplusplus ) } #endif #endif /* __OWNDEFS_H__ */ cryptography-primitives-1.0.0/sources/include/stateful_sig_common/000077500000000000000000000000001470420105600256025ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/include/stateful_sig_common/common.h000066400000000000000000000024521470420105600272460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ /* * Represent the `in` value as the `out` array that length is `outlen` * !Works only for big-endian data! * * Input parameters: * outlen length of resulted array * in value that needs to be represent as an array * Output parameters: * out resulted array of bytes */ __IPPCP_INLINE void toByte(Ipp8u *out, Ipp32s outlen, Ipp32u in) { /* Iterate over out in decreasing order, for big-endianness. */ for (Ipp32s i = outlen - 1; i >= 0; i--) { out[i] = (Ipp8u)(in & 0xff); in = in >> /*bitsize of 1 byte*/ 8; } } cryptography-primitives-1.0.0/sources/include/utils.inc000066400000000000000000000073211470420105600233770ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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 __UTILS_INC__ %define __UTILS_INC__ 1 ; Apply a functor provided as a last parameter to each element of the list, provided as sequence of first parameters. ; A list is processed in direct order. Note: an input list can be empty. %macro FOREACH 2-*.nolist %rotate -1 %xdefine %%functor %1 %rep %0-1 %rotate 1 %ifnempty %1 %%functor %1 %endif %endrep %endmacro ; Apply a functor provided as a last parameter to each element of the list, provided as sequence of first parameters. ; A list is processed in reverse order. Note: an input list can be empty. %macro RFOREACH 2-*.nolist %rotate -1 %xdefine %%functor %1 %rep %0-1 %rotate -1 %ifnempty %1 %%functor %1 %endif %endrep %endmacro ; Shall be called before INTERSECT macro to open corresponding context. %macro BEGIN_INTERSECT 0.nolist %push _INTERSECT_CTX_ %xdefine %$intersection %assign %$cardinality 0 %endmacro ; Shall be called after INTERSECT macro to close corresponding context. %macro END_INTERSECT 0.nolist %pop _INTERSECT_CTX_ %endmacro ; The macro searches intersection between two lists. ; Input: two comma-separated lists, enclosed in curly braces. ; Output: ; - Intersection will be located in the %$intersection context macro (can be empty). ; - Count of intersection elements list will be stored in the %$cardinality context variable. %macro INTERSECT 2.nolist %ifnctx _INTERSECT_CTX_ %fatal "Not in the context: _INTERSECT_CTX_" %endif %xdefine %%list1 %1 %xdefine %%list2 %2 FOREACH %%list1,{?INTERSECT_BODY {%%list2},} %endmacro ; Helper macro to concatenate two lists. ; The result will be stored in the 3rd parameter that must be a macro identifier. %macro CONCATENATE 3.nolist %ifnid %3 %fatal "CONCATENATE: 3rd parameter must be a macro identifier." %endif %define %3 %[%1] %ifnempty %3 %ifnempty %2 %define %3 %[%3],%[%2] %endif %else %define %3 %[%2] %endif %endmacro ; Helper macro that searches the specified element in the input list. ; Input: ; - Last parameter - target element ; - First parameters refer to the list where the search is processed. ; Output: ; - The macro is context dependent and upon the element is found, the context macro %$elem_exists will be defined. %macro ?FIND 2-*.nolist %ifnctx _FIND_CTX_ %fatal "Not in the context: _FIND_CTX_" %endif %rotate -1 %xdefine %%elem_to_check %1 %undef %$elem_exists %rep %0-1 %rotate -1 %ifidni %%elem_to_check, %1 %define %$elem_exists %1 %exitrep %endif %endrep %endmacro ; Macro that finds and collects intersection elements. To be used as INTERSECT macro functor. %macro ?INTERSECT_BODY 2.nolist %xdefine %%list %1 %xdefine %%elem %2 %push _FIND_CTX_ ?FIND %%list,%%elem %ifdef %$elem_exists %ifempty %$$intersection %define %$$intersection %2 %else %define %$$intersection %[%$$intersection],%%elem %endif %assign %$$cardinality %$$cardinality + 1 %endif %pop _FIND_CTX_ %endmacro %endif cryptography-primitives-1.0.0/sources/include/xmss_internal/000077500000000000000000000000001470420105600244275ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/include/xmss_internal/wots.h000066400000000000000000000061771470420105600256070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 IPPCP_WOTS_H_ #define IPPCP_WOTS_H_ #include "owndefs.h" #include "pcptool.h" #include "stateful_sig_common/common.h" // WOTS+ algorithms params. See 3.1.1. XMSS spec. typedef struct { Ipp32s n; Ipp32u w; Ipp32s len_1; Ipp32s len; Ipp32s log2_w; IppsHashMethod* hash_method; } cpWOTSParams; // declarations #define base_w OWNAPI(base_w) IPP_OWN_DECL(void, base_w, (const Ipp8u* pMsg, Ipp32s out_len, Ipp8u* basew, cpWOTSParams* params)) #define do_xmss_hash OWNAPI(do_xmss_hash) IPP_OWN_DECL(IppStatus, do_xmss_hash, (Ipp32u padding_id, const Ipp8u* key, const Ipp8u* msg, Ipp32s msgLen, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) #define prf OWNAPI(prf) IPP_OWN_DECL(IppStatus, prf, (const Ipp8u* key, const Ipp8u* index, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) #define chain OWNAPI(chain) IPP_OWN_DECL(IppStatus, chain, (Ipp8u* X, Ipp8u i, Ipp8u s, Ipp8u* pSeed, Ipp8u* adrs, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) #define WOTS_pkFromSig OWNAPI(WOTS_pkFromSig) IPP_OWN_DECL(IppStatus, WOTS_pkFromSig, (const Ipp8u* M, Ipp8u* sig, Ipp8u* pSeed, Ipp8u* adrs, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) /* * Set idx as a 4-elements byte array to adrs * * Input parameters: * adrs array of bytes * idx value to represent as 4-bytes array * word_id int32 idx in the adrs array * Output parameters: * adrs changed array of bytes */ __IPPCP_INLINE void set_adrs_idx(Ipp8u* adrs, Ipp32u idx, int word_id){ adrs[4 * word_id + 3] = (Ipp8u) idx & 0xff; adrs[4 * word_id + 2] = (Ipp8u)(idx >> 8) & 0xff; adrs[4 * word_id + 1] = (Ipp8u)(idx >> 16) & 0xff; adrs[4 * word_id] = (Ipp8u)(idx >> 24) & 0xff; } /* * Find an index in the adrs array to set 1 byte to * * Returns: * index of adrs to set data to * * Input parameters: * word_id int32 idx in the adrs array */ __IPPCP_INLINE Ipp8u set_adrs_1_byte(int word_id){ return (Ipp8u)(4 * word_id + 3); } /* * Implement a ceil function that returns the smallest integer greater than or equal to x. * * Input parameters: * x double precision floating point value */ __IPPCP_INLINE Ipp32s cpCeil(double x) { Ipp32s int_val = (Ipp32s) x; if(int_val == x || x <= 0.0){ return int_val; } else{ return int_val + 1; } } #endif /* #ifndef IPPCP_WOTS_H_ */ cryptography-primitives-1.0.0/sources/include/xmss_internal/xmss.h000066400000000000000000000103541470420105600255750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 IPPCP_XMSS_H_ #define IPPCP_XMSS_H_ #include "owndefs.h" #include "owncp.h" #include "wots.h" // The format of an XMSS public key // +---------------------------------+ // | algorithm OID | // +---------------------------------+ // | | // | root node | n bytes // | | // +---------------------------------+ // | | // | SEED | n bytes // | | // +---------------------------------+ struct _cpXMSSPublicKeyState { IppsXMSSAlgo OIDAlgo; Ipp8u* pRoot; Ipp8u* pSeed; }; // The data format for a signature // +---------------------------------+ // | | // | index idx_sig | 4 bytes // | | // +---------------------------------+ // | | // | randomness r | n bytes // | | // +---------------------------------+ // | | // | WOTS+ signature sig_ots | len * n bytes // | | // +---------------------------------+ // | | // | auth[0] | n bytes // | | // +---------------------------------+ // | | // ˜ .... ˜ // | | // +---------------------------------+ // | | // | auth[h - 1] | n bytes // | | // +---------------------------------+ struct _cpXMSSSignatureState { Ipp32u idx; Ipp8u* r; Ipp8u* pOTSSign; Ipp8u* pAuthPath; }; // declarations #define ltree OWNAPI(ltree) IPP_OWN_DECL(IppStatus, ltree, (Ipp8u* pk, Ipp8u* seed, Ipp8u* adrs, Ipp8u* temp_buf, cpWOTSParams* params)) #define rand_hash OWNAPI(rand_hash) IPP_OWN_DECL(IppStatus, rand_hash, (Ipp8u* left, Ipp8u* right, Ipp8u* seed, Ipp8u* adrs, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) /* * Set XMSS algorithms parameters * * Returns: Reason: * ippStsBadArgErr OIDAlgo > Max value for IppsXMSSAlgo * OIDAlgo <= 0 * ippStsNoErr no errors * * Input parameters: * OIDAlgo id of XMSS set of parameters (algorithm) * h height of the XMSS tree * * Output parameters: * params WOTS parameters (w, log2_w, n, len, len_1, hash_method) */ __IPPCP_INLINE IppStatus setXMSSParams(IppsXMSSAlgo OIDAlgo, Ipp32s* h, cpWOTSParams* params) { // Digits below are from the XMSS algo spec // don't depend on the algo params->w = 16; params->log2_w = 4; // 256-bit or 512-bit if(OIDAlgo > 0 && OIDAlgo < 4) { params->n = 32; params->len = 67; params->len_1 = 64; params->hash_method = (IppsHashMethod*) ippsHashMethod_SHA256_TT(); } else if(OIDAlgo > 3 && OIDAlgo < 7) { params->n = 64; params->len = 131; params->len_1 = 128; params->hash_method = (IppsHashMethod*) ippsHashMethod_SHA512(); } else { return ippStsBadArgErr; } // tree height if(OIDAlgo % 3 == 1) { *h = 10; } else if(OIDAlgo % 3 == 2) { *h = 16; } else if(OIDAlgo % 3 == 0) { *h = 20; } return ippStsNoErr; } #endif /* #ifndef IPPCP_XMSS_H_ */ cryptography-primitives-1.0.0/sources/ippcp/000077500000000000000000000000001470420105600212315ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/CMakeLists.txt000066400000000000000000000740051470420105600237770ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2017 Intel Corporation # # 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. #========================================================================= # # Intel® Cryptography Primitives Library # include (GenerateExportHeader) set(TARGET_NAME ${LIB_NAME}) #Set platform list if (NOT MERGED_BLD) if(${ARCH} MATCHES "ia32") set(BASE_PLATFORM_LIST px) else() set(BASE_PLATFORM_LIST mx) endif() endif() if(WIN32) if(${ARCH} MATCHES "ia32") set(BASE_PLATFORM_LIST_1CPU ${BASE_PLATFORM_LIST} w7 s8 p8 g9 h9) set(BASE_PLATFORM_LIST ${BASE_PLATFORM_LIST} w7 p8 h9) else() set(BASE_PLATFORM_LIST_1CPU ${BASE_PLATFORM_LIST} m7 n8 y8 e9 l9 k0 k1) set(BASE_PLATFORM_LIST ${BASE_PLATFORM_LIST} m7 y8 l9 k0 k1) endif() endif(WIN32) if(UNIX) if(APPLE) set(BASE_PLATFORM_LIST_1CPU ${BASE_PLATFORM_LIST} y8 e9 l9 k0 k1) set(BASE_PLATFORM_LIST ${BASE_PLATFORM_LIST} y8 l9 k0 k1) else() if (${ARCH} MATCHES "ia32") set(BASE_PLATFORM_LIST_1CPU ${BASE_PLATFORM_LIST} w7 s8 p8 g9 h9) set(BASE_PLATFORM_LIST ${BASE_PLATFORM_LIST} w7 p8 h9) else() set(BASE_PLATFORM_LIST_1CPU ${BASE_PLATFORM_LIST} m7 n8 y8 e9 l9 k0 k1) set(BASE_PLATFORM_LIST ${BASE_PLATFORM_LIST} m7 y8 l9 k0 k1) endif(${ARCH} MATCHES "ia32") endif(APPLE) endif(UNIX) if(PLATFORM_LIST) if (NOT MERGED_BLD) foreach(opt ${PLATFORM_LIST}) set(FOUND_PLATFORM false) foreach(base_opt ${BASE_PLATFORM_LIST_1CPU}) string(STRIP "${opt}" opt_strip) if(opt_strip STREQUAL base_opt) set(FOUND_PLATFORM true) endif() endforeach(base_opt ${BASE_PLATFORM_LIST_1CPU}) if(NOT FOUND_PLATFORM) message (FATAL_ERROR "Incorrect platform: " ${opt}) endif() endforeach(opt ${PLATFORM_LIST}) if (PLATFORM_LIST STREQUAL "") message (FATAL_ERROR "PLATFORM_LIST cannot be empty") endif(PLATFORM_LIST STREQUAL "") message (STATUS "Platform list ......................... " ${PLATFORM_LIST}) else() message (FATAL_ERROR "PLATFORM_LIST cannot be set, when MERGED_BLD is on") endif(NOT MERGED_BLD) endif() # Platform-specific definitions set(px_def "_PX") set(w7_def "_W7") set(s8_def "_S8") set(p8_def "_P8") set(g9_def "_G9") set(h9_def "_H9") set(mx_def "_PX") set(m7_def "_M7") set(n8_def "_N8") set(y8_def "_Y8") set(e9_def "_E9") set(l9_def "_L9") set(k0_def "_K0") set(k1_def "_K1") if(NOT PLATFORM_LIST) set(PLATFORM_LIST ${BASE_PLATFORM_LIST}) endif() if (NOT MERGED_BLD) set(PLATFORM_LIST ${PLATFORM_LIST} PARENT_SCOPE) endif(NOT MERGED_BLD) # define defaults for every supported compiler set(DEFAULT_Intel_COMPILER_VER 19.0.0) set(DEFAULT_MSVC_COMPILER_VER 19.14) set(DEFAULT_GNU_COMPILER_VER 8.2.0) set(DEFAULT_APPLE_CLANG_COMPILER_VER 12.0.0) set(DEFAULT_Clang_COMPILER_VER 9.0.0) set(DEFAULT_Intel18_COMPILER_VER 18.0.0) set(DEFAULT_Intel19_COMPILER_VER 19.0.0) set(DEFAULT_MSVC19_COMPILER_VER 19.14) set(DEFAULT_IntelLLVM_COMPILER_VER 2023.1.0) string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*$" "\\1.\\2.\\3" CMAKE_C_COMPILER_VERSION_SHORT ${CMAKE_C_COMPILER_VERSION}) string(REGEX REPLACE "^([0-9]+)\\..*$" "\\1" CMAKE_C_COMPILER_VERSION_MAJOR ${CMAKE_C_COMPILER_VERSION}) if(UNIX) if(APPLE) set(OS_STRING "macosx") else() set(OS_STRING "linux") endif() else() set(OS_STRING "windows") endif() # common build options and ${OS_DEFAULT_COMPILER} include("${IPP_CRYPTO_DIR}/sources/cmake/${OS_STRING}/common.cmake") include("${IPP_CRYPTO_DIR}/sources/cmake/os_common.cmake") if(("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_MSVC_COMPILER_VER)) message(FATAL_ERROR "Microsoft Visual C++ Compiler version must be 19.14 or higher (MSVC 19.14 or higher)") endif() if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_GNU_COMPILER_VER)) message(FATAL_ERROR "GNU C Compiler version must be 8.2 or higher") endif() if(("${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_APPLE_CLANG_COMPILER_VER)) message(FATAL_ERROR "Apple Clang C Compiler version must be 12.0 or higher") endif() if(("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_CLANG_COMPILER_VER)) message(FATAL_ERROR "Clang C Compiler version must be 9.0 or higher") endif() if(("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")) set(CLANG_COMPILER ON) set(CLANG_COMPILER ${CLANG_COMPILER} PARENT_SCOPE) endif() # Compiler options file set(COMPILER_OPTIONS_FILE "${IPP_CRYPTO_DIR}/sources/cmake/${OS_STRING}") if (EXISTS "${COMPILER_OPTIONS_FILE}/${CMAKE_C_COMPILER_ID}${CMAKE_C_COMPILER_VERSION_SHORT}.cmake") set(COMPILER_OPTIONS_FILE "${COMPILER_OPTIONS_FILE}/${CMAKE_C_COMPILER_ID}${CMAKE_C_COMPILER_VERSION_SHORT}.cmake") else() if ("${DEFAULT_${CMAKE_C_COMPILER_ID}${CMAKE_C_COMPILER_VERSION_MAJOR}_COMPILER_VER}" STREQUAL "") if ("${DEFAULT_${CMAKE_C_COMPILER_ID}_COMPILER_VER}" STREQUAL "") set(COMPILER_OPTIONS_FILE "${COMPILER_OPTIONS_FILE}/${OS_DEFAULT_COMPILER}.cmake") message(WARNING "Unknown compiler, using options from the OS default one: ${OS_DEFAULT_COMPILER}") else() set(COMPILER_OPTIONS_FILE "${COMPILER_OPTIONS_FILE}/${CMAKE_C_COMPILER_ID}${DEFAULT_${CMAKE_C_COMPILER_ID}_COMPILER_VER}.cmake") if(CMAKE_C_COMPILER_VERSION VERSION_LESS ${DEFAULT_${CMAKE_C_COMPILER_ID}_COMPILER_VER}) message(WARNING "Version of the compiler is lower than default, using options from: ${DEFAULT_${CMAKE_C_COMPILER_ID}_COMPILER_VER}") endif() endif() else() set(COMPILER_OPTIONS_FILE "${COMPILER_OPTIONS_FILE}/${CMAKE_C_COMPILER_ID}${DEFAULT_${CMAKE_C_COMPILER_ID}${CMAKE_C_COMPILER_VERSION_MAJOR}_COMPILER_VER}.cmake") endif() endif() message (STATUS "Using compiler options from ........... " ${COMPILER_OPTIONS_FILE}) # Assembler options # Note: do not move this initialization after LIBRARY_DEFINES extension set(CMAKE_USER_MAKE_RULES_OVERRIDE_ASM "${IPP_CRYPTO_DIR}/sources/cmake/CMakeASM_NASMOptions.txt") enable_language(ASM_NASM) if(NOT CMAKE_ASM_NASM_COMPILER_LOADED) message(FATAL_ERROR "Can't find assembler") endif() message(STATUS "ASM compiler version .................. " ${CMAKE_ASM_NASM_COMPILER}) message(STATUS "ASM object format ..................... " ${CMAKE_ASM_NASM_OBJECT_FORMAT}) # set Intel Cryptography Primitives Library revision, if required if(IPP_REVISION) # IPP_REVISION - release revision id, added into LibraryVersion set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPP_REVISION=${IPP_REVISION}") endif() # Enable tech-preview feature in the library set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPPCP_PREVIEW_XMSS -DIPPCP_PREVIEW_LMS") set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -D_NO_IPP_DEPRECATED") # do not warn about ippcp deprecated functions # set BN_OPENSSL_DISABLE for Intel Cryptography Primitives Library # set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DBN_OPENSSL_DISABLE") if(IPPCP_FIPS_MODE) set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPPCP_FIPS_MODE") # Internal memory management in FIPS Selftests if(IPPCP_SELFTEST_USE_MALLOC) set(LIBRARY_DEFINES "${LIBRARY_DEFINES} -DIPPCP_SELFTEST_USE_MALLOC") endif() endif() include(${COMPILER_OPTIONS_FILE}) # uses ${CMAKE_C_FLAGS} ${LIBRARY_DEFINES} ${opt} from the scope if(UNIX) set(CMAKE_C_CREATE_SHARED_LIBRARY " ${LIB_EXPORT_FILE} -o ") set(CMAKE_CXX_CREATE_SHARED_LIBRARY " ${LIB_EXPORT_FILE} -o ") if("${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang") string(REPLACE "" " " CMAKE_C_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_LIBRARY}) string(REPLACE "" " " CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) endif() endif(UNIX) if(NOT MERGED_BLD) set(IPPCP_LIB_STATIC "") set(IPPCP_LIB_DYNAMIC "") endif(NOT MERGED_BLD) file(GLOB IPPCP_PUBLIC_HEADERS ${IPP_CRYPTO_INCLUDE_DIR}/*.h) file(GLOB LIBRARY_HEADERS ${IPP_CRYPTO_SOURCES_DIR}/*.h ${IPP_CRYPTO_SOURCES_INCLUDE_DIR}/*.h ${IPP_CRYPTO_INCLUDE_DIR}/ippcp*.h # RSA_SB (ifma) uses crypto_mb headers ${IPP_CRYPTO_SOURCES_DIR}/crypto_mb/include/crypto_mb/*.h ) file(GLOB LIBRARY_C_SOURCES_ORIGINAL ${IPP_CRYPTO_SOURCES_DIR}/*.c ${IPP_CRYPTO_SOURCES_DIR}/hash/*.c ${IPP_CRYPTO_SOURCES_DIR}/hash/*/*.c ${IPP_CRYPTO_SOURCES_DIR}/gfpec/*.c ${IPP_CRYPTO_SOURCES_DIR}/gfpec/*/*.c ${IPP_CRYPTO_SOURCES_DIR}/xmss/*.c ${IPP_CRYPTO_SOURCES_DIR}/lms/*.c ) file(GLOB LIBRARY_ASM_SOURCES_ORIGINAL ${IPP_CRYPTO_SOURCES_DIR}/asm_${ARCH}/*.asm ) set(INTERNAL_INCLUDE_DIR ${CMAKE_BINARY_DIR}/include/autogen_1cpu) set (C_INCLUDE_DIRECTORIES ${IPP_CRYPTO_SOURCES_DIR} ${IPP_CRYPTO_SOURCES_INCLUDE_DIR} ${IPP_CRYPTO_INCLUDE_DIR} ${INTERNAL_INCLUDE_DIR} # RSA_SB (ifma) uses crypto_mb headers ${IPP_CRYPTO_SOURCES_DIR}/crypto_mb/include $<$:$ENV{ROOT}/compiler/include $ENV{ROOT}/compiler/include/icc> $<$>:${CMAKE_SYSTEM_INCLUDE_PATH}> $<$,$>:$ENV{INCLUDE}> ) set (ASM_INCLUDE_DIRECTORIES ${IPP_CRYPTO_SOURCES_INCLUDE_DIR} ${IPP_CRYPTO_SOURCES_DIR}/asm_${ARCH} ) if(IPPCP_FIPS_MODE) file(GLOB IPPCP_FIPS_CERT_PUBLIC_HEADERS ${IPP_CRYPTO_INCLUDE_DIR}/ippcp/*.h ) file(GLOB IPPCP_FIPS_CERT_INTERNAL_HEADERS ${IPPCP_FIPS_CERT_PUBLIC_HEADERS} ${IPP_CRYPTO_SOURCE_INCLUDE_DIR}/fips_cert_internal/*.h ) file(GLOB IPPCP_FIPS_CERT_LIBRARY_C_SOURCES ${IPP_CRYPTO_SOURCES_DIR}/fips_cert/*.c ) list(APPEND IPPCP_PUBLIC_HEADERS "${IPPCP_FIPS_CERT_PUBLIC_HEADERS}") list(APPEND LIBRARY_HEADERS "${IPPCP_FIPS_CERT_INTERNAL_HEADERS}") set_source_files_properties(${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES} PROPERTIES INCLUDE_DIRECTORIES "${C_INCLUDE_DIRECTORIES}") # Add FIPS custom API header if(FIPS_CUSTOM_IPPCP_API_HEADER) message (STATUS "Using FIPS_CUSTOM_IPPCP_API_HEADER ......................... " ${FIPS_CUSTOM_IPPCP_API_HEADER}) if(WIN32) set_source_files_properties(${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES} PROPERTIES COMPILE_FLAGS "/FI${FIPS_CUSTOM_IPPCP_API_HEADER}") else() set_source_files_properties(${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES} PROPERTIES COMPILE_FLAGS "-imacros ${FIPS_CUSTOM_IPPCP_API_HEADER}") endif() endif() endif() # Because of CMake bug (https://gitlab.kitware.com/cmake/cmake/issues/19178) it is impossible to add # target specific NASM compiler options/definitions when using VS generator, but it is possible to specify # them based on source files. So, here is the workaround - we spawn same assembler sources across different # platform-specific directories and assign different definitions for each directory using set_source_files_properties(). # # The same trick is used for C sources, but it aims a different purpose: to rename object files in the library archive, # so that they do not intersect in a 'merged' library. foreach(opt ${PLATFORM_LIST}) # Populate ASM source files in to corresponding folders per library 'letter' set(asm_cache_dir "${CMAKE_BINARY_DIR}/asm_sources/${opt}/asm_${ARCH}") file(MAKE_DIRECTORY ${asm_cache_dir}) # Prefer configure_file() over simple file(COPY) as it creates dependencies, so that cmake project # will be regenerated each time when any original file is changed. This is needed to keep all copied files up-to-date. foreach (file ${LIBRARY_ASM_SOURCES_ORIGINAL}) get_filename_component(basename ${file} NAME) configure_file(${file} ${asm_cache_dir}/${opt}_${basename} COPYONLY) endforeach() file (GLOB LIBRARY_ASM_SOURCES_${opt} ${asm_cache_dir}/*.asm ) set_source_files_properties(${LIBRARY_ASM_SOURCES_${opt}} PROPERTIES COMPILE_DEFINITIONS "$<$:_MERGED_BLD>;${${opt}_def}" COMPILE_OPTIONS "$<$:${CMAKE_ASM_NASM_DEBUG_OPTIONS}>" INCLUDE_DIRECTORIES "${ASM_INCLUDE_DIRECTORIES}") ######################################################################################### # Populate C source files in to corresponding folders per library 'letter' if (NOT CODE_COVERAGE) set(c_cache_dir "${CMAKE_BINARY_DIR}/c_sources/${opt}/c_${ARCH}") file(MAKE_DIRECTORY ${c_cache_dir}) # Add a prefix to the source files, so that corresponding object files in the merged library are unique named foreach (file ${LIBRARY_C_SOURCES_ORIGINAL}) get_filename_component(basename ${file} NAME) configure_file(${file} ${c_cache_dir}/${opt}_${basename} COPYONLY) endforeach() file (GLOB LIBRARY_C_SOURCES_${opt} ${c_cache_dir}/*.c ) else() # Code coverage data gathering is a bit easier, when sources for ISA-specific builds point to the same location on a filesystem set(LIBRARY_C_SOURCES_${opt} "${LIBRARY_C_SOURCES_ORIGINAL}") endif() set_source_files_properties(${LIBRARY_C_SOURCES_${opt}} pcpver.rc PROPERTIES INCLUDE_DIRECTORIES "${C_INCLUDE_DIRECTORIES}") # Set optimization flag for cpinit.c to -O1 # Fix for problem related with MSVC compiler -O2 optimization if((${ARCH} STREQUAL "intel64") AND ("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")) set_source_files_properties("${c_cache_dir}/${opt}_cpinit.c" PROPERTIES COMPILE_FLAGS " /O1") endif() endforeach() # Generate single-CPU headers if(MERGED_BLD) set(ONE_CPU_FOLDER ${INTERNAL_INCLUDE_DIR}/single_cpu) set(ONE_CPU_GENERATOR ${IPP_CRYPTO_DIR}/sources/gen_cpu_spc_header/gen_cpu_spc_1cpu_header.py) execute_process(COMMAND ${Python_EXECUTABLE} ${ONE_CPU_GENERATOR} ${IPP_CRYPTO_INCLUDE_DIR}/ippcp.h ${ONE_CPU_FOLDER}) file(GLOB ONE_CPU_HEADERS "${ONE_CPU_FOLDER}/*.h") set(INTERNAL_GENERATOR ${IPP_CRYPTO_DIR}/sources/gen_cpu_spc_header/gen_cpu_spc_header.py) execute_process(COMMAND ${Python_EXECUTABLE} ${INTERNAL_GENERATOR} ${IPP_CRYPTO_INCLUDE_DIR}/ippcp.h ${INTERNAL_INCLUDE_DIR}) set(HEADERS ${LIBRARY_HEADERS} ${INTERNAL_INCLUDE_DIR}/ippcp_cpuspc.h) endif(MERGED_BLD) # Copy headers to the output directory foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) file(COPY ${IPP_CRYPTO_INCLUDE_DIR}/ippcp.h ${IPP_CRYPTO_INCLUDE_DIR}/ippcpdefs.h ${IPP_CRYPTO_INCLUDE_DIR}/ippcpversion.h ${IPP_CRYPTO_INCLUDE_DIR}/ippversion.h ${ONE_CPU_FOLDER} DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/include") if(IPPCP_FIPS_MODE) file(COPY ${IPP_CRYPTO_INCLUDE_DIR}/ippcp/fips_cert.h DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/include/ippcp") endif() endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) # Different def files depending on the build type if(IPPCP_FIPS_MODE) set(IPPCP_WIN_DEF_FILE ippcp_fips_selftests.def) else() set(IPPCP_WIN_DEF_FILE ippcp.def) endif() foreach(opt ${PLATFORM_LIST}) set(OPT_FLAGS_${opt} ${${opt}_opt}) if(DYNAMIC_LIB AND NOT MERGED_BLD) set(IPPCP_DYN_ITER ${TARGET_NAME}_dyn_${opt}) set(IPPCP_DYN_ITER_ASMOBJS ${TARGET_NAME}_dyn_${opt}-asmobjs) if(WIN32) add_library(${IPPCP_DYN_ITER_ASMOBJS} OBJECT ${LIBRARY_ASM_SOURCES_${opt}}) add_library(${IPPCP_DYN_ITER} SHARED ${IPPCP_WIN_DEF_FILE} pcpver.rc ${LIBRARY_HEADERS} ${LIBRARY_C_SOURCES_${opt}} ${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES} $) set_target_properties(${IPPCP_DYN_ITER} PROPERTIES LINK_FLAGS ${LINK_FLAG_DYNAMIC_WINDOWS}) foreach(link ${LINK_LIB_STATIC_DEBUG}) target_link_libraries(${IPPCP_DYN_ITER} debug ${link}) endforeach() foreach(link ${LINK_LIB_STATIC_RELEASE}) target_link_libraries(${IPPCP_DYN_ITER} optimized ${link}) endforeach() else() add_library(${IPPCP_DYN_ITER_ASMOBJS} OBJECT ${LIBRARY_ASM_SOURCES_${opt}}) add_library(${IPPCP_DYN_ITER} SHARED ${LIBRARY_HEADERS} ${LIBRARY_C_SOURCES_${opt}} ${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES} $) if(APPLE) ## gres: copy LINK_FLAG_DYNAMIC_LINUX set(LINK_FLAGS ${LINK_FLAG_DYNAMIC_MACOSX}) ## add export file set(LINK_FLAGS "${LINK_FLAGS} -exported_symbols_list ${IPP_CRYPTO_SOURCES_DIR}/exports.macosx.lib-export") if (IPPCP_FIPS_MODE) set(LINK_FLAGS "${LINK_FLAGS} -exported_symbols_list ${IPP_CRYPTO_SOURCES_DIR}/exports.macosx.selftests-export") endif() set_target_properties(${IPPCP_DYN_ITER} PROPERTIES LINK_FLAGS "${LINK_FLAGS}") add_custom_command(TARGET ${IPPCP_DYN_ITER} POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -id @rpath/lib${TARGET_NAME}${opt}.dylib $) else() ## gres: copy LINK_FLAG_DYNAMIC_LINUX set(LINK_FLAGS ${LINK_FLAG_DYNAMIC_LINUX}) ## add export file if (IPPCP_FIPS_MODE) set(LINK_FLAGS "${LINK_FLAGS} ${IPP_CRYPTO_SOURCES_DIR}/exports.linux.selftests-export") else() set(LINK_FLAGS "${LINK_FLAGS} ${IPP_CRYPTO_SOURCES_DIR}/exports.linux.lib-export") endif() set_target_properties(${IPPCP_DYN_ITER} PROPERTIES LINK_FLAGS ${LINK_FLAGS}) endif() if(NOT APPLE) if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${IPPCP_DYN_ITER} gcc) # gcc is because of -nostdlib target_link_libraries(${IPPCP_DYN_ITER} c) # for printf - debug purpose only, not used endif() endif() endif() set_target_properties(${IPPCP_DYN_ITER} PROPERTIES OUTPUT_NAME "${TARGET_NAME}${opt}" COMPILE_FLAGS "${OPT_FLAGS_${opt}}" COMPILE_DEFINITIONS "_IPP_DYNAMIC;${${opt}_def}" PUBLIC_HEADER "${IPPCP_PUBLIC_HEADERS}" ) if(UNIX) set_target_properties(${IPPCP_DYN_ITER} PROPERTIES VERSION ${IPPCP_INTERFACE_VERSION} SOVERSION ${IPPCP_INTERFACE_VERSION_MAJOR}) endif() install(TARGETS ${IPPCP_DYN_ITER} LIBRARY DESTINATION "lib/${ARCH}/$<$:nonpic>" RUNTIME DESTINATION "lib/${ARCH}/$<$:nonpic>" PUBLIC_HEADER DESTINATION "include") list(APPEND IPPCP_LIB_DYNAMIC ${IPPCP_DYN_ITER}) endif(DYNAMIC_LIB AND NOT MERGED_BLD) set(IPPCP_ST_ITER ${TARGET_NAME}_s_${opt}) set(IPPCP_ST_ITER_ASMOBJS ${TARGET_NAME}_s_${opt}-asmobjs) if(MERGED_BLD) add_library(${IPPCP_ST_ITER} OBJECT ${LIBRARY_HEADERS} ${LIBRARY_C_SOURCES_${opt}} ${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES}) add_library(${IPPCP_ST_ITER_ASMOBJS} OBJECT ${LIBRARY_ASM_SOURCES_${opt}}) set(merged_dependency ${merged_dependency} $ $) else() add_library(${IPPCP_ST_ITER_ASMOBJS} OBJECT ${LIBRARY_ASM_SOURCES_${opt}}) add_library(${IPPCP_ST_ITER} STATIC ${LIBRARY_HEADERS} ${LIBRARY_C_SOURCES_${opt}} ${IPPCP_FIPS_CERT_LIBRARY_C_SOURCES} $) endif() if(WIN32) set_target_properties(${IPPCP_ST_ITER} ${IPPCP_ST_ITER_ASMOBJS} PROPERTIES STATIC_LIBRARY_FLAGS ${LINK_FLAG_STATIC_WINDOWS}) endif() set_target_properties(${IPPCP_ST_ITER} PROPERTIES COMPILE_FLAGS "${OPT_FLAGS_${opt}}" COMPILE_DEFINITIONS "$<$:_MERGED_BLD>;${${opt}_def}") # Merged build install is handled in another target if (NOT MERGED_BLD) set_target_properties(${IPPCP_ST_ITER} PROPERTIES PUBLIC_HEADER "${IPPCP_PUBLIC_HEADERS}") install(TARGETS ${IPPCP_ST_ITER} ARCHIVE DESTINATION "lib/${ARCH}/$<$:nonpic>" PUBLIC_HEADER DESTINATION "include") endif() list(APPEND IPPCP_LIB_STATIC ${IPPCP_ST_ITER}) endforeach() if(NOT MERGED_BLD) set(IPPCP_LIB_STATIC ${IPPCP_LIB_STATIC} PARENT_SCOPE) set(IPPCP_LIB_DYNAMIC ${IPPCP_LIB_DYNAMIC} PARENT_SCOPE) endif() if(MERGED_BLD) set(DISPATCHER ${CMAKE_BINARY_DIR}/dispatcher) set(IPPCP_API ${IPP_CRYPTO_INCLUDE_DIR}/ippcp.h) file(MAKE_DIRECTORY ${DISPATCHER}) if(WIN32) if(${ARCH} MATCHES "ia32") set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_win32.py) else() set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_win64.py) endif() elseif(UNIX) if(APPLE) set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_mac64.py) else() if(NOT NONPIC_LIB) if(${ARCH} MATCHES "ia32") set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_lin32.py) else() set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_lin64.py) endif() else() if(${ARCH} MATCHES "ia32") set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_lin32.nonpic.py) else() set(DISPATCHER_GENERATOR ${IPP_CRYPTO_DISPATCHER_DIR}/gen_disp_lin64.nonpic.py) endif() endif() endif() endif(WIN32) execute_process(COMMAND ${Python_EXECUTABLE} ${DISPATCHER_GENERATOR} -i ${IPPCP_API} -o ${DISPATCHER} -l "${PLATFORM_LIST}" -c ${CMAKE_C_COMPILER_ID} RESULT_VARIABLE result ) file(GLOB DISPATCHER_HEADERS ${CMAKE_BINARY_DIR}/dispatcher/*.h ) file(GLOB DISPATCHER_C_SOURCES ${CMAKE_BINARY_DIR}/dispatcher/*.c ) file(GLOB DISPATCHER_ASM_SOURCES ${CMAKE_BINARY_DIR}/dispatcher/*.asm ) set(IPPCP_LIB_MERGED ${TARGET_NAME}_s) add_library(${IPPCP_LIB_MERGED} STATIC ${DISPATCHER_HEADERS} ${DISPATCHER_C_SOURCES} ${DISPATCHER_ASM_SOURCES} ${merged_dependency}) set(IPPCP_LIB_MERGED ${IPPCP_LIB_MERGED} PARENT_SCOPE) if(WIN32) set_target_properties(${IPPCP_LIB_MERGED} PROPERTIES OUTPUT_NAME "${TARGET_NAME}mt") set_target_properties(${IPPCP_LIB_MERGED} PROPERTIES STATIC_LIBRARY_FLAGS ${LINK_FLAG_STATIC_WINDOWS}) else() set_target_properties(${IPPCP_LIB_MERGED} PROPERTIES OUTPUT_NAME "${TARGET_NAME}") endif(WIN32) set_target_properties(${IPPCP_LIB_MERGED} PROPERTIES PUBLIC_HEADER "${IPPCP_PUBLIC_HEADERS}" PRIVATE_HEADER "${ONE_CPU_HEADERS}") install(TARGETS ${IPPCP_LIB_MERGED} ARCHIVE DESTINATION "lib/${ARCH}/$<$:nonpic>" PUBLIC_HEADER DESTINATION "include" PRIVATE_HEADER DESTINATION "tools/${ARCH}/staticlib") set_source_files_properties(${DISPATCHER_ASM_SOURCES} PROPERTIES INCLUDE_DIRECTORIES "${ASM_INCLUDE_DIRECTORIES}") # Intel® C++ Compiler specific - the dispatcher also contains C source code # that doesn't use build settings from CMAKE_C/CXX_FLAGS_DEBUG/RELEASE set_source_files_properties(${DISPATCHER_C_SOURCES} pcpver.rc PROPERTIES INCLUDE_DIRECTORIES "${C_INCLUDE_DIRECTORIES}") # protection (_FORTIFY_SOURCE) and optimization flags for dispatcher if(UNIX) set(DISPATCHER_C_SOURCES_COMPILE_FLAGS "-D_GNU_SOURCE -O2") if(CMAKE_BUILD_TYPE STREQUAL "Release") set(DISPATCHER_C_SOURCES_COMPILE_FLAGS "${DISPATCHER_C_SOURCES_COMPILE_FLAGS} -D_FORTIFY_SOURCE=2") endif() if(${ARCH} MATCHES "ia32") set(DISPATCHER_C_SOURCES_COMPILE_FLAGS " ${CC_FLAGS_INLINE_ASM_UNIX_IA32} ${DISPATCHER_C_SOURCES_COMPILE_FLAGS}") else() set(DISPATCHER_C_SOURCES_COMPILE_FLAGS "${CC_FLAGS_INLINE_ASM_UNIX_INTEL64} ${DISPATCHER_C_SOURCES_COMPILE_FLAGS}") endif() set_source_files_properties(${DISPATCHER_C_SOURCES} PROPERTIES COMPILE_FLAGS "${DISPATCHER_C_SOURCES_COMPILE_FLAGS}") endif() # Single merged dynamic lib if(DYNAMIC_LIB) set(IPPCP_LIB_PCS ${TARGET_NAME}_dyn) set(IPPCP_LIB_PCS ${IPPCP_LIB_PCS} PARENT_SCOPE) if(WIN32) add_library(${IPPCP_LIB_PCS} SHARED ${IPPCP_WIN_DEF_FILE} emptyfile.c pcpver.rc) # emptyfile.c - Visual Studio does not produce a .dll without source files else() add_library(${IPPCP_LIB_PCS} SHARED emptyfile.c) # emptyfile.c to suppress the cmake warning endif() set_target_properties(${IPPCP_LIB_PCS} PROPERTIES LINKER_LANGUAGE C COMPILE_DEFINITIONS "_MERGED_BLD" PUBLIC_HEADER "${IPPCP_PUBLIC_HEADERS}" PRIVATE_HEADER "${ONE_CPU_HEADERS}") if(UNIX) set_target_properties(${IPPCP_LIB_PCS} PROPERTIES VERSION ${IPPCP_INTERFACE_VERSION} SOVERSION ${IPPCP_INTERFACE_VERSION_MAJOR}) endif() target_link_libraries(${IPPCP_LIB_PCS} ${IPPCP_LIB_MERGED}) # link to the static merged set_target_properties(${IPPCP_LIB_PCS} PROPERTIES OUTPUT_NAME "${TARGET_NAME}") install(TARGETS ${IPPCP_LIB_PCS} LIBRARY DESTINATION "lib/${ARCH}/$<$:nonpic>" RUNTIME DESTINATION "lib/${ARCH}/$<$:nonpic>" PUBLIC_HEADER DESTINATION "include" PRIVATE_HEADER DESTINATION "tools/${ARCH}/staticlib") if(WIN32) set_target_properties(${IPPCP_LIB_PCS} PROPERTIES LINK_FLAGS ${LINK_FLAG_DYNAMIC_WINDOWS}) foreach(link ${LINK_LIB_STATIC_DEBUG}) target_link_libraries(${IPPCP_LIB_PCS} debug ${link}) endforeach() foreach(link ${LINK_LIB_STATIC_RELEASE}) target_link_libraries(${IPPCP_LIB_PCS} optimized ${link}) endforeach() else() if(APPLE) set(LINK_FLAGS ${LINK_FLAG_PCS_MACOSX}) ## add export file set(LINK_FLAGS "${LINK_FLAGS} -exported_symbols_list ${IPP_CRYPTO_SOURCES_DIR}/exports.macosx.lib-export") if (IPPCP_FIPS_MODE) set(LINK_FLAGS "${LINK_FLAGS} -exported_symbols_list ${IPP_CRYPTO_SOURCES_DIR}/exports.macosx.selftests-export") endif() set_target_properties(${IPPCP_LIB_PCS} PROPERTIES LINK_FLAGS "${LINK_FLAGS}") add_custom_command(TARGET ${IPPCP_LIB_PCS} POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -id @rpath/lib${TARGET_NAME}.dylib $) else() set(LINK_FLAGS ${LINK_FLAG_PCS_LINUX}) ## add export file if (IPPCP_FIPS_MODE) set(LINK_FLAGS "${LINK_FLAGS} ${IPP_CRYPTO_SOURCES_DIR}/exports.linux.selftests-export") else() set(LINK_FLAGS "${LINK_FLAGS} ${IPP_CRYPTO_SOURCES_DIR}/exports.linux.lib-export") endif() set_target_properties(${IPPCP_LIB_PCS} PROPERTIES LINK_FLAGS ${LINK_FLAGS}) if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") target_link_libraries(${IPPCP_LIB_PCS} gcc) # gcc is because of -nostdlib target_link_libraries(${IPPCP_LIB_PCS} c) # for stack check on gcc endif() endif() endif(WIN32) endif(DYNAMIC_LIB) endif() # Generate CMake configs to let external projects find ippcp and crypto_mb libraries easily include("${IPP_CRYPTO_DIR}/sources/cmake/ippcp-gen-config.cmake") # Install Custom Library tool install(DIRECTORY "${TOOLS_DIR}/ipp_custom_library_tool_python/" DESTINATION "tools/custom_library_tool_python") # Crypto multi-buffer library if ((NOT NO_CRYPTO_MB) AND ("${ARCH}" STREQUAL "intel64")) # MB_STANDALONE adjusts some build settings in crypto_mb # (e.g. output directories, make some crypto_mb build variables visible in parent scope, etc) set(MB_STANDALONE false) add_subdirectory(crypto_mb) # Throw these variables further up, so that tests can grab them and link to crypto_mb libraries set(MB_DYN_LIB_TARGET "${MB_DYN_LIB_TARGET}" PARENT_SCOPE) set(MB_STATIC_LIB_TARGET "${MB_STATIC_LIB_TARGET}" PARENT_SCOPE) # Copy crypto_mb public headers to the output directory foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) foreach(HEADER ${MB_PUBLIC_HEADERS}) file(COPY "${HEADER}" DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/include/crypto_mb") endforeach(HEADER ${MB_PUBLIC_HEADERS}) endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) # Interface versions (a.k.a. shared library versions) of ippcp and crypto_mb shall be equal, # as they share single cmake-config routine with same "package name" IPPCP (in terms of find_package()). # The intention behind this is ippcp and crypto_mb are part of the same product, and should # share single find_package() call that can accept just one version common for all package components. if(NOT "${IPPCP_INTERFACE_VERSION}" MATCHES "${MBX_INTERFACE_VERSION}") message(SEND_ERROR "IPPCP_INTERFACE_VERSION and MBX_INTERFACE_VERSION don't match") endif() endif() cryptography-primitives-1.0.0/sources/ippcp/aes_cfb_aesni_mb.h000066400000000000000000000022351470420105600246230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ #if !defined(_AES_CFB_AESNI_MB) #define _AES_CFB_AESNI_MB #include "owndefs.h" #include "owncp.h" #if (_IPP32E>=_IPP32E_Y8) #define aes_cfb16_enc_aesni_mb4 OWNAPI(aes_cfb16_enc_aesni_mb4) IPP_OWN_DECL (void, aes_cfb16_enc_aesni_mb4, (const Ipp8u* const source_pa[4], Ipp8u* const dst_pa[4], const int len[4], const int num_of_rounds, const Ipp32u* enc_keys[4], const Ipp8u* pIV[4])) #endif #endif /* _AES_CFB_AESNI_MB */ cryptography-primitives-1.0.0/sources/ippcp/aes_cfb_aesni_mb4.c000066400000000000000000000062361470420105600247070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "aes_cfb_aesni_mb.h" #if (_IPP32E>=_IPP32E_Y8) static inline void aes_encrypt4_aesni_mb4(__m128i blocks[4], __m128i enc_keys[4][15], int cipherRounds) { blocks[0] = _mm_xor_si128(blocks[0], enc_keys[0][0]); blocks[1] = _mm_xor_si128(blocks[1], enc_keys[1][0]); blocks[2] = _mm_xor_si128(blocks[2], enc_keys[2][0]); blocks[3] = _mm_xor_si128(blocks[3], enc_keys[3][0]); int nr; for (nr = 1; nr < cipherRounds; nr += 1) { blocks[0] = _mm_aesenc_si128(blocks[0], enc_keys[0][nr]); blocks[1] = _mm_aesenc_si128(blocks[1], enc_keys[1][nr]); blocks[2] = _mm_aesenc_si128(blocks[2], enc_keys[2][nr]); blocks[3] = _mm_aesenc_si128(blocks[3], enc_keys[3][nr]); } blocks[0] = _mm_aesenclast_si128(blocks[0], enc_keys[0][nr]); blocks[1] = _mm_aesenclast_si128(blocks[1], enc_keys[1][nr]); blocks[2] = _mm_aesenclast_si128(blocks[2], enc_keys[2][nr]); blocks[3] = _mm_aesenclast_si128(blocks[3], enc_keys[3][nr]); } IPP_OWN_DEFN (void, aes_cfb16_enc_aesni_mb4, (const Ipp8u* const source_pa[4], Ipp8u* const dst_pa[4], const int len[4], const int cipherRounds, const Ipp32u* enc_keys[4], const Ipp8u* pIV[4])) { __m128i* pSrc[4]; __m128i* pDst[4]; __m128i blocks[4]; __m128i plainBlocks[4]; int nBlocks[4]; int maxBlocks = 0; __m128i keySchedule[4][15]; for (int i = 0; i < 4; i++) { pSrc[i] = (__m128i*)source_pa[i]; pDst[i] = (__m128i*)dst_pa[i]; nBlocks[i] = len[i] / CFB16_BLOCK_SIZE; if(nBlocks[i] > 0) { blocks[i] = _mm_loadu_si128((__m128i const*)(pIV[i])); for (int j = 0; j <= cipherRounds; j++) { keySchedule[i][j] = _mm_loadu_si128((__m128i const*)enc_keys[i] + j); } } if (nBlocks[i] > maxBlocks) { maxBlocks = nBlocks[i]; } } for (int block = 0; block < maxBlocks; block++) { aes_encrypt4_aesni_mb4(blocks, keySchedule, cipherRounds); for (int i = 0; i < 4; i++) { if (nBlocks[i] > 0) { plainBlocks[i] = _mm_loadu_si128(pSrc[i]); blocks[i] = _mm_xor_si128(blocks[i], plainBlocks[i]); _mm_storeu_si128(pDst[i], blocks[i]); pSrc[i]+= 1; pDst[i]+= 1; nBlocks[i] -= 1; } } } } #endif cryptography-primitives-1.0.0/sources/ippcp/aes_cfb_vaes_mb.h000066400000000000000000000050461470420105600244650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ #if !defined(_AES_CFB_VAES_MB) #define _AES_CFB_VAES_MB #include "owndefs.h" #include "owncp.h" #if (_IPP32E>=_IPP32E_K1) #define TRANSPOSE_4x4_I128(X0_, X1_ ,X2_ ,X3_) {\ __m512i T0_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, X0_, X1_, 0b01000100); \ __m512i T1_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, X2_, X3_, 0b01000100); \ __m512i T2_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, X0_, X1_, 0b11101110); \ __m512i T3_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, X2_, X3_, 0b11101110); \ \ X0_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, T0_, T1_, 0b10001000); \ X1_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, T0_, T1_, 0b11011101); \ X2_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, T2_, T3_, 0b10001000); \ X3_ = _mm512_maskz_shuffle_i64x2((__mmask8)0xFF, T2_, T3_, 0b11011101); \ } #define UPDATE_MASK(len64, mask) {\ if (len64 < 2 * 4 && len64 >= 0) \ mask = (__mmask8)(((1 << len64) - 1) & 0xFF); \ else if (len64 < 0) \ mask = 0; \ } #define aes_cfb16_enc_vaes_mb4 OWNAPI(aes_cfb16_enc_vaes_mb4) IPP_OWN_DECL (void, aes_cfb16_enc_vaes_mb4, (const Ipp8u* const source_pa[4], Ipp8u* const dst_pa[4], const int len[4], const int num_of_rounds, const Ipp32u* enc_keys[4], const Ipp8u* pIV[4])) #define aes_cfb16_enc_vaes_mb8 OWNAPI(aes_cfb16_enc_vaes_mb8) IPP_OWN_DECL (void, aes_cfb16_enc_vaes_mb8, (const Ipp8u* const source_pa[8], Ipp8u* const dst_pa[8], const int len[8], const int num_of_rounds, const Ipp32u* enc_keys[8], const Ipp8u* pIV[8])) #define aes_cfb16_enc_vaes_mb16 OWNAPI(aes_cfb16_enc_vaes_mb16) IPP_OWN_DECL (void, aes_cfb16_enc_vaes_mb16, (const Ipp8u* const source_pa[16], Ipp8u* const dst_pa[16], const int len[16], const int num_of_rounds, const Ipp32u* enc_keys[16], const Ipp8u* pIV[16])) #endif #endif /* _AES_CFB_VAES_MB */ cryptography-primitives-1.0.0/sources/ippcp/aes_cfb_vaes_mb16.c000066400000000000000000000310421470420105600246220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "aes_cfb_vaes_mb.h" #if(_IPP32E>=_IPP32E_K1) #define AES_ENCRYPT_VAES_MB16(b0, b1, b2, b3, pRkey, num_rounds) { \ __m512i (*tkeys)[4] = &pRkey[num_rounds-9]; \ b0 = _mm512_xor_si512(b0, pRkey[0][0]); \ b1 = _mm512_xor_si512(b1, pRkey[0][1]); \ b2 = _mm512_xor_si512(b2, pRkey[0][2]); \ b3 = _mm512_xor_si512(b3, pRkey[0][3]); \ switch(num_rounds) { \ case 14: \ b0 = _mm512_aesenc_epi128(b0, tkeys[-4][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-4][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[-4][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[-4][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[-3][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-3][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[-3][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[-3][3]); \ case 12: \ b0 = _mm512_aesenc_epi128(b0, tkeys[-2][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-2][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[-2][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[-2][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[-1][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-1][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[-1][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[-1][3]); \ default: \ b0 = _mm512_aesenc_epi128(b0, tkeys[0][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[0][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[0][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[0][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[1][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[1][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[1][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[1][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[2][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[2][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[2][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[2][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[3][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[3][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[3][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[3][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[4][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[4][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[4][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[4][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[5][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[5][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[5][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[5][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[6][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[6][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[6][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[6][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[7][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[7][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[7][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[7][3]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[8][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[8][1]); \ b2 = _mm512_aesenc_epi128(b2, tkeys[8][2]); \ b3 = _mm512_aesenc_epi128(b3, tkeys[8][3]); \ \ b0 = _mm512_aesenclast_epi128(b0, tkeys[9][0]); \ b1 = _mm512_aesenclast_epi128(b1, tkeys[9][1]); \ b2 = _mm512_aesenclast_epi128(b2, tkeys[9][2]); \ b3 = _mm512_aesenclast_epi128(b3, tkeys[9][3]); \ } \ } // Disable optimization for MSVC #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma optimize( "", off ) #endif IPP_OWN_DEFN(void, aes_cfb16_enc_vaes_mb16, (const Ipp8u* const source_pa[16], Ipp8u* const dst_pa[16], const int arr_len[16], const int num_rounds, const Ipp32u* enc_keys[16], const Ipp8u* iv_pa[16])) { int i, j, k; int maxLen = 0; int loc_len64[16]; Ipp8u* loc_src[16]; Ipp8u* loc_dst[16]; __m512i iv512[4]; __mmask8 mbMask128[16] = { 0x03, 0x0C, 0x30, 0xC0, 0x03, 0x0C, 0x30, 0xC0, 0x03, 0x0C, 0x30, 0xC0, 0x03, 0x0C, 0x30, 0xC0 }; __mmask8 mbMask[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // - Local copy of length, source and target pointers, maxLen calculation for (i = 0; i < 16; i++) { // The case of the empty input buffer if (arr_len[i] == 0) { mbMask128[i] = 0; mbMask[i] = 0; loc_len64[i] = 0; continue; } loc_src[i] = (Ipp8u*)source_pa[i]; loc_dst[i] = (Ipp8u*)dst_pa[i]; int len64 = arr_len[i] / (Ipp32s)sizeof(Ipp64u); // length in 64-bit chunks loc_len64[i] = len64; if (len64 < 8) mbMask[i] = (__mmask8)(((1 << len64) - 1) & 0xFF); if (len64 > maxLen) maxLen = len64; } // Load the necessary number of 128-bit IV j = 0; for (i = 0; i < 16; i += 4) { iv512[j] = _mm512_setzero_si512(); iv512[j] = _mm512_mask_expandloadu_epi64(iv512[j], mbMask128[i], iv_pa[i]); iv512[j] = _mm512_mask_expandloadu_epi64(iv512[j], mbMask128[i + 1], iv_pa[i + 1]); iv512[j] = _mm512_mask_expandloadu_epi64(iv512[j], mbMask128[i + 2], iv_pa[i + 2]); iv512[j] = _mm512_mask_expandloadu_epi64(iv512[j], mbMask128[i + 3], iv_pa[i + 3]); j += 1; } // Temporary block to left IV unchanged to use it on the next round __m512i chip0 = iv512[0]; __m512i chip1 = iv512[1]; __m512i chip2 = iv512[2]; __m512i chip3 = iv512[3]; // Prepare array with key schedule __m512i keySchedule[15][4]; __m512i tmpKeyMb = _mm512_setzero_si512(); for (i = 0; i <= num_rounds; i++) { k = 0; for (j = 0; j < 16; j += 4) { tmpKeyMb = _mm512_setzero_si512(); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[j], (const void *)(enc_keys[j] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[j + 1], (const void *)(enc_keys[j + 1] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[j + 2], (const void *)(enc_keys[j + 2] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[j + 3], (const void *)(enc_keys[j + 3] + (Ipp32u)i * sizeof(Ipp32u))); keySchedule[i][k] = _mm512_loadu_si512(&tmpKeyMb); k += 1; } } for (; maxLen >= 0; maxLen -= 8) { __m512i b0 = _mm512_maskz_loadu_epi64(mbMask[0], loc_src[0]); loc_src[0] += CFB16_BLOCK_SIZE * 4; __m512i b1 = _mm512_maskz_loadu_epi64(mbMask[1], loc_src[1]); loc_src[1] += CFB16_BLOCK_SIZE * 4; __m512i b2 = _mm512_maskz_loadu_epi64(mbMask[2], loc_src[2]); loc_src[2] += CFB16_BLOCK_SIZE * 4; __m512i b3 = _mm512_maskz_loadu_epi64(mbMask[3], loc_src[3]); loc_src[3] += CFB16_BLOCK_SIZE * 4; __m512i b4 = _mm512_maskz_loadu_epi64(mbMask[4], loc_src[4]); loc_src[4] += CFB16_BLOCK_SIZE * 4; __m512i b5 = _mm512_maskz_loadu_epi64(mbMask[5], loc_src[5]); loc_src[5] += CFB16_BLOCK_SIZE * 4; __m512i b6 = _mm512_maskz_loadu_epi64(mbMask[6], loc_src[6]); loc_src[6] += CFB16_BLOCK_SIZE * 4; __m512i b7 = _mm512_maskz_loadu_epi64(mbMask[7], loc_src[7]); loc_src[7] += CFB16_BLOCK_SIZE * 4; __m512i b8 = _mm512_maskz_loadu_epi64(mbMask[8], loc_src[8]); loc_src[8] += CFB16_BLOCK_SIZE * 4; __m512i b9 = _mm512_maskz_loadu_epi64(mbMask[9], loc_src[9]); loc_src[9] += CFB16_BLOCK_SIZE * 4; __m512i b10 = _mm512_maskz_loadu_epi64(mbMask[10], loc_src[10]); loc_src[10] += CFB16_BLOCK_SIZE * 4; __m512i b11 = _mm512_maskz_loadu_epi64(mbMask[11], loc_src[11]); loc_src[11] += CFB16_BLOCK_SIZE * 4; __m512i b12 = _mm512_maskz_loadu_epi64(mbMask[12], loc_src[12]); loc_src[12] += CFB16_BLOCK_SIZE * 4; __m512i b13 = _mm512_maskz_loadu_epi64(mbMask[13], loc_src[13]); loc_src[13] += CFB16_BLOCK_SIZE * 4; __m512i b14 = _mm512_maskz_loadu_epi64(mbMask[14], loc_src[14]); loc_src[14] += CFB16_BLOCK_SIZE * 4; __m512i b15 = _mm512_maskz_loadu_epi64(mbMask[15], loc_src[15]); loc_src[15] += CFB16_BLOCK_SIZE * 4; TRANSPOSE_4x4_I128(b0, b1, b2, b3); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} TRANSPOSE_4x4_I128(b4, b5, b6, b7); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} TRANSPOSE_4x4_I128(b8, b9, b10, b11); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} TRANSPOSE_4x4_I128(b12, b13, b14, b15); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} AES_ENCRYPT_VAES_MB16(chip0, chip1, chip2, chip3, keySchedule, num_rounds); chip0 = b0 = _mm512_xor_si512(b0, chip0); chip1 = b4 = _mm512_xor_si512(b4, chip1); chip2 = b8 = _mm512_xor_si512(b8, chip2); chip3 = b12 = _mm512_xor_si512(b12, chip3); AES_ENCRYPT_VAES_MB16(chip0, chip1, chip2, chip3, keySchedule, num_rounds); chip0 = b1 = _mm512_xor_si512(b1, chip0); chip1 = b5 = _mm512_xor_si512(b5, chip1); chip2 = b9 = _mm512_xor_si512(b9, chip2); chip3 = b13 = _mm512_xor_si512(b13, chip3); AES_ENCRYPT_VAES_MB16(chip0, chip1, chip2, chip3, keySchedule, num_rounds); chip0 = b2 = _mm512_xor_si512(b2, chip0); chip1 = b6 = _mm512_xor_si512(b6, chip1); chip2 = b10 = _mm512_xor_si512(b10, chip2); chip3 = b14 = _mm512_xor_si512(b14, chip3); AES_ENCRYPT_VAES_MB16(chip0, chip1, chip2, chip3, keySchedule, num_rounds); chip0 = b3 = _mm512_xor_si512(b3, chip0); chip1 = b7 = _mm512_xor_si512(b7, chip1); chip2 = b11 = _mm512_xor_si512(b11, chip2); chip3 = b15 = _mm512_xor_si512(b15, chip3); TRANSPOSE_4x4_I128(b0, b1, b2, b3); TRANSPOSE_4x4_I128(b4, b5, b6, b7); TRANSPOSE_4x4_I128(b8, b9, b10, b11); TRANSPOSE_4x4_I128(b12, b13, b14, b15); _mm512_mask_storeu_epi64(loc_dst[0], mbMask[0], b0); loc_dst[0] += CFB16_BLOCK_SIZE * 4; loc_len64[0] -= 2 * 4; UPDATE_MASK(loc_len64[0], mbMask[0]); _mm512_mask_storeu_epi64(loc_dst[1], mbMask[1], b1); loc_dst[1] += CFB16_BLOCK_SIZE * 4; loc_len64[1] -= 2 * 4; UPDATE_MASK(loc_len64[1], mbMask[1]); _mm512_mask_storeu_epi64(loc_dst[2], mbMask[2], b2); loc_dst[2] += CFB16_BLOCK_SIZE * 4; loc_len64[2] -= 2 * 4; UPDATE_MASK(loc_len64[2], mbMask[2]); _mm512_mask_storeu_epi64(loc_dst[3], mbMask[3], b3); loc_dst[3] += CFB16_BLOCK_SIZE * 4; loc_len64[3] -= 2 * 4; UPDATE_MASK(loc_len64[3], mbMask[3]); _mm512_mask_storeu_epi64(loc_dst[4], mbMask[4], b4); loc_dst[4] += CFB16_BLOCK_SIZE * 4; loc_len64[4] -= 2 * 4; UPDATE_MASK(loc_len64[4], mbMask[4]); _mm512_mask_storeu_epi64(loc_dst[5], mbMask[5], b5); loc_dst[5] += CFB16_BLOCK_SIZE * 4; loc_len64[5] -= 2 * 4; UPDATE_MASK(loc_len64[5], mbMask[5]); _mm512_mask_storeu_epi64(loc_dst[6], mbMask[6], b6); loc_dst[6] += CFB16_BLOCK_SIZE * 4; loc_len64[6] -= 2 * 4; UPDATE_MASK(loc_len64[6], mbMask[6]); _mm512_mask_storeu_epi64(loc_dst[7], mbMask[7], b7); loc_dst[7] += CFB16_BLOCK_SIZE * 4; loc_len64[7] -= 2 * 4; UPDATE_MASK(loc_len64[7], mbMask[7]); _mm512_mask_storeu_epi64(loc_dst[8], mbMask[8], b8); loc_dst[8] += CFB16_BLOCK_SIZE * 4; loc_len64[8] -= 2 * 4; UPDATE_MASK(loc_len64[8], mbMask[8]); _mm512_mask_storeu_epi64(loc_dst[9], mbMask[9], b9); loc_dst[9] += CFB16_BLOCK_SIZE * 4; loc_len64[9] -= 2 * 4; UPDATE_MASK(loc_len64[9], mbMask[9]); _mm512_mask_storeu_epi64(loc_dst[10], mbMask[10], b10); loc_dst[10] += CFB16_BLOCK_SIZE * 4; loc_len64[10] -= 2 * 4; UPDATE_MASK(loc_len64[10], mbMask[10]); _mm512_mask_storeu_epi64(loc_dst[11], mbMask[11], b11); loc_dst[11] += CFB16_BLOCK_SIZE * 4; loc_len64[11] -= 2 * 4; UPDATE_MASK(loc_len64[11], mbMask[11]); _mm512_mask_storeu_epi64(loc_dst[12], mbMask[12], b12); loc_dst[12] += CFB16_BLOCK_SIZE * 4; loc_len64[12] -= 2 * 4; UPDATE_MASK(loc_len64[12], mbMask[12]); _mm512_mask_storeu_epi64(loc_dst[13], mbMask[13], b13); loc_dst[13] += CFB16_BLOCK_SIZE * 4; loc_len64[13] -= 2 * 4; UPDATE_MASK(loc_len64[13], mbMask[13]); _mm512_mask_storeu_epi64(loc_dst[14], mbMask[14], b14); loc_dst[14] += CFB16_BLOCK_SIZE * 4; loc_len64[14] -= 2 * 4; UPDATE_MASK(loc_len64[14], mbMask[14]); _mm512_mask_storeu_epi64(loc_dst[15], mbMask[15], b15); loc_dst[15] += CFB16_BLOCK_SIZE * 4; loc_len64[15] -= 2 * 4; UPDATE_MASK(loc_len64[15], mbMask[15]); } } #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma optimize( "", on ) #endif #endif cryptography-primitives-1.0.0/sources/ippcp/aes_cfb_vaes_mb4.c000066400000000000000000000140351470420105600245420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "aes_cfb_vaes_mb.h" #if(_IPP32E>=_IPP32E_K1) #define AES_ENCRYPT_VAES_MB16(b0, pRkey, num_rounds) { \ __m512i (*tkeys) = &pRkey[num_rounds-9]; \ b0 = _mm512_xor_si512(b0, pRkey[0]); \ switch(num_rounds) { \ case 14: \ b0 = _mm512_aesenc_epi128(b0, tkeys[-4]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[-3]); \ case 12: \ b0 = _mm512_aesenc_epi128(b0, tkeys[-2]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[-1]); \ default: \ b0 = _mm512_aesenc_epi128(b0, tkeys[0]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[1]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[2]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[3]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[4]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[5]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[6]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[7]); \ b0 = _mm512_aesenc_epi128(b0, tkeys[8]); \ b0 = _mm512_aesenclast_epi128(b0, tkeys[9]); \ } \ } // Disable optimization for MSVC #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma optimize( "", off ) #endif IPP_OWN_DEFN (void, aes_cfb16_enc_vaes_mb4, (const Ipp8u* const source_pa[4], Ipp8u* const dst_pa[4], const int arr_len[4], const int num_rounds, const Ipp32u* enc_keys[4], const Ipp8u* iv_pa[4])) { int i; int maxLen = 0; int loc_len64[4]; Ipp8u* loc_src[4]; Ipp8u* loc_dst[4]; __mmask8 mbMask128[4] = { 0x03, 0x0C, 0x30, 0xC0 }; __mmask8 mbMask[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; for (i = 0; i < 4; i++) { // The case of the empty input buffer if (arr_len[i] == 0) { mbMask128[i] = 0; mbMask[i] = 0; loc_len64[i] = 0; loc_src[i] = NULL; loc_dst[i] = NULL; continue; } loc_src[i] = (Ipp8u*)source_pa[i]; loc_dst[i] = (Ipp8u*)dst_pa[i]; int len64 = arr_len[i] / (Ipp32s)sizeof(Ipp64u); // length in 64-bit chunks loc_len64[i] = len64; if (len64 < 8) mbMask[i] = (__mmask8)(((1 << len64) - 1) & 0xFF); if (len64 > maxLen) maxLen = len64; } // Load the necessary number of 128-bit IV __m512i iv512 = _mm512_setzero_si512(); iv512 = _mm512_mask_expandloadu_epi64(iv512, mbMask128[0], iv_pa[0]); // 0 0 0 IV1 iv512 = _mm512_mask_expandloadu_epi64(iv512, mbMask128[1], iv_pa[1]); // 0 0 IV2 0 iv512 = _mm512_mask_expandloadu_epi64(iv512, mbMask128[2], iv_pa[2]); // 0 IV3 0 0 iv512 = _mm512_mask_expandloadu_epi64(iv512, mbMask128[3], iv_pa[3]); // IV4 0 0 0 // Temporary block to left IV unchanged to use it on the next round __m512i chip0 = iv512; // Prepare array with key schedule __m512i keySchedule[15]; __m512i tmpKeyMb = _mm512_setzero_si512(); for (i = 0; i <= num_rounds; i++) { tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[0], (const void *)(enc_keys[0] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[1], (const void *)(enc_keys[1] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[2], (const void *)(enc_keys[2] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[3], (const void *)(enc_keys[3] + (Ipp32u)i * sizeof(Ipp32u))); keySchedule[i] = _mm512_loadu_si512(&tmpKeyMb); } for (; maxLen >= 0; maxLen -= 8) { // Load plain text from the different buffers __m512i b0 = _mm512_maskz_loadu_epi64(mbMask[0], loc_src[0]); loc_src[0] += CFB16_BLOCK_SIZE * 4; __m512i b1 = _mm512_maskz_loadu_epi64(mbMask[1], loc_src[1]); loc_src[1] += CFB16_BLOCK_SIZE * 4; __m512i b2 = _mm512_maskz_loadu_epi64(mbMask[2], loc_src[2]); loc_src[2] += CFB16_BLOCK_SIZE * 4; __m512i b3 = _mm512_maskz_loadu_epi64(mbMask[3], loc_src[3]); loc_src[3] += CFB16_BLOCK_SIZE * 4; TRANSPOSE_4x4_I128(b0, b1, b2, b3); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} AES_ENCRYPT_VAES_MB16(chip0, keySchedule, num_rounds); chip0 = b0 = _mm512_xor_si512(b0, chip0); AES_ENCRYPT_VAES_MB16(chip0, keySchedule, num_rounds); chip0 = b1 = _mm512_xor_si512(b1, chip0); AES_ENCRYPT_VAES_MB16(chip0, keySchedule, num_rounds); chip0 = b2 = _mm512_xor_si512(b2, chip0); AES_ENCRYPT_VAES_MB16(chip0, keySchedule, num_rounds); chip0 = b3 = _mm512_xor_si512(b3, chip0); TRANSPOSE_4x4_I128(b0, b1, b2, b3); _mm512_mask_storeu_epi64(loc_dst[0], mbMask[0], b0); loc_dst[0] += CFB16_BLOCK_SIZE * 4; loc_len64[0] -= 2 * 4; UPDATE_MASK(loc_len64[0], mbMask[0]); _mm512_mask_storeu_epi64(loc_dst[1], mbMask[1], b1); loc_dst[1] += CFB16_BLOCK_SIZE * 4; loc_len64[1] -= 2 * 4; UPDATE_MASK(loc_len64[1], mbMask[1]); _mm512_mask_storeu_epi64(loc_dst[2], mbMask[2], b2); loc_dst[2] += CFB16_BLOCK_SIZE * 4; loc_len64[2] -= 2 * 4; UPDATE_MASK(loc_len64[2], mbMask[2]); _mm512_mask_storeu_epi64(loc_dst[3], mbMask[3], b3); loc_dst[3] += CFB16_BLOCK_SIZE * 4; loc_len64[3] -= 2 * 4; UPDATE_MASK(loc_len64[3], mbMask[3]); } } #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma optimize( "", on ) #endif #endif cryptography-primitives-1.0.0/sources/ippcp/aes_cfb_vaes_mb8.c000066400000000000000000000224661470420105600245550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "aes_cfb_vaes_mb.h" #if(_IPP32E>=_IPP32E_K1) #define AES_ENCRYPT_VAES_MB16(b0, b1, pRkey, num_rounds) { \ __m512i (*tkeys)[2] = &pRkey[num_rounds-9]; \ b0 = _mm512_xor_si512(b0, pRkey[0][0]); \ b1 = _mm512_xor_si512(b1, pRkey[0][1]); \ switch(num_rounds) { \ case 14: \ b0 = _mm512_aesenc_epi128(b0, tkeys[-4][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-4][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[-3][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-3][1]); \ case 12: \ b0 = _mm512_aesenc_epi128(b0, tkeys[-2][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-2][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[-1][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[-1][1]); \ default: \ b0 = _mm512_aesenc_epi128(b0, tkeys[0][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[0][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[1][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[1][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[2][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[2][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[3][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[3][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[4][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[4][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[5][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[5][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[6][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[6][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[7][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[7][1]); \ \ b0 = _mm512_aesenc_epi128(b0, tkeys[8][0]); \ b1 = _mm512_aesenc_epi128(b1, tkeys[8][1]); \ \ b0 = _mm512_aesenclast_epi128(b0, tkeys[9][0]); \ b1 = _mm512_aesenclast_epi128(b1, tkeys[9][1]); \ } \ } // Disable optimization for MSVC #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma optimize( "", off ) #endif IPP_OWN_DEFN (void, aes_cfb16_enc_vaes_mb8, (const Ipp8u* const source_pa[8], Ipp8u* const dst_pa[8], const int arr_len[8], const int num_rounds, const Ipp32u* enc_keys[8], const Ipp8u* iv_pa[8])) { int i; int maxLen = 0; int loc_len64[8]; Ipp8u* loc_src[8]; Ipp8u* loc_dst[8]; __m512i iv512[2]; __mmask8 mbMask128[8] = { 0x03, 0x0C, 0x30, 0xC0, 0x03, 0x0C, 0x30, 0xC0 }; __mmask8 mbMask[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; for (i = 0; i < 8; i++) { // The case of the empty input buffer if (arr_len[i] == 0) { mbMask128[i] = 0; mbMask[i] = 0; loc_len64[i] = 0; loc_src[i] = NULL; loc_dst[i] = NULL; continue; } loc_src[i] = (Ipp8u*)source_pa[i]; loc_dst[i] = (Ipp8u*)dst_pa[i]; int len64 = arr_len[i] / (Ipp32s)sizeof(Ipp64u); // length in 64-bit chunks loc_len64[i] = len64; if (len64 < 8) mbMask[i] = (__mmask8)(((1 << len64) - 1) & 0xFF); if (len64 > maxLen) maxLen = len64; } // Load the necessary number of 128-bit IV iv512[0] = _mm512_setzero_si512(); iv512[0] = _mm512_mask_expandloadu_epi64(iv512[0], mbMask128[0], iv_pa[0]); iv512[0] = _mm512_mask_expandloadu_epi64(iv512[0], mbMask128[1], iv_pa[1]); iv512[0] = _mm512_mask_expandloadu_epi64(iv512[0], mbMask128[2], iv_pa[2]); iv512[0] = _mm512_mask_expandloadu_epi64(iv512[0], mbMask128[3], iv_pa[3]); iv512[1] = _mm512_setzero_si512(); iv512[1] = _mm512_mask_expandloadu_epi64(iv512[1], mbMask128[4], iv_pa[4]); iv512[1] = _mm512_mask_expandloadu_epi64(iv512[1], mbMask128[5], iv_pa[5]); iv512[1] = _mm512_mask_expandloadu_epi64(iv512[1], mbMask128[6], iv_pa[6]); iv512[1] = _mm512_mask_expandloadu_epi64(iv512[1], mbMask128[7], iv_pa[7]); // Temporary block to left IV unchanged to use it on the next round __m512i chip0 = iv512[0]; __m512i chip1 = iv512[1]; // Prepare array with key schedule __m512i keySchedule[15][2]; __m512i tmpKeyMb = _mm512_setzero_si512(); for (i = 0; i <= num_rounds; i++) { tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[0], (const void *)(enc_keys[0] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[1], (const void *)(enc_keys[1] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[2], (const void *)(enc_keys[2] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[3], (const void *)(enc_keys[3] + (Ipp32u)i * sizeof(Ipp32u))); keySchedule[i][0] = _mm512_loadu_si512(&tmpKeyMb); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[4], (const void *)(enc_keys[4] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[5], (const void *)(enc_keys[5] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[6], (const void *)(enc_keys[6] + (Ipp32u)i * sizeof(Ipp32u))); tmpKeyMb = _mm512_mask_expandloadu_epi64(tmpKeyMb, mbMask128[7], (const void *)(enc_keys[7] + (Ipp32u)i * sizeof(Ipp32u))); keySchedule[i][1] = _mm512_loadu_si512(&tmpKeyMb); } for (; maxLen >= 0; maxLen -= 8) { // Load plain text from the different buffers __m512i b0 = _mm512_maskz_loadu_epi64(mbMask[0], loc_src[0]); loc_src[0] += CFB16_BLOCK_SIZE * 4; __m512i b1 = _mm512_maskz_loadu_epi64(mbMask[1], loc_src[1]); loc_src[1] += CFB16_BLOCK_SIZE * 4; __m512i b2 = _mm512_maskz_loadu_epi64(mbMask[2], loc_src[2]); loc_src[2] += CFB16_BLOCK_SIZE * 4; __m512i b3 = _mm512_maskz_loadu_epi64(mbMask[3], loc_src[3]); loc_src[3] += CFB16_BLOCK_SIZE * 4; __m512i b4 = _mm512_maskz_loadu_epi64(mbMask[4], loc_src[4]); loc_src[4] += CFB16_BLOCK_SIZE * 4; __m512i b5 = _mm512_maskz_loadu_epi64(mbMask[5], loc_src[5]); loc_src[5] += CFB16_BLOCK_SIZE * 4; __m512i b6 = _mm512_maskz_loadu_epi64(mbMask[6], loc_src[6]); loc_src[6] += CFB16_BLOCK_SIZE * 4; __m512i b7 = _mm512_maskz_loadu_epi64(mbMask[7], loc_src[7]); loc_src[7] += CFB16_BLOCK_SIZE * 4; TRANSPOSE_4x4_I128(b0, b1, b2, b3); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} TRANSPOSE_4x4_I128(b4, b5, b6, b7); // {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} AES_ENCRYPT_VAES_MB16(chip0, chip1, keySchedule, num_rounds); chip0 = b0 = _mm512_xor_si512(b0, chip0); chip1 = b4 = _mm512_xor_si512(b4, chip1); AES_ENCRYPT_VAES_MB16(chip0, chip1, keySchedule, num_rounds); chip0 = b1 = _mm512_xor_si512(b1, chip0); chip1 = b5 = _mm512_xor_si512(b5, chip1); AES_ENCRYPT_VAES_MB16(chip0, chip1, keySchedule, num_rounds); chip0 = b2 = _mm512_xor_si512(b2, chip0); chip1 = b6 = _mm512_xor_si512(b6, chip1); AES_ENCRYPT_VAES_MB16(chip0, chip1, keySchedule, num_rounds); chip0 = b3 = _mm512_xor_si512(b3, chip0); chip1 = b7 = _mm512_xor_si512(b7, chip1); TRANSPOSE_4x4_I128(b0, b1, b2, b3); TRANSPOSE_4x4_I128(b4, b5, b6, b7); _mm512_mask_storeu_epi64(loc_dst[0], mbMask[0], b0); loc_dst[0] += CFB16_BLOCK_SIZE * 4; loc_len64[0] -= 2 * 4; UPDATE_MASK(loc_len64[0], mbMask[0]); _mm512_mask_storeu_epi64(loc_dst[1], mbMask[1], b1); loc_dst[1] += CFB16_BLOCK_SIZE * 4; loc_len64[1] -= 2 * 4; UPDATE_MASK(loc_len64[1], mbMask[1]); _mm512_mask_storeu_epi64(loc_dst[2], mbMask[2], b2); loc_dst[2] += CFB16_BLOCK_SIZE * 4; loc_len64[2] -= 2 * 4; UPDATE_MASK(loc_len64[2], mbMask[2]); _mm512_mask_storeu_epi64(loc_dst[3], mbMask[3], b3); loc_dst[3] += CFB16_BLOCK_SIZE * 4; loc_len64[3] -= 2 * 4; UPDATE_MASK(loc_len64[3], mbMask[3]); _mm512_mask_storeu_epi64(loc_dst[4], mbMask[4], b4); loc_dst[4] += CFB16_BLOCK_SIZE * 4; loc_len64[4] -= 2 * 4; UPDATE_MASK(loc_len64[4], mbMask[4]); _mm512_mask_storeu_epi64(loc_dst[5], mbMask[5], b5); loc_dst[5] += CFB16_BLOCK_SIZE * 4; loc_len64[5] -= 2 * 4; UPDATE_MASK(loc_len64[5], mbMask[5]); _mm512_mask_storeu_epi64(loc_dst[6], mbMask[6], b6); loc_dst[6] += CFB16_BLOCK_SIZE * 4; loc_len64[6] -= 2 * 4; UPDATE_MASK(loc_len64[6], mbMask[6]); _mm512_mask_storeu_epi64(loc_dst[7], mbMask[7], b7); loc_dst[7] += CFB16_BLOCK_SIZE * 4; loc_len64[7] -= 2 * 4; UPDATE_MASK(loc_len64[7], mbMask[7]); } } #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma optimize( "", on ) #endif #endif cryptography-primitives-1.0.0/sources/ippcp/aes_gcm_avx512.h000066400000000000000000000111551470420105600241110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES GCM AVX512 // Internal Functions Prototypes // */ #ifndef __AES_GCM_AVX512_H_ #define __AES_GCM_AVX512_H_ #include "owndefs.h" #include "owncp.h" #include "aes_gcm_avx512_structures.h" #if(_IPP32E>=_IPP32E_K0) #define aes_gcm_enc_128_update_avx512 OWNAPI(aes_gcm_enc_128_update_avx512) IPP_OWN_DECL (void, aes_gcm_enc_128_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_enc_192_update_avx512 OWNAPI(aes_gcm_enc_192_update_avx512) IPP_OWN_DECL (void, aes_gcm_enc_192_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_enc_256_update_avx512 OWNAPI(aes_gcm_enc_256_update_avx512) IPP_OWN_DECL (void, aes_gcm_enc_256_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_dec_128_update_avx512 OWNAPI(aes_gcm_dec_128_update_avx512) IPP_OWN_DECL (void, aes_gcm_dec_128_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_dec_192_update_avx512 OWNAPI(aes_gcm_dec_192_update_avx512) IPP_OWN_DECL (void, aes_gcm_dec_192_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_dec_256_update_avx512 OWNAPI(aes_gcm_dec_256_update_avx512) IPP_OWN_DECL (void, aes_gcm_dec_256_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_gettag_128_avx512 OWNAPI(aes_gcm_gettag_128_avx512) IPP_OWN_DECL (void, aes_gcm_gettag_128_avx512, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) #define aes_gcm_gettag_192_avx512 OWNAPI(aes_gcm_gettag_192_avx512) IPP_OWN_DECL (void, aes_gcm_gettag_192_avx512, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) #define aes_gcm_gettag_256_avx512 OWNAPI(aes_gcm_gettag_256_avx512) IPP_OWN_DECL (void, aes_gcm_gettag_256_avx512, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) #define aes_gcm_precomp_128_avx512 OWNAPI(aes_gcm_precomp_128_avx512) IPP_OWN_DECL (void, aes_gcm_precomp_128_avx512, (struct gcm_key_data *key_data)) #define aes_gcm_precomp_192_avx512 OWNAPI(aes_gcm_precomp_192_avx512) IPP_OWN_DECL (void, aes_gcm_precomp_192_avx512, (struct gcm_key_data *key_data)) #define aes_gcm_precomp_256_avx512 OWNAPI(aes_gcm_precomp_256_avx512) IPP_OWN_DECL (void, aes_gcm_precomp_256_avx512, (struct gcm_key_data *key_data)) #define aes_gcm_aad_hash_update_avx512 OWNAPI(aes_gcm_aad_hash_update_avx512) IPP_OWN_DECL (void, aes_gcm_aad_hash_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *aad, const Ipp64u aad_len)) #define aes_gcm_iv_hash_update_avx512 OWNAPI(aes_gcm_iv_hash_update_avx512) IPP_OWN_DECL (void, aes_gcm_iv_hash_update_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *iv, const Ipp64u iv_len)) #define aes_gcm_iv_hash_finalize_avx512 OWNAPI(aes_gcm_iv_hash_finalize_avx512) IPP_OWN_DECL (void, aes_gcm_iv_hash_finalize_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *iv, const Ipp64u iv_len, const Ipp64u iv_general_len)) #define aes_gcm_gmult_avx512 OWNAPI(aes_gcm_gmult_avx512) IPP_OWN_DECL (void, aes_gcm_gmult_avx512, (const struct gcm_key_data *key_data, Ipp8u *ghash)) #endif /* #if(_IPP32E>=_IPP32E_K0) */ #endif cryptography-primitives-1.0.0/sources/ippcp/aes_gcm_avx512_structures.h000066400000000000000000000042111470420105600264070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES GCM optimized for AVX512 and AVX512-VAES features // Internal Definitions // // */ #ifndef __AES_GCM_AVX512_STRUCTURES_H_ #define __AES_GCM_AVX512_STRUCTURES_H_ #include "owndefs.h" #include "owncp.h" // declaration of internal structures used for AVX512 AES GCM optimization /* GCM data structures */ #define GCM_BLOCK_LEN 16 /** * \brief holds GCM operation context */ struct gcm_context_data { /* init, update and finalize context data */ Ipp8u aad_hash[GCM_BLOCK_LEN]; Ipp64u aad_length; Ipp64u in_length; Ipp8u partial_block_enc_key[GCM_BLOCK_LEN]; Ipp8u orig_IV[GCM_BLOCK_LEN]; Ipp8u current_counter[GCM_BLOCK_LEN]; Ipp64u partial_block_length; }; /* #define GCM_BLOCK_LEN 16 */ #define GCM_ENC_KEY_LEN 16 #define GCM_KEY_SETS (15) /*exp key + 14 exp round keys*/ /** * \brief holds intermediate key data needed to improve performance * * gcm_key_data hold internal key information used by gcm128, gcm192 and gcm256. */ struct gcm_key_data { Ipp8u expanded_keys[GCM_ENC_KEY_LEN * GCM_KEY_SETS]; /* * (HashKey<<1 mod poly), (HashKey^2<<1 mod poly), ..., * (Hashkey^48<<1 mod poly) */ Ipp8u shifted_hkey[GCM_ENC_KEY_LEN * 48]; } #ifdef LINUX __attribute__((aligned(64))); #else ; #endif #endif // __AES_GCM_AVX512_STRUCTURES_H_ cryptography-primitives-1.0.0/sources/ippcp/aes_gcm_vaes.h000066400000000000000000000114471470420105600240250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES GCM AVX512-VAES // Internal Functions Prototypes // */ #ifndef __AES_GCM_VAES_H_ #define __AES_GCM_VAES_H_ #include "owndefs.h" #include "owncp.h" #include "aes_gcm_avx512_structures.h" #if(_IPP32E>=_IPP32E_K0) #define aes_gcm_enc_128_update_vaes_avx512 OWNAPI(aes_gcm_enc_128_update_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_enc_128_update_vaes_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_enc_192_update_vaes_avx512 OWNAPI(aes_gcm_enc_192_update_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_enc_192_update_vaes_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_enc_256_update_vaes_avx512 OWNAPI(aes_gcm_enc_256_update_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_enc_256_update_vaes_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_dec_128_update_vaes_avx512 OWNAPI(aes_gcm_dec_128_update_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_dec_128_update_vaes_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_dec_192_update_vaes_avx512 OWNAPI(aes_gcm_dec_192_update_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_dec_192_update_vaes_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_dec_256_update_vaes_avx512 OWNAPI(aes_gcm_dec_256_update_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_dec_256_update_vaes_avx512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) #define aes_gcm_gettag_128_vaes_avx512 OWNAPI(aes_gcm_gettag_128_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_gettag_128_vaes_avx512, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) #define aes_gcm_gettag_192_vaes_avx512 OWNAPI(aes_gcm_gettag_192_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_gettag_192_vaes_avx512, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) #define aes_gcm_gettag_256_vaes_avx512 OWNAPI(aes_gcm_gettag_256_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_gettag_256_vaes_avx512, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) #define aes_gcm_precomp_128_vaes_avx512 OWNAPI(aes_gcm_precomp_128_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_precomp_128_vaes_avx512, (struct gcm_key_data *key_data)) #define aes_gcm_precomp_192_vaes_avx512 OWNAPI(aes_gcm_precomp_192_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_precomp_192_vaes_avx512, (struct gcm_key_data *key_data)) #define aes_gcm_precomp_256_vaes_avx512 OWNAPI(aes_gcm_precomp_256_vaes_avx512) IPP_OWN_DECL (void, aes_gcm_precomp_256_vaes_avx512, (struct gcm_key_data *key_data)) #define aes_gcm_aad_hash_update_vaes512 OWNAPI(aes_gcm_aad_hash_update_vaes512) IPP_OWN_DECL (void, aes_gcm_aad_hash_update_vaes512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *aad, const Ipp64u aad_len)) #define aes_gcm_iv_hash_update_vaes512 OWNAPI(aes_gcm_iv_hash_update_vaes512) IPP_OWN_DECL (void, aes_gcm_iv_hash_update_vaes512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *iv, const Ipp64u iv_len)) #define aes_gcm_iv_hash_finalize_vaes512 OWNAPI(aes_gcm_iv_hash_finalize_vaes512) IPP_OWN_DECL (void, aes_gcm_iv_hash_finalize_vaes512, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *iv, const Ipp64u iv_len, const Ipp64u iv_general_len)) #define aes_gcm_gmult_vaes512 OWNAPI(aes_gcm_gmult_vaes512) IPP_OWN_DECL (void, aes_gcm_gmult_vaes512, (const struct gcm_key_data *key_data, Ipp8u *ghash)) #endif /* #if(_IPP32E>=_IPP32E_K0) */ #endif cryptography-primitives-1.0.0/sources/ippcp/aes_keyexp.h000066400000000000000000000032131470420105600235360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES Key Expansion // Internal Definitions // */ #ifndef __AES_KEYEXP_H_ #define __AES_KEYEXP_H_ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm_avx512.h" // These functions for key expansion are used only with AVX512 and AVX512-VAES optimizations for AES GCM // TODO: replace AVX2 keyexp with AVX512 keyexp #if(_IPP32E>=_IPP32E_K0) #define aes_keyexp_128_enc OWNAPI(aes_keyexp_128_enc) IPP_OWN_DECL (void, aes_keyexp_128_enc, (const Ipp8u* key, struct gcm_key_data *key_data)) #define aes_keyexp_192_enc OWNAPI(aes_keyexp_192_enc) IPP_OWN_DECL (void, aes_keyexp_192_enc, (const Ipp8u* key, struct gcm_key_data *key_data)) #define aes_keyexp_256_enc OWNAPI(aes_keyexp_256_enc) IPP_OWN_DECL (void, aes_keyexp_256_enc, (const Ipp8u* key, struct gcm_key_data *key_data)) #endif // (_IPP32E>=_IPP32E_K0) #endif // __AES_KEYEXP_H_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/000077500000000000000000000000001470420105600226275ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/cpinitas.asm000066400000000000000000000422661470420105600251550ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_emm.inc" %assign LOCAL_ALIGN_FACTOR 32 segment .text align=LOCAL_ALIGN_FACTOR %ifdef _IPP_DATA ;#################################################################### ;# void ownGetReg( int* buf, int valueEAX, int valueECX ); # ;#################################################################### %define buf [esp+12] %define valueEAX [esp+16] %define valueECX [esp+20] align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpGetReg,PUBLIC push ebx push esi mov eax, valueEAX mov ecx, valueECX xor ebx, ebx xor edx, edx mov esi, buf cpuid mov [esi], eax mov [esi + 4], ebx mov [esi + 8], ecx mov [esi + 12], edx pop esi pop ebx ret ENDFUNC cpGetReg ;################################################### ; Feature information after XGETBV(ECX=0), EAX, bits 2,1 ( XMM state and YMM state are enabled by OS ) %assign XGETBV_MASK 06h ; OSXSAVE support, feature information after cpuid(1), ECX, bit 27 ( XGETBV is enabled by OS ) %assign XSAVEXGETBV_FLAG 8000000h %assign XGETBV_AVX512_MASK 0E0h align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_is_avx_extension,PUBLIC USES_GPR ebx,edx,ecx mov eax, 1 cpuid xor eax, eax and ecx, 018000000h cmp ecx, 018000000h jne .not_avx xor ecx, ecx db 00fh,001h,0d0h ; xgetbv mov ecx, eax xor eax, eax and ecx, XGETBV_MASK cmp ecx, XGETBV_MASK jne .not_avx mov eax, 1 .not_avx: REST_GPR ret ENDFUNC cp_is_avx_extension align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_is_avx512_extension,PUBLIC USES_GPR ebx,edx,ecx mov eax, 1 cpuid xor eax, eax and ecx, XSAVEXGETBV_FLAG cmp ecx, XSAVEXGETBV_FLAG jne .not_avx512 xor ecx, ecx db 00fh,001h,0d0h ; xgetbv mov ecx, eax xor eax, eax and ecx, XGETBV_AVX512_MASK cmp ecx, XGETBV_AVX512_MASK jne .not_avx512 mov eax, 1 .not_avx512: REST_GPR ret ENDFUNC cp_is_avx512_extension %ifdef LINUX32 %ifndef OSX32 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __ashldi3,PUBLIC,WEAK mov eax, [esp+4] mov edx, [esp+8] mov ecx, [esp+12] test cl, 20H je .less mov edx, eax xor eax, eax shl edx, cl ret .less: shld edx, eax, cl shl eax, cl ret ENDFUNC __ashldi3 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __ashrdi3,PUBLIC,WEAK mov eax, [esp+4] mov edx, [esp+8] mov ecx, [esp+12] test cl, 20H je .less mov eax, edx sar edx, 1FH sar eax, cl ret .less: shrd eax, edx, cl sar edx, cl ret ENDFUNC __ashrdi3 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __divdi3,PUBLIC,WEAK xor ecx, ecx mov eax, dword [8+esp] or eax, eax jge .Apositive mov ecx, 1 mov edx, dword [4+esp] neg eax neg edx sbb eax, 0 mov dword [4+esp], edx mov dword [8+esp], eax .Apositive: mov eax, dword [16+esp] or eax,eax jge .ABpositive sub ecx, 1 mov edx, dword [12+esp] neg eax neg edx sbb eax, 0 mov dword [12+esp], edx mov dword [16+esp], eax .ABpositive: mov eax, dword [16+esp] xor edx, edx push ecx test eax, eax jne .non_zero_hi mov eax, dword [12+esp] div dword [16+esp] mov ecx, eax mov eax, dword [8+esp] div dword [16+esp] mov edx, ecx jmp .return .non_zero_hi: mov ecx, dword [12+esp] cmp eax, ecx jb .divisor_greater jne .return_zero mov ecx, dword [16+esp] mov eax, dword [8+esp] cmp ecx, eax ja .return_zero .return_one: mov eax, 1 jmp .return .return_zero: add esp, 4 xor eax, eax ret .divisor_greater: test eax, 80000000h jne .return_one .find_hi_bit: bsr ecx, eax add ecx, 1 .hi_bit_found: mov edx, dword [16+esp] push ebx shrd edx, eax, cl mov ebx, edx mov eax, dword [12+esp] mov edx, dword [16+esp] shrd eax, edx, cl shr edx, cl .make_div: div ebx mov ebx, eax mul dword [24+esp] mov ecx, eax mov eax, dword [20+esp] mul ebx add edx, ecx jb .need_dec cmp dword [16+esp], edx jb .need_dec ja .after_dec cmp dword [12+esp], eax jae .after_dec .need_dec: sub ebx, 1 .after_dec: xor edx, edx mov eax, ebx pop ebx .return: pop ecx test ecx, ecx jne .ch_sign ret .ch_sign: neg edx neg eax sbb edx, 0 ret ENDFUNC __divdi3 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __udivdi3,PUBLIC,WEAK xor ecx,ecx .ABpositive: mov eax, dword [16+esp] xor edx, edx push ecx test eax, eax jne .non_zero_hi mov eax, dword [12+esp] div dword [16+esp] mov ecx, eax mov eax, dword [8+esp] div dword [16+esp] mov edx, ecx jmp .return .non_zero_hi: mov ecx, dword [12+esp] cmp eax, ecx jb .divisor_greater jne .return_zero mov ecx, dword [16+esp] mov eax, dword [8+esp] cmp ecx, eax ja .return_zero .return_one: mov eax, 1 jmp .return .return_zero: add esp, 4 xor eax, eax ret .divisor_greater: test eax, 80000000h jne .return_one .find_hi_bit: bsr ecx, eax add ecx, 1 .hi_bit_found: mov edx, dword [16+esp] push ebx shrd edx, eax, cl mov ebx, edx mov eax, dword [12+esp] mov edx, dword [16+esp] shrd eax, edx, cl shr edx, cl .make_div: div ebx mov ebx, eax mul dword [24+esp] mov ecx, eax mov eax, dword [20+esp] mul ebx add edx, ecx jb .need_dec cmp dword [16+esp], edx jb .need_dec ja .after_dec cmp dword [12+esp], eax jae .after_dec .need_dec: sub ebx, 1 .after_dec: xor edx, edx mov eax, ebx pop ebx .return: pop ecx test ecx, ecx jne .ch_sign ret .ch_sign: neg edx neg eax sbb edx, 0 ret ENDFUNC __udivdi3 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __moddi3,PUBLIC,WEAK sub esp, 8 mov dword [esp], 0 mov eax, dword [esp+16] or eax, eax jge .Apositive inc dword [esp] mov edx, dword [esp+12] neg eax neg edx sbb eax, 0 mov dword [esp+16], eax mov dword [esp+12], edx .Apositive: mov eax, dword [esp+24] or eax, eax jge .ABpositive mov edx, dword [esp+20] neg eax neg edx sbb eax, 0 mov dword [esp+24], eax mov dword [esp+20], edx jmp .ABpositive lea esi, [esi] lea edi, [edi] sub esp, 8 mov dword [esp], 0 .ABpositive: mov eax, dword [esp+24] test eax, eax jne .non_zero_hi mov eax, dword [esp+16] mov edx, 0 div dword [esp+20] mov ecx, eax mov eax, dword [12+esp] div dword [20+esp] mov eax, edx xor edx, edx jmp .return .non_zero_hi: mov ecx, dword [16+esp] cmp eax, ecx jb .divisor_greater jne .return_devisor mov ecx, dword [20+esp] cmp ecx, dword [12+esp] ja .return_devisor .return_dif: mov eax, dword [12+esp] mov edx, dword [16+esp] sub eax, dword [20+esp] sbb edx, dword [24+esp] jmp .return .return_devisor: mov eax, dword [12+esp] mov edx, dword [16+esp] jmp .return .divisor_greater: test eax, 80000000h jne .return_dif .find_hi_bit: bsr ecx, eax add ecx, 1 .hi_bit_found: push ebx mov edx, dword [24+esp] shrd edx, eax, cl mov ebx, edx mov eax, dword [16+esp] mov edx, dword [20+esp] shrd eax, edx, cl shr edx, cl div ebx mov ebx, eax .multiple: mul dword [28+esp] mov ecx, eax mov eax, dword [24+esp] mul ebx add edx, ecx jb .need_dec cmp dword [20+esp], edx jb .need_dec ja .after_dec cmp dword [16+esp], eax jb .need_dec .after_dec: mov ebx, eax mov eax, dword [16+esp] sub eax, ebx mov ebx, edx mov edx, dword [20+esp] sbb edx, ebx pop ebx .return: mov dword [4+esp], eax mov eax, dword [esp] test eax, eax jne .ch_sign mov eax, dword [4+esp] add esp, 8 ret .ch_sign: mov eax, dword [4+esp] neg edx neg eax sbb edx, 0 add esp, 8 ret .need_dec: dec ebx mov eax, ebx jmp .multiple ENDFUNC __moddi3 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __umoddi3,PUBLIC,WEAK sub esp, 8 mov dword [esp], 0 .ABpositive: mov eax, dword [esp+24] test eax, eax jne .non_zero_hi mov eax, dword [esp+16] mov edx, 0 div dword [esp+20] mov ecx, eax mov eax, dword [12+esp] div dword [20+esp] mov eax, edx xor edx, edx jmp .return .non_zero_hi: mov ecx, dword [16+esp] cmp eax, ecx jb .divisor_greater jne .return_devisor mov ecx, dword [20+esp] cmp ecx, dword [12+esp] ja .return_devisor .return_dif: mov eax, dword [12+esp] mov edx, dword [16+esp] sub eax, dword [20+esp] sbb edx, dword [24+esp] jmp .return .return_devisor: mov eax, dword [12+esp] mov edx, dword [16+esp] jmp .return .divisor_greater: test eax, 80000000h jne .return_dif .find_hi_bit: bsr ecx, eax add ecx, 1 .hi_bit_found: push ebx mov edx, dword [24+esp] shrd edx, eax, cl mov ebx, edx mov eax, dword [16+esp] mov edx, dword [20+esp] shrd eax, edx, cl shr edx, cl div ebx mov ebx, eax .multiple: mul dword [28+esp] mov ecx, eax mov eax, dword [24+esp] mul ebx add edx, ecx jb .need_dec cmp dword [20+esp], edx jb .need_dec ja .after_dec cmp dword [16+esp], eax jb .need_dec .after_dec: mov ebx, eax mov eax, dword [16+esp] sub eax, ebx mov ebx, edx mov edx, dword [20+esp] sbb edx, ebx pop ebx .return: mov dword [4+esp], eax mov eax, dword [esp] test eax, eax jne .ch_sign mov eax, dword [4+esp] add esp, 8 ret .ch_sign: mov eax, dword [4+esp] neg edx neg eax sbb edx, 0 add esp, 8 ret .need_dec: dec ebx mov eax, ebx jmp .multiple ENDFUNC __umoddi3 align LOCAL_ALIGN_FACTOR DECLARE_FUNC __muldi3,PUBLIC,WEAK mov eax, dword [esp+8] mul dword [esp+12] mov ecx, eax mov eax, dword [esp+4] mul dword [esp+16] add ecx, eax mov eax, dword [esp+4] mul dword [esp+12] add edx, ecx ret ENDFUNC __muldi3 %endif; IFNDEF OSX32 %endif; IFDEF LINUX32 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_get_pentium_counter,PUBLIC rdtsc ret ENDFUNC cp_get_pentium_counter ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStartTscp,PUBLIC push ebx xor eax, eax cpuid pop ebx rdtscp ret ENDFUNC cpStartTscp align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStopTscp,PUBLIC rdtscp push eax push edx push ebx xor eax, eax cpuid pop ebx pop edx pop eax ret ENDFUNC cpStopTscp align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStartTsc,PUBLIC push ebx xor eax, eax cpuid pop ebx rdtsc ret ENDFUNC cpStartTsc align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStopTsc,PUBLIC rdtsc push eax push edx push ebx xor eax, eax cpuid pop ebx pop edx pop eax ret ENDFUNC cpStopTsc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;***************************************** ; int cpGetCacheSize( int* tableCache ); align LOCAL_ALIGN_FACTOR %define table [36+esp] DECLARE_FUNC cpGetCacheSize,PUBLIC push edi push esi push ebx push ebp sub esp, 16 mov edi, table mov ebp, esp xor esi, esi mov eax, 2 cpuid cmp al, 1 jne .GetCacheSize_11 test eax, 080000000h jz .GetCacheSize_00 xor eax, eax .GetCacheSize_00: test ebx, 080000000h jz .GetCacheSize_01 xor ebx, ebx .GetCacheSize_01: test ecx, 080000000h jz .GetCacheSize_02 xor ecx, ecx .GetCacheSize_02: test edx, 080000000h jz .GetCacheSize_03 xor edx, edx .GetCacheSize_03: test eax, eax jz .GetCacheSize_04 mov [ebp], eax add ebp, 4 add esi, 3 .GetCacheSize_04: test ebx, ebx jz .GetCacheSize_05 mov [ebp], ebx add ebp, 4 add esi, 4 .GetCacheSize_05: test ecx, ecx jz .GetCacheSize_06 mov [ebp], ecx add ebp, 4 add esi, 4 .GetCacheSize_06: test edx, edx jz .GetCacheSize_07 mov [ebp], edx add esi, 4 .GetCacheSize_07: test esi, esi jz .GetCacheSize_11 mov eax, -1 .GetCacheSize_08: xor edx, edx add edx, [edi] jz .ExitGetCacheSize00 add edi, 8 mov ecx, esi .GetCacheSize_09: cmp dl, BYTE [esp + ecx] je .GetCacheSize_10 dec ecx jnz .GetCacheSize_09 jmp .GetCacheSize_08 .GetCacheSize_10: mov eax, [edi - 4] .ExitGetCacheSize00: add esp, 16 pop ebp pop ebx pop esi pop edi ret .GetCacheSize_11: mov eax, -1 jmp .ExitGetCacheSize00 ENDFUNC cpGetCacheSize ; ***************************************** %endif ; IPP_DATA cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/emulator.inc000066400000000000000000000333261470420105600251610ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2009 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: x86 Cryptography Primitive. ; ; ; %macro my_pclmulqdq 3.nolist %define %%xxDst %1 %define %%xxSrc %2 %define %%xxOp %3 %if (my_emulator == 0) pclmulqdq %%xxDst, %%xxSrc, %%xxOp %else ;;;; esp => &p1 ;; +4 => &p2 ;; +8 => p3 ;; +12 => p2 (16 bytes) ;; +28 => p1 (16 bytes) ;; +44 => eax %assign %%stackSize (4+4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+44], eax ;; save eax mov dword [esp+48], ebx ;; save ebx mov dword [esp+52], ecx ;; save ecx mov dword [esp+56], edx ;; save edx mov dword [esp+60], esi ;; save esi mov dword [esp+64], edi ;; save edi movdqu oword [esp+28], %%xxDst ;; store mmDst movdqu oword [esp+12], %%xxSrc ;; store mmSrc mov dword [esp+8], %%xxOp ;; put p3 (mmOp) into the stack lea eax, [esp+28] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+12] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_pclmulqdq movdqu %%xxDst, oword [esp+28] ;; load result mov eax, dword [esp+44] ;; restore eax mov ebx, dword [esp+48] ;; restore ebx mov ecx, dword [esp+52] ;; restore ecx mov edx, dword [esp+56] ;; restore edx mov esi, dword [esp+60] ;; restore esi mov edi, dword [esp+64] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_palignr 3.nolist %define %%xxDst %1 %define %%xxSrc %2 %define %%xxOp %3 %if (my_emulator == 0) palignr %%xxDst, %%xxSrc, %%xxOp %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p3 ;; +12 => p2 (16 bytes) ;; +28 => p1 (16 bytes) ;; +44 => eax %assign %%stackSize (4+4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+44], eax ;; save eax mov dword [esp+48], ebx ;; save ebx mov dword [esp+52], ecx ;; save ecx mov dword [esp+56], edx ;; save edx mov dword [esp+60], esi ;; save esi mov dword [esp+64], edi ;; save edi movdqu oword [esp+28], %%xxDst ;; store mmDst movdqu oword [esp+12], %%xxSrc ;; store mmSrc mov dword [esp+8], %%xxOp ;; put p3 (mmOp) into the stack lea eax, [esp+28] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+12] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_palignr movdqu %%xxDst, oword [esp+28] ;; load result mov eax, dword [esp+44] ;; restore eax mov ebx, dword [esp+48] ;; restore ebx mov ecx, dword [esp+52] ;; restore ecx mov edx, dword [esp+56] ;; restore edx mov esi, dword [esp+60] ;; restore esi mov edi, dword [esp+64] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_pshufd 3.nolist %define %%xxDst %1 %define %%xxSrc %2 %define %%xxOp %3 %if (my_emulator == 0) pshufd %%xxDst, %%xxSrc, %%xxOp %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p3 ;; +12 => p2 (16 bytes) ;; +28 => p1 (16 bytes) ;; +44 => eax %assign %%stackSize (4+4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+44], eax ;; save eax mov dword [esp+48], ebx ;; save ebx mov dword [esp+52], ecx ;; save ecx mov dword [esp+56], edx ;; save edx mov dword [esp+60], esi ;; save esi mov dword [esp+64], edi ;; save edi movdqu oword [esp+28], %%xxDst ;; store mmDst movdqu oword [esp+12], %%xxSrc ;; store mmSrc mov dword [esp+8], %%xxOp ;; put p3 (mmOp) into the stack lea eax, [esp+28] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+12] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_pshufd movdqu %%xxDst, oword [esp+28] ;; load result mov eax, dword [esp+44] ;; restore eax mov ebx, dword [esp+48] ;; restore ebx mov ecx, dword [esp+52] ;; restore ecx mov edx, dword [esp+56] ;; restore edx mov esi, dword [esp+60] ;; restore esi mov edi, dword [esp+64] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_pshufb 2.nolist %define %%xxDst %1 %define %%xxSrc %2 %if (my_emulator == 0) pshufb %%xxDst, %%xxSrc %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p2 (16 bytes) ;; +24 => p1 (16 bytes) ;; +40 => eax %assign %%stackSize (4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+40], eax ;; save eax mov dword [esp+44], ebx ;; save ebx mov dword [esp+48], ecx ;; save ecx mov dword [esp+52], edx ;; save edx mov dword [esp+56], esi ;; save esi mov dword [esp+60], edi ;; save edi movdqu oword [esp+24], %%xxDst ;; store mmDst movdqu oword [esp+8], %%xxSrc ;; store mmSrc lea eax, [esp+24] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+8] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_pshufb movdqu %%xxDst, oword [esp+24] ;; load result mov eax, dword [esp+40] ;; restore eax mov ebx, dword [esp+44] ;; restore ebx mov ecx, dword [esp+48] ;; restore ecx mov edx, dword [esp+52] ;; restore edx mov esi, dword [esp+56] ;; restore esi mov edi, dword [esp+60] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_pshufbM 2.nolist %define %%xxDst %1 %define %%xxSrc %2 %if (my_emulator == 0) pshufb %%xxDst, %%xxSrc %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p2 (16 bytes) ;; +24 => p1 (16 bytes) ;; +40 => eax %assign %%stackSize (4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+40], eax ;; save eax mov dword [esp+44], ebx ;; save ebx mov dword [esp+48], ecx ;; save ecx mov dword [esp+52], edx ;; save edx mov dword [esp+56], esi ;; save esi mov dword [esp+60], edi ;; save edi movdqu oword [esp+24], %%xxDst ;; store mmDst movdqu %%xxDst, %%xxSrc movdqu oword [esp+8], %%xxDst ;; store mmSrc lea eax, [esp+24] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+8] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_pshufb movdqu %%xxDst, oword [esp+24] ;; load result mov eax, dword [esp+40] ;; restore eax mov ebx, dword [esp+44] ;; restore ebx mov ecx, dword [esp+48] ;; restore ecx mov edx, dword [esp+52] ;; restore edx mov esi, dword [esp+56] ;; restore esi mov edi, dword [esp+60] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_aesenc 2.nolist %define %%xxDst %1 %define %%xxSrc %2 %if (my_emulator == 0) aesenc %%xxDst, %%xxSrc %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p1 (16 bytes) ;; +24 => p2 (16 bytes) ;; +40 => eax %assign %%stackSize (4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+40], eax ;; save eax mov dword [esp+44], ebx ;; save ebx mov dword [esp+48], ecx ;; save ecx mov dword [esp+52], edx ;; save edx mov dword [esp+56], esi ;; save esi mov dword [esp+60], edi ;; save edi movdqu oword [esp+8], %%xxDst ;; store mmDst movdqu oword [esp+24], %%xxSrc ;; store mmSrc lea eax, [esp+8] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+24] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_aesenc movdqu %%xxDst, oword [esp+8] ;; load result mov eax, dword [esp+40] ;; restore eax mov ebx, dword [esp+44] ;; restore ebx mov ecx, dword [esp+48] ;; restore ecx mov edx, dword [esp+52] ;; restore edx mov esi, dword [esp+56] ;; restore esi mov edi, dword [esp+60] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_aesenclast 2.nolist %define %%xxDst %1 %define %%xxSrc %2 %if (my_emulator == 0) aesenclast %%xxDst, %%xxSrc %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p1 (16 bytes) ;; +24 => p2 (16 bytes) ;; +40 => eax %assign %%stackSize (4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+40], eax ;; save eax mov dword [esp+44], ebx ;; save ebx mov dword [esp+48], ecx ;; save ecx mov dword [esp+52], edx ;; save edx mov dword [esp+56], esi ;; save esi mov dword [esp+60], edi ;; save edi movdqu oword [esp+8], %%xxDst ;; store mmDst movdqu oword [esp+24], %%xxSrc ;; store mmSrc lea eax, [esp+8] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+24] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_aesenclast movdqu %%xxDst, oword [esp+8] ;; load result mov eax, dword [esp+40] ;; restore eax mov ebx, dword [esp+44] ;; restore ebx mov ecx, dword [esp+48] ;; restore ecx mov edx, dword [esp+52] ;; restore edx mov esi, dword [esp+56] ;; restore esi mov edi, dword [esp+60] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_aesdec 2.nolist %define %%xxDst %1 %define %%xxSrc %2 %if (my_emulator == 0) aesdec %%xxDst, %%xxSrc %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p1 (16 bytes) ;; +24 => p2 (16 bytes) ;; +40 => eax %assign %%stackSize (4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+40], eax ;; save eax mov dword [esp+44], ebx ;; save ebx mov dword [esp+48], ecx ;; save ecx mov dword [esp+52], edx ;; save edx mov dword [esp+56], esi ;; save esi mov dword [esp+60], edi ;; save edi movdqu oword [esp+8], %%xxDst ;; store mmDst movdqu oword [esp+24], %%xxSrc ;; store mmSrc lea eax, [esp+8] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+24] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_aesdec movdqu %%xxDst, oword [esp+8] ;; load result mov eax, dword [esp+40] ;; restore eax mov ebx, dword [esp+44] ;; restore ebx mov ecx, dword [esp+48] ;; restore ecx mov edx, dword [esp+52] ;; restore edx mov esi, dword [esp+56] ;; restore esi mov edi, dword [esp+60] ;; restore edi add esp, %%stackSize %endif %endmacro %macro my_aesdeclast 2.nolist %define %%xxDst %1 %define %%xxSrc %2 %if (my_emulator == 0) aesdeclast %%xxDst, %%xxSrc %else ;; ;; esp => &p1 ;; +4 => &p2 ;; +8 => p1 (16 bytes) ;; +24 => p2 (16 bytes) ;; +40 => eax %assign %%stackSize (4+4)+(16+16)+(4+4+4+4+4+4) sub esp,%%stackSize mov dword [esp+40], eax ;; save eax mov dword [esp+44], ebx ;; save ebx mov dword [esp+48], ecx ;; save ecx mov dword [esp+52], edx ;; save edx mov dword [esp+56], esi ;; save esi mov dword [esp+60], edi ;; save edi movdqu oword [esp+8], %%xxDst ;; store mmDst movdqu oword [esp+24], %%xxSrc ;; store mmSrc lea eax, [esp+8] ;; &p1 (&mmSrc) mov dword [esp], eax ;; put &p1 into the stack lea eax, [esp+24] ;; &p2 mov dword [esp+4], eax ;; put &p2 into the stack call emu_aesdeclast movdqu %%xxDst, oword [esp+8] ;; load result mov eax, dword [esp+40] ;; restore eax mov ebx, dword [esp+44] ;; restore ebx mov ecx, dword [esp+48] ;; restore ecx mov edx, dword [esp+52] ;; restore edx mov esi, dword [esp+56] ;; restore esi mov edi, dword [esp+60] ;; restore edi add esp, %%stackSize %endif %endmacro %if (my_emulator != 0) extern emu_pclmulqdq extern emu_palignr extern emu_pshufd extern emu_pshufb extern emu_aesenc extern emu_aesenclast extern emu_aesdec extern emu_aesdeclast %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpaesgcmg9as.asm000066400000000000000000000777041470420105600260760ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; AES-GCM function ; ; Content: ; AesGcmPrecompute_avx() ; AesGcmMulGcm_avx() ; AesGcmAuth_avx() ; AesGcmEnc_avx() ; AesGcmDec_avx() ; ; ; %include "asmdefs.inc" %include "ia_emm.inc" %assign my_emulator 0; set 1 for emulation %include "emulator.inc" ;; ;; a = a*b mod g(x), g(x) = x^128 + x^7 + x^2 +x +1 ;; %macro sse_clmul_gcm 5.nolist %xdefine %%GH %1 %xdefine %%HK %2 %xdefine %%tmpX0 %3 %xdefine %%tmpX1 %4 %xdefine %%tmpX2 %5 ;; GH, HK hold the values for the two operands which are carry-less multiplied ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Karatsuba Method ;; ;; GH = [GH1:GH0] ;; HK = [HK1:HK0] ;; pshufd %%tmpX2, %%GH, 01001110b ;; xmm2 = {GH0:GH1} pshufd %%tmpX0, %%HK, 01001110b ;; xmm0 = {HK0:HK1} pxor %%tmpX2, %%GH ;; xmm2 = {GH0+GH1:GH1+GH0} pxor %%tmpX0, %%HK ;; xmm0 = {HK0+HK1:HK1+HK0} my_pclmulqdq %%tmpX2, %%tmpX0,00h ;; tmpX2 = (a1+a0)*(b1+b0) xmm2 = (GH1+GH0)*(HK1+HK0) movdqa %%tmpX1, %%GH my_pclmulqdq %%GH, %%HK, 00h ;; GH = a0*b0 GH = GH0*HK0 pxor %%tmpX0, %%tmpX0 my_pclmulqdq %%tmpX1, %%HK, 11h ;; tmpX1 = a1*b1 xmm1 = GH1*HK1 pxor %%tmpX2, %%GH ;; xmm2 = (GH1+GH0)*(HK1+HK0) + GH0*HK0 pxor %%tmpX2, %%tmpX1 ;; tmpX2 = a0*b1+a1*b0 xmm2 = (GH1+GH0)*(HK1+HK0) + GH0*HK0 + GH1*HK1 = GH0*HK1+GH1*HK0 palignr %%tmpX0, %%tmpX2, 8 ;; tmpX0 = {Zeros : HI(a0*b1+a1*b0)} pslldq %%tmpX2, 8 ;; tmpX2 = {LO(HI(a0*b1+a1*b0)) : Zeros} pxor %%tmpX1, %%tmpX0 ;; holds the result of the carry-less multiplication of GH by HK pxor %%GH, %%tmpX2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction: ; Most( (product_H * g1), 128)) product_H = GH ; g1 = 2^256/g = g = 1+x+x^2+x^7+x^128 ; movdqa %%tmpX0, %%GH psllq %%tmpX0, 1 ; GH<<1 pxor %%tmpX0, %%GH psllq %%tmpX0, 5 ; ((GH<<1) ^ GH)<<5 pxor %%tmpX0, %%GH psllq %%tmpX0, 57 ; (((GH<<1) ^ GH)<<5) ^ GH)<<57 <==> GH<<63 ^ GH<<62 ^ GH<<57 movdqa %%tmpX2, %%tmpX0 pslldq %%tmpX2, 8 ; shift-L tmpX2 2 DWs psrldq %%tmpX0, 8 ; shift-R xmm2 2 DWs pxor %%GH, %%tmpX2 ; first phase of the reduction complete pxor %%tmpX1, %%tmpX0 ; save the lost MS 1-2-7 bits from first phase ;second phase of the reduction movdqa %%tmpX2, %%GH ; move GH into xmm15 psrlq %%tmpX2, 5 ; packed right shifting >> 5 pxor %%tmpX2, %%GH ; xor shifted versions psrlq %%tmpX2, 1 ; packed right shifting >> 1 pxor %%tmpX2, %%GH ; xor shifted versions psrlq %%tmpX2, 1 ; packed right shifting >> 1 pxor %%GH, %%tmpX2 ; second phase of the reduction complete pxor %%GH, %%tmpX1 ; the result is in GH %endmacro %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR CONST_TABLE: _poly DQ 00000000000000001h,0C200000000000000h ;; 0xC2000000000000000000000000000001 _twoone DQ 00000000000000001h,00000000100000000h ;; 0x00000001000000000000000000000001 _u128_str DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 _mask1 DQ 0ffffffffffffffffh,00000000000000000h ;; 0x0000000000000000ffffffffffffffff _mask2 DQ 00000000000000000h,0ffffffffffffffffh ;; 0xffffffffffffffff0000000000000000 _inc1 DQ 1,0 %xdefine POLY [esi+(_poly - CONST_TABLE)] %xdefine TWOONE [esi+(_twoone - CONST_TABLE)] %xdefine u128_str [esi+(_u128_str - CONST_TABLE)] %xdefine MASK1 [esi+(_mask1 - CONST_TABLE)] %xdefine MASK2 [esi+(_mask2 - CONST_TABLE)] %xdefine inc1 [esi+(_inc1 - CONST_TABLE)] %assign sizeof_oword_ (16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void GCMpipePrecomute(const Ipp8u* pRefHkey, Ipp8u* pMultipliers); ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmPrecompute_avx,PUBLIC USES_GPR esi %xdefine pHkey [esp + ARG_1 + 0*sizeof(dword)] ; pointer to the reflected hkey %xdefine pMultipliers [esp + ARG_1 + 1*sizeof(dword)] ; output to the precomputed multipliers LD_ADDR esi, CONST_TABLE mov eax, pHkey movdqu xmm0, oword [eax] ; xmm0 holds HashKey pshufb xmm0, u128_str ; precompute HashKey<<1 mod poly from the HashKey movdqa xmm4, xmm0 psllq xmm0, 1 psrlq xmm4, 63 movdqa xmm3, xmm4 pslldq xmm4, 8 psrldq xmm3, 8 por xmm0, xmm4 ;reduction pshufd xmm4, xmm3, 00100100b pcmpeqd xmm4, oword TWOONE ; TWOONE = 0x00000001000000000000000000000001 pand xmm4, oword POLY pxor xmm0, xmm4 ; xmm0 holds the HashKey<<1 mod poly movdqa xmm1, xmm0 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^2)<<1 mod poly movdqa xmm2, xmm1 sse_clmul_gcm xmm2, xmm1, xmm3, xmm4, xmm5 ; xmm2 holds (HashKey^4)<<1 mod poly mov eax, pMultipliers movdqu oword [eax+sizeof_oword_*0], xmm0 movdqu oword [eax+sizeof_oword_*1], xmm1 movdqu oword [eax+sizeof_oword_*2], xmm2 REST_GPR ret ENDFUNC AesGcmPrecompute_avx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmPrecompute_avx2_vaes(const Ipp8u* pRefHkey, Ipp8u* pMultipliers); ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmPrecompute_avx2_vaes,PUBLIC USES_GPR esi %xdefine pHkey [esp + ARG_1 + 0*sizeof(dword)] ; pointer to the reflected hkey %xdefine pMultipliers [esp + ARG_1 + 1*sizeof(dword)] ; output to the precomputed multipliers LD_ADDR esi, CONST_TABLE mov eax, pHkey movdqu xmm0, oword [eax] ; xmm0 holds HashKey pshufb xmm0, u128_str ; precompute HashKey<<1 mod poly from the HashKey movdqa xmm4, xmm0 psllq xmm0, 1 psrlq xmm4, 63 movdqa xmm3, xmm4 pslldq xmm4, 8 psrldq xmm3, 8 por xmm0, xmm4 ;reduction pshufd xmm4, xmm3, 00100100b pcmpeqd xmm4, oword TWOONE ; TWOONE = 0x00000001000000000000000000000001 pand xmm4, oword POLY pxor xmm0, xmm4 ; xmm0 holds the HashKey<<1 mod poly mov eax, pMultipliers movdqu oword [eax+sizeof_oword_*0], xmm0 movdqa xmm1, xmm0 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^2)<<1 mod poly movdqu oword [eax+sizeof_oword_*1], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^3)<<1 mod poly movdqu oword [eax+sizeof_oword_*2], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^4)<<1 mod poly movdqu oword [eax+sizeof_oword_*3], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^5)<<1 mod poly movdqu oword [eax+sizeof_oword_*4], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^6)<<1 mod poly movdqu oword [eax+sizeof_oword_*5], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^7)<<1 mod poly movdqu oword [eax+sizeof_oword_*6], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^8)<<1 mod poly movdqu oword [eax+sizeof_oword_*7], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^9)<<1 mod poly movdqu oword [eax+sizeof_oword_*8], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^10)<<1 mod poly movdqu oword [eax+sizeof_oword_*9], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^11)<<1 mod poly movdqu oword [eax+sizeof_oword_*10], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^12)<<1 mod poly movdqu oword [eax+sizeof_oword_*11], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^13)<<1 mod poly movdqu oword [eax+sizeof_oword_*12], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^14)<<1 mod poly movdqu oword [eax+sizeof_oword_*13], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^15)<<1 mod poly movdqu oword [eax+sizeof_oword_*14], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^16)<<1 mod poly movdqu oword [eax+sizeof_oword_*15], xmm1 REST_GPR ret ENDFUNC AesGcmPrecompute_avx2_vaes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmMulGcm_avx(Ipp8u* pHash, const Ipp8u* pHKey) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmMulGcm_avx,PUBLIC USES_GPR esi,edi %xdefine pHash [esp + ARG_1 + 0*sizeof(dword)] %xdefine pHKey [esp + ARG_1 + 1*sizeof(dword)] LD_ADDR esi, CONST_TABLE mov edi, pHash ; (edi) pointer to the Hash value mov eax, pHKey ; (eax) pointer to the (hkey<<1) value movdqa xmm0, oword [edi] pshufb xmm0, u128_str movdqa xmm1, oword [eax] sse_clmul_gcm xmm0, xmm1, xmm2, xmm3, xmm4 ; xmm0 holds Hash*HKey mod poly pshufb xmm0, u128_str movdqa oword [edi], xmm0 REST_GPR ret ENDFUNC AesGcmMulGcm_avx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmAuth_avx(Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pHKey ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmAuth_avx,PUBLIC USES_GPR esi,edi %xdefine pHash [esp + ARG_1 + 0*sizeof(dword)] %xdefine pSrc [esp + ARG_1 + 1*sizeof(dword)] %xdefine len [esp + ARG_1 + 2*sizeof(dword)] %xdefine pHKey [esp + ARG_1 + 3*sizeof(dword)] %assign BYTES_PER_BLK (16) LD_ADDR esi, CONST_TABLE mov edi, pHash movdqa xmm0, oword [edi] pshufb xmm0, u128_str mov eax, pHKey movdqa xmm1, oword [eax] mov ecx, pSrc mov edx, len align IPP_ALIGN_FACTOR .auth_loop: movdqu xmm2, oword [ecx] ; src[] pshufb xmm2, u128_str add ecx, BYTES_PER_BLK pxor xmm0, xmm2 ; hash ^= src[] sse_clmul_gcm xmm0, xmm1, xmm2, xmm3, xmm4 ; xmm0 holds Hash*HKey mod poly sub edx, BYTES_PER_BLK jnz .auth_loop pshufb xmm0, u128_str movdqa oword [edi], xmm0 REST_GPR ret ENDFUNC AesGcmAuth_avx ;*************************************************************** ;* Purpose: pipelined AES-GCM encryption ;* ;* void AesGcmEnc_avx(Ipp8u* pDst, ;* const Ipp8u* pSrc, ;* int length, ;* RijnCipher cipher, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp8u* pGhash, ;* Ipp8u* pCtrValue, ;* Ipp8u* pEncCtrValue, ;* const Ipp8u* pPrecomData) ;*************************************************************** ;; ;; Lib = P8, G9 ;; ;; Caller = ippsRijndael128GCMEncrypt ;; align IPP_ALIGN_FACTOR IPPASM AesGcmEnc_avx,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pDst [ebp + ARG_1 + 0*sizeof(dword)] ; output block address %xdefine pSrc [ebp + ARG_1 + 1*sizeof(dword)] ; input block address %xdefine len [ebp + ARG_1 + 2*sizeof(dword)] ; length(byte) %xdefine cipher [ebp + ARG_1 + 3*sizeof(dword)] %xdefine nr [ebp + ARG_1 + 4*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 5*sizeof(dword)] ; key material address %xdefine pGhash [ebp + ARG_1 + 6*sizeof(dword)] ; hash %xdefine pCounter [ebp + ARG_1 + 7*sizeof(dword)] ; counter %xdefine pEcounter [ebp + ARG_1 + 8*sizeof(dword)] ; enc. counter %xdefine pPrecomData [ebp + ARG_1 + 9*sizeof(dword)] ; const multipliers %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) ;; ;; stack structure: %assign CNT (0) %assign ECNT (CNT+sizeof_oword_) %assign GHASH (ECNT+sizeof_oword_) %assign GHASH0 (GHASH) %assign GHASH1 (GHASH0+sizeof_oword_) %assign GHASH2 (GHASH1+sizeof_oword_) %assign GHASH3 (GHASH2+sizeof_oword_) %assign SHUF_CONST (GHASH3+sizeof_oword_) %assign INC_1 (SHUF_CONST+sizeof_oword_) %assign BLKS4 (INC_1+sizeof_oword_) %assign BLKS (BLKS4+sizeof(dword)) %assign STACK_SIZE (BLKS+sizeof(dword)+sizeof_oword_) sub esp, STACK_SIZE ; allocate stack lea ebx, [esp+sizeof_oword_] ; align stack and ebx, -sizeof_oword_ mov eax, cipher ; due to bug in ml12 - dummy instruction LD_ADDR esi, CONST_TABLE movdqa xmm4, oword u128_str movdqa xmm5, oword inc1 mov eax, pCounter ; address of the counter mov ecx, pEcounter ; address of the encrypted counter mov edx, pGhash ; address of hash value movdqu xmm0, oword [eax] ; counter value movdqu xmm1, oword [ecx] ; encrypted counter value movdqu xmm2, oword [edx] ; hash value my_pshufb xmm0, xmm4 ; convert counter and movdqa oword [ebx+CNT], xmm0 ; and store into the stack movdqa oword [ebx+ECNT], xmm1 ; store encrypted counter into the stack my_pshufb xmm2, xmm4 ; convert hash value pxor xmm1, xmm1 movdqa oword [ebx+GHASH0], xmm2 ; store hash into the stack movdqa oword [ebx+GHASH1], xmm1 ; movdqa oword [ebx+GHASH2], xmm1 ; movdqa oword [ebx+GHASH3], xmm1 ; movdqa oword [ebx+SHUF_CONST], xmm4 ; store constants into the stack movdqa oword [ebx+INC_1], xmm5 mov ecx, pKey ; key marerial mov esi, pSrc ; src/dst pointers mov edi, pDst mov eax, len mov edx, BYTES_PER_LOOP-1 and edx, eax and eax,-BYTES_PER_LOOP mov dword [ebx+BLKS4], eax ; 4-blks counter mov dword [ebx+BLKS], edx ; rest counter jz .single_block_proc ;; ;; pipelined processing ;; align IPP_ALIGN_FACTOR .blks4_loop: ;; ;; ctr encryption ;; movdqa xmm5, oword [ebx+INC_1] movdqa xmm1, xmm0 ; counter+1 paddd xmm1, xmm5 movdqa xmm2, xmm1 ; counter+2 paddd xmm2, xmm5 movdqa xmm3, xmm2 ; counter+3 paddd xmm3, xmm5 movdqa xmm4, xmm3 ; counter+4 paddd xmm4, xmm5 movdqa oword [ebx+CNT], xmm4 movdqa xmm5,oword [ebx+SHUF_CONST] movdqa xmm0, oword [ecx] ; pre-load whitening keys lea eax, [ecx+16] ; pointer to the round's key material my_pshufb xmm1, xmm5 ; counter, counter+1, counter+2, counter+3 my_pshufb xmm2, xmm5 ; ready to be encrypted my_pshufb xmm3, xmm5 my_pshufb xmm4, xmm5 pxor xmm1, xmm0 ; whitening pxor xmm2, xmm0 pxor xmm3, xmm0 pxor xmm4, xmm0 movdqa xmm0, oword [eax] ; pre load round keys add eax, 16 mov edx, nr ; counter depending on key length sub edx, 1 align IPP_ALIGN_FACTOR .cipher4_loop: my_aesenc xmm1, xmm0 ; regular round my_aesenc xmm2, xmm0 my_aesenc xmm3, xmm0 my_aesenc xmm4, xmm0 movdqa xmm0, oword [eax] add eax, 16 dec edx jnz .cipher4_loop my_aesenclast xmm1, xmm0 my_aesenclast xmm2, xmm0 my_aesenclast xmm3, xmm0 my_aesenclast xmm4, xmm0 movdqa xmm0, oword [ebx+ECNT] ; load pre-calculated encrypted counter movdqa oword [ebx+ECNT], xmm4 ; save encrypted counter+4 movdqu xmm4, oword [esi+0*BYTES_PER_BLK] ; ctr encryption of 4 input blocks movdqu xmm5, oword [esi+1*BYTES_PER_BLK] movdqu xmm6, oword [esi+2*BYTES_PER_BLK] movdqu xmm7, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_LOOP pxor xmm0, xmm4 ; ctr encryption movdqu oword [edi+0*BYTES_PER_BLK], xmm0 ; store result my_pshufbM xmm0, [ebx+SHUF_CONST] ; convert for multiplication and pxor xmm0, oword [ebx+GHASH0] pxor xmm1, xmm5 movdqu oword [edi+1*BYTES_PER_BLK], xmm1 my_pshufbM xmm1, [ebx+SHUF_CONST] pxor xmm1, oword [ebx+GHASH1] pxor xmm2, xmm6 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 my_pshufbM xmm2, [ebx+SHUF_CONST] pxor xmm2, oword [ebx+GHASH2] pxor xmm3, xmm7 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 my_pshufbM xmm3, [ebx+SHUF_CONST] pxor xmm3, oword [ebx+GHASH3] add edi, BYTES_PER_LOOP mov eax, pPrecomData ; pointer to the {hk<<1,hk^2<<1,kh^4<<1} multipliers movdqa xmm7,oword [eax+sizeof_oword_*2] cmp dword [ebx+BLKS4], BYTES_PER_LOOP je .combine_hash ;; ;; update hash value ;; sse_clmul_gcm xmm0, xmm7, xmm4, xmm5, xmm6 ; gHash0 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm1, xmm7, xmm4, xmm5, xmm6 ; gHash1 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm2, xmm7, xmm4, xmm5, xmm6 ; gHash2 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm3, xmm7, xmm4, xmm5, xmm6 ; gHash3 = gHash0 * (HashKey^4)<<1 mod poly movdqa oword [ebx+GHASH0], xmm0 movdqa oword [ebx+GHASH1], xmm1 movdqa oword [ebx+GHASH2], xmm2 movdqa oword [ebx+GHASH3], xmm3 movdqa xmm0, oword [ebx+CNT] ; next counter value sub dword [ebx+BLKS4], BYTES_PER_LOOP jge .blks4_loop .combine_hash: sse_clmul_gcm xmm0, xmm7, xmm4, xmm5, xmm6 ; gHash0 = gHash0 * (HashKey^4)<<1 mod poly movdqa xmm7,oword [eax+sizeof_oword_*1] sse_clmul_gcm xmm1, xmm7, xmm4, xmm5, xmm6 ; gHash1 = gHash1 * (HashKey^2)<<1 mod poly movdqa xmm7,oword [eax+sizeof_oword_*0] sse_clmul_gcm xmm2, xmm7, xmm4, xmm5, xmm6 ; gHash2 = gHash2 * (HashKey^1)<<1 mod poly pxor xmm3, xmm1 pxor xmm3, xmm2 sse_clmul_gcm xmm3, xmm7, xmm4, xmm5, xmm6 ; gHash3 = gHash3 * (HashKey)<<1 mod poly pxor xmm3, xmm0 movdqa oword [ebx+GHASH0], xmm3 ; store ghash ;; ;; rest of input processing (1-3 blocks) ;; .single_block_proc: cmp dword [ebx+BLKS],0 jz .quit align IPP_ALIGN_FACTOR .blk_loop: movdqa xmm0, oword [ebx+CNT] ; advance counter value movdqa xmm1, xmm0 paddd xmm1, oword [ebx+INC_1] movdqa oword [ebx+CNT], xmm1 movdqa xmm0, oword [ecx] ; pre-load whitening keys lea eax, [ecx+16] my_pshufb xmm1, [ebx+SHUF_CONST] ; counter is ready to be encrypted pxor xmm1, xmm0 ; whitening movdqa xmm0, oword [eax] add eax, 16 mov edx, nr ; counter depending on key length sub edx, 1 align IPP_ALIGN_FACTOR .cipher_loop: my_aesenc xmm1, xmm0 ; regular round movdqa xmm0, oword [eax] add eax, 16 dec edx jnz .cipher_loop my_aesenclast xmm1, xmm0 movdqa xmm0, oword [ebx+ECNT] ; load pre-calculated encrypted counter movdqa oword [ebx+ECNT], xmm1 ; save encrypted counter movdqu xmm1, oword [esi] ; input block add esi, BYTES_PER_BLK pxor xmm0, xmm1 ; ctr encryption movdqu oword [edi], xmm0 add edi, BYTES_PER_BLK mov eax, pPrecomData pshufb xmm0, [ebx+SHUF_CONST] pxor xmm0, oword [ebx+GHASH0] movdqa xmm1, oword [eax] sse_clmul_gcm xmm0, xmm1, xmm2, xmm3, xmm4 ; update hash value movdqa oword [ebx+GHASH0], xmm0 sub dword [ebx+BLKS], BYTES_PER_BLK jg .blk_loop ;; ;; exit ;; .quit: movdqa xmm4, oword [ebx+SHUF_CONST] movdqa xmm0, oword [ebx+CNT] ; counter movdqa xmm1, oword [ebx+ECNT] ; encrypted counter movdqa xmm2, oword [ebx+GHASH0] ; hash mov eax, pCounter ; address of the counter mov ecx, pEcounter ; address of the encrypted counter mov edx, pGhash ; address of hash value my_pshufb xmm0, xmm4 ; convert counter back and movdqu oword [eax], xmm0 ; and store movdqu oword [ecx], xmm1 ; store encrypted counter into the context my_pshufb xmm2, xmm4 ; convert hash value back movdqu oword [edx], xmm2 ; store hash into the context add esp, STACK_SIZE ; free stack REST_GPR ret ENDFUNC AesGcmEnc_avx ;*************************************************************** ;* Purpose: pipelined AES-GCM decryption ;* ;* void AesGcmEnc_avx(Ipp8u* pDst, ;* const Ipp8u* pSrc, ;* int length, ;* RijnCipher cipher, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp8u* pGhash, ;* Ipp8u* pCtrValue, ;* Ipp8u* pEncCtrValue, ;* const Ipp8u* pPrecomData) ;*************************************************************** ;; ;; Lib = P8, G9 ;; ;; Caller = ippsRijndael128GCMDecrypt ;; align IPP_ALIGN_FACTOR IPPASM AesGcmDec_avx,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pDst [ebp + ARG_1 + 0*sizeof(dword)] ; output block address %xdefine pSrc [ebp + ARG_1 + 1*sizeof(dword)] ; input block address %xdefine len [ebp + ARG_1 + 2*sizeof(dword)] ; length(byte) %xdefine cipher [ebp + ARG_1 + 3*sizeof(dword)] %xdefine nr [ebp + ARG_1 + 4*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 5*sizeof(dword)] ; key material address %xdefine pGhash [ebp + ARG_1 + 6*sizeof(dword)] ; hash %xdefine pCounter [ebp + ARG_1 + 7*sizeof(dword)] ; counter %xdefine pEcounter [ebp + ARG_1 + 8*sizeof(dword)] ; enc. counter %xdefine pPrecomData [ebp + ARG_1 + 9*sizeof(dword)] ; const multipliers %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) ;; ;; stack structure: %assign CNT (0) %assign ECNT (CNT+sizeof_oword_) %assign GHASH (ECNT+sizeof_oword_) %assign GHASH0 (GHASH) %assign GHASH1 (GHASH0+sizeof_oword_) %assign GHASH2 (GHASH1+sizeof_oword_) %assign GHASH3 (GHASH2+sizeof_oword_) %assign SHUF_CONST (GHASH3+sizeof_oword_) %assign INC_1 (SHUF_CONST+sizeof_oword_) %assign BLKS4 (INC_1+sizeof_oword_) %assign BLKS (BLKS4+sizeof(dword)) %assign STACK_SIZE (BLKS+sizeof(dword)+sizeof_oword_) sub esp, STACK_SIZE ; allocate stack lea ebx, [esp+sizeof_oword_] ; align stack and ebx, -sizeof_oword_ mov eax, cipher ; due to bug in ml12 - dummy instruction LD_ADDR esi, CONST_TABLE movdqa xmm4, oword u128_str movdqa xmm5, oword inc1 mov eax, pCounter ; address of the counter mov ecx, pEcounter ; address of the encrypted counter mov edx, pGhash ; address of hash value movdqu xmm0, oword [eax] ; counter value movdqu xmm1, oword [ecx] ; encrypted counter value movdqu xmm2, oword [edx] ; hash value my_pshufb xmm0, xmm4 ; convert counter and movdqa oword [ebx+CNT], xmm0 ; and store into the stack movdqa oword [ebx+ECNT], xmm1 ; store encrypted counter into the stack my_pshufb xmm2, xmm4 ; convert hash value pxor xmm1, xmm1 movdqa oword [ebx+GHASH0], xmm2 ; store hash into the stack movdqa oword [ebx+GHASH1], xmm1 ; movdqa oword [ebx+GHASH2], xmm1 ; movdqa oword [ebx+GHASH3], xmm1 ; movdqa oword [ebx+SHUF_CONST], xmm4 ; store constants into the stack movdqa oword [ebx+INC_1], xmm5 mov ecx, pKey ; key marerial mov esi, pSrc ; src/dst pointers mov edi, pDst mov eax, len mov edx, BYTES_PER_LOOP-1 and edx, eax and eax,-BYTES_PER_LOOP mov dword [ebx+BLKS4], eax ; 4-blks counter mov dword [ebx+BLKS], edx ; rest counter jz .single_block_proc ;; ;; pipelined processing ;; align IPP_ALIGN_FACTOR .blks4_loop: ;; ;; ctr encryption ;; movdqa xmm5, oword [ebx+INC_1] movdqa xmm1, xmm0 ; counter+1 paddd xmm1, xmm5 movdqa xmm2, xmm1 ; counter+2 paddd xmm2, xmm5 movdqa xmm3, xmm2 ; counter+3 paddd xmm3, xmm5 movdqa xmm4, xmm3 ; counter+4 paddd xmm4, xmm5 movdqa oword [ebx+CNT], xmm4 movdqa xmm5,oword [ebx+SHUF_CONST] movdqa xmm0, oword [ecx] ; pre-load whitening keys lea eax, [ecx+16] ; pointer to the round's key material my_pshufb xmm1, xmm5 ; counter, counter+1, counter+2, counter+3 my_pshufb xmm2, xmm5 ; ready to be encrypted my_pshufb xmm3, xmm5 my_pshufb xmm4, xmm5 pxor xmm1, xmm0 ; whitening pxor xmm2, xmm0 pxor xmm3, xmm0 pxor xmm4, xmm0 movdqa xmm0, oword [eax] ; pre load round keys add eax, 16 mov edx, nr ; counter depending on key length sub edx, 1 align IPP_ALIGN_FACTOR .cipher4_loop: my_aesenc xmm1, xmm0 ; regular round my_aesenc xmm2, xmm0 my_aesenc xmm3, xmm0 my_aesenc xmm4, xmm0 movdqa xmm0, oword [eax] add eax, 16 dec edx jnz .cipher4_loop my_aesenclast xmm1, xmm0 my_aesenclast xmm2, xmm0 my_aesenclast xmm3, xmm0 my_aesenclast xmm4, xmm0 movdqa xmm0, oword [ebx+ECNT] ; load pre-calculated encrypted counter movdqa oword [ebx+ECNT], xmm4 ; save encrypted counter+4 movdqu xmm4, oword [esi+0*BYTES_PER_BLK] ; ctr encryption of 4 input blocks movdqu xmm5, oword [esi+1*BYTES_PER_BLK] movdqu xmm6, oword [esi+2*BYTES_PER_BLK] movdqu xmm7, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_LOOP pxor xmm0, xmm4 ; ctr encryption movdqu oword [edi+0*BYTES_PER_BLK], xmm0 ; store result my_pshufbM xmm4, [ebx+SHUF_CONST] ; convert for multiplication and pxor xmm4, oword [ebx+GHASH0] pxor xmm1, xmm5 movdqu oword [edi+1*BYTES_PER_BLK], xmm1 my_pshufbM xmm5, [ebx+SHUF_CONST] pxor xmm5, oword [ebx+GHASH1] pxor xmm2, xmm6 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 ;pshufb xmm6, [ebx+SHUF_CONST] my_pshufbM xmm6, [ebx+SHUF_CONST] pxor xmm6, oword [ebx+GHASH2] pxor xmm3, xmm7 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 my_pshufbM xmm7, [ebx+SHUF_CONST] pxor xmm7, oword [ebx+GHASH3] add edi, BYTES_PER_LOOP mov eax, pPrecomData ; pointer to the const multipliers (c^1, c^2, c^4) movdqa xmm0,oword [eax+sizeof_oword_*2] cmp dword [ebx+BLKS4], BYTES_PER_LOOP je .combine_hash ;; ;; update hash value ;; sse_clmul_gcm xmm4, xmm0, xmm1, xmm2, xmm3 ; gHash0 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm5, xmm0, xmm1, xmm2, xmm3 ; gHash1 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm6, xmm0, xmm1, xmm2, xmm3 ; gHash2 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm7, xmm0, xmm1, xmm2, xmm3 ; gHash3 = gHash0 * (HashKey^4)<<1 mod poly movdqa oword [ebx+GHASH0], xmm4 movdqa oword [ebx+GHASH1], xmm5 movdqa oword [ebx+GHASH2], xmm6 movdqa oword [ebx+GHASH3], xmm7 movdqa xmm0, oword [ebx+CNT] ; next counter value sub dword [ebx+BLKS4], BYTES_PER_LOOP jge .blks4_loop .combine_hash: sse_clmul_gcm xmm4, xmm0, xmm1, xmm2, xmm3 ; gHash0 = gHash0 * (HashKey^4)<<1 mod poly movdqa xmm0, oword [eax+sizeof_oword_*1] sse_clmul_gcm xmm5, xmm0, xmm1, xmm2, xmm3 ; gHash1 = gHash1 * (HashKey^2)<<1 mod poly movdqa xmm0, oword [eax+sizeof_oword_*0] sse_clmul_gcm xmm6, xmm0, xmm1, xmm2, xmm3 ; gHash2 = gHash2 * (HashKey^1)<<1 mod poly pxor xmm7, xmm5 pxor xmm7, xmm6 sse_clmul_gcm xmm7, xmm0, xmm1, xmm2, xmm3 ; gHash3 = gHash3 * (HashKey)<<1 mod poly pxor xmm7, xmm4 movdqa oword [ebx+GHASH0], xmm7 ; store ghash ;; ;; rest of input processing (1-3 blocks) ;; .single_block_proc: cmp dword [ebx+BLKS],0 jz .quit align IPP_ALIGN_FACTOR .blk_loop: movdqa xmm0, oword [ebx+CNT] ; advance counter value movdqa xmm1, xmm0 paddd xmm1, oword [ebx+INC_1] movdqa oword [ebx+CNT], xmm1 movdqa xmm0, oword [ecx] ; pre-load whitening keys lea eax, [ecx+16] my_pshufb xmm1, [ebx+SHUF_CONST] ; counter is ready to be encrypted pxor xmm1, xmm0 ; whitening movdqa xmm0, oword [eax] add eax, 16 mov edx, nr ; counter depending on key length sub edx, 1 align IPP_ALIGN_FACTOR .cipher_loop: my_aesenc xmm1, xmm0 ; regular round movdqa xmm0, oword [eax] add eax, 16 dec edx jnz .cipher_loop my_aesenclast xmm1, xmm0 movdqa xmm0, oword [ebx+ECNT] ; load pre-calculated encrypted counter movdqa oword [ebx+ECNT], xmm1 ; save encrypted counter movdqu xmm1, oword [esi] ; input block add esi, BYTES_PER_BLK pxor xmm0, xmm1 ; ctr encryption movdqu oword [edi], xmm0 add edi, BYTES_PER_BLK mov eax, pPrecomData pshufb xmm1, [ebx+SHUF_CONST] pxor xmm1, oword [ebx+GHASH0] movdqa xmm0, oword [eax] sse_clmul_gcm xmm1, xmm0, xmm2, xmm3, xmm4 ; update hash value movdqa oword [ebx+GHASH0], xmm1 sub dword [ebx+BLKS], BYTES_PER_BLK jg .blk_loop ;; ;; exit ;; .quit: movdqa xmm4, oword [ebx+SHUF_CONST] movdqa xmm0, oword [ebx+CNT] ; counter movdqa xmm1, oword [ebx+ECNT] ; encrypted counter movdqa xmm2, oword [ebx+GHASH0] ; hash mov eax, pCounter ; address of the counter mov ecx, pEcounter ; address of the encrypted counter mov edx, pGhash ; address of hash value my_pshufb xmm0, xmm4 ; convert counter back and movdqu oword [eax], xmm0 ; and store movdqu oword [ecx], xmm1 ; store encrypted counter into the context my_pshufb xmm2, xmm4 ; convert hash value back movdqu oword [edx], xmm2 ; store hash into the context add esp, STACK_SIZE ; free stack REST_GPR ret ENDFUNC AesGcmDec_avx %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpaesgcmtable2kv8as.asm000066400000000000000000000302501470420105600273420ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) ; ; Content: ; AesGcmMulGcm_table2K() ; AesGcmAuth_table2K() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_V8) segment .text align=IPP_ALIGN_FACTOR ; ; getAesGcmConst_table_ct provides c-e-t access to pre-computed Ipp16u AesGcmConst_table[256] ; ; input: ; edx: address of the AesGcmConst_table ; ecx: index in the table ; ; output: ; eax ; ; register ecx destroyed ; registers mmx2, mmx3, mmx6, and mmx7 destroyed ; align IPP_ALIGN_FACTOR _CONST_DATA: _INIT_IDX DW 000h,001h,002h,003h,004h,005h,006h,007h ;; initial search inx = {0:1:2:3:4:5:6:7} _INCR_IDX DW 008h,008h,008h,008h,008h,008h,008h,008h ;; index increment = {8:8:8:8:8:8:8:8} %xdefine INIT_IDX [ebx+(_INIT_IDX - _CONST_DATA)] %xdefine INCR_IDX [ebx+(_INCR_IDX - _CONST_DATA)] align IPP_ALIGN_FACTOR IPPASM getAesGcmConst_table_ct,PRIVATE push ebx LD_ADDR ebx, _CONST_DATA pxor xmm2, xmm2 ;; accumulator xmm2 = 0 mov eax, ecx ;; broadcast inx into dword shl ecx, 16 or ecx, eax movd xmm3, ecx pshufd xmm3, xmm3, 00b ;; search index xmm3 = broadcast(idx) movdqa xmm6, xmmword INIT_IDX ;; current indexes xor eax, eax align IPP_ALIGN_FACTOR .search_loop: movdqa xmm7, xmm6 ;; copy current indexes paddw xmm6, xmmword INCR_IDX ;; advance current indexes pcmpeqw xmm7, xmm3 ;; selection mask pand xmm7, xmmword [edx+eax*sizeof(word)];; mask data add eax, 8 cmp eax, 256 por xmm2, xmm7 ;; and accumulate jl .search_loop movdqa xmm3, xmm2 ;; pack result in qword psrldq xmm2, sizeof(xmmword)/2 por xmm2, xmm3 movdqa xmm3, xmm2 ;; pack result in dword psrldq xmm2, sizeof(xmmword)/4 por xmm2, xmm3 movd eax, xmm2 pop ebx and ecx, 3 ;; select tbl[idx] value shl ecx, 4 ;; rcx *=16 = sizeof(word)*8 shr eax, cl ret ENDFUNC getAesGcmConst_table_ct ; ; void AesGcmMulGcm_table2K(Ipp8u* pHash, const Ipp8u* pPrecomputedData, , const void* pParam)) ; align IPP_ALIGN_FACTOR IPPASM AesGcmMulGcm_table2K,PUBLIC USES_GPR esi,edi,ebx %xdefine pHash [esp + ARG_1 + 0*sizeof(dword)] %xdefine pMulTbl [esp + ARG_1 + 1*sizeof(dword)] %xdefine pParam [esp + ARG_1 + 2*sizeof(dword)] mov edi, pHash movdqu xmm0, [edi] ; hash value mov esi, pMulTbl mov edx, pParam ; pointer to the fixed table movd ebx, xmm0 ; ebx = hash.0 mov eax, 0f0f0f0f0h and eax, ebx ; eax = 4 x 4_bits shl ebx, 4 and ebx, 0f0f0f0f0h ; ebx = 4 x 4_bits (another) movzx ecx, ah movdqa xmm5, oword [esi+1024+ecx] movzx ecx, al movdqa xmm4, oword [esi+1024+ecx] shr eax, 16 movzx ecx, ah movdqa xmm3, oword [esi+1024+ecx] movzx ecx, al movdqa xmm2, oword [esi+1024+ecx] psrldq xmm0, 4 ; shift xmm0 movd eax, xmm0 ; eax = hash[1] and eax, 0f0f0f0f0h ; eax = 4 x 4_bits movzx ecx, bh pxor xmm5, oword [esi+ 0*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 0*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 0*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 0*256 + ecx] movd ebx, xmm0 ; ebx = hash[1] shl ebx, 4 ; another 4 x 4_bits and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [esi+1024+ 1*256 + ecx] movzx ecx, al pxor xmm4, oword [esi+1024+ 1*256 + ecx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [esi+1024+ 1*256 + ecx] movzx ecx, al pxor xmm2, oword [esi+1024+ 1*256 + ecx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash.2 and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [esi+ 1*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 1*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 1*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 1*256 + ecx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [esi+1024+ 2*256 + ecx] movzx ecx, al pxor xmm4, oword [esi+1024+ 2*256 + ecx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [esi+1024+ 2*256 + ecx] movzx ecx, al pxor xmm2, oword [esi+1024+ 2*256 + ecx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash.3 and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [esi+ 2*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 2*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 2*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 2*256 + ecx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [esi+1024+ 3*256 + ecx] movzx ecx, al pxor xmm4, oword [esi+1024+ 3*256 + ecx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [esi+1024+ 3*256 + ecx] movzx ecx, al pxor xmm2, oword [esi+1024+ 3*256 + ecx] movzx ecx, bh pxor xmm5, oword [esi+ 3*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 3*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 3*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 3*256 + ecx] movdqa xmm0, xmm3 pslldq xmm3, 1 pxor xmm2, xmm3 movdqa xmm1, xmm2 pslldq xmm2, 1 pxor xmm5, xmm2 psrldq xmm0, 15 movd ecx, xmm0 CALL_IPPASM getAesGcmConst_table_ct ;;movzx eax, word [edx + ecx*sizeof(word)] shl eax, 8 movdqa xmm0, xmm5 pslldq xmm5, 1 pxor xmm4, xmm5 psrldq xmm1, 15 movd ecx, xmm1 mov ebx, eax ;;xor ax, word [edx + ecx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor eax, ebx ;; shl eax, 8 psrldq xmm0, 15 movd ecx, xmm0 mov ebx, eax ;;xor ax, word [edx + ecx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor eax, ebx ;; movd xmm0, eax pxor xmm0, xmm4 movdqu oword [edi], xmm0 ; store hash value REST_GPR ret ENDFUNC AesGcmMulGcm_table2K ; ; void AesGcmAuth_table2K(Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pPrecomputedData, const void* pParam) ; align IPP_ALIGN_FACTOR IPPASM AesGcmAuth_table2K,PUBLIC USES_GPR esi,edi,ebx %xdefine pHash [esp + ARG_1 + 0*sizeof(dword)] %xdefine pSrc [esp + ARG_1 + 1*sizeof(dword)] %xdefine len [esp + ARG_1 + 2*sizeof(dword)] %xdefine pMulTbl [esp + ARG_1 + 3*sizeof(dword)] %xdefine pParam [esp + ARG_1 + 4*sizeof(dword)] mov edi, pHash movdqu xmm0, [edi] ; hash value mov esi, pMulTbl mov edi, pSrc mov edx, pParam ; pointer to the fixed table align IPP_ALIGN_FACTOR .auth_loop: movdqu xmm4, [edi] ; get src[] pxor xmm0, xmm4 ; hash ^= src[] movd ebx, xmm0 ; ebx = hash.0 mov eax, 0f0f0f0f0h and eax, ebx ; eax = 4 x 4_bits shl ebx, 4 and ebx, 0f0f0f0f0h ; ebx = 4 x 4_bits (another) movzx ecx, ah movdqa xmm5, oword [esi+1024+ecx] movzx ecx, al movdqa xmm4, oword [esi+1024+ecx] shr eax, 16 movzx ecx, ah movdqa xmm3, oword [esi+1024+ecx] movzx ecx, al movdqa xmm2, oword [esi+1024+ecx] psrldq xmm0, 4 ; shift xmm0 movd eax, xmm0 ; eax = hash[1] and eax, 0f0f0f0f0h ; eax = 4 x 4_bits movzx ecx, bh pxor xmm5, oword [esi+ 0*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 0*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 0*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 0*256 + ecx] movd ebx, xmm0 ; ebx = hash[1] shl ebx, 4 ; another 4 x 4_bits and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [esi+1024+ 1*256 + ecx] movzx ecx, al pxor xmm4, oword [esi+1024+ 1*256 + ecx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [esi+1024+ 1*256 + ecx] movzx ecx, al pxor xmm2, oword [esi+1024+ 1*256 + ecx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash[2] and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [esi+ 1*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 1*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 1*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 1*256 + ecx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [esi+1024+ 2*256 + ecx] movzx ecx, al pxor xmm4, oword [esi+1024+ 2*256 + ecx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [esi+1024+ 2*256 + ecx] movzx ecx, al pxor xmm2, oword [esi+1024+ 2*256 + ecx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash[3] and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [esi+ 2*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 2*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 2*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 2*256 + ecx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [esi+1024+ 3*256 + ecx] movzx ecx, al pxor xmm4, oword [esi+1024+ 3*256 + ecx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [esi+1024+ 3*256 + ecx] movzx ecx, al pxor xmm2, oword [esi+1024+ 3*256 + ecx] movzx ecx, bh pxor xmm5, oword [esi+ 3*256 + ecx] movzx ecx, bl pxor xmm4, oword [esi+ 3*256 + ecx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [esi+ 3*256 + ecx] movzx ecx, bl pxor xmm2, oword [esi+ 3*256 + ecx] movdqa xmm0, xmm3 pslldq xmm3, 1 pxor xmm2, xmm3 movdqa xmm1, xmm2 pslldq xmm2, 1 pxor xmm5, xmm2 psrldq xmm0, 15 movd ecx, xmm0 CALL_IPPASM getAesGcmConst_table_ct ;;movzx eax, word [edx + ecx*sizeof(word)] shl eax, 8 movdqa xmm0, xmm5 pslldq xmm5, 1 pxor xmm4, xmm5 psrldq xmm1, 15 movd ecx, xmm1 mov ebx, eax ;;xor ax, word [edx + ecx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor eax, ebx ;; shl eax, 8 psrldq xmm0, 15 movd ecx, xmm0 mov ebx, eax ;;xor ax, word [edx + ecx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor eax, ebx ;; movd xmm0, eax pxor xmm0, xmm4 add edi, sizeof(oword) ; advance src address sub dword len, sizeof(oword) ; decrease counter jnz .auth_loop ; process next block mov edi, pHash movdqu oword [edi], xmm0 ; store hash value REST_GPR ret ENDFUNC AesGcmAuth_table2K %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnu.inc000066400000000000000000000160061470420105600246140ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2006 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number macros ; ; Content: ; COPY_BNU ; CMP_BNU ; FIX_BNU ; ; SUB_FIX_BNU ; ADD_FIX_BNU ; ;; ;; CMP_BNU compare arbitrary BNUs ;; ;; input ;; rSrc1 points BNU1 ;; rSrc2 points BNU2 ;; rLen size of BNUs ;; ;; output ;; flags ;; %macro CMP_BNU 4.nolist %xdefine %%rSrc1 %1 %xdefine %%rSrc2 %2 %xdefine %%rLen %3 %xdefine %%tmp %4 %%cmp_loop: mov %%tmp,[%%rSrc1+%%rLen*4-4] cmp %%tmp,[%%rSrc2+%%rLen*4-4] jne %%cmp_quit sub %%rLen,1 jg %%cmp_loop %%cmp_quit: %endmacro ;; ;; SUB_FIX_BNU subtract fixed size BNUs ;; ;; input ;; rVal points src/dst BNU ;; rSrc points source BNU ;; immLen BNU size ;; %macro SUB_FIX_BNU 3.nolist %xdefine %%rVal %1 %xdefine %%rSrc %2 %xdefine %%immLen %3 pxor mm0,mm0 %assign %%i 0 %rep %%immLen movd mm1,DWORD [%%rVal+%%i*4] movd mm2,DWORD [%%rSrc+%%i*4] %if %%i != 0 paddq mm1,mm0 %endif psubq mm1,mm2 movd DWORD [%%rVal+%%i*4],mm1 %if %%i < (%%immLen-1) pshufw mm0,mm1,11111110b %endif %assign %%i %%i+1 %endrep %endmacro ;; ;; ADD_FIX_BNU add fixed size BNUs ;; ;; input ;; rVal points src/dst BNU ;; rSrc points source BNU ;; immLen BNU size ;; %macro ADD_FIX_BNU 3.nolist %xdefine %%rVal %1 %xdefine %%rSrc %2 %xdefine %%immLen %3 pxor mm0,mm0 %assign %%i 0 %rep %%immLen movd mm1,DWORD [%%rVal+%%i*4] movd mm2,DWORD [%%rSrc+%%i*4] %if %%i != 0 paddq mm1,mm0 %endif paddq mm1,mm2 movd DWORD [%%rVal+%%i*4],mm1 %if %%i < (%%immLen-1) pshufw mm0,mm1,11111110b %endif %assign %%i %%i+1 %endrep %endmacro ;; ;; COPY_BNU copy arbitrary BNU ;; %macro COPY_BNU 5.nolist %xdefine %%rSrc %1 %xdefine %%rDst %2 %xdefine %%rLen %3 %xdefine %%rIdx %4 %xdefine %%rTmp %5 xor %%rIdx,%%rIdx %%copy_bnu: mov %%rTmp,[%%rSrc+%%rIdx*4] mov [%%rDst+%%rIdx*4],%%rTmp add %%rIdx,1 cmp %%rIdx,%%rLen jl %%copy_bnu %endmacro ;; ;; FIX_BNU returns actual length of BNU ;; ;; input ;; rSrc points BNU ;; rLen initial BNU size ;; ;; output ;; rLen actual BNU size ;; %macro FIX_BNU 3.nolist %xdefine %%rSrc %1 %xdefine %%rLen %2 %xdefine %%tmp %3 %%fix_bnu_loop: mov %%tmp,[%%rSrc+%%rLen*4-4] ;; value test %%tmp,%%tmp ;; test BNU component jnz %%fix_bnu_quit sub %%rLen,1 jg %%fix_bnu_loop add %%rLen,1 %%fix_bnu_quit: %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro MULADD_START 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd mm1,DWORD [eax + 4*%%j] movd mm3,DWORD [eax + 4*%%j] pmuludq mm1,mm0 paddq mm7,mm1 movd DWORD [edx + 4*(%%i+%%j)],mm7 pand mm3,mm6 psrlq mm7,32 paddq mm7,mm3 %endmacro %macro MULADD 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd mm1,DWORD [eax + 4*%%j] movd mm3,DWORD [eax + 4*%%j] movd mm2,DWORD [edx + 4*(%%i+%%j)] pmuludq mm1,mm0 pand mm3,mm6 paddq mm1,mm2 paddq mm7,mm1 movd DWORD [edx + 4*(%%i+%%j)],mm7 psrlq mm7,32 paddq mm7,mm3 %endmacro %macro SQR_DECOMPOSE 1.nolist %xdefine %%i %1 movd mm7,DWORD [eax + 4*%%i] movd mm0,DWORD [eax + 4*%%i] movd mm6,DWORD [eax + 4*%%i] %if %%i != 0 movd mm1,DWORD [edx + 4*(2*%%i)] %endif pslld mm0,1 pmuludq mm7,mm7 psrad mm6,32 %if %%i != 0 paddq mm7,mm1 %endif movd DWORD [edx + 4*(2*%%i)],mm7 psrlq mm7,32 %endmacro %macro STORE_CARRY 2.nolist %xdefine %%i %1 %xdefine %%s %2 movq DWORD [edx + 4*(%%i + %%s)],mm7 %endmacro %macro STORE_CARRY_NEXT 2.nolist %xdefine %%i %1 %xdefine %%s %2 movd mm4,DWORD [edx + 4*(%%i + %%s)] paddq mm4,mm7 movd DWORD [edx + 4*(%%i + %%s)],mm4 psrlq mm7,32 movd DWORD [edx + 4*(%%i + %%s + 1)],mm7 %endmacro %macro LAST_STEP 1.nolist %xdefine %%s %1 movd mm7,DWORD [eax + 4*(%%s - 1)] movd mm2,DWORD [edx + 4*(2*%%s - 2)] pmuludq mm7,mm7 paddq mm7,mm2 movd mm4,DWORD [edx + 4*(2*%%s - 1)] movd DWORD [edx + 4*(2*%%s - 2)],mm7 psrlq mm7,32 paddq mm4,mm7 movd DWORD [edx + 4*(2*%%s - 1)],mm4 %endmacro %macro INNER_LOOP 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 %assign %%j %%i + 1 %assign %%s %%nsize - %%i - 1 SQR_DECOMPOSE %%i %rep %%s %if %%i == 0 MULADD_START %%i,%%j el%%se MULADD %%i,%%j %endif %assign %%j %%j + 1 %endrep %if %%i == 0 STORE_CARRY %%i,%%nsize el%%se STORE_CARRY_NEXT %%i,%%nsize %endif %endmacro %macro OUTER_LOOP 1.nolist %xdefine %%nsize %1 %assign %%i 0 %rep ns%%ize - 1 INNER_LOOP %%i,%%nsize %assign %%i %%i + 1 %endrep LAST_STEP %%nsize %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro MULADD_START_wt_carry 1.nolist %xdefine %%i %1 movd mm7,DWORD [eax] movd mm2,DWORD [edx + 4*(%%i)] pmuludq mm7,mm0 paddq mm7,mm2 movd DWORD [edx + 4*(%%i)],mm7 psrlq mm7,32 %endmacro %macro MULADD_START1 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd mm1,DWORD [eax + 4*%%j] pmuludq mm1,mm0 paddq mm7,mm1 movd DWORD [edx + 4*(%%i+%%j)],mm7 psrlq mm7,32 %endmacro %macro MULADD_START_wt_carry1 0.nolist movd mm7,DWORD [eax] pmuludq mm7,mm0 movd DWORD [edx],mm7 psrlq mm7,32 %endmacro %macro MULADD1 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd mm1,DWORD [eax + 4*%%j] movd mm2,DWORD [edx + 4*(%%i+%%j)] pmuludq mm1,mm0 paddq mm1,mm2 paddq mm7,mm1 movd DWORD [edx + 4*(%%i+%%j)],mm7 psrlq mm7,32 %endmacro %macro INNER_LOOP1 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 %assign %%j 0 movd mm0,DWORD [ebx + 4*%%i] %rep %%nsize %if %%i == 0 %if %%j == 0 MULADD_START_wt_carry1 %else MULADD_START1 %%i,%%j %endif %else %if %%j == 0 MULADD_START_wt_carry %%i %else MULADD1 %%i,%%j %endif %endif %assign %%j %%j + 1 %endrep movd DWORD [edx + 4*(%%i + %%nsize)],mm7 %endmacro %macro OUTER_LOOP1 1.nolist %xdefine %%nsize %1 %assign %%i 0 %rep %%nsize INNER_LOOP1 %%i,%%nsize %assign %%i %%i + 1 %endrep %endmacro cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnuaddw7as.asm000066400000000000000000000035351470420105600261010ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic ; ; Content: ; cpAddMul_BNU() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) %include "pcpvariant.inc" segment .text align=IPP_ALIGN_FACTOR %if (_USE_C_cpAdd_BNU_ == 0) align IPP_ALIGN_FACTOR IPPASM cpAdd_BNU,PUBLIC USES_GPR esi,edi,ebx %xdefine pDst [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine pSrc1 [esp + ARG_1 + 1*sizeof(dword)] ; source address %xdefine pSrc2 [esp + ARG_1 + 2*sizeof(dword)] ; source address %xdefine len [esp + ARG_1 + 3*sizeof(dword)] ; length of BNU mov eax,pSrc1 ; src1 mov ebx,pSrc2 ; src2 mov edx,pDst ; dst mov edi,len ; length shl edi,2 xor ecx,ecx pandn mm0,mm0 align IPP_ALIGN_FACTOR .main_loop: movd mm1,DWORD [eax + ecx] movd mm2,DWORD [ebx + ecx] paddq mm0,mm1 paddq mm0,mm2 movd DWORD [edx + ecx],mm0 pshufw mm0,mm0,11111110b add ecx,4 cmp ecx,edi jl .main_loop movd eax,mm0 emms REST_GPR ret ENDFUNC cpAdd_BNU %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnuincw7as.asm000066400000000000000000000034141470420105600261160ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; ; Content: ; cpInc_BNU() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) %include "pcpvariant.inc" %if (_USE_C_cpInc_BNU_ == 0) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM cpInc_BNU,PUBLIC USES_GPR esi,edi,ebx %xdefine pDst [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine pSrc [esp + ARG_1 + 1*sizeof(dword)] ; source address %xdefine len [esp + ARG_1 + 2*sizeof(dword)] ; length of BNU %xdefine value [esp + ARG_1 + 3*sizeof(dword)] ; increment val mov edi, pDst ; dst mov esi, pSrc ; src mov eax, value ; value movd mm0, value mov edx,len ; length shl edx,2 xor ecx,ecx align IPP_ALIGN_FACTOR .main_loop: movd mm1,DWORD [esi + ecx] paddq mm1,mm0 movd DWORD [edi + ecx],mm1 pshufw mm0,mm1,11111110b movd eax, mm0 add ecx,4 cmp ecx,edx jl .main_loop .exit_loop: emms REST_GPR ret ENDFUNC cpInc_BNU %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnumuldgtw7as.asm000066400000000000000000000037271470420105600266500ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic ; ; Content: ; cpMulDgt_BNU() ; cpAddMulDgt_BNU() ; cpSubMulDgtBNU() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) %include "pcpvariant.inc" segment .text align=IPP_ALIGN_FACTOR %if (_USE_C_cpAddMulDgt_BNU_ == 0) ;; ;; Ipp32u cpAddMulDgt_BNU(Ipp32u* pDst, const Ipp32u* pSrc, cpSize len, Ipp32u dgt) ;; IPPASM cpAddMulDgt_BNU,PUBLIC USES_GPR edi %xdefine pDst [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine pSrc [esp + ARG_1 + 1*sizeof(dword)] ; source address %xdefine len [esp + ARG_1 + 2*sizeof(dword)] ; BNU length %xdefine dgt [esp + ARG_1 + 3*sizeof(dword)] ; 32-bit multiplier mov eax,pSrc ; src mov edx,pDst ; dst mov edi,len ; length xor ecx,ecx shl edi,2 movd mm0,dgt pandn mm7,mm7 ;c .main_loop: movd mm1,DWORD [eax + ecx] movd mm2,DWORD [edx + ecx] pmuludq mm1,mm0 paddq mm7,mm1 paddq mm7,mm2 movd DWORD [edx + ecx],mm7 psrlq mm7,32 add ecx,4 cmp ecx,edi jl .main_loop movd eax,mm7 emms REST_GPR ret ENDFUNC cpAddMulDgt_BNU %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnumulschoolv8as.asm000066400000000000000000000701311470420105600273520ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic ; ; Content: ; cpMulAdc_BNU_school() ; ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_V8) %include "pcpvariant.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; Short-Length Squaring ;; %macro INIT 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 movd xmm0,DWORD [%%a] ;; a[0] pxor xmm7,xmm7 ;; clear carry movd DWORD [%%r],xmm7 ;; r[0] = 0 %assign %%i 1 movd xmm1,DWORD [%%a+%%i*4] ;; a[i] pmuludq xmm1,xmm0 ;; t0 = a[i]*a[0] movd xmm2,DWORD [%%a+%%i*4+4] ;; a[i+1] pmuludq xmm2,xmm0 ;; t1 = a[i+1]*a[0] %rep (%%n-1)/2 paddq xmm7,xmm1 ;; t0 += carry %if %%n-(%%i+2) > 0 movd xmm1,DWORD [%%a+(%%i+2)*4] ;; read in advance a[i+2] pmuludq xmm1,xmm0 ;; multiply in advance a[i+2]*a[0] %endif movd DWORD [%%r+%%i*4],xmm7 ;; r[i] = LO(t0) psrlq xmm7,32 ;; carry = HI(t0) paddq xmm7,xmm2 ;; t1 += carry %if %%n-(%%i+3) > 0 movd xmm2,DWORD [%%a+(%%i+2)*4+4] ;; read in advance a[i+3] pmuludq xmm2,xmm0 ;; multiply in advance a[i+3]*a[0] %endif movd DWORD [%%r+%%i*4+4],xmm7 ;; r[i+1] = LO(t1) psrlq xmm7,32 ;; carry = HI(t1) %assign %%i %%i+2 %endrep %if (((%%n-1) & 1) != 0) paddq xmm7,xmm1 ;; t0 += carry movd DWORD [%%r+%%i*4],xmm7 ;; r[i] = LO(t0) psrlq xmm7,32 ;; carry = HI(t0) %endif movd DWORD [%%r+%%n*4],xmm7 ;; r[n] = extension %endmacro %macro UPDATE_MUL 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 %assign %%i 1 %rep (%%n-2) movd xmm0,DWORD [%%a+%%i*4] ;; a[i] pxor xmm7,xmm7 ;; clear carry %assign %%j %%i+1 movd xmm1,DWORD [%%a+%%j*4] ;; a[j] pmuludq xmm1,xmm0 ;; t0 = a[j]*a[i] movd xmm3,DWORD [%%r+(%%i+%%j)*4] ;; r[i+j] %if (%%j+1) < %%n movd xmm2,DWORD [%%a+%%j*4+4] ;; a[j+1] pmuludq xmm2,xmm0 ;; t1 = a[j+1]*a[i] movd xmm4,DWORD [%%r+(%%i+%%j)*4+4];; r[i+j+1] %endif %assign %%tn %%n-%%j %rep %%tn/2 paddq xmm7,xmm1 ;; t0 += carry+r[i+j] %if %%n-(%%j+2) > 0 movd xmm1,DWORD [%%a+(%%j+2)*4] ;; read in advance a[j+2] pmuludq xmm1,xmm0 ;; multiply in advance a[j+2]*a[i] %endif paddq xmm7,xmm3 %if %%n-(%%j+2) > 0 movd xmm3,DWORD [%%r+(%%i+2+%%j)*4];; read in advance r[i+j+2] %endif movd DWORD [%%r+(%%i+%%j)*4],xmm7 ;; r[i+j] = LO(t0) psrlq xmm7,32 ;; carry = HI(t0) paddq xmm7,xmm2 ;; t1 += carry+r[i+j] %if %%n-(%%j+3) > 0 movd xmm2,DWORD [%%a+(%%j+2)*4+4];; read in advance a[j+3] pmuludq xmm2,xmm0 ;; multiply in advance a[j+3]*a[i] %endif paddq xmm7,xmm4 %if %%n-(%%j+3) > 0 movd xmm4,DWORD [%%r+(%%i+2+%%j)*4+4];; read in advance r[i+j+3] %endif movd DWORD [%%r+(%%i+%%j)*4+4],xmm7 ;; r[i+j+1] = LO(t1) psrlq xmm7,32 ;; carry = HI(t1) %assign %%j %%j+2 %endrep %if ((%%tn & 1) != 0) paddq xmm7,xmm1 paddq xmm7,xmm3 movd DWORD [%%r+(%%i+%%j)*4],xmm7 psrlq xmm7,32 ;; carry = HI(t1) %endif movd DWORD [%%r+(%%n+%%i)*4],xmm7 ;; r[i+j] = extension %assign %%i %%i+1 %endrep pandn xmm7,xmm7 ;; clear carry movd DWORD [%%r+(2*%%n-1)*4],xmm7 ;; r[2*n-1] = zero extension %endmacro %macro FINALIZE 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 %assign %%i 0 movd xmm0,DWORD [%%a+%%i*4] ;; a[i] pmuludq xmm0,xmm0 ;; p = a[i]*a[i] movd xmm2,DWORD [%%r+(2*%%i)*4] ;; r[2*i] paddq xmm2,xmm2 movd xmm3,DWORD [%%r+(2*%%i+1)*4] ;; r[2*i+1] paddq xmm3,xmm3 pcmpeqd xmm6,xmm6 ;; mm6 = low 32 bit mask psrlq xmm6,32 pandn xmm7,xmm7 ;; clear carry %rep %%n movq xmm1,xmm0 pand xmm0,xmm6 ;; mm0 = LO(p) psrlq xmm1,32 ;; mm1 = HI(p) paddq xmm7,xmm0 ;; q = carry + 2*r[2*i] + LO(p) %if %%n-(%%i+1) > 0 movd xmm0,DWORD [%%a+(%%i+1)*4] ;; a[i] pmuludq xmm0,xmm0 ;; p = a[i]*a[i] %endif paddq xmm7,xmm2 %if %%n-(%%i+1) > 0 movd xmm2,DWORD [%%r+(2*%%i+2)*4] ;; r[2*(i+1)] paddq xmm2,xmm2 %endif movd DWORD [%%r+(2*%%i)*4],xmm7 ;; r[2*i] = LO(q) psrlq xmm7,32 ;; carry = HI(q) paddq xmm7,xmm1 ;; q = carry + 2*r[2*i+1] + HI(p) paddq xmm7,xmm3 %if %%n-(%%i+1) > 0 movd xmm3,DWORD [%%r+(2*%%i+2)*4+4];; r[2*(i+1)+1] paddq xmm3,xmm3 %endif movd DWORD [%%r+(2*%%i+1)*4],xmm7 ;; r[2*i+1] = LO(q) psrlq xmm7,32 ;; carry = HI(q) %assign %%i %%i+1 %endrep %endmacro %macro SQR_SHORT 3 %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 INIT %%r,%%a,%%n UPDATE_MUL %%r,%%a,%%n FINALIZE %%r,%%a,%%n %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Middle-Length Squaring ;; %macro SQR_DECOMPOSE 1.nolist %xdefine %%i %1 movd xmm7,DWORD [eax + 4*%%i] movd xmm0,DWORD [eax + 4*%%i] movd xmm6,DWORD [eax + 4*%%i] %if %%i != 0 movd xmm1,DWORD [edx + 4*(2*%%i)] %endif psllq xmm0,1 pmuludq xmm7,xmm7 psrad xmm6,32 %if %%i != 0 paddq xmm7,xmm1 %endif movd DWORD [edx + 4*(2*%%i)],xmm7 psrlq xmm7,32 %endmacro %macro MULADD_START 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd xmm1,DWORD [eax + 4*%%j] movd xmm3,DWORD [eax + 4*%%j] pmuludq xmm1,xmm0 paddq xmm7,xmm1 movd DWORD [edx + 4*(%%i+%%j)],xmm7 pand xmm3,xmm6 psrlq xmm7,32 paddq xmm7,xmm3 %endmacro %macro MULADD 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd xmm1,DWORD [eax + 4*%%j] movd xmm3,DWORD [eax + 4*%%j] movd xmm2,DWORD [edx + 4*(%%i+%%j)] pmuludq xmm1,xmm0 pand xmm3,xmm6 paddq xmm1,xmm2 paddq xmm7,xmm1 movd DWORD [edx + 4*(%%i+%%j)],xmm7 psrlq xmm7,32 paddq xmm7,xmm3 %endmacro %macro STORE_CARRY 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 movq QWORD [edx + 4*(%%i + %%nsize)],xmm7 %endmacro %macro STORE_CARRY_NEXT 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 movd xmm4,DWORD [edx + 4*(%%i + %%nsize)] paddq xmm4,xmm7 movd DWORD [edx + 4*(%%i + %%nsize)],xmm4 psrlq xmm7,32 movd DWORD [edx + 4*(%%i + %%nsize + 1)],xmm7 %endmacro %macro INNER_LOOP 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 %assign %%j %%i + 1 %assign %%s %%nsize - %%i - 1 SQR_DECOMPOSE %%i %rep %%s %if %%i == 0 MULADD_START %%i,%%j el%%se MULADD %%i,%%j %endif %assign %%j %%j + 1 %endrep %if %%i == 0 STORE_CARRY %%i,%%nsize el%%se STORE_CARRY_NEXT %%i,%%nsize %endif %endmacro %macro LAST_STEP 1.nolist %xdefine %%nsize %1 movd xmm7,DWORD [eax + 4*(%%nsize - 1)] pmuludq xmm7,xmm7 movd xmm2,DWORD [edx + 4*(2*%%nsize - 2)] paddq xmm7,xmm2 movd xmm4,DWORD [edx + 4*(2*%%nsize - 1)] movd DWORD [edx + 4*(2*%%nsize - 2)],xmm7 psrlq xmm7,32 paddq xmm7,xmm4 movd DWORD [edx + 4*(2*%%nsize - 1)],xmm7 %endmacro %macro SQR_MIDDL 1.nolist %xdefine %%nsize %1 %assign %%i 0 %rep %%nsize - 1 INNER_LOOP %%i,%%nsize %assign %%i %%i + 1 %endrep LAST_STEP %%nsize %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro UNROLL16_MULADD 0.nolist movd xmm1,DWORD [eax + ecx] movd xmm2,DWORD [edx + ecx] movd xmm3,DWORD [eax + ecx + 4] movd xmm4,DWORD [edx + ecx + 4] movd xmm5,DWORD [eax + ecx + 8] movd xmm6,DWORD [edx + ecx + 8] pmuludq xmm1,xmm0 paddq xmm1,xmm2 pmuludq xmm3,xmm0 paddq xmm3,xmm4 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 12] movd xmm2,DWORD [edx + ecx + 12] movd DWORD [edx + ecx],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax + ecx + 16] movd xmm4,DWORD [edx + ecx + 16] movd DWORD [edx + ecx + 4],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax + ecx + 20] movd xmm6,DWORD [edx + ecx + 20] movd DWORD [edx + ecx + 8],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 24] movd xmm2,DWORD [edx + ecx + 24] movd DWORD [edx + ecx + 12],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax + ecx + 28] movd xmm4,DWORD [edx + ecx + 28] movd DWORD [edx + ecx + 16],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax + ecx + 32] movd xmm6,DWORD [edx + ecx + 32] movd DWORD [edx + ecx + 20],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 36] movd xmm2,DWORD [edx + ecx + 36] movd DWORD [edx + ecx + 24],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax + ecx + 40] movd xmm4,DWORD [edx + ecx + 40] movd DWORD [edx + ecx + 28],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax + ecx + 44] movd xmm6,DWORD [edx + ecx + 44] movd DWORD [edx + ecx + 32],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 48] movd xmm2,DWORD [edx + ecx + 48] movd DWORD [edx + ecx + 36],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax + ecx + 52] movd xmm4,DWORD [edx + ecx + 52] movd DWORD [edx + ecx + 40],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax + ecx + 56] movd xmm6,DWORD [edx + ecx + 56] movd DWORD [edx + ecx + 44],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 60] movd xmm2,DWORD [edx + ecx + 60] movd DWORD [edx + ecx + 48],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd DWORD [edx + ecx + 52],xmm7 psrlq xmm7,32 paddq xmm7,xmm5 movd DWORD [edx + ecx + 56],xmm7 psrlq xmm7,32 paddq xmm7,xmm1 movd DWORD [edx + ecx + 60],xmm7 psrlq xmm7,32 %endmacro %macro UNROLL8_MULADD 0.nolist movd xmm1,DWORD [eax + ecx] movd xmm2,DWORD [edx + ecx] movd xmm3,DWORD [eax + ecx + 4] movd xmm4,DWORD [edx + ecx + 4] movd xmm5,DWORD [eax + ecx + 8] movd xmm6,DWORD [edx + ecx + 8] pmuludq xmm1,xmm0 paddq xmm1,xmm2 pmuludq xmm3,xmm0 paddq xmm3,xmm4 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 12] movd xmm2,DWORD [edx + ecx + 12] movd DWORD [edx + ecx],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax + ecx + 16] movd xmm4,DWORD [edx + ecx + 16] movd DWORD [edx + ecx + 4],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax + ecx + 20] movd xmm6,DWORD [edx + ecx + 20] movd DWORD [edx + ecx + 8],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax + ecx + 24] movd xmm2,DWORD [edx + ecx + 24] movd DWORD [edx + ecx + 12],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax + ecx + 28] movd xmm4,DWORD [edx + ecx + 28] movd DWORD [edx + ecx + 16],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd DWORD [edx + ecx + 20],xmm7 psrlq xmm7,32 paddq xmm7,xmm1 movd DWORD [edx + ecx + 24],xmm7 psrlq xmm7,32 paddq xmm7,xmm3 movd DWORD [edx + ecx + 28],xmm7 psrlq xmm7,32 %endmacro %macro MUL_MAC0_START 0.nolist movd xmm7,DWORD [eax] pmuludq xmm7,xmm0 movd DWORD [edx],xmm7 psrlq xmm7,32 %endmacro %macro MUL_MAC0_START2 0.nolist movd xmm1,DWORD [eax] pmuludq xmm1,xmm0 movd DWORD [edx],xmm1 psrlq xmm1,32 movd xmm7,DWORD [eax+4] pmuludq xmm7,xmm0 paddq xmm7,xmm1 movd DWORD [edx+4],xmm7 psrlq xmm7,32 %endmacro %macro MUL_MAC0 1.nolist %xdefine %%j %1 movd xmm1,DWORD [eax + 4*%%j] pmuludq xmm1,xmm0 paddq xmm1,xmm7 movd DWORD [edx + 4*%%j],xmm1 psrlq xmm1,32 movd xmm7,DWORD [eax + 4*(%%j+1)] pmuludq xmm7,xmm0 paddq xmm7,xmm1 movd DWORD [edx + 4*(%%j+1)],xmm7 psrlq xmm7,32 %endmacro %macro MUL_MAC_START 1.nolist %xdefine %%i %1 movd xmm7,DWORD [eax] pmuludq xmm7,xmm0 movd xmm2,DWORD [edx + 4*(%%i)] paddq xmm7,xmm2 movd DWORD [edx + 4*(%%i)],xmm7 psrlq xmm7,32 %endmacro %macro MUL_MAC_START2 1.nolist %xdefine %%i %1 movd xmm1,DWORD [eax] pmuludq xmm1,xmm0 movd xmm2,DWORD [edx + 4*%%i] paddq xmm1,xmm2 movd DWORD [edx + 4*%%i],xmm1 psrlq xmm1,32 movd xmm7,DWORD [eax+4] pmuludq xmm7,xmm0 movd xmm2,DWORD [edx + 4*(%%i+1)] paddq xmm7,xmm2 paddq xmm7,xmm1 movd DWORD [edx + 4*(%%i+1)],xmm7 psrlq xmm7,32 %endmacro %macro MUL_MAC 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd xmm1,DWORD [eax + 4*%%j] pmuludq xmm1,xmm0 movd xmm2,DWORD [edx + 4*(%%i+%%j)] paddq xmm1,xmm2 paddq xmm1,xmm7 movd DWORD [edx + 4*(%%i+%%j)],xmm1 psrlq xmm1,32 movd xmm7,DWORD [eax + 4*(%%j+1)] pmuludq xmm7,xmm0 movd xmm2,DWORD [edx + 4*(%%i+%%j+1)] paddq xmm7,xmm2 paddq xmm7,xmm1 movd DWORD [edx + 4*(%%i+%%j+1)],xmm7 psrlq xmm7,32 %endmacro %macro INNER_LOOP1 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 %assign %%j 0 movd xmm0,DWORD [ebx + 4*%%i] %if %%i == 0 %if %%nsize & 1 MUL_MAC0_START %assign %%j %%j + 1 %else MUL_MAC0_START2 %assign %%j %%j + 2 %endif %else %if %%nsize & 1 MUL_MAC_START %%i %assign %%j %%j + 1 %else MUL_MAC_START2 %%i %assign %%j %%j + 2 %endif %endif %rep ((%%nsize-%%j)/2) %if %%i == 0 MUL_MAC0 %%j %else MUL_MAC %%i,%%j %endif %assign %%j %%j + 2 %endrep movd DWORD [edx + 4*(%%i + %%nsize)],xmm7 %endmacro %macro OUTER_LOOP1 1.nolist %xdefine %%nsize %1 %assign %%i 0 %rep %%nsize INNER_LOOP1 %%i,%%nsize %assign %%i %%i+1 %endrep %endmacro segment .text align=IPP_ALIGN_FACTOR %if (_USE_C_cpMulAdc_BNU_school_ == 0) ;************************************************************* ;* ;* void cpMulAdc_BNU_school(Ipp32u* pR, ;* const Ipp32u* pA, int aSize, ;* const Ipp32u* pB, int bSize) ;* ;************************************************************* ;; ;; Lib = V8 ;; ;; Caller = ippsMontMul ;; Caller = ippsMontExp ;; Caller = ippsModInv_BN ;; ;; Caller = ippsGFpECGetPointRegular ;; Caller = ippsGFpECTstPoint ;; Caller = ippsGFpECAddPoint ;; Caller = ippsGFpECMulPoint ;; Caller = ippsGFpECPrivateKey ;; Caller = ippsGFpECPublicKey ;; Caller = ippsGFpECTstKeyPair ;; Caller = ippsGFpECSharedSecretDH ;; Caller = ippsGFpECSharedSecretDHC ;; Caller = ippsGFpECSignDSA ;; Caller = ippsGFpECSignNR ;; Caller = ippsGFpECVerifyDSA ;; Caller = ippsGFpECVerifyNR ;; IPPASM cpMulAdc_BNU_school,PUBLIC USES_GPR esi,edi,ebx %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source address %xdefine aSize [esp + ARG_1 + 2*sizeof(dword)] ; BNU length %xdefine pB [esp + ARG_1 + 3*sizeof(dword)] ; source address %xdefine bSize [esp + ARG_1 + 4*sizeof(dword)] ; BNU length mov eax,pA ; pA mov edi,aSize ; aSzie_len mov ebx,pB ; pB mov esi,bSize ; bSize mov edx,pR ; pR cmp eax,ebx jne .multiplication ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; squaring ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp edi,1 jg .sqr2 .sqr1: movd xmm0,DWORD [eax] pmuludq xmm0,xmm0 movq QWORD [edx],xmm0 jmp .finish .sqr2: cmp edi,2 jg .sqr3 movd xmm0,DWORD [eax] movd xmm1,DWORD [eax+4] movq xmm2,xmm0 pmuludq xmm0,xmm0 ; a[0]*a[0] pmuludq xmm2,xmm1 ; a[0]*a[1] pmuludq xmm1,xmm1 ; a[1]*a[1] pcmpeqd xmm7,xmm7 ; mm7 = low 32 bit mask psrlq xmm7,32 pand xmm7,xmm2 ; mm7 = LO(a[0]*a[1]) paddq xmm7,xmm7 psrlq xmm2,32 ; mm2 = HI(a[0]*a[1]) paddq xmm2,xmm2 movd DWORD [edx],xmm0 psrlq xmm0,32 paddq xmm0,xmm7 movd DWORD [edx+4],xmm0 psrlq xmm0,32 paddq xmm2,xmm1 paddq xmm2,xmm0 movq QWORD [edx+8],xmm2 jmp .finish .sqr3: cmp edi,3 jg .sqr4 SQR_SHORT edx,eax,3 jmp .finish .sqr4: cmp edi,4 jg .sqr5 SQR_SHORT edx,eax,4 jmp .finish .sqr5: cmp edi,5 jg .sqr6 SQR_SHORT edx,eax,5 jmp .finish .sqr6: cmp edi,6 jg .sqr7 SQR_SHORT edx,eax,6 jmp .finish .sqr7: cmp edi,7 jg .sqr8 SQR_SHORT edx,eax,7 jmp .finish .sqr8: cmp edi,8 jg .sqr9 ;SQR_MIDDL 8 SQR_SHORT edx,eax,8 jmp .finish .sqr9: cmp edi,9 jg .sqr10 ;SQR_MIDDL 9 SQR_SHORT edx,eax,9 jmp .finish .sqr10: cmp edi,10 jg .sqr11 ;SQR_MIDDL 10 SQR_SHORT edx,eax,10 jmp .finish .sqr11: cmp edi,11 jg .sqr12 ;SQR_MIDDL 11 SQR_SHORT edx,eax,11 jmp .finish .sqr12: cmp edi,12 jg .sqr13 ;SQR_MIDDL 12 SQR_SHORT edx,eax,12 jmp .finish .sqr13: cmp edi,13 jg .sqr14 ;SQR_MIDDL 13 SQR_SHORT edx,eax,13 jmp .finish .sqr14: cmp edi,14 jg .sqr15 ;SQR_MIDDL 14 SQR_SHORT edx,eax,14 jmp .finish .sqr15: cmp edi,15 jg .sqr16 ;SQR_MIDDL 15 SQR_SHORT edx,eax,15 jmp .finish .sqr16: cmp edi,16 jg .sqr17 ;SQR_MIDDL 16 SQR_SHORT edx,eax,16 jmp .finish .sqr17: cmp edi,17 jg .common_case_sqr ;SQR_MIDDL 17 SQR_SHORT edx,eax,17 jmp .finish ;; ;; General case Squaring (aSize > 17) ;; .common_case_sqr: mov ebx,edx ; copy pR mov ecx,edi ; copy aSize ;; ;; init result: ;; r = (a[1],a[2],..a[N-1]) * a[0] ;; mov edx,1 ; i=1 movd xmm0,DWORD [eax] ; a[0] movd xmm1,DWORD [eax+edx*4] ; a[i] pmuludq xmm1,xmm0 ; p = a[i]*a[0] pandn xmm7,xmm7 ; clear carry movd DWORD [ebx],xmm7 ; r[0] = 0 .sqr_init_loop: movd xmm2,DWORD [eax+edx*4+4] ; read in advance a[i+1] pmuludq xmm2,xmm0 ; q = a[i+1]*a[0] paddq xmm7,xmm1 ; p+= carry movd DWORD [ebx+edx*4],xmm7 ; r[i] = LO(p) psrlq xmm7,32 ; carry = HI(p) add edx,2 cmp edx,ecx jg .sqr_break_init_loop movd xmm1,DWORD [eax+edx*4] ; next a[i] pmuludq xmm1,xmm0 ; p = a[i]*a[0] paddq xmm7,xmm2 ; q += carry movd DWORD [ebx+edx*4-4],xmm7 ; r[i+1] = LO(q) psrlq xmm7,32 ; carry = HI(q) jl .sqr_init_loop .sqr_break_init_loop: movd DWORD [ebx+ecx*4],xmm7 ; r[aSize] = carry ;; ;; add other a[i]*a[j], i=1,..,N-1, j=i+1,..,N-1 ;; mov edx,1 ; i=1 .sqr_update_mul_loop: mov esi,edx ; j=i+1 add esi,1 mov edi,edx ; i+j add edi,esi movd xmm0,DWORD [eax+edx*4] ; a[i] movd xmm1,DWORD [eax+esi*4] ; a[j] pmuludq xmm1,xmm0 ; p = a[j]*a[i] movd xmm3,DWORD [ebx+edi*4] ; r[i+j] pandn xmm7,xmm7 ; clear carry .sqr_update_mul_inner_loop: paddq xmm7,xmm1 ; p += carry+r[i+j] paddq xmm7,xmm3 movd DWORD [ebx+edi*4],xmm7 ; r[i+j] = LO(p) psrlq xmm7,32 ; carry = HI(p) movd xmm1,DWORD [eax+esi*4+4] ; read in advance a[i+1] pmuludq xmm1,xmm0 ; p = a[j+1]*a[i] movd xmm3,DWORD [ebx+edi*4+4] ; read in advance r[i+j+1] add edi,1 add esi,1 cmp esi,ecx jl .sqr_update_mul_inner_loop movd DWORD [ebx+edi*4],xmm7 ; r[i+j] = carry add edx,1 sub esi,1 cmp edx,esi jl .sqr_update_mul_loop pandn xmm7,xmm7 ; clear carry movd DWORD [ebx+edi*4+4],xmm7 ; r[i+j+1] = 0 ;; ;; double a[i]*a[j] and add a[i]^2 ;; pcmpeqd xmm6,xmm6 ; xmm6 = low 32 bit mask psrlq xmm6,32 movd xmm0,DWORD [eax] ; a[i] pmuludq xmm0,xmm0 ; p = a[i]*a[i] mov edx,0 ; i=0 movd xmm2,DWORD [ebx] ; r[2*i] movd xmm3,DWORD [ebx+4] ; r[2*i+1] pandn xmm7,xmm7 ; clear carry .sqr_loop: paddq xmm2,xmm2 ; 2*r[2*i] paddq xmm3,xmm3 ; 2*r[2*i+1] movq xmm1,xmm0 pand xmm0,xmm6 ; xmm0 = LO(p) psrlq xmm1,32 ; xmm1 = HI(p) paddq xmm7,xmm2 ; q = carry + 2*r[2*i] + LO(p) paddq xmm7,xmm0 movd DWORD [ebx+edx*8],xmm7 ; r[2*i] = LO(q) psrlq xmm7,32 ; carry = HI(q) movd xmm0,DWORD [eax+edx*4+4] ; read in advance a[i+1] pmuludq xmm0,xmm0 ; p = a[i+1]*a[i+1] paddq xmm7,xmm3 ; q = carry + 2*r[2*i+1] + HI(p) paddq xmm7,xmm1 movd DWORD [ebx+edx*8+4],xmm7 ; r[2*i+1] = LO(q) psrlq xmm7,32 ; carry = HI(q) add edx,1 movd xmm2,DWORD [ebx+edx*8] ; r[2*(i+1)] movd xmm3,DWORD [ebx+edx*8+4] ; r[2*(i+1)+1] cmp edx,ecx jl .sqr_loop jmp .finish ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; multiplication ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .multiplication: cmp edi,esi jne .common_case_mul .mul4: cmp edi,4 jne .mul5 OUTER_LOOP1 4 jmp .finish .mul5: cmp edi,5 jne .mul6 OUTER_LOOP1 5 jmp .finish .mul6: cmp edi,6 jne .mul7 OUTER_LOOP1 6 jmp .finish .mul7: cmp edi,7 jne .mul8 OUTER_LOOP1 7 jmp .finish .mul8: cmp edi,8 jne .mul9 OUTER_LOOP1 8 jmp .finish .mul9: cmp edi,9 jne .mul10 OUTER_LOOP1 9 jmp .finish .mul10: cmp edi,10 jne .mul11 OUTER_LOOP1 10 jmp .finish .mul11: cmp edi,11 jne .mul12 OUTER_LOOP1 11 jmp .finish .mul12: cmp edi,12 jne .mul13 OUTER_LOOP1 12 jmp .finish .mul13: cmp edi,13 jne .mul14 OUTER_LOOP1 13 jmp .finish .mul14: cmp edi,14 jne .mul15 OUTER_LOOP1 14 jmp .finish .mul15: cmp edi,15 jne .mul16 OUTER_LOOP1 15 jmp .finish .mul16: cmp edi,16 jne .mul17 OUTER_LOOP1 16 jmp .finish .mul17: cmp edi,17 jne .common_case_mul OUTER_LOOP1 17 jmp .finish ;; ;; General case Multiplication ;; .common_case_mul: cmp esi,edi ; bSize ~ aSize jae .ini_result xor edi,esi ; swap(aSize,bSize) xor esi,edi xor edi,esi mov edi,aSize mov esi,bSize xor eax,ebx ; swap(pA,pB) xor ebx,eax xor eax,ebx mov eax,pA mov ebx,pB .ini_result: add esi,edi xor ecx,ecx .mul_init_loop: mov [edx],ecx add edx,4 sub esi,1 jne .mul_init_loop mov esi,edi ; restore aSize mov edx,pR ; restore pR shl edi,2 ; aSize*4 ; ; multiplication loop ; .macLoop: movd xmm0,DWORD [ebx] ; pB[] pxor xmm7,xmm7 mov esi,edi ; number of loops (==aSize*4) xor ecx,ecx ; init loop counter and esi,7*4 jz .testSize_8 .tiny_loop: movd xmm1,DWORD [eax+ecx] movd xmm2,DWORD [edx+ecx] pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm1 movd DWORD [edx+ecx],xmm7 psrlq xmm7,32 add ecx,4 cmp ecx,esi jl .tiny_loop .testSize_8: mov esi,edi ; restore aSize*4 and esi,8*4 jz .testSize_16 UNROLL8_MULADD add ecx,8*4 .testSize_16: mov esi,edi ; restore aSize*4 and esi,0FFFFFFC0h jz .next_term .huge_loop: UNROLL16_MULADD add ecx,16*4 cmp ecx,esi jl .huge_loop .next_term: movd DWORD [edx + ecx],xmm7 add ebx,4 ; move to the next B[] add edx,4 ; move pR sub dword bSize,1 ; decrease bSize jne .macLoop .finish: REST_GPR ret ENDFUNC cpMulAdc_BNU_school %endif %endif ;; _IPP_V8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnusqrw7as.asm000066400000000000000000000426571470420105600261660ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic ; ; Content: ; cpSqrAdc_BNU_school() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) %include "pcpvariant.inc" ;; ;; Short-Length Squaring ;; %macro INIT 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 movd mm0,DWORD [%%a] ;; a[0] pandn mm7,mm7 ;; clear carry movd DWORD [%%r],mm7 ;; r[0] = 0 %assign %%i 1 movd mm1,DWORD [%%a+%%i*4] ;; a[i] pmuludq mm1,mm0 ;; t0 = a[i]*a[0] movd mm2,DWORD [%%a+%%i*4+4] ;; a[i+1] pmuludq mm2,mm0 ;; t1 = a[i+1]*a[0] %rep (%%n-1)/2 paddq mm7,mm1 ;; t0 += carry %if %%n-(%%i+2) > 0 movd mm1,DWORD [%%a+(%%i+2)*4] ;; read in advance a[i+2] pmuludq mm1,mm0 ;; multiply in advance a[i+2]*a[0] %endif movd DWORD [%%r+%%i*4],mm7 ;; r[i] = LO(t0) psrlq mm7,32 ;; carry = HI(t0) paddq mm7,mm2 ;; t1 += carry %if %%n-(%%i+3) > 0 movd mm2,DWORD [%%a+(%%i+2)*4+4] ;; read in advance a[i+3] pmuludq mm2,mm0 ;; multiply in advance a[i+3]*a[0] %endif movd DWORD [%%r+%%i*4+4],mm7 ;; r[i+1] = LO(t1) psrlq mm7,32 ;; carry = HI(t1) %assign %%i %%i+2 %endrep %if (((%%n-1) & 1) != 0) paddq mm7,mm1 ;; t0 += carry movd DWORD [%%r+%%i*4],mm7 ;; r[i] = LO(t0) psrlq mm7,32 ;; carry = HI(t0) %endif movd DWORD [%%r+%%n*4],mm7 ;; r[n] = extension %endmacro %macro UPDATE_MUL 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 %assign %%i 1 %rep (%%n-2) movd mm0,DWORD [%%a+%%i*4] ;; a[i] pandn mm7,mm7 ;; clear carry %assign %%j %%i+1 movd mm1,DWORD [%%a+%%j*4] ;; a[j] pmuludq mm1,mm0 ;; t0 = a[j]*a[i] movd mm3,DWORD [%%r+(%%i+%%j)*4] ;; r[i+j] %if (%%j+1) < %%n movd mm2,DWORD [%%a+%%j*4+4] ;; a[j+1] pmuludq mm2,mm0 ;; t1 = a[j+1]*a[i] movd mm4,DWORD [%%r+(%%i+%%j)*4+4] ;; r[i+j+1] %endif %assign %%tn %%n-%%j %rep %%tn/2 paddq mm7,mm1 ;; t0 += carry+r[i+j] %if %%n-(%%j+2) > 0 movd mm1,DWORD [%%a+(%%j+2)*4] ;; read in advance a[j+2] pmuludq mm1,mm0 ;; multiply in advance a[j+2]*a[i] %endif paddq mm7,mm3 %if %%n-(%%j+2) > 0 movd mm3,DWORD [%%r+(%%i+2+%%j)*4] ;; read in advance r[i+j+2] %endif movd DWORD [%%r+(%%i+%%j)*4],mm7 ;; r[i+j] = LO(t0) psrlq mm7,32 ;; carry = HI(t0) paddq mm7,mm2 ;; t1 += carry+r[i+j] %if %%n-(%%j+3) > 0 movd mm2,DWORD [%%a+(%%j+2)*4+4] ;; read in advance a[j+3] pmuludq mm2,mm0 ;; multiply in advance a[j+3]*a[i] %endif paddq mm7,mm4 %if %%n-(%%j+3) > 0 movd mm4,DWORD [%%r+(%%i+2+%%j)*4+4];; read in advance r[i+j+3] %endif movd DWORD [%%r+(%%i+%%j)*4+4],mm7 ;; r[i+j+1] = LO(t1) psrlq mm7,32 ;; carry = HI(t1) %assign %%j %%j+2 %endrep %if ((%%tn & 1) != 0) paddq mm7,mm1 paddq mm7,mm3 movd DWORD [%%r+(%%i+%%j)*4],mm7 psrlq mm7,32 ;; carry = HI(t1) %endif movd DWORD [%%r+(%%n+%%i)*4],mm7 ;; r[i+j] = extension %assign %%i %%i+1 %endrep pandn mm7,mm7 ;; clear carry movd DWORD [%%r+(2*%%n-1)*4],mm7 ;; r[2*n-1] = zero extension %endmacro %macro FINALIZE 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 %assign %%i 0 movd mm0,DWORD [%%a+%%i*4] ;; a[i] pmuludq mm0,mm0 ;; p = a[i]*a[i] movd mm2,DWORD [%%r+(2*%%i)*4] ;; r[2*i] paddq mm2,mm2 movd mm3,DWORD [%%r+(2*%%i+1)*4];; r[2*i+1] paddq mm3,mm3 pcmpeqd mm6,mm6 ;; mm6 = low 32 bit mask psrlq mm6,32 pandn mm7,mm7 ;; clear carry %rep %%n movq mm1,mm0 pand mm0,mm6 ;; mm0 = LO(p) psrlq mm1,32 ;; mm1 = HI(p) paddq mm7,mm0 ;; q = carry + 2*r[2*i] + LO(p) %if %%n-(%%i+1) > 0 movd mm0,DWORD [%%a+(%%i+1)*4] ;; a[i] pmuludq mm0,mm0 ;; p = a[i]*a[i] %endif paddq mm7,mm2 %if %%n-(%%i+1) > 0 movd mm2,DWORD [%%r+(2*%%i+2)*4] ;; r[2*(i+1)] paddq mm2,mm2 %endif movd DWORD [%%r+(2*%%i)*4],mm7 ;; r[2*i] = LO(q) psrlq mm7,32 ;; carry = HI(q) paddq mm7,mm1 ;; q = carry + 2*r[2*i+1] + HI(p) paddq mm7,mm3 %if %%n-(%%i+1) > 0 movd mm3,DWORD [%%r+(2*%%i+2)*4+4] ;; r[2*(i+1)+1] paddq mm3,mm3 %endif movd DWORD [%%r+(2*%%i+1)*4],mm7 ;; r[2*i+1] = LO(q) psrlq mm7,32 ;; carry = HI(q) %assign %%i %%i+1 %endrep %endmacro %macro INIT1 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 movd mm0,DWORD [%%a] ;; a[0] pandn mm7,mm7 ;; clear carry movd DWORD [%%r],mm7 ;; r[0] = 0 %assign %%i 1 %rep (%%n-1) movd mm1,DWORD [%%a+%%i*4] ;; a[i] pmuludq mm1,mm0 ;; t0 = a[i]*a[0] paddq mm7,mm1 ;; t0 += carry movd DWORD [%%r+%%i*4],mm7 ;; r[i] = LO(t0) psrlq mm7,32 ;; carry = HI(t0) %assign %%i %%i+1 %endrep movd DWORD [%%r+%%n*4],mm7 ;; r[n] = extension %endmacro %macro UPDATE_MUL1 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 %assign %%i 1 %rep (%%n-2) movd mm0,DWORD [%%a+%%i*4] ;; a[i] pandn mm7,mm7 ;; clear carry %assign %%j %%i+1 %rep (%%n-%%j) movd mm1,DWORD [%%a+%%j*4] ;; a[j]) pmuludq mm1,mm0 ;; t0 = a[j]*a[i] movd mm3,DWORD [%%r+(%%i+%%j)*4] ;; r[i+j] paddq mm7,mm1 ;; t0 += carry+r[i+j] paddq mm7,mm3 movd DWORD [%%r+(%%i+%%j)*4],mm7 ;; r[i+j] = LO(t0) psrlq mm7,32 ;; carry = HI(t0) %assign %%j %%j+1 %endrep movd DWORD [%%r+(%%n+%%i)*4],mm7 ;; r[i+j] = extension %assign %%i %%i+1 %endrep pandn mm7,mm7 ;; clear carry movd DWORD [%%r+(2*%%n-1)*4],mm7 ;; r[2*n-1] = zero extension %endmacro %macro SQUARE_SHORT 3.nolist %xdefine %%r %1 %xdefine %%a %2 %xdefine %%n %3 INIT %%r,%%a,%%n UPDATE_MUL %%r,%%a,%%n FINALIZE %%r,%%a,%%n emms %endmacro ;; ;; Middle-Length Squaring ;; %macro SQR_DECOMPOSE 1.nolist %xdefine %%i %1 movd mm7,DWORD [eax + 4*%%i] movd mm0,DWORD [eax + 4*%%i] movd mm6,DWORD [eax + 4*%%i] %if %%i != 0 movd mm1,DWORD [ebx + 4*(2*%%i)] %endif pslld mm0,1 pmuludq mm7,mm7 psrad mm6,32 %if %%i != 0 paddq mm7,mm1 %endif movd DWORD [ebx + 4*(2*%%i)],mm7 psrlq mm7,32 %endmacro %macro MULADD_START 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd mm1,DWORD [eax + 4*%%j] movd mm3,DWORD [eax + 4*%%j] pmuludq mm1,mm0 paddq mm7,mm1 movd DWORD [ebx + 4*(%%i+%%j)],mm7 pand mm3,mm6 psrlq mm7,32 paddq mm7,mm3 %endmacro %macro MULADD 2.nolist %xdefine %%i %1 %xdefine %%j %2 movd mm1,DWORD [eax + 4*%%j] movd mm3,DWORD [eax + 4*%%j] movd mm2,DWORD [ebx + 4*(%%i+%%j)] pmuludq mm1,mm0 pand mm3,mm6 paddq mm1,mm2 paddq mm7,mm1 movd DWORD [ebx + 4*(%%i+%%j)],mm7 psrlq mm7,32 paddq mm7,mm3 %endmacro %macro STORE_CARRY 2.nolist %xdefine %%i %1 %xdefine %%s %2 movq [ebx + 4*(%%i + %%s)],mm7 %endmacro %macro STORE_CARRY_NEXT 2.nolist %xdefine %%i %1 %xdefine %%s %2 movd mm4,DWORD [ebx + 4*(%%i + %%s)] paddq mm4,mm7 movd DWORD [ebx + 4*(%%i + %%s)],mm4 psrlq mm7,32 movd DWORD [ebx + 4*(%%i + %%s + 1)],mm7 %endmacro %macro INNER_LOOP 2.nolist %xdefine %%i %1 %xdefine %%nsize %2 %assign %%j %%i + 1 %assign %%s %%nsize - %%i - 1 SQR_DECOMPOSE %%i %rep %%s %if %%i == 0 MULADD_START %%i,%%j el%%se MULADD %%i,%%j %endif %assign %%j %%j + 1 %endrep %if %%i == 0 STORE_CARRY %%i,%%nsize %else STORE_CARRY_NEXT %%i,%%nsize %endif %endmacro %macro LAST_STEP 1.nolist %xdefine %%s %1 movd mm7,DWORD [eax + 4*(%%s - 1)] movd mm2,DWORD [ebx + 4*(2*%%s - 2)] pmuludq mm7,mm7 paddq mm7,mm2 movd mm4,DWORD [ebx + 4*(2*%%s - 1)] movd DWORD [ebx + 4*(2*%%s - 2)],mm7 psrlq mm7,32 paddq mm4,mm7 movd DWORD [ebx + 4*(2*%%s - 1)],mm4 %endmacro %macro SQUARE_MIDL 1.nolist %xdefine %%nsize %1 %assign %%i 0 %rep %%nsize - 1 INNER_LOOP %%i,%%nsize %assign %%i %%i + 1 %endrep LAST_STEP %%nsize emms %endmacro %if (_USE_C_cpSqrAdc_BNU_school_ == 0) segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* void cpSqrAdc_BNU_school(Ipp32u* pR, const Ipp32u* pA, int aSize) ;* ;************************************************************* ;; ;; Lib = W7 ;; ;; Caller = ippsMontMul ;; Caller = ippsMontExp ;; ;; Caller = ippsGFpECGetPointRegular ;; Caller = ippsGFpECTstPoint ;; Caller = ippsGFpECAddPoint ;; Caller = ippsGFpECMulPoint ;; Caller = ippsGFpECPrivateKey ;; Caller = ippsGFpECPublicKey ;; Caller = ippsGFpECTstKeyPair ;; Caller = ippsGFpECSharedSecretDH ;; Caller = ippsGFpECSharedSecretDHC ;; Caller = ippsGFpECSignDSA ;; Caller = ippsGFpECSignNR ;; Caller = ippsGFpECVerifyDSA ;; Caller = ippsGFpECVerifyNR ;; IPPASM cpSqrAdc_BNU_school,PUBLIC USES_GPR esi,edi,ebx %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source address %xdefine aSize [esp + ARG_1 + 2*sizeof(dword)] ; BNU length mov eax,pA ; src mov ebx,pR ; dst mov ecx,aSize ; length ;; ;; switch ;; .len1: cmp ecx,1 jg .len2 movd mm0,DWORD [eax] pmuludq mm0,mm0 movq QWORD [ebx],mm0 jmp .finish .len2: cmp ecx,2 jg .len3 movd mm0,DWORD [eax] movd mm1,DWORD [eax+4] movq mm2,mm0 pmuludq mm0,mm0 ; a[0]*a[0] pmuludq mm2,mm1 ; a[0]*a[1] pmuludq mm1,mm1 ; a[1]*a[1] pcmpeqd mm7,mm7 ; mm7 = low 32 bit mask psrlq mm7,32 pand mm7,mm2 ; mm7 = LO(a[0]*a[1]) paddq mm7,mm7 psrlq mm2,32 ; mm2 = HI(a[0]*a[1]) paddq mm2,mm2 movd DWORD [ebx],mm0 psrlq mm0,32 paddq mm0,mm7 movd DWORD [ebx+4],mm0 psrlq mm0,32 paddq mm2,mm1 paddq mm2,mm0 movq QWORD [ebx+8],mm2 jmp .finish .len3: cmp ecx,3 jg .len4 SQUARE_SHORT ebx,eax,3 jmp .finish .len4: cmp ecx,4 jg .len5 SQUARE_SHORT ebx,eax,4 jmp .finish .len5: cmp ecx,5 jg .len6 SQUARE_SHORT ebx,eax,5 jmp .finish .len6: cmp ecx,6 jg .len7 SQUARE_SHORT ebx,eax,6 jmp .finish .len7: cmp ecx,7 jg .len8 SQUARE_SHORT ebx,eax,7 jmp .finish .len8: cmp ecx,8 jg .len9 ;SQUARE_MIDL 8 SQUARE_SHORT ebx,eax,8 jmp .finish .len9: cmp ecx,9 jg .len10 ;SQUARE_MIDL 9 SQUARE_SHORT ebx,eax,9 jmp .finish .len10: cmp ecx,10 jg .len11 ;SQUARE_MIDL 10 SQUARE_SHORT ebx,eax,10 jmp .finish .len11: cmp ecx,11 jg .len12 ;SQUARE_MIDL 11 SQUARE_SHORT ebx,eax,11 jmp .finish .len12: cmp ecx,12 jg .len13 ;SQUARE_MIDL 12 SQUARE_SHORT ebx,eax,12 jmp .finish .len13: cmp ecx,13 jg .len14 ;SQUARE_MIDL 13 SQUARE_SHORT ebx,eax,13 jmp .finish .len14: cmp ecx,14 jg .len15 ;SQUARE_MIDL 14 SQUARE_SHORT ebx,eax,14 jmp .finish .len15: cmp ecx,15 jg .len16 ;SQUARE_MIDL 15 SQUARE_SHORT ebx,eax,15 jmp .finish .len16: cmp ecx,16 jg .len17 ;SQUARE_MIDL 16 SQUARE_SHORT ebx,eax,16 jmp .finish .len17: cmp ecx,17 jg .common_case ;SQUARE_MIDL 17 SQUARE_SHORT ebx,eax,17 jmp .finish ;; ;; Ceneral case (aSize > 17) ;; .common_case: ;; ;; init result: ;; r = (a[1],a[2],..a[N-1]) * a[0] ;; mov edx,1 ; i=1 movd mm0,DWORD [eax] ; a[0] movd mm1,DWORD [eax+edx*4] ; a[i] pmuludq mm1,mm0 ; p = a[i]*a[0] pandn mm7,mm7 ; clear carry movd DWORD [ebx],mm7 ; r[0] = 0 .init_loop: movd mm2,DWORD [eax+edx*4+4] ; read in advance a[i+1] pmuludq mm2,mm0 ; q = a[i+1]*a[0] paddq mm7,mm1 ; p+= carry movd DWORD [ebx+edx*4],mm7 ; r[i] = LO(p) psrlq mm7,32 ; carry = HI(p) add edx,2 cmp edx,ecx jg .break_init_loop movd mm1,DWORD [eax+edx*4] ; next a[i] pmuludq mm1,mm0 ; p = a[i]*a[0] paddq mm7,mm2 ; q += carry movd DWORD [ebx+edx*4-4],mm7 ; r[i+1] = LO(q) psrlq mm7,32 ; carry = HI(q) jl .init_loop .break_init_loop: movd DWORD [ebx+ecx*4],mm7 ; r[aSize] = carry ;; ;; add other a[i]*a[j], i=1,..,N-1, j=i+1,..,N-1 ;; mov edx,1 ; i=1 .update_mul_loop: mov esi,edx ; j=i+1 add esi,1 mov edi,edx ; i+j add edi,esi movd mm0,DWORD [eax+edx*4] ; a[i] movd mm1,DWORD [eax+esi*4] ; a[j] pmuludq mm1,mm0 ; p = a[j]*a[i] movd mm3,DWORD [ebx+edi*4] ; r[i+j] pandn mm7,mm7 ; clear carry .update_mul_inner_loop: paddq mm7,mm1 ; p += carry+r[i+j] paddq mm7,mm3 movd DWORD [ebx+edi*4],mm7 ; r[i+j] = LO(p) psrlq mm7,32 ; carry = HI(p) movd mm1,DWORD [eax+esi*4+4] ; read in advance a[i+1] pmuludq mm1,mm0 ; p = a[j+1]*a[i] movd mm3,DWORD [ebx+edi*4+4] ; read in advance r[i+j+1] add edi,1 add esi,1 cmp esi,ecx jl .update_mul_inner_loop movd DWORD [ebx+edi*4],mm7 ; r[i+j] = carry add edx,1 sub esi,1 cmp edx,esi jl .update_mul_loop pandn mm7,mm7 ; clear carry movd DWORD [ebx+edi*4+4],mm7 ; r[i+j+1] = 0 ;; ;; double a[i]*a[j] and add a[i]^2 ;; pcmpeqd mm6,mm6 ; mm6 = low 32 bit mask psrlq mm6,32 movd mm0,DWORD [eax] ; a[i] pmuludq mm0,mm0 ; p = a[i]*a[i] mov edx,0 ; i=0 movd mm2,DWORD [ebx] ; r[2*i] movd mm3,DWORD [ebx+4] ; r[2*i+1] pandn mm7,mm7 ; clear carry .sqr_loop: paddq mm2,mm2 ; 2*r[2*i] paddq mm3,mm3 ; 2*r[2*i+1] movq mm1,mm0 pand mm0,mm6 ; mm0 = LO(p) psrlq mm1,32 ; mm1 = HI(p) paddq mm7,mm2 ; q = carry + 2*r[2*i] + LO(p) paddq mm7,mm0 movd DWORD [ebx+edx*8],mm7 ; r[2*i] = LO(q) psrlq mm7,32 ; carry = HI(q) movd mm0,DWORD [eax+edx*4+4] ; read in advance a[i+1] pmuludq mm0,mm0 ; p = a[i+1]*a[i+1] paddq mm7,mm3 ; q = carry + 2*r[2*i+1] + HI(p) paddq mm7,mm1 movd DWORD [ebx+edx*8+4],mm7 ; r[2*i+1] = LO(q) psrlq mm7,32 ; carry = HI(q) add edx,1 movd mm2,DWORD [ebx+edx*8] ; r[2*(i+1)] movd mm3,DWORD [ebx+edx*8+4] ; r[2*(i+1)+1] cmp edx,ecx jl .sqr_loop .finish: emms REST_GPR ret ENDFUNC cpSqrAdc_BNU_school %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpbnusubw7as.asm000066400000000000000000000035541470420105600261430ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic ; ; Content: ; cpSubMul_BNU() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) %include "pcpvariant.inc" segment .text align=IPP_ALIGN_FACTOR %if (_USE_C_cpSub_BNU_ == 0) align IPP_ALIGN_FACTOR IPPASM cpSub_BNU,PUBLIC USES_GPR esi,edi,ebx %xdefine pDst [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine pSrc1 [esp + ARG_1 + 1*sizeof(dword)] ; source address %xdefine pSrc2 [esp + ARG_1 + 2*sizeof(dword)] ; source address %xdefine len [esp + ARG_1 + 3*sizeof(dword)] ; length of BNU mov eax,pSrc1 ; src1 mov ebx,pSrc2 ; src2 mov edx,pDst ; dst mov edi,len ; length shl edi,2 xor ecx,ecx pandn mm0,mm0 align IPP_ALIGN_FACTOR .main_loop: movd mm1,DWORD [eax + ecx] movd mm2,DWORD [ebx + ecx] paddq mm0,mm1 psubq mm0,mm2 movd DWORD [edx + ecx],mm0 pshufw mm0,mm0,11111110b add ecx,4 cmp ecx,edi jl .main_loop movd eax,mm0 neg eax emms REST_GPR ret ENDFUNC cpSub_BNU %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpdelay.asm000066400000000000000000000025421470420105600251350ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2022 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Delay function, ia32 version ; ; Content: ; _ippcpDelay() ; %include "asmdefs.inc" %include "ia_emm.inc" segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: delay ;* ;* void _ippcpDelay(Ipp32u value) ;* ;* Caller = cpAESRandomNoise ;*************************************************************** align IPP_ALIGN_FACTOR IPPASM _ippcpDelay,PUBLIC %xdefine delayVal [esp + 4] ; indent through the return address mov ecx,delayVal .Loop: mov eax,ecx dec ecx test eax,eax jnz .Loop ret ENDFUNC _ippcpDelay cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpmd5w7as.asm000066400000000000000000000234221470420105600253260ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to MD5 ; (derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm) ; ; Content: ; UpdateMD5 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_MD5_) %if (_IPP >= _IPP_M5) ;; ;; Magic functions defined in RFC 1321 ;; %macro MAGIC_F 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F,%%Z xor %%F,%%Y and %%F,%%X xor %%F,%%Z %endmacro %macro MAGIC_G 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 MAGIC_F %%F,%%Z,%%X,%%Y %endmacro %macro MAGIC_H 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F,%%Z xor %%F,%%Y xor %%F,%%X %endmacro %macro MAGIC_I 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F,%%Z not %%F or %%F,%%X xor %%F,%%Y %endmacro ;; ;; single MD5 step ;; ;; A = B +ROL32((A +MAGIC(B,C,D) +data +const), nrot) ;; %macro MD5_STEP 9.nolist %xdefine %%MAGIC_FUN %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%FUN %6 %xdefine %%data %7 %xdefine %%MD5const %8 %xdefine %%nrot %9 add %%A,%%MD5const add %%A,[%%data] MAGIC_FUN %%FUN, %%B,%%C,%%D add %%A,%%FUN rol %%A,%%nrot add %%A,%%B %endmacro %macro MD5_RND 9.nolist %xdefine %%MAGIC_FUN %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%FUN %6 %xdefine %%MD5const %7 %xdefine %%nrot %8 %xdefine %%nextdata %9 %%MAGIC_FUN %%FUN, %%B,%%C,%%D lea %%A,[%%A+ebp+%%MD5const] %ifnempty %%nextdata mov ebp,[%%nextdata] %endif ; MAGIC_FUN FUN, B,C,D add %%A,%%FUN rol %%A,%%nrot add %%A,%%B %endmacro segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateMD5(DigestMD5digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; MD5 left rotations (number of bits) ;; %assign rot11 7 %assign rot12 12 %assign rot13 17 %assign rot14 22 %assign rot21 5 %assign rot22 9 %assign rot23 14 %assign rot24 20 %assign rot31 4 %assign rot32 11 %assign rot33 16 %assign rot34 23 %assign rot41 6 %assign rot42 10 %assign rot43 15 %assign rot44 21 ;; ;; Lib = W7 ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; align IPP_ALIGN_FACTOR IPPASM UpdateMD5,PUBLIC USES_GPR esi,edi,ebx,ebp %xdefine digest [esp + ARG_1 + 0*sizeof(dword)] ; digest address %xdefine mblk [esp + ARG_1 + 1*sizeof(dword)] ; buffer address %xdefine mlen [esp + ARG_1 + 2*sizeof(dword)] ; buffer length %xdefine pParam [esp + ARG_1 + 3*sizeof(dword)] ; dummy parameter %xdefine MBS_MD5 (64) mov eax, pParam ; due to bug in ml12 - dummy instruction mov edi,digest ; digest address mov esi,mblk ; source data address mov eax,mlen ; data length sub esp,2*sizeof(dword) mov [esp+0*sizeof(dword)],edi ; save digest address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .md5_block_loop: mov [esp+1*sizeof(dword)],eax ; save data length mov ebp,[esi+ 0*4] ; preload data ;; ;; init A, B, C, D by the internal digest ;; mov eax,[edi+0*4] ; eax = digest[0] (A) mov ebx,[edi+1*4] ; ebx = digest[1] (B) mov ecx,[edi+2*4] ; ecx = digest[2] (C) mov edx,[edi+3*4] ; edx = digest[3] (D) ;; ;; perform 0-63 steps ;; ;; MAGIC A, B, C, D, FUN, cnt, nrot, pNextData (ebp) ;; ------------------------------------------------------------ MD5_RND MAGIC_F, eax,ebx,ecx,edx, edi, 0d76aa478h, rot11, {esi+ 1*4} MD5_RND MAGIC_F, edx,eax,ebx,ecx, edi, 0e8c7b756h, rot12, {esi+ 2*4} MD5_RND MAGIC_F, ecx,edx,eax,ebx, edi, 0242070dbh, rot13, {esi+ 3*4} MD5_RND MAGIC_F, ebx,ecx,edx,eax, edi, 0c1bdceeeh, rot14, {esi+ 4*4} MD5_RND MAGIC_F, eax,ebx,ecx,edx, edi, 0f57c0fafh, rot11, {esi+ 5*4} MD5_RND MAGIC_F, edx,eax,ebx,ecx, edi, 04787c62ah, rot12, {esi+ 6*4} MD5_RND MAGIC_F, ecx,edx,eax,ebx, edi, 0a8304613h, rot13, {esi+ 7*4} MD5_RND MAGIC_F, ebx,ecx,edx,eax, edi, 0fd469501h, rot14, {esi+ 8*4} MD5_RND MAGIC_F, eax,ebx,ecx,edx, edi, 0698098d8h, rot11, {esi+ 9*4} MD5_RND MAGIC_F, edx,eax,ebx,ecx, edi, 08b44f7afh, rot12, {esi+10*4} MD5_RND MAGIC_F, ecx,edx,eax,ebx, edi, 0ffff5bb1h, rot13, {esi+11*4} MD5_RND MAGIC_F, ebx,ecx,edx,eax, edi, 0895cd7beh, rot14, {esi+12*4} MD5_RND MAGIC_F, eax,ebx,ecx,edx, edi, 06b901122h, rot11, {esi+13*4} MD5_RND MAGIC_F, edx,eax,ebx,ecx, edi, 0fd987193h, rot12, {esi+14*4} MD5_RND MAGIC_F, ecx,edx,eax,ebx, edi, 0a679438eh, rot13, {esi+15*4} MD5_RND MAGIC_F, ebx,ecx,edx,eax, edi, 049b40821h, rot14, {esi+ 1*4} MD5_RND MAGIC_G, eax,ebx,ecx,edx, edi, 0f61e2562h, rot21, {esi+ 6*4} MD5_RND MAGIC_G, edx,eax,ebx,ecx, edi, 0c040b340h, rot22, {esi+11*4} MD5_RND MAGIC_G, ecx,edx,eax,ebx, edi, 0265e5a51h, rot23, {esi+ 0*4} MD5_RND MAGIC_G, ebx,ecx,edx,eax, edi, 0e9b6c7aah, rot24, {esi+ 5*4} MD5_RND MAGIC_G, eax,ebx,ecx,edx, edi, 0d62f105dh, rot21, {esi+10*4} MD5_RND MAGIC_G, edx,eax,ebx,ecx, edi, 002441453h, rot22, {esi+15*4} MD5_RND MAGIC_G, ecx,edx,eax,ebx, edi, 0d8a1e681h, rot23, {esi+ 4*4} MD5_RND MAGIC_G, ebx,ecx,edx,eax, edi, 0e7d3fbc8h, rot24, {esi+ 9*4} MD5_RND MAGIC_G, eax,ebx,ecx,edx, edi, 021e1cde6h, rot21, {esi+14*4} MD5_RND MAGIC_G, edx,eax,ebx,ecx, edi, 0c33707d6h, rot22, {esi+ 3*4} MD5_RND MAGIC_G, ecx,edx,eax,ebx, edi, 0f4d50d87h, rot23, {esi+ 8*4} MD5_RND MAGIC_G, ebx,ecx,edx,eax, edi, 0455a14edh, rot24, {esi+13*4} MD5_RND MAGIC_G, eax,ebx,ecx,edx, edi, 0a9e3e905h, rot21, {esi+ 2*4} MD5_RND MAGIC_G, edx,eax,ebx,ecx, edi, 0fcefa3f8h, rot22, {esi+ 7*4} MD5_RND MAGIC_G, ecx,edx,eax,ebx, edi, 0676f02d9h, rot23, {esi+12*4} MD5_RND MAGIC_G, ebx,ecx,edx,eax, edi, 08d2a4c8ah, rot24, {esi+ 5*4} MD5_RND MAGIC_H, eax,ebx,ecx,edx, edi, 0fffa3942h, rot31, {esi+ 8*4} MD5_RND MAGIC_H, edx,eax,ebx,ecx, edi, 08771f681h, rot32, {esi+11*4} MD5_RND MAGIC_H, ecx,edx,eax,ebx, edi, 06d9d6122h, rot33, {esi+14*4} MD5_RND MAGIC_H, ebx,ecx,edx,eax, edi, 0fde5380ch, rot34, {esi+ 1*4} MD5_RND MAGIC_H, eax,ebx,ecx,edx, edi, 0a4beea44h, rot31, {esi+ 4*4} MD5_RND MAGIC_H, edx,eax,ebx,ecx, edi, 04bdecfa9h, rot32, {esi+ 7*4} MD5_RND MAGIC_H, ecx,edx,eax,ebx, edi, 0f6bb4b60h, rot33, {esi+10*4} MD5_RND MAGIC_H, ebx,ecx,edx,eax, edi, 0bebfbc70h, rot34, {esi+13*4} MD5_RND MAGIC_H, eax,ebx,ecx,edx, edi, 0289b7ec6h, rot31, {esi+ 0*4} MD5_RND MAGIC_H, edx,eax,ebx,ecx, edi, 0eaa127fah, rot32, {esi+ 3*4} MD5_RND MAGIC_H, ecx,edx,eax,ebx, edi, 0d4ef3085h, rot33, {esi+ 6*4} MD5_RND MAGIC_H, ebx,ecx,edx,eax, edi, 004881d05h, rot34, {esi+ 9*4} MD5_RND MAGIC_H, eax,ebx,ecx,edx, edi, 0d9d4d039h, rot31, {esi+12*4} MD5_RND MAGIC_H, edx,eax,ebx,ecx, edi, 0e6db99e5h, rot32, {esi+15*4} MD5_RND MAGIC_H, ecx,edx,eax,ebx, edi, 01fa27cf8h, rot33, {esi+ 2*4} MD5_RND MAGIC_H, ebx,ecx,edx,eax, edi, 0c4ac5665h, rot34, {esi+ 0*4} MD5_RND MAGIC_I, eax,ebx,ecx,edx, edi, 0f4292244h, rot41, {esi+ 7*4} MD5_RND MAGIC_I, edx,eax,ebx,ecx, edi, 0432aff97h, rot42, {esi+14*4} MD5_RND MAGIC_I, ecx,edx,eax,ebx, edi, 0ab9423a7h, rot43, {esi+ 5*4} MD5_RND MAGIC_I, ebx,ecx,edx,eax, edi, 0fc93a039h, rot44, {esi+12*4} MD5_RND MAGIC_I, eax,ebx,ecx,edx, edi, 0655b59c3h, rot41, {esi+ 3*4} MD5_RND MAGIC_I, edx,eax,ebx,ecx, edi, 08f0ccc92h, rot42, {esi+10*4} MD5_RND MAGIC_I, ecx,edx,eax,ebx, edi, 0ffeff47dh, rot43, {esi+ 1*4} MD5_RND MAGIC_I, ebx,ecx,edx,eax, edi, 085845dd1h, rot44, {esi+ 8*4} MD5_RND MAGIC_I, eax,ebx,ecx,edx, edi, 06fa87e4fh, rot41, {esi+15*4} MD5_RND MAGIC_I, edx,eax,ebx,ecx, edi, 0fe2ce6e0h, rot42, {esi+ 6*4} MD5_RND MAGIC_I, ecx,edx,eax,ebx, edi, 0a3014314h, rot43, {esi+13*4} MD5_RND MAGIC_I, ebx,ecx,edx,eax, edi, 04e0811a1h, rot44, {esi+ 4*4} MD5_RND MAGIC_I, eax,ebx,ecx,edx, edi, 0f7537e82h, rot41, {esi+11*4} MD5_RND MAGIC_I, edx,eax,ebx,ecx, edi, 0bd3af235h, rot42, {esi+ 2*4} MD5_RND MAGIC_I, ecx,edx,eax,ebx, edi, 02ad7d2bbh, rot43, {esi+ 9*4} MD5_RND MAGIC_I, ebx,ecx,edx,eax, edi, 0eb86d391h, rot44, {esp} ;; ;; update digest ;; add [ebp+0*4],eax ; advance digest mov eax, dword [esp+1*sizeof(dword)] add [ebp+1*4],ebx add [ebp+2*4],ecx add [ebp+3*4],edx mov edi, ebp ; restore hash address add esi, MBS_MD5 sub eax, MBS_MD5 jg .md5_block_loop add esp,2*sizeof(dword) REST_GPR ret ENDFUNC UpdateMD5 %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpmontreductionv8as.asm000066400000000000000000000344661470420105600275450ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic (Montgomery Reduction) ; ; Content: ; cpMontRedAdc_BNU() ; ; History: ; This implementation used instead of previous one ; (see pcpmontredictw7as.asm) ; ; Extra reduction (R=A-M) has been added to perform MontReduction safe ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_V8) %include "pcpvariant.inc" %include "pcpbnu.inc" %if _USE_NN_MONTMUL_ == _NUSE %macro MULADD_wt_carry 1.nolist %xdefine %%i %1 movd xmm7,DWORD [eax] ;; pM[0] pmuludq xmm7,xmm0 ;; t = pM[0] * u movd xmm2,DWORD [edx+4*(%%i)] ;; pBuffer[i] paddq xmm7,xmm2 ;; t += pBuffer[i] movd DWORD [edx+4*(%%i)],xmm7 ;; pBuffer[i] = LO(t) psrlq xmm7,32 ;; carryLcl = HI(t) %endmacro %macro MULADD1 3.nolist %xdefine %%i %1 %xdefine %%j %2 %xdefine %%nsize %3 movd xmm1,DWORD [eax+4*%%j] ;; pM[j] pmuludq xmm1,xmm0 ;; t = pM[j] * u movd xmm2,DWORD [edx+4*(%%i+%%j)] ;; pBuffer[i+j] paddq xmm1,xmm2 ;; t +=pBuffer[i+j] paddq xmm7,xmm1 ;; +carryLcl movd DWORD [edx+4*(%%i+%%j)],xmm7 ;; pBuffer[i+j] = LO(t) psrlq xmm7,32 ;; carryLcl = HI(t) %endmacro ; INNER_LOOP1 is defined in pcpbnu.inc as well %ifmacro INNER_LOOP1 2 %unmacro INNER_LOOP1 2 %endif %macro INNER_LOOP1 2.nolist %xdefine %%i %1 %xdefine %%size %2 %assign %%j 0 movd xmm0,DWORD [edx+4*%%i] ;; pBuffer[i] pmuludq xmm0,xmm5 ;; u = (Ipp32u)( m0*pBuffer[i] ) movd xmm4,DWORD [edx+4*(%%i+%%size)] ;; w = pBuffer[i+mSize] paddq xmm4,xmm6 ;; +carryGbl %rep %%size %if %%j == 0 MULADD_wt_carry %%i %else MULADD1 %%i,%%j,%%size %endif %assign %%j %%j + 1 %endrep paddq xmm7,xmm4 ;; w+= carryLcl movd DWORD [edx+4*(%%i+%%size)],xmm7 ;; pBuffer[i+mSize] = LO(w) ; pshufw xmm6,xmm7,11111110b ;; carryGbl = HI(w) pshuflw xmm6,xmm7,11111110b ;; carryGbl = HI(w) %endmacro ; OUTER_LOOP1 is defined in pcpbnu.inc as well %ifmacro OUTER_LOOP1 1 %unmacro OUTER_LOOP1 1 %endif %macro OUTER_LOOP1 1.nolist %xdefine %%nsize %1 movd xmm5,DWORD m0 ; m0 pandn xmm6,xmm6 ; init carryGbl = 0 %assign %%i 0 %rep %%nsize INNER_LOOP1 %%i,%%nsize %assign %%i %%i + 1 %endrep psrlq xmm7,32 %endmacro %macro UNROLL8 0.nolist movd xmm1,DWORD [eax+ecx] movd xmm2,DWORD [edx+ecx] movd xmm3,DWORD [eax+ecx+4] movd xmm4,DWORD [edx+ecx+4] movd xmm5,DWORD [eax+ecx+8] movd xmm6,DWORD [edx+ecx+8] pmuludq xmm1,xmm0 paddq xmm1,xmm2 pmuludq xmm3,xmm0 paddq xmm3,xmm4 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+12] movd xmm2,DWORD [edx+ecx+12] movd DWORD [edx+ecx],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax+ecx+16] movd xmm4,DWORD [edx+ecx+16] movd DWORD [edx+ecx+4],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax+ecx+20] movd xmm6,DWORD [edx+ecx+20] movd DWORD [edx+ecx+8],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+24] movd xmm2,DWORD [edx+ecx+24] movd DWORD [edx+ecx+12],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax+ecx+28] movd xmm4,DWORD [edx+ecx+28] movd DWORD [edx+ecx+16],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd DWORD [edx+ecx+20],xmm7 psrlq xmm7,32 paddq xmm7,xmm1 movd DWORD [edx+ecx+24],xmm7 psrlq xmm7,32 paddq xmm7,xmm3 movd DWORD [edx+ecx+28],xmm7 psrlq xmm7,32 %endmacro %macro UNROLL16 0.nolist movd xmm1,DWORD [eax+ecx] movd xmm2,DWORD [edx+ecx] movd xmm3,DWORD [eax+ecx+4] movd xmm4,DWORD [edx+ecx+4] movd xmm5,DWORD [eax+ecx+8] movd xmm6,DWORD [edx+ecx+8] pmuludq xmm1,xmm0 paddq xmm1,xmm2 pmuludq xmm3,xmm0 paddq xmm3,xmm4 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+12] movd xmm2,DWORD [edx+ecx+12] movd DWORD [edx+ecx],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax+ecx+16] movd xmm4,DWORD [edx+ecx+16] movd DWORD [edx+ecx+4],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax+ecx+20] movd xmm6,DWORD [edx+ecx+20] movd DWORD [edx+ecx+8],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+24] movd xmm2,DWORD [edx+ecx+24] movd DWORD [edx+ecx+12],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax+ecx+28] movd xmm4,DWORD [edx+ecx+28] movd DWORD [edx+ecx+16],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax+ecx+32] movd xmm6,DWORD [edx+ecx+32] movd DWORD [edx+ecx+20],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+36] movd xmm2,DWORD [edx+ecx+36] movd DWORD [edx+ecx+24],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax+ecx+40] movd xmm4,DWORD [edx+ecx+40] movd DWORD [edx+ecx+28],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax+ecx+44] movd xmm6,DWORD [edx+ecx+44] movd DWORD [edx+ecx+32],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+48] movd xmm2,DWORD [edx+ecx+48] movd DWORD [edx+ecx+36],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd xmm3,DWORD [eax+ecx+52] movd xmm4,DWORD [edx+ecx+52] movd DWORD [edx+ecx+40],xmm7 psrlq xmm7,32 pmuludq xmm3,xmm0 paddq xmm3,xmm4 paddq xmm7,xmm5 movd xmm5,DWORD [eax+ecx+56] movd xmm6,DWORD [edx+ecx+56] movd DWORD [edx+ecx+44],xmm7 psrlq xmm7,32 pmuludq xmm5,xmm0 paddq xmm5,xmm6 paddq xmm7,xmm1 movd xmm1,DWORD [eax+ecx+60] movd xmm2,DWORD [edx+ecx+60] movd DWORD [edx+ecx+48],xmm7 psrlq xmm7,32 pmuludq xmm1,xmm0 paddq xmm1,xmm2 paddq xmm7,xmm3 movd DWORD [edx+ecx+52],xmm7 psrlq xmm7,32 paddq xmm7,xmm5 movd DWORD [edx+ecx+56],xmm7 psrlq xmm7,32 paddq xmm7,xmm1 movd DWORD [edx+ecx+60],xmm7 psrlq xmm7,32 %endmacro segment .text align=IPP_ALIGN_FACTOR %if (_USE_C_cpMontRedAdc_BNU_ == 0) ;************************************************************* ;* void cpMontRedAdc_BNU(Ipp32u* pR, ;* Ipp32u* pBuffer, ;* const Ipp32u* pModulo, int mSize, Ipp32u m0) ;* ;************************************************************* ;; ;; Lib = V8 ;; ;; Caller = ippsMontMul ;; IPPASM cpMontRedAdc_BNU,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to the reduction %xdefine pBuffer [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to the product %xdefine pModulo [ebp + ARG_1 + 2*sizeof(dword)] ; pointer to the modulo %xdefine mSize [ebp + ARG_1 + 3*sizeof(dword)] ; modulo size %xdefine m0 [ebp + ARG_1 + 4*sizeof(dword)] ; helper mov eax,pModulo ; modulo address mov edi,mSize ; modulo size mov edx,pBuffer ; temp product address ; ; spesial cases ; .tst_reduct4: cmp edi,4 ; special case jne .tst_reduct5 OUTER_LOOP1 4 add edx,4*4 jmp .finish .tst_reduct5: cmp edi,5 ; special case jne .tst_reduct6 OUTER_LOOP1 5 add edx,4*5 jmp .finish .tst_reduct6: cmp edi,6 ; special case jne .tst_reduct7 OUTER_LOOP1 6 add edx,4*6 jmp .finish .tst_reduct7: cmp edi,7 ; special case jne .tst_reduct8 OUTER_LOOP1 7 add edx,4*7 jmp .finish .tst_reduct8: cmp edi,8 ; special case jne .tst_reduct9 OUTER_LOOP1 8 add edx,4*8 jmp .finish .tst_reduct9: cmp edi,9 ; special case jne .tst_reduct10 OUTER_LOOP1 9 add edx,4*9 jmp .finish .tst_reduct10: cmp edi,10 ; special case jne .tst_reduct11 OUTER_LOOP1 10 add edx,4*10 jmp .finish .tst_reduct11: cmp edi,11 ; special case jne .tst_reduct12 OUTER_LOOP1 11 add edx,4*11 jmp .finish .tst_reduct12: cmp edi,12 ; special case jne .tst_reduct13 OUTER_LOOP1 12 add edx,4*12 jmp .finish .tst_reduct13: cmp edi,13 ; special case jne .tst_reduct14 OUTER_LOOP1 13 add edx,4*13 jmp .finish .tst_reduct14: cmp edi,14 ; special case jne .tst_reduct15 OUTER_LOOP1 14 add edx,4*14 jmp .finish .tst_reduct15: cmp edi,15 ; special case jne .tst_reduct16 OUTER_LOOP1 15 add edx,4*15 jmp .finish .tst_reduct16: cmp edi,16 ; special case jne .reduct_general OUTER_LOOP1 16 add edx,4*16 jmp .finish ; ; general case ; .reduct_general: sub esp,4 ; allocate slot for carryGbl pandn xmm6,xmm6 ; init carryGbl = 0 mov ebx,edi shl ebx,2 ; modulo size in bytes (outer counter) shl edi,2 .mainLoop: movd xmm0,DWORD m0 ; m0 helper movd xmm1,DWORD [edx] ; pBuffer[i] movd DWORD [esp],xmm6 ; save carryGbl pmuludq xmm0,xmm1 ; u = (Ipp32u)( m0*pBuffer[i] ) xor ecx,ecx ; inner index pandn xmm7,xmm7 ; int carryLcl = 0 ; ; case: 0 != mSize%8 ; mov esi,edi ; copy modulo size copy and esi,7*4 ; and test (inner counter) jz .testSize_8 .small_loop: movd xmm1,DWORD [eax+ecx] ; pModulo[] pmuludq xmm1,xmm0 ; t = pModulo[]*u movd xmm2,DWORD [edx+ecx] ; pBuffer[] paddq xmm1,xmm2 ; t +=pBuffer[] paddq xmm7,xmm1 ; +carryLcl movd DWORD [edx+ecx],xmm7 ; pBuffer[] = LO(t) psrlq xmm7,32 ; carryLcl = HI(t) add ecx,4 cmp ecx,esi jl .small_loop ; ; case: mSize==8 ; .testSize_8: mov esi,edi ; copy modulo size copy and esi,8*4 ; and test jz .testSize_16 UNROLL8 add ecx,8*4 ; ; case: mSize==16*n ; .testSize_16: mov esi,edi ; copy modulo size copy and esi,0FFFFFFC0h ; and test jz .next_term .unroll16_loop: UNROLL16 add ecx,16*4 cmp ecx,esi jl .unroll16_loop .next_term: movd xmm1,DWORD [edx+ecx] ; pBuffer[] paddq xmm7,xmm1 ; t = pBuffer[]+carryLcl movd xmm6,DWORD [esp] ; carryGbl paddq xmm6,xmm7 ; t +=carryGbl movd DWORD [edx+ecx],xmm6 ; pBuffer[] = LO(t) psrlq xmm6,32 ; carryGbl = HI(t) add edx,4 ; advance pBuffer sub ebx,4 ; decrease outer counter jg .mainLoop add esp,4 ; release slot for carryGbl shr edi,2 ; restore mSize ;; ;; finish ;; .finish: pxor xmm7,xmm7 ; converr carryGbl into the mask psubd xmm7,xmm6 mov esi,pR ; pointer to the result pandn xmm0,xmm0 ; borrow=0 xor ecx,ecx ; index =0 ; perform pR[] = pBuffer[] - pModulus[] .subtract_loop: movd xmm1,DWORD [edx+ecx*4]; pBuffer[] paddq xmm0,xmm1 movd xmm2,DWORD [eax+ecx*4]; pModulus[] psubq xmm0,xmm2 movd DWORD [esi+ecx*4],xmm0 pshuflw xmm0,xmm0,11111110b add ecx,1 cmp ecx,edi jl .subtract_loop pcmpeqd xmm6,xmm6 ; convert borrow into the mask pxor xmm0,xmm6 por xmm0,xmm7 ; common (carryGbl and borrow) mask pcmpeqd xmm7,xmm7 ; mask and pxor xmm7,xmm0 ; ~mask xor ecx,ecx ; index =0 ; masked copy: pR[] = (mask & pR[]) | (~mask & pBuffer[]) .masked_copy_loop: movd xmm1,DWORD [esi+ecx*4]; pR[] pand xmm1,xmm0 movd xmm2,DWORD [edx+ecx*4]; pBuffer[] pand xmm2,xmm7 por xmm1,xmm2 movd DWORD [esi+ecx*4],xmm1; pR[] add ecx,1 cmp ecx,edi jl .masked_copy_loop REST_GPR ret ENDFUNC cpMontRedAdc_BNU %endif %endif ;; _IPP_V8 %endif ;; _USE_NN_MONTMUL_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpmontreductionw7as.asm000066400000000000000000000337701470420105600275420ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Arithmetic (Montgomery Reduction) ; ; Content: ; cpMontRedAdc_BNU() ; ; History: ; This implementation used instead of previous one ; (see pcpmontredictw7as.asm) ; ; Extra reduction (R=A-M) has been added to perform MontReduction safe ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP == _IPP_W7) || (_IPP == _IPP_T7) %include "pcpvariant.inc" %include "pcpbnu.inc" %if _USE_NN_MONTMUL_ == _NUSE %macro MULADD_wt_carry 1.nolist %xdefine %%i %1 movd mm7,DWORD [eax] ;; pM[0] movd mm2,DWORD [edx+4*(%%i)] ;; pBuffer[i] pmuludq mm7,mm0 ;; t = pM[0] * u paddq mm7,mm2 ;; +pBuffer[i] movd DWORD [edx+4*(%%i)],mm7 ;; pBuffer[i] = LO(t) psrlq mm7,32 ;; carryLcl = HI(t) %endmacro %macro MULADD1 3.nolist %xdefine %%i %1 %xdefine %%j %2 %xdefine %%nsize %3 movd mm1,DWORD [eax+4*%%j] ;; pM[j] movd mm2,DWORD [edx+4*(%%i+%%j)] ;; pBuffer[i+j] pmuludq mm1,mm0 ;; t = pM[j] * u paddq mm1,mm2 ;; +pBuffer[i+j] paddq mm7,mm1 ;; +carryLcl movd DWORD [edx+4*(%%i+%%j)],mm7 ;; pBuffer[i+j] = LO(t) psrlq mm7,32 ;; carryLcl = HI(t) %endmacro ; INNER_LOOP1 is defined in pcpbnu.inc as well %ifmacro INNER_LOOP1 2 %unmacro INNER_LOOP1 2 %endif %macro INNER_LOOP1 2.nolist %xdefine %%i %1 %xdefine %%size %2 %assign %%j 0 movd mm0,DWORD [edx+4*%%i] ;; pBuffer[i] pmuludq mm0,mm5 ;; u = (Ipp32u)( m0*pBuffer[i] ) movd mm4,DWORD [edx+4*(%%i+%%size)] ;; w = pBuffer[i+mSize] paddq mm4,mm6 ;; +carryGbl %rep %%size %if %%j == 0 MULADD_wt_carry %%i %else MULADD1 %%i,%%j,%%size %endif %assign %%j %%j + 1 %endrep paddq mm7,mm4 ;; w+= carryLcl movd DWORD [edx+4*(%%i+%%size)],mm7 ;; pBuffer[i+mSize] = LO(w) pshufw mm6,mm7,11111110b ;; carryGbl = HI(w) %endmacro ; OUTER_LOOP1 is defined in pcpbnu.inc as well %ifmacro OUTER_LOOP1 1 %unmacro OUTER_LOOP1 1 %endif %macro OUTER_LOOP1 1.nolist %xdefine %%nsize %1 movd mm5,DWORD m0 ; m0 pandn mm6,mm6 ; init carryGbl = 0 %assign %%i 0 %rep %%nsize INNER_LOOP1 %%i,%%nsize %assign %%i %%i + 1 %endrep psrlq mm7,32 %endmacro %macro UNROLL8 0.nolist movd mm1,DWORD [eax+ecx] movd mm2,DWORD [edx+ecx] movd mm3,DWORD [eax+ecx+4] movd mm4,DWORD [edx+ecx+4] movd mm5,DWORD [eax+ecx+8] movd mm6,DWORD [edx+ecx+8] pmuludq mm1,mm0 paddq mm1,mm2 pmuludq mm3,mm0 paddq mm3,mm4 pmuludq mm5,mm0 paddq mm5,mm6 movd mm2,DWORD [edx+ecx+12] paddq mm7,mm1 movd mm1,DWORD [eax+ecx+12] pmuludq mm1,mm0 paddq mm1,mm2 movd mm2,DWORD [edx+ecx+24] movd DWORD [edx+ecx],mm7 psrlq mm7,32 paddq mm7,mm3 movd mm3,DWORD [eax+ecx+16] movd mm4,DWORD [edx+ecx+16] pmuludq mm3,mm0 movd DWORD [edx+ecx+4],mm7 psrlq mm7,32 paddq mm3,mm4 movd mm4,DWORD [edx+ecx+28] paddq mm7,mm5 movd mm5,DWORD [eax+ecx+20] movd mm6,DWORD [edx+ecx+20] pmuludq mm5,mm0 movd DWORD [edx+ecx+8],mm7 psrlq mm7,32 paddq mm5,mm6 paddq mm7,mm1 movd mm1,DWORD [eax+ecx+24] pmuludq mm1,mm0 movd DWORD [edx+ecx+12],mm7 psrlq mm7,32 paddq mm1,mm2 paddq mm7,mm3 movd mm3,DWORD [eax+ecx+28] pmuludq mm3,mm0 movd DWORD [edx+ecx+16],mm7 psrlq mm7,32 paddq mm3,mm4 paddq mm7,mm5 movd DWORD [edx+ecx+20],mm7 psrlq mm7,32 paddq mm7,mm1 movd DWORD [edx+ecx+24],mm7 psrlq mm7,32 paddq mm7,mm3 movd DWORD [edx+ecx+28],mm7 psrlq mm7,32 %endmacro %macro UNROLL16 0.nolist movd mm1,DWORD [eax+ecx] movd mm2,DWORD [edx+ecx] movd mm3,DWORD [eax+ecx+4] movd mm4,DWORD [edx+ecx+4] movd mm5,DWORD [eax+ecx+8] movd mm6,DWORD [edx+ecx+8] pmuludq mm1,mm0 paddq mm1,mm2 pmuludq mm3,mm0 paddq mm3,mm4 pmuludq mm5,mm0 paddq mm5,mm6 movd mm2,DWORD [edx+ecx+12] paddq mm7,mm1 movd mm1,DWORD [eax+ecx+12] pmuludq mm1,mm0 paddq mm1,mm2 movd mm2,DWORD [edx+ecx+24] movd DWORD [edx+ecx],mm7 psrlq mm7,32 paddq mm7,mm3 movd mm3,DWORD [eax+ecx+16] movd mm4,DWORD [edx+ecx+16] pmuludq mm3,mm0 movd DWORD [edx+ecx+4],mm7 psrlq mm7,32 paddq mm3,mm4 movd mm4,DWORD [edx+ecx+28] paddq mm7,mm5 movd mm5,DWORD [eax+ecx+20] movd mm6,DWORD [edx+ecx+20] pmuludq mm5,mm0 movd DWORD [edx+ecx+8],mm7 psrlq mm7,32 paddq mm5,mm6 movd mm6,DWORD [edx+ecx+32] paddq mm7,mm1 movd mm1,DWORD [eax+ecx+24] pmuludq mm1,mm0 movd DWORD [edx+ecx+12],mm7 psrlq mm7,32 paddq mm1,mm2 movd mm2,DWORD [edx+ecx+36] paddq mm7,mm3 movd mm3,DWORD [eax+ecx+28] pmuludq mm3,mm0 movd DWORD [edx+ecx+16],mm7 psrlq mm7,32 paddq mm3,mm4 movd mm4,DWORD [edx+ecx+40] paddq mm7,mm5 movd mm5,DWORD [eax+ecx+32] pmuludq mm5,mm0 movd DWORD [edx+ecx+20],mm7 psrlq mm7,32 paddq mm5,mm6 movd mm6,DWORD [edx+ecx+44] paddq mm7,mm1 movd mm1,DWORD [eax+ecx+36] pmuludq mm1,mm0 movd DWORD [edx+ecx+24],mm7 psrlq mm7,32 paddq mm1,mm2 movd mm2,DWORD [edx+ecx+48] paddq mm7,mm3 movd mm3,DWORD [eax+ecx+40] pmuludq mm3,mm0 movd DWORD [edx+ecx+28],mm7 psrlq mm7,32 paddq mm3,mm4 movd mm4,DWORD [edx+ecx+52] paddq mm7,mm5 movd mm5,DWORD [eax+ecx+44] pmuludq mm5,mm0 movd DWORD [edx+ecx+32],mm7 psrlq mm7,32 paddq mm5,mm6 movd mm6,DWORD [edx+ecx+56] paddq mm7,mm1 movd mm1,DWORD [eax+ecx+48] pmuludq mm1,mm0 movd DWORD [edx+ecx+36],mm7 psrlq mm7,32 paddq mm1,mm2 movd mm2,DWORD [edx+ecx+60] paddq mm7,mm3 movd mm3,DWORD [eax+ecx+52] pmuludq mm3,mm0 movd DWORD [edx+ecx+40],mm7 psrlq mm7,32 paddq mm3,mm4 paddq mm7,mm5 movd mm5,DWORD [eax+ecx+56] pmuludq mm5,mm0 movd DWORD [edx+ecx+44],mm7 psrlq mm7,32 paddq mm5,mm6 paddq mm7,mm1 movd mm1,DWORD [eax+ecx+60] pmuludq mm1,mm0 movd DWORD [edx+ecx+48],mm7 psrlq mm7,32 paddq mm7,mm3 movd DWORD [edx+ecx+52],mm7 psrlq mm7,32 paddq mm1,mm2 paddq mm7,mm5 movd DWORD [edx+ecx+56],mm7 psrlq mm7,32 paddq mm7,mm1 movd DWORD [edx+ecx+60],mm7 psrlq mm7,32 %endmacro segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* void cpMontRedAdc_BNU(Ipp32u* pR, ;* Ipp32u* pBuffer, ;* const Ipp32u* pModulo, int mSize, Ipp32u m0) ;* ;************************************************************* ;; ;; Lib = W7 ;; ;; Caller = ippsMontMul ;; IPPASM cpMontRedAdc_BNU,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to the reduction %xdefine pBuffer [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to the product %xdefine pModulo [ebp + ARG_1 + 2*sizeof(dword)] ; pointer to the modulo %xdefine mSize [ebp + ARG_1 + 3*sizeof(dword)] ; modulo size %xdefine m0 [ebp + ARG_1 + 4*sizeof(dword)] ; helper mov eax,pModulo ; modulo address mov edi,mSize ; modulo size mov edx,pBuffer ; temp product address ; ; spesial cases ; .tst_reduct4: cmp edi,4 ; special case jne .tst_reduct5 OUTER_LOOP1 4 add edx,4*4 jmp .finish .tst_reduct5: cmp edi,5 ; special case jne .tst_reduct6 OUTER_LOOP1 5 add edx,4*5 jmp .finish .tst_reduct6: cmp edi,6 ; special case jne .tst_reduct7 OUTER_LOOP1 6 add edx,4*6 jmp .finish .tst_reduct7: cmp edi,7 ; special case jne .tst_reduct8 OUTER_LOOP1 7 add edx,4*7 jmp .finish .tst_reduct8: cmp edi,8 ; special case jne .tst_reduct9 OUTER_LOOP1 8 add edx,4*8 jmp .finish .tst_reduct9: cmp edi,9 ; special case jne .tst_reduct10 OUTER_LOOP1 9 add edx,4*9 jmp .finish .tst_reduct10: cmp edi,10 ; special case jne .tst_reduct11 OUTER_LOOP1 10 add edx,4*10 jmp .finish .tst_reduct11: cmp edi,11 ; special case jne .tst_reduct12 OUTER_LOOP1 11 add edx,4*11 jmp .finish .tst_reduct12: cmp edi,12 ; special case jne .tst_reduct13 OUTER_LOOP1 12 add edx,4*12 jmp .finish .tst_reduct13: cmp edi,13 ; special case jne .tst_reduct14 OUTER_LOOP1 13 add edx,4*13 jmp .finish .tst_reduct14: cmp edi,14 ; special case jne .tst_reduct15 OUTER_LOOP1 14 add edx,4*14 jmp .finish .tst_reduct15: cmp edi,15 ; special case jne .tst_reduct16 OUTER_LOOP1 15 add edx,4*15 jmp .finish .tst_reduct16: cmp edi,16 ; special case jne .reduct_general OUTER_LOOP1 16 add edx,4*16 jmp .finish ; ; general case ; .reduct_general: sub esp,4 ; allocate slot for carryGbl pandn mm6,mm6 ; init carryGbl = 0 mov ebx,edi shl ebx,2 ; modulo size in bytes (outer counter) shl edi,2 .mainLoop: movd mm0,DWORD m0 ; m0 helper movd mm1,DWORD [edx] ; pBuffer[i] movd DWORD [esp],mm6 ; save carryGbl pmuludq mm0,mm1 ; u = (Ipp32u)( m0*pBuffer[i] ) xor ecx,ecx ; inner index pandn mm7,mm7 ; int carryLcl = 0 ; ; case: 0 != mSize%8 ; mov esi,edi ; copy modulo size copy and esi,7*4 ; and test (inner counter) jz .testSize_8 .small_loop: movd mm1,DWORD [eax+ecx] ; pModulo[] movd mm2,DWORD [edx+ecx] ; pBuffer[] pmuludq mm1,mm0 ; t = pModulo[]*u paddq mm2,mm1 ; +pBuffer[] paddq mm7,mm2 ; +carryLcl movd DWORD [edx+ecx],mm7 ; pBuffer[] = LO(t) psrlq mm7,32 ; carryLcl = HI(t) add ecx,4 cmp ecx,esi jl .small_loop ; ; case: mSize==8 ; .testSize_8: mov esi,edi ; copy modulo size copy and esi,8*4 ; and test jz .testSize_16 UNROLL8 add ecx,8*4 ; ; case: mSize==16*n ; .testSize_16: mov esi,edi ; copy modulo size copy and esi,0FFFFFFC0h ; and test jz .next_term .unroll16_loop: UNROLL16 add ecx,16*4 cmp ecx,esi jl .unroll16_loop .next_term: movd mm1,DWORD [edx+ecx] ; pBuffer[] movd mm6,DWORD [esp] ; carryGbl paddq mm7,mm1 ; t = pBuffer[]+carryLcl paddq mm6,mm7 ; +carryGbl movd DWORD [edx+ecx],mm6 ; pBuffer[] = LO(t) psrlq mm6,32 ; carryGbl = HI(t) add edx,4 ; advance pBuffer sub ebx,4 ; decrease outer counter jg .mainLoop add esp,4 ; release slot for carryGbl shr edi,2 ; restore mSize ;; ;; finish ;; .finish: pxor mm7,mm7 ; converr carryGbl into the mask psubd mm7,mm6 mov esi,pR ; pointer to the result mov ebx,edi ; restore mSize pandn mm0,mm0 ; borrow=0 xor ecx,ecx ; index =0 ; perform pR[] = pBuffer[] - pModulus[] .subtract_loop: movd mm1,DWORD [edx+ecx*4]; pBuffer[] movd mm2,DWORD [eax+ecx*4]; pModulus[] psubq mm1,mm2 paddq mm1,mm0 movd DWORD [esi+ecx*4],mm1 pshufw mm0,mm1,11111110b add ecx,1 cmp ecx,edi jl .subtract_loop pcmpeqd mm6,mm6 ; convert borrow into the mask pxor mm0,mm6 por mm0,mm7 ; common (carryGbl and borrow) mask pcmpeqd mm7,mm7 ; mask and pxor mm7,mm0 ; ~mask xor ecx,ecx ; index =0 ; masked copy: pR[] = (mask & pR[]) | (~mask & pBuffer[]) .masked_copy_loop: movd mm1,DWORD [esi+ecx*4]; pR[] pand mm1,mm0 movd mm2,DWORD [edx+ecx*4]; pBuffer[] pand mm2,mm7 por mm1,mm2 movd DWORD [esi+ecx*4],mm1; pR[] add ecx,1 cmp ecx,edi jl .masked_copy_loop emms REST_GPR ret ENDFUNC cpMontRedAdc_BNU %endif ;; _IPP_W7 || _IPP_T7 %endif ;; _USE_NN_MONTMUL_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpp192r1arith_mont_slm.asm000066400000000000000000000553601470420105600277430ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; P192r1 basic arithmetic function ; ; Content: ; p192r1_add ; p192r1_sub ; p192r1_neg ; p192r1_div_by_2 ; p192r1_mul_mont_slm ; p192r1_sqr_mont_slm ; p192r1_mred ; p192r1_select_ap_w7 ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR ;; ;; some p384r1 constants ;; p192r1_data: _prime192r1 DD 0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFEh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh %assign LEN192 (192/32) ; dword's length of operands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Ipp32u add_192(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = carry = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM add_192,PRIVATE ; r = a+b mov eax, dword [esi] add eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] adc eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] adc eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] adc eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] adc eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] adc eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 adc eax, 0 ret ENDFUNC add_192 ;; ;; Ipp32u sub_192(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = borrow = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM sub_192,PRIVATE ; r = a-b mov eax, dword [esi] sub eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] sbb eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] sbb eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] sbb eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] sbb eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] sbb eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 adc eax, 0 ret ENDFUNC sub_192 ;; ;; Ipp32u shl_192(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shl_192,PRIVATE mov eax, dword [esi+(LEN192-1)*sizeof(dword)] ; r = a<<1 movq xmm2, qword [esi+sizeof(oword)] movdqu xmm1, oword [esi] movdqa xmm3, xmm2 palignr xmm3, xmm1, sizeof(qword) psllq xmm2, 1 psrlq xmm3, 63 por xmm2, xmm3 movq qword [edi+sizeof(oword)], xmm2 movdqa xmm3, xmm1 pslldq xmm3, sizeof(qword) psllq xmm1, 1 psrlq xmm3, 63 por xmm1, xmm3 movdqu oword [edi], xmm1 shr eax, 31 ret ENDFUNC shl_192 ;; ;; void shr_192(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; eax = ext ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shr_192,PRIVATE ; r = a>>1 movdqu xmm2, oword [esi] movq xmm1, qword [esi+sizeof(oword)] movdqa xmm3, xmm1 palignr xmm3, xmm2, sizeof(qword) psrlq xmm2, 1 psllq xmm3, 63 por xmm2, xmm3 movdqu oword [edi], xmm2 movdqa xmm3, xmm0 psrlq xmm1, 1 psllq xmm3, 63 por xmm1, xmm3 movq qword [edi+sizeof(oword)], xmm1 ret ENDFUNC shr_192 ;; ;; void cpy_192(Ipp32u* r, const Ipp32u* a) ;; %macro cpy_192 2.nolist %xdefine %%pdst %1 %xdefine %%psrc %2 movdqu xmm0, oword [%%psrc] movq xmm1, qword [%%psrc+sizeof(oword)] movdqu oword [%%pdst], xmm0 movq qword [%%pdst+sizeof(oword)], xmm1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_add(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_add,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN192] %assign _sp_ _buf_+(LEN192)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM add_192 ; R = A+B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p192r1_data ; modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM sub_192 ; T = R-modulus lea esi,[esp+_buf_] mov edi, pR sub edx, eax ; R = T<0? R : T cmovnz esi, edi cpy_192 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p192r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_sub(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_sub,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN192] %assign _sp_ _buf_+(LEN192)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM sub_192 ; R = A-B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p192r1_data ; modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM add_192 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_192 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p192r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_neg(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_neg,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN192] %assign _sp_ _buf_+(LEN192)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; outpur pR mov esi, pA ; input pA ; r = 0-a mov eax, 0 sub eax, dword [esi] mov dword [edi], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax sbb edx,edx lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p192r1_data ; modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM add_192 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_192 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p192r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_mul_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_mul_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN192] %assign _sp_ _buf_+(LEN192)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; pA CALL_IPPASM shl_192 ; T = A<<1 mov edx, eax mov esi, edi ; T mov edi, pR ; R LD_ADDR ebx, p192r1_data ; modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM sub_192 ; R = T-modulus sub edx, eax ; R = R<0? T : R cmovz esi, edi cpy_192 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p192r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_mul_by_3(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_mul_by_3,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _bufT_ 0 ; T buffer[LEN192] %assign _bufU_ _bufT_+(LEN192)*sizeof(dword) ; U buffer[LEN192] %assign _mod_ _bufU_+(LEN192)*sizeof(dword) ; modulus address [1] %assign _sp_ _mod_+sizeof(dword) ; esp [1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp LD_ADDR eax, p192r1_data ; srore modulus address lea eax, [eax+(_prime192r1-p192r1_data)] mov dword [esp+_mod_], eax lea edi, [esp+_bufT_] ; T mov esi, pA ; A CALL_IPPASM shl_192 ; T = A<<1 mov edx, eax mov esi, edi ; T lea edi, [esp+_bufU_] ; U mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_192 ; U = T-modulus sub edx, eax ; T = U<0? T : U cmovz esi, edi cpy_192 edi, esi mov esi, edi mov ebx, pA CALL_IPPASM add_192 ; T +=A mov edx, eax mov edi, pR ; R mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_192 ; R = T-modulus sub edx, eax ; R = T<0? R : T cmovz esi, edi cpy_192 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p192r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_div_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_div_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN192] %assign _sp_ _buf_+(LEN192)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; A LD_ADDR ebx, p192r1_data ; modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM add_192 ; R = A+modulus mov edx, 0 mov ecx, dword [esi] ; shifted_data = (a[0]&1)? T : A and ecx, 1 cmovnz esi, edi cmovz eax, edx movd xmm0, eax mov edi, pR CALL_IPPASM shr_192 mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p192r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_mul_mont_slm(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_mul_mont_slm,PUBLIC USES_GPR ebp,ebx,esi,edi %xdefine pR [eax + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [eax + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [eax + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 %assign _rp_ _buf_+(LEN192+1)*sizeof(dword) ; pR %assign _ap_ _rp_+sizeof(dword) ; pA %assign _bp_ _ap_+sizeof(dword) ; pB %assign _sp_ _bp_+sizeof(dword) ; esp storage %assign _ssize_ _sp_+sizeof(dword) ; size allocated stack mov eax, esp ; save esp sub esp, _ssize_ ; allocate stack and esp, -16 ; provide 16-byte stack alignment mov dword [esp+_sp_], eax ; store original esp ; clear buffer pxor mm0, mm0 movq [esp+_buf_], mm0 movq [esp+_buf_+sizeof(qword)], mm0 movq [esp+_buf_+sizeof(qword)*2], mm0 movq [esp+_buf_+sizeof(qword)*3], mm0 ; store parameters into the stack ; note: eax here stores an original esp, so it can be used to reach function parameters mov edi, pR mov esi, pA mov ebp, pB mov dword [esp+_rp_], edi mov dword [esp+_ap_], esi mov dword [esp+_bp_], ebp mov edi, LEN192 movd mm1, dword [esi+sizeof(dword)] ; pre load a[1], a[2] movd mm2, dword [esi+sizeof(dword)*2] align IPP_ALIGN_FACTOR .mmul_loop: ; ; i-st pass ; modulus = 2^192 -2^64 -1 ; [6] [2] [0] ; m0 = 1 ; movd mm7, edi ; save pass counter mov edx, dword [ebp] ; b = b[i] mov eax, dword [esi] ; a[0] movd mm0, edx add ebp, sizeof(dword) mov dword [esp+_bp_], ebp pmuludq mm1, mm0 ; a[1]*b[i] mul edx ; (E:u) = (edx:eax) = a[0]*b[i]+buf[0] add eax, dword [esp+_buf_] adc edx, 0 pmuludq mm2, mm0 ; a[2]*b[i] ; multiplication round 1 - round 2 movd ecx, mm1 ; p = a[1]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*1] movd mm1, dword [esi+sizeof(dword)*3] adc edx, 0 movd ebx, mm2 ; p = a[2]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*2] movd mm2, dword [esi+sizeof(dword)*4] movd mm3, dword [esi+sizeof(dword)*5] adc edx, 0 pmuludq mm1, mm0 ; a[3]*b[i] pmuludq mm2, mm0 ; a[4]*b[i] pmuludq mm3, mm0 ; a[5]*b[i] ;;; and reduction ;;; mov dword [esp+_buf_+sizeof(dword)*0], ecx ; +0 sub ebx, eax ; -u0 mov edi, 0 mov dword [esp+_buf_+sizeof(dword)*1], ebx adc edi, 0 ; ssave bf ; multiplication round 3 - round 5 movd ecx, mm1 ; p = a[3]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*3] adc edx, 0 movd ebx, mm2 ; p = a[4]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*4] adc edx, 0 movd ebp, mm3 ; p = a[5]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*5] adc edx, 0 ;;; and reduction ;;; sub ecx, edi ; -cb mov dword [esp+_buf_+sizeof(dword)*2], ecx sbb ebx, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*3], ebx sbb ebp, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*4], ebp ;;; last multiplication round 6 movd edi, mm7 ; restore pass counter sbb eax, 0 ; u0 -bf mov ebx, 0 add edx, dword [esp+_buf_+sizeof(dword)*6] adc ebx, 0 add edx, eax adc ebx, 0 mov dword [esp+_buf_+sizeof(dword)*5], edx mov dword [esp+_buf_+sizeof(dword)*6], ebx sub edi, 1 movd mm1, dword [esi+sizeof(dword)] ; speculative load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] jz .exit_mmul_loop mov ebp, dword [esp+_bp_] ; restore pB jmp .mmul_loop .exit_mmul_loop: emms ; final reduction mov edi, [esp+_rp_] ; result lea esi, [esp+_buf_] ; buffer LD_ADDR ebx, p192r1_data ; modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM sub_192 mov edx, dword [esp+_buf_+sizeof(dword)*LEN192] sub edx, eax ; copy cmovz esi, edi cpy_192 edi, esi mov esp, [esp+_sp_] ; release stack REST_GPR ret ENDFUNC p192r1_mul_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_sqr_mont_slm(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p192r1_sqr_mont_slm,PUBLIC USES_GPR esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source A address ;; use p192r1_mul_mont_slm to compute sqr mov esi, pA mov edi, pR push esi push esi push edi CALL_IPPASM p192r1_mul_mont_slm,PUBLIC add esp, sizeof(dword)*3 REST_GPR ret ENDFUNC p192r1_sqr_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p192r1_mred(Ipp32u* r, Ipp32u* prod) ;; ; modulus = 2^192 -2^64 -1 ; [6] [2] [0] ; m0 = 1 ; align IPP_ALIGN_FACTOR IPPASM p192r1_mred,PUBLIC USES_GPR ebx,esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; reduction address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source product address ; get parameters: mov esi, pA mov ecx, LEN192 xor edx, edx align IPP_ALIGN_FACTOR .mred_loop: mov eax, dword [esi] mov ebx, 0 mov dword [esi], ebx mov ebx, dword [esi+sizeof(dword)] mov dword [esi+sizeof(dword)], ebx mov ebx, dword [esi+sizeof(dword)*2] sub ebx, eax mov dword [esi+sizeof(dword)*2], ebx mov ebx, dword [esi+sizeof(dword)*3] sbb ebx, 0 mov dword [esi+sizeof(dword)*3], ebx mov ebx, dword [esi+sizeof(dword)*4] sbb ebx, 0 mov dword [esi+sizeof(dword)*4], ebx mov ebx, dword [esi+sizeof(dword)*5] sbb ebx, 0 mov dword [esi+sizeof(dword)*5], ebx mov ebx, dword [esi+sizeof(dword)*6] sbb eax, 0 add eax, edx mov edx, 0 adc edx, 0 add ebx, eax mov dword [esi+sizeof(dword)*6], ebx adc edx, 0 lea esi, [esi+sizeof(dword)] sub ecx, 1 jnz .mred_loop ; final reduction mov edi, pR ; result LD_ADDR ebx, p192r1_data ; address of the modulus lea ebx, [ebx+(_prime192r1-p192r1_data)] CALL_IPPASM sub_192 sub edx, eax cmovz esi, edi cpy_192 edi, esi REST_GPR ret ENDFUNC p192r1_mred %endif ;; _IPP >= _IPP_P8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpp224r1arith_mont_slm.asm000066400000000000000000000612031470420105600277300ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; P224r1 basic arithmetic function ; ; Content: ; p224r1_add ; p224r1_sub ; p224r1_neg ; p224r1_div_by_2 ; p224r1_mul_mont_slm ; p224r1_sqr_mont_slm ; p224r1_mred ; p224r1_mont_back ; p224r1_select_ap_w7 ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR ;; ;; some p224r1 constants ;; p224r1_data: _prime224r1 DD 000000001h,000000000h,000000000h,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh %assign LEN224 (224/32) ; dword's length of operands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Ipp32u add_224(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = carry = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM add_224,PRIVATE ; r = a+b mov eax, dword [esi] add eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] adc eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] adc eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] adc eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] adc eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] adc eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] adc eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, 0 adc eax, 0 ret ENDFUNC add_224 ;; ;; Ipp32u sub_224(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = borrow = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM sub_224,PRIVATE ; r = a-b mov eax, dword [esi] sub eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] sbb eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] sbb eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] sbb eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] sbb eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] sbb eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] sbb eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, 0 adc eax, 0 ret ENDFUNC sub_224 ;; ;; Ipp32u shl_224(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shl_224,PRIVATE ; r = a<<1 movdqu xmm0, oword [esi] movdqu xmm1, oword [esi+LEN224*sizeof(dword)-sizeof(oword)] mov eax, dword [esi+(LEN224-1)*sizeof(dword)] psrldq xmm1, sizeof(dword) movdqa xmm2, xmm0 psllq xmm0, 1 psrlq xmm2, 63 movdqa xmm3, xmm1 psllq xmm1, 1 psrlq xmm3, 63 palignr xmm3, xmm2, sizeof(qword) pslldq xmm2, sizeof(qword) por xmm1, xmm3 por xmm0, xmm2 movdqu oword [edi], xmm0 movq qword [edi+sizeof(oword)], xmm1 psrldq xmm1, sizeof(qword) movd dword [edi+sizeof(oword)+sizeof(qword)], xmm1 shr eax, 31 ret ENDFUNC shl_224 ;; ;; void shr_224(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; eax = ext ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shr_224,PRIVATE ; r = a>>1 movdqu xmm0, oword [esi] movdqu xmm2, oword [esi+LEN224*sizeof(dword)-sizeof(oword)] movd xmm1, eax palignr xmm1, xmm2, sizeof(dword) movdqa xmm2, xmm0 psrlq xmm0, 1 psllq xmm2, 63 movdqa xmm3, xmm1 psrlq xmm1, 1 psllq xmm3, 63 movdqa xmm4, xmm3 palignr xmm3, xmm2, sizeof(qword) psrldq xmm4, sizeof(qword) por xmm0, xmm3 por xmm1, xmm4 movdqu oword [edi], xmm0 movq qword [edi+sizeof(oword)], xmm1 psrldq xmm1, sizeof(qword) movd dword [edi+sizeof(oword)+sizeof(qword)], xmm1 ret ENDFUNC shr_224 ;; ;; void cpy_224(Ipp32u* r, const Ipp32u* a) ;; %macro cpy_224 2.nolist %xdefine %%pdst %1 %xdefine %%psrc %2 movdqu xmm0, oword [%%psrc] movq xmm1, qword [%%psrc+sizeof(oword)] movd xmm2, dword [%%psrc+sizeof(oword)+sizeof(qword)] movdqu oword [%%pdst], xmm0 movq qword [%%pdst+sizeof(oword)], xmm1 movd dword [%%pdst+sizeof(oword)+sizeof(qword)], xmm2 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_add(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_add,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN224] %assign _sp_ _buf_+(LEN224)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM add_224 ; R = A+B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p224r1_data ; modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM sub_224 ; T = R-modulus lea esi,[esp+_buf_] mov edi, pR sub edx, eax ; R = T<0? R : T cmovnz esi, edi cpy_224 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p224r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_sub(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_sub,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN224] %assign _sp_ _buf_+(LEN224)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM sub_224 ; R = A-B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p224r1_data ; modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM add_224 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_224 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p224r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_neg(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_neg,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN224] %assign _sp_ _buf_+(LEN224)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; outpur pR mov esi, pA ; input pA ; r = 0-a mov eax, 0 sub eax, dword [esi] mov dword [edi], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax sbb edx,edx lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p224r1_data ; modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM add_224 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_224 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p224r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_mul_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_mul_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN224] %assign _sp_ _buf_+(LEN224)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; pA CALL_IPPASM shl_224 ; T = A<<1 mov edx, eax mov esi, edi ; T mov edi, pR ; R LD_ADDR ebx, p224r1_data ; modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM sub_224 ; R = T-modulus sub edx, eax ; R = R<0? T : R cmovz esi, edi cpy_224 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p224r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_mul_by_3(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_mul_by_3,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _bufT_ 0 ; T buffer[LEN224] %assign _bufU_ _bufT_+(LEN224)*sizeof(dword) ; U buffer[LEN224] %assign _mod_ _bufU_+(LEN224)*sizeof(dword) ; modulus address [1] %assign _sp_ _mod_+sizeof(dword) ; esp [1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp LD_ADDR eax, p224r1_data ; srore modulus address lea eax, [eax+(_prime224r1-p224r1_data)] mov dword [esp+_mod_], eax lea edi, [esp+_bufT_] ; T mov esi, pA ; A CALL_IPPASM shl_224 ; T = A<<1 mov edx, eax mov esi, edi ; T lea edi, [esp+_bufU_] ; U mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_224 ; U = T-modulus sub edx, eax ; T = U<0? T : U cmovz esi, edi cpy_224 edi, esi mov esi, edi mov ebx, pA CALL_IPPASM add_224 ; T +=A mov edx, eax mov edi, pR ; R mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_224 ; R = T-modulus sub edx, eax ; R = T<0? R : T cmovz esi, edi cpy_224 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p224r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_div_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_div_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN224] %assign _sp_ _buf_+(LEN224)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; A LD_ADDR ebx, p224r1_data ; modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM add_224 ; R = A+modulus mov edx, 0 mov ecx, dword [esi] ; shifted_data = (a[0]&1)? T : A and ecx, 1 cmovnz esi, edi cmovz eax, edx mov edi, pR CALL_IPPASM shr_224 mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p224r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_mul_mont_slm(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_mul_mont_slm,PUBLIC USES_GPR ebp,ebx,esi,edi %xdefine pR [eax + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [eax + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [eax + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 %assign _rp_ _buf_+(LEN224+1)*sizeof(dword) ; pR %assign _ap_ _rp_ +sizeof(dword) ; pA %assign _bp_ _ap_+sizeof(dword) ; pB %assign _sp_ _bp_+sizeof(dword) ; esp storage %assign _ssize_ _sp_+sizeof(dword) ; size allocated stack mov eax, esp ; save esp sub esp, _ssize_ ; allocate stack and esp, -16 ; provide 16-byte stack alignment mov dword [esp+_sp_], eax ; store original esp ; clear buffer pxor mm0, mm0 movq [esp+_buf_], mm0 movq [esp+_buf_+sizeof(qword)], mm0 movq [esp+_buf_+sizeof(qword)*2], mm0 movq [esp+_buf_+sizeof(qword)*3], mm0 ; store parameters into the stack ; note: eax here stores an original esp, so it can be used to reach function parameters mov edi, pR mov esi, pA mov ebp, pB mov dword [esp+_rp_], edi mov dword [esp+_ap_], esi mov dword [esp+_bp_], ebp mov edi, LEN224 movd mm1, dword [esi+sizeof(dword)] ; pre load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] align IPP_ALIGN_FACTOR .mmul_loop: ; ; i-st pass ; modulus = 2^224 -2^96 +1 ; [7] [3] [0] ; m0 = 1 ; movd mm7, edi ; save pass counter mov edx, dword [ebp] ; b = b[i] mov eax, dword [esi] ; a[0] movd mm0, edx add ebp, sizeof(dword) mov dword [esp+_bp_], ebp pmuludq mm1, mm0 ; a[1]*b[i] pmuludq mm2, mm0 ; a[2]*b[i] mul edx ; (E:u) = (edx:eax) = a[0]*b[i]+buf[0] add eax, dword [esp+_buf_] adc edx, 0 pmuludq mm3, mm0 ; a[3]*b[i] pmuludq mm4, mm0 ; a[4]*b[i] ; multiplication round 1 - round 4 movd ecx, mm1 ; p = a[1]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*1] movd mm1, dword [esi+sizeof(dword)*5] adc edx, 0 movd ebx, mm2 ; p = a[2]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*2] movd mm2, dword [esi+sizeof(dword)*6] adc edx, 0 pmuludq mm1, mm0 ; a[5]*b[i] pmuludq mm2, mm0 ; a[6]*b[i] movd ebp, mm3 ; p = a[3]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*3] adc edx, 0 movd edi, mm4 ; p = a[4]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*4] adc edx, 0 ;;; and reduction ;;; neg eax ; u0 adc ecx, 0 ; +cf mov dword [esp+_buf_+sizeof(dword)*0], ecx adc ebx, 0 ; +cf mov dword [esp+_buf_+sizeof(dword)*1], ebx mov ecx, eax ; save u0 sbb eax, 0 ; u0-cf sub ebp, eax ; -u0+cf mov dword [esp+_buf_+sizeof(dword)*2], ebp mov eax, ecx ; restore u0 mov ebp, 0 sbb edi, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*3], edi adc ebp, 0 ; save bf ; multiplication round 5 - round 6 movd ecx, mm1 ; p = a[5]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*5] adc edx, 0 movd ebx, mm2 ; p = a[6]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*6] adc edx, 0 ;;; and reduction ;;; sub ecx, ebp ; -bf mov dword [esp+_buf_+sizeof(dword)*4], ecx sbb ebx, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*5], ebx ; last multiplication round 7 movd edi, mm7 ; restore pass counter sbb eax, 0 ; u-bf mov ebx, 0 add edx, dword [esp+_buf_+sizeof(dword)*7] adc ebx, 0 add edx, eax mov dword [esp+_buf_+sizeof(dword)*6], edx adc ebx, 0 mov dword [esp+_buf_+sizeof(dword)*7], ebx sub edi, 1 movd mm1, dword [esi+sizeof(dword)] ; speculative load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] jz .exit_mmul_loop mov ebp, dword [esp+_bp_] ; restore pB jmp .mmul_loop .exit_mmul_loop: emms ; final reduction mov edi, [esp+_rp_] ; result lea esi, [esp+_buf_] ; buffer LD_ADDR ebx, p224r1_data ; modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM sub_224 mov edx, dword [esp+_buf_+LEN224*sizeof(dword)] sub edx, eax ; copy cmovz esi, edi cpy_224 edi, esi mov esp, [esp+_sp_] ; release stack REST_GPR ret ENDFUNC p224r1_mul_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_sqr_mont_slm(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p224r1_sqr_mont_slm,PUBLIC USES_GPR esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source A address ;; use p224r1_mul_mont_slm to compute sqr mov esi, pA mov edi, pR push esi push esi push edi CALL_IPPASM p224r1_mul_mont_slm,PUBLIC add esp, sizeof(dword)*3 REST_GPR ret ENDFUNC p224r1_sqr_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p224r1_mred(Ipp32u* r, Ipp32u* prod) ;; ; modulus = 2^224 -2^96 +1 ; [7] [3] [0] ; m0 = -1 ; align IPP_ALIGN_FACTOR IPPASM p224r1_mred,PUBLIC USES_GPR ebx,esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; reduction address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source product address ; get parameters: mov esi, pA mov ecx, LEN224 xor edx, edx align IPP_ALIGN_FACTOR .mred_loop: mov eax, dword [esi] neg eax mov ebx, 0 mov dword [esi], ebx mov ebx, dword [esi+sizeof(dword)] adc ebx, 0 mov dword [esi+sizeof(dword)], ebx mov ebx, dword [esi+sizeof(dword)*2] adc ebx, 0 mov dword [esi+sizeof(dword)*2], ebx push eax mov ebx, dword [esi+sizeof(dword)*3] sbb eax, 0 sub ebx, eax mov dword [esi+sizeof(dword)*3], ebx pop eax mov ebx, dword [esi+sizeof(dword)*4] sbb ebx, 0 mov dword [esi+sizeof(dword)*4], ebx mov ebx, dword [esi+sizeof(dword)*5] sbb ebx, 0 mov dword [esi+sizeof(dword)*5], ebx mov ebx, dword [esi+sizeof(dword)*6] sbb ebx, 0 mov dword [esi+sizeof(dword)*6], ebx mov ebx, dword [esi+sizeof(dword)*7] sbb eax, 0 add eax, edx mov edx, 0 adc edx, 0 add ebx, eax mov dword [esi+sizeof(dword)*7], ebx adc edx, 0 lea esi, [esi+sizeof(dword)] sub ecx, 1 jnz .mred_loop ; final reduction mov edi, pR ; result LD_ADDR ebx, p224r1_data ; address of the modulus lea ebx, [ebx+(_prime224r1-p224r1_data)] CALL_IPPASM sub_224 sub edx, eax cmovz esi, edi cpy_224 edi, esi REST_GPR ret ENDFUNC p224r1_mred %endif ;; _IPP >= _IPP_P8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpp256r1arith_mont_slm.asm000066400000000000000000000614651470420105600277470ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; P256r1 basic arithmetic function ; ; Content: ; p256r1_add ; p256r1_sub ; p256r1_neg ; p256r1_div_by_2 ; p256r1_mul_mont_slm ; p256r1_sqr_mont_slm ; p256r1_mred ; p256r1_mont_back ; p256r1_select_ap_w7 ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR ;; ;; some p256r1 constants ;; p256r1_data: _prime256r1 DD 0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,000000000h,000000000h,000000000h,000000001h, 0FFFFFFFFh %assign LEN256 (256/32) ; dword's length of operands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Ipp32u add_256(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = carry = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM add_256,PRIVATE ; r = a+b mov eax, dword [esi] add eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] adc eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] adc eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] adc eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] adc eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] adc eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] adc eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] adc eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, 0 adc eax, 0 ret ENDFUNC add_256 ;; ;; Ipp32u sub_256(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = borrow = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM sub_256,PRIVATE ; r = a-b mov eax, dword [esi] sub eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] sbb eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] sbb eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] sbb eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] sbb eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] sbb eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] sbb eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] sbb eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, 0 adc eax, 0 ret ENDFUNC sub_256 ;; ;; Ipp32u shl_256(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shl_256,PRIVATE ; r = a<<1 movdqu xmm0, oword [esi] movdqu xmm1, oword [esi+sizeof(oword)] mov eax, dword [esi+(LEN256-1)*sizeof(dword)] movdqa xmm2, xmm0 psllq xmm0, 1 psrlq xmm2, 63 movdqa xmm3, xmm1 psllq xmm1, 1 psrlq xmm3, 63 palignr xmm3, xmm2, sizeof(qword) pslldq xmm2, sizeof(qword) por xmm1, xmm3 por xmm0, xmm2 movdqu oword [edi], xmm0 movdqu oword [edi+sizeof(oword)], xmm1 shr eax, 31 ret ENDFUNC shl_256 ;; ;; void shr_256(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; eax = ext ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shr_256,PRIVATE ; r = a>>1 movd xmm4, eax movdqu xmm0, oword [esi] movdqu xmm1, oword [esi+sizeof(oword)] psllq xmm4, 63 movdqa xmm2, xmm0 psrlq xmm0, 1 psllq xmm2, 63 movdqa xmm3, xmm1 psrlq xmm1, 1 psllq xmm3, 63 palignr xmm4, xmm3, sizeof(qword) palignr xmm3, xmm2, sizeof(qword) por xmm1, xmm4 por xmm0, xmm3 movdqu oword [edi], xmm0 movdqu oword [edi+sizeof(oword)], xmm1 ret ENDFUNC shr_256 ;; ;; void cpy_256(Ipp32u* r, const Ipp32u* a) ;; %macro cpy_256 2.nolist %xdefine %%pdst %1 %xdefine %%psrc %2 movdqu xmm0, oword [%%psrc] movdqu xmm1, oword [%%psrc+sizeof(oword)] movdqu oword [%%pdst], xmm0 movdqu oword [%%pdst+sizeof(oword)], xmm1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_add(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_add,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN256] %assign _sp_ _buf_+(LEN256)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM add_256 ; R = A+B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p256r1_data ; modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM sub_256 ; T = R-modulus lea esi,[esp+_buf_] mov edi, pR sub edx, eax ; R = T<0? R : T cmovnz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p256r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_sub(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_sub,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN256] %assign _sp_ _buf_+(LEN256)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM sub_256 ; R = A-B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p256r1_data ; modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM add_256 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p256r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_neg(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_neg,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN256] %assign _sp_ _buf_+(LEN256)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; outpur pR mov esi, pA ; input pA ; r = 0-a mov eax, 0 sub eax, dword [esi] mov dword [edi], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax sbb edx,edx lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p256r1_data ; modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM add_256 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p256r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_mul_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_mul_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN256] %assign _sp_ _buf_+(LEN256)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; pA CALL_IPPASM shl_256 ; T = A<<1 mov edx, eax mov esi, edi ; T mov edi, pR ; R LD_ADDR ebx, p256r1_data ; modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM sub_256 ; R = T-modulus sub edx, eax ; R = R<0? T : R cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p256r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_mul_by_3(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_mul_by_3,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _bufT_ 0 ; T buffer[LEN256] %assign _bufU_ _bufT_+(LEN256)*sizeof(dword) ; U buffer[LEN256] %assign _mod_ _bufU_+(LEN256)*sizeof(dword) ; modulus address [1] %assign _sp_ _mod_+sizeof(dword) ; esp [1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp LD_ADDR eax, p256r1_data ; srore modulus address lea eax, [eax+(_prime256r1-p256r1_data)] mov dword [esp+_mod_], eax lea edi, [esp+_bufT_] ; T mov esi, pA ; A CALL_IPPASM shl_256 ; T = A<<1 mov edx, eax mov esi, edi ; T lea edi, [esp+_bufU_] ; U mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_256 ; U = T-modulus sub edx, eax ; T = U<0? T : U cmovz esi, edi cpy_256 edi, esi mov esi, edi mov ebx, pA CALL_IPPASM add_256 ; T +=A mov edx, eax mov edi, pR ; R mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_256 ; R = T-modulus sub edx, eax ; R = T<0? R : T cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p256r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_div_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_div_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN256] %assign _sp_ _buf_+(LEN256)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; A LD_ADDR ebx, p256r1_data ; modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM add_256 ; R = A+modulus mov edx, 0 mov ecx, dword [esi] ; shifted_data = (a[0]&1)? T : A and ecx, 1 cmovnz esi, edi cmovz eax, edx mov edi, pR CALL_IPPASM shr_256 mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p256r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_mul_mont_slm(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_mul_mont_slm,PUBLIC USES_GPR ebp,ebx,esi,edi %xdefine pR [eax + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [eax + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [eax + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 %assign _rp_ _buf_+(LEN256+1)*sizeof(dword) ; pR %assign _ap_ _rp_ +sizeof(dword) ; pA %assign _bp_ _ap_+sizeof(dword) ; pB %assign _sp_ _bp_+sizeof(dword) ; esp storage %assign _ssize_ _sp_+sizeof(dword) ; size allocated stack mov eax, esp ; save esp sub esp, _ssize_ ; allocate stack and esp, -16 ; provide 16-byte stack alignment mov dword [esp+_sp_], eax ; store original esp ; clear buffer pxor mm0, mm0 movq qword [esp+_buf_], mm0 movq qword [esp+_buf_+sizeof(qword)], mm0 movq qword [esp+_buf_+sizeof(qword)*2], mm0 movq qword [esp+_buf_+sizeof(qword)*3], mm0 movd dword [esp+_buf_+sizeof(qword)*4], mm0 ; store parameters into the stack ; note: eax here stores an original esp, so it can be used to reach function parameters mov edi, pR mov esi, pA mov ebp, pB mov dword [esp+_rp_], edi mov dword [esp+_ap_], esi mov dword [esp+_bp_], ebp mov edi, LEN256 movd mm1, dword [esi+sizeof(dword)] ; pre load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] align IPP_ALIGN_FACTOR .mmul_loop: ; ; i-st pass ; modulus = 2^256 -2^224 +2^192 +2^96 -1 ; [8] [7] [6] [3] [0] ; m0 = 1 ; movd mm7, edi ; save pass counter mov edx, dword [ebp] ; b = b[i] mov eax, dword [esi] ; a[0] movd mm0, edx add ebp, sizeof(dword) mov dword [esp+_bp_], ebp pmuludq mm1, mm0 ; a[1]*b[i] pmuludq mm2, mm0 ; a[2]*b[i] mul edx ; (E:u) = (edx:eax) = a[0]*b[i]+buf[0] add eax, dword [esp+_buf_] adc edx, 0 pmuludq mm3, mm0 ; a[3]*b[i] pmuludq mm4, mm0 ; a[4]*b[i] ; multiplication round 1 - round 4 movd ecx, mm1 ; p = a[1]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*1] movd mm1, dword [esi+sizeof(dword)*5] adc edx, 0 movd ebx, mm2 ; p = a[2]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*2] movd mm2, dword [esi+sizeof(dword)*6] adc edx, 0 pmuludq mm1, mm0 ; a[5]*b[i] pmuludq mm2, mm0 ; a[6]*b[i] movd ebp, mm3 ; p = a[3]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*3] movd mm3, dword [esi+sizeof(dword)*7] adc edx, 0 movd edi, mm4 ; p = a[4]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*4] adc edx, 0 pmuludq mm3, mm0 ; a[7]*b[i] ;;; and reduction ;;; ; eax =u0 mov dword [esp+_buf_+sizeof(dword)*0], ecx ; copy mov dword [esp+_buf_+sizeof(dword)*1], ebx ; copy add ebp, eax ; +u0 mov dword [esp+_buf_+sizeof(dword)*2], ebp adc edi, 0 ; +cf mov dword [esp+_buf_+sizeof(dword)*3], edi mov edi, 0 ; save edi = cf adc edi, 0 ; multiplication round 5 - round 7 movd ecx, mm1 ; p = a[5]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*5] adc edx, 0 movd ebx, mm2 ; p = a[6]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*6] adc edx, 0 movd ebp, mm3 ; p = a[7]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*7] adc edx, 0 ;;; and reduction ;;; add ecx, edi ; +cf mov dword [esp+_buf_+sizeof(dword)*4], ecx adc ebx, eax ; +u0+cf mov dword [esp+_buf_+sizeof(dword)*5], ebx mov ecx, eax sbb eax, 0 sub ebp, eax ; -u0+cf mov dword [esp+_buf_+sizeof(dword)*6], ebp ; last multiplication round 8 movd edi, mm7 ; restore pass counter sbb ecx, 0 ; u-bf mov ebx, 0 add edx, dword [esp+_buf_+sizeof(dword)*8] adc ebx, 0 add edx, ecx mov dword [esp+_buf_+sizeof(dword)*7], edx adc ebx, 0 mov dword [esp+_buf_+sizeof(dword)*8], ebx sub edi, 1 movd mm1, dword [esi+sizeof(dword)] ; speculative load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] jz .exit_mmul_loop mov ebp, dword [esp+_bp_] ; restore pB jmp .mmul_loop .exit_mmul_loop: emms ; final reduction mov edi, [esp+_rp_] ; result lea esi, [esp+_buf_] ; buffer LD_ADDR ebx, p256r1_data ; modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM sub_256 mov edx, dword [esp+_buf_+LEN256*sizeof(dword)] sub edx, eax ; copy cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] ; release stack REST_GPR ret ENDFUNC p256r1_mul_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_sqr_mont_slm(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p256r1_sqr_mont_slm,PUBLIC USES_GPR esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source A address ;; use p256r1_mul_mont_slm to compute sqr mov esi, pA mov edi, pR push esi push esi push edi CALL_IPPASM p256r1_mul_mont_slm,PUBLIC add esp, sizeof(dword)*3 REST_GPR ret ENDFUNC p256r1_sqr_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p256r1_mred(Ipp32u* r, Ipp32u* prod) ;; ; modulus = 2^256 -2^224 +2^192 +2^96 -1 ; [8] [7] [6] [3] [0] ; m0 = 1 ; align IPP_ALIGN_FACTOR IPPASM p256r1_mred,PUBLIC USES_GPR ebx,esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; reduction address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source product address ; get parameters: mov esi, pA mov ecx, LEN256 xor edx, edx align IPP_ALIGN_FACTOR .mred_loop: mov eax, dword [esi] mov ebx, 0 mov dword [esi], ebx mov ebx, dword [esi+sizeof(dword)*3] add ebx, eax mov dword [esi+sizeof(dword)*3], ebx mov ebx, dword [esi+sizeof(dword)*4] adc ebx, 0 mov dword [esi+sizeof(dword)*4], ebx mov ebx, dword [esi+sizeof(dword)*5] adc ebx, 0 mov dword [esi+sizeof(dword)*5], ebx mov ebx, dword [esi+sizeof(dword)*6] adc ebx, eax mov dword [esi+sizeof(dword)*6], ebx mov ebx, dword [esi+sizeof(dword)*7] push eax sbb eax, 0 sub ebx, eax mov dword [esi+sizeof(dword)*7], ebx pop eax mov ebx, dword [esi+sizeof(dword)*8] sbb eax, 0 add eax, edx mov edx, 0 adc edx, 0 add ebx, eax mov dword [esi+sizeof(dword)*8], ebx adc edx, 0 lea esi, [esi+sizeof(dword)] sub ecx, 1 jnz .mred_loop ; final reduction mov edi, pR ; result LD_ADDR ebx, p256r1_data ; address of the modulus lea ebx, [ebx+(_prime256r1-p256r1_data)] CALL_IPPASM sub_256 sub edx, eax cmovz esi, edi cpy_256 edi, esi REST_GPR ret ENDFUNC p256r1_mred %endif ;; _IPP >= _IPP_P8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpp384r1arith_mont_slm.asm000066400000000000000000000763741470420105600277560ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; P384r1 basic arithmetic function ; ; Content: ; p384r1_add ; p384r1_sub ; p384r1_neg ; p384r1_div_by_2 ; p384r1_mul_mont_slm ; p384r1_sqr_mont_slm ; p384r1_mred ; p384r1_select_ap_w5 ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR ;; ;; some p384r1 constants ;; p384r1_data: _prime384r1 DD 0FFFFFFFFh,000000000h,000000000h,0FFFFFFFFh,0FFFFFFFEh,0FFFFFFFFh DD 0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh %assign LEN384 (384/32) ; dword's length of operands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Ipp32u add_384(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = carry = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM add_384,PRIVATE ; r = a+b mov eax, dword [esi] add eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] adc eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] adc eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] adc eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] adc eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] adc eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] adc eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] adc eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, dword [esi+sizeof(dword)*8] adc eax, dword [ebx+sizeof(dword)*8] mov dword [edi+sizeof(dword)*8], eax mov eax, dword [esi+sizeof(dword)*9] adc eax, dword [ebx+sizeof(dword)*9] mov dword [edi+sizeof(dword)*9], eax mov eax, dword [esi+sizeof(dword)*10] adc eax, dword [ebx+sizeof(dword)*10] mov dword [edi+sizeof(dword)*10], eax mov eax, dword [esi+sizeof(dword)*11] adc eax, dword [ebx+sizeof(dword)*11] mov dword [edi+sizeof(dword)*11], eax mov eax, 0 adc eax, 0 ret ENDFUNC add_384 ;; ;; Ipp32u sub_384(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = borrow = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM sub_384,PRIVATE ; r = a-b mov eax, dword [esi] sub eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] sbb eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] sbb eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] sbb eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] sbb eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] sbb eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] sbb eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] sbb eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, dword [esi+sizeof(dword)*8] sbb eax, dword [ebx+sizeof(dword)*8] mov dword [edi+sizeof(dword)*8], eax mov eax, dword [esi+sizeof(dword)*9] sbb eax, dword [ebx+sizeof(dword)*9] mov dword [edi+sizeof(dword)*9], eax mov eax, dword [esi+sizeof(dword)*10] sbb eax, dword [ebx+sizeof(dword)*10] mov dword [edi+sizeof(dword)*10], eax mov eax, dword [esi+sizeof(dword)*11] sbb eax, dword [ebx+sizeof(dword)*11] mov dword [edi+sizeof(dword)*11], eax mov eax, 0 adc eax, 0 ret ENDFUNC sub_384 ;; ;; Ipp32u shl_384(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shl_384,PRIVATE mov eax, dword [esi+(LEN384-1)*sizeof(dword)] ; r = a<<1 movdqu xmm3, oword [esi+sizeof(oword)*2] movdqu xmm2, oword [esi+sizeof(oword)] movdqu xmm1, oword [esi] movdqa xmm4, xmm3 palignr xmm4, xmm2, sizeof(qword) psllq xmm3, 1 psrlq xmm4, 63 por xmm3, xmm4 movdqu oword [edi+sizeof(oword)*2], xmm3 movdqa xmm4, xmm2 palignr xmm4, xmm1, sizeof(qword) psllq xmm2, 1 psrlq xmm4, 63 por xmm2, xmm4 movdqu oword [edi+sizeof(oword)], xmm2 movdqa xmm4, xmm1 pslldq xmm4, sizeof(qword) psllq xmm1, 1 psrlq xmm4, 63 por xmm1, xmm4 movdqu oword [edi], xmm1 shr eax, 31 ret ENDFUNC shl_384 ;; ;; void shr_384(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; eax = ext ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shr_384,PRIVATE ; r = a>>1 movdqu xmm3, oword [esi] movdqu xmm2, oword [esi+sizeof(oword)] movdqu xmm1, oword [esi+sizeof(oword)*2] movdqa xmm4, xmm2 palignr xmm4, xmm3, sizeof(qword) psrlq xmm3, 1 psllq xmm4, 63 por xmm3, xmm4 movdqu oword [edi], xmm3 movdqa xmm4, xmm1 palignr xmm4, xmm2, sizeof(qword) psrlq xmm2, 1 psllq xmm4, 63 por xmm2, xmm4 movdqu oword [edi+sizeof(oword)], xmm2 movdqa xmm4, xmm0 palignr xmm4, xmm1, sizeof(qword) psrlq xmm1, 1 psllq xmm4, 63 por xmm1, xmm4 movdqu oword [edi+sizeof(oword)*2], xmm1 ret ENDFUNC shr_384 ;; ;; void cpy_384(Ipp32u* r, const Ipp32u* a) ;; %macro cpy_384 2.nolist %xdefine %%pdst %1 %xdefine %%psrc %2 movdqu xmm0, oword [%%psrc] movdqu xmm1, oword [%%psrc+sizeof(oword)] movdqu xmm2, oword [%%psrc+sizeof(oword)*2] movdqu oword [%%pdst], xmm0 movdqu oword [%%pdst+sizeof(oword)], xmm1 movdqu oword [%%pdst+sizeof(oword)*2], xmm2 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_add(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_add,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN384] %assign _sp_ _buf_+(LEN384)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM add_384 ; R = A+B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p384r1_data ; modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM sub_384 ; T = R-modulus lea esi,[esp+_buf_] mov edi, pR sub edx, eax ; R = T<0? R : T cmovnz esi, edi cpy_384 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p384r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_sub(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_sub,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN384] %assign _sp_ _buf_+(LEN384)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM sub_384 ; R = A-B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p384r1_data ; modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM add_384 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_384 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p384r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_neg(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_neg,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN384] %assign _sp_ _buf_+(LEN384)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; outpur pR mov esi, pA ; input pA ; r = 0-a mov eax, 0 sub eax, dword [esi] mov dword [edi], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*8] mov dword [edi+sizeof(dword)*8], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*9] mov dword [edi+sizeof(dword)*9], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*10] mov dword [edi+sizeof(dword)*10], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*11] mov dword [edi+sizeof(dword)*11], eax sbb edx,edx lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p384r1_data ; modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM add_384 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_384 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p384r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_mul_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_mul_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN384] %assign _sp_ _buf_+(LEN384)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; pA CALL_IPPASM shl_384 ; T = A<<1 mov edx, eax mov esi, edi ; T mov edi, pR ; R LD_ADDR ebx, p384r1_data ; modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM sub_384 ; R = T-modulus sub edx, eax ; R = R<0? T : R cmovz esi, edi cpy_384 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p384r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_mul_by_3(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_mul_by_3,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _bufT_ 0 ; T buffer[LEN384] %assign _bufU_ _bufT_+(LEN384)*sizeof(dword) ; U buffer[LEN384] %assign _mod_ _bufU_+(LEN384)*sizeof(dword) ; modulus address [1] %assign _sp_ _mod_+sizeof(dword) ; esp [1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp LD_ADDR eax, p384r1_data ; srore modulus address lea eax, [eax+(_prime384r1-p384r1_data)] mov dword [esp+_mod_], eax lea edi, [esp+_bufT_] ; T mov esi, pA ; A CALL_IPPASM shl_384 ; T = A<<1 mov edx, eax mov esi, edi ; T lea edi, [esp+_bufU_] ; U mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_384 ; U = T-modulus sub edx, eax ; T = U<0? T : U cmovz esi, edi cpy_384 edi, esi mov esi, edi mov ebx, pA CALL_IPPASM add_384 ; T +=A mov edx, eax mov edi, pR ; R mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_384 ; R = T-modulus sub edx, eax ; R = T<0? R : T cmovz esi, edi cpy_384 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p384r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_div_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_div_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN384] %assign _sp_ _buf_+(LEN384)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; A LD_ADDR ebx, p384r1_data ; modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM add_384 ; R = A+modulus mov edx, 0 mov ecx, dword [esi] ; shifted_data = (a[0]&1)? T : A and ecx, 1 cmovnz esi, edi cmovz eax, edx movd xmm0, eax mov edi, pR CALL_IPPASM shr_384 mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p384r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_mul_mont_slm(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_mul_mont_slm,PUBLIC USES_GPR ebp,ebx,esi,edi %xdefine pR [eax + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [eax + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [eax + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 %assign _rp_ _buf_+(LEN384+1)*sizeof(dword) ; pR %assign _ap_ _rp_ +sizeof(dword) ; pA %assign _bp_ _ap_+sizeof(dword) ; pB %assign _sp_ _bp_+sizeof(dword) ; esp storage %assign _ssize_ _sp_+sizeof(dword) ; size allocated stack mov eax, esp ; save esp sub esp, _ssize_ ; allocate stack and esp, -16 ; provide 16-byte stack alignment mov dword [esp+_sp_], eax ; store original esp ; clear buffer pxor mm0, mm0 movq [esp+_buf_], mm0 movq [esp+_buf_+sizeof(qword)], mm0 movq [esp+_buf_+sizeof(qword)*2], mm0 movq [esp+_buf_+sizeof(qword)*3], mm0 movq [esp+_buf_+sizeof(qword)*4], mm0 movq [esp+_buf_+sizeof(qword)*5], mm0 movq [esp+_buf_+sizeof(qword)*6], mm0 ; store parameters into the stack ; note: eax here stores an original esp, so it can be used to reach function parameters mov edi, pR mov esi, pA mov ebp, pB mov dword [esp+_rp_], edi mov dword [esp+_ap_], esi mov dword [esp+_bp_], ebp mov eax, LEN384 movd mm1, dword [esi+sizeof(dword)] ; pre load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] align IPP_ALIGN_FACTOR .mmul_loop: ; ; i-st pass ; modulus = 2^384 -2^128 -2^96 +2^32 -1 ; [12] [4] [3] [1] [0] ; m0 = 1 ; ; T0 = a[ 0]*b[i] + p[0] ; e0 = HI(T0), u = LO(T0) ; ; T1 = a[ 1]*b[i] +e0 +p[ 1], (cf=0), e1 = HI( T1), p1 =LO( T1), (cf1 ,p1 ) = p1 +u, p[ 0] = p1, cf1 ; T2 = a[ 2]*b[i] +e1 +p[ 2], (cf=0), e2 = HI( T2), p2 =LO( T2), (cf2 ,p2 ) = p2 +cf1, p[ 1] = p2, cf2 ; T3 = a[ 3]*b[i] +e2 +p[ 3], (cf=0), e3 = HI( T3), p3 =LO( T3), (bf3 ,p3 ) = p3 +cf2 -u, p[ 2] = p3, bf3 ; T4 = a[ 4]*b[i] +e3 +p[ 4], (cf=0), e4 = HI( T4), p4 =LO( T4), (bf4 ,p4 ) = p4 -bf3 -u, p[ 3] = p4, bf4 ; T5 = a[ 5]*b[i] +e4 +p[ 5], (cf=0), e5 = HI( T5), p5 =LO( T5), (bf5 ,p5 ) = p5 -bf4, p[ 4] = p5, bf5 ; T6 = a[ 6]*b[i] +e5 +p[ 6], (cf=0), e6 = HI( T6), p6 =LO( T6), (bf6 ,p6 ) = p6 -bf5, p[ 5] = p6, bf6 ; T7 = a[ 7]*b[i] +e6 +p[ 7], (cf=0), e7 = HI( T7), p7 =LO( T7), (bf7 ,p7 ) = p7 -bf6, p[ 6] = p7, bf7 ; T8 = a[ 8]*b[i] +e7 +p[ 8], (cf=0), e8 = HI( T8), p8 =LO( T8), (bf8 ,p8 ) = p8 -bf7, p[ 7] = p8, bf8 ; T9 = a[ 9]*b[i] +e8 +p[ 9], (cf=0), e9 = HI( T9), p9 =LO( T9), (bf9 ,p9 ) = p9 -bf8, p[ 8] = p9, bf9 ; T10 = a[10]*b[i] +e9 +p[10], (cf=0), e10= HI(T10), p10=LO(T10), (bf10,p10) = p10-bf9, p[ 9] = p10, bf9 ; T11 = a[11]*b[i] +e10 +p[11], (cf=0), e11= HI(T11), p11=LO(T11), (bf11,p11) = p11-bf10, p[10] = p11, bf10 ; (cf12,p12) = e11-bf11+u p[11] = p12, cf12 ; p[13] = cf12 movd mm7, eax ; save pass counter mov edx, dword [ebp] ; b = b[i] mov eax, dword [esi] ; a[0] movd mm0, edx add ebp, sizeof(dword) mov dword [esp+_bp_], ebp pmuludq mm1, mm0 ; a[1]*b[i] pmuludq mm2, mm0 ; a[2]*b[i] mul edx ; (E:u) = (edx:eax) = a[0]*b[i]+buf[0] add eax, dword [esp+_buf_] adc edx, 0 pmuludq mm3, mm0 ; a[3]*b[i] pmuludq mm4, mm0 ; a[4]*b[i] ; multiplication round 1 - round 4 movd ecx, mm1 ; p = a[1]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*1] movd mm1, dword [esi+sizeof(dword)*5] adc edx, 0 ;pmuludq mm1, mm0 movd ebx, mm2 ; p = a[2]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*2] movd mm2, dword [esi+sizeof(dword)*6] adc edx, 0 pmuludq mm1, mm0 pmuludq mm2, mm0 movd ebp, mm3 ; p = a[3]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*3] movd mm3, dword [esi+sizeof(dword)*7] adc edx, 0 ;pmuludq mm3, mm0 movd edi, mm4 ; p = a[4]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*4] movd mm4, dword [esi+sizeof(dword)*8] adc edx, 0 pmuludq mm3, mm0 pmuludq mm4, mm0 ;;; and reduction ;;; add ecx, eax ; +u0 mov dword [esp+_buf_+sizeof(dword)*0], ecx mov ecx, eax ; save u0 adc ebx, 0 ; +cf mov dword [esp+_buf_+sizeof(dword)*1], ebx sbb eax, 0 ; eax = u0-cf sub ebp, eax ; ebp-eax = ebp+cf-u0 mov dword [esp+_buf_+sizeof(dword)*2], ebp sbb edi, ecx ; edi-u0-bf mov eax, 0 mov dword [esp+_buf_+sizeof(dword)*3], edi movd mm6, ecx ;sbb eax, eax ; save bf signu: eax = bf? 0xffffffff: 0x00000000 adc eax, 0 ; multiplication round 5 - round 8 movd ecx, mm1 ; p = a[5]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*5] movd mm1, dword [esi+sizeof(dword)*9] adc edx, 0 ;pmuludq mm1, mm0 movd ebx, mm2 ; p = a[6]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*6] movd mm2, dword [esi+sizeof(dword)*10] adc edx, 0 pmuludq mm1, mm0 pmuludq mm2, mm0 movd ebp, mm3 ; p = a[7]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*7] movd mm3, dword [esi+sizeof(dword)*11] adc edx, 0 pmuludq mm3, mm0 movd edi, mm4 ; p = a[8]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*8] adc edx, 0 ;;; and reduction ;;; ;add eax, eax ; restore bf ;sbb ecx, 0 ; -bf sub ecx, eax movd eax, mm6 mov dword [esp+_buf_+sizeof(dword)*4], ecx sbb ebx, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*5], ebx sbb ebp, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*6], ebp sbb edi, 0 ; -bf mov eax, 0 mov dword [esp+_buf_+sizeof(dword)*7], edi ;sbb eax, eax adc eax, 0 ; multiplication round 9 - round 11 movd ecx, mm1 ; p = a[9]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*9] adc edx, 0 movd ebx, mm2 ; p = a[10]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*10] adc edx, 0 movd ebp, mm3 ; p = a[11]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*11] adc edx, 0 ;;; and reduction ;;; ;add eax, eax ; restore bf ;sbb ecx, 0 ; u0-bf sub ecx, eax mov dword [esp+_buf_+sizeof(dword)*8], ecx movd ecx, mm6 sbb ebx, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*9], ebx sbb ebp, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*10], ebp sbb ecx, 0 ; u0-bf mov ebx, 0 ; last multiplication round 12 movd eax, mm7 ; restore pass counter add edx, dword [esp+_buf_+sizeof(dword)*12] adc ebx, 0 add edx, ecx adc ebx, 0 mov dword [esp+_buf_+sizeof(dword)*11], edx mov dword [esp+_buf_+sizeof(dword)*12], ebx sub eax, 1 movd mm1, dword [esi+sizeof(dword)] ; speculative load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] jz .exit_mmul_loop mov ebp, dword [esp+_bp_] ; restore pB jmp .mmul_loop .exit_mmul_loop: emms ; final reduction mov edi, [esp+_rp_] ; result lea esi, [esp+_buf_] ; buffer LD_ADDR ebx, p384r1_data ; modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM sub_384 mov edx, dword [esp+_buf_+sizeof(dword)*12] sub edx, eax ; copy cmovz esi, edi cpy_384 edi, esi mov esp, [esp+_sp_] ; release stack REST_GPR ret ENDFUNC p384r1_mul_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_sqr_mont_slm(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p384r1_sqr_mont_slm,PUBLIC USES_GPR esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source A address ;; use p384r1_mul_mont_slm to compute sqr mov esi, pA mov edi, pR push esi push esi push edi CALL_IPPASM p384r1_mul_mont_slm,PUBLIC add esp, sizeof(dword)*3 REST_GPR ret ENDFUNC p384r1_sqr_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p384r1_mred(Ipp32u* r, Ipp32u* prod) ;; ; modulus = 2^384 -2^128 -2^96 +2^32 -1 ; [12] [4] [3] [1] [0] ; m0 = 1 ; align IPP_ALIGN_FACTOR IPPASM p384r1_mred,PUBLIC USES_GPR ebx,esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; reduction address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source product address ; get parameters: mov esi, pA mov ecx, LEN384 xor edx, edx align IPP_ALIGN_FACTOR .mred_loop: mov eax, dword [esi] mov ebx, dword [esi+sizeof(dword)] add ebx, eax mov dword [esi+sizeof(dword)], ebx mov ebx, dword [esi+sizeof(dword)*2] adc ebx, 0 mov dword [esi+sizeof(dword)*2], ebx mov ebx, dword [esi+sizeof(dword)*3] sbb eax, 0 sub ebx, eax mov eax, dword [esi] mov dword [esi+sizeof(dword)*3], ebx mov ebx, dword [esi+sizeof(dword)*4] sbb ebx, eax mov dword [esi+sizeof(dword)*4], ebx mov ebx, dword [esi+sizeof(dword)*5] sbb ebx, 0 mov dword [esi+sizeof(dword)*5], ebx mov ebx, dword [esi+sizeof(dword)*6] sbb ebx, 0 mov dword [esi+sizeof(dword)*6], ebx mov ebx, dword [esi+sizeof(dword)*7] sbb ebx, 0 mov dword [esi+sizeof(dword)*7], ebx mov ebx, dword [esi+sizeof(dword)*8] sbb ebx, 0 mov dword [esi+sizeof(dword)*8], ebx mov ebx, dword [esi+sizeof(dword)*9] sbb ebx, 0 mov dword [esi+sizeof(dword)*9], ebx mov ebx, dword [esi+sizeof(dword)*10] sbb ebx, 0 mov dword [esi+sizeof(dword)*10], ebx mov ebx, dword [esi+sizeof(dword)*11] sbb ebx, 0 mov dword [esi+sizeof(dword)*11], ebx mov ebx, dword [esi+sizeof(dword)*12] sbb eax, 0 add eax, edx mov edx, 0 adc edx, 0 add ebx, eax mov dword [esi+sizeof(dword)*12], ebx adc edx, 0 lea esi, [esi+sizeof(dword)] sub ecx, 1 jnz .mred_loop ; final reduction mov edi, pR ; result LD_ADDR ebx, p384r1_data ; address of the modulus lea ebx, [ebx+(_prime384r1-p384r1_data)] CALL_IPPASM sub_384 sub edx, eax cmovz esi, edi cpy_384 edi, esi REST_GPR ret ENDFUNC p384r1_mred %endif ;; _IPP >= _IPP_P8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpp521r1arith_mont_slm.asm000066400000000000000000000770571470420105600277460ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; P521r1 basic arithmetic function ; ; Content: ; p521r1_add ; p521r1_sub ; p521r1_neg ; p521r1_div_by_2 ; p521r1_mul_mont_slm ; p521r1_sqr_mont_slm ; p521r1_mred ; p521r1_mont_back ; p521r1_select_ap_w7 ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR ;; ;; some p256r1 constants ;; p521r1_data: _prime521r1 DD 0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh, 0FFFFFFFFh DD 0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh, 0FFFFFFFFh DD 0000001FFh %assign LEN521 ((521+32-1)/32) ; dword's length of operands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Ipp32u add_521(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = carry = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM add_521,PRIVATE ; r = a+b mov eax, dword [esi] add eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] adc eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] adc eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] adc eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] adc eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] adc eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] adc eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] adc eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, dword [esi+sizeof(dword)*8] adc eax, dword [ebx+sizeof(dword)*8] mov dword [edi+sizeof(dword)*8], eax mov eax, dword [esi+sizeof(dword)*9] adc eax, dword [ebx+sizeof(dword)*9] mov dword [edi+sizeof(dword)*9], eax mov eax, dword [esi+sizeof(dword)*10] adc eax, dword [ebx+sizeof(dword)*10] mov dword [edi+sizeof(dword)*10], eax mov eax, dword [esi+sizeof(dword)*11] adc eax, dword [ebx+sizeof(dword)*11] mov dword [edi+sizeof(dword)*11], eax mov eax, dword [esi+sizeof(dword)*12] adc eax, dword [ebx+sizeof(dword)*12] mov dword [edi+sizeof(dword)*12], eax mov eax, dword [esi+sizeof(dword)*13] adc eax, dword [ebx+sizeof(dword)*13] mov dword [edi+sizeof(dword)*13], eax mov eax, dword [esi+sizeof(dword)*14] adc eax, dword [ebx+sizeof(dword)*14] mov dword [edi+sizeof(dword)*14], eax mov eax, dword [esi+sizeof(dword)*15] adc eax, dword [ebx+sizeof(dword)*15] mov dword [edi+sizeof(dword)*15], eax mov eax, dword [esi+sizeof(dword)*16] adc eax, dword [ebx+sizeof(dword)*16] mov dword [edi+sizeof(dword)*16], eax mov eax, 0 adc eax, 0 ret ENDFUNC add_521 ;; ;; Ipp32u sub_521(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = borrow = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM sub_521,PRIVATE ; r = a-b mov eax, dword [esi] sub eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] sbb eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] sbb eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] sbb eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] sbb eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] sbb eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] sbb eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] sbb eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, dword [esi+sizeof(dword)*8] sbb eax, dword [ebx+sizeof(dword)*8] mov dword [edi+sizeof(dword)*8], eax mov eax, dword [esi+sizeof(dword)*9] sbb eax, dword [ebx+sizeof(dword)*9] mov dword [edi+sizeof(dword)*9], eax mov eax, dword [esi+sizeof(dword)*10] sbb eax, dword [ebx+sizeof(dword)*10] mov dword [edi+sizeof(dword)*10], eax mov eax, dword [esi+sizeof(dword)*11] sbb eax, dword [ebx+sizeof(dword)*11] mov dword [edi+sizeof(dword)*11], eax mov eax, dword [esi+sizeof(dword)*12] sbb eax, dword [ebx+sizeof(dword)*12] mov dword [edi+sizeof(dword)*12], eax mov eax, dword [esi+sizeof(dword)*13] sbb eax, dword [ebx+sizeof(dword)*13] mov dword [edi+sizeof(dword)*13], eax mov eax, dword [esi+sizeof(dword)*14] sbb eax, dword [ebx+sizeof(dword)*14] mov dword [edi+sizeof(dword)*14], eax mov eax, dword [esi+sizeof(dword)*15] sbb eax, dword [ebx+sizeof(dword)*15] mov dword [edi+sizeof(dword)*15], eax mov eax, dword [esi+sizeof(dword)*16] sbb eax, dword [ebx+sizeof(dword)*16] mov dword [edi+sizeof(dword)*16], eax mov eax, 0 adc eax, 0 ret ENDFUNC sub_521 ;; ;; Ipp32u shl_521(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shl_521,PRIVATE ; r = a<<1 push ecx mov ecx, LEN521-4 pxor xmm1, xmm1 .shl_loop: movdqu xmm0, oword [esi] movdqa xmm2, xmm0 add esi, sizeof(oword) palignr xmm2, xmm1, sizeof(qword) movdqa xmm1, xmm0 psllq xmm0, 1 psrlq xmm2, 63 por xmm0, xmm2 movdqu oword [edi], xmm0 add edi, sizeof(oword) sub ecx, 4 jg .shl_loop movd xmm0, dword [esi] palignr xmm0, xmm1, sizeof(dword)*3 psllq xmm0, 1 psrldq xmm0, sizeof(dword) movd dword [edi], xmm0 sub esi, sizeof(oword)*4 sub edi, sizeof(oword)*4 pop ecx xor eax, eax ret ENDFUNC shl_521 ;; ;; void shr_521(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; eax = ext ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM shr_521,PRIVATE ; r = a>>1 mov eax, dword [esi+(LEN521-1)*sizeof(dword)] push ecx mov ecx, LEN521-(4*2) .shr_loop: movdqu xmm0, oword [esi] movdqu xmm1, oword [esi+sizeof(oword)] palignr xmm1, xmm0, sizeof(qword) add esi, sizeof(oword) psrlq xmm0, 1 psllq xmm1, 63 por xmm0, xmm1 movdqu oword [edi], xmm0 add edi, sizeof(oword) sub ecx, 4 jg .shr_loop pop ecx movdqu xmm0, oword [esi] movd xmm1, eax palignr xmm1, xmm0, sizeof(qword) psrlq xmm0, 1 psllq xmm1, 63 por xmm0, xmm1 movdqu oword [edi], xmm0 shr eax, 1 mov dword [edi+sizeof(oword)], eax sub esi, sizeof(qword)*3 sub esi, sizeof(qword)*3 ret ENDFUNC shr_521 ;; ;; void cpy_521(Ipp32u* r, const Ipp32u* a) ;; %macro cpy_521 2.nolist %xdefine %%pdst %1 %xdefine %%psrc %2 movdqu xmm0, oword [%%psrc] movdqu xmm1, oword [%%psrc+sizeof(oword)] movdqu xmm2, oword [%%psrc+sizeof(oword)*2] movdqu xmm3, oword [%%psrc+sizeof(oword)*3] mov eax, dword [%%psrc+sizeof(oword)*4] movdqu oword [%%pdst], xmm0 movdqu oword [%%pdst+sizeof(oword)], xmm1 movdqu oword [%%pdst+sizeof(oword)*2], xmm2 movdqu oword [%%pdst+sizeof(oword)*3], xmm3 mov dword [%%pdst+sizeof(oword)*4], eax %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_add(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_add,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN521] %assign _sp_ _buf_+(LEN521)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM add_521 ; R = A+B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p521r1_data ; modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM sub_521 ; T = R-modulus lea esi,[esp+_buf_] mov edi, pR sub edx, eax ; R = T<0? R : T cmovnz esi, edi cpy_521 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p521r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_sub(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_sub,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN521] %assign _sp_ _buf_+(LEN521)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM sub_521 ; R = A-B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p521r1_data ; modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM add_521 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_521 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p521r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_neg(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_neg,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN521] %assign _sp_ _buf_+(LEN521)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; outpur pR mov esi, pA ; input pA ; r = 0-a mov eax, 0 sub eax, dword [esi] mov dword [edi], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*8] mov dword [edi+sizeof(dword)*8], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*9] mov dword [edi+sizeof(dword)*9], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*10] mov dword [edi+sizeof(dword)*10], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*11] mov dword [edi+sizeof(dword)*11], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*12] mov dword [edi+sizeof(dword)*12], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*13] mov dword [edi+sizeof(dword)*13], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*14] mov dword [edi+sizeof(dword)*14], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*15] mov dword [edi+sizeof(dword)*15], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*16] mov dword [edi+sizeof(dword)*16], eax sbb edx,edx lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, p521r1_data ; modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM add_521 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_521 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p521r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_mul_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_mul_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN521] %assign _sp_ _buf_+(LEN521)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; pA CALL_IPPASM shl_521 ; T = A<<1 mov edx, eax mov esi, edi ; T mov edi, pR ; R LD_ADDR ebx, p521r1_data ; modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM sub_521 ; R = T-modulus sub edx, eax ; R = R<0? T : R cmovz esi, edi cpy_521 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p521r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_mul_by_3(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_mul_by_3,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _bufT_ 0 ; T buffer[LEN521] %assign _bufU_ _bufT_+(LEN521)*sizeof(dword) ; U buffer[LEN521] %assign _mod_ _bufU_+(LEN521)*sizeof(dword) ; modulus address [1] %assign _sp_ _mod_+sizeof(dword) ; esp [1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp LD_ADDR eax, p521r1_data ; srore modulus address lea eax, [eax+(_prime521r1-p521r1_data)] mov dword [esp+_mod_], eax lea edi, [esp+_bufT_] ; T mov esi, pA ; A CALL_IPPASM shl_521 ; T = A<<1 mov edx, eax mov esi, edi ; T lea edi, [esp+_bufU_] ; U mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_521 ; U = T-modulus sub edx, eax ; T = U<0? T : U cmovz esi, edi cpy_521 edi, esi mov esi, edi mov ebx, pA CALL_IPPASM add_521 ; T +=A mov edx, eax mov edi, pR ; R mov ebx, [esp+_mod_] ; modulus CALL_IPPASM sub_521 ; R = T-modulus sub edx, eax ; R = T<0? R : T cmovz esi, edi cpy_521 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p521r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_div_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_div_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LEN521] %assign _sp_ _buf_+(LEN521)*sizeof(dword) ; esp[1] %assign _frame_ _sp_ +sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; A LD_ADDR ebx, p521r1_data ; modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM add_521 ; R = A+modulus mov edx, 0 mov ecx, dword [esi] ; shifted_data = (a[0]&1)? T : A and ecx, 1 cmovnz esi, edi cmovz eax, edx mov edi, pR CALL_IPPASM shr_521 mov esp, [esp+_sp_] REST_GPR ret ENDFUNC p521r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_mul_mont_slm(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_mul_mont_slm,PUBLIC USES_GPR ebp,ebx,esi,edi %xdefine pR [eax + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [eax + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [eax + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 %assign _rp_ _buf_+(LEN521+1)*sizeof(dword) ; pR %assign _ap_ _rp_ +sizeof(dword) ; pA %assign _bp_ _ap_ +sizeof(dword) ; pB %assign _sp_ _bp_ +sizeof(dword) ; esp storage %assign _ssize_ _sp_ +sizeof(dword) ; size allocated stack mov eax, esp ; save esp sub esp, _ssize_ ; allocate stack and esp, -16 ; provide 16-byte stack alignment mov dword [esp+_sp_], eax ; store original esp ; clear buffer pxor xmm0, xmm0 movdqa oword [esp+_buf_], xmm0 movdqa oword [esp+_buf_+sizeof(oword)], xmm0 movdqa oword [esp+_buf_+sizeof(oword)*2], xmm0 movdqa oword [esp+_buf_+sizeof(oword)*3], xmm0 movq qword [esp+_buf_+sizeof(oword)*4], xmm0 ; store parameters into the stack ; note: eax here stores an original esp, so it can be used to reach function parameters mov edi, pR mov esi, pA mov ebp, pB mov dword [esp+_rp_], edi mov dword [esp+_ap_], esi mov dword [esp+_bp_], ebp mov ebx, LEN521 movd mm1, dword [esi+sizeof(dword)] ; pre load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] align IPP_ALIGN_FACTOR .mmul_loop: ; ; i-st pass ; modulus = 2^521 -1 ; [17] [0] ; m0 = 1 ; movd mm7, ebx ; save pass counter mov edx, dword [ebp] ; b = b[i] mov eax, dword [esi] ; a[0] movd mm0, edx add ebp, sizeof(dword) mov dword [esp+_bp_], ebp pmuludq mm1, mm0 ; a[1]*b[i] pmuludq mm2, mm0 ; a[2]*b[i] mul edx ; (E:u) = (edx:eax) = a[0]*b[i]+buf[0] add eax, dword [esp+_buf_] adc edx, 0 pmuludq mm3, mm0 ; a[3]*b[i] pmuludq mm4, mm0 ; a[4]*b[i] ; multiplication round 1 - round 4 movd ecx, mm1 ; p = a[1]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*1] movd mm1, dword [esi+sizeof(dword)*5] mov dword [esp+_buf_+sizeof(dword)*0], ecx adc edx, 0 movd ebx, mm2 ; p = a[2]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*2] movd mm2, dword [esi+sizeof(dword)*6] mov dword [esp+_buf_+sizeof(dword)*1], ebx adc edx, 0 pmuludq mm1, mm0 ; a[5]*b[i] pmuludq mm2, mm0 ; a[6]*b[i] movd ebp, mm3 ; p = a[3]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*3] movd mm3, dword [esi+sizeof(dword)*7] mov dword [esp+_buf_+sizeof(dword)*2], ebp adc edx, 0 movd edi, mm4 ; p = a[4]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*4] movd mm4, dword [esi+sizeof(dword)*8] mov dword [esp+_buf_+sizeof(dword)*3], edi adc edx, 0 pmuludq mm3, mm0 ; a[7]*b[i] pmuludq mm4, mm0 ; a[8]*b[i] ; multiplication round 5 - round 8 movd ecx, mm1 ; p = a[5]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*5] movd mm1, dword [esi+sizeof(dword)*9] mov dword [esp+_buf_+sizeof(dword)*4], ecx adc edx, 0 movd ebx, mm2 ; p = a[6]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*6] movd mm2, dword [esi+sizeof(dword)*10] mov dword [esp+_buf_+sizeof(dword)*5], ebx adc edx, 0 pmuludq mm1, mm0 ; a[9]*b[i] pmuludq mm2, mm0 ; a[10]*b[i] movd ebp, mm3 ; p = a[7]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*7] movd mm3, dword [esi+sizeof(dword)*11] mov dword [esp+_buf_+sizeof(dword)*6], ebp adc edx, 0 movd edi, mm4 ; p = a[8]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*8] movd mm4, dword [esi+sizeof(dword)*12] mov dword [esp+_buf_+sizeof(dword)*7], edi adc edx, 0 pmuludq mm3, mm0 ; a[11]*b[i] pmuludq mm4, mm0 ; a[12]*b[i] ; multiplication round 9 - round 12 movd ecx, mm1 ; p = a[9]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*9] movd mm1, dword [esi+sizeof(dword)*13] mov dword [esp+_buf_+sizeof(dword)*8], ecx adc edx, 0 movd ebx, mm2 ; p = a[10]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*10] movd mm2, dword [esi+sizeof(dword)*14] mov dword [esp+_buf_+sizeof(dword)*9], ebx adc edx, 0 pmuludq mm1, mm0 ; a[13]*b[i] pmuludq mm2, mm0 ; a[14]*b[i] movd ebp, mm3 ; p = a[11]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*11] movd mm3, dword [esi+sizeof(dword)*15] mov dword [esp+_buf_+sizeof(dword)*10], ebp adc edx, 0 movd edi, mm4 ; p = a[12]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*12] movd mm4, dword [esi+sizeof(dword)*16] mov dword [esp+_buf_+sizeof(dword)*11], edi adc edx, 0 pmuludq mm3, mm0 ; a[15]*b[i] pmuludq mm4, mm0 ; a[16]*b[i] ; multiplication round 13 - round 16 movd ecx, mm1 ; p = a[13]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*13] mov dword [esp+_buf_+sizeof(dword)*12], ecx adc edx, 0 movd ebx, mm2 ; p = a[14]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*14] mov dword [esp+_buf_+sizeof(dword)*13], ebx adc edx, 0 movd ebp, mm3 ; p = a[15]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*15] mov dword [esp+_buf_+sizeof(dword)*14], ebp adc edx, 0 movd edi, mm4 ; p = a[16]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*16] adc edx, 0 ;;; and reduction and last multiplication round 17 movd ebx, mm7 ; restore pass counter mov ecx, eax ; u0 <<= 9 shl eax, (521-512) shr ecx, (32-(521-512)) add edi, eax mov dword [esp+_buf_+sizeof(dword)*15], edi adc edx, ecx mov dword [esp+_buf_+sizeof(dword)*16], edx sub ebx, 1 movd mm1, dword [esi+sizeof(dword)] ; speculative load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] jz .exit_mmul_loop mov ebp, dword [esp+_bp_] ; restore pB jmp .mmul_loop .exit_mmul_loop: emms ; final reduction mov edi, [esp+_rp_] ; result lea esi, [esp+_buf_] ; buffer LD_ADDR ebx, p521r1_data ; modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM sub_521 mov edx, dword [esp+_buf_+LEN521*sizeof(dword)] ; copy cmovz esi, edi cpy_521 edi, esi mov esp, [esp+_sp_] ; release stack REST_GPR ret ENDFUNC p521r1_mul_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_sqr_mont_slm(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM p521r1_sqr_mont_slm,PUBLIC USES_GPR esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source A address ;; use p521r1_mul_mont_slm to compute sqr mov esi, pA mov edi, pR push esi push esi push edi CALL_IPPASM p521r1_mul_mont_slm,PUBLIC add esp, sizeof(dword)*3 REST_GPR ret ENDFUNC p521r1_sqr_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void p521r1_mred(Ipp32u* r, Ipp32u* prod) ;; ; modulus = 2^521 -1 ; [17] [0] ; m0 = 1 ; align IPP_ALIGN_FACTOR IPPASM p521r1_mred,PUBLIC USES_GPR ebx,esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; reduction address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source product address ; get parameters: mov esi, pA mov ecx, LEN521 xor edx, edx align IPP_ALIGN_FACTOR .mred_loop: mov ebx, dword [esi] ; [ebx:eax] = u0<<9 mov eax, dword [esi] shr ebx,(32-(521-512)) shl eax,(521-512) add ebx, edx ;; [esi+i*sizeof(dword)] = [esi+i*sizeof(dword)], i=1,..,16 add eax, dword [esi+sizeof(dword)*16] mov edx, dword [esi+sizeof(dword)*17] adc ebx, edx mov edx, 0 mov dword [esi+sizeof(dword)*16], eax mov dword [esi+sizeof(dword)*17], ebx adc edx, 0 lea esi, [esi+sizeof(dword)] sub ecx, 1 jnz .mred_loop ; final reduction mov edi, pR ; result LD_ADDR ebx, p521r1_data ; address of the modulus lea ebx, [ebx+(_prime521r1-p521r1_data)] CALL_IPPASM sub_521 sub edx, eax cmovz esi, edi cpy_521 edi, esi REST_GPR ret ENDFUNC p521r1_mred %endif ;; _IPP >= _IPP_P8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcppurgeblkw7as.asm000066400000000000000000000035111470420105600264510ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Purge block ; ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: Clear memory block ;* ;* void PurgeBlock(Ipp8u *pDst, int len) ;* ;*************************************************************** ;; ;; Lib = W7 ;; align IPP_ALIGN_FACTOR IPPASM PurgeBlock,PUBLIC USES_GPR edi %xdefine pDst [esp + ARG_1 + 0*sizeof(dword)] ; target address %xdefine len [esp + ARG_1 + 1*sizeof(dword)] ; length mov edi, pDst ; mem address mov ecx, len ; length xor eax, eax sub ecx, sizeof(dword) jl .test_purge .purge4: mov dword [edi], eax ; clear add edi, sizeof(dword) sub ecx, sizeof(dword) jge .purge4 .test_purge: add ecx, sizeof(dword) jz .quit .purge1: mov byte [edi], al add edi, sizeof(byte) sub ecx, sizeof(byte) jg .purge1 .quit: REST_GPR ret ENDFUNC PurgeBlock %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprc4v8as.asm000066400000000000000000000062671470420105600253410ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; ARCFour ; ; Content: ; ARCFourKernel() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_V8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: RC4 kernel ;* ;* void ARCFourProcessData(const Ipp8u *pSrc, Ipp8u *pDst, int len, ;* IppsARCFourState* pCtx) ;* ;*************************************************************** ;; ;; Lib = V8 ;; ;; Caller = ippsARCFourEncrypt ;; Caller = ippsARCFourDecrypt ;; align IPP_ALIGN_FACTOR IPPASM ARCFourProcessData,PUBLIC USES_GPR esi,edi,ebx,ebp %xdefine pSrc [esp + ARG_1 + 0*sizeof(dword)] %xdefine pDst [esp + ARG_1 + 1*sizeof(dword)] %xdefine len [esp + ARG_1 + 2*sizeof(dword)] %xdefine pCtx [esp + ARG_1 + 3*sizeof(dword)] mov edx, len ; data length mov esi, pSrc ; source data mov edi, pDst ; target data mov ebp, pCtx ; context test edx, edx ; test length jz .quit mov eax, dword [ebp+4] ; extract x mov ebx, dword [ebp+8] ; extract y lea ebp, [ebp+12] ; sbox add eax,1 ; x = (x+1)&0xFF and eax, 0FFh mov ecx, dword [ebp+eax*4] ; tx = S[x] lea edx, [esi+edx] ; store stop data address push edx ;; ;; main code ;; align IPP_ALIGN_FACTOR .main_loop: add ebx, ecx ; y = (x+tx)&0xFF movzx ebx, bl mov edx, dword [ebp+ebx*4] ; ty = S[y] mov dword [ebp+ebx*4],ecx ; S[y] = tx add ecx, edx ; tmp_idx = (tx+ty)&0xFF movzx ecx, cl mov dword [ebp+eax*4],edx ; S[x] = ty add eax, 1 ; next x = (x+1)&0xFF mov dl, byte [ebp+ecx*4] ; byte of gamma movzx eax, al xor dl,byte [esi] ; gamma ^= src add esi, 1 mov ecx, dword [ebp+eax*4] ; next tx = S[x] mov byte [edi],dl ; store result add edi, 1 cmp esi, dword [esp] jb .main_loop lea ebp, [ebp-12] ; pointer to context pop edx ; remove local variable dec eax ; actual new x counter and eax, 0FFh mov dword [ebp+4], eax ; update x counter mov dword [ebp+8], ebx ; updtae y counter .quit: REST_GPR ret ENDFUNC ARCFourProcessData %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprc4w7as.asm000066400000000000000000000060731470420105600253340ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; ARCFour ; ; Content: ; ARCFourKernel() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_M5) && (_IPP < _IPP_V8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: RC4 kernel ;* ;* void ARCFourProcessData(const Ipp8u *pSrc, Ipp8u *pDst, int len, ;* IppsARCFourState* pCtx) ;* ;*************************************************************** ;; ;; Lib = W7 ;; ;; Caller = ippsARCFourEncrypt ;; Caller = ippsARCFourDecrypt ;; IPPASM ARCFourProcessData,PUBLIC USES_GPR esi,edi,ebx,ebp %xdefine pSrc [esp + ARG_1 + 0*sizeof(dword)] %xdefine pDst [esp + ARG_1 + 1*sizeof(dword)] %xdefine len [esp + ARG_1 + 2*sizeof(dword)] %xdefine pCtx [esp + ARG_1 + 3*sizeof(dword)] mov edx, len ; data length mov esi, pSrc ; source data mov edi, pDst ; target data mov ebp, pCtx ; context test edx, edx ; test length jz .quit xor eax, eax movzx eax, byte [ebp+4] ; extract x xor ebx, ebx movzx ebx, byte [ebp+8] ; extract y lea ebp, [ebp+12] ; sbox inc al ; x = (x+1)&0xFF movzx ecx, byte [ebp+eax] ; tx = S[x] lea edx, [esi+edx] ; store stop data address push edx ;; ;; main code ;; align IPP_ALIGN_FACTOR .main_loop: add bl,cl ; y = (x+tx)&0xFF movzx edx,byte [ebx+ebp] ; ty = S[y] mov byte [ebx+ebp],cl ; S[y] = tx mov byte [eax+ebp],dl ; S[x] = ty add dl, cl ; tmp_idx = (tx+ty)&0xFF movzx edx,byte [edx+ebp] ; byte of gamma add al,1 ; next x = (x+1)&0xFF xor dl,byte [esi] ; gamma ^= src lea esi,[esi+1] movzx ecx,byte [eax+ebp] ; next tx = S[x] cmp esi, dword [esp] mov byte [edi],dl ; store result lea edi,[edi+1] jb .main_loop lea ebp, [ebp-12] ; pointer to context pop edx ; remove local variable dec eax ; actual new x counter mov byte [ebp+4], al ; update x counter mov byte [ebp+8], bl ; updtae y counter .quit: REST_GPR ret ENDFUNC ARCFourProcessData %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128ccmg9as.asm000066400000000000000000000205111470420105600263210ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; AuthEncrypt_RIJ128_AES_NI() ; DecryptAuth_RIJ128_AES_NI() ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ENCODE_DATA: u128_str DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 increment DQ 1,0 ;*************************************************************** ;* Purpose: Authenticate and Encrypt ;* ;* void AuthEncrypt_RIJ128_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp32u len, ;* Ipp8u* pLocalState) ;* inp localCtx: ;* MAC ;* CTRi ;* CTRi mask ;* ;* out localCtx: ;* new MAC ;* S = enc(CTRi) ;*************************************************************** ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128CCMEncrypt ;; Caller = ippsRijndael128CCMEncryptMessage ;; align IPP_ALIGN_FACTOR IPPASM AuthEncrypt_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi,ebx %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input blocks address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output blocks address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [esp + ARG_1 + 4*sizeof(dword)] ; length (bytes) %xdefine pLocCtx [esp + ARG_1 + 5*sizeof(dword)] ; pointer to the localState %assign BYTES_PER_BLK (16) mov eax, pLocCtx movdqa xmm0, oword [eax] ; MAC movdqa xmm2, oword [eax+sizeof(oword)] ; CTRi block movdqa xmm1, oword [eax+sizeof(oword)*2] ; CTR mask LD_ADDR eax, ENCODE_DATA movdqa xmm7, oword [eax+(u128_str-ENCODE_DATA)] pshufb xmm2, xmm7 ; CTRi block (LE) pshufb xmm1, xmm7 ; CTR mask movdqa xmm3, xmm1 pandn xmm3, xmm2 ; CTR block template pand xmm2, xmm1 ; CTR value mov edx, nr ; number of rounds mov ecx, pKey ; and keys lea edx, [edx*4] ; nrCounter = -nr*16 lea edx, [edx*4] ; pKey += nr*16 lea ecx, [ecx+edx] neg edx mov ebx, edx mov esi, pInpBlk mov edi, pOutBlk align IPP_ALIGN_FACTOR ;; ;; block-by-block processing ;; .blk_loop: movdqu xmm4, oword [esi] ; input block src[i] pxor xmm0, xmm4 ; MAC ^= src[i] movdqa xmm5, xmm3 paddq xmm2, oword [eax+(increment-ENCODE_DATA)] ; advance counter bits pand xmm2, xmm1 ; and mask them por xmm5, xmm2 pshufb xmm5, xmm7 ; CTRi (BE) movdqa xmm6, oword [ecx+edx] ; keys for whitening add edx, 16 pxor xmm5, xmm6 ; whitening (CTRi) pxor xmm0, xmm6 ; whitening (MAC) movdqa xmm6, oword [ecx+edx] ; pre load operation's keys align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm5, xmm6 ; regular round (CTRi) aesenc xmm0, xmm6 ; regular round (MAC) movdqa xmm6, oword [ecx+edx+16] add edx, 16 jnz .cipher_loop aesenclast xmm5, xmm6 ; irregular round (CTRi) aesenclast xmm0, xmm6 ; irregular round (MAC) pxor xmm4, xmm5 ; dst[i] = src[i] ^ ENC(CTRi) movdqu oword [edi], xmm4 mov edx, ebx add esi, BYTES_PER_BLK add edi, BYTES_PER_BLK sub dword len, BYTES_PER_BLK jnz .blk_loop mov eax, pLocCtx movdqu oword [eax], xmm0 ; update MAC value movdqu oword [eax+sizeof(oword)], xmm5 ; update ENC(Ctri) REST_GPR ret ENDFUNC AuthEncrypt_RIJ128_AES_NI ;*************************************************************** ;* Purpose: Decrypt and Authenticate ;* ;* void DecryptAuth_RIJ128_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp32u len, ;* Ipp8u* pLocalState) ;* inp localCtx: ;* MAC ;* CTRi ;* CTRi mask ;* ;* out localCtx: ;* new MAC ;* S = enc(CTRi) ;*************************************************************** ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128CCMDecrypt ;; Caller = ippsRijndael128CCMDecryptMessage ;; align IPP_ALIGN_FACTOR IPPASM DecryptAuth_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi,ebx %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input blocks address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output blocks address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [esp + ARG_1 + 4*sizeof(dword)] ; length (bytes) %xdefine pLocCtx [esp + ARG_1 + 5*sizeof(dword)] ; pointer to the localState %assign BYTES_PER_BLK (16) mov eax, pLocCtx movdqa xmm0, oword [eax] ; MAC movdqa xmm2, oword [eax+sizeof(oword)] ; CTRi block movdqa xmm1, oword [eax+sizeof(oword)*2] ; CTR mask LD_ADDR eax, ENCODE_DATA movdqa xmm7, oword [eax+(u128_str-ENCODE_DATA)] pshufb xmm2, xmm7 ; CTRi block (LE) pshufb xmm1, xmm7 ; CTR mask movdqa xmm3, xmm1 pandn xmm3, xmm2 ; CTR block template pand xmm2, xmm1 ; CTR value mov edx, nr ; number of rounds mov ecx, pKey ; and keys lea edx, [edx*4] ; nrCounter = -nr*16 lea edx, [edx*4] ; pKey += nr*16 lea ecx, [ecx+edx] neg edx mov ebx, edx mov esi, pInpBlk mov edi, pOutBlk align IPP_ALIGN_FACTOR ;; ;; block-by-block processing ;; .blk_loop: ;;;;;;;;;;;;;;;;; ;; decryption ;;;;;;;;;;;;;;;;; movdqu xmm4, oword [esi] ; input block src[i] movdqa xmm5, xmm3 paddq xmm2, oword [eax+(increment-ENCODE_DATA)] ; advance counter bits pand xmm2, xmm1 ; and mask them por xmm5, xmm2 pshufb xmm5, xmm7 ; CTRi (BE) movdqa xmm6, oword [ecx+edx] ; keys for whitening add edx, 16 pxor xmm5, xmm6 ; whitening (CTRi) movdqa xmm6, oword [ecx+edx] ; pre load operation's keys align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm5, xmm6 ; regular round (CTRi) movdqa xmm6, oword [ecx+edx+16] add edx, 16 jnz .cipher_loop aesenclast xmm5, xmm6 ; irregular round (CTRi) pxor xmm4, xmm5 ; dst[i] = src[i] ^ ENC(CTRi) movdqu oword [edi], xmm4 ;;;;;;;;;;;;;;;;; ;; update MAC ;;;;;;;;;;;;;;;;; mov edx, ebx movdqa xmm6, oword [ecx+edx] ; keys for whitening add edx, 16 pxor xmm0, xmm4 ; MAC ^= dst[i] pxor xmm0, xmm6 ; whitening (MAC) movdqa xmm6, oword [ecx+edx] ; pre load operation's keys align IPP_ALIGN_FACTOR .auth_loop: aesenc xmm0, xmm6 ; regular round (MAC) movdqa xmm6, oword [ecx+edx+16] add edx, 16 jnz .auth_loop aesenclast xmm0, xmm6 ; irregular round (MAC) mov edx, ebx add esi, BYTES_PER_BLK add edi, BYTES_PER_BLK sub dword len, BYTES_PER_BLK jnz .blk_loop mov eax, pLocCtx movdqu oword [eax], xmm0 ; update MAC value movdqu oword [eax+sizeof(oword)], xmm6 ; update ENC(Ctri) REST_GPR ret ENDFUNC DecryptAuth_RIJ128_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128cmacg9as.asm000066400000000000000000000064721470420105600264740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2018 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; cpAESCMAC_Update_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: AES-CMAC update ;* ;* void cpAESCMAC_Update_AES_NI(Ipp8u* digest, ;* const Ipp8u* input, ;* int inpLen, ;* int nr, ;* const Ipp32u* pRKey) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsAES_CMACUpdate ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM cpAESCMAC_Update_AES_NI,PUBLIC USES_GPR esi,edi %xdefine pDigest [esp + ARG_1 + 0*sizeof(dword)] ; input/output digest %xdefine pInpBlk [esp + ARG_1 + 1*sizeof(dword)] ; input blocks %xdefine len [esp + ARG_1 + 2*sizeof(dword)] ; length (bytes) %xdefine nr [esp + ARG_1 + 3*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 4*sizeof(dword)] ; key material address %xdefine SC (4) %assign BYTES_PER_BLK (16) mov edi, pDigest ; pointer to digest mov esi,pInpBlk ; input data address mov ecx,pKey ; key material address mov eax,nr ; number of rounds movdqu xmm0, oword [edi] ; digest mov edx, len ; length of stream align IPP_ALIGN_FACTOR ;; ;; block-by-block processing ;; .blks_loop: movdqu xmm1, oword [esi] ; input block movdqa xmm4, oword [ecx] ; preload key material pxor xmm0, xmm1 ; digest ^ src[] pxor xmm0, xmm4 ; whitening movdqa xmm4, oword [ecx+16] ; preload key material add ecx, 16 sub eax, 1 ; counter depending on key length align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm0, xmm4 ; regular round movdqa xmm4, oword [ecx+16] add ecx, 16 sub eax, 1 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round mov ecx, pKey ; restore key pointer mov eax, nr ; resrore number of rounds add esi, BYTES_PER_BLK ; advance pointers sub edx, BYTES_PER_BLK ; decrease counter jnz .blks_loop pxor xmm4, xmm4 movdqu oword [edi], xmm0 ; store output block REST_GPR ret ENDFUNC cpAESCMAC_Update_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128decryptcbcpipeg9as.asm000066400000000000000000000145631470420105600305710ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; DecryptCBC_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: pipelined RIJ128 CBC decryption ;* ;* void DecryptCBC_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len, ;* const Ipp8u* pIV) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = G9 ;; ;; Caller = ippsRijndael128DecryptCBC ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM DecryptCBC_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; length(byte) %xdefine pIV [ebp + ARG_1 + 5*sizeof(dword)] ; IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov ecx,pKey ; key material address mov eax,nr ; number of rounds sub esp, 16*(1+4+1) ; allocate stack lea edx, [esp+16] and edx, -16 mov ebx, pIV movdqu xmm4, oword [ebx] ; save IV movdqa oword [edx+0*16], xmm4 ; into the stack sub dword len, BYTES_PER_LOOP jl .short_input lea ebx,[eax*SC] ; keys offset lea ecx,[ecx+ebx*4] ;; ;; pipelined processing ;; .blks_loop: movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [ecx-16] ; set pointer to the round's key material movdqu xmm0, oword [esi+0*BYTES_PER_BLK] ; get input blocks movdqu xmm1, oword [esi+1*BYTES_PER_BLK] movdqu xmm2, oword [esi+2*BYTES_PER_BLK] movdqu xmm3, oword [esi+3*BYTES_PER_BLK] movdqa oword [edx+1*16], xmm0 ; and save as IVx movdqa oword [edx+2*16], xmm1 ; for next operations movdqa oword [edx+3*16], xmm2 ; into the stack movdqa oword [edx+4*16], xmm3 pxor xmm0, xmm4 ;whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys sub ebx, 16 mov eax, nr ; counter depending on key length sub eax, 1 .cipher_loop: aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys sub ebx, 16 dec eax jnz .cipher_loop aesdeclast xmm0, xmm4 ; irregular round and IV pxor xmm0, oword [edx+0*16] ; xor with IV movdqu oword [edi+0*16], xmm0 ; and store output blocls aesdeclast xmm1, xmm4 pxor xmm1, oword [edx+1*16] movdqu oword [edi+1*16], xmm1 aesdeclast xmm2, xmm4 pxor xmm2, oword [edx+2*16] movdqu oword [edi+2*16], xmm2 aesdeclast xmm3, xmm4 pxor xmm3, oword [edx+3*16] movdqu oword [edi+3*16], xmm3 movdqa xmm4, oword [edx+4*16] ; update IV movdqa oword [edx+0*16], xmm4 add esi, BYTES_PER_LOOP add edi, BYTES_PER_LOOP sub dword len, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add dword len, BYTES_PER_LOOP jz .quit mov eax, nr mov ecx, pKey lea ebx,[eax*SC] ; set pointer to the key material lea ebx,[ecx+ebx*4] .single_blk_loop: movdqu xmm0, oword [esi] ; get input block movdqa oword [edx+16], xmm0 ; and save as IV for future pxor xmm0, oword [ebx] ; whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesdec xmm0, oword [ecx+9*SC*4+4*SC*4] aesdec xmm0, oword [ecx+9*SC*4+3*SC*4] .key_192_s: aesdec xmm0, oword [ecx+9*SC*4+2*SC*4] aesdec xmm0, oword [ecx+9*SC*4+1*SC*4] .key_128_s: aesdec xmm0, oword [ecx+9*SC*4-0*SC*4] aesdec xmm0, oword [ecx+9*SC*4-1*SC*4] aesdec xmm0, oword [ecx+9*SC*4-2*SC*4] aesdec xmm0, oword [ecx+9*SC*4-3*SC*4] aesdec xmm0, oword [ecx+9*SC*4-4*SC*4] aesdec xmm0, oword [ecx+9*SC*4-5*SC*4] aesdec xmm0, oword [ecx+9*SC*4-6*SC*4] aesdec xmm0, oword [ecx+9*SC*4-7*SC*4] aesdec xmm0, oword [ecx+9*SC*4-8*SC*4] aesdeclast xmm0, oword [ecx+9*SC*4-9*SC*4] pxor xmm0, oword [edx+0*16] ; add IV movdqu oword [edi], xmm0 ; and save output blocl movdqa xmm4, oword [edx+1*16] ; update IV movdqa oword [edx+0*16], xmm4 add esi, BYTES_PER_BLK add edi, BYTES_PER_BLK sub dword len, BYTES_PER_BLK jnz .single_blk_loop .quit: add esp, 16*(1+4+1) ; free stack REST_GPR ret ENDFUNC DecryptCBC_RIJ128pipe_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128decryptcfbpipeg9as.asm000066400000000000000000000416311470420105600305700ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Decrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %macro COPY_8U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_byte: mov %%tmp, byte [%%src+ecx] mov byte [%%dst+ecx], %%tmp add ecx, 1 cmp ecx, %%limit jl %%next_byte %endmacro %macro COPY_32U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_dword: mov %%tmp, dword [%%src+ecx] mov dword [%%dst+ecx], %%tmp add ecx, 4 cmp ecx, %%limit jl %%next_dword %endmacro %macro COPY_128U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_oword: movdqu %%tmp, oword [%%src+ecx] movdqu oword [%%dst+ecx], %%tmp add ecx, 16 cmp ecx, %%limit jl %%next_oword %endmacro ;*************************************************************** ;* Purpose: pipelined RIJ128 CFB decryption ;* ;* void DecryptCFB_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int cfbBlks, ;* int cfbSize, ;* const Ipp8u* pIV) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128DecryptCFB ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM DecryptCFB_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine cfbBlks [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in cfbSize %xdefine cfbSize [ebp + ARG_1 + 5*sizeof(dword)] ; cfb blk size %xdefine pIV [ebp + ARG_1 + 6*sizeof(dword)] ; IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) sub esp,16*(1+4+4) ; allocate stask: ; +0*16 IV ; +1*16 inp0, inp1, inp2, inp3 ; +5*16 out0, out1, out2, out3 mov eax, pIV ; IV address movdqu xmm4, oword [eax] ; get IV movdqu oword [esp+0*16], xmm4 ; into the stack mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov edx,cfbSize ; size of block sub dword cfbBlks, BLKS_PER_LOOP jl .short_input ;; ;; pipelined processing ;; .blks_loop: lea eax, [edx*BLKS_PER_LOOP] COPY_32U {esp+16}, esi, eax, ebx ; move 4 input blocks to stack mov ecx, pKey movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [edx+edx*2] movdqu xmm0, oword [esp] ; get encoded blocks movdqu xmm1, oword [esp+edx] movdqu xmm2, oword [esp+edx*2] movdqu xmm3, oword [esp+ebx] lea ebx, [ecx+16] ; pointer to the round's key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys add ebx, 16 mov eax, nr ; counter depending on key length sub eax, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys add ebx, 16 dec eax jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round and IV aesenclast xmm1, xmm4 aesenclast xmm2, xmm4 aesenclast xmm3, xmm4 lea ebx, [edx+edx*2] ; get src blocks from the stack movdqu xmm4, oword [esp+16] movdqu xmm5, oword [esp+16+edx] movdqu xmm6, oword [esp+16+edx*2] movdqu xmm7, oword [esp+16+ebx] pxor xmm0, xmm4 ; xor src movdqu oword [esp+5*16],xmm0;and store into the stack pxor xmm1, xmm5 movdqu oword [esp+5*16+edx], xmm1 pxor xmm2, xmm6 movdqu oword [esp+5*16+edx*2], xmm2 pxor xmm3, xmm7 movdqu oword [esp+5*16+ebx], xmm3 lea eax, [edx*BLKS_PER_LOOP] COPY_32U edi, {esp+5*16}, eax, ebx ; move 4 blocks to output movdqu xmm0, oword [esp+eax] ; update IV movdqu oword [esp], xmm0 add esi, eax add edi, eax sub dword cfbBlks, BLKS_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add dword cfbBlks, BLKS_PER_LOOP jz .quit lea ebx, [edx*2] lea ecx, [edx+edx*2] cmp dword cfbBlks, 2 cmovl ebx, edx cmovg ebx, ecx COPY_8U {esp+16}, esi, ebx, al ; move recent input blocks to stack ; get actual address of key material: pRKeys += (nr-9) * SC mov ecx, pKey mov eax, nr lea esi,[eax*4] lea esi, [ecx+esi*4-9*(SC)*4] ; AES-128 round keys xor eax, eax ; index .single_blk_loop: movdqu xmm0, oword [esp+eax] ; get encoded block pxor xmm0, oword [ecx] ; whitening cmp dword nr, 12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0, oword [esi-4*4*SC] aesenc xmm0, oword [esi-3*4*SC] .key_192_s: aesenc xmm0, oword [esi-2*4*SC] aesenc xmm0, oword [esi-1*4*SC] .key_128_s: aesenc xmm0, oword [esi+0*4*SC] aesenc xmm0, oword [esi+1*4*SC] aesenc xmm0, oword [esi+2*4*SC] aesenc xmm0, oword [esi+3*4*SC] aesenc xmm0, oword [esi+4*4*SC] aesenc xmm0, oword [esi+5*4*SC] aesenc xmm0, oword [esi+6*4*SC] aesenc xmm0, oword [esi+7*4*SC] aesenc xmm0, oword [esi+8*4*SC] aesenclast xmm0, oword [esi+9*4*SC] movdqu xmm1, oword [esp+eax+16] ; get input block from the stack pxor xmm0, xmm1 ; xor src movdqu oword [esp+5*16+eax], xmm0 ; and save output add eax, edx dec dword cfbBlks jnz .single_blk_loop COPY_8U edi, {esp+5*16}, ebx, al ; copy rest output from the stack .quit: add esp, 16*(1+4+4) ; free stack REST_GPR ret ENDFUNC DecryptCFB_RIJ128pipe_AES_NI align IPP_ALIGN_FACTOR IPPASM DecryptCFB32_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine cfbBlks [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in cfbSize %xdefine cfbSize [ebp + ARG_1 + 5*sizeof(dword)] ; cfb blk size (4 bytes multiple) %xdefine pIV [ebp + ARG_1 + 6*sizeof(dword)] ; IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) sub esp,16*(1+4+4) ; allocate stask: ; +0*16 IV ; +1*16 inp0, inp1, inp2, inp3 ; +5*16 out0, out1, out2, out3 mov eax, pIV ; IV address movdqu xmm4, oword [eax] ; get IV movdqu oword [esp+0*16], xmm4 ; into the stack mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov edx,cfbSize ; size of block sub dword cfbBlks, BLKS_PER_LOOP jl .short_input ;; ;; pipelined processing ;; .blks_loop: lea eax, [edx*BLKS_PER_LOOP] COPY_128U {esp+16}, esi, eax, xmm0 ; move 4 input blocks to stack mov ecx, pKey movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [edx+edx*2] movdqu xmm0, oword [esp] ; get encoded blocks movdqu xmm1, oword [esp+edx] movdqu xmm2, oword [esp+edx*2] movdqu xmm3, oword [esp+ebx] lea ebx, [ecx+16] ; pointer to the round's key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys add ebx, 16 mov eax, nr ; counter depending on key length sub eax, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys add ebx, 16 dec eax jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round and IV aesenclast xmm1, xmm4 aesenclast xmm2, xmm4 aesenclast xmm3, xmm4 lea ebx, [edx+edx*2] ; get src blocks from the stack movdqu xmm4, oword [esp+16] movdqu xmm5, oword [esp+16+edx] movdqu xmm6, oword [esp+16+edx*2] movdqu xmm7, oword [esp+16+ebx] pxor xmm0, xmm4 ; xor src movdqu oword [esp+5*16],xmm0;and store into the stack pxor xmm1, xmm5 movdqu oword [esp+5*16+edx], xmm1 pxor xmm2, xmm6 movdqu oword [esp+5*16+edx*2], xmm2 pxor xmm3, xmm7 movdqu oword [esp+5*16+ebx], xmm3 lea eax, [edx*BLKS_PER_LOOP] COPY_128U edi, {esp+5*16}, eax, xmm0 ; move 4 blocks to output movdqu xmm0, oword [esp+eax] ; update IV movdqu oword [esp], xmm0 add esi, eax add edi, eax sub dword cfbBlks, BLKS_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add dword cfbBlks, BLKS_PER_LOOP jz .quit lea ebx, [edx*2] lea ecx, [edx+edx*2] cmp dword cfbBlks, 2 cmovl ebx, edx cmovg ebx, ecx COPY_32U {esp+16}, esi, ebx, eax ; move recent input blocks to stack ; get actual address of key material: pRKeys += (nr-9) * SC mov ecx, pKey mov eax, nr lea esi,[eax*4] lea esi, [ecx+esi*4-9*(SC)*4] ; AES-128 round keys xor eax, eax ; index .single_blk_loop: movdqu xmm0, oword [esp+eax] ; get encoded block pxor xmm0, oword [ecx] ; whitening cmp dword nr, 12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0, oword [esi-4*4*SC] aesenc xmm0, oword [esi-3*4*SC] .key_192_s: aesenc xmm0, oword [esi-2*4*SC] aesenc xmm0, oword [esi-1*4*SC] .key_128_s: aesenc xmm0, oword [esi+0*4*SC] aesenc xmm0, oword [esi+1*4*SC] aesenc xmm0, oword [esi+2*4*SC] aesenc xmm0, oword [esi+3*4*SC] aesenc xmm0, oword [esi+4*4*SC] aesenc xmm0, oword [esi+5*4*SC] aesenc xmm0, oword [esi+6*4*SC] aesenc xmm0, oword [esi+7*4*SC] aesenc xmm0, oword [esi+8*4*SC] aesenclast xmm0, oword [esi+9*4*SC] movdqu xmm1, oword [esp+eax+16] ; get input block from the stack pxor xmm0, xmm1 ; xor src movdqu oword [esp+5*16+eax], xmm0 ; and save output add eax, edx dec dword cfbBlks jnz .single_blk_loop COPY_32U edi, {esp+5*16}, ebx, eax ; copy rest output from the stack .quit: add esp, 16*(1+4+4) ; free stack REST_GPR ret ENDFUNC DecryptCFB32_RIJ128pipe_AES_NI ;; ;; Lib = G9 ;; ;; Caller = ippsRijndael128DecryptCFB ;; align IPP_ALIGN_FACTOR IPPASM DecryptCFB128_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in bytes %xdefine pIV [ebp + ARG_1 + 5*sizeof(dword)] ; IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov ecx,pKey ; keys mov edx, len mov eax, pIV movdqu xmm0, oword [eax] ; get IV sub edx, BYTES_PER_LOOP ; test length of the stream jl .short_input ;; ;; pipelined processing ;; .blks_loop: movdqa xmm7, oword [ecx] ; keys for whitening lea ebx, [ecx+16] ; pointer to the round's key material movdqu xmm1, oword [esi+0*BYTES_PER_BLK] ; get another encoded cblocks movdqu xmm2, oword [esi+1*BYTES_PER_BLK] movdqu xmm3, oword [esi+2*BYTES_PER_BLK] pxor xmm0, xmm7 ; whitening pxor xmm1, xmm7 pxor xmm2, xmm7 pxor xmm3, xmm7 movdqa xmm7, oword [ebx] ; pre load operation's keys add ebx, 16 mov eax, nr ; counter depending on key length sub eax, 1 .cipher_loop: aesenc xmm0, xmm7 ; regular round aesenc xmm1, xmm7 aesenc xmm2, xmm7 aesenc xmm3, xmm7 movdqa xmm7, oword [ebx] ; pre load operation's keys add ebx, 16 dec eax jnz .cipher_loop aesenclast xmm0, xmm7 ; irregular round and IV for 4 input blocks movdqu xmm4, oword [esi+0*BYTES_PER_BLK] aesenclast xmm1, xmm7 movdqu xmm5, oword [esi+1*BYTES_PER_BLK] aesenclast xmm2, xmm7 movdqu xmm6, oword [esi+2*BYTES_PER_BLK] aesenclast xmm3, xmm7 movdqu xmm7, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_LOOP pxor xmm0, xmm4 ; 4 output blocks movdqu oword [edi+0*BYTES_PER_BLK], xmm0 pxor xmm1, xmm5 movdqu oword [edi+1*BYTES_PER_BLK], xmm1 pxor xmm2, xmm6 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 pxor xmm3, xmm7 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 add edi, BYTES_PER_LOOP movdqa xmm0, xmm7 ; update IV sub edx, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add edx, BYTES_PER_LOOP jz .quit ; get actual address of key material: pRKeys += (nr-9) * SC mov eax, nr lea ebx,[eax*4] lea ebx, [ecx+ebx*4-9*(SC)*4] ; AES-128 round keys .single_blk_loop: pxor xmm0, oword [ecx] ; whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0, oword [ebx-4*4*SC] aesenc xmm0, oword [ebx-3*4*SC] .key_192_s: aesenc xmm0, oword [ebx-2*4*SC] aesenc xmm0, oword [ebx-1*4*SC] .key_128_s: aesenc xmm0, oword [ebx+0*4*SC] aesenc xmm0, oword [ebx+1*4*SC] aesenc xmm0, oword [ebx+2*4*SC] aesenc xmm0, oword [ebx+3*4*SC] aesenc xmm0, oword [ebx+4*4*SC] aesenc xmm0, oword [ebx+5*4*SC] aesenc xmm0, oword [ebx+6*4*SC] aesenc xmm0, oword [ebx+7*4*SC] aesenc xmm0, oword [ebx+8*4*SC] aesenclast xmm0, oword [ebx+9*4*SC] movdqu xmm1, oword [esi] ; input block from the stream add esi, BYTES_PER_BLK pxor xmm0, xmm1 ; xor src movdqu oword [edi], xmm0 ; and save output add edi, BYTES_PER_BLK movdqa xmm0, xmm1 ; update IV sub edx, BYTES_PER_BLK jnz .single_blk_loop .quit: REST_GPR ret ENDFUNC DecryptCFB128_RIJ128pipe_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128decryptecbpipeg9as.asm000066400000000000000000000124351470420105600305670ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; DecryptECB_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: pipelined RIJ128 ECB decryption ;* ;* void DecryptECB_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128DecryptECB ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM DecryptECB_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [esp + ARG_1 + 4*sizeof(dword)] ; length(byte) %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov ecx,pKey ; key material address mov edx,len ; length mov eax,nr ; number of rounds sub edx, BYTES_PER_LOOP jl .short_input lea ebx,[eax*SC] ; keys offset lea ecx,[ecx+ebx*4] ;; ;; pipelined processing ;; .blks_loop: movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [ecx-16] ; set pointer to the round's key material movdqu xmm0, oword [esi+0*BYTES_PER_BLK] ; get input blocks movdqu xmm1, oword [esi+1*BYTES_PER_BLK] movdqu xmm2, oword [esi+2*BYTES_PER_BLK] movdqu xmm3, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_LOOP pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load round keys sub ebx, 16 mov eax, nr ; counter depending on key length sub eax, 1 .cipher_loop: aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load operation's keys sub ebx, 16 dec eax jnz .cipher_loop aesdeclast xmm0, xmm4 ; irregular round movdqu oword [edi+0*BYTES_PER_BLK], xmm0 ; store output blocks aesdeclast xmm1, xmm4 movdqu oword [edi+1*BYTES_PER_BLK], xmm1 aesdeclast xmm2, xmm4 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 aesdeclast xmm3, xmm4 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 add edi, BYTES_PER_LOOP sub edx, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add edx, BYTES_PER_LOOP jz .quit mov eax, nr mov ecx, pKey lea ebx,[eax*SC] ; set pointer to the key material lea ebx,[ecx+ebx*4] .single_blk_loop: movdqu xmm0, oword [esi] ; get input block add esi, BYTES_PER_BLK pxor xmm0, oword [ebx] ; whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesdec xmm0, oword [ecx+9*SC*4+4*SC*4] aesdec xmm0, oword [ecx+9*SC*4+3*SC*4] .key_192_s: aesdec xmm0, oword [ecx+9*SC*4+2*SC*4] aesdec xmm0, oword [ecx+9*SC*4+1*SC*4] .key_128_s: aesdec xmm0, oword [ecx+9*SC*4-0*SC*4] aesdec xmm0, oword [ecx+9*SC*4-1*SC*4] aesdec xmm0, oword [ecx+9*SC*4-2*SC*4] aesdec xmm0, oword [ecx+9*SC*4-3*SC*4] aesdec xmm0, oword [ecx+9*SC*4-4*SC*4] aesdec xmm0, oword [ecx+9*SC*4-5*SC*4] aesdec xmm0, oword [ecx+9*SC*4-6*SC*4] aesdec xmm0, oword [ecx+9*SC*4-7*SC*4] aesdec xmm0, oword [ecx+9*SC*4-8*SC*4] aesdeclast xmm0, oword [ecx+9*SC*4-9*SC*4] movdqu oword [edi], xmm0 ; save output block add edi, BYTES_PER_BLK sub edx, BYTES_PER_BLK jnz .single_blk_loop .quit: REST_GPR ret ENDFUNC DecryptECB_RIJ128pipe_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128decryptg9as.asm000066400000000000000000000062471470420105600272430ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Decrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: single block RIJ128 Inverse Cipher ;* ;* void Encrypt_RIJ128(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* const Ipp32u Tables[][256]) ;* ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128DecryptECB ;; Caller = ippsRijndael128DecryptCBC ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM Decrypt_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine SC (4) mov esi,pInpBlk ; input data address mov ecx,pKey ; key material address mov eax,nr ; number of rounds mov edi,pOutBlk ; output data address lea edx,[eax*4] movdqu xmm0, oword [esi] ; input block ;;whitening pxor xmm0, oword [ecx+edx*4] ; whitening cmp eax,12 ; switch according to number of rounds jl .key_128 jz .key_192 ;; ;; regular rounds ;; .key_256: aesdec xmm0,oword [ecx+9*SC*4+4*4*SC] aesdec xmm0,oword [ecx+9*SC*4+3*4*SC] .key_192: aesdec xmm0,oword [ecx+9*SC*4+2*4*SC] aesdec xmm0,oword [ecx+9*SC*4+1*4*SC] .key_128: aesdec xmm0,oword [ecx+9*SC*4-0*4*SC] aesdec xmm0,oword [ecx+9*SC*4-1*4*SC] aesdec xmm0,oword [ecx+9*SC*4-2*4*SC] aesdec xmm0,oword [ecx+9*SC*4-3*4*SC] aesdec xmm0,oword [ecx+9*SC*4-4*4*SC] aesdec xmm0,oword [ecx+9*SC*4-5*4*SC] aesdec xmm0,oword [ecx+9*SC*4-6*4*SC] aesdec xmm0,oword [ecx+9*SC*4-7*4*SC] aesdec xmm0,oword [ecx+9*SC*4-8*4*SC] ;; ;; last rounds ;; aesdeclast xmm0,oword [ecx+9*SC*4-9*4*SC] movdqu oword [edi], xmm0 ; output block REST_GPR ret ENDFUNC Decrypt_RIJ128_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128decryptxtsg9as.asm000066400000000000000000000172131470420105600277750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; AES function ; ; Content: ; cpAESDecryptXTS_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %macro MUL_X 4.nolist %xdefine %%y %1 %xdefine %%x %2 %xdefine %%t %3 %xdefine %%cnt %4 pxor %%t, %%t movdqa %%y, %%x pcmpgtq %%t, %%x paddq %%y, %%y palignr %%t, %%t, sizeof(qword) pand %%t, %%cnt pxor %%y, %%t %endmacro ;*************************************************************** ;* Purpose: AES-XTS decryption ;* ;* void cpAESDecryptXTS_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int length, ;* const Ipp8u* pRKey, ;* int nr, ;* const Ipp8u* pTweak) ;*************************************************************** %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsAESDecryptXTS ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM cpAESDecryptXTS_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pOutBlk [ebp + ARG_1 + 0*sizeof(dword)] ; output block address %xdefine pInpBlk [ebp + ARG_1 + 1*sizeof(dword)] ; input block address %xdefine blks [ebp + ARG_1 + 2*sizeof(dword)] ; length(blocks) %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine nr [ebp + ARG_1 + 4*sizeof(dword)] ; number of rounds %xdefine pTweak [ebp + ARG_1 + 5*sizeof(dword)] ; tweaks %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address ; ; stack layout: ; %assign _tweakCnt 0 ; constant %assign _tweak0 _tweakCnt+sizeof(oword) ; * alpha %assign _tweak1 _tweak0+sizeof(oword) ; * alpha^2 %assign _tweak2 _tweak1+sizeof(oword) ; * alpha^3 %assign _tweak3 _tweak2+sizeof(oword) ; * alpha^4 %assign _tkey _tweak3+sizeof(oword) ; decryption keys (top) %assign _bkey _tkey+sizeof(dword) ; decryption keys (bottom) %assign _nr _bkey+sizeof(dword) ; # rounds %assign _sp _nr+sizeof(dword) ; esp %assign stackSize _sp+sizeof(dword) ; stack size mov eax, esp sub esp, stackSize ; aligned stack and esp, (-16) mov dword [esp+_sp], eax ; store esp mov eax, pTweak movdqu xmm4, oword [eax] ; initial tweak movdqa xmm7, xmm4 mov eax, 087h ; create tweakCnt = {0x01:0x87} mov ecx, 1 movd xmm0, eax movd xmm1, ecx punpcklqdq xmm0, xmm1 mov ecx,pKey ; key material address mov eax,nr ; num of rounds mov edx,blks ; num of blocks ; move parameters to local stack frame movdqa oword [esp+_tweakCnt], xmm0 mov dword [esp+_tkey], ecx lea ebx, [eax*SC] lea ecx, [ecx+ebx*sizeof(dword)] mov dword [esp+_bkey], ecx mov dword [esp+_nr], eax sub edx, BLKS_PER_LOOP jl .short_input jmp .blks_loop_ep ;; ;; pipelined processing ;; .blks_loop: MUL_X xmm4, xmm7, xmm1, xmm0 .blks_loop_ep: movdqa oword [esp+_tweak0], xmm4 MUL_X xmm5, xmm4, xmm1, xmm0 movdqa oword [esp+_tweak1], xmm5 MUL_X xmm6, xmm5, xmm1, xmm0 movdqa oword [esp+_tweak2], xmm6 MUL_X xmm7, xmm6, xmm1, xmm0 movdqa oword [esp+_tweak3], xmm7 movdqu xmm0, oword [esi+0*BYTES_PER_BLK] ; get input blocks movdqu xmm1, oword [esi+1*BYTES_PER_BLK] movdqu xmm2, oword [esi+2*BYTES_PER_BLK] movdqu xmm3, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_BLK*BLKS_PER_LOOP pxor xmm0, xmm4 ; tweak pre-whitening pxor xmm1, xmm5 pxor xmm2, xmm6 pxor xmm3, xmm7 movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [ecx-BYTES_PER_BLK]; pointer to the round's key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load round keys sub ebx, BYTES_PER_BLK sub eax, 1 .cipher_loop: aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 movdqa xmm4, oword [ebx] sub ebx, BYTES_PER_BLK dec eax jnz .cipher_loop aesdeclast xmm0, xmm4 ; irregular round aesdeclast xmm1, xmm4 aesdeclast xmm2, xmm4 aesdeclast xmm3, xmm4 movdqa xmm4, oword [esp+_tweak0] ; tweak post-whitening movdqa xmm5, oword [esp+_tweak1] movdqa xmm6, oword [esp+_tweak2] movdqa xmm7, oword [esp+_tweak3] pxor xmm0, xmm4 pxor xmm1, xmm5 pxor xmm2, xmm6 pxor xmm3, xmm7 movdqu oword [edi+0*BYTES_PER_BLK], xmm0 ; store output blocks movdqu oword [edi+1*BYTES_PER_BLK], xmm1 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 add edi, BYTES_PER_BLK*BLKS_PER_LOOP movdqa xmm0, oword [esp+_tweakCnt] ; restore tweak const mov eax, dword [esp+_nr] ; number of rounds sub edx, BLKS_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add edx, BLKS_PER_LOOP jz .quit mov ecx, dword [esp+_tkey] mov ebx, dword [esp+_bkey] mov eax, dword [esp+_nr] jmp .single_blk_loop_ep .single_blk_loop: MUL_X xmm7, xmm7, xmm1, xmm0 .single_blk_loop_ep: movdqu xmm1, oword [esi] ; input block add esi, BYTES_PER_BLK pxor xmm1, xmm7 ; tweak pre-whitening pxor xmm1, oword [ebx] ; AES whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s .key_256_s: aesdec xmm1,oword [ecx+9*SC*4+4*SC*4] aesdec xmm1,oword [ecx+9*SC*4+3*SC*4] aesdec xmm1,oword [ecx+9*SC*4+2*SC*4] aesdec xmm1,oword [ecx+9*SC*4+1*SC*4] .key_128_s: aesdec xmm1,oword [ecx+9*SC*4-0*SC*4] aesdec xmm1,oword [ecx+9*SC*4-1*SC*4] aesdec xmm1,oword [ecx+9*SC*4-2*SC*4] aesdec xmm1,oword [ecx+9*SC*4-3*SC*4] aesdec xmm1,oword [ecx+9*SC*4-4*SC*4] aesdec xmm1,oword [ecx+9*SC*4-5*SC*4] aesdec xmm1,oword [ecx+9*SC*4-6*SC*4] aesdec xmm1,oword [ecx+9*SC*4-7*SC*4] aesdec xmm1,oword [ecx+9*SC*4-8*SC*4] aesdeclast xmm1,oword [ecx+9*SC*4-9*SC*4] pxor xmm1, xmm7 ; tweak post-whitening movdqu oword [edi], xmm1 ; output block add edi, BYTES_PER_BLK sub edx, 1 jnz .single_blk_loop .quit: mov eax, pTweak ; save tweak movdqu oword [eax], xmm7 mov esp, [esp+_sp] REST_GPR ret ENDFUNC cpAESDecryptXTS_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptcbcg9as.asm000066400000000000000000000070011470420105600277120ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptCBC_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: RIJ128 CBC encryption ;* ;* void EncryptCBC_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len, ;* const Ipp8u* pIV) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128EncryptCBC ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM EncryptCBC_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [esp + ARG_1 + 4*sizeof(dword)] ; length (bytes) %xdefine pIV [esp + ARG_1 + 5*sizeof(dword)] ; IV %xdefine SC (4) %assign BYTES_PER_BLK (16) mov edx, pIV ; IV address mov esi,pInpBlk ; input data address mov ecx,pKey ; key material address mov eax,nr ; number of rounds mov edi,pOutBlk ; output data address movdqu xmm0, oword [edx] ; IV mov edx, len ; length of stream align IPP_ALIGN_FACTOR ;; ;; block-by-block processing ;; .blks_loop: movdqu xmm1, oword [esi] ; input block movdqa xmm4, oword [ecx] ; preload key material pxor xmm0, xmm1 ; src[] ^ iv pxor xmm0, xmm4 ; whitening movdqa xmm4, oword [ecx+16] ; preload key material add ecx, 16 sub eax, 1 ; counter depending on key length align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm0, xmm4 ; regular round movdqa xmm4, oword [ecx+16] add ecx, 16 sub eax, 1 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round movdqu oword [edi], xmm0 ; store output block mov ecx, pKey ; restore key pointer mov eax, nr ; resrore number of rounds add esi, BYTES_PER_BLK ; advance pointers add edi, BYTES_PER_BLK sub edx, BYTES_PER_BLK ; decrease counter jnz .blks_loop REST_GPR ret ENDFUNC EncryptCBC_RIJ128_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptcfbg9as.asm000066400000000000000000000260731470420105600277270ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Encrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %macro COPY_8U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_byte: mov %%tmp, byte [%%src+ecx] mov byte [%%dst+ecx], %%tmp add ecx, 1 cmp ecx, %%limit jl %%next_byte %endmacro %macro COPY_32U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_dword: mov %%tmp, dword [%%src+ecx] mov dword [%%dst+ecx], %%tmp add ecx, 4 cmp ecx, %%limit jl %%next_dword %endmacro %macro COPY_128U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_oword: movdqu %%tmp, oword [%%src+ecx] movdqu oword [%%dst+ecx], %%tmp add ecx, 16 cmp ecx, %%limit jl %%next_oword %endmacro ;*************************************************************** ;* Purpose: RIJ128 CFB encryption ;* ;* void EncryptCFB_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len, ;* int cfbSize, ;* const Ipp8u* pIV) ;*************************************************************** %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128EncryptCFB ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM EncryptCFB_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input blocks address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output blocks address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in bytes %xdefine cfbSize [ebp + ARG_1 + 5*sizeof(dword)] ; cfb blk size %xdefine pIV [ebp + ARG_1 + 6*sizeof(dword)] ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) sub esp,16*(1+4+4) ; allocate stask: ; +0*16 IV ; +1*16 inp0, inp1, inp2, inp3 ; +5*16 out0, out1, out2, out3 mov eax, pIV ; IV address movdqu xmm4, oword [eax] ; get IV movdqu oword [esp+0*16], xmm4 ; into the stack ;; ;; processing ;; .blks_loop: mov esi,pInpBlk ; input data address mov edx,cfbSize ; size of block lea ebx, [edx*BLKS_PER_LOOP] ; 4 cfb block mov edx, len cmp edx, ebx cmovl ebx, edx COPY_8U {esp+5*16}, esi, ebx, dl ; move 1-4 input blocks to stack ; get actual address of key material: pRKeys += (nr-9) * SC mov ecx, pKey mov edx, nr lea eax,[edx*4] lea eax, [ecx+eax*4-9*(SC)*4] ; AES-128 round keys xor esi, esi ; index mov edi, ebx .single_blk: movdqu xmm0, oword [esp+esi] ; get processing blocks pxor xmm0, oword [ecx] ; whitening cmp edx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [eax-4*4*SC] aesenc xmm0, oword [eax-3*4*SC] .key_192_s: aesenc xmm0, oword [eax-2*4*SC] aesenc xmm0, oword [eax-1*4*SC] .key_128_s: aesenc xmm0, oword [eax+0*4*SC] aesenc xmm0, oword [eax+1*4*SC] aesenc xmm0, oword [eax+2*4*SC] aesenc xmm0, oword [eax+3*4*SC] aesenc xmm0, oword [eax+4*4*SC] aesenc xmm0, oword [eax+5*4*SC] aesenc xmm0, oword [eax+6*4*SC] aesenc xmm0, oword [eax+7*4*SC] aesenc xmm0, oword [eax+8*4*SC] aesenclast xmm0, oword [eax+9*4*SC] movdqu xmm1, oword [esp+5*16+esi] ; get src blocks from the stack pxor xmm0, xmm1 ; xor src movdqu oword [esp+1*16+esi],xmm0 ;and store into the stack add esi, cfbSize ; advance index sub edi, cfbSize ; decrease length jg .single_blk mov edi,pOutBlk ; output data address COPY_8U edi, {esp+1*16}, ebx, dl ; move 1-4 blocks to output movdqu xmm0, oword [esp+ebx]; update IV movdqu oword [esp], xmm0 add pInpBlk, ebx add pOutBlk, ebx sub len, ebx jg .blks_loop add esp, 16*(1+4+4) REST_GPR ret ENDFUNC EncryptCFB_RIJ128_AES_NI align IPP_ALIGN_FACTOR IPPASM EncryptCFB32_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input blocks address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output blocks address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in bytes %xdefine cfbSize [ebp + ARG_1 + 5*sizeof(dword)] ; cfb blk size %xdefine pIV [ebp + ARG_1 + 6*sizeof(dword)] ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) sub esp,16*(1+4+4) ; allocate stask: ; +0*16 IV ; +1*16 inp0, inp1, inp2, inp3 ; +5*16 out0, out1, out2, out3 mov eax, pIV ; IV address movdqu xmm4, oword [eax] ; get IV movdqu oword [esp+0*16], xmm4 ; into the stack ;; ;; processing ;; .blks_loop: mov esi,pInpBlk ; input data address mov edx,cfbSize ; size of block lea ebx, [edx*BLKS_PER_LOOP] ; 4 cfb block mov edx, len cmp edx, ebx cmovl ebx, edx COPY_32U {esp+5*16}, esi, ebx, edx ; move 1-4 input blocks to stack ; get actual address of key material: pRKeys += (nr-9) * SC mov ecx, pKey mov edx, nr lea eax,[edx*4] lea eax, [ecx+eax*4-9*(SC)*4] ; AES-128 round keys xor esi, esi ; index mov edi, ebx .single_blk: movdqu xmm0, oword [esp+esi] ; get processing blocks pxor xmm0, oword [ecx] ; whitening cmp edx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [eax-4*4*SC] aesenc xmm0, oword [eax-3*4*SC] .key_192_s: aesenc xmm0, oword [eax-2*4*SC] aesenc xmm0, oword [eax-1*4*SC] .key_128_s: aesenc xmm0, oword [eax+0*4*SC] aesenc xmm0, oword [eax+1*4*SC] aesenc xmm0, oword [eax+2*4*SC] aesenc xmm0, oword [eax+3*4*SC] aesenc xmm0, oword [eax+4*4*SC] aesenc xmm0, oword [eax+5*4*SC] aesenc xmm0, oword [eax+6*4*SC] aesenc xmm0, oword [eax+7*4*SC] aesenc xmm0, oword [eax+8*4*SC] aesenclast xmm0, oword [eax+9*4*SC] movdqu xmm1, oword [esp+5*16+esi] ; get src blocks from the stack pxor xmm0, xmm1 ; xor src movdqu oword [esp+1*16+esi],xmm0 ;and store into the stack add esi, cfbSize ; advance index sub edi, cfbSize ; decrease length jg .single_blk mov edi,pOutBlk ; output data address COPY_32U edi, {esp+1*16}, ebx, edx ; move 1-4 blocks to output movdqu xmm0, oword [esp+ebx] ; update IV movdqu oword [esp], xmm0 add pInpBlk, ebx add pOutBlk, ebx sub len, ebx jg .blks_loop add esp, 16*(1+4+4) REST_GPR ret ENDFUNC EncryptCFB32_RIJ128_AES_NI align IPP_ALIGN_FACTOR IPPASM EncryptCFB128_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input blocks address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output blocks address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in bytes %xdefine pIV [ebp + ARG_1 + 5*sizeof(dword)] ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) mov eax, pIV ; IV address movdqu xmm0, oword [eax] ; get IV mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov ebx, len ; get actual address of key material: pRKeys += (nr-9) * SC mov ecx, pKey mov edx, nr lea eax,[edx*4] lea eax, [ecx+eax*4-9*(SC)*4] ; AES-128 round keys ;; ;; processing ;; .blks_loop: pxor xmm0, oword [ecx] ; whitening movdqu xmm1, oword [esi] ; input blocks cmp edx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [eax-4*4*SC] aesenc xmm0, oword [eax-3*4*SC] .key_192_s: aesenc xmm0, oword [eax-2*4*SC] aesenc xmm0, oword [eax-1*4*SC] .key_128_s: aesenc xmm0, oword [eax+0*4*SC] aesenc xmm0, oword [eax+1*4*SC] aesenc xmm0, oword [eax+2*4*SC] aesenc xmm0, oword [eax+3*4*SC] aesenc xmm0, oword [eax+4*4*SC] aesenc xmm0, oword [eax+5*4*SC] aesenc xmm0, oword [eax+6*4*SC] aesenc xmm0, oword [eax+7*4*SC] aesenc xmm0, oword [eax+8*4*SC] aesenclast xmm0, oword [eax+9*4*SC] pxor xmm0, xmm1 ; xor src movdqu oword [edi],xmm0 ;and store into the dst add esi, 16 add edi, 16 sub ebx, 16 jg .blks_loop REST_GPR ret ENDFUNC EncryptCFB128_RIJ128_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptctrpipeg9as.asm000066400000000000000000000233571470420105600306450ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptCTR_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: pipelined RIJ128 CTR encryption/decryption ;* ;* void EncryptCTR_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int length, ;* Ipp8u* pCtrValue, ;* Ipp8u* pCtrBitMask) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128EncryptCTR ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR CONST_TABLE: u128_str DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 align IPP_ALIGN_FACTOR IPPASM EncryptCTR_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; number of blocks being processed %xdefine pCtrValue [ebp + ARG_1 + 5*sizeof(dword)] ; pointer to the Counter %xdefine pCtrBitMask [ebp + ARG_1 + 6*sizeof(dword)] ; pointer to the Counter Bit Mask %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi, pCtrBitMask mov edi, pCtrValue movdqu xmm6, oword [esi] ; counter bit mask movdqu xmm1, oword [edi] ; initial counter movdqu xmm5, xmm6 ; counter bit mask pandn xmm6, xmm1 ; counter template sub esp, (4*4) ; allocate stack LD_ADDR eax, CONST_TABLE ; load bswap conversion tbl movdqa xmm4, oword [eax+(u128_str - CONST_TABLE)] ;; ;; init counter ;; mov edx, dword [edi] mov ecx, dword [edi+4] mov ebx, dword [edi+8] mov eax, dword [edi+12] bswap edx bswap ecx bswap ebx bswap eax mov dword [esp], eax ; store counter mov dword [esp+4], ebx mov dword [esp+8], ecx mov dword [esp+12], edx mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address sub dword len, BYTES_PER_LOOP jl .short_input ;; ;; pipelined processing ;; .blks_loop: mov eax, dword [esp] ; get coutnter value mov ebx, dword [esp+4] mov ecx, dword [esp+8] mov edx, dword [esp+12] pinsrd xmm0, eax, 0 ; set counter value pinsrd xmm0, ebx, 1 pinsrd xmm0, ecx, 2 pinsrd xmm0, edx, 3 pshufb xmm0, xmm4 ; convert int the octet string pand xmm0, xmm5 ; select counter bits por xmm0, xmm6 ; add unchanged bits add eax, 1 ; increment counter adc ebx, 0 adc ecx, 0 adc edx, 0 pinsrd xmm1, eax, 0 ; set counter value pinsrd xmm1, ebx, 1 pinsrd xmm1, ecx, 2 pinsrd xmm1, edx, 3 pshufb xmm1, xmm4 ; convert int the octet string pand xmm1, xmm5 ; select counter bits por xmm1, xmm6 ; add unchanged bits add eax, 1 ; increment counter adc ebx, 0 adc ecx, 0 adc edx, 0 pinsrd xmm2, eax, 0 ; set counter value pinsrd xmm2, ebx, 1 pinsrd xmm2, ecx, 2 pinsrd xmm2, edx, 3 pshufb xmm2, xmm4 ; convert int the octet string pand xmm2, xmm5 ; select counter bits por xmm2, xmm6 ; add unchanged bits add eax, 1 ; increment counter adc ebx, 0 adc ecx, 0 adc edx, 0 pinsrd xmm3, eax, 0 ; set counter value pinsrd xmm3, ebx, 1 pinsrd xmm3, ecx, 2 pinsrd xmm3, edx, 3 pshufb xmm3, xmm4 ; convert int the octet string pand xmm3, xmm5 ; select counter bits por xmm3, xmm6 ; add unchanged bits add eax, 1 ; increment counter adc ebx, 0 adc ecx, 0 adc edx, 0 mov dword [esp], eax ; and store for next iteration mov dword [esp+4], ebx mov dword [esp+8], ecx mov dword [esp+12], edx mov ecx, pKey ; get key material address movdqa xmm7, oword [ecx] lea ebx, [ecx+16] ; pointer to the round's key material pxor xmm0, xmm7 ; whitening pxor xmm1, xmm7 pxor xmm2, xmm7 pxor xmm3, xmm7 movdqa xmm7, oword [ebx] ; pre load round keys add ebx, 16 mov eax, nr ; counter depending on key length sub eax, 1 .cipher_loop: aesenc xmm0, xmm7 ; regular round aesenc xmm1, xmm7 aesenc xmm2, xmm7 aesenc xmm3, xmm7 movdqa xmm7, oword [ebx] add ebx, 16 dec eax jnz .cipher_loop aesenclast xmm0, xmm7 ; irregular round aesenclast xmm1, xmm7 aesenclast xmm2, xmm7 aesenclast xmm3, xmm7 movdqu xmm7, oword [esi+0*BYTES_PER_BLK] ; xor input blocks pxor xmm0, xmm7 movdqu oword [edi+0*BYTES_PER_BLK], xmm0 movdqu xmm7, oword [esi+1*BYTES_PER_BLK] pxor xmm1, xmm7 movdqu oword [edi+1*BYTES_PER_BLK], xmm1 movdqu xmm7, oword [esi+2*BYTES_PER_BLK] pxor xmm2, xmm7 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 movdqu xmm7, oword [esi+3*BYTES_PER_BLK] pxor xmm3, xmm7 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 add esi, BYTES_PER_LOOP add edi, BYTES_PER_LOOP sub dword len, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add dword len, BYTES_PER_LOOP jz .quit mov ecx,pKey ; key material address ; get actual address of key material: pRKeys += (nr-9) * SC mov eax, nr lea ebx,[eax*4] lea ebx,[ecx+ebx*4-9*(SC)*4] ; AES-128 round keys .single_blk_loop: movdqu xmm0, oword [esp] ; get counter value pshufb xmm0, xmm4 ; convert int the octet string pand xmm0, xmm5 ; select counter bits por xmm0, xmm6 ; add unchanged bits pxor xmm0, oword [ecx] ; whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0,oword [ebx-4*4*SC] aesenc xmm0,oword [ebx-3*4*SC] .key_192_s: aesenc xmm0,oword [ebx-2*4*SC] aesenc xmm0,oword [ebx-1*4*SC] .key_128_s: aesenc xmm0,oword [ebx+0*4*SC] aesenc xmm0,oword [ebx+1*4*SC] aesenc xmm0,oword [ebx+2*4*SC] aesenc xmm0,oword [ebx+3*4*SC] aesenc xmm0,oword [ebx+4*4*SC] aesenc xmm0,oword [ebx+5*4*SC] aesenc xmm0,oword [ebx+6*4*SC] aesenc xmm0,oword [ebx+7*4*SC] aesenc xmm0,oword [ebx+8*4*SC] aesenclast xmm0,oword [ebx+9*4*SC] add dword [esp], 1 ; advance counter value adc dword [esp+4], 0 adc dword [esp+8], 0 adc dword [esp+12], 0 sub dword len, BYTES_PER_BLK jl .partial_block movdqu xmm1, oword [esi] ; input block add esi, BYTES_PER_BLK pxor xmm0, xmm1 ; output block movdqu oword [edi], xmm0 ; save output block add edi, BYTES_PER_BLK cmp dword len, 0 jz .quit jmp .single_blk_loop .partial_block: add dword len, BYTES_PER_BLK .partial_block_loop: pextrb eax, xmm0, 0 psrldq xmm0, 1 movzx ebx, byte [esi] xor eax, ebx mov byte [edi], al inc esi inc edi dec dword len jnz .partial_block_loop .quit: mov eax, pCtrValue movdqu xmm0, oword [esp] ; get counter value pshufb xmm0, xmm4 ; convert int the octet string pand xmm0, xmm5 ; select counter bits por xmm0, xmm6 ; add unchanged bits movdqu oword [eax], xmm0 ; return updated counter add esp, (4*4) ; free stack REST_GPR ret ENDFUNC EncryptCTR_RIJ128pipe_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptecbpipeg9as.asm000066400000000000000000000120521470420105600305740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptECB_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: pipelined RIJ128 ECB encryption ;* ;* void EncryptECB_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len) ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128EncryptECB ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM EncryptECB_RIJ128pipe_AES_NI,PUBLIC USES_GPR esi,edi,ebx %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [esp + ARG_1 + 4*sizeof(dword)] ; length(byte) %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address mov ecx,pKey ; key material address mov edx,len ; length sub edx, BYTES_PER_LOOP jl .short_input ;; ;; pipelined processing ;; .blks_loop: movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [ecx+16] ; pointer to the round's key material movdqu xmm0, oword [esi+0*BYTES_PER_BLK] ; get input blocks movdqu xmm1, oword [esi+1*BYTES_PER_BLK] movdqu xmm2, oword [esi+2*BYTES_PER_BLK] movdqu xmm3, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_LOOP pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load round keys add ebx, 16 mov eax,nr ; number of rounds depending on key length sub eax, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [ebx] add ebx, 16 dec eax jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round movdqu oword [edi+0*BYTES_PER_BLK], xmm0 ; store output blocks aesenclast xmm1, xmm4 movdqu oword [edi+1*BYTES_PER_BLK], xmm1 aesenclast xmm2, xmm4 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 aesenclast xmm3, xmm4 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 add edi, BYTES_PER_LOOP sub edx, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add edx, BYTES_PER_LOOP jz .quit ; get actual address of key material: pRKeys += (nr-9) * SC mov eax, nr lea ebx,[eax*4] lea ebx,[ecx+ebx*4-9*(SC)*4] ; AES-128 round keys .single_blk_loop: movdqu xmm0, oword [esi] ; get input block add esi, BYTES_PER_BLK pxor xmm0, oword [ecx] ; whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0,oword [ebx-4*4*SC] aesenc xmm0,oword [ebx-3*4*SC] .key_192_s: aesenc xmm0,oword [ebx-2*4*SC] aesenc xmm0,oword [ebx-1*4*SC] .key_128_s: aesenc xmm0,oword [ebx+0*4*SC] aesenc xmm0,oword [ebx+1*4*SC] aesenc xmm0,oword [ebx+2*4*SC] aesenc xmm0,oword [ebx+3*4*SC] aesenc xmm0,oword [ebx+4*4*SC] aesenc xmm0,oword [ebx+5*4*SC] aesenc xmm0,oword [ebx+6*4*SC] aesenc xmm0,oword [ebx+7*4*SC] aesenc xmm0,oword [ebx+8*4*SC] aesenclast xmm0,oword [ebx+9*4*SC] movdqu oword [edi], xmm0 ; save output block add edi, BYTES_PER_BLK sub edx, BYTES_PER_BLK jnz .single_blk_loop .quit: REST_GPR ret ENDFUNC EncryptECB_RIJ128pipe_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptg9as.asm000066400000000000000000000065641470420105600272570ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; Encrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" ;*************************************************************** ;* Purpose: single block RIJ128 Cipher ;* ;* void Encrypt_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* const Ipp32u Tables[][256]) ;* ;*************************************************************** ;%if (_IPP >= _IPP_P8) && (_IPP < _IPP_G9) %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128EncryptECB ;; Caller = ippsRijndael128EncryptCBC ;; Caller = ippsRijndael128EncryptCFB ;; Caller = ippsRijndael128DecryptCFB ;; ;; Caller = ippsDAARijndael128Update ;; Caller = ippsDAARijndael128Final ;; Caller = ippsDAARijndael128MessageDigest ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM Encrypt_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine SC (4) mov esi,pInpBlk ; input data address mov ecx,pKey ; key material address mov eax,nr ; number of rounds mov edi,pOutBlk ; output data address movdqu xmm0, oword [esi] ; input block pxor xmm0, oword [ecx] ; whitening ; get actual address of key material: pRKeys += (nr-9) * SC lea edx,[eax*4] lea ecx,[ecx+edx*4-9*(SC)*4]; AES-128-keys cmp eax,12 ; switch according to number of rounds jl .key_128 jz .key_192 ;; ;; regular rounds ;; .key_256: aesenc xmm0,oword [ecx-4*4*SC] aesenc xmm0,oword [ecx-3*4*SC] .key_192: aesenc xmm0,oword [ecx-2*4*SC] aesenc xmm0,oword [ecx-1*4*SC] .key_128: aesenc xmm0,oword [ecx+0*4*SC] aesenc xmm0,oword [ecx+1*4*SC] aesenc xmm0,oword [ecx+2*4*SC] aesenc xmm0,oword [ecx+3*4*SC] aesenc xmm0,oword [ecx+4*4*SC] aesenc xmm0,oword [ecx+5*4*SC] aesenc xmm0,oword [ecx+6*4*SC] aesenc xmm0,oword [ecx+7*4*SC] aesenc xmm0,oword [ecx+8*4*SC] ;; ;; last rounds ;; aesenclast xmm0,oword [ecx+9*4*SC] movdqu oword [edi], xmm0 ; output block REST_GPR ret ENDFUNC Encrypt_RIJ128_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptofbg9as.asm000066400000000000000000000171571470420105600277460ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Encrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %macro COPY_8U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor ecx, ecx %%next_byte: mov %%tmp, byte [%%src+ecx] mov byte [%%dst+ecx], %%tmp add ecx, 1 cmp ecx, %%limit jl %%next_byte %endmacro ;*************************************************************** ;* Purpose: RIJ128 OFB encryption ;* ;* void EncryptOFB_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int length, ;* int ofbBlks, ;* const Ipp8u* pIV) ;*************************************************************** %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsRijndael128DecryptOFB ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM EncryptOFB_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInpBlk [ebp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [ebp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [ebp + ARG_1 + 4*sizeof(dword)] ; length of stream in bytes %xdefine ofbSize [ebp + ARG_1 + 5*sizeof(dword)] ; ofb blk size %xdefine pIV [ebp + ARG_1 + 6*sizeof(dword)] ; IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) %xdefine tmpInp esp %xdefine tmpOut tmpInp+sizeof(oword) %xdefine locDst tmpOut+sizeof(oword) %xdefine locSrc locDst+sizeof(oword)*4 %xdefine locLen locSrc+sizeof(oword)*4 %xdefine stackLen sizeof(oword)+sizeof(oword)+sizeof(oword)*4+sizeof(oword)*4+sizeof(dword) sub esp,stackLen ; allocate stack mov eax, pIV ; get IV movdqu xmm0, oword [eax] ; movdqu oword [tmpInp], xmm0 ; and save into the stack mov eax, nr ; number of rounds mov ecx, pKey ; key material address lea eax, [eax*4] ; nr*16 offset (bytes) to end of key material lea eax, [eax*4] lea ecx, [ecx+eax] neg eax ; save -nr*16 mov nr, eax mov pKey, ecx ; save key material address mov esi, pInpBlk ; input stream mov edi, pOutBlk ; output stream mov ebx, ofbSize ; cfb blk size align IPP_ALIGN_FACTOR ;; ;; processing ;; .blks_loop: lea ebx, [ebx*BLKS_PER_LOOP] ; 4 cfb block cmp len, ebx cmovl ebx, len COPY_8U {locSrc}, esi, ebx, dl ; move 1-4 input blocks to stack mov ecx, pKey mov eax, nr mov dword [locLen], ebx xor edx, edx ; index align IPP_ALIGN_FACTOR .single_blk: movdqa xmm3, oword [ecx+eax] ; preload key material add eax, 16 movdqa xmm4, oword [ecx+eax] ; preload next key material pxor xmm0, xmm3 ; whitening align IPP_ALIGN_FACTOR .cipher_loop: add eax, 16 aesenc xmm0, xmm4 ; regular round movdqa xmm4, oword [ecx+eax] jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round movdqu oword [tmpOut], xmm0 ; save chipher output mov eax, ofbSize ; cfb blk size movdqu xmm1, oword [locSrc+edx] ; get src blocks from the stack pxor xmm1, xmm0 ; xor src movdqu oword [locDst+edx],xmm1 ;and store into the stack movdqu xmm0, oword [tmpInp+eax] ; update cipher input (IV) movdqu oword [tmpInp], xmm0 add edx, eax ; advance index mov eax, nr cmp edx, ebx jl .single_blk COPY_8U edi, {locDst}, edx, bl ; move 1-4 blocks to output mov ebx, ofbSize ; restore cfb blk size add esi, edx ; advance pointers add edi, edx sub len, edx ; decrease stream counter jg .blks_loop mov eax, pIV ; IV address movdqu xmm0, oword [tmpInp] ; update IV before return movdqu oword [eax], xmm0 add esp,stackLen ; remove local variables REST_GPR ret ENDFUNC EncryptOFB_RIJ128_AES_NI align IPP_ALIGN_FACTOR IPPASM EncryptOFB128_RIJ128_AES_NI,PUBLIC USES_GPR esi,edi %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine len [esp + ARG_1 + 4*sizeof(dword)] ; length of stream in bytes %xdefine pIV [esp + ARG_1 + 5*sizeof(dword)] ; IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) mov eax, pIV ; get IV movdqu xmm0, oword [eax] ; mov eax, nr ; number of rounds mov ecx, pKey ; key material address lea eax, [eax*4] ; nr*16 offset (bytes) to end of key material lea eax, [eax*4] lea ecx, [ecx+eax] neg eax ; save -nr*16 mov nr, eax mov esi, pInpBlk ; input stream mov edi, pOutBlk ; output stream mov edx, len ; length of stream align IPP_ALIGN_FACTOR ;; ;; processing ;; .blks_loop: movdqa xmm3, oword [ecx+eax] ; preload key material add eax, 16 align IPP_ALIGN_FACTOR .single_blk: movdqa xmm4, oword [ecx+eax] ; preload next key material pxor xmm0, xmm3 ; whitening movdqu xmm1, oword [esi] ; input block align IPP_ALIGN_FACTOR .cipher_loop: add eax, 16 aesenc xmm0, xmm4 ; regular round movdqa xmm4, oword [ecx+eax] jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round pxor xmm1, xmm0 ; xor src movdqu oword [edi],xmm1 ; and store into the dst mov eax, nr ; restore key material counter add esi, 16 ; advance pointers add edi, 16 sub edx, 16 ; decrease stream counter jg .blks_loop mov eax, pIV ; get IV address movdqu oword [eax], xmm0 ; update IV before return REST_GPR ret ENDFUNC EncryptOFB128_RIJ128_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128encryptxtsg9as.asm000066400000000000000000000165161470420105600300140ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; AES function ; ; Content: ; cpAESEncryptXTS_AES_NI() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %macro MUL_X 4.nolist %xdefine %%y %1 %xdefine %%x %2 %xdefine %%t %3 %xdefine %%cnt %4 pxor %%t, %%t movdqa %%y, %%x pcmpgtq %%t, %%x paddq %%y, %%y palignr %%t, %%t, sizeof(qword) pand %%t, %%cnt pxor %%y, %%t %endmacro ;*************************************************************** ;* Purpose: AES-XTS encryption ;* ;* void cpAESEncryptXTS_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int length, ;* const Ipp8u* pRKey, ;* int nr, ;* const Ipp8u* pTweak) ;*************************************************************** %if (_IPP >= _IPP_P8) ;; ;; Lib = P8 ;; ;; Caller = ippsAESEncryptXTS ;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM cpAESEncryptXTS_AES_NI,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pOutBlk [ebp + ARG_1 + 0*sizeof(dword)] ; output block address %xdefine pInpBlk [ebp + ARG_1 + 1*sizeof(dword)] ; input block address %xdefine blks [ebp + ARG_1 + 2*sizeof(dword)] ; length(blocks) %xdefine pKey [ebp + ARG_1 + 3*sizeof(dword)] ; key material address %xdefine nr [ebp + ARG_1 + 4*sizeof(dword)] ; number of rounds %xdefine pTweak [ebp + ARG_1 + 5*sizeof(dword)] ; tweaks %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address ; ; stack layout: ; %assign _tweakCnt 0 ; constant %assign _tweak0 _tweakCnt+sizeof(oword) ; * alpha %assign _tweak1 _tweak0+sizeof(oword) ; * alpha^2 %assign _tweak2 _tweak1+sizeof(oword) ; * alpha^3 %assign _tweak3 _tweak2+sizeof(oword) ; * alpha^4 %assign _nr _tweak3+sizeof(oword) ; # rounds %assign _sp _nr+sizeof(dword) ; esp %assign stackSize _sp+sizeof(dword) ; stack size mov eax, esp sub esp, stackSize ; aligned stack and esp, (-16) mov dword [esp+_sp], eax ; store esp mov eax, pTweak movdqu xmm4, oword [eax] ; initial tweak movdqa xmm7, xmm4 mov eax, 087h ; create tweakCnt = {0x01:0x87} mov ecx, 1 movd xmm0, eax movd xmm1, ecx punpcklqdq xmm0, xmm1 mov ecx,pKey ; key material address mov edx,blks ; num of blocks ; move parameters to local stack frame mov eax,nr ; num of rounds movdqa oword [esp+_tweakCnt], xmm0 mov dword [esp+_nr], eax sub edx, BLKS_PER_LOOP jl .short_input jmp .blks_loop_ep ;; ;; pipelined processing ;; .blks_loop: MUL_X xmm4, xmm7, xmm1, xmm0 .blks_loop_ep: movdqa oword [esp+_tweak0], xmm4 MUL_X xmm5, xmm4, xmm1, xmm0 movdqa oword [esp+_tweak1], xmm5 MUL_X xmm6, xmm5, xmm1, xmm0 movdqa oword [esp+_tweak2], xmm6 MUL_X xmm7, xmm6, xmm1, xmm0 movdqa oword [esp+_tweak3], xmm7 movdqu xmm0, oword [esi+0*BYTES_PER_BLK] ; get input blocks movdqu xmm1, oword [esi+1*BYTES_PER_BLK] movdqu xmm2, oword [esi+2*BYTES_PER_BLK] movdqu xmm3, oword [esi+3*BYTES_PER_BLK] add esi, BYTES_PER_BLK*BLKS_PER_LOOP pxor xmm0, xmm4 ; tweak pre-whitening pxor xmm1, xmm5 pxor xmm2, xmm6 pxor xmm3, xmm7 movdqa xmm4, oword [ecx] ; keys for whitening lea ebx, [ecx+BYTES_PER_BLK]; pointer to the round's key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [ebx] ; pre load round keys add ebx, BYTES_PER_BLK sub eax, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [ebx] add ebx, BYTES_PER_BLK dec eax jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round aesenclast xmm1, xmm4 aesenclast xmm2, xmm4 aesenclast xmm3, xmm4 movdqa xmm4, oword [esp+_tweak0] ; tweak post-whitening movdqa xmm5, oword [esp+_tweak1] movdqa xmm6, oword [esp+_tweak2] movdqa xmm7, oword [esp+_tweak3] pxor xmm0, xmm4 pxor xmm1, xmm5 pxor xmm2, xmm6 pxor xmm3, xmm7 movdqu oword [edi+0*BYTES_PER_BLK], xmm0 ; store output blocks movdqu oword [edi+1*BYTES_PER_BLK], xmm1 movdqu oword [edi+2*BYTES_PER_BLK], xmm2 movdqu oword [edi+3*BYTES_PER_BLK], xmm3 add edi, BYTES_PER_BLK*BLKS_PER_LOOP movdqa xmm0, oword [esp+_tweakCnt] ; restore tweak const mov eax, dword [esp+_nr] ; number of rounds sub edx, BLKS_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add edx, BLKS_PER_LOOP jz .quit mov eax, dword [esp+_nr] ; bottom of the keys lea ebx,[eax*sizeof(dword)] lea ebx,[ecx+ebx*4-9*(SC)*4] ; AES-128 keys jmp .single_blk_loop_ep .single_blk_loop: MUL_X xmm7, xmm7, xmm1, xmm0 .single_blk_loop_ep: movdqu xmm1, oword [esi] ; input block add esi, BYTES_PER_BLK pxor xmm1, xmm7 ; tweak pre-whitening pxor xmm1, oword [ecx] ; AES whitening cmp eax,12 ; switch according to number of rounds jl .key_128_s .key_256_s: aesenc xmm1,oword [ebx-4*4*SC] aesenc xmm1,oword [ebx-3*4*SC] aesenc xmm1,oword [ebx-2*4*SC] aesenc xmm1,oword [ebx-1*4*SC] .key_128_s: aesenc xmm1,oword [ebx+0*4*SC] aesenc xmm1,oword [ebx+1*4*SC] aesenc xmm1,oword [ebx+2*4*SC] aesenc xmm1,oword [ebx+3*4*SC] aesenc xmm1,oword [ebx+4*4*SC] aesenc xmm1,oword [ebx+5*4*SC] aesenc xmm1,oword [ebx+6*4*SC] aesenc xmm1,oword [ebx+7*4*SC] aesenc xmm1,oword [ebx+8*4*SC] aesenclast xmm1,oword [ebx+9*4*SC] pxor xmm1, xmm7 ; tweak post-whitening movdqu oword [edi], xmm1 ; output block add edi, BYTES_PER_BLK sub edx, 1 jnz .single_blk_loop .quit: mov eax, pTweak ; save tweak movdqu oword [eax], xmm7 mov esp, [esp+_sp] REST_GPR ret ENDFUNC cpAESEncryptXTS_AES_NI %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128safedecm5as.asm000066400000000000000000000266451470420105600271710ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael-128 (AES) inverse cipher functions. ; (It's the special free from Sbox/tables implementation) ; ; Content: ; SafeDecrypt_RIJ128() ; ; History: ; ; Notes. ; The implementation is based on compact S-box usage. ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP == _IPP_M5) ;; ;; transpose 16x16 martix to [dst] ;; eax,ebx,ecx,edx constins matrix rows ;; %macro TRANSPOSE 1.nolist %xdefine %%dst %1 mov byte [%%dst+0 ], al shr eax, 8 mov byte [%%dst+1 ], bl shr ebx, 8 mov byte [%%dst+2 ], cl shr ecx, 8 mov byte [%%dst+3 ], dl shr edx, 8 mov byte [%%dst+4 ], al shr eax, 8 mov byte [%%dst+5 ], bl shr ebx, 8 mov byte [%%dst+6 ], cl shr ecx, 8 mov byte [%%dst+7 ], dl shr edx, 8 mov byte [%%dst+8 ], al shr eax, 8 mov byte [%%dst+9 ], bl shr ebx, 8 mov byte [%%dst+10], cl shr ecx, 8 mov byte [%%dst+11], dl shr edx, 8 mov byte [%%dst+12], al shr eax, 8 mov byte [%%dst+13], bl shr ebx, 8 mov byte [%%dst+14], cl shr ecx, 8 mov byte [%%dst+15], dl shr edx, 8 %endmacro ;; ;; SubBute ;; %macro SBOX_ZERO 1.nolist %xdefine %%inpb %1 mov al, byte [esi+%%inpb] %endmacro %macro SBOX_QUAD 1.nolist %xdefine %%inpb %1 mov eax, 03Fh and eax, %%inpb ; x%64 shr %%inpb, 6 ; x/64 add esi, eax ; &Sbox[x%64] mov al, byte [esi+64*0] mov bl, byte [esi+64*1] mov cl, byte [esi+64*2] mov dl, byte [esi+64*3] mov byte [esp+oBuffer+1*0], al mov byte [esp+oBuffer+1*1], bl mov byte [esp+oBuffer+1*2], cl mov byte [esp+oBuffer+1*3], dl mov al, byte [esp+oBuffer+%%inpb] %endmacro %macro SBOX_FULL 1.nolist %xdefine %%inpb %1 mov eax, 0Fh and eax, %%inpb ; x%16 shr %%inpb, 4 ; x/16 add esi, eax ; &Sbox[x%16] movzx eax, byte [esi+16*15] movzx ebx, byte [esi+16*14] movzx ecx, byte [esi+16*13] movzx edx, byte [esi+16*12] push eax push ebx push ecx push edx movzx eax, byte [esi+16*11] movzx ebx, byte [esi+16*10] movzx ecx, byte [esi+16*9] movzx edx, byte [esi+16*8] push eax push ebx push ecx push edx movzx eax, byte [esi+16*7] movzx ebx, byte [esi+16*6] movzx ecx, byte [esi+16*5] movzx edx, byte [esi+16*4] push eax push ebx push ecx push edx movzx eax, byte [esi+16*3] movzx ebx, byte [esi+16*2] movzx ecx, byte [esi+16*1] movzx edx, byte [esi+16*0] push eax push ebx push ecx push edx mov eax, dword [esp+%%inpb*sizeof(dword)] add esp, 16*sizeof(dword) %endmacro ;; ;; AddRoundKey ;; %macro ADD_ROUND_KEY 5.nolist %xdefine %%x0 %1 %xdefine %%x1 %2 %xdefine %%x2 %3 %xdefine %%x3 %4 %xdefine %%key %5 xor %%x0, dword [%%key+sizeof(dword)*0] xor %%x1, dword [%%key+sizeof(dword)*1] xor %%x2, dword [%%key+sizeof(dword)*2] xor %%x3, dword [%%key+sizeof(dword)*3] %endmacro ;; ;; GFMULx x, t0,t1 ;; ;; mask = x & 0x80808080 ;; mask = (mask<<1) - (mask>>7) ;; ;; x = (x<<=1) & 0xFEFEFEFE ;; x ^= msk & 0x1B1B1B1B ;; %macro GFMULx 3.nolist %xdefine %%x %1 %xdefine %%msk %2 %xdefine %%t %3 mov %%t, %%x add %%x, %%x ;; mul: x = (x<<=1) & 0xFEFEFEFE and %%t, 080808080h ;; mask: t = x & 0x80808080 and %%x, 0FEFEFEFEh ;; lea %%msk, [%%t+%%t] ;; mask: msk = (t<<1) - (t>>7) shr %%t, 7 ;; mask: sub %%msk, %%t ;; mask: and %%msk, 01B1B1B1Bh ;; mul: x ^= msk & 0x1B1B1B1B xor %%x, %%msk %endmacro ;; ;; MixColumn ;; %macro MIX_COLUMNS 6.nolist %xdefine %%x0 %1 %xdefine %%x1 %2 %xdefine %%x2 %3 %xdefine %%x3 %4 %xdefine %%t0 %5 %xdefine %%t1 %6 ;; Ipp32u y0 = state[1] ^ state[2] ^ state[3]; ;; Ipp32u y1 = state[0] ^ state[2] ^ state[3]; ;; Ipp32u y2 = state[0] ^ state[1] ^ state[3]; ;; Ipp32u y3 = state[0] ^ state[1] ^ state[2]; mov %%t0, %%x1 xor %%t0, %%x2 xor %%t0, %%x3 mov %%t1, %%x0 xor %%t1, %%x2 xor %%t1, %%x3 mov dword [esp+oBuffer+sizeof(dword)*0], %%t0 mov dword [esp+oBuffer+sizeof(dword)*1], %%t1 mov %%t0, %%x0 xor %%t0, %%x1 xor %%t0, %%x3 mov %%t1, %%x0 xor %%t1, %%x1 xor %%t1, %%x2 mov dword [esp+oBuffer+sizeof(dword)*2], %%t0 mov dword [esp+oBuffer+sizeof(dword)*3], %%t1 ;; state[0] = xtime4(state[0]); ;; state[1] = xtime4(state[1]); ;; state[2] = xtime4(state[2]); ;; state[3] = xtime4(state[3]); GFMULx %%x0, %%t0,%%t1 GFMULx %%x1, %%t0,%%t1 GFMULx %%x2, %%t0,%%t1 GFMULx %%x3, %%t0,%%t1 ;; y0 ^= state[0] ^ state[1]; ;; y1 ^= state[1] ^ state[2]; ;; y2 ^= state[2] ^ state[3]; ;; y3 ^= state[3] ^ state[0]; mov %%t0, dword [esp+oBuffer+sizeof(dword)*0] mov %%t1, dword [esp+oBuffer+sizeof(dword)*1] xor %%t0, %%x0 xor %%t1, %%x1 xor %%t0, %%x1 xor %%t1, %%x2 mov dword [esp+oBuffer+sizeof(dword)*0], %%t0 mov dword [esp+oBuffer+sizeof(dword)*1], %%t1 mov %%t0, dword [esp+oBuffer+sizeof(dword)*2] mov %%t1, dword [esp+oBuffer+sizeof(dword)*3] xor %%t0, %%x2 xor %%t1, %%x3 xor %%t0, %%x3 xor %%t1, %%x0 mov dword [esp+oBuffer+sizeof(dword)*2], %%t0 mov dword [esp+oBuffer+sizeof(dword)*3], %%t1 ;; t02 = state[0] ^ state[2]; ;; t13 = state[1] ^ state[3]; ;; t02 = xtime4(t02); ;; t13 = xtime4(t13); mov %%t0, %%x0 mov %%t1, %%x1 xor %%t0, %%x2 xor %%t1, %%x3 GFMULx %%t0, %%x0,%%x1 ;; t02 GFMULx %%t1, %%x0,%%x1 ;; t13 ;; t0123 = t02^t13; ;; t0123 = xtime4(t0123); mov %%x0, %%t0 xor %%x0, %%t1 GFMULx %%x0, %%x1,%%x2 ;; state[0] = y0 ^t02 ^t0123; ;; state[1] = y1 ^t13 ^t0123; ;; state[2] = y2 ^t02 ^t0123; ;; state[3] = y3 ^t13 ^t0123; xor %%t0, %%x0 ;; t02^t0123 xor %%t1, %%x0 ;; t13^t0123 mov %%x0, dword [esp+oBuffer+sizeof(dword)*0] mov %%x1, dword [esp+oBuffer+sizeof(dword)*1] mov %%x2, dword [esp+oBuffer+sizeof(dword)*2] mov %%x3, dword [esp+oBuffer+sizeof(dword)*3] xor %%x0, %%t0 xor %%x1, %%t1 xor %%x2, %%t0 xor %%x3, %%t1 %endmacro segment .text align=IPP_ALIGN_FACTOR IPPASM Safe2Decrypt_RIJ128,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pInp [ebp + ARG_1 + 0*sizeof(dword)] ; input buffer %xdefine pOut [ebp + ARG_1 + 1*sizeof(dword)] ; output buffer %xdefine nrounds [ebp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pRK [ebp + ARG_1 + 3*sizeof(dword)] ; round keys %xdefine pSbox [ebp + ARG_1 + 4*sizeof(dword)] ; S-box ;; stack %assign oState 0 ; 4*dword state %assign oBuffer oState+sizeof(dword)*4 ; 4*dword buffer %assign oSbox oBuffer+sizeof(dword)*4 ; S-box address %assign oSaveEBP oSbox+sizeof(dword) ; save EBP slot %assign stackSize oSaveEBP+sizeof(dword) ; stack size sub esp, stackSize ; state on the stack mov edi, nrounds ; read input block and transpose one mov esi, pInp mov eax, dword [esi+sizeof(dword)*0] mov ebx, dword [esi+sizeof(dword)*1] mov ecx, dword [esi+sizeof(dword)*2] mov edx, dword [esi+sizeof(dword)*3] TRANSPOSE {esp+oState} shl edi, 4 ; nrounds*16 mov esi, pRK add esi, edi ; read input block mov eax, dword [esp+oState+sizeof(dword)*0] mov ebx, dword [esp+oState+sizeof(dword)*1] mov ecx, dword [esp+oState+sizeof(dword)*2] mov edx, dword [esp+oState+sizeof(dword)*3] ; add round key ADD_ROUND_KEY eax,ebx,ecx,edx, esi ; add round key sub esi, sizeof(byte)*16 mov pRK, esi mov dword [esp+oState+sizeof(dword)*0], eax mov dword [esp+oState+sizeof(dword)*1], ebx mov dword [esp+oState+sizeof(dword)*2], ecx mov dword [esp+oState+sizeof(dword)*3], edx dec nrounds mov esi, pSbox mov dword [esp+oSbox], esi mov dword [esp+oSaveEBP], ebp ;; regular rounds .next_aes_round: ;; shift rows ror ebx, 24 ror ecx, 16 ror edx, 8 mov dword [esp+oState+sizeof(dword)*0], eax mov dword [esp+oState+sizeof(dword)*1], ebx mov dword [esp+oState+sizeof(dword)*2], ecx mov dword [esp+oState+sizeof(dword)*3], edx ;; sub bytes xor ebp, ebp .sub_byte_loop: mov esi, dword [esp+oSbox] ; Sbox address movzx edi, byte [esp+oState+ebp] ; x input byte add ebp, 1 SBOX_FULL edi ;;SBOX_QUAD edi ;;SBOX_ZERO edi mov byte [esp+oState+ebp-1], al cmp ebp, 16 jl .sub_byte_loop ;; add round key mov ebp, dword [esp+oSaveEBP] mov esi, pRK mov eax, dword [esp+oState+sizeof(dword)*0] mov ebx, dword [esp+oState+sizeof(dword)*1] mov ecx, dword [esp+oState+sizeof(dword)*2] mov edx, dword [esp+oState+sizeof(dword)*3] ADD_ROUND_KEY eax,ebx,ecx,edx, esi ; add round key sub esi, sizeof(byte)*16 mov pRK, esi ;; mix columns MIX_COLUMNS eax,ebx,ecx,edx, esi, edi ; mix columns sub nrounds, 1 jne .next_aes_round ;; irregular round: shift rows ror ebx, 24 ror ecx, 16 ror edx, 8 mov dword [esp+oState+sizeof(dword)*0], eax mov dword [esp+oState+sizeof(dword)*1], ebx mov dword [esp+oState+sizeof(dword)*2], ecx mov dword [esp+oState+sizeof(dword)*3], edx ;; irregular round: sub bytes xor ebp, ebp .sub_byte_irr_loop: mov esi, dword [esp+oSbox] movzx edi, byte [esp+oState+ebp] ; x input byte add ebp, 1 SBOX_FULL edi ;;SBOX_QUAD edi ;;SBOX_ZERO edi mov byte [esp+oState+ebp-1], al cmp ebp, 16 jl .sub_byte_irr_loop ;; irregular round: add round key mov ebp, dword [esp+oSaveEBP] mov esi, pRK mov eax, dword [esp+oState+sizeof(dword)*0] mov ebx, dword [esp+oState+sizeof(dword)*1] mov ecx, dword [esp+oState+sizeof(dword)*2] mov edx, dword [esp+oState+sizeof(dword)*3] ADD_ROUND_KEY eax,ebx,ecx,edx, esi ; add round key mov edi, pOut TRANSPOSE edi add esp, stackSize ; remove state REST_GPR ret ENDFUNC Safe2Decrypt_RIJ128 %endif ; _IPP == _IPP_M5 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128safedecv8as.asm000066400000000000000000000405471470420105600272020ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael-128 (AES) cipher functions. ; (It's the special free from Sbox/tables implementation) ; ; Content: ; SafeDecrypt_RIJ128() ; ; History: ; ; Notes. ; The implementation is based on ; isomorphism between native GF(2^8) and composite GF((2^4)^2). ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_V8) %macro PTRANSFORM 6.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%memTransLO %3 %xdefine %%memTransHI %4 %xdefine %%tmp %5 %xdefine %%srcLO %6 movdqa %%dst, oword [%%memTransLO] ;; LO transformation movdqa %%tmp, oword [%%memTransHI] ;; HI transformation movdqa %%srcLO, %%src ;; split src: psrlw %%src, 4 ;; pand %%srcLO, xmm7 ;; low 4 bits -> srcLO pand %%src, xmm7 ;; upper 4 bits -> src pshufb %%dst, %%srcLO ;; transformation pshufb %%tmp, %%src pxor %%dst, %%tmp %endmacro %macro PLOOKUP_MEM 3.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%Table %3 movdqa %%dst, OWORD %%Table pshufb %%dst,%%src %endmacro %macro PREDUCE_MOD15 2.nolist %xdefine %%dst %1 %xdefine %%src %2 movdqa %%dst, %%src pcmpgtb %%src, xmm7 psubb %%dst, %%src %endmacro %macro PINVERSE_GF16_INV 6.nolist %xdefine %%xmmB %1 %xdefine %%xmmC %2 %xdefine %%xmmP %3 %xdefine %%xmmQ %4 %xdefine %%xmmD %5 %xdefine %%xmmT %6 PLOOKUP_MEM %%xmmT, %%xmmC, [eax+(GF16_logTbl-DECODE_DATA)] ;; xmmT = index_of(c) pxor %%xmmC, %%xmmB PLOOKUP_MEM %%xmmQ, %%xmmC, [eax+(GF16_logTbl-DECODE_DATA)] ;; xmmQ = index_of(b xor c) PLOOKUP_MEM %%xmmD, %%xmmB, [eax+(GF16_sqr1-DECODE_DATA)] ;; xmmD = sqr(b)*beta^14 PLOOKUP_MEM %%xmmP, %%xmmB, [eax+(GF16_logTbl-DECODE_DATA)] ;; xmmP = index_of(b) paddb %%xmmT, %%xmmQ ;; xmmT = index_of(c) + index_of(b xor c) PREDUCE_MOD15 %%xmmC, %%xmmT ;; PLOOKUP_MEM %%xmmT, %%xmmC, [eax+(GF16_expTbl-DECODE_DATA)] ;; c*(b xor c) pxor %%xmmD, %%xmmT ;; xmmD = delta = (c*(b xor c)) xor (sqr(b)*beta^14) PLOOKUP_MEM %%xmmT, %%xmmD, [eax+(GF16_invLog-DECODE_DATA)] ;; xmmT = index_of( inv(delta) ) paddb %%xmmQ, %%xmmT ;; xmmQ = index_of((b xor c) * inv(delta)) paddb %%xmmP, %%xmmT ;; xmmP = index_of(b * inv(delta)) PREDUCE_MOD15 %%xmmT, %%xmmQ PLOOKUP_MEM %%xmmC, %%xmmT, [eax+(GF16_expTbl-DECODE_DATA)] PREDUCE_MOD15 %%xmmT, %%xmmP PLOOKUP_MEM %%xmmB, %%xmmT, [eax+(GF16_expTbl-DECODE_DATA)] %endmacro segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR DECODE_DATA: ;; (forward) native GF(2^8) to composite GF((2^4)^2) transformation : {0x01,0x2E,0x49,0x43,0x35,0xD0,0x3D,0xE9} TransFwdLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 02Eh ;; 02Eh ;; 2 DB 02Fh ;; 02Eh XOR 001h ;; 3 DB 049h ;; 049h ;; 4 DB 048h ;; 049h XOR 001h ;; 5 DB 067h ;; 049h XOR 02Eh ;; 6 DB 066h ;; 049h XOR 02Eh XOR 001h ;; 7 DB 043h ;; 043h ;; 8 DB 042h ;; 043h XOR 001h ;; 9 DB 06Dh ;; 043h XOR 02Eh ;; a DB 06Ch ;; 043h XOR 02Eh XOR 001h ;; b DB 00Ah ;; 043h XOR 049h ;; c DB 00Bh ;; 043h XOR 049h XOR 001h ;; d DB 024h ;; 043h XOR 049h XOR 02Eh ;; e DB 025h ;; 043h XOR 049h XOR 02Eh XOR 001h ;; f TransFwdHI \ DB 000h ;; 000h ;; 0 DB 035h ;; 035h ;; 1 DB 0D0h ;; 0D0h ;; 2 DB 0E5h ;; 0D0h XOR 035h ;; 3 DB 03Dh ;; 03Dh ;; 4 DB 008h ;; 03Dh XOR 035h ;; 5 DB 0EDh ;; 03Dh XOR 0D0h ;; 6 DB 0D8h ;; 03Dh XOR 0D0h XOR 035h ;; 7 DB 0E9h ;; 0E9h ;; 8 DB 0DCh ;; 0E9h XOR 035h ;; 9 DB 039h ;; 0E9h XOR 0D0h ;; a DB 00Ch ;; 0E9h XOR 0D0h XOR 035h ;; b DB 0D4h ;; 0E9h XOR 03Dh ;; c DB 0E1h ;; 0E9h XOR 03Dh XOR 035h ;; d DB 004h ;; 0E9h XOR 03Dh XOR 0D0h ;; e DB 031h ;; 0E9h XOR 03Dh XOR 0D0h XOR 035h ;; f ;; (inverse) composite GF((2^4)^2) to native GF(2^8) transformation : {0x01,0x5C,0xE0,0x50,0x1F,0xEE,0x55,0x6A} TransInvLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 05Ch ;; 05Ch ;; 2 DB 05Dh ;; 05Ch XOR 001h ;; 3 DB 0E0h ;; 0E0h ;; 4 DB 0E1h ;; 0E0h XOR 001h ;; 5 DB 0BCh ;; 0E0h XOR 05Ch ;; 6 DB 0BDh ;; 0E0h XOR 05Ch XOR 001h ;; 7 DB 050h ;; 050h ;; 8 DB 051h ;; 050h XOR 001h ;; 9 DB 00Ch ;; 050h XOR 05Ch ;; a DB 00Dh ;; 050h XOR 05Ch XOR 001h ;; b DB 0B0h ;; 050h XOR 0E0h ;; c DB 0B1h ;; 050h XOR 0E0h XOR 001h ;; d DB 0ECh ;; 050h XOR 0E0h XOR 05Ch ;; e DB 0EDh ;; 050h XOR 0E0h XOR 05Ch XOR 001h ;; f TransInvHI \ DB 000h ;; 000h ;; 0 DB 01Fh ;; 01Fh ;; 1 DB 0EEh ;; 0EEh ;; 2 DB 0F1h ;; 0EEh XOR 01Fh ;; 3 DB 055h ;; 055h ;; 4 DB 04Ah ;; 055h XOR 01Fh ;; 5 DB 0BBh ;; 055h XOR 0EEh ;; 6 DB 0A4h ;; 055h XOR 0EEh XOR 01Fh ;; 7 DB 06Ah ;; 06Ah ;; 8 DB 075h ;; 06Ah XOR 01Fh ;; 9 DB 084h ;; 06Ah XOR 0EEh ;; a DB 09Bh ;; 06Ah XOR 0EEh XOR 01Fh ;; b DB 03Fh ;; 06Ah XOR 055h ;; c DB 020h ;; 06Ah XOR 055h XOR 01Fh ;; d DB 0D1h ;; 06Ah XOR 055h XOR 0EEh ;; e DB 0CEh ;; 06Ah XOR 055h XOR 0EEh XOR 01Fh ;; f GF16_csize DB 00Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh ;; GF16 elements: ;; 0 1 2 3 4 5 6 7 8 9 A B C D E F GF16_logTbl \ DB 0C0h,00h,01h,04h,02h,08h,05h,0Ah,03h,0Eh,09h,07h,06h,0Dh,0Bh,0Ch GF16_expTbl \ DB 001h,02h,04h,08h,03h,06h,0Ch,0Bh,05h,0Ah,07h,0Eh,0Fh,0Dh,09h,01h GF16_sqr1 \ DB 000h,09h,02h,0Bh,08h,01h,0Ah,03h,06h,0Fh,04h,0Dh,0Eh,07h,0Ch,05h ;; sqr(GF16_element) * beta^14 GF16_invLog \ DB 0C0h,00h,0Eh,0Bh,0Dh,07h,0Ah,05h,0Ch,01h,06h,08h,09h,02h,04h,03h ;; affine transformation matrix (inverse cipher) : {0x50,0x36,0x15,0x82,0x01,0x34,0x40,0x3E} InvAffineLO \ DB 000h ;; 000h ;; 0 DB 050h ;; 050h ;; 1 DB 036h ;; 036h ;; 2 DB 066h ;; 036h XOR 050h ;; 3 DB 015h ;; 015h ;; 4 DB 045h ;; 015h XOR 050h ;; 5 DB 023h ;; 015h XOR 036h ;; 6 DB 073h ;; 015h XOR 036h XOR 050h ;; 7 DB 082h ;; 082h ;; 8 DB 0D2h ;; 082h XOR 050h ;; 9 DB 0B4h ;; 082h XOR 036h ;; a DB 0E4h ;; 082h XOR 036h XOR 050h ;; b DB 097h ;; 082h XOR 015h ;; c DB 0C7h ;; 082h XOR 015h XOR 050h ;; d DB 0A1h ;; 082h XOR 015h XOR 036h ;; e DB 0F1h ;; 082h XOR 015h XOR 036h XOR 050h ;; f InvAffineHI \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 034h ;; 034h ;; 2 DB 035h ;; 034h XOR 001h ;; 3 DB 040h ;; 040h ;; 4 DB 041h ;; 040h XOR 001h ;; 5 DB 074h ;; 040h XOR 034h ;; 6 DB 075h ;; 040h XOR 034h XOR 001h ;; 7 DB 03Eh ;; 03Eh ;; 8 DB 03Fh ;; 03Eh XOR 001h ;; 9 DB 00Ah ;; 03Eh XOR 034h ;; a DB 00Bh ;; 03Eh XOR 034h XOR 001h ;; b DB 07Eh ;; 03Eh XOR 040h ;; c DB 07Fh ;; 03Eh XOR 040h XOR 001h ;; d DB 04Ah ;; 03Eh XOR 040h XOR 034h ;; e DB 04Bh ;; 03Eh XOR 040h XOR 034h XOR 001h ;; f ;; affine transformation constant (inverse cipher) InvAffineCnt \ DQ 04848484848484848h,04848484848484848h ;; shift rows transformation (inverse cipher) InvShiftRows \ DB 0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3 ;; mix columns transformation (inverse cipher) GF16mul_4_2x \ DB 000h,024h,048h,06Ch,083h,0A7h,0CBh,0EFh,036h,012h,07Eh,05Ah,0B5h,091h,0FDh,0D9h ;; *(4+2x) GF16mul_1_6x \ DB 000h,061h,0C2h,0A3h,0B4h,0D5h,076h,017h,058h,039h,09Ah,0FBh,0ECh,08Dh,02Eh,04Fh ;; *(1+6x) GF16mul_C_6x \ DB 000h,06Ch,0CBh,0A7h,0B5h,0D9h,07Eh,012h,05Ah,036h,091h,0FDh,0EFh,083h,024h,048h ;; *(C+6x) GF16mul_3_Ax \ DB 000h,0A3h,076h,0D5h,0ECh,04Fh,09Ah,039h,0FBh,058h,08Dh,02Eh,017h,0B4h,061h,0C2h ;; *(3+Ax) GF16mul_B_0x \ DB 000h,00Bh,005h,00Eh,00Ah,001h,00Fh,004h,007h,00Ch,002h,009h,00Dh,006h,008h,003h ;; *(B+0x) GF16mul_0_Bx \ DB 000h,0B0h,050h,0E0h,0A0h,010h,0F0h,040h,070h,0C0h,020h,090h,0D0h,060h,080h,030h ;; *(0+Bx) GF16mul_2_4x \ DB 000h,042h,084h,0C6h,038h,07Ah,0BCh,0FEh,063h,021h,0E7h,0A5h,05Bh,019h,0DFh,09Dh ;; *(2+4x) GF16mul_2_6x \ DB 000h,062h,0C4h,0A6h,0B8h,0DAh,07Ch,01Eh,053h,031h,097h,0F5h,0EBh,089h,02Fh,04Dh ;; *(2+6x) ColumnROR \ DB 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12 ;************************************************************* ; convert GF(2^128) -> GF((2^4)^2) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM TransformNative2Composite,PUBLIC USES_GPR esi,edi %xdefine pOutBlk [esp + ARG_1 + 0*sizeof(dword)] ; output block address %xdefine pInpBlk [esp + ARG_1 + 1*sizeof(dword)] ; input block address LD_ADDR eax, DECODE_DATA mov edi,pOutBlk ; output data address mov esi,pInpBlk ; input data address movdqa xmm7, oword [eax+(GF16_csize-DECODE_DATA)] ;; convert input into the composite GF((2^4)^2) movdqu xmm0, oword [esi] ; input block PTRANSFORM xmm1, xmm0, {eax+(TransFwdLO-DECODE_DATA)},{eax+(TransFwdHI-DECODE_DATA)}, xmm2, xmm3 movdqu oword [edi], xmm1 ; output block REST_GPR ret ENDFUNC TransformNative2Composite align IPP_ALIGN_FACTOR ;************************************************************* ;* void SafeDecrypt_RIJ128( ;* const Ipp32u* pInpBlk, ;* Ipp32u* pOutBlk, ;* int nr, ;* const Ipp32u* pKeys, ;* const void* Tables) ;************************************************************* ;; ;; Lib = V8 ;; IPPASM SafeDecrypt_RIJ128,PUBLIC USES_GPR esi,edi %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %assign RSIZE sizeof(dword) ; size of row %assign SC 4 ; columns in STATE %assign SSIZE RSIZE*SC ; size of state mov edx, pKey mov ecx, nr mov esi,pInpBlk ; input data address mov edi,pOutBlk ; output data address lea eax,[ecx*4] lea edx,[edx+eax*4] ; AES-128-keys LD_ADDR eax, DECODE_DATA movdqu xmm0, oword [esi] ; input block movdqa xmm7, oword [eax+(GF16_csize-DECODE_DATA)] ;; convert input into the composite GF((2^4)^2) PTRANSFORM xmm2,xmm0, {eax+(TransFwdLO-DECODE_DATA)},{eax+(TransFwdHI-DECODE_DATA)}, xmm1,xmm3 ;; initial whitening pxor xmm2, oword [edx] sub edx, SSIZE ;; (nr-1) regular rounds sub ecx,1 .decode_round: ;; InvSubByte() Transformation: ;; affine transformation PTRANSFORM xmm0,xmm2, {eax+(InvAffineLO-DECODE_DATA)},{eax+(InvAffineHI-DECODE_DATA)}, xmm1,xmm3 pxor xmm0, oword [eax+(InvAffineCnt-DECODE_DATA)] ; H(c), c=0x05 ;; split input by low and upper parts movdqa xmm1, xmm0 pand xmm0, xmm7 ; upper parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; low parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_INV xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; InvShiftRows() Transformation: pshufb xmm0, [eax+(InvShiftRows-DECODE_DATA)] pshufb xmm1, [eax+(InvShiftRows-DECODE_DATA)] ;; InvMixColumn() Transformation: PLOOKUP_MEM xmm2, xmm0, [eax+(GF16mul_4_2x-DECODE_DATA)] ; mul H(0xE) = 0x24 pshufb xmm0, [eax+(ColumnROR-DECODE_DATA)] PLOOKUP_MEM xmm3, xmm1, [eax+(GF16mul_1_6x-DECODE_DATA)] pshufb xmm1, [eax+(ColumnROR-DECODE_DATA)] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm0, [eax+(GF16mul_C_6x-DECODE_DATA)] ; mul H(0xB) = 0x6C pshufb xmm0, [eax+(ColumnROR-DECODE_DATA)] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm1, [eax+(GF16mul_3_Ax-DECODE_DATA)] pshufb xmm1, [eax+(ColumnROR-DECODE_DATA)] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm0, [eax+(GF16mul_B_0x-DECODE_DATA)] ; mul H(0xD) = 0x0B pshufb xmm0, [eax+(ColumnROR-DECODE_DATA)] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm1, [eax+(GF16mul_0_Bx-DECODE_DATA)] pshufb xmm1, [eax+(ColumnROR-DECODE_DATA)] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm0, [eax+(GF16mul_2_4x-DECODE_DATA)] ; mul H(0x9) = 0x42 pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm1, [eax+(GF16mul_2_6x-DECODE_DATA)] pxor xmm2, xmm3 ;; AddRoundKey() Transformation: pxor xmm2, oword [edx] sub edx, SSIZE sub ecx,1 jg .decode_round ;; ;; the last one is irregular ;; ;; InvSubByte() Transformation: ;; affine transformation PTRANSFORM xmm0,xmm2, {eax+(InvAffineLO-DECODE_DATA)},{eax+(InvAffineHI-DECODE_DATA)}, xmm1,xmm3 pxor xmm0, oword [eax+(InvAffineCnt-DECODE_DATA)] ; H(c), c=0x05 ;; split input by low and upper parts movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_INV xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; InvShiftRows() Transformation: psllw xmm1, 4 por xmm1, xmm0 pshufb xmm1, [eax+(InvShiftRows-DECODE_DATA)] ;; AddRoundKey() Transformation: pxor xmm1, oword [edx] sub edx, SSIZE ;; convert output into the native GF(2^8) PTRANSFORM xmm0,xmm1, {eax+(TransInvLO-DECODE_DATA)},{eax+(TransInvHI-DECODE_DATA)}, xmm2, xmm3 movdqu oword [edi], xmm0 REST_GPR ret ENDFUNC SafeDecrypt_RIJ128 %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprij128safeencv8as.asm000066400000000000000000000350661470420105600272140ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael-128 (AES) cipher functions. ; (It's the special free from Sbox/tables implementation) ; ; Content: ; SafeEncrypt_RIJ128() ; ; History: ; ; Notes. ; The implementation is based on ; isomorphism between native GF(2^8) and composite GF((2^4)^2). ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_V8) %macro PTRANSFORM 6.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%memTransLO %3 %xdefine %%memTransHI %4 %xdefine %%tmp %5 %xdefine %%srcLO %6 movdqa %%dst, oword [%%memTransLO] ;; LO transformation movdqa %%tmp, oword [%%memTransHI] ;; HI transformation movdqa %%srcLO, %%src ;; split src: psrlw %%src, 4 ;; pand %%srcLO, xmm7 ;; low 4 bits -> srcLO pand %%src, xmm7 ;; upper 4 bits -> src pshufb %%dst, %%srcLO ;; transformation pshufb %%tmp, %%src pxor %%dst, %%tmp %endmacro %macro PLOOKUP_MEM 3.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%Table %3 movdqa %%dst, OWORD %%Table pshufb %%dst,%%src %endmacro %macro PREDUCE_MOD15 2.nolist %xdefine %%dst %1 %xdefine %%src %2 movdqa %%dst, %%src pcmpgtb %%src, xmm7 psubb %%dst, %%src %endmacro %macro PINVERSE_GF16_FWD 6.nolist %xdefine %%xmmB %1 %xdefine %%xmmC %2 %xdefine %%xmmP %3 %xdefine %%xmmQ %4 %xdefine %%xmmD %5 %xdefine %%xmmT %6 PLOOKUP_MEM %%xmmT, %%xmmC, [eax+(GF16_logTbl-ENCODE_DATA)] ;; xmmT = index_of(c) pxor %%xmmC, %%xmmB PLOOKUP_MEM %%xmmQ, %%xmmC, [eax+(GF16_logTbl-ENCODE_DATA)] ;; xmmQ = index_of(b xor c) PLOOKUP_MEM %%xmmD, %%xmmB, [eax+(GF16_sqr1-ENCODE_DATA)] ;; xmmD = sqr(b)*beta^14 PLOOKUP_MEM %%xmmP, %%xmmB, [eax+(GF16_logTbl-ENCODE_DATA)] ;; xmmP = index_of(b) paddb %%xmmT, %%xmmQ ;; xmmT = index_of(c) + index_of(b xor c) PREDUCE_MOD15 %%xmmC, %%xmmT ;; PLOOKUP_MEM %%xmmT, %%xmmC, [eax+(GF16_expTbl-ENCODE_DATA)] ;; c*(b xor c) pxor %%xmmD, %%xmmT ;; xmmD = delta = (c*(b xor c)) xor (sqr(b)*beta^14) PLOOKUP_MEM %%xmmT, %%xmmD, [eax+(GF16_invLog-ENCODE_DATA)] ;; xmmT = index_of( inv(delta) ) paddb %%xmmQ, %%xmmT ;; xmmQ = index_of((b xor c) * inv(delta)) paddb %%xmmP, %%xmmT ;; xmmP = index_of(b * inv(delta)) PREDUCE_MOD15 %%xmmT, %%xmmQ PLOOKUP_MEM %%xmmC, %%xmmT, [eax+(GF16_expTbl-ENCODE_DATA)] PREDUCE_MOD15 %%xmmT, %%xmmP PLOOKUP_MEM %%xmmB, %%xmmT, [eax+(GF16_expTbl-ENCODE_DATA)] %endmacro segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ENCODE_DATA: ;; (forward) native GF(2^8) to composite GF((2^4)^2) transformation : {0x01,0x2E,0x49,0x43,0x35,0xD0,0x3D,0xE9} TransFwdLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 02Eh ;; 02Eh ;; 2 DB 02Fh ;; 02Eh XOR 001h ;; 3 DB 049h ;; 049h ;; 4 DB 048h ;; 049h XOR 001h ;; 5 DB 067h ;; 049h XOR 02Eh ;; 6 DB 066h ;; 049h XOR 02Eh XOR 001h ;; 7 DB 043h ;; 043h ;; 8 DB 042h ;; 043h XOR 001h ;; 9 DB 06Dh ;; 043h XOR 02Eh ;; a DB 06Ch ;; 043h XOR 02Eh XOR 001h ;; b DB 00Ah ;; 043h XOR 049h ;; c DB 00Bh ;; 043h XOR 049h XOR 001h ;; d DB 024h ;; 043h XOR 049h XOR 02Eh ;; e DB 025h ;; 043h XOR 049h XOR 02Eh XOR 001h ;; f TransFwdHI \ DB 000h ;; 000h ;; 0 DB 035h ;; 035h ;; 1 DB 0D0h ;; 0D0h ;; 2 DB 0E5h ;; 0D0h XOR 035h ;; 3 DB 03Dh ;; 03Dh ;; 4 DB 008h ;; 03Dh XOR 035h ;; 5 DB 0EDh ;; 03Dh XOR 0D0h ;; 6 DB 0D8h ;; 03Dh XOR 0D0h XOR 035h ;; 7 DB 0E9h ;; 0E9h ;; 8 DB 0DCh ;; 0E9h XOR 035h ;; 9 DB 039h ;; 0E9h XOR 0D0h ;; a DB 00Ch ;; 0E9h XOR 0D0h XOR 035h ;; b DB 0D4h ;; 0E9h XOR 03Dh ;; c DB 0E1h ;; 0E9h XOR 03Dh XOR 035h ;; d DB 004h ;; 0E9h XOR 03Dh XOR 0D0h ;; e DB 031h ;; 0E9h XOR 03Dh XOR 0D0h XOR 035h ;; f ;; (inverse) composite GF((2^4)^2) to native GF(2^8) transformation : {0x01,0x5C,0xE0,0x50,0x1F,0xEE,0x55,0x6A} TransInvLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 05Ch ;; 05Ch ;; 2 DB 05Dh ;; 05Ch XOR 001h ;; 3 DB 0E0h ;; 0E0h ;; 4 DB 0E1h ;; 0E0h XOR 001h ;; 5 DB 0BCh ;; 0E0h XOR 05Ch ;; 6 DB 0BDh ;; 0E0h XOR 05Ch XOR 001h ;; 7 DB 050h ;; 050h ;; 8 DB 051h ;; 050h XOR 001h ;; 9 DB 00Ch ;; 050h XOR 05Ch ;; a DB 00Dh ;; 050h XOR 05Ch XOR 001h ;; b DB 0B0h ;; 050h XOR 0E0h ;; c DB 0B1h ;; 050h XOR 0E0h XOR 001h ;; d DB 0ECh ;; 050h XOR 0E0h XOR 05Ch ;; e DB 0EDh ;; 050h XOR 0E0h XOR 05Ch XOR 001h ;; f TransInvHI \ DB 000h ;; 000h ;; 0 DB 01Fh ;; 01Fh ;; 1 DB 0EEh ;; 0EEh ;; 2 DB 0F1h ;; 0EEh XOR 01Fh ;; 3 DB 055h ;; 055h ;; 4 DB 04Ah ;; 055h XOR 01Fh ;; 5 DB 0BBh ;; 055h XOR 0EEh ;; 6 DB 0A4h ;; 055h XOR 0EEh XOR 01Fh ;; 7 DB 06Ah ;; 06Ah ;; 8 DB 075h ;; 06Ah XOR 01Fh ;; 9 DB 084h ;; 06Ah XOR 0EEh ;; a DB 09Bh ;; 06Ah XOR 0EEh XOR 01Fh ;; b DB 03Fh ;; 06Ah XOR 055h ;; c DB 020h ;; 06Ah XOR 055h XOR 01Fh ;; d DB 0D1h ;; 06Ah XOR 055h XOR 0EEh ;; e DB 0CEh ;; 06Ah XOR 055h XOR 0EEh XOR 01Fh ;; f GF16_csize DB 00Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh ;; GF16 elements: ;; 0 1 2 3 4 5 6 7 8 9 A B C D E F GF16_logTbl \ DB 0C0h,00h,01h,04h,02h,08h,05h,0Ah,03h,0Eh,09h,07h,06h,0Dh,0Bh,0Ch GF16_expTbl \ DB 001h,02h,04h,08h,03h,06h,0Ch,0Bh,05h,0Ah,07h,0Eh,0Fh,0Dh,09h,01h GF16_sqr1 \ DB 000h,09h,02h,0Bh,08h,01h,0Ah,03h,06h,0Fh,04h,0Dh,0Eh,07h,0Ch,05h ;; sqr(GF16_element) * beta^14 GF16_invLog \ DB 0C0h,00h,0Eh,0Bh,0Dh,07h,0Ah,05h,0Ch,01h,06h,08h,09h,02h,04h,03h GF16_expTbl_shift \ DB 010h,020h,040h,080h,030h,060h,0C0h,0B0h,050h,0A0h,070h,0E0h,0F0h,0D0h,090h,010h ;; affine transformation matrix (forward cipher) : {0x10,0x22,0x55,0x82,0x41,0x34,0x40,0x2A} FwdAffineLO \ DB 000h ;; 000h ;; 0 DB 010h ;; 010h ;; 1 DB 022h ;; 022h ;; 2 DB 032h ;; 022h XOR 010h ;; 3 DB 055h ;; 055h ;; 4 DB 045h ;; 055h XOR 010h ;; 5 DB 077h ;; 055h XOR 022h ;; 6 DB 067h ;; 055h XOR 022h XOR 010h ;; 7 DB 082h ;; 082h ;; 8 DB 092h ;; 082h XOR 010h ;; 9 DB 0A0h ;; 082h XOR 022h ;; a DB 0B0h ;; 082h XOR 022h XOR 010h ;; b DB 0D7h ;; 082h XOR 055h ;; c DB 0C7h ;; 082h XOR 055h XOR 010h ;; d DB 0F5h ;; 082h XOR 055h XOR 022h ;; e DB 0E5h ;; 082h XOR 055h XOR 022h XOR 010h ;; f FwdAffineHI \ DB 000h ;; 000h ;; 0 DB 041h ;; 041h ;; 1 DB 034h ;; 034h ;; 2 DB 075h ;; 034h XOR 041h ;; 3 DB 040h ;; 040h ;; 4 DB 001h ;; 040h XOR 041h ;; 5 DB 074h ;; 040h XOR 034h ;; 6 DB 035h ;; 040h XOR 034h XOR 041h ;; 7 DB 02Ah ;; 02Ah ;; 8 DB 06Bh ;; 02Ah XOR 041h ;; 9 DB 01Eh ;; 02Ah XOR 034h ;; a DB 05Fh ;; 02Ah XOR 034h XOR 041h ;; b DB 06Ah ;; 02Ah XOR 040h ;; c DB 02Bh ;; 02Ah XOR 040h XOR 041h ;; d DB 05Eh ;; 02Ah XOR 040h XOR 034h ;; e DB 01Fh ;; 02Ah XOR 040h XOR 034hXOR 041h ;; f ;; affine transformation constant (forward cipher) FwdAffineCnt \ DQ 0C2C2C2C2C2C2C2C2h,0C2C2C2C2C2C2C2C2h ;; shift rows transformation (forward cipher) FwdShiftRows \ DB 0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11 ;; mix columns transformation (forward cipher) GF16mul_E_2x \ DB 000h,02Eh,04Fh,061h,08Dh,0A3h,0C2h,0ECh,039h,017h,076h,058h,0B4h,09Ah,0FBh,0D5h GF16mul_1_Cx \ DB 000h,0C1h,0B2h,073h,054h,095h,0E6h,027h,0A8h,069h,01Ah,0DBh,0FCh,03Dh,04Eh,08Fh ColumnROR \ DB 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12 align IPP_ALIGN_FACTOR ;************************************************************* ;* void SafeEncrypt_RIJ128( ;* const Ipp32u* pInpBlk, ;* Ipp32u* pOutBlk, ;* int nr, ;* const Ipp32u* pKeys, ;* const void* Tables); ;* ;************************************************************* ;; ;; Lib = V8 ;; IPPASM SafeEncrypt_RIJ128,PUBLIC USES_GPR esi,edi %xdefine pInpBlk [esp + ARG_1 + 0*sizeof(dword)] ; input block address %xdefine pOutBlk [esp + ARG_1 + 1*sizeof(dword)] ; output block address %xdefine nr [esp + ARG_1 + 2*sizeof(dword)] ; number of rounds %xdefine pKey [esp + ARG_1 + 3*sizeof(dword)] ; key material address %assign RSIZE sizeof(dword) ; size of row %assign SC 4 ; columns in STATE %assign SSIZE RSIZE*SC ; size of state mov esi, pInpBlk mov edi, pOutBlk mov edx, pKey mov ecx, nr LD_ADDR eax, ENCODE_DATA movdqu xmm1, oword [esi] ; input block movdqa xmm7, oword [eax+(GF16_csize-ENCODE_DATA)] ;; convert input into the composite GF((2^4)^2) PTRANSFORM xmm0,xmm1, {eax+(TransFwdLO-ENCODE_DATA)},{eax+(TransFwdHI-ENCODE_DATA)}, xmm2,xmm3 ;; initial whitening pxor xmm0, oword [edx] add edx, SSIZE ;; (nr-1) regular rounds sub ecx,1 .encode_round: ;; SubByte() Transformation: ;; split input by low and upper parts movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_FWD xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; affine transformation movdqa xmm3, oword [eax+(FwdAffineLO-ENCODE_DATA)] movdqa xmm2, oword [eax+(FwdAffineHI-ENCODE_DATA)] movdqa xmm4, oword [eax+(FwdAffineCnt-ENCODE_DATA)] ; H(c), c=0x63 pshufb xmm3, xmm0 pshufb xmm2, xmm1 pxor xmm3, xmm4 pxor xmm3, xmm2 ;; ShiftRows() Transformation: pshufb xmm3, [eax+(FwdShiftRows-ENCODE_DATA)] ;; MixColumn() Transformation: movdqa xmm1, xmm3 movdqa xmm2, xmm3 pxor xmm4, xmm4 psrlw xmm2, 4 pand xmm1, xmm7 ;; a0*(0xE + 0x2*t) PLOOKUP_MEM xmm0, xmm1, [eax+(GF16mul_E_2x-ENCODE_DATA)] pand xmm2, xmm7 ;; a1*(0x2*0x9 + (0x2+0xE)*t) PLOOKUP_MEM xmm1, xmm2, [eax+(GF16mul_1_Cx-ENCODE_DATA)] pxor xmm0, xmm1 pshufb xmm3, [eax+(ColumnROR-ENCODE_DATA)] pxor xmm4, xmm3 pshufb xmm3, [eax+(ColumnROR-ENCODE_DATA)] pxor xmm4, xmm3 movdqa xmm2, xmm0 pshufb xmm2, [eax+(ColumnROR-ENCODE_DATA)] pxor xmm0, xmm2 pshufb xmm3, [eax+(ColumnROR-ENCODE_DATA)] pxor xmm4, xmm3 pxor xmm0, xmm4 ;; AddRoundKey() Transformation: pxor xmm0, oword [edx] add edx, SSIZE sub ecx,1 jg .encode_round ;; ;; the last one is irregular ;; ;; SubByte() Transformation: movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_FWD xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; affine transformation movdqa xmm3, oword [eax+(FwdAffineLO-ENCODE_DATA)] movdqa xmm2, oword [eax+(FwdAffineHI-ENCODE_DATA)] movdqa xmm4, oword [eax+(FwdAffineCnt-ENCODE_DATA)] ; H(c), c=0x63 pshufb xmm3, xmm0 pshufb xmm2, xmm1 pxor xmm3, xmm4 pxor xmm3, xmm2 ;; ShiftRows() Transformation: pshufb xmm3, [eax+(FwdShiftRows-ENCODE_DATA)] ;; AddRoundKey() Transformation: pxor xmm3, oword [edx] add edx, SSIZE ;; convert output into the native GF(2^8) PTRANSFORM xmm0,xmm3, {eax+(TransInvLO-ENCODE_DATA)},{eax+(TransInvHI-ENCODE_DATA)}, xmm2, xmm1 movdqu oword [edi], xmm0 REST_GPR ret ENDFUNC SafeEncrypt_RIJ128 %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcprijnkeyw7as.asm000066400000000000000000000045541470420105600263210ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Key Expansion Support ; ; Content: ; SubsDword_8uT() ; ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_W7) segment .text align=IPP_ALIGN_FACTOR %xdefine CACHE_LINE_SIZE (64) ;*************************************************************** ;* Purpose: Mitigation of the Key Expansion procedure ;* ;* Ipp32u Touch_SubsDword_8uT(Ipp32u inp, ;* const Ipp8u* pTbl, ;* int tblBytes) ;*************************************************************** align IPP_ALIGN_FACTOR IPPASM Touch_SubsDword_8uT,PUBLIC USES_GPR esi,edi,ebx %xdefine inp [esp + ARG_1 + 0*sizeof(dword)] ; input dword %xdefine pTbl [esp + ARG_1 + 1*sizeof(dword)] ; Rijndael's S-box %xdefine tblLen [esp + ARG_1 + 2*sizeof(dword)] ; length of table (bytes) mov esi, pTbl ; tbl address and mov edx, tblLen ; length xor ecx, ecx .touch_tbl: mov eax, [esi+ecx] add ecx, CACHE_LINE_SIZE cmp ecx, edx jl .touch_tbl mov edx, inp mov eax, edx and eax, 0FFh ; b[0] movzx eax, BYTE [esi+eax] shr edx, 8 mov ebx, edx and ebx, 0FFh ; b[1] movzx ebx, BYTE [esi+ebx] shl ebx, 8 shr edx, 8 mov ecx, edx and ecx, 0FFh ; b[2] movzx ecx, BYTE [esi+ecx] shl ecx, 16 shr edx, 8 movzx edx, BYTE [esi+edx] shl edx, 24 or eax, ebx or eax, ecx or eax, edx REST_GPR ret ENDFUNC Touch_SubsDword_8uT %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha1nias.asm000066400000000000000000000403321470420105600255450ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA-1 ; ; Content: ; UpdateSHA1ni ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_ON_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR CODE_DATA: UPPER_DWORD_MASK \ DQ 00000000000000000h, 0ffffffff00000000h PSHUFFLE_BYTE_FLIP_MASK \ DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 align IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1ni(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** %ifndef _VXWORKS IPPASM UpdateSHA1ni,PUBLIC USES_GPR esi,edi,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pDigest [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to the in/out digest %xdefine pMsg [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to the inp message %xdefine msgLen [ebp + ARG_1 + 2*sizeof(dword)] ; message length %xdefine MBS_SHA1 (64) ; SHA-1 message block length (bytes) %xdefine HASH_PTR edi ; 1st arg %xdefine MSG_PTR esi ; 2nd arg %xdefine MSG_LEN edx ; 3rd arg %xdefine ABCD xmm0 %xdefine E0 xmm1 ; Need two E's b/c they ping pong %xdefine E1 xmm2 %xdefine MSG0 xmm3 %xdefine MSG1 xmm4 %xdefine MSG2 xmm5 %xdefine MSG3 xmm6 %xdefine SHUF_MASK xmm7 ; ; stack frame ; %xdefine abcd_save eax %xdefine e_save eax+sizeof(oword) %xdefine frame_size sizeof(oword)+sizeof(oword) sub esp, (frame_size+16) lea eax, [esp+16] and eax, -16 mov MSG_LEN, msgLen ; message length test MSG_LEN, MSG_LEN jz .quit mov HASH_PTR, pDigest ; digest mov MSG_PTR, pMsg ; and message pointers LD_ADDR ecx, CODE_DATA ;; load initial hash values movdqu ABCD, oword [HASH_PTR] pinsrd E0, dword [HASH_PTR+16], 3 ;pand E0, oword [UPPER_DWORD_MASK] pand E0, oword [ecx+(UPPER_DWORD_MASK-CODE_DATA)] pshufd ABCD, ABCD, 01Bh ;movdqa SHUF_MASK, oword [PSHUFFLE_BYTE_FLIP_MASK] movdqa SHUF_MASK, oword [ecx+(PSHUFFLE_BYTE_FLIP_MASK-CODE_DATA)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: movdqa oword [abcd_save], ABCD movdqa oword [e_save], E0 ;; rounds 0-3 movdqu MSG0, oword [MSG_PTR +0*16] pshufb MSG0, SHUF_MASK paddd E0, MSG0 movdqa E1, ABCD sha1rnds4 ABCD, E0, 0 ;movdqu oword [rcx+16*0], ABCD ;; rounds 4-7 movdqu MSG1, oword [MSG_PTR +1*16] pshufb MSG1, SHUF_MASK sha1nexte E1, MSG1 movdqa E0, ABCD sha1rnds4 ABCD, E1, 0 sha1msg1 MSG0, MSG1 ;movdqu oword [rcx+16*1], ABCD ;; rounds 8-11 movdqu MSG2, oword [MSG_PTR +2*16] pshufb MSG2, SHUF_MASK sha1nexte E0, MSG2 movdqa E1, ABCD sha1rnds4 ABCD, E0, 0 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*2], ABCD ;; rounds 12-15 movdqu MSG3, oword [MSG_PTR +3*16] pshufb MSG3, SHUF_MASK sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 0 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*3], ABCD ;; rounds 16-19 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 0 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*4], ABCD ;; rounds 20-23 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 1 sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*5], ABCD ;; rounds 24-27 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 1 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*6], ABCD ;; rounds 28-31 sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 1 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*7], ABCD ;; rounds 32-35 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 1 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*8], ABCD ;; rounds 36-39 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 1 sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*9], ABCD ;; rounds 40-43 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 2 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*10], ABCD ;; rounds 44-47 sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 2 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*11], ABCD ;; rounds 48-51 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 2 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*12], ABCD ;; rounds 52-55 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 2 sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*13], ABCD ;; rounds 56-59 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 2 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*14], ABCD ;; rounds 60-63 sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 3 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*15], ABCD ;; rounds 64-67 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 3 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*16], ABCD ;; rounds 68-71 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 3 pxor MSG3, MSG1 ;movdqu oword [rcx+16*17], ABCD ;; rounds 72-75 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 3 ;movdqu oword [rcx+16*18], ABCD ;; rounds 76-79 sha1nexte E1, MSG3 movdqa E0, ABCD sha1rnds4 ABCD, E1, 3 ;movdqu oword [rcx+16*19], ABCD ;; add current hash values with previously saved sha1nexte E0, oword [e_save] paddd ABCD, oword [abcd_save] add MSG_PTR, MBS_SHA1 sub MSG_LEN, MBS_SHA1 jg .sha1_block_loop ;; write hash values back in the correct order pshufd ABCD, ABCD, 01Bh movdqu oword [HASH_PTR], ABCD pextrd dword [HASH_PTR+16], E0, 3 .quit: add esp, (frame_size+16) REST_GPR ret ENDFUNC UpdateSHA1ni %else ;; no sha ni support in VxWorks - therefore we temporary use db IPPASM UpdateSHA1ni,PUBLIC USES_GPR esi,edi,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pDigest [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to the in/out digest %xdefine pMsg [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to the inp message %xdefine msgLen [ebp + ARG_1 + 2*sizeof(dword)] ; message length %xdefine MBS_SHA1 (64) ; SHA-1 message block length (bytes) %xdefine HASH_PTR edi ; 1st arg %xdefine MSG_PTR esi ; 2nd arg %xdefine MSG_LEN edx ; 3rd arg %xdefine ABCD xmm0 %xdefine E0 xmm1 ; Need two E's b/c they ping pong %xdefine E1 xmm2 %xdefine MSG0 xmm3 %xdefine MSG1 xmm4 %xdefine MSG2 xmm5 %xdefine MSG3 xmm6 %xdefine SHUF_MASK xmm7 ; ; stack frame ; %xdefine abcd_save eax %xdefine e_save eax+sizeof(oword) %xdefine frame_size sizeof(oword)+sizeof(oword) sub esp, (frame_size+16) lea eax, [esp+16] and eax, -16 mov MSG_LEN, msgLen ; message length test MSG_LEN, MSG_LEN jz .quit mov HASH_PTR, pDigest ; digest mov MSG_PTR, pMsg ; and message pointers LD_ADDR ecx, CODE_DATA ;; load initial hash values movdqu ABCD, oword [HASH_PTR] pinsrd E0, dword [HASH_PTR+16], 3 ;pand E0, oword [UPPER_DWORD_MASK] pand E0, oword [ecx+(UPPER_DWORD_MASK-CODE_DATA)] pshufd ABCD, ABCD, 01Bh ;movdqa SHUF_MASK, oword [PSHUFFLE_BYTE_FLIP_MASK] movdqa SHUF_MASK, oword [ecx+(PSHUFFLE_BYTE_FLIP_MASK-CODE_DATA)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: movdqa oword [abcd_save], ABCD movdqa oword [e_save], E0 ;; rounds 0-3 movdqu MSG0, oword [MSG_PTR +0*16] pshufb MSG0, SHUF_MASK paddd E0, MSG0 movdqa E1, ABCD db 0FH,03AH,0CCH,0C1H,00H ;; sha1rnds4 ABCD, E0, 0 ;movdqu oword [rcx+16*0], ABCD ;; rounds 4-7 movdqu MSG1, oword [MSG_PTR +1*16] pshufb MSG1, SHUF_MASK db 0FH,038H,0C8H,0D4H ;; sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,03AH,0CCH,0C2H,00H ;; sha1rnds4 ABCD, E1, 0 db 0FH,038H,0C9H,0DCH ;; sha1msg1 MSG0, MSG1 ;movdqu oword [rcx+16*1], ABCD ;; rounds 8-11 movdqu MSG2, oword [MSG_PTR +2*16] pshufb MSG2, SHUF_MASK db 0FH,038H,0C8H,0CDH ;; sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,03AH,0CCH,0C1H,00H ;; sha1rnds4 ABCD, E0, 0 db 0FH,038H,0C9H,0E5H ;; sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*2], ABCD ;; rounds 12-15 movdqu MSG3, oword [MSG_PTR +3*16] pshufb MSG3, SHUF_MASK db 0FH,038H,0C8H,0D6H ;; sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,038H,0CAH,0DEH ;; sha1msg2 MSG0, MSG3 db 0FH,03AH,0CCH,0C2H,00H ;; sha1rnds4 ABCD, E1, 0 db 0FH,038H,0C9H,0EEH ;; sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*3], ABCD ;; rounds 16-19 db 0FH,038H,0C8H,0CBH ;; sha1nexte E0, MSG0 movdqa E1, ABCD db 0FH,038H,0CAH,0E3H ;; sha1msg2 MSG1, MSG0 db 0FH,03AH,0CCH,0C1H,00H ;; sha1rnds4 ABCD, E0, 0 db 0FH,038H,0C9H,0F3H ;; sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*4], ABCD ;; rounds 20-23 db 0FH,038H,0C8H,0D4H ;; sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,038H,0CAH,0ECH ;; sha1msg2 MSG2, MSG1 db 0FH,03AH,0CCH,0C2H,01H ;; sha1rnds4 ABCD, E1, 1 db 0FH,038H,0C9H,0DCH ;; sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*5], ABCD ;; rounds 24-27 db 0FH,038H,0C8H,0CDH ;; sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,038H,0CAH,0F5H ;; sha1msg2 MSG3, MSG2 db 0FH,03AH,0CCH,0C1H,01H ;; sha1rnds4 ABCD, E0, 1 db 0FH,038H,0C9H,0E5H ;; sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*6], ABCD ;; rounds 28-31 db 0FH,038H,0C8H,0D6H ;; sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,038H,0CAH,0DEH ;; sha1msg2 MSG0, MSG3 db 0FH,03AH,0CCH,0C2H,01H ;; sha1rnds4 ABCD, E1, 1 db 0FH,038H,0C9H,0EEH ;; sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*7], ABCD ;; rounds 32-35 db 0FH,038H,0C8H,0CBH ;; sha1nexte E0, MSG0 movdqa E1, ABCD db 0FH,038H,0CAH,0E3H ;; sha1msg2 MSG1, MSG0 db 0FH,03AH,0CCH,0C1H,01H ;; sha1rnds4 ABCD, E0, 1 db 0FH,038H,0C9H,0F3H ;; sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*8], ABCD ;; rounds 36-39 db 0FH,038H,0C8H,0D4H ;; sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,038H,0CAH,0ECH ;; sha1msg2 MSG2, MSG1 db 0FH,03AH,0CCH,0C2H,01H ;; sha1rnds4 ABCD, E1, 1 db 0FH,038H,0C9H,0DCH ;; sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*9], ABCD ;; rounds 40-43 db 0FH,038H,0C8H,0CDH ;; sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,038H,0CAH,0F5H ;; sha1msg2 MSG3, MSG2 db 0FH,03AH,0CCH,0C1H,02H ;; sha1rnds4 ABCD, E0, 2 db 0FH,038H,0C9H,0E5H ;; sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*10], ABCD ;; rounds 44-47 db 0FH,038H,0C8H,0D6H ;; sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,038H,0CAH,0DEH ;; sha1msg2 MSG0, MSG3 db 0FH,03AH,0CCH,0C2H,02H ;; sha1rnds4 ABCD, E1, 2 db 0FH,038H,0C9H,0EEH ;; sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*11], ABCD ;; rounds 48-51 db 0FH,038H,0C8H,0CBH ;; sha1nexte E0, MSG0 movdqa E1, ABCD db 0FH,038H,0CAH,0E3H ;; sha1msg2 MSG1, MSG0 db 0FH,03AH,0CCH,0C1H,02H ;; sha1rnds4 ABCD, E0, 2 db 0FH,038H,0C9H,0F3H ;; sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*12], ABCD ;; rounds 52-55 db 0FH,038H,0C8H,0D4H ;; sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,038H,0CAH,0ECH ;; sha1msg2 MSG2, MSG1 db 0FH,03AH,0CCH,0C2H,02H ;; sha1rnds4 ABCD, E1, 2 db 0FH,038H,0C9H,0DCH ;; sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*13], ABCD ;; rounds 56-59 db 0FH,038H,0C8H,0CDH ;; sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,038H,0CAH,0F5H ;; sha1msg2 MSG3, MSG2 db 0FH,03AH,0CCH,0C1H,02H ;; sha1rnds4 ABCD, E0, 2 db 0FH,038H,0C9H,0E5H ;; sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*14], ABCD ;; rounds 60-63 db 0FH,038H,0C8H,0D6H ;; sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,038H,0CAH,0DEH ;; sha1msg2 MSG0, MSG3 db 0FH,03AH,0CCH,0C2H,03H ;; sha1rnds4 ABCD, E1, 3 db 0FH,038H,0C9H,0EEH ;; sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*15], ABCD ;; rounds 64-67 db 0FH,038H,0C8H,0CBH ;; sha1nexte E0, MSG0 movdqa E1, ABCD db 0FH,038H,0CAH,0E3H ;; sha1msg2 MSG1, MSG0 db 0FH,03AH,0CCH,0C1H,03H ;; sha1rnds4 ABCD, E0, 3 db 0FH,038H,0C9H,0F3H ;; sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*16], ABCD ;; rounds 68-71 db 0FH,038H,0C8H,0D4H ;; sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,038H,0CAH,0ECH ;; sha1msg2 MSG2, MSG1 db 0FH,03AH,0CCH,0C2H,03H ;; sha1rnds4 ABCD, E1, 3 pxor MSG3, MSG1 ;movdqu oword [rcx+16*17], ABCD ;; rounds 72-75 db 0FH,038H,0C8H,0CDH ;; sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,038H,0CAH,0F5H ;; sha1msg2 MSG3, MSG2 db 0FH,03AH,0CCH,0C1H,03H ;; sha1rnds4 ABCD, E0, 3 ;movdqu oword [rcx+16*18], ABCD ;; rounds 76-79 db 0FH,038H,0C8H,0D6H ;; sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,03AH,0CCH,0C2H,03H ;; sha1rnds4 ABCD, E1, 3 ;movdqu oword [rcx+16*19], ABCD ;; add current hash values with previously saved db 0FH,038H,0C8H,048H,10h ;; sha1nexte E0, oword [e_save] paddd ABCD, oword [abcd_save] add MSG_PTR, MBS_SHA1 sub MSG_LEN, MBS_SHA1 jg .sha1_block_loop ;; write hash values back in the correct order pshufd ABCD, ABCD, 01Bh movdqu oword [HASH_PTR], ABCD pextrd dword [HASH_PTR+16], E0, 3 .quit: add esp, (frame_size+16) REST_GPR ret ENDFUNC UpdateSHA1ni %endif ;; VxWorks %endif ;; _FEATURE_ON_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha1w7as.asm000066400000000000000000000334121470420105600254750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA1 ; ; Content: ; UpdateSHA1 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP >= _IPP_M5) ;; ;; Magic functions defined in FIPS 180-1 ;; %macro MAGIC_F0 4.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 mov %%regF,%%regC xor %%regF,%%regD and %%regF,%%regB xor %%regF,%%regD %endmacro %macro MAGIC_F1 4.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 mov %%regF,%%regD xor %%regF,%%regC xor %%regF,%%regB %endmacro %macro MAGIC_F2 5.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regT %5 mov %%regF,%%regB mov %%regT,%%regB or %%regF,%%regC and %%regT,%%regC and %%regF,%%regD or %%regF,%%regT %endmacro %macro MAGIC_F3 4.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 MAGIC_F1 %%regF,%%regB,%%regC,%%regD %endmacro ;; ;; single SHA1 step ;; ;; Ipp32u tmp = ROL(A,5) + MAGIC_Fi(B,C,D) + E + W[t] + CNT[i]; ;; E = D; ;; D = C; ;; C = ROL(B,30); ;; B = A; ;; A = tmp; ;; %macro SHA1_STEP 10.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%memW %8 %xdefine %%immCNT %9 %xdefine %%MAGIC %10 add %%regE,%%immCNT add %%regE,[%%memW] mov %%regT,%%regA rol %%regT,5 add %%regE,%%regT %%MAGIC %%regF,%%regB,%%regC,%%regD,%%regT ;; FUN = MAGIC_Fi(B,C,D) rol %%regB,30 add %%regE,%%regF %endmacro ;; ;; ENDIANNESS ;; %macro ENDIANNESS 2.nolist %xdefine %%dst %1 %xdefine %%src %2 %ifnidn %%dst,%%src mov %%dst,%%src %endif bswap %%dst %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Following Macros are especially for new implementation of SHA1 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro UPDATE 2-3.nolist %xdefine %%nr %1 %xdefine %%regU %2 %xdefine %%regT %3 %ifempty %%regT mov %%regU,[esp+((%%nr-16)&0Fh)*4] xor %%regU,[esp+((%%nr-14)&0Fh)*4] xor %%regU,[esp+((%%nr-8) &0Fh)*4] xor %%regU,[esp+((%%nr-3) &0Fh)*4] %else mov %%regU,[esp+((%%nr-16)&0Fh)*4] mov %%regT,[esp+((%%nr-14)&0Fh)*4] xor %%regU,%%regT mov %%regT,[esp+((%%nr-8) &0Fh)*4] xor %%regU,%%regT mov %%regT,[esp+((%%nr-3) &0Fh)*4] xor %%regU,%%regT %endif rol %%regU,1 mov [esp+(%%nr&0Fh)*4],%%regU %endmacro ;; ;; single SHA1 step ;; ;; Ipp32u tmp = ROL(A,5) + MAGIC_Fi(B,C,D) + E + W[t] + CNT[i]; ;; E = D; ;; D = C; ;; C = ROL(B,30); ;; B = A; ;; A = tmp; ;; %macro SHA1_RND0 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %assign %%immCNT 05A827999h MAGIC_F0 %%regF,%%regB,%%regC,%%regD ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[esp+(((%%nr) & 0Fh)*4)] lea %%regE,[%%regE+%%regF+%%immCNT] add %%regE,%%regT %endmacro %macro SHA1_RND1 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %assign %%immCNT 06ED9EBA1h MAGIC_F1 %%regF,%%regB,%%regC,%%regD ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[esp+(((%%nr)&0Fh)*4)] lea %%regE,[%%regE+%%regF+%%immCNT] add %%regE,%%regT %endmacro %macro SHA1_RND2 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %assign %%immCNT 08F1BBCDCh MAGIC_F2 %%regF,%%regB,%%regC,%%regD,%%regT ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[esp+(((%%nr)&0Fh)*4)] lea %%regE,[%%regE+%%regF+%%immCNT] add %%regE,%%regT %endmacro %macro SHA1_RND3 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %assign %%immCNT 0CA62C1D6h MAGIC_F3 %%regF,%%regB,%%regC,%%regD ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[esp+(((%%nr)&0Fh)*4)] lea %%regE,[%%regE+%%regF+%%immCNT] add %%regE,%%regT %endmacro segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; Lib = W7,V8 ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA1,PUBLIC USES_GPR esi,edi,ebx,ebp %xdefine digest [esp + ARG_1 + 0*sizeof(dword)] ; hash address %xdefine mblk [esp + ARG_1 + 1*sizeof(dword)] ; buffer address %xdefine mlen [esp + ARG_1 + 2*sizeof(dword)] ; buffer length %xdefine pTable [esp + ARG_1 + 3*sizeof(dword)] ; pointer to SHA1 const (dummy) %xdefine MBS_SHA1 (64) %assign stackSize (16+3) ; stack size mov eax, pTable ; dummy mov esi,mblk ; source data address mov eax,mlen ; data length mov edi,digest ; hash address sub esp,stackSize*4 ; allocate local buffer mov [esp+stackSize*4-3*4],edi ; save hash address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: mov [esp+stackSize*4-2*4],esi ; save data address mov [esp+stackSize*4-1*4],eax ; save data length ;; ;; initialize the first 16 words in the array W (remember about endian) ;; xor ecx,ecx .loop1: mov eax,[esi+ecx*4+0*4] mov edx,[esi+ecx*4+1*4] ENDIANNESS eax,eax ENDIANNESS edx,edx mov [esp+ecx*4+0*4],eax mov [esp+ecx*4+1*4],edx add ecx,2 cmp ecx,16 jl .loop1 ;; ;; init A, B, C, D, E by the internal digest ;; mov eax,[edi+0*4] ; r2 = digest[0] (A) mov ebx,[edi+1*4] ; r3 = digest[1] (B) mov ecx,[edi+2*4] ; r4 = digest[2] (C) mov edx,[edi+3*4] ; r5 = digest[3] (D) mov ebp,[edi+4*4] ; r6 = digest[4] (E) ;; ;; perform 0-79 steps ;; ;; A, B, C, D, E, TMP,FUN, round ;; ----------------------------------- SHA1_RND0 eax,ebx,ecx,edx,ebp, esi,edi, 0 UPDATE 16, esi SHA1_RND0 ebp,eax,ebx,ecx,edx, esi,edi, 1 UPDATE 17, esi SHA1_RND0 edx,ebp,eax,ebx,ecx, esi,edi, 2 UPDATE 18, esi SHA1_RND0 ecx,edx,ebp,eax,ebx, esi,edi, 3 UPDATE 19, esi SHA1_RND0 ebx,ecx,edx,ebp,eax, esi,edi, 4 UPDATE 20, esi SHA1_RND0 eax,ebx,ecx,edx,ebp, esi,edi, 5 UPDATE 21, esi SHA1_RND0 ebp,eax,ebx,ecx,edx, esi,edi, 6 UPDATE 22, esi SHA1_RND0 edx,ebp,eax,ebx,ecx, esi,edi, 7 UPDATE 23, esi SHA1_RND0 ecx,edx,ebp,eax,ebx, esi,edi, 8 UPDATE 24, esi SHA1_RND0 ebx,ecx,edx,ebp,eax, esi,edi, 9 UPDATE 25, esi SHA1_RND0 eax,ebx,ecx,edx,ebp, esi,edi, 10 UPDATE 26, esi SHA1_RND0 ebp,eax,ebx,ecx,edx, esi,edi, 11 UPDATE 27, esi SHA1_RND0 edx,ebp,eax,ebx,ecx, esi,edi, 12 UPDATE 28, esi SHA1_RND0 ecx,edx,ebp,eax,ebx, esi,edi, 13 UPDATE 29, esi SHA1_RND0 ebx,ecx,edx,ebp,eax, esi,edi, 14 UPDATE 30, esi SHA1_RND0 eax,ebx,ecx,edx,ebp, esi,edi, 15 UPDATE 31, esi SHA1_RND0 ebp,eax,ebx,ecx,edx, esi,edi, 16 UPDATE 32, esi SHA1_RND0 edx,ebp,eax,ebx,ecx, esi,edi, 17 UPDATE 33, esi SHA1_RND0 ecx,edx,ebp,eax,ebx, esi,edi, 18 UPDATE 34, esi SHA1_RND0 ebx,ecx,edx,ebp,eax, esi,edi, 19 UPDATE 35, esi SHA1_RND1 eax,ebx,ecx,edx,ebp, esi,edi, 20 UPDATE 36, esi SHA1_RND1 ebp,eax,ebx,ecx,edx, esi,edi, 21 UPDATE 37, esi SHA1_RND1 edx,ebp,eax,ebx,ecx, esi,edi, 22 UPDATE 38, esi SHA1_RND1 ecx,edx,ebp,eax,ebx, esi,edi, 23 UPDATE 39, esi SHA1_RND1 ebx,ecx,edx,ebp,eax, esi,edi, 24 UPDATE 40, esi SHA1_RND1 eax,ebx,ecx,edx,ebp, esi,edi, 25 UPDATE 41, esi SHA1_RND1 ebp,eax,ebx,ecx,edx, esi,edi, 26 UPDATE 42, esi SHA1_RND1 edx,ebp,eax,ebx,ecx, esi,edi, 27 UPDATE 43, esi SHA1_RND1 ecx,edx,ebp,eax,ebx, esi,edi, 28 UPDATE 44, esi SHA1_RND1 ebx,ecx,edx,ebp,eax, esi,edi, 29 UPDATE 45, esi SHA1_RND1 eax,ebx,ecx,edx,ebp, esi,edi, 30 UPDATE 46, esi SHA1_RND1 ebp,eax,ebx,ecx,edx, esi,edi, 31 UPDATE 47, esi SHA1_RND1 edx,ebp,eax,ebx,ecx, esi,edi, 32 UPDATE 48, esi SHA1_RND1 ecx,edx,ebp,eax,ebx, esi,edi, 33 UPDATE 49, esi SHA1_RND1 ebx,ecx,edx,ebp,eax, esi,edi, 34 UPDATE 50, esi SHA1_RND1 eax,ebx,ecx,edx,ebp, esi,edi, 35 UPDATE 51, esi SHA1_RND1 ebp,eax,ebx,ecx,edx, esi,edi, 36 UPDATE 52, esi SHA1_RND1 edx,ebp,eax,ebx,ecx, esi,edi, 37 UPDATE 53, esi SHA1_RND1 ecx,edx,ebp,eax,ebx, esi,edi, 38 UPDATE 54, esi SHA1_RND1 ebx,ecx,edx,ebp,eax, esi,edi, 39 UPDATE 55, esi SHA1_RND2 eax,ebx,ecx,edx,ebp, esi,edi, 40 UPDATE 56, esi SHA1_RND2 ebp,eax,ebx,ecx,edx, esi,edi, 41 UPDATE 57, esi SHA1_RND2 edx,ebp,eax,ebx,ecx, esi,edi, 42 UPDATE 58, esi SHA1_RND2 ecx,edx,ebp,eax,ebx, esi,edi, 43 UPDATE 59, esi SHA1_RND2 ebx,ecx,edx,ebp,eax, esi,edi, 44 UPDATE 60, esi SHA1_RND2 eax,ebx,ecx,edx,ebp, esi,edi, 45 UPDATE 61, esi SHA1_RND2 ebp,eax,ebx,ecx,edx, esi,edi, 46 UPDATE 62, esi SHA1_RND2 edx,ebp,eax,ebx,ecx, esi,edi, 47 UPDATE 63, esi SHA1_RND2 ecx,edx,ebp,eax,ebx, esi,edi, 48 UPDATE 64, esi SHA1_RND2 ebx,ecx,edx,ebp,eax, esi,edi, 49 UPDATE 65, esi SHA1_RND2 eax,ebx,ecx,edx,ebp, esi,edi, 50 UPDATE 66, esi SHA1_RND2 ebp,eax,ebx,ecx,edx, esi,edi, 51 UPDATE 67, esi SHA1_RND2 edx,ebp,eax,ebx,ecx, esi,edi, 52 UPDATE 68, esi SHA1_RND2 ecx,edx,ebp,eax,ebx, esi,edi, 53 UPDATE 69, esi SHA1_RND2 ebx,ecx,edx,ebp,eax, esi,edi, 54 UPDATE 70, esi SHA1_RND2 eax,ebx,ecx,edx,ebp, esi,edi, 55 UPDATE 71, esi SHA1_RND2 ebp,eax,ebx,ecx,edx, esi,edi, 56 UPDATE 72, esi SHA1_RND2 edx,ebp,eax,ebx,ecx, esi,edi, 57 UPDATE 73, esi SHA1_RND2 ecx,edx,ebp,eax,ebx, esi,edi, 58 UPDATE 74, esi SHA1_RND2 ebx,ecx,edx,ebp,eax, esi,edi, 59 UPDATE 75, esi SHA1_RND3 eax,ebx,ecx,edx,ebp, esi,edi, 60 UPDATE 76, esi SHA1_RND3 ebp,eax,ebx,ecx,edx, esi,edi, 61 UPDATE 77, esi SHA1_RND3 edx,ebp,eax,ebx,ecx, esi,edi, 62 UPDATE 78, esi SHA1_RND3 ecx,edx,ebp,eax,ebx, esi,edi, 63 UPDATE 79, esi SHA1_RND3 ebx,ecx,edx,ebp,eax, esi,edi, 64 SHA1_RND3 eax,ebx,ecx,edx,ebp, esi,edi, 65 SHA1_RND3 ebp,eax,ebx,ecx,edx, esi,edi, 66 SHA1_RND3 edx,ebp,eax,ebx,ecx, esi,edi, 67 SHA1_RND3 ecx,edx,ebp,eax,ebx, esi,edi, 68 SHA1_RND3 ebx,ecx,edx,ebp,eax, esi,edi, 69 SHA1_RND3 eax,ebx,ecx,edx,ebp, esi,edi, 70 SHA1_RND3 ebp,eax,ebx,ecx,edx, esi,edi, 71 SHA1_RND3 edx,ebp,eax,ebx,ecx, esi,edi, 72 SHA1_RND3 ecx,edx,ebp,eax,ebx, esi,edi, 73 SHA1_RND3 ebx,ecx,edx,ebp,eax, esi,edi, 74 SHA1_RND3 eax,ebx,ecx,edx,ebp, esi,edi, 75 SHA1_RND3 ebp,eax,ebx,ecx,edx, esi,edi, 76 SHA1_RND3 edx,ebp,eax,ebx,ecx, esi,edi, 77 SHA1_RND3 ecx,edx,ebp,eax,ebx, esi,edi, 78 SHA1_RND3 ebx,ecx,edx,ebp,eax, esi,edi, 79 ;; ;; update digest ;; mov edi,[esp+stackSize*4-3*4] ; restore hash address mov esi,[esp+stackSize*4-2*4] ; restore data address add [edi+0*4],eax ; advance digest mov eax,[esp+stackSize*4-1*4] ; restore data length add [edi+1*4],ebx add [edi+2*4],ecx add [edi+3*4],edx add [edi+4*4],ebp add esi, MBS_SHA1 sub eax, MBS_SHA1 jg .sha1_block_loop add esp,stackSize*4 ; remove local buffer REST_GPR ret ENDFUNC UpdateSHA1 %endif ;; _IPP >= _IPP_M5 %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha256g9as.asm000066400000000000000000000324211470420105600256320ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP >= _IPP_G9) %xdefine XMM_SHUFB_BSWAP xmm6 %xdefine W0 xmm0 %xdefine W4 xmm1 %xdefine W8 xmm2 %xdefine W12 xmm3 %xdefine SIG1 xmm4 %xdefine SIG0 xmm5 %xdefine X xmm6 %xdefine W xmm7 %xdefine regTbl ebx ;; we are considering x, y, z are polynomials over GF(2) ;; & - multiplication ;; ^ - additive ;; operations ;; ;; Chj(x,y,z) = (x&y) ^ (~x & z) ;; = (x&y) ^ ((1^x) &z) ;; = (x&y) ^ (z ^ x&z) ;; = x&y ^ z ^ x&z ;; = x&(y^z) ^z ;; %macro Chj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%Y xor %%F, %%Z and %%F, %%X xor %%F, %%Z %endmacro ;; ;; Maj(x,y,z) = (x&y) ^ (x&z) ^ (y&z) ;; = (x&y) ^ (x&z) ^ (y&z) ^ (z&z) ^z // note: ((z&z) ^z) = 0 ;; = x&(y^z) ^ z&(y^z) ^z ;; = (x^z)&(y^z) ^z ;; %macro Maj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%X xor %%F, %%Z xor %%Z, %%Y and %%F, %%Z xor %%Z, %%Y xor %%F, %%Z %endmacro %macro ROTR 2.nolist %xdefine %%X %1 %xdefine %%n %2 shrd %%X,%%X, %%n ;;ror X, n %endmacro ;; ;; Summ0(x) = ROR(x,2) ^ ROR(x,13) ^ ROR(x,22) ;; %macro Summ0 3.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%T %3 mov %%F, %%X ROTR %%F, 2 mov %%T, %%X ROTR %%T, 13 xor %%F, %%T ROTR %%T, (22-13) xor %%F, %%T %endmacro ;; ;; Summ1(x) = ROR(x,6) ^ ROR(x,11) ^ ROR(x,25) ;; %macro Summ1 3.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%T %3 mov %%F, %%X ROTR %%F, 6 mov %%T, %%X ROTR %%T, 11 xor %%F, %%T ROTR %%T, (25-11) xor %%F, %%T %endmacro ;; ;; regular round (i): ;; ;; T1 = h + Sigma1(e) + Ch(e,f,g) + K[i] + W[i] ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h = g ;; g = f ;; f = e ;; e = d + T1 ;; d = c ;; c = b ;; b = a ;; a = T1+T2 ;; ;; or ;; ;; h += Sigma1(e) + Ch(e,f,g) + K[i] + W[i] (==T1) ;; d += h ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h += T2 ;; and following textual shift {a,b,c,d,e,f,g,h} => {h,a,b,c,d,e,f,g} ;; %macro ROUND 6.nolist %xdefine %%nr %1 %xdefine %%hashBuff %2 %xdefine %%wBuff %3 %xdefine %%F1 %4 %xdefine %%F2 %5 %xdefine %%T1 %6 ; %xdefine T2 %7 Summ1 %%F1, eax, %%T1 Chj %%F2, eax,{[%%hashBuff+((vF-%%nr)&7)*sizeof(dword)]},{[%%hashBuff+((vG-%%nr)&7)*sizeof(dword)]} mov eax, [%%hashBuff+((vH-%%nr)&7)*sizeof(dword)] add eax, %%F1 add eax, %%F2 add eax, dword [%%wBuff+(%%nr&3)*sizeof(dword)] mov %%F1, dword [%%hashBuff+((vB-%%nr)&7)*sizeof(dword)] mov %%T1, dword [%%hashBuff+((vC-%%nr)&7)*sizeof(dword)] Maj %%F2, edx,%%F1, %%T1 Summ0 %%F1, edx, %%T1 lea edx, [%%F1+%%F2] add edx,eax ; T2+T1 add eax,[%%hashBuff+((vD-%%nr)&7)*sizeof(dword)] ; T1+d mov [%%hashBuff+((vH-%%nr)&7)*sizeof(dword)],edx mov [%%hashBuff+((vD-%%nr)&7)*sizeof(dword)],eax %endmacro ;; ;; W[i] = Sigma1(W[i-2]) + W[i-7] + Sigma0(W[i-15]) + W[i-16], i=16,..,63 ;; ;;for next rounds 16,17,18 and 19: ;; W[0] <= W[16] = Sigma1(W[14]) + W[ 9] + Sigma0(W[1]) + W[0] ;; W[1] <= W[17] = Sigma1(W[15]) + W[10] + Sigma0(W[2]) + W[1] ;; W[2] <= W[18] = Sigma1(W[ 0]) + W[11] + Sigma0(W[3]) + W[1] ;; W[3] <= W[19] = Sigma1(W[ 1]) + W[12] + Sigma0(W[4]) + W[2] ;; ;; the process is repeated exactly because textual round of W[] ;; ;; Sigma1() and Sigma0() functions are defined as following: ;; Sigma1(X) = ROR(X,17)^ROR(X,19)^SHR(X,10) ;; Sigma0(X) = ROR(X, 7)^ROR(X,18)^SHR(X, 3) ;; %macro UPDATE_W 8.nolist %xdefine %%xS %1 %xdefine %%xS0 %2 %xdefine %%xS4 %3 %xdefine %%xS8 %4 %xdefine %%xS12 %5 %xdefine %%SIGMA1 %6 %xdefine %%SIGMA0 %7 %xdefine %%X %8 vpshufd %%X, %%xS12, 11111010b ;; SIGMA1 = {W[15],W[15],W[14],W[14]} vpsrld %%SIGMA1, %%X, 10 vpsrlq %%X, %%X, 17 vpxor %%SIGMA1, %%SIGMA1, %%X vpsrlq %%X, %%X, (19-17) vpxor %%SIGMA1, %%SIGMA1, %%X vpshufd %%X, %%xS0, 10100101b ;; SIGMA0 = {W[2],W[2],W[1],W[1]} vpsrld %%SIGMA0, %%X, 3 vpsrlq %%X, %%X, 7 vpxor %%SIGMA0, %%SIGMA0, %%X vpsrlq %%X, %%X, (18-7) vpxor %%SIGMA0, %%SIGMA0, %%X vpshufd %%xS, %%xS0, 01010000b ;; {W[ 1],W[ 1],W[ 0],W[ 0]} vpaddd %%SIGMA1, %%SIGMA1, %%SIGMA0 vpshufd %%X, %%xS8, 10100101b ;; {W[10],W[10],W[ 9],W[ 9]} vpaddd %%xS, %%xS, %%SIGMA1 vpaddd %%xS, %%xS, %%X vpshufd %%X, %%xS, 10100000b ;; SIGMA1 = {W[1],W[1],W[0],W[0]} vpsrld %%SIGMA1, %%X, 10 vpsrlq %%X, %%X, 17 vpxor %%SIGMA1, %%SIGMA1, %%X vpsrlq %%X, %%X, (19-17) vpxor %%SIGMA1, %%SIGMA1, %%X vpalignr %%X, %%xS4, %%xS0, (3*sizeof(dword)) ;; SIGMA0 = {W[4],W[4],W[3],W[3]} vpshufd %%X, %%X, 01010000b vpsrld %%SIGMA0, %%X, 3 vpsrlq %%X, %%X, 7 vpxor %%SIGMA0, %%SIGMA0, %%X vpsrlq %%X, %%X, (18-7) vpxor %%SIGMA0, %%SIGMA0, %%X vpalignr %%X, %%xS12, %%xS8, (3*sizeof(dword)) ;; {W[14],W[13],W[12],W[11]} vpshufd %%xS0, %%xS0, 11111010b ;; {W[ 3],W[ 3],W[ 2],W[ 2]} vpaddd %%SIGMA1, %%SIGMA1, %%SIGMA0 vpshufd %%X, %%X, 01010000b ;; {W[12],W[12],W[11],W[11]} vpaddd %%xS0, %%xS0, %%SIGMA1 vpaddd %%xS0, %%xS0, %%X vpshufd %%xS, %%xS, 10001000b ;; {W[1],W[0],W[1],W[0]} vpshufd %%xS0, %%xS0, 10001000b ;; {W[3],W[2],W[3],W[2]} vpalignr %%xS0, %%xS0, %%xS, (2*sizeof(dword)) ;; {W[3],W[2],W[1],W[0]} %endmacro segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SWP_BYTE: pByteSwp DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; UpdateSHA256(Ipp32u digest[], Ipp8u dataBlock[], int datalen, Ipp32u K_256[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pHash [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to hash %xdefine pData [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to data block %xdefine dataLen [ebp + ARG_1 + 2*sizeof(dword)] ; data length %xdefine pTbl [ebp + ARG_1 + 3*sizeof(dword)] ; pointer to the SHA256 const table %xdefine MBS_SHA256 (64) %assign hSize sizeof(dword)*8 ; size of hash %assign wSize sizeof(oword) ; W values queue (dwords) %assign cntSize sizeof(dword) ; local counter %assign hashOff 0 ; hash address %assign wOff hashOff+hSize ; W values offset %assign cntOff wOff+wSize %assign stackSize (hSize+wSize+cntSize) ; stack size sub esp, stackSize ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: mov eax, pHash ; pointer to the hash vmovdqu W0, oword [eax] ; load initial hash value vmovdqu W4, oword [eax+sizeof(oword)] vmovdqu oword [esp+hashOff], W0 vmovdqu oword [esp+hashOff+sizeof(oword)*1], W4 mov eax, pData ; pointer to the data block mov regTbl, pTbl ; pointer to SHA256 table (points K_256[] constants) ;vmovdqa XMM_SHUFB_BSWAP, oword pByteSwp ; load shuffle mask LD_ADDR ecx, SWP_BYTE movdqa XMM_SHUFB_BSWAP, oword [ecx+(pByteSwp-SWP_BYTE)] vmovdqu W0, oword [eax] ; load buffer content vmovdqu W4, oword [eax+sizeof(oword)] vmovdqu W8, oword [eax+sizeof(oword)*2] vmovdqu W12,oword [eax+sizeof(oword)*3] %assign vA 0 %assign vB 1 %assign vC 2 %assign vD 3 %assign vE 4 %assign vF 5 %assign vG 6 %assign vH 7 mov eax, [esp+hashOff+vE*sizeof(dword)] mov edx, [esp+hashOff+vA*sizeof(dword)] ;; perform 0-3 regular rounds vpshufb W0, W0, XMM_SHUFB_BSWAP ; swap input vpaddd W, W0, oword [regTbl+sizeof(oword)*0] ; T += K_SHA256[0-3] vmovdqu oword [esp+wOff], W ROUND 0, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 1, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 2, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 3, {esp+hashOff},{esp+wOff}, esi,edi,ecx ;; perform next 4-7 regular rounds vpshufb W4, W4, XMM_SHUFB_BSWAP ; swap input vpaddd W, W4, oword [regTbl+sizeof(oword)*1] ; T += K_SHA256[4-7] vmovdqu oword [esp+wOff], W ROUND 4, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 5, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 6, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 7, {esp+hashOff},{esp+wOff}, esi,edi,ecx ;; perform next 8-11 regular rounds vpshufb W8, W8, XMM_SHUFB_BSWAP ; swap input vpaddd W, W8, oword [regTbl+sizeof(oword)*2] ; T += K_SHA256[8-11] vmovdqu oword [esp+wOff], W ROUND 8, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 9, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 10, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 11, {esp+hashOff},{esp+wOff}, esi,edi,ecx ;; perform next 12-15 regular rounds vpshufb W12, W12, XMM_SHUFB_BSWAP ; swap input vpaddd W, W12, oword [regTbl+sizeof(oword)*3] ; T += K_SHA256[12-15] vmovdqu oword [esp+wOff], W ROUND 12, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 13, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 14, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 15, {esp+hashOff},{esp+wOff}, esi,edi,ecx mov dword [esp+cntOff], (64-16) ; init counter .loop_16_63: add regTbl, sizeof(oword)*4 ; update SHA_256 pointer UPDATE_W W, W0, W4, W8, W12, SIG1,SIG0,X ; round: 16*i - 16*i+3 vpaddd W, W0, oword [regTbl+sizeof(oword)*0] ; T += K_SHA256[16-19] vmovdqu oword [esp+wOff], W ROUND 16, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 17, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 18, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 19, {esp+hashOff},{esp+wOff}, esi,edi,ecx UPDATE_W W, W4, W8, W12,W0, SIG1,SIG0,X ; round: 20*i 20*i+3 vpaddd W, W4, oword [regTbl+sizeof(oword)*1] ; T += K_SHA256[20-23] vmovdqu oword [esp+wOff], W ROUND 20, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 21, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 22, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 23, {esp+hashOff},{esp+wOff}, esi,edi,ecx UPDATE_W W, W8, W12,W0, W4, SIG1,SIG0,X ; round: 24*i - 24*i+3 vpaddd W, W8, oword [regTbl+sizeof(oword)*2] ; T += K_SHA256[24-27] vmovdqu oword [esp+wOff], W ROUND 24, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 25, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 26, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 27, {esp+hashOff},{esp+wOff}, esi,edi,ecx UPDATE_W W, W12,W0, W4, W8, SIG1,SIG0,X ; round: 28*i - 28*i+3 vpaddd W, W12, oword [regTbl+sizeof(oword)*3]; T += K_SHA256[28-31] vmovdqu oword [esp+wOff], W ROUND 28, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 29, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 30, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 31, {esp+hashOff},{esp+wOff}, esi,edi,ecx sub dword [esp+cntOff], 16 jg .loop_16_63 mov eax, pHash ; pointer to the hash vmovdqu W0, oword [esp+hashOff] vmovdqu W4, oword [esp+hashOff+sizeof(oword)*1] ; update hash vmovdqu W, oword [eax] vpaddd W, W, W0 vmovdqu oword [eax], W vmovdqu W, oword [eax+sizeof(oword)] vpaddd W, W, W4 vmovdqu oword [eax+sizeof(oword)], W add dword pData, MBS_SHA256 sub dword dataLen, MBS_SHA256 jg .sha256_block_loop add esp, stackSize REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; _IPP32E_G9 and above %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha256nias.asm000066400000000000000000000465021470420105600257260ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA-256 ; ; Content: ; UpdateSHA256ni ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_ON_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR CODE_DATA: PSHUFFLE_BYTE_FLIP_MASK \ DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 align IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA256ni(DigestSHA256 digest, const Ipp8u* msg, int mlen, const Ipp32u K_256[]) ;* ;***************************************************************************************** %ifndef _VXWORKS IPPASM UpdateSHA256ni,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pDigest [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to the in/out digest %xdefine pMsg [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to the inp message %xdefine msgLen [ebp + ARG_1 + 2*sizeof(dword)] ; message length %xdefine pTbl [ebp + ARG_1 + 3*sizeof(dword)] ; pointer to SHA256 table of constants %xdefine MBS_SHA256 (64) ; SHA-1 message block length (bytes) %xdefine HASH_PTR edi ; 1st arg %xdefine MSG_PTR esi ; 2nd arg %xdefine MSG_LEN edx ; 3rd arg %xdefine K256_PTR ebx ; 4th arg %xdefine MSG xmm0 %xdefine STATE0 xmm1 %xdefine STATE1 xmm2 %xdefine MSGTMP0 xmm3 %xdefine MSGTMP1 xmm4 %xdefine MSGTMP2 xmm5 %xdefine MSGTMP3 xmm6 %xdefine MSGTMP4 xmm7 ; ; stack frame ; %xdefine mask_save eax %xdefine abef_save eax+sizeof(oword) %xdefine cdgh_save eax+sizeof(oword)*2 %xdefine frame_size sizeof(oword)+sizeof(oword)+sizeof(oword) sub esp, (frame_size+16) lea eax, [esp+16] and eax, -16 mov MSG_LEN, msgLen ; message length test MSG_LEN, MSG_LEN jz .quit mov HASH_PTR, pDigest mov MSG_PTR, pMsg mov K256_PTR, pTbl ;; load input hash value, reorder these appropriately movdqu STATE0, oword [HASH_PTR+0*sizeof(oword)] movdqu STATE1, oword [HASH_PTR+1*sizeof(oword)] pshufd STATE0, STATE0, 0B1h ; CDAB pshufd STATE1, STATE1, 01Bh ; EFGH movdqa MSGTMP4, STATE0 palignr STATE0, STATE1, 8 ; ABEF pblendw STATE1, MSGTMP4, 0F0h ; CDGH ;; copy byte_flip_mask to stack mov ecx, 000010203h ;; DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 mov dword [mask_save], ecx mov ecx, 004050607h mov dword [mask_save+1*sizeof(dword)], ecx mov ecx, 008090a0bh mov dword [mask_save+2*sizeof(dword)], ecx mov ecx, 00c0d0e0fh mov dword [mask_save+3*sizeof(dword)], ecx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: movdqa oword [abef_save], STATE0 ; save for addition after rounds movdqa oword [cdgh_save], STATE1 ;; rounds 0-3 movdqu MSG, oword [MSG_PTR + 0*sizeof(oword)] pshufb MSG, [mask_save] movdqa MSGTMP0, MSG paddd MSG, oword [K256_PTR + 0*sizeof(oword)] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 ;; rounds 4-7 movdqu MSG, oword [MSG_PTR + 1*sizeof(oword)] pshufb MSG, [mask_save] movdqa MSGTMP1, MSG paddd MSG, oword [K256_PTR + 1*sizeof(oword)] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 8-11 movdqu MSG, oword [MSG_PTR + 2*sizeof(oword)] pshufb MSG, [mask_save] movdqa MSGTMP2, MSG paddd MSG, oword [K256_PTR + 2*sizeof(oword)] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 12-15 movdqu MSG, oword [MSG_PTR + 3*sizeof(oword)] pshufb MSG, [mask_save] movdqa MSGTMP3, MSG paddd MSG, oword [K256_PTR + 3*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 16-19 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 4*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 20-23 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 5*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 24-27 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 6*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 28-31 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 7*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 32-35 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 8*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 36-39 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 9*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 40-43 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 10*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 44-47 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 11*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 48-51 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 12*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 52-55 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 13*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 ;; rounds 56-59 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 14*sizeof(oword)] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 ;; rounds 60-63 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 15*sizeof(oword)] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 paddd STATE0, oword [abef_save] ; update previously saved hash paddd STATE1, oword [cdgh_save] add MSG_PTR, MBS_SHA256 sub MSG_LEN, MBS_SHA256 jg .sha256_block_loop ; reorder hash pshufd STATE0, STATE0, 01Bh ; FEBA pshufd STATE1, STATE1, 0B1h ; DCHG movdqa MSGTMP4, STATE0 pblendw STATE0, STATE1, 0F0h ; DCBA palignr STATE1, MSGTMP4, 8 ; HGFE ; and store it back movdqu oword [HASH_PTR + 0*sizeof(oword)], STATE0 movdqu oword [HASH_PTR + 1*sizeof(oword)], STATE1 .quit: add esp, (frame_size+16) REST_GPR ret ENDFUNC UpdateSHA256ni %else ;; no sha ni support in VxWorks - therefore we temporary use db IPPASM UpdateSHA256ni,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pDigest [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to the in/out digest %xdefine pMsg [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to the inp message %xdefine msgLen [ebp + ARG_1 + 2*sizeof(dword)] ; message length %xdefine pTbl [ebp + ARG_1 + 3*sizeof(dword)] ; pointer to SHA256 table of constants %xdefine MBS_SHA256 (64) ; SHA-1 message block length (bytes) %xdefine HASH_PTR edi ; 1st arg %xdefine MSG_PTR esi ; 2nd arg %xdefine MSG_LEN edx ; 3rd arg %xdefine K256_PTR ebx ; 4th arg %xdefine MSG xmm0 %xdefine STATE0 xmm1 %xdefine STATE1 xmm2 %xdefine MSGTMP0 xmm3 %xdefine MSGTMP1 xmm4 %xdefine MSGTMP2 xmm5 %xdefine MSGTMP3 xmm6 %xdefine MSGTMP4 xmm7 ; ; stack frame ; %xdefine mask_save eax %xdefine abef_save eax+sizeof(oword) %xdefine cdgh_save eax+sizeof(oword)*2 %xdefine frame_size sizeof(oword)+sizeof(oword)+sizeof(oword) sub esp, (frame_size+16) lea eax, [esp+16] and eax, -16 mov MSG_LEN, msgLen ; message length test MSG_LEN, MSG_LEN jz .quit mov HASH_PTR, pDigest mov MSG_PTR, pMsg mov K256_PTR, pTbl ;; load input hash value, reorder these appropriately movdqu STATE0, oword [HASH_PTR+0*sizeof(oword)] movdqu STATE1, oword [HASH_PTR+1*sizeof(oword)] pshufd STATE0, STATE0, 0B1h ; CDAB pshufd STATE1, STATE1, 01Bh ; EFGH movdqa MSGTMP4, STATE0 palignr STATE0, STATE1, 8 ; ABEF pblendw STATE1, MSGTMP4, 0F0h ; CDGH ;; copy byte_flip_mask to stack ;movdqa MSGTMP4, oword [PSHUFFLE_BYTE_FLIP_MASK] LD_ADDR ecx, CODE_DATA movdqa MSGTMP4, oword [ecx+(PSHUFFLE_BYTE_FLIP_MASK-CODE_DATA)] movdqa oword [mask_save], MSGTMP4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: movdqa oword [abef_save], STATE0 ; save for addition after rounds movdqa oword [cdgh_save], STATE1 ;; rounds 0-3 movdqu MSG, oword [MSG_PTR + 0*sizeof(oword)] pshufb MSG, oword [mask_save] movdqa MSGTMP0, MSG paddd MSG, oword [K256_PTR + 0*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 ;; rounds 4-7 movdqu MSG, oword [MSG_PTR + 1*sizeof(oword)] pshufb MSG, oword [mask_save] movdqa MSGTMP1, MSG paddd MSG, oword [K256_PTR + 1*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0DCH ;; sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 8-11 movdqu MSG, oword [MSG_PTR + 2*sizeof(oword)] pshufb MSG, oword [mask_save] movdqa MSGTMP2, MSG paddd MSG, oword [K256_PTR + 2*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0E5H ;; sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 12-15 movdqu MSG, oword [MSG_PTR + 3*sizeof(oword)] pshufb MSG, oword [mask_save] movdqa MSGTMP3, MSG paddd MSG, oword [K256_PTR + 3*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 db 0FH,038H,0CDH,0DEH ;; sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0EEH ;; sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 16-19 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 4*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 db 0FH,038H,0CDH,0E3H ;; sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0F3H ;; sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 20-23 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 5*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 db 0FH,038H,0CDH,0ECH ;; sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0DCH ;; sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 24-27 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 6*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 db 0FH,038H,0CDH,0F5H ;; sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0E5H ;; sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 28-31 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 7*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 db 0FH,038H,0CDH,0DEH ;; sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0EEH ;; sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 32-35 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 8*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 db 0FH,038H,0CDH,0E3H ;; sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0F3H ;; sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 36-39 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 9*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 db 0FH,038H,0CDH,0ECH ;; sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0DCH ;; sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 40-43 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 10*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 db 0FH,038H,0CDH,0F5H ;; sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0E5H ;; sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 44-47 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 11*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 db 0FH,038H,0CDH,0DEH ;; sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0EEH ;; sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 48-51 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 12*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 db 0FH,038H,0CDH,0E3H ;; sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,038H,0CCH,0F3H ;; sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 52-55 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 13*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 db 0FH,038H,0CDH,0ECH ;; sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 ;; rounds 56-59 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 14*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 db 0FH,038H,0CDH,0F5H ;; sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 ;; rounds 60-63 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 15*sizeof(oword)] db 0FH,038H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,038H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 paddd STATE0, oword [abef_save] ; update previously saved hash paddd STATE1, oword [cdgh_save] add MSG_PTR, MBS_SHA256 sub MSG_LEN, MBS_SHA256 jg .sha256_block_loop ; reorder hash pshufd STATE0, STATE0, 01Bh ; FEBA pshufd STATE1, STATE1, 0B1h ; DCHG movdqa MSGTMP4, STATE0 pblendw STATE0, STATE1, 0F0h ; DCBA palignr STATE1, MSGTMP4, 8 ; HGFE ; and store it back movdqu oword [HASH_PTR + 0*sizeof(oword)], STATE0 movdqu oword [HASH_PTR + 1*sizeof(oword)], STATE1 .quit: add esp, (frame_size+16) REST_GPR ret ENDFUNC UpdateSHA256ni %endif ;; VxWorks %endif ;; _FEATURE_ON_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha256v8as.asm000066400000000000000000000325471470420105600256610ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP >= _IPP_V8) && (_IPP < _IPP_G9) %xdefine XMM_SHUFB_BSWAP xmm6 %xdefine W0 xmm0 %xdefine W4 xmm1 %xdefine W8 xmm2 %xdefine W12 xmm3 %xdefine SIG1 xmm4 %xdefine SIG0 xmm5 %xdefine X xmm6 %xdefine W xmm7 %xdefine regTbl ebx ;; we are considering x, y, z are polynomials over GF(2) ;; & - multiplication ;; ^ - additive ;; operations ;; ;; Chj(x,y,z) = (x&y) ^ (~x & z) ;; = (x&y) ^ ((1^x) &z) ;; = (x&y) ^ (z ^ x&z) ;; = x&y ^ z ^ x&z ;; = x&(y^z) ^z ;; %macro Chj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%Y xor %%F, %%Z and %%F, %%X xor %%F, %%Z %endmacro ;; ;; Maj(x,y,z) = (x&y) ^ (x&z) ^ (y&z) ;; = (x&y) ^ (x&z) ^ (y&z) ^ (z&z) ^z // note: ((z&z) ^z) = 0 ;; = x&(y^z) ^ z&(y^z) ^z ;; = (x^z)&(y^z) ^z ;; %macro Maj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%X xor %%F, %%Z xor %%Z, %%Y and %%F, %%Z xor %%Z, %%Y xor %%F, %%Z %endmacro %macro ROTR 2.nolist %xdefine %%X %1 %xdefine %%n %2 ;;shrd X,X, n ror %%X, %%n %endmacro ;; ;; Summ0(x) = ROR(x,2) ^ ROR(x,13) ^ ROR(x,22) ;; %macro Summ0 3.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%T %3 mov %%F, %%X ROTR %%F, 2 mov %%T, %%X ROTR %%T, 13 xor %%F, %%T ROTR %%T, (22-13) xor %%F, %%T %endmacro ;; ;; Summ1(x) = ROR(x,6) ^ ROR(x,11) ^ ROR(x,25) ;; %macro Summ1 3.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%T %3 mov %%F, %%X ROTR %%F, 6 mov %%T, %%X ROTR %%T, 11 xor %%F, %%T ROTR %%T, (25-11) xor %%F, %%T %endmacro ;; ;; regular round (i): ;; ;; T1 = h + Sigma1(e) + Ch(e,f,g) + K[i] + W[i] ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h = g ;; g = f ;; f = e ;; e = d + T1 ;; d = c ;; c = b ;; b = a ;; a = T1+T2 ;; ;; or ;; ;; h += Sigma1(e) + Ch(e,f,g) + K[i] + W[i] (==T1) ;; d += h ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h += T2 ;; and following textual shift {a,b,c,d,e,f,g,h} => {h,a,b,c,d,e,f,g} ;; %macro ROUND 6.nolist %xdefine %%nr %1 %xdefine %%hashBuff %2 %xdefine %%wBuff %3 %xdefine %%F1 %4 %xdefine %%F2 %5 %xdefine %%T1 %6 ; %xdefine T2 %7 Summ1 %%F1, eax, %%T1 Chj %%F2, eax,{[%%hashBuff+((vF-%%nr)&7)*sizeof(dword)]},{[%%hashBuff+((vG-%%nr)&7)*sizeof(dword)]} mov eax, [%%hashBuff+((vH-%%nr)&7)*sizeof(dword)] add eax, %%F1 add eax, %%F2 add eax, dword [%%wBuff+(%%nr&3)*sizeof(dword)] mov %%F1, dword [%%hashBuff+((vB-%%nr)&7)*sizeof(dword)] mov %%T1, dword [%%hashBuff+((vC-%%nr)&7)*sizeof(dword)] Maj %%F2, edx,%%F1, %%T1 Summ0 %%F1, edx, %%T1 lea edx, [%%F1+%%F2] add edx,eax ; T2+T1 add eax,[%%hashBuff+((vD-%%nr)&7)*sizeof(dword)] ; T1+d mov [%%hashBuff+((vH-%%nr)&7)*sizeof(dword)],edx mov [%%hashBuff+((vD-%%nr)&7)*sizeof(dword)],eax %endmacro ;; ;; W[i] = Sigma1(W[i-2]) + W[i-7] + Sigma0(W[i-15]) + W[i-16], i=16,..,63 ;; ;;for next rounds 16,17,18 and 19: ;; W[0] <= W[16] = Sigma1(W[14]) + W[ 9] + Sigma0(W[1]) + W[0] ;; W[1] <= W[17] = Sigma1(W[15]) + W[10] + Sigma0(W[2]) + W[1] ;; W[2] <= W[18] = Sigma1(W[ 0]) + W[11] + Sigma0(W[3]) + W[1] ;; W[3] <= W[19] = Sigma1(W[ 1]) + W[12] + Sigma0(W[4]) + W[2] ;; ;; the process is repeated exactly because textual round of W[] ;; ;; Sigma1() and Sigma0() functions are defined as following: ;; Sigma1(X) = ROR(X,17)^ROR(X,19)^SHR(X,10) ;; Sigma0(X) = ROR(X, 7)^ROR(X,18)^SHR(X, 3) ;; %macro UPDATE_W 8.nolist %xdefine %%xS %1 %xdefine %%xS0 %2 %xdefine %%xS4 %3 %xdefine %%xS8 %4 %xdefine %%xS12 %5 %xdefine %%SIGMA1 %6 %xdefine %%SIGMA0 %7 %xdefine %%X %8 pshufd %%SIGMA1, %%xS12, 11111010b ;; SIGMA1 = {W[15],W[15],W[14],W[14]} movdqa %%X, %%SIGMA1 psrld %%SIGMA1, 10 psrlq %%X, 17 pxor %%SIGMA1, %%X psrlq %%X, (19-17) pxor %%SIGMA1, %%X pshufd %%SIGMA0, %%xS0, 10100101b ;; SIGMA0 = {W[2],W[2],W[1],W[1]} movdqa %%X, %%SIGMA0 psrld %%SIGMA0, 3 psrlq %%X, 7 pxor %%SIGMA0, %%X psrlq %%X, (18-7) pxor %%SIGMA0, %%X pshufd %%xS, %%xS0, 01010000b ;; {W[ 1],W[ 1],W[ 0],W[ 0]} pshufd %%X, %%xS8, 10100101b ;; {W[10],W[10],W[ 9],W[ 9]} paddd %%xS, %%SIGMA1 paddd %%xS, %%SIGMA0 paddd %%xS, %%X pshufd %%SIGMA1, %%xS, 10100000b ;; SIGMA1 = {W[1],W[1],W[0],W[0]} movdqa %%X, %%SIGMA1 psrld %%SIGMA1, 10 psrlq %%X, 17 pxor %%SIGMA1, %%X psrlq %%X, (19-17) pxor %%SIGMA1, %%X movdqa %%SIGMA0, %%xS4 ;; SIGMA0 = {W[4],W[4],W[3],W[3]} palignr %%SIGMA0, %%xS0, (3*sizeof(dword)) pshufd %%SIGMA0, %%SIGMA0, 01010000b movdqa %%X, %%SIGMA0 psrld %%SIGMA0, 3 psrlq %%X, 7 pxor %%SIGMA0, %%X psrlq %%X, (18-7) pxor %%SIGMA0, %%X movdqa %%X, %%xS12 palignr %%X, %%xS8, (3*sizeof(dword)) ;; {W[14],W[13],W[12],W[11]} pshufd %%xS0, %%xS0, 11111010b ;; {W[ 3],W[ 3],W[ 2],W[ 2]} pshufd %%X, %%X, 01010000b ;; {W[12],W[12],W[11],W[11]} paddd %%xS0, %%SIGMA1 paddd %%xS0, %%SIGMA0 paddd %%xS0, %%X pshufd %%xS, %%xS, 10001000b ;; {W[1],W[0],W[1],W[0]} pshufd %%xS0, %%xS0, 10001000b ;; {W[3],W[2],W[3],W[2]} palignr %%xS0, %%xS, (2*sizeof(dword)) ;; {W[3],W[2],W[1],W[0]} movdqa %%xS, %%xS0 %endmacro segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SWP_BYTE: pByteSwp DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; SHA256(Ipp32u digest[], Ipp8u dataBlock[], int dataLen, Ipp32u K_256[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pHash [ebp + ARG_1 + 0*sizeof(dword)] ; pointer to hash %xdefine pData [ebp + ARG_1 + 1*sizeof(dword)] ; pointer to data block %xdefine dataLen [ebp + ARG_1 + 2*sizeof(dword)] ; data length %xdefine pTbl [ebp + ARG_1 + 3*sizeof(dword)] ; pointer to the SHA256 const table %xdefine MBS_SHA256 (64) %assign hSize sizeof(dword)*8 ; size of hash %assign wSize sizeof(oword) ; W values queue (dwords) %assign cntSize sizeof(dword) ; local counter %assign hashOff 0 ; hash address %assign wOff hashOff+hSize ; W values offset %assign cntOff wOff+wSize %assign stackSize (hSize+wSize+cntSize) ; stack size sub esp, stackSize ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: mov eax, pHash ; pointer to the hash movdqu W0, oword [eax] ; load initial hash value movdqu W4, oword [eax+sizeof(oword)] movdqu oword [esp+hashOff], W0 movdqu oword [esp+hashOff+sizeof(oword)*1], W4 ;movdqa XMM_SHUFB_BSWAP, oword pByteSwp ; load shuffle mask LD_ADDR eax, SWP_BYTE movdqa XMM_SHUFB_BSWAP, oword [eax+(pByteSwp-SWP_BYTE)] mov eax, pData ; pointer to the data block mov regTbl, pTbl ; pointer to SHA256 table (points K_256[] constants) movdqu W0, oword [eax] ; load buffer content movdqu W4, oword [eax+sizeof(oword)] movdqu W8, oword [eax+sizeof(oword)*2] movdqu W12,oword [eax+sizeof(oword)*3] %assign vA 0 %assign vB 1 %assign vC 2 %assign vD 3 %assign vE 4 %assign vF 5 %assign vG 6 %assign vH 7 mov eax, [esp+hashOff+vE*sizeof(dword)] mov edx, [esp+hashOff+vA*sizeof(dword)] ;; perform 0-3 regular rounds pshufb W0, XMM_SHUFB_BSWAP ; swap input movdqa W, W0 ; T = W[0-3] paddd W, oword [regTbl+sizeof(oword)*0] ; T += K_SHA256[0-3] movdqu oword [esp+wOff], W ROUND 0, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 1, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 2, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 3, {esp+hashOff},{esp+wOff}, esi,edi,ecx ;; perform next 4-7 regular rounds pshufb W4, XMM_SHUFB_BSWAP ; swap input movdqa W, W4 ; T = W[4-7] paddd W, oword [regTbl+sizeof(oword)*1] ; T += K_SHA256[4-7] movdqu oword [esp+wOff], W ROUND 4, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 5, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 6, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 7, {esp+hashOff},{esp+wOff}, esi,edi,ecx ;; perform next 8-11 regular rounds pshufb W8, XMM_SHUFB_BSWAP ; swap input movdqa W, W8 ; T = W[8-11] paddd W, oword [regTbl+sizeof(oword)*2] ; T += K_SHA256[8-11] movdqu oword [esp+wOff], W ROUND 8, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 9, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 10, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 11, {esp+hashOff},{esp+wOff}, esi,edi,ecx ;; perform next 12-15 regular rounds pshufb W12, XMM_SHUFB_BSWAP ; swap input movdqa W, W12 ; T = W[12-15] paddd W, oword [regTbl+sizeof(oword)*3] ; T += K_SHA256[12-15] movdqu oword [esp+wOff], W ROUND 12, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 13, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 14, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 15, {esp+hashOff},{esp+wOff}, esi,edi,ecx mov dword [esp+cntOff], (64-16) ; init counter .loop_16_63: add regTbl, sizeof(oword)*4 ; update SHA_256 pointer UPDATE_W W, W0, W4, W8, W12, SIG1,SIG0,X ; round: 16*i - 16*i+3 paddd W, oword [regTbl+sizeof(oword)*0] ; T += K_SHA256[16-19] movdqu oword [esp+wOff], W ROUND 16, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 17, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 18, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 19, {esp+hashOff},{esp+wOff}, esi,edi,ecx UPDATE_W W, W4, W8, W12,W0, SIG1,SIG0,X ; round: 20*i 20*i+3 paddd W, oword [regTbl+sizeof(oword)*1] ; T += K_SHA256[20-23] movdqu oword [esp+wOff], W ROUND 20, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 21, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 22, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 23, {esp+hashOff},{esp+wOff}, esi,edi,ecx UPDATE_W W, W8, W12,W0, W4, SIG1,SIG0,X ; round: 24*i - 24*i+3 paddd W, oword [regTbl+sizeof(oword)*2] ; T += K_SHA256[24-27] movdqu oword [esp+wOff], W ROUND 24, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 25, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 26, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 27, {esp+hashOff},{esp+wOff}, esi,edi,ecx UPDATE_W W, W12,W0, W4, W8, SIG1,SIG0,X ; round: 28*i - 28*i+3 paddd W, oword [regTbl+sizeof(oword)*3] ; T += K_SHA256[28-31] movdqu oword [esp+wOff], W ROUND 28, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 29, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 30, {esp+hashOff},{esp+wOff}, esi,edi,ecx ROUND 31, {esp+hashOff},{esp+wOff}, esi,edi,ecx sub dword [esp+cntOff], 16 jg .loop_16_63 mov eax, pHash ; pointer to the hash movdqu W0, oword [esp+hashOff] movdqu W4, oword [esp+hashOff+sizeof(oword)*1] ; update hash movdqu W, oword [eax] paddd W, W0 movdqu oword [eax], W movdqu W, oword [eax+sizeof(oword)] paddd W, W4 movdqu oword [eax+sizeof(oword)], W add dword pData, MBS_SHA256 sub dword dataLen, MBS_SHA256 jg .sha256_block_loop add esp, stackSize REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; (_IPP >= _IPP_V8) && (_IPP < _IPP_G9) %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha256w7as.asm000066400000000000000000000360011470420105600256460ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP >= _IPP_M5) && (_IPP < _IPP_V8) ;; ;; SIG0(x) = ROR32(x, 7) ^ ROR32(x,18) ^ LSR(x, 3) ;; SIG1(x) = ROR32(x,17) ^ ROR32(x,19) ^ LSR(x,10) ;; W[i] = SIG1(W[i-2]) + W[i-7] + SIG0(W[i-15]) + W[i-16], i=16,..,63 ;; %macro UPDATE 2.nolist %xdefine %%nr %1 %xdefine %%wBuff %2 mov ebx,[%%wBuff+((%%nr-2) &0Fh)*sizeof(dword)] ; W[i- 2] ror ebx, 10 mov ecx,[%%wBuff+((%%nr-15)&0Fh)*sizeof(dword)] ; W[i-15] ror ecx, 3 mov esi,[%%wBuff+((%%nr-7) &0Fh)*sizeof(dword)] ; +W[i- 7] add esi,[%%wBuff+((%%nr-16)&0Fh)*sizeof(dword)] ; +W[i-16] mov edi,003FFFFFh ; SIG1() and edi,ebx ror ebx,(17-10) xor edi,ebx ror ebx,(19-17) xor edi,ebx add edi, esi ; SIG0() +W[i-7] +W[i-16] mov esi,1FFFFFFFh ; SIG0() and esi,ecx ror ecx,(7-3) xor esi,ecx ror ecx,(18-7) xor esi,ecx add edi,esi ; SIG0() +W[i-7] +W[i-16] + SIG1() mov [%%wBuff+(%%nr&0Fh)*sizeof(dword)],edi %endmacro ; ; SUM1(x) = ROR32(x, 6) ^ ROR32(x,11) ^ ROR32(x,25) ; SUM0(x) = ROR32(x, 2) ^ ROR32(x,13) ^ ROR32(x,22) ; ; CH(x,y,x) = (x & y) ^ (~x & z) ; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) = (x&y)^((x^y)&z) ; ; T1 = SUM1(E) +CH(E,F,G) +K[i] +W[i] + H ; T2 = SUM0(A) +MAJ(A,B,C) ; ; D += T1 ; H = T1+T2 ; ; eax = E ; edx = A ; %macro SHA256_STEP 4.nolist %xdefine %%nr %1 %xdefine %%hashBuff %2 %xdefine %%wBuff %3 %xdefine %%immCnt %4 mov esi,[%%hashBuff+((vF-%%nr)&7)*sizeof(dword)] ; init CH() mov ecx,eax mov edi,[%%hashBuff+((vG-%%nr)&7)*sizeof(dword)] ; init CH() mov ebx,eax ; SUM1() ror eax,6 ; SUM1() not ecx ; CH() and esi,ebx ; CH() ror ebx,11 ; SUM1() and edi,ecx ; CH() xor eax,ebx ; SUM1() ror ebx,(25-11) ; SUM1() xor esi,edi ; CH() xor eax,ebx ; SUM1() add eax,esi ; T1 = SUM1() +CH() add eax,[%%hashBuff+((vH-%%nr)&7)*sizeof(dword)] ; T1 += h ;; add eax,[wBuff+(nr&0Fh)*sizeof(dword)] ; T1 += w[] add eax,[%%wBuff] ; T1 += w[] add eax, %%immCnt ; T1 += K[] mov esi,[%%hashBuff+((vB-%%nr)&7)*sizeof(dword)] ; init MAJ() mov ecx,edx mov edi,[%%hashBuff+((vC-%%nr)&7)*sizeof(dword)] ; init MAJ() mov ebx,edx ; SUM0() and ecx,esi ; MAJ() ror edx,2 ; SUM0() xor esi,ebx ; MAJ() ror ebx,13 ; SUM0() and esi,edi ; MAJ() xor edx,ebx ; SUM0() xor esi,ecx ; MAJ() ror ebx,(22-13) ; SUM0() xor edx,ebx ; SUM0() add edx,esi ; T2 = SUM0()+MAJ() add edx,eax ; T2+T1 add eax,[%%hashBuff+((vD-%%nr)&7)*sizeof(dword)] ; T1+d mov [%%hashBuff+((vH-%%nr)&7)*sizeof(dword)],edx mov [%%hashBuff+((vD-%%nr)&7)*sizeof(dword)],eax %endmacro segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA256(DigestSHA256 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; Lib = W7 ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC USES_GPR esi,edi,ebx,ebp %xdefine pHash [esp + ARG_1 + 0*sizeof(dword)] ; pointer to the input/output hash %xdefine pSrc [esp + ARG_1 + 1*sizeof(dword)] ; input message %xdefine srcL [esp + ARG_1 + 2*sizeof(dword)] ; message length %xdefine pParm [esp + ARG_1 + 3*sizeof(dword)] ; dummy parameter %xdefine MBS_SHA256 (64) ; SHA256 block data size %assign dSize 8 ; size of digest (dwords) %assign wSize 16 ; W values queue (dwords) %assign hashOffset 0 ; hash address %assign msgOffset hashOffset+sizeof(dword) ; message address offset %assign lenOffset msgOffset+sizeof(dword) ; message length offset %assign dOffset lenOffset+sizeof(dword) ; hash buffer offset %assign wOffset dOffset+dSize*sizeof(dword) ; W values offset %assign stackSize 3*sizeof(dword) + (dSize+wSize)*sizeof(dword) %assign vA 0 %assign vB 1 %assign vC 2 %assign vD 3 %assign vE 4 %assign vF 5 %assign vG 6 %assign vH 7 mov eax, pParm ; dummy mov edi, pHash ; hash address mov esi, pSrc ; source data address mov eax, srcL ; source data length sub esp, stackSize ; allocate local buffers mov [esp+hashOffset], edi; save hash address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: mov [esp+msgOffset], esi ; save message address mov [esp+lenOffset], eax ; save message length ;; ;; copy input digest ;; mov eax, [edi+0*sizeof(dword)] mov ebx, [edi+1*sizeof(dword)] mov ecx, [edi+2*sizeof(dword)] mov edx, [edi+3*sizeof(dword)] mov [esp+dOffset+vA*sizeof(dword)], eax mov [esp+dOffset+vB*sizeof(dword)], ebx mov [esp+dOffset+vC*sizeof(dword)], ecx mov [esp+dOffset+vD*sizeof(dword)], edx mov eax, [edi+4*sizeof(dword)] mov ebx, [edi+5*sizeof(dword)] mov ecx, [edi+6*sizeof(dword)] mov edx, [edi+7*sizeof(dword)] mov [esp+dOffset+vE*sizeof(dword)], eax mov [esp+dOffset+vF*sizeof(dword)], ebx mov [esp+dOffset+vG*sizeof(dword)], ecx mov [esp+dOffset+vH*sizeof(dword)], edx ;; ;; initialize the first 16 qwords of W array ;; - remember about endian ;; xor ecx, ecx .loop1: mov eax, [esi+ecx*sizeof(dword)] bswap eax mov ebx, [esi+ecx*sizeof(dword)+sizeof(dword)] bswap ebx mov [esp+wOffset+ecx*sizeof(dword)], eax mov [esp+wOffset+ecx*sizeof(dword)+sizeof(dword)], ebx add ecx, 2 cmp ecx, 16 jl .loop1 ;; ;; perform 0-64 steps ;; mov eax, [esp+dOffset+vE*sizeof(dword)] mov edx, [esp+dOffset+vA*sizeof(dword)] SHA256_STEP 0, {esp+dOffset}, {esp+wOffset+ 0*sizeof(dword)}, 0428A2F98h UPDATE 16, {esp+wOffset} SHA256_STEP 1, {esp+dOffset}, {esp+wOffset+ 1*sizeof(dword)}, 071374491h UPDATE 17, {esp+wOffset} SHA256_STEP 2, {esp+dOffset}, {esp+wOffset+ 2*sizeof(dword)}, 0B5C0FBCFh UPDATE 18, {esp+wOffset} SHA256_STEP 3, {esp+dOffset}, {esp+wOffset+ 3*sizeof(dword)}, 0E9B5DBA5h UPDATE 19, {esp+wOffset} SHA256_STEP 4, {esp+dOffset}, {esp+wOffset+ 4*sizeof(dword)}, 03956C25Bh UPDATE 20, {esp+wOffset} SHA256_STEP 5, {esp+dOffset}, {esp+wOffset+ 5*sizeof(dword)}, 059F111F1h UPDATE 21, {esp+wOffset} SHA256_STEP 6, {esp+dOffset}, {esp+wOffset+ 6*sizeof(dword)}, 0923F82A4h UPDATE 22, {esp+wOffset} SHA256_STEP 7, {esp+dOffset}, {esp+wOffset+ 7*sizeof(dword)}, 0AB1C5ED5h UPDATE 23, {esp+wOffset} SHA256_STEP 8, {esp+dOffset}, {esp+wOffset+ 8*sizeof(dword)}, 0D807AA98h UPDATE 24, {esp+wOffset} SHA256_STEP 9, {esp+dOffset}, {esp+wOffset+ 9*sizeof(dword)}, 012835B01h UPDATE 25, {esp+wOffset} SHA256_STEP 10,{esp+dOffset}, {esp+wOffset+10*sizeof(dword)}, 0243185BEh UPDATE 26, {esp+wOffset} SHA256_STEP 11, {esp+dOffset}, {esp+wOffset+11*sizeof(dword)}, 0550C7DC3h UPDATE 27, {esp+wOffset} SHA256_STEP 12, {esp+dOffset}, {esp+wOffset+12*sizeof(dword)}, 072BE5D74h UPDATE 28, {esp+wOffset} SHA256_STEP 13, {esp+dOffset}, {esp+wOffset+13*sizeof(dword)}, 080DEB1FEh UPDATE 29, {esp+wOffset} SHA256_STEP 14, {esp+dOffset}, {esp+wOffset+14*sizeof(dword)}, 09BDC06A7h UPDATE 30, {esp+wOffset} SHA256_STEP 15, {esp+dOffset}, {esp+wOffset+15*sizeof(dword)}, 0C19BF174h UPDATE 31, {esp+wOffset} SHA256_STEP 16, {esp+dOffset}, {esp+wOffset+ 0*sizeof(dword)}, 0E49B69C1h UPDATE 32, {esp+wOffset} SHA256_STEP 17, {esp+dOffset}, {esp+wOffset+ 1*sizeof(dword)}, 0EFBE4786h UPDATE 33, {esp+wOffset} SHA256_STEP 18, {esp+dOffset}, {esp+wOffset+ 2*sizeof(dword)}, 00FC19DC6h UPDATE 34, {esp+wOffset} SHA256_STEP 19, {esp+dOffset}, {esp+wOffset+ 3*sizeof(dword)}, 0240CA1CCh UPDATE 35, {esp+wOffset} SHA256_STEP 20, {esp+dOffset}, {esp+wOffset+ 4*sizeof(dword)}, 02DE92C6Fh UPDATE 36, {esp+wOffset} SHA256_STEP 21, {esp+dOffset}, {esp+wOffset+ 5*sizeof(dword)}, 04A7484AAh UPDATE 37, {esp+wOffset} SHA256_STEP 22, {esp+dOffset}, {esp+wOffset+ 6*sizeof(dword)}, 05CB0A9DCh UPDATE 38, {esp+wOffset} SHA256_STEP 23, {esp+dOffset}, {esp+wOffset+ 7*sizeof(dword)}, 076F988DAh UPDATE 39, {esp+wOffset} SHA256_STEP 24, {esp+dOffset}, {esp+wOffset+ 8*sizeof(dword)}, 0983E5152h UPDATE 40, {esp+wOffset} SHA256_STEP 25, {esp+dOffset}, {esp+wOffset+ 9*sizeof(dword)}, 0A831C66Dh UPDATE 41, {esp+wOffset} SHA256_STEP 26, {esp+dOffset}, {esp+wOffset+10*sizeof(dword)}, 0B00327C8h UPDATE 42, {esp+wOffset} SHA256_STEP 27, {esp+dOffset}, {esp+wOffset+11*sizeof(dword)}, 0BF597FC7h UPDATE 43, {esp+wOffset} SHA256_STEP 28, {esp+dOffset}, {esp+wOffset+12*sizeof(dword)}, 0C6E00BF3h UPDATE 44, {esp+wOffset} SHA256_STEP 29, {esp+dOffset}, {esp+wOffset+13*sizeof(dword)}, 0D5A79147h UPDATE 45, {esp+wOffset} SHA256_STEP 30, {esp+dOffset}, {esp+wOffset+14*sizeof(dword)}, 006CA6351h UPDATE 46, {esp+wOffset} SHA256_STEP 31, {esp+dOffset}, {esp+wOffset+15*sizeof(dword)}, 014292967h UPDATE 47, {esp+wOffset} SHA256_STEP 32, {esp+dOffset}, {esp+wOffset+ 0*sizeof(dword)}, 027B70A85h UPDATE 48, {esp+wOffset} SHA256_STEP 33, {esp+dOffset}, {esp+wOffset+ 1*sizeof(dword)}, 02E1B2138h UPDATE 49, {esp+wOffset} SHA256_STEP 34, {esp+dOffset}, {esp+wOffset+ 2*sizeof(dword)}, 04D2C6DFCh UPDATE 50, {esp+wOffset} SHA256_STEP 35, {esp+dOffset}, {esp+wOffset+ 3*sizeof(dword)}, 053380D13h UPDATE 51, {esp+wOffset} SHA256_STEP 36, {esp+dOffset}, {esp+wOffset+ 4*sizeof(dword)}, 0650A7354h UPDATE 52, {esp+wOffset} SHA256_STEP 37, {esp+dOffset}, {esp+wOffset+ 5*sizeof(dword)}, 0766A0ABBh UPDATE 53, {esp+wOffset} SHA256_STEP 38, {esp+dOffset}, {esp+wOffset+ 6*sizeof(dword)}, 081C2C92Eh UPDATE 54, {esp+wOffset} SHA256_STEP 39, {esp+dOffset}, {esp+wOffset+ 7*sizeof(dword)}, 092722C85h UPDATE 55, {esp+wOffset} SHA256_STEP 40, {esp+dOffset}, {esp+wOffset+ 8*sizeof(dword)}, 0A2BFE8A1h UPDATE 56, {esp+wOffset} SHA256_STEP 41, {esp+dOffset}, {esp+wOffset+ 9*sizeof(dword)}, 0A81A664Bh UPDATE 57, {esp+wOffset} SHA256_STEP 42, {esp+dOffset}, {esp+wOffset+10*sizeof(dword)}, 0C24B8B70h UPDATE 58, {esp+wOffset} SHA256_STEP 43, {esp+dOffset}, {esp+wOffset+11*sizeof(dword)}, 0C76C51A3h UPDATE 59, {esp+wOffset} SHA256_STEP 44, {esp+dOffset}, {esp+wOffset+12*sizeof(dword)}, 0D192E819h UPDATE 60, {esp+wOffset} SHA256_STEP 45, {esp+dOffset}, {esp+wOffset+13*sizeof(dword)}, 0D6990624h UPDATE 61, {esp+wOffset} SHA256_STEP 46, {esp+dOffset}, {esp+wOffset+14*sizeof(dword)}, 0F40E3585h UPDATE 62, {esp+wOffset} SHA256_STEP 47, {esp+dOffset}, {esp+wOffset+15*sizeof(dword)}, 0106AA070h UPDATE 63, {esp+wOffset} SHA256_STEP 48, {esp+dOffset}, {esp+wOffset+ 0*sizeof(dword)}, 019A4C116h SHA256_STEP 49, {esp+dOffset}, {esp+wOffset+ 1*sizeof(dword)}, 01E376C08h SHA256_STEP 50, {esp+dOffset}, {esp+wOffset+ 2*sizeof(dword)}, 02748774Ch SHA256_STEP 51, {esp+dOffset}, {esp+wOffset+ 3*sizeof(dword)}, 034B0BCB5h SHA256_STEP 52, {esp+dOffset}, {esp+wOffset+ 4*sizeof(dword)}, 0391C0CB3h SHA256_STEP 53, {esp+dOffset}, {esp+wOffset+ 5*sizeof(dword)}, 04ED8AA4Ah SHA256_STEP 54, {esp+dOffset}, {esp+wOffset+ 6*sizeof(dword)}, 05B9CCA4Fh SHA256_STEP 55, {esp+dOffset}, {esp+wOffset+ 7*sizeof(dword)}, 0682E6FF3h SHA256_STEP 56, {esp+dOffset}, {esp+wOffset+ 8*sizeof(dword)}, 0748F82EEh SHA256_STEP 57, {esp+dOffset}, {esp+wOffset+ 9*sizeof(dword)}, 078A5636Fh SHA256_STEP 58, {esp+dOffset}, {esp+wOffset+10*sizeof(dword)}, 084C87814h SHA256_STEP 59, {esp+dOffset}, {esp+wOffset+11*sizeof(dword)}, 08CC70208h SHA256_STEP 60, {esp+dOffset}, {esp+wOffset+12*sizeof(dword)}, 090BEFFFAh SHA256_STEP 61, {esp+dOffset}, {esp+wOffset+13*sizeof(dword)}, 0A4506CEBh SHA256_STEP 62, {esp+dOffset}, {esp+wOffset+14*sizeof(dword)}, 0BEF9A3F7h SHA256_STEP 63, {esp+dOffset}, {esp+wOffset+15*sizeof(dword)}, 0C67178F2h ; ; update digest ; mov edi,[esp+hashOffset] mov esi,[esp+msgOffset] mov eax,[esp+dOffset+vA*sizeof(dword)] mov ebx,[esp+dOffset+vB*sizeof(dword)] mov ecx,[esp+dOffset+vC*sizeof(dword)] mov edx,[esp+dOffset+vD*sizeof(dword)] add [edi+0*sizeof(dword)],eax add [edi+1*sizeof(dword)],ebx add [edi+2*sizeof(dword)],ecx add [edi+3*sizeof(dword)],edx mov eax,[esp+dOffset+vE*sizeof(dword)] mov ebx,[esp+dOffset+vF*sizeof(dword)] mov ecx,[esp+dOffset+vG*sizeof(dword)] mov edx,[esp+dOffset+vH*sizeof(dword)] add [edi+4*sizeof(dword)],eax add [edi+5*sizeof(dword)],ebx add [edi+6*sizeof(dword)],ecx add [edi+7*sizeof(dword)],edx mov eax,[esp+lenOffset] add esi, MBS_SHA256 sub eax, MBS_SHA256 jg .sha256_block_loop add esp,stackSize ; remove local buffers REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; (_IPP >= _IPP_M5) && (_IPP < _IPP_V8) %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha512g9as.asm000066400000000000000000000352661470420105600256370ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA512 ; ; Content: ; UpdateSHA512 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA512_) %if (_IPP >= _IPP_G9) ;; ;; ENDIANNESS ;; %macro ENDIANNESS 2.nolist %xdefine %%xmm %1 %xdefine %%masks %2 vpshufb %%xmm, %%xmm, %%masks %endmacro ;; ;; Rotate Right ;; %macro PRORQ 3.nolist %xdefine %%mm %1 %xdefine %%nbits %2 %xdefine %%tmp %3 vpsllq %%tmp, %%mm, (64-%%nbits) vpsrlq %%mm, %%mm, %%nbits vpor %%mm, %%mm,%%tmp %endmacro ;; ;; Init and Update W: ;; ;; j = 0-15 ;; W[j] = ENDIANNESS(src) ;; ;; j = 16-79 ;; W[j] = SIGMA1(W[j- 2]) + W[j- 7] ;; +SIGMA0(W[j-15]) + W[j-16] ;; ;; SIGMA0(x) = ROR64(x,1) ^ROR64(x,8) ^LSR64(x,7) ;; SIGMA1(x) = ROR64(x,19)^ROR64(x,61)^LSR64(x,6) ;; %macro SIGMA0 4.nolist %xdefine %%sigma %1 %xdefine %%x %2 %xdefine %%t1 %3 %xdefine %%t2 %4 vpsrlq %%sigma, %%x, 7 vmovdqa %%t1, %%x PRORQ %%x, 1, %%t2 vpxor %%sigma, %%sigma, %%x PRORQ %%t1,8, %%t2 vpxor %%sigma, %%sigma, %%t1 %endmacro %macro SIGMA1 4.nolist %xdefine %%sigma %1 %xdefine %%x %2 %xdefine %%t1 %3 %xdefine %%t2 %4 vpsrlq %%sigma, %%x, 6 vmovdqa %%t1, %%x PRORQ %%x, 19, %%t2 vpxor %%sigma, %%sigma, %%x PRORQ %%t1,61, %%t2 vpxor %%sigma, %%sigma, %%t1 %endmacro ;; ;; SHA512 step ;; ;; Ipp64u T1 = H + SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t]; ;; Ipp64u T2 = SUM0(A) + MAJ(A,B,C); ;; D+= T1; ;; H = T1 + T2; ;; ;; where ;; SUM1(x) = ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41) ;; SUM0(x) = ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39) ;; ;; CHJ(x,y,z) = (x & y) ^ (~x & z) => x&(y^z) ^z ;; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) = (x&y)^((x^y)&z) ;; ;; Input: ;; A,B,C,D,E,F,G,H - 8 digest's values ;; pW - pointer to the W array ;; pK512 - pointer to the constants ;; pBuffer - temporary buffer ;; Output: ;; A,B,C,D*,E,F,G,H* - 8 digest's values (D and H updated) ;; pW - pointer to the W array ;; pK512 - pointer to the constants ;; pBuffer - temporary buffer (changed) ;; %macro CHJ 5.nolist %xdefine %%R %1 %xdefine %%E %2 %xdefine %%F %3 %xdefine %%G %4 %xdefine %%T %5 vpxor %%R, %%F,%%G ; R=(f^g) vpand %%R, %%R,%%E ; R=e & (f^g) vpxor %%R, %%R,%%G ; R=e & (f^g) ^g %endmacro %macro MAJ 5.nolist %xdefine %%R %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%T %5 vpxor %%T, %%A,%%B ; T=a^b vpand %%R, %%A,%%B ; R=a&b vpand %%T, %%T,%%C ; T=(a^b)&c vpxor %%R, %%R,%%T ; R=(a&b)^((a^b)&c) %endmacro %macro SUM0 3.nolist %xdefine %%R %1 %xdefine %%X %2 %xdefine %%tmp %3 vmovdqa %%R,%%X PRORQ %%R,28,%%tmp ; R=ROR(X,28) PRORQ %%X,34,%%tmp ; X=ROR(X,34) vpxor %%R, %%R,%%X PRORQ %%X,(39-34),%%tmp ; X=ROR(x,39) vpxor %%R, %%R,%%X %endmacro %macro SUM1 3.nolist %xdefine %%R %1 %xdefine %%X %2 %xdefine %%tmp %3 vmovdqa %%R,%%X PRORQ %%R,14,%%tmp ; R=ROR(X,14) PRORQ %%X,18,%%tmp ; X=ROR(X,18) vpxor %%R, %%R,%%X PRORQ %%X,(41-18),%%tmp ; X=ROR(x,41) vpxor %%R, %%R,%%X %endmacro %macro SHA512_STEP 11.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%F %6 %xdefine %%G %7 %xdefine %%H %8 %xdefine %%pW %9 %xdefine %%pK512 %10 %xdefine %%pBuffer %11 vmovdqa oword [%%pBuffer+0*sizeof(oword)],%%E ; save E vmovdqa oword [%%pBuffer+1*sizeof(oword)],%%A ; save A vmovdqa oword [%%pBuffer+2*sizeof(oword)],%%D ; save D vmovdqa oword [%%pBuffer+3*sizeof(oword)],%%H ; save H CHJ %%D,%%E,%%F,%%G, %%H ; t1 = h+CHJ(e,f,g)+pW[]+pK512[] vmovq %%H, qword [%%pW] vpaddq %%D, %%D,%%H ; +[pW] vmovq %%H, qword [%%pK512] vpaddq %%D, %%D,%%H ; +[pK512] vpaddq %%D, %%D,oword [%%pBuffer+3*sizeof(oword)] vmovdqa oword [%%pBuffer+3*sizeof(oword)],%%D ; save t1 MAJ %%H,%%A,%%B,%%C, %%D ; t2 = MAJ(a,b,c) vmovdqa oword [%%pBuffer+4*sizeof(oword)],%%H ; save t2 SUM1 %%D,%%E,%%H ; D = SUM1(e) vpaddq %%D, %%D,oword [%%pBuffer+3*sizeof(oword)]; t1 = h+CHJ(e,f,g)+pW[]+pK512[] + SUM1(e) SUM0 %%H,%%A,%%E ; H = SUM0(a) vpaddq %%H, %%H,oword [%%pBuffer+4*sizeof(oword)]; t2 = MAJ(a,b,c)+SUM0(a) vpaddq %%H, %%H,%%D ; h = t1+t2 vpaddq %%D, %%D,oword [%%pBuffer+2*sizeof(oword)]; d+= t1 vmovdqa %%E,oword [%%pBuffer+0*sizeof(oword)] ; restore E vmovdqa %%A,oword [%%pBuffer+1*sizeof(oword)] ; restore A %endmacro segment .text align=IPP_ALIGN_FACTOR %if (_IPP >= _IPP_V8) align IPP_ALIGN_FACTOR SWP_BYTE: pByteSwp DB 7,6,5,4,3,2,1,0, 15,14,13,12,11,10,9,8 %endif ;******************************************************************************************* ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA512(DigestSHA512 digest, const Ipp64u* mblk, int mlen, const void* pParam) ;* ;******************************************************************************************* ;; ;; Lib = W7, V8, P8 ;; ;; ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; ;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA512,PUBLIC USES_GPR esi,edi,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine digest [ebp + ARG_1 + 0*sizeof(dword)] ; digest address %xdefine mblk [ebp + ARG_1 + 1*sizeof(dword)] ; buffer address %xdefine mlen [ebp + ARG_1 + 2*sizeof(dword)] ; buffer length %xdefine pSHA512 [ebp + ARG_1 + 3*sizeof(dword)] ; address of SHA constants %xdefine MBS_SHA512 (128) ; SHA512 block data size %assign sSize 5 ; size of save area (oword) %assign dSize 8 ; size of digest (oword) %assign wSize 80 ; W values queue (qword) %assign stackSize (sSize*sizeof(oword)+dSize*sizeof(oword)+wSize*sizeof(qword)+sizeof(dword)) ; stack size (bytes) %assign sOffset 0 ; save area %assign dOffset sOffset+sSize*sizeof(oword) ; digest offset %assign wOffset dOffset+dSize*sizeof(oword) ; W values offset %assign acualOffset wOffset+wSize*sizeof(qword) ; actual stack size offset mov edi,digest ; digest address mov esi,mblk ; source data address mov eax,mlen ; source data length mov edx, pSHA512 ; table constant address sub esp,stackSize ; allocate local buffer (probably unaligned) mov ecx,esp and esp,-16 ; 16-byte aligned stack sub ecx,esp add ecx,stackSize ; actual stack size (bytes) mov [esp+acualOffset],ecx vmovq xmm0,qword [edi+sizeof(qword)*0] ; A = digest[0] vmovq xmm1,qword [edi+sizeof(qword)*1] ; B = digest[1] vmovq xmm2,qword [edi+sizeof(qword)*2] ; C = digest[2] vmovq xmm3,qword [edi+sizeof(qword)*3] ; D = digest[3] vmovq xmm4,qword [edi+sizeof(qword)*4] ; E = digest[4] vmovq xmm5,qword [edi+sizeof(qword)*5] ; F = digest[5] vmovq xmm6,qword [edi+sizeof(qword)*6] ; G = digest[6] vmovq xmm7,qword [edi+sizeof(qword)*7] ; H = digest[7] vmovdqa oword [esp+dOffset+sizeof(oword)*0], xmm0 vmovdqa oword [esp+dOffset+sizeof(oword)*1], xmm1 vmovdqa oword [esp+dOffset+sizeof(oword)*2], xmm2 vmovdqa oword [esp+dOffset+sizeof(oword)*3], xmm3 vmovdqa oword [esp+dOffset+sizeof(oword)*4], xmm4 vmovdqa oword [esp+dOffset+sizeof(oword)*5], xmm5 vmovdqa oword [esp+dOffset+sizeof(oword)*6], xmm6 vmovdqa oword [esp+dOffset+sizeof(oword)*7], xmm7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha512_block_loop: ;; ;; initialize the first 16 qwords in the array W (remember about endian) ;; ;vmovdqa xmm1, oword pByteSwp ; load shuffle mask LD_ADDR ecx, SWP_BYTE movdqa xmm1, oword [ecx+(pByteSwp-SWP_BYTE)] mov ecx,0 align IPP_ALIGN_FACTOR .loop1: vmovdqu xmm0, oword [esi+ecx*sizeof(qword)] ; swap input ENDIANNESS xmm0, xmm1 vmovdqa oword [esp+wOffset+ecx*sizeof(qword)],xmm0 add ecx,sizeof(oword)/sizeof(qword) cmp ecx,16 jl .loop1 ;; ;; initialize another 80-16 qwords in the array W ;; align IPP_ALIGN_FACTOR .loop2: vmovdqa xmm1,oword [esp+ecx*sizeof(qword)+wOffset- 2*sizeof(qword)] ; xmm1 = W[j-2] SIGMA1 xmm0,xmm1,xmm2,xmm3 vmovdqu xmm5,oword [esp+ecx*sizeof(qword)+wOffset-15*sizeof(qword)] ; xmm5 = W[j-15] SIGMA0 xmm4,xmm5,xmm6,xmm3 vmovdqu xmm7,oword [esp+ecx*sizeof(qword)+wOffset- 7*sizeof(qword)] ; W[j-7] vpaddq xmm0, xmm0,xmm4 vpaddq xmm7, xmm7,oword [esp+ecx*sizeof(qword)+wOffset-16*sizeof(qword)] ; W[j-16] vpaddq xmm0, xmm0,xmm7 vmovdqa oword [esp+ecx*sizeof(qword)+wOffset],xmm0 add ecx,sizeof(oword)/sizeof(qword) cmp ecx,80 jl .loop2 ;; ;; init A,B,C,D,E,F,G,H by the internal digest ;; vmovdqa xmm0,oword [esp+dOffset+sizeof(oword)*0] ; A = digest[0] vmovdqa xmm1,oword [esp+dOffset+sizeof(oword)*1] ; B = digest[1] vmovdqa xmm2,oword [esp+dOffset+sizeof(oword)*2] ; C = digest[2] vmovdqa xmm3,oword [esp+dOffset+sizeof(oword)*3] ; D = digest[3] vmovdqa xmm4,oword [esp+dOffset+sizeof(oword)*4] ; E = digest[4] vmovdqa xmm5,oword [esp+dOffset+sizeof(oword)*5] ; F = digest[5] vmovdqa xmm6,oword [esp+dOffset+sizeof(oword)*6] ; G = digest[6] vmovdqa xmm7,oword [esp+dOffset+sizeof(oword)*7] ; H = digest[7] ;; ;; perform 0-79 steps ;; xor ecx,ecx align IPP_ALIGN_FACTOR .loop3: ;; A, B, C, D, E, F, G, H W[], K[], buffer ;; -------------------------------------------------------------------------------------------------------------------------------------- SHA512_STEP xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*0},{edx+ecx*sizeof(qword)+sizeof(qword)*0}, {esp} SHA512_STEP xmm7,xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*1},{edx+ecx*sizeof(qword)+sizeof(qword)*1}, {esp} SHA512_STEP xmm6,xmm7,xmm0,xmm1,xmm2,xmm3,xmm4,xmm5, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*2},{edx+ecx*sizeof(qword)+sizeof(qword)*2}, {esp} SHA512_STEP xmm5,xmm6,xmm7,xmm0,xmm1,xmm2,xmm3,xmm4, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*3},{edx+ecx*sizeof(qword)+sizeof(qword)*3}, {esp} SHA512_STEP xmm4,xmm5,xmm6,xmm7,xmm0,xmm1,xmm2,xmm3, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*4},{edx+ecx*sizeof(qword)+sizeof(qword)*4}, {esp} SHA512_STEP xmm3,xmm4,xmm5,xmm6,xmm7,xmm0,xmm1,xmm2, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*5},{edx+ecx*sizeof(qword)+sizeof(qword)*5}, {esp} SHA512_STEP xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm0,xmm1, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*6},{edx+ecx*sizeof(qword)+sizeof(qword)*6}, {esp} SHA512_STEP xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm0, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*7},{edx+ecx*sizeof(qword)+sizeof(qword)*7}, {esp} add ecx,8 cmp ecx,80 jl .loop3 ;; ;; update digest ;; vpaddq xmm0, xmm0,oword [esp+dOffset+sizeof(oword)*0] ; A += digest[0] vpaddq xmm1, xmm1,oword [esp+dOffset+sizeof(oword)*1] ; B += digest[1] vpaddq xmm2, xmm2,oword [esp+dOffset+sizeof(oword)*2] ; C += digest[2] vpaddq xmm3, xmm3,oword [esp+dOffset+sizeof(oword)*3] ; D += digest[3] vpaddq xmm4, xmm4,oword [esp+dOffset+sizeof(oword)*4] ; E += digest[4] vpaddq xmm5, xmm5,oword [esp+dOffset+sizeof(oword)*5] ; F += digest[5] vpaddq xmm6, xmm6,oword [esp+dOffset+sizeof(oword)*6] ; G += digest[6] vpaddq xmm7, xmm7,oword [esp+dOffset+sizeof(oword)*7] ; H += digest[7] vmovdqa oword [esp+dOffset+sizeof(oword)*0],xmm0 ; digest[0] = A vmovdqa oword [esp+dOffset+sizeof(oword)*1],xmm1 ; digest[1] = B vmovdqa oword [esp+dOffset+sizeof(oword)*2],xmm2 ; digest[2] = C vmovdqa oword [esp+dOffset+sizeof(oword)*3],xmm3 ; digest[3] = D vmovdqa oword [esp+dOffset+sizeof(oword)*4],xmm4 ; digest[4] = E vmovdqa oword [esp+dOffset+sizeof(oword)*5],xmm5 ; digest[5] = F vmovdqa oword [esp+dOffset+sizeof(oword)*6],xmm6 ; digest[6] = G vmovdqa oword [esp+dOffset+sizeof(oword)*7],xmm7 ; digest[7] = H add esi, MBS_SHA512 sub eax, MBS_SHA512 jg .sha512_block_loop vmovq qword [edi+sizeof(qword)*0], xmm0 ; A = digest[0] vmovq qword [edi+sizeof(qword)*1], xmm1 ; B = digest[1] vmovq qword [edi+sizeof(qword)*2], xmm2 ; C = digest[2] vmovq qword [edi+sizeof(qword)*3], xmm3 ; D = digest[3] vmovq qword [edi+sizeof(qword)*4], xmm4 ; E = digest[4] vmovq qword [edi+sizeof(qword)*5], xmm5 ; F = digest[5] vmovq qword [edi+sizeof(qword)*6], xmm6 ; G = digest[6] vmovq qword [edi+sizeof(qword)*7], xmm7 ; H = digest[7] add esp,[esp+acualOffset] REST_GPR ret ENDFUNC UpdateSHA512 %endif ;; (_IPP >= _IPP_G9) %endif ;; _ENABLE_ALG_SHA512_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsha512w7as.asm000066400000000000000000000356271470420105600256560ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA512 ; ; Content: ; UpdateSHA512 ; ; %include "asmdefs.inc" %include "ia_emm.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA512_) %if (_IPP >= _IPP_W7) && (_IPP < _IPP_G9) ;; ;; ENDIANNESS ;; %if (_IPP >= _IPP_V8) %macro ENDIANNESS 2.nolist %xdefine %%xmm %1 %xdefine %%masks %2 pshufb %%xmm, %%masks %endmacro %else %macro ENDIANNESS 2.nolist %xdefine %%xmm %1 %xdefine %%tmp %2 pshuflw %%xmm,%%xmm, 00011011b pshufhw %%xmm,%%xmm, 00011011b movdqa %%tmp,%%xmm psrlw %%tmp,8 psllw %%xmm,8 por %%xmm,%%tmp %endmacro %endif ;; ;; Rotate Right ;; %macro PRORQ 3.nolist %xdefine %%mm %1 %xdefine %%nbits %2 %xdefine %%tmp %3 movdqa %%tmp,%%mm psrlq %%mm,%%nbits psllq %%tmp,(64-%%nbits) por %%mm,%%tmp %endmacro ;; ;; Init and Update W: ;; ;; j = 0-15 ;; W[j] = ENDIANNESS(src) ;; ;; j = 16-79 ;; W[j] = SIGMA1(W[j- 2]) + W[j- 7] ;; +SIGMA0(W[j-15]) + W[j-16] ;; ;; SIGMA0(x) = ROR64(x,1) ^ROR64(x,8) ^LSR64(x,7) ;; SIGMA1(x) = ROR64(x,19)^ROR64(x,61)^LSR64(x,6) ;; %macro SIGMA0 4.nolist %xdefine %%sigma %1 %xdefine %%x %2 %xdefine %%t1 %3 %xdefine %%t2 %4 movdqa %%sigma, %%x psrlq %%x, 7 movdqa %%t1,%%sigma PRORQ %%sigma, 1, %%t2 pxor %%sigma, %%x PRORQ %%t1,8, %%t2 pxor %%sigma, %%t1 %endmacro %macro SIGMA1 4.nolist %xdefine %%sigma %1 %xdefine %%x %2 %xdefine %%t1 %3 %xdefine %%t2 %4 movdqa %%sigma, %%x psrlq %%x, 6 movdqa %%t1,%%sigma PRORQ %%sigma, 19, %%t2 pxor %%sigma, %%x PRORQ %%t1,61, %%t2 pxor %%sigma, %%t1 %endmacro ;; ;; SHA512 step ;; ;; Ipp64u T1 = H + SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t]; ;; Ipp64u T2 = SUM0(A) + MAJ(A,B,C); ;; D+= T1; ;; H = T1 + T2; ;; ;; where ;; SUM1(x) = ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41) ;; SUM0(x) = ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39) ;; ;; CHJ(x,y,z) = (x & y) ^ (~x & z) => x&(y^z) ^z ;; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) = (x&y)^((x^y)&z) ;; ;; Input: ;; A,B,C,D,E,F,G,H - 8 digest's values ;; pW - pointer to the W array ;; pK512 - pointer to the constants ;; pBuffer - temporary buffer ;; Output: ;; A,B,C,D*,E,F,G,H* - 8 digest's values (D and H updated) ;; pW - pointer to the W array ;; pK512 - pointer to the constants ;; pBuffer - temporary buffer (changed) ;; %macro CHJ 5.nolist %xdefine %%R %1 %xdefine %%E %2 %xdefine %%F %3 %xdefine %%G %4 %xdefine %%T %5 movdqa %%R,%%F ; R=f pxor %%R,%%G ; R=(f^g) pand %%R,%%E ; R=e & (f^g) pxor %%R,%%G ; R=e & (f^g) ^g %endmacro %macro MAJ 5.nolist %xdefine %%R %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%T %5 movdqa %%T,%%B ; T=b movdqa %%R,%%A ; R=a pxor %%T,%%A ; T=a^b pand %%R,%%B ; R=a&b pand %%T,%%C ; T=(a^b)&c pxor %%R,%%T ; R=(a&b)^((a^b)&c) %endmacro %macro SUM0 3.nolist %xdefine %%R %1 %xdefine %%X %2 %xdefine %%tmp %3 movdqa %%R,%%X PRORQ %%R,28,%%tmp ; R=ROR(X,28) PRORQ %%X,34,%%tmp ; X=ROR(X,34) pxor %%R,%%X PRORQ %%X,(39-34),%%tmp ; X=ROR(x,39) pxor %%R,%%X %endmacro %macro SUM1 3.nolist %xdefine %%R %1 %xdefine %%X %2 %xdefine %%tmp %3 movdqa %%R,%%X PRORQ %%R,14,%%tmp ; R=ROR(X,14) PRORQ %%X,18,%%tmp ; X=ROR(X,18) pxor %%R,%%X PRORQ %%X,(41-18),%%tmp ; X=ROR(x,41) pxor %%R,%%X %endmacro %macro SHA512_STEP 11.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%F %6 %xdefine %%G %7 %xdefine %%H %8 %xdefine %%pW %9 %xdefine %%pK512 %10 %xdefine %%pBuffer %11 movdqa oword [%%pBuffer+0*sizeof(oword)],%%E ; save E movdqa oword [%%pBuffer+1*sizeof(oword)],%%A ; save A movdqa oword [%%pBuffer+2*sizeof(oword)],%%D ; save D movdqa oword [%%pBuffer+3*sizeof(oword)],%%H ; save H CHJ %%D,%%E,%%F,%%G, %%H ; t1 = h+CHJ(e,f,g)+pW[]+pK512[] movq %%H, qword [%%pW] paddq %%D, %%H ; +[pW] movq %%H, qword [%%pK512] paddq %%D, %%H ; +[pK512] paddq %%D,oword [%%pBuffer+3*sizeof(oword)] movdqa oword [%%pBuffer+3*sizeof(oword)],%%D ; save t1 MAJ %%H,%%A,%%B,%%C, %%D ; t2 = MAJ(a,b,c) movdqa oword [%%pBuffer+4*sizeof(oword)],%%H ; save t2 SUM1 %%D,%%E,%%H ; D = SUM1(e) paddq %%D,oword [%%pBuffer+3*sizeof(oword)] ; t1 = h+CHJ(e,f,g)+pW[]+pK512[] + SUM1(e) SUM0 %%H,%%A,%%E ; H = SUM0(a) paddq %%H,oword [%%pBuffer+4*sizeof(oword)] ; t2 = MAJ(a,b,c)+SUM0(a) paddq %%H,%%D ; h = t1+t2 paddq %%D,oword [%%pBuffer+2*sizeof(oword)] ; d+= t1 movdqa %%E,oword [%%pBuffer+0*sizeof(oword)] ; restore E movdqa %%A,oword [%%pBuffer+1*sizeof(oword)] ; restore A %endmacro segment .text align=IPP_ALIGN_FACTOR %if (_IPP >= _IPP_V8) align IPP_ALIGN_FACTOR SWP_BYTE: pByteSwp DB 7,6,5,4,3,2,1,0, 15,14,13,12,11,10,9,8 %endif ;******************************************************************************************* ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA512(DigestSHA512 digest, const Ipp64u* mblk, int mlen, const void* pParam) ;* ;******************************************************************************************* ;; ;; Lib = W7, V8, P8 ;; ;; ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; ;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA512,PUBLIC USES_GPR esi,edi %xdefine digest [esp + ARG_1 + 0*sizeof(dword)] ; digest address %xdefine mblk [esp + ARG_1 + 1*sizeof(dword)] ; buffer address %xdefine mlen [esp + ARG_1 + 2*sizeof(dword)] ; buffer length %xdefine pSHA512 [esp + ARG_1 + 3*sizeof(dword)] ; address of SHA constants %xdefine MBS_SHA512 (128) ; SHA512 block data size %assign sSize 5 ; size of save area (oword) %assign dSize 8 ; size of digest (oword) %assign wSize 80 ; W values queue (qword) %assign stackSize (sSize*sizeof(oword)+dSize*sizeof(oword)+wSize*sizeof(qword)+sizeof(dword)) ; stack size (bytes) %assign sOffset 0 ; save area %assign dOffset sOffset+sSize*sizeof(oword) ; digest offset %assign wOffset dOffset+dSize*sizeof(oword) ; W values offset %assign acualOffset wOffset+wSize*sizeof(qword) ; actual stack size offset mov edi,digest ; digest address mov esi,mblk ; source data address mov eax,mlen ; source data length mov edx, pSHA512 ; table constant address sub esp,stackSize ; allocate local buffer (probably unaligned) mov ecx,esp and esp,-16 ; 16-byte aligned stack sub ecx,esp add ecx,stackSize ; actual stack size (bytes) mov [esp+acualOffset],ecx movq xmm0,qword [edi+sizeof(qword)*0] ; A = digest[0] movq xmm1,qword [edi+sizeof(qword)*1] ; B = digest[1] movq xmm2,qword [edi+sizeof(qword)*2] ; C = digest[2] movq xmm3,qword [edi+sizeof(qword)*3] ; D = digest[3] movq xmm4,qword [edi+sizeof(qword)*4] ; E = digest[4] movq xmm5,qword [edi+sizeof(qword)*5] ; F = digest[5] movq xmm6,qword [edi+sizeof(qword)*6] ; G = digest[6] movq xmm7,qword [edi+sizeof(qword)*7] ; H = digest[7] movdqa oword [esp+dOffset+sizeof(oword)*0], xmm0 movdqa oword [esp+dOffset+sizeof(oword)*1], xmm1 movdqa oword [esp+dOffset+sizeof(oword)*2], xmm2 movdqa oword [esp+dOffset+sizeof(oword)*3], xmm3 movdqa oword [esp+dOffset+sizeof(oword)*4], xmm4 movdqa oword [esp+dOffset+sizeof(oword)*5], xmm5 movdqa oword [esp+dOffset+sizeof(oword)*6], xmm6 movdqa oword [esp+dOffset+sizeof(oword)*7], xmm7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha512_block_loop: ;; ;; initialize the first 16 qwords in the array W (remember about endian) ;; %if (_IPP >= _IPP_V8) ;movdqa xmm1, oword pByteSwp ; load shuffle mask LD_ADDR ecx, SWP_BYTE movdqa xmm1, oword [ecx+(pByteSwp-SWP_BYTE)] %endif mov ecx,0 align IPP_ALIGN_FACTOR .loop1: movdqu xmm0, oword [esi+ecx*sizeof(qword)] ; swap input ENDIANNESS xmm0, xmm1 movdqa oword [esp+wOffset+ecx*sizeof(qword)],xmm0 add ecx,sizeof(oword)/sizeof(qword) cmp ecx,16 jl .loop1 ;; ;; initialize another 80-16 qwords in the array W ;; align IPP_ALIGN_FACTOR .loop2: movdqa xmm1,oword [esp+ecx*sizeof(qword)+wOffset- 2*sizeof(qword)] ; xmm1 = W[j-2] SIGMA1 xmm0,xmm1,xmm2,xmm3 movdqu xmm5,oword [esp+ecx*sizeof(qword)+wOffset-15*sizeof(qword)] ; xmm5 = W[j-15] SIGMA0 xmm4,xmm5,xmm6,xmm3 movdqu xmm7,oword [esp+ecx*sizeof(qword)+wOffset- 7*sizeof(qword)] ; W[j-7] paddq xmm0,xmm4 paddq xmm7,oword [esp+ecx*sizeof(qword)+wOffset-16*sizeof(qword)] ; W[j-16] paddq xmm0,xmm7 movdqa oword [esp+ecx*sizeof(qword)+wOffset],xmm0 add ecx,sizeof(oword)/sizeof(qword) cmp ecx,80 jl .loop2 ;; ;; init A,B,C,D,E,F,G,H by the internal digest ;; movdqa xmm0,oword [esp+dOffset+sizeof(oword)*0] ; A = digest[0] movdqa xmm1,oword [esp+dOffset+sizeof(oword)*1] ; B = digest[1] movdqa xmm2,oword [esp+dOffset+sizeof(oword)*2] ; C = digest[2] movdqa xmm3,oword [esp+dOffset+sizeof(oword)*3] ; D = digest[3] movdqa xmm4,oword [esp+dOffset+sizeof(oword)*4] ; E = digest[4] movdqa xmm5,oword [esp+dOffset+sizeof(oword)*5] ; F = digest[5] movdqa xmm6,oword [esp+dOffset+sizeof(oword)*6] ; G = digest[6] movdqa xmm7,oword [esp+dOffset+sizeof(oword)*7] ; H = digest[7] ;; ;; perform 0-79 steps ;; xor ecx,ecx align IPP_ALIGN_FACTOR .loop3: ;; A, B, C, D, E, F, G, H W[], K[], buffer ;; -------------------------------------------------------------------------------------------------------------------------------------- SHA512_STEP xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*0},{edx+ecx*sizeof(qword)+sizeof(qword)*0}, {esp} SHA512_STEP xmm7,xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*1},{edx+ecx*sizeof(qword)+sizeof(qword)*1}, {esp} SHA512_STEP xmm6,xmm7,xmm0,xmm1,xmm2,xmm3,xmm4,xmm5, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*2},{edx+ecx*sizeof(qword)+sizeof(qword)*2}, {esp} SHA512_STEP xmm5,xmm6,xmm7,xmm0,xmm1,xmm2,xmm3,xmm4, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*3},{edx+ecx*sizeof(qword)+sizeof(qword)*3}, {esp} SHA512_STEP xmm4,xmm5,xmm6,xmm7,xmm0,xmm1,xmm2,xmm3, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*4},{edx+ecx*sizeof(qword)+sizeof(qword)*4}, {esp} SHA512_STEP xmm3,xmm4,xmm5,xmm6,xmm7,xmm0,xmm1,xmm2, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*5},{edx+ecx*sizeof(qword)+sizeof(qword)*5}, {esp} SHA512_STEP xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm0,xmm1, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*6},{edx+ecx*sizeof(qword)+sizeof(qword)*6}, {esp} SHA512_STEP xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm0, {esp+ecx*sizeof(qword)+wOffset+sizeof(qword)*7},{edx+ecx*sizeof(qword)+sizeof(qword)*7}, {esp} add ecx,8 cmp ecx,80 jl .loop3 ;; ;; update digest ;; paddq xmm0,oword [esp+dOffset+sizeof(oword)*0] ; A += digest[0] paddq xmm1,oword [esp+dOffset+sizeof(oword)*1] ; B += digest[1] paddq xmm2,oword [esp+dOffset+sizeof(oword)*2] ; C += digest[2] paddq xmm3,oword [esp+dOffset+sizeof(oword)*3] ; D += digest[3] paddq xmm4,oword [esp+dOffset+sizeof(oword)*4] ; E += digest[4] paddq xmm5,oword [esp+dOffset+sizeof(oword)*5] ; F += digest[5] paddq xmm6,oword [esp+dOffset+sizeof(oword)*6] ; G += digest[6] paddq xmm7,oword [esp+dOffset+sizeof(oword)*7] ; H += digest[7] movdqa oword [esp+dOffset+sizeof(oword)*0],xmm0 ; digest[0] = A movdqa oword [esp+dOffset+sizeof(oword)*1],xmm1 ; digest[1] = B movdqa oword [esp+dOffset+sizeof(oword)*2],xmm2 ; digest[2] = C movdqa oword [esp+dOffset+sizeof(oword)*3],xmm3 ; digest[3] = D movdqa oword [esp+dOffset+sizeof(oword)*4],xmm4 ; digest[4] = E movdqa oword [esp+dOffset+sizeof(oword)*5],xmm5 ; digest[5] = F movdqa oword [esp+dOffset+sizeof(oword)*6],xmm6 ; digest[6] = G movdqa oword [esp+dOffset+sizeof(oword)*7],xmm7 ; digest[7] = H add esi, MBS_SHA512 sub eax, MBS_SHA512 jg .sha512_block_loop movq qword [edi+sizeof(qword)*0], xmm0 ; A = digest[0] movq qword [edi+sizeof(qword)*1], xmm1 ; B = digest[1] movq qword [edi+sizeof(qword)*2], xmm2 ; C = digest[2] movq qword [edi+sizeof(qword)*3], xmm3 ; D = digest[3] movq qword [edi+sizeof(qword)*4], xmm4 ; E = digest[4] movq qword [edi+sizeof(qword)*5], xmm5 ; F = digest[5] movq qword [edi+sizeof(qword)*6], xmm6 ; G = digest[6] movq qword [edi+sizeof(qword)*7], xmm7 ; H = digest[7] add esp,[esp+acualOffset] REST_GPR ret ENDFUNC UpdateSHA512 %endif ;; (_IPP >= _IPP_W7) && (_IPP < _IPP_G9) %endif ;; _ENABLE_ALG_SHA512_ cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpsm2arith_mont_slm.asm000066400000000000000000000615371470420105600275110ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; P256r1 basic arithmetic function ; ; Content: ; sm2_add ; sm2_sub ; sm2_neg ; sm2_div_by_2 ; sm2_mul_mont_slm ; sm2_sqr_mont_slm ; sm2_mred ; sm2_mont_back ; %include "asmdefs.inc" %include "ia_emm.inc" %if (_IPP >= _IPP_P8) segment .text align=IPP_ALIGN_FACTOR ;; ;; some SM2 constants ;; sm2_data: _prime_sm2 DD 0FFFFFFFFh,0FFFFFFFFh,000000000h,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh,0FFFFFFFFh, 0FFFFFFFEh %assign LENSM2 (256/32) ; dword's length of operands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Ipp32u _add_256(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = carry = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM _add_256,PRIVATE ; r = a+b mov eax, dword [esi] add eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] adc eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] adc eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] adc eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] adc eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] adc eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] adc eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] adc eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, 0 adc eax, 0 ret ENDFUNC _add_256 ;; ;; Ipp32u _sub_256(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; ;; input: edi = r ;; esi = a ;; ebx = b ;; ;; output: eax = borrow = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM _sub_256,PRIVATE ; r = a-b mov eax, dword [esi] sub eax, dword [ebx] mov dword [edi], eax mov eax, dword [esi+sizeof(dword)] sbb eax, dword [ebx+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, dword [esi+sizeof(dword)*2] sbb eax, dword [ebx+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, dword [esi+sizeof(dword)*3] sbb eax, dword [ebx+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, dword [esi+sizeof(dword)*4] sbb eax, dword [ebx+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, dword [esi+sizeof(dword)*5] sbb eax, dword [ebx+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, dword [esi+sizeof(dword)*6] sbb eax, dword [ebx+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, dword [esi+sizeof(dword)*7] sbb eax, dword [ebx+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax mov eax, 0 adc eax, 0 ret ENDFUNC _sub_256 ;; ;; Ipp32u _shl_256(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM _shl_256,PRIVATE ; r = a<<1 movdqu xmm0, oword [esi] movdqu xmm1, oword [esi+sizeof(oword)] mov eax, dword [esi+(LENSM2-1)*sizeof(dword)] movdqa xmm2, xmm0 psllq xmm0, 1 psrlq xmm2, 63 movdqa xmm3, xmm1 psllq xmm1, 1 psrlq xmm3, 63 palignr xmm3, xmm2, sizeof(qword) pslldq xmm2, sizeof(qword) por xmm1, xmm3 por xmm0, xmm2 movdqu oword [edi], xmm0 movdqu oword [edi+sizeof(oword)], xmm1 shr eax, 31 ret ENDFUNC _shl_256 ;; ;; void _shr_256(Ipp32u* r, const Ipp32u* a) ;; ;; input: edi = r ;; esi = a ;; eax = ext ;; output: eax = extension = 0/1 ;; align IPP_ALIGN_FACTOR IPPASM _shr_256,PRIVATE ; r = a>>1 movd xmm4, eax movdqu xmm0, oword [esi] movdqu xmm1, oword [esi+sizeof(oword)] psllq xmm4, 63 movdqa xmm2, xmm0 psrlq xmm0, 1 psllq xmm2, 63 movdqa xmm3, xmm1 psrlq xmm1, 1 psllq xmm3, 63 palignr xmm4, xmm3, sizeof(qword) palignr xmm3, xmm2, sizeof(qword) por xmm1, xmm4 por xmm0, xmm3 movdqu oword [edi], xmm0 movdqu oword [edi+sizeof(oword)], xmm1 ret ENDFUNC _shr_256 ;; ;; void cpy_256(Ipp32u* r, const Ipp32u* a) ;; %macro cpy_256 2.nolist %xdefine %%pdst %1 %xdefine %%psrc %2 movdqu xmm0, oword [%%psrc] movdqu xmm1, oword [%%psrc+sizeof(oword)] movdqu oword [%%pdst], xmm0 movdqu oword [%%pdst+sizeof(oword)], xmm1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_add(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM sm2_add,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LENSM2] %assign _sp_ _buf_+(LENSM2)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM _add_256 ; R = A+B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, sm2_data ; modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _sub_256 ; T = R-modulus lea esi,[esp+_buf_] mov edi, pR sub edx, eax ; R = T<0? R : T cmovnz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC sm2_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_sub(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM sm2_sub,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [ebp + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LENSM2] %assign _sp_ _buf_+(LENSM2)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; pR mov esi, pA ; pA mov ebx, pB ; pB CALL_IPPASM _sub_256 ; R = A-B mov edx, eax lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, sm2_data ; modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _add_256 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC sm2_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_neg(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM sm2_neg,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LENSM2] %assign _sp_ _buf_+(LENSM2)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp mov edi, pR ; outpur pR mov esi, pA ; input pA ; r = 0-a mov eax, 0 sub eax, dword [esi] mov dword [edi], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)] mov dword [edi+sizeof(dword)], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*2] mov dword [edi+sizeof(dword)*2], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*3] mov dword [edi+sizeof(dword)*3], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*4] mov dword [edi+sizeof(dword)*4], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*5] mov dword [edi+sizeof(dword)*5], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*6] mov dword [edi+sizeof(dword)*6], eax mov eax, 0 sbb eax, dword [esi+sizeof(dword)*7] mov dword [edi+sizeof(dword)*7], eax sbb edx,edx lea edi, [esp+_buf_] ; T mov esi, pR ; R LD_ADDR ebx, sm2_data ; modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _add_256 ; T = R+modulus lea esi,[esp+_buf_] mov edi, pR test edx, edx ; R = T<0? R : T cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC sm2_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_mul_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM sm2_mul_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LENSM2] %assign _sp_ _buf_+(LENSM2)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; pA CALL_IPPASM _shl_256 ; T = A<<1 mov edx, eax mov esi, edi ; T mov edi, pR ; R LD_ADDR ebx, sm2_data ; modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _sub_256 ; R = T-modulus sub edx, eax ; R = R<0? T : R cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC sm2_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_mul_by_3(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM sm2_mul_by_3,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _bufT_ 0 ; T buffer[LENSM2] %assign _bufU_ _bufT_+(LENSM2)*sizeof(dword) ; U buffer[LENSM2] %assign _mod_ _bufU_+(LENSM2)*sizeof(dword) ; modulus address [1] %assign _sp_ _mod_+sizeof(dword) ; esp [1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp LD_ADDR eax, sm2_data ; srore modulus address lea eax, [eax+(_prime_sm2-sm2_data)] mov dword [esp+_mod_], eax lea edi, [esp+_bufT_] ; T mov esi, pA ; A CALL_IPPASM _shl_256 ; T = A<<1 mov edx, eax mov esi, edi ; T lea edi, [esp+_bufU_] ; U mov ebx, [esp+_mod_] ; modulus CALL_IPPASM _sub_256 ; U = T-modulus sub edx, eax ; T = U<0? T : U cmovz esi, edi cpy_256 edi, esi mov esi, edi mov ebx, pA CALL_IPPASM _add_256 ; T +=A mov edx, eax mov edi, pR ; R mov ebx, [esp+_mod_] ; modulus CALL_IPPASM _sub_256 ; R = T-modulus sub edx, eax ; R = T<0? R : T cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] REST_GPR ret ENDFUNC sm2_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_div_by_2(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM sm2_div_by_2,PUBLIC USES_GPR esi,edi,ebx,ebp mov ebp, esp ; save original esp to use it to reach parameters %xdefine pR [ebp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [ebp + ARG_1 + 1*sizeof(dword)] ; source A address ; ; stack layout: ; %assign _buf_ 0 ; buffer[LENSM2] %assign _sp_ _buf_+(LENSM2)*sizeof(dword) ; esp[1] %assign _frame_ _sp_+sizeof(dword) ; +16 bytes for alignment mov eax, esp ; save esp sub esp, _frame_ ; allocate frame and esp, -16 ; provide 16-byte alignment mov dword [esp+_sp_], eax ; store esp lea edi, [esp+_buf_] ; T mov esi, pA ; A LD_ADDR ebx, sm2_data ; modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _add_256 ; R = A+modulus mov edx, 0 mov ecx, dword [esi] ; shifted_data = (a[0]&1)? T : A and ecx, 1 cmovnz esi, edi cmovz eax, edx mov edi, pR CALL_IPPASM _shr_256 mov esp, [esp+_sp_] REST_GPR ret ENDFUNC sm2_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_mul_mont_slm(Ipp32u* r, const Ipp32u* a, const Ipp32u* b) ;; align IPP_ALIGN_FACTOR IPPASM sm2_mul_mont_slm,PUBLIC USES_GPR ebp,ebx,esi,edi %xdefine pR [eax + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [eax + ARG_1 + 1*sizeof(dword)] ; source A address %xdefine pB [eax + ARG_1 + 2*sizeof(dword)] ; source B address ; ; stack layout: ; %assign _buf_ 0 %assign _rp_ _buf_+(LENSM2+1)*sizeof(dword) ; pR %assign _ap_ _rp_ +sizeof(dword) ; pA %assign _bp_ _ap_+sizeof(dword) ; pB %assign _sp_ _bp_+sizeof(dword) ; esp storage %assign _ssize_ _sp_+sizeof(dword) ; size allocated stack mov eax, esp ; save esp sub esp, _ssize_ ; allocate stack and esp, -16 ; provide 16-byte stack alignment mov dword [esp+_sp_], eax ; store original esp ; clear buffer pxor mm0, mm0 movq qword [esp+_buf_], mm0 movq qword [esp+_buf_+sizeof(qword)], mm0 movq qword [esp+_buf_+sizeof(qword)*2], mm0 movq qword [esp+_buf_+sizeof(qword)*3], mm0 movd dword [esp+_buf_+sizeof(qword)*4], mm0 ; store parameters into the stack ; note: eax here stores an original esp, so it can be used to reach function parameters mov edi, pR mov esi, pA mov ebp, pB mov dword [esp+_rp_], edi mov dword [esp+_ap_], esi mov dword [esp+_bp_], ebp mov edi, LENSM2 movd mm1, dword [esi+sizeof(dword)] ; pre load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] align IPP_ALIGN_FACTOR .mmul_loop: ; ; i-st pass ; modulus = 2^256 -2^224 +2^192 +2^96 -1 ; [8] [7] [6] [3] [0] ; m0 = 1 ; movd mm7, edi ; save pass counter mov edx, dword [ebp] ; b = b[i] mov eax, dword [esi] ; a[0] movd mm0, edx add ebp, sizeof(dword) mov dword [esp+_bp_], ebp pmuludq mm1, mm0 ; a[1]*b[i] pmuludq mm2, mm0 ; a[2]*b[i] mul edx ; (E:u) = (edx:eax) = a[0]*b[i]+buf[0] add eax, dword [esp+_buf_] adc edx, 0 pmuludq mm3, mm0 ; a[3]*b[i] pmuludq mm4, mm0 ; a[4]*b[i] ; multiplication round 1 - round 4 movd ecx, mm1 ; p = a[1]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*1] movd mm1, dword [esi+sizeof(dword)*5] adc edx, 0 movd ebx, mm2 ; p = a[2]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*2] movd mm2, dword [esi+sizeof(dword)*6] adc edx, 0 pmuludq mm1, mm0 ; a[5]*b[i] pmuludq mm2, mm0 ; a[6]*b[i] movd ebp, mm3 ; p = a[3]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*3] movd mm3, dword [esi+sizeof(dword)*7] adc edx, 0 movd edi, mm4 ; p = a[4]*b[i] + E psrlq mm4, 32 add edi, edx movd edx, mm4 adc edx, 0 add edi, dword [esp+_buf_+sizeof(dword)*4] adc edx, 0 pmuludq mm3, mm0 ; a[7]*b[i] ;;; and reduction ;;; ; eax =u0 mov dword [esp+_buf_+sizeof(dword)*0], ecx ; copy add ebx, eax ; +u0 mov dword [esp+_buf_+sizeof(dword)*1], ebx mov ecx, eax sbb eax, 0 sub ebp, eax ; -u0 +cf mov dword [esp+_buf_+sizeof(dword)*2], ebp sbb edi, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*3], edi mov edi, 0 ; save edi = bf adc edi, 0 mov eax, ecx ; multiplication round 5 - round 7 movd ecx, mm1 ; p = a[5]*b[i] + E psrlq mm1, 32 add ecx, edx movd edx, mm1 adc edx, 0 add ecx, dword [esp+_buf_+sizeof(dword)*5] adc edx, 0 movd ebx, mm2 ; p = a[6]*b[i] + E psrlq mm2, 32 add ebx, edx movd edx, mm2 adc edx, 0 add ebx, dword [esp+_buf_+sizeof(dword)*6] adc edx, 0 movd ebp, mm3 ; p = a[7]*b[i] + E psrlq mm3, 32 add ebp, edx movd edx, mm3 adc edx, 0 add ebp, dword [esp+_buf_+sizeof(dword)*7] adc edx, 0 ;;; and reduction ;;; sub ecx, edi ; -bf mov dword [esp+_buf_+sizeof(dword)*4], ecx sbb ebx, 0 ; -bf mov dword [esp+_buf_+sizeof(dword)*5], ebx sbb ebp, eax ; -u0+bf mov dword [esp+_buf_+sizeof(dword)*6], ebp ; last multiplication round 8 movd edi, mm7 ; restore pass counter sbb eax, 0 ; u0-bf mov ebx, 0 add edx, dword [esp+_buf_+sizeof(dword)*8] adc ebx, 0 add edx, eax mov dword [esp+_buf_+sizeof(dword)*7], edx adc ebx, 0 mov dword [esp+_buf_+sizeof(dword)*8], ebx sub edi, 1 movd mm1, dword [esi+sizeof(dword)] ; speculative load a[1], a[2], a[3], a[4] movd mm2, dword [esi+sizeof(dword)*2] movd mm3, dword [esi+sizeof(dword)*3] movd mm4, dword [esi+sizeof(dword)*4] jz .exit_mmul_loop mov ebp, dword [esp+_bp_] ; restore pB jmp .mmul_loop .exit_mmul_loop: emms ; final reduction mov edi, [esp+_rp_] ; result lea esi, [esp+_buf_] ; buffer LD_ADDR ebx, sm2_data ; modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _sub_256 mov edx, dword [esp+_buf_+LENSM2*sizeof(dword)] sub edx, eax ; copy cmovz esi, edi cpy_256 edi, esi mov esp, [esp+_sp_] ; release stack REST_GPR ret ENDFUNC sm2_mul_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_sqr_mont_slm(Ipp32u* r, const Ipp32u* a) ;; align IPP_ALIGN_FACTOR IPPASM sm2_sqr_mont_slm,PUBLIC USES_GPR esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; product address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source A address ;; use sm2_mul_mont_slm to compute sqr mov esi, pA mov edi, pR push esi push esi push edi CALL_IPPASM sm2_mul_mont_slm,PUBLIC add esp, sizeof(dword)*3 REST_GPR ret ENDFUNC sm2_sqr_mont_slm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; void sm2_mred(Ipp32u* r, Ipp32u* prod) ;; ; modulus = 2^256 -2^224 +2^192 +2^96 -1 ; [8] [7] [6] [3] [0] ; m0 = 1 ; align IPP_ALIGN_FACTOR IPPASM sm2_mred,PUBLIC USES_GPR ebx,esi,edi %xdefine pR [esp + ARG_1 + 0*sizeof(dword)] ; reduction address %xdefine pA [esp + ARG_1 + 1*sizeof(dword)] ; source product address ; get parameters: mov esi, pA mov ecx, LENSM2 xor edx, edx align IPP_ALIGN_FACTOR .mred_loop: mov eax, dword [esi] mov ebx, 0 mov dword [esi], ebx mov ebx, dword [esi+sizeof(dword)*2] add ebx, eax mov dword [esi+sizeof(dword)*2], ebx mov ebx, dword [esi+sizeof(dword)*3] push eax sbb eax, 0 sub ebx, eax mov dword [esi+sizeof(dword)*3], ebx pop eax mov ebx, dword [esi+sizeof(dword)*4] sbb ebx, 0 mov dword [esi+sizeof(dword)*4], ebx mov ebx, dword [esi+sizeof(dword)*5] sbb ebx, 0 mov dword [esi+sizeof(dword)*5], ebx mov ebx, dword [esi+sizeof(dword)*6] sbb ebx, 0 mov dword [esi+sizeof(dword)*6], ebx mov ebx, dword [esi+sizeof(dword)*7] sbb ebx, eax mov dword [esi+sizeof(dword)*7], ebx mov ebx, dword [esi+sizeof(dword)*8] sbb eax, 0 add eax, edx mov edx, 0 adc edx, 0 add ebx, eax mov dword [esi+sizeof(dword)*8], ebx adc edx, 0 lea esi, [esi+sizeof(dword)] sub ecx, 1 jnz .mred_loop ; final reduction mov edi, pR ; result LD_ADDR ebx, sm2_data ; address of the modulus lea ebx, [ebx+(_prime_sm2-sm2_data)] CALL_IPPASM _sub_256 sub edx, eax cmovz esi, edi cpy_256 edi, esi REST_GPR ret ENDFUNC sm2_mred %endif ;; _IPP >= _IPP_P8 cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpvariant.inc000066400000000000000000000066111470420105600254750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; Intel(R) Cryptography Primitives Library ; ; Purpose: ; Define ippCP variant ; ; do not change definitions below! ; ;; ;; modes of the feature ;; %assign _FEATURE_OFF_ 0 ;; feature is OFF %assign _FEATURE_ON_ 1 ;; feature is ON %assign _FEATURE_TICKTOCK_ 2 ;; detect is feature OFF/ON ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;_XMM7560_ = 1 %ifdef _XMM7560_ %include "pcpvariant_xmm7560.inc" %endif ;;_TXT_ACM_ = 1 %ifdef _TXT_ACM_ %include "pcpvariant_txt_acm.inc" %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; it possible to force use of C-version of some implementations ;; instead of ASM one ;; %ifndef _USE_C_cpAdd_BNU_ %assign _USE_C_cpAdd_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpSub_BNU_ %assign _USE_C_cpSub_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpInc_BNU_ %assign _USE_C_cpInc_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpAddMulDgt_BNU_ %assign _USE_C_cpAddMulDgt_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpMulAdc_BNU_school_ %assign _USE_C_cpMulAdc_BNU_school_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpSqrAdc_BNU_school_ %assign _USE_C_cpSqrAdc_BNU_school_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpMontRedAdc_BNU_ %assign _USE_C_cpMontRedAdc_BNU_ _FEATURE_OFF_ %endif ;; ;; if there is no outside assignment ;; set _SHA_NI_ENABLING_ based on CPU specification ;; %ifndef _SHA_NI_ENABLING_ %if (_IPP >= _IPP_P8 ) %assign _SHA_NI_ENABLING_ _FEATURE_TICKTOCK_ %else %assign _SHA_NI_ENABLING_ _FEATURE_OFF_ %endif %endif ;; ;; select Hash algorithm ;; %ifndef _DISABLE_ALG_SHA1_ %assign _ENABLE_ALG_SHA1_ _FEATURE_ON_ ;; SHA1 on %else %assign _ENABLE_ALG_SHA1_ _FEATURE_OFF_ ;; SHA1 on %endif %ifndef _DISABLE_ALG_SHA256_ %assign _ENABLE_ALG_SHA256_ _FEATURE_ON_ ;; SHA256 on %else %assign _ENABLE_ALG_SHA256_ _FEATURE_OFF_ ;; SHA256 off %endif %ifndef _DISABLE_ALG_SHA521_ %assign _ENABLE_ALG_SHA512_ _FEATURE_ON_ ;; SHA512 on %else %assign _ENABLE_ALG_SHA512_ _FEATURE_OFF_ ;; SHA512 off %endif %ifndef _DISABLE_ALG_MD5_ %assign _ENABLE_ALG_MD5_ _FEATURE_ON_ ;; MD5 on %else %assign _ENABLE_ALG_MD5_ _FEATURE_OFF_ ;; MD5 off %endif %ifndef _DISABLE_ALG_SM3_ %assign _ENABLE_ALG_SM3_ _FEATURE_ON_ ;; SM3 on %else %assign _ENABLE_ALG_SM3_ _FEATURE_OFF_ ;; SM3 off %endif %assign _ENABLE_KARATSUBA_ 0 ;; not use Karatsuba method for multiplication %assign _NUSE 0 ;; do not use use %assign _USE 1 ;; do use ;; ~ 5.0 %assign _USE_NN_MUL_BNU_FS_ _NUSE ;; use/not use NN version of full-size multiplication %assign _USE_NN_MONTMUL_ _NUSE ;; use/not use NN version of Montgomery multiplication cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpvariant_txt_acm.inc000066400000000000000000000020741470420105600272130ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; Intel(R) Cryptography Primitives Library ; ; Purpose: ; Update standard ippCP variant ; ; do not change definitions below! ; %ifdef _TXT_ACM_ ;; ;; HASH algs outside settings ;; %assign _SHA_NI_ENABLING_ _FEATURE_TICKTOCK_ ;; ;; select Hash algorithm ;; %assign _ENABLE_ALG_MD5_ _FEATURE_OFF_ %endif cryptography-primitives-1.0.0/sources/ippcp/asm_ia32/pcpvariant_xmm7560.inc000066400000000000000000000025371470420105600267030ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; Intel(R) Cryptography Primitives Library ; ; Purpose: ; Update standard ippCP variant ; for code size optimization ; %ifdef _XMM7560_ %if (_IPP >= _IPP_P8) %assign OFF 0 %assign ON 1 ;%assign _USE_C_cpAdd_BNU_ ON ;%assign _USE_C_cpSub_BNU_ ON ;%assign _USE_C_cpInc_BNU_ ON ;%assign _USE_C_cpAddMulDgt_BNU_ ON ;%assign _USE_C_cpSubMulDgt_BNU_ ON %assign _USE_C_cpMulAdc_BNU_school_ ON %assign _USE_C_cpSqrAdc_BNU_school_ ON %assign _USE_C_cpMontRedAdc_BNU_ ON %assign _DISABLE_ECP_256R1_HARDCODED_BP_TBL_ OFF %assign _DISABLE_ECP_384R1_HARDCODED_BP_TBL_ OFF %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/000077500000000000000000000000001470420105600233565ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/aes_common.inc000066400000000000000000000361011470420105600261720ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 _AES_COMMON_ASM_ %define _AES_COMMON_ASM_ %include "reg_sizes.inc" ;; ============================================================================= ;; Generic macro to produce code that executes %%OPCODE instruction ;; on selected number of AES blocks (16 bytes long ) between 0 and 16. ;; All three operands of the instruction come from registers. ;; Note: if 3 blocks are left at the end instruction is produced to operate all ;; 4 blocks (full width of ZMM) %macro ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 14 %define %%NUM_BLOCKS %1 ; [in] numerical value, number of AES blocks (0 to 16) %define %%OPCODE %2 ; [in] instruction name %define %%DST0 %3 ; [out] destination ZMM register %define %%DST1 %4 ; [out] destination ZMM register %define %%DST2 %5 ; [out] destination ZMM register %define %%DST3 %6 ; [out] destination ZMM register %define %%SRC1_0 %7 ; [in] source 1 ZMM register %define %%SRC1_1 %8 ; [in] source 1 ZMM register %define %%SRC1_2 %9 ; [in] source 1 ZMM register %define %%SRC1_3 %10 ; [in] source 1 ZMM register %define %%SRC2_0 %11 ; [in] source 2 ZMM register %define %%SRC2_1 %12 ; [in] source 2 ZMM register %define %%SRC2_2 %13 ; [in] source 2 ZMM register %define %%SRC2_3 %14 ; [in] source 2 ZMM register %assign reg_idx 0 %assign blocks_left %%NUM_BLOCKS %rep (%%NUM_BLOCKS / 4) %xdefine %%DSTREG %%DST %+ reg_idx %xdefine %%SRC1REG %%SRC1_ %+ reg_idx %xdefine %%SRC2REG %%SRC2_ %+ reg_idx %%OPCODE %%DSTREG, %%SRC1REG, %%SRC2REG %undef %%DSTREG %undef %%SRC1REG %undef %%SRC2REG %assign reg_idx (reg_idx + 1) %assign blocks_left (blocks_left - 4) %endrep %xdefine %%DSTREG %%DST %+ reg_idx %xdefine %%SRC1REG %%SRC1_ %+ reg_idx %xdefine %%SRC2REG %%SRC2_ %+ reg_idx %if blocks_left == 1 %%OPCODE XWORD(%%DSTREG), XWORD(%%SRC1REG), XWORD(%%SRC2REG) %elif blocks_left == 2 %%OPCODE YWORD(%%DSTREG), YWORD(%%SRC1REG), YWORD(%%SRC2REG) %elif blocks_left == 3 %%OPCODE %%DSTREG, %%SRC1REG, %%SRC2REG %endif %endmacro ;; ============================================================================= ;; Loads specified number of AES blocks into ZMM registers ;; %%FLAGS are optional and only affect behavior when 3 trailing blocks are left ;; - if %%FlAGS not provided then exactly 3 blocks are loaded (move and insert) ;; - if "load_4_instead_of_3" option is passed then 4 blocks are loaded %macro ZMM_LOAD_BLOCKS_0_16 7-8 %define %%NUM_BLOCKS %1 ; [in] numerical value, number of AES blocks (0 to 16) %define %%INP %2 ; [in] input data pointer to read from %define %%DATA_OFFSET %3 ; [in] offset to the output pointer (GP or numerical) %define %%DST0 %4 ; [out] ZMM register with loaded data %define %%DST1 %5 ; [out] ZMM register with loaded data %define %%DST2 %6 ; [out] ZMM register with loaded data %define %%DST3 %7 ; [out] ZMM register with loaded data %define %%FLAGS %8 ; [in] optional "load_4_instead_of_3" %assign src_offset 0 %assign dst_idx 0 %rep (%%NUM_BLOCKS / 4) %xdefine %%DSTREG %%DST %+ dst_idx vmovdqu8 %%DSTREG, [%%INP + %%DATA_OFFSET + src_offset] %undef %%DSTREG %assign src_offset (src_offset + 64) %assign dst_idx (dst_idx + 1) %endrep %assign blocks_left (%%NUM_BLOCKS % 4) %xdefine %%DSTREG %%DST %+ dst_idx %if blocks_left == 1 vmovdqu8 XWORD(%%DSTREG), [%%INP + %%DATA_OFFSET + src_offset] %elif blocks_left == 2 vmovdqu8 YWORD(%%DSTREG), [%%INP + %%DATA_OFFSET + src_offset] %elif blocks_left == 3 %ifidn %%FLAGS, load_4_instead_of_3 vmovdqu8 %%DSTREG, [%%INP + %%DATA_OFFSET + src_offset] %else vmovdqu8 YWORD(%%DSTREG), [%%INP + %%DATA_OFFSET + src_offset] vinserti64x2 %%DSTREG, [%%INP + %%DATA_OFFSET + src_offset + 32], 2 %endif %endif %endmacro ;; ============================================================================= ;; Loads specified number of AES blocks into ZMM registers using mask register ;; for the last loaded register (xmm, ymm or zmm). ;; Loads take place at 1 byte granularity. %macro ZMM_LOAD_MASKED_BLOCKS_0_16 8 %define %%NUM_BLOCKS %1 ; [in] numerical value, number of AES blocks (0 to 16) %define %%INP %2 ; [in] input data pointer to read from %define %%DATA_OFFSET %3 ; [in] offset to the output pointer (GP or numerical) %define %%DST0 %4 ; [out] ZMM register with loaded data %define %%DST1 %5 ; [out] ZMM register with loaded data %define %%DST2 %6 ; [out] ZMM register with loaded data %define %%DST3 %7 ; [out] ZMM register with loaded data %define %%MASK %8 ; [in] mask register %assign src_offset 0 %assign dst_idx 0 %assign blocks_left %%NUM_BLOCKS %if %%NUM_BLOCKS > 0 %rep (((%%NUM_BLOCKS + 3) / 4) - 1) %xdefine %%DSTREG %%DST %+ dst_idx vmovdqu8 %%DSTREG, [%%INP + %%DATA_OFFSET + src_offset] %undef %%DSTREG %assign src_offset (src_offset + 64) %assign dst_idx (dst_idx + 1) %assign blocks_left (blocks_left - 4) %endrep %endif ; %if %%NUM_BLOCKS > 0 %xdefine %%DSTREG %%DST %+ dst_idx %if blocks_left == 1 vmovdqu8 XWORD(%%DSTREG){%%MASK}{z}, [%%INP + %%DATA_OFFSET + src_offset] %elif blocks_left == 2 vmovdqu8 YWORD(%%DSTREG){%%MASK}{z}, [%%INP + %%DATA_OFFSET + src_offset] %elif (blocks_left == 3 || blocks_left == 4) vmovdqu8 %%DSTREG{%%MASK}{z}, [%%INP + %%DATA_OFFSET + src_offset] %endif %endmacro ;; ============================================================================= ;; Stores specified number of AES blocks from ZMM registers %macro ZMM_STORE_BLOCKS_0_16 7 %define %%NUM_BLOCKS %1 ; [in] numerical value, number of AES blocks (0 to 16) %define %%OUTP %2 ; [in] output data pointer to write to %define %%DATA_OFFSET %3 ; [in] offset to the output pointer (GP or numerical) %define %%SRC0 %4 ; [in] ZMM register with data to store %define %%SRC1 %5 ; [in] ZMM register with data to store %define %%SRC2 %6 ; [in] ZMM register with data to store %define %%SRC3 %7 ; [in] ZMM register with data to store %assign dst_offset 0 %assign src_idx 0 %rep (%%NUM_BLOCKS / 4) %xdefine %%SRCREG %%SRC %+ src_idx vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset], %%SRCREG %undef %%SRCREG %assign dst_offset (dst_offset + 64) %assign src_idx (src_idx + 1) %endrep %assign blocks_left (%%NUM_BLOCKS % 4) %xdefine %%SRCREG %%SRC %+ src_idx %if blocks_left == 1 vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset], XWORD(%%SRCREG) %elif blocks_left == 2 vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset], YWORD(%%SRCREG) %elif blocks_left == 3 vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset], YWORD(%%SRCREG) vextracti32x4 [%%OUTP + %%DATA_OFFSET + dst_offset + 32], %%SRCREG, 2 %endif %endmacro ;; ============================================================================= ;; Stores specified number of AES blocks from ZMM registers with mask register ;; for the last loaded register (xmm, ymm or zmm). ;; Stores take place at 1 byte granularity. %macro ZMM_STORE_MASKED_BLOCKS_0_16 8 %define %%NUM_BLOCKS %1 ; [in] numerical value, number of AES blocks (0 to 16) %define %%OUTP %2 ; [in] output data pointer to write to %define %%DATA_OFFSET %3 ; [in] offset to the output pointer (GP or numerical) %define %%SRC0 %4 ; [in] ZMM register with data to store %define %%SRC1 %5 ; [in] ZMM register with data to store %define %%SRC2 %6 ; [in] ZMM register with data to store %define %%SRC3 %7 ; [in] ZMM register with data to store %define %%MASK %8 ; [in] mask register %assign dst_offset 0 %assign src_idx 0 %assign blocks_left %%NUM_BLOCKS %if %%NUM_BLOCKS > 0 %rep (((%%NUM_BLOCKS + 3) / 4) - 1) %xdefine %%SRCREG %%SRC %+ src_idx vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset], %%SRCREG %undef %%SRCREG %assign dst_offset (dst_offset + 64) %assign src_idx (src_idx + 1) %assign blocks_left (blocks_left - 4) %endrep %endif ; %if %%NUM_BLOCKS > 0 %xdefine %%SRCREG %%SRC %+ src_idx %if blocks_left == 1 vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset]{%%MASK}, XWORD(%%SRCREG) %elif blocks_left == 2 vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset]{%%MASK}, YWORD(%%SRCREG) %elif (blocks_left == 3 || blocks_left == 4) vmovdqu8 [%%OUTP + %%DATA_OFFSET + dst_offset]{%%MASK}, %%SRCREG %endif %endmacro ;;; =========================================================================== ;;; Handles AES encryption rounds ;;; It handles special cases: the last and first rounds ;;; Optionally, it performs XOR with data after the last AES round. ;;; Uses NROUNDS parameterto check what needs to be done for the current round. ;;; If 3 blocks are trailing then operation on whole ZMM is performed (4 blocks). %macro ZMM_AESENC_ROUND_BLOCKS_0_16 12 %define %%L0B0_3 %1 ; [in/out] zmm; blocks 0 to 3 %define %%L0B4_7 %2 ; [in/out] zmm; blocks 4 to 7 %define %%L0B8_11 %3 ; [in/out] zmm; blocks 8 to 11 %define %%L0B12_15 %4 ; [in/out] zmm; blocks 12 to 15 %define %%KEY %5 ; [in] zmm containing round key %define %%ROUND %6 ; [in] round number %define %%D0_3 %7 ; [in] zmm or no_data; plain/cipher text blocks 0-3 %define %%D4_7 %8 ; [in] zmm or no_data; plain/cipher text blocks 4-7 %define %%D8_11 %9 ; [in] zmm or no_data; plain/cipher text blocks 8-11 %define %%D12_15 %10 ; [in] zmm or no_data; plain/cipher text blocks 12-15 %define %%NUMBL %11 ; [in] number of blocks; numerical value %define %%NROUNDS %12 ; [in] number of rounds; numerical value ;;; === first AES round %if (%%ROUND < 1) ;; round 0 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vpxorq, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%KEY, %%KEY, %%KEY, %%KEY %endif ; ROUND 0 ;;; === middle AES rounds %if (%%ROUND >= 1 && %%ROUND <= %%NROUNDS) ;; rounds 1 to 9/11/13 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vaesenc, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%KEY, %%KEY, %%KEY, %%KEY %endif ; rounds 1 to 9/11/13 ;;; === last AES round %if (%%ROUND > %%NROUNDS) ;; the last round - mix enclast with text xor's ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vaesenclast, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%KEY, %%KEY, %%KEY, %%KEY ;;; === XOR with data %ifnidn %%D0_3, no_data %ifnidn %%D4_7, no_data %ifnidn %%D8_11, no_data %ifnidn %%D12_15, no_data ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vpxorq, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%D0_3, %%D4_7, %%D8_11, %%D12_15 %endif ; !no_data %endif ; !no_data %endif ; !no_data %endif ; !no_data %endif ; The last round %endmacro ;;; =========================================================================== ;;; Handles AES decryption rounds ;;; It handles special cases: the last and first rounds ;;; Optionally, it performs XOR with data after the last AES round. ;;; Uses NROUNDS parameter to check what needs to be done for the current round. ;;; If 3 blocks are trailing then operation on whole ZMM is performed (4 blocks). %macro ZMM_AESDEC_ROUND_BLOCKS_0_16 12 %define %%L0B0_3 %1 ; [in/out] zmm; blocks 0 to 3 %define %%L0B4_7 %2 ; [in/out] zmm; blocks 4 to 7 %define %%L0B8_11 %3 ; [in/out] zmm; blocks 8 to 11 %define %%L0B12_15 %4 ; [in/out] zmm; blocks 12 to 15 %define %%KEY %5 ; [in] zmm containing round key %define %%ROUND %6 ; [in] round number %define %%D0_3 %7 ; [in] zmm or no_data; cipher text blocks 0-3 %define %%D4_7 %8 ; [in] zmm or no_data; cipher text blocks 4-7 %define %%D8_11 %9 ; [in] zmm or no_data; cipher text blocks 8-11 %define %%D12_15 %10 ; [in] zmm or no_data; cipher text blocks 12-15 %define %%NUMBL %11 ; [in] number of blocks; numerical value %define %%NROUNDS %12 ; [in] number of rounds; numerical value ;;; === first AES round %if (%%ROUND < 1) ;; round 0 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vpxorq, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%KEY, %%KEY, %%KEY, %%KEY %endif ; ROUND 0 ;;; === middle AES rounds %if (%%ROUND >= 1 && %%ROUND <= %%NROUNDS) ;; rounds 1 to 9/11/13 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vaesdec, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%KEY, %%KEY, %%KEY, %%KEY %endif ; rounds 1 to 9/11/13 ;;; === last AES round %if (%%ROUND > %%NROUNDS) ;; the last round - mix enclast with text xor's ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vaesdeclast, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%KEY, %%KEY, %%KEY, %%KEY ;;; === XOR with data %ifnidn %%D0_3, no_data %ifnidn %%D4_7, no_data %ifnidn %%D8_11, no_data %ifnidn %%D12_15, no_data ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUMBL, vpxorq, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%L0B0_3, %%L0B4_7, %%L0B8_11, %%L0B12_15, \ %%D0_3, %%D4_7, %%D8_11, %%D12_15 %endif ; !no_data %endif ; !no_data %endif ; !no_data %endif ; !no_data %endif ; The last round %endmacro %endif ;; _AES_COMMON_ASM cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/aes_keyexp_128.asm000066400000000000000000000057521470420105600266200ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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. ;========================================================================= ; Routine to do AES key expansion %include "os.inc" %define NO_AESNI_RENAME %include "clear_regs.inc" %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %macro key_expansion_128_avx 0 ;; Assumes the xmm3 includes all zeros at this point. vpshufd xmm2, xmm2, 11111111b vshufps xmm3, xmm3, xmm1, 00010000b vpxor xmm1, xmm1, xmm3 vshufps xmm3, xmm3, xmm1, 10001100b vpxor xmm1, xmm1, xmm3 vpxor xmm1, xmm1, xmm2 %endmacro %ifdef LINUX %define KEY rdi %define EXP_ENC_KEYS rsi %define EXP_DEC_KEYS rdx %else %define KEY rcx %define EXP_ENC_KEYS rdx %define EXP_DEC_KEYS r8 %endif section .text IPPASM aes_keyexp_128_enc, PUBLIC vmovdqu xmm1, [KEY] ; loading the AES key vmovdqa [EXP_ENC_KEYS + 16*0], xmm1 vpxor xmm3, xmm3, xmm3 vaeskeygenassist xmm2, xmm1, 0x1 ; Generating round key 1 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*1], xmm1 vaeskeygenassist xmm2, xmm1, 0x2 ; Generating round key 2 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*2], xmm1 vaeskeygenassist xmm2, xmm1, 0x4 ; Generating round key 3 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*3], xmm1 vaeskeygenassist xmm2, xmm1, 0x8 ; Generating round key 4 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*4], xmm1 vaeskeygenassist xmm2, xmm1, 0x10 ; Generating round key 5 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*5], xmm1 vaeskeygenassist xmm2, xmm1, 0x20 ; Generating round key 6 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*6], xmm1 vaeskeygenassist xmm2, xmm1, 0x40 ; Generating round key 7 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*7], xmm1 vaeskeygenassist xmm2, xmm1, 0x80 ; Generating round key 8 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*8], xmm1 vaeskeygenassist xmm2, xmm1, 0x1b ; Generating round key 9 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*9], xmm1 vaeskeygenassist xmm2, xmm1, 0x36 ; Generating round key 10 key_expansion_128_avx vmovdqa [EXP_ENC_KEYS + 16*10], xmm1 clear_scratch_gps_asm clear_scratch_xmms_avx_asm ret ENDFUNC aes_keyexp_128_enc %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/aes_keyexp_192.asm000066400000000000000000000074101470420105600266120ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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. ;========================================================================= ; Routine to do AES key expansion %include "os.inc" %define NO_AESNI_RENAME %include "clear_regs.inc" %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %ifdef LINUX %define KEY rdi %define EXP_ENC_KEYS rsi %define EXP_DEC_KEYS rdx %else %define KEY rcx %define EXP_ENC_KEYS rdx %define EXP_DEC_KEYS r8 %endif %macro key_expansion_1_192_avx 1 ;; Assumes the xmm3 includes all zeros at this point. vpshufd xmm2, xmm2, 11111111b vshufps xmm3, xmm3, xmm1, 00010000b vpxor xmm1, xmm1, xmm3 vshufps xmm3, xmm3, xmm1, 10001100b vpxor xmm1, xmm1, xmm3 vpxor xmm1, xmm1, xmm2 vmovdqu [EXP_ENC_KEYS + %1], xmm1 %endmacro ; Calculate w10 and w11 using calculated w9 and known w4-w5 %macro key_expansion_2_192_avx 1 vmovdqa xmm5, xmm4 vpslldq xmm5, xmm5, 4 vshufps xmm6, xmm6, xmm1, 11110000b vpxor xmm6, xmm6, xmm5 vpxor xmm4, xmm4, xmm6 vpshufd xmm7, xmm4, 00001110b vmovdqu [EXP_ENC_KEYS + %1], xmm7 %endmacro %macro key_dec_192_avx 1 vmovdqa xmm0, [EXP_ENC_KEYS + 16 * %1] vaesimc xmm1, xmm0 vmovdqa [EXP_DEC_KEYS + 16 * (12 - %1)], xmm1 %endmacro section .text IPPASM aes_keyexp_192_enc, PUBLIC %ifndef LINUX sub rsp, 16*2 + 8 vmovdqa [rsp + 0*16], xmm6 vmovdqa [rsp + 1*16], xmm7 %endif vmovq xmm7, [KEY + 16] ; loading the AES key, 64 bits vmovq [EXP_ENC_KEYS + 16], xmm7 ; Storing key in memory where all key expansion vpshufd xmm4, xmm7, 01001111b vmovdqu xmm1, [KEY] ; loading the AES key, 128 bits vmovdqu [EXP_ENC_KEYS], xmm1 ; Storing key in memory where all key expansion vpxor xmm3, xmm3, xmm3 vpxor xmm6, xmm6, xmm6 vaeskeygenassist xmm2, xmm4, 0x1 ; Complete round key 1 and generate round key 2 key_expansion_1_192_avx 24 key_expansion_2_192_avx 40 vaeskeygenassist xmm2, xmm4, 0x2 ; Generate round key 3 and part of round key 4 key_expansion_1_192_avx 48 key_expansion_2_192_avx 64 vaeskeygenassist xmm2, xmm4, 0x4 ; Complete round key 4 and generate round key 5 key_expansion_1_192_avx 72 key_expansion_2_192_avx 88 vaeskeygenassist xmm2, xmm4, 0x8 ; Generate round key 6 and part of round key 7 key_expansion_1_192_avx 96 key_expansion_2_192_avx 112 vaeskeygenassist xmm2, xmm4, 0x10 ; Complete round key 7 and generate round key 8 key_expansion_1_192_avx 120 key_expansion_2_192_avx 136 vaeskeygenassist xmm2, xmm4, 0x20 ; Generate round key 9 and part of round key 10 key_expansion_1_192_avx 144 key_expansion_2_192_avx 160 vaeskeygenassist xmm2, xmm4, 0x40 ; Complete round key 10 and generate round key 11 key_expansion_1_192_avx 168 key_expansion_2_192_avx 184 vaeskeygenassist xmm2, xmm4, 0x80 ; Generate round key 12 key_expansion_1_192_avx 192 clear_scratch_gps_asm clear_scratch_xmms_avx_asm %ifndef LINUX vmovdqa xmm6, [rsp + 0*16] vmovdqa xmm7, [rsp + 1*16] add rsp, 16*2 + 8 %endif ret ENDFUNC aes_keyexp_192_enc %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/aes_keyexp_256.asm000066400000000000000000000076561470420105600266270ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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. ;========================================================================= ; Routine to do AES key expansion %include "os.inc" %define NO_AESNI_RENAME %include "clear_regs.inc" %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) ; Uses the f() function of the aeskeygenassist result %macro key_expansion_256_avx 0 ;; Assumes the xmm3 includes all zeros at this point. vpshufd xmm2, xmm2, 11111111b vshufps xmm3, xmm3, xmm1, 00010000b vpxor xmm1, xmm1, xmm3 vshufps xmm3, xmm3, xmm1, 10001100b vpxor xmm1, xmm1, xmm3 vpxor xmm1, xmm1, xmm2 %endmacro ; Uses the SubWord function of the aeskeygenassist result %macro key_expansion_256_avx_2 0 ;; Assumes the xmm3 includes all zeros at this point. vpshufd xmm2, xmm2, 10101010b vshufps xmm3, xmm3, xmm4, 00010000b vpxor xmm4, xmm4, xmm3 vshufps xmm3, xmm3, xmm4, 10001100b vpxor xmm4, xmm4, xmm3 vpxor xmm4, xmm4, xmm2 %endmacro %ifdef LINUX %define KEY rdi %define EXP_ENC_KEYS rsi %define EXP_DEC_KEYS rdx %else %define KEY rcx %define EXP_ENC_KEYS rdx %define EXP_DEC_KEYS r8 %endif section .text IPPASM aes_keyexp_256_enc, PUBLIC vmovdqu xmm1, [KEY] ; loading the AES key vmovdqa [EXP_ENC_KEYS + 16*0], xmm1 vmovdqu xmm4, [KEY+16] ; loading the AES key vmovdqa [EXP_ENC_KEYS + 16*1], xmm4 vpxor xmm3, xmm3, xmm3 ; Required for the key_expansion. vaeskeygenassist xmm2, xmm4, 0x1 ; Generating round key 2 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*2], xmm1 vaeskeygenassist xmm2, xmm1, 0x1 ; Generating round key 3 key_expansion_256_avx_2 vmovdqa [EXP_ENC_KEYS + 16*3], xmm4 vaeskeygenassist xmm2, xmm4, 0x2 ; Generating round key 4 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*4], xmm1 vaeskeygenassist xmm2, xmm1, 0x2 ; Generating round key 5 key_expansion_256_avx_2 vmovdqa [EXP_ENC_KEYS + 16*5], xmm4 vaeskeygenassist xmm2, xmm4, 0x4 ; Generating round key 6 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*6], xmm1 vaeskeygenassist xmm2, xmm1, 0x4 ; Generating round key 7 key_expansion_256_avx_2 vmovdqa [EXP_ENC_KEYS + 16*7], xmm4 vaeskeygenassist xmm2, xmm4, 0x8 ; Generating round key 8 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*8], xmm1 vaeskeygenassist xmm2, xmm1, 0x8 ; Generating round key 9 key_expansion_256_avx_2 vmovdqa [EXP_ENC_KEYS + 16*9], xmm4 vaeskeygenassist xmm2, xmm4, 0x10 ; Generating round key 10 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*10], xmm1 vaeskeygenassist xmm2, xmm1, 0x10 ; Generating round key 11 key_expansion_256_avx_2 vmovdqa [EXP_ENC_KEYS + 16*11], xmm4 vaeskeygenassist xmm2, xmm4, 0x20 ; Generating round key 12 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*12], xmm1 vaeskeygenassist xmm2, xmm1, 0x20 ; Generating round key 13 key_expansion_256_avx_2 vmovdqa [EXP_ENC_KEYS + 16*13], xmm4 vaeskeygenassist xmm2, xmm4, 0x40 ; Generating round key 14 key_expansion_256_avx vmovdqa [EXP_ENC_KEYS + 16*14], xmm1 clear_scratch_gps_asm clear_scratch_xmms_avx_asm ret ENDFUNC aes_keyexp_256_enc %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/clear_regs.inc000066400000000000000000000077551470420105600261750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 _CLEAR_REGS_ASM_ %define _CLEAR_REGS_ASM_ %include "os.inc" ; ; This macro clears any GP registers passed ; %macro clear_gps 1-16 %define %%NUM_REGS %0 %rep %%NUM_REGS xor %1, %1 %rotate 1 %endrep %endmacro ; ; This macro clears any XMM registers passed on SSE ; %macro clear_xmms_sse 1-16 %define %%NUM_REGS %0 %rep %%NUM_REGS pxor %1, %1 %rotate 1 %endrep %endmacro ; ; This macro clears any XMM registers passed on AVX ; %macro clear_xmms_avx 1-16 %define %%NUM_REGS %0 %rep %%NUM_REGS vpxor %1, %1 %rotate 1 %endrep %endmacro ; ; This macro clears any YMM registers passed ; %macro clear_ymms 1-16 %define %%NUM_REGS %0 %rep %%NUM_REGS vpxor %1, %1 %rotate 1 %endrep %endmacro ; ; This macro clears any ZMM registers passed ; %macro clear_zmms 1-32 %define %%NUM_REGS %0 %rep %%NUM_REGS vpxorq %1, %1 %rotate 1 %endrep %endmacro ; ; This macro clears all scratch GP registers ; for Windows or Linux ; %macro clear_scratch_gps_asm 0 clear_gps rax, rcx, rdx, r8, r9, r10, r11 %ifdef LINUX clear_gps rdi, rsi %endif %endmacro ; ; This macro clears all scratch XMM registers on SSE ; %macro clear_scratch_xmms_sse_asm 0 %ifdef LINUX %assign i 0 %rep 16 pxor xmm %+ i, xmm %+ i %assign i (i+1) %endrep ; On Windows, XMM0-XMM5 registers are scratch registers %else %assign i 0 %rep 6 pxor xmm %+ i, xmm %+ i %assign i (i+1) %endrep %endif ; LINUX %endmacro ; ; This macro clears all scratch XMM registers on AVX ; %macro clear_scratch_xmms_avx_asm 0 %ifdef LINUX vzeroall ; On Windows, XMM0-XMM5 registers are scratch registers %else %assign i 0 %rep 6 vpxor xmm %+ i, xmm %+ i %assign i (i+1) %endrep %endif ; LINUX %endmacro ; ; This macro clears all scratch YMM registers ; ; It should be called before restoring the XMM registers ; for Windows (XMM6-XMM15) ; %macro clear_scratch_ymms_asm 0 ; On Linux, all YMM registers are scratch registers %ifdef LINUX vzeroall ; On Windows, YMM0-YMM5 registers are scratch registers. ; YMM6-YMM15 upper 128 bits are scratch registers too, but ; the lower 128 bits are to be restored after calling these function ; which clears the upper bits too. %else %assign i 0 %rep 6 vpxor ymm %+ i, ymm %+ i %assign i (i+1) %endrep %endif ; LINUX %endmacro ; ; This macro clears all scratch ZMM registers ; ; It should be called before restoring the XMM registers ; for Windows (XMM6-XMM15). YMM registers are used ; on purpose, since XOR'ing YMM registers is faster ; than XOR'ing ZMM registers, and the operation clears ; also the upper 256 bits ; %macro clear_scratch_zmms_asm 0 ; On Linux, all ZMM registers are scratch registers %ifdef LINUX vzeroall ;; vzeroall only clears the first 16 ZMM registers %assign i 16 %rep 16 vpxorq ymm %+ i, ymm %+ i %assign i (i+1) %endrep ; On Windows, ZMM0-ZMM5 and ZMM16-ZMM31 registers are scratch registers. ; ZMM6-ZMM15 upper 384 bits are scratch registers too, but ; the lower 128 bits are to be restored after calling these function ; which clears the upper bits too. %else %assign i 0 %rep 6 vpxorq ymm %+ i, ymm %+ i %assign i (i+1) %endrep %assign i 16 %rep 16 vpxorq ymm %+ i, ymm %+ i %assign i (i+1) %endrep %endif ; LINUX %endmacro %endif ;; _CLEAR_REGS_ASM cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/cpinitas.asm000066400000000000000000000165711470420105600257040ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %assign LOCAL_ALIGN_FACTOR 32 %ifdef _IPP_DATA segment .text align=LOCAL_ALIGN_FACTOR ;#################################################################### ;# void cpGetReg( int* buf, int valueEAX, int valueECX ); # ;#################################################################### %ifdef WIN32E %define buf rcx %define valueEAX edx %define valueECX r8d %else %define buf rdi %define valueEAX esi %define valueECX edx %endif align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpGetReg,PUBLIC push rbx movsxd r9, valueEAX movsxd r10, valueECX mov r11, buf mov rax, r9 mov rcx, r10 xor ebx, ebx xor edx, edx cpuid mov [r11], eax mov [r11 + 4], ebx mov [r11 + 8], ecx mov [r11 + 12], edx pop rbx ret ENDFUNC cpGetReg ;################################################### ; OSXSAVE support, feature information after cpuid(1), ECX, bit 27 ( XGETBV is enabled by OS ) %assign XSAVEXGETBV_FLAG 8000000h ; Feature information after XGETBV(ECX=0), EAX, bits 2,1 ( XMM state and YMM state are enabled by OS ) %assign XGETBV_MASK 06h %assign XGETBV_AVX512_MASK 0E0h align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_is_avx_extension,PUBLIC push rbx mov eax, 1 cpuid xor eax, eax and ecx, 018000000h cmp ecx, 018000000h jne .not_avx xor ecx, ecx db 00fh,001h,0d0h ; xgetbv mov ecx, eax xor eax, eax and ecx, XGETBV_MASK cmp ecx, XGETBV_MASK jne .not_avx mov eax, 1 .not_avx: pop rbx ret ENDFUNC cp_is_avx_extension align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_is_avx512_extension,PUBLIC push rbx mov eax, 1 cpuid xor eax, eax and ecx, XSAVEXGETBV_FLAG cmp ecx, XSAVEXGETBV_FLAG jne .not_avx512 xor ecx, ecx db 00fh,001h,0d0h ; xgetbv mov ecx, eax xor eax, eax and ecx, XGETBV_AVX512_MASK cmp ecx, XGETBV_AVX512_MASK jne .not_avx512 mov eax, 1 .not_avx512: pop rbx ret ENDFUNC cp_is_avx512_extension align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_issue_avx512_instruction,PUBLIC db 062h,0f1h,07dh,048h,0efh,0c0h ; vpxord zmm0, zmm0, zmm0 xor eax, eax ret ENDFUNC cp_issue_avx512_instruction %ifdef OSXEM64T extern _ippcpInit %else extern ippcpInit %endif ;#################################################################### ;# void ippSafeInit( ); # ;#################################################################### align LOCAL_ALIGN_FACTOR DECLARE_FUNC ippcpSafeInit,PUBLIC push rcx push rdx %ifdef LINUX32E push rdi push rsi %endif push r8 push r9 %ifdef LINUX32E %ifdef OSXEM64T call _ippcpInit %else %ifdef IPP_PIC call ippcpInit wrt ..plt %else call ippcpInit %endif %endif %else call ippcpInit %endif pop r9 pop r8 %ifdef LINUX32E pop rsi pop rdi %endif pop rdx pop rcx ret ENDFUNC ippcpSafeInit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align LOCAL_ALIGN_FACTOR DECLARE_FUNC cp_get_pentium_counter,PUBLIC rdtsc sal rdx,32 or rax,rdx ret ENDFUNC cp_get_pentium_counter align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStartTscp,PUBLIC push rbx xor rax, rax cpuid pop rbx rdtscp sal rdx,32 or rax,rdx ret ENDFUNC cpStartTscp align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStopTscp,PUBLIC rdtscp sal rdx,32 or rax,rdx push rax push rbx xor rax, rax cpuid pop rbx pop rax ret ENDFUNC cpStopTscp align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStartTsc,PUBLIC push rbx xor rax, rax cpuid pop rbx rdtsc sal rdx,32 or rax,rdx ret ENDFUNC cpStartTsc align LOCAL_ALIGN_FACTOR DECLARE_FUNC cpStopTsc,PUBLIC rdtsc sal rdx,32 or rax,rdx push rax push rbx xor rax, rax cpuid pop rbx pop rax ret ENDFUNC cpStopTsc ;***************************************** ; int cpGetCacheSize( int* tableCache ); align LOCAL_ALIGN_FACTOR %define table rdi DECLARE_FUNC cpGetCacheSize,PUBLIC %assign LOCAL_FRAME 16 USES_GPR rsi, rdi, rbx, rbp USES_XMM COMP_ABI 1 mov rbp, rsp xor esi, esi mov eax, 2 cpuid cmp al, 1 jne .GetCacheSize_11 test eax, 080000000h jz .GetCacheSize_00 xor eax, eax .GetCacheSize_00: test ebx, 080000000h jz .GetCacheSize_01 xor ebx, ebx .GetCacheSize_01: test ecx, 080000000h jz .GetCacheSize_02 xor ecx, ecx .GetCacheSize_02: test edx, 080000000h jz .GetCacheSize_03 xor edx, edx .GetCacheSize_03: test eax, eax jz .GetCacheSize_04 mov [rbp], eax add rbp, 4 add esi, 3 .GetCacheSize_04: test ebx, ebx jz .GetCacheSize_05 mov [rbp], ebx add rbp, 4 add esi, 4 .GetCacheSize_05: test ecx, ecx jz .GetCacheSize_06 mov [rbp], ecx add rbp, 4 add esi, 4 .GetCacheSize_06: test edx, edx jz .GetCacheSize_07 mov [rbp], edx add esi, 4 .GetCacheSize_07: test esi, esi jz .GetCacheSize_11 mov eax, -1 .GetCacheSize_08: xor edx, edx add edx, [table] jz .ExitGetCacheSize00 add table, 8 mov ecx, esi .GetCacheSize_09: cmp dl, BYTE [rsp + rcx] je .GetCacheSize_10 dec ecx jnz .GetCacheSize_09 jmp .GetCacheSize_08 .GetCacheSize_10: mov eax, [table - 4] .ExitGetCacheSize00: REST_XMM REST_GPR ret .GetCacheSize_11: mov eax, -1 jmp .ExitGetCacheSize00 ENDFUNC cpGetCacheSize ;**************************** %endif ; _IPP_DATA cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/emulator.inc000066400000000000000000000150171470420105600257050ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2009 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: EM64T Cryptography Primitive. ; ; ; %ifndef _EMULATOR_INC_ %define _EMULATOR_INC_ %macro my_pclmulqdq 3.nolist %xdefine %%xxDst %1 %xdefine %%xxSrc %2 %xdefine %%xxOp %3 %if (my_emulator == 0) pclmulqdq %%xxDst, %%xxSrc, %%xxOp %else ;; ;; rsp ;; registers ;; +00 => xxDst ;; +16 => xxSrc pushf push rax push rbx push rcx push rdx push rdi push rsi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 %assign %%stackSize (sizeof(oword)*2) sub rsp,%%stackSize movdqu oword [rsp+00], %%xxDst ;; save Dst movdqu oword [rsp+16], %%xxSrc ;; save Src lea rcx, [rsp+00] lea rdx, [rsp+16] mov r8, %%xxOp sub rsp, (sizeof(qword)*3) call emu_pclmulqdq add rsp, (sizeof(qword)*3) movdqu %%xxDst, oword [rsp+00] ;; return Dst ;movdqu xxSrc, oword [rsp+16] ;; return Src add esp, %%stackSize pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rsi pop rdi pop rdx pop rcx pop rbx pop rax popf %endif %endmacro %macro my_aesenc 2.nolist %xdefine %%xxDst %1 %xdefine %%xxSrc %2 %if (my_emulator == 0) aesenc %%xxDst, %%xxSrc %else pushf push rax push rbx push rcx push rdx push rdi push rsi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 %assign %%stackSize (sizeof(oword)*2) sub rsp,%%stackSize movdqu oword [rsp+00], %%xxDst ;; save Dst movdqu oword [rsp+16], %%xxSrc ;; save Src lea rcx, [rsp+00] lea rdx, [rsp+16] sub rsp, (sizeof(qword)*2) call emu_aesenc add rsp, (sizeof(qword)*2) movdqu %%xxDst, oword [rsp+00] ;; return Dst add esp, %%stackSize pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rsi pop rdi pop rdx pop rcx pop rbx pop rax popf %endif %endmacro %macro my_aesenclast 2.nolist %xdefine %%xxDst %1 %xdefine %%xxSrc %2 %if (my_emulator == 0) aesenclast %%xxDst, %%xxSrc %else pushf push rax push rbx push rcx push rdx push rdi push rsi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 %assign %%stackSize (sizeof(oword)*2) sub rsp,%%stackSize movdqu oword [rsp+00], %%xxDst ;; save Dst movdqu oword [rsp+16], %%xxSrc ;; save Src lea rcx, [rsp+00] lea rdx, [rsp+16] sub rsp, (sizeof(qword)*2) call emu_aesenclast add rsp, (sizeof(qword)*2) movdqu %%xxDst, oword [rsp+00] ;; return Dst add esp, %%stackSize pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rsi pop rdi pop rdx pop rcx pop rbx pop rax popf %endif %endmacro %macro my_aesdec 2.nolist %xdefine %%xxDst %1 %xdefine %%xxSrc %2 %if (my_emulator == 0) aesdec %%xxDst, %%xxSrc %else pushf push rax push rbx push rcx push rdx push rdi push rsi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 %assign %%stackSize (sizeof(oword)*2) sub rsp,%%stackSize movdqu oword [rsp+00], %%xxDst ;; save Dst movdqu oword [rsp+16], %%xxSrc ;; save Src lea rcx, [rsp+00] lea rdx, [rsp+16] sub rsp, (sizeof(qword)*2) call emu_aesdec add rsp, (sizeof(qword)*2) movdqu %%xxDst, oword [rsp+00] ;; return Dst add esp, %%stackSize pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rsi pop rdi pop rdx pop rcx pop rbx pop rax popf %endif %endmacro %macro my_aesdeclast 2.nolist %xdefine %%xxDst %1 %xdefine %%xxSrc %2 %if (my_emulator == 0) aesenclast %%xxDst, %%xxSrc %else pushf push rax push rbx push rcx push rdx push rdi push rsi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 %assign %%stackSize (sizeof(oword)*2) sub rsp,%%stackSize movdqu oword [rsp+00], %%xxDst ;; save Dst movdqu oword [rsp+16], %%xxSrc ;; save Src lea rcx, [rsp+00] lea rdx, [rsp+16] sub rsp, (sizeof(qword)*2) call emu_aesdeclast add rsp, (sizeof(qword)*2) movdqu %%xxDst, oword [rsp+00] ;; return Dst add esp, %%stackSize pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rsi pop rdi pop rdx pop rcx pop rbx pop rax popf %endif %endmacro %if (my_emulator != 0) extern emu_pclmulqdq extern emu_aesenc extern emu_aesenclast extern emu_aesdec extern emu_aesdeclast %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm128_api_vaes_avx512.asm000066400000000000000000000016441470420105600300430ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %define GCM128_MODE 1 %include "gcm_api_vaes_avx512.inc" %include "gcm_ippcp_api_vaes_avx512.inc" %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm128_avx512.asm000066400000000000000000000015631470420105600261740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %define GCM128_MODE 1 %include "gcm_avx512.inc" %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm192_api_vaes_avx512.asm000066400000000000000000000016341470420105600300430ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %define GCM192_MODE 1 ;; single buffer implementation %include "gcm_api_vaes_avx512.inc" %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm192_avx512.asm000066400000000000000000000015631470420105600261750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %define GCM192_MODE 1 %include "gcm_avx512.inc" %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm256_api_vaes_avx512.asm000066400000000000000000000016341470420105600300440ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %define GCM256_MODE 1 ;; single buffer implementation %include "gcm_api_vaes_avx512.inc" %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm256_avx512.asm000066400000000000000000000015631470420105600261760ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_K0) %define GCM256_MODE 1 %include "gcm_avx512.inc" %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_api_vaes_avx512.inc000066400000000000000000000140621470420105600275770ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 _GCM_API_VAES_AVX512_INC_ %define _GCM_API_VAES_AVX512_INC_ %include "gcm_vaes_avx512.inc" section .text default rel ;; Safe param check is disabled as parameters checking is done outside. %ifdef SAFE_PARAM %undef SAFE_PARAM %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_precomp_128_vaes_avx512 / ; aes_gcm_precomp_192_vaes_avx512 / ; aes_gcm_precomp_256_vaes_avx512 ; (struct gcm_key_data *key_data) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(precomp,_), PUBLIC ;; Parameter is passed through register %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz .exit_precomp %endif FUNC_SAVE vpxor xmm6, xmm6 ENCRYPT_SINGLE_BLOCK arg1, xmm6 ; xmm6 = HashKey vpshufb xmm6, [rel SHUF_MASK] ;;;;;;;;;;;;;;; PRECOMPUTATION of HashKey<<1 mod poly from the HashKey;;;;;;;;;;;;;;; vmovdqa xmm2, xmm6 vpsllq xmm6, xmm6, 1 vpsrlq xmm2, xmm2, 63 vmovdqa xmm1, xmm2 vpslldq xmm2, xmm2, 8 vpsrldq xmm1, xmm1, 8 vpor xmm6, xmm6, xmm2 ;reduction vpshufd xmm2, xmm1, 00100100b vpcmpeqd xmm2, [rel TWOONE] vpand xmm2, xmm2, [rel POLY] vpxor xmm6, xmm6, xmm2 ; xmm6 holds the HashKey<<1 mod poly ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu [arg1 + HashKey], xmm6 ; store HashKey<<1 mod poly PRECOMPUTE arg1, xmm6, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm7, xmm8 FUNC_RESTORE .exit_precomp: ret ENDFUNC FN_NAME(precomp,_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_enc_128_update_vaes_avx512 / aes_gcm_enc_192_update_vaes_avx512 / ; aes_gcm_enc_256_update_vaes_avx512 ; (const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; u8 *out, ; const u8 *in, ; u64 plaintext_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(enc,_update_), PUBLIC FUNC_SAVE %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz .exit_update_enc ;; Check context_data != NULL cmp arg2, 0 jz .exit_update_enc ;; Check if plaintext_len == 0 cmp arg5, 0 jz .exit_update_enc ;; Check out != NULL (plaintext_len != 0) cmp arg3, 0 jz .exit_update_enc ;; Check in != NULL (plaintext_len != 0) cmp arg4, 0 jz .exit_update_enc %endif GCM_ENC_DEC arg1, arg2, arg3, arg4, arg5, ENC, multi_call .exit_update_enc: FUNC_RESTORE ret ENDFUNC FN_NAME(enc,_update_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_dec_128_update_vaes_avx512 / aes_gcm_dec_192_update_vaes_avx512 / ; aes_gcm_dec_256_update_vaes_avx512 ; (const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; u8 *out, ; const u8 *in, ; u64 plaintext_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(dec,_update_), PUBLIC FUNC_SAVE %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz .exit_update_dec ;; Check context_data != NULL cmp arg2, 0 jz .exit_update_dec ;; Check if plaintext_len == 0 cmp arg5, 0 jz .exit_update_dec ;; Check out != NULL (plaintext_len != 0) cmp arg3, 0 jz .exit_update_dec ;; Check in != NULL (plaintext_len != 0) cmp arg4, 0 jz .exit_update_dec %endif GCM_ENC_DEC arg1, arg2, arg3, arg4, arg5, DEC, multi_call .exit_update_dec: FUNC_RESTORE ret ENDFUNC FN_NAME(dec,_update_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_gettag_128_vaes_avx512 / aes_gcm_gettag_192_vaes_avx512 / ; aes_gcm_gettag_256_vaes_avx512 ; (const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; u8 *auth_tag, ; u64 auth_tag_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(gettag,_), PUBLIC ;; All parameters are passed through registers %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz .exit_enc_fin ;; Check context_data != NULL cmp arg2, 0 jz .exit_enc_fin ;; Check auth_tag != NULL cmp arg3, 0 jz .exit_enc_fin ;; Check auth_tag_len == 0 or > 16 cmp arg4, 0 jz .exit_enc_fin cmp arg4, 16 ja .exit_enc_fin %endif FUNC_SAVE GCM_COMPLETE arg1, arg2, arg3, arg4, multi_call, k1, r10, r11, r12 FUNC_RESTORE .exit_enc_fin: ret ENDFUNC FN_NAME(gettag,_) %endif ; _GCM_API_VAES_AVX512_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_avx512.inc000066400000000000000000004062701470420105600257360ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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. ;========================================================================= ; ; Authors: ; Erdinc Ozturk ; Vinodh Gopal ; James Guilford ; Tomasz Kantecki ; ; ; References: ; This code was derived and highly optimized from the code described in paper: ; Vinodh Gopal et. al. Optimized Galois-Counter-Mode Implementation on Intel Architecture Processors. August, 2010 ; The details of the implementation is explained in: ; Erdinc Ozturk et. al. Enabling High-Performance Galois-Counter-Mode on Intel Architecture Processors. October, 2012. ; ; ; ; ; Assumptions: ; ; ; ; iv: ; 0 1 2 3 ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | Salt (From the SA) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | Initialization Vector | ; | (This is the sequence number from IPSec header) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 0x1 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; ; ; AAD: ; AAD will be padded with 0 to the next 16byte multiple ; for example, assume AAD is a u32 vector ; ; if AAD is 8 bytes: ; AAD[3] = {A0, A1}; ; padded AAD in xmm register = {A1 A0 0 0} ; ; 0 1 2 3 ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | SPI (A1) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 32-bit Sequence Number (A0) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 0x0 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; AAD Format with 32-bit Sequence Number ; ; if AAD is 12 bytes: ; AAD[3] = {A0, A1, A2}; ; padded AAD in xmm register = {A2 A1 A0 0} ; ; 0 1 2 3 ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | SPI (A2) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 64-bit Extended Sequence Number {A1,A0} | ; | | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 0x0 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; AAD Format with 64-bit Extended Sequence Number ; ; ; aadLen: ; Must be a multiple of 4 bytes and from the definition of the spec. ; The code additionally supports any aadLen length. ; ; TLen: ; from the definition of the spec, TLen can only be 8, 12 or 16 bytes. ; ; poly = x^128 + x^127 + x^126 + x^121 + 1 ; throughout the code, one tab and two tab indentations are used. one tab is for GHASH part, two tabs is for AES part. ; %ifndef _GCM_AVX512_INC_ %define _GCM_AVX512_INC_ %include "os.inc" %include "reg_sizes.inc" %include "clear_regs.inc" %include "gcm_defines.inc" %include "gcm_keys_avx512.inc" %include "memcpy.inc" %include "aes_common.inc" %include "asmdefs.inc" %include "ia_32e.inc" %ifndef GCM128_MODE %ifndef GCM192_MODE %ifndef GCM256_MODE %error "No GCM mode selected for gcm_avx512.asm!" %endif %endif %endif ;; Decide on AES-GCM key size to compile for %ifdef GCM128_MODE %define NROUNDS 9 %define FN_NAME(x,y) aes_gcm_ %+ x %+ _128 %+ y %+ avx512 %endif %ifdef GCM192_MODE %define NROUNDS 11 %define FN_NAME(x,y) aes_gcm_ %+ x %+ _192 %+ y %+ avx512 %endif %ifdef GCM256_MODE %define NROUNDS 13 %define FN_NAME(x,y) aes_gcm_ %+ x %+ _256 %+ y %+ avx512 %endif section .text default rel ; need to push 4 registers into stack to maintain %define STACK_OFFSET 8*4 %ifidn __OUTPUT_FORMAT__, win64 %define XMM_STORAGE 16*10 %else %define XMM_STORAGE 0 %endif %define TMP2 16*0 ; Temporary storage for AES State 2 (State 1 is stored in an XMM register) %define TMP3 16*1 ; Temporary storage for AES State 3 %define TMP4 16*2 ; Temporary storage for AES State 4 %define TMP5 16*3 ; Temporary storage for AES State 5 %define TMP6 16*4 ; Temporary storage for AES State 6 %define TMP7 16*5 ; Temporary storage for AES State 7 %define TMP8 16*6 ; Temporary storage for AES State 8 %define LOCAL_STORAGE 16*7 %define VARIABLE_OFFSET LOCAL_STORAGE + XMM_STORAGE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Utility Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GHASH_MUL MACRO to implement: Data*HashKey mod (128,127,126,121,0) ; Input: A and B (128-bits each, bit-reflected) ; Output: C = A*B*x mod poly, (i.e. >>1 ) ; To compute GH = GH*HashKey mod poly, give HK = HashKey<<1 mod poly as input ; GH = GH * HK * x mod poly which is equivalent to GH*HashKey mod poly. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GHASH_MUL 7 %define %%GH %1 ; 16 Bytes %define %%HK %2 ; 16 Bytes %define %%T1 %3 %define %%T2 %4 %define %%T3 %5 %define %%T4 %6 %define %%T5 %7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpclmulqdq %%T1, %%GH, %%HK, 0x11 ; %%T1 = a1*b1 vpclmulqdq %%T2, %%GH, %%HK, 0x00 ; %%T2 = a0*b0 vpclmulqdq %%T3, %%GH, %%HK, 0x01 ; %%T3 = a1*b0 vpclmulqdq %%GH, %%GH, %%HK, 0x10 ; %%GH = a0*b1 vpxor %%GH, %%GH, %%T3 vpsrldq %%T3, %%GH, 8 ; shift-R %%GH 2 DWs vpslldq %%GH, %%GH, 8 ; shift-L %%GH 2 DWs vpxor %%T1, %%T1, %%T3 vpxor %%GH, %%GH, %%T2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqu %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%GH, 0x01 vpslldq %%T2, %%T2, 8 ; shift-L %%T2 2 DWs vpxor %%GH, %%GH, %%T2 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%T2, %%T3, %%GH, 0x00 vpsrldq %%T2, %%T2, 4 ; shift-R %%T2 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%GH, %%T3, %%GH, 0x10 vpslldq %%GH, %%GH, 4 ; shift-L %%GH 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%GH, %%GH, %%T2 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%GH, %%GH, %%T1 ; the result is in %%GH %endmacro ; In PRECOMPUTE, the commands filling Hashkey_i_k are not required for avx512 ; functions, but are kept to allow users to switch cpu architectures between calls ; of pre, init, update, and finalize. %macro PRECOMPUTE 8 %define %%GDATA %1 %define %%HK %2 %define %%T1 %3 %define %%T2 %4 %define %%T3 %5 %define %%T4 %6 %define %%T5 %7 %define %%T6 %8 ; Haskey_i_k holds XORed values of the low and high parts of the Haskey_i vmovdqa %%T5, %%HK GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^2<<1 mod poly vmovdqu [%%GDATA + HashKey_2], %%T5 ; [HashKey_2] = HashKey^2<<1 mod poly GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^3<<1 mod poly vmovdqu [%%GDATA + HashKey_3], %%T5 GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^4<<1 mod poly vmovdqu [%%GDATA + HashKey_4], %%T5 GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^5<<1 mod poly vmovdqu [%%GDATA + HashKey_5], %%T5 GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^6<<1 mod poly vmovdqu [%%GDATA + HashKey_6], %%T5 GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^7<<1 mod poly vmovdqu [%%GDATA + HashKey_7], %%T5 GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 ; %%T5 = HashKey^8<<1 mod poly vmovdqu [%%GDATA + HashKey_8], %%T5 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; READ_SMALL_DATA_INPUT: Packs xmm register with data when data input is less than 16 bytes. ; Returns 0 if data has length 0. ; Input: The input data (INPUT), that data's length (LENGTH). ; Output: The packed xmm register (OUTPUT). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro READ_SMALL_DATA_INPUT 4 %define %%OUTPUT %1 ; %%OUTPUT is an xmm register %define %%INPUT %2 %define %%LENGTH %3 %define %%TMP1 %4 lea %%TMP1, [rel byte_len_to_mask_table] %ifidn __OUTPUT_FORMAT__, win64 add %%TMP1, %%LENGTH add %%TMP1, %%LENGTH kmovw k1, [%%TMP1] %else kmovw k1, [%%TMP1 + %%LENGTH*2] %endif vmovdqu8 XWORD(%%OUTPUT){k1}{z}, [%%INPUT] %endmacro ; READ_SMALL_DATA_INPUT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CALC_AAD_HASH: Calculates the hash of the data which will not be encrypted. ; Input: The input data (A_IN), that data's length (A_LEN), and the hash key (HASH_KEY). ; Output: The hash of the data (AAD_HASH). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro CALC_AAD_HASH 13 %define %%A_IN %1 %define %%A_LEN %2 %define %%AAD_HASH %3 %define %%GDATA_KEY %4 %define %%XTMP0 %5 ; xmm temp reg 5 %define %%XTMP1 %6 ; xmm temp reg 5 %define %%XTMP2 %7 %define %%XTMP3 %8 %define %%XTMP4 %9 %define %%XTMP5 %10 ; xmm temp reg 5 %define %%T1 %11 ; temp reg 1 %define %%T2 %12 %define %%T3 %13 mov %%T1, %%A_IN ; T1 = AAD mov %%T2, %%A_LEN ; T2 = aadLen vpxor %%AAD_HASH, %%AAD_HASH %%_get_AAD_loop128: cmp %%T2, 128 jl %%_exit_AAD_loop128 vmovdqu %%XTMP0, [%%T1 + 16*0] vpshufb %%XTMP0, [rel SHUF_MASK] vpxor %%XTMP0, %%AAD_HASH vmovdqu %%XTMP5, [%%GDATA_KEY + HashKey_8] vpclmulqdq %%XTMP1, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = a1*b1 vpclmulqdq %%XTMP2, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = a0*b0 vpclmulqdq %%XTMP3, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = a1*b0 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 ; %%T4 = a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 ; %%T3 = a1*b0 + a0*b1 %assign i 1 %assign j 7 %rep 7 vmovdqu %%XTMP0, [%%T1 + 16*i] vpshufb %%XTMP0, [rel SHUF_MASK] vmovdqu %%XTMP5, [%%GDATA_KEY + HashKey_ %+ j] vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = T1 + a1*b1 vpxor %%XTMP1, %%XTMP1, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = T2 + a0*b0 vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = T3 + a1*b0 + a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 vpxor %%XTMP3, %%XTMP3, %%XTMP4 %assign i (i + 1) %assign j (j - 1) %endrep vpslldq %%XTMP4, %%XTMP3, 8 ; shift-L 2 DWs vpsrldq %%XTMP3, %%XTMP3, 8 ; shift-R 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpxor %%XTMP1, %%XTMP1, %%XTMP3 ; accumulate the results in %%T1(M):%%T2(L) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqa %%XTMP5, [rel POLY2] vpclmulqdq %%XTMP0, %%XTMP5, %%XTMP2, 0x01 vpslldq %%XTMP0, %%XTMP0, 8 ; shift-L xmm2 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP0 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%XTMP3, %%XTMP5, %%XTMP2, 0x00 vpsrldq %%XTMP3, %%XTMP3, 4 ; shift-R 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%XTMP4, %%XTMP5, %%XTMP2, 0x10 vpslldq %%XTMP4, %%XTMP4, 4 ; shift-L 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%XTMP4, %%XTMP4, %%XTMP3 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%AAD_HASH, %%XTMP1, %%XTMP4 ; the result is in %%T1 sub %%T2, 128 je %%_CALC_AAD_done add %%T1, 128 jmp %%_get_AAD_loop128 %%_exit_AAD_loop128: cmp %%T2, 16 jl %%_get_small_AAD_block ;; calculate hash_key position to start with mov %%T3, %%T2 and %%T3, -16 ; 1 to 7 blocks possible here neg %%T3 add %%T3, HashKey_1 + 16 lea %%T3, [%%GDATA_KEY + %%T3] vmovdqu %%XTMP0, [%%T1] vpshufb %%XTMP0, [rel SHUF_MASK] vpxor %%XTMP0, %%AAD_HASH vmovdqu %%XTMP5, [%%T3] vpclmulqdq %%XTMP1, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = a1*b1 vpclmulqdq %%XTMP2, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = a0*b0 vpclmulqdq %%XTMP3, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = a1*b0 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 ; %%T4 = a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 ; %%T3 = a1*b0 + a0*b1 add %%T3, 16 ; move to next hashkey add %%T1, 16 ; move to next data block sub %%T2, 16 cmp %%T2, 16 jl %%_AAD_reduce %%_AAD_blocks: vmovdqu %%XTMP0, [%%T1] vpshufb %%XTMP0, [rel SHUF_MASK] vmovdqu %%XTMP5, [%%T3] vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = T1 + a1*b1 vpxor %%XTMP1, %%XTMP1, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = T2 + a0*b0 vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = T3 + a1*b0 + a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 vpxor %%XTMP3, %%XTMP3, %%XTMP4 add %%T3, 16 ; move to next hashkey add %%T1, 16 sub %%T2, 16 cmp %%T2, 16 jl %%_AAD_reduce jmp %%_AAD_blocks %%_AAD_reduce: vpslldq %%XTMP4, %%XTMP3, 8 ; shift-L 2 DWs vpsrldq %%XTMP3, %%XTMP3, 8 ; shift-R 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpxor %%XTMP1, %%XTMP1, %%XTMP3 ; accumulate the results in %%T1(M):%%T2(L) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqa %%XTMP5, [rel POLY2] vpclmulqdq %%XTMP0, %%XTMP5, %%XTMP2, 0x01 vpslldq %%XTMP0, %%XTMP0, 8 ; shift-L xmm2 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP0 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%XTMP3, %%XTMP5, %%XTMP2, 0x00 vpsrldq %%XTMP3, %%XTMP3, 4 ; shift-R 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%XTMP4, %%XTMP5, %%XTMP2, 0x10 vpslldq %%XTMP4, %%XTMP4, 4 ; shift-L 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%XTMP4, %%XTMP4, %%XTMP3 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%AAD_HASH, %%XTMP1, %%XTMP4 ; the result is in %%T1 or %%T2, %%T2 je %%_CALC_AAD_done %%_get_small_AAD_block: vmovdqu %%XTMP0, [%%GDATA_KEY + HashKey] READ_SMALL_DATA_INPUT %%XTMP1, %%T1, %%T2, %%T3 ;byte-reflect the AAD data vpshufb %%XTMP1, [rel SHUF_MASK] vpxor %%AAD_HASH, %%XTMP1 GHASH_MUL %%AAD_HASH, %%XTMP0, %%XTMP1, %%XTMP2, %%XTMP3, %%XTMP4, %%XTMP5 %%_CALC_AAD_done: %endmacro ; CALC_AAD_HASH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PARTIAL_BLOCK: Handles encryption/decryption and the tag partial blocks between update calls. ; Requires the input data be at least 1 byte long. ; Input: gcm_key_data * (GDATA_KEY), gcm_context_data *(GDATA_CTX), input text (PLAIN_CYPH_IN), ; input text length (PLAIN_CYPH_LEN), the current data offset (DATA_OFFSET), ; and whether encoding or decoding (ENC_DEC) ; Output: A cypher of the first partial block (CYPH_PLAIN_OUT), and updated GDATA_CTX ; Clobbers rax, r10, r12, r13, r15, xmm0, xmm1, xmm2, xmm3, xmm5, xmm6, xmm9, xmm10, xmm11, xmm13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro PARTIAL_BLOCK 8 %define %%GDATA_KEY %1 %define %%GDATA_CTX %2 %define %%CYPH_PLAIN_OUT %3 %define %%PLAIN_CYPH_IN %4 %define %%PLAIN_CYPH_LEN %5 %define %%DATA_OFFSET %6 %define %%AAD_HASH %7 %define %%ENC_DEC %8 mov r13, [%%GDATA_CTX + PBlockLen] cmp r13, 0 je %%_partial_block_done ;Leave Macro if no partial blocks cmp %%PLAIN_CYPH_LEN, 16 ;Read in input data without over reading jl %%_fewer_than_16_bytes VXLDR xmm1, [%%PLAIN_CYPH_IN] ;If more than 16 bytes of data, just fill the xmm register jmp %%_data_read %%_fewer_than_16_bytes: lea r10, [%%PLAIN_CYPH_IN] READ_SMALL_DATA_INPUT xmm1, r10, %%PLAIN_CYPH_LEN, rax %%_data_read: ;Finished reading in data vmovdqu xmm9, [%%GDATA_CTX + PBlockEncKey] ;xmm9 = my_ctx_data.partial_block_enc_key vmovdqu xmm13, [%%GDATA_KEY + HashKey] lea r12, [rel SHIFT_MASK] add r12, r13 ; adjust the shuffle mask pointer to be able to shift r13 bytes (16-r13 is the number of bytes in plaintext mod 16) vmovdqu xmm2, [r12] ; get the appropriate shuffle mask vpshufb xmm9, xmm2 ;shift right r13 bytes %ifidn %%ENC_DEC, DEC vmovdqa xmm3, xmm1 %endif vpxor xmm9, xmm1 ; Ciphertext XOR E(K, Yn) mov r15, %%PLAIN_CYPH_LEN add r15, r13 sub r15, 16 ;Set r15 to be the amount of data left in CYPH_PLAIN_IN after filling the block jge %%_no_extra_mask ;Determine if if partial block is not being filled and shift mask accordingly sub r12, r15 %%_no_extra_mask: vmovdqu xmm1, [r12 + ALL_F - SHIFT_MASK]; get the appropriate mask to mask out bottom r13 bytes of xmm9 vpand xmm9, xmm1 ; mask out bottom r13 bytes of xmm9 %ifidn %%ENC_DEC, DEC vpand xmm3, xmm1 vpshufb xmm3, [rel SHUF_MASK] vpshufb xmm3, xmm2 vpxor %%AAD_HASH, xmm3 %else vpshufb xmm9, [rel SHUF_MASK] vpshufb xmm9, xmm2 vpxor %%AAD_HASH, xmm9 %endif cmp r15,0 jl %%_partial_incomplete GHASH_MUL %%AAD_HASH, xmm13, xmm0, xmm10, xmm11, xmm5, xmm6 ;GHASH computation for the last <16 Byte block xor rax,rax mov [%%GDATA_CTX + PBlockLen], rax jmp %%_enc_dec_done %%_partial_incomplete: %ifidn __OUTPUT_FORMAT__, win64 mov rax, %%PLAIN_CYPH_LEN add [%%GDATA_CTX + PBlockLen], rax %else add [%%GDATA_CTX + PBlockLen], %%PLAIN_CYPH_LEN %endif %%_enc_dec_done: vmovdqu [%%GDATA_CTX + AadHash], %%AAD_HASH %ifidn %%ENC_DEC, ENC vpshufb xmm9, [rel SHUF_MASK] ; shuffle xmm9 back to output as ciphertext vpshufb xmm9, xmm2 %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; output encrypted Bytes cmp r15,0 jl %%_partial_fill mov r12, r13 mov r13, 16 sub r13, r12 ; Set r13 to be the number of bytes to write out jmp %%_count_set %%_partial_fill: mov r13, %%PLAIN_CYPH_LEN %%_count_set: lea rax, [rel byte_len_to_mask_table] kmovw k1, [rax + r13*2] vmovdqu8 [%%CYPH_PLAIN_OUT + %%DATA_OFFSET]{k1}, xmm9 add %%DATA_OFFSET, r13 %%_partial_block_done: %endmacro ; PARTIAL_BLOCK %macro GHASH_SINGLE_MUL 9 %define %%GDATA %1 %define %%HASHKEY %2 %define %%CIPHER %3 %define %%STATE_11 %4 %define %%STATE_00 %5 %define %%STATE_MID %6 %define %%T1 %7 %define %%T2 %8 %define %%FIRST %9 vmovdqu %%T1, [%%GDATA + %%HASHKEY] %ifidn %%FIRST, first vpclmulqdq %%STATE_11, %%CIPHER, %%T1, 0x11 ; %%T4 = a1*b1 vpclmulqdq %%STATE_00, %%CIPHER, %%T1, 0x00 ; %%T4_2 = a0*b0 vpclmulqdq %%STATE_MID, %%CIPHER, %%T1, 0x01 ; %%T6 = a1*b0 vpclmulqdq %%T2, %%CIPHER, %%T1, 0x10 ; %%T5 = a0*b1 vpxor %%STATE_MID, %%STATE_MID, %%T2 %else vpclmulqdq %%T2, %%CIPHER, %%T1, 0x11 vpxor %%STATE_11, %%STATE_11, %%T2 vpclmulqdq %%T2, %%CIPHER, %%T1, 0x00 vpxor %%STATE_00, %%STATE_00, %%T2 vpclmulqdq %%T2, %%CIPHER, %%T1, 0x01 vpxor %%STATE_MID, %%STATE_MID, %%T2 vpclmulqdq %%T2, %%CIPHER, %%T1, 0x10 vpxor %%STATE_MID, %%STATE_MID, %%T2 %endif %endmacro ; if a = number of total plaintext bytes ; b = floor(a/16) ; %%num_initial_blocks = b mod 8; ; encrypt the initial %%num_initial_blocks blocks and apply ghash on the ciphertext ; %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r14 are used as a pointer only, not modified. ; Updated AAD_HASH is returned in %%T3 %macro INITIAL_BLOCKS 23 %define %%GDATA_KEY %1 %define %%CYPH_PLAIN_OUT %2 %define %%PLAIN_CYPH_IN %3 %define %%LENGTH %4 %define %%DATA_OFFSET %5 %define %%num_initial_blocks %6 ; can be 0, 1, 2, 3, 4, 5, 6 or 7 %define %%T1 %7 %define %%T2 %8 %define %%T3 %9 %define %%T4 %10 %define %%T5 %11 %define %%CTR %12 %define %%XMM1 %13 %define %%XMM2 %14 %define %%XMM3 %15 %define %%XMM4 %16 %define %%XMM5 %17 %define %%XMM6 %18 %define %%XMM7 %19 %define %%XMM8 %20 %define %%T6 %21 %define %%T_key %22 %define %%ENC_DEC %23 %assign i (8-%%num_initial_blocks) ;; Move AAD_HASH to temp reg vmovdqu %%T2, %%XMM8 ;; Start AES for %%num_initial_blocks blocks ;; vmovdqu %%CTR, [%%GDATA_CTX + CurCount] ; %%CTR = Y0 %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks vpaddd %%CTR, %%CTR, [rel ONE] ; INCR Y0 vmovdqa reg(i), %%CTR vpshufb reg(i), [rel SHUF_MASK] ; perform a 16Byte swap %assign i (i+1) %endrep %if(%%num_initial_blocks>0) vmovdqu %%T_key, [%%GDATA_KEY+16*0] %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks vpxor reg(i),reg(i),%%T_key %assign i (i+1) %endrep %assign j 1 %rep NROUNDS vmovdqu %%T_key, [%%GDATA_KEY+16*j] %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks vaesenc reg(i),%%T_key %assign i (i+1) %endrep %assign j (j+1) %endrep vmovdqu %%T_key, [%%GDATA_KEY+16*j] %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks vaesenclast reg(i),%%T_key %assign i (i+1) %endrep %endif ; %if(%%num_initial_blocks>0) %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET] vpxor reg(i), reg(i), %%T1 ;; Write back ciphertext for %%num_initial_blocks blocks VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET], reg(i) add %%DATA_OFFSET, 16 %ifidn %%ENC_DEC, DEC vmovdqa reg(i), %%T1 %endif ;; Prepare ciphertext for GHASH computations vpshufb reg(i), [rel SHUF_MASK] %assign i (i+1) %endrep ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %assign i (9-%%num_initial_blocks) %if(%%num_initial_blocks>0) vmovdqa %%T3, reg(i) %assign i (i+1) %endif %if %%num_initial_blocks>1 %rep %%num_initial_blocks-1 vmovdqu [rsp + TMP %+ i], reg(i) %assign i (i+1) %endrep %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Prepare 8 counter blocks and perform rounds of AES cipher on ;; them, load plain/cipher text and store cipher/plain text. ;; Stitch GHASH computation in between AES rounds. vpaddd %%XMM1, %%CTR, [rel ONE] ; INCR Y0 vpaddd %%XMM2, %%CTR, [rel TWO] ; INCR Y0 vpaddd %%XMM3, %%XMM1, [rel TWO] ; INCR Y0 vpaddd %%XMM4, %%XMM2, [rel TWO] ; INCR Y0 vpaddd %%XMM5, %%XMM3, [rel TWO] ; INCR Y0 vpaddd %%XMM6, %%XMM4, [rel TWO] ; INCR Y0 vpaddd %%XMM7, %%XMM5, [rel TWO] ; INCR Y0 vpaddd %%XMM8, %%XMM6, [rel TWO] ; INCR Y0 vmovdqa %%CTR, %%XMM8 vpshufb %%XMM1, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM2, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM3, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM4, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM5, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM6, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM7, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM8, [rel SHUF_MASK] ; perform a 16Byte swap vmovdqu %%T_key, [%%GDATA_KEY+16*0] vpxor %%XMM1, %%XMM1, %%T_key vpxor %%XMM2, %%XMM2, %%T_key vpxor %%XMM3, %%XMM3, %%T_key vpxor %%XMM4, %%XMM4, %%T_key vpxor %%XMM5, %%XMM5, %%T_key vpxor %%XMM6, %%XMM6, %%T_key vpxor %%XMM7, %%XMM7, %%T_key vpxor %%XMM8, %%XMM8, %%T_key %assign i (8-%%num_initial_blocks) %assign j (9-%%num_initial_blocks) %assign k (%%num_initial_blocks) %define %%T4_2 %%T4 %if(%%num_initial_blocks>0) ;; Hash in AES state ;; T2 - incoming AAD hash vpxor %%T2, %%T3 ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, first %endif vmovdqu %%T_key, [%%GDATA_KEY+16*1] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*2] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>1) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif vmovdqu %%T_key, [%%GDATA_KEY+16*3] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*4] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>2) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>3) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif vmovdqu %%T_key, [%%GDATA_KEY+16*5] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*6] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>4) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif vmovdqu %%T_key, [%%GDATA_KEY+16*7] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*8] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>5) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif vmovdqu %%T_key, [%%GDATA_KEY+16*9] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %ifndef GCM128_MODE vmovdqu %%T_key, [%%GDATA_KEY+16*10] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %endif %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>6) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif %ifdef GCM128_MODE vmovdqu %%T_key, [%%GDATA_KEY+16*10] vaesenclast %%XMM1, %%T_key vaesenclast %%XMM2, %%T_key vaesenclast %%XMM3, %%T_key vaesenclast %%XMM4, %%T_key vaesenclast %%XMM5, %%T_key vaesenclast %%XMM6, %%T_key vaesenclast %%XMM7, %%T_key vaesenclast %%XMM8, %%T_key %endif %ifdef GCM192_MODE vmovdqu %%T_key, [%%GDATA_KEY+16*11] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*12] vaesenclast %%XMM1, %%T_key vaesenclast %%XMM2, %%T_key vaesenclast %%XMM3, %%T_key vaesenclast %%XMM4, %%T_key vaesenclast %%XMM5, %%T_key vaesenclast %%XMM6, %%T_key vaesenclast %%XMM7, %%T_key vaesenclast %%XMM8, %%T_key %endif %ifdef GCM256_MODE vmovdqu %%T_key, [%%GDATA_KEY+16*11] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*12] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key %endif %assign i (i+1) %assign j (j+1) %assign k (k-1) %if(%%num_initial_blocks>7) ;; GDATA, HASHKEY, CIPHER, ;; STATE_11, STATE_00, STATE_MID, T1, T2 vmovdqu %%T2, [rsp + TMP %+ j] GHASH_SINGLE_MUL %%GDATA_KEY, HashKey_ %+ k, %%T2, \ %%T1, %%T4, %%T6, %%T5, %%T3, not_first %endif %ifdef GCM256_MODE ; GCM256 vmovdqu %%T_key, [%%GDATA_KEY+16*13] vaesenc %%XMM1, %%T_key vaesenc %%XMM2, %%T_key vaesenc %%XMM3, %%T_key vaesenc %%XMM4, %%T_key vaesenc %%XMM5, %%T_key vaesenc %%XMM6, %%T_key vaesenc %%XMM7, %%T_key vaesenc %%XMM8, %%T_key vmovdqu %%T_key, [%%GDATA_KEY+16*14] vaesenclast %%XMM1, %%T_key vaesenclast %%XMM2, %%T_key vaesenclast %%XMM3, %%T_key vaesenclast %%XMM4, %%T_key vaesenclast %%XMM5, %%T_key vaesenclast %%XMM6, %%T_key vaesenclast %%XMM7, %%T_key vaesenclast %%XMM8, %%T_key %endif ; GCM256 mode %if(%%num_initial_blocks>0) vpsrldq %%T3, %%T6, 8 ; shift-R %%T2 2 DWs vpslldq %%T6, %%T6, 8 ; shift-L %%T3 2 DWs vpxor %%T1, %%T1, %%T3 ; accumulate the results in %%T1:%%T4 vpxor %%T4, %%T6, %%T4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; First phase of the reduction vmovdqu %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%T4, 0x01 vpslldq %%T2, %%T2, 8 ; shift-L xmm2 2 DWs ;; First phase of the reduction complete vpxor %%T4, %%T4, %%T2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Second phase of the reduction vpclmulqdq %%T2, %%T3, %%T4, 0x00 ;; Shift-R xmm2 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpsrldq %%T2, %%T2, 4 vpclmulqdq %%T4, %%T3, %%T4, 0x10 ;; Shift-L xmm0 1 DW (Shift-L 1-DW to obtain result with no shifts) vpslldq %%T4, %%T4, 4 ;; Second phase of the reduction complete vpxor %%T4, %%T4, %%T2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The result is in %%T3 vpxor %%T3, %%T1, %%T4 %else ;; The hash should end up in T3 vmovdqa %%T3, %%T2 %endif ;; Final hash is now in T3 %if %%num_initial_blocks > 0 ;; NOTE: obsolete in case %%num_initial_blocks = 0 sub %%LENGTH, 16*%%num_initial_blocks %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*0] vpxor %%XMM1, %%XMM1, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*0], %%XMM1 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM1, %%T1 %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*1] vpxor %%XMM2, %%XMM2, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*1], %%XMM2 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM2, %%T1 %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*2] vpxor %%XMM3, %%XMM3, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*2], %%XMM3 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM3, %%T1 %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*3] vpxor %%XMM4, %%XMM4, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*3], %%XMM4 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM4, %%T1 %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*4] vpxor %%XMM5, %%XMM5, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*4], %%XMM5 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM5, %%T1 %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*5] vpxor %%XMM6, %%XMM6, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*5], %%XMM6 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM6, %%T1 %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*6] vpxor %%XMM7, %%XMM7, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*6], %%XMM7 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM7, %%T1 %endif %if %%num_initial_blocks > 0 ;; NOTE: 'jl' is never taken for %%num_initial_blocks = 0 ;; This macro is executed for length 128 and up, ;; zero length is checked in GCM_ENC_DEC. ;; If the last block is partial then the xor will be done later ;; in ENCRYPT_FINAL_PARTIAL_BLOCK. ;; We know it's partial if LENGTH - 16*num_initial_blocks < 128 cmp %%LENGTH, 128 jl %%_initial_skip_last_word_write %endif VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET + 16*7] vpxor %%XMM8, %%XMM8, %%T1 VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET + 16*7], %%XMM8 %ifidn %%ENC_DEC, DEC vmovdqa %%XMM8, %%T1 %endif ;; Update %%LENGTH with the number of blocks processed sub %%LENGTH, 16 add %%DATA_OFFSET, 16 %%_initial_skip_last_word_write: sub %%LENGTH, 128-16 add %%DATA_OFFSET, 128-16 vpshufb %%XMM1, [rel SHUF_MASK] ; perform a 16Byte swap ;; Combine GHASHed value with the corresponding ciphertext vpxor %%XMM1, %%XMM1, %%T3 vpshufb %%XMM2, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM3, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM4, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM5, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM6, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM7, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM8, [rel SHUF_MASK] ; perform a 16Byte swap ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %%_initial_blocks_done: %endmacro ;;; INITIAL_BLOCKS macro with support for a partial final block. ;;; num_initial_blocks is expected to include the partial final block ;;; in the count. %macro INITIAL_BLOCKS_PARTIAL 25 %define %%GDATA_KEY %1 %define %%GDATA_CTX %2 %define %%CYPH_PLAIN_OUT %3 %define %%PLAIN_CYPH_IN %4 %define %%LENGTH %5 %define %%DATA_OFFSET %6 %define %%num_initial_blocks %7 ; can be 1, 2, 3, 4, 5, 6 or 7 (not 0) %define %%T1 %8 %define %%T2 %9 %define %%T3 %10 ; [out] hash value %define %%T4 %11 %define %%T5 %12 %define %%CTR %13 %define %%XMM1 %14 %define %%XMM2 %15 %define %%XMM3 %16 %define %%XMM4 %17 %define %%XMM5 %18 %define %%XMM6 %19 %define %%XMM7 %20 %define %%XMM8 %21 ; [in] hash value %define %%T6 %22 %define %%T_key %23 %define %%ENC_DEC %24 %define %%INSTANCE_TYPE %25 ;; Move AAD_HASH to temp reg vmovdqu %%T2, %%XMM8 %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks ;; Compute AES counters vpaddd %%CTR, %%CTR, [rel ONE] ; INCR Y0 vmovdqa reg(i), %%CTR vpshufb reg(i), [rel SHUF_MASK] ; perform a 16Byte swap %assign i (i+1) %endrep vmovdqu %%T_key, [%%GDATA_KEY+16*0] %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks ; Start AES for %%num_initial_blocks blocks vpxor reg(i),reg(i),%%T_key %assign i (i+1) %endrep %assign j 1 %rep NROUNDS vmovdqu %%T_key, [%%GDATA_KEY+16*j] %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks vaesenc reg(i),%%T_key %assign i (i+1) %endrep %assign j (j+1) %endrep vmovdqu %%T_key, [%%GDATA_KEY+16*j] %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks vaesenclast reg(i),%%T_key %assign i (i+1) %endrep ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Hash all but the last block of data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %assign i (9-%%num_initial_blocks) %rep %%num_initial_blocks-1 ;; Encrypt the message for all but the last block VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET] vpxor reg(i), reg(i), %%T1 ;; write back ciphertext for %%num_initial_blocks blocks VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET], reg(i) add %%DATA_OFFSET, 16 %ifidn %%ENC_DEC, DEC vmovdqa reg(i), %%T1 %endif ;; Prepare ciphertext for GHASH computations vpshufb reg(i), [rel SHUF_MASK] %assign i (i+1) %endrep %if %%num_initial_blocks > 1 ;; The final block of data may be <16B sub %%LENGTH, 16*(%%num_initial_blocks-1) %endif %if %%num_initial_blocks < 8 ;; NOTE: the 'jl' is always taken for num_initial_blocks = 8. ;; This is run in the context of GCM_ENC_DEC_SMALL for length < 128. cmp %%LENGTH, 16 jl %%_small_initial_partial_block ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Handle a full length final block - encrypt and hash all blocks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sub %%LENGTH, 16 mov [%%GDATA_CTX + PBlockLen], %%LENGTH ;; Encrypt the message VXLDR %%T1, [%%PLAIN_CYPH_IN + %%DATA_OFFSET] vpxor reg(i), reg(i), %%T1 ;; write back ciphertext for %%num_initial_blocks blocks VXSTR [%%CYPH_PLAIN_OUT + %%DATA_OFFSET], reg(i) add %%DATA_OFFSET, 16 %ifidn %%ENC_DEC, DEC vmovdqa reg(i), %%T1 %endif ;; Prepare ciphertext for GHASH computations vpshufb reg(i), [rel SHUF_MASK] ;; Hash all of the data %assign i (8-%%num_initial_blocks) %assign j (9-%%num_initial_blocks) %assign k (%%num_initial_blocks) %assign last_block_to_hash 0 %if(%%num_initial_blocks>last_block_to_hash) ;; Hash in AES state vpxor %%T2, reg(j) ;; T2 - incoming AAD hash ;; reg(i) holds ciphertext ;; T5 - hash key ;; T6 - updated xor ;; reg(1)/xmm1 should now be available for tmp use vmovdqu %%T5, [%%GDATA_KEY + HashKey_ %+ k] vpclmulqdq %%T1, %%T2, %%T5, 0x11 ; %%T4 = a1*b1 vpclmulqdq %%T4, %%T2, %%T5, 0x00 ; %%T4 = a0*b0 vpclmulqdq %%T6, %%T2, %%T5, 0x01 ; %%T6 = a1*b0 vpclmulqdq %%T5, %%T2, %%T5, 0x10 ; %%T5 = a0*b1 vpxor %%T6, %%T6, %%T5 %endif %assign i (i+1) %assign j (j+1) %assign k (k-1) %assign rep_count (%%num_initial_blocks-1) %rep rep_count vmovdqu %%T5, [%%GDATA_KEY + HashKey_ %+ k] vpclmulqdq %%T3, reg(j), %%T5, 0x11 vpxor %%T1, %%T1, %%T3 vpclmulqdq %%T3, reg(j), %%T5, 0x00 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, reg(j), %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, reg(j), %%T5, 0x10 vpxor %%T6, %%T6, %%T3 %assign i (i+1) %assign j (j+1) %assign k (k-1) %endrep ;; Record that a reduction is needed mov r12, 1 jmp %%_small_initial_compute_hash %endif ; %if %%num_initial_blocks < 8 %%_small_initial_partial_block: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Handle ghash for a <16B final block ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; In this case if it's a single call to encrypt we can ;; hash all of the data but if it's an init / update / finalize ;; series of call we need to leave the last block if it's ;; less than a full block of data. mov [%%GDATA_CTX + PBlockLen], %%LENGTH vmovdqu [%%GDATA_CTX + PBlockEncKey], reg(i) ;; Handle a partial final block ;; GDATA, KEY, T1, T2 ;; r13 - length ;; LT16 - indicates type of read and that the buffer is less than 16 bytes long ;; NOTE: could be replaced with %%LENGTH but at this point ;; %%LENGTH is always less than 16. ;; No PLAIN_CYPH_LEN argument available in this macro. ENCRYPT_FINAL_PARTIAL_BLOCK reg(i), %%T1, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, LT16, %%ENC_DEC, %%DATA_OFFSET vpshufb reg(i), [rel SHUF_MASK] %ifidn %%INSTANCE_TYPE, multi_call %assign i (8-%%num_initial_blocks) %assign j (9-%%num_initial_blocks) %assign k (%%num_initial_blocks-1) %assign last_block_to_hash 1 %else %assign i (8-%%num_initial_blocks) %assign j (9-%%num_initial_blocks) %assign k (%%num_initial_blocks) %assign last_block_to_hash 0 %endif %if(%%num_initial_blocks>last_block_to_hash) ;; Record that a reduction is needed mov r12, 1 ;; Hash in AES state vpxor %%T2, reg(j) ;; T2 - incoming AAD hash ;; reg(i) holds ciphertext ;; T5 - hash key ;; T6 - updated xor ;; reg(1)/xmm1 should now be available for tmp use vmovdqu %%T5, [%%GDATA_KEY + HashKey_ %+ k] vpclmulqdq %%T1, %%T2, %%T5, 0x11 ; %%T4 = a1*b1 vpclmulqdq %%T4, %%T2, %%T5, 0x00 ; %%T4 = a0*b0 vpclmulqdq %%T6, %%T2, %%T5, 0x01 ; %%T6 = a1*b0 vpclmulqdq %%T5, %%T2, %%T5, 0x10 ; %%T5 = a0*b1 vpxor %%T6, %%T6, %%T5 %else ;; Record that a reduction is not needed - ;; In this case no hashes are computed because there ;; is only one initial block and it is < 16B in length. xor r12, r12 %endif %assign i (i+1) %assign j (j+1) %assign k (k-1) %ifidn %%INSTANCE_TYPE, multi_call %assign rep_count (%%num_initial_blocks-2) %%_multi_call_hash: %else %assign rep_count (%%num_initial_blocks-1) %endif %if rep_count < 0 ;; fix for negative rep_count %assign rep_count 0 %endif %rep rep_count vmovdqu %%T5, [%%GDATA_KEY + HashKey_ %+ k] vpclmulqdq %%T3, reg(j), %%T5, 0x11 vpxor %%T1, %%T1, %%T3 vpclmulqdq %%T3, reg(j), %%T5, 0x00 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, reg(j), %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, reg(j), %%T5, 0x10 vpxor %%T6, %%T6, %%T3 %assign i (i+1) %assign j (j+1) %assign k (k-1) %endrep %%_small_initial_compute_hash: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Ghash reduction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %if(%%num_initial_blocks=1) %ifidn %%INSTANCE_TYPE, multi_call ;; We only need to check if a reduction is needed if ;; initial_blocks == 1 and init/update/final is being used. ;; In this case we may just have a partial block, and that ;; gets hashed in finalize. ;; cmp r12, 0 or r12, r12 je %%_no_reduction_needed %endif %endif vpsrldq %%T3, %%T6, 8 ; shift-R %%T2 2 DWs vpslldq %%T6, %%T6, 8 ; shift-L %%T3 2 DWs vpxor %%T1, %%T1, %%T3 ; accumulate the results in %%T1:%%T4 vpxor %%T4, %%T6, %%T4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; First phase of the reduction vmovdqu %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%T4, 0x01 ;; shift-L xmm2 2 DWs vpslldq %%T2, %%T2, 8 vpxor %%T4, %%T4, %%T2 ;; First phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Second phase of the reduction vpclmulqdq %%T2, %%T3, %%T4, 0x00 ;; Shift-R xmm2 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpsrldq %%T2, %%T2, 4 vpclmulqdq %%T4, %%T3, %%T4, 0x10 ;; Shift-L xmm0 1 DW (Shift-L 1-DW to obtain result with no shifts) vpslldq %%T4, %%T4, 4 vpxor %%T4, %%T4, %%T2 ;; Second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%T3, %%T1, %%T4 %ifidn %%INSTANCE_TYPE, multi_call ;; If using init/update/finalize, we need to xor any partial block data ;; into the hash. %if %%num_initial_blocks > 1 ;; NOTE: for %%num_initial_blocks = 0 the xor never takes place %if %%num_initial_blocks != 8 ;; NOTE: for %%num_initial_blocks = 8, %%LENGTH, stored in [PBlockLen] is never zero cmp qword [%%GDATA_CTX + PBlockLen], 0 je %%_no_partial_block_xor %endif ; %%num_initial_blocks != 8 vpxor %%T3, %%T3, reg(8) %%_no_partial_block_xor: %endif ; %%num_initial_blocks > 1 %endif ; %%INSTANCE_TYPE, multi_call %if(%%num_initial_blocks=1) %ifidn %%INSTANCE_TYPE, multi_call ;; NOTE: %%_no_reduction_needed case only valid for ;; multi_call with initial_blocks = 1. ;; Look for comment above around '_no_reduction_needed' ;; The jmp below is obsolete as the code will fall through. ;; The result is in %%T3 jmp %%_after_reduction %%_no_reduction_needed: ;; The hash should end up in T3. The only way we should get here is if ;; there is a partial block of data, so xor that into the hash. vpxor %%T3, %%T2, reg(8) %endif ; %%INSTANCE_TYPE = multi_call %endif ; %%num_initial_blocks=1 %%_after_reduction: ;; Final hash is now in T3 %endmacro ; INITIAL_BLOCKS_PARTIAL ; encrypt 8 blocks at a time ; ghash the 8 previously encrypted ciphertext blocks ; %%GDATA (KEY), %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN are used as pointers only, not modified ; %%DATA_OFFSET is the data offset value %macro GHASH_8_ENCRYPT_8_PARALLEL 23 %define %%GDATA %1 %define %%CYPH_PLAIN_OUT %2 %define %%PLAIN_CYPH_IN %3 %define %%DATA_OFFSET %4 %define %%T1 %5 %define %%T2 %6 %define %%T3 %7 %define %%T4 %8 %define %%T5 %9 %define %%T6 %10 %define %%CTR %11 %define %%XMM1 %12 %define %%XMM2 %13 %define %%XMM3 %14 %define %%XMM4 %15 %define %%XMM5 %16 %define %%XMM6 %17 %define %%XMM7 %18 %define %%XMM8 %19 %define %%T7 %20 %define %%loop_idx %21 %define %%ENC_DEC %22 %define %%FULL_PARTIAL %23 vmovdqa %%T2, %%XMM1 vmovdqu [rsp + TMP2], %%XMM2 vmovdqu [rsp + TMP3], %%XMM3 vmovdqu [rsp + TMP4], %%XMM4 vmovdqu [rsp + TMP5], %%XMM5 vmovdqu [rsp + TMP6], %%XMM6 vmovdqu [rsp + TMP7], %%XMM7 vmovdqu [rsp + TMP8], %%XMM8 %ifidn %%loop_idx, in_order vpaddd %%XMM1, %%CTR, [rel ONE] ; INCR CNT vmovdqu %%T5, [rel TWO] vpaddd %%XMM2, %%CTR, %%T5 vpaddd %%XMM3, %%XMM1, %%T5 vpaddd %%XMM4, %%XMM2, %%T5 vpaddd %%XMM5, %%XMM3, %%T5 vpaddd %%XMM6, %%XMM4, %%T5 vpaddd %%XMM7, %%XMM5, %%T5 vpaddd %%XMM8, %%XMM6, %%T5 vmovdqa %%CTR, %%XMM8 vmovdqu %%T5, [rel SHUF_MASK] vpshufb %%XMM1, %%T5 ; perform a 16Byte swap vpshufb %%XMM2, %%T5 ; perform a 16Byte swap vpshufb %%XMM3, %%T5 ; perform a 16Byte swap vpshufb %%XMM4, %%T5 ; perform a 16Byte swap vpshufb %%XMM5, %%T5 ; perform a 16Byte swap vpshufb %%XMM6, %%T5 ; perform a 16Byte swap vpshufb %%XMM7, %%T5 ; perform a 16Byte swap vpshufb %%XMM8, %%T5 ; perform a 16Byte swap %else vpaddd %%XMM1, %%CTR, [rel ONEf] ; INCR CNT vmovdqu %%T5, [rel TWOf] vpaddd %%XMM2, %%CTR, %%T5 vpaddd %%XMM3, %%XMM1, %%T5 vpaddd %%XMM4, %%XMM2, %%T5 vpaddd %%XMM5, %%XMM3, %%T5 vpaddd %%XMM6, %%XMM4, %%T5 vpaddd %%XMM7, %%XMM5, %%T5 vpaddd %%XMM8, %%XMM6, %%T5 vmovdqa %%CTR, %%XMM8 %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T1, [%%GDATA + 16*0] vpxor %%XMM1, %%XMM1, %%T1 vpxor %%XMM2, %%XMM2, %%T1 vpxor %%XMM3, %%XMM3, %%T1 vpxor %%XMM4, %%XMM4, %%T1 vpxor %%XMM5, %%XMM5, %%T1 vpxor %%XMM6, %%XMM6, %%T1 vpxor %%XMM7, %%XMM7, %%T1 vpxor %%XMM8, %%XMM8, %%T1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T1, [%%GDATA + 16*1] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 vmovdqu %%T1, [%%GDATA + 16*2] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_8] vpclmulqdq %%T4, %%T2, %%T5, 0x11 ; %%T4 = a1*b1 vpclmulqdq %%T7, %%T2, %%T5, 0x00 ; %%T7 = a0*b0 vpclmulqdq %%T6, %%T2, %%T5, 0x01 ; %%T6 = a1*b0 vpclmulqdq %%T5, %%T2, %%T5, 0x10 ; %%T5 = a0*b1 vpxor %%T6, %%T6, %%T5 vmovdqu %%T1, [%%GDATA + 16*3] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 vmovdqu %%T1, [rsp + TMP2] vmovdqu %%T5, [%%GDATA + HashKey_7] vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 vmovdqu %%T1, [%%GDATA + 16*4] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T1, [rsp + TMP3] vmovdqu %%T5, [%%GDATA + HashKey_6] vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 vmovdqu %%T1, [%%GDATA + 16*5] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 vmovdqu %%T1, [rsp + TMP4] vmovdqu %%T5, [%%GDATA + HashKey_5] vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 vmovdqu %%T1, [%%GDATA + 16*6] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 vmovdqu %%T1, [rsp + TMP5] vmovdqu %%T5, [%%GDATA + HashKey_4] vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 vmovdqu %%T1, [%%GDATA + 16*7] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 vmovdqu %%T1, [rsp + TMP6] vmovdqu %%T5, [%%GDATA + HashKey_3] vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 vmovdqu %%T1, [%%GDATA + 16*8] vaesenc %%XMM1, %%T1 vaesenc %%XMM2, %%T1 vaesenc %%XMM3, %%T1 vaesenc %%XMM4, %%T1 vaesenc %%XMM5, %%T1 vaesenc %%XMM6, %%T1 vaesenc %%XMM7, %%T1 vaesenc %%XMM8, %%T1 vmovdqu %%T1, [rsp + TMP7] vmovdqu %%T5, [%%GDATA + HashKey_2] vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T4, %%T4, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + 16*9] vaesenc %%XMM1, %%T5 vaesenc %%XMM2, %%T5 vaesenc %%XMM3, %%T5 vaesenc %%XMM4, %%T5 vaesenc %%XMM5, %%T5 vaesenc %%XMM6, %%T5 vaesenc %%XMM7, %%T5 vaesenc %%XMM8, %%T5 vmovdqu %%T1, [rsp + TMP8] vmovdqu %%T5, [%%GDATA + HashKey] vpclmulqdq %%T3, %%T1, %%T5, 0x00 vpxor %%T7, %%T7, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x01 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x10 vpxor %%T6, %%T6, %%T3 vpclmulqdq %%T3, %%T1, %%T5, 0x11 vpxor %%T1, %%T4, %%T3 vmovdqu %%T5, [%%GDATA + 16*10] %ifndef GCM128_MODE ; GCM192 or GCM256 vaesenc %%XMM1, %%T5 vaesenc %%XMM2, %%T5 vaesenc %%XMM3, %%T5 vaesenc %%XMM4, %%T5 vaesenc %%XMM5, %%T5 vaesenc %%XMM6, %%T5 vaesenc %%XMM7, %%T5 vaesenc %%XMM8, %%T5 vmovdqu %%T5, [%%GDATA + 16*11] vaesenc %%XMM1, %%T5 vaesenc %%XMM2, %%T5 vaesenc %%XMM3, %%T5 vaesenc %%XMM4, %%T5 vaesenc %%XMM5, %%T5 vaesenc %%XMM6, %%T5 vaesenc %%XMM7, %%T5 vaesenc %%XMM8, %%T5 vmovdqu %%T5, [%%GDATA + 16*12] %endif %ifdef GCM256_MODE vaesenc %%XMM1, %%T5 vaesenc %%XMM2, %%T5 vaesenc %%XMM3, %%T5 vaesenc %%XMM4, %%T5 vaesenc %%XMM5, %%T5 vaesenc %%XMM6, %%T5 vaesenc %%XMM7, %%T5 vaesenc %%XMM8, %%T5 vmovdqu %%T5, [%%GDATA + 16*13] vaesenc %%XMM1, %%T5 vaesenc %%XMM2, %%T5 vaesenc %%XMM3, %%T5 vaesenc %%XMM4, %%T5 vaesenc %%XMM5, %%T5 vaesenc %%XMM6, %%T5 vaesenc %%XMM7, %%T5 vaesenc %%XMM8, %%T5 vmovdqu %%T5, [%%GDATA + 16*14] %endif ; GCM256 %assign i 0 %assign j 1 %rep 8 ;; SNP TBD: This is pretty ugly - consider whether just XORing the ;; data in after vaesenclast is simpler and performant. Would ;; also have to ripple it through partial block and ghash_mul_8. %ifidn %%FULL_PARTIAL, full %ifdef NT_LD VXLDR %%T2, [%%PLAIN_CYPH_IN+%%DATA_OFFSET+16*i] vpxor %%T2, %%T2, %%T5 %else vpxor %%T2, %%T5, [%%PLAIN_CYPH_IN+%%DATA_OFFSET+16*i] %endif %ifidn %%ENC_DEC, ENC vaesenclast reg(j), reg(j), %%T2 %else vaesenclast %%T3, reg(j), %%T2 vpxor reg(j), %%T2, %%T5 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*i], %%T3 %endif %else ; Don't read the final data during partial block processing %ifdef NT_LD %if (i<7) VXLDR %%T2, [%%PLAIN_CYPH_IN+%%DATA_OFFSET+16*i] vpxor %%T2, %%T2, %%T5 %else ;; Stage the key directly in T2 rather than hash it with plaintext vmovdqu %%T2, %%T5 %endif %else %if (i<7) vpxor %%T2, %%T5, [%%PLAIN_CYPH_IN+%%DATA_OFFSET+16*i] %else ;; Stage the key directly in T2 rather than hash it with plaintext vmovdqu %%T2, %%T5 %endif %endif %ifidn %%ENC_DEC, ENC vaesenclast reg(j), reg(j), %%T2 %else %if (i<7) vaesenclast %%T3, reg(j), %%T2 vpxor reg(j), %%T2, %%T5 ;; Do not read the data since it could fault VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*i], %%T3 %else vaesenclast reg(j), reg(j), %%T2 %endif %endif %endif %assign i (i+1) %assign j (j+1) %endrep ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpslldq %%T3, %%T6, 8 ; shift-L %%T3 2 DWs vpsrldq %%T6, %%T6, 8 ; shift-R %%T2 2 DWs vpxor %%T7, %%T7, %%T3 vpxor %%T1, %%T1, %%T6 ; accumulate the results in %%T1:%%T7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqu %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%T7, 0x01 vpslldq %%T2, %%T2, 8 ; shift-L xmm2 2 DWs vpxor %%T7, %%T7, %%T2 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %ifidn %%ENC_DEC, ENC ; Write to the Ciphertext buffer VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*0], %%XMM1 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*1], %%XMM2 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*2], %%XMM3 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*3], %%XMM4 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*4], %%XMM5 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*5], %%XMM6 VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*6], %%XMM7 %ifidn %%FULL_PARTIAL, full ;; Avoid writing past the buffer if handling a partial block VXSTR [%%CYPH_PLAIN_OUT+%%DATA_OFFSET+16*7], %%XMM8 %endif %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%T2, %%T3, %%T7, 0x00 vpsrldq %%T2, %%T2, 4 ; shift-R xmm2 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%T4, %%T3, %%T7, 0x10 vpslldq %%T4, %%T4, 4 ; shift-L xmm0 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%T4, %%T4, %%T2 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%T1, %%T1, %%T4 ; the result is in %%T1 vpshufb %%XMM1, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM2, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM3, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM4, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM5, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM6, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM7, [rel SHUF_MASK] ; perform a 16Byte swap vpshufb %%XMM8, [rel SHUF_MASK] ; perform a 16Byte swap vpxor %%XMM1, %%T1 %endmacro ; GHASH_8_ENCRYPT_8_PARALLEL ; GHASH the last 4 ciphertext blocks. %macro GHASH_LAST_8 16 %define %%GDATA %1 %define %%T1 %2 %define %%T2 %3 %define %%T3 %4 %define %%T4 %5 %define %%T5 %6 %define %%T6 %7 %define %%T7 %8 %define %%XMM1 %9 %define %%XMM2 %10 %define %%XMM3 %11 %define %%XMM4 %12 %define %%XMM5 %13 %define %%XMM6 %14 %define %%XMM7 %15 %define %%XMM8 %16 ;; Karatsuba Method vmovdqu %%T5, [%%GDATA + HashKey_8] vpshufd %%T2, %%XMM1, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM1 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T6, %%XMM1, %%T5, 0x11 vpclmulqdq %%T7, %%XMM1, %%T5, 0x00 vpclmulqdq %%XMM1, %%T2, %%T3, 0x00 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_7] vpshufd %%T2, %%XMM2, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM2 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM2, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM2, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_6] vpshufd %%T2, %%XMM3, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM3 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM3, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM3, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_5] vpshufd %%T2, %%XMM4, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM4 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM4, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM4, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_4] vpshufd %%T2, %%XMM5, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM5 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM5, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM5, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_3] vpshufd %%T2, %%XMM6, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM6 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM6, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM6, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_2] vpshufd %%T2, %%XMM7, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM7 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM7, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM7, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey] vpshufd %%T2, %%XMM8, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM8 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM8, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM8, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 vpxor %%XMM1, %%XMM1, %%T6 vpxor %%T2, %%XMM1, %%T7 vpslldq %%T4, %%T2, 8 vpsrldq %%T2, %%T2, 8 vpxor %%T7, %%T7, %%T4 vpxor %%T6, %%T6, %%T2 ; <%%T6:%%T7> holds the result of the accumulated carry-less multiplications ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqu %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%T7, 0x01 vpslldq %%T2, %%T2, 8 ; shift-L xmm2 2 DWs vpxor %%T7, %%T7, %%T2 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%T2, %%T3, %%T7, 0x00 vpsrldq %%T2, %%T2, 4 ; shift-R %%T2 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%T4, %%T3, %%T7, 0x10 vpslldq %%T4, %%T4, 4 ; shift-L %%T4 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%T4, %%T4, %%T2 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%T6, %%T6, %%T4 ; the result is in %%T6 %endmacro ; GHASH the last 4 ciphertext blocks. %macro GHASH_LAST_7 15 %define %%GDATA %1 %define %%T1 %2 %define %%T2 %3 %define %%T3 %4 %define %%T4 %5 %define %%T5 %6 %define %%T6 %7 %define %%T7 %8 %define %%XMM1 %9 %define %%XMM2 %10 %define %%XMM3 %11 %define %%XMM4 %12 %define %%XMM5 %13 %define %%XMM6 %14 %define %%XMM7 %15 ;; Karatsuba Method vmovdqu %%T5, [%%GDATA + HashKey_7] vpshufd %%T2, %%XMM1, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM1 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T6, %%XMM1, %%T5, 0x11 vpclmulqdq %%T7, %%XMM1, %%T5, 0x00 vpclmulqdq %%XMM1, %%T2, %%T3, 0x00 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_6] vpshufd %%T2, %%XMM2, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM2 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM2, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM2, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_5] vpshufd %%T2, %%XMM3, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM3 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM3, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM3, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_4] vpshufd %%T2, %%XMM4, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM4 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM4, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM4, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_3] vpshufd %%T2, %%XMM5, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM5 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM5, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM5, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_2] vpshufd %%T2, %%XMM6, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM6 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM6, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM6, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vmovdqu %%T5, [%%GDATA + HashKey_1] vpshufd %%T2, %%XMM7, 01001110b vpshufd %%T3, %%T5, 01001110b vpxor %%T2, %%T2, %%XMM7 vpxor %%T3, %%T3, %%T5 vpclmulqdq %%T4, %%XMM7, %%T5, 0x11 vpxor %%T6, %%T6, %%T4 vpclmulqdq %%T4, %%XMM7, %%T5, 0x00 vpxor %%T7, %%T7, %%T4 vpclmulqdq %%T2, %%T2, %%T3, 0x00 vpxor %%XMM1, %%XMM1, %%T2 ;;;;;;;;;;;;;;;;;;;;;; vpxor %%XMM1, %%XMM1, %%T6 vpxor %%T2, %%XMM1, %%T7 vpslldq %%T4, %%T2, 8 vpsrldq %%T2, %%T2, 8 vpxor %%T7, %%T7, %%T4 vpxor %%T6, %%T6, %%T2 ; <%%T6:%%T7> holds the result of the accumulated carry-less multiplications ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqu %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%T7, 0x01 vpslldq %%T2, %%T2, 8 ; shift-L xmm2 2 DWs vpxor %%T7, %%T7, %%T2 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%T2, %%T3, %%T7, 0x00 vpsrldq %%T2, %%T2, 4 ; shift-R %%T2 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%T4, %%T3, %%T7, 0x10 vpslldq %%T4, %%T4, 4 ; shift-L %%T4 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%T4, %%T4, %%T2 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%T6, %%T6, %%T4 ; the result is in %%T6 %endmacro ;;; Handle encryption of the final partial block ;;; IN: ;;; r13 - Number of bytes to read ;;; MODIFIES: ;;; KEY - Key for encrypting the partial block ;;; SMASHES: ;;; rax, T1 ;;; Note: ;;; PLAIN_CYPH_LEN is unused at this stage. Previously: ;;; it was used to determine if buffer is big enough to do ;;; a 16 byte read & shift. ;;; 'LT16' is passed here only if buffer is known to be smaller ;;; than 16 bytes. ;;; Any other value passed here will result in 16 byte read ;;; code path. %macro ENCRYPT_FINAL_PARTIAL_BLOCK 7 %define %%KEY %1 %define %%T1 %2 %define %%CYPH_PLAIN_OUT %3 %define %%PLAIN_CYPH_IN %4 %define %%PLAIN_CYPH_LEN %5 %define %%ENC_DEC %6 %define %%DATA_OFFSET %7 ;; %%PLAIN_CYPH_IN + %%DATA_OFFSET ;; - input data address ;; r13 - input data length ;; rax - temp registers ;; out: ;; T1 - packed output ;; k1 - valid byte mask READ_SMALL_DATA_INPUT %%T1, %%PLAIN_CYPH_IN+%%DATA_OFFSET, r13, rax ;; At this point T1 contains the partial block data ;; Plaintext XOR E(K, Yn) vpxorq %%KEY, %%KEY, %%T1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Output r13 Bytes vmovdqu8 [%%CYPH_PLAIN_OUT + %%DATA_OFFSET]{k1}, %%KEY %ifidn %%ENC_DEC, DEC ;; If decrypt, restore the ciphertext into %%KEY vmovdqa64 %%KEY, %%T1 %else vmovdqu8 %%KEY{k1}{z}, %%KEY %endif %endmacro ; ENCRYPT_FINAL_PARTIAL_BLOCK ; Encryption of a single block %macro ENCRYPT_SINGLE_BLOCK 2 %define %%GDATA %1 %define %%XMM0 %2 vpxor %%XMM0, %%XMM0, [%%GDATA+16*0] %assign i 1 %rep NROUNDS vaesenc %%XMM0, [%%GDATA+16*i] %assign i (i+1) %endrep vaesenclast %%XMM0, [%%GDATA+16*i] %endmacro ;; Start of Stack Setup %macro FUNC_SAVE 0 ;; Required for Update/GMC_ENC ;the number of pushes must equal STACK_OFFSET push r12 push r13 push r14 push r15 mov r14, rsp sub rsp, VARIABLE_OFFSET and rsp, ~63 %ifidn __OUTPUT_FORMAT__, win64 ; xmm6:xmm15 need to be maintained for Windows vmovdqu [rsp + LOCAL_STORAGE + 0*16],xmm6 vmovdqu [rsp + LOCAL_STORAGE + 1*16],xmm7 vmovdqu [rsp + LOCAL_STORAGE + 2*16],xmm8 vmovdqu [rsp + LOCAL_STORAGE + 3*16],xmm9 vmovdqu [rsp + LOCAL_STORAGE + 4*16],xmm10 vmovdqu [rsp + LOCAL_STORAGE + 5*16],xmm11 vmovdqu [rsp + LOCAL_STORAGE + 6*16],xmm12 vmovdqu [rsp + LOCAL_STORAGE + 7*16],xmm13 vmovdqu [rsp + LOCAL_STORAGE + 8*16],xmm14 vmovdqu [rsp + LOCAL_STORAGE + 9*16],xmm15 %endif %endmacro %macro FUNC_RESTORE 0 %ifdef SAFE_DATA clear_scratch_gps_asm clear_scratch_zmms_asm %endif %ifidn __OUTPUT_FORMAT__, win64 vmovdqu xmm15, [rsp + LOCAL_STORAGE + 9*16] vmovdqu xmm14, [rsp + LOCAL_STORAGE + 8*16] vmovdqu xmm13, [rsp + LOCAL_STORAGE + 7*16] vmovdqu xmm12, [rsp + LOCAL_STORAGE + 6*16] vmovdqu xmm11, [rsp + LOCAL_STORAGE + 5*16] vmovdqu xmm10, [rsp + LOCAL_STORAGE + 4*16] vmovdqu xmm9, [rsp + LOCAL_STORAGE + 3*16] vmovdqu xmm8, [rsp + LOCAL_STORAGE + 2*16] vmovdqu xmm7, [rsp + LOCAL_STORAGE + 1*16] vmovdqu xmm6, [rsp + LOCAL_STORAGE + 0*16] %endif ;; Required for Update/GMC_ENC mov rsp, r14 pop r15 pop r14 pop r13 pop r12 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; UPDATE_HASH: Calculates the hash of the data which will not be encrypted. ; Input: The input data (A_IN), that data's length (A_LEN), and the hash key (HASH_KEY). ; Output: The hash of the data (AAD_HASH). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro UPDATE_HASH 13 %define %%A_IN %1 %define %%A_LEN %2 %define %%AAD_HASH %3 %define %%GDATA_KEY %4 %define %%XTMP0 %5 ; xmm temp reg 5 %define %%XTMP1 %6 ; xmm temp reg 5 %define %%XTMP2 %7 %define %%XTMP3 %8 %define %%XTMP4 %9 %define %%XTMP5 %10 ; xmm temp reg 5 %define %%T1 %11 ; temp reg 1 %define %%T2 %12 %define %%T3 %13 mov %%T1, %%A_IN ; T1 = AAD mov %%T2, %%A_LEN ; T2 = aadLen or %%T2, %%T2 jz %%_CALC_AAD_done %%_get_AAD_loop128: cmp %%T2, 128 jl %%_exit_AAD_loop128 vmovdqu %%XTMP0, [%%T1 + 16*0] vpshufb %%XTMP0, [rel SHUF_MASK] vpxor %%XTMP0, %%AAD_HASH vmovdqu %%XTMP5, [%%GDATA_KEY + HashKey_8] vpclmulqdq %%XTMP1, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = a1*b1 vpclmulqdq %%XTMP2, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = a0*b0 vpclmulqdq %%XTMP3, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = a1*b0 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 ; %%T4 = a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 ; %%T3 = a1*b0 + a0*b1 %assign i 1 %assign j 7 %rep 7 vmovdqu %%XTMP0, [%%T1 + 16*i] vpshufb %%XTMP0, [rel SHUF_MASK] vmovdqu %%XTMP5, [%%GDATA_KEY + HashKey_ %+ j] vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = T1 + a1*b1 vpxor %%XTMP1, %%XTMP1, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = T2 + a0*b0 vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = T3 + a1*b0 + a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 vpxor %%XTMP3, %%XTMP3, %%XTMP4 %assign i (i + 1) %assign j (j - 1) %endrep vpslldq %%XTMP4, %%XTMP3, 8 ; shift-L 2 DWs vpsrldq %%XTMP3, %%XTMP3, 8 ; shift-R 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpxor %%XTMP1, %%XTMP1, %%XTMP3 ; accumulate the results in %%T1(M):%%T2(L) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqa %%XTMP5, [rel POLY2] vpclmulqdq %%XTMP0, %%XTMP5, %%XTMP2, 0x01 vpslldq %%XTMP0, %%XTMP0, 8 ; shift-L xmm2 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP0 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%XTMP3, %%XTMP5, %%XTMP2, 0x00 vpsrldq %%XTMP3, %%XTMP3, 4 ; shift-R 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%XTMP4, %%XTMP5, %%XTMP2, 0x10 vpslldq %%XTMP4, %%XTMP4, 4 ; shift-L 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%XTMP4, %%XTMP4, %%XTMP3 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%AAD_HASH, %%XTMP1, %%XTMP4 ; the result is in %%T1 sub %%T2, 128 je %%_CALC_AAD_done add %%T1, 128 jmp %%_get_AAD_loop128 %%_exit_AAD_loop128: cmp %%T2, 16 jl %%_get_small_AAD_block ;; calculate hash_key position to start with mov %%T3, %%T2 and %%T3, -16 ; 1 to 7 blocks possible here neg %%T3 add %%T3, HashKey_1 + 16 lea %%T3, [%%GDATA_KEY + %%T3] vmovdqu %%XTMP0, [%%T1] vpshufb %%XTMP0, [rel SHUF_MASK] vpxor %%XTMP0, %%AAD_HASH vmovdqu %%XTMP5, [%%T3] vpclmulqdq %%XTMP1, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = a1*b1 vpclmulqdq %%XTMP2, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = a0*b0 vpclmulqdq %%XTMP3, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = a1*b0 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 ; %%T4 = a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 ; %%T3 = a1*b0 + a0*b1 add %%T3, 16 ; move to next hashkey add %%T1, 16 ; move to next data block sub %%T2, 16 cmp %%T2, 16 jl %%_AAD_reduce %%_AAD_blocks: vmovdqu %%XTMP0, [%%T1] vpshufb %%XTMP0, [rel SHUF_MASK] vmovdqu %%XTMP5, [%%T3] vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x11 ; %%T1 = T1 + a1*b1 vpxor %%XTMP1, %%XTMP1, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x00 ; %%T2 = T2 + a0*b0 vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x01 ; %%T3 = T3 + a1*b0 + a0*b1 vpxor %%XTMP3, %%XTMP3, %%XTMP4 vpclmulqdq %%XTMP4, %%XTMP0, %%XTMP5, 0x10 vpxor %%XTMP3, %%XTMP3, %%XTMP4 add %%T3, 16 ; move to next hashkey add %%T1, 16 sub %%T2, 16 cmp %%T2, 16 jl %%_AAD_reduce jmp %%_AAD_blocks %%_AAD_reduce: vpslldq %%XTMP4, %%XTMP3, 8 ; shift-L 2 DWs vpsrldq %%XTMP3, %%XTMP3, 8 ; shift-R 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP4 vpxor %%XTMP1, %%XTMP1, %%XTMP3 ; accumulate the results in %%T1(M):%%T2(L) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqa %%XTMP5, [rel POLY2] vpclmulqdq %%XTMP0, %%XTMP5, %%XTMP2, 0x01 vpslldq %%XTMP0, %%XTMP0, 8 ; shift-L xmm2 2 DWs vpxor %%XTMP2, %%XTMP2, %%XTMP0 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%XTMP3, %%XTMP5, %%XTMP2, 0x00 vpsrldq %%XTMP3, %%XTMP3, 4 ; shift-R 1 DW (Shift-R only 1-DW to obtain 2-DWs shift-R) vpclmulqdq %%XTMP4, %%XTMP5, %%XTMP2, 0x10 vpslldq %%XTMP4, %%XTMP4, 4 ; shift-L 1 DW (Shift-L 1-DW to obtain result with no shifts) vpxor %%XTMP4, %%XTMP4, %%XTMP3 ; second phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpxor %%AAD_HASH, %%XTMP1, %%XTMP4 ; the result is in %%T1 or %%T2, %%T2 je %%_CALC_AAD_done %%_get_small_AAD_block: vmovdqu %%XTMP0, [%%GDATA_KEY + HashKey] READ_SMALL_DATA_INPUT %%XTMP1, %%T1, %%T2, %%T3 ;byte-reflect the AAD data vpshufb %%XTMP1, [rel SHUF_MASK] vpxor %%AAD_HASH, %%XTMP1 GHASH_MUL %%AAD_HASH, %%XTMP0, %%XTMP1, %%XTMP2, %%XTMP3, %%XTMP4, %%XTMP5 %%_CALC_AAD_done: %endmacro ; UPDATE_HASH %macro CALC_J0 14 %define %%KEY %1 ;; [in] Pointer to GCM KEY structure %define %%IV %2 ;; [in] Pointer to IV %define %%IV_LEN %3 ;; [in] IV length %define %%J0 %4 ;; [out] XMM reg to contain J0 %define %%TMP0 %5 ;; [clobbered] Temporary GP reg %define %%TMP1 %6 ;; [clobbered] Temporary GP reg %define %%TMP2 %7 ;; [clobbered] Temporary GP reg %define %%XTMP0 %8 ;; [clobbered] Temporary XMM reg %define %%XTMP1 %9 ;; [clobbered] Temporary XMM reg %define %%XTMP2 %10 ;; [clobbered] Temporary XMM reg %define %%XTMP3 %11 ;; [clobbered] Temporary XMM reg %define %%XTMP4 %12 ;; [clobbered] Temporary XMM reg %define %%XTMP5 %13 ;; [clobbered] Temporary XMM reg %define %%IV_GEN_LEN %14 ;; [in] IV general length ;; J0 = GHASH(IV || 0s+64 || len(IV)64) ;; s = 16 * RoundUp(len(IV)/16) - len(IV) */ ;; Calculate GHASH of (IV || 0s) UPDATE_HASH %%IV, %%IV_LEN, %%J0, %%KEY, %%XTMP0, %%XTMP1, %%XTMP2, \ %%XTMP3, %%XTMP4, %%XTMP5, %%TMP0, %%TMP1, %%TMP2 ;; Calculate GHASH of last 16-byte block (0 || len(IV)64) vmovdqu %%XTMP0, [%%KEY + HashKey] mov %%TMP2, %%IV_GEN_LEN shl %%TMP2, 3 ;; IV length in bits vmovq %%XTMP1, %%TMP2 vpxor %%J0, %%XTMP1 GHASH_MUL %%J0, %%XTMP0, %%XTMP1, %%XTMP2, %%XTMP3, %%XTMP4, %%XTMP5 vpshufb %%J0, [rel SHUF_MASK] ; perform a 16Byte swap %endmacro %macro GCM_ENC_DEC_SMALL 12 %define %%GDATA_KEY %1 %define %%GDATA_CTX %2 %define %%CYPH_PLAIN_OUT %3 %define %%PLAIN_CYPH_IN %4 %define %%PLAIN_CYPH_LEN %5 %define %%ENC_DEC %6 %define %%DATA_OFFSET %7 %define %%LENGTH %8 ; assumed r13 %define %%NUM_BLOCKS %9 %define %%CTR %10 ; assumed xmm9 %define %%HASH_OUT %11 ; assumed xmm14 %define %%INSTANCE_TYPE %12 ;; NOTE: the check below is obsolete in current implementation. The check is already done in GCM_ENC_DEC. ;; cmp %%NUM_BLOCKS, 0 ;; je %%_small_initial_blocks_encrypted cmp %%NUM_BLOCKS, 8 je %%_small_initial_num_blocks_is_8 cmp %%NUM_BLOCKS, 7 je %%_small_initial_num_blocks_is_7 cmp %%NUM_BLOCKS, 6 je %%_small_initial_num_blocks_is_6 cmp %%NUM_BLOCKS, 5 je %%_small_initial_num_blocks_is_5 cmp %%NUM_BLOCKS, 4 je %%_small_initial_num_blocks_is_4 cmp %%NUM_BLOCKS, 3 je %%_small_initial_num_blocks_is_3 cmp %%NUM_BLOCKS, 2 je %%_small_initial_num_blocks_is_2 jmp %%_small_initial_num_blocks_is_1 %%_small_initial_num_blocks_is_8: ;; r13 - %%LENGTH ;; xmm12 - T1 ;; xmm13 - T2 ;; xmm14 - T3 - AAD HASH OUT when not producing 8 AES keys ;; xmm15 - T4 ;; xmm11 - T5 ;; xmm9 - CTR ;; xmm1 - XMM1 - Cipher + Hash when producing 8 AES keys ;; xmm2 - XMM2 ;; xmm3 - XMM3 ;; xmm4 - XMM4 ;; xmm5 - XMM5 ;; xmm6 - XMM6 ;; xmm7 - XMM7 ;; xmm8 - XMM8 - AAD HASH IN ;; xmm10 - T6 ;; xmm0 - T_key INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 8, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_7: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 7, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_6: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 6, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_5: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 5, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_4: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 4, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_3: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 3, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_2: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 2, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE jmp %%_small_initial_blocks_encrypted %%_small_initial_num_blocks_is_1: INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, \ %%PLAIN_CYPH_IN, %%LENGTH, %%DATA_OFFSET, 1, \ xmm12, xmm13, %%HASH_OUT, xmm15, xmm11, %%CTR, \ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, \ xmm10, xmm0, %%ENC_DEC, %%INSTANCE_TYPE %%_small_initial_blocks_encrypted: %endmacro ; GCM_ENC_DEC_SMALL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GCM_ENC_DEC Encodes/Decodes given data. Assumes that the passed gcm_context_data struct ; has been initialized by GCM_INIT ; Requires the input data be at least 1 byte long because of READ_SMALL_INPUT_DATA. ; Input: gcm_key_data struct* (GDATA_KEY), gcm_context_data *(GDATA_CTX), input text (PLAIN_CYPH_IN), ; input text length (PLAIN_CYPH_LEN) and whether encoding or decoding (ENC_DEC). ; Output: A cypher of the given plain text (CYPH_PLAIN_OUT), and updated GDATA_CTX ; Clobbers rax, r10-r15, and xmm0-xmm15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_ENC_DEC 7 %define %%GDATA_KEY %1 %define %%GDATA_CTX %2 %define %%CYPH_PLAIN_OUT %3 %define %%PLAIN_CYPH_IN %4 %define %%PLAIN_CYPH_LEN %5 %define %%ENC_DEC %6 %define %%INSTANCE_TYPE %7 %define %%DATA_OFFSET r11 ; Macro flow: ; calculate the number of 16byte blocks in the message ; process (number of 16byte blocks) mod 8 '%%_initial_num_blocks_is_# .. %%_initial_blocks_encrypted' ; process 8 16 byte blocks at a time until all are done '%%_encrypt_by_8_new .. %%_eight_cipher_left' ; if there is a block of less than 16 bytes process it '%%_zero_cipher_left .. %%_multiple_of_16_bytes' %ifidn __OUTPUT_FORMAT__, win64 cmp %%PLAIN_CYPH_LEN, 0 %else or %%PLAIN_CYPH_LEN, %%PLAIN_CYPH_LEN %endif je %%_enc_dec_done xor %%DATA_OFFSET, %%DATA_OFFSET ;; Update length of data processed %ifidn __OUTPUT_FORMAT__, win64 mov rax, %%PLAIN_CYPH_LEN add [%%GDATA_CTX + InLen], rax %else add [%%GDATA_CTX + InLen], %%PLAIN_CYPH_LEN %endif vmovdqu xmm13, [%%GDATA_KEY + HashKey] vmovdqu xmm8, [%%GDATA_CTX + AadHash] %ifidn %%INSTANCE_TYPE, multi_call ;; NOTE: partial block processing makes only sense for multi_call here. ;; Used for the update flow - if there was a previous partial ;; block fill the remaining bytes here. PARTIAL_BLOCK %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, %%PLAIN_CYPH_LEN, %%DATA_OFFSET, xmm8, %%ENC_DEC %endif ;; lift CTR set from initial_blocks to here %ifidn %%INSTANCE_TYPE, single_call vmovdqu xmm9, xmm2 %else vmovdqu xmm9, [%%GDATA_CTX + CurCount] %endif ;; Save the amount of data left to process in r10 mov r13, %%PLAIN_CYPH_LEN %ifidn %%INSTANCE_TYPE, multi_call ;; NOTE: %%DATA_OFFSET is zero in single_call case. ;; Consequently PLAIN_CYPH_LEN will never be zero after ;; %%DATA_OFFSET subtraction below. sub r13, %%DATA_OFFSET ;; There may be no more data if it was consumed in the partial block. cmp r13, 0 je %%_enc_dec_done %endif ; %%INSTANCE_TYPE, multi_call mov r10, r13 ;; Determine how many blocks to process in INITIAL mov r12, r13 shr r12, 4 and r12, 7 ;; Process one additional block in INITIAL if there is a partial block and r10, 0xf blsmsk r10, r10 ; Set CF if zero cmc ; Flip CF adc r12, 0x0 ; Process an additional INITIAL block if CF set ;; Less than 127B will be handled by the small message code, which ;; can process up to 7 16B blocks. cmp r13, 128 jge %%_large_message_path GCM_ENC_DEC_SMALL %%GDATA_KEY, %%GDATA_CTX, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, %%PLAIN_CYPH_LEN, %%ENC_DEC, %%DATA_OFFSET, r13, r12, xmm9, xmm14, %%INSTANCE_TYPE jmp %%_ghash_done %%_large_message_path: and r12, 0x7 ; Still, don't allow 8 INITIAL blocks since this will ; can be handled by the x8 partial loop. cmp r12, 0 je %%_initial_num_blocks_is_0 cmp r12, 7 je %%_initial_num_blocks_is_7 cmp r12, 6 je %%_initial_num_blocks_is_6 cmp r12, 5 je %%_initial_num_blocks_is_5 cmp r12, 4 je %%_initial_num_blocks_is_4 cmp r12, 3 je %%_initial_num_blocks_is_3 cmp r12, 2 je %%_initial_num_blocks_is_2 jmp %%_initial_num_blocks_is_1 %%_initial_num_blocks_is_7: ;; r13 - %%LENGTH ;; xmm12 - T1 ;; xmm13 - T2 ;; xmm14 - T3 - AAD HASH OUT when not producing 8 AES keys ;; xmm15 - T4 ;; xmm11 - T5 ;; xmm9 - CTR ;; xmm1 - XMM1 - Cipher + Hash when producing 8 AES keys ;; xmm2 - XMM2 ;; xmm3 - XMM3 ;; xmm4 - XMM4 ;; xmm5 - XMM5 ;; xmm6 - XMM6 ;; xmm7 - XMM7 ;; xmm8 - XMM8 - AAD HASH IN ;; xmm10 - T6 ;; xmm0 - T_key INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 7, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_6: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 6, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_5: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 5, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_4: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 4, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_3: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 3, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_2: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 2, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_1: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 1, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC jmp %%_initial_blocks_encrypted %%_initial_num_blocks_is_0: INITIAL_BLOCKS %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, r13, %%DATA_OFFSET, 0, xmm12, xmm13, xmm14, xmm15, xmm11, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm10, xmm0, %%ENC_DEC %%_initial_blocks_encrypted: ;; The entire message was encrypted processed in initial and now need to be hashed cmp r13, 0 je %%_encrypt_done ;; Encrypt the final <16 byte (partial) block, then hash cmp r13, 16 jl %%_encrypt_final_partial ;; Process 7 full blocks plus a partial block cmp r13, 128 jl %%_encrypt_by_8_partial %%_encrypt_by_8_parallel: ;; in_order vs. out_order is an optimization to increment the counter without shuffling ;; it back into little endian. r15d keeps track of when we need to increent in order so ;; that the carry is handled correctly. vmovd r15d, xmm9 and r15d, 255 vpshufb xmm9, [rel SHUF_MASK] %%_encrypt_by_8_new: cmp r15d, 255-8 jg %%_encrypt_by_8 ;; xmm0 - T1 ;; xmm10 - T2 ;; xmm11 - T3 ;; xmm12 - T4 ;; xmm13 - T5 ;; xmm14 - T6 ;; xmm9 - CTR ;; xmm1 - XMM1 ;; xmm2 - XMM2 ;; xmm3 - XMM3 ;; xmm4 - XMM4 ;; xmm5 - XMM5 ;; xmm6 - XMM6 ;; xmm7 - XMM7 ;; xmm8 - XMM8 ;; xmm15 - T7 add r15b, 8 GHASH_8_ENCRYPT_8_PARALLEL %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, %%DATA_OFFSET, xmm0, xmm10, xmm11, xmm12, xmm13, xmm14, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm15, out_order, %%ENC_DEC, full add %%DATA_OFFSET, 128 sub r13, 128 cmp r13, 128 jge %%_encrypt_by_8_new vpshufb xmm9, [rel SHUF_MASK] jmp %%_encrypt_by_8_parallel_done %%_encrypt_by_8: vpshufb xmm9, [rel SHUF_MASK] add r15b, 8 GHASH_8_ENCRYPT_8_PARALLEL %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, %%DATA_OFFSET, xmm0, xmm10, xmm11, xmm12, xmm13, xmm14, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm15, in_order, %%ENC_DEC, full vpshufb xmm9, [rel SHUF_MASK] add %%DATA_OFFSET, 128 sub r13, 128 cmp r13, 128 jge %%_encrypt_by_8_new vpshufb xmm9, [rel SHUF_MASK] %%_encrypt_by_8_parallel_done: ;; Test to see if we need a by 8 with partial block. At this point ;; bytes remaining should be either zero or between 113-127. cmp r13, 0 je %%_encrypt_done %%_encrypt_by_8_partial: ;; Shuffle needed to align key for partial block xor. out_order ;; is a little faster because it avoids extra shuffles. ;; TBD: Might need to account for when we don't have room to increment the counter. ;; Process parallel buffers with a final partial block. GHASH_8_ENCRYPT_8_PARALLEL %%GDATA_KEY, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, %%DATA_OFFSET, xmm0, xmm10, xmm11, xmm12, xmm13, xmm14, xmm9, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm15, in_order, %%ENC_DEC, partial add %%DATA_OFFSET, 128-16 sub r13, 128-16 %%_encrypt_final_partial: vpshufb xmm8, [rel SHUF_MASK] mov [%%GDATA_CTX + PBlockLen], r13 vmovdqu [%%GDATA_CTX + PBlockEncKey], xmm8 ;; xmm8 - Final encrypted counter - need to hash with partial or full block ciphertext ;; GDATA, KEY, T1, T2 ENCRYPT_FINAL_PARTIAL_BLOCK xmm8, xmm0, %%CYPH_PLAIN_OUT, %%PLAIN_CYPH_IN, %%PLAIN_CYPH_LEN, %%ENC_DEC, %%DATA_OFFSET vpshufb xmm8, [rel SHUF_MASK] %%_encrypt_done: ;; Mapping to macro parameters ;; IN: ;; xmm9 contains the counter ;; xmm1-xmm8 contain the xor'd ciphertext ;; OUT: ;; xmm14 contains the final hash ;; GDATA, T1, T2, T3, T4, T5, T6, T7, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8 %ifidn %%INSTANCE_TYPE, multi_call mov r13, [%%GDATA_CTX + PBlockLen] cmp r13, 0 jz %%_hash_last_8 GHASH_LAST_7 %%GDATA_KEY, xmm0, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 ;; XOR the partial word into the hash vpxor xmm14, xmm14, xmm8 jmp %%_ghash_done %endif %%_hash_last_8: GHASH_LAST_8 %%GDATA_KEY, xmm0, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8 %%_ghash_done: vmovdqu [%%GDATA_CTX + CurCount], xmm9 ; my_ctx_data.current_counter = xmm9 vmovdqu [%%GDATA_CTX + AadHash], xmm14 ; my_ctx_data.aad hash = xmm14 %%_enc_dec_done: %endmacro ; GCM_ENC_DEC ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GCM_COMPLETE Finishes Encryption/Decryption of last partial block after GCM_UPDATE finishes. ; Input: A gcm_key_data * (GDATA_KEY), gcm_context_data (GDATA_CTX) and whether encoding or decoding (ENC_DEC). ; Output: Authorization Tag (AUTH_TAG) and Authorization Tag length (AUTH_TAG_LEN) ; Clobbers rax, r10-r12, and xmm0-xmm2, xmm5-xmm6, xmm9-xmm11, xmm13-xmm15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_COMPLETE 6 %define %%GDATA_KEY %1 %define %%GDATA_CTX %2 %define %%AUTH_TAG %3 %define %%AUTH_TAG_LEN %4 %define %%ENC_DEC %5 %define %%INSTANCE_TYPE %6 %define %%PLAIN_CYPH_LEN rax vmovdqu xmm13, [%%GDATA_KEY + HashKey] ;; Start AES as early as possible vmovdqu xmm9, [%%GDATA_CTX + OrigIV] ; xmm9 = Y0 ENCRYPT_SINGLE_BLOCK %%GDATA_KEY, xmm9 ; E(K, Y0) %ifidn %%INSTANCE_TYPE, multi_call ;; If the GCM function is called as a single function call rather ;; than invoking the individual parts (init, update, finalize) we ;; can remove a write to read dependency on AadHash. vmovdqu xmm14, [%%GDATA_CTX + AadHash] ;; Encrypt the final partial block. If we did this as a single call then ;; the partial block was handled in the main GCM_ENC_DEC macro. mov r12, [%%GDATA_CTX + PBlockLen] cmp r12, 0 je %%_partial_done GHASH_MUL xmm14, xmm13, xmm0, xmm10, xmm11, xmm5, xmm6 ;GHASH computation for the last <16 Byte block ;; The next code line has been removed due to incorrect work in case of two calls of GetTag - tags were not identical ;; vmovdqu [%%GDATA_CTX + AadHash], xmm14 %%_partial_done: %endif mov r12, [%%GDATA_CTX + AadLen] ; r12 = aadLen (number of bytes) mov %%PLAIN_CYPH_LEN, [%%GDATA_CTX + InLen] shl r12, 3 ; convert into number of bits vmovd xmm15, r12d ; len(A) in xmm15 shl %%PLAIN_CYPH_LEN, 3 ; len(C) in bits (*128) vmovq xmm1, %%PLAIN_CYPH_LEN vpslldq xmm15, xmm15, 8 ; xmm15 = len(A)|| 0x0000000000000000 vpxor xmm15, xmm15, xmm1 ; xmm15 = len(A)||len(C) vpxor xmm14, xmm15 GHASH_MUL xmm14, xmm13, xmm0, xmm10, xmm11, xmm5, xmm6 vpshufb xmm14, [rel SHUF_MASK] ; perform a 16Byte swap vpxor xmm9, xmm9, xmm14 %%_return_T: mov r10, %%AUTH_TAG ; r10 = authTag mov r11, %%AUTH_TAG_LEN ; r11 = auth_tag_len cmp r11, 16 je %%_T_16 cmp r11, 12 je %%_T_12 cmp r11, 8 je %%_T_8 simd_store_avx r10, xmm9, r11, r12, rax jmp %%_return_T_done %%_T_8: vmovq rax, xmm9 mov [r10], rax jmp %%_return_T_done %%_T_12: vmovq rax, xmm9 mov [r10], rax vpsrldq xmm9, xmm9, 8 vmovd eax, xmm9 mov [r10 + 8], eax jmp %%_return_T_done %%_T_16: vmovdqu [r10], xmm9 %%_return_T_done: ;; IPPCP: disabled clearing of context fields, as in IPPCP case GetTag may be called ;; several times and it should not stop GCM processing. Context zeroing is done by user. ;; https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-reference/current/aes-gcm-functions.html ;; %ifdef SAFE_DATA ;; ;; Clear sensitive data from context structure ;; vpxor xmm0, xmm0 ;; vmovdqu [%%GDATA_CTX + AadHash], xmm0 ;; vmovdqu [%%GDATA_CTX + PBlockEncKey], xmm0 ;; %endif %endmacro ; GCM_COMPLETE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; GCM_UPDATE_AAD_HASH update AadHash value in gcm_context_data struct to prepare for encoding/decoding. ;;; Input: gcm_key_data * (GDATA_KEY), gcm_context_data *(GDATA_CTX), ;;; Additional Authentication data (A_IN), Additional Data length (A_LEN). ;;; Output: Updated GDATA_CTX with the hash of A_IN (AadHash). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_UPDATE_AAD_HASH 7 %define %%GDATA_KEY %1 ; [in] GCM expanded keys pointer %define %%GDATA_CTX %2 ; [in] GCM context pointer %define %%A_IN %3 ; [in] AAD pointer %define %%A_LEN %4 ; [in] AAD length in bytes %define %%GPR1 %5 ; temp GPR %define %%GPR2 %6 ; temp GPR %define %%GPR3 %7 ; temp GPR %define %%AAD_HASH xmm14 vmovdqu64 %%AAD_HASH, [%%GDATA_CTX + AadHash] ; load current hash UPDATE_HASH %%A_IN, %%A_LEN, %%AAD_HASH, %%GDATA_KEY, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, %%GPR1, %%GPR2, %%GPR3 vmovdqu64 [%%GDATA_CTX + AadHash], %%AAD_HASH ; store updated hash %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; GCM_UPDATE_IV_HASH update orig_IV value in gcm_context_data struct to prepare for encoding/decoding. ;;; Input: gcm_key_data * (GDATA_KEY), gcm_context_data *(GDATA_CTX), ;;; Initialization Vector (IV), Initialization Vector length (IV_LEN). ;;; Output: Updated GDATA_CTX with the hash of A_IN (orig_IV). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_UPDATE_IV_HASH 7 %define %%GDATA_KEY %1 ; [in] GCM expanded keys pointer %define %%GDATA_CTX %2 ; [in] GCM context pointer %define %%IV %3 ; [in] AAD pointer %define %%IV_LEN %4 ; [in] AAD length in bytes %define %%GPR1 %5 ; temp GPR %define %%GPR2 %6 ; temp GPR %define %%GPR3 %7 ; temp GPR %define %%IV_HASH xmm14 vmovdqu64 %%IV_HASH, [%%GDATA_CTX + OrigIV] ; load current hash UPDATE_HASH %%IV, %%IV_LEN, %%IV_HASH, %%GDATA_KEY, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, %%GPR1, %%GPR2, %%GPR3 vmovdqu64 [%%GDATA_CTX + OrigIV], %%IV_HASH ; store updated hash %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; GCM_FINALIZE_IV_HASH finalize updating of AadHash value in gcm_context_data struct ;;; to prepare for encoding/decoding. ;;; Input: gcm_key_data * (GDATA_KEY), gcm_context_data *(GDATA_CTX), ;;; Initialization Vector (IV), Initialization Vector length (IV_LEN). ;;; Output: Updated GDATA_CTX with the hash of A_IN (orig_IV). and initialized other parts of GDATA_CTX. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_FINALIZE_IV_HASH 7-8 %define %%GDATA_KEY %1 ; [in] GCM expanded keys pointer %define %%GDATA_CTX %2 ; [in] GCM context pointer %define %%IV %3 ; [in] IV pointer %define %%IV_LEN %4 ; [in] IV length in bytes %define %%GPR1 %5 ; temp GPR %define %%GPR2 %6 ; temp GPR %define %%GPR3 %7 ; temp GPR %define %%IV_GEN_LEN %8 ; [in] IV general length in bytes %if %0 == 7 ;; IV is 12 bytes ;; read 12 IV bytes and pad with 0x00000001 mov %%GPR2, %%IV vmovd xmm3, [%%GPR2 + 8] vpslldq xmm3, 8 vmovq xmm2, [%%GPR2] vmovdqa xmm4, [rel ONEf] vpternlogq xmm2, xmm3, xmm4, 0xfe ; xmm2 = xmm2 or xmm3 or xmm4 %else ;; IV is not 12 bytes vmovdqu xmm2, [%%GDATA_CTX + OrigIV] CALC_J0 %%GDATA_KEY, %%IV, %%IV_LEN, xmm2, r10, r11, r12, xmm0, xmm1, \ xmm3, xmm4, xmm5, xmm6, %%IV_GEN_LEN %endif vmovdqu [%%GDATA_CTX + OrigIV], xmm2 ; ctx_data.orig_IV = iv ;; store IV as counter in LE format vpshufb xmm2, [rel SHUF_MASK] vmovdqu [%%GDATA_CTX + CurCount], xmm2 ; ctx_data.current_counter = iv %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_precomp_128_avx512 / ; aes_gcm_precomp_192_avx512 / ; aes_gcm_precomp_256_avx512 ; (struct gcm_key_data *key_data) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(precomp,_), PUBLIC ;; Parameter is passed through register %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz exit_precomp %endif push r12 push r13 push r14 push r15 mov r14, rsp sub rsp, VARIABLE_OFFSET and rsp, ~63 ; align rsp to 64 bytes %ifidn __OUTPUT_FORMAT__, win64 ; only xmm6 needs to be maintained vmovdqu [rsp + LOCAL_STORAGE + 0*16],xmm6 %endif vpxor xmm6, xmm6 ENCRYPT_SINGLE_BLOCK arg1, xmm6 ; xmm6 = HashKey vpshufb xmm6, [rel SHUF_MASK] ;;;;;;;;;;;;;;; PRECOMPUTATION of HashKey<<1 mod poly from the HashKey;;;;;;;;;;;;;;; vmovdqa xmm2, xmm6 vpsllq xmm6, xmm6, 1 vpsrlq xmm2, xmm2, 63 vmovdqa xmm1, xmm2 vpslldq xmm2, xmm2, 8 vpsrldq xmm1, xmm1, 8 vpor xmm6, xmm6, xmm2 ;reduction vpshufd xmm2, xmm1, 00100100b vpcmpeqd xmm2, [rel TWOONE] vpand xmm2, xmm2, [rel POLY] vpxor xmm6, xmm6, xmm2 ; xmm6 holds the HashKey<<1 mod poly ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vmovdqu [arg1 + HashKey], xmm6 ; store HashKey<<1 mod poly PRECOMPUTE arg1, xmm6, xmm0, xmm1, xmm2, xmm3, xmm4, xmm5 %ifdef SAFE_DATA clear_scratch_gps_asm clear_scratch_zmms_asm %endif %ifidn __OUTPUT_FORMAT__, win64 vmovdqu xmm6, [rsp + LOCAL_STORAGE + 0*16] %endif mov rsp, r14 pop r15 pop r14 pop r13 pop r12 .exit_precomp: ret ENDFUNC FN_NAME(precomp,_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_enc_128_update_avx512 / aes_gcm_enc_192_update_avx512 / ; aes_gcm_enc_256_update_avx512 ; (const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; u8 *out, ; const u8 *in, ; u64 plaintext_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(enc,_update_), PUBLIC FUNC_SAVE %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz exit_update_enc ;; Check context_data != NULL cmp arg2, 0 jz exit_update_enc ;; Check if plaintext_len == 0 cmp arg5, 0 jz skip_in_out_check_update_enc ;; Check out != NULL (plaintext_len != 0) cmp arg3, 0 jz exit_update_enc ;; Check in != NULL (plaintext_len != 0) cmp arg4, 0 jz exit_update_enc .skip_in_out_check_update_enc: %endif GCM_ENC_DEC arg1, arg2, arg3, arg4, arg5, ENC, multi_call .exit_update_enc: FUNC_RESTORE ret ENDFUNC FN_NAME(enc,_update_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_dec_128_update_avx512 / aes_gcm_dec_192_update_avx512 / ; aes_gcm_dec_256_update_avx512 ; (const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; u8 *out, ; const u8 *in, ; u64 plaintext_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(dec,_update_), PUBLIC FUNC_SAVE %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz exit_update_dec ;; Check context_data != NULL cmp arg2, 0 jz exit_update_dec ;; Check if plaintext_len == 0 cmp arg5, 0 jz skip_in_out_check_update_dec ;; Check out != NULL (plaintext_len != 0) cmp arg3, 0 jz exit_update_dec ;; Check in != NULL (plaintext_len != 0) cmp arg4, 0 jz exit_update_dec skip_in_out_check_update_dec: %endif GCM_ENC_DEC arg1, arg2, arg3, arg4, arg5, DEC, multi_call .exit_update_dec: FUNC_RESTORE ret ENDFUNC FN_NAME(dec,_update_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_gettag_128_avx512 / aes_gcm_gettag_192_avx512 / ; aes_gcm_gettag_256_avx512 ; (const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; u8 *auth_tag, ; u64 auth_tag_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM FN_NAME(gettag,_), PUBLIC FUNC_SAVE ;; All parameters are passed through registers %ifdef SAFE_PARAM ;; Check key_data != NULL cmp arg1, 0 jz exit_enc_fin ;; Check context_data != NULL cmp arg2, 0 jz exit_enc_fin ;; Check auth_tag != NULL cmp arg3, 0 jz exit_enc_fin ;; Check auth_tag_len == 0 or > 16 cmp arg4, 0 jz exit_enc_fin cmp arg4, 16 ja exit_enc_fin %endif GCM_COMPLETE arg1, arg2, arg3, arg4, ENC, multi_call .exit_enc_fin: FUNC_RESTORE ret ENDFUNC FN_NAME(gettag,_) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; IV and AAD in disconnected buffers processing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %ifdef GCM128_MODE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_aad_hash_update_avx512( ; const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; const u8 *aad, ; const u64 aad_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_aad_hash_update_avx512, PUBLIC FUNC_SAVE GCM_UPDATE_AAD_HASH arg1, arg2, arg3, arg4, r10, r11, r12 FUNC_RESTORE ret ENDFUNC aes_gcm_aad_hash_update_avx512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_iv_hash_update_avx512( ; const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; const u8 *iv, ; const u64 iv_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_iv_hash_update_avx512, PUBLIC FUNC_SAVE GCM_UPDATE_IV_HASH arg1, arg2, arg3, arg4, r10, r11, r12 FUNC_RESTORE ret ENDFUNC aes_gcm_iv_hash_update_avx512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_iv_hash_finalize_avx512( ; const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; const u8 *iv, ; const u64 iv_len, ; const u64 iv_general_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_iv_hash_finalize_avx512, PUBLIC FUNC_SAVE cmp arg5, 12 je .iv_eq_12 GCM_FINALIZE_IV_HASH arg1, arg2, arg3, arg4, r10, r11, r12, arg5 jmp .skip_iv_eq_12 .iv_eq_12: GCM_FINALIZE_IV_HASH arg1, arg2, arg3, arg4, r10, r11, r12 .skip_iv_eq_12: FUNC_RESTORE ret ENDFUNC aes_gcm_iv_hash_finalize_avx512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_gmult_avx512( ; const struct gcm_key_data *key_data, ; u8 *ghash) ; ; Function updates |ghash| value by multiplying it on H^1 key. ; Leaf function. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_gmult_avx512, PUBLIC vmovdqu64 xmm1, [arg2] vmovdqu64 xmm2, [arg1 + HashKey_1] GHASH_MUL xmm1, xmm2, xmm3, xmm4, xmm5, xmm16, xmm17 vmovdqu64 [arg2], xmm1 ret ENDFUNC aes_gcm_gmult_avx512 %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_defines.inc000066400000000000000000000206221470420105600263160ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 GCM_DEFINES_ASM_INCLUDED %define GCM_DEFINES_ASM_INCLUDED ; ; Authors: ; Erdinc Ozturk ; Vinodh Gopal ; James Guilford section .data default rel align 16 POLY: dq 0x0000000000000001, 0xC200000000000000 align 64 POLY2: dq 0x00000001C2000000, 0xC200000000000000 dq 0x00000001C2000000, 0xC200000000000000 dq 0x00000001C2000000, 0xC200000000000000 dq 0x00000001C2000000, 0xC200000000000000 align 16 TWOONE: dq 0x0000000000000001, 0x0000000100000000 ;;; @note Order of these constants should not change. ;;; More specifically, ALL_F should follow SHIFT_MASK, and ZERO should follow ALL_F align 64 SHUF_MASK: dq 0x08090A0B0C0D0E0F, 0x0001020304050607 dq 0x08090A0B0C0D0E0F, 0x0001020304050607 dq 0x08090A0B0C0D0E0F, 0x0001020304050607 dq 0x08090A0B0C0D0E0F, 0x0001020304050607 align 16 SHIFT_MASK: dq 0x0706050403020100, 0x0f0e0d0c0b0a0908 ALL_F: dq 0xffffffffffffffff, 0xffffffffffffffff ZERO: dq 0x0000000000000000, 0x0000000000000000 align 16 ONE: dq 0x0000000000000001, 0x0000000000000000 align 16 TWO: dq 0x0000000000000002, 0x0000000000000000 align 16 ONEf: dq 0x0000000000000000, 0x0100000000000000 align 16 TWOf: dq 0x0000000000000000, 0x0200000000000000 align 64 ddq_add_1234: dq 0x0000000000000001, 0x0000000000000000 dq 0x0000000000000002, 0x0000000000000000 dq 0x0000000000000003, 0x0000000000000000 dq 0x0000000000000004, 0x0000000000000000 align 64 ddq_add_5678: dq 0x0000000000000005, 0x0000000000000000 dq 0x0000000000000006, 0x0000000000000000 dq 0x0000000000000007, 0x0000000000000000 dq 0x0000000000000008, 0x0000000000000000 align 64 ddq_add_4444: dq 0x0000000000000004, 0x0000000000000000 dq 0x0000000000000004, 0x0000000000000000 dq 0x0000000000000004, 0x0000000000000000 dq 0x0000000000000004, 0x0000000000000000 align 64 ddq_add_8888: dq 0x0000000000000008, 0x0000000000000000 dq 0x0000000000000008, 0x0000000000000000 dq 0x0000000000000008, 0x0000000000000000 dq 0x0000000000000008, 0x0000000000000000 align 64 ddq_addbe_1234: dq 0x0000000000000000, 0x0100000000000000 dq 0x0000000000000000, 0x0200000000000000 dq 0x0000000000000000, 0x0300000000000000 dq 0x0000000000000000, 0x0400000000000000 align 64 ddq_addbe_5678: dq 0x0000000000000000, 0x0500000000000000 dq 0x0000000000000000, 0x0600000000000000 dq 0x0000000000000000, 0x0700000000000000 dq 0x0000000000000000, 0x0800000000000000 align 64 ddq_addbe_4444: dq 0x0000000000000000, 0x0400000000000000 dq 0x0000000000000000, 0x0400000000000000 dq 0x0000000000000000, 0x0400000000000000 dq 0x0000000000000000, 0x0400000000000000 align 64 ddq_addbe_8888: dq 0x0000000000000000, 0x0800000000000000 dq 0x0000000000000000, 0x0800000000000000 dq 0x0000000000000000, 0x0800000000000000 dq 0x0000000000000000, 0x0800000000000000 align 64 byte_len_to_mask_table: dw 0x0000, 0x0001, 0x0003, 0x0007, dw 0x000f, 0x001f, 0x003f, 0x007f, dw 0x00ff, 0x01ff, 0x03ff, 0x07ff, dw 0x0fff, 0x1fff, 0x3fff, 0x7fff, dw 0xffff align 64 byte64_len_to_mask_table: dq 0x0000000000000000, 0x0000000000000001 dq 0x0000000000000003, 0x0000000000000007 dq 0x000000000000000f, 0x000000000000001f dq 0x000000000000003f, 0x000000000000007f dq 0x00000000000000ff, 0x00000000000001ff dq 0x00000000000003ff, 0x00000000000007ff dq 0x0000000000000fff, 0x0000000000001fff dq 0x0000000000003fff, 0x0000000000007fff dq 0x000000000000ffff, 0x000000000001ffff dq 0x000000000003ffff, 0x000000000007ffff dq 0x00000000000fffff, 0x00000000001fffff dq 0x00000000003fffff, 0x00000000007fffff dq 0x0000000000ffffff, 0x0000000001ffffff dq 0x0000000003ffffff, 0x0000000007ffffff dq 0x000000000fffffff, 0x000000001fffffff dq 0x000000003fffffff, 0x000000007fffffff dq 0x00000000ffffffff, 0x00000001ffffffff dq 0x00000003ffffffff, 0x00000007ffffffff dq 0x0000000fffffffff, 0x0000001fffffffff dq 0x0000003fffffffff, 0x0000007fffffffff dq 0x000000ffffffffff, 0x000001ffffffffff dq 0x000003ffffffffff, 0x000007ffffffffff dq 0x00000fffffffffff, 0x00001fffffffffff dq 0x00003fffffffffff, 0x00007fffffffffff dq 0x0000ffffffffffff, 0x0001ffffffffffff dq 0x0003ffffffffffff, 0x0007ffffffffffff dq 0x000fffffffffffff, 0x001fffffffffffff dq 0x003fffffffffffff, 0x007fffffffffffff dq 0x00ffffffffffffff, 0x01ffffffffffffff dq 0x03ffffffffffffff, 0x07ffffffffffffff dq 0x0fffffffffffffff, 0x1fffffffffffffff dq 0x3fffffffffffffff, 0x7fffffffffffffff dq 0xffffffffffffffff align 64 mask_out_top_block: dq 0xffffffffffffffff, 0xffffffffffffffff dq 0xffffffffffffffff, 0xffffffffffffffff dq 0xffffffffffffffff, 0xffffffffffffffff dq 0x0000000000000000, 0x0000000000000000 section .text ;;define the fields of gcm_context_data struct ;; struct gcm_context_data { ;; // init, update and finalize context data ;; uint8_t aad_hash[GCM_BLOCK_LEN]; ;; uint64_t aad_length; ;; uint64_t in_length; ;; uint8_t partial_block_enc_key[GCM_BLOCK_LEN]; ;; uint8_t orig_IV[GCM_BLOCK_LEN]; ;; uint8_t current_counter[GCM_BLOCK_LEN]; ;; uint64_t partial_block_length; ;; }; %define AadHash (16*0) ; store current Hash of data which has been input %define AadLen (16*1) ; store length of input data which will not be encrypted or decrypted %define InLen ((16*1)+8); store length of input data which will be encrypted or decrypted %define PBlockEncKey (16*2) ; encryption key for the partial block at the end of the previous update %define OrigIV (16*3) ; input IV %define CurCount (16*4) ; Current counter for generation of encryption key %define PBlockLen (16*5) ; length of partial block at the end of the previous update %define reg(q) xmm %+ q %define regy(q) ymm %+ q %define regz(q) zmm %+ q %ifdef WIN_ABI %xdefine arg1 rcx %xdefine arg2 rdx %xdefine arg3 r8 %xdefine arg4 r9 %xdefine arg5 qword [r14 + STACK_OFFSET + 8*5] %xdefine arg6 qword [r14 + STACK_OFFSET + 8*6] %xdefine arg7 qword [r14 + STACK_OFFSET + 8*7] %xdefine arg8 qword [r14 + STACK_OFFSET + 8*8] %xdefine arg9 qword [r14 + STACK_OFFSET + 8*9] %xdefine arg10 qword [r14 + STACK_OFFSET + 8*10] %else %xdefine arg1 rdi %xdefine arg2 rsi %xdefine arg3 rdx %xdefine arg4 rcx %xdefine arg5 r8 %xdefine arg6 r9 %xdefine arg7 qword [r14 + STACK_OFFSET + 8*1] %xdefine arg8 qword [r14 + STACK_OFFSET + 8*2] %xdefine arg9 qword [r14 + STACK_OFFSET + 8*3] %xdefine arg10 qword [r14 + STACK_OFFSET + 8*4] %endif %ifdef NT_LDST %define NT_LD %define NT_ST %endif ;;; Use Non-temporal load/stor %ifdef NT_LD %define XLDR movntdqa %define VXLDR vmovntdqa %define VX512LDR vmovntdqa %else %define XLDR movdqu %define VXLDR vmovdqu %define VX512LDR vmovdqu8 %endif ;;; Use Non-temporal load/stor %ifdef NT_ST %define XSTR movntdq %define VXSTR vmovntdq %define VX512STR vmovntdq %else %define XSTR movdqu %define VXSTR vmovdqu %define VX512STR vmovdqu8 %endif %define SAFE_DATA 1 %endif ; GCM_DEFINES_ASM_INCLUDED cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_ippcp_api_vaes_avx512.inc000066400000000000000000000122531470420105600307720ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 _GCM_IPPCP_API_VAES_AVX512_INC_ %define _GCM_IPPCP_API_VAES_AVX512_INC_ %include "gcm_vaes_avx512.inc" section .text default rel %ifdef GCM128_MODE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_iv_hash_update_vaes512( ; const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; const u8 *iv, ; const u64 iv_len); ; ; NB: |iv_len| shall be multiple of 16 bytes (block size). This restriction is handled outside. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_iv_hash_update_vaes512, PUBLIC FUNC_SAVE vmovdqu64 xmm8, [arg2 + OrigIV] ; load current hash ;; Calculate GHASH of this segment CALC_AAD_HASH arg3, arg4, xmm8, arg1, zmm1, zmm2, zmm3, zmm4, zmm5, \ zmm6, zmm7, zmm9, zmm10, zmm11, zmm12, zmm13, zmm15, \ zmm16, zmm17, zmm18, zmm19, zmm20, r10, r11, r12, k1 vmovdqu64 [arg2 + OrigIV], xmm8 ; store updated hash FUNC_RESTORE ret ENDFUNC aes_gcm_iv_hash_update_vaes512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_iv_hash_finalize_vaes512( ; const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; const u8 *iv, ; const u64 iv_len, ; const u64 iv_general_len); ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_iv_hash_finalize_vaes512, PUBLIC FUNC_SAVE cmp arg5, 12 jnz .Liv_is_not_12_bytes ;; read 12 IV bytes and pad with 0x00000001 vmovdqa64 xmm2, [rel ONEf] mov r11, arg3 mov DWORD(r10), 0x0000_0fff kmovd k1, DWORD(r10) vmovdqu8 xmm2{k1}, [r11] ; ctr = IV | 0x1 jmp .Liv_compute_done .Liv_is_not_12_bytes: vmovdqu xmm2, [arg2 + OrigIV] ;; prepare IV CALC_J0 arg1, arg3, arg4, xmm2, \ zmm1, zmm11, zmm3, zmm4, zmm5, zmm6, zmm7, zmm8, zmm9, zmm10, \ zmm12, zmm13, zmm15, zmm16, zmm17, zmm18, zmm19, zmm20, \ r10, r11, r12, k1, arg5 .Liv_compute_done: vmovdqu64 [arg2 + OrigIV], xmm2 ; ctx.orig_IV = iv vpshufb xmm2, [rel SHUF_MASK] vmovdqu64 [arg2 + CurCount], xmm2 ; ctx.current_counter = iv (LE format) FUNC_RESTORE ret ENDFUNC aes_gcm_iv_hash_finalize_vaes512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_aad_hash_update_vaes512( ; const struct gcm_key_data *key_data, ; struct gcm_context_data *context_data, ; const u8 *aad, ; const u64 aad_len); ; ; NB: This function is always called with |aad_len| that is multiple of 16 bytes (block size). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_aad_hash_update_vaes512, PUBLIC FUNC_SAVE vmovdqu64 xmm14, [arg2 + AadHash] ; load current hash ;; Calculate GHASH of this segment CALC_AAD_HASH arg3, arg4, xmm14, arg1, zmm1, zmm2, zmm3, zmm4, zmm5, \ zmm6, zmm7, zmm9, zmm10, zmm11, zmm12, zmm13, zmm15, \ zmm16, zmm17, zmm18, zmm19, zmm20, r10, r11, r12, k1 vmovdqu64 [arg2 + AadHash], xmm14 ; store updated hash FUNC_RESTORE ret ENDFUNC aes_gcm_aad_hash_update_vaes512 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;void aes_gcm_gmult_vaes512( ; struct gcm_context_data *context_data, ; u8 *ghash) ; ; Function updates |ghash| value by multiplying it on H^1 key. ; Leaf function. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IPPASM aes_gcm_gmult_vaes512, PUBLIC vmovdqu64 xmm1, [arg2] vmovdqu64 xmm2, [arg1 + HashKey_1] GHASH_MUL xmm1, xmm2, xmm3, xmm4, xmm5, xmm16, xmm17 vmovdqu64 [arg2], xmm1 ret ENDFUNC aes_gcm_gmult_vaes512 %endif ; GCM128_MODE %endif ; _GCM_IPPCP_API_VAES_AVX512_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_keys_avx512.inc000066400000000000000000000037631470420105600267710ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2019 Intel Corporation ; ; 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 GCM_KEYS_AVX512_INCLUDED %define GCM_KEYS_AVX512_INCLUDED ;; Define the fields of gcm_key_data struct: ;; uint8_t expanded_keys[GCM_ENC_KEY_LEN * GCM_KEY_SETS]; ;; uint8_t shifted_hkey_8[GCM_ENC_KEY_LEN]; // HashKey^8 <<1 mod poly ;; uint8_t shifted_hkey_7[GCM_ENC_KEY_LEN]; // HashKey^7 <<1 mod poly ;; uint8_t shifted_hkey_6[GCM_ENC_KEY_LEN]; // HashKey^6 <<1 mod poly ;; uint8_t shifted_hkey_5[GCM_ENC_KEY_LEN]; // HashKey^5 <<1 mod poly ;; uint8_t shifted_hkey_4[GCM_ENC_KEY_LEN]; // HashKey^4 <<1 mod poly ;; uint8_t shifted_hkey_3[GCM_ENC_KEY_LEN]; // HashKey^3 <<1 mod poly ;; uint8_t shifted_hkey_2[GCM_ENC_KEY_LEN]; // HashKey^2 <<1 mod poly ;; uint8_t shifted_hkey_1[GCM_ENC_KEY_LEN]; // HashKey <<1 mod poly %define HashKey_8 (16*15) ; HashKey^8 <<1 mod poly %define HashKey_7 (16*16) ; HashKey^7 <<1 mod poly %define HashKey_6 (16*17) ; HashKey^6 <<1 mod poly %define HashKey_5 (16*18) ; HashKey^5 <<1 mod poly %define HashKey_4 (16*19) ; HashKey^4 <<1 mod poly %define HashKey_3 (16*20) ; HashKey^3 <<1 mod poly %define HashKey_2 (16*21) ; HashKey^2 <<1 mod poly %define HashKey_1 (16*22) ; HashKey <<1 mod poly %define HashKey (16*22) ; HashKey <<1 mod poly %endif ; GCM_KEYS_AVX512_INCLUDED cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_keys_vaes_avx512.inc000066400000000000000000000302061470420105600277770ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 GCM_KEYS_VAES_AVX512_INCLUDED %define GCM_KEYS_VAES_AVX512_INCLUDED ;; Define the fields of gcm_key_data struct: ;; uint8_t expanded_keys[GCM_ENC_KEY_LEN * GCM_KEY_SETS]; ;; uint8_t shifted_hkey_9_128[GCM_ENC_KEY_LEN * (128 - 8)]; ;; uint8_t shifted_hkey_8[GCM_ENC_KEY_LEN]; // HashKey^8 <<1 mod poly ;; uint8_t shifted_hkey_7[GCM_ENC_KEY_LEN]; // HashKey^7 <<1 mod poly ;; uint8_t shifted_hkey_6[GCM_ENC_KEY_LEN]; // HashKey^6 <<1 mod poly ;; uint8_t shifted_hkey_5[GCM_ENC_KEY_LEN]; // HashKey^5 <<1 mod poly ;; uint8_t shifted_hkey_4[GCM_ENC_KEY_LEN]; // HashKey^4 <<1 mod poly ;; uint8_t shifted_hkey_3[GCM_ENC_KEY_LEN]; // HashKey^3 <<1 mod poly ;; uint8_t shifted_hkey_2[GCM_ENC_KEY_LEN]; // HashKey^2 <<1 mod poly ;; uint8_t shifted_hkey_1[GCM_ENC_KEY_LEN]; // HashKey <<1 mod poly %ifdef GCM_BIG_DATA ;; ;; Key structure holds up to 128 ghash keys ;; %define HashKey_128 (16*15) ; HashKey^128 <<1 mod poly %define HashKey_127 (16*16) ; HashKey^127 <<1 mod poly %define HashKey_126 (16*17) ; HashKey^126 <<1 mod poly %define HashKey_125 (16*18) ; HashKey^125 <<1 mod poly %define HashKey_124 (16*19) ; HashKey^124 <<1 mod poly %define HashKey_123 (16*20) ; HashKey^123 <<1 mod poly %define HashKey_122 (16*21) ; HashKey^122 <<1 mod poly %define HashKey_121 (16*22) ; HashKey^121 <<1 mod poly %define HashKey_120 (16*23) ; HashKey^120 <<1 mod poly %define HashKey_119 (16*24) ; HashKey^119 <<1 mod poly %define HashKey_118 (16*25) ; HashKey^118 <<1 mod poly %define HashKey_117 (16*26) ; HashKey^117 <<1 mod poly %define HashKey_116 (16*27) ; HashKey^116 <<1 mod poly %define HashKey_115 (16*28) ; HashKey^115 <<1 mod poly %define HashKey_114 (16*29) ; HashKey^114 <<1 mod poly %define HashKey_113 (16*30) ; HashKey^113 <<1 mod poly %define HashKey_112 (16*31) ; HashKey^112 <<1 mod poly %define HashKey_111 (16*32) ; HashKey^111 <<1 mod poly %define HashKey_110 (16*33) ; HashKey^110 <<1 mod poly %define HashKey_109 (16*34) ; HashKey^109 <<1 mod poly %define HashKey_108 (16*35) ; HashKey^108 <<1 mod poly %define HashKey_107 (16*36) ; HashKey^107 <<1 mod poly %define HashKey_106 (16*37) ; HashKey^106 <<1 mod poly %define HashKey_105 (16*38) ; HashKey^105 <<1 mod poly %define HashKey_104 (16*39) ; HashKey^104 <<1 mod poly %define HashKey_103 (16*40) ; HashKey^103 <<1 mod poly %define HashKey_102 (16*41) ; HashKey^102 <<1 mod poly %define HashKey_101 (16*42) ; HashKey^101 <<1 mod poly %define HashKey_100 (16*43) ; HashKey^100 <<1 mod poly %define HashKey_99 (16*44) ; HashKey^99 <<1 mod poly %define HashKey_98 (16*45) ; HashKey^98 <<1 mod poly %define HashKey_97 (16*46) ; HashKey^97 <<1 mod poly %define HashKey_96 (16*47) ; HashKey^96 <<1 mod poly %define HashKey_95 (16*48) ; HashKey^95 <<1 mod poly %define HashKey_94 (16*49) ; HashKey^94 <<1 mod poly %define HashKey_93 (16*50) ; HashKey^93 <<1 mod poly %define HashKey_92 (16*51) ; HashKey^92 <<1 mod poly %define HashKey_91 (16*52) ; HashKey^91 <<1 mod poly %define HashKey_90 (16*53) ; HashKey^90 <<1 mod poly %define HashKey_89 (16*54) ; HashKey^89 <<1 mod poly %define HashKey_88 (16*55) ; HashKey^88 <<1 mod poly %define HashKey_87 (16*56) ; HashKey^87 <<1 mod poly %define HashKey_86 (16*57) ; HashKey^86 <<1 mod poly %define HashKey_85 (16*58) ; HashKey^85 <<1 mod poly %define HashKey_84 (16*59) ; HashKey^84 <<1 mod poly %define HashKey_83 (16*60) ; HashKey^83 <<1 mod poly %define HashKey_82 (16*61) ; HashKey^82 <<1 mod poly %define HashKey_81 (16*62) ; HashKey^81 <<1 mod poly %define HashKey_80 (16*63) ; HashKey^80 <<1 mod poly %define HashKey_79 (16*64) ; HashKey^79 <<1 mod poly %define HashKey_78 (16*65) ; HashKey^78 <<1 mod poly %define HashKey_77 (16*66) ; HashKey^77 <<1 mod poly %define HashKey_76 (16*67) ; HashKey^76 <<1 mod poly %define HashKey_75 (16*68) ; HashKey^75 <<1 mod poly %define HashKey_74 (16*69) ; HashKey^74 <<1 mod poly %define HashKey_73 (16*70) ; HashKey^73 <<1 mod poly %define HashKey_72 (16*71) ; HashKey^72 <<1 mod poly %define HashKey_71 (16*72) ; HashKey^71 <<1 mod poly %define HashKey_70 (16*73) ; HashKey^70 <<1 mod poly %define HashKey_69 (16*74) ; HashKey^69 <<1 mod poly %define HashKey_68 (16*75) ; HashKey^68 <<1 mod poly %define HashKey_67 (16*76) ; HashKey^67 <<1 mod poly %define HashKey_66 (16*77) ; HashKey^66 <<1 mod poly %define HashKey_65 (16*78) ; HashKey^65 <<1 mod poly %define HashKey_64 (16*79) ; HashKey^64 <<1 mod poly %define HashKey_63 (16*80) ; HashKey^63 <<1 mod poly %define HashKey_62 (16*81) ; HashKey^62 <<1 mod poly %define HashKey_61 (16*82) ; HashKey^61 <<1 mod poly %define HashKey_60 (16*83) ; HashKey^60 <<1 mod poly %define HashKey_59 (16*84) ; HashKey^59 <<1 mod poly %define HashKey_58 (16*85) ; HashKey^58 <<1 mod poly %define HashKey_57 (16*86) ; HashKey^57 <<1 mod poly %define HashKey_56 (16*87) ; HashKey^56 <<1 mod poly %define HashKey_55 (16*88) ; HashKey^55 <<1 mod poly %define HashKey_54 (16*89) ; HashKey^54 <<1 mod poly %define HashKey_53 (16*90) ; HashKey^53 <<1 mod poly %define HashKey_52 (16*91) ; HashKey^52 <<1 mod poly %define HashKey_51 (16*92) ; HashKey^51 <<1 mod poly %define HashKey_50 (16*93) ; HashKey^50 <<1 mod poly %define HashKey_49 (16*94) ; HashKey^49 <<1 mod poly %define HashKey_48 (16*95) ; HashKey^48 <<1 mod poly %define HashKey_47 (16*96) ; HashKey^47 <<1 mod poly %define HashKey_46 (16*97) ; HashKey^46 <<1 mod poly %define HashKey_45 (16*98) ; HashKey^45 <<1 mod poly %define HashKey_44 (16*99) ; HashKey^44 <<1 mod poly %define HashKey_43 (16*100) ; HashKey^43 <<1 mod poly %define HashKey_42 (16*101) ; HashKey^42 <<1 mod poly %define HashKey_41 (16*102) ; HashKey^41 <<1 mod poly %define HashKey_40 (16*103) ; HashKey^40 <<1 mod poly %define HashKey_39 (16*104) ; HashKey^39 <<1 mod poly %define HashKey_38 (16*105) ; HashKey^38 <<1 mod poly %define HashKey_37 (16*106) ; HashKey^37 <<1 mod poly %define HashKey_36 (16*107) ; HashKey^36 <<1 mod poly %define HashKey_35 (16*108) ; HashKey^35 <<1 mod poly %define HashKey_34 (16*109) ; HashKey^34 <<1 mod poly %define HashKey_33 (16*110) ; HashKey^33 <<1 mod poly %define HashKey_32 (16*111) ; HashKey^32 <<1 mod poly %define HashKey_31 (16*112) ; HashKey^31 <<1 mod poly %define HashKey_30 (16*113) ; HashKey^30 <<1 mod poly %define HashKey_29 (16*114) ; HashKey^29 <<1 mod poly %define HashKey_28 (16*115) ; HashKey^28 <<1 mod poly %define HashKey_27 (16*116) ; HashKey^27 <<1 mod poly %define HashKey_26 (16*117) ; HashKey^26 <<1 mod poly %define HashKey_25 (16*118) ; HashKey^25 <<1 mod poly %define HashKey_24 (16*119) ; HashKey^24 <<1 mod poly %define HashKey_23 (16*120) ; HashKey^23 <<1 mod poly %define HashKey_22 (16*121) ; HashKey^22 <<1 mod poly %define HashKey_21 (16*122) ; HashKey^21 <<1 mod poly %define HashKey_20 (16*123) ; HashKey^20 <<1 mod poly %define HashKey_19 (16*124) ; HashKey^19 <<1 mod poly %define HashKey_18 (16*125) ; HashKey^18 <<1 mod poly %define HashKey_17 (16*126) ; HashKey^17 <<1 mod poly %define HashKey_16 (16*127) ; HashKey^16 <<1 mod poly %define HashKey_15 (16*128) ; HashKey^15 <<1 mod poly %define HashKey_14 (16*129) ; HashKey^14 <<1 mod poly %define HashKey_13 (16*130) ; HashKey^13 <<1 mod poly %define HashKey_12 (16*131) ; HashKey^12 <<1 mod poly %define HashKey_11 (16*132) ; HashKey^11 <<1 mod poly %define HashKey_10 (16*133) ; HashKey^10 <<1 mod poly %define HashKey_9 (16*134) ; HashKey^9 <<1 mod poly %define HashKey_8 (16*135) ; HashKey^8 <<1 mod poly %define HashKey_7 (16*136) ; HashKey^7 <<1 mod poly %define HashKey_6 (16*137) ; HashKey^6 <<1 mod poly %define HashKey_5 (16*138) ; HashKey^5 <<1 mod poly %define HashKey_4 (16*139) ; HashKey^4 <<1 mod poly %define HashKey_3 (16*140) ; HashKey^3 <<1 mod poly %define HashKey_2 (16*141) ; HashKey^2 <<1 mod poly %define HashKey_1 (16*142) ; HashKey <<1 mod poly %define HashKey (16*142) ; HashKey <<1 mod poly %else ;; ;; Key structure holds up to 48 ghash keys ;; %define HashKey_48 (16*15) ; HashKey^48 <<1 mod poly %define HashKey_47 (16*16) ; HashKey^47 <<1 mod poly %define HashKey_46 (16*17) ; HashKey^46 <<1 mod poly %define HashKey_45 (16*18) ; HashKey^45 <<1 mod poly %define HashKey_44 (16*19) ; HashKey^44 <<1 mod poly %define HashKey_43 (16*20) ; HashKey^43 <<1 mod poly %define HashKey_42 (16*21) ; HashKey^42 <<1 mod poly %define HashKey_41 (16*22) ; HashKey^41 <<1 mod poly %define HashKey_40 (16*23) ; HashKey^40 <<1 mod poly %define HashKey_39 (16*24) ; HashKey^39 <<1 mod poly %define HashKey_38 (16*25) ; HashKey^38 <<1 mod poly %define HashKey_37 (16*26) ; HashKey^37 <<1 mod poly %define HashKey_36 (16*27) ; HashKey^36 <<1 mod poly %define HashKey_35 (16*28) ; HashKey^35 <<1 mod poly %define HashKey_34 (16*29) ; HashKey^34 <<1 mod poly %define HashKey_33 (16*30) ; HashKey^33 <<1 mod poly %define HashKey_32 (16*31) ; HashKey^32 <<1 mod poly %define HashKey_31 (16*32) ; HashKey^31 <<1 mod poly %define HashKey_30 (16*33) ; HashKey^30 <<1 mod poly %define HashKey_29 (16*34) ; HashKey^29 <<1 mod poly %define HashKey_28 (16*35) ; HashKey^28 <<1 mod poly %define HashKey_27 (16*36) ; HashKey^27 <<1 mod poly %define HashKey_26 (16*37) ; HashKey^26 <<1 mod poly %define HashKey_25 (16*38) ; HashKey^25 <<1 mod poly %define HashKey_24 (16*39) ; HashKey^24 <<1 mod poly %define HashKey_23 (16*40) ; HashKey^23 <<1 mod poly %define HashKey_22 (16*41) ; HashKey^22 <<1 mod poly %define HashKey_21 (16*42) ; HashKey^21 <<1 mod poly %define HashKey_20 (16*43) ; HashKey^20 <<1 mod poly %define HashKey_19 (16*44) ; HashKey^19 <<1 mod poly %define HashKey_18 (16*45) ; HashKey^18 <<1 mod poly %define HashKey_17 (16*46) ; HashKey^17 <<1 mod poly %define HashKey_16 (16*47) ; HashKey^16 <<1 mod poly %define HashKey_15 (16*48) ; HashKey^15 <<1 mod poly %define HashKey_14 (16*49) ; HashKey^14 <<1 mod poly %define HashKey_13 (16*50) ; HashKey^13 <<1 mod poly %define HashKey_12 (16*51) ; HashKey^12 <<1 mod poly %define HashKey_11 (16*52) ; HashKey^11 <<1 mod poly %define HashKey_10 (16*53) ; HashKey^10 <<1 mod poly %define HashKey_9 (16*54) ; HashKey^9 <<1 mod poly %define HashKey_8 (16*55) ; HashKey^8 <<1 mod poly %define HashKey_7 (16*56) ; HashKey^7 <<1 mod poly %define HashKey_6 (16*57) ; HashKey^6 <<1 mod poly %define HashKey_5 (16*58) ; HashKey^5 <<1 mod poly %define HashKey_4 (16*59) ; HashKey^4 <<1 mod poly %define HashKey_3 (16*60) ; HashKey^3 <<1 mod poly %define HashKey_2 (16*61) ; HashKey^2 <<1 mod poly %define HashKey_1 (16*62) ; HashKey <<1 mod poly %define HashKey (16*62) ; HashKey <<1 mod poly %endif ; !GCM_BIG_DATA %endif ; GCM_KEYS_VAES_AVX512_INCLUDED cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/gcm_vaes_avx512.inc000066400000000000000000004701301470420105600267500ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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. ;========================================================================= ; ; Authors: ; Erdinc Ozturk ; Vinodh Gopal ; James Guilford ; Tomasz Kantecki ; ; ; References: ; This code was derived and highly optimized from the code described in paper: ; Vinodh Gopal et. al. Optimized Galois-Counter-Mode Implementation on Intel Architecture Processors. August, 2010 ; The details of the implementation is explained in: ; Erdinc Ozturk et. al. Enabling High-Performance Galois-Counter-Mode on Intel Architecture Processors. October, 2012. ; ; ; ; ; Assumptions: ; ; ; ; iv: ; 0 1 2 3 ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | Salt (From the SA) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | Initialization Vector | ; | (This is the sequence number from IPSec header) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 0x1 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; ; ; AAD: ; AAD will be padded with 0 to the next 16byte multiple ; for example, assume AAD is a u32 vector ; ; if AAD is 8 bytes: ; AAD[3] = {A0, A1}; ; padded AAD in xmm register = {A1 A0 0 0} ; ; 0 1 2 3 ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | SPI (A1) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 32-bit Sequence Number (A0) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 0x0 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; AAD Format with 32-bit Sequence Number ; ; if AAD is 12 bytes: ; AAD[3] = {A0, A1, A2}; ; padded AAD in xmm register = {A2 A1 A0 0} ; ; 0 1 2 3 ; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | SPI (A2) | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 64-bit Extended Sequence Number {A1,A0} | ; | | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; | 0x0 | ; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ; ; AAD Format with 64-bit Extended Sequence Number ; ; ; aadLen: ; Must be a multiple of 4 bytes and from the definition of the spec. ; The code additionally supports any aadLen length. ; ; TLen: ; from the definition of the spec, TLen can only be 8, 12 or 16 bytes. ; ; poly = x^128 + x^127 + x^126 + x^121 + 1 ; throughout the code, one tab and two tab indentations are used. one tab is for GHASH part, two tabs is for AES part. ; %ifndef _GCM_VAES_AVX512_INC_ %define _GCM_VAES_AVX512_INC_ %include "os.inc" %include "reg_sizes.inc" %include "clear_regs.inc" %include "gcm_defines.inc" %include "gcm_keys_vaes_avx512.inc" %include "memcpy.inc" %include "aes_common.inc" %ifndef GCM128_MODE %ifndef GCM192_MODE %ifndef GCM256_MODE %error "No GCM mode selected for gcm_avx512.asm!" %endif %endif %endif ;; Decide on AES-GCM key size to compile for %ifdef GCM128_MODE %define NROUNDS 9 %define FN_NAME(x,y) aes_gcm_ %+ x %+ _128 %+ y %+ vaes_avx512 %endif %ifdef GCM192_MODE %define NROUNDS 11 %define FN_NAME(x,y) aes_gcm_ %+ x %+ _192 %+ y %+ vaes_avx512 %endif %ifdef GCM256_MODE %define NROUNDS 13 %define FN_NAME(x,y) aes_gcm_ %+ x %+ _256 %+ y %+ vaes_avx512 %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Stack frame definition ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %ifidn __OUTPUT_FORMAT__, win64 %define XMM_STORAGE (10*16) ; space for 10 XMM registers %define GP_STORAGE ((9*8) + 24) ; space for 9 GP registers + 24 bytes for 64 byte alignment %else %define XMM_STORAGE 0 %define GP_STORAGE (8*8) ; space for 7 GP registers + 1 for alignment %endif %define LOCAL_STORAGE (48*16) ; space for up to 48 AES blocks ;;; sequence is (bottom-up): GP, XMM, local %define STACK_GP_OFFSET 0 %define STACK_XMM_OFFSET (STACK_GP_OFFSET + GP_STORAGE) %define STACK_LOCAL_OFFSET (STACK_XMM_OFFSET + XMM_STORAGE) %define STACK_FRAME_SIZE (STACK_LOCAL_OFFSET + LOCAL_STORAGE) ;; for compatibility with stack argument definitions in gcm_defines.asm %define STACK_OFFSET 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Utility Macros ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; =========================================================================== ;;; =========================================================================== ;;; Horizontal XOR - 4 x 128bits xored together %macro VHPXORI4x128 2 %define %%REG %1 ; [in/out] ZMM with 4x128bits to xor; 128bit output %define %%TMP %2 ; [clobbered] ZMM temporary register vextracti64x4 YWORD(%%TMP), %%REG, 1 vpxorq YWORD(%%REG), YWORD(%%REG), YWORD(%%TMP) vextracti32x4 XWORD(%%TMP), YWORD(%%REG), 1 vpxorq XWORD(%%REG), XWORD(%%REG), XWORD(%%TMP) %endmacro ; VHPXORI4x128 ;;; =========================================================================== ;;; =========================================================================== ;;; AVX512 reduction macro %macro VCLMUL_REDUCE 6 %define %%OUT %1 ; [out] zmm/ymm/xmm: result (must not be %%TMP1 or %%HI128) %define %%POLY %2 ; [in] zmm/ymm/xmm: polynomial %define %%HI128 %3 ; [in] zmm/ymm/xmm: high 128b of hash to reduce %define %%LO128 %4 ; [in] zmm/ymm/xmm: low 128b of hash to reduce %define %%TMP0 %5 ; [in] zmm/ymm/xmm: temporary register %define %%TMP1 %6 ; [in] zmm/ymm/xmm: temporary register ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; first phase of the reduction vpclmulqdq %%TMP0, %%POLY, %%LO128, 0x01 vpslldq %%TMP0, %%TMP0, 8 ; shift-L 2 DWs vpxorq %%TMP0, %%LO128, %%TMP0 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; second phase of the reduction vpclmulqdq %%TMP1, %%POLY, %%TMP0, 0x00 vpsrldq %%TMP1, %%TMP1, 4 ; shift-R only 1-DW to obtain 2-DWs shift-R vpclmulqdq %%OUT, %%POLY, %%TMP0, 0x10 vpslldq %%OUT, %%OUT, 4 ; shift-L 1-DW to obtain result with no shifts vpternlogq %%OUT, %%TMP1, %%HI128, 0x96 ; OUT/GHASH = OUT xor TMP1 xor HI128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %endmacro ;;; =========================================================================== ;;; =========================================================================== ;;; schoolbook multiply of 16 blocks (8 x 16 bytes) ;;; - it is assumed that data read from %%INPTR is already shuffled and ;;; %%INPTR address is 64 byte aligned ;;; - there is an option to pass ready blocks through ZMM registers too. ;;; 4 extra parameters need to passed in such case and 21st argument can be empty %macro GHASH_16 21-25 %define %%TYPE %1 ; [in] ghash type: start (xor hash), mid, end (same as mid; no reduction), ; end_reduce (end with reduction), start_reduce %define %%GH %2 ; [in/out] ZMM ghash sum: high 128-bits %define %%GM %3 ; [in/out] ZMM ghash sum: middle 128-bits %define %%GL %4 ; [in/out] ZMM ghash sum: low 128-bits %define %%INPTR %5 ; [in] data input pointer %define %%INOFF %6 ; [in] data input offset %define %%INDIS %7 ; [in] data input displacement %define %%HKPTR %8 ; [in] hash key pointer %define %%HKOFF %9 ; [in] hash key offset %define %%HKDIS %10 ; [in] hash key displacement %define %%HASH %11 ; [in/out] ZMM hash value in/out %define %%ZTMP0 %12 ; [clobbered] temporary ZMM %define %%ZTMP1 %13 ; [clobbered] temporary ZMM %define %%ZTMP2 %14 ; [clobbered] temporary ZMM %define %%ZTMP3 %15 ; [clobbered] temporary ZMM %define %%ZTMP4 %16 ; [clobbered] temporary ZMM %define %%ZTMP5 %17 ; [clobbered] temporary ZMM %define %%ZTMP6 %18 ; [clobbered] temporary ZMM %define %%ZTMP7 %19 ; [clobbered] temporary ZMM %define %%ZTMP8 %20 ; [clobbered] temporary ZMM %define %%ZTMP9 %21 ; [clobbered] temporary ZMM %define %%DAT0 %22 ; [in] ZMM with 4 blocks of input data (INPTR, INOFF, INDIS unused) %define %%DAT1 %23 ; [in] ZMM with 4 blocks of input data (INPTR, INOFF, INDIS unused) %define %%DAT2 %24 ; [in] ZMM with 4 blocks of input data (INPTR, INOFF, INDIS unused) %define %%DAT3 %25 ; [in] ZMM with 4 blocks of input data (INPTR, INOFF, INDIS unused) %assign start_ghash 0 %assign do_reduction 0 %ifidn %%TYPE, start %assign start_ghash 1 %endif %ifidn %%TYPE, start_reduce %assign start_ghash 1 %assign do_reduction 1 %endif %ifidn %%TYPE, end_reduce %assign do_reduction 1 %endif ;; ghash blocks 0-3 %if %0 == 21 vmovdqa64 %%ZTMP9, [%%INPTR + %%INOFF + %%INDIS] %else %xdefine %%ZTMP9 %%DAT0 %endif %if start_ghash != 0 vpxorq %%ZTMP9, %%HASH %endif vmovdqu64 %%ZTMP8, [%%HKPTR + %%HKOFF + %%HKDIS] vpclmulqdq %%ZTMP0, %%ZTMP9, %%ZTMP8, 0x11 ; T0H = a1*b1 vpclmulqdq %%ZTMP1, %%ZTMP9, %%ZTMP8, 0x00 ; T0L = a0*b0 vpclmulqdq %%ZTMP2, %%ZTMP9, %%ZTMP8, 0x01 ; T0M1 = a1*b0 vpclmulqdq %%ZTMP3, %%ZTMP9, %%ZTMP8, 0x10 ; T0M2 = a0*b1 ;; ghash blocks 4-7 %if %0 == 21 vmovdqa64 %%ZTMP9, [%%INPTR + %%INOFF + %%INDIS + 64] %else %xdefine %%ZTMP9 %%DAT1 %endif vmovdqu64 %%ZTMP8, [%%HKPTR + %%HKOFF + %%HKDIS + 64] vpclmulqdq %%ZTMP4, %%ZTMP9, %%ZTMP8, 0x11 ; T1H = a1*b1 vpclmulqdq %%ZTMP5, %%ZTMP9, %%ZTMP8, 0x00 ; T1L = a0*b0 vpclmulqdq %%ZTMP6, %%ZTMP9, %%ZTMP8, 0x01 ; T1M1 = a1*b0 vpclmulqdq %%ZTMP7, %%ZTMP9, %%ZTMP8, 0x10 ; T1M2 = a0*b1 ;; update sums %if start_ghash != 0 vpxorq %%GM, %%ZTMP2, %%ZTMP6 ; GM = T0M1 + T1M1 vpxorq %%GH, %%ZTMP0, %%ZTMP4 ; GH = T0H + T1H vpxorq %%GL, %%ZTMP1, %%ZTMP5 ; GL = T0L + T1L vpternlogq %%GM, %%ZTMP3, %%ZTMP7, 0x96 ; GM = T0M2 + T1M1 %else ;; mid, end, end_reduce vpternlogq %%GM, %%ZTMP2, %%ZTMP6, 0x96 ; GM += T0M1 + T1M1 vpternlogq %%GH, %%ZTMP0, %%ZTMP4, 0x96 ; GH += T0H + T1H vpternlogq %%GL, %%ZTMP1, %%ZTMP5, 0x96 ; GL += T0L + T1L vpternlogq %%GM, %%ZTMP3, %%ZTMP7, 0x96 ; GM += T0M2 + T1M1 %endif ;; ghash blocks 8-11 %if %0 == 21 vmovdqa64 %%ZTMP9, [%%INPTR + %%INOFF + %%INDIS + 128] %else %xdefine %%ZTMP9 %%DAT2 %endif vmovdqu64 %%ZTMP8, [%%HKPTR + %%HKOFF + %%HKDIS + 128] vpclmulqdq %%ZTMP0, %%ZTMP9, %%ZTMP8, 0x11 ; T0H = a1*b1 vpclmulqdq %%ZTMP1, %%ZTMP9, %%ZTMP8, 0x00 ; T0L = a0*b0 vpclmulqdq %%ZTMP2, %%ZTMP9, %%ZTMP8, 0x01 ; T0M1 = a1*b0 vpclmulqdq %%ZTMP3, %%ZTMP9, %%ZTMP8, 0x10 ; T0M2 = a0*b1 ;; ghash blocks 12-15 %if %0 == 21 vmovdqa64 %%ZTMP9, [%%INPTR + %%INOFF + %%INDIS + 192] %else %xdefine %%ZTMP9 %%DAT3 %endif vmovdqu64 %%ZTMP8, [%%HKPTR + %%HKOFF + %%HKDIS + 192] vpclmulqdq %%ZTMP4, %%ZTMP9, %%ZTMP8, 0x11 ; T1H = a1*b1 vpclmulqdq %%ZTMP5, %%ZTMP9, %%ZTMP8, 0x00 ; T1L = a0*b0 vpclmulqdq %%ZTMP6, %%ZTMP9, %%ZTMP8, 0x01 ; T1M1 = a1*b0 vpclmulqdq %%ZTMP7, %%ZTMP9, %%ZTMP8, 0x10 ; T1M2 = a0*b1 ;; update sums vpternlogq %%GM, %%ZTMP2, %%ZTMP6, 0x96 ; GM += T0M1 + T1M1 vpternlogq %%GH, %%ZTMP0, %%ZTMP4, 0x96 ; GH += T0H + T1H vpternlogq %%GL, %%ZTMP1, %%ZTMP5, 0x96 ; GL += T0L + T1L vpternlogq %%GM, %%ZTMP3, %%ZTMP7, 0x96 ; GM += T0M2 + T1M1 %if do_reduction != 0 ;; integrate GM into GH and GL vpsrldq %%ZTMP0, %%GM, 8 vpslldq %%ZTMP1, %%GM, 8 vpxorq %%GH, %%GH, %%ZTMP0 vpxorq %%GL, %%GL, %%ZTMP1 ;; add GH and GL 128-bit words horizontally VHPXORI4x128 %%GH, %%ZTMP0 VHPXORI4x128 %%GL, %%ZTMP1 ;; reduction vmovdqa64 XWORD(%%ZTMP2), [rel POLY2] VCLMUL_REDUCE XWORD(%%HASH), XWORD(%%ZTMP2), \ XWORD(%%GH), XWORD(%%GL), XWORD(%%ZTMP0), XWORD(%%ZTMP1) %endif %endmacro ;;; =========================================================================== ;;; =========================================================================== ;;; GHASH 1 to 16 blocks of cipher text ;;; - performs reduction at the end ;;; - it doesn't load the data and it assumed it is already loaded and ;;; shuffled ;;; - single_call scenario only %macro GHASH_1_TO_16 17-20 %define %%KP %1 ; [in] pointer to expanded keys %define %%GHASH %2 ; [out] ghash output %define %%T0H %3 ; [clobbered] temporary ZMM %define %%T0L %4 ; [clobbered] temporary ZMM %define %%T0M1 %5 ; [clobbered] temporary ZMM %define %%T0M2 %6 ; [clobbered] temporary ZMM %define %%T1H %7 ; [clobbered] temporary ZMM %define %%T1L %8 ; [clobbered] temporary ZMM %define %%T1M1 %9 ; [clobbered] temporary ZMM %define %%T1M2 %10 ; [clobbered] temporary ZMM %define %%HK %11 ; [clobbered] temporary ZMM %define %%AAD_HASH_IN %12 ; [in] input hash value %define %%CIPHER_IN0 %13 ; [in] ZMM with cipher text blocks 0-3 %define %%CIPHER_IN1 %14 ; [in] ZMM with cipher text blocks 4-7 %define %%CIPHER_IN2 %15 ; [in] ZMM with cipher text blocks 8-11 %define %%CIPHER_IN3 %16 ; [in] ZMM with cipher text blocks 12-15 %define %%NUM_BLOCKS %17 ; [in] numerical value, number of blocks %define %%GH %18 ; [in] ZMM with hi product part %define %%GM %19 ; [in] ZMM with mid product part %define %%GL %20 ; [in] ZMM with lo product part %assign hashk HashKey_ %+ %%NUM_BLOCKS %if %0 == 17 vpxorq %%CIPHER_IN0, %%CIPHER_IN0, %%AAD_HASH_IN %endif %if %%NUM_BLOCKS == 16 vmovdqu64 %%HK, [%%KP + hashk] vpclmulqdq %%T0H, %%CIPHER_IN0, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T0L, %%CIPHER_IN0, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T0M1, %%CIPHER_IN0, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T0M2, %%CIPHER_IN0, %%HK, 0x10 ; M2 = a0*b1 vmovdqu64 %%HK, [%%KP + hashk + (1*64)] vpclmulqdq %%T1H, %%CIPHER_IN1, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T1L, %%CIPHER_IN1, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T1M1, %%CIPHER_IN1, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T1M2, %%CIPHER_IN1, %%HK, 0x10 ; M2 = a0*b1 vmovdqu64 %%HK, [%%KP + hashk + (2*64)] vpclmulqdq %%CIPHER_IN0, %%CIPHER_IN2, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%CIPHER_IN1, %%CIPHER_IN2, %%HK, 0x00 ; L = a0*b0 vpternlogq %%T0H, %%CIPHER_IN0, %%T1H, 0x96 vpternlogq %%T0L, %%CIPHER_IN1, %%T1L, 0x96 vpclmulqdq %%CIPHER_IN0, %%CIPHER_IN2, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%CIPHER_IN1, %%CIPHER_IN2, %%HK, 0x10 ; M2 = a0*b1 vpternlogq %%T0M1, %%CIPHER_IN0, %%T1M1, 0x96 vpternlogq %%T0M2, %%CIPHER_IN1, %%T1M2, 0x96 vmovdqu64 %%HK, [%%KP + hashk + (3*64)] vpclmulqdq %%T1H, %%CIPHER_IN3, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T1L, %%CIPHER_IN3, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T1M1, %%CIPHER_IN3, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T1M2, %%CIPHER_IN3, %%HK, 0x10 ; M2 = a0*b1 vpxorq %%T1H, %%T0H, %%T1H vpxorq %%T1L, %%T0L, %%T1L vpxorq %%T1M1, %%T0M1, %%T1M1 vpxorq %%T1M2, %%T0M2, %%T1M2 %elif %%NUM_BLOCKS >= 12 vmovdqu64 %%HK, [%%KP + hashk] vpclmulqdq %%T0H, %%CIPHER_IN0, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T0L, %%CIPHER_IN0, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T0M1, %%CIPHER_IN0, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T0M2, %%CIPHER_IN0, %%HK, 0x10 ; M2 = a0*b1 vmovdqu64 %%HK, [%%KP + hashk + (1*64)] vpclmulqdq %%T1H, %%CIPHER_IN1, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T1L, %%CIPHER_IN1, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T1M1, %%CIPHER_IN1, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T1M2, %%CIPHER_IN1, %%HK, 0x10 ; M2 = a0*b1 vmovdqu64 %%HK, [%%KP + hashk + (2*64)] vpclmulqdq %%CIPHER_IN0, %%CIPHER_IN2, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%CIPHER_IN1, %%CIPHER_IN2, %%HK, 0x00 ; L = a0*b0 vpternlogq %%T1H, %%CIPHER_IN0, %%T0H, 0x96 vpternlogq %%T1L, %%CIPHER_IN1, %%T0L, 0x96 vpclmulqdq %%CIPHER_IN0, %%CIPHER_IN2, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%CIPHER_IN1, %%CIPHER_IN2, %%HK, 0x10 ; M2 = a0*b1 vpternlogq %%T1M1, %%CIPHER_IN0, %%T0M1, 0x96 vpternlogq %%T1M2, %%CIPHER_IN1, %%T0M2, 0x96 %elif %%NUM_BLOCKS >= 8 vmovdqu64 %%HK, [%%KP + hashk] vpclmulqdq %%T0H, %%CIPHER_IN0, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T0L, %%CIPHER_IN0, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T0M1, %%CIPHER_IN0, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T0M2, %%CIPHER_IN0, %%HK, 0x10 ; M2 = a0*b1 vmovdqu64 %%HK, [%%KP + hashk + (1*64)] vpclmulqdq %%T1H, %%CIPHER_IN1, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T1L, %%CIPHER_IN1, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T1M1, %%CIPHER_IN1, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T1M2, %%CIPHER_IN1, %%HK, 0x10 ; M2 = a0*b1 vpxorq %%T1H, %%T0H, %%T1H vpxorq %%T1L, %%T0L, %%T1L vpxorq %%T1M1, %%T0M1, %%T1M1 vpxorq %%T1M2, %%T0M2, %%T1M2 %elif %%NUM_BLOCKS >= 4 vmovdqu64 %%HK, [%%KP + hashk] vpclmulqdq %%T1H, %%CIPHER_IN0, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T1L, %%CIPHER_IN0, %%HK, 0x00 ; L = a0*b0 vpclmulqdq %%T1M1, %%CIPHER_IN0, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T1M2, %%CIPHER_IN0, %%HK, 0x10 ; M2 = a0*b1 %endif ;; T1H/L/M1/M2 - hold current product sums (provided %%NUM_BLOCKS >= 4) %assign blocks_left (%%NUM_BLOCKS % 4) %if blocks_left > 0 ;; ===================================================== ;; There are 1, 2 or 3 blocks left to process. ;; It may also be that they are the only blocks to process. ;; Set hash key and register index position for the remaining 1 to 3 blocks %assign hashk HashKey_ %+ blocks_left %assign reg_idx (%%NUM_BLOCKS / 4) %xdefine %%REG_IN %%CIPHER_IN %+ reg_idx %if blocks_left == 1 vmovdqu64 XWORD(%%HK), [%%KP + hashk] vpclmulqdq XWORD(%%T0M1), XWORD(%%REG_IN), XWORD(%%HK), 0x01 ; M1 = a1*b0 vpclmulqdq XWORD(%%T0M2), XWORD(%%REG_IN), XWORD(%%HK), 0x10 ; M2 = a0*b1 vpclmulqdq XWORD(%%T0H), XWORD(%%REG_IN), XWORD(%%HK), 0x11 ; H = a1*b1 vpclmulqdq XWORD(%%T0L), XWORD(%%REG_IN), XWORD(%%HK), 0x00 ; L = a0*b0 %elif blocks_left == 2 vmovdqu64 YWORD(%%HK), [%%KP + hashk] vpclmulqdq YWORD(%%T0M1), YWORD(%%REG_IN), YWORD(%%HK), 0x01 ; M1 = a1*b0 vpclmulqdq YWORD(%%T0M2), YWORD(%%REG_IN), YWORD(%%HK), 0x10 ; M2 = a0*b1 vpclmulqdq YWORD(%%T0H), YWORD(%%REG_IN), YWORD(%%HK), 0x11 ; H = a1*b1 vpclmulqdq YWORD(%%T0L), YWORD(%%REG_IN), YWORD(%%HK), 0x00 ; L = a0*b0 %else ; blocks_left == 3 vmovdqu64 YWORD(%%HK), [%%KP + hashk] vinserti64x2 %%HK, [%%KP + hashk + 32], 2 vpclmulqdq %%T0M1, %%REG_IN, %%HK, 0x01 ; M1 = a1*b0 vpclmulqdq %%T0M2, %%REG_IN, %%HK, 0x10 ; M2 = a0*b1 vpclmulqdq %%T0H, %%REG_IN, %%HK, 0x11 ; H = a1*b1 vpclmulqdq %%T0L, %%REG_IN, %%HK, 0x00 ; L = a0*b0 %endif ; blocks_left %undef %%REG_IN %if %0 == 20 ;; *** GH/GM/GL passed as arguments %if %%NUM_BLOCKS >= 4 ;; add ghash product sums from the first 4, 8 or 12 blocks vpxorq %%T0M1, %%T0M1, %%T1M1 vpternlogq %%T0M2, %%GM, %%T1M2, 0x96 vpternlogq %%T0H, %%GH, %%T1H, 0x96 vpternlogq %%T0L, %%GL, %%T1L, 0x96 %else vpxorq %%T0M1, %%T0M1, %%GM vpxorq %%T0H, %%T0H, %%GH vpxorq %%T0L, %%T0L, %%GL %endif ;; %%NUM_BLOCKS >= 4 %else ;; *** GH/GM/GL NOT passed as arguments %if %%NUM_BLOCKS >= 4 ;; add ghash product sums from the first 4, 8 or 12 blocks vpxorq %%T0M1, %%T0M1, %%T1M1 vpxorq %%T0M2, %%T0M2, %%T1M2 vpxorq %%T0H, %%T0H, %%T1H vpxorq %%T0L, %%T0L, %%T1L %endif ;; %%NUM_BLOCKS >= 4 %endif ;; %0 == 20 ;; integrate TM into TH and TL vpxorq %%T0M1, %%T0M1, %%T0M2 vpsrldq %%T1M1, %%T0M1, 8 vpslldq %%T1M2, %%T0M1, 8 vpxorq %%T0H, %%T0H, %%T1M1 vpxorq %%T0L, %%T0L, %%T1M2 %else ;; ===================================================== ;; number of blocks is 4, 8, 12 or 16 ;; T1H/L/M1/M2 include product sums not T0H/L/M1/M2 %if %0 == 20 ;; *** GH/GM/GL passed as arguments vpxorq %%T1M1, %%T1M1, %%GM vpxorq %%T1H, %%T1H, %%GH vpxorq %%T1L, %%T1L, %%GL %endif ;; integrate TM into TH and TL vpxorq %%T1M1, %%T1M1, %%T1M2 vpsrldq %%T0M1, %%T1M1, 8 vpslldq %%T0M2, %%T1M1, 8 vpxorq %%T0H, %%T1H, %%T0M1 vpxorq %%T0L, %%T1L, %%T0M2 %endif ; blocks_left > 0 ;; add TH and TL 128-bit words horizontally VHPXORI4x128 %%T0H, %%T1M1 VHPXORI4x128 %%T0L, %%T1M2 ;; reduction vmovdqa64 XWORD(%%HK), [rel POLY2] VCLMUL_REDUCE XWORD(%%GHASH), XWORD(%%HK), \ XWORD(%%T0H), XWORD(%%T0L), XWORD(%%T0M1), XWORD(%%T0M2) %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; GHASH_MUL MACRO to implement: Data*HashKey mod (128,127,126,121,0) ;;; Input: A and B (128-bits each, bit-reflected) ;;; Output: C = A*B*x mod poly, (i.e. >>1 ) ;;; To compute GH = GH*HashKey mod poly, give HK = HashKey<<1 mod poly as input ;;; GH = GH * HK * x mod poly which is equivalent to GH*HashKey mod poly. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GHASH_MUL 7 %define %%GH %1 ;; [in/out] xmm/ymm/zmm with multiply operand(s) (128-bits) %define %%HK %2 ;; [in] xmm/ymm/zmm with hash key value(s) (128-bits) %define %%T1 %3 ;; [clobbered] xmm/ymm/zmm %define %%T2 %4 ;; [clobbered] xmm/ymm/zmm %define %%T3 %5 ;; [clobbered] xmm/ymm/zmm %define %%T4 %6 ;; [clobbered] xmm/ymm/zmm %define %%T5 %7 ;; [clobbered] xmm/ymm/zmm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpclmulqdq %%T1, %%GH, %%HK, 0x11 ; %%T1 = a1*b1 vpclmulqdq %%T2, %%GH, %%HK, 0x00 ; %%T2 = a0*b0 vpclmulqdq %%T3, %%GH, %%HK, 0x01 ; %%T3 = a1*b0 vpclmulqdq %%GH, %%GH, %%HK, 0x10 ; %%GH = a0*b1 vpxorq %%GH, %%GH, %%T3 vpsrldq %%T3, %%GH, 8 ; shift-R %%GH 2 DWs vpslldq %%GH, %%GH, 8 ; shift-L %%GH 2 DWs vpxorq %%T1, %%T1, %%T3 vpxorq %%GH, %%GH, %%T2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction vmovdqu64 %%T3, [rel POLY2] vpclmulqdq %%T2, %%T3, %%GH, 0x01 vpslldq %%T2, %%T2, 8 ; shift-L %%T2 2 DWs vpxorq %%GH, %%GH, %%T2 ; first phase of the reduction complete ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;second phase of the reduction vpclmulqdq %%T2, %%T3, %%GH, 0x00 vpsrldq %%T2, %%T2, 4 ; shift-R only 1-DW to obtain 2-DWs shift-R vpclmulqdq %%GH, %%T3, %%GH, 0x10 vpslldq %%GH, %%GH, 4 ; Shift-L 1-DW to obtain result with no shifts ; second phase of the reduction complete, the result is in %%GH vpternlogq %%GH, %%T1, %%T2, 0x96 ; GH = GH xor T1 xor T2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; In PRECOMPUTE, the commands filling Hashkey_i_k are not required for avx512 ;;; functions, but are kept to allow users to switch cpu architectures between calls ;;; of pre, init, update, and finalize. %macro PRECOMPUTE 10 %define %%GDATA %1 ;; [in/out] GPR, pointer to GCM key data structure, content updated %define %%HK %2 ;; [in] xmm, hash key %define %%T1 %3 ;; [clobbered] xmm %define %%T2 %4 ;; [clobbered] xmm %define %%T3 %5 ;; [clobbered] xmm %define %%T4 %6 ;; [clobbered] xmm %define %%T5 %7 ;; [clobbered] xmm %define %%T6 %8 ;; [clobbered] xmm %define %%T7 %9 ;; [clobbered] xmm %define %%T8 %10 ;; [clobbered] xmm %xdefine %%ZT1 ZWORD(%%T1) %xdefine %%ZT2 ZWORD(%%T2) %xdefine %%ZT3 ZWORD(%%T3) %xdefine %%ZT4 ZWORD(%%T4) %xdefine %%ZT5 ZWORD(%%T5) %xdefine %%ZT6 ZWORD(%%T6) %xdefine %%ZT7 ZWORD(%%T7) %xdefine %%ZT8 ZWORD(%%T8) vmovdqa64 %%T5, %%HK vinserti64x2 %%ZT7, %%HK, 3 ;; calculate HashKey^2<<1 mod poly GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 vmovdqu64 [%%GDATA + HashKey_2], %%T5 vinserti64x2 %%ZT7, %%T5, 2 ;; calculate HashKey^3<<1 mod poly GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 vmovdqu64 [%%GDATA + HashKey_3], %%T5 vinserti64x2 %%ZT7, %%T5, 1 ;; calculate HashKey^4<<1 mod poly GHASH_MUL %%T5, %%HK, %%T1, %%T3, %%T4, %%T6, %%T2 vmovdqu64 [%%GDATA + HashKey_4], %%T5 vinserti64x2 %%ZT7, %%T5, 0 ;; switch to 4x128-bit computations now vshufi64x2 %%ZT5, %%ZT5, %%ZT5, 0x00 ;; broadcast HashKey^4 across all ZT5 vmovdqa64 %%ZT8, %%ZT7 ;; save HashKey^4 to HashKey^1 in ZT8 ;; calculate HashKey^5<<1 mod poly, HashKey^6<<1 mod poly, ... HashKey^8<<1 mod poly GHASH_MUL %%ZT7, %%ZT5, %%ZT1, %%ZT3, %%ZT4, %%ZT6, %%ZT2 vmovdqu64 [%%GDATA + HashKey_8], %%ZT7 ;; HashKey^8 to HashKey^5 in ZT7 now vshufi64x2 %%ZT5, %%ZT7, %%ZT7, 0x00 ;; broadcast HashKey^8 across all ZT5 ;; calculate HashKey^9<<1 mod poly, HashKey^10<<1 mod poly, ... HashKey^48<<1 mod poly ;; use HashKey^8 as multiplier against ZT8 and ZT7 - this allows deeper ooo execution %assign i 12 %rep ((48 - 8) / 8) ;; compute HashKey^(4 + n), HashKey^(3 + n), ... HashKey^(1 + n) GHASH_MUL %%ZT8, %%ZT5, %%ZT1, %%ZT3, %%ZT4, %%ZT6, %%ZT2 vmovdqu64 [%%GDATA + HashKey_ %+ i], %%ZT8 %assign i (i + 4) ;; compute HashKey^(8 + n), HashKey^(7 + n), ... HashKey^(5 + n) GHASH_MUL %%ZT7, %%ZT5, %%ZT1, %%ZT3, %%ZT4, %%ZT6, %%ZT2 vmovdqu64 [%%GDATA + HashKey_ %+ i], %%ZT7 %assign i (i + 4) %endrep %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; READ_SMALL_DATA_INPUT ;;; Packs xmm register with data when data input is less or equal to 16 bytes ;;; Returns 0 if data has length 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro READ_SMALL_DATA_INPUT 6 %define %%OUTPUT %1 ; [out] xmm register %define %%INPUT %2 ; [in] buffer pointer to read from %define %%LENGTH %3 ; [in] number of bytes to read %define %%TMP1 %4 ; [clobbered] %define %%TMP2 %5 ; [clobbered] %define %%MASK %6 ; [out] k1 to k7 register to store the partial block mask mov DWORD(%%TMP2), 16 lea %%TMP1, [rel byte_len_to_mask_table] cmp %%LENGTH, %%TMP2 cmovb %%TMP2, %%LENGTH %ifidn __OUTPUT_FORMAT__, win64 add %%TMP1, %%TMP2 add %%TMP1, %%TMP2 kmovw %%MASK, [%%TMP1] %else kmovw %%MASK, [%%TMP1 + %%TMP2*2] %endif vmovdqu8 %%OUTPUT{%%MASK}{z}, [%%INPUT] %endmacro ; READ_SMALL_DATA_INPUT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; CALC_AAD_HASH: Calculates the hash of the data which will not be encrypted. ; Input: The input data (A_IN), that data's length (A_LEN), and the hash key (HASH_KEY). ; Output: The hash of the data (AAD_HASH). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro CALC_AAD_HASH 26 %define %%A_IN %1 ; [in] AAD text pointer %define %%A_LEN %2 ; [in] AAD length %define %%AAD_HASH %3 ; [in/out] xmm ghash value %define %%GDATA_KEY %4 ; [in] pointer to keys %define %%ZT0 %5 ; [clobbered] ZMM register %define %%ZT1 %6 ; [clobbered] ZMM register %define %%ZT2 %7 ; [clobbered] ZMM register %define %%ZT3 %8 ; [clobbered] ZMM register %define %%ZT4 %9 ; [clobbered] ZMM register %define %%ZT5 %10 ; [clobbered] ZMM register %define %%ZT6 %11 ; [clobbered] ZMM register %define %%ZT7 %12 ; [clobbered] ZMM register %define %%ZT8 %13 ; [clobbered] ZMM register %define %%ZT9 %14 ; [clobbered] ZMM register %define %%ZT10 %15 ; [clobbered] ZMM register %define %%ZT11 %16 ; [clobbered] ZMM register %define %%ZT12 %17 ; [clobbered] ZMM register %define %%ZT13 %18 ; [clobbered] ZMM register %define %%ZT14 %19 ; [clobbered] ZMM register %define %%ZT15 %20 ; [clobbered] ZMM register %define %%ZT16 %21 ; [clobbered] ZMM register %define %%ZT17 %22 ; [clobbered] ZMM register %define %%T1 %23 ; [clobbered] GP register %define %%T2 %24 ; [clobbered] GP register %define %%T3 %25 ; [clobbered] GP register %define %%MASKREG %26 ; [clobbered] mask register %define %%SHFMSK %%ZT13 mov %%T1, %%A_IN ; T1 = AAD mov %%T2, %%A_LEN ; T2 = aadLen or %%T2, %%T2 jz %%_CALC_AAD_done vmovdqa64 %%SHFMSK, [rel SHUF_MASK] %%_get_AAD_loop48x16: cmp %%T2, (48*16) jl %%_exit_AAD_loop48x16 vmovdqu64 %%ZT1, [%%T1 + 64*0] ; Blocks 0-3 vmovdqu64 %%ZT2, [%%T1 + 64*1] ; Blocks 4-7 vmovdqu64 %%ZT3, [%%T1 + 64*2] ; Blocks 8-11 vmovdqu64 %%ZT4, [%%T1 + 64*3] ; Blocks 12-15 vpshufb %%ZT1, %%SHFMSK vpshufb %%ZT2, %%SHFMSK vpshufb %%ZT3, %%SHFMSK vpshufb %%ZT4, %%SHFMSK GHASH_16 start, %%ZT5, %%ZT6, %%ZT7, \ NO_INPUT_PTR, NO_INPUT_PTR, NO_INPUT_PTR, \ %%GDATA_KEY, HashKey_48, 0, ZWORD(%%AAD_HASH), \ %%ZT0, %%ZT8, %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ %%ZT14, %%ZT15, %%ZT16, NO_ZMM, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4 vmovdqu64 %%ZT1, [%%T1 + 16*16 + 64*0] ; Blocks 16-19 vmovdqu64 %%ZT2, [%%T1 + 16*16 + 64*1] ; Blocks 20-23 vmovdqu64 %%ZT3, [%%T1 + 16*16 + 64*2] ; Blocks 24-27 vmovdqu64 %%ZT4, [%%T1 + 16*16 + 64*3] ; Blocks 28-31 vpshufb %%ZT1, %%SHFMSK vpshufb %%ZT2, %%SHFMSK vpshufb %%ZT3, %%SHFMSK vpshufb %%ZT4, %%SHFMSK GHASH_16 mid, %%ZT5, %%ZT6, %%ZT7, \ NO_INPUT_PTR, NO_INPUT_PTR, NO_INPUT_PTR, \ %%GDATA_KEY, HashKey_32, 0, NO_HASH_IN_OUT, \ %%ZT0, %%ZT8, %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ %%ZT14, %%ZT15, %%ZT16, NO_ZMM, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4 vmovdqu64 %%ZT1, [%%T1 + 32*16 + 64*0] ; Blocks 32-35 vmovdqu64 %%ZT2, [%%T1 + 32*16 + 64*1] ; Blocks 36-39 vmovdqu64 %%ZT3, [%%T1 + 32*16 + 64*2] ; Blocks 40-43 vmovdqu64 %%ZT4, [%%T1 + 32*16 + 64*3] ; Blocks 44-47 vpshufb %%ZT1, %%SHFMSK vpshufb %%ZT2, %%SHFMSK vpshufb %%ZT3, %%SHFMSK vpshufb %%ZT4, %%SHFMSK GHASH_16 end_reduce, %%ZT5, %%ZT6, %%ZT7, \ NO_INPUT_PTR, NO_INPUT_PTR, NO_INPUT_PTR, \ %%GDATA_KEY, HashKey_16, 0, ZWORD(%%AAD_HASH), \ %%ZT0, %%ZT8, %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ %%ZT14, %%ZT15, %%ZT16, NO_ZMM, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4 sub %%T2, (48*16) je %%_CALC_AAD_done add %%T1, (48*16) jmp %%_get_AAD_loop48x16 %%_exit_AAD_loop48x16: ; Less than 48x16 bytes remaining cmp %%T2, (32*16) jl %%_less_than_32x16 ; Get next 16 blocks vmovdqu64 %%ZT1, [%%T1 + 64*0] vmovdqu64 %%ZT2, [%%T1 + 64*1] vmovdqu64 %%ZT3, [%%T1 + 64*2] vmovdqu64 %%ZT4, [%%T1 + 64*3] vpshufb %%ZT1, %%SHFMSK vpshufb %%ZT2, %%SHFMSK vpshufb %%ZT3, %%SHFMSK vpshufb %%ZT4, %%SHFMSK GHASH_16 start, %%ZT5, %%ZT6, %%ZT7, \ NO_INPUT_PTR, NO_INPUT_PTR, NO_INPUT_PTR, \ %%GDATA_KEY, HashKey_32, 0, ZWORD(%%AAD_HASH), \ %%ZT0, %%ZT8, %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ %%ZT14, %%ZT15, %%ZT16, NO_ZMM, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4 vmovdqu64 %%ZT1, [%%T1 + 16*16 + 64*0] vmovdqu64 %%ZT2, [%%T1 + 16*16 + 64*1] vmovdqu64 %%ZT3, [%%T1 + 16*16 + 64*2] vmovdqu64 %%ZT4, [%%T1 + 16*16 + 64*3] vpshufb %%ZT1, %%SHFMSK vpshufb %%ZT2, %%SHFMSK vpshufb %%ZT3, %%SHFMSK vpshufb %%ZT4, %%SHFMSK GHASH_16 end_reduce, %%ZT5, %%ZT6, %%ZT7, \ NO_INPUT_PTR, NO_INPUT_PTR, NO_INPUT_PTR, \ %%GDATA_KEY, HashKey_16, 0, ZWORD(%%AAD_HASH), \ %%ZT0, %%ZT8, %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ %%ZT14, %%ZT15, %%ZT16, NO_ZMM, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4 sub %%T2, (32*16) je %%_CALC_AAD_done add %%T1, (32*16) jmp %%_less_than_16x16 %%_less_than_32x16: cmp %%T2, (16*16) jl %%_less_than_16x16 ; Get next 16 blocks vmovdqu64 %%ZT1, [%%T1 + 64*0] vmovdqu64 %%ZT2, [%%T1 + 64*1] vmovdqu64 %%ZT3, [%%T1 + 64*2] vmovdqu64 %%ZT4, [%%T1 + 64*3] vpshufb %%ZT1, %%SHFMSK vpshufb %%ZT2, %%SHFMSK vpshufb %%ZT3, %%SHFMSK vpshufb %%ZT4, %%SHFMSK GHASH_16 start_reduce, %%ZT5, %%ZT6, %%ZT7, \ NO_INPUT_PTR, NO_INPUT_PTR, NO_INPUT_PTR, \ %%GDATA_KEY, HashKey_16, 0, ZWORD(%%AAD_HASH), \ %%ZT0, %%ZT8, %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ %%ZT14, %%ZT15, %%ZT16, NO_ZMM, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4 sub %%T2, (16*16) je %%_CALC_AAD_done add %%T1, (16*16) ; Less than 16x16 bytes remaining %%_less_than_16x16: ;; prep mask source address lea %%T3, [rel byte64_len_to_mask_table] lea %%T3, [%%T3 + %%T2*8] ;; calculate number of blocks to ghash (including partial bytes) add DWORD(%%T2), 15 shr DWORD(%%T2), 4 cmp DWORD(%%T2), 2 jb %%_AAD_blocks_1 je %%_AAD_blocks_2 cmp DWORD(%%T2), 4 jb %%_AAD_blocks_3 je %%_AAD_blocks_4 cmp DWORD(%%T2), 6 jb %%_AAD_blocks_5 je %%_AAD_blocks_6 cmp DWORD(%%T2), 8 jb %%_AAD_blocks_7 je %%_AAD_blocks_8 cmp DWORD(%%T2), 10 jb %%_AAD_blocks_9 je %%_AAD_blocks_10 cmp DWORD(%%T2), 12 jb %%_AAD_blocks_11 je %%_AAD_blocks_12 cmp DWORD(%%T2), 14 jb %%_AAD_blocks_13 je %%_AAD_blocks_14 cmp DWORD(%%T2), 15 je %%_AAD_blocks_15 ;; fall through for 16 blocks ;; The flow of each of these cases is identical: ;; - load blocks plain text ;; - shuffle loaded blocks ;; - xor in current hash value into block 0 ;; - perform up multiplications with ghash keys ;; - jump to reduction code %assign I 16 ;; generate all 16 cases using preprocessor %rep 16 %%_AAD_blocks_ %+ I: %if I > 12 sub %%T3, 12 * 16 * 8 %elif I > 8 sub %%T3, 8 * 16 * 8 %elif I > 4 sub %%T3, 4 * 16 * 8 %endif kmovq %%MASKREG, [%%T3] ZMM_LOAD_MASKED_BLOCKS_0_16 \ I, %%T1, 0, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4, %%MASKREG ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 \ I, vpshufb, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%SHFMSK, %%SHFMSK, %%SHFMSK, %%SHFMSK GHASH_1_TO_16 %%GDATA_KEY, ZWORD(%%AAD_HASH), \ %%ZT0, %%ZT5, %%ZT6, %%ZT7, %%ZT8, \ %%ZT9, %%ZT10, %%ZT11, %%ZT12, \ ZWORD(%%AAD_HASH), %%ZT1, %%ZT2, %%ZT3, %%ZT4, I %if I > 1 ;; fall through to CALC_AAD_done in 1 block case jmp %%_CALC_AAD_done %endif %assign I (I - 1) %endrep %%_CALC_AAD_done: ;; result in AAD_HASH %endmacro ; CALC_AAD_HASH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; PARTIAL_BLOCK ;;; Handles encryption/decryption and the tag partial blocks between ;;; update calls. ;;; Requires the input data be at least 1 byte long. ;;; Output: ;;; A cipher/plain of the first partial block (CIPH_PLAIN_OUT), ;;; AAD_HASH and updated GDATA_CTX ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro PARTIAL_BLOCK 22 %define %%GDATA_KEY %1 ; [in] key pointer %define %%GDATA_CTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] output buffer %define %%PLAIN_CIPH_IN %4 ; [in] input buffer %define %%PLAIN_CIPH_LEN %5 ; [in] buffer length %define %%DATA_OFFSET %6 ; [out] data offset (gets set) %define %%AAD_HASH %7 ; [out] updated GHASH value %define %%ENC_DEC %8 ; [in] cipher direction %define %%GPTMP0 %9 ; [clobbered] GP temporary register %define %%GPTMP1 %10 ; [clobbered] GP temporary register %define %%GPTMP2 %11 ; [clobbered] GP temporary register %define %%ZTMP0 %12 ; [clobbered] ZMM temporary register %define %%ZTMP1 %13 ; [clobbered] ZMM temporary register %define %%ZTMP2 %14 ; [clobbered] ZMM temporary register %define %%ZTMP3 %15 ; [clobbered] ZMM temporary register %define %%ZTMP4 %16 ; [clobbered] ZMM temporary register %define %%ZTMP5 %17 ; [clobbered] ZMM temporary register %define %%ZTMP6 %18 ; [clobbered] ZMM temporary register %define %%ZTMP7 %19 ; [clobbered] ZMM temporary register %define %%ZTMP8 %20 ; [clobbered] ZMM temporary register %define %%ZTMP9 %21 ; [clobbered] ZMM temporary register %define %%MASKREG %22 ; [clobbered] mask temporary register %define %%XTMP0 XWORD(%%ZTMP0) %define %%XTMP1 XWORD(%%ZTMP1) %define %%XTMP2 XWORD(%%ZTMP2) %define %%XTMP3 XWORD(%%ZTMP3) %define %%XTMP4 XWORD(%%ZTMP4) %define %%XTMP5 XWORD(%%ZTMP5) %define %%XTMP6 XWORD(%%ZTMP6) %define %%XTMP7 XWORD(%%ZTMP7) %define %%XTMP8 XWORD(%%ZTMP8) %define %%XTMP9 XWORD(%%ZTMP9) %define %%LENGTH %%DATA_OFFSET %define %%IA0 %%GPTMP1 %define %%IA1 %%GPTMP2 %define %%IA2 %%GPTMP0 ;; if no partial block present then LENGTH/DATA_OFFSET will be set to zero mov %%LENGTH, [%%GDATA_CTX + PBlockLen] or %%LENGTH, %%LENGTH je %%_partial_block_done ;Leave Macro if no partial blocks READ_SMALL_DATA_INPUT %%XTMP0, %%PLAIN_CIPH_IN, %%PLAIN_CIPH_LEN, %%IA0, %%IA2, %%MASKREG ;; XTMP1 = my_ctx_data.partial_block_enc_key vmovdqu64 %%XTMP1, [%%GDATA_CTX + PBlockEncKey] vmovdqu64 %%XTMP2, [%%GDATA_KEY + HashKey] ;; adjust the shuffle mask pointer to be able to shift right %%LENGTH bytes ;; (16 - %%LENGTH) is the number of bytes in plaintext mod 16) lea %%IA0, [rel SHIFT_MASK] add %%IA0, %%LENGTH vmovdqu64 %%XTMP3, [%%IA0] ; shift right shuffle mask vpshufb %%XTMP1, %%XTMP3 %ifidn %%ENC_DEC, DEC ;; keep copy of cipher text in %%XTMP4 vmovdqa64 %%XTMP4, %%XTMP0 %endif vpxorq %%XTMP1, %%XTMP0 ; Ciphertext XOR E(K, Yn) ;; Set %%IA1 to be the amount of data left in CIPH_PLAIN_IN after filling the block ;; Determine if partial block is not being filled and shift mask accordingly %ifidn __OUTPUT_FORMAT__, win64 mov %%IA1, %%PLAIN_CIPH_LEN add %%IA1, %%LENGTH %else lea %%IA1, [%%PLAIN_CIPH_LEN + %%LENGTH] %endif sub %%IA1, 16 jge %%_no_extra_mask sub %%IA0, %%IA1 %%_no_extra_mask: ;; get the appropriate mask to mask out bottom %%LENGTH bytes of %%XTMP1 ;; - mask out bottom %%LENGTH bytes of %%XTMP1 vmovdqu64 %%XTMP0, [%%IA0 + ALL_F - SHIFT_MASK] vpand %%XTMP1, %%XTMP0 %ifidn %%ENC_DEC, DEC vpand %%XTMP4, %%XTMP0 vpshufb %%XTMP4, [rel SHUF_MASK] vpshufb %%XTMP4, %%XTMP3 vpxorq %%AAD_HASH, %%XTMP4 %else vpshufb %%XTMP1, [rel SHUF_MASK] vpshufb %%XTMP1, %%XTMP3 vpxorq %%AAD_HASH, %%XTMP1 %endif cmp %%IA1, 0 jl %%_partial_incomplete ;; GHASH computation for the last <16 Byte block GHASH_MUL %%AAD_HASH, %%XTMP2, %%XTMP5, %%XTMP6, %%XTMP7, %%XTMP8, %%XTMP9 mov qword [%%GDATA_CTX + PBlockLen], 0 ;; Set %%LENGTH to be the number of bytes to write out mov %%IA0, %%LENGTH mov %%LENGTH, 16 sub %%LENGTH, %%IA0 jmp %%_enc_dec_done %%_partial_incomplete: %ifidn __OUTPUT_FORMAT__, win64 mov %%IA0, %%PLAIN_CIPH_LEN add [%%GDATA_CTX + PBlockLen], %%IA0 %else add [%%GDATA_CTX + PBlockLen], %%PLAIN_CIPH_LEN %endif mov %%LENGTH, %%PLAIN_CIPH_LEN %%_enc_dec_done: ;; output encrypted Bytes lea %%IA0, [rel byte_len_to_mask_table] kmovw %%MASKREG, [%%IA0 + %%LENGTH*2] vmovdqu64 [%%GDATA_CTX + AadHash], %%AAD_HASH %ifidn %%ENC_DEC, ENC ;; shuffle XTMP1 back to output as ciphertext vpshufb %%XTMP1, [rel SHUF_MASK] vpshufb %%XTMP1, %%XTMP3 %endif vmovdqu8 [%%CIPH_PLAIN_OUT]{%%MASKREG}, %%XTMP1 %%_partial_block_done: %endmacro ; PARTIAL_BLOCK ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Ciphers 1 to 16 blocks and prepares them for later GHASH compute operation %macro INITIAL_BLOCKS_PARTIAL_CIPHER 25 %define %%GDATA_KEY %1 ; [in] key pointer %define %%GDATA_CTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] text output pointer %define %%PLAIN_CIPH_IN %4 ; [in] text input pointer %define %%LENGTH %5 ; [in/clobbered] length in bytes %define %%DATA_OFFSET %6 ; [in/out] current data offset (updated) %define %%NUM_BLOCKS %7 ; [in] can only be 1, 2, 3, 4, 5, ..., 15 or 16 (not 0) %define %%CTR %8 ; [in/out] current counter value %define %%ENC_DEC %9 ; [in] cipher direction (ENC/DEC) %define %%INSTANCE_TYPE %10 ; [in] multi_call or single_call %define %%DAT0 %11 ; [out] ZMM with cipher text shuffled for GHASH %define %%DAT1 %12 ; [out] ZMM with cipher text shuffled for GHASH %define %%DAT2 %13 ; [out] ZMM with cipher text shuffled for GHASH %define %%DAT3 %14 ; [out] ZMM with cipher text shuffled for GHASH %define %%LAST_CIPHER_BLK %15 ; [out] XMM to put ciphered counter block partially xor'ed with text %define %%LAST_GHASH_BLK %16 ; [out] XMM to put last cipher text block shuffled for GHASH %define %%CTR0 %17 ; [clobbered] ZMM temporary %define %%CTR1 %18 ; [clobbered] ZMM temporary %define %%CTR2 %19 ; [clobbered] ZMM temporary %define %%CTR3 %20 ; [clobbered] ZMM temporary %define %%ZT1 %21 ; [clobbered] ZMM temporary %define %%IA0 %22 ; [clobbered] GP temporary %define %%IA1 %23 ; [clobbered] GP temporary %define %%MASKREG %24 ; [clobbered] mask register %define %%SHUFMASK %25 ; [out] ZMM loaded with BE/LE shuffle mask %if %%NUM_BLOCKS == 1 vmovdqa64 XWORD(%%SHUFMASK), [rel SHUF_MASK] %elif %%NUM_BLOCKS == 2 vmovdqa64 YWORD(%%SHUFMASK), [rel SHUF_MASK] %else vmovdqa64 %%SHUFMASK, [rel SHUF_MASK] %endif ;; prepare AES counter blocks %if %%NUM_BLOCKS == 1 vpaddd XWORD(%%CTR0), %%CTR, [rel ONE] %elif %%NUM_BLOCKS == 2 vshufi64x2 YWORD(%%CTR0), YWORD(%%CTR), YWORD(%%CTR), 0 vpaddd YWORD(%%CTR0), YWORD(%%CTR0), [rel ddq_add_1234] %else vshufi64x2 ZWORD(%%CTR), ZWORD(%%CTR), ZWORD(%%CTR), 0 vpaddd %%CTR0, ZWORD(%%CTR), [rel ddq_add_1234] %if %%NUM_BLOCKS > 4 vpaddd %%CTR1, ZWORD(%%CTR), [rel ddq_add_5678] %endif %if %%NUM_BLOCKS > 8 vpaddd %%CTR2, %%CTR0, [rel ddq_add_8888] %endif %if %%NUM_BLOCKS > 12 vpaddd %%CTR3, %%CTR1, [rel ddq_add_8888] %endif %endif ;; get load/store mask lea %%IA0, [rel byte64_len_to_mask_table] mov %%IA1, %%LENGTH %if %%NUM_BLOCKS > 12 sub %%IA1, 3 * 64 %elif %%NUM_BLOCKS > 8 sub %%IA1, 2 * 64 %elif %%NUM_BLOCKS > 4 sub %%IA1, 64 %endif kmovq %%MASKREG, [%%IA0 + %%IA1*8] ;; extract new counter value ;; shuffle the counters for AES rounds %ifidn %%INSTANCE_TYPE, multi_call %if %%NUM_BLOCKS <= 4 vextracti32x4 %%CTR, %%CTR0, (%%NUM_BLOCKS - 1) %elif %%NUM_BLOCKS <= 8 vextracti32x4 %%CTR, %%CTR1, (%%NUM_BLOCKS - 5) %elif %%NUM_BLOCKS <= 12 vextracti32x4 %%CTR, %%CTR2, (%%NUM_BLOCKS - 9) %else vextracti32x4 %%CTR, %%CTR3, (%%NUM_BLOCKS - 13) %endif %endif ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpshufb, \ %%CTR0, %%CTR1, %%CTR2, %%CTR3, \ %%CTR0, %%CTR1, %%CTR2, %%CTR3, \ %%SHUFMASK, %%SHUFMASK, %%SHUFMASK, %%SHUFMASK ;; load plain/cipher text ZMM_LOAD_MASKED_BLOCKS_0_16 %%NUM_BLOCKS, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, %%MASKREG ;; AES rounds and XOR with plain/cipher text %assign j 0 %rep (NROUNDS + 2) vbroadcastf64x2 %%ZT1, [%%GDATA_KEY + (j * 16)] ZMM_AESENC_ROUND_BLOCKS_0_16 %%CTR0, %%CTR1, %%CTR2, %%CTR3, \ %%ZT1, j, \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, \ %%NUM_BLOCKS, NROUNDS %assign j (j + 1) %endrep %ifidn %%INSTANCE_TYPE, multi_call ;; retrieve the last cipher counter block (partially XOR'ed with text) ;; - this is needed for partial block cases %if %%NUM_BLOCKS <= 4 vextracti32x4 %%LAST_CIPHER_BLK, %%CTR0, (%%NUM_BLOCKS - 1) %elif %%NUM_BLOCKS <= 8 vextracti32x4 %%LAST_CIPHER_BLK, %%CTR1, (%%NUM_BLOCKS - 5) %elif %%NUM_BLOCKS <= 12 vextracti32x4 %%LAST_CIPHER_BLK, %%CTR2, (%%NUM_BLOCKS - 9) %else vextracti32x4 %%LAST_CIPHER_BLK, %%CTR3, (%%NUM_BLOCKS - 13) %endif %endif ;; write cipher/plain text back to output and ZMM_STORE_MASKED_BLOCKS_0_16 %%NUM_BLOCKS, %%CIPH_PLAIN_OUT, %%DATA_OFFSET, \ %%CTR0, %%CTR1, %%CTR2, %%CTR3, %%MASKREG ;; zero bytes outside the mask before hashing %if %%NUM_BLOCKS <= 4 vmovdqu8 %%CTR0{%%MASKREG}{z}, %%CTR0 %elif %%NUM_BLOCKS <= 8 vmovdqu8 %%CTR1{%%MASKREG}{z}, %%CTR1 %elif %%NUM_BLOCKS <= 12 vmovdqu8 %%CTR2{%%MASKREG}{z}, %%CTR2 %else vmovdqu8 %%CTR3{%%MASKREG}{z}, %%CTR3 %endif ;; Shuffle the cipher text blocks for hashing part ;; ZT5 and ZT6 are expected outputs with blocks for hashing %ifidn %%ENC_DEC, DEC ;; Decrypt case ;; - cipher blocks are in ZT5 & ZT6 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpshufb, \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, \ %%SHUFMASK, %%SHUFMASK, %%SHUFMASK, %%SHUFMASK %else ;; Encrypt case ;; - cipher blocks are in CTR0-CTR3 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpshufb, \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, \ %%CTR0, %%CTR1, %%CTR2, %%CTR3, \ %%SHUFMASK, %%SHUFMASK, %%SHUFMASK, %%SHUFMASK %endif ; Encrypt %ifidn %%INSTANCE_TYPE, multi_call ;; Extract the last block for partials and multi_call cases %if %%NUM_BLOCKS <= 4 vextracti32x4 %%LAST_GHASH_BLK, %%DAT0, %%NUM_BLOCKS - 1 %elif %%NUM_BLOCKS <= 8 vextracti32x4 %%LAST_GHASH_BLK, %%DAT1, %%NUM_BLOCKS - 5 %elif %%NUM_BLOCKS <= 12 vextracti32x4 %%LAST_GHASH_BLK, %%DAT2, %%NUM_BLOCKS - 9 %else vextracti32x4 %%LAST_GHASH_BLK, %%DAT3, %%NUM_BLOCKS - 13 %endif %endif %endmacro ; INITIAL_BLOCKS_PARTIAL_CIPHER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Computes GHASH on 1 to 16 blocks %macro INITIAL_BLOCKS_PARTIAL_GHASH 22-25 %define %%GDATA_KEY %1 ; [in] key pointer %define %%GDATA_CTX %2 ; [in] context pointer %define %%LENGTH %3 ; [in/clobbered] length in bytes %define %%NUM_BLOCKS %4 ; [in] can only be 1, 2, 3, 4, 5, ..., 15 or 16 (not 0) %define %%HASH_IN_OUT %5 ; [in/out] XMM ghash in/out value %define %%ENC_DEC %6 ; [in] cipher direction (ENC/DEC) %define %%INSTANCE_TYPE %7 ; [in] multi_call or single_call %define %%DAT0 %8 ; [in] ZMM with cipher text shuffled for GHASH %define %%DAT1 %9 ; [in] ZMM with cipher text shuffled for GHASH %define %%DAT2 %10 ; [in] ZMM with cipher text shuffled for GHASH %define %%DAT3 %11 ; [in] ZMM with cipher text shuffled for GHASH %define %%LAST_CIPHER_BLK %12 ; [in] XMM with ciphered counter block partially xor'ed with text %define %%LAST_GHASH_BLK %13 ; [in] XMM with last cipher text block shuffled for GHASH %define %%ZT0 %14 ; [clobbered] ZMM temporary %define %%ZT1 %15 ; [clobbered] ZMM temporary %define %%ZT2 %16 ; [clobbered] ZMM temporary %define %%ZT3 %17 ; [clobbered] ZMM temporary %define %%ZT4 %18 ; [clobbered] ZMM temporary %define %%ZT5 %19 ; [clobbered] ZMM temporary %define %%ZT6 %20 ; [clobbered] ZMM temporary %define %%ZT7 %21 ; [clobbered] ZMM temporary %define %%ZT8 %22 ; [clobbered] ZMM temporary %define %%GH %23 ; [in] ZMM with hi product part %define %%GM %24 ; [in] ZMM with mid product part %define %%GL %25 ; [in] ZMM with lo product part %ifidn %%INSTANCE_TYPE, single_call ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; SINGLE CALL case ;;; - hash all data including partial block ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %if %0 == 22 ;; start GHASH compute GHASH_1_TO_16 %%GDATA_KEY, %%HASH_IN_OUT, \ %%ZT0, %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT5, %%ZT6, %%ZT7, %%ZT8, ZWORD(%%HASH_IN_OUT), \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, %%NUM_BLOCKS %elif %0 == 25 ;; continue GHASH compute GHASH_1_TO_16 %%GDATA_KEY, %%HASH_IN_OUT, \ %%ZT0, %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT5, %%ZT6, %%ZT7, %%ZT8, ZWORD(%%HASH_IN_OUT), \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, %%NUM_BLOCKS, %%GH, %%GM, %%GL %endif %else ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; MULTI CALL (SGL) case ;;; - hash all but the last partial block of data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; update data offset %if %%NUM_BLOCKS > 1 ;; The final block of data may be <16B sub %%LENGTH, 16 * (%%NUM_BLOCKS - 1) %endif %if %%NUM_BLOCKS < 16 ;; NOTE: the 'jl' is always taken for num_initial_blocks = 16. ;; This is run in the context of GCM_ENC_DEC_SMALL for length < 256. cmp %%LENGTH, 16 jl %%_small_initial_partial_block ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Handle a full length final block - encrypt and hash all blocks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sub %%LENGTH, 16 mov qword [%%GDATA_CTX + PBlockLen], 0 ;; Hash all of the data %if %0 == 22 ;; start GHASH compute GHASH_1_TO_16 %%GDATA_KEY, %%HASH_IN_OUT, \ %%ZT0, %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT5, %%ZT6, %%ZT7, %%ZT8, ZWORD(%%HASH_IN_OUT), \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, %%NUM_BLOCKS %elif %0 == 25 ;; continue GHASH compute GHASH_1_TO_16 %%GDATA_KEY, %%HASH_IN_OUT, \ %%ZT0, %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT5, %%ZT6, %%ZT7, %%ZT8, ZWORD(%%HASH_IN_OUT), \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, %%NUM_BLOCKS, %%GH, %%GM, %%GL %endif jmp %%_small_initial_compute_done %endif ; %if %%NUM_BLOCKS < 16 %%_small_initial_partial_block: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Handle ghash for a <16B final block ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; In this case if it's a single call to encrypt we can ;; hash all of the data but if it's an init / update / finalize ;; series of call we need to leave the last block if it's ;; less than a full block of data. mov [%%GDATA_CTX + PBlockLen], %%LENGTH vmovdqu64 [%%GDATA_CTX + PBlockEncKey], %%LAST_CIPHER_BLK %assign k (%%NUM_BLOCKS - 1) %assign last_block_to_hash 1 %if (%%NUM_BLOCKS > last_block_to_hash) ;; ZT12-ZT20 - temporary registers %if %0 == 22 ;; start GHASH compute GHASH_1_TO_16 %%GDATA_KEY, %%HASH_IN_OUT, \ %%ZT0, %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT5, %%ZT6, %%ZT7, %%ZT8, ZWORD(%%HASH_IN_OUT), \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, k %elif %0 == 25 ;; continue GHASH compute GHASH_1_TO_16 %%GDATA_KEY, %%HASH_IN_OUT, \ %%ZT0, %%ZT1, %%ZT2, %%ZT3, %%ZT4, \ %%ZT5, %%ZT6, %%ZT7, %%ZT8, ZWORD(%%HASH_IN_OUT), \ %%DAT0, %%DAT1, %%DAT2, %%DAT3, k, %%GH, %%GM, %%GL %endif ;; just fall through no jmp needed %else %if %0 == 25 ;; Reduction is required in this case. ;; Integrate GM into GH and GL. vpsrldq %%ZT0, %%GM, 8 vpslldq %%ZT1, %%GM, 8 vpxorq %%GH, %%GH, %%ZT0 vpxorq %%GL, %%GL, %%ZT1 ;; Add GH and GL 128-bit words horizontally VHPXORI4x128 %%GH, %%ZT0 VHPXORI4x128 %%GL, %%ZT1 ;; 256-bit to 128-bit reduction vmovdqa64 XWORD(%%ZT0), [rel POLY2] VCLMUL_REDUCE XWORD(%%HASH_IN_OUT), XWORD(%%ZT0), \ XWORD(%%GH), XWORD(%%GL), XWORD(%%ZT1), XWORD(%%ZT2) %endif ;; Record that a reduction is not needed - ;; In this case no hashes are computed because there ;; is only one initial block and it is < 16B in length. ;; We only need to check if a reduction is needed if ;; initial_blocks == 1 and init/update/final is being used. ;; In this case we may just have a partial block, and that ;; gets hashed in finalize. ;; The hash should end up in HASH_IN_OUT. ;; The only way we should get here is if there is ;; a partial block of data, so xor that into the hash. vpxorq %%HASH_IN_OUT, %%HASH_IN_OUT, %%LAST_GHASH_BLK ;; The result is in %%HASH_IN_OUT jmp %%_after_reduction %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; After GHASH reduction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %%_small_initial_compute_done: ;; If using init/update/finalize, we need to xor any partial block data ;; into the hash. %if %%NUM_BLOCKS > 1 ;; NOTE: for %%NUM_BLOCKS = 0 the xor never takes place %if %%NUM_BLOCKS != 16 ;; NOTE: for %%NUM_BLOCKS = 16, %%LENGTH, stored in [PBlockLen] is never zero or %%LENGTH, %%LENGTH je %%_after_reduction %endif ; %%NUM_BLOCKS != 16 vpxorq %%HASH_IN_OUT, %%HASH_IN_OUT, %%LAST_GHASH_BLK %endif ; %%NUM_BLOCKS > 1 %%_after_reduction: %endif ; %%INSTANCE_TYPE, multi_call ;; Final hash is now in HASH_IN_OUT %endmacro ; INITIAL_BLOCKS_PARTIAL_GHASH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; INITIAL_BLOCKS_PARTIAL macro with support for a partial final block. ;;; It may look similar to INITIAL_BLOCKS but its usage is different: ;;; - first encrypts/decrypts required number of blocks and then ;;; ghashes these blocks ;;; - Small packets or left over data chunks (<256 bytes) ;;; - single or multi call ;;; - Remaining data chunks below 256 bytes (multi buffer code) ;;; ;;; num_initial_blocks is expected to include the partial final block ;;; in the count. %macro INITIAL_BLOCKS_PARTIAL 30 %define %%GDATA_KEY %1 ; [in] key pointer %define %%GDATA_CTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] text output pointer %define %%PLAIN_CIPH_IN %4 ; [in] text input pointer %define %%LENGTH %5 ; [in/clobbered] length in bytes %define %%DATA_OFFSET %6 ; [in/out] current data offset (updated) %define %%NUM_BLOCKS %7 ; [in] can only be 1, 2, 3, 4, 5, ..., 15 or 16 (not 0) %define %%CTR %8 ; [in/out] current counter value %define %%HASH_IN_OUT %9 ; [in/out] XMM ghash in/out value %define %%ENC_DEC %10 ; [in] cipher direction (ENC/DEC) %define %%INSTANCE_TYPE %11 ; [in] multi_call or single_call %define %%CTR0 %12 ; [clobbered] ZMM temporary %define %%CTR1 %13 ; [clobbered] ZMM temporary %define %%CTR2 %14 ; [clobbered] ZMM temporary %define %%CTR3 %15 ; [clobbered] ZMM temporary %define %%DAT0 %16 ; [clobbered] ZMM temporary %define %%DAT1 %17 ; [clobbered] ZMM temporary %define %%DAT2 %18 ; [clobbered] ZMM temporary %define %%DAT3 %19 ; [clobbered] ZMM temporary %define %%LAST_CIPHER_BLK %20 ; [clobbered] ZMM temporary %define %%LAST_GHASH_BLK %21 ; [clobbered] ZMM temporary %define %%ZT0 %22 ; [clobbered] ZMM temporary %define %%ZT1 %23 ; [clobbered] ZMM temporary %define %%ZT2 %24 ; [clobbered] ZMM temporary %define %%ZT3 %25 ; [clobbered] ZMM temporary %define %%ZT4 %26 ; [clobbered] ZMM temporary %define %%IA0 %27 ; [clobbered] GP temporary %define %%IA1 %28 ; [clobbered] GP temporary %define %%MASKREG %29 ; [clobbered] mask register %define %%SHUFMASK %30 ; [clobbered] ZMM for BE/LE shuffle mask INITIAL_BLOCKS_PARTIAL_CIPHER \ %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%LENGTH, %%DATA_OFFSET, %%NUM_BLOCKS, %%CTR, \ %%ENC_DEC, %%INSTANCE_TYPE, %%DAT0, %%DAT1, %%DAT2, %%DAT3, \ XWORD(%%LAST_CIPHER_BLK), XWORD(%%LAST_GHASH_BLK), \ %%CTR0, %%CTR1, %%CTR2, %%CTR3, %%ZT0, \ %%IA0, %%IA1, %%MASKREG, %%SHUFMASK INITIAL_BLOCKS_PARTIAL_GHASH \ %%GDATA_KEY, %%GDATA_CTX, %%LENGTH, \ %%NUM_BLOCKS, %%HASH_IN_OUT, %%ENC_DEC, \ %%INSTANCE_TYPE, %%DAT0, %%DAT1, %%DAT2, %%DAT3, \ XWORD(%%LAST_CIPHER_BLK), XWORD(%%LAST_GHASH_BLK), \ %%CTR0, %%CTR1, %%CTR2, %%CTR3, %%ZT0, %%ZT1, \ %%ZT2, %%ZT3, %%ZT4 %endmacro ; INITIAL_BLOCKS_PARTIAL ;;; =========================================================================== ;;; =========================================================================== ;;; Stitched GHASH of 16 blocks (with reduction) with encryption of N blocks ;;; followed with GHASH of the N blocks. %macro GHASH_16_ENCRYPT_N_GHASH_N 47 %define %%GDATA %1 ; [in] key pointer %define %%GCTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] pointer to output buffer %define %%PLAIN_CIPH_IN %4 ; [in] pointer to input buffer %define %%DATA_OFFSET %5 ; [in] data offset %define %%LENGTH %6 ; [in] data length %define %%CTR_BE %7 ; [in/out] ZMM counter blocks (last 4) in big-endian %define %%CTR_CHECK %8 ; [in/out] GP with 8-bit counter for overflow check %define %%HASHKEY_OFFSET %9 ; [in] numerical offset for the highest hash key %define %%GHASHIN_BLK_OFFSET %10 ; [in] numerical offset for GHASH blocks in %define %%SHFMSK %11 ; [in] ZMM with byte swap mask for pshufb %define %%B00_03 %12 ; [clobbered] temporary ZMM %define %%B04_07 %13 ; [clobbered] temporary ZMM %define %%B08_11 %14 ; [clobbered] temporary ZMM %define %%B12_15 %15 ; [clobbered] temporary ZMM %define %%GH1H_UNUSED %16 ; [clobbered] temporary ZMM %define %%GH1L %17 ; [clobbered] temporary ZMM %define %%GH1M %18 ; [clobbered] temporary ZMM %define %%GH1T %19 ; [clobbered] temporary ZMM %define %%GH2H %20 ; [clobbered] temporary ZMM %define %%GH2L %21 ; [clobbered] temporary ZMM %define %%GH2M %22 ; [clobbered] temporary ZMM %define %%GH2T %23 ; [clobbered] temporary ZMM %define %%GH3H %24 ; [clobbered] temporary ZMM %define %%GH3L %25 ; [clobbered] temporary ZMM %define %%GH3M %26 ; [clobbered] temporary ZMM %define %%GH3T %27 ; [clobbered] temporary ZMM %define %%AESKEY1 %28 ; [clobbered] temporary ZMM %define %%AESKEY2 %29 ; [clobbered] temporary ZMM %define %%GHKEY1 %30 ; [clobbered] temporary ZMM %define %%GHKEY2 %31 ; [clobbered] temporary ZMM %define %%GHDAT1 %32 ; [clobbered] temporary ZMM %define %%GHDAT2 %33 ; [clobbered] temporary ZMM %define %%ZT01 %34 ; [clobbered] temporary ZMM %define %%ADDBE_4x4 %35 ; [in] ZMM with 4x128bits 4 in big-endian %define %%ADDBE_1234 %36 ; [in] ZMM with 4x128bits 1, 2, 3 and 4 in big-endian %define %%GHASH_TYPE %37 ; [in] "start", "start_reduce", "mid", "end_reduce" %define %%TO_REDUCE_L %38 ; [in] ZMM for low 4x128-bit GHASH sum %define %%TO_REDUCE_H %39 ; [in] ZMM for hi 4x128-bit GHASH sum %define %%TO_REDUCE_M %40 ; [in] ZMM for medium 4x128-bit GHASH sum %define %%ENC_DEC %41 ; [in] cipher direction %define %%HASH_IN_OUT %42 ; [in/out] XMM ghash in/out value %define %%IA0 %43 ; [clobbered] GP temporary %define %%IA1 %44 ; [clobbered] GP temporary %define %%MASKREG %45 ; [clobbered] mask register %define %%NUM_BLOCKS %46 ; [in] numerical value with number of blocks to be encrypted/ghashed (1 to 16) %define %%INSTANCE_TYPE %47 ; [in] multi_call or single_call %xdefine %%GH1H %%HASH_IN_OUT ; this is to avoid additional move in do_reduction case %define %%LAST_GHASH_BLK %%GH1L %define %%LAST_CIPHER_BLK %%GH1T %define %%RED_POLY %%GH2T %define %%RED_P1 %%GH2L %define %%RED_T1 %%GH2H %define %%RED_T2 %%GH2M %define %%DATA1 %%GH3H %define %%DATA2 %%GH3L %define %%DATA3 %%GH3M %define %%DATA4 %%GH3T ;; do reduction after the 16 blocks ? %assign do_reduction 0 ;; is 16 block chunk a start? %assign is_start 0 %ifidn %%GHASH_TYPE, start_reduce %assign is_start 1 %assign do_reduction 1 %endif %ifidn %%GHASH_TYPE, start %assign is_start 1 %endif %ifidn %%GHASH_TYPE, end_reduce %assign do_reduction 1 %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; - get load/store mask ;; - load plain/cipher text ;; get load/store mask lea %%IA0, [rel byte64_len_to_mask_table] mov %%IA1, %%LENGTH %if %%NUM_BLOCKS > 12 sub %%IA1, 3 * 64 %elif %%NUM_BLOCKS > 8 sub %%IA1, 2 * 64 %elif %%NUM_BLOCKS > 4 sub %%IA1, 64 %endif kmovq %%MASKREG, [%%IA0 + %%IA1*8] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; prepare counter blocks cmp DWORD(%%CTR_CHECK), (256 - %%NUM_BLOCKS) jae %%_16_blocks_overflow ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpaddd, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%CTR_BE, %%B00_03, %%B04_07, %%B08_11, \ %%ADDBE_1234, %%ADDBE_4x4, %%ADDBE_4x4, %%ADDBE_4x4 jmp %%_16_blocks_ok %%_16_blocks_overflow: vpshufb %%CTR_BE, %%CTR_BE, %%SHFMSK vpaddd %%B00_03, %%CTR_BE, [rel ddq_add_1234] %if %%NUM_BLOCKS > 4 vmovdqa64 %%B12_15, [rel ddq_add_4444] vpaddd %%B04_07, %%B00_03, %%B12_15 %endif %if %%NUM_BLOCKS > 8 vpaddd %%B08_11, %%B04_07, %%B12_15 %endif %if %%NUM_BLOCKS > 12 vpaddd %%B12_15, %%B08_11, %%B12_15 %endif ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpshufb, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%SHFMSK, %%SHFMSK, %%SHFMSK, %%SHFMSK %%_16_blocks_ok: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; - pre-load constants ;; - add current hash into the 1st block vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 0)] %if is_start != 0 vpxorq %%GHDAT1, %%HASH_IN_OUT, [rsp + %%GHASHIN_BLK_OFFSET + (0*64)] %else vmovdqa64 %%GHDAT1, [rsp + %%GHASHIN_BLK_OFFSET + (0*64)] %endif vmovdqu64 %%GHKEY1, [%%GDATA + %%HASHKEY_OFFSET + (0*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; save counter for the next round ;; increment counter overflow check register %ifidn %%INSTANCE_TYPE, multi_call %if %%NUM_BLOCKS <= 4 vextracti32x4 XWORD(%%CTR_BE), %%B00_03, (%%NUM_BLOCKS - 1) %elif %%NUM_BLOCKS <= 8 vextracti32x4 XWORD(%%CTR_BE), %%B04_07, (%%NUM_BLOCKS - 5) %elif %%NUM_BLOCKS <= 12 vextracti32x4 XWORD(%%CTR_BE), %%B08_11, (%%NUM_BLOCKS - 9) %else vextracti32x4 XWORD(%%CTR_BE), %%B12_15, (%%NUM_BLOCKS - 13) %endif vshufi64x2 %%CTR_BE, %%CTR_BE, %%CTR_BE, 0000_0000b %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; pre-load constants vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 1)] vmovdqu64 %%GHKEY2, [%%GDATA + %%HASHKEY_OFFSET + (1*64)] vmovdqa64 %%GHDAT2, [rsp + %%GHASHIN_BLK_OFFSET + (1*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; stitch AES rounds with GHASH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 0 - ARK ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpxorq, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 2)] ;;================================================== ;; GHASH 4 blocks (15 to 12) vpclmulqdq %%GH1H, %%GHDAT1, %%GHKEY1, 0x11 ; a1*b1 vpclmulqdq %%GH1L, %%GHDAT1, %%GHKEY1, 0x00 ; a0*b0 vpclmulqdq %%GH1M, %%GHDAT1, %%GHKEY1, 0x01 ; a1*b0 vpclmulqdq %%GH1T, %%GHDAT1, %%GHKEY1, 0x10 ; a0*b1 vmovdqu64 %%GHKEY1, [%%GDATA + %%HASHKEY_OFFSET + (2*64)] vmovdqa64 %%GHDAT1, [rsp + %%GHASHIN_BLK_OFFSET + (2*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 1 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 3)] ;; ================================================= ;; GHASH 4 blocks (11 to 8) vpclmulqdq %%GH2M, %%GHDAT2, %%GHKEY2, 0x10 ; a0*b1 vpclmulqdq %%GH2T, %%GHDAT2, %%GHKEY2, 0x01 ; a1*b0 vpclmulqdq %%GH2H, %%GHDAT2, %%GHKEY2, 0x11 ; a1*b1 vpclmulqdq %%GH2L, %%GHDAT2, %%GHKEY2, 0x00 ; a0*b0 vmovdqu64 %%GHKEY2, [%%GDATA + %%HASHKEY_OFFSET + (3*64)] vmovdqa64 %%GHDAT2, [rsp + %%GHASHIN_BLK_OFFSET + (3*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 2 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 4)] ;; ================================================= ;; GHASH 4 blocks (7 to 4) vpclmulqdq %%GH3M, %%GHDAT1, %%GHKEY1, 0x10 ; a0*b1 vpclmulqdq %%GH3T, %%GHDAT1, %%GHKEY1, 0x01 ; a1*b0 vpclmulqdq %%GH3H, %%GHDAT1, %%GHKEY1, 0x11 ; a1*b1 vpclmulqdq %%GH3L, %%GHDAT1, %%GHKEY1, 0x00 ; a0*b0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds 3 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 5)] ;; ================================================= ;; Gather (XOR) GHASH for 12 blocks vpternlogq %%GH1H, %%GH2H, %%GH3H, 0x96 vpternlogq %%GH1L, %%GH2L, %%GH3L, 0x96 vpternlogq %%GH1T, %%GH2T, %%GH3T, 0x96 vpternlogq %%GH1M, %%GH2M, %%GH3M, 0x96 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds 4 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 6)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; load plain/cipher text ZMM_LOAD_MASKED_BLOCKS_0_16 %%NUM_BLOCKS, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%DATA1, %%DATA2, %%DATA3, %%DATA4, %%MASKREG ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds 5 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 7)] ;; ================================================= ;; GHASH 4 blocks (3 to 0) vpclmulqdq %%GH2M, %%GHDAT2, %%GHKEY2, 0x10 ; a0*b1 vpclmulqdq %%GH2T, %%GHDAT2, %%GHKEY2, 0x01 ; a1*b0 vpclmulqdq %%GH2H, %%GHDAT2, %%GHKEY2, 0x11 ; a1*b1 vpclmulqdq %%GH2L, %%GHDAT2, %%GHKEY2, 0x00 ; a0*b0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 6 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 8)] ;; ================================================= ;; gather GHASH in GH1L (low), GH1H (high), GH1M (mid) ;; - add GH2[MTLH] to GH1[MTLH] vpternlogq %%GH1M, %%GH1T, %%GH2T, 0x96 %if do_reduction != 0 %if is_start != 0 vpxorq %%GH1M, %%GH1M, %%GH2M %else vpternlogq %%GH1H, %%TO_REDUCE_H, %%GH2H, 0x96 vpternlogq %%GH1L, %%TO_REDUCE_L, %%GH2L, 0x96 vpternlogq %%GH1M, %%TO_REDUCE_M, %%GH2M, 0x96 %endif %else ;; Update H/M/L hash sums if not carrying reduction %if is_start != 0 vpxorq %%TO_REDUCE_H, %%GH1H, %%GH2H vpxorq %%TO_REDUCE_L, %%GH1L, %%GH2L vpxorq %%TO_REDUCE_M, %%GH1M, %%GH2M %else vpternlogq %%TO_REDUCE_H, %%GH1H, %%GH2H, 0x96 vpternlogq %%TO_REDUCE_L, %%GH1L, %%GH2L, 0x96 vpternlogq %%TO_REDUCE_M, %%GH1M, %%GH2M, 0x96 %endif %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 7 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 9)] ;; ================================================= ;; prepare mid sum for adding to high & low ;; load polynomial constant for reduction %if do_reduction != 0 vpsrldq %%GH2M, %%GH1M, 8 vpslldq %%GH1M, %%GH1M, 8 vmovdqa64 XWORD(%%RED_POLY), [rel POLY2] %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 8 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 10)] ;; ================================================= ;; Add mid product to high and low %if do_reduction != 0 %if is_start != 0 vpternlogq %%GH1H, %%GH2H, %%GH2M, 0x96 ; TH = TH1 + TH2 + TM>>64 vpternlogq %%GH1L, %%GH2L, %%GH1M, 0x96 ; TL = TL1 + TL2 + TM<<64 %else vpxorq %%GH1H, %%GH1H, %%GH2M ; TH = TH1 + TM>>64 vpxorq %%GH1L, %%GH1L, %%GH1M ; TL = TL1 + TM<<64 %endif %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 9 ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 ;; ================================================= ;; horizontal xor of low and high 4x128 %if do_reduction != 0 VHPXORI4x128 %%GH1H, %%GH2H VHPXORI4x128 %%GH1L, %%GH2L %endif %if (NROUNDS >= 11) vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 11)] %endif ;; ================================================= ;; first phase of reduction %if do_reduction != 0 vpclmulqdq XWORD(%%RED_P1), XWORD(%%RED_POLY), XWORD(%%GH1L), 0x01 vpslldq XWORD(%%RED_P1), XWORD(%%RED_P1), 8 ; shift-L 2 DWs vpxorq XWORD(%%RED_P1), XWORD(%%GH1L), XWORD(%%RED_P1) ; first phase of the reduct %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds up to 11 (AES192) or 13 (AES256) ;; AES128 is done %if (NROUNDS >= 11) ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 12)] ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 %if (NROUNDS == 13) vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 13)] ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 14)] ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenc, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY2, %%AESKEY2, %%AESKEY2, %%AESKEY2 %endif ; GCM256 / NROUNDS = 13 (15 including the first and the last) %endif ; GCM192 / NROUNDS = 11 (13 including the first and the last) ;; ================================================= ;; second phase of the reduction %if do_reduction != 0 vpclmulqdq XWORD(%%RED_T1), XWORD(%%RED_POLY), XWORD(%%RED_P1), 0x00 vpsrldq XWORD(%%RED_T1), XWORD(%%RED_T1), 4 ; shift-R 1-DW to obtain 2-DWs shift-R vpclmulqdq XWORD(%%RED_T2), XWORD(%%RED_POLY), XWORD(%%RED_P1), 0x10 vpslldq XWORD(%%RED_T2), XWORD(%%RED_T2), 4 ; shift-L 1-DW for result without shifts ;; GH1H = GH1H + RED_T1 + RED_T2 vpternlogq XWORD(%%GH1H), XWORD(%%RED_T2), XWORD(%%RED_T1), 0x96 %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; the last AES round ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vaesenclast, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%AESKEY1, %%AESKEY1, %%AESKEY1, %%AESKEY1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; XOR against plain/cipher text ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpxorq, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%DATA1, %%DATA2, %%DATA3, %%DATA4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; retrieve the last cipher counter block (partially XOR'ed with text) ;; - this is needed for partial block cases %ifidn %%INSTANCE_TYPE, multi_call %if %%NUM_BLOCKS <= 4 vextracti32x4 XWORD(%%LAST_CIPHER_BLK), %%B00_03, (%%NUM_BLOCKS - 1) %elif %%NUM_BLOCKS <= 8 vextracti32x4 XWORD(%%LAST_CIPHER_BLK), %%B04_07, (%%NUM_BLOCKS - 5) %elif %%NUM_BLOCKS <= 12 vextracti32x4 XWORD(%%LAST_CIPHER_BLK), %%B08_11, (%%NUM_BLOCKS - 9) %else vextracti32x4 XWORD(%%LAST_CIPHER_BLK), %%B12_15, (%%NUM_BLOCKS - 13) %endif %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; store cipher/plain text ZMM_STORE_MASKED_BLOCKS_0_16 %%NUM_BLOCKS, %%CIPH_PLAIN_OUT, %%DATA_OFFSET, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, %%MASKREG ;; ================================================= ;; shuffle cipher text blocks for GHASH computation %ifidn %%ENC_DEC, ENC ;; zero bytes outside the mask before hashing %if %%NUM_BLOCKS <= 4 vmovdqu8 %%B00_03{%%MASKREG}{z}, %%B00_03 %elif %%NUM_BLOCKS <= 8 vmovdqu8 %%B04_07{%%MASKREG}{z}, %%B04_07 %elif %%NUM_BLOCKS <= 12 vmovdqu8 %%B08_11{%%MASKREG}{z}, %%B08_11 %else vmovdqu8 %%B12_15{%%MASKREG}{z}, %%B12_15 %endif ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpshufb, \ %%DATA1, %%DATA2, %%DATA3, %%DATA4, \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, \ %%SHFMSK, %%SHFMSK, %%SHFMSK, %%SHFMSK %else ;; zero bytes outside the mask before hashing %if %%NUM_BLOCKS <= 4 vmovdqu8 %%DATA1{%%MASKREG}{z}, %%DATA1 %elif %%NUM_BLOCKS <= 8 vmovdqu8 %%DATA2{%%MASKREG}{z}, %%DATA2 %elif %%NUM_BLOCKS <= 12 vmovdqu8 %%DATA3{%%MASKREG}{z}, %%DATA3 %else vmovdqu8 %%DATA4{%%MASKREG}{z}, %%DATA4 %endif ZMM_OPCODE3_DSTR_SRC1R_SRC2R_BLOCKS_0_16 %%NUM_BLOCKS, vpshufb, \ %%DATA1, %%DATA2, %%DATA3, %%DATA4, \ %%DATA1, %%DATA2, %%DATA3, %%DATA4, \ %%SHFMSK, %%SHFMSK, %%SHFMSK, %%SHFMSK %endif ;; ================================================= ;; Extract the last block for partial / multi_call cases %ifidn %%INSTANCE_TYPE, multi_call %if %%NUM_BLOCKS <= 4 vextracti32x4 XWORD(%%LAST_GHASH_BLK), %%DATA1, %%NUM_BLOCKS - 1 %elif %%NUM_BLOCKS <= 8 vextracti32x4 XWORD(%%LAST_GHASH_BLK), %%DATA2, %%NUM_BLOCKS - 5 %elif %%NUM_BLOCKS <= 12 vextracti32x4 XWORD(%%LAST_GHASH_BLK), %%DATA3, %%NUM_BLOCKS - 9 %else vextracti32x4 XWORD(%%LAST_GHASH_BLK), %%DATA4, %%NUM_BLOCKS - 13 %endif %endif %if do_reduction != 0 ;; GH1H holds reduced hash value ;; - normally do "vmovdqa64 XWORD(%%HASH_IN_OUT), XWORD(%%GH1H)" ;; - register rename trick obsoletes the above move %endif ;; ================================================= ;; GHASH last N blocks ;; - current hash value in HASH_IN_OUT or ;; product parts in TO_REDUCE_H/M/L ;; - DATA1-DATA4 include blocks for GHASH %if do_reduction == 0 INITIAL_BLOCKS_PARTIAL_GHASH \ %%GDATA, %%GCTX, %%LENGTH, \ %%NUM_BLOCKS, XWORD(%%HASH_IN_OUT), %%ENC_DEC, \ %%INSTANCE_TYPE, %%DATA1, %%DATA2, %%DATA3, %%DATA4, \ XWORD(%%LAST_CIPHER_BLK), XWORD(%%LAST_GHASH_BLK), \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, %%GHDAT1, %%GHDAT2, \ %%AESKEY1, %%AESKEY2, %%GHKEY1, \ %%TO_REDUCE_H, %%TO_REDUCE_M, %%TO_REDUCE_L %else INITIAL_BLOCKS_PARTIAL_GHASH \ %%GDATA, %%GCTX, %%LENGTH, \ %%NUM_BLOCKS, XWORD(%%HASH_IN_OUT), %%ENC_DEC, \ %%INSTANCE_TYPE, %%DATA1, %%DATA2, %%DATA3, %%DATA4, \ XWORD(%%LAST_CIPHER_BLK), XWORD(%%LAST_GHASH_BLK), \ %%B00_03, %%B04_07, %%B08_11, %%B12_15, %%GHDAT1, %%GHDAT2, \ %%AESKEY1, %%AESKEY2, %%GHKEY1 %endif %endmacro ;;; =========================================================================== ;;; =========================================================================== ;;; Stitched GHASH of 16 blocks (with reduction) with encryption of N blocks ;;; followed with GHASH of the N blocks. %macro GCM_ENC_DEC_LAST 46 %define %%GDATA %1 ; [in] key pointer %define %%GCTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] pointer to output buffer %define %%PLAIN_CIPH_IN %4 ; [in] pointer to input buffer %define %%DATA_OFFSET %5 ; [in] data offset %define %%LENGTH %6 ; [in/clobbered] data length %define %%CTR_BE %7 ; [in/out] ZMM counter blocks (last 4) in big-endian %define %%CTR_CHECK %8 ; [in/out] GP with 8-bit counter for overflow check %define %%HASHKEY_OFFSET %9 ; [in] numerical offset for the highest hash key %define %%GHASHIN_BLK_OFFSET %10 ; [in] numerical offset for GHASH blocks in %define %%SHFMSK %11 ; [in] ZMM with byte swap mask for pshufb %define %%ZT00 %12 ; [clobbered] temporary ZMM %define %%ZT01 %13 ; [clobbered] temporary ZMM %define %%ZT02 %14 ; [clobbered] temporary ZMM %define %%ZT03 %15 ; [clobbered] temporary ZMM %define %%ZT04 %16 ; [clobbered] temporary ZMM %define %%ZT05 %17 ; [clobbered] temporary ZMM %define %%ZT06 %18 ; [clobbered] temporary ZMM %define %%ZT07 %19 ; [clobbered] temporary ZMM %define %%ZT08 %20 ; [clobbered] temporary ZMM %define %%ZT09 %21 ; [clobbered] temporary ZMM %define %%ZT10 %22 ; [clobbered] temporary ZMM %define %%ZT11 %23 ; [clobbered] temporary ZMM %define %%ZT12 %24 ; [clobbered] temporary ZMM %define %%ZT13 %25 ; [clobbered] temporary ZMM %define %%ZT14 %26 ; [clobbered] temporary ZMM %define %%ZT15 %27 ; [clobbered] temporary ZMM %define %%ZT16 %28 ; [clobbered] temporary ZMM %define %%ZT17 %29 ; [clobbered] temporary ZMM %define %%ZT18 %30 ; [clobbered] temporary ZMM %define %%ZT19 %31 ; [clobbered] temporary ZMM %define %%ZT20 %32 ; [clobbered] temporary ZMM %define %%ZT21 %33 ; [clobbered] temporary ZMM %define %%ZT22 %34 ; [clobbered] temporary ZMM %define %%ADDBE_4x4 %35 ; [in] ZMM with 4x128bits 4 in big-endian %define %%ADDBE_1234 %36 ; [in] ZMM with 4x128bits 1, 2, 3 and 4 in big-endian %define %%GHASH_TYPE %37 ; [in] "start", "start_reduce", "mid", "end_reduce" %define %%TO_REDUCE_L %38 ; [in] ZMM for low 4x128-bit GHASH sum %define %%TO_REDUCE_H %39 ; [in] ZMM for hi 4x128-bit GHASH sum %define %%TO_REDUCE_M %40 ; [in] ZMM for medium 4x128-bit GHASH sum %define %%ENC_DEC %41 ; [in] cipher direction %define %%HASH_IN_OUT %42 ; [in/out] XMM ghash in/out value %define %%IA0 %43 ; [clobbered] GP temporary %define %%IA1 %44 ; [clobbered] GP temporary %define %%MASKREG %45 ; [clobbered] mask register %define %%INSTANCE_TYPE %46 ; [in] multi_call or single_call mov DWORD(%%IA0), DWORD(%%LENGTH) add DWORD(%%IA0), 15 shr DWORD(%%IA0), 4 je %%_last_num_blocks_is_0 cmp DWORD(%%IA0), 8 je %%_last_num_blocks_is_8 jb %%_last_num_blocks_is_7_1 cmp DWORD(%%IA0), 12 je %%_last_num_blocks_is_12 jb %%_last_num_blocks_is_11_9 ;; 16, 15, 14 or 13 cmp DWORD(%%IA0), 15 je %%_last_num_blocks_is_15 ja %%_last_num_blocks_is_16 cmp DWORD(%%IA0), 14 je %%_last_num_blocks_is_14 jmp %%_last_num_blocks_is_13 %%_last_num_blocks_is_11_9: ;; 11, 10 or 9 cmp DWORD(%%IA0), 10 je %%_last_num_blocks_is_10 ja %%_last_num_blocks_is_11 jmp %%_last_num_blocks_is_9 %%_last_num_blocks_is_7_1: cmp DWORD(%%IA0), 4 je %%_last_num_blocks_is_4 jb %%_last_num_blocks_is_3_1 ;; 7, 6 or 5 cmp DWORD(%%IA0), 6 ja %%_last_num_blocks_is_7 je %%_last_num_blocks_is_6 jmp %%_last_num_blocks_is_5 %%_last_num_blocks_is_3_1: ;; 3, 2 or 1 cmp DWORD(%%IA0), 2 ja %%_last_num_blocks_is_3 je %%_last_num_blocks_is_2 ;; fall through for `jmp %%_last_num_blocks_is_1` ;; Use rep to generate different block size variants ;; - one block size has to be the first one %assign num_blocks 1 %rep 16 %%_last_num_blocks_is_ %+ num_blocks : GHASH_16_ENCRYPT_N_GHASH_N \ %%GDATA, %%GCTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%DATA_OFFSET, %%LENGTH, %%CTR_BE, %%CTR_CHECK, \ %%HASHKEY_OFFSET, %%GHASHIN_BLK_OFFSET, %%SHFMSK, \ %%ZT00, %%ZT01, %%ZT02, %%ZT03, %%ZT04, %%ZT05, %%ZT06, %%ZT07, \ %%ZT08, %%ZT09, %%ZT10, %%ZT11, %%ZT12, %%ZT13, %%ZT14, %%ZT15, \ %%ZT16, %%ZT17, %%ZT18, %%ZT19, %%ZT20, %%ZT21, %%ZT22, \ %%ADDBE_4x4, %%ADDBE_1234, %%GHASH_TYPE, \ %%TO_REDUCE_L, %%TO_REDUCE_H, %%TO_REDUCE_M, \ %%ENC_DEC, %%HASH_IN_OUT, %%IA0, %%IA1, %%MASKREG, \ num_blocks, %%INSTANCE_TYPE jmp %%_last_blocks_done %assign num_blocks (num_blocks + 1) %endrep %%_last_num_blocks_is_0: ;; if there is 0 blocks to cipher then there are only 16 blocks for ghash and reduction ;; - convert mid into end_reduce ;; - convert start into start_reduce %ifidn %%GHASH_TYPE, mid %xdefine %%GHASH_TYPE end_reduce %endif %ifidn %%GHASH_TYPE, start %xdefine %%GHASH_TYPE start_reduce %endif GHASH_16 %%GHASH_TYPE, %%TO_REDUCE_H, %%TO_REDUCE_M, %%TO_REDUCE_L, \ rsp, %%GHASHIN_BLK_OFFSET, 0, %%GDATA, %%HASHKEY_OFFSET, 0, %%HASH_IN_OUT, \ %%ZT00, %%ZT01, %%ZT02, %%ZT03, %%ZT04, %%ZT05, %%ZT06, %%ZT07, %%ZT08, %%ZT09 %%_last_blocks_done: %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Main GCM macro stitching cipher with GHASH ;;; - operates on single stream ;;; - encrypts 16 blocks at a time ;;; - ghash the 16 previously encrypted ciphertext blocks ;;; - no partial block or multi_call handling here %macro GHASH_16_ENCRYPT_16_PARALLEL 42 %define %%GDATA %1 ; [in] key pointer %define %%CIPH_PLAIN_OUT %2 ; [in] pointer to output buffer %define %%PLAIN_CIPH_IN %3 ; [in] pointer to input buffer %define %%DATA_OFFSET %4 ; [in] data offset %define %%CTR_BE %5 ; [in/out] ZMM counter blocks (last 4) in big-endian %define %%CTR_CHECK %6 ; [in/out] GP with 8-bit counter for overflow check %define %%HASHKEY_OFFSET %7 ; [in] numerical offset for the highest hash key %define %%AESOUT_BLK_OFFSET %8 ; [in] numerical offset for AES-CTR out %define %%GHASHIN_BLK_OFFSET %9 ; [in] numerical offset for GHASH blocks in %define %%SHFMSK %10 ; [in] ZMM with byte swap mask for pshufb %define %%ZT1 %11 ; [clobbered] temporary ZMM (cipher) %define %%ZT2 %12 ; [clobbered] temporary ZMM (cipher) %define %%ZT3 %13 ; [clobbered] temporary ZMM (cipher) %define %%ZT4 %14 ; [clobbered] temporary ZMM (cipher) %define %%ZT5 %15 ; [clobbered/out] temporary ZMM or GHASH OUT (final_reduction) %define %%ZT6 %16 ; [clobbered] temporary ZMM (cipher) %define %%ZT7 %17 ; [clobbered] temporary ZMM (cipher) %define %%ZT8 %18 ; [clobbered] temporary ZMM (cipher) %define %%ZT9 %19 ; [clobbered] temporary ZMM (cipher) %define %%ZT10 %20 ; [clobbered] temporary ZMM (ghash) %define %%ZT11 %21 ; [clobbered] temporary ZMM (ghash) %define %%ZT12 %22 ; [clobbered] temporary ZMM (ghash) %define %%ZT13 %23 ; [clobbered] temporary ZMM (ghash) %define %%ZT14 %24 ; [clobbered] temporary ZMM (ghash) %define %%ZT15 %25 ; [clobbered] temporary ZMM (ghash) %define %%ZT16 %26 ; [clobbered] temporary ZMM (ghash) %define %%ZT17 %27 ; [clobbered] temporary ZMM (ghash) %define %%ZT18 %28 ; [clobbered] temporary ZMM (ghash) %define %%ZT19 %29 ; [clobbered] temporary ZMM %define %%ZT20 %30 ; [clobbered] temporary ZMM %define %%ZT21 %31 ; [clobbered] temporary ZMM %define %%ZT22 %32 ; [clobbered] temporary ZMM %define %%ZT23 %33 ; [clobbered] temporary ZMM %define %%ADDBE_4x4 %34 ; [in] ZMM with 4x128bits 4 in big-endian %define %%ADDBE_1234 %35 ; [in] ZMM with 4x128bits 1, 2, 3 and 4 in big-endian %define %%TO_REDUCE_L %36 ; [in/out] ZMM for low 4x128-bit GHASH sum %define %%TO_REDUCE_H %37 ; [in/out] ZMM for hi 4x128-bit GHASH sum %define %%TO_REDUCE_M %38 ; [in/out] ZMM for medium 4x128-bit GHASH sum %define %%DO_REDUCTION %39 ; [in] "no_reduction", "final_reduction", "first_time" %define %%ENC_DEC %40 ; [in] cipher direction %define %%DATA_DISPL %41 ; [in] fixed numerical data displacement/offset %define %%GHASH_IN %42 ; [in] current GHASH value or "no_ghash_in" %define %%B00_03 %%ZT1 %define %%B04_07 %%ZT2 %define %%B08_11 %%ZT3 %define %%B12_15 %%ZT4 %define %%GH1H %%ZT5 ; @note: do not change this mapping %define %%GH1L %%ZT6 %define %%GH1M %%ZT7 %define %%GH1T %%ZT8 %define %%GH2H %%ZT9 %define %%GH2L %%ZT10 %define %%GH2M %%ZT11 %define %%GH2T %%ZT12 %define %%RED_POLY %%GH2T %define %%RED_P1 %%GH2L %define %%RED_T1 %%GH2H %define %%RED_T2 %%GH2M %define %%GH3H %%ZT13 %define %%GH3L %%ZT14 %define %%GH3M %%ZT15 %define %%GH3T %%ZT16 %define %%DATA1 %%ZT13 %define %%DATA2 %%ZT14 %define %%DATA3 %%ZT15 %define %%DATA4 %%ZT16 %define %%AESKEY1 %%ZT17 %define %%AESKEY2 %%ZT18 %define %%GHKEY1 %%ZT19 %define %%GHKEY2 %%ZT20 %define %%GHDAT1 %%ZT21 %define %%GHDAT2 %%ZT22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; prepare counter blocks cmp BYTE(%%CTR_CHECK), (256 - 16) jae %%_16_blocks_overflow vpaddd %%B00_03, %%CTR_BE, %%ADDBE_1234 vpaddd %%B04_07, %%B00_03, %%ADDBE_4x4 vpaddd %%B08_11, %%B04_07, %%ADDBE_4x4 vpaddd %%B12_15, %%B08_11, %%ADDBE_4x4 jmp %%_16_blocks_ok %%_16_blocks_overflow: vpshufb %%CTR_BE, %%CTR_BE, %%SHFMSK vmovdqa64 %%B12_15, [rel ddq_add_4444] vpaddd %%B00_03, %%CTR_BE, [rel ddq_add_1234] vpaddd %%B04_07, %%B00_03, %%B12_15 vpaddd %%B08_11, %%B04_07, %%B12_15 vpaddd %%B12_15, %%B08_11, %%B12_15 vpshufb %%B00_03, %%SHFMSK vpshufb %%B04_07, %%SHFMSK vpshufb %%B08_11, %%SHFMSK vpshufb %%B12_15, %%SHFMSK %%_16_blocks_ok: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; pre-load constants vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 0)] %ifnidn %%GHASH_IN, no_ghash_in vpxorq %%GHDAT1, %%GHASH_IN, [rsp + %%GHASHIN_BLK_OFFSET + (0*64)] %else vmovdqa64 %%GHDAT1, [rsp + %%GHASHIN_BLK_OFFSET + (0*64)] %endif vmovdqu64 %%GHKEY1, [%%GDATA + %%HASHKEY_OFFSET + (0*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; save counter for the next round ;; increment counter overflow check register vshufi64x2 %%CTR_BE, %%B12_15, %%B12_15, 1111_1111b add BYTE(%%CTR_CHECK), 16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; pre-load constants vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 1)] vmovdqu64 %%GHKEY2, [%%GDATA + %%HASHKEY_OFFSET + (1*64)] vmovdqa64 %%GHDAT2, [rsp + %%GHASHIN_BLK_OFFSET + (1*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; stitch AES rounds with GHASH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 0 - ARK vpxorq %%B00_03, %%AESKEY1 vpxorq %%B04_07, %%AESKEY1 vpxorq %%B08_11, %%AESKEY1 vpxorq %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 2)] ;;================================================== ;; GHASH 4 blocks (15 to 12) vpclmulqdq %%GH1H, %%GHDAT1, %%GHKEY1, 0x11 ; a1*b1 vpclmulqdq %%GH1L, %%GHDAT1, %%GHKEY1, 0x00 ; a0*b0 vpclmulqdq %%GH1M, %%GHDAT1, %%GHKEY1, 0x01 ; a1*b0 vpclmulqdq %%GH1T, %%GHDAT1, %%GHKEY1, 0x10 ; a0*b1 vmovdqu64 %%GHKEY1, [%%GDATA + %%HASHKEY_OFFSET + (2*64)] vmovdqa64 %%GHDAT1, [rsp + %%GHASHIN_BLK_OFFSET + (2*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 1 vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 3)] ;; ================================================= ;; GHASH 4 blocks (11 to 8) vpclmulqdq %%GH2M, %%GHDAT2, %%GHKEY2, 0x10 ; a0*b1 vpclmulqdq %%GH2T, %%GHDAT2, %%GHKEY2, 0x01 ; a1*b0 vpclmulqdq %%GH2H, %%GHDAT2, %%GHKEY2, 0x11 ; a1*b1 vpclmulqdq %%GH2L, %%GHDAT2, %%GHKEY2, 0x00 ; a0*b0 vmovdqu64 %%GHKEY2, [%%GDATA + %%HASHKEY_OFFSET + (3*64)] vmovdqa64 %%GHDAT2, [rsp + %%GHASHIN_BLK_OFFSET + (3*64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 2 vaesenc %%B00_03, %%B00_03, %%AESKEY1 vaesenc %%B04_07, %%B04_07, %%AESKEY1 vaesenc %%B08_11, %%B08_11, %%AESKEY1 vaesenc %%B12_15, %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 4)] ;; ================================================= ;; GHASH 4 blocks (7 to 4) vpclmulqdq %%GH3M, %%GHDAT1, %%GHKEY1, 0x10 ; a0*b1 vpclmulqdq %%GH3T, %%GHDAT1, %%GHKEY1, 0x01 ; a1*b0 vpclmulqdq %%GH3H, %%GHDAT1, %%GHKEY1, 0x11 ; a1*b1 vpclmulqdq %%GH3L, %%GHDAT1, %%GHKEY1, 0x00 ; a0*b0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds 3 vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 5)] ;; ================================================= ;; Gather (XOR) GHASH for 12 blocks vpternlogq %%GH1H, %%GH2H, %%GH3H, 0x96 vpternlogq %%GH1L, %%GH2L, %%GH3L, 0x96 vpternlogq %%GH1T, %%GH2T, %%GH3T, 0x96 vpternlogq %%GH1M, %%GH2M, %%GH3M, 0x96 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds 4 vaesenc %%B00_03, %%B00_03, %%AESKEY1 vaesenc %%B04_07, %%B04_07, %%AESKEY1 vaesenc %%B08_11, %%B08_11, %%AESKEY1 vaesenc %%B12_15, %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 6)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; load plain/cipher text (recycle GH3xx registers) VX512LDR %%DATA1, [%%PLAIN_CIPH_IN + %%DATA_OFFSET + %%DATA_DISPL + (0 * 64)] VX512LDR %%DATA2, [%%PLAIN_CIPH_IN + %%DATA_OFFSET + %%DATA_DISPL + (1 * 64)] VX512LDR %%DATA3, [%%PLAIN_CIPH_IN + %%DATA_OFFSET + %%DATA_DISPL + (2 * 64)] VX512LDR %%DATA4, [%%PLAIN_CIPH_IN + %%DATA_OFFSET + %%DATA_DISPL + (3 * 64)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds 5 vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 7)] ;; ================================================= ;; GHASH 4 blocks (3 to 0) vpclmulqdq %%GH2M, %%GHDAT2, %%GHKEY2, 0x10 ; a0*b1 vpclmulqdq %%GH2T, %%GHDAT2, %%GHKEY2, 0x01 ; a1*b0 vpclmulqdq %%GH2H, %%GHDAT2, %%GHKEY2, 0x11 ; a1*b1 vpclmulqdq %%GH2L, %%GHDAT2, %%GHKEY2, 0x00 ; a0*b0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 6 vaesenc %%B00_03, %%B00_03, %%AESKEY1 vaesenc %%B04_07, %%B04_07, %%AESKEY1 vaesenc %%B08_11, %%B08_11, %%AESKEY1 vaesenc %%B12_15, %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 8)] ;; ================================================= ;; gather GHASH in GH1L (low) and GH1H (high) %ifidn %%DO_REDUCTION, first_time vpternlogq %%GH1M, %%GH1T, %%GH2T, 0x96 ; TM vpxorq %%TO_REDUCE_M, %%GH1M, %%GH2M ; TM vpxorq %%TO_REDUCE_H, %%GH1H, %%GH2H ; TH vpxorq %%TO_REDUCE_L, %%GH1L, %%GH2L ; TL %endif %ifidn %%DO_REDUCTION, no_reduction vpternlogq %%GH1M, %%GH1T, %%GH2T, 0x96 ; TM vpternlogq %%TO_REDUCE_M, %%GH1M, %%GH2M, 0x96 ; TM vpternlogq %%TO_REDUCE_H, %%GH1H, %%GH2H, 0x96 ; TH vpternlogq %%TO_REDUCE_L, %%GH1L, %%GH2L, 0x96 ; TL %endif %ifidn %%DO_REDUCTION, final_reduction ;; phase 1: add mid products together ;; also load polynomial constant for reduction vpternlogq %%GH1M, %%GH1T, %%GH2T, 0x96 ; TM vpternlogq %%GH1M, %%TO_REDUCE_M, %%GH2M, 0x96 vpsrldq %%GH2M, %%GH1M, 8 vpslldq %%GH1M, %%GH1M, 8 vmovdqa64 XWORD(%%RED_POLY), [rel POLY2] %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 7 vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 9)] ;; ================================================= ;; Add mid product to high and low %ifidn %%DO_REDUCTION, final_reduction vpternlogq %%GH1H, %%GH2H, %%GH2M, 0x96 ; TH = TH1 + TH2 + TM>>64 vpxorq %%GH1H, %%TO_REDUCE_H vpternlogq %%GH1L, %%GH2L, %%GH1M, 0x96 ; TL = TL1 + TL2 + TM<<64 vpxorq %%GH1L, %%TO_REDUCE_L %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 8 vaesenc %%B00_03, %%B00_03, %%AESKEY1 vaesenc %%B04_07, %%B04_07, %%AESKEY1 vaesenc %%B08_11, %%B08_11, %%AESKEY1 vaesenc %%B12_15, %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 10)] ;; ================================================= ;; horizontal xor of low and high 4x128 %ifidn %%DO_REDUCTION, final_reduction VHPXORI4x128 %%GH1H, %%GH2H VHPXORI4x128 %%GH1L, %%GH2L %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES round 9 vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 %if (NROUNDS >= 11) vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 11)] %endif ;; ================================================= ;; first phase of reduction %ifidn %%DO_REDUCTION, final_reduction vpclmulqdq XWORD(%%RED_P1), XWORD(%%RED_POLY), XWORD(%%GH1L), 0x01 vpslldq XWORD(%%RED_P1), XWORD(%%RED_P1), 8 ; shift-L 2 DWs vpxorq XWORD(%%RED_P1), XWORD(%%GH1L), XWORD(%%RED_P1) ; first phase of the reduct %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; AES rounds up to 11 (AES192) or 13 (AES256) ;; AES128 is done %if (NROUNDS >= 11) vaesenc %%B00_03, %%B00_03, %%AESKEY1 vaesenc %%B04_07, %%B04_07, %%AESKEY1 vaesenc %%B08_11, %%B08_11, %%AESKEY1 vaesenc %%B12_15, %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 12)] vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 %if (NROUNDS == 13) vbroadcastf64x2 %%AESKEY2, [%%GDATA + (16 * 13)] vaesenc %%B00_03, %%B00_03, %%AESKEY1 vaesenc %%B04_07, %%B04_07, %%AESKEY1 vaesenc %%B08_11, %%B08_11, %%AESKEY1 vaesenc %%B12_15, %%B12_15, %%AESKEY1 vbroadcastf64x2 %%AESKEY1, [%%GDATA + (16 * 14)] vaesenc %%B00_03, %%B00_03, %%AESKEY2 vaesenc %%B04_07, %%B04_07, %%AESKEY2 vaesenc %%B08_11, %%B08_11, %%AESKEY2 vaesenc %%B12_15, %%B12_15, %%AESKEY2 %endif ; GCM256 / NROUNDS = 13 (15 including the first and the last) %endif ; GCM192 / NROUNDS = 11 (13 including the first and the last) ;; ================================================= ;; second phase of the reduction %ifidn %%DO_REDUCTION, final_reduction vpclmulqdq XWORD(%%RED_T1), XWORD(%%RED_POLY), XWORD(%%RED_P1), 0x00 vpsrldq XWORD(%%RED_T1), XWORD(%%RED_T1), 4 ; shift-R 1-DW to obtain 2-DWs shift-R vpclmulqdq XWORD(%%RED_T2), XWORD(%%RED_POLY), XWORD(%%RED_P1), 0x10 vpslldq XWORD(%%RED_T2), XWORD(%%RED_T2), 4 ; shift-L 1-DW for result without shifts ;; GH1H = GH1H x RED_T1 x RED_T2 vpternlogq XWORD(%%GH1H), XWORD(%%RED_T2), XWORD(%%RED_T1), 0x96 %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; the last AES round vaesenclast %%B00_03, %%B00_03, %%AESKEY1 vaesenclast %%B04_07, %%B04_07, %%AESKEY1 vaesenclast %%B08_11, %%B08_11, %%AESKEY1 vaesenclast %%B12_15, %%B12_15, %%AESKEY1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; XOR against plain/cipher text vpxorq %%B00_03, %%B00_03, %%DATA1 vpxorq %%B04_07, %%B04_07, %%DATA2 vpxorq %%B08_11, %%B08_11, %%DATA3 vpxorq %%B12_15, %%B12_15, %%DATA4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; store cipher/plain text VX512STR [%%CIPH_PLAIN_OUT + %%DATA_OFFSET + %%DATA_DISPL + (0 * 64)], %%B00_03 VX512STR [%%CIPH_PLAIN_OUT + %%DATA_OFFSET + %%DATA_DISPL + (1 * 64)], %%B04_07 VX512STR [%%CIPH_PLAIN_OUT + %%DATA_OFFSET + %%DATA_DISPL + (2 * 64)], %%B08_11 VX512STR [%%CIPH_PLAIN_OUT + %%DATA_OFFSET + %%DATA_DISPL + (3 * 64)], %%B12_15 ;; ================================================= ;; shuffle cipher text blocks for GHASH computation %ifidn %%ENC_DEC, ENC vpshufb %%B00_03, %%B00_03, %%SHFMSK vpshufb %%B04_07, %%B04_07, %%SHFMSK vpshufb %%B08_11, %%B08_11, %%SHFMSK vpshufb %%B12_15, %%B12_15, %%SHFMSK %else vpshufb %%B00_03, %%DATA1, %%SHFMSK vpshufb %%B04_07, %%DATA2, %%SHFMSK vpshufb %%B08_11, %%DATA3, %%SHFMSK vpshufb %%B12_15, %%DATA4, %%SHFMSK %endif ;; ================================================= ;; store shuffled cipher text for ghashing vmovdqa64 [rsp + %%AESOUT_BLK_OFFSET + (0*64)], %%B00_03 vmovdqa64 [rsp + %%AESOUT_BLK_OFFSET + (1*64)], %%B04_07 vmovdqa64 [rsp + %%AESOUT_BLK_OFFSET + (2*64)], %%B08_11 vmovdqa64 [rsp + %%AESOUT_BLK_OFFSET + (3*64)], %%B12_15 %ifidn %%DO_REDUCTION, final_reduction ;; ================================================= ;; Return GHASH value through %%GH1H %endif %endmacro ; GHASH_16_ENCRYPT_16_PARALLEL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Encryption of a single block %macro ENCRYPT_SINGLE_BLOCK 2 %define %%GDATA %1 %define %%XMM0 %2 vpxorq %%XMM0, %%XMM0, [%%GDATA+16*0] %assign i 1 %rep NROUNDS vaesenc %%XMM0, [%%GDATA+16*i] %assign i (i+1) %endrep vaesenclast %%XMM0, [%%GDATA+16*i] %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Save register content for the caller %macro FUNC_SAVE 0 ;; Required for Update/GMC_ENC ;the number of pushes must equal STACK_OFFSET mov rax, rsp sub rsp, STACK_FRAME_SIZE and rsp, ~63 mov [rsp + STACK_GP_OFFSET + 0*8], r12 mov [rsp + STACK_GP_OFFSET + 1*8], r13 mov [rsp + STACK_GP_OFFSET + 2*8], r14 mov [rsp + STACK_GP_OFFSET + 3*8], r15 mov [rsp + STACK_GP_OFFSET + 4*8], rax ; stack mov r14, rax ; r14 is used to retrieve stack args mov [rsp + STACK_GP_OFFSET + 5*8], rbp mov [rsp + STACK_GP_OFFSET + 6*8], rbx %ifidn __OUTPUT_FORMAT__, win64 mov [rsp + STACK_GP_OFFSET + 7*8], rdi mov [rsp + STACK_GP_OFFSET + 8*8], rsi %endif %ifidn __OUTPUT_FORMAT__, win64 ; xmm6:xmm15 need to be maintained for Windows vmovdqu [rsp + STACK_XMM_OFFSET + 0*16], xmm6 vmovdqu [rsp + STACK_XMM_OFFSET + 1*16], xmm7 vmovdqu [rsp + STACK_XMM_OFFSET + 2*16], xmm8 vmovdqu [rsp + STACK_XMM_OFFSET + 3*16], xmm9 vmovdqu [rsp + STACK_XMM_OFFSET + 4*16], xmm10 vmovdqu [rsp + STACK_XMM_OFFSET + 5*16], xmm11 vmovdqu [rsp + STACK_XMM_OFFSET + 6*16], xmm12 vmovdqu [rsp + STACK_XMM_OFFSET + 7*16], xmm13 vmovdqu [rsp + STACK_XMM_OFFSET + 8*16], xmm14 vmovdqu [rsp + STACK_XMM_OFFSET + 9*16], xmm15 %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Restore register content for the caller %macro FUNC_RESTORE 0 %ifdef SAFE_DATA clear_scratch_gps_asm clear_scratch_zmms_asm %else vzeroupper %endif %ifidn __OUTPUT_FORMAT__, win64 vmovdqu xmm15, [rsp + STACK_XMM_OFFSET + 9*16] vmovdqu xmm14, [rsp + STACK_XMM_OFFSET + 8*16] vmovdqu xmm13, [rsp + STACK_XMM_OFFSET + 7*16] vmovdqu xmm12, [rsp + STACK_XMM_OFFSET + 6*16] vmovdqu xmm11, [rsp + STACK_XMM_OFFSET + 5*16] vmovdqu xmm10, [rsp + STACK_XMM_OFFSET + 4*16] vmovdqu xmm9, [rsp + STACK_XMM_OFFSET + 3*16] vmovdqu xmm8, [rsp + STACK_XMM_OFFSET + 2*16] vmovdqu xmm7, [rsp + STACK_XMM_OFFSET + 1*16] vmovdqu xmm6, [rsp + STACK_XMM_OFFSET + 0*16] %endif ;; Required for Update/GMC_ENC mov rbp, [rsp + STACK_GP_OFFSET + 5*8] mov rbx, [rsp + STACK_GP_OFFSET + 6*8] %ifidn __OUTPUT_FORMAT__, win64 mov rdi, [rsp + STACK_GP_OFFSET + 7*8] mov rsi, [rsp + STACK_GP_OFFSET + 8*8] %endif mov r12, [rsp + STACK_GP_OFFSET + 0*8] mov r13, [rsp + STACK_GP_OFFSET + 1*8] mov r14, [rsp + STACK_GP_OFFSET + 2*8] mov r15, [rsp + STACK_GP_OFFSET + 3*8] mov rsp, [rsp + STACK_GP_OFFSET + 4*8] ; stack %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Calculate J0 for cases when IV length is different than 12 bytes %macro CALC_J0 27 %define %%KEY %1 ;; [in] Pointer to GCM KEY structure %define %%IV %2 ;; [in] Pointer to IV %define %%IV_LEN %3 ;; [in] IV length %define %%J0 %4 ;; [out] XMM reg to contain J0 %define %%ZT0 %5 ;; [clobbered] ZMM register %define %%ZT1 %6 ;; [clobbered] ZMM register %define %%ZT2 %7 ;; [clobbered] ZMM register %define %%ZT3 %8 ;; [clobbered] ZMM register %define %%ZT4 %9 ;; [clobbered] ZMM register %define %%ZT5 %10 ;; [clobbered] ZMM register %define %%ZT6 %11 ;; [clobbered] ZMM register %define %%ZT7 %12 ;; [clobbered] ZMM register %define %%ZT8 %13 ;; [clobbered] ZMM register %define %%ZT9 %14 ;; [clobbered] ZMM register %define %%ZT10 %15 ;; [clobbered] ZMM register %define %%ZT11 %16 ;; [clobbered] ZMM register %define %%ZT12 %17 ;; [clobbered] ZMM register %define %%ZT13 %18 ;; [clobbered] ZMM register %define %%ZT14 %19 ;; [clobbered] ZMM register %define %%ZT15 %20 ;; [clobbered] ZMM register %define %%ZT16 %21 ;; [clobbered] ZMM register %define %%ZT17 %22 ;; [clobbered] ZMM register %define %%T1 %23 ;; [clobbered] GP register %define %%T2 %24 ;; [clobbered] GP register %define %%T3 %25 ;; [clobbered] GP register %define %%MASKREG %26 ;; [clobbered] mask register ;; IPPCP: unlike IPsec-MB this macro is called in iv_finalize only that can follow ;; several iv_update calls, so iv_total_len should be an additional external parameter ;; here. %define %%IV_TOTAL_LEN %27 ;; [in] total len of IV ;; J0 = GHASH(IV || 0s+64 || len(IV)64) ;; s = 16 * RoundUp(len(IV)/16) - len(IV) */ ;; Calculate GHASH of (IV || 0s) ;; vpxor %%J0, %%J0 ;; IPPCP: xor disabled (zeroing is done outside) CALC_AAD_HASH %%IV, %%IV_LEN, %%J0, %%KEY, %%ZT0, %%ZT1, %%ZT2, %%ZT3, \ %%ZT4, %%ZT5, %%ZT6, %%ZT7, %%ZT8, %%ZT9, %%ZT10, %%ZT11, \ %%ZT12, %%ZT13, %%ZT14, %%ZT15, %%ZT16, %%ZT17, \ %%T1, %%T2, %%T3, %%MASKREG ;; Calculate GHASH of last 16-byte block (0 || len(IV)64) ;; mov %%T1, %%IV_LEN ;; IPPCP: iv total len is external parameter mov %%T1, %%IV_TOTAL_LEN shl %%T1, 3 ;; IV length in bits vmovq XWORD(%%ZT2), %%T1 ;; Might need shuffle of ZT2 vpxorq %%J0, XWORD(%%ZT2), %%J0 vmovdqu64 XWORD(%%ZT0), [%%KEY + HashKey_1] GHASH_MUL %%J0, XWORD(%%ZT0), XWORD(%%ZT1), XWORD(%%ZT2), XWORD(%%ZT3), XWORD(%%ZT4), XWORD(%%ZT5) vpshufb %%J0, [rel SHUF_MASK] ; perform a 16Byte swap %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Cipher and ghash of payloads shorter than 256 bytes ;;; - number of blocks in the message comes as argument ;;; - depending on the number of blocks an optimized variant of ;;; INITIAL_BLOCKS_PARTIAL is invoked %macro GCM_ENC_DEC_SMALL 39 %define %%GDATA_KEY %1 ; [in] key pointer %define %%GDATA_CTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] output buffer %define %%PLAIN_CIPH_IN %4 ; [in] input buffer %define %%PLAIN_CIPH_LEN %5 ; [in] buffer length %define %%ENC_DEC %6 ; [in] cipher direction %define %%DATA_OFFSET %7 ; [in] data offset %define %%LENGTH %8 ; [in] GP data length %define %%NUM_BLOCKS %9 ; [in] GP number of blocks to process 1 to 16 %define %%CTR %10 ; [in/out] XMM counter block %define %%HASH_IN_OUT %11 ; [in/out] XMM GHASH value %define %%INSTANCE_TYPE %12 ; [in] single or multi call %define %%ZTMP0 %13 ; [clobbered] ZMM register %define %%ZTMP1 %14 ; [clobbered] ZMM register %define %%ZTMP2 %15 ; [clobbered] ZMM register %define %%ZTMP3 %16 ; [clobbered] ZMM register %define %%ZTMP4 %17 ; [clobbered] ZMM register %define %%ZTMP5 %18 ; [clobbered] ZMM register %define %%ZTMP6 %19 ; [clobbered] ZMM register %define %%ZTMP7 %20 ; [clobbered] ZMM register %define %%ZTMP8 %21 ; [clobbered] ZMM register %define %%ZTMP9 %22 ; [clobbered] ZMM register %define %%ZTMP10 %23 ; [clobbered] ZMM register %define %%ZTMP11 %24 ; [clobbered] ZMM register %define %%ZTMP12 %25 ; [clobbered] ZMM register %define %%ZTMP13 %26 ; [clobbered] ZMM register %define %%ZTMP14 %27 ; [clobbered] ZMM register %define %%ZTMP15 %28 ; [clobbered] ZMM register %define %%ZTMP16 %29 ; [clobbered] ZMM register %define %%ZTMP17 %30 ; [clobbered] ZMM register %define %%ZTMP18 %31 ; [clobbered] ZMM register %define %%ZTMP19 %32 ; [clobbered] ZMM register %define %%ZTMP20 %33 ; [clobbered] ZMM register %define %%ZTMP21 %34 ; [clobbered] ZMM register %define %%ZTMP22 %35 ; [clobbered] ZMM register %define %%IA0 %36 ; [clobbered] GP register %define %%IA1 %37 ; [clobbered] GP register %define %%MASKREG %38 ; [clobbered] mask register %define %%SHUFMASK %39 ; [clobbered] ZMM to be used for BE/LE shuffle mask cmp DWORD(%%NUM_BLOCKS), 8 je %%_small_initial_num_blocks_is_8 jb %%_small_initial_num_blocks_is_7_1 cmp DWORD(%%NUM_BLOCKS), 12 je %%_small_initial_num_blocks_is_12 jb %%_small_initial_num_blocks_is_11_9 ;; 16, 15, 14 or 13 cmp DWORD(%%NUM_BLOCKS), 15 ja %%_small_initial_num_blocks_is_16 je %%_small_initial_num_blocks_is_15 cmp DWORD(%%NUM_BLOCKS), 14 je %%_small_initial_num_blocks_is_14 jmp %%_small_initial_num_blocks_is_13 %%_small_initial_num_blocks_is_11_9: ;; 11, 10 or 9 cmp DWORD(%%NUM_BLOCKS), 10 ja %%_small_initial_num_blocks_is_11 je %%_small_initial_num_blocks_is_10 jmp %%_small_initial_num_blocks_is_9 %%_small_initial_num_blocks_is_7_1: cmp DWORD(%%NUM_BLOCKS), 4 je %%_small_initial_num_blocks_is_4 jb %%_small_initial_num_blocks_is_3_1 ;; 7, 6 or 5 cmp DWORD(%%NUM_BLOCKS), 6 ja %%_small_initial_num_blocks_is_7 je %%_small_initial_num_blocks_is_6 jmp %%_small_initial_num_blocks_is_5 %%_small_initial_num_blocks_is_3_1: ;; 3, 2 or 1 cmp DWORD(%%NUM_BLOCKS), 2 ja %%_small_initial_num_blocks_is_3 je %%_small_initial_num_blocks_is_2 ;; for %%NUM_BLOCKS == 1, just fall through and no 'jmp' needed ;; Use rep to generate different block size variants ;; - one block size has to be the first one ;; - ZTMP15 - ZTMP22 are free %assign num_blocks 1 %rep 16 %%_small_initial_num_blocks_is_ %+ num_blocks : INITIAL_BLOCKS_PARTIAL %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, \ %%PLAIN_CIPH_IN, %%LENGTH, %%DATA_OFFSET, num_blocks, \ %%CTR, %%HASH_IN_OUT, %%ENC_DEC, %%INSTANCE_TYPE, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, \ %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, %%ZTMP9, \ %%ZTMP10, %%ZTMP11, %%ZTMP12, %%ZTMP13, %%ZTMP14, \ %%IA0, %%IA1, %%MASKREG, %%SHUFMASK %if num_blocks != 16 jmp %%_small_initial_blocks_encrypted %endif %assign num_blocks (num_blocks + 1) %endrep %%_small_initial_blocks_encrypted: %endmacro ; GCM_ENC_DEC_SMALL ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GCM_ENC_DEC Encodes/Decodes given data. Assumes that the passed gcm_context_data struct ; has been initialized by GCM_INIT ; Requires the input data be at least 1 byte long because of READ_SMALL_INPUT_DATA. ; Input: gcm_key_data struct* (GDATA_KEY), gcm_context_data *(GDATA_CTX), input text (PLAIN_CIPH_IN), ; input text length (PLAIN_CIPH_LEN) and whether encoding or decoding (ENC_DEC). ; Output: A cipher of the given plain text (CIPH_PLAIN_OUT), and updated GDATA_CTX ; Clobbers rax, r10-r15, and zmm0-zmm31, k1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_ENC_DEC 7 %define %%GDATA_KEY %1 ; [in] key pointer %define %%GDATA_CTX %2 ; [in] context pointer %define %%CIPH_PLAIN_OUT %3 ; [in] output buffer pointer %define %%PLAIN_CIPH_IN %4 ; [in] input buffer pointer %define %%PLAIN_CIPH_LEN %5 ; [in] buffer length %define %%ENC_DEC %6 ; [in] cipher direction %define %%INSTANCE_TYPE %7 ; [in] 'single_call' or 'multi_call' selection %define %%IA0 r10 %define %%IA1 r12 %define %%IA2 r13 %define %%IA3 r15 %define %%IA4 r11 %define %%IA5 rax %define %%IA6 rbx %ifidn __OUTPUT_FORMAT__, win64 %define %%LENGTH %%IA2 %endif %define %%CTR_CHECK %%IA3 %define %%DATA_OFFSET %%IA4 %define %%HASHK_PTR %%IA6 %define %%CTR_BLOCKz zmm2 %define %%CTR_BLOCKx xmm2 ; hardcoded in GCM_INIT %define %%AAD_HASHz zmm14 %define %%AAD_HASHx xmm14 ; hardcoded in GCM_COMPLETE %define %%ZTMP0 zmm0 %define %%ZTMP1 zmm3 %define %%ZTMP2 zmm4 %define %%ZTMP3 zmm5 %define %%ZTMP4 zmm6 %define %%ZTMP5 zmm7 %define %%ZTMP6 zmm10 %define %%ZTMP7 zmm11 %define %%ZTMP8 zmm12 %define %%ZTMP9 zmm13 %define %%ZTMP10 zmm15 %define %%ZTMP11 zmm16 %define %%ZTMP12 zmm17 %define %%ZTMP13 zmm19 %define %%ZTMP14 zmm20 %define %%ZTMP15 zmm21 %define %%ZTMP16 zmm30 %define %%ZTMP17 zmm31 %define %%ZTMP18 zmm1 %define %%ZTMP19 zmm18 %define %%ZTMP20 zmm8 %define %%ZTMP21 zmm22 %define %%ZTMP22 zmm23 %define %%GH zmm24 %define %%GL zmm25 %define %%GM zmm26 %define %%SHUF_MASK zmm29 ;;; Unused in the small packet path %define %%ADDBE_4x4 zmm27 %define %%ADDBE_1234 zmm28 %define %%MASKREG k1 ;; reduction every 48 blocks, depth 32 blocks ;; @note 48 blocks is the maximum capacity of the stack frame %assign big_loop_nblocks 48 %assign big_loop_depth 32 ;;; Macro flow depending on packet size ;;; - LENGTH <= 16 blocks ;;; - cipher followed by hashing (reduction) ;;; - 16 blocks < LENGTH < 32 blocks ;;; - cipher 16 blocks ;;; - cipher N blocks & hash 16 blocks, hash N blocks (reduction) ;;; - 32 blocks < LENGTH < 48 blocks ;;; - cipher 2 x 16 blocks ;;; - hash 16 blocks ;;; - cipher N blocks & hash 16 blocks, hash N blocks (reduction) ;;; - LENGTH >= 48 blocks ;;; - cipher 2 x 16 blocks ;;; - while (data_to_cipher >= 48 blocks): ;;; - cipher 16 blocks & hash 16 blocks ;;; - cipher 16 blocks & hash 16 blocks ;;; - cipher 16 blocks & hash 16 blocks (reduction) ;;; - if (data_to_cipher >= 32 blocks): ;;; - cipher 16 blocks & hash 16 blocks ;;; - cipher 16 blocks & hash 16 blocks ;;; - hash 16 blocks (reduction) ;;; - cipher N blocks & hash 16 blocks, hash N blocks (reduction) ;;; - elif (data_to_cipher >= 16 blocks): ;;; - cipher 16 blocks & hash 16 blocks ;;; - hash 16 blocks ;;; - cipher N blocks & hash 16 blocks, hash N blocks (reduction) ;;; - else: ;;; - hash 16 blocks ;;; - cipher N blocks & hash 16 blocks, hash N blocks (reduction) %ifidn __OUTPUT_FORMAT__, win64 cmp %%PLAIN_CIPH_LEN, 0 %else or %%PLAIN_CIPH_LEN, %%PLAIN_CIPH_LEN %endif je %%_enc_dec_done ;; Update length of data processed %ifidn __OUTPUT_FORMAT__, win64 mov %%IA0, %%PLAIN_CIPH_LEN add [%%GDATA_CTX + InLen], %%IA0 %else add [%%GDATA_CTX + InLen], %%PLAIN_CIPH_LEN %endif vmovdqu64 %%AAD_HASHx, [%%GDATA_CTX + AadHash] %ifidn %%INSTANCE_TYPE, multi_call ;; NOTE: partial block processing makes only sense for multi_call here. ;; Used for the update flow - if there was a previous partial ;; block fill the remaining bytes here. PARTIAL_BLOCK %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%PLAIN_CIPH_LEN, %%DATA_OFFSET, %%AAD_HASHx, %%ENC_DEC, \ %%IA0, %%IA1, %%IA2, %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, \ %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, %%ZTMP9, %%MASKREG %else xor %%DATA_OFFSET, %%DATA_OFFSET %endif %ifidn %%INSTANCE_TYPE, single_call ;; use counter block from GCM_INIT %else vmovdqu64 %%CTR_BLOCKx, [%%GDATA_CTX + CurCount] %endif ;; Save the amount of data left to process in %%LENGTH %ifidn __OUTPUT_FORMAT__, win64 mov %%LENGTH, %%PLAIN_CIPH_LEN %else %define %%LENGTH %%PLAIN_CIPH_LEN ;; PLAIN_CIPH_LEN is a register on linux %endif %ifidn %%INSTANCE_TYPE, multi_call ;; NOTE: %%DATA_OFFSET is zero in single_call case. ;; Consequently PLAIN_CIPH_LEN will never be zero after ;; %%DATA_OFFSET subtraction below. ;; There may be no more data if it was consumed in the partial block. sub %%LENGTH, %%DATA_OFFSET je %%_enc_dec_done %endif ; %%INSTANCE_TYPE, multi_call cmp %%LENGTH, (16 * 16) jbe %%_message_below_equal_16_blocks vmovdqa64 %%SHUF_MASK, [rel SHUF_MASK] vmovdqa64 %%ADDBE_4x4, [rel ddq_addbe_4444] vmovdqa64 %%ADDBE_1234, [rel ddq_addbe_1234] ;; start the pipeline ;; - 32 blocks aes-ctr ;; - 16 blocks ghash + aes-ctr ;; set up CTR_CHECK vmovd DWORD(%%CTR_CHECK), %%CTR_BLOCKx and DWORD(%%CTR_CHECK), 255 ;; in LE format after init, convert to BE vshufi64x2 %%CTR_BLOCKz, %%CTR_BLOCKz, %%CTR_BLOCKz, 0 vpshufb %%CTR_BLOCKz, %%CTR_BLOCKz, %%SHUF_MASK ;; ==== AES-CTR - first 16 blocks %assign aesout_offset (STACK_LOCAL_OFFSET + (0 * 16)) %assign data_in_out_offset 0 INITIAL_BLOCKS_16 %%PLAIN_CIPH_IN, %%CIPH_PLAIN_OUT, %%GDATA_KEY, %%DATA_OFFSET, \ no_ghash, %%CTR_BLOCKz, %%CTR_CHECK, %%ADDBE_4x4, %%ADDBE_1234, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, \ %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, \ %%SHUF_MASK, %%ENC_DEC, aesout_offset, data_in_out_offset cmp %%LENGTH, (32 * 16) jb %%_message_below_32_blocks ;; ==== AES-CTR - next 16 blocks %assign aesout_offset (STACK_LOCAL_OFFSET + (16 * 16)) %assign data_in_out_offset (16 * 16) INITIAL_BLOCKS_16 %%PLAIN_CIPH_IN, %%CIPH_PLAIN_OUT, %%GDATA_KEY, %%DATA_OFFSET, \ no_ghash, %%CTR_BLOCKz, %%CTR_CHECK, %%ADDBE_4x4, %%ADDBE_1234, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, \ %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, \ %%SHUF_MASK, %%ENC_DEC, aesout_offset, data_in_out_offset add %%DATA_OFFSET, (32 * 16) sub %%LENGTH, (32 * 16) cmp %%LENGTH, (big_loop_nblocks * 16) jb %%_no_more_big_nblocks ;; ==== ;; ==== AES-CTR + GHASH - 48 blocks loop ;; ==== %%_encrypt_big_nblocks: ;; ==== AES-CTR + GHASH - 16 blocks, start %assign aesout_offset (STACK_LOCAL_OFFSET + (32 * 16)) %assign data_in_out_offset (0 * 16) %assign ghashin_offset (STACK_LOCAL_OFFSET + (0 * 16)) GHASH_16_ENCRYPT_16_PARALLEL %%GDATA_KEY, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_48, aesout_offset, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11,\ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15,\ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, \ %%GL, %%GH, %%GM, \ first_time, %%ENC_DEC, data_in_out_offset, %%AAD_HASHz ;; ==== AES-CTR + GHASH - 16 blocks, no reduction %assign aesout_offset (STACK_LOCAL_OFFSET + (0 * 16)) %assign data_in_out_offset (16 * 16) %assign ghashin_offset (STACK_LOCAL_OFFSET + (16 * 16)) GHASH_16_ENCRYPT_16_PARALLEL %%GDATA_KEY, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_32, aesout_offset, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11,\ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15,\ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, \ %%GL, %%GH, %%GM, \ no_reduction, %%ENC_DEC, data_in_out_offset, no_ghash_in ;; ==== AES-CTR + GHASH - 16 blocks, reduction %assign aesout_offset (STACK_LOCAL_OFFSET + (16 * 16)) %assign data_in_out_offset (32 * 16) %assign ghashin_offset (STACK_LOCAL_OFFSET + (32 * 16)) GHASH_16_ENCRYPT_16_PARALLEL %%GDATA_KEY, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_16, aesout_offset, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11,\ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15,\ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, \ %%GL, %%GH, %%GM, \ final_reduction, %%ENC_DEC, data_in_out_offset, no_ghash_in ;; === xor cipher block 0 with GHASH (ZT4) vmovdqa64 %%AAD_HASHz, %%ZTMP4 add %%DATA_OFFSET, (big_loop_nblocks * 16) sub %%LENGTH, (big_loop_nblocks * 16) cmp %%LENGTH, (big_loop_nblocks * 16) jae %%_encrypt_big_nblocks %%_no_more_big_nblocks: cmp %%LENGTH, (32 * 16) jae %%_encrypt_32_blocks cmp %%LENGTH, (16 * 16) jae %%_encrypt_16_blocks ;; ===================================================== ;; ===================================================== ;; ==== GHASH 1 x 16 blocks ;; ==== GHASH 1 x 16 blocks (reduction) & encrypt N blocks ;; ==== then GHASH N blocks %%_encrypt_0_blocks_ghash_32: ;; calculate offset to the right hash key %ifidn %%INSTANCE_TYPE, multi_call mov DWORD(%%IA0), DWORD(%%LENGTH) %else lea DWORD(%%IA0), [DWORD(%%LENGTH) + 15] %endif and DWORD(%%IA0), ~15 mov DWORD(%%HASHK_PTR), HashKey_32 sub DWORD(%%HASHK_PTR), DWORD(%%IA0) ;; ==== GHASH 32 blocks and follow with reduction GHASH_16 start, %%GH, %%GM, %%GL, rsp, STACK_LOCAL_OFFSET, (0 * 16), %%GDATA_KEY, %%HASHK_PTR, 0, %%AAD_HASHz, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, %%ZTMP9 ;; ==== GHASH 1 x 16 blocks with reduction + cipher and ghash on the reminder %assign ghashin_offset (STACK_LOCAL_OFFSET + (16 * 16)) add DWORD(%%HASHK_PTR), (16 * 16) GCM_ENC_DEC_LAST \ %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%DATA_OFFSET, %%LENGTH, %%CTR_BLOCKz, %%CTR_CHECK, \ %%HASHK_PTR, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, \ %%ZTMP7, %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11, %%ZTMP12, %%ZTMP13, \ %%ZTMP14, %%ZTMP15, %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, %%ZTMP20, \ %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, mid, %%GL, %%GH, %%GM, \ %%ENC_DEC, %%AAD_HASHz, %%IA0, %%IA5, %%MASKREG, %%INSTANCE_TYPE %ifidn %%INSTANCE_TYPE, multi_call vpshufb %%CTR_BLOCKx, %%CTR_BLOCKx, XWORD(%%SHUF_MASK) %endif jmp %%_ghash_done ;; ===================================================== ;; ===================================================== ;; ==== GHASH & encrypt 1 x 16 blocks ;; ==== GHASH & encrypt 1 x 16 blocks ;; ==== GHASH 1 x 16 blocks (reduction) ;; ==== GHASH 1 x 16 blocks (reduction) & encrypt N blocks ;; ==== then GHASH N blocks %%_encrypt_32_blocks: ;; ==== AES-CTR + GHASH - 16 blocks, start %assign aesout_offset (STACK_LOCAL_OFFSET + (32 * 16)) %assign ghashin_offset (STACK_LOCAL_OFFSET + (0 * 16)) %assign data_in_out_offset (0 * 16) GHASH_16_ENCRYPT_16_PARALLEL %%GDATA_KEY, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_48, aesout_offset, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11,\ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15,\ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, \ %%GL, %%GH, %%GM, \ first_time, %%ENC_DEC, data_in_out_offset, %%AAD_HASHz ;; ==== AES-CTR + GHASH - 16 blocks, no reduction %assign aesout_offset (STACK_LOCAL_OFFSET + (0 * 16)) %assign ghashin_offset (STACK_LOCAL_OFFSET + (16 * 16)) %assign data_in_out_offset (16 * 16) GHASH_16_ENCRYPT_16_PARALLEL %%GDATA_KEY, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_32, aesout_offset, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11,\ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15,\ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, \ %%GL, %%GH, %%GM, \ no_reduction, %%ENC_DEC, data_in_out_offset, no_ghash_in ;; ==== GHASH 16 blocks with reduction GHASH_16 end_reduce, %%GH, %%GM, %%GL, rsp, STACK_LOCAL_OFFSET, (32 * 16), %%GDATA_KEY, HashKey_16, 0, %%AAD_HASHz, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, %%ZTMP9 ;; ==== GHASH 1 x 16 blocks with reduction + cipher and ghash on the reminder %assign ghashin_offset (STACK_LOCAL_OFFSET + (0 * 16)) sub %%LENGTH, (32 * 16) add %%DATA_OFFSET, (32 * 16) ;; calculate offset to the right hash key %ifidn %%INSTANCE_TYPE, multi_call mov DWORD(%%IA0), DWORD(%%LENGTH) %else lea DWORD(%%IA0), [DWORD(%%LENGTH) + 15] %endif and DWORD(%%IA0), ~15 mov DWORD(%%HASHK_PTR), HashKey_16 sub DWORD(%%HASHK_PTR), DWORD(%%IA0) GCM_ENC_DEC_LAST \ %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%DATA_OFFSET, %%LENGTH, %%CTR_BLOCKz, %%CTR_CHECK, \ %%HASHK_PTR, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, \ %%ZTMP7, %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11, %%ZTMP12, %%ZTMP13, \ %%ZTMP14, %%ZTMP15, %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, %%ZTMP20, \ %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, start, %%GL, %%GH, %%GM, \ %%ENC_DEC, %%AAD_HASHz, %%IA0, %%IA5, %%MASKREG, %%INSTANCE_TYPE %ifidn %%INSTANCE_TYPE, multi_call vpshufb %%CTR_BLOCKx, %%CTR_BLOCKx, XWORD(%%SHUF_MASK) %endif jmp %%_ghash_done ;; ===================================================== ;; ===================================================== ;; ==== GHASH & encrypt 16 blocks (done before) ;; ==== GHASH 1 x 16 blocks ;; ==== GHASH 1 x 16 blocks (reduction) & encrypt N blocks ;; ==== then GHASH N blocks %%_encrypt_16_blocks: ;; ==== AES-CTR + GHASH - 16 blocks, start %assign aesout_offset (STACK_LOCAL_OFFSET + (32 * 16)) %assign ghashin_offset (STACK_LOCAL_OFFSET + (0 * 16)) %assign data_in_out_offset (0 * 16) GHASH_16_ENCRYPT_16_PARALLEL %%GDATA_KEY, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, %%DATA_OFFSET, \ %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_48, aesout_offset, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11,\ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15,\ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, \ %%GL, %%GH, %%GM, \ first_time, %%ENC_DEC, data_in_out_offset, %%AAD_HASHz ;; ==== GHASH 1 x 16 blocks GHASH_16 mid, %%GH, %%GM, %%GL, rsp, STACK_LOCAL_OFFSET, (16 * 16), %%GDATA_KEY, HashKey_32, 0, no_hash_input, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, %%ZTMP8, %%ZTMP9 ;; ==== GHASH 1 x 16 blocks with reduction + cipher and ghash on the reminder %assign ghashin_offset (STACK_LOCAL_OFFSET + (32 * 16)) sub %%LENGTH, (16 * 16) add %%DATA_OFFSET, (16 * 16) GCM_ENC_DEC_LAST \ %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%DATA_OFFSET, %%LENGTH, %%CTR_BLOCKz, %%CTR_CHECK, \ HashKey_16, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, \ %%ZTMP7, %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11, %%ZTMP12, %%ZTMP13, \ %%ZTMP14, %%ZTMP15, %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, %%ZTMP20, \ %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, end_reduce, %%GL, %%GH, %%GM, \ %%ENC_DEC, %%AAD_HASHz, %%IA0, %%IA5, %%MASKREG, %%INSTANCE_TYPE %ifidn %%INSTANCE_TYPE, multi_call vpshufb %%CTR_BLOCKx, %%CTR_BLOCKx, XWORD(%%SHUF_MASK) %endif jmp %%_ghash_done %%_message_below_32_blocks: ;; 32 > number of blocks > 16 sub %%LENGTH, (16 * 16) add %%DATA_OFFSET, (16 * 16) %assign ghashin_offset (STACK_LOCAL_OFFSET + (0 * 16)) ;; calculate offset to the right hash key %ifidn %%INSTANCE_TYPE, multi_call mov DWORD(%%IA0), DWORD(%%LENGTH) %else lea DWORD(%%IA0), [DWORD(%%LENGTH) + 15] %endif and DWORD(%%IA0), ~15 mov DWORD(%%HASHK_PTR), HashKey_16 sub DWORD(%%HASHK_PTR), DWORD(%%IA0) GCM_ENC_DEC_LAST \ %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%DATA_OFFSET, %%LENGTH, %%CTR_BLOCKz, %%CTR_CHECK, \ %%HASHK_PTR, ghashin_offset, %%SHUF_MASK, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, %%ZTMP4, %%ZTMP5, %%ZTMP6, \ %%ZTMP7, %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11, %%ZTMP12, %%ZTMP13, \ %%ZTMP14, %%ZTMP15, %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, %%ZTMP20, \ %%ZTMP21, %%ZTMP22, \ %%ADDBE_4x4, %%ADDBE_1234, start, %%GL, %%GH, %%GM, \ %%ENC_DEC, %%AAD_HASHz, %%IA0, %%IA5, %%MASKREG, %%INSTANCE_TYPE %ifidn %%INSTANCE_TYPE, multi_call vpshufb %%CTR_BLOCKx, %%CTR_BLOCKx, XWORD(%%SHUF_MASK) %endif jmp %%_ghash_done %%_message_below_equal_16_blocks: ;; Determine how many blocks to process ;; - process one additional block if there is a partial block mov DWORD(%%IA1), DWORD(%%LENGTH) add DWORD(%%IA1), 15 shr DWORD(%%IA1), 4 ;; %%IA1 can be in the range from 0 to 16 GCM_ENC_DEC_SMALL \ %%GDATA_KEY, %%GDATA_CTX, %%CIPH_PLAIN_OUT, %%PLAIN_CIPH_IN, \ %%PLAIN_CIPH_LEN, %%ENC_DEC, %%DATA_OFFSET, \ %%LENGTH, %%IA1, %%CTR_BLOCKx, %%AAD_HASHx, %%INSTANCE_TYPE, \ %%ZTMP0, %%ZTMP1, %%ZTMP2, %%ZTMP3, \ %%ZTMP4, %%ZTMP5, %%ZTMP6, %%ZTMP7, \ %%ZTMP8, %%ZTMP9, %%ZTMP10, %%ZTMP11, \ %%ZTMP12, %%ZTMP13, %%ZTMP14, %%ZTMP15, \ %%ZTMP16, %%ZTMP17, %%ZTMP18, %%ZTMP19, \ %%ZTMP20, %%ZTMP21, %%ZTMP22, \ %%IA0, %%IA3, %%MASKREG, %%SHUF_MASK ;; fall through to exit %%_ghash_done: %ifidn %%INSTANCE_TYPE, multi_call ;; save the last counter block vmovdqu64 [%%GDATA_CTX + CurCount], %%CTR_BLOCKx %endif vmovdqu64 [%%GDATA_CTX + AadHash], %%AAD_HASHx %%_enc_dec_done: %endmacro ; GCM_ENC_DEC ;;; =========================================================================== ;;; =========================================================================== ;;; Encrypt/decrypt the initial 16 blocks %macro INITIAL_BLOCKS_16 22 %define %%IN %1 ; [in] input buffer %define %%OUT %2 ; [in] output buffer %define %%KP %3 ; [in] pointer to expanded keys %define %%DATA_OFFSET %4 ; [in] data offset %define %%GHASH %5 ; [in] ZMM with AAD (low 128 bits) %define %%CTR %6 ; [in] ZMM with CTR BE blocks 4x128 bits %define %%CTR_CHECK %7 ; [in/out] GPR with counter overflow check %define %%ADDBE_4x4 %8 ; [in] ZMM 4x128bits with value 4 (big endian) %define %%ADDBE_1234 %9 ; [in] ZMM 4x128bits with values 1, 2, 3 & 4 (big endian) %define %%T0 %10 ; [clobered] temporary ZMM register %define %%T1 %11 ; [clobered] temporary ZMM register %define %%T2 %12 ; [clobered] temporary ZMM register %define %%T3 %13 ; [clobered] temporary ZMM register %define %%T4 %14 ; [clobered] temporary ZMM register %define %%T5 %15 ; [clobered] temporary ZMM register %define %%T6 %16 ; [clobered] temporary ZMM register %define %%T7 %17 ; [clobered] temporary ZMM register %define %%T8 %18 ; [clobered] temporary ZMM register %define %%SHUF_MASK %19 ; [in] ZMM with BE/LE shuffle mask %define %%ENC_DEC %20 ; [in] ENC (encrypt) or DEC (decrypt) selector %define %%BLK_OFFSET %21 ; [in] stack frame offset to ciphered blocks %define %%DATA_DISPL %22 ; [in] fixed numerical data displacement/offset %define %%B00_03 %%T5 %define %%B04_07 %%T6 %define %%B08_11 %%T7 %define %%B12_15 %%T8 %assign stack_offset (%%BLK_OFFSET) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; prepare counter blocks cmp BYTE(%%CTR_CHECK), (256 - 16) jae %%_next_16_overflow vpaddd %%B00_03, %%CTR, %%ADDBE_1234 vpaddd %%B04_07, %%B00_03, %%ADDBE_4x4 vpaddd %%B08_11, %%B04_07, %%ADDBE_4x4 vpaddd %%B12_15, %%B08_11, %%ADDBE_4x4 jmp %%_next_16_ok %%_next_16_overflow: vpshufb %%CTR, %%CTR, %%SHUF_MASK vmovdqa64 %%B12_15, [rel ddq_add_4444] vpaddd %%B00_03, %%CTR, [rel ddq_add_1234] vpaddd %%B04_07, %%B00_03, %%B12_15 vpaddd %%B08_11, %%B04_07, %%B12_15 vpaddd %%B12_15, %%B08_11, %%B12_15 vpshufb %%B00_03, %%SHUF_MASK vpshufb %%B04_07, %%SHUF_MASK vpshufb %%B08_11, %%SHUF_MASK vpshufb %%B12_15, %%SHUF_MASK %%_next_16_ok: vshufi64x2 %%CTR, %%B12_15, %%B12_15, 1111_1111b add BYTE(%%CTR_CHECK), 16 ;; === load 16 blocks of data VX512LDR %%T0, [%%IN + %%DATA_OFFSET + %%DATA_DISPL + (64*0)] VX512LDR %%T1, [%%IN + %%DATA_OFFSET + %%DATA_DISPL + (64*1)] VX512LDR %%T2, [%%IN + %%DATA_OFFSET + %%DATA_DISPL + (64*2)] VX512LDR %%T3, [%%IN + %%DATA_OFFSET + %%DATA_DISPL + (64*3)] ;; move to AES encryption rounds %assign i 0 vbroadcastf64x2 %%T4, [%%KP + (16*i)] vpxorq %%B00_03, %%B00_03, %%T4 vpxorq %%B04_07, %%B04_07, %%T4 vpxorq %%B08_11, %%B08_11, %%T4 vpxorq %%B12_15, %%B12_15, %%T4 %assign i (i + 1) %rep NROUNDS vbroadcastf64x2 %%T4, [%%KP + (16*i)] vaesenc %%B00_03, %%B00_03, %%T4 vaesenc %%B04_07, %%B04_07, %%T4 vaesenc %%B08_11, %%B08_11, %%T4 vaesenc %%B12_15, %%B12_15, %%T4 %assign i (i + 1) %endrep vbroadcastf64x2 %%T4, [%%KP + (16*i)] vaesenclast %%B00_03, %%B00_03, %%T4 vaesenclast %%B04_07, %%B04_07, %%T4 vaesenclast %%B08_11, %%B08_11, %%T4 vaesenclast %%B12_15, %%B12_15, %%T4 ;; xor against text vpxorq %%B00_03, %%B00_03, %%T0 vpxorq %%B04_07, %%B04_07, %%T1 vpxorq %%B08_11, %%B08_11, %%T2 vpxorq %%B12_15, %%B12_15, %%T3 ;; store VX512STR [%%OUT + %%DATA_OFFSET + %%DATA_DISPL + (64*0)], %%B00_03 VX512STR [%%OUT + %%DATA_OFFSET + %%DATA_DISPL + (64*1)], %%B04_07 VX512STR [%%OUT + %%DATA_OFFSET + %%DATA_DISPL + (64*2)], %%B08_11 VX512STR [%%OUT + %%DATA_OFFSET + %%DATA_DISPL + (64*3)], %%B12_15 %ifidn %%ENC_DEC, DEC ;; decryption - cipher text needs to go to GHASH phase vpshufb %%B00_03, %%T0, %%SHUF_MASK vpshufb %%B04_07, %%T1, %%SHUF_MASK vpshufb %%B08_11, %%T2, %%SHUF_MASK vpshufb %%B12_15, %%T3, %%SHUF_MASK %else ;; encryption vpshufb %%B00_03, %%B00_03, %%SHUF_MASK vpshufb %%B04_07, %%B04_07, %%SHUF_MASK vpshufb %%B08_11, %%B08_11, %%SHUF_MASK vpshufb %%B12_15, %%B12_15, %%SHUF_MASK %endif %ifnidn %%GHASH, no_ghash ;; === xor cipher block 0 with GHASH for the next GHASH round vpxorq %%B00_03, %%B00_03, %%GHASH %endif vmovdqa64 [rsp + stack_offset + (0 * 64)], %%B00_03 vmovdqa64 [rsp + stack_offset + (1 * 64)], %%B04_07 vmovdqa64 [rsp + stack_offset + (2 * 64)], %%B08_11 vmovdqa64 [rsp + stack_offset + (3 * 64)], %%B12_15 %endmacro ;INITIAL_BLOCKS_16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GCM_COMPLETE Finishes Encryption/Decryption of last partial block after GCM_UPDATE finishes. ; Input: A gcm_key_data * (GDATA_KEY), gcm_context_data (GDATA_CTX). ; Output: Authorization Tag (AUTH_TAG) and Authorization Tag length (AUTH_TAG_LEN) ; Clobbers xmm0-xmm2, xmm5-xmm6, xmm9-xmm11, xmm13-xmm15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro GCM_COMPLETE 9 %define %%GDATA_KEY %1 ; [in] GP with pointer to key structure %define %%GDATA_CTX %2 ; [in] GP with pointer to context structure %define %%AUTH_TAG %3 ; [in] pointer to store auth tag into (GP or mem) %define %%AUTH_TAG_LEN %4 ; [in] length in bytes of auth tag (GP or mem) %define %%INSTANCE_TYPE %5 ; [in] instance type "single_call" vs "multi_call" %define %%MASKREG %6 ; [clobbered] temporary K register %define %%IA0 %7 ; [clobbered] temporary GP %define %%IA1 %8 ; [clobbered] temporary GP %define %%IA2 %9 ; [clobbered] temporary GP ;; @note: xmm14 is hardcoded for hash input in singe_call case vmovdqu xmm13, [%%GDATA_KEY + HashKey] ;; Start AES as early as possible vmovdqu xmm9, [%%GDATA_CTX + OrigIV] ; xmm9 = Y0 ENCRYPT_SINGLE_BLOCK %%GDATA_KEY, xmm9 ; E(K, Y0) %ifidn %%INSTANCE_TYPE, multi_call ;; If the GCM function is called as a single function call rather ;; than invoking the individual parts (init, update, finalize) we ;; can remove a write to read dependency on AadHash. vmovdqu xmm14, [%%GDATA_CTX + AadHash] ;; Encrypt of the final partial block was already done in the main GCM_ENC_DEC macro. ;; It may be required to GHASH it now cmp qword [%%GDATA_CTX + PBlockLen], 0 je %%_partial_done ;; GHASH computation for the last <16 Byte block GHASH_MUL xmm14, xmm13, xmm0, xmm10, xmm11, xmm5, xmm6 %%_partial_done: %endif vmovq xmm15, [%%GDATA_CTX + InLen] vpinsrq xmm15, [%%GDATA_CTX + AadLen], 1 ; xmm15 = len(A)||len(C) vpsllq xmm15, xmm15, 3 ; convert bytes into bits vpxor xmm14, xmm15 GHASH_MUL xmm14, xmm13, xmm0, xmm10, xmm11, xmm5, xmm6 vpshufb xmm14, [rel SHUF_MASK] ; perform a 16Byte swap vpxor xmm9, xmm9, xmm14 ;; xmm9 includes the final TAG mov %%IA0, %%AUTH_TAG ; r10 = authTag mov %%IA1, %%AUTH_TAG_LEN ; r11 = auth_tag_len cmp %%IA1, 16 je %%_T_16 cmp %%IA1, 12 je %%_T_12 cmp %%IA1, 8 je %%_T_8 lea %%IA2, [rel byte64_len_to_mask_table] kmovq %%MASKREG, [%%IA2 + %%IA1*8] vmovdqu8 [%%IA0]{%%MASKREG}, xmm9 jmp %%_return_T_done %%_T_8: vmovq [%%IA0], xmm9 jmp %%_return_T_done %%_T_12: vmovq [%%IA0], xmm9 vpextrd [%%IA0 + 8], xmm9, 2 jmp %%_return_T_done %%_T_16: vmovdqu [%%IA0], xmm9 %%_return_T_done: ;; IPPCP: disabled clearing of context fields, as in IPPCP case GetTag may be called ;; several times and it should not stop GCM processing. Context zeroing is done by user. ;; https://www.intel.com/content/www/us/en/docs/ipp-crypto/developer-reference/current/aes-gcm-functions.html ;; %ifdef SAFE_DATA ;; ;; Clear sensitive data from context structure ;; vpxor xmm0, xmm0 ;; vmovdqu [%%GDATA_CTX + AadHash], xmm0 ;; %ifidn %%INSTANCE_TYPE, multi_call ;; vmovdqu [%%GDATA_CTX + PBlockEncKey], xmm0 ;; %endif ;; %endif %endmacro ; GCM_COMPLETE %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/ia_32e_regs.inc000066400000000000000000000046151470420105600261410ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2012 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: EM64T Cryptography Primitive. ; ; ; ;; ;; Just for unify GPRs usage ;; %ifndef _IA_32_REGS_INC_ %define _IA_32_REGS_INC_ %define r0 rax ;; 64-bits GPRs %define r1 rbx %define r2 rcx %define r3 rdx %define r4 rdi %define r5 rsi %define r6 rbp %define r7 rsp %define r0d eax ;; 32-bits GPRs %define r1d ebx %define r2d ecx %define r3d edx %define r4d edi %define r5d esi %define r6d ebp %define r7d esp %define raxd eax %define rbxd ebx %define rcxd ecx %define rdxd edx %define rdid edi %define rsid esi %define rbpd ebp %define r0w ax ;; 16-bits GPRs %define r1w bx %define r2w cx %define r3w dx %define r4w di %define r5w si %define r6w bp %define r7w sp %define raxw ax %define rbxw bx %define rcxw cx %define rdxw dx %define rdiw di %define rsiw si %define rbpw bp %define r0b al ;; 8-bits GPRs %define r1b bl %define r2b cl %define r3b dl %define r4b dil %define r5b sil %define r6b bpl %define r7b spl %define raxb al %define rbxb bl %define rcxb cl %define rdxb dl %define rdib dil %define rsib sil %define rbpb bpl %define raxbl al %define rbxbl bl %define rcxbl cl %define rdxbl dl %define raxbh ah %define rbxbh bh %define rcxbh ch %define rdxbh dh ;; ;; Register Parameters (depend on used OS) ;; %ifdef WIN32E %define rpar1 rcx %define rpar2 rdx %define rpar3 r8 %define rpar4 r9 %define rpar5 [rsp + ARG_5] %define rpar6 [rsp + ARG_6] %endif %ifdef LINUX32E %define rpar1 rdi %define rpar2 rsi %define rpar3 rdx %define rpar4 rcx %define rpar5 r8 %define rpar6 r9 %endif ;; use GPR implementation everywhere possible %assign GPR_version 1 %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/memcpy.inc000066400000000000000000000374671470420105600253640ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 __MEMCPY_ASM__ %define __MEMCPY_ASM__ %include "reg_sizes.inc" ; This section defines a series of macros to copy small to medium amounts ; of data from memory to memory, where the size is variable but limited. ; ; The macros are all called as: ; memcpy DST, SRC, SIZE, TMP0, TMP1, XTMP0, XTMP1, XTMP2, XTMP3 ; with the parameters defined as: ; DST : register: pointer to dst (not modified) ; SRC : register: pointer to src (not modified) ; SIZE : register: length in bytes (not modified) ; TMP0 : 64-bit temp GPR (clobbered) ; TMP1 : 64-bit temp GPR (clobbered) ; XTMP0 : temp XMM (clobbered) ; XTMP1 : temp XMM (clobbered) ; XTMP2 : temp XMM (clobbered) ; XTMP3 : temp XMM (clobbered) ; ; The name indicates the options. The name is of the form: ; memcpy__ ; where: ; is either "sse" or "avx" or "avx2" ; is either "64" or "128" and defines largest value of SIZE ; is blank or "_1". If "_1" then the min SIZE is 1 (otherwise 0) ; is blank or "_ret". If blank, the code falls through. If "ret" ; it does a "ret" at the end ; ; For the avx2 versions, the temp XMM registers need to be YMM registers ; If the SZ is 64, then only two YMM temps are needed, i.e. it is called as: ; memcpy_avx2_64 DST, SRC, SIZE, TMP0, TMP1, YTMP0, YTMP1 ; memcpy_avx2_128 DST, SRC, SIZE, TMP0, TMP1, YTMP0, YTMP1, YTMP2, YTMP3 ; ; For example: ; memcpy_sse_64 : SSE, 0 <= size < 64, falls through ; memcpy_avx_64_1 : AVX1, 1 <= size < 64, falls through ; memcpy_sse_128_ret : SSE, 0 <= size < 128, ends with ret ; mempcy_avx_128_1_ret : AVX1, 1 <= size < 128, ends with ret ; %macro memcpy_sse_64 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 64, 0, 0 %endm %macro memcpy_sse_64_1 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 64, 0, 0 %endm %macro memcpy_sse_128 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 128, 0, 0 %endm %macro memcpy_sse_128_1 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 128, 0, 0 %endm %macro memcpy_sse_64_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 64, 1, 0 %endm %macro memcpy_sse_64_1_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 64, 1, 0 %endm %macro memcpy_sse_128_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 128, 1, 0 %endm %macro memcpy_sse_128_1_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 128, 1, 0 %endm %macro memcpy_sse_16 5 __memcpy_int %1,%2,%3,%4,%5,,,,, 0, 16, 0, 0 %endm %macro memcpy_sse_16_1 5 __memcpy_int %1,%2,%3,%4,%5,,,,, 1, 16, 0, 0 %endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro memcpy_avx_64 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 64, 0, 1 %endm %macro memcpy_avx_64_1 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 64, 0, 1 %endm %macro memcpy_avx_128 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 128, 0, 1 %endm %macro memcpy_avx_128_1 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 128, 0, 1 %endm %macro memcpy_avx_64_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 64, 1, 1 %endm %macro memcpy_avx_64_1_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 64, 1, 1 %endm %macro memcpy_avx_128_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 128, 1, 1 %endm %macro memcpy_avx_128_1_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 128, 1, 1 %endm %macro memcpy_avx_16 5 __memcpy_int %1,%2,%3,%4,%5,,,,, 0, 16, 0, 1 %endm %macro memcpy_avx_16_1 5 __memcpy_int %1,%2,%3,%4,%5,,,,, 1, 16, 0, 1 %endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro memcpy_avx2_64 7 __memcpy_int %1,%2,%3,%4,%5,%6,%7,--,--, 0, 64, 0, 2 %endm %macro memcpy_avx2_64_1 7 __memcpy_int %1,%2,%3,%4,%5,%6,%7,--,--, 1, 64, 0, 2 %endm %macro memcpy_avx2_128 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7, %8, %9, 0, 128, 0, 2 %endm %macro memcpy_avx2_128_1 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7, %8, %9, 1, 128, 0, 2 %endm %macro memcpy_avx2_64_ret 7 __memcpy_int %1,%2,%3,%4,%5,%6,%7,--,--, 0, 64, 1, 2 %endm %macro memcpy_avx2_64_1_ret 7 __memcpy_int %1,%2,%3,%4,%5,%6,%7,--,--, 1, 64, 1, 2 %endm %macro memcpy_avx2_128_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 0, 128, 1, 2 %endm %macro memcpy_avx2_128_1_ret 9 __memcpy_int %1,%2,%3,%4,%5,%6,%7,%8,%9, 1, 128, 1, 2 %endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro __memcpy_int 13 %define %%DST %1 ; register: pointer to dst (not modified) %define %%SRC %2 ; register: pointer to src (not modified) %define %%SIZE %3 ; register: length in bytes (not modified) %define %%TMP0 %4 ; 64-bit temp GPR (clobbered) %define %%TMP1 %5 ; 64-bit temp GPR (clobbered) %define %%XTMP0 %6 ; temp XMM (clobbered) %define %%XTMP1 %7 ; temp XMM (clobbered) %define %%XTMP2 %8 ; temp XMM (clobbered) %define %%XTMP3 %9 ; temp XMM (clobbered) %define %%NOT0 %10 ; if not 0, then assume size cannot be zero %define %%MAXSIZE %11 ; 128, 64, etc %define %%USERET %12 ; if not 0, use "ret" at end %define %%USEAVX %13 ; 0 = SSE, 1 = AVX1, 2 = AVX2 %if (%%USERET != 0) %define %%DONE ret %else %define %%DONE jmp %%end %endif %if (%%USEAVX != 0) %define %%MOVDQU vmovdqu %else %define %%MOVDQU movdqu %endif %if (%%MAXSIZE >= 128) test %%SIZE, 64 jz %%lt64 %if (%%USEAVX >= 2) %%MOVDQU %%XTMP0, [%%SRC + 0*32] %%MOVDQU %%XTMP1, [%%SRC + 1*32] %%MOVDQU %%XTMP2, [%%SRC + %%SIZE - 2*32] %%MOVDQU %%XTMP3, [%%SRC + %%SIZE - 1*32] %%MOVDQU [%%DST + 0*32], %%XTMP0 %%MOVDQU [%%DST + 1*32], %%XTMP1 %%MOVDQU [%%DST + %%SIZE - 2*32], %%XTMP2 %%MOVDQU [%%DST + %%SIZE - 1*32], %%XTMP3 %else %%MOVDQU %%XTMP0, [%%SRC + 0*16] %%MOVDQU %%XTMP1, [%%SRC + 1*16] %%MOVDQU %%XTMP2, [%%SRC + 2*16] %%MOVDQU %%XTMP3, [%%SRC + 3*16] %%MOVDQU [%%DST + 0*16], %%XTMP0 %%MOVDQU [%%DST + 1*16], %%XTMP1 %%MOVDQU [%%DST + 2*16], %%XTMP2 %%MOVDQU [%%DST + 3*16], %%XTMP3 %%MOVDQU %%XTMP0, [%%SRC + %%SIZE - 4*16] %%MOVDQU %%XTMP1, [%%SRC + %%SIZE - 3*16] %%MOVDQU %%XTMP2, [%%SRC + %%SIZE - 2*16] %%MOVDQU %%XTMP3, [%%SRC + %%SIZE - 1*16] %%MOVDQU [%%DST + %%SIZE - 4*16], %%XTMP0 %%MOVDQU [%%DST + %%SIZE - 3*16], %%XTMP1 %%MOVDQU [%%DST + %%SIZE - 2*16], %%XTMP2 %%MOVDQU [%%DST + %%SIZE - 1*16], %%XTMP3 %endif %%DONE %endif %if (%%MAXSIZE >= 64) %%lt64: test %%SIZE, 32 jz %%lt32 %if (%%USEAVX >= 2) %%MOVDQU %%XTMP0, [%%SRC + 0*32] %%MOVDQU %%XTMP1, [%%SRC + %%SIZE - 1*32] %%MOVDQU [%%DST + 0*32], %%XTMP0 %%MOVDQU [%%DST + %%SIZE - 1*32], %%XTMP1 %else %%MOVDQU %%XTMP0, [%%SRC + 0*16] %%MOVDQU %%XTMP1, [%%SRC + 1*16] %%MOVDQU %%XTMP2, [%%SRC + %%SIZE - 2*16] %%MOVDQU %%XTMP3, [%%SRC + %%SIZE - 1*16] %%MOVDQU [%%DST + 0*16], %%XTMP0 %%MOVDQU [%%DST + 1*16], %%XTMP1 %%MOVDQU [%%DST + %%SIZE - 2*16], %%XTMP2 %%MOVDQU [%%DST + %%SIZE - 1*16], %%XTMP3 %endif %%DONE %endif %if (%%MAXSIZE >= 32) %%lt32: test %%SIZE, 16 jz %%lt16 %if (%%USEAVX >= 2) %%MOVDQU XWORD(%%XTMP0), [%%SRC + 0*16] %%MOVDQU XWORD(%%XTMP1), [%%SRC + %%SIZE - 1*16] %%MOVDQU [%%DST + 0*16], XWORD(%%XTMP0) %%MOVDQU [%%DST + %%SIZE - 1*16], XWORD(%%XTMP1) %else %%MOVDQU %%XTMP0, [%%SRC + 0*16] %%MOVDQU %%XTMP1, [%%SRC + %%SIZE - 1*16] %%MOVDQU [%%DST + 0*16], %%XTMP0 %%MOVDQU [%%DST + %%SIZE - 1*16], %%XTMP1 %endif %%DONE %endif %if (%%MAXSIZE >= 16) %%lt16: test %%SIZE, 8 jz %%lt8 mov %%TMP0, [%%SRC] mov %%TMP1, [%%SRC + %%SIZE - 8] mov [%%DST], %%TMP0 mov [%%DST + %%SIZE - 8], %%TMP1 %%DONE %endif %if (%%MAXSIZE >= 8) %%lt8: test %%SIZE, 4 jz %%lt4 mov DWORD(%%TMP0), [%%SRC] mov DWORD(%%TMP1), [%%SRC + %%SIZE - 4] mov [%%DST], DWORD(%%TMP0) mov [%%DST + %%SIZE - 4], DWORD(%%TMP1) %%DONE %endif %if (%%MAXSIZE >= 4) %%lt4: test %%SIZE, 2 jz %%lt2 movzx DWORD(%%TMP0), word [%%SRC] movzx DWORD(%%TMP1), byte [%%SRC + %%SIZE - 1] mov [%%DST], WORD(%%TMP0) mov [%%DST + %%SIZE - 1], BYTE(%%TMP1) %%DONE %endif %%lt2: %if (%%NOT0 == 0) test %%SIZE, 1 jz %%end %endif movzx DWORD(%%TMP0), byte [%%SRC] mov [%%DST], BYTE(%%TMP0) %%end: %if (%%USERET != 0) ret %endif %endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Utility macro to assist with SIMD shifting %macro _PSRLDQ 3 %define %%VEC %1 %define %%REG %2 %define %%IMM %3 %ifidn %%VEC, SSE psrldq %%REG, %%IMM %else vpsrldq %%REG, %%REG, %%IMM %endif %endm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This section defines a series of macros to store small to medium amounts ; of data from SIMD registers to memory, where the size is variable but limited. ; ; The macros are all called as: ; memcpy DST, SRC, SIZE, TMP, IDX ; with the parameters defined as: ; DST : register: pointer to dst (not modified) ; SRC : register: src data (clobbered) ; SIZE : register: length in bytes (not modified) ; TMP : 64-bit temp GPR (clobbered) ; IDX : 64-bit GPR to store dst index/offset (clobbered) ; ; The name indicates the options. The name is of the form: ; simd_store_ ; where is the SIMD instruction type e.g. "sse" or "avx" %macro simd_store_sse 5 __simd_store %1,%2,%3,%4,%5,SSE %endm %macro simd_store_avx 5 __simd_store %1,%2,%3,%4,%5,AVX %endm %macro simd_store_sse_15 5 __simd_store %1,%2,%3,%4,%5,SSE,15 %endm %macro simd_store_avx_15 5 __simd_store %1,%2,%3,%4,%5,AVX,15 %endm %macro __simd_store 6-7 %define %%DST %1 ; register: pointer to dst (not modified) %define %%SRC %2 ; register: src data (clobbered) %define %%SIZE %3 ; register: length in bytes (not modified) %define %%TMP %4 ; 64-bit temp GPR (clobbered) %define %%IDX %5 ; 64-bit temp GPR to store dst idx (clobbered) %define %%SIMDTYPE %6 ; "SSE" or "AVX" %define %%MAX_LEN %7 ; [optional] maximum length to be stored, default 16 %define %%PSRLDQ _PSRLDQ %%SIMDTYPE, %ifidn %%SIMDTYPE, SSE %define %%MOVDQU movdqu %define %%MOVQ movq %else %define %%MOVDQU vmovdqu %define %%MOVQ vmovq %endif ;; determine max byte size for store operation %if %0 > 6 %assign max_length_to_store %%MAX_LEN %else %assign max_length_to_store 16 %endif %if max_length_to_store > 16 %error "__simd_store macro invoked with MAX_LEN bigger than 16!" %endif xor %%IDX, %%IDX ; zero idx %if max_length_to_store == 16 test %%SIZE, 16 jz %%lt16 %%MOVDQU [%%DST], %%SRC jmp %%end %%lt16: %endif %if max_length_to_store >= 8 test %%SIZE, 8 jz %%lt8 %%MOVQ [%%DST + %%IDX], %%SRC %%PSRLDQ %%SRC, 8 add %%IDX, 8 %%lt8: %endif %%MOVQ %%TMP, %%SRC ; use GPR from now on %if max_length_to_store >= 4 test %%SIZE, 4 jz %%lt4 mov [%%DST + %%IDX], DWORD(%%TMP) shr %%TMP, 32 add %%IDX, 4 %%lt4: %endif test %%SIZE, 2 jz %%lt2 mov [%%DST + %%IDX], WORD(%%TMP) shr %%TMP, 16 add %%IDX, 2 %%lt2: test %%SIZE, 1 jz %%end mov [%%DST + %%IDX], BYTE(%%TMP) %%end: %endm ; This section defines a series of macros to load small to medium amounts ; (from 0 to 16 bytes) of data from memory to SIMD registers, ; where the size is variable but limited. ; ; The macros are all called as: ; simd_load DST, SRC, SIZE ; with the parameters defined as: ; DST : register: destination XMM register ; SRC : register: pointer to src data (not modified) ; SIZE : register: length in bytes (not modified) ; ; The name indicates the options. The name is of the form: ; simd_load__ ; where: ; is either "sse" or "avx" ; is either "15" or "16" and defines largest value of SIZE ; is blank or "_1". If "_1" then the min SIZE is 1 (otherwise 0) ; ; For example: ; simd_load_sse_16 : SSE, 0 <= size <= 16 ; simd_load_avx_15_1 : AVX, 1 <= size <= 15 %macro simd_load_sse_15_1 3 __simd_load %1,%2,%3,0,0,SSE %endm %macro simd_load_sse_15 3 __simd_load %1,%2,%3,1,0,SSE %endm %macro simd_load_sse_16_1 3 __simd_load %1,%2,%3,0,1,SSE %endm %macro simd_load_sse_16 3 __simd_load %1,%2,%3,1,1,SSE %endm %macro simd_load_avx_15_1 3 __simd_load %1,%2,%3,0,0,AVX %endm %macro simd_load_avx_15 3 __simd_load %1,%2,%3,1,0,AVX %endm %macro simd_load_avx_16_1 3 __simd_load %1,%2,%3,0,1,AVX %endm %macro simd_load_avx_16 3 __simd_load %1,%2,%3,1,1,AVX %endm %macro __simd_load 6 %define %%DST %1 ; [out] destination XMM register %define %%SRC %2 ; [in] pointer to src data %define %%SIZE %3 ; [in] length in bytes (0-16 bytes) %define %%ACCEPT_0 %4 ; 0 = min length = 1, 1 = min length = 0 %define %%ACCEPT_16 %5 ; 0 = max length = 15 , 1 = max length = 16 %define %%SIMDTYPE %6 ; "SSE" or "AVX" %ifidn %%SIMDTYPE, SSE %define %%MOVDQU movdqu %define %%PINSRB pinsrb %define %%PINSRQ pinsrq %define %%PXOR pxor %else %define %%MOVDQU vmovdqu %define %%PINSRB vpinsrb %define %%PINSRQ vpinsrq %define %%PXOR vpxor %endif %if (%%ACCEPT_16 != 0) test %%SIZE, 16 jz %%_skip_16 %%MOVDQU %%DST, [%%SRC] jmp %%end_load %%_skip_16: %endif %%PXOR %%DST, %%DST ; clear XMM register %if (%%ACCEPT_0 != 0) or %%SIZE, %%SIZE je %%end_load %endif cmp %%SIZE, 1 je %%_size_1 cmp %%SIZE, 2 je %%_size_2 cmp %%SIZE, 3 je %%_size_3 cmp %%SIZE, 4 je %%_size_4 cmp %%SIZE, 5 je %%_size_5 cmp %%SIZE, 6 je %%_size_6 cmp %%SIZE, 7 je %%_size_7 cmp %%SIZE, 8 je %%_size_8 cmp %%SIZE, 9 je %%_size_9 cmp %%SIZE, 10 je %%_size_10 cmp %%SIZE, 11 je %%_size_11 cmp %%SIZE, 12 je %%_size_12 cmp %%SIZE, 13 je %%_size_13 cmp %%SIZE, 14 je %%_size_14 %%_size_15: %%PINSRB %%DST, [%%SRC + 14], 14 %%_size_14: %%PINSRB %%DST, [%%SRC + 13], 13 %%_size_13: %%PINSRB %%DST, [%%SRC + 12], 12 %%_size_12: %%PINSRB %%DST, [%%SRC + 11], 11 %%_size_11: %%PINSRB %%DST, [%%SRC + 10], 10 %%_size_10: %%PINSRB %%DST, [%%SRC + 9], 9 %%_size_9: %%PINSRB %%DST, [%%SRC + 8], 8 %%_size_8: %%PINSRQ %%DST, [%%SRC], 0 jmp %%end_load %%_size_7: %%PINSRB %%DST, [%%SRC + 6], 6 %%_size_6: %%PINSRB %%DST, [%%SRC + 5], 5 %%_size_5: %%PINSRB %%DST, [%%SRC + 4], 4 %%_size_4: %%PINSRB %%DST, [%%SRC + 3], 3 %%_size_3: %%PINSRB %%DST, [%%SRC + 2], 2 %%_size_2: %%PINSRB %%DST, [%%SRC + 1], 1 %%_size_1: %%PINSRB %%DST, [%%SRC + 0], 0 %%end_load: %endm %endif ; ifndef __MEMCPY_ASM__ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/os.inc000066400000000000000000000021251470420105600244720ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 OS_ASM_FILE %define OS_ASM_FILE %ifndef WIN_ABI %ifidn __OUTPUT_FORMAT__, win64 %define WIN_ABI %endif %endif %ifndef LINUX %ifidn __OUTPUT_FORMAT__, elf64 %define LINUX %endif %endif ;; code is the same for linux and macos %ifndef LINUX %ifidn __OUTPUT_FORMAT__, macho64 %define LINUX %endif %endif %endif ; OS_ASM_FILE cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpaesgcme9as.asm000066400000000000000000001052661470420105600266160ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; AES-GCM function ; ; Content: ; AesGcmPrecompute_avx() ; AesGcmMulGcm_avx() ; AesGcmAuth_avx() ; AesGcmEnc_avx() ; AesGcmDec_avx() ; %include "asmdefs.inc" %include "ia_32e.inc" %assign my_emulator 0; set 1 for emulation %include "emulator.inc" ; sse_clmul_gcm MACRO to implement: Data*HashKey mod (128,127,126,121,0) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %assign REFLECTED_IN_OUT 1 ; GCM input and output are represented in reflected form naturally ;USE_BYTE_REFLECTED = 0 ; set to 1 %if input data is byte-reflected %macro sse_clmul_gcm_2way 11.nolist %xdefine %%HK %1 %xdefine %%HKforKaratsuba %2 %xdefine %%GH_1 %3 %xdefine %%tmpX0_1 %4 %xdefine %%tmpX1_1 %5 %xdefine %%tmpX2_1 %6 %xdefine %%GH_2 %7 %xdefine %%tmpX0_2 %8 %xdefine %%tmpX1_2 %9 %xdefine %%tmpX2_2 %10 %xdefine %%tmpX3_2 %11 pshufd %%tmpX2_1, %%GH_1, 01001110b ;; Karatsuba Method movdqa %%tmpX1_1, %%GH_1 pxor %%tmpX2_1, %%GH_1 my_pclmulqdq %%GH_1, %%HK, 00h pshufd %%tmpX2_2, %%GH_2, 01001110b ;; Karatsuba Method movdqa %%tmpX1_2, %%GH_2 pxor %%tmpX2_2, %%GH_2 my_pclmulqdq %%tmpX1_1, %%HK, 11h my_pclmulqdq %%tmpX2_1, %%HKforKaratsuba, 00h pxor %%tmpX2_1, %%GH_1 pxor %%tmpX2_1, %%tmpX1_1 pshufd %%tmpX0_1, %%tmpX2_1, 78 movdqa %%tmpX2_1, %%tmpX0_1 pand %%tmpX0_1, oword [rel MASK2] pand %%tmpX2_1, xmm14 pxor %%GH_1, %%tmpX0_1 pxor %%tmpX1_1, %%tmpX2_1 ;first phase of the reduction movdqa %%tmpX0_1, %%GH_1 psllq %%GH_1, 1 my_pclmulqdq %%GH_2, %%HK, 00h pxor %%GH_1, %%tmpX0_1 psllq %%GH_1, 5 pxor %%GH_1, %%tmpX0_1 psllq %%GH_1, 57 pshufd %%tmpX2_1, %%GH_1, 78 movdqa %%GH_1, %%tmpX2_1 my_pclmulqdq %%tmpX1_2, %%HK, 11h pand %%tmpX2_1, xmm14 pand %%GH_1, oword [rel MASK2] pxor %%GH_1, %%tmpX0_1 pxor %%tmpX1_1, %%tmpX2_1 ;second phase of the reduction movdqa %%tmpX2_1, %%GH_1 psrlq %%GH_1, 5 my_pclmulqdq %%tmpX2_2, %%HKforKaratsuba, 00h pxor %%GH_1, %%tmpX2_1 psrlq %%GH_1, 1 pxor %%GH_1, %%tmpX2_1 psrlq %%GH_1, 1 pxor %%GH_1, %%tmpX2_1 pxor %%GH_1, %%tmpX1_1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pxor %%tmpX2_2, %%GH_2 pxor %%tmpX2_2, %%tmpX1_2 pshufd %%tmpX0_2, %%tmpX2_2, 78 movdqa %%tmpX2_2, %%tmpX0_2 pand %%tmpX0_2, oword [rel MASK2] pand %%tmpX2_2, xmm14 pxor %%GH_2, %%tmpX0_2 pxor %%tmpX1_2, %%tmpX2_2 ;first phase of the reduction movdqa %%tmpX0_2, %%GH_2 movdqa %%tmpX2_2, %%GH_2 movdqa %%tmpX3_2, %%GH_2 ; move GH_2 into tmpX0_2, tmpX2_2, tmpX3_2 psllq %%tmpX0_2, 63 ; packed left shifting << 63 psllq %%tmpX2_2, 62 ; packed left shifting shift << 62 psllq %%tmpX3_2, 57 ; packed left shifting shift << 57 pxor %%tmpX0_2, %%tmpX2_2 ; xor the shifted versions pxor %%tmpX0_2, %%tmpX3_2 movdqa %%tmpX2_2, %%tmpX0_2 pslldq %%tmpX2_2, 8 ; shift-L tmpX2_2 2 DWs psrldq %%tmpX0_2, 8 ; shift-R xmm2 2 DWs pxor %%GH_2, %%tmpX2_2 ; first phase of the reduction complete pxor %%tmpX1_2, %%tmpX0_2 ; save the lost MS 1-2-7 bits from first phase ;second phase of the reduction movdqa %%tmpX2_2, %%GH_2 ; move GH_2 into tmpX3_2 psrlq %%tmpX2_2, 5 ; packed right shifting >> 5 pxor %%tmpX2_2, %%GH_2 ; xor shifted versions psrlq %%tmpX2_2, 1 ; packed right shifting >> 1 pxor %%tmpX2_2, %%GH_2 ; xor shifted versions psrlq %%tmpX2_2, 1 ; packed right shifting >> 1 pxor %%GH_2, %%tmpX2_2 ; second phase of the reduction complete pxor %%GH_2, %%tmpX1_2 ; the result is in GH_2 %endmacro %macro sse_clmul_gcm 5.nolist %xdefine %%GH %1 %xdefine %%HK %2 %xdefine %%tmpX0 %3 %xdefine %%tmpX1 %4 %xdefine %%tmpX2 %5 ;; GH, HK hold the values for the two operands which are carry-less multiplied ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Karatsuba Method ;; ;; GH = [GH1:GH0] ;; HK = [HK1:HK0] ;; pshufd %%tmpX2, %%GH, 01001110b ;; xmm2 = {GH0:GH1} pshufd %%tmpX0, %%HK, 01001110b ;; xmm0 = {HK0:HK1} pxor %%tmpX2, %%GH ;; xmm2 = {GH0+GH1:GH1+GH0} pxor %%tmpX0, %%HK ;; xmm0 = {HK0+HK1:HK1+HK0} my_pclmulqdq %%tmpX2, %%tmpX0,00h ;; tmpX2 = (a1+a0)*(b1+b0) xmm2 = (GH1+GH0)*(HK1+HK0) movdqa %%tmpX1, %%GH my_pclmulqdq %%GH, %%HK, 00h ;; GH = a0*b0 GH = GH0*HK0 pxor %%tmpX0, %%tmpX0 my_pclmulqdq %%tmpX1, %%HK, 11h ;; tmpX1 = a1*b1 xmm1 = GH1*HK1 pxor %%tmpX2, %%GH ;; xmm2 = (GH1+GH0)*(HK1+HK0) + GH0*HK0 pxor %%tmpX2, %%tmpX1 ;; tmpX2 = a0*b1+a1*b0 xmm2 = (GH1+GH0)*(HK1+HK0) + GH0*HK0 + GH1*HK1 = GH0*HK1+GH1*HK0 palignr %%tmpX0, %%tmpX2, 8 ;; tmpX0 = {Zeros : HI(a0*b1+a1*b0)} pslldq %%tmpX2, 8 ;; tmpX2 = {LO(HI(a0*b1+a1*b0)) : Zeros} pxor %%tmpX1, %%tmpX0 ;; holds the result of the carry-less multiplication of GH by HK pxor %%GH, %%tmpX2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;first phase of the reduction: ; Most( (product_H * g1), 128)) product_H = GH ; g1 = 2^256/g = g = 1+x+x^2+x^7+x^128 ; movdqa %%tmpX0, %%GH ;; copy GH into tmpX0, tmpX2, xmm15 movdqa %%tmpX2, %%GH movdqa xmm15, %%GH psllq %%tmpX0, 63 ; packed left shifting << 63 psllq %%tmpX2, 62 ; packed left shifting shift << 62 psllq xmm15, 57 ; packed left shifting shift << 57 pxor %%tmpX0, %%tmpX2 ; xor the shifted versions pxor %%tmpX0, xmm15 movdqa %%tmpX2, %%tmpX0 pslldq %%tmpX2, 8 ; shift-L tmpX2 2 DWs psrldq %%tmpX0, 8 ; shift-R xmm2 2 DWs pxor %%GH, %%tmpX2 ; first phase of the reduction complete pxor %%tmpX1, %%tmpX0 ; save the lost MS 1-2-7 bits from first phase ;second phase of the reduction movdqa %%tmpX2, %%GH ; move GH into xmm15 psrlq %%tmpX2, 5 ; packed right shifting >> 5 pxor %%tmpX2, %%GH ; xor shifted versions psrlq %%tmpX2, 1 ; packed right shifting >> 1 pxor %%tmpX2, %%GH ; xor shifted versions psrlq %%tmpX2, 1 ; packed right shifting >> 1 pxor %%GH, %%tmpX2 ; second phase of the reduction complete pxor %%GH, %%tmpX1 ; the result is in GH %endmacro %if (_IPP32E >= _IPP32E_Y8) segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR POLY DQ 00000000000000001h,0C200000000000000h ;; 0xC2000000000000000000000000000001 TWOONE DQ 00000000000000001h,00000000100000000h ;; 0x00000001000000000000000000000001 SHUF_CONST DQ 008090a0b0c0d0e0fh,00001020304050607h ;; 0x000102030405060708090a0b0c0d0e0f MASK1 DQ 0ffffffffffffffffh,00000000000000000h ;; 0x0000000000000000ffffffffffffffff MASK2 DQ 00000000000000000h,0ffffffffffffffffh ;; 0xffffffffffffffff0000000000000000 INC_1 DQ 1,0 segment .text align=IPP_ALIGN_FACTOR %assign sizeof_oword_ (16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmPrecomute_avx(Ipp8u* pPrecomData, const Ipp8u* pHKey) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmPrecompute_avx,PUBLIC USES_GPR rdi,rsi USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 2 %xdefine pPrecomData rdi ; (rdi) pointer to the reflected multipliers reflect(hkey),(hkey<<1), (hkey^2)<<1, (hkey^4)<<1, %xdefine pHKey rsi ; (rsi) pointer to the Hkey value movdqu xmm0, oword [pHKey] ; xmm0 holds HashKey pshufb xmm0, [rel SHUF_CONST] ;movdqu oword [pPrecomData+sizeof_oword_*0], xmm0 ; precompute HashKey<<1 mod poly from the HashKey movdqa xmm4, xmm0 psllq xmm0, 1 psrlq xmm4, 63 movdqa xmm3, xmm4 pslldq xmm4, 8 psrldq xmm3, 8 por xmm0, xmm4 ;reduction pshufd xmm4, xmm3, 00100100b pcmpeqd xmm4, oword [rel TWOONE] ; [TWOONE] = 0x00000001000000000000000000000001 pand xmm4, oword [rel POLY] pxor xmm0, xmm4 ; xmm0 holds the HashKey<<1 mod poly movdqa xmm1, xmm0 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^2)<<1 mod poly movdqa xmm2, xmm1 sse_clmul_gcm xmm2, xmm1, xmm3, xmm4, xmm5 ; xmm2 holds (HashKey^4)<<1 mod poly movdqu oword [pPrecomData+sizeof_oword_*0], xmm0 movdqu oword [pPrecomData+sizeof_oword_*1], xmm1 movdqu oword [pPrecomData+sizeof_oword_*2], xmm2 REST_XMM REST_GPR ret ENDFUNC AesGcmPrecompute_avx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmPrecompute_avx2_vaes(Ipp8u* pPrecomputedData, const Ipp8u* pHKey) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; calculates 16 hash keys - HashKey<<1, (HashKey^2)<<1, ..., (HashKey^16)<<1 align IPP_ALIGN_FACTOR IPPASM AesGcmPrecompute_avx2_vaes,PUBLIC USES_GPR rdi,rsi USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 2 %xdefine pPrecomputedData rdi ; (rdi) pointer to the reflected multipliers reflect(hkey),(hkey<<1), (hkey^2)<<1, (hkey^4)<<1, %xdefine pHKey rsi ; (rsi) pointer to the Hkey value movdqu xmm0, oword [pHKey] ; xmm0 holds HashKey pshufb xmm0, [rel SHUF_CONST] ; precompute HashKey<<1 mod poly from the HashKey movdqa xmm4, xmm0 psllq xmm0, 1 psrlq xmm4, 63 movdqa xmm3, xmm4 pslldq xmm4, 8 psrldq xmm3, 8 por xmm0, xmm4 ;reduction pshufd xmm4, xmm3, 00100100b pcmpeqd xmm4, oword [rel TWOONE] ; [TWOONE] = 0x00000001000000000000000000000001 pand xmm4, oword [rel POLY] pxor xmm0, xmm4 ; xmm0 holds the HashKey<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*0], xmm0 movdqa xmm1, xmm0 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^2)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*1], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^3)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*2], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^4)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*3], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^5)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*4], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^6)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*5], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^7)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*6], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^8)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*7], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^9)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*8], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^10)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*9], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^11)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*10], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^12)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*11], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^13)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*12], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^14)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*13], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^15)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*14], xmm1 sse_clmul_gcm xmm1, xmm0, xmm3, xmm4, xmm5 ; xmm1 holds (HashKey^16)<<1 mod poly movdqu oword [pPrecomputedData+sizeof_oword_*15], xmm1 REST_XMM REST_GPR ret ENDFUNC AesGcmPrecompute_avx2_vaes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmMulGcm_avx(Ipp8u* pHash, const Ipp8u* pHKey) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmMulGcm_avx,PUBLIC USES_GPR rsi,rdi USES_XMM xmm15 COMP_ABI 2 %xdefine pHash rdi ; (rdi) pointer to the Hash value %xdefine pHKey rsi ; (rsi) pointer to the (hkey<<1) value movdqa xmm0, oword [pHash] pshufb xmm0, [rel SHUF_CONST] movdqa xmm1, oword [pHKey] sse_clmul_gcm xmm0, xmm1, xmm2, xmm3, xmm4 ; xmm0 holds Hash*HKey mod poly pshufb xmm0, [rel SHUF_CONST] movdqa oword [pHash], xmm0 REST_XMM REST_GPR ret ENDFUNC AesGcmMulGcm_avx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; void AesGcmAuth_avx(Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pHKey, const void* pParam ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM AesGcmAuth_avx,PUBLIC USES_GPR rsi,rdi USES_XMM xmm15 COMP_ABI 5 %xdefine pHash rdi ; (rdi) pointer to the Hash value %xdefine pSrc rsi ; (rsi) pointer to the input data %xdefine len rdx ; (rdx) length of data (multiplr by AES_DATA_BLOCK) %xdefine pHKey rcx ; (rcx) pointer to the (hkey<<1) value %assign BYTES_PER_BLK (16) movdqa xmm0, oword [pHash] pshufb xmm0, [rel SHUF_CONST] movdqa xmm1, oword [pHKey] movsxd rdx, edx align IPP_ALIGN_FACTOR .auth_loop: movdqu xmm2, oword [pSrc] ; src[] pshufb xmm2, [rel SHUF_CONST] add pSrc, BYTES_PER_BLK pxor xmm0, xmm2 ; hash ^= src[] sse_clmul_gcm xmm0, xmm1, xmm2, xmm3, xmm4 ; xmm0 holds Hash*HKey mod poly sub len, BYTES_PER_BLK jnz .auth_loop pshufb xmm0, [rel SHUF_CONST] movdqa oword [pHash], xmm0 REST_XMM REST_GPR ret ENDFUNC AesGcmAuth_avx ;*************************************************************** ;* Purpose: pipelined AES-GCM encryption ;* ;* void AesGcmEnc_avx(Ipp8u* pDst, ;* const Ipp8u* pSrc, ;* int length, ;* RijnCipher cipher, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp8u* pGhash, ;* Ipp8u* pCtrValue, ;* Ipp8u* pEncCtrValue, ;* const Ipp8u* pPrecomData) ;*************************************************************** align IPP_ALIGN_FACTOR ;; ;; Lib = Y8, E9 ;; ;; Caller = ippsRijndael128GCMEncrypt ;; IPPASM AesGcmEnc_avx,PUBLIC %assign LOCAL_FRAME (8*16) USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 10 %xdefine pDst rdi ; pointer to the encrypted data %xdefine pSrc rsi ; pointer to the plane data %xdefine len rdx ; data length in bytes (multiple by BYTES_PER_BLK) %xdefine cipher rcx ; cipher function (don't need in fact) %xdefine nr r8d ; number of cipher's rounds %xdefine pRKey r9 ; pointer to the cipher's round keys %xdefine pGhash [rsp+ARG_7] ; pointer to the Hash value %xdefine pCtrValue [rsp+ARG_8] ; pointer to the counter value %xdefine pEncCtrValue [rsp+ARG_9] ; pointer to the encrypted counter %xdefine pPrecomData [rsp+ARG_10]; pointer to the precomputed data %assign SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) ;; ;; stack structure: %assign CNT (0) %assign ECNT (CNT+sizeof_oword_) %assign GHASH (ECNT+sizeof_oword_) %assign GHASH0 (GHASH) %assign GHASH1 (GHASH0+sizeof_oword_) %assign GHASH2 (GHASH1+sizeof_oword_) %assign GHASH3 (GHASH2+sizeof_oword_) %assign HKeyKaratsuba (GHASH3+sizeof_oword_) mov rax, pCtrValue ; address of the counter mov rbx, pEncCtrValue ; address of the encrypted counter mov rcx, pGhash ; address of hash value movdqa xmm4,oword [rel SHUF_CONST] movdqu xmm0, oword [rax] ; counter value movdqu xmm1, oword [rbx] ; encrypted counter value movdqu xmm2, oword [rcx] ; hash value pshufb xmm0, xmm4 ; convert counter and movdqa oword [rsp+CNT], xmm0 ; store into the stack movdqa oword [rsp+ECNT], xmm1 ; store encrypted counter into the stack pshufb xmm2, xmm4 ; convert hash value pxor xmm1, xmm1 movdqa oword [rsp+GHASH0], xmm2 ; store hash into the stack movdqa oword [rsp+GHASH1], xmm1 ; movdqa oword [rsp+GHASH2], xmm1 ; movdqa oword [rsp+GHASH3], xmm1 ; mov rbx, [rsp+ARG_10] ; pointer to the {hk<<1,hk^2<<1,kh^4<<1} multipliers movdqa xmm10,oword [rbx+sizeof_oword_*2] pshufd xmm9, xmm10, 01001110b ; xmm9 holds qword-swapped version of (HashKey^4)<<1 mod poly for Karatsuba pxor xmm9, xmm10 movdqa oword [rsp+HKeyKaratsuba], xmm9 movsxd len, edx ; data length mov rcx, pRKey ; rcx point to the chipher's round keys mov rax, len and rax, BYTES_PER_LOOP-1 and len, -BYTES_PER_LOOP jz .single_block_proc ;; ;; pipelined processing (4 blocks) ;; align IPP_ALIGN_FACTOR .blks4_loop: ;; ;; ctr encryption ;; movdqa xmm6,oword [rel INC_1] movdqa xmm5,oword [rel SHUF_CONST] movdqa xmm1, xmm0 ; counter+1 paddd xmm1, xmm6 movdqa xmm2, xmm1 ; counter+2 paddd xmm2, xmm6 movdqa xmm3, xmm2 ; counter+3 paddd xmm3, xmm6 movdqa xmm4, xmm3 ; counter+4 paddd xmm4, xmm6 movdqa oword [rsp+CNT], xmm4 movdqa xmm0, oword [rcx] ; pre-load whitening keys mov r10, rcx pshufb xmm1, xmm5 ; counter, counter+1, counter+2, counter+3 pshufb xmm2, xmm5 ; ready to be encrypted pshufb xmm3, xmm5 pshufb xmm4, xmm5 pxor xmm1, xmm0 ; whitening pxor xmm2, xmm0 pxor xmm3, xmm0 pxor xmm4, xmm0 movdqa xmm0, oword [r10+16] add r10, 16 mov r11d, nr ; counter depending on key length sub r11, 1 align IPP_ALIGN_FACTOR .cipher4_loop: my_aesenc xmm1, xmm0 ; regular round my_aesenc xmm2, xmm0 my_aesenc xmm3, xmm0 my_aesenc xmm4, xmm0 movdqa xmm0, oword [r10+16] add r10, 16 dec r11 jnz .cipher4_loop my_aesenclast xmm1, xmm0 my_aesenclast xmm2, xmm0 my_aesenclast xmm3, xmm0 my_aesenclast xmm4, xmm0 movdqa xmm0, oword [rsp+ECNT] ; load pre-calculated encrypted counter movdqa oword [rsp+ECNT], xmm4 ; save encrypted counter+4 movdqu xmm4, oword [pSrc+0*BYTES_PER_BLK] ; 4 input blocks movdqu xmm5, oword [pSrc+1*BYTES_PER_BLK] movdqu xmm6, oword [pSrc+2*BYTES_PER_BLK] movdqu xmm7, oword [pSrc+3*BYTES_PER_BLK] add pSrc, BYTES_PER_LOOP pxor xmm0, xmm4 ; ctr encryption movdqu oword [pDst+0*BYTES_PER_BLK], xmm0 ; store result pshufb xmm0, [rel SHUF_CONST] ; convert for multiplication and pxor xmm0, oword [rsp+GHASH0] pxor xmm1, xmm5 movdqu oword [pDst+1*BYTES_PER_BLK], xmm1 pshufb xmm1, [rel SHUF_CONST] pxor xmm1, oword [rsp+GHASH1] pxor xmm2, xmm6 movdqu oword [pDst+2*BYTES_PER_BLK], xmm2 pshufb xmm2, [rel SHUF_CONST] pxor xmm2, oword [rsp+GHASH2] pxor xmm3, xmm7 movdqu oword [pDst+3*BYTES_PER_BLK], xmm3 pshufb xmm3, [rel SHUF_CONST] pxor xmm3, oword [rsp+GHASH3] add pDst, BYTES_PER_LOOP cmp len, BYTES_PER_LOOP je .combine_hash ;; ;; update hash value ;; movdqa xmm14, oword [rel MASK1] sse_clmul_gcm_2way xmm10, xmm9, xmm0, xmm4, xmm5, xmm6, xmm1, xmm11, xmm12, xmm13, xmm15 sse_clmul_gcm_2way xmm10, xmm9, xmm2, xmm4, xmm5, xmm6, xmm3, xmm11, xmm12, xmm13, xmm15 movdqa oword [rsp+GHASH0], xmm0 movdqa oword [rsp+GHASH1], xmm1 movdqa oword [rsp+GHASH2], xmm2 movdqa oword [rsp+GHASH3], xmm3 sub len, BYTES_PER_LOOP movdqa xmm0, oword [rsp+CNT] ; next counter value cmp len, BYTES_PER_LOOP jge .blks4_loop .combine_hash: movdqa xmm8,oword [rbx] ; hk<<1 movdqa xmm9,oword [rbx+sizeof_oword_] ; (hk^2)<<1 sse_clmul_gcm xmm0, xmm10, xmm6, xmm4, xmm5 ; gHash0 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm1, xmm9, xmm6, xmm4, xmm5 ; gHash1 = gHash1 * (HashKey^2)<<1 mod poly sse_clmul_gcm xmm2, xmm8, xmm6, xmm4, xmm5 ; gHash2 = gHash2 * (HashKey^1)<<1 mod poly pxor xmm3, xmm1 pxor xmm3, xmm2 sse_clmul_gcm xmm3, xmm8, xmm6, xmm4, xmm5 ; gHash3 = gHash3 * (HashKey)<<1 mod poly pxor xmm3, xmm0 movdqa oword [rsp+GHASH0], xmm3 ; store gHash ;; ;; rest of input processing (1-3 blocks) ;; .single_block_proc: test rax, rax jz .quit align IPP_ALIGN_FACTOR .blk_loop: movdqa xmm0, oword [rsp+CNT] ; advance counter value movdqa xmm1, xmm0 paddd xmm1, oword [rel INC_1] movdqa oword [rsp+CNT], xmm1 movdqa xmm0, oword [rcx] ; pre-load whitening keys mov r10, rcx pshufb xmm1, [rel SHUF_CONST] ; counter is ready to be encrypted pxor xmm1, xmm0 ; whitening movdqa xmm0, oword [r10+16] add r10, 16 mov r11d, nr ; counter depending on key length sub r11, 1 align IPP_ALIGN_FACTOR .cipher_loop: my_aesenc xmm1, xmm0 ; regular round movdqa xmm0, oword [r10+16] add r10, 16 dec r11 jnz .cipher_loop my_aesenclast xmm1, xmm0 movdqa xmm0, oword [rsp+ECNT] ; load pre-calculated encrypted counter movdqa oword [rsp+ECNT], xmm1 ; save encrypted counter movdqu xmm1, oword [pSrc] ; input block add pSrc, BYTES_PER_BLK pxor xmm0, xmm1 ; ctr encryption movdqu oword [pDst], xmm0 add pDst, BYTES_PER_BLK pshufb xmm0, [rel SHUF_CONST] pxor xmm0, oword [rsp+GHASH0] movdqa xmm1, oword [rbx] sse_clmul_gcm xmm0, xmm1, xmm2, xmm3, xmm4 ; update hash value movdqa oword [rsp+GHASH0], xmm0 sub rax, BYTES_PER_BLK jg .blk_loop ;; ;; exit ;; .quit: movdqa xmm0, oword [rsp+CNT] ; counter movdqa xmm1, oword [rsp+ECNT] ; encrypted counter movdqa xmm2, oword [rsp+GHASH0] ; hash mov rax, pCtrValue ; address of the counter mov rbx, pEncCtrValue ; address of the encrypted counter mov rcx, pGhash ; address of hash value pshufb xmm0, [rel SHUF_CONST] ; convert counter back and movdqu oword [rax], xmm0 ; store counter into the context movdqu oword [rbx], xmm1 ; store encrypted counter into the context pshufb xmm2, [rel SHUF_CONST] ; convert hash value back movdqu oword [rcx], xmm2 ; store hash into the context REST_XMM REST_GPR ret ENDFUNC AesGcmEnc_avx ;*************************************************************** ;* Purpose: pipelined AES-GCM decryption ;* ;* void AesGcmDec_avx(Ipp8u* pDst, ;* const Ipp8u* pSrc,, ;* int length, ;* RijnCipher cipher, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp8u* pGhash, ;* Ipp8u* pCtrValue, ;* Ipp8u* pEncCtrValue, ;* const Ipp8u* pPrecomData) ;*************************************************************** align IPP_ALIGN_FACTOR ;; ;; Lib = Y8, E9 ;; ;; Caller = ippsRijndael128GCMDecrypt ;; IPPASM AesGcmDec_avx,PUBLIC %assign LOCAL_FRAME (8*16) USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 10 %xdefine pDst rdi ; pointer to the encrypted data %xdefine pSrc rsi ; pointer to the plane data %xdefine len rdx ; data length in bytes (multiple by BYTES_PER_BLK) %xdefine cipher rcx ; cipher function (don't need in fact) %xdefine nr r8d ; number of cipher's rounds %xdefine pRKey r9 ; pointer to the cipher's round keys %xdefine pGhash [rsp+ARG_7] ; pointer to the Hash value %xdefine pCtrValue [rsp+ARG_8] ; pointer to the counter value %xdefine pEncCtrValue [rsp+ARG_9] ; pointer to the encrypted counter %xdefine pPrecomData [rsp+ARG_10]; pointer to the precomputed data %assign SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) ;; ;; stack structure: %assign CNT (0) %assign ECNT (CNT+sizeof_oword_) %assign GHASH (ECNT+sizeof_oword_) %assign GHASH0 (GHASH) %assign GHASH1 (GHASH0+sizeof_oword_) %assign GHASH2 (GHASH1+sizeof_oword_) %assign GHASH3 (GHASH2+sizeof_oword_) %assign HKeyKaratsuba (GHASH3+sizeof_oword_) mov rax, pCtrValue ; address of the counter mov rbx, pEncCtrValue ; address of the encrypted counter mov rcx, pGhash ; address of hash value movdqa xmm4,oword [rel SHUF_CONST] movdqu xmm0, oword [rax] ; counter value movdqu xmm1, oword [rbx] ; encrypted counter value movdqu xmm2, oword [rcx] ; hash value pshufb xmm0, xmm4 ; convert counter and movdqa oword [rsp+CNT], xmm0 ; store into the stack movdqa oword [rsp+ECNT], xmm1 ; store encrypted counter into the stack pshufb xmm2, xmm4 ; convert hash value pxor xmm1, xmm1 movdqa oword [rsp+GHASH0], xmm2 ; store hash into the stack movdqa oword [rsp+GHASH1], xmm1 ; movdqa oword [rsp+GHASH2], xmm1 ; movdqa oword [rsp+GHASH3], xmm1 ; mov rbx, [rsp+ARG_10] ; pointer to the {hk<<1,hk^2<<1,kh^4<<1} multipliers movdqa xmm10,oword [rbx+sizeof_oword_*2] pshufd xmm9, xmm10, 01001110b ; xmm0 holds qword-swapped version of (HashKey^4)<<1 mod poly for Karatsuba pxor xmm9, xmm10 movdqa oword [rsp+HKeyKaratsuba], xmm9 movsxd len, edx ; data length mov rcx, pRKey ; rcx point to the chipher's round keys mov rax, len and rax, BYTES_PER_LOOP-1 and len, -BYTES_PER_LOOP jz .single_block_proc ;; ;; pipelined processing (4 blocks) ;; align IPP_ALIGN_FACTOR .blks4_loop: ;; ;; ctr encryption ;; movdqa xmm6,oword [rel INC_1] movdqa xmm5,oword [rel SHUF_CONST] movdqa xmm1, xmm0 ; counter+1 paddd xmm1, oword [rel INC_1] movdqa xmm2, xmm1 ; counter+2 paddd xmm2, oword [rel INC_1] movdqa xmm3, xmm2 ; counter+3 paddd xmm3, oword [rel INC_1] movdqa xmm4, xmm3 ; counter+4 paddd xmm4, oword [rel INC_1] movdqa oword [rsp+CNT], xmm4 movdqa xmm0, oword [rcx] ; pre-load whitening keys mov r10, rcx pshufb xmm1, xmm5 ; counter, counter+1, counter+2, counter+3 pshufb xmm2, xmm5 ; ready to be encrypted pshufb xmm3, xmm5 pshufb xmm4, xmm5 pxor xmm1, xmm0 ; whitening pxor xmm2, xmm0 pxor xmm3, xmm0 pxor xmm4, xmm0 movdqa xmm0, oword [r10+16] add r10, 16 mov r11d, nr ; counter depending on key length sub r11, 1 align IPP_ALIGN_FACTOR .cipher4_loop: my_aesenc xmm1, xmm0 ; regular round my_aesenc xmm2, xmm0 my_aesenc xmm3, xmm0 my_aesenc xmm4, xmm0 movdqa xmm0, oword [r10+16] add r10, 16 dec r11 jnz .cipher4_loop my_aesenclast xmm1, xmm0 my_aesenclast xmm2, xmm0 my_aesenclast xmm3, xmm0 my_aesenclast xmm4, xmm0 movdqa xmm0, oword [rsp+ECNT] ; load pre-calculated encrypted counter movdqa oword [rsp+ECNT], xmm4 ; save encrypted counter+4 movdqu xmm4, oword [pSrc+0*BYTES_PER_BLK] ; 4 input blocks movdqu xmm5, oword [pSrc+1*BYTES_PER_BLK] movdqu xmm6, oword [pSrc+2*BYTES_PER_BLK] movdqu xmm7, oword [pSrc+3*BYTES_PER_BLK] add pSrc, BYTES_PER_LOOP pxor xmm0, xmm4 ; ctr encryption movdqu oword [pDst+0*BYTES_PER_BLK], xmm0 ; store result pshufb xmm4, [rel SHUF_CONST] ; convert for multiplication and pxor xmm4, oword [rsp+GHASH0] pxor xmm1, xmm5 movdqu oword [pDst+1*BYTES_PER_BLK], xmm1 pshufb xmm5, [rel SHUF_CONST] pxor xmm5, oword [rsp+GHASH1] pxor xmm2, xmm6 movdqu oword [pDst+2*BYTES_PER_BLK], xmm2 pshufb xmm6, [rel SHUF_CONST] pxor xmm6, oword [rsp+GHASH2] pxor xmm3, xmm7 movdqu oword [pDst+3*BYTES_PER_BLK], xmm3 pshufb xmm7, [rel SHUF_CONST] pxor xmm7, oword [rsp+GHASH3] add pDst, BYTES_PER_LOOP cmp len, BYTES_PER_LOOP je .combine_hash ;; ;; update hash value ;; movdqa xmm14, oword [rel MASK1] sse_clmul_gcm_2way xmm10, xmm9, xmm4, xmm0, xmm1, xmm2, xmm5, xmm11, xmm12, xmm13, xmm15 sse_clmul_gcm_2way xmm10, xmm9, xmm6, xmm0, xmm1, xmm2, xmm7, xmm11, xmm12, xmm13, xmm15 movdqa oword [rsp+GHASH0], xmm4 movdqa oword [rsp+GHASH1], xmm5 movdqa oword [rsp+GHASH2], xmm6 movdqa oword [rsp+GHASH3], xmm7 sub len, BYTES_PER_LOOP movdqa xmm0, oword [rsp+CNT] ; next counter value cmp len, BYTES_PER_LOOP jge .blks4_loop .combine_hash: movdqa xmm8,oword [rbx] ; hk<<1 movdqa xmm9,oword [rbx+sizeof_oword_] ; (hk^2)<<1 sse_clmul_gcm xmm4, xmm10, xmm0, xmm1, xmm2 ; gHash0 = gHash0 * (HashKey^4)<<1 mod poly sse_clmul_gcm xmm5, xmm9, xmm0, xmm1, xmm2 ; gHash1 = gHash1 * (HashKey^2)<<1 mod poly sse_clmul_gcm xmm6, xmm8, xmm0, xmm1, xmm2 ; gHash2 = gHash2 * (HashKey^1)<<1 mod poly pxor xmm7, xmm5 pxor xmm7, xmm6 sse_clmul_gcm xmm7, xmm8, xmm0, xmm1, xmm2 ; gHash3 = gHash3 * (HashKey)<<1 mod poly pxor xmm7, xmm4 movdqa oword [rsp+GHASH0], xmm7 ; store gHash ;; ;; rest of input processing (1-3 blocks) ;; .single_block_proc: test rax, rax jz .quit align IPP_ALIGN_FACTOR .blk_loop: movdqa xmm0, oword [rsp+CNT] ; advance counter value movdqa xmm1, xmm0 paddd xmm1, oword [rel INC_1] movdqa oword [rsp+CNT], xmm1 movdqa xmm0, oword [rcx] ; pre-load whitening keys mov r10, rcx pshufb xmm1, [rel SHUF_CONST] ; counter is ready to be encrypted pxor xmm1, xmm0 ; whitening movdqa xmm0, oword [r10+16] add r10, 16 mov r11d, nr ; counter depending on key length sub r11, 1 align IPP_ALIGN_FACTOR .cipher_loop: my_aesenc xmm1, xmm0 ; regular round movdqa xmm0, oword [r10+16] add r10, 16 dec r11 jnz .cipher_loop my_aesenclast xmm1, xmm0 movdqa xmm0, oword [rsp+ECNT] ; load pre-calculated encrypted counter movdqa oword [rsp+ECNT], xmm1 ; save encrypted counter movdqu xmm1, oword [pSrc] ; input block add pSrc, BYTES_PER_BLK pxor xmm0, xmm1 ; ctr encryption movdqu oword [pDst], xmm0 add pDst, BYTES_PER_BLK pshufb xmm1, [rel SHUF_CONST] pxor xmm1, oword [rsp+GHASH0] movdqa xmm0, oword [rbx] sse_clmul_gcm xmm1, xmm0, xmm2, xmm3, xmm4 ; update hash value movdqa oword [rsp+GHASH0], xmm1 sub rax, BYTES_PER_BLK jg .blk_loop ;; ;; exit ;; .quit: movdqa xmm0, oword [rsp+CNT] ; counter movdqa xmm1, oword [rsp+ECNT] ; encrypted counter movdqa xmm2, oword [rsp+GHASH0] ; hash mov rax, pCtrValue ; address of the counter mov rbx, pEncCtrValue ; address of the encrypted counter mov rcx, pGhash ; address of hash value pshufb xmm0, [rel SHUF_CONST] ; convert counter back and movdqu oword [rax], xmm0 ; store counter into the context movdqu oword [rbx], xmm1 ; store encrypted counter into the context pshufb xmm2, [rel SHUF_CONST] ; convert hash value back movdqu oword [rcx], xmm2 ; store hash into the context REST_XMM REST_GPR ret ENDFUNC AesGcmDec_avx %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpaesgcmtable2ku8as.asm000066400000000000000000000273241470420105600301000ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) ; ; Content: ; AesGcmMulGcm_table2K() ; AesGcmAuth_table2K() ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_U8) segment .data align=IPP_ALIGN_FACTOR ; ; getAesGcmConst_table_ct provides c-e-t access to pre-computed Ipp16u AesGcmConst_table[256] ; ; input: ; r9: address of the AesGcmConst_table ; rcx: index in the table ; ; output: ; rax ; ; register rcx destroyed ; registers mmx2, mmx3, mmx6, and mmx7 destroyed ; align IPP_ALIGN_FACTOR INIT_IDX dw 000h,001h,002h,003h,004h,005h,006h,007h ;; initial search inx = {0:1:2:3:4:5:6:7} INCR_IDX dw 008h,008h,008h,008h,008h,008h,008h,008h ;; index increment = {8:8:8:8:8:8:8:8} segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM getAesGcmConst_table_ct,PRIVATE pxor xmm2, xmm2 ;; accumulator xmm2 = 0 mov rax, rcx ;; broadcast inx into dword shl rcx, 16 or rcx, rax movq xmm3, rcx pshufd xmm3, xmm3, 00b ;; search index xmm3 = broadcast(idx) movdqa xmm6, xmmword [rel INIT_IDX] ;; current indexes xor rax, rax align IPP_ALIGN_FACTOR .search_loop: movdqa xmm7, xmm6 ;; copy current indexes paddw xmm6, xmmword [rel INCR_IDX] ;; advance current indexes pcmpeqw xmm7, xmm3 ;; selection mask pand xmm7, xmmword [r9+rax*sizeof(word)] ;; mask data add rax, 8 cmp rax, 256 por xmm2, xmm7 ;; and accumulate jl .search_loop movdqa xmm3, xmm2 ;; pack result in qword psrldq xmm2, sizeof(xmmword)/2 por xmm2, xmm3 movq rax, xmm2 and rcx, 3 ;; select tbl[idx] value shl rcx, 4 ;; rcx *=16 = sizeof(word)*8 shr rax, cl ret ENDFUNC getAesGcmConst_table_ct ; ; void AesGcmMulGcm_table2K(Ipp8u* pHash, const Ipp8u* pPrecomputedData, const void* pParam) ; align IPP_ALIGN_FACTOR IPPASM AesGcmMulGcm_table2K,PUBLIC USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7 COMP_ABI 3 movdqu xmm0, [rdi] ; hash value mov r8, rsi ; precomputed data pointer mov r9, rdx ; pointer to the fixed table (AesGcmConst_table) movd ebx, xmm0 ; ebx = hash.0 mov eax, 0f0f0f0f0h and eax, ebx ; eax = 4 x 4_bits shl ebx, 4 and ebx, 0f0f0f0f0h ; ebx = 4 x 4_bits (another) movzx ecx, ah movdqa xmm5, oword [r8+1024+rcx] movzx ecx, al movdqa xmm4, oword [r8+1024+rcx] shr eax, 16 movzx ecx, ah movdqa xmm3, oword [r8+1024+rcx] movzx ecx, al movdqa xmm2, oword [r8+1024+rcx] psrldq xmm0, 4 ; shift xmm0 movd eax, xmm0 ; eax = hash[1] and eax, 0f0f0f0f0h ; eax = 4 x 4_bits movzx ecx, bh pxor xmm5, oword [r8+ (1-1)*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ (1-1)*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ (1-1)*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ (1-1)*256 + rcx] movd ebx, xmm0 ; ebx = hash[1] shl ebx, 4 ; another 4 x 4_bits and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [r8+1024+ 1*256 + rcx] movzx ecx, al pxor xmm4, oword [r8+1024+ 1*256 + rcx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [r8+1024+ 1*256 + rcx] movzx ecx, al pxor xmm2, oword [r8+1024+ 1*256 + rcx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash.2 and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [r8+ (2-1)*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ (2-1)*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ (2-1)*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ (2-1)*256 + rcx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [r8+1024+ 2*256 + rcx] movzx ecx, al pxor xmm4, oword [r8+1024+ 2*256 + rcx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [r8+1024+ 2*256 + rcx] movzx ecx, al pxor xmm2, oword [r8+1024+ 2*256 + rcx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash.3 and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [r8+ (3-1)*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ (3-1)*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ (3-1)*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ (3-1)*256 + rcx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [r8+1024+ 3*256 + rcx] movzx ecx, al pxor xmm4, oword [r8+1024+ 3*256 + rcx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [r8+1024+ 3*256 + rcx] movzx ecx, al pxor xmm2, oword [r8+1024+ 3*256 + rcx] movzx ecx, bh pxor xmm5, oword [r8+ 3*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ 3*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ 3*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ 3*256 + rcx] movdqa xmm0, xmm3 pslldq xmm3, 1 pxor xmm2, xmm3 movdqa xmm1, xmm2 pslldq xmm2, 1 pxor xmm5, xmm2 psrldq xmm0, 15 movd ecx, xmm0 CALL_IPPASM getAesGcmConst_table_ct ;;movzx eax, word [r9 + rcx*sizeof(word)] shl eax, 8 movdqa xmm0, xmm5 pslldq xmm5, 1 pxor xmm4, xmm5 psrldq xmm1, 15 movd ecx, xmm1 mov rbx, rax ;;xor ax, word [r9 + rcx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor rax, rbx ;; shl eax, 8 psrldq xmm0, 15 movd ecx, xmm0 mov rbx, rax ;;xor ax, word [r9 + rcx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor rax, rbx ;; movd xmm0, eax pxor xmm0, xmm4 movdqu oword [rdi], xmm0 ; store hash value REST_XMM REST_GPR ret ENDFUNC AesGcmMulGcm_table2K ; ; void AesGcmAuth_table2K(Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pPrecomputedData, const void* pParam) ; align IPP_ALIGN_FACTOR IPPASM AesGcmAuth_table2K,PUBLIC USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7 COMP_ABI 5 mov r9, r8 ; pointer to the fixed table (pParam) movdqu xmm0, [rdi] ; hash value mov r8, rcx ; precomputed data pointer align IPP_ALIGN_FACTOR .auth_loop: movdqu xmm4, [rsi] ; get src[] pxor xmm0, xmm4 ; hash ^= src[] movd ebx, xmm0 ; ebx = hash.0 mov eax, 0f0f0f0f0h and eax, ebx ; eax = 4 x 4_bits shl ebx, 4 and ebx, 0f0f0f0f0h ; ebx = 4 x 4_bits (another) movzx ecx, ah movdqa xmm5, oword [r8+1024+rcx] movzx ecx, al movdqa xmm4, oword [r8+1024+rcx] shr eax, 16 movzx ecx, ah movdqa xmm3, oword [r8+1024+rcx] movzx ecx, al movdqa xmm2, oword [r8+1024+rcx] psrldq xmm0, 4 ; shift xmm0 movd eax, xmm0 ; eax = hash[1] and eax, 0f0f0f0f0h ; eax = 4 x 4_bits movzx ecx, bh pxor xmm5, oword [r8+ (1-1)*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ (1-1)*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ (1-1)*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ (1-1)*256 + rcx] movd ebx, xmm0 ; ebx = hash[1] shl ebx, 4 ; another 4 x 4_bits and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [r8+1024+ 1*256 + rcx] movzx ecx, al pxor xmm4, oword [r8+1024+ 1*256 + rcx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [r8+1024+ 1*256 + rcx] movzx ecx, al pxor xmm2, oword [r8+1024+ 1*256 + rcx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash[2] and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [r8+ (2-1)*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ (2-1)*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ (2-1)*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ (2-1)*256 + rcx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [r8+1024+ 2*256 + rcx] movzx ecx, al pxor xmm4, oword [r8+1024+ 2*256 + rcx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [r8+1024+ 2*256 + rcx] movzx ecx, al pxor xmm2, oword [r8+1024+ 2*256 + rcx] psrldq xmm0, 4 movd eax, xmm0 ; eax = hash[3] and eax, 0f0f0f0f0h movzx ecx, bh pxor xmm5, oword [r8+ (3-1)*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ (3-1)*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ (3-1)*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ (3-1)*256 + rcx] movd ebx, xmm0 shl ebx, 4 and ebx, 0f0f0f0f0h movzx ecx, ah pxor xmm5, oword [r8+1024+ 3*256 + rcx] movzx ecx, al pxor xmm4, oword [r8+1024+ 3*256 + rcx] shr eax, 16 movzx ecx, ah pxor xmm3, oword [r8+1024+ 3*256 + rcx] movzx ecx, al pxor xmm2, oword [r8+1024+ 3*256 + rcx] movzx ecx, bh pxor xmm5, oword [r8+ 3*256 + rcx] movzx ecx, bl pxor xmm4, oword [r8+ 3*256 + rcx] shr ebx, 16 movzx ecx, bh pxor xmm3, oword [r8+ 3*256 + rcx] movzx ecx, bl pxor xmm2, oword [r8+ 3*256 + rcx] movdqa xmm0, xmm3 pslldq xmm3, 1 pxor xmm2, xmm3 movdqa xmm1, xmm2 pslldq xmm2, 1 pxor xmm5, xmm2 psrldq xmm0, 15 movd ecx, xmm0 CALL_IPPASM getAesGcmConst_table_ct ;;movzx eax, word [r9 + rcx*sizeof(word)] shl eax, 8 movdqa xmm0, xmm5 pslldq xmm5, 1 pxor xmm4, xmm5 psrldq xmm1, 15 movd ecx, xmm1 mov rbx, rax ;;xor ax, word [r9 + rcx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor rax, rbx ;; shl eax, 8 psrldq xmm0, 15 movd ecx, xmm0 mov rbx, rax ;;xor ax, word [r9 + rcx*sizeof(word)] CALL_IPPASM getAesGcmConst_table_ct ;; xor rax, rbx ;; movd xmm0, eax pxor xmm0, xmm4 add rsi, sizeof(oword) ; advance src address sub rdx, sizeof(oword) ; decrease counter jnz .auth_loop ; process next block movdqu oword [rdi], xmm0 ; store hash value REST_XMM REST_GPR ret ENDFUNC AesGcmAuth_table2K %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnuaddm7as.asm000066400000000000000000000264241470420105600266200ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpAdd_BNU() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* Ipp64u cpAdd_BNU(Ipp64u* pDst, ;* const Ipp64u* pSrc1, ;* const Ipp64u* pSrc2, ;* int len) ;* returns carry ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpAdd_BNU,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 4 ; rdi = pDst ; rsi = pSrcA ; rdx = pSrcB ; rcx = len movsxd rcx, ecx ; unsigned length xor rax, rax cmp rcx, 2 jge .ADD_GE2 ;********** lenSrcA == 1 ************************************* add rax, rax mov r8, qword [rsi] ; rsi = a adc r8, qword [rdx] ; r8 = a+b = s mov qword [rdi], r8 ; save s sbb rax, rax ; jmp .FINAL ;********** lenSrcA == 1 END ******************************** .ADD_GE2: jg .ADD_GT2 ;********** lenSrcA == 2 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 2 END ********************************* .ADD_GT2: cmp rcx, 4 jge .ADD_GE4 ;********** lenSrcA == 3 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 adc r10, qword [rdx+16] ; r10 = a2+b2 = s2 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 3 END ********************************* .ADD_GE4: jg .ADD_GT4 ;********** lenSrcA == 4 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 adc r10, qword [rdx+16] ; r10 = a2+b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 adc r11, qword [rdx+24] ; r11 = a3+b3 = s3 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s2 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 4 END ********************************* .ADD_GT4: cmp rcx, 6 jge .ADD_GE6 ;********** lenSrcA == 5 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 adc r10, qword [rdx+16] ; r10 = a2+b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 adc r11, qword [rdx+24] ; r11 = a3+b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 adc rcx, qword [rdx+32] ; rcx = a4+b4 = s4 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 5 END ********************************* .ADD_GE6: jg .ADD_GT6 ;********** lenSrcA == 6 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 adc r10, qword [rdx+16] ; r10 = a2+b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 adc r11, qword [rdx+24] ; r11 = a3+b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 adc rcx, qword [rdx+32] ; rcx = a4+b4 = s4 mov rsi, qword [rsi+40] ; rsi = a5 adc rsi, qword [rdx+40] ; rsi = a5+b5 = s5 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 mov qword [rdi+40], rsi ; save s5 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 6 END ********************************* .ADD_GT6: cmp rcx, 8 jge .ADD_GE8 .ADD_EQ7: ;********** lenSrcA == 7 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 adc r10, qword [rdx+16] ; r10 = a2+b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 adc r11, qword [rdx+24] ; r11 = a3+b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 adc rcx, qword [rdx+32] ; rcx = a4+b4 = s4 mov qword [rdi], r8 ; save s0 mov r8, qword [rsi+40] ; r8 = a5 adc r8, qword [rdx+40] ; r8 = a5+b5 = s5 mov rsi, qword [rsi+48] ; rsi = a6 adc rsi, qword [rdx+48] ; rsi = a6+b6 = s6 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 mov qword [rdi+40], r8 ; save s5 mov qword [rdi+48], rsi ; save s6 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 7 END ********************************* .ADD_GE8: jg .ADD_GT8 ;********** lenSrcA == 8 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 adc r9, qword [rdx+8] ; r9 = a1+b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 adc r10, qword [rdx+16] ; r10 = a2+b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 adc r11, qword [rdx+24] ; r11 = a3+b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 adc rcx, qword [rdx+32] ; rcx = a4+b4 = s4 mov qword [rdi], r8 ; save s0 mov r8, qword [rsi+40] ; r8 = a5 adc r8, qword [rdx+40] ; r8 = a5+b5 = s5 mov qword [rdi+8], r9 ; save s1 mov r9, qword [rsi+48] ; r9 = a7 adc r9, qword [rdx+48] ; r9 = a7+b7 = s7 mov rsi, qword [rsi+56] ; rsi = a6 adc rsi, qword [rdx+56] ; rsi = a6+b6 = s6 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 mov qword [rdi+40], r8 ; save s5 mov qword [rdi+48], r9 ; save s6 mov qword [rdi+56], rsi ; save s7 sbb rax, rax ; rax = carry jmp .FINAL ;********** lenSrcA == 8 END ********************************* ;********** lenSrcA > 8 ************************************* .ADD_GT8: mov r8, rax mov rax, rcx ; rax = len and rcx, 3 ; xor rcx, rax ; lea rsi, [rsi+8*rcx] ; lea rdx, [rdx+8*rcx] ; lea rdi, [rdi+8*rcx] ; neg rcx add r8, r8 jmp .ADD_GLOOP align IPP_ALIGN_FACTOR .ADD_GLOOP: mov r8, qword [rsi+8*rcx] ; r8 = a0 mov r9, qword [rsi+8*rcx+8] ; r9 = a1 mov r10, qword [rsi+8*rcx+16] ; r10 = a2 mov r11, qword [rsi+8*rcx+24] ; r11 = a3 adc r8, qword [rdx+8*rcx] ; r8 = a0+b0 = r0 adc r9, qword [rdx+8*rcx+8] ; r9 = a1+b1 = r1 adc r10, qword [rdx+8*rcx+16] ; r10 = a2+b2 = r2 adc r11, qword [rdx+8*rcx+24] ; r11 = a3+b3 = r3 mov qword [rdi+8*rcx], r8 ; mov qword [rdi+8*rcx+8], r9 ; mov qword [rdi+8*rcx+16], r10 ; mov qword [rdi+8*rcx+24], r11 ; lea rcx, [rcx+4] jrcxz .ADD_LLAST0 jmp .ADD_GLOOP .ADD_LLAST0: sbb rcx, rcx and rax, 3 jz .FIN0 .ADD_LLOOP: test rax, 2 jz .ADD_LLAST1 add rcx, rcx mov r8, qword [rsi] ; r8 = a0 mov r9, qword [rsi+8] ; r9 = a1 adc r8, qword [rdx] ; r8 = a0+b0 = r0 adc r9, qword [rdx+8] ; r9 = a1+b1 = r1 mov qword [rdi], r8 ; mov qword [rdi+8], r9 ; sbb rcx, rcx test rax, 1 jz .FIN0 add rsi, 16 add rdx, 16 add rdi, 16 .ADD_LLAST1: add rcx, rcx mov r8, qword [rsi] ; r8 = a0 adc r8, qword [rdx] ; r8 = a0+b0 = r0 mov qword [rdi], r8 ; sbb rcx, rcx .FIN0: mov rax, rcx ;******************* .FINAL *********************************************************** .FINAL: neg rax REST_XMM REST_GPR ret ENDFUNC cpAdd_BNU %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnudivm7as.asm000066400000000000000000000303711470420105600266460ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpDiv_BNU32() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %if (_IPP32E >= _IPP32E_M7) ;; ;; FIX_BNU returns actual length of BNU ;; ;; input ;; rSrc points BNU ;; rLen initial BNU size ;; ;; output ;; rSrc points BNU ;; rLen actual BNU size ;; %macro FIX_BNU 3.nolist %xdefine %%rSrc %1 %xdefine %%rLen %2 %xdefine %%tmp %3 %%fix_bnu_loop: mov %%tmp%+d,[%%rSrc+%%rLen*4-4] ;; value test %%tmp%+d,%%tmp%+d ;; test BNU component jnz %%fix_bnu_quit sub %%rLen,1 jg %%fix_bnu_loop add %%rLen,1 %%fix_bnu_quit: %endmacro ;; ;; Number of Leaging Zeros in32-bit value ;; %macro NLZ32u 2.nolist %xdefine %%rNlz %1 %xdefine %%rVal %2 mov %%rNlz, 32 test %%rVal,%%rVal jz %%nlz_quit xor %%rNlz,%%rNlz %%nlz16: test %%rVal,0FFFF0000h jnz %%nlz8 shl %%rVal,16 add %%rNlz,16 %%nlz8: test %%rVal,0FF000000h jnz %%nlz4 shl %%rVal,8 add %%rNlz,8 %%nlz4: test %%rVal,0F0000000h jnz %%nlz2 shl %%rVal,4 add %%rNlz,4 %%nlz2: test %%rVal,0C0000000h jnz %%nlz1 shl %%rVal,2 add %%rNlz,2 %%nlz1: test %%rVal,080000000h jnz %%nlz_quit add %%rNlz,1 %%nlz_quit: %endmacro ;; ;; (Logical) Shift BNU Left and Right ;; ;; Input: ;; rDst source/destination address ;; rLen length (dwords) of BNU ;; CL left shift ;; rTmpH scratch ;; rTmpL scratch ;; Note ;; rDst don't changes ;; rLen changes ;; %macro SHL_BNU_I 4.nolist %xdefine %%rDst %1 %xdefine %%rLen %2 %xdefine %%rTmpH %3 %xdefine %%rTmpL %4 mov %%rTmpH%+d,[%%rDst+%%rLen*4-4] sub %%rLen,1 jz %%shl_bnu_quit %%shl_bnu_loop: mov %%rTmpL%+d,[%%rDst+%%rLen*4-4] shld %%rTmpH%+d,%%rTmpL%+d, CL mov [%%rDst+%%rLen*4],%%rTmpH%+d mov %%rTmpH%+d,%%rTmpL%+d sub %%rLen,1 jg %%shl_bnu_loop %%shl_bnu_quit: shl %%rTmpH%+d,CL mov [%%rDst],%%rTmpH%+d %endmacro %macro SHR_BNU_I 4.nolist %xdefine %%rDst %1 %xdefine %%rLen %2 %xdefine %%rTmpH %3 %xdefine %%rTmpL %4 push %%rDst mov %%rTmpL%+d,[%%rDst] sub %%rLen,1 jz %%shr_bnu_quit %%shr_bnu_loop: mov %%rTmpH%+d,[%%rDst+4] shrd %%rTmpL%+d,%%rTmpH%+d, CL mov [%%rDst],%%rTmpL%+d add %%rDst,4 mov %%rTmpL%+d,%%rTmpH%+d sub %%rLen,1 jg %%shr_bnu_loop %%shr_bnu_quit: shr %%rTmpL%+d,CL mov [%%rDst],%%rTmpL%+d pop %%rDst %endmacro ;; ;; Multiply BNU by 32-bit digit and Subtract ;; ;; input ;; rSrc points source BNU ;; rDgt 32-bit digit value ;; rDst points accumulator (resultant) BNU ;; rLen BNU size ;; rIdx (scratch) source/target index ;; rExp (scratch) expansion ;; ;; output ;; rDgt 32-bit expansion ;; ;; Note ;; rdx and rax used in mul instruction, ;; this mean any macro argument may be neither rax nor rdx ;; %macro xMDC_BNU_D32 6.nolist %xdefine %%rSrc %1 %xdefine %%rDgt %2 %xdefine %%rDst %3 %xdefine %%rLen %4 %xdefine %%rIdx %5 %xdefine %%rExp %6 xor %%rIdx,%%rIdx ;; index = 0 xor %%rExp,%%rExp ;; carry = 0 sub %%rLen,2 ;; test length jl %%mdc_short %%mdc_loop: mov rax, [%%rSrc+%%rIdx] ;; a = src[i] mul %%rDgt ;; x = a*w add rax, %%rExp ;; x += borrow adc rdx,0 xor %%rExp,%%rExp ;; zero extension of r sub [%%rDst+%%rIdx],rax ;; dst[] -= x sbb %%rExp,rdx neg %%rExp ;; update borrow add %%rIdx,2*4 ;; advance index sub %%rLen,2 ;; decrease counter jge %%mdc_loop ;; continue add %%rLen,2 jz %%mdc_quit %%mdc_short: mov eax, [%%rSrc+%%rIdx] ;; a = src[i] mul %%rDgt%+d ;; x = a*w add eax, %%rExp%+d ;; x += borrow adc edx,0 xor %%rExp%+d, %%rExp%+d ;; zero extension of r sub [%%rDst+%%rIdx],eax ;; dst[] -= x sbb %%rExp%+d,edx neg %%rExp%+d ;; update borrow %%mdc_quit: mov %%rDgt,%%rExp ;; return borrow %endmacro ;; ;; xADD_BNU add BNUs ;; ;; input ;; rDst points resultant BNU ;; rSrc1 points source BNU ;; rSrc2 points source BNU ;; rLen BNU size ;; rIdx source, resultant index ;; ;; output ;; rCarry carry value (byte) ;; %macro xADD_BNU 8.nolist %xdefine %%rDst %1 %xdefine %%rCarry %2 %xdefine %%rSrc1 %3 %xdefine %%rSrc2 %4 %xdefine %%rLen %5 %xdefine %%rIdx %6 %xdefine %%tmp1 %7 %xdefine %%tmp2 %8 xor %%rCarry,%%rCarry ;; carry=0 xor %%rIdx,%%rIdx ;; index=0 sub %%rLen,2 ;; test BNU size jl %%short_bnu clc ;; CF=0 %%add_bnu_loop: mov %%tmp1,[%%rSrc1+%%rIdx*8] ;; src1[] mov %%tmp2,[%%rSrc2+%%rIdx*8] ;; src2[] adc %%tmp1,%%tmp2 ;; x = src1[]+src[2]+CF mov [%%rDst+%%rIdx*8],%%tmp1 ;; dst[] = x inc %%rIdx ;; advance index dec %%rLen ;; decrease length dec %%rLen jge %%add_bnu_loop ;; continue setc %%rCarry%+b ;; save CF add %%rIdx,%%rIdx ;; restore ordinal index add %%rLen,2 ;; restore length jz %%add_bnu_exit %%short_bnu: shr %%rCarry%+d,1 ;; restore CF mov %%tmp1%+d,[%%rSrc1+%%rIdx*4] ;; src1[] mov %%tmp2%+d,[%%rSrc2+%%rIdx*4] ;; src2[] adc %%tmp1%+d,%%tmp2%+d ;; x = src1[]-src[2]-CF mov [%%rDst+%%rIdx*4],%%tmp1%+d ;; dst[] = x setc %%rCarry%+b ;; save CF add %%rIdx,1 ;; advance index %%add_bnu_exit: %endmacro segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* Ipp32u cpDiv_BNU32(Ipp32u* pQ, int* sizeQ, ;* Ipp32u* pX, int sizeX, ;* Ipp32u* pY, int sizeY) ;* ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpDiv_BNU32,PUBLIC %assign LOCAL_FRAME 4*8 USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14,r15 USES_XMM COMP_ABI 6 ; rdi = pQ ; address of quotient ; rsi = sizeQ ; address of quotient length ; rdx = pX ; address of denominator (remaider) ; rcx = sizeX ; length (dwords) of denominator ; r8 = pY ; address of divired ; r9 = sizeY ; length (dwords) of length movsxd rcx, ecx ; length movsxd r9, r9d ; make sure denominator and divider are fixed FIX_BNU rdx,rcx, rax FIX_BNU r8, r9, rax mov r10, rdx ; save pX mov r11, rcx ; save sizeX ; ; special case: sizeX < sizeY ; .spec_case1: cmp rcx, r9 jae .spec_case2 test rdi, rdi ; %if quotient was requested jz .spec_case1_quit mov DWORD [rdi], 0 ; pQ[0] = 0 mov DWORD [rsi], 1 ; sizeQ = 1 .spec_case1_quit: mov rax, rcx ; remainder length address REST_XMM REST_GPR ret ; ; special case: 1 == sizeY ; .spec_case2: cmp r9, 1 jnz .common_case mov ebx, [r8] ; divider = pY[0] xor edx,edx ; init remaider .spec_case2_loop: mov eax,[r10+r11*4-4] div ebx ; (edx,eax)/pY[0] test rdi, rdi ; store %if quotient requested je .spec_case2_cont mov [rdi+r11*4-4],eax .spec_case2_cont: sub r11,1 jg .spec_case2_loop test rdi, rdi ; %if quotient was requested je .spec_case2_quit FIX_BNU rdi,rcx, rax ; fix quotient mov DWORD [rsi], ecx ; store quotient length .spec_case2_quit: mov DWORD [r10],edx ; pX[0] = remainder value mov rax, dword 1 REST_XMM REST_GPR ret ; ; common case ; .common_case: xor eax,eax ; expand denominator mov [r10+r11*4], eax ; by zero mov eax,[r8+r9*4-4] ; get divider's NLZ32u ecx,eax ; factor test ecx,ecx ; test normalization factor jz .division ; and mov r15,r9 ; normalize SHL_BNU_I r8,r15, r12,r13 ; divider lea r15,[r11+1] ; and SHL_BNU_I r10,r15, r12,r13 ; denominator ; compute quotation digit-by-digit .division: mov ebx,[r8+r9*4-4] ; yHi - the most significant divider digit pY[ySize-1] mov [rsp], r10 ; save pX mov [rsp+8], r11 ; save sizeX sub r11, r9 ; estimate length of quotient = (sizeX-sizeY+1) mov [rsp+16], r11 ; (will use for loop counter) lea r10, [r10+r11*4] ; points current denominator position .division_loop: mov rax,[r10+r9*4-4] ; tmp = (pX[xSize],pX[xSize-1]) xor rdx,rdx ; estimate quotation digit: div rbx ; (rax) q = tmp/yHi ; (rdx) r = tmp%yHi mov r12,rax mov r13,rdx mov ebp,[r8+r9*4-8] ; next significant divider digit pY[ySize-2] .tune_loop: mov r15,0FFFFFFFF00000000h and r15,rax ; %if q >= base .tune q value jne .tune mul rbp ; (rax) A = q*pY[ySize-2] mov r14,r13 shl r14,32 ; (rdx) B = QWORD(r,pX[xSize-2]) mov edx,[r10+r9*4-8] or rdx,r14 cmp rax,rdx ; %if A>B .tune q value jbe .mul_and_sub .tune: sub r12,1 ; q -= 1 add r13d,ebx ; r += yHi mov rax,r12 jnc .tune_loop .mul_and_sub: mov r15,r9 ; multiplay and subtract mov ebp,r12d xMDC_BNU_D32 r8, rbp, r10,r15, r13,r14 sub [r10+r9*4],ebp ; extend = (pX[i+sizeY] -= extend); jnc .store_duotation sub r12d,1 mov r15,r9 xADD_BNU r10,rax, r10,r8,r15, r13,r14,rdx add [r10+r9*4],eax ; pX[i+sizeY] += extend; .store_duotation: test rdi, rdi jz .cont_division_loop mov DWORD [rdi+r11*4],r12d .cont_division_loop: sub r10,4 sub r11,1 jge .division_loop mov r10,[rsp] ; restore pX mov r11,[rsp+8] ; restore sizeX test ecx,ecx ; test normalization factor jz .store_results ; and mov r15,r9 ; de-normalize SHR_BNU_I r8,r15, r12,r13 ; divider mov r15,r11 ; and SHR_BNU_I r10,r15, r12,r13 ; remainder .store_results: test rdi, rdi jz .quit mov rcx,[rsp+16] ; restore quotient length add rcx,1 FIX_BNU rdi, rcx, rax ; fix quotient mov DWORD [rsi], ecx .quit: FIX_BNU r10,r11, rax ; fix remainder mov rax, r11 REST_XMM REST_GPR ret ENDFUNC cpDiv_BNU32 %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnuincm7as.asm000066400000000000000000000076321470420105600266410ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpInc_BNU() ; cpDec_BNU() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* Ipp64u cpInc_BNU(Ipp64u* pDst, ;* const Ipp64u* pSrc, int len, ;* Ipp64u increment) ;* returns carry ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpInc_BNU,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 4 ; rdi = pDst ; rsi = pSrc ; rdx = len ; rcx = increment movsxd rdx, edx ; length mov r8, qword [rsi] ; r[0] = r[0]+increment add r8, rcx mov qword [rdi], r8 lea rsi, [rsi+rdx*sizeof(qword)] lea rdi, [rdi+rdx*sizeof(qword)] lea rcx, [rdx*sizeof(qword)] sbb rax, rax ; save cf neg rcx ; rcx = negative length (bytes) add rcx, sizeof(qword) jrcxz .exit add rax, rax ; restore cf jnc .copy align IPP_ALIGN_FACTOR .inc_loop: mov r8, qword [rsi+rcx] adc r8, 0 mov qword [rdi+rcx], r8 lea rcx, [rcx+sizeof(qword)] jrcxz .exit_loop jnc .exit_loop jmp .inc_loop .exit_loop: sbb rax, rax ; save cf .copy: cmp rsi, rdi jz .exit jrcxz .exit .copy_loop: mov r8, qword [rsi+rcx] mov qword [rdi+rcx], r8 add rcx, sizeof(qword) jnz .copy_loop .exit: neg rax REST_XMM REST_GPR ret ENDFUNC cpInc_BNU ;************************************************************* ;* Ipp64u cpDec_BNU(Ipp64u* pDst, ;* const Ipp64u* pSrc, int len, ;* Ipp64u increment) ;* returns borrow ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpDec_BNU,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 4 ; rdi = pDst ; rsi = pSrc ; rdx = len ; rcx = increment movsxd rdx, edx ; length mov r8, qword [rsi] ; r[0] = r[0]+increment sub r8, rcx mov qword [rdi], r8 lea rsi, [rsi+rdx*sizeof(qword)] lea rdi, [rdi+rdx*sizeof(qword)] lea rcx, [rdx*sizeof(qword)] sbb rax, rax ; save cf neg rcx ; rcx = negative length (bytes) add rcx, sizeof(qword) jrcxz .exit add rax, rax ; restore cf jnc .copy align IPP_ALIGN_FACTOR .inc_loop: mov r8, qword [rsi+rcx] sbb r8, 0 mov qword [rdi+rcx], r8 lea rcx, [rcx+sizeof(qword)] jrcxz .exit_loop jnc .exit_loop jmp .inc_loop .exit_loop: sbb rax, rax ; save cf .copy: cmp rsi, rdi jz .exit jrcxz .exit .copy_loop: mov r8, qword [rsi+rcx] mov qword [rdi+rcx], r8 add rcx, sizeof(qword) jnz .copy_loop .exit: neg rax REST_XMM REST_GPR ret ENDFUNC cpDec_BNU %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnum7.inc000066400000000000000000000437061470420105600256160ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number macros ; ; Content: ; SWAP ; EXPAND_BNU ; ; COPY_BNU ; FIX_BNU CMP_BNU ; ; ADD_BNU SUB_BNU ; ECARRY EBORROW ; ; MUL_BNU_D32 MAC_BNU_D32 ; MUL_BNU_D64 MAC_BNU_D64 ; ; MAC MAC2 ; ; ADD_FIX_BNU SUB_FIX_BNU ; ;; ;; Swap values or addresses ;; %macro SWAP 4.nolist %xdefine %%cc %1 %xdefine %%dst %2 %xdefine %%src %3 %xdefine %%tmp %4 cmov&%%cc %%tmp,%%src cmov&%%cc %%src,%%dst cmov&%%cc %%dst,%%tmp %endmacro ;; ;; EXPAND_BNU expands BNU by zero %if one has odd size ;; %macro EXPAND_BNU 2.nolist %xdefine %%rBNU %1 %xdefine %%rLen %2 test %%rLen,1 jz %%expand_quit mov DWORD [%%rBNU+%%rLen*4],0 add %%rLen,1 %%expand_quit: %endmacro ;; ;; COPY_BNU ;; %macro COPY_BNU 5.nolist %xdefine %%rSrc %1 %xdefine %%rDst %2 %xdefine %%rLen %3 %xdefine %%rIdx %4 %xdefine %%rTmp %5 xor %%rIdx,%%rIdx %%copy_bnu: mov %%rTmp&d,[%%rSrc+%%rIdx*4] mov [%%rDst+%%rIdx*4],%%rTmp&d add %%rIdx,1 cmp %%rIdx,%%rLen jl %%copy_bnu %endmacro ;; ;; FIX_BNU returns actual length of BNU ;; ;; input ;; rSrc points BNU ;; rLen initial BNU size ;; ;; output ;; rSrc points BNU ;; rLen actual BNU size ;; %macro FIX_BNU 3.nolist %xdefine %%rSrc %1 %xdefine %%rLen %2 %xdefine %%tmp %3 %%fix_bnu_loop: mov %%tmp&d,[%%rSrc+%%rLen*4-4] ;; value test %%tmp&d,%%tmp&d ;; test BNU component jnz %%fix_bnu_quit sub %%rLen,1 jg %%fix_bnu_loop add %%rLen,1 %%fix_bnu_quit: %endmacro ;; ;; CMP_BNU compare BNUs ;; ;; input ;; rSrc1 points BNU1 ;; rSrc2 points BNU2 ;; rLen size of BNUs ;; ;; output ;; rCode -1/0/1 ;; %macro CMP_BNU 4.nolist %xdefine %%rCode %1 %xdefine %%rSrc1 %2 %xdefine %%rSrc2 %3 %xdefine %%rLen %4 %%cmp_bnu_loop: mov %%rCode&d,[%%rSrc1+%%rLen*4-4] ;; src1[] cmp %%rCode&d,[%%rSrc2+%%rLen*4-4] ;; src1[] ~ src2[] jnz %%cmp_bnu_quit ;; src1[] != src2[] sub %%rLen,1 jg %%cmp_bnu_loop %%cmp_bnu_quit: seta %%rCode&b ;; rCode = (src1[]>src2[])? 1:0 setb %%rLen&b ;; rLen = (src1[]= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ; Ipp64u cpAddMulDgt_BNU(Ipp64u* pDst, ; const Ipp64u* pSrcA, ; int len, ; Ipp64u B ) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpAddMulDgt_BNU,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r11,r12 USES_XMM COMP_ABI 4 ; rdi = pDst ; rsi = pSrc ; rdx = len ; rcx = B %xdefine B0 rcx ; b %xdefine T0 r8 ; temporary %xdefine T1 r9 %xdefine T2 r10 %xdefine T3 r11 %xdefine idx rbx ; index %xdefine rDst rdi %xdefine rSrc rsi mov edx, edx ; unsigned length mov rax, qword [rsi] cmp rdx, 1 jnz .general_case mul rcx add qword [rdi], rax adc rdx, 0 mov rax, rdx REST_XMM REST_GPR ret .general_case: lea rSrc, [rSrc+rdx*sizeof(qword)-sizeof(qword)*5] lea rDst, [rDst+rdx*sizeof(qword)-sizeof(qword)*5] mov idx, dword 5 sub idx, rdx ; negative counter -(len-5) mul rcx ; {T1:T0} = a[0]*B mov T0, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)] mov T1, rdx cmp idx, 0 jge .skip_muladd_loop4 align IPP_ALIGN_FACTOR .muladd_loop4: mul rcx ; a[4*i+1]*B xor T2, T2 add qword [rDst+idx*sizeof(qword)], T0 adc T1, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*2] adc T2, rdx mul rcx ; a[4*i+2]*B xor T3, T3 add qword [rDst+idx*sizeof(qword)+sizeof(qword)], T1 adc T2, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*3] adc T3, rdx mul rcx ; a[4*i+3]*B xor T0, T0 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*2], T2 adc T3, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*4] adc T0, rdx mul rcx ; a[4*i+4]*B xor T1, T1 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*3], T3 adc T0, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*5] adc T1, rdx add idx, 4 jnc .muladd_loop4 .skip_muladd_loop4: mul rcx xor T2, T2 add qword [rDst+idx*sizeof(qword)], T0 adc T1, rax adc T2, rdx cmp idx, 2 ja .fin_mul1x4n_2 ; idx=3 jz .fin_mul1x4n_3 ; idx=2 jp .fin_mul1x4n_4 ; idx=1 ; .fin_mul1x4n_1 ; idx=0 .fin_mul1x4n_1: mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*2] mul rcx xor T3, T3 add qword [rDst+idx*sizeof(qword)+sizeof(qword)], T1 adc T2, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*3] adc T3, rdx mul rcx xor T0, T0 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*2], T2 adc T3, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*4] adc T0, rdx mul rcx xor T1, T1 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*3], T3 adc T0, rax adc rdx, 0 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*4], T0 adc rdx, 0 mov rax, rdx jmp .exit .fin_mul1x4n_4: mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*2] mul rcx xor T3, T3 add qword [rDst+idx*sizeof(qword)+sizeof(qword)], T1 adc T2, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*3] adc T3, rdx mul rcx xor T0, T0 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*2], T2 adc T3, rax adc rdx, 0 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*3], T3 adc rdx, 0 mov rax, rdx jmp .exit .fin_mul1x4n_3: mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)*2] mul rcx xor T3, T3 add qword [rDst+idx*sizeof(qword)+sizeof(qword)], T1 adc T2, rax adc rdx, 0 add qword [rDst+idx*sizeof(qword)+sizeof(qword)*2], T2 adc rdx, 0 mov rax, rdx jmp .exit .fin_mul1x4n_2: add qword [rDst+idx*sizeof(qword)+sizeof(qword)], T1 adc T2, 0 mov rax, T2 .exit: REST_XMM REST_GPR ret ENDFUNC cpAddMulDgt_BNU %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumul.inc000066400000000000000000000443471470420105600260720ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number multiplication Support ; ; %ifndef _PCPBNUMUL_INC_ %assign _PCPBNUMUL_INC_ 1 %include "pcpbnumul_basic.inc" %macro CLEAR 2.nolist %xdefine %%rPtr %1 %xdefine %%rLen %2 %%L_1: mov qword [%%rPtr], rax add %%rPtr, sizeof(qword) sub %%rLen, 1 jnz %%L_1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; (8*n)x(8*m) multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mul_8Nx8M,PRIVATE push rbx ;; nsB push rdi ;; pR push rsi ;; pA push rdx ;; nsA ;;; ;;; init ;;; .mul_loopA: push rdx ;; nsA call mla_8x8 add rdi, sizeof(qword)*8 ; adv pR add rsi, sizeof(qword)*8 ; adv pA pop rdx ; nsA-- sub rdx, 8 jnz .mul_loopA mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .mla_entry .mla_loopB: push rbx ;; nsB push rdi ;; pR push rsi ;; pA push rdx ;; nsA xor rax, rax ; c-flag push rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] .loopA: push rdx ; nsA call mla_8x8 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 pop rdx ; nsA-- sub rdx, 8 jz .exit_loopA pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15,qword [rdi+sizeof(qword)*7], rax sbb rax, rax ; save c-flag push rax jmp .loopA .exit_loopA: pop rax ; restore c-flag neg rax adc r8, 0 mov qword [rdi+sizeof(qword)*0], r8 adc r9, 0 mov qword [rdi+sizeof(qword)*1], r9 adc r10,0 mov qword [rdi+sizeof(qword)*2],r10 adc r11,0 mov qword [rdi+sizeof(qword)*3],r11 adc r12,0 mov qword [rdi+sizeof(qword)*4],r12 adc r13,0 mov qword [rdi+sizeof(qword)*5],r13 adc r14,0 mov qword [rdi+sizeof(qword)*6],r14 adc r15,0 mov qword [rdi+sizeof(qword)*7],r15 .mla_entry: pop rdx ; restore nsA pop rsi ; restore pA pop rdi add rdi, sizeof(qword)*8 add rcx, sizeof(qword)*8 pop rbx ;; nsB-- sub rbx, 8 jnz .mla_loopB ret ENDFUNC mul_8Nx8M ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; simplest general case N x M multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_simple,PRIVATE xor rax, rax ; carry = 0 mov r11, rdx cmp r11, rbx jge .ms_mla_entry SWAP r11, rbx SWAP rsi, rcx jmp .ms_mla_entry .ms_loopB: push rbx ;; nsB push rdi ;; pR push rsi ;; pA push r11 ;; nsA push rax ;; save previous pass carry mov rdx, qword [rcx] ; pB[] xor r10, r10 ; extension .ms_loopA: gsmulx r9, r8, qword [rsi] add rdi, sizeof(qword) add rsi, sizeof(qword) add r8, r10 adc r9, 0 add r8, qword [rdi-sizeof(qword)] adc r9, 0 mov qword [rdi-sizeof(qword)], r8 mov r10, r9 sub r11, 1 jnz .ms_loopA pop rax ; restore carry shr rax, 1 adc r10, qword [rdi] mov qword [rdi], r10 adc rax, 0 ; save carry pop r11 ; restore nsA pop rsi ; restore pA pop rdi ; restore pR pop rbx ; nsB add rdi, sizeof(qword) add rcx, sizeof(qword) .ms_mla_entry: sub rbx, 1 jnc .ms_loopB ret ENDFUNC mla_simple ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case N x M multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mul_NxM,PRIVATE ; ; stack struct ; %assign nsB_cnt 0 ; rest of B operand %assign ptrR nsB_cnt+sizeof(qword) ; current product pointer %assign ptrA ptrR+sizeof(qword) ; pointer to A operand (pA) %assign nsA ptrA+sizeof(qword) ; length of A operand (nsA) %assign nsA_cnt nsA+sizeof(qword) ; rest of A operand %assign carry nsA_cnt+sizeof(qword) ; carry %assign tailproc carry+sizeof(qword) ; mla_8xn procedure %assign stack_mem tailproc+sizeof(qword) ; size of stack allocation sub rsp, stack_mem ; allocate stack cmp rbx, 8 jge .regular_entry cmp rdx, 8 jge .irregular_entry ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; degradated case ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; clear product mov r8, rdx add r8, rbx mov rbp, rdi xor rax, rax CLEAR rbp, r8 call mla_simple jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; irregular init ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .irregular_entry: mov [rsp+nsB_cnt], rbx mov [rsp+nsA], rdx mov [rsp+nsA_cnt], rdx GET_EP rax, mla_8xl_tail, rbx, rbp ; tail procedure (mla_8xn) address mov [rsp+tailproc], rax jmp .irr_init_entry .irr_init_loop: mov [rsp+nsA_cnt], rdx ; save A counter call rax mov rbx, [rsp+nsB_cnt] mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*7], r15 add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 xor r8, r8 xor r9, r9 xor r10,r10 xor r11,r11 xor r12,r12 xor r13,r13 xor r14,r14 xor r15,r15 ; load data depending on nsB length mov r8, qword [rdi] cmp rbx, 1 jz .continue mov r9, qword [rdi+sizeof(qword)] cmp rbx, 2 jz .continue mov r10, qword [rdi+sizeof(qword)*2] cmp rbx, 3 jz .continue mov r11, qword [rdi+sizeof(qword)*3] cmp rbx, 4 jz .continue mov r12, qword [rdi+sizeof(qword)*4] cmp rbx, 5 jz .continue mov r13, qword [rdi+sizeof(qword)*5] cmp rbx, 6 jz .continue mov r14, qword [rdi+sizeof(qword)*6] .continue: mov rdx, [rsp+nsA_cnt] ; nsA .irr_init_entry: sub rdx, 8 mov rax, [rsp+tailproc] jnc .irr_init_loop add rdx, 8 jz .quit ; clear uninitialized rest of product lea rbp, [rdi+rbx*sizeof(qword)] xor rax, rax CLEAR rbp, rdx mov rdx, [rsp+nsA_cnt] call mla_simple jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; regular ep ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .regular_entry: sub rbx, 8 xor rax, rax mov [rsp+nsB_cnt], rbx mov [rsp+ptrR], rdi mov [rsp+ptrA], rsi mov [rsp+nsA], rdx mov [rsp+nsA_cnt], rdx mov [rsp+carry], rax mov rbp, rdx ; n = nsA %8 and rbp, 7 GET_EP rax, mla_8xl_tail, rbp ; tail procedure (mla_8xn) address mov [rsp+tailproc], rax ;; ;; regular init ;; sub rdx, 8 ;; nsA counter .init_loopA: mov [rsp+nsA_cnt], rdx ; nsA call mla_8x8 mov rdx, [rsp+nsA_cnt] add rdi, sizeof(qword)*8 ; adv ptrR add rsi, sizeof(qword)*8 ; adv ptrA sub rdx, 8 ; nsA -= 8 jnc .init_loopA add rdx, 8 jz .init_complete mov [rsp+nsA_cnt], rdx mov rax, [rsp+tailproc] SWAP rcx, rsi call rax SWAP rcx, rsi mov rdx, [rsp+nsA_cnt] lea rdi, [rdi+rdx*sizeof(qword)] .init_complete: mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .mla_entry ;; ;; regular mla passes ;; .mla_loopB: mov [rsp+nsB_cnt], rbx ; update B counter mov [rsp+ptrR], rdi ; update current product pointer xor rax, rax ; init carry mov [rsp+carry], rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] sub rdx, 8 .loopA: mov [rsp+nsA_cnt], rdx ; save A counter call mla_8x8 mov rdx, [rsp+nsA_cnt] ; A counter add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 sub rdx, 8 ; nsA -= 8 jc .exit_loopA mov rax, [rsp+carry] ; restore carry shr rax, 1 op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rbx op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rbx op_reg_mem adc, r10,qword [rdi+sizeof(qword)*2], rbx op_reg_mem adc, r11,qword [rdi+sizeof(qword)*3], rbx op_reg_mem adc, r12,qword [rdi+sizeof(qword)*4], rbx op_reg_mem adc, r13,qword [rdi+sizeof(qword)*5], rbx op_reg_mem adc, r14,qword [rdi+sizeof(qword)*6], rbx op_reg_mem adc, r15,qword [rdi+sizeof(qword)*7], rbx adc rax, 0 ; save carry mov [rsp+carry], rax jmp .loopA .exit_loopA: add rdx, 8 jz .complete_reg_loopB mov [rsp+nsA_cnt], rdx ; put zeros xor rax, rax .put_zero: mov qword [rdi+rdx*sizeof(qword)], rax add rdx,1 cmp rdx, 8 jl .put_zero mov rax, [rsp+carry] ; restore carry shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*4], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*5], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*6], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*7], rbx adc rax, 0 ; save carry mov [rsp+carry], rax mov rax, [rsp+tailproc] SWAP rcx, rsi call rax SWAP rcx, rsi mov rdx, [rsp+nsA_cnt] ; restore nsA lea rdi, [rdi+rdx*sizeof(qword)] mov rax, [rsp+carry] ; restore carry shr rax, 1 dec rdx jz .mt_1 dec rdx jz .mt_2 dec rdx jz .mt_3 dec rdx jz .mt_4 dec rdx jz .mt_5 dec rdx jz .mt_6 .mt_7: adc r9, 0 .mt_6: adc r10,0 .mt_5: adc r11,0 .mt_4: adc r12,0 .mt_3: adc r13,0 .mt_2: adc r14,0 .mt_1: adc r15,0 mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .mla_entry .complete_reg_loopB: mov rax, [rsp+carry] ; restore carry add r8, rax adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 adc r14,0 adc r15,0 mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 .mla_entry: ; restore: mov rbx, [rsp+nsB_cnt] ; - B counter mov rdi, [rsp+ptrR] ; - ptrR mov rdx, [rsp+nsA] ; - nsA mov rsi, [rsp+ptrA] ; - pA add rcx, sizeof(qword)*8 ; adv pB add rdi, sizeof(qword)*8 ; adv ptrR sub rbx, 8 ; nsB -= 8 jnc .mla_loopB add rbx, 8 jz .quit ;; ;; final mla pass ;; mov [rsp+nsB_cnt], rbx GET_EP rax, mla_8xl_tail, rbx, rbp ; tail procedure (mla_8xn) address mov [rsp+tailproc], rax ; clear uninitialized rest of product lea rbp, [rdi+rdx*sizeof(qword)] xor rax, rax CLEAR rbp, rbx xor rax, rax ; init carry mov [rsp+carry], rax sub rdx, 8 .tail_loopA: mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov [rsp+nsA_cnt], rdx ; save A counter mov rax, [rsp+tailproc] call rax .entry_tail_loopA: mov rax, [rsp+carry] ; restore carry shr rax, 1 adc r8, 0 adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 mov rbx, [rsp+nsB_cnt] ; nsB mov rbp, rbx dec rbp jz .tt_1 dec rbp jz .tt_2 dec rbp jz .tt_3 dec rbp jz .tt_4 dec rbp jz .tt_5 dec rbp jz .tt_6 .tt_7: op_reg_mem adc, r9, [rdi+rbx*sizeof(qword)+sizeof(qword)*1], rbp .tt_6: op_reg_mem adc, r10,[rdi+rbx*sizeof(qword)+sizeof(qword)*2], rbp .tt_5: op_reg_mem adc, r11,[rdi+rbx*sizeof(qword)+sizeof(qword)*3], rbp .tt_4: op_reg_mem adc, r12,[rdi+rbx*sizeof(qword)+sizeof(qword)*4], rbp .tt_3: op_reg_mem adc, r13,[rdi+rbx*sizeof(qword)+sizeof(qword)*5], rbp .tt_2: op_reg_mem adc, r14,[rdi+rbx*sizeof(qword)+sizeof(qword)*6], rbp .tt_1: op_reg_mem adc, r15,[rdi+rbx*sizeof(qword)+sizeof(qword)*7], rbp adc rax, 0 mov [rsp+carry], rax ; update carry mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*7], r15 mov rdx, [rsp+nsA_cnt] ; A counter add rsi, sizeof(qword)*8 ; adv pA add rdi, sizeof(qword)*8 ; adv pR sub rdx, 8 ; nsA -= 8 jnc .tail_loopA add rdx, 8 jz .quit ; carry propagation mov rax, [rsp+carry] mov rbp, rbx dec rbp mov r8, qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0] add r8, rax mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 jz .simple dec rbp mov r9, qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1] adc r9, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 jz .simple dec rbp mov r10,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2] adc r10, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 jz .simple dec rbp mov r11,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3] adc r11, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 jz .simple dec rbp mov r12,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4] adc r12, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 jz .simple dec rbp mov r13,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5] adc r13, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 jz .simple dec rbp mov r14,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6] adc r14, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 .simple: call mla_simple .quit: add rsp, stack_mem ; release stack ret ENDFUNC mul_NxM %endif ;; _PCPBNUMUL_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumul_basic.inc000066400000000000000000000564241470420105600272320ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number multiplication Support ; ; %ifndef _PCPBNUMUL_BASIC_INC_ %assign _PCPBNUMUL_BASIC_INC_ 1 %include "pcpmulx.inc" %include "pcpbnumul_fix.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; short size (1-8 qwords) operand mla and mul operations ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; 1x1 multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_1x1,PRIVATE mov rdx, qword [rcx] MLA_FIX 1, rdi, rsi, rbx,rbp, r8 ret ENDFUNC mla_1x1 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_1x1,PRIVATE mov rdx,qword [rcx] gsmulx rdx, rax, qword [rsi] mov qword [rdi], rax mov qword [rdi+sizeof(qword)], rdx ret ENDFUNC mul_1x1 ;; ;; 2x2 multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_2x2,PRIVATE mov rdx, qword [rcx] MLA_FIX 2, rdi, rsi, rbx,rbp, r8,r9 mov rdx, qword [rcx+sizeof(qword)] MLA_FIX 2, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9 ret ENDFUNC mla_2x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_2x2,PRIVATE call mla_2x2 mov qword [rdi+sizeof(qword)*2], r8 mov qword [rdi+sizeof(qword)*3], r9 ret ENDFUNC mul_2x2 ;; ;; 3x3 multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_3x3,PRIVATE mov rdx, qword [rcx] MLA_FIX 3, rdi, rsi, rbx,rbp, r8,r9,r10 mov rdx, qword [rcx+sizeof(qword)] MLA_FIX 3, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10 mov rdx, qword [rcx+sizeof(qword)*2] MLA_FIX 3, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10 ret ENDFUNC mla_3x3 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_3x3,PRIVATE call mla_3x3 mov qword [rdi+sizeof(qword)*3], r8 mov qword [rdi+sizeof(qword)*4], r9 mov qword [rdi+sizeof(qword)*5], r10 ret ENDFUNC mul_3x3 ;; ;; 4x{2,4} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_4x2,PRIVATE mov rdx, qword [rcx] MLA_FIX 4, rdi, rsi, rbx,rbp, r8,r9,r10,r11 mov rdx, qword [rcx+sizeof(qword)] MLA_FIX 4, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10,r11 ret ENDFUNC mla_4x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_4x4,PRIVATE call mla_4x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_4x2 sub rdi, sizeof(qword)*2 sub rcx, sizeof(qword)*2 ret ENDFUNC mla_4x4 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_4x4,PRIVATE call mla_4x4 mov qword [rdi+sizeof(qword)*4], r8 mov qword [rdi+sizeof(qword)*5], r9 mov qword [rdi+sizeof(qword)*6], r10 mov qword [rdi+sizeof(qword)*7], r11 ret ENDFUNC mul_4x4 ;; ;; 5x{2,5} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_5x2,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 5, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 5, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10,r11,r12 ret ENDFUNC mla_5x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_5x5,PRIVATE mov rdx, [rcx] MLA_FIX 5, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_5x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_5x2 sub rdi, sizeof(qword)*3 sub rcx, sizeof(qword)*3 ret ENDFUNC mla_5x5 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_5x5,PRIVATE call mla_5x5 mov qword [rdi+sizeof(qword)*5], r8 mov qword [rdi+sizeof(qword)*6], r9 mov qword [rdi+sizeof(qword)*7], r10 mov qword [rdi+sizeof(qword)*8], r11 mov qword [rdi+sizeof(qword)*9], r12 ret ENDFUNC mul_5x5 ;; ;; 6x{2,6} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_6x2,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 6, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 6, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 ret ENDFUNC mla_6x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_6x6,PRIVATE call mla_6x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_6x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_6x2 sub rdi, sizeof(qword)*4 sub rcx, sizeof(qword)*4 ret ENDFUNC mla_6x6 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_6x6,PRIVATE call mla_6x6 mov qword [rdi+sizeof(qword)*6], r8 mov qword [rdi+sizeof(qword)*7], r9 mov qword [rdi+sizeof(qword)*8], r10 mov qword [rdi+sizeof(qword)*9], r11 mov qword [rdi+sizeof(qword)*10],r12 mov qword [rdi+sizeof(qword)*11],r13 ret ENDFUNC mul_6x6 ;; ;; 7x{2,7} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_7x2,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 7, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 7, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 ret ENDFUNC mla_7x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_7x7,PRIVATE mov rdx, [rcx] MLA_FIX 7, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_7x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_7x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_7x2 sub rdi, sizeof(qword)*5 sub rcx, sizeof(qword)*5 ret ENDFUNC mla_7x7 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_7x7,PRIVATE call mla_7x7 mov qword [rdi+sizeof(qword)*7], r8 mov qword [rdi+sizeof(qword)*8], r9 mov qword [rdi+sizeof(qword)*9], r10 mov qword [rdi+sizeof(qword)*10],r11 mov qword [rdi+sizeof(qword)*11],r12 mov qword [rdi+sizeof(qword)*12],r13 mov qword [rdi+sizeof(qword)*13],r14 ret ENDFUNC mul_7x7 ;; ;; 8x{1,2,3,4,5,6,7,8} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x1,PRIVATE mov rdx, [rcx] MLA_FIX 8, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x1 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x2,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x3,PRIVATE call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x2 sub rdi, sizeof(qword) sub rcx, sizeof(qword) ret ENDFUNC mla_8x3 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x4,PRIVATE call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*2 sub rcx, sizeof(qword)*2 ret ENDFUNC mla_8x4 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x5,PRIVATE call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x4 sub rdi, sizeof(qword) sub rcx, sizeof(qword) ret ENDFUNC mla_8x5 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x6,PRIVATE call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x4 sub rdi, sizeof(qword)*2 sub rcx, sizeof(qword)*2 ret ENDFUNC mla_8x6 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x7,PRIVATE call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x6 sub rdi, sizeof(qword) sub rcx, sizeof(qword) ret ENDFUNC mla_8x7 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x8,PRIVATE call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*6 sub rcx, sizeof(qword)*6 ret ENDFUNC mla_8x8 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_8x8,PRIVATE call mla_8x8 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],r15 ret ENDFUNC mul_8x8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; middle size (9-16 qwords) operand mla and mul operations ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mul_9x9,PRIVATE call mla_8x8 mov rdx, [rcx+sizeof(qword)*8] MLA_FIX 8, {rdi+sizeof(qword)*8}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 push r15 mov rdx, [rsi+sizeof(qword)*8] mov r15, [rdi+sizeof(qword)*8] MLA_FIX 8, {rdi+sizeof(qword)*8}, rcx, rbx,rbp, r15,r8,r9,r10,r11,r12,r13,r14 mov qword [rdi+sizeof(qword)*9], r15 gsmulx r15, rbp, [rcx+sizeof(qword)*8] pop rax add r14, rax adc r15,0 add r14, rbp adc r15, 0 mov qword [rdi+sizeof(qword)*10],r8 mov qword [rdi+sizeof(qword)*11],r9 mov qword [rdi+sizeof(qword)*12],r10 mov qword [rdi+sizeof(qword)*13],r11 mov qword [rdi+sizeof(qword)*14],r12 mov qword [rdi+sizeof(qword)*15],r13 mov qword [rdi+sizeof(qword)*16],r14 mov qword [rdi+sizeof(qword)*17],r15 ret ENDFUNC mul_9x9 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_10x10,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x2 push r15 push r14 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r13 mov r14, r12 mov r13, r11 mov r12, r10 mov r11, r9 mov r10, r8 mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x2 mov qword [rdi+sizeof(qword)*2],r8 mov qword [rdi+sizeof(qword)*3],r9 mov qword [rdi+sizeof(qword)*4],r10 mov qword [rdi+sizeof(qword)*5],r11 mov qword [rdi+sizeof(qword)*6],r12 mov qword [rdi+sizeof(qword)*7],r13 add rdi, sizeof(qword)*8 xor r10, r10 pop r8 pop r9 add r8, r14 adc r9, r15 adc r10,0 ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_2x2 add rdi, sizeof(qword)*2 add r8, r10 adc r9, 0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 ret ENDFUNC mul_10x10 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_11x11,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x3 push r15 push r14 push r13 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r12 mov r14, r11 mov r13, r10 mov r12, r9 mov r11, r8 mov r10,qword [rdi+sizeof(qword)*2] mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x3 mov qword [rdi+sizeof(qword)*3],r8 mov qword [rdi+sizeof(qword)*4],r9 mov qword [rdi+sizeof(qword)*5],r10 mov qword [rdi+sizeof(qword)*6],r11 mov qword [rdi+sizeof(qword)*7],r12 add rdi, sizeof(qword)*8 xor r11, r11 pop r8 pop r9 pop r10 add r8, r13 adc r9, r14 adc r10,r15 adc r11,0 ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_3x3 add rdi, sizeof(qword)*3 add r8, r11 adc r9, 0 adc r10,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 ret ENDFUNC mul_11x11 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_12x12,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x4 push r15 push r14 push r13 push r12 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r11 mov r14, r10 mov r13, r9 mov r12, r8 mov r11,qword [rdi+sizeof(qword)*3] mov r10,qword [rdi+sizeof(qword)*2] mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x4 mov qword [rdi+sizeof(qword)*4],r8 mov qword [rdi+sizeof(qword)*5],r9 mov qword [rdi+sizeof(qword)*6],r10 mov qword [rdi+sizeof(qword)*7],r11 add rdi, sizeof(qword)*8 xor rax, rax pop r8 pop r9 pop r10 pop r11 add r8, r12 adc r9, r13 adc r10,r14 adc r11,r15 adc rax,0 push rax ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_4x4 add rdi, sizeof(qword)*4 pop rax add r8, rax adc r9, 0 adc r10,0 adc r11,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 ret ENDFUNC mul_12x12 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_13x13,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x5 push r15 push r14 push r13 push r12 push r11 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r10 mov r14, r9 mov r13, r8 mov r12,qword [rdi+sizeof(qword)*4] mov r11,qword [rdi+sizeof(qword)*3] mov r10,qword [rdi+sizeof(qword)*2] mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x5 mov qword [rdi+sizeof(qword)*5], r8 mov qword [rdi+sizeof(qword)*6], r9 mov qword [rdi+sizeof(qword)*7], r10 add rdi, sizeof(qword)*8 xor rax, rax pop r8 pop r9 pop r10 pop rbx pop rbp add r8, r11 adc r9, r12 adc r10,r13 adc rbx,r14 adc rbp,r15 adc rax,0 push rax mov r11, rbx mov r12, rbp ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_5x5 add rdi, sizeof(qword)*5 pop rax add r8, rax adc r9, 0 adc r10,0 adc r11,0 adc r12,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 ret ENDFUNC mul_13x13 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_14x14,PRIVATE call mla_7x7 add rdi, sizeof(qword)*7 add rsi, sizeof(qword)*7 call mla_7x7 mov qword [rdi+sizeof(qword)*7], r8 mov qword [rdi+sizeof(qword)*8], r9 mov qword [rdi+sizeof(qword)*9], r10 mov qword [rdi+sizeof(qword)*10],r11 mov qword [rdi+sizeof(qword)*11],r12 mov qword [rdi+sizeof(qword)*12],r13 mov qword [rdi+sizeof(qword)*13],r14 mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] add rcx, sizeof(qword)*7 sub rsi, sizeof(qword)*7 call mla_7x7 xor rdx, rdx op_reg_mem add, r8, qword [rdi+sizeof(qword)*7], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*8], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*9], rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*10],rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*11],rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*12],rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*13],rax adc rdx, 0 push rdx add rdi, sizeof(qword)*7 add rsi, sizeof(qword)*7 call mla_7x7 sub rdi, sizeof(qword)*14 sub rsi, sizeof(qword)*7 sub rcx, sizeof(qword)*7 pop rdx add r8, rdx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 mov qword [rdi+sizeof(qword)*21],r8 mov qword [rdi+sizeof(qword)*22],r9 mov qword [rdi+sizeof(qword)*23],r10 mov qword [rdi+sizeof(qword)*24],r11 mov qword [rdi+sizeof(qword)*25],r12 mov qword [rdi+sizeof(qword)*26],r13 mov qword [rdi+sizeof(qword)*27],r14 ret ENDFUNC mul_14x14 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_15x15,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x7 mov qword [rdi+sizeof(qword)*7], r8 mov qword [rdi+sizeof(qword)*8], r9 mov qword [rdi+sizeof(qword)*9], r10 mov qword [rdi+sizeof(qword)*10],r11 mov qword [rdi+sizeof(qword)*11],r12 mov qword [rdi+sizeof(qword)*12],r13 mov qword [rdi+sizeof(qword)*13],r14 mov qword [rdi+sizeof(qword)*14],r15 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mla_8x7 mov qword [rdi+sizeof(qword)*7], r8 add rdi, sizeof(qword)*8 ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 mov r8, r9 mov r9, r10 mov r10,r11 mov r11,r12 mov r12,r13 mov r13,r14 mov r14,r15 xor rdx, rdx op_reg_mem add, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*6], rax adc rdx, 0 push rdx call mla_7x7 add rdi, sizeof(qword)*7 pop rax add r8, rax adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 adc r14,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 ret ENDFUNC mul_15x15 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_16x16,PRIVATE call mla_8x8 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_8x8 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],r15 mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] add rcx, sizeof(qword)*8 sub rsi, sizeof(qword)*8 call mla_8x8 xor rdx, rdx op_reg_mem add, r8, qword [rdi+sizeof(qword)*8], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*9], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*10],rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*11],rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*12],rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*13],rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*14],rax op_reg_mem adc, r15,qword [rdi+sizeof(qword)*15],rax adc rdx, 0 push rdx add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_8x8 sub rdi, sizeof(qword)*16 sub rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 pop rdx add r8, rdx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 mov qword [rdi+sizeof(qword)*24],r8 mov qword [rdi+sizeof(qword)*25],r9 mov qword [rdi+sizeof(qword)*26],r10 mov qword [rdi+sizeof(qword)*27],r11 mov qword [rdi+sizeof(qword)*28],r12 mov qword [rdi+sizeof(qword)*29],r13 mov qword [rdi+sizeof(qword)*30],r14 mov qword [rdi+sizeof(qword)*31],r15 ret ENDFUNC mul_16x16 mul_lxl_basic DQ mul_1x1 - mul_lxl_basic DQ mul_2x2 - mul_lxl_basic DQ mul_3x3 - mul_lxl_basic DQ mul_4x4 - mul_lxl_basic DQ mul_5x5 - mul_lxl_basic DQ mul_6x6 - mul_lxl_basic DQ mul_7x7 - mul_lxl_basic DQ mul_8x8 - mul_lxl_basic DQ mul_9x9 - mul_lxl_basic DQ mul_10x10-mul_lxl_basic DQ mul_11x11-mul_lxl_basic DQ mul_12x12-mul_lxl_basic DQ mul_13x13-mul_lxl_basic DQ mul_14x14-mul_lxl_basic DQ mul_15x15-mul_lxl_basic DQ mul_16x16-mul_lxl_basic mla_lxl_short DQ mla_1x1 - mla_lxl_short DQ mla_2x2 - mla_lxl_short DQ mla_3x3 - mla_lxl_short DQ mla_4x4 - mla_lxl_short DQ mla_5x5 - mla_lxl_short DQ mla_6x6 - mla_lxl_short DQ mla_7x7 - mla_lxl_short mla_8xl_tail DQ mla_8x1 - mla_8xl_tail DQ mla_8x2 - mla_8xl_tail DQ mla_8x3 - mla_8xl_tail DQ mla_8x4 - mla_8xl_tail DQ mla_8x5 - mla_8xl_tail DQ mla_8x6 - mla_8xl_tail DQ mla_8x7 - mla_8xl_tail %endif ;; _PCPBNUMUL_BASIC_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumul_fix.inc000066400000000000000000000247071470420105600267360ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number multiplication Support ; ; %ifndef _PCPBNUMUL_FIX_ADCX_INC_ %assign _PCPBNUMUL_FIX_ADCX_INC_ 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; macro used to replace op reg, mem instructions %macro SWAP 2.nolist %xdefine %%r1 %1 %xdefine %%r2 %2 xor %%r1, %%r2 xor %%r2, %%r1 xor %%r1, %%r2 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; macro used extract proc ep from the table %macro GET_EP 3-4.nolist %xdefine %%regEp %1 %xdefine %%Table %2 %xdefine %%regIdx %3 %xdefine %%tmp %4 lea %%regEp, [rel %%Table] %ifnempty %%tmp mov %%tmp, [%%regEp+%%regIdx*sizeof(qword)-sizeof(qword)] add %%regEp, %%tmp %else mov %%regIdx, [%%regEp+%%regIdx*sizeof(qword)-sizeof(qword)] add %%regEp, %%regIdx %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; op DST, mem_src %macro op_reg_mem 4.nolist %xdefine %%opCode %1 %xdefine %%dst %2 %xdefine %%mem_src %3 %xdefine %%tmp %4 mov %%tmp, %%mem_src %%opCode %%dst, %%tmp %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEM_DST = (op src1, mem_src2) %macro op_mem_reg_mem 5.nolist %xdefine %%opCode %1 %xdefine %%mem_dst %2 %xdefine %%src1 %3 %xdefine %%mem_src2 %4 %xdefine %%tmp %5 op_reg_mem %%opCode, %%src1, %%mem_src2, %%tmp mov %%mem_dst, %%src1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEM_DST = op mem_src1, mem_src2 %macro op_mem_mem 5.nolist %xdefine %%opCode %1 %xdefine %%mem_dst %2 %xdefine %%mem_src1 %3 %xdefine %%mem_src2 %4 %xdefine %%tmp %5 mov %%tmp, %%mem_src1 %%opCode %%tmp, %%mem_src2 mov %%mem_dst, %%tmp %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Inputs: pDst: Destination (up to 1024 bits, 16 qwords) ;;; pA: Multiplicand (up to 512 bits, 8 qwords) ;;; ;;; ;;; Uses registers: ;;; rdx - implicit multiplicand ;;; (HIP:LOP)- 64x64-bit product (mulx) ;;; X7,,X0 - high result ;;; %macro MUL_FIX 12-13.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%HIP %4 %xdefine %%LOP %5 %xdefine %%X0 %6 %xdefine %%X1 %7 %xdefine %%X2 %8 %xdefine %%X3 %9 %xdefine %%X4 %10 %xdefine %%X5 %11 %xdefine %%X6 %12 %xdefine %%X7 %13 gsmulx %%X0, %%LOP, [%%pA] ; (X0:LO) = a[0]*b %ifnempty %%pDst mov [%%pDst], %%LOP %endif %if %%N > 1 gsmulx %%X1, %%HIP, [%%pA+sizeof(qword)] ; (X1:LO) = a[1]*b add %%X0, %%HIP %if %%N == 2 adc %%X1, 0 %endif %if %%N > 2 gsmulx %%X2, %%LOP, [%%pA+sizeof(qword)*2] ; (X2:LO) = a[2]*b adc %%X1, %%LOP %if %%N == 3 adc %%X2, 0 %endif %if %%N > 3 gsmulx %%X3, %%HIP, [%%pA+sizeof(qword)*3] ; (X3:LO) = a[3]*b adc %%X2, %%HIP %if %%N == 4 adc %%X3, 0 %endif %if %%N > 4 gsmulx %%X4, %%LOP, [%%pA+sizeof(qword)*4] ; (X4:LO) = a[4]*b adc %%X3, %%LOP %if %%N == 5 adc %%X4, 0 %endif %if %%N > 5 gsmulx %%X5, %%HIP, [%%pA+sizeof(qword)*5] ; (X5:LO) = a[5]*b adc %%X4, %%HIP %if %%N == 6 adc %%X5, 0 %endif %if %%N > 6 gsmulx %%X6, %%LOP, [%%pA+sizeof(qword)*6] ; (X6:LO) = a[6]*b adc %%X5, %%LOP %if %%N == 7 adc %%X6, 0 %endif %if %%N > 7 gsmulx %%X7, %%HIP, [%%pA+sizeof(qword)*7] ; (X7:LO) = a[7]*b adc %%X6, %%HIP adc %%X7, 0 %endif %endif %endif %endif %endif %endif %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; {x7,x6,x5,x4,x3,x2,x1,x0},DCT[0] = {x7,x6,x5,x4,x3,x2,x1,x0} + A[7:0]*B[i] ;; ;; uses rax, rdx ;; rdx - implicit multiplicand B[i] (should to be preloaded) ;; rax - temporary product ;; (HIP:LOP)- 64x64-bit product (mulx) ;; X7,,X0 - high result ;; %macro MLA_FIX 6-13.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%HIP %4 %xdefine %%LOP %5 %xdefine %%X0 %6 %xdefine %%X1 %7 %xdefine %%X2 %8 %xdefine %%X3 %9 %xdefine %%X4 %10 %xdefine %%X5 %11 %xdefine %%X6 %12 %xdefine %%X7 %13 gsmulx %%HIP, rax, [%%pA] ; (HI:rax) = a[0]*b[i] add rax, %%X0 adc %%HIP, 0 %ifnempty %%pDst mov [%%pDst], rax %endif %if %%N == 1 mov %%X0, %%HIP %endif %if %%N > 1 gsmulx %%LOP,%%X0, [%%pA+sizeof(qword)] ; (LO:X0) = a[1]*b[i] add %%X0, %%X1 adc %%LOP, 0 add %%X0, %%HIP adc %%LOP, 0 %if %%N == 2 mov %%X1, %%LOP %endif %if %%N > 2 gsmulx %%HIP,%%X1, [%%pA+sizeof(qword)*2] ; (HI:X1) = a[2]*b[i] add %%X1, %%X2 adc %%HIP, 0 add %%X1, %%LOP adc %%HIP, 0 %if %%N == 3 mov %%X2, %%HIP %endif %if %%N > 3 gsmulx %%LOP,%%X2, [%%pA+sizeof(qword)*3] ; (LO,X2) = a[3]*b[i] add %%X2, %%X3 adc %%LOP, 0 add %%X2, %%HIP adc %%LOP, 0 %if %%N == 4 mov %%X3, %%LOP %endif %if %%N > 4 gsmulx %%HIP,%%X3, [%%pA+sizeof(qword)*4] ; (HI:X3) = a[4]*b[i] add %%X3, %%X4 adc %%HIP, 0 add %%X3, %%LOP adc %%HIP, 0 %if %%N == 5 mov %%X4, %%HIP %endif %if %%N > 5 gsmulx %%LOP,%%X4, [%%pA+sizeof(qword)*5] ; (LO:X4) = a[5]*b[i] add %%X4, %%X5 adc %%LOP, 0 add %%X4, %%HIP adc %%LOP, 0 %if %%N == 6 mov %%X5, %%LOP %endif %if %%N > 6 gsmulx %%HIP,%%X5, [%%pA+sizeof(qword)*6] ; (HI:X5) = a[6]*b[i] add %%X5, %%X6 adc %%HIP, 0 add %%X5, %%LOP adc %%HIP, 0 %if %%N == 7 mov %%X6, %%HIP %endif %if %%N > 7 gsmulx %%LOP, %%X6, [%%pA+sizeof(qword)*7] ; (LO:X6) = a[7]*b[i] add %%X6, %%X7 adc %%LOP, 0 add %%X6, %%HIP adc %%LOP, 0 mov %%X7, %%LOP %endif %endif %endif %endif %endif %endif %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Inputs: pDst: Destination (up to 1024 bits, 16 qwords) ;;; pA: Multiplicand (up to 512 bits, 8 qwords) ;;; pB: Multiplicand (up to 512 bits, 8 qwords) ;;; ;;; ;;; Uses registers: ;;; rdx - implicit multiplicand ;;; (HIP:LOP)- 64x64-bit product (mulx) ;;; X0,,X7 - high result ;;; %macro MUL_NxN 7-14.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%pB %4 %xdefine %%HIP %5 %xdefine %%LOP %6 %xdefine %%X0 %7 %xdefine %%X1 %8 %xdefine %%X2 %9 %xdefine %%X3 %10 %xdefine %%X4 %11 %xdefine %%X5 %12 %xdefine %%X6 %13 %xdefine %%X7 %14 mov rdx, [%%pB] MUL_FIX {%%N},%%pDst,{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%N > 1 mov rdx, [%%pB+sizeof(qword)*1] MLA_FIX {%%N},{%%pDst+sizeof(qword)*1},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 2 mov rdx, [%%pB+sizeof(qword)*2] MLA_FIX {%%N},{%%pDst+sizeof(qword)*2},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 3 mov rdx, [%%pB+sizeof(qword)*3] MLA_FIX {%%N},{%%pDst+sizeof(qword)*3},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 4 mov rdx, [%%pB+sizeof(qword)*4] MLA_FIX {%%N},{%%pDst+sizeof(qword)*4},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 5 mov rdx, [%%pB+sizeof(qword)*5] MLA_FIX {%%N},{%%pDst+sizeof(qword)*5},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 6 mov rdx, [%%pB+sizeof(qword)*6] MLA_FIX {%%N},{%%pDst+sizeof(qword)*6},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 7 mov rdx, [%%pB+sizeof(qword)*7] MLA_FIX {%%N},{%%pDst+sizeof(qword)*7},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 7 mov qword [%%pDst+sizeof(qword)*8], %%X0 mov qword [%%pDst+sizeof(qword)*9], %%X1 mov qword [%%pDst+sizeof(qword)*10], %%X2 mov qword [%%pDst+sizeof(qword)*11], %%X3 mov qword [%%pDst+sizeof(qword)*12], %%X4 mov qword [%%pDst+sizeof(qword)*13], %%X5 mov qword [%%pDst+sizeof(qword)*14], %%X6 mov qword [%%pDst+sizeof(qword)*15], %%X7 %elif %%N > 6 mov qword [%%pDst+sizeof(qword)*7], %%X0 mov qword [%%pDst+sizeof(qword)*8], %%X1 mov qword [%%pDst+sizeof(qword)*9], %%X2 mov qword [%%pDst+sizeof(qword)*10], %%X3 mov qword [%%pDst+sizeof(qword)*11], %%X4 mov qword [%%pDst+sizeof(qword)*12], %%X5 mov qword [%%pDst+sizeof(qword)*13], %%X6 %elif %%N > 5 mov qword [%%pDst+sizeof(qword)*6], %%X0 mov qword [%%pDst+sizeof(qword)*7], %%X1 mov qword [%%pDst+sizeof(qword)*8], %%X2 mov qword [%%pDst+sizeof(qword)*9], %%X3 mov qword [%%pDst+sizeof(qword)*10], %%X4 mov qword [%%pDst+sizeof(qword)*11], %%X5 %elif %%N > 4 mov qword [%%pDst+sizeof(qword)*5], %%X0 mov qword [%%pDst+sizeof(qword)*6], %%X1 mov qword [%%pDst+sizeof(qword)*7], %%X2 mov qword [%%pDst+sizeof(qword)*8], %%X3 mov qword [%%pDst+sizeof(qword)*9], %%X4 %elif %%N > 3 mov qword [%%pDst+sizeof(qword)*4], %%X0 mov qword [%%pDst+sizeof(qword)*5], %%X1 mov qword [%%pDst+sizeof(qword)*6], %%X2 mov qword [%%pDst+sizeof(qword)*7], %%X3 %elif %%N > 2 mov qword [%%pDst+sizeof(qword)*3], %%X0 mov qword [%%pDst+sizeof(qword)*4], %%X1 mov qword [%%pDst+sizeof(qword)*5], %%X2 %elif %%N > 1 mov qword [%%pDst+sizeof(qword)*2], %%X0 mov qword [%%pDst+sizeof(qword)*3], %%X1 %else mov qword [%%pDst+sizeof(qword)*1], %%X0 %endif ;; N==2 %endmacro %endif ;; _PCPBNUMUL_FIX_ADCX_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulpp.inc000066400000000000000000000444011470420105600264210ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number multiplication Support ; ; %ifndef _PCPBNUMUL_INC_ %assign _PCPBNUMUL_INC_ 1 %include "pcpbnumulpp_basic.inc" %macro CLEAR 2.nolist %xdefine %%rPtr %1 %xdefine %%rLen %2 %%L_1: mov qword [%%rPtr], rax add %%rPtr, sizeof(qword) sub %%rLen, 1 jnz %%L_1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; (8*n)x(8*m) multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mul_8Nx8M_adcox,PRIVATE push rbx ;; nsB push rdi ;; pR push rsi ;; pA push rdx ;; nsA ;;; ;;; init ;;; .mul_loopA: push rdx ;; nsA call mla_8x8 add rdi, sizeof(qword)*8 ; adv pR add rsi, sizeof(qword)*8 ; adv pA pop rdx ; nsA-- sub rdx, 8 jnz .mul_loopA mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .mla_entry .mla_loopB: push rbx ;; nsB push rdi ;; pR push rsi ;; pA push rdx ;; nsA xor rax, rax ; c-flag push rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] .loopA: push rdx ; nsA call mla_8x8 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 pop rdx ; nsA-- sub rdx, 8 jz .exit_loopA pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15,qword [rdi+sizeof(qword)*7], rax sbb rax, rax ; save c-flag push rax jmp .loopA .exit_loopA: pop rax ; restore c-flag neg rax adc r8, 0 mov qword [rdi+sizeof(qword)*0], r8 adc r9, 0 mov qword [rdi+sizeof(qword)*1], r9 adc r10,0 mov qword [rdi+sizeof(qword)*2],r10 adc r11,0 mov qword [rdi+sizeof(qword)*3],r11 adc r12,0 mov qword [rdi+sizeof(qword)*4],r12 adc r13,0 mov qword [rdi+sizeof(qword)*5],r13 adc r14,0 mov qword [rdi+sizeof(qword)*6],r14 adc r15,0 mov qword [rdi+sizeof(qword)*7],r15 .mla_entry: pop rdx ; restore nsA pop rsi ; restore pA pop rdi add rdi, sizeof(qword)*8 add rcx, sizeof(qword)*8 pop rbx ;; nsB-- sub rbx, 8 jnz .mla_loopB ret ENDFUNC mul_8Nx8M_adcox ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; simplest general case N x M multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_simple,PRIVATE xor rax, rax ; carry = 0 mov r11, rdx cmp r11, rbx jge .ms_mla_entry SWAP r11, rbx SWAP rsi, rcx jmp .ms_mla_entry .ms_loopB: push rbx ;; nsB push rdi ;; pR push rsi ;; pA push r11 ;; nsA push rax ;; save previous pass carry mov rdx, qword [rcx] ; pB[] xor r10, r10 ; extension .ms_loopA: gsmulx r9, r8, qword [rsi] add rdi, sizeof(qword) add rsi, sizeof(qword) add r8, r10 adc r9, 0 add r8, qword [rdi-sizeof(qword)] adc r9, 0 mov qword [rdi-sizeof(qword)], r8 mov r10, r9 sub r11, 1 jnz .ms_loopA pop rax ; restore carry shr rax, 1 adc r10, qword [rdi] mov qword [rdi], r10 adc rax, 0 ; save carry pop r11 ; restore nsA pop rsi ; restore pA pop rdi ; restore pR pop rbx ; nsB add rdi, sizeof(qword) add rcx, sizeof(qword) .ms_mla_entry: sub rbx, 1 jnc .ms_loopB ret ENDFUNC mla_simple ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case N x M multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mul_NxM_adcox,PRIVATE ; ; stack struct ; %assign nsB_cnt 0 ; rest of B operand %assign ptrR nsB_cnt+sizeof(qword) ; current product pointer %assign ptrA ptrR+sizeof(qword) ; pointer to A operand (pA) %assign nsA ptrA+sizeof(qword) ; length of A operand (nsA) %assign nsA_cnt nsA+sizeof(qword) ; rest of A operand %assign carry nsA_cnt+sizeof(qword) ; carry %assign tailproc carry+sizeof(qword) ; mla_8xn procedure %assign stack_mem tailproc+sizeof(qword) ; size of stack allocation sub rsp, stack_mem ; allocate stack cmp rbx, 8 jge .regular_entry cmp rdx, 8 jge .irregular_entry ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; degradated case ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; clear product mov r8, rdx add r8, rbx mov rbp, rdi xor rax, rax CLEAR rbp, r8 call mla_simple jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; irregular init ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .irregular_entry: mov [rsp+nsB_cnt], rbx mov [rsp+nsA], rdx mov [rsp+nsA_cnt], rdx GET_EP rax, mla_8xl_tail, rbx, rbp ; tail procedure (mla_8xn) address mov [rsp+tailproc], rax jmp .irr_init_entry .irr_init_loop: mov [rsp+nsA_cnt], rdx ; save A counter call rax mov rbx, [rsp+nsB_cnt] mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*7], r15 add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 xor r8, r8 xor r9, r9 xor r10,r10 xor r11,r11 xor r12,r12 xor r13,r13 xor r14,r14 xor r15,r15 ; load data depending on nsB length mov r8, qword [rdi] cmp rbx, 1 jz .continue mov r9, qword [rdi+sizeof(qword)] cmp rbx, 2 jz .continue mov r10, qword [rdi+sizeof(qword)*2] cmp rbx, 3 jz .continue mov r11, qword [rdi+sizeof(qword)*3] cmp rbx, 4 jz .continue mov r12, qword [rdi+sizeof(qword)*4] cmp rbx, 5 jz .continue mov r13, qword [rdi+sizeof(qword)*5] cmp rbx, 6 jz .continue mov r14, qword [rdi+sizeof(qword)*6] .continue: mov rdx, [rsp+nsA_cnt] ; nsA .irr_init_entry: sub rdx, 8 mov rax, [rsp+tailproc] jnc .irr_init_loop add rdx, 8 jz .quit ; clear uninitialized rest of product lea rbp, [rdi+rbx*sizeof(qword)] xor rax, rax CLEAR rbp, rdx mov rdx, [rsp+nsA_cnt] call mla_simple jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; regular ep ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .regular_entry: sub rbx, 8 xor rax, rax mov [rsp+nsB_cnt], rbx mov [rsp+ptrR], rdi mov [rsp+ptrA], rsi mov [rsp+nsA], rdx mov [rsp+nsA_cnt], rdx mov [rsp+carry], rax mov rbp, rdx ; n = nsA %8 and rbp, 7 GET_EP rax, mla_8xl_tail, rbp ; tail procedure (mla_8xn) address mov [rsp+tailproc], rax ;; ;; regular init ;; sub rdx, 8 ;; nsA counter .init_loopA: mov [rsp+nsA_cnt], rdx ; nsA call mla_8x8 mov rdx, [rsp+nsA_cnt] add rdi, sizeof(qword)*8 ; adv ptrR add rsi, sizeof(qword)*8 ; adv ptrA sub rdx, 8 ; nsA -= 8 jnc .init_loopA add rdx, 8 jz .init_complete mov [rsp+nsA_cnt], rdx mov rax, [rsp+tailproc] SWAP rcx, rsi call rax SWAP rcx, rsi mov rdx, [rsp+nsA_cnt] lea rdi, [rdi+rdx*sizeof(qword)] .init_complete: mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .mla_entry ;; ;; regular mla passes ;; .mla_loopB: mov [rsp+nsB_cnt], rbx ; update B counter mov [rsp+ptrR], rdi ; update current product pointer xor rax, rax ; init carry mov [rsp+carry], rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] sub rdx, 8 .loopA: mov [rsp+nsA_cnt], rdx ; save A counter call mla_8x8 mov rdx, [rsp+nsA_cnt] ; A counter add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 sub rdx, 8 ; nsA -= 8 jc .exit_loopA mov rax, [rsp+carry] ; restore carry shr rax, 1 op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rbx op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rbx op_reg_mem adc, r10,qword [rdi+sizeof(qword)*2], rbx op_reg_mem adc, r11,qword [rdi+sizeof(qword)*3], rbx op_reg_mem adc, r12,qword [rdi+sizeof(qword)*4], rbx op_reg_mem adc, r13,qword [rdi+sizeof(qword)*5], rbx op_reg_mem adc, r14,qword [rdi+sizeof(qword)*6], rbx op_reg_mem adc, r15,qword [rdi+sizeof(qword)*7], rbx adc rax, 0 ; save carry mov [rsp+carry], rax jmp .loopA .exit_loopA: add rdx, 8 jz .complete_reg_loopB mov [rsp+nsA_cnt], rdx ; put zeros xor rax, rax .put_zero: mov qword [rdi+rdx*sizeof(qword)], rax add rdx,1 cmp rdx, 8 jl .put_zero mov rax, [rsp+carry] ; restore carry shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*4], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*5], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*6], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*7], rbx adc rax, 0 ; save carry mov [rsp+carry], rax mov rax, [rsp+tailproc] SWAP rcx, rsi call rax SWAP rcx, rsi mov rdx, [rsp+nsA_cnt] ; restore nsA lea rdi, [rdi+rdx*sizeof(qword)] mov rax, [rsp+carry] ; restore carry shr rax, 1 dec rdx jz .mt_1 dec rdx jz .mt_2 dec rdx jz .mt_3 dec rdx jz .mt_4 dec rdx jz .mt_5 dec rdx jz .mt_6 .mt_7: adc r9, 0 .mt_6: adc r10,0 .mt_5: adc r11,0 .mt_4: adc r12,0 .mt_3: adc r13,0 .mt_2: adc r14,0 .mt_1: adc r15,0 mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .mla_entry .complete_reg_loopB: mov rax, [rsp+carry] ; restore carry add r8, rax adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 adc r14,0 adc r15,0 mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 .mla_entry: ; restore: mov rbx, [rsp+nsB_cnt] ; - B counter mov rdi, [rsp+ptrR] ; - ptrR mov rdx, [rsp+nsA] ; - nsA mov rsi, [rsp+ptrA] ; - pA add rcx, sizeof(qword)*8 ; adv pB add rdi, sizeof(qword)*8 ; adv ptrR sub rbx, 8 ; nsB -= 8 jnc .mla_loopB add rbx, 8 jz .quit ;; ;; final mla pass ;; mov [rsp+nsB_cnt], rbx GET_EP rax, mla_8xl_tail, rbx, rbp ; tail procedure (mla_8xn) address mov [rsp+tailproc], rax ; clear uninitialized rest of product lea rbp, [rdi+rdx*sizeof(qword)] xor rax, rax CLEAR rbp, rbx xor rax, rax ; init carry mov [rsp+carry], rax sub rdx, 8 .tail_loopA: mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov [rsp+nsA_cnt], rdx ; save A counter mov rax, [rsp+tailproc] call rax .entry_tail_loopA: mov rax, [rsp+carry] ; restore carry shr rax, 1 adc r8, 0 adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 mov rbx, [rsp+nsB_cnt] ; nsB mov rbp, rbx dec rbp jz .tt_1 dec rbp jz .tt_2 dec rbp jz .tt_3 dec rbp jz .tt_4 dec rbp jz .tt_5 dec rbp jz .tt_6 .tt_7: op_reg_mem adc, r9, [rdi+rbx*sizeof(qword)+sizeof(qword)*1], rbp .tt_6: op_reg_mem adc, r10,[rdi+rbx*sizeof(qword)+sizeof(qword)*2], rbp .tt_5: op_reg_mem adc, r11,[rdi+rbx*sizeof(qword)+sizeof(qword)*3], rbp .tt_4: op_reg_mem adc, r12,[rdi+rbx*sizeof(qword)+sizeof(qword)*4], rbp .tt_3: op_reg_mem adc, r13,[rdi+rbx*sizeof(qword)+sizeof(qword)*5], rbp .tt_2: op_reg_mem adc, r14,[rdi+rbx*sizeof(qword)+sizeof(qword)*6], rbp .tt_1: op_reg_mem adc, r15,[rdi+rbx*sizeof(qword)+sizeof(qword)*7], rbp adc rax, 0 mov [rsp+carry], rax ; update carry mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*7], r15 mov rdx, [rsp+nsA_cnt] ; A counter add rsi, sizeof(qword)*8 ; adv pA add rdi, sizeof(qword)*8 ; adv pR sub rdx, 8 ; nsA -= 8 jnc .tail_loopA add rdx, 8 jz .quit ; carry propagation mov rax, [rsp+carry] mov rbp, rbx dec rbp mov r8, qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0] add r8, rax mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 jz .simple dec rbp mov r9, qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1] adc r9, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 jz .simple dec rbp mov r10,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2] adc r10, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 jz .simple dec rbp mov r11,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3] adc r11, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 jz .simple dec rbp mov r12,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4] adc r12, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 jz .simple dec rbp mov r13,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5] adc r13, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 jz .simple dec rbp mov r14,qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6] adc r14, 0 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 .simple: call mla_simple .quit: add rsp, stack_mem ; release stack ret ENDFUNC mul_NxM_adcox %endif ;; _PCPBNUMUL_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulpp_basic.inc000066400000000000000000000643141470420105600275670ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number multiplication Support ; ; %ifndef _PCPBNUMUL_BASIC_INC_ %assign _PCPBNUMUL_BASIC_INC_ 1 %include "pcpmulx.inc" %include "pcpbnumulpp_fix.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; short size (1-8 qwords) operand mla and mul operations ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; 1x1 multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_1x1,PRIVATE mov rdx, qword [rcx] MLA_FIX 1, rdi, rsi, rbx,rbp, r8 ret ENDFUNC mla_1x1 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_1x1,PRIVATE mov rdx,qword [rcx] gsmulx rdx, rax, qword [rsi] mov qword [rdi], rax mov qword [rdi+sizeof(qword)], rdx ret ENDFUNC mul_1x1 ;; ;; 2x2 multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_2x2,PRIVATE mov rdx, qword [rcx] MLA_FIX 2, rdi, rsi, rbx,rbp, r8,r9 mov rdx, qword [rcx+sizeof(qword)] MLA_FIX 2, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9 ret ENDFUNC mla_2x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_2x2,PRIVATE call mla_2x2 mov qword [rdi+sizeof(qword)*2], r8 mov qword [rdi+sizeof(qword)*3], r9 ret ENDFUNC mul_2x2 ;; ;; 3x3 multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_3x3,PRIVATE mov rdx, qword [rcx] MLA_FIX 3, rdi, rsi, rbx,rbp, r8,r9,r10 mov rdx, qword [rcx+sizeof(qword)] MLA_FIX 3, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10 mov rdx, qword [rcx+sizeof(qword)*2] MLA_FIX 3, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10 ret ENDFUNC mla_3x3 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_3x3,PRIVATE call mla_3x3 mov qword [rdi+sizeof(qword)*3], r8 mov qword [rdi+sizeof(qword)*4], r9 mov qword [rdi+sizeof(qword)*5], r10 ret ENDFUNC mul_3x3 ;; ;; 4x{2,4} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_4x4,PRIVATE mov rdx, qword [rcx] MLA_FIX 4, rdi, rsi, rbx,rbp, r8,r9,r10,r11 mov rdx, qword [rcx+sizeof(qword)] MLA_FIX 4, {rdi+sizeof(qword)}, rsi, rbx,rbp, r8,r9,r10,r11 mov rdx, qword [rcx+sizeof(qword)*2] MLA_FIX 4, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11 mov rdx, qword [rcx+sizeof(qword)*3] MLA_FIX 4, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11 ret ENDFUNC mla_4x4 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_4x4,PRIVATE call mla_4x4 mov qword [rdi+sizeof(qword)*4], r8 mov qword [rdi+sizeof(qword)*5], r9 mov qword [rdi+sizeof(qword)*6], r10 mov qword [rdi+sizeof(qword)*7], r11 ret ENDFUNC mul_4x4 ;; ;; 5x{2,5} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_5x5,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 5, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 5, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 5, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 5, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 5, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12 ret ENDFUNC mla_5x5 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_5x5,PRIVATE call mla_5x5 mov qword [rdi+sizeof(qword)*5], r8 mov qword [rdi+sizeof(qword)*6], r9 mov qword [rdi+sizeof(qword)*7], r10 mov qword [rdi+sizeof(qword)*8], r11 mov qword [rdi+sizeof(qword)*9], r12 ret ENDFUNC mul_5x5 ;; ;; 6x{2,6} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_6x6,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 6, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 6, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 6, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 6, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 6, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 mov rdx, [rcx+sizeof(qword)*5] MLA_FIX 6, {rdi+sizeof(qword)*5}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 ret ENDFUNC mla_6x6 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_6x6,PRIVATE call mla_6x6 mov qword [rdi+sizeof(qword)*6], r8 mov qword [rdi+sizeof(qword)*7], r9 mov qword [rdi+sizeof(qword)*8], r10 mov qword [rdi+sizeof(qword)*9], r11 mov qword [rdi+sizeof(qword)*10],r12 mov qword [rdi+sizeof(qword)*11],r13 ret ENDFUNC mul_6x6 ;; ;; 7x{2,7} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_7x7,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 7, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 7, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 7, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 7, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 7, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*5] MLA_FIX 7, {rdi+sizeof(qword)*5}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 mov rdx, [rcx+sizeof(qword)*6] MLA_FIX 7, {rdi+sizeof(qword)*6}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 ret ENDFUNC mla_7x7 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_7x7,PRIVATE call mla_7x7 mov qword [rdi+sizeof(qword)*7], r8 mov qword [rdi+sizeof(qword)*8], r9 mov qword [rdi+sizeof(qword)*9], r10 mov qword [rdi+sizeof(qword)*10],r11 mov qword [rdi+sizeof(qword)*11],r12 mov qword [rdi+sizeof(qword)*12],r13 mov qword [rdi+sizeof(qword)*13],r14 ret ENDFUNC mul_7x7 ;; ;; 8x{1,2,3,4,5,6,7,8} multiplication ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x1,PRIVATE mov rdx, [rcx] MLA_FIX 8, rdi, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x1 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x2,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x2 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x3,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 8, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x3 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x4,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 8, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 8, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x4 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x5,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 8, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 8, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 8, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x5 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x6,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 8, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 8, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 8, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*5] MLA_FIX 8, {rdi+sizeof(qword)*5}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x6 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x7,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 8, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 8, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 8, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*5] MLA_FIX 8, {rdi+sizeof(qword)*5}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*6] MLA_FIX 8, {rdi+sizeof(qword)*6}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x7 align IPP_ALIGN_FACTOR DECLARE_FUNC mla_8x8,PRIVATE mov rdx, [rcx+sizeof(qword)*0] MLA_FIX 8, {rdi+sizeof(qword)*0}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*1] MLA_FIX 8, {rdi+sizeof(qword)*1}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*2] MLA_FIX 8, {rdi+sizeof(qword)*2}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*3] MLA_FIX 8, {rdi+sizeof(qword)*3}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*4] MLA_FIX 8, {rdi+sizeof(qword)*4}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*5] MLA_FIX 8, {rdi+sizeof(qword)*5}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*6] MLA_FIX 8, {rdi+sizeof(qword)*6}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 mov rdx, [rcx+sizeof(qword)*7] MLA_FIX 8, {rdi+sizeof(qword)*7}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mla_8x8 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_8x8,PRIVATE call mla_8x8 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],r15 ret ENDFUNC mul_8x8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; middle size (9-16 qwords) operand mla and mul operations ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC mul_9x9,PRIVATE call mla_8x8 mov rdx, [rcx+sizeof(qword)*8] MLA_FIX 8, {rdi+sizeof(qword)*8}, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 push r15 mov rdx, [rsi+sizeof(qword)*8] mov r15, [rdi+sizeof(qword)*8] MLA_FIX 8, {rdi+sizeof(qword)*8}, rcx, rbx,rbp, r15,r8,r9,r10,r11,r12,r13,r14 mov qword [rdi+sizeof(qword)*9], r15 gsmulx r15, rbp, [rcx+sizeof(qword)*8] pop rax add r14, rax adc r15,0 add r14, rbp adc r15, 0 mov qword [rdi+sizeof(qword)*10],r8 mov qword [rdi+sizeof(qword)*11],r9 mov qword [rdi+sizeof(qword)*12],r10 mov qword [rdi+sizeof(qword)*13],r11 mov qword [rdi+sizeof(qword)*14],r12 mov qword [rdi+sizeof(qword)*15],r13 mov qword [rdi+sizeof(qword)*16],r14 mov qword [rdi+sizeof(qword)*17],r15 ret ENDFUNC mul_9x9 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_10x10,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x2 push r15 push r14 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r13 mov r14, r12 mov r13, r11 mov r12, r10 mov r11, r9 mov r10, r8 mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x2 mov qword [rdi+sizeof(qword)*2],r8 mov qword [rdi+sizeof(qword)*3],r9 mov qword [rdi+sizeof(qword)*4],r10 mov qword [rdi+sizeof(qword)*5],r11 mov qword [rdi+sizeof(qword)*6],r12 mov qword [rdi+sizeof(qword)*7],r13 add rdi, sizeof(qword)*8 xor r10, r10 pop r8 pop r9 add r8, r14 adc r9, r15 adc r10,0 ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_2x2 add rdi, sizeof(qword)*2 add r8, r10 adc r9, 0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 ret ENDFUNC mul_10x10 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_11x11,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x3 push r15 push r14 push r13 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r12 mov r14, r11 mov r13, r10 mov r12, r9 mov r11, r8 mov r10,qword [rdi+sizeof(qword)*2] mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x3 mov qword [rdi+sizeof(qword)*3],r8 mov qword [rdi+sizeof(qword)*4],r9 mov qword [rdi+sizeof(qword)*5],r10 mov qword [rdi+sizeof(qword)*6],r11 mov qword [rdi+sizeof(qword)*7],r12 add rdi, sizeof(qword)*8 xor r11, r11 pop r8 pop r9 pop r10 add r8, r13 adc r9, r14 adc r10,r15 adc r11,0 ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_3x3 add rdi, sizeof(qword)*3 add r8, r11 adc r9, 0 adc r10,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 ret ENDFUNC mul_11x11 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_12x12,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x4 push r15 push r14 push r13 push r12 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r11 mov r14, r10 mov r13, r9 mov r12, r8 mov r11,qword [rdi+sizeof(qword)*3] mov r10,qword [rdi+sizeof(qword)*2] mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x4 mov qword [rdi+sizeof(qword)*4],r8 mov qword [rdi+sizeof(qword)*5],r9 mov qword [rdi+sizeof(qword)*6],r10 mov qword [rdi+sizeof(qword)*7],r11 add rdi, sizeof(qword)*8 xor rax, rax pop r8 pop r9 pop r10 pop r11 add r8, r12 adc r9, r13 adc r10,r14 adc r11,r15 adc rax,0 push rax ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_4x4 add rdi, sizeof(qword)*4 pop rax add r8, rax adc r9, 0 adc r10,0 adc r11,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 ret ENDFUNC mul_12x12 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_13x13,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x5 push r15 push r14 push r13 push r12 push r11 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r15, r10 mov r14, r9 mov r13, r8 mov r12,qword [rdi+sizeof(qword)*4] mov r11,qword [rdi+sizeof(qword)*3] mov r10,qword [rdi+sizeof(qword)*2] mov r9, qword [rdi+sizeof(qword)*1] mov r8, qword [rdi+sizeof(qword)*0] call mla_8x5 mov qword [rdi+sizeof(qword)*5], r8 mov qword [rdi+sizeof(qword)*6], r9 mov qword [rdi+sizeof(qword)*7], r10 add rdi, sizeof(qword)*8 xor rax, rax pop r8 pop r9 pop r10 pop rbx pop rbp add r8, r11 adc r9, r12 adc r10,r13 adc rbx,r14 adc rbp,r15 adc rax,0 push rax mov r11, rbx mov r12, rbp ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 call mla_5x5 add rdi, sizeof(qword)*5 pop rax add r8, rax adc r9, 0 adc r10,0 adc r11,0 adc r12,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 ret ENDFUNC mul_13x13 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_14x14,PRIVATE call mla_7x7 add rdi, sizeof(qword)*7 add rsi, sizeof(qword)*7 call mla_7x7 mov qword [rdi+sizeof(qword)*7], r8 mov qword [rdi+sizeof(qword)*8], r9 mov qword [rdi+sizeof(qword)*9], r10 mov qword [rdi+sizeof(qword)*10],r11 mov qword [rdi+sizeof(qword)*11],r12 mov qword [rdi+sizeof(qword)*12],r13 mov qword [rdi+sizeof(qword)*13],r14 mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] add rcx, sizeof(qword)*7 sub rsi, sizeof(qword)*7 call mla_7x7 xor rdx, rdx op_reg_mem add, r8, qword [rdi+sizeof(qword)*7], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*8], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*9], rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*10],rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*11],rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*12],rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*13],rax adc rdx, 0 push rdx add rdi, sizeof(qword)*7 add rsi, sizeof(qword)*7 call mla_7x7 sub rdi, sizeof(qword)*14 sub rsi, sizeof(qword)*7 sub rcx, sizeof(qword)*7 pop rdx add r8, rdx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 mov qword [rdi+sizeof(qword)*21],r8 mov qword [rdi+sizeof(qword)*22],r9 mov qword [rdi+sizeof(qword)*23],r10 mov qword [rdi+sizeof(qword)*24],r11 mov qword [rdi+sizeof(qword)*25],r12 mov qword [rdi+sizeof(qword)*26],r13 mov qword [rdi+sizeof(qword)*27],r14 ret ENDFUNC mul_14x14 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_15x15,PRIVATE ; A0*B0 call mla_8x8 add rdi, sizeof(qword)*8 ; + A0*B1 add rcx, sizeof(qword)*8 call mla_8x7 mov qword [rdi+sizeof(qword)*7], r8 mov qword [rdi+sizeof(qword)*8], r9 mov qword [rdi+sizeof(qword)*9], r10 mov qword [rdi+sizeof(qword)*10],r11 mov qword [rdi+sizeof(qword)*11],r12 mov qword [rdi+sizeof(qword)*12],r13 mov qword [rdi+sizeof(qword)*13],r14 mov qword [rdi+sizeof(qword)*14],r15 ; + A1*B0 add rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 SWAP rcx, rsi mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mla_8x7 mov qword [rdi+sizeof(qword)*7], r8 add rdi, sizeof(qword)*8 ; + A1*B1 SWAP rcx, rsi add rcx, sizeof(qword)*8 mov r8, r9 mov r9, r10 mov r10,r11 mov r11,r12 mov r12,r13 mov r13,r14 mov r14,r15 xor rdx, rdx op_reg_mem add, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*6], rax adc rdx, 0 push rdx call mla_7x7 add rdi, sizeof(qword)*7 pop rax add r8, rax adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 adc r14,0 mov qword [rdi+sizeof(qword)*0],r8 mov qword [rdi+sizeof(qword)*1],r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 ret ENDFUNC mul_15x15 align IPP_ALIGN_FACTOR DECLARE_FUNC mul_16x16,PRIVATE call mla_8x8 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_8x8 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],r15 mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] add rcx, sizeof(qword)*8 sub rsi, sizeof(qword)*8 call mla_8x8 xor rdx, rdx op_reg_mem add, r8, qword [rdi+sizeof(qword)*8], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*9], rax op_reg_mem adc, r10,qword [rdi+sizeof(qword)*10],rax op_reg_mem adc, r11,qword [rdi+sizeof(qword)*11],rax op_reg_mem adc, r12,qword [rdi+sizeof(qword)*12],rax op_reg_mem adc, r13,qword [rdi+sizeof(qword)*13],rax op_reg_mem adc, r14,qword [rdi+sizeof(qword)*14],rax op_reg_mem adc, r15,qword [rdi+sizeof(qword)*15],rax adc rdx, 0 push rdx add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_8x8 sub rdi, sizeof(qword)*16 sub rsi, sizeof(qword)*8 sub rcx, sizeof(qword)*8 pop rdx add r8, rdx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 mov qword [rdi+sizeof(qword)*24],r8 mov qword [rdi+sizeof(qword)*25],r9 mov qword [rdi+sizeof(qword)*26],r10 mov qword [rdi+sizeof(qword)*27],r11 mov qword [rdi+sizeof(qword)*28],r12 mov qword [rdi+sizeof(qword)*29],r13 mov qword [rdi+sizeof(qword)*30],r14 mov qword [rdi+sizeof(qword)*31],r15 ret ENDFUNC mul_16x16 mul_lxl_basic DQ mul_1x1 - mul_lxl_basic DQ mul_2x2 - mul_lxl_basic DQ mul_3x3 - mul_lxl_basic DQ mul_4x4 - mul_lxl_basic DQ mul_5x5 - mul_lxl_basic DQ mul_6x6 - mul_lxl_basic DQ mul_7x7 - mul_lxl_basic DQ mul_8x8 - mul_lxl_basic DQ mul_9x9 - mul_lxl_basic DQ mul_10x10-mul_lxl_basic DQ mul_11x11-mul_lxl_basic DQ mul_12x12-mul_lxl_basic DQ mul_13x13-mul_lxl_basic DQ mul_14x14-mul_lxl_basic DQ mul_15x15-mul_lxl_basic DQ mul_16x16-mul_lxl_basic mla_lxl_short DQ mla_1x1 - mla_lxl_short DQ mla_2x2 - mla_lxl_short DQ mla_3x3 - mla_lxl_short DQ mla_4x4 - mla_lxl_short DQ mla_5x5 - mla_lxl_short DQ mla_6x6 - mla_lxl_short DQ mla_7x7 - mla_lxl_short mla_8xl_tail DQ mla_8x1 - mla_8xl_tail DQ mla_8x2 - mla_8xl_tail DQ mla_8x3 - mla_8xl_tail DQ mla_8x4 - mla_8xl_tail DQ mla_8x5 - mla_8xl_tail DQ mla_8x6 - mla_8xl_tail DQ mla_8x7 - mla_8xl_tail %endif ;; _PCPBNUMUL_BASIC_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulpp_fix.inc000066400000000000000000000247541470420105600273000ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number multiplication Support ; ; %ifndef _PCPBNUMUL_FIX_ADCX_INC_ %assign _PCPBNUMUL_FIX_ADCX_INC_ 1 %ifdef _ADCX_ADOX_ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; macro used to replace op reg, mem instructions %macro SWAP 2.nolist %xdefine %%r1 %1 %xdefine %%r2 %2 xor %%r1, %%r2 xor %%r2, %%r1 xor %%r1, %%r2 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; macro used extract proc ep from the table %macro GET_EP 3-4.nolist %xdefine %%regEp %1 %xdefine %%Table %2 %xdefine %%regIdx %3 %xdefine %%tmp %4 lea %%regEp, [rel %%Table] %ifnempty %%tmp mov %%tmp, [%%regEp+%%regIdx*sizeof(qword)-sizeof(qword)] add %%regEp, %%tmp %else mov %%regIdx, [%%regEp+%%regIdx*sizeof(qword)-sizeof(qword)] add %%regEp, %%regIdx %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; op DST, mem_src %macro op_reg_mem 4.nolist %xdefine %%opCode %1 %xdefine %%dst %2 %xdefine %%mem_src %3 %xdefine %%tmp %4 mov %%tmp, %%mem_src %%opCode %%dst, %%tmp %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEM_DST = (op src1, mem_src2) %macro op_mem_reg_mem 5.nolist %xdefine %%opCode %1 %xdefine %%mem_dst %2 %xdefine %%src1 %3 %xdefine %%mem_src2 %4 %xdefine %%tmp %5 op_reg_mem %%opCode, %%src1, %%mem_src2, %%tmp mov %%mem_dst, %%src1 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; MEM_DST = op mem_src1, mem_src2 %macro op_mem_mem 5.nolist %xdefine %%opCode %1 %xdefine %%mem_dst %2 %xdefine %%mem_src1 %3 %xdefine %%mem_src2 %4 %xdefine %%tmp %5 mov %%tmp, %%mem_src1 %%opCode %%tmp, %%mem_src2 mov %%mem_dst, %%tmp %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Inputs: pDst: Destination (up to 1024 bits, 16 qwords) ;;; pA: Multiplicand (up to 512 bits, 8 qwords) ;;; ;;; ;;; Uses registers: ;;; rdx - implicit multiplicand ;;; (HIP:LOP)- 64x64-bit product (mulx) ;;; X7,,X0 - high result ;;; %macro MUL_FIX 12-13.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%HIP %4 %xdefine %%LOP %5 %xdefine %%X0 %6 %xdefine %%X1 %7 %xdefine %%X2 %8 %xdefine %%X3 %9 %xdefine %%X4 %10 %xdefine %%X5 %11 %xdefine %%X6 %12 %xdefine %%X7 %13 gsmulx %%X0, %%LOP, [%%pA] ; (X0:LO) = a[0]*b %ifnempty %%pDst mov [%%pDst], %%LOP %endif %if %%N > 1 gsmulx %%X1, %%HIP, [%%pA+sizeof(qword)] ; (X1:LO) = a[1]*b add %%X0, %%HIP %if %%N == 2 adc %%X1, 0 %endif %endif %if %%N > 2 gsmulx %%X2, %%LOP, [%%pA+sizeof(qword)*2] ; (X2:LO) = a[2]*b adc %%X1, %%LOP %if %%N == 3 adc %%X2, 0 %endif %endif %if %%N > 3 gsmulx %%X3, %%HIP, [%%pA+sizeof(qword)*3] ; (X3:LO) = a[3]*b adc %%X2, %%HIP %if %%N == 4 adc %%X3, 0 %endif %endif %if %%N > 4 gsmulx %%X4, %%LOP, [%%pA+sizeof(qword)*4] ; (X4:LO) = a[4]*b adc %%X3, %%LOP %if %%N == 5 adc %%X4, 0 %endif %endif %if %%N > 5 gsmulx %%X5, %%HIP, [%%pA+sizeof(qword)*5] ; (X5:LO) = a[5]*b adc %%X4, %%HIP %if %%N == 6 adc %%X5, 0 %endif %endif %if %%N > 6 gsmulx %%X6, %%LOP, [%%pA+sizeof(qword)*6] ; (X6:LO) = a[6]*b adc %%X5, %%LOP %if %%N == 7 adc %%X6, 0 %endif %endif %if %%N > 7 gsmulx %%X7, %%HIP, [%%pA+sizeof(qword)*7] ; (X7:LO) = a[7]*b adc %%X6, %%HIP adc %%X7, 0 %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; {x7,x6,x5,x4,x3,x2,x1,x0},DCT[0] = {x7,x6,x5,x4,x3,x2,x1,x0} + A[7:0]*B[i] ;; ;; uses rax, rdx ;; rdx - implicit multiplicand B[i] (should to be preloaded) ;; rax - temporary product ;; (HIP:LOP)- 64x64-bit product (mulx) ;; X7,,X0 - high result ;; %macro MLA_FIX 6-13.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%HIP %4 %xdefine %%LOP %5 %xdefine %%X0 %6 %xdefine %%X1 %7 %xdefine %%X2 %8 %xdefine %%X3 %9 %xdefine %%X4 %10 %xdefine %%X5 %11 %xdefine %%X6 %12 %xdefine %%X7 %13 xor rax, rax gsmulx %%HIP, %%LOP, [%%pA] ; (HI:LO) = a[0]*b[i] gsadox %%X0, %%LOP %ifnempty %%pDst mov [%%pDst], %%X0 %endif %if %%N == 1 gsadox %%HIP, rax mov %%X0, %%HIP %else gsadcx %%X1, %%HIP gsmulx %%LOP,%%X0, [%%pA+sizeof(qword)] ; (LO:X0) = a[1]*b[i] gsadox %%X0, %%X1 %if %%N == 2 gsadcx %%LOP, rax gsadox %%LOP, rax mov %%X1, %%LOP %else gsadcx %%X2, %%LOP gsmulx %%HIP,%%X1, [%%pA+sizeof(qword)*2] ; (HI:X1) = a[2]*b[i] gsadox %%X1, %%X2 %if %%N == 3 gsadcx %%HIP, rax gsadox %%HIP, rax mov %%X2, %%HIP %else gsadcx %%X3, %%HIP gsmulx %%LOP,%%X2, [%%pA+sizeof(qword)*3] ; (LO,X2) = a[3]*b[i] gsadox %%X2, %%X3 %if %%N == 4 gsadcx %%LOP, rax gsadox %%LOP, rax mov %%X3, %%LOP %else gsadcx %%X4, %%LOP gsmulx %%HIP,%%X3, [%%pA+sizeof(qword)*4] ; (HI:X3) = a[4]*b[i] gsadox %%X3, %%X4 %if %%N == 5 gsadcx %%HIP, rax gsadox %%HIP, rax mov %%X4, %%HIP %else gsadcx %%X5, %%HIP gsmulx %%LOP,%%X4, [%%pA+sizeof(qword)*5] ; (LO:X4) = a[5]*b[i] gsadox %%X4, %%X5 %if %%N == 6 gsadcx %%LOP, rax gsadox %%LOP, rax mov %%X5, %%LOP %else gsadcx %%X6, %%LOP gsmulx %%HIP,%%X5, [%%pA+sizeof(qword)*6] ; (HI:X5) = a[6]*b[i] gsadox %%X5, %%X6 %if %%N == 7 gsadcx %%HIP, rax gsadox %%HIP, rax mov %%X6, %%HIP %else gsadcx %%HIP,%%X7 gsmulx %%X7, %%X6, [%%pA+sizeof(qword)*7] ; (LO:X6) = a[7]*b[i] gsadox %%X6, %%HIP gsadcx %%X7, rax gsadox %%X7, rax %endif %endif %endif %endif %endif %endif %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Inputs: pDst: Destination (up to 1024 bits, 16 qwords) ;;; pA: Multiplicand (up to 512 bits, 8 qwords) ;;; pB: Multiplicand (up to 512 bits, 8 qwords) ;;; ;;; ;;; Uses registers: ;;; rdx - implicit multiplicand ;;; (HIP:LOP)- 64x64-bit product (mulx) ;;; X0,,X7 - high result ;;; %macro MUL_NxN 7-14.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%pB %4 %xdefine %%HIP %5 %xdefine %%LOP %6 %xdefine %%X0 %7 %xdefine %%X1 %8 %xdefine %%X2 %9 %xdefine %%X3 %10 %xdefine %%X4 %11 %xdefine %%X5 %12 %xdefine %%X6 %13 %xdefine %%X7 %14 mov rdx, [%%pB] MUL_FIX {%%N},{%%pDst},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%N > 1 mov rdx, [%%pB+sizeof(qword)*1] MLA_FIX {%%N},{%%pDst+sizeof(qword)*1},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 2 mov rdx,[%%pB+sizeof(qword)*2] MLA_FIX {%%N},{%%pDst+sizeof(qword)*2},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 3 mov rdx,[%%pB+sizeof(qword)*3] MLA_FIX {%%N},{%%pDst+sizeof(qword)*3},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 4 mov rdx,[%%pB+sizeof(qword)*4] MLA_FIX {%%N},{%%pDst+sizeof(qword)*4},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 5 mov rdx,[%%pB+sizeof(qword)*5] MLA_FIX {%%N},{%%pDst+sizeof(qword)*5},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 6 mov rdx,[%%pB+sizeof(qword)*6] MLA_FIX {%%N},{%%pDst+sizeof(qword)*6},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 7 mov rdx,[%%pB+sizeof(qword)*7] MLA_FIX {%%N},{%%pDst+sizeof(qword)*7},{%%pA},{%%HIP},{%%LOP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%N > 7 mov qword [%%pDst+sizeof(qword)*8], %%X0 mov qword [%%pDst+sizeof(qword)*9], %%X1 mov qword [%%pDst+sizeof(qword)*10], %%X2 mov qword [%%pDst+sizeof(qword)*11], %%X3 mov qword [%%pDst+sizeof(qword)*12], %%X4 mov qword [%%pDst+sizeof(qword)*13], %%X5 mov qword [%%pDst+sizeof(qword)*14], %%X6 mov qword [%%pDst+sizeof(qword)*15], %%X7 %elif %%N > 6 mov qword [%%pDst+sizeof(qword)*7], %%X0 mov qword [%%pDst+sizeof(qword)*8], %%X1 mov qword [%%pDst+sizeof(qword)*9], %%X2 mov qword [%%pDst+sizeof(qword)*10], %%X3 mov qword [%%pDst+sizeof(qword)*11], %%X4 mov qword [%%pDst+sizeof(qword)*12], %%X5 mov qword [%%pDst+sizeof(qword)*13], %%X6 %elif %%N > 5 mov qword [%%pDst+sizeof(qword)*6], %%X0 mov qword [%%pDst+sizeof(qword)*7], %%X1 mov qword [%%pDst+sizeof(qword)*8], %%X2 mov qword [%%pDst+sizeof(qword)*9], %%X3 mov qword [%%pDst+sizeof(qword)*10], %%X4 mov qword [%%pDst+sizeof(qword)*11], %%X5 %elif %%N > 4 mov qword [%%pDst+sizeof(qword)*5], %%X0 mov qword [%%pDst+sizeof(qword)*6], %%X1 mov qword [%%pDst+sizeof(qword)*7], %%X2 mov qword [%%pDst+sizeof(qword)*8], %%X3 mov qword [%%pDst+sizeof(qword)*9], %%X4 %elif %%N > 3 mov qword [%%pDst+sizeof(qword)*4], %%X0 mov qword [%%pDst+sizeof(qword)*5], %%X1 mov qword [%%pDst+sizeof(qword)*6], %%X2 mov qword [%%pDst+sizeof(qword)*7], %%X3 %elif %%N > 2 mov qword [%%pDst+sizeof(qword)*3], %%X0 mov qword [%%pDst+sizeof(qword)*4], %%X1 mov qword [%%pDst+sizeof(qword)*5], %%X2 %elif %%N > 1 mov qword [%%pDst+sizeof(qword)*2], %%X0 mov qword [%%pDst+sizeof(qword)*3], %%X1 %else mov qword [%%pDst+sizeof(qword)*1], %%X0 %endif ;; N==2 %endmacro %endif ;; _ADCX_ADOX_ %endif ;; _PCPBNUMUL_FIX_ADCX_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulschool.inc000066400000000000000000001163441470420105600272770ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2010 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; BNU multiplication support ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; fixed multiplier macros ;; ;; ;; {x0,x7,x6,x5,x4,x3,x2,x1},DCT[0] = OP*SRC2[] + {x7,x6,x5,x4,x3,x2,x1,x0} ;; ;; uses rax, rdx ;; OP=SRC1[i] should to be preloaded ;; TMP is destroyed ;; %macro MLA_FIX 6-13.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%SRC2 %3 %xdefine %%OP %4 %xdefine %%TMP %5 %xdefine %%X7 %6 %xdefine %%X6 %7 %xdefine %%X5 %8 %xdefine %%X4 %9 %xdefine %%X3 %10 %xdefine %%X2 %11 %xdefine %%X1 %12 %xdefine %%X0 %13 mov rax, [%%SRC2+8*0] mul %%OP ; rdx:rax = OP * [] add %%X0, rax adc rdx, 0 mov %%pDst, %%X0 mov %%TMP, rdx %if %%N > 1 mov rax, [%%SRC2+8*1] mul %%OP ; rdx:rax = OP * [] add %%X1, rax adc rdx, 0 add %%X1, %%TMP adc rdx, 0 %if %%N == 2 mov %%X2, rdx %else mov %%TMP, rdx %endif %if %%N > 2 mov rax, [%%SRC2+8*2] mul %%OP ; rdx:rax = OP * [] add %%X2, rax adc rdx, 0 add %%X2, %%TMP adc rdx, 0 %if %%N == 3 mov %%X3, rdx %else mov %%TMP, rdx %endif %if %%N > 3 mov rax, [%%SRC2+8*3] mul %%OP ; rdx:rax = OP * [] add %%X3, rax adc rdx, 0 add %%X3, %%TMP adc rdx, 0 %if %%N == 4 mov %%X4, rdx %else mov %%TMP, rdx %endif %if %%N > 4 mov rax, [%%SRC2+8*4] mul %%OP ; rdx:rax = OP * [] add %%X4, rax adc rdx, 0 add %%X4, %%TMP adc rdx, 0 %if %%N == 5 mov %%X5, rdx %else mov %%TMP, rdx %endif %if %%N > 5 mov rax, [%%SRC2+8*5] mul %%OP ; rdx:rax = OP * [] add %%X5, rax adc rdx, 0 add %%X5, %%TMP adc rdx, 0 %if %%N == 6 mov %%X6, rdx %else mov %%TMP, rdx %endif %if %%N > 6 mov rax, [%%SRC2+8*6] mul %%OP ; rdx:rax = OP * [] add %%X6, rax adc rdx, 0 add %%X6, %%TMP adc rdx, 0 %if %%N == 7 mov %%X7, rdx %else mov %%TMP, rdx %endif %if %%N > 7 mov rax, [%%SRC2+8*7] mul %%OP ; rdx:rax = OP * [] add %%X7, rax adc rdx, 0 add %%X7, %%TMP adc rdx, 0 mov %%X0, rdx %endif %endif %endif %endif %endif %endif %endif %endmacro ;;; Inputs: pDst: Destination (1024 bits, 16 qwords) ;;; pA: Multiplicand (512 bits, 8 qwords) ;;; pB: Multiplicand (512 bits, 8 qwords) ;;; ;;; ;;; Uses registers rax, rdx, args and rbp, rbx ;;; B operand in [pB] and also in x7...x0 %macro MUL_NxN 7-14.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pA %3 %xdefine %%pB %4 %xdefine %%OP %5 %xdefine %%TMP %6 %xdefine %%X7 %7 %xdefine %%X6 %8 %xdefine %%X5 %9 %xdefine %%X4 %10 %xdefine %%X3 %11 %xdefine %%X2 %12 %xdefine %%X1 %13 %xdefine %%X0 %14 mov %%OP, [%%pA+8*0] mov rax, %%X0 mul %%OP ; rdx:rax = OP * [] mov [%%pDst+8*0], rax mov %%X0, rdx %if %%N > 1 mov rax, %%X1 mul %%OP ; rdx:rax = OP * [] add %%X0, rax adc rdx, 0 mov %%X1, rdx %endif %if %%N > 2 mov rax, %%X2 mul %%OP ; rdx:rax = OP * [] add %%X1, rax adc rdx, 0 mov %%X2, rdx %endif %if %%N > 3 mov rax, %%X3 mul %%OP ; rdx:rax = OP * [] add %%X2, rax adc rdx, 0 mov %%X3, rdx %endif %if %%N > 4 mov rax, %%X4 mul %%OP ; rdx:rax = OP * [] add %%X3, rax adc rdx, 0 mov %%X4, rdx %endif %if %%N > 5 mov rax, %%X5 mul %%OP ; rdx:rax = OP * [] add %%X4, rax adc rdx, 0 mov %%X5, rdx %endif %if %%N > 6 mov rax, %%X6 mul %%OP ; rdx:rax = OP * [] add %%X5, rax adc rdx, 0 mov %%X6, rdx %endif %if %%N > 7 mov rax, %%X7 mul %%OP ; rdx:rax = OP * [] add %%X6, rax adc rdx, 0 mov %%X7, rdx %endif %if %%N > 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; {X0,X7,X6,X5,X4,X3,X2,X1},pDst[1] = pA[1]*pB[] + {X7,X6,X5,X4,X3,X2,X1,X0} mov %%OP, [%%pA+sizeof(qword)*1] MLA_FIX {%%N},[%%pDst+sizeof(qword)*1],{%%pB},{%%OP},{%%TMP},{%%X7},{%%X6},{%%X5},{%%X4},{%%X3},{%%X2},{%%X1},{%%X0} %endif %if %%N > 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; {X1,X0,X7,X6,X5,X4,X3,X2},pDst[2] = pA[2]*pB[] + {X0,X7,X6,X5,X4,X3,X2,X1} mov %%OP, [%%pA+sizeof(qword)*2] MLA_FIX {%%N},[%%pDst+sizeof(qword)*2],{%%pB},{%%OP},{%%TMP},{%%X0},{%%X7},{%%X6},{%%X5},{%%X4},{%%X3},{%%X2},{%%X1} %endif %if %%N > 3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; {X2,X1,X0,X7,X6,X5,X4,X3},pDst[3] = pA[3]*pB[] + {X1,X0,X7,X6,X5,X4,X3,X2} mov %%OP, [%%pA+sizeof(qword)*3] MLA_FIX {%%N},[%%pDst+sizeof(qword)*3],{%%pB},{%%OP},{%%TMP},{%%X1},{%%X0},{%%X7},{%%X6},{%%X5},{%%X4},{%%X3},{%%X2} %endif %if %%N > 4 ; {X3,X2,X1,X0,X7,X6,X5,X4},pDst[4] = pA[4]*pB[] + {X2,X1,X0,X7,X6,X5,X4,X3} mov %%OP, [%%pA+sizeof(qword)*4] MLA_FIX {%%N},[%%pDst+sizeof(qword)*4],{%%pB},{%%OP},{%%TMP},{%%X2},{%%X1},{%%X0},{%%X7},{%%X6},{%%X5},{%%X4},{%%X3} %endif %if %%N > 5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; {X4,X3,X2,X1,X0,X7,X6,X5},pDst[5] = pA[5]*pB[] + {X3,X2,X1,X0,X7,X6,X5,X4} mov %%OP, [%%pA+sizeof(qword)*5] MLA_FIX {%%N},[%%pDst+sizeof(qword)*5],{%%pB},{%%OP},{%%TMP},{%%X3},{%%X2},{%%X1},{%%X0},{%%X7},{%%X6},{%%X5},{%%X4} %endif %if %%N > 6 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; {X5,X4,X3,X2,X1,X0,X7,X6},pDst[6] = pA[6]*pB[] + {X4,X3,X2,X1,X0,X7,X6,X5} mov %%OP, [%%pA+sizeof(qword)*6] MLA_FIX {%%N},[%%pDst+sizeof(qword)*6],{%%pB},{%%OP},{%%TMP},{%%X4},{%%X3},{%%X2},{%%X1},{%%X0},{%%X7},{%%X6},{%%X5} %endif %if %%N > 7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; {X6,X5,X4,X3,X2,X1,X0,X7},pDst[7] = pA[7]*pB[] + {X5,X4,X3,X2,X1,X0,X7,X6} mov %%OP, [%%pA+sizeof(qword)*7] MLA_FIX {%%N},[%%pDst+sizeof(qword)*7],{%%pB},{%%OP},{%%TMP},{%%X5},{%%X4},{%%X3},{%%X2},{%%X1},{%%X0},{%%X7},{%%X6} %endif %if %%N > 7 mov qword [%%pDst+sizeof(qword)*8], %%X7 mov qword [%%pDst+sizeof(qword)*9], %%X0 mov qword [%%pDst+sizeof(qword)*10], %%X1 mov qword [%%pDst+sizeof(qword)*11], %%X2 mov qword [%%pDst+sizeof(qword)*12], %%X3 mov qword [%%pDst+sizeof(qword)*13], %%X4 mov qword [%%pDst+sizeof(qword)*14], %%X5 mov qword [%%pDst+sizeof(qword)*15], %%X6 %elif %%N > 6 mov qword [%%pDst+sizeof(qword)*7], %%X6 mov qword [%%pDst+sizeof(qword)*8], %%X7 mov qword [%%pDst+sizeof(qword)*9], %%X0 mov qword [%%pDst+sizeof(qword)*10], %%X1 mov qword [%%pDst+sizeof(qword)*11], %%X2 mov qword [%%pDst+sizeof(qword)*12], %%X3 mov qword [%%pDst+sizeof(qword)*13], %%X4 %elif %%N > 5 mov qword [%%pDst+sizeof(qword)*6], %%X5 mov qword [%%pDst+sizeof(qword)*7], %%X6 mov qword [%%pDst+sizeof(qword)*8], %%X7 mov qword [%%pDst+sizeof(qword)*9], %%X0 mov qword [%%pDst+sizeof(qword)*10], %%X1 mov qword [%%pDst+sizeof(qword)*11], %%X2 %elif %%N > 4 mov qword [%%pDst+sizeof(qword)*5], %%X4 mov qword [%%pDst+sizeof(qword)*6], %%X5 mov qword [%%pDst+sizeof(qword)*7], %%X6 mov qword [%%pDst+sizeof(qword)*8], %%X7 mov qword [%%pDst+sizeof(qword)*9], %%X0 %elif %%N > 3 mov qword [%%pDst+sizeof(qword)*4], %%X3 mov qword [%%pDst+sizeof(qword)*5], %%X4 mov qword [%%pDst+sizeof(qword)*6], %%X5 mov qword [%%pDst+sizeof(qword)*7], %%X6 %elif %%N > 2 mov qword [%%pDst+sizeof(qword)*3], %%X2 mov qword [%%pDst+sizeof(qword)*4], %%X3 mov qword [%%pDst+sizeof(qword)*5], %%X4 %elif %%N > 1 mov qword [%%pDst+sizeof(qword)*2], %%X1 mov qword [%%pDst+sizeof(qword)*3], %%X2 %else mov qword [%%pDst+sizeof(qword)*1], %%X0 %endif ;; N==2 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MULx1 genaral-case multiplier macros ;; ;; dst = src * B (body) %macro MULx1 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%B %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 align 16 %%L_1: mul %%B xor %%T1, %%T1 add %%T0, rax mov qword [%%rDst+%%idx*sizeof(qword)], %%T0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] adc %%T1, rdx mul %%B xor %%T2, %%T2 add %%T1, rax mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T1 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] adc %%T2, rdx mul %%B xor %%T3, %%T3 add %%T2, rax mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T2 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] adc %%T3, rdx mul %%B xor %%T0, %%T0 add %%T3, rax mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3], %%T3 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] adc %%T0, rdx add %%idx, 4 jnc %%L_1 %endmacro ;; dst = src * B epilogue (srcLen=4*n+4) %macro MULx1_4N_4_ELOG 7.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B %3 %xdefine %%T0 %4 %xdefine %%T1 %5 %xdefine %%T2 %6 %xdefine %%T3 %7 mul %%B xor %%T1, %%T1 add %%T0, rax mov qword [%%rDst], %%T0 mov rax, qword [%%rSrc+sizeof(qword)] adc %%T1, rdx mul %%B xor %%T2, %%T2 add %%T1, rax mov qword [%%rDst+sizeof(qword)], %%T1 mov rax, qword [%%rSrc+sizeof(qword)*2] adc %%T2, rdx mul %%B xor %%T3, %%T3 add %%T2, rax mov qword [%%rDst+sizeof(qword)*2], %%T2 mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T3, rdx mul %%B mov idx, qword [rsp+counterA] add %%T3, rax mov qword [%%rDst+sizeof(qword)*3], %%T3 mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, 0 ;mov rbp, rax mov qword [%%rDst+sizeof(qword)*4], rdx add %%rDst, sizeof(qword) %endmacro ;; dst = src * B epilogue (srcLen=4*n+3) %macro MULx1_4N_3_ELOG 7.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B %3 %xdefine %%T0 %4 %xdefine %%T1 %5 %xdefine %%T2 %6 %xdefine %%T3 %7 mul %%B xor %%T1, %%T1 add %%T0, rax mov qword [%%rDst+sizeof(qword)], %%T0 mov rax, qword [%%rSrc+sizeof(qword)*2] adc %%T1, rdx mul %%B xor %%T2, %%T2 add %%T1, rax mov qword [%%rDst+sizeof(qword)*2], %%T1 mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T2, rdx mul %%B mov idx, qword [rsp+counterA] add %%T2, rax mov qword [%%rDst+sizeof(qword)*3], %%T2 mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, 0 ;mov rbp, rax mov qword [%%rDst+sizeof(qword)*4], rdx add %%rDst, sizeof(qword) %endmacro ;; dst = src * B epilogue (srcLen=4*n+2) %macro MULx1_4N_2_ELOG 7.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B %3 %xdefine %%T0 %4 %xdefine %%T1 %5 %xdefine %%T2 %6 %xdefine %%T3 %7 mul %%B xor %%T1, %%T1 add %%T0, rax mov qword [%%rDst+sizeof(qword)*2], %%T0 mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T1, rdx mul %%B mov idx, qword [rsp+counterA] add %%T1, rax mov qword [%%rDst+sizeof(qword)*3], %%T1 mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, 0 ;mov rbp, rax mov qword [%%rDst+sizeof(qword)*4], rdx add %%rDst, sizeof(qword) %endmacro ;; dst = src * B epilogue (srcLen=4*n+1) %macro MULx1_4N_1_ELOG 7.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B %3 %xdefine %%T0 %4 %xdefine %%T1 %5 %xdefine %%T2 %6 %xdefine %%T3 %7 mul %%B mov idx, qword [rsp+counterA] add %%T0, rax mov qword [%%rDst+sizeof(qword)*3], %%T0 mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, 0 ;mov rbp, rax mov qword [%%rDst+sizeof(qword)*4], rdx add %%rDst, sizeof(qword) %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MULx2 genaral-case multiplier macros ;; ; dst = src*{B1:B0} %macro MULx2 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 align IPP_ALIGN_FACTOR %%L_1: mul %%B1 ; {T2:T1} += a[i]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; a[i+1] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[i+1]*B0 mov qword [%%rDst+%%idx*sizeof(qword)], %%T0 add %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; a[i+1] adc %%T2, rdx adc %%T3, 0 mul %%B1 ; {T3:T2} += a[i+1]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] ; a[i+2] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[i+2]*B0 mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T1 add %%T2, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] ; a[i+2] adc %%T3, rdx adc %%T0, 0 mul %%B1 ; {T0:T3} += a[i+2]*B1 xor %%T1, %%T1 add %%T3, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] ; a[i+3] adc %%T0, rdx mul %%B0 ; {T1:T0:T3} += a[i+3]*B0 mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T2 add %%T3, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] ; a[i+3] adc %%T0, rdx adc %%T1, 0 mul %%B1 ; {T1:T0} += a[i+3]*B1 xor %%T2, %%T2 add %%T0, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] ; a[i+4] adc %%T1, rdx mul %%B0 ; {T2:T1:T0} += a[i+4]*B0 mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3], %%T3 add %%T0, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] ; a[i+4] adc %%T1, rdx adc %%T2, 0 add %%idx, 4 jnc %%L_1 %endmacro ;; dst = src * {B1:B0} epilogue (srcLen=4*n+1) %macro MULx2_4N_1_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-1]*B1 add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T0 add %%T1, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T2 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T1 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = src * {B1:B0} epilogue (srcLen=4*n+2) %macro MULx2_4N_2_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-2]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[LenA-1]*B0 mov qword [%%rDst+sizeof(qword)*2], %%T0 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T2, rdx adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-1]*B1 add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T1 add %%T2, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T3 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T2 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = src * {B1:B0} epilogue (srcLen=4*n+3) %macro MULx2_4N_3_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-3]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[LenA-2]*B0 mov qword [%%rDst+sizeof(qword)], %%T0 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-2]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[lenA-1]*B0 mov qword [%%rDst+sizeof(qword)*2], %%T1 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T3, rdx adc %%T0, 0 mul %%B1 ; {T0:T3} += a[lenA-1]*B1 add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T2 add %%T3, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T0 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T3 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = src * {B1:B0} epilogue (srcLen=4*n+4) %macro MULx2_4N_4_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-4]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[lenA-3]*B0 mov qword [%%rDst], %%T0 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-3]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[aLen-2]*B0 mov qword [%%rDst+sizeof(qword)], %%T1 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] adc %%T3, rdx adc %%T0, 0 mul %%B1 ; {T0:T3} += a[lenA-2]*B1 xor %%T1, %%T1 add %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T0, rdx mul %%B0 ; {T1:T0:T3} += a[lenA-1]*B0 mov qword [%%rDst+sizeof(qword)*2], %%T2 add %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T0, rdx adc %%T1, 0 mul %%B1 ; {T1:T0} += a[lenA-1]*B1 add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T3 add %%T0, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T1 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T0 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MLAx2 genaral-case multiplier macros ;; %macro MLAx2_PLOG 7.nolist %xdefine %%B0 %1 %xdefine %%B1 %2 %xdefine %%dataB %3 %xdefine %%T0 %4 %xdefine %%T1 %5 %xdefine %%T2 %6 %xdefine %%T3 %7 mov %%B0, qword [%%dataB] mul %%B0 ; {T2:T1:T0} = a[0]*b[i] mov %%B1, qword [%%dataB+sizeof(qword)] xor %%T2, %%T2 mov %%T0, rax mov rax, qword [rSrc+idx*sizeof(qword)] ; a[i] mov %%T1, rdx %endmacro %if (_IPP32E <= _IPP32E_Y8) ;; ;; Pre- Sandy Bridge specific code ;; %macro MLAx2 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 align IPP_ALIGN_FACTOR %%L_1: mul %%B1 ; {T2:T1} += a[i]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; a[i+1] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[i+1]*B0 + r[i] add %%T0, qword [%%rDst+%%idx*sizeof(qword)] adc %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; a[i+1] adc %%T2, rdx mov qword [%%rDst+%%idx*sizeof(qword)], %%T0 adc %%T3, 0 mul %%B1 ; {T3:T2} += a[i+1]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] ; a[i+2] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[i+2]*B0 + r[i+1] add %%T1, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)] adc %%T2, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] ; a[i+2] adc %%T3, rdx mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T1 adc %%T0, 0 mul %%B1 ; {T0:T3} += a[i+2]*B1 xor %%T1, %%T1 add %%T3, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] ; a[i+3] adc %%T0, rdx mul %%B0 ; {T1:T0:T3} += a[i+3]*B0 + r[i+2] add %%T2, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2] adc %%T3, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] ; a[i+3] adc %%T0, rdx mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T2 adc %%T1, 0 mul %%B1 ; {T1:T0} += a[i+3]*B1 xor %%T2, %%T2 add %%T0, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] ; a[i+4] adc %%T1, rdx mul %%B0 ; {T2:T1:T0} += a[i+4]*B0 + r[i+3] add %%T3, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3] adc %%T0, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] ; a[i+4] adc %%T1, rdx mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3], %%T3 adc %%T2, 0 add %%idx, 4 jnc %%L_1 %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+1) %macro MLAx2_4N_1_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T0, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T0 adc %%T1, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T2 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T1 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = dst + src * {B1:B0} epilogue (srcLen=4*n+2) %macro MLAx2_4N_2_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-2]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[lenA-1]*B0 + r[lenA-2] add %%T0, qword [%%rDst+sizeof(qword)*2] adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T2, rdx mov qword [%%rDst+sizeof(qword)*2], %%T0 adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T1, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T1 adc %%T2, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T3 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T2 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+3) %macro MLAx2_4N_3_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-3]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[LenA-2]*B0 + r[len-3] add %%T0, qword [%%rDst+sizeof(qword)] adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx mov qword [%%rDst+sizeof(qword)], %%T0 adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-2]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[lenA-1]*B0 + r[lenA-2] add %%T1, qword [%%rDst+sizeof(qword)*2] adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T3, rdx mov qword [%%rDst+sizeof(qword)*2], %%T1 adc %%T0, 0 mul %%B1 ; {T0:T3} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T2, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T2 adc %%T3, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T0 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T3 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+4) %macro MLAx2_4N_4_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-4]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[lenA-3]*B0 + r[lenA-4] add %%T0, qword [%%rDst] adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx mov qword [%%rDst], %%T0 adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-3]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[aLen-2]*B0 + r[lenA-3] add %%T1, qword [%%rDst+sizeof(qword)] adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] adc %%T3, rdx mov qword [%%rDst+sizeof(qword)], %%T1 adc %%T0, 0 mul %%B1 ; {T0:T3} += a[lenA-2]*B1 xor %%T1, %%T1 add %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T0, rdx mul %%B0 ; {T1:T0:T3} += a[lenA-1]*B0 + r[lenA-2] add %%T2, qword [%%rDst+sizeof(qword)*2] adc %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T0, rdx mov qword [%%rDst+sizeof(qword)*2], %%T2 adc %%T1, 0 mul %%B1 ; {T1:T0} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T3, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T3 adc %%T0, rax mov rax, qword [%%rSrc+idx*sizeof(qword)] adc rdx, %%T1 mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T0 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro %endif %if (_IPP32E >= _IPP32E_E9) ;; ;; Sandy Bridge specific code ;; %macro MLAx2 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 align IPP_ALIGN_FACTOR %%L_1: mul %%B1 ; {T2:T1} += a[i]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; a[i+1] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[i+1]*B0 + r[i] add %%T0, qword [%%rDst+%%idx*sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)], %%T0 adc %%T1, rax adc %%T2, rdx adc %%T3, 0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; a[i+1] mul %%B1 ; {T3:T2} += a[i+1]*B1 xor %%T0, %%T0 add %%T2, rax adc %%T3, rdx mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] ; a[i+2] mul %%B0 ; {T0:T3:T2} += a[i+2]*B0 + r[i+1] add %%T1, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T1 adc %%T2, rax adc %%T3, rdx adc %%T0, 0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] ; a[i+2] mul %%B1 ; {T0:T3} += a[i+2]*B1 xor %%T1, %%T1 add %%T3, rax adc %%T0, rdx mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] ; a[i+3] mul %%B0 ; {T1:T0:T3} += a[i+3]*B0 + r[i+2] add %%T2, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T2 adc %%T3, rax adc %%T0, rdx adc %%T1, 0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] ; a[i+3] mul %%B1 ; {T1:T0} += a[i+3]*B1 xor %%T2, %%T2 add %%T0, rax adc %%T1, rdx mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] ; a[i+4] mul %%B0 ; {T2:T1:T0} += a[i+4]*B0 + r[i+3] add %%T3, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3], %%T3 adc %%T0, rax adc %%T1, rdx adc %%T2, 0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] ; a[i+4] add %%idx, 4 jnc %%L_1 %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+1) %macro MLAx2_4N_1_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T0, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T0 adc %%T1, rax adc rdx, %%T2 mov rax, qword [%%rSrc+idx*sizeof(qword)] mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T1 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = dst + src * {B1:B0} epilogue (srcLen=4*n+2) %macro MLAx2_4N_2_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-2]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[lenA-1]*B0 + r[lenA-2] add %%T0, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T0 adc %%T1, rax adc %%T2, rdx adc %%T3, 0 mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B1 ; {T3:T2} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T1, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T1 adc %%T2, rax adc rdx, %%T3 mov rax, qword [%%rSrc+idx*sizeof(qword)] mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T2 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+3) %macro MLAx2_4N_3_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-3]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[LenA-2]*B0 + r[len-3] add %%T0, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T0 adc %%T1, rax adc %%T2, rdx adc %%T3, 0 mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] mul %%B1 ; {T3:T2} += a[lenA-2]*B1 xor %%T0, %%T0 add %%T2, rax adc %%T3, rdx mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B0 ; {T0:T3:T2} += a[lenA-1]*B0 + r[lenA-2] add %%T1, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T1 adc %%T2, rax adc %%T3, rdx adc %%T0, 0 mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B1 ; {T0:T3} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T2, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T2 adc %%T3, rax adc rdx, %%T0 mov rax, qword [%%rSrc+idx*sizeof(qword)] mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T3 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+4) %macro MLAx2_4N_4_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B1 ; {T2:T1} += a[lenA-4]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[lenA-3]*B0 + r[lenA-4] add %%T0, qword [%%rDst] mov qword [%%rDst], %%T0 adc %%T1, rax adc %%T2, rdx adc %%T3, 0 mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] mul %%B1 ; {T3:T2} += a[lenA-3]*B1 xor %%T0, %%T0 add %%T2, rax adc %%T3, rdx mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] mul %%B0 ; {T0:T3:T2} += a[aLen-2]*B0 + r[lenA-3] add %%T1, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T1 adc %%T2, rax adc %%T3, rdx adc %%T0, 0 mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] mul %%B1 ; {T0:T3} += a[lenA-2]*B1 xor %%T1, %%T1 add %%T3, rax adc %%T0, rdx mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B0 ; {T1:T0:T3} += a[lenA-1]*B0 + r[lenA-2] add %%T2, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T2 adc %%T3, rax adc %%T0, rdx adc %%T1, 0 mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B1 ; {T1:T0} += a[lenA-1]*B1 + r[lenA-1] add %%rDst, sizeof(qword)*2 mov idx, [rsp+counterA] add %%T3, qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*3-sizeof(qword)*2], %%T3 adc %%T0, rax adc rdx, %%T1 mov rax, qword [%%rSrc+idx*sizeof(qword)] mov qword [%%rDst+sizeof(qword)*4-sizeof(qword)*2], %%T0 mov qword [%%rDst+sizeof(qword)*5-sizeof(qword)*2], rdx %endmacro %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulschoolm7as.asm000066400000000000000000000226261470420105600300750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpMulAdc_BNU_school() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpbnumulschool.inc" %include "pcpvariant.inc" %if (_ADCOX_NI_ENABLING_ == _FEATURE_OFF_) || (_ADCOX_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_M7) && (_IPP32E < _IPP32E_L9) segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* Ipp64u cpMulAdc_BNU_school(Ipp64u* pR; ;* const Ipp64u* pA, int aSize, ;* const Ipp64u* pB, int bSize) ;* returns pR[aSize+bSize] ;* ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMulAdc_BNU_school,PUBLIC %assign LOCAL_FRAME (1*sizeof(qword)) USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ; rdi = pDst ; rsi = pSrcA ; edx = lenA ; rcx = pSrcB ; r8d = lenB ;; ;; stack structure: ;;counterB = (0) ;;counterA = (counterB+sizeof(qword)) %assign counterA (0) cmp edx, r8d jl .general_case_mul_entry jg .general_case_mul %if (_IPP32E < _IPP32E_E9) cmp edx, 4 %else cmp edx, 8 %endif jg .general_case_mul %if (_IPP32E >= _IPP32E_E9) cmp edx, 4 jg .more_then_4 %endif cmp edx, 3 ja .mul_4x4 jz .mul_3x3 jp .mul_2x2 ; mul_1x1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; fixed-size multipliers (1-4) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .mul_1x1: mov rax, qword [rsi] mul qword [rcx] mov qword [rdi], rax mov qword [rdi+sizeof(qword)], rdx mov rax, qword [rdi+sizeof(qword)*1] REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .mul_2x2: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] MUL_NxN 2, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*3] REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .mul_3x3: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] mov r10,[rcx+sizeof(qword)*2] MUL_NxN 3, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*5] REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .mul_4x4: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] mov r10,[rcx+sizeof(qword)*2] mov r11,[rcx+sizeof(qword)*3] MUL_NxN 4, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*7] REST_XMM REST_GPR ret %if (_IPP32E >= _IPP32E_E9) .more_then_4: cmp edx, 7 ja .mul_8x8 jz .mul_7x7 jp .mul_6x6 ; mul_5x5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; fixed-size multipliers (5-8) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .mul_5x5: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] mov r10,[rcx+sizeof(qword)*2] mov r11,[rcx+sizeof(qword)*3] mov r12,[rcx+sizeof(qword)*4] MUL_NxN 5, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*9] REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .mul_6x6: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] mov r10,[rcx+sizeof(qword)*2] mov r11,[rcx+sizeof(qword)*3] mov r12,[rcx+sizeof(qword)*4] mov r13,[rcx+sizeof(qword)*5] MUL_NxN 6, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*11] REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .mul_7x7: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] mov r10,[rcx+sizeof(qword)*2] mov r11,[rcx+sizeof(qword)*3] mov r12,[rcx+sizeof(qword)*4] mov r13,[rcx+sizeof(qword)*5] mov r14,[rcx+sizeof(qword)*6] MUL_NxN 7, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*13] REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .mul_8x8: mov r8, [rcx] mov r9, [rcx+sizeof(qword)*1] mov r10,[rcx+sizeof(qword)*2] mov r11,[rcx+sizeof(qword)*3] mov r12,[rcx+sizeof(qword)*4] mov r13,[rcx+sizeof(qword)*5] mov r14,[rcx+sizeof(qword)*6] mov r15,[rcx+sizeof(qword)*7] MUL_NxN 8, rdi, rsi, rcx, rbx, rbp, r15, r14, r13, r12, r11, r10, r9, r8 mov rax, qword [rdi+sizeof(qword)*15] REST_XMM REST_GPR ret %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; general case multiplier ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .general_case_mul_entry: ; swap operands %if lenA < lenB then exchange operands xor rsi, rcx xor edx, r8d xor rcx, rsi xor r8d, edx xor rsi, rcx xor edx, r8d %xdefine B0 r10 ; b[i], b[i+1] %xdefine B1 r11 %xdefine T0 r12 ; temporary %xdefine T1 r13 %xdefine T2 r14 %xdefine T3 r15 %xdefine idx rbx ; index %xdefine rDst rdi %xdefine rSrc rsi align IPP_ALIGN_FACTOR .general_case_mul: movsxd rdx, edx ; expand length movsxd r8, r8d lea rdi, [rdi+rdx*sizeof(qword)-sizeof(qword)*4] ; rdi = &R[lenA-4] lea rsi, [rsi+rdx*sizeof(qword)-sizeof(qword)*4] ; rsi = &A[lenA-4] mov idx, dword 4 ; negative sub idx, rdx ; A-counter mov qword [rsp+counterA], idx mov rax, qword [rsi+idx*sizeof(qword)] ; a[0] mov B0, qword [rcx] ; b[0] test r8, 1 jz .init_even_B ;********** lenSrcB = 2*n+ 1 (multiply only) ********************* .init_odd_B: xor T0, T0 cmp idx, 0 jge .skip_mul1 MULx1 rdi, rsi, idx, B0, T0, T1, T2, T3 .skip_mul1: cmp idx, 2 ja .fin_mul1x4n_1 ; idx=3 jz .fin_mul1x4n_2 ; idx=2 jp .fin_mul1x4n_3 ; idx=1 ; fin_mul1x4n_4 ; idx=0 .fin_mul1x4n_4: MULx1_4N_4_ELOG rdi, rsi, B0, T0,T1,T2,T3 add rcx, sizeof(qword) add r8, 1 jmp .mla2x4n_4 .fin_mul1x4n_3: MULx1_4N_3_ELOG rdi, rsi, B0, T0,T1,T2,T3 add rcx, sizeof(qword) add r8, 1 jmp .mla2x4n_3 .fin_mul1x4n_2: MULx1_4N_2_ELOG rdi, rsi, B0, T0,T1,T2,T3 add rcx, sizeof(qword) add r8, 1 jmp .mla2x4n_2 .fin_mul1x4n_1: MULx1_4N_1_ELOG rdi, rsi, B0, T0,T1,T2,T3 add rcx, sizeof(qword) add r8, 1 jmp .mla2x4n_1 ;********** lenSrcB = 2*n (multiply only) ************************ .init_even_B: mov rbp, rax mul B0 ; {T2:T1:T0} = a[0]*B0 mov B1, qword [rcx+sizeof(qword)] xor T2, T2 mov T0, rax mov rax, rbp ; restore a[0] mov T1, rdx cmp idx, 0 jge .skip_mul_nx2 MULx2 rdi, rsi, idx, B0,B1, T0,T1,T2,T3 .skip_mul_nx2: cmp idx, 2 ja .fin_mul2x4n_1 ; idx=3 jz .fin_mul2x4n_2 ; idx=2 jp .fin_mul2x4n_3 ; idx=1 ; fin_mul2x4n_4 ; idx=0 .fin_mul2x4n_4: MULx2_4N_4_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 align IPP_ALIGN_FACTOR .mla2x4n_4: sub r8, 2 jz .quit MLAx2_PLOG B0,B1, rcx, T0,T1,T2,T3 cmp idx, 0 jz .skip_mla_x2 MLAx2 rdi, rsi, idx, B0,B1, T0,T1,T2,T3 .skip_mla_x2: MLAx2_4N_4_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 jmp .mla2x4n_4 .fin_mul2x4n_3: MULx2_4N_3_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 align IPP_ALIGN_FACTOR .mla2x4n_3: sub r8, 2 jz .quit MLAx2_PLOG B0,B1, rcx, T0,T1,T2,T3 MLAx2 rdi, rsi, idx, B0,B1, T0,T1,T2,T3 MLAx2_4N_3_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 jmp .mla2x4n_3 .fin_mul2x4n_2: MULx2_4N_2_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 align IPP_ALIGN_FACTOR .mla2x4n_2: sub r8, 2 jz .quit MLAx2_PLOG B0,B1, rcx, T0,T1,T2,T3 MLAx2 rdi, rsi, idx, B0,B1, T0,T1,T2,T3 MLAx2_4N_2_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 jmp .mla2x4n_2 .fin_mul2x4n_1: MULx2_4N_1_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 align IPP_ALIGN_FACTOR .mla2x4n_1: sub r8, 2 jz .quit MLAx2_PLOG B0,B1, rcx, T0,T1,T2,T3 MLAx2 rdi, rsi, idx, B0,B1, T0,T1,T2,T3 MLAx2_4N_1_ELOG rdi, rsi, B0,B1, T0,T1,T2,T3 add rcx, sizeof(qword)*2 jmp .mla2x4n_1 .quit: mov rax, rdx REST_XMM REST_GPR ret ENDFUNC cpMulAdc_BNU_school %endif %endif ;; _ADCOX_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulschoolsrvl9.asm000066400000000000000000000165411470420105600303040ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Multiplicative Operations ; ; Content: ; cpMulAdc_BNU_school() ; cpSqrAdc_BNU_school() ; cpMontRedAdc_BNU() ; ; Implementation is using mulx and adcx/adox instruvtions ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ADCOX_NI_ENABLING_ == _FEATURE_ON_) || (_ADCOX_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_L9) %assign _xEMULATION_ 1 segment .text align=IPP_ALIGN_FACTOR %include "pcpbnumul.inc" %include "pcpbnusqr.inc" %include "pcpmred.inc" ;************************************************************* ;* Ipp64u cpMulAdc_BNU_school(Ipp64u* pR; ;* const Ipp64u* pA, int aSize, ;* const Ipp64u* pB, int bSize) ;* ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMulAdc_BNU_school,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ; rdi = pR ; rsi = pA ; edx = nsA ; rcx = pB ; r8d = nsB movsxd rdx, edx ; expand length movsxd rbx, r8d xor r8, r8 ; clear scratch xor r9, r9 xor r10, r10 xor r11, r11 xor r12, r12 xor r13, r13 xor r14, r14 xor r15, r15 cmp rdx, rbx jl .swap_operans ; nsA < nsB jg .test_8N_case ; test %if nsA=8*N and nsB=8*M cmp rdx, 16 jg .test_8N_case ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short nsA==nsB (1,..,16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp rdx, 4 jg .more_then_4 cmp edx, 3 ja .mul_4_4 jz .mul_3_3 jp .mul_2_2 ; mul_1_1 .mul_1_1: MUL_NxN 1, rdi, rsi, rcx, rbx,rbp, r8 jmp .quit .mul_2_2: MUL_NxN 2, rdi, rsi, rcx, rbx,rbp, r8,r9 jmp .quit .mul_3_3: MUL_NxN 3, rdi, rsi, rcx, rbx,rbp, r8,r9,r10 jmp .quit .mul_4_4: MUL_NxN 4, rdi, rsi, rcx, rbx,rbp, r8,r9,r10,r11 jmp .quit .more_then_4: GET_EP rax, mul_lxl_basic, rdx, rbp call rax jmp .quit .swap_operans: SWAP rsi, rcx ; swap operands SWAP rdx, rbx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8*N x 8*M case multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .test_8N_case: mov rax, rdx or rax, rbx and rax, 7 jnz .general_mul CALL_FUNC mul_8Nx8M jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .general_mul: CALL_FUNC mul_NxM jmp .quit .quit: REST_XMM REST_GPR ret ENDFUNC cpMulAdc_BNU_school ;************************************************************* ;* ;* Ipp64u cpSqrAdc_BNU_school(Ipp64u* pR; ;* const Ipp64u* pA, int aSize) ;* ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpSqrAdc_BNU_school,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 movsxd rdx, edx ; expand length xor r8, r8 ; clear scratch xor r9, r9 xor r10, r10 xor r11, r11 xor r12, r12 xor r13, r13 xor r14, r14 xor r15, r15 cmp rdx, 16 jg .test_8N_case ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short nsA (1,..,16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GET_EP rax, sqr_l_basic, rdx, rbp call rax jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8N case squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .test_8N_case: test rdx, 7 jnz .general_sqr CALL_FUNC sqr_8N jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .general_sqr: CALL_FUNC sqr_N .quit: REST_XMM REST_GPR ret ENDFUNC cpSqrAdc_BNU_school ;************************************************************* ;* ;* Ipp64u cpMontRedAdc_BNU(Ipp64u* pR; ;* Ipp64u* pProduct, ;* const Ipp64u* pModulus, int mSize, ;* Ipp64u m) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontRedAdc_BNU,PUBLIC %assign LOCAL_FRAME (0) USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ;pR (rdi) address of the reduction ;pProduct (rsi) address of the temporary product ;pModulus (rdx) address of the modulus ;mSize (rcx) size of the modulus ;m0 (r8) montgomery helper (m') mov r15, rdi ; store reduction address ; reload parameters for future convenience: mov rdi, rsi ; rdi = temporary product buffer mov rsi, rdx ; rsi = modulus movsxd rdx, ecx ; rdx = length of modulus cmp rdx, 16 ja .test_8N_case ; length of modulus >16 cmp rdx, 4 ja .above4 ; length of modulus 4,..,16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short modulus (1,..,4) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp rdx, 3 ja .red_4 jz .red_3 jp .red_2 ; red_1 .red_1: mov r9, qword [rdi+sizeof(qword)*0] MRED_FIX 1, r15, rdi, rsi, r8, rbp,rbx, r9 jmp .quit .red_2: mov r9, qword [rdi+sizeof(qword)*0] mov r10, qword [rdi+sizeof(qword)*1] MRED_FIX 2, r15, rdi, rsi, r8, rbp,rbx, r9,r10 jmp .quit .red_3: mov r9, qword [rdi+sizeof(qword)*0] mov r10, qword [rdi+sizeof(qword)*1] mov r11, qword [rdi+sizeof(qword)*2] MRED_FIX 3, r15, rdi, rsi, r8, rbp,rbx, r9,r10,r11 jmp .quit .red_4: mov r9, qword [rdi+sizeof(qword)*0] mov r10, qword [rdi+sizeof(qword)*1] mov r11, qword [rdi+sizeof(qword)*2] mov r12, qword [rdi+sizeof(qword)*3] MRED_FIX 4, r15, rdi, rsi, r8, rbp,rbx, r9,r10,r11,r12 jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short modulus (5,..,16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .above4: mov rbp, rdx sub rbp, 4 GET_EP rax, mred_short, rbp ; mred procedure call rax jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8N case squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .test_8N_case: test rdx, 7 jnz .general_case CALL_FUNC mred_8N jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; general case modulus ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .general_case: CALL_FUNC mred_N .quit: REST_XMM REST_GPR ret ENDFUNC cpMontRedAdc_BNU %endif %endif ;; _ADCOX_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnumulschoolsrvl9pp.asm000066400000000000000000000166431470420105600306470ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Multiplicative Operations ; ; Content: ; cpMulAdx_BNU_school() ; cpSqrAdx_BNU_school() ; cpMontRedAdx_BNU() ; ; Implementation is using mulx and adcx/adox instruvtions ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ADCOX_NI_ENABLING_ == _FEATURE_ON_) || (_ADCOX_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_L9) %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .text align=IPP_ALIGN_FACTOR %include "pcpbnumulpp.inc" %include "pcpbnusqrpp.inc" %include "pcpmredpp.inc" ;************************************************************* ;* Ipp64u cpMulAdx_BNU_school(Ipp64u* pR; ;* const Ipp64u* pA, int aSize, ;* const Ipp64u* pB, int bSize) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMulAdx_BNU_school,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ; rdi = pR ; rsi = pA ; edx = nsA ; rcx = pB ; r8d = nsB movsxd rdx, edx ; expand length movsxd rbx, r8d xor r8, r8 ; clear scratch xor r9, r9 xor r10, r10 xor r11, r11 xor r12, r12 xor r13, r13 xor r14, r14 xor r15, r15 cmp rdx, rbx jl .swap_operans ; nsA < nsB jg .test_8N_case ; test %if nsA=8*N and nsB=8*M cmp rdx, 16 jg .test_8N_case ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short nsA==nsB (1,..,16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp rdx, 4 jg .more_then_4 cmp edx, 3 ja .mul_4_4 jz .mul_3_3 jp .mul_2_2 ; mul_1_1 .mul_1_1: MUL_NxN 1, rdi, rsi, rcx, rbx, rbp, r8 jmp .quit .mul_2_2: MUL_NxN 2, rdi, rsi, rcx, rbx, rbp, r8, r9 jmp .quit .mul_3_3: MUL_NxN 3, rdi, rsi, rcx, rbx, rbp, r8, r9, r10 jmp .quit .mul_4_4: MUL_NxN 4, rdi, rsi, rcx, rbx, rbp, r8, r9, r10, r11 jmp .quit .more_then_4: GET_EP rax, mul_lxl_basic, rdx, rbp call rax jmp .quit .swap_operans: SWAP rsi, rcx ; swap operands SWAP rdx, rbx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8*N x 8*M case multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .test_8N_case: mov rax, rdx or rax, rbx and rax, 7 jnz .general_mul CALL_FUNC mul_8Nx8M_adcox jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case multiplier ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .general_mul: CALL_FUNC mul_NxM_adcox jmp .quit .quit: REST_XMM REST_GPR ret ENDFUNC cpMulAdx_BNU_school ;************************************************************* ;* ;* Ipp64u cpSqrAdx_BNU_school(Ipp64u* pR; ;* const Ipp64u* pA, int aSize) ;* ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpSqrAdx_BNU_school,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 movsxd rdx, edx ; expand length xor r8, r8 ; clear scratch xor r9, r9 xor r10, r10 xor r11, r11 xor r12, r12 xor r13, r13 xor r14, r14 xor r15, r15 cmp rdx, 16 jg .test_8N_case ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short nsA (1,..,16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GET_EP rax, sqr_l_basic, rdx, rbp call rax jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8N case squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .test_8N_case: test rdx, 7 jnz .general_sqr CALL_FUNC sqr_8N_adcox jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .general_sqr: CALL_FUNC sqr_N_adcox .quit: REST_XMM REST_GPR ret ENDFUNC cpSqrAdx_BNU_school ;************************************************************* ;* ;* Ipp64u cpMontRedAdx_BNU(Ipp64u* pR; ;* Ipp64u* pProduct, ;* const Ipp64u* pModulus, int mSize, ;* Ipp64u m) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontRedAdx_BNU,PUBLIC %assign LOCAL_FRAME (0) USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ;pR (rdi) address of the reduction ;pProduct (rsi) address of the temporary product ;pModulus (rdx) address of the modulus ;mSize (rcx) size of the modulus ;m0 (r8) montgomery helper (m') mov r15, rdi ; store reduction address ; reload parameters for future convenience: mov rdi, rsi ; rdi = temporary product buffer mov rsi, rdx ; rsi = modulus movsxd rdx, ecx ; rdx = length of modulus cmp rdx, 16 ja .test_8N_case ; length of modulus >16 cmp rdx, 4 ja .above4 ; length of modulus 4,..,16 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short modulus (1,..,4) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp rdx, 3 ja .red_4 jz .red_3 jp .red_2 ; red_1 .red_1: mov r9, qword [rdi+sizeof(qword)*0] MRED_FIX 1, r15, rdi, rsi, r8, rbp,rbx, r9 jmp .quit .red_2: mov r9, qword [rdi+sizeof(qword)*0] mov r10, qword [rdi+sizeof(qword)*1] MRED_FIX 2, r15, rdi, rsi, r8, rbp,rbx, r9,r10 jmp .quit .red_3: mov r9, qword [rdi+sizeof(qword)*0] mov r10, qword [rdi+sizeof(qword)*1] mov r11, qword [rdi+sizeof(qword)*2] MRED_FIX 3, r15, rdi, rsi, r8, rbp,rbx, r9,r10,r11 jmp .quit .red_4: mov r9, qword [rdi+sizeof(qword)*0] mov r10, qword [rdi+sizeof(qword)*1] mov r11, qword [rdi+sizeof(qword)*2] mov r12, qword [rdi+sizeof(qword)*3] MRED_FIX 4, r15, rdi, rsi, r8, rbp,rbx, r9,r10,r11,r12 jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; short modulus (5,..,16) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .above4: mov rbp, rdx sub rbp, 4 GET_EP rax, mred_short, rbp ; mred procedure call rax jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 8N case squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .test_8N_case: test rdx, 7 jnz .general_case CALL_FUNC mred_8N_adcox jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; general case modulus ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .general_case: CALL_FUNC mred_N_adcox .quit: REST_XMM REST_GPR ret ENDFUNC cpMontRedAdx_BNU %endif %endif ;; _ADCOX_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusqr.inc000066400000000000000000000301671470420105600260750ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number squaring Support ; ; %ifndef _PCPBNUSQR_INC_ %assign _PCPBNUSQR_INC_ 1 %include "pcpmulx.inc" %include "pcpbnusqr_basic.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; (8*n) squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_8N,PRIVATE push rdi ; save diagonal loop parameters push rsi push rdx push rdi ; save initial triangle product parameters push rsi push rdx ; ; init upper triangle product ; push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 add rdi, sizeof(qword)*8 sub rdx, 8 mov rcx, rsi add rsi, sizeof(qword)*8 .initLoop: push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnz .initLoop mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .update_Triangle ; ; update upper triangle product ; .outerLoop: push rdi ; update triangle product parameters push rsi push rdx xor rax, rax ; c-flag push rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10, qword [rdi+sizeof(qword)*2] mov r11, qword [rdi+sizeof(qword)*3] mov r12, qword [rdi+sizeof(qword)*4] mov r13, qword [rdi+sizeof(qword)*5] mov r14, qword [rdi+sizeof(qword)*6] mov r15, qword [rdi+sizeof(qword)*7] .innerLoop_entry: push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 add rdi, sizeof(qword)*8 sub rdx, 8 jz .skipInnerLoop mov rcx, rsi add rsi, sizeof(qword)*8 .innerLoop: pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10, qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11, qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12, qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13, qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14, qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15, qword [rdi+sizeof(qword)*7], rax sbb rax, rax ; save c-flag push rax push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnz .innerLoop .skipInnerLoop: pop rax ; restore c-flag neg rax adc r8, 0 mov qword [rdi+sizeof(qword)*0], r8 adc r9, 0 mov qword [rdi+sizeof(qword)*1], r9 adc r10,0 mov qword [rdi+sizeof(qword)*2],r10 adc r11,0 mov qword [rdi+sizeof(qword)*3],r11 adc r12,0 mov qword [rdi+sizeof(qword)*4],r12 adc r13,0 mov qword [rdi+sizeof(qword)*5],r13 adc r14,0 mov qword [rdi+sizeof(qword)*6],r14 adc r15,0 mov qword [rdi+sizeof(qword)*7],r15 .update_Triangle: pop rdx pop rsi pop rdi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*(8*2) sub rdx, 8 jnz .outerLoop ; ; add diagonal terms ; pop rcx pop rsi pop rdi xor rbx, rbx .update_loop: call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 sub rcx, 4 jnz .update_loop ret ENDFUNC sqr_8N ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case N>16 squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_N,PRIVATE push rdi ; save diagonal loop parameters push rsi push rdx push rdi ; save initial triangle product parameters push rsi push rdx mov rbp, rdx and rbp, 7 GET_EP rax, mla_8xl_tail, rbp ; get tail procedure push rax ; ; init upper triangle product ; sub rdx, 8 push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 add rdi, sizeof(qword)*8 xor r15, r15 mov rcx, rsi add rsi, sizeof(qword)*8 sub rdx, 8 .initLoop: push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnc .initLoop add rdx, 8 ; ; tail ; SWAP rsi, rcx mov rax, [rsp] ; procedure push rdx call rax pop rdx lea rdi, [rdi+rdx*sizeof(qword)] mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .update_Triangle ; ; update upper triangle product ; .outerLoop: push rdi ; update triangle product parameters push rsi push rdx push rax ; tail procedure xor rax, rax ; c-flag push rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10, qword [rdi+sizeof(qword)*2] mov r11, qword [rdi+sizeof(qword)*3] mov r12, qword [rdi+sizeof(qword)*4] mov r13, qword [rdi+sizeof(qword)*5] mov r14, qword [rdi+sizeof(qword)*6] mov r15, qword [rdi+sizeof(qword)*7] sub rdx, 8 push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 add rdi, sizeof(qword)*8 xor r15, r15 mov rcx, rsi add rsi, sizeof(qword)*8 sub rdx, 8 .innerLoop: pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10, qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11, qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12, qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13, qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14, qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15, qword [rdi+sizeof(qword)*7], rax sbb rax, rax ; save c-flag push rax push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnc .innerLoop add rdx, 8 ; ; tail ; ; clear in advance pxor xmm0, xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)], xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)+sizeof(qword)*2], xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)+sizeof(qword)*4], xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)+sizeof(qword)*6], xmm0 ; updates registers before mla operation pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10, qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11, qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12, qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13, qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14, qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15, qword [rdi+sizeof(qword)*7], rax ; store carry for future sbb rax, rax neg rax mov qword [rdi+sizeof(qword)*8], rax ; mla_8xn operation SWAP rsi, rcx mov rax, [rsp] ; procedure push rdx call rax pop rdx lea rdi, [rdi+rdx*sizeof(qword)] ; updates registers before store xor rax, rax mov rax, qword [rdi+sizeof(qword)*0] add r8, rax mov qword [rdi+sizeof(qword)*0], r8 mov rax, qword [rdi+sizeof(qword)*1] adc r9, rax mov qword [rdi+sizeof(qword)*1], r9 mov rax, qword [rdi+sizeof(qword)*2] adc r10, rax mov qword [rdi+sizeof(qword)*2], r10 mov rax, qword [rdi+sizeof(qword)*3] adc r11, rax mov qword [rdi+sizeof(qword)*3], r11 mov rax, qword [rdi+sizeof(qword)*4] adc r12, rax mov qword [rdi+sizeof(qword)*4], r12 mov rax, qword [rdi+sizeof(qword)*5] adc r13, rax mov qword [rdi+sizeof(qword)*5], r13 mov rax, qword [rdi+sizeof(qword)*6] adc r14, rax mov qword [rdi+sizeof(qword)*6], r14 mov rax, qword [rdi+sizeof(qword)*7] adc r15, rax mov qword [rdi+sizeof(qword)*7], r15 .update_Triangle: pop rax ; tail procedure pop rdx pop rsi pop rdi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*(8*2) sub rdx, 8 cmp rdx, 16 jg .outerLoop ; ; tail ; mov rbp, rdx sub rbp, 8 GET_EP rax, sqrN_triangle, rbp ; get triangle proc sub rsp, sizeof(qword)*32 push rdi push rdx mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] lea rdi, [rsp+sizeof(qword)*2] call rax mov rsi, rdi pop rdx pop rdi ; copy 8 terms movdqu xmm0, xmmword [rsi] movdqu xmm1, xmmword [rsi+sizeof(qword)*2] movdqu xmm2, xmmword [rsi+sizeof(qword)*4] movdqu xmm3, xmmword [rsi+sizeof(qword)*6] add rsi, sizeof(qword)*8 movdqu xmmword [rdi], xmm0 movdqu xmmword [rdi+sizeof(qword)*2], xmm1 movdqu xmmword [rdi+sizeof(qword)*4], xmm2 movdqu xmmword [rdi+sizeof(qword)*6], xmm3 add rdi, sizeof(qword)*8 ; update rdx-8 terms lea rax, [rdx-8] xor rbx, rbx .update1: mov r8, qword [rsi] mov r9, qword [rdi] add rsi, sizeof(qword) neg rbx adc r8, r9 sbb rbx, rbx mov qword [rdi], r8 add rdi, sizeof(qword) sub rax, 1 jg .update1 ; update rdx terms .update2: mov r8, qword [rsi] add rsi, sizeof(qword) neg rbx adc r8, 0 sbb rbx, rbx mov qword [rdi], r8 add rdi, sizeof(qword) sub rdx, 1 jg .update2 add rsp, sizeof(qword)*32 ; ; add diagonal terms ; .add_diagonals: pop rcx pop rsi pop rdi sub rcx, 4 xor rbx, rbx .add_diagonal_loop: call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 sub rcx, 4 jnc .add_diagonal_loop add rcx, 4 jz .quit .add_diagonal_rest: ADD_DIAG 1, rdi, rsi add rdi, sizeof(qword)*2 add rsi, sizeof(qword) sub rcx, 1 jnz .add_diagonal_rest .quit: ret ENDFUNC sqr_N %endif ;; _PCPBNUSQR_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusqr_basic.inc000066400000000000000000001575741470420105600272520ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number squaring Support ; ; %ifndef _PCPBNSQR_BASIC_ADCX_INC_ %assign _PCPBNSQR_BASIC_ADCX_INC_ 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Fixed-size (1-8 qwords) square operations ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; acc:a1 = src * mem + a1 %macro MULADD1x 4.nolist %xdefine %%acc %1 %xdefine %%a1 %2 %xdefine %%src %3 %xdefine %%mem %4 %ifnidni %%src,rdx mov rdx, %%src %endif gsmulx %%acc, rax, %%mem add %%a1, rax adc %%acc, 0 %endmacro ; acc:a1 = src * mem + a1 + acc %macro MULADDx 5.nolist %xdefine %%acc %1 %xdefine %%a1 %2 %xdefine %%src %3 %xdefine %%mem %4 %xdefine %%H %5 %ifnidni %%src,rdx mov rdx, %%src %endif gsmulx %%H,rax, %%mem add %%a1, rax adc %%H, 0 add %%a1, %%acc adc %%H, 0 mov %%acc, %%H %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; assignment ;; %xdefine pDst rdi %xdefine pSrc rsi %xdefine pA rsi %xdefine A rcx %xdefine x0 r8 %xdefine x1 r9 %xdefine x2 r10 %xdefine x3 r11 %xdefine x4 r12 %xdefine x5 r13 %xdefine x6 r14 %xdefine x7 r15 %xdefine x8 rbx %xdefine t0 rbp ;; ;; 1*qword squarer ;; %macro SQR_64 2.nolist %xdefine %%pDst %1 %xdefine %%pA %2 mov rdx, qword [%%pA] gsmulx rdx, rax, rdx mov qword [%%pDst], rax mov qword [%%pDst+sizeof(qword)], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_1,PRIVATE SQR_64 pDst, pA ret ENDFUNC sqr_1 ;; ;; 2*qword squarer ;; %macro SQR_128 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, qword [%%pA] gsmulx %%x1,%%x0,qword [rsi+sizeof(qword)*1] ; a[0]*a[1] gsmulx %%x3,%%x2,rdx ; a[0]^2 mov rdx, qword [%%pA+sizeof(qword)] ; a[1] gsmulx rdx,rax,rdx ; a[1]^2 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%A, 0 mov qword [%%pDst+sizeof(qword)*0], %%x2 add %%x3, %%x0 mov qword [%%pDst+sizeof(qword)*1], %%x3 adc rax, %%x1 mov qword [%%pDst+sizeof(qword)*2], rax adc rdx, %%A mov qword [%%pDst+sizeof(qword)*3], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_2,PRIVATE SQR_128 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_2 ;; ;; 3*qword squarer ;; %macro SQR_192 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, [%%pA] gsmulx %%x1,%%x0, [%%pA+sizeof(qword)*1] MULADD1x %%x2, %%x1, rdx, [%%pA+sizeof(qword)*2] mov rdx, qword [%%pA+sizeof(qword)*1] gsmulx %%x3, rax, qword [%%pA+sizeof(qword)*2] add %%x2, rax adc %%x3, 0 mov rdx, qword [%%pA+ sizeof(qword)*0] xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%A, %%A ;; add sqr(a[0]),...,sqr(a[2]) gsmulx rax, rdx, rdx ; a[0]^2 mov [%%pDst+sizeof(qword)*0], rdx mov rdx, [%%pA+sizeof(qword)*1] add %%x0, rax mov [%%pDst+sizeof(qword)*1], %%x0 gsmulx rax, rdx, rdx ; a[1]^2 adc %%x1, rdx mov [%%pDst+sizeof(qword)*2], %%x1 mov rdx, [%%pA+sizeof(qword)*2] adc %%x2, rax mov [%%pDst+sizeof(qword)*3], %%x2 gsmulx rax, rdx, rdx ; a[2]^2 adc %%x3, rdx mov [%%pDst+sizeof(qword)*4], %%x3 adc %%A, rax mov [%%pDst+sizeof(qword)*5], %%A %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_3,PRIVATE SQR_192 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_3 ;; ;; 4*qword squarer ;; %macro SQR_256 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, [%%pA] gsmulx %%x1,%%x0, [%%pA+sizeof(qword)*1] MULADD1x %%x2, %%x1, rdx, [%%pA+sizeof(qword)*2] MULADD1x %%x3, %%x2, rdx, [%%pA+sizeof(qword)*3] mov rdx, qword [%%pA+sizeof(qword)*1] gsmulx %%A, rax, qword [%%pA+sizeof(qword)*2] xor %%x4, %%x4 add %%x2, rax adc %%x3, %%A adc %%x4, 0 gsmulx %%A, rax, qword [%%pA+sizeof(qword)*3] add %%x3, rax adc %%x4, %%A mov rdx, qword [%%pA+sizeof(qword)*2] gsmulx %%x5, rax, qword [%%pA+sizeof(qword)*3] add %%x4, rax adc %%x5, 0 mov rdx, [%%pA+sizeof(qword)*0] ;; --- double x0...x5 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%A, 0 ;; add sqr(a[0]),...,sqr(a[3]) gsmulx rax, rdx, rdx ; a[0]^2 mov [%%pDst+sizeof(qword)*0], rdx mov rdx, [%%pA+sizeof(qword)*1] add %%x0, rax mov [%%pDst+sizeof(qword)*1], %%x0 gsmulx rax, rdx, rdx ; a[1]^2 adc %%x1, rdx mov [%%pDst+sizeof(qword)*2], %%x1 mov rdx, [%%pA+sizeof(qword)*2] adc %%x2, rax mov [%%pDst+sizeof(qword)*3], %%x2 gsmulx rax, rdx, rdx ; a[2]^2 adc %%x3, rdx mov [%%pDst+sizeof(qword)*4], %%x3 mov rdx, [%%pA+sizeof(qword)*3] adc %%x4, rax mov [%%pDst+sizeof(qword)*5], %%x4 gsmulx rax, rdx, rdx ; a[3]^2 adc %%x5, rdx mov [%%pDst+sizeof(qword)*6], %%x5 adc %%A, rax mov [%%pDst+sizeof(qword)*7], %%A %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_4,PRIVATE SQR_256 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_4 ;; ;; 5*qword squarer ;; %macro SQR_320 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, [%%pA] gsmulx %%x1,%%x0, [%%pA+sizeof(qword)*1] MULADD1x %%x2, %%x1, rdx, [%%pA+sizeof(qword)*2] MULADD1x %%x3, %%x2, rdx, [%%pA+sizeof(qword)*3] MULADD1x %%x4, %%x3, rdx, [%%pA+sizeof(qword)*4] mov rdx, [%%pA + sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] add %%x2, rax adc %%t0, 0 MULADDx %%t0, %%x3, rdx, [%%pA+sizeof(qword)*3], %%A MULADDx %%t0, %%x4, rdx, [%%pA+sizeof(qword)*4], %%A mov %%x5, %%t0 mov rdx, qword [%%pA+sizeof(qword)*2] gsmulx %%A, rax, qword [%%pA+sizeof(qword)*3] xor %%x6, %%x6 add %%x4, rax adc %%x5, %%A adc %%x6, 0 gsmulx %%A, rax, qword [%%pA+sizeof(qword)*4] add %%x5, rax adc %%x6, %%A mov rdx, qword [%%pA+sizeof(qword)*3] gsmulx %%x7, rax, qword [%%pA+sizeof(qword)*4] add %%x6, rax adc %%x7, 0 mov rdx, [%%pA+sizeof(qword)*0] ;; --- double x0...x5 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%x7, %%x7 adc %%A, 0 ;; add sqr(a[0]),...,sqr(a[4]) gsmulx rax, rdx, rdx ; a[0]^2 mov [%%pDst+sizeof(qword)*0], rdx mov rdx, [%%pA+sizeof(qword)*1] add %%x0, rax mov [%%pDst+sizeof(qword)*1], %%x0 gsmulx rax, rdx, rdx ; a[1]^2 adc %%x1, rdx mov [%%pDst+sizeof(qword)*2], %%x1 mov rdx, [%%pA+sizeof(qword)*2] adc %%x2, rax mov [%%pDst+sizeof(qword)*3], %%x2 gsmulx rax, rdx, rdx ; a[2]^2 adc %%x3, rdx mov [%%pDst+sizeof(qword)*4], %%x3 mov rdx, [%%pA+sizeof(qword)*3] adc %%x4, rax mov [%%pDst+sizeof(qword)*5], %%x4 gsmulx rax, rdx, rdx ; a[3]^2 adc %%x5, rdx mov [%%pDst+sizeof(qword)*6], %%x5 mov rdx, [%%pA+sizeof(qword)*4] adc %%x6, rax mov [%%pDst+sizeof(qword)*7], %%x6 gsmulx rax, rdx, rdx ; a[4]^2 adc %%x7, rdx mov [%%pDst+sizeof(qword)*8], %%x7 mov rdx, [%%pA+sizeof(qword)*5] adc %%A, rax mov [%%pDst+sizeof(qword)*9], %%A %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_5,PRIVATE SQR_320 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_5 ;; ;; 6*qword squarer ;; %macro SQR_384 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, [%%pA] gsmulx %%x1,%%x0, [%%pA+sizeof(qword)*1] MULADD1x %%x2, %%x1, rdx, [%%pA+sizeof(qword)*2] MULADD1x %%x3, %%x2, rdx, [%%pA+sizeof(qword)*3] MULADD1x %%x4, %%x3, rdx, [%%pA+sizeof(qword)*4] MULADD1x %%x5, %%x4, rdx, [%%pA+sizeof(qword)*5] mov rdx, [%%pA + sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] add %%x2, rax adc %%t0, 0 MULADDx %%t0, %%x3, rdx, [%%pA+sizeof(qword)*3], %%A MULADDx %%t0, %%x4, rdx, [%%pA+sizeof(qword)*4], %%A MULADDx %%t0, %%x5, rdx, [%%pA+sizeof(qword)*5], %%A mov %%x6, %%t0 mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] add %%x4, rax adc %%t0, 0 MULADDx %%t0, %%x5, rdx, [%%pA+sizeof(qword)*4], %%A MULADDx %%t0, %%x6, rdx, [%%pA+sizeof(qword)*5], %%A mov %%x7, %%t0 mov rdx, qword [%%pA+sizeof(qword)*3] gsmulx %%A, rax, qword [%%pA+sizeof(qword)*4] xor %%x8, %%x8 add %%x6, rax adc %%x7, %%A adc %%x8, 0 gsmulx %%A, rax, qword [%%pA+sizeof(qword)*5] add %%x7, rax adc %%x8, %%A mov rdx, qword [%%pA+sizeof(qword)*4] gsmulx %%t0, rax, qword [%%pA+sizeof(qword)*5] add %%x8, rax adc %%t0, 0 mov rdx, [%%pA+sizeof(qword)*0] ;; --- double x0...x7,x8,t0 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%x7, %%x7 adc %%x8, %%x8 adc %%t0, %%t0 adc %%A, 0 ;; add sqr(a[0]),...,sqr(a[5]) gsmulx rax, rdx, rdx ; a[0]^2 mov [%%pDst+sizeof(qword)*0], rdx mov rdx, [%%pA+sizeof(qword)*1] add %%x0, rax mov [%%pDst+sizeof(qword)*1], %%x0 gsmulx rax, rdx, rdx ; a[1]^2 adc %%x1, rdx mov [%%pDst+sizeof(qword)*2], %%x1 mov rdx, [%%pA+sizeof(qword)*2] adc %%x2, rax mov [%%pDst+sizeof(qword)*3], %%x2 gsmulx rax, rdx, rdx ; a[2]^2 adc %%x3, rdx mov [%%pDst+sizeof(qword)*4], %%x3 mov rdx, [%%pA+sizeof(qword)*3] adc %%x4, rax mov [%%pDst+sizeof(qword)*5], %%x4 gsmulx rax, rdx, rdx ; a[3]^2 adc %%x5, rdx mov [%%pDst+sizeof(qword)*6], %%x5 mov rdx, [%%pA+sizeof(qword)*4] adc %%x6, rax mov [%%pDst+sizeof(qword)*7], %%x6 gsmulx rax, rdx, rdx ; a[4]^2 adc %%x7, rdx mov [%%pDst+sizeof(qword)*8], %%x7 mov rdx, [%%pA+sizeof(qword)*5] adc %%x8, rax mov [%%pDst+sizeof(qword)*9], %%x8 gsmulx rax, rdx, rdx ; a[5]^2 adc %%t0, rdx mov [%%pDst+sizeof(qword)*10], %%t0 adc %%A, rax mov [%%pDst+sizeof(qword)*11], %%A %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_6,PRIVATE SQR_384 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_6 ;; ;; 7*qword squarer ;; %macro SQR_448 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; ------------------ ;; first pass 01...06 ;; ------------------ mov rdx, [%%pA] gsmulx %%x1,%%x0, [%%pA+sizeof(qword)*1] MULADD1x %%x2, %%x1, rdx, [%%pA+sizeof(qword)*2] MULADD1x %%x3, %%x2, rdx, [%%pA+sizeof(qword)*3] MULADD1x %%x4, %%x3, rdx, [%%pA+sizeof(qword)*4] MULADD1x %%x5, %%x4, rdx, [%%pA+sizeof(qword)*5] MULADD1x %%x6, %%x5, rdx, [%%pA+sizeof(qword)*6] ;; ------------------ ;; second pass 12...16 ;; ------------------ mov rdx, [%%pA + sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] add %%x2, rax adc %%t0, 0 MULADDx %%t0, %%x3, rdx, [%%pA+sizeof(qword)*3], %%A MULADDx %%t0, %%x4, rdx, [%%pA+sizeof(qword)*4], %%A MULADDx %%t0, %%x5, rdx, [%%pA+sizeof(qword)*5], %%A MULADDx %%t0, %%x6, rdx, [%%pA+sizeof(qword)*6], %%A mov %%x7, %%t0 ;; ------------------ ;; third pass 23...25 ;; ------------------ mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] add %%x4, rax adc %%t0, 0 xor %%x8, %%x8 MULADDx %%t0, %%x5, rdx, [%%pA+sizeof(qword)*4], %%A MULADDx %%t0, %%x6, rdx, [%%pA+sizeof(qword)*5], %%A add %%x7, %%t0 adc %%x8, 0 ;; ------------------ ;; fourth pass 34 ;; ------------------ mov rax, [%%pA+sizeof(qword)*3] mul qword [%%pA+sizeof(qword)*4] add %%x6, rax adc rdx, 0 add %%x7, rdx adc %%x8, 0 mov rdx, [%%pA+sizeof(qword)*0] ;; --- double x0...x6 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%A, 0 ;; add sqr(a[0]),...,sqr(a[3]) gsmulx rax, rdx, rdx ; a[0]^2 mov [%%pDst+sizeof(qword)*0], rdx mov rdx, [%%pA+sizeof(qword)*1] add %%x0, rax mov [%%pDst+sizeof(qword)*1], %%x0 gsmulx rax, rdx, rdx ; a[1]^2 adc %%x1, rdx mov [%%pDst+sizeof(qword)*2], %%x1 mov rdx, [%%pA+sizeof(qword)*2] adc %%x2, rax mov [%%pDst+sizeof(qword)*3], %%x2 gsmulx rax, rdx, rdx ; a[2]^2 adc %%x3, rdx mov [%%pDst+sizeof(qword)*4], %%x3 mov rdx, [%%pA+sizeof(qword)*3] adc %%x4, rax mov [%%pDst+sizeof(qword)*5], %%x4 gsmulx rax, rdx, rdx ; a[3]^2 adc %%x5, rdx mov [%%pDst+sizeof(qword)*6], %%x5 adc %%x6, rax mov [%%pDst+sizeof(qword)*7], %%x6 adc %%A, 0 ;; ------------------ ;; third pass complete 26 ;; ------------------ mov rax, [%%pA+sizeof(qword)*2] xor %%x0, %%x0 mul qword [%%pA+sizeof(qword)*6] add %%x7, rax adc rdx, 0 add %%x8, rdx adc %%x0, 0 ;; ------------------ ;; forth pass complete 35...36 ;; ------------------ mov rdx, [%%pA+sizeof(qword)*3] gsmulx %%x6, rax, [%%pA+sizeof(qword)*5] add %%x7, rax adc %%x8, %%x6 adc %%x0, 0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*6] add %%x8, rax adc %%x0, %%x6 ;; ------------------ ;; fifth pass 45...46 ;; ------------------ mov rdx, [%%pA+sizeof(qword)*4] gsmulx %%x6, rax, [%%pA+sizeof(qword)*5] xor %%x1, %%x1 add %%x8, rax adc %%x0, %%x6 adc %%x1, 0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*6] add %%x0, rax adc %%x1, %%x6 ;; ------------------ ;; six pass 56 ;; ------------------ mov rax, [%%pA+sizeof(qword)*5] xor %%x2, %%x2 mul qword [%%pA + sizeof(qword)*6] add %%x1, rax adc %%x2, rdx mov rdx, [%%pA+sizeof(qword)*4] ;; --- double x7, x8, x0, x1, x2 xor %%x3, %%x3 add %%x7, %%x7 adc %%x8, %%x8 adc %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, 0 gsmulx rax, rdx, rdx ; a[4]^2 add rdx, %%A adc rax, 0 add %%x7, rdx mov rdx, [%%pA+sizeof(qword)*5] mov [%%pDst+sizeof(qword)*8], %%x7 adc %%x8, rax mov [%%pDst+sizeof(qword)*9], %%x8 gsmulx rax, rdx, rdx ; a[5]^2 adc %%x0, rdx mov [%%pDst+sizeof(qword)*10], %%x0 mov rdx, [%%pA+sizeof(qword)*6] adc %%x1, rax mov [%%pDst+sizeof(qword)*11], %%x1 gsmulx rax, rdx, rdx ; a[6]^2 adc %%x2, rdx mov [%%pDst+sizeof(qword)*12], %%x2 adc %%x3, rax mov [%%pDst+sizeof(qword)*13], %%x3 %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_7,PRIVATE SQR_448 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_7 ;; ;; 8*qword squarer ;; %macro SQR_512 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; ---------------------------------- ;; first pass a[0]*a[1],...,a[0]*a[7] ;; ---------------------------------- mov rdx, [%%pA] gsmulx %%x1,%%x0, [%%pA+sizeof(qword)*1] MULADD1x %%x2, %%x1, rdx, [%%pA+sizeof(qword)*2] MULADD1x %%x3, %%x2, rdx, [%%pA+sizeof(qword)*3] MULADD1x %%x4, %%x3, rdx, [%%pA+sizeof(qword)*4] MULADD1x %%x5, %%x4, rdx, [%%pA+sizeof(qword)*5] MULADD1x %%x6, %%x5, rdx, [%%pA+sizeof(qword)*6] MULADD1x %%x7, %%x6, rdx, [%%pA+sizeof(qword)*7] ;; ----------------------------------- ;; second pass a[1]*a[2],...,a[1]*a[6] ;; ----------------------------------- mov rdx, [%%pA + sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] add %%x2, rax adc %%t0, 0 xor %%x8, %%x8 MULADDx %%t0, %%x3, rdx, [%%pA+sizeof(qword)*3], %%A MULADDx %%t0, %%x4, rdx, [%%pA+sizeof(qword)*4], %%A MULADDx %%t0, %%x5, rdx, [%%pA+sizeof(qword)*5], %%A MULADDx %%t0, %%x6, rdx, [%%pA+sizeof(qword)*6], %%A add %%x7, %%t0 adc %%x8, 0 ;; ---------------------------------- ;; third pass a[2]*a[3],...,a[2]*a[5] ;; ---------------------------------- mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] add %%x4, rax adc %%t0, 0 MULADDx %%t0, %%x5, rdx, [%%pA+sizeof(qword)*4], %%A MULADDx %%t0, %%x6, rdx, [%%pA+sizeof(qword)*5], %%A add %%x7, %%t0 adc %%x8, 0 ;; --------------------- ;; fourth pass a[3]*a[4] ;; --------------------- mov rax, [%%pA+sizeof(qword)*3] mul qword [%%pA+sizeof(qword)*4] add %%x6, rax adc rdx, 0 add %%x7, rdx adc %%x8, 0 mov rdx, [%%pA+sizeof(qword)*0] ;; double x0,...,x6 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%A, 0 ;; add sqr(a[0]),...,sqr(a[3]) gsmulx rax, rdx, rdx ; a[0]^2 mov [%%pDst+sizeof(qword)*0], rdx mov rdx, [%%pA+sizeof(qword)*1] add %%x0, rax mov [%%pDst+sizeof(qword)*1], %%x0 gsmulx rax, rdx, rdx ; a[1]^2 adc %%x1, rdx mov [%%pDst+sizeof(qword)*2], %%x1 mov rdx, [%%pA+sizeof(qword)*2] adc %%x2, rax mov [%%pDst+sizeof(qword)*3], %%x2 gsmulx rax, rdx, rdx ; a[2]^2 adc %%x3, rdx mov [%%pDst+sizeof(qword)*4], %%x3 mov rdx, [%%pA+sizeof(qword)*3] adc %%x4, rax mov [%%pDst+sizeof(qword)*5], %%x4 gsmulx rax, rdx, rdx ; a[3]^2 adc %%x5, rdx mov [%%pDst+sizeof(qword)*6], %%x5 adc %%x6, rax mov [%%pDst+sizeof(qword)*7], %%x6 adc %%A, 0 ;; ---------------------------- ;; second pass (cont) a[1]*a[7] ;; ---------------------------- mov rax, [%%pA+sizeof(qword)*1] xor %%x0, %%x0 mul qword [%%pA+sizeof(qword)*7] add %%x7, rax adc rdx, 0 add %%x8, rdx adc %%x0, 0 ;; ----------------------------------------- ;; third pass (cont) a[2]*a[6],...,a[2]*a[7] ;; ----------------------------------------- mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%x6, rax, [%%pA+sizeof(qword)*6] add %%x7, rax adc %%x8, %%x6 adc %%x0, 0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*7] xor %%x1, %%x1 add %%x8, rax adc %%x0, %%x6 adc %%x1, 0 ;; ----------------------------------- ;; fourth pass a[3]*a[5],...,a[3]*a[7] ;; ----------------------------------- mov rdx, [%%pA+sizeof(qword)*3] gsmulx %%x6, rax, [%%pA+sizeof(qword)*5] add %%x7, rax adc %%x6, 0 add %%x8, %%x6 adc %%x0, 0 adc %%x1, 0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*6] add %%x8, rax adc %%x6, 0 add %%x0, %%x6 adc %%x1, 0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*7] add %%x0, rax adc %%x6, 0 add %%x1, %%x6 ;; carry out should be 0 ;; ----------------------------------- ;; fifth pass a[4]*a[5],...,a[4]*a[7] ;; ----------------------------------- mov rdx, [%%pA+sizeof(qword)*4] gsmulx %%x2, rax, [%%pA+sizeof(qword)*5] add %%x8, rax adc %%x2, 0 MULADDx %%x2, %%x0, rdx, [%%pA+sizeof(qword)*6], %%x6 MULADDx %%x2, %%x1, rdx, [%%pA+sizeof(qword)*7], %%x6 ;; ----------------------------------------------------------- ;; sixth pass a[5]*a[6],...,a[5]*a[7] & seventh pass a[6]*a[7] ;; ----------------------------------------------------------- mov rdx, [%%pA+sizeof(qword)*5] gsmulx %%x3, rax, [%%pA+sizeof(qword)*6] add %%x1, rax adc %%x3, 0 MULADDx %%x3, %%x2, rdx, [%%pA+sizeof(qword)*7], %%x6 mov rax, [%%pA+sizeof(qword)*6] mul qword [%%pA+sizeof(qword)*7] add %%x3, rax adc rdx, 0 mov %%x4, rdx mov rdx, [%%pA+sizeof(qword)*4] ;; --- double x7, x8, x0, ..., x4 xor %%x5, %%x5 add %%x7, %%x7 adc %%x8, %%x8 adc %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, 0 ;; add sqr(a[4]),...,sqr(a[7]) gsmulx rax, rdx, rdx ; a[4]^2 add rdx, %%A adc rax, 0 add %%x7, rdx mov rdx, [%%pA+sizeof(qword)*5] mov [%%pDst+sizeof(qword)*8], %%x7 adc %%x8, rax mov [%%pDst+sizeof(qword)*9], %%x8 gsmulx rax, rdx, rdx ; a[5]^2 adc %%x0, rdx mov [%%pDst+sizeof(qword)*10], %%x0 mov rdx, [%%pA+sizeof(qword)*6] adc %%x1, rax mov [%%pDst+sizeof(qword)*11], %%x1 gsmulx rax, rdx, rdx ; a[6]^2 adc %%x2, rdx mov [%%pDst+sizeof(qword)*12], %%x2 mov rdx, [%%pA+sizeof(qword)*7] adc %%x3, rax mov [%%pDst+sizeof(qword)*13], %%x3 gsmulx rax, rdx, rdx ; a[7]^2 adc %%x4, rdx mov [%%pDst+sizeof(qword)*14], %%x4 adc %%x5, rax mov [%%pDst+sizeof(qword)*15], %%x5 %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_8,PRIVATE SQR_512 pDst, pA, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 ret ENDFUNC sqr_8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SQR_512_TRIANGLE_STEP ; executes single line of upper tpiangle ; ; Inp:partial sum: x7 x6 x5 x4 x3 x2 x1 x0 ; rdx * pA[] p p p p p p p p p ; Out: x0 x7 x6 x5 x4 x3 x2 x1 ; [dst] %macro SQR_512_TRIANGLE_STEP 14.nolist %xdefine %%HEAD_X %1 %xdefine %%X7 %2 %xdefine %%X6 %3 %xdefine %%X5 %4 %xdefine %%X4 %5 %xdefine %%X3 %6 %xdefine %%X2 %7 %xdefine %%X1 %8 %xdefine %%X0 %9 %xdefine %%TAIL_X %10 %xdefine %%pDst %11 %xdefine %%pA %12 %xdefine %%TMP1 %13 %xdefine %%TMP2 %14 %ifnempty %%X0 gsmulx %%TMP1, rax, [%%pA+sizeof(qword)*0] ; TMP1:rax = rdx * pA[0] add %%X0, rax adc %%TMP1, 0 %endif %ifnempty %%TAIL_X mov %%pDst, %%TAIL_X %endif %ifnempty %%X1 gsmulx %%TMP2, rax, [%%pA+sizeof(qword)*1] ; TMP2:rax = rdx * pA[1] add %%X1, rax adc %%TMP2, 0 %ifnempty %%X0 add %%X1, %%TMP1 adc %%TMP2, 0 %endif %endif %ifnempty %%X2 gsmulx %%TMP1, rax, [%%pA+sizeof(qword)*2] ; TMP1:rax = rdx * pA[2] add %%X2, rax adc %%TMP1, 0 %ifnempty %%X1 add %%X2, %%TMP2 adc %%TMP1, 0 %endif %endif %ifnempty %%X3 gsmulx %%TMP2, rax, [%%pA+sizeof(qword)*3] ; TMP2:rax = rdx * pA[3] add %%X3, rax adc %%TMP2, 0 %ifnempty %%X2 add %%X3, %%TMP1 adc %%TMP2, 0 %endif %endif %ifnempty %%X4 gsmulx %%TMP1, rax, [%%pA+sizeof(qword)*4] ; TMP1:rax = rdx * pA[4] add %%X4, rax adc %%TMP1, 0 %ifnempty %%X3 add %%X4, %%TMP2 adc %%TMP1, 0 %endif %endif %ifnempty %%X5 gsmulx %%TMP2, rax, [%%pA+sizeof(qword)*5] ; TMP2:rax = rdx * pA[5] add %%X5, rax adc %%TMP2, 0 %ifnempty %%X4 add %%X5, %%TMP1 adc %%TMP2, 0 %endif %endif %ifnempty %%X6 gsmulx %%TMP1, rax, [%%pA+sizeof(qword)*6] ; TMP1:rax = rdx * pA[6] add %%X6, rax adc %%TMP1, 0 %ifnempty %%X5 add %%X6, %%TMP2 adc %%TMP1, 0 %endif %endif %ifnempty %%X7 gsmulx %%HEAD_X, rax, [%%pA+sizeof(qword)*7] ; X0:rax = rdx * pA[7] add %%X7, rax adc %%HEAD_X, 0 %ifnempty %%X6 add %%X7, %%TMP1 adc %%HEAD_X, 0 %endif %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; square and add diagonal terms %macro ADD_DIAG 3.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pSrc %3 mov r8, qword [%%pDst+sizeof(qword)*0] mov r9, qword [%%pDst+sizeof(qword)*1] %if %%N > 1 mov r10,qword [%%pDst+sizeof(qword)*2] mov r11,qword [%%pDst+sizeof(qword)*3] %if %%N > 2 mov r12,qword [%%pDst+sizeof(qword)*4] mov r13,qword [%%pDst+sizeof(qword)*5] %if %%N > 3 mov r14,qword [%%pDst+sizeof(qword)*6] mov r15,qword [%%pDst+sizeof(qword)*7] %endif %endif %endif xor rbp, rbp add r8, r8 adc r9, r9 %if %%N > 1 adc r10,r10 adc r11,r11 %if %%N > 2 adc r12,r12 adc r13,r13 %if %%N > 3 adc r14,r14 adc r15,r15 %endif %endif %endif adc rbp, 0 mov rdx, [%%pSrc+sizeof(qword)*0] gsmulx rdx, rax, rdx add rax, rbx adc rdx, 0 add r8, rax mov rbx, rbp adc r9, rdx %if %%N > 1 mov rdx, [%%pSrc+sizeof(qword)*1] gsmulx rdx, rax, rdx adc r10,rax adc r11,rdx %if %%N > 2 mov rdx, [%%pSrc+sizeof(qword)*2] gsmulx rdx, rax, rdx adc r12,rax adc r13,rdx %if %%N > 3 mov rdx, [%%pSrc+sizeof(qword)*3] gsmulx rdx, rax, rdx adc r14,rax adc r15,rdx %endif %endif %endif adc rbx, 0 mov qword [%%pDst+sizeof(qword)*0], r8 mov qword [%%pDst+sizeof(qword)*1], r9 %if %%N > 1 mov qword [%%pDst+sizeof(qword)*2], r10 mov qword [%%pDst+sizeof(qword)*3], r11 %if %%N > 2 mov qword [%%pDst+sizeof(qword)*4], r12 mov qword [%%pDst+sizeof(qword)*5], r13 %if %%N > 3 mov qword [%%pDst+sizeof(qword)*6], r14 mov qword [%%pDst+sizeof(qword)*7], r15 %endif %endif %endif %endmacro ;; rbp = local carry ;; rbx = global carry align IPP_ALIGN_FACTOR DECLARE_FUNC add_diag_4,PRIVATE ADD_DIAG 4, rdi, rsi ret ENDFUNC add_diag_4 ;; ;; 8*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr8_triangle,PRIVATE ;; A[0]*A[1..7] mov rdx, [rsi+sizeof(qword)*0] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11,r10, r9, , r8, [rdi+sizeof(qword)*0],rsi, rbx,rbp ;; A[1]*A[2..7] mov rdx, [rsi+sizeof(qword)*1] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13,r12,r11, , , r9, [rdi+sizeof(qword)*1],rsi, rbx,rbp ;; A[2]*A[3..7] mov rdx, [rsi+sizeof(qword)*2] SQR_512_TRIANGLE_STEP r10, r9, r8,r15,r14,r13, , , , r10, [rdi+sizeof(qword)*2],rsi, rbx,rbp ;; A[3]*A[4..7] mov rdx, [rsi+sizeof(qword)*3] SQR_512_TRIANGLE_STEP r11, r10, r9, r8,r15, , , , , r11, [rdi+sizeof(qword)*3],rsi, rbx,rbp ;; A[4]*A[5..7] mov rdx, [rsi+sizeof(qword)*4] SQR_512_TRIANGLE_STEP r12, r11,r10, r9, , , , , , r12, [rdi+sizeof(qword)*4],rsi, rbx,rbp ;; A[5]*A[6..7] mov rdx, [rsi+sizeof(qword)*5] SQR_512_TRIANGLE_STEP r13, r12,r11, , , , , , , r13, [rdi+sizeof(qword)*5],rsi, rbx,rbp ;; A[6]*A[7] mov rdx, [rsi+sizeof(qword)*6] SQR_512_TRIANGLE_STEP r14, r13, , , , , , , , r14, [rdi+sizeof(qword)*6],rsi, rbx,rbp ret ENDFUNC sqr8_triangle ;; ;; 9*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_9,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 mov qword [rdi+sizeof(qword)*(1+0)], r8 mov qword [rdi+sizeof(qword)*(1+1)], r9 mov qword [rdi+sizeof(qword)*(1+2)], r10 mov qword [rdi+sizeof(qword)*(1+3)], r11 mov qword [rdi+sizeof(qword)*(1+4)], r12 mov qword [rdi+sizeof(qword)*(1+5)], r13 mov qword [rdi+sizeof(qword)*(1+6)], r14 mov qword [rdi+sizeof(qword)*(1+7)], r15 xor rbx, rbx mov qword [rdi+sizeof(qword)*(1+8)], rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 ADD_DIAG 1, rdi, rsi sub rsi, sizeof(qword)*8 sub rdi, sizeof(qword)*16 ret ENDFUNC sqr_9 ;; ;; 10*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_10,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 mov qword [rdi+sizeof(qword)*(2+0)], r8 mov qword [rdi+sizeof(qword)*(2+1)], r9 mov qword [rdi+sizeof(qword)*(2+2)], r10 mov qword [rdi+sizeof(qword)*(2+3)], r11 mov qword [rdi+sizeof(qword)*(2+4)], r12 mov qword [rdi+sizeof(qword)*(2+5)], r13 mov qword [rdi+sizeof(qword)*(2+6)], r14 mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15, , , , , , , , , , {rsi+sizeof(qword)*2}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(2+7)], r15 mov qword [rdi+sizeof(qword)*(2+8)], r8 mov qword [rdi+sizeof(qword)*(2+9)], rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 ADD_DIAG 2, rdi, rsi sub rsi, sizeof(qword)*8 sub rdi, sizeof(qword)*16 ret ENDFUNC sqr_10 ;; ;; 10*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_11,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 add rdi, sizeof(qword)*1 add rcx, sizeof(qword)*1 call mla_8x2 sub rdi, sizeof(qword)*1 sub rcx, sizeof(qword)*1 mov qword [rdi+sizeof(qword)*(3+0)], r8 mov qword [rdi+sizeof(qword)*(3+1)], r9 mov qword [rdi+sizeof(qword)*(3+2)], r10 mov qword [rdi+sizeof(qword)*(3+3)], r11 mov qword [rdi+sizeof(qword)*(3+4)], r12 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14, , , , , , , r13,[rdi+sizeof(qword)*(3+5)],{rsi+sizeof(qword)*3}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8, , , , , , , , r14,[rdi+sizeof(qword)*(3+6)],{rsi+sizeof(qword)*3}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(3+7)], r15 mov qword [rdi+sizeof(qword)*(3+8)], r8 mov qword [rdi+sizeof(qword)*(3+9)], r9 mov qword [rdi+sizeof(qword)*(3+10)],rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 ADD_DIAG 3, rdi, rsi sub rsi, sizeof(qword)*(4*2) sub rdi, sizeof(qword)*(8*2) ret ENDFUNC sqr_11 ;; ;; 12*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_12,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*2 sub rcx, sizeof(qword)*2 mov qword [rdi+sizeof(qword)*(4+0)], r8 mov qword [rdi+sizeof(qword)*(4+1)], r9 mov qword [rdi+sizeof(qword)*(4+2)], r10 mov qword [rdi+sizeof(qword)*(4+3)], r11 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13, , , , , , r12,[rdi+sizeof(qword)*(4+4)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15, , , , , , , r13,[rdi+sizeof(qword)*(4+5)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, , , , , , , , r14,[rdi+sizeof(qword)*(4+6)],{rsi+sizeof(qword)*4}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(4+7)], r15 mov qword [rdi+sizeof(qword)*(4+8)], r8 mov qword [rdi+sizeof(qword)*(4+9)], r9 mov qword [rdi+sizeof(qword)*(4+10)],r10 mov qword [rdi+sizeof(qword)*(4+11)],rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 sub rsi, sizeof(qword)*(4*2) sub rdi, sizeof(qword)*(8*2) ret ENDFUNC sqr_12 ;; ;; 13*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_13,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*3 sub rcx, sizeof(qword)*3 mov qword [rdi+sizeof(qword)*(5+0)], r8 mov qword [rdi+sizeof(qword)*(5+1)], r9 mov qword [rdi+sizeof(qword)*(5+2)], r10 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12, , , , , r11,[rdi+sizeof(qword)*(5+3)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14, , , , , , r12,[rdi+sizeof(qword)*(5+4)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8, , , , , , , r13,[rdi+sizeof(qword)*(5+5)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, , , , , , , , r14,[rdi+sizeof(qword)*(5+6)],{rsi+sizeof(qword)*5}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(5+7)], r15 mov qword [rdi+sizeof(qword)*(5+8)], r8 mov qword [rdi+sizeof(qword)*(5+9)], r9 mov qword [rdi+sizeof(qword)*(5+10)],r10 mov qword [rdi+sizeof(qword)*(5+11)],r11 mov qword [rdi+sizeof(qword)*(5+12)],rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 ADD_DIAG 1, rdi, rsi sub rsi, sizeof(qword)*(4*3) sub rdi, sizeof(qword)*(8*3) ret ENDFUNC sqr_13 ;; ;; 14*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_14,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*4 sub rcx, sizeof(qword)*4 mov qword [rdi+sizeof(qword)*(6+0)], r8 mov qword [rdi+sizeof(qword)*(6+1)], r9 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11, , , , r10,[rdi+sizeof(qword)*(6+2)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13, , , , , r11,[rdi+sizeof(qword)*(6+3)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15, , , , , , r12,[rdi+sizeof(qword)*(6+4)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, , , , , , , r13,[rdi+sizeof(qword)*(6+5)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11, , , , , , , , r14,[rdi+sizeof(qword)*(6+6)],{rsi+sizeof(qword)*6}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(6+7)], r15 mov qword [rdi+sizeof(qword)*(6+8)], r8 mov qword [rdi+sizeof(qword)*(6+9)], r9 mov qword [rdi+sizeof(qword)*(6+10)],r10 mov qword [rdi+sizeof(qword)*(6+11)],r11 mov qword [rdi+sizeof(qword)*(6+12)],r12 mov qword [rdi+sizeof(qword)*(6+13)],rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 ADD_DIAG 2, rdi, rsi sub rsi, sizeof(qword)*(4*3) sub rdi, sizeof(qword)*(8*3) ret ENDFUNC sqr_14 ;; ;; 15*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_15,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*5 sub rcx, sizeof(qword)*5 mov qword [rdi+sizeof(qword)*(7+0)], r8 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11,r10, , , r9, [rdi+sizeof(qword)*(7+1)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13,r12, , , , r10,[rdi+sizeof(qword)*(7+2)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15,r14, , , , , r11,[rdi+sizeof(qword)*(7+3)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, r8, , , , , , r12,[rdi+sizeof(qword)*(7+4)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11,r10, , , , , , , r13,[rdi+sizeof(qword)*(7+5)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*13] SQR_512_TRIANGLE_STEP r13, r12, , , , , , , , r14,[rdi+sizeof(qword)*(7+6)],{rsi+sizeof(qword)*7}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(7+7)], r15 mov qword [rdi+sizeof(qword)*(7+8)], r8 mov qword [rdi+sizeof(qword)*(7+9)], r9 mov qword [rdi+sizeof(qword)*(7+10)],r10 mov qword [rdi+sizeof(qword)*(7+11)],r11 mov qword [rdi+sizeof(qword)*(7+12)],r12 mov qword [rdi+sizeof(qword)*(7+13)],r13 mov qword [rdi+sizeof(qword)*(7+14)],rbx sub rdi, sizeof(qword)*8 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 ADD_DIAG 3, rdi, rsi sub rsi, sizeof(qword)*(4*3) sub rdi, sizeof(qword)*(8*3) ret ENDFUNC sqr_15 ;; ;; 16*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_16,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 mov rcx, rsi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*6 sub rcx, sizeof(qword)*6 add rdi, sizeof(qword)*8 call sqr8_triangle xor rbx, rbx mov qword [rdi+sizeof(qword)*7], r15 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],rbx sub rsi, sizeof(qword)*8 sub rdi, sizeof(qword)*16 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*4 call add_diag_4 sub rsi, sizeof(qword)*12 sub rdi, sizeof(qword)*24 ret ENDFUNC sqr_16 ;; ;; 9*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr9_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x1 xor rax, rax mov qword [rdi+sizeof(qword)*(1+0)], r8 mov qword [rdi+sizeof(qword)*(1+1)], r9 mov qword [rdi+sizeof(qword)*(1+2)], r10 mov qword [rdi+sizeof(qword)*(1+3)], r11 mov qword [rdi+sizeof(qword)*(1+4)], r12 mov qword [rdi+sizeof(qword)*(1+5)], r13 mov qword [rdi+sizeof(qword)*(1+6)], r14 mov qword [rdi+sizeof(qword)*(1+7)], r15 mov qword [rdi+sizeof(qword)*(1+8)], rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr9_triangle ;; ;; 10*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr10_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x2 mov qword [rdi+sizeof(qword)*(2+0)], r8 mov qword [rdi+sizeof(qword)*(2+1)], r9 mov qword [rdi+sizeof(qword)*(2+2)], r10 mov qword [rdi+sizeof(qword)*(2+3)], r11 mov qword [rdi+sizeof(qword)*(2+4)], r12 mov qword [rdi+sizeof(qword)*(2+5)], r13 mov qword [rdi+sizeof(qword)*(2+6)], r14 mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15, , , , , , , , , , {rsi+sizeof(qword)*2}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(2+7)], r15 mov qword [rdi+sizeof(qword)*(2+8)], r8 mov qword [rdi+sizeof(qword)*(2+9)], rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr10_triangle ;; ;; 11*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr11_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x3 mov qword [rdi+sizeof(qword)*(3+0)], r8 mov qword [rdi+sizeof(qword)*(3+1)], r9 mov qword [rdi+sizeof(qword)*(3+2)], r10 mov qword [rdi+sizeof(qword)*(3+3)], r11 mov qword [rdi+sizeof(qword)*(3+4)], r12 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14, , , , , , , r13,[rdi+sizeof(qword)*(3+5)],{rsi+sizeof(qword)*3}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8, , , , , , , , r14,[rdi+sizeof(qword)*(3+6)],{rsi+sizeof(qword)*3}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(3+7)], r15 mov qword [rdi+sizeof(qword)*(3+8)], r8 mov qword [rdi+sizeof(qword)*(3+9)], r9 mov qword [rdi+sizeof(qword)*(3+10)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr11_triangle ;; ;; 12*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr12_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x4 mov qword [rdi+sizeof(qword)*(4+0)], r8 mov qword [rdi+sizeof(qword)*(4+1)], r9 mov qword [rdi+sizeof(qword)*(4+2)], r10 mov qword [rdi+sizeof(qword)*(4+3)], r11 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13, , , , , , r12,[rdi+sizeof(qword)*(4+4)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15, , , , , , , r13,[rdi+sizeof(qword)*(4+5)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, , , , , , , , r14,[rdi+sizeof(qword)*(4+6)],{rsi+sizeof(qword)*4}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(4+7)], r15 mov qword [rdi+sizeof(qword)*(4+8)], r8 mov qword [rdi+sizeof(qword)*(4+9)], r9 mov qword [rdi+sizeof(qword)*(4+10)],r10 mov qword [rdi+sizeof(qword)*(4+11)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr12_triangle ;; ;; 13*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr13_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x5 mov qword [rdi+sizeof(qword)*(5+0)], r8 mov qword [rdi+sizeof(qword)*(5+1)], r9 mov qword [rdi+sizeof(qword)*(5+2)], r10 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12, , , , , r11,[rdi+sizeof(qword)*(5+3)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14, , , , , , r12,[rdi+sizeof(qword)*(5+4)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8, , , , , , , r13,[rdi+sizeof(qword)*(5+5)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, , , , , , , , r14,[rdi+sizeof(qword)*(5+6)],{rsi+sizeof(qword)*5}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(5+7)], r15 mov qword [rdi+sizeof(qword)*(5+8)], r8 mov qword [rdi+sizeof(qword)*(5+9)], r9 mov qword [rdi+sizeof(qword)*(5+10)],r10 mov qword [rdi+sizeof(qword)*(5+11)],r11 mov qword [rdi+sizeof(qword)*(5+12)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr13_triangle ;; ;; 14*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr14_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x6 mov qword [rdi+sizeof(qword)*(6+0)], r8 mov qword [rdi+sizeof(qword)*(6+1)], r9 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11, , , , r10,[rdi+sizeof(qword)*(6+2)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13, , , , , r11,[rdi+sizeof(qword)*(6+3)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15, , , , , , r12,[rdi+sizeof(qword)*(6+4)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, , , , , , , r13,[rdi+sizeof(qword)*(6+5)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11, , , , , , , , r14,[rdi+sizeof(qword)*(6+6)],{rsi+sizeof(qword)*6}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(6+7)], r15 mov qword [rdi+sizeof(qword)*(6+8)], r8 mov qword [rdi+sizeof(qword)*(6+9)], r9 mov qword [rdi+sizeof(qword)*(6+10)],r10 mov qword [rdi+sizeof(qword)*(6+11)],r11 mov qword [rdi+sizeof(qword)*(6+12)],r12 mov qword [rdi+sizeof(qword)*(6+13)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr14_triangle ;; ;; 15*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr15_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x7 mov qword [rdi+sizeof(qword)*(7+0)], r8 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11,r10, , , r9, [rdi+sizeof(qword)*(7+1)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13,r12, , , , r10,[rdi+sizeof(qword)*(7+2)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15,r14, , , , , r11,[rdi+sizeof(qword)*(7+3)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, r8, , , , , , r12,[rdi+sizeof(qword)*(7+4)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11,r10, , , , , , , r13,[rdi+sizeof(qword)*(7+5)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*13] SQR_512_TRIANGLE_STEP r13, r12, , , , , , , , r14,[rdi+sizeof(qword)*(7+6)],{rsi+sizeof(qword)*7}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(7+7)], r15 mov qword [rdi+sizeof(qword)*(7+8)], r8 mov qword [rdi+sizeof(qword)*(7+9)], r9 mov qword [rdi+sizeof(qword)*(7+10)],r10 mov qword [rdi+sizeof(qword)*(7+11)],r11 mov qword [rdi+sizeof(qword)*(7+12)],r12 mov qword [rdi+sizeof(qword)*(7+13)],r13 mov qword [rdi+sizeof(qword)*(7+14)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr15_triangle ;; ;; 16*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr16_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 mov rcx, rsi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 call mla_8x8 add rdi, sizeof(qword)*8 call sqr8_triangle xor rax, rax mov qword [rdi+sizeof(qword)*7], r15 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],rax sub rsi, sizeof(qword)*8 sub rdi, sizeof(qword)*16 ret ENDFUNC sqr16_triangle sqr_l_basic dq sqr_1 - sqr_l_basic dq sqr_2 - sqr_l_basic dq sqr_3 - sqr_l_basic dq sqr_4 - sqr_l_basic dq sqr_5 - sqr_l_basic dq sqr_6 - sqr_l_basic dq sqr_7 - sqr_l_basic dq sqr_8 - sqr_l_basic dq sqr_9 - sqr_l_basic dq sqr_10- sqr_l_basic dq sqr_11- sqr_l_basic dq sqr_12- sqr_l_basic dq sqr_13- sqr_l_basic dq sqr_14- sqr_l_basic dq sqr_15- sqr_l_basic dq sqr_16- sqr_l_basic sqrN_triangle dq sqr9_triangle - sqrN_triangle dq sqr10_triangle - sqrN_triangle dq sqr11_triangle - sqrN_triangle dq sqr12_triangle - sqrN_triangle dq sqr13_triangle - sqrN_triangle dq sqr14_triangle - sqrN_triangle dq sqr15_triangle - sqrN_triangle dq sqr16_triangle - sqrN_triangle %endif ;; _PCPBNSQR_BASIC_ADCX_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusqrpp.inc000066400000000000000000000272101470420105600264300ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number squaring Support ; ; %ifndef _PCPBNUSQR_INC_ %assign _PCPBNUSQR_INC_ 1 %include "pcpmulx.inc" %include "pcpbnusqrpp_basic.inc" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; (8*n) squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_8N_adcox,PRIVATE push rdi ; save diagonal loop parameters push rsi push rdx push rdi ; save initial triangle product parameters push rsi push rdx ; ; init upper triangle product ; push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 add rdi, sizeof(qword)*8 sub rdx, 8 mov rcx, rsi add rsi, sizeof(qword)*8 .initLoop: push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnz .initLoop mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .update_Triangle ; ; update upper triangle product ; .outerLoop: push rdi ; update triangle product parameters push rsi push rdx xor rax, rax ; c-flag push rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10, qword [rdi+sizeof(qword)*2] mov r11, qword [rdi+sizeof(qword)*3] mov r12, qword [rdi+sizeof(qword)*4] mov r13, qword [rdi+sizeof(qword)*5] mov r14, qword [rdi+sizeof(qword)*6] mov r15, qword [rdi+sizeof(qword)*7] .innerLoop_entry: push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 add rdi, sizeof(qword)*8 sub rdx, 8 jz .skipInnerLoop mov rcx, rsi add rsi, sizeof(qword)*8 .innerLoop: pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10, qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11, qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12, qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13, qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14, qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15, qword [rdi+sizeof(qword)*7], rax sbb rax, rax ; save c-flag push rax push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnz .innerLoop .skipInnerLoop: pop rax ; restore c-flag neg rax adc r8, 0 mov qword [rdi+sizeof(qword)*0], r8 adc r9, 0 mov qword [rdi+sizeof(qword)*1], r9 adc r10,0 mov qword [rdi+sizeof(qword)*2],r10 adc r11,0 mov qword [rdi+sizeof(qword)*3],r11 adc r12,0 mov qword [rdi+sizeof(qword)*4],r12 adc r13,0 mov qword [rdi+sizeof(qword)*5],r13 adc r14,0 mov qword [rdi+sizeof(qword)*6],r14 adc r15,0 mov qword [rdi+sizeof(qword)*7],r15 .update_Triangle: pop rdx pop rsi pop rdi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*(8*2) sub rdx, 8 jnz .outerLoop ; ; add diagonal terms ; pop rcx pop rsi pop rdi call finalize ret ENDFUNC sqr_8N_adcox ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; general case N>16 squarer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_N_adcox,PRIVATE push rdi ; save diagonal loop parameters push rsi push rdx push rdi ; save initial triangle product parameters push rsi push rdx mov rbp, rdx and rbp, 7 GET_EP rax, mla_8xl_tail, rbp ; get tail procedure push rax ; ; init upper triangle product ; sub rdx, 8 push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 add rdi, sizeof(qword)*8 xor r15, r15 mov rcx, rsi add rsi, sizeof(qword)*8 sub rdx, 8 .initLoop: push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnc .initLoop add rdx, 8 ; ; tail ; SWAP rsi, rcx mov rax, [rsp] ; procedure push rdx call rax pop rdx lea rdi, [rdi+rdx*sizeof(qword)] mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2],r10 mov qword [rdi+sizeof(qword)*3],r11 mov qword [rdi+sizeof(qword)*4],r12 mov qword [rdi+sizeof(qword)*5],r13 mov qword [rdi+sizeof(qword)*6],r14 mov qword [rdi+sizeof(qword)*7],r15 jmp .update_Triangle ; ; update upper triangle product ; .outerLoop: push rdi ; update triangle product parameters push rsi push rdx push rax ; tail procedure xor rax, rax ; c-flag push rax mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10, qword [rdi+sizeof(qword)*2] mov r11, qword [rdi+sizeof(qword)*3] mov r12, qword [rdi+sizeof(qword)*4] mov r13, qword [rdi+sizeof(qword)*5] mov r14, qword [rdi+sizeof(qword)*6] mov r15, qword [rdi+sizeof(qword)*7] sub rdx, 8 push rdx call sqr8_triangle pop rdx mov qword [rdi+sizeof(qword)*7], r15 add rdi, sizeof(qword)*8 xor r15, r15 mov rcx, rsi add rsi, sizeof(qword)*8 sub rdx, 8 .innerLoop: pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10, qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11, qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12, qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13, qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14, qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15, qword [rdi+sizeof(qword)*7], rax sbb rax, rax ; save c-flag push rax push rdx call mla_8x8 pop rdx add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnc .innerLoop add rdx, 8 ; ; tail ; ; clear in advance pxor xmm0, xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)], xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)+sizeof(qword)*2], xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)+sizeof(qword)*4], xmm0 movdqu xmmword [rdi+rdx*sizeof(qword)+sizeof(qword)*6], xmm0 ; updates registers before mla operation pop rax ; restore c-flag neg rax op_reg_mem adc, r8, qword [rdi+sizeof(qword)*0], rax op_reg_mem adc, r9, qword [rdi+sizeof(qword)*1], rax op_reg_mem adc, r10, qword [rdi+sizeof(qword)*2], rax op_reg_mem adc, r11, qword [rdi+sizeof(qword)*3], rax op_reg_mem adc, r12, qword [rdi+sizeof(qword)*4], rax op_reg_mem adc, r13, qword [rdi+sizeof(qword)*5], rax op_reg_mem adc, r14, qword [rdi+sizeof(qword)*6], rax op_reg_mem adc, r15, qword [rdi+sizeof(qword)*7], rax ; store carry for future sbb rax, rax neg rax mov qword [rdi+sizeof(qword)*8], rax ; mla_8xn operation SWAP rsi, rcx mov rax, [rsp] ; procedure push rdx call rax pop rdx lea rdi, [rdi+rdx*sizeof(qword)] ; updates registers before store xor rax, rax mov rax, qword [rdi+sizeof(qword)*0] add r8, rax mov qword [rdi+sizeof(qword)*0], r8 mov rax, qword [rdi+sizeof(qword)*1] adc r9, rax mov qword [rdi+sizeof(qword)*1], r9 mov rax, qword [rdi+sizeof(qword)*2] adc r10, rax mov qword [rdi+sizeof(qword)*2], r10 mov rax, qword [rdi+sizeof(qword)*3] adc r11, rax mov qword [rdi+sizeof(qword)*3], r11 mov rax, qword [rdi+sizeof(qword)*4] adc r12, rax mov qword [rdi+sizeof(qword)*4], r12 mov rax, qword [rdi+sizeof(qword)*5] adc r13, rax mov qword [rdi+sizeof(qword)*5], r13 mov rax, qword [rdi+sizeof(qword)*6] adc r14, rax mov qword [rdi+sizeof(qword)*6], r14 mov rax, qword [rdi+sizeof(qword)*7] adc r15, rax mov qword [rdi+sizeof(qword)*7], r15 .update_Triangle: pop rax ; tail procedure pop rdx pop rsi pop rdi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*(8*2) sub rdx, 8 cmp rdx, 16 jg .outerLoop ; ; tail ; mov rbp, rdx sub rbp, 8 GET_EP rax, sqrN_triangle, rbp ; get triangle proc sub rsp, sizeof(qword)*32 push rdi push rdx mov r8, qword [rdi+sizeof(qword)*0] mov r9, qword [rdi+sizeof(qword)*1] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] lea rdi, [rsp+sizeof(qword)*2] call rax mov rsi, rdi pop rdx pop rdi ; copy 8 terms movdqu xmm0, xmmword [rsi] movdqu xmm1, xmmword [rsi+sizeof(qword)*2] movdqu xmm2, xmmword [rsi+sizeof(qword)*4] movdqu xmm3, xmmword [rsi+sizeof(qword)*6] add rsi, sizeof(qword)*8 movdqu xmmword [rdi], xmm0 movdqu xmmword [rdi+sizeof(qword)*2], xmm1 movdqu xmmword [rdi+sizeof(qword)*4], xmm2 movdqu xmmword [rdi+sizeof(qword)*6], xmm3 add rdi, sizeof(qword)*8 ; update rdx-8 terms lea rax, [rdx-8] xor rbx, rbx .update1: mov r8, qword [rsi] mov r9, qword [rdi] add rsi, sizeof(qword) neg rbx adc r8, r9 sbb rbx, rbx mov qword [rdi], r8 add rdi, sizeof(qword) sub rax, 1 jg .update1 ; update rdx terms .update2: mov r8, qword [rsi] add rsi, sizeof(qword) neg rbx adc r8, 0 sbb rbx, rbx mov qword [rdi], r8 add rdi, sizeof(qword) sub rdx, 1 jg .update2 add rsp, sizeof(qword)*32 ; ; add diagonal terms ; .add_diagonals: pop rcx pop rsi pop rdi call finalize .quit: ret ENDFUNC sqr_N_adcox %endif ;; _PCPBNUSQR_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusqrpp_basic.inc000066400000000000000000001501621470420105600275740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number squaring Support ; ; %ifndef _PCPBNSQR_BASIC_ADCX_INC_ %assign _PCPBNSQR_BASIC_ADCX_INC_ 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Fixed-size (1-8 qwords) square operations ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; 1*qword squarer ;; %macro SQR_64 2.nolist %xdefine %%pDst %1 %xdefine %%pA %2 mov rdx, qword [%%pA] gsmulx rdx, rax, rdx mov qword [%%pDst], rax mov qword [%%pDst+sizeof(qword)], rdx %endmacro align IPP_ALIGN_FACTOR sqr_1: SQR_64 rdi, rsi ret ;; ;; 2*qword squarer ;; %macro SQR_128 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, qword [%%pA+sizeof(qword)] gsmulx rax, %%x1, qword [%%pA] ; (rax:x1) = a[0]*a[1] gsmulx %%x3, %%x2, rdx ; (x3 :x2) = a[1]^2 mov rdx, qword [%%pA] ; a[0] gsmulx rdx, %%x0, rdx ; (rdx:x0) = a[0]^2 add %%x1, %%x1 ; (rax:x1) = a[0]*a[1]*2 adc rax,rax adc %%x3, 0 mov qword [%%pDst+sizeof(qword)*0], %%x0 add %%x1, rdx mov qword [%%pDst+sizeof(qword)*1], %%x1 adc %%x2, rax mov qword [%%pDst+sizeof(qword)*2], %%x2 adc %%x3, 0 mov qword [%%pDst+sizeof(qword)*3], %%x3 %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_2,PRIVATE SQR_128 rdi, rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx, rbx, rbp ret ENDFUNC sqr_2 ;; ;; 3*qword squarer ;; %macro SQR_192 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov rdx, [%%pA] ;; a[0]*{a[1],a[2]} gsmulx %%x1, %%x0, [%%pA+sizeof(qword)*1] gsmulx %%x2, rax,[%%pA+sizeof(qword)*2] add %%x1, rax adc %%x2, 0 mov rdx, [%%pA+sizeof(qword)*1] ;; a[1]*a[2] gsmulx %%x3, rax, [%%pA+sizeof(qword)*2] add %%x2, rax adc %%x3, 0 xor %%A, %%A ;; square a[0],a[1],a[2] and add double x0,x1,x2,x3 mov rdx, [%%pA+sizeof(qword)*0] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, %%x0 gsadox rdx, %%x0 mov qword [%%pDst+sizeof(qword)], rdx mov rdx, [%%pA+sizeof(qword)*1] gsmulx rdx, rax, rdx gsadcx rax, %%x1 gsadox rax, %%x1 mov qword [%%pDst+sizeof(qword)*2], rax gsadcx rdx, %%x2 gsadox rdx, %%x2 mov qword [%%pDst+sizeof(qword)*3], rdx mov rdx, [%%pA+sizeof(qword)*2] gsmulx rdx, rax, rdx gsadcx rax, %%x3 gsadox rax, %%x3 mov qword [%%pDst+sizeof(qword)*4], rax gsadcx rdx, %%A gsadox rdx, %%A mov qword [%%pDst+sizeof(qword)*5], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_3,PRIVATE SQR_192 rdi,rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx,rbx,rbp ret ENDFUNC sqr_3 ;; ;; 4*qword squarer ;; %macro SQR_256 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; 1-st pass a[0]*{a[1],a[2],a[3]} mov rdx, [%%pA] gsmulx %%x1, %%x0, [%%pA+sizeof(qword)*1] xor %%A, %%A gsmulx %%x2, rax,[%%pA+sizeof(qword)*2] add %%x1, rax gsmulx %%x3, rax,[%%pA+sizeof(qword)*3] adc %%x2, rax adc %%x3, 0 ;; 2-nd pass a[1]*{a[2],a[3]} mov rdx, [%%pA+sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] gsadcx %%x2, rax gsadox %%x3, %%t0 gsmulx %%x4, rax, [%%pA+sizeof(qword)*3] gsadcx %%x3, rax gsadox %%x4, %%A adc %%x4, 0 ;; 3-rd pass a[2]*a[3] mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%x5, rax, [%%pA+sizeof(qword)*3] add %%x4, rax adc %%x5, 0 ;; square a[0],...,a[3] and add double x0,...,,x5 mov rdx, [%%pA+sizeof(qword)*0] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, %%x0 gsadox rdx, %%x0 mov qword [%%pDst+sizeof(qword)], rdx mov rdx, [%%pA+sizeof(qword)*1] gsmulx rdx, rax, rdx gsadcx rax, %%x1 gsadox rax, %%x1 mov qword [%%pDst+sizeof(qword)*2], rax gsadcx rdx, %%x2 gsadox rdx, %%x2 mov qword [%%pDst+sizeof(qword)*3], rdx mov rdx, [%%pA+sizeof(qword)*2] gsmulx rdx, rax, rdx gsadcx rax, %%x3 gsadox rax, %%x3 mov qword [%%pDst+sizeof(qword)*4], rax gsadcx rdx, %%x4 gsadox rdx, %%x4 mov qword [%%pDst+sizeof(qword)*5], rdx mov rdx, [%%pA+sizeof(qword)*3] gsmulx rdx, rax, rdx gsadcx rax, %%x5 gsadox rax, %%x5 mov qword [%%pDst+sizeof(qword)*6], rax gsadcx rdx, %%A gsadox rdx, %%A mov qword [%%pDst+sizeof(qword)*7], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_4,PRIVATE SQR_256 rdi,rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx,rbx,rbp ret ENDFUNC sqr_4 ;; ;; 5*qword squarer ;; %macro SQR_320 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; 1-st pass a[0]*{a[1],...,a[4]} mov rdx, [%%pA] gsmulx %%x1, %%x0, [%%pA+sizeof(qword)*1] xor %%A, %%A gsmulx %%x2, rax,[%%pA+sizeof(qword)*2] add %%x1, rax gsmulx %%x3, rax,[%%pA+sizeof(qword)*3] adc %%x2, rax gsmulx %%x4, rax,[%%pA+sizeof(qword)*4] adc %%x3, rax adc %%x4, 0 ;; 2-nd pass a[1]*{a[2],...,a[4]} mov rdx, [%%pA+sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] gsadcx %%x2, rax gsadox %%x3, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x3, rax gsadox %%x4, %%t0 gsmulx %%x5, rax, [%%pA+sizeof(qword)*4] gsadcx %%x4, rax gsadox %%x5, %%A adc %%x5, 0 ;; 3-rd pass a[2]*{a[3],a[4]} mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*4] gsadcx %%x5, rax gsadox %%x6, %%A adc %%x6, 0 ;; 4-th pass a[3]*a[4] mov rdx, [%%pA+sizeof(qword)*3] gsmulx %%x7, rax, [%%pA+sizeof(qword)*4] add %%x6, rax adc %%x7, 0 ;; square a[0],...,a[4] and add double x0,...,,x7 mov rdx, [%%pA+sizeof(qword)*0] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, %%x0 gsadox rdx, %%x0 mov qword [%%pDst+sizeof(qword)], rdx mov rdx, [%%pA+sizeof(qword)*1] gsmulx rdx, rax, rdx gsadcx rax, %%x1 gsadox rax, %%x1 mov qword [%%pDst+sizeof(qword)*2], rax gsadcx rdx, %%x2 gsadox rdx, %%x2 mov qword [%%pDst+sizeof(qword)*3], rdx mov rdx, [%%pA+sizeof(qword)*2] gsmulx rdx, rax, rdx gsadcx rax, %%x3 gsadox rax, %%x3 mov qword [%%pDst+sizeof(qword)*4], rax gsadcx rdx, %%x4 gsadox rdx, %%x4 mov qword [%%pDst+sizeof(qword)*5], rdx mov rdx, [%%pA+sizeof(qword)*3] gsmulx rdx, rax, rdx gsadcx rax, %%x5 gsadox rax, %%x5 mov qword [%%pDst+sizeof(qword)*6], rax gsadcx rdx, %%x6 gsadox rdx, %%x6 mov qword [%%pDst+sizeof(qword)*7], rdx mov rdx, [%%pA+sizeof(qword)*4] gsmulx rdx, rax, rdx gsadcx rax, %%x7 gsadox rax, %%x7 mov qword [%%pDst+sizeof(qword)*8], rax gsadcx rdx, %%A gsadox rdx, %%A mov qword [%%pDst+sizeof(qword)*9], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_5,PRIVATE SQR_320 rdi,rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx,rbx,rbp ret ENDFUNC sqr_5 ;; ;; 6*qword squarer ;; %macro SQR_384 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; 1-st pass a[0]*{a[1],...,a[5]} mov rdx, [%%pA] gsmulx %%x1, %%x0, [%%pA+sizeof(qword)*1] xor %%A, %%A gsmulx %%x2, rax,[%%pA+sizeof(qword)*2] add %%x1, rax gsmulx %%x3, rax,[%%pA+sizeof(qword)*3] adc %%x2, rax gsmulx %%x4, rax,[%%pA+sizeof(qword)*4] adc %%x3, rax gsmulx %%x5, rax,[%%pA+sizeof(qword)*5] adc %%x4, rax adc %%x5, 0 ;; 2-nd pass a[1]*{a[2],...,a[5]} mov rdx, [%%pA+sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] gsadcx %%x2, rax gsadox %%x3, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x3, rax gsadox %%x4, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%x6, rax, [%%pA+sizeof(qword)*5] gsadcx %%x5, rax gsadox %%x6, %%A adc %%x6, 0 ;; 3-rd pass a[2]*{a[3],a[4],a[5]} mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x5, rax gsadox %%x6, %%t0 gsmulx %%x7, rax, [%%pA+sizeof(qword)*5] gsadcx %%x6, rax gsadox %%x7, %%A adc %%x7, 0 ;; 4-th pass a[3]*{a[4],a[5]} mov rdx, [%%pA+sizeof(qword)*3] gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x6, rax gsadox %%x7, %%t0 gsmulx %%x8, rax, [%%pA+sizeof(qword)*5] gsadcx %%x7, rax gsadox %%x8, %%A adc %%x8, 0 ;; 5-th pass a[4]*a[5] mov rdx, [%%pA+sizeof(qword)*4] gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] add %%x8, rax adc %%t0, 0 ;; square a[0],...,a[5] and add double x0,...,x7,x8,t0 mov rdx, [%%pA+sizeof(qword)*0] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, %%x0 gsadox rdx, %%x0 mov qword [%%pDst+sizeof(qword)], rdx mov rdx, [%%pA+sizeof(qword)*1] gsmulx rdx, rax, rdx gsadcx rax, %%x1 gsadox rax, %%x1 mov qword [%%pDst+sizeof(qword)*2], rax gsadcx rdx, %%x2 gsadox rdx, %%x2 mov qword [%%pDst+sizeof(qword)*3], rdx mov rdx, [%%pA+sizeof(qword)*2] gsmulx rdx, rax, rdx gsadcx rax, %%x3 gsadox rax, %%x3 mov qword [%%pDst+sizeof(qword)*4], rax gsadcx rdx, %%x4 gsadox rdx, %%x4 mov qword [%%pDst+sizeof(qword)*5], rdx mov rdx, [%%pA+sizeof(qword)*3] gsmulx rdx, rax, rdx gsadcx rax, %%x5 gsadox rax, %%x5 mov qword [%%pDst+sizeof(qword)*6], rax gsadcx rdx, %%x6 gsadox rdx, %%x6 mov qword [%%pDst+sizeof(qword)*7], rdx mov rdx, [%%pA+sizeof(qword)*4] gsmulx rdx, rax, rdx gsadcx rax, %%x7 gsadox rax, %%x7 mov qword [%%pDst+sizeof(qword)*8], rax gsadcx rdx, %%x8 gsadox rdx, %%x8 mov qword [%%pDst+sizeof(qword)*9], rdx mov rdx, [%%pA+sizeof(qword)*5] gsmulx rdx, rax, rdx gsadcx rax, %%t0 gsadox rax, %%t0 mov qword [%%pDst+sizeof(qword)*10], rax gsadcx rdx, %%A gsadox rdx, %%A mov qword [%%pDst+sizeof(qword)*11], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_6,PRIVATE SQR_384 rdi,rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx,rbx,rbp ret ENDFUNC sqr_6 ;; ;; 7*qword squarer ;; %macro SQR_448 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; 1-st pass a[0]*{a[1],...,a[6]} mov rdx, [%%pA] gsmulx %%x1, %%x0, [%%pA+sizeof(qword)*1] xor %%A, %%A gsmulx %%x2, rax,[%%pA+sizeof(qword)*2] add %%x1, rax gsmulx %%x3, rax,[%%pA+sizeof(qword)*3] adc %%x2, rax gsmulx %%x4, rax,[%%pA+sizeof(qword)*4] adc %%x3, rax gsmulx %%x5, rax,[%%pA+sizeof(qword)*5] adc %%x4, rax gsmulx %%x6, rax,[%%pA+sizeof(qword)*6] adc %%x5, rax adc %%x6, 0 mov [%%pDst+sizeof(qword)*1], %%x0 mov [%%pDst+sizeof(qword)*2], %%x1 ;; 2-nd pass a[1]*{a[2],...,a[6]} mov rdx, [%%pA+sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] gsadcx %%x2, rax gsadox %%x3, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x3, rax gsadox %%x4, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x5, rax gsadox %%x6, %%t0 gsmulx %%x7, rax, [%%pA+sizeof(qword)*6] gsadcx %%x6, rax gsadox %%x7, %%A adc %%x7, 0 mov [%%pDst+sizeof(qword)*3], %%x2 ;; 3-rd pass a[2]*{a[3],...,a[6]} mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x5, rax gsadox %%x6, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x6, rax gsadox %%x7, %%t0 gsmulx %%x8, rax, [%%pA+sizeof(qword)*6] gsadcx %%x7, rax gsadox %%x8, %%A adc %%x8, 0 ;; 4-rd pass a[3]*{a[4],...,a[6]} mov rdx, [%%pA+sizeof(qword)*3] gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x6, rax gsadox %%x7, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x7, rax gsadox %%x8, %%t0 gsmulx %%x0, rax, [%%pA+sizeof(qword)*6] gsadcx %%x8, rax gsadox %%x0, %%A adc %%x0, 0 ;; 5-rd pass a[4]*{a[5],a[6]} mov rdx, [%%pA+sizeof(qword)*4] gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x8, rax gsadox %%x0, %%t0 gsmulx %%x1, rax, [%%pA+sizeof(qword)*6] gsadcx %%x0, rax gsadox %%x1, %%A adc %%x1, 0 ;; 6-rd pass a[5]*a[6] mov rdx, [%%pA+sizeof(qword)*5] gsmulx %%x2, rax, [%%pA+sizeof(qword)*6] add %%x1, rax adc %%x2, 0 ;; square a[0],...,a[5] and add double mov rdx, [%%pA+sizeof(qword)*0] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, qword [%%pDst+sizeof(qword)] gsadox rdx, qword [%%pDst+sizeof(qword)] mov qword [%%pDst+sizeof(qword)], rdx mov rdx, [%%pA+sizeof(qword)*1] gsmulx rdx, rax, rdx gsadcx rax, qword [%%pDst+sizeof(qword)*2] gsadox rax, qword [%%pDst+sizeof(qword)*2] mov qword [%%pDst+sizeof(qword)*2], rax gsadcx rdx, qword [%%pDst+sizeof(qword)*3] gsadox rdx, qword [%%pDst+sizeof(qword)*3] mov qword [%%pDst+sizeof(qword)*3], rdx mov rdx, [%%pA+sizeof(qword)*2] gsmulx rdx, rax, rdx gsadcx rax, %%x3 gsadox rax, %%x3 mov qword [%%pDst+sizeof(qword)*4], rax gsadcx rdx, %%x4 gsadox rdx, %%x4 mov qword [%%pDst+sizeof(qword)*5], rdx mov rdx, [%%pA+sizeof(qword)*3] gsmulx rdx, rax, rdx gsadcx rax, %%x5 gsadox rax, %%x5 mov qword [%%pDst+sizeof(qword)*6], rax gsadcx rdx, %%x6 gsadox rdx, %%x6 mov qword [%%pDst+sizeof(qword)*7], rdx mov rdx, [%%pA+sizeof(qword)*4] gsmulx rdx, rax, rdx gsadcx rax, %%x7 gsadox rax, %%x7 mov qword [%%pDst+sizeof(qword)*8], rax gsadcx rdx, %%x8 gsadox rdx, %%x8 mov qword [%%pDst+sizeof(qword)*9], rdx mov rdx, [%%pA+sizeof(qword)*5] gsmulx rdx, rax, rdx gsadcx rax, %%x0 gsadox rax, %%x0 mov qword [%%pDst+sizeof(qword)*10], rax gsadcx rdx, %%x1 gsadox rdx, %%x1 mov qword [%%pDst+sizeof(qword)*11], rdx mov rdx, [%%pA+sizeof(qword)*6] gsmulx rdx, rax, rdx gsadcx rax, %%x2 gsadox rax, %%x2 mov qword [%%pDst+sizeof(qword)*12], rax gsadcx rdx, %%A gsadox rdx, %%A mov qword [%%pDst+sizeof(qword)*13], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_7,PRIVATE SQR_448 rdi,rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx,rbx,rbp ret ENDFUNC sqr_7 ;; ;; 8*qword squarer ;; %macro SQR_512 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; 1-st pass a[0]*{a[1],...,a[7]} mov rdx, [%%pA] gsmulx %%x1, %%x0, [%%pA+sizeof(qword)*1] xor %%A, %%A gsmulx %%x2, rax,[%%pA+sizeof(qword)*2] add %%x1, rax gsmulx %%x3, rax,[%%pA+sizeof(qword)*3] adc %%x2, rax gsmulx %%x4, rax,[%%pA+sizeof(qword)*4] adc %%x3, rax gsmulx %%x5, rax,[%%pA+sizeof(qword)*5] adc %%x4, rax gsmulx %%x6, rax,[%%pA+sizeof(qword)*6] adc %%x5, rax gsmulx %%x7, rax,[%%pA+sizeof(qword)*7] adc %%x6, rax adc %%x7, 0 mov [%%pDst+sizeof(qword)*1], %%x0 mov [%%pDst+sizeof(qword)*2], %%x1 ;; 2-nd pass a[1]*{a[2],...,a[7]} mov rdx, [%%pA+sizeof(qword)*1] gsmulx %%t0, rax, [%%pA+sizeof(qword)*2] gsadcx %%x2, rax gsadox %%x3, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x3, rax gsadox %%x4, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x5, rax gsadox %%x6, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*6] gsadcx %%x6, rax gsadox %%x7, %%t0 gsmulx %%x8, rax, [%%pA+sizeof(qword)*7] gsadcx %%x7, rax gsadox %%x8, %%A adc %%x8, 0 mov [%%pDst+sizeof(qword)*3], %%x2 mov [%%pDst+sizeof(qword)*4], %%x3 ;; 3-rd pass a[2]*{a[3],...,a[7]} mov rdx, [%%pA+sizeof(qword)*2] gsmulx %%t0, rax, [%%pA+sizeof(qword)*3] gsadcx %%x4, rax gsadox %%x5, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x5, rax gsadox %%x6, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x6, rax gsadox %%x7, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*6] gsadcx %%x7, rax gsadox %%x8, %%t0 gsmulx %%x0, rax, [%%pA+sizeof(qword)*7] gsadcx %%x8, rax gsadox %%x0, %%A adc %%x0, 0 ;; 4-rd pass a[3]*{a[4],...,a[7]} mov rdx, [%%pA+sizeof(qword)*3] gsmulx %%t0, rax, [%%pA+sizeof(qword)*4] gsadcx %%x6, rax gsadox %%x7, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x7, rax gsadox %%x8, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*6] gsadcx %%x8, rax gsadox %%x0, %%t0 gsmulx %%x1, rax, [%%pA+sizeof(qword)*7] gsadcx %%x0, rax gsadox %%x1, %%A adc %%x1, 0 ;; 5-rd pass a[4]*{a[5],...,a[7]} mov rdx, [%%pA+sizeof(qword)*4] gsmulx %%t0, rax, [%%pA+sizeof(qword)*5] gsadcx %%x8, rax gsadox %%x0, %%t0 gsmulx %%t0, rax, [%%pA+sizeof(qword)*6] gsadcx %%x0, rax gsadox %%x1, %%t0 gsmulx %%x2, rax, [%%pA+sizeof(qword)*7] gsadcx %%x1, rax gsadox %%x2, %%A adc %%x2, 0 ;; 6-rd pass a[5]*{a[6],a[7]} mov rdx, [%%pA+sizeof(qword)*5] gsmulx %%t0, rax, [%%pA+sizeof(qword)*6] gsadcx %%x1, rax gsadox %%x2, %%t0 gsmulx %%x3, rax, [%%pA+sizeof(qword)*7] gsadcx %%x2, rax gsadox %%x3, %%A adc %%x3, 0 ;; 7-rd pass a[6]*a[7] mov rdx, [%%pA+sizeof(qword)*6] gsmulx %%t0, rax, [%%pA+sizeof(qword)*7] add %%x3, rax adc %%t0, 0 ;; square a[0],...,a[7] and add double mov rdx, [%%pA+sizeof(qword)*0] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, qword [%%pDst+sizeof(qword)] gsadox rdx, qword [%%pDst+sizeof(qword)] mov qword [%%pDst+sizeof(qword)], rdx mov rdx, [%%pA+sizeof(qword)*1] gsmulx rdx, rax, rdx gsadcx rax, qword [%%pDst+sizeof(qword)*2] gsadox rax, qword [%%pDst+sizeof(qword)*2] mov qword [%%pDst+sizeof(qword)*2], rax gsadcx rdx, qword [%%pDst+sizeof(qword)*3] gsadox rdx, qword [%%pDst+sizeof(qword)*3] mov qword [%%pDst+sizeof(qword)*3], rdx mov rdx, [%%pA+sizeof(qword)*2] gsmulx rdx, rax, rdx gsadcx rax, qword [%%pDst+sizeof(qword)*4] gsadox rax, qword [%%pDst+sizeof(qword)*4] mov qword [%%pDst+sizeof(qword)*4], rax gsadcx rdx, %%x4 gsadox rdx, %%x4 mov qword [%%pDst+sizeof(qword)*5], rdx mov rdx, [%%pA+sizeof(qword)*3] gsmulx rdx, rax, rdx gsadcx rax, %%x5 gsadox rax, %%x5 mov qword [%%pDst+sizeof(qword)*6], rax gsadcx rdx, %%x6 gsadox rdx, %%x6 mov qword [%%pDst+sizeof(qword)*7], rdx mov rdx, [%%pA+sizeof(qword)*4] gsmulx rdx, rax, rdx gsadcx rax, %%x7 gsadox rax, %%x7 mov qword [%%pDst+sizeof(qword)*8], rax gsadcx rdx, %%x8 gsadox rdx, %%x8 mov qword [%%pDst+sizeof(qword)*9], rdx mov rdx, [%%pA+sizeof(qword)*5] gsmulx rdx, rax, rdx gsadcx rax, %%x0 gsadox rax, %%x0 mov qword [%%pDst+sizeof(qword)*10], rax gsadcx rdx, %%x1 gsadox rdx, %%x1 mov qword [%%pDst+sizeof(qword)*11], rdx mov rdx, [%%pA+sizeof(qword)*6] gsmulx rdx, rax, rdx gsadcx rax, %%x2 gsadox rax, %%x2 mov qword [%%pDst+sizeof(qword)*12], rax gsadcx rdx, %%x3 gsadox rdx, %%x3 mov qword [%%pDst+sizeof(qword)*13], rdx mov rdx, [%%pA+sizeof(qword)*7] gsmulx rdx, rax, rdx gsadcx rax, %%t0 gsadox rax, %%t0 mov qword [%%pDst+sizeof(qword)*14], rax gsadcx rdx, %%A gsadox rdx, %%A mov qword [%%pDst+sizeof(qword)*15], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_8,PRIVATE SQR_512 rdi, rsi, r15,r14,r13,r12,r11,r10,r9,r8, rcx, rbx, rbp ret ENDFUNC sqr_8 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SQR_512_TRIANGLE_STEP ; executes single line of upper triangle ; ; Inp:partial sum: x7 x6 x5 x4 x3 x2 x1 x0 ; rdx * pA[] p p p p p p p p p ; Out: x0 x7 x6 x5 x4 x3 x2 x1 ; [dst] %macro SQR_512_TRIANGLE_STEP 14.nolist %xdefine %%HEAD_X %1 %xdefine %%X7 %2 %xdefine %%X6 %3 %xdefine %%X5 %4 %xdefine %%X4 %5 %xdefine %%X3 %6 %xdefine %%X2 %7 %xdefine %%X1 %8 %xdefine %%X0 %9 %xdefine %%TAIL_X %10 %xdefine %%pDst %11 %xdefine %%pA %12 %xdefine %%TMP1 %13 %xdefine %%TMP2 %14 xor rax, rax %ifnempty %%X0 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*0] ; TMP2:TMP1 = rdx * pA[0] gsadcx %%X0, %%TMP1 gsadox %%X1, %%TMP2 %endif %ifnempty %%TAIL_X mov %%pDst, %%TAIL_X %endif %ifnempty %%X1 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*1] ; TMP2:TMP1 = rdx * pA[1] gsadcx %%X1, %%TMP1 gsadox %%X2, %%TMP2 %endif %ifnempty %%X2 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*2] ; TMP2:TMP1 = rdx * pA[2] gsadcx %%X2, %%TMP1 gsadox %%X3, %%TMP2 %endif %ifnempty %%X3 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*3] ; TMP2:TMP1 = rdx * pA[3] gsadcx %%X3, %%TMP1 gsadox %%X4, %%TMP2 %endif %ifnempty %%X4 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*4] ; TMP2:TMP1 = rdx * pA[4] gsadcx %%X4, %%TMP1 gsadox %%X5, %%TMP2 %endif %ifnempty %%X5 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*5] ; TMP2:TMP1 = rdx * pA[5] gsadcx %%X5, %%TMP1 gsadox %%X6, %%TMP2 %endif %ifnempty %%X6 gsmulx %%TMP2,%%TMP1, [%%pA+sizeof(qword)*6] ; TMP2:TMP1 = rdx * pA[6] gsadcx %%X6, %%TMP1 gsadox %%X7, %%TMP2 %endif %ifnempty %%X7 gsmulx %%HEAD_X,%%TMP1, [%%pA+sizeof(qword)*7] ; X0:TMP1 = rdx * pA[7] gsadcx %%X7, %%TMP1 gsadox %%HEAD_X, rax adc %%HEAD_X, 0 %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; square and add diagonal terms ; ;; rdi = dst ;; rsi = src ;; rcx = src length %macro FINALIZE_FIX 3.nolist %xdefine %%N %1 %xdefine %%pDst %2 %xdefine %%pSrc %3 xor rax, rax mov rdx, qword [%%pSrc] gsmulx rdx, rax, rdx mov qword [%%pDst], rax gsadcx rdx, qword [%%pDst+sizeof(qword)] gsadox rdx, qword [%%pDst+sizeof(qword)] mov qword [rdi+sizeof(qword)], rdx %assign %%i 1 %rep (%%N-2) mov rdx, qword [%%pSrc+%%i*sizeof(qword)] gsmulx rdx, rax, rdx gsadcx rax, qword [%%pDst+(2*%%i)*sizeof(qword)] gsadox rax, qword [%%pDst+(2*%%i)*sizeof(qword)] mov qword [%%pDst+(2*%%i)*sizeof(qword)], rax gsadcx rdx, qword [%%pDst+(2*%%i+1)*sizeof(qword)] gsadox rdx, qword [%%pDst+(2*%%i+1)*sizeof(qword)] mov qword [rdi+(2*%%i+1)*sizeof(qword)], rdx %assign %%i %%i+1 %endrep mov rdx, qword [%%pSrc+(%%N-1)*sizeof(qword)] gsmulx rdx, rax, rdx gsadcx rax, qword [%%pDst+(2*%%N-2)*sizeof(qword)] gsadox rax, qword [%%pDst+(2*%%N-2)*sizeof(qword)] mov qword [%%pDst+(2*%%N-2)*sizeof(qword)], rax mov rax, dword 0 gsadcx rdx, rax gsadox rdx, rax mov qword [rdi+(2*%%N-1)*sizeof(qword)], rdx %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC finalize,PRIVATE push rcx xor rax, rax mov rdx, qword [rsi] gsmulx rdx, rax, rdx lea rsi, [rsi+sizeof(qword)] mov qword [rdi], rax gsadcx rdx, qword [rdi+sizeof(qword)] gsadox rdx, qword [rdi+sizeof(qword)] mov qword [rdi+sizeof(qword)], rdx lea rdi, [rdi+sizeof(qword)*2] lea rcx, [rcx-2] .next_sqr: mov rdx, qword [rsi] gsmulx rdx, rax, rdx lea rsi, [rsi+sizeof(qword)] gsadcx rax, qword [rdi] gsadox rax, qword [rdi] mov qword [rdi], rax gsadcx rdx, qword [rdi+sizeof(qword)] gsadox rdx, qword [rdi+sizeof(qword)] mov qword [rdi+sizeof(qword)], rdx lea rdi, [rdi+sizeof(qword)*2] lea rcx, [rcx-1] jrcxz .last_sqr jmp .next_sqr .last_sqr: mov rdx, qword [rsi] gsmulx rdx, rax, rdx gsadcx rax, qword [rdi] gsadox rax, qword [rdi] mov qword [rdi], rax mov rax, dword 0 gsadcx rdx, rax gsadox rdx, rax mov qword [rdi+sizeof(qword)], rdx pop rcx lea rax, [rcx*sizeof(qword)-sizeof(qword)] sub rsi, rax sub rdi, rax sub rdi, rax ret ENDFUNC finalize ;; ;; 8*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr8_triangle,PRIVATE ;; A[0]*A[1..7] mov rdx, [rsi+sizeof(qword)*0] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11,r10, r9, , r8, [rdi+sizeof(qword)*0],rsi, rbx,rbp ;; A[1]*A[2..7] mov rdx, [rsi+sizeof(qword)*1] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13,r12,r11, , , r9, [rdi+sizeof(qword)*1],rsi, rbx,rbp ;; A[2]*A[3..7] mov rdx, [rsi+sizeof(qword)*2] SQR_512_TRIANGLE_STEP r10, r9, r8,r15,r14,r13, , , , r10, [rdi+sizeof(qword)*2],rsi, rbx,rbp ;; A[3]*A[4..7] mov rdx, [rsi+sizeof(qword)*3] SQR_512_TRIANGLE_STEP r11, r10, r9, r8,r15, , , , , r11, [rdi+sizeof(qword)*3],rsi, rbx,rbp ;; A[4]*A[5..7] mov rdx, [rsi+sizeof(qword)*4] SQR_512_TRIANGLE_STEP r12, r11,r10, r9, , , , , , r12, [rdi+sizeof(qword)*4],rsi, rbx,rbp ;; A[5]*A[6..7] mov rdx, [rsi+sizeof(qword)*5] SQR_512_TRIANGLE_STEP r13, r12,r11, , , , , , , r13, [rdi+sizeof(qword)*5],rsi, rbx,rbp ;; A[6]*A[7] mov rdx, [rsi+sizeof(qword)*6] SQR_512_TRIANGLE_STEP r14, r13, , , , , , , , r14, [rdi+sizeof(qword)*6],rsi, rbx,rbp ret ENDFUNC sqr8_triangle ;; ;; 9*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_9,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 mov qword [rdi+sizeof(qword)*(1+0)], r8 mov qword [rdi+sizeof(qword)*(1+1)], r9 mov qword [rdi+sizeof(qword)*(1+2)], r10 mov qword [rdi+sizeof(qword)*(1+3)], r11 mov qword [rdi+sizeof(qword)*(1+4)], r12 mov qword [rdi+sizeof(qword)*(1+5)], r13 mov qword [rdi+sizeof(qword)*(1+6)], r14 mov qword [rdi+sizeof(qword)*(1+7)], r15 xor rbx, rbx mov qword [rdi+sizeof(qword)*(1+8)], rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 9, rdi, rsi ret ENDFUNC sqr_9 ;; ;; 10*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_10,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 mov qword [rdi+sizeof(qword)*(2+0)], r8 mov qword [rdi+sizeof(qword)*(2+1)], r9 mov qword [rdi+sizeof(qword)*(2+2)], r10 mov qword [rdi+sizeof(qword)*(2+3)], r11 mov qword [rdi+sizeof(qword)*(2+4)], r12 mov qword [rdi+sizeof(qword)*(2+5)], r13 mov qword [rdi+sizeof(qword)*(2+6)], r14 mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15, , , , , , , , , , {rsi+sizeof(qword)*2}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(2+7)], r15 mov qword [rdi+sizeof(qword)*(2+8)], r8 mov qword [rdi+sizeof(qword)*(2+9)], rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 10, rdi, rsi ret ENDFUNC sqr_10 ;; ;; 10*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_11,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 add rdi, sizeof(qword)*1 add rcx, sizeof(qword)*1 call mla_8x2 sub rdi, sizeof(qword)*1 sub rcx, sizeof(qword)*1 mov qword [rdi+sizeof(qword)*(3+0)], r8 mov qword [rdi+sizeof(qword)*(3+1)], r9 mov qword [rdi+sizeof(qword)*(3+2)], r10 mov qword [rdi+sizeof(qword)*(3+3)], r11 mov qword [rdi+sizeof(qword)*(3+4)], r12 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14, , , , , , , r13,[rdi+sizeof(qword)*(3+5)],{rsi+sizeof(qword)*3}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8, , , , , , , , r14,[rdi+sizeof(qword)*(3+6)],{rsi+sizeof(qword)*3}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(3+7)], r15 mov qword [rdi+sizeof(qword)*(3+8)], r8 mov qword [rdi+sizeof(qword)*(3+9)], r9 mov qword [rdi+sizeof(qword)*(3+10)],rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 11, rdi, rsi ret ENDFUNC sqr_11 ;; ;; 12*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_12,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*2 sub rcx, sizeof(qword)*2 mov qword [rdi+sizeof(qword)*(4+0)], r8 mov qword [rdi+sizeof(qword)*(4+1)], r9 mov qword [rdi+sizeof(qword)*(4+2)], r10 mov qword [rdi+sizeof(qword)*(4+3)], r11 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13, , , , , , r12,[rdi+sizeof(qword)*(4+4)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15, , , , , , , r13,[rdi+sizeof(qword)*(4+5)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, , , , , , , , r14,[rdi+sizeof(qword)*(4+6)],{rsi+sizeof(qword)*4}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(4+7)], r15 mov qword [rdi+sizeof(qword)*(4+8)], r8 mov qword [rdi+sizeof(qword)*(4+9)], r9 mov qword [rdi+sizeof(qword)*(4+10)],r10 mov qword [rdi+sizeof(qword)*(4+11)],rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 12, rdi, rsi ret ENDFUNC sqr_12 ;; ;; 13*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_13,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*3 sub rcx, sizeof(qword)*3 mov qword [rdi+sizeof(qword)*(5+0)], r8 mov qword [rdi+sizeof(qword)*(5+1)], r9 mov qword [rdi+sizeof(qword)*(5+2)], r10 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12, , , , , r11,[rdi+sizeof(qword)*(5+3)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14, , , , , , r12,[rdi+sizeof(qword)*(5+4)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8, , , , , , , r13,[rdi+sizeof(qword)*(5+5)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, , , , , , , , r14,[rdi+sizeof(qword)*(5+6)],{rsi+sizeof(qword)*5}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(5+7)], r15 mov qword [rdi+sizeof(qword)*(5+8)], r8 mov qword [rdi+sizeof(qword)*(5+9)], r9 mov qword [rdi+sizeof(qword)*(5+10)],r10 mov qword [rdi+sizeof(qword)*(5+11)],r11 mov qword [rdi+sizeof(qword)*(5+12)],rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 13, rdi, rsi ret ENDFUNC sqr_13 ;; ;; 14*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_14,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*4 sub rcx, sizeof(qword)*4 mov qword [rdi+sizeof(qword)*(6+0)], r8 mov qword [rdi+sizeof(qword)*(6+1)], r9 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11, , , , r10,[rdi+sizeof(qword)*(6+2)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13, , , , , r11,[rdi+sizeof(qword)*(6+3)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15, , , , , , r12,[rdi+sizeof(qword)*(6+4)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, , , , , , , r13,[rdi+sizeof(qword)*(6+5)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11, , , , , , , , r14,[rdi+sizeof(qword)*(6+6)],{rsi+sizeof(qword)*6}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(6+7)], r15 mov qword [rdi+sizeof(qword)*(6+8)], r8 mov qword [rdi+sizeof(qword)*(6+9)], r9 mov qword [rdi+sizeof(qword)*(6+10)],r10 mov qword [rdi+sizeof(qword)*(6+11)],r11 mov qword [rdi+sizeof(qword)*(6+12)],r12 mov qword [rdi+sizeof(qword)*(6+13)],rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 14, rdi, rsi ret ENDFUNC sqr_14 ;; ;; 15*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_15,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x1 add rdi, sizeof(qword) add rcx, sizeof(qword) call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*5 sub rcx, sizeof(qword)*5 mov qword [rdi+sizeof(qword)*(7+0)], r8 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11,r10, , , r9, [rdi+sizeof(qword)*(7+1)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13,r12, , , , r10,[rdi+sizeof(qword)*(7+2)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15,r14, , , , , r11,[rdi+sizeof(qword)*(7+3)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, r8, , , , , , r12,[rdi+sizeof(qword)*(7+4)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11,r10, , , , , , , r13,[rdi+sizeof(qword)*(7+5)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*13] SQR_512_TRIANGLE_STEP r13, r12, , , , , , , , r14,[rdi+sizeof(qword)*(7+6)],{rsi+sizeof(qword)*7}, rbx,rbp xor rbx, rbx mov qword [rdi+sizeof(qword)*(7+7)], r15 mov qword [rdi+sizeof(qword)*(7+8)], r8 mov qword [rdi+sizeof(qword)*(7+9)], r9 mov qword [rdi+sizeof(qword)*(7+10)],r10 mov qword [rdi+sizeof(qword)*(7+11)],r11 mov qword [rdi+sizeof(qword)*(7+12)],r12 mov qword [rdi+sizeof(qword)*(7+13)],r13 mov qword [rdi+sizeof(qword)*(7+14)],rbx sub rdi, sizeof(qword)*8 FINALIZE_FIX 15, rdi, rsi ret ENDFUNC sqr_15 ;; ;; 16*qword squarer ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr_16,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 mov rcx, rsi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 xor r15, r15 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 add rdi, sizeof(qword)*2 add rcx, sizeof(qword)*2 call mla_8x2 sub rdi, sizeof(qword)*6 sub rcx, sizeof(qword)*6 add rdi, sizeof(qword)*8 call sqr8_triangle xor rbx, rbx mov qword [rdi+sizeof(qword)*7], r15 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],rbx sub rsi, sizeof(qword)*8 sub rdi, sizeof(qword)*16 FINALIZE_FIX 16, rdi, rsi ret ENDFUNC sqr_16 ;; ;; 9*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr9_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x1 xor rax, rax mov qword [rdi+sizeof(qword)*(1+0)], r8 mov qword [rdi+sizeof(qword)*(1+1)], r9 mov qword [rdi+sizeof(qword)*(1+2)], r10 mov qword [rdi+sizeof(qword)*(1+3)], r11 mov qword [rdi+sizeof(qword)*(1+4)], r12 mov qword [rdi+sizeof(qword)*(1+5)], r13 mov qword [rdi+sizeof(qword)*(1+6)], r14 mov qword [rdi+sizeof(qword)*(1+7)], r15 mov qword [rdi+sizeof(qword)*(1+8)], rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr9_triangle ;; ;; 10*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr10_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x2 mov qword [rdi+sizeof(qword)*(2+0)], r8 mov qword [rdi+sizeof(qword)*(2+1)], r9 mov qword [rdi+sizeof(qword)*(2+2)], r10 mov qword [rdi+sizeof(qword)*(2+3)], r11 mov qword [rdi+sizeof(qword)*(2+4)], r12 mov qword [rdi+sizeof(qword)*(2+5)], r13 mov qword [rdi+sizeof(qword)*(2+6)], r14 mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15, , , , , , , , , , {rsi+sizeof(qword)*2}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(2+7)], r15 mov qword [rdi+sizeof(qword)*(2+8)], r8 mov qword [rdi+sizeof(qword)*(2+9)], rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr10_triangle ;; ;; 11*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr11_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x3 mov qword [rdi+sizeof(qword)*(3+0)], r8 mov qword [rdi+sizeof(qword)*(3+1)], r9 mov qword [rdi+sizeof(qword)*(3+2)], r10 mov qword [rdi+sizeof(qword)*(3+3)], r11 mov qword [rdi+sizeof(qword)*(3+4)], r12 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14, , , , , , , r13,[rdi+sizeof(qword)*(3+5)],{rsi+sizeof(qword)*3}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8, , , , , , , , r14,[rdi+sizeof(qword)*(3+6)],{rsi+sizeof(qword)*3}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(3+7)], r15 mov qword [rdi+sizeof(qword)*(3+8)], r8 mov qword [rdi+sizeof(qword)*(3+9)], r9 mov qword [rdi+sizeof(qword)*(3+10)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr11_triangle ;; ;; 12*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr12_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x4 mov qword [rdi+sizeof(qword)*(4+0)], r8 mov qword [rdi+sizeof(qword)*(4+1)], r9 mov qword [rdi+sizeof(qword)*(4+2)], r10 mov qword [rdi+sizeof(qword)*(4+3)], r11 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13, , , , , , r12,[rdi+sizeof(qword)*(4+4)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15, , , , , , , r13,[rdi+sizeof(qword)*(4+5)],{rsi+sizeof(qword)*4}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, , , , , , , , r14,[rdi+sizeof(qword)*(4+6)],{rsi+sizeof(qword)*4}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(4+7)], r15 mov qword [rdi+sizeof(qword)*(4+8)], r8 mov qword [rdi+sizeof(qword)*(4+9)], r9 mov qword [rdi+sizeof(qword)*(4+10)],r10 mov qword [rdi+sizeof(qword)*(4+11)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr12_triangle ;; ;; 13*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr13_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x5 mov qword [rdi+sizeof(qword)*(5+0)], r8 mov qword [rdi+sizeof(qword)*(5+1)], r9 mov qword [rdi+sizeof(qword)*(5+2)], r10 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12, , , , , r11,[rdi+sizeof(qword)*(5+3)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14, , , , , , r12,[rdi+sizeof(qword)*(5+4)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8, , , , , , , r13,[rdi+sizeof(qword)*(5+5)],{rsi+sizeof(qword)*5}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, , , , , , , , r14,[rdi+sizeof(qword)*(5+6)],{rsi+sizeof(qword)*5}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(5+7)], r15 mov qword [rdi+sizeof(qword)*(5+8)], r8 mov qword [rdi+sizeof(qword)*(5+9)], r9 mov qword [rdi+sizeof(qword)*(5+10)],r10 mov qword [rdi+sizeof(qword)*(5+11)],r11 mov qword [rdi+sizeof(qword)*(5+12)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr13_triangle ;; ;; 14*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr14_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x6 mov qword [rdi+sizeof(qword)*(6+0)], r8 mov qword [rdi+sizeof(qword)*(6+1)], r9 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11, , , , r10,[rdi+sizeof(qword)*(6+2)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13, , , , , r11,[rdi+sizeof(qword)*(6+3)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15, , , , , , r12,[rdi+sizeof(qword)*(6+4)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, , , , , , , r13,[rdi+sizeof(qword)*(6+5)],{rsi+sizeof(qword)*6}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11, , , , , , , , r14,[rdi+sizeof(qword)*(6+6)],{rsi+sizeof(qword)*6}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(6+7)], r15 mov qword [rdi+sizeof(qword)*(6+8)], r8 mov qword [rdi+sizeof(qword)*(6+9)], r9 mov qword [rdi+sizeof(qword)*(6+10)],r10 mov qword [rdi+sizeof(qword)*(6+11)],r11 mov qword [rdi+sizeof(qword)*(6+12)],r12 mov qword [rdi+sizeof(qword)*(6+13)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr14_triangle ;; ;; 15*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr15_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 lea rcx, [rsi+sizeof(qword)*8] add rdi, sizeof(qword)*8 call mla_8x7 mov qword [rdi+sizeof(qword)*(7+0)], r8 ; SQR_512_TRIANGLE_STEP H, p7, p6, p5, p4, p3, p2, p1, p0, T, ,, rbx,rbp ; ------------------------------ mov rdx, qword [rsi+sizeof(qword)*8] SQR_512_TRIANGLE_STEP r8, r15,r14,r13,r12,r11,r10, , , r9, [rdi+sizeof(qword)*(7+1)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*9] SQR_512_TRIANGLE_STEP r9, r8,r15,r14,r13,r12, , , , r10,[rdi+sizeof(qword)*(7+2)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*10] SQR_512_TRIANGLE_STEP r10, r9, r8,r15,r14, , , , , r11,[rdi+sizeof(qword)*(7+3)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*11] SQR_512_TRIANGLE_STEP r11, r10, r9, r8, , , , , , r12,[rdi+sizeof(qword)*(7+4)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*12] SQR_512_TRIANGLE_STEP r12, r11,r10, , , , , , , r13,[rdi+sizeof(qword)*(7+5)],{rsi+sizeof(qword)*7}, rbx,rbp mov rdx, qword [rsi+sizeof(qword)*13] SQR_512_TRIANGLE_STEP r13, r12, , , , , , , , r14,[rdi+sizeof(qword)*(7+6)],{rsi+sizeof(qword)*7}, rbx,rbp xor rax, rax mov qword [rdi+sizeof(qword)*(7+7)], r15 mov qword [rdi+sizeof(qword)*(7+8)], r8 mov qword [rdi+sizeof(qword)*(7+9)], r9 mov qword [rdi+sizeof(qword)*(7+10)],r10 mov qword [rdi+sizeof(qword)*(7+11)],r11 mov qword [rdi+sizeof(qword)*(7+12)],r12 mov qword [rdi+sizeof(qword)*(7+13)],r13 mov qword [rdi+sizeof(qword)*(7+14)],rax sub rdi, sizeof(qword)*8 ret ENDFUNC sqr15_triangle ;; ;; 16*qword triangle ;; align IPP_ALIGN_FACTOR DECLARE_FUNC sqr16_triangle,PRIVATE call sqr8_triangle mov qword [rdi+sizeof(qword)*7], r15 xor r15, r15 mov rcx, rsi add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 call mla_8x8 add rdi, sizeof(qword)*8 call sqr8_triangle xor rax, rax mov qword [rdi+sizeof(qword)*7], r15 mov qword [rdi+sizeof(qword)*8], r8 mov qword [rdi+sizeof(qword)*9], r9 mov qword [rdi+sizeof(qword)*10],r10 mov qword [rdi+sizeof(qword)*11],r11 mov qword [rdi+sizeof(qword)*12],r12 mov qword [rdi+sizeof(qword)*13],r13 mov qword [rdi+sizeof(qword)*14],r14 mov qword [rdi+sizeof(qword)*15],rax sub rsi, sizeof(qword)*8 sub rdi, sizeof(qword)*16 ret ENDFUNC sqr16_triangle sqr_l_basic DQ sqr_1 - sqr_l_basic DQ sqr_2 - sqr_l_basic DQ sqr_3 - sqr_l_basic DQ sqr_4 - sqr_l_basic DQ sqr_5 - sqr_l_basic DQ sqr_6 - sqr_l_basic DQ sqr_7 - sqr_l_basic DQ sqr_8 - sqr_l_basic DQ sqr_9 - sqr_l_basic DQ sqr_10- sqr_l_basic DQ sqr_11- sqr_l_basic DQ sqr_12- sqr_l_basic DQ sqr_13- sqr_l_basic DQ sqr_14- sqr_l_basic DQ sqr_15- sqr_l_basic DQ sqr_16- sqr_l_basic sqrN_triangle DQ sqr9_triangle - sqrN_triangle DQ sqr10_triangle - sqrN_triangle DQ sqr11_triangle - sqrN_triangle DQ sqr12_triangle - sqrN_triangle DQ sqr13_triangle - sqrN_triangle DQ sqr14_triangle - sqrN_triangle DQ sqr15_triangle - sqrN_triangle DQ sqr16_triangle - sqrN_triangle %endif ;; _PCPBNSQR_BASIC_ADCX_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusqrschool.inc000066400000000000000000000176341470420105600273110ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2010 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; BNU squaring support ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MULx1 genaral-case squarer macros ;; ;; dst = src * B epilogue (srcLen=4*n+3) %macro sMULx1_4N_3_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%update_idx %3 %xdefine %%B %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B xor %%T1, %%T1 add %%T0, rax mov qword [%%rDst+sizeof(qword)], %%T0 mov rax, qword [%%rSrc+sizeof(qword)*2] adc %%T1, rdx mul %%B xor %%T2, %%T2 add %%T1, rax mov qword [%%rDst+sizeof(qword)*2], %%T1 mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T2, rdx mul %%B %%update_idx add %%T2, rax mov qword [%%rDst+sizeof(qword)*3], %%T2 ;mov rax, qword [rSrc+idx*sizeof(qword)] adc rdx, 0 mov qword [%%rDst+sizeof(qword)*4], rdx add %%rDst, sizeof(qword) %endmacro ;; dst = src * B epilogue (srcLen=4*n+1) %macro sMULx1_4N_1_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%update_idx %3 %xdefine %%B %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mul %%B %%update_idx add %%T0, rax mov qword [%%rDst+sizeof(qword)*3], %%T0 ;mov rax, qword [rSrc+idx*sizeof(qword)] adc rdx, 0 mov qword [%%rDst+sizeof(qword)*4], rdx add %%rDst, sizeof(qword) %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MULx2 genaral-case multiplier macros ;; ;; dst = src * {B1:B0} epilogue (srcLen=4*n+1) %macro sMULx2_4N_1_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%update_idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%B1 ; {T2:T1} += a[lenA-1]*B1 ;add rDst, sizeof(qword)*2 %%update_idx mov qword [%%rDst+sizeof(qword)*3], %%T0 add %%T1, rax ;mov rax, qword [rSrc+idx*sizeof(qword)] adc rdx, %%T2 mov qword [%%rDst+sizeof(qword)*4], %%T1 mov qword [%%rDst+sizeof(qword)*5], rdx %endmacro ;; dst = src * {B1:B0} epilogue (srcLen=4*n+3) %macro sMULx2_4N_3_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%update_idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%B1 ; {T2:T1} += a[lenA-3]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[LenA-2]*B0 mov qword [%%rDst+sizeof(qword)], %%T0 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx adc %%T3, 0 mul %%B1 ; {T3:T2} += a[lenA-2]*B1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T3, rdx mul %%B0 ; {T0:T3:T2} += a[lenA-1]*B0 mov qword [%%rDst+sizeof(qword)*2], %%T1 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] adc %%T3, rdx adc %%T0, 0 mul %%B1 ; {T0:T3} += a[lenA-1]*B1 ;add rDst, sizeof(qword)*2 %%update_idx mov qword [%%rDst+sizeof(qword)*3], %%T2 add %%T3, rax ;mov rax, qword [rSrc+idx*sizeof(qword)] adc rdx, %%T0 mov qword [%%rDst+sizeof(qword)*4], %%T3 mov qword [%%rDst+sizeof(qword)*5], rdx %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MLAx2 genaral-case multiplier macros ;; ;; ;; B0 = rSrc[-2] ;; B1 = rSrc[-1] ;; inp_vector = rSrc ;; out_vector = rDst %macro sMLAx2_PLOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%B0 %3 %xdefine %%B1 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov %%B0, qword [%%rSrc-2*sizeof(qword)] ; preload a[-2] mov %%B1, qword [%%rSrc-sizeof(qword)] ; and a[i-1] mov rax, %%B1 mul %%B0 ; a[-2]*a[i-1] xor %%T0, %%T0 add qword [%%rDst-sizeof(qword)], rax mov rax, qword [%%rSrc] ; a[i] adc %%T0, rdx mul %%B0 ; B0*a[i] xor %%T1, %%T1 xor %%T2, %%T2 add %%T0, rax mov rax, qword [%%rSrc] ; a[i] adc %%T1, rdx %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+1) %macro sMLAx2_4N_1_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%update_idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%B1 ; {T2:T1} += a[lenA-1]*B1 + r[lenA-1] ;add rDst, sizeof(qword)*2 %%update_idx add %%T0, qword [%%rDst+sizeof(qword)*3] mov qword [%%rDst+sizeof(qword)*3], %%T0 adc %%T1, rax adc rdx, %%T2 ;mov rax, qword [rSrc+idx*sizeof(qword)] mov qword [%%rDst+sizeof(qword)*4], %%T1 mov qword [%%rDst+sizeof(qword)*5], rdx %endmacro ;; dst = + src * {B1:B0} epilogue (srcLen=4*n+3) %macro sMLAx2_4N_3_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%update_idx %3 %xdefine %%B0 %4 %xdefine %%B1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%B1 ; {T2:T1} += a[lenA-3]*B1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] adc %%T2, rdx mul %%B0 ; {T3:T2:T1} += a[LenA-2]*B0 + r[len-3] add %%T0, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T0 adc %%T1, rax adc %%T2, rdx adc %%T3, 0 mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[lenA-2] mul %%B1 ; {T3:T2} += a[lenA-2]*B1 xor %%T0, %%T0 add %%T2, rax adc %%T3, rdx mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B0 ; {T0:T3:T2} += a[lenA-1]*B0 + r[lenA-2] add %%T1, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T1 adc %%T2, rax adc %%T3, rdx adc %%T0, 0 mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[lenA-1] mul %%B1 ; {T0:T3} += a[lenA-1]*B1 + r[lenA-1] ;add rDst, sizeof(qword)*2 %%update_idx add %%T2, qword [%%rDst+sizeof(qword)*3] mov qword [%%rDst+sizeof(qword)*3], %%T2 adc %%T3, rax adc rdx, %%T0 ;mov rax, qword [rSrc+idx*sizeof(qword)] mov qword [%%rDst+sizeof(qword)*4], %%T3 mov qword [%%rDst+sizeof(qword)*5], rdx %endmacro cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusqrschoolm7as.asm000066400000000000000000000774341470420105600301140ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpSqrAdc_BNU_school() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpbnumulschool.inc" %include "pcpbnusqrschool.inc" %include "pcpvariant.inc" %if (_ADCOX_NI_ENABLING_ == _FEATURE_OFF_) || (_ADCOX_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_M7) && (_IPP32E < _IPP32E_L9) ; acc:a1 = src * mem + a1 ; clobbers rax, rdx %macro MULADD0 4.nolist %xdefine %%acc %1 %xdefine %%a1 %2 %xdefine %%src %3 %xdefine %%mem %4 mov rax, %%mem mul %%src xor %%acc, %%acc add %%a1, rax adc %%acc, rdx %endmacro ; acc:a1 = src * mem + a1 + acc ; clobbers rax, rdx %macro MULADD 4.nolist %xdefine %%acc %1 %xdefine %%a1 %2 %xdefine %%src %3 %xdefine %%mem %4 mov rax, %%mem mul %%src add %%a1, rax adc rdx, 0 add %%a1, %%acc adc rdx, 0 mov %%acc, rdx %endmacro ; acc:a1 = src * mem + a1 ; clobbers rax, rdx %macro MULADD1 4.nolist %xdefine %%acc %1 %xdefine %%a1 %2 %xdefine %%src %3 %xdefine %%mem %4 mov rax, %%mem mul %%src add %%a1, rax adc rdx, 0 mov %%acc, rdx %endmacro ; Macro to allow us to do an adc as an adc_0/add pair %macro adc2 2.nolist %xdefine %%a1 %1 %xdefine %%a2 %2 %if 1 adc %%a1, %%a2 %else adc %%a2, 0 add %%a1, %%a2 %endif %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; This version does the first half of the off-diagonal terms, then adds ; in the first half of the diagonal terms, then does the second half. ; This is to avoid the writing and reading of the off-diagonal terms to mem. ; Due to extra overhead in the arithmetic, this may or may not be faster ; than the simple version (which follows) ; ; Input in memory [pA] and also in x7...x0 ; Uses all argument registers plus rax and rdx ; %macro SQR_512 13.nolist %xdefine %%pDst %1 %xdefine %%pA %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; ------------------ ;; first pass 01...07 ;; ------------------ mov %%A, %%x0 mov rax, %%x1 mul %%A mov %%x0, rax mov %%x1, rdx MULADD1 %%x2, %%x1, %%A, %%x2 MULADD1 %%x3, %%x2, %%A, %%x3 MULADD1 %%x4, %%x3, %%A, %%x4 MULADD1 %%x5, %%x4, %%A, %%x5 MULADD1 %%x6, %%x5, %%A, %%x6 MULADD1 %%x7, %%x6, %%A, %%x7 ;; ------------------ ;; second pass 12...16 ;; ------------------ mov %%A, [%%pA + 8*1] xor %%x8, %%x8 mov rax, [%%pA + 8*2] mul %%A add %%x2, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x3, %%A, [%%pA + 8*3] MULADD %%t0, %%x4, %%A, [%%pA + 8*4] MULADD %%t0, %%x5, %%A, [%%pA + 8*5] MULADD %%t0, %%x6, %%A, [%%pA + 8*6] add %%x7, %%t0 adc %%x8, 0 ;; ------------------ ;; third pass 23...25 ;; ------------------ mov %%A, [%%pA + 8*2] mov rax, [%%pA + 8*3] mul %%A add %%x4, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x5, %%A, [%%pA + 8*4] MULADD %%t0, %%x6, %%A, [%%pA + 8*5] add %%x7, %%t0 adc %%x8, 0 ;; ------------------ ;; fourth pass 34 ;; ------------------ mov rax, [%%pA + 8*3] mul qword [%%pA + 8*4] add %%x6, rax adc rdx, 0 add %%x7, rdx adc %%x8, 0 ;; --- double x0...x6 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%A, 0 mov rax, [%%pA + 8*0] mul rax mov [%%pDst + 8*0], rax mov %%t0, rdx mov rax, [%%pA + 8*1] mul rax add %%x0, %%t0 adc %%x1, rax mov [%%pDst + 8*1], %%x0 adc rdx, 0 mov [%%pDst + 8*2], %%x1 mov %%t0, rdx mov rax, [%%pA + 8*2] mul rax mov %%x0, rax mov %%x1, rdx mov rax, [%%pA + 8*3] mul rax add %%x2, %%t0 adc %%x3, %%x0 mov [%%pDst + 8*3], %%x2 adc2 %%x4, %%x1 mov [%%pDst + 8*4], %%x3 adc %%x5, rax mov [%%pDst + 8*5], %%x4 adc2 %%x6, rdx mov [%%pDst + 8*6], %%x5 adc %%A, 0 mov [%%pDst + 8*7], %%x6 ;; ------------------ ;; second pass 17 ;; ------------------ mov rax, [%%pA + 8*1] xor %%x0, %%x0 mul qword [%%pA + 8*7] add %%x7, rax adc rdx, 0 add %%x8, rdx adc %%x0, 0 ;; ------------------ ;; third pass 26...27 ;; ------------------ mov %%x6, [%%pA + 8*2] mov rax, [%%pA + 8*6] mul %%x6 add %%x7, rax adc rdx, 0 add %%x8, rdx adc %%x0, 0 mov rax, [%%pA + 8*7] xor %%x1, %%x1 mul %%x6 add %%x8, rax adc rdx, 0 add %%x0, rdx adc %%x1, 0 ;; ------------------ ;; fourth pass 35...37 ;; ------------------ mov %%x6, [%%pA + 8*3] mov rax, [%%pA + 8*5] mul %%x6 add %%x7, rax adc rdx, 0 add %%x8, rdx adc %%x0, 0 adc %%x1, 0 mov rax, [%%pA + 8*6] mul %%x6 add %%x8, rax adc rdx, 0 add %%x0, rdx adc %%x1, 0 mov rax, [%%pA + 8*7] mul %%x6 add %%x0, rax adc rdx, 0 add %%x1, rdx ;; carry out should be 0 ;; ------------------ ;; f%ifth pass 45...47 ;; ------------------ mov %%x6, [%%pA + 8*4] mov rax, [%%pA + 8*5] mul %%x6 add %%x8, rax adc rdx, 0 mov %%x2, rdx MULADD %%x2, %%x0, %%x6, [%%pA + 8*6] MULADD %%x2, %%x1, %%x6, [%%pA + 8*7] ;; ------------------ ;; sixth pass 56...57 & seventh pass 67 ;; ------------------ mov %%x6, [%%pA + 8*5] mov rax, [%%pA + 8*6] mul %%x6 add %%x1, rax adc rdx, 0 mov %%x3, rdx MULADD %%x3, %%x2, %%x6, [%%pA + 8*7] mov rax, [%%pA + 8*6] mul qword [%%pA + 8*7] add %%x3, rax adc rdx, 0 mov %%x4, rdx ;; --- double x7, x8, x0, ..., x4 xor %%x5, %%x5 add %%x7, %%x7 adc %%x8, %%x8 adc %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, 0 mov rax, [%%pA + 8*4] mul rax add rax, %%A adc rdx, 0 add rax, %%x7 adc rdx, 0 mov [%%pDst + 8*8], rax mov %%A, rdx mov rax, [%%pA + 8*5] mul rax add %%x8, %%A adc %%x0, rax mov [%%pDst + 8*9], %%x8 adc rdx, 0 mov [%%pDst + 8*10], %%x0 mov %%A, rdx mov rax, [%%pA + 8*6] mul rax mov %%x7, rax mov %%x8, rdx mov rax, [%%pA + 8*7] mul rax add %%x1, %%A adc %%x2, %%x7 mov [%%pDst + 8*11], %%x1 adc2 %%x3, %%x8 mov [%%pDst + 8*12], %%x2 adc %%x4, rax mov [%%pDst + 8*13], %%x3 adc2 %%x5, rdx mov [%%pDst + 8*14], %%x4 mov [%%pDst + 8*15], %%x5 %endmacro %macro SQR_448 13.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; ------------------ ;; first pass 01...06 ;; ------------------ mov %%A, %%x0 mov rax, %%x1 mul %%A mov %%x0, rax mov %%x1, rdx MULADD1 %%x2, %%x1, %%A, %%x2 MULADD1 %%x3, %%x2, %%A, %%x3 MULADD1 %%x4, %%x3, %%A, %%x4 MULADD1 %%x5, %%x4, %%A, %%x5 MULADD1 %%x6, %%x5, %%A, %%x6 ;; ------------------ ;; second pass 12...16 ;; ------------------ mov %%A, [%%rSrc + sizeof(qword)*1] mov rax, [%%rSrc+ sizeof(qword)*2] mul %%A add %%x2, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x3, %%A, [%%rSrc + sizeof(qword)*3] MULADD %%t0, %%x4, %%A, [%%rSrc + sizeof(qword)*4] MULADD %%t0, %%x5, %%A, [%%rSrc + sizeof(qword)*5] MULADD %%t0, %%x6, %%A, [%%rSrc + sizeof(qword)*6] mov %%x7, %%t0 ;; ------------------ ;; third pass 23...25 ;; ------------------ mov %%A, [%%rSrc + sizeof(qword)*2] xor %%x8, %%x8 mov rax, [%%rSrc + sizeof(qword)*3] mul %%A add %%x4, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x5, %%A, [%%rSrc+ sizeof(qword)*4] MULADD %%t0, %%x6, %%A, [%%rSrc+ sizeof(qword)*5] add %%x7, %%t0 adc %%x8, 0 ;; ------------------ ;; fourth pass 34 ;; ------------------ mov rax, [%%rSrc + sizeof(qword)*3] mul qword [%%rSrc + sizeof(qword)*4] add %%x6, rax adc rdx, 0 add %%x7, rdx adc %%x8, 0 mov rax, [%%rSrc + sizeof(qword)*0] ;; --- double x0...x6 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%A, 0 mul rax ; a[0]^2 mov [%%rDst + sizeof(qword)*0], rax mov rax, [%%rSrc + sizeof(qword)*1] mov %%t0, rdx mul rax ; a[1]^2 add %%x0, %%t0 adc %%x1, rax mov rax, [%%rSrc + sizeof(qword)*2] mov [%%rDst + sizeof(qword)*1], %%x0 adc rdx, 0 mov [%%rDst + sizeof(qword)*2], %%x1 mov %%t0, rdx mul rax ; a[2]^2 add %%x2, %%t0 adc %%x3, rax mov rax, [%%rSrc + sizeof(qword)*3] mov [%%rDst + sizeof(qword)*3], %%x2 adc rdx, 0 mov [%%rDst + sizeof(qword)*4], %%x3 mov %%t0, rdx mul rax ; a[3]^2 add %%x4, %%t0 adc %%x5, rax mov [%%rDst + sizeof(qword)*5], %%x4 adc %%x6, rdx mov [%%rDst + sizeof(qword)*6], %%x5 adc %%A, 0 mov [%%rDst + sizeof(qword)*7], %%x6 ;; ------------------ ;; third pass complete 26 ;; ------------------ mov rax, [%%rSrc + sizeof(qword)*2] xor %%x0, %%x0 mul qword [%%rSrc + sizeof(qword)*6] add %%x7, rax adc rdx, 0 add %%x8, rdx adc %%x0, 0 ;; ------------------ ;; forth pass complete 35...36 ;; ------------------ mov %%x6, [%%rSrc + sizeof(qword)*3] mov rax, [%%rSrc+ sizeof(qword)*5] mul %%x6 add %%x7, rax mov rax, [%%rSrc + sizeof(qword)*6] adc %%x8, rdx adc %%x0, 0 mul %%x6 add %%x8, rax adc %%x0, rdx ;; ------------------ ;; f%ifth pass 45...46 ;; ------------------ mov %%x6, [%%rSrc + sizeof(qword)*4] xor %%x1, %%x1 mov rax, [%%rSrc + sizeof(qword)*5] mul %%x6 add %%x8, rax mov rax, [%%rSrc + sizeof(qword)*6] adc %%x0, rdx adc %%x1, 0 mul %%x6 add %%x0, rax adc %%x1, rdx ;; ------------------ ;; six pass 56 ;; ------------------ mov %%x6, [%%rSrc + sizeof(qword)*5] xor %%x2, %%x2 mov rax, [%%rSrc + sizeof(qword)*6] mul %%x6 add %%x1, rax adc %%x2, rdx mov rax, [%%rSrc + sizeof(qword)*4] ;; --- double x7, x8, x0, x1, x2 xor %%x3, %%x3 add %%x7, %%x7 adc %%x8, %%x8 adc %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, 0 mul rax ; a[4]^2 add %%x7, %%A adc rdx, 0 xor %%A, %%A add %%x7, rax mov rax, [%%rSrc + sizeof(qword)*5] adc %%x8, rdx mov [%%rDst+ sizeof(qword)*8], %%x7 adc %%A, 0 mov [%%rDst + sizeof(qword)*9], %%x8 mul rax ; a[5]^2 add %%x0, %%A adc rdx, 0 xor %%A, %%A add %%x0, rax mov rax, [%%rSrc + sizeof(qword)*6] adc %%x1, rdx mov [%%rDst + sizeof(qword)*10], %%x0 adc %%A, 0 mov [%%rDst + sizeof(qword)*11], %%x1 mul rax ; a[6]^2 add %%x2, %%A adc rdx, 0 add %%x2, rax adc rdx, %%x3 mov [%%rDst + sizeof(qword)*12], %%x2 mov [%%rDst + sizeof(qword)*13], rdx %endmacro %macro SQR_384 13.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov %%A, %%x0 mov rax, %%x1 mul %%A mov %%x0, rax mov %%x1, rdx MULADD1 %%x2, %%x1, %%A, %%x2 MULADD1 %%x3, %%x2, %%A, %%x3 MULADD1 %%x4, %%x3, %%A, %%x4 MULADD1 %%x5, %%x4, %%A, %%x5 mov %%A, qword [%%rSrc+ sizeof(qword)*1] mov rax, qword [%%rSrc+ sizeof(qword)*2] mul %%A add %%x2, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x3, %%A, [%%rSrc + sizeof(qword)*3] MULADD %%t0, %%x4, %%A, [%%rSrc + sizeof(qword)*4] MULADD %%t0, %%x5, %%A, [%%rSrc + sizeof(qword)*5] mov %%x6, %%t0 mov %%A, qword [%%rSrc+ sizeof(qword)*2] mov rax, qword [%%rSrc+ sizeof(qword)*3] mul %%A add %%x4, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x5, %%A, [%%rSrc + sizeof(qword)*4] MULADD %%t0, %%x6, %%A, [%%rSrc + sizeof(qword)*5] mov %%x7, %%t0 mov %%A, qword [%%rSrc+ sizeof(qword)*3] mov rax, qword [%%rSrc+ sizeof(qword)*4] mul %%A xor %%x8, %%x8 add %%x6, rax mov rax, qword [%%rSrc+ sizeof(qword)*5] adc %%x7, rdx adc %%x8, 0 mul %%A mov %%A, qword [%%rSrc+ sizeof(qword)*4] add %%x7, rax mov rax, qword [%%rSrc+ sizeof(qword)*5] adc %%x8, rdx mul %%A xor %%t0, %%t0 add %%x8, rax adc %%t0, rdx mov rax, [%%rSrc + sizeof(qword)*0] ;; --- double x0...x7,x8,t0 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%x7, %%x7 adc %%x8, %%x8 adc %%t0, %%t0 adc %%A, 0 mov qword [rsp], %%A mul rax mov [%%rDst + sizeof(qword)*0], rax mov rax, [%%rSrc + sizeof(qword)*1] ; a[1] mov %%A, rdx mul rax add %%x0, %%A adc %%x1, rax mov rax, [%%rSrc + sizeof(qword)*2] ; a[2] mov [%%rDst + sizeof(qword)*1], %%x0 adc rdx, 0 mov [%%rDst + sizeof(qword)*2], %%x1 mov %%A, rdx mul rax add %%x2, %%A adc %%x3, rax mov rax, [%%rSrc + sizeof(qword)*3] ; a[3] mov [%%rDst + sizeof(qword)*3], %%x2 adc rdx, 0 mov [%%rDst + sizeof(qword)*4], %%x3 mov %%A, rdx mul rax add %%x4, %%A adc %%x5, rax mov rax, [%%rSrc + sizeof(qword)*4] ; a[4] mov [%%rDst + sizeof(qword)*5], %%x4 adc rdx, 0 mov [%%rDst + sizeof(qword)*6], %%x5 mov %%A, rdx mul rax add %%x6, %%A adc %%x7, rax mov rax, [%%rSrc + sizeof(qword)*5] ; a[5] mov [%%rDst + sizeof(qword)*7], %%x6 adc rdx, 0 mov [%%rDst + sizeof(qword)*8], %%x7 mov %%A, rdx mul rax add %%x8, %%A adc %%t0, rax mov [%%rDst + sizeof(qword)*9], %%x8 adc rdx, qword [rsp] mov [%%rDst + sizeof(qword)*10], %%t0 mov [%%rDst + sizeof(qword)*11], rdx %endmacro %macro SQR_320 13.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov %%A, %%x0 mov rax, %%x1 mul %%A mov %%x0, rax mov %%x1, rdx MULADD1 %%x2, %%x1, %%A, %%x2 MULADD1 %%x3, %%x2, %%A, %%x3 MULADD1 %%x4, %%x3, %%A, %%x4 mov %%A, qword [%%rSrc+ sizeof(qword)*1] mov rax, qword [%%rSrc+ sizeof(qword)*2] mul %%A add %%x2, rax adc rdx, 0 mov %%t0, rdx MULADD %%t0, %%x3, %%A, [%%rSrc + sizeof(qword)*3] MULADD %%t0, %%x4, %%A, [%%rSrc + sizeof(qword)*4] mov %%x5, %%t0 mov %%A, qword [%%rSrc+ sizeof(qword)*2] mov rax, qword [%%rSrc+ sizeof(qword)*3] mul %%A xor %%x6, %%x6 add %%x4, rax mov rax, qword [%%rSrc+ sizeof(qword)*4] adc %%x5, rdx adc %%x6, 0 mul %%A mov %%A, qword [%%rSrc+ sizeof(qword)*3] add %%x5, rax mov rax, qword [%%rSrc+ sizeof(qword)*4] adc %%x6, rdx mul %%A xor %%x7, %%x7 add %%x6, rax adc %%x7, rdx mov rax, [%%rSrc + sizeof(qword)*0] ;; --- double x0...x5 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%x6, %%x6 adc %%x7, %%x7 adc %%A, 0 mul rax mov [%%rDst + sizeof(qword)*0], rax mov rax, [%%rSrc + sizeof(qword)*1] mov %%t0, rdx mul rax add %%x0, %%t0 adc %%x1, rax mov rax, [%%rSrc + sizeof(qword)*2] mov [%%rDst + sizeof(qword)*1], %%x0 adc rdx, 0 mov [%%rDst + sizeof(qword)*2], %%x1 mov %%t0, rdx mul rax add %%x2, %%t0 adc %%x3, rax mov rax, [%%rSrc + sizeof(qword)*3] mov [%%rDst + sizeof(qword)*3], %%x2 adc rdx, 0 mov [%%rDst + sizeof(qword)*4], %%x3 mov %%t0, rdx mul rax add %%x4, %%t0 adc %%x5, rax mov rax, [%%rSrc + sizeof(qword)*4] mov [%%rDst + sizeof(qword)*5], %%x4 adc rdx, 0 mov [%%rDst + sizeof(qword)*6], %%x5 mov %%t0, rdx mul rax add %%x6, %%t0 adc %%x7, rax mov [%%rDst + sizeof(qword)*7], %%x6 adc rdx, 0 mov [%%rDst + sizeof(qword)*8], %%x7 add rdx, %%A mov [%%rDst + sizeof(qword)*9], rdx %endmacro %macro SQR_256 13.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 ;; ------------------ ;; first pass 01...03 ;; ------------------ mov %%A, %%x0 mov rax, %%x1 mul %%A mov %%x0, rax mov %%x1, rdx MULADD1 %%x2, %%x1, %%A, %%x2 MULADD1 %%x3, %%x2, %%A, %%x3 ;; ------------------ ;; second pass 12, 13 ;; ------------------ mov %%A, qword [%%rSrc+ sizeof(qword)*1] mov rax, qword [%%rSrc+ sizeof(qword)*2] mul %%A xor %%x4, %%x4 add %%x2, rax mov rax, qword [%%rSrc+ sizeof(qword)*3] adc %%x3, rdx adc %%x4, 0 mul %%A mov %%A, qword [%%rSrc+ sizeof(qword)*2] add %%x3, rax mov rax, qword [%%rSrc+ sizeof(qword)*3] adc %%x4, rdx ;; ------------------ ;; third pass 23 ;; ------------------ mul %%A xor %%x5, %%x5 add %%x4, rax adc %%x5, rdx mov rax, [%%rSrc + sizeof(qword)*0] ;; --- double x0...x5 xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%x4, %%x4 adc %%x5, %%x5 adc %%A, 0 mul rax mov [%%rDst + sizeof(qword)*0], rax mov rax, [%%rSrc + sizeof(qword)*1] mov %%t0, rdx mul rax add %%x0, %%t0 adc %%x1, rax mov rax, [%%rSrc + sizeof(qword)*2] mov [%%rDst + sizeof(qword)*1], %%x0 adc rdx, 0 mov [%%rDst + sizeof(qword)*2], %%x1 mov %%t0, rdx mul rax add %%x2, %%t0 adc %%x3, rax mov rax, [%%rSrc + sizeof(qword)*3] mov [%%rDst + sizeof(qword)*3], %%x2 adc rdx, 0 mov [%%rDst + sizeof(qword)*4], %%x3 mov %%t0, rdx mul rax add %%x4, %%t0 adc %%x5, rax mov [%%rDst + sizeof(qword)*5], %%x4 adc rdx, 0 mov [%%rDst + sizeof(qword)*6], %%x5 add rdx, %%A mov [%%rDst + sizeof(qword)*7], rdx %endmacro %macro SQR_192 13.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%x7 %3 %xdefine %%x6 %4 %xdefine %%x5 %5 %xdefine %%x4 %6 %xdefine %%x3 %7 %xdefine %%x2 %8 %xdefine %%x1 %9 %xdefine %%x0 %10 %xdefine %%A %11 %xdefine %%x8 %12 %xdefine %%t0 %13 mov %%A, %%x0 mov rax, %%x1 mul %%A mov %%x0, rax mov %%x1, rdx MULADD1 %%x2, %%x1, %%A, %%x2 mov rax, qword [%%rSrc+ sizeof(qword)*1] mul qword [%%rSrc+ sizeof(qword)*2] xor %%x3, %%x3 add %%x2, rax adc %%x3, rdx xor %%A, %%A add %%x0, %%x0 adc %%x1, %%x1 adc %%x2, %%x2 adc %%x3, %%x3 adc %%A, %%A mov rax, qword [%%rSrc+ sizeof(qword)*0] mul rax mov %%x4, rax mov %%x5, rdx mov rax, qword [%%rSrc+ sizeof(qword)*1] mul rax mov %%x6, rax mov %%x7, rdx mov rax, qword [%%rSrc+ sizeof(qword)*2] mul rax mov qword [%%rDst+sizeof(qword)*0], %%x4 add %%x5, %%x0 mov qword [%%rDst+sizeof(qword)*1], %%x5 adc %%x6, %%x1 mov qword [%%rDst+sizeof(qword)*2], %%x6 adc %%x7, %%x2 mov qword [%%rDst+sizeof(qword)*3], %%x7 adc rax, %%x3 mov qword [%%rDst+sizeof(qword)*4], rax adc rdx, %%A mov qword [%%rDst+sizeof(qword)*5], rdx %endmacro segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* Ipp64u cpSqrAdc_BNU_school(Ipp64u* pR; ;* const Ipp64u* pA, int aSize) ;* returns pR[aSize+aSize-1] ;* ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpSqrAdc_BNU_school,PUBLIC %assign LOCAL_FRAME (3*sizeof(qword)) USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 ;; ;; assignment %xdefine rDst rdi %xdefine rSrc rsi %xdefine srcL rdx %xdefine A rcx %xdefine x0 r8 %xdefine x1 r9 %xdefine x2 r10 %xdefine x3 r11 %xdefine x4 r12 %xdefine x5 r13 %xdefine x6 r14 %xdefine x7 r15 %xdefine x8 rbx %xdefine t0 rbp cmp edx, 4 jg .more_then_4 cmp edx, 3 jg .SQR4 je .SQR3 jp .SQR2 align IPP_ALIGN_FACTOR .SQR1: ;; len=1 mov rax, qword [rsi] ; eax = a mul rax ; eax = rL edx = rH mov qword [rdi], rax ; mov rax, rdx ; mov qword [rdi+8], rdx ; mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .SQR2: ;; len=2 mov rax, qword [rsi] ; a[0] mul qword [rsi+sizeof(qword)*1] ; a[0]*a[1] xor A, A mov x2, rax mov x3, rdx mov rax, qword [rsi] ; a[0] mul rax ; (x1:x0) = a[1]^2 add x2, x2 ; (A:x3:x2) = 2*a[0]*a[1] adc x3, x3 adc A, 0 mov x0, rax mov x1, rdx mov rax, qword [rsi+sizeof(qword)*1]; a[1] mul rax ; (rdx:rax) = a[1]^2 mov qword [rdi+sizeof(qword)*0], x0 add x1, x2 mov qword [rdi+sizeof(qword)*1], x1 adc rax, x3 mov qword [rdi+sizeof(qword)*2], rax adc rdx, A mov qword [rdi+sizeof(qword)*3], rdx mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .SQR3: ;; len=3 mov x0, [rSrc+ sizeof(qword)*0] mov x1, [rSrc+ sizeof(qword)*1] mov x2, [rSrc+ sizeof(qword)*2] SQR_192 rDst, rSrc, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .SQR4: ;; len=4 mov x0, [rSrc+ sizeof(qword)*0] mov x1, [rSrc+ sizeof(qword)*1] mov x2, [rSrc+ sizeof(qword)*2] mov x3, [rSrc+ sizeof(qword)*3] SQR_256 rDst, rSrc, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .more_then_4: cmp edx, 8 jg .general_case cmp edx, 7 jg .SQR8 je .SQR7 jp .SQR6 align IPP_ALIGN_FACTOR .SQR5: ;; len=5 mov x0, [rSrc+ sizeof(qword)*0] mov x1, [rSrc+ sizeof(qword)*1] mov x2, [rSrc+ sizeof(qword)*2] mov x3, [rSrc+ sizeof(qword)*3] mov x4, [rSrc+ sizeof(qword)*4] SQR_320 rDst, rSrc, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .SQR6: ;; len=6 mov x0, [rSrc+ sizeof(qword)*0] mov x1, [rSrc+ sizeof(qword)*1] mov x2, [rSrc+ sizeof(qword)*2] mov x3, [rSrc+ sizeof(qword)*3] mov x4, [rSrc+ sizeof(qword)*4] mov x5, [rSrc+ sizeof(qword)*5] SQR_384 rDst, rSrc, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .SQR7: ;; len=7 mov x0, [rSrc+ sizeof(qword)*0] mov x1, [rSrc+ sizeof(qword)*1] mov x2, [rSrc+ sizeof(qword)*2] mov x3, [rSrc+ sizeof(qword)*3] mov x4, [rSrc+ sizeof(qword)*4] mov x5, [rSrc+ sizeof(qword)*5] mov x6, [rSrc+ sizeof(qword)*6] SQR_448 rDst, rSrc, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 mov rax, rdx REST_XMM REST_GPR ret align IPP_ALIGN_FACTOR .SQR8: ;; len=8 mov x0, [rSrc+ sizeof(qword)*0] mov x1, [rSrc+ sizeof(qword)*1] mov x2, [rSrc+ sizeof(qword)*2] mov x3, [rSrc+ sizeof(qword)*3] mov x4, [rSrc+ sizeof(qword)*4] mov x5, [rSrc+ sizeof(qword)*5] mov x6, [rSrc+ sizeof(qword)*6] mov x7, [rSrc+ sizeof(qword)*7] SQR_512 rDst, rSrc, x7, x6, x5, x4, x3, x2, x1, x0, A, x8, t0 mov rax, rdx REST_XMM REST_GPR ret ;********** lenSrcA > 8 ************************************** align IPP_ALIGN_FACTOR .general_case: ;; ;; stack structure: %assign pDst 0 %assign pSrc pDst+sizeof(qword) %assign len pSrc+sizeof(qword) ;; ;; assignment %xdefine B0 r10 ; a[i], a[i+1] %xdefine B1 r11 %xdefine T0 r12 ; temporary %xdefine T1 r13 %xdefine T2 r14 %xdefine T3 r15 %xdefine idx rcx ; indexes %xdefine idxt rbx %xdefine rSrc rsi %xdefine rDst rdi movsxd rdx, edx ; expand length mov [rsp+pDst], rdi ; save parameters mov [rsp+pSrc], rsi mov [rsp+len], rdx mov r8, rdx mov rax, dword 2 mov rbx, dword 1 test r8, 1 cmove rax, rbx ; delta = len&1? 2:1 sub rdx, rax ; len -= delta lea rsi, [rsi+rax*sizeof(qword)] ; A' = A+delta lea rdi, [rdi+rax*sizeof(qword)] ; R' = R+delta lea rsi, [rsi+rdx*sizeof(qword)-4*sizeof(qword)] ; rsi = &A'[len-4] lea rdi, [rdi+rdx*sizeof(qword)-4*sizeof(qword)] ; rdi = &R'[len-4] mov idx, dword 4 ; init sub idx, rdx ; negative index test r8, 1 jnz .init_odd_len_operation ;********** odd number of passes (multiply only) ********************* .init_even_len_operation: mov B0, qword [rsi+idx*sizeof(qword)-sizeof(qword)] ; B0 = a[0] mov rax, qword [rsi+idx*sizeof(qword)] ; a[1] xor T0, T0 cmp idx, 0 jge .skip_mul1 mov idxt, idx MULx1 rdi, rsi, idxt, B0, T0, T1, T2, T3 .skip_mul1: cmp idxt, 1 jne .fin_mulx1_3 ; idx=3 (effective len=4n+1) ; .fin_mulx1_1 ; idx=1 (effective len=4n+3) .fin_mulx1_1: sMULx1_4N_3_ELOG rdi, rsi, {add idx,2}, B0, T0,T1,T2,T3 jmp .odd_pass_pairs .fin_mulx1_3: sMULx1_4N_1_ELOG rdi, rsi, {add idx,2}, B0, T0,T1,T2,T3 jmp .even_pass_pairs ;********** even number of passes (multiply only) ********************* .init_odd_len_operation: mov B0, qword [rsi+idx*sizeof(qword)-2*sizeof(qword)] ; a[0] and a[1] mov B1, qword [rsi+idx*sizeof(qword)-sizeof(qword)] mov rax, B1 ; a[0]*a[1] mul B0 mov qword [rdi+idx*sizeof(qword)-sizeof(qword)], rax mov rax, qword [rsi+idx*sizeof(qword)] ; a[2] mov T0, rdx mul B0 ; a[0]*a[2] xor T1, T1 xor T2, T2 add T0, rax mov rax, qword [rsi+idx*sizeof(qword)] ; a[2] adc T1, rdx cmp idx, 0 jge .skip_mul_nx2 mov idxt, idx MULx2 rdi, rsi, idxt, B0,B1, T0,T1,T2,T3 .skip_mul_nx2: cmp idxt, 1 jnz .fin_mul2x_3 ; idx=3 (effective len=4n+3) ; .fin_mul2x_1 ; idx=1 (effective len=4n+1) .fin_mul2x_1: sMULx2_4N_3_ELOG rdi, rsi, {add idx,2}, B0,B1, T0,T1,T2,T3 add rdi, 2*sizeof(qword) jmp .odd_pass_pairs .fin_mul2x_3: sMULx2_4N_1_ELOG rdi, rsi, {add idx,2}, B0,B1, T0,T1,T2,T3 add rdi, 2*sizeof(qword) align IPP_ALIGN_FACTOR .even_pass_pairs: sMLAx2_PLOG {rdi+idx*sizeof(qword)}, {rsi+idx*sizeof(qword)}, B0,B1, T0,T1,T2,T3 cmp idx, 0 jge .skip1 mov idxt, idx MLAx2 rdi, rsi, idxt, B0,B1, T0,T1,T2,T3 .skip1: sMLAx2_4N_3_ELOG rdi, rsi, {add idx,2}, B0,B1, T0,T1,T2,T3 add rdi, 2*sizeof(qword) .odd_pass_pairs: sMLAx2_PLOG {rdi+idx*sizeof(qword)}, {rsi+idx*sizeof(qword)}, B0,B1, T0,T1,T2,T3 cmp idx, 0 jge .skip2 mov idxt, idx MLAx2 rdi, rsi, idxt, B0,B1, T0,T1,T2,T3 .skip2: sMLAx2_4N_1_ELOG rdi, rsi, {add idx,2}, B0,B1, T0,T1,T2,T3 add rdi, 2*sizeof(qword) cmp idx, 4 jl .even_pass_pairs .add_diag: mov rdi, [rsp+pDst] ; restore parameters mov rsi, [rsp+pSrc] mov rcx, [rsp+len] xor idxt, idxt xor T0, T0 xor T1, T1 lea rax, [rdi+rcx*sizeof(qword)] lea rsi, [rsi+rcx*sizeof(qword)] mov qword [rdi], T0 ; r[0] = 0 mov qword [rax+rcx*sizeof(qword)-sizeof(qword)], T0 ; r[2*len-1] = 0 neg rcx align IPP_ALIGN_FACTOR .add_diag_loop: mov rax, qword [rsi+rcx*sizeof(qword)] ; a[i] mul rax mov T2, qword [rdi] ; r[2*i] mov T3, qword [rdi+sizeof(qword)] ; r[2*i+1] add T0, 1 adc T2, T2 adc T3, T3 sbb T0, T0 add T1, 1 adc T2, rax adc T3, rdx sbb T1, T1 mov qword [rdi], T2 mov qword [rdi+sizeof(qword)], T3 add rdi, sizeof(qword)*2 add rcx, 1 jnz .add_diag_loop mov rax, T3 ; r[2*len-1] REST_XMM REST_GPR ret ENDFUNC cpSqrAdc_BNU_school %endif %endif ;; _ADCOX_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpbnusubm7as.asm000066400000000000000000000264431470420105600266620ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpSub_BNU() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* Ipp64u cpSub_BNU(Ipp64u* pDst, ;* const Ipp64u* pSrc1, ;* const Ipp64u* pSrc2, ;* int len) ;* ;* returns borrow >= 0 ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpSub_BNU,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 4 ; rdi = pDst ; rsi = pSrcA ; rdx = pSrcB ; rcx = len movsxd rcx, ecx ; unsigned length xor rax, rax cmp rcx, 2 jge .SUB_GE2 ;********** lenSrcA == 1 ************************************* add rax, rax mov r8, qword [rsi] ; rsi = a sbb r8, qword [rdx] ; r8 = a-b = s mov qword [rdi], r8 ; save s sbb rax, rax ; jmp .FINAL ;********** lenSrcA == 1 END ******************************** .SUB_GE2: jg .SUB_GT2 ;********** lenSrcA == 2 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 2 END ********************************* .SUB_GT2: cmp rcx, 4 jge .SUB_GE4 ;********** lenSrcA == 3 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 sbb r10, qword [rdx+16] ; r10 = a2-b2 = s2 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 3 END ********************************* .SUB_GE4: jg .SUB_GT4 ;********** lenSrcA == 4 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 sbb r10, qword [rdx+16] ; r10 = a2-b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 sbb r11, qword [rdx+24] ; r11 = a3-b3 = s3 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s2 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 4 END ********************************* .SUB_GT4: cmp rcx, 6 jge .SUB_GE6 ;********** lenSrcA == 5 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 sbb r10, qword [rdx+16] ; r10 = a2-b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 sbb r11, qword [rdx+24] ; r11 = a3-b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 sbb rcx, qword [rdx+32] ; rcx = a4-b4 = s4 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 5 END ********************************* .SUB_GE6: jg .SUB_GT6 ;********** lenSrcA == 6 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 sbb r10, qword [rdx+16] ; r10 = a2-b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 sbb r11, qword [rdx+24] ; r11 = a3-b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 sbb rcx, qword [rdx+32] ; rcx = a4-b4 = s4 mov rsi, qword [rsi+40] ; rsi = a5 sbb rsi, qword [rdx+40] ; rsi = a5-b5 = s5 mov qword [rdi], r8 ; save s0 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 mov qword [rdi+40], rsi ; save s5 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 6 END ********************************* .SUB_GT6: cmp rcx, 8 jge .SUB_GE8 .SUB_EQ7: ;********** lenSrcA == 7 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 sbb r10, qword [rdx+16] ; r10 = a2-b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 sbb r11, qword [rdx+24] ; r11 = a3-b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 sbb rcx, qword [rdx+32] ; rcx = a4-b4 = s4 mov qword [rdi], r8 ; save s0 mov r8, qword [rsi+40] ; r8 = a5 sbb r8, qword [rdx+40] ; r8 = a5-b5 = s5 mov rsi, qword [rsi+48] ; rsi = a6 sbb rsi, qword [rdx+48] ; rsi = a6-b6 = s6 mov qword [rdi+8], r9 ; save s1 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 mov qword [rdi+40], r8 ; save s5 mov qword [rdi+48], rsi ; save s6 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 7 END ********************************* .SUB_GE8: jg .SUB_GT8 ;********** lenSrcA == 8 ************************************* add rax, rax mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0-b0 = s0 mov r9, qword [rsi+8] ; r9 = a1 sbb r9, qword [rdx+8] ; r9 = a1-b1 = s1 mov r10, qword [rsi+16] ; r10 = a2 sbb r10, qword [rdx+16] ; r10 = a2-b2 = s2 mov r11, qword [rsi+24] ; r11 = a3 sbb r11, qword [rdx+24] ; r11 = a3-b3 = s3 mov rcx, qword [rsi+32] ; rcx = a4 sbb rcx, qword [rdx+32] ; rcx = a4-b4 = s4 mov qword [rdi], r8 ; save s0 mov r8, qword [rsi+40] ; r8 = a5 sbb r8, qword [rdx+40] ; r8 = a5-b5 = s5 mov qword [rdi+8], r9 ; save s1 mov r9, qword [rsi+48] ; r9 = a7 sbb r9, qword [rdx+48] ; r9 = a7-b7 = s7 mov rsi, qword [rsi+56] ; rsi = a6 sbb rsi, qword [rdx+56] ; rsi = a6-b6 = s6 mov qword [rdi+16], r10 ; save s2 mov qword [rdi+24], r11 ; save s3 mov qword [rdi+32], rcx ; save s4 mov qword [rdi+40], r8 ; save s5 mov qword [rdi+48], r9 ; save s6 mov qword [rdi+56], rsi ; save s7 sbb rax, rax ; rax = borrow jmp .FINAL ;********** lenSrcA == 8 END ********************************* ;********** lenSrcA > 8 ************************************* .SUB_GT8: mov r8, rax mov rax, rcx ; rax = len and rcx, 3 ; xor rcx, rax ; lea rsi, [rsi+8*rcx] ; lea rdx, [rdx+8*rcx] ; lea rdi, [rdi+8*rcx] ; neg rcx add r8, r8 jmp .SUB_GLOOP align IPP_ALIGN_FACTOR .SUB_GLOOP: mov r8, qword [rsi+8*rcx] ; r8 = a0 mov r9, qword [rsi+8*rcx+8] ; r9 = a1 mov r10, qword [rsi+8*rcx+16] ; r10 = a2 mov r11, qword [rsi+8*rcx+24] ; r11 = a3 sbb r8, qword [rdx+8*rcx] ; r8 = a0+b0 = r0 sbb r9, qword [rdx+8*rcx+8] ; r9 = a1+b1 = r1 sbb r10, qword [rdx+8*rcx+16] ; r10 = a2+b2 = r2 sbb r11, qword [rdx+8*rcx+24] ; r11 = a3+b3 = r3 mov qword [rdi+8*rcx], r8 ; mov qword [rdi+8*rcx+8], r9 ; mov qword [rdi+8*rcx+16], r10 ; mov qword [rdi+8*rcx+24], r11 ; lea rcx, [rcx+4] jrcxz .SUB_LLAST0 jmp .SUB_GLOOP .SUB_LLAST0: sbb rcx, rcx and rax, 3 jz .FIN0 .SUB_LLOOP: test rax, 2 jz .SUB_LLAST1 add rcx, rcx mov r8, qword [rsi] ; r8 = a0 mov r9, qword [rsi+8] ; r9 = a1 sbb r8, qword [rdx] ; r8 = a0+b0 = r0 sbb r9, qword [rdx+8] ; r9 = a1+b1 = r1 mov qword [rdi], r8 ; mov qword [rdi+8], r9 ; sbb rcx, rcx test rax, 1 jz .FIN0 add rsi, 16 add rdx, 16 add rdi, 16 .SUB_LLAST1: add rcx, rcx mov r8, qword [rsi] ; r8 = a0 sbb r8, qword [rdx] ; r8 = a0+b0 = r0 mov qword [rdi], r8 ; sbb rcx, rcx .FIN0: mov rax, rcx ;******************* .FINAL *********************************************************** .FINAL: neg rax REST_XMM REST_GPR ret ENDFUNC cpSub_BNU %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpdelay.asm000066400000000000000000000025071470420105600256650ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2022 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Delay function, intel64 version ; ; Content: ; _ippcpDelay() ; %include "asmdefs.inc" %include "ia_32e.inc" segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: delay ;* ;* void _ippcpDelay(Ipp32u value) ;* ;* Caller = cpAESRandomNoise ;*************************************************************** align IPP_ALIGN_FACTOR IPPASM _ippcpDelay,PUBLIC COMP_ABI 1 ;; edi - delay value mov ecx,edi .Loop: mov eax,ecx dec ecx test eax,eax jnz .Loop ret ENDFUNC _ippcpDelay cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmd5m7as.asm000066400000000000000000000242631470420105600260470ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to MD5 ; (derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm) ; ; Content: ; UpdateMD5 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_MD5_) %if (_IPP32E >= _IPP32E_M7) ;; ;; Magic functions defined in RFC 1321 ;; %macro MAGIC_F 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F,%%Z xor %%F,%%Y and %%F,%%X xor %%F,%%Z %endmacro %macro MAGIC_G 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 MAGIC_F %%F,%%Z,%%X,%%Y %endmacro %macro MAGIC_H 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F,%%Z xor %%F,%%Y xor %%F,%%X %endmacro %macro MAGIC_I 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F,%%Z not %%F or %%F,%%X xor %%F,%%Y %endmacro %macro ROT_L 2.nolist %xdefine %%r %1 %xdefine %%nbits %2 %if (_IPP32E >= _IPP32E_L9) rorx %%r,%%r,(32-%%nbits) %elif (_IPP32E >= _IPP32E_Y8) shld %%r,%%r,%%nbits %else rol %%r,%%nbits %endif %endmacro ;; ;; single MD5 step ;; ;; A = B +ROL32((A +MAGIC(B,C,D) +data +const), nrot) ;; %macro xMD5_STEP 10.nolist %xdefine %%MAGIC_FUN %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%FUN %6 %xdefine %%TMP %7 %xdefine %%data %8 %xdefine %%MD5const %9 %xdefine %%nrot %10 mov %%TMP,[%%data] ; lea A,[TMP+A+MD5const] add %%A, %%MD5const add %%A, %%TMP %%MAGIC_FUN %%FUN, %%B,%%C,%%D add %%A,%%FUN rol %%A,%%nrot add %%A,%%B %endmacro %macro MD5_STEP 10.nolist %xdefine %%MAGIC_FUN %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%FUN %6 %xdefine %%TMP %7 %xdefine %%data %8 %xdefine %%MD5const %9 %xdefine %%nrot %10 mov %%TMP,[%%data] add %%A, %%MD5const add %%A, %%TMP %%MAGIC_FUN %%FUN, %%B,%%C,%%D add %%A,%%FUN ROT_L %%A,%%nrot add %%A,%%B %endmacro segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateMD5(DigestMD5digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; MD5 left rotations (number of bits) ;; %assign rot11 7 %assign rot12 12 %assign rot13 17 %assign rot14 22 %assign rot21 5 %assign rot22 9 %assign rot23 14 %assign rot24 20 %assign rot31 4 %assign rot32 11 %assign rot33 16 %assign rot34 23 %assign rot41 6 %assign rot42 10 %assign rot43 15 %assign rot44 21 align IPP_ALIGN_FACTOR ;; ;; Lib = M7 ;; ;; Caller = ippsMD5Update ;; Caller = ippsMD5Final ;; Caller = ippsMD5MessageDigest ;; ;; Caller = ippsHMACMD5Update ;; Caller = ippsHMACMD5Final ;; Caller = ippsHMACMD5MessageDigest ;; align IPP_ALIGN_FACTOR IPPASM UpdateMD5,PUBLIC USES_GPR rbx,rsi,rdi,r12 USES_XMM COMP_ABI 4 ;; rdi = hash ;; rsi = data buffer ;; rdx = buffer length ;; rcx = address of MD5 constants %assign MBS_MD5 64 movsxd r12, edx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .md5_block_loop: ; prefetcht0 [rsi+64] ;; ;; init A, B, C, D by the internal digest ;; mov r8d, [rdi+0*4] ; r8d = digest[0] (A) mov r9d, [rdi+1*4] ; r9d = digest[1] (B) mov r10d,[rdi+2*4] ; r10d = digest[2] (C) mov r11d,[rdi+3*4] ; r11d = digest[3] (D) ;; ;; perform 0-63 steps ;; ;; MAGIC A, B, C, D, FUN,TMP, pData, cnt, nrot ;; ------------------------------------------------------------------- MD5_STEP MAGIC_F, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 0*4}, 0d76aa478h, rot11 MD5_STEP MAGIC_F, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 1*4}, 0e8c7b756h, rot12 MD5_STEP MAGIC_F, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 2*4}, 0242070dbh, rot13 MD5_STEP MAGIC_F, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 3*4}, 0c1bdceeeh, rot14 MD5_STEP MAGIC_F, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 4*4}, 0f57c0fafh, rot11 MD5_STEP MAGIC_F, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 5*4}, 04787c62ah, rot12 MD5_STEP MAGIC_F, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 6*4}, 0a8304613h, rot13 MD5_STEP MAGIC_F, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 7*4}, 0fd469501h, rot14 MD5_STEP MAGIC_F, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 8*4}, 0698098d8h, rot11 MD5_STEP MAGIC_F, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 9*4}, 08b44f7afh, rot12 MD5_STEP MAGIC_F, r10d,r11d,r8d, r9d, edx,ecx, {rsi+10*4}, 0ffff5bb1h, rot13 MD5_STEP MAGIC_F, r9d, r10d,r11d,r8d, edx,ecx, {rsi+11*4}, 0895cd7beh, rot14 MD5_STEP MAGIC_F, r8d, r9d, r10d,r11d, edx,ecx, {rsi+12*4}, 06b901122h, rot11 MD5_STEP MAGIC_F, r11d,r8d, r9d, r10d, edx,ecx, {rsi+13*4}, 0fd987193h, rot12 MD5_STEP MAGIC_F, r10d,r11d,r8d, r9d, edx,ecx, {rsi+14*4}, 0a679438eh, rot13 MD5_STEP MAGIC_F, r9d, r10d,r11d,r8d, edx,ecx, {rsi+15*4}, 049b40821h, rot14 MD5_STEP MAGIC_G, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 1*4}, 0f61e2562h, rot21 MD5_STEP MAGIC_G, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 6*4}, 0c040b340h, rot22 MD5_STEP MAGIC_G, r10d,r11d,r8d, r9d, edx,ecx, {rsi+11*4}, 0265e5a51h, rot23 MD5_STEP MAGIC_G, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 0*4}, 0e9b6c7aah, rot24 MD5_STEP MAGIC_G, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 5*4}, 0d62f105dh, rot21 MD5_STEP MAGIC_G, r11d,r8d, r9d, r10d, edx,ecx, {rsi+10*4}, 002441453h, rot22 MD5_STEP MAGIC_G, r10d,r11d,r8d, r9d, edx,ecx, {rsi+15*4}, 0d8a1e681h, rot23 MD5_STEP MAGIC_G, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 4*4}, 0e7d3fbc8h, rot24 MD5_STEP MAGIC_G, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 9*4}, 021e1cde6h, rot21 MD5_STEP MAGIC_G, r11d,r8d, r9d, r10d, edx,ecx, {rsi+14*4}, 0c33707d6h, rot22 MD5_STEP MAGIC_G, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 3*4}, 0f4d50d87h, rot23 MD5_STEP MAGIC_G, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 8*4}, 0455a14edh, rot24 MD5_STEP MAGIC_G, r8d, r9d, r10d,r11d, edx,ecx, {rsi+13*4}, 0a9e3e905h, rot21 MD5_STEP MAGIC_G, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 2*4}, 0fcefa3f8h, rot22 MD5_STEP MAGIC_G, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 7*4}, 0676f02d9h, rot23 MD5_STEP MAGIC_G, r9d, r10d,r11d,r8d, edx,ecx, {rsi+12*4}, 08d2a4c8ah, rot24 MD5_STEP MAGIC_H, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 5*4}, 0fffa3942h, rot31 MD5_STEP MAGIC_H, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 8*4}, 08771f681h, rot32 MD5_STEP MAGIC_H, r10d,r11d,r8d, r9d, edx,ecx, {rsi+11*4}, 06d9d6122h, rot33 MD5_STEP MAGIC_H, r9d, r10d,r11d,r8d, edx,ecx, {rsi+14*4}, 0fde5380ch, rot34 MD5_STEP MAGIC_H, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 1*4}, 0a4beea44h, rot31 MD5_STEP MAGIC_H, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 4*4}, 04bdecfa9h, rot32 MD5_STEP MAGIC_H, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 7*4}, 0f6bb4b60h, rot33 MD5_STEP MAGIC_H, r9d, r10d,r11d,r8d, edx,ecx, {rsi+10*4}, 0bebfbc70h, rot34 MD5_STEP MAGIC_H, r8d, r9d, r10d,r11d, edx,ecx, {rsi+13*4}, 0289b7ec6h, rot31 MD5_STEP MAGIC_H, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 0*4}, 0eaa127fah, rot32 MD5_STEP MAGIC_H, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 3*4}, 0d4ef3085h, rot33 MD5_STEP MAGIC_H, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 6*4}, 004881d05h, rot34 MD5_STEP MAGIC_H, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 9*4}, 0d9d4d039h, rot31 MD5_STEP MAGIC_H, r11d,r8d, r9d, r10d, edx,ecx, {rsi+12*4}, 0e6db99e5h, rot32 MD5_STEP MAGIC_H, r10d,r11d,r8d, r9d, edx,ecx, {rsi+15*4}, 01fa27cf8h, rot33 MD5_STEP MAGIC_H, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 2*4}, 0c4ac5665h, rot34 MD5_STEP MAGIC_I, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 0*4}, 0f4292244h, rot41 MD5_STEP MAGIC_I, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 7*4}, 0432aff97h, rot42 MD5_STEP MAGIC_I, r10d,r11d,r8d, r9d, edx,ecx, {rsi+14*4}, 0ab9423a7h, rot43 MD5_STEP MAGIC_I, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 5*4}, 0fc93a039h, rot44 MD5_STEP MAGIC_I, r8d, r9d, r10d,r11d, edx,ecx, {rsi+12*4}, 0655b59c3h, rot41 MD5_STEP MAGIC_I, r11d,r8d, r9d, r10d, edx,ecx, {rsi+ 3*4}, 08f0ccc92h, rot42 MD5_STEP MAGIC_I, r10d,r11d,r8d, r9d, edx,ecx, {rsi+10*4}, 0ffeff47dh, rot43 MD5_STEP MAGIC_I, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 1*4}, 085845dd1h, rot44 MD5_STEP MAGIC_I, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 8*4}, 06fa87e4fh, rot41 MD5_STEP MAGIC_I, r11d,r8d, r9d, r10d, edx,ecx, {rsi+15*4}, 0fe2ce6e0h, rot42 MD5_STEP MAGIC_I, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 6*4}, 0a3014314h, rot43 MD5_STEP MAGIC_I, r9d, r10d,r11d,r8d, edx,ecx, {rsi+13*4}, 04e0811a1h, rot44 MD5_STEP MAGIC_I, r8d, r9d, r10d,r11d, edx,ecx, {rsi+ 4*4}, 0f7537e82h, rot41 MD5_STEP MAGIC_I, r11d,r8d, r9d, r10d, edx,ecx, {rsi+11*4}, 0bd3af235h, rot42 MD5_STEP MAGIC_I, r10d,r11d,r8d, r9d, edx,ecx, {rsi+ 2*4}, 02ad7d2bbh, rot43 MD5_STEP MAGIC_I, r9d, r10d,r11d,r8d, edx,ecx, {rsi+ 9*4}, 0eb86d391h, rot44 ;; ;; update digest ;; add [rdi+0*4],r8d ; advance digest add [rdi+1*4],r9d add [rdi+2*4],r10d add [rdi+3*4],r11d add rsi, MBS_MD5 sub r12, MBS_MD5 jg .md5_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateMD5 %endif ;; _IPP32E >= _IPP32E_M7 %endif ;; _ENABLE_ALG_MD5_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmontmul1024_avx2as.asm000066400000000000000000000367041470420105600300630ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpMontMul1024_avx2() ; %include "asmdefs.inc" %include "ia_32e.inc" ;include pcpbnumulschool.inc ;include pcpvariant.inc %if (_IPP32E >= _IPP32E_L9) segment .text align=IPP_ALIGN_FACTOR %assign DIGIT_BITS 27 %assign DIGIT_MASK (1 << DIGIT_BITS) -1 ;************************************************************* ;* void cpMontMul1024_avx2(Ipp64u* pR, ;* const Ipp64u* pA, ;* const Ipp64u* pB, ;* const Ipp64u* pModulo, int mSize, ;* Ipp64u m0) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontMul1024_avx2,PUBLIC %assign LOCAL_FRAME sizeof(ymmword) USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13,ymm14 COMP_ABI 6 mov rbp,rdx ; pointer to B operand movsxd r8, r8d ; redLen value counter ;; clear results and buffers vzeroall ;; expands A and M operands vmovdqu ymmword [rsi+r8*sizeof(qword)], ymm0 vmovdqu ymmword [rcx+r8*sizeof(qword)], ymm0 xor r10, r10 ; ac0 = 0 vmovdqu ymmword [rsp], ymm0 ; {r3:r2:r1;R0} = 0 align IPP_ALIGN_FACTOR ;; ;; process b[] by quadruples (b[j], b[j+1], b[j+2] and b[j+3]) per pass ;; .loop4_B: mov rbx, qword [rbp] ; rbx = b[j] vpbroadcastq ymm0, qword [rbp] mov r10, rbx ; ac0 = pa[0]*b[j]+pr[0] imul r10, qword [rsi] add r10, qword [rsp] mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov r11, rbx ; ac1 = pa[1]*b[j]+pr[1] imul r11, qword [rsi+sizeof(qword)] add r11, qword [rsp+sizeof(qword)] mov r12, rbx ; ac2 = pa[2]*b[j]+pr[2] imul r12, qword [rsi+sizeof(qword)*2] add r12, qword [rsp+sizeof(qword)*2] mov r13, rbx ; ac3 = pa[3]*b[j]+pr[3] imul r13, qword [rsi+sizeof(qword)*3] add r13, qword [rsp+sizeof(qword)*3] vmovd xmm11, edx vpbroadcastq ymm11, xmm11 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*4] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*5] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*6] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*7] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*8] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*9] vpaddq ymm9, ymm9, ymm14 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*4] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*5] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*6] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*7] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*8] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*9] vpaddq ymm9, ymm9, ymm14 ;; ------------------------------------------------------------ mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[j+1] vpbroadcastq ymm0, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm11, edx vpbroadcastq ymm11, xmm11 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)-sizeof(qword)] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*2-sizeof(qword)] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*3-sizeof(qword)] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*4-sizeof(qword)] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*5-sizeof(qword)] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*6-sizeof(qword)] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*7-sizeof(qword)] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*8-sizeof(qword)] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*9-sizeof(qword)] vpaddq ymm9, ymm9, ymm14 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)-sizeof(qword)] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*2-sizeof(qword)] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*3-sizeof(qword)] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*4-sizeof(qword)] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*5-sizeof(qword)] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*6-sizeof(qword)] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*7-sizeof(qword)] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*8-sizeof(qword)] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*9-sizeof(qword)] vpaddq ymm9, ymm9, ymm14 sub r8, 2 jz .exit_loop_B ;; ------------------------------------------------------------ mov rbx, qword [rbp+sizeof(qword)*2] ; rbx = b[j+2] vpbroadcastq ymm0, qword [rbp+sizeof(qword)*2] mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi] add r12, rax mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi+sizeof(qword)] add r13, rax vmovd xmm11, edx vpbroadcastq ymm11, xmm11 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)-sizeof(qword)*2] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*2-sizeof(qword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*3-sizeof(qword)*2] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*4-sizeof(qword)*2] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*5-sizeof(qword)*2] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*6-sizeof(qword)*2] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*7-sizeof(qword)*2] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*8-sizeof(qword)*2] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*9-sizeof(qword)*2] vpaddq ymm9, ymm9, ymm14 mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] add r12, rax shr r12, DIGIT_BITS mov rax, rdx ; ac3 += pn[1]*y2 imul rax, qword [rcx+sizeof(qword)] add r13, rax add r13, r12 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)-sizeof(qword)*2] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*2-sizeof(qword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*3-sizeof(qword)*2] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*4-sizeof(qword)*2] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*5-sizeof(qword)*2] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*6-sizeof(qword)*2] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*7-sizeof(qword)*2] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*8-sizeof(qword)*2] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*9-sizeof(qword)*2] vpaddq ymm9, ymm9, ymm14 ;; ------------------------------------------------------------ mov rbx, qword [rbp+sizeof(qword)*3] ; rbx = b[j+3] vpbroadcastq ymm0, qword [rbp+sizeof(qword)*3] imul rbx, qword [rsi] ; ac3 += pa[0]*b[j+3] add r13, rbx mov rdx, r13 ; y3 = (ac3*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK vmovd xmm11, edx vpbroadcastq ymm11, xmm11 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)-sizeof(qword)*3] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*2-sizeof(qword)*3] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*3-sizeof(qword)*3] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*4-sizeof(qword)*3] vpaddq ymm4, ymm4, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*5-sizeof(qword)*3] vpaddq ymm5, ymm5, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*6-sizeof(qword)*3] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm12, ymm0, ymmword [rsi+sizeof(ymmword)*7-sizeof(qword)*3] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm0, ymmword [rsi+sizeof(ymmword)*8-sizeof(qword)*3] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm14, ymm0, ymmword [rsi+sizeof(ymmword)*9-sizeof(qword)*3] vpaddq ymm9, ymm9, ymm14 vpmuludq ymm10, ymm0, ymmword [rsi+sizeof(ymmword)*10-sizeof(qword)*3] imul rdx, qword [rcx] ; ac3 += pn[0]*y3 add r13, rdx shr r13, DIGIT_BITS vmovq xmm14, r13 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)-sizeof(qword)*3] vpaddq ymm1, ymm1, ymm12 vpaddq ymm1, ymm1, ymm14 vmovdqu ymmword [rsp], ymm1 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*2-sizeof(qword)*3] vpaddq ymm1, ymm2, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*3-sizeof(qword)*3] vpaddq ymm2, ymm3, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*4-sizeof(qword)*3] vpaddq ymm3, ymm4, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*5-sizeof(qword)*3] vpaddq ymm4, ymm5, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*6-sizeof(qword)*3] vpaddq ymm5, ymm6, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*7-sizeof(qword)*3] vpaddq ymm6, ymm7, ymm12 vpmuludq ymm13, ymm11, ymmword [rcx+sizeof(ymmword)*8-sizeof(qword)*3] vpaddq ymm7, ymm8, ymm13 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*9-sizeof(qword)*3] vpaddq ymm8, ymm9, ymm14 vpmuludq ymm12, ymm11, ymmword [rcx+sizeof(ymmword)*10-sizeof(qword)*3] vpaddq ymm9, ymm10, ymm12 ;; ------------------------------------------------------------ add rbp, sizeof(qword)*4 sub r8, 2 jnz .loop4_B .exit_loop_B: mov qword [rdi], r12 mov qword [rdi+sizeof(qword)], r13 vmovdqu ymmword [rdi+sizeof(qword)*2], ymm1 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)], ymm2 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*2], ymm3 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*3], ymm4 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*4], ymm5 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*5], ymm6 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*6], ymm7 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*7], ymm8 vmovdqu ymmword [rdi+sizeof(qword)*2+sizeof(ymmword)*8], ymm9 ;; ;; normalize ;; mov r8, dword 38 xor rax, rax .norm_loop: add rax, qword [rdi] add rdi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi-sizeof(qword)], rdx sub r8, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpMontMul1024_avx2 %endif ; _IPP32E_L9 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmontmul_avx2as.asm000066400000000000000000002207641470420105600275550ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpMontMul4n_avx2() ; cpMontMul4n1_avx2() ; cpMontMul4n2_avx2() ; cpMontMul4n3_avx2() ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_L9) segment .text align=IPP_ALIGN_FACTOR %assign DIGIT_BITS 27 %assign DIGIT_MASK (1 << DIGIT_BITS) -1 ;************************************************************* ;* void cpMontMul4n_avx2(Ipp64u* pR, ;* const Ipp64u* pA, ;* const Ipp64u* pB, ;* const Ipp64u* pModulo, int mSize, ;* Ipp64u m0, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontMul4n_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*5 USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13 COMP_ABI 7 mov rbp,rdx ; pointer to B operand movsxd r8, r8d ; redLen value counter ; ; stack struct ; %assign pR 0 ; pointer to result %assign pResult pR+sizeof(qword) ; pointer to buffer %assign pA pResult+sizeof(qword) ; pointer to A operand %assign pM pA+sizeof(qword) ; pointer to modulus %assign redLen pM+sizeof(qword) ; length mov qword [rsp+pR], rdi ; save pointer to destination mov qword [rsp+pA], rsi ; A operand mov qword [rsp+pM], rcx ; modulus mov qword [rsp+redLen], r8 ; modulus length mov rdi, qword [rsp+ARG_7] ; buffer mov [rsp+pResult], rdi vpxor ymm0, ymm0, ymm0 xor rax, rax ;; expands A and M operands vmovdqu ymmword [rsi+r8*sizeof(qword)], ymm0 vmovdqu ymmword [rcx+r8*sizeof(qword)], ymm0 ;; clear result buffer of (redLen+4) qword length mov r14, r8 align IPP_ALIGN_FACTOR .clearLoop: vmovdqu ymmword [rdi], ymm0 add rdi, sizeof(ymmword) sub r14, sizeof(ymmword)/sizeof(qword) jg .clearLoop vmovdqu ymmword [rdi], ymm0 lea r14, [r8+sizeof(ymmword)/sizeof(qword)-1] ; a_counter = (redLen+3) & (-4) and r14,-(sizeof(ymmword)/sizeof(qword)) align IPP_ALIGN_FACTOR ;; ;; process b[] by quadruples (b[j], b[j+1], b[j+2] and b[j+3]) per pass ;; .loop4_B: sub r8, sizeof(ymmword)/sizeof(qword) jl .exit_loop4_B mov rbx, qword [rbp] ; rbx = b[j] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[j+1] vpbroadcastq ymm5, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm9, edx vpbroadcastq ymm9, xmm9 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax mov rbx, qword [rbp+sizeof(qword)*2] ; rbx = b[j+2] vpbroadcastq ymm6, qword [rbp+sizeof(qword)*2] mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi] add r12, rax mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi+sizeof(qword)] add r13, rax vmovd xmm10, edx vpbroadcastq ymm10, xmm10 mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] add r12, rax shr r12, DIGIT_BITS mov rax, rdx ; ac3 += pn[1]*y2 imul rax, qword [rcx+sizeof(qword)] add r13, rax add r13, r12 mov rbx, qword [rbp+sizeof(qword)*3] ; rbx = b[j+3] vpbroadcastq ymm7, qword [rbp+sizeof(qword)*3] imul rbx, qword [rsi] ; ac3 += pa[0]*b[j+3] add r13, rbx mov rdx, r13 ; y3 = (ac3*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK vmovd xmm11, edx vpbroadcastq ymm11, xmm11 imul rdx, qword [rcx] ; ac3 += pn[0]*y3 add r13, rdx shr r13, DIGIT_BITS vmovq xmm0, r13 vpaddq ymm0, ymm0, ymmword [rdi+sizeof(ymmword)] vmovdqu ymmword [rdi+sizeof(ymmword)], ymm0 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter ;; (vb0) ymm4 = {b0:b0:b0:b0} ;; (vb1) ymm5 = {b1:b1:b1:b1} ;; (vb2) ymm6 = {b2:b2:b2:b2} ;; (vb3) ymm7 = {b3:b3:b3:b3} ;; (vy0) ymm8 = {y0:y0:y0:y0} ;; (vy1) ymm9 = {y1:y1:y1:y1} ;; (vy2) ymm10= {y2:y2:y2:y2} ;; (vy3) ymm11= {y3:y3:y3:y3} sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .loop16_A: sub r11, 4*sizeof(ymmword)/sizeof(qword) jl .exit_loop16_A vmovdqu ymm0, ymmword [rdi] ; r0 vmovdqu ymm1, ymmword [rdi+sizeof(ymmword)] ; r1 vmovdqu ymm2, ymmword [rdi+sizeof(ymmword)*2] ; r2 vmovdqu ymm3, ymmword [rdi+sizeof(ymmword)*3] ; r3 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)] ; r1 += vb0 * (__m256i*)(pa)[j+1] + vy0 * (__m256i*)(pn)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*2] ; r2 += vb0 * (__m256i*)(pa)[j+2] + vy0 * (__m256i*)(pn)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*3] ; r3 += vb0 * (__m256i*)(pa)[j+3] + vy0 * (__m256i*)(pn)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)] ; r1 += vb1 * (__m256i*)(pa-1)[j+1] + vy1 * (__m256i*)(pn-1)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*2] ; r2 += vb1 * (__m256i*)(pa-1)[j+2] + vy1 * (__m256i*)(pn-1)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*3] ; r3 += vb1 * (__m256i*)(pa-1)[j+3] + vy1 * (__m256i*)(pn-1)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)] ; r1 += vb2 * (__m256i*)(pa-2)[j+1] + vy2 * (__m256i*)(pn-2)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*2] ; r2 += vb2 * (__m256i*)(pa-2)[j+2] + vy2 * (__m256i*)(pn-2)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*3] ; r3 += vb2 * (__m256i*)(pa-2)[j+3] + vy2 * (__m256i*)(pn-2)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)] ; r1 += vb3 * (__m256i*)(pa-3)[j+1] + vy3 * (__m256i*)(pn-3)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*2] ; r2 += vb3 * (__m256i*)(pa-3)[j+2] + vy3 * (__m256i*)(pn-3)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*3] ; r3 += vb3 * (__m256i*)(pa-3)[j+3] + vy3 * (__m256i*)(pn-3)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)], ymm1 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*2], ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*3], ymm3 add rdi, sizeof(ymmword)*4 add rsi, sizeof(ymmword)*4 add rcx, sizeof(ymmword)*4 jmp .loop16_A .exit_loop16_A: add r11, 4*(sizeof(ymmword)/sizeof(qword)) jz .exitA .loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exitA vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm2 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .loop4_A .exitA: vpmuludq ymm1, ymm5, ymmword [rsi-sizeof(qword)] ; r1 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm2, ymm6, ymmword [rsi-sizeof(qword)*2] ; r2 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm3, ymm7, ymmword [rsi-sizeof(qword)*3] ; r3 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm3, ymm3, ymm13 vpaddq ymm1, ymm1, ymm2 vpaddq ymm1, ymm1, ymm3 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm1 jmp .loop4_B .exit_loop4_B: ;; ;; normalize ;; mov rdi, qword [rsp+pR] mov rsi, qword [rsp+pResult] mov r8, qword [rsp+redLen] xor rax, rax .norm_loop: add rax, qword [rsi] add rsi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi], rdx add rdi, sizeof(qword) sub r8, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpMontMul4n_avx2 ;************************************************************* ;* void cpMontMul4n1_avx2(Ipp64u* pR, ;* const Ipp64u* pA, ;* const Ipp64u* pB, ;* const Ipp64u* pModulo, int mSize, ;* Ipp64u m0, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontMul4n1_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*5 USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13 COMP_ABI 7 mov rbp,rdx ; pointer to B operand movsxd r8, r8d ; redLen value counter ; ; stack struct ; %xdefine pR 0 ; pointer to result %xdefine pResult pR+sizeof(qword) ; pointer to buffer %xdefine pA pResult+sizeof(qword) ; pointer to A operand %xdefine pM pA+sizeof(qword) ; pointer to modulus %xdefine redLen pM+sizeof(qword) ; length mov qword [rsp+pR], rdi ; save pointer to destination mov qword [rsp+pA], rsi ; A operand mov qword [rsp+pM], rcx ; modulus mov qword [rsp+redLen], r8 ; modulus length mov rdi, qword [rsp+ARG_7] ; buffer mov [rsp+pResult], rdi vpxor ymm0, ymm0, ymm0 xor rax, rax ;; expands A and M operands vmovdqu ymmword [rsi+r8*sizeof(qword)], ymm0 vmovdqu ymmword [rcx+r8*sizeof(qword)], ymm0 ;; clear result buffer of (redLen+4) qword length mov r14, r8 align IPP_ALIGN_FACTOR .clearLoop: vmovdqu ymmword [rdi], ymm0 add rdi, sizeof(ymmword) sub r14, sizeof(ymmword)/sizeof(qword) jg .clearLoop mov qword [rdi], rax lea r14, [r8+sizeof(ymmword)/sizeof(qword)-1] ; a_counter = (redLen+3) & (-4) and r14,-(sizeof(ymmword)/sizeof(qword)) align IPP_ALIGN_FACTOR ;; ;; process b[] by quadruples (b[j], b[j+1], b[j+2] and b[j+3]) per pass ;; .loop4_B: sub r8, sizeof(ymmword)/sizeof(qword) jl .exit_loop4_B mov rbx, qword [rbp] ; rbx = b[j] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[j+1] vpbroadcastq ymm5, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm9, edx vpbroadcastq ymm9, xmm9 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax mov rbx, qword [rbp+sizeof(qword)*2] ; rbx = b[j+2] vpbroadcastq ymm6, qword [rbp+sizeof(qword)*2] mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi] add r12, rax mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi+sizeof(qword)] add r13, rax vmovd xmm10, edx vpbroadcastq ymm10, xmm10 mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] add r12, rax shr r12, DIGIT_BITS mov rax, rdx ; ac3 += pn[1]*y2 imul rax, qword [rcx+sizeof(qword)] add r13, rax add r13, r12 mov rbx, qword [rbp+sizeof(qword)*3] ; rbx = b[j+3] vpbroadcastq ymm7, qword [rbp+sizeof(qword)*3] imul rbx, qword [rsi] ; ac3 += pa[0]*b[j+3] add r13, rbx mov rdx, r13 ; y3 = (ac3*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK vmovd xmm11, edx vpbroadcastq ymm11, xmm11 imul rdx, qword [rcx] ; ac3 += pn[0]*y3 add r13, rdx shr r13, DIGIT_BITS vmovq xmm0, r13 vpaddq ymm0, ymm0, ymmword [rdi+sizeof(ymmword)] vmovdqu ymmword [rdi+sizeof(ymmword)], ymm0 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter ;; (vb0) ymm4 = {b0:b0:b0:b0} ;; (vb1) ymm5 = {b1:b1:b1:b1} ;; (vb2) ymm6 = {b2:b2:b2:b2} ;; (vb3) ymm7 = {b3:b3:b3:b3} ;; (vy0) ymm8 = {y0:y0:y0:y0} ;; (vy1) ymm9 = {y1:y1:y1:y1} ;; (vy2) ymm10= {y2:y2:y2:y2} ;; (vy3) ymm11= {y3:y3:y3:y3} sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .loop16_A: sub r11, 4*sizeof(ymmword)/sizeof(qword) jl .exit_loop16_A vmovdqu ymm0, ymmword [rdi] ; r0 vmovdqu ymm1, ymmword [rdi+sizeof(ymmword)] ; r1 vmovdqu ymm2, ymmword [rdi+sizeof(ymmword)*2] ; r2 vmovdqu ymm3, ymmword [rdi+sizeof(ymmword)*3] ; r3 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)] ; r1 += vb0 * (__m256i*)(pa)[j+1] + vy0 * (__m256i*)(pn)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*2] ; r2 += vb0 * (__m256i*)(pa)[j+2] + vy0 * (__m256i*)(pn)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*3] ; r3 += vb0 * (__m256i*)(pa)[j+3] + vy0 * (__m256i*)(pn)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)] ; r1 += vb1 * (__m256i*)(pa-1)[j+1] + vy1 * (__m256i*)(pn-1)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*2] ; r2 += vb1 * (__m256i*)(pa-1)[j+2] + vy1 * (__m256i*)(pn-1)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*3] ; r3 += vb1 * (__m256i*)(pa-1)[j+3] + vy1 * (__m256i*)(pn-1)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)] ; r1 += vb2 * (__m256i*)(pa-2)[j+1] + vy2 * (__m256i*)(pn-2)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*2] ; r2 += vb2 * (__m256i*)(pa-2)[j+2] + vy2 * (__m256i*)(pn-2)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*3] ; r3 += vb2 * (__m256i*)(pa-2)[j+3] + vy2 * (__m256i*)(pn-2)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)] ; r1 += vb3 * (__m256i*)(pa-3)[j+1] + vy3 * (__m256i*)(pn-3)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*2] ; r2 += vb3 * (__m256i*)(pa-3)[j+2] + vy3 * (__m256i*)(pn-3)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*3] ; r3 += vb3 * (__m256i*)(pa-3)[j+3] + vy3 * (__m256i*)(pn-3)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)], ymm1 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*2], ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*3], ymm3 add rdi, sizeof(ymmword)*4 add rsi, sizeof(ymmword)*4 add rcx, sizeof(ymmword)*4 jmp .loop16_A .exit_loop16_A: add r11, 4*(sizeof(ymmword)/sizeof(qword)) jz .exitA .loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exitA vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm2 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .loop4_A .exitA: jmp .loop4_B ;; ;; process latest b[redLen-1] ;; .exit_loop4_B: mov rbx, qword [rbp] ; rbx = b[redLen-1] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov qword [rdi], r11 ; pr[0] = ac1 mov qword [rdi+sizeof(qword)], r12 ; pr[1] = ac2 mov qword [rdi+sizeof(qword)*2], r13 ; pr[2] = ac3 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .rem_loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exit_rem_loop4_A vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vmovdqu ymmword [rdi+3*sizeof(qword)-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .rem_loop4_A .exit_rem_loop4_A: ;; ;; normalize ;; mov rdi, qword [rsp+pR] mov rsi, qword [rsp+pResult] mov r8, qword [rsp+redLen] xor rax, rax .norm_loop: add rax, qword [rsi] add rsi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi], rdx add rdi, sizeof(qword) sub r8, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpMontMul4n1_avx2 ;************************************************************* ;* void cpMontMul4n2_avx2(Ipp64u* pR, ;* const Ipp64u* pA, ;* const Ipp64u* pB, ;* const Ipp64u* pModulo, int mSize, ;* Ipp64u m0, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontMul4n2_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*5 USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13 COMP_ABI 7 mov rbp,rdx ; pointer to B operand movsxd r8, r8d ; redLen value counter ; ; stack struct ; %xdefine pR 0 ; pointer to result %xdefine pResult pR+sizeof(qword) ; pointer to buffer %xdefine pA pResult+sizeof(qword) ; pointer to A operand %xdefine pM pA+sizeof(qword) ; pointer to modulus %xdefine redLen pM+sizeof(qword) ; length mov qword [rsp+pR], rdi ; save pointer to destination mov qword [rsp+pA], rsi ; A operand mov qword [rsp+pM], rcx ; modulus mov qword [rsp+redLen], r8 ; modulus length mov rdi, qword [rsp+ARG_7] ; buffer mov [rsp+pResult], rdi vpxor ymm0, ymm0, ymm0 xor rax, rax ;; expands A and M operands vmovdqu ymmword [rsi+r8*sizeof(qword)], ymm0 vmovdqu ymmword [rcx+r8*sizeof(qword)], ymm0 ;; clear result buffer of (redLen+4) qword length mov r14, r8 align IPP_ALIGN_FACTOR .clearLoop: vmovdqu ymmword [rdi], ymm0 add rdi, sizeof(ymmword) sub r14, sizeof(ymmword)/sizeof(qword) jg .clearLoop vmovdqu xmmword [rdi], xmm0 lea r14, [r8+sizeof(ymmword)/sizeof(qword)-1] ; a_counter = (redLen+3) & (-4) and r14,-(sizeof(ymmword)/sizeof(qword)) align IPP_ALIGN_FACTOR ;; ;; process b[] by quadruples (b[j], b[j+1], b[j+2] and b[j+3]) per pass ;; .loop4_B: sub r8, sizeof(ymmword)/sizeof(qword) jl .exit_loop4_B mov rbx, qword [rbp] ; rbx = b[j] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[j+1] vpbroadcastq ymm5, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm9, edx vpbroadcastq ymm9, xmm9 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax mov rbx, qword [rbp+sizeof(qword)*2] ; rbx = b[j+2] vpbroadcastq ymm6, qword [rbp+sizeof(qword)*2] mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi] add r12, rax mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi+sizeof(qword)] add r13, rax vmovd xmm10, edx vpbroadcastq ymm10, xmm10 mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] add r12, rax shr r12, DIGIT_BITS mov rax, rdx ; ac3 += pn[1]*y2 imul rax, qword [rcx+sizeof(qword)] add r13, rax add r13, r12 mov rbx, qword [rbp+sizeof(qword)*3] ; rbx = b[j+3] vpbroadcastq ymm7, qword [rbp+sizeof(qword)*3] imul rbx, qword [rsi] ; ac3 += pa[0]*b[j+3] add r13, rbx mov rdx, r13 ; y3 = (ac3*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK vmovd xmm11, edx vpbroadcastq ymm11, xmm11 imul rdx, qword [rcx] ; ac3 += pn[0]*y3 add r13, rdx shr r13, DIGIT_BITS vmovq xmm0, r13 vpaddq ymm0, ymm0, ymmword [rdi+sizeof(ymmword)] vmovdqu ymmword [rdi+sizeof(ymmword)], ymm0 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter ;; (vb0) ymm4 = {b0:b0:b0:b0} ;; (vb1) ymm5 = {b1:b1:b1:b1} ;; (vb2) ymm6 = {b2:b2:b2:b2} ;; (vb3) ymm7 = {b3:b3:b3:b3} ;; (vy0) ymm8 = {y0:y0:y0:y0} ;; (vy1) ymm9 = {y1:y1:y1:y1} ;; (vy2) ymm10= {y2:y2:y2:y2} ;; (vy3) ymm11= {y3:y3:y3:y3} sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .loop16_A: sub r11, 4*sizeof(ymmword)/sizeof(qword) jl .exit_loop16_A vmovdqu ymm0, ymmword [rdi] ; r0 vmovdqu ymm1, ymmword [rdi+sizeof(ymmword)] ; r1 vmovdqu ymm2, ymmword [rdi+sizeof(ymmword)*2] ; r2 vmovdqu ymm3, ymmword [rdi+sizeof(ymmword)*3] ; r3 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)] ; r1 += vb0 * (__m256i*)(pa)[j+1] + vy0 * (__m256i*)(pn)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*2] ; r2 += vb0 * (__m256i*)(pa)[j+2] + vy0 * (__m256i*)(pn)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*3] ; r3 += vb0 * (__m256i*)(pa)[j+3] + vy0 * (__m256i*)(pn)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)] ; r1 += vb1 * (__m256i*)(pa-1)[j+1] + vy1 * (__m256i*)(pn-1)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*2] ; r2 += vb1 * (__m256i*)(pa-1)[j+2] + vy1 * (__m256i*)(pn-1)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*3] ; r3 += vb1 * (__m256i*)(pa-1)[j+3] + vy1 * (__m256i*)(pn-1)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)] ; r1 += vb2 * (__m256i*)(pa-2)[j+1] + vy2 * (__m256i*)(pn-2)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*2] ; r2 += vb2 * (__m256i*)(pa-2)[j+2] + vy2 * (__m256i*)(pn-2)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*3] ; r3 += vb2 * (__m256i*)(pa-2)[j+3] + vy2 * (__m256i*)(pn-2)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)] ; r1 += vb3 * (__m256i*)(pa-3)[j+1] + vy3 * (__m256i*)(pn-3)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*2] ; r2 += vb3 * (__m256i*)(pa-3)[j+2] + vy3 * (__m256i*)(pn-3)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*3] ; r3 += vb3 * (__m256i*)(pa-3)[j+3] + vy3 * (__m256i*)(pn-3)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)], ymm1 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*2], ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*3], ymm3 add rdi, sizeof(ymmword)*4 add rsi, sizeof(ymmword)*4 add rcx, sizeof(ymmword)*4 jmp .loop16_A .exit_loop16_A: add r11, 4*(sizeof(ymmword)/sizeof(qword)) jz .exitA .loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exitA vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm2 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .loop4_A .exitA: vpmuludq ymm0, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpmuludq ymm1, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm1 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 jmp .loop4_B ;; ;; process latest b[redLen-2] and b[redLen-1] ;; .exit_loop4_B: mov rbx, qword [rbp] ; rbx = b[redLen-2] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[j+1] vpbroadcastq ymm5, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm9, edx vpbroadcastq ymm9, xmm9 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax mov qword [rdi], r12 ; pr[0] = ac2 mov qword [rdi+sizeof(qword)], r13 ; pr[1] = ac3 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .rem_loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exit_rem_loop4_A vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm13 vmovdqu ymmword [rdi+sizeof(qword)*2-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .rem_loop4_A .exit_rem_loop4_A: ;; ;; normalize ;; mov rdi, qword [rsp+pR] mov rsi, qword [rsp+pResult] mov r8, qword [rsp+redLen] xor rax, rax .norm_loop: add rax, qword [rsi] add rsi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi], rdx add rdi, sizeof(qword) sub r8, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpMontMul4n2_avx2 ;************************************************************* ;* void cpMontMul4n3_avx2(Ipp64u* pR, ;* const Ipp64u* pA, ;* const Ipp64u* pB, ;* const Ipp64u* pModulo, int mSize, ;* Ipp64u m0, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontMul4n3_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*5 USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13 COMP_ABI 7 mov rbp,rdx ; pointer to B operand movsxd r8, r8d ; redLen value counter ; ; stack struct ; %xdefine pR 0 ; pointer to result %xdefine pResult pR+sizeof(qword) ; pointer to buffer %xdefine pA pResult+sizeof(qword) ; pointer to A operand %xdefine pM pA+sizeof(qword) ; pointer to modulus %xdefine redLen pM+sizeof(qword) ; length mov qword [rsp+pR], rdi ; save pointer to destination mov qword [rsp+pA], rsi ; A operand mov qword [rsp+pM], rcx ; modulus mov qword [rsp+redLen], r8 ; modulus length mov rdi, qword [rsp+ARG_7] ; buffer mov [rsp+pResult], rdi vpxor ymm0, ymm0, ymm0 xor rax, rax ;; expands A and M operands vmovdqu ymmword [rsi+r8*sizeof(qword)], ymm0 vmovdqu ymmword [rcx+r8*sizeof(qword)], ymm0 ;; clear result buffer of (redLen+4) qword length mov r14, r8 align IPP_ALIGN_FACTOR .clearLoop: vmovdqu ymmword [rdi], ymm0 add rdi, sizeof(ymmword) sub r14, sizeof(ymmword)/sizeof(qword) jg .clearLoop vmovdqu xmmword [rdi], xmm0 mov qword [rdi+sizeof(xmmword)], rax lea r14, [r8+sizeof(ymmword)/sizeof(qword)-1] ; a_counter = (redLen+3) & (-4) and r14,-(sizeof(ymmword)/sizeof(qword)) align IPP_ALIGN_FACTOR ;; ;; process b[] by quadruples (b[j], b[j+1], b[j+2] and b[j+3]) per pass ;; .loop4_B: sub r8, sizeof(ymmword)/sizeof(qword) jl .exit_loop4_B mov rbx, qword [rbp] ; rbx = b[j] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[j+1] vpbroadcastq ymm5, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm9, edx vpbroadcastq ymm9, xmm9 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax mov rbx, qword [rbp+sizeof(qword)*2] ; rbx = b[j+2] vpbroadcastq ymm6, qword [rbp+sizeof(qword)*2] mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi] add r12, rax mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi+sizeof(qword)] add r13, rax vmovd xmm10, edx vpbroadcastq ymm10, xmm10 mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] add r12, rax shr r12, DIGIT_BITS mov rax, rdx ; ac3 += pn[1]*y2 imul rax, qword [rcx+sizeof(qword)] add r13, rax add r13, r12 mov rbx, qword [rbp+sizeof(qword)*3] ; rbx = b[j+3] vpbroadcastq ymm7, qword [rbp+sizeof(qword)*3] imul rbx, qword [rsi] ; ac3 += pa[0]*b[j+3] add r13, rbx mov rdx, r13 ; y3 = (ac3*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK vmovd xmm11, edx vpbroadcastq ymm11, xmm11 imul rdx, qword [rcx] ; ac3 += pn[0]*y3 add r13, rdx shr r13, DIGIT_BITS vmovq xmm0, r13 vpaddq ymm0, ymm0, ymmword [rdi+sizeof(ymmword)] vmovdqu ymmword [rdi+sizeof(ymmword)], ymm0 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter ;; (vb0) ymm4 = {b0:b0:b0:b0} ;; (vb1) ymm5 = {b1:b1:b1:b1} ;; (vb2) ymm6 = {b2:b2:b2:b2} ;; (vb3) ymm7 = {b3:b3:b3:b3} ;; (vy0) ymm8 = {y0:y0:y0:y0} ;; (vy1) ymm9 = {y1:y1:y1:y1} ;; (vy2) ymm10= {y2:y2:y2:y2} ;; (vy3) ymm11= {y3:y3:y3:y3} sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .loop16_A: sub r11, 4*sizeof(ymmword)/sizeof(qword) jl .exit_loop16_A vmovdqu ymm0, ymmword [rdi] ; r0 vmovdqu ymm1, ymmword [rdi+sizeof(ymmword)] ; r1 vmovdqu ymm2, ymmword [rdi+sizeof(ymmword)*2] ; r2 vmovdqu ymm3, ymmword [rdi+sizeof(ymmword)*3] ; r3 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)] ; r1 += vb0 * (__m256i*)(pa)[j+1] + vy0 * (__m256i*)(pn)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*2] ; r2 += vb0 * (__m256i*)(pa)[j+2] + vy0 * (__m256i*)(pn)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm4, ymmword [rsi+sizeof(ymmword)*3] ; r3 += vb0 * (__m256i*)(pa)[j+3] + vy0 * (__m256i*)(pn)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)] ; r1 += vb1 * (__m256i*)(pa-1)[j+1] + vy1 * (__m256i*)(pn-1)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*2] ; r2 += vb1 * (__m256i*)(pa-1)[j+2] + vy1 * (__m256i*)(pn-1)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)+sizeof(ymmword)*3] ; r3 += vb1 * (__m256i*)(pa-1)[j+3] + vy1 * (__m256i*)(pn-1)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)] ; r1 += vb2 * (__m256i*)(pa-2)[j+1] + vy2 * (__m256i*)(pn-2)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*2] ; r2 += vb2 * (__m256i*)(pa-2)[j+2] + vy2 * (__m256i*)(pn-2)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2+sizeof(ymmword)*3] ; r3 += vb2 * (__m256i*)(pa-2)[j+3] + vy2 * (__m256i*)(pn-2)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)] ; r1 += vb3 * (__m256i*)(pa-3)[j+1] + vy3 * (__m256i*)(pn-3)[j+1] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*2] ; r2 += vb3 * (__m256i*)(pa-3)[j+2] + vy3 * (__m256i*)(pn-3)[j+2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm12, ymm7, ymmword [rsi-sizeof(qword)*3+sizeof(ymmword)*3] ; r3 += vb3 * (__m256i*)(pa-3)[j+3] + vy3 * (__m256i*)(pn-3)[j+3] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm13 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)], ymm1 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*2], ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)+sizeof(ymmword)*3], ymm3 add rdi, sizeof(ymmword)*4 add rsi, sizeof(ymmword)*4 add rcx, sizeof(ymmword)*4 jmp .loop16_A .exit_loop16_A: add r11, 4*(sizeof(ymmword)/sizeof(qword)) jz .exitA .loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exitA vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm2 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2] ; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm1, ymm7, ymmword [rsi-sizeof(qword)*3] ; r0 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpaddq ymm0, ymm0, ymm1 vpmuludq ymm2, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm0, ymm0, ymm2 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .loop4_A .exitA: vpmuludq ymm2, ymm6, ymmword [rsi-sizeof(qword)*2] ; r2 += vb3 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpmuludq ymm12, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm3, ymm7, ymmword [rsi-sizeof(qword)*3] ; r3 += vb3 * (__m256i*)(pa-3)[j] + vy3 * (__m256i*)(pn-3)[j] vpmuludq ymm13, ymm11,ymmword [rcx-sizeof(qword)*3] vpaddq ymm3, ymm3, ymm13 vpaddq ymm2, ymm2, ymm3 vmovdqu ymmword [rdi-sizeof(ymmword)], ymm2 jmp .loop4_B ;; ;; process latest b[redLen-3], b[redLen-2] and b[redLen-1] ;; .exit_loop4_B: mov rbx, qword [rbp] ; rbx = b[redLen-3] vpbroadcastq ymm4, qword [rbp] mov rdi, qword [rsp+pResult] ; restore pointer to destination mov rsi, qword [rsp+pA] ; A operand mov rcx, qword [rsp+pM] ; modulus mov r10, qword [rdi] mov r11, qword [rdi+sizeof(qword)] mov r12, qword [rdi+sizeof(qword)*2] mov r13, qword [rdi+sizeof(qword)*3] mov rax, rbx ; ac0 = pa[0]*b[j]+pr[0] imul rax, qword [rsi] add r10, rax mov rdx, r10 ; y0 = (ac0*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac1 = pa[1]*b[j]+pr[1] imul rax, qword [rsi+sizeof(qword)] add r11, rax mov rax, rbx ; ac2 = pa[2]*b[j]+pr[2] imul rax, qword [rsi+sizeof(qword)*2] add r12, rax mov rax, rbx ; ac3 = pa[3]*b[j]+pr[3] imul rax, qword [rsi+sizeof(qword)*3] add r13, rax vmovd xmm8, edx vpbroadcastq ymm8, xmm8 mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax shr r10, DIGIT_BITS mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax add r11, r10 mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax mov rax, rdx ; ac3 += pn[3]*y0 imul rax, qword [rcx+sizeof(qword)*3] add r13, rax mov rbx, qword [rbp+sizeof(qword)] ; rbx = b[redLen-2] vpbroadcastq ymm5, qword [rbp+sizeof(qword)] mov rax, rbx ; ac1 += pa[0]*b[j+1] imul rax, qword [rsi] add r11, rax mov rdx, r11 ; y1 = (ac1*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[1]*b[j+1] imul rax, qword [rsi+sizeof(qword)] add r12, rax mov rax, rbx ; ac3 += pa[2]*b[j+1] imul rax, qword [rsi+sizeof(qword)*2] add r13, rax vmovd xmm9, edx vpbroadcastq ymm9, xmm9 mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] add r11, rax shr r11, DIGIT_BITS mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] add r12, rax add r12, r11 mov rax, rdx ; ac3 += pn[2]*y1 imul rax, qword [rcx+sizeof(qword)*2] add r13, rax mov rbx, qword [rbp+sizeof(qword)*2] ; rbx = b[redLen-1] vpbroadcastq ymm6, qword [rbp+sizeof(qword)*2] mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi] add r12, rax mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r9d and edx, DIGIT_MASK mov rax, rbx ; ac2 += pa[0]*b[j+2] imul rax, qword [rsi+sizeof(qword)] add r13, rax vmovd xmm10, edx vpbroadcastq ymm10, xmm10 mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] add r12, rax shr r12, DIGIT_BITS mov rax, rdx ; ac3 += pn[1]*y2 imul rax, qword [rcx+sizeof(qword)] add r13, rax add r13, r12 mov qword [rdi], r13 ; pr[0] = ac3 add rbp, sizeof(qword)*4 add rsi, sizeof(qword)*4 add rcx, sizeof(qword)*4 add rdi, sizeof(ymmword) mov r11, r14 ; init a_counter sub r11, sizeof(ymmword)/sizeof(qword) align IPP_ALIGN_FACTOR .rem_loop4_A: sub r11, sizeof(ymmword)/sizeof(qword) jl .exit_rem_loop4_A vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm4, ymmword [rsi] ; r0 += vb0 * (__m256i*)(pa)[j] + vy0 * (__m256i*)(pn)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm8, ymmword [rcx] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm5, ymmword [rsi-sizeof(qword)] ; r0 += vb1 * (__m256i*)(pa-1)[j] + vy1 * (__m256i*)(pn-1)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm9, ymmword [rcx-sizeof(qword)] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2]; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vmovdqu ymmword [rdi+sizeof(qword)-sizeof(ymmword)], ymm0 add rdi, sizeof(ymmword) add rsi, sizeof(ymmword) add rcx, sizeof(ymmword) jmp .rem_loop4_A .exit_rem_loop4_A: vmovdqu ymm0, ymmword [rdi] ; r0 vpmuludq ymm12, ymm6, ymmword [rsi-sizeof(qword)*2]; r0 += vb2 * (__m256i*)(pa-2)[j] + vy2 * (__m256i*)(pn-2)[j] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm10,ymmword [rcx-sizeof(qword)*2] vpaddq ymm0, ymm0, ymm13 vmovdqu ymmword [rdi+sizeof(qword)-sizeof(ymmword)], ymm0 ;; ;; normalize ;; mov rdi, qword [rsp+pR] mov rsi, qword [rsp+pResult] mov r8, qword [rsp+redLen] xor rax, rax .norm_loop: add rax, qword [rsi] add rsi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi], rdx add rdi, sizeof(qword) sub r8, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpMontMul4n3_avx2 %endif ; _IPP32E_L9 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmontreductionm7as.asm000066400000000000000000001247071470420105600302600ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpMontRedAdc_BNU() ; ; ; History: ; Extra reduction (R=A-M) has been added to perform MontReduction safe ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpbnumulschool.inc" %include "pcpvariant.inc" %if (_ADCOX_NI_ENABLING_ == _FEATURE_OFF_) || (_ADCOX_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_M7) && (_IPP32E < _IPP32E_L9) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; fixed size reduction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro MREDUCE_FIX_STEP 12.nolist %xdefine %%mSize %1 %xdefine %%X7 %2 %xdefine %%X6 %3 %xdefine %%X5 %4 %xdefine %%X4 %5 %xdefine %%X3 %6 %xdefine %%X2 %7 %xdefine %%X1 %8 %xdefine %%X0 %9 %xdefine %%rSrc %10 %xdefine %%U %11 %xdefine %%rCarry %12 %if %%mSize > 0 mul %%U xor %%rCarry, %%rCarry add %%X0, rax %if %%mSize > 1 mov rax, qword [%%rSrc+sizeof(qword)] adc %%rCarry, rdx mul %%U add %%X1, %%rCarry adc rdx, 0 xor %%rCarry, %%rCarry add %%X1, rax %if %%mSize > 2 mov rax, qword [%%rSrc+sizeof(qword)*2] adc %%rCarry, rdx mul %%U add %%X2, %%rCarry adc rdx, 0 xor %%rCarry, %%rCarry add %%X2, rax %if %%mSize > 3 mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%rCarry, rdx mul %%U add %%X3, %%rCarry adc rdx, 0 xor %%rCarry, %%rCarry add %%X3, rax %if %%mSize == 4 adc %%X4, rdx adc %%rCarry, 0 add %%X4, qword [rsp+carry] %endif %endif ;; mSize==4 %if %%mSize == 3 adc %%X3, rdx adc %%rCarry, 0 add %%X3, qword [rsp+carry] %endif %endif ;; mSize==3 %if %%mSize == 2 adc %%X2, rdx adc %%rCarry, 0 add %%X2, qword [rsp+carry] %endif %endif ;; mSize==2 %if %%mSize == 1 adc %%X1, rdx adc %%rCarry, 0 add %%X1, qword [rsp+carry] %endif %endif ;; mSize==1 adc %%rCarry, 0 mov qword [rsp+carry], %%rCarry %endmacro %macro MREDUCE_FIX 14.nolist %xdefine %%mSize %1 %xdefine %%rDst %2 %xdefine %%rSrc %3 %xdefine %%M0 %4 %xdefine %%X7 %5 %xdefine %%X6 %6 %xdefine %%X5 %7 %xdefine %%X4 %8 %xdefine %%X3 %9 %xdefine %%X2 %10 %xdefine %%X1 %11 %xdefine %%X0 %12 %xdefine %%U %13 %xdefine %%rCarry %14 %if %%mSize > 0 mov %%U, %%X0 imul %%U, %%M0 mov rax, qword [%%rSrc] MREDUCE_FIX_STEP %%mSize, %%X7,%%X6,%%X5,%%X4,%%X3,%%X2,%%X1,%%X0, %%rSrc, %%U, %%rCarry %if %%mSize > 1 mov %%U, %%X1 imul %%U, %%M0 mov rax, qword [%%rSrc] MREDUCE_FIX_STEP %%mSize, %%X0,%%X7,%%X6,%%X5,%%X4,%%X3,%%X2,%%X1, %%rSrc, %%U, %%rCarry %if %%mSize > 2 mov %%U, %%X2 imul %%U, %%M0 mov rax, qword [%%rSrc] MREDUCE_FIX_STEP %%mSize, %%X1,%%X0,%%X7,%%X6,%%X5,%%X4,%%X3,%%X2, %%rSrc, %%U, %%rCarry %if %%mSize > 3 ; mSize == 4 mov %%U, %%X3 imul %%U, %%M0 mov rax, qword [%%rSrc] MREDUCE_FIX_STEP %%mSize, %%X2,%%X1,%%X0,%%X7,%%X6,%%X5,%%X4,%%X3, %%rSrc, %%U, %%rCarry mov %%X0, %%X4 ; {X3:X2:X1:X0} = {X7:X6:X5:X4} sub %%X4, qword [%%rSrc] ; {X7:X6:X5:X4}-= modulus mov %%X1, %%X5 sbb %%X5, qword [%%rSrc+sizeof(qword)] mov %%X2, %%X6 sbb %%X6, qword [%%rSrc+sizeof(qword)*2] mov %%X3, %%X7 sbb %%X7, qword [%%rSrc+sizeof(qword)*3] sbb %%rCarry, 0 cmovc %%X4, %%X0 ; dst = borrow? {X3:X2:X1:X0} : {X7:X6:X5:X4} mov qword [%%rDst], %%X4 cmovc %%X5, %%X1 mov qword [%%rDst+sizeof(qword)], %%X5 cmovc %%X6, %%X2 mov qword [%%rDst+sizeof(qword)*2], %%X6 cmovc %%X7, %%X3 mov qword [%%rDst+sizeof(qword)*3], %%X7 %endif %endif %endif %endif %if %%mSize == 3 mov %%X0, %%X3 ; {X2:X1:X0} = {X5:X4:X3} sub %%X3, qword [%%rSrc] ; {X5:X4:X3}-= modulus mov %%X1, %%X4 sbb %%X4, qword [%%rSrc+sizeof(qword)] mov %%X2, %%X5 sbb %%X5, qword [%%rSrc+sizeof(qword)*2] sbb %%rCarry, 0 cmovc %%X3, %%X0 ; dst = borrow? {X2:X1:X0} : {X5:X4:X3} mov qword [%%rDst], %%X3 cmovc %%X4, %%X1 mov qword [%%rDst+sizeof(qword)], %%X4 cmovc %%X5, %%X2 mov qword [%%rDst+sizeof(qword)*2], %%X5 %endif ; mSize==3 %if %%mSize == 2 mov %%X0, %%X2 ; {X1:X0} = {X3:X2} sub %%X2, qword [%%rSrc] ; {X3:X2}-= modulus mov %%X1, %%X3 sbb %%X3, qword [%%rSrc+sizeof(qword)] sbb %%rCarry, 0 cmovc %%X2, %%X0 ; dst = borrow? {X1:X0} : {X3:X2} mov qword [%%rDst], %%X2 cmovc %%X3, %%X1 mov qword [%%rDst+sizeof(qword)], %%X3 %endif ; mSize==2 %if %%mSize == 1 mov %%X0, %%X1 ; X1 = X0 sub %%X1, qword [%%rSrc] ; X1 -= modulus sbb %%rCarry, 0 cmovc %%X1, %%X0 ; dst = borrow? X0 : X1 mov qword [%%rDst], %%X1 %endif ; mSize==1 %endmacro %if (_IPP32E <= _IPP32E_Y8) ;; ;; Pre- Sandy Bridge specific code ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; product = + modulus * U0 ;; main body: product = + modulus * U0 %macro MLAx1 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 ALIGN IPP_ALIGN_FACTOR %%L_1: mul %%U0 xor %%T2, %%T2 add %%T0, qword [%%rDst+%%idx*sizeof(qword)-sizeof(qword)] adc %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] adc %%T2, rdx mov qword [%%rDst+%%idx*sizeof(qword)-sizeof(qword)], %%T0 mul %%U0 xor %%T3, %%T3 add %%T1, qword [%%rDst+%%idx*sizeof(qword)] adc %%T2, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] adc %%T3, rdx mov qword [%%rDst+%%idx*sizeof(qword)], %%T1 mul %%U0 xor %%T0, %%T0 add %%T2, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)] adc %%T3, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] adc %%T0, rdx mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T2 mul %%U0 xor %%T1, %%T1 add %%T3, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2] adc %%T0, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] adc %%T1, rdx mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T3 add %%idx, 4 jnc %%L_1 %endmacro ;; elipogue: product = modulus * U0, (srcLen=4*n+1) %macro MM_MLAx1_4N_1_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov rax, qword [%%rSrc+sizeof(qword)] mov %%idx, qword [rsp+counter] mul %%U0 xor %%T3, %%T3 add %%T1, qword [%%rDst] adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] adc %%T3, rdx mov qword [%%rDst], %%T1 mul %%U0 xor %%T0, %%T0 add %%T2, qword [%%rDst+sizeof(qword)] adc %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T0, rdx mov qword [%%rDst+sizeof(qword)], %%T2 mul %%U0 add %%T3, qword [%%rDst+sizeof(qword)*2] adc %%T0, rax adc rdx, 0 xor rax, rax mov qword [%%rDst+sizeof(qword)*2], %%T3 add %%T0, qword [%%rDst+sizeof(qword)*3] adc rdx, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T0 mov qword [%%rDst+sizeof(qword)*4], rdx mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro ;; elipogue: product = modulus * U0, (srcLen=4*n+4) %macro MM_MLAx1_4N_4_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov rax, qword [%%rSrc+sizeof(qword)*2] mov %%idx, qword [rsp+counter] mul %%U0 xor %%T3, %%T0 add %%T1, qword [%%rDst+sizeof(qword)] adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T3, rdx mov qword [%%rDst+sizeof(qword)], %%T1 mul %%U0 add %%T2, qword [%%rDst+sizeof(qword)*2] adc %%T3, rax adc rdx, 0 xor rax, rax mov qword [%%rDst+sizeof(qword)*2], %%T2 add %%T3, qword [%%rDst+sizeof(qword)*3] adc rdx, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T3 mov qword [%%rDst+sizeof(qword)*4], rdx mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro ;; elipogue: product = modulus * U0, (srcLen=4*n+3) %macro MM_MLAx1_4N_3_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov rax, qword [%%rSrc+sizeof(qword)*3] mov %%idx, qword [rsp+counter] mul %%U0 add %%T1, qword [%%rDst+sizeof(qword)*2] adc %%T2, rax adc rdx, 0 xor rax, rax mov qword [%%rDst+sizeof(qword)*2], %%T1 add %%T2, qword [%%rDst+sizeof(qword)*3] adc rdx, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T2 mov qword [%%rDst+sizeof(qword)*4], rdx mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro ;; elipogue: product = modulus * U0, (srcLen=4*n+2) %macro MM_MLAx1_4N_2_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov %%idx, qword [rsp+counter] xor rax, rax add %%T1, qword [%%rDst+sizeof(qword)*3] adc %%T2, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T1 mov qword [%%rDst+sizeof(qword)*4], %%T2 mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro %endif %if (_IPP32E >= _IPP32E_E9) ;; ;; Sandy Bridge specific code ;; %macro MLAx1 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 ALIGN IPP_ALIGN_FACTOR %%L_1: mul %%U0 xor %%T2, %%T2 add %%T0, qword [%%rDst+%%idx*sizeof(qword)-sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)-sizeof(qword)], %%T0 adc %%T1, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] adc %%T2, rdx mul %%U0 xor %%T3, %%T3 add %%T1, qword [%%rDst+%%idx*sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)], %%T1 adc %%T2, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*2] adc %%T3, rdx mul %%U0 xor %%T0, %%T0 add %%T2, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T2 adc %%T3, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*3] adc %%T0, rdx mul %%U0 xor %%T1, %%T1 add %%T3, qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T3 adc %%T0, rax mov rax, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)*4] adc %%T1, rdx add %%idx, 4 jnc %%L_1 %endmacro %macro MM_MLAx1_4N_1_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov rax, qword [%%rSrc+sizeof(qword)] mov %%idx, qword [rsp+counter] mul %%U0 xor %%T3, %%T3 add %%T1, qword [%%rDst] mov qword [%%rDst], %%T1 adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] adc %%T3, rdx mul %%U0 xor %%T0, %%T0 add %%T2, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T2 adc %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T0, rdx mul %%U0 add %%T3, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T3 adc %%T0, rax adc rdx, 0 xor rax, rax add %%T0, qword [%%rDst+sizeof(qword)*3] adc rdx, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T0 mov qword [%%rDst+sizeof(qword)*4], rdx mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro %macro MM_MLAx1_4N_4_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov rax, qword [%%rSrc+sizeof(qword)*2] mov %%idx, qword [rsp+counter] mul %%U0 xor %%T3, %%T0 add %%T1, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T1 adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] adc %%T3, rdx mul %%U0 add %%T2, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T2 adc %%T3, rax adc rdx, 0 xor rax, rax add %%T3, qword [%%rDst+sizeof(qword)*3] adc rdx, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T3 mov qword [%%rDst+sizeof(qword)*4], rdx mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro %macro MM_MLAx1_4N_3_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov rax, qword [%%rSrc+sizeof(qword)*3] mov %%idx, qword [rsp+counter] mul %%U0 add %%T1, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T1 adc %%T2, rax adc rdx, 0 xor rax, rax add %%T2, qword [%%rDst+sizeof(qword)*3] adc rdx, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T2 mov qword [%%rDst+sizeof(qword)*4], rdx mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro %macro MM_MLAx1_4N_2_ELOG 8.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 mov %%idx, qword [rsp+counter] xor rax, rax add %%T1, qword [%%rDst+sizeof(qword)*3] adc %%T2, qword [%%rDst+sizeof(qword)*4] adc rax, 0 mov qword [%%rDst+sizeof(qword)*3], %%T1 mov qword [%%rDst+sizeof(qword)*4], %%T2 mov qword [rsp+carry], rax add %%rDst, sizeof(qword) %endmacro %endif ; ; prologue: ; pre-compute: ; - u0 = product[0]*m0 ; - u1 = (product[1] + LO(modulo[1]*u0) + HI(modulo[0]*u0) carry(product[0]+LO(modulo[0]*u0)))*m0 ; %macro MMx2_PLOG 10.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%m0 %4 %xdefine %%U0 %5 %xdefine %%U1 %6 %xdefine %%T0 %7 %xdefine %%T1 %8 %xdefine %%T2 %9 %xdefine %%T3 %10 mov %%U0, qword [%%rDst+%%idx*sizeof(qword)] ; product[0] imul %%U0, %%m0 ; u0 = product[0]*m0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)] ; modulo[0]*u0 mul %%U0 mov %%U1, qword [%%rSrc+%%idx*sizeof(qword)+sizeof(qword)] ; modulo[1]*u0 imul %%U1, %%U0 mov %%T0, rax ; save modulo[0]*u0 mov %%T1, rdx add rax, qword [rdi+%%idx*sizeof(qword)] ; a[1] = product[1] + LO(modulo[1]*u0) adc rdx, qword [rdi+%%idx*sizeof(qword)+sizeof(qword)] ; + HI(modulo[0]*u0) add %%U1, rdx ; + carry(product[0]+LO(modulo[0]*u0)) imul %%U1, %%m0 ; u1 = a[1]*m0 mov rax, qword [%%rSrc+%%idx*sizeof(qword)] xor %%T2, %%T2 %endmacro %if (_IPP32E <= _IPP32E_Y8) ;; ;; Pre- Sandy Bridge specific code ;; %macro MM_MLAx2_4N_1_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += modulus[mSize-1]*U1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T0, qword [%%rDst+sizeof(qword)*3] adc %%T1, rax mov qword [%%rDst+sizeof(qword)*3], %%T0 adc %%T2, rdx xor rax, rax add %%T1, qword [%%rDst+sizeof(qword)*4] adc %%T2, qword [%%rDst+sizeof(qword)*5] adc rax, 0 add %%T1, qword [rsp+carry] adc %%T2, 0 adc rax, 0 mov qword [%%rDst+sizeof(qword)*4], %%T1 mov qword [%%rDst+sizeof(qword)*5], %%T2 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %macro MM_MLAx2_4N_2_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += a[mSize-2]*U1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T2, rdx mul %%U0 ; {T3:T2:T1} += a[mSize-1]*U0 + r[mSize-2] add %%T0, qword [%%rDst+sizeof(qword)*2] adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T2, rdx mov qword [%%rDst+sizeof(qword)*2], %%T0 adc %%T3, 0 mul %%U1 ; {T3:T2} += a[mSize-1]*B1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T1, qword [%%rDst+sizeof(qword)*3] adc %%T2, rax mov qword [%%rDst+sizeof(qword)*3], %%T1 adc %%T3, rdx xor rax, rax add %%T2, qword [%%rDst+sizeof(qword)*4] adc %%T3, qword [%%rDst+sizeof(qword)*5] adc rax, 0 add %%T2, qword [rsp+carry] adc %%T3, 0 adc rax, 0 mov qword [%%rDst+sizeof(qword)*4], %%T2 mov qword [%%rDst+sizeof(qword)*5], %%T3 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %macro MM_MLAx2_4N_3_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += a[mSize-3]*U1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[mSize-2] adc %%T2, rdx mul %%U0 ; {T3:T2:T1} += a[mSize-2]*U0 + r[mSize-3] add %%T0, qword [%%rDst+sizeof(qword)] adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[mSize-2] adc %%T2, rdx mov qword [%%rDst+sizeof(qword)], %%T0 adc %%T3, 0 mul %%U1 ; {T3:T2} += a[mSize-2]*U1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T3, rdx mul %%U0 ; {T0:T3:T2} += a[mSize-1]*U0 + r[mSize-2] add %%T1, qword [rdi+sizeof(qword)*2] adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T3, rdx mov qword [rdi+sizeof(qword)*2], %%T1 adc %%T0, 0 mul %%U1 ; {T0:T3} += a[mSize-1]*U1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T2, qword [rdi+sizeof(qword)*3] adc %%T3, rax mov qword [rdi+sizeof(qword)*3], %%T2 adc %%T0, rdx xor rax, rax add %%T3, qword [rdi+sizeof(qword)*4] adc %%T0, qword [rdi+sizeof(qword)*5] adc rax, 0 add %%T3, qword [rsp+carry] adc %%T0, 0 adc rax, 0 mov qword [rdi+sizeof(qword)*4], %%T3 mov qword [rdi+sizeof(qword)*5], %%T0 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %macro MM_MLAx2_4N_4_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += a[mSize-4]*U1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx mul %%U0 ; {T3:T2:T1} += a[mSize-3]*U0 + r[mSize-4] add %%T0, qword [%%rDst] adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[mSize-3] adc %%T2, rdx mov qword [%%rDst], %%T0 adc %%T3, 0 mul %%U1 ; {T3:T2} += a[mSize-3]*U1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[mSize-2] adc %%T3, rdx mul %%U0 ; {T0:T3:T2} += a[mSize-2]*U0 + r[mSize-3] add %%T1, qword [%%rDst+sizeof(qword)] adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] adc %%T3, rdx mov qword [%%rDst+sizeof(qword)], %%T1 adc %%T0, 0 mul %%U1 ; {T0:T3} += a[mSize-2]*U1 xor %%T1, %%T1 add %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T0, rdx mul %%U0 ; {T1:T0:T3} += a[mSize-1]*U0 + r[mSize-2] add %%T2, qword [%%rDst+sizeof(qword)*2] adc %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T0, rdx mov qword [%%rDst+sizeof(qword)*2], %%T2 adc %%T1, 0 mul %%U1 ; {T1:T0} += a[mSize-1]*U1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T3, qword [%%rDst+sizeof(qword)*3] adc %%T0, rax mov qword [%%rDst+sizeof(qword)*3], %%T3 adc %%T1, rdx xor rax, rax add %%T0, qword [%%rDst+sizeof(qword)*4] adc %%T1, qword [%%rDst+sizeof(qword)*5] adc rax, 0 add %%T0, qword [rsp+carry] adc %%T1, 0 adc rax, 0 mov qword [%%rDst+sizeof(qword)*4], %%T0 mov qword [%%rDst+sizeof(qword)*5], %%T1 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %endif %if (_IPP32E >= _IPP32E_E9) ;; ;; Sandy Bridge specific code ;; %macro MM_MLAx2_4N_1_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += modulus[mSize-1]*U1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T0, qword [%%rDst+sizeof(qword)*3] mov qword [%%rDst+sizeof(qword)*3], %%T0 adc %%T1, rax adc %%T2, rdx xor rax, rax add %%T1, qword [%%rDst+sizeof(qword)*4] adc %%T2, qword [%%rDst+sizeof(qword)*5] adc rax, 0 add %%T1, qword [rsp+carry] adc %%T2, 0 adc rax, 0 mov qword [%%rDst+sizeof(qword)*4], %%T1 mov qword [%%rDst+sizeof(qword)*5], %%T2 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %macro MM_MLAx2_4N_2_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += a[mSize-2]*U1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T2, rdx mul %%U0 ; {T3:T2:T1} += a[mSize-1]*U0 + r[mSize-2] add %%T0, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T0 adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T2, rdx adc %%T3, 0 mul %%U1 ; {T3:T2} += a[mSize-1]*B1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T1, qword [%%rDst+sizeof(qword)*3] mov qword [%%rDst+sizeof(qword)*3], %%T1 adc %%T2, rax adc %%T3, rdx xor rax, rax add %%T2, qword [%%rDst+sizeof(qword)*4] adc %%T3, qword [%%rDst+sizeof(qword)*5] adc rax, 0 add %%T2, qword [rsp+carry] adc %%T3, 0 adc rax, 0 mov qword [%%rDst+sizeof(qword)*4], %%T2 mov qword [%%rDst+sizeof(qword)*5], %%T3 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %macro MM_MLAx2_4N_3_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += a[mSize-3]*U1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[mSize-2] adc %%T2, rdx mul %%U0 ; {T3:T2:T1} += a[mSize-2]*U0 + r[mSize-3] add %%T0, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T0 adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[mSize-2] adc %%T2, rdx adc %%T3, 0 mul %%U1 ; {T3:T2} += a[mSize-2]*U1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T3, rdx mul %%U0 ; {T0:T3:T2} += a[mSize-1]*U0 + r[mSize-2] add %%T1, qword [rdi+sizeof(qword)*2] mov qword [rdi+sizeof(qword)*2], %%T1 adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T3, rdx adc %%T0, 0 mul %%U1 ; {T0:T3} += a[mSize-1]*U1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T2, qword [rdi+sizeof(qword)*3] mov qword [rdi+sizeof(qword)*3], %%T2 adc %%T3, rax adc %%T0, rdx xor rax, rax add %%T3, qword [rdi+sizeof(qword)*4] adc %%T0, qword [rdi+sizeof(qword)*5] adc rax, 0 add %%T3, qword [rsp+carry] adc %%T0, 0 adc rax, 0 mov qword [rdi+sizeof(qword)*4], %%T3 mov qword [rdi+sizeof(qword)*5], %%T0 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %macro MM_MLAx2_4N_4_ELOG 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc %2 %xdefine %%idx %3 %xdefine %%U0 %4 %xdefine %%U1 %5 %xdefine %%T0 %6 %xdefine %%T1 %7 %xdefine %%T2 %8 %xdefine %%T3 %9 mul %%U1 ; {T2:T1} += a[mSize-4]*U1 xor %%T3, %%T3 add %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[lenA-3] adc %%T2, rdx mul %%U0 ; {T3:T2:T1} += a[mSize-3]*U0 + r[mSize-4] add %%T0, qword [%%rDst] mov qword [%%rDst], %%T0 adc %%T1, rax mov rax, qword [%%rSrc+sizeof(qword)] ; a[mSize-3] adc %%T2, rdx adc %%T3, 0 mul %%U1 ; {T3:T2} += a[mSize-3]*U1 xor %%T0, %%T0 add %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a[mSize-2] adc %%T3, rdx mul %%U0 ; {T0:T3:T2} += a[mSize-2]*U0 + r[mSize-3] add %%T1, qword [%%rDst+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T1 adc %%T2, rax mov rax, qword [%%rSrc+sizeof(qword)*2] ; a{lenA-2] adc %%T3, rdx adc %%T0, 0 mul %%U1 ; {T0:T3} += a[mSize-2]*U1 xor %%T1, %%T1 add %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T0, rdx mul %%U0 ; {T1:T0:T3} += a[mSize-1]*U0 + r[mSize-2] add %%T2, qword [%%rDst+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T2 adc %%T3, rax mov rax, qword [%%rSrc+sizeof(qword)*3] ; a[mSize-1] adc %%T0, rdx adc %%T1, 0 mul %%U1 ; {T1:T0} += a[mSize-1]*U1 + r[mSize-1] mov %%idx, qword [rsp+counter] add %%T3, qword [%%rDst+sizeof(qword)*3] mov qword [%%rDst+sizeof(qword)*3], %%T3 adc %%T0, rax adc %%T1, rdx xor rax, rax add %%T0, qword [%%rDst+sizeof(qword)*4] adc %%T1, qword [%%rDst+sizeof(qword)*5] adc rax, 0 add %%T0, qword [rsp+carry] adc %%T1, 0 adc rax, 0 mov qword [%%rDst+sizeof(qword)*4], %%T0 mov qword [%%rDst+sizeof(qword)*5], %%T1 mov qword [rsp+carry], rax add %%rDst, sizeof(qword)*2 %endmacro %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro SBB_x4 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc1 %2 %xdefine %%rSrc2 %3 %xdefine %%idx %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 %xdefine %%rcf %9 ALIGN IPP_ALIGN_FACTOR %%L_1: add %%rcf, %%rcf ; restore cf mov %%T0, qword [%%rSrc1+%%idx*sizeof(qword)] sbb %%T0, qword [%%rSrc2+%%idx*sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)], %%T0 mov %%T1, qword [%%rSrc1+%%idx*sizeof(qword)+sizeof(qword)] sbb %%T1, qword [%%rSrc2+%%idx*sizeof(qword)+sizeof(qword)] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T1 mov %%T2, qword [%%rSrc1+%%idx*sizeof(qword)+sizeof(qword)*2] sbb %%T2, qword [%%rSrc2+%%idx*sizeof(qword)+sizeof(qword)*2] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T2 mov %%T3, qword [%%rSrc1+%%idx*sizeof(qword)+sizeof(qword)*3] sbb %%T3, qword [%%rSrc2+%%idx*sizeof(qword)+sizeof(qword)*3] mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3], %%T3 sbb %%rcf, %%rcf ; save cf add %%idx, 4 jnc %%L_1 %endmacro %macro SBB_TAIL 9.nolist %xdefine %%N %1 %xdefine %%rDst %2 %xdefine %%rSrc1 %3 %xdefine %%rSrc2 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 %xdefine %%rcf %9 add %%rcf, %%rcf ; restore cf mov idx, qword [rsp+counter] ; restore counter %if %%N > 3 mov %%T0, qword [%%rSrc1] sbb %%T0, qword [%%rSrc2] mov qword [%%rDst], %%T0 %endif %if %%N > 2 mov %%T1, qword [%%rSrc1+sizeof(qword)] sbb %%T1, qword [%%rSrc2+sizeof(qword)] mov qword [%%rDst+sizeof(qword)], %%T1 %endif %if %%N > 1 mov %%T2, qword [%%rSrc1+sizeof(qword)*2] sbb %%T2, qword [%%rSrc2+sizeof(qword)*2] mov qword [%%rDst+sizeof(qword)*2], %%T2 %endif %if %%N > 0 mov %%T3, qword [%%rSrc1+sizeof(qword)*3] sbb %%T3, qword [%%rSrc2+sizeof(qword)*3] mov qword [%%rDst+sizeof(qword)*3], %%T3 %endif sbb rax, 0 sbb %%rcf, %%rcf ; set cf %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; dst[] = cf? src1[] : src2[] %macro CMOV_x4 9.nolist %xdefine %%rDst %1 %xdefine %%rSrc1 %2 %xdefine %%rSrc2 %3 %xdefine %%idx %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 %xdefine %%rcf %9 mov %%T3, %%rcf ; copy cf ALIGN IPP_ALIGN_FACTOR %%L_1: add %%T3, %%T3 ; restore cf mov %%T0, qword [%%rSrc2+%%idx*sizeof(qword)] mov %%T1, qword [%%rSrc1+%%idx*sizeof(qword)] mov %%T2, qword [%%rSrc2+%%idx*sizeof(qword)+sizeof(qword)] mov %%T3, qword [%%rSrc1+%%idx*sizeof(qword)+sizeof(qword)] cmovc %%T0, %%T1 mov qword [%%rDst+%%idx*sizeof(qword)], %%T0 cmovc %%T2, %%T3 mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)], %%T2 mov %%T0, qword [%%rSrc2+%%idx*sizeof(qword)+sizeof(qword)*2] mov %%T1, qword [%%rSrc1+%%idx*sizeof(qword)+sizeof(qword)*2] mov %%T2, qword [%%rSrc2+%%idx*sizeof(qword)+sizeof(qword)*3] mov %%T3, qword [%%rSrc1+%%idx*sizeof(qword)+sizeof(qword)*3] cmovc %%T0, %%T1 mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*2], %%T0 cmovc %%T2, %%T3 mov qword [%%rDst+%%idx*sizeof(qword)+sizeof(qword)*3], %%T2 mov %%T3, %%rcf ; copy cf add %%idx, 4 jnc %%L_1 %endmacro %macro CMOV_TAIL 9.nolist %xdefine %%N %1 %xdefine %%rDst %2 %xdefine %%rSrc1 %3 %xdefine %%rSrc2 %4 %xdefine %%T0 %5 %xdefine %%T1 %6 %xdefine %%T2 %7 %xdefine %%T3 %8 %xdefine %%rcf %9 add %%rcf, %%rcf ; restore cf mov idx, qword [rsp+counter] ; restore counter %if %%N > 3 mov %%T0, qword [%%rSrc2] mov %%T1, qword [%%rSrc1] cmovc %%T0, %%T1 mov qword [%%rDst], %%T0 %endif %if %%N > 2 mov %%T2, qword [%%rSrc2+sizeof(qword)] mov %%T3, qword [%%rSrc1+sizeof(qword)] cmovc %%T2, %%T3 mov qword [%%rDst+sizeof(qword)], %%T2 %endif %if %%N > 1 mov %%T0, qword [%%rSrc2+sizeof(qword)*2] mov %%T1, qword [%%rSrc1+sizeof(qword)*2] cmovc %%T0, %%T1 mov qword [%%rDst+sizeof(qword)*2], %%T0 %endif %if %%N > 0 mov %%T2, qword [%%rSrc2+sizeof(qword)*3] mov %%T3, qword [%%rSrc1+sizeof(qword)*3] cmovc %%T2, %%T3 mov qword [%%rDst+sizeof(qword)*3], %%T2 %endif %endmacro segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ;* void cpMontRedAdc_BNU(Ipp64u* pR, ;* Ipp64u* pBuffer, ;* const Ipp64u* pModulo, int mSize, Ipp64u m0) ;* ;************************************************************* ;; ;; Lib = M7 ;; ;; Caller = ippsMontMul ;; align IPP_ALIGN_FACTOR IPPASM cpMontRedAdc_BNU,PUBLIC %assign LOCAL_FRAME (1+1+1+1)*sizeof(qword) USES_GPR rbx,rbp,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ;pR (rdi) address of the reduction ;pBuffer (rsi) address of the temporary product ;pModulo (rdx) address of the modulus ;mSize (rcx) size of the modulus ;m0 (r8) helper ;; ;; stack structure: %assign pR (0) ; reduction address %assign mSize (pR+sizeof(qword)) ; modulus length (qwords) %assign carry (mSize+sizeof(qword)) ; carry from previous MLAx1 or MLAx2 operation %assign counter (carry+sizeof(qword)) ; counter = 4-mSize mov qword [rsp+carry], 0 ; clear carry movsxd rcx, ecx ; expand modulus length mov r15, r8 ; helper m0 cmp rcx, 5 jge .general_case ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; reducer of the fixed sizes ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cmp rcx, 3 ja .mSize_4 ; rcx=4 jz .mSize_3 ; rcx=3 jp .mSize_2 ; rcx=2 ; mSize_1 ; rcx=1 %xdefine X0 r8 %xdefine X1 r9 %xdefine X2 r10 %xdefine X3 r11 %xdefine X4 r12 %xdefine X5 r13 %xdefine X6 r14 %xdefine X7 rcx align IPP_ALIGN_FACTOR .mSize_1: mov X0, qword [rsi] mov X1, qword [rsi+sizeof(qword)] mov rsi, rdx ; rDst,rSrc, U, M0, T0 MREDUCE_FIX 1, rdi, rsi, r15, X7, X6, X5, X4, X3, X2, X1,X0, rbp,rbx jmp .quit align IPP_ALIGN_FACTOR .mSize_2: mov X0, qword [rsi] mov X1, qword [rsi+sizeof(qword)] mov X2, qword [rsi+sizeof(qword)*2] mov X3, qword [rsi+sizeof(qword)*3] mov rsi, rdx MREDUCE_FIX 2, rdi, rsi, r15, X7, X6, X5, X4, X3, X2, X1,X0, rbp,rbx jmp .quit align IPP_ALIGN_FACTOR .mSize_3: mov X0, qword [rsi] mov X1, qword [rsi+sizeof(qword)] mov X2, qword [rsi+sizeof(qword)*2] mov X3, qword [rsi+sizeof(qword)*3] mov X4, qword [rsi+sizeof(qword)*4] mov X5, qword [rsi+sizeof(qword)*5] mov rsi, rdx MREDUCE_FIX 3, rdi, rsi, r15, X7, X6, X5, X4, X3, X2, X1,X0, rbp,rbx jmp .quit align IPP_ALIGN_FACTOR .mSize_4: mov X0, qword [rsi] mov X1, qword [rsi+sizeof(qword)] mov X2, qword [rsi+sizeof(qword)*2] mov X3, qword [rsi+sizeof(qword)*3] mov X4, qword [rsi+sizeof(qword)*4] mov X5, qword [rsi+sizeof(qword)*5] mov X6, qword [rsi+sizeof(qword)*6] mov X7, qword [rsi+sizeof(qword)*7] mov rsi, rdx MREDUCE_FIX 4, rdi, rsi, r15, X7, X6, X5, X4, X3, X2, X1,X0, rbp,rbx jmp .quit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; general case reducer ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %xdefine U0 r9 ; u0, u1 %xdefine U1 r10 %xdefine T0 r11 ; temporary %xdefine T1 r12 %xdefine T2 r13 %xdefine T3 r14 %xdefine idx rbx ; index %xdefine rDst rdi %xdefine rSrc rsi align IPP_ALIGN_FACTOR .general_case: lea rdi, [rdi+rcx*sizeof(qword)-sizeof(qword)*4] ; save pR+mSzie-4 mov qword [rsp+pR], rdi ; save pR ;mov qword [rsp+mSize], rcx ; save length of modulus mov rdi, rsi ; rdi = pBuffer mov rsi, rdx ; rsi = pModulo lea rdi, [rdi+rcx*sizeof(qword)-sizeof(qword)*4] ; rdi = pBuffer lea rsi, [rsi+rcx*sizeof(qword)-sizeof(qword)*4] ; rsi = pModulus mov idx, dword 4 ; init negative counter sub idx, rcx mov qword [rsp+counter], idx mov rdx, dword 3 and rdx, rcx test rcx,1 jz .even_len_Modulus ; ; modulus of odd length ; .odd_len_Modulus: mov U0, qword [rDst+idx*sizeof(qword)] ; pBuffer[0] imul U0, r15 ; u0 = pBuffer[0]*m0 mov rax, qword [rSrc+idx*sizeof(qword)] ; pModulo[0] mul U0 ; prologue mov T0, rax mov rax, qword [rSrc+idx*sizeof(qword)+sizeof(qword)] mov T1, rdx add idx, 1 jz .skip_mlax1 MLAx1 rdi, rsi, idx, U0, T0,T1,T2,T3 ; pBuffer[] += pModulo[]*u .skip_mlax1: mul U0 xor T2, T2 add qword [rDst+idx*sizeof(qword)-sizeof(qword)], T0 adc T1, rax adc T2, rdx cmp idx, 2 ja .fin_mla1x4n_2 ; idx=3 jz .fin_mla1x4n_3 ; idx=2 jp .fin_mla1x4n_4 ; idx=1 ; fin_mla1x4n_1 ; idx=0 .fin_mla1x4n_1: MM_MLAx1_4N_1_ELOG rdi, rsi, idx, U0, T0,T1,T2,T3 ; [rsp+carry] = rax = cf = pBuffer[]+pModulo[]*u sub rcx, 1 jmp .mla2x4n_1 .fin_mla1x4n_4: MM_MLAx1_4N_4_ELOG rdi, rsi, idx, U0, T0,T1,T2,T3 ; [rsp+carry] = rax = cf = pBuffer[]+pModulo[]*u sub rcx, 1 jmp .mla2x4n_4 .fin_mla1x4n_3: MM_MLAx1_4N_3_ELOG rdi, rsi, idx, U0, T0,T1,T2,T3 ; [rsp+carry] = rax = cf = pBuffer[]+pModulo[]*u sub rcx, 1 jmp .mla2x4n_3 .fin_mla1x4n_2: MM_MLAx1_4N_2_ELOG rdi, rsi, idx, U0, T0,T1,T2,T3 ; [rsp+carry] = rax = cf = pBuffer[]+pModulo[]*u sub rcx, 1 jmp .mla2x4n_2 align IPP_ALIGN_FACTOR ; ; modulus of even length ; .even_len_Modulus: xor rax, rax ; clear carry cmp rdx, 2 ja .mla2x4n_1 ; rdx=1 jz .mla2x4n_2 ; rdx=2 jp .mla2x4n_3 ; rdx=3 ; mla2x4n_4 ; rdx=0 align IPP_ALIGN_FACTOR .mla2x4n_4: MMx2_PLOG rdi, rsi, idx, r15, U0,U1,T0,T1,T2,T3 ; pre-compute u0 and u1 MLAx2 rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; rax = cf = product[]+modulo[]*{u1:u0} MM_MLAx2_4N_4_ELOG rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; [rsp+carry] = rax = cf sub rcx, 2 jnz .mla2x4n_4 ; (borrow, pR) = (carry,product) - modulo mov rdx, qword [rsp+pR] xor rcx, rcx SBB_x4 rdx, rdi, rsi, idx, T0,T1,T2,T3, rcx SBB_TAIL 4, rdx, rdi, rsi, T0,T1,T2,T3, rcx ; pR = borrow? product : pR CMOV_x4 rdx, rdi, rdx, idx, T0,T1,T2,T3, rcx CMOV_TAIL 4, rdx, rdi, rdx, T0,T1,T2,T3, rcx jmp .quit align IPP_ALIGN_FACTOR .mla2x4n_3: MMx2_PLOG rdi, rsi, idx, r15, U0,U1,T0,T1,T2,T3 ; pre-compute u0 and u1 MLAx2 rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; rax = cf = product[]+modulo[]*{u1:u0} MM_MLAx2_4N_3_ELOG rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; [rsp+carry] = rax = cf sub rcx, 2 jnz .mla2x4n_3 ; (borrow, pR) = (carry,product) - modulo mov rdx, qword [rsp+pR] xor rcx, rcx SBB_x4 rdx, rdi, rsi, idx, T0,T1,T2,T3, rcx SBB_TAIL 3, rdx, rdi, rsi, T0,T1,T2,T3, rcx ; pR = borrow? product : pR CMOV_x4 rdx, rdi, rdx, idx, T0,T1,T2,T3, rcx CMOV_TAIL 3, rdx, rdi, rdx, T0,T1,T2,T3, rcx jmp .quit align IPP_ALIGN_FACTOR .mla2x4n_2: MMx2_PLOG rdi, rsi, idx, r15, U0,U1,T0,T1,T2,T3 ; pre-compute u0 and u1 MLAx2 rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; rax = cf = product[]+modulo[]*{u1:u0} MM_MLAx2_4N_2_ELOG rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; [rsp+carry] = rax = cf sub rcx, 2 jnz .mla2x4n_2 ; (borrow, pR) = (carry,product) - modulo mov rdx, qword [rsp+pR] xor rcx, rcx SBB_x4 rdx, rdi, rsi, idx, T0,T1,T2,T3, rcx SBB_TAIL 2, rdx, rdi, rsi, T0,T1,T2,T3, rcx ; pR = borrow? product : pR CMOV_x4 rdx, rdi, rdx, idx, T0,T1,T2,T3, rcx CMOV_TAIL 2, rdx, rdi, rdx, T0,T1,T2,T3, rcx jmp .quit align IPP_ALIGN_FACTOR .mla2x4n_1: MMx2_PLOG rdi, rsi, idx, r15, U0,U1,T0,T1,T2,T3 ; pre-compute u0 and u1 MLAx2 rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; rax = cf = product[]+modulo[]*{u1:u0} MM_MLAx2_4N_1_ELOG rdi, rsi, idx, U0,U1, T0,T1,T2,T3 ; [rsp+carry] = rax = cf sub rcx, 2 jnz .mla2x4n_1 ; (borrow, pR) = (carry,product) - modulo mov rdx, qword [rsp+pR] xor rcx, rcx SBB_x4 rdx, rdi, rsi, idx, T0,T1,T2,T3, rcx SBB_TAIL 1, rdx, rdi, rsi, T0,T1,T2,T3, rcx ; pR = borrow? product : pR CMOV_x4 rdx, rdi, rdx, idx, T0,T1,T2,T3, rcx CMOV_TAIL 1, rdx, rdi, rdx, T0,T1,T2,T3, rcx .quit: REST_XMM REST_GPR ret ENDFUNC cpMontRedAdc_BNU %endif %endif ;; _ADCOX_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmontsqr1024_avx2as.asm000066400000000000000000001057031470420105600300670ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpMontSqr1024_avx2() ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_L9) segment .text align=IPP_ALIGN_FACTOR %assign DIGIT_BITS 27 %assign DIGIT_MASK (1 << DIGIT_BITS) -1 ;************************************************************* ;* void cpMontSqr1024_avx2(Ipp64u* pR, ;* const Ipp64u* pA, ;* const Ipp64u* pModulus, int mSize, ;* Ipp64u k0, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpMontSqr1024_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*7 USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13,ymm14 COMP_ABI 6 movsxd rcx, ecx ; redLen value counter vpxor ymm11, ymm11, ymm11 ;; expands A and M operands vmovdqu ymmword [rsi+rcx*sizeof(qword)], ymm11 vmovdqu ymmword [rdx+rcx*sizeof(qword)], ymm11 ; ; stack struct ; %assign pResult 0 ; pointer to result %assign pA pResult+sizeof(qword) ; pointer to A operand %assign pM pA+sizeof(qword) ; pointer to modulus %assign redLen pM+sizeof(qword) ; length %assign m0 redLen+sizeof(qword) ; m0 value %assign pA2 m0+sizeof(qword) ; pointer to buffer (contains doubled input (A*2) and temporary result (A^2) ) %assign pAxA pA2+sizeof(qword) ; pointer to temporary result (A^2) mov qword [rsp+pResult], rdi ; store pointer to result mov qword [rsp+pA], rsi ; store pointer to input A mov qword [rsp+pM], rdx ; store pointer to modulus mov qword [rsp+redLen], rcx ; store redLen mov qword [rsp+m0], r8 ; store m0 value mov rcx, dword 40 mov rdi, r9 mov qword [rsp+pAxA], rdi ; pointer to temporary result (low A^2) lea rbx, [rdi+rcx*sizeof(qword)] ; pointer to temporary result (high A^2) lea r9, [rbx+rcx*sizeof(qword)] ; pointer to doubled input (A*2) mov qword [rsp+pA2], r9 mov rax, rsi mov rcx, dword sizeof(ymmword)/sizeof(qword) ;; doubling input vmovdqu ymm0, ymmword [rsi] vmovdqu ymm1, ymmword [rsi+sizeof(ymmword)] vmovdqu ymm2, ymmword [rsi+sizeof(ymmword)*2] vmovdqu ymm3, ymmword [rsi+sizeof(ymmword)*3] vmovdqu ymm4, ymmword [rsi+sizeof(ymmword)*4] vmovdqu ymm5, ymmword [rsi+sizeof(ymmword)*5] vmovdqu ymm6, ymmword [rsi+sizeof(ymmword)*6] vmovdqu ymm7, ymmword [rsi+sizeof(ymmword)*7] vmovdqu ymm8, ymmword [rsi+sizeof(ymmword)*8] vmovdqu ymm9, ymmword [rsi+sizeof(ymmword)*9] vmovdqu ymmword [r9], ymm0 vpbroadcastq ymm10, qword [rax] ; ymm10 = {a0:a0:a0:a0} vpaddq ymm1, ymm1, ymm1 vmovdqu ymmword [r9+sizeof(ymmword)], ymm1 vpaddq ymm2, ymm2, ymm2 vmovdqu ymmword [r9+sizeof(ymmword)*2], ymm2 vpaddq ymm3, ymm3, ymm3 vmovdqu ymmword [r9+sizeof(ymmword)*3], ymm3 vpaddq ymm4, ymm4, ymm4 vmovdqu ymmword [r9+sizeof(ymmword)*4], ymm4 vpaddq ymm5, ymm5, ymm5 vmovdqu ymmword [r9+sizeof(ymmword)*5], ymm5 vpaddq ymm6, ymm6, ymm6 vmovdqu ymmword [r9+sizeof(ymmword)*6], ymm6 vpaddq ymm7, ymm7, ymm7 vmovdqu ymmword [r9+sizeof(ymmword)*7], ymm7 vpaddq ymm8, ymm8, ymm8 vmovdqu ymmword [r9+sizeof(ymmword)*8], ymm8 vpaddq ymm9, ymm9, ymm9 vmovdqu ymmword [r9+sizeof(ymmword)*9], ymm9 ;; ;; squaring ;; vpmuludq ymm0, ymm10, ymmword [rsi] vpbroadcastq ymm14, qword [rax+sizeof(qword)*4] ; ymm14 = {a4:a4:a4:a4} vmovdqu ymmword [rbx], ymm11 vpmuludq ymm1, ymm10, ymmword [r9+sizeof(ymmword)] vmovdqu ymmword [rbx+sizeof(ymmword)], ymm11 vpmuludq ymm2, ymm10, ymmword [r9+sizeof(ymmword)*2] vmovdqu ymmword [rbx+sizeof(ymmword)*2], ymm11 vpmuludq ymm3, ymm10, ymmword [r9+sizeof(ymmword)*3] vmovdqu ymmword [rbx+sizeof(ymmword)*3], ymm11 vpmuludq ymm4, ymm10, ymmword [r9+sizeof(ymmword)*4] vmovdqu ymmword [rbx+sizeof(ymmword)*4], ymm11 vpmuludq ymm5, ymm10, ymmword [r9+sizeof(ymmword)*5] vmovdqu ymmword [rbx+sizeof(ymmword)*5], ymm11 vpmuludq ymm6, ymm10, ymmword [r9+sizeof(ymmword)*6] vmovdqu ymmword [rbx+sizeof(ymmword)*6], ymm11 vpmuludq ymm7, ymm10, ymmword [r9+sizeof(ymmword)*7] vmovdqu ymmword [rbx+sizeof(ymmword)*7], ymm11 vpmuludq ymm8, ymm10, ymmword [r9+sizeof(ymmword)*8] vmovdqu ymmword [rbx+sizeof(ymmword)*8], ymm11 vpmuludq ymm9, ymm10, ymmword [r9+sizeof(ymmword)*9] vmovdqu ymmword [rbx+sizeof(ymmword)*9], ymm11 jmp .sqr1024_ep align IPP_ALIGN_FACTOR .sqr1024_loop4: vpmuludq ymm0, ymm10, ymmword [rsi] vpbroadcastq ymm14, qword [rax+sizeof(qword)*4] ; ymm14 = {a4:a4:a4:a4} vpaddq ymm0, ymm0, ymmword [rdi] vpmuludq ymm1, ymm10, ymmword [r9+sizeof(ymmword)] vpaddq ymm1, ymm1, ymmword [rdi+sizeof(ymmword)] vpmuludq ymm2, ymm10, ymmword [r9+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymmword [rdi+sizeof(ymmword)*2] vpmuludq ymm3, ymm10, ymmword [r9+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymmword [rdi+sizeof(ymmword)*3] vpmuludq ymm4, ymm10, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm4, ymm4, ymmword [rdi+sizeof(ymmword)*4] vpmuludq ymm5, ymm10, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm5, ymm5, ymmword [rdi+sizeof(ymmword)*5] vpmuludq ymm6, ymm10, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm6, ymm6, ymmword [rdi+sizeof(ymmword)*6] vpmuludq ymm7, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm7, ymm7, ymmword [rdi+sizeof(ymmword)*7] vpmuludq ymm8, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm8, ymm8, ymmword [rdi+sizeof(ymmword)*8] vpmuludq ymm9, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm9, ymm9, ymmword [rdi+sizeof(ymmword)*9] .sqr1024_ep: vmovdqu ymmword [rdi], ymm0 vmovdqu ymmword [rdi+sizeof(ymmword)], ymm1 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)] vpbroadcastq ymm10, qword [rax+sizeof(qword)*8] ; ymm10 = {a8:a8:a8:a8} vpaddq ymm2, ymm2, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*2] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*3] vpaddq ymm4, ymm4, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm5, ymm5, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm6, ymm6, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm7, ymm7, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm8, ymm8, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm9, ymm9, ymm12 vpmuludq ymm0, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm0, ymm0, ymmword [rbx] vmovdqu ymmword [rdi+sizeof(ymmword)*2], ymm2 vmovdqu ymmword [rdi+sizeof(ymmword)*3], ymm3 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*2] vpbroadcastq ymm14, qword [rax+sizeof(qword)*12] ; ymm14 = {a12:a12:a12:a12} vpaddq ymm4, ymm4, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*3] vpaddq ymm5, ymm5, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm6, ymm6, ymm13 vpmuludq ymm11, ymm10, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm7, ymm7, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm8, ymm8, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm9, ymm9, ymm13 vpmuludq ymm11, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm0, ymm0, ymm11 vpmuludq ymm1, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm1, ymm1, ymmword [rbx+sizeof(ymmword)] vmovdqu ymmword [rdi+sizeof(ymmword)*4], ymm4 vmovdqu ymmword [rdi+sizeof(ymmword)*5], ymm5 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)*3] vpbroadcastq ymm10, qword [rax+sizeof(qword)*16] ; ymm10 = {a16:a16:a16:a16} vpaddq ymm6, ymm6, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm9, ymm9, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm2, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm2, ymm2, ymmword [rbx+sizeof(ymmword)*2] vmovdqu ymmword [rdi+sizeof(ymmword)*6], ymm6 vmovdqu ymmword [rdi+sizeof(ymmword)*7], ymm7 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*4] vpbroadcastq ymm14, qword [rax+sizeof(qword)*20] ; ymm14 = {a20:a20:a20:a20} vpaddq ymm8, ymm8, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm9, ymm9, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm11, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm1, ymm1, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm3, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm3, ymm3, ymmword [rbx+sizeof(ymmword)*3] vmovdqu ymmword [rdi+sizeof(ymmword)*8], ymm8 vmovdqu ymmword [rdi+sizeof(ymmword)*9], ymm9 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)*5] vpbroadcastq ymm10, qword [rax+sizeof(qword)*24] ; ymm10 = {a24:a24:a24:a24} vpaddq ymm0, ymm0, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm3, ymm3, ymm11 vpmuludq ymm4, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm4, ymm4, ymmword [rbx+sizeof(ymmword)*4] vmovdqu ymmword [rdi+sizeof(ymmword)*10], ymm0 vmovdqu ymmword [rdi+sizeof(ymmword)*11], ymm1 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*6] vpbroadcastq ymm14, qword [rax+sizeof(qword)*28] ; ymm14 = {a28:a28:a28:a28} vpaddq ymm2, ymm2, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm4, ymm4, ymm13 vpmuludq ymm5, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm5, ymm5, ymmword [rbx+sizeof(ymmword)*5] vmovdqu ymmword [rdi+sizeof(ymmword)*12], ymm2 vmovdqu ymmword [rdi+sizeof(ymmword)*13], ymm3 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)*7] vpbroadcastq ymm10, qword [rax+sizeof(qword)*32] ; ymm10 = {a32:a32:a32:a32} vpaddq ymm4, ymm4, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm5, ymm5, ymm12 vpmuludq ymm6, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm6, ymm6, ymmword [rbx+sizeof(ymmword)*6] vmovdqu ymmword [rdi+sizeof(ymmword)*14], ymm4 vmovdqu ymmword [rdi+sizeof(ymmword)*15], ymm5 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*8] vpbroadcastq ymm14, qword [rax+sizeof(qword)*36] ; ymm14 = {a36:a36:a36:a36} vpaddq ymm6, ymm6, ymm11 vpmuludq ymm7, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm7, ymm7, ymmword [rbx+sizeof(ymmword)*7] vpmuludq ymm8, ymm14, ymmword [rsi+sizeof(ymmword)*9] vpbroadcastq ymm10, qword [rax+sizeof(qword)] ; ymm10 = {a[1/2/3]:a[1/2/3]:a[1/2/3]:a[1/2/3]} vpaddq ymm8, ymm8, ymmword [rbx+sizeof(ymmword)*8] vmovdqu ymmword [rdi+sizeof(ymmword)*16], ymm6 vmovdqu ymmword [rdi+sizeof(ymmword)*17], ymm7 vmovdqu ymmword [rdi+sizeof(ymmword)*18], ymm8 add rdi, sizeof(qword) add rbx, sizeof(qword) add rax, sizeof(qword) sub rcx, 1 jnz .sqr1024_loop4 ;; ;; reduction ;; mov rdi, qword [rsp+pAxA] ; restore pointer to temporary result (low A^2) mov rcx, qword [rsp+pM] ; restore pointer to modulus mov r8, qword [rsp+m0] ; restore m0 value mov r9, dword 38 ; modulus length mov r10, qword [rdi] ; load low part of temporary result mov r11, qword [rdi+sizeof(qword)] ; mov r12, qword [rdi+sizeof(qword)*2] ; mov r13, qword [rdi+sizeof(qword)*3] ; mov rdx, r10 ; y0 = (ac0*k0) & DIGIT_MASK imul edx, r8d and edx, DIGIT_MASK vmovd xmm10, edx vmovdqu ymm1, ymmword [rdi+sizeof(ymmword)*1] ; load other data vmovdqu ymm2, ymmword [rdi+sizeof(ymmword)*2] ; vmovdqu ymm3, ymmword [rdi+sizeof(ymmword)*3] ; vmovdqu ymm4, ymmword [rdi+sizeof(ymmword)*4] ; vmovdqu ymm5, ymmword [rdi+sizeof(ymmword)*5] ; vmovdqu ymm6, ymmword [rdi+sizeof(ymmword)*6] ; mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] add r10, rax vpbroadcastq ymm10, xmm10 vmovdqu ymm7, ymmword [rdi+sizeof(ymmword)*7] ; load other data vmovdqu ymm8, ymmword [rdi+sizeof(ymmword)*8] ; vmovdqu ymm9, ymmword [rdi+sizeof(ymmword)*9] ; mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] add r11, rax mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] add r12, rax shr r10, DIGIT_BITS ; updtae ac1 imul rdx, qword [rcx+sizeof(qword)*3] ; ac3 += pn[3]*y0 add r13, rdx add r11, r10 ; updtae ac1 mov rdx, r11 ; y1 = (ac1*k0) & DIGIT_MASK imul edx, r8d and rdx, DIGIT_MASK align IPP_ALIGN_FACTOR .reduction_loop: vmovd xmm11, edx vpbroadcastq ymm11, xmm11 vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)] mov rax, rdx ; ac1 += pn[0]*y1 imul rax, qword [rcx] vpaddq ymm1, ymm1, ymm14 vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymm14 vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*4] add r11, rax shr r11, DIGIT_BITS ; update ac2 vpaddq ymm4, ymm4, ymm14 vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*5] mov rax, rdx ; ac2 += pn[1]*y1 imul rax, qword [rcx+sizeof(qword)] vpaddq ymm5, ymm5, ymm14 add r12, rax vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*6] imul rdx, qword [rcx+sizeof(qword)*2] ; ac3 += pn[2]*y1 add r12, r11 vpaddq ymm6, ymm6, ymm14 add r13, rdx vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*7] mov rdx, r12 ; y2 = (ac2*m0) & DIGIT_MASK imul edx, r8d vpaddq ymm7, ymm7, ymm14 vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*8] vpaddq ymm8, ymm8, ymm14 and rdx, DIGIT_MASK vpmuludq ymm14, ymm10, ymmword [rcx+sizeof(ymmword)*9] vpaddq ymm9, ymm9, ymm14 ;; ------------------------------------------------------------ vmovd xmm12, edx vpbroadcastq ymm12, xmm12 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)-sizeof(qword)] mov rax, rdx ; ac2 += pn[0]*y2 imul rax, qword [rcx] vpaddq ymm1, ymm1, ymm14 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*2-sizeof(qword)] vpaddq ymm2, ymm2, ymm14 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*3-sizeof(qword)] vpaddq ymm3, ymm3, ymm14 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*4-sizeof(qword)] vpaddq ymm4, ymm4, ymm14 add rax, r12 shr rax, DIGIT_BITS ; update ac3 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*5-sizeof(qword)] imul rdx, qword [rcx+sizeof(qword)] ; ac3 += pn[1]*y2 vpaddq ymm5, ymm5, ymm14 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*6-sizeof(qword)] vpaddq ymm6, ymm6, ymm14 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*7-sizeof(qword)] vpaddq ymm7, ymm7, ymm14 add rdx, r13 add rdx, rax ; update ac3 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*8-sizeof(qword)] vpaddq ymm8, ymm8, ymm14 vpmuludq ymm14, ymm11, ymmword [rcx+sizeof(ymmword)*9-sizeof(qword)] vpaddq ymm9, ymm9, ymm14 sub r9, 2 jz .exit_reduction_loop ;; ------------------------------------------------------------ vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)-sizeof(qword)*2] mov r13, rdx ; y3 = (ac3*m0) & DIGIT_MASK imul edx, r8d vpaddq ymm1, ymm1, ymm14 vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*2-sizeof(qword)*2] vpaddq ymm2, ymm2, ymm14 and rdx, DIGIT_MASK vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*3-sizeof(qword)*2] vmovd xmm13, edx vpaddq ymm3, ymm3, ymm14 vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*4-sizeof(qword)*2] vpbroadcastq ymm13, xmm13 vpaddq ymm4, ymm4, ymm14 vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*5-sizeof(qword)*2] imul rdx, qword [rcx] ; ac3 += pn[0]*y3 vpaddq ymm5, ymm5, ymm14 vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*6-sizeof(qword)*2] vpaddq ymm6, ymm6, ymm14 add r13, rdx vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*7-sizeof(qword)*2] vpaddq ymm7, ymm7, ymm14 shr r13, DIGIT_BITS vmovq xmm0, r13 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)-sizeof(qword)*3] vpaddq ymm1, ymm1, ymm0 vpaddq ymm1, ymm1, ymm14 vmovdqu ymmword [rdi], ymm1 vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*8-sizeof(qword)*2] vpaddq ymm8, ymm8, ymm14 vpmuludq ymm14, ymm12, ymmword [rcx+sizeof(ymmword)*9-sizeof(qword)*2] vpaddq ymm9, ymm9, ymm14 ;; ------------------------------------------------------------ vmovq rdx, xmm1 ; y0 = (ac0*k0) & DIGIT_MASK imul edx, r8d and edx, DIGIT_MASK vmovq r10, xmm1 ; update lowest part of temporary result mov r11, qword [rdi+sizeof(qword)] ; mov r12, qword [rdi+sizeof(qword)*2] ; mov r13, qword [rdi+sizeof(qword)*3] ; vmovd xmm10, edx vpbroadcastq ymm10, xmm10 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*2-sizeof(qword)*3] mov rax, rdx ; ac0 += pn[0]*y0 imul rax, qword [rcx] vpaddq ymm1, ymm2, ymm14 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*3-sizeof(qword)*3] add r10, rax vpaddq ymm2, ymm3, ymm14 shr r10, DIGIT_BITS ; updtae ac1 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*4-sizeof(qword)*3] mov rax, rdx ; ac1 += pn[1]*y0 imul rax, qword [rcx+sizeof(qword)] vpaddq ymm3, ymm4, ymm14 add r11, rax vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*5-sizeof(qword)*3] mov rax, rdx ; ac2 += pn[2]*y0 imul rax, qword [rcx+sizeof(qword)*2] vpaddq ymm4, ymm5, ymm14 add r12, rax vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*6-sizeof(qword)*3] imul rdx, qword [rcx+sizeof(qword)*3] ; ac3 += pn[3]*y0 vpaddq ymm5, ymm6, ymm14 add r13, rdx add r11, r10 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*7-sizeof(qword)*3] mov rdx, r11 ; y1 = (ac1*k0) & DIGIT_MASK imul edx, r8d vpaddq ymm6, ymm7, ymm14 and rdx, DIGIT_MASK vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*8-sizeof(qword)*3] vpaddq ymm7, ymm8, ymm14 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*9-sizeof(qword)*3] vpaddq ymm8, ymm9, ymm14 vpmuludq ymm14, ymm13, ymmword [rcx+sizeof(ymmword)*10-sizeof(qword)*3] vpaddq ymm9, ymm14, ymmword [rdi+sizeof(ymmword)*10] add rdi, sizeof(qword)*4 sub r9, 2 jnz .reduction_loop .exit_reduction_loop: mov rdi, qword [rsp+pResult] ; restore pointer to result mov qword [rdi], r12 mov qword [rdi+sizeof(qword)], r13 vmovdqu ymmword [rdi+sizeof(ymmword)-sizeof(qword)*2], ymm1 vmovdqu ymmword [rdi+sizeof(ymmword)*2-sizeof(qword)*2], ymm2 vmovdqu ymmword [rdi+sizeof(ymmword)*3-sizeof(qword)*2], ymm3 vmovdqu ymmword [rdi+sizeof(ymmword)*4-sizeof(qword)*2], ymm4 vmovdqu ymmword [rdi+sizeof(ymmword)*5-sizeof(qword)*2], ymm5 vmovdqu ymmword [rdi+sizeof(ymmword)*6-sizeof(qword)*2], ymm6 vmovdqu ymmword [rdi+sizeof(ymmword)*7-sizeof(qword)*2], ymm7 vmovdqu ymmword [rdi+sizeof(ymmword)*8-sizeof(qword)*2], ymm8 vmovdqu ymmword [rdi+sizeof(ymmword)*9-sizeof(qword)*2], ymm9 ;; ;; normalization ;; mov r9, dword 38 xor rax, rax .norm_loop: add rax, qword [rdi] add rdi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi-sizeof(qword)], rdx sub r9, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpMontSqr1024_avx2 ;************************************************************* ;* void cpSqr1024_avx2(Ipp64u* pR, ;* const Ipp64u* pA, int nsA, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpSqr1024_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*5 USES_GPR rsi,rdi,rbx USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13,ymm14 COMP_ABI 4 movsxd rdx, edx ; redLen value counter vpxor ymm11, ymm11, ymm11 ;; expands A operand vmovdqu ymmword [rsi+rdx*sizeof(qword)], ymm11 ; ; stack struct ; %assign pResult 0 ; pointer to result %assign pA pResult+sizeof(qword) ; pointer to A operand %assign redLen pA+sizeof(qword) ; length %assign pA2 redLen+sizeof(qword) ; pointer to buffer (contains doubled input (A*2) and temporary result (A^2) ) %assign pAxA pA2+sizeof(qword) ; pointer to temporary result (A^2) mov qword [rsp+pResult], rdi ; store pointer to result mov qword [rsp+pA], rsi ; store pointer to input A mov qword [rsp+redLen], rdx ; store redLen mov rdx, dword 40 mov rdi, rcx ; pointer to buffer mov qword [rsp+pAxA], rdi ; pointer to temporary result (low A^2) lea rbx, [rdi+rdx*sizeof(qword)] ; pointer to temporary result (high A^2) lea r9, [rbx+rdx*sizeof(qword)] ; pointer to doubled input (A*2) mov qword [rsp+pA2], r9 mov rax, rsi mov rcx, dword sizeof(ymmword)/sizeof(qword) ;; doubling input vmovdqu ymm0, ymmword [rsi] vmovdqu ymm1, ymmword [rsi+sizeof(ymmword)] vmovdqu ymm2, ymmword [rsi+sizeof(ymmword)*2] vmovdqu ymm3, ymmword [rsi+sizeof(ymmword)*3] vmovdqu ymm4, ymmword [rsi+sizeof(ymmword)*4] vmovdqu ymm5, ymmword [rsi+sizeof(ymmword)*5] vmovdqu ymm6, ymmword [rsi+sizeof(ymmword)*6] vmovdqu ymm7, ymmword [rsi+sizeof(ymmword)*7] vmovdqu ymm8, ymmword [rsi+sizeof(ymmword)*8] vmovdqu ymm9, ymmword [rsi+sizeof(ymmword)*9] vmovdqu ymmword [r9], ymm0 vpbroadcastq ymm10, qword [rax] ; ymm10 = {a0:a0:a0:a0} vpaddq ymm1, ymm1, ymm1 vmovdqu ymmword [r9+sizeof(ymmword)], ymm1 vpaddq ymm2, ymm2, ymm2 vmovdqu ymmword [r9+sizeof(ymmword)*2], ymm2 vpaddq ymm3, ymm3, ymm3 vmovdqu ymmword [r9+sizeof(ymmword)*3], ymm3 vpaddq ymm4, ymm4, ymm4 vmovdqu ymmword [r9+sizeof(ymmword)*4], ymm4 vpaddq ymm5, ymm5, ymm5 vmovdqu ymmword [r9+sizeof(ymmword)*5], ymm5 vpaddq ymm6, ymm6, ymm6 vmovdqu ymmword [r9+sizeof(ymmword)*6], ymm6 vpaddq ymm7, ymm7, ymm7 vmovdqu ymmword [r9+sizeof(ymmword)*7], ymm7 vpaddq ymm8, ymm8, ymm8 vmovdqu ymmword [r9+sizeof(ymmword)*8], ymm8 vpaddq ymm9, ymm9, ymm9 vmovdqu ymmword [r9+sizeof(ymmword)*9], ymm9 ;; ;; squaring ;; vpmuludq ymm0, ymm10, ymmword [rsi] vpbroadcastq ymm14, qword [rax+sizeof(qword)*4] ; ymm14 = {a4:a4:a4:a4} vmovdqu ymmword [rbx], ymm11 vpmuludq ymm1, ymm10, ymmword [r9+sizeof(ymmword)] vmovdqu ymmword [rbx+sizeof(ymmword)], ymm11 vpmuludq ymm2, ymm10, ymmword [r9+sizeof(ymmword)*2] vmovdqu ymmword [rbx+sizeof(ymmword)*2], ymm11 vpmuludq ymm3, ymm10, ymmword [r9+sizeof(ymmword)*3] vmovdqu ymmword [rbx+sizeof(ymmword)*3], ymm11 vpmuludq ymm4, ymm10, ymmword [r9+sizeof(ymmword)*4] vmovdqu ymmword [rbx+sizeof(ymmword)*4], ymm11 vpmuludq ymm5, ymm10, ymmword [r9+sizeof(ymmword)*5] vmovdqu ymmword [rbx+sizeof(ymmword)*5], ymm11 vpmuludq ymm6, ymm10, ymmword [r9+sizeof(ymmword)*6] vmovdqu ymmword [rbx+sizeof(ymmword)*6], ymm11 vpmuludq ymm7, ymm10, ymmword [r9+sizeof(ymmword)*7] vmovdqu ymmword [rbx+sizeof(ymmword)*7], ymm11 vpmuludq ymm8, ymm10, ymmword [r9+sizeof(ymmword)*8] vmovdqu ymmword [rbx+sizeof(ymmword)*8], ymm11 vpmuludq ymm9, ymm10, ymmword [r9+sizeof(ymmword)*9] vmovdqu ymmword [rbx+sizeof(ymmword)*9], ymm11 jmp .sqr1024_ep align IPP_ALIGN_FACTOR .sqr1024_loop4: vpmuludq ymm0, ymm10, ymmword [rsi] vpbroadcastq ymm14, qword [rax+sizeof(qword)*4] ; ymm14 = {a4:a4:a4:a4} vpaddq ymm0, ymm0, ymmword [rdi] vpmuludq ymm1, ymm10, ymmword [r9+sizeof(ymmword)] vpaddq ymm1, ymm1, ymmword [rdi+sizeof(ymmword)] vpmuludq ymm2, ymm10, ymmword [r9+sizeof(ymmword)*2] vpaddq ymm2, ymm2, ymmword [rdi+sizeof(ymmword)*2] vpmuludq ymm3, ymm10, ymmword [r9+sizeof(ymmword)*3] vpaddq ymm3, ymm3, ymmword [rdi+sizeof(ymmword)*3] vpmuludq ymm4, ymm10, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm4, ymm4, ymmword [rdi+sizeof(ymmword)*4] vpmuludq ymm5, ymm10, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm5, ymm5, ymmword [rdi+sizeof(ymmword)*5] vpmuludq ymm6, ymm10, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm6, ymm6, ymmword [rdi+sizeof(ymmword)*6] vpmuludq ymm7, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm7, ymm7, ymmword [rdi+sizeof(ymmword)*7] vpmuludq ymm8, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm8, ymm8, ymmword [rdi+sizeof(ymmword)*8] vpmuludq ymm9, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm9, ymm9, ymmword [rdi+sizeof(ymmword)*9] .sqr1024_ep: vmovdqu ymmword [rdi], ymm0 vmovdqu ymmword [rdi+sizeof(ymmword)], ymm1 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)] vpbroadcastq ymm10, qword [rax+sizeof(qword)*8] ; ymm10 = {a8:a8:a8:a8} vpaddq ymm2, ymm2, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*2] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*3] vpaddq ymm4, ymm4, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm5, ymm5, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm6, ymm6, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm7, ymm7, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm8, ymm8, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm9, ymm9, ymm12 vpmuludq ymm0, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm0, ymm0, ymmword [rbx] vmovdqu ymmword [rdi+sizeof(ymmword)*2], ymm2 vmovdqu ymmword [rdi+sizeof(ymmword)*3], ymm3 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*2] vpbroadcastq ymm14, qword [rax+sizeof(qword)*12] ; ymm14 = {a12:a12:a12:a12} vpaddq ymm4, ymm4, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*3] vpaddq ymm5, ymm5, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm6, ymm6, ymm13 vpmuludq ymm11, ymm10, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm7, ymm7, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm8, ymm8, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm9, ymm9, ymm13 vpmuludq ymm11, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm0, ymm0, ymm11 vpmuludq ymm1, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm1, ymm1, ymmword [rbx+sizeof(ymmword)] vmovdqu ymmword [rdi+sizeof(ymmword)*4], ymm4 vmovdqu ymmword [rdi+sizeof(ymmword)*5], ymm5 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)*3] vpbroadcastq ymm10, qword [rax+sizeof(qword)*16] ; ymm10 = {a16:a16:a16:a16} vpaddq ymm6, ymm6, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*4] vpaddq ymm7, ymm7, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm8, ymm8, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm9, ymm9, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm0, ymm0, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm1, ymm1, ymm13 vpmuludq ymm2, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm2, ymm2, ymmword [rbx+sizeof(ymmword)*2] vmovdqu ymmword [rdi+sizeof(ymmword)*6], ymm6 vmovdqu ymmword [rdi+sizeof(ymmword)*7], ymm7 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*4] vpbroadcastq ymm14, qword [rax+sizeof(qword)*20] ; ymm14 = {a20:a20:a20:a20} vpaddq ymm8, ymm8, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*5] vpaddq ymm9, ymm9, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm0, ymm0, ymm13 vpmuludq ymm11, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm1, ymm1, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm2, ymm2, ymm12 vpmuludq ymm3, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm3, ymm3, ymmword [rbx+sizeof(ymmword)*3] vmovdqu ymmword [rdi+sizeof(ymmword)*8], ymm8 vmovdqu ymmword [rdi+sizeof(ymmword)*9], ymm9 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)*5] vpbroadcastq ymm10, qword [rax+sizeof(qword)*24] ; ymm10 = {a24:a24:a24:a24} vpaddq ymm0, ymm0, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*6] vpaddq ymm1, ymm1, ymm12 vpmuludq ymm13, ymm14, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm2, ymm2, ymm13 vpmuludq ymm11, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm3, ymm3, ymm11 vpmuludq ymm4, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm4, ymm4, ymmword [rbx+sizeof(ymmword)*4] vmovdqu ymmword [rdi+sizeof(ymmword)*10], ymm0 vmovdqu ymmword [rdi+sizeof(ymmword)*11], ymm1 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*6] vpbroadcastq ymm14, qword [rax+sizeof(qword)*28] ; ymm14 = {a28:a28:a28:a28} vpaddq ymm2, ymm2, ymm11 vpmuludq ymm12, ymm10, ymmword [r9+sizeof(ymmword)*7] vpaddq ymm3, ymm3, ymm12 vpmuludq ymm13, ymm10, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm4, ymm4, ymm13 vpmuludq ymm5, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm5, ymm5, ymmword [rbx+sizeof(ymmword)*5] vmovdqu ymmword [rdi+sizeof(ymmword)*12], ymm2 vmovdqu ymmword [rdi+sizeof(ymmword)*13], ymm3 vpmuludq ymm11, ymm14, ymmword [rsi+sizeof(ymmword)*7] vpbroadcastq ymm10, qword [rax+sizeof(qword)*32] ; ymm10 = {a32:a32:a32:a32} vpaddq ymm4, ymm4, ymm11 vpmuludq ymm12, ymm14, ymmword [r9+sizeof(ymmword)*8] vpaddq ymm5, ymm5, ymm12 vpmuludq ymm6, ymm14, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm6, ymm6, ymmword [rbx+sizeof(ymmword)*6] vmovdqu ymmword [rdi+sizeof(ymmword)*14], ymm4 vmovdqu ymmword [rdi+sizeof(ymmword)*15], ymm5 vpmuludq ymm11, ymm10, ymmword [rsi+sizeof(ymmword)*8] vpbroadcastq ymm14, qword [rax+sizeof(qword)*36] ; ymm14 = {a36:a36:a36:a36} vpaddq ymm6, ymm6, ymm11 vpmuludq ymm7, ymm10, ymmword [r9+sizeof(ymmword)*9] vpaddq ymm7, ymm7, ymmword [rbx+sizeof(ymmword)*7] vpmuludq ymm8, ymm14, ymmword [rsi+sizeof(ymmword)*9] vpbroadcastq ymm10, qword [rax+sizeof(qword)] ; ymm10 = {a[1/2/3]:a[1/2/3]:a[1/2/3]:a[1/2/3]} vpaddq ymm8, ymm8, ymmword [rbx+sizeof(ymmword)*8] vmovdqu ymmword [rdi+sizeof(ymmword)*16], ymm6 vmovdqu ymmword [rdi+sizeof(ymmword)*17], ymm7 vmovdqu ymmword [rdi+sizeof(ymmword)*18], ymm8 add rdi, sizeof(qword) add rbx, sizeof(qword) add rax, sizeof(qword) sub rcx, 1 jnz .sqr1024_loop4 ;; ;; normalization ;; mov rsi, qword [rsp+pAxA] mov rdi, qword [rsp+pResult] mov r9, dword 38*2 xor rax, rax .norm_loop: add rax, qword [rsi] add rsi, sizeof(qword) mov rdx, dword DIGIT_MASK and rdx, rax shr rax, DIGIT_BITS mov qword [rdi], rdx add rdi, sizeof(qword) sub r9, 1 jg .norm_loop mov qword [rdi], rax REST_XMM_AVX REST_GPR ret ENDFUNC cpSqr1024_avx2 %endif ; _IPP32E_L9 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmontsqr_avx2as.asm000066400000000000000000001011111470420105600275450ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Big Number Operations ; ; Content: ; cpSqr_avx2() ; cpMontRed_avx2() ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_L9) segment .text align=IPP_ALIGN_FACTOR %assign DIGIT_BITS 27 %assign DIGIT_MASK (1 << DIGIT_BITS) -1 ;************************************************************* ;* void cpSqr_avx2(Ipp64u* pR, ;* const Ipp64u* pA, int aSize, ;* Ipp64u* pBuffer) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM cpSqr_avx2,PUBLIC %assign LOCAL_FRAME sizeof(qword)*6 USES_GPR rsi,rdi,rbx,rbp,r12,r13 USES_XMM_AVX ymm6,ymm7,ymm8,ymm9,ymm10,ymm11,ymm12,ymm13,ymm14 COMP_ABI 4 movsxd rdx, edx ; redLen value counter vpxor ymm11, ymm11, ymm11 ;; expands A vmovdqu ymmword [rsi+rdx*sizeof(qword)], ymm11 ; size of buffer = redLen+4 ; ; stack struct ; %assign pResult 0 ; pointer to result %assign pA pResult+sizeof(qword) ; pointer to A operand %assign redLen pA+sizeof(qword) ; length %assign len4 redLen+sizeof(qword) ; x4 length %assign pA2 len4+sizeof(qword) ; pointer to buffer (contains doubled input (A*2) and temporary result (A^2) ) %assign pAxA pA2+sizeof(qword) ; pointer to temporary result (A^2) lea rax, [rdx+3] ; len4 = ((redLen+3) &(-4))/4 and rax, -4 ; multiple 4 length of operand (in ymmwords) shr rax, 2 mov qword [rsp+pResult], rdi ; store pointer to result mov qword [rsp+pA], rsi ; store pointer to input A mov qword [rsp+redLen], rdx ; store redLen mov qword [rsp+len4], rax ; store len4 mov rdi, rcx ; pointer to word buffer shl rax, 2 mov qword [rsp+pAxA], rdi ; pointer to temporary result (low A^2) lea rbx, [rdi+rax*sizeof(qword)] ; pointer to temporary result (high A^2) lea r9, [rbx+rax*sizeof(qword)] ; pointer to doubled input (A*2) mov qword [rsp+pA2], r9 ;; clear temporary result and double input .clr_dbl_loop: vmovdqu ymm0, ymmword [rsi] vpaddq ymm0, ymm0, ymm0 vmovdqu ymmword [rdi], ymm11 vmovdqu ymmword [rbx], ymm11 vmovdqu ymmword [r9], ymm0 add rsi, sizeof(ymmword) add rdi, sizeof(ymmword) add rbx, sizeof(ymmword) add r9, sizeof(ymmword) sub rax, sizeof(ymmword)/sizeof(qword) jg .clr_dbl_loop ;; ;; squaring ;; mov rsi, qword [rsp+pA] ; restore A mov rdi, qword [rsp+pAxA] ; restore temp result buffer mov r9, qword [rsp+pA2] ; restore temp double buffer mov rax, rsi ; tsrc = src + sizeof(qword)*n, n=0,1,2,3 mov rcx, dword 4 align IPP_ALIGN_FACTOR .sqr_offset_loop: ; for(n=0; n<4; n++) mov r10, qword [rsp+len4] mov r12, dword 3 and r12, r10 ; init vflg = len4%4 lea r11, [r10-(4*2-1)] ; init inner_loop counter (hcnt = len4 -7) shr r10, 2 ; init outer_loop counter (vcnt = len4/4 -1) sub r10, 1 ; push r9 ; (optr_d256) push rsi ; (optr_s256) push rdi ; (optr_r256) push rax ; (optr_a256) align IPP_ALIGN_FACTOR .sqr_outer_loop: ; for(i=0; i 1 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%mSize > 2 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%mSize > 3 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%mSize > 4 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%mSize > 5 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%mSize > 6 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %if %%mSize > 7 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif xor %%TMP, %%TMP add %%X0, qword [%%rProduct+sizeof(qword)*(%%mSize+0)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+0)], %%X0 %if %%mSize > 1 adc %%X1, qword [%%rProduct+sizeof(qword)*(%%mSize+1)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+1)], %%X1 %endif %if %%mSize > 2 adc %%X2, qword [%%rProduct+sizeof(qword)*(%%mSize+2)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+2)], %%X2 %endif %if %%mSize > 3 adc %%X3, qword [%%rProduct+sizeof(qword)*(%%mSize+3)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+3)], %%X3 %endif %if %%mSize > 4 adc %%X4, qword [%%rProduct+sizeof(qword)*(%%mSize+4)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+4)], %%X4 %endif %if %%mSize > 5 adc %%X5, qword [%%rProduct+sizeof(qword)*(%%mSize+5)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+5)], %%X5 %endif %if %%mSize > 6 adc %%X6, qword [%%rProduct+sizeof(qword)*(%%mSize+6)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+6)], %%X6 %endif %if %%mSize > 7 adc %%X7, qword [%%rProduct+sizeof(qword)*(%%mSize+7)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+7)], %%X7 %endif adc %%TMP, 0 sub %%X0, qword [%%rModulus+sizeof(qword)*0] %if %%mSize > 1 sbb %%X1, qword [%%rModulus+sizeof(qword)*1] %endif %if %%mSize > 2 sbb %%X2, qword [%%rModulus+sizeof(qword)*2] %endif %if %%mSize > 3 sbb %%X3, qword [%%rModulus+sizeof(qword)*3] %endif %if %%mSize > 4 sbb %%X4, qword [%%rModulus+sizeof(qword)*4] %endif %if %%mSize > 5 sbb %%X5, qword [%%rModulus+sizeof(qword)*5] %endif %if %%mSize > 6 sbb %%X6, qword [%%rModulus+sizeof(qword)*6] %endif %if %%mSize > 7 sbb %%X7, qword [%%rModulus+sizeof(qword)*7] %endif sbb %%TMP, 0 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+0)] cmovae rax, %%X0 mov qword [%%rRed+sizeof(qword)*0], rax %if %%mSize > 1 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+1)] cmovae rax, %%X1 mov qword [%%rRed+sizeof(qword)*1], rax %endif %if %%mSize > 2 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+2)] cmovae rax, %%X2 mov qword [%%rRed+sizeof(qword)*2], rax %endif %if %%mSize > 3 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+3)] cmovae rax, %%X3 mov qword [%%rRed+sizeof(qword)*3], rax %endif %if %%mSize > 4 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+4)] cmovae rax, %%X4 mov qword [%%rRed+sizeof(qword)*4], rax %endif %if %%mSize > 5 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+5)] cmovae rax, %%X5 mov qword [%%rRed+sizeof(qword)*5], rax %endif %if %%mSize > 6 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+6)] cmovae rax, %%X6 mov qword [%%rRed+sizeof(qword)*6], rax %endif %if %%mSize > 7 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+7)] cmovae rax, %%X7 mov qword [%%rRed+sizeof(qword)*7], rax %endif %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sub_N,PRIVATE xor rax, rax ; cf = 0 .sub_next: lea rdi, [rdi+sizeof(qword)] mov r8, qword [rsi] mov r9, qword [rcx] lea rsi, [rsi+sizeof(qword)] lea rcx, [rcx+sizeof(qword)] sbb r8, r9 mov qword [rdi-sizeof(qword)], r8 dec rdx jnz .sub_next adc rax, 0 ret ENDFUNC sub_N align IPP_ALIGN_FACTOR DECLARE_FUNC copy_ae_N,PRIVATE lea rdi, [rdi+sizeof(qword)] mov r8, qword [rsi] ; src1[] mov r9, qword [rcx] ; src2[] lea rsi, [rsi+sizeof(qword)] lea rcx, [rcx+sizeof(qword)] cmovae r8, r9 mov qword [rdi-sizeof(qword)], r8 dec rdx jnz copy_ae_N ret ENDFUNC copy_ae_N ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; mredN_start procedures align IPP_ALIGN_FACTOR DECLARE_FUNC mred1_start,PRIVATE MLA_FIX 1,, rsi, rbx,rbp, r8 ret ENDFUNC mred1_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred2_start,PRIVATE MLA_FIX 2,, rsi, rbx,rbp, r8,r9 ret ENDFUNC mred2_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred3_start,PRIVATE MLA_FIX 3,, rsi, rbx,rbp, r8,r9,r10 ret ENDFUNC mred3_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred4_start,PRIVATE MLA_FIX 4,, rsi, rbx,rbp, r8,r9,r10,r11 ret ENDFUNC mred4_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred5_start,PRIVATE MLA_FIX 5,, rsi, rbx,rbp, r8,r9,r10,r11,r12 ret ENDFUNC mred5_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred6_start,PRIVATE MLA_FIX 6,, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 ret ENDFUNC mred6_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred7_start,PRIVATE MLA_FIX 7,, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 ret ENDFUNC mred7_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8_start,PRIVATE MLA_FIX 8,, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mred8_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x1_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax pop rdx ; resrore m' ret ENDFUNC mred8x1_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x2_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax pop rdx ; resrore m' ret ENDFUNC mred8x2_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x3_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax pop rdx ; resrore m' ret ENDFUNC mred8x3_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x4_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax pop rdx ; resrore m' ret ENDFUNC mred8x4_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x5_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax pop rdx ; resrore m' ret ENDFUNC mred8x5_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x6_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*5], rdx call mred8_start mov [rdi+sizeof(qword)*5], rax pop rdx ; resrore m' ret ENDFUNC mred8x6_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x7_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*5], rdx call mred8_start mov [rdi+sizeof(qword)*5], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*6], rdx call mred8_start mov [rdi+sizeof(qword)*6], rax pop rdx ; resrore m' ret ENDFUNC mred8x7_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x8_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*5], rdx call mred8_start mov [rdi+sizeof(qword)*5], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*6], rdx call mred8_start mov [rdi+sizeof(qword)*6], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*7], rdx call mred8_start mov [rdi+sizeof(qword)*7], rax pop rdx ; resrore m' ret ENDFUNC mred8x8_start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; rdi - temporary product buffer/temporary reduction ;; rsi - modulus ;; r8 - m' ;; r15 - target reduction address ;; ;; ;; 1*qword modulus length ;; ;; ;; 2*qword modulus length ;; ;; ;; 3*qword modulus length ;; ;; ;; 4*qword modulus length ;; ;; ;; 5*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_5,PRIVATE %assign MSIZE 5 push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx sbb rax, 0 ; copy under cf [r15] = cf? [r15] : {r8-r12} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] mov rbp, qword [rdi+sizeof(qword)*(MSIZE+4)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 cmovae rbp, r12 mov qword [r15+sizeof(qword)*0], rax mov qword [r15+sizeof(qword)*1], rbx mov qword [r15+sizeof(qword)*2], rcx mov qword [r15+sizeof(qword)*3], rdx mov qword [r15+sizeof(qword)*4], rbp ret ENDFUNC mred_5 ;; ;; 6*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_6,PRIVATE %assign MSIZE 6 push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE+5)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+5)], r13 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx op_reg_mem sbb, r13,[rsi+sizeof(qword)*5], rbx sbb rax, 0 ; copy under cf [r15] = cf? [r15] : {r8-r13} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] mov rbp, qword [rdi+sizeof(qword)*(MSIZE+4)] mov rsi, qword [rdi+sizeof(qword)*(MSIZE+5)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 cmovae rbp, r12 cmovae rsi, r13 mov qword [r15+sizeof(qword)*0], rax mov qword [r15+sizeof(qword)*1], rbx mov qword [r15+sizeof(qword)*2], rcx mov qword [r15+sizeof(qword)*3], rdx mov qword [r15+sizeof(qword)*4], rbp mov qword [r15+sizeof(qword)*5], rsi ret ENDFUNC mred_6 ;; ;; 7*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_7,PRIVATE %assign MSIZE 7 push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE+5)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+5)], r13 op_reg_mem adc, r14,[rdi+sizeof(qword)*(MSIZE+6)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+6)], r14 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx op_reg_mem sbb, r13,[rsi+sizeof(qword)*5], rbx op_reg_mem sbb, r14,[rsi+sizeof(qword)*6], rbx sbb rax, 0 ; copy under cf [r15] = cf? [r15] : {r8-r14} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] mov rbp, qword [rdi+sizeof(qword)*(MSIZE+4)] mov rsi, qword [rdi+sizeof(qword)*(MSIZE+5)] mov rdi, qword [rdi+sizeof(qword)*(MSIZE+6)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 cmovae rbp, r12 cmovae rsi, r13 cmovae rdi, r14 mov qword [r15+sizeof(qword)*0], rax mov qword [r15+sizeof(qword)*1], rbx mov qword [r15+sizeof(qword)*2], rcx mov qword [r15+sizeof(qword)*3], rdx mov qword [r15+sizeof(qword)*4], rbp mov qword [r15+sizeof(qword)*5], rsi mov qword [r15+sizeof(qword)*6], rdi ret ENDFUNC mred_7 ;; ;; 8*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_8,PRIVATE %assign MSIZE 8 push r15 ; save reduction address push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE+5)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+5)], r13 op_reg_mem adc, r14,[rdi+sizeof(qword)*(MSIZE+6)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+6)], r14 op_reg_mem adc, r15,[rdi+sizeof(qword)*(MSIZE+7)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+7)], r15 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx op_reg_mem sbb, r13,[rsi+sizeof(qword)*5], rbx op_reg_mem sbb, r14,[rsi+sizeof(qword)*6], rbx op_reg_mem sbb, r15,[rsi+sizeof(qword)*7], rbx sbb rax, 0 pop rsi ; address of reduction ; copy under cf [rsi] = cf? [rdi] : {r8-r15} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 mov qword [rsi+sizeof(qword)*0], rax mov qword [rsi+sizeof(qword)*1], rbx mov qword [rsi+sizeof(qword)*2], rcx mov qword [rsi+sizeof(qword)*3], rdx mov rax, qword [rdi+sizeof(qword)*(MSIZE+4)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+5)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+6)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+7)] cmovae rax, r12 cmovae rbx, r13 cmovae rcx, r14 cmovae rdx, r15 mov qword [rsi+sizeof(qword)*4], rax mov qword [rsi+sizeof(qword)*5], rbx mov qword [rsi+sizeof(qword)*6], rcx mov qword [rsi+sizeof(qword)*7], rdx ret ENDFUNC mred_8 ;; ;; 9*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_9,PRIVATE %assign MSIZE 9 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x1 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x1_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14 mov r8, r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_1x1 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_9 ;; ;; 10*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_10,PRIVATE %assign MSIZE 10 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x2 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x2_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov r8, r14 mov r9, r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_2x2 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_10 ;; ;; 11*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_11,PRIVATE %assign MSIZE 11 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x3 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x3_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov r8, r13 mov r9, r14 mov r10,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_3x3 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_11 ;; ;; 12*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_12,PRIVATE %assign MSIZE 12 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x4 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x4_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov r8, r12 mov r9, r13 mov r10,r14 mov r11,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_4x4 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_12 ;; ;; 13*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_13,PRIVATE %assign MSIZE 13 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x5 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x5_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov r8, r11 mov r9, r12 mov r10,r13 mov r11,r14 mov r12,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r12,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_5x5 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 adc r12,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_13 ;; ;; 14*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_14,PRIVATE %assign MSIZE 14 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x6 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x6_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov r8, r10 mov r9, r11 mov r10,r12 mov r11,r13 mov r12,r14 mov r13,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r12,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r13,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_6x6 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_14 ;; ;; 15*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_15,PRIVATE %assign MSIZE 15 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x7 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x7_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov r8, r9 mov r9, r10 mov r10,r11 mov r11,r12 mov r12,r13 mov r13,r14 mov r14,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r12,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r13,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r14,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_7x7 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 adc r14,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_15 ;; ;; 16*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_16,PRIVATE %assign MSIZE 16 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp mov rdx, r8 ; copy m' ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 push rdx call mla_8x8 pop rdx pop rax shr rax, 1 op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+0)], r8, [rdi+sizeof(qword)*(8+0)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+1)], r9, [rdi+sizeof(qword)*(8+1)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+2)], r10,[rdi+sizeof(qword)*(8+2)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+3)], r11,[rdi+sizeof(qword)*(8+3)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+4)], r12,[rdi+sizeof(qword)*(8+4)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+5)], r13,[rdi+sizeof(qword)*(8+5)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+6)], r14,[rdi+sizeof(qword)*(8+6)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+7)], r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax sub rsi, sizeof(qword)*8 mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_8x8 sub rsi, sizeof(qword)*8 pop rax shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10, [rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11, [rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12, [rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13, [rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14, [rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15, [rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 pop rbx add r8, rbx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 mov qword [rdi+sizeof(qword)*(8+0)], r8 mov qword [rdi+sizeof(qword)*(8+1)], r9 mov qword [rdi+sizeof(qword)*(8+2)], r10 mov qword [rdi+sizeof(qword)*(8+3)], r11 mov qword [rdi+sizeof(qword)*(8+4)], r12 mov qword [rdi+sizeof(qword)*(8+5)], r13 mov qword [rdi+sizeof(qword)*(8+6)], r14 mov qword [rdi+sizeof(qword)*(8+7)], r15 add rsp, sizeof(qword)*8 ; release U space pop rbp ; reduction -= modulus op_mem_mem sub, [rbp+sizeof(qword)*0 ], [rdi+sizeof(qword)*0 ], [rsi+sizeof(qword)*0 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*1 ], [rdi+sizeof(qword)*1 ], [rsi+sizeof(qword)*1 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*2 ], [rdi+sizeof(qword)*2 ], [rsi+sizeof(qword)*2 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*3 ], [rdi+sizeof(qword)*3 ], [rsi+sizeof(qword)*3 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*4 ], [rdi+sizeof(qword)*4 ], [rsi+sizeof(qword)*4 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*5 ], [rdi+sizeof(qword)*5 ], [rsi+sizeof(qword)*5 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*6 ], [rdi+sizeof(qword)*6 ], [rsi+sizeof(qword)*6 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*7 ], [rdi+sizeof(qword)*7 ], [rsi+sizeof(qword)*7 ], rbx op_reg_mem sbb, r8, [rsi+sizeof(qword)*8 ], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*9 ], rbx op_reg_mem sbb, r10, [rsi+sizeof(qword)*10], rbx op_reg_mem sbb, r11, [rsi+sizeof(qword)*11], rbx op_reg_mem sbb, r12, [rsi+sizeof(qword)*12], rbx op_reg_mem sbb, r13, [rsi+sizeof(qword)*13], rbx op_reg_mem sbb, r14, [rsi+sizeof(qword)*14], rbx op_reg_mem sbb, r15, [rsi+sizeof(qword)*15], rbx sbb rax, 0 ; copy under cf [rbp] = cf? [rdi] : [rbp] mov rax, qword [rdi+sizeof(qword)*8 ] mov rbx, qword [rdi+sizeof(qword)*9 ] mov rcx, qword [rdi+sizeof(qword)*10] mov rdx, qword [rdi+sizeof(qword)*11] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 mov qword [rbp+sizeof(qword)*8 ], rax mov qword [rbp+sizeof(qword)*9 ], rbx mov qword [rbp+sizeof(qword)*10], rcx mov qword [rbp+sizeof(qword)*11], rdx mov rax, qword [rdi+sizeof(qword)*12] mov rbx, qword [rdi+sizeof(qword)*13] mov rcx, qword [rdi+sizeof(qword)*14] mov rdx, qword [rdi+sizeof(qword)*15] cmovae rax, r12 cmovae rbx, r13 cmovae rcx, r14 cmovae rdx, r15 mov qword [rbp+sizeof(qword)*12], rax mov qword [rbp+sizeof(qword)*13], rbx mov qword [rbp+sizeof(qword)*14], rcx mov qword [rbp+sizeof(qword)*15], rdx mov r8, qword [rbp+sizeof(qword)*0] mov r9, qword [rbp+sizeof(qword)*1] mov r10, qword [rbp+sizeof(qword)*2] mov r11, qword [rbp+sizeof(qword)*3] mov r12, qword [rbp+sizeof(qword)*4] mov r13, qword [rbp+sizeof(qword)*5] mov r14, qword [rbp+sizeof(qword)*6] mov r15, qword [rbp+sizeof(qword)*7] mov rax, qword [rdi+sizeof(qword)*0] mov rbx, qword [rdi+sizeof(qword)*1] mov rcx, qword [rdi+sizeof(qword)*2] mov rdx, qword [rdi+sizeof(qword)*3] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 mov qword [rbp+sizeof(qword)*0], rax mov qword [rbp+sizeof(qword)*1], rbx mov qword [rbp+sizeof(qword)*2], rcx mov qword [rbp+sizeof(qword)*3], rdx mov rax, qword [rdi+sizeof(qword)*4] mov rbx, qword [rdi+sizeof(qword)*5] mov rcx, qword [rdi+sizeof(qword)*6] mov rdx, qword [rdi+sizeof(qword)*7] cmovae rax, r12 cmovae rbx, r13 cmovae rcx, r14 cmovae rdx, r15 mov qword [rbp+sizeof(qword)*4], rax mov qword [rbp+sizeof(qword)*5], rbx mov qword [rbp+sizeof(qword)*6], rcx mov qword [rbp+sizeof(qword)*7], rdx ret ENDFUNC mred_16 mred_short DQ mred_5 - mred_short DQ mred_6 - mred_short DQ mred_7 - mred_short DQ mred_8 - mred_short DQ mred_9 - mred_short DQ mred_10 - mred_short DQ mred_11 - mred_short DQ mred_12 - mred_short DQ mred_13 - mred_short DQ mred_14 - mred_short DQ mred_15 - mred_short DQ mred_16 - mred_short mred8x_start DQ mred8x1_start - mred8x_start DQ mred8x2_start - mred8x_start DQ mred8x3_start - mred8x_start DQ mred8x4_start - mred8x_start DQ mred8x5_start - mred8x_start DQ mred8x6_start - mred8x_start DQ mred8x7_start - mred8x_start cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmredpp.inc000066400000000000000000000417331470420105600260530ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number reduction Support ; ; %ifndef _PCPMRED_INC_ %assign _PCPMRED_INC_ 1 %include "pcpmredpp_basic.inc" ; ; r15 - reduction ; rdi - buffer ; rsi - modulus ; rdx - modulus length ; r8 - m' align IPP_ALIGN_FACTOR DECLARE_FUNC mred_8N_adcox,PRIVATE push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp mov rbx, rdx ; number of passes == modulus length xor rax, rax ; init global carry .passLoop: ; save: push rdi ; - buffer address push rsi ; - modulus address push rdx ; - modulus length push r8 ; - m' push rbx ; - rest of passes push rax ; - global carry ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; signgle pass ; push rdx ; init modulus counter mov rdx, r8 ; copy m' ; load low part of the product into r8,r9,r10,r11,r12,r13,r14,r15 mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start pop rdx ; restore modulus counter xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax jmp .entryInnerLoop .innerLoop: push rdx ; save modulus counter call mla_8x8 pop rdx ; restore modulus counter pop rax shr rax, 1 op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+0)], r8, [rdi+sizeof(qword)*(8+0)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+1)], r9, [rdi+sizeof(qword)*(8+1)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+2)], r10,[rdi+sizeof(qword)*(8+2)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+3)], r11,[rdi+sizeof(qword)*(8+3)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+4)], r12,[rdi+sizeof(qword)*(8+4)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+5)], r13,[rdi+sizeof(qword)*(8+5)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+6)], r14,[rdi+sizeof(qword)*(8+6)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+7)], r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax .entryInnerLoop: add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 sub rdx, 8 jg .innerLoop ; single pass completion pop rax ; new global carry pop rbx ; prev global carry add r8, rbx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 ; update global carry mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*6], r14 mov qword [rdi+sizeof(qword)*7], r15 ; ; end of single pass ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; restore: pop rbx ; - rest of passes pop r8 ; - m' pop rdx ; - modulus length pop rsi ; - modulus address pop rdi ; - buffer address add rdi, sizeof(qword)*8 sub rbx, 8 jg .passLoop add rsp, sizeof(qword)*8 ; release U space mov r14, rdx ; save modulus length lea r15, [rdx*sizeof(qword)]; save modulus length (bytes) mov rbx, rax ; global carry mov rcx, rsi ; modulus mov rsi, rdi ; buffer pop rdi ; reduction address call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow mov rdx, r14 ; length sub rdi, r15 ; reduction sub rsi, r15 ; buffer (src1) mov rcx, rdi ; reduction (src2) shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_8N_adcox ; ; r15 - reduction ; rdi - buffer ; rsi - modulus ; rdx - modulus length ; r8 - m' align IPP_ALIGN_FACTOR DECLARE_FUNC mred_N_adcox,PRIVATE push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp mov rbx, rdx ; number of passes counter == (modulus_length -8) sub rbx, 8 xor rax, rax ; init carryGBL mov r15, dword 7 ; n = modulus_len%8 and r15, rdx GET_EP rbp, mla_8xl_tail, r15 ; tail procedure (mla_8xn) address .passLoop: ; save: push rdi ; - buffer address push rsi ; - modulus address push rdx ; - modulus length push r8 ; - m' push rbx ; - rest of passes push rax ; - carryGBL push rbp ; - mla_8xn procedure ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; regular pass ;; sub rdx, 8 ; init modulus counter push rdx mov rdx, r8 ; copy m' ; load low part of the product into r8,r9,r10,r11,r12,r13,r14,r15 mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start pop rdx ; restore modulus counter xor rax, rax ; init carryLCL push rax jmp .entryInnerLoop .innerLoop: push rdx ; save modulus counter call mla_8x8 pop rdx ; restore modulus counter .entryInnerLoop: pop rax ; restore carryLCL shr rax, 1 op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+0)], r8, [rdi+sizeof(qword)*(8+0)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+1)], r9, [rdi+sizeof(qword)*(8+1)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+2)], r10,[rdi+sizeof(qword)*(8+2)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+3)], r11,[rdi+sizeof(qword)*(8+3)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+4)], r12,[rdi+sizeof(qword)*(8+4)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+5)], r13,[rdi+sizeof(qword)*(8+5)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+6)], r14,[rdi+sizeof(qword)*(8+6)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+7)], r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; update store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 sub rdx, 8 jnc .innerLoop add rdx, 8 jz .complete_regular_pass ; tail of single pass mov rax, [rsp+sizeof(qword)] ; procedure address SWAP rcx, rsi push rdx call rax pop rdx SWAP rcx, rsi lea rdi, [rdi+rdx*sizeof(qword)] pop rax ; restore carryLCL shr rax, 1 mov rbx, rdx dec rbx jz .mt_1 dec rbx jz .mt_2 dec rbx jz .mt_3 dec rbx jz .mt_4 dec rbx jz .mt_5 dec rbx jz .mt_6 .mt_7: op_reg_mem adc, r9, [rdi+sizeof(qword)*1], rbx .mt_6: op_reg_mem adc, r10,[rdi+sizeof(qword)*2], rbx .mt_5: op_reg_mem adc, r11,[rdi+sizeof(qword)*3], rbx .mt_4: op_reg_mem adc, r12,[rdi+sizeof(qword)*4], rbx .mt_3: op_reg_mem adc, r13,[rdi+sizeof(qword)*5], rbx .mt_2: op_reg_mem adc, r14,[rdi+sizeof(qword)*6], rbx .mt_1: op_reg_mem adc, r15,[rdi+sizeof(qword)*7], rbx adc rax, 0 ; update carryLCL push rax ; single pass completion .complete_regular_pass: pop rax ; carryLCL pop rbp ; mla_8xn procedure pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 ; update carryGBL mov qword [rdi+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*6], r14 mov qword [rdi+sizeof(qword)*7], r15 ;; ;; end of regular pass ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; restore: pop rbx ; - rest of passes pop r8 ; - m' pop rdx ; - modulus length pop rsi ; - modulus address pop rdi ; - buffer address add rdi, sizeof(qword)*8 sub rbx, 8 jnc .passLoop add rbx, 8 jz .complete_reduction ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; tail pass of reduction ;; ; save: push rdi ; - buffer address push rsi ; - modulus address push rdx ; - modulus length push r8 ; - m' push rbx ; - rest of passes push rax ; - carry push rbp ; - mla_8xn procedure sub rdx, 8 ; init modulus counter push rdx mov rdx, r8 ; copy m' ; load low part of the product into r8,r9,r10,r11,r12,r13,r14,r15 mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] GET_EP rax, mred8x_start, rbx, rbp ; procedure mred8xn_start address call rax pop rdx ; restore modulus counter xor rax, rax ; init carryCLC push rax jmp .entryTailLoop .tailLoop: mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rax, [rsp+sizeof(qword)] ; procedure address push rdx ; save modulus counter call rax pop rdx ; restore modulus counter .entryTailLoop: pop rax ; restore carryLCL shr rax, 1 adc r8, 0 adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 ; update carryGBL mov rbx, [rsp+sizeof(qword)*2] ; modulus_len%7 cmp rbx, 1 jz .tt_1 cmp rbx, 2 jz .tt_2 cmp rbx, 3 jz .tt_3 cmp rbx, 4 jz .tt_4 cmp rbx, 5 jz .tt_5 cmp rbx, 6 jz .tt_6 .tt_7: op_reg_mem adc, r9, [rdi+rbx*sizeof(qword)+sizeof(qword)*1], rbp .tt_6: op_reg_mem adc, r10,[rdi+rbx*sizeof(qword)+sizeof(qword)*2], rbp .tt_5: op_reg_mem adc, r11,[rdi+rbx*sizeof(qword)+sizeof(qword)*3], rbp .tt_4: op_reg_mem adc, r12,[rdi+rbx*sizeof(qword)+sizeof(qword)*4], rbp .tt_3: op_reg_mem adc, r13,[rdi+rbx*sizeof(qword)+sizeof(qword)*5], rbp .tt_2: op_reg_mem adc, r14,[rdi+rbx*sizeof(qword)+sizeof(qword)*6], rbp .tt_1: op_reg_mem adc, r15,[rdi+rbx*sizeof(qword)+sizeof(qword)*7], rbp adc rax, 0 push rax ; update store carryLCL mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*0], r8 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*1], r9 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*2], r10 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*3], r11 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*4], r12 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*5], r13 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*6], r14 mov qword [rdi+rbx*sizeof(qword)+sizeof(qword)*7], r15 add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 sub rdx, 8 jnc .tailLoop add rdx, 8 ; load data depending on length of tail mov rbx, rdx mov r8, qword [rdi] dec rbx jz .get_tail_proc mov r9, qword [rdi+sizeof(qword)] dec rbx jz .get_tail_proc mov r10, qword [rdi+sizeof(qword)*2] dec rbx jz .get_tail_proc mov r11, qword [rdi+sizeof(qword)*3] dec rbx jz .get_tail_proc mov r12, qword [rdi+sizeof(qword)*4] dec rbx jz .get_tail_proc mov r13, qword [rdi+sizeof(qword)*5] dec rbx jz .get_tail_proc mov r14, qword [rdi+sizeof(qword)*6] .get_tail_proc: ; multiply ; GET_EP rax, mla_8xl_tail, rdx, rbp ; tail procedure mla_8xn address GET_EP rax, mla_lxl_short, rdx, rbp ; tail procedure mla_lxl address push rdx call rax ; mla_nxn pop rdx lea rdi, [rdi+rdx*sizeof(qword)] ; accumulate carryLCL and update high product above pop rax shr rax, 1 mov rbx, rdx op_reg_mem adc, r8, [rdi+sizeof(qword)*0], rbp dec rbx jz .add_carry1 op_reg_mem adc, r9, [rdi+sizeof(qword)*1], rbp dec rbx jz .add_carry1 op_reg_mem adc, r10,[rdi+sizeof(qword)*2], rbp dec rbx jz .add_carry1 op_reg_mem adc, r11,[rdi+sizeof(qword)*3], rbp dec rbx jz .add_carry1 op_reg_mem adc, r12,[rdi+sizeof(qword)*4], rbp dec rbx jz .add_carry1 op_reg_mem adc, r13,[rdi+sizeof(qword)*5], rbp dec rbx jz .add_carry1 op_reg_mem adc, r14,[rdi+sizeof(qword)*6], rbp .add_carry1: adc rax, 0 pop rbp ; mul_8xn procedure ; accumulate carryGBL and store high product above pop rbx ; carryGBL add r8, rbx mov qword [rdi+sizeof(qword)*0], r8 dec rdx jz .add_carry2 adc r9, 0 mov qword [rdi+sizeof(qword)*1], r9 dec rdx jz .add_carry2 adc r10, 0 mov qword [rdi+sizeof(qword)*2], r10 dec rdx jz .add_carry2 adc r11, 0 mov qword [rdi+sizeof(qword)*3], r11 dec rdx jz .add_carry2 adc r12, 0 mov qword [rdi+sizeof(qword)*4], r12 dec rdx jz .add_carry2 adc r13, 0 mov qword [rdi+sizeof(qword)*5], r13 dec rdx jz .add_carry2 adc r14, 0 mov qword [rdi+sizeof(qword)*6], r14 .add_carry2: adc rax, 0 ; update carryGBL ; release stack pop rbx ; - passes counter pop r8 ; - m' pop rdx ; - modulus length pop rsi ; - modulus pop rdi ; - buffer lea rdi, [rdi+rbx*sizeof(qword)] .complete_reduction: add rsp, sizeof(qword)*8 ; release U space mov r14, rdx ; save modulus length lea r15, [rdx*sizeof(qword)]; save modulus length (bytes) mov rbx, rax ; carry mov rcx, rsi ; modulus mov rsi, rdi ; buffer pop rdi ; reduction address call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow mov rdx, r14 ; length sub rdi, r15 ; reduction sub rsi, r15 ; buffer (src1) mov rcx, rdi ; reduction (src2) shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_N_adcox %endif ;; _PCPMRED_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmredpp_basic.inc000066400000000000000000002150551470420105600272140ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Low level Big Number reduction Support ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Fixed-size Montgomery reduction ;; ; ; X7,X6,X5,X4,X3,X2,X1,X0 contains already preloaded (low) product ; %macro MRED_FIX 8-15.nolist %xdefine %%mSize %1 %xdefine %%rRed %2 %xdefine %%rProduct %3 %xdefine %%rModulus %4 %xdefine %%M0 %5 %xdefine %%TMPH %6 %xdefine %%TMP %7 %xdefine %%X0 %8 %xdefine %%X1 %9 %xdefine %%X2 %10 %xdefine %%X3 %11 %xdefine %%X4 %12 %xdefine %%X5 %13 %xdefine %%X6 %14 %xdefine %%X7 %15 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 1 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{}, {%%rModulus}, {%%TMPH},{%%TMP}, {%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 2 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 3 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{}, {%%rModulus}, {%%TMPH},{%%TMP}, {%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 4 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 5 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{}, {%%rModulus}, {%%TMPH},{%%TMP}, {%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 6 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %if %%mSize > 7 mov rdx, %%M0 imul rdx, %%X0 MLA_FIX {%%mSize},{},{%%rModulus},{%%TMPH},{%%TMP},{%%X0},{%%X1},{%%X2},{%%X3},{%%X4},{%%X5},{%%X6},{%%X7} %endif %endif %endif %endif %endif %endif %endif xor %%TMP, %%TMP add %%X0, qword [%%rProduct+sizeof(qword)*(%%mSize+0)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+0)], %%X0 %if %%mSize > 1 adc %%X1, qword [%%rProduct+sizeof(qword)*(%%mSize+1)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+1)], %%X1 %if %%mSize > 2 adc %%X2, qword [%%rProduct+sizeof(qword)*(%%mSize+2)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+2)], %%X2 %if %%mSize > 3 adc %%X3, qword [%%rProduct+sizeof(qword)*(%%mSize+3)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+3)], %%X3 %if %%mSize > 4 adc %%X4, qword [%%rProduct+sizeof(qword)*(%%mSize+4)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+4)], %%X4 %if %%mSize > 5 adc %%X5, qword [%%rProduct+sizeof(qword)*(%%mSize+5)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+5)], %%X5 %if %%mSize > 6 adc %%X6, qword [%%rProduct+sizeof(qword)*(%%mSize+6)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+6)], %%X6 %if %%mSize > 7 adc %%X7, qword [%%rProduct+sizeof(qword)*(%%mSize+7)] mov qword [%%rProduct+sizeof(qword)*(%%mSize+7)], %%X7 %endif %endif %endif %endif %endif %endif %endif adc %%TMP, 0 sub %%X0, qword [%%rModulus+sizeof(qword)*0] %if %%mSize > 1 sbb %%X1, qword [%%rModulus+sizeof(qword)*1] %if %%mSize > 2 sbb %%X2, qword [%%rModulus+sizeof(qword)*2] %if %%mSize > 3 sbb %%X3, qword [%%rModulus+sizeof(qword)*3] %if %%mSize > 4 sbb %%X4, qword [%%rModulus+sizeof(qword)*4] %if %%mSize > 5 sbb %%X5, qword [%%rModulus+sizeof(qword)*5] %if %%mSize > 6 sbb %%X6, qword [%%rModulus+sizeof(qword)*6] %if %%mSize > 7 sbb %%X7, qword [%%rModulus+sizeof(qword)*7] %endif %endif %endif %endif %endif %endif %endif sbb %%TMP, 0 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+0)] cmovae rax, %%X0 mov qword [%%rRed+sizeof(qword)*0], rax %if %%mSize > 1 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+1)] cmovae rax, %%X1 mov qword [%%rRed+sizeof(qword)*1], rax %if %%mSize > 2 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+2)] cmovae rax, %%X2 mov qword [%%rRed+sizeof(qword)*2], rax %if %%mSize > 3 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+3)] cmovae rax, %%X3 mov qword [%%rRed+sizeof(qword)*3], rax %if %%mSize > 4 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+4)] cmovae rax, %%X4 mov qword [%%rRed+sizeof(qword)*4], rax %if %%mSize > 5 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+5)] cmovae rax, %%X5 mov qword [%%rRed+sizeof(qword)*5], rax %if %%mSize > 6 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+6)] cmovae rax, %%X6 mov qword [%%rRed+sizeof(qword)*6], rax %if %%mSize > 7 mov rax, qword [%%rProduct+sizeof(qword)*(%%mSize+7)] cmovae rax, %%X7 mov qword [%%rRed+sizeof(qword)*7], rax %endif %endif %endif %endif %endif %endif %endif %endmacro align IPP_ALIGN_FACTOR DECLARE_FUNC sub_N,PRIVATE xor rax, rax ; cf = 0 .sub_next: lea rdi, [rdi+sizeof(qword)] mov r8, qword [rsi] mov r9, qword [rcx] lea rsi, [rsi+sizeof(qword)] lea rcx, [rcx+sizeof(qword)] sbb r8, r9 mov qword [rdi-sizeof(qword)], r8 dec rdx jnz .sub_next adc rax, 0 ret ENDFUNC sub_N align IPP_ALIGN_FACTOR DECLARE_FUNC copy_ae_N,PRIVATE lea rdi, [rdi+sizeof(qword)] mov r8, qword [rsi] ; src1[] mov r9, qword [rcx] ; src2[] lea rsi, [rsi+sizeof(qword)] lea rcx, [rcx+sizeof(qword)] cmovae r8, r9 mov qword [rdi-sizeof(qword)], r8 dec rdx jnz copy_ae_N ret ENDFUNC copy_ae_N ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; mredN_start procedures align IPP_ALIGN_FACTOR DECLARE_FUNC mred1_start,PRIVATE MLA_FIX 1,, rsi, rbx,rbp, r8 ret ENDFUNC mred1_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred2_start,PRIVATE MLA_FIX 2,, rsi, rbx,rbp, r8,r9 ret ENDFUNC mred2_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred3_start,PRIVATE MLA_FIX 3,, rsi, rbx,rbp, r8,r9,r10 ret ENDFUNC mred3_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred4_start,PRIVATE MLA_FIX 4,, rsi, rbx,rbp, r8,r9,r10,r11 ret ENDFUNC mred4_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred5_start,PRIVATE MLA_FIX 5,, rsi, rbx,rbp, r8,r9,r10,r11,r12 ret ENDFUNC mred5_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred6_start,PRIVATE MLA_FIX 6,, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13 ret ENDFUNC mred6_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred7_start,PRIVATE MLA_FIX 7,, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14 ret ENDFUNC mred7_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8_start,PRIVATE MLA_FIX 8,, rsi, rbx,rbp, r8,r9,r10,r11,r12,r13,r14,r15 ret ENDFUNC mred8_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x1_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax pop rdx ; resrore m' ret ENDFUNC mred8x1_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x2_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax pop rdx ; resrore m' ret ENDFUNC mred8x2_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x3_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax pop rdx ; resrore m' ret ENDFUNC mred8x3_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x4_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax pop rdx ; resrore m' ret ENDFUNC mred8x4_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x5_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax pop rdx ; resrore m' ret ENDFUNC mred8x5_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x6_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*5], rdx call mred8_start mov [rdi+sizeof(qword)*5], rax pop rdx ; resrore m' ret ENDFUNC mred8x6_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x7_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*5], rdx call mred8_start mov [rdi+sizeof(qword)*5], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*6], rdx call mred8_start mov [rdi+sizeof(qword)*6], rax pop rdx ; resrore m' ret ENDFUNC mred8x7_start align IPP_ALIGN_FACTOR DECLARE_FUNC mred8x8_start,PRIVATE push rdx ; save m' gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*0], rdx call mred8_start mov [rdi], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*1], rdx call mred8_start mov [rdi+sizeof(qword)*1], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*2], rdx call mred8_start mov [rdi+sizeof(qword)*2], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*3], rdx call mred8_start mov [rdi+sizeof(qword)*3], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*4], rdx call mred8_start mov [rdi+sizeof(qword)*4], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*5], rdx call mred8_start mov [rdi+sizeof(qword)*5], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*6], rdx call mred8_start mov [rdi+sizeof(qword)*6], rax mov rdx, [rsp] gsmulx rbx, rdx, r8 mov qword [rcx+sizeof(qword)*7], rdx call mred8_start mov [rdi+sizeof(qword)*7], rax pop rdx ; resrore m' ret ENDFUNC mred8x8_start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; rdi - temporary product buffer/temporary reduction ;; rsi - modulus ;; r8 - m' ;; r15 - target reduction address ;; ;; ;; 1*qword modulus length ;; ;; ;; 2*qword modulus length ;; ;; ;; 3*qword modulus length ;; ;; ;; 4*qword modulus length ;; ;; ;; 5*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_5,PRIVATE %assign MSIZE 5 push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred5_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx sbb rax, 0 ; copy under cf [r15] = cf? [r15] : {r8-r12} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] mov rbp, qword [rdi+sizeof(qword)*(MSIZE+4)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 cmovae rbp, r12 mov qword [r15+sizeof(qword)*0], rax mov qword [r15+sizeof(qword)*1], rbx mov qword [r15+sizeof(qword)*2], rcx mov qword [r15+sizeof(qword)*3], rdx mov qword [r15+sizeof(qword)*4], rbp ret ENDFUNC mred_5 ;; ;; 6*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_6,PRIVATE %assign MSIZE 6 push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred6_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE+5)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+5)], r13 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx op_reg_mem sbb, r13,[rsi+sizeof(qword)*5], rbx sbb rax, 0 ; copy under cf [r15] = cf? [r15] : {r8-r13} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] mov rbp, qword [rdi+sizeof(qword)*(MSIZE+4)] mov rsi, qword [rdi+sizeof(qword)*(MSIZE+5)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 cmovae rbp, r12 cmovae rsi, r13 mov qword [r15+sizeof(qword)*0], rax mov qword [r15+sizeof(qword)*1], rbx mov qword [r15+sizeof(qword)*2], rcx mov qword [r15+sizeof(qword)*3], rdx mov qword [r15+sizeof(qword)*4], rbp mov qword [r15+sizeof(qword)*5], rsi ret ENDFUNC mred_6 ;; ;; 7*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_7,PRIVATE %assign MSIZE 7 push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred7_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE+5)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+5)], r13 op_reg_mem adc, r14,[rdi+sizeof(qword)*(MSIZE+6)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+6)], r14 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx op_reg_mem sbb, r13,[rsi+sizeof(qword)*5], rbx op_reg_mem sbb, r14,[rsi+sizeof(qword)*6], rbx sbb rax, 0 ; copy under cf [r15] = cf? [r15] : {r8-r14} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] mov rbp, qword [rdi+sizeof(qword)*(MSIZE+4)] mov rsi, qword [rdi+sizeof(qword)*(MSIZE+5)] mov rdi, qword [rdi+sizeof(qword)*(MSIZE+6)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 cmovae rbp, r12 cmovae rsi, r13 cmovae rdi, r14 mov qword [r15+sizeof(qword)*0], rax mov qword [r15+sizeof(qword)*1], rbx mov qword [r15+sizeof(qword)*2], rcx mov qword [r15+sizeof(qword)*3], rdx mov qword [r15+sizeof(qword)*4], rbp mov qword [r15+sizeof(qword)*5], rsi mov qword [r15+sizeof(qword)*6], rdi ret ENDFUNC mred_7 ;; ;; 8*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_8,PRIVATE %assign MSIZE 8 push r15 ; save reduction address push r8 ; m' ; load low half of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] ; ui = x[i]*m' ; reduction += ui*modulus mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start mov rdx, [rsp] gsmulx rbx, rdx, r8 call mred8_start pop rax ; remove m' ; finalize cf, reduction += U0*modulus operation xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(MSIZE+0)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+0)], r8 op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE+1)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+1)], r9 op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE+2)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+2)], r10 op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE+3)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+3)], r11 op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE+4)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+4)], r12 op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE+5)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+5)], r13 op_reg_mem adc, r14,[rdi+sizeof(qword)*(MSIZE+6)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+6)], r14 op_reg_mem adc, r15,[rdi+sizeof(qword)*(MSIZE+7)], rbx mov qword [rdi+sizeof(qword)*(MSIZE+7)], r15 adc rax, 0 ; reduction -= modulus op_reg_mem sub, r8, [rsi+sizeof(qword)*0], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*1], rbx op_reg_mem sbb, r10,[rsi+sizeof(qword)*2], rbx op_reg_mem sbb, r11,[rsi+sizeof(qword)*3], rbx op_reg_mem sbb, r12,[rsi+sizeof(qword)*4], rbx op_reg_mem sbb, r13,[rsi+sizeof(qword)*5], rbx op_reg_mem sbb, r14,[rsi+sizeof(qword)*6], rbx op_reg_mem sbb, r15,[rsi+sizeof(qword)*7], rbx sbb rax, 0 pop rsi ; address of reduction ; copy under cf [rsi] = cf? [rdi] : {r8-r15} mov rax, qword [rdi+sizeof(qword)*(MSIZE+0)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+1)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+2)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+3)] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 mov qword [rsi+sizeof(qword)*0], rax mov qword [rsi+sizeof(qword)*1], rbx mov qword [rsi+sizeof(qword)*2], rcx mov qword [rsi+sizeof(qword)*3], rdx mov rax, qword [rdi+sizeof(qword)*(MSIZE+4)] mov rbx, qword [rdi+sizeof(qword)*(MSIZE+5)] mov rcx, qword [rdi+sizeof(qword)*(MSIZE+6)] mov rdx, qword [rdi+sizeof(qword)*(MSIZE+7)] cmovae rax, r12 cmovae rbx, r13 cmovae rcx, r14 cmovae rdx, r15 mov qword [rsi+sizeof(qword)*4], rax mov qword [rsi+sizeof(qword)*5], rbx mov qword [rsi+sizeof(qword)*6], rcx mov qword [rsi+sizeof(qword)*7], rdx ret ENDFUNC mred_8 ;; ;; 9*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_9,PRIVATE %assign MSIZE 9 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x1 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x1_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14 mov r8, r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_1x1 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_9 ;; ;; 10*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_10,PRIVATE %assign MSIZE 10 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x2 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x2_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov r8, r14 mov r9, r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_2x2 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_10 ;; ;; 11*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_11,PRIVATE %assign MSIZE 11 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x3 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x3_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov r8, r13 mov r9, r14 mov r10,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_3x3 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_11 ;; ;; 12*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_12,PRIVATE %assign MSIZE 12 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x4 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x4_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov r8, r12 mov r9, r13 mov r10,r14 mov r11,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_4x4 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_12 ;; ;; 13*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_13,PRIVATE %assign MSIZE 13 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x5 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x5_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov r8, r11 mov r9, r12 mov r10,r13 mov r11,r14 mov r12,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r12,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_5x5 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 adc r12,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_13 ;; ;; 14*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_14,PRIVATE %assign MSIZE 14 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x6 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x6_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov r8, r10 mov r9, r11 mov r10,r12 mov r11,r13 mov r12,r14 mov r13,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r12,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r13,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_6x6 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_14 ;; ;; 15*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_15,PRIVATE %assign MSIZE 15 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp push r8 ; save m' mov rdx, r8 ;; ;; init pass ;; ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax ; init carryLCL op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 SWAP rcx, rsi call mla_8x7 SWAP rcx, rsi pop rax shr rax, 1 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], r15, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7], rbx adc rax, 0 push rax ; store carryGBL ;; ;; last pass ;; sub rsi, sizeof(qword)*8 mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] mov rdx, [rsp+sizeof(qword)] call mred8x7_start xor rax, rax ; init carryLCL mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov r8, r9 mov r9, r10 mov r10,r11 mov r11,r12 mov r12,r13 mov r13,r14 mov r14,r15 add r8, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1] adc r9, qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2] adc r10,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3] adc r11,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4] adc r12,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5] adc r13,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6] adc r14,qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*7] adc rax, 0 push rax ; store carryLCL add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_7x7 pop rax ; restore carryLCL shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], rbx adc rax, 0 pop rbx ; carryGBL add r8, rbx adc r9, 0 adc r10,0 adc r11,0 adc r12,0 adc r13,0 adc r14,0 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*0], r8 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*1], r9 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*2], r10 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*3], r11 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*4], r12 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*5], r13 mov qword [rdi+sizeof(qword)*(MSIZE-8)+sizeof(qword)*6], r14 adc rax, 0 ; update carryGBL pop rcx ; remove m' add rsp, sizeof(qword)*8 ; release U space lea rcx, [rsi-sizeof(qword)*8] ; restore modulus lea rsi, [rdi+sizeof(qword)*(MSIZE-8)-sizeof(qword)*8] ; restore buffer pop rdi ; restore reduction mov rbx, rax ; save carryGBL mov rdx, dword MSIZE call sub_N ; reduction = buffer - modulus sub rbx, rax ; rbx = borrow sub rdi, sizeof(qword)*MSIZE ; reduction sub rsi, sizeof(qword)*MSIZE ; buffer (src1) mov rcx, rdi ; reduction (src2) mov rdx, dword MSIZE shr rbx,1 ; restore cf call copy_ae_N ; copy under cf, reduction = cf? buffer : reduction ret ENDFUNC mred_15 ;; ;; 16*qword modulus length ;; align IPP_ALIGN_FACTOR DECLARE_FUNC mred_16,PRIVATE %assign MSIZE 16 push r15 ; save reduction address sub rsp, sizeof(qword)*8 ; allocate U space mov rcx, rsp mov rdx, r8 ; copy m' ; load low part of the product mov r8, qword [rdi] ; x0,x1,x2,x3,x4,x5,x6,x7 mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax add rsi, sizeof(qword)*8 add rdi, sizeof(qword)*8 push rdx call mla_8x8 pop rdx pop rax shr rax, 1 op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+0)], r8, [rdi+sizeof(qword)*(8+0)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+1)], r9, [rdi+sizeof(qword)*(8+1)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+2)], r10,[rdi+sizeof(qword)*(8+2)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+3)], r11,[rdi+sizeof(qword)*(8+3)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+4)], r12,[rdi+sizeof(qword)*(8+4)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+5)], r13,[rdi+sizeof(qword)*(8+5)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+6)], r14,[rdi+sizeof(qword)*(8+6)], rbx op_mem_reg_mem adc, [rdi+sizeof(qword)*(8+7)], r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax sub rsi, sizeof(qword)*8 mov r8, qword [rdi] mov r9, qword [rdi+sizeof(qword)] mov r10,qword [rdi+sizeof(qword)*2] mov r11,qword [rdi+sizeof(qword)*3] mov r12,qword [rdi+sizeof(qword)*4] mov r13,qword [rdi+sizeof(qword)*5] mov r14,qword [rdi+sizeof(qword)*6] mov r15,qword [rdi+sizeof(qword)*7] call mred8x8_start xor rax, rax op_reg_mem add, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10,[rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11,[rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12,[rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13,[rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14,[rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15,[rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 push rax add rdi, sizeof(qword)*8 add rsi, sizeof(qword)*8 call mla_8x8 sub rsi, sizeof(qword)*8 pop rax shr rax, 1 op_reg_mem adc, r8, [rdi+sizeof(qword)*(8+0)], rbx op_reg_mem adc, r9, [rdi+sizeof(qword)*(8+1)], rbx op_reg_mem adc, r10, [rdi+sizeof(qword)*(8+2)], rbx op_reg_mem adc, r11, [rdi+sizeof(qword)*(8+3)], rbx op_reg_mem adc, r12, [rdi+sizeof(qword)*(8+4)], rbx op_reg_mem adc, r13, [rdi+sizeof(qword)*(8+5)], rbx op_reg_mem adc, r14, [rdi+sizeof(qword)*(8+6)], rbx op_reg_mem adc, r15, [rdi+sizeof(qword)*(8+7)], rbx adc rax, 0 pop rbx add r8, rbx adc r9, 0 adc r10, 0 adc r11, 0 adc r12, 0 adc r13, 0 adc r14, 0 adc r15, 0 adc rax, 0 mov qword [rdi+sizeof(qword)*(8+0)], r8 mov qword [rdi+sizeof(qword)*(8+1)], r9 mov qword [rdi+sizeof(qword)*(8+2)], r10 mov qword [rdi+sizeof(qword)*(8+3)], r11 mov qword [rdi+sizeof(qword)*(8+4)], r12 mov qword [rdi+sizeof(qword)*(8+5)], r13 mov qword [rdi+sizeof(qword)*(8+6)], r14 mov qword [rdi+sizeof(qword)*(8+7)], r15 add rsp, sizeof(qword)*8 ; release U space pop rbp ; reduction -= modulus op_mem_mem sub, [rbp+sizeof(qword)*0 ], [rdi+sizeof(qword)*0 ], [rsi+sizeof(qword)*0 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*1 ], [rdi+sizeof(qword)*1 ], [rsi+sizeof(qword)*1 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*2 ], [rdi+sizeof(qword)*2 ], [rsi+sizeof(qword)*2 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*3 ], [rdi+sizeof(qword)*3 ], [rsi+sizeof(qword)*3 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*4 ], [rdi+sizeof(qword)*4 ], [rsi+sizeof(qword)*4 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*5 ], [rdi+sizeof(qword)*5 ], [rsi+sizeof(qword)*5 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*6 ], [rdi+sizeof(qword)*6 ], [rsi+sizeof(qword)*6 ], rbx op_mem_mem sbb, [rbp+sizeof(qword)*7 ], [rdi+sizeof(qword)*7 ], [rsi+sizeof(qword)*7 ], rbx op_reg_mem sbb, r8, [rsi+sizeof(qword)*8 ], rbx op_reg_mem sbb, r9, [rsi+sizeof(qword)*9 ], rbx op_reg_mem sbb, r10, [rsi+sizeof(qword)*10], rbx op_reg_mem sbb, r11, [rsi+sizeof(qword)*11], rbx op_reg_mem sbb, r12, [rsi+sizeof(qword)*12], rbx op_reg_mem sbb, r13, [rsi+sizeof(qword)*13], rbx op_reg_mem sbb, r14, [rsi+sizeof(qword)*14], rbx op_reg_mem sbb, r15, [rsi+sizeof(qword)*15], rbx sbb rax, 0 ; copy under cf [rbp] = cf? [rdi] : [rbp] mov rax, qword [rdi+sizeof(qword)*8 ] mov rbx, qword [rdi+sizeof(qword)*9 ] mov rcx, qword [rdi+sizeof(qword)*10] mov rdx, qword [rdi+sizeof(qword)*11] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 mov qword [rbp+sizeof(qword)*8 ], rax mov qword [rbp+sizeof(qword)*9 ], rbx mov qword [rbp+sizeof(qword)*10], rcx mov qword [rbp+sizeof(qword)*11], rdx mov rax, qword [rdi+sizeof(qword)*12] mov rbx, qword [rdi+sizeof(qword)*13] mov rcx, qword [rdi+sizeof(qword)*14] mov rdx, qword [rdi+sizeof(qword)*15] cmovae rax, r12 cmovae rbx, r13 cmovae rcx, r14 cmovae rdx, r15 mov qword [rbp+sizeof(qword)*12], rax mov qword [rbp+sizeof(qword)*13], rbx mov qword [rbp+sizeof(qword)*14], rcx mov qword [rbp+sizeof(qword)*15], rdx mov r8, qword [rbp+sizeof(qword)*0] mov r9, qword [rbp+sizeof(qword)*1] mov r10, qword [rbp+sizeof(qword)*2] mov r11, qword [rbp+sizeof(qword)*3] mov r12, qword [rbp+sizeof(qword)*4] mov r13, qword [rbp+sizeof(qword)*5] mov r14, qword [rbp+sizeof(qword)*6] mov r15, qword [rbp+sizeof(qword)*7] mov rax, qword [rdi+sizeof(qword)*0] mov rbx, qword [rdi+sizeof(qword)*1] mov rcx, qword [rdi+sizeof(qword)*2] mov rdx, qword [rdi+sizeof(qword)*3] cmovae rax, r8 cmovae rbx, r9 cmovae rcx, r10 cmovae rdx, r11 mov qword [rbp+sizeof(qword)*0], rax mov qword [rbp+sizeof(qword)*1], rbx mov qword [rbp+sizeof(qword)*2], rcx mov qword [rbp+sizeof(qword)*3], rdx mov rax, qword [rdi+sizeof(qword)*4] mov rbx, qword [rdi+sizeof(qword)*5] mov rcx, qword [rdi+sizeof(qword)*6] mov rdx, qword [rdi+sizeof(qword)*7] cmovae rax, r12 cmovae rbx, r13 cmovae rcx, r14 cmovae rdx, r15 mov qword [rbp+sizeof(qword)*4], rax mov qword [rbp+sizeof(qword)*5], rbx mov qword [rbp+sizeof(qword)*6], rcx mov qword [rbp+sizeof(qword)*7], rdx ret ENDFUNC mred_16 mred_short DQ mred_5 - mred_short DQ mred_6 - mred_short DQ mred_7 - mred_short DQ mred_8 - mred_short DQ mred_9 - mred_short DQ mred_10 - mred_short DQ mred_11 - mred_short DQ mred_12 - mred_short DQ mred_13 - mred_short DQ mred_14 - mred_short DQ mred_15 - mred_short DQ mred_16 - mred_short mred8x_start DQ mred8x1_start - mred8x_start DQ mred8x2_start - mred8x_start DQ mred8x3_start - mred8x_start DQ mred8x4_start - mred8x_start DQ mred8x5_start - mred8x_start DQ mred8x6_start - mred8x_start DQ mred8x7_start - mred8x_start cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpmulx.inc000066400000000000000000000066051470420105600255500ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2013 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: EM64T Cryptography Primitive. ; Emulation of Intel(R) instructions MULX, ADCX, ADOX (for debug only) ; ; %ifndef _PCPMULX_INC_ %assign _PCPMULX_INC_ 1 %ifndef _EMULATION_ %macro gsmulx 3.nolist %xdefine %%resH %1 %xdefine %%resL %2 %xdefine %%src %3 mulx %%resH,%%resL,%%src %endmacro %endif %ifdef _EMULATION_ %macro gsmulx 3.nolist %xdefine %%resH %1 %xdefine %%resL %2 %xdefine %%src %3 pushf ;; store flags sub rsp, sizeof(qword)*4 mov [rsp-sizeof(qword)*3], rax ;; store RAX mov [rsp-sizeof(qword)*2], rdx ;; store RDX mov rax,rdx mov rdx, %%src mul rdx mov [rsp-sizeof(qword)*1], rax ;; store Low product mov [rsp-sizeof(qword)*0], rdx ;; store Hig product mov rax, [rsp-sizeof(qword)*3] ;; re-store RAX mov rdx, [rsp-sizeof(qword)*2] ;; re-store RDX mov %%resL, [rsp-sizeof(qword)*1];; load Low product mov %%resH, [rsp-sizeof(qword)*0];; load Hig product add rsp, sizeof(qword)*4 popf ;; re-store flags %endmacro %endif %ifndef _EMULATION_ %macro gsadcx 2.nolist %xdefine %%rdst %1 %xdefine %%rsrc %2 adcx %%rdst, %%rsrc %endmacro %endif %ifdef _EMULATION_ %macro gsadcx 2.nolist %xdefine %%rdst %1 %xdefine %%src %2 push %%rdst ;; slot for result push rax ;; save rax pushfq ;; flags before adc adc %%rdst, %%src mov [rsp+2*sizeof(qword)], %%rdst pushfq ;; rsrc = flags after operation pop rax and rax, 1 ;; cf after operation and qword [rsp], (-2) ;; clear cf before operation or [rsp], rax ;; new psw popfq pop rax pop %%rdst %endmacro %endif %ifndef _EMULATION_ %macro gsadox 2.nolist %xdefine %%rdst %1 %xdefine %%rsrc %2 adox %%rdst, %%rsrc %endmacro %endif %ifdef _EMULATION_ %macro gsadox 2.nolist %xdefine %%rdst %1 %xdefine %%src %2 push %%rdst push rax ;; save rax pushfq ;; rax = flags before adc mov rax, [rsp] and rax, 800h ;; of xor [rsp], rax ;; clear of shr rax, 11 ;; mov of to cf position push rax ;; new psw popfq %ifidni %%src,rax mov rax, [rsp+sizeof(qword)] %endif %ifidni %%rdst,rax mov %%rdst, [rsp+2*sizeof(qword)] %endif adc %%rdst, %%src mov [rsp+2*sizeof(qword)], %%rdst pushfq ;; rsrc = flags after operation pop rax and rax, 1 ;; cf after operation shl rax, 11 ;; mov cf into of position or [rsp], rax ;; new psw popfq pop rax pop %%rdst %endmacro %endif %endif ;; _PCPMULX_INC_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpp192r1funcs_montas.asm000066400000000000000000000550031470420105600301440ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; secp p192r1 specific implementation ; %include "asmdefs.inc" %include "ia_32e.inc" %if _IPP32E >= _IPP32E_M7 %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;; The p192r1 polynomial Lpoly DQ 0FFFFFFFFFFFFFFFFh,0FFFFFFFFFFFFFFFEh,0FFFFFFFFFFFFFFFFh ;; 2^(192*2) mod P precomputed for p192r1 polynomial LRR DQ 00000000000000001h,00000000000000002h,00000000000000001h LOne DD 1,1,1,1,1,1,1,1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_mul_by_2(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_mul_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 xor t3, t3 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] shld t3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 REST_XMM REST_GPR ret ENDFUNC p192r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_div_by_2(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_div_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] xor t3, t3 xor r13, r13 mov t0, a0 mov t1, a1 mov t2, a2 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, 0 test a0, 1 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz r13,t3 shrd a0, a1, 1 shrd a1, a2, 1 shrd a2, r13,1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 REST_XMM REST_GPR ret ENDFUNC p192r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_mul_by_3(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_mul_by_3,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 xor t3, t3 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] shld t3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 xor t3, t3 add a0, qword [rsi+sizeof(qword)*0] adc a1, qword [rsi+sizeof(qword)*1] adc a2, qword [rsi+sizeof(qword)*2] adc t3, 0 mov t0, a0 mov t1, a1 mov t2, a2 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 REST_XMM REST_GPR ret ENDFUNC p192r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_add(uint64_t res[3], uint64_t a[3], uint64_t b[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 xor t3, t3 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] add a0, qword [rdx+sizeof(qword)*0] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc t3, 0 mov t0, a0 mov t1, a1 mov t2, a2 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 REST_XMM REST_GPR ret ENDFUNC p192r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_sub(uint64_t res[3], uint64_t a[3], uint64_t b[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 xor t3, t3 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] sub a0, qword [rdx+sizeof(qword)*0] sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb t3, 0 mov t0, a0 mov t1, a1 mov t2, a2 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] test t3, t3 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 REST_XMM REST_GPR ret ENDFUNC p192r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_neg(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 xor t3, t3 xor a0, a0 xor a1, a1 xor a2, a2 sub a0, qword [rsi+sizeof(qword)*0] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb t3, 0 mov t0, a0 mov t1, a1 mov t2, a2 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] test t3, t3 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 REST_XMM REST_GPR ret ENDFUNC p192r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_mul_montl(uint64_t res[3], uint64_t a[3], uint64_t b[3]); ; void p192r1_mul_montx(uint64_t res[3], uint64_t a[3], uint64_t b[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; product = {p3,p2,p1,p0}, p4=0 ; product += 2^192*p0 -2^64*p0 -p0 ; ; on entry p4=0 ; on exit p0=0 ; %macro p192r1_mul_redstep 5.nolist %xdefine %%p4 %1 %xdefine %%p3 %2 %xdefine %%p2 %3 %xdefine %%p1 %4 %xdefine %%p0 %5 sub %%p1, %%p0 sbb %%p2, 0 sbb %%p0, 0 add %%p3, %%p0 adc %%p4, 0 xor %%p0, %%p0 %endmacro align IPP_ALIGN_FACTOR p192r1_mmull: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc4, acc4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*0] mov acc0, rax mov acc1, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*1] add acc1, rax adc rdx, 0 mov acc2, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*2] add acc2, rax adc rdx, 0 mov acc3, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 p192r1_mul_redstep acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*0] add acc1, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*1] add acc2, rcx adc rdx, 0 add acc2, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*2] add acc3, rcx adc rdx, 0 add acc3, rax adc acc4, rdx adc acc0, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 p192r1_mul_redstep acc0,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*0] add acc2, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*1] add acc3, rcx adc rdx, 0 add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*2] add acc4, rcx adc rdx, 0 add acc4, rax adc acc0, rdx adc acc1, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 (final) p192r1_mul_redstep acc1,acc0,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, acc3 ;; copy reducted result mov t1, acc4 mov t2, acc0 sub t0, qword [rel Lpoly+sizeof(qword)*0] ;; test %if it exceeds prime value sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb acc1, 0 cmovnc acc3, t0 cmovnc acc4, t1 cmovnc acc0, t2 mov qword [rdi+sizeof(qword)*0], acc3 mov qword [rdi+sizeof(qword)*1], acc4 mov qword [rdi+sizeof(qword)*2], acc0 ret %if (_IPP32E >= _IPP32E_L9) align IPP_ALIGN_FACTOR p192r1_mmulx: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc4, acc4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] xor rdx, rdx mov rdx, qword [bPtr+sizeof(qword)*0] mulx acc1,acc0, qword [aPtr+sizeof(qword)*0] mulx acc2,t2, qword [aPtr+sizeof(qword)*1] add acc1,t2 mulx acc3,t2, qword [aPtr+sizeof(qword)*2] adc acc2,t2 adc acc3,0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 p192r1_mul_redstep acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rdx, qword [bPtr+sizeof(qword)*1] mulx t0, t2, qword [aPtr+sizeof(qword)*0] adcx acc1, t2 adox acc2, t0 mulx t0, t2, qword [aPtr+sizeof(qword)*1] adcx acc2, t2 adox acc3, t0 mulx t0, t2, qword [aPtr+sizeof(qword)*2] adcx acc3, t2 adox acc4, t0 adcx acc4, acc0 adox acc0, acc0 adc acc0, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 p192r1_mul_redstep acc0,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rdx, qword [bPtr+sizeof(qword)*2] mulx t0, t2, qword [aPtr+sizeof(qword)*0] adcx acc2, t2 adox acc3, t0 mulx t0, t2, qword [aPtr+sizeof(qword)*1] adcx acc3, t2 adox acc4, t0 mulx t0, t2, qword [aPtr+sizeof(qword)*2] adcx acc4, t2 adox acc0, t0 adcx acc0, acc1 adox acc1, acc1 adc acc1, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 (final) p192r1_mul_redstep acc1,acc0,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, acc3 ;; copy reducted result mov t1, acc4 mov t2, acc0 sub t0, qword [rel Lpoly+sizeof(qword)*0] ;; test %if it exceeds prime value sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb acc1, 0 cmovnc acc3, t0 cmovnc acc4, t1 cmovnc acc0, t2 mov qword [rdi+sizeof(qword)*0], acc3 mov qword [rdi+sizeof(qword)*1], acc4 mov qword [rdi+sizeof(qword)*2], acc0 ret %endif align IPP_ALIGN_FACTOR IPPASM p192r1_mul_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call p192r1_mmull REST_XMM REST_GPR ret ENDFUNC p192r1_mul_montl %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM p192r1_mul_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call p192r1_mmulx REST_XMM REST_GPR ret ENDFUNC p192r1_mul_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_to_mont(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_to_mont,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12 USES_XMM COMP_ABI 2 lea rbx, [rel LRR] call p192r1_mmull REST_XMM REST_GPR ret ENDFUNC p192r1_to_mont ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_sqr_montl(uint64_t res[3], uint64_t a[3]); ; void p192r1_sqr_montx(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; on entry e = expansion (previous step) ; on exit p0= expansion (next step) ; %macro p192r1_prod_redstep 5.nolist %xdefine %%e %1 %xdefine %%p3 %2 %xdefine %%p2 %3 %xdefine %%p1 %4 %xdefine %%p0 %5 sub %%p1, %%p0 sbb %%p2, 0 sbb %%p0, 0 add %%p3, %%p0 mov %%p0, dword 0 adc %%p0, 0 %ifnempty %%e add %%p3, %%e adc %%p0, 0 %endif %endmacro align IPP_ALIGN_FACTOR IPPASM p192r1_sqr_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*0] mov rax,qword [aPtr+sizeof(qword)*1] mul t2 mov acc1, rax mov acc2, rdx mov rax,qword [aPtr+sizeof(qword)*2] mul t2 add acc2, rax adc rdx, 0 mov acc3, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*1] mov rax,qword [aPtr+sizeof(qword)*2] mul t2 add acc3, rax adc rdx, 0 mov acc4, rdx xor acc5, acc5 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 mov rax,qword [aPtr+sizeof(qword)*0] mul rax mov acc0, rax add acc1, rdx adc acc2, 0 mov rax,qword [aPtr+sizeof(qword)*1] mul rax add acc2, rax adc acc3, rdx adc acc4, 0 mov rax,qword [aPtr+sizeof(qword)*2] mul rax add acc4, rax adc acc5, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; p192r1_prod_redstep ,acc3,acc2,acc1,acc0 p192r1_prod_redstep acc0,acc4,acc3,acc2,acc1 p192r1_prod_redstep acc1,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, acc3 mov t1, acc4 mov t2, acc5 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb acc2, 0 cmovnc acc3, t0 cmovnc acc4, t1 cmovnc acc5, t2 mov qword [rdi+sizeof(qword)*0], acc3 mov qword [rdi+sizeof(qword)*1], acc4 mov qword [rdi+sizeof(qword)*2], acc5 REST_XMM REST_GPR ret ENDFUNC p192r1_sqr_montl %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM p192r1_sqr_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine t0 rcx %xdefine t1 rax %xdefine t2 rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*0] mulx acc2, acc1, qword [aPtr+sizeof(qword)*1] mulx acc3, t0, qword [aPtr+sizeof(qword)*2] add acc2, t0 adc acc3, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*1] mulx acc4, t0, qword [aPtr+sizeof(qword)*2] add acc3, t0 adc acc4, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; xor acc5, acc5 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 xor acc0, acc0 mov rdx, qword [aPtr+sizeof(qword)*0] mulx t1, acc0, rdx adcx acc1, t1 mov rdx, qword [aPtr+sizeof(qword)*1] mulx t1, t0, rdx adcx acc2, t0 adcx acc3, t1 mov rdx, qword [aPtr+sizeof(qword)*2] mulx t1, t0, rdx adcx acc4, t0 adcx acc5, t1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; p192r1_prod_redstep ,acc3,acc2,acc1,acc0 p192r1_prod_redstep acc0,acc4,acc3,acc2,acc1 p192r1_prod_redstep acc1,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, acc3 mov t1, acc4 mov t2, acc5 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb acc2, 0 cmovnc acc3, t0 cmovnc acc4, t1 cmovnc acc5, t2 mov qword [rdi+sizeof(qword)*0], acc3 mov qword [rdi+sizeof(qword)*1], acc4 mov qword [rdi+sizeof(qword)*2], acc5 REST_XMM REST_GPR ret ENDFUNC p192r1_sqr_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_mont_back(uint64_t res[3], uint64_t a[3]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_mont_back,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rsi mov acc2, qword [rsi+sizeof(qword)*0] mov acc3, qword [rsi+sizeof(qword)*1] mov acc4, qword [rsi+sizeof(qword)*2] xor acc0, acc0 xor acc1, acc1 p192r1_mul_redstep acc1,acc0,acc4,acc3,acc2 p192r1_mul_redstep acc2,acc1,acc0,acc4,acc3 p192r1_mul_redstep acc3,acc2,acc1,acc0,acc4 mov t0, acc0 mov t1, acc1 mov t2, acc2 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb acc4, 0 cmovnc acc0, t0 cmovnc acc1, t1 cmovnc acc2, t2 mov qword [rdi+sizeof(qword)*0], acc0 mov qword [rdi+sizeof(qword)*1], acc1 mov qword [rdi+sizeof(qword)*2], acc2 REST_XMM REST_GPR ret ENDFUNC p192r1_mont_back %ifndef _DISABLE_ECP_192R1_HARDCODED_BP_TBL_ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p192r1_select_ap_w7(AF_POINT *val, const AF_POINT *in_t, int index); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p192r1_select_ap_w7,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM xmm6,xmm7,xmm8,xmm9 COMP_ABI 3 %xdefine val rdi %xdefine in_t rsi %xdefine idx edx %xdefine ONE xmm0 %xdefine INDEX xmm1 %xdefine Ra xmm2 %xdefine Rb xmm3 %xdefine Rc xmm4 %xdefine T0a xmm5 %xdefine T0b xmm6 %xdefine T0c xmm7 %xdefine M0 xmm8 %xdefine TMP0 xmm9 movdqa ONE, oword [rel LOne] pxor Ra, Ra pxor Rb, Rb pxor Rc, Rc movdqa M0, ONE movd INDEX, idx pshufd INDEX, INDEX, 0 ; Skip index = 0, is implicictly infty -> load with offset -1 mov rcx, dword 64 .select_loop_sse_w7: movdqa TMP0, M0 pcmpeqd TMP0, INDEX paddd M0, ONE movdqa T0a, oword [in_t+sizeof(oword)*0] movdqa T0b, oword [in_t+sizeof(oword)*1] movdqa T0c, oword [in_t+sizeof(oword)*2] add in_t, sizeof(oword)*3 pand T0a, TMP0 pand T0b, TMP0 pand T0c, TMP0 por Ra, T0a por Rb, T0b por Rc, T0c dec rcx jnz .select_loop_sse_w7 movdqu oword [val+sizeof(oword)*0], Ra movdqu oword [val+sizeof(oword)*1], Rb movdqu oword [val+sizeof(oword)*2], Rc REST_XMM REST_GPR ret ENDFUNC p192r1_select_ap_w7 %endif %endif ;; _IPP32E_M7 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpp224r1funcs_montas.asm000066400000000000000000000576451470420105600301560ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; secp p224r1 specific implementation ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;; The p224r1 polynomial Lpoly DQ 00000000000000001h,0ffffffff00000000h,0ffffffffffffffffh,000000000ffffffffh ;; mont(1) ;; ffffffff00000000 ffffffffffffffff 0000000000000000 0000000000000000 ;; 2^(2*224) mod P precomputed for p224r1 polynomial LRR DQ 0ffffffff00000001h,0ffffffff00000000h,0fffffffe00000000h,000000000ffffffffh LOne DD 1,1,1,1,1,1,1,1 LTwo DD 2,2,2,2,2,2,2,2 LThree DD 3,3,3,3,3,3,3,3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_mul_by_2(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_mul_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] shld t4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p224r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_div_by_2(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_div_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] xor t4, t4 xor r14, r14 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] adc t4, 0 test a0, 1 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 cmovnz r14,t4 shrd a0, a1, 1 shrd a1, a2, 1 shrd a2, a3, 1 shrd a3, r14,1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p224r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_mul_by_3(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_mul_by_3,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] shld t4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 xor t4, t4 add a0, qword [rsi+sizeof(qword)*0] adc a1, qword [rsi+sizeof(qword)*1] adc a2, qword [rsi+sizeof(qword)*2] adc a3, qword [rsi+sizeof(qword)*3] adc t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p224r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_add(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] add a0, qword [rdx+sizeof(qword)*0] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc a3, qword [rdx+sizeof(qword)*3] adc t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p224r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_sub(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] sub a0, qword [rdx+sizeof(qword)*0] sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb a3, qword [rdx+sizeof(qword)*3] sbb t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p224r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_neg(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 xor a0, a0 xor a1, a1 xor a2, a2 xor a3, a3 sub a0, qword [rsi+sizeof(qword)*0] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb a3, qword [rsi+sizeof(qword)*3] sbb t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p224r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_mul_montl(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; void p224r1_mul_montx(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; was working on GFp functionality the problem (in reduction spep) has been found ;; 1) "sqr" implementation has been changed by "mul" ;; 2) fortunately "mont_back" stay as is because of operand zero extensioned ; on entry p5=0 ; on exit p0=0 ; %macro p224r1_prod_redstep 5.nolist %xdefine %%p4 %1 %xdefine %%p3 %2 %xdefine %%p2 %3 %xdefine %%p1 %4 %xdefine %%p0 %5 neg %%p0 mov t2, %%p0 mov t3, %%p0 xor t0, t0 xor t1, t1 shr t3, 32 shl t2, 32 sub t0, t2 sbb t1, t3 sbb t2, 0 sbb t3, 0 neg %%p0 adc %%p1, t0 adc %%p2, t1 adc %%p3, t2 adc %%p4, t3 %endmacro align IPP_ALIGN_FACTOR p224r1_mmull: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rbp %xdefine t4 rbx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc5, acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*0] mov acc0, rax mov acc1, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*1] add acc1, rax adc rdx, 0 mov acc2, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*2] add acc2, rax adc rdx, 0 mov acc3, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*3] add acc3, rax adc rdx, 0 mov acc4, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 p224r1_prod_redstep acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*0] add acc1, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*1] add acc2, rcx adc rdx, 0 add acc2, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*2] add acc3, rcx adc rdx, 0 add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*3] add acc4, rcx adc rdx, 0 add acc4, rax adc rdx, 0 mov acc5, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 p224r1_prod_redstep acc5,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*0] add acc2, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*1] add acc3, rcx adc rdx, 0 add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*2] add acc4, rcx adc rdx, 0 add acc4, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*3] add acc5, rcx adc rdx, 0 add acc5, rax adc rdx, 0 mov acc6, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 p224r1_prod_redstep acc6,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[3] mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*0] add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*1] add acc4, rcx adc rdx, 0 add acc4, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*2] add acc5, rcx adc rdx, 0 add acc5, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*3] add acc6, rcx adc rdx, 0 add acc6, rax adc rdx, 0 mov acc7, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 3 (final) p224r1_prod_redstep acc7,acc6,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov acc0, acc4 ;; copy reducted result mov acc1, acc5 mov acc2, acc6 mov acc3, acc7 sub acc4, t0 ;; test %if it exceeds prime value sbb acc5, t1 sbb acc6, t2 sbb acc7, t3 cmovc acc4, acc0 cmovc acc5, acc1 cmovc acc6, acc2 cmovc acc7, acc3 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 ret %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR p224r1_mmulx: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rbp %xdefine t4 rbx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc5, acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] mov rdx, qword [bPtr+sizeof(qword)*0] mulx acc1,acc0, qword [aPtr+sizeof(qword)*0] mulx acc2,t2, qword [aPtr+sizeof(qword)*1] add acc1,t2 mulx acc3,t2, qword [aPtr+sizeof(qword)*2] adc acc2,t2 mulx acc4,t2, qword [aPtr+sizeof(qword)*3] adc acc3,t2 adc acc4,0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 p224r1_prod_redstep acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rdx, qword [bPtr+sizeof(qword)*1] xor t0, t0 mulx t3, t2, qword [aPtr+sizeof(qword)*0] adcx acc1, t2 adox acc2, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*1] adcx acc2, t2 adox acc3, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*2] adcx acc3, t2 adox acc4, t3 mulx acc5, t2, qword [aPtr+sizeof(qword)*3] adcx acc4, t2 adox acc5, t0 adc acc5, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 p224r1_prod_redstep acc5,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rdx, qword [bPtr+sizeof(qword)*2] xor t0, t0 mulx t3, t2, qword [aPtr+sizeof(qword)*0] adcx acc2, t2 adox acc3, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*1] adcx acc3, t2 adox acc4, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*2] adcx acc4, t2 adox acc5, t3 mulx acc6, t2, qword [aPtr+sizeof(qword)*3] adcx acc5, t2 adox acc6, t0 adc acc6, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 p224r1_prod_redstep acc6,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[3] mov rdx, qword [bPtr+sizeof(qword)*3] xor t0, t0 mulx t3, t2, qword [aPtr+sizeof(qword)*0] adcx acc3, t2 adox acc4, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*1] adcx acc4, t2 adox acc5, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*2] adcx acc5, t2 adox acc6, t3 mulx acc7, t2, qword [aPtr+sizeof(qword)*3] adcx acc6, t2 adox acc7, t0 adc acc7, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 3 (final) p224r1_prod_redstep acc7,acc6,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov acc0, acc4 ;; copy reducted result mov acc1, acc5 mov acc2, acc6 mov acc3, acc7 sub acc4, t0 ;; test %if it exceeds prime value sbb acc5, t1 sbb acc6, t2 sbb acc7, t3 cmovc acc4, acc0 cmovc acc5, acc1 cmovc acc6, acc2 cmovc acc7, acc3 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 ret %endif IPPASM p224r1_mul_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call p224r1_mmull REST_XMM REST_GPR ret ENDFUNC p224r1_mul_montl %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM p224r1_mul_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call p224r1_mmulx REST_XMM REST_GPR ret ENDFUNC p224r1_mul_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_to_mont(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_to_mont,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 lea rbx, [rel LRR] call p224r1_mmull REST_XMM REST_GPR ret ENDFUNC p224r1_to_mont ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_sqr_montl(uint64_t res[4], uint64_t a[4]); ; void p224r1_sqr_montx(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_sqr_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 mov rbx, rsi call p224r1_mmull REST_XMM REST_GPR ret ENDFUNC p224r1_sqr_montl %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM p224r1_sqr_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 mov rbx, rsi call p224r1_mmulx REST_XMM REST_GPR ret ENDFUNC p224r1_sqr_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_mont_back(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_mont_back,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rsi mov acc0, qword [rsi+sizeof(qword)*0] mov acc1, qword [rsi+sizeof(qword)*1] mov acc2, qword [rsi+sizeof(qword)*2] mov acc3, qword [rsi+sizeof(qword)*3] xor acc4, acc4 xor acc5, acc5 xor acc6, acc6 xor acc7, acc7 p224r1_prod_redstep acc4,acc3,acc2,acc1,acc0 p224r1_prod_redstep acc5,acc4,acc3,acc2,acc1 p224r1_prod_redstep acc6,acc5,acc4,acc3,acc2 p224r1_prod_redstep acc7,acc6,acc5,acc4,acc3 mov acc0, acc4 mov acc1, acc5 mov acc2, acc6 mov acc3, acc7 sub acc4, qword [rel Lpoly+sizeof(qword)*0] sbb acc5, qword [rel Lpoly+sizeof(qword)*1] sbb acc6, qword [rel Lpoly+sizeof(qword)*2] sbb acc7, qword [rel Lpoly+sizeof(qword)*3] cmovc acc4, acc0 cmovc acc5, acc1 cmovc acc6, acc2 cmovc acc7, acc3 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 REST_XMM REST_GPR ret ENDFUNC p224r1_mont_back %ifndef _DISABLE_ECP_224R1_HARDCODED_BP_TBL_ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p224r1_select_ap_w7(AF_POINT *val, const AF_POINT *in_t, int index); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p224r1_select_ap_w7,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 3 %xdefine val rdi %xdefine in_t rsi %xdefine idx edx %xdefine ONE xmm0 %xdefine INDEX xmm1 %xdefine Ra xmm2 %xdefine Rb xmm3 %xdefine Rc xmm4 %xdefine Rd xmm5 %xdefine M0 xmm8 %xdefine T0a xmm9 %xdefine T0b xmm10 %xdefine T0c xmm11 %xdefine T0d xmm12 %xdefine TMP0 xmm15 movdqa ONE, oword [rel LOne] pxor Ra, Ra pxor Rb, Rb pxor Rc, Rc pxor Rd, Rd movdqa M0, ONE movd INDEX, idx pshufd INDEX, INDEX, 0 ; Skip index = 0, is implicictly infty -> load with offset -1 mov rcx, dword 64 .select_loop_sse_w7: movdqa TMP0, M0 pcmpeqd TMP0, INDEX paddd M0, ONE movdqa T0a, oword [in_t+sizeof(oword)*0] movdqa T0b, oword [in_t+sizeof(oword)*1] movdqa T0c, oword [in_t+sizeof(oword)*2] movdqa T0d, oword [in_t+sizeof(oword)*3] add in_t, sizeof(oword)*4 pand T0a, TMP0 pand T0b, TMP0 pand T0c, TMP0 pand T0d, TMP0 por Ra, T0a por Rb, T0b por Rc, T0c por Rd, T0d dec rcx jnz .select_loop_sse_w7 movdqu oword [val+sizeof(oword)*0], Ra movdqu oword [val+sizeof(oword)*1], Rb movdqu oword [val+sizeof(oword)*2], Rc movdqu oword [val+sizeof(oword)*3], Rd REST_XMM REST_GPR ret ENDFUNC p224r1_select_ap_w7 %endif %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpp256funcs_montas.asm000066400000000000000000000407101470420105600277010ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; 256-bit modular arithmetic ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Ipp64u* gf256_add(Ipp64u res[4], Ipp64u a[4], Ipp64u b[4], Ipp64u poly[4]) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM gf256_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 4 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 r12 %xdefine t3 r13 %xdefine t4 r14 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] ; a[] = A mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] add a0, qword [rdx+sizeof(qword)*0] ; a[] = a[]+b[] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc a3, qword [rdx+sizeof(qword)*3] adc t4, 0 mov t0, a0 ; save result t[] = a[] mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rcx+sizeof(qword)*0] ; t[] = a[]+b[] -poly[] sbb t1, qword [rcx+sizeof(qword)*1] sbb t2, qword [rcx+sizeof(qword)*2] sbb t3, qword [rcx+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 ; A = a:t cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov rax, rdi ; return pointer to result REST_XMM REST_GPR ret ENDFUNC gf256_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Ipp64u* gf256_sub(Ipp64u res[4], Ipp64u a[4], Ipp64u b[4], Ipp64u poly[4]) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM gf256_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 4 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 r12 %xdefine t3 r13 %xdefine t4 r14 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] ; a[] = A mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] sub a0, qword [rdx+sizeof(qword)*0] ; a[] = a[]-b[] sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb a3, qword [rdx+sizeof(qword)*3] sbb t4, 0 mov t0, a0 ; save result t[] = a[] mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rcx+sizeof(qword)*0] ; t[] = a[]-b[] +poly[] adc t1, qword [rcx+sizeof(qword)*1] adc t2, qword [rcx+sizeof(qword)*2] adc t3, qword [rcx+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 ; A = a:t cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov rax, rdi ; return pointer to result REST_XMM REST_GPR ret ENDFUNC gf256_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Ipp64u* gf256_neg(Ipp64u res[4], Ipp64u a[4], Ipp64u poly[4]) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM gf256_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rcx %xdefine t2 r12 %xdefine t3 r13 %xdefine t4 r14 xor t4, t4 xor a0, a0 ; a[] = 0; xor a1, a1 xor a2, a2 xor a3, a3 sub a0, qword [rsi+sizeof(qword)*0] ; a[] = -a[] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb a3, qword [rsi+sizeof(qword)*3] sbb t4, 0 mov t0, a0 ; t[] = a[] mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rdx+sizeof(qword)*0] ; t[] = -a[] +poly[] adc t1, qword [rdx+sizeof(qword)*1] adc t2, qword [rdx+sizeof(qword)*2] adc t3, qword [rdx+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 ; A = a:t cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov rax, rdi ; return pointer to result REST_XMM REST_GPR ret ENDFUNC gf256_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Ipp64u* gf256_div2(Ipp64u res[4], Ipp64u a[4], Ipp64u poly[4]) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM gf256_div2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rcx %xdefine t2 r12 %xdefine t3 r13 %xdefine t4 r14 mov a0, qword [rsi+sizeof(qword)*0] ; a[] = A mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] xor t4, t4 xor rsi, rsi mov t0, a0 ; t[] = A mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rdx+sizeof(qword)*0] ; t[] += poly[] adc t1, qword [rdx+sizeof(qword)*1] adc t2, qword [rdx+sizeof(qword)*2] adc t3, qword [rdx+sizeof(qword)*3] adc t4, 0 test a0, 1 ; %if (A[0] & 1) cmovnz a0, t0 ; a[] = t[] cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 cmovnz rsi,t4 shrd a0, a1, 1 ; a[] /= 2 shrd a1, a2, 1 shrd a2, a3, 1 shrd a3, rsi,1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov rax, rdi ; return pointer to result REST_XMM REST_GPR ret ENDFUNC gf256_div2 ;; ;; GF256 multiplicative operations ;; %macro MUL_4x1 8.nolist %xdefine %%dm %1 %xdefine %%ACC4 %2 %xdefine %%ACC3 %3 %xdefine %%ACC2 %4 %xdefine %%ACC1 %5 %xdefine %%ACC0 %6 %xdefine %%aPtr %7 %xdefine %%B %8 mov rax, qword [%%aPtr+sizeof(qword)*0] mul %%B mov %%ACC0,rax mov %%ACC1,rdx imul %%dm, %%ACC0 mov rax, qword [%%aPtr+sizeof(qword)*1] mul %%B add %%ACC1,rax adc rdx, 0 mov %%ACC2,rdx mov rax, qword [%%aPtr+sizeof(qword)*2] mul %%B add %%ACC2,rax adc rdx, 0 mov %%ACC3,rdx mov rax, qword [%%aPtr+sizeof(qword)*3] mul %%B add %%ACC3,rax adc rdx, 0 mov %%ACC4,rdx %endmacro %macro MLA_4x1 10.nolist %xdefine %%dm %1 %xdefine %%ACC5 %2 %xdefine %%ACC4 %3 %xdefine %%ACC3 %4 %xdefine %%ACC2 %5 %xdefine %%ACC1 %6 %xdefine %%ACC0 %7 %xdefine %%aPtr %8 %xdefine %%B %9 %xdefine %%TMP %10 mov rax, qword [%%aPtr+sizeof(qword)*0] mul %%B add %%ACC0,rax adc rdx, 0 mov %%TMP, rdx imul %%dm, %%ACC0 mov rax, qword [%%aPtr+sizeof(qword)*1] mul %%B add %%ACC1,%%TMP adc rdx, 0 add %%ACC1,rax adc rdx, 0 mov %%TMP, rdx mov rax, qword [%%aPtr+sizeof(qword)*2] mul %%B add %%ACC2,%%TMP adc rdx, 0 add %%ACC2,rax adc rdx, 0 mov %%TMP, rdx mov rax, qword [%%aPtr+sizeof(qword)*3] mul %%B add %%ACC3,%%TMP adc rdx, 0 add %%ACC3,rax adc %%ACC4,rdx adc %%ACC5,0 %endmacro %macro MRED_4x1 8.nolist %xdefine %%ACC5 %1 %xdefine %%ACC4 %2 %xdefine %%ACC3 %3 %xdefine %%ACC2 %4 %xdefine %%ACC1 %5 %xdefine %%ACC0 %6 %xdefine %%mPtr %7 %xdefine %%dm %8 mov rax, qword [%%mPtr+sizeof(qword)*0] mul %%dm add %%ACC0,rax adc rdx, 0 mov %%ACC0,rdx mov rax, qword [%%mPtr+sizeof(qword)*1] mul %%dm add %%ACC1,%%ACC0 adc rdx, 0 add %%ACC1,rax adc rdx, 0 mov %%ACC0,rdx mov rax, qword [%%mPtr+sizeof(qword)*2] mul %%dm add %%ACC2,%%ACC0 adc rdx, 0 add %%ACC2,rax adc rdx, 0 mov %%ACC0,rdx mov rax, qword [%%mPtr+sizeof(qword)*3] mul %%dm add %%ACC3,%%ACC0 adc rdx, 0 add %%ACC3,rax adc rdx, 0 add %%ACC4,rdx adc %%ACC5,0 xor %%ACC0,%%ACC0 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Ipp64u* gf256_mulm(Ipp64u res[4], Ipp64u a[4], Ipp64u b[4], Ipp64u poly[4], Ipp64u m0) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM gf256_mulm,PUBLIC %assign LOCAL_FRAME 2*sizeof(qword) USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14,r15 USES_XMM COMP_ABI 5 ;; stack structure: %assign res 0 %assign m0 res+sizeof(qword) mov qword [rsp+res], rdi ; save result mov rbx, rdx ; rbx = bPtr mov rdi, rcx ; rcx = mPtr mov qword [rsp+m0], r8 ; save m0 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; P = A[] * b[0] mov r14, qword [rbx+sizeof(qword)*0] mov r15, qword [rsp+m0] MUL_4x1 r15, acc4,acc3,acc2,acc1,acc0, rsi, r14 xor acc5,acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step MRED_4x1 acc5,acc4,acc3,acc2,acc1,acc0, rdi, r15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; P+= A[] * b[1] mov r14, qword [rbx+sizeof(qword)*1] mov r15, qword [rsp+m0] MLA_4x1 r15, acc0,acc5,acc4,acc3,acc2,acc1, rsi, r14, rcx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step MRED_4x1 acc0,acc5,acc4,acc3,acc2,acc1, rdi, r15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; P+= A[] * b[2] mov r14, qword [rbx+sizeof(qword)*2] mov r15, qword [rsp+m0] MLA_4x1 r15, acc1,acc0,acc5,acc4,acc3,acc2, rsi, r14, rcx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step MRED_4x1 acc1,acc0,acc5,acc4,acc3,acc2, rdi, r15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; P+= A[] * b[3] mov r14, qword [rbx+sizeof(qword)*3] mov r15, qword [rsp+m0] MLA_4x1 r15, acc2,acc1,acc0,acc5,acc4,acc3, rsi, r14, rcx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step MRED_4x1 acc2,acc1,acc0,acc5,acc4,acc3, rdi, r15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; final reduction mov rsi, qword [rsp+res] ;; restore result address mov rax, acc4 ;; copy temporary result mov rbx, acc5 mov rcx, acc0 mov rdx, acc1 sub rax, qword [rdi+sizeof(qword)*0] ;; subtract modulus sbb rbx, qword [rdi+sizeof(qword)*1] sbb rcx, qword [rdi+sizeof(qword)*2] sbb rdx, qword [rdi+sizeof(qword)*3] sbb acc2, 0 cmovnc acc4, rax cmovnc acc5, rbx cmovnc acc0, rcx cmovnc acc1, rdx mov qword [rsi+sizeof(qword)*0], acc4 mov qword [rsi+sizeof(qword)*1], acc5 mov qword [rsi+sizeof(qword)*2], acc0 mov qword [rsi+sizeof(qword)*3], acc1 mov rax, rsi ; return pointer to result REST_XMM REST_GPR ret ENDFUNC gf256_mulm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Ipp64u* gf256_sqrm(Ipp64u res[4], Ipp64u a[4], Ipp64u poly[4], Ipp64u m0) ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM gf256_sqrm,PUBLIC %assign LOCAL_FRAME 2*sizeof(qword) USES_GPR rsi,rdi,rbx,rbp,r12,r13,r14,r15 USES_XMM COMP_ABI 4 ;; stack structure: %assign res 0 %assign m0 res+sizeof(qword) mov qword [rsp+res], rdi ; save result mov rdi, rdx ; rdi = mPtr mov qword [rsp+m0], rcx ; save m0 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; diagonal mov t2, qword [rsi+sizeof(qword)*0] mov rax,qword [rsi+sizeof(qword)*1] mul t2 mov acc1, rax mov acc2, rdx mov rax,qword [rsi+sizeof(qword)*2] mul t2 add acc2, rax adc rdx, 0 mov acc3, rdx mov rax,qword [rsi+sizeof(qword)*3] mul t2 add acc3, rax adc rdx, 0 mov acc4, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [rsi+sizeof(qword)*1] mov rax,qword [rsi+sizeof(qword)*2] mul t2 add acc3, rax adc rdx, 0 mov t1, rdx mov rax,qword [rsi+sizeof(qword)*3] mul t2 add acc4, rax adc rdx, 0 add acc4, t1 adc rdx, 0 mov acc5, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [rsi+sizeof(qword)*2] mov rax,qword [rsi+sizeof(qword)*3] mul t2 add acc5, rax adc rdx, 0 mov acc6, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; doubling xor acc7, acc7 shld acc7, acc6, 1 shld acc6, acc5, 1 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; add sruares mov rax,qword [rsi+sizeof(qword)*0] mul rax mov acc0, rax add acc1, rdx adc acc2, 0 mov rax,qword [rsi+sizeof(qword)*1] mul rax add acc2, rax adc acc3, rdx adc acc4, 0 mov rax,qword [rsi+sizeof(qword)*2] mul rax add acc4, rax adc acc5, rdx adc acc6, 0 mov rax,qword [rsi+sizeof(qword)*3] mul rax add acc6, rax adc acc7, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction mov rcx, qword [rsp+m0] ; restore m0 imul rcx, acc0 MRED_4x1 acc5,acc4,acc3,acc2,acc1,acc0, rdi, rcx mov rcx, qword [rsp+m0] ; restore m0 imul rcx, acc1 MRED_4x1 acc6,acc5,acc4,acc3,acc2,acc1, rdi, rcx mov rcx, qword [rsp+m0] ; restore m0 imul rcx, acc2 MRED_4x1 acc7,acc6,acc5,acc4,acc3,acc2, rdi, rcx mov rcx, qword [rsp+m0] ; restore m0 imul rcx, acc3 MRED_4x1 acc0,acc7,acc6,acc5,acc4,acc3, rdi, rcx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; final reduction mov rsi, qword [rsp+res] ;; restore result address mov rax, acc4 ;; copy temporary result mov rbx, acc5 mov rcx, acc6 mov rdx, acc7 sub rax, qword [rdi+sizeof(qword)*0] ;; subtract modulus sbb rbx, qword [rdi+sizeof(qword)*1] sbb rcx, qword [rdi+sizeof(qword)*2] sbb rdx, qword [rdi+sizeof(qword)*3] sbb acc0, 0 cmovnc acc4, rax cmovnc acc5, rbx cmovnc acc6, rcx cmovnc acc7, rdx mov qword [rsi+sizeof(qword)*0], acc4 mov qword [rsi+sizeof(qword)*1], acc5 mov qword [rsi+sizeof(qword)*2], acc6 mov qword [rsi+sizeof(qword)*3], acc7 mov rax, rsi ; return pointer to result REST_XMM REST_GPR ret ENDFUNC gf256_sqrm %endif ;; _IPP32E_M7 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpp256r1funcs_montas.asm000066400000000000000000000735671470420105600301640ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; secp p256r1 specific implementation ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;; The p256r1 polynomial Lpoly DQ 0FFFFFFFFFFFFFFFFh,000000000FFFFFFFFh,00000000000000000h,0FFFFFFFF00000001h ;; 2^512 mod P precomputed for p256r1 polynomial LRR DQ 00000000000000003h,0fffffffbffffffffh,0fffffffffffffffeh,000000004fffffffdh LOne DD 1,1,1,1,1,1,1,1 LTwo DD 2,2,2,2,2,2,2,2 LThree DD 3,3,3,3,3,3,3,3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_mul_by_2(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_mul_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] shld t4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p256r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_div_by_2(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_div_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] xor t4, t4 xor r14, r14 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] adc t4, 0 test a0, 1 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 cmovnz r14,t4 shrd a0, a1, 1 shrd a1, a2, 1 shrd a2, a3, 1 shrd a3, r14,1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p256r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_mul_by_3(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_mul_by_3,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] shld t4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 xor t4, t4 add a0, qword [rsi+sizeof(qword)*0] adc a1, qword [rsi+sizeof(qword)*1] adc a2, qword [rsi+sizeof(qword)*2] adc a3, qword [rsi+sizeof(qword)*3] adc t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p256r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_add(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] add a0, qword [rdx+sizeof(qword)*0] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc a3, qword [rdx+sizeof(qword)*3] adc t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p256r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_sub(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] sub a0, qword [rdx+sizeof(qword)*0] sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb a3, qword [rdx+sizeof(qword)*3] sbb t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p256r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_neg(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 xor a0, a0 xor a1, a1 xor a2, a2 xor a3, a3 sub a0, qword [rsi+sizeof(qword)*0] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb a3, qword [rsi+sizeof(qword)*3] sbb t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC p256r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_mul_montl(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; on entry p5=0 ; on exit p0=0 ; %macro p256r1_mul_redstep 6.nolist %xdefine %%p5 %1 %xdefine %%p4 %2 %xdefine %%p3 %3 %xdefine %%p2 %4 %xdefine %%p1 %5 %xdefine %%p0 %6 mov t0, %%p0 shl t0, 32 mov t1, %%p0 shr t1, 32 ;; (t1:t0) = p0*2^32 mov t2, %%p0 mov t3, %%p0 xor %%p0, %%p0 sub t2, t0 sbb t3, t1 ;; (t3:t2) = (p0*2^64+p0) - p0*2^32 add %%p1, t0 ;; (p2:p1) += (t1:t0) adc %%p2, t1 adc %%p3, t2 ;; (p4:p3) += (t3:t2) adc %%p4, t3 adc %%p5, 0 ;; extension = {0/1} %endmacro align IPP_ALIGN_FACTOR p256r1_mmull: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rbp %xdefine t4 rbx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc5, acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*0] mov acc0, rax mov acc1, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*1] add acc1, rax adc rdx, 0 mov acc2, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*2] add acc2, rax adc rdx, 0 mov acc3, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*3] add acc3, rax adc rdx, 0 mov acc4, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 p256r1_mul_redstep acc5,acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*0] add acc1, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*1] add acc2, rcx adc rdx, 0 add acc2, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*2] add acc3, rcx adc rdx, 0 add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*3] add acc4, rcx adc rdx, 0 add acc4, rax adc acc5, rdx adc acc0, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 p256r1_mul_redstep acc0,acc5,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*0] add acc2, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*1] add acc3, rcx adc rdx, 0 add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*2] add acc4, rcx adc rdx, 0 add acc4, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*3] add acc5, rcx adc rdx, 0 add acc5, rax adc acc0, rdx adc acc1, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 p256r1_mul_redstep acc1,acc0,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[3] mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*0] add acc3, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*1] add acc4, rcx adc rdx, 0 add acc4, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*2] add acc5, rcx adc rdx, 0 add acc5, rax adc rdx, 0 mov rcx, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*3] add acc0, rcx adc rdx, 0 add acc0, rax adc acc1, rdx adc acc2, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 3 (final) p256r1_mul_redstep acc2,acc1,acc0,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 ;; copy reducted result mov acc3, acc5 mov acc6, acc0 mov acc7, acc1 sub t4, t0 ;; test %if it exceeds prime value sbb acc3, t1 sbb acc6, t2 sbb acc7, t3 sbb acc2, 0 cmovnc acc4, t4 cmovnc acc5, acc3 cmovnc acc0, acc6 cmovnc acc1, acc7 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc0 mov qword [rdi+sizeof(qword)*3], acc1 ret align IPP_ALIGN_FACTOR IPPASM p256r1_mul_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call p256r1_mmull REST_XMM REST_GPR ret ENDFUNC p256r1_mul_montl ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_to_mont(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_to_mont,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 lea rbx, [rel LRR] call p256r1_mmull REST_XMM REST_GPR ret ENDFUNC p256r1_to_mont ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_mul_montx(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR p256r1_mmulx: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rbp %xdefine t4 rbx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc5, acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] xor rdx, rdx mov rdx, qword [bPtr+sizeof(qword)*0] mulx acc1,acc0, qword [aPtr+sizeof(qword)*0] mulx acc2,t2, qword [aPtr+sizeof(qword)*1] add acc1,t2 mulx acc3,t2, qword [aPtr+sizeof(qword)*2] adc acc2,t2 mulx acc4,t2, qword [aPtr+sizeof(qword)*3] adc acc3,t2 adc acc4,0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 p256r1_mul_redstep acc5,acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rdx, qword [bPtr+sizeof(qword)*1] mulx t3, t2, qword [aPtr+sizeof(qword)*0] adcx acc1, t2 adox acc2, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*1] adcx acc2, t2 adox acc3, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*2] adcx acc3, t2 adox acc4, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*3] adcx acc4, t2 adox acc5, t3 adcx acc5, acc0 adox acc0, acc0 adc acc0, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 p256r1_mul_redstep acc0,acc5,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rdx, qword [bPtr+sizeof(qword)*2] mulx t3, t2, qword [aPtr+sizeof(qword)*0] adcx acc2, t2 adox acc3, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*1] adcx acc3, t2 adox acc4, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*2] adcx acc4, t2 adox acc5, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*3] adcx acc5, t2 adox acc0, t3 adcx acc0, acc1 adox acc1, acc1 adc acc1, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 p256r1_mul_redstep acc1,acc0,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[3] mov rdx, qword [bPtr+sizeof(qword)*3] mulx t3, t2, qword [aPtr+sizeof(qword)*0] adcx acc3, t2 adox acc4, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*1] adcx acc4, t2 adox acc5, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*2] adcx acc5, t2 adox acc0, t3 mulx t3, t2, qword [aPtr+sizeof(qword)*3] adcx acc0, t2 adox acc1, t3 adcx acc1, acc2 adox acc2, acc2 adc acc2, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 3 (final) p256r1_mul_redstep acc2,acc1,acc0,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 ;; copy reducted result mov acc3, acc5 mov acc6, acc0 mov acc7, acc1 sub t4, t0 ;; test %if it exceeds prime value sbb acc3, t1 sbb acc6, t2 sbb acc7, t3 sbb acc2, 0 cmovnc acc4, t4 cmovnc acc5, acc3 cmovnc acc0, acc6 cmovnc acc1, acc7 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc0 mov qword [rdi+sizeof(qword)*3], acc1 ret %endif %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM p256r1_mul_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call p256r1_mmulx REST_XMM REST_GPR ret ENDFUNC p256r1_mul_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_sqr_montl(uint64_t res[4], uint64_t a[4]); ; void p256r1_sqr_montx(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; on entry e = expansion (previous step) ; on exit p0= expansion (next step) ; %macro p256r1_prod_redstep 6.nolist %xdefine %%e %1 %xdefine %%p4 %2 %xdefine %%p3 %3 %xdefine %%p2 %4 %xdefine %%p1 %5 %xdefine %%p0 %6 mov t0, %%p0 shl t0, 32 mov t1, %%p0 shr t1, 32 ;; (t1:t0) = p0*2^32 mov t2, %%p0 mov t3, %%p0 xor %%p0, %%p0 sub t2, t0 sbb t3, t1 ;; (t3:t2) = (p0*2^64+p0) - p0*2^32 add %%p1, t0 ;; (p2:p1) += (t1:t0) adc %%p2, t1 adc %%p3, t2 ;; (p4:p3) += (t3:t2) adc %%p4, t3 adc %%p0, 0 ;; extension = {0/1} %ifnempty %%e add %%p4, %%e adc %%p0, 0 %endif %endmacro align IPP_ALIGN_FACTOR IPPASM p256r1_sqr_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*0] mov rax,qword [aPtr+sizeof(qword)*1] mul t2 mov acc1, rax mov acc2, rdx mov rax,qword [aPtr+sizeof(qword)*2] mul t2 add acc2, rax adc rdx, 0 mov acc3, rdx mov rax,qword [aPtr+sizeof(qword)*3] mul t2 add acc3, rax adc rdx, 0 mov acc4, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*1] mov rax,qword [aPtr+sizeof(qword)*2] mul t2 add acc3, rax adc rdx, 0 mov t1, rdx mov rax,qword [aPtr+sizeof(qword)*3] mul t2 add acc4, rax adc rdx, 0 add acc4, t1 adc rdx, 0 mov acc5, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*2] mov rax,qword [aPtr+sizeof(qword)*3] mul t2 add acc5, rax adc rdx, 0 mov acc6, rdx xor acc7, acc7 shld acc7, acc6, 1 shld acc6, acc5, 1 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 mov rax,qword [aPtr+sizeof(qword)*0] mul rax mov acc0, rax add acc1, rdx adc acc2, 0 mov rax,qword [aPtr+sizeof(qword)*1] mul rax add acc2, rax adc acc3, rdx adc acc4, 0 mov rax,qword [aPtr+sizeof(qword)*2] mul rax add acc4, rax adc acc5, rdx adc acc6, 0 mov rax,qword [aPtr+sizeof(qword)*3] mul rax add acc6, rax adc acc7, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; p256r1_prod_redstep ,acc4,acc3,acc2,acc1,acc0 p256r1_prod_redstep acc0,acc5,acc4,acc3,acc2,acc1 p256r1_prod_redstep acc1,acc6,acc5,acc4,acc3,acc2 p256r1_prod_redstep acc2,acc7,acc6,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 mov acc0, acc5 mov acc1, acc6 mov acc2, acc7 sub t4, t0 sbb acc0, t1 sbb acc1, t2 sbb acc2, t3 sbb acc3, 0 cmovnc acc4, t4 cmovnc acc5, acc0 cmovnc acc6, acc1 cmovnc acc7, acc2 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 REST_XMM REST_GPR ret ENDFUNC p256r1_sqr_montl %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM p256r1_sqr_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*0] mulx acc2, acc1, qword [aPtr+sizeof(qword)*1] mulx acc3, t0, qword [aPtr+sizeof(qword)*2] add acc2, t0 mulx acc4, t0, qword [aPtr+sizeof(qword)*3] adc acc3, t0 adc acc4, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*1] xor acc5, acc5 mulx t1, t0, qword [aPtr+sizeof(qword)*2] adcx acc3, t0 adox acc4, t1 mulx t1, t0, qword [aPtr+sizeof(qword)*3] adcx acc4, t0 adox acc5, t1 adc acc5, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*2] mulx acc6, t0, qword [aPtr+sizeof(qword)*3] add acc5, t0 adc acc6, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; xor acc7, acc7 shld acc7, acc6, 1 shld acc6, acc5, 1 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 xor acc0, acc0 mov rdx, qword [aPtr+sizeof(qword)*0] mulx t1, acc0, rdx adcx acc1, t1 mov rdx, qword [aPtr+sizeof(qword)*1] mulx t1, t0, rdx adcx acc2, t0 adcx acc3, t1 mov rdx, qword [aPtr+sizeof(qword)*2] mulx t1, t0, rdx adcx acc4, t0 adcx acc5, t1 mov rdx, qword [aPtr+sizeof(qword)*3] mulx t1, t0, rdx adcx acc6, t0 adcx acc7, t1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; p256r1_prod_redstep ,acc4,acc3,acc2,acc1,acc0 p256r1_prod_redstep acc0,acc5,acc4,acc3,acc2,acc1 p256r1_prod_redstep acc1,acc6,acc5,acc4,acc3,acc2 p256r1_prod_redstep acc2,acc7,acc6,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 mov acc0, acc5 mov acc1, acc6 mov acc2, acc7 sub t4, t0 sbb acc0, t1 sbb acc1, t2 sbb acc2, t3 sbb acc3, 0 cmovnc acc4, t4 cmovnc acc5, acc0 cmovnc acc6, acc1 cmovnc acc7, acc2 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 REST_XMM REST_GPR ret ENDFUNC p256r1_sqr_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_mont_back(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_mont_back,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 rsi mov acc2, qword [rsi+sizeof(qword)*0] mov acc3, qword [rsi+sizeof(qword)*1] mov acc4, qword [rsi+sizeof(qword)*2] mov acc5, qword [rsi+sizeof(qword)*3] xor acc0, acc0 xor acc1, acc1 p256r1_mul_redstep acc1,acc0,acc5,acc4,acc3,acc2 p256r1_mul_redstep acc2,acc1,acc0,acc5,acc4,acc3 p256r1_mul_redstep acc3,acc2,acc1,acc0,acc5,acc4 p256r1_mul_redstep acc4,acc3,acc2,acc1,acc0,acc5 mov t0, acc0 mov t1, acc1 mov t2, acc2 mov t3, acc3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb acc4, 0 cmovnc acc0, t0 cmovnc acc1, t1 cmovnc acc2, t2 cmovnc acc3, t3 mov qword [rdi+sizeof(qword)*0], acc0 mov qword [rdi+sizeof(qword)*1], acc1 mov qword [rdi+sizeof(qword)*2], acc2 mov qword [rdi+sizeof(qword)*3], acc3 REST_XMM REST_GPR ret ENDFUNC p256r1_mont_back ;;%if _IPP32E < _IPP32E_L9 %ifndef _DISABLE_ECP_256R1_HARDCODED_BP_TBL_ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p256r1_select_ap_w7(AF_POINT *val, const AF_POINT *in_t, int index); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p256r1_select_ap_w7,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 3 %xdefine val rdi %xdefine in_t rsi %xdefine idx edx %xdefine ONE xmm0 %xdefine INDEX xmm1 %xdefine Ra xmm2 %xdefine Rb xmm3 %xdefine Rc xmm4 %xdefine Rd xmm5 %xdefine M0 xmm8 %xdefine T0a xmm9 %xdefine T0b xmm10 %xdefine T0c xmm11 %xdefine T0d xmm12 %xdefine TMP0 xmm15 movdqa ONE, oword [rel LOne] pxor Ra, Ra pxor Rb, Rb pxor Rc, Rc pxor Rd, Rd movdqa M0, ONE movd INDEX, idx pshufd INDEX, INDEX, 0 ; Skip index = 0, is implicictly infty -> load with offset -1 mov rcx, dword 64 .select_loop_sse_w7: movdqa TMP0, M0 pcmpeqd TMP0, INDEX paddd M0, ONE movdqa T0a, oword [in_t+sizeof(oword)*0] movdqa T0b, oword [in_t+sizeof(oword)*1] movdqa T0c, oword [in_t+sizeof(oword)*2] movdqa T0d, oword [in_t+sizeof(oword)*3] add in_t, sizeof(oword)*4 pand T0a, TMP0 pand T0b, TMP0 pand T0c, TMP0 pand T0d, TMP0 por Ra, T0a por Rb, T0b por Rc, T0c por Rd, T0d dec rcx jnz .select_loop_sse_w7 movdqu oword [val+sizeof(oword)*0], Ra movdqu oword [val+sizeof(oword)*1], Rb movdqu oword [val+sizeof(oword)*2], Rc movdqu oword [val+sizeof(oword)*3], Rd REST_XMM REST_GPR ret ENDFUNC p256r1_select_ap_w7 %endif ;;%endif ;; _IPP32E < _IPP32E_L9 %endif ;; _IPP32E_M7 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpp384r1funcs_montas.asm000066400000000000000000000564511470420105600301570ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; secp p384r1 specific implementation ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;; The p384r1 polynomial Lpoly DQ 000000000ffffffffh,0ffffffff00000000h,0fffffffffffffffeh DQ 0ffffffffffffffffh,0ffffffffffffffffh,0ffffffffffffffffh ;; 2^(2*384) mod P precomputed for p384r1 polynomial ;LRR DQ 0fffffffe00000001h,00000000200000000h,0fffffffe00000000h ; DQ 00000000200000000h,00000000000000001h,00000000000000000h LOne DD 1,1,1,1,1,1,1,1 LTwo DD 2,2,2,2,2,2,2,2 LThree DD 3,3,3,3,3,3,3,3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p384r1_mul_by_2(uint64_t res[6], uint64_t a[6]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_mul_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine a0 rax %xdefine a1 rcx %xdefine a2 rdx %xdefine a3 r8 %xdefine a4 r9 %xdefine a5 r10 %xdefine ex r11 %xdefine t r12 xor ex, ex mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] shld ex, a5, 1 shld a5, a4, 1 mov qword [rdi+sizeof(qword)*5], a5 shld a4, a3, 1 mov qword [rdi+sizeof(qword)*4], a4 shld a3, a2, 1 mov qword [rdi+sizeof(qword)*3], a3 shld a2, a1, 1 mov qword [rdi+sizeof(qword)*2], a2 shld a1, a0, 1 mov qword [rdi+sizeof(qword)*1], a1 shl a0, 1 mov qword [rdi+sizeof(qword)*0], a0 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb ex, 0 mov t, qword [rdi+sizeof(qword)*0] cmovnz a0, t mov t, qword [rdi+sizeof(qword)*1] cmovnz a1, t mov t, qword [rdi+sizeof(qword)*2] cmovnz a2, t mov t, qword [rdi+sizeof(qword)*3] cmovnz a3, t mov t, qword [rdi+sizeof(qword)*4] cmovnz a4, t mov t, qword [rdi+sizeof(qword)*5] cmovnz a5, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 REST_XMM REST_GPR ret ENDFUNC p384r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p384r1_div_by_2(uint64_t res[6], uint64_t a[6]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_div_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine a0 rax %xdefine a1 rcx %xdefine a2 rdx %xdefine a3 r8 %xdefine a4 r9 %xdefine a5 r10 %xdefine ex r11 %xdefine t r12 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] xor t, t xor ex, ex add a0, qword [rel Lpoly+sizeof(qword)*0] adc a1, qword [rel Lpoly+sizeof(qword)*1] adc a2, qword [rel Lpoly+sizeof(qword)*2] adc a3, qword [rel Lpoly+sizeof(qword)*3] adc a4, qword [rel Lpoly+sizeof(qword)*4] adc a5, qword [rel Lpoly+sizeof(qword)*5] adc ex, 0 test a0, 1 cmovnz ex, t mov t, qword [rsi+sizeof(qword)*0] cmovnz a0, t mov t, qword [rsi+sizeof(qword)*1] cmovnz a1, t mov t, qword [rsi+sizeof(qword)*2] cmovnz a2, t mov t, qword [rsi+sizeof(qword)*3] cmovnz a3, t mov t, qword [rsi+sizeof(qword)*4] cmovnz a4, t mov t, qword [rsi+sizeof(qword)*5] cmovnz a5, t shrd a0, a1, 1 shrd a1, a2, 1 shrd a2, a3, 1 shrd a3, a4, 1 shrd a4, a5, 1 shrd a5, ex, 1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 REST_XMM REST_GPR ret ENDFUNC p384r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p384r1_mul_by_3(uint64_t res[6], uint64_t a[6]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_mul_by_3,PUBLIC %assign LOCAL_FRAME sizeof(qword)*6 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 rax %xdefine a1 rcx %xdefine a2 rdx %xdefine a3 r8 %xdefine a4 r9 %xdefine a5 r10 %xdefine ex r11 %xdefine t r12 xor ex, ex mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] shld ex, a5, 1 shld a5, a4, 1 mov qword [rsp+sizeof(qword)*5], a5 shld a4, a3, 1 mov qword [rsp+sizeof(qword)*4], a4 shld a3, a2, 1 mov qword [rsp+sizeof(qword)*3], a3 shld a2, a1, 1 mov qword [rsp+sizeof(qword)*2], a2 shld a1, a0, 1 mov qword [rsp+sizeof(qword)*1], a1 shl a0, 1 mov qword [rsp+sizeof(qword)*0], a0 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb ex, 0 mov t, qword [rsp+0*sizeof(qword)] cmovb a0, t mov t, qword [rsp+1*sizeof(qword)] cmovb a1, t mov t, qword [rsp+2*sizeof(qword)] cmovb a2, t mov t, qword [rsp+3*sizeof(qword)] cmovb a3, t mov t, qword [rsp+4*sizeof(qword)] cmovb a4, t mov t, qword [rsp+5*sizeof(qword)] cmovb a5, t xor ex, ex add a0, qword [rsi+sizeof(qword)*0] mov qword [rsp+sizeof(qword)*0], a0 adc a1, qword [rsi+sizeof(qword)*1] mov qword [rsp+sizeof(qword)*1], a1 adc a2, qword [rsi+sizeof(qword)*2] mov qword [rsp+sizeof(qword)*2], a2 adc a3, qword [rsi+sizeof(qword)*3] mov qword [rsp+sizeof(qword)*3], a3 adc a4, qword [rsi+sizeof(qword)*4] mov qword [rsp+sizeof(qword)*4], a4 adc a5, qword [rsi+sizeof(qword)*5] mov qword [rsp+sizeof(qword)*5], a5 adc ex, 0 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb ex, 0 mov t, qword [rsp+sizeof(qword)*0] cmovb a0, t mov t, qword [rsp+sizeof(qword)*1] cmovb a1, t mov t, qword [rsp+sizeof(qword)*2] cmovb a2, t mov t, qword [rsp+sizeof(qword)*3] cmovb a3, t mov t, qword [rsp+sizeof(qword)*4] cmovb a4, t mov t, qword [rsp+sizeof(qword)*5] cmovb a5, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 REST_XMM REST_GPR ret ENDFUNC p384r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p384r1_add(uint64_t res[6], uint64_t a[6], uint64_t b[6]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12 USES_XMM COMP_ABI 3 %xdefine a0 rax %xdefine a1 rcx %xdefine a2 rbx %xdefine a3 r8 %xdefine a4 r9 %xdefine a5 r10 %xdefine ex r11 %xdefine t r12 xor ex, ex mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] add a0, qword [rdx+sizeof(qword)*0] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc a3, qword [rdx+sizeof(qword)*3] adc a4, qword [rdx+sizeof(qword)*4] adc a5, qword [rdx+sizeof(qword)*5] adc ex, 0 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb ex, 0 mov t, qword [rdi+sizeof(qword)*0] cmovb a0, t mov t, qword [rdi+sizeof(qword)*1] cmovb a1, t mov t, qword [rdi+sizeof(qword)*2] cmovb a2, t mov t, qword [rdi+sizeof(qword)*3] cmovb a3, t mov t, qword [rdi+sizeof(qword)*4] cmovb a4, t mov t, qword [rdi+sizeof(qword)*5] cmovb a5, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 REST_XMM REST_GPR ret ENDFUNC p384r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p384r1_sub(uint64_t res[6], uint64_t a[6], uint64_t b[6]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12 USES_XMM COMP_ABI 3 %xdefine a0 rax %xdefine a1 rcx %xdefine a2 rbx %xdefine a3 r8 %xdefine a4 r9 %xdefine a5 r10 %xdefine ex r11 %xdefine t r12 xor ex, ex mov a0, qword [rsi+sizeof(qword)*0] ; a mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] sub a0, qword [rdx+sizeof(qword)*0] ; a-b sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb a3, qword [rdx+sizeof(qword)*3] sbb a4, qword [rdx+sizeof(qword)*4] sbb a5, qword [rdx+sizeof(qword)*5] sbb ex, 0 ; ex = a>=b? 0 : -1 mov qword [rdi+sizeof(qword)*0], a0 ; store (a-b) mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 add a0, qword [rel Lpoly+sizeof(qword)*0] ; (a-b) +poly adc a1, qword [rel Lpoly+sizeof(qword)*1] adc a2, qword [rel Lpoly+sizeof(qword)*2] adc a3, qword [rel Lpoly+sizeof(qword)*3] adc a4, qword [rel Lpoly+sizeof(qword)*4] adc a5, qword [rel Lpoly+sizeof(qword)*5] test ex, ex ; r = (ex)? ((a-b)+poly) : (a-b) mov t, qword [rdi+sizeof(qword)*0] cmovz a0, t mov t, qword [rdi+sizeof(qword)*1] cmovz a1, t mov t, qword [rdi+sizeof(qword)*2] cmovz a2, t mov t, qword [rdi+sizeof(qword)*3] cmovz a3, t mov t, qword [rdi+sizeof(qword)*4] cmovz a4, t mov t, qword [rdi+sizeof(qword)*5] cmovz a5, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 REST_XMM REST_GPR ret ENDFUNC p384r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p384r1_neg(uint64_t res[6], uint64_t a[6]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12 USES_XMM COMP_ABI 2 %xdefine a0 rax %xdefine a1 rcx %xdefine a2 rdx %xdefine a3 r8 %xdefine a4 r9 %xdefine a5 r10 %xdefine ex r11 %xdefine t r12 xor ex, ex xor a0, a0 xor a1, a1 xor a2, a2 xor a3, a3 xor a4, a4 xor a5, a5 sub a0, qword [rsi+sizeof(qword)*0] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb a3, qword [rsi+sizeof(qword)*3] sbb a4, qword [rsi+sizeof(qword)*4] sbb a5, qword [rsi+sizeof(qword)*5] sbb ex, 0 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 add a0, qword [rel Lpoly+sizeof(qword)*0] adc a1, qword [rel Lpoly+sizeof(qword)*1] adc a2, qword [rel Lpoly+sizeof(qword)*2] adc a3, qword [rel Lpoly+sizeof(qword)*3] adc a4, qword [rel Lpoly+sizeof(qword)*4] adc a5, qword [rel Lpoly+sizeof(qword)*5] test ex, ex mov t, qword [rdi+sizeof(qword)*0] cmovz a0, t mov t, qword [rdi+sizeof(qword)*1] cmovz a1, t mov t, qword [rdi+sizeof(qword)*2] cmovz a2, t mov t, qword [rdi+sizeof(qword)*3] cmovz a3, t mov t, qword [rdi+sizeof(qword)*4] cmovz a4, t mov t, qword [rdi+sizeof(qword)*5] cmovz a5, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 REST_XMM REST_GPR ret ENDFUNC p384r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; projective point selector ; ; void p384r1_mred(Ipp464u* res, Ipp64u product); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; mred_step does single Montgomery reduction step -- computes {a0:a1:a2:a3:a4:a5:a6} += u*M[] ; where u = a0*m0 = a0*(2^32+1) and ; M[] = (2^32-1) + (2^64-2^32)*2^64 + (2^64-2)*2^64*2 + (2^64-1)*2^64*3 + (2^64-1)*2^64*4 + (2^64-1)*2^64*5 ; ; u*M[] = u*(2^32-1) + u*(2^64-2^32)*2^64 + u*(2^64-2)*2^64*2 + u*(2^64-1)*2^64*3 + u*(2^64-1)*2^64*4 + u*(2^64-1)*2^64*5 ; = u*2^32 -u ; +u*2^128 -u*2^32*2^64 ; +u*2^192 -u*2^128 -u*2^128 ; +u*2^256 -u*2^192 ; +u*2^320 -u*2^256 ; +u*2^384 -u*2^320 ; ; = (u*2^32 -u) + u*2^384 ; -u*2^32*2^64 -u*2^128 ; ; = (u*2^32 -u) + u*B^5 ; -(u*2^32 +u*B)*B, where B=2^64 is the target radix ; ; so update of {a0:a1:a2:a3:a4:a5:a6} consisns of 2 steps: ; {a0:a1:a2:a3:a4:a5:a6} += {(u*2^32 -u):0:0:0:0:0:u} and ; {a0:a1:a2:a3:a4:a5:a6} -= {0:(u*2^32 +u*B):0:0:0:0:0} ; %macro mred_step 9.nolist %xdefine %%a6 %1 %xdefine %%a5 %2 %xdefine %%a4 %3 %xdefine %%a3 %4 %xdefine %%a2 %5 %xdefine %%a1 %6 %xdefine %%a0 %7 %xdefine %%t2 %8 %xdefine %%t1 %9 mov rax, %%a0 ;; u = (m0*a0) mod 2^64= ((2^32+1)*a0) mod 2^64 shl rax, 32 add rax, %%a0 mov %%t2, rax ;; (t2:t1) = u*2^32, store shr %%t2, (64-32) push %%t2 mov %%t1, rax shl %%t1, 32 push %%t1 sub %%t1, rax ;; {t2:t1} = (2^32 -1)*u sbb %%t2, 0 ;; {a0:a1:a2:a3:a4:a5:a6} += (u*2^32 -u) + u*2^64*6 add %%a0, %%t1 ;; {a0:a1} += (u*2^32 -u) mov %%t1, rdx ;; t1 = carry_inp mov rdx, 0 adc %%a1, %%t2 adc %%a2, 0 adc %%a3, 0 adc %%a4, 0 adc %%a5, 0 adc %%a6, rax ;; a6 += u + cf adc rdx, 0 ;; rdx = carry_out add %%a6, %%t1 ;; add input carry adc rdx, 0 ;; rdx = carry_out pop %%t1 ;; restore {t2:t1} = u*2^32 pop %%t2 add %%t2, rax ;; {t1:t2} = u*2^32 +u*2^64 mov rax,0 adc rax,0 ;; {a1:a2:a3:a4:a5:a6} -= (u*2^32 + u) sub %%a1, %%t1 sbb %%a2, %%t2 sbb %%a3, rax sbb %%a4, 0 sbb %%a5, 0 sbb %%a6, 0 sbb rdx, 0 ;; update carry_out %endmacro align IPP_ALIGN_FACTOR IPPASM p384r1_mred,PUBLIC USES_GPR rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 ;; rdi = result ;; rsi = product buffer xor rdx, rdx mov r8, qword [rsi] mov r9, qword [rsi+sizeof(qword)] mov r10, qword [rsi+sizeof(qword)*2] mov r11, qword [rsi+sizeof(qword)*3] mov r12, qword [rsi+sizeof(qword)*4] mov r13, qword [rsi+sizeof(qword)*5] mov r14, qword [rsi+sizeof(qword)*6] mred_step r14,r13,r12,r11,r10,r9,r8, r15,rcx ;mov qword [rdi+sizeof(qword)*0], r9 ;mov qword [rdi+sizeof(qword)*1], r10 ;mov qword [rdi+sizeof(qword)*2], r11 ;mov qword [rdi+sizeof(qword)*3], r12 ;mov qword [rdi+sizeof(qword)*4], r13 ;mov qword [rdi+sizeof(qword)*5], r14 mov r8, qword [rsi+sizeof(qword)*7] mred_step r8,r14,r13,r12,r11,r10,r9, r15,rcx ;mov qword [rdi+sizeof(qword)*0], r10 ;mov qword [rdi+sizeof(qword)*1], r11 ;mov qword [rdi+sizeof(qword)*2], r12 ;mov qword [rdi+sizeof(qword)*3], r13 ;mov qword [rdi+sizeof(qword)*4], r14 ;mov qword [rdi+sizeof(qword)*5], r8 mov r9, qword [rsi+sizeof(qword)*8] mred_step r9,r8,r14,r13,r12,r11,r10, r15,rcx ;mov qword [rdi+sizeof(qword)*0], r11 ;mov qword [rdi+sizeof(qword)*1], r12 ;mov qword [rdi+sizeof(qword)*2], r13 ;mov qword [rdi+sizeof(qword)*3], r14 ;mov qword [rdi+sizeof(qword)*4], r8 ;mov qword [rdi+sizeof(qword)*5], r9 mov r10, qword [rsi+sizeof(qword)*9] mred_step r10,r9,r8,r14,r13,r12,r11, r15,rcx ;mov qword [rdi+sizeof(qword)*0], r12 ;mov qword [rdi+sizeof(qword)*1], r13 ;mov qword [rdi+sizeof(qword)*2], r14 ;mov qword [rdi+sizeof(qword)*3], r8 ;mov qword [rdi+sizeof(qword)*4], r9 ;mov qword [rdi+sizeof(qword)*5], r10 mov r11, qword [rsi+sizeof(qword)*10] mred_step r11,r10,r9,r8,r14,r13,r12, r15,rcx ;mov qword [rdi+sizeof(qword)*0], r13 ;mov qword [rdi+sizeof(qword)*1], r14 ;mov qword [rdi+sizeof(qword)*2], r8 ;mov qword [rdi+sizeof(qword)*3], r9 ;mov qword [rdi+sizeof(qword)*4], r10 ;mov qword [rdi+sizeof(qword)*5], r11 mov r12, qword [rsi+sizeof(qword)*11] mred_step r12,r11,r10,r9,r8,r14,r13, r15,rcx ; {r12,r11,r10,r9,r8,r14} - result mov qword [rdi+sizeof(qword)*0], r14 mov qword [rdi+sizeof(qword)*1], r8 mov qword [rdi+sizeof(qword)*2], r9 mov qword [rdi+sizeof(qword)*3], r10 mov qword [rdi+sizeof(qword)*4], r11 mov qword [rdi+sizeof(qword)*5], r12 sub r14, qword [rel Lpoly+sizeof(qword)*0] sbb r8, qword [rel Lpoly+sizeof(qword)*1] sbb r9, qword [rel Lpoly+sizeof(qword)*2] sbb r10, qword [rel Lpoly+sizeof(qword)*3] sbb r11, qword [rel Lpoly+sizeof(qword)*4] sbb r12, qword [rel Lpoly+sizeof(qword)*5] sbb rdx, 0 mov rax, qword [rdi+sizeof(qword)*0] cmovnz r14, rax mov rax, qword [rdi+sizeof(qword)*1] cmovnz r8, rax mov rax, qword [rdi+sizeof(qword)*2] cmovnz r9, rax mov rax, qword [rdi+sizeof(qword)*3] cmovnz r10, rax mov rax, qword [rdi+sizeof(qword)*4] cmovnz r11, rax mov rax, qword [rdi+sizeof(qword)*5] cmovnz r12, rax mov qword [rdi+sizeof(qword)*0], r14 mov qword [rdi+sizeof(qword)*1], r8 mov qword [rdi+sizeof(qword)*2], r9 mov qword [rdi+sizeof(qword)*3], r10 mov qword [rdi+sizeof(qword)*4], r11 mov qword [rdi+sizeof(qword)*5], r12 REST_XMM REST_GPR ret ENDFUNC p384r1_mred %ifndef _DISABLE_ECP_384R1_HARDCODED_BP_TBL_ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; affine point selector ; ; void p384r1_select_ap_w5(AF_POINT *val, const AF_POINT *tbl, int idx); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p384r1_select_ap_w5,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14 COMP_ABI 3 %xdefine val rdi %xdefine in_t rsi %xdefine idx edx %xdefine Xa xmm0 %xdefine Xb xmm1 %xdefine Xc xmm2 %xdefine Ya xmm3 %xdefine Yb xmm4 %xdefine Yc xmm5 %xdefine TXa xmm6 %xdefine TXb xmm7 %xdefine TXc xmm8 %xdefine TYa xmm9 %xdefine TYb xmm10 %xdefine TYc xmm11 %xdefine REQ_IDX xmm12 %xdefine CUR_IDX xmm13 %xdefine MASKDATA xmm14 movdqa CUR_IDX, oword [rel LOne] movd REQ_IDX, idx pshufd REQ_IDX, REQ_IDX, 0 pxor Xa, Xa pxor Xb, Xb pxor Xc, Xc pxor Ya, Ya pxor Yb, Yb pxor Yc, Yc ; Skip index = 0, is implicictly infty -> load with offset -1 mov rcx, dword 16 .select_loop: movdqa MASKDATA, CUR_IDX ; MASK = CUR_IDX==REQ_IDX? 0xFF : 0x00 pcmpeqd MASKDATA, REQ_IDX ; paddd CUR_IDX, oword [rel LOne] movdqa TXa, oword [in_t+sizeof(oword)*0] movdqa TXb, oword [in_t+sizeof(oword)*1] movdqa TXc, oword [in_t+sizeof(oword)*2] movdqa TYa, oword [in_t+sizeof(oword)*3] movdqa TYb, oword [in_t+sizeof(oword)*4] movdqa TYc, oword [in_t+sizeof(oword)*5] add in_t, sizeof(oword)*6 pand TXa, MASKDATA pand TXb, MASKDATA pand TXc, MASKDATA pand TYa, MASKDATA pand TYb, MASKDATA pand TYc, MASKDATA por Xa, TXa por Xb, TXb por Xc, TXc por Ya, TYa por Yb, TYb por Yc, TYc dec rcx jnz .select_loop movdqu oword [val+sizeof(oword)*0], Xa movdqu oword [val+sizeof(oword)*1], Xb movdqu oword [val+sizeof(oword)*2], Xc movdqu oword [val+sizeof(oword)*3], Ya movdqu oword [val+sizeof(oword)*4], Yb movdqu oword [val+sizeof(oword)*5], Yc REST_XMM REST_GPR ret ENDFUNC p384r1_select_ap_w5 %endif %endif ;; _IPP32E_M7 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpp521r1funcs_montas.asm000066400000000000000000000703411470420105600301420ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; secp p521r1 specific implementation ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR LOne DD 1,1,1,1,1,1,1,1 LTwo DD 2,2,2,2,2,2,2,2 LThree DD 3,3,3,3,3,3,3,3 ;; The p521r1 polynomial Lpoly DQ 0ffffffffffffffffh,0ffffffffffffffffh,0ffffffffffffffffh DQ 0ffffffffffffffffh,0ffffffffffffffffh,0ffffffffffffffffh DQ 0ffffffffffffffffh,0ffffffffffffffffh,000000000000001ffh ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p521r1_mul_by_2(uint64_t res[9], uint64_t a[9]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_mul_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx %xdefine t rdx xor ex, ex mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] mov a6, qword [rsi+sizeof(qword)*6] mov a7, qword [rsi+sizeof(qword)*7] mov a8, qword [rsi+sizeof(qword)*8] shld ex, a8, 1 shld a8, a7, 1 shld a7, a6, 1 shld a6, a5, 1 shld a5, a4, 1 shld a4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov qword [rdi+sizeof(qword)*8], a8 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*0], a0 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb a6, qword [rel Lpoly+sizeof(qword)*6] sbb a7, qword [rel Lpoly+sizeof(qword)*7] sbb a8, qword [rel Lpoly+sizeof(qword)*8] sbb ex, 0 mov t, qword [rdi+sizeof(qword)*0] cmovnz a0, t mov t, qword [rdi+sizeof(qword)*1] cmovnz a1, t mov t, qword [rdi+sizeof(qword)*2] cmovnz a2, t mov t, qword [rdi+sizeof(qword)*3] cmovnz a3, t mov t, qword [rdi+sizeof(qword)*4] cmovnz a4, t mov t, qword [rdi+sizeof(qword)*5] cmovnz a5, t mov t, qword [rdi+sizeof(qword)*6] cmovnz a6, t mov t, qword [rdi+sizeof(qword)*7] cmovnz a7, t mov t, qword [rdi+sizeof(qword)*8] cmovnz a8, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 REST_XMM REST_GPR ret ENDFUNC p521r1_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p521r1_div_by_2(uint64_t res[9], uint64_t a[9]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_div_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx %xdefine t rdx mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] mov a6, qword [rsi+sizeof(qword)*6] mov a7, qword [rsi+sizeof(qword)*7] mov a8, qword [rsi+sizeof(qword)*8] xor t, t xor ex, ex add a0, qword [rel Lpoly+sizeof(qword)*0] adc a1, qword [rel Lpoly+sizeof(qword)*1] adc a2, qword [rel Lpoly+sizeof(qword)*2] adc a3, qword [rel Lpoly+sizeof(qword)*3] adc a4, qword [rel Lpoly+sizeof(qword)*4] adc a5, qword [rel Lpoly+sizeof(qword)*5] adc a6, qword [rel Lpoly+sizeof(qword)*6] adc a7, qword [rel Lpoly+sizeof(qword)*7] adc a8, qword [rel Lpoly+sizeof(qword)*8] adc ex, 0 test a0, 1 cmovnz ex, t mov t, qword [rsi+sizeof(qword)*0] cmovnz a0, t mov t, qword [rsi+sizeof(qword)*1] cmovnz a1, t mov t, qword [rsi+sizeof(qword)*2] cmovnz a2, t mov t, qword [rsi+sizeof(qword)*3] cmovnz a3, t mov t, qword [rsi+sizeof(qword)*4] cmovnz a4, t mov t, qword [rsi+sizeof(qword)*5] cmovnz a5, t mov t, qword [rsi+sizeof(qword)*6] cmovnz a6, t mov t, qword [rsi+sizeof(qword)*7] cmovnz a7, t mov t, qword [rsi+sizeof(qword)*8] cmovnz a8, t shrd a0, a1, 1 shrd a1, a2, 1 shrd a2, a3, 1 shrd a3, a4, 1 shrd a4, a5, 1 shrd a5, a6, 1 shrd a6, a7, 1 shrd a7, a8, 1 shrd a8, ex, 1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 REST_XMM REST_GPR ret ENDFUNC p521r1_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p521r1_mul_by_3(uint64_t res[9], uint64_t a[9]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_mul_by_3,PUBLIC %assign LOCAL_FRAME sizeof(qword)*9 USES_GPR rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx %xdefine t rdx mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] mov a6, qword [rsi+sizeof(qword)*6] mov a7, qword [rsi+sizeof(qword)*7] mov a8, qword [rsi+sizeof(qword)*8] xor ex, ex shld ex, a8, 1 shld a8, a7, 1 shld a7, a6, 1 shld a6, a5, 1 shld a5, a4, 1 shld a4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov qword [rsp+sizeof(qword)*8], a8 mov qword [rsp+sizeof(qword)*7], a7 mov qword [rsp+sizeof(qword)*6], a6 mov qword [rsp+sizeof(qword)*5], a5 mov qword [rsp+sizeof(qword)*4], a4 mov qword [rsp+sizeof(qword)*3], a3 mov qword [rsp+sizeof(qword)*2], a2 mov qword [rsp+sizeof(qword)*1], a1 mov qword [rsp+sizeof(qword)*0], a0 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb a6, qword [rel Lpoly+sizeof(qword)*6] sbb a7, qword [rel Lpoly+sizeof(qword)*7] sbb a8, qword [rel Lpoly+sizeof(qword)*8] sbb ex, 0 mov t, qword [rsp+sizeof(qword)*0] cmovb a0, t mov t, qword [rsp+sizeof(qword)*1] cmovb a1, t mov t, qword [rsp+sizeof(qword)*2] cmovb a2, t mov t, qword [rsp+sizeof(qword)*3] cmovb a3, t mov t, qword [rsp+sizeof(qword)*4] cmovb a4, t mov t, qword [rsp+sizeof(qword)*5] cmovb a5, t mov t, qword [rsp+sizeof(qword)*6] cmovb a6, t mov t, qword [rsp+sizeof(qword)*7] cmovb a7, t mov t, qword [rsp+sizeof(qword)*8] cmovb a8, t xor ex, ex add a0, qword [rsi+sizeof(qword)*0] adc a1, qword [rsi+sizeof(qword)*1] adc a2, qword [rsi+sizeof(qword)*2] adc a3, qword [rsi+sizeof(qword)*3] adc a4, qword [rsi+sizeof(qword)*4] adc a5, qword [rsi+sizeof(qword)*5] adc a6, qword [rsi+sizeof(qword)*6] adc a7, qword [rsi+sizeof(qword)*7] adc a8, qword [rsi+sizeof(qword)*8] adc ex, 0 mov qword [rsp+sizeof(qword)*0], a0 mov qword [rsp+sizeof(qword)*1], a1 mov qword [rsp+sizeof(qword)*2], a2 mov qword [rsp+sizeof(qword)*3], a3 mov qword [rsp+sizeof(qword)*4], a4 mov qword [rsp+sizeof(qword)*5], a5 mov qword [rsp+sizeof(qword)*6], a6 mov qword [rsp+sizeof(qword)*7], a7 mov qword [rsp+sizeof(qword)*8], a8 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb a6, qword [rel Lpoly+sizeof(qword)*6] sbb a7, qword [rel Lpoly+sizeof(qword)*7] sbb a8, qword [rel Lpoly+sizeof(qword)*8] sbb ex, 0 mov t, qword [rsp+sizeof(qword)*0] cmovb a0, t mov t, qword [rsp+sizeof(qword)*1] cmovb a1, t mov t, qword [rsp+sizeof(qword)*2] cmovb a2, t mov t, qword [rsp+sizeof(qword)*3] cmovb a3, t mov t, qword [rsp+sizeof(qword)*4] cmovb a4, t mov t, qword [rsp+sizeof(qword)*5] cmovb a5, t mov t, qword [rsp+sizeof(qword)*6] cmovb a6, t mov t, qword [rsp+sizeof(qword)*7] cmovb a7, t mov t, qword [rsp+sizeof(qword)*8] cmovb a8, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 REST_XMM REST_GPR ret ENDFUNC p521r1_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p521r1_add(uint64_t res[9], uint64_t a[9], uint64_t b[9]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx %xdefine t rdx mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] mov a6, qword [rsi+sizeof(qword)*6] mov a7, qword [rsi+sizeof(qword)*7] mov a8, qword [rsi+sizeof(qword)*8] xor ex, ex add a0, qword [rdx+sizeof(qword)*0] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc a3, qword [rdx+sizeof(qword)*3] adc a4, qword [rdx+sizeof(qword)*4] adc a5, qword [rdx+sizeof(qword)*5] adc a6, qword [rdx+sizeof(qword)*6] adc a7, qword [rdx+sizeof(qword)*7] adc a8, qword [rdx+sizeof(qword)*8] adc ex, 0 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 sub a0, qword [rel Lpoly+sizeof(qword)*0] sbb a1, qword [rel Lpoly+sizeof(qword)*1] sbb a2, qword [rel Lpoly+sizeof(qword)*2] sbb a3, qword [rel Lpoly+sizeof(qword)*3] sbb a4, qword [rel Lpoly+sizeof(qword)*4] sbb a5, qword [rel Lpoly+sizeof(qword)*5] sbb a6, qword [rel Lpoly+sizeof(qword)*6] sbb a7, qword [rel Lpoly+sizeof(qword)*7] sbb a8, qword [rel Lpoly+sizeof(qword)*8] sbb ex, 0 mov t, qword [rdi+sizeof(qword)*0] cmovb a0, t mov t, qword [rdi+sizeof(qword)*1] cmovb a1, t mov t, qword [rdi+sizeof(qword)*2] cmovb a2, t mov t, qword [rdi+sizeof(qword)*3] cmovb a3, t mov t, qword [rdi+sizeof(qword)*4] cmovb a4, t mov t, qword [rdi+sizeof(qword)*5] cmovb a5, t mov t, qword [rdi+sizeof(qword)*6] cmovb a6, t mov t, qword [rdi+sizeof(qword)*7] cmovb a7, t mov t, qword [rdi+sizeof(qword)*8] cmovb a8, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 REST_XMM REST_GPR ret ENDFUNC p521r1_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p521r1_sub(uint64_t res[9], uint64_t a[9], uint64_t b[9]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx %xdefine t rdx mov a0, qword [rsi+sizeof(qword)*0] ; a mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] mov a6, qword [rsi+sizeof(qword)*6] mov a7, qword [rsi+sizeof(qword)*7] mov a8, qword [rsi+sizeof(qword)*8] xor ex, ex sub a0, qword [rdx+sizeof(qword)*0] ; a-b sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb a3, qword [rdx+sizeof(qword)*3] sbb a4, qword [rdx+sizeof(qword)*4] sbb a5, qword [rdx+sizeof(qword)*5] sbb a6, qword [rdx+sizeof(qword)*6] sbb a7, qword [rdx+sizeof(qword)*7] sbb a8, qword [rdx+sizeof(qword)*8] sbb ex, 0 ; ex = a>=b? 0 : -1 mov qword [rdi+sizeof(qword)*0], a0 ; store (a-b) mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 add a0, qword [rel Lpoly+sizeof(qword)*0] ; (a-b) +poly adc a1, qword [rel Lpoly+sizeof(qword)*1] adc a2, qword [rel Lpoly+sizeof(qword)*2] adc a3, qword [rel Lpoly+sizeof(qword)*3] adc a4, qword [rel Lpoly+sizeof(qword)*4] adc a5, qword [rel Lpoly+sizeof(qword)*5] adc a6, qword [rel Lpoly+sizeof(qword)*6] adc a7, qword [rel Lpoly+sizeof(qword)*7] adc a8, qword [rel Lpoly+sizeof(qword)*8] test ex, ex ; r = (ex)? ((a-b)+poly) : (a-b) mov t, qword [rdi+sizeof(qword)*0] cmovz a0, t mov t, qword [rdi+sizeof(qword)*1] cmovz a1, t mov t, qword [rdi+sizeof(qword)*2] cmovz a2, t mov t, qword [rdi+sizeof(qword)*3] cmovz a3, t mov t, qword [rdi+sizeof(qword)*4] cmovz a4, t mov t, qword [rdi+sizeof(qword)*5] cmovz a5, t mov t, qword [rdi+sizeof(qword)*6] cmovz a6, t mov t, qword [rdi+sizeof(qword)*7] cmovz a7, t mov t, qword [rdi+sizeof(qword)*8] cmovz a8, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 REST_XMM REST_GPR ret ENDFUNC p521r1_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void p521r1_neg(uint64_t res[9], uint64_t a[9]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx %xdefine t rdx xor a0, a0 xor a1, a1 xor a2, a2 xor a3, a3 xor a4, a4 xor a5, a5 xor a6, a6 xor a7, a7 xor a8, a8 xor ex, ex sub a0, qword [rsi+sizeof(qword)*0] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb a3, qword [rsi+sizeof(qword)*3] sbb a4, qword [rsi+sizeof(qword)*4] sbb a5, qword [rsi+sizeof(qword)*5] sbb a6, qword [rsi+sizeof(qword)*6] sbb a7, qword [rsi+sizeof(qword)*7] sbb a8, qword [rsi+sizeof(qword)*8] sbb ex, 0 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 add a0, qword [rel Lpoly+sizeof(qword)*0] adc a1, qword [rel Lpoly+sizeof(qword)*1] adc a2, qword [rel Lpoly+sizeof(qword)*2] adc a3, qword [rel Lpoly+sizeof(qword)*3] adc a4, qword [rel Lpoly+sizeof(qword)*4] adc a5, qword [rel Lpoly+sizeof(qword)*5] adc a6, qword [rel Lpoly+sizeof(qword)*6] adc a7, qword [rel Lpoly+sizeof(qword)*7] adc a8, qword [rel Lpoly+sizeof(qword)*8] test ex, ex mov t, qword [rdi+sizeof(qword)*0] cmovz a0, t mov t, qword [rdi+sizeof(qword)*1] cmovz a1, t mov t, qword [rdi+sizeof(qword)*2] cmovz a2, t mov t, qword [rdi+sizeof(qword)*3] cmovz a3, t mov t, qword [rdi+sizeof(qword)*4] cmovz a4, t mov t, qword [rdi+sizeof(qword)*5] cmovz a5, t mov t, qword [rdi+sizeof(qword)*6] cmovz a6, t mov t, qword [rdi+sizeof(qword)*7] cmovz a7, t mov t, qword [rdi+sizeof(qword)*8] cmovz a8, t mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 mov qword [rdi+sizeof(qword)*4], a4 mov qword [rdi+sizeof(qword)*5], a5 mov qword [rdi+sizeof(qword)*6], a6 mov qword [rdi+sizeof(qword)*7], a7 mov qword [rdi+sizeof(qword)*8], a8 REST_XMM REST_GPR ret ENDFUNC p521r1_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; p521r1_mred(uint64_t res[9], const uint64_t product[9*2]); ; ; modulus = 2^521 -1 ; [17] [0] ; m0 = 1 ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro mred_step 12.nolist %xdefine %%EX %1 %xdefine %%X8 %2 %xdefine %%X7 %3 %xdefine %%X6 %4 %xdefine %%X5 %5 %xdefine %%X4 %6 %xdefine %%X3 %7 %xdefine %%X2 %8 %xdefine %%X1 %9 %xdefine %%X0 %10 %xdefine %%T %11 %xdefine %%CF %12 mov %%T, %%X0 ;; u0 = X0 shr %%T, (64-(521-512)) ;; (T:X0) = u0<<9 shl %%X0, (521-512) add %%T, %%CF add %%X8, %%X0 adc %%EX, %%T mov %%CF, dword 0 adc %%CF, 0 %endmacro align IPP_ALIGN_FACTOR IPPASM p521r1_mred,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine a4 r12 %xdefine a5 r13 %xdefine a6 r14 %xdefine a7 r15 %xdefine a8 rax %xdefine ex rcx mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] mov a4, qword [rsi+sizeof(qword)*4] mov a5, qword [rsi+sizeof(qword)*5] mov a6, qword [rsi+sizeof(qword)*6] mov a7, qword [rsi+sizeof(qword)*7] mov a8, qword [rsi+sizeof(qword)*8] mov ex, qword [rsi+sizeof(qword)*9] %xdefine t rbx %xdefine carry rdx xor carry, carry mred_step ex,a8,a7,a6,a5,a4,a3,a2,a1,a0, t,carry ;; step 0 {rcx,rax,r15,r14,r13,r12,r11,r10,r9,r8} -> {rcx,rax,r15,r14,r13,r12,r11,r10,r9,--} mov a0, qword [rsi+sizeof(qword)*10] mred_step a0,ex,a8,a7,a6,a5,a4,a3,a2,a1, t,carry ;; step 1 {r8,rcx,rax,r15,r14,r13,r12,r11,r10,r9} -> {r8,rcx,rax,r15,r14,r13,r12,r11,r10,--} mov a1, qword [rsi+sizeof(qword)*11] mred_step a1,a0,ex,a8,a7,a6,a5,a4,a3,a2, t,carry ;; step 2 {r9,r8,rcx,rax,r15,r14,r13,r12,r11,r10} -> {r9,r8,rcx,rax,r15,r14,r13,r12,r11, --} mov a2, qword [rsi+sizeof(qword)*12] mred_step a2,a1,a0,ex,a8,a7,a6,a5,a4,a3, t,carry ;; step 3 {r10,r9,r8,rcx,rax,r15,r14,r13,r12,r11} -> {r10,r9,r8,rcx,rax,r15,r14,r13,r12, --} mov a3, qword [rsi+sizeof(qword)*13] mred_step a3,a2,a1,a0,ex,a8,a7,a6,a5,a4, t,carry ;; step 4 {r11,r10,r9,r8,rcx,rax,r15,r14,r13,r12} -> {r11,r10,r9,r8,rcx,rax,r15,r14,r13, --} mov a4, qword [rsi+sizeof(qword)*14] mred_step a4,a3,a2,a1,a0,ex,a8,a7,a6,a5, t,carry ;; step 5 {r12,r11,r10,r9,r8,rcx,rax,r15,r14,r13} -> {r12,r11,r10,r9,r8,rcx,rax,r15,r14, --} mov a5, qword [rsi+sizeof(qword)*15] mred_step a5,a4,a3,a2,a1,a0,ex,a8,a7,a6, t,carry ;; step 6 {r13,r12,r11,r10,r9,r8,rcx,rax,r15,r14} -> {r13,r12,r11,r10,r9,r8,rcx,rax,r15, --} mov a6, qword [rsi+sizeof(qword)*16] mred_step a6,a5,a4,a3,a2,a1,a0,ex,a8,a7, t,carry ;; step 7 {r14,r13,r12,r11,r10,r9,r8,rcx,rax,r15} -> {r14,r13,r12,r11,r10,r9,r8,rcx,rax, --} mov a7, qword [rsi+sizeof(qword)*17] mred_step a7,a6,a5,a4,a3,a2,a1,a0,ex,a8, t,carry ;; step 8 {r15,r14,r13,r12,r11,r10,r9,r8,rcx,rax} -> {r15,r14,r13,r12,r11,r10,r9,r8,rcx, --} ;; temporary result: a8,a7,a6,a5,a4,a3,a2,a1,a0,ex mov qword [rdi+sizeof(qword)*0], ex mov qword [rdi+sizeof(qword)*1], a0 mov qword [rdi+sizeof(qword)*2], a1 mov qword [rdi+sizeof(qword)*3], a2 mov qword [rdi+sizeof(qword)*4], a3 mov qword [rdi+sizeof(qword)*5], a4 mov qword [rdi+sizeof(qword)*6], a5 mov qword [rdi+sizeof(qword)*7], a6 mov qword [rdi+sizeof(qword)*8], a7 ;; sub modulus sub ex, qword [rel Lpoly+sizeof(qword)*0] sbb a0, qword [rel Lpoly+sizeof(qword)*1] sbb a1, qword [rel Lpoly+sizeof(qword)*2] sbb a2, qword [rel Lpoly+sizeof(qword)*3] sbb a3, qword [rel Lpoly+sizeof(qword)*4] sbb a4, qword [rel Lpoly+sizeof(qword)*5] sbb a5, qword [rel Lpoly+sizeof(qword)*6] sbb a6, qword [rel Lpoly+sizeof(qword)*7] sbb a7, qword [rel Lpoly+sizeof(qword)*8] ;; masked copy mov t, qword [rdi+sizeof(qword)*0] cmovb ex, t mov t, qword [rdi+sizeof(qword)*1] cmovb a0, t mov t, qword [rdi+sizeof(qword)*2] cmovb a1, t mov t, qword [rdi+sizeof(qword)*3] cmovb a2, t mov t, qword [rdi+sizeof(qword)*4] cmovb a3, t mov t, qword [rdi+sizeof(qword)*5] cmovb a4, t mov t, qword [rdi+sizeof(qword)*6] cmovb a5, t mov t, qword [rdi+sizeof(qword)*7] cmovb a6, t mov t, qword [rdi+sizeof(qword)*8] cmovb a7, t ;; store result: a7,a6,a5,a4,a3,a2,a1,a0,ex mov qword [rdi+sizeof(qword)*0], ex mov qword [rdi+sizeof(qword)*1], a0 mov qword [rdi+sizeof(qword)*2], a1 mov qword [rdi+sizeof(qword)*3], a2 mov qword [rdi+sizeof(qword)*4], a3 mov qword [rdi+sizeof(qword)*5], a4 mov qword [rdi+sizeof(qword)*6], a5 mov qword [rdi+sizeof(qword)*7], a6 mov qword [rdi+sizeof(qword)*8], a7 REST_XMM REST_GPR ret ENDFUNC p521r1_mred %ifndef _DISABLE_ECP_521R1_HARDCODED_BP_TBL_ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; affine point selector ; ; void p521r1_select_ap_w5(AF_POINT *val, const AF_POINT *tbl, int idx); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM p521r1_select_ap_w5,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm14 COMP_ABI 3 %xdefine val rdi %xdefine in_t rsi %xdefine idx edx %xdefine xyz0 xmm0 %xdefine xyz1 xmm1 %xdefine xyz2 xmm2 %xdefine xyz3 xmm3 %xdefine xyz4 xmm4 %xdefine xyz5 xmm5 %xdefine xyz6 xmm6 %xdefine xyz7 xmm7 %xdefine xyz8 xmm8 %xdefine REQ_IDX xmm9 %xdefine CUR_IDX xmm10 %xdefine MASKDATA xmm11 %xdefine TMP xmm12 movdqa CUR_IDX, oword [rel LOne] movd REQ_IDX, idx pshufd REQ_IDX, REQ_IDX, 0 pxor xyz0, xyz0 pxor xyz1, xyz1 pxor xyz2, xyz2 pxor xyz3, xyz3 pxor xyz4, xyz4 pxor xyz5, xyz5 pxor xyz6, xyz6 pxor xyz7, xyz7 pxor xyz8, xyz8 ; Skip index = 0, is implicictly infty -> load with offset -1 mov rcx, dword 16 .select_loop: movdqa MASKDATA, CUR_IDX ; MASK = CUR_IDX==REQ_IDX? 0xFF : 0x00 pcmpeqd MASKDATA, REQ_IDX ; paddd CUR_IDX, oword [rel LOne] movdqa TMP, oword [in_t+sizeof(oword)*0] pand TMP, MASKDATA por xyz0, TMP movdqa TMP, oword [in_t+sizeof(oword)*1] pand TMP, MASKDATA por xyz1, TMP movdqa TMP, oword [in_t+sizeof(oword)*2] pand TMP, MASKDATA por xyz2, TMP movdqa TMP, oword [in_t+sizeof(oword)*3] pand TMP, MASKDATA por xyz3, TMP movdqa TMP, oword [in_t+sizeof(oword)*4] pand TMP, MASKDATA por xyz4, TMP movdqa TMP, oword [in_t+sizeof(oword)*5] pand TMP, MASKDATA por xyz5, TMP movdqa TMP, oword [in_t+sizeof(oword)*6] pand TMP, MASKDATA por xyz6, TMP movdqa TMP, oword [in_t+sizeof(oword)*7] pand TMP, MASKDATA por xyz7, TMP movdqa TMP, oword [in_t+sizeof(oword)*8] pand TMP, MASKDATA por xyz8, TMP add in_t, sizeof(qword)*(9*2) dec rcx jnz .select_loop movdqu oword [val+sizeof(oword)*0], xyz0 movdqu oword [val+sizeof(oword)*1], xyz1 movdqu oword [val+sizeof(oword)*2], xyz2 movdqu oword [val+sizeof(oword)*3], xyz3 movdqu oword [val+sizeof(oword)*4], xyz4 movdqu oword [val+sizeof(oword)*5], xyz5 movdqu oword [val+sizeof(oword)*6], xyz6 movdqu oword [val+sizeof(oword)*7], xyz7 movdqu oword [val+sizeof(oword)*8], xyz8 REST_XMM REST_GPR ret ENDFUNC p521r1_select_ap_w5 %endif %endif ;; _IPP32E_M7 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcppurgeblkm7as.asm000066400000000000000000000035071470420105600271730ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Purge block ; ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: Clear memory block ;* ;* void PurgeBlock(Ipp8u *pDst, int len) ;* ;*************************************************************** ;; ;; Lib = M7 ;; align IPP_ALIGN_FACTOR IPPASM PurgeBlock,PUBLIC USES_GPR rsi,rdi USES_XMM COMP_ABI 2 ;; rdi: pDst: BYTE, ; mem being clear ;; rsi: len: DWORD ; length movsxd rcx, esi ; store stream length xor rax, rax sub rcx, sizeof(qword) jl .test_purge .purge8: mov qword [rdi], rax ; clear add rdi, sizeof(qword) sub rcx, sizeof(qword) jge .purge8 .test_purge: add rcx, sizeof(qword) jz .quit .purge1: mov byte [rdi], al add rdi, sizeof(byte) sub rcx, sizeof(byte) jg .purge1 .quit: REST_XMM REST_GPR ret ENDFUNC PurgeBlock %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprc4m7as.asm000066400000000000000000000057711470420105600260550ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; ARCFour ; ; Content: ; ARCFourKernel() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: RC4 kernel ;* ;* void ARCFourProcessData(const Ipp8u *pSrc, Ipp8u *pDst, int len, ;* IppsARCFourState* pCtx) ;* ;*************************************************************** ;; ;; Lib = M7 ;; ;; Caller = ippsARCFourEncrypt ;; Caller = ippsARCFourDecrypt ;; align IPP_ALIGN_FACTOR IPPASM ARCFourProcessData,PUBLIC USES_GPR rsi,rdi,rbx,rbp USES_XMM COMP_ABI 4 ;; rdi: pSrc: BYTE, ; input stream ;; rsi: pDst: BYTE, ; output stream ;; rdx: len: DWORD, ; stream length ;; rcx: pCtx: BYTE ; context movsxd r8, edx test r8, r8 ; test length mov rbp, rcx ; copy pointer context jz .quit movzx rax, byte [rbp+4] ; extract x movzx rbx, byte [rbp+8] ; extract y lea rbp, [rbp+12] ; sbox add rax,1 ; x = (x+1)&0xFF movzx rax, al movzx rcx, byte [rbp+rax*4] ; tx = S[x] ;; ;; main code ;; align IPP_ALIGN_FACTOR .main_loop: add rbx, rcx ; y = (x+tx)&0xFF movzx rbx, bl add rdi, 1 add rsi, 1 movzx rdx, byte [rbp+rbx*4] ; ty = S[y] mov dword [rbp+rbx*4],ecx ; S[y] = tx add rcx, rdx ; tmp_idx = (tx+ty)&0xFF movzx rcx, cl mov dword [rbp+rax*4],edx ; S[x] = ty mov dl, byte [rbp+rcx*4] ; byte of gamma add rax, 1 ; next x = (x+1)&0xFF movzx rax, al xor dl,byte [rdi-1] ; gamma ^= src sub r8, 1 movzx rcx, byte [rbp+rax*4] ; next tx = S[x] mov byte [rsi-1],dl ; store result jne .main_loop lea rbp, [rbp-12] ; pointer to context sub rax, 1 ; actual new x counter movzx rax, al mov dword [rbp+4], eax ; update x counter mov dword [rbp+8], ebx ; updtae y counter .quit: REST_XMM REST_GPR ret ENDFUNC ARCFourProcessData %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128ccme9as.asm000066400000000000000000000201341470420105600270470ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; AuthEncrypt_RIJ128_AES_NI() ; DecryptAuth_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR u128_str DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 increment DQ 1,0 segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: Authenticate and Encrypt ;* ;* void AuthEncrypt_RIJ128_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp32u len, ;* Ipp8u* pLocalState) ;* inp localCtx: ;* MAC ;* CTRi ;* CTRi mask ;* ;* out localCtx: ;* new MAC ;* S = enc(CTRi) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAES_CCMEncrypt ;; align IPP_ALIGN_FACTOR IPPASM AuthEncrypt_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7 COMP_ABI 6 ;; rdi: pInpBlk: BYTE, ; input blocks address ;; rsi: pOutBlk: BYTE, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: BYTE, ; key material address ;; r8d length: DWORD, ; length (bytes) ;; r9 pLocCtx: BYTE ; pointer to the localState %assign BYTES_PER_BLK (16) movdqa xmm0, oword [r9] ; MAC movdqa xmm2, oword [r9+sizeof(oword)] ; CTRi block movdqa xmm1, oword [r9+sizeof(oword)*2] ; CTR mask movdqa xmm7, oword [rel u128_str] pshufb xmm2, xmm7 ; CTRi block (LE) pshufb xmm1, xmm7 ; CTR mask movdqa xmm3, xmm1 pandn xmm3, xmm2 ; CTR block template pand xmm2, xmm1 ; CTR value mov r8d, r8d ; expand length movsxd rdx, edx ; expand number of rounds lea rdx, [rdx*4] ; nrCounter = -nr*16 lea rdx, [rdx*4] ; pKey += nr*16 lea rcx, [rcx+rdx] neg rdx mov rbx, rdx align IPP_ALIGN_FACTOR ;; ;; block-by-block processing ;; .blk_loop: movdqu xmm4, oword [rdi] ; input block src[i] pxor xmm0, xmm4 ; MAC ^= src[i] movdqa xmm5, xmm3 paddq xmm2, oword [rel increment] ; advance counter bits pand xmm2, xmm1 ; and mask them por xmm5, xmm2 pshufb xmm5, xmm7 ; CTRi (BE) movdqa xmm6, oword [rcx+rdx] ; keys for whitening add rdx, 16 pxor xmm5, xmm6 ; whitening (CTRi) pxor xmm0, xmm6 ; whitening (MAC) movdqa xmm6, oword [rcx+rdx] ; pre load operation's keys align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm5, xmm6 ; regular round (CTRi) aesenc xmm0, xmm6 ; regular round (MAC) movdqa xmm6, oword [rcx+rdx+16] add rdx, 16 jnz .cipher_loop aesenclast xmm5, xmm6 ; irregular round (CTRi) aesenclast xmm0, xmm6 ; irregular round (MAC) pxor xmm4, xmm5 ; dst[i] = src[i] ^ ENC(CTRi) movdqu oword [rsi], xmm4 mov rdx, rbx add rsi, BYTES_PER_BLK add rdi, BYTES_PER_BLK sub r8, BYTES_PER_BLK jnz .blk_loop movdqu oword [r9], xmm0 ; update MAC value movdqu oword [r9+sizeof(oword)], xmm5 ; update ENC(Ctri) pxor xmm6, xmm6 REST_XMM REST_GPR ret ENDFUNC AuthEncrypt_RIJ128_AES_NI ;*************************************************************** ;* Purpose: Decrypt and Authenticate ;* ;* void DecryptAuth_RIJ128_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int nr, ;* const Ipp8u* pRKey, ;* Ipp32u len, ;* Ipp8u* pLocalState) ;* inp localCtx: ;* MAC ;* CTRi ;* CTRi mask ;* ;* out localCtx: ;* new MAC ;* S = enc(CTRi) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAES_CCMDecrypt ;; align IPP_ALIGN_FACTOR IPPASM DecryptAuth_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME sizeof(qword) USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7 COMP_ABI 6 ;; rdi: pInpBlk: BYTE, ; input blocks address ;; rsi: pOutBlk: BYTE, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: BYTE, ; key material address ;; r8d length: DWORD, ; length (bytes) ;; r9 pLocCtx: BYTE ; pointer to the localState %assign BYTES_PER_BLK (16) movdqa xmm0, oword [r9] ; MAC movdqa xmm2, oword [r9+sizeof(oword)] ; CTRi block movdqa xmm1, oword [r9+sizeof(oword)*2] ; CTR mask movdqa xmm7, oword [rel u128_str] pshufb xmm2, xmm7 ; CTRi block (LE) pshufb xmm1, xmm7 ; CTR mask movdqa xmm3, xmm1 pandn xmm3, xmm2 ; CTR block template pand xmm2, xmm1 ; CTR value mov r8d, r8d ; expand length movsxd rdx, edx ; expand number of rounds lea rdx, [rdx*4] ; nrCounter = -nr*16 lea rdx, [rdx*4] ; pKey += nr*16 lea rcx, [rcx+rdx] neg rdx mov rbx, rdx align IPP_ALIGN_FACTOR ;; ;; block-by-block processing ;; .blk_loop: ;;;;;;;;;;;;;;;;; ;; decryption ;;;;;;;;;;;;;;;;; movdqu xmm4, oword [rdi] ; input block src[i] movdqa xmm5, xmm3 paddq xmm2, oword [rel increment] ; advance counter bits pand xmm2, xmm1 ; and mask them por xmm5, xmm2 pshufb xmm5, xmm7 ; CTRi (BE) movdqa xmm6, oword [rcx+rdx] ; keys for whitening add rdx, 16 pxor xmm5, xmm6 ; whitening (CTRi) movdqa xmm6, oword [rcx+rdx] ; pre load operation's keys align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm5, xmm6 ; regular round (CTRi) movdqa xmm6, oword [rcx+rdx+16] add rdx, 16 jnz .cipher_loop aesenclast xmm5, xmm6 ; irregular round (CTRi) pxor xmm4, xmm5 ; dst[i] = src[i] ^ ENC(CTRi) movdqu oword [rsi], xmm4 ;;;;;;;;;;;;;;;;; ;; update MAC ;;;;;;;;;;;;;;;;; mov rdx, rbx movdqa xmm6, oword [rcx+rdx] ; keys for whitening add rdx, 16 pxor xmm0, xmm4 ; MAC ^= dst[i] pxor xmm0, xmm6 ; whitening (MAC) movdqa xmm6, oword [rcx+rdx] ; pre load operation's keys align IPP_ALIGN_FACTOR .auth_loop: aesenc xmm0, xmm6 ; regular round (MAC) movdqa xmm6, oword [rcx+rdx+16] add rdx, 16 jnz .auth_loop aesenclast xmm0, xmm6 ; irregular round (MAC) mov rdx, rbx add rsi, BYTES_PER_BLK add rdi, BYTES_PER_BLK sub r8, BYTES_PER_BLK jnz .blk_loop movdqu oword [r9], xmm0 ; update MAC value movdqu oword [r9+sizeof(oword)], xmm6 ; update ENC(Ctri) pxor xmm6, xmm6 REST_XMM REST_GPR ret ENDFUNC DecryptAuth_RIJ128_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128cmace9as.asm000066400000000000000000000062411470420105600272130ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2018 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; cpAESCMAC_Update_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: AES-CMAC update ;* ;* void cpAESCMAC_Update_AES_NI(Ipp8u* digest, ;* const Ipp8u* input, ;* int inpLen, ;* int nr, ;* const Ipp32u* pRKey) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAES_CMACUpdate ;; align IPP_ALIGN_FACTOR IPPASM cpAESCMAC_Update_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 5 ;; rdi: pDigest: DWORD, ; input blocks address ;; rsi: pInput: DWORD, ; output blocks address ;; rdx: length: DWORD, ; length in bytes (multiple 16) ;; rcx: nr: DWORD ; number of rounds ;; r8: pRKey: DWORD ; pointer to keys %xdefine SC (4) %assign BYTES_PER_BLK (16) movsxd rdx, edx ; input length movdqu xmm0, oword [rdi] ; digest align IPP_ALIGN_FACTOR ;; ;; pseudo-pipelined processing ;; .blks_loop: movdqu xmm1, oword [rsi] ; input block movdqa xmm4, oword [r8] mov r9, r8 ; save pointer to the key material pxor xmm0, xmm1 ; digest ^ src[] pxor xmm0, xmm4 ; whitening movdqa xmm4, oword [r9+16] add r9, 16 mov r10, rcx ; counter depending on key length sub r10, 1 align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm0, xmm4 ; regular round movdqa xmm4, oword [r9+16] add r9, 16 dec r10 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round add rsi, BYTES_PER_BLK ; advance pointers sub rdx, BYTES_PER_BLK ; decrease counter jnz .blks_loop pxor xmm4, xmm4 movdqu oword [rdi], xmm0 ; store updated digest digest REST_XMM REST_GPR ret ENDFUNC cpAESCMAC_Update_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128decryptcbcpipee9as.asm000066400000000000000000000250741470420105600313150ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; DecryptCBC_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: pipelined RIJ128 CBC decryption ;* ;* void DecryptCBC_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len, ;* const Ipp8u* pIV) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAESDecryptCBC ;; %assign AES_BLOCK (16) align IPP_ALIGN_FACTOR IPPASM DecryptCBC_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME ((1+8)*AES_BLOCK) USES_GPR rsi,rdi,rbx USES_XMM xmm15 COMP_ABI 6 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d length: DWORD ; length (bytes) ;; r9 pIV BYTE ; pointer to the IV %xdefine SC (4) movdqu xmm15, oword [r9] ; IV movsxd r8, r8d ; processed length lea rax,[rdx*SC] ; keys offset cmp r8, (4*AES_BLOCK) jl .short123_input cmp r8, (16*AES_BLOCK) jle .block4x ;; ;; 8-blocks processing ;; mov rbx, rsp ; rbx points on cipher's data in stack sub rsp, sizeof(oword)*4 ; allocate stack and xmm registers movdqa oword [rsp+0*sizeof(oword)], xmm6 movdqa oword [rsp+1*sizeof(oword)], xmm7 movdqa oword [rsp+2*sizeof(oword)], xmm8 movdqa oword [rsp+3*sizeof(oword)], xmm9 sub r8, (8*AES_BLOCK) align IPP_ALIGN_FACTOR .blk8_loop: lea r9,[rcx+rax*sizeof(dword)-AES_BLOCK]; pointer to the key material movdqu xmm0, oword [rdi+0*AES_BLOCK] ; get input blocks movdqu xmm1, oword [rdi+1*AES_BLOCK] movdqu xmm2, oword [rdi+2*AES_BLOCK] movdqu xmm3, oword [rdi+3*AES_BLOCK] movdqu xmm6, oword [rdi+4*AES_BLOCK] movdqu xmm7, oword [rdi+5*AES_BLOCK] movdqu xmm8, oword [rdi+6*AES_BLOCK] movdqu xmm9, oword [rdi+7*AES_BLOCK] movdqa xmm5, oword [r9+AES_BLOCK] ; whitening keys movdqa xmm4, oword [r9] ; pre load operation's keys movdqa oword [rbx+1*AES_BLOCK], xmm0 ; save input into the stack pxor xmm0, xmm5 ; and do whitening movdqa oword [rbx+2*AES_BLOCK], xmm1 pxor xmm1, xmm5 movdqa oword [rbx+3*AES_BLOCK], xmm2 pxor xmm2, xmm5 movdqa oword [rbx+4*AES_BLOCK], xmm3 pxor xmm3, xmm5 movdqa oword [rbx+5*AES_BLOCK], xmm6 pxor xmm6, xmm5 movdqa oword [rbx+6*AES_BLOCK], xmm7 pxor xmm7, xmm5 movdqa oword [rbx+7*AES_BLOCK], xmm8 pxor xmm8, xmm5 movdqa oword [rbx+8*AES_BLOCK], xmm9 pxor xmm9, xmm5 movdqa xmm5, oword [r9-AES_BLOCK] ; pre load operation's keys sub r9, (2*AES_BLOCK) lea r10, [rdx-2] ; counter = nrounds-2 align IPP_ALIGN_FACTOR .cipher_loop8: aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 aesdec xmm6, xmm4 aesdec xmm7, xmm4 aesdec xmm8, xmm4 aesdec xmm9, xmm4 movdqa xmm4, oword [r9] ; pre load operation's keys aesdec xmm0, xmm5 ; regular round aesdec xmm1, xmm5 aesdec xmm2, xmm5 aesdec xmm3, xmm5 aesdec xmm6, xmm5 aesdec xmm7, xmm5 aesdec xmm8, xmm5 aesdec xmm9, xmm5 movdqa xmm5, oword [r9-AES_BLOCK] ; pre load operation's keys sub r9, (2*AES_BLOCK) sub r10, 2 jnz .cipher_loop8 aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 aesdec xmm6, xmm4 aesdec xmm7, xmm4 aesdec xmm8, xmm4 aesdec xmm9, xmm4 aesdeclast xmm0, xmm5 ; irregular round, ^IV, and store result pxor xmm0, xmm15 movdqu oword [rsi+0*AES_BLOCK], xmm0 aesdeclast xmm1, xmm5 pxor xmm1, oword [rbx+1*AES_BLOCK] movdqu oword [rsi+1*AES_BLOCK], xmm1 aesdeclast xmm2, xmm5 pxor xmm2, oword [rbx+2*AES_BLOCK] movdqu oword [rsi+2*AES_BLOCK], xmm2 aesdeclast xmm3, xmm5 pxor xmm3, oword [rbx+3*AES_BLOCK] movdqu oword [rsi+3*AES_BLOCK], xmm3 aesdeclast xmm6, xmm5 pxor xmm6, oword [rbx+4*AES_BLOCK] movdqu oword [rsi+4*AES_BLOCK], xmm6 aesdeclast xmm7, xmm5 pxor xmm7, oword [rbx+5*AES_BLOCK] movdqu oword [rsi+5*AES_BLOCK], xmm7 aesdeclast xmm8, xmm5 pxor xmm8, oword [rbx+6*AES_BLOCK] movdqu oword [rsi+6*AES_BLOCK], xmm8 aesdeclast xmm9, xmm5 pxor xmm9, oword [rbx+7*AES_BLOCK] movdqu oword [rsi+7*AES_BLOCK], xmm9 movdqa xmm15,oword [rbx+8*AES_BLOCK] ; update IV add rsi, (8*AES_BLOCK) add rdi, (8*AES_BLOCK) sub r8, (8*AES_BLOCK) jge .blk8_loop movdqa xmm6, oword [rsp+0*sizeof(oword)] ; restore xmm registers movdqa xmm7, oword [rsp+1*sizeof(oword)] movdqa xmm8, oword [rsp+2*sizeof(oword)] movdqa xmm9, oword [rsp+3*sizeof(oword)] add rsp, sizeof(oword)*4 ; and release stack add r8, (8*AES_BLOCK) jz .quit ;; ;; test %if 4-blocks processing alaivalbe ;; .block4x: cmp r8, (4*AES_BLOCK) jl .short123_input sub r8, (4*AES_BLOCK) align IPP_ALIGN_FACTOR .blk4_loop: lea r9,[rcx+rax*sizeof(dword)-AES_BLOCK]; pointer to the key material movdqu xmm0, oword [rdi+0*AES_BLOCK] ; get input blocks movdqu xmm1, oword [rdi+1*AES_BLOCK] movdqu xmm2, oword [rdi+2*AES_BLOCK] movdqu xmm3, oword [rdi+3*AES_BLOCK] movdqa xmm5, oword [r9+AES_BLOCK] ; whitening keys movdqa xmm4, oword [r9] ; pre load operation's keys movdqa oword [rsp+1*AES_BLOCK], xmm0 ; save input into the stack pxor xmm0, xmm5 ; and do whitening movdqa oword [rsp+2*AES_BLOCK], xmm1 pxor xmm1, xmm5 movdqa oword [rsp+3*AES_BLOCK], xmm2 pxor xmm2, xmm5 movdqa oword [rsp+4*AES_BLOCK], xmm3 pxor xmm3, xmm5 movdqa xmm5, oword [r9-AES_BLOCK] ; pre load operation's keys sub r9, (2*AES_BLOCK) lea r10, [rdx-2] ; counter = nrounds-2 align IPP_ALIGN_FACTOR .cipher_loop4: aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 movdqa xmm4, oword [r9] ; pre load operation's keys aesdec xmm0, xmm5 ; regular round aesdec xmm1, xmm5 aesdec xmm2, xmm5 aesdec xmm3, xmm5 movdqa xmm5, oword [r9-AES_BLOCK] ; pre load operation's keys sub r9, (2*AES_BLOCK) sub r10, 2 jnz .cipher_loop4 aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 aesdeclast xmm0, xmm5 ; irregular round, ^IV, and store result pxor xmm0, xmm15 movdqu oword [rsi+0*AES_BLOCK], xmm0 aesdeclast xmm1, xmm5 pxor xmm1, oword [rsp+1*AES_BLOCK] movdqu oword [rsi+1*AES_BLOCK], xmm1 aesdeclast xmm2, xmm5 pxor xmm2, oword [rsp+2*AES_BLOCK] movdqu oword [rsi+2*AES_BLOCK], xmm2 aesdeclast xmm3, xmm5 pxor xmm3, oword [rsp+3*AES_BLOCK] movdqu oword [rsi+3*AES_BLOCK], xmm3 movdqa xmm15,oword [rsp+4*AES_BLOCK] ; update IV add rsi, (4*AES_BLOCK) add rdi, (4*AES_BLOCK) sub r8, (4*AES_BLOCK) jge .blk4_loop add r8, (4*AES_BLOCK) jz .quit ;; ;; block-by-block processing ;; .short123_input: lea r9,[rcx+rax*sizeof(dword)] ; pointer to the key material (whitening) align IPP_ALIGN_FACTOR .single_blk_loop: movdqu xmm0, oword [rdi] ; get input block add rdi, AES_BLOCK movdqa xmm1, xmm0 ; and save as IV for future pxor xmm0, oword [r9] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesdec xmm0, oword [rcx+9*SC*4+4*SC*4] aesdec xmm0, oword [rcx+9*SC*4+3*SC*4] .key_192_s: aesdec xmm0, oword [rcx+9*SC*4+2*SC*4] aesdec xmm0, oword [rcx+9*SC*4+1*SC*4] .key_128_s: aesdec xmm0, oword [rcx+9*SC*4-0*SC*4] aesdec xmm0, oword [rcx+9*SC*4-1*SC*4] aesdec xmm0, oword [rcx+9*SC*4-2*SC*4] aesdec xmm0, oword [rcx+9*SC*4-3*SC*4] aesdec xmm0, oword [rcx+9*SC*4-4*SC*4] aesdec xmm0, oword [rcx+9*SC*4-5*SC*4] aesdec xmm0, oword [rcx+9*SC*4-6*SC*4] aesdec xmm0, oword [rcx+9*SC*4-7*SC*4] aesdec xmm0, oword [rcx+9*SC*4-8*SC*4] aesdeclast xmm0, oword [rcx+9*SC*4-9*SC*4] pxor xmm0, xmm15 ; add IV movdqu oword [rsi], xmm0 ; and save output blocl add rsi, AES_BLOCK sub r8, AES_BLOCK movdqa xmm15, xmm1 ; update IV jnz .single_blk_loop .quit: pxor xmm4, xmm4 pxor xmm5, xmm5 REST_XMM REST_GPR ret ENDFUNC DecryptCBC_RIJ128pipe_AES_NI %endif ;; _IPP32E >= _IPP32E_Y8 %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128decryptcfbpipee9as.asm000066400000000000000000000376141470420105600313230ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Decrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) %macro COPY_8U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_byte: mov %%tmp, byte [%%src+rcx] mov byte [%%dst+rcx], %%tmp add rcx, 1 cmp rcx, %%limit jl %%next_byte %endmacro %macro COPY_32U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_dword: mov %%tmp, dword [%%src+rcx] mov dword [%%dst+rcx], %%tmp add rcx, 4 cmp rcx, %%limit jl %%next_dword %endmacro %macro COPY_128U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_oword: movdqu %%tmp, oword [%%src+rcx] movdqu oword [%%dst+rcx], %%tmp add rcx, 16 cmp rcx, %%limit jl %%next_oword %endmacro segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: pipelined RIJ128 CFB decryption ;* ;* void DecryptCFB_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int cfbBlks, ;* int cfbSize, ;* const Ipp8u* pIV) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsRijndael128DecryptCFB ;; align IPP_ALIGN_FACTOR IPPASM DecryptCFB_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME (1+4+4)*16 USES_GPR rsi,rdi,r13,r14,r15 USES_XMM xmm6,xmm7 COMP_ABI 7 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in cfbSize ;; r9d cfbSize: DWORD ; cfb blk size ;; [rsp+ARG_7] pIV BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) mov rax, [rsp+ARG_7] ; IV address movdqu xmm4, oword [rax] ; get IV movdqa oword [rsp+0*16], xmm4 ; into the stack mov r13, rdi mov r14, rsi mov r15, rcx movsxd r8, r8d ; length of stream movsxd r9, r9d ; cfb blk size sub r8, BLKS_PER_LOOP jl .short_input ;; ;; pipelined processing ;; lea r10, [r9*BLKS_PER_LOOP] .blks_loop: COPY_32U {rsp+16}, r13, r10, r11d ; move 4 input blocks to stack movdqa xmm4, oword [r15] lea r10, [r9+r9*2] movdqa xmm0, oword [rsp] ; get encoded blocks movdqu xmm1, oword [rsp+r9] movdqu xmm2, oword [rsp+r9*2] movdqu xmm3, oword [rsp+r10] mov r10, r15 ; set pointer to the key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [r10+16] ; pre load operation's keys add r10, 16 mov r11, rdx ; counter depending on key length sub r11, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [r10+16]; pre load operation's keys add r10, 16 dec r11 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round and IV aesenclast xmm1, xmm4 aesenclast xmm2, xmm4 aesenclast xmm3, xmm4 lea r10, [r9+r9*2] ; get src blocks from the stack movdqa xmm4, oword [rsp+16] movdqu xmm5, oword [rsp+16+r9] movdqu xmm6, oword [rsp+16+r9*2] movdqu xmm7, oword [rsp+16+r10] pxor xmm0, xmm4 ; xor src movdqa oword [rsp+5*16],xmm0;and store into the stack pxor xmm1, xmm5 movdqu oword [rsp+5*16+r9], xmm1 pxor xmm2, xmm6 movdqu oword [rsp+5*16+r9*2], xmm2 pxor xmm3, xmm7 movdqu oword [rsp+5*16+r10], xmm3 lea r10, [r9*BLKS_PER_LOOP] ;COPY_8U r14, {rsp+5*16}, r10 ; move 4 blocks to output COPY_32U r14, {rsp+5*16}, r10, r11d ; move 4 blocks to output movdqu xmm0, oword [rsp+r10]; update IV movdqu oword [rsp], xmm0 add r13, r10 add r14, r10 sub r8, BLKS_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add r8, BLKS_PER_LOOP jz .quit lea r10, [r9*2] lea r11, [r9+r9*2] cmp r8, 2 cmovl r10, r9 cmovg r10, r11 COPY_8U {rsp+16}, r13, r10, al ; move recent input blocks to stack ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [r15+rax*4-9*(SC)*4] ; AES-128 round keys xor r11, r11 ; index .single_blk_loop: movdqu xmm0, oword [rsp+r11] ; get encoded block pxor xmm0, oword [r15] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] movdqu xmm1, oword [rsp+r11+16] ; get input block from the stack pxor xmm0, xmm1 ; xor src movdqu oword [rsp+5*16+r11], xmm0 ; and save output add r11, r9 dec r8 jnz .single_blk_loop COPY_8U r14, {rsp+5*16}, r10, al ; copy rest output from the stack .quit: REST_XMM REST_GPR ret ENDFUNC DecryptCFB_RIJ128pipe_AES_NI align IPP_ALIGN_FACTOR IPPASM DecryptCFB32_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME (1+4+4)*16 USES_GPR rsi,rdi,r13,r14,r15 USES_XMM xmm6,xmm7 COMP_ABI 7 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in cfbSize ;; r9d cfbSize: DWORD ; cfb blk size (4 bytes multiple) ;; [rsp+ARG_7] pIV BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) mov rax, [rsp+ARG_7] ; IV address movdqu xmm4, oword [rax] ; get IV movdqa oword [rsp+0*16], xmm4 ; into the stack mov r13, rdi mov r14, rsi mov r15, rcx movsxd r8, r8d ; length of stream movsxd r9, r9d ; cfb blk size sub r8, BLKS_PER_LOOP jl .short_input ;; ;; pipelined processing ;; lea r10, [r9*BLKS_PER_LOOP] .blks_loop: COPY_128U {rsp+16}, r13, r10, xmm0 ; move 4 input blocks to stack movdqa xmm4, oword [r15] lea r10, [r9+r9*2] movdqa xmm0, oword [rsp] ; get encoded blocks movdqu xmm1, oword [rsp+r9] movdqu xmm2, oword [rsp+r9*2] movdqu xmm3, oword [rsp+r10] mov r10, r15 ; set pointer to the key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [r10+16] ; pre load operation's keys add r10, 16 mov r11, rdx ; counter depending on key length sub r11, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [r10+16]; pre load operation's keys add r10, 16 dec r11 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round and IV aesenclast xmm1, xmm4 aesenclast xmm2, xmm4 aesenclast xmm3, xmm4 lea r10, [r9+r9*2] ; get src blocks from the stack movdqa xmm4, oword [rsp+16] movdqu xmm5, oword [rsp+16+r9] movdqu xmm6, oword [rsp+16+r9*2] movdqu xmm7, oword [rsp+16+r10] pxor xmm0, xmm4 ; xor src movdqa oword [rsp+5*16],xmm0;and store into the stack pxor xmm1, xmm5 movdqu oword [rsp+5*16+r9], xmm1 pxor xmm2, xmm6 movdqu oword [rsp+5*16+r9*2], xmm2 pxor xmm3, xmm7 movdqu oword [rsp+5*16+r10], xmm3 lea r10, [r9*BLKS_PER_LOOP] COPY_128U r14, {rsp+5*16}, r10, xmm0 ; move 4 blocks to output movdqu xmm0, oword [rsp+r10] ; update IV movdqu oword [rsp], xmm0 add r13, r10 add r14, r10 sub r8, BLKS_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add r8, BLKS_PER_LOOP jz .quit lea r10, [r9*2] lea r11, [r9+r9*2] cmp r8, 2 cmovl r10, r9 cmovg r10, r11 COPY_32U {rsp+16}, r13, r10, eax ; move recent input blocks to stack ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [r15+rax*4-9*(SC)*4] ; AES-128 round keys xor r11, r11 ; index .single_blk_loop: movdqu xmm0, oword [rsp+r11] ; get encoded block pxor xmm0, oword [r15] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] movdqu xmm1, oword [rsp+r11+16] ; get input block from the stack pxor xmm0, xmm1 ; xor src movdqu oword [rsp+5*16+r11], xmm0 ; and save output add r11, r9 dec r8 jnz .single_blk_loop COPY_32U r14, {rsp+5*16}, r10, eax ; copy rest output from the stack .quit: REST_XMM REST_GPR ret ENDFUNC DecryptCFB32_RIJ128pipe_AES_NI ;; ;; Lib = Y8 ;; ;; Caller = ippsRijndael128DecryptCFB ;; align IPP_ALIGN_FACTOR IPPASM DecryptCFB128_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM xmm6,xmm7 COMP_ABI 6 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d lenBytes: DWORD ; length of stream in bytes ;; r9 pIV BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) movdqu xmm0, oword [r9] ; get IV movsxd r8, r8d ; length of the stream sub r8, BYTES_PER_LOOP jl .short_input ;; ;; pipelined processing ;; .blks_loop: movdqa xmm7, oword [rcx] ; get initial key material mov r10, rcx ; set pointer to the key material movdqu xmm1, oword [rdi+0*BYTES_PER_BLK] ; get another encoded cblocks movdqu xmm2, oword [rdi+1*BYTES_PER_BLK] movdqu xmm3, oword [rdi+2*BYTES_PER_BLK] pxor xmm0, xmm7 ; whitening pxor xmm1, xmm7 pxor xmm2, xmm7 pxor xmm3, xmm7 movdqa xmm7, oword [r10+16] ; pre load operation's keys add r10, 16 mov r11, rdx ; counter depending on key length sub r11, 1 .cipher_loop: aesenc xmm0, xmm7 ; regular round aesenc xmm1, xmm7 aesenc xmm2, xmm7 aesenc xmm3, xmm7 movdqa xmm7, oword [r10+16] ; pre load operation's keys add r10, 16 dec r11 jnz .cipher_loop aesenclast xmm0, xmm7 ; irregular round and IV movdqu xmm4, oword [rdi+0*BYTES_PER_BLK] ; 4 input blocks aesenclast xmm1, xmm7 movdqu xmm5, oword [rdi+1*BYTES_PER_BLK] aesenclast xmm2, xmm7 movdqu xmm6, oword [rdi+2*BYTES_PER_BLK] aesenclast xmm3, xmm7 movdqu xmm7, oword [rdi+3*BYTES_PER_BLK] add rdi, BYTES_PER_LOOP pxor xmm0, xmm4 ; 4 output blocks movdqu oword [rsi+0*16], xmm0 pxor xmm1, xmm5 movdqu oword [rsi+1*16], xmm1 pxor xmm2, xmm6 movdqu oword [rsi+2*16], xmm2 pxor xmm3, xmm7 movdqu oword [rsi+3*16], xmm3 add rsi, BYTES_PER_LOOP movdqa xmm0, xmm7 ; update IV sub r8, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add r8, BYTES_PER_LOOP jz .quit ; get actual address of key material: pRKeys += (nr-9) * SC lea rax, [rdx*4] lea rax, [rcx+rax*4-9*(SC)*4] ; AES-128 round keys .single_blk_loop: pxor xmm0, oword [rcx] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] movdqu xmm1, oword [rdi] ; input block from the stream add rdi, BYTES_PER_BLK pxor xmm0, xmm1 ; xor src movdqu oword [rsi], xmm0 ; and save output add rsi, BYTES_PER_BLK movdqa xmm0, xmm1 ; update IV sub r8, BYTES_PER_BLK jnz .single_blk_loop .quit: REST_XMM REST_GPR ret ENDFUNC DecryptCFB128_RIJ128pipe_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128decrypte9as.asm000066400000000000000000000062051470420105600277620ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Decrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: single block RIJ128 Inverse Cipher ;* ;* void Decrypt_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* const Ipp32u Tables[][256]) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsRijndael128DecryptECB ;; Caller = ippsRijndael128DecryptCBC ;; align IPP_ALIGN_FACTOR IPPASM Decrypt_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 4 ;; rdi: pInpBlk: DWORD, ; input block address ;; rsi: pOutBlk: DWORD, ; output block address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address %xdefine SC (4) lea rax,[rdx*SC] lea rax,[rax*4] movdqu xmm0, oword [rdi] ; input block ;;whitening pxor xmm0, oword [rcx+rax] cmp rdx,12 ; switch according to number of rounds jl .key_128 jz .key_192 ;; ;; regular rounds ;; .key_256: aesdec xmm0,oword [rcx+9*SC*4+4*SC*4] aesdec xmm0,oword [rcx+9*SC*4+3*SC*4] .key_192: aesdec xmm0,oword [rcx+9*SC*4+2*SC*4] aesdec xmm0,oword [rcx+9*SC*4+1*SC*4] .key_128: aesdec xmm0,oword [rcx+9*SC*4-0*SC*4] aesdec xmm0,oword [rcx+9*SC*4-1*SC*4] aesdec xmm0,oword [rcx+9*SC*4-2*SC*4] aesdec xmm0,oword [rcx+9*SC*4-3*SC*4] aesdec xmm0,oword [rcx+9*SC*4-4*SC*4] aesdec xmm0,oword [rcx+9*SC*4-5*SC*4] aesdec xmm0,oword [rcx+9*SC*4-6*SC*4] aesdec xmm0,oword [rcx+9*SC*4-7*SC*4] aesdec xmm0,oword [rcx+9*SC*4-8*SC*4] ;; ;; last rounds ;; aesdeclast xmm0,oword [rcx+9*SC*4-9*SC*4] movdqu oword [rsi], xmm0 ; output block REST_XMM REST_GPR ret ENDFUNC Decrypt_RIJ128_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128decryptecbpipee9as.asm000066400000000000000000000122531470420105600313120ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; DecryptECB_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: pipelined RIJ128 ECB decryption ;* ;* void DecryptECB_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAESDecryptECB ;; align IPP_ALIGN_FACTOR IPPASM DecryptECB_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 5 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d length: DWORD ; length (bytes) %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) lea rax,[rdx*SC] ; keys offset movsxd r8, r8d sub r8, BYTES_PER_LOOP jl .short_input ;; ;; pipelined processing ;; ;ALIGN IPP_ALIGN_FACTOR .blks_loop: lea r9,[rcx+rax*4] ; set pointer to the key material movdqa xmm4, oword [r9] ; keys for whitening sub r9, 16 movdqu xmm0, oword [rdi+0*BYTES_PER_BLK] ; get input blocks movdqu xmm1, oword [rdi+1*BYTES_PER_BLK] movdqu xmm2, oword [rdi+2*BYTES_PER_BLK] movdqu xmm3, oword [rdi+3*BYTES_PER_BLK] add rdi, BYTES_PER_LOOP pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [r9] ; pre load operation's keys sub r9, 16 mov r10, rdx ; counter depending on key length sub r10, 1 ;ALIGN IPP_ALIGN_FACTOR .cipher_loop: aesdec xmm0, xmm4 ; regular round aesdec xmm1, xmm4 aesdec xmm2, xmm4 aesdec xmm3, xmm4 movdqa xmm4, oword [r9] ; pre load operation's keys sub r9, 16 dec r10 jnz .cipher_loop aesdeclast xmm0, xmm4 ; irregular round movdqu oword [rsi+0*BYTES_PER_BLK], xmm0 ; store output blocks aesdeclast xmm1, xmm4 movdqu oword [rsi+1*BYTES_PER_BLK], xmm1 aesdeclast xmm2, xmm4 movdqu oword [rsi+2*BYTES_PER_BLK], xmm2 aesdeclast xmm3, xmm4 movdqu oword [rsi+3*BYTES_PER_BLK], xmm3 add rsi, BYTES_PER_LOOP sub r8, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add r8, BYTES_PER_LOOP jz .quit lea r9,[rcx+rax*4] ; set pointer to the key material align IPP_ALIGN_FACTOR .single_blk_loop: movdqu xmm0, oword [rdi] ; get input block add rdi, BYTES_PER_BLK pxor xmm0, oword [r9] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesdec xmm0, oword [rcx+9*SC*4+4*SC*4] aesdec xmm0, oword [rcx+9*SC*4+3*SC*4] .key_192_s: aesdec xmm0, oword [rcx+9*SC*4+2*SC*4] aesdec xmm0, oword [rcx+9*SC*4+1*SC*4] .key_128_s: aesdec xmm0, oword [rcx+9*SC*4-0*SC*4] aesdec xmm0, oword [rcx+9*SC*4-1*SC*4] aesdec xmm0, oword [rcx+9*SC*4-2*SC*4] aesdec xmm0, oword [rcx+9*SC*4-3*SC*4] aesdec xmm0, oword [rcx+9*SC*4-4*SC*4] aesdec xmm0, oword [rcx+9*SC*4-5*SC*4] aesdec xmm0, oword [rcx+9*SC*4-6*SC*4] aesdec xmm0, oword [rcx+9*SC*4-7*SC*4] aesdec xmm0, oword [rcx+9*SC*4-8*SC*4] aesdeclast xmm0, oword [rcx+9*SC*4-9*SC*4] movdqu oword [rsi], xmm0 ; save output block add rsi, BYTES_PER_BLK sub r8, BYTES_PER_BLK jnz .single_blk_loop .quit: pxor xmm4, xmm4 REST_XMM REST_GPR ret ENDFUNC DecryptECB_RIJ128pipe_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128decryptxtse9as.asm000066400000000000000000000256051470420105600305260ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; AES functions ; ; Content: ; cpAESEncryptXTS_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ALPHA_MUL_CNT dq 00000000000000087h, 00000000000000001h ;*************************************************************** ;* Purpose: AES-XTS encryption ;* ;* void cpAESDecryptXTS_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int length, ;* const Ipp8u* pRKey, ;* int nr, ;* Ipp8u* pTweak) ;*************************************************************** ;; ;; key = ks[0] ;; mul_cnt = {0x0000000000000001:0x0000000000000087} ;; returns: ;; ktwk = twk^key ;; twk = twk*alpha ;; twk2= twk2 *2 - auxiliary ;; %macro OUTER_MUL_X 6.nolist %xdefine %%ktwk %1 %xdefine %%twk %2 %xdefine %%key %3 %xdefine %%mul_cnt %4 %xdefine %%twk2 %5 %xdefine %%mask %6 movdqa %%mask, %%twk2 paddd %%twk2, %%twk2 movdqa %%ktwk, %%twk psrad %%mask, 31 paddq %%twk, %%twk pand %%mask, %%mul_cnt pxor %%ktwk, %%key pxor %%twk, %%mask %endmacro %macro LAST_OUTER_MUL_X 5.nolist %xdefine %%ktwk %1 %xdefine %%twk %2 %xdefine %%key %3 %xdefine %%mul_cnt %4 %xdefine %%twk2 %5 movdqa %%ktwk, %%twk psrad %%twk2, 31 paddq %%twk, %%twk pand %%twk2, %%mul_cnt pxor %%ktwk, %%key pxor %%twk, %%twk2 %endmacro %macro INNER_MUL_X 6.nolist %xdefine %%ktwk %1 %xdefine %%twk %2 %xdefine %%key %3 %xdefine %%mul_cnt %4 %xdefine %%twk2 %5 %xdefine %%mask %6 movdqa %%mask, %%twk2 paddd %%twk2, %%twk2 psrad %%mask, 31 paddq %%twk, %%twk pand %%mask, %%mul_cnt pxor %%twk, %%mask %ifnidn %%key,%%ktwk movdqa %%key, %%ktwk %endif pxor %%ktwk, %%twk %endmacro %macro LAST_INNER_MUL_X 3.nolist %xdefine %%twk %1 %xdefine %%mul_cnt %2 %xdefine %%twk2 %3 psrad %%twk2, 31 paddq %%twk, %%twk pand %%twk2, %%mul_cnt pxor %%twk, %%twk2 %endmacro align IPP_ALIGN_FACTOR IPPASM cpAESDecryptXTS_AES_NI,PUBLIC %assign LOCAL_FRAME sizeof(oword)*6 USES_GPR rsi,rdi USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 6 ;; rdi: pOutBlk: BYTE ; pointer to the output bloak ;; rsi: pInpBlk: BYTE ; pointer to the input block ;; edx: nBlocks DWORD ; number of blocks ;; rcx: pKey: BYTE ; key material address ;; r8d: nr: DWORD ; number of rounds ;; r9 pTweak: BYTE ; pointer to the input/output (ciphertext) tweak %assign AES_BLOCK (16) movsxd r8, r8d ; number of cipher rounds movdqu xmm15, xmmword [r9] ; input tweak value shl r8, 4 ; key schedule length (bytes) movdqa xmm0, xmmword [rcx+r8] ; key[0] movdqa xmm8, xmmword [rel ALPHA_MUL_CNT] ; mul constant pshufd xmm9, xmm15, 5Fh ; {twk[1]:twk[1]:twk[3]:twk[3]} - auxiliary value movsxd rdx, edx ; number of blocks being processing ;; compute: ;; - ktwk[i] = twk[i]^key[0] ;; - twk[i+1] = twk[i]*alpha^(i+1), i=0..5 OUTER_MUL_X xmm10, xmm15, xmm0, xmm8, xmm9, xmm14 OUTER_MUL_X xmm11, xmm15, xmm0, xmm8, xmm9, xmm14 OUTER_MUL_X xmm12, xmm15, xmm0, xmm8, xmm9, xmm14 OUTER_MUL_X xmm13, xmm15, xmm0, xmm8, xmm9, xmm14 LAST_OUTER_MUL_X xmm14, xmm15, xmm0, xmm8, xmm9 movdqa xmm8, xmm15 ; save tweak for next iteration pxor xmm15, xmm0 ; add key[0] sub rdx, 6 ; test input length jc .short_input ;; ;; blocks processing ;; align IPP_ALIGN_FACTOR .blks_loop: pxor xmm0, xmmword [rcx] ; key[0]^key[last] lea rax, [r8-6*AES_BLOCK] ; cipher_loop counter lea r10, [rcx+6*AES_BLOCK] ; mov key pointer down movdqu xmm2, xmmword [rsi] ; src[0] - src[7] movdqu xmm3, xmmword [rsi+AES_BLOCK] movdqu xmm4, xmmword [rsi+2*AES_BLOCK] movdqu xmm5, xmmword [rsi+3*AES_BLOCK] movdqu xmm6, xmmword [rsi+4*AES_BLOCK] movdqu xmm7, xmmword [rsi+5*AES_BLOCK] movdqa xmm1, xmmword [rcx+r8-1*AES_BLOCK] ; key[1] pxor xmm2, xmm10 ; src[] ^twk[] ^ key[0] pxor xmm3, xmm11 pxor xmm4, xmm12 pxor xmm5, xmm13 pxor xmm6, xmm14 pxor xmm7, xmm15 pxor xmm10, xmm0 ; store twk[] ^ key[last] pxor xmm11, xmm0 pxor xmm12, xmm0 pxor xmm13, xmm0 pxor xmm14, xmm0 pxor xmm15, xmm0 movdqa xmm0, xmmword [rcx+r8-2*AES_BLOCK] ; key[2] movdqa xmmword [rsp+0*AES_BLOCK], xmm10 movdqa xmmword [rsp+1*AES_BLOCK], xmm11 movdqa xmmword [rsp+2*AES_BLOCK], xmm12 movdqa xmmword [rsp+3*AES_BLOCK], xmm13 movdqa xmmword [rsp+4*AES_BLOCK], xmm14 movdqa xmmword [rsp+5*AES_BLOCK], xmm15 add rsi, 6*AES_BLOCK align IPP_ALIGN_FACTOR .cipher_loop: sub rax, 2*AES_BLOCK ; dec loop counter aesdec xmm2, xmm1 ; regular rounds 3 - (last-2) aesdec xmm3, xmm1 aesdec xmm4, xmm1 aesdec xmm5, xmm1 aesdec xmm6, xmm1 aesdec xmm7, xmm1 movdqa xmm1, xmmword [r10+rax-1*AES_BLOCK] aesdec xmm2, xmm0 aesdec xmm3, xmm0 aesdec xmm4, xmm0 aesdec xmm5, xmm0 aesdec xmm6, xmm0 aesdec xmm7, xmm0 movdqa xmm0, xmmword [r10+rax-2*AES_BLOCK] jnz .cipher_loop movdqa xmm10, xmmword [rcx+r8] ; key[0] movdqa xmm15, xmm8 ; restore tweak value pshufd xmm9, xmm8, 5Fh ; {twk[1]:twk[1]:twk[3]:twk[3]} - auxiliary value movdqa xmm8, xmmword [rel ALPHA_MUL_CNT] ; mul constant ; ; last 6 rounds (5 regular rounds + irregular) ; merged together with next tweaks computation ; aesdec xmm2, xmm1 aesdec xmm3, xmm1 aesdec xmm4, xmm1 aesdec xmm5, xmm1 aesdec xmm6, xmm1 aesdec xmm7, xmm1 movdqa xmm1, xmmword [rcx+3*AES_BLOCK] INNER_MUL_X xmm10, xmm15, xmm11, xmm8, xmm9, xmm14 aesdec xmm2, xmm0 aesdec xmm3, xmm0 aesdec xmm4, xmm0 aesdec xmm5, xmm0 aesdec xmm6, xmm0 aesdec xmm7, xmm0 movdqa xmm0, xmmword [rcx+2*AES_BLOCK] INNER_MUL_X xmm11, xmm15, xmm12, xmm8, xmm9, xmm14 aesdec xmm2, xmm1 aesdec xmm3, xmm1 aesdec xmm4, xmm1 aesdec xmm5, xmm1 aesdec xmm6, xmm1 aesdec xmm7, xmm1 movdqa xmm1, xmmword [rcx+1*AES_BLOCK] INNER_MUL_X xmm12, xmm15, xmm13, xmm8, xmm9, xmm14 aesdec xmm2, xmm0 aesdec xmm3, xmm0 aesdec xmm4, xmm0 aesdec xmm5, xmm0 aesdec xmm6, xmm0 aesdec xmm7, xmm0 INNER_MUL_X xmm13, xmm15, xmm14, xmm8, xmm9, xmm14 aesdec xmm2, xmm1 aesdec xmm3, xmm1 aesdec xmm4, xmm1 aesdec xmm5, xmm1 aesdec xmm6, xmm1 aesdec xmm7, xmm1 INNER_MUL_X xmm14, xmm15, xmm0, xmm8, xmm9, xmm0 aesdeclast xmm2, xmmword [rsp] ; final irregular round aesdeclast xmm3, xmmword [rsp+1*AES_BLOCK] aesdeclast xmm4, xmmword [rsp+2*AES_BLOCK] aesdeclast xmm5, xmmword [rsp+3*AES_BLOCK] aesdeclast xmm6, xmmword [rsp+4*AES_BLOCK] aesdeclast xmm7, xmmword [rsp+5*AES_BLOCK] LAST_INNER_MUL_X xmm15, xmm8, xmm9 movdqa xmm8, xmm15 ; save tweak for next iteration pxor xmm15, xmm0 ; add key[0] movdqu xmmword [rdi+0*AES_BLOCK], xmm2 ; store output blocks movdqu xmmword [rdi+1*AES_BLOCK], xmm3 movdqu xmmword [rdi+2*AES_BLOCK], xmm4 movdqu xmmword [rdi+3*AES_BLOCK], xmm5 movdqu xmmword [rdi+4*AES_BLOCK], xmm6 movdqu xmmword [rdi+5*AES_BLOCK], xmm7 add rdi, 6*AES_BLOCK sub rdx, 6 jnc .blks_loop .short_input: add rdx, 6 jz .quit movdqa xmmword [rsp+0*AES_BLOCK], xmm10 ; save pre-computed twae movdqa xmmword [rsp+1*AES_BLOCK], xmm11 movdqa xmmword [rsp+2*AES_BLOCK], xmm12 movdqa xmmword [rsp+3*AES_BLOCK], xmm13 movdqa xmmword [rsp+4*AES_BLOCK], xmm14 movdqa xmmword [rsp+5*AES_BLOCK], xmm15 ;; ;; block-by-block processing ;; movdqa xmm0, xmmword [rcx+r8] ; key[0] pxor xmm0, xmmword [rcx] ; key[0] ^ key[last] xor rax, rax .single_blk_loop: movdqu xmm2, xmmword [rsi] ; input block movdqa xmm1, xmmword [rsp+rax] ; tweak ^ key[0] add rsi, AES_BLOCK pxor xmm2, xmm1 ; src[] ^tweak ^ key[0] pxor xmm1, xmm0 ; tweak ^ key[lasl] cmp r8, 12*16 ; switch according to number of rounds jl .key_128_s .key_256_s: aesdec xmm2, xmmword [rcx+9*AES_BLOCK+4*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK+3*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK+2*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK+1*AES_BLOCK] .key_128_s: aesdec xmm2, xmmword [rcx+9*AES_BLOCK-0*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-1*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-2*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-3*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-4*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-5*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-6*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-7*AES_BLOCK] aesdec xmm2, xmmword [rcx+9*AES_BLOCK-8*AES_BLOCK] aesdeclast xmm2, xmm1 movdqu xmmword [rdi], xmm2 ; output block add rdi, AES_BLOCK add rax, AES_BLOCK sub rdx, 1 jnz .single_blk_loop movdqa xmm10, xmmword [rsp+rax] ; tweak ^ key[0] .quit: pxor xmm10, xmmword [rcx+r8] ; remove key[0] movdqu xmmword [r9], xmm10 ; and save tweak value pxor xmm0, xmm0 pxor xmm1, xmm1 REST_XMM REST_GPR ret ENDFUNC cpAESDecryptXTS_AES_NI %endif ;; _AES_NI_ENABLING_ %endif ;;_IPP32E_Y8 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptcbce9as.asm000066400000000000000000000064441470420105600304510ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptCBC_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: RIJ128 CBC encryption ;* ;* void EncryptCBC_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len, ;* const Ipp8u* pIV) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAESEncryptCBC ;; align IPP_ALIGN_FACTOR IPPASM EncryptCBC_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 6 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d length: DWORD ; length (bytes) ;; r9 pIV: DWORD ; IV address %xdefine SC (4) %assign BYTES_PER_BLK (16) movsxd r8, r8d ; input length movdqu xmm0, oword [r9] ; IV align IPP_ALIGN_FACTOR ;; ;; pseudo-pipelined processing ;; .blks_loop: movdqu xmm1, oword [rdi] ; input block movdqa xmm4, oword [rcx] mov r9, rcx ; set pointer to the key material pxor xmm0, xmm1 ; src[] ^ iv pxor xmm0, xmm4 ; whitening movdqa xmm4, oword [r9+16] add r9, 16 mov r10, rdx ; counter depending on key length sub r10, 1 align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm0, xmm4 ; regular round movdqa xmm4, oword [r9+16] add r9, 16 dec r10 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round movdqu oword [rsi], xmm0 ; store output block add rdi, BYTES_PER_BLK ; advance pointers add rsi, BYTES_PER_BLK sub r8, BYTES_PER_BLK ; decrease counter jnz .blks_loop pxor xmm4, xmm4 REST_XMM REST_GPR ret ENDFUNC EncryptCBC_RIJ128_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptcfbe9as.asm000066400000000000000000000244731470420105600304560ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Encrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) %macro COPY_8U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_byte: mov %%tmp, byte [%%src+rcx] mov byte [%%dst+rcx], %%tmp add rcx, 1 cmp rcx, %%limit jl %%next_byte %endmacro %macro COPY_32U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_dword: mov %%tmp, dword [%%src+rcx] mov dword [%%dst+rcx], %%tmp add rcx, 4 cmp rcx, %%limit jl %%next_dword %endmacro %macro COPY_128U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_oword: movdqu %%tmp, oword [%%src+rcx] movdqu oword [%%dst+rcx], %%tmp add rcx, 16 cmp rcx, %%limit jl %%next_oword %endmacro segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: RIJ128 CFB encryption ;* ;* void EncryptCFB_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int cfbBlks, ;* int cfbSize, ;* const Ipp8u* pIV) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAESEncryptCFB ;; align IPP_ALIGN_FACTOR IPPASM EncryptCFB_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME (1+4+4)*16 USES_GPR rsi,rdi,r12,r15 USES_XMM COMP_ABI 7 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in bytes ;; r9d cfbSize: DWORD ; cfb blk size ;; [rsp+ARG_7] pIV BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) mov rax, [rsp+ARG_7] ; IV address movdqu xmm4, oword [rax] ; get IV movdqa oword [rsp+0*16], xmm4 ; into the stack movsxd r8, r8d ; length of stream movsxd r9, r9d ; cfb blk size mov r15, rcx ; save key material address ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [r15+rax*4-9*(SC)*4] ; AES-128 round keys ;; ;; processing ;; lea r10, [r9*BLKS_PER_LOOP] ; 4 cfb block .blks_loop: cmp r8, r10 cmovl r10, r8 COPY_8U {rsp+5*16}, rdi, r10, r11b ; move 1-4 input blocks to stack mov r12, r10 ; copy length to be processed xor r11, r11 ; index .single_blk: movdqu xmm0, oword [rsp+r11] ; get processing blocks pxor xmm0, oword [r15] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] movdqu xmm1, oword [rsp+5*16+r11] ; get src blocks from the stack pxor xmm0, xmm1 ; xor src movdqu oword [rsp+1*16+r11],xmm0 ;and store into the stack add r11, r9 ; advance index sub r12, r9 ; decrease length jg .single_blk COPY_8U rsi, {rsp+1*16}, r10, r11b ; move 1-4 blocks to output movdqu xmm0, oword [rsp+r10]; update IV movdqa oword [rsp], xmm0 add rdi, r10 add rsi, r10 sub r8, r10 jg .blks_loop REST_XMM REST_GPR ret ENDFUNC EncryptCFB_RIJ128_AES_NI align IPP_ALIGN_FACTOR IPPASM EncryptCFB32_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME (1+4+4)*16 USES_GPR rsi,rdi,r12,r15 USES_XMM COMP_ABI 7 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in bytes ;; r9d cfbSize: DWORD ; cfb blk size ;; [rsp+ARG_7] pIV BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) mov rax, [rsp+ARG_7] ; IV address movdqu xmm4, oword [rax] ; get IV movdqa oword [rsp+0*16], xmm4 ; into the stack movsxd r8, r8d ; length of stream movsxd r9, r9d ; cfb blk size mov r15, rcx ; save key material address ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [r15+rax*4-9*(SC)*4] ; AES-128 round keys ;; ;; processing ;; lea r10, [r9*BLKS_PER_LOOP] ; 4 cfb block .blks_loop: cmp r8, r10 cmovl r10, r8 COPY_32U {rsp+5*16}, rdi, r10, r11d ; move 1-4 input blocks to stack mov r12, r10 ; copy length to be processed xor r11, r11 ; index .single_blk: movdqu xmm0, oword [rsp+r11] ; get processing blocks pxor xmm0, oword [r15] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] movdqu xmm1, oword [rsp+5*16+r11] ; get src blocks from the stack pxor xmm0, xmm1 ; xor src movdqu oword [rsp+1*16+r11],xmm0 ;and store into the stack add r11, r9 ; advance index sub r12, r9 ; decrease length jg .single_blk COPY_32U rsi, {rsp+1*16}, r10, r11d ; move 1-4 blocks to output movdqu xmm0, oword [rsp+r10]; update IV movdqa oword [rsp], xmm0 add rdi, r10 add rsi, r10 sub r8, r10 jg .blks_loop REST_XMM REST_GPR ret ENDFUNC EncryptCFB32_RIJ128_AES_NI align IPP_ALIGN_FACTOR IPPASM EncryptCFB128_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 6 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in bytes ;; r9d pIV: BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) movdqu xmm0, oword [r9] ; get IV movsxd r8, r8d ; length of stream movsxd r9, r9d ; cfb blk size ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [rcx+rax*4-9*(SC)*4] ; AES-128 round keys ;; ;; processing ;; .blks_loop: pxor xmm0, oword [rcx] ; whitening movdqu xmm1, oword [rdi] ; input blocks cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] pxor xmm0, xmm1 ; xor src movdqu oword [rsi],xmm0 ;and store into the dst add rdi, 16 add rsi, 16 sub r8, 16 jg .blks_loop REST_XMM REST_GPR ret ENDFUNC EncryptCFB128_RIJ128_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptctr128pipee9as.asm000066400000000000000000000331341470420105600316170ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptCTR_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: pipelined RIJ128 CTR128 encryption/decryption ;* ;* ;* void EncryptStreamCTR32_AES_NI(const Ipp8u* inpBlk, ;* Ipp8u* outBlk, ;* int nr, ;* const Ipp8u* pRKey, ;* int length, ;* Ipp8u* pIV) ;*************************************************************** %assign AES_BLOCK (16) align IPP_ALIGN_FACTOR IPPASM EncryptStreamCTR32_AES_NI,PUBLIC %assign LOCAL_FRAME sizeof(oword)*8 USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7,xmm8,xmm9 COMP_ABI 6 ;; rdi: pInpBlk: BYTE ; pointer to the input ;; rsi: pOutBlk: BYTE ; pointer to the output ;; rdx: nr: DWORD ; number of rounds ;; rcx pKey: BYTE ; key material address ;; r8d length: DWORD ; length of the input ;; r9 pIV : BYTE ; pointer to the iv (BE string counter representation) %xdefine SC (4) movdqu xmm0, oword [r9] ; input IV movsxd r8, r8d ; length lea r11, [r8+AES_BLOCK-1] ; r11 = blocks = ceil(len/AES_BLOCK) shr r11, 4 mov rax, qword [r9+sizeof(qword)] ; input IV mov rbx, qword [r9] bswap rax bswap rbx mov r10d, eax ; save ctr32 add rax, r11 ; +blocks adc rbx, 0 bswap rax bswap rbx mov qword [r9+sizeof(qword)], rax ; update IV mov qword [r9], rbx mov r11d, dword [rcx+AES_BLOCK-sizeof(dword)] ; get whitening keys corresponding to ctr32 pxor xmm0, oword [rcx] ; apply whitening keys add rcx, AES_BLOCK ; mov pointer to the round keys movdqa oword [rsp+0*AES_BLOCK], xmm0 ; store unchanged part of ctr128 movdqa oword [rsp+1*AES_BLOCK], xmm0 movdqa oword [rsp+2*AES_BLOCK], xmm0 movdqa oword [rsp+3*AES_BLOCK], xmm0 movdqa oword [rsp+4*AES_BLOCK], xmm0 movdqa oword [rsp+5*AES_BLOCK], xmm0 movdqa oword [rsp+6*AES_BLOCK], xmm0 movdqa oword [rsp+7*AES_BLOCK], xmm0 mov r9, rsp cmp r8, AES_BLOCK ; test %if single block processed jle .short123_input movdqa xmm1, xmm0 movdqa xmm2, xmm0 movdqa xmm3, xmm0 lea ebx, [r10d+1] ; init ctr32+1 lea eax, [r10d+2] ; init ctr32+2 lea r9d, [r10d+3] ; init ctr32+3 bswap ebx bswap eax bswap r9d xor ebx, r11d pinsrd xmm1, ebx, 3 xor eax, r11d pinsrd xmm2, eax, 3 xor r9d, r11d pinsrd xmm3, r9d, 3 movdqa oword [rsp+1*AES_BLOCK], xmm1 movdqa oword [rsp+2*AES_BLOCK], xmm2 movdqa oword [rsp+3*AES_BLOCK], xmm3 mov r9, rsp movdqa xmm4, oword [rcx+0*AES_BLOCK] ; pre load operation's keys movdqa xmm5, oword [rcx+1*AES_BLOCK] cmp r8, (4*AES_BLOCK) ; test %if 1-2-3 blocks processed jl .short123_input jz .short_input lea eax, [r10d+4] ; init ctr32+4 lea ebx, [r10d+5] ; init ctr32+5 bswap eax bswap ebx xor ebx, r11d xor eax, r11d mov dword [rsp+4*AES_BLOCK+AES_BLOCK-sizeof(dword)], eax mov dword [rsp+5*AES_BLOCK+AES_BLOCK-sizeof(dword)], ebx lea eax, [r10d+6] ; init ctr32+6 lea ebx, [r10d+7] ; init ctr32+7 bswap eax bswap ebx xor eax, r11d xor ebx, r11d mov dword [rsp+6*AES_BLOCK+AES_BLOCK-sizeof(dword)], eax mov dword [rsp+7*AES_BLOCK+AES_BLOCK-sizeof(dword)], ebx cmp r8, (8*AES_BLOCK) jl .short_input ;; ;; 8-blocks processing alaivalbe ;; sub rsp, sizeof(oword)*4 ; save xmm registers movdqa oword [rsp+0*sizeof(oword)], xmm10 movdqa oword [rsp+1*sizeof(oword)], xmm11 movdqa oword [rsp+2*sizeof(oword)], xmm12 movdqa oword [rsp+3*sizeof(oword)], xmm13 push rcx ; store pointer to the key material push rdx ; store number of rounds sub r8, (8*AES_BLOCK) align IPP_ALIGN_FACTOR .blk8_loop: ; movdqa xmm4, oword [rcx+0*AES_BLOCK] ; pre load operation's keys ; movdqa xmm5, oword [rcx+1*AES_BLOCK] add rcx, (2*AES_BLOCK) add r10d, 8 ; next counter value sub rdx, 4 ; rounds -= 4 movdqa xmm6, oword [r9+4*AES_BLOCK] ; load current ctr32 movdqa xmm7, oword [r9+5*AES_BLOCK] movdqa xmm8, oword [r9+6*AES_BLOCK] movdqa xmm9, oword [r9+7*AES_BLOCK] mov eax, r10d ; improve next 2 ctr32 values in advance aesenc xmm0, xmm4 lea ebx, [r10d+1] aesenc xmm1, xmm4 bswap eax aesenc xmm2, xmm4 bswap ebx aesenc xmm3, xmm4 xor eax, r11d aesenc xmm6, xmm4 xor ebx, r11d aesenc xmm7, xmm4 mov dword [r9+0*AES_BLOCK+AES_BLOCK-sizeof(dword)], eax aesenc xmm8, xmm4 mov dword [r9+1*AES_BLOCK+AES_BLOCK-sizeof(dword)], ebx aesenc xmm9, xmm4 movdqa xmm4, oword [rcx] ; pre load operation's keys lea eax, [r10d+2] ; improve next 2 ctr32 values in advance aesenc xmm0, xmm5 lea ebx, [r10d+3] aesenc xmm1, xmm5 bswap eax aesenc xmm2, xmm5 bswap ebx aesenc xmm3, xmm5 xor eax, r11d aesenc xmm6, xmm5 xor ebx, r11d aesenc xmm7, xmm5 mov dword [r9+2*AES_BLOCK+AES_BLOCK-sizeof(dword)], eax aesenc xmm8, xmm5 mov dword [r9+3*AES_BLOCK+AES_BLOCK-sizeof(dword)], ebx aesenc xmm9, xmm5 movdqa xmm5, oword [rcx+AES_BLOCK] ; pre load operation's keys align IPP_ALIGN_FACTOR .cipher_loop: add rcx, (2*AES_BLOCK) sub rdx, 2 aesenc xmm0, xmm4 aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 aesenc xmm6, xmm4 aesenc xmm7, xmm4 aesenc xmm8, xmm4 aesenc xmm9, xmm4 movdqa xmm4, oword [rcx] ; pre load operation's keys aesenc xmm0, xmm5 aesenc xmm1, xmm5 aesenc xmm2, xmm5 aesenc xmm3, xmm5 aesenc xmm6, xmm5 aesenc xmm7, xmm5 aesenc xmm8, xmm5 aesenc xmm9, xmm5 movdqa xmm5, oword [rcx+AES_BLOCK] ; pre load operation's keys jnz .cipher_loop lea eax, [r10d+4] ; improve next 2 ctr32 values in advance aesenc xmm0, xmm4 lea ebx, [r10d+5] aesenc xmm1, xmm4 bswap eax aesenc xmm2, xmm4 bswap ebx aesenc xmm3, xmm4 xor eax, r11d aesenc xmm6, xmm4 xor ebx, r11d aesenc xmm7, xmm4 mov dword [r9+4*AES_BLOCK+AES_BLOCK-sizeof(dword)], eax aesenc xmm8, xmm4 mov dword [r9+5*AES_BLOCK+AES_BLOCK-sizeof(dword)], ebx aesenc xmm9, xmm4 lea eax, [r10d+6] ; improve next 2 ctr32 values in advance aesenclast xmm0, xmm5 lea ebx, [r10d+7] aesenclast xmm1, xmm5 bswap eax aesenclast xmm2, xmm5 bswap ebx aesenclast xmm3, xmm5 xor eax, r11d aesenclast xmm6, xmm5 xor ebx, r11d aesenclast xmm7, xmm5 mov dword [r9+6*AES_BLOCK+AES_BLOCK-sizeof(dword)], eax aesenclast xmm8, xmm5 mov dword [r9+7*AES_BLOCK+AES_BLOCK-sizeof(dword)], ebx aesenclast xmm9, xmm5 movdqu xmm10, oword [rdi+0*AES_BLOCK] movdqu xmm11, oword [rdi+1*AES_BLOCK] movdqu xmm12, oword [rdi+2*AES_BLOCK] movdqu xmm13, oword [rdi+3*AES_BLOCK] pxor xmm0, xmm10 pxor xmm1, xmm11 pxor xmm2, xmm12 pxor xmm3, xmm13 movdqu oword [rsi+0*AES_BLOCK], xmm0 movdqu oword [rsi+1*AES_BLOCK], xmm1 movdqu oword [rsi+2*AES_BLOCK], xmm2 movdqu oword [rsi+3*AES_BLOCK], xmm3 movdqu xmm10, oword [rdi+4*AES_BLOCK] movdqu xmm11, oword [rdi+5*AES_BLOCK] movdqu xmm12, oword [rdi+6*AES_BLOCK] movdqu xmm13, oword [rdi+7*AES_BLOCK] pxor xmm6, xmm10 pxor xmm7, xmm11 pxor xmm8, xmm12 pxor xmm9, xmm13 movdqu oword [rsi+4*AES_BLOCK], xmm6 movdqu oword [rsi+5*AES_BLOCK], xmm7 movdqu oword [rsi+6*AES_BLOCK], xmm8 movdqu oword [rsi+7*AES_BLOCK], xmm9 mov rcx, qword [rsp+sizeof(qword)] ; restore pointer to the key material mov rdx, qword [rsp] ; restore number of rounds movdqa xmm0, oword [r9+0*AES_BLOCK] ; load next current ctr32 movdqa xmm1, oword [r9+1*AES_BLOCK] movdqa xmm2, oword [r9+2*AES_BLOCK] movdqa xmm3, oword [r9+3*AES_BLOCK] movdqa xmm4, oword [rcx+0*AES_BLOCK] ; pre load operation's keys movdqa xmm5, oword [rcx+1*AES_BLOCK] ; pre load operation's keys add rdi, 8*AES_BLOCK add rsi, 8*AES_BLOCK sub r8, 8*AES_BLOCK jge .blk8_loop pop rdx pop rcx movdqa xmm10,oword [rsp+0*sizeof(oword)] ; resrore xmm registers movdqa xmm11,oword [rsp+1*sizeof(oword)] movdqa xmm12,oword [rsp+2*sizeof(oword)] movdqa xmm13,oword [rsp+3*sizeof(oword)] add rsp, sizeof(oword)*4 ; release stack add r8, 8*AES_BLOCK jz .quit align IPP_ALIGN_FACTOR .short_input: ;; ;; test %if 4-blocks processing alaivalbe ;; cmp r8, (4*AES_BLOCK) jl .short123_input mov rbx, rcx ; pointer to the key material lea r10, [rdx-2] ; rounds -= 2 align IPP_ALIGN_FACTOR .cipher_loop4: add rbx, (2*AES_BLOCK) sub r10, 2 aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [rbx] ; pre load operation's keys aesenc xmm0, xmm5 aesenc xmm1, xmm5 aesenc xmm2, xmm5 aesenc xmm3, xmm5 movdqa xmm5, oword [rbx+AES_BLOCK] ; pre load operation's keys jnz .cipher_loop4 movdqu xmm6, oword [rdi+0*AES_BLOCK] movdqu xmm7, oword [rdi+1*AES_BLOCK] movdqu xmm8, oword [rdi+2*AES_BLOCK] movdqu xmm9, oword [rdi+3*AES_BLOCK] add rdi, (4*AES_BLOCK) aesenc xmm0, xmm4 aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 aesenclast xmm0, xmm5 aesenclast xmm1, xmm5 aesenclast xmm2, xmm5 aesenclast xmm3, xmm5 pxor xmm0, xmm6 movdqu oword [rsi+0*AES_BLOCK], xmm0 pxor xmm1, xmm7 movdqu oword [rsi+1*AES_BLOCK], xmm1 pxor xmm2, xmm8 movdqu oword [rsi+2*AES_BLOCK], xmm2 pxor xmm3, xmm9 movdqu oword [rsi+3*AES_BLOCK], xmm3 add rsi, (4*AES_BLOCK) add r9, (4*AES_BLOCK) sub r8, (4*AES_BLOCK) jz .quit ;; ;; block-by-block processing ;; .short123_input: ; get actual address of key material: pRKeys += (nr-9) * SC lea rbx,[rdx*4] lea rbx, [rcx+rbx*4-10*(SC)*4] ; AES-128 round keys .single_blk: movdqa xmm0, oword [r9] ; counter from the stack add r9, AES_BLOCK cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0,oword [rbx-4*4*SC] aesenc xmm0,oword [rbx-3*4*SC] .key_192_s: aesenc xmm0,oword [rbx-2*4*SC] aesenc xmm0,oword [rbx-1*4*SC] .key_128_s: aesenc xmm0,oword [rbx+0*4*SC] aesenc xmm0,oword [rbx+1*4*SC] aesenc xmm0,oword [rbx+2*4*SC] aesenc xmm0,oword [rbx+3*4*SC] aesenc xmm0,oword [rbx+4*4*SC] aesenc xmm0,oword [rbx+5*4*SC] aesenc xmm0,oword [rbx+6*4*SC] aesenc xmm0,oword [rbx+7*4*SC] aesenc xmm0,oword [rbx+8*4*SC] aesenclast xmm0,oword [rbx+9*4*SC] cmp r8, AES_BLOCK ; test %if partial bloak jl .partial_block movdqu xmm1, oword [rdi] ; input data block add rdi, AES_BLOCK pxor xmm0, xmm1 ; output block movdqu oword [rsi], xmm0 ; save output block add rsi, AES_BLOCK sub r8, AES_BLOCK jz .quit jmp .single_blk .partial_block: pextrb eax, xmm0, 0 psrldq xmm0, 1 movzx edx, byte [rdi] inc rdi xor rax, rdx mov byte [rsi], al inc rsi dec r8 jnz .partial_block .quit: pxor xmm4, xmm4 pxor xmm5, xmm5 REST_XMM REST_GPR ret ENDFUNC EncryptStreamCTR32_AES_NI %endif ;; _IPP32E_Y8 %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptctrpipee9as.asm000066400000000000000000000174531470420105600313720ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptCTR_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR u128_str DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: pipelined RIJ128 CTR encryption/decryption ;* ;* void EncryptCTR_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int length, ;* Ipp8u* pCtrValue, ;* Ipp8u* pCtrBitMask) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAESEncryptCTR ;; align IPP_ALIGN_FACTOR IPPASM EncryptCTR_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,rbx USES_XMM xmm6,xmm7,xmm8,xmm9 COMP_ABI 7 ;; rdi: pInpBlk: DWORD, ; pointer to the input ;; rsi: pOutBlk: DWORD, ; pointer to the output ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d length: DWORD ; length of the input ;; r9 pCtrValue: BYTED ; pointer to the Counter ;; [rsp+ARG_7] pCtrBitMask: BYTE ; pointer to the Counter Bit Mask %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) mov rax, [rsp+ARG_7] movdqu xmm8, oword [rax] ; counter bit mask movdqu xmm0, oword [r9] ; initial counter movdqa xmm9, xmm8 pandn xmm9, xmm0 ; counter template ;; ;; init counter ;; mov rbx, qword [r9] ; initial counter (BE) mov rax, qword [r9+8] bswap rbx bswap rax movsxd r8, r8d sub r8, BYTES_PER_LOOP jl .short_input ;; ;; pipelined processing ;; .blks_loop: movdqa xmm4,oword [rel u128_str] pinsrq xmm0, rax, 0 ; get counter value pinsrq xmm0, rbx, 1 pshufb xmm0, xmm4 ; convert int the octet string pand xmm0, xmm8 ; select counter bits por xmm0, xmm9 ; add unchanged bits add rax, 1 adc rbx, 0 pinsrq xmm1, rax, 0 pinsrq xmm1, rbx, 1 pshufb xmm1, xmm4 pand xmm1, xmm8 por xmm1, xmm9 add rax, 1 adc rbx, 0 pinsrq xmm2, rax, 0 pinsrq xmm2, rbx, 1 pshufb xmm2, xmm4 pand xmm2, xmm8 por xmm2, xmm9 add rax, 1 adc rbx, 0 pinsrq xmm3, rax, 0 pinsrq xmm3, rbx, 1 pshufb xmm3, xmm4 pand xmm3, xmm8 por xmm3, xmm9 movdqa xmm4, oword [rcx] mov r10, rcx ; set pointer to the key material pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [r10+16] add r10, 16 mov r11, rdx ; counter depending on key length sub r11, 1 .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [r10+16] add r10, 16 dec r11 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round aesenclast xmm1, xmm4 aesenclast xmm2, xmm4 aesenclast xmm3, xmm4 movdqu xmm4, oword [rdi+0*BYTES_PER_BLK] ; 4 input blocks movdqu xmm5, oword [rdi+1*BYTES_PER_BLK] movdqu xmm6, oword [rdi+2*BYTES_PER_BLK] movdqu xmm7, oword [rdi+3*BYTES_PER_BLK] add rdi, BYTES_PER_LOOP pxor xmm0, xmm4 ; 4 output blocks movdqu oword [rsi+0*BYTES_PER_BLK], xmm0 pxor xmm1, xmm5 movdqu oword [rsi+1*BYTES_PER_BLK], xmm1 pxor xmm2, xmm6 movdqu oword [rsi+2*BYTES_PER_BLK], xmm2 pxor xmm3, xmm7 movdqu oword [rsi+3*BYTES_PER_BLK], xmm3 add rax, 1 ; advance counter adc rbx, 0 add rsi, BYTES_PER_LOOP sub r8, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add r8, BYTES_PER_LOOP jz .quit ; get actual address of key material: pRKeys += (nr-9) * SC lea r10,[rdx*4] lea r10, [rcx+r10*4-9*(SC)*4] ; AES-128 round keys .single_blk_loop: pinsrq xmm0, rax, 0 ; get counter value pinsrq xmm0, rbx, 1 pshufb xmm0, [rel u128_str] ; convert int the octet string pand xmm0, xmm8 ; select counter bits por xmm0, xmm9 ; add unchanged bits pxor xmm0, oword [rcx] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0,oword [r10-4*4*SC] aesenc xmm0,oword [r10-3*4*SC] .key_192_s: aesenc xmm0,oword [r10-2*4*SC] aesenc xmm0,oword [r10-1*4*SC] .key_128_s: aesenc xmm0,oword [r10+0*4*SC] aesenc xmm0,oword [r10+1*4*SC] aesenc xmm0,oword [r10+2*4*SC] aesenc xmm0,oword [r10+3*4*SC] aesenc xmm0,oword [r10+4*4*SC] aesenc xmm0,oword [r10+5*4*SC] aesenc xmm0,oword [r10+6*4*SC] aesenc xmm0,oword [r10+7*4*SC] aesenc xmm0,oword [r10+8*4*SC] aesenclast xmm0,oword [r10+9*4*SC] add rax, 1 ; update counter adc rbx, 0 sub r8, BYTES_PER_BLK jl .partial_block movdqu xmm4, oword [rdi] ; input block pxor xmm0, xmm4 ; output block movdqu oword [rsi], xmm0 ; save output block add rdi, BYTES_PER_BLK add rsi, BYTES_PER_BLK cmp r8, 0 jz .quit jmp .single_blk_loop .partial_block: add r8, BYTES_PER_BLK .partial_block_loop: pextrb r10d, xmm0, 0 psrldq xmm0, 1 movzx r11d, byte [rdi] xor r10, r11 mov byte [rsi], r10b inc rdi inc rsi dec r8 jnz .partial_block_loop .quit: pinsrq xmm0, rax, 0 ; get counter value pinsrq xmm0, rbx, 1 pshufb xmm0, [rel u128_str] ; convert int the octet string pand xmm0, xmm8 ; select counter bits por xmm0, xmm9 ; add unchanged bits movdqu oword [r9], xmm0 ; return updated counter REST_XMM REST_GPR ret ENDFUNC EncryptCTR_RIJ128pipe_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encrypte9as.asm000066400000000000000000000065111470420105600277740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; Encrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: single block RIJ128 Cipher ;* ;* void Encrypt_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* const Ipp32u Tables[][256]) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsRijndael128EncryptECB ;; Caller = ippsRijndael128EncryptCBC ;; Caller = ippsRijndael128EncryptCFB ;; Caller = ippsRijndael128DecryptCFB ;; ;; Caller = ippsDAARijndael128Update ;; Caller = ippsDAARijndael128Final ;; Caller = ippsDAARijndael128MessageDigest ;; align IPP_ALIGN_FACTOR IPPASM Encrypt_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 4 ;; rdi: pInpBlk: DWORD, ; input block address ;; rsi: pOutBlk: DWORD, ; output block address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address %xdefine SC (4) movdqu xmm0, oword [rdi] ; input block ;;whitening pxor xmm0, oword [rcx] ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rcx,[rcx+rax*4-9*(SC)*4] ; AES-128-keys cmp rdx,12 ; switch according to number of rounds jl .key_128 jz .key_192 ;; ;; regular rounds ;; .key_256: aesenc xmm0,oword [rcx-4*4*SC] aesenc xmm0,oword [rcx-3*4*SC] .key_192: aesenc xmm0,oword [rcx-2*4*SC] aesenc xmm0,oword [rcx-1*4*SC] .key_128: aesenc xmm0,oword [rcx+0*4*SC] aesenc xmm0,oword [rcx+1*4*SC] aesenc xmm0,oword [rcx+2*4*SC] aesenc xmm0,oword [rcx+3*4*SC] aesenc xmm0,oword [rcx+4*4*SC] aesenc xmm0,oword [rcx+5*4*SC] aesenc xmm0,oword [rcx+6*4*SC] aesenc xmm0,oword [rcx+7*4*SC] aesenc xmm0,oword [rcx+8*4*SC] ;; ;; last rounds ;; aesenclast xmm0,oword [rcx+9*4*SC] movdqu oword [rsi], xmm0 ; output block REST_XMM REST_GPR ret ENDFUNC Encrypt_RIJ128_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptecbpipee9as.asm000066400000000000000000000116221470420105600313230ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Cipher function ; ; Content: ; EncryptECB_RIJ128pipe_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: pipelined RIJ128 ECB encryption ;* ;* void EncryptECB_RIJ128pipe_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int len) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsAESEncryptECB ;; align IPP_ALIGN_FACTOR IPPASM EncryptECB_RIJ128pipe_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 5 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d length: DWORD ; length (bytes) %xdefine SC (4) %assign BLKS_PER_LOOP (4) %assign BYTES_PER_BLK (16) %assign BYTES_PER_LOOP (BYTES_PER_BLK*BLKS_PER_LOOP) movsxd r8, r8d sub r8, BYTES_PER_LOOP jl .short_input ;; ;; pipelined processing ;; align IPP_ALIGN_FACTOR .blks_loop: movdqa xmm4, oword [rcx] mov r9, rcx ; set pointer to the key material movdqu xmm0, oword [rdi+0*16] ; get input blocks movdqu xmm1, oword [rdi+1*16] movdqu xmm2, oword [rdi+2*16] movdqu xmm3, oword [rdi+3*16] add rdi, BYTES_PER_LOOP pxor xmm0, xmm4 ; whitening pxor xmm1, xmm4 pxor xmm2, xmm4 pxor xmm3, xmm4 movdqa xmm4, oword [r9+16] add r9, 16 mov r10, rdx ; counter depending on key length sub r10, 1 align IPP_ALIGN_FACTOR .cipher_loop: aesenc xmm0, xmm4 ; regular round aesenc xmm1, xmm4 aesenc xmm2, xmm4 aesenc xmm3, xmm4 movdqa xmm4, oword [r9+16] add r9, 16 dec r10 jnz .cipher_loop aesenclast xmm0, xmm4 ; irregular round movdqu oword [rsi+0*16], xmm0 ; store output blocks aesenclast xmm1, xmm4 movdqu oword [rsi+1*16], xmm1 aesenclast xmm2, xmm4 movdqu oword [rsi+2*16], xmm2 aesenclast xmm3, xmm4 movdqu oword [rsi+3*16], xmm3 add rsi, BYTES_PER_LOOP sub r8, BYTES_PER_LOOP jge .blks_loop ;; ;; block-by-block processing ;; .short_input: add r8, BYTES_PER_LOOP jz .quit ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea r9, [rcx+rax*4-9*(SC)*4] ; AES-128 round keys align IPP_ALIGN_FACTOR .single_blk_loop: movdqu xmm0, oword [rdi] ; get input block add rdi, BYTES_PER_BLK pxor xmm0, oword [rcx] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s .key_256_s: aesenc xmm0,oword [r9-4*4*SC] aesenc xmm0,oword [r9-3*4*SC] .key_192_s: aesenc xmm0,oword [r9-2*4*SC] aesenc xmm0,oword [r9-1*4*SC] .key_128_s: aesenc xmm0,oword [r9+0*4*SC] aesenc xmm0,oword [r9+1*4*SC] aesenc xmm0,oword [r9+2*4*SC] aesenc xmm0,oword [r9+3*4*SC] aesenc xmm0,oword [r9+4*4*SC] aesenc xmm0,oword [r9+5*4*SC] aesenc xmm0,oword [r9+6*4*SC] aesenc xmm0,oword [r9+7*4*SC] aesenc xmm0,oword [r9+8*4*SC] aesenclast xmm0,oword [r9+9*4*SC] movdqu oword [rsi], xmm0 ; save output block add rsi, BYTES_PER_BLK sub r8, BYTES_PER_BLK jnz .single_blk_loop .quit: pxor xmm4, xmm4 REST_XMM REST_GPR ret ENDFUNC EncryptECB_RIJ128pipe_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptofbe9as.asm000066400000000000000000000163201470420105600304620ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Inverse Cipher function ; ; Content: ; Encrypt_RIJ128_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) %macro COPY_8U 4.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%limit %3 %xdefine %%tmp %4 xor rcx, rcx %%next_byte: mov %%tmp, byte [%%src+rcx] mov byte [%%dst+rcx], %%tmp add rcx, 1 cmp rcx, %%limit jl %%next_byte %endmacro segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: RIJ128 OFB encryption ;* ;* void EncryptOFB_RIJ128_AES_NI(const Ipp32u* inpBlk, ;* Ipp32u* outBlk, ;* int nr, ;* const Ipp32u* pRKey, ;* int length, ;* int ofbBlks, ;* const Ipp8u* pIV) ;*************************************************************** ;; ;; Lib = Y8 ;; ;; Caller = ippsRijndael128DecryptCFB ;; align IPP_ALIGN_FACTOR IPPASM EncryptOFB_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME (1+1+4+4)*16 USES_GPR rsi,rdi,r12,r15 USES_XMM COMP_ABI 7 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in bytes ;; r9d cfbSize: DWORD ; cfb blk size ;; [rsp+ARG_7] pIV BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) %xdefine tmpInp [rsp] %xdefine tmpOut [rsp+16*1] %xdefine locDst [rsp+16*2] %xdefine locSrc [rsp+16*6] mov rax, [rsp+ARG_7] ; IV address movdqu xmm0, oword [rax] ; get IV movdqa oword [rsp+0*16], xmm0 ; into the stack movsxd r8, r8d ; length of stream movsxd r9, r9d ; cfb blk size mov r15, rcx ; save key material address ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [r15+rax*4-9*(SC)*4] ; AES-128 round keys ;; ;; processing ;; lea r10, [r9*BLKS_PER_LOOP] ; 4 cfb block align IPP_ALIGN_FACTOR .blks_loop: cmp r8, r10 cmovl r10, r8 COPY_8U {rsp+6*16}, rdi, r10, r11b ; move 1-4 input blocks to stack mov r12, r10 ; copy length to be processed xor r11, r11 ; index align IPP_ALIGN_FACTOR .single_blk: pxor xmm0, oword [r15] ; whitening cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] movdqa oword [rsp+1*16], xmm0 ; save chipher output movdqu xmm1, oword [rsp+6*16+r11] ; get src blocks from the stack pxor xmm1, xmm0 ; xor src movdqu oword [rsp+2*16+r11],xmm1 ;and store into the stack movdqu xmm0, oword [rsp+r9] ; update cipher input (IV) movdqa oword [rsp], xmm0 add r11, r9 ; advance index sub r12, r9 ; decrease length jg .single_blk COPY_8U rsi, {rsp+2*16}, r10, r11b ; move 1-4 blocks to output add rdi, r10 add rsi, r10 sub r8, r10 jg .blks_loop mov rax, [rsp+ARG_7] ; IV address movdqa xmm0, oword [rsp] ; update IV before return movdqu oword [rax], xmm0 REST_XMM REST_GPR ret ENDFUNC EncryptOFB_RIJ128_AES_NI align IPP_ALIGN_FACTOR IPPASM EncryptOFB128_RIJ128_AES_NI,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM COMP_ABI 6 ;; rdi: pInpBlk: DWORD, ; input blocks address ;; rsi: pOutBlk: DWORD, ; output blocks address ;; rdx: nr: DWORD, ; number of rounds ;; rcx pKey: DWORD ; key material address ;; r8d cfbBlks: DWORD ; length of stream in bytes ;; r9 pIV: BYTE ; pointer to the IV %xdefine SC (4) %assign BLKS_PER_LOOP (4) movdqu xmm0, oword [r9] ; get IV movsxd r8, r8d ; length of stream ; get actual address of key material: pRKeys += (nr-9) * SC lea rax,[rdx*4] lea rax, [rcx+rax*4-9*(SC)*4] ; AES-128 round keys ;; ;; processing ;; .blks_loop: pxor xmm0, oword [rcx] ; whitening movdqu xmm1, oword [rdi] ; input blocks cmp rdx,12 ; switch according to number of rounds jl .key_128_s jz .key_192_s ; do encryption .key_256_s: aesenc xmm0, oword [rax-4*4*SC] aesenc xmm0, oword [rax-3*4*SC] .key_192_s: aesenc xmm0, oword [rax-2*4*SC] aesenc xmm0, oword [rax-1*4*SC] .key_128_s: aesenc xmm0, oword [rax+0*4*SC] aesenc xmm0, oword [rax+1*4*SC] aesenc xmm0, oword [rax+2*4*SC] aesenc xmm0, oword [rax+3*4*SC] aesenc xmm0, oword [rax+4*4*SC] aesenc xmm0, oword [rax+5*4*SC] aesenc xmm0, oword [rax+6*4*SC] aesenc xmm0, oword [rax+7*4*SC] aesenc xmm0, oword [rax+8*4*SC] aesenclast xmm0, oword [rax+9*4*SC] pxor xmm1, xmm0 ; xor src movdqu oword [rsi],xmm1 ;and store into the dst add rdi, 16 add rsi, 16 sub r8, 16 jg .blks_loop movdqu oword [r9], xmm0 ; update IV before return REST_XMM REST_GPR ret ENDFUNC EncryptOFB128_RIJ128_AES_NI %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128encryptxtse9as.asm000066400000000000000000000254571470420105600305450ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2016 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; AES functions ; ; Content: ; cpAESEncryptXTS_AES_NI() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_ON_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_Y8) segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ALPHA_MUL_CNT dq 00000000000000087h, 00000000000000001h segment .text align=IPP_ALIGN_FACTOR ;*************************************************************** ;* Purpose: AES-XTS encryption ;* ;* void cpAESEncryptXTS_AES_NI(Ipp8u* outBlk, ;* const Ipp8u* inpBlk, ;* int length, ;* const Ipp8u* pRKey, ;* int nr, ;* Ipp8u* pTweak) ;*************************************************************** ;; ;; key = ks[0] ;; mul_cnt = {0x0000000000000001:0x0000000000000087} ;; returns: ;; ktwk = twk^key ;; twk = twk*alpha ;; twk2= twk2 *2 - auxiliary ;; %macro OUTER_MUL_X 6.nolist %xdefine %%ktwk %1 %xdefine %%twk %2 %xdefine %%key %3 %xdefine %%mul_cnt %4 %xdefine %%twk2 %5 %xdefine %%mask %6 movdqa %%mask, %%twk2 paddd %%twk2, %%twk2 movdqa %%ktwk, %%twk psrad %%mask, 31 paddq %%twk, %%twk pand %%mask, %%mul_cnt pxor %%ktwk, %%key pxor %%twk, %%mask %endmacro %macro LAST_OUTER_MUL_X 5.nolist %xdefine %%ktwk %1 %xdefine %%twk %2 %xdefine %%key %3 %xdefine %%mul_cnt %4 %xdefine %%twk2 %5 movdqa %%ktwk, %%twk psrad %%twk2, 31 paddq %%twk, %%twk pand %%twk2, %%mul_cnt pxor %%ktwk, %%key pxor %%twk, %%twk2 %endmacro %macro INNER_MUL_X 6.nolist %xdefine %%ktwk %1 %xdefine %%twk %2 %xdefine %%key %3 %xdefine %%mul_cnt %4 %xdefine %%twk2 %5 %xdefine %%mask %6 movdqa %%mask, %%twk2 paddd %%twk2, %%twk2 psrad %%mask, 31 paddq %%twk, %%twk pand %%mask, %%mul_cnt pxor %%twk, %%mask %ifnidn %%key,%%ktwk movdqa %%key, %%ktwk %endif pxor %%ktwk, %%twk %endmacro %macro LAST_INNER_MUL_X 3.nolist %xdefine %%twk %1 %xdefine %%mul_cnt %2 %xdefine %%twk2 %3 psrad %%twk2, 31 paddq %%twk, %%twk pand %%twk2, %%mul_cnt pxor %%twk, %%twk2 %endmacro align IPP_ALIGN_FACTOR IPPASM cpAESEncryptXTS_AES_NI,PUBLIC %assign LOCAL_FRAME sizeof(oword)*6 USES_GPR rsi,rdi USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15 COMP_ABI 6 ;; rdi: pOutBlk: BYTE ; pointer to the output bloak ;; rsi: pInpBlk: BYTE ; pointer to the input block ;; edx: nBlocks DWORD ; number of blocks ;; rcx: pKey: BYTE ; key material address ;; r8d: nr: DWORD ; number of rounds ;; r9 pTweak: BYTE ; pointer to the input/output (ciphertext) tweak %assign AES_BLOCK (16) movsxd r8, r8d ; number of cipher rounds movdqu xmm15, xmmword [r9] ; input tweak value shl r8, 4 ; key schedule length (bytes) movdqa xmm0, xmmword [rcx] ; key[0] movdqa xmm8, xmmword [rel ALPHA_MUL_CNT] ; mul constant pshufd xmm9, xmm15, 5Fh ; {twk[1]:twk[1]:twk[3]:twk[3]} - auxiliary value movsxd rdx, edx ; number of blocks being processing ;; compute: ;; - ktwk[i] = twk[i]^key[0] ;; - twk[i+1] = twk[i]*alpha^(i+1), i=0..5 OUTER_MUL_X xmm10, xmm15, xmm0, xmm8, xmm9, xmm14 OUTER_MUL_X xmm11, xmm15, xmm0, xmm8, xmm9, xmm14 OUTER_MUL_X xmm12, xmm15, xmm0, xmm8, xmm9, xmm14 OUTER_MUL_X xmm13, xmm15, xmm0, xmm8, xmm9, xmm14 LAST_OUTER_MUL_X xmm14, xmm15, xmm0, xmm8, xmm9 movdqa xmm8, xmm15 ; save tweak for next iteration pxor xmm15, xmm0 ; add key[0] sub rdx, 6 ; test input length jc .short_input ;; ;; blocks processing ;; align IPP_ALIGN_FACTOR .blks_loop: pxor xmm0, xmmword [rcx+r8] ; key[0]^key[last] lea rax, [r8-6*AES_BLOCK] ; cipher_loop counter lea r10, [rcx+rax+AES_BLOCK] ; mov key pointer down neg rax movdqu xmm2, xmmword [rsi] ; src[0] - src[7] movdqu xmm3, xmmword [rsi+AES_BLOCK] movdqu xmm4, xmmword [rsi+2*AES_BLOCK] movdqu xmm5, xmmword [rsi+3*AES_BLOCK] movdqu xmm6, xmmword [rsi+4*AES_BLOCK] movdqu xmm7, xmmword [rsi+5*AES_BLOCK] movdqa xmm1, xmmword [rcx+1*AES_BLOCK] ; key[1] pxor xmm2, xmm10 ; src[] ^twk[] ^ key[0] pxor xmm3, xmm11 pxor xmm4, xmm12 pxor xmm5, xmm13 pxor xmm6, xmm14 pxor xmm7, xmm15 pxor xmm10, xmm0 ; store twk[] ^ key[last] pxor xmm11, xmm0 pxor xmm12, xmm0 pxor xmm13, xmm0 pxor xmm14, xmm0 pxor xmm15, xmm0 movdqa xmm0, xmmword [rcx+2*AES_BLOCK] ; key[2] movdqa xmmword [rsp+0*AES_BLOCK], xmm10 movdqa xmmword [rsp+1*AES_BLOCK], xmm11 movdqa xmmword [rsp+2*AES_BLOCK], xmm12 movdqa xmmword [rsp+3*AES_BLOCK], xmm13 movdqa xmmword [rsp+4*AES_BLOCK], xmm14 movdqa xmmword [rsp+5*AES_BLOCK], xmm15 add rsi, 6*AES_BLOCK align IPP_ALIGN_FACTOR .cipher_loop: add rax, 2*AES_BLOCK ; inc loop counter aesenc xmm2, xmm1 ; regular rounds 3 - (last-2) aesenc xmm3, xmm1 aesenc xmm4, xmm1 aesenc xmm5, xmm1 aesenc xmm6, xmm1 aesenc xmm7, xmm1 movdqa xmm1, xmmword [r10+rax] aesenc xmm2, xmm0 aesenc xmm3, xmm0 aesenc xmm4, xmm0 aesenc xmm5, xmm0 aesenc xmm6, xmm0 aesenc xmm7, xmm0 movdqa xmm0, xmmword [r10+rax+AES_BLOCK] jnz .cipher_loop movdqa xmm10, xmmword [rcx] ; key[0] movdqa xmm15, xmm8 ; restore tweak value pshufd xmm9, xmm8, 5Fh ; {twk[1]:twk[1]:twk[3]:twk[3]} - auxiliary value movdqa xmm8, xmmword [rel ALPHA_MUL_CNT] ; mul constant ; ; last 6 rounds (5 regular rounds + irregular) ; merged together with next tweaks computation ; aesenc xmm2, xmm1 aesenc xmm3, xmm1 aesenc xmm4, xmm1 aesenc xmm5, xmm1 aesenc xmm6, xmm1 aesenc xmm7, xmm1 movdqa xmm1, xmmword [rcx+r8-3*AES_BLOCK] INNER_MUL_X xmm10, xmm15, xmm11, xmm8, xmm9, xmm14 aesenc xmm2, xmm0 aesenc xmm3, xmm0 aesenc xmm4, xmm0 aesenc xmm5, xmm0 aesenc xmm6, xmm0 aesenc xmm7, xmm0 movdqa xmm0, xmmword [rcx+r8-2*AES_BLOCK] INNER_MUL_X xmm11, xmm15, xmm12, xmm8, xmm9, xmm14 aesenc xmm2, xmm1 aesenc xmm3, xmm1 aesenc xmm4, xmm1 aesenc xmm5, xmm1 aesenc xmm6, xmm1 aesenc xmm7, xmm1 movdqa xmm1, xmmword [rcx+r8-1*AES_BLOCK] INNER_MUL_X xmm12, xmm15, xmm13, xmm8, xmm9, xmm14 aesenc xmm2, xmm0 aesenc xmm3, xmm0 aesenc xmm4, xmm0 aesenc xmm5, xmm0 aesenc xmm6, xmm0 aesenc xmm7, xmm0 INNER_MUL_X xmm13, xmm15, xmm14, xmm8, xmm9, xmm14 aesenc xmm2, xmm1 aesenc xmm3, xmm1 aesenc xmm4, xmm1 aesenc xmm5, xmm1 aesenc xmm6, xmm1 aesenc xmm7, xmm1 INNER_MUL_X xmm14, xmm15, xmm0, xmm8, xmm9, xmm0 aesenclast xmm2, xmmword [rsp] ; final irregular round aesenclast xmm3, xmmword [rsp+1*AES_BLOCK] aesenclast xmm4, xmmword [rsp+2*AES_BLOCK] aesenclast xmm5, xmmword [rsp+3*AES_BLOCK] aesenclast xmm6, xmmword [rsp+4*AES_BLOCK] aesenclast xmm7, xmmword [rsp+5*AES_BLOCK] LAST_INNER_MUL_X xmm15, xmm8, xmm9 movdqa xmm8, xmm15 ; save tweak for next iteration pxor xmm15, xmm0 ; add key[0] movdqu xmmword [rdi+0*AES_BLOCK], xmm2 ; store output blocks movdqu xmmword [rdi+1*AES_BLOCK], xmm3 movdqu xmmword [rdi+2*AES_BLOCK], xmm4 movdqu xmmword [rdi+3*AES_BLOCK], xmm5 movdqu xmmword [rdi+4*AES_BLOCK], xmm6 movdqu xmmword [rdi+5*AES_BLOCK], xmm7 add rdi, 6*AES_BLOCK sub rdx, 6 jnc .blks_loop .short_input: add rdx, 6 jz .quit movdqa xmmword [rsp+0*AES_BLOCK], xmm10 ; save pre-computed twae movdqa xmmword [rsp+1*AES_BLOCK], xmm11 movdqa xmmword [rsp+2*AES_BLOCK], xmm12 movdqa xmmword [rsp+3*AES_BLOCK], xmm13 movdqa xmmword [rsp+4*AES_BLOCK], xmm14 movdqa xmmword [rsp+5*AES_BLOCK], xmm15 ;; ;; block-by-block processing ;; movdqa xmm0, xmmword [rcx] ; key[0] pxor xmm0, xmmword [rcx+r8] ; key[0] ^ key[last] lea r10, [rcx+r8-9*AES_BLOCK] ; r10 = &key[nr-9] xor rax, rax .single_blk_loop: movdqu xmm2, xmmword [rsi] ; input block movdqa xmm1, xmmword [rsp+rax] ; tweak ^ key[0] add rsi, AES_BLOCK pxor xmm2, xmm1 ; src[] ^tweak ^ key[0] pxor xmm1, xmm0 ; tweak ^ key[lasl] cmp r8, 12*16 ; switch according to number of rounds jl .key_128_s .key_256_s: aesenc xmm2, xmmword [r10-4*AES_BLOCK] aesenc xmm2, xmmword [r10-3*AES_BLOCK] aesenc xmm2, xmmword [r10-2*AES_BLOCK] aesenc xmm2, xmmword [r10-1*AES_BLOCK] .key_128_s: aesenc xmm2, xmmword [r10+0*AES_BLOCK] aesenc xmm2, xmmword [r10+1*AES_BLOCK] aesenc xmm2, xmmword [r10+2*AES_BLOCK] aesenc xmm2, xmmword [r10+3*AES_BLOCK] aesenc xmm2, xmmword [r10+4*AES_BLOCK] aesenc xmm2, xmmword [r10+5*AES_BLOCK] aesenc xmm2, xmmword [r10+6*AES_BLOCK] aesenc xmm2, xmmword [r10+7*AES_BLOCK] aesenc xmm2, xmmword [r10+8*AES_BLOCK] aesenclast xmm2, xmm1 movdqu xmmword [rdi], xmm2 ; output block add rdi, AES_BLOCK add rax, AES_BLOCK sub rdx, 1 jnz .single_blk_loop movdqa xmm10, xmmword [rsp+rax] ; tweak ^ key[0] .quit: pxor xmm10, xmmword [rcx] ; remove key[0] movdqu xmmword [r9], xmm10 ; and save tweak value pxor xmm1, xmm1 REST_XMM REST_GPR ret ENDFUNC cpAESEncryptXTS_AES_NI %endif ;; _AES_NI_ENABLING_ %endif ;;_IPP32E_Y8 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128safedecu8as.asm000066400000000000000000000357201470420105600277250ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael-128 (AES) cipher functions. ; (It's the special free from Sbox/tables implementation) ; ; Content: ; SafeDecrypt_RIJ128() ; ; History: ; ; Notes. ; The implementation is based on ; isomorphism between native GF(2^8) and composite GF((2^4)^2). ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_OFF_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_U8) %macro PTRANSFORM 6.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%memTransLO %3 %xdefine %%memTransHI %4 %xdefine %%tmp %5 %xdefine %%srcLO %6 movdqa %%dst, oword [rel %%memTransLO] ;; LO transformation movdqa %%tmp, oword [rel %%memTransHI] ;; HI transformation movdqa %%srcLO, %%src ;; split src: psrlw %%src, 4 ;; pand %%srcLO, xmm7 ;; low 4 bits -> srcLO pand %%src, xmm7 ;; upper 4 bits -> src pshufb %%dst, %%srcLO ;; transformation pshufb %%tmp, %%src pxor %%dst, %%tmp %endmacro %macro PLOOKUP_MEM 3.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%Table %3 movdqa %%dst, OWORD [rel %%Table] pshufb %%dst,%%src %endmacro %macro PREDUCE_MOD15 2.nolist %xdefine %%dst %1 %xdefine %%src %2 movdqa %%dst, %%src pcmpgtb %%src, xmm7 psubb %%dst, %%src %endmacro %macro PINVERSE_GF16_INV 6.nolist %xdefine %%xmmB %1 %xdefine %%xmmC %2 %xdefine %%xmmP %3 %xdefine %%xmmQ %4 %xdefine %%xmmD %5 %xdefine %%xmmT %6 PLOOKUP_MEM %%xmmT, %%xmmC, GF16_logTbl ;; xmmT = index_of(c) pxor %%xmmC, %%xmmB PLOOKUP_MEM %%xmmQ, %%xmmC, GF16_logTbl ;; xmmQ = index_of(b xor c) PLOOKUP_MEM %%xmmD, %%xmmB, GF16_sqr1 ;; xmmD = sqr(b)*beta^14 PLOOKUP_MEM %%xmmP, %%xmmB, GF16_logTbl ;; xmmP = index_of(b) paddb %%xmmT, %%xmmQ ;; xmmT = index_of(c) + index_of(b xor c) PREDUCE_MOD15 %%xmmC, %%xmmT ;; PLOOKUP_MEM %%xmmT, %%xmmC, GF16_expTbl ;; c*(b xor c) pxor %%xmmD, %%xmmT ;; xmmD = delta = (c*(b xor c)) xor (sqr(b)*beta^14) PLOOKUP_MEM %%xmmT, %%xmmD, GF16_invLog ;; xmmT = index_of( inv(delta) ) paddb %%xmmQ, %%xmmT ;; xmmQ = index_of((b xor c) * inv(delta)) paddb %%xmmP, %%xmmT ;; xmmP = index_of(b * inv(delta)) PREDUCE_MOD15 %%xmmT, %%xmmQ PLOOKUP_MEM %%xmmC, %%xmmT, GF16_expTbl PREDUCE_MOD15 %%xmmT, %%xmmP PLOOKUP_MEM %%xmmB, %%xmmT, GF16_expTbl %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR DECODE_DATA: ;; (forward) native GF(2^8) to composite GF((2^4)^2) transformation : {0x01,0x2E,0x49,0x43,0x35,0xD0,0x3D,0xE9} TransFwdLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 02Eh ;; 02Eh ;; 2 DB 02Fh ;; 02Eh XOR 001h ;; 3 DB 049h ;; 049h ;; 4 DB 048h ;; 049h XOR 001h ;; 5 DB 067h ;; 049h XOR 02Eh ;; 6 DB 066h ;; 049h XOR 02Eh XOR 001h ;; 7 DB 043h ;; 043h ;; 8 DB 042h ;; 043h XOR 001h ;; 9 DB 06Dh ;; 043h XOR 02Eh ;; a DB 06Ch ;; 043h XOR 02Eh XOR 001h ;; b DB 00Ah ;; 043h XOR 049h ;; c DB 00Bh ;; 043h XOR 049h XOR 001h ;; d DB 024h ;; 043h XOR 049h XOR 02Eh ;; e DB 025h ;; 043h XOR 049h XOR 02Eh XOR 001h ;; f TransFwdHI \ DB 000h ;; 000h ;; 0 DB 035h ;; 035h ;; 1 DB 0D0h ;; 0D0h ;; 2 DB 0E5h ;; 0D0h XOR 035h ;; 3 DB 03Dh ;; 03Dh ;; 4 DB 008h ;; 03Dh XOR 035h ;; 5 DB 0EDh ;; 03Dh XOR 0D0h ;; 6 DB 0D8h ;; 03Dh XOR 0D0h XOR 035h ;; 7 DB 0E9h ;; 0E9h ;; 8 DB 0DCh ;; 0E9h XOR 035h ;; 9 DB 039h ;; 0E9h XOR 0D0h ;; a DB 00Ch ;; 0E9h XOR 0D0h XOR 035h ;; b DB 0D4h ;; 0E9h XOR 03Dh ;; c DB 0E1h ;; 0E9h XOR 03Dh XOR 035h ;; d DB 004h ;; 0E9h XOR 03Dh XOR 0D0h ;; e DB 031h ;; 0E9h XOR 03Dh XOR 0D0h XOR 035h ;; f ;; (inverse) composite GF((2^4)^2) to native GF(2^8) transformation : {0x01,0x5C,0xE0,0x50,0x1F,0xEE,0x55,0x6A} TransInvLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 05Ch ;; 05Ch ;; 2 DB 05Dh ;; 05Ch XOR 001h ;; 3 DB 0E0h ;; 0E0h ;; 4 DB 0E1h ;; 0E0h XOR 001h ;; 5 DB 0BCh ;; 0E0h XOR 05Ch ;; 6 DB 0BDh ;; 0E0h XOR 05Ch XOR 001h ;; 7 DB 050h ;; 050h ;; 8 DB 051h ;; 050h XOR 001h ;; 9 DB 00Ch ;; 050h XOR 05Ch ;; a DB 00Dh ;; 050h XOR 05Ch XOR 001h ;; b DB 0B0h ;; 050h XOR 0E0h ;; c DB 0B1h ;; 050h XOR 0E0h XOR 001h ;; d DB 0ECh ;; 050h XOR 0E0h XOR 05Ch ;; e DB 0EDh ;; 050h XOR 0E0h XOR 05Ch XOR 001h ;; f TransInvHI \ DB 000h ;; 000h ;; 0 DB 01Fh ;; 01Fh ;; 1 DB 0EEh ;; 0EEh ;; 2 DB 0F1h ;; 0EEh XOR 01Fh ;; 3 DB 055h ;; 055h ;; 4 DB 04Ah ;; 055h XOR 01Fh ;; 5 DB 0BBh ;; 055h XOR 0EEh ;; 6 DB 0A4h ;; 055h XOR 0EEh XOR 01Fh ;; 7 DB 06Ah ;; 06Ah ;; 8 DB 075h ;; 06Ah XOR 01Fh ;; 9 DB 084h ;; 06Ah XOR 0EEh ;; a DB 09Bh ;; 06Ah XOR 0EEh XOR 01Fh ;; b DB 03Fh ;; 06Ah XOR 055h ;; c DB 020h ;; 06Ah XOR 055h XOR 01Fh ;; d DB 0D1h ;; 06Ah XOR 055h XOR 0EEh ;; e DB 0CEh ;; 06Ah XOR 055h XOR 0EEh XOR 01Fh ;; f GF16_csize DB 00Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh ;; GF16 elements: ;; 0 1 2 3 4 5 6 7 8 9 A B C D E F GF16_logTbl \ DB 0C0h,00h,01h,04h,02h,08h,05h,0Ah,03h,0Eh,09h,07h,06h,0Dh,0Bh,0Ch GF16_expTbl \ DB 001h,02h,04h,08h,03h,06h,0Ch,0Bh,05h,0Ah,07h,0Eh,0Fh,0Dh,09h,01h GF16_sqr1 \ DB 000h,09h,02h,0Bh,08h,01h,0Ah,03h,06h,0Fh,04h,0Dh,0Eh,07h,0Ch,05h ;; sqr(GF16_element) * beta^14 GF16_invLog \ DB 0C0h,00h,0Eh,0Bh,0Dh,07h,0Ah,05h,0Ch,01h,06h,08h,09h,02h,04h,03h ;; affine transformation matrix (inverse cipher) : {0x50,0x36,0x15,0x82,0x01,0x34,0x40,0x3E} InvAffineLO \ DB 000h ;; 000h ;; 0 DB 050h ;; 050h ;; 1 DB 036h ;; 036h ;; 2 DB 066h ;; 036h XOR 050h ;; 3 DB 015h ;; 015h ;; 4 DB 045h ;; 015h XOR 050h ;; 5 DB 023h ;; 015h XOR 036h ;; 6 DB 073h ;; 015h XOR 036h XOR 050h ;; 7 DB 082h ;; 082h ;; 8 DB 0D2h ;; 082h XOR 050h ;; 9 DB 0B4h ;; 082h XOR 036h ;; a DB 0E4h ;; 082h XOR 036h XOR 050h ;; b DB 097h ;; 082h XOR 015h ;; c DB 0C7h ;; 082h XOR 015h XOR 050h ;; d DB 0A1h ;; 082h XOR 015h XOR 036h ;; e DB 0F1h ;; 082h XOR 015h XOR 036h XOR 050h ;; f InvAffineHI \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 034h ;; 034h ;; 2 DB 035h ;; 034h XOR 001h ;; 3 DB 040h ;; 040h ;; 4 DB 041h ;; 040h XOR 001h ;; 5 DB 074h ;; 040h XOR 034h ;; 6 DB 075h ;; 040h XOR 034h XOR 001h ;; 7 DB 03Eh ;; 03Eh ;; 8 DB 03Fh ;; 03Eh XOR 001h ;; 9 DB 00Ah ;; 03Eh XOR 034h ;; a DB 00Bh ;; 03Eh XOR 034h XOR 001h ;; b DB 07Eh ;; 03Eh XOR 040h ;; c DB 07Fh ;; 03Eh XOR 040h XOR 001h ;; d DB 04Ah ;; 03Eh XOR 040h XOR 034h ;; e DB 04Bh ;; 03Eh XOR 040h XOR 034h XOR 001h ;; f ;; affine transformation constant (inverse cipher) InvAffineCnt \ DQ 04848484848484848h,04848484848484848h ;; shift rows transformation (inverse cipher) InvShiftRows \ DB 0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3 ;; mix columns transformation (inverse cipher) GF16mul_4_2x \ DB 000h,024h,048h,06Ch,083h,0A7h,0CBh,0EFh,036h,012h,07Eh,05Ah,0B5h,091h,0FDh,0D9h ;; *(4+2x) GF16mul_1_6x \ DB 000h,061h,0C2h,0A3h,0B4h,0D5h,076h,017h,058h,039h,09Ah,0FBh,0ECh,08Dh,02Eh,04Fh ;; *(1+6x) GF16mul_C_6x \ DB 000h,06Ch,0CBh,0A7h,0B5h,0D9h,07Eh,012h,05Ah,036h,091h,0FDh,0EFh,083h,024h,048h ;; *(C+6x) GF16mul_3_Ax \ DB 000h,0A3h,076h,0D5h,0ECh,04Fh,09Ah,039h,0FBh,058h,08Dh,02Eh,017h,0B4h,061h,0C2h ;; *(3+Ax) GF16mul_B_0x \ DB 000h,00Bh,005h,00Eh,00Ah,001h,00Fh,004h,007h,00Ch,002h,009h,00Dh,006h,008h,003h ;; *(B+0x) GF16mul_0_Bx \ DB 000h,0B0h,050h,0E0h,0A0h,010h,0F0h,040h,070h,0C0h,020h,090h,0D0h,060h,080h,030h ;; *(0+Bx) GF16mul_2_4x \ DB 000h,042h,084h,0C6h,038h,07Ah,0BCh,0FEh,063h,021h,0E7h,0A5h,05Bh,019h,0DFh,09Dh ;; *(2+4x) GF16mul_2_6x \ DB 000h,062h,0C4h,0A6h,0B8h,0DAh,07Ch,01Eh,053h,031h,097h,0F5h,0EBh,089h,02Fh,04Dh ;; *(2+6x) ColumnROR \ DB 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;************************************************************* ;* void SafeDecrypt_RIJ128(const Ipp8u* pInpBlk, ;* Ipp8u* pOutBlk, ;* int nr, ;* const Ipp8u* pKeys, ;* const void* Tables) ;************************************************************* ;; ;; Lib = U8 ;; IPPASM SafeDecrypt_RIJ128,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM xmm6,xmm7 COMP_ABI 5 ;; rdi: pInpBlk: DWORD, ; input block address ;; rsi: pOutBlk: DWORD, ; output block address ;; rdx: nr: DWORD, ; number of rounds ;; rcx: pKey: DWORD ; key material address %assign RSIZE sizeof(dword) ; size of row %assign SC 4 ; columns in STATE %assign SSIZE RSIZE*SC ; size of state lea rax,[rdx*4] lea rcx,[rcx+rax*4] ; AES-128-keys movdqu xmm0, oword [rdi] ; input block movdqa xmm7, oword [rel GF16_csize] ;; convert input into the composite GF((2^4)^2) PTRANSFORM xmm2, xmm0, TransFwdLO,TransFwdHI, xmm1, xmm3 ;; initial whitening pxor xmm2, oword [rcx] sub rcx, SSIZE ;; (nr-1) regular rounds sub rdx,1 .decode_round: ;; InvSubByte() Transformation: ;; affine transformation PTRANSFORM xmm0, xmm2, InvAffineLO,InvAffineHI, xmm1, xmm3 pxor xmm0, oword [rel InvAffineCnt] ; H(c), c=0x05 ;; split input by low and upper parts movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_INV xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; InvShiftRows() Transformation: pshufb xmm0, [rel InvShiftRows] pshufb xmm1, [rel InvShiftRows] ;; InvMixColumn() Transformation: PLOOKUP_MEM xmm2, xmm0, GF16mul_4_2x ; mul H(0xE) = 0x24 pshufb xmm0, [rel ColumnROR] PLOOKUP_MEM xmm3, xmm1, GF16mul_1_6x pshufb xmm1, [rel ColumnROR] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm0, GF16mul_C_6x ; mul H(0xB) = 0x6C pshufb xmm0, [rel ColumnROR] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm1, GF16mul_3_Ax pshufb xmm1, [rel ColumnROR] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm0, GF16mul_B_0x ; mul H(0xD) = 0x0B pshufb xmm0, [rel ColumnROR] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm1, GF16mul_0_Bx pshufb xmm1, [rel ColumnROR] pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm0, GF16mul_2_4x ; mul H(0x9) = 0x42 pxor xmm2, xmm3 PLOOKUP_MEM xmm3, xmm1, GF16mul_2_6x pxor xmm2, xmm3 ;; AddRoundKey() Transformation: pxor xmm2, oword [rcx] sub rcx, SSIZE sub rdx,1 jg .decode_round ;; ;; the last one is irregular ;; ;; InvSubByte() Transformation ;; affine transformation PTRANSFORM xmm0, xmm2, InvAffineLO,InvAffineHI, xmm1, xmm3 pxor xmm0, oword [rel InvAffineCnt] ; H(c), c=0x05 ;; split input by low and upper parts movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_INV xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; InvShiftRows() Transformation: psllw xmm1, 4 por xmm1, xmm0 pshufb xmm1, [rel InvShiftRows] ;; AddRoundKey() Transformation: pxor xmm1, oword [rcx] ;; convert output into the native GF(2^8) PTRANSFORM xmm0,xmm1, TransInvLO,TransInvHI, xmm2, xmm3 movdqu oword [rsi], xmm0 REST_XMM REST_GPR ret ENDFUNC SafeDecrypt_RIJ128 %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprij128safeencu8as.asm000066400000000000000000000357431470420105600277440ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael-128 (AES) cipher functions. ; (It's the special free from Sbox/tables implementation) ; ; Content: ; SafeEncrypt_RIJ128() ; ; History: ; ; Notes. ; The implementation is based on ; isomorphism between native GF(2^8) and composite GF((2^4)^2). ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_AES_NI_ENABLING_ == _FEATURE_OFF_) || (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_U8) %macro PTRANSFORM 6.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%memTransLO %3 %xdefine %%memTransHI %4 %xdefine %%tmp %5 %xdefine %%srcLO %6 movdqa %%dst, oword [rel %%memTransLO] ;; LO transformation movdqa %%tmp, oword [rel %%memTransHI] ;; HI transformation movdqa %%srcLO, %%src ;; split src: psrlw %%src, 4 ;; pand %%srcLO, xmm7 ;; low 4 bits -> srcLO pand %%src, xmm7 ;; upper 4 bits -> src pshufb %%dst, %%srcLO ;; transformation pshufb %%tmp, %%src pxor %%dst, %%tmp %endmacro %macro PLOOKUP_MEM 3.nolist %xdefine %%dst %1 %xdefine %%src %2 %xdefine %%Table %3 movdqa %%dst, OWORD [rel %%Table] pshufb %%dst,%%src %endmacro %macro PREDUCE_MOD15 2.nolist %xdefine %%dst %1 %xdefine %%src %2 movdqa %%dst, %%src pcmpgtb %%src, xmm7 psubb %%dst, %%src %endmacro %macro PINVERSE_GF16_FWD 6.nolist %xdefine %%xmmB %1 %xdefine %%xmmC %2 %xdefine %%xmmP %3 %xdefine %%xmmQ %4 %xdefine %%xmmD %5 %xdefine %%xmmT %6 PLOOKUP_MEM %%xmmT, %%xmmC, GF16_logTbl ;; xmmT = index_of(c) pxor %%xmmC, %%xmmB PLOOKUP_MEM %%xmmQ, %%xmmC, GF16_logTbl ;; xmmQ = index_of(b xor c) PLOOKUP_MEM %%xmmD, %%xmmB, GF16_sqr1 ;; xmmD = sqr(b)*beta^14 PLOOKUP_MEM %%xmmP, %%xmmB, GF16_logTbl ;; xmmP = index_of(b) paddb %%xmmT, %%xmmQ ;; xmmT = index_of(c) + index_of(b xor c) PREDUCE_MOD15 %%xmmC, %%xmmT ;; PLOOKUP_MEM %%xmmT, %%xmmC, GF16_expTbl ;; c*(b xor c) pxor %%xmmD, %%xmmT ;; xmmD = delta = (c*(b xor c)) xor (sqr(b)*beta^14) PLOOKUP_MEM %%xmmT, %%xmmD, GF16_invLog ;; xmmT = index_of( inv(delta) ) paddb %%xmmQ, %%xmmT ;; xmmQ = index_of((b xor c) * inv(delta)) paddb %%xmmP, %%xmmT ;; xmmP = index_of(b * inv(delta)) PREDUCE_MOD15 %%xmmT, %%xmmQ PLOOKUP_MEM %%xmmC, %%xmmT, GF16_expTbl PREDUCE_MOD15 %%xmmT, %%xmmP PLOOKUP_MEM %%xmmB, %%xmmT, GF16_expTbl %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ENCODE_DATA: ;; (forward) native GF(2^8) to composite GF((2^4)^2) transformation : {0x01,0x2E,0x49,0x43,0x35,0xD0,0x3D,0xE9} TransFwdLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 02Eh ;; 02Eh ;; 2 DB 02Fh ;; 02Eh XOR 001h ;; 3 DB 049h ;; 049h ;; 4 DB 048h ;; 049h XOR 001h ;; 5 DB 067h ;; 049h XOR 02Eh ;; 6 DB 066h ;; 049h XOR 02Eh XOR 001h ;; 7 DB 043h ;; 043h ;; 8 DB 042h ;; 043h XOR 001h ;; 9 DB 06Dh ;; 043h XOR 02Eh ;; a DB 06Ch ;; 043h XOR 02Eh XOR 001h ;; b DB 00Ah ;; 043h XOR 049h ;; c DB 00Bh ;; 043h XOR 049h XOR 001h ;; d DB 024h ;; 043h XOR 049h XOR 02Eh ;; e DB 025h ;; 043h XOR 049h XOR 02Eh XOR 001h ;; f TransFwdHI \ DB 000h ;; 000h ;; 0 DB 035h ;; 035h ;; 1 DB 0D0h ;; 0D0h ;; 2 DB 0E5h ;; 0D0h XOR 035h ;; 3 DB 03Dh ;; 03Dh ;; 4 DB 008h ;; 03Dh XOR 035h ;; 5 DB 0EDh ;; 03Dh XOR 0D0h ;; 6 DB 0D8h ;; 03Dh XOR 0D0h XOR 035h ;; 7 DB 0E9h ;; 0E9h ;; 8 DB 0DCh ;; 0E9h XOR 035h ;; 9 DB 039h ;; 0E9h XOR 0D0h ;; a DB 00Ch ;; 0E9h XOR 0D0h XOR 035h ;; b DB 0D4h ;; 0E9h XOR 03Dh ;; c DB 0E1h ;; 0E9h XOR 03Dh XOR 035h ;; d DB 004h ;; 0E9h XOR 03Dh XOR 0D0h ;; e DB 031h ;; 0E9h XOR 03Dh XOR 0D0h XOR 035h ;; f ;; (inverse) composite GF((2^4)^2) to native GF(2^8) transformation : {0x01,0x5C,0xE0,0x50,0x1F,0xEE,0x55,0x6A} TransInvLO \ DB 000h ;; 000h ;; 0 DB 001h ;; 001h ;; 1 DB 05Ch ;; 05Ch ;; 2 DB 05Dh ;; 05Ch XOR 001h ;; 3 DB 0E0h ;; 0E0h ;; 4 DB 0E1h ;; 0E0h XOR 001h ;; 5 DB 0BCh ;; 0E0h XOR 05Ch ;; 6 DB 0BDh ;; 0E0h XOR 05Ch XOR 001h ;; 7 DB 050h ;; 050h ;; 8 DB 051h ;; 050h XOR 001h ;; 9 DB 00Ch ;; 050h XOR 05Ch ;; a DB 00Dh ;; 050h XOR 05Ch XOR 001h ;; b DB 0B0h ;; 050h XOR 0E0h ;; c DB 0B1h ;; 050h XOR 0E0h XOR 001h ;; d DB 0ECh ;; 050h XOR 0E0h XOR 05Ch ;; e DB 0EDh ;; 050h XOR 0E0h XOR 05Ch XOR 001h ;; f TransInvHI \ DB 000h ;; 000h ;; 0 DB 01Fh ;; 01Fh ;; 1 DB 0EEh ;; 0EEh ;; 2 DB 0F1h ;; 0EEh XOR 01Fh ;; 3 DB 055h ;; 055h ;; 4 DB 04Ah ;; 055h XOR 01Fh ;; 5 DB 0BBh ;; 055h XOR 0EEh ;; 6 DB 0A4h ;; 055h XOR 0EEh XOR 01Fh ;; 7 DB 06Ah ;; 06Ah ;; 8 DB 075h ;; 06Ah XOR 01Fh ;; 9 DB 084h ;; 06Ah XOR 0EEh ;; a DB 09Bh ;; 06Ah XOR 0EEh XOR 01Fh ;; b DB 03Fh ;; 06Ah XOR 055h ;; c DB 020h ;; 06Ah XOR 055h XOR 01Fh ;; d DB 0D1h ;; 06Ah XOR 055h XOR 0EEh ;; e DB 0CEh ;; 06Ah XOR 055h XOR 0EEh XOR 01Fh ;; f GF16_csize DB 00Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh,0Fh ;; GF16 elements: ;; 0 1 2 3 4 5 6 7 8 9 A B C D E F GF16_logTbl \ DB 0C0h,00h,01h,04h,02h,08h,05h,0Ah,03h,0Eh,09h,07h,06h,0Dh,0Bh,0Ch GF16_expTbl \ DB 001h,02h,04h,08h,03h,06h,0Ch,0Bh,05h,0Ah,07h,0Eh,0Fh,0Dh,09h,01h GF16_sqr1 \ DB 000h,09h,02h,0Bh,08h,01h,0Ah,03h,06h,0Fh,04h,0Dh,0Eh,07h,0Ch,05h ;; sqr(GF16_element) * beta^14 GF16_invLog \ DB 0C0h,00h,0Eh,0Bh,0Dh,07h,0Ah,05h,0Ch,01h,06h,08h,09h,02h,04h,03h GF16_expTbl_shift \ DB 010h,020h,040h,080h,030h,060h,0C0h,0B0h,050h,0A0h,070h,0E0h,0F0h,0D0h,090h,010h ;; affine transformation matrix (forward cipher) : {0x10,0x22,0x55,0x82,0x41,0x34,0x40,0x2A} FwdAffineLO \ DB 000h ;; 000h ;; 0 DB 010h ;; 010h ;; 1 DB 022h ;; 022h ;; 2 DB 032h ;; 022h XOR 010h ;; 3 DB 055h ;; 055h ;; 4 DB 045h ;; 055h XOR 010h ;; 5 DB 077h ;; 055h XOR 022h ;; 6 DB 067h ;; 055h XOR 022h XOR 010h ;; 7 DB 082h ;; 082h ;; 8 DB 092h ;; 082h XOR 010h ;; 9 DB 0A0h ;; 082h XOR 022h ;; a DB 0B0h ;; 082h XOR 022h XOR 010h ;; b DB 0D7h ;; 082h XOR 055h ;; c DB 0C7h ;; 082h XOR 055h XOR 010h ;; d DB 0F5h ;; 082h XOR 055h XOR 022h ;; e DB 0E5h ;; 082h XOR 055h XOR 022h XOR 010h ;; f FwdAffineHI \ DB 000h ;; 000h ;; 0 DB 041h ;; 041h ;; 1 DB 034h ;; 034h ;; 2 DB 075h ;; 034h XOR 041h ;; 3 DB 040h ;; 040h ;; 4 DB 001h ;; 040h XOR 041h ;; 5 DB 074h ;; 040h XOR 034h ;; 6 DB 035h ;; 040h XOR 034h XOR 041h ;; 7 DB 02Ah ;; 02Ah ;; 8 DB 06Bh ;; 02Ah XOR 041h ;; 9 DB 01Eh ;; 02Ah XOR 034h ;; a DB 05Fh ;; 02Ah XOR 034h XOR 041h ;; b DB 06Ah ;; 02Ah XOR 040h ;; c DB 02Bh ;; 02Ah XOR 040h XOR 041h ;; d DB 05Eh ;; 02Ah XOR 040h XOR 034h ;; e DB 01Fh ;; 02Ah XOR 040h XOR 034h XOR 041h ;; f ;; affine transformation constant (forward cipher) FwdAffineCnt \ DQ 0C2C2C2C2C2C2C2C2h,0C2C2C2C2C2C2C2C2h ;; shift rows transformation (forward cipher) FwdShiftRows \ DB 0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11 ;; mix columns transformation (forward cipher) GF16mul_E_2x \ DB 000h,02Eh,04Fh,061h,08Dh,0A3h,0C2h,0ECh,039h,017h,076h,058h,0B4h,09Ah,0FBh,0D5h GF16mul_1_Cx \ DB 000h,0C1h,0B2h,073h,054h,095h,0E6h,027h,0A8h,069h,01Ah,0DBh,0FCh,03Dh,04Eh,08Fh ColumnROR \ DB 1,2,3,0,5,6,7,4,9,10,11,8,13,14,15,12 segment .text align=IPP_ALIGN_FACTOR ;************************************************************* ; convert GF(2^128) -> GF((2^4)^2) ;************************************************************* align IPP_ALIGN_FACTOR IPPASM TransformNative2Composite,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM xmm7 COMP_ABI 2 ;; rdi: pOutBlk: DWORD, ; output block address ;; rsi: pInpBlk: DWORD, ; input block address movdqu xmm0, oword [rsi] ; input block movdqa xmm7, oword [rel GF16_csize] ;; convert input into the composite GF((2^4)^2) PTRANSFORM xmm1, xmm0, TransFwdLO,TransFwdHI, xmm2, xmm3 movdqu oword [rdi], xmm1 ; output block REST_XMM REST_GPR ret ENDFUNC TransformNative2Composite ;************************************************************* ;* void SafeEncrypt_RIJ128(const Ipp8u* pInpBlk, ;* Ipp8u* pOutBlk, ;* int nr, ;* const Ipp8u* pKeys, ;* const void* Tables) ;************************************************************* align IPP_ALIGN_FACTOR ;; ;; Lib = U8 ;; IPPASM SafeEncrypt_RIJ128,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi USES_XMM xmm6,xmm7 COMP_ABI 5 ;; rdi: pInpBlk: DWORD, ; input block address ;; rsi: pOutBlk: DWORD, ; output block address ;; rdx: nr: DWORD, ; number of rounds ;; rcx: pKey: DWORD ; key material address %assign RSIZE sizeof(dword) ; size of row %assign SC 4 ; columns in STATE %assign SSIZE RSIZE*SC ; size of state movdqu xmm1, oword [rdi] ; input block movdqa xmm7, oword [rel GF16_csize] ;; convert input into the composite GF((2^4)^2) PTRANSFORM xmm0, xmm1, TransFwdLO,TransFwdHI, xmm2, xmm3 ;; initial whitening pxor xmm0, oword [rcx] add rcx, SSIZE ;; (nr-1) regular rounds sub rdx,1 .encode_round: ;; SubByte() Transformation: ;; split input by low and upper parts movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_FWD xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; affine transformation movdqa xmm3, oword [rel FwdAffineLO] movdqa xmm2, oword [rel FwdAffineHI] movdqa xmm4, oword [rel FwdAffineCnt] ; H(c), c=0x63 pshufb xmm3, xmm0 pshufb xmm2, xmm1 pxor xmm3, xmm4 pxor xmm3, xmm2 ;; ShiftRows() Transformation: pshufb xmm3, [rel FwdShiftRows] ;; MixColumn() Transformation: movdqa xmm1, xmm3 movdqa xmm2, xmm3 pxor xmm4, xmm4 psrlw xmm2, 4 pand xmm1, xmm7 ;; a0*(0xE + 0x2*t) PLOOKUP_MEM xmm0, xmm1, GF16mul_E_2x pand xmm2, xmm7 ;; a1*(0x2*0x9 + (0x2+0xE)*t) PLOOKUP_MEM xmm1, xmm2, GF16mul_1_Cx pxor xmm0, xmm1 pshufb xmm3, [rel ColumnROR] pxor xmm4, xmm3 pshufb xmm3, [rel ColumnROR] pxor xmm4, xmm3 movdqa xmm2, xmm0 pshufb xmm2, [rel ColumnROR] pxor xmm0, xmm2 pshufb xmm3, [rel ColumnROR] pxor xmm4, xmm3 pxor xmm0, xmm4 ;; AddRoundKey() Transformation: pxor xmm0, oword [rcx] add rcx, SSIZE sub rdx,1 jg .encode_round ;; ;; the last one is irregular ;; ;; SubByte() Transformation: movdqa xmm1, xmm0 pand xmm0, xmm7 ; low parts (4 bits) psrlw xmm1, 4 pand xmm1, xmm7 ; upper parts (4 bits) ;; compute multiplicative inverse PINVERSE_GF16_FWD xmm1,xmm0, xmm3,xmm2,xmm4,xmm5 ;; affine transformation movdqa xmm3, oword [rel FwdAffineLO] movdqa xmm2, oword [rel FwdAffineHI] movdqa xmm4, oword [rel FwdAffineCnt] ; H(c), c=0x63 pshufb xmm3, xmm0 pshufb xmm2, xmm1 pxor xmm3, xmm4 pxor xmm3, xmm2 ;; ShiftRows() Transformation: pshufb xmm3, [rel FwdShiftRows] ;; AddRoundKey() Transformation: pxor xmm3, oword [rcx] ;; convert output into the native GF(2^8) PTRANSFORM xmm0,xmm3, TransInvLO,TransInvHI, xmm2,xmm1 movdqu oword [rsi], xmm0 REST_XMM REST_GPR ret ENDFUNC SafeEncrypt_RIJ128 %endif %endif ;; _AES_NI_ENABLING_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcprijnkeym7as.asm000066400000000000000000000045521470420105600270340ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2014 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Rijndael Key Expansion Support ; ; Content: ; SubsDword_8uT() ; ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) segment .text align=IPP_ALIGN_FACTOR %xdefine CACHE_LINE_SIZE (64) ;*************************************************************** ;* Purpose: Mitigation of the Key Expansion procedure ;* ;* Ipp32u Touch_SubsDword_8uT(Ipp32u inp, ;* const Ipp8u* pTbl, ;* int tblBytes) ;*************************************************************** align IPP_ALIGN_FACTOR IPPASM Touch_SubsDword_8uT,PUBLIC USES_GPR rsi,rdi USES_XMM COMP_ABI 3 ;; rdi: inp: DWORD, ; input dword ;; rsi: pTbl: BYTE, ; Rijndael's S-box ;; edx tblLen: DWORD ; length of table (bytes) movsxd r8, edx ; length xor rcx, rcx .touch_tbl: mov rax, [rsi+rcx] add rcx, CACHE_LINE_SIZE cmp rcx, r8 jl .touch_tbl mov rax, rdi and rax, 0FFh ; b[0] movzx rax, BYTE [rsi+rax] shr rdi, 8 mov r9, rdi and r9, 0FFh ; b[1] movzx r9, BYTE [rsi+r9] shl r9, 8 shr rdi, 8 mov rcx, rdi and rcx, 0FFh ; b[2] movzx rcx, BYTE [rsi+rcx] shl rcx, 16 shr rdi, 8 mov rdx, rdi and rdx, 0FFh ; b[3] movzx rdx, BYTE [rsi+rdx] shl rdx, 24 or rax, r9 or rax, rcx or rax, rdx REST_XMM REST_GPR ret ENDFUNC Touch_SubsDword_8uT %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha1e9as.asm000066400000000000000000000275621470420105600262150ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA1 ; ; Content: ; UpdateSHA1 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) ;;%if (_IPP32E >= _IPP32E_E9 ) %if (_IPP32E == _IPP32E_E9 ) ;; ;; SHA1 constants K[i] %xdefine SHA1_K1 (05a827999h) %xdefine SHA1_K2 (06ed9eba1h) %xdefine SHA1_K3 (08f1bbcdch) %xdefine SHA1_K4 (0ca62c1d6h) ;; ;; Magic functions defined in FIPS 180-1 ;; ;; F1, F2, F3 and F4 assumes, that ;; - T1 returns function value ;; - T2 is the temporary ;; %macro F1 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 mov T1,%%C xor T1,%%D and T1,%%B xor T1,%%D %endmacro %macro F2 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 mov T1,%%D xor T1,%%C xor T1,%%B %endmacro %macro F3 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 mov T1,%%C mov T2,%%B or T1,%%B and T2,%%C and T1,%%D or T1,T2 %endmacro %macro F4 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 F2 %%B,%%C,%%D %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; rotations ;; %macro ROL_5 1.nolist %xdefine %%x %1 shld %%x,%%x, 5 %endmacro %macro ROL_30 1.nolist %xdefine %%x %1 shld %%x,%%x, 30 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; textual rotation of W array ;; %macro ROTATE_W 0.nolist %xdefine W_minus_32 W_minus_28 %xdefine W_minus_28 W_minus_24 %xdefine W_minus_24 W_minus_20 %xdefine W_minus_20 W_minus_16 %xdefine W_minus_16 W_minus_12 %xdefine W_minus_12 W_minus_08 %xdefine W_minus_08 W_minus_04 %xdefine W_minus_04 W %xdefine W W_minus_32 %endmacro ;; ;; SHA1 update round: ;; - F1 magic is used (and embedded into the macros directly) ;; - 16 bytes of input are swapped ;; %macro SHA1_UPDATE_RND_F1_BSWAP 7.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%nr %6 %xdefine %%Wchunk %7 vpshufb W, %%Wchunk, XMM_SHUFB_BSWAP vpaddd %%Wchunk, W, oword [K_XMM] vmovdqa oword [rsp + (%%nr & 15)*4], %%Wchunk mov T1,%%C ; F1 mov T2,%%A xor T1,%%D ; F1 and T1,%%B ; F1 ROL_5 T2 xor T1,%%D ; F1 add %%E, T2 ROL_30 %%B add T1, dword [rsp + (%%nr & 15)*4] add %%E,T1 ROTATE_W %endmacro ;; ;; SHA1 update round: ;; - F1 magic is used (and embedded into the macros directly) ;; %macro SHA1_UPDATE_RND_F1 6.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%nr %6 mov T1,%%C ; F1 mov T2,%%A xor T1,%%D ; F1 ROL_5 T2 and T1,%%B ; F1 xor T1,%%D ; F1 add %%E, T2 ROL_30 %%B add T1, dword [rsp + (%%nr & 15)*4] add %%E,T1 %endmacro ;; ;; update W ;; %macro W_CALC 1.nolist %xdefine %%nr %1 %assign %%W_CALC_ahead 8 %assign %%i (%%nr + %%W_CALC_ahead) %if (%%i < 20) %xdefine K_XMM K_BASE %elif (%%i < 40) %xdefine K_XMM K_BASE+16 %elif (%%i < 60) %xdefine K_XMM K_BASE+32 %else %xdefine K_XMM K_BASE+48 %endif %if (%%i < 32) %if ((%%i & 3) == 0) ;; just scheduling to interleave with ALUs vpalignr W, W_minus_12, W_minus_16, 8 ; w[i-14] vpsrldq W_TMP, W_minus_04, 4 ; w[i-3] vpxor W, W, W_minus_08 %elif ((%%i & 3) == 1) vpxor W_TMP, W_TMP, W_minus_16 vpxor W, W, W_TMP vpslldq W_TMP2, W, 12 %elif ((%%i & 3) == 2) vpslld W_TMP, W, 1 vpsrld W, W, 31 vpor W_TMP, W_TMP, W vpslld W, W_TMP2, 2 vpsrld W_TMP2, W_TMP2, 30 %elif ((%%i & 3) == 3) vpxor W_TMP, W_TMP, W vpxor W, W_TMP, W_TMP2 vpaddd W_TMP, W, oword [K_XMM] vmovdqa oword [rsp + ((%%i & (~3)) & 15)*4],W_TMP ROTATE_W %endif ;; %elif (i < 83) %elif (%%i < 80) %if ((%%i & 3) == 0) ;; scheduling to interleave with ALUs vpalignr W_TMP, W_minus_04, W_minus_08, 8 vpxor W, W, W_minus_28 ;; W == W_minus_32 %elif ((%%i & 3) == 1) vpxor W_TMP, W_TMP, W_minus_16 vpxor W, W, W_TMP %elif ((%%i & 3) == 2) vpslld W_TMP, W, 2 vpsrld W, W, 30 vpor W, W_TMP, W %elif ((%%i & 3) == 3) vpaddd W_TMP, W, oword [K_XMM] vmovdqa oword [rsp + ((%%i & (~3)) & 15)*4],W_TMP ROTATE_W %endif %endif %endmacro ;; ;; Regular hash update ;; %macro SHA1_UPDATE_REGULAR 7.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%nr %6 %xdefine %%MagiF %7 W_CALC %%nr add %%E, dword [rsp + (%%nr & 15)*4] %%MagiF %%B,%%C,%%D add %%D, dword [rsp +((%%nr+1) & 15)*4] ROL_30 %%B mov T3,%%A add %%E, T1 ROL_5 T3 add T3, %%E mov %%E, T3 W_CALC %%nr+1 ROL_5 T3 add %%D,T3 %%MagiF %%A,%%B,%%C add %%D, T1 ROL_30 %%A ; write: %1, %2 ; rotate: %1<=%4, %2<=%5, %3<=%1, %4<=%2, %5<=%3 %endmacro ;; update hash macro %macro UPDATE_HASH 2.nolist %xdefine %%hash0 %1 %xdefine %%hashAdd %2 add %%hashAdd, %%hash0 mov %%hash0, %%hashAdd %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR K_XMM_AR dd SHA1_K1, SHA1_K1, SHA1_K1, SHA1_K1 dd SHA1_K2, SHA1_K2, SHA1_K2, SHA1_K2 dd SHA1_K3, SHA1_K3, SHA1_K3, SHA1_K3 dd SHA1_K4, SHA1_K4, SHA1_K4, SHA1_K4 shuffle_mask DD 00010203h DD 04050607h DD 08090a0bh DD 0c0d0e0fh segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; Lib = Y8 ;; ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; ;; ;; assign hash values to GPU registers %xdefine A ecx %xdefine B eax %xdefine C edx %xdefine D r8d %xdefine E r9d ;; temporary %xdefine T1 r10d %xdefine T2 r11d %xdefine T3 r13d %xdefine T4 r13d %xdefine W_TMP xmm0 %xdefine W_TMP2 xmm1 %xdefine W0 xmm2 %xdefine W4 xmm3 %xdefine W8 xmm4 %xdefine W12 xmm5 %xdefine W16 xmm6 %xdefine W20 xmm7 %xdefine W24 xmm8 %xdefine W28 xmm9 ;; endianness swap constant %xdefine XMM_SHUFB_BSWAP xmm10 ;; K_BASE contains [K_XMM_AR] address %xdefine K_BASE r12 align IPP_ALIGN_FACTOR IPPASM UpdateSHA1,PUBLIC %assign LOCAL_FRAME (16*4) USES_GPR rdi,rsi,r12,r13,r14 USES_XMM_AVX xmm6,xmm7,xmm8,xmm9,xmm10 COMP_ABI 4 ;; ;; rdi = digest ptr ;; rsi = data block ptr ;; rdx = data length ;; rcx = dummy %xdefine MBS_SHA1 (64) movsxd r14, edx movdqa XMM_SHUFB_BSWAP, oword [rel shuffle_mask] ; load shuffle mask lea K_BASE, [rel K_XMM_AR] ; SHA1 const array address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: mov A, dword [rdi] ; load initial hash value mov B, dword [rdi+4] mov C, dword [rdi+8] mov D, dword [rdi+12] mov E, dword [rdi+16] movdqu W28, oword [rsi] ; load buffer content movdqu W24, oword [rsi+16] movdqu W20, oword [rsi+32] movdqu W16, oword [rsi+48] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;SHA1_MAIN_BODY %xdefine W W0 %xdefine W_minus_04 W4 %xdefine W_minus_08 W8 %xdefine W_minus_12 W12 %xdefine W_minus_16 W16 %xdefine W_minus_20 W20 %xdefine W_minus_24 W24 %xdefine W_minus_28 W28 %xdefine W_minus_32 W ;; assignment %xdefine K_XMM K_BASE ;;F textequ SHA1_UPDATE_RND_F1_BSWAP A,B,C,D,E, 0, W28 SHA1_UPDATE_RND_F1 E,A,B,C,D, 1 SHA1_UPDATE_RND_F1 D,E,A,B,C, 2 SHA1_UPDATE_RND_F1 C,D,E,A,B, 3 SHA1_UPDATE_RND_F1_BSWAP B,C,D,E,A, 4, W24 SHA1_UPDATE_RND_F1 A,B,C,D,E, 5 SHA1_UPDATE_RND_F1 E,A,B,C,D, 6 SHA1_UPDATE_RND_F1 D,E,A,B,C, 7 SHA1_UPDATE_RND_F1_BSWAP C,D,E,A,B, 8, W20 SHA1_UPDATE_RND_F1 B,C,D,E,A, 9 SHA1_UPDATE_RND_F1 A,B,C,D,E, 10 SHA1_UPDATE_RND_F1 E,A,B,C,D, 11 SHA1_UPDATE_RND_F1_BSWAP D,E,A,B,C, 12, W16 W_CALC 8 W_CALC 9 W_CALC 10 SHA1_UPDATE_RND_F1 C,D,E,A,B, 13 W_CALC 11 W_CALC 12 SHA1_UPDATE_RND_F1 B,C,D,E,A, 14 W_CALC 13 W_CALC 14 W_CALC 15 SHA1_UPDATE_RND_F1 A,B,C,D,E, 15 SHA1_UPDATE_REGULAR E,A,B,C,D,16, F1 SHA1_UPDATE_REGULAR C,D,E,A,B,18, F1 ;;F textequ SHA1_UPDATE_REGULAR A,B,C,D,E,20, F2 SHA1_UPDATE_REGULAR D,E,A,B,C,22, F2 SHA1_UPDATE_REGULAR B,C,D,E,A,24, F2 SHA1_UPDATE_REGULAR E,A,B,C,D,26, F2 SHA1_UPDATE_REGULAR C,D,E,A,B,28, F2 SHA1_UPDATE_REGULAR A,B,C,D,E,30, F2 SHA1_UPDATE_REGULAR D,E,A,B,C,32, F2 SHA1_UPDATE_REGULAR B,C,D,E,A,34, F2 SHA1_UPDATE_REGULAR E,A,B,C,D,36, F2 SHA1_UPDATE_REGULAR C,D,E,A,B,38, F2 ;;F textequ SHA1_UPDATE_REGULAR A,B,C,D,E,40, F3 SHA1_UPDATE_REGULAR D,E,A,B,C,42, F3 SHA1_UPDATE_REGULAR B,C,D,E,A,44, F3 SHA1_UPDATE_REGULAR E,A,B,C,D,46, F3 SHA1_UPDATE_REGULAR C,D,E,A,B,48, F3 SHA1_UPDATE_REGULAR A,B,C,D,E,50, F3 SHA1_UPDATE_REGULAR D,E,A,B,C,52, F3 SHA1_UPDATE_REGULAR B,C,D,E,A,54, F3 SHA1_UPDATE_REGULAR E,A,B,C,D,56, F3 SHA1_UPDATE_REGULAR C,D,E,A,B,58, F3 ;;F textequ SHA1_UPDATE_REGULAR A,B,C,D,E,60, F4 SHA1_UPDATE_REGULAR D,E,A,B,C,62, F4 SHA1_UPDATE_REGULAR B,C,D,E,A,64, F4 SHA1_UPDATE_REGULAR E,A,B,C,D,66, F4 SHA1_UPDATE_REGULAR C,D,E,A,B,68, F4 SHA1_UPDATE_REGULAR A,B,C,D,E,70, F4 SHA1_UPDATE_REGULAR D,E,A,B,C,72, F4 SHA1_UPDATE_REGULAR B,C,D,E,A,74, F4 SHA1_UPDATE_REGULAR E,A,B,C,D,76, F4 SHA1_UPDATE_REGULAR C,D,E,A,B,78, F4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UPDATE_HASH dword [rdi], A UPDATE_HASH dword [rdi+4], B UPDATE_HASH dword [rdi+8], C UPDATE_HASH dword [rdi+12],D UPDATE_HASH dword [rdi+16],E add rsi, MBS_SHA1 sub r14, MBS_SHA1 jg .sha1_block_loop REST_XMM_AVX REST_GPR ret ENDFUNC UpdateSHA1 %endif ;; _IPP32E >= _IPP32E_E9 %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha1l9as.asm000066400000000000000000000500731470420105600262150ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2017 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA1 ; ; Content: ; UpdateSHA1 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_L9 ) ;; ;; assignments ;; %xdefine hA eax ;; hash values into GPU registers %xdefine F ebp %xdefine hB ebx %xdefine hC ecx %xdefine hD edx %xdefine hE r8d %xdefine T1 r10d ;; SHA1 round computation (temporary) %xdefine T2 r11d %xdefine W00 ymm2 ;; W values into YMM registers %xdefine W04 ymm3 %xdefine W08 ymm4 %xdefine W12 ymm5 %xdefine W16 ymm6 %xdefine W20 ymm7 %xdefine W24 ymm8 %xdefine W28 ymm9 %xdefine W16L xmm6 %xdefine W20L xmm7 %xdefine W24L xmm8 %xdefine W28L xmm9 %xdefine WTMP1 ymm0 ;; msg scheduling computation (temporary) %xdefine WTMP2 ymm1 %xdefine WTMP3 ymm10 %xdefine YMM_SHUFB ymm11 ;; byte swap constant %xdefine YMM_K ymm12 ;; sha1 round constant value %xdefine F_PTR r13 ;; frame ptr/data block ptr ;;W_PTR textequ r12 ;; frame ptr/data block ptr ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; textual rotation of W array ;; %macro ROTATE_W 0.nolist %xdefine W_minus_32 W_minus_28 %xdefine W_minus_28 W_minus_24 %xdefine W_minus_24 W_minus_20 %xdefine W_minus_20 W_minus_16 %xdefine W_minus_16 W_minus_12 %xdefine W_minus_12 W_minus_08 %xdefine W_minus_08 W_minus_04 %xdefine W_minus_04 W %xdefine W W_minus_32 %endmacro ;; ;; msg scheduling for initial 00-15 sha1 rounds: ;; - byte swap input ;; - add sha1 round constant %macro W_CALC_00_15 2.nolist %xdefine %%nr %1 %xdefine %%Wchunk %2 vpshufb W, %%Wchunk, YMM_SHUFB vpaddd %%Wchunk, W, YMM_K vmovdqa ymmword [F_PTR + (%%nr)*sizeof(dword)*2], %%Wchunk ROTATE_W %endmacro ;; ;; msg scheduling for other 16-79 sha1 rounds: ;; %macro W_CALC 1.nolist %xdefine %%rndw %1 %if (%%rndw < 32) %if ((%%rndw & 3) == 0) ;; scheduling to interleave with ALUs vpalignr W, W_minus_12, W_minus_16, 8 ;; w[t-14] vpsrldq WTMP1, W_minus_04, 4 ;; w[t-3] vpxor W, W, W_minus_16 vpxor WTMP1, WTMP1, W_minus_08 %elif ((%%rndw & 3) == 1) vpxor W, W, WTMP1 vpsrld WTMP1, W, 31 vpslldq WTMP2, W, 12 vpaddd W, W, W %elif ((%%rndw & 3) == 2) vpsrld WTMP3, WTMP2, 30 vpxor W, W, WTMP1 vpslld WTMP2, WTMP2, 2 vpxor W, W, WTMP3 %elif ((%%rndw & 3) == 3) vpxor W, W, WTMP2 ;;vpaddd WTMP1, W, ymmword [K_SHA1_PTR] vpaddd WTMP1, W, YMM_K vmovdqa ymmword [F_PTR+4*sizeof(ymmword)+((%%rndw & 15)/4)*sizeof(ymmword)],WTMP1 ROTATE_W %endif %elif (%%rndw < 80) %if ((%%rndw & 3) == 0) ;; scheduling to interleave with ALUs vpalignr WTMP1, W_minus_04, W_minus_08, 8 vpxor W, W, W_minus_28 ;; W == W_minus_32 %elif ((%%rndw & 3) == 1) vpxor W, W, W_minus_16 vpxor W, W, WTMP1 %elif ((%%rndw & 3) == 2) vpslld WTMP1, W, 2 vpsrld W, W, 30 %elif ((%%rndw & 3) == 3) vpxor W, WTMP1, W ;;vpaddd WTMP1, W, ymmword [K_SHA1_PTR] vpaddd WTMP1, W, YMM_K vmovdqa ymmword [F_PTR+4*sizeof(ymmword)+((%%rndw & 15)/4)*sizeof(ymmword)],WTMP1 ROTATE_W %endif %endif %endmacro ;; ;; update hash macro ;; %macro UPDATE_HASH 2.nolist %xdefine %%hashMem %1 %xdefine %%hash %2 add %%hash, %%hashMem mov %%hashMem, %%hash %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; textual rotation of HASH arguments ;; %macro ROTATE_H 0.nolist %xdefine %%_X hE %xdefine hE hD %xdefine hD hC %xdefine hC hB %xdefine hB F %xdefine F hA %xdefine hA %%_X %endmacro ;; ;; SHA1 rounds 0 - 19 ;; on entry: ;; - a, f(), b', c, d, e values ;; where: f() = F(b,c,d) = (b&c) & (~b&d) already pre-computed for this round ;; b' = rotl(b,30) already pre-computed for the next round ;; note: ;; %if nr==19 the f(b,c,d)=b^c^d precomputed ;; %macro SHA1_ROUND_00_19 1.nolist %xdefine %%nr %1 ;; hE+=W[nr]+K add hE, dword [F_PTR+((%%nr & 15)/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] %if (((%%nr+1) & 15) == 0) add F_PTR, (16/4)*sizeof(ymmword) %endif %if (%%nr < 19) andn T1,hA,hC ;; ~hB&hC (next round) %endif add hE, F ;; hE += F() rorx T2,hA, 27 ;; hA<<<5 rorx F, hA, 2 ;; hB<<<30 (next round) %if (%%nr < 19) and hA, hB ;; hB&hC (next round) %endif add hE, T2 ;; hE += (hA<<<5) %if (%%nr < 19) xor hA, T1 ;; F() = (hB&hC)^(~hB&hC) (next round) %else xor hA, hB ;; F() = hB^hC^hD next round xor hA, hC %endif ROTATE_H %endmacro ;; ;; SHA1 rounds 20 - 39 ;; on entry: ;; - a, f(), b', c, d, e values ;; where: f() = F(b,c,d) = b^c^d already pre-computed for this round ;; b' = rotl(b,30) already pre-computed for the next round ;; ;; note: ;; %if nr==39 the f(b,c,d)=(b^c)&(c^d) precomputed ;; %macro SHA1_ROUND_20_39 1.nolist %xdefine %%nr %1 ;; hE+=W[nr]+K add hE, dword [F_PTR+((%%nr & 15)/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] %if (((%%nr+1) & 15) == 0) add F_PTR, (16/4)*sizeof(ymmword) %endif add hE, F ;; hE += F() rorx T2,hA, 27 ;; hA<<<5 rorx F, hA, 2 ;; hB<<<30 (next round) xor hA, hB ;; hB^hC (next round) add hE, T2 ;; hE += (hA<<<5) %if (%%nr < 39) xor hA, hC ;; F() = hB^hC^hD (next round) %else mov T1, hB ;; hC^hD (next round) xor T1, hC ;; and hA, T1 ;; (hB^hC)&(hC^hD) %endif ROTATE_H %endmacro ;; ;; SHA1 rounds 40 - 59 ;; on entry: ;; - a, f(), b', c, d, e values ;; where: f() = (b&c)^(c&d) already pre-computed (part of F()) for this round ;; b' = rotl(b,30) already pre-computed for the next round ;; ;; F(b,c,d) = (b&c)^(b&d)^(c&d) ;; ;; note, using GF(2): arithmetic ;; F(b,c,d) = (b&c)^(b&d)^(c&d) ~ bc+bd+cd ;; =(b+c)(c+d) +c^2 = (b+c)(c+d) +c ;; ~ ((b^c)&(c^d)) ^c ;; direct substitution: ;; (b+c)(c+d) = bc + bd + c^2 + cd, but c^2 = c ;; %macro SHA1_ROUND_40_59 1.nolist %xdefine %%nr %1 ;; hE+=W[nr]+K add hE, dword [F_PTR+((%%nr & 15)/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] %if (((%%nr+1) & 15) == 0) add F_PTR, (16/4)*sizeof(ymmword) %endif xor F, hC ;; F() = ((b^c)&(c^d)) ^c %if(%%nr < 59) mov T1, hB ;; hC^hD (next round) xor T1, hC ;; %endif add hE, F ;; hE += F() rorx T2,hA, 27 ;; hA<<<5 rorx F, hA, 2 ;; hB<<<30 (next round) xor hA, hB ;; hB^hC (next round) add hE, T2 ;; hE += (hA<<<5) %if(%%nr < 59) and hA, T1 ;; (hB^hC)&(hC^hD) (next round) %else xor hA, hC ;; (hB^hC^hD) (next round) %endif ROTATE_H %endmacro ;; ;; SHA1 rounds 60 - 79 ;; on entry: ;; - a, f(), b', c, d, e values ;; where: f() = F(b,c,d) = b^c^d already pre-computed for this round ;; b' = rotl(b,30) already pre-computed for the next round ;; %macro SHA1_ROUND_60_79 1.nolist %xdefine %%nr %1 ;; hE+=W[nr]+K add hE, dword [F_PTR+((%%nr & 15)/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] %if (((%%nr+1) & 15) == 0) add F_PTR, (16/4)*sizeof(ymmword) %endif add hE, F ;; hE += F() rorx T2,hA, 27 ;; hA<<<5 %if (%%nr < 79) rorx F, hA, 2 ;; hB<<<30 (next round) xor hA, hB ;; hB^hC (next round) %endif add hE, T2 ;; hE += (hA<<<5) %if (%%nr < 79) xor hA, hC ;; F() = hB^hC^hD (next round) %endif ROTATE_H %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SHA1_YMM_K dd 05a827999h, 05a827999h, 05a827999h, 05a827999h, 05a827999h, 05a827999h, 05a827999h, 05a827999h dd 06ed9eba1h, 06ed9eba1h, 06ed9eba1h, 06ed9eba1h, 06ed9eba1h, 06ed9eba1h, 06ed9eba1h, 06ed9eba1h dd 08f1bbcdch, 08f1bbcdch, 08f1bbcdch, 08f1bbcdch, 08f1bbcdch, 08f1bbcdch, 08f1bbcdch, 08f1bbcdch dd 0ca62c1d6h, 0ca62c1d6h, 0ca62c1d6h, 0ca62c1d6h, 0ca62c1d6h, 0ca62c1d6h, 0ca62c1d6h, 0ca62c1d6h SHA1_YMM_BF dd 00010203h,04050607h,08090a0bh,0c0d0e0fh dd 00010203h,04050607h,08090a0bh,0c0d0e0fh segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** align IPP_ALIGN_FACTOR IPPASM UpdateSHA1,PUBLIC %assign LOCAL_FRAME (sizeof(dword)*80*2) USES_GPR rdi,rsi,rbp,rbx,r12,r13,r14,r15 USES_XMM_AVX xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12 COMP_ABI 4 ;; rdi = hash ptr ;; rsi = data block ptr ;; rdx = data length in bytes ;; rcx = dummy %xdefine MBS_SHA1 (64) mov r15, rsp ; store original rsp and rsp, -IPP_ALIGN_FACTOR ; 32-byte aligned stack movsxd r14, edx ; input length in bytes vmovdqa YMM_SHUFB, [rel SHA1_YMM_BF] ; load byte shuffler mov hA, dword [rdi] ; load initial hash value mov F, dword [rdi+sizeof(dword)] mov hC, dword [rdi+2*sizeof(dword)] mov hD, dword [rdi+3*sizeof(dword)] mov hE, dword [rdi+4*sizeof(dword)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data 2 block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; assignment: ;; - W00,...,W28 are fixed ;; - W_minus_04,...,W_minus_32 are rorarted ;; - W corresponds to W[t] ;; %xdefine W W00 %xdefine W_minus_04 W04 %xdefine W_minus_08 W08 %xdefine W_minus_12 W12 %xdefine W_minus_16 W16 %xdefine W_minus_20 W20 %xdefine W_minus_24 W24 %xdefine W_minus_28 W28 %xdefine W_minus_32 W align IPP_ALIGN_FACTOR .sha1_block2_loop: lea F_PTR, [rsi+MBS_SHA1] ; next block cmp r14, MBS_SHA1 ; %if single block processed cmovbe F_PTR, rsi ; use the same data block address ;; ;; load data block and merge next data block ;; vmovdqa YMM_K, [rel SHA1_YMM_K] ; pre-load sha1 constant vmovdqu W28L, xmmword [rsi] ; load data block vmovdqu W24L, xmmword [rsi+1*sizeof(xmmword)] vmovdqu W20L, xmmword [rsi+2*sizeof(xmmword)] vmovdqu W16L, xmmword [rsi+3*sizeof(xmmword)] vinserti128 W28, W28, xmmword [F_PTR], 1 ; merge next data block vinserti128 W24, W24, xmmword [F_PTR+1*sizeof(xmmword)], 1 vinserti128 W20, W20, xmmword [F_PTR+2*sizeof(xmmword)], 1 vinserti128 W16, W16, xmmword [F_PTR+3*sizeof(xmmword)], 1 mov F_PTR, rsp ;; set local data pointer W_CALC_00_15 0, W28 ;; msg scheduling for rounds 00 .. 15 W_CALC_00_15 4, W24 ;; W_CALC_00_15 8, W20 ;; msg scheduling for rounds 08 .. 15 W_CALC_00_15 12, W16 ;; rorx hB, F, 2 ;; pre-compute (b<<<30) next round andn T1,F, hD ;; pre-compute F1(F,hC,hD) = hB&hC ^(~hB&hD) and F, hC xor F, T1 W_CALC 16 ;; msg schedilling ahead 16 rounds SHA1_ROUND_00_19 0 ;; sha1 round W_CALC 17 SHA1_ROUND_00_19 1 W_CALC 18 SHA1_ROUND_00_19 2 W_CALC 19 SHA1_ROUND_00_19 3 ; pre-load sha1 constant vmovdqa YMM_K, [rel SHA1_YMM_K+sizeof(ymmword)] W_CALC 20 SHA1_ROUND_00_19 4 W_CALC 21 SHA1_ROUND_00_19 5 W_CALC 22 SHA1_ROUND_00_19 6 W_CALC 23 SHA1_ROUND_00_19 7 W_CALC 24 SHA1_ROUND_00_19 8 W_CALC 25 SHA1_ROUND_00_19 9 W_CALC 26 SHA1_ROUND_00_19 10 W_CALC 27 SHA1_ROUND_00_19 11 W_CALC 28 SHA1_ROUND_00_19 12 W_CALC 29 SHA1_ROUND_00_19 13 W_CALC 30 SHA1_ROUND_00_19 14 W_CALC 31 SHA1_ROUND_00_19 15 W_CALC 32 SHA1_ROUND_00_19 16 W_CALC 33 SHA1_ROUND_00_19 17 W_CALC 34 SHA1_ROUND_00_19 18 W_CALC 35 SHA1_ROUND_00_19 19 W_CALC 36 SHA1_ROUND_20_39 20 W_CALC 37 SHA1_ROUND_20_39 21 W_CALC 38 SHA1_ROUND_20_39 22 W_CALC 39 SHA1_ROUND_20_39 23 ; pre-load sha1 constant vmovdqa YMM_K, [rel SHA1_YMM_K+2*sizeof(ymmword)] W_CALC 40 SHA1_ROUND_20_39 24 W_CALC 41 SHA1_ROUND_20_39 25 W_CALC 42 SHA1_ROUND_20_39 26 W_CALC 43 SHA1_ROUND_20_39 27 W_CALC 44 SHA1_ROUND_20_39 28 W_CALC 45 SHA1_ROUND_20_39 29 W_CALC 46 SHA1_ROUND_20_39 30 W_CALC 47 SHA1_ROUND_20_39 31 W_CALC 48 SHA1_ROUND_20_39 32 W_CALC 49 SHA1_ROUND_20_39 33 W_CALC 50 SHA1_ROUND_20_39 34 W_CALC 51 SHA1_ROUND_20_39 35 W_CALC 52 SHA1_ROUND_20_39 36 W_CALC 53 SHA1_ROUND_20_39 37 W_CALC 54 SHA1_ROUND_20_39 38 W_CALC 55 SHA1_ROUND_20_39 39 W_CALC 56 SHA1_ROUND_40_59 40 W_CALC 57 SHA1_ROUND_40_59 41 W_CALC 58 SHA1_ROUND_40_59 42 W_CALC 59 SHA1_ROUND_40_59 43 ; pre-load sha1 constant vmovdqa YMM_K, [rel SHA1_YMM_K+3*sizeof(ymmword)] W_CALC 60 SHA1_ROUND_40_59 44 W_CALC 61 SHA1_ROUND_40_59 45 W_CALC 62 SHA1_ROUND_40_59 46 W_CALC 63 SHA1_ROUND_40_59 47 W_CALC 64 SHA1_ROUND_40_59 48 W_CALC 65 SHA1_ROUND_40_59 49 W_CALC 66 SHA1_ROUND_40_59 50 W_CALC 67 SHA1_ROUND_40_59 51 W_CALC 68 SHA1_ROUND_40_59 52 W_CALC 69 SHA1_ROUND_40_59 53 W_CALC 70 SHA1_ROUND_40_59 54 W_CALC 71 SHA1_ROUND_40_59 55 W_CALC 72 SHA1_ROUND_40_59 56 W_CALC 73 SHA1_ROUND_40_59 57 W_CALC 74 SHA1_ROUND_40_59 58 W_CALC 75 SHA1_ROUND_40_59 59 W_CALC 76 SHA1_ROUND_60_79 60 W_CALC 77 SHA1_ROUND_60_79 61 W_CALC 78 SHA1_ROUND_60_79 62 W_CALC 79 SHA1_ROUND_60_79 63 SHA1_ROUND_60_79 64 SHA1_ROUND_60_79 65 SHA1_ROUND_60_79 66 SHA1_ROUND_60_79 67 SHA1_ROUND_60_79 68 SHA1_ROUND_60_79 69 SHA1_ROUND_60_79 70 SHA1_ROUND_60_79 71 SHA1_ROUND_60_79 72 SHA1_ROUND_60_79 73 SHA1_ROUND_60_79 74 SHA1_ROUND_60_79 75 SHA1_ROUND_60_79 76 SHA1_ROUND_60_79 77 SHA1_ROUND_60_79 78 SHA1_ROUND_60_79 79 lea F_PTR, [rsp+sizeof(xmmword)] ;; set local data pointer ;; update hash values by 1-st data block UPDATE_HASH dword [rdi], hA UPDATE_HASH dword [rdi+4], F UPDATE_HASH dword [rdi+8], hC UPDATE_HASH dword [rdi+12],hD UPDATE_HASH dword [rdi+16],hE cmp r14, MBS_SHA1*2 jl .done rorx hB, F, 2 ;; pre-compute (b<<<30) next round andn T1,F, hD ;; pre-compute F1(F,hC,hD) = hB&hC ^(~hB&hD) and F, hC xor F, T1 SHA1_ROUND_00_19 0 SHA1_ROUND_00_19 1 SHA1_ROUND_00_19 2 SHA1_ROUND_00_19 3 SHA1_ROUND_00_19 4 SHA1_ROUND_00_19 5 SHA1_ROUND_00_19 6 SHA1_ROUND_00_19 7 SHA1_ROUND_00_19 8 SHA1_ROUND_00_19 9 SHA1_ROUND_00_19 10 SHA1_ROUND_00_19 11 SHA1_ROUND_00_19 12 SHA1_ROUND_00_19 13 SHA1_ROUND_00_19 14 SHA1_ROUND_00_19 15 SHA1_ROUND_00_19 16 SHA1_ROUND_00_19 17 SHA1_ROUND_00_19 18 SHA1_ROUND_00_19 19 SHA1_ROUND_20_39 20 SHA1_ROUND_20_39 21 SHA1_ROUND_20_39 22 SHA1_ROUND_20_39 23 SHA1_ROUND_20_39 24 SHA1_ROUND_20_39 25 SHA1_ROUND_20_39 26 SHA1_ROUND_20_39 27 SHA1_ROUND_20_39 28 SHA1_ROUND_20_39 29 SHA1_ROUND_20_39 30 SHA1_ROUND_20_39 31 SHA1_ROUND_20_39 32 SHA1_ROUND_20_39 33 SHA1_ROUND_20_39 34 SHA1_ROUND_20_39 35 SHA1_ROUND_20_39 36 SHA1_ROUND_20_39 37 SHA1_ROUND_20_39 38 SHA1_ROUND_20_39 39 SHA1_ROUND_40_59 40 SHA1_ROUND_40_59 41 SHA1_ROUND_40_59 42 SHA1_ROUND_40_59 43 SHA1_ROUND_40_59 44 SHA1_ROUND_40_59 45 SHA1_ROUND_40_59 46 SHA1_ROUND_40_59 47 SHA1_ROUND_40_59 48 SHA1_ROUND_40_59 49 SHA1_ROUND_40_59 50 SHA1_ROUND_40_59 51 SHA1_ROUND_40_59 52 SHA1_ROUND_40_59 53 SHA1_ROUND_40_59 54 SHA1_ROUND_40_59 55 SHA1_ROUND_40_59 56 SHA1_ROUND_40_59 57 SHA1_ROUND_40_59 58 SHA1_ROUND_40_59 59 SHA1_ROUND_60_79 60 SHA1_ROUND_60_79 61 SHA1_ROUND_60_79 62 SHA1_ROUND_60_79 63 SHA1_ROUND_60_79 64 SHA1_ROUND_60_79 65 SHA1_ROUND_60_79 66 SHA1_ROUND_60_79 67 SHA1_ROUND_60_79 68 SHA1_ROUND_60_79 69 SHA1_ROUND_60_79 70 SHA1_ROUND_60_79 71 SHA1_ROUND_60_79 72 SHA1_ROUND_60_79 73 SHA1_ROUND_60_79 74 SHA1_ROUND_60_79 75 SHA1_ROUND_60_79 76 SHA1_ROUND_60_79 77 SHA1_ROUND_60_79 78 SHA1_ROUND_60_79 79 ;; update hash values by 2-nd data block UPDATE_HASH dword [rdi], hA UPDATE_HASH dword [rdi+4], F UPDATE_HASH dword [rdi+8], hC UPDATE_HASH dword [rdi+12],hD UPDATE_HASH dword [rdi+16],hE ;; unfortunately 2*80%6 != 0 ;; and so need to re-order hA,F,hB,hC,hD,hE values ;; to match the code generated for 1-st block processing mov hB, hD ; re-order data physically mov hD, hA mov T1, hE mov hE, F mov F, hC mov hC, T1 ROTATE_H ; re-order data logically ROTATE_H ; twice, because 6 -(2*80%6) = 2 add rsi, MBS_SHA1*2 sub r14, MBS_SHA1*2 jg .sha1_block2_loop .done: mov rsp, r15 REST_XMM_AVX REST_GPR ret ENDFUNC UpdateSHA1 %endif ;; _IPP32E >= _IPP32E_L9 %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha1m7as.asm000066400000000000000000000335151470420105600262160ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA1 ; ; Content: ; UpdateSHA1 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_M7) && (_IPP32E < _IPP32E_U8 ) ;; ;; Magic functions defined in FIPS 180-1 ;; %macro MAGIC_F0 4-5.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regT %5 mov %%regF,%%regC xor %%regF,%%regD and %%regF,%%regB xor %%regF,%%regD %endmacro %macro MAGIC_F1 4-5.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regT %5 mov %%regF,%%regD xor %%regF,%%regC xor %%regF,%%regB %endmacro %macro MAGIC_F2 5.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regT %5 mov %%regF,%%regB mov %%regT,%%regB or %%regF,%%regC and %%regT,%%regC and %%regF,%%regD or %%regF,%%regT %endmacro %macro MAGIC_F3 4-5.nolist %xdefine %%regF %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regT %5 MAGIC_F1 {%%regF},{%%regB},{%%regC},{%%regD},{%%regT} %endmacro ;; ;; single SHA1 step ;; ;; Ipp32u tmp = ROL(A,5) + MAGIC_Fi(B,C,D) + E + W[t] + CNT[i]; ;; E = D; ;; D = C; ;; C = ROL(B,30); ;; B = A; ;; A = tmp; ;; %macro SHA1_STEP 10.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%memW %8 %xdefine %%immCNT %9 %xdefine %%MAGIC %10 add %%regE,%%immCNT add %%regE,[%%memW] mov %%regT,%%regA rol %%regT,5 add %%regE,%%regT %%MAGIC %%regF,%%regB,%%regC,%%regD,%%regT ;; FUN = MAGIC_Fi(B,C,D) rol %%regB,30 add %%regE,%%regF %endmacro %macro SHA1_RND0 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %assign %%immCNT 05A827999h mov r13d,%%immCNT MAGIC_F0 %%regF,%%regB,%%regC,%%regD ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[rsp+(((%%nr) & 0Fh)*4)] ; lea regE,[regE+regF+immCNT] ; substituted with 2 adds because of gnu as bug add r13d, %%regF add %%regE, r13d add %%regE,%%regT %endmacro %macro SHA1_RND1 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %assign %%immCNT 06ED9EBA1h mov r13d,%%immCNT MAGIC_F1 {%%regF},{%%regB},{%%regC},{%%regD} ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[rsp+(((%%nr) & 0Fh)*4)] ; lea regE,[regE+regF+immCNT] ; substituted with 2 adds because of gnu as bug add r13d, %%regF add %%regE, r13d add %%regE,%%regT %endmacro %macro SHA1_RND2 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %ifndef _VXWORKS %assign %%immCNT 08F1BBCDCh %else %assign %%immCNT -1894007588 %endif mov r13d,%%immCNT MAGIC_F2 %%regF,%%regB,%%regC,%%regD,%%regT ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[rsp+(((%%nr) & 0Fh)*4)] ; lea regE,[regE+regF+immCNT] ; substituted with 2 adds because of gnu as bug add r13d, %%regF add %%regE, r13d add %%regE,%%regT %endmacro %macro SHA1_RND3 8.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regT %6 %xdefine %%regF %7 %xdefine %%nr %8 %ifndef _VXWORKS %assign %%immCNT 0CA62C1D6h %else %assign %%immCNT -899497514 %endif mov r13d,%%immCNT MAGIC_F3 {%%regF},{%%regB},{%%regC},{%%regD} ;; FUN = MAGIC_Fi(B,C,D) ror %%regB,(32-30) mov %%regT,%%regA rol %%regT,5 add %%regE,[rsp+(((%%nr) & 0Fh)*4)] ; lea regE,[regE+regF+immCNT] ; substituted with 2 adds because of gnu as bug add r13d, %%regF add %%regE, r13d add %%regE,%%regT %endmacro ;; ;; ENDIANNESS ;; %macro ENDIANNESS 2.nolist %xdefine %%dst %1 %xdefine %%src %2 %ifnidn %%dst,%%src mov %%dst,%%src %endif bswap %%dst %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Following Macros are especially for new implementation of SHA1 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro UPDATE 2-3.nolist %xdefine %%nr %1 %xdefine %%regU %2 %xdefine %%regT %3 %ifempty %%regT mov %%regU,[rsp+((%%nr-16) & 0Fh)*4] xor %%regU,[rsp+((%%nr-14) & 0Fh)*4] xor %%regU,[rsp+((%%nr-8) & 0Fh)*4] xor %%regU,[rsp+((%%nr-3) & 0Fh)*4] %else mov %%regU,[rsp+((%%nr-16) & 0Fh)*4] mov %%regT,[rsp+((%%nr-14) & 0Fh)*4] xor %%regU,%%regT mov %%regT,[rsp+((%%nr-8) & 0Fh)*4] xor %%regU,%%regT mov %%regT,[rsp+((%%nr-3) & 0Fh)*4] xor %%regU,%%regT %endif rol %%regU,1 mov [rsp+(%%nr & 0Fh)*4],%%regU %endmacro segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; Lib = M7 ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA1,PUBLIC %assign LOCAL_FRAME 16*4 USES_GPR rbx,rsi,rdi,r8,r9,r10,r11,r12,r13 USES_XMM COMP_ABI 4 %xdefine MBS_SHA1 (64) movsxd rdx, edx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: ;; ;; init A, B, C, D, E by the internal digest ;; mov r8d, [rdi+0*4] ; r8d = digest[0] (A) mov r9d, [rdi+1*4] ; r9d = digest[1] (B) mov r10d,[rdi+2*4] ; r10d= digest[2] (C) mov r11d,[rdi+3*4] ; r11d= digest[3] (D) mov r12d,[rdi+4*4] ; r12d= digest[4] (E) ;; ;; initialize the first 16 words in the array W (remember about endian) ;; xor rcx,rcx .loop1: mov eax,[rsi+rcx*4+0*4] ENDIANNESS eax,eax mov [rsp+rcx*4+0*4],eax mov ebx,[rsi+rcx*4+1*4] ENDIANNESS ebx,ebx mov [rsp+rcx*4+1*4],ebx add rcx,2 cmp rcx,16 jl .loop1 ;; ;; perform 0-79 steps ;; ;; A, B, C, D, E, TMP,FUN, round ;; ----------------------------------- SHA1_RND0 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 0 UPDATE 16, eax SHA1_RND0 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 1 UPDATE 17, eax SHA1_RND0 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 2 UPDATE 18, eax SHA1_RND0 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 3 UPDATE 19, eax SHA1_RND0 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 4 UPDATE 20, eax SHA1_RND0 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 5 UPDATE 21, eax SHA1_RND0 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 6 UPDATE 22, eax SHA1_RND0 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 7 UPDATE 23, eax SHA1_RND0 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 8 UPDATE 24, eax SHA1_RND0 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 9 UPDATE 25, eax SHA1_RND0 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 10 UPDATE 26, eax SHA1_RND0 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 11 UPDATE 27, eax SHA1_RND0 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 12 UPDATE 28, eax SHA1_RND0 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 13 UPDATE 29, eax SHA1_RND0 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 14 UPDATE 30, eax SHA1_RND0 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 15 UPDATE 31, eax SHA1_RND0 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 16 UPDATE 32, eax SHA1_RND0 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 17 UPDATE 33, eax SHA1_RND0 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 18 UPDATE 34, eax SHA1_RND0 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 19 UPDATE 35, eax SHA1_RND1 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 20 UPDATE 36, eax SHA1_RND1 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 21 UPDATE 37, eax SHA1_RND1 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 22 UPDATE 38, eax SHA1_RND1 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 23 UPDATE 39, eax SHA1_RND1 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 24 UPDATE 40, eax SHA1_RND1 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 25 UPDATE 41, eax SHA1_RND1 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 26 UPDATE 42, eax SHA1_RND1 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 27 UPDATE 43, eax SHA1_RND1 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 28 UPDATE 44, eax SHA1_RND1 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 29 UPDATE 45, eax SHA1_RND1 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 30 UPDATE 46, eax SHA1_RND1 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 31 UPDATE 47, eax SHA1_RND1 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 32 UPDATE 48, eax SHA1_RND1 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 33 UPDATE 49, eax SHA1_RND1 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 34 UPDATE 50, eax SHA1_RND1 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 35 UPDATE 51, eax SHA1_RND1 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 36 UPDATE 52, eax SHA1_RND1 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 37 UPDATE 53, eax SHA1_RND1 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 38 UPDATE 54, eax SHA1_RND1 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 39 UPDATE 55, eax SHA1_RND2 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 40 UPDATE 56, eax SHA1_RND2 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 41 UPDATE 57, eax SHA1_RND2 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 42 UPDATE 58, eax SHA1_RND2 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 43 UPDATE 59, eax SHA1_RND2 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 44 UPDATE 60, eax SHA1_RND2 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 45 UPDATE 61, eax SHA1_RND2 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 46 UPDATE 62, eax SHA1_RND2 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 47 UPDATE 63, eax SHA1_RND2 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 48 UPDATE 64, eax SHA1_RND2 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 49 UPDATE 65, eax SHA1_RND2 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 50 UPDATE 66, eax SHA1_RND2 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 51 UPDATE 67, eax SHA1_RND2 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 52 UPDATE 68, eax SHA1_RND2 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 53 UPDATE 69, eax SHA1_RND2 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 54 UPDATE 70, eax SHA1_RND2 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 55 UPDATE 71, eax SHA1_RND2 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 56 UPDATE 72, eax SHA1_RND2 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 57 UPDATE 73, eax SHA1_RND2 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 58 UPDATE 74, eax SHA1_RND2 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 59 UPDATE 75, eax SHA1_RND3 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 60 UPDATE 76, eax SHA1_RND3 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 61 UPDATE 77, eax SHA1_RND3 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 62 UPDATE 78, eax SHA1_RND3 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 63 UPDATE 79, eax SHA1_RND3 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 64 SHA1_RND3 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 65 SHA1_RND3 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 66 SHA1_RND3 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 67 SHA1_RND3 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 68 SHA1_RND3 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 69 SHA1_RND3 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 70 SHA1_RND3 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 71 SHA1_RND3 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 72 SHA1_RND3 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 73 SHA1_RND3 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 74 SHA1_RND3 r8d,r9d,r10d,r11d,r12d, ecx,ebx, 75 SHA1_RND3 r12d,r8d,r9d,r10d,r11d, ecx,ebx, 76 SHA1_RND3 r11d,r12d,r8d,r9d,r10d, ecx,ebx, 77 SHA1_RND3 r10d,r11d,r12d,r8d,r9d, ecx,ebx, 78 SHA1_RND3 r9d,r10d,r11d,r12d,r8d, ecx,ebx, 79 ;; ;; update digest ;; add [rdi+0*4],r8d ; advance digest add [rdi+1*4],r9d add [rdi+2*4],r10d add [rdi+3*4],r11d add [rdi+4*4],r12d add rsi, MBS_SHA1 sub rdx, MBS_SHA1 jg .sha1_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA1 %endif ;; (_IPP32E >= _IPP32E_M7) AND (_IPP32E < _IPP32E_U8 ) %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha1nias.asm000066400000000000000000000357111470420105600263010ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA-1 ; ; Content: ; UpdateSHA1ni ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_ON_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) ;;%if (_IPP32E >= _IPP32E_Y8 ) segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR UPPER_DWORD_MASK \ DQ 00000000000000000h, 0ffffffff00000000h PSHUFFLE_BYTE_FLIP_MASK \ DB 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1ni(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** %ifndef _VXWORKS IPPASM UpdateSHA1ni,PUBLIC %assign LOCAL_FRAME 16*2 USES_GPR rsi,rdi USES_XMM xmm6,xmm7 COMP_ABI 4 %xdefine MBS_SHA1 (64) ; SHA-1 message block length (bytes) %xdefine HASH_PTR rdi ; 1st arg %xdefine MSG_PTR rsi ; 2nd arg %xdefine MSG_LEN rdx ; 3rd arg %xdefine ABCD xmm0 %xdefine E0 xmm1 ; Need two E's b/c they ping pong %xdefine E1 xmm2 %xdefine MSG0 xmm3 %xdefine MSG1 xmm4 %xdefine MSG2 xmm5 %xdefine MSG3 xmm6 %xdefine SHUF_MASK xmm7 ; ; stack frame ; %xdefine abcd_save rsp %xdefine e_save rsp+16 movsxd MSG_LEN, edx ; expand mLen test MSG_LEN, MSG_LEN jz .quit ;; load initial hash values movdqu ABCD, oword [HASH_PTR] pinsrd E0, dword [HASH_PTR+16], 3 pand E0, oword [rel UPPER_DWORD_MASK] pshufd ABCD, ABCD, 01Bh movdqa SHUF_MASK, oword [rel PSHUFFLE_BYTE_FLIP_MASK] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: movdqa oword [abcd_save], ABCD movdqa oword [e_save], E0 ;; rounds 0-3 movdqu MSG0, oword [MSG_PTR +0*16] pshufb MSG0, SHUF_MASK paddd E0, MSG0 movdqa E1, ABCD sha1rnds4 ABCD, E0, 0 ;movdqu oword [rcx+16*0], ABCD ;; rounds 4-7 movdqu MSG1, oword [MSG_PTR +1*16] pshufb MSG1, SHUF_MASK sha1nexte E1, MSG1 movdqa E0, ABCD sha1rnds4 ABCD, E1, 0 sha1msg1 MSG0, MSG1 ;movdqu oword [rcx+16*1], ABCD ;; rounds 8-11 movdqu MSG2, oword [MSG_PTR +2*16] pshufb MSG2, SHUF_MASK sha1nexte E0, MSG2 movdqa E1, ABCD sha1rnds4 ABCD, E0, 0 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*2], ABCD ;; rounds 12-15 movdqu MSG3, oword [MSG_PTR +3*16] pshufb MSG3, SHUF_MASK sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 0 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*3], ABCD ;; rounds 16-19 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 0 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*4], ABCD ;; rounds 20-23 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 1 sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*5], ABCD ;; rounds 24-27 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 1 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*6], ABCD ;; rounds 28-31 sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 1 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*7], ABCD ;; rounds 32-35 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 1 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*8], ABCD ;; rounds 36-39 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 1 sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*9], ABCD ;; rounds 40-43 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 2 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*10], ABCD ;; rounds 44-47 sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 2 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*11], ABCD ;; rounds 48-51 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 2 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*12], ABCD ;; rounds 52-55 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 2 sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*13], ABCD ;; rounds 56-59 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 2 sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*14], ABCD ;; rounds 60-63 sha1nexte E1, MSG3 movdqa E0, ABCD sha1msg2 MSG0, MSG3 sha1rnds4 ABCD, E1, 3 sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*15], ABCD ;; rounds 64-67 sha1nexte E0, MSG0 movdqa E1, ABCD sha1msg2 MSG1, MSG0 sha1rnds4 ABCD, E0, 3 sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*16], ABCD ;; rounds 68-71 sha1nexte E1, MSG1 movdqa E0, ABCD sha1msg2 MSG2, MSG1 sha1rnds4 ABCD, E1, 3 pxor MSG3, MSG1 ;movdqu oword [rcx+16*17], ABCD ;; rounds 72-75 sha1nexte E0, MSG2 movdqa E1, ABCD sha1msg2 MSG3, MSG2 sha1rnds4 ABCD, E0, 3 ;movdqu oword [rcx+16*18], ABCD ;; rounds 76-79 sha1nexte E1, MSG3 movdqa E0, ABCD sha1rnds4 ABCD, E1, 3 ;movdqu oword [rcx+16*19], ABCD ;; add current hash values with previously saved sha1nexte E0, oword [e_save] paddd ABCD, oword [abcd_save] add MSG_PTR, MBS_SHA1 sub MSG_LEN, MBS_SHA1 jg .sha1_block_loop ;; write hash values back in the correct order pshufd ABCD, ABCD, 01Bh movdqu oword [HASH_PTR], ABCD pextrd dword [HASH_PTR+16], E0, 3 .quit: REST_XMM REST_GPR ret ENDFUNC UpdateSHA1ni %else ;; no sha ni support in VxWorks - therefore we temporary use db IPPASM UpdateSHA1ni,PUBLIC %assign LOCAL_FRAME 16*2 USES_GPR rsi,rdi USES_XMM xmm6,xmm7 COMP_ABI 4 %xdefine MBS_SHA1 (64) ; SHA-1 message block length (bytes) %xdefine HASH_PTR rdi ; 1st arg %xdefine MSG_PTR rsi ; 2nd arg %xdefine MSG_LEN rdx ; 3rd arg %xdefine ABCD xmm0 %xdefine E0 xmm1 ; Need two E's b/c they ping pong %xdefine E1 xmm2 %xdefine MSG0 xmm3 %xdefine MSG1 xmm4 %xdefine MSG2 xmm5 %xdefine MSG3 xmm6 %xdefine SHUF_MASK xmm7 ; ; stack frame ; %xdefine abcd_save rsp %xdefine e_save rsp+16 movsxd MSG_LEN, edx ; expand mLen test MSG_LEN, MSG_LEN jz .quit ;; load initial hash values movdqu ABCD, oword [HASH_PTR] pinsrd E0, dword [HASH_PTR+16], 3 pand E0, oword [rel UPPER_DWORD_MASK] pshufd ABCD, ABCD, 01Bh movdqa SHUF_MASK, oword [rel PSHUFFLE_BYTE_FLIP_MASK] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: movdqa oword [abcd_save], ABCD movdqa oword [e_save], E0 ;; rounds 0-3 movdqu MSG0, oword [MSG_PTR +0*16] pshufb MSG0, SHUF_MASK paddd E0, MSG0 movdqa E1, ABCD db 0FH,3AH,0CCH,0C1H,00H ;;sha1rnds4 ABCD, E0, 0 ;movdqu oword [rcx+16*0], ABCD ;; rounds 4-7 movdqu MSG1, oword [MSG_PTR +1*16] pshufb MSG1, SHUF_MASK db 0FH,38H,0C8H,0D4H ;;sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,3AH,0CCH,0C2H,00H ;;sha1rnds4 ABCD, E1, 0 db 0FH,38H,0C9H,0DCH ;;sha1msg1 MSG0, MSG1 ;movdqu oword [rcx+16*1], ABCD ;; rounds 8-11 movdqu MSG2, oword [MSG_PTR +2*16] pshufb MSG2, SHUF_MASK db 0FH,38H,0C8H,0CDH ;;sha1nexte E0, MSG2 movdqa E1, ABCD db 0Fh,3Ah,0CCh,0C1h,00h ;;sha1rnds4 ABCD, E0, 0 db 0Fh,38h,0C9h,0E5h ;;sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*2], ABCD ;; rounds 12-15 movdqu MSG3, oword [MSG_PTR +3*16] pshufb MSG3, SHUF_MASK db 0Fh,38H,0C8h,0D6h ;;sha1nexte E1, MSG3 movdqa E0, ABCD db 0Fh,38H,0CAh,0DEh ;;sha1msg2 MSG0, MSG3 db 0Fh,3AH,0CCh,0C2h,00h ;;sha1rnds4 ABCD, E1, 0 db 0Fh,38H,0C9h,0EEh ;;sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*3], ABCD ;; rounds 16-19 db 0Fh,38H,0C8h,0CBh ;;sha1nexte E0, MSG0 movdqa E1, ABCD db 0Fh,38H,0CAh,0E3h ;;sha1msg2 MSG1, MSG0 db 0Fh,3AH,0CCh,0C1h,00h ;;sha1rnds4 ABCD, E0, 0 db 0Fh,38H,0C9h,0F3h ;;sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*4], ABCD ;; rounds 20-23 db 0FH,38H,0C8h,0D4h ;;sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,38H,0CAh,0ECH ;;sha1msg2 MSG2, MSG1 db 0FH,3AH,0CCH,0C2H,01H ;;sha1rnds4 ABCD, E1, 1 db 0FH,38H,0C9h,0DCh ;;sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*5], ABCD ;; rounds 24-27 db 0FH,38H,0C8h,0CDh ;;sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,38H,0CAh,0F5h ;;sha1msg2 MSG3, MSG2 db 0FH,3AH,0CCh,0C1h,01h ;;sha1rnds4 ABCD, E0, 1 db 0FH,38H,0C9h,0E5h ;;sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*6], ABCD ;; rounds 28-31 db 0FH,38H,0C8H,0D6h ;;sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,38H,0CAH,0DEh ;;sha1msg2 MSG0, MSG3 db 0FH,3AH,0CCH,0C2H,01h ;;sha1rnds4 ABCD, E1, 1 db 0FH,38H,0C9H,0EEh ;;sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*7], ABCD ;; rounds 32-35 db 0FH,38H,0C8H,0CBh ;;sha1nexte E0, MSG0 movdqa E1, ABCD db 0FH,38H,0CAH,0E3h ;;sha1msg2 MSG1, MSG0 db 0FH,3AH,0CCH,0C1H,01h ;;sha1rnds4 ABCD, E0, 1 db 0FH,38H,0C9H,0F3h ;;sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*8], ABCD ;; rounds 36-39 db 0FH,38H,0C8H,0D4h ;;sha1nexte E1, MSG1 movdqa E0, ABCD db 0FH,38H,0CAH,0ECh ;;sha1msg2 MSG2, MSG1 db 0FH,3AH,0CCH,0C2H,01h ;;sha1rnds4 ABCD, E1, 1 db 0FH,38H,0C9H,0DCh ;;sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*9], ABCD ;; rounds 40-43 db 0FH,38H,0C8H,0CDh ;;sha1nexte E0, MSG2 movdqa E1, ABCD db 0FH,38H,0CAH,0F5h ;;sha1msg2 MSG3, MSG2 db 0FH,3AH,0CCH,0C1H,02h ;;sha1rnds4 ABCD, E0, 2 db 0FH,38H,0C9H,0E5h ;;sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*10], ABCD ;; rounds 44-47 db 0FH,38H,0C8H,0D6h ;;sha1nexte E1, MSG3 movdqa E0, ABCD db 0FH,38H,0CAH,0DEh ;;sha1msg2 MSG0, MSG3 db 0FH,3AH,0CCH,0C2h,02h ;;sha1rnds4 ABCD, E1, 2 db 0FH,38H,0C9H,0EEh ;;sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*11], ABCD ;; rounds 48-51 db 0Fh,38H,0C8h,0CBh ;;sha1nexte E0, MSG0 movdqa E1, ABCD db 0Fh,38H,0CAH,0E3h ;;sha1msg2 MSG1, MSG0 db 0Fh,3AH,0CCH,0C1H,02h ;;sha1rnds4 ABCD, E0, 2 db 0Fh,38H,0C9H,0F3h ;;sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*12], ABCD ;; rounds 52-55 db 0Fh,38H,0C8h,0D4h ;;sha1nexte E1, MSG1 movdqa E0, ABCD db 0Fh,38H,0CAH,0ECh ;;sha1msg2 MSG2, MSG1 db 0Fh,3AH,0CCH,0C2H,02h ;;sha1rnds4 ABCD, E1, 2 db 0Fh,38H,0C9H,0DCh ;;sha1msg1 MSG0, MSG1 pxor MSG3, MSG1 ;movdqu oword [rcx+16*13], ABCD ;; rounds 56-59 db 0Fh,38H,0C8H,0CDh ;;sha1nexte E0, MSG2 movdqa E1, ABCD db 0Fh,38H,0CAH,0F5h ;;sha1msg2 MSG3, MSG2 db 0Fh,3AH,0CCH,0C1H,02h ;;sha1rnds4 ABCD, E0, 2 db 0Fh,38H,0C9H,0E5h ;;sha1msg1 MSG1, MSG2 pxor MSG0, MSG2 ;movdqu oword [rcx+16*14], ABCD ;; rounds 60-63 db 0Fh,38H,0C8H,0D6h ;;sha1nexte E1, MSG3 movdqa E0, ABCD db 0Fh,38H,0CAH,0DEh ;;sha1msg2 MSG0, MSG3 db 0Fh,3AH,0CCH,0C2H,03h ;;sha1rnds4 ABCD, E1, 3 db 0Fh,38H,0C9H,0EEh ;;sha1msg1 MSG2, MSG3 pxor MSG1, MSG3 ;movdqu oword [rcx+16*15], ABCD ;; rounds 64-67 db 0Fh,38H,0C8H,0CBh ;;sha1nexte E0, MSG0 movdqa E1, ABCD db 0Fh,38H,0CAH,0E3h ;;sha1msg2 MSG1, MSG0 db 0Fh,3AH,0CCH,0C1H,03h ;;sha1rnds4 ABCD, E0, 3 db 0Fh,38H,0C9H,0F3h ;;sha1msg1 MSG3, MSG0 pxor MSG2, MSG0 ;movdqu oword [rcx+16*16], ABCD ;; rounds 68-71 db 0Fh,38H,0C8h,0D4h ;;sha1nexte E1, MSG1 movdqa E0, ABCD db 0Fh,38H,0CAh,0ECh ;;sha1msg2 MSG2, MSG1 db 0Fh,3AH,0CCh,0C2h,03h ;;sha1rnds4 ABCD, E1, 3 pxor MSG3, MSG1 ;movdqu oword [rcx+16*17], ABCD ;; rounds 72-75 db 0Fh,38H,0C8h,0CDh ;;sha1nexte E0, MSG2 movdqa E1, ABCD db 0Fh,38H,0CAh,0F5h ;;sha1msg2 MSG3, MSG2 db 0Fh,3AH,0CCh,0C1h,03h ;;sha1rnds4 ABCD, E0, 3 ;movdqu oword [rcx+16*18], ABCD ;; rounds 76-79 db 0Fh,38H,0C8h,0D6h ;;sha1nexte E1, MSG3 movdqa E0, ABCD db 0Fh,3AH,0CCh,0C2h,03h ;;sha1rnds4 ABCD, E1, 3 ;movdqu oword [rcx+16*19], ABCD ;; add current hash values with previously saved db 0Fh,38H,0C8h,4Ch,24h,10h ;;sha1nexte E0, oword [e_save] paddd ABCD, oword [abcd_save] add MSG_PTR, MBS_SHA1 sub MSG_LEN, MBS_SHA1 jg .sha1_block_loop ;; write hash values back in the correct order pshufd ABCD, ABCD, 01Bh movdqu oword [HASH_PTR], ABCD pextrd dword [HASH_PTR+16], E0, 3 .quit: REST_XMM REST_GPR ret ENDFUNC UpdateSHA1ni %endif ;; VxWorks ;;%endif ;; (_IPP32E >= _IPP32E_Y8) %endif ;; _FEATURE_ON_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha1u8as.asm000066400000000000000000000277701470420105600262350ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA1 ; ; Content: ; UpdateSHA1 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA1_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if ((_IPP32E >= _IPP32E_U8 ) && (_IPP32E < _IPP32E_E9 )) || (_IPP32E == _IPP32E_N8 ) ;; ;; SHA1 constants K[i] %xdefine SHA1_K1 (05a827999h) %xdefine SHA1_K2 (06ed9eba1h) %xdefine SHA1_K3 (08f1bbcdch) %xdefine SHA1_K4 (0ca62c1d6h) ;; ;; Magic functions defined in FIPS 180-1 ;; ;; F1, F2, F3 and F4 assumes, that ;; - T1 returns function value ;; - T2 is the temporary ;; %macro F1 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 mov T1,%%C xor T1,%%D and T1,%%B xor T1,%%D %endmacro %macro F2 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 mov T1,%%D xor T1,%%C xor T1,%%B %endmacro %macro F3 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 mov T1,%%C mov T2,%%B or T1,%%B and T2,%%C and T1,%%D or T1,T2 %endmacro %macro F4 3.nolist %xdefine %%B %1 %xdefine %%C %2 %xdefine %%D %3 F2 %%B,%%C,%%D %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; rotations ;; %macro ROL_5 1.nolist %xdefine %%x %1 rol %%x, 5 %endmacro %macro ROL_30 1.nolist %xdefine %%x %1 rol %%x, 30 %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; textual rotation of W array ;; %macro ROTATE_W 0.nolist %xdefine W_minus_32 W_minus_28 %xdefine W_minus_28 W_minus_24 %xdefine W_minus_24 W_minus_20 %xdefine W_minus_20 W_minus_16 %xdefine W_minus_16 W_minus_12 %xdefine W_minus_12 W_minus_08 %xdefine W_minus_08 W_minus_04 %xdefine W_minus_04 W %xdefine W W_minus_32 %endmacro ;; ;; SHA1 update round: ;; - F1 magic is used (and embedded into the macros directly) ;; - 16 bytes of input are swapped ;; %macro SHA1_UPDATE_RND_F1_BSWAP 7.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%nr %6 %xdefine %%Wchunk %7 pshufb %%Wchunk, XMM_SHUFB_BSWAP movdqa W, %%Wchunk paddd %%Wchunk, oword [K_XMM] movdqa oword [rsp + (%%nr & 15)*4], %%Wchunk mov T1,%%C ; F1 mov T2,%%A xor T1,%%D ; F1 and T1,%%B ; F1 ROL_5 T2 xor T1,%%D ; F1 add %%E, T2 ROL_30 %%B add T1, dword [rsp + (%%nr & 15)*4] add %%E,T1 ROTATE_W %endmacro ;; ;; SHA1 update round: ;; - F1 magic is used (and embedded into the macros directly) ;; %macro SHA1_UPDATE_RND_F1 6.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%nr %6 mov T1,%%C ; F1 mov T2,%%A xor T1,%%D ; F1 ROL_5 T2 and T1,%%B ; F1 xor T1,%%D ; F1 add %%E, T2 ROL_30 %%B add T1, dword [rsp + (%%nr & 15)*4] add %%E,T1 %endmacro ;; ;; update W ;; %macro W_CALC 1.nolist %xdefine %%nr %1 %assign %%W_CALC_ahead 8 %assign %%i (%%nr + %%W_CALC_ahead) %if (%%i < 20) %xdefine K_XMM K_BASE %elif (%%i < 40) %xdefine K_XMM K_BASE+16 %elif (%%i < 60) %xdefine K_XMM K_BASE+32 %else %xdefine K_XMM K_BASE+48 %endif %if (%%i < 32) %if ((%%i & 3) == 0) ;; just scheduling to interleave with ALUs movdqa W, W_minus_12 palignr W, W_minus_16, 8 ; w[i-14] movdqa W_TMP, W_minus_04 psrldq W_TMP, 4 ; w[i-3] pxor W, W_minus_08 %elif ((%%i & 3) == 1) pxor W_TMP, W_minus_16 pxor W, W_TMP movdqa W_TMP2, W movdqa W_TMP, W pslldq W_TMP2, 12 %elif ((%%i & 3) == 2) psrld W, 31 pslld W_TMP, 1 por W_TMP, W movdqa W, W_TMP2 psrld W_TMP2, 30 pslld W, 2 %elif ((%%i & 3) == 3) pxor W_TMP, W pxor W_TMP, W_TMP2 movdqa W, W_TMP paddd W_TMP, oword [K_XMM] movdqa oword [rsp + ((%%i & (~3)) & 15)*4],W_TMP ROTATE_W %endif %elif (%%i < 83) %if ((%%i & 3) == 0) ;; scheduling to interleave with ALUs movdqa W_TMP, W_minus_04 pxor W, W_minus_28 ;; W == W_minus_32 palignr W_TMP, W_minus_08, 8 %elif ((%%i & 3) == 1) pxor W, W_minus_16 pxor W, W_TMP movdqa W_TMP, W %elif ((%%i & 3) == 2) psrld W, 30 pslld W_TMP, 2 por W_TMP, W %elif ((%%i & 3) == 3) movdqa W, W_TMP paddd W_TMP, oword [K_XMM] movdqa oword [rsp + ((%%i & (~3)) & 15)*4],W_TMP ROTATE_W %endif %endif %endmacro ;; ;; Regular hash update ;; %macro SHA1_UPDATE_REGULAR 7.nolist %xdefine %%A %1 %xdefine %%B %2 %xdefine %%C %3 %xdefine %%D %4 %xdefine %%E %5 %xdefine %%nr %6 %xdefine %%MagiF %7 W_CALC %%nr add %%E, dword [rsp + (%%nr & 15)*4] %%MagiF %%B,%%C,%%D add %%D, dword [rsp +((%%nr+1) & 15)*4] ROL_30 %%B mov T3,%%A add %%E, T1 ROL_5 T3 add T3, %%E mov %%E, T3 W_CALC %%nr+1 ROL_5 T3 add %%D,T3 %%MagiF %%A,%%B,%%C add %%D, T1 ROL_30 %%A ; write: %1, %2 ; rotate: %1<=%4, %2<=%5, %3<=%1, %4<=%2, %5<=%3 %endmacro ;; update hash macro %macro UPDATE_HASH 2.nolist %xdefine %%hash0 %1 %xdefine %%hashAdd %2 add %%hashAdd, %%hash0 mov %%hash0, %%hashAdd %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR K_XMM_AR dd SHA1_K1, SHA1_K1, SHA1_K1, SHA1_K1 dd SHA1_K2, SHA1_K2, SHA1_K2, SHA1_K2 dd SHA1_K3, SHA1_K3, SHA1_K3, SHA1_K3 dd SHA1_K4, SHA1_K4, SHA1_K4, SHA1_K4 shuffle_mask DD 00010203h DD 04050607h DD 08090a0bh DD 0c0d0e0fh segment .text align=IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA1(DigestSHA1 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;***************************************************************************************** ;; ;; Lib = U8, N8 ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; ;; assign hash values to GPU registers %xdefine A ecx %xdefine B eax %xdefine C edx %xdefine D r8d %xdefine E r9d ;; temporary %xdefine T1 r10d %xdefine T2 r11d %xdefine T3 r13d %xdefine T4 r13d %xdefine W_TMP xmm0 %xdefine W_TMP2 xmm1 %xdefine W0 xmm2 %xdefine W4 xmm3 %xdefine W8 xmm4 %xdefine W12 xmm5 %xdefine W16 xmm6 %xdefine W20 xmm7 %xdefine W24 xmm8 %xdefine W28 xmm9 ;; endianness swap constant %xdefine XMM_SHUFB_BSWAP xmm10 ;; K_BASE contains K_XMM_AR address %xdefine K_BASE r12 align IPP_ALIGN_FACTOR IPPASM UpdateSHA1,PUBLIC %assign LOCAL_FRAME (16*4) USES_GPR rdi,rsi,r12,r13,r14 USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10 COMP_ABI 4 %xdefine MBS_SHA1 (64) movsxd r14, edx movdqa XMM_SHUFB_BSWAP, oword [rel shuffle_mask] ; load shuffle mask lea K_BASE, [rel K_XMM_AR] ; SHA1 const array address ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha1_block_loop: mov A, dword [rdi] ; load initial hash value mov B, dword [rdi+4] mov C, dword [rdi+8] mov D, dword [rdi+12] mov E, dword [rdi+16] movdqu W28, oword [rsi] ; load buffer content movdqu W24, oword [rsi+16] movdqu W20, oword [rsi+32] movdqu W16, oword [rsi+48] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;SHA1_MAIN_BODY %xdefine W W0 %xdefine W_minus_04 W4 %xdefine W_minus_08 W8 %xdefine W_minus_12 W12 %xdefine W_minus_16 W16 %xdefine W_minus_20 W20 %xdefine W_minus_24 W24 %xdefine W_minus_28 W28 %xdefine W_minus_32 W ;; assignment %xdefine K_XMM K_BASE ;;F textequ SHA1_UPDATE_RND_F1_BSWAP A,B,C,D,E, 0, W28 SHA1_UPDATE_RND_F1 E,A,B,C,D, 1 SHA1_UPDATE_RND_F1 D,E,A,B,C, 2 SHA1_UPDATE_RND_F1 C,D,E,A,B, 3 SHA1_UPDATE_RND_F1_BSWAP B,C,D,E,A, 4, W24 SHA1_UPDATE_RND_F1 A,B,C,D,E, 5 SHA1_UPDATE_RND_F1 E,A,B,C,D, 6 SHA1_UPDATE_RND_F1 D,E,A,B,C, 7 SHA1_UPDATE_RND_F1_BSWAP C,D,E,A,B, 8, W20 SHA1_UPDATE_RND_F1 B,C,D,E,A, 9 SHA1_UPDATE_RND_F1 A,B,C,D,E, 10 SHA1_UPDATE_RND_F1 E,A,B,C,D, 11 SHA1_UPDATE_RND_F1_BSWAP D,E,A,B,C, 12, W16 W_CALC 8 W_CALC 9 W_CALC 10 SHA1_UPDATE_RND_F1 C,D,E,A,B, 13 W_CALC 11 W_CALC 12 SHA1_UPDATE_RND_F1 B,C,D,E,A, 14 W_CALC 13 W_CALC 14 W_CALC 15 SHA1_UPDATE_RND_F1 A,B,C,D,E, 15 SHA1_UPDATE_REGULAR E,A,B,C,D,16, F1 SHA1_UPDATE_REGULAR C,D,E,A,B,18, F1 ;;F textequ SHA1_UPDATE_REGULAR A,B,C,D,E,20, F2 SHA1_UPDATE_REGULAR D,E,A,B,C,22, F2 SHA1_UPDATE_REGULAR B,C,D,E,A,24, F2 SHA1_UPDATE_REGULAR E,A,B,C,D,26, F2 SHA1_UPDATE_REGULAR C,D,E,A,B,28, F2 SHA1_UPDATE_REGULAR A,B,C,D,E,30, F2 SHA1_UPDATE_REGULAR D,E,A,B,C,32, F2 SHA1_UPDATE_REGULAR B,C,D,E,A,34, F2 SHA1_UPDATE_REGULAR E,A,B,C,D,36, F2 SHA1_UPDATE_REGULAR C,D,E,A,B,38, F2 ;;F textequ SHA1_UPDATE_REGULAR A,B,C,D,E,40, F3 SHA1_UPDATE_REGULAR D,E,A,B,C,42, F3 SHA1_UPDATE_REGULAR B,C,D,E,A,44, F3 SHA1_UPDATE_REGULAR E,A,B,C,D,46, F3 SHA1_UPDATE_REGULAR C,D,E,A,B,48, F3 SHA1_UPDATE_REGULAR A,B,C,D,E,50, F3 SHA1_UPDATE_REGULAR D,E,A,B,C,52, F3 SHA1_UPDATE_REGULAR B,C,D,E,A,54, F3 SHA1_UPDATE_REGULAR E,A,B,C,D,56, F3 SHA1_UPDATE_REGULAR C,D,E,A,B,58, F3 ;;F textequ SHA1_UPDATE_REGULAR A,B,C,D,E,60, F4 SHA1_UPDATE_REGULAR D,E,A,B,C,62, F4 SHA1_UPDATE_REGULAR B,C,D,E,A,64, F4 SHA1_UPDATE_REGULAR E,A,B,C,D,66, F4 SHA1_UPDATE_REGULAR C,D,E,A,B,68, F4 SHA1_UPDATE_REGULAR A,B,C,D,E,70, F4 SHA1_UPDATE_REGULAR D,E,A,B,C,72, F4 SHA1_UPDATE_REGULAR B,C,D,E,A,74, F4 SHA1_UPDATE_REGULAR E,A,B,C,D,76, F4 SHA1_UPDATE_REGULAR C,D,E,A,B,78, F4 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UPDATE_HASH dword [rdi], A UPDATE_HASH dword [rdi+4], B UPDATE_HASH dword [rdi+8], C UPDATE_HASH dword [rdi+12],D UPDATE_HASH dword [rdi+16],E add rsi, MBS_SHA1 sub r14, MBS_SHA1 jg .sha1_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA1 %endif ;; ((_IPP32E >= _IPP32E_U8 ) AND (_IPP32E < _IPP32E_E9 )) OR (_IPP32E == _IPP32E_N8 ) %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA1_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha256e9as.asm000066400000000000000000000414321470420105600263610ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E == _IPP32E_E9 ) %xdefine W0 xmm0 %xdefine W4 xmm1 %xdefine W8 xmm2 %xdefine W12 xmm3 %xdefine SIG1 xmm4 %xdefine SIG0 xmm5 %xdefine X xmm6 %xdefine W xmm7 %xdefine XMM_SHUFB_BSWAP xmm6 ;; assign hash values to GPU registers %xdefine A eax %xdefine B ebx %xdefine C ecx %xdefine D edx %xdefine E r8d %xdefine F r9d %xdefine G r10d %xdefine H r11d %xdefine T1 r12d %xdefine T2 r13d %xdefine T3 r14d %xdefine T4 r15d ;; we are considering x, y, z are polynomials over GF(2) ;; & - multiplication ;; ^ - additive ;; operations ;; ;; Chj(x,y,z) = (x&y) ^ (~x & z) ;; = (x&y) ^ ((1^x) &z) ;; = (x&y) ^ (z ^ x&z) ;; = x&y ^ z ^ x&z ;; = x&(y^z) ^z ;; %macro Chj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%Y xor %%F, %%Z and %%F, %%X xor %%F, %%Z %endmacro ;; ;; Maj(x,y,z) = (x&y) ^ (x&z) ^ (y&z) ;; = (x&y) ^ (x&z) ^ (y&z) ^ (z&z) ^z // note: ((z&z) ^z) = 0 ;; = x&(y^z) ^ z&(y^z) ^z ;; = (x^z)&(y^z) ^z ;; %macro Maj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%X xor %%F, %%Z xor %%Y, %%Z and %%F, %%Y xor %%Y, %%Z xor %%F, %%Z %endmacro %macro ROTR 2.nolist %xdefine %%X %1 %xdefine %%n %2 shrd %%X,%%X, %%n %endmacro ;; ;; Summ0(x) = ROR(x,2) ^ ROR(x,13) ^ ROR(x,22) ;; %macro Summ0 2.nolist %xdefine %%F %1 %xdefine %%X %2 mov %%F, %%X ROTR %%F, (22-13) xor %%F, %%X ROTR %%F, (13-2) xor %%F, %%X ROTR %%F, 2 %endmacro ;; ;; Summ1(x) = ROR(x,6) ^ ROR(x,11) ^ ROR(x,25) ;; %macro Summ1 2.nolist %xdefine %%F %1 %xdefine %%X %2 mov %%F, %%X ROTR %%F, (25-11) xor %%F, %%X ROTR %%F, (11-6) xor %%F, %%X ROTR %%F, 6 %endmacro ;; ;; regular round (i): ;; ;; T1 = h + Sigma1(e) + Ch(e,f,g) + K[i] + W[i] ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h = g ;; g = f ;; f = e ;; e = d + T1 ;; d = c ;; c = b ;; b = a ;; a = T1+T2 ;; ;; or ;; ;; h += Sigma1(e) + Ch(e,f,g) + K[i] + W[i] (==T1) ;; d += h ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h += T2 ;; and following textual shift {a,b,c,d,e,f,g,h} => {h,a,b,c,d,e,f,g} ;; %macro ROUND 11.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 %xdefine %%T1 %10 %xdefine %%T2 %11 add %%H, dword [rsp+(%%nr & 3)*sizeof(dword)] Summ1 %%T1, %%E Chj %%T2, %%E,%%F,%%G add %%H, %%T1 add %%H, %%T2 add %%D, %%H Summ0 %%T1, %%A Maj %%T2, %%A,%%B,%%C add %%H, %%T1 add %%H, %%T2 %endmacro %macro ROUND_v1 12.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 %xdefine %%T1 %10 %xdefine %%T2 %11 %xdefine %%T3 %12 Summ1 %%T1, %%E ;; S1 Chj %%T2, %%E,%%F,%%G ;; CH add %%H, dword [rsp+(%%nr & 3)*sizeof(dword)] add %%H, %%T1 add %%H, %%T2 Maj %%T1, %%A,%%B,%%C ;; MAJ Summ0 %%T2, %%A ;; S0 add %%D, %%H add %%H, %%T1 add %%H, %%T2 %endmacro ;; W[i] = Sigma1(W[i-2]) + W[i-7] + Sigma0(W[i-15]) + W[i-16], i=16,..,63 ;; ;;for next rounds 16,17,18 and 19: ;; W[0] <= W[16] = Sigma1(W[14]) + W[ 9] + Sigma0(W[1]) + W[0] ;; W[1] <= W[17] = Sigma1(W[15]) + W[10] + Sigma0(W[2]) + W[1] ;; W[2] <= W[18] = Sigma1(W[ 0]) + W[11] + Sigma0(W[3]) + W[2] ;; W[3] <= W[19] = Sigma1(W[ 1]) + W[12] + Sigma0(W[4]) + W[3] ;; ;; the process is repeated exactly because textual round of W[] ;; ;; Sigma1() and Sigma0() functions are defined as following: ;; Sigma1(X) = ROR(X,17)^ROR(X,19)^SHR(X,10) ;; Sigma0(X) = ROR(X, 7)^ROR(X,18)^SHR(X, 3) ;; %macro UPDATE_W 8.nolist %xdefine %%xS0 %1 %xdefine %%xS4 %2 %xdefine %%xS8 %3 %xdefine %%xS12 %4 %xdefine %%SIGMA %5 %xdefine %%xS %6 %xdefine %%xT %7 %xdefine %%phase %8 %if %%phase == 0 ;; SIGMA0 vpalignr %%xS, %%xS4, %%xS0, 4 ;; xS = {W04,W03,W02,W01} vpsrld %%SIGMA, %%xS, 3 ;; SIGMA0 = SHR({W04,W03,W02,W01},3) vpsrld %%xT, %%xS, 7 ;; SIGMA0 ^= SHR({W04,W03,W02,W01},7) vpxor %%SIGMA, %%SIGMA, %%xT vpsrld %%xT, %%xS, 18 ;; SIGMA0 ^= SHR({W04,W03,W02,W01},18) vpxor %%SIGMA, %%SIGMA, %%xT vpslld %%xT, %%xS, (32-18) ;; SIGMA0 ^= SHL({W04,W03,W02,W01},32-18) vpxor %%SIGMA, %%SIGMA, %%xT vpslld %%xT, %%xS, (32-7) ;; SIGMA0 ^= SHL({W04,W03,W02,W01},32-7) vpxor %%SIGMA, %%SIGMA, %%xT %endif %if %%phase == 1 vpalignr %%xS, %%xS12,%%xS8, 4 ;; xS = {W12,W11,W10,W09} vpaddd %%xS0, %%xS0, %%xS ;; xS0 = xS0 + {W12,W11,W10,W09} + SIGMA0 vpaddd %%xS0, %%xS0, %%SIGMA %endif %if %%phase == 2 ;; SIGMA1 (low) vpshufd %%xS, %%xS12, 11111010b ;; xS = {W[15],W[15],W[14],W[14]} vpsrld %%SIGMA, %%xS, 10 ;; SIGMA1 = SHR({W[15],W[15],W[14],W[14]},10) vpsrlq %%xT, %%xS, 17 ;; xT = SHR({W[15],W[15],W[14],W[14]},17) vpsrlq %%xS, %%xS, 19 ;; xS = SHR({W[15],W[15],W[14],W[14]},19) vpxor %%SIGMA, %%SIGMA, %%xT vpxor %%SIGMA, %%SIGMA, %%xS ;; SIGMA1 ^= xT ^ xS vpshufb %%SIGMA, %%SIGMA, [rel SHUFD_ZZ10] ;; SIGMA1 = {zzz,zzz,SIGMA1.1,SIGMA1.0} vpaddd %%xS0, %%xS0, %%SIGMA ;; {???,???,new W01,new W00} = {??,??,W17,W16} %endif %if %%phase == 3 ;; SIGMA1 (high) vpshufd %%xS, %%xS0, 01010000b ;; xS = {W17,W17,W16,W16} vpsrld %%SIGMA, %%xS, 10 ;; SIGMA1 = SHR({W[17],W[17],W[16],W[16]},10) vpsrlq %%xT, %%xS, 17 ;; xT = ROTR({W[17],W[17],W[16],W[16]},17)- low 32 rotation in fact vpsrlq %%xS, %%xS, 19 ;; xS = RORR({W[17],W[17],W[16],W[16]},19) - low 32 rotation in fact vpxor %%SIGMA, %%SIGMA, %%xT vpxor %%SIGMA, %%SIGMA, %%xS ;; SIGMA1 ^= xT ^ xS vpshufb %%SIGMA, %%SIGMA, [rel SHUFD_32ZZ] ;; SIGMA1 = {SIGMA1.3,SIGMA1.2,zzz,zzz} vpaddd %%xS0, %%xS0, %%SIGMA ;; {new W03, new W02,new W01,new W00} = {W19,W18,W17,W16} %endif %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SHUFB_BSWAP DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 SHUFD_ZZ10 DB 0,1,2,3, 8,9,10,11, 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh SHUFD_32ZZ DB 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh, 0,1,2,3, 8,9,10,11 segment .text align=IPP_ALIGN_FACTOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; UpdateSHA256(Ipp32u digest[], Ipp8u dataBlock[], int datalen, Ipp32u K_256[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC %assign LOCAL_FRAME sizeof(oword)+sizeof(qword) USES_GPR rbx,rsi,rdi,rbp,r12,r13,r14,r15 USES_XMM xmm6,xmm7 COMP_ABI 4 ;; ;; rdi = pointer to the updated hash ;; rsi = pointer to the data block ;; rdx = data block length ;; rcx = pointer to the SHA_256 constant ;; %xdefine MBS_SHA256 (64) movsxd rdx, edx mov qword [rsp+sizeof(oword)], rdx ; save length of buffer mov rbp, rcx ; rbp points K_256[] constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .sha256_block_loop: vmovdqu W0, oword [rsi] ; load buffer content and swap vpshufb W0, W0, [rel SHUFB_BSWAP] vmovdqu W4, oword [rsi+sizeof(oword)] vpshufb W4, W4, [rel SHUFB_BSWAP] vmovdqu W8, oword [rsi+sizeof(oword)*2] vpshufb W8, W8, [rel SHUFB_BSWAP] vmovdqu W12,oword [rsi+sizeof(oword)*3] vpshufb W12,W12, [rel SHUFB_BSWAP] mov A, dword [rdi] ; load initial hash value mov B, dword [rdi+sizeof(dword)] mov C, dword [rdi+sizeof(dword)*2] mov D, dword [rdi+sizeof(dword)*3] mov E, dword [rdi+sizeof(dword)*4] mov F, dword [rdi+sizeof(dword)*5] mov G, dword [rdi+sizeof(dword)*6] mov H, dword [rdi+sizeof(dword)*7] ;; perform 0-3 regular rounds vpaddd W, W0, oword [rbp+sizeof(oword)*0] ; T += K_SHA256[0-3] vmovdqa oword [rsp], W UPDATE_W W0,W4,W8,W12, SIG1,W,X, 0 ; update for round: 16-19 ROUND 0, A,B,C,D,E,F,G,H, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 1 ROUND 1, H,A,B,C,D,E,F,G, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 2 ROUND 2, G,H,A,B,C,D,E,F, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 3 ROUND 3, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 4-7 regular rounds vpaddd W, W4, oword [rbp+sizeof(oword)*1] ; T += K_SHA256[4-7] vmovdqa oword [rsp], W UPDATE_W W4,W8,W12,W0, SIG1,W,X, 0 ; update for round: 20-23 ROUND 4, E,F,G,H,A,B,C,D, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 1 ROUND 5, D,E,F,G,H,A,B,C, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 2 ROUND 6, C,D,E,F,G,H,A,B, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 3 ROUND 7, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 8-11 regular rounds vpaddd W, W8, oword [rbp+sizeof(oword)*2] ; T += K_SHA256[8-11] vmovdqa oword [rsp], W UPDATE_W W8,W12,W0,W4, SIG1,W,X, 0 ; update for round: 24-27 ROUND 8, A,B,C,D,E,F,G,H, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 1 ROUND 9, H,A,B,C,D,E,F,G, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 2 ROUND 10, G,H,A,B,C,D,E,F, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 3 ROUND 11, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 12-15 regular rounds vpaddd W, W12, oword [rbp+sizeof(oword)*3] ; T += K_SHA256[12-15] vmovdqa oword [rsp], W UPDATE_W W12,W0,W4,W8, SIG1,W,X, 0 ; update for round: 28-31 ROUND 12, E,F,G,H,A,B,C,D, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 1 ROUND 13, D,E,F,G,H,A,B,C, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 2 ROUND 14, C,D,E,F,G,H,A,B, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 3 ROUND 15, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 16-19 regular rounds vpaddd W, W0, oword [rbp+sizeof(oword)*4] ; T += K_SHA256[16-19] vmovdqa oword [rsp], W UPDATE_W W0,W4,W8,W12, SIG1,W,X, 0 ; update for round: 32-35 ROUND 16, A,B,C,D,E,F,G,H, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 1 ROUND 17, H,A,B,C,D,E,F,G, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 2 ROUND 18, G,H,A,B,C,D,E,F, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 3 ROUND 19, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 20-23 regular rounds vpaddd W, W4, oword [rbp+sizeof(oword)*5] ; T += K_SHA256[20-23] vmovdqa oword [rsp], W UPDATE_W W4,W8,W12,W0, SIG1,W,X, 0 ; update for round: 36-39 ROUND 20, E,F,G,H,A,B,C,D, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 1 ROUND 21, D,E,F,G,H,A,B,C, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 2 ROUND 22, C,D,E,F,G,H,A,B, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 3 ROUND 23, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 24-27 regular rounds vpaddd W, W8, oword [rbp+sizeof(oword)*6] ; T += K_SHA256[24-27] vmovdqa oword [rsp], W UPDATE_W W8,W12,W0,W4, SIG1,W,X, 0 ; update for round: 40-43 ROUND 24, A,B,C,D,E,F,G,H, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 1 ROUND 25, H,A,B,C,D,E,F,G, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 2 ROUND 26, G,H,A,B,C,D,E,F, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 3 ROUND 27, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 28-31 regular rounds vpaddd W, W12, oword [rbp+sizeof(oword)*7] ; T += K_SHA256[28-31] vmovdqa oword [rsp], W UPDATE_W W12,W0,W4,W8, SIG1,W,X, 0 ; update for round: 44-47 ROUND 28, E,F,G,H,A,B,C,D, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 1 ROUND 29, D,E,F,G,H,A,B,C, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 2 ROUND 30, C,D,E,F,G,H,A,B, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 3 ROUND 31, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 32-35 regular rounds vpaddd W, W0, oword [rbp+sizeof(oword)*8] ; T += K_SHA256[32-35] vmovdqa oword [rsp], W UPDATE_W W0,W4,W8,W12, SIG1,W,X, 0 ; update for round: 48-51 ROUND 32, A,B,C,D,E,F,G,H, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 1 ROUND 33, H,A,B,C,D,E,F,G, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 2 ROUND 34, G,H,A,B,C,D,E,F, T1,T2 UPDATE_W W0,W4,W8,W12, SIG1,W,X, 3 ROUND 35, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 36-39 regular rounds vpaddd W, W4, oword [rbp+sizeof(oword)*9] ; T += K_SHA256[36-39] vmovdqa oword [rsp], W UPDATE_W W4,W8,W12,W0, SIG1,W,X, 0 ; update for round: 52-55 ROUND 36, E,F,G,H,A,B,C,D, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 1 ROUND 37, D,E,F,G,H,A,B,C, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 2 ROUND 38, C,D,E,F,G,H,A,B, T1,T2 UPDATE_W W4,W8,W12,W0, SIG1,W,X, 3 ROUND 39, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 40-43 regular rounds vpaddd W, W8, oword [rbp+sizeof(oword)*10] ; T += K_SHA256[40-43] vmovdqa oword [rsp], W UPDATE_W W8,W12,W0,W4, SIG1,W,X, 0 ; update for round: 56-59 ROUND 40, A,B,C,D,E,F,G,H, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 1 ROUND 41, H,A,B,C,D,E,F,G, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 2 ROUND 42, G,H,A,B,C,D,E,F, T1,T2 UPDATE_W W8,W12,W0,W4, SIG1,W,X, 3 ROUND 43, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 44-47 regular rounds vpaddd W, W12, oword [rbp+sizeof(oword)*11] ; T += K_SHA256[44-47] vmovdqa oword [rsp], W UPDATE_W W12,W0,W4,W8, SIG1,W,X, 0 ; update for round: 60-63 ROUND 44, E,F,G,H,A,B,C,D, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 1 ROUND 45, D,E,F,G,H,A,B,C, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 2 ROUND 46, C,D,E,F,G,H,A,B, T1,T2 UPDATE_W W12,W0,W4,W8, SIG1,W,X, 3 ROUND 47, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 48-51 regular rounds vpaddd W, W0, oword [rbp+sizeof(oword)*12] ; T += K_SHA256[48-51] vmovdqa oword [rsp], W ROUND 48, A,B,C,D,E,F,G,H, T1,T2 ROUND 49, H,A,B,C,D,E,F,G, T1,T2 ROUND 50, G,H,A,B,C,D,E,F, T1,T2 ROUND 51, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 52-55 regular rounds vpaddd W, W4, oword [rbp+sizeof(oword)*13] ; T += K_SHA256[52-55] vmovdqa oword [rsp], W ROUND 52, E,F,G,H,A,B,C,D, T1,T2 ROUND 53, D,E,F,G,H,A,B,C, T1,T2 ROUND 54, C,D,E,F,G,H,A,B, T1,T2 ROUND 55, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 56-59 regular rounds vpaddd W, W8, oword [rbp+sizeof(oword)*14] ; T += K_SHA256[56-59] vmovdqa oword [rsp], W ROUND 56, A,B,C,D,E,F,G,H, T1,T2 ROUND 57, H,A,B,C,D,E,F,G, T1,T2 ROUND 58, G,H,A,B,C,D,E,F, T1,T2 ROUND 59, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 60-63 regular rounds vpaddd W, W12, oword [rbp+sizeof(oword)*15] ; T += K_SHA256[60-63] vmovdqa oword [rsp], W ROUND 60, E,F,G,H,A,B,C,D, T1,T2 ROUND 61, D,E,F,G,H,A,B,C, T1,T2 ROUND 62, C,D,E,F,G,H,A,B, T1,T2 ROUND 63, B,C,D,E,F,G,H,A, T1,T2 add dword [rdi], A ; update shash add dword [rdi+sizeof(dword)*1], B add dword [rdi+sizeof(dword)*2], C add dword [rdi+sizeof(dword)*3], D add dword [rdi+sizeof(dword)*4], E add dword [rdi+sizeof(dword)*5], F add dword [rdi+sizeof(dword)*6], G add dword [rdi+sizeof(dword)*7], H add rsi, MBS_SHA256 sub qword [rsp+sizeof(oword)], MBS_SHA256 jg .sha256_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; _IPP32E_E9 and above %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha256l9as.asm000066400000000000000000000450111470420105600263650ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2017 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_L9 ) ;; ;; assignments ;; %xdefine hA eax ;; hash values into GPU registers %xdefine hB ebx %xdefine hC ecx %xdefine hD edx %xdefine hE r8d %xdefine hF r9d %xdefine hG r10d %xdefine hH r11d %xdefine T1 r12d ;; scratch %xdefine T2 r13d %xdefine T3 r14d %xdefine T4 r15d %xdefine T5 edi %xdefine W0 ymm0 ;; W values into YMM registers %xdefine W1 ymm1 %xdefine W2 ymm2 %xdefine W3 ymm3 %xdefine yT1 ymm4 ;; scratch %xdefine yT2 ymm5 %xdefine yT3 ymm6 %xdefine yT4 ymm7 %xdefine W0L xmm0 %xdefine W1L xmm1 %xdefine W2L xmm2 %xdefine W3L xmm3 %xdefine YMM_zzBA ymm8 ;; byte swap constant %xdefine YMM_DCzz ymm9 ;; byte swap constant %xdefine YMM_SHUFB_BSWAP ymm10 ;; byte swap constant ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; textual rotation of W args ;; %macro ROTATE_W 0.nolist %xdefine %%_X W0 %xdefine W0 W1 %xdefine W1 W2 %xdefine W2 W3 %xdefine W3 %%_X %endmacro ;; ;; textual rotation of HASH arguments ;; %macro ROTATE_H 0.nolist %xdefine %%_X hH %xdefine hH hG %xdefine hG hF %xdefine hF hE %xdefine hE hD %xdefine hD hC %xdefine hC hB %xdefine hB hA %xdefine hA %%_X %endmacro %macro ROTATE_T4_T5 0.nolist %xdefine %%T T4 %xdefine T4 T5 %xdefine T5 %%T %endmacro ;; ;; compute next 4 W[t], W[t+1], W[t+2] and W[t+3], t=16,...63 ;; (see pcpsha256e9as.asm for details) %macro UPDATE_W 5.nolist %xdefine %%nr %1 %xdefine %%W0 %2 %xdefine %%W1 %3 %xdefine %%W2 %4 %xdefine %%W3 %5 %assign %%W_AHEAD 16 vpalignr yT3,%%W1,%%W0,4 vpalignr yT2,%%W3,%%W2,4 vpsrld yT1,yT3,7 vpaddd %%W0,%%W0,yT2 vpsrld yT2,yT3,3 vpslld yT4,yT3,14 vpxor yT3,yT2,yT1 vpshufd yT2,%%W3,250 vpsrld yT1,yT1,11 vpxor yT3,yT3,yT4 vpslld yT4,yT4,11 vpxor yT3,yT3,yT1 vpsrld yT1,yT2,10 vpxor yT3,yT3,yT4 vpsrlq yT2,yT2,17 vpaddd %%W0,%%W0,yT3 vpxor yT1,yT1,yT2 vpsrlq yT2,yT2,2 vpxor yT1,yT1,yT2 vpshufb yT1,yT1,YMM_zzBA vpaddd %%W0,%%W0,yT1 vpshufd yT2,%%W0,80 vpsrld yT1,yT2,10 vpsrlq yT2,yT2,17 vpxor yT1,yT1,yT2 vpsrlq yT2,yT2,2 vpxor yT1,yT1,yT2 vpshufb yT1,yT1,YMM_DCzz vpaddd %%W0,%%W0,yT1 vpaddd yT1,%%W0,YMMWORD [rbp+(%%nr/4)*sizeof(ymmword)] vmovdqa YMMWORD [rsi+(%%W_AHEAD/4)*sizeof(ymmword)+(%%nr/4)*sizeof(ymmword)],yT1 %endmacro ;; ;; regular round (i): ;; ;; T1 = h + Sum1(e) + Ch(e,f,g) + K[i] + W[i] ;; T2 = Sum0(a) + Maj(a,b,c) ;; h = g ;; g = f ;; f = e ;; e = d + T1 ;; d = c ;; c = b ;; b = a ;; a = T1+T2 ;; ;; sum1(e) = (e>>>25)^(e>>>11)^(e>>>6) ;; sum0(a) = (a>>>13)^(a>>>22)^(a>>>2) ;; ch(e,f,g) = (e&f)^(~e^g) ;; maj(a,b,m)= (a&b)^(a&c)^(b&c) ;; ;; note: ;; 1) U + ch(e,f,g) = U + (e&f) & (~e&g) ;; 2) maj(a,b,c)= (a&b)^(a&c)^(b&c) = (a^b)&(b^c) ^b ;; to make sure both are correct - use GF(2) arith instead of logic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; or ;; X = sum0(a[i-1]) computed on prev round ;; a[i] += X ;; h[i] += (K[i]+W[i]) + sum1(e[i]) + ch(e[i],f[i],g[i]) or ;; h[i] += (K[i]+W[i]) + sum1(e[i]) + (e[i]&f[i]) + (~e[i]&g[i]) -- helps break dependencies ;; d[i] += h[i] ;; h[i] += maj(a[i],b[i],c[i]) ;; and following textual shift ;; {a[i+1],b[i+1],c[i+1],d[i+1],e[i+1],f[i+1],g[i+1],h[i+1]} <= {h[i],a[i],b[i],c[i],d[i],e[i],f[i],g[i]} ;; ;; on entry: ;; - T1 = f ;; - T3 = sum0{a[i-1]) ;; - T5 = b&c %macro SHA256_ROUND 9.nolist %xdefine %%nr %1 %xdefine %%hA %2 %xdefine %%hB %3 %xdefine %%hC %4 %xdefine %%hD %5 %xdefine %%hE %6 %xdefine %%hF %7 %xdefine %%hG %8 %xdefine %%hH %9 add %%hH, dword [rsi+(%%nr/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] ;; h += (k[t]+w[t]) and T1, %%hE ;; ch(e,f,g): (f&e) rorx T2, %%hE, 25 ;; sum1(e): e>>>25 rorx T4, %%hE, 11 ;; sum1(e): e>>>11 add %%hA, T3 ;; complete computation a += sum0(a[t-1]) add %%hH, T1 ;; h += (k[t]+w[t]) + (f&e) andn T1, %%hE, %%hG ;; ch(e,f,g): (~e&g) xor T2, T4 ;; sum1(e): (e>>>25)^(e>>>11) rorx T3, %%hE, 6 ;; sum1(e): e>>>6 add %%hH, T1 ;; h += (k[t]+w[t]) + (f&e) + (~e&g) xor T2, T3 ;; sum1(e) = (e>>>25)^(e>>>11)^(e>>>6) mov T4, %%hA ;; maj(a,b,c): a rorx T1, %%hA, 22 ;; sum0(a): a>>>22 add %%hH, T2 ;; h += (k[t]+w[t]) +(f&e) +(~e&g) +sig1(e) xor T4, %%hB ;; maj(a,b,c): (a^b) rorx T3, %%hA, 13 ;; sum0(a): a>>>13 rorx T2, %%hA, 2 ;; sum0(a): a>>>2 add %%hD, %%hH ;; d += h and T5, T4 ;; maj(a,b,c): (b^c)&(a^b) xor T3, T1 ;; sum0(a): (a>>>13)^(a>>>22) xor T5, %%hB ;; maj(a,b,c) = (b^c)&(a^b)^b = (a&b)^(a&c)^(b&c) xor T3, T2 ;; sum0(a): = (a>>>13)^(a>>>22)^(a>>>2) add %%hH, T5 ;; h += (k[t]+w[t]) +(f&e) +(~e&g) +sig1(e) +maj(a,b,c) mov T1, %%hE ;; T1 = f (next round) ROTATE_T4_T5 ;; T5 = (b^c) (next round) %endmacro ;; ;; does 4 regular rounds and computes next 4 W values ;; (just 4 instances of SHA256_ROUND merged together with UPDATE_W) ;; %macro SHA256_4ROUND_SHED 1.nolist %xdefine %%round %1 %assign %%W_AHEAD 16 vpalignr yT3,W1,W0,4 %assign %%nr %%round add hH, dword [rsi+(%%nr/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] and T1, hE rorx T2, hE, 25 vpalignr yT2,W3,W2,4 rorx T4, hE, 11 add hA, T3 add hH, T1 vpsrld yT1,yT3,7 andn T1, hE, hG xor T2, T4 rorx T3, hE, 6 vpaddd W0,W0,yT2 add hH, T1 xor T2, T3 mov T4, hA vpsrld yT2,yT3,3 rorx T1, hA, 22 add hH, T2 xor T4, hB vpslld yT4,yT3,14 rorx T3, hA, 13 rorx T2, hA, 2 add hD, hH vpxor yT3,yT2,yT1 and T5, T4 xor T3, T1 xor T5, hB vpshufd yT2,W3,250 xor T3, T2 add hH, T5 mov T1, hE ROTATE_T4_T5 ROTATE_H vpsrld yT1,yT1,11 %assign %%nr %%nr+1 add hH, dword [rsi+(%%nr/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] and T1, hE rorx T2, hE, 25 vpxor yT3,yT3,yT4 rorx T4, hE, 11 add hA, T3 add hH, T1 vpslld yT4,yT4,11 andn T1, hE, hG xor T2, T4 rorx T3, hE, 6 vpxor yT3,yT3,yT1 add hH, T1 xor T2, T3 mov T4, hA vpsrld yT1,yT2,10 rorx T1, hA, 22 add hH, T2 xor T4, hB vpxor yT3,yT3,yT4 rorx T3, hA, 13 rorx T2, hA, 2 add hD, hH vpsrlq yT2,yT2,17 and T5, T4 xor T3, T1 xor T5, hB vpaddd W0,W0,yT3 xor T3, T2 add hH, T5 mov T1, hE ROTATE_T4_T5 ROTATE_H vpxor yT1,yT1,yT2 %assign %%nr %%nr+1 add hH, dword [rsi+(%%nr/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] and T1, hE rorx T2, hE, 25 vpsrlq yT2,yT2,2 rorx T4, hE, 11 add hA, T3 add hH, T1 vpxor yT1,yT1,yT2 andn T1, hE, hG xor T2, T4 rorx T3, hE, 6 vpshufb yT1,yT1,YMM_zzBA add hH, T1 xor T2, T3 mov T4, hA vpaddd W0,W0,yT1 rorx T1, hA, 22 add hH, T2 xor T4, hB vpshufd yT2,W0,80 rorx T3, hA, 13 rorx T2, hA, 2 add hD, hH vpsrld yT1,yT2,10 and T5, T4 xor T3, T1 xor T5, hB vpsrlq yT2,yT2,17 xor T3, T2 add hH, T5 mov T1, hE ROTATE_T4_T5 ROTATE_H vpxor yT1,yT1,yT2 %assign %%nr %%nr+1 add hH, dword [rsi+(%%nr/4)*sizeof(ymmword)+(%%nr & 3)*sizeof(dword)] and T1, hE rorx T2, hE, 25 vpsrlq yT2,yT2,2 rorx T4, hE, 11 add hA, T3 add hH, T1 vpxor yT1,yT1,yT2 andn T1, hE, hG xor T2, T4 rorx T3, hE, 6 vpshufb yT1,yT1,YMM_DCzz add hH, T1 xor T2, T3 mov T4, hA vpaddd W0,W0,yT1 rorx T1, hA, 22 add hH, T2 xor T4, hB vpaddd yT1,W0,YMMWORD [rbp+(%%nr/4)*sizeof(ymmword)] rorx T3, hA, 13 rorx T2, hA, 2 add hD, hH and T5, T4 xor T3, T1 xor T5, hB vmovdqa YMMWORD [rsi+(%%W_AHEAD/4)*sizeof(ymmword)+(%%round/4)*sizeof(ymmword)],yT1 xor T3, T2 add hH, T5 mov T1, hE ROTATE_T4_T5 ROTATE_H ROTATE_W %endmacro ;; ;; update hash ;; %macro UPDATE_HASH 2.nolist %xdefine %%hashMem %1 %xdefine %%hash %2 add %%hash, %%hashMem mov %%hashMem, %%hash %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SHA256_YMM_K dd 0428a2f98h, 071374491h, 0b5c0fbcfh, 0e9b5dba5h, 0428a2f98h, 071374491h, 0b5c0fbcfh, 0e9b5dba5h dd 03956c25bh, 059f111f1h, 0923f82a4h, 0ab1c5ed5h, 03956c25bh, 059f111f1h, 0923f82a4h, 0ab1c5ed5h dd 0d807aa98h, 012835b01h, 0243185beh, 0550c7dc3h, 0d807aa98h, 012835b01h, 0243185beh, 0550c7dc3h dd 072be5d74h, 080deb1feh, 09bdc06a7h, 0c19bf174h, 072be5d74h, 080deb1feh, 09bdc06a7h, 0c19bf174h dd 0e49b69c1h, 0efbe4786h, 00fc19dc6h, 0240ca1cch, 0e49b69c1h, 0efbe4786h, 00fc19dc6h, 0240ca1cch dd 02de92c6fh, 04a7484aah, 05cb0a9dch, 076f988dah, 02de92c6fh, 04a7484aah, 05cb0a9dch, 076f988dah dd 0983e5152h, 0a831c66dh, 0b00327c8h, 0bf597fc7h, 0983e5152h, 0a831c66dh, 0b00327c8h, 0bf597fc7h dd 0c6e00bf3h, 0d5a79147h, 006ca6351h, 014292967h, 0c6e00bf3h, 0d5a79147h, 006ca6351h, 014292967h dd 027b70a85h, 02e1b2138h, 04d2c6dfch, 053380d13h, 027b70a85h, 02e1b2138h, 04d2c6dfch, 053380d13h dd 0650a7354h, 0766a0abbh, 081c2c92eh, 092722c85h, 0650a7354h, 0766a0abbh, 081c2c92eh, 092722c85h dd 0a2bfe8a1h, 0a81a664bh, 0c24b8b70h, 0c76c51a3h, 0a2bfe8a1h, 0a81a664bh, 0c24b8b70h, 0c76c51a3h dd 0d192e819h, 0d6990624h, 0f40e3585h, 0106aa070h, 0d192e819h, 0d6990624h, 0f40e3585h, 0106aa070h dd 019a4c116h, 01e376c08h, 02748774ch, 034b0bcb5h, 019a4c116h, 01e376c08h, 02748774ch, 034b0bcb5h dd 0391c0cb3h, 04ed8aa4ah, 05b9cca4fh, 0682e6ff3h, 0391c0cb3h, 04ed8aa4ah, 05b9cca4fh, 0682e6ff3h dd 0748f82eeh, 078a5636fh, 084c87814h, 08cc70208h, 0748f82eeh, 078a5636fh, 084c87814h, 08cc70208h dd 090befffah, 0a4506cebh, 0bef9a3f7h, 0c67178f2h, 090befffah, 0a4506cebh, 0bef9a3f7h, 0c67178f2h SHA256_YMM_BF dd 000010203h, 004050607h, 008090a0bh, 00c0d0e0fh, 000010203h, 004050607h, 008090a0bh, 00c0d0e0fh SHA256_DCzz db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh, 0,1,2,3, 8,9,10,11 db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh, 0,1,2,3, 8,9,10,11 SHA256_zzBA db 0,1,2,3, 8,9,10,11, 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh db 0,1,2,3, 8,9,10,11, 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh segment .text align=IPP_ALIGN_FACTOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; UpdateSHA256(Ipp32u digest[], Ipp8u dataBlock[], int datalen, Ipp32u K_256[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC %assign LOCAL_FRAME (sizeof(qword)*4 + sizeof(dword)*64*2) USES_GPR rbx,rsi,rdi,rbp,rbx,r12,r13,r14,r15 USES_XMM_AVX xmm6,xmm7,xmm8,xmm9,xmm10 COMP_ABI 4 ;; ;; rdi = pointer to the updated hash ;; rsi = pointer to the data block ;; rdx = data block length ;; rcx = pointer to the SHA_256 constant (ignored) ;; %xdefine MBS_SHA256 (64) ;; ;; stack structure: ;; %assign _block 0 ;; block address %assign _hash _block+sizeof(qword) ;; hash address %assign _len _hash+sizeof(qword) ;; rest of processed data %assign _frame _len+sizeof(qword) ;; rsp before alignment %assign _dataW _frame+sizeof(qword) ;; W[t] values mov r15, rsp ; store orifinal rsp and rsp, -IPP_ALIGN_FACTOR ; 32-byte aligned stack movsxd r14, edx ; input length in bytes mov qword [rsp+_hash], rdi ; store hash address mov qword [rsp+_len], r14 ; store length mov qword [rsp+_frame], r15 ; store rsp mov hA, dword [rdi] ; load initial hash value mov hB, dword [rdi+1*sizeof(dword)] mov hC, dword [rdi+2*sizeof(dword)] mov hD, dword [rdi+3*sizeof(dword)] mov hE, dword [rdi+4*sizeof(dword)] mov hF, dword [rdi+5*sizeof(dword)] mov hG, dword [rdi+6*sizeof(dword)] mov hH, dword [rdi+7*sizeof(dword)] vmovdqa YMM_SHUFB_BSWAP, ymmword [rel SHA256_YMM_BF] ; load byte shuffler vmovdqa YMM_zzBA, ymmword [rel SHA256_zzBA] ; load byte shuffler (zzBA) vmovdqa YMM_DCzz, ymmword [rel SHA256_DCzz] ; load byte shuffler (DCzz) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data 2 block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .sha256_block2_loop: lea r12, [rsi+MBS_SHA256] ; next block cmp r14, MBS_SHA256 ; %if single block processed cmovbe r12, rsi ; use the same data block address lea rbp, [rel SHA256_YMM_K] ; to SHA256 consts vmovdqu W0L, xmmword [rsi] ; load data block vmovdqu W1L, xmmword [rsi+1*sizeof(xmmword)] vmovdqu W2L, xmmword [rsi+2*sizeof(xmmword)] vmovdqu W3L, xmmword [rsi+3*sizeof(xmmword)] vinserti128 W0, W0, xmmword [r12], 1 ; merge next data block vinserti128 W1, W1, xmmword [r12+1*sizeof(xmmword)], 1 vinserti128 W2, W2, xmmword [r12+2*sizeof(xmmword)], 1 vinserti128 W3, W3, xmmword [r12+3*sizeof(xmmword)], 1 vpshufb W0, W0, YMM_SHUFB_BSWAP vpshufb W1, W1, YMM_SHUFB_BSWAP vpshufb W2, W2, YMM_SHUFB_BSWAP vpshufb W3, W3, YMM_SHUFB_BSWAP vpaddd yT1, W0, ymmword [rbp] vpaddd yT2, W1, ymmword [rbp+1*sizeof(ymmword)] vpaddd yT3, W2, ymmword [rbp+2*sizeof(ymmword)] vpaddd yT4, W3, ymmword [rbp+3*sizeof(ymmword)] add rbp, 4*sizeof(ymmword) vmovdqa ymmword [rsp+_dataW], yT1 vmovdqa ymmword [rsp+_dataW+1*sizeof(ymmword)], yT2 vmovdqa ymmword [rsp+_dataW+2*sizeof(ymmword)], yT3 vmovdqa ymmword [rsp+_dataW+3*sizeof(ymmword)], yT4 mov T5, hB ; T5 = b^c xor T3, T3 ; T3 = 0 mov T1, hF ; T1 = f xor T5, hC mov qword [rsp+_block], rsi ; store block address lea rsi, [rsp+_dataW] ; use rsi as stack pointer align IPP_ALIGN_FACTOR .block1_shed_proc: SHA256_4ROUND_SHED 0 SHA256_4ROUND_SHED 4 SHA256_4ROUND_SHED 8 SHA256_4ROUND_SHED 12 add rsi, 4*sizeof(ymmword) add rbp, 4*sizeof(ymmword) ;; and repeat cmp dword [rbp-sizeof(dword)],0c67178f2h jne .block1_shed_proc ;; the rest 16 rounds SHA256_ROUND 0, hA,hB,hC,hD,hE,hF,hG,hH SHA256_ROUND 1, hH,hA,hB,hC,hD,hE,hF,hG SHA256_ROUND 2, hG,hH,hA,hB,hC,hD,hE,hF SHA256_ROUND 3, hF,hG,hH,hA,hB,hC,hD,hE SHA256_ROUND 4, hE,hF,hG,hH,hA,hB,hC,hD SHA256_ROUND 5, hD,hE,hF,hG,hH,hA,hB,hC SHA256_ROUND 6, hC,hD,hE,hF,hG,hH,hA,hB SHA256_ROUND 7, hB,hC,hD,hE,hF,hG,hH,hA SHA256_ROUND 8, hA,hB,hC,hD,hE,hF,hG,hH SHA256_ROUND 9, hH,hA,hB,hC,hD,hE,hF,hG SHA256_ROUND 10, hG,hH,hA,hB,hC,hD,hE,hF SHA256_ROUND 11, hF,hG,hH,hA,hB,hC,hD,hE SHA256_ROUND 12, hE,hF,hG,hH,hA,hB,hC,hD SHA256_ROUND 13, hD,hE,hF,hG,hH,hA,hB,hC SHA256_ROUND 14, hC,hD,hE,hF,hG,hH,hA,hB SHA256_ROUND 15, hB,hC,hD,hE,hF,hG,hH,hA add hA, T3 sub rsi, (16-4)*sizeof(ymmword) ; restore stack to W mov rdi, qword [rsp+_hash] ; restore hash pointer mov r14, qword [rsp+_len] ; restore data length ;; update hash values by 1-st data block UPDATE_HASH dword [rdi], hA UPDATE_HASH dword [rdi+1*sizeof(dword)], hB UPDATE_HASH dword [rdi+2*sizeof(dword)], hC UPDATE_HASH dword [rdi+3*sizeof(dword)], hD UPDATE_HASH dword [rdi+4*sizeof(dword)], hE UPDATE_HASH dword [rdi+5*sizeof(dword)], hF UPDATE_HASH dword [rdi+6*sizeof(dword)], hG UPDATE_HASH dword [rdi+7*sizeof(dword)], hH cmp r14, MBS_SHA256*2 jl .done ;; do 64 rounds for the next block add rsi, 4*sizeof(dword) ; restore stack to next block W lea rbp, [rsi+16*sizeof(ymmword)] ; use rbp for loop limiter mov T5, hB ; T5 = b^c xor T3, T3 ; T3 = 0 mov T1, hF ; T1 = f xor T5, hC align IPP_ALIGN_FACTOR .block2_proc: SHA256_ROUND 0, hA,hB,hC,hD,hE,hF,hG,hH SHA256_ROUND 1, hH,hA,hB,hC,hD,hE,hF,hG SHA256_ROUND 2, hG,hH,hA,hB,hC,hD,hE,hF SHA256_ROUND 3, hF,hG,hH,hA,hB,hC,hD,hE SHA256_ROUND 4, hE,hF,hG,hH,hA,hB,hC,hD SHA256_ROUND 5, hD,hE,hF,hG,hH,hA,hB,hC SHA256_ROUND 6, hC,hD,hE,hF,hG,hH,hA,hB SHA256_ROUND 7, hB,hC,hD,hE,hF,hG,hH,hA add rsi, 2*sizeof(ymmword) cmp rsi, rbp jb .block2_proc add hA, T3 mov rdi, qword [rsp+_hash] ; restore hash pointer mov r14, qword [rsp+_len] ; restore data length ;; update hash values by 2-nd data block UPDATE_HASH dword [rdi], hA UPDATE_HASH dword [rdi+1*sizeof(dword)], hB UPDATE_HASH dword [rdi+2*sizeof(dword)], hC UPDATE_HASH dword [rdi+3*sizeof(dword)], hD UPDATE_HASH dword [rdi+4*sizeof(dword)], hE UPDATE_HASH dword [rdi+5*sizeof(dword)], hF UPDATE_HASH dword [rdi+6*sizeof(dword)], hG UPDATE_HASH dword [rdi+7*sizeof(dword)], hH mov rsi, qword [rsp+_block] ; restore block address add rsi, MBS_SHA256*2 ; move data pointer sub r14, MBS_SHA256*2 ; update data length mov qword [rsp+_len], r14 jg .sha256_block2_loop .done: mov rsp, qword [rsp+_frame] REST_XMM_AVX REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; _IPP32E_L9 and above %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha256m7as.asm000066400000000000000000000364601470420105600263740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_M7) && (_IPP32E < _IPP32E_U8 ) ;; ;; ENDIANNESS ;; %macro ENDIANNESS 2.nolist %xdefine %%dst %1 %xdefine %%src %2 %ifnidn %%dst,%%src mov %%dst,%%src %endif bswap %%dst %endmacro ;; ;; single SHA256 step ;; ;; Ipp32u T1 = H + SUM1(E) + CH(E,F,G) + K_SHA256[t] + W[t]; ;; Ipp32u T2 = SUM0(A) + MAJ(A,B,C); ;; D+= T1; ;; H = T1 + T2; ;; ;; where ;; SUM1(x) = ROR(x,6) ^ ROR(x,11) ^ ROR(x,25) ;; SUM0(x) = ROR(x,2) ^ ROR(x,13) ^ ROR(x,22) ;; ;; CH(x,y,z) = (x & y) ^ (~x & z) ;; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) = (x&y)^((x^y)&z) ;; %macro SHA256_STEP_2 13.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regF %6 %xdefine %%regG %7 %xdefine %%regH %8 %xdefine %%regT %9 %xdefine %%regF1 %10 %xdefine %%regF2 %11 %xdefine %%memW %12 %xdefine %%immCNT %13 ;; update H (start) add %%regH%+d,%%immCNT ;; H += W[t]+K_SHA256[t] add %%regH%+d,[%%memW] ;; compute T = SUM1(E) + CH(E,F,G) mov %%regF1%+d,%%regE%+d ;; SUM1() = E mov %%regF2%+d,%%regE%+d ;; CH() = E ror %%regF1%+d,6 ;; ROR(E,6) mov %%regT%+d, %%regE%+d push %%regE not %%regF2%+d ;; ~E ror %%regE%+d, 11 ;; ROR(E,11) and %%regT%+d, %%regF%+d ;; E&F and %%regF2%+d,%%regG%+d ;;~E&G xor %%regF1%+d,%%regE%+d ;; ROR(E,6)^ROR(E,11) ror %%regE%+d, 14 ;; ROR(E,25) xor %%regF2%+d,%%regT%+d ;; CH() = (E&F)&(~E&G) xor %%regF1%+d,%%regE%+d ;; SUM1() = ROR(E,6)^ROR(E,11)^ROR(E,25) pop %%regE ;; repair E lea %%regT, [%%regF1+%%regF2] ;; update H (continue) add %%regH%+d, %%regT%+d ;; update D add %%regD%+d, %%regH%+d ;; compute T = SUM0(A) + MAJ(A,B,C) mov %%regF1%+d,%%regA%+d ;; SUM0() = A mov %%regF2%+d,%%regA%+d ;; MAJ() = A ror %%regF1%+d,2 ;; ROR(A,2) mov %%regT%+d, %%regA%+d push %%regA xor %%regF2%+d,%%regB%+d ;; A^B ror %%regA%+d, 13 ;; ROR(A,13) and %%regT%+d, %%regB%+d ;; A&B and %%regF2%+d,%%regC%+d ;; (A^B)&C xor %%regF1%+d,%%regA%+d ;; ROR(A,2)^ROR(A,13) ror %%regA%+d, 9 ;; ROR(A,22) xor %%regF2%+d,%%regT%+d ;; MAJ() = (A^B)^((A^B)&C) xor %%regF1%+d,%%regA%+d ;; SUM0() = ROR(A,2)^ROR(A,13)^ROR(A,22) pop %%regA ;; repair A lea %%regT, [%%regF1+%%regF2] ;; update H (finish) add %%regH%+d, %%regT%+d %endmacro ;; ;; update W[] ;; ;; W[j] = SIG1(W[j- 2]) + W[j- 7] ;; +SIG0(W[j-15]) + W[j-16] ;; ;; SIG0(x) = ROR(x,7) ^ROR(x,18) ^LSR(x,3) ;; SIG1(x) = ROR(x,17)^ROR(x,19) ^LSR(x,10) ;; %macro UPDATE_2 5.nolist %xdefine %%nr %1 %xdefine %%sig0 %2 %xdefine %%sig1 %3 %xdefine %%W15 %4 %xdefine %%W2 %5 mov %%sig0, [rsp+((%%nr-15) & 0Fh)*4] ;; W[j-15] mov %%sig1, [rsp+((%%nr-2) & 0Fh)*4] ;; W[j-2] shr %%sig0, 3 shr %%sig1, 10 mov %%W15, [rsp+((%%nr-15) & 0Fh)*4] ;; W[j-15] mov %%W2, [rsp+((%%nr-2) & 0Fh)*4] ;; W[j-2] ror %%W15, 7 ror %%W2, 17 xor %%sig0, %%W15 ;; SIG0 = LSR(W[j-15], 3) xor %%sig1, %%W2 ;; SIG1 = LSR(W[j-2], 10) ror %%W15, 11 ;; ROR(W[j-15], 18) ror %%W2, 2 ;; ROR(W[j-2, 19) xor %%sig0, %%W15 xor %%sig1, %%W2 add %%sig0, [rsp+((%%nr-16) & 0Fh)*4] ;;SIG0 += W[j-16] add %%sig1, [rsp+((%%nr-7) & 0Fh)*4] ;;SIG1 += W[j-7] add %%sig0, %%sig1 mov [rsp+((%%nr-16) & 0Fh)*4], %%sig0 %endmacro ;****************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA256(DigestSHA256 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;****************************************************************************************** ;; ;; Lib = M7 ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; segment .data align=IPP_ALIGN_FACTOR %if (_IPP32E >= _IPP32E_U8) align IPP_ALIGN_FACTOR pByteSwp DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 %endif segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC %assign LOCAL_FRAME (16*sizeof(dword) + sizeof(qword)) USES_GPR rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 4 ;; rdi = digest ;; rsi = data buffer ;; rdx = buffer len ;; rcx = dummy parameter %xdefine MBS_SHA256 (64) movsxd rdx, edx mov qword [rsp+16*sizeof(dword)], rdx ; save length of buffer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: ;; ;; initialize the first 16 words in the array W (remember about endian) ;; %if (_IPP32E >= _IPP32E_U8) movdqa xmm4, oword [rel pByteSwp] movdqu xmm0, oword [rsi+0*16] pshufb xmm0, xmm4 movdqa oword [rsp+0*16], xmm0 movdqu xmm1, oword [rsi+1*16] pshufb xmm1, xmm4 movdqa oword [rsp+1*16], xmm1 movdqu xmm2, oword [rsi+2*16] pshufb xmm2, xmm4 movdqa oword [rsp+2*16], xmm2 movdqu xmm3, oword [rsi+3*16] pshufb xmm3, xmm4 movdqa oword [rsp+3*16], xmm3 %else xor rcx,rcx .loop1: mov r8d,[rsi+rcx*4+0*4] ENDIANNESS r8d,r8d mov [rsp+rcx*4+0*4],r8d mov r9d,[rsi+rcx*4+1*4] ENDIANNESS r9d,r9d mov [rsp+rcx*4+1*4],r9d add rcx,2 cmp rcx,16 jl .loop1 %endif ;; ;; init A, B, C, D, E, F, G, H by the internal digest ;; mov r8d, [rdi+0*4] ; r8d = digest[0] (A) mov r9d, [rdi+1*4] ; r9d = digest[1] (B) mov r10d,[rdi+2*4] ; r10d= digest[2] (C) mov r11d,[rdi+3*4] ; r11d= digest[3] (D) mov r12d,[rdi+4*4] ; r12d= digest[4] (E) mov r13d,[rdi+5*4] ; r13d= digest[5] (F) mov r14d,[rdi+6*4] ; r14d= digest[6] (G) mov r15d,[rdi+7*4] ; r15d= digest[7] (H) ;; ;; perform 0-64 steps ;; ;; A, B, C, D, E, F, G, H T, F1, F2, W[], K256 ;; ---------------------------------------------------------------------------- SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*4}, 0428A2F98h UPDATE_2 16, eax,ebx, ecx,edx SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*4}, 071374491h UPDATE_2 17, eax,ebx, ecx,edx SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*4}, 0B5C0FBCFh UPDATE_2 18, eax,ebx, ecx,edx SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*4}, 0E9B5DBA5h UPDATE_2 19, eax,ebx, ecx,edx SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*4}, 03956C25Bh UPDATE_2 20, eax,ebx, ecx,edx SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*4}, 059F111F1h UPDATE_2 21, eax,ebx, ecx,edx SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*4}, 0923F82A4h UPDATE_2 22, eax,ebx, ecx,edx SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*4}, 0AB1C5ED5h UPDATE_2 23, eax,ebx, ecx,edx SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*4}, 0D807AA98h UPDATE_2 24, eax,ebx, ecx,edx SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*4}, 012835B01h UPDATE_2 25, eax,ebx, ecx,edx SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*4}, 0243185BEh UPDATE_2 26, eax,ebx, ecx,edx SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*4}, 0550C7DC3h UPDATE_2 27, eax,ebx, ecx,edx SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*4}, 072BE5D74h UPDATE_2 28, eax,ebx, ecx,edx SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*4}, 080DEB1FEh UPDATE_2 29, eax,ebx, ecx,edx SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*4}, 09BDC06A7h UPDATE_2 30, eax,ebx, ecx,edx SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*4}, 0C19BF174h UPDATE_2 31, eax,ebx, ecx,edx SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*4}, 0E49B69C1h UPDATE_2 32, eax,ebx, ecx,edx SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*4}, 0EFBE4786h UPDATE_2 33, eax,ebx, ecx,edx SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*4}, 00FC19DC6h UPDATE_2 34, eax,ebx, ecx,edx SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*4}, 0240CA1CCh UPDATE_2 35, eax,ebx, ecx,edx SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*4}, 02DE92C6Fh UPDATE_2 36, eax,ebx, ecx,edx SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*4}, 04A7484AAh UPDATE_2 37, eax,ebx, ecx,edx SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*4}, 05CB0A9DCh UPDATE_2 38, eax,ebx, ecx,edx SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*4}, 076F988DAh UPDATE_2 39, eax,ebx, ecx,edx SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*4}, 0983E5152h UPDATE_2 40, eax,ebx, ecx,edx SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*4}, 0A831C66Dh UPDATE_2 41, eax,ebx, ecx,edx SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*4}, 0B00327C8h UPDATE_2 42, eax,ebx, ecx,edx SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*4}, 0BF597FC7h UPDATE_2 43, eax,ebx, ecx,edx SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*4}, 0C6E00BF3h UPDATE_2 44, eax,ebx, ecx,edx SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*4}, 0D5A79147h UPDATE_2 45, eax,ebx, ecx,edx SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*4}, 006CA6351h UPDATE_2 46, eax,ebx, ecx,edx SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*4}, 014292967h UPDATE_2 47, eax,ebx, ecx,edx SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*4}, 027B70A85h UPDATE_2 48, eax,ebx, ecx,edx SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*4}, 02E1B2138h UPDATE_2 49, eax,ebx, ecx,edx SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*4}, 04D2C6DFCh UPDATE_2 50, eax,ebx, ecx,edx SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*4}, 053380D13h UPDATE_2 51, eax,ebx, ecx,edx SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*4}, 0650A7354h UPDATE_2 52, eax,ebx, ecx,edx SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*4}, 0766A0ABBh UPDATE_2 53, eax,ebx, ecx,edx SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*4}, 081C2C92Eh UPDATE_2 54, eax,ebx, ecx,edx SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*4}, 092722C85h UPDATE_2 55, eax,ebx, ecx,edx SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*4}, 0A2BFE8A1h UPDATE_2 56, eax,ebx, ecx,edx SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*4}, 0A81A664Bh UPDATE_2 57, eax,ebx, ecx,edx SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*4}, 0C24B8B70h UPDATE_2 58, eax,ebx, ecx,edx SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*4}, 0C76C51A3h UPDATE_2 59, eax,ebx, ecx,edx SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*4}, 0D192E819h UPDATE_2 60, eax,ebx, ecx,edx SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*4}, 0D6990624h UPDATE_2 61, eax,ebx, ecx,edx SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*4}, 0F40E3585h UPDATE_2 62, eax,ebx, ecx,edx SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*4}, 0106AA070h UPDATE_2 63, eax,ebx, ecx,edx SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*4}, 019A4C116h SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*4}, 01E376C08h SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*4}, 02748774Ch SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*4}, 034B0BCB5h SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*4}, 0391C0CB3h SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*4}, 04ED8AA4Ah SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*4}, 05B9CCA4Fh SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*4}, 0682E6FF3h SHA256_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*4}, 0748F82EEh SHA256_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*4}, 078A5636Fh SHA256_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*4}, 084C87814h SHA256_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*4}, 08CC70208h SHA256_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*4}, 090BEFFFAh SHA256_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*4}, 0A4506CEBh SHA256_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*4}, 0BEF9A3F7h SHA256_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*4}, 0C67178F2h ;; ;; update digest ;; add [rdi+0*4],r8d add [rdi+1*4],r9d add [rdi+2*4],r10d add [rdi+3*4],r11d add [rdi+4*4],r12d add [rdi+5*4],r13d add [rdi+6*4],r14d add [rdi+7*4],r15d add rsi, MBS_SHA256 sub qword [rsp+16*sizeof(dword)], MBS_SHA256 jg .sha256_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; (_IPP32E >= _IPP32E_M7) AND (_IPP32E < _IPP32E_U8 ) %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha256nias.asm000066400000000000000000000421451470420105600264540ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA-256 ; ; Content: ; UpdateSHA256ni ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_ON_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) ;;%if (_IPP32E >= _IPP32E_Y8 ) segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR PSHUFFLE_BYTE_FLIP_MASK \ DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;***************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA256ni(DigestSHA256 digest, const Ipp8u* msg, int mlen, const void* pParam) ;* ;***************************************************************************************** %ifndef _VXWORKS IPPASM UpdateSHA256ni,PUBLIC %assign LOCAL_FRAME 16*2 USES_GPR rsi,rdi USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10 COMP_ABI 4 %xdefine MBS_SHA256 (64) ; SHA-256 message block length (bytes) %xdefine HASH_PTR rdi ; 1st arg %xdefine MSG_PTR rsi ; 2nd arg %xdefine MSG_LEN rdx ; 3rd arg %xdefine K256_PTR rcx ; 4th arg %xdefine MSG xmm0 %xdefine STATE0 xmm1 %xdefine STATE1 xmm2 %xdefine MSGTMP0 xmm3 %xdefine MSGTMP1 xmm4 %xdefine MSGTMP2 xmm5 %xdefine MSGTMP3 xmm6 %xdefine MSGTMP4 xmm7 %xdefine SHUF_MASK xmm8 %xdefine ABEF_SAVE xmm9 %xdefine CDGH_SAVE xmm10 movsxd MSG_LEN, edx ; expand mLen test MSG_LEN, MSG_LEN jz .quit ;; load input hash value, reorder these appropriately movdqu STATE0, oword [HASH_PTR+0*16] movdqu STATE1, oword [HASH_PTR+1*16] pshufd STATE0, STATE0, 0B1h ; CDAB pshufd STATE1, STATE1, 01Bh ; EFGH movdqa MSGTMP4, STATE0 palignr STATE0, STATE1, 8 ; ABEF pblendw STATE1, MSGTMP4, 0F0h ; CDGH movdqa SHUF_MASK, oword [rel PSHUFFLE_BYTE_FLIP_MASK] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: movdqa ABEF_SAVE, STATE0 ; save for addition after rounds movdqa CDGH_SAVE, STATE1 ;; rounds 0-3 movdqu MSG, oword [MSG_PTR + 0*16] pshufb MSG, SHUF_MASK movdqa MSGTMP0, MSG paddd MSG, oword [K256_PTR + 0*16] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 ;; rounds 4-7 movdqu MSG, oword [MSG_PTR + 1*16] pshufb MSG, SHUF_MASK movdqa MSGTMP1, MSG paddd MSG, oword [K256_PTR + 1*16] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 8-11 movdqu MSG, oword [MSG_PTR + 2*16] pshufb MSG, SHUF_MASK movdqa MSGTMP2, MSG paddd MSG, oword [K256_PTR + 2*16] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 12-15 movdqu MSG, oword [MSG_PTR + 3*16] pshufb MSG, SHUF_MASK movdqa MSGTMP3, MSG paddd MSG, oword [K256_PTR + 3*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 16-19 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 4*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 20-23 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 5*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 24-27 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 6*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 28-31 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 7*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 32-35 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 8*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 36-39 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 9*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 40-43 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 10*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 44-47 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 11*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 48-51 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 12*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 52-55 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 13*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 ;; rounds 56-59 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 14*16] sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 ;; rounds 60-63 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 15*16] sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh sha256rnds2 STATE0, STATE1 paddd STATE0, ABEF_SAVE ; update previously saved hash paddd STATE1, CDGH_SAVE add MSG_PTR, MBS_SHA256 sub MSG_LEN, MBS_SHA256 jg .sha256_block_loop ; reorder hash pshufd STATE0, STATE0, 01Bh ; FEBA pshufd STATE1, STATE1, 0B1h ; DCHG movdqa MSGTMP4, STATE0 pblendw STATE0, STATE1, 0F0h ; DCBA palignr STATE1, MSGTMP4, 8 ; HGFE ; and store it back movdqu oword [HASH_PTR + 0*16], STATE0 movdqu oword [HASH_PTR + 1*16], STATE1 .quit: REST_XMM REST_GPR ret ENDFUNC UpdateSHA256ni %else ;; no sha ni support in VxWorks - therefore we temporary use db IPPASM UpdateSHA256ni,PUBLIC %assign LOCAL_FRAME 16*2 USES_GPR rsi,rdi USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10 COMP_ABI 4 %xdefine MBS_SHA256 (64) ; SHA-256 message block length (bytes) %xdefine HASH_PTR rdi ; 1st arg %xdefine MSG_PTR rsi ; 2nd arg %xdefine MSG_LEN rdx ; 3rd arg %xdefine K256_PTR rcx ; 4th arg %xdefine MSG xmm0 %xdefine STATE0 xmm1 %xdefine STATE1 xmm2 %xdefine MSGTMP0 xmm3 %xdefine MSGTMP1 xmm4 %xdefine MSGTMP2 xmm5 %xdefine MSGTMP3 xmm6 %xdefine MSGTMP4 xmm7 %xdefine SHUF_MASK xmm8 %xdefine ABEF_SAVE xmm9 %xdefine CDGH_SAVE xmm10 movsxd MSG_LEN, edx ; expand mLen test MSG_LEN, MSG_LEN jz .quit ;; load input hash value, reorder these appropriately movdqu STATE0, oword [HASH_PTR+0*16] movdqu STATE1, oword [HASH_PTR+1*16] pshufd STATE0, STATE0, 0B1h ; CDAB pshufd STATE1, STATE1, 01Bh ; EFGH movdqa MSGTMP4, STATE0 palignr STATE0, STATE1, 8 ; ABEF pblendw STATE1, MSGTMP4, 0F0h ; CDGH movdqa SHUF_MASK, oword [rel PSHUFFLE_BYTE_FLIP_MASK] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: movdqa ABEF_SAVE, STATE0 ; save for addition after rounds movdqa CDGH_SAVE, STATE1 ;; rounds 0-3 movdqu MSG, oword [MSG_PTR + 0*16] pshufb MSG, SHUF_MASK movdqa MSGTMP0, MSG paddd MSG, oword [K256_PTR + 0*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 ;; rounds 4-7 movdqu MSG, oword [MSG_PTR + 1*16] pshufb MSG, SHUF_MASK movdqa MSGTMP1, MSG paddd MSG, oword [K256_PTR + 1*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0DCH ;; sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 8-11 movdqu MSG, oword [MSG_PTR + 2*16] pshufb MSG, SHUF_MASK movdqa MSGTMP2, MSG paddd MSG, oword [K256_PTR + 2*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0E5H ;; sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 12-15 movdqu MSG, oword [MSG_PTR + 3*16] pshufb MSG, SHUF_MASK movdqa MSGTMP3, MSG paddd MSG, oword [K256_PTR + 3*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 db 0FH,38H,0CDH,0DEH ;; sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0EEH ;; sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 16-19 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 4*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 db 0FH,38H,0CDH,0E3H ;; sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0F3H ;; sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 20-23 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 5*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 db 0FH,38H,0CDH,0ECH ;; sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0DCH ;; sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 24-27 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 6*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 db 0FH,38H,0CDH,0F5H ;; sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0E5H ;; sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 28-31 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 7*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 db 0FH,38H,0CDH,0DEH ;; sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0EEH ;; sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 32-35 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 8*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 db 0FH,38H,0CDH,0E3H ;; sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0F3H ;; sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 36-39 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 9*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 db 0FH,38H,0CDH,0ECH ;; sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0DCH ;; sha256msg1 MSGTMP0, MSGTMP1 ;; rounds 40-43 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 10*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 db 0FH,38H,0CDH,0F5H ;; sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0E5H ;; sha256msg1 MSGTMP1, MSGTMP2 ;; rounds 44-47 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 11*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP3 palignr MSGTMP4, MSGTMP2, 4 paddd MSGTMP0, MSGTMP4 db 0FH,38H,0CDH,0DEH ;; sha256msg2 MSGTMP0, MSGTMP3 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0EEH ;; sha256msg1 MSGTMP2, MSGTMP3 ;; rounds 48-51 movdqa MSG, MSGTMP0 paddd MSG, oword [K256_PTR + 12*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP0 palignr MSGTMP4, MSGTMP3, 4 paddd MSGTMP1, MSGTMP4 db 0FH,38H,0CDH,0E3H ;; sha256msg2 MSGTMP1, MSGTMP0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 db 0FH,38H,0CCH,0F3H ;; sha256msg1 MSGTMP3, MSGTMP0 ;; rounds 52-55 movdqa MSG, MSGTMP1 paddd MSG, oword [K256_PTR + 13*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP1 palignr MSGTMP4, MSGTMP0, 4 paddd MSGTMP2, MSGTMP4 db 0FH,38H,0CDH,0ECH ;; sha256msg2 MSGTMP2, MSGTMP1 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 ;; rounds 56-59 movdqa MSG, MSGTMP2 paddd MSG, oword [K256_PTR + 14*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 movdqa MSGTMP4, MSGTMP2 palignr MSGTMP4, MSGTMP1, 4 paddd MSGTMP3, MSGTMP4 db 0FH,38H,0CDH,0F5H ;; sha256msg2 MSGTMP3, MSGTMP2 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 ;; rounds 60-63 movdqa MSG, MSGTMP3 paddd MSG, oword [K256_PTR + 15*16] db 0FH,38H,0CBH,0D1H ;; sha256rnds2 STATE1, STATE0 pshufd MSG, MSG, 0Eh db 0FH,38H,0CBH,0CAH ;; sha256rnds2 STATE0, STATE1 paddd STATE0, ABEF_SAVE ; update previously saved hash paddd STATE1, CDGH_SAVE add MSG_PTR, MBS_SHA256 sub MSG_LEN, MBS_SHA256 jg .sha256_block_loop ; reorder hash pshufd STATE0, STATE0, 01Bh ; FEBA pshufd STATE1, STATE1, 0B1h ; DCHG movdqa MSGTMP4, STATE0 pblendw STATE0, STATE1, 0F0h ; DCBA palignr STATE1, MSGTMP4, 8 ; HGFE ; and store it back movdqu oword [HASH_PTR + 0*16], STATE0 movdqu oword [HASH_PTR + 1*16], STATE1 .quit: REST_XMM REST_GPR ret ENDFUNC UpdateSHA256ni %endif ;; VxWorks ;;%endif ;; (_IPP32E >= _IPP32E_Y8) %endif ;; _FEATURE_ON_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha256u8as.asm000066400000000000000000000343431470420105600264030ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA256 ; ; Content: ; UpdateSHA256 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA256_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if ((_IPP32E >= _IPP32E_U8 ) && (_IPP32E < _IPP32E_E9 )) || (_IPP32E == _IPP32E_N8 ) %xdefine XMM_SHUFB_BSWAP xmm6 %xdefine W0 xmm0 %xdefine W4 xmm1 %xdefine W8 xmm2 %xdefine W12 xmm3 %xdefine SIG1 xmm4 %xdefine SIG0 xmm5 %xdefine X xmm6 %xdefine W xmm7 ;; assign hash values to GPU registers %xdefine A eax %xdefine B ebx %xdefine C edx %xdefine D r8d %xdefine E r9d %xdefine F r10d %xdefine G r11d %xdefine H r12d %xdefine T1 r13d %xdefine T2 r14d %xdefine T3 r15d ;; we are considering x, y, z are polynomials over GF(2) ;; & - multiplication ;; ^ - additive ;; operations ;; ;; Chj(x,y,z) = (x&y) ^ (~x & z) ;; = (x&y) ^ ((1^x) &z) ;; = (x&y) ^ (z ^ x&z) ;; = x&y ^ z ^ x&z ;; = x&(y^z) ^z ;; %macro Chj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%Y xor %%F, %%Z and %%F, %%X xor %%F, %%Z %endmacro ;; ;; Maj(x,y,z) = (x&y) ^ (x&z) ^ (y&z) ;; = (x&y) ^ (x&z) ^ (y&z) ^ (z&z) ^z // note: ((z&z) ^z) = 0 ;; = x&(y^z) ^ z&(y^z) ^z ;; = (x^z)&(y^z) ^z ;; %macro Maj 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%X xor %%F, %%Z xor %%Z, %%Y and %%F, %%Z xor %%Z, %%Y xor %%F, %%Z %endmacro %macro ROTR 2.nolist %xdefine %%X %1 %xdefine %%n %2 ;;shrd X,X, n ror %%X, %%n %endmacro ;; ;; Summ0(x) = ROR(x,2) ^ ROR(x,13) ^ ROR(x,22) ;; %macro Summ0 3.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%T %3 mov %%F, %%X ROTR %%F, 2 mov %%T, %%X ROTR %%T, 13 xor %%F, %%T ROTR %%T, (22-13) xor %%F, %%T %endmacro ;; ;; Summ1(x) = ROR(x,6) ^ ROR(x,11) ^ ROR(x,25) ;; %macro Summ1 3.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%T %3 mov %%F, %%X ROTR %%F, 6 mov %%T, %%X ROTR %%T, 11 xor %%F, %%T ROTR %%T, (25-11) xor %%F, %%T %endmacro ;; ;; regular round (i): ;; ;; T1 = h + Sigma1(e) + Ch(e,f,g) + K[i] + W[i] ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h = g ;; g = f ;; f = e ;; e = d + T1 ;; d = c ;; c = b ;; b = a ;; a = T1+T2 ;; ;; or ;; ;; h += Sigma1(e) + Ch(e,f,g) + K[i] + W[i] (==T1) ;; d += h ;; T2 = Sigma0(a) + Maj(a,b,c) ;; h += T2 ;; and following textual shift {a,b,c,d,e,f,g,h} => {h,a,b,c,d,e,f,g} ;; %macro ROUND 11.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 %xdefine %%T1 %10 %xdefine %%T2 %11 add %%H, dword [rsp+(%%nr & 3)*sizeof(dword)] Summ1 %%T1, %%E, %%T2 Chj %%T2, %%E,%%F,%%G add %%H, %%T1 add %%H, %%T2 add %%D, %%H Summ0 %%T1, %%A, %%T2 Maj %%T2, %%A,%%B,%%C add %%H, %%T1 add %%H, %%T2 %endmacro ;; W[i] = Sigma1(W[i-2]) + W[i-7] + Sigma0(W[i-15]) + W[i-16], i=16,..,63 ;; ;;for next rounds 16,17,18 and 19: ;; W[0] <= W[16] = Sigma1(W[14]) + W[ 9] + Sigma0(W[1]) + W[0] ;; W[1] <= W[17] = Sigma1(W[15]) + W[10] + Sigma0(W[2]) + W[1] ;; W[2] <= W[18] = Sigma1(W[ 0]) + W[11] + Sigma0(W[3]) + W[1] ;; W[3] <= W[19] = Sigma1(W[ 1]) + W[12] + Sigma0(W[4]) + W[2] ;; ;; the process is repeated exactly because textual round of W[] ;; ;; Sigma1() and Sigma0() functions are defined as following: ;; Sigma1(X) = ROR(X,17)^ROR(X,19)^SHR(X,10) ;; Sigma0(X) = ROR(X, 7)^ROR(X,18)^SHR(X, 3) ;; %macro UPDATE_W 8.nolist %xdefine %%xS %1 %xdefine %%xS0 %2 %xdefine %%xS4 %3 %xdefine %%xS8 %4 %xdefine %%xS12 %5 %xdefine %%SIGMA1 %6 %xdefine %%SIGMA0 %7 %xdefine %%X %8 pshufd %%SIGMA1, %%xS12, 11111010b ;; SIGMA1 = {W[15],W[15],W[14],W[14]} movdqa %%X, %%SIGMA1 psrld %%SIGMA1, 10 psrlq %%X, 17 pxor %%SIGMA1, %%X psrlq %%X, (19-17) pxor %%SIGMA1, %%X pshufd %%SIGMA0, %%xS0, 10100101b ;; SIGMA0 = {W[2],W[2],W[1],W[1]} movdqa %%X, %%SIGMA0 psrld %%SIGMA0, 3 psrlq %%X, 7 pxor %%SIGMA0, %%X psrlq %%X, (18-7) pxor %%SIGMA0, %%X pshufd %%xS, %%xS0, 01010000b ;; {W[ 1],W[ 1],W[ 0],W[ 0]} pshufd %%X, %%xS8, 10100101b ;; {W[10],W[10],W[ 9],W[ 9]} paddd %%xS, %%SIGMA1 paddd %%xS, %%SIGMA0 paddd %%xS, %%X pshufd %%SIGMA1, %%xS, 10100000b ;; SIGMA1 = {W[1],W[1],W[0],W[0]} movdqa %%X, %%SIGMA1 psrld %%SIGMA1, 10 psrlq %%X, 17 pxor %%SIGMA1, %%X psrlq %%X, (19-17) pxor %%SIGMA1, %%X movdqa %%SIGMA0, %%xS4 ;; SIGMA0 = {W[4],W[4],W[3],W[3]} palignr %%SIGMA0, %%xS0, (3*sizeof(dword)) pshufd %%SIGMA0, %%SIGMA0, 01010000b movdqa %%X, %%SIGMA0 psrld %%SIGMA0, 3 psrlq %%X, 7 pxor %%SIGMA0, %%X psrlq %%X, (18-7) pxor %%SIGMA0, %%X movdqa %%X, %%xS12 palignr %%X, %%xS8, (3*sizeof(dword)) ;; {W[14],W[13],W[12],W[11]} pshufd %%xS0, %%xS0, 11111010b ;; {W[ 3],W[ 3],W[ 2],W[ 2]} pshufd %%X, %%X, 01010000b ;; {W[12],W[12],W[11],W[11]} paddd %%xS0, %%SIGMA1 paddd %%xS0, %%SIGMA0 paddd %%xS0, %%X pshufd %%xS, %%xS, 10001000b ;; {W[1],W[0],W[1],W[0]} pshufd %%xS0, %%xS0, 10001000b ;; {W[3],W[2],W[3],W[2]} palignr %%xS0, %%xS, (2*sizeof(dword)) ;; {W[3],W[2],W[1],W[0]} movdqa %%xS, %%xS0 %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR pByteSwp DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 segment .text align=IPP_ALIGN_FACTOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; UpdateSHA256(Ipp32u digest[], Ipp8u dataBlock[], int datalen, Ipp32u K_256[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA256,PUBLIC %assign LOCAL_FRAME sizeof(oword)+sizeof(qword) USES_GPR rbx,rsi,rdi,rbp,r12,r13,r14,r15 USES_XMM xmm6,xmm7 COMP_ABI 4 ;; ;; rdi = pointer to the updated hash ;; rsi = pointer to the data block ;; rdx = data block length ;; rcx = pointer to the SHA_256 constant ;; %xdefine MBS_SHA256 (64) movsxd rdx, edx mov qword [rsp+sizeof(oword)], rdx ; save length of buffer ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .sha256_block_loop: movdqu W0, oword [rsi] ; load buffer content movdqu W4, oword [rsi+sizeof(oword)] movdqu W8, oword [rsi+sizeof(oword)*2] movdqu W12,oword [rsi+sizeof(oword)*3] mov A, dword [rdi] ; load initial hash value mov B, dword [rdi+sizeof(dword)] mov C, dword [rdi+sizeof(dword)*2] mov D, dword [rdi+sizeof(dword)*3] mov E, dword [rdi+sizeof(dword)*4] mov F, dword [rdi+sizeof(dword)*5] mov G, dword [rdi+sizeof(dword)*6] mov H, dword [rdi+sizeof(dword)*7] movdqa XMM_SHUFB_BSWAP, oword [rel pByteSwp] ; load shuffle mask ; rcx points K_256[] constants ;; perform 0-3 regular rounds pshufb W0, XMM_SHUFB_BSWAP ; swap input movdqa W, W0 ; T = W[0-3] paddd W, oword [rcx+sizeof(oword)*0] ; T += K_SHA256[0-3] movdqa oword [rsp], W ROUND 0, A,B,C,D,E,F,G,H, T1,T2 ROUND 1, H,A,B,C,D,E,F,G, T1,T2 ROUND 2, G,H,A,B,C,D,E,F, T1,T2 ROUND 3, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 4-7 regular rounds pshufb W4, XMM_SHUFB_BSWAP ; swap input movdqa W, W4 ; T = W[4-7] paddd W, oword [rcx+sizeof(oword)*1] ; T += K_SHA256[4-7] movdqa oword [rsp], W ROUND 4, E,F,G,H,A,B,C,D, T1,T2 ROUND 5, D,E,F,G,H,A,B,C, T1,T2 ROUND 6, C,D,E,F,G,H,A,B, T1,T2 ROUND 7, B,C,D,E,F,G,H,A, T1,T2 ;; perform next 8-11 regular rounds pshufb W8, XMM_SHUFB_BSWAP ; swap input movdqa W, W8 ; T = W[8-11] paddd W, oword [rcx+sizeof(oword)*2] ; T += K_SHA256[8-11] movdqa oword [rsp], W ROUND 8, A,B,C,D,E,F,G,H, T1,T2 ROUND 9, H,A,B,C,D,E,F,G, T1,T2 ROUND 10, G,H,A,B,C,D,E,F, T1,T2 ROUND 11, F,G,H,A,B,C,D,E, T1,T2 ;; perform next 12-15 regular rounds pshufb W12, XMM_SHUFB_BSWAP ; swap input movdqa W, W12 ; T = W[12-15] paddd W, oword [rcx+sizeof(oword)*3] ; T += K_SHA256[12-15] movdqa oword [rsp], W ROUND 12, E,F,G,H,A,B,C,D, T1,T2 ROUND 13, D,E,F,G,H,A,B,C, T1,T2 ROUND 14, C,D,E,F,G,H,A,B, T1,T2 ROUND 15, B,C,D,E,F,G,H,A, T1,T2 UPDATE_W W, W0, W4, W8, W12, SIG1,SIG0,X ; round: 16-19 paddd W, oword [rcx+sizeof(oword)*4] ; T += K_SHA256[16-19] movdqa oword [rsp], W ROUND 16, A,B,C,D,E,F,G,H, T1,T2 ROUND 17, H,A,B,C,D,E,F,G, T1,T2 ROUND 18, G,H,A,B,C,D,E,F, T1,T2 ROUND 19, F,G,H,A,B,C,D,E, T1,T2 UPDATE_W W, W4, W8, W12,W0, SIG1,SIG0,X ; round: 20-23 paddd W, oword [rcx+sizeof(oword)*5] ; T += K_SHA256[20-23] movdqa oword [rsp], W ROUND 20, E,F,G,H,A,B,C,D, T1,T2 ROUND 21, D,E,F,G,H,A,B,C, T1,T2 ROUND 22, C,D,E,F,G,H,A,B, T1,T2 ROUND 23, B,C,D,E,F,G,H,A, T1,T2 UPDATE_W W, W8, W12,W0, W4, SIG1,SIG0,X ; round: 24-27 paddd W, oword [rcx+sizeof(oword)*6] ; T += K_SHA256[24-27] movdqa oword [rsp], W ROUND 24, A,B,C,D,E,F,G,H, T1,T2 ROUND 25, H,A,B,C,D,E,F,G, T1,T2 ROUND 26, G,H,A,B,C,D,E,F, T1,T2 ROUND 27, F,G,H,A,B,C,D,E, T1,T2 UPDATE_W W, W12,W0, W4, W8, SIG1,SIG0,X ; round: 28-31 paddd W, oword [rcx+sizeof(oword)*7] ; T += K_SHA256[28-31] movdqa oword [rsp], W ROUND 28, E,F,G,H,A,B,C,D, T1,T2 ROUND 29, D,E,F,G,H,A,B,C, T1,T2 ROUND 30, C,D,E,F,G,H,A,B, T1,T2 ROUND 31, B,C,D,E,F,G,H,A, T1,T2 UPDATE_W W, W0, W4, W8, W12, SIG1,SIG0,X ; round: 32-35 paddd W, oword [rcx+sizeof(oword)*8] ; T += K_SHA256[32-35] movdqa oword [rsp], W ROUND 32, A,B,C,D,E,F,G,H, T1,T2 ROUND 33, H,A,B,C,D,E,F,G, T1,T2 ROUND 34, G,H,A,B,C,D,E,F, T1,T2 ROUND 35, F,G,H,A,B,C,D,E, T1,T2 UPDATE_W W, W4, W8, W12,W0, SIG1,SIG0,X ; round: 36-39 paddd W, oword [rcx+sizeof(oword)*9] ; T += K_SHA256[36-39] movdqa oword [rsp], W ROUND 36, E,F,G,H,A,B,C,D, T1,T2 ROUND 37, D,E,F,G,H,A,B,C, T1,T2 ROUND 38, C,D,E,F,G,H,A,B, T1,T2 ROUND 39, B,C,D,E,F,G,H,A, T1,T2 UPDATE_W W, W8, W12,W0, W4, SIG1,SIG0,X ; round: 40-43 paddd W, oword [rcx+sizeof(oword)*10] ; T += K_SHA256[40-43] movdqa oword [rsp], W ROUND 40, A,B,C,D,E,F,G,H, T1,T2 ROUND 41, H,A,B,C,D,E,F,G, T1,T2 ROUND 42, G,H,A,B,C,D,E,F, T1,T2 ROUND 43, F,G,H,A,B,C,D,E, T1,T2 UPDATE_W W, W12,W0, W4, W8, SIG1,SIG0,X ; round: 44-47 paddd W, oword [rcx+sizeof(oword)*11] ; T += K_SHA256[44-47] movdqa oword [rsp], W ROUND 44, E,F,G,H,A,B,C,D, T1,T2 ROUND 45, D,E,F,G,H,A,B,C, T1,T2 ROUND 46, C,D,E,F,G,H,A,B, T1,T2 ROUND 47, B,C,D,E,F,G,H,A, T1,T2 UPDATE_W W, W0, W4, W8, W12, SIG1,SIG0,X ; round: 48-51 paddd W, oword [rcx+sizeof(oword)*12] ; T += K_SHA256[48-51] movdqa oword [rsp], W ROUND 48, A,B,C,D,E,F,G,H, T1,T2 ROUND 49, H,A,B,C,D,E,F,G, T1,T2 ROUND 50, G,H,A,B,C,D,E,F, T1,T2 ROUND 51, F,G,H,A,B,C,D,E, T1,T2 UPDATE_W W, W4, W8, W12,W0, SIG1,SIG0,X ; round: 52-55 paddd W, oword [rcx+sizeof(oword)*13] ; T += K_SHA256[52-55] movdqa oword [rsp], W ROUND 52, E,F,G,H,A,B,C,D, T1,T2 ROUND 53, D,E,F,G,H,A,B,C, T1,T2 ROUND 54, C,D,E,F,G,H,A,B, T1,T2 ROUND 55, B,C,D,E,F,G,H,A, T1,T2 UPDATE_W W, W8, W12,W0, W4, SIG1,SIG0,X ; round: 56-59 paddd W, oword [rcx+sizeof(oword)*14] ; T += K_SHA256[56-59] movdqa oword [rsp], W ROUND 56, A,B,C,D,E,F,G,H, T1,T2 ROUND 57, H,A,B,C,D,E,F,G, T1,T2 ROUND 58, G,H,A,B,C,D,E,F, T1,T2 ROUND 59, F,G,H,A,B,C,D,E, T1,T2 UPDATE_W W, W12,W0, W4, W8, SIG1,SIG0,X ; round: 60-63 paddd W, oword [rcx+sizeof(oword)*15] ; T += K_SHA256[60-63] movdqa oword [rsp], W ROUND 60, E,F,G,H,A,B,C,D, T1,T2 ROUND 61, D,E,F,G,H,A,B,C, T1,T2 ROUND 62, C,D,E,F,G,H,A,B, T1,T2 ROUND 63, B,C,D,E,F,G,H,A, T1,T2 add dword [rdi], A ; update hash add dword [rdi+sizeof(dword)*1], B add dword [rdi+sizeof(dword)*2], C add dword [rdi+sizeof(dword)*3], D add dword [rdi+sizeof(dword)*4], E add dword [rdi+sizeof(dword)*5], F add dword [rdi+sizeof(dword)*6], G add dword [rdi+sizeof(dword)*7], H add rsi, MBS_SHA256 sub qword [rsp+sizeof(oword)], MBS_SHA256 jg .sha256_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA256 %endif ;; ((_IPP32E >= _IPP32E_U8 ) AND (_IPP32E < _IPP32E_E9 )) OR (_IPP32E == _IPP32E_N8 ) %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA256_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha512e9as.asm000066400000000000000000000507171470420105600263620ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA512 ; ; Content: ; UpdateSHA256 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA512_) ;;%if (_IPP32E >= _IPP32E_E9) %if (_IPP32E == _IPP32E_E9 ) %xdefine W0 xmm0 %xdefine W1 xmm1 %xdefine W2 xmm2 %xdefine W3 xmm3 %xdefine W4 xmm4 %xdefine W5 xmm5 %xdefine W6 xmm6 %xdefine W7 xmm7 %xdefine xT0 xmm8 %xdefine xT1 xmm9 %xdefine xT2 xmm10 %xdefine SIGMA xmm11 ;; assign hash values to GPU registers %xdefine A r8 %xdefine B r9 %xdefine C r10 %xdefine D r11 %xdefine E r12 %xdefine F r13 %xdefine G r14 %xdefine H r15 %xdefine T1 rax %xdefine T2 rbx %xdefine T0 rbp %xdefine KK_SHA512 rcx %macro ROTATE_H 0.nolist %xdefine %%_TMP H %xdefine H G %xdefine G F %xdefine F E %xdefine E D %xdefine D C %xdefine C B %xdefine B A %xdefine A %%_TMP %endmacro %macro ROTATE_W 0.nolist %xdefine %%DUMMY W0 %xdefine W0 W1 %xdefine W1 W2 %xdefine W2 W3 %xdefine W3 W4 %xdefine W4 W5 %xdefine W5 W6 %xdefine W6 W7 %xdefine W7 %%DUMMY %endmacro %macro ROR64 2.nolist %xdefine %%r %1 %xdefine %%nbits %2 %if _IPP32E >= _IPP32E_L9 rorx %%r,%%r,%%nbits %elif _IPP32E >= _IPP32E_Y8 shld %%r,%%r,(64-%%nbits) %else ror %%r,%%nbits %endif %endmacro ;; ;; CHJ(x,y,z) = (x & y) ^ (~x & z) ;; ;; CHJ(x,y,z) = (x & y) ^ (~x & z) ;; = (x&y) ^ ((1^x) &z) ;; = (x&y) ^ (z ^ x&z) ;; = x&y ^ z ^ x&z ;; = x&(y^z) ^z ;; ;; => CHJ(E,F,G) = ((F^G) & E) ^G ;; %macro CHJ 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%Y xor %%F, %%Z and %%F, %%X xor %%F, %%Z %endmacro ;; ;; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) ;; ;; MAJ(x,y,z) = (x&y) ^ (x&z) ^ (y&z) ;; = (x&y) ^ (x&z) ^ (y&z) ^ (z&z) ^z // note: ((z&z) ^z) = 0 ;; = x&(y^z) ^ z&(y^z) ^z ;; = (x^z)&(y^z) ^z ;; ;; => MAJ(A,B,C) = ((A^C) & B) ^ (A&C) ;; %macro MAJ 4.nolist %xdefine %%F %1 %xdefine %%X %2 %xdefine %%Y %3 %xdefine %%Z %4 mov %%F, %%X xor %%F, %%Z ;; maj = x^z xor %%Y, %%Z ;; y ^= z and %%F, %%Y ;; maj = (x^z)&(y^z) xor %%F, %%Z ;; maj = (x^z)&(y^z) ^z xor %%Y, %%Z ;; restore y %endmacro ;; ;; SUM1(x) = ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41) ;; ;;=> SUM1(x) = ROR((ROR((ROR(x, 23) ^x), 4) ^x), 14) ;; %macro SUM1 2.nolist %xdefine %%F %1 %xdefine %%X %2 mov %%F, %%X ROR64 %%F, 23 xor %%F, %%X ROR64 %%F, 4 xor %%F, %%X ROR64 %%F, 14 %endmacro ;; ;; SUM0(x) = ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39) ;; ;; => SUM0(x) = ROR((ROR((ROR(x, 5) ^x), 6) ^x), 28) ;; %macro SUM0 2.nolist %xdefine %%F %1 %xdefine %%X %2 mov %%F, %%X ROR64 %%F, 5 xor %%F, %%X ROR64 %%F, 6 xor %%F, %%X ROR64 %%F, 28 %endmacro ;; regular SHA512 step ;; ;; Ipp64u T1 = H + SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t]; ;; Ipp64u T2 = SUM0(A) + MAJ(A,B,C); ;; D+= T1; ;; H = T1 + T2; ;; ;; where ;; SUM1(x) = ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41) ;; SUM0(x) = ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39) ;; ;; CHJ(x,y,z) = (x & y) ^ (~x & z) ;; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) = (x&y)^((x^y)&z) ;; %macro SHA512_STEP_v0 1.nolist %xdefine %%nr %1 add H, qword [rsp+(%%nr & 1)*sizeof(qword)] SUM1 T0, E CHJ T1, E,F,G add H, T1 add H, T0 add D, H SUM0 T0, A MAJ T1, A,B,C add H, T1 add H, T0 ROTATE_H %endmacro %macro SHA512_2step 9.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 mov T0, %%E ;; T0: SUM1(E) ROR64 T0, 23 ;; T0: SUM1(E) add %%H, qword [rsp+(%%nr & 1)*sizeof(qword)] mov T1, %%F ;; T1: CHJ(E,F,G) xor T0, %%E ;; T0: SUM1(E) ROR64 T0, 4 ;; T0: SUM1(E) xor T1, %%G ;; T1: CHJ(E,G,G) and T1, %%E ;; T1: CHJ(E,G,G) xor T0, %%E ;; T0: SUM1(E) ROR64 T0,14 ;; T0: SUM1(E) xor T1, %%G ;; T1: CHJ(E,G,G) add %%H, T1 add %%H, T0 ;; H += SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t] add %%D, %%H mov T0, %%A ;; T0: SUM0(A) ROR64 T0, 5 ;; T0: SUM0(A) mov T1, %%A ;; T1: MAJ(A,B,C) xor T1, %%C ;; T1: MAJ(A,B,C) xor T0, %%A ;; T0: SUM0(A) ROR64 T0, 6 ;; T0: SUM0(A) xor %%B, %%C ;; T1: MAJ(A,B,C) and T1, %%B ;; T1: MAJ(A,B,C) xor T0, %%A ;; T0: SUM0(A) ROR64 T0,28 ;; T0: SUM0(A) xor %%B, %%C ;; T1: MAJ(A,B,C) xor T1, %%C ;; T1: MAJ(A,B,C) add %%H, T0 add %%H, T1 ;ROTATE_H mov T0, %%D ;; T0: SUM1(E) ROR64 T0, 23 ;; T0: SUM1(E) add %%G, qword [rsp+((%%nr+1) & 1)*sizeof(qword)] mov T1, %%E ;; T1: CHJ(E,F,G) xor T0, %%D ;; T0: SUM1(E) ROR64 T0, 4 ;; T0: SUM1(E) xor T1, %%F ;; T1: CHJ(E,G,G) and T1, %%D ;; T1: CHJ(E,G,G) xor T0, %%D ;; T0: SUM1(E) ROR64 T0,14 ;; T0: SUM1(E) xor T1, %%F ;; T1: CHJ(E,G,G) add %%G, T1 add %%G, T0 ;; H += SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t] add %%C, %%G mov T0, %%H ;; T0: SUM0(A) ROR64 T0, 5 ;; T0: SUM0(A) mov T1, %%H ;; T1: MAJ(A,B,C) xor T1, %%B ;; T1: MAJ(A,B,C) xor T0, %%H ;; T0: SUM0(A) ROR64 T0, 6 ;; T0: SUM0(A) xor %%A, %%B ;; T1: MAJ(A,B,C) and T1, %%A ;; T1: MAJ(A,B,C) xor T0, %%H ;; T0: SUM0(A) ROR64 T0,28 ;; T0: SUM0(A) xor %%A, %%B ;; T1: MAJ(A,B,C) xor T1, %%B ;; T1: MAJ(A,B,C) add %%G, T0 add %%G, T1 ;ROTATE_H %endmacro ;; ;; update W[] ;; ;; W[j] = SIG1(W[j- 2]) + W[j- 7] ;; +SIG0(W[j-15]) + W[j-16] ;; ;; SIG0(x) = ROR(x,1) ^ROR(x,8) ^LSR(x,7) ;; SIG1(x) = ROR(x,19)^ROR(x,61) ^LSR(x,6) ;; %macro SHA512_2Wupdate 0.nolist vpalignr xT1, W5, W4, 8 ;; xT1 = W[t-7] vpalignr xT0, W1, W0, 8 ;; xT0 = W[t-15] vpaddq W0, W0, xT1 ;; W0 = W0 + W[t-7] vpsrlq SIGMA, W7, 6 ;; SIG1: W[t-2]>>6 vpsrlq xT1, W7,61 ;; SIG1: W[t-2]>>61 vpsllq xT2, W7,(64-61) ;; SIG1: W[t-2]<<(64-61) vpxor SIGMA, SIGMA, xT1 vpxor SIGMA, SIGMA, xT2 vpsrlq xT1, W7,19 ;; SIG1: W[t-2]>>19 vpsllq xT2, W7,(64-19) ;; SIG1: W[t-2]<<(64-19) vpxor SIGMA, SIGMA, xT1 vpxor SIGMA, SIGMA, xT2 vpaddq W0, W0, SIGMA ;; W0 = W0 + W[t-7] + SIG1(W[t-2]) vpsrlq SIGMA, xT0, 7 ;; SIG0: W[t-15]>>7 vpsrlq xT1, xT0, 1 ;; SIG0: W[t-15]>>1 vpsllq xT2, xT0,(64-1) ;; SIG0: W[t-15]<<(64-1) vpxor SIGMA, SIGMA, xT1 vpxor SIGMA, SIGMA, xT2 vpsrlq xT1, xT0, 8 ;; SIG0: W[t-15]>>8 vpsllq xT2, xT0,(64-8) ;; SIG0: W[t-15]<<(64-8) vpxor SIGMA, SIGMA, xT1 vpxor SIGMA, SIGMA, xT2 vpaddq W0, W0, SIGMA ;; W0 = W0 + W[t-7] + SIG1(W[t-2]) +SIG0(W[t-15]) ROTATE_W %endmacro %macro SHA512_2step_2Wupdate 9.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 add %%H, qword [rsp+(%%nr & 1)*sizeof(qword)] vpalignr xT1, W5, W4, 8 ;; xT1 = W[t-7] mov T0, %%E ;; T0: SUM1(E) ROR64 T0, 23 ;; T0: SUM1(E) vpalignr xT0, W1, W0, 8 ;; xT0 = W[t-15] mov T1, %%F ;; T1: CHJ(E,F,G) xor T0, %%E ;; T0: SUM1(E) vpaddq W0, W0, xT1 ;; W0 = W0 + W[t-7] ROR64 T0, 4 ;; T0: SUM1(E) xor T1, %%G ;; T1: CHJ(E,G,G) vpsrlq SIGMA, W7, 6 ;; SIG1: W[t-2]>>6 and T1, %%E ;; T1: CHJ(E,G,G) xor T0, %%E ;; T0: SUM1(E) ROR64 T0,14 ;; T0: SUM1(E) vpsrlq xT1, W7,61 ;; SIG1: W[t-2]>>61 xor T1, %%G ;; T1: CHJ(E,G,G) add %%H, T1 add %%H, T0 ;; H += SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t] vpsllq xT2, W7,(64-61) ;; SIG1: W[t-2]<<(64-61) add %%D, %%H mov T0, %%A ;; T0: SUM0(A) ROR64 T0, 5 ;; T0: SUM0(A) vpxor SIGMA, SIGMA, xT1 mov T1, %%A ;; T1: MAJ(A,B,C) xor T1, %%C ;; T1: MAJ(A,B,C) vpxor SIGMA, SIGMA, xT2 xor T0, %%A ;; T0: SUM0(A) ROR64 T0, 6 ;; T0: SUM0(A) vpsrlq xT1, W7,19 ;; SIG1: W[t-2]>>19 xor %%B, %%C ;; T1: MAJ(A,B,C) and T1, %%B ;; T1: MAJ(A,B,C) xor T0, %%A ;; T0: SUM0(A) vpsllq xT2, W7,(64-19) ;; SIG1: W[t-2]<<(64-19) ROR64 T0,28 ;; T0: SUM0(A) xor %%B, %%C ;; T1: MAJ(A,B,C) xor T1, %%C ;; T1: MAJ(A,B,C) vpxor SIGMA, SIGMA, xT1 add %%H, T0 add %%H, T1 ;ROTATE_H vpxor SIGMA, SIGMA, xT2 mov T0, %%D ;; T0: SUM1(E) ROR64 T0, 23 ;; T0: SUM1(E) vpaddq W0, W0, SIGMA ;; W0 = W0 + W[t-7] + SIG1(W[t-2]) add %%G, qword [rsp+((%%nr+1) & 1)*sizeof(qword)] mov T1, %%E ;; T1: CHJ(E,F,G) vpsrlq SIGMA, xT0, 7 ;; SIG0: W[t-15]>>7 xor T0, %%D ;; T0: SUM1(E) ROR64 T0, 4 ;; T0: SUM1(E) xor T1, %%F ;; T1: CHJ(E,G,G) vpsrlq xT1, xT0, 1 ;; SIG0: W[t-15]>>1 and T1, %%D ;; T1: CHJ(E,G,G) xor T0, %%D ;; T0: SUM1(E) ROR64 T0,14 ;; T0: SUM1(E) vpsllq xT2, xT0,(64-1) ;; SIG0: W[t-15]<<(64-1) xor T1, %%F ;; T1: CHJ(E,G,G) add %%G, T1 add %%G, T0 ;; H += SUM1(E) + CHJ(E,F,G) + K_SHA512[t] + W[t] vpxor SIGMA, SIGMA, xT1 add %%C, %%G mov T0, %%H ;; T0: SUM0(A) vpxor SIGMA, SIGMA, xT2 ROR64 T0, 5 ;; T0: SUM0(A) mov T1, %%H ;; T1: MAJ(A,B,C) vpsrlq xT1, xT0, 8 ;; SIG0: W[t-15]>>8 xor T1, %%B ;; T1: MAJ(A,B,C) xor T0, %%H ;; T0: SUM0(A) ROR64 T0, 6 ;; T0: SUM0(A) vpsllq xT2, xT0,(64-8) ;; SIG0: W[t-15]<<(64-8) xor %%A, %%B ;; T1: MAJ(A,B,C) and T1, %%A ;; T1: MAJ(A,B,C) xor T0, %%H ;; T0: SUM0(A) vpxor SIGMA, SIGMA, xT1 ROR64 T0,28 ;; T0: SUM0(A) xor %%A, %%B ;; T1: MAJ(A,B,C) vpxor SIGMA, SIGMA, xT2 xor T1, %%B ;; T1: MAJ(A,B,C) add %%G, T0 vpaddq W0, W0, SIGMA ;; W0 = W0 + W[t-7] + SIG1(W[t-2]) +SIG0(W[t-15]) add %%G, T1 ;ROTATE_H ROTATE_W %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SHUFB_BSWAP DB 7,6,5,4,3,2,1,0, 15,14,13,12,11,10,9,8 segment .text align=IPP_ALIGN_FACTOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; UpdateSHA512(Ipp64u digest[], Ipp8u dataBlock[], int datalen, Ipp64u K_512[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM UpdateSHA512,PUBLIC %assign LOCAL_FRAME sizeof(oword)+sizeof(qword) USES_GPR rbx,rsi,rdi,rbp,r12,r13,r14,r15 USES_XMM xmm6,xmm7,xmm8,xmm9,xmm10,xmm11 COMP_ABI 4 ;; ;; rdi = pointer to the updated hash ;; rsi = pointer to the data block ;; rdx = data block length ;; rcx = pointer to the SHA_512 constant ;; %xdefine MBS_SHA512 (128) vmovdqa xT1, oword [rel SHUFB_BSWAP] movsxd rdx, edx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .sha512_block_loop: ;; ;; initialize the first 16 qwords in the array W (remember about endian) ;; vmovdqu W0, oword [rsi] ; load buffer content and swap vpshufb W0, W0, xT1 vmovdqu W1, oword [rsi+sizeof(oword)*1]; vpshufb W1, W1, xT1 vmovdqu W2, oword [rsi+sizeof(oword)*2]; vpshufb W2, W2, xT1 vmovdqu W3, oword [rsi+sizeof(oword)*3]; vpshufb W3, W3, xT1 vmovdqu W4, oword [rsi+sizeof(oword)*4]; vpshufb W4, W4, xT1 vmovdqu W5, oword [rsi+sizeof(oword)*5]; vpshufb W5, W5, xT1 vmovdqu W6, oword [rsi+sizeof(oword)*6]; vpshufb W6, W6, xT1 vmovdqu W7, oword [rsi+sizeof(oword)*7]; vpshufb W7, W7, xT1 mov A, qword [rdi] ; load initial hash value mov B, qword [rdi+sizeof(qword)] mov C, qword [rdi+sizeof(qword)*2] mov D, qword [rdi+sizeof(qword)*3] mov E, qword [rdi+sizeof(qword)*4] mov F, qword [rdi+sizeof(qword)*5] mov G, qword [rdi+sizeof(qword)*6] mov H, qword [rdi+sizeof(qword)*7] ;; perform 0- 9 rounds vpaddq xT1, W0, oword [KK_SHA512+ 0*sizeof(qword)] ; T += K_SHA512[0-1] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 0, A,B,C,D,E,F,G,H vpaddq xT1, W0, oword [KK_SHA512+ 2*sizeof(qword)] ; T += K_SHA512[2-3] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 2, G,H,A,B,C,D,E,F vpaddq xT1, W0, oword [KK_SHA512+ 4*sizeof(qword)] ; T += K_SHA512[4-5] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 4, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+ 6*sizeof(qword)] ; T += K_SHA512[6-7] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 6, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+ 8*sizeof(qword)] ; T += K_SHA512[8-9] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 8, A,B,C,D,E,F,G,H ;; perform 10-19 rounds vpaddq xT1, W0, oword [KK_SHA512+10*sizeof(qword)] ; T += K_SHA512[10-11] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 10, G,H,A,B,C,D,E,F vpaddq xT1, W0, oword [KK_SHA512+12*sizeof(qword)] ; T += K_SHA512[12-13] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 12, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+14*sizeof(qword)] ; T += K_SHA512[14-15] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 14, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+16*sizeof(qword)] ; T += K_SHA512[16-17] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 16, A,B,C,D,E,F,G,H vpaddq xT1, W0, oword [KK_SHA512+18*sizeof(qword)] ; T += K_SHA512[18-19] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 18, G,H,A,B,C,D,E,F ;; perform 20-29 rounds vpaddq xT1, W0, oword [KK_SHA512+20*sizeof(qword)] ; T += K_SHA512[20-21] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 20, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+22*sizeof(qword)] ; T += K_SHA512[22-23] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 22, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+24*sizeof(qword)] ; T += K_SHA512[24-25] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 24, A,B,C,D,E,F,G,H vpaddq xT1, W0, oword [KK_SHA512+26*sizeof(qword)] ; T += K_SHA512[26-27] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 26, G,H,A,B,C,D,E,F vpaddq xT1, W0, oword [KK_SHA512+28*sizeof(qword)] ; T += K_SHA512[28-29] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 28, E,F,G,H,A,B,C,D ;; perform 30-39 rounds vpaddq xT1, W0, oword [KK_SHA512+30*sizeof(qword)] ; T += K_SHA512[30-31] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 30, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+32*sizeof(qword)] ; T += K_SHA512[32-33] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 32, A,B,C,D,E,F,G,H vpaddq xT1, W0, oword [KK_SHA512+34*sizeof(qword)] ; T += K_SHA512[34-35] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 34, G,H,A,B,C,D,E,F vpaddq xT1, W0, oword [KK_SHA512+36*sizeof(qword)] ; T += K_SHA512[36-37] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 36, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+38*sizeof(qword)] ; T += K_SHA512[38-39] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 38, C,D,E,F,G,H,A,B ;; perform 40-49 rounds vpaddq xT1, W0, oword [KK_SHA512+40*sizeof(qword)] ; T += K_SHA512[40-41] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 40, A,B,C,D,E,F,G,H vpaddq xT1, W0, oword [KK_SHA512+42*sizeof(qword)] ; T += K_SHA512[42-43] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 42, G,H,A,B,C,D,E,F vpaddq xT1, W0, oword [KK_SHA512+44*sizeof(qword)] ; T += K_SHA512[44-45] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 44, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+46*sizeof(qword)] ; T += K_SHA512[46-47] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 46, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+48*sizeof(qword)] ; T += K_SHA512[48-49] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 48, A,B,C,D,E,F,G,H ;; perform 50-59 rounds vpaddq xT1, W0, oword [KK_SHA512+50*sizeof(qword)] ; T += K_SHA512[50-51] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 50, G,H,A,B,C,D,E,F vpaddq xT1, W0, oword [KK_SHA512+52*sizeof(qword)] ; T += K_SHA512[52-53] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 52, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+54*sizeof(qword)] ; T += K_SHA512[54-55] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 54, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+56*sizeof(qword)] ; T += K_SHA512[56-57] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 56, A,B,C,D,E,F,G,H vpaddq xT1, W0, oword [KK_SHA512+58*sizeof(qword)] ; T += K_SHA512[58-59] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 58, G,H,A,B,C,D,E,F ;; perform 60-69 rounds vpaddq xT1, W0, oword [KK_SHA512+60*sizeof(qword)] ; T += K_SHA512[60-61] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 60, E,F,G,H,A,B,C,D vpaddq xT1, W0, oword [KK_SHA512+62*sizeof(qword)] ; T += K_SHA512[62-63] vmovdqa oword [rsp], xT1 SHA512_2step_2Wupdate 62, C,D,E,F,G,H,A,B vpaddq xT1, W0, oword [KK_SHA512+64*sizeof(qword)] ; T += K_SHA512[64-65] vmovdqa oword [rsp], xT1 SHA512_2step 64, A,B,C,D,E,F,G,H ROTATE_W vpaddq xT1, W0, oword [KK_SHA512+66*sizeof(qword)] ; T += K_SHA512[66-67] vmovdqa oword [rsp], xT1 SHA512_2step 66, G,H,A,B,C,D,E,F ROTATE_W vpaddq xT1, W0, oword [KK_SHA512+68*sizeof(qword)] ; T += K_SHA512[68-69] vmovdqa oword [rsp], xT1 SHA512_2step 68, E,F,G,H,A,B,C,D ROTATE_W ;; perform 70-79 rounds vpaddq xT1, W0, oword [KK_SHA512+70*sizeof(qword)] ; T += K_SHA512[70-71] vmovdqa oword [rsp], xT1 SHA512_2step 70, C,D,E,F,G,H,A,B ROTATE_W vpaddq xT1, W0, oword [KK_SHA512+72*sizeof(qword)] ; T += K_SHA512[72-73] vmovdqa oword [rsp], xT1 SHA512_2step 72, A,B,C,D,E,F,G,H ROTATE_W vpaddq xT1, W0, oword [KK_SHA512+74*sizeof(qword)] ; T += K_SHA512[74-75] vmovdqa oword [rsp], xT1 SHA512_2step 74, G,H,A,B,C,D,E,F ROTATE_W vpaddq xT1, W0, oword [KK_SHA512+76*sizeof(qword)] ; T += K_SHA512[76-77] vmovdqa oword [rsp], xT1 SHA512_2step 76, E,F,G,H,A,B,C,D ROTATE_W vpaddq xT1, W0, oword [KK_SHA512+78*sizeof(qword)] ; T += K_SHA512[78-79] vmovdqa oword [rsp], xT1 SHA512_2step 78, C,D,E,F,G,H,A,B ROTATE_W add qword [rdi], A ; update shash add qword [rdi+sizeof(qword)*1], B add qword [rdi+sizeof(qword)*2], C add qword [rdi+sizeof(qword)*3], D add qword [rdi+sizeof(qword)*4], E add qword [rdi+sizeof(qword)*5], F add qword [rdi+sizeof(qword)*6], G add qword [rdi+sizeof(qword)*7], H vmovdqa xT1, oword [rel SHUFB_BSWAP] add rsi, MBS_SHA512 sub rdx, MBS_SHA512 jg .sha512_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA512 %endif ;; (_IPP32E >= _IPP32E_E9 ) %endif ;; _ENABLE_ALG_SHA512_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha512l9as.asm000066400000000000000000000532731470420105600263710ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2017 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA512 ; ; Content: ; UpdateSHA512 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "ia_32e_regs.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA512_) %if (_SHA_NI_ENABLING_ == _FEATURE_OFF_) || (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) %if (_IPP32E >= _IPP32E_L9 ) ;; ;; assignments ;; %xdefine hA rax ;; hash values into GPU registers %xdefine hB rbx %xdefine hC rcx %xdefine hD rdx %xdefine hE r8 %xdefine hF r9 %xdefine hG r10 %xdefine hH r11 %xdefine T1 r12 ;; scratch %xdefine T2 r13 %xdefine T3 r14 %xdefine T4 r15 %xdefine T5 rdi %xdefine W0 ymm0 ;; W values into YMM registers %xdefine W1 ymm1 %xdefine W2 ymm2 %xdefine W3 ymm3 %xdefine W4 ymm4 %xdefine W5 ymm5 %xdefine W6 ymm6 %xdefine W7 ymm7 %xdefine yT1 ymm8 ;; scratch %xdefine yT2 ymm9 %xdefine yT3 ymm10 %xdefine yT4 ymm11 %xdefine W0L xmm0 %xdefine W1L xmm1 %xdefine W2L xmm2 %xdefine W3L xmm3 %xdefine W4L xmm4 %xdefine W5L xmm5 %xdefine W6L xmm6 %xdefine W7L xmm7 %xdefine YMM_SHUFB_BSWAP ymm12 ;; byte swap constant ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; textual rotation of W args ;; %macro ROTATE_W 0.nolist %xdefine %%_X W0 %xdefine W0 W1 %xdefine W1 W2 %xdefine W2 W3 %xdefine W3 W4 %xdefine W4 W5 %xdefine W5 W6 %xdefine W6 W7 %xdefine W7 %%_X %endmacro ;; ;; textual rotation of HASH arguments ;; %macro ROTATE_H 0.nolist %xdefine %%_X hH %xdefine hH hG %xdefine hG hF %xdefine hF hE %xdefine hE hD %xdefine hD hC %xdefine hC hB %xdefine hB hA %xdefine hA %%_X %endmacro %macro ROTATE_T4_T5 0.nolist %xdefine %%T T4 %xdefine T4 T5 %xdefine T5 %%T %endmacro ;; ;; update next 2 W[t] and W[t+1], t=16,...79 ;; ;; W[j] = sig1(W[t- 2]) + W[t- 7] ;; +sig0(W[t-15]) + W[t-16] ;; ;; sig0(x) = ROR(x,1) ^ROR(x,8) ^SHR(x,7) ;; = SHR(x,7) ;; ^SHR(x,1) ^SHL(x,63) ;; ^SHR(x,8) ^SHL(x,56) ;; sig1(x) = ROR(x,19)^ROR(x,61) ^SHR(x,6) ;; = SHR(x,6) ;; ^SHR(x,19) ^SHL(x,45) ;; ^SHR(x,61) ^SHL(x,3) ;; %macro UPDATE_W 9.nolist %xdefine %%nr %1 %xdefine %%W0 %2 %xdefine %%W1 %3 %xdefine %%W2 %4 %xdefine %%W3 %5 %xdefine %%W4 %6 %xdefine %%W5 %7 %xdefine %%W6 %8 %xdefine %%W7 %9 %assign %%W_AHEAD 16 vpalignr yT1,%%W1,%%W0,sizeof(qword) ;; T1 = {w2:w1} args sig0() vpalignr yT4,%%W5,%%W4,sizeof(qword) ;; T4 = {w10:w9} additive vpsrlq yT3,yT1,1 ;; sig0(): T3 = {w2:w1}>>1 vpaddq %%W0,%%W0,yT4 ;; W0 += {w10:w9} vpsrlq yT4,yT1,7 ;; sig0(): {w2:w1}>>7 vpsllq yT2,yT1,56 ;; sig0(): {w2:w1}<<(64-8) vpxor yT1,yT4,yT3 ;; sig0(): {w2:w1}>>7 ^ {w2:w1}>>1 vpsrlq yT3,yT3, 7 ;; sig0(): {w2:w1}>>1>>7 = {w2:w1}>>8 vpxor yT1,yT1,yT2 ;; sig0(): {w2:w1}>>7 ^ {w2:w1}>>1 ^ {w2:w1}<<(64-8) vpsllq yT2,yT2, 7 ;; sig0(): {w2:w1}<<(64-8)<<7 = {w2:w1}<<63 vpxor yT1,yT1,yT3 ;; sig0(): {w2:w1}>>7 ^ {w2:w1}>>1 ^ {w2:w1}<<(64-8) ^ {w2:w1}>>8 vpsrlq yT4,%%W7, 6 ;; sig1(): {w15:w14}>>6 vpxor yT1,yT1,yT2 ;; sig0()= {w2:w1}>>7 ;; ^{w2:w1}>>1 ^ {w2:w1}<<63 ;; ^{w2:w1}<<(64-8) ^ {w2:w1}>>8 vpsllq yT3,%%W7, 3 ;; sig1(): {w15:w14}<<3 vpaddq %%W0,%%W0,yT1 ;; W0 += sig0() vpsrlq yT2,%%W7, 19 ;; sig1(): {w15:w14}>>19 vpxor yT4,yT4,yT3 ;; sig1(): {w15:w14}>>6 ^ {w15:w14}<<3 vpsllq yT3,yT3, 42 ;; sig1(): {w15:w14}<<3<<42 = {w15:w14}<<45 vpxor yT4,yT4,yT2 ;; sig1(): {w15:w14}>>6 ^ {w15:w14}<<3 ^ {w15:w14}>>19 vpsrlq yT2,yT2,42 ;; sig1(): {w15:w14}>>19>>42= {w15:w14}>>61 vpxor yT4,yT4,yT3 ;; sig1(): {w15:w14}>>6 ^ {w15:w14}<<3 ^ {w15:w14}>>19 ^ {w15:w14}<<45 vpxor yT4,yT4,yT2 ;; sig1()= {w15:w14}>>6 ;; ^{w15:w14}<<3 ^ {w15:w14}>>61 ;; ^{w15:w14}>>19 ^ {w15:w14}<<45 vpaddq %%W0,%%W0,yT4 ;; W0 += sig1() vpaddq yT3,%%W0,YMMWORD [rbp+(%%nr/2)*sizeof(ymmword)] vmovdqa YMMWORD [rsi+(%%W_AHEAD/2)*sizeof(ymmword)+(%%nr/2)*sizeof(ymmword)],yT3 ROTATE_W %endmacro ;; ;; regular round (i): ;; ;; T1 = h + Sum1(e) + Ch(e,f,g) + K[i] + W[i] ;; T2 = Sum0(a) + Maj(a,b,c) ;; h = g ;; g = f ;; f = e ;; e = d + T1 ;; d = c ;; c = b ;; b = a ;; a = T1+T2 ;; ;; sum1(e) = (e>>>14)^(e>>>18)^(e>>>41) ;; sum0(a) = (a>>>28)^(a>>>34)^(a>>>39) ;; ch(e,f,g) = (e&f)^(~e^g) ;; maj(a,b,m)= (a&b)^(a&c)^(b&c) ;; ;; note: ;; 1) U + ch(e,f,g) = U + (e&f) & (~e&g) ;; 2) maj(a,b,c)= (a&b)^(a&c)^(b&c) = (a^b)&(b^c) ^b ;; to make sure both are correct - use GF(2) arith instead of logic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; or ;; X = sum0(a[i-1]) computed on prev round ;; a[i] += X ;; h[i] += (K[i]+W[i]) + sum1(e[i]) + ch(e[i],f[i],g[i]) or ;; h[i] += (K[i]+W[i]) + sum1(e[i]) + (e[i]&f[i]) + (~e[i]&g[i]) -- helps break dependencies ;; d[i] += h[i] ;; h[i] += maj(a[i],b[i],c[i]) ;; and following textual shift ;; {a[i+1],b[i+1],c[i+1],d[i+1],e[i+1],f[i+1],g[i+1],h[i+1]} <= {h[i],a[i],b[i],c[i],d[i],e[i],f[i],g[i]} ;; ;; on entry: ;; - T1 = f ;; - T3 = sum0{a[i-1]) ;; - T5 = b&c %macro SHA512_ROUND 9.nolist %xdefine %%nr %1 %xdefine %%hA %2 %xdefine %%hB %3 %xdefine %%hC %4 %xdefine %%hD %5 %xdefine %%hE %6 %xdefine %%hF %7 %xdefine %%hG %8 %xdefine %%hH %9 add %%hH, qword [rsi+(%%nr/2)*sizeof(ymmword)+(%%nr & 1)*sizeof(qword)] ;; h += (k[t]+w[t]) and T1, %%hE ;; ch(e,f,g): (f&e) rorx T2, %%hE, 41 ;; sum1(e): e>>>41 rorx T4, %%hE, 18 ;; sum1(e): e>>>18 add %%hA, T3 ;; complete computation a += sum0(a[t-1]) add %%hH, T1 ;; h += (k[t]+w[t]) + (f&e) andn T1, %%hE, %%hG ;; ch(e,f,g): (~e&g) xor T2, T4 ;; sum1(e): (e>>>41)^(e>>>18) rorx T3, %%hE, 14 ;; sum1(e): e>>>14 add %%hH, T1 ;; h += (k[t]+w[t]) + (f&e) + (~e&g) xor T2, T3 ;; sum1(e) = (e>>>41)^(e>>>18)^(e>>>14) mov T4, %%hA ;; maj(a,b,c): a rorx T1, %%hA, 39 ;; sum0(a): a>>>39 add %%hH, T2 ;; h += (k[t]+w[t]) +(f&e) +(~e&g) +sig1(e) xor T4, %%hB ;; maj(a,b,c): (a^b) rorx T3, %%hA, 34 ;; sum0(a): a>>>34 rorx T2, %%hA, 28 ;; sum0(a): a>>>28 add %%hD, %%hH ;; d += h and T5, T4 ;; maj(a,b,c): (b^c)&(a^b) xor T3, T1 ;; sum0(a): (a>>>13)^(a>>>22) xor T5, %%hB ;; maj(a,b,c) = (b^c)&(a^b)^b = (a&b)^(a&c)^(b&c) xor T3, T2 ;; sum0(a): = (a>>>13)^(a>>>22)^(a>>>2) add %%hH, T5 ;; h += (k[t]+w[t]) +(f&e) +(~e&g) +sig1(e) +maj(a,b,c) mov T1, %%hE ;; T1 = f (next round) ROTATE_T4_T5 ;; T5 = (b^c) (next round) %endmacro ;; ;; does 2 regular rounds and computes next 2 W values ;; (just 2 instances of SHA512_ROUND merged together with UPDATE_W) ;; %macro SHA512_2ROUND_SHED 1.nolist %xdefine %%round %1 %assign %%W_AHEAD 16 %assign %%nr %%round vpalignr yT1,W1,W0,sizeof(qword) add hH, qword [rsi+(%%nr/2)*sizeof(ymmword)+(%%nr & 1)*sizeof(qword)] and T1, hE vpalignr yT4,W5,W4,sizeof(qword) rorx T2, hE, 41 rorx T4, hE, 18 vpsrlq yT3,yT1,1 add hA, T3 add hH, T1 vpaddq W0,W0,yT4 andn T1, hE, hG xor T2, T4 vpsrlq yT4,yT1,7 rorx T3, hE, 14 add hH, T1 vpsllq yT2,yT1,56 xor T2, T3 mov T4, hA vpxor yT1,yT4,yT3 rorx T1, hA, 39 add hH, T2 vpsrlq yT3,yT3, 7 xor T4, hB rorx T3, hA, 34 vpxor yT1,yT1,yT2 rorx T2, hA, 28 add hD, hH vpsllq yT2,yT2, 7 and T5, T4 xor T3, T1 vpxor yT1,yT1,yT3 xor T5, hB xor T3, T2 vpsrlq yT4,W7, 6 add hH, T5 mov T1, hE vpxor yT1,yT1,yT2 ROTATE_T4_T5 ROTATE_H %assign %%nr %%nr+1 add hH, qword [rsi+(%%nr/2)*sizeof(ymmword)+(%%nr & 1)*sizeof(qword)] and T1, hE vpsllq yT3,W7, 3 rorx T2, hE, 41 rorx T4, hE, 18 vpaddq W0,W0,yT1 add hA, T3 add hH, T1 vpsrlq yT2,W7, 19 andn T1, hE, hG xor T2, T4 vpxor yT4,yT4,yT3 rorx T3, hE, 14 add hH, T1 vpsllq yT3,yT3, 42 xor T2, T3 mov T4, hA vpxor yT4,yT4,yT2 rorx T1, hA, 39 add hH, T2 vpsrlq yT2,yT2,42 xor T4, hB rorx T3, hA, 34 vpxor yT4,yT4,yT3 rorx T2, hA, 28 add hD, hH vpxor yT4,yT4,yT2 and T5, T4 xor T3, T1 vpaddq W0,W0,yT4 xor T5, hB xor T3, T2 vpaddq yT3,W0,YMMWORD [rbp+(%%nr/2)*sizeof(ymmword)] add hH, T5 mov T1, hE vmovdqa YMMWORD [rsi+(%%W_AHEAD/2)*sizeof(ymmword)+(%%nr/2)*sizeof(ymmword)],yT3 ROTATE_T4_T5 ROTATE_H ROTATE_W %endmacro ;; ;; update hash ;; %macro UPDATE_HASH 2.nolist %xdefine %%hashMem %1 %xdefine %%hash %2 add %%hash, %%hashMem mov %%hashMem, %%hash %endmacro ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR SHA512_YMM_K dq 0428a2f98d728ae22h, 07137449123ef65cdh, 0428a2f98d728ae22h, 07137449123ef65cdh dq 0b5c0fbcfec4d3b2fh, 0e9b5dba58189dbbch, 0b5c0fbcfec4d3b2fh, 0e9b5dba58189dbbch dq 03956c25bf348b538h, 059f111f1b605d019h, 03956c25bf348b538h, 059f111f1b605d019h dq 0923f82a4af194f9bh, 0ab1c5ed5da6d8118h, 0923f82a4af194f9bh, 0ab1c5ed5da6d8118h dq 0d807aa98a3030242h, 012835b0145706fbeh, 0d807aa98a3030242h, 012835b0145706fbeh dq 0243185be4ee4b28ch, 0550c7dc3d5ffb4e2h, 0243185be4ee4b28ch, 0550c7dc3d5ffb4e2h dq 072be5d74f27b896fh, 080deb1fe3b1696b1h, 072be5d74f27b896fh, 080deb1fe3b1696b1h dq 09bdc06a725c71235h, 0c19bf174cf692694h, 09bdc06a725c71235h, 0c19bf174cf692694h dq 0e49b69c19ef14ad2h, 0efbe4786384f25e3h, 0e49b69c19ef14ad2h, 0efbe4786384f25e3h dq 00fc19dc68b8cd5b5h, 0240ca1cc77ac9c65h, 00fc19dc68b8cd5b5h, 0240ca1cc77ac9c65h dq 02de92c6f592b0275h, 04a7484aa6ea6e483h, 02de92c6f592b0275h, 04a7484aa6ea6e483h dq 05cb0a9dcbd41fbd4h, 076f988da831153b5h, 05cb0a9dcbd41fbd4h, 076f988da831153b5h dq 0983e5152ee66dfabh, 0a831c66d2db43210h, 0983e5152ee66dfabh, 0a831c66d2db43210h dq 0b00327c898fb213fh, 0bf597fc7beef0ee4h, 0b00327c898fb213fh, 0bf597fc7beef0ee4h dq 0c6e00bf33da88fc2h, 0d5a79147930aa725h, 0c6e00bf33da88fc2h, 0d5a79147930aa725h dq 006ca6351e003826fh, 0142929670a0e6e70h, 006ca6351e003826fh, 0142929670a0e6e70h dq 027b70a8546d22ffch, 02e1b21385c26c926h, 027b70a8546d22ffch, 02e1b21385c26c926h dq 04d2c6dfc5ac42aedh, 053380d139d95b3dfh, 04d2c6dfc5ac42aedh, 053380d139d95b3dfh dq 0650a73548baf63deh, 0766a0abb3c77b2a8h, 0650a73548baf63deh, 0766a0abb3c77b2a8h dq 081c2c92e47edaee6h, 092722c851482353bh, 081c2c92e47edaee6h, 092722c851482353bh dq 0a2bfe8a14cf10364h, 0a81a664bbc423001h, 0a2bfe8a14cf10364h, 0a81a664bbc423001h dq 0c24b8b70d0f89791h, 0c76c51a30654be30h, 0c24b8b70d0f89791h, 0c76c51a30654be30h dq 0d192e819d6ef5218h, 0d69906245565a910h, 0d192e819d6ef5218h, 0d69906245565a910h dq 0f40e35855771202ah, 0106aa07032bbd1b8h, 0f40e35855771202ah, 0106aa07032bbd1b8h dq 019a4c116b8d2d0c8h, 01e376c085141ab53h, 019a4c116b8d2d0c8h, 01e376c085141ab53h dq 02748774cdf8eeb99h, 034b0bcb5e19b48a8h, 02748774cdf8eeb99h, 034b0bcb5e19b48a8h dq 0391c0cb3c5c95a63h, 04ed8aa4ae3418acbh, 0391c0cb3c5c95a63h, 04ed8aa4ae3418acbh dq 05b9cca4f7763e373h, 0682e6ff3d6b2b8a3h, 05b9cca4f7763e373h, 0682e6ff3d6b2b8a3h dq 0748f82ee5defb2fch, 078a5636f43172f60h, 0748f82ee5defb2fch, 078a5636f43172f60h dq 084c87814a1f0ab72h, 08cc702081a6439ech, 084c87814a1f0ab72h, 08cc702081a6439ech dq 090befffa23631e28h, 0a4506cebde82bde9h, 090befffa23631e28h, 0a4506cebde82bde9h dq 0bef9a3f7b2c67915h, 0c67178f2e372532bh, 0bef9a3f7b2c67915h, 0c67178f2e372532bh dq 0ca273eceea26619ch, 0d186b8c721c0c207h, 0ca273eceea26619ch, 0d186b8c721c0c207h dq 0eada7dd6cde0eb1eh, 0f57d4f7fee6ed178h, 0eada7dd6cde0eb1eh, 0f57d4f7fee6ed178h dq 006f067aa72176fbah, 00a637dc5a2c898a6h, 006f067aa72176fbah, 00a637dc5a2c898a6h dq 0113f9804bef90daeh, 01b710b35131c471bh, 0113f9804bef90daeh, 01b710b35131c471bh dq 028db77f523047d84h, 032caab7b40c72493h, 028db77f523047d84h, 032caab7b40c72493h dq 03c9ebe0a15c9bebch, 0431d67c49c100d4ch, 03c9ebe0a15c9bebch, 0431d67c49c100d4ch dq 04cc5d4becb3e42b6h, 0597f299cfc657e2ah, 04cc5d4becb3e42b6h, 0597f299cfc657e2ah dq 05fcb6fab3ad6faech, 06c44198c4a475817h, 05fcb6fab3ad6faech, 06c44198c4a475817h SHA512_YMM_BF dq 00001020304050607h, 008090a0b0c0d0e0fh, 00001020304050607h, 008090a0b0c0d0e0fh ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; UpdateSHA512(Ipp64u digest[], Ipp8u dataBlock[], int datalen, Ipp64u K_512[]) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM UpdateSHA512,PUBLIC %assign LOCAL_FRAME (sizeof(qword)*4 + sizeof(qword)*80*2) USES_GPR rbx,rsi,rdi,rbp,rbx,r12,r13,r14,r15 USES_XMM_AVX xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12 COMP_ABI 4 ;; ;; rdi = pointer to the updated hash ;; rsi = pointer to the data block ;; rdx = data block length ;; rcx = pointer to the SHA_512 constant (ignored) ;; %xdefine MBS_SHA512 (128) ;; ;; stack structure: ;; %assign _block 0 ;; block address %assign _hash _block+sizeof(qword) ;; hash address %assign _len _hash+sizeof(qword) ;; rest of processed data %assign _frame _len+sizeof(qword) ;; rsp before alignment %assign _dataW _frame+sizeof(qword) ;; W[t] values mov r15, rsp ; store orifinal rsp and rsp, -IPP_ALIGN_FACTOR ; 32-byte aligned stack movsxd r14, edx ; input length in bytes mov qword [rsp+_hash], rdi ; store hash address mov qword [rsp+_len], r14 ; store length mov qword [rsp+_frame], r15 ; store rsp vmovdqa YMM_SHUFB_BSWAP, ymmword [rel SHA512_YMM_BF] ; load byte shuffler mov hA, qword [rdi] ; load initial hash value mov hB, qword [rdi+1*sizeof(qword)] mov hC, qword [rdi+2*sizeof(qword)] mov hD, qword [rdi+3*sizeof(qword)] mov hE, qword [rdi+4*sizeof(qword)] mov hF, qword [rdi+5*sizeof(qword)] mov hG, qword [rdi+6*sizeof(qword)] mov hH, qword [rdi+7*sizeof(qword)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data 2 block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .sha512_block2_loop: lea r12, [rsi+MBS_SHA512] ; next block cmp r14, MBS_SHA512 ; %if single block processed cmovbe r12, rsi ; use the same data block address lea rbp, [rel SHA512_YMM_K] ; to SHA512 consts vmovdqu W0L, xmmword [rsi] ; load data block vmovdqu W1L, xmmword [rsi+1*sizeof(xmmword)] vmovdqu W2L, xmmword [rsi+2*sizeof(xmmword)] vmovdqu W3L, xmmword [rsi+3*sizeof(xmmword)] vmovdqu W4L, xmmword [rsi+4*sizeof(xmmword)] vmovdqu W5L, xmmword [rsi+5*sizeof(xmmword)] vmovdqu W6L, xmmword [rsi+6*sizeof(xmmword)] vmovdqu W7L, xmmword [rsi+7*sizeof(xmmword)] vinserti128 W0, W0, xmmword [r12], 1 ; merge next data block vinserti128 W1, W1, xmmword [r12+1*sizeof(xmmword)], 1 vinserti128 W2, W2, xmmword [r12+2*sizeof(xmmword)], 1 vinserti128 W3, W3, xmmword [r12+3*sizeof(xmmword)], 1 vinserti128 W4, W4, xmmword [r12+4*sizeof(xmmword)], 1 vinserti128 W5, W5, xmmword [r12+5*sizeof(xmmword)], 1 vinserti128 W6, W6, xmmword [r12+6*sizeof(xmmword)], 1 vinserti128 W7, W7, xmmword [r12+7*sizeof(xmmword)], 1 vpshufb W0, W0, YMM_SHUFB_BSWAP vpshufb W1, W1, YMM_SHUFB_BSWAP vpshufb W2, W2, YMM_SHUFB_BSWAP vpshufb W3, W3, YMM_SHUFB_BSWAP vpshufb W4, W4, YMM_SHUFB_BSWAP vpshufb W5, W5, YMM_SHUFB_BSWAP vpshufb W6, W6, YMM_SHUFB_BSWAP vpshufb W7, W7, YMM_SHUFB_BSWAP vpaddq yT1, W0, ymmword [rbp] vmovdqa ymmword [rsp+_dataW], yT1 vpaddq yT2, W1, ymmword [rbp+1*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+1*sizeof(ymmword)], yT2 vpaddq yT3, W2, ymmword [rbp+2*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+2*sizeof(ymmword)], yT3 vpaddq yT4, W3, ymmword [rbp+3*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+3*sizeof(ymmword)], yT4 vpaddq yT1, W4, ymmword [rbp+4*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+4*sizeof(ymmword)], yT1 vpaddq yT2, W5, ymmword [rbp+5*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+5*sizeof(ymmword)], yT2 vpaddq yT3, W6, ymmword [rbp+6*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+6*sizeof(ymmword)], yT3 vpaddq yT4, W7, ymmword [rbp+7*sizeof(ymmword)] vmovdqa ymmword [rsp+_dataW+7*sizeof(ymmword)], yT4 add rbp, 8*sizeof(ymmword) mov T5, hB ; T5 = b^c xor T3, T3 ; T3 = 0 mov T1, hF ; T1 = f xor T5, hC mov qword [rsp+_block], rsi ; store block address lea rsi, [rsp+_dataW] ; use rsi as stack pointer align IPP_ALIGN_FACTOR .block1_shed_proc: SHA512_2ROUND_SHED 0 SHA512_2ROUND_SHED 2 SHA512_2ROUND_SHED 4 SHA512_2ROUND_SHED 6 SHA512_2ROUND_SHED 8 SHA512_2ROUND_SHED 10 SHA512_2ROUND_SHED 12 SHA512_2ROUND_SHED 14 add rsi, 8*sizeof(ymmword) add rbp, 8*sizeof(ymmword) ;; and repeat cmp dword [rbp-sizeof(qword)],04a475817h jne .block1_shed_proc ;; the rest 16 rounds SHA512_ROUND 0, hA,hB,hC,hD,hE,hF,hG,hH SHA512_ROUND 1, hH,hA,hB,hC,hD,hE,hF,hG SHA512_ROUND 2, hG,hH,hA,hB,hC,hD,hE,hF SHA512_ROUND 3, hF,hG,hH,hA,hB,hC,hD,hE SHA512_ROUND 4, hE,hF,hG,hH,hA,hB,hC,hD SHA512_ROUND 5, hD,hE,hF,hG,hH,hA,hB,hC SHA512_ROUND 6, hC,hD,hE,hF,hG,hH,hA,hB SHA512_ROUND 7, hB,hC,hD,hE,hF,hG,hH,hA SHA512_ROUND 8, hA,hB,hC,hD,hE,hF,hG,hH SHA512_ROUND 9, hH,hA,hB,hC,hD,hE,hF,hG SHA512_ROUND 10, hG,hH,hA,hB,hC,hD,hE,hF SHA512_ROUND 11, hF,hG,hH,hA,hB,hC,hD,hE SHA512_ROUND 12, hE,hF,hG,hH,hA,hB,hC,hD SHA512_ROUND 13, hD,hE,hF,hG,hH,hA,hB,hC SHA512_ROUND 14, hC,hD,hE,hF,hG,hH,hA,hB SHA512_ROUND 15, hB,hC,hD,hE,hF,hG,hH,hA add hA, T3 sub rsi, ((80-16)/2)*sizeof(ymmword) ; restore stack to W mov rdi, qword [rsi+_hash-_dataW] ; restore hash pointer mov r14, qword [rsi+_len-_dataW] ; restore data length ;; update hash values by 1-st data block UPDATE_HASH qword [rdi], hA UPDATE_HASH qword [rdi+1*sizeof(qword)], hB UPDATE_HASH qword [rdi+2*sizeof(qword)], hC UPDATE_HASH qword [rdi+3*sizeof(qword)], hD UPDATE_HASH qword [rdi+4*sizeof(qword)], hE UPDATE_HASH qword [rdi+5*sizeof(qword)], hF UPDATE_HASH qword [rdi+6*sizeof(qword)], hG UPDATE_HASH qword [rdi+7*sizeof(qword)], hH cmp r14, MBS_SHA512*2 jl .done ;; do 80 rounds for the next block add rsi, 2*sizeof(qword) ; restore stack to next block W lea rbp, [rsi+40*sizeof(ymmword)] ; use rbp for loop limiter mov T5, hB ; T5 = b^c xor T3, T3 ; T3 = 0 mov T1, hF ; T1 = f xor T5, hC align IPP_ALIGN_FACTOR .block2_proc: SHA512_ROUND 0, hA,hB,hC,hD,hE,hF,hG,hH SHA512_ROUND 1, hH,hA,hB,hC,hD,hE,hF,hG SHA512_ROUND 2, hG,hH,hA,hB,hC,hD,hE,hF SHA512_ROUND 3, hF,hG,hH,hA,hB,hC,hD,hE SHA512_ROUND 4, hE,hF,hG,hH,hA,hB,hC,hD SHA512_ROUND 5, hD,hE,hF,hG,hH,hA,hB,hC SHA512_ROUND 6, hC,hD,hE,hF,hG,hH,hA,hB SHA512_ROUND 7, hB,hC,hD,hE,hF,hG,hH,hA add rsi, 4*sizeof(ymmword) cmp rsi, rbp jb .block2_proc add hA, T3 mov rdi, qword [rsp+_hash] ; restore hash pointer mov r14, qword [rsp+_len] ; restore data length ;; update hash values by 1-st data block UPDATE_HASH qword [rdi], hA UPDATE_HASH qword [rdi+1*sizeof(qword)], hB UPDATE_HASH qword [rdi+2*sizeof(qword)], hC UPDATE_HASH qword [rdi+3*sizeof(qword)], hD UPDATE_HASH qword [rdi+4*sizeof(qword)], hE UPDATE_HASH qword [rdi+5*sizeof(qword)], hF UPDATE_HASH qword [rdi+6*sizeof(qword)], hG UPDATE_HASH qword [rdi+7*sizeof(qword)], hH mov rsi, qword [rsp+_block] ; restore block address add rsi, MBS_SHA512*2 ; move data pointer sub r14, MBS_SHA512*2 ; update data length mov qword [rsp+_len], r14 jg .sha512_block2_loop .done: mov rsp, qword [rsp+_frame] REST_XMM_AVX REST_GPR ret ENDFUNC UpdateSHA512 %endif ;; _IPP32E_L9 and above %endif ;; _FEATURE_OFF_ / _FEATURE_TICKTOCK_ %endif ;; _ENABLE_ALG_SHA512_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsha512m7as.asm000066400000000000000000000452511470420105600263650ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SHA512 ; ; Content: ; UpdateSHA512 ; ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SHA512_) %if (_IPP32E >= _IPP32E_M7) && (_IPP32E < _IPP32E_E9 ) ;; ;; ENDIANNESS ;; %macro ENDIANNESS 2.nolist %xdefine %%dst %1 %xdefine %%src %2 %ifnidn %%dst,%%src mov %%dst,%%src %endif bswap %%dst %endmacro %macro ROT_R 2.nolist %xdefine %%r %1 %xdefine %%nbits %2 %if _IPP32E >= _IPP32E_L9 rorx %%r,%%r,%%nbits ;; %elif _IPP32E >= _IPP32E_Y8 ;; shrd %%r,%%r,%%nbits %else ror %%r,%%nbits %endif %endmacro ;; ;; SHA512 step ;; ;; Ipp64u T1 = H + SUM1(E) + CH(E,F,G) + K_SHA512[t] + W[t]; ;; Ipp64u T2 = SUM0(A) + MAJ(A,B,C); ;; D+= T1; ;; H = T1 + T2; ;; ;; where ;; SUM1(x) = ROR64(x,14) ^ ROR64(x,18) ^ ROR64(x,41) ;; SUM0(x) = ROR64(x,28) ^ ROR64(x,34) ^ ROR64(x,39) ;; ;; CHJ(x,y,z) = (x & y) ^ (~x & z) ;; MAJ(x,y,z) = (x & y) ^ (x & z) ^ (y & z) = (x&y)^((x^y)&z) ;; %macro SHA512_STEP_2 13.nolist %xdefine %%regA %1 %xdefine %%regB %2 %xdefine %%regC %3 %xdefine %%regD %4 %xdefine %%regE %5 %xdefine %%regF %6 %xdefine %%regG %7 %xdefine %%regH %8 %xdefine %%regT %9 %xdefine %%regF1 %10 %xdefine %%regF2 %11 %xdefine %%memW %12 %xdefine %%memCNT %13 ;; update H (start) add %%regH,[%%memCNT] ;; H += W[t]+K_SHA512[t] add %%regH,[%%memW] ;; compute T = SUM1(E) + CH(E,F,G) mov %%regF1,%%regE ;; SUM1() = E mov %%regF2,%%regE ;; CH() = E ROT_R %%regF1,14 ;; ROR(E,14) mov %%regT, %%regE push %%regE not %%regF2 ;; ~E ROT_R %%regE, 18 ;; ROR(E,18) and %%regT, %%regF ;; E&F and %%regF2,%%regG ;;~E&G xor %%regF1,%%regE ;; ROR(E,14)^ROR(E,18) ROT_R %%regE, 23 ;; ROR(E,41) xor %%regF2,%%regT ;; CH() = (E&F)&(~E&G) xor %%regF1,%%regE ;; SUM1() = ROR(E,14)^ROR(E,18)^ROR(E,41) pop %%regE ;; repair E lea %%regT, [%%regF1+%%regF2] ;; update H (continue) add %%regH, %%regT ;; update D add %%regD, %%regH ;; compute T = SUM0(A) + MAJ(A,B,C) mov %%regF1,%%regA ;; SUM0() = A mov %%regF2,%%regA ;; MAJ() = A ROT_R %%regF1,28 ;; ROR(A,28) mov %%regT, %%regA push %%regA xor %%regF2,%%regB ;; A^B ROT_R %%regA, 34 ;; ROR(A,34) and %%regT, %%regB ;; A&B and %%regF2,%%regC ;; (A^B)&C xor %%regF1,%%regA ;; ROR(A,2)^ROR(A,13) ROT_R %%regA, 5 ;; ROR(A,39) xor %%regF2,%%regT ;; MAJ() = (A^B)^((A^B)&C) xor %%regF1,%%regA ;; SUM0() = ROR(A,28)^ROR(A,34)^ROR(A,39) pop %%regA ;; repair A lea %%regT, [%%regF1+%%regF2] ;; update H (finish) add %%regH, %%regT %endmacro ;; ;; update W[] ;; ;; W[j] = SIG1(W[j- 2]) + W[j- 7] ;; +SIG0(W[j-15]) + W[j-16] ;; ;; SIG0(x) = ROR(x,1) ^ROR(x,8) ^LSR(x,7) ;; SIG1(x) = ROR(x,19)^ROR(x,61) ^LSR(x,6) ;; %macro UPDATE_2 5.nolist %xdefine %%nr %1 %xdefine %%sig0 %2 %xdefine %%sig1 %3 %xdefine %%W15 %4 %xdefine %%W2 %5 mov %%sig0, [rsp+((%%nr-15) & 0Fh)*8] ;; W[j-15] mov %%sig1, [rsp+((%%nr-2) & 0Fh)*8] ;; W[j-2] shr %%sig0, 7 ;; LSR(W[j-15], 7) shr %%sig1, 6 ;; LSR(W[j-2], 6) mov %%W15, [rsp+((%%nr-15) & 0Fh)*8] ;; W[j-15] mov %%W2, [rsp+((%%nr-2) & 0Fh)*8] ;; W[j-2] ROT_R %%W15, 1 ;; ROR(W[j-15], 1) ROT_R %%W2, 19 ;; ROR(W[j-2], 19) xor %%sig0, %%W15 ;; SIG0 ^= ROR(W[j-15], 1) xor %%sig1, %%W2 ;; SIG1 ^= ROR(W[j-2], 19) ROT_R %%W15, 7 ;; ROR(W[j-15], 8) ROT_R %%W2, 42 ;; ROR(W[j-2], 61) xor %%sig0, %%W15 ;; SIG0 ^= ROR(W[j-15], 8) xor %%sig1, %%W2 ;; SIG1 ^= ROR(W[j-2], 61) add %%sig0, [rsp+((%%nr-16) & 0Fh)*8] ;; SIG0 += W[j-16] add %%sig1, [rsp+((%%nr-7) & 0Fh)*8] ;; SIG1 += W[j-7] add %%sig0, %%sig1 mov [rsp+((%%nr-16) & 0Fh)*8], %%sig0 %endmacro segment .text align=IPP_ALIGN_FACTOR ;****************************************************************************************** ;* Purpose: Update internal digest according to message block ;* ;* void UpdateSHA512(DigestSHA512 digest, const Ipp32u* mblk, int mlen, const void* pParam) ;* ;****************************************************************************************** ;; ;; Lib = M7 ;; ;; ;; Caller = ippsHashUpdate_rmf ;; Caller = ippsHashFinal_rmf ;; Caller = ippsHashMessage_rmf ;; %xdefine KK_SHA512 rbp %if _IPP32E >= _IPP32E_U8 segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR pByteSwp DB 7,6,5,4,3,2,1,0, 15,14,13,12,11,10,9,8 %endif segment .text align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR IPPASM UpdateSHA512,PUBLIC %assign LOCAL_FRAME (16*sizeof(qword)+sizeof(qword)) USES_GPR rbx,rsi,rdi,r12,r13,r14,r15,rbp USES_XMM COMP_ABI 4 ;; rdi = hash ;; rsi = data buffer ;; rdx = buffer length ;; rcx = address of SHA512 constants %xdefine MBS_SHA512 (128) movsxd rdx, edx mov qword [rsp+16*sizeof(qword)], rdx ; save length of buffer mov KK_SHA512, rcx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process next data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .sha512_block_loop: ;; ;; initialize the first 16 qwords in the array W (remember about endian) ;; %if (_IPP32E >= _IPP32E_U8) movdqu xmm4, oword [rel pByteSwp] movdqu xmm0, oword [rsi+0*16] pshufb xmm0, xmm4 movdqa oword [rsp+0*16], xmm0 movdqu xmm1, oword [rsi+1*16] pshufb xmm1, xmm4 movdqa oword [rsp+1*16], xmm1 movdqu xmm2, oword [rsi+2*16] pshufb xmm2, xmm4 movdqa oword [rsp+2*16], xmm2 movdqu xmm3, oword [rsi+3*16] pshufb xmm3, xmm4 movdqa oword [rsp+3*16], xmm3 movdqu xmm0, oword [rsi+4*16] pshufb xmm0, xmm4 movdqa oword [rsp+4*16], xmm0 movdqu xmm1, oword [rsi+5*16] pshufb xmm1, xmm4 movdqa oword [rsp+5*16], xmm1 movdqu xmm2, oword [rsi+6*16] pshufb xmm2, xmm4 movdqa oword [rsp+6*16], xmm2 movdqu xmm3, oword [rsi+7*16] pshufb xmm3, xmm4 movdqa oword [rsp+7*16], xmm3 %else xor rcx,rcx align IPP_ALIGN_FACTOR .loop1: mov r8,[rsi+rcx*8+0*8] ENDIANNESS r8,r8 mov [rsp+rcx*8+0*8],r8 mov r9,[rsi+rcx*8+1*8] ENDIANNESS r9,r9 mov [rsp+rcx*8+1*8],r9 add rcx,2 cmp rcx,16 jl .loop1 %endif ;; ;; init A,B,C,D,E,F,G,H by the internal digest ;; ;; ;; init A, B, C, D, E, F, G, H by the internal digest ;; mov r8, [rdi+0*8] ; r8 = digest[0] (A) mov r9, [rdi+1*8] ; r9 = digest[1] (B) mov r10,[rdi+2*8] ; r10= digest[2] (C) mov r11,[rdi+3*8] ; r11= digest[3] (D) mov r12,[rdi+4*8] ; r12= digest[4] (E) mov r13,[rdi+5*8] ; r13= digest[5] (F) mov r14,[rdi+6*8] ; r14= digest[6] (G) mov r15,[rdi+7*8] ; r15= digest[7] (H) ;; ;; perform 0-79 steps ;; ;; A, B, C, D, E, F, G, H W[], K[] ;; ------------------------------------------------------------------------- SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*8}, {KK_SHA512+ 0*8} UPDATE_2 16, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*8}, {KK_SHA512+ 1*8} UPDATE_2 17, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*8}, {KK_SHA512+ 2*8} UPDATE_2 18, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*8}, {KK_SHA512+ 3*8} UPDATE_2 19, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*8}, {KK_SHA512+ 4*8} UPDATE_2 20, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*8}, {KK_SHA512+ 5*8} UPDATE_2 21, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*8}, {KK_SHA512+ 6*8} UPDATE_2 22, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*8}, {KK_SHA512+ 7*8} UPDATE_2 23, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*8}, {KK_SHA512+ 8*8} UPDATE_2 24, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*8}, {KK_SHA512+ 9*8} UPDATE_2 25, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*8}, {KK_SHA512+10*8} UPDATE_2 26, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*8}, {KK_SHA512+11*8} UPDATE_2 27, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*8}, {KK_SHA512+12*8} UPDATE_2 28, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*8}, {KK_SHA512+13*8} UPDATE_2 29, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*8}, {KK_SHA512+14*8} UPDATE_2 30, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*8}, {KK_SHA512+15*8} UPDATE_2 31, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*8}, {KK_SHA512+16*8} UPDATE_2 32, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*8}, {KK_SHA512+17*8} UPDATE_2 33, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*8}, {KK_SHA512+18*8} UPDATE_2 34, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*8}, {KK_SHA512+19*8} UPDATE_2 35, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*8}, {KK_SHA512+20*8} UPDATE_2 36, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*8}, {KK_SHA512+21*8} UPDATE_2 37, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*8}, {KK_SHA512+22*8} UPDATE_2 38, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*8}, {KK_SHA512+23*8} UPDATE_2 39, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*8}, {KK_SHA512+24*8} UPDATE_2 40, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*8}, {KK_SHA512+25*8} UPDATE_2 41, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*8}, {KK_SHA512+26*8} UPDATE_2 42, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*8}, {KK_SHA512+27*8} UPDATE_2 43, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*8}, {KK_SHA512+28*8} UPDATE_2 44, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*8}, {KK_SHA512+29*8} UPDATE_2 45, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*8}, {KK_SHA512+30*8} UPDATE_2 46, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*8}, {KK_SHA512+31*8} UPDATE_2 47, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*8}, {KK_SHA512+32*8} UPDATE_2 48, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*8}, {KK_SHA512+33*8} UPDATE_2 49, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*8}, {KK_SHA512+34*8} UPDATE_2 50, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*8}, {KK_SHA512+35*8} UPDATE_2 51, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*8}, {KK_SHA512+36*8} UPDATE_2 52, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*8}, {KK_SHA512+37*8} UPDATE_2 53, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*8}, {KK_SHA512+38*8} UPDATE_2 54, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*8}, {KK_SHA512+39*8} UPDATE_2 55, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*8}, {KK_SHA512+40*8} UPDATE_2 56, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*8}, {KK_SHA512+41*8} UPDATE_2 57, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*8}, {KK_SHA512+42*8} UPDATE_2 58, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*8}, {KK_SHA512+43*8} UPDATE_2 59, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*8}, {KK_SHA512+44*8} UPDATE_2 60, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*8}, {KK_SHA512+45*8} UPDATE_2 61, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*8}, {KK_SHA512+46*8} UPDATE_2 62, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*8}, {KK_SHA512+47*8} UPDATE_2 63, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*8}, {KK_SHA512+48*8} UPDATE_2 64, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*8}, {KK_SHA512+49*8} UPDATE_2 65, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*8}, {KK_SHA512+50*8} UPDATE_2 66, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*8}, {KK_SHA512+51*8} UPDATE_2 67, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*8}, {KK_SHA512+52*8} UPDATE_2 68, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*8}, {KK_SHA512+53*8} UPDATE_2 69, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*8}, {KK_SHA512+54*8} UPDATE_2 70, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*8}, {KK_SHA512+55*8} UPDATE_2 71, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*8}, {KK_SHA512+56*8} UPDATE_2 72, rax,rbx, rcx,rdx SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*8}, {KK_SHA512+57*8} UPDATE_2 73, rax,rbx, rcx,rdx SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*8}, {KK_SHA512+58*8} UPDATE_2 74, rax,rbx, rcx,rdx SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*8}, {KK_SHA512+59*8} UPDATE_2 75, rax,rbx, rcx,rdx SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*8}, {KK_SHA512+60*8} UPDATE_2 76, rax,rbx, rcx,rdx SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*8}, {KK_SHA512+61*8} UPDATE_2 77, rax,rbx, rcx,rdx SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*8}, {KK_SHA512+62*8} UPDATE_2 78, rax,rbx, rcx,rdx SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*8}, {KK_SHA512+63*8} UPDATE_2 79, rax,rbx, rcx,rdx SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 0*8}, {KK_SHA512+64*8} SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 1*8}, {KK_SHA512+65*8} SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+ 2*8}, {KK_SHA512+66*8} SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+ 3*8}, {KK_SHA512+67*8} SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+ 4*8}, {KK_SHA512+68*8} SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+ 5*8}, {KK_SHA512+69*8} SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+ 6*8}, {KK_SHA512+70*8} SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+ 7*8}, {KK_SHA512+71*8} SHA512_STEP_2 r8, r9, r10,r11,r12,r13,r14,r15, rbx,rcx,rdx, {rsp+ 8*8}, {KK_SHA512+72*8} SHA512_STEP_2 r15,r8, r9, r10,r11,r12,r13,r14, rbx,rcx,rdx, {rsp+ 9*8}, {KK_SHA512+73*8} SHA512_STEP_2 r14,r15,r8, r9, r10,r11,r12,r13, rbx,rcx,rdx, {rsp+10*8}, {KK_SHA512+74*8} SHA512_STEP_2 r13,r14,r15,r8, r9, r10,r11,r12, rbx,rcx,rdx, {rsp+11*8}, {KK_SHA512+75*8} SHA512_STEP_2 r12,r13,r14,r15,r8, r9, r10,r11, rbx,rcx,rdx, {rsp+12*8}, {KK_SHA512+76*8} SHA512_STEP_2 r11,r12,r13,r14,r15,r8, r9, r10, rbx,rcx,rdx, {rsp+13*8}, {KK_SHA512+77*8} SHA512_STEP_2 r10,r11,r12,r13,r14,r15,r8, r9, rbx,rcx,rdx, {rsp+14*8}, {KK_SHA512+78*8} SHA512_STEP_2 r9, r10,r11,r12,r13,r14,r15,r8, rbx,rcx,rdx, {rsp+15*8}, {KK_SHA512+79*8} ;; ;; update digest ;; add [rdi+0*8],r8 add [rdi+1*8],r9 add [rdi+2*8],r10 add [rdi+3*8],r11 add [rdi+4*8],r12 add [rdi+5*8],r13 add [rdi+6*8],r14 add [rdi+7*8],r15 add rsi, MBS_SHA512 sub qword [rsp+16*sizeof(qword)], MBS_SHA512 jg .sha512_block_loop REST_XMM REST_GPR ret ENDFUNC UpdateSHA512 %endif ;; (_IPP32E >= _IPP32E_M7) AND (_IPP32E < _IPP32E_E9 ) %endif ;; _ENABLE_ALG_SHA512_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsm2pfuncs_montas.asm000066400000000000000000000675771470420105600301120ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; SM2 specific implementation ; %include "asmdefs.inc" %include "ia_32e.inc" %if (_IPP32E >= _IPP32E_M7) %assign _xEMULATION_ 1 %assign _ADCX_ADOX_ 1 segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR ;; The SM2 polynomial Lpoly DQ 0FFFFFFFFFFFFFFFFh,0FFFFFFFF00000000h,0FFFFFFFFFFFFFFFFh,0FFFFFFFEFFFFFFFFh ;; 2^512 mod P precomputed for SM2 polynomial LRR DQ 00000000200000003h,000000002ffffffffh,00000000100000001h,00000000400000002h LOne DD 1,1,1,1,1,1,1,1 LTwo DD 2,2,2,2,2,2,2,2 LThree DD 3,3,3,3,3,3,3,3 segment .text align=IPP_ALIGN_FACTOR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_mul_by_2(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_mul_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] shld t4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC sm2_mul_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_div_by_2(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_div_by_2,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13,r14 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] xor t4, t4 xor r14, r14 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] adc t4, 0 test a0, 1 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 cmovnz r14,t4 shrd a0, a1, 1 shrd a1, a2, 1 shrd a2, a3, 1 shrd a3, r14,1 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC sm2_div_by_2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_mul_by_3(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_mul_by_3,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] shld t4, a3, 1 shld a3, a2, 1 shld a2, a1, 1 shld a1, a0, 1 shl a0, 1 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 xor t4, t4 add a0, qword [rsi+sizeof(qword)*0] adc a1, qword [rsi+sizeof(qword)*1] adc a2, qword [rsi+sizeof(qword)*2] adc a3, qword [rsi+sizeof(qword)*3] adc t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC sm2_mul_by_3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_add(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_add,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] add a0, qword [rdx+sizeof(qword)*0] adc a1, qword [rdx+sizeof(qword)*1] adc a2, qword [rdx+sizeof(qword)*2] adc a3, qword [rdx+sizeof(qword)*3] adc t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb t4, 0 cmovz a0, t0 cmovz a1, t1 cmovz a2, t2 cmovz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC sm2_add ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_sub(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_sub,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 3 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 mov a0, qword [rsi+sizeof(qword)*0] mov a1, qword [rsi+sizeof(qword)*1] mov a2, qword [rsi+sizeof(qword)*2] mov a3, qword [rsi+sizeof(qword)*3] sub a0, qword [rdx+sizeof(qword)*0] sbb a1, qword [rdx+sizeof(qword)*1] sbb a2, qword [rdx+sizeof(qword)*2] sbb a3, qword [rdx+sizeof(qword)*3] sbb t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC sm2_sub ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_neg(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_neg,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rsi,rdi,r12,r13 USES_XMM COMP_ABI 2 %xdefine a0 r8 %xdefine a1 r9 %xdefine a2 r10 %xdefine a3 r11 %xdefine t0 rax %xdefine t1 rdx %xdefine t2 rcx %xdefine t3 r12 %xdefine t4 r13 xor t4, t4 xor a0, a0 xor a1, a1 xor a2, a2 xor a3, a3 sub a0, qword [rsi+sizeof(qword)*0] sbb a1, qword [rsi+sizeof(qword)*1] sbb a2, qword [rsi+sizeof(qword)*2] sbb a3, qword [rsi+sizeof(qword)*3] sbb t4, 0 mov t0, a0 mov t1, a1 mov t2, a2 mov t3, a3 add t0, qword [rel Lpoly+sizeof(qword)*0] adc t1, qword [rel Lpoly+sizeof(qword)*1] adc t2, qword [rel Lpoly+sizeof(qword)*2] adc t3, qword [rel Lpoly+sizeof(qword)*3] test t4, t4 cmovnz a0, t0 cmovnz a1, t1 cmovnz a2, t2 cmovnz a3, t3 mov qword [rdi+sizeof(qword)*0], a0 mov qword [rdi+sizeof(qword)*1], a1 mov qword [rdi+sizeof(qword)*2], a2 mov qword [rdi+sizeof(qword)*3], a3 REST_XMM REST_GPR ret ENDFUNC sm2_neg ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_mul_montl(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; on entry p5=0 ; on exit p0=0, p5=0/1 ; %macro sm2_mul_redstep 6.nolist %xdefine %%p5 %1 %xdefine %%p4 %2 %xdefine %%p3 %3 %xdefine %%p2 %4 %xdefine %%p1 %5 %xdefine %%p0 %6 mov acc6, %%p0 ;; (u1:u0) = p0*2^32 shl acc6, 32 mov acc7, %%p0 shr acc7, 32 mov t0, %%p0 mov t4, %%p0 xor t1, t1 xor t3, t3 sub t0, acc6 ;; (t3:t2:t1:t0) = p0*2^256 -p0*2^224 +p0*2^64 -p0*2^96 sbb t1, acc7 sbb t3, acc6 sbb t4, acc7 add %%p1, t0 ;; (p5:p4:p3:p2:p1) -= (t3:t2:t1:t0) adc %%p2, t1 adc %%p3, t3 adc %%p4, t4 adc %%p5, 0 ;; p5 extension xor %%p0, %%p0 ;; p0 = 0; %endmacro align IPP_ALIGN_FACTOR sm2_mmull: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax %xdefine t5 r14 ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc5, acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*0] mov acc0, rax mov acc1, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*1] add acc1, rax adc rdx, 0 mov acc2, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*2] add acc2, rax adc rdx, 0 mov acc3, rdx mov rax, qword [bPtr+sizeof(qword)*0] mul qword [aPtr+sizeof(qword)*3] add acc3, rax adc rdx, 0 mov acc4, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 1-st reduction step sm2_mul_redstep acc5,acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*0] add acc1, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*1] add acc2, t0 adc rdx, 0 add acc2, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*2] add acc3, t0 adc rdx, 0 add acc3, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*1] mul qword [aPtr+sizeof(qword)*3] add acc4, t0 adc rdx, 0 add acc4, rax adc acc5, rdx adc acc0, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 2-ndt reduction step sm2_mul_redstep acc0,acc5,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*0] add acc2, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*1] add acc3, t0 adc rdx, 0 add acc3, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*2] add acc4, t0 adc rdx, 0 add acc4, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*2] mul qword [aPtr+sizeof(qword)*3] add acc5, t0 adc rdx, 0 add acc5, rax adc acc0, rdx adc acc1, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 3-rd reduction step sm2_mul_redstep acc1,acc0,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[3] mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*0] add acc3, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*1] add acc4, t0 adc rdx, 0 add acc4, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*2] add acc5, t0 adc rdx, 0 add acc5, rax adc rdx, 0 mov t0, rdx mov rax, qword [bPtr+sizeof(qword)*3] mul qword [aPtr+sizeof(qword)*3] add acc0, t0 adc rdx, 0 add acc0, rax adc acc1, rdx adc acc2, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; final reduction step sm2_mul_redstep acc2,acc1,acc0,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 mov acc3, acc5 mov acc6, acc0 mov acc7, acc1 sub t4, t0 ;; test %if it exceeds prime value sbb acc3, t1 sbb acc6, t2 sbb acc7, t3 sbb acc2, 0 cmovnc acc4, t4 cmovnc acc5, acc3 cmovnc acc0, acc6 cmovnc acc1, acc7 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc0 mov qword [rdi+sizeof(qword)*3], acc1 ret align IPP_ALIGN_FACTOR IPPASM sm2_mul_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call sm2_mmull REST_XMM REST_GPR ret ENDFUNC sm2_mul_montl ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_to_mont(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_to_mont,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 lea rbx, [rel LRR] call sm2_mmull REST_XMM REST_GPR ret ENDFUNC sm2_to_mont ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_mul_montx(uint64_t res[4], uint64_t a[4], uint64_t b[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %if (_IPP32E >= _IPP32E_L9) align IPP_ALIGN_FACTOR sm2_mmulx: %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rax %xdefine t1 rdx %xdefine t3 rcx %xdefine t4 rbp %xdefine t2 rbx ; rdi assumed as result %xdefine aPtr rsi %xdefine bPtr rbx xor acc5, acc5 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[0] xor rdx, rdx mov rdx, qword [bPtr+sizeof(qword)*0] mulx acc1,acc0, qword [aPtr+sizeof(qword)*0] mulx acc2,t3, qword [aPtr+sizeof(qword)*1] add acc1,t3 mulx acc3,t3, qword [aPtr+sizeof(qword)*2] adc acc2,t3 mulx acc4,t3, qword [aPtr+sizeof(qword)*3] adc acc3,t3 adc acc4,0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 0 sm2_mul_redstep acc5,acc4,acc3,acc2,acc1,acc0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[1] mov rdx, qword [bPtr+sizeof(qword)*1] mulx t4, t3, qword [aPtr+sizeof(qword)*0] adcx acc1, t3 adox acc2, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*1] adcx acc2, t3 adox acc3, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*2] adcx acc3, t3 adox acc4, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*3] adcx acc4, t3 adox acc5, t4 adcx acc5, acc0 adox acc0, acc0 adc acc0, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 1 sm2_mul_redstep acc0,acc5,acc4,acc3,acc2,acc1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[2] mov rdx, qword [bPtr+sizeof(qword)*2] mulx t4, t3, qword [aPtr+sizeof(qword)*0] adcx acc2, t3 adox acc3, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*1] adcx acc3, t3 adox acc4, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*2] adcx acc4, t3 adox acc5, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*3] adcx acc5, t3 adox acc0, t4 adcx acc0, acc1 adox acc1, acc1 adc acc1, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 2 sm2_mul_redstep acc1,acc0,acc5,acc4,acc3,acc2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; * b[3] mov rdx, qword [bPtr+sizeof(qword)*3] mulx t4, t3, qword [aPtr+sizeof(qword)*0] adcx acc3, t3 adox acc4, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*1] adcx acc4, t3 adox acc5, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*2] adcx acc5, t3 adox acc0, t4 mulx t4, t3, qword [aPtr+sizeof(qword)*3] adcx acc0, t3 adox acc1, t4 adcx acc1, acc2 adox acc2, acc2 adc acc2, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; reduction step 3 (final) sm2_mul_redstep acc2,acc1,acc0,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 ;; copy reducted result mov acc3, acc5 mov acc6, acc0 mov acc7, acc1 sub t4, t0 ;; test %if it exceeds prime value sbb acc3, t1 sbb acc6, t2 sbb acc7, t3 sbb acc2, 0 cmovnc acc4, t4 cmovnc acc5, acc3 cmovnc acc0, acc6 cmovnc acc1, acc7 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc0 mov qword [rdi+sizeof(qword)*3], acc1 ret %endif %if _IPP32E >= _IPP32E_L9 align IPP_ALIGN_FACTOR IPPASM sm2_mul_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 3 %xdefine bPtr rbx mov bPtr, rdx call sm2_mmulx REST_XMM REST_GPR ret ENDFUNC sm2_mul_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_sqr_montl(uint64_t res[4], uint64_t a[4]); ; void sm2_sqr_montx(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; %macro sm2_prod_redstep 6.nolist %xdefine %%e %1 %xdefine %%p4 %2 %xdefine %%p3 %3 %xdefine %%p2 %4 %xdefine %%p1 %5 %xdefine %%p0 %6 mov t4, %%p0 mov t0, %%p0 mov t3, %%p0 xor t1, t1 xor t2, t2 shl %%p0, 32 shr t4, 32 ;; (t4:p0) = p0*2^32 sub t0, %%p0 ;; (t3:t2:t1:t0) = p0*2^256 -p0*2^224 +p0*2^64 -p0*2^96 sbb t1, t4 sbb t2, %%p0 sbb t3, t4 xor %%p0, %%p0 add %%p1, t0 ;; (p5:p4:p3:p2:p1) -= (t3:t2:t1:t0) adc %%p2, t1 adc %%p3, t2 adc %%p4, t3 adc %%p0, 0 %ifnempty %%e add %%p4, %%e adc %%p0, 0 %endif %endmacro align IPP_ALIGN_FACTOR IPPASM sm2_sqr_montl,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*0] mov rax,qword [aPtr+sizeof(qword)*1] mul t2 mov acc1, rax mov acc2, rdx mov rax,qword [aPtr+sizeof(qword)*2] mul t2 add acc2, rax adc rdx, 0 mov acc3, rdx mov rax,qword [aPtr+sizeof(qword)*3] mul t2 add acc3, rax adc rdx, 0 mov acc4, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*1] mov rax,qword [aPtr+sizeof(qword)*2] mul t2 add acc3, rax adc rdx, 0 mov t1, rdx mov rax,qword [aPtr+sizeof(qword)*3] mul t2 add acc4, rax adc rdx, 0 add acc4, t1 adc rdx, 0 mov acc5, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t2, qword [aPtr+sizeof(qword)*2] mov rax,qword [aPtr+sizeof(qword)*3] mul t2 add acc5, rax adc rdx, 0 mov acc6, rdx xor acc7, acc7 shld acc7, acc6, 1 shld acc6, acc5, 1 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 mov rax,qword [aPtr+sizeof(qword)*0] mul rax mov acc0, rax add acc1, rdx adc acc2, 0 mov rax,qword [aPtr+sizeof(qword)*1] mul rax add acc2, rax adc acc3, rdx adc acc4, 0 mov rax,qword [aPtr+sizeof(qword)*2] mul rax add acc4, rax adc acc5, rdx adc acc6, 0 mov rax,qword [aPtr+sizeof(qword)*3] mul rax add acc6, rax adc acc7, rdx ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sm2_prod_redstep ,acc4,acc3,acc2,acc1,acc0 sm2_prod_redstep acc0,acc5,acc4,acc3,acc2,acc1 sm2_prod_redstep acc1,acc6,acc5,acc4,acc3,acc2 sm2_prod_redstep acc2,acc7,acc6,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 mov acc0, acc5 mov acc1, acc6 mov acc2, acc7 sub t4, t0 sbb acc0, t1 sbb acc1, t2 sbb acc2, t3 sbb acc3, 0 cmovnc acc4, t4 cmovnc acc5, acc0 cmovnc acc6, acc1 cmovnc acc7, acc2 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 REST_XMM REST_GPR ret ENDFUNC sm2_sqr_montl %if (_IPP32E >= _IPP32E_L9) align IPP_ALIGN_FACTOR IPPASM sm2_sqr_montx,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*0] mulx acc2, acc1, qword [aPtr+sizeof(qword)*1] mulx acc3, t0, qword [aPtr+sizeof(qword)*2] add acc2, t0 mulx acc4, t0, qword [aPtr+sizeof(qword)*3] adc acc3, t0 adc acc4, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*1] xor acc5, acc5 mulx t1, t0, qword [aPtr+sizeof(qword)*2] adcx acc3, t0 adox acc4, t1 mulx t1, t0, qword [aPtr+sizeof(qword)*3] adcx acc4, t0 adox acc5, t1 adc acc5, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov rdx, qword [aPtr+sizeof(qword)*2] mulx acc6, t0, qword [aPtr+sizeof(qword)*3] add acc5, t0 adc acc6, 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; xor acc7, acc7 shld acc7, acc6, 1 shld acc6, acc5, 1 shld acc5, acc4, 1 shld acc4, acc3, 1 shld acc3, acc2, 1 shld acc2, acc1, 1 shl acc1, 1 xor acc0, acc0 mov rdx, qword [aPtr+sizeof(qword)*0] mulx t1, acc0, rdx adcx acc1, t1 mov rdx, qword [aPtr+sizeof(qword)*1] mulx t1, t0, rdx adcx acc2, t0 adcx acc3, t1 mov rdx, qword [aPtr+sizeof(qword)*2] mulx t1, t0, rdx adcx acc4, t0 adcx acc5, t1 mov rdx, qword [aPtr+sizeof(qword)*3] mulx t1, t0, rdx adcx acc6, t0 adcx acc7, t1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; sm2_prod_redstep ,acc4,acc3,acc2,acc1,acc0 sm2_prod_redstep acc0,acc5,acc4,acc3,acc2,acc1 sm2_prod_redstep acc1,acc6,acc5,acc4,acc3,acc2 sm2_prod_redstep acc2,acc7,acc6,acc5,acc4,acc3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov t0, qword [rel Lpoly+sizeof(qword)*0] mov t1, qword [rel Lpoly+sizeof(qword)*1] mov t2, qword [rel Lpoly+sizeof(qword)*2] mov t3, qword [rel Lpoly+sizeof(qword)*3] mov t4, acc4 mov acc0, acc5 mov acc1, acc6 mov acc2, acc7 sub t4, t0 sbb acc0, t1 sbb acc1, t2 sbb acc2, t3 sbb acc3, 0 cmovnc acc4, t4 cmovnc acc5, acc0 cmovnc acc6, acc1 cmovnc acc7, acc2 mov qword [rdi+sizeof(qword)*0], acc4 mov qword [rdi+sizeof(qword)*1], acc5 mov qword [rdi+sizeof(qword)*2], acc6 mov qword [rdi+sizeof(qword)*3], acc7 REST_XMM REST_GPR ret ENDFUNC sm2_sqr_montx %endif ;; _IPP32E_L9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; void sm2_mont_back(uint64_t res[4], uint64_t a[4]); ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR IPPASM sm2_mont_back,PUBLIC %assign LOCAL_FRAME 0 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 2 %xdefine acc0 r8 %xdefine acc1 r9 %xdefine acc2 r10 %xdefine acc3 r11 %xdefine acc4 r12 %xdefine acc5 r13 %xdefine acc6 r14 %xdefine acc7 r15 %xdefine t0 rcx %xdefine t1 rbp %xdefine t2 rbx %xdefine t3 rdx %xdefine t4 rax mov acc2, qword [rsi+sizeof(qword)*0] mov acc3, qword [rsi+sizeof(qword)*1] mov acc4, qword [rsi+sizeof(qword)*2] mov acc5, qword [rsi+sizeof(qword)*3] xor acc0, acc0 xor acc1, acc1 sm2_mul_redstep acc1,acc0,acc5,acc4,acc3,acc2 sm2_mul_redstep acc2,acc1,acc0,acc5,acc4,acc3 sm2_mul_redstep acc3,acc2,acc1,acc0,acc5,acc4 sm2_mul_redstep acc4,acc3,acc2,acc1,acc0,acc5 mov t0, acc0 mov t1, acc1 mov t2, acc2 mov t3, acc3 sub t0, qword [rel Lpoly+sizeof(qword)*0] sbb t1, qword [rel Lpoly+sizeof(qword)*1] sbb t2, qword [rel Lpoly+sizeof(qword)*2] sbb t3, qword [rel Lpoly+sizeof(qword)*3] sbb acc4, 0 cmovnc acc0, t0 cmovnc acc1, t1 cmovnc acc2, t2 cmovnc acc3, t3 mov qword [rdi+sizeof(qword)*0], acc0 mov qword [rdi+sizeof(qword)*1], acc1 mov qword [rdi+sizeof(qword)*2], acc2 mov qword [rdi+sizeof(qword)*3], acc3 REST_XMM REST_GPR ret ENDFUNC sm2_mont_back %endif ;; _IPP32E>=_IPP32E_M7 cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsm3e9as.asm000066400000000000000000000535711470420105600260620ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SM3 ; ; Content: ; UpdateSM3 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SM3_) %if (_IPP32E >= _IPP32E_E9) %xdefine A r8d %xdefine B r9d %xdefine C r10d %xdefine D r11d %xdefine E r12d %xdefine F r13d %xdefine G r14d %xdefine H r15d %xdefine hPtr rdi %xdefine mPtr rsi %xdefine kPtr rcx %xdefine t0 eax %xdefine t1 ebx %xdefine t2 ebp %xdefine t3 edx %xdefine W0 xmm0 %xdefine W1 xmm1 %xdefine W2 xmm2 %xdefine W3 xmm3 %xdefine xT0 xmm4 %xdefine xT1 xmm5 %xdefine xTr xmm6 %xdefine xWZZZ xmm7 %xdefine xBCAST xmm8 %xdefine xROL8 xmm9 %macro ROTATE_H 0.nolist %xdefine %%DUMMY H %xdefine H G %xdefine G F %xdefine F E %xdefine E D %xdefine D C %xdefine C B %xdefine B A %xdefine A %%DUMMY %endmacro %macro ROUND_00_15 1.nolist %xdefine %%nr %1 mov t0, A mov t1, [kPtr+%%nr*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, E shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 add t1, H ; t1: TT2 = SS1 + h add t0, D ; t0: TT1 = SS2 + d add t1, [rsp+(%%nr & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%nr & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) mov t2, B mov t3, F xor t2, C xor t3, G xor t2, A ; t2 = FF(a,b,c) = a^b^c xor t3, E ; t3 = GG(e,f,g) = e^f^g add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF shld B, B, 9 shld F, F, 19 mov H, t0 mov D, t1 shld D, D, 8 xor D, t1 shld D, D, 9 xor D, t1 ROTATE_H %endmacro %macro ROUND_16_63 9.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 mov t0, %%A mov t1, [kPtr+%%nr*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%E shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 add t1, %%H ; t1: TT2 = SS1 + h add t0, %%D ; t0: TT1 = SS2 + d add t1, [rsp+(%%nr & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%nr & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) mov t3, %%B mov t2, %%B and t3, %%C xor t2, %%C and t2, %%A add t2, t3 mov t3, %%F xor t3, %%G and t3, %%E xor t3, %%G add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG shld %%B, %%B, 9 shld %%F, %%F, 19 mov %%H, t0 mov %%D, t1 shld %%D, %%D, 8 xor %%D, t1 shld %%D, %%D, 9 xor %%D, t1 ;ROTATE_H %endmacro ;; ;; Y = ROL32(X,nbits) %macro xmmROL32 3.nolist %xdefine %%Y %1 %xdefine %%X %2 %xdefine %%nbits %3 %if %%nbits != 8 vpslld xTr,%%X, %%nbits vpsrld %%Y, %%X, (32-%%nbits) vpxor %%Y, %%Y, xTr %else ;;vpshufb Y, X, oword [rel rol_32_8] vpshufb %%Y, %%X, xROL8 %endif %endmacro %macro xmmBCAST 2.nolist %xdefine %%Y %1 %xdefine %%X %2 ;;vpshufb Y, X, oword [rel bcast] vpshufb %%Y, %%X, xBCAST %endmacro ;; ;; w[j] = P1(w[t-16]^w[t-9]^ROL32(w[t-3],15)) ^ ROL32(w[t-13],7) ^ w[t-6] ;; %macro ROTATE_W 0.nolist %xdefine %%DUMMY W0 %xdefine W0 W1 %xdefine W1 W2 %xdefine W2 W3 %xdefine W3 %%DUMMY %endmacro %macro QSCHED 0.nolist vpalignr xT0, W1, W0, sizeof(dword)*3 ;; T0 = {w6,w5,w4,w3} xmmROL32 xT0, xT0, 7 ;; T0 = ROL32({w6,w5,w4,w3}, 7) ;; compute P1() argument vpsrldq xT1, W3, sizeof(dword) ;; T1 = {Z,w15,w14,w13} xmmROL32 xT1, xT1, 15 ;; T1 = ROL32({Z,w15,w14,w13}, 15) vpxor W0, W0, xT1 ;; W0 = {w3,w2,w1,w0} ^ ROL32({Z,w15,w14,w13}, 15) vpalignr xT1, W2, W1, sizeof(dword)*3 ;; T1 = {w10,w9,w8,w7} vpxor W0, W0, xT1 ;; W0 = {w3,w2,w1,w0} ^ ROL32({Z,w15,w14,w13}, 15) ^ {w10,w9,w8,w7} ;; compute W0 = P1(W0), P1(x) = x ^ rol32(x,15) ^ rol(x,23) xmmROL32 xT1, W0, 8 vpxor xT1, xT1, W0 xmmROL32 xT1, xT1, 15 vpxor W0, W0, xT1 vpalignr xT1, W3, W2, sizeof(dword)*2 ;; T1 = {w13,w12,w11,w10} vpxor W0, W0, xT0 vpxor W0, W0, xT1 ;; compute P1(rol(w16,15)) xmmBCAST xT0, W0 ;; T0 = {w16,w16,w16,rw16} vpsrlq xT0, xT0, (32-15) ;; T0 = {??,rol(w16,15),??,rol(w16,15)} xmmBCAST xT0, xT0 ;; T0 = {rol(w16,15),rol(w16,15),rol(w16,15),rol(w16,15)} vpsllq xT1, xT0, 15 vpxor xT0, xT0, xT1 vpsllq xT1, xT1, (23-15) vpxor xT0, xT0, xT1 ;;vpshufb xT0, xT0, [rel wzzz] ;; T0 = {P1(rol(w16,15)),zz,zz,zz} vpshufb xT0, xT0, xWZZZ ;; T0 = {P1(rol(w16,15)),zz,zz,zz} vpxor W0, W0, xT0 ROTATE_W %endmacro %macro QSCHED_W_QROUND_00_15 9.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 vpalignr xT0, W1, W0, sizeof(dword)*3 ;; T0 = {w6,w5,w4,w3} xmmROL32 xT0, xT0, 7 ;; T0 = ROL32({w6,w5,w4,w3}, 7) %assign %%t %%nr ;ROUND_00_15 t mov t0, %%A mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%E shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 add t1, %%H ; t1: TT2 = SS1 + h add t0, %%D ; t0: TT1 = SS2 + d add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) vpsrldq xT1, W3, sizeof(dword) ;; T1 = {Z,w15,w14,w13} xmmROL32 xT1, xT1, 15 ;; T1 = ROL32({Z,w15,w14,w13}, 15) mov t2, %%B mov t3, %%F xor t2, %%C xor t3, %%G xor t2, %%A ; t2 = FF(a,b,c) = a^b^c xor t3, %%E ; t3 = GG(e,f,g) = e^f^g add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF shld %%B, %%B, 9 shld %%F, %%F, 19 mov %%H, t0 vpxor W0, W0, xT1 ;; W0 = {w3,w2,w1,w0} ^ ROL32({Z,w15,w14,w13}, 15) vpalignr xT1, W2, W1, sizeof(dword)*3 ;; T1 = {w10,w9,w8,w7} vpxor W0, W0, xT1 ;; W0 = {w3,w2,w1,w0} ^ ROL32({Z,w15,w14,w13}, 15) ^ {w10,w9,w8,w7} mov %%D, t1 shld %%D, %%D, 8 xor %%D, t1 shld %%D, %%D, 9 xor %%D, t1 ;ROTATE_H ;;;;;;;;;;;;;;; %assign %%t %%t+1 ;ROUND_00_15 t mov t0, %%H mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%D shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 xmmROL32 xT1, W0, 8 vpxor xT1, xT1, W0 add t1, %%G ; t1: TT2 = SS1 + h add t0, %%C ; t0: TT1 = SS2 + d add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) xmmROL32 xT1, xT1, 15 vpxor W0, W0, xT1 mov t2, %%A mov t3, %%E xor t2, %%B xor t3, %%F xor t2, %%H ; t2 = FF(a,b,c) = a^b^c xor t3, %%D ; t3 = GG(e,f,g) = e^f^g add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF shld %%A, %%A, 9 shld %%E, %%E, 19 mov %%G, t0 mov %%C, t1 shld %%C, %%C, 8 xor %%C, t1 shld %%C, %%C, 9 xor %%C, t1 ;ROTATE_H ;;;;;;;;;;;;;;; vpalignr xT1, W3, W2, sizeof(dword)*2 ;; T1 = {w13,w12,w11,w10} vpxor W0, W0, xT0 vpxor W0, W0, xT1 %assign %%t %%t+1 ;ROUND_00_15 t mov t0, %%G mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%C shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 add t1, %%F ; t1: TT2 = SS1 + h add t0, %%B ; t0: TT1 = SS2 + d xmmBCAST xT0, W0 ;; T0 = {w16,w16,w16,rw16} vpsrlq xT0, xT0, (32-15) ;; T0 = {??,rol(w16,15),??,rol(w16,15)} add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) mov t2, %%H mov t3, %%D xor t2, %%A xor t3, %%E xor t2, %%G ; t2 = FF(a,b,c) = a^b^c xor t3, %%C ; t3 = GG(e,f,g) = e^f^g add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF shld %%H, %%H, 9 shld %%D, %%D, 19 xmmBCAST xT0, xT0 ;; T0 = {rol(w16,15),rol(w16,15),rol(w16,15),rol(w16,15)} vpsllq xT1, xT0, 15 mov %%F, t0 mov %%B, t1 shld %%B, %%B, 8 xor %%B, t1 shld %%B, %%B, 9 xor %%B, t1 ;ROTATE_H ;;;;;;;;;;;;;;; %assign %%t %%t+1 ;ROUND_00_15 t mov t0, %%F mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%B shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 vpxor xT0, xT0, xT1 vpsllq xT1, xT1, (23-15) add t1, %%E ; t1: TT2 = SS1 + h add t0, %%A ; t0: TT1 = SS2 + d add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) mov t2, %%G mov t3, %%C xor t2, %%H xor t3, %%D vpxor xT0, xT0, xT1 ;;vpshufb xT0, xT0, [rel wzzz] ;; T0 = {P1(rol(w16,15)),zz,zz,zz} vpshufb xT0, xT0, xWZZZ ;; T0 = {P1(rol(w16,15)),zz,zz,zz} xor t2, %%F ; t2 = FF(a,b,c) = a^b^c xor t3, %%B ; t3 = GG(e,f,g) = e^f^g add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF shld %%G, %%G, 9 shld %%C, %%C, 19 vpxor W0, W0, xT0 mov %%E, t0 mov %%A, t1 shld %%A, %%A, 8 xor %%A, t1 shld %%A, %%A, 9 xor %%A, t1 ;ROTATE_H ROTATE_W ;;;;;;;;;;;;;;; %endmacro %macro QSCHED_W_QROUND_16_63 9.nolist %xdefine %%nr %1 %xdefine %%A %2 %xdefine %%B %3 %xdefine %%C %4 %xdefine %%D %5 %xdefine %%E %6 %xdefine %%F %7 %xdefine %%G %8 %xdefine %%H %9 vpalignr xT0, W1, W0, sizeof(dword)*3 ;; T0 = {w6,w5,w4,w3} xmmROL32 xT0, xT0, 7 ;; T0 = ROL32({w6,w5,w4,w3}, 7) %assign %%t %%nr ;ROUND_16_63 t mov t0, %%A mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%E shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 add t1, %%H ; t1: TT2 = SS1 + h add t0, %%D ; t0: TT1 = SS2 + d add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) vpsrldq xT1, W3, sizeof(dword) ;; T1 = {Z,w15,w14,w13} xmmROL32 xT1, xT1, 15 ;; T1 = ROL32({Z,w15,w14,w13}, 15) mov t3, %%B mov t2, %%B and t3, %%C xor t2, %%C and t2, %%A add t2, t3 mov t3, %%F xor t3, %%G and t3, %%E xor t3, %%G add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG shld %%B, %%B, 9 shld %%F, %%F, 19 mov %%H, t0 vpxor W0, W0, xT1 ;; W0 = {w3,w2,w1,w0} ^ ROL32({Z,w15,w14,w13}, 15) vpalignr xT1, W2, W1, sizeof(dword)*3 ;; T1 = {w10,w9,w8,w7} vpxor W0, W0, xT1 ;; W0 = {w3,w2,w1,w0} ^ ROL32({Z,w15,w14,w13}, 15) ^ {w10,w9,w8,w7} mov %%D, t1 shld %%D, %%D, 8 xor %%D, t1 shld %%D, %%D, 9 xor %%D, t1 ;ROTATE_H ;;;;;;;;;;;;;;;;;;;;;;;;;;;; %assign %%t %%t + 1 ;ROUND_16_63 t mov t0, %%H mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%D shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 xmmROL32 xT1, W0, 8 vpxor xT1, xT1, W0 add t1, %%G ; t1: TT2 = SS1 + h add t0, %%C ; t0: TT1 = SS2 + d add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) xmmROL32 xT1, xT1, 15 vpxor W0, W0, xT1 mov t3, %%A mov t2, %%A and t3, %%B xor t2, %%B and t2, %%H add t2, t3 mov t3, %%E xor t3, %%F and t3, %%D xor t3, %%F add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG shld %%A, %%A, 9 shld %%E, %%E, 19 mov %%G, t0 mov %%C, t1 shld %%C, %%C, 8 xor %%C, t1 shld %%C, %%C, 9 xor %%C, t1 ;ROTATE_H ;;;;;;;;;;;;;;;;;;;;;;;;;;;; vpalignr xT1, W3, W2, sizeof(dword)*2 ;; T1 = {w13,w12,w11,w10} vpxor W0, W0, xT0 vpxor W0, W0, xT1 %assign %%t %%t + 1 ;ROUND_16_63 t mov t0, %%G mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%C shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 add t1, %%F ; t1: TT2 = SS1 + h add t0, %%B ; t0: TT1 = SS2 + d xmmBCAST xT0, W0 ;; T0 = {w16,w16,w16,rw16} vpsrlq xT0, xT0, (32-15) ;; T0 = {??,rol(w16,15),??,rol(w16,15)} add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) mov t3, %%H mov t2, %%H and t3, %%A xor t2, %%A and t2, %%G add t2, t3 mov t3, %%D xor t3, %%E and t3, %%C xor t3, %%E add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG shld %%H, %%H, 9 shld %%D, %%D, 19 xmmBCAST xT0, xT0 ;; T0 = {rol(w16,15),rol(w16,15),rol(w16,15),rol(w16,15)} vpsllq xT1, xT0, 15 mov %%F, t0 mov %%B, t1 shld %%B, %%B, 8 xor %%B, t1 shld %%B, %%B, 9 xor %%B, t1 ;ROTATE_H ;;;;;;;;;;;;;;;;;;;;;;;;;;;; %assign %%t %%t + 1 ;ROUND_16_63 t mov t0, %%F mov t1, [kPtr+%%t*sizeof(dword)] shld t0, t0, 12 ; t0 = t add t1, t0 add t1, %%B shld t1, t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 vpxor xT0, xT0, xT1 vpsllq xT1, xT1, (23-15) add t1, %%E ; t1: TT2 = SS1 + h add t0, %%A ; t0: TT1 = SS2 + d add t1, [rsp+(%%t & 3)*sizeof(dword)] ; t1: TT2 = SS1 + h +w[nr] add t0, [rsp+(%%t & 3)*sizeof(dword)+sizeof(oword)] ; t0: TT1 = SS2 + d +(w[nr]^w[nr+4]) mov t3, %%G mov t2, %%G and t3, %%H xor t2, %%H and t2, %%F add t2, t3 vpxor xT0, xT0, xT1 ;;vpshufb xT0, xT0, [rel wzzz] ;; T0 = {P1(rol(w16,15)),zz,zz,zz} vpshufb xT0, xT0, xWZZZ ;; T0 = {P1(rol(w16,15)),zz,zz,zz} mov t3, %%C xor t3, %%D and t3, %%B xor t3, %%D add t0, t2 ; t0: TT1 = SS2 +d +(w[nr]^w[nr+4]) +FF add t1, t3 ; t1: TT2 = SS1 +h +w[nr] +GG shld %%G, %%G, 9 shld %%C, %%C, 19 vpxor W0, W0, xT0 mov %%E, t0 mov %%A, t1 shld %%A, %%A, 8 xor %%A, t1 shld %%A, %%A, 9 xor %%A, t1 ;ROTATE_H ROTATE_W ;;;;;;;;;;;;;;;;;;;;;;;;;;;; %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR bswap128 DB 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 rol_32_8 DB 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14 bcast DB 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3 wzzz DB 80h,80h,80h,80h, 80h,80h,80h,80h, 80h,80h,80h,80h,12,13,14,15 segment .text align=IPP_ALIGN_FACTOR ;******************************************************************** ;* void UpdateSM3(Ipp32u* hash, ; const Ipp8u* msg, int msgLen, ; const Ipp32u* K_SM3) ;******************************************************************** align IPP_ALIGN_FACTOR IPPASM UpdateSM3,PUBLIC %assign LOCAL_FRAME sizeof(oword)*2+sizeof(qword)*2 USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM xmm6,xmm7,xmm8,xmm9 COMP_ABI 4 ;; rdi = hash ;; rsi = data buffer ;; rdx = data buffer length (bytes) ;; rcx = address of SM3 constants ;; stack structure: %assign _wj 0 ; W[t+3]:W[t+2]:W[t+1]:W[t] %assign _hash _wj+sizeof(oword)*2 ; hash pointer %assign _len _hash+sizeof(qword) ; msg length %xdefine MBS_SM3 (64) movsxd rdx, edx movdqa xT0, oword [rel bswap128] ; swap byte movdqa xWZZZ, oword [rel wzzz] ; shuffle constant movdqa xBCAST, oword [rel bcast] movdqa xROL8, oword [rel rol_32_8] mov qword [rsp+_hash], rdi ; save hash pointer mov qword [rsp+_len], rdx ; save msg length align IPP_ALIGN_FACTOR .sm3_loop: ; read data block (64 bytes) vmovdqu W0, oword [mPtr+sizeof(oword)*0] vpshufb W0, W0, xT0 vmovdqu W1, oword [mPtr+sizeof(oword)*1] vpshufb W1, W1, xT0 vmovdqu W2, oword [mPtr+sizeof(oword)*2] vpshufb W2, W2, xT0 vmovdqu W3, oword [mPtr+sizeof(oword)*3] vpshufb W3, W3, xT0 add mPtr, MBS_SM3 mov A, [hPtr+0*sizeof(dword)] ; input hash value mov B, [hPtr+1*sizeof(dword)] mov C, [hPtr+2*sizeof(dword)] mov D, [hPtr+3*sizeof(dword)] mov E, [hPtr+4*sizeof(dword)] mov F, [hPtr+5*sizeof(dword)] mov G, [hPtr+6*sizeof(dword)] mov H, [hPtr+7*sizeof(dword)] vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_00_15 0, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_00_15 4, E,F,G,H,A,B,C,D vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_00_15 8, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_00_15 12, E,F,G,H,A,B,C,D vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 16, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 20, E,F,G,H,A,B,C,D vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 24, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 28, E,F,G,H,A,B,C,D vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 32, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 36, E,F,G,H,A,B,C,D vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 40, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 44, E,F,G,H,A,B,C,D vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 QSCHED_W_QROUND_16_63 48, A,B,C,D,E,F,G,H vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 ROTATE_W ROUND_16_63 52, E,F,G,H,A,B,C,D ROUND_16_63 53, D,E,F,G,H,A,B,C ROUND_16_63 54, C,D,E,F,G,H,A,B ROUND_16_63 55, B,C,D,E,F,G,H,A vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 ROTATE_W ROUND_16_63 56, A,B,C,D,E,F,G,H ROUND_16_63 57, H,A,B,C,D,E,F,G ROUND_16_63 58, G,H,A,B,C,D,E,F ROUND_16_63 59, F,G,H,A,B,C,D,E vmovdqa oword [rsp+_wj], W0 vpxor xT0, W0, W1 vmovdqa oword [rsp+_wj+sizeof(oword)], xT0 ROTATE_W ROUND_16_63 60, E,F,G,H,A,B,C,D ROUND_16_63 61, D,E,F,G,H,A,B,C ROUND_16_63 62, C,D,E,F,G,H,A,B ROUND_16_63 63, B,C,D,E,F,G,H,A mov hPtr, qword [rsp+_hash] ; restore hash pointer xor [hPtr+0*sizeof(dword)], A ; update hash xor [hPtr+1*sizeof(dword)], B xor [hPtr+2*sizeof(dword)], C xor [hPtr+3*sizeof(dword)], D xor [hPtr+4*sizeof(dword)], E xor [hPtr+5*sizeof(dword)], F xor [hPtr+6*sizeof(dword)], G xor [hPtr+7*sizeof(dword)], H movdqa xT0, oword [rel bswap128] ; swap byte sub qword [rsp+_len], MBS_SM3 cmp qword [rsp+_len], MBS_SM3 jge .sm3_loop REST_XMM REST_GPR ret ENDFUNC UpdateSM3 %endif ;; _IPP32E >= _IPP32E_E9 %endif ;; _ENABLE_ALG_SM3_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsm3l9_ni_as.asm000066400000000000000000000221631470420105600267070ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2024 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SM3 with SM3_NI instructions ; ; Content: ; UpdateSM3ni ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SM3_) %if (_IPP32E >= _IPP32E_L9) %xdefine hPtr rdi %xdefine mPtr rsi %xdefine mLen rdx segment .data align=IPP_ALIGN_FACTOR align 16 SHUFF_MASK: db 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 segment .text ; *************************************************************************** ; Create 4 x 32-bit new words of message schedule W[] using SM3-NI ISA ; *************************************************************************** %macro SM3MSG 7 %define %%W03_00 %1 ;; [in] XMM register with W[0..3] %define %%W07_04 %2 ;; [in] XMM register with W[4..7] %define %%W11_08 %3 ;; [in] XMM register with W[8..11] %define %%W15_12 %4 ;; [in] XMM register with W[12..15] %define %%W19_16 %5 ;; [out] XMM register with W[19..16] %define %%T1 %6 ;; [clobbered] XMM register %define %%T2 %7 ;; [clobbered] XMM register %define %%T3 %%W19_16 vpalignr %%T3, %%W11_08, %%W07_04, 3*4 ;; xmm8 = W10 W9 W8 W7 vpsrldq %%T1, %%W15_12, 4 ;; xmm9 = 0 W15 W14 W13 vsm3msg1 %%T3, %%T1, %%W03_00 ;; xmm8 = WTMP3 WTMP2 WTMP1 WTMP0 vpalignr %%T1, %%W07_04, %%W03_00, 3*4 ;; xmm9 = W6 W5 W4 W3 vpalignr %%T2, %%W15_12, %%W11_08, 2*4 ;; xmm1 = W13 W12 W11 W10 vsm3msg2 %%T3, %%T1, %%T2 ;; xmm8 = W19 W18 W17 W16 %endmacro ; *************************************************************************** ; Performs 4 rounds of SM3 algorithm ; - consumes 4 words of message schedule W[] ; - updates SM3 state registers: ABEF and CDGH ; *************************************************************************** %macro SM3ROUNDS4 6 %define %%ABEF %1 ;; [in/out] XMM register with ABEF registers %define %%CDGH %2 ;; [in/out] XMM register with CDGH registers %define %%W03_00 %3 ;; [in] XMM register with W[8..11] %define %%W07_04 %4 ;; [in] XMM register with W[12..15] %define %%T1 %5 ;; [clobbered] XMM register %define %%R %6 ;; [in] round number vpunpcklqdq %%T1, %%W03_00, %%W07_04 ;; T1 = W5 W4 W1 W0 vsm3rnds2 %%CDGH, %%ABEF, %%T1, %%R ;; CDGH = updated ABEF // 2 rounds vpunpckhqdq %%T1, %%W03_00, %%W07_04 ;; T1 = W7 W6 W3 W2 vsm3rnds2 %%ABEF, %%CDGH, %%T1, (%%R + 2) ;; ABEF = updated CDGH // 2 rounds %endmacro ;******************************************************************** ;* void UpdateSM3ni(uint32_t hash[8], ; const uint32_t msg[16], int msgLen, const uint32_t* K_SM3) ;******************************************************************** align IPP_ALIGN_FACTOR IPPASM UpdateSM3ni,PUBLIC %assign LOCAL_FRAME 68*sizeof(dword)+3*sizeof(qword) USES_GPR rsi,rdi,rdx,rcx USES_XMM COMP_ABI 4 ;; rdi = hash ;; rsi = data buffer ;; rdx = data buffer length (bytes) ;; rcx = address of SM3 constants (not used) %xdefine MBS_SM3 (64) movsxd rdx, edx vmovdqu xmm6, [hPtr] vmovdqu xmm7, [hPtr + 16] ;; xmm6 = D C B A, xmm7 = H G F E vpshufd xmm0, xmm6, 0x1B ;; xmm0 = A B C D vpshufd xmm1, xmm7, 0x1B ;; xmm1 = E F G H vpunpckhqdq xmm6, xmm1, xmm0 ;; xmm6 = A B E F vpunpcklqdq xmm7, xmm1, xmm0 ;; xmm7 = C D G H vpsrld xmm2, xmm7, 9 vpslld xmm3, xmm7, 23 vpxor xmm1, xmm2, xmm3 ;; xmm1 = xmm2 ^ xmm3 = ROL32(CDGH, 23) vpsrld xmm4, xmm7, 19 vpslld xmm5, xmm7, 13 vpxor xmm0, xmm4, xmm5 ;; xmm0 = xmm2 ^ xmm3 = ROL32(CDGH, 13) vpblendd xmm7, xmm1, xmm0, 0x3 ;; xmm7 = ROL32(C, 23) ROL32(D, 23) ROL32(G, 13) ROL32(H, 13) vmovdqa xmm12, [rel SHUFF_MASK] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .main_loop: vmovdqa xmm10, xmm6 vmovdqa xmm11, xmm7 ;; prepare W[0..15] - read and shuffle the data vmovdqu xmm2, [mPtr + 0*16] vmovdqu xmm3, [mPtr + 1*16] vmovdqu xmm4, [mPtr + 2*16] vmovdqu xmm5, [mPtr + 3*16] vpshufb xmm2, xmm2, xmm12 ;; xmm2 = W03 W02 W01 W00 vpshufb xmm3, xmm3, xmm12 ;; xmm3 = W07 W06 W05 W04 vpshufb xmm4, xmm4, xmm12 ;; xmm4 = W11 W10 W09 W08 vpshufb xmm5, xmm5, xmm12 ;; xmm5 = W15 W14 W13 W12 SM3MSG xmm2, xmm3, xmm4, xmm5, xmm8, xmm9, xmm1 ;; xmm8 = W19 W18 W17 W16 SM3ROUNDS4 xmm6, xmm7, xmm2, xmm3, xmm1, 0 vmovdqa xmm2, xmm8 SM3MSG xmm3, xmm4, xmm5, xmm2, xmm8, xmm9, xmm1 ;; xmm8 = W23 W22 W21 W20 SM3ROUNDS4 xmm6, xmm7, xmm3, xmm4, xmm1, 4 vmovdqa xmm3, xmm8 SM3MSG xmm4, xmm5, xmm2, xmm3, xmm8, xmm9, xmm1 ;; xmm8 = W27 W26 W25 W24 SM3ROUNDS4 xmm6, xmm7, xmm4, xmm5, xmm1, 8 vmovdqa xmm4, xmm8 SM3MSG xmm5, xmm2, xmm3, xmm4, xmm8, xmm9, xmm1 ;; xmm8 = W31 W30 W29 W28 SM3ROUNDS4 xmm6, xmm7, xmm5, xmm2, xmm1, 12 vmovdqa xmm5, xmm8 SM3MSG xmm2, xmm3, xmm4, xmm5, xmm8, xmm9, xmm1 ;; xmm8 = W35 W34 W33 W32 SM3ROUNDS4 xmm6, xmm7, xmm2, xmm3, xmm1, 16 vmovdqa xmm2, xmm8 SM3MSG xmm3, xmm4, xmm5, xmm2, xmm8, xmm9, xmm1 ;; xmm8 = W39 W38 W37 W36 SM3ROUNDS4 xmm6, xmm7, xmm3, xmm4, xmm1, 20 vmovdqa xmm3, xmm8 SM3MSG xmm4, xmm5, xmm2, xmm3, xmm8, xmm9, xmm1 ;; xmm8 = W43 W42 W41 W40 SM3ROUNDS4 xmm6, xmm7, xmm4, xmm5, xmm1, 24 vmovdqa xmm4, xmm8 SM3MSG xmm5, xmm2, xmm3, xmm4, xmm8, xmm9, xmm1 ;; xmm8 = W47 W46 W45 W44 SM3ROUNDS4 xmm6, xmm7, xmm5, xmm2, xmm1, 28 vmovdqa xmm5, xmm8 SM3MSG xmm2, xmm3, xmm4, xmm5, xmm8, xmm9, xmm1 ;; xmm8 = W51 W50 W49 W48 SM3ROUNDS4 xmm6, xmm7, xmm2, xmm3, xmm1, 32 vmovdqa xmm2, xmm8 SM3MSG xmm3, xmm4, xmm5, xmm2, xmm8, xmm9, xmm1 ;; xmm8 = W55 W54 W53 W52 SM3ROUNDS4 xmm6, xmm7, xmm3, xmm4, xmm1, 36 vmovdqa xmm3, xmm8 SM3MSG xmm4, xmm5, xmm2, xmm3, xmm8, xmm9, xmm1 ;; xmm8 = W59 W58 W57 W56 SM3ROUNDS4 xmm6, xmm7, xmm4, xmm5, xmm1, 40 vmovdqa xmm4, xmm8 SM3MSG xmm5, xmm2, xmm3, xmm4, xmm8, xmm9, xmm1 ;; xmm8 = W63 W62 W61 W60 SM3ROUNDS4 xmm6, xmm7, xmm5, xmm2, xmm1, 44 vmovdqa xmm5, xmm8 SM3MSG xmm2, xmm3, xmm4, xmm5, xmm8, xmm9, xmm1 ;; xmm8 = W67 W66 W65 W64 SM3ROUNDS4 xmm6, xmm7, xmm2, xmm3, xmm1, 48 vmovdqa xmm2, xmm8 SM3ROUNDS4 xmm6, xmm7, xmm3, xmm4, xmm1, 52 SM3ROUNDS4 xmm6, xmm7, xmm4, xmm5, xmm1, 56 SM3ROUNDS4 xmm6, xmm7, xmm5, xmm2, xmm1, 60 ;; update the hash value (xmm6, xmm7) and process the next message block vpxor xmm6, xmm6, xmm10 vpxor xmm7, xmm7, xmm11 add mPtr, MBS_SM3 sub mLen, MBS_SM3 jne .main_loop ;; store the hash value back in memory vpslld xmm2, xmm7, 9 vpsrld xmm3, xmm7, 23 vpxor xmm1, xmm2, xmm3 ;; xmm1 = xmm2 ^ xmm3 = ROL32(CDGH, 9) vpslld xmm4, xmm7, 19 vpsrld xmm5, xmm7, 13 vpxor xmm0, xmm4, xmm5 ;; xmm0 = xmm2 ^ xmm3 = ROL32(CDGH, 19) vpblendd xmm7, xmm1, xmm0, 0x3 ;; xmm7 = ROL32(C, 9) ROL32(D, 9) ROL32(G, 19) ROL32(H, 19) vpshufd xmm0, xmm6, 0x1B ;; xmm0 = F E B A vpshufd xmm1, xmm7, 0x1B ;; xmm1 = H G D C vpunpcklqdq xmm6, xmm0, xmm1 ;; xmm6 = D C B A vpunpckhqdq xmm7, xmm0, xmm1 ;; xmm7 = H G F E vmovdqu [hPtr], xmm6 vmovdqu [hPtr + 16], xmm7 REST_XMM REST_GPR ret ENDFUNC UpdateSM3ni %endif ;; _IPP32E >= _IPP32E_L9 %endif ;; _ENABLE_ALG_SM3_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpsm3u8as.asm000066400000000000000000000214631470420105600260740ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; ; Purpose: Cryptography Primitive. ; Message block processing according to SM3 ; ; Content: ; UpdateSM3 ; %include "asmdefs.inc" %include "ia_32e.inc" %include "pcpvariant.inc" %if (_ENABLE_ALG_SM3_) %if ((_IPP32E >= _IPP32E_U8 ) && (_IPP32E < _IPP32E_E9 )) || (_IPP32E == _IPP32E_N8 ) %xdefine a r8d %xdefine b r9d %xdefine c r10d %xdefine d r11d %xdefine e r12d %xdefine f r13d %xdefine g r14d %xdefine h r15d %xdefine hPtr rdi %xdefine mPtr rsi %xdefine kPtr rcx %xdefine t0 eax %xdefine t1 ebx %xdefine t2 ebp %xdefine t3 edx %xdefine ctr hPtr %if (_IPP32E >= _IPP32E_U8 ) %macro ROTL 2.nolist %xdefine %%x %1 %xdefine %%n %2 shld %%x,%%x, %%n %endmacro %else %macro ROTL 2.nolist %xdefine %%x %1 %xdefine %%n %2 rol %%x, %%n %endmacro %endif %macro ROUND_00_15 9.nolist %xdefine %%a %1 %xdefine %%b %2 %xdefine %%c %3 %xdefine %%d %4 %xdefine %%e %5 %xdefine %%f %6 %xdefine %%g %7 %xdefine %%h %8 %xdefine %%i %9 mov t0, %%a mov t1, [kPtr+ctr*sizeof(dword)+%%i*sizeof(dword)] ROTL t0, 12 ; t0 = t add t1, t0 add t1, %%e ROTL t1, 7 ; t1 = SS1 xor t0, t1 ; t0 = SS2 mov t2, %%b mov t3, %%f xor t2, %%c xor t3, %%g xor t2, %%a ; t2 = FF xor t3, %%e ; t3 = GG add t0, t2 ; t0 = SS2 + FF add t1, t3 ; t1 = SS1 + GG add t0, %%d ; t0 = SS2 + FF + d add t1, %%h ; t1 = SS1 + GG + h mov t2, [rsp+ctr*sizeof(dword)+%%i*sizeof(dword)] ; t2 = w[i] add t1, t2 ; t1 = TT2 xor t2, [rsp+ctr*sizeof(dword)+(%%i+4)*sizeof(dword)] ; t2 = w[i] ^ w[i+4] add t0, t2 ; t0 = TT1 ROTL %%b, 9 ROTL %%f, 19 mov %%h, t0 mov %%d, t1 ROTL %%d, 8 xor %%d, t1 ROTL %%d, 9 xor %%d, t1 %endmacro %macro ROUND_16_63 9.nolist %xdefine %%a %1 %xdefine %%b %2 %xdefine %%c %3 %xdefine %%d %4 %xdefine %%e %5 %xdefine %%f %6 %xdefine %%g %7 %xdefine %%h %8 %xdefine %%i %9 mov t0, %%a mov t1, [kPtr+ctr*sizeof(dword)+%%i*sizeof(dword)] ROTL t0, 12 add t1, t0 add t1, %%e ROTL t1, 7 ;; t1 = SS1 xor t0, t1 ;; t0 = SS2 mov t3, %%b mov t2, %%b and t3, %%c xor t2, %%c and t2, %%a add t2, t3 mov t3, %%f xor t3, %%g and t3, %%e xor t3, %%g add t0, t2 ;; t0 = SS2 + FF add t1, t3 ;; t1 = SS1 + GG add t0, %%d ;; t0 = SS2 + FF + d add t1, %%h ;; t1 = SS1 + GG + h mov t2, [rsp+ctr*sizeof(dword)+%%i*sizeof(dword)] ;; t2 = w[i] add t1, t2 ;; t1 = TT2 xor t2, [rsp+ctr*sizeof(dword)+(%%i+4)*sizeof(dword)] ;; t2 = w[i] ^ w[i+4] add t0, t2 ;; t0 = TT1 ROTL %%b, 9 ROTL %%f, 19 mov %%h, t0 mov %%d, t1 ROTL %%d, 8 xor %%d, t1 ROTL %%d, 9 xor %%d, t1 %endmacro %macro SCHED_16_67 1.nolist %xdefine %%i %1 mov t2, [rsp+ctr*sizeof(dword)+(%%i-3)*sizeof(dword)] ;; t2 = w[i-3] ROTL t2, 15 ;; t2 = rol(t2,15) xor t2, [rsp+ctr*sizeof(dword)+(%%i-9)*sizeof(dword)] ;; t2 ^= w[i-9] xor t2, [rsp+ctr*sizeof(dword)+(%%i-16)*sizeof(dword)] ;; t2 ^= w[i-16] mov t3, t2 ROTL t3, 8 xor t3, t2 ROTL t3, 15 xor t3, t2 ;; t3 = P1 mov t2, [rsp+ctr*sizeof(dword)+(%%i-13)*sizeof(dword)] xor t3, [rsp+ctr*sizeof(dword)+(%%i-6)*sizeof(dword)] ROTL t2, 7 xor t3, t2 mov [rsp+ctr*sizeof(dword)+%%i*sizeof(dword)], t3 %endmacro segment .data align=IPP_ALIGN_FACTOR align IPP_ALIGN_FACTOR bswap128 DB 3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12 segment .text align=IPP_ALIGN_FACTOR ;******************************************************************** ;* void UpdateSM3(uint32_t hash[8], ; const uint32_t msg[16], int msgLen, ; const uint32_t* K_SM3) ;******************************************************************** align IPP_ALIGN_FACTOR IPPASM UpdateSM3,PUBLIC %assign LOCAL_FRAME 68*sizeof(dword)+3*sizeof(qword) USES_GPR rbp,rbx,rsi,rdi,r12,r13,r14,r15 USES_XMM COMP_ABI 4 ;; rdi = hash ;; rsi = data buffer ;; rdx = data buffer length (bytes) ;; rcx = address of SM3 constants ;; stack structure: %assign _w 0 ; msg extension W0, ..., W67 %assign _hash _w+68*sizeof(dword) ; hash %assign _msg _hash+sizeof(qword) ; msg pointer %assign _len _msg+sizeof(qword) ; msg length %xdefine MBS_SM3 (64) movsxd rdx, edx mov qword [rsp+_hash], hPtr ; save hash pointer mov qword [rsp+_len], rdx ; save msg length mov a, [hPtr+0*sizeof(dword)] ; input hash value mov b, [hPtr+1*sizeof(dword)] mov c, [hPtr+2*sizeof(dword)] mov d, [hPtr+3*sizeof(dword)] mov e, [hPtr+4*sizeof(dword)] mov f, [hPtr+5*sizeof(dword)] mov g, [hPtr+6*sizeof(dword)] mov h, [hPtr+7*sizeof(dword)] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; process data block ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; align IPP_ALIGN_FACTOR .main_loop: xor ctr, ctr ; round movdqu xmm0, oword [mPtr+0*sizeof(oword)] movdqu xmm1, oword [mPtr+1*sizeof(oword)] movdqu xmm2, oword [mPtr+2*sizeof(oword)] movdqu xmm3, oword [mPtr+3*sizeof(oword)] add mPtr, MBS_SM3 mov qword [rsp+_msg], mPtr ; save msg pointer pshufb xmm0, [rel bswap128] pshufb xmm1, [rel bswap128] pshufb xmm2, [rel bswap128] pshufb xmm3, [rel bswap128] movdqu oword [rsp+0*sizeof(oword)], xmm0 movdqu oword [rsp+1*sizeof(oword)], xmm1 movdqu oword [rsp+2*sizeof(oword)], xmm2 movdqu oword [rsp+3*sizeof(oword)], xmm3 align IPP_ALIGN_FACTOR .rounds_00_15: SCHED_16_67 16 ROUND_00_15 a,b,c,d,e,f,g,h,0 SCHED_16_67 17 ROUND_00_15 h,a,b,c,d,e,f,g,1 SCHED_16_67 18 ROUND_00_15 g,h,a,b,c,d,e,f,2 SCHED_16_67 19 ROUND_00_15 f,g,h,a,b,c,d,e,3 SCHED_16_67 20 ROUND_00_15 e,f,g,h,a,b,c,d,4 SCHED_16_67 21 ROUND_00_15 d,e,f,g,h,a,b,c,5 SCHED_16_67 22 ROUND_00_15 c,d,e,f,g,h,a,b,6 SCHED_16_67 23 ROUND_00_15 b,c,d,e,f,g,h,a,7 add ctr, 8 cmp ctr, 16 jne .rounds_00_15 align IPP_ALIGN_FACTOR .rounds_16_47: SCHED_16_67 16 ROUND_16_63 a,b,c,d,e,f,g,h,0 SCHED_16_67 17 ROUND_16_63 h,a,b,c,d,e,f,g,1 SCHED_16_67 18 ROUND_16_63 g,h,a,b,c,d,e,f,2 SCHED_16_67 19 ROUND_16_63 f,g,h,a,b,c,d,e,3 SCHED_16_67 20 ROUND_16_63 e,f,g,h,a,b,c,d,4 SCHED_16_67 21 ROUND_16_63 d,e,f,g,h,a,b,c,5 SCHED_16_67 22 ROUND_16_63 c,d,e,f,g,h,a,b,6 SCHED_16_67 23 ROUND_16_63 b,c,d,e,f,g,h,a,7 add ctr, 8 cmp ctr, 48 jne .rounds_16_47 SCHED_16_67 16 SCHED_16_67 17 SCHED_16_67 18 SCHED_16_67 19 align IPP_ALIGN_FACTOR .rounds_48_63: ROUND_16_63 a,b,c,d,e,f,g,h,0 ROUND_16_63 h,a,b,c,d,e,f,g,1 ROUND_16_63 g,h,a,b,c,d,e,f,2 ROUND_16_63 f,g,h,a,b,c,d,e,3 ROUND_16_63 e,f,g,h,a,b,c,d,4 ROUND_16_63 d,e,f,g,h,a,b,c,5 ROUND_16_63 c,d,e,f,g,h,a,b,6 ROUND_16_63 b,c,d,e,f,g,h,a,7 add ctr, 8 cmp ctr, 64 jne .rounds_48_63 mov hPtr, [rsp+_hash] mov mPtr, [rsp+_msg] xor a, [hPtr+0*sizeof(dword)] xor b, [hPtr+1*sizeof(dword)] xor c, [hPtr+2*sizeof(dword)] xor d, [hPtr+3*sizeof(dword)] xor e, [hPtr+4*sizeof(dword)] xor f, [hPtr+5*sizeof(dword)] xor g, [hPtr+6*sizeof(dword)] xor h, [hPtr+7*sizeof(dword)] mov [hPtr+0*sizeof(dword)], a mov [hPtr+1*sizeof(dword)], b mov [hPtr+2*sizeof(dword)], c mov [hPtr+3*sizeof(dword)], d mov [hPtr+4*sizeof(dword)], e mov [hPtr+5*sizeof(dword)], f mov [hPtr+6*sizeof(dword)], g mov [hPtr+7*sizeof(dword)], h sub qword [rsp+_len], MBS_SM3 jne .main_loop REST_XMM REST_GPR ret ENDFUNC UpdateSM3 %endif ;; ((_IPP32E >= _IPP32E_U8 ) AND (_IPP32E < _IPP32E_E9 )) OR (_IPP32E == _IPP32E_N8 ) %endif ;; _ENABLE_ALG_SM3_ cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpvariant.inc000066400000000000000000000111161470420105600262200ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; Intel(R) Cryptography Primitives Library ; ; Purpose: ; Define ippCP variant ; ; do not changes in definitions below! ; ;; ;; modes of the feature ;; %assign _FEATURE_OFF_ 0 ;; feature is OFF %assign _FEATURE_ON_ 1 ;; feature is ON %assign _FEATURE_TICKTOCK_ 2 ;; detect is feature OFF/ON ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; %define _XMM7560_ 1 %ifdef _XMM7560_ %include "pcpvariant_xmm7560.inc" %endif ; %define _TXT_ACM_ 1 %ifdef _TXT_ACM_ %include "pcpvariant_txt_acm.inc" %endif ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; it possible to force use of C-version of some implementations ;; instead of ASM one ;; %ifndef _USE_C_cpAdd_BNU_ %assign _USE_C_cpAdd_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpSub_BNU_ %assign _USE_C_cpSub_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpInc_BNU_ %assign _USE_C_cpInc_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpAddMulDgt_BNU_ %assign _USE_C_cpAddMulDgt_BNU_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpMulAdc_BNU_school_ %assign _USE_C_cpMulAdc_BNU_school_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpSqrAdc_BNU_school_ %assign _USE_C_cpMulSqr_BNU_school_ _FEATURE_OFF_ %endif %ifndef _USE_C_cpMontRedAdc_BNU_ %assign _USE_C_cpMontRedAdc_BNU_ _FEATURE_OFF_ %endif ;; ;; set _AES_NI_ENABLING_ ;; %ifdef _IPP_AES_NI_ %if (_IPP_AES_NI_ == 0) %assign _AES_NI_ENABLING_ _FEATURE_OFF_ %elif (_IPP_AES_NI_ == 1) %assign _AES_NI_ENABLING_ _FEATURE_ON_ %else %error %endif %else %if (_IPP32E >= _IPP32E_Y8) %assign _AES_NI_ENABLING_ _FEATURE_TICKTOCK_ %else %assign _AES_NI_ENABLING_ _FEATURE_OFF_ %endif %endif ;; ;; if there is no outside assignment ;; set _SHA_NI_ENABLING_ based on CPU specification ;; %ifndef _SHA_NI_ENABLING_ %if (_IPP32E >= _IPP32E_Y8 ) %assign _SHA_NI_ENABLING_ _FEATURE_TICKTOCK_ %else %assign _SHA_NI_ENABLING_ _FEATURE_OFF_ %endif %endif ;; ;; set _ADCOX_NI_ENABLING_ ;; %ifdef _IPP_ADCX_NI_ %if (_IPP_ADCX_NI_ == 0) %assign _ADCOX_NI_ENABLING_ _FEATURE_OFF_ %elif (_IPP_ADCX_NI_ == 1) %assign _ADCOX_NI_ENABLING_ _FEATURE_ON_ %else %error %endif %else %if (_IPP32E >= _IPP32E_L9) %assign _ADCOX_NI_ENABLING_ _FEATURE_TICKTOCK_ %else %assign _ADCOX_NI_ENABLING_ _FEATURE_OFF_ %endif %endif ;; ;; select Hash algorithm ;; %ifndef _DISABLE_ALG_SHA1_ %assign _ENABLE_ALG_SHA1_ _FEATURE_ON_ ;; SHA1 on %else %assign _ENABLE_ALG_SHA1_ _FEATURE_OFF_ ;; SHA1 on %endif %ifndef _DISABLE_ALG_SHA256_ %assign _ENABLE_ALG_SHA256_ _FEATURE_ON_ ;; SHA256 on %else %assign _ENABLE_ALG_SHA256_ _FEATURE_OFF_ ;; SHA256 off %endif %ifndef _DISABLE_ALG_SHA521_ %assign _ENABLE_ALG_SHA512_ _FEATURE_ON_ ;; SHA512 on %else %assign _ENABLE_ALG_SHA512_ _FEATURE_OFF_ ;; SHA512 off %endif %ifndef _DISABLE_ALG_MD5_ %assign _ENABLE_ALG_MD5_ _FEATURE_ON_ ;; MD5 on %else %assign _ENABLE_ALG_MD5_ _FEATURE_OFF_ ;; MD5 off %endif %ifndef _DISABLE_ALG_SM3_ %assign _ENABLE_ALG_SM3_ _FEATURE_ON_ ;; SM3 on %else %assign _ENABLE_ALG_SM3_ _FEATURE_OFF_ ;; SM3 off %endif ;; ;; BN arithmetic ;; %assign _ENABLE_KARATSUBA_ _FEATURE_OFF_ ;; not use Karatsuba method for multiplication ;; ;; EC specific ;; %assign _ECP_IMPL_NONE_ 0 %assign _ECP_IMPL_ARBIRTRARY_ 1 %assign _ECP_IMPL_SPECIFIC_ 2 %assign _ECP_IMPL_MFM_ 3 %ifndef _ECP_128_ %assign _ECP_128_ _ECP_IMPL_SPECIFIC_ %endif %ifndef _ECP_192_ %assign _ECP_192_ _ECP_IMPL_MFM_ %endif %ifndef _ECP_224_ %assign _ECP_224_ _ECP_IMPL_MFM_ %endif %ifndef _ECP_256_ %assign _ECP_256_ _ECP_IMPL_MFM_ %endif %ifndef _ECP_384_ %assign _ECP_384_ _ECP_IMPL_MFM_ %endif %ifndef _ECP_521_ %assign _ECP_521_ _ECP_IMPL_MFM_ %endif %ifndef _ECP_SM2_ %assign _ECP_SM2_ _ECP_IMPL_MFM_ %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/pcpvariant_txt_acm.inc000066400000000000000000000021041470420105600277340ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2015 Intel Corporation ; ; 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. ;========================================================================= ; ; Intel(R) Cryptography Primitives Library ; ; Purpose: ; Update standard ippCP variant ; ; do not changes in definitions below! ; %ifdef _TXT_ACM_ ;; ;; HASH algs outside settings ;; %assign _SHA_NI_ENABLING_ _FEATURE_TICKTOCK_ ;; ;; select Hash algorithm ;; ; %assign _ENABLE_ALG_MD5_ _FEATURE_OFF_ %endif cryptography-primitives-1.0.0/sources/ippcp/asm_intel64/reg_sizes.inc000066400000000000000000000135111470420105600260440ustar00rootroot00000000000000;========================================================================= ; Copyright (C) 2020 Intel Corporation ; ; 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 d and w variants for registers %ifndef _REG_SIZES_ASM_ %define _REG_SIZES_ASM_ %define raxd eax %define raxw ax %define raxb al %define rbxd ebx %define rbxw bx %define rbxb bl %define rcxd ecx %define rcxw cx %define rcxb cl %define rdxd edx %define rdxw dx %define rdxb dl %define rsid esi %define rsiw si %define rsib sil %define rdid edi %define rdiw di %define rdib dil %define rbpd ebp %define rbpw bp %define rbpb bpl %define zmm0x xmm0 %define zmm1x xmm1 %define zmm2x xmm2 %define zmm3x xmm3 %define zmm4x xmm4 %define zmm5x xmm5 %define zmm6x xmm6 %define zmm7x xmm7 %define zmm8x xmm8 %define zmm9x xmm9 %define zmm10x xmm10 %define zmm11x xmm11 %define zmm12x xmm12 %define zmm13x xmm13 %define zmm14x xmm14 %define zmm15x xmm15 %define zmm16x xmm16 %define zmm17x xmm17 %define zmm18x xmm18 %define zmm19x xmm19 %define zmm20x xmm20 %define zmm21x xmm21 %define zmm22x xmm22 %define zmm23x xmm23 %define zmm24x xmm24 %define zmm25x xmm25 %define zmm26x xmm26 %define zmm27x xmm27 %define zmm28x xmm28 %define zmm29x xmm29 %define zmm30x xmm30 %define zmm31x xmm31 %define ymm0x xmm0 %define ymm1x xmm1 %define ymm2x xmm2 %define ymm3x xmm3 %define ymm4x xmm4 %define ymm5x xmm5 %define ymm6x xmm6 %define ymm7x xmm7 %define ymm8x xmm8 %define ymm9x xmm9 %define ymm10x xmm10 %define ymm11x xmm11 %define ymm12x xmm12 %define ymm13x xmm13 %define ymm14x xmm14 %define ymm15x xmm15 %define ymm16x xmm16 %define ymm17x xmm17 %define ymm18x xmm18 %define ymm19x xmm19 %define ymm20x xmm20 %define ymm21x xmm21 %define ymm22x xmm22 %define ymm23x xmm23 %define ymm24x xmm24 %define ymm25x xmm25 %define ymm26x xmm26 %define ymm27x xmm27 %define ymm28x xmm28 %define ymm29x xmm29 %define ymm30x xmm30 %define ymm31x xmm31 %define xmm0x xmm0 %define xmm1x xmm1 %define xmm2x xmm2 %define xmm3x xmm3 %define xmm4x xmm4 %define xmm5x xmm5 %define xmm6x xmm6 %define xmm7x xmm7 %define xmm8x xmm8 %define xmm9x xmm9 %define xmm10x xmm10 %define xmm11x xmm11 %define xmm12x xmm12 %define xmm13x xmm13 %define xmm14x xmm14 %define xmm15x xmm15 %define xmm16x xmm16 %define xmm17x xmm17 %define xmm18x xmm18 %define xmm19x xmm19 %define xmm20x xmm20 %define xmm21x xmm21 %define xmm22x xmm22 %define xmm23x xmm23 %define xmm24x xmm24 %define xmm25x xmm25 %define xmm26x xmm26 %define xmm27x xmm27 %define xmm28x xmm28 %define xmm29x xmm29 %define xmm30x xmm30 %define xmm31x xmm31 %define zmm0y ymm0 %define zmm1y ymm1 %define zmm2y ymm2 %define zmm3y ymm3 %define zmm4y ymm4 %define zmm5y ymm5 %define zmm6y ymm6 %define zmm7y ymm7 %define zmm8y ymm8 %define zmm9y ymm9 %define zmm10y ymm10 %define zmm11y ymm11 %define zmm12y ymm12 %define zmm13y ymm13 %define zmm14y ymm14 %define zmm15y ymm15 %define zmm16y ymm16 %define zmm17y ymm17 %define zmm18y ymm18 %define zmm19y ymm19 %define zmm20y ymm20 %define zmm21y ymm21 %define zmm22y ymm22 %define zmm23y ymm23 %define zmm24y ymm24 %define zmm25y ymm25 %define zmm26y ymm26 %define zmm27y ymm27 %define zmm28y ymm28 %define zmm29y ymm29 %define zmm30y ymm30 %define zmm31y ymm31 %define xmm0y ymm0 %define xmm1y ymm1 %define xmm2y ymm2 %define xmm3y ymm3 %define xmm4y ymm4 %define xmm5y ymm5 %define xmm6y ymm6 %define xmm7y ymm7 %define xmm8y ymm8 %define xmm9y ymm9 %define xmm10y ymm10 %define xmm11y ymm11 %define xmm12y ymm12 %define xmm13y ymm13 %define xmm14y ymm14 %define xmm15y ymm15 %define xmm16y ymm16 %define xmm17y ymm17 %define xmm18y ymm18 %define xmm19y ymm19 %define xmm20y ymm20 %define xmm21y ymm21 %define xmm22y ymm22 %define xmm23y ymm23 %define xmm24y ymm24 %define xmm25y ymm25 %define xmm26y ymm26 %define xmm27y ymm27 %define xmm28y ymm28 %define xmm29y ymm29 %define xmm30y ymm30 %define xmm31y ymm31 %define xmm0z zmm0 %define xmm1z zmm1 %define xmm2z zmm2 %define xmm3z zmm3 %define xmm4z zmm4 %define xmm5z zmm5 %define xmm6z zmm6 %define xmm7z zmm7 %define xmm8z zmm8 %define xmm9z zmm9 %define xmm10z zmm10 %define xmm11z zmm11 %define xmm12z zmm12 %define xmm13z zmm13 %define xmm14z zmm14 %define xmm15z zmm15 %define xmm16z zmm16 %define xmm17z zmm17 %define xmm18z zmm18 %define xmm19z zmm19 %define xmm20z zmm20 %define xmm21z zmm21 %define xmm22z zmm22 %define xmm23z zmm23 %define xmm24z zmm24 %define xmm25z zmm25 %define xmm26z zmm26 %define xmm27z zmm27 %define xmm28z zmm28 %define xmm29z zmm29 %define xmm30z zmm30 %define xmm31z zmm31 %define ymm0z zmm0 %define ymm1z zmm1 %define ymm2z zmm2 %define ymm3z zmm3 %define ymm4z zmm4 %define ymm5z zmm5 %define ymm6z zmm6 %define ymm7z zmm7 %define ymm8z zmm8 %define ymm9z zmm9 %define ymm10z zmm10 %define ymm11z zmm11 %define ymm12z zmm12 %define ymm13z zmm13 %define ymm14z zmm14 %define ymm15z zmm15 %define ymm16z zmm16 %define ymm17z zmm17 %define ymm18z zmm18 %define ymm19z zmm19 %define ymm20z zmm20 %define ymm21z zmm21 %define ymm22z zmm22 %define ymm23z zmm23 %define ymm24z zmm24 %define ymm25z zmm25 %define ymm26z zmm26 %define ymm27z zmm27 %define ymm28z zmm28 %define ymm29z zmm29 %define ymm30z zmm30 %define ymm31z zmm31 %define DWORD(reg) reg %+ d %define WORD(reg) reg %+ w %define BYTE(reg) reg %+ b %define XWORD(reg) reg %+ x %define YWORD(reg) reg %+ y %define ZWORD(reg) reg %+ z %endif ;; _REG_SIZES_ASM_ cryptography-primitives-1.0.0/sources/ippcp/cpinit.c000066400000000000000000000554171470420105600226770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2001 Intel Corporation * * 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. *************************************************************************/ // // Intel® Cryptography Primitives Library // #include "owndefs.h" #include "ippcpdefs.h" #include "ippcp.h" #include "dispatcher.h" #if defined( _IPP_DATA ) static Ipp64u cpFeatures = 0; static Ipp64u cpFeaturesMask = 0; static int cpGetFeatures( Ipp64u* pFeaturesMask ); extern IPP_OWN_DECL (void, cpGetReg, ( int* buf, int valEAX, int valECX )) extern IPP_OWN_DECL (int, cp_is_avx_extension, ( void )) extern IPP_OWN_DECL (int, cp_is_avx512_extension, ( void )) extern IPP_OWN_DECL (int, cp_issue_avx512_instruction, ( void )) IppStatus owncpSetCpuFeaturesAndIdx( Ipp64u cpuFeatures, int* index ); IPPFUN( Ipp64u, ippcpGetEnabledCpuFeatures, ( void )) { return cpFeaturesMask; } /*===================================================================*/ IPPFUN( IppStatus, ippcpGetCpuFeatures, ( Ipp64u* pFeaturesMask )) { IPP_BAD_PTR1_RET( pFeaturesMask ) { if( 0 != cpFeatures){ *pFeaturesMask = cpFeatures;// & cpFeaturesMask; } else { int ret = cpGetFeatures( pFeaturesMask ); if( !ret ) return ippStsNotSupportedCpu; } return ippStsNoErr; } } /*===================================================================*/ int cpGetFeature( Ipp64u Feature ) { // We provide users the ability to build their own custom build of 1cpu Intel® Cryptography Primitives Library // and turn CPU features on at compile-time if they are sure these features available on the target systems. #if (!defined(_MERGED_BLD) && defined(IPPCP_CUSTOM_BUILD)) int if_feature_enabled = ((IPP_CUSTOM_ENABLED_FEATURES & Feature) == Feature); return if_feature_enabled; #else if( 0 == cpFeaturesMask ) { Ipp64u loc_features; // set up cpFeaturesMask and cpFeatures for the proper work of tick-tok in 1cpu libraries ippcpGetCpuFeatures(&loc_features); } if((cpFeaturesMask & Feature) == Feature) { return 1; } else { return 0; } #endif } /*===================================================================*/ #define BIT00 0x00000001 #define BIT01 0x00000002 #define BIT02 0x00000004 #define BIT03 0x00000008 #define BIT04 0x00000010 #define BIT05 0x00000020 #define BIT06 0x00000040 #define BIT07 0x00000080 #define BIT08 0x00000100 #define BIT09 0x00000200 #define BIT10 0x00000400 #define BIT11 0x00000800 #define BIT12 0x00001000 #define BIT13 0x00002000 #define BIT14 0x00004000 #define BIT15 0x00008000 #define BIT16 0x00010000 #define BIT17 0x00020000 #define BIT18 0x00040000 #define BIT19 0x00080000 #define BIT20 0x00100000 #define BIT21 0x00200000 #define BIT22 0x00400000 #define BIT23 0x00800000 #define BIT24 0x01000000 #define BIT25 0x02000000 #define BIT26 0x04000000 #define BIT27 0x08000000 #define BIT28 0x10000000 #define BIT29 0x20000000 #define BIT30 0x40000000 #define BIT31 0x80000000 static int cpGetFeatures( Ipp64u* pFeaturesMask ) { Ipp32u buf[4]; Ipp32u eax_, ebx_, ecx_, edx_, tmp; Ipp64u mask; int flgFMA=0, flgINT=0, flgGPR=0; // for avx2 Ipp32u idBaseMax, idExtdMax; cpGetReg((int*)buf, 0, 0); //get max value for basic info. idBaseMax = buf[0]; cpGetReg((int*)buf, (Ipp32s)0x80000000, 0); //get max value for extended info. idExtdMax = buf[0]; cpGetReg( (int*)buf, 1, 0 ); eax_ = (Ipp32u)buf[0]; ecx_ = (Ipp32u)buf[2]; edx_ = (Ipp32u)buf[3]; mask = 0; if( edx_ & BIT23 ) mask |= ippCPUID_MMX; // edx[23] - MMX(TM) Technology if( edx_ & BIT25 ) mask |= ippCPUID_SSE; // edx[25] - Intel® Streaming SIMD Extensions (Intel® SSE) if( edx_ & BIT26 ) mask |= ippCPUID_SSE2; // edx[26] - Intel® Streaming SIMD Extensions 2 (Intel® SSE2) if( ecx_ & BIT00 ) mask |= ippCPUID_SSE3; // ecx[0] - Intel® Streaming SIMD Extensions 3 (Intel® SSE3) (formerly codenamed Prescott) if( ecx_ & BIT09 ) mask |= ippCPUID_SSSE3; // ecx[9] - Supplemental Streaming SIMD Extensions 3 (SSSE3) (formerly codenamed Merom) if( ecx_ & BIT22 ) mask |= ippCPUID_MOVBE; // ecx[22] - Intel® instruction MOVBE (Intel Atom® processor) if( ecx_ & BIT19 ) mask |= ippCPUID_SSE41; // ecx[19] - Intel® Streaming SIMD Extensions 4.1 (Intel® SSE4.1) (formerly codenamed Penryn) if( ecx_ & BIT20 ) mask |= ippCPUID_SSE42; // ecx[20] - Intel® Streaming SIMD Extensions 4.2 (Intel® SSE4.2) (formerly codenamed Nenalem) if( ecx_ & BIT28 ) mask |= ippCPUID_AVX; // ecx[28] - Intel® Advanced Vector Extensions (Intel® AVX) (formerly codenamed Sandy Bridge) if(( ecx_ & 0x18000000 ) == 0x18000000 ){ tmp = (Ipp32u)cp_is_avx_extension(); if( tmp & BIT00 ) mask |= ippAVX_ENABLEDBYOS; // Intel® AVX is supported by OS } if( ecx_ & BIT25 ) mask |= ippCPUID_AES; // ecx[25] - Intel® AES New Instructions if( ecx_ & BIT01 ) mask |= ippCPUID_CLMUL; // ecx[1] - Intel® instruction PCLMULQDQ if( ecx_ & BIT30 ) mask |= ippCPUID_RDRAND; // ecx[30] - Intel® instruction RDRRAND if( ecx_ & BIT29 ) mask |= ippCPUID_F16C; // ecx[29] - Intel® instruction F16C // Intel® AVX2 instructions extension: only if 3 features are enabled at once: // FMA, Intel® AVX 256 int & GPR BMI (bit-manipulation); if( ecx_ & BIT12 ) flgFMA = 1; else flgFMA = 0; // ecx[12] - FMA 128 & 256 bit if( idBaseMax >= 7 ){ // get CPUID.eax = 7 cpGetReg( (int*)buf, 0x7, 0 ); ebx_ = (Ipp32u)buf[1]; ecx_ = (Ipp32u)buf[2]; edx_ = (Ipp32u)buf[3]; if( ebx_ & BIT05 ) flgINT = 1; else flgINT = 0; //ebx[5], Intel® Advanced Vector Extensions 2 (Intel® AVX2) (int 256bits) // ebx[3] - enabled ANDN, BEXTR, BLSI, BLSMK, BLSR, TZCNT // ebx[8] - enabled BZHI, MULX, PDEP, PEXT, RORX, SARX, SHLX, SHRX if(( ebx_ & BIT03 )&&( ebx_ & BIT08 )) flgGPR = 1; else flgGPR = 0; // VEX-encoded GPR instructions (GPR BMI) // Intel® architecture formerly codenamed Broadwell instructions extension if( ebx_ & BIT19 ) mask |= ippCPUID_ADCOX; // eax[0x7] -->> ebx:: Bit 19: Intel® instructions ADOX/ADCX if( ebx_ & BIT18 ) mask |= ippCPUID_RDSEED; // eax[0x7] -->> ebx:: Bit 18: Intel® instruction RDSEED if( ebx_ & BIT29 ) mask |= ippCPUID_SHA; // eax[0x7] -->> ebx:: Bit 29: Intel® Secure Hash Algorithm Extensions if( ecx_ & BIT09 ) mask |= ippCPUID_AVX2VAES; // ecx[09] - Intel® Vector AES instruction set if( ecx_ & BIT10 ) mask |= ippCPUID_AVX2VCLMUL; // ecx[10] - Intel® instruction VPCLMULQDQ // Intel® Advanced Vector Extensions 512 (Intel® AVX-512) extension if( ebx_ & BIT16 ) mask |= ippCPUID_AVX512F; // ebx[16] - Intel® AVX-512 Foundation if( ebx_ & BIT26 ) mask |= ippCPUID_AVX512PF; // ebx[26] - Intel® AVX-512 Pre Fetch Instructions (PFI) if( ebx_ & BIT27 ) mask |= ippCPUID_AVX512ER; // ebx[27] - Intel® AVX-512 Exponential and Reciprocal Instructions (ERI) if( ebx_ & BIT28 ) mask |= ippCPUID_AVX512CD; // ebx[28] - Intel® AVX-512 Conflict Detection if( ebx_ & BIT17 ) mask |= ippCPUID_AVX512DQ; // ebx[17] - Intel® AVX-512 Dword & Quadword if( ebx_ & BIT30 ) mask |= ippCPUID_AVX512BW; // ebx[30] - Intel® AVX-512 Byte & Word if( ebx_ & BIT31 ) mask |= ippCPUID_AVX512VL; // ebx[31] - Intel® AVX-512 Vector Length Extensions (VLE) if( ecx_ & BIT01 ) mask |= ippCPUID_AVX512VBMI; // ecx[01] - Intel® AVX-512 Vector Bit Manipulation Instructions if( ecx_ & BIT06 ) mask |= ippCPUID_AVX512VBMI2; // ecx[06] - Intel® AVX-512 Vector Bit Manipulation Instructions 2 if( edx_ & BIT02 ) mask |= ippCPUID_AVX512_4VNNIW; // edx[02] - Intel® AVX-512 Vector instructions for deep learning enhanced word variable precision if( edx_ & BIT03 ) mask |= ippCPUID_AVX512_4FMADDPS; // edx[03] - Intel® AVX-512 Vector instructions for deep learning floating-point single precision // bitwise OR between ippCPUID_MPX & ippCPUID_AVX flags can be used to define that arch is GE than formerly codenamed Skylake if( ebx_ & BIT14 ) mask |= ippCPUID_MPX; // ebx[14] - Intel® Memory Protection Extensions (Intel® MPX) if( ebx_ & BIT21 ) mask |= ippCPUID_AVX512IFMA; // ebx[21] - Intel® AVX-512 IFMA PMADD52 if (ecx_ & BIT08) mask |= ippCPUID_AVX512GFNI; // test bit ecx[08] if (ecx_ & BIT09) mask |= ippCPUID_AVX512VAES; // test bit ecx[09] if (ecx_ & BIT10) mask |= ippCPUID_AVX512VCLMUL; // test bit ecx[10] cpGetReg( (int*)buf, 0x7, 1 ); // Intel® SMX-NI and Intel® SHA512-NI Instructions set check eax_ = (Ipp32u)buf[0]; if (eax_ & BIT00) mask |= ippCPUID_AVX2SHA512; // test bit eax[00] if (eax_ & BIT01) mask |= ippCPUID_AVX2SM3; // test bit eax[01] if (eax_ & BIT02) mask |= ippCPUID_AVX2SM4; // test bit eax[02] if (mask & ippCPUID_AVX512F) { /* test if Intel® AVX-512 is supported by OS */ if (cp_is_avx512_extension()) mask |= ippAVX512_ENABLEDBYOS; #if defined(OSXEM64T) else { /* submit some avx512f instructions, returns 0 */ mask |= cp_issue_avx512_instruction(); /* and check OS support again */ if (cp_is_avx512_extension()) mask |= ippAVX512_ENABLEDBYOS; } #endif } } mask = ( flgFMA && flgINT && flgGPR ) ? (mask | ippCPUID_AVX2) : mask; // to separate Intel® AVX2 flags here if( idExtdMax >= 0x80000001 ){ // get CPUID.eax=0x80000001 cpGetReg( (int*)buf, (Ipp32s)0x80000001, 0 ); ecx_ = (Ipp32u)buf[2]; // Intel® architecture formerly codenamed Broadwell instructions extension if( ecx_ & BIT08 ) mask |= ippCPUID_PREFETCHW; // eax[0x80000001] -->> ecx:: Bit 8: Intel® instruction PREFETCHW } // Intel® architecture formerly codenamed Knights Corner if(((( eax_ << 20 ) >> 24 ) ^ 0xb1 ) == 0 ){ mask = mask | ippCPUID_KNC; } cpFeatures = mask; cpFeaturesMask = mask; /* all CPU features are enabled by default */ *pFeaturesMask = cpFeatures; return 1; /* if somebody need to check for cpuid support - do it at the top of function and return 0 if it's not supported */ } int ippcpJumpIndexForMergedLibs = -1; static int cpthreads_omp_of_n_ipp = 1; IPPFUN( int, ippcpGetEnabledNumThreads,( void )) { return cpthreads_omp_of_n_ipp; } #define AVX3X_FEATURES ( ippCPUID_AVX512F|ippCPUID_AVX512CD|ippCPUID_AVX512VL|ippCPUID_AVX512BW|ippCPUID_AVX512DQ ) #define AVX3M_FEATURES ( ippCPUID_AVX512F|ippCPUID_AVX512CD|ippCPUID_AVX512PF|ippCPUID_AVX512ER ) // AVX3X_FEATURES means Intel® Xeon® processor // AVX3M_FEATURES means Intel® Many Integrated Core Architecture #define AVX3I_FEATURES ( AVX3X_FEATURES| \ ippCPUID_SHA|ippCPUID_AVX512VBMI|ippCPUID_AVX512VBMI2| \ ippCPUID_AVX512IFMA| \ ippCPUID_AVX512GFNI|ippCPUID_AVX512VAES|ippCPUID_AVX512VCLMUL) IppStatus owncpFeaturesToIdx( Ipp64u* cpuFeatures, int* index ) { IppStatus ownStatus = ippStsNoErr; Ipp64u mask = 0; *index = 0; if(( AVX3I_FEATURES == ( *cpuFeatures & AVX3I_FEATURES ))&& ( ippAVX512_ENABLEDBYOS & cpFeatures )){ /* Intel® architecture formerly codenamed Icelake ia32=S0, x64=K0 */ mask = AVX3I_MSK; *index = LIB_AVX3I; } else if(( AVX3X_FEATURES == ( *cpuFeatures & AVX3X_FEATURES ))&& ( ippAVX512_ENABLEDBYOS & cpFeatures )){ /* Intel® architecture formerly codenamed Skylake ia32=S0, x64=K0 */ mask = AVX3X_MSK; *index = LIB_AVX3X; } else if(( AVX3M_FEATURES == ( *cpuFeatures & AVX3M_FEATURES ))&& ( ippAVX512_ENABLEDBYOS & cpFeatures )){ /* Intel® architecture formerly codenamed Knights Landing ia32=i0, x64=L9 (N0 is no longer supported) */ mask = AVX3M_MSK; *index = LIB_AVX3M; } else if(( ippCPUID_AVX2 == ( *cpuFeatures & ippCPUID_AVX2 ))&& ( ippAVX_ENABLEDBYOS & cpFeatures )){ /* Intel® architecture formerly codenamed Haswell ia32=H9, x64=L9 */ mask = AVX2_MSK; *index = LIB_AVX2; } else /* Note: AVX code path is removed, SSE42 code path is used instead // Intel® architecture formerly codenamed Sandy Bridge ia32=G9, x64=E9 if(( ippCPUID_AVX == ( *cpuFeatures & ippCPUID_AVX ))&& ( ippAVX_ENABLEDBYOS & cpFeatures )){ mask = AVX_MSK; *index = LIB_AVX; } else */ /* Intel® microarchitecture code name Nehalem or Intel® architecture formerly codenamed Westmer = Intel® architecture formerly codenamed Penryn + Intel® SSE4.2 + ?Intel® instruction PCLMULQDQ + ?(Intel® AES New Instructions) + ?(Intel® Secure Hash Algorithm Extensions) or new Intel Atom® processor formerly codenamed Silvermont */ if( ippCPUID_SSE42 == ( *cpuFeatures & ippCPUID_SSE42 ) || ippCPUID_AVX == ( *cpuFeatures & ippCPUID_AVX )){ mask = SSE42_MSK; *index = LIB_SSE42; } else /* Note: SSSE3 code path is removed, SSE3 code path is used instead // Intel Atom® processor formerly codenamed Silverthorne ia32=S8, x64=N8 if( ippCPUID_SSE41 == ( *cpuFeatures & ippCPUID_SSE41 )){ mask = SSE41_MSK; *index = LIB_SSE41; } else // Intel Atom® processor formerly codenamed Silverthorne ia32=S8, x64=N8 if( ippCPUID_MOVBE == ( *cpuFeatures & ippCPUID_MOVBE )) { mask = ATOM_MSK; *index = LIB_ATOM; } else // Intel® architecture formerly codenamed Merom ia32=V8, x64=U8 (letters etymology is unknown) if( ippCPUID_SSSE3 == ( *cpuFeatures & ippCPUID_SSSE3 )) { mask = SSSE3_MSK; *index = LIB_SSSE3; } else */ /* Intel® architecture formerly codenamed Prescott ia32=W7, x64=M7 */ if( (ippCPUID_SSE3 == ( *cpuFeatures & ippCPUID_SSE3 )) || (ippCPUID_MOVBE == ( *cpuFeatures & ippCPUID_MOVBE )) || (ippCPUID_SSSE3 == ( *cpuFeatures & ippCPUID_SSSE3 )) || (ippCPUID_SSE41 == ( *cpuFeatures & ippCPUID_SSE41 ))) { mask = SSE3_MSK; *index = LIB_SSE3; } else /* Intel® architecture formerly codenamed Willamette ia32=W7, x64=PX */ if( ippCPUID_SSE2 == ( *cpuFeatures & ippCPUID_SSE2 )) { mask = SSE2_MSK; *index = LIB_SSE2; } else /* Intel® Pentium® processor III ia32=PX only */ if( ippCPUID_SSE == ( *cpuFeatures & ippCPUID_SSE )) { mask = SSE_MSK; *index = LIB_SSE; #if (defined( WIN32E ) || defined( LINUX32E ) || defined( OSXEM64T )) && !(defined( _ARCH_LRB2 )) ownStatus = ippStsNotSupportedCpu; /* the lowest CPU supported by Intel Cryptography Primitives Library must at least support Intel® SSE2 for x64 */ #endif } else /* not supported, PX dispatched */ { mask = MMX_MSK; *index = LIB_MMX; ownStatus = ippStsNotSupportedCpu; /* the lowest CPU supported by Intel Cryptography Primitives Library must at least support Intel® SSE for ia32 or Intel® SSE2 for x64 */ } if(( mask != ( *cpuFeatures & mask ))&&( ownStatus == ippStsNoErr )) ownStatus = ippStsFeaturesCombination; /* warning if combination of features is incomplete */ *cpuFeatures |= mask; return ownStatus; } IPPFUN(IppStatus, ippcpSetNumThreads, (int numThr)) { IppStatus status = ippStsNoErr; IPP_UNREFERENCED_PARAMETER(numThr); status = ippStsNoOperation; return status; } IPPFUN(IppStatus, ippcpGetNumThreads, (int* pNumThr)) { IppStatus status = ippStsNoErr; IPP_BAD_PTR1_RET(pNumThr) *pNumThr = 1; status = ippStsNoOperation; return status; } IPPFUN( IppStatus, ippcpInit,( void )) { Ipp64u cpuFeatures; ippcpGetCpuFeatures( &cpuFeatures ); return ippcpSetCpuFeatures( cpuFeatures ); } IPPFUN( IppStatus, ippcpSetCpuFeatures,( Ipp64u cpuFeatures )) { IppStatus ownStatus; int index = 0; ownStatus = owncpSetCpuFeaturesAndIdx( cpuFeatures, &index ); ippcpJumpIndexForMergedLibs = index; cpFeaturesMask = cpuFeatures; return ownStatus; } IppStatus owncpSetCpuFeaturesAndIdx(Ipp64u cpuFeatures, int* index) { Ipp64u tmp; IppStatus tmpStatus; *index = 0; if (ippCPUID_NOCHECK & cpuFeatures) { // if NOCHECK is set - static variable cpFeatures is initialized unconditionally and real CPU features from CPUID are ignored; // the one who uses this method of initialization must understand what and why it does and the possible unpredictable consequences. // the only one known purpose for this approach - environments where CPUID instruction is disabled (for example Intel® Software Guard Extensions). cpuFeatures &= (IPP_MAX_64U ^ ippCPUID_NOCHECK); cpFeatures = cpuFeatures; } else /* read cpu features unconditionally */ cpGetFeatures(&tmp); tmpStatus = owncpFeaturesToIdx(&cpuFeatures, index); cpFeaturesMask = cpuFeatures; return tmpStatus; } static struct { int sts; const char *msg; } ippcpMsg[] = { /* ippStatus */ /* -9999 */ {ippStsCpuNotSupportedErr, "ippStsCpuNotSupportedErr: The target CPU is not supported"}, /* -9702 */ {MSG_NO_SHARED, "No shared libraries were found in the Waterfall procedure"}, /* -9701 */ {MSG_NO_DLL, "No DLLs were found in the Waterfall procedure"}, /* -9700 */ {MSG_LOAD_DLL_ERR, "Error at loading of %s library"}, /* -1017 */ {ippStsInvalidPoint, "ippStsInvalidPoint ECC: Invalid point (out of EC)"}, /* -1016 */ {ippStsQuadraticNonResidueErr, "ippStsQuadraticNonResidueErr: SQRT operation on quadratic non-residue value"}, /* -1015 */ {ippStsPointAtInfinity, "ippStsPointAtInfinity: Point at infinity is detected"}, /* -1014 */ {ippStsOFBSizeErr, "ippStsOFBSizeErr: Incorrect value for cryptography OFB block size"}, /* -1013 */ {ippStsIncompleteContextErr, "ippStsIncompleteContextErr: Set up of context is not complete"}, /* -1012 */ {ippStsCTRSizeErr, "ippStsCTRSizeErr: Incorrect value for cryptography CTR block size"}, /* -1011 */ {ippStsEphemeralKeyErr, "ippStsEphemeralKeyErr: ECC: Invalid ephemeral key"}, /* -1010 */ {ippStsMessageErr, "ippStsMessageErr: ECC: Invalid message digest"}, /* -1009 */ {ippStsShareKeyErr, "ippStsShareKeyErr: ECC: Invalid share key"}, /* -1008 */ {ippStsInvalidPrivateKey, "ippStsInvalidPrivateKey ECC: Invalid private key"}, /* -1007 */ {ippStsOutOfECErr, "ippStsOutOfECErr: ECC: Point out of EC"}, /* -1006 */ {ippStsECCInvalidFlagErr, "ippStsECCInvalidFlagErr: ECC: Invalid Flag"}, /* -1005 */ {ippStsUnderRunErr, "ippStsUnderRunErr: Error in data under run"}, /* -1004 */ {ippStsPaddingErr, "ippStsPaddingErr: Detected padding error indicates the possible data corruption"}, /* -1003 */ {ippStsCFBSizeErr, "ippStsCFBSizeErr: Incorrect value for cryptography CFB block size"}, /* -1002 */ {ippStsPaddingSchemeErr, "ippStsPaddingSchemeErr: Invalid padding scheme"}, /* -1001 */ {ippStsBadModulusErr, "ippStsBadModulusErr: Bad modulus caused a failure in module inversion"}, /* -216 */ {ippStsUnknownStatusCodeErr, "ippStsUnknownStatusCodeErr: Unknown status code"}, /* -221 */ {ippStsLoadDynErr, "ippStsLoadDynErr: Error when loading the dynamic library"}, /* -15 */ {ippStsLengthErr, "ippStsLengthErr: Incorrect value for string length"}, /* -14 */ {ippStsNotSupportedModeErr, "ippStsNotSupportedModeErr: The requested mode is currently not supported"}, /* -13 */ {ippStsContextMatchErr, "ippStsContextMatchErr: Context parameter does not match the operation"}, /* -12 */ {ippStsScaleRangeErr, "ippStsScaleRangeErr: Scale bounds are out of range"}, /* -11 */ {ippStsOutOfRangeErr, "ippStsOutOfRangeErr: Argument is out of range, or point is outside the image"}, /* -10 */ {ippStsDivByZeroErr, "ippStsDivByZeroErr: An attempt to divide by zero"}, /* -9 */ {ippStsMemAllocErr, "ippStsMemAllocErr: Memory allocated for the operation is not enough"}, /* -8 */ {ippStsNullPtrErr, "ippStsNullPtrErr: Null pointer error"}, /* -7 */ {ippStsRangeErr, "ippStsRangeErr: Incorrect values for bounds: the lower bound is greater than the upper bound"}, /* -6 */ {ippStsSizeErr, "ippStsSizeErr: Incorrect value for data size"}, /* -5 */ {ippStsBadArgErr, "ippStsBadArgErr: Incorrect arg/param of the function"}, /* -4 */ {ippStsNoMemErr, "ippStsNoMemErr: Not enough memory for the operation"}, /* -2 */ {ippStsErr, "ippStsErr: Unknown/unspecified error, -2"}, /* 0 */ {ippStsNoErr, "ippStsNoErr: No errors"}, /* 1 */ {ippStsNoOperation, "ippStsNoOperation: No operation has been executed"}, /* 2 */ {ippStsDivByZero, "ippStsDivByZero: Zero value(s) for the divisor in the Div function"}, /* 25 */ {ippStsInsufficientEntropy, "ippStsInsufficientEntropy: Generation of the prime/key failed due to insufficient entropy in the random seed and stimulus bit string"}, /* 36 */ {ippStsNotSupportedCpu, "The CPU is not supported"}, /* 51 */ {ippStsFeaturesCombination, "Wrong combination of features"}, /* 53 */ {ippStsMbWarning, "ippStsMbWarning: Error(s) in statuses array"}, }; /* ///////////////////////////////////////////////////////////////////////////// // Name: ippcpGetStatusString // Purpose: transformation of a code of a status Intel Cryptography Primitives Library to string // Returns: // Parameters: // StsCode Intel Cryptography Primitives Library status code // // Notes: not necessary to release the returned string */ IPPFUN( const char*, ippcpGetStatusString, ( IppStatus StsCode ) ) { unsigned int i; for( i=0; i= 13.0.0, CLANG >= 16.0.0, Intel ICX >= 2025.0.0 or MSVC >= 17.7 is required") else() message(STATUS "Intel® AVX-IFMA .............................. off, compiler version GCC >= 13.0.0, CLANG >= 16.0.0, Intel ICX >= 2024.2.0 or MSVC >= 17.7 is required") endif() endif() if(MB_STANDALONE) foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} ) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/bin") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/bin") endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") set(INTERNAL_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/autogen_1cpu") else() # Make variables below accessible in parent CMakeLists.txt set(MBX_INTERFACE_VERSION ${MBX_INTERFACE_VERSION} PARENT_SCOPE) set(MB_PUBLIC_HEADERS ${MB_PUBLIC_HEADERS} PARENT_SCOPE) set(MB_DYN_LIB_TARGET "${MB_DYN_LIB_TARGET}" PARENT_SCOPE) set(MB_STATIC_LIB_TARGET "${MB_STATIC_LIB_TARGET}" PARENT_SCOPE) endif() if(MB_STANDALONE) find_package(Python REQUIRED) if(Python_Interpreter_FOUND) message (STATUS "PYTHON_VERSION_STRING ................. " ${Python_VERSION}) else() message (STATUS "PYTHON_VERSION_STRING ................. Python not found" ) endif() if(NOT CMAKE_OUTPUT_DIR) set(CMAKE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/.build") endif() endif() if(BORINGSSL OR BABASSL OR TONGSUO) # off by default # BoringSSL doesn't appear to have version information found # Tongsuo has own versioning # by find_package(OpenSSL) find_package(OpenSSL REQUIRED) else() find_package(OpenSSL 3.0.8 REQUIRED) # set -DOPENSSL_INCLUDE_DIR= -DOPENSSL_LIBRARIES= -DOPENSSL_ROOT_DIR= to use patched endif() if(BABASSL) # off by default message(WARNING "-DBABASSL:BOOL=on flag is deprecated and targeted to be removed in the future releases. Please use -DTONGSUO:BOOL=on instead.") endif() if(BN_OPENSSL_PATCH) # Link static OpenSSL only for patched version set(OPENSSL_USE_STATIC_LIBS TRUE) endif() include_directories( ${CRYPTO_MB_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${INTERNAL_INCLUDE_DIR} ${INTERNAL_INCLUDE_DIR}/single_cpu/crypto_mb $<$:$ENV{ROOT}/compiler/include $ENV{ROOT}/compiler/include/icc> $<$>:${CMAKE_SYSTEM_INCLUDE_PATH}> $<$,$>:$ENV{INCLUDE}> ) add_subdirectory(src) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/Readme.md000066400000000000000000000157431470420105600247600ustar00rootroot00000000000000# Crypto Multi-buffer Library Currently, the library provides optimized version of the following algorithms: 1. RSA, ECDSA, ECDH, x25519, SM2 multi-buffer algorithms based on Intel® Advanced Vector Extensions 512 (Intel® AVX-512) integer fused multiply-add (IFMA) operations. This CPU feature is introduced with Intel® Microarchitecture Code Named Ice Lake. 2. SM4 based on Intel(R) Advanced Vector Extensions 512 (Intel(R) AVX-512) GFNI instructions. 3. SM3 based on Intel® Advanced Vector Extensions 512 (Intel® AVX-512) instructions. ## Multiple Buffers Processing Overview Some of the cryptography algorithms cannot be parallelized due to their specificity. For example, the RSA algorithm consists of big-number (multi-digit) arithmetic: multi-precision modular multiplications and squaring operations. Digits of multi-digit numbers are dependent because of carry propagation during arithmetic operations. Therefore, single RSA computation based on general purpose mul/adc instructions is not efficient. The way to get high-performance implementations of such cryptographic algorithms is a parallel processing using *single instruction, multiple data* (SIMD) architecture. The usage model implies presence of several independent and homogeneous (encryption or decryption) requests for RSA operations, using of SIMD leads to performance improvement. Multi-buffer processing collects up to eight RSA operations. Each request is computed independently from the others, so it is possible to process several packets at the same time. This library consists of highly-optimized kernels taking advantage of Intel’s multi-buffer processing and Intel® AVX-512 instruction set. ## Software Requirements ### Common tools - CMake\* 3.18 or higher - The Netwide Assembler (NASM) 2.16.02\* - OpenSSL\* 3.0.8 or higher **OR** BoringSSL* [45cf810d](https://github.com/google/boringssl/archive/45cf810dbdbd767f09f8cb0b0fcccd342c39041f.tar.gz) **OR** Tongsuo* 8.3.3 ### Linux* OS - [Common tools](#common-tools) - Intel® oneAPI DPC++/C++ Compiler latest for Linux\* OS - GCC 8.5 - GCC 11.4 - GCC 14.1 - Clang 9.0 - Clang 12.0 - Clang 16.0 - GNU binutils 2.32 > **NOTE:** [CMake\*](https://cmake.org/download) 3.22 or higher is required to build using Intel® oneAPI DPC++/C++ Compiler. > **NOTE:** GNU binutils 2.40 are required to build Intel® AVX-IFMA RSA optimization with GCC compiler. ### Windows* OS - [Common tools](#common-tools) - Intel® oneAPI DPC++/C++ Compiler latest for Windows\* OS - Microsoft Visual C++ Compiler\* version 19.29 provided by Microsoft Visual Studio\* 2019 version 16.11 - Microsoft Visual C++ Compiler\* version 19.30 provided by Microsoft Visual Studio\* 2022 version 17.11 > **NOTE:** [CMake\*](https://cmake.org/download) 3.21 or higher is required to build using Microsoft Visual Studio\* 2022. > **NOTE:** [CMake\*](https://cmake.org/download) 3.22 or higher is required to build using Intel® oneAPI DPC++/C++ Compiler. ### macOS* - [Common tools](#common-tools) - Intel® C++ Compiler Classic 2021.9 for macOS\* ## Installation You can install the Crypto Multi-buffer library in two different ways: 1. Installation to the default directories. > **Note**: To run this installation type, you need to have appropriate permissions to write to the installation directory. Default locations (default values of `CMAKE_INSTALL_PREFIX`): - Unix: /usr/local - Windows: C:\Program Files\crypto_mb or C:\Program Files (x86)\crypto_mb To begin installation, run the command below in the project folder that was specified with `-B`: ``` bash make install ``` > **Note**: Installation requires write permissions to the build directory to create the installation manifest file. If it is not feasible in your setup, copy the build to the local directory and change permissions accordingly. 2. Installation to your own directory. If you want to install the library not by default paths, specify the `CMAKE_INSTALL_PREFIX` variable at the configuration step, for example: ``` bash cmake . -B"../build" -DCMAKE_INSTALL_PREFIX=path/to/libcrypto_mb/installation ``` You can find the installed files in: ``` bash ├── ${CMAKE_INSTALL_PREFIX}    ├── include | └── crypto_mb | ├── cpu_features.h    │   ├── defs.h    │   ├── ec_nistp256.h    │   ├── ec_nistp384.h    │   ├── ec_nistp521.h    │   ├── ec_sm2.h    │   ├── ed25519.h    │   ├── exp.h    │   ├── fips_cert.h    │   ├── rsa.h    │   ├── sm3.h    │   ├── sm4.h    │   ├── sm4_ccm.h    │   ├── sm4_gcm.h    │   ├── status.h | ├── version.h    │   └── x25519.h    └── lib └── libcrypto_mb.so ``` > **Note**: This project uses the default `RPATH` settings: > > CMake is linking the executables and shared libraries with full `RPATH` to all used > libraries in the build tree. When installing, CMake will clear the `RPATH` of these > targets so they are installed with an empty `RPATH`. > In this case to resolve the Crypto Multi-buffer Library dependency on OpenSSL it is > necessary to update `LD_LIBRARY_PATH` with the path to the target OpenSSL library. ## How to Build 1. Clone the repository from GitHub\* as follows: ``` bash git clone --recursive https://github.com/intel/ipp-crypto ``` and navigate to the `sources/ippcp/crypto_mb` folder. 2. Set the environment variables for one of the supported C/C++ compilers. *example for Intel® oneAPI DPC++/C++ Compiler:* ```bash source /opt/intel/oneapi/setvars.sh intel64 ``` For details, refer to the [Intel® oneAPI DPC++/C++ Compiler Developer Guide and Reference](https://www.intel.com/content/www/us/en/docs/dpcpp-cpp-compiler/developer-guide-reference/current/specifying-the-location-of-compiler-components.html). 3. Run CMake on the command line. Use `-B` to specify path to the resulting project. ``` bash CC=icx CXX=icpx cmake CMakeLists.txt -B_build -DARCH=intel64 ``` 4. Go to the project folder that was specified with `-B` and run `make` to build the library (`crypto_mb` target). ### Building with Intel® Cryptography Primitives Library The Crypto Multi-buffer library will be built automatically with Intel® Cryptography Primitives Library if optimization for Intel® Microarchitecture Code Named Ice Lake is available. For more information see [Intel Cryptography Primitives Library Build Instructions](../../../BUILD.md) ### CMake Build Options - Use `OPENSSL_INCLUDE_DIR`, `OPENSSL_LIBRARIES` and `OPENSSL_ROOT_DIR` to override path to OpenSSL\*: ``` bash cmake . -B"../build" -DOPENSSL_INCLUDE_DIR=/path/to/openssl/include -DOPENSSL_LIBRARIES=/path/to/openssl/lib -DOPENSSL_ROOT_DIR=/path/to/openssl/installation/dir ``` - Set `-DOPENSSL_USE_STATIC_LIBS=TRUE` if static OpenSSL libraries are preferred. cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/dispatcher/000077500000000000000000000000001470420105600253555ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/dispatcher/gen_disp_common_crypto_mb.py000066400000000000000000000052601470420105600331500ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2024 Intel Corporation # # 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. #========================================================================= # # Crypto_MB APIs parser. Parses strings such as: MBXAPI( type,name,arg ) # import re import sys import os import hashlib def readNextFunction(header, curLine, headerID): ## read next function with arguments ## find header ID macros FunName = '' FunArg = '' FunType = '' FunArgCall = '' success = False while (curLine < len(header) and success == False): if not headerID and re.match( '\s*#\s*if\s*!\s*defined\s*\(\s*__IPP', header[curLine]): headerID= re.sub( '.*__IPP', '__IPP', header[curLine] ) headerID= re.sub( "\)", '', headerID) headerID= re.sub( '[\n\s]', '', headerID ) if re.match( '^\s*MBXAPI\s*\(.*', header[curLine] ) : FunStr= header[curLine] FunStr= re.sub('\n','',FunStr) ## remove EOL symbols while not re.match('.*\)\s*\)\s*$', FunStr): ## concatenate string if string is not completed curLine= curLine+1 FunStr= FunStr+header[curLine] FunStr= re.sub('\n','',FunStr) ## remove EOL symbols FunStr= re.sub('\s+', ' ', FunStr) s= FunStr.split(',') ## Extract function name FunName= s[1] FunName= re.sub('\s', '', FunName) ## Extract function type FunType= re.sub( '.*\(', '', s[0] ) ## Extract function arguments FunArg= re.sub('.*\(.*,.+,\s*\(', '(', FunStr) FunArg= re.sub('\)\s*\)', ')', FunArg) ## Extract function arguments for call s= FunArg.split(',') for i in s: l= i.split(' ') FunArgCall+= l[-1] + ', ' FunArgCall= re.sub('\[\w*\]', '', FunArgCall) FunArgCall= re.sub('\*', '', FunArgCall) FunArgCall= FunArgCall[:-2] FunArgCall= '(' + FunArgCall if (FunArg == '(void)'): FunArg= '()' FunArgCall= '()' success = True curLine = curLine + 1 return {'curLine':curLine, 'FunType':FunType, 'FunName':FunName, 'FunArg':FunArg, 'FunArgCall':FunArgCall, 'success':success } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/dispatcher/gen_disp_crypto_mb.py000066400000000000000000000071331470420105600316010ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2024 Intel Corporation # # 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. #========================================================================= # # Generates jmp_ files necessary for the dispatcher # import re import sys import os import hashlib import argparse parser = argparse.ArgumentParser() parser.add_argument('-i', '--header', action='store', required=True, help='Crypto Multi-buffer Library dispatcher will be generated for functions in Header') parser.add_argument('-o', '--out-directory', action='store', required=True, help='Output folder for generated files') parser.add_argument('-l', '--cpu-list', action='store', required=True, help='Actual CPU list: semicolon separated string') parser.add_argument('-c', '--compiler', action='store', required=True, help='Compiler') args = parser.parse_args() Header = args.header OutDir = args.out_directory cpulist = args.cpu_list.split(';') compiler = args.compiler headerID= False ## Header ID define to avoid multiple include like: #if !defined( __IPPCP_H__ ) from gen_disp_common_crypto_mb import readNextFunction HDR= open( Header, 'r' ) h= HDR.readlines() HDR.close() ## keep filename only (incdir, Header)= os.path.split(Header) ## original header name to declare external functions as internal for dispatcher OrgH= Header isFunctionFound = True curLine = 0 FunType = "" FunName = "" FunArg = "" while (isFunctionFound == True): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunType = result['FunType'] FunName = result['FunName'] FunArg = result['FunArg'] FunArgCall = result['FunArgCall'] isFunctionFound = result['success'] if (isFunctionFound == True): ################################################## ## create dispatcher C file ################################################## DISP= open( os.sep.join([OutDir, "jmp_"+FunName+"_" + hashlib.sha512(FunName.encode('utf-8')).hexdigest()[:8] + ".c"]), 'w' ) DISP.write(f"#include \n\n") DISP.write(f"#include \n\n") DISP.write(f"typedef {FunType} (*MBX_FUNC_PTR){FunArg};\n\n") DISP.write(f"static int {FunName}_index = -1;\n") DISP.write(f"static int *p_{FunName}_index = &{FunName}_index;\n\n") DISP.write(f"extern int* _mbx_own_get_index();\n") DISP.write(f"extern {FunType} ini_{FunName}{FunArg};\n") for cpu in cpulist: DISP.write(f"extern {FunType} {cpu}_{FunName}{FunArg};\n") DISP.write(f"static MBX_FUNC_PTR arraddr[] =\n{{\n ini_{FunName}") for cpu in cpulist: DISP.write(f",\n {cpu}_{FunName}") DISP.write(f"\n}};") DISP.write(f""" DLL_PUBLIC {FunType} {FunName}{FunArg} {{ return (arraddr[*p_{FunName}_index + 1]){FunArgCall}; }} {FunType} ini_{FunName}{FunArg} {{ p_{FunName}_index = _mbx_own_get_index(); return (arraddr[*p_{FunName}_index + 1]{FunArgCall}); }} """) DISP.close() cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/gen_cpu_spc_header/000077500000000000000000000000001470420105600270245ustar00rootroot00000000000000gen_cpu_spc_1cpu_header_crypto_mb.py000066400000000000000000000051731470420105600361300ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/gen_cpu_spc_header#========================================================================= # Copyright (C) 2024 Intel Corporation # # 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. #========================================================================= # # Generates headers for 1cpu library. func -> ${opt}_func # import sys import os import datetime import ntpath import re def path_leaf(path): head, tail = ntpath.split(path) return tail or ntpath.basename(head) sys.path.append(os.path.join(sys.path[0], '../dispatcher')) from gen_disp_common_crypto_mb import readNextFunction Header = sys.argv[1] OutDir = sys.argv[2] Header = os.path.abspath(Header) Filename = "" HDR= open(Header, 'r') h= HDR.readlines() HDR.close() headerID= False FunName = "" Filename = re.sub('.h','',path_leaf(Header)) if not os.path.exists(OutDir): os.makedirs(OutDir) Filenames=["k1", "l9"] year = datetime.datetime.today() for name in Filenames: OutFile = os.sep.join([OutDir, Filename + "_"+ name + ".h"]) OUT= open( OutFile, 'w' ) OUT.write(f"""/******************************************************************************* * Copyright {year} Intel Corporation * * 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. *******************************************************************************/ """) curLine = 0 isFunctionFound = True while (isFunctionFound): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] isFunctionFound = result['success'] if (isFunctionFound): OUT.write(f"#define {FunName} {name}_{FunName}\n") OUT.close() gen_cpu_spc_header_crypto_mb.py000066400000000000000000000050241470420105600351730ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/gen_cpu_spc_header#========================================================================= # Copyright (C) 2024 Intel Corporation # # 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. #========================================================================= # # Generates spc headers for the dispatcher. func -> ${opt}_func # import sys import os import datetime import ntpath import re def path_leaf(path): head, tail = ntpath.split(path) return tail or ntpath.basename(head) sys.path.append(os.path.join(sys.path[0], '../dispatcher')) from gen_disp_common_crypto_mb import readNextFunction Header = sys.argv[1] OutDir = sys.argv[2] Header = os.path.abspath(Header) Filename = "" HDR= open(Header, 'r') h= HDR.readlines() HDR.close() headerID= False FunName = "" if not os.path.exists(OutDir): os.makedirs(OutDir) Filename = re.sub('.h','',path_leaf(Header)) OutFile = os.sep.join([OutDir, Filename + "_cpuspc" + ".h"]) year = datetime.datetime.today() OUT= open( OutFile, 'w' ) OUT.write(f"""/******************************************************************************* * Copyright {year} Intel Corporation * * 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. *******************************************************************************/ """) curLine = 0 isFunctionFound = True while (isFunctionFound): result = readNextFunction(h, curLine, headerID) curLine = result['curLine'] FunName = result['FunName'] isFunctionFound = result['success'] if (isFunctionFound): OUT.write(f"#define {FunName} OWNAPI({FunName})\n") OUT.close() cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/000077500000000000000000000000001470420105600246525ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/000077500000000000000000000000001470420105600266505ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/cpu_features.h000066400000000000000000000216561470420105600315200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 CPU_FEATURES_H #define CPU_FEATURES_H #include /* definition of cpu features */ #define mbcpCPUID_MMX 0x00000001LL /* Intel® architecture with MMX(TM) technology supported */ #define mbcpCPUID_SSE 0x00000002LL /* Intel® Streaming SIMD Extensions (Intel® SSE) instruction set */ #define mbcpCPUID_SSE2 0x00000004LL /* Intel® Streaming SIMD Extensions 2 (Intel® SSE2) instruction set */ #define mbcpCPUID_SSE3 0x00000008LL /* Intel® Streaming SIMD Extensions 3 (Intel® SSE3) instruction set */ #define mbcpCPUID_SSSE3 0x00000010LL /* Supplemental Streaming SIMD Extensions 3 (SSSE3) instruction set */ #define mbcpCPUID_MOVBE 0x00000020LL /* Intel® instruction MOVBE */ #define mbcpCPUID_SSE41 0x00000040LL /* Intel® Streaming SIMD Extensions 4.1 (Intel® SSE4.1) instruction set */ #define mbcpCPUID_SSE42 0x00000080LL /* Intel® Streaming SIMD Extensions 4.2 (Intel® SSE4.2) instruction set */ #define mbcpCPUID_AVX 0x00000100LL /* Intel® Advanced Vector Extensions (Intel® AVX) instruction set */ #define mbcpAVX_ENABLEDBYOS 0x00000200LL /* Intel® Advanced Vector Extensions (Intel® AVX) instruction set is supported by OS */ #define mbcpCPUID_AES 0x00000400LL /* AES */ #define mbcpCPUID_CLMUL 0x00000800LL /* Intel® instruction PCLMULQDQ */ #define mbcpCPUID_ABR 0x00001000LL /* Reserved */ #define mbcpCPUID_RDRAND 0x00002000LL /* Intel® instruction RDRAND */ #define mbcpCPUID_F16C 0x00004000LL /* Intel® instruction F16C */ #define mbcpCPUID_AVX2 0x00008000LL /* Intel® Advanced Vector Extensions 2 (Intel® AVX2) */ #define mbcpCPUID_ADX 0x00010000LL /* Intel® instructions ADOX/ADCX */ #define mbcpCPUID_RDSEED 0x00020000LL /* Intel® instruction RDSEED */ #define mbcpCPUID_PREFETCHW 0x00040000LL /* Intel® instruction PREFETCHW */ #define mbcpCPUID_SHA 0x00080000LL /* Intel® Secure Hash Algorithm Extensions (Intel® SHA Extensions) */ #define mbcpCPUID_AVX512F 0x00100000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) Foundation instruction set */ #define mbcpCPUID_AVX512CD 0x00200000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) CD instruction set */ #define mbcpCPUID_AVX512ER 0x00400000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) ER instruction set */ #define mbcpCPUID_AVX512PF 0x00800000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) PF instruction set */ #define mbcpCPUID_AVX512BW 0x01000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) BW instruction set */ #define mbcpCPUID_AVX512DQ 0x02000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) DQ instruction set */ #define mbcpCPUID_AVX512VL 0x04000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) VL instruction set */ #define mbcpCPUID_AVX512VBMI 0x08000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) Bit Manipulation instructions */ #define mbcpCPUID_MPX 0x10000000LL /* Intel® Memory Protection Extensions (Intel® MPX) */ #define mbcpCPUID_AVX512_4FMADDPS 0x20000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) DL floating-point single precision */ #define mbcpCPUID_AVX512_4VNNIW 0x40000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) DL enhanced word variable precision */ #define mbcpCPUID_KNC 0x80000000LL /* Intel® Xeon Phi(TM) coprocessor */ #define mbcpCPUID_AVX512IFMA 0x100000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) IFMA (PMADD52) instruction set */ #define mbcpAVX512_ENABLEDBYOS 0x200000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) is supported by OS */ #define mbcpCPUID_AVX512GFNI 0x400000000LL /* GFNI */ #define mbcpCPUID_AVX512VAES 0x800000000LL /* VAES */ #define mbcpCPUID_AVX512VCLMUL 0x1000000000LL /* VCLMUL */ #define mbcpCPUID_AVX512VBMI2 0x2000000000LL /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) Bit Manipulation instructions 2 */ #define mbcpCPUID_BMI1 0x4000000000LL /* BMI1 */ #define mbcpCPUID_BMI2 0x8000000000LL /* BMI2 */ #define mbcpCPUID_AVXIFMA 0x10000000000LL /* general sets of the cpu features */ #define MBX_AVX512_GENERAL_ISA ( \ mbcpCPUID_BMI2 \ | mbcpCPUID_AVX512F \ | mbcpCPUID_AVX512DQ \ | mbcpCPUID_AVX512BW \ | mbcpCPUID_AVX512IFMA \ | mbcpCPUID_AVX512VBMI2 \ | mbcpAVX512_ENABLEDBYOS) #define MBX_AVX2_GENERAL_ISA ( \ mbcpCPUID_MOVBE \ | mbcpCPUID_AVX2 \ | mbcpCPUID_RDSEED \ | mbcpAVX_ENABLEDBYOS) /* map cpu features */ MBXAPI(int64u, mbx_get_cpu_features,(void)) MBXAPI(void, mbx_set_cpu_features,(int64u features)) /* check if crypto_mb is applicable */ MBXAPI(int, mbx_is_crypto_mb_applicable,(int64u cpu_features)) /* supported algorithm */ enum MBX_ALGO { MBX_ALGO_RSA_1K, MBX_ALGO_RSA_2K, MBX_ALGO_RSA_3K, MBX_ALGO_RSA_4K, MBX_ALGO_X25519, MBX_ALGO_EC_NIST_P256, MBX_ALGO_ECDHE_NIST_P256 = MBX_ALGO_EC_NIST_P256, MBX_ALGO_ECDSA_NIST_P256 = MBX_ALGO_EC_NIST_P256, MBX_ALGO_EC_NIST_P384, MBX_ALGO_ECDHE_NIST_P384 = MBX_ALGO_EC_NIST_P384, MBX_ALGO_ECDSA_NIST_P384 = MBX_ALGO_EC_NIST_P384, MBX_ALGO_EC_NIST_P521, MBX_ALGO_ECDHE_NIST_P521 = MBX_ALGO_EC_NIST_P521, MBX_ALGO_ECDSA_NIST_P521 = MBX_ALGO_EC_NIST_P521, MBX_ALGO_EC_SM2, MBX_ALGO_ECDHE_SM2 = MBX_ALGO_EC_SM2, MBX_ALGO_ECDSA_SM2 = MBX_ALGO_EC_SM2, MBX_ALGO_SM3, MBX_ALGO_SM4, MBX_ALGO_ECB_SM4 = MBX_ALGO_SM4, MBX_ALGO_CBC_SM4 = MBX_ALGO_SM4, MBX_ALGO_CTR_SM4 = MBX_ALGO_SM4, MBX_ALGO_OFB_SM4 = MBX_ALGO_SM4, MBX_ALGO_OFB128_SM4 = MBX_ALGO_SM4, }; /* multi-buffer width implemented by library */ enum MBX_WIDTH { MBX_WIDTH_MB8 = 8, MBX_WIDTH_MB16 = 16, MBX_WIDTH_ANY = (1 << 16) - 1 }; typedef int64u MBX_ALGO_INFO; /* check if algorithm is supported on current platform * returns: multi-buffer width mask or 0 if algorithm not supported */ MBXAPI(MBX_ALGO_INFO, mbx_get_algo_info,(enum MBX_ALGO algo)) #endif /* CPU_FEATURES_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/defs.h000066400000000000000000000054061470420105600277470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 DEFS_H #define DEFS_H /* externals */ #undef EXTERN_C #ifdef __cplusplus #define EXTERN_C extern "C" #else #define EXTERN_C #endif #if !defined( MBXAPI ) #define MBXAPI( type,name,arg ) EXTERN_C type MBX_CALL name arg; #endif #if defined (_MSC_VER) #define MBX_CDECL __cdecl #elif (defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || defined (__GNUC__ ) || defined (__clang__)) && defined (_ARCH_IA32) #define MBX_CDECL __attribute((cdecl)) #else #define MBX_CDECL #endif #if defined( _WIN32 ) || defined( _WIN64 ) #define MBX_STDCALL __stdcall #define MBX_CALL MBX_STDCALL #else #define MBX_STDCALL #define MBX_CALL MBX_CDECL #endif /* data types */ typedef unsigned char int8u; typedef unsigned short int16u; typedef unsigned int int32u; typedef unsigned long long int64u; #ifndef NULL #define NULL ((void *)0) #endif /* alignment & inline */ #if defined(__GNUC__) #if !defined(__ALIGN64) #define __ALIGN64 __attribute__((aligned(64))) #endif #if !defined(__MBX_INLINE) #define __MBX_INLINE static __inline__ __attribute__((always_inline)) #endif #if !defined(__NOINLINE) #define __NOINLINE __attribute__((noinline)) #endif #else #if !defined(__ALIGN64) #define __ALIGN64 __declspec(align(64)) #endif #if !defined(__MBX_INLINE) #define __MBX_INLINE static __forceinline #endif #if !defined(__NOINLINE) #define __NOINLINE __declspec(noinline) #endif #endif #if !defined(MBX_ZEROING_FUNC_ATTRIBUTES) #if defined(_MSC_VER) && !defined(__clang__) #define MBX_ZEROING_FUNC_ATTRIBUTES __declspec(noinline) #elif defined(__GNUC__) && !defined(__clang__) #define MBX_ZEROING_FUNC_ATTRIBUTES __attribute__((noinline)) #elif defined(__clang__) || defined(__INTEL_LLVM_COMPILER) #define MBX_ZEROING_FUNC_ATTRIBUTES __attribute__((noinline)) __attribute((optnone)) #else #define MBX_ZEROING_FUNC_ATTRIBUTES #endif #endif /* MBX_ZEROING_FUNC_ATTRIBUTES */ #define MBX_UNREFERENCED_PARAMETER(p) (void)(p) #endif /* DEFS_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/ec_nistp256.h000066400000000000000000000225201470420105600310630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 EC_NISTP256_H #define EC_NISTP256_H #include #include #ifndef BN_OPENSSL_DISABLE #include #include #endif // BN_OPENSSL_DISABLE /* // ECDHE */ /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key is represented by (X:Y:Z) projective Jacobian coordinates */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp256_ecpublic_key_ssl_mb8,(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp256_ecpublic_key_mb8,(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer)) /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates // pBuffer pointer to the scratch buffer // // Note: // input party's public key is represented by (X:Y:Z) projective Jacobian coordinates */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp256_ecdh_ssl_mb8,(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp256_ecdh_mb8,(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // ECDSA signature generation */ /* // Pre-computes ECDSA signature // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_sign_rp[] array of pointers to the pre-computed r-components of the signatures // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp256_ecdsa_sign_setup_mb8,(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer)) /* // computes ECDSA signature // // pa_sign_r[] array of pointers to the r-components of the signatures // pa_sign_s[] array of pointers to the s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_sgn_rp[] array of pointers to the pre-computed r-components of the signatures // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_reg_skey[] array of pointers to the regular signer's ephemeral private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp256_ecdsa_sign_complete_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sgn_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer)) /* // Computes ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pa_reg_skey[] array of pointers to the signer's regular private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp256_ecdsa_sign_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer)) /* // Verifies ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages that have been signed // pa_pubx[] array of pointers to the signer's public keys X-coordinates // pa_puby[] array of pointers to the signer's public keys Y-coordinates // pa_pubz[] array of pointers to the signer's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp256_ecdsa_verify_mb8,(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // OpenSSL's specific similar APIs */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp256_ecdsa_sign_setup_ssl_mb8,(BIGNUM* pa_inv_eph_skey[8], BIGNUM* pa_sign_pr[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp256_ecdsa_sign_complete_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sgn_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp256_ecdsa_sign_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp256_ecdsa_verify_ssl_mb8,(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE #endif /* EC_NISTP256_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/ec_nistp384.h000066400000000000000000000225461470420105600310750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 EC_NISTP384_H #define EC_NISTP384_H #include #include #ifndef BN_OPENSSL_DISABLE #include #include #endif // BN_OPENSSL_DISABLE /* // ECDHE */ /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key is represented by (X:Y:Z) projective Jacobian coordinates */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp384_ecpublic_key_ssl_mb8,(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp384_ecpublic_key_mb8,(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer)) /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates // pBuffer pointer to the scratch buffer // // Note: // input party's public key is represented by (X:Y:Z) projective Jacobian coordinates */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp384_ecdh_ssl_mb8,(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp384_ecdh_mb8,(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // ECDSA signature generation */ /* // Pre-computes ECDSA signature // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_sign_rp[] array of pointers to the pre-computed r-components of the signatures // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp384_ecdsa_sign_setup_mb8,(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer)) /* // computes ECDSA signature // // pa_sign_r[] array of pointers to the r-components of the signatures // pa_sign_s[] array of pointers to the s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_sgn_rp[] array of pointers to the pre-computed r-components of the signatures // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_reg_skey[] array of pointers to the regular signer's ephemeral private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp384_ecdsa_sign_complete_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sgn_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer)) /* // Computes ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pa_reg_skey[] array of pointers to the signer's regular private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp384_ecdsa_sign_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer)) /* // Verifies ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages that have been signed // pa_pubx[] array of pointers to the signer's public keys X-coordinates // pa_puby[] array of pointers to the signer's public keys Y-coordinates // pa_pubz[] array of pointers to the signer's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp384_ecdsa_verify_mb8,(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // OpenSSL's specific similar APIs */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp384_ecdsa_sign_setup_ssl_mb8,(BIGNUM* pa_inv_eph_skey[8], BIGNUM* pa_sign_pr[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp384_ecdsa_sign_complete_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sgn_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp384_ecdsa_sign_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp384_ecdsa_verify_ssl_mb8,(const ECDSA_SIG* const pa_sign[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE #endif /* EC_NISTP384_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/ec_nistp521.h000066400000000000000000000225501470420105600310610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 EC_NISTP521_H #define EC_NISTP521_H #include #include #ifndef BN_OPENSSL_DISABLE #include #include #endif // BN_OPENSSL_DISABLE /* // ECDHE */ /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key is represented by (X:Y:Z) projective Jacobian coordinates */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp521_ecpublic_key_ssl_mb8,(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp521_ecpublic_key_mb8,(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer)) /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates // pBuffer pointer to the scratch buffer // // Note: // input party's public key is represented by (X:Y:Z) projective Jacobian coordinates */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp521_ecdh_ssl_mb8,(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp521_ecdh_mb8,(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // ECDSA signature generation */ /* // Pre-computes ECDSA signature // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_sign_rp[] array of pointers to the pre-computed r-components of the signatures // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp521_ecdsa_sign_setup_mb8,(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer)) /* // computes ECDSA signature // // pa_sign_r[] array of pointers to the r-components of the signatures // pa_sign_s[] array of pointers to the s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_sgn_rp[] array of pointers to the pre-computed r-components of the signatures // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_reg_skey[] array of pointers to the regular signer's ephemeral private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp521_ecdsa_sign_complete_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sgn_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer)) /* // Computes ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pa_reg_skey[] array of pointers to the signer's regular private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp521_ecdsa_sign_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer)) /* // Verifies ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_nistp521_ecdsa_verify_mb8,(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // OpenSSL's specific similar APIs */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_nistp521_ecdsa_sign_setup_ssl_mb8,(BIGNUM* pa_inv_eph_skey[8], BIGNUM* pa_sign_pr[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp521_ecdsa_sign_complete_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sgn_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp521_ecdsa_sign_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_nistp521_ecdsa_verify_ssl_mb8,(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE #endif /* EC_NISTP521_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/ec_sm2.h000066400000000000000000000200051470420105600301660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 EC_SM2_H #define EC_SM2_H #include #include #ifndef BN_OPENSSL_DISABLE #include #include #endif // BN_OPENSSL_DISABLE /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates (or NULL, if affine coordinate requested) // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_sm2_ecpublic_key_mb8,(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer)) /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer // // Note: // This function implements ECDHE over SM2 curve according to IEEE 1363-2000 standard. */ MBXAPI(mbx_status, mbx_sm2_ecdh_mb8,(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // Computes SM2 ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_user_id[] array of pointers to the users ID // user_id_len[] array of users ID length // pa_msg[] array of pointers to the messages are being signed // msg_len[] array of messages length // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pa_reg_skey[] array of pointers to the signer's regular private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_sm2_ecdsa_sign_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // Verifies SM2 ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_user_id[] array of pointers to the users ID // user_id_len[] array of users ID length // pa_msg[] array of pointers to the messages are being signed // msg_len[] array of messages length // pa_pubx[] array of pointers to the signer's public keys X-coordinates // pa_puby[] array of pointers to the signer's public keys Y-coordinates // pa_pubz[] array of pointers to the signer's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer */ MBXAPI(mbx_status, mbx_sm2_ecdsa_verify_mb8,(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer)) /* // OpenSSL's specific similar APIs */ #ifndef BN_OPENSSL_DISABLE MBXAPI(mbx_status, mbx_sm2_ecpublic_key_ssl_mb8,(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_sm2_ecdh_ssl_mb8,(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_sm2_ecdsa_sign_ssl_mb8,(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) MBXAPI(mbx_status, mbx_sm2_ecdsa_verify_ssl_mb8,(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer)) #endif // BN_OPENSSL_DISABLE #endif /* EC_SM2_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/ed25519.h000066400000000000000000000060001470420105600300130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 ED25519_H #define ED25519_H #include #include typedef int8u ed25519_sign_component[32]; typedef ed25519_sign_component ed25519_sign[2]; typedef int8u ed25519_public_key[32]; typedef int8u ed25519_private_key[32]; /* // Computes ed25519 public key // pa_public_key[] array of pointers to the public keys // pa_private_key[] array of pointers to the public keys Y-coordinates */ MBXAPI(mbx_status, mbx_ed25519_public_key_mb8,(ed25519_public_key* pa_public_key[8], const ed25519_private_key* const pa_private_key[8])) /* // Computes ed25519 signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // msgLen[] lengths of the messages are being signed // pa_private_key[] array of pointers to the signer's private keys // pa_public_key[] array of pointers to the signer's public keys */ MBXAPI(mbx_status, mbx_ed25519_sign_mb8,(ed25519_sign_component* pa_sign_r[8], ed25519_sign_component* pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_private_key* const pa_private_key[8], const ed25519_public_key* const pa_public_key[8])) /* // Verifies ed25519 signature // pa_sign_r[] array of pointers to the r-components of the verified signatures // pa_sign_s[] array of pointers to the s-components of the verified signatures // pa_msg[] array of pointers to the signed messages // msgLen[] array of signed messages lengths // pa_public_key[] array of pointers to the signer's public keys */ MBXAPI(mbx_status, mbx_ed25519_verify_mb8,(const ed25519_sign_component* const pa_sign_r[8], const ed25519_sign_component* const pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_public_key* const pa_public_key[8])) #endif /* ED25519_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/exp.h000066400000000000000000000051041470420105600276150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 EXP_H #define EXP_H #include #include /* size of scratch buffer */ MBXAPI(int, mbx_exp_BufferSize,(int modulusBits)) /* exp operation */ MBXAPI(mbx_status, mbx_exp1024_mb8,(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen)) MBXAPI(mbx_status, mbx_exp2048_mb8,(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen)) MBXAPI(mbx_status, mbx_exp3072_mb8,(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen)) MBXAPI(mbx_status, mbx_exp4096_mb8,(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen)) MBXAPI(mbx_status, mbx_exp_mb8,(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen)) #endif /* EXP_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/fips_cert.h000066400000000000000000000215561470420105600310100ustar00rootroot00000000000000/******************************************************************************* * Copyright 2023 Intel Corporation * * 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 CRYPTO_MB_FIPS_CERT_H #define CRYPTO_MB_FIPS_CERT_H #include #include #define MBX_ALGO_SELFTEST_OK (0) #define MBX_ALGO_SELFTEST_BAD_ARGS_ERR (1) #define MBX_ALGO_SELFTEST_KAT_ERR (2) #define MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR (4) typedef int fips_test_status; typedef int func_fips_approved; EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecpublic_key_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecpublic_key_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecpublic_key_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdh_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdh_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdh_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_mb8(void); /* mbx_nistp256_ecdsa_sign_setup_mb8() + mbx_nistp256_ecdsa_sign_complete_mb8() */ EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8(void); /* mbx_nistp384_ecdsa_sign_setup_mb8() + mbx_nistp384_ecdsa_sign_complete_mb8() */ EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8(void); /* mbx_nistp521_ecdsa_sign_setup_mb8() + mbx_nistp521_ecdsa_sign_complete_mb8() */ EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdsa_verify_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdsa_verify_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdsa_verify_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_ed25519_public_key_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_ed25519_sign_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_ed25519_verify_mb8(void); /* x25519 scheme is not yet FIPS-approved */ // EXTERN_C fips_test_status fips_selftest_mbx_x25519_public_key_mb8(void); // EXTERN_C fips_test_status fips_selftest_mbx_x25519_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa2k_public_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa3k_public_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa4k_public_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa2k_private_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa3k_private_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa4k_private_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa2k_private_crt_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa3k_private_crt_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa4k_private_crt_mb8(void); #ifndef BN_OPENSSL_DISABLE EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecpublic_key_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecpublic_key_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecpublic_key_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdh_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdh_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdh_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_ssl_mb8(void); /* mbx_nistp256_ecdsa_sign_setup_ssl_mb8() + mbx_nistp256_ecdsa_sign_complete_ssl_mb8() */ EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_ssl_mb8(void); /* mbx_nistp384_ecdsa_sign_setup_ssl_mb8() + mbx_nistp384_ecdsa_sign_complete_ssl_mb8() */ EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_ssl_mb8(void); /* mbx_nistp521_ecdsa_sign_setup_ssl_mb8() + mbx_nistp521_ecdsa_sign_complete_ssl_mb8() */ EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp256_ecdsa_verify_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp384_ecdsa_verify_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_nistp521_ecdsa_verify_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa2k_public_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa3k_public_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa4k_public_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa2k_private_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa3k_private_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa4k_private_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa2k_private_crt_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa3k_private_crt_ssl_mb8(void); EXTERN_C fips_test_status fips_selftest_mbx_rsa4k_private_crt_ssl_mb8(void); #endif // BN_OPEN_SSL_DISABLE /* // Enumerator that contains information about FIPS-approved // functions inside the crypto_mb cryptographic boundary */ enum FIPS_CRYPTO_MB_FUNC { /* Approved functions, > 0 */ nistp256_ecpublic_key_mb8 = 0x1, nistp384_ecpublic_key_mb8, nistp521_ecpublic_key_mb8, nistp256_ecdh_mb8, nistp384_ecdh_mb8, nistp521_ecdh_mb8, nistp256_ecdsa_sign_mb8, nistp384_ecdsa_sign_mb8, nistp521_ecdsa_sign_mb8, nistp256_ecdsa_sign_setup_mb8, nistp384_ecdsa_sign_setup_mb8, nistp521_ecdsa_sign_setup_mb8, nistp256_ecdsa_sign_complete_mb8, nistp384_ecdsa_sign_complete_mb8, nistp521_ecdsa_sign_complete_mb8, nistp256_ecdsa_verify_mb8, nistp384_ecdsa_verify_mb8, nistp521_ecdsa_verify_mb8, ed25519_public_key_mb8, ed25519_sign_mb8, ed25519_verify_mb8, rsa_public_mb8, rsa_private_mb8, rsa_private_crt_mb8, nistp256_ecpublic_key_ssl_mb8, nistp384_ecpublic_key_ssl_mb8, nistp521_ecpublic_key_ssl_mb8, nistp256_ecdh_ssl_mb8, nistp384_ecdh_ssl_mb8, nistp521_ecdh_ssl_mb8, nistp256_ecdsa_sign_ssl_mb8, nistp384_ecdsa_sign_ssl_mb8, nistp521_ecdsa_sign_ssl_mb8, nistp256_ecdsa_sign_setup_ssl_mb8, nistp384_ecdsa_sign_setup_ssl_mb8, nistp521_ecdsa_sign_setup_ssl_mb8, nistp256_ecdsa_sign_complete_ssl_mb8, nistp384_ecdsa_sign_complete_ssl_mb8, nistp521_ecdsa_sign_complete_ssl_mb8, nistp256_ecdsa_verify_ssl_mb8, nistp384_ecdsa_verify_ssl_mb8, nistp521_ecdsa_verify_ssl_mb8, rsa_public_ssl_mb8, rsa_private_ssl_mb8, rsa_private_crt_ssl_mb8, /* Not approved functions, < 0 */ exp1024_mb8 = -0xFFF, exp2048_mb8, exp3072_mb8, exp4096_mb8, exp_mb8, x25519_public_key_mb8, x25519_mb8, sm2_ecpublic_key_mb8, sm2_ecdh_mb8, sm2_ecdsa_sign_mb8, sm2_ecdsa_verify_mb8, sm2_ecpublic_key_ssl_mb8, sm2_ecdh_ssl_mb8, sm2_ecdsa_sign_ssl_mb8, sm2_ecdsa_verify_ssl_mb8, sm3_init_mb16, sm3_update_mb16, sm3_final_mb16, sm3_msg_digest_mb16, sm4_set_key_mb16, sm4_encrypt_ecb_mb16, sm4_decrypt_ecb_mb16, sm4_encrypt_cbc_mb16, sm4_decrypt_cbc_mb16, sm4_encrypt_ctr128_mb16, sm4_decrypt_ctr128_mb16, sm4_encrypt_ofb_mb16, sm4_decrypt_ofb_mb16, sm4_encrypt_cfb128_mb16, sm4_decrypt_cfb128_mb16, sm4_gcm_init_mb16, sm4_gcm_update_iv_mb16, sm4_gcm_update_aad_mb16, sm4_gcm_encrypt_mb16, sm4_gcm_decrypt_mb16, sm4_gcm_get_tag_mb16, sm4_ccm_init_mb16, sm4_ccm_update_aad_mb16, sm4_ccm_encrypt_mb16, sm4_ccm_decrypt_mb16, sm4_ccm_get_tag_mb16, sm4_xts_set_keys_mb16, sm4_xts_encrypt_mb16, sm4_xts_decrypt_mb16, }; /** * \brief * * An indicator if a function is FIPS-approved or not * * \param[in] function member of FIPS_CRYPTO_MB_FUNC enumerator * that corresponds to API being checked. * \return func_fips_approved equal to 1 if FIPS-approved algorithm is used * * Example: * Library API FIPS_CRYPTO_MB_FUNC * mbx_rsa_public_mb8 -> rsa_public_mb8 * mbx_nistp256_ecdh_mb8 -> nistp256_ecdh_mb8 * mbx_ -> * */ __MBX_INLINE func_fips_approved mbx_is_fips_approved_func(enum FIPS_CRYPTO_MB_FUNC function) { return ((int)function > 0); } #endif /* CRYPTO_MB_FIPS_CERT_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/rsa.h000066400000000000000000000117251470420105600276140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 RSA_H #define RSA_H #include #include #ifndef BN_OPENSSL_DISABLE #include MBXAPI(mbx_status, mbx_rsa_public_ssl_mb8,(const int8u* const from_pa[8], int8u* const to_pa[8], const BIGNUM* const e_pa[8], const BIGNUM* const n_pa[8], int expected_rsa_bitsize)) MBXAPI(mbx_status, mbx_rsa_private_ssl_mb8,(const int8u* const from_pa[8], int8u* const to_pa[8], const BIGNUM* const d_pa[8], const BIGNUM* const n_pa[8], int expected_rsa_bitsize)) MBXAPI(mbx_status, mbx_rsa_private_crt_ssl_mb8,(const int8u* const from_pa[8], int8u* const to_pa[8], const BIGNUM* const p_pa[8], const BIGNUM* const q_pa[8], const BIGNUM* const dp_pa[8], const BIGNUM* const dq_pa[8], const BIGNUM* const iq_pa[8], int expected_rsa_bitsize)) #endif /* BN_OPENSSL_DISABLE */ /* // rsa cp methods */ typedef struct _ifma_rsa_method mbx_RSA_Method; /* rsa public key operation */ MBXAPI(const mbx_RSA_Method*, mbx_RSA1K_pub65537_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA2K_pub65537_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA3K_pub65537_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA4K_pub65537_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA_pub65537_Method,(int rsaBitsize)) /* rsa private key operation */ MBXAPI(const mbx_RSA_Method*, mbx_RSA1K_private_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA2K_private_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA3K_private_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA4K_private_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA_private_Method,(int rsaBitsize)) /* rsa private key operation (ctr) */ MBXAPI(const mbx_RSA_Method*, mbx_RSA1K_private_crt_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA2K_private_crt_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA3K_private_crt_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA4K_private_crt_Method,(void)) MBXAPI(const mbx_RSA_Method*, mbx_RSA_private_crt_Method,(int rsaBitsize)) MBXAPI(int, mbx_RSA_Method_BufSize,(const mbx_RSA_Method* m)) MBXAPI(mbx_status, mbx_rsa_public_mb8,(const int8u* const from_pa[8], int8u* const to_pa[8], const int64u* const n_pa[8], int rsaBitlen, const mbx_RSA_Method* m, int8u* pBuffer)) MBXAPI(mbx_status, mbx_rsa_private_mb8,(const int8u* const from_pa[8], int8u* const to_pa[8], const int64u* const d_pa[8], const int64u* const n_pa[8], int rsaBitlen, const mbx_RSA_Method* m, int8u* pBuffer)) MBXAPI(mbx_status, mbx_rsa_private_crt_mb8,(const int8u* const from_pa[8], int8u* const to_pa[8], const int64u* const p_pa[8], const int64u* const q_pa[8], const int64u* const dp_pa[8], const int64u* const dq_pa[8], const int64u* const iq_pa[8], int rsaBitlen, const mbx_RSA_Method* m, int8u* pBuffer)) #endif /* RSA_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/sm3.h000066400000000000000000000052671470420105600275350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 SM3_H #define SM3_H #include #include #define SM3_SIZE_IN_BITS (256) /* sm3 size in bits */ #define SM3_SIZE_IN_WORDS (SM3_SIZE_IN_BITS/(sizeof(int32u)*8)) /* sm3 hash size in words */ #define SM3_MSG_BLOCK_SIZE (64) /* message block size */ #define SM3_NUM_BUFFERS (16) /* max number of buffers in sm3 multi-buffer */ /* // sm3 context for mb16 */ typedef int32u sm3_hash_mb[SM3_SIZE_IN_WORDS][SM3_NUM_BUFFERS]; /* sm3 hash value in multi-buffer format */ struct _sm3_context_mb16 { int msg_buff_idx[SM3_NUM_BUFFERS]; /* buffer entry */ int64u msg_len[SM3_NUM_BUFFERS]; /* message length */ int8u msg_buffer[SM3_NUM_BUFFERS][SM3_MSG_BLOCK_SIZE]; /* buffer */ __ALIGN64 sm3_hash_mb msg_hash; /* intermediate hash */ }; typedef struct _sm3_context_mb16 SM3_CTX_mb16; MBXAPI(mbx_status16, mbx_sm3_init_mb16,(SM3_CTX_mb16* p_state)) MBXAPI(mbx_status16, mbx_sm3_update_mb16,(const int8u* const msg_pa[16], int len[16], SM3_CTX_mb16* p_state)) MBXAPI(mbx_status16, mbx_sm3_final_mb16,(int8u* hash_pa[16], SM3_CTX_mb16* p_state)) MBXAPI(mbx_status16, mbx_sm3_msg_digest_mb16,(const int8u* const msg_pa[16], int len[16], int8u* hash_pa[16])) #endif /* SM3_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/sm4.h000066400000000000000000000103701470420105600275250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 SM4_H #define SM4_H #include #include #define SM4_LINES (16) /* Max number of buffers */ #define SM4_BLOCK_SIZE (16) /* SM4 data block size (bytes) */ #define SM4_KEY_SIZE (16) /* SM4 key size (bytes) */ #define SM4_ROUNDS (32) /* SM4 number of rounds */ #define SM4_XTS_MAX_SIZE ((1 << 20) * SM4_BLOCK_SIZE) /* SM4 max buffer size (bytes) */ typedef int8u sm4_key[SM4_KEY_SIZE]; typedef int8u sm4_xts_key[SM4_KEY_SIZE*2]; typedef int32u mbx_sm4_key_schedule[SM4_ROUNDS][SM4_LINES]; MBXAPI(mbx_status16, mbx_sm4_set_key_mb16,(mbx_sm4_key_schedule* key_sched, const sm4_key* pa_key[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_xts_set_keys_mb16,(mbx_sm4_key_schedule* key_sched1, mbx_sm4_key_schedule* key_sched2, const sm4_xts_key* pa_key[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_encrypt_ecb_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched)) MBXAPI(mbx_status16, mbx_sm4_decrypt_ecb_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched)) MBXAPI(mbx_status16, mbx_sm4_encrypt_cbc_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_decrypt_cbc_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_encrypt_ctr128_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_ctr[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_decrypt_ctr128_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_ctr[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_encrypt_ofb_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_iv[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_decrypt_ofb_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_iv[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_encrypt_cfb128_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_decrypt_cfb128_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_xts_encrypt_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched1, const mbx_sm4_key_schedule* key_sched2, const int8u* pa_tweak[SM4_LINES])) MBXAPI(mbx_status16, mbx_sm4_xts_decrypt_mb16,(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched1, const mbx_sm4_key_schedule* key_sched2, const int8u* pa_tweak[SM4_LINES])) #endif /* SM4_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/sm4_ccm.h000066400000000000000000000141561470420105600303550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 SM4_CCM_H #define SM4_CCM_H #include #include #define MIN_CCM_IV_LENGTH 7 #define MAX_CCM_IV_LENGTH 13 #define MIN_CCM_TAG_LENGTH 4 #define MAX_CCM_TAG_LENGTH 16 #define MAX_CCM_AAD_LENGTH 65280 /* 2^16 - 2^8 */ #define SM4_CCM_CONTEXT_BUFFER_SLOT_TYPE int64u #define SM4_CCM_CONTEXT_BUFFER_SLOT_SIZE_BYTES (sizeof(SM4_CCM_CONTEXT_BUFFER_SLOT_TYPE)) #define SM4_CCM_CONTEXT_BUFFER_SIZE_BYTES ((SM4_LINES * SM4_BLOCK_SIZE) / SM4_CCM_CONTEXT_BUFFER_SLOT_SIZE_BYTES) /* // Enum to control call sequence // // Valid call sequence: // // 1) mbx_sm4_ccm_init_mb16 // 2) mbx_sm4_ccm_update_aad_mb16 – optional // 3) mbx_sm4_ccm_encrypt_mb16/mbx_sm4_ccm_decrypt_mb16 – optional, can be called as many times as necessary // 4) mbx_sm4_ccm_get_tag_mb16 // // Call sequence restrictions: // // * mbx_sm4_ccm_get_tag_mb16 can be called after mbx_sm4_ccm_init_mb16 has been called. // * functions at steps 2-3 can be called as many times as needed to process payload while this functions processes buffers // with full blocks (Blocks of 16 bytes size) or empty buffers and length of processed payload is not overflowed. // * if functions at steps 2-3 called to process a partial block, it can’t be called again. // * if mbx_sm4_ccm_encrypt_mb16 or mbx_sm4_ccm_decrypt_mb16 was called, mbx_sm4_ccm_update_aad_mb16 can’t be called. // * if mbx_sm4_ccm_encrypt_mb16 was called, mbx_sm4_ccm_decrypt_mb16 can’t be called. // * if mbx_sm4_ccm_decrypt_mb16 was called, mbx_sm4_ccm_encrypt_mb16 can’t be called. */ typedef enum { sm4_ccm_update_aad = 0xF0A1, sm4_ccm_start_encdec, sm4_ccm_enc, sm4_ccm_dec, sm4_ccm_get_tag } sm4_ccm_state; struct _sm4_ccm_context_mb16 { int64u msg_len[SM4_LINES]; /* Message length (in bytes) of all lines */ int64u total_processed_len[SM4_LINES]; /* Total processed plaintext/ciphertext length (in bytes) of all lines */ int tag_len[SM4_LINES]; /* Tag length (in bytes) of all lines */ int iv_len[SM4_LINES]; /* Total IV length (in bytes) of all lines */ __m128i ctr0[SM4_LINES]; /* CTR0 content */ __m128i ctr[SM4_LINES]; /* CTR content */ __m128i hash[SM4_LINES]; /* hash value accumulator for AAD and TXT processing */ mbx_sm4_key_schedule key_sched; /* SM4 key schedule */ sm4_ccm_state state; /* call sequence state */ }; typedef struct _sm4_ccm_context_mb16 SM4_CCM_CTX_mb16; /* * Initializes SM4-CCM context. * * @param[in] pa_key Array of key pointers * @param[in] pa_iv Array of IV pointers * @param[in] iv_len Array of IV lengths * @param[in] tag_len Array of authentication tag lengths * @param[in] msg_len Array of total message lengths * @param[in/out] p_context SM4-CCM context * * @return Bitmask of operation status */ MBXAPI(mbx_status16, mbx_sm4_ccm_init_mb16,(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], const int tag_len[SM4_LINES], const int64u msg_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context)) /* * Digests additional authenticated data (AAD) for 16 buffers * * @param[in] pa_aad Array of AAD pointers * @param[in] aad_len Array of AAD lengths * @param[in/out] p_context SM4-CCM context * * @return Bitmask of operation status */ MBXAPI(mbx_status16, mbx_sm4_ccm_update_aad_mb16,(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context)) /* * Retrieves authentication tag for 16 buffers * * @param[out] pa_tag Array of authentication tag pointers * @param[in] tag_len Array of tag lengths * @param[in/out] p_context SM4-CCM context * * @return Bitmask of operation status */ MBXAPI(mbx_status16, mbx_sm4_ccm_get_tag_mb16,(int8u *pa_tag[SM4_LINES], const int tag_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context)) /* * Encrypts 16 buffers with SM4-CCM. * * @param[out] pa_out Array of ciphertext pointers * @param[in] pa_in Array of plaintext pointers * @param[in] in_len Array of plaintext lengths * @param[in/out] p_context SM4-CCM context * * @return Bitmask of operation status */ MBXAPI(mbx_status16, mbx_sm4_ccm_encrypt_mb16,(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context)) /* * Decrypts 16 buffers with SM4-CCM. * * @param[out] pa_out Array of plaintext pointers * @param[in] pa_in Array of ciphertext pointers * @param[in] in_len Array of ciphertext lengths * @param[in/out] p_context SM4-CCM context * * @return Bitmask of operation status */ MBXAPI(mbx_status16, mbx_sm4_ccm_decrypt_mb16,(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context)) #endif /* SM4_CCM_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/sm4_gcm.h000066400000000000000000000126411470420105600303560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 SM4_GCM_H #define SM4_GCM_H #include #include #define SM4_GCM_CONTEXT_BUFFER_SLOT_TYPE int64u #define SM4_GCM_CONTEXT_BUFFER_SLOT_SIZE_BYTES (sizeof(SM4_GCM_CONTEXT_BUFFER_SLOT_TYPE)) #define SM4_GCM_CONTEXT_BUFFER_SIZE_BYTES ((SM4_LINES * SM4_BLOCK_SIZE) / SM4_GCM_CONTEXT_BUFFER_SLOT_SIZE_BYTES) #define SM4_GCM_HASHKEY_PWR_NUM 8 /* // Enum to control call sequence // // Valid call sequence: // // 1) mbx_sm4_gcm_init_mb16 // 2) mbx_sm4_gcm_update_iv_mb16 – optional, can be called as many times as necessary // 3) mbx_sm4_gcm_update_aad_mb16 – optional, can be called as many times as necessary // 4) mbx_sm4_gcm_encrypt_mb16/mbx_sm4_gcm_decrypt_mb16 – optional, can be called as many times as necessary // 5) mbx_sm4_gcm_get_tag_mb16 // // Call sequence restrictions: // // * mbx_sm4_gcm_get_tag_mb16 can be called after IV is fully processed. // IV is fully processed if buffer with partial block (Block of less than 16 bytes size) was processed or if mbx_sm4_gcm_update_aad_mb16 was called // * functions at steps 2-4 can be called as many times as needed to process payload while this functions processes buffers // with full blocks (Blocks of 16 bytes size) or empty buffers and length of processed payload is not overflowed. // * if functions at steps 2-4 called to process a partial block, it can’t be called again. // * if mbx_sm4_gcm_update_aad_mb16 was called, mbx_sm4_gcm_update_iv_mb16 can’t be called. // * if mbx_sm4_gcm_encrypt_mb16 or mbx_sm4_gcm_decrypt_mb16 was called, mbx_sm4_gcm_update_aad_mb16 and mbx_sm4_gcm_update_iv_mb16 can’t be called. // * if mbx_sm4_gcm_encrypt_mb16 was called, mbx_sm4_gcm_decrypt_mb16 can’t be called. // * if mbx_sm4_gcm_decrypt_mb16 was called, mbx_sm4_gcm_encrypt_mb16 can’t be called. */ typedef enum { sm4_gcm_update_iv = 0xF0A1, sm4_gcm_update_aad, sm4_gcm_start_encdec, sm4_gcm_enc, sm4_gcm_dec, sm4_gcm_get_tag } sm4_gcm_state; struct _sm4_gcm_context_mb16 { __m128i hashkey[SM4_GCM_HASHKEY_PWR_NUM][SM4_LINES]; /* Set of hashkeys for ghash computation */ __m128i j0[SM4_LINES]; /* J0 value accumulator for IV processing */ __m128i ghash[SM4_LINES]; /* ghash value accumulator for AAD and TXT processing */ __m128i ctr[SM4_LINES]; /* counter for gctr encryption */ /* // buffer to store IV, AAD and TXT length in bytes // // this buffer is used to store IV length to compute J0 block // and reused to store AAD and TXT length to compute ghash // // length is stored as follow: // // J0 computation: // [64 bits with IV len (buffer 0)] // [64 bits with IV len (buffer 1)] // .. // [64 bits with IV len (buffer SM4_LINES-1)] // // Only half of buffer is used for J0 computation // // ghash computation: // [64 bits with AAD len (buffer 0)][64 bits with TXT len (buffer 0)] // [64 bits with AAD len (buffer 1)][64 bits with TXT len (buffer 1)] // .. // [64 bits with AAD len (buffer SM4_LINES-1)][64 bits with TXT len (buffer SM4_LINES-1)] // */ int64u len[SM4_LINES * 2]; mbx_sm4_key_schedule key_sched; /* SM4 key schedule */ sm4_gcm_state state; /* call sequence state */ }; typedef struct _sm4_gcm_context_mb16 SM4_GCM_CTX_mb16; MBXAPI(mbx_status16, mbx_sm4_gcm_init_mb16,(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context)) MBXAPI(mbx_status16, mbx_sm4_gcm_update_iv_mb16,(const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_state)) MBXAPI(mbx_status16, mbx_sm4_gcm_update_aad_mb16,(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_state)) MBXAPI(mbx_status16, mbx_sm4_gcm_encrypt_mb16,(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context)) MBXAPI(mbx_status16, mbx_sm4_gcm_decrypt_mb16,(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context)) MBXAPI(mbx_status16, mbx_sm4_gcm_get_tag_mb16,(int8u *pa_tag[SM4_LINES], const int tag_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context)) #endif /* SM4_GCM_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/status.h000066400000000000000000000102071470420105600303440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 STATUS_H #define STATUS_H #include typedef int32u mbx_status; typedef int64u mbx_status16; // error statuses and manipulators #define MBX_STATUS_OK (0) #define MBX_STATUS_MISMATCH_PARAM_ERR (1) #define MBX_STATUS_NULL_PARAM_ERR (2) #define MBX_STATUS_LOW_ORDER_ERR (4) #define MBX_STATUS_SIGNATURE_ERR (8) #define MBX_STATUS_UNSUPPORTED_ISA_ERR (10) __MBX_INLINE mbx_status MBX_SET_STS(mbx_status status, int numb, mbx_status sttVal) { numb &= 7; /* 0 <= numb < 8 */ status &= (mbx_status)(~(0xF << (numb*4))); return status |= (sttVal & 0xF) << (numb*4); } __MBX_INLINE mbx_status MBX_GET_STS(mbx_status status, int numb) { return (status >>(numb*4)) & 0xF; } __MBX_INLINE mbx_status MBX_SET_STS_ALL(mbx_status stsVal) { return (stsVal<<4*7) | (stsVal<<4*6) | (stsVal<<4*5) | (stsVal<<4*4) | (stsVal<<4*3) | (stsVal<<4*2) | (stsVal<<4*1) | stsVal; } __MBX_INLINE mbx_status MBX_SET_STS_BY_MASK(mbx_status status, int8u mask, mbx_status sttVal) { int numb; for(numb=0; numb<8; numb++) { mbx_status buf_stt = (0 - ((mask>>numb) &1)) & sttVal; status = MBX_SET_STS(status, numb, buf_stt); } return status; } __MBX_INLINE int MBX_IS_ANY_0_TO_3_OK_STS(const mbx_status status) { const int ret = MBX_STATUS_OK==MBX_GET_STS(status, 0) || MBX_STATUS_OK==MBX_GET_STS(status, 1) || MBX_STATUS_OK==MBX_GET_STS(status, 2) || MBX_STATUS_OK==MBX_GET_STS(status, 3); return ret; } __MBX_INLINE int MBX_IS_ANY_4_TO_7_OK_STS(const mbx_status status) { const int ret = MBX_STATUS_OK==MBX_GET_STS(status, 4) || MBX_STATUS_OK==MBX_GET_STS(status, 5) || MBX_STATUS_OK==MBX_GET_STS(status, 6) || MBX_STATUS_OK==MBX_GET_STS(status, 7); return ret; } __MBX_INLINE int MBX_IS_ANY_OK_STS(mbx_status status) { const int ret = MBX_IS_ANY_0_TO_3_OK_STS(status) || MBX_IS_ANY_4_TO_7_OK_STS(status); return (int) ret; } /* // Helpers for 64-bit status mbx_status16 */ /* Accessors for the low and high part of 64-bit status */ __MBX_INLINE mbx_status MBX_GET_HIGH_PART_STS16(mbx_status16 status16) { return ((mbx_status)(((mbx_status16)(status16) >> 32) & 0xFFFFFFFF)); } __MBX_INLINE mbx_status MBX_GET_LOW_PART_STS16(mbx_status16 status16) { return ((mbx_status)(status16)); } __MBX_INLINE mbx_status16 MBX_SET_STS16_ALL(mbx_status16 stsVal) { return (stsVal<<4*15) | (stsVal<<4*14) | (stsVal<<4*13) | (stsVal<<4*12) | (stsVal<<4*11) | (stsVal<<4*10) | (stsVal<<4*9) | (stsVal<<4*8) | \ (stsVal<<4*7) | (stsVal<<4*6) | (stsVal<<4*5) | (stsVal<<4*4) | (stsVal<<4*3) | (stsVal<<4*2) | (stsVal<<4*1) | stsVal; } __MBX_INLINE mbx_status16 MBX_SET_STS16(mbx_status16 status, int numb, mbx_status16 sttVal) { numb &= 15; /* 0 <= numb < 16 */ status &= (mbx_status16)(~((int64u)0xF << (numb*4))); return status |= (sttVal & 0xF) << (numb*4); } __MBX_INLINE mbx_status16 MBX_SET_STS16_BY_MASK(mbx_status16 status, int16u mask, mbx_status16 sttVal) { int numb; for (numb = 0; numb < 16; numb++) { mbx_status16 buf_stt = (0 - ((mask >> numb) & 1)) & sttVal; status = MBX_SET_STS16(status, numb, buf_stt); } return status; } __MBX_INLINE int MBX_IS_ANY_OK_STS16(mbx_status16 status) { return MBX_IS_ANY_OK_STS(MBX_GET_HIGH_PART_STS16(status)) || \ MBX_IS_ANY_OK_STS(MBX_GET_LOW_PART_STS16(status)); } #endif /* STATUS_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/version.h000066400000000000000000000031711470420105600305100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 VERSION_H #define VERSION_H #include /* crypto_mb name & version */ #define MBX_LIB_NAME() "crypto_mb" #define MBX_VER_MAJOR 1 #define MBX_VER_MINOR 0 #define MBX_VER_PATCH 0 /* major interface version */ #define MBX_INTERFACE_VERSION_MAJOR 12 /* minor interface version */ #define MBX_INTERFACE_VERSION_MINOR 0 typedef struct { int major; /* e.g. 1 */ int minor; /* e.g. 2 */ int patch; /* e.g. 3 */ char targetCpu[4]; /* corresponding to Intel® processor */ const char* name; /* e,g. "crypto_mb" */ const char* buildDate; /* e.g. "Oct 28 2019" */ const char* strVersion;/* e.g. "crypto_mb (ver 1.2.3 Oct 28 2019)" */ } mbxVersion; MBXAPI(const mbxVersion*, mbx_getversion,(void)) #endif /* VERSION_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/crypto_mb/x25519.h000066400000000000000000000023141470420105600276760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 X25519_H #define X25519_H #include #include MBXAPI(mbx_status, mbx_x25519_public_key_mb8,(int8u* const pa_public_key[8], const int8u* const pa_private_key[8])) MBXAPI(mbx_status, mbx_x25519_mb8,(int8u* const pa_shared_key[8], const int8u* const pa_private_key[8], const int8u* const pa_public_key[8])) #endif /* X25519_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/000077500000000000000000000000001470420105600264665ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/common/000077500000000000000000000000001470420105600277565ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/common/crypto_mb_ver.h000066400000000000000000000032451470420105600330050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #define STR2(x) #x #define STR(x) STR2(x) #define MBX_LIB_LONGNAME() "Crypto multi-buffer" #define MBX_LIB_SHORTNAME() "crypto_mb" #ifndef MBX_BASE_VERSION #define MBX_BASE_VERSION() MBX_VER_MAJOR,MBX_VER_MINOR,MBX_VER_PATCH #endif #define MBX_BUILD() 1043 #define MBX_VERSION() MBX_BASE_VERSION(),MBX_BUILD() #ifndef STR_MBX_BASE_VERSION #define STR_MBX_BASE_VERSION() STR(MBX_VER_MAJOR) "," STR(MBX_VER_MINOR) "," STR(MBX_VER_PATCH) #endif #define STR_FILE_MBX_VERSION() STR_MBX_BASE_VERSION()"," STR(MBX_BUILD()) #ifndef MBX_STR_VERSION #define MBX_STR_VERSION() STR(MBX_VER_MAJOR) "." STR(MBX_VER_MINOR) "." STR(MBX_VER_PATCH) " (" STR(MBX_INTERFACE_VERSION_MAJOR) "." STR(MBX_INTERFACE_VERSION_MINOR) ")" #endif #ifndef CRYPTO_MB_STR_VERSION #define CRYPTO_MB_STR_VERSION() MBX_STR_VERSION() #endif /* ////////////////////////////// End of file /////////////////////////////// */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/common/ifma_cvt52.h000066400000000000000000000056041470420105600320730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 IFMA_CVT52_H #define IFMA_CVT52_H #include #ifndef BN_OPENSSL_DISABLE #include #endif #include #if (_MBX >= _MBX_K1) // from 8 buffers regular (radix2^64) to mb8 redundant (radix 2^52) representation EXTERN_C int8u ifma_BNU_to_mb8(int64u out_mb8[][8], const int64u* const bn[8], int bitLen); EXTERN_C int8u ifma_HexStr8_to_mb8(int64u out_mb8[][8], const int8u* const pStr[8], int bitLen); #ifndef BN_OPENSSL_DISABLE EXTERN_C int8u ifma_BN_to_mb8(int64u res[][8], const BIGNUM* const bn[8], int bitLen); #endif // from 8 buffers mb8 redundant (radix 2^52) to regular (radix2^64) representation EXTERN_C int8u ifma_mb8_to_BNU(int64u* const out_bn[8], const int64u inp_mb8[][8], const int bitLen); EXTERN_C int8u ifma_mb8_to_HexStr8(int8u* const pStr[8], const int64u inp_mb8[][8], int bitLen); EXTERN_C int8u ifma_BNU_transpose_copy(int64u out_mb8[][8], const int64u* const inp[8], int bitLen); #ifndef BN_OPENSSL_DISABLE EXTERN_C int8u ifma_BN_transpose_copy(int64u out_mb8[][8], const BIGNUM* const inp[8], int bitLen); #endif /* BN_OPENSSL_DISABLE */ #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) // from 4 buffers regular (radix2^64) to mb4 redundant (radix 2^52) representation EXTERN_C int8u ifma_BNU_to_mb4(int64u out_mb4[][4], const int64u* const bn[4], int bitLen); EXTERN_C int8u ifma_HexStr4_to_mb4(int64u out_mb4[][4], const int8u* const pStr[4], int bitLen); #ifndef BN_OPENSSL_DISABLE EXTERN_C int8u ifma_BN_to_mb4(int64u res[][4], const BIGNUM* const bn[4], int bitLen); #endif // from 4 buffers mb8 redundant (radix 2^52) to regular (radix2^64) representation EXTERN_C int8u ifma_mb4_to_BNU(int64u* const out_bn[4], const int64u inp_mb4[][4], const int bitLen); EXTERN_C int8u ifma_mb4_to_HexStr4(int8u* const pStr[4], const int64u inp_mb4[][4], int bitLen); EXTERN_C int8u ifma_BNU_transpose_copy_mb4(int64u out_mb4[][4], const int64u* const inp[4], int bitLen); #ifndef BN_OPENSSL_DISABLE EXTERN_C int8u ifma_BN_transpose_copy_mb4(int64u out_mb4[][4], const BIGNUM* const inp[4], int bitLen); #endif /* BN_OPENSSL_DISABLE */ #endif /* #if (_MBX >= _MBX_K1) */ #endif /* IFMA_CVT52_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/common/ifma_defs.h000066400000000000000000000057251470420105600320550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 IFMA_DEFS_H #define IFMA_DEFS_H #include #include /* define DLL_EXPORT */ #if defined(__GNUC__) || defined(__CLANG__) #define DLL_PUBLIC __attribute__ ((visibility ("default"))) #define DLL_LOCAL __attribute__ ((visibility ("hidden"))) #else #define DLL_PUBLIC #define DLL_LOCAL #endif /* define optimization on/off VS2019 (>= 19.27) */ #if defined(_MSC_VER) && (_MSC_VER >= 1927) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) #define OPTIMIZE_OFF_VS19 _Pragma("optimize( \"\", off )") #define OPTIMIZE_ON_VS19 _Pragma("optimize( \"\", on )") #else #define OPTIMIZE_OFF_VS19 #define OPTIMIZE_ON_VS19 #endif /* define SIMD_LEN if not set (Default is 512 bit AVX) */ #ifndef SIMD_LEN #define SIMD_LEN 512 #endif #if ((SIMD_LEN != 512) && (SIMD_LEN != 256)) #error "Incorrect SIMD length" #endif /* internal function names */ #if (SIMD_LEN == 512) #define FUNC_SUFFIX mb8 #define MB_FUNC_NAME(name) name ## mb8 #else #define FUNC_SUFFIX mb4 #define MB_FUNC_NAME(name) name ## mb4 #endif #define SIMD_TYPE(LEN) typedef __m ## LEN ## i U64; /* max internal data bitsize */ #define IFMA_MAX_BITSIZE (4096) /* internal radix definition */ #define DIGIT_SIZE (52) #define DIGIT_BASE ((int64u)1< #include #if (SIMD_LEN == 512) SIMD_TYPE(512) typedef __mmask8 __mb_mask; #define SIMD_LEN 512 #define SIMD_BYTES (SIMD_LEN/8) #define MB_WIDTH (SIMD_LEN/64) __MBX_INLINE U64 loadu64(const void *p) { return _mm512_loadu_si512((U64*)p); } __MBX_INLINE U64 loadstream64(const void *p) { return _mm512_stream_load_si512 ((U64*)p); } __MBX_INLINE void storeu64(const void *p, U64 v) { _mm512_storeu_si512((U64*)p, v); } #define mask_mov64 _mm512_mask_mov_epi64 #define set64 _mm512_set1_epi64 __MBX_INLINE U64 fma52lo(U64 a, U64 b, U64 c) { return _mm512_madd52lo_epu64(a, b, c); } __MBX_INLINE U64 fma52hi(U64 a, U64 b, U64 c) { return _mm512_madd52hi_epu64(a, b, c); } __MBX_INLINE U64 mul52lo(U64 b, U64 c) { return _mm512_madd52lo_epu64(_mm512_setzero_si512(), b, c); } #ifdef __GNUC__ // memory ops intrinsics - force load from original buffer #define _mm512_madd52lo_epu64_(r, a, b, c, o) {\ r=a; \ __asm__ ( "vpmadd52luq " #o "(%2), %1, %0" : "+x" (r): "x" (b), "r" (c) ); \ } #define _mm512_madd52hi_epu64_(r, a, b, c, o) {\ r=a; \ __asm__ ( "vpmadd52huq " #o "(%2), %1, %0" : "+x" (r): "x" (b), "r" (c) ); \ } __MBX_INLINE U64 select64(__mb_mask k, U64 v, U64 *d) { __asm__("vmovdqu64 %2, %%zmm0 \n" "vpblendmq %%zmm0, %0, %0 %{%1%} \n" : "+v"(v) : "Yk"(k), "m"(*d) : "zmm0"); return v; } #else // Use IFMA intrinsics for all other compilers #define _mm512_madd52lo_epu64_(r, a, b, c, o) {\ r=fma52lo(a, b, _mm512_loadu_si512((U64*)(((char*)c)+o))); \ } #define _mm512_madd52hi_epu64_(r, a, b, c, o) {\ r=fma52hi(a, b, _mm512_loadu_si512((U64*)(((char*)c)+o))); \ } #pragma optimize("", off) __MBX_INLINE U64 select64(__mb_mask k, U64 v, U64 *d) { return _mm512_mask_blend_epi64(k, v, _mm512_load_si512(d)); } #pragma optimize("", on) #endif #define fma52lo_mem(r, a, b, c, o) _mm512_madd52lo_epu64_(r, a, b, c, o) // gres #define fma52hi_mem(r, a, b, c, o) _mm512_madd52hi_epu64_(r, a, b, c, o) // gres __MBX_INLINE U64 add64(U64 a, U64 b) { return _mm512_add_epi64(a, b); } __MBX_INLINE U64 sub64(U64 a, U64 b) { return _mm512_sub_epi64(a, b); } __MBX_INLINE U64 get_zero64() { return _mm512_setzero_si512(); } __MBX_INLINE void set_zero64(U64 *a) { *a = _mm512_xor_si512(*a, *a); } __MBX_INLINE U64 set1(unsigned long long a) { return _mm512_set1_epi64((long long)a); } __MBX_INLINE U64 srli64(U64 a, int s) { return _mm512_srli_epi64(a, s); } #define srai64 _mm512_srai_epi64 #define slli64 _mm512_slli_epi64 __MBX_INLINE U64 and64_const(U64 a, unsigned long long mask) { return _mm512_and_epi64(a, _mm512_set1_epi64((long long)mask)); } __MBX_INLINE U64 and64(U64 a, U64 mask) { return _mm512_and_epi64(a, mask); } #define or64 _mm512_or_epi64 #define xor64 _mm512_xor_epi64 #define cmp64_mask _mm512_cmp_epi64_mask #define cmpeq16_mask _mm512_cmpeq_epi16_mask #define cmpeq64_mask _mm512_cmpeq_epi64_mask // Mask operations #define mask_blend64 _mm512_mask_blend_epi64 #define mask_add64 _mm512_mask_add_epi64 #define mask_sub64 _mm512_mask_sub_epi64 #define maskz_sub64 _mm512_maskz_sub_epi64 __MBX_INLINE __mb_mask is_zero(U64* p, int len) { U64 Z = p[0]; for(int i = 1; i < len; i++) { Z = or64(Z, p[i]); } return cmpeq64_mask(Z, get_zero64()); } #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) // for MSVC #define mask_xor(m1,m2) (__mb_mask)(_mm512_kxor((m1),(m2))) #else #define mask_xor _kxor_mask8 #endif #define get_mask(a) (a) #define get_mask_value(a) (a) #define TRANSPOSE_8xI64x8(X0_, X1_ ,X2_ ,X3_ ,X4_ ,X5_ ,X6_ ,X7_) {\ __m512i X01L = _mm512_unpacklo_epi64(X0_, X1_); \ __m512i X23L = _mm512_unpacklo_epi64(X2_, X3_); \ __m512i X45L = _mm512_unpacklo_epi64(X4_, X5_); \ __m512i X67L = _mm512_unpacklo_epi64(X6_, X7_); \ \ __m512i X01H = _mm512_unpackhi_epi64(X0_, X1_); \ __m512i X23H = _mm512_unpackhi_epi64(X2_, X3_); \ __m512i X45H = _mm512_unpackhi_epi64(X4_, X5_); \ __m512i X67H = _mm512_unpackhi_epi64(X6_, X7_); \ \ __m512i X4567L, X0123L, X4567H, X0123H; \ X4567L = _mm512_shuffle_i64x2(X45L, X67L, 0b01000100 ); \ X0_ = _mm512_mask_shuffle_i64x2(X01L, 0b11111100, X23L, X4567L, 0b10000000 ); \ X2_ = _mm512_mask_shuffle_i64x2(X23L, 0b11110011, X01L, X4567L, 0b11010001 ); \ \ X0123L = _mm512_shuffle_i64x2(X01L, X23L, 0b11101110 ); \ X4_ = _mm512_mask_shuffle_i64x2(X45L, 0b11001111, X0123L, X67L, 0b10001000 ); \ X6_ = _mm512_mask_shuffle_i64x2(X67L, 0b00111111, X0123L, X45L, 0b10111101 ); \ \ X4567H = _mm512_shuffle_i64x2(X45H, X67H, 0b01000100 ); \ X1_ = _mm512_mask_shuffle_i64x2(X01H, 0b11111100, X23H, X4567H, 0b10000000 ); \ X3_ = _mm512_mask_shuffle_i64x2(X23H, 0b11110011, X01H, X4567H, 0b11010001 ); \ \ X0123H = _mm512_shuffle_i64x2(X01H, X23H, 0b11101110 ); \ X5_ = _mm512_mask_shuffle_i64x2(X45H, 0b11001111, X0123H, X67H, 0b10001000 ); \ X7_ = _mm512_mask_shuffle_i64x2(X67H, 0b00111111, X0123H, X45H, 0b10111101 ); \ } #elif (SIMD_LEN == 256) SIMD_TYPE(256) #if (defined(__GNUC__) && !defined(__clang__)) #define _mm_cvtsd_si64(_x) _mm_cvtsd_si64x(_x) #define _mm_cvtsi64_sd(_x, _y) _mm_cvtsi64x_sd((_x), (_y)) #elif defined(__clang__) // nothing for now here #elif defined(_MSC_VER) #define _mm_madd52hi_epu64 _mm_madd52hi_avx_epu64 #define _mm_madd52lo_epu64 _mm_madd52lo_avx_epu64 #define _mm256_madd52hi_epu64 _mm256_madd52hi_avx_epu64 #define _mm256_madd52lo_epu64 _mm256_madd52lo_avx_epu64 #else #error " wrappers need update for the compiler being used" #endif #else #error "Incorrect SIMD length" #endif // SIMD_LEN #endif // IFMA_MATH_H cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/common/internal_defs.h000066400000000000000000000026531470420105600327520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 INTERNAL_DEFS_H #define INTERNAL_DEFS_H #define _MBX_L9 1 #define _MBX_K1 2 #if defined( _L9 ) || (_K1) #include "ec_nistp256_cpuspc.h" #include "ec_nistp384_cpuspc.h" #include "ec_nistp521_cpuspc.h" #include "ec_sm2_cpuspc.h" #include "ed25519_cpuspc.h" #include "exp_cpuspc.h" #include "rsa_cpuspc.h" #include "sm3_cpuspc.h" #include "sm4_ccm_cpuspc.h" #include "sm4_cpuspc.h" #include "sm4_gcm_cpuspc.h" #include "x25519_cpuspc.h" #endif #if defined( _L9 ) /* Intel® AVX2 */ #define OWNAPI(name) l9_##name #define _MBX _MBX_L9 #elif defined( _K1 ) #define OWNAPI(name) k1_##name #define _MBX _MBX_K1 #endif #endif /* INTERNAL_DEFS_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/common/mem_fns.h000066400000000000000000000022541470420105600315560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021-2022 Intel Corporation * * 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. *************************************************************************/ /* * Auxiliary functions to set and copy memory */ __MBX_INLINE void CopyBlock(const void* pSrc, void* pDst, int numBytes) { const int8u* s = (int8u*)pSrc; int8u* d = (int8u*)pDst; int k; for (k = 0; k < numBytes; k++) d[k] = s[k]; } __MBX_INLINE void PadBlock(int8u paddingByte, void* pDst, int numBytes) { int8u* d = (int8u*)pDst; int k; for (k = 0; k < numBytes; k++) d[k] = paddingByte; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/000077500000000000000000000000001470420105600277535ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_arith_p256.h000066400000000000000000000150331470420105600330050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ARITH_P256_H #define IFMA_ARITH_P256_H #include #include #if (_MBX>=_MBX_K1) /* underlying prime's size */ #define P256_BITSIZE (256) /* lengths of FF elements */ #define P256_LEN52 NUMBER_OF_DIGITS(P256_BITSIZE,DIGIT_SIZE) #define P256_LEN64 NUMBER_OF_DIGITS(P256_BITSIZE,64) __ALIGN64 static const int64u ones[P256_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(1) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) } }; static const int64u VMASK52[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(DIGIT_MASK) }; #define NORM_LSHIFTR(R, I, J) \ R##J = add64(R##J, srli64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); #define NORM_ASHIFTR(R, I, J) \ R##J = add64(R##J, srai64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); /* set FE to zero */ __MBX_INLINE void MB_FUNC_NAME(zero_FE256_)(U64 T[]) { T[0] = T[1] = T[2] = T[3] = T[4] = get_zero64(); } /* check if FE is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_FE256_)(const U64 T[]) { U64 Z = or64(or64(T[0], T[1]), or64(or64(T[2], T[3]), T[4])); return cmpeq64_mask(Z, get_zero64()); } __MBX_INLINE U64 cmov_U64(U64 a, U64 b, __mb_mask kmask) { return mask_mov64 (a, kmask, b); } /* move field element */ __MBX_INLINE void MB_FUNC_NAME(mov_FE256_)(U64 r[], const U64 a[]) { r[0] = a[0]; r[1] = a[1]; r[2] = a[2]; r[3] = a[3]; r[4] = a[4]; } /* move coordinate using mask: R = k? A : B */ OPTIMIZE_OFF_VS19 __MBX_INLINE void MB_FUNC_NAME(mask_mov_FE256_)(U64 R[], const U64 B[], __mb_mask k, const U64 A[]) { R[0] = mask_mov64(B[0], k, A[0]); R[1] = mask_mov64(B[1], k, A[1]); R[2] = mask_mov64(B[2], k, A[2]); R[3] = mask_mov64(B[3], k, A[3]); R[4] = mask_mov64(B[4], k, A[4]); } __MBX_INLINE void MB_FUNC_NAME(secure_mask_mov_FE256_)(U64 R[], U64 B[], __mb_mask k, const U64 A[]) { R[0] = select64(k, B[0], (U64*)(&A[0])); R[1] = select64(k, B[1], (U64*)(&A[1])); R[2] = select64(k, B[2], (U64*)(&A[2])); R[3] = select64(k, B[3], (U64*)(&A[3])); R[4] = select64(k, B[4], (U64*)(&A[4])); } /* compare two FE */ __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_lt_FE256_)(const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); /* normalize r0 – r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) /* return mask LT */ return cmp64_mask(r4, get_zero64(), _MM_CMPINT_LT); } __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_eq_FE256_)(const U64 A[], const U64 B[]) { __ALIGN64 U64 msg[P256_LEN52]; msg[0] = xor64(A[0], B[0]); msg[1] = xor64(A[1], B[1]); msg[2] = xor64(A[2], B[2]); msg[3] = xor64(A[3], B[3]); msg[4] = xor64(A[4], B[4]); return MB_FUNC_NAME(is_zero_FE256_)(msg); } /* General 256-bit operations */ EXTERN_C void MB_FUNC_NAME(ifma_amm52x5_)(U64 R[], const U64 inpA[], const U64 inpB[], const U64 inpM[], const int64u* k0_mb); EXTERN_C void MB_FUNC_NAME(ifma_ams52x5_)(U64 r[], const U64 a[], const U64 m[], const int64u* k0_mb); EXTERN_C void MB_FUNC_NAME(ifma_add52x5_)(U64 R[], const U64 A[], const U64 B[], const U64 M[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52x5_)(U64 R[], const U64 A[], const U64 B[], const U64 M[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52x5_)(U64 R[], const U64 A[], const U64 M[]); /* Specialized operations over NIST P256 */ EXTERN_C void MB_FUNC_NAME(ifma_tomont52_p256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_p256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_p256_)(U64 r[], const U64 va[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_p256_)(U64 r[], const U64 va[], const U64 vb[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_p256_)(U64 r[], const U64 z[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_p256_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_p256_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_p256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_double52_p256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_tripple52_p256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_half52_p256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_p256_dual_)(U64 r0[], U64 r1[], const U64 inp0[], const U64 inp1[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_p256_dual_)(U64 r0[], U64 r1[], const U64 inp0A[], const U64 inp0B[], const U64 inp1A[], const U64 inp1B[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_p256_)(const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_p256_)(const U64 a[]); /* Specialized operations over EC NIST-P256 order */ EXTERN_C U64* MB_FUNC_NAME(ifma_n256_)(void); EXTERN_C void MB_FUNC_NAME(ifma_tomont52_n256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_n256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_n256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_n256_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_n256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_n256_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_n256_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_n256_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_fastred52_pn256_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_n256_)(const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_n256_)(const U64 a[]); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ARITH_P256_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_arith_p384.h000066400000000000000000000145561470420105600330200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ARITH_P384_H #define IFMA_ARITH_P384_H #include #include #if (_MBX>=_MBX_K1) /* underlying prime's size */ #define P384_BITSIZE (384) /* lengths of FF elements */ #define P384_LEN52 NUMBER_OF_DIGITS(P384_BITSIZE,DIGIT_SIZE) #define P384_LEN64 NUMBER_OF_DIGITS(P384_BITSIZE,64) __ALIGN64 static const int64u ones[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(1) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) } }; static const int64u VMASK52[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(DIGIT_MASK) }; #define NORM_LSHIFTR(R, I, J) \ R##J = add64(R##J, srli64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); #define NORM_ASHIFTR(R, I, J) \ R##J = add64(R##J, srai64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); /* set FE to zero */ __MBX_INLINE void MB_FUNC_NAME(zero_FE384_)(U64 T[]) { T[0] = T[1] = T[2] = T[3] = T[4] = T[5] = T[6] = T[7] = get_zero64(); } /* check if FE is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_FE384_)(const U64 T[]) { //U64 Z = or64(or64(or64(or64(or64(or64(or64(T[0], T[1]), T[2]), T[3]), T[4]), T[5]), T[6]), T[7]); U64 Z = or64(or64(or64(T[0], T[1]), or64(T[2], T[3])), or64(or64(T[4], T[5]), or64(T[6], T[7]))); return cmpeq64_mask(Z, get_zero64()); } __MBX_INLINE U64 cmov_U64(U64 a, U64 b, __mb_mask kmask) { return mask_mov64 (a, kmask, b); } /* move field element */ __MBX_INLINE void MB_FUNC_NAME(mov_FE384_)(U64 r[], const U64 a[]) { r[0] = a[0]; r[1] = a[1]; r[2] = a[2]; r[3] = a[3]; r[4] = a[4]; r[5] = a[5]; r[6] = a[6]; r[7] = a[7]; } /* move coordinate using mask: R = k? A : B */ OPTIMIZE_OFF_VS19 __MBX_INLINE void MB_FUNC_NAME(mask_mov_FE384_)(U64 R[], const U64 B[], __mb_mask k, const U64 A[]) { R[0] = mask_mov64(B[0], k, A[0]); R[1] = mask_mov64(B[1], k, A[1]); R[2] = mask_mov64(B[2], k, A[2]); R[3] = mask_mov64(B[3], k, A[3]); R[4] = mask_mov64(B[4], k, A[4]); R[5] = mask_mov64(B[5], k, A[5]); R[6] = mask_mov64(B[6], k, A[6]); R[7] = mask_mov64(B[7], k, A[7]); } __MBX_INLINE void MB_FUNC_NAME(secure_mask_mov_FE384_)(U64 R[], U64 B[], __mb_mask k, const U64 A[]) { R[0] = select64(k, B[0], (U64*)(&A[0])); R[1] = select64(k, B[1], (U64*)(&A[1])); R[2] = select64(k, B[2], (U64*)(&A[2])); R[3] = select64(k, B[3], (U64*)(&A[3])); R[4] = select64(k, B[4], (U64*)(&A[4])); R[5] = select64(k, B[5], (U64*)(&A[5])); R[6] = select64(k, B[6], (U64*)(&A[6])); R[7] = select64(k, B[7], (U64*)(&A[7])); } __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_lt_FE384_)(const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); U64 r5 = sub64(A[5], B[5]); U64 r6 = sub64(A[6], B[6]); U64 r7 = sub64(A[7], B[7]); /* normalize r0 – r7 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) /* return mask LT */ return cmp64_mask(r7, get_zero64(), _MM_CMPINT_LT); } /* compare two FE */ __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_eq_FE384_)(const U64 A[], const U64 B[]) { U64 T[P384_LEN52]; T[0] = xor64(A[0], B[0]); T[1] = xor64(A[1], B[1]); T[2] = xor64(A[2], B[2]); T[3] = xor64(A[3], B[3]); T[4] = xor64(A[4], B[4]); T[5] = xor64(A[5], B[5]); T[6] = xor64(A[6], B[6]); T[7] = xor64(A[7], B[7]); return MB_FUNC_NAME(is_zero_FE384_)(T); } /* Specialized operations over NIST P384 */ EXTERN_C void MB_FUNC_NAME(ifma_tomont52_p384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_p384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_p384_)(U64 r[], const U64 va[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_p384_)(U64 r[], const U64 va[], const U64 vb[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_p384_)(U64 r[], const U64 z[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_p384_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_p384_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_p384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_double52_p384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_tripple52_p384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_half52_p384_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_p384)(const U64 A[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_p384_)(const U64 a[]); /* Specialized operations over EC NIST-P384 order */ EXTERN_C U64* MB_FUNC_NAME(ifma_n384_)(void); EXTERN_C void MB_FUNC_NAME(ifma_tomont52_n384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_n384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_n384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_n384_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_n384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_n384_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_n384_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_n384_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_fastred52_pn384_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_n384)(const U64 A[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_n384_)(const U64 a[]); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ARITH_P384_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_arith_p521.h000066400000000000000000000156341470420105600330070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ARITH_P521_H #define IFMA_ARITH_P521_H #include #include #if (_MBX>=_MBX_K1) /* underlying prime's size */ #define P521_BITSIZE (521) /* lengths of FF elements */ #define P521_LEN52 NUMBER_OF_DIGITS(P521_BITSIZE,DIGIT_SIZE) #define P521_LEN64 NUMBER_OF_DIGITS(P521_BITSIZE,64) __ALIGN64 static const int64u ones[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(1) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) }, { REP8_DECL(0) } }; static const int64u VMASK52[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(DIGIT_MASK) }; #define NORM_LSHIFTR(R, I, J) \ R##J = add64(R##J, srli64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); #define NORM_ASHIFTR(R, I, J) \ R##J = add64(R##J, srai64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); /* set FE to zero */ __MBX_INLINE void MB_FUNC_NAME(zero_FE521_)(U64 T[]) { T[0] = T[1] = T[2] = T[3] = T[4] = T[5] = T[6] = T[7] = T[8] = T[9] = T[10] = get_zero64(); } /* check if FE is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_FE521_)(const U64 T[]) { U64 Z = or64(or64(or64(or64(T[0], T[1]), or64(T[2], T[3])), or64(or64(T[4], T[5]), or64(T[6], T[7]))), or64(or64(T[8], T[9]), T[10])); return cmpeq64_mask(Z, get_zero64()); } __MBX_INLINE U64 cmov_U64(U64 a, U64 b, __mb_mask kmask) { return mask_mov64 (a, kmask, b); } /* move field element */ __MBX_INLINE void MB_FUNC_NAME(mov_FE521_)(U64 r[], const U64 a[]) { r[0] = a[0]; r[1] = a[1]; r[2] = a[2]; r[3] = a[3]; r[4] = a[4]; r[5] = a[5]; r[6] = a[6]; r[7] = a[7]; r[8] = a[8]; r[9] = a[9]; r[10]= a[10]; } /* move coordinate using mask: R = k? A : B */ OPTIMIZE_OFF_VS19 __MBX_INLINE void MB_FUNC_NAME(mask_mov_FE521_)(U64 R[], const U64 B[], __mb_mask k, const U64 A[]) { R[0] = mask_mov64(B[0], k, A[0]); R[1] = mask_mov64(B[1], k, A[1]); R[2] = mask_mov64(B[2], k, A[2]); R[3] = mask_mov64(B[3], k, A[3]); R[4] = mask_mov64(B[4], k, A[4]); R[5] = mask_mov64(B[5], k, A[5]); R[6] = mask_mov64(B[6], k, A[6]); R[7] = mask_mov64(B[7], k, A[7]); R[8] = mask_mov64(B[8], k, A[8]); R[9] = mask_mov64(B[9], k, A[9]); R[10]= mask_mov64(B[10],k, A[10]); } __MBX_INLINE void MB_FUNC_NAME(secure_mask_mov_FE521_)(U64 R[], U64 B[], __mb_mask k, const U64 A[]) { R[0] = select64(k, B[0], (U64*)(&A[0])); R[1] = select64(k, B[1], (U64*)(&A[1])); R[2] = select64(k, B[2], (U64*)(&A[2])); R[3] = select64(k, B[3], (U64*)(&A[3])); R[4] = select64(k, B[4], (U64*)(&A[4])); R[5] = select64(k, B[5], (U64*)(&A[5])); R[6] = select64(k, B[6], (U64*)(&A[6])); R[7] = select64(k, B[7], (U64*)(&A[7])); R[8] = select64(k, B[8], (U64*)(&A[8])); R[9] = select64(k, B[9], (U64*)(&A[9])); R[10]= select64(k,B[10], (U64*)(&A[10])); } __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_lt_FE521_)(const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); U64 r5 = sub64(A[5], B[5]); U64 r6 = sub64(A[6], B[6]); U64 r7 = sub64(A[7], B[7]); U64 r8 = sub64(A[8], B[8]); U64 r9 = sub64(A[9], B[9]); U64 r10= sub64(A[10],B[10]); /* normalize r0 – r10 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9,10) /* return mask LT */ return cmp64_mask(r10, get_zero64(), _MM_CMPINT_LT); } __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_eq_FE521_)(const U64 A[], const U64 B[]) { U64 T[P521_LEN52]; T[0] = xor64(A[0], B[0]); T[1] = xor64(A[1], B[1]); T[2] = xor64(A[2], B[2]); T[3] = xor64(A[3], B[3]); T[4] = xor64(A[4], B[4]); T[5] = xor64(A[5], B[5]); T[6] = xor64(A[6], B[6]); T[7] = xor64(A[7], B[7]); T[8] = xor64(A[8], B[8]); T[9] = xor64(A[9], B[9]); T[10] = xor64(A[10], B[10]); return MB_FUNC_NAME(is_zero_FE521_)(T); } /* Specialized operations over NIST P521 */ EXTERN_C void MB_FUNC_NAME(ifma_tomont52_p521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_p521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_p521_)(U64 r[], const U64 va[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_p521_)(U64 r[], const U64 va[], const U64 vb[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_p521_)(U64 r[], const U64 z[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_p521_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_p521_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_p521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_double52_p521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_tripple52_p521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_half52_p521_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_p521_)(const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_p521_)(const U64 a[]); /* Specialized operations over EC NIST-P521 order */ EXTERN_C U64* MB_FUNC_NAME(ifma_n521_)(void); EXTERN_C void MB_FUNC_NAME(ifma_tomont52_n521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_n521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_n521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_n521_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_n521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_n521_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_n521_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_n521_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_fastred52_pn521_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_n521_)(const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_n521_)(const U64 a[]); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ARITH_P521_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecpoint_p256.h000066400000000000000000000225521470420105600333430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPOINT_P256_H #define IFMA_ECPOINT_P256_H #include "crypto_mb/status.h" #include #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* BN_OPENSSL_DISABLE */ #if (_MBX>=_MBX_K1) typedef struct { U64 X[P256_LEN52]; U64 Y[P256_LEN52]; U64 Z[P256_LEN52]; } P256_POINT; typedef struct { U64 x[P256_LEN52]; U64 y[P256_LEN52]; } P256_POINT_AFFINE; typedef struct { int64u x[P256_LEN52]; int64u y[P256_LEN52]; } SINGLE_P256_POINT_AFFINE; /* check if coordinate is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_point_cordinate_)(const U64 T[]) { return MB_FUNC_NAME(is_zero_FE256_)(T); } /* set point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_to_infinity_)(P256_POINT* r) { r->X[0] = r->X[1] = r->X[2] = r->X[3] = r->X[4] = get_zero64(); r->Y[0] = r->Y[1] = r->Y[2] = r->Y[3] = r->Y[4] = get_zero64(); r->Z[0] = r->Z[1] = r->Z[2] = r->Z[3] = r->Z[4] = get_zero64(); } /* set point to infinity by mask */ __MBX_INLINE void MB_FUNC_NAME(mask_set_point_to_infinity_)(P256_POINT* r, __mb_mask mask) { U64 zeros = get_zero64(); r->X[0] = mask_mov64(r->X[0], mask, zeros); r->X[1] = mask_mov64(r->X[1], mask, zeros); r->X[2] = mask_mov64(r->X[2], mask, zeros); r->X[3] = mask_mov64(r->X[3], mask, zeros); r->X[4] = mask_mov64(r->X[4], mask, zeros); r->Y[0] = mask_mov64(r->Y[0], mask, zeros); r->Y[1] = mask_mov64(r->Y[1], mask, zeros); r->Y[2] = mask_mov64(r->Y[2], mask, zeros); r->Y[3] = mask_mov64(r->Y[3], mask, zeros); r->Y[4] = mask_mov64(r->Y[4], mask, zeros); r->Z[0] = mask_mov64(r->Z[0], mask, zeros); r->Z[1] = mask_mov64(r->Z[1], mask, zeros); r->Z[2] = mask_mov64(r->Z[2], mask, zeros); r->Z[3] = mask_mov64(r->Z[3], mask, zeros); r->Z[4] = mask_mov64(r->Z[4], mask, zeros); } /* set affine point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_affine_to_infinity_)(P256_POINT_AFFINE* r) { r->x[0] = r->x[1] = r->x[2] = r->x[3] = r->x[4] = get_zero64(); r->y[0] = r->y[1] = r->y[2] = r->y[3] = r->y[4] = get_zero64(); } EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(P256_POINT* r, const P256_POINT* p); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp256_add_point_)(P256_POINT* r, const P256_POINT* p, const P256_POINT* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp256_add_point_affine_)(P256_POINT* r, const P256_POINT* p, const P256_POINT_AFFINE* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp256_mul_point_)(P256_POINT* r, const P256_POINT* p, const U64* scalar); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp256_mul_pointbase_)(P256_POINT* r, const U64* scalar); EXTERN_C void MB_FUNC_NAME(get_nistp256_ec_affine_coords_)(U64 x[], U64 y[], const P256_POINT* P); EXTERN_C const U64* MB_FUNC_NAME(ifma_ec_nistp256_coord_one_)(void); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_is_on_curve_p256_)(const P256_POINT* p, int use_jproj_coords); #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_mbx_nistp256_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp256_ecdsa_sign_setup_ssl_mb8(BIGNUM* pa_inv_skey[8], BIGNUM* pa_sign_rp[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp256_ecdsa_sign_complete_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sign_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp256_ecdsa_sign_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp256_ecdsa_verify_ssl_mb8(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp256_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* BN_OPENSSL_DISABLE */ mbx_status internal_avx512_nistp256_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp256_ecdsa_sign_setup_mb8(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp256_ecdsa_sign_complete_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp256_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp256_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp256_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPOINT_P256_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecpoint_p384.h000066400000000000000000000247331470420105600333500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPOINT_P384_H #define IFMA_ECPOINT_P384_H #include "crypto_mb/status.h" #include #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* BN_OPENSSL_DISABLE */ #if (_MBX>=_MBX_K1) typedef struct { U64 X[P384_LEN52]; U64 Y[P384_LEN52]; U64 Z[P384_LEN52]; } P384_POINT; typedef struct { U64 x[P384_LEN52]; U64 y[P384_LEN52]; } P384_POINT_AFFINE; typedef struct { int64u x[P384_LEN52]; int64u y[P384_LEN52]; } SINGLE_P384_POINT_AFFINE; /* check if coordinate is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_point_cordinate_)(const U64 T[]) { return MB_FUNC_NAME(is_zero_FE384_)(T); } /* set point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_to_infinity_)(P384_POINT* r) { r->X[0] = r->X[1] = r->X[2] = r->X[3] = r->X[4] = r->X[5] = r->X[6] = r->X[7] = get_zero64(); r->Y[0] = r->Y[1] = r->Y[2] = r->Y[3] = r->Y[4] = r->Y[5] = r->Y[6] = r->Y[7] = get_zero64(); r->Z[0] = r->Z[1] = r->Z[2] = r->Z[3] = r->Z[4] = r->Z[5] = r->Z[6] = r->Z[7] = get_zero64(); } /* set point to infinity by mask */ __MBX_INLINE void MB_FUNC_NAME(mask_set_point_to_infinity_)(P384_POINT* r, __mb_mask mask) { U64 zeros = get_zero64(); r->X[0] = mask_mov64(r->X[0], mask, zeros); r->X[1] = mask_mov64(r->X[1], mask, zeros); r->X[2] = mask_mov64(r->X[2], mask, zeros); r->X[3] = mask_mov64(r->X[3], mask, zeros); r->X[4] = mask_mov64(r->X[4], mask, zeros); r->X[5] = mask_mov64(r->X[5], mask, zeros); r->X[6] = mask_mov64(r->X[6], mask, zeros); r->X[7] = mask_mov64(r->X[7], mask, zeros); r->Y[0] = mask_mov64(r->Y[0], mask, zeros); r->Y[1] = mask_mov64(r->Y[1], mask, zeros); r->Y[2] = mask_mov64(r->Y[2], mask, zeros); r->Y[3] = mask_mov64(r->Y[3], mask, zeros); r->Y[4] = mask_mov64(r->Y[4], mask, zeros); r->Y[5] = mask_mov64(r->Y[5], mask, zeros); r->Y[6] = mask_mov64(r->Y[6], mask, zeros); r->Y[7] = mask_mov64(r->Y[7], mask, zeros); r->Z[0] = mask_mov64(r->Z[0], mask, zeros); r->Z[1] = mask_mov64(r->Z[1], mask, zeros); r->Z[2] = mask_mov64(r->Z[2], mask, zeros); r->Z[3] = mask_mov64(r->Z[3], mask, zeros); r->Z[4] = mask_mov64(r->Z[4], mask, zeros); r->Z[5] = mask_mov64(r->Z[5], mask, zeros); r->Z[6] = mask_mov64(r->Z[6], mask, zeros); r->Z[7] = mask_mov64(r->Z[7], mask, zeros); } /* set affine point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_affine_to_infinity_)(P384_POINT_AFFINE* r) { r->x[0] = r->x[1] = r->x[2] = r->x[3] = r->x[4] = r->x[5] = r->x[6] = r->x[7] = get_zero64(); r->y[0] = r->y[1] = r->y[2] = r->y[3] = r->y[4] = r->y[5] = r->y[6] = r->y[7] = get_zero64(); } EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(P384_POINT* r, const P384_POINT* p); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp384_add_point_)(P384_POINT* r, const P384_POINT* p, const P384_POINT* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp384_add_point_affine_)(P384_POINT* r, const P384_POINT* p, const P384_POINT_AFFINE* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp384_mul_point_)(P384_POINT* r, const P384_POINT* p, const U64* scalar); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp384_mul_pointbase_)(P384_POINT* r, const U64* scalar); EXTERN_C void MB_FUNC_NAME(get_nistp384_ec_affine_coords_)(U64 x[], U64 y[], const P384_POINT* P); EXTERN_C const U64* MB_FUNC_NAME(ifma_ec_nistp384_coord_one_)(void); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_is_on_curve_p384_)(const P384_POINT* p, int use_jproj_coords); #ifndef BN_OPENSSL_DISABLE EXTERN_C mbx_status internal_avx512_nistp384_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_sign_setup_ssl_mb8(BIGNUM* pa_inv_skey[8], BIGNUM* pa_sign_rp[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_sign_complete_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sign_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_sign_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_verify_ssl_mb8(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); EXTERN_C mbx_status internal_avx512_nistp384_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* BN_OPENSSL_DISABLE */ EXTERN_C mbx_status internal_avx512_nistp384_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_sign_setup_mb8(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_sign_complete_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer); EXTERN_C mbx_status internal_avx512_nistp384_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); EXTERN_C mbx_status internal_avx512_nistp384_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPOINT_P384_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecpoint_p521.h000066400000000000000000000247661470420105600333470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPOINT_P521_H #define IFMA_ECPOINT_P521_H #include "crypto_mb/status.h" #include #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* BN_OPENSSL_DISABLE */ #if (_MBX>=_MBX_K1) typedef struct { U64 X[P521_LEN52]; U64 Y[P521_LEN52]; U64 Z[P521_LEN52]; } P521_POINT; typedef struct { U64 x[P521_LEN52]; U64 y[P521_LEN52]; } P521_POINT_AFFINE; typedef struct { int64u x[P521_LEN52]; int64u y[P521_LEN52]; } SINGLE_P521_POINT_AFFINE; /* check if coordinate is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_point_cordinate_)(const U64 T[]) { return MB_FUNC_NAME(is_zero_FE521_)(T); } /* set point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_to_infinity_)(P521_POINT* r) { r->X[0] = r->X[1] = r->X[2] = r->X[3] = r->X[4] = r->X[5] = r->X[6] = r->X[7] = r->X[8] = r->X[9] = r->X[10] = get_zero64(); r->Y[0] = r->Y[1] = r->Y[2] = r->Y[3] = r->Y[4] = r->Y[5] = r->Y[6] = r->Y[7] = r->Y[8] = r->Y[9] = r->Y[10] = get_zero64(); r->Z[0] = r->Z[1] = r->Z[2] = r->Z[3] = r->Z[4] = r->Z[5] = r->Z[6] = r->Z[7] = r->Z[8] = r->Z[9] = r->Z[10] = get_zero64(); } /* set point to infinity by mask */ __MBX_INLINE void MB_FUNC_NAME(mask_set_point_to_infinity_)(P521_POINT* r, __mb_mask mask) { U64 zeros = get_zero64(); r->X[0] = mask_mov64(r->X[0], mask, zeros); r->X[1] = mask_mov64(r->X[1], mask, zeros); r->X[2] = mask_mov64(r->X[2], mask, zeros); r->X[3] = mask_mov64(r->X[3], mask, zeros); r->X[4] = mask_mov64(r->X[4], mask, zeros); r->X[5] = mask_mov64(r->X[5], mask, zeros); r->X[6] = mask_mov64(r->X[6], mask, zeros); r->X[7] = mask_mov64(r->X[7], mask, zeros); r->X[8] = mask_mov64(r->X[8], mask, zeros); r->X[9] = mask_mov64(r->X[9], mask, zeros); r->X[10]= mask_mov64(r->X[10],mask, zeros); r->Y[0] = mask_mov64(r->Y[0], mask, zeros); r->Y[1] = mask_mov64(r->Y[1], mask, zeros); r->Y[2] = mask_mov64(r->Y[2], mask, zeros); r->Y[3] = mask_mov64(r->Y[3], mask, zeros); r->Y[4] = mask_mov64(r->Y[4], mask, zeros); r->Y[5] = mask_mov64(r->Y[5], mask, zeros); r->Y[6] = mask_mov64(r->Y[6], mask, zeros); r->Y[7] = mask_mov64(r->Y[7], mask, zeros); r->Y[8] = mask_mov64(r->Y[8], mask, zeros); r->Y[9] = mask_mov64(r->Y[9], mask, zeros); r->Y[10]= mask_mov64(r->Y[10],mask, zeros); r->Z[0] = mask_mov64(r->Z[0], mask, zeros); r->Z[1] = mask_mov64(r->Z[1], mask, zeros); r->Z[2] = mask_mov64(r->Z[2], mask, zeros); r->Z[3] = mask_mov64(r->Z[3], mask, zeros); r->Z[4] = mask_mov64(r->Z[4], mask, zeros); r->Z[5] = mask_mov64(r->Z[5], mask, zeros); r->Z[6] = mask_mov64(r->Z[6], mask, zeros); r->Z[7] = mask_mov64(r->Z[7], mask, zeros); r->Z[8] = mask_mov64(r->Z[8], mask, zeros); r->Z[9] = mask_mov64(r->Z[9], mask, zeros); r->Z[10]= mask_mov64(r->Z[10],mask, zeros); } /* set affine point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_affine_to_infinity_)(P521_POINT_AFFINE* r) { r->x[0] = r->x[1] = r->x[2] = r->x[3] = r->x[4] = r->x[5] = r->x[6] = r->x[7] = r->x[8] = r->x[9] = r->x[10] = get_zero64(); r->y[0] = r->y[1] = r->y[2] = r->y[3] = r->y[4] = r->y[5] = r->y[6] = r->y[7] = r->y[8] = r->y[9] = r->y[10] = get_zero64(); } EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(P521_POINT* r, const P521_POINT* p); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp521_add_point_)(P521_POINT* r, const P521_POINT* p, const P521_POINT* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp521_add_point_affine_)(P521_POINT* r, const P521_POINT* p, const P521_POINT_AFFINE* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp521_mul_point_)(P521_POINT* r, const P521_POINT* p, const U64* scalar); EXTERN_C void MB_FUNC_NAME(ifma_ec_nistp521_mul_pointbase_)(P521_POINT* r, const U64* scalar); EXTERN_C void MB_FUNC_NAME(get_nistp521_ec_affine_coords_)(U64 x[], U64 y[], const P521_POINT* P); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_is_on_curve_p521_)(const P521_POINT* p, int use_jproj_coords); #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp521_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp521_ecdsa_sign_setup_ssl_mb8(BIGNUM* pa_inv_skey[8], BIGNUM* pa_sign_rp[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp521_ecdsa_sign_complete_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sign_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp521_ecdsa_sign_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp521_ecdsa_verify_ssl_mb8(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp521_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* BN_OPENSSL_DISABLE */ mbx_status internal_avx512_nistp521_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp521_ecdsa_sign_setup_mb8(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp521_ecdsa_sign_complete_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp521_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer); mbx_status internal_avx512_nistp521_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_nistp521_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPOINT_P521_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecprecomp4_p256.h000066400000000000000000003242361470420105600337470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPRECOMP4_P256_H #define IFMA_ECPRECOMP4_P256_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (4) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_SLOTS NUMBER_OF_DIGITS(P256_BITSIZE+1,BP_WIN_SIZE) #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static SINGLE_P256_POINT_AFFINE ifma_ec_nistp256_bp_precomp[][BP_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x00030d418a9143c1,0x000c4fedb60179e7,0x00062251075ba95f,0x0005c669fb732b77,0x00008905f76b5375}, {0x0005357ce95560a8,0x00043a19e45cddf2,0x00021f3258b4ab8e,0x000d8552e88688dd,0x0000571ff18a5885}}, {{0x00046d410ddd64df,0x0000b433827d8500,0x0001490d9aa6ae3c,0x000a3a832205038d,0x00006bb32e52dcf3}, {0x00048d361bee1a57,0x000b7b236ff82f36,0x000042dbe152cd7c,0x000a3aa9a8fb0e92,0x00008c577517a5b8}}, {{0x0003f904eebc1272,0x0009e87d81fbffac,0x000cbbc98b027f84,0x00047e46ad77dd87,0x00006936a3fd6ff7}, {0x0005c1fc983a7ebd,0x000c3861fe1ab04c,0x0002ee98e583e47a,0x000c06a88208311a,0x00005f06a2ab587c}}, {{0x000b50d46918dcc5,0x000d7623c17374b0,0x000100af24650a6e,0x00076abcdaacace8,0x000077362f591b01}, {0x000f24ce4cbaba68,0x00017ad6f4472d96,0x000ddd22e1762847,0x000862eb6c36dee5,0x00004b14c39cc5ab}}, {{0x0008aaec45c61f5c,0x0009d4b9537dbe1b,0x00076c20c90ec649,0x0003c7d41cb5aad0,0x0000907960649052}, {0x0009b4ae7ba4f107,0x000f75eb882beb30,0x0007a1f6873c568e,0x000915c540a9877e,0x00003a076bb9dd1e}}, {{0x00047373e77664a1,0x000f246cee3e4039,0x00017a3ad55ae744,0x000673c50a961a5b,0x00003074b5964213}, {0x0006220d377e44ba,0x00030dff14b593d3,0x000639f11299c2b5,0x00075f5424d44cef,0x00004c9916dea07f}}, {{0x000354ea0173b4f1,0x0003c23c00f70746,0x00023bb082bd2021,0x000e03e43eaab50c,0x00003ba5119d3123}, {0x000d0303f5b9d4de,0x00017da67bdd2847,0x000c941956742f2f,0x0008670f933bdc77,0x0000aedd9164e240}}, {{0x0004cd19499a78fb,0x0004bf9b345527f1,0x0002cfc6b462ab5c,0x00030cdf90f02af0,0x0000763891f62652}, {0x000a3a9532d49775,0x000d7f9eba15f59d,0x00060bbf021e3327,0x000f75c23c7b84be,0x00006ec12f2c706d}}, }, {/* digit=1 [{1,2,3,..,}]*([2^4]*G) */ {{0x0000b650bc6fb805,0x0004effe2e6b808b,0x00083f5495882e07,0x00072385ef2f7c2c,0x00004d63c80e103b}, {0x0001bd652a23f9b6,0x0008eb0b6587f2f1,0x000580e9e3670c31,0x00021ff5c4623bb1,0x00004edf7b261efe}}, {{0x000fccfc5e3a3d83,0x000c1079dfbfd8c5,0x000ad0197befd904,0x0002a48c6d6a58fe,0x0000922707799553}, {0x0003e6ddbef42f56,0x0003e80a990809e2,0x0009a2e407e449b6,0x0002a41b969c1aad,0x0000231d792f591c}}, {{0x000413077adc612c,0x0008fbd803a06b34,0x0008805bda749652,0x0003ac5a1baaa76d,0x0000840390307034}, {0x0009f66175adff18,0x000b37d8c5b739f5,0x0009d75e30b26d7f,0x000cc22875f5ce52,0x00005efc7e9c1325}}, {{0x00096f305968b809,0x0002789f73b9db6d,0x000c61e01380a091,0x0008c6eda70b83c2,0x00005fb8394e69b3}, {0x000651280edfe2f2,0x00096faeaf829a3c,0x000424bf88f726bb,0x0009706010a4a078,0x000096720442e844}}, {{0x000dc0752b3e584c,0x0007f5f86a2c492b,0x0007de57335ff9aa,0x0003296074213db2,0x00000bfffc512638}, {0x000c22a1d49c6052,0x00059320ebfb2429,0x00020f4281b037d7,0x00066032b6a17392,0x0000995919cc4cd2}}, {{0x0008d2333e12b701,0x000b09dd329b802b,0x000bc354d6d490a4,0x000a0d04f356cc6a,0x00001eddf7fe0a0d}, {0x0008328d87fd1d83,0x000ccd0258131e20,0x00029bca2fd2f4f8,0x000b70d3b48cc47c,0x0000f2a78b3541a2}}, {{0x00005760a99cbca7,0x000594a428f26a95,0x00032ba0c94e258f,0x000166d5ab5a4d78,0x00001704d00f938c}, {0x000ab0ef88b8b706,0x000e600eb207db97,0x000367d8056feb92,0x000a41870352687d,0x00005000c2527973}}, {{0x000cb817a2ad62aa,0x00090c62ff5463c5,0x000ad9db57ef2b6b,0x0006169749bba4b3,0x0000d311f2ce6d5a}, {0x0008087c2ff3b6df,0x0002467834ffb77a,0x000d6b138b46feaf,0x00018808aa266d75,0x0000a38d321dc008}}, }, {/* digit=2 [{1,2,3,..,}]*([2^8]*G) */ {{0x0008ffa696946fc7,0x000849cba56d486d,0x000f35a1550fbc6d,0x00062c0e3d423e90,0x0000c3da19630dd9}, {0x000fdb03cfd5d8b3,0x0002589dfca5e673,0x0002305aa0704b7c,0x000e53c6ce581ff5,0x000099d49ebc14d5}}, {{0x0008110399492969,0x000aa61db1b544e3,0x0006eaff55b63827,0x00028fae5323ed20,0x000042370d3521f4}, {0x000af2ee0d985a17,0x000b0239846df2ca,0x0006312f8192cc64,0x0001080c0b8f47ae,0x0000dc61f9206620}}, {{0x000a53eed4c37174,0x000efd0ed2a335d6,0x000543aa59f8240c,0x0004b44c0d4d05e5,0x00005d5bbfc1d33b}, {0x000cc73137fd28e3,0x000f973b3ffdfa04,0x000f51ef2862ac6e,0x0005a2103ff9f531,0x00004d5e0fcec73f}}, {{0x00081e144cc3adda,0x0005e7be82cf4f70,0x000dd6472d5ffa1d,0x000862e9890b6c0e,0x0000da26e1aded17}, {0x000271563483caaf,0x00083f6077fd276f,0x000466e3ce6924cd,0x000d1e15a7fe980a,0x00001c794b1a1902}}, {{0x000385c08369a907,0x000aa90eb4f833b2,0x0008eac802990c59,0x000014119a6145c6,0x0000a786d629ec4a}, {0x000adbe20ac3a8dd,0x00008aba2d3033fa,0x000a4f56531a2178,0x000fba509d2742db,0x0000b2ce9e425aa0}}, {{0x0006bf38bd7aff18,0x000a9d81b146b315,0x00028a9151b5ee4c,0x00099dfba1ac41d6,0x0000f3a8f9d7d896}, {0x000b9c9a0748be7d,0x0004d92e621f7329,0x00010a8371d391c9,0x000435151e6b214d,0x0000255f53b1947b}}, {{0x00058d474a861082,0x000fce4c5d900c4a,0x0006d4c80f8048a8,0x000e60c3c7c924e8,0x00008c889de256a1}, {0x000662eb214a040f,0x000747e1034757e2,0x000ac748ae8c48e9,0x0006f19774286280,0x00001c24023086b0}}, {{0x00024b9eb7926b83,0x00039dbe55093d2b,0x000dd640bbff88cb,0x000d45a0f399afe4,0x0000c5fe1305f76e}, {0x00062f43764fb3df,0x00074151b62d6f35,0x0009ce5f37b5af31,0x00090ee5bd0bc7d7,0x0000daf6b21dc668}}, }, {/* digit=3 [{1,2,3,..,}]*([2^12]*G) */ {{0x000b0e5ab4b35a24,0x0001b5eeaacf6772,0x0005b95801d8b600,0x0001da328f7ce479,0x0000a20ed2a81fb8}, {0x0005cd44fec01e63,0x000c77ff50ad9f68,0x0002d97fd3ed7ddc,0x0004f9160fd2640c,0x0000a2414271b82f}}, {{0x0009862d5d721d5b,0x0002abd3a1828000,0x000a2cda40c3357a,0x00008477f3a83b7a,0x000058ae74fa6f83}, {0x0001a812e6dad6be,0x0001143d6c5b2a91,0x00096c4d8de28605,0x00024d6bdccc41f9,0x00007312ec0eae1e}}, {{0x00068feaae6ee702,0x00053602b0c96faf,0x00094052a78f4cc1,0x000d805e3321a86e,0x0000fb3a0d6934d5}, {0x0008f3bb25a43ba1,0x000109ee2951f3b9,0x000b0612a30bf803,0x0001d06ffee43321,0x00002f775e43eb82}}, {{0x00012e76e6485b37,0x000b071c52f8f8d1,0x0004a2f6d4d3e24d,0x000550d8e3ee4168,0x0000161957d91d95}, {0x0001283cdb12a6c3,0x0001fe50e1641963,0x00066cc73bf3fa88,0x000c38c6254b6331,0x0000aefa7aedee8c}}, {{0x000008037a929a9e,0x000d39fec6bd46f7,0x000ab8b6265601a8,0x0000ce737f5edc12,0x0000497cd963e599}, {0x000387f9aa5b2f93,0x000f37b78fe82fcd,0x0005d5e30e5faa3f,0x0007ebebcf538d29,0x0000a573239d813a}}, {{0x000286bd17c24093,0x000333264d9be9f5,0x000f6880f2c4e479,0x000e42e77042b117,0x00009b7e2c87ce1e}, {0x000e722d096f4a9c,0x000afed5e697cec8,0x0002319116861aec,0x00037a02d153f06c,0x0000c2f42b8e8905}}, {{0x000cb51d0a917b49,0x0002b899f93133e2,0x000a2f6b6c2cfa3f,0x0002b722c94f4be9,0x0000707b1820ca16}, {0x000a172d5f8b10d2,0x00052fd4542ab602,0x000996992fd30783,0x0005e1cef226dddd,0x000021fa98a0b0a1}}, {{0x000fe623b36f9fd2,0x0003dde19fc079b0,0x0008482ef26543b2,0x000824f36e64a095,0x00003f63771bb095}, {0x000d596b6a1142e5,0x0005e35aac0b14cf,0x000081dd55ea6aac,0x00012a36a0e8bdf3,0x0000fb89d79503dc}}, }, {/* digit=4 [{1,2,3,..,}]*([2^16]*G) */ {{0x00065fce3779ee34,0x000d7d495d9e0f01,0x000284e7ae00e7f9,0x000218dfa4efa220,0x0000564bade87ac6}, {0x000312ac4708e8e4,0x000b671e9adf90e6,0x000684b9f4f5725f,0x000415a95f55ae3d,0x00007f7ccb15e94b}}, {{0x000890361a341c13,0x000fdcfd61423617,0x00033316c3604dc5,0x000921d22295eb85,0x0000dbde4ac74af2}, {0x000fc5d1c7eef696,0x0005714f4fa1898a,0x0003c21ca5889680,0x00030aa500216020,0x0000f0d1f30a0ef7}}, {{0x0008b1dbe7a2af37,0x0008dfb74a72bd9b,0x000879697ec51caa,0x0007d549937a4b63,0x0000c9a9d215c268}, {0x000e44f6ef5f0145,0x0002990c69001773,0x00042161e8abcf41,0x000f29e87bd02281,0x000003937564cb6f}}, {{0x000770977f7195ad,0x0006ddeb838ffabf,0x0004f012d8ec8616,0x000b3f1a1285a8bb,0x000068835046a3ea}, {0x00024f8309004c28,0x000593ffe95eee5d,0x000223ea4a96e4b7,0x000a528cdffe12bd,0x0000f5c2ee636739}}, {{0x000333959145a65f,0x00080a4063373d61,0x0008a52a0cd9bc36,0x00058f92d11be32d,0x00006877b2887a1c}, {0x000819bf5cbdb258,0x00085e090249837a,0x000990e5f2a4fd1d,0x00011ae22a7de774,0x000040fa5a0f9455}}, {{0x00090b36b0cf82eb,0x00057615b5e7e58e,0x0009c145a6438d24,0x0001ca57b1f8fc66,0x00000d8b2dae6f1e}, {0x000dadbd9184c4d2,0x0005d93d997654d5,0x000147d473dbb18d,0x000608ea3e0f56d1,0x0000afa8c8dc0a48}}, {{0x0008c07e3533d77b,0x00097e341c9926e0,0x0002dc4edd7222e6,0x000cf7ed60ec3d8d,0x0000dfe0d902c476}, {0x0009ab61d056605f,0x000596a8551f1fe5,0x000fb8d8ca9ea9df,0x000b0f9489941e47,0x0000eb874ec3a7f1}}, {{0x0006aa9bd7638026,0x000005303da1ed40,0x000e62ec4c21486a,0x00033e01ae291ec7,0x000022a04933f993}, {0x0000c9dbb7a8ee0d,0x000b9c01aedb7fd8,0x000be74ecdc2ed3b,0x00071e65c35a1208,0x0000540cb1b169f6}}, }, {/* digit=5 [{1,2,3,..,}]*([2^20]*G) */ {{0x000746a584c5e205,0x000169dc7035a7a8,0x000548c9b267e4ea,0x0002f3093a15cfb9,0x0000e6e21359bd01}, {0x000cc6a8c8f936e6,0x000455c241dcdf31,0x0005efb868af84d0,0x0002cb03990a6f34,0x0000fef4e6219b96}}, {{0x0008f09257226088,0x000a931cf5c6f636,0x000b4f7ac131260d,0x000828c0eb353bfa,0x00005c78880b7eee}, {0x00081ffc3bdf24eb,0x000b45c3c5a84c15,0x0004e6f405bff75c,0x0000c985e8c83fa1,0x000081d1c0fb295e}}, {{0x000e23d442a8ad11,0x000cf6b9c164f2ef,0x0000aa5e5c3816a7,0x000e6599df2d8bdc,0x000091ae46f220a8}, {0x0007f8700611c5bf,0x00070f1099488366,0x00069595283171ed,0x000a1243a2ecf8ca,0x0000a4a73efe48d1}}, {{0x0007cc8f43a730f8,0x000bb3ab590efcde,0x00003240be89b6f3,0x0005db4823f529ad,0x00002b79aff18bea}, {0x0002856962fe5de3,0x000b30c591f3568f,0x00028a8580c590ad,0x000f4befc74a144a,0x0000b662498e3203}}, {{0x0004ed082dd1b6ad,0x000797b703af48fc,0x0005d6aaa5783a13,0x000d425463cb9a00,0x000031ec55d406ec}, {0x000d33f8e9a76414,0x000cc98d9e7a9f8e,0x000887493625453e,0x00056663beade4ec,0x000042b80509a795}}, {{0x000cf0d6c39765a2,0x000d8c3cca0b91e3,0x000953b50a2db3ac,0x000f1a088f2f08cb,0x0000414582cef43c}, {0x0008bbc60eee9a8a,0x0001d29aa0428dec,0x00032f5d554c79f0,0x00015f381cd5ec65,0x0000672303b6f82e}}, {{0x000582d3bfab839b,0x00037f8adade46df,0x0007a1bc392474e0,0x00097886a7766a14,0x00006940f54bdc0f}, {0x0008ef2f2759f255,0x00095719f4c64473,0x00050c3459dd9578,0x0000d4d859b7f407,0x0000e788bf302218}}, {{0x000afa8719c05631,0x000cac5fc79f376a,0x000750cd3cd8ad2d,0x00008e203fdb9fcb,0x00004ff052f5418b}, {0x00084cf3e2d65208,0x0007944ed509f750,0x000f25b987ebdf0f,0x000837743bf0f2d3,0x00006ad71d02354d}}, }, {/* digit=6 [{1,2,3,..,}]*([2^24]*G) */ {{0x000c8c4868af75df,0x000e55c8c7ead9d0,0x00081ecb0d7325cf,0x0004ecbb471996cc,0x0000f5d55f451182}, {0x00045411977a0ee8,0x0004f22038c6be31,0x0004bb4955085c4c,0x000081ad5335bff9,0x000094ad8a748e2a}}, {{0x00034b22c11bb373,0x000dbd4c74a35402,0x000c5f25d2d0366d,0x000142c9a968daee,0x0000660106897b63}, {0x0006d2c68d7b6d44,0x0008cc84294207cd,0x00068b1eea8f74f0,0x000ee4a275140477,0x0000b5f7e8a3e62a}}, {{0x00059b21994ef202,0x0009438ae318d1e0,0x0006990102a653b6,0x00084a50d5eb582f,0x000079739f729f5f}, {0x000663c8b799336a,0x000c803c37eb5da4,0x000dbfb2dfdfdf14,0x000f9a92d8a9dca1,0x0000b40cff117d48}}, {{0x0009f0b879fbbed4,0x00069a9d1869f236,0x000766f450ff0ae8,0x0000fc1251d75956,0x0000984d8c06be8d}, {0x00095a6d21008f03,0x00000a1a1c497ecc,0x0006c50f329bd54a,0x0002517b9828c5d2,0x00002c0087c81d0d}}, {{0x00090abfbaf50a55,0x000b184e0750f617,0x00076b005df55e76,0x000dc79c516da7f1,0x000075553bbca2dd}, {0x0007ca3553afa736,0x000bed55c25137c8,0x0003e5d35315f3ff,0x000f288846442aaf,0x00001b91149c495f}}, {{0x000eb6662b5f3af3,0x0000dabb373447fe,0x000f35cb1cefab56,0x000eb9149de60e19,0x00009f8db14457f0}, {0x000cc5b3c61bfd60,0x000d41216703ffae,0x0004e1cc2a5a4d41,0x0009537f8fabed22,0x0000d5a8186871ad}}, {{0x0003a4956f908239,0x000fe41d777b4bdf,0x0008bf760ba0f507,0x000b01791d71c3f3,0x0000633d5102b625}, {0x000b743b8c9de617,0x0003ede7472003ec,0x000ce1cb2b475125,0x0002ef2f9defc974,0x000074a4f6a70bd3}}, {{0x0008ea601799a527,0x0001486d2952190d,0x000ff2a7ca20cec4,0x000d36c062ffb27f,0x000041b32e5e9f19}, {0x00081814eb57d471,0x000406aef06bf80d,0x000ecb5887a2d0ed,0x000f5af9735fb01c,0x0000641caaad6061}}, }, {/* digit=7 [{1,2,3,..,}]*([2^28]*G) */ {{0x000824f20151427a,0x0005f24302067f99,0x000112357206828b,0x0004ec0a9097d7e1,0x0000cf9a2f2a9e41}, {0x000c9da279153564,0x0006c01efee3dbda,0x000b288e27e0734b,0x00009c14fab5bbd2,0x0000c630fc5362dd}}, {{0x000107a1ac2703b2,0x00084bc857b58537,0x000daccd1b49258d,0x00052937df14debc,0x00004ab68d7e4ae8}, {0x000b5d4734e59d08,0x00084495cc807ed8,0x0001db9b35f8740c,0x0005be04aedd5a29,0x00000b360f8cfb99}}, {{0x0005f5d5fa067d1d,0x000ec668960cae91,0x0008edaac4134b57,0x000435ed3656d6a4,0x0000ac1e3e5cc1d7}, {0x000f869d81fbb26c,0x000bf26c33d4674f,0x0004203e8449ed3e,0x000f49c5138705d9,0x0000cde538c7eeb6}}, {{0x000c68da61a76fa3,0x000d9a1554dc55d5,0x0003b279c598b441,0x000efca39923b977,0x00003331d3c66bf9}, {0x000848e298de399d,0x0006d1a27f562d4c,0x000b8ab70cfdb8e7,0x0009b9c4c855ea57,0x0000cdb9daf3f787}}, {{0x000f8c2019f2a596,0x00036b4fbc747bdf,0x0009173ddb3ce5bb,0x0004398a907f688a,0x0000cd3d0d3f5a75}, {0x000c4d6efed021c1,0x00005a77339a92ec,0x00088c64a09a9f9b,0x00015877ca6b1571,0x00000c2996854899}}, {{0x000a229ed6e82ef1,0x000355ebaf4e5859,0x000ad67ae16f338e,0x000bb3fcd313875e,0x0000c73d22864ef0}, {0x000513174a5c8c7d,0x000faf69ad6a4cb5,0x00066f87e01cd296,0x000320d04d00dde9,0x000096fe447db7b0}}, {{0x000c06e88fbd3813,0x00042c35a493342a,0x000f1bbcd02cd4a8,0x000d4cb8fa89de54,0x000041d63675575e}, {0x00057fbd238202b9,0x000a1984ead9ebe3,0x000436ea0600b4d1,0x00051b335c9f4452,0x00006fe0a3a33707}}, {{0x00007367f636a38c,0x00064e76d5cb4c4f,0x000b68b8b9f943fb,0x000a1ef03510baa8,0x0000246780b5ed07}, {0x00014156d549fc2b,0x0000b07781ca3c05,0x000d95413c2953f3,0x0002e2e55e2c69d8,0x0000300fadd2bd28}}, }, {/* digit=8 [{1,2,3,..,}]*([2^32]*G) */ {{0x00086024147519ad,0x000b56b372f02028,0x00085ebc8d0981ea,0x0008e8d9d4a7caa7,0x0000953c50eabdf5}, {0x00061ccfd590f8f8,0x000ac4e6c9179d63,0x000eb64cf72e9626,0x0008f2ffd9611022,0x000063ebb7f1eb28}}, {{0x0007cf5678a31b0f,0x000d4998b620877b,0x0000fb396d50301a,0x0002a5834257c5c0,0x00009fb18a0f4e67}, {0x000d8ebe8758851b,0x0005ad99ba44ff8b,0x000fd93b71e64e4c,0x000b8b9b8eaedf7d,0x0000a2f2a98b4e76}}, {{0x00007e0e90fb21e5,0x00006ba7fca1a18f,0x000cd67b500fd2b8,0x0007f6d0387f2795,0x0000b89a4e823970}, {0x000ad3f894407ce5,0x00041c2261328f83,0x00006c13ba0025b9,0x000025779563c7f9,0x0000f548f319e7bb}}, {{0x000d3a7c35d87949,0x00077356bae50ee6,0x0003322fd042e655,0x0009670f59698d64,0x0000379ae15e0a61}, {0x000ae62fcc9981ea,0x0000cd2934c664b9,0x0004e65ebaed3d63,0x0004278454b3025e,0x0000b09f64899950}}, {{0x000d3d331b85f091,0x000a988ae64ac1b3,0x000ec50fd0f45354,0x00034f98b626d32f,0x0000bdcfbd4f8288}, {0x0002866cd5225391,0x0002710f7ab3e45a,0x00005f293fa9d473,0x000597c8c1d6b4c9,0x00000ac80474461b}}, {{0x00015366d91cd2c0,0x000adaa3f0e4e2c8,0x00041e08340a2bee,0x000347fb167a5924,0x000004675e9e9240}, {0x000aaff840e446e0,0x000fea308f727848,0x0009bfad99f9f258,0x000af650f1289963,0x0000939ae63205c0}}, {{0x00075146fc627e20,0x000591573a51bbb1,0x0008243d5a0569bc,0x000692a7016d9e35,0x0000dac0c56ac1d6}, {0x00033b5da590d5fc,0x00031e8174919938,0x000bf75d0a806780,0x000cfaa5b4f2124d,0x0000c9602338cf80}}, {{0x0003a1222248acc7,0x000ec264e366b208,0x000fdee281f6ec0e,0x000bb4e659b7045a,0x0000a823a4156430}, {0x0002a04e1900a791,0x000ab9ee65762459,0x0005ea54acde09d4,0x0005a742b6463f4b,0x0000efe9ed3e3ca6}}, }, {/* digit=9 [{1,2,3,..,}]*([2^36]*G) */ {{0x0006dbe305406dd9,0x000f4d5d1957e27a,0x0007d4d8f8eb7dc7,0x000de4654a687638,0x0000c47940a57762}, {0x0005b5d99b307781,0x00065e793682be4d,0x000c740e325380c5,0x0004ae502d37f3da,0x000040deabe2566e}}, {{0x0006126c49a861ec,0x0005214f0d06eaee,0x0009bfc17024f3b6,0x00038091a3f1e8c6,0x00003c3a8ea67686}, {0x000752cb103d4c8d,0x0002c218b36b3400,0x00051504a02bc461,0x000bf9f67f75eb76,0x00006848b57a02ae}}, {{0x00081db1782269b6,0x0008c597e5509583,0x000385153ae34bf7,0x0000485b5c60645f,0x0000f0e96b043088}, {0x000021577884456e,0x000b89310ea7bf6a,0x000fad2deb3b5688,0x000d4c37c9429504,0x0000020f0e5f7896}}, {{0x000428dbbe5a1a9a,0x000e9126bd67cca4,0x0001058268187fd5,0x00019f6036973a48,0x000039b666458bd6}, {0x000deef2d65a8087,0x000f24636b196d42,0x0005d564c4969044,0x0000778611ee47dd,0x0000b2f3a4a42873}}, {{0x000d8dd0f82b2148,0x00097103cbc603b0,0x000d79e19460c34f,0x0007f8732e5c0318,0x0000b8888bb28411}, {0x00037dcc07226779,0x00088c1c0f278f3c,0x000f7a0c610d21be,0x0000e0447c8468e0,0x0000bf022143decc}}, {{0x0004160b7fe7b6e0,0x000a400a3fb29755,0x00028ca1e7d16189,0x0008ccd73e9beae3,0x0000dd04b97e793d}, {0x0003c9b506db8cc0,0x000ecf38814ca9c8,0x0004b45e65cd47aa,0x000a8426fc430db6,0x000079b5499d818e}}, {{0x000d21ae0ac29416,0x000462d3193703b5,0x000c992d0279b025,0x0001f2d307c052ca,0x0000aa7cb934fa8b}, {0x00025800d37c7a50,0x0007342d54225a18,0x000d2ef9213380c3,0x0003c692ac2d66d5,0x000035a70c9030c6}}, {{0x000b78571ba18615,0x000c80c8f93d5109,0x00033bb9348b22d5,0x000d0898fa84a786,0x00003fba6baaaebb}, {0x0007df3e5eea7d82,0x000648ca71587ff2,0x0006f1a05521c879,0x000ee499d5133bce,0x0000d50cd541d0eb}}, }, {/* digit=10 [{1,2,3,..,}]*([2^40]*G) */ {{0x0006d65533ef2177,0x000453ca2e87889f,0x0002b41677158c7e,0x00057f8b670dfbdc,0x00005910a01f44c2}, {0x000bf07cf88577d2,0x0000c45e2acef336,0x000a23d852224525,0x000f580ed92e8d7c,0x00009f8be4c4b812}}, {{0x000b2452133ffd9d,0x0000b30f1a20fbb9,0x000a1f52a39a8b2f,0x000df7784bc97dd5,0x00006aebf57740ed}, {0x0007acb76ccdac60,0x000c1586ff273225,0x000de7dd1af4d36e,0x000c168eaa8863f8,0x0000045d5cf88647}}, {{0x000414351facc618,0x000d668a25bcc51e,0x000f872edbaf2647,0x0006590f5271a00f,0x0000f32ef99bd2d9}, {0x000488c7593cbd4c,0x000c42b82fabca12,0x000eb3f16ed266c5,0x000fe24a2f78ad14,0x000034049490d47a}}, {{0x000d574c005979da,0x0001ca40e350a6f3,0x000e2ecf9c2072b4,0x00044e5ca5c1568d,0x00008c8bf5c45153}, {0x000e555114df14a7,0x000d8dc5ec6b97ae,0x000a85418d4374a4,0x000f78054cc28f2c,0x00001cb9e2843c41}}, {{0x0006702094704963,0x000dbbd2381509c1,0x000dd4398a489a5e,0x00069694dde4648e,0x0000ca7b94ab0111}, {0x0005d682ad636a41,0x0004f8dc5f1e3c38,0x000a219436702702,0x00069dfc1965deaf,0x00008666e16710be}}, {{0x000fd350369c8e10,0x0002b9dc843b6792,0x00002e2ab9271aa6,0x0003838711a4b14d,0x00002b2a3e27ee1a}, {0x000e35f0e2b379be,0x000bf652ab25b226,0x0005601063d3de39,0x000876cca6d4c93b,0x0000ced0cf5a95bd}}, {{0x000b4ca2a604b3b7,0x0003ca61676245be,0x0008b806e56f6518,0x000480852f5a7097,0x0000aa3978781dc4}, {0x000ac2a0e01fabc4,0x0004e37d99f9e13f,0x000211ffe7c6ee8a,0x0003eae51384ee05,0x0000ff6976d5bc9d}}, {{0x000507903605c397,0x000e3142c96c8910,0x000923684f0843d9,0x0008938374493416,0x000032caa306a0a2}, {0x000c27061160170e,0x000b637fbaa3b2e8,0x000eda3acc32788c,0x000e0659cd818ea6,0x00002e9423a7e2b2}}, }, {/* digit=11 [{1,2,3,..,}]*([2^44]*G) */ {{0x00075455922ac1c3,0x000c752b3f638df2,0x000de57c4a7b3ef5,0x00008b5e77b21471,0x00001682c10b34c0}, {0x00024f04bd55d319,0x000587b61c71c768,0x000a5089db6d1c08,0x000d3ea1db0903c2,0x0000c092172a84e5}}, {{0x0005035ea6c39976,0x000a62610bef5ace,0x00080dd3954259aa,0x000a398f18bb3f3c,0x0000910b95bbfc3f}, {0x000f51043e09aee6,0x000f47675665fce2,0x00072db61ced56c9,0x000e68b0e265acd8,0x0000982812f0e9fc}}, {{0x000b690768fccfce,0x000cd835b362ca2e,0x000fdfccef402d37,0x00098f2efac0d0e2,0x0000fc9cdf09638d}, {0x0002b72d1669a8bc,0x000b9774ccbd2af1,0x00034870e33c536b,0x000ac970b21909fb,0x000038fa2f83df25}}, {{0x0003d931341ed7a4,0x000c67b59d49b8fa,0x000b8c4a44223272,0x0002e3fdcb194783,0x0000e413c022d130}, {0x0009127e17e44ceb,0x000483b3adfb6d99,0x000aa96caee86bf7,0x00047d46902fe625,0x000073540e595aae}}, {{0x0005e75b2c69dbcc,0x000843c3da6c7bfc,0x0009102713aa77a2,0x000c551e0df03cca,0x0000bd5ca4b3806d}, {0x00058076db476cb9,0x0001cf37a31ee1ca,0x0001af416fde15d6,0x000db5649af520f4,0x00006c5c5b20d342}}, {{0x000ef6c872b4a606,0x0003e613521bcc50,0x0003e15d1ab2a34a,0x000511d9c5c19098,0x00001dde5dfb9905}, {0x000f6219f2275f33,0x0006151d894be417,0x000b0bdaa0750c8b,0x0009bd45b04ab978,0x0000bfd9fd475858}}, {{0x000e02adb22b94b8,0x000921eaa45bc792,0x0001e1c63993d8ae,0x00088a0aad6cd3cd,0x00009529ca845ce6}, {0x000e3aae572a2530,0x000802a21efb2cce,0x000430358e02b643,0x000504a7091b6ec9,0x00006d1b1fa9d7db}}, {{0x000bfabaf95894c5,0x0006d76b2241aafc,0x000dda48b7b9bdc0,0x0004df9af983625b,0x0000977faf2f3fcb}, {0x00042ef052c4b5b7,0x0000967591f0bed0,0x000f24ec79fe87f7,0x000f1b589c73ca22,0x0000d37fa9f564a9}}, }, {/* digit=12 [{1,2,3,..,}]*([2^48]*G) */ {{0x00064880a750c0f3,0x00031e548e83cc7a,0x000110f0539bacfe,0x0005880d418c760c,0x0000e4daa4ce1f11}, {0x000e7b55ffc69ff6,0x000c320531272733,0x00022df9446f147b,0x000b7c285b2434d7,0x0000a444f6646fc6}}, {{0x000465ac3f16ea83,0x000d82f1d11c7a1a,0x00068a172115a461,0x0006981767dd956c,0x0000392f2ec013a4}, {0x0009ccde526cdc7f,0x000b32292b81c7a9,0x000d391988e537fd,0x00052c86d8cf69a6,0x0000fc5ff4414468}}, {{0x00016f4bdaedfbdc,0x000fc6746ced6d0b,0x0004b3e1723fd325,0x0004c7cbfb1d2fff,0x00007f2ec2dc19c1}, {0x00032f245104b0d2,0x000b8dea2b7e3e08,0x000fbfb0f5f00daf,0x000cda09e5cf6699,0x000064f972381827}}, {{0x0004f7ea90567e6d,0x0006e6ae5cb797b1,0x00010903d513257b,0x000723b5454a3c9f,0x00008d2c9ae39bc3}, {0x00093246b29cb44f,0x000c87c8cbac38da,0x000918e42b540a21,0x00014dabbfe43501,0x0000ffa707b46c36}}, {{0x000a2f3e30bc27ff,0x0009c08365116eb1,0x00065ab0ee5f0c05,0x000bbc5d741bbf49,0x0000eec41cb73464}, {0x000705f99d0b09f8,0x0006742da5fa1aca,0x00052b931c5d6cc5,0x0008d7c9964eddcc,0x0000ae596164884d}}, {{0x000e3f1d4e353b7b,0x00043f46b0a00ce4,0x0004b73fd062d8a1,0x000ffcb408d5ab57,0x0000c41d1ca83273}, {0x000e1e76be77800a,0x0007256550313538,0x0009b331a71fe8b3,0x000f727cd916216b,0x0000d825d0c5b388}}, {{0x000b57b39f8868a8,0x0003f5cc69aff634,0x000d5496ee27f4fd,0x00007f247e58cbd0,0x0000a2679405323e}, {0x0009b72fa30f349b,0x00090696d134c61a,0x00080a6d194c9d9c,0x000994c92beca858,0x0000dcc46465f039}}, {{0x000e05b1cb76219d,0x0000a1567e7e56c2,0x000c4c9100ec0bf9,0x0004d917076f8661,0x000067b085c8abc0}, {0x00004595e93a96a9,0x000a6bdc249a9fb9,0x000dd0bb77526c1e,0x0006947d44d367ec,0x000053999182dc0d}}, }, {/* digit=13 [{1,2,3,..,}]*([2^52]*G) */ {{0x0009167ceca9754a,0x0005ab7939a083f4,0x0003fd0bf426d2cf,0x0004e18555e35572,0x000096e6d0764f14}, {0x000a8dd87880e616,0x00058508e4d54768,0x000b65e151554381,0x000f9fa9d7e772b1,0x00003439dd70c302}}, {{0x0003145983c38b5e,0x000b837abc8b859d,0x000ff7be6b14f176,0x000a594793fb9dca,0x0000be5a56015a66}, {0x0001dcd9f87dc596,0x00039bdbf5607cec,0x000eb32577c595cd,0x0005fcfb543b2226,0x0000908064724c93}}, {{0x000688eadd70482e,0x00099b4a4e8a6aac,0x0008a6eef708de92,0x000c4295b6dd7375,0x0000a4bf353525b3}, {0x0001f2c87912868c,0x00052f09297a1004,0x000f3860ab1b1be9,0x000f4a59ae23c5a9,0x00004f0f83a115dc}}, {{0x00052381d531696e,0x000fa8cdde69b934,0x00086afc757201bf,0x000ea7fde922519a,0x000030438969d35c}, {0x000c1e18555970de,0x00084535935e7608,0x0002ea38b8267dfa,0x0008b4f4c60a5732,0x00000bf7978604ef}}, {{0x000049f16a66e918,0x00007a1b0e0dd730,0x0004c28eae97f282,0x000c61c131e00330,0x000020ab732d26ba}, {0x0009ef9287144234,0x000a6db10cb2b2ac,0x00086a4cc54ecfff,0x000d494781476ef8,0x0000b2c87b61b2f8}}, {{0x0001d4286d2e0f86,0x0001ae8a9fd56ada,0x0008c1b49e592012,0x000afea2c936af70,0x00000f30fee8b4bf}, {0x000ad06858e6a61a,0x00069fd374d06637,0x00088defbce4c776,0x000b6599d54b2d71,0x00008c9d251956a6}}, {{0x000c0965f5206989,0x000db4f7b8d90e6e,0x0005a68b9640631f,0x000f4e02fd34fca3,0x0000c5a4b66dd40c}, {0x00054bf80b6783d1,0x000e2a320a109494,0x0000a39b280e701f,0x0007db7d1a564a1a,0x0000436d53d42058}}, {{0x000ea68c094dbb56,0x000e7968d4106233,0x000b3002db77d062,0x000d57de719bbc58,0x00008e7dd3d9dc49}, {0x0005740013a5e585,0x0006ec9e3c1b8d82,0x00099b6ab2131174,0x0008f1bcb0a2a77c,0x0000c48a3b412f88}}, }, {/* digit=14 [{1,2,3,..,}]*([2^56]*G) */ {{0x0003e91991724f36,0x000bd9cbd686c791,0x000d4fc1e5eda799,0x000d547db595c763,0x0000b63b80c0c4fe}, {0x000fc697e5fb5166,0x000a70f1c9646ea0,0x000a92ca5737708b,0x00067a3628745f11,0x00001f37958fa869}}, {{0x0009b2caa6650728,0x00046fd324ef9af3,0x00027bd3178322fa,0x000aafbd153394c3,0x00001d5f271b129d}, {0x0000c42f48027f5b,0x000bd536e717c72e,0x000369d0faa40cdb,0x0004e6445a657a2d,0x000003bbfc59a7f7}}, {{0x000c4180d738ded3,0x0000b0de572946a8,0x000a816756f1a5bb,0x0003d4c10230b98b,0x00002c6f30c412b3}, {0x000129dd8fffb620,0x0007b459bf057559,0x0003b67766a281b4,0x00073a77c1bd3afa,0x0000709b38078299}}, {{0x000b232a3326505c,0x00022e1d41bf8c26,0x000e32afa38d6927,0x000a864459453eff,0x0000e8143ae3cb3e}, {0x000c1fa7e6ab6665,0x000fd2286264932e,0x00036f8ed6cd2d22,0x0005baf59a46fe67,0x00000bf0d00eeca8}}, {{0x0005852877a21ec5,0x0006bf537a940b82,0x000a9a6a2300414a,0x000bffef1cba4021,0x00000824eeec6943}, {0x000fcecf83cba5d5,0x000843b4f3c0a0db,0x000f24dd7f953814,0x0009dd1174416248,0x0000322d64e34fb0}}, {{0x00073843d9325f3b,0x00004371cb845744,0x0001e36c5a9bef2d,0x000f71c7d2188ba6,0x0000bd6a7d87602d}, {0x000a9028f61bc0b8,0x000ceed0b6a1ba3a,0x0006e8298f49085e,0x00001d0bc625d6ae,0x000032b0b1e22e9c}}, {{0x000c447f1f0ced18,0x00031492dd2ba337,0x000a08efa800cc79,0x00041dcb93151dbe,0x000020cf3f95e0a7}, {0x00082dc1c0f7d133,0x000054dde6caff19,0x000f96ee3ef92196,0x0000c6ead7d97245,0x000019c8dbe59dea}}, {{0x00038717b82b99b6,0x000ce70eb624d3ea,0x00095d46675922d4,0x0003462f66ec543b,0x00006e673cd1ee1e}, {0x00067c4b5f2b89a4,0x0005e90e5cd36afe,0x0000a2ada3de9c1e,0x00023b4c278bb631,0x000020fa3844bdb3}}, }, {/* digit=15 [{1,2,3,..,}]*([2^60]*G) */ {{0x00096796424c49b9,0x0007d7c241c9646f,0x000f68b49f888dfe,0x000f20512d4b9324,0x0000a6b62d93571d}, {0x000b26d179483cb7,0x00022511fae281b4,0x0003aa51f666f963,0x000d166281b3e4d5,0x0000f96a765ef3db}}, {{0x000d37c051af62b9,0x000a7bf944968553,0x000d59aa1e9a998e,0x00081350844f9fb0,0x000083fd55976afb}, {0x000c0ca65d698049,0x000ddea5ff2d9670,0x000d8623b732b22d,0x00078247640ba95f,0x0000f61916436351}}, {{0x000b4e0bdefdd4f1,0x0005e366e401f167,0x0003bbec06995846,0x000c214aa368aba7,0x000021487098b240}, {0x000323318969006d,0x000e11fe53d1378c,0x0000c4361cb4d73c,0x00012a8f50a80e13,0x000067f59524ef52}}, {{0x00081088cad38c0b,0x000fbbd68ae2332f,0x0008e27a3471b7e8,0x000b0ca6ac3fb20d,0x000054660dbc36b4}, {0x0001e11a6fd8de44,0x000a637799ef123a,0x0006ac17c44dbffe,0x000cef0540b977ce,0x000095173a8ef60a}}, {{0x00037434573eab0b,0x000b21ac6031eb44,0x000dd9afd11570df,0x00023147d9b45b44,0x00008066addd2067}, {0x0002ad8f8a3f0b44,0x0009a0ace2a215f9,0x000b38b809e0e489,0x0000527dcd0aadfa,0x00006506ae957020}}, {{0x00069f78fca399da,0x00016207bb63429a,0x00088f582fe9e27d,0x000f6e4c655ed687,0x0000426d7494db75}, {0x0005c02ca81c66da,0x00070531d4251869,0x000ff48ba84fb8d2,0x0002469a3a8956de,0x0000f1d0d57166d2}}, {{0x0009565352c4b5c2,0x0001390bc3e25a05,0x0006f9f5f4926153,0x000a9b609f7521f6,0x0000baef6bfe70a4}, {0x000fa6509ed3561b,0x0002e84b230ce7e6,0x0004cdc691137023,0x0004157151659bd0,0x0000db83c64a007d}}, {{0x000284d391c2a82a,0x0002758308e89ebb,0x000f1edcabcdd486,0x0006c7606f16ec83,0x000013e2c38095dc}, {0x00056f04a057a87a,0x000006b48f982ab7,0x000651c44a876550,0x000e01a252face68,0x000052b540c81765}}, }, {/* digit=16 [{1,2,3,..,}]*([2^64]*G) */ {{0x0002fc516a0d2bb2,0x000bfa6234994f92,0x000c62c8b0d5cc16,0x00067f7241cf3a57,0x0000f5e69621d1b6}, {0x000c70bf5a01797f,0x000c709561925c15,0x0001fdb523d20b44,0x000f7a14911b3707,0x0000648f9177d6f0}}, {{0x000c8b8fac61d9a1,0x0002d3c6fe8a027c,0x000bff5037d25e06,0x0002f7d08805bfe5,0x00003271e6c7ff63}, {0x000a6c0232f76a55,0x000d201ef42655dc,0x0000a51788957c32,0x0001739e728bcba1,0x0000ea60412062c5}}, {{0x000914bb5def9961,0x0003133dd1e74090,0x0003d5e761cb69c8,0x000012b1e9c1d39b,0x0000f3338ee0ccf6}, {0x0005d0d2f5378a8d,0x00065f00cd21b1e9,0x0005fe290acf4c2c,0x0008ad9e984240eb,0x000066c038df4808}}, {{0x000462bb4d8bc50a,0x0006091957709ad5,0x000412a68181c0b1,0x00048c4bd4fe1c78,0x0000e0341bd60dff}, {0x00045cf7003e8666,0x000a2a24a41bb6bc,0x0004c24c2f11a6de,0x000b67f407151ad0,0x00002c9d27e3a5b7}}, {{0x0002b30614c09004,0x00017d00c24bd499,0x000c4bfa1da98d12,0x0004bc3f534dc87e,0x0000a5ff67477dc3}, {0x00096b81d7ea1d7e,0x0002a0a6d20868c1,0x000cbbd6e38cf289,0x0005b61d56cd09e3,0x0000c72e27f2205a}}, {{0x0005719a8afd30bb,0x0007da826dce3286,0x000a8fbe08679832,0x000ad32f04e891c4,0x0000b6b6e1c9bf56}, {0x0005b11471f1ff0f,0x0008ce15baf00a69,0x00096c43ed76c338,0x000157118edb95be,0x00002beaaf580794}}, {{0x0007932b88756ddc,0x0002317e3e61e8b9,0x000e1c4a4ed4e865,0x000c0e02dd14993e,0x00000aaee18197f8}, {0x000edb96c168af3a,0x000f139ae87515c4,0x000adb4366563c7b,0x000ac00dfadb6f20,0x0000d55e8ca3a042}}, {{0x000b12e523b8bf60,0x000b8f910c1b0a50,0x0001675888009eb5,0x000abdf535af824a,0x0000f835f9cfb2a2}, {0x00029312afceb620,0x000a169d383ff59b,0x000ac02b0c797df2,0x0000caeb3f5fb066,0x000029d4c6fdaa2d}}, }, {/* digit=17 [{1,2,3,..,}]*([2^68]*G) */ {{0x0002010f5b343bcf,0x000a02f142fe58af,0x0005f4bdf0f2e400,0x000aa84483bfdea8,0x00000b1d093f3bfe}, {0x0001b95c70816030,0x00093dba10972ea0,0x00038f3a6e943e4c,0x00063647be92adb4,0x00000bb7742e5bf6}}, {{0x000481b7bfe71786,0x000e05405868b674,0x0008c867d4e1deba,0x0000e9a61b2821c4,0x00009c15b35b13b3}, {0x0001666368710884,0x000cd220b1ff3b4a,0x0003d9f4de5e29f5,0x0006750b82bb3523,0x0000e07633358cdc}}, {{0x000c39731815e696,0x00067cdd28023a63,0x000b4f6af6df9cbd,0x000977ec47ed4a15,0x00002009d82cac0f}, {0x00080d28b898fc75,0x0009dc17c91f664d,0x000ae660972f1eed,0x0008954e84d3bc7a,0x00008c7c19578376}}, {{0x000f5c7a3e6fced0,0x0005f45fbdeb0d53,0x000339a70e8cbbdd,0x000b81f85c01df13,0x0000ff71880142ce}, {0x0008774bd70437a2,0x00019a0bda6a4c4e,0x0008bd26e5fb3289,0x000521fcdbebd2f1,0x0000f9526f123a9d}}, {{0x000c905a8271d7e9,0x0004c8e5810ba752,0x000925aeb4735dfa,0x000853518a44ee5d,0x0000708697fa3c8a}, {0x000d540bfcc9a0be,0x000c0574d4038377,0x00060a8a67b27e01,0x0008be5d3d180ccf,0x000048ef153d1c29}}, {{0x0002e8c0aeaa3c09,0x000e1be85b0a313a,0x000a97d3a89f46d9,0x000cba42889ebd2d,0x0000484026aa03f8}, {0x0009f8a87d83b5f4,0x000671ef02955215,0x000c01acfdb2220d,0x000fe37da0746e03,0x0000f97b2a754419}}, {{0x0007ac2c880e5cac,0x000dcd11c450ccbf,0x00077a6bf8299dbe,0x000792fb27d11b0f,0x0000601630c1edce}, {0x000b9fb79e7f8ea9,0x000764367288db73,0x00035571be448bba,0x0001a265b6416fb0,0x000081b8f5e34889}}, {{0x000305192c4d6840,0x00057612efcd40ce,0x0009cae208b04d72,0x00056cb9dcda366f,0x0000edc4d24f0588}, {0x000e6bf854279005,0x00058c09dfea64f2,0x0009bf26c3de8129,0x0005a9841b448737,0x00000b62c6dbdf13}}, }, {/* digit=18 [{1,2,3,..,}]*([2^72]*G) */ {{0x000fb5ed005832ae,0x000ab1042e4f0db2,0x00070f8ca5f5efd3,0x0009cbac4ffdc6ed,0x00004645d0c952da}, {0x000f58bc9001d1f8,0x000bce1172059596,0x00098a08452c8f0b,0x0009de7d4aa0d2e3,0x000015bfe3a904f4}}, {{0x0003acce548b37b2,0x000264d4054954eb,0x000341b4fb38e754,0x0007fa6c3daa517b,0x0000f6928ec890bf}, {0x000b32386ce6c413,0x0004e0adadcd0496,0x000b5faf901be1c5,0x000985904e67e74b,0x0000cbaf679115c9}}, {{0x000226ad7ab9a2d8,0x000cfdfae958524d,0x00051d8c29c00090,0x00062c8ba5f53987,0x0000afcbcddbab82}, {0x0002729e99d043b6,0x000b4ebc943a5739,0x000862935ef51263,0x00017b3feace9320,0x000039efc04106c8}}, {{0x000be7d341d81dcf,0x000842148379e839,0x000026eadcddb688,0x000c5dea6211a1f7,0x00003b25760e4d1c}, {0x000c8f6a7a73ae65,0x000e11d5b48340cf,0x000a50ebc83879a5,0x0008fa75acb1ed41,0x00009a60cc88c07d}}, {{0x0008d4ac3b819900,0x00029e0cc8fedec9,0x000b427b91cb8372,0x00066cfe0b0491d2,0x0000f2386ace983a}, {0x0004d1eb32912137,0x000de9a62ae4930c,0x0003e89e3a2f82b2,0x000c7f07233853f9,0x0000f8063ac81777}}, {{0x000c97c593710000,0x00007f759c18604a,0x000db6b65e1c48c7,0x0004953f62ecc5a5,0x0000a78b17338a21}, {0x000819dbcc8ad945,0x0006889c34006be1,0x000b4840a70dc04f,0x0001bff62557b4a6,0x000044c6adeb0bd2}}, {{0x00007cf02ff6072b,0x0008dad98cdc36e6,0x000f56609a47d2ca,0x000da00f471d1ef5,0x0000cf86624a264a}, {0x0000687aa9e5cb6d,0x000147401c6cb70c,0x000a61435c98124f,0x000ea5b189635fd4,0x000028fb8b079d98}}, {{0x00030b665c7322db,0x000103c1b3fb4395,0x00072f685cf12cc0,0x00091d170b018601,0x0000915ee22cb583}, {0x000f03ba317db248,0x000897b8ffc49afd,0x000d3d05087dec65,0x0000e6ff46597be4,0x00000a1c1ed80650}}, }, {/* digit=19 [{1,2,3,..,}]*([2^76]*G) */ {{0x000a7b397acf4ec2,0x00003ea8b6403e22,0x0009692850426c40,0x0006703e3295a64e,0x00002aabc59c6a45}, {0x000714c5f5942bc4,0x000dba3182edb929,0x0004152ba9a6168b,0x000367e216a66510,0x00006908d03f6926}}, {{0x000d8745a1251fb6,0x0008672725c7a9f5,0x000ffe89e967747a,0x00035db95c33e531,0x000009d211049649}, {0x0006ca82fe122271,0x0005f426469dcafd,0x00093183caf9b5b9,0x000fef1e9ee04c56,0x0000084a333d8146}}, {{0x000b88210395755c,0x00039ec1df80ce06,0x000f55e96117ce63,0x000d1e3efae513ef,0x0000f36cba7bd7fe}, {0x000eca9a40ebf884,0x000f73d37e127340,0x000bbf9ffe6ec1bc,0x00005e8a51b64e86,0x0000e0dbb58cb40e}}, {{0x0009933aed1d1f71,0x0003405630909664,0x0002e39cf566eaff,0x000124245057f0ad,0x000048ff65b2f832}, {0x00089d4cf94cf0dc,0x0003920c58b3042e,0x00061aa0d319bec8,0x0007ac6a26762653,0x000086fa3034fbc8}}, {{0x0007b9c7ea2ee345,0x000bb9cc3a71359d,0x0001ea37a3fd0d94,0x000c876b53c31c3a,0x000033425fb1f818}, {0x00099c3810156e0e,0x000350c164487cd1,0x0006425420ea020e,0x0005ea0557ba094a,0x0000657e7e87465f}}, {{0x000d2ab5c8b06d5c,0x00023e4eac46fc83,0x0006f7779b1a785a,0x000504f99315bc84,0x0000f31d817af9ea}, {0x000fe6a15d7dc85d,0x0003e4016b332391,0x0001cb4c72f132b0,0x0005a059547fe318,0x0000b66d8a735015}}, {{0x0000e8b593d070f7,0x0005e255625d59cd,0x0007a03994375751,0x000eeae51fdda75b,0x0000bb6e6b09dec1}, {0x000b662334c0922f,0x000e1cf41b79729b,0x000f324023df631d,0x000c8711abf3c578,0x0000cb4666d8cd33}}, {{0x000d7e1adc1696fc,0x00024acd72d06b66,0x0001b743598ebe59,0x0005eba5f24550cc,0x0000e23139474b9a}, {0x00022d4db067df91,0x0005baff9b00234a,0x00000c9c198dda09,0x0006950bbc75a061,0x0000560a9c8a39cf}}, }, {/* digit=20 [{1,2,3,..,}]*([2^80]*G) */ {{0x0000f1cf1c367cab,0x000b190fbc7de405,0x000a110329bc85a9,0x0003a8f373c4a2e1,0x000064232b85d039}, {0x0007eb0167dad297,0x000124b78ab2f557,0x00029348b1604f30,0x0003419baa94afe8,0x00007fbd8ddb1654}}, {{0x0004802fcf0a7fd8,0x0008d488b01e31f1,0x00052b49842fd078,0x000200f1d78d6d99,0x0000eb572d987ac5}, {0x000a44c4d194a88b,0x00090a017e66e0a2,0x00088aefcd2b63fd,0x000a10c8efc6c8f8,0x000076f6bdafa881}}, {{0x000932c68af43eec,0x000db03d00bda2f7,0x000b061f55502468,0x0005ad25dc978f2f,0x00009a1904ae8c81}, {0x000538d470c56a4f,0x000e293d8cedd3af,0x000108ef3159abc5,0x0001773a37245f20,0x0000a17081f123f7}}, {{0x000a9b2b4b4b67c8,0x0000680206041fe2,0x0008058d8c1d10df,0x000fbb1d64abfcbc,0x0000943b9b2f12a0}, {0x000d9143b3def048,0x0001cce775ff90ee,0x000bc904085ab3aa,0x000dfae05fd4ca7b,0x0000b34a56562c75}}, {{0x000acf88e2f7d902,0x000757be32cd5c18,0x000eb5ee9fdbf33d,0x000114ea085cd7d2,0x0000d702cfbd3201}, {0x000ebdb85c88ce89,0x000b8e01d617b6e0,0x0007333ac23a3ce3,0x000b6aa041618e56,0x0000dd0fd8fa57ed}}, {{0x000610798fa7aaac,0x00043073aa4eb2b2,0x000d6b19b41209ee,0x000caf31570359f2,0x0000be6868dbc577}, {0x0004bdc32c04dd3e,0x000defeee397186c,0x00086c0cfa6c35fa,0x000fe1d4a1b312f0,0x00000a5ccc7b9461}}, {{0x000f3a36fa6110cc,0x00013b93561f516f,0x00057522b74fb1eb,0x000dc5ac0c904784,0x0000fd321052bb8b}, {0x00084a2cc80ad571,0x000576a9b6372d68,0x000f4e8cd7c27fc3,0x0002f02461baedad,0x0000d56251a71724}}, {{0x00011a9431dd80e8,0x0009f3306cd9b840,0x000b3b730eb7c7cc,0x0003d2a0fadd29d1,0x00003858b5c7e37b}, {0x000d193b6251d5c7,0x0002a352d952bf4c,0x000fbc0511cca1fd,0x000636566157a490,0x0000990a638f9b98}}, }, {/* digit=21 [{1,2,3,..,}]*([2^84]*G) */ {{0x000692a87dec0e16,0x000d97b39d00e5aa,0x000cfa0b5010ded8,0x000a281b1b80c854,0x00006beb87700f8e}, {0x000f5313476cd0e8,0x0005308d394950d7,0x000479fc6a63d0e6,0x0007419a09eea953,0x00002ae98927499e}}, {{0x000b9105ca7d8669,0x0001aadb3b34ab58,0x000eac0bc582967e,0x000af4f9ae4447cc,0x000019c667d0bf56}, {0x00017b160f5dcd7b,0x000f2dcaadbc9aec,0x0003467f5ec697b9,0x00032e5b98f34146,0x0000187f1f859671}}, {{0x0007a1d214aeb181,0x000c641432f790fe,0x00091a0c41506af3,0x000bc3ab5565f9e5,0x00000d41a77c44f1}, {0x00065e4a84bde96b,0x0008420a6a1ca09d,0x0007f9ce742f060d,0x00039eb52a3bfdf2,0x00006bdb65ceb3d7}}, {{0x000dcb6ec7fae9f1,0x0004dfb66e5aeb5d,0x000445d52995f271,0x000620cee95d8e69,0x0000b6c2d4619e27}, {0x0001c318129d7161,0x0000f958c1aa3262,0x000f4af63b03909f,0x000df67c468ef91a,0x000062c42a00ba5c}}, {{0x0002343753b9371c,0x00099f1f9cd72f68,0x00045db9629cab45,0x000998971623abb2,0x0000507db09ffd79}, {0x000f652af036c326,0x0007a5018e5c4e2e,0x0008be35086f0cc7,0x000327610a73d4ab,0x0000519b397de826}}, {{0x0005eef9c053df72,0x00079300ea6fe8cb,0x00049cffb8de25b3,0x0009bbbb03fa92c8,0x000042e43a808416}, {0x00051f4dd6f958ec,0x000f34445a8de4fa,0x0000d89496925a77,0x00039026e72a50e9,0x000066648e3eb1f6}}, {{0x0001957173e460c5,0x0004e0704590b2ab,0x0001c71621bbbce7,0x00065d70a90dbddb,0x000005e399e65cdd}, {0x0004dcb57797ab7b,0x0009ba2ca8e86843,0x0003336c160ad35b,0x0000149bfdb1e0de,0x0000bef99ec88b39}}, {{0x00096f31711ebec8,0x000f4e98fdc46c3b,0x000b4411f2da40f1,0x000bb6399774d357,0x00007c8bdf495b65}, {0x00089e3c2eef12d5,0x000aec7471f3da3a,0x00012c594de95bb9,0x00056b100f225bd8,0x00004907c5d7b75a}}, }, {/* digit=22 [{1,2,3,..,}]*([2^88]*G) */ {{0x0001db6f79588c00,0x0009b55768cca80d,0x00054438afa52fc6,0x000a4f0b4df1ae7f,0x0000cadd1a7f9b46}, {0x000a6b31803dd6fc,0x000495eaae35b40e,0x0002e4e16488e4fa,0x000c97df047d5538,0x00009b5b7e0ef6e0}}, {{0x00038b67c4a658ad,0x000870e72182c127,0x00098e44fb3c4763,0x00085e6b77be4687,0x0000c047df2e7a7f}, {0x000d4c55e59d92d3,0x0005b8e64d8d2439,0x000ca9b16cedca47,0x000dfe7724cd0d87,0x00005e4fd59d5540}}, {{0x0000e0683a7337bd,0x00042fecf2494b7d,0x000a2b71f1e3416d,0x00026c54840eff66,0x00000d9a50b837cc}, {0x00081506fe28ef7e,0x000543324c7fe219,0x0009b52633cc5ef1,0x000474420f345576,0x00002ade2f2810bf}}, {{0x000344f3a29467a3,0x0009951eba6d9894,0x000e5c2f2de81e94,0x0007b3aaea066ba5,0x0000fc8a61438c8c}, {0x000f88f06d0de9fa,0x00049b75ce0a7adf,0x000bc87d5bbc11cf,0x000de1ffbb7accfb,0x00001458e271badf}}, {{0x000c8c7dacddb7dc,0x0003be1edcad03b6,0x00008063392ed500,0x0001cde0e46c2f54,0x0000d37663e06dec}, {0x00084c5f365b7cc3,0x000ab79bb95d3969,0x000b1d3c1294e3a2,0x0000f56aa17d7727,0x0000ffd3cfb14944}}, {{0x00093e3abb830d13,0x00022c2c5270041c,0x0004b259d2ad2353,0x0008577efd1be2ee,0x0000ef267774eadd}, {0x000f7039b0d7d86e,0x000c9b7e6f202af8,0x000c8e29580f5af2,0x0009f5d5fa1d3cce,0x000073f3903d68f0}}, {{0x0009d11399f9cf33,0x000dee3c43942667,0x00098daf178e7a48,0x000ea2d8722dea0d,0x00007e7ed58b0030}, {0x0001ad43c8aae72e,0x0004cc729695f373,0x000c283527878be9,0x000b608a643affbb,0x0000f8b801c58759}}, {{0x0003668e039c2560,0x000b7c17fd5d1cb4,0x000aa062b5f26fb8,0x000f04eee426af79,0x000072002d0d78fb}, {0x000a237e84fb7e3e,0x00002c82133d4c9c,0x0007e4181b401d8a,0x000151caa525926d,0x0000943083453dbb}}, }, {/* digit=23 [{1,2,3,..,}]*([2^92]*G) */ {{0x000da31be24319a2,0x000bc095a8e7f92d,0x00078218503f7d28,0x000dbc852fe84098,0x000076ddafe49c24}, {0x00054961d7a64eb7,0x00090f1dbe4280cd,0x00038d2d5e436088,0x000035bf81a87784,0x0000e4d52a8f5169}}, {{0x000fd9d615faa8f2,0x0000768554ed7b15,0x000a448828fa1eb4,0x000f325bb4447e7a,0x0000bb2d0d1229ff}, {0x0002a646caa6d2f2,0x000e02e7351b075e,0x000506c628eb879d,0x0004dc9cd5624e9a,0x000018eaef0c87e2}}, {{0x00047d83d30a2c5c,0x000e378a81dc1fe6,0x0001a4a9b0857f77,0x0003f451d5a33413,0x00000a94af9e9d39}, {0x0005c0bdaa6ec1a9,0x0002f8d2d7edbc3a,0x000614797ba9fe49,0x0005332b4335b4bb,0x000091c4d6902f83}}, {{0x00068cee978a1d35,0x00032ab92d0477b8,0x000a5b862e3a68b3,0x00041d0102979487,0x0000f0606c38a61d}, {0x000be276f9326f11,0x0004b6fe3c2e2814,0x000df73512f521c1,0x000e4407464d7dac,0x00000f5f9d3877f7}}, {{0x0004ce43d34a2e3f,0x000dc43b5d611fd8,0x0009186c7ee3759c,0x000259995bc78c61,0x000019c380abbb97}, {0x00021aade744b1f6,0x000000f8056bc0be,0x0003efe11a7d222b,0x00025314be6157b2,0x0000fab2b4f6cd68}}, {{0x0003878a4d32282f,0x000c58020ae7b6e3,0x000a9b750e36e029,0x000818f05847fb37,0x0000876812da29e3}, {0x000138ed23a17f08,0x000070b3950e84ad,0x000d67ae06d7b448,0x000af65fa8aef42f,0x0000d3eea24d2333}}, {{0x000a522b99a72cb0,0x0007876180162101,0x000f3653e06de6e6,0x00054a5ff8c7cde6,0x0000a821ab5c7a67}, {0x000a52b7cb0b5a2b,0x000c190487907e3f,0x000ce053aa7fb121,0x0009af6a72502006,0x0000490a31fb4e92}}, {{0x0001244c5f95cd80,0x0000f4ab95f4b06b,0x000e5836dda8c8af,0x000ffc1bae59c2b9,0x00007d51e7e3acff}, {0x0005e6ac2ccbcda6,0x000f2528c3e001e1,0x0009fead43bc1923,0x000710e3324577a4,0x00001a1b8848aa7a}}, }, {/* digit=24 [{1,2,3,..,}]*([2^96]*G) */ {{0x000ee31b0e63d348,0x000229e54fab4fe7,0x000e7b5a4f460057,0x00083140493334d5,0x0000589fb9286d54}, {0x000f5cc6583553ae,0x000a025649e5aa70,0x0000446520879094,0x000c4eec90450710,0x0000bb0696de2541}}, {{0x0001a3ea2dee7a63,0x000c434b2284758c,0x000aba6addcde2f3,0x0000a77ba445d24e,0x00005aaf668a6cee}, {0x00004a9e5aa049a6,0x000d31103e847e0b,0x000afecc3e74083a,0x000f7a5eb183ce40,0x0000b89dea04a043}}, {{0x0000e0399375235e,0x0006d9917970b99f,0x0004ec0677614c84,0x0005201ec93ce952,0x000040e7bf97b122}, {0x0000631ee4c47744,0x0009fb04914cb567,0x0009dd2266f03847,0x0001f8896e9429dc,0x00003489b6ccc57c}}, {{0x0009d23fe67ba665,0x000043cf2f340e29,0x000fcf9139145076,0x000ddaa45b5ea997,0x0000be00843dbd7d}, {0x0003e05d53ff04d3,0x00032de91ef7358c,0x0009ec1a0bf7ccdc,0x0009977d684dbfb6,0x000067e7cf2b01fd}}, {{0x000d227cc2338fb4,0x000950e2615346ff,0x0001a007689ff6fa,0x0003af7e57077933,0x00003d241c546e1f}, {0x000b97dde9b62a31,0x000490ae30eafdcd,0x000bddf7d6a06e98,0x0003c4b9bf16804f,0x000070471a2e3616}}, {{0x000a8ae3113655ef,0x000a67b83180ff5b,0x000e0eabefa2c6e2,0x000a962c48271977,0x00009f3c556237fe}, {0x0007022a42581cb1,0x000208f710e3340f,0x0002e5aa8e1de0bc,0x000940de640adef6,0x00006b2389159428}}, {{0x00019e455950cc3a,0x000bb6b66bb83616,0x000ac6d84c71d665,0x0007e34a034b34af,0x0000987f83385e4c}, {0x00027727a79a6a7a,0x0007426d6c23a074,0x000167e1056e5d01,0x00084dde50b97638,0x0000a6c81f0888aa}}, {{0x000f3b7b0dc85957,0x00082f1d9f2e0ca1,0x000dd82a727de460,0x000447aaf3bf39ba,0x00009356a79d5862}, {0x0002345f5f9a0529,0x0008839a42f9c060,0x0004d40fc1a8b0f8,0x000368253eee4284,0x00003b0bfe5de5b6}}, }, {/* digit=25 [{1,2,3,..,}]*([2^100]*G) */ {{0x0003a5dc8de610b8,0x000ae7e223ce0f89,0x000ad6dc5e8c515f,0x00028ef774bfa64e,0x00009d20f96125c7}, {0x0000966098583ce0,0x000493f2a7d77a1e,0x000304d4aa2eedb9,0x00082d1b2820974c,0x0000842e3dac0772}}, {{0x0000e9d74cd06ff8,0x000f2ca3eeaca101,0x00063aa2b9c17c7d,0x0004fef4c86cd380,0x0000595c4b3f3461}, {0x00000ca990f62ccd,0x0002fa0c3be5a3de,0x0008ce9f5d9bed21,0x000443a886078adf,0x0000db27ce42cd44}}, {{0x00097befc15aa1ee,0x0007d54b07455a30,0x0009a5f1240d1254,0x000ee57bad470651,0x0000d03f7188439d}, {0x000bb6c4a02c4997,0x000d5ffe71d20794,0x0003adcaff725083,0x00030fbcad75190f,0x0000f68ea1cb3729}}, {{0x000581d26ee83821,0x0005259d638e9c7c,0x00028ae3dcf17dcc,0x000047de8273abb7,0x0000d1129270821f}, {0x000847750491a746,0x00019de0dfb91149,0x000a435ab687fa76,0x000e3ecc2580227e,0x0000b8bdb94f1ce7}}, {{0x0006d8af7f91d0f2,0x0001882a57289c80,0x000d767543b61b0f,0x0004c62640032d94,0x000073eb5de67d83}, {0x000abf77b4e4d538,0x000f5e4017772988,0x0005071b3b7ce66b,0x000a981fba6b3271,0x00002413c252d3a1}}, {{0x0007b7e3cc8ac855,0x00078d02753b7553,0x00037df2f8d725f5,0x00031dad05ff64b7,0x00005fe871346d25}, {0x00004a96ab6b01c8,0x0008fcd9372457ce,0x00086699b69a02a8,0x000231cf82ac35cf,0x0000242d3ae1cb4b}}, {{0x00035269be47be0e,0x0007eb28fea169c4,0x0006c67e5323b7dd,0x000e461a5538ba3a,0x0000f921d70fd378}, {0x00061fc3c4b880ea,0x000df8940a67f929,0x000f0ff393f6f914,0x000f9c0990eb0afe,0x00006c2921090eef}}, {{0x00003a553fb2b560,0x00074e057f78b23a,0x000e490d96ce141e,0x000e75796525c389,0x0000bc95725a31a7}, {0x00067911220fd06a,0x000ba08b0bd61ec5,0x000ebeba9716e3a3,0x00066f91cd6bf7e8,0x00007326ca75ee6b}}, }, {/* digit=26 [{1,2,3,..,}]*([2^104]*G) */ {{0x000c982cf7d62d27,0x000cb3ba815020d3,0x000763f9e1f36e29,0x000006d8ae0bf092,0x0000a527e6b8d3a7}, {0x0009097581a85e38,0x000f5c158be5b4a8,0x0007d726e1f1a520,0x000862798db37d16,0x0000802786e9113e}}, {{0x000149e36f09ab05,0x0009fa10bb5befb2,0x000e2099803f163c,0x000bab8029704506,0x00006f0af006b5a3}, {0x000cfec70880e0de,0x000ede3d913f7af4,0x000ceb4bd7332a66,0x000f5452e6c84a7e,0x0000dc4a79b7c228}}, {{0x00094d1f4c6b6ec2,0x0006f8b3cd9bf6e8,0x000117fbf526b082,0x000bf553f952a812,0x0000be864b031945}, {0x0008ea542099b646,0x0009a7548ce286f1,0x0005c1c9c2770b28,0x0006c337390f2829,0x000072e6a442b520}}, {{0x0007dd0c55c44969,0x000695bbabd2c37c,0x000d7f363a6a9635,0x0001decb7e63f2ad,0x0000dce3782be73f}, {0x000a16ab2b91f71a,0x0002bba0163ce1e5,0x000e515ade448982,0x000ecf52759c32f6,0x00005e2f1f92615e}}, {{0x000e2c847c643671,0x000f35af4ec0cacc,0x00034042c6a496b9,0x0002ea1a0836f360,0x00004a1f3901b6c6}, {0x00093633ef1f5404,0x000a32a76d93e7fa,0x000eae451d323b30,0x000f87bfeec8b50f,0x0000eafc172fd04e}}, {{0x0009be7abded5516,0x000868b744107451,0x00010d9a903d358b,0x0002b6ed00b10b0e,0x0000392b0b188da5}, {0x000a2980b75c904f,0x000db8f7f96c6744,0x0002cf932c305b0a,0x0006c9142e421d18,0x00006fc5d518e463}}, {{0x0005a51b3e59b897,0x0004d133a1c9e443,0x0000bee591361395,0x0001e417f4697344,0x000014710f870c40}, {0x0004bced6c446c96,0x00060c4d5368c0cf,0x00068fc37e0aa7fd,0x0000577e5d811afc,0x00001febd7317c2a}}, {{0x00047c9d64cc78c4,0x000b5b6cb27b7958,0x0008022ab6c50621,0x000a1cc7099bf8df,0x00008f862ec004ed}, {0x00032ede1603c166,0x000efc9a9450d127,0x00029b4fc19a80e0,0x00051582257f54b4,0x00006d3b2c6a5460}}, }, {/* digit=27 [{1,2,3,..,}]*([2^108]*G) */ {{0x000b7bc453cadd69,0x00072c0bc1f88de2,0x000abd3af203900a,0x000ffb2cd86e47a6,0x000011cac131502e}, {0x0000242ec965469f,0x000139e0017e2d55,0x0009798850e9f769,0x0001ee733f078f65,0x0000b87d44a3cf75}}, {{0x000e2a2d551ee106,0x0008127e09a66066,0x00001148d87a8f1d,0x0003fda0d08bab2c,0x0000da8e4f1a24f3}, {0x00017f0cf9a4e718,0x000fbbf5cb19466d,0x00062ecc0ff50200,0x000ac45ccf97d8d0,0x00000c0d9b001d80}}, {{0x00045ff1d7aadabe,0x000ff5f6a67c1a04,0x000cfb26f65d3825,0x0001d58e62fb0891,0x0000f1e0fa63c7d9}, {0x000c7ba33db72cdc,0x00093a7c74b247e7,0x0000a503c017cbc0,0x000a417c931590f5,0x0000ac54f61216ba}}, {{0x0007ceb1bf4581ca,0x00060ca7b1669885,0x0009722ace635e18,0x000006878ddd2265,0x00000903c4cbdb68}, {0x000458948f214029,0x0004296abda2366e,0x00040319031b49c1,0x0003fda29c4b09e0,0x00007197ca4629f4}}, {{0x000dd5d4b07e2b19,0x000afd9ea2217173,0x00005ab14d144c4c,0x0008f158b04ea411,0x00002dda5438e80d}, {0x0002fa8cf03dce66,0x0004ba22cffce998,0x000ad88c48b5ea96,0x00095c97f4ea7f3f,0x00002db773eca5ba}}, {{0x0003fb4820357c72,0x000e4f1458ad18bd,0x000b44aa1992039a,0x0002817a1df3c525,0x0000d7803580d3d5}, {0x0007e4dc77ad4d4a,0x000859df4fc458cf,0x00071205ed49a799,0x0004a9a465a8b51d,0x00000ee0ea704925}}, {{0x000e6e89c92b2350,0x000e6b3993a14baa,0x0003dd031a73bbd0,0x00081cd06d60ec69,0x00003cab91b71568}, {0x000862f1db3574b2,0x000544bb061ad615,0x000181e06485b018,0x00075707434988a0,0x0000cd61ad4e1c0c}}, {{0x000de1cf3480d4af,0x0006cc8acf1a03e2,0x000295a9cf0d8edc,0x00097d023e330368,0x0000add5f69b546a}, {0x00097ad96f8acb1a,0x0004c71bdae28955,0x000dd43f4bddd49d,0x00041976fcd52821,0x00005a4541306191}}, }, {/* digit=28 [{1,2,3,..,}]*([2^112]*G) */ {{0x000b6bfc360e25a8,0x0004875a1a788ce9,0x0001732f4e642519,0x00057a1dc756a848,0x00003c0440fd432b}, {0x000b3f1d720281f6,0x000e7135e051c670,0x000052be72205910,0x000a397ed14b0edb,0x000097b3d282568e}}, {{0x0009b9afb3ff9ed0,0x000b17f6515c2e59,0x0004da44928c2e0a,0x0004521cbee4fd47,0x000071279a44f364}, {0x000ff6601fbe8556,0x0007ffda51c497ab,0x000597c0b3ee394e,0x00034ab90385f667,0x0000e9fccc7027ee}}, {{0x000de9314092ebb4,0x000d028e240c0b89,0x000d2f064f17256b,0x000b148f89a7f393,0x0000f57841f21ed3}, {0x0004405e708d8553,0x0001d3f1c3d04ee1,0x000d7eed5856aae7,0x00027098e5424fbd,0x0000333e4efa3ab4}}, {{0x0007adedda492f81,0x000a682972053bc7,0x000931b4cc11a3ae,0x0004bb4e89a3e734,0x00007512e2eaf569}, {0x00049f3177bf8b6c,0x000948c7ff3e5dc3,0x00011145d232ea4b,0x0009c2dc4f9d16f5,0x0000cf109a3f3b37}}, {{0x0007a88a1f258972,0x000f81b5d4d8e75e,0x000f3ed5c7ac6961,0x000dfbc3e1077308,0x000008a54ec2a892}, {0x0006e1978660710a,0x0006837df2c8be82,0x000704da50cf70a9,0x0003fca18a7340ed,0x00003eeb9a9a8ca3}}, {{0x0006233169bca968,0x0003ada6aafb49d9,0x000c2fa9404d286d,0x000fb3409606eca0,0x0000869d0d5a3ff0}, {0x00037e5d0150d651,0x0003140c14c9a999,0x0008e2d49a92e250,0x000e2b556bf94510,0x000052a733ab2f59}}, {{0x0003d588434a920a,0x0002c22103c5b432,0x0008dbf9ac0af8e9,0x000df1c67518ef93,0x0000184307423a9c}, {0x00094aa5447ab801,0x0005b75a3d61350a,0x000411a9ee5e5a32,0x0000c564ba507f68,0x00000581fc1694f7}}, {{0x000857080eb24a90,0x000d488e0cfd60e2,0x00059cdb87bedfb4,0x0000a9721ebbd7c2,0x0000b0da855bc639}, {0x00004dbde314c709,0x000bdc32e8462b4d,0x00062fc9ecdbf1fb,0x000ab6a3833eabb1,0x0000939b48c40dd3}}, }, {/* digit=29 [{1,2,3,..,}]*([2^116]*G) */ {{0x0002c1f711b0eb9e,0x0007980ab9549689,0x0000792dbb905f2c,0x000125cce26309a2,0x0000c8ac9b3e684e}, {0x000d8b6b40a24474,0x00015fe3fb24486a,0x0008e3b3f60121fc,0x0003941626fccf1a,0x0000e568622aad1f}}, {{0x00046c64a8a3d626,0x000fc47743d25a4b,0x000f7e4338469c4c,0x000848cbb3a13d88,0x00002b23a1061be5}, {0x00096b4a63d1a4c4,0x000a3d183f3ee835,0x000afb01c454e7fe,0x000638243fce6117,0x0000e65e5e65c4c3}}, {{0x00077176add85450,0x000672c49b66e5db,0x000421d771b71cb6,0x000fead856073968,0x00003840fe883e3a}, {0x000dad51ec699775,0x0008e07f6726b391,0x000ca160cae243fb,0x0005f4788ac87be8,0x0000174cced9ce35}}, {{0x0007eb6cbc613e57,0x0004d97ea61cc1e1,0x0007eded533131d5,0x00011abf69d39eaf,0x00003c2f4354e6af}, {0x0002493a4a375fa7,0x000c4833c5c24ca5,0x0006e71cf5f06787,0x000666114e091f3e,0x00006451f57fb746}}, {{0x000ab8495fe1347f,0x00087f24503c5ee6,0x00086dd6bab0f6c3,0x000ef4907e3ffb44,0x000000b6c757002f}, {0x000f9a6a78629992,0x000c9ed89e2648bf,0x0008419eb85e5a06,0x000f1666d311af3d,0x00004f3ad7854733}}, {{0x00003fc6c68d6876,0x000cbff052c75e3e,0x000d16e7a3e732c3,0x00074692d0efa66e,0x00003d92b27165bb}, {0x00082badd44867cb,0x000e48c081b8ffcd,0x0006c8785a71b4a9,0x0002cfbc1676a773,0x0000e2c06174d893}}, {{0x0006d282bcffbc46,0x0006a6eadb7a5337,0x00035ae69708817a,0x000fde0ff50e05cd,0x00003b5fb75d4bc7}, {0x000e953e7fe08c4a,0x00045583ca1871c9,0x000e81c5cb4d8bfd,0x0001383e8d788245,0x00005f5e93d80474}}, {{0x000bdef694db7e04,0x000779fcddc680f9,0x000b8dce1edca878,0x000ba111981c3403,0x0000274dcf1b0e10}, {0x00043b86def6d1a2,0x0000cbdb1866f727,0x0000c6f58d25b167,0x0007f5a4491e8c05,0x0000be2b2aba7fbd}}, }, {/* digit=30 [{1,2,3,..,}]*([2^120]*G) */ {{0x0005c9dd111f8ec7,0x000d47c4e7603e0e,0x000392a51bcc33f8,0x00092d002f9a91bd,0x0000da4a7963132e}, {0x0000ae30bb1151be,0x000722e322511a0b,0x0004e9e7854febac,0x0000b80a3a508269,0x000058ffec2c4fe4}}, {{0x000349d29c4120ba,0x000f20d0d915fbb8,0x00010ba519f94391,0x00091124074fa754,0x000066adbf6b50a5}, {0x000543c34bfca38e,0x000fd9e1ccfcc164,0x00020219ce0f2755,0x000979b9da0f53e8,0x00008234499a6b49}}, {{0x000c513516e19e45,0x000775c4d5937b23,0x000e71ef656e2e84,0x0004c54f727d735c,0x0000b6304a7479a4}, {0x000a7363ab7e433f,0x00000e742f836638,0x0007fc19f1adea47,0x000697f054b8545b,0x0000935381baa1d0}}, {{0x0004f9d918e49366,0x000652513982b550,0x0004d9cb965035ef,0x000508a553a0c26f,0x0000cb10d571ea85}, {0x00057b7a242da112,0x000d472b726848d9,0x00002a96b16a4d3d,0x00063b1d7e637c85,0x00007c7032b930d4}}, {{0x0006b7d5846426f7,0x0008b47d441d5536,0x0006fbf48e7d09e8,0x000d7ce10b404d73,0x0000fa003d15784b}, {0x000614f17fd95965,0x0000e5cb98db25f7,0x00083a76a49e0e0a,0x0000f7dc65957b2e,0x0000d40da8e1ddbe}}, {{0x0008bb4a595939dd,0x00085874021737f6,0x000ad76120355647,0x00095ebe740e7c84,0x000089bc84460446}, {0x000da5d85a9184d6,0x000b3fc0b074f7f3,0x0008a888e562563b,0x000e7ba6d2e6aaf8,0x000012d8643761fb}}, {{0x000bba354530bb24,0x00078b0869ea9fb3,0x000431163bde3ef7,0x000a3549bc90460b,0x0000d03d7d324819}, {0x0004f9e43b6a782b,0x0006ec88a68633ae,0x000ffedd9216db30,0x00083fe1dd88e000,0x0000280da9fc2bd4}}, {{0x00086913e538cd75,0x000c3e08ad53458f,0x0005d15ffa7001f6,0x0005dd02b8c6e6bf,0x000048234a451121}, {0x0009d2d3d5b40458,0x0005ca904190ff5a,0x000607f8bb0ffeeb,0x000729d5a3aca448,0x0000cbd665cb0a06}}, }, {/* digit=31 [{1,2,3,..,}]*([2^124]*G) */ {{0x000a8f833f6746cb,0x00054ea990cac7f3,0x000ddb0a921e46f6,0x000554e15fd5c5ca,0x0000d41f01728614}, {0x0004434426ffb589,0x000584dbc204346f,0x000969b7f8055943,0x00039a63dd20fe5a,0x0000d59e9577899a}}, {{0x0000ba9b733aa5fc,0x000b305af2353c2f,0x000ac82a5dece47c,0x00018a38e3f715a2,0x000097ba641e203f}, {0x000550409c110608,0x0004c6af512dc3af,0x000f2814656ea2c0,0x0004947ac28daff3,0x00007fab43b159ef}}, {{0x000115c775d6ece0,0x000be8c0e78def4f,0x0005cfc8169d2e3b,0x00088bb0264ef114,0x0000a41e9fa1b697}, {0x00033be909a1f0b1,0x0001fae76b300d92,0x00032bb69150a845,0x00084ada33753706,0x00005f7b3cfba255}}, {{0x0001641d4c5105f3,0x000e3d7fbd650989,0x000e6bdb01ae80f8,0x0008606d67225fbe,0x0000b433b59afc4d}, {0x0006db693e856387,0x000273e9862f44e6,0x0005c32ecf7b5925,0x000f506b78515766,0x000002fefd81e362}}, {{0x000a9141339609ae,0x000d5e37eabd6eb4,0x0008c8d9c2b627de,0x0001e40a4083d172,0x000070814d5318f2}, {0x0005b5717398d14c,0x0004c003f6c94cb0,0x0008292759d37d25,0x000e4eb0577af760,0x0000b4a9a9b867d7}}, {{0x0006a5c97290293f,0x000be388acbffe75,0x000916bdabf04a19,0x000bec0bbbb9cf5e,0x0000489527481f93}, {0x0007ec32a5923d75,0x000bade0c370dee0,0x00019d8fcc7bc949,0x00093f6d51217504,0x00004f5d4768fdcc}}, {{0x00005f7d13fb27da,0x0002cc7195c0c20f,0x000fc56c5c05b30d,0x00082b0335cf1832,0x0000e65bcd402b3a}, {0x000aab8630d99eaf,0x0005f62cec6ccbf6,0x000eed2f1164be81,0x000d0c7d41819d2f,0x0000cdc5907fb91b}}, {{0x000475d0fefb0c3a,0x000aa6d7c35d3754,0x0003798a4d48fb56,0x0008e60070b63336,0x0000e89f3d32fdb9}, {0x00089c86363d14cb,0x0000b7abd27d970b,0x000d5a0218981752,0x000aedebf7d47444,0x00003083bb07ac72}}, }, {/* digit=32 [{1,2,3,..,}]*([2^128]*G) */ {{0x000c244bfe209256,0x00032fdce86762a8,0x00038706391c19ac,0x0004f5fa96a5d5dd,0x00001d587d481d32}, {0x00073a2a37173eaf,0x000763778b65e876,0x000bab43e2384800,0x000fbd20f8441e05,0x0000a11fe133621e}}, {{0x00049feb8a24a205,0x0001a52ca53f23f9,0x000fb485317ebfed,0x00005d4b691bbebc,0x0000617ff6bb278a}, {0x00034c5e3c99ebdb,0x000d6784156a241b,0x0005d67dffc64242,0x0000109206482f69,0x0000967ce0f9e27c}}, {{0x00034a3b23358342,0x000a70ef6860c0f7,0x000e2bb0d9526205,0x0003faab8be71704,0x0000418871e22f38}, {0x00076814082c1576,0x000fc9c20073d717,0x00087e728cc914ac,0x0005fd9186c1ebe5,0x0000fdb3c22c1bcd}}, {{0x0000f0441c23fa36,0x000061989a2eb448,0x000a29ca7b4712eb,0x00028bdccbba0f93,0x0000e205c1536194}, {0x0007957b36416860,0x000d45ac8b4e90db,0x0004e03500432691,0x00051707a759acf6,0x0000514d89c9c972}}, {{0x0004c1c2cf9d7c1c,0x000a2e95e5abcc7c,0x000ae170c1320886,0x000661fb7b9056be,0x00008a5b2519bc0d}, {0x0001432c11d23031,0x00020f03769f4ed8,0x0005398287da6691,0x000d022ac7a5fd84,0x00004dada944bccd}}, {{0x000f7aaf0dcbc49e,0x000890bbb45b7bb4,0x0002ca2e57de551f,0x0006eeefd0f3e49f,0x0000ce58709ff5c7}, {0x0000edd167d79ae1,0x0002ea7d7ec13292,0x00030af91039df8a,0x000b59e46206c0bb,0x0000ff5e2f532676}}, {{0x0000651cbae2f701,0x000583aaa8eb51b9,0x0001df499efc4bc0,0x0007a57ecd8689dd,0x0000aee99a832f36}, {0x00085b9ae8274c57,0x00050d30b39c95d4,0x000c1ef816c14d44,0x0002ed4afea90bbc,0x0000c5f317b1459a}}, {{0x0002c6bc4fe3c395,0x00031c7bebdfe3b2,0x000693459ba4a815,0x000b11a23ab6b725,0x00003bc377064922}, {0x000c8ab5afc60db8,0x0004a0b9f2a34645,0x0000fc507aa02235,0x0002e6d2a2954cce,0x0000c2731bbfce1c}}, }, {/* digit=33 [{1,2,3,..,}]*([2^132]*G) */ {{0x00091c2e48fb8898,0x0002fb8a9d066a70,0x00082a0e226882c1,0x00052d224986631b,0x000044ed736b5181}, {0x000476fd86e27c75,0x0009b4afefdc282f,0x00019e34da04edac,0x00078b3b256ebc61,0x00006a413e95787d}}, {{0x000061d5a74be506,0x00047ea16ff582ee,0x000bfc8a2e41781c,0x000e2d80b0c81e99,0x000024f4d696b547}, {0x000545dbdcc9ae4f,0x0005509b1e8e3a83,0x000c935392573dbb,0x000797582960c4a6,0x000001059ae4ae18}}, {{0x0001e274d559d96d,0x0002e8db6c013815,0x0009921af4f18c0d,0x00002879a3aa836f,0x0000beab27c5c046}, {0x0009eaa7040bf3b5,0x0004c614b091242b,0x0004baf5d39c479e,0x000944e38ede2b0e,0x0000bb192b840a53}}, {{0x0009f973112795f7,0x0007284e6ee1715c,0x000b66bcde824443,0x000bede5cb4858ec,0x0000c1367361baff}, {0x00015955dbec38e2,0x000c188ad1535466,0x000e0952f51c0782,0x000fa87ba4c53ac6,0x00007e6782a3b21d}}, {{0x000c251ec5d7f652,0x0006703940877d89,0x000691ab30c8f561,0x000b21409e1cfcf0,0x0000a0300c009b20}, {0x0002fadb114faf4d,0x0008821bf5d1bf53,0x000fc36de328fc0b,0x000f5fed51f93c3b,0x0000989050f4a4e5}}, {{0x000903d4ed2dbc25,0x00082c3b2d83682f,0x0007e93350eba59c,0x0006d73e9dc84d9c,0x0000f9b21b05eb22}, {0x000d394af267bae5,0x00056e2e15aee33b,0x0008ec500aa86cc2,0x000657ff0bf67d6a,0x0000846aa4549630}}, {{0x000ba38e7e0c2780,0x000e588b2e6f6786,0x0005fee3a09bf87c,0x000394723b702246,0x00008b8411464682}, {0x0002ce029e646294,0x000f8ca78e430eb5,0x00054a991adb60e8,0x000fe4e0dd7062b6,0x0000281d429069a6}}, {{0x0009740e2c2bf152,0x000589e99704feb0,0x000fbc565627a220,0x000de8cc8d73d0c2,0x000023eed8fe20c8}, {0x0002583a8363b49a,0x000929c2b0a61ee3,0x000dbc85c1a0b6cb,0x0001aba9f7c3d290,0x00008dfbb97bef4c}}, }, {/* digit=34 [{1,2,3,..,}]*([2^136]*G) */ {{0x000236e846e364f6,0x000c7ea50ca0c16c,0x00026b86d7f33527,0x00070c6481077509,0x0000c2a36096598e}, {0x0005e52f024e9245,0x00044db4afcaa675,0x000831790e0fa07a,0x0000d5c5c3ce7d66,0x0000b4ef350f6cbb}}, {{0x0004c050f15dde91,0x0007fd5f2b820521,0x000e82b62a47a76a,0x0005eeab254d3062,0x00001a05fe04ec95}, {0x000f46e9d529b36f,0x00009f9e3df67eaf,0x00031769855ab130,0x0007acd463e37199,0x0000d251439bcda4}}, {{0x0007598a9d82abfd,0x000b16c170f5e2a3,0x00066b0875f188cc,0x000ad9b168220050,0x0000a22c21397155}, {0x0005d3afbddb4799,0x0003dd715b99151e,0x00097cb2e4b606b8,0x000b65ba73b54bf9,0x0000a1bfe43cecd8}}, {{0x00022f3dbfb894e2,0x0006ae274b18e131,0x00058aadfbe9b79f,0x00035165a49de5ca,0x0000495775831487}, {0x000ef61bb9390993,0x0009f6d13694111d,0x000fc253b1d6a974,0x00015e1474b4ced3,0x0000a1485e67c5db}}, {{0x000dab61430c9ab7,0x0002b238e9975afd,0x0008042ae0bdd41d,0x0004cb8094743041,0x00001f9addb3dddc}, {0x000c016c52dd907b,0x000c79e2047f7090,0x0001011a6d9bdf44,0x000c7836f1fe801b,0x000063accbd89acd}}, {{0x000acab4baef62e3,0x0002785b91e87817,0x000e576109f5a220,0x000e036666ebe66c,0x00002ad31f4273bf}, {0x00030a425bcf4d6c,0x0002915056e66283,0x000332156ea95059,0x0002d699811c89e1,0x000089cf1ff4c11b}}, {{0x000337ac0b7eff35,0x000e75e48b3c0ad7,0x000f13a5f8552225,0x000cbe96f78b0c73,0x0000e70062ed2349}, {0x0005048e7073969a,0x0009233cb3d26b8d,0x000caa20f392d2a2,0x0007074e4f727c4e,0x0000068c99ecccde}}, {{0x00086ec1ed66f181,0x000bc61fce43ebde,0x000bed74d225d906,0x000ab74cab07d6e8,0x00006e4617f37855}, {0x000aaddb2fbc3dd3,0x000f5aeddf5b6568,0x000cf2fadedb5484,0x000699578f20e86d,0x0000516497c915f5}}, }, {/* digit=35 [{1,2,3,..,}]*([2^140]*G) */ {{0x0003fecfa181e695,0x0000e0d69a98ef0a,0x000eab95d9ea02f8,0x00002162e9cf8e66,0x000020f2beb74720}, {0x000540a1df843618,0x0000f1fa6d5d621c,0x000f5f6ff1203772,0x000ef2ee3c7b510f,0x000017a069c2bb2b}}, {{0x0002fb6b294cda6a,0x000519039f348357,0x0005cbb216ce9bf7,0x0000d980e012f009,0x00000aecc1c7063f}, {0x0001c3af02909e50,0x000f48ce9cdc57c2,0x000e336f8c7d59ec,0x0005f42732b8448a,0x000056e37233f4f8}}, {{0x000b53189e800ca4,0x0006d45208fd8a10,0x00014ba3750fe0c1,0x000acc5e43c0d3b7,0x000027d200e74189}, {0x000e24fe616e2c00,0x0008ee1854c105de,0x000342a739c25f4c,0x0009524d3222a58f,0x0000807804fa027c}}, {{0x000653a4f0d56f34,0x00078a28b805c222,0x00073434b961e404,0x000a18ec03f8b04a,0x0000c966787eb712}, {0x0006c42864fee422,0x000a3b0ece5ccc19,0x00031c159c1be93d,0x000655887d9f22c1,0x0000bb6d593fce45}}, {{0x0009ec9b809b7ceb,0x000b32c72c2c22c4,0x000a0bf368a41486,0x000c68d13b9420fe,0x00003d36eea566da}, {0x000c08a328cc987f,0x000b4a3264616fdd,0x00010dbba0a3bcd2,0x0004c38103c49dd8,0x00009d81a293b78a}}, {{0x00065ade4d559419,0x000da03840873de8,0x000f18b9bdedafa5,0x000267df414abb4e,0x0000ee9ea438aee5}, {0x000aa1637a55a4a5,0x0003b15f93b9260f,0x0009c3598eb19a51,0x00078e01d7ebd29e,0x000023fc56d69321}}, {{0x000070cb98fe684f,0x0009224a1458501d,0x000bc6b3fd60fbe9,0x0007cab45761c892,0x00005384859ee6f2}, {0x00071f7b59e763bd,0x00088b5a8e5e4b02,0x000a482923d4606a,0x0004454eda5d9b05,0x0000a7731d1b6fec}}, {{0x000369390d458714,0x000fc6166d8da3e3,0x000a90403e976403,0x00063775c3368289,0x0000bd17983b2f1d}, {0x000679ed5d2c53a7,0x00088dcf3b87a616,0x0006a694e5ec4bcd,0x0007e53e6d7613b6,0x0000460fc7753fc2}}, }, {/* digit=36 [{1,2,3,..,}]*([2^144]*G) */ {{0x0001fe1c63c4962c,0x0008d81fdb258053,0x0004c2b6b50541e8,0x000fca1c1291a1fd,0x00000693a1866df4}, {0x000604e0117f203b,0x00025a99b8d0b2c4,0x000212c44245f196,0x0002a7fedc20aac6,0x00001ed4e57020f5}}, {{0x0000fb6700a1acd0,0x0003fd999681b556,0x000b4e1bae823fd7,0x0000a3da915d1f6c,0x0000d0301186ebe0}, {0x000b0c989fca8cdb,0x000b49da0e0b744f,0x00031d76f970d01d,0x0009695ad8c56479,0x000015737c0a659b}}, {{0x0007a9c6bdf22da8,0x000f10dc82df18f3,0x000703651efbc432,0x0001a5452cef8e5d,0x00002887ba159988}, {0x0009ddab920ec1de,0x00030c3e8d3b7cec,0x000a88747d0d7e8c,0x000534645bc3954c,0x0000deaa2e17fd53}}, {{0x000384ece53c2d04,0x000d1e4606daa12b,0x000ec12b0779d897,0x0001ad653e47b073,0x000062dbbba9756f}, {0x00009f2cafe37b68,0x000f6cce2e1769fe,0x000f607fd273d1eb,0x000c250ac1d5383c,0x0000035f7ff92e10}}, {{0x000cc0f296c9005d,0x0009ab0aebdbb7d4,0x0000ec8d44b9094f,0x00010111bf10f1c0,0x0000807b1c5a667c}, {0x0002cdfbe7133835,0x000e31142ba1a941,0x0000a6bdc435e063,0x000ab9484c15ecaf,0x000092c2460e2a3d}}, {{0x0002d5a2093c22a9,0x000145703aedca44,0x0003287b6ebd0bd3,0x0008b9a08f2afd65,0x0000bb88bac9d1bc}, {0x000853875c1e3b2d,0x000ffa11447cfbaf,0x0005c4c8dbd2ac94,0x000207586d816cea,0x0000c3aa800f8dc3}}, {{0x000690016e23e9d2,0x000b87cc41e19365,0x000d6245ccb220c6,0x000a6a936b20c369,0x0000d63c348d62e9}, {0x0003e19cdc0bcb5a,0x000eef601b98a347,0x000e346e470f18b3,0x000a63ead7a2c7cd,0x0000e9f6ec45d3aa}}, {{0x00034c77e6c55202,0x000fbcb9ea58854d,0x00086666dc27df9e,0x000a85205f2369d6,0x00009d1febf2417a}, {0x000819e93470afed,0x000912a27f9e9846,0x0001e65043e6a966,0x00080954d008a2e3,0x0000ba7ced06cb76}}, }, {/* digit=37 [{1,2,3,..,}]*([2^148]*G) */ {{0x000f541338d6e434,0x00030541d5ccecaf,0x000bc88ca56f7dd7,0x0002c375d426de96,0x00008d94f6bded3a}, {0x000a3bb2ef8279cf,0x000a1b1867f26354,0x000225151d575465,0x0000d7ff99b0ff95,0x00003e19d89e9450}}, {{0x000f6ce51efb3108,0x0004158df5be0d0d,0x000158e59cb5b2eb,0x00033656459e2936,0x00002aae2b99466e}, {0x0008a39411aa636f,0x0004e4c0a933fb65,0x000f026b77152ecc,0x00011f010c758a49,0x00004837f98bb093}}, {{0x000f364b71698f58,0x00021f7b605e7807,0x0003b2cbb6ba418d,0x00086f7d20b00fa0,0x000083eca385a543}, {0x000e43ff3437f24a,0x0002048bb33cff0b,0x0009df765e910b43,0x0006f6a963a12832,0x0000c1dd5575e2fe}}, {{0x000523a626332d5d,0x00028561bb44994f,0x000845ea27bc3883,0x000089305ed4b03d,0x000039d3ee292a1f}, {0x000fdd3e7676b0dc,0x000f3b7060176561,0x00064f9a8620e35f,0x0001f676ce424ff2,0x00004c341a09a268}}, {{0x000861cf405ff065,0x000cf86e828b1c30,0x0006933fcebac86b,0x0009479791a97163,0x00000e7c2becaeee}, {0x000a095fa90d7679,0x000b5670ab7bc3d4,0x0007b056dae60eb7,0x0002a987633a6439,0x00003a21f33a0501}}, {{0x0001f22369b87ada,0x000892fca556857c,0x000b064663c00e5d,0x000af17ad74cab90,0x00007112386f50fa}, {0x000e1986d9bd5f51,0x000849c3463f7435,0x0007bd4b22dcc7e3,0x000f31cc7df748ca,0x00003cd4c08adec2}}, {{0x000e46022caf46b4,0x000f5a96fe4f5936,0x0008f474e6a45dd8,0x000f15b7925434b9,0x000014104124053e}, {0x0008d1241de97bff,0x0000cd80bef471cf,0x000db0037b8547b6,0x000dfec47d3970c4,0x00001bcd329eef20}}, {{0x00031769bb816483,0x0005353120d000f8,0x000cabc62d69eb48,0x000cb1a17d75f44c,0x00004a07f82e749f}, {0x000f787bbfb55541,0x000052e283f82c3a,0x0009213a0b06ed4d,0x0007b44722889fa1,0x000062b085eecf3c}}, }, {/* digit=38 [{1,2,3,..,}]*([2^152]*G) */ {{0x0000d2f7189e71f4,0x00081ecf91e73267,0x000757a21c643874,0x000ce4d5758e57db,0x000027d09f8690a9}, {0x000308f38384a7a9,0x000420732b99846a,0x000845819aac3acb,0x000e030e94100917,0x00005cba11237ce5}}, {{0x000851aaaca5e9b7,0x0000e6713b9797b7,0x0000a61f6518aa52,0x000b68c357e8c715,0x0000842e7e35c2c2}, {0x000af656868a5489,0x00025068fc818dff,0x000917733d963bd8,0x000327d4da5c8b65,0x000027091000b247}}, {{0x0001e48a105fc8eb,0x0009789ba48c37a0,0x0001c2180769d754,0x000387108c6fe1d5,0x0000032dd3467bd1}, {0x00026db020b0aa69,0x000f7664c73c9538,0x0000cf95d05137e7,0x00028a366302c466,0x00009004e1242cef}}, {{0x000c9a7d298c241d,0x000986807cfd214b,0x00064eadbe3b697b,0x0009c51f1c780245,0x0000de8cdd084814}, {0x000f0a75a4d2604d,0x000e9c1538af946b,0x0005b1fcc27154d7,0x000f81c5cc9230de,0x000088519ea36864}}, {{0x000e4f796ea6ca1f,0x00092f7928711013,0x000658d45567cdc2,0x000e97bdb728705c,0x00007c1ff4bbe600}, {0x00086574b6cad39a,0x00041a20b428a1ba,0x000e6fdfb3d58d63,0x00060d20011cdea2,0x0000832367b1b189}}, {{0x0008c9f0e4938f75,0x00098c83719e4761,0x0001a64cc58d47d6,0x000f66874c1a23f4,0x0000d28e06905829}, {0x0007529210466f66,0x000f66a64ef8d8d3,0x000ce6a7a2af1152,0x0002d6f5d4485c19,0x0000d0bd2f65648e}}, {{0x000032af416448df,0x000ffc76d9711ecc,0x0000b6eae4a7e8c0,0x000593954f9805b9,0x0000d0b15333bed0}, {0x0001848d98b5ca3e,0x000c1039b3ef89f7,0x0007bda2ed01fe5f,0x000e406481332e62,0x000067cecd885073}}, {{0x000dd1a7cb1282c7,0x00064e46973ab828,0x00008d6b2a08d762,0x0003f2fbaf8d40e7,0x00002571fa1bdaeb}, {0x000732ff22dfd98c,0x00064087108d85b1,0x00088207a87ab01a,0x000754eaaafea859,0x0000cc832f929f00}}, }, {/* digit=39 [{1,2,3,..,}]*([2^156]*G) */ {{0x0001185ca8d9d1ae,0x000cf987ded2488f,0x000c46124adf2c77,0x0005f37f3039f060,0x00005d70b7651e09}, {0x00086506260e70ff,0x00070750d10582d5,0x000bac36439d75ea,0x0003289cf3d0b175,0x00003a7564e11d01}}, {{0x000a43e3fcd3efca,0x000418088e9ab24a,0x0003d46eadd26c03,0x000a6f05ef4dc9bd,0x00002f99d592a4c6}, {0x000d3552f1da46cd,0x000d4afacdd1ddab,0x000d4057872c3f8c,0x000b94090c4eee92,0x000028bb4209a623}}, {{0x00092d2e7417ce17,0x0001270ee7f52427,0x00067a41eff42bc7,0x000a57aff4dc6d5c,0x00007709b7b90882}, {0x000731dbe217f2cb,0x000cabb721773554,0x0001dd0592af2a8c,0x000476a8eee76959,0x0000b2930c9fbba6}}, {{0x000dddaf176f2c08,0x0004625726581e6a,0x000342ffb01ca460,0x0008d58a404ded85,0x0000cf60f96c4183}, {0x000691cc9071c4aa,0x0003944428039bbc,0x0009c0d81fd58874,0x000f7ef7101c8580,0x00007fb754d2c456}}, {{0x000a1d5af71013f7,0x00049bedc9466af7,0x0007370a0e68216e,0x0001cc84cba30bd2,0x0000981afbff7042}, {0x0006a679449f0e1f,0x000d1a47edae0249,0x000feca2286cfc4b,0x0008fa4073c936b1,0x00005694612f3f8f}}, {{0x000d6715bde48f8d,0x00025189bc7dbcad,0x00009ee8ac970387,0x000ff78d45299ec7,0x00001287ee3545aa}, {0x0008874db1dbf1fd,0x000ac90c88d67d1f,0x000368313ea46588,0x0003ad90ba649a84,0x00005fdcbcf30d54}}, {{0x000e9959890272db,0x00098e713a10cf3d,0x0008227b875f3432,0x000dc7ae13479fe2,0x00008561eaaaefac}, {0x00097a08332aafd7,0x000503809b62a6a2,0x00063036f9b0d8bb,0x000da862fa1cfd0c,0x0000a16eb562d64b}}, {{0x0008e8a2ac13e274,0x000f0eb1a9f5f7e4,0x0001f0a624494f6d,0x0008f0adbf84eb98,0x00009badc3293643}, {0x000a541004f7571b,0x00002f1c94ee50be,0x00027bc31bac67d1,0x000e27753d73a1b7,0x00003d01cf2e0686}}, }, {/* digit=40 [{1,2,3,..,}]*([2^160]*G) */ {{0x000e50f6d3549cf8,0x000f7acd665ed433,0x00011fcb46f33696,0x00085fe95bfdacce,0x000010ee2532f7c9}, {0x0000fe17159bb2cd,0x000da58b357b6545,0x0009fea72f7dfbeb,0x0007445b057e74d6,0x0000485717b62731}}, {{0x00042e8ee36860ce,0x000c6113c22d896c,0x000104213daf04df,0x0004e93adbb7b744,0x00005fd5fa1ffd39}, {0x0005d941a4e0551e,0x000d38d101516823,0x0009845236772cfb,0x000a97476071e309,0x00004e879df3a56b}}, {{0x0000aa9b898fd522,0x00079e9af1a76c8d,0x0004f03f82fb38a5,0x000c6fc1f2b9a93b,0x0000b1aad44e3f0c}, {0x000332e7cf2c0846,0x000ea367d26d58b5,0x0006e4a8d1c57d96,0x000b69c297eabdfa,0x00005a947eeaa0e2}}, {{0x000afb0285b94916,0x0007be4c705eaaaf,0x000d9caab01a0be8,0x00033f9f1d4f5d2a,0x0000e349a4b237a2}, {0x00012464a1c6a163,0x0005f9383260cf1c,0x0006d5471d99e6b6,0x00089bba3d43665f,0x00006974d052f8cc}}, {{0x000b616fdd5b8549,0x0007c728719ff535,0x000921cad592549c,0x000ef85231468606,0x00008c8ce34c11b1}, {0x00037e7e9090b363,0x0008dbf7bbb728b9,0x000d8797467fc3ab,0x0003fde2337097a9,0x0000e5adca22970e}}, {{0x00049a1cfe89d80f,0x000cea9c8371c26c,0x000d066d2b42c026,0x0003edda6c013ada,0x0000b8f722946a4f}, {0x00079ecd850935b3,0x000ca631e1b308b5,0x00019853434c1a74,0x000f259b5fe596ac,0x00009ff21f711f24}}, {{0x00068a7b3f85ff0f,0x000c2a888044cdcc,0x000dbe894acd21cd,0x0000d3c6719b2e05,0x0000ae1d3d97b826}, {0x000dece8a1c5d92d,0x00040c52077eedfe,0x000dd13edbca01a9,0x000aacf085549c16,0x0000c5c3baf195eb}}, {{0x0009e148f9290579,0x000630c853df27f2,0x000e9c5ce7a64ae0,0x0002a4956cd18358,0x0000d9cce836ed09}, {0x00059796e93b7c7b,0x000181bb9e27cc6e,0x0009e29a0e1e4709,0x000644070b3083aa,0x0000f181a75e785e}}, }, {/* digit=41 [{1,2,3,..,}]*([2^164]*G) */ {{0x000a13f1402b9d0c,0x00026c7bc863d3b3,0x0008c3e6e573441c,0x00057d8b301ec457,0x000026fc9c4cadaf}, {0x0001bfd7493cea35,0x000ecaf8145696e7,0x0008c608fd05d4b3,0x0002768aca2a8a6a,0x00003ef07f65725b}}, {{0x000c9d646ac49d20,0x000b83137aa9a6b5,0x000225a3842c77c0,0x00090724d000fc68,0x0000f63cfc82fe1e}, {0x000b01bc6441f959,0x00095c8e448f22d1,0x0007fb1ba7d38f71,0x0008df0b33fa5f78,0x00004dcfda1a9015}}, {{0x000ed45526f09fd2,0x000c6128240a057f,0x0002bfd8de8a4f10,0x000a317332efc4ff,0x000014e77a0dd35a}, {0x0006d7314faa40ec,0x000b41e5f1863289,0x000a1813e767867e,0x00079509adf8f117,0x0000b6cda7914741}}, {{0x000de10296c36eff,0x000192c4da77211c,0x0007836da7ee8967,0x00060ac617d270a5,0x00000cd9c328cb75}, {0x000cbf7e455fe908,0x000afe7334f301fd,0x0007de4ec3fb53cb,0x000fcff81e2ea44e,0x0000adab3ad8b384}}, {{0x000d47d53b618c0e,0x000b8a2279231c6b,0x00092d964c424f46,0x000bf19303ffdedd,0x0000971287951b5a}, {0x000a632f815561dd,0x000503c055d18f48,0x00025684f85f48ff,0x000cc2522a142775,0x00000d841a137360}}, {{0x0008a2b599ff0f94,0x00074104fc6b0177,0x000694ff368a923d,0x000f121bfa44dfda,0x0000f7199dc37667}, {0x0008ff6e46f2a79c,0x000d29f8131dc06d,0x000b4ce7c08b5dea,0x000c3d42519a59ab,0x00004f710bd742ae}}, {{0x000a90f0e0b040d2,0x000225ff897fb228,0x000fa6122baf02d8,0x0005570aac79e600,0x00004828817ae36f}, {0x0001d31113ec3567,0x000da5eff1f8b952,0x000d417159e48861,0x0001b7baa1d412e0,0x00001f86203c3f13}}, {{0x000368b4ed80940f,0x00058a6fcedd3014,0x00097579f67e6d05,0x0007f58c208c49ca,0x0000e3d7a8292359}, {0x00032027e096ae27,0x0006b4b393665e20,0x000dcdffcb1f3e1e,0x000e82b6da26f32f,0x00009422f1dd097b}}, }, {/* digit=42 [{1,2,3,..,}]*([2^168]*G) */ {{0x0002cfb9db3b3818,0x000e54df0a4b263a,0x00004e61f9c3a2de,0x000324f28d06e97d,0x0000b1adfbcc2449}, {0x000d9397e053a1bd,0x000696daf7076ec1,0x0000ac7abee2be5c,0x000173b0ba1e1481,0x0000d2ae779c530f}}, {{0x000d97a205b9d8b0,0x0004056756d40435,0x000f8210e6eb8f06,0x0009ead5e88a8bb6,0x000070ef12dec9fd}, {0x00095053bcc876ae,0x0007c7404ce34d84,0x000a1db5e12a7533,0x0005acf22b49e1b8,0x0000c1f2051f4bfa}}, {{0x000eb79b6828f364,0x0007c1bd5b9eadba,0x000844b0c9d7a025,0x000fc9ada01e0d1e,0x0000b625175c87ed}, {0x0009fdd9669b6210,0x0006f6f87b981410,0x0000df6bc88a2ca5,0x0003f9fe2eb78817,0x0000cea06f4ffa47}}, {{0x00081b5c4e83d33c,0x00089efd488b43ed,0x000eb4d0fd9f3587,0x000393564a620f9d,0x00006927bdc6c6a7}, {0x0008df79f9e0f036,0x000e9cd7e1a945c2,0x000a348f12868661,0x0008e01cf4e8d0ff,0x0000bd4c28499853}}, {{0x000a091289a8619a,0x000fc671b1732618,0x00090c632ef796e5,0x0008fac64e46e590,0x000038062d4be66f}, {0x0004a200573274eb,0x0003f92713946c74,0x000dc0e20d07b67e,0x0005a6891223b26b,0x0000e2d93f29b0a0}}, {{0x0002e533f36d1411,0x00043dfca442f23e,0x0007c023ae84bb3d,0x000c3ba804a48d6b,0x0000e16a8fa86431}, {0x00052adddd472e03,0x0006dd1ee1271b54,0x000a275997d405ee,0x000b3520fc6f1dff,0x000051ac53cef391}}, {{0x00014b84444896b8,0x000f794027fb7efa,0x00084487d64974d2,0x00089b6fdcd0e8de,0x0000c45b260ab489}, {0x000bbc2d84634875,0x0006efbc476ca8fc,0x000f443c0d1b2b3f,0x00039bd1d005b7c8,0x000018f2e6790c01}}, {{0x0006e8c06d75fc1f,0x00064249a89f5603,0x00045e7dd2dcf7bb,0x0002a691dd1d3de2,0x0000578dc4cdbd6e}, {0x0008903df2ce7a06,0x00083c39afac4c02,0x0006404abaee3628,0x0008187c847c3114,0x0000304c0d904e97}}, }, {/* digit=43 [{1,2,3,..,}]*([2^172]*G) */ {{0x0008b33070d3aab6,0x000b3a2cd5e5e4ac,0x000fc91732643672,0x00013ef2eff79b1c,0x000065ca49bf0a7c}, {0x000da59b3efb9983,0x000cd52f13415a8d,0x000f9a5308a5b922,0x0004d77e9ebbab3c,0x00005986e7c256da}}, {{0x000cf4fda79e5acb,0x0009d630215f534a,0x00085756e68b83b3,0x000cb1ac748b2ed0,0x0000031725995d37}, {0x000841ac5ccc2c46,0x000add9d50696735,0x0001754bd7d7dc96,0x000dd54147e410fd,0x00005296e953399d}}, {{0x000b3edf0290a8fd,0x0005fb47c387831a,0x0004efb4fcae8196,0x00010ddad7dece18,0x0000cfc53b417491}, {0x000f23c4cb632f9e,0x0005d91f80676698,0x00084180ac42a1ad,0x00026ed116a81d62,0x0000bedf5f9c9013}}, {{0x000c4cdb30cfb3a6,0x00010c9db4c8d7e0,0x000c8d9df6d09b8c,0x00066ce0ba1a4207,0x0000fd495f77c52c}, {0x000169f275264daf,0x0005f57d8362fb0e,0x000ad722280c2b74,0x000c7afdd987f749,0x0000dc229b03398e}}, {{0x000fe5a59b0ff628,0x0002c094d0d454a6,0x000437f1d25ec81a,0x0004dc7cfd834e33,0x0000e98378c26760}, {0x0007dd6f48485983,0x000f32fda36a5313,0x00074df4687f2c5b,0x00005640dc1c27ef,0x0000ebf428f3a86a}}, {{0x000ac7ad0d350a3a,0x0008705a1f2f6713,0x00025404684f6ebf,0x0006f677a1495816,0x0000fa5e9a54ef40}, {0x000af7c1cdd69b63,0x00002ee86474f97b,0x00027f62a64081a3,0x00052cbb9f7f0912,0x0000e47f1dc64856}}, {{0x0005e7fb7f01d83d,0x000a75ccf5cb6f97,0x00070930f5f1f860,0x00087852702eba8b,0x00008186df7fb5cc}, {0x0005da01720468f0,0x000100464c808c06,0x00077e1ca4247726,0x00042fd8c4bbbec2,0x00004aaea1766ba6}}, {{0x000ed8452666a58c,0x000026a9c3c2b0d1,0x0009064084bcb6e0,0x0003ff7c57411c26,0x0000fc20755d3556}, {0x0001c505294dba30,0x00068b7dd31ea08b,0x0001eca74a30ba28,0x0002b9d70ba90e99,0x000094e142ce762c}}, }, {/* digit=44 [{1,2,3,..,}]*([2^176]*G) */ {{0x000783e979f39254,0x000a6f4c89a7b81d,0x0001bf7fa1efd130,0x000a9e125c2144fd,0x0000b2969045b265}, {0x0009634b9db65b69,0x000173599d8aed8e,0x0003563f335c82e3,0x0008ab4aa7a54f40,0x0000df088ad922c3}}, {{0x0004f124237b64b8,0x000963ecfd078d08,0x000845dd8688ebe9,0x000324d7b8a70cf6,0x000008fc59cdda4a}, {0x0002b2ba3585862b,0x00053df29386a903,0x0001ec29bb66825d,0x000dc805a5a8db43,0x0000b143a98ea1e8}}, {{0x000ba24f111661eb,0x00040105eb049e93,0x00024b578edced48,0x000068e6dc9ba1f4,0x0000f8f66b8983e9}, {0x0004df4d7ed8216f,0x00069e2cbecf872d,0x000e73754bf07f37,0x0007075281d89998,0x0000ec85fbc7aab8}}, {{0x000bf22765fa7d04,0x000fdd6a537013b5,0x00080db9859805be,0x000ce327a5e29d42,0x0000f53916fb76b1}, {0x000f61f33ddf6269,0x000e1085d103714f,0x000809ee34206238,0x000b1c8c50d4b7e5,0x000099f450e15f8e}}, {{0x000be731a3a93bc2,0x0005821adc1a82ee,0x000030efd42bbf46,0x0007bba10b6fa4ef,0x000047aa4c7a7b09}, {0x000c632f60c77da5,0x000a7223523e8b8d,0x0004579cf6ffbc26,0x0000f654f6ff1134,0x0000825653ce8025}}, {{0x00067ba4a493b31c,0x0001dbf7f0264bf3,0x00095914b54f20a5,0x0006abf696e06297,0x0000ddab96e4bf23}, {0x000c70aed25ea138,0x000b01cbbbe74ff2,0x0008544c5fa1d09e,0x00031708fc8c8746,0x000047a670de96b3}}, {{0x000c595d314e7bc2,0x000b267899ededa6,0x0001ed5d32ee7464,0x000612fcef423c0a,0x000017e76ea89cc7}, {0x000ce1fe7cda917f,0x000a9a893f1627cc,0x000c74f6b12d8016,0x000e60ccd6de849f,0x0000a5817e3e3144}}, {{0x0004cc5ac751e7b7,0x00028d4211bdb79d,0x000de4fc693f9647,0x0000641c72d3d2c8,0x0000b69cbf64f44f}, {0x0000ca2f4bf94e19,0x0008612894e23da9,0x00017d60b1a5325f,0x000b5c7a437f6c79,0x0000be7048726c9c}}, }, {/* digit=45 [{1,2,3,..,}]*([2^180]*G) */ {{0x0009976e1337c262,0x000db73d68e5949c,0x000b768d96faadeb,0x0000697e158614f1,0x00002dfa557bcc4f}, {0x000da17be93c6d61,0x00019504f5b9ccd6,0x000694da124866c6,0x0008c61121353c8d,0x0000c6ca5801140b}}, {{0x0004a7dd4b79bb87,0x000ae2c878c8f160,0x00047b8e8aee806f,0x000053c4144f118d,0x00002edf52c049f9}, {0x000a84e2127015a3,0x00006cb7cef3ebfc,0x0006deec89051d0c,0x000d7456e8fe5829,0x00003b2818871010}}, {{0x00060ed9aed9f40e,0x0000732a8c99bd56,0x000c371ea70ca6ad,0x00009ce4978bfb95,0x00005464d0e50031}, {0x0002fdfd9e535ef8,0x000718c9185b1af3,0x000b42488abf57ea,0x0006fa6d7a741712,0x0000e0296a869728}}, {{0x0009383171b445fe,0x0002a131ad4c0107,0x0003987e89bcf21e,0x000c8eacdfe205c9,0x000063f4153a92e8}, {0x00062a930add43df,0x0002d980f05a7294,0x00006e96862ebb14,0x0006b05f3954e53b,0x0000e1d75ae142cf}}, {{0x000416e1f017d5eb,0x0005c674e99b8b57,0x000f488a03753339,0x00095dbe6d94c0e8,0x000093a787b8c16f}, {0x00051a2dcc99ccc0,0x00039aa47c1dc3ac,0x000dfd8d5c134b41,0x0001edf28fcdafaf,0x0000d57bd8e10b83}}, {{0x000fbccf0bcfc46a,0x000e15cffee69276,0x0005d915b3a822ac,0x00076b928ed2fec7,0x0000145c11463594}, {0x00081538be17bcdc,0x0002ea6c3d8ff61a,0x00016c82f01e867c,0x0009af9634e15d65,0x00001437bd32948b}}, {{0x000d2006c19d4c7d,0x000711b1e976d2fc,0x000f237e8a0f3c43,0x000bb120545ff694,0x0000d10ec4090bf8}, {0x000696cac7cd3e1f,0x000b6f24bfe64f89,0x000af7706ed3714e,0x000c31463eb1d85f,0x0000cbd604eb027c}}, {{0x000c6c7af8685c8b,0x000d7f8f01aa5f95,0x00074692ad4c1c8c,0x000068144bbe3225,0x0000800347984a4a}, {0x000c6e52eca3cdb7,0x000b7c04d3997c8f,0x0002bc5cfea1db16,0x0003d2405bc82e8f,0x000063d518064479}}, }, {/* digit=46 [{1,2,3,..,}]*([2^184]*G) */ {{0x000963f4c8303203,0x0000603203e3f3b7,0x000327afb842c7aa,0x0009b67f22ca0ae7,0x00008e13092c6760}, {0x000fb62757558f1a,0x000157eca8c173b8,0x0003316273cc3e83,0x00023444174474f6,0x000077989cb63c40}}, {{0x00017f4b0166f7a3,0x00079eec74e6ae83,0x000874bfdfbd3e3f,0x0003a3cdb516ace0,0x0000d846019f681f}, {0x000ee5c7c1620b02,0x000d0b63c5010b12,0x00068c51eba68b4d,0x000b5b8c03cd3266,0x0000a6279f76e0bc}}, {{0x000b8b0b796d2197,0x000ec4741dd9b32c,0x000edf6f5c3e95f4,0x000b8e1721212568,0x0000a03aee512b9c}, {0x000c376f53a89aa8,0x0001148a28dc0cd3,0x0002ab04f0d8af9b,0x00002d4f86a3f490,0x0000aacb62aff420}}, {{0x000139f8f5fcda83,0x00048dee5bfdfd8e,0x0003f9f77f3e558c,0x000969a76cbaf4e3,0x0000a4c97a4a1771}, {0x000e84bf6dce6a73,0x0005e3e6c2d1da27,0x00059a6e9ff373d9,0x00062cc115193cd7,0x0000f9b702593d22}}, {{0x000ae6c252bd4796,0x0009b2b5848f9cb0,0x000c9766305e0f88,0x00025c18f6d2b2a5,0x0000f6e149c21622}, {0x000235cde601a897,0x00088373be1fe602,0x000471827d17bbe9,0x0001165af49a5ba8,0x0000e1a0a8588aaa}}, {{0x0006fea87baa6279,0x0001672aa6801253,0x0001e5dc958c1fec,0x0001b8dc29b63760,0x0000e3c3c1d6e9e0}, {0x000127b2bcfe0b0f,0x00013a12f50defc8,0x00079b3973510710,0x000f207ccd6cb148,0x0000792f805e8a82}}, {{0x000572235e6fc06c,0x000e4b3e13d58b1e,0x0008a73723477728,0x000289550c294daa,0x00000291d43fbfa5}, {0x000bc67cec5a196b,0x0003ac2e8a7cc6c8,0x0006e1c51deeb31e,0x0001560a93e244fb,0x00009f8b71bde28e}}, {{0x00084911a335cc88,0x0009ea5913e48c31,0x000b32919563459b,0x0005ac9b920d61c7,0x000005ab8b720242}, {0x00012da8d006086c,0x0009fcf5c0fd2ac5,0x0002138d76ca4846,0x000442efea51d8ac,0x0000b647545f44cd}}, }, {/* digit=47 [{1,2,3,..,}]*([2^188]*G) */ {{0x00053e453544774f,0x000b4adba2bc5110,0x000e371f5834d0ec,0x0003bb5215d7f7ba,0x0000cfd57c05c866}, {0x000383dd6901b1d3,0x000485587dc3ded2,0x000625f623b49fbb,0x000762cd44a08d07,0x0000ee4d65bcde9b}}, {{0x000137d0d63d1fae,0x000122a9d89f64e5,0x000436309658fc05,0x000a606889487450,0x00009ae30f9b598d}, {0x00010d1818baf918,0x00060b6a0c202ed7,0x0001a6b44e27e9e0,0x0007db9e28dcfb1c,0x000083acb6556ac5}}, {{0x0002e774e6daae2d,0x0002ce0a19bced7f,0x000ae677e7b3ae0e,0x00011f03293f8a91,0x0000363b0cc15c86}, {0x0001ccf309ae93b1,0x00072920cae1be1d,0x0008edf01a3f80be,0x000c909aacba7449,0x0000e6d2a4ac2f5a}}, {{0x000728dc2c6ff707,0x000f55dc22358735,0x000e277f979d6122,0x000cc6b3f5d00319,0x0000ee84e264ded8}, {0x000afb063cd880a6,0x0005d574af6091a8,0x000de7f423f3ea7c,0x000151acfcdc8402,0x00002d07930131aa}}, {{0x000f5aabeccefb5d,0x00086621d7c740fd,0x000b576c1cf56ede,0x000026e632a9ce52,0x00003403ae96a6f6}, {0x000050de8785a64c,0x0006d682652e660a,0x000bcbe0210f3d64,0x00015cb8b25edf4f,0x00009710fdf74f93}}, {{0x0004e438a5807cef,0x0002f4109a7e8e1b,0x000d59ddaad28389,0x000092d30cc9cbaf,0x000065f36c72d8d8}, {0x000469ea60d32b2d,0x000a6e8191c8df31,0x0005bdeb5ee93df4,0x000a27cc1017c535,0x000026231865616a}}, {{0x000ade73245980e9,0x0006f1067200d655,0x000136be1a6f5965,0x00087954fc23bedb,0x0000f246cdd3f13d}, {0x0003117f961ac0ef,0x0004fbdb9e1ac2b9,0x000693bd1c8a741b,0x00001d92ede2466c,0x0000cde6b502dd17}}, {{0x00083f9dec31a21e,0x00028ad9d573b02c,0x0007be365988c8b2,0x00034d73e983aea5,0x0000968734e446f8}, {0x000ea8f5da6309bd,0x0003f1f1ce169137,0x00044092110f3a62,0x0001b4a82a9ea2ca,0x0000f94739f2b46f}}, }, {/* digit=48 [{1,2,3,..,}]*([2^192]*G) */ {{0x000410ef4f8b16a8,0x000e447b266a56f8,0x0009c87c197241af,0x000b1a8a406b8e6d,0x000003f3e034d42a}, {0x00009a804dbec69c,0x00067bbad05f7f03,0x0008e197fa83b85f,0x000dc106097273ad,0x0000097440f1067a}}, {{0x0007fa0b311898c7,0x00045d0eac653f74,0x00014d0bce2a272e,0x000ee2dbba5851f9,0x0000a1a966134a43}, {0x00067cea1c8cde9a,0x0008d271abe3e5a3,0x0001615cd9d958ba,0x0000b053ff7eb63d,0x00002280dcf95ae2}}, {{0x00044a43794f8dcb,0x0009983c5c362663,0x0009d10a0dcca923,0x000df27d6b6bbf3f,0x0000320c5cb31d9b}, {0x00028ff47b50a951,0x0001bef03371620e,0x000100153933e3b0,0x0008d6e081bf8599,0x000083be9a0d3a8c}}, {{0x00085c341dca5663,0x000aa8622aa3b6c1,0x0001b6dfb7de7fed,0x00028869e84d9290,0x00000a02b0eac4ad}, {0x0001daa2fd3cf36d,0x00070f89e59fc7c8,0x000496733d131954,0x00012ae2be8184cd,0x00005f449ec63d34}}, {{0x0000fabe085116b3,0x0005572853102547,0x000bfd52f04a4337,0x000c741e39187ee2,0x00006166b44ad9eb}, {0x000433cfd4b322cf,0x0006ca79ab5192ad,0x000db15eb726aa81,0x000e63096eacd8c1,0x0000af71e91f476b}}, {{0x0009bdac97e65165,0x00007230f49ed74e,0x00074ea498877936,0x0005a256ec1de31e,0x000081dcee58fb64}, {0x00023918f483f148,0x000c5137d13bbaef,0x000743a426d2dddf,0x000e66d4cde50ed2,0x00009a34fc664d97}}, {{0x000d2e949dee1686,0x0002de2af23972cf,0x00094066a1ae0522,0x000412a09e75be1d,0x0000cca31c798abf}, {0x000d61d9bc499082,0x000cd5e2bc1eb50b,0x0006f83ac4a9b4a8,0x000b28cb6cc5f794,0x00007da93fd0bffa}}, {{0x000ec644cd8f64c3,0x000ff79d7b51c492,0x000c7525658a2d78,0x000016dced1fc51f,0x0000e658aedbf433}, {0x000942e05da59eb6,0x0002addc37220b61,0x0002e7f87ba3d60a,0x000b6e1c311cd174,0x0000473ffef56b01}}, }, {/* digit=49 [{1,2,3,..,}]*([2^196]*G) */ {{0x000604f692ac542f,0x0000327b91d38303,0x000aaf9bdf079ffe,0x0004fa29f63e6315,0x000099ee566e1f34}, {0x000661fd62191997,0x0006648ce41c8a1d,0x00074d9048c883bc,0x000b1aa065118f3c,0x000013889ee7faf8}}, {{0x0003f8f81a1b3bed,0x0004fe2764a0972b,0x000c4f5f74f3ce14,0x00085b12d0f1cc28,0x0000eee0c0e97f39}, {0x000adc0d39e25c35,0x00007467a0807df4,0x000cf5a584061982,0x0005fff40ebc9361,0x000027729a6922ad}}, {{0x0000937b1b76ba6f,0x00045d2026dcca6c,0x000d9ae0a1a2eab8,0x000025c1715e1519,0x00001ad919aaac4a}, {0x000dfb807ea7b0ef,0x000e4ed9eb8935b3,0x0006d08abedf5496,0x0007309932e5ff2d,0x0000314874f15bd2}}, {{0x0006a753f73f449b,0x0007dd44fc79efb2,0x000c0dc4d1d1c94f,0x0000cf99f0fbc53b,0x0000747ea0be698a}, {0x000c3fe228d291e6,0x0004e3c129d65218,0x000acc51635b804b,0x0006689ac859b8d1,0x0000c10697df5d6e}}, {{0x000438f0876fd4e6,0x000723d2f383c38e,0x0000934cb45f0c30,0x0006edc03cc2ecb1,0x0000a8f24398c9d4}, {0x000431b65ccde7b6,0x0007c7e76a6ff16b,0x0003484d741e2cd1,0x00044a59c8cf8f4e,0x00004426efde3152}}, {{0x0008e44fc94dea3f,0x000eead6a0b01c0a,0x000113cef34c8cdb,0x000ff9a19c384004,0x0000d32fba505490}, {0x00090f6795dcfb75,0x000333588baf58d1,0x0001fc1c0fef01b0,0x000ac94e6d1d63ca,0x00003173f9740a41}}, {{0x000402aba16f73bc,0x0003ccf9b9fc2b1d,0x0006ef7bf2fb3101,0x0007446d51e60e44,0x0000731021c791e1}, {0x00047244fee99d47,0x00068ac5c1ea9d3b,0x000ea9af74bca48b,0x00083a00f5f514bb,0x000051f55a6074c2}}, {{0x000251acb452fdbb,0x0004a0f306506e30,0x0003548d931ee696,0x000f5b00b3e50893,0x00008949a50a4b0e}, {0x00083263c88f3bd1,0x0000cb1d9989208b,0x000d4df03ab147c3,0x0000c5dd6515fd44,0x00007a12f75f72eb}}, }, {/* digit=50 [{1,2,3,..,}]*([2^200]*G) */ {{0x0004f7881fdad909,0x00057d2cf6ab2591,0x000054de5cf638f5,0x000350290bc03fcc,0x000032811a7a8b06}, {0x000b3309bbd11ff0,0x000fb40449742f00,0x00051d26676108a6,0x0000c1801bb9e0a8,0x0000dd099bebf899}}, {{0x000dd8a58d6cd461,0x00057e6634d214c6,0x0001bc3289cb633b,0x0007e5b1305047f8,0x00002ede0e236a17}, {0x000ca62065a6f4f9,0x000cd7be487b332c,0x00047ed1cc3a47ec,0x000b13e41eb1870f,0x00009e66e5977598}}, {{0x000a6777b0ac93d1,0x000d68f5e0d7ebd6,0x000f5492ba6e37b0,0x000f3a1516c09676,0x0000e4bf888aac05}, {0x0002ce04df0ba2b4,0x000d1062341bcdb4,0x000acac20935d5cf,0x00000e4a30333382,0x000029438c49198b}}, {{0x00038be67e573e06,0x0008e084c44bfb28,0x000c1c2c505891db,0x00044b3131137396,0x0000aebfa4039584}, {0x000dce9e56e55c19,0x00029caa46d0ac9c,0x0001fe8eb7148ced,0x000f4c9e10c7efb6,0x0000fd835db8f97c}}, {{0x0006f56c17706169,0x000d79da9a2d6c62,0x000730e455351909,0x000a79558e6825a3,0x0000d8c8bc093ef0}, {0x00078b6056becfd1,0x00039090b36d543f,0x0004432f933f1325,0x00050272ad499779,0x0000386493c5721f}}, {{0x000eefa5abea82a6,0x000933fe62d43794,0x0001ef6068dc611b,0x000e6909f1af3728,0x0000af546c899839}, {0x00078c7c977ec238,0x000c3d5c05766255,0x000d1a4c0a8de294,0x0004d462ddaf0f7c,0x0000243fc70cf95f}}, {{0x000f400b008733a5,0x000d012e1f57e566,0x000509cd0cba0697,0x000d8c4537c2b240,0x0000f989c69a7353}, {0x000c9724c3c2b2fb,0x00084f031fa87dbe,0x000d5d11f90e02fa,0x000dfc44d15c53cf,0x00003404faef8314}}, {{0x000a109081e9387c,0x0006cc935828a36d,0x00040b015fb9780d,0x0006fa15940332e5,0x00009d7b51ca0f46}, {0x000cd41d6d9f6711,0x0008a1a2ac17faad,0x000201e5fba6c1e2,0x00062af66a7833ed,0x00009d9971a090f4}}, }, {/* digit=51 [{1,2,3,..,}]*([2^204]*G) */ {{0x000f462060b5f619,0x0003ebd057c2f431,0x000e1bf65a56f46b,0x0001fea48dca6c47,0x0000a38783ed1bcf}, {0x00033a9da710718f,0x00063e0aeaf67a5d,0x00029d1875a77998,0x000732da87314d2d,0x0000a0edc3fb687d}}, {{0x0004849cb198ac73,0x000cdf2646651c89,0x000200678a884a93,0x0004e5fda964ef9b,0x0000c351b8730983}, {0x000ef9fe2c4b44b8,0x0006b326790cafb2,0x00002264a580f6c4,0x0004e2384805210b,0x0000ba6f9e2c2a19}}, {{0x0006ab65eb03c0ee,0x000392bc3fde499b,0x0003a80d2f19b795,0x00019ec86b5b9c6e,0x000043775094d428}, {0x0003650bb3ee8a3e,0x000bd132075fc166,0x000d834f675eb14f,0x000ffcc8ccc9067a,0x0000a6a2475c6e92}}, {{0x00034abd3c095f18,0x000e64b76d7139d9,0x0003e698404b261b,0x000b109d2e6970e7,0x000079fb23bde5fc}, {0x0006c72dfd754907,0x0004f1bcf1c11150,0x0005e70073a97d08,0x0002a6d3201d82bf,0x0000f0ac52fe9823}}, {{0x00020ee4b049136e,0x0001556a4613cb4d,0x000e081288b63bf1,0x000b153221aef670,0x000062d8c522acb6}, {0x0004a67379e7896c,0x00020afd7fa571f6,0x00041ba6ab25237a,0x000e7e3077bd9838,0x00004ac0244fcd16}}, {{0x00001fb319d76820,0x00090a982feeb251,0x00061b344b029312,0x0001fa51c1c9b902,0x0000e008c5bbfd37}, {0x000dd1c0278ca331,0x0006d5aa53b1d866,0x00013a2cf666f76a,0x000836d5cfb77960,0x0000d3a1aadb3521}}, {{0x00004ff50f75f9cd,0x0002ae752b223c56,0x0009a11181d8eddf,0x000d7a3ef074dd3c,0x00000ffc1739cb86}, {0x000ece3037d90f29,0x0005d055856cabd1,0x0004c6dafe3f307d,0x00099fb22f93287e,0x000002aac66c3487}}, {{0x000131a567193ec5,0x000a95f6e70b76b4,0x0001eebddaf3c305,0x0008314587bd3903,0x0000709def8c1bbe}, {0x00099830eb2b6692,0x000b675b70295705,0x00064ac164d80ce1,0x0003ab638a7da803,0x0000f431d23de1c8}}, }, {/* digit=52 [{1,2,3,..,}]*([2^208]*G) */ {{0x000bc15adf7cccff,0x0005efa1e1b075d9,0x0009bc17e81a3e5d,0x000d429c39e44424,0x000037dccb37ea7f}, {0x0004873907fba12d,0x00097a372904da65,0x00083a6c535daa6d,0x0005be3564cfc662,0x000009fa4f71a939}}, {{0x0007080eb6b242d6,0x0002db71e246832d,0x00031139dd30bd02,0x000e531027991bbe,0x00008797e91a62e4}, {0x000e20a6b4e185ab,0x000d92d9b707423f,0x000f7811b82f2c67,0x00095c75c817684c,0x0000d53005eb45bb}}, {{0x000a29e5cfe5c487,0x000e115ee096c51a,0x00049a68a82c020a,0x0003550848ad8275,0x0000933d489d0471}, {0x0008d2e67c51e574,0x000a99944afc0499,0x000fadac60f64020,0x00092c3a299fe1a7,0x00000c73ff49aefe}}, {{0x00049be9d8e68fd9,0x00028b044320e5f6,0x000c33398db0f053,0x000fae66fde9b3e0,0x00002f4209bf6c8c}, {0x000afcc1a739d4b6,0x000f428ab8dee9d1,0x000c6f1d009aea75,0x000aa4b4375fb5ea,0x0000420b560d08f7}}, {{0x000ffc75488771a4,0x00013f2f2191bf44,0x000f86a42cb76e3f,0x000d9a0197bde394,0x00005c25bb9b0641}, {0x0009e31f88ce6dce,0x000c6bb7ac7dd8a2,0x000670cc7be2becf,0x00043233094214b5,0x000090a8fd640af8}}, {{0x000fd5696f37750f,0x0006a1507ff22d1a,0x0006543ed25dda55,0x0009103b95fd4c00,0x00003c778da923c3}, {0x000f4463b04938d5,0x00062eef947b84cc,0x000e325b53d9dded,0x00055d6ed83735da,0x0000ba0f75d49214}}, {{0x0009b8b4ebd3f02d,0x000cb6b770ea0ecf,0x000a213cea47acd9,0x0008cec3b84a6a2d,0x0000760871c23e7c}, {0x00058e536e530d74,0x0004d912ad517a5f,0x000a0252a7abc52a,0x0007423ad43db02e,0x000098b00ed0176b}}, {{0x000499c6254dc41f,0x00038a837e7e9eae,0x0000524a77e29392,0x0005f184aec08c09,0x000082b921a7d6f5}, {0x000962e1402cec5e,0x00071a2f30e7493c,0x000b879cb9f17ca1,0x00045edcd783e8e9,0x0000a3d8c153a6f1}}, }, {/* digit=53 [{1,2,3,..,}]*([2^212]*G) */ {{0x00046e60ebcf7262,0x00014231470e103c,0x0007c21094482b83,0x0006ef4f6dfaca48,0x0000e0ace9782e66}, {0x000a9d31f8d1f420,0x0001574944d23246,0x0007f334b1b1e83f,0x000d8113dfa63aa5,0x0000cf8daed9f025}}, {{0x0001f0d1e935abb5,0x0003c54de37a85de,0x0009cebb5defd10b,0x0004be68d9e39236,0x00004d5ef9bc6132}, {0x00041ba74f17e266,0x000818c1dde44d63,0x000d918fdc0a0e3c,0x000a1346d7758187,0x0000687601562ca3}}, {{0x000180c207674f17,0x0006c3ae8fdbbc19,0x000aeb71e112e09a,0x0001c7296675546a,0x00009432af25101b}, {0x000558fde2ddec64,0x000f1357753fd5eb,0x000e1158a81392d1,0x00099167a76b973a,0x000016fbbff8a899}}, {{0x00032c7904fc3fa4,0x000587e3636aee73,0x00091d9aa14a23f4,0x000540838659c3f0,0x0000a995e5df12d8}, {0x0003becf3a5598a7,0x000741eaa99520a5,0x00004e03c56534b1,0x0002682ed3dca4bf,0x000016c563b48d56}}, {{0x0006e892f3b26e7d,0x00000a8752476d95,0x00082dda3f470986,0x0002ef6ad1517924,0x000064110e3d17d8}, {0x0008d2cfad414e41,0x00081ed02b241492,0x000821bf12b155f5,0x0005da381a141bcb,0x00002e3c7705f81f}}, {{0x00044ea308780f21,0x00012845f5e4dd59,0x00024d7a3dc8de76,0x00011e5beaba7d76,0x0000e709afd404df}, {0x0004376021704560,0x000ac8f94b649536,0x00080ca68bf204b3,0x0005744e53af7c56,0x0000526074ae0c67}}, {{0x000a63e7882f14f1,0x0004f7c6cadce29f,0x00082bed0c9f6dc3,0x00052c36f22d6fb8,0x0000a45755be118e}, {0x0007c277c4608cf7,0x0001e68012c29f2c,0x000729b0e7ccbdf3,0x000dbf8cb0aedd61,0x0000ca2ca9f67d75}}, {{0x000dea7e0f222c2d,0x000ba2e651425043,0x00016cd30309d42a,0x000eebc4fe9ddd92,0x00006539c7ddf87f}, {0x000a57c432ac7d72,0x0000127fda1003c5,0x0000698de72692cf,0x0003b1cc28c85f28,0x0000331fb469ec28}}, }, {/* digit=54 [{1,2,3,..,}]*([2^216]*G) */ {{0x0008eeae457a4773,0x000bbe6ddc05a015,0x000c41671d19857d,0x000d588326522418,0x0000ffdfc7e6c2c0}, {0x000525426ee7cda3,0x0009af02c3a83a3a,0x0003bbfc8341b086,0x0006917023bf4272,0x0000d15002a44452}}, {{0x000324c85edfa308,0x000407d4f3da5ef7,0x000b50c862597655,0x00096bb52f5bc0dc,0x0000f6927b0c832a}, {0x000e1ba55f2f94c5,0x0008e44b45fad08e,0x000aa455d6a996f9,0x0001f79133cb8da8,0x0000d0721ecc58dc}}, {{0x000e7e9262a35393,0x000d3670d59ef3ca,0x000c5e1b978a49d1,0x000c1c07de0f63c1,0x0000072c30c99cb7}, {0x0008a5277c850e61,0x000f0f6a3de61d27,0x0002ca7ad84f15f8,0x0004b836a8bb4559,0x0000912e3eef4d42}}, {{0x000a92079e5fb67e,0x000a90aa725e6ba7,0x000f5d837e1331fe,0x000e207080ccf57d,0x00004cae01e5ff72}, {0x0003ee60412a77db,0x000c2f449025d924,0x000ef5a3106ff7ca,0x0007a80e75f7cd23,0x0000c957822bddef}}, {{0x0008086365e668b9,0x000a1abda5fbdc98,0x0005f1fbeada8dcd,0x000fc32c146b4c25,0x0000cfcde2a5f34c}, {0x000453e7e85d1e48,0x0009792358b5acbb,0x0000823ff9ca0967,0x00011d95fc2d9624,0x0000d65adf78c11d}}, {{0x000230cb0ce1c552,0x0004ebbfb6078cf7,0x00016363b5b534d0,0x000e82ce1ef1130e,0x00007e0aa7ad4999}, {0x000ac2d79362c410,0x000091bb6cb0ce1d,0x00023df2467920c9,0x000f281e648d6322,0x0000f7d9eefe32e8}}, {{0x00057f10296f4fd3,0x0003ba51b4367755,0x0009508051dca76a,0x0007f1c3e98f60fb,0x00001ff32eab31cf}, {0x0007bf18d2c714bf,0x00083e9d2aca643e,0x000dc2d2364b5c33,0x000b9ab9fd9ccc6a,0x0000c2397edbc721}}, {{0x000f39afa8338349,0x0002163285626943,0x00070fc102295172,0x000e6cf1d63dd541,0x0000f5fa5903ecc2}, {0x0008725e77d9a3b0,0x000a6384ebe0b66c,0x00045e24a11235ce,0x0003b106a8c11858,0x0000137b286ebd09}}, }, {/* digit=55 [{1,2,3,..,}]*([2^220]*G) */ {{0x0007d6ac42bd6d29,0x00082b1f96aedb56,0x00043b28e6df8646,0x00023f7efe5b1a48,0x000061bbb05f379b}, {0x000f5f070a6a26b8,0x000cb28e6e39b6ca,0x0005fc8d370686c0,0x000dc900da06cf89,0x000004d88113363f}}, {{0x0009ce74462007dd,0x00047cb5f5b763b9,0x0005edde7b8ab48a,0x000fd9cec673d2f5,0x00001567f755cfae}, {0x0001b6b0887bcec5,0x000e9178f3c24638,0x0006266cb694497c,0x0004130e6525e31e,0x0000931de26b97d6}}, {{0x0009da11f17a34c7,0x0008b35a145614e4,0x00050363b5420ab3,0x000b6e476372412f,0x0000b15d62433fab}, {0x00040b1e274e49c4,0x000456b1860aa0ef,0x000afe5a45cf5074,0x000e9a96583fbf66,0x00004240511347e3}}, {{0x00055021a93507a4,0x00074d3c06cf142b,0x000ec3f40b4cd118,0x0003c29f70e76a91,0x000084e81ad8e755}, {0x00087b5272e9d6ec,0x000506ff514a830f,0x000192a8eea1c93e,0x000359a7cc2adcc4,0x000077e27e302f45}}, {{0x0008b1e48ac28403,0x0004bcba9477b535,0x000946b431831129,0x000819aa58f990a6,0x0000098baf9cab41}, {0x000c1584198da522,0x000bf46bfd1b66c4,0x00036a908ab4fc17,0x0008380f0a4c3cbf,0x0000ae9e34b78cf7}}, {{0x00040ec0ccced589,0x000b7da44f9845eb,0x0001812c625cd4b9,0x000650b3e0645887,0x00009f80d55a6cef}, {0x00040c9ce6dc1532,0x0007b86655215713,0x00007014d138d511,0x000b918cdb45bc4e,0x0000f34bb38a4b60}}, {{0x00099e84a34f239b,0x000c090402d54174,0x0003aa83215fdb83,0x000db1075f46bf43,0x000061e15b013215}, {0x00059d4a127f89a5,0x000bb7e816daaabe,0x00018b6925d541e0,0x0000265aba0659a6,0x0000532773367266}}, {{0x0009cf2d0c051995,0x0002aae784548cda,0x00072a182502fbc2,0x00037270bda9dff5,0x0000f9b71b8b158b}, {0x0003a592b82dd077,0x00052523032ee0f3,0x000505a327630273,0x00009f0fe1a721c4,0x0000b6e3e8367964}}, }, {/* digit=56 [{1,2,3,..,}]*([2^224]*G) */ {{0x0007bc035d0b34a2,0x000b6327c0a7e341,0x0000362d1440b386,0x0009436fb7262dac,0x0000c41114d00cdf}, {0x000cef1ad95a0b12,0x000847d543622ba5,0x000e486c9c09b37a,0x00029706d6cdd201,0x00000477abf62ff9}}, {{0x000dcb3292a92874,0x000637b092c7a004,0x0006c0605ddc15cf,0x0007afc83a846480,0x0000a68df707db99}, {0x0004e4505bf7dd0a,0x0008eccf7f8c9c13,0x000b5f8afa4e63d3,0x0001cc06e6517f41,0x0000a8b93434d7bc}}, {{0x00035b51e706ad97,0x000453a9ebdf126f,0x000608d90b99cebb,0x000858375389afbf,0x00006113c5036c89}, {0x0008eb097e2b5aa3,0x000c33b9130480de,0x000cc066c7e1022c,0x0009000bdab6056c,0x00003cbb144e2edf}}, {{0x00064717af715d2e,0x0003f0134a96c417,0x0001ec956e2f7f59,0x0003034c1873efa4,0x00004e7b4f757821}, {0x000ff9788d5374a6,0x000320823d5be5c8,0x000ee8fe22b915e6,0x0006518a6bc755b2,0x0000657624d47112}}, {{0x000f101dace5aca9,0x000181a6a267157a,0x0009c8609c4fdbcf,0x000a654addf340c4,0x00007e49f5379604}, {0x000e790937e2ad5c,0x0007726e17f19be8,0x000bbc0dc846e250,0x0006d57f38007a0b,0x0000f036040711e1}}, {{0x00000e07442f1d58,0x0000e6e0e3abd6f8,0x000c64047475607d,0x00083d02807f16b7,0x0000858e1e427498}, {0x000120b8231ee10a,0x000ac38a1ece5859,0x000aa73a41b80e7e,0x0003ac2b72525ac6,0x00007cdea3e24442}}, {{0x000c007f8ae7c38d,0x000b6d7401925ed0,0x000e36db36db07a5,0x000045ee5e9c2a5f,0x00005b9d57b46e95}, {0x00032e78eba20f2f,0x000e81b9a35254ac,0x00098a658ef11ca8,0x000666405e373eff,0x0000fe5a101723eb}}, {{0x0007b11e51732d26,0x0007c538fc0e5747,0x00039eec5dfd6eb2,0x000c56fc43b0cc3b,0x0000af127792b36c}, {0x000852d06c425aef,0x000b6c221b9b70b0,0x000826d9c6df92f8,0x0009c27c8d4f9ece,0x000059aba7ca4935}}, }, {/* digit=57 [{1,2,3,..,}]*([2^228]*G) */ {{0x0002c2e421d3aa42,0x000cc84fa840c37e,0x00054e41cf926407,0x000643f8abc03d14,0x00006605ecd5f7af}, {0x00041a6d6a5eabf5,0x0003d16b668e2423,0x0000101021edb84f,0x000d8c8836edb804,0x0000b337ce7e45e1}}, {{0x0006b86d23ddc820,0x000c7e0143f04c07,0x0007af2c503fd344,0x000a4fa95362ff31,0x0000add3db7e18b7}, {0x0003e3f8260e01bc,0x000494a1cc919c67,0x000f2e433fbeb49e,0x0001ead1351bf292,0x0000755e7ed45114}}, {{0x000e368da9f3804c,0x000de164349c349a,0x00062baa5470f07f,0x000df3152f4cc985,0x000074a9e86eb290}, {0x000aa3543471a24c,0x000df8194511d3a1,0x000dcd44d239446b,0x00082cfec2dd0081,0x0000a3d7f10842ac}}, {{0x000db47f23206d55,0x000fcd2601522bf5,0x0008ff89a2f6d341,0x000457c7b876533f,0x0000157c30c878fa}, {0x000c5c52d4fb936f,0x000bf6518cdc7517,0x000847a64ef22f7a,0x000a88eeb483e6bf,0x0000508455982e0f}}, {{0x000c2a69b583160e,0x0003d4e59194b418,0x00083e3ffbe74fcd,0x00029b1178eeaa3c,0x0000051f896c296f}, {0x000523806ceb84af,0x000df111fe6bd023,0x0000455455ace48c,0x00014550e43a491c,0x00003fa86decd522}}, {{0x00016fa908ec5b55,0x000d501ab12d9596,0x00082ae8a882d661,0x000f5e749f608243,0x0000cdf92ebad133}, {0x000cc425ef6c9c1e,0x0001864d84ee98ce,0x00025b8c4b52d668,0x000e87be285ed86f,0x0000b80cdc828deb}}, {{0x00094c1ec222ba0e,0x000e723e5d482d97,0x000e4846bc3dff42,0x0001736a7cd5700f,0x0000fc5b114df135}, {0x000b25bc6b05e85d,0x0008954cd0772630,0x000d8b89d0a6d302,0x000c26e4f1f54f32,0x0000e3baff2e627f}}, {{0x00059d8df7304d44,0x000bbf210e8eab96,0x0003fbd60b71bcf1,0x0004de69a2438bd7,0x0000595cd1f9d11b}, {0x000329a4835859dc,0x000cbdbb6e569c0d,0x000928a4e4a0f0d2,0x00015406038e5edf,0x000094296224f5ad}}, }, {/* digit=58 [{1,2,3,..,}]*([2^232]*G) */ {{0x0003462f23f2d925,0x000d10b940789121,0x0006cde206cab71b,0x0004bc1bdd0a6317,0x00004c9b20d3e4d5}, {0x000d8aa9f2ac02f8,0x0006a06eedb03cd2,0x00008643403f8e61,0x000db947f68e1693,0x000031469c612dd3}}, {{0x000a1583ae9c1bde,0x0008037ce2407aa7,0x000ab38b4e0af6d9,0x0008ca054342d928,0x00008b75007ea1c9}, {0x00086afe02358f2b,0x00063a921228efce,0x0001c67fc31b8b85,0x000d58552a19120a,0x00004069ea593aea}}, {{0x00090cde36d07576,0x000179a293824a90,0x000b48ddff722d7b,0x000f439b7fb04c04,0x000028ad2a84be16}, {0x000bfb520226040e,0x00007104b6c4cd3f,0x00003c1886c34ecb,0x000aaf50c0754ec9,0x0000c336b090d23c}}, {{0x000439e558df0194,0x000a6c712b279f51,0x000185a24230da4b,0x000f50118919e355,0x0000dcefcddc4b78}, {0x0000fb2a47d4c5ab,0x000f030e009ea7d9,0x000eed27355ac9ab,0x000faf4d2fc35974,0x000072d824d8bea8}}, {{0x000f923cbb13d1b0,0x00025bfb9bfed213,0x0001144a998799f4,0x0005ee1ae8ddc970,0x0000b8b3bb64c559}, {0x000ef2e3ecebb211,0x000b2671f9a70ea9,0x0006f1d1f17cb6c4,0x00027637ef464f72,0x000071b94847943a}}, {{0x0008552de7e5c194,0x000981c0256c779b,0x000d4743dfab2860,0x00093b24f58eeeab,0x0000e8ef838bb6cc}, {0x0000d264cb1bf3d1,0x000963dedf61ee65,0x000b70ced4c1f9d0,0x000e1e9ef7c9d7bf,0x0000ec0507e2641d}}, {{0x0001109a607419d5,0x00026b6bca80c994,0x000c431f3faa71e6,0x000479e4158c1307,0x000094abebce92bc}, {0x000a691eb78399f1,0x00052f42cba46dfe,0x0007c04f048aafb3,0x00091addcd65af07,0x0000a29a366f8844}}, {{0x000b2b5ef7d92893,0x0007e97f015a549d,0x0000493b62480d4a,0x00033131d5590bc4,0x0000a55b52e9f780}, {0x0008115309eadb09,0x000a02e5c62540eb,0x0006a3d5adea7de5,0x000d60d4d631f0cc,0x0000d5e9d7d23e8d}}, }, {/* digit=59 [{1,2,3,..,}]*([2^236]*G) */ {{0x00060411e84e0e5b,0x0002fea34c931968,0x00073a732a5db84d,0x0007c049d5bb1970,0x00008d2fe571bcfd}, {0x0005f36f3eb82fab,0x000c4dff8b584577,0x00074c1108cb20cc,0x0008996659b65f83,0x00008b4a422e30c7}}, {{0x000cda3af2ebc2fd,0x000cfb4efe24c4f4,0x000cd10b1a0af843,0x000e0383b857c19c,0x0000dc9d1ec614d3}, {0x000c8bb62771deb1,0x000a81c5aa817bde,0x0002391ae829277a,0x0004ca6af18dd683,0x0000740f316d71a8}}, {{0x0000910cab91f1eb,0x00039d1cd2162d50,0x000d02252bedd9e4,0x00017a2634b74fed,0x0000d60f8e1c2586}, {0x000537b9e05614a8,0x000667af5fc5d8c7,0x0002bd926fd26c76,0x000fc78660b58158,0x000070192452cf07}}, {{0x000e99aeeaf8c495,0x000d1e24d7288928,0x0002b156cee7aa73,0x000a1cfc5007c2e7,0x0000fcf57c63d408}, {0x0009e39b6057604e,0x0000e2868bbf9f71,0x000103e2d7d343c0,0x000ea14cca254b7e,0x00006eb38aad131b}}, {{0x000e3520a981b0d0,0x0003bd1a41a40ba4,0x0009fab9c1c354cb,0x0008d51aabaa3adf,0x0000701a7d153c41}, {0x0007cefdcf2b9218,0x00033cf48061dd1a,0x00025cce66ceef0b,0x000e339083b598de,0x000090a54c8690a5}}, {{0x00018db4f6d01b11,0x00027f11e8a04057,0x000591a3be73c6bc,0x0005319c11bb8ca0,0x00002d09a5a1acc4}, {0x00074eee7de13f4c,0x0005444fd682cbf1,0x00048af70177e2be,0x000b7ba5f574cb1c,0x0000e5966935961c}}, {{0x000ed6c048752a14,0x000e601341b4c59e,0x000c6b09241f2702,0x000b232e35903b9d,0x0000291aba85f5b5}, {0x000aa70a653d61da,0x0003af2eb51e8173,0x000b93f8fd1b648d,0x0004fd91b7ce065a,0x000055408ef39e2f}}, {{0x000624f8be762b49,0x0000758e3413b33e,0x000d805fa2a9ee4d,0x000fd7068e636967,0x0000848949c0db8b}, {0x000d7e5d23a84178,0x000d73e29da55308,0x000ee471f892f3b1,0x000089495c139e3d,0x0000631594e5757e}}, }, {/* digit=60 [{1,2,3,..,}]*([2^240]*G) */ {{0x000e2ea1f095615b,0x000664e68c331083,0x0008818be0a28ad7,0x0000ccbbfc02523d,0x0000585113ba3585}, {0x0005f0b30df8aa1c,0x000b8ab7e3ac7d93,0x0002f00cbaddda07,0x000f6bd2c3429955,0x000033ed1dee909d}}, {{0x0000d483e07113c9,0x0008ed8b63ae2dc4,0x000684c2b6e4a5d3,0x00026bc582a94b79,0x000032b33d4f22da}, {0x000f6510dbbf08dd,0x000894c23a52f534,0x0005bdc9b211d07c,0x0005573eeece0fee,0x0000f178169c7015}}, {{0x000905a83cdd60ed,0x0004d1170184abe7,0x00023642a50602fb,0x000aff989886cdb0,0x0000568d09176e1f}, {0x00022c70259217fd,0x0008f43141e45b19,0x00095f86e93831cd,0x0008280fca35870c,0x0000ec2057b268ae}}, {{0x0008925913cc16df,0x000cf1a26f5a568f,0x000f499ae18bc5b6,0x000e83efa413bef5,0x00008835dedb3f0a}, {0x0000bd865a40ab05,0x0008c94b377eb6e6,0x000084a696559643,0x000de06cd8562592,0x0000ce433b99f23e}}, {{0x000523d42e06189e,0x00006e3aff13860d,0x000b20650bf07794,0x00000c2b616dcac1,0x000066dd6d201313}, {0x000fd67ff99abde3,0x000097aac50dd4a0,0x00046b2d7c990355,0x0002aed22ecf8b7c,0x0000333b1e86abf9}}, {{0x00065e784d6365d8,0x000f0f759fb8c0da,0x000e81930bcb7443,0x0008aab5c712b17a,0x00000428dffcc6e0}, {0x000afefa4faf8433,0x000dcfa9855ff19d,0x0003ac7ceced8538,0x00071df0ac409cbe,0x000058c1fb6b82da}}, {{0x000def7be42a5821,0x000055046be6efec,0x000e8dba9d3fc608,0x0001ffb9af13c809,0x0000e6c984774149}, {0x0004925d30c31f70,0x000aac2a21223b57,0x0000859e7b7eb72b,0x000942776a0dacef,0x00006fec31421900}}, {{0x00094b07e50122b3,0x000b1af07ca53247,0x0003fc97bdd744f8,0x000d9d00a12f08d6,0x00009650f1aa6626}, {0x00047f71fa38477c,0x000914dc124f101b,0x0006eb58a3d815f1,0x0008865569ae95b2,0x00003cde18955fb1}}, }, {/* digit=61 [{1,2,3,..,}]*([2^244]*G) */ {{0x0007a952f41deff1,0x000ad63b89b702b3,0x0003ff9510e44a59,0x000af4573257dc14,0x00009c02205e752b}, {0x0003069c4b7d692e,0x00031d1502ac46c2,0x0002208462e6392c,0x000b628057b1a21b,0x000051ff946ec1b5}}, {{0x000cb51566c5c43e,0x00085597f0466e85,0x00094d94acff9c91,0x00027cb354e90c49,0x00000a3933301479}, {0x000fac10dc1eb2bf,0x00013ff319fa8427,0x00096527488cfd8c,0x000745f2d4e68401,0x0000a2e067e57aaa}}, {{0x000857c5b0f7bd45,0x0008c08ea1cdb9dc,0x00084c7a96990c2c,0x000a7834730b83b9,0x000052723d33ab18}, {0x000c2e2919ba0f93,0x00091bf408909752,0x000d98212075a3bd,0x0004c841e52a04a6,0x0000fb6607acf18a}}, {{0x0002a7f3e5f9f11f,0x0009e6cb3b8eb6d9,0x000f800bd9afe153,0x000e185d1a6dd7dd,0x00006c13cc1baf17}, {0x000c58e325fc3ee3,0x0000731dc3b215f6,0x000a3d3e77109540,0x000e2ce68e7c07af,0x0000f8417a1c4c7a}}, {{0x00075216ce400bb1,0x0007baf07d99f47b,0x000ce62e0f72919f,0x00000e85b86e0600,0x00001872baf9fcfd}, {0x00021eb211f7dc69,0x0005c4ebd6f6049b,0x0002d78dab8900e5,0x000d9fec38cea416,0x0000a586c9e9bfa3}}, {{0x0004772813b230d7,0x000ea7344427ec23,0x0007fc56a634d0f5,0x000f76a1548ab1d7,0x0000fab17513e06a}, {0x00010a74f7c4f830,0x0004220a67d9b62c,0x0001209a0a7d2edc,0x0009f01c40417092,0x0000b9815a0face5}}, {{0x00083e151c3ebe53,0x0007a25d7be8ad38,0x0008ea8c9db14d5c,0x0006aaf3e4491155,0x0000a68529f6f45c}, {0x000a1dc149f75b88,0x0000879c7cb2eb18,0x00057a94e9b8946a,0x000859a7ad2a1911,0x00004b14f469106f}}, {{0x000589b319540c33,0x00097283d6f82842,0x000ae9fcb18490f5,0x000ba072731f84da,0x0000db6d960f3683}, {0x00063bb146110697,0x000e9788bf05c85c,0x0007460d2b19436a,0x000db1205459df34,0x00003f6e095511a7}}, }, {/* digit=62 [{1,2,3,..,}]*([2^248]*G) */ {{0x000a3c8ee3c76cb3,0x0003a32a1f6ef306,0x00063e9563cf1162,0x000c26b6d5ab6468,0x0000b8a4cbe8c005}, {0x00029a59ce6bb278,0x000184d4b16fdcd5,0x00023798dc4afaa5,0x000fab30624a2679,0x00005e56df6eb307}}, {{0x0000fef4e4ca4631,0x00072566cc63b233,0x000780900bcef728,0x00027dc161d2cacf,0x000035dc5396b548}, {0x000052e27bf1bc68,0x000f87dfa06c638f,0x0003321da10a224e,0x000c8f6973586d6d,0x0000b0c5738a6152}}, {{0x00095959884aaf7a,0x000267b348a68968,0x000147c87b1959be,0x0001f7f6250e573c,0x0000e0efb3b7d0c6}, {0x000745eca8c325e7,0x00067cff3f70ed00,0x0009ad41d3c91169,0x0007ef03acbc6531,0x0000b01a02160b1c}}, {{0x000ba6b23a5d8961,0x00056fe4364e9910,0x00033c6771fe19e3,0x000fd05e1da8c39a,0x00005b4488b39fd9}, {0x00092541a1f22bff,0x000fbb8163e81f43,0x000e5658e920a8a6,0x00039a4fd1b24907,0x00002c4f79da6ec8}}, {{0x00043b5224c08dca,0x0003e1b50c912621,0x000a8c84f2bbb09b,0x000ca8216ed709ac,0x00006210d9e52850}, {0x000f67a09cb54d69,0x000fc00919a46d8d,0x00013285791eef6d,0x00028b00f613810f,0x0000acede4888d50}}, {{0x000a0691416a6a5e,0x000863ef881c84ce,0x000038a5d8f860c7,0x00006661311f8a38,0x000078c2ec1dc612}, {0x0002e815ad735813,0x000029604097494d,0x000612cbab4cc9e0,0x00039ecf558aecf3,0x00005beef7ace36c}}, {{0x0001446de6736294,0x000e303c2d2145e2,0x000c868c757f7aa1,0x00067660e99b7f98,0x0000e42f66dcb641}, {0x00084dc910778965,0x000f72c9885b6028,0x0009a5187a0d690c,0x0007eeaeb4da333b,0x0000f789598653c8}}, {{0x000619c76497ee80,0x0006c717370e8b5c,0x000cf68e15d2b0ac,0x00079298204cb64f,0x0000bdec21162bc6}, {0x000ccefa63b10110,0x0007e0de1ac56973,0x0000e0c8bf9e3fa9,0x000cb45efb693e3d,0x000037248e9d2d4f}}, }, {/* digit=63 [{1,2,3,..,}]*([2^252]*G) */ {{0x0002dc91ec34f9e7,0x0004c38106038080,0x0000cb4f3d8772d3,0x000128cf06d66c53,0x0000be5ed0e3475c}, {0x0003c1931e82b100,0x0007c9ff6b4ccb9e,0x000a1b45ec63d285,0x000bcab92118c692,0x0000aec44147285b}}, {{0x0009ae71e29a3efb,0x000f9c93302efc18,0x000aae10ecbe906e,0x0009f820107914ce,0x00007a23f35668e1}, {0x00075c2efd2119d3,0x000eccadc9c8e9d8,0x000a1711303198c6,0x00003835591bf64d,0x0000cf0bbf86d443}}, {{0x0005bb72b7247593,0x000182d4c63aae48,0x0007d6f2c945353e,0x00010952159d07de,0x000089caef37ec5b}, {0x000bb53db65ef147,0x000e6d99de434a8e,0x000f2405f2dc2cb7,0x0008a3116fa3ed83,0x00003429bba31420}}, {{0x000d590b01e6e274,0x000da180b2dcb618,0x000aea4a9047e2cc,0x0003a491b299b504,0x000012c9e1edfa40}, {0x0008a36794075521,0x0006e332b8e388d2,0x00068de1949c5013,0x000b972a1b6fcce6,0x000078851bc85122}}, {{0x0003752fb85fa4ca,0x000d983c8ce9b1e1,0x000f74daed61257c,0x000bbb343da670d2,0x000035aa2405f846}, {0x000235d4421fc835,0x00007363473b5e74,0x0004aa158f6df8ee,0x00022de4d7f52a3c,0x00000d05aabebc6d}}, {{0x000e735a64785f45,0x000b0f29cd078c56,0x000e35067bc56637,0x00027003b2bb803e,0x00000235a102c919}, {0x000b6d8f2c4aa658,0x00010396023b191a,0x000f805bac347583,0x00080f00400ba5f0,0x0000881065bdec0f}}, {{0x000e522cc1b5e838,0x0001060b8bfbc370,0x000b256dfde2d4ad,0x0009972d364df067,0x0000f12502f60138}, {0x000a0dc7783920a0,0x000dc0bc866a503f,0x000064ba6e80014a,0x000ba53f89b744d3,0x00003511dcdcba5d}}, {{0x000d46d95a7b1a29,0x0005ac6341fb197d,0x0004c2ece9c4e7ad,0x000f89b26eca2948,0x0000211e48a6e7f4}, {0x0007f6ec78ef1f42,0x000fe65745861499,0x0003eede82b2c090,0x000017f7286a6e1c,0x00005f92e472f60e}}, }, {/* digit=64 [{1,2,3,..,}]*([2^256]*G) */ {{0x00070af3aeac968f,0x0008d4b63266b4e3,0x000ac5664e4f7fee,0x000cbec4acd4c2e3,0x00008910bd3beb38}, {0x000e50cc9c0726e3,0x0009a97b40bf1c3a,0x0005a5a1b1530956,0x0004cd40884b7ffd,0x0000890896b1f831}}, {{0x0003c9f82e4c6346,0x0003da4464f85ced,0x0001dca258efb831,0x00012b8706381b7a,0x0000cd15a3cba2a4}, {0x000a8fdbfcd8fb51,0x000f5e54cd229347,0x000d8932f31db2ee,0x0001afb4aeb11ef8,0x00001e7c1ed44441}}, {{0x00084f5903fa2711,0x0002a9da921e9968,0x000b01e54e6da0fd,0x00014e96f2f2695d,0x0000ee3e9bd78762}, {0x000181ce27a94979,0x0003fe215e04a26e,0x0002cabca36d254e,0x000613b2f32a6c25,0x0000948148810b57}}, {{0x000b43a43228d831,0x00003ad63f99ab41,0x000a5122924ae1c3,0x0002b47e525f1a46,0x00004af860fdd26d}, {0x000ef613f714aa18,0x000d6b78795ed6ba,0x000a9d694f51865a,0x00052753e21fcee6,0x00002ceb1de0a37b}}, {{0x0005bfd2f9fd51a3,0x0002181b97f74a66,0x00036ce507f2f1fe,0x000ded9ad05d69ad,0x000014fc2a4b44f4}, {0x0003d8cb55fc5c6d,0x0007efb1e23dd559,0x000453ccee3510ce,0x00063129b7be6937,0x00003541b7a39fae}}, {{0x0006525eca445df4,0x0001ecdfa4c69929,0x000a6d3bcf1af24f,0x000cc7b5b4eb61eb,0x0000560910cd8972}, {0x0001c32093eaa327,0x00090d3c67bb5475,0x0008711100183134,0x000a7dcbd90ce62d,0x00005fc863ac38ba}}, {{0x0008a4176a9f05d0,0x000b9011d488711b,0x00048a65e06ca4e4,0x000894543bc62ba2,0x000017535ffc9290}, {0x00084ce406851d75,0x000f40e960b4840b,0x00028fd34afa3acd,0x00092c5c3394af71,0x00004eb4d5b7ac0f}}, {{0x000e87355dbd4b3d,0x00079639bbb1db09,0x0006519621f87992,0x000573e83e47e51c,0x00004ef0fb7943fb}, {0x000b9d8f1bfb12a4,0x00082e5e8b7227d3,0x0007b90146ab877e,0x000b644eebdc9d15,0x0000c2110057aa5c}}, } }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPRECOMP4_P256_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecprecomp4_p384.h000066400000000000000000007503561470420105600337570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPRECOMP4_P384_H #define IFMA_ECPRECOMP4_P384_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (4) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_SLOTS NUMBER_OF_DIGITS(P384_BITSIZE+1,BP_WIN_SIZE) #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static SINGLE_P384_POINT_AFFINE ifma_ec_nistp384_bp_precomp[][BP_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x000607664d3aadc2,0x000fa3dd07565fc8,0x000e1e26a4ee117b,0x0003afc541b4d6e6,0x000459a30eff879c,0x0004ede2b6454868,0x000513812ff72361,0x00000000000299e1}, {0x000af93c2b78abc2,0x0006e23043dad1f8,0x000d385481a72d55,0x000e7562e83b050c,0x000968f4ffd98bad,0x00069a840c6c3521,0x0005e9dd80022639,0x000000000005a15c}}, {{0x000a271bdb93b776,0x00066c8229e549ca,0x000a0046a4ddbf0b,0x000e6f0ff9d48a26,0x0005f0687f503504,0x000e4b506da82149,0x0000c39c90a4fd2d,0x0000000000042746}, {0x000777e3e34947f7,0x000cf42ea84624df,0x000c322ca0a5f414,0x000f18bdc588259c,0x00015172bad915e4,0x000b0e68409f1fe4,0x0000c2070d430900,0x00000000000123df}}, {{0x0008420bd283fe68,0x0000405e4dbe5ef5,0x0007d2a868c2d376,0x00034e9a170ccf19,0x0002d51c6c3e6b20,0x0003aa4703a48d73,0x0003ace36f7e2d26,0x00000000000e7c1c}, {0x000a7b5b465465fc,0x000697e28482179f,0x00092befa3c13549,0x00063c04ef67446d,0x000ad2e1d0b41326,0x00002b33968012d5,0x0002aff6db68b151,0x0000000000098329}}, {{0x0007a84fcfeee6dd,0x000c00aae84771bc,0x00004833a9bdf308,0x000153b0aecac470,0x0004736400ad2e4f,0x00085d979078358d,0x000228fb40f647d6,0x0000000000034179}, {0x00059b3d50946875,0x000f354f3e8e74aa,0x0007e02066cc9331,0x00061a34c542ad23,0x00030418c6938e3e,0x00020017d147162d,0x000319e607b9e338,0x00000000000303df}}, {{0x0006ca2ee1bb26b1,0x00017bb595eb9873,0x000340e77dae425b,0x000b1b5293c703ca,0x0005aacc05e67f1e,0x000e8e4c660db2cf,0x000ffbc676b987e2,0x000000000001d178}, {0x0002304b4db1c9d6,0x0003c2b694ba022c,0x0000733804c0a50f,0x0001b3101c35b997,0x000f982c041180b6,0x000de236d4b237fa,0x0004a3e6c5944024,0x00000000000e209e}}, {{0x0003f94fc482e189,0x000c37eb5c930b8d,0x000fa7363cfe5622,0x000930f580d57f38,0x00061bdf6015ec52,0x00002d33b2a33f66,0x000c404f0f6a962b,0x00000000000f0430}, {0x000a60b1c9962152,0x000203f62b16dde1,0x000d30e7f024d36f,0x000bffcb79e33b13,0x00061b546f058bd4,0x00021559a93c9e5f,0x000eba586d8ededf,0x00000000000af2a9}}, {{0x000c82aa932c9f81,0x00032df13b9d0ea3,0x000012e0e11a7414,0x000dcf8211faa95e,0x0001659753ed731e,0x000b2df555f4215d,0x00025bf893db589d,0x000000000001c890}, {0x000c8f68d90a16b6,0x0002f0996b21f9df,0x000c5d608c816e33,0x000d76f50130844e,0x000401fff78065aa,0x0003b07060ff37c0,0x000b3ef57f238e69,0x00000000000af6c9}}, {{0x0006da365db4f184,0x000fe23f60a057fe,0x000be85f6a0c5049,0x0002e7193d7e30ff,0x00064f3ddb371c5c,0x000b664231d9aebd,0x0009b11c7b5fe116,0x00000000000349cd}, {0x0008ec6d3c0c6dd7,0x0005e0d2cfe83aa5,0x000f7a290df3f1cc,0x00054bf7d8686e4b,0x0003a42dbba27017,0x0008ecf0ee992326,0x000f617008d943c4,0x000000000000d27e}}, }, {/* digit=1 [{1,2,3,..,}]*([2^4]*G) */ {{0x000b56e7a10896aa,0x00082da6e8a7edb2,0x000a339205afd669,0x00065517917652b3,0x000a2887d5ff37cf,0x000bdc3fa317b63e,0x000aa137065f5313,0x00000000000435ab}, {0x000e15a5659db481,0x0008e9b21615f8a0,0x0000a5926b88aaa4,0x00071dc154d41105,0x000bc88ee1489148,0x0002d1967b333bdf,0x00051351c305c6a7,0x0000000000081ef2}}, {{0x0007c0045dd2a4a0,0x00075ad852b872e3,0x000b4af19266ca1e,0x000b9fcc651b1dd6,0x000612e8dc871896,0x00031cfb0ba8953d,0x000d793a9865baa6,0x00000000000626b3}, {0x000b7328c510ad93,0x000901148bc71a36,0x0008838d56b7b5d9,0x0005f9e9448fd096,0x00000a2377b67731,0x0005b4ff04bcb06f,0x00099f73b42725b3,0x00000000000aabca}}, {{0x00077d8466e4794b,0x000763ccf806a4c7,0x00041b06944ed785,0x0004e06ea52bef99,0x00053a7d2f3c4f50,0x0003a1bc940d01ff,0x00040062e5c5d3e7,0x00000000000ae7d7}, {0x0000b071271e42a1,0x000923d30625e38e,0x000c9ea33ece8520,0x000a10d04bab9856,0x00009da2a2ca5c3c,0x000c9462c2605ca0,0x00058348eab00eb5,0x000000000002624a}}, {{0x000c57a24f5d5ab6,0x000eded4de4f83f2,0x0004d9f2c578d7f4,0x0003d30f8a0580de,0x000dca57b7bde04b,0x000e44d56a309199,0x000e5cfc8e87cf3b,0x00000000000d1b30}, {0x000dc1d0888b708b,0x0008cb213c69fa81,0x00085d35b9791d2c,0x000bbbf1090fede9,0x000c301fe259fe51,0x000cd3fe86d97cab,0x000a513ee127895e,0x000000000009404c}}, {{0x0004d8911e8568cc,0x000c5194924b48e8,0x00026b2f852cc83a,0x0006428b12136094,0x000351fea1dc4906,0x00015ace6dd2ec6d,0x00024620fe8c27a7,0x00000000000a4463}, {0x0003c328530abb42,0x000b900c213bba9c,0x000bf43a5f2c2e1e,0x000903c6484641de,0x000a1378e68fbc7a,0x000cd8ae42413063,0x0006f9b960b5efee,0x000000000000614a}}, {{0x0001dedb8bf3dccc,0x000a0dc529384912,0x000bc9fafda07c1d,0x000597e52ce08f71,0x000581998af2ee21,0x00041eb4226de4c6,0x000b96cb4aa43c97,0x0000000000039c18}, {0x000a9ce2b257fb6c,0x000a566e1d5da261,0x0002d61f72303077,0x000396f305ee4f10,0x0000c831254b8545,0x0005680b8f9d19ea,0x0004a4cee0842f5d,0x000000000005a443}}, {{0x00007168b4a67147,0x000a12e206547853,0x0001c6a852120cb6,0x00009d5504c8129c,0x000c9710b70b2b56,0x000296a52fb25e37,0x000dce83f2fd2cd8,0x0000000000062f45}, {0x0000b128f82bb944,0x000a8a818b9bda93,0x000ed2d611039805,0x000e43a2ec76a180,0x0007caa846883e7e,0x000182141473e687,0x00004db9a19eb57c,0x0000000000045ed2}}, {{0x0001e64ba6661cc4,0x000cee484fd9edbf,0x0005b5c2b4988114,0x000449e7c1c3984b,0x000118eb5195c0dd,0x0007a16d2f313389,0x00020a0336aab877,0x00000000000c2417}, {0x0001e21e239dcab2,0x00034678db970845,0x000627331787ffae,0x000a0e4a022c7a44,0x000434a02a6b5d85,0x000791ce3b01f1e0,0x000c5b2657eedda5,0x00000000000a277a}}, }, {/* digit=2 [{1,2,3,..,}]*([2^8]*G) */ {{0x000fa21fa335ab82,0x000a49a7a5b41c7a,0x000300862e13765b,0x000438e3d9f0e627,0x0009e328c2e27539,0x000cbf891013c671,0x000d287f4a706ccc,0x00000000000735a2}, {0x000a7119424dd00b,0x0004246694eeffb4,0x000059afb703b483,0x000ed8b423d47e45,0x000bf44c91809d54,0x000e9b3848075a8c,0x000c75d4f5b184ab,0x0000000000041abd}}, {{0x00093e732cc6e06c,0x000c65e2cb07faab,0x0006c10c7767a2e6,0x000c53fd4de1f262,0x000c838f7169a296,0x0008a6ce7d408060,0x00067168e19d7b2e,0x0000000000094b58}, {0x000136755dca2adc,0x0000293d02a07640,0x000ed9dfab92ca5c,0x00069f51aa3bc4ef,0x0000dd09b1426aa0,0x0002e59450e44fbf,0x0006ace264f34383,0x000000000001fc16}}, {{0x0001b41eba2511e6,0x0003e9ee4f521f6d,0x0005af7a840c9880,0x000396db7edb07d1,0x000c2e8290630d5f,0x0003495da09b3457,0x0009b8f1d28188f8,0x00000000000cce55}, {0x000f6b035c499b66,0x0005617cbaf577ca,0x0007eb3582ad9848,0x00008995145b8fd9,0x00081a33b1a72982,0x0005149e992cb5da,0x0004c0ca49fe334c,0x000000000001772b}}, {{0x000b80038e0f9767,0x0006756ad758212d,0x00066af19dfc2941,0x000c6ffe2c8b0369,0x0007fcd7336b85f2,0x000a46acd55c6d35,0x000ac7b1ecc56d22,0x0000000000036277}, {0x000330b02f145871,0x000c1a4ed11e8d27,0x000297add7ae640e,0x000ba45266158ab0,0x000d89e0dff05fda,0x0006b02d06f0b27f,0x0006e132ef7ae2eb,0x00000000000cc1b4}}, {{0x0008162061985fbc,0x00005c112733b3ba,0x00062ae17de90bd5,0x0008e01810097859,0x0002bfe16c4fbb7d,0x000d9f8107640a3e,0x0005d74e34813ec1,0x000000000008d260}, {0x00078cdfc58ed763,0x000f72a544cd81e6,0x000e167259300b75,0x00057bacec18a7f0,0x000511b882d69e61,0x000f86563a555fc9,0x00096e4305a4dd04,0x000000000001d0fd}}, {{0x00008da90a96090a,0x00032f04145e8229,0x000a916fb6ff9132,0x000ba4e12aa299fb,0x000991b3b5179ffc,0x00081c747cc5ec24,0x0003eb9edcd4616f,0x0000000000077a88}, {0x000a4909883002a4,0x0008b9b0bab581a7,0x000e659d0317cb87,0x000d81e438a9d43f,0x000e25ca8b3cfe8c,0x000bc720cf40e2b5,0x0006a34254030067,0x000000000006b244}}, {{0x00099b58a43c6d42,0x0005180e1cd16205,0x000e96620312fe6d,0x00019d509ddce071,0x000e70c4b03267a0,0x0003ba57e52573e3,0x0004f716d253e14d,0x0000000000016250}, {0x0003e944594baca0,0x00013a237bbf8f9b,0x000a642b05f4171f,0x000531a1f384daed,0x0003981251654b13,0x0002dccc139067f3,0x0007b5e98fb14167,0x00000000000a75e2}}, {{0x0009f542630002ea,0x00044e65245ce93e,0x00012350ea59da7e,0x000c121bad2c8070,0x0002060fcf245677,0x00078cccac52dec3,0x0006fb78d070675d,0x000000000001bc8b}, {0x000ac9684403d046,0x000b5c5cb86bea72,0x00053d522dc955a1,0x000cdf2c92a70d83,0x0001f53cd2a1fbb7,0x0004f11395a9ff1f,0x0009f1fdbe6b7a98,0x00000000000a470a}}, }, {/* digit=3 [{1,2,3,..,}]*([2^12]*G) */ {{0x0006766eb19e084c,0x00028eb06571b5db,0x000430cbda13e4c9,0x000966726eed225a,0x00046100e387a185,0x0006298d18d9e56e,0x000ad0470506b9dc,0x00000000000f3350}, {0x0009595e79f27f3a,0x0006683eb62a798b,0x000ae3d2069c14b3,0x000e880e1bd4a82e,0x000fcaf3b3fcb089,0x000ffd65cd4d1e70,0x000ebbd0b1ec6395,0x000000000009b184}}, {{0x000d72326a677bdc,0x0001bd4277730e1a,0x0004e8c2adc8ef98,0x00046b099f1867d4,0x0002602dd4cc6b07,0x0000811201ec73d7,0x000f2d27fae51538,0x000000000002f8b2}, {0x000e28e4b1971c05,0x0001bb924af64246,0x0005d0fd898e9387,0x000e9ae068565acc,0x0005a9a4f1464e88,0x00093f7348a3dbd2,0x0003bcdb4a3e483f,0x000000000008f1d3}}, {{0x000da9f02128c46a,0x00049d1de964bafd,0x0007f571d595c1ce,0x00055af0de9eb074,0x0005a60289bfbc4b,0x000392c619f11b99,0x0004fc3e59000c52,0x000000000005ccff}, {0x000c017748720be7,0x00064b28b306ba1a,0x0007e101bd3e41b0,0x000542ce3f824faa,0x00022f52b71c59b0,0x000c6d26370f097b,0x000e5b4483b72604,0x0000000000034d93}}, {{0x000b2e0b9f0415b8,0x000c7721bb8359b7,0x000a5f46c16031df,0x000a789348538714,0x0007af598c4f9cc9,0x0006f27c878b604a,0x000ba5d370375e47,0x000000000000b15c}, {0x00021b9613cec089,0x000662bcfd9a4c03,0x000e3ea0c45f94ee,0x0006464a211b19f3,0x00019990b504b05a,0x0004951d3ce059d4,0x0007b0011c5f87d9,0x0000000000000d9c}}, {{0x0002533a1c8fbed1,0x000ce64e84c28804,0x000338cbe4f167c9,0x000d9ed9fbf23cc9,0x000f5b93118bb77e,0x0006255cf155fd45,0x0008941e9f6d7d9c,0x00000000000c4f64}, {0x00008205c725e2b1,0x000154bc3a502a87,0x00030c3fbf39b6ac,0x0005548d3c862428,0x0004030f713cc7df,0x000785cbf9dbfc08,0x000637f3623326ad,0x00000000000dd3ad}}, {{0x00053a3eba12bfa4,0x000ced8b8b37a274,0x000ff25533a7ef36,0x000684bd17d58a93,0x0002032fda408ac7,0x0004b49645f9557e,0x0001097fe128e6ed,0x00000000000ed02e}, {0x000f765f56c35dab,0x0008c0052d88eb68,0x000256931b154329,0x00010798446a4f6a,0x0007c99ad35fbf46,0x0000906073bc4391,0x0008aada18234dda,0x000000000005164f}}, {{0x000f715095892612,0x0004e02c16c7865e,0x0009e82bb73222b5,0x000bbc0795486af0,0x00070427332d3abe,0x0005d3cabad858cc,0x00019c9a1d4b6aa3,0x00000000000e208c}, {0x000d5b54420318c5,0x0000afcc14276eea,0x0008e6c4a86b5358,0x0007cb4e7706b5bf,0x000e479e2c750027,0x0007ad688c01ed42,0x000626ff1759604d,0x00000000000c045f}}, {{0x000e0b227c3a04b7,0x00029f365419f1ee,0x00001db5dec2705b,0x000c165c41880aa9,0x0007f9712fbd8a91,0x000c556783eb27a9,0x0009cfa6587aec76,0x0000000000002cd7}, {0x000e78bc85d2b5fc,0x000fefc878f9c549,0x000d411713959cf3,0x00084d8caf6df5e8,0x0002aabcde7509a1,0x000de597ad32bf23,0x000858f601d0de03,0x00000000000c5da2}}, }, {/* digit=4 [{1,2,3,..,}]*([2^16]*G) */ {{0x000f068a28ea9470,0x0008bb6029961859,0x0007d86ade910602,0x000693b4df3e5b1b,0x0008a0c3e35782db,0x000b2f577b513148,0x000cc3bfb01ff3cc,0x0000000000027a72}, {0x0000fdf0e7cd346e,0x000f626170927fbd,0x000aa1bbda6cc535,0x0006a634c872d772,0x0000b14d9c9f0bec,0x0006c7778a0a7cc9,0x000a4c8a32d2c44f,0x000000000003b889}}, {{0x000f462aea173d82,0x000a4860ef793767,0x000a7a5856850902,0x00083662ee7f523d,0x000f54122af0322c,0x000bb2d8058ccd95,0x0005777454880c2b,0x0000000000086d8d}, {0x000038487c4c8fb9,0x00042d5a3057c6dd,0x000955643c37ff31,0x000c99ec3c512f97,0x0006556d891e26aa,0x0009f6112c3eac03,0x0007e9866c3aa7bf,0x00000000000c144f}}, {{0x00000b161de71555,0x000aead0d24c7983,0x0006a55d94bbb854,0x00034ff7655aa29d,0x00057a5e217ea551,0x00021b295a3d1038,0x00036dfbb9eeb53a,0x00000000000c84a1}, {0x000aac3258d9db81,0x000087579398db29,0x000fa470f6fa27aa,0x0002e1e464522581,0x0005479d8f2c99b3,0x0000b80ef99d5495,0x00050bc2a8a6a193,0x00000000000656c8}}, {{0x000f81f2532800c4,0x00045171898aa3c4,0x000ea2712f9cc33b,0x000835ffdb2c1bad,0x0001591f5aafbc0e,0x000272c6a4ee3028,0x00068afd71de3bcc,0x000000000006e93f}, {0x000145dbf5847f9b,0x000bc35ee08038de,0x0001b04c30c2d081,0x0007ff5957b2ff76,0x000e5ec029c049f3,0x000324c12315d8e7,0x00057833230602ef,0x00000000000966b2}}, {{0x0003e43e11c6c113,0x0002e86283e21e81,0x0009c3e50b313030,0x0009b1bb9784a9a5,0x000ea0c0acb57d02,0x0007c682b7c7798b,0x0002b041241c716d,0x000000000001d33c}, {0x00079a15b39e351d,0x000dc5d469ca181c,0x000ce825406e72f2,0x0004cc2a13cf4ce5,0x00069e3ce2793d05,0x0004beafc13bd216,0x00087e01bc70e68a,0x000000000008aba0}}, {{0x0009cf16a3c4418b,0x0005884aa863e012,0x00089c47322b55de,0x0003206b5c399b2c,0x00073cc109bd553f,0x000384088775b921,0x0003cf25c01263fe,0x00000000000d5f74}, {0x00057c2efedc75c2,0x000933d69705ce0b,0x000359bbe99d9a50,0x000ab1a2626cebe5,0x000285b1afe80198,0x0007e6efdaf8320f,0x000bb6b9c0968ce1,0x0000000000090215}}, {{0x00066543cf4fd691,0x0000d3ee52d8e909,0x00094816ee49cd7e,0x00095c61881a757d,0x0009c13e370735ce,0x000d2d3f60a8cf9d,0x000c0de71258d548,0x000000000000bbe7}, {0x000476d4cb00031d,0x000bfbd6496e1309,0x000c1c69b8768cb6,0x000501358cfdfb53,0x000b59275b4acbe8,0x000f722ba655c902,0x000aad7e0ff05b20,0x0000000000042b17}}, {{0x000b76411fcb09e7,0x00066da643272cd3,0x0006802b1cc8eac2,0x0005a7c35b43943a,0x00084606bbf22386,0x00059fb9a6ac0158,0x0001a59660ab7215,0x000000000003ce2f}, {0x00083d9ad8b4f172,0x0006e62af29aaa08,0x00060fa06813a370,0x00029b744c110388,0x0001d36c2571ee9f,0x000b552b7b2a19cf,0x0003d4b87d88e265,0x00000000000beb25}}, }, {/* digit=5 [{1,2,3,..,}]*([2^20]*G) */ {{0x0002b4a5d3a4b643,0x0000231bdb4829ee,0x0006d713dc69c388,0x00042469b6fc64eb,0x000a15786b8c18c0,0x00063da4a0dcc15f,0x0000fb81acdb068e,0x00000000000dada7}, {0x0008c1ca45ab6321,0x0009146361afe98f,0x0001d88fcfcf648c,0x000b61b615694e72,0x0001872951d2f389,0x0003badc77036def,0x0008d340fd3bdad9,0x00000000000380a6}}, {{0x000d66b2c4fdf4c0,0x0007ac5cf8997090,0x000a08d2a2626f49,0x000681e307b254af,0x000775cd94d78139,0x000684954cc87fb5,0x00099190e7027478,0x0000000000095ceb}, {0x0004649153ee63bb,0x0006891bbc0ab337,0x0001f845e221f84c,0x0003d704b93d45fb,0x0004f541da1f1cb8,0x0007ffd10e229902,0x000b9a3eef7ce14b,0x00000000000b3fc1}}, {{0x00067cf1182bf349,0x0007f23c1f744697,0x000288faa5d1b184,0x0002c9d5afd1bfd3,0x0004f89d76fea4f8,0x000702f80a3d1e9a,0x00089d964f705075,0x00000000000f56c0}, {0x000478c2e0092e1f,0x00012e205fa8ede0,0x0002998cd8ea4a27,0x0001004356d43961,0x0001fdbbdfde331a,0x000a00e7158b7890,0x000a30a52a15979b,0x0000000000055497}}, {{0x000d05d101bb2988,0x00097e5004e8001a,0x000e96c63ff7fdd5,0x00050d1bd869f77c,0x000de7ebea2c405f,0x0007620baecffa54,0x000ff43354dc22d8,0x00000000000b1c01}, {0x000d9286dd26e577,0x000c2d9370076043,0x00025722a20b989f,0x00076273291e5c62,0x0007f0a7ca55c0de,0x000592a305cfebd8,0x000ce4de1162809e,0x00000000000a78eb}}, {{0x000153343d6d3c05,0x000a15562a856338,0x00041dfd1ca25266,0x000317409c75b8cc,0x000124923f80c19f,0x0005b291e21c7cc3,0x000b05e63fe47f8f,0x000000000000dc08}, {0x000a81ce4831b7d3,0x0001558ae455ea5d,0x0000f05c04530b31,0x000c97f3ee3989cc,0x0005f38759ae42c7,0x000f46899c1b03af,0x000c7d1a673c75bc,0x000000000008d508}}, {{0x000fc69642676f12,0x0008d1e9b23b9bca,0x000626ac6d6d75ba,0x00000fe59b7721d0,0x000c9e2f4cebd4cc,0x0000af70ed5c36f9,0x000799deca06bac9,0x00000000000416ee}, {0x000affe525098c8a,0x000df0d7afe1b4a6,0x000083fa6f5ecd29,0x0003d6ee6eaed183,0x0002496087e011e4,0x000a3a66e5baf860,0x000677f833634fb1,0x0000000000079398}}, {{0x000c39f67e66a95e,0x0005b76512d1b46e,0x0009e5603da596ca,0x0003aa8025a5f25a,0x00095cbd2a40d1c7,0x0008d61c62aba192,0x0000f3b53cadc3c8,0x0000000000009829}, {0x000894e8b1d3bb8b,0x0003a72800ecafd7,0x0003c62dea4f99fb,0x00092a7282ba9d23,0x0002bd5f1bb214bf,0x0007c6c969062967,0x000601362f68eba9,0x000000000007ea9d}}, {{0x0004d04ff62d3721,0x00071e141e762de4,0x000fa0d592d3e0eb,0x000cde496131447a,0x0005cb6c2ef746e6,0x0002f9fd80458a5d,0x000457b774763453,0x0000000000016544}, {0x000adb5cae252cf8,0x0005abfacb4de24e,0x000e9db72a61c26c,0x0003220f22d92e51,0x0006557232589b54,0x000ddb8bcaa4590f,0x0007bdc7b6730e01,0x0000000000069e1e}}, }, {/* digit=6 [{1,2,3,..,}]*([2^24]*G) */ {{0x000e98d9a0583230,0x000f77d27d71f312,0x000823b17edc1a45,0x000afeb6075b2d00,0x0006d93a06f7418c,0x000d001b9c0d691e,0x0007b9c16a95259d,0x00000000000026f1}, {0x000b72219cfa1dea,0x000984c1041afdb4,0x00056e257be49c48,0x000efd62c1758e9c,0x0007e6c3229a8d08,0x0002d89249cc6f20,0x000fe7ec69e90208,0x00000000000f331d}}, {{0x00061c722c01a99c,0x000518ec4335f7fe,0x000df3425d366c49,0x0006de001141ab62,0x000c2eca98a13ff9,0x000fdf648b21acc2,0x000e8b6154849010,0x00000000000d1403}, {0x00097be7041b8df0,0x0008ff1a35f306b8,0x000b8cedd3e80c1c,0x0006c077fc9a752f,0x000e420d48a089c2,0x000fe2e738d2535f,0x000f3980ec5ddd52,0x0000000000071704}}, {{0x000259172095dfcf,0x000a020aa15d95a2,0x000d85bd292d185e,0x00005caef579e8f8,0x000b325981bfe2f2,0x000438be8ad27e38,0x0000d9087b8284c3,0x0000000000042236}, {0x00091bc7ac277af8,0x000bb87cdf5accaa,0x000de0f7da8c4a28,0x00040c1891046669,0x000c9c1578e8a712,0x00050ffa2eb5a175,0x000a28bd66910ad1,0x0000000000011459}}, {{0x000f920077501dce,0x00091498808ed4f0,0x000dc6c59ac5d089,0x00025f176c6b964a,0x000bac474261796e,0x000a460c11aced64,0x000e48a62470fc29,0x000000000005e751}, {0x000842d2c145f36f,0x0007acc00053aac5,0x000ca1b81e5b854d,0x000cc2e3f9ca178e,0x000a0b80d1b0ddac,0x000642225ad33f34,0x00061b6a76df9364,0x00000000000778e7}}, {{0x0009eb69fa5f1bc6,0x0008ed30302342c1,0x000e3ef7d69039f0,0x0009b575c4630f26,0x00008d098d745364,0x0007f5cbc60197fc,0x000efc9c295d5464,0x00000000000c0813}, {0x0001c5999be2ce7e,0x000e7f6e08007370,0x000b6019bc473a63,0x000e08e11d9b388e,0x000a5db61c657af3,0x000b4dc4d073ec38,0x00082a9b480cb89d,0x00000000000372fa}}, {{0x0003179049382c1e,0x00069dffb03ae77d,0x0002e9528cdd6bd1,0x0002521b19fe0db8,0x000f3d5c7fee4c26,0x000e68e1e0ec1e54,0x0008a62856510b05,0x00000000000dc80b}, {0x000ac17897e6fc5d,0x0000680a509308c8,0x0000b4dde3197e47,0x00012ee28235c538,0x0008301f9653ca61,0x0001fcdf8d28a0eb,0x0005f322b11e26e1,0x00000000000e4d73}}, {{0x0002a6a91ebadb85,0x0006346a2a08bc3b,0x00020e574ba891b2,0x00056a2b3df9fbc8,0x000eb121d51228c5,0x0003bc86c81d3161,0x0000d14e27ce0b12,0x00000000000bfb24}, {0x00072db1b86f039c,0x0005986edb71958e,0x00011b5a99c9a865,0x000c6d8067f5870b,0x00033fe8e5322f6b,0x000a7997ff558b88,0x000b9be9433e2321,0x0000000000087e53}}, {{0x00084d7bdfada95f,0x0008b9c66a32b0d1,0x0004ace9a2f6c763,0x000fab721e716f0c,0x000b96ed74e68c6c,0x000110c8332c8fcc,0x000efe475890dd0b,0x000000000005cb4e}, {0x0003947e05207b63,0x000d29d7b89a68e0,0x00001e2e33262bf2,0x000b55bca7a7d527,0x000655d04585c3f0,0x00057acc5a6e56a0,0x00039e818e221c42,0x00000000000fcb8d}}, }, {/* digit=7 [{1,2,3,..,}]*([2^28]*G) */ {{0x0007398749666d45,0x0009c0a74da828f4,0x00001ff782080bc1,0x00026bb57c2f5ad1,0x0002845d45e4896c,0x0009a7d36981e2f7,0x000e8fca152b877e,0x000000000007b582}, {0x000b1649b1810a70,0x000c3ea3b9bd9987,0x000d4cd2bb2df2fb,0x000fc5d5748a6550,0x0007622665eed346,0x000f16e277ac2f21,0x000dc8bb5efe7fb6,0x00000000000644c9}}, {{0x000db9a336c7d7d8,0x0003598d0898164f,0x00065860354f4784,0x00018287cfc13dbd,0x000c8655a658651b,0x000c91b712d606e4,0x000090ba64d3c563,0x00000000000b82a5}, {0x000726397fcaaf5f,0x0006c2d1dff024ae,0x00092238373e43a8,0x000ee6b0ea1fe022,0x000cd5c1273c1ac2,0x000e603e7c100b60,0x000dfb4496084cea,0x0000000000077c2f}}, {{0x00064d07c56a20fe,0x00000a93fec079c4,0x000155e36a436889,0x00045a5cce5662fd,0x000f83a9a4a9c00b,0x000bbeb632e8a0a7,0x00080f6e0cdebbc0,0x0000000000063ccd}, {0x0008f36be2f62c1e,0x00061fc10fa07d22,0x000b3e653f03a3be,0x0009cc66bf53af92,0x0000f10bb6c9fda6,0x0007625e1474b744,0x0003cbcda9db3b1e,0x000000000001dc7f}}, {{0x0006fec7b896d97b,0x0007de8e32259b22,0x00051ccb0af3cd54,0x000a4219f42edba4,0x000d0d411d4df147,0x000014bb46d4bc00,0x00066fa1a13a2770,0x00000000000fa101}, {0x000b6039e0c4cc34,0x000d8b2a1dfa62b6,0x000ae98992614f2f,0x000a3a2f88c7359e,0x0008347726a08409,0x000507bb9071f383,0x000167d18a551c27,0x00000000000b359b}}, {{0x000fae4c55d4b2c3,0x0000aeaaaf45fd46,0x000aa7e37459675f,0x0009b673fe123f1e,0x000dd8fd0129989b,0x0004982a4e2ca56d,0x000ec777d6d0cd62,0x0000000000071e1f}, {0x0001c6bdd9bc3a7f,0x000043e9a049f5c5,0x0006deb929a38a20,0x00008e24fed8f86f,0x000ce199e8dbac2b,0x0009cc964a1d1357,0x00063b7cf06ec8e9,0x00000000000d85ec}}, {{0x000ba68a3fc0bcb2,0x0004e7d111c66c1b,0x000d9aa66fbcd347,0x000730c6db857e9e,0x0009f4b46d124cd8,0x0008472dc3c9c03e,0x0001bbd42f0242a7,0x0000000000026084}, {0x000aac1b65a94c0d,0x000ea6332b11a21d,0x000acbe9385d6783,0x00028eee7e8944ac,0x00005ab28372402f,0x0005e1ff33d1bab5,0x0007296944e82cad,0x00000000000e8c75}}, {{0x00058e168fe9a81d,0x00043a151dcbb9f9,0x0002eed94828803a,0x000fc00604d46e1d,0x000572f3e28c947a,0x000b1cd1dc3c9d57,0x000a45ce4c1cbd14,0x00000000000f80de}, {0x000d8f65d998669e,0x0003c50920f39bce,0x000b6be78ee5193f,0x0008ba13f798e332,0x0006c5edde471997,0x000714a1e1294aaa,0x00003c280002c2be,0x00000000000f2126}}, {{0x000493dde1b54616,0x0002ea44f6ef79f3,0x000c2b67fffeca1c,0x0004ed80eaf66728,0x0008181514a2cb0e,0x0002927ea2bf485f,0x00064574670e180a,0x0000000000012c14}, {0x000339b9a314b3a8,0x000724068c073875,0x0004212e0016a517,0x000651d698b28177,0x00096da14fa8391b,0x000a578b1f310d16,0x000ad7a089be6bd8,0x0000000000044389}}, }, {/* digit=8 [{1,2,3,..,}]*([2^32]*G) */ {{0x00024e7304503422,0x000f0ba86aec16bc,0x0007f0cf87c57f69,0x000ff0789df2f808,0x000d97a773d58978,0x0003f35f685750cf,0x0008c9806bb730fc,0x00000000000fed86}, {0x0006b0ff06192aaf,0x000eadc0fcde080e,0x00055bc2901e7a1e,0x0007d028d3ad6cd9,0x000997293550fefb,0x0005cfbba5c652b5,0x000d2232e12942ed,0x0000000000098800}}, {{0x000418b23a7be4e3,0x000cb162cdf33f48,0x000c8d04be100c6b,0x000d114454eb977c,0x0008dea38a674478,0x00035728a8ce403d,0x000504d459633b74,0x00000000000a63b0}, {0x00010a5f9fdcafdf,0x000c40c74066a938,0x000e6c61b766c71e,0x000b588a99690ede,0x000c3ad775623398,0x000bb60ee4949517,0x000becf9824f09cb,0x0000000000085660}}, {{0x00083bb80ede991f,0x000a02daddb11952,0x000f09f6c4b181d6,0x000e82721a6aa89b,0x0007467506deb73c,0x0008d8daa1091958,0x000dfd0927724c42,0x000000000007c17a}, {0x0009a9bb30e43182,0x0003a8518dab18e9,0x000594c3465b3913,0x000c37f89e7a3983,0x0008e273f6f35943,0x000143d228e63f5e,0x00028ec6d0352b83,0x00000000000ebd16}}, {{0x000731dadf48f7e1,0x000a14074ee26b83,0x00088243bc9a29c8,0x000d53972cecb4c8,0x00079a7dd9c4aa01,0x000c787cf4b0cf12,0x00053f3e3e3f165b,0x00000000000942de}, {0x000bfa5d149fa2b1,0x000010cc6971941d,0x0007bdd5c6a1acca,0x000c1e292314a097,0x000614a1adcb9fed,0x00062b86a7547d22,0x000b7d405561a486,0x00000000000f5480}}, {{0x000be69f3af05d97,0x00082c4e59f2ff48,0x000865d4a01ec6bd,0x0000d824464bbbbd,0x000016f9540dfbc8,0x000595b5d3bacfa2,0x00080d1954efb613,0x000000000007a5cd}, {0x0009c6dbd9d7e6b6,0x000ac926a54cf784,0x000f3366624e7b07,0x000167ccb5c8d4c7,0x000ff9a21ce20677,0x0002df8cdc994d22,0x0009083a25ff6b42,0x00000000000f68e9}}, {{0x000a093607905265,0x000ede544b89ab7b,0x00017731e314dedd,0x0000da69a73104b6,0x00067274b105a6a9,0x000c61bb65c26021,0x0005068f9705cf60,0x000000000003c4d1}, {0x000ed5677f9dc5c6,0x00020ab5a27accb8,0x000e0bb2ed27cc25,0x00036d15a36afae3,0x00095c455916e68f,0x000b5d1fa79004b1,0x00048916ffe6249b,0x0000000000049338}}, {{0x000a7603914a9a59,0x0000b941be86e102,0x0001a6f35b551149,0x00095b469d75ec8a,0x0003db0d4374658f,0x000fc77053fa79d5,0x00012885da635c6a,0x000000000008e7e8}, {0x000f4285c3e56baf,0x00002558cfa8eed1,0x0000effdf411ca89,0x00098b96a32e8849,0x000e3c45ce1a104f,0x00085de0268237ef,0x000de35c820dc22d,0x000000000007459e}}, {{0x000a78ec870a31bb,0x00036923d0b44369,0x0005db7ea085ecd1,0x000be009cf5b87e5,0x000d1d61103d1656,0x00065239313a37d0,0x000ed81d705880fb,0x00000000000ed712}, {0x000ff1a5976c303e,0x0006f15ad02e6160,0x00077114865ad858,0x000376cba2b3ffe8,0x000f9745443c56aa,0x000903660c3be2b2,0x00092d47c8a870eb,0x000000000006c6c1}}, }, {/* digit=9 [{1,2,3,..,}]*([2^36]*G) */ {{0x000b550138d02bd3,0x00038148bd39cbc2,0x000f6b4c6038c07a,0x000fbe2ce5484157,0x000c87fdde9ff397,0x000e9c179441e5c2,0x000c716366b49ffe,0x000000000002938d}, {0x0008a64bcbf3adf9,0x000d026d450f9f8a,0x00015da756f71781,0x000bf4d298fd8771,0x0007544768b65f68,0x000491267e86df04,0x00071a40b69a32f8,0x00000000000f917c}}, {{0x0007f3a58f523dab,0x000a7a66c70349a5,0x000f8ae356d6f09f,0x0003e96b5ab54115,0x000c7c57d123dee3,0x000d6ad37d068929,0x0001780839a208f1,0x00000000000123f8}, {0x000f3c2b5c9dfc15,0x000f4b3e5e52449d,0x00055ba373af8955,0x0000ab7389f2dd3e,0x0005890bba6f513a,0x00066bf093197a14,0x00072261add75b6f,0x000000000004eef1}}, {{0x000fbdf154b15bac,0x00063810b6ab3193,0x0006da8c3809a3ef,0x00038dd898977511,0x000e7a336c9a3cf8,0x0006f89c03e391e4,0x000e227014833717,0x00000000000bc4f1}, {0x000e7d4400e0ab41,0x0006b32b104f92b2,0x000d1a7a3b67e3fa,0x0000437bf178ac12,0x0005c99370d5b831,0x0002b93a8722299f,0x0007190a493cf033,0x00000000000a420f}}, {{0x00046acf9a0ee15c,0x0006a21feb7fb87b,0x000579369777bef5,0x000557624b04e704,0x0006342cb0ad03a6,0x0004f64262531f18,0x0003ea088c4d54a2,0x0000000000006a87}, {0x000f1f11e0fca837,0x000d5dbe0253ef23,0x000bcfdbd73eb554,0x000368173e65902b,0x0002ccbfa504eaaf,0x0000e163e71f1fab,0x000f3bb7b845224b,0x000000000003c779}}, {{0x000cf36036019ecd,0x00029cd7b3c4286b,0x0005e1ca08cbdeb9,0x000bcbd24ef5c386,0x000ce579c309eb66,0x000f6c9007edcc21,0x000c2c7b19d49116,0x00000000000b6317}, {0x000aad793c4e52a3,0x000e7554ba553558,0x0002315e3b514170,0x000e33bffda4032e,0x00082306675c3d1f,0x0000c91e75dfec47,0x000879be59305e00,0x0000000000025a6b}}, {{0x0002c6fd041a12fc,0x0006aa35802f5d21,0x0000c3d459456256,0x000991d472b9d211,0x0006a2f8e875261a,0x0009b6d63d81a1ed,0x000758942f213a69,0x000000000000ae57}, {0x00067bfe08ea2ebd,0x0007061191c82b48,0x0000611a48f73652,0x0003e86525112224,0x000d30dabb91abe2,0x000d2742466dd967,0x00005077650c597e,0x00000000000ab25a}}, {{0x000abb01ee5e0194,0x000bca624ab366b4,0x0009dc413b0af513,0x0009c4273aa694c3,0x0009779288abe822,0x000575e0e0cc3102,0x00003ef8eff30f57,0x000000000007d528}, {0x00093a51fb5fbbe1,0x0002f32d87e548f1,0x0004001c13dfb44c,0x000b8dd16c6e6274,0x000c2c140452aa2c,0x0003031b1add098a,0x000543d25f285d2d,0x0000000000075b59}}, {{0x00032a5061a42b94,0x000dc520b0bb8a42,0x000466f1305a432b,0x000c73a73c239760,0x0009783aabba85c1,0x0004631556e4dec4,0x00017b69f0c69bb0,0x000000000009c97b}, {0x000fbbef3e8375b4,0x000b155af24a9074,0x000991d9ad3481f7,0x000283d708671c48,0x00035fd9001a4034,0x0002eaf3b200ddab,0x0006c4e45f28e434,0x000000000001ba93}}, }, {/* digit=10 [{1,2,3,..,}]*([2^40]*G) */ {{0x000e8393cd68c757,0x000b2b083ba6a1e9,0x0004638d474c7417,0x0007a21fc82dc041,0x000a9d3679d89536,0x0009724c0227be26,0x000c0fc70f6d6c7e,0x00000000000f9ebe}, {0x00075bdec21bc5d4,0x000b029dde03dcdd,0x000a669d8fc534ff,0x00090c90f602f4cb,0x000849722bc4daf5,0x0009b22b617c5288,0x000b90a8df99f008,0x00000000000e59b9}}, {{0x00015e6442d15d01,0x000dc6f5775290ef,0x000cdd79298e58a8,0x000842778b96c6d8,0x00022f59350519a1,0x0007209d6a674f99,0x000fff5abeeec46b,0x0000000000047cf5}, {0x0009d3497d146805,0x000ede24509b7378,0x000ed2fba1e0b34e,0x000af595761e8e3f,0x0008d420a2887f7d,0x0000ff696ed5cfcb,0x000c8f365b29eb7a,0x0000000000099a1a}}, {{0x000785db50fa1164,0x000694936c6a0393,0x0005ce545ed4b2d3,0x000e8b45714f2c6a,0x00023f5ac25a03ae,0x000b33794139bd69,0x000ba96a2e42bab5,0x000000000003ff7b}, {0x00034248c56f7e51,0x00088b61d8643327,0x0008d647e582cbe4,0x0000e1472eb77fae,0x00013b99c6356211,0x00074c9f23d5b96f,0x000250956ecf64f6,0x00000000000ef2ba}}, {{0x000a8baf84131eb9,0x000019ee1ec3a29b,0x000d9f684960ce84,0x000737588102ac15,0x0009c08527f432b9,0x000e3dfbedd296cf,0x000c4fb74f8145fa,0x000000000006cd7c}, {0x000debad8e4205ae,0x00062a0f2fe7a043,0x00094ce3fc7d23aa,0x000f2d40eeb90a7f,0x0000be4de6846e7d,0x000dd06bce2f46e2,0x0009f6cd28feba3f,0x00000000000e6d6d}}, {{0x0002283f4c1e03dc,0x000bc246ffcb6b34,0x000a382150ba305c,0x0003ae2250e66766,0x0000924ce5fab4b4,0x000d8c77695c1b5f,0x0009d02555795beb,0x00000000000acd9d}, {0x000cf0d26acc1b8f,0x00088e1d74aa6321,0x00035822f91490d5,0x000df2795af56df1,0x000fb331b6f4df74,0x00059e13724b10c5,0x0007f2b0a6df9a65,0x00000000000c0663}}, {{0x000c55f77d493f59,0x000089ad73168775,0x000791ccc3015317,0x0006c2d30b3a5f4a,0x0007c89723d59e94,0x00031f6077bc4ced,0x00034179f514a1bd,0x000000000003a274}, {0x0007950f4645c0c2,0x000e07eb010278e1,0x000a3d29cb5ab91d,0x000760f35be21cba,0x000b7c793331718d,0x00030d29eba58160,0x00003afbc0ce1f8d,0x00000000000c6f4b}}, {{0x000986e6462b5c9b,0x0000cbd8c0867ee8,0x000db80962770b4f,0x00012de024593896,0x000fdef840b687ed,0x0000b56e13f7d98f,0x000e8771eee0cb5f,0x00000000000d8d9b}, {0x000f5c1c38b9eff3,0x000c1e6b50b5a5f4,0x000fada267894657,0x0001bd17cb1f9925,0x000d4ff11827418b,0x000042c63607818e,0x000ae3e630d93a9b,0x000000000008c779}}, {{0x0000de60ecec558f,0x000bb35d474260aa,0x0007deb342712d19,0x00015e22e91bf5f3,0x000cc08b6b1abd6a,0x000b97de8e366a84,0x000f29759c122f55,0x0000000000008a03}, {0x0005b54173576b1f,0x00000dcc9fca2774,0x00073c06ae128d8b,0x00039029b59cd052,0x00006f5e5bd4deae,0x000099f4df532ede,0x00005284fbeeb936,0x00000000000088d2}}, }, {/* digit=11 [{1,2,3,..,}]*([2^44]*G) */ {{0x000b3d633d0721cb,0x000732ba8c78fe5a,0x00016e2c1c57f816,0x000f36a2fc2451f3,0x0008bb91e1e36842,0x000ead762fc5c955,0x000556035d1dfcc3,0x00000000000031e5}, {0x000b4359fe8646d5,0x000383af0cc803c6,0x00070f15b8bb97ea,0x000de0a6ade1d137,0x000d93b2dcb580c3,0x000a2214de8c3a5b,0x00048de3adbd7c90,0x0000000000011929}}, {{0x000e8783f9b6f97e,0x0009b65026296c0d,0x00086ba77888a60e,0x00063a460c8bbf8b,0x00078b2a71206237,0x0005497e7fa8f5ad,0x000618fd744bdf08,0x000000000002ba35}, {0x0004df87b45c7eff,0x000870cebfe9d444,0x000c034f12ddb3df,0x00017a3fcf19627f,0x0007c2f112616558,0x000f2c85030ab44f,0x0000c3bb001c9ddd,0x0000000000007326}}, {{0x000e365e9f55b0a4,0x000aeb08fb116bd9,0x0002cf623c1f798f,0x000fc7b6f9549671,0x000f76bd243c73ae,0x00009d5a8c0fb886,0x000049871eacc5ce,0x00000000000e773f}, {0x0001eb3732cb8726,0x000aa92945c840e9,0x000022c04533de34,0x000bc1d0509d7400,0x00010f1af1754762,0x0008c160f15cf97f,0x000f0c1f85569532,0x000000000003b439}}, {{0x0004f7c9bedca76f,0x0006dfa7d1236235,0x000a7e4930642e7b,0x0007288beb1282c5,0x000a07fee8a99ea2,0x00070fee91c069ef,0x0006fa5749c7b558,0x00000000000afcec}, {0x00048441716f41a1,0x00064a3f8f1b0daf,0x000b8af2f805e4cc,0x00029a9b59dc06f1,0x000b98a92c387533,0x0002b4662fa8e5f5,0x0006c66b6f46fd3c,0x00000000000ec04c}}, {{0x00054b9f6efe8494,0x0005eaa16c27a15a,0x000106292d7b104e,0x000d193aae87c9d3,0x0009916d634e7ae2,0x000a65b4b125ab45,0x000e2202ded714cf,0x000000000004e212}, {0x0009494225bd1826,0x000c097c48a1862b,0x000bf9e4c3ff8573,0x000b77b2652f5018,0x000d078efd386fe8,0x000cb82991daa602,0x00062635885364db,0x00000000000b8240}}, {{0x000f5a3697f1c244,0x0000e0430af76c1b,0x000f0e87f66ce63d,0x000905f12e919108,0x000012db9e14e1a7,0x000baeeac1c689b7,0x0003196bdd3dc90a,0x00000000000504f0}, {0x000e18cdf6373284,0x0003c874afd60b16,0x000a978150da10ac,0x000eee1ebf4aab2c,0x000c1aa49fe60d33,0x000217cfda3631ca,0x000e770d8340fbf2,0x00000000000423b7}}, {{0x000b3813851ecc4b,0x0001df8c07372826,0x000ea9f99e2d35f1,0x000faf1a6305a291,0x0007f3e0f93d2b97,0x000aeb8c15bc61f6,0x00024b7238583cd7,0x0000000000039f5f}, {0x0002b746db300ac6,0x000a11cc8b467be6,0x000e46954d17b55e,0x0005f95ba2641ae4,0x0002ce9d565b1b9a,0x000eedc6287a0c36,0x00003d07fb51b2e1,0x00000000000a9739}}, {{0x000d77fe5e566bbd,0x0001978a53b5a370,0x00081dca6fe505a1,0x000f427019a6f8e7,0x0006dc3ad0ba3520,0x000745b7cde6fcad,0x0002dcfec96e4f79,0x00000000000b133f}, {0x000924a225ecf745,0x0000c50088a2b006,0x000c145291ebead7,0x00032ff23ae4b9d3,0x000e85246712f213,0x0000b515e8cbc659,0x0008b727fa9c8df5,0x00000000000494ac}}, }, {/* digit=12 [{1,2,3,..,}]*([2^48]*G) */ {{0x000ff6bf222c5c9c,0x000322986475308d,0x000309c5ef927cbf,0x000d6b4216ab9acb,0x0007be12d76a038c,0x000347bdb3df9b7b,0x00048913f4d9785f,0x0000000000013e94}, {0x000466717b5c75f3,0x0000a5f8e796eab2,0x000d6af2aad3919a,0x0005d8ad10740b88,0x000b5337dee6254b,0x000f02247c38b8ef,0x000c4cf688c2e194,0x000000000006c25b}}, {{0x000272cd3b35df41,0x000d936c9dbbec27,0x00026ae70fa619c9,0x0008db696a8f9f19,0x00056b01e6bc1ab3,0x000fc4adae031d23,0x0004e410466ae68a,0x00000000000ed9c4}, {0x0005ea962547af52,0x000cb61272c12a27,0x000f929706a5a2ac,0x0007a910ecc49eb8,0x000ccbe84d5cf4c4,0x000e497d7eb95dfe,0x000ce443f3b71c8e,0x000000000004c6fe}}, {{0x0002d9d94d551889,0x0006182e5d818574,0x000101531df0c231,0x00044261daa2e22b,0x0000e46f32576b02,0x00069db38b86a358,0x00027eacf145bd76,0x000000000004df27}, {0x000d2ba752047cd9,0x000c203d9391e25b,0x0007c9592434b2d4,0x0007845ec38fa9ac,0x000a265ad6bbefb7,0x00054a1b2dd40660,0x000499a22d988618,0x00000000000737ea}}, {{0x000ef1248ca55f15,0x00028e323ed0c422,0x0001736a7d35b006,0x0002f06e8d68e4e9,0x000ad0742e5d9c09,0x000d3df92d8f5555,0x000eabe2d175bf00,0x000000000004f71a}, {0x000a6a143a42cf09,0x000c6d1762d7229e,0x000840a2cbe90735,0x000cb4c6281f2a74,0x00003603e53a2caa,0x000fecf29635ba47,0x00036194a9811d49,0x00000000000466bf}}, {{0x0009fc85048451fa,0x000fd4737236d065,0x0005b89cfa755eca,0x00070306da6e06f0,0x0006f3838f569da9,0x00043188730279bd,0x0005d0fb328c8b94,0x00000000000be90e}, {0x000859016f87df1b,0x000843334a6711d3,0x00078d74e5890358,0x0007b6e38904b738,0x000296b588a53493,0x000577ae391e227c,0x000c7da599b21544,0x00000000000214a0}}, {{0x000fcc62fe159c27,0x000c9e63fbb0fb71,0x0007ab3cd12c8947,0x00030677afd4bf85,0x000dfd37120d5cea,0x000d718a74494e39,0x0005fb8c572c7249,0x000000000005fa30}, {0x0005abf2e0c1181d,0x00074751c217ee1b,0x0005917c5a26a520,0x0006e6efe7a64872,0x0000f53b0e479a99,0x0005fd5931a4f6d1,0x0009ee651390ecd1,0x00000000000739ee}}, {{0x000e27c9677a2151,0x000ef0b6d37446aa,0x0007f13e8f2bd87e,0x000c94fa109847d5,0x000044944c7712bb,0x0005a31b874c0d53,0x0005920d280b18eb,0x000000000007ef42}, {0x000c07ddca373d80,0x0004ef11030c77be,0x000075bee798eeea,0x0002d013d22f1b04,0x000cd93ee54dd5e0,0x00041d4b1b6d66c9,0x0006ed80b4154faa,0x00000000000acf8f}}, {{0x0004ca485f1804e7,0x000ad0f05710ab2a,0x00002b0d41da0420,0x000a67a46b8d0e2d,0x000c698b78cc137d,0x0008a9393454b89f,0x000e69f2a6e1de25,0x0000000000016488}, {0x000b96b954a8287c,0x0003d7c6c5501c10,0x000fb63222050457,0x000e30e92f152478,0x000327e70a0a4b9d,0x00014936309d4ca9,0x0001379c8b16340d,0x00000000000ce642}}, }, {/* digit=13 [{1,2,3,..,}]*([2^52]*G) */ {{0x0003c432161be476,0x000c0f8a8499b505,0x000715248b87d78c,0x0001b1d515e1328e,0x000ba941e788b85e,0x0005dd8d888a2636,0x000350a045241d2b,0x00000000000332f0}, {0x0008eeabc026bdc0,0x000f796c4b204e16,0x000ce54b1f342310,0x0003fc6d00b602a1,0x000e89aa3b796fc3,0x000d4dd0007a914e,0x00095635353eb7a4,0x00000000000673e8}}, {{0x00027e0f6ecb7465,0x00040f36e83987c1,0x0002e0c806d929c2,0x00007464efc5b0d5,0x000ad316c43436ab,0x000ccf839b211e59,0x000a072515ec9f16,0x0000000000003dc6}, {0x000ec4a69e8d5661,0x00017842b727527c,0x00065c4526d40261,0x000711ccef5255e9,0x00075108cb92967d,0x0001b9740cd3bfb0,0x000308e50c0d8aec,0x000000000001a9e6}}, {{0x0002078cea733c1a,0x0005b283eec25eca,0x00036d44d991d5b4,0x00083b827ad302e8,0x0002bde3fdd0269a,0x00030b3a6225f2f1,0x000043046fcf3801,0x00000000000c3ed9}, {0x00066dedc2439ae4,0x000eff870f14cae6,0x000680b39cf67cb8,0x000d5f4847be7732,0x0003d0ed73a0f3e1,0x000b3babba949822,0x000f706933ccf014,0x0000000000037f08}}, {{0x000ba839c8cf3524,0x000ed1afa6aa5579,0x000f9ef0d2ddddd9,0x000920b5d36da502,0x0009291e774f07fb,0x0000d87a8144d51f,0x0001a026c2c134f4,0x00000000000a932f}, {0x0003544f31a7b78f,0x0009935bb2a42294,0x000ea47969f6664d,0x000cabfaa1838ed8,0x000fe2855f1f5c40,0x000525934ea0c05f,0x000fd4931ebb02fd,0x0000000000016246}}, {{0x000bd623cb7fe067,0x00038ecfabd26775,0x0008c3832c0a3527,0x00064ccfe2691ca7,0x00058347566acf4e,0x000b8c733e3889e2,0x000f5748da354885,0x000000000009d9c9}, {0x000592cc5e5c9fb4,0x0000e8c26a8d609c,0x0000459f168ec210,0x000a70a3f8db9f92,0x0000e758213e181c,0x000b2653e25aa645,0x00003aa4898f9169,0x00000000000ccd83}}, {{0x000fac468f3d59db,0x00099517d13b0e90,0x000cf2490366b8de,0x00026866d752aaab,0x0001cab026676e2e,0x0003163c395da9fa,0x0003c9be8d91ad42,0x00000000000a6995}, {0x0007a57ea4ee9030,0x0006ef728b1d231f,0x00013aa7ae93d8f6,0x00000a82e75d9c30,0x000e3ad09def97a9,0x0008a2be8136c6b1,0x0004474bab14a6dd,0x0000000000025cf1}}, {{0x000e1d30e97eb41c,0x000b411b59f3da92,0x00020acfcec12d54,0x000f0a1936595900,0x000cca0b1b0e5cad,0x000274a5e8fef04f,0x00027ebcb4d9fb0c,0x00000000000ba784}, {0x0008e71ae4477c5e,0x000fbc49f0bc478a,0x000ac96d890c62e2,0x0009e583f796b820,0x000b17964262200e,0x000db00395bbea92,0x0002ba86b3c15756,0x00000000000ead48}}, {{0x0007642e08638534,0x000b5cd92906c650,0x000ae6db49a06b5d,0x00029781fdc19156,0x000c269d611e0d69,0x00065b00a45d01a8,0x000388e7bd1e7096,0x000000000009bcaa}, {0x0007591cdd6ae97d,0x000ed8f189e87506,0x000ccf1d10959a9b,0x000bf16c633b1123,0x0009d6f1dac8ca65,0x000c3381dc6adc9c,0x000d120df2c293a3,0x000000000008388c}}, }, {/* digit=14 [{1,2,3,..,}]*([2^56]*G) */ {{0x000653d60a9d872c,0x0003bffdbd0eb2dc,0x00061fddaf39f568,0x000cead35e7a3a29,0x000c67833028c11a,0x0004c79764998cf8,0x000a1c8f3a346b84,0x00000000000db9b1}, {0x000642a471b701b9,0x000628735dabc47d,0x0005300f39a216a2,0x000dd49d267a01b0,0x0003ffa20d117c0a,0x000ab2d4a2b46c91,0x000080f2acef26d8,0x000000000003d926}}, {{0x000ba70a22083784,0x00084e9d2a98a2f2,0x00091072e4da23c2,0x000325dceaf86ae5,0x00088f161525f399,0x000211b9d03b17c8,0x000a48d8ac35c984,0x000000000009050c}, {0x000bbfa19d5ef891,0x0006ba818c44b2c9,0x0005e1b560830da0,0x000af35f8715b052,0x00099d8829a9633a,0x000a820f15463e1b,0x00075db18df52d84,0x00000000000d0966}}, {{0x000ae853a945611a,0x000bed54e2c7c031,0x0009b2bf77ae12b1,0x00005e8e60f7f5a6,0x0008427483adcb41,0x000bff383705db30,0x0006e9f73ba98bf2,0x000000000000220e}, {0x000231b48f25af77,0x000e8c01c46b84a3,0x0004ae472f3bd7a2,0x000dc0bfa3403e6d,0x0007d2202896f738,0x000882e5e098bc68,0x000b13ec0c217a5f,0x00000000000a1f4e}}, {{0x0009208204f520a2,0x000ed2615c78254f,0x0002b7a2ee7b484b,0x0001d771c84a04b5,0x000fcb9f9e349c3b,0x0004f7846b6fc203,0x000248bed65464c6,0x00000000000eb004}, {0x00040455a574f8cd,0x0003f5c017726a4e,0x000b0a7d5066828d,0x0006666aceb0e3ac,0x0008fc046f0ab78c,0x000aa959518d3c18,0x0004e87f3e2f301b,0x000000000008a284}}, {{0x0008a96d207a2eb2,0x000e3c899eba3614,0x0002ec9689146ad2,0x0008629da55568ed,0x00082b1dc1d9607c,0x000c001ff6b54722,0x000b8523232311c9,0x00000000000488f8}, {0x0000aca655c2cd82,0x000723867ac9a850,0x00092fe2557b4773,0x000c647a74488fff,0x000fbe0876407398,0x00019a571f6ed920,0x000aeb72beddc763,0x000000000006a244}}, {{0x0006fe658431a6d6,0x00064b7da79c5a1c,0x000fc6b2b6576354,0x000b7b54aa36d18e,0x0008ed0e30913481,0x00093074c6efeaf8,0x000654eb017bddc9,0x00000000000529dd}, {0x00089f1ff5fdf666,0x000fcf5177230c70,0x000373317732e646,0x00082d34ca267426,0x0005adcd1650194d,0x0007758b7eaeffe1,0x0008194dcec3d9af,0x000000000004cc2c}}, {{0x0003e55601cd21ee,0x0004794bdc7f4a7b,0x00080eb7c8f212fa,0x000dab0d654cb574,0x00037a49195627e2,0x000d5d0991d4e1e5,0x000de7a1ef570c31,0x00000000000295f3}, {0x000c78902e5817a8,0x000198681b00d89c,0x00061b3376c1d033,0x000e90c6a1b57484,0x000c1222e5544324,0x000d53dd044f9324,0x000ef0e30ba10fff,0x00000000000b48ee}}, {{0x0004a14fee68295a,0x00041a349bb65da9,0x0006f09eba200d68,0x000d891c18d37516,0x000dae8d2bfba6e1,0x000b330789985aa4,0x000e948baec9ae31,0x0000000000098750}, {0x000e6cd5311f8630,0x0009c0d834bf8a5b,0x000c536623c88198,0x000faaa0c51d098d,0x0002b887a10f0c22,0x0008bed323240404,0x00066231f6a61424,0x000000000001ce0d}}, }, {/* digit=15 [{1,2,3,..,}]*([2^60]*G) */ {{0x000c2532e44da930,0x0009eac6dbdf6097,0x0009dd0474f3e9a9,0x0004de3dc28e1b18,0x0002a66477111669,0x000b08b4b2d039cf,0x0008cea13bbe6fc5,0x0000000000010ebd}, {0x0006e345ee3db6d1,0x000c2cd4720862b2,0x000fcd0516567c14,0x0006303929bfa29c,0x0003818249bfb3f6,0x0007f7cd97c378e4,0x000a1676068c8084,0x00000000000987eb}}, {{0x000e55f593b72e2d,0x0008c1238e0971aa,0x00081a4c08ea4523,0x00054e7f74c5c514,0x00028805813b4512,0x0005e7a6e238b16d,0x0000bc23987b2892,0x000000000002a1a1}, {0x000c0e8fa1a83cf0,0x00010944c784c643,0x000f1939fa2e366e,0x000ab2aead457171,0x000631c042056bf1,0x0000b8881d5f8f0e,0x0005a8ac062526a1,0x00000000000fe550}}, {{0x000d9597e54c99bb,0x00076cbbd8575ded,0x000019092c8277a0,0x00056202e6b72a58,0x000e7c024443e5cb,0x0005368f35738ea0,0x00044f8ed06170b5,0x000000000001aeed}, {0x0001a7ce730f30e4,0x0003a3d90a6b26fd,0x000480ba5c428a59,0x00093dcc5612aec9,0x000f99c1bacc0890,0x00043eaadc272ef6,0x00089147db3b43dc,0x000000000000832d}}, {{0x0001abaa498687bf,0x0001bac92ee14ee5,0x0002ef494748554e,0x000ca876e7a32661,0x000a8456c9af29a7,0x00054326f0f2b7e7,0x000ec87471824e97,0x00000000000364d2}, {0x0007a1e32547416e,0x000f386d8aacd172,0x000735a9921c3b5f,0x000fc881d79f7eb2,0x00040040547d9805,0x000b4e90b377ac3a,0x00081bd39215d461,0x000000000004c5fd}}, {{0x000bf8e11ac3f3fa,0x000df9ffe5562f1b,0x0000905bb11344f5,0x000f981cbefa3c77,0x0003667bfd643039,0x00040e3df2ab0688,0x0009ca9007a25743,0x000000000005a3a4}, {0x000a64031de3bcfa,0x000fd9c7be629ab9,0x0003fbe0cdc1be9c,0x000ff39e7380dbb1,0x00059facc3b8ffe7,0x000ae422c620bb9b,0x000c432ddcb8cd31,0x00000000000d12c3}}, {{0x00072db65199d9d3,0x000d703621d34a54,0x0008bb1d8b92a619,0x00000f66ca2933b1,0x0002de1494a2886d,0x000dcdf82d0a2238,0x000832b8656c4d0b,0x00000000000c4a58}, {0x0005f2f5aceb0154,0x0002fa982c1aa34d,0x0006b9fce5077d2d,0x0008de431390c6e9,0x00018c4fe595fc26,0x00090d82fea4160e,0x0009076c427a6367,0x00000000000fc519}}, {{0x000775c688e983e3,0x0003e8c0749464df,0x000f192d78daad34,0x000e96904bb2048e,0x0004d6dc8b606cda,0x000438bbc6dec959,0x0005a58d26586954,0x000000000001b0e9}, {0x0001e04544fa17f3,0x0005e8189f1141bd,0x000c131e8abc17dc,0x00075a227f8ec1ab,0x0000607e37397757,0x000793e4e7a12524,0x000af4afae84e74f,0x000000000005bf5b}}, {{0x00039549b6d366af,0x0000aa10292b850d,0x000fff80cff6798a,0x000f18f73ad7a1fd,0x000c5897b11f7a36,0x000664c618b2c7b0,0x00022cf7b9a272cb,0x000000000008f81e}, {0x000e957ffad5963b,0x000663b99b210935,0x000ea3abc7ab4283,0x000175d001db74bf,0x00067159cb8a3af1,0x000de4601526f084,0x000eac6a3c6e1feb,0x000000000008c232}}, }, {/* digit=16 [{1,2,3,..,}]*([2^64]*G) */ {{0x0004c667c92f7888,0x000aaa54768d9e88,0x000d1397d0aa7f52,0x000f203faef6863d,0x0004bd7471b3774d,0x0007de2e9f795a03,0x000cfff0958718b4,0x00000000000e1160}, {0x0005c7ba07a0ffd6,0x0005186ded97af9a,0x0008fa18cb4fab4b,0x0008920424e84590,0x0004eecf8b2b0558,0x00068a6fa3745591,0x00019fe7d3df1fb9,0x00000000000bad07}}, {{0x000b4e8b4136f0e4,0x000ae2566021f579,0x000cbf2ef6760188,0x00047a5d9f51b6a3,0x000df8efa64634e0,0x0001f584f0b50d91,0x00091cc2bbcbb297,0x000000000000907c}, {0x000fd43610d5f812,0x0000ca7ebeb0dd65,0x0008a7b6eef1e9c1,0x0009a073f5c962ab,0x00053ff74a2fc04d,0x000f0749d95c155e,0x0005d0923c65a53d,0x0000000000027ae3}}, {{0x000cd3b33afd62e7,0x0003c4d37c266037,0x00042b261375e38f,0x000a2e928ca9d674,0x000a79beb236566d,0x000f801e7a9771c1,0x000358af6b97a976,0x0000000000071259}, {0x00004ab4fe03d3c3,0x000bcc23a5e31cf5,0x000c506466ff69e3,0x000233b1911ccf3a,0x000cfa3b3ace3f3a,0x0004c5f5c93e4664,0x0003c04bdc14832d,0x000000000006abf1}}, {{0x000832aefb763bd9,0x000f0d5469c7af17,0x0000d7bc962f1b04,0x000ca21a16caa7b0,0x0002e6cc7f39f881,0x000378723221de18,0x00066010d61ab531,0x00000000000520c9}, {0x000ed27c50cc42c5,0x000ac145214ccbc9,0x000ac441f327ce66,0x00059e30cb1fe6a2,0x000a3e299fe79fce,0x000af78cf2e6e77f,0x0001593a0cf652d5,0x000000000003e852}}, {{0x00087e649fa97c56,0x00029ebbe18b74d8,0x000417a0e476f2ee,0x0005a2a0b24f97ba,0x000262fc61243ddf,0x00003b73af9a400c,0x000fde9ad9b0bc6b,0x00000000000153c8}, {0x0006f3a6ac904b01,0x000f41b6477d9542,0x0008ea414bce433e,0x0007128953069569,0x000db9e775794428,0x00005e0d14b5db01,0x0002f5237edf0bde,0x0000000000085533}}, {{0x000e220415482512,0x000190791dfa1ca2,0x0007078d88a1aeff,0x0005b77ccedf4f34,0x000d5d965c0549f2,0x0009e672705170cc,0x00017637d9521bd4,0x0000000000086a00}, {0x000e53f005b29758,0x000b5dab44493664,0x0005df02ede5bef3,0x0000c3e4c2506ba1,0x00065ec6f1324366,0x000ac7691b2fb261,0x000eb5ccc4221a99,0x00000000000a576d}}, {{0x0006b1405a6d6a62,0x0001e3a17f86cedc,0x000ffc614b14d0e0,0x000a3f0927935e2a,0x000ac04d4fb0a86e,0x0007694212f43742,0x00012f32a30bce38,0x00000000000d8d39}, {0x00091bf3c81523e6,0x000ed34154b18f9f,0x0001725c2ac49b1c,0x000be0f9f7a13c1b,0x000a531736e526cf,0x000cfa2c250d50b3,0x000e5f81849773b2,0x000000000003ba8a}}, {{0x0003089126b94126,0x000854a87307686d,0x000fced9f497ff98,0x000042f427ea198a,0x0001ed259219c1d3,0x0004850cadc59211,0x000e8d0abdbd1623,0x0000000000043b6f}, {0x0004352ff19d9aba,0x00069d3c79d16450,0x00090120dc8bc8d6,0x000535d5a98bf664,0x000dab2cdb2ba736,0x000af89eeacb3b7d,0x00053237d3743ada,0x000000000000b348}}, }, {/* digit=17 [{1,2,3,..,}]*([2^68]*G) */ {{0x0006e0a86f5827e3,0x000e1a68295d9bd5,0x00032e6b7dcbdf31,0x000a0cffe0c3df09,0x000b3cd00a1a8deb,0x0000f90885b4d037,0x000ef7e9edc429aa,0x000000000005847d}, {0x00025d7642f87bf0,0x000f49739d03ced7,0x000f63949ff1cd98,0x00034ff1759060ab,0x0009a7e94dbbdc3d,0x000e8b7f3029e9aa,0x0006f42a3cdfa0f7,0x00000000000bbd8f}}, {{0x000178a4d4ad7d87,0x00040cd8c2ec862e,0x0003f7b9dc665542,0x00086d4db83e1ac5,0x0002bb549bb5e123,0x00007c0f19a79203,0x00008eaf81cba628,0x00000000000abf20}, {0x000001ed540ad4e0,0x0000a9d7a72302a9,0x0007110b90df5c50,0x00024daec9005170,0x00037193eb3047c3,0x00015c655408cd0d,0x000c228f0bcce2d3,0x00000000000869d6}}, {{0x000e5354c88a38dc,0x000717192a26df13,0x00059c532d5dc6ab,0x000195620aeab120,0x00057c2328498938,0x00079bc39ebe39dd,0x0000925787970e4f,0x00000000000143e4}, {0x0006e01b286241f3,0x0001e5f60303562b,0x000cf202635ec6b7,0x000b3a2f1856e619,0x000bbf77d65c7ec4,0x00011058fbef7dc4,0x000945b444d50670,0x00000000000c33cb}}, {{0x0000e30b66c01c80,0x000354b5e753d742,0x000c1ca06540fdb4,0x000d75f42fa905c4,0x000ac33e462b4034,0x0008de3bb89b85ed,0x00039131f413c305,0x000000000006ba75}, {0x00046bc0a659bd1e,0x000573f50020190e,0x0006ea7059f1f5a4,0x000aa10efa2adddf,0x000e1a6566aa7297,0x000b4f2143e8ccdb,0x000ae74dfda07fd7,0x000000000007cb1c}}, {{0x0008cb34259001d3,0x0001d49d1cfcc46a,0x0008f80188e0d2b9,0x000d285d2ab0a996,0x00071df5b6cb8cd5,0x00003fadd9c5cff6,0x000c0019f4095a30,0x00000000000aa463}, {0x0002c2d4a3652c8f,0x00087f86673b013d,0x000814cd905b85f4,0x00075b44cc2cd5ed,0x0000b0342517b376,0x000817cd771d5262,0x0006183af1f31657,0x0000000000079199}}, {{0x000066ce8afe9a22,0x000815600fedffd0,0x000fa276d4e1e61e,0x00062674cb08e4e2,0x00052e9ab52d8f12,0x0005686adfab0c1f,0x000e4e090b1ac94c,0x00000000000bb10d}, {0x000c301d650cbaa8,0x0003b3383f48546f,0x00045006d2b6b386,0x00092fe500058f01,0x0007f4ce508ac5ab,0x0007a5166f03c7c9,0x000d66525ac2cea7,0x00000000000996ef}}, {{0x0002ee0f55870dbe,0x000f522daed9eb3c,0x0008bd7a619de4ba,0x0007daa46ec27562,0x0004df0f7a076593,0x0006036c14c58eeb,0x000aa5eb972393fa,0x000000000004d17f}, {0x0005a44cb91701e0,0x000a3de29c31e831,0x0004699fe7072908,0x000952e2c563ddbf,0x000e5d6b0b57ac00,0x000c4728203a767f,0x000d56e858fdf3a6,0x00000000000a5213}}, {{0x000b5ed7b705b7ba,0x0002631796c22d0c,0x00099ed65d60e408,0x000cb716cb0c301b,0x0007d1702ca94ff0,0x000a02a90dd0cdbd,0x000625470a26c8e1,0x00000000000d7054}, {0x000218ab60af89bd,0x000e0fadc2e8673f,0x0000890003c99982,0x0005ebb2951a8fe7,0x000364197a76042b,0x0009c1b5de4af9d0,0x0002b1dd2c6bb324,0x00000000000f0193}}, }, {/* digit=18 [{1,2,3,..,}]*([2^72]*G) */ {{0x0004ea16a709d85d,0x000329ded9b0ccd4,0x0002e9bda4d583bd,0x000aaf5393937290,0x0002a438413e94f3,0x0003c7de32213686,0x000540449286da37,0x0000000000029aa1}, {0x0001d592acb2cf64,0x000ef1bd13e4055d,0x0004681cce9d2c6b,0x000558f6bcd0cb2e,0x000e9e610369d43b,0x0006e0651f5757c0,0x0000aa15c80b23c1,0x0000000000000182}}, {{0x0004d40f93bd737d,0x0008c10a8aabc8f9,0x000d5b1177a72237,0x000df1a076945a2e,0x000c03861f02a009,0x000866a3cf869152,0x000cbbc405226e9f,0x000000000008b41e}, {0x000cb1b314f36d3a,0x000bab5c9ed101e9,0x0005d83bc9ae2498,0x000f22e57589279a,0x000d7fe2d6aa1a9e,0x00073dbfa83ef607,0x000066f2da845434,0x0000000000057879}}, {{0x000f91047abd3166,0x000593df98ea92d5,0x0002ec06cefe6ff8,0x000d1b5ea6d69771,0x00097e25ffbcc9cb,0x000a6280e3f9f231,0x000713bca8e0567d,0x0000000000035cda}, {0x000fe70b79caf906,0x0003946ef321cfa3,0x000b4a657c54ec43,0x0003b4b51de40452,0x000cccd9ba8d37b7,0x000f7045b5bccf3c,0x000dcca2ca080dd0,0x0000000000068cf4}}, {{0x000d265e2cd7626e,0x0007e3499b44b9a9,0x000ad7706fd7669e,0x0000406c1f517d80,0x000b82a174e83014,0x0002c9b3ad4b3c8e,0x0006f4c8835b13af,0x0000000000044371}, {0x000fa90f05b33562,0x000c2336c4f4b966,0x000385e7d9f805d4,0x000a2dc828c34d3a,0x000c34d0d1f76ffb,0x000a4fbce257a345,0x00049fbc1eff056c,0x0000000000007683}}, {{0x000db1540add72ad,0x0009e5ebdc79cc93,0x000baaf845cf7653,0x000efe79c8b7f7df,0x000ac469aa5793f6,0x00033c455b2f1e40,0x00012a882f0e9434,0x00000000000aea07}, {0x00030f4a7dec8786,0x000e9b13578c31bc,0x0001af154c9f03fd,0x000a2d854e09133c,0x000cc6ad853283ac,0x00004f75cae03943,0x000c37ce0a619171,0x00000000000f9838}}, {{0x0004bc7eb2d5ec5c,0x0007e9db114e2be8,0x000c421a1f0f05da,0x000016bd2f3080f0,0x000fb9b7203704df,0x0004fe2ab0cb3f7c,0x000ec1adb877c781,0x0000000000037761}, {0x00081bf9c70c3c38,0x0003cb5d6068d8ec,0x0006b75a387ed168,0x000aa5457d36d422,0x0007423cc8cb39b4,0x000a6566dec1de46,0x000f55280e02dafd,0x000000000003ca55}}, {{0x000e1cebdad8aedb,0x0006b340d77c218d,0x000b7391085bcda5,0x0005b028b74d32db,0x000a3cc1117e3e91,0x0006c5939ae7101c,0x000caa3c36152b52,0x00000000000d3ec0}, {0x0001039f162ada74,0x0004534de058e1ef,0x0005d23a486e5201,0x00030efc214ac0e4,0x000cc7100acb27c0,0x0009097b72a216d1,0x000aaf3b73004330,0x000000000007afd8}}, {{0x000af1b588df6219,0x0003a5d7afe99881,0x000b20bd69a8d3f2,0x000067dc65234936,0x000527557f5de39a,0x0000e9f9d3458527,0x0002d8756b8d8693,0x00000000000040d5}, {0x0003845ac0bf2beb,0x000a9606eb60a92a,0x000238ad785ef768,0x0005748e068d2949,0x00022fce158da621,0x000183c8f73fbdca,0x000c989cfee07dcb,0x00000000000a5e03}}, }, {/* digit=19 [{1,2,3,..,}]*([2^76]*G) */ {{0x0000e52cf2e9b4ad,0x0003f86230933fe6,0x000fe37b1c8aab75,0x00086ba6f595ed40,0x000de2284a5801e1,0x0009e5e25d3291c3,0x000f5303dee2311b,0x0000000000015cc9}, {0x000f15883981ad15,0x000444fba15675de,0x0008ff144b8a465b,0x0001eb92532d015f,0x00084e7455de8690,0x000f811c94396fd7,0x000b372fbcea8fbc,0x00000000000ae952}}, {{0x0007195bc501819f,0x000f06bd2c54c87b,0x000c8e0d99fb53f8,0x0002654e3eee748a,0x00039598d90727f5,0x000cb371256f2058,0x000c5b5f91c2d027,0x00000000000a3e33}, {0x0002b15fc69c25d9,0x0003e248490a9884,0x000516ef1dee14b6,0x0008b3d74f7d38ca,0x00002fb602142013,0x000033d4eae791f6,0x000f176b4fb300bd,0x00000000000bdfd1}}, {{0x000558e7c27dd125,0x0004d9bd2b68cfc0,0x0001783c86b4626f,0x000f35989586da1d,0x000afd0944ca67e7,0x000569b5abc04c8a,0x00046eb8db5424f0,0x000000000000cc55}, {0x0008ec9be17ec8dc,0x0009e8f0ef9decbe,0x000cdc094579a394,0x000eb644e7329b8f,0x0007e6896b042ec1,0x00018b6bf3e0e7f3,0x000fa6ad2bff11c1,0x0000000000040f93}}, {{0x000fa586c442030a,0x000a30c3d2055f9d,0x000061ff065411bd,0x000a98b1fbf56cae,0x000f396e31cd1b68,0x00082c03b56fd85f,0x000917d2ca584443,0x000000000007d3ef}, {0x000572f96fe58801,0x000c74129a730d28,0x000ce4a000ce9071,0x0004180653f3b241,0x00049ee066bd9e85,0x0002ea5fee65a1a1,0x000e2e3420084e36,0x00000000000c7911}}, {{0x00079bb68a21bf45,0x000b04c3f4f487b8,0x000f5bdc807ffd5c,0x0009bad1844be875,0x000e272afc140fbd,0x00040a7386b3b80e,0x000a37d727b0b6aa,0x000000000004d809}, {0x0001886f07e4e9c3,0x0004c09fb0640689,0x000e568c8f4da447,0x000ff8ad73a211ba,0x0001d9a6b97da7e5,0x0009e8f56ccdbf62,0x000a0938448e2cc8,0x000000000002126d}}, {{0x000bfb3f1befeb61,0x0004c43f0ae67505,0x0007b68cdb6c3beb,0x0006c25dbb4492ec,0x000884bff97fd5be,0x0002da2e27efc9ee,0x000c3254fbd9d706,0x00000000000c6d2a}, {0x000d04af3852eaac,0x0003e14cf6dc0935,0x0006b6f8f3aa240c,0x0006543d9a16800c,0x0009beb1e28dd056,0x000e658339cc2ade,0x000cb2cbfeb45038,0x00000000000d0f5a}}, {{0x00014927529fad7a,0x000714f10299a19b,0x0007bc14eebc4178,0x00018bc0cbede41f,0x000e6b03ac7d024b,0x0005213be7883c01,0x000540a7b99e741c,0x0000000000085a97}, {0x0007979358dabc76,0x000060b6fe59caa3,0x000a32d2efcf0218,0x000969d6ad1891a4,0x0003ee7761dccaa0,0x000b12539c47afe1,0x0005f4cae681fcdf,0x0000000000002ea6}}, {{0x00033b53cfd1d032,0x000865e930d64f49,0x000e6882e13322aa,0x0004f7efa08bd4a8,0x0006a6e10f64cfac,0x0007ac162277e845,0x00068b41be306740,0x0000000000052a9b}, {0x000cf81e872685ed,0x000e28d8d216a150,0x000406cac9d54222,0x0004102c60d54c43,0x000028815187ad9a,0x0003b8e59b09420f,0x000ba1881179c60b,0x000000000005b09a}}, }, {/* digit=20 [{1,2,3,..,}]*([2^80]*G) */ {{0x0002bb0ebd1ffa8d,0x0000c22313ded9b3,0x000c76c37673c0ae,0x000eeaea76ec3812,0x00060275ad3643d6,0x000095bdaa165513,0x0004b0e5c1b65adf,0x00000000000367c4}, {0x000f3876ae1976b5,0x0007de2b419c1bd2,0x0005d5344cebbb0b,0x000e51fa2baff060,0x00006269b5d0b5fb,0x000e8d667a0594d7,0x0006e70b07b70523,0x0000000000063e01}}, {{0x00082243f0134f99,0x000d9022aa09c335,0x0001e1b9a8966dc5,0x00044c5b38b417ba,0x000b436451ec3173,0x000b1c87629a74cd,0x000ffdd898eb6ca8,0x00000000000b74ee}, {0x000187e3675bea14,0x000410d9eab63bb0,0x000dd59e68360fb6,0x00094ce14dbff2ff,0x00092706528037c8,0x00029a0cd3704d34,0x000c4f9ee435d8ba,0x0000000000009c11}}, {{0x000414827bc8962c,0x000552fde4893802,0x00000bdd0aabfbb8,0x0008a5b09456ed5c,0x000925797c6c157b,0x000c14c0673606a7,0x0001caa9d0f47c33,0x00000000000faf97}, {0x00082453cb3879aa,0x000ec6e763c509a5,0x0006f45dc5dfe238,0x0007ecbc49e9efce,0x0007b38f2b59d95b,0x000c397db0c31792,0x000bc797912b53b3,0x0000000000045c7a}}, {{0x0002600fe807b0d9,0x000578b3269a1894,0x000cd6a11a8caa23,0x000c714e428865d4,0x000ffdaba094bc5a,0x000d657f2531dd17,0x000bbf86d2405718,0x000000000002f99d}, {0x00063a9cad22b4ec,0x000d1c428a80ebb2,0x000111bbf67dd9f1,0x000691922a5d2566,0x000318a18586a752,0x000f633b3bfe6392,0x00029828a0c772fc,0x000000000003f3c5}}, {{0x000cdc4baa08bf36,0x00052cd81bdce7a2,0x0009dbe6198554f1,0x000228bf8ebe39d1,0x000eb2cdd8524cb0,0x000e9b3af496a9dc,0x000f8a0f115a1ad0,0x00000000000d8eee}, {0x000de9efc567fd4a,0x0009b5232a514417,0x000762e720496fa2,0x00018b08994b4e8e,0x000809097a52289d,0x0004621d0b4e346a,0x000ab8c641510f32,0x0000000000095a41}}, {{0x000c5913c30a847d,0x00004c8c9b0adae6,0x000c6088d1ec2259,0x0007946e62c508f6,0x0006e9fe2321b03b,0x000c1d1366042592,0x000c9c73b10bba80,0x000000000009d218}, {0x000e72b1483512ee,0x0006d6ed0c8eed83,0x0009abfdad8b62ec,0x000096ab9e96167e,0x000cc473e3773078,0x0003a3bc8b28f0e6,0x000796b44e499568,0x00000000000d3523}}, {{0x000ec81c53fdc5cd,0x00095261578c7817,0x000dba0eec8c348b,0x00066b414c803900,0x0005faa7cc399932,0x0009b7e27bacad75,0x000533418c4defd6,0x00000000000ae751}, {0x000b26e534337f55,0x000f36f3bd3298fb,0x000bd59fe7197151,0x0004f73dc4c54ecd,0x000d44d3d74eb716,0x0009ea511ca66290,0x000c49f77c62424c,0x000000000001f714}}, {{0x000343bd88e025df,0x000b893a62e7c716,0x0003b75e6fa4a448,0x0003cbb10cc95456,0x00062f37154c265e,0x000f2e08b28cceb0,0x0000916b79b0713b,0x000000000003ab39}, {0x00046ae52480b7d8,0x000a750a8d04cede,0x000f3c798fdbfa72,0x000336ac21cc62f0,0x00036fc004503db4,0x0004b2d954747f0a,0x0007a7067cbf1c54,0x00000000000fd2be}}, }, {/* digit=21 [{1,2,3,..,}]*([2^84]*G) */ {{0x000f8f632d3f21bf,0x000880233e423a7e,0x000fc3a5113e93d2,0x0009cef6349e35be,0x0003ded2ec542ca0,0x000dded3d3b70afc,0x000ee0c813474d52,0x0000000000012f00}, {0x0002c304534f52c2,0x00002a0908f763fa,0x000cccb3aba1eb57,0x00010c134b6a8e10,0x00056e7c163e84ad,0x00057e0c36f37fd9,0x0001a27caae8c8d0,0x0000000000055372}}, {{0x00086fa76217d20b,0x00015a354c1de108,0x000a55c4648be905,0x00010999d532bbe4,0x000f520117516766,0x00059e35eb7c2f4c,0x000b7b6945d34ff6,0x00000000000a1303}, {0x000495f21c8085bb,0x00028a200ddba08f,0x0003caf84b1e53dc,0x000445faa82b46fc,0x000cfccedc1b3018,0x00053e29fc3e6a3a,0x000547e86ae87033,0x00000000000fd7e8}}, {{0x000683184a93e477,0x000a4728c8e14128,0x0003d8bece755c7e,0x000c2da4796df734,0x000e00a55efc3016,0x0006b1cb8f6d79e4,0x0005a94fced26952,0x0000000000091f16}, {0x00031165825c7f6e,0x000cf528b857275f,0x000d8cb6dce0ced4,0x0003520e07bb990b,0x000f4ea8ae6b4f90,0x000b735bb07ddb97,0x000d4a29c01e70b3,0x000000000005000d}}, {{0x000f814f4e7d6929,0x0005e306b63e3665,0x00098d89bb61e0d2,0x00068898bdeddea9,0x000d67a329ac36bb,0x00092ccce9331655,0x0009b414c7fe26ba,0x00000000000be051}, {0x00042824d37928be,0x000830dc39dbc42d,0x00083d595f84e0c5,0x0008818fa8682bba,0x000db60aad97c7f7,0x0002c64cc43396ea,0x00043e751784d7ff,0x00000000000866af}}, {{0x0007b94e1c1e3bf9,0x000a53742b61de85,0x0004d0debb63955e,0x0006787abce34016,0x000ea4cb41b4f52c,0x000ca817e4749711,0x0000487ce0dfb03f,0x0000000000096e85}, {0x000c4c6d7efe5c7c,0x000b6cd65250dc1f,0x0007ec2aec96d815,0x0003cb2b4dd561a2,0x000abb5379f57352,0x000a847ba15ba773,0x0002decc5e62d6c0,0x0000000000004d85}}, {{0x0003450b4a8e849f,0x00036f0a69e68100,0x000d9356a0504fb6,0x0003ab7cd14af1d4,0x000d558d555d773a,0x000e63dd6c0b88ed,0x000db3eb12d197d2,0x00000000000bcd9c}, {0x000ed15d1fefd8b7,0x000fa06432985766,0x00052d6c3d3a4a47,0x000f6164171b9bc6,0x0009bbfcf90abd28,0x00036084d3778163,0x000a751f93898f3a,0x00000000000dd00c}}, {{0x0000e82da9d478f7,0x000ae3b8d8e48b47,0x0000534e09405090,0x000430c2aad8c684,0x0006b82c16731d72,0x0000fb41de8c5d50,0x00034f989978868a,0x000000000000f812}, {0x000d9518cbfe70fc,0x000f1a0c941ce78c,0x000c323a8cf0aba1,0x000e296101f89af8,0x0003ca6a3227aa7d,0x00064ec0c4cadd8e,0x000db43b4db51f27,0x0000000000009256}}, {{0x000e28a122d0f32b,0x00022b9207dbc085,0x000dce5b9cc6b932,0x0004e5534ba150b8,0x0001dfec99724992,0x0006f870d2935ebf,0x00085c34bf5e94b7,0x000000000004c203}, {0x000bdbb9ed40b2b9,0x000c3c78ac1719f8,0x0008866adbfa0f7d,0x0007ee4cfb4b8bb6,0x0002cd8724b676c6,0x0000bc1efecfaefb,0x0001b5e9bc3d6734,0x00000000000ca554}}, }, {/* digit=22 [{1,2,3,..,}]*([2^88]*G) */ {{0x0004ccdc054842bd,0x000704f293478100,0x0000ca74cad5c267,0x000c94f64d55f6f2,0x000d725c51251bf7,0x000b6a0914489b57,0x0000fa3aa4d43ab1,0x00000000000cf7a6}, {0x0007fef943134dbd,0x00038aa918a4ce7d,0x000eee4d56ef907f,0x00000a16812a03d0,0x00070b0a1e4bed0e,0x00028386bb09acf2,0x000321c73a41f7ac,0x00000000000f4cd1}}, {{0x000b2804db21ede5,0x000fd10a53b8f9a2,0x00080087f23a6e5f,0x000513fabef2b974,0x000cd3f802fd740d,0x0000627afff6cc47,0x0002dc1be6825beb,0x000000000005886c}, {0x0002ebc44567c313,0x000afb6cfb2c6b07,0x000e1dddbc404a5d,0x00016f53a5a485ba,0x0002e7b2223e7a1e,0x000a13a9b16b60b9,0x0001a2332f33d836,0x00000000000876cd}}, {{0x000bcac1cf1b2eda,0x00095802f495c1f2,0x000e55ffc912d44b,0x000b294e9b3f0f6d,0x000033cbdcd1eaf3,0x00083fce582cc760,0x0004cc1a5642278e,0x00000000000ffa0e}, {0x000dada72c71a95f,0x000ed7d93e9766ea,0x00015d2d9c24e57f,0x000dd79eafe5f361,0x0000fcaafabbcb53,0x000053efecbbed8f,0x000b7a570472705f,0x000000000001ebfe}}, {{0x0005f3669cd44c3c,0x00025a896d28dae1,0x0002e7c6820a84bb,0x000fe8c06fb15cd6,0x00061cdffdad1bba,0x000119b3a2daab29,0x0005a3984defc8e1,0x00000000000de2a2}, {0x0000f914a19c745f,0x000b3a7f54ecdb35,0x00041f75def22ce4,0x0000efc6a3b94437,0x00076785163b6913,0x0002b1d0a5d17f12,0x00093cc019911b17,0x000000000007e3e0}}, {{0x00049fc81e69d5e0,0x00085d307d4279b4,0x00039a33441f2443,0x00078371531d6263,0x0008b42639ecfff7,0x00099fb76fdd61b0,0x000f0eca9462e7be,0x000000000007c3f2}, {0x0008f656f3641bfa,0x000f85c07066bcc1,0x0008bd883c4e6617,0x0001387d93ff4937,0x000b864eed19b6d3,0x000fad6382fd7d67,0x000fe667b707ff5a,0x00000000000d0206}}, {{0x000bb568a2a2f3e3,0x000a9235455295a9,0x0008072539522964,0x0006d10c75720aab,0x0009f6a0df88ac83,0x0005a9c96ea2c538,0x0007bedfbf31519e,0x000000000008cad4}, {0x000d6b001091ce3f,0x00036dbd5de982e7,0x000e935fa43e76d4,0x000fef6324ba9235,0x000e8f14a2f5a2bd,0x000880ade8b0f981,0x000d4a590de1c45f,0x00000000000107f3}}, {{0x00091e8b5ebad75d,0x00009b03d47621b9,0x000da50c79b05bb6,0x000ca72548723c56,0x0007c944e3849da9,0x000947973a12e40d,0x0001ea403dbcf2cc,0x00000000000c6ef4}, {0x000f1cf0966fef48,0x000d74ccc2856b9a,0x00011bbeae1e30d2,0x0007f7e43ee1576e,0x000a0a894961701a,0x000396f6e7f061c1,0x000ca956059fb88f,0x000000000001a91f}}, {{0x0000a27b9e3336b7,0x0000be185bdc20d5,0x0008a8bb1575f81e,0x0003397c3fe5695a,0x000f61f6a04f1f6f,0x00090a92b6c9f3a5,0x0004543c0f9d4bb3,0x000000000004793b}, {0x00055e696b3d9202,0x000d991ad0c33a93,0x000c4d967cf46a4f,0x000d90565d53c83a,0x00034176007dfa24,0x000d1623cd63e583,0x000345741089fd2c,0x000000000002685d}}, }, {/* digit=23 [{1,2,3,..,}]*([2^92]*G) */ {{0x000883b867d2fbb5,0x000271d51015761f,0x000afd0328ae7e6f,0x0007e2fc6dde9e2b,0x000937d5bb1f2ea0,0x000cc6e28ceed9ad,0x000fc43121994b98,0x0000000000067ad8}, {0x000d53a60b81c5b7,0x000ca34707fb3d11,0x0005e1e4ff2b5765,0x0009b8d81ef6cb57,0x000b1223a9a1fe93,0x00074cf375c51e8a,0x0008e18f6d7993db,0x0000000000097280}}, {{0x00067952d0358e02,0x0005b0db3322730d,0x000098edfd5f000a,0x00085380e8a38fae,0x0005769360d86efd,0x000f27ef5c1812ea,0x0002e8505723dc76,0x00000000000f35af}, {0x000764970d5cb557,0x000849f7bb7fecc3,0x00052323da5066c3,0x0007549773eaf7f9,0x000489d51bda0118,0x0000ccde605bbbba,0x00087d52cabb0664,0x00000000000e7ff3}}, {{0x000fa071b96c7c7e,0x0009c70187dfb0a2,0x0000f19decc5bd43,0x0008b816a6c0d616,0x000d6a27e97b3018,0x000a389aaeaeda67,0x0002734a5192826b,0x00000000000a2bf1}, {0x000832bf68c7b455,0x0000c8ff10656bdb,0x0008bc56c7023546,0x000a3e11dc7aed54,0x000b38853d61e34b,0x000cbf658c457048,0x000edde89825db1c,0x000000000006b255}}, {{0x00067336ad6a8789,0x000d0c377b3730db,0x00063e31dca6f13f,0x000f2adf39b68951,0x0006bd6da22ed9c2,0x00009678e1bbff10,0x000e783f7e5b8e7e,0x000000000007ed3e}, {0x000a0e3ab40df97f,0x00071689e6b30fb8,0x0000b670f8712d68,0x000277edda78c55a,0x000cefb65cb717d3,0x000a30f0ce686cac,0x00071e758aa1ab19,0x00000000000b11f0}}, {{0x0007d3d2024290f7,0x0000c0bef2d25159,0x000b908d7c494e4d,0x00017cedd4af7aeb,0x000bc8e88ca42c24,0x00020d15452b5b3b,0x000d4bc00328c44f,0x0000000000030af5}, {0x00053687c2073cc9,0x000dee8bacbeb2cf,0x000bf613b57931f9,0x0001da61d9e70314,0x000c0e70a331b67d,0x000e325772ddefcb,0x0009797d09bc6d61,0x000000000005b52e}}, {{0x0000d7a5438e4dd1,0x000b5d40f36e5e3e,0x000702a395a7941d,0x00094d7cc51dbaf1,0x000f0edf8bf9e340,0x000b5e16520f93f0,0x0003a8534b75aa23,0x00000000000dc1b7}, {0x000196b771cc1d7e,0x000b09dd48c40ca1,0x000664851f0b3766,0x000f8a2a9ffa0db3,0x0004d94ed9bd4212,0x00069cb198d5236c,0x000dfc81bec489f1,0x000000000006104e}}, {{0x00076550d0174653,0x0008d9cb21b56311,0x000fe59ad5e35eee,0x000a67100d7b34c9,0x0001a6c1b0c3e3f3,0x0003c3e31d4bcb3d,0x000be86ebd26fb9f,0x000000000002dc79}, {0x000582f4b4dfea09,0x0002ae7cf9a0a1f3,0x000c37b50dcbdab8,0x000320e69e1f08bd,0x000b946f83d78b0e,0x000a399ad2a8caf9,0x0000866daff0ba98,0x0000000000038ed6}}, {{0x000af81ab2009a09,0x000fc16f3708ae33,0x000f381b02290f16,0x00015b227bb71a8b,0x0004162f8b5597a6,0x0001e3fb9a8b9a86,0x000ff680ee8362d9,0x00000000000f83a4}, {0x0005ffc830c362b9,0x0009507a7873a90a,0x0008c2637b53ccc0,0x000683d860d60ba4,0x00071f87d32a427f,0x00050319dea99592,0x0009ceb2ac69faa0,0x00000000000d2d0b}}, }, {/* digit=24 [{1,2,3,..,}]*([2^96]*G) */ {{0x000fbfb66a502f43,0x0008324480c57881,0x000d6a55d7a45e41,0x00002c3273e2bc82,0x00053ef1ed4c7350,0x0004948e88c42e9c,0x000632028babf67f,0x000000000008a978}, {0x0008edce917c4930,0x0001bf5f13a4625c,0x000e9dd4dc6a263a,0x0006bcc37232768a,0x0001576e8c1830f3,0x000bcb766c5317b3,0x0004dcef1d57a69b,0x00000000000b3e3d}}, {{0x000aa97e11eb2f75,0x0004f53ebbaaea28,0x000f59d2921161ee,0x000f25d340986b44,0x000e3365312a3c15,0x000641f96c5925d2,0x0008e4c35d3ee251,0x0000000000098412}, {0x00032040e2f19c59,0x00029b41a21a75a1,0x0005c4225a472860,0x000f4c0faf5663dd,0x000a0a62c9dc4ffc,0x0002d60c5889d285,0x000be50908665acb,0x000000000000a131}}, {{0x0006f87a21caa381,0x000a6318feb4c006,0x000ed4b6b2c3b939,0x000786d5b2386621,0x0005a722c5911e4a,0x00006cb0188e0430,0x00036438eb062af4,0x00000000000e7216}, {0x0003e9f2fb9e0c73,0x00093450c1d28f54,0x00023904331c181f,0x000a53a6f6c06813,0x000a25eac032fe46,0x000c497224553199,0x000a2941fa659aff,0x00000000000bbcb7}}, {{0x000a3dcccc791733,0x000a8c0de60f43c9,0x0004454fef6e3630,0x0002aa8e734e2e0a,0x0003ef773db6f412,0x0002d71c508f40f6,0x0008250a7e9484ce,0x0000000000078a3f}, {0x0005a99063a64539,0x000ef0cac7a5b50d,0x000064e61e079dfa,0x0009a90d3e181458,0x000a0aadf689ecf1,0x000f0acf70d1b062,0x0002b942299f1ff3,0x000000000005ac25}}, {{0x000b4c356075ce0d,0x000a8a4bfe150fb5,0x000907dbaf6f1c40,0x0008260a0ee708f9,0x0004abc9d5f541e2,0x000aae99eff4fdff,0x0004d96ed92241ff,0x00000000000c04fe}, {0x000731763369357f,0x000a8f10a173e2a4,0x00065723921ac826,0x000823f8ed02e85d,0x00042e522dc1d2a0,0x000c939fdffa78cf,0x000bba07041e4600,0x000000000003a9a8}}, {{0x0008012ba5de4e7d,0x000c7a1fc20f7144,0x000540a292e6e434,0x00081c28e2e8e16b,0x000a4c4562342e55,0x000e31ad4912c80f,0x0008117fd61fb9e9,0x000000000001c19e}, {0x000de815bbe3ce38,0x0003b6a7ab2cb6d7,0x000aeaa95e1796a8,0x0006a85ab06af4e7,0x00044866378d33f7,0x000826f8cda387e5,0x000cb6bb71deb856,0x00000000000eb64e}}, {{0x000d7e72d8af89da,0x000ba0e93593424a,0x000584230569d130,0x0003dba8e15d8645,0x0001cab64644ab77,0x000fff0619cea4a5,0x0006a4516754d72e,0x00000000000cd3a3}, {0x000ee6af7eb6909f,0x000c6c7d352abc75,0x00007221eaa0649d,0x000ed979199938f5,0x000acd6f34958a8a,0x0005f93eeeb06789,0x000851c51d776677,0x000000000000a8af}}, {{0x000b089742823cef,0x000c544bfd166199,0x0008c58b08cf9fc3,0x000cf81c39366838,0x00068b08680fe50f,0x00032aab0c9b4eb0,0x000ddaf90882c528,0x00000000000ecbf5}, {0x0004bc1447794cdc,0x000f8fd4d51c6fd3,0x000cc355ce034b68,0x00053dbfb187c34f,0x0006f8ed037fb729,0x0007bad45166f7f2,0x000808d2b1077a09,0x00000000000790dd}}, }, {/* digit=25 [{1,2,3,..,}]*([2^100]*G) */ {{0x000273ed4a6f3c1a,0x00092a05c751c876,0x000bdb5d554c8320,0x000e26cf4c98fee4,0x0009e7b3a7c79c56,0x000cc16466084f8b,0x0000bca0b042f6de,0x00000000000fbf3a}, {0x000078eb34f9801e,0x0006694524c2c1cd,0x0008ad2d5e6f66b7,0x0002d6e7ce1f9f62,0x0007fc0c34fa1879,0x0000a16938ebc2fd,0x000019032a9f4178,0x0000000000056a60}}, {{0x00009be19d72cca6,0x0009ea4b957d1c55,0x000c88712c99979c,0x0005e80a271d9e14,0x00044b9367e51157,0x00079779f0fff68d,0x000f68f55ba67322,0x00000000000d4d68}, {0x000ebae305d14369,0x000b401474ab1533,0x0007e0884a0d1ea6,0x0003a8336111d25d,0x000fab531cef6390,0x0002ed86737342a5,0x0007e1d3c93fe770,0x000000000006279f}}, {{0x000ed609fa3c6148,0x000beb398290bf69,0x000b5366c9b47f2a,0x000aa2956560b89f,0x000c50e6647b3e71,0x000be42da80817aa,0x000a4e35c833ada0,0x00000000000f1bab}, {0x000a4dc6e615148d,0x0009ac57be644e77,0x000de3f8f9ac6cc1,0x00077310defd9095,0x000e899cba568300,0x000effb5a92fe9bc,0x0004bf48450ec4bc,0x00000000000f2f5f}}, {{0x000e1a6a67c12c1b,0x000e7dccf68bc63e,0x000af5107f8ecb57,0x000e199254dd3e41,0x0006ddce5c84e43a,0x0000b4258e8526e2,0x0004c452bad815ea,0x0000000000009457}, {0x000fc838b5157d7f,0x000e1a5362fcad0f,0x0003a5c9b577c868,0x00012b5eeffc2cdf,0x000b14de4e5b0f93,0x000233fa55475657,0x000ec2746e67d4f0,0x0000000000035471}}, {{0x000afd6c233d63fa,0x0009cf55edabb6d7,0x000b353b7e2a9194,0x000822b9bf171614,0x0003afe808dcf53e,0x000272f554a5b3b9,0x0009a1590bbbded7,0x00000000000eaea7}, {0x000101d093edb837,0x000b5d7042bea6a3,0x0006a766d7a462c5,0x000e69031078aa66,0x00087e37bc8bd8d1,0x0000089759e837f1,0x0008679558ff4f85,0x00000000000421fe}}, {{0x00076617121c3ac1,0x000a13503d9370d0,0x0006e1d369d53e18,0x00001ef5b52e0f07,0x0002f955b5fa67f1,0x0000e0569b6b5b4c,0x0003efb5f03d5388,0x00000000000c9939}, {0x000c81fd72768469,0x000a690755bd5e4b,0x000324dbfd474da1,0x000fd519e9ce792e,0x000396ccfa14326f,0x0004a22de1b772d7,0x000342652710f487,0x00000000000db210}}, {{0x0008597293bd01e8,0x000dfaa6489def01,0x000dc630321a7c29,0x00043a95fa2efed7,0x0003720e1a8c4d89,0x000a4f8a3c9baae5,0x00006bc055444b95,0x00000000000a7c12}, {0x00017016dee8b7c9,0x000dfd97765b5926,0x00050b911df827d2,0x000c35af1503b16b,0x000fa9fa21f8115c,0x000fed1f11dd5359,0x000679197c32996d,0x00000000000f77f2}}, {{0x0004d7575fc73ce2,0x000ce58d6998db75,0x000d11d5d661c62a,0x0002a0165739fcf5,0x000822f7a073420b,0x000042f005c5db30,0x0003d9016c547805,0x00000000000a1241}, {0x0008aac8eaa9ff4f,0x000fe8ceb2d6ffe8,0x000f806ab6efe1ae,0x000d012339c146c9,0x000628ac05552638,0x000d46e6302fbb7b,0x00088e7fcb0c8162,0x00000000000066d0}}, }, {/* digit=26 [{1,2,3,..,}]*([2^104]*G) */ {{0x00029831f2b8ed10,0x0004917e3d0b77e8,0x00062b9d59b96ed5,0x0000261d0bb1849e,0x000ec71a3bbef8ef,0x0002a88ae9b804ce,0x000b9e00b7d17154,0x00000000000e9097}, {0x0001f74d24b8094d,0x0000cdbad9f12075,0x000917cb364517bb,0x000834fb83debf54,0x000d637e449ba8a4,0x000b82664c3ee226,0x0000e8e3070d93ca,0x00000000000b3732}}, {{0x000cd133b578c566,0x0004bb506b7b86f8,0x000a189da5b723c8,0x00029ad3789281ee,0x0001f9af456164b7,0x000f9186069ae8f8,0x0000fb007befe156,0x00000000000edc25}, {0x0003b5e8dc3a9219,0x000ab1c16d7598b7,0x0000fdec987e0e87,0x0007da936881f89e,0x000103a5b1ea5dc9,0x000153a0faddb603,0x000ee27eb515b13e,0x000000000002b4a1}}, {{0x000bcceb06f924be,0x000d4e6b739c7071,0x0004a4fc7ff778b8,0x0003acc1b4b45493,0x0008f6bad44a14e3,0x000020972d6704b2,0x00033543cd7e5ddf,0x00000000000e0d6c}, {0x0008ad0a64850139,0x000b67d395c3ef6a,0x00040e40560ce9c8,0x0009f21efe4a5757,0x0004f55ea727b626,0x000450c823f97b37,0x0005d5b689b4de42,0x000000000004f5ae}}, {{0x000bd2a72ae0f683,0x000d7e7365f9e264,0x0009dec60e7c539c,0x00089ac8e611fc3c,0x0005699c227dbfb3,0x000f2ef17ce778fd,0x000ed4dc1f47b63f,0x0000000000002672}, {0x00013b4caed73e7f,0x000a551c63805fa1,0x0002b72b6fe7e133,0x0003d13e00e12a38,0x0000bf8df325375b,0x000f5f21a91f9f75,0x000584f1ea0e421d,0x0000000000032c60}}, {{0x000c6a3d385d54a6,0x000a26d720050d7c,0x00008151ff431078,0x000aee6f1c89ce3d,0x000b57b2b79d5d1d,0x000c7ce823f7644b,0x000b0bb1063f92fc,0x00000000000c15a9}, {0x0004b892e4ed0e8c,0x0007865661a5290d,0x000a266171fca5c3,0x000dc5d42ecede66,0x000c8eb0689e0661,0x000d7ff77be586ca,0x000c3bc86641a02d,0x00000000000b9ef4}}, {{0x0006b862a25bd60b,0x0005903b07fb53e1,0x0000603f2bb26df9,0x0006449356376454,0x0002a55bcadf272e,0x00071c6af2b6ad1c,0x00080686c527765c,0x00000000000c1678}, {0x000fb64422cb7cb4,0x000660cae829453e,0x000b68619a56abb9,0x000f8337513dfb65,0x000e1b351dda504d,0x000af7cd04260ee8,0x0000fda473c5d9db,0x0000000000071e39}}, {{0x000c98e3f8d5e928,0x000c217544e9789d,0x00047053e368c072,0x0000e3937af8cf8c,0x0009a2f308e2e146,0x0005060e98b4aa2f,0x000a7dafa2bdbc3a,0x00000000000f84dd}, {0x0004961384232a8d,0x000d53b256b55aeb,0x00063be03fa9b44c,0x00010d13c8e52f06,0x000b38865772c405,0x000416f1062c1542,0x000eb54755de7ebf,0x0000000000097aa2}}, {{0x0009115b2961da7d,0x000f01d9aa9f9fd6,0x0004c642e6501980,0x000d6a17f167b479,0x00085bd9153d7ebe,0x000682ba6324c13f,0x0006e2e9ea5b734c,0x000000000007e3ff}, {0x000ac4814edd792c,0x000361ed2b04fb2c,0x0001100e4a13806f,0x000a5d3d68b8ec70,0x000d1c6ce0d2afce,0x00019410c21dc058,0x0005340043de75e7,0x00000000000e15cf}}, }, {/* digit=27 [{1,2,3,..,}]*([2^108]*G) */ {{0x000e0e09fdbcad95,0x0004ef7aaa73197d,0x000fdf5aa02c7c2e,0x00017372e0c286f0,0x00025da3472da1a4,0x00076f2a23b66850,0x0007d4bc0d116b75,0x00000000000a36a2}, {0x000b11735059e67b,0x0001ecdb3f4744cf,0x00033adc74dab02a,0x00011b969d4f1723,0x00066cca4ef7c70d,0x000c6afdfdf96d13,0x0004da570693db2f,0x0000000000056750}}, {{0x00080567673bd755,0x000df02c6b607d3c,0x00025bebf3a2d95d,0x000b01d4f57eb0c9,0x0004d750e515af5a,0x00089ad6859935b9,0x000eff32721b408f,0x00000000000a7e3c}, {0x0009a7a317218bf0,0x00010bd462fd8d81,0x000035ae54257b2d,0x000da619263fa61b,0x000eb6488eb34162,0x0005680c42ed1f2d,0x0007b0b0bd37a872,0x0000000000029ec2}}, {{0x000d73368a1e2f2d,0x00047170f8a745d8,0x00056c4ca9228944,0x000bd224b08921af,0x000de6caca3a5f65,0x000cb9d5b1017ae3,0x00099b613f36b626,0x00000000000ed19d}, {0x00092b03ebebeebf,0x000c752c915a4d7d,0x00088621f044eee8,0x000f7c206a51a132,0x00066e0197ce2cd7,0x00071b04cfed60db,0x000b134e5b2bb7d9,0x000000000002f45a}}, {{0x0009fb6e89b64981,0x00034fb09e755c21,0x0005804661454c99,0x0005b01cdb1f4f66,0x0008f1dd1cf0451c,0x000687e41b02f906,0x000bd3d4765e7c0c,0x00000000000d1967}, {0x000f135de5248a08,0x000f406a0e4ec0b1,0x000b70c2868ad046,0x000d01ac651d8073,0x00030618a96cc1e9,0x0004ad8ce5e6ebd8,0x00090f9ce1aacec5,0x000000000009953f}}, {{0x000f6e431dc5b814,0x00044fa4b66978a6,0x00032f1c66e89ca4,0x000ba60986c85001,0x0004dae014e110aa,0x000bc0e4649bdfff,0x000d5fe2a810bd0a,0x0000000000062d1d}, {0x0007dc411c936920,0x0002c15d2f2c7072,0x00075b1f6234ac4c,0x000b6f94c545f5b7,0x0002f99241e840c6,0x0007082935875b6b,0x000344fa3e88a9d6,0x00000000000ad6d9}}, {{0x000edb2b4857e570,0x000fba8d7901c33b,0x000ae7d92e8b3979,0x000d7c504e4bce1a,0x000e5ab0696fb905,0x000db9cd5dfbf9c4,0x0000fe0f4e6e2ab6,0x00000000000482e4}, {0x000aa1f98e714cdb,0x000225ccd9b418dc,0x00058c553b3cc2f6,0x0000dbe59065754a,0x000a461c1620cebe,0x000e541a74d052d3,0x0002d8396bac422f,0x0000000000070bf3}}, {{0x000a0c1fea68e228,0x0005003c88a847c6,0x0008f73e5d2fc7c6,0x0003d393870d90fd,0x0004f2fdb976d90a,0x000312a302fd78d1,0x000f2f9472a6066a,0x000000000003484a}, {0x000f5efbe46efdf7,0x0008c7cf25950c82,0x0006be05e61c118c,0x0009379e563a2bde,0x0004b46e93d85d47,0x00037285ce87b50a,0x0007e69128fc11f1,0x000000000007c67d}}, {{0x0006a0e99182cb3e,0x00059da2b072529a,0x0000a5cae364c3e2,0x000e35a5b132756b,0x0004fadb6907c721,0x00083f546e5695e8,0x0008aebc5a3bf4c2,0x00000000000dde12}, {0x000842d7630a9d87,0x0000d179c7fa6028,0x00016ae518569923,0x00083bea16bad558,0x000e9137ecd8af7e,0x00030d1ab6f41231,0x000ee8ac87543d8f,0x00000000000b1ee0}}, }, {/* digit=28 [{1,2,3,..,}]*([2^112]*G) */ {{0x00021880433d0094,0x000fe359cbfa01b1,0x000ccfcddd1c5f17,0x000e90f630cbcb5a,0x00006ddbf2382fd5,0x000f753e62b0f613,0x0000165070970a3a,0x0000000000041727}, {0x000724192d1373c9,0x0003e2eb15b3b70b,0x000786ed962decdc,0x00074aee930a75c6,0x0006849e77270d43,0x0006a19ff3cd3604,0x000c049ac3117e33,0x00000000000433dd}}, {{0x000b49aee05ae3b9,0x0005d985dcb4303d,0x000d13447c8994a2,0x0007f3055fbf1d6c,0x000f43fcd98a4059,0x000ec99cab6d166b,0x0003705932570915,0x00000000000c5bdd}, {0x00050b2df8b6890e,0x000dac18f782613c,0x000d7472d5468bfb,0x000a89df478e56c7,0x000864d290535d50,0x000cf7e0e242c2f4,0x000d40cda12c6161,0x00000000000ac8d1}}, {{0x0001c7858f5f5373,0x000027a9a9dd7275,0x000baba450a60383,0x000267b6726c3253,0x000d7f841afb1550,0x00004643012cfb2f,0x0006cba41b19052f,0x00000000000b7d78}, {0x0007d7e12176321a,0x000667b61b39c512,0x00091b7379479d0c,0x000efb84a3489052,0x000cf2e864b965d6,0x00096cdb2f377862,0x0000f63c94000dab,0x000000000008efef}}, {{0x0001ea0f696fd259,0x000ff8c558000585,0x0007b878d3ed6d3e,0x000d75ceb7a35cc0,0x000cf0a93110acf0,0x000c50c850fbdce4,0x000d6f82b2d13a9c,0x00000000000cef70}, {0x000ce46086dea462,0x0001e1cc9be2dbe9,0x00043757ada5e365,0x000479f195a532b9,0x000a1ab3605c52bd,0x00024c1e0769fe6c,0x000d7aba6a63e48a,0x0000000000099da5}}, {{0x000ad5fa3c1cbaf9,0x00066df2a6cec962,0x0003dc76a0f4995b,0x0007e4c0de8a6aa7,0x0004be7b8f5d7c8a,0x000da3e7e5c806b9,0x0008e5ccca1c714f,0x00000000000cff78}, {0x00056778e2279cec,0x0006e17a081a8743,0x0007133643f614b8,0x00090549e4cfac8a,0x00029d53a2000d7c,0x000977a8b6fb74c6,0x0007c465b9ed6d5f,0x000000000000ba2e}}, {{0x000a6aa57649a837,0x0000f8435e295b6f,0x0009b668270d6cf9,0x0006e6fece5cb161,0x00095336f7ffe2fe,0x0008ee2676f249b0,0x00017b5801feb990,0x00000000000fc8f2}, {0x00006b2a4f1b5cde,0x00053fc1adc3e51d,0x000e0bc8cae40bdd,0x0005404cc1d9b726,0x0001a1f2c5a44afb,0x00008f19575cabd6,0x000f492bd797e1cd,0x00000000000cbea0}}, {{0x0008ce5f4471b983,0x000d8e9759aa9a33,0x0001c65f7f2a0258,0x00059aa2c80bb617,0x000230c9b328e49a,0x0004ebffcdb89e21,0x0008e4f42b9adb00,0x0000000000047967}, {0x000c42c02e645b6d,0x000f20dde5b0e690,0x000d9a21c0cf9036,0x0007a5cd8c8285c5,0x00071d1562069f8d,0x000e126bcd7cde59,0x00060bdbe765d7a8,0x00000000000e3f4e}}, {{0x000bcd16afac5b0a,0x00041509abccab5b,0x000ba67813ffa4bc,0x00071bd640bc2f7a,0x00078f546c681ae3,0x0008b8cbfa155c29,0x00048b8858cadcc0,0x000000000001d969}, {0x000da5c95714aa4d,0x00010919cb2262bc,0x00085c89980779aa,0x0000f1ab4abe5612,0x00069cb75bd125dd,0x000a778e4c6bbe63,0x0004b3bb367cf947,0x00000000000bde52}}, }, {/* digit=29 [{1,2,3,..,}]*([2^116]*G) */ {{0x000545d771f3d008,0x00076c6307398a47,0x00054915c4cf9c72,0x00026aae3a993222,0x0006da9308d18e01,0x00068e5050fbfdf7,0x0008bd2163ed6b61,0x000000000007500d}, {0x000f06ed5b023878,0x000d3f571595fffb,0x000ccfd2dfb01965,0x0005f7e53d84c661,0x0009025029da6b22,0x000d89aed9c03126,0x00015054c1edfa17,0x000000000006b435}}, {{0x0007c3fb4d5bcba6,0x0005b009ef80a60c,0x00017966ca95c6c2,0x00055ed685add960,0x000672c7dac8ab44,0x00072f16818f323f,0x000a99e7009790e3,0x00000000000067be}, {0x000c5bcf19664dda,0x00043f15bdbcc383,0x0007e49d4e4912df,0x0002c304bdbec36f,0x000d1b3ac6c72fd6,0x0002938898b3ea93,0x000f8bce1c8e5c9c,0x0000000000011564}}, {{0x00098a86761cd6cf,0x0008477faac22471,0x0009e917079e4be8,0x0001dd45fbd35ab8,0x000a45d6d40e31ad,0x000749ef67e0de9d,0x000cf2a16c5f1939,0x0000000000085691}, {0x00046f38fcf548ca,0x000e7156536ac506,0x000b8e250c84b9f9,0x0001eacd35088fde,0x000538fb995c165a,0x00093b3a5ce8a733,0x000e7934d0d33132,0x000000000008b570}}, {{0x0002b3fc481df360,0x0006d6a3a232752d,0x0000509b75e73d18,0x0000c3322a82d404,0x000a14cbc8351703,0x000da272724bf18e,0x000d4a319dc4cab2,0x000000000006d020}, {0x000398eafd6e92bb,0x00066aeebdd89825,0x000a73a882a68cbb,0x0002978595f361eb,0x000c1ae8fa3cfc8a,0x000341575e60dd96,0x000e4819c2109aa5,0x0000000000006a0e}}, {{0x000065dd44a81443,0x00083443deaaabf2,0x000c83e66800298b,0x00018ded51d6acd9,0x00017d4ec9bef889,0x000c48a6948c9b2f,0x000f5478b41104df,0x0000000000078827}, {0x0003f535562e2f60,0x0004674ed7948c07,0x0001ccc08940c103,0x000449b0d9fe252c,0x0006c14e825a6fe6,0x000690f0031743d0,0x000748d9d4ad8c08,0x000000000000e65f}}, {{0x000eaf196980dd99,0x0009692501ff821f,0x00072b4a2cc10b2a,0x0009a05e53038473,0x000c2543d1a995b9,0x00080877130a72fd,0x0001456648126b11,0x00000000000eefb8}, {0x00041f6a86207b43,0x000d8d9a87f836b7,0x00016f9bd17dd926,0x000e118c40122e4c,0x000f853b291e3341,0x000565bade513567,0x000f77d4f1bbb73b,0x00000000000a7658}}, {{0x0007b4a08d152bb9,0x0007cbab37a630ed,0x00077618410cb7bb,0x000086c1d4a8f5be,0x00046581428269e1,0x00076cc7d3a87384,0x0003a0b642dc1626,0x0000000000097e42}, {0x0008ca2aba5729e1,0x0005b66ac1b365bb,0x000e67e449b0ae7e,0x000debbadcc68242,0x0004b1536fa18f47,0x0009e546144e9bf6,0x000b901cfdd50493,0x0000000000043bb3}}, {{0x0005a0a5974046e0,0x000112e32f89636a,0x000495f55b511bd6,0x000b1ad8f8328866,0x0008adcbd933278d,0x00064f863271d907,0x0003652208fae34a,0x0000000000039c89}, {0x0000e167567c2b6c,0x00048cb46f2725d5,0x00086f7986cb61ca,0x000d316edd504188,0x0004cabe36ed3421,0x0002efcdab1d8a06,0x0003eedb13e56036,0x00000000000c71eb}}, }, {/* digit=30 [{1,2,3,..,}]*([2^120]*G) */ {{0x0000e8a3d453ef19,0x000752af8ed809c8,0x000017d0798a8632,0x000726f782193578,0x0001b87254c44c0e,0x000e7691a8c1962a,0x0002ee30796a71c9,0x00000000000a75a1}, {0x000c339094f215d4,0x0003e535f42c17eb,0x000b753210a29b6e,0x000ef35e39a7a591,0x0002d459b91ab7f1,0x000fd429da2789ae,0x000f57eadbca7f02,0x0000000000065290}}, {{0x000ffd02d3a50b87,0x00027c085500177e,0x00023ee786608759,0x0001d964318e861c,0x000604fe9b85dda7,0x0005e7e2001d3d39,0x00081cda4bc065e2,0x00000000000e076c}, {0x000171ac92e482e8,0x000095b9f82189f0,0x000cf8881039863b,0x00083e4d8dd159bf,0x000720b18043f526,0x000a0d8f5ca9c888,0x0005c473c040fa08,0x0000000000017952}}, {{0x00023e634e793b49,0x0000c37ed2be4ce8,0x000e92823d3628c0,0x000ad8ae77c2f00c,0x000a44de16a8b061,0x000e490ffe87e1a9,0x0003eddf4f57c87e,0x0000000000000599}, {0x00036b9f1b67eda0,0x00020e1036387a16,0x000cdc81b1b14889,0x00020d15ab42f920,0x000dac0ff03359cb,0x000c1e7f4a738a18,0x0006e0da501a2e2a,0x0000000000084d8a}}, {{0x0000efaf35b1418f,0x000173a8289046f2,0x0004fa8840c897aa,0x000898ae5fa19d2f,0x00065e1c5fa4c574,0x000390fc20b13dbb,0x000187f11343ba7c,0x00000000000d7d32}, {0x000b8b2ed2cc734d,0x00011c92cb1bab11,0x000e6307a3aa4fd9,0x000dfe5672f2af7d,0x000430932441da69,0x000af02d69c62d7b,0x000c22165672ad94,0x00000000000cde81}}, {{0x0006bff8295a2913,0x000d91d27efcde72,0x000bdb7b59692a46,0x000fb83caa26d18c,0x0003b82babbe99a3,0x00083dd60d27e613,0x000cb861030dfdd7,0x0000000000073c78}, {0x000a3caf05842de3,0x0002d8707a2cf633,0x000f47297bf43775,0x000d412a2b176b8c,0x000fc72021017c3f,0x000a6d536d5b52e2,0x000ec024a63030f0,0x0000000000004648}}, {{0x00024dd131928645,0x00063d45e3501026,0x000cd2a97f7d8b99,0x000a088e302483ae,0x00082c2485c01532,0x0009cdbe63475e8b,0x00073808f9ea5696,0x00000000000253cd}, {0x0002a544f2d5917a,0x000581cf323a3b9c,0x00023a0e49f58c76,0x000e84fc06f3d0ad,0x000e39efe6d99a31,0x000ac4decd326b86,0x00058277e3e1df14,0x00000000000f3e0c}}, {{0x000611e8121168e1,0x0008967477cdc1e4,0x0003ef00563660fb,0x00060b9917eec666,0x0004d66c5c1d31fd,0x0009508baacd95bd,0x0002432e0551f3bf,0x00000000000688cb}, {0x000033e51fe09e4b,0x000448c039740256,0x0004cddb41207f6c,0x00025e144db62afe,0x000bc4a030da1918,0x0000815043ee8aca,0x000cd08ab154a894,0x00000000000486c9}}, {{0x0009bbd8fc757c25,0x00003e92b56bf065,0x0003d138d6f390b1,0x000d0ef50f5c483a,0x000611fa89fe7754,0x0004ea7d8850a9ef,0x000a2e97d74b1bba,0x00000000000aab7b}, {0x00042e268ab251b7,0x000af06f30ab067f,0x000bbd0bcb9d997c,0x0000bca7a2e053e3,0x0008dcf0e14c4758,0x000f553108579559,0x000e18c3596781d6,0x000000000004c9b7}}, }, {/* digit=31 [{1,2,3,..,}]*([2^124]*G) */ {{0x00056db726934b05,0x000d28db8b78ca20,0x000efbe1df76bc8b,0x0000f022dde2e3c8,0x00038cbf406c67e5,0x000f7ff602e2461f,0x00068832182781e1,0x00000000000e30e2}, {0x00008c8748c4086f,0x0000895adc204b38,0x00054339345edf7d,0x000f060b73417379,0x000fd128d46cd5ca,0x000fc1e04ed93187,0x0000a13f2819cb20,0x000000000002b7f7}}, {{0x000424a4cdc9ef0a,0x0009fd74d09c0410,0x000c23c8eb2570ac,0x000cfdce132b9412,0x000c843d3c66db1c,0x000cb3ef4a0e5309,0x0001771fbd03a5f9,0x0000000000000ea5}, {0x0001bb0b6df68f60,0x000fa1ebf5a155d8,0x00046a120ff8039f,0x000c37aa0d34d161,0x00050fca43af3256,0x000841bdeee40efa,0x000a0bc299bbd4b9,0x000000000003bef4}}, {{0x0001fdb0e87d4c69,0x0008f5bbf8bfdcec,0x0002c8b1b68f641d,0x000718bfd3fb74be,0x00015a085196abd2,0x000dba2ea03c0150,0x0008bc147474dc4d,0x00000000000eaa2c}, {0x000a67e6cbd2f408,0x000e9bc3dc5c2f94,0x00045e933f00eed5,0x000e98325d341410,0x000406fcbc8e0276,0x00024ebab9372694,0x00050b8c4b7f2ca3,0x000000000007dc3a}}, {{0x000547a274927d68,0x00075e01295fd654,0x0003c43252dc8b6c,0x000689f9eaf8eb82,0x0005c622acc52ec9,0x000757f2a327b96c,0x00006eae918f81b2,0x000000000004fd66}, {0x000f52e65907ef2f,0x000a109bb7fcdbf4,0x0007ab72ec41ee7a,0x0006f125fb475125,0x00018e399520df2a,0x000b1c3a2be88faa,0x00081f0166d57e3f,0x00000000000e525f}}, {{0x0005132af5b85725,0x0006e0c64cec623a,0x000d73b377e49971,0x00043ae5a8027b17,0x0007d0a7406ac27a,0x0002bfeed1c5729c,0x000357445fc7d34e,0x00000000000809bc}, {0x000fe2c3577b04e1,0x000a30598626b6a7,0x00059236250da683,0x0009b314294839a7,0x00093ab9bc662151,0x000ab597466282da,0x00012e84c422c25c,0x0000000000071c0f}}, {{0x00044dd5af953087,0x000b3f24fab9aa7e,0x0007e53a0eea7298,0x00070e733ac4fb68,0x0002c8a6976575e3,0x00030aa0ed8d6164,0x000637f057f10a5e,0x000000000004f1e8}, {0x000514c4bb67bcdc,0x0005e887f06b2b4b,0x00032e66a34587bd,0x000f7eb6e6483a19,0x000f475d4bfd4319,0x000811fc744f1aaf,0x000f8ba8ee73b50f,0x0000000000082916}}, {{0x000b0ecbb3371c13,0x0009596495c1e57a,0x0002216cb93b15bb,0x000c858fe6e84ffb,0x000b0b189be26806,0x00058a7685c215e8,0x000202ac61577e80,0x0000000000088e0d}, {0x0004f2a99a53c49a,0x000de70322e164ce,0x000973bc42c42efc,0x0001f014d701ab8e,0x0004a61df25f8863,0x000f6dbeb889f10d,0x000168affec5a9bb,0x00000000000934ee}}, {{0x0006f789ccd0fed7,0x0003cdefe3a7abd6,0x000569da64526056,0x000c26a73d1f9b54,0x0008237ae8b77366,0x00047825935d5d71,0x000ee33efb20feb4,0x00000000000aa545}, {0x000d70972e2560bb,0x00081750edd05bef,0x000da581b51c4635,0x0000f370a9e29dc7,0x0006bfbec7f616e6,0x00047e1439cf0a13,0x0001a9b430a34b2e,0x00000000000c6cdd}}, }, {/* digit=32 [{1,2,3,..,}]*([2^128]*G) */ {{0x00056f0266d7e788,0x00065f186d6bc61b,0x000e03ac4fb95d1d,0x000432edfe64dc3e,0x0002d795ea57c9e7,0x00045af2bd9fc483,0x000517f4ffdb81c8,0x000000000002b670}, {0x0004d8950582c931,0x0007aa7c1be04d23,0x00045b4daadb356b,0x0008aba03f2ef6dc,0x000420dc701d62ff,0x000f1011960ecaac,0x000fd09f4b559f4f,0x000000000003cd54}}, {{0x000973c51356e0d2,0x000aa31954a56667,0x00047c018911cdb5,0x0003ec5e37ef1d2d,0x000575bc3b668c43,0x0009cd98bcd0f203,0x0002a33723f14524,0x00000000000ea3b4}, {0x000998df93db2ed6,0x0000ff607fee05d9,0x0005662b349502ed,0x0005d74cea5417fc,0x000a10fca22bd47b,0x000635e8b6891940,0x000fef5cea41332b,0x00000000000b5934}}, {{0x0000bd5aa7cff3d9,0x0003c365a4a426e6,0x00069eea0aae5d6c,0x000c8b4b7205a704,0x000357df815ca330,0x000a926744858eab,0x0005d76e522afaf1,0x00000000000f4136}, {0x0001a59021cca096,0x0002a00dd3461384,0x0008629f956ac671,0x000103f7c082301c,0x00076b092b71f427,0x000037a3314a2a18,0x000e14210f632130,0x0000000000039340}}, {{0x00025fc00f86f9f5,0x000b5b1f4fead323,0x000e624d9ef69f8a,0x0007efe2e28aa2a7,0x0009b3151d6748b4,0x0006a346070dad2e,0x000af787a8178b43,0x00000000000801f7}, {0x000701583b4bfabc,0x00034fab462e36e3,0x000ddd2177064fe4,0x0006b3fe66812831,0x000a6a3fdc1db469,0x000e37dac3bd9910,0x000fb34409128449,0x00000000000cf605}}, {{0x00081f556f82acd9,0x0006f59470e4953f,0x000963a40f813b02,0x0003c1e0fb30ecd3,0x0003b62892f14761,0x000eefa161fbeffa,0x000719ddfeef49f8,0x00000000000daeff}, {0x0004929822ef7d6f,0x000dcff1872cd89c,0x0009edd2dba5c5c9,0x0003a387695218a2,0x000720802b8852a6,0x000f4a473a0d413a,0x000a4a233f1f3118,0x00000000000c9d7d}}, {{0x0006ae71b9b2b784,0x000ca86737912907,0x000e250552a02dec,0x000185ee92c712de,0x0006c201e3272efe,0x000f6b0788b908f8,0x000bf33ab5528894,0x00000000000ce0a5}, {0x000abf1c0844ab25,0x000185eab37ac7f5,0x000c6bca8c37680c,0x000edff304f1cf97,0x0008f6fd3e90f3a3,0x00016e5ed8992ecd,0x0005c4ff24d7c69f,0x00000000000def9a}}, {{0x00054a31e739d50e,0x0001e2edaaaa9c57,0x000574cc3b6825a1,0x000fc42bcb161908,0x00046709d8513542,0x000af4ce06c04ec2,0x000e2e5fe9768ea9,0x00000000000eb6eb}, {0x0005126ebc807472,0x000c87b7da4abcae,0x000d07139021766d,0x0001c51fd563c816,0x000926c775e17f69,0x000b58889ea990d6,0x000c2c2cd96f1321,0x000000000000f1aa}}, {{0x000e697116bc35a7,0x0002057edf71ec8d,0x00063f77e7793641,0x000ba1aa6934160d,0x000c5e639a54b37a,0x000bce957d45b3d2,0x0007f362c6b9ad70,0x000000000005d7e8}, {0x000a8127f71a285b,0x00017b02169816f9,0x000c7a7939056bf2,0x000692b478e4b92a,0x0009be3fe25a15aa,0x000bdd4a8dd67cf2,0x00027af1ef75b006,0x0000000000041df6}}, }, {/* digit=33 [{1,2,3,..,}]*([2^132]*G) */ {{0x000455d88f7fc60e,0x00091a58a27c4fad,0x000ee65aa7e47d3c,0x000826600079a263,0x000f2606caf52431,0x000cb28c8113f6fc,0x000aa6f6ff2be316,0x000000000003c17c}, {0x000c05f668a9dc76,0x000798ea577e0148,0x000c912137590c65,0x000eff4592a57ef2,0x000c5e3f67b24b28,0x00000890276e1f87,0x000b7e40d7a676fb,0x000000000004b6e6}}, {{0x0007f95d338f5fb6,0x0000076e27519dec,0x000fefb9477deeec,0x0002dfb71fba6625,0x00085e0886af5832,0x000ee544c228aec0,0x0006398d83b6276a,0x00000000000e29f9}, {0x0004808391599977,0x0006d1ba4cfe02e0,0x0000441e3d4b3e92,0x000ed58cee95d92c,0x000abe5355407e0e,0x000a9a1f42d29282,0x000c82866638b607,0x000000000006ab8d}}, {{0x000c43ee7094e067,0x0000b599ece9688c,0x00025bcbe937baac,0x0005ba86373ccef5,0x0003c64f72612afc,0x0004ce1abe455683,0x000a77f29ad54041,0x000000000003ee82}, {0x000e0b1548890be5,0x00094fa26eaa0940,0x000c96b0a3e57442,0x000ade54e1c94bd7,0x000e20b0ddbe9570,0x0006eff6ff4a86d8,0x0007a4967ab653dc,0x00000000000e8bab}}, {{0x000de87dcf2f3d8e,0x00056a16c79cee01,0x000db47cfbc9e301,0x0006aa0c2f47e69c,0x000f2c9b4914b8bd,0x0007242a8277d590,0x000512b6d1c81009,0x0000000000045f75}, {0x00044d25d22dbf16,0x000f02176162aa27,0x0001167bcefd598c,0x000c0d1a503aee8c,0x00057af4dd78fcf8,0x000b43be45d1f94a,0x00071b8f0bc1a62a,0x00000000000ba9e0}}, {{0x000adf4d6bef5a3d,0x000a19a2dc376622,0x000b08bb2e394780,0x000e5cf7c0765207,0x000c4063c3538e70,0x000baec46c0dbb4a,0x0001ad3f4550566a,0x00000000000f9356}, {0x000e15a92e3f32ae,0x00055d0bc6d91fc6,0x00092d1d7bd54520,0x00033424b80c021f,0x0007af5e458c62a7,0x000bfde586e1d546,0x00052c6922574f70,0x00000000000d19f0}}, {{0x00077ca19b6937db,0x000c3bf87f30d9c2,0x000f3d29bdf61e62,0x00032bd50ec0ba46,0x000ae60d1e72d5fd,0x0004ff2d37de8fe0,0x0007e452d77fe0e1,0x0000000000055ca4}, {0x000fd784e6c9781f,0x0000339e3d19e6d1,0x00045fa26fa441a0,0x0000c7afe92c6d07,0x000869a829043bd7,0x0006d1d9ea3fbc06,0x00024be263f00ed9,0x0000000000075c0c}}, {{0x0002619f4e7dcc16,0x00090a1d1a8f0893,0x000f4151f0e91898,0x000c39b84ee41fc5,0x0002e4a019099db2,0x000a66c12ad292a0,0x0000f6ee6b26ddfc,0x00000000000f04f7}, {0x000e18e3a8161ac5,0x0007f01e66788b92,0x00099db080ad62ab,0x000e4542595d5a6c,0x000bdce965cc3e7c,0x000ec7931f894a64,0x0005be12e46952d9,0x00000000000fb65b}}, {{0x000d91fc53fa82b7,0x0007d705bfe3760e,0x0006eb6118c41a96,0x00077a9bc4567977,0x000617081a2f811e,0x000e1640e4f52c4e,0x0001d787405d819f,0x0000000000070771}, {0x00085581b6dc5925,0x00062dc6fff82580,0x000af03b55b43c90,0x00066bea9cf3eae3,0x000e87139b8b0ecb,0x00042b4d77418372,0x00032e6aaccf295e,0x0000000000031fc9}}, }, {/* digit=34 [{1,2,3,..,}]*([2^136]*G) */ {{0x000f65dda78f831c,0x00073fa3b4c8e10f,0x0006b8117d5cb12e,0x00039562e8c4d8cc,0x0005cf89935b06aa,0x000fa071e4981c3e,0x0003bebdbd0c4745,0x0000000000049607}, {0x00004bb91c157448,0x0007009a7298688d,0x000867eb798cb22b,0x000b5b3988f2781c,0x000d73b1719d9a64,0x000d2e8076ac9440,0x00042b58ad54c7e3,0x000000000008f067}}, {{0x000489635dd868b5,0x000ef339521774bb,0x0001f606d4b5774d,0x000d61e0a285bd5e,0x000e71171b1c1084,0x0009b29f93935a84,0x0009bd8ac2433cf2,0x000000000006dd1e}, {0x000f576ac5f0cc26,0x000f788da0477c71,0x0007313f812b64cc,0x000a25f9d5b19e1d,0x000b6a27fa79a792,0x000a16a8e9ee015c,0x000e67ea3bf8b57b,0x00000000000c15fd}}, {{0x000f3b091fcd53e3,0x000c537f50e43695,0x00003782e79d52fb,0x000af85e1d111511,0x000f6785ae1c3916,0x0006ada8cf56e852,0x0005b2bf8c72adae,0x00000000000e1328}, {0x000cbe0d0bda153b,0x000e35327920cb17,0x000e7daa3650306d,0x00028573caf37928,0x000b550ffe1ca713,0x0005d4e4fb15ab34,0x000f9d818980666a,0x000000000002f854}}, {{0x0005d9265089916f,0x000013b623150146,0x0007ede4f0fb2f49,0x000c31c56471100e,0x000b1bae8d2a4bc2,0x000f1f76a4a0e73b,0x0006cabfc0770a8d,0x00000000000a7bb1}, {0x00039cb13d9c4b7d,0x000f42afe5b1cb58,0x0008a2ce9b2dade4,0x000a333a1af2a824,0x0005dafed6cd97ca,0x000c3b2e393cb92c,0x00095609553e7e92,0x0000000000061af2}}, {{0x000ea55edca2a058,0x0003f5559dd3109c,0x000f7ba60d37c6c8,0x0000fabcaf57d0dc,0x000578742ab60d84,0x0009c1c8e9625866,0x000167c85482ad40,0x00000000000adaa6}, {0x000208d39ae67d2a,0x000dcec26ad9971a,0x00067a35ccc54689,0x000a7fc2539986bb,0x0006a23dee41340a,0x0001a9837d767487,0x000da9a948a9292e,0x0000000000071438}}, {{0x000778a60c6bd7ad,0x0007f39038863eb8,0x000e85efa03ef35f,0x000682ef3d8310f4,0x0008f412315338aa,0x00026310bb52d41e,0x0006924fbef3dd70,0x00000000000f6ff5}, {0x000ba50eddf2b7fe,0x000b63831c6b1cbc,0x0003bc6684c6c5e0,0x0006abc6516bba59,0x0005446d35a876d2,0x00012a8d0c237f9a,0x00015bb2b16c0ff0,0x000000000000ee03}}, {{0x00014182dba86bd2,0x0009c817d77b02b0,0x0006420950654aca,0x0004107da68b7691,0x000dbebc4c4dd3ac,0x0003d39e96904bcd,0x000950b0d2103ca5,0x0000000000030a5e}, {0x00028ff31a9f909b,0x000c7b092568034b,0x000262a60542e8eb,0x000ab34c15855ae5,0x00063017194f2389,0x00046b838c14dfd9,0x0006fc420e071911,0x000000000008fb4b}}, {{0x0009c78614d38ab4,0x000d813722ab0651,0x00088626a03970e0,0x000f467f76fdaf74,0x000912ddfd9ad3d0,0x000bdefd37ce072f,0x000315ce918a5747,0x00000000000750e5}, {0x000fa00e65975639,0x000cd08bbb20dcda,0x000822e7b86b49be,0x0005c21ca865ba6a,0x00002e6e8e6fc8fb,0x000608b60ee6e41e,0x0005cdd00ae6214c,0x000000000006ff68}}, }, {/* digit=35 [{1,2,3,..,}]*([2^140]*G) */ {{0x000cd00e20fc1fe8,0x0002bbbccce39826,0x0009c6cbc7ade77c,0x00035a5d2252fdaf,0x000954e7dd499eae,0x0005100fda8f4f20,0x000727a56d72a629,0x0000000000056767}, {0x000898f026420cbb,0x000adbf60b247e57,0x000b35db15577b1e,0x0007ad4b93dab9cc,0x000022d71f39c2a6,0x000304db218cd0ed,0x00082104380c425f,0x000000000006729c}}, {{0x0000345995afd46f,0x0009dca07923b790,0x000129149d2f3565,0x00079e83cb025114,0x0005beb383ef41e3,0x00076dd0dfabac00,0x00012724d12d9a10,0x00000000000b208f}, {0x000d58cd6475c579,0x000359cc38a604c8,0x000857e410d47fbc,0x00060d98ac219eff,0x000faf284c806f63,0x0009e366a1edaab3,0x0007269c3b528101,0x00000000000bc9e9}}, {{0x000a386526319283,0x0008d26bd07d697c,0x0006e6a9c305333a,0x000c5466798b96c3,0x00081d3f3859d831,0x0001b9ec71d6b410,0x0001a9501d38ec99,0x00000000000d7843}, {0x0008f62f7d623e0d,0x000dd8b85baf6942,0x0003f90bead64135,0x000c1107acdcf58c,0x000c848d5842efc7,0x000c7fdacd9af415,0x00019b6b5a06bc0a,0x00000000000a3443}}, {{0x000517cc17c08a8e,0x000a28410d82975c,0x0000ae8bc362b8a4,0x0000d0d18c253486,0x00007eb035a3ae46,0x0001144145d0279a,0x000f7987e7c1289a,0x00000000000c0744}, {0x000ccad1ad801112,0x00072b7b2b4f054d,0x0007f502703051c0,0x0007395b51ee6864,0x000bf6122422124a,0x000f1a7fff2937c4,0x00032eb4ec133207,0x00000000000f8860}}, {{0x000daf15d19f8632,0x000794c0d78053af,0x000ade8ac0a0ca73,0x000c453e4b57e236,0x0005f4172b285217,0x000f999f8b4669e3,0x000d41509a3cd049,0x0000000000087c69}, {0x000ec5ba18211916,0x00032e14d01e8346,0x000c499a14031eb7,0x000bff270dc2bf04,0x000bc01864000e17,0x000a4dd3446560b7,0x000d06e28c7b9c49,0x000000000000f325}}, {{0x000161555383d319,0x000d0dd4eb3d0283,0x000dca801a8bb250,0x000285ddc1973c7e,0x000aa0046b981200,0x00019a7fcfd342be,0x000fe5d191734912,0x00000000000b7caf}, {0x000a5ee9f805422f,0x00057ea5a0c4d360,0x0004c8206c9d4abd,0x00016dc6046eeeb1,0x000ecc8e64b15b2a,0x0007fadda1755e1f,0x000ec251e4946e9e,0x00000000000fcbf4}}, {{0x00024bd4d62de244,0x0001d46d7088801b,0x0002ae4b99b01f02,0x0008fca4fbea2725,0x0005bd80a9dfe494,0x000871c717d6c776,0x0005701b470ea6f3,0x000000000008330a}, {0x0004db08d904e89f,0x0009bdaecddc0ed5,0x000f26cdb2e08463,0x000cd84caeeef145,0x000fc685a35656c7,0x000d93ddcc60c910,0x000895e68bc5c59d,0x00000000000feb64}}, {{0x0001bb5474d7445b,0x0008af877e8c6483,0x000948d44b23fa45,0x000269f2b004cfe9,0x000795450f8b19ff,0x000a7d4588adc5d7,0x000fdc688ce8bce2,0x0000000000097bd7}, {0x00043a2684d27187,0x0007c1b9f4ad5bd1,0x000b255e8d74e0bd,0x0001f7e71d83d86e,0x000d25ffc219abee,0x00073f553e693c76,0x000a551c9a84afc8,0x0000000000066d77}}, }, {/* digit=36 [{1,2,3,..,}]*([2^144]*G) */ {{0x000e4a9a609d4f93,0x000f05584cbb3289,0x0002a9b59e61225b,0x000d8267df2d43de,0x00000109e8014126,0x000172f1cdd5bbbf,0x0000d985b92ee338,0x00000000000f3143}, {0x000ac2d50dd03701,0x000b11e059a07dd0,0x000eb68a6d1ce296,0x0000751560f20e77,0x000e7aaf3a9ad622,0x000bae14ea59489a,0x0002497b70e2f664,0x0000000000076d08}}, {{0x0001e7720f69ad57,0x0004baff47822226,0x00011f4e0e8fa5c8,0x0005f8d2ef696aa0,0x000b4fa94fcabeb8,0x000d41a438ce5baa,0x0007720a32f96200,0x0000000000074f6e}, {0x0005b3ae79f59da9,0x000a8be0221aef2d,0x0005793443a4452f,0x00085d6a7e49f3a4,0x0009cb5d3c6378ff,0x000eb65f56300658,0x000bdfe8e4383596,0x00000000000ff8ad}}, {{0x000ec83ab52a5d83,0x0006cf6fd26cb934,0x000ee1af72ab19a2,0x000788be372817f8,0x000ae8c90c31694a,0x000aa0ce585f3dc1,0x0002238c90c6bf15,0x00000000000f01bb}, {0x00043ef688d7f41f,0x00075bdae01dd56c,0x000cf79ad5ecb5f0,0x000ff4ec2548f251,0x0008d12802a750dd,0x0004d924054a4986,0x000d1acd922fb640,0x00000000000957f6}}, {{0x0006a17488184bb0,0x0004d082ea61c88d,0x0004b5a68e9c5821,0x000df962e54f5d00,0x0006e39dc6ab7d33,0x000179b13340b0d3,0x00088cd97a8b848d,0x00000000000288d3}, {0x000bcf17110adf56,0x000462237e507d00,0x000fa28fb932260c,0x0008bcb42be74594,0x0004de2176b6645f,0x000e2f09cce2b0f5,0x000001af570a09d1,0x0000000000057fdc}}, {{0x00009414087acee6,0x000fc7dd81467f3f,0x0007997c546fe735,0x0004e832d2e9fbfb,0x00061c9d9c7ca2ae,0x000f27f140f127f6,0x00029ef06c5a57e6,0x000000000001f303}, {0x000b431a1206d910,0x00037a1b2b82f82b,0x0007312610c2e220,0x000cb8b039f12bbb,0x000902b92d6b1cf0,0x000f649e606ce433,0x0006eccb5e826869,0x00000000000e9309}}, {{0x000f672480aedb22,0x000c79d21c740037,0x0001a34fe6cb5f73,0x000b1a3aae5d701b,0x000891978d1557f8,0x000b85b1e477e4f8,0x000fb42913ffb40f,0x0000000000058489}, {0x00047efe2cde596c,0x000a60e1ab266dc3,0x00073cc3adaf7198,0x000ccb657ab8d871,0x0006547f64bdf578,0x0003e497e339fd79,0x000706904693943f,0x000000000001d864}}, {{0x0009da8454e1979d,0x00030da92e482d7a,0x000b666249139a91,0x000ebb3639c78714,0x0009d77aac3c8763,0x0002769a43bf7177,0x000eda92a5420d3f,0x00000000000d092e}, {0x000352bd3a0254a9,0x000b5d7bd8d8f8e8,0x0009446f6266c164,0x000fa3ed6b0cf872,0x00040490a771a5ea,0x000ff37225255afc,0x000cdbd40bb0fd15,0x0000000000079294}}, {{0x0005908307814aa6,0x00009158bfe27b53,0x000df35ce707d624,0x000153b8e71aca19,0x000171b11643f07b,0x0004e2f905e67698,0x00010977b7dd7dd0,0x00000000000f0dcf}, {0x000bd23edf0138e0,0x00071d3bab2a41f1,0x000facf3129d6b1f,0x00099afc6f53cda2,0x000f628039e454fe,0x00083aa16071f2a4,0x0006f9f1f44181b1,0x000000000005010f}}, }, {/* digit=37 [{1,2,3,..,}]*([2^148]*G) */ {{0x000b28d4d03ca18c,0x000a0b1e36500cc3,0x000e44ebafd13e2f,0x0001d2ca4bfdcedc,0x000fb29cdcfebf45,0x000514871d210892,0x0001e35b12bcd894,0x000000000001809b}, {0x000c86d0fbcc5e1a,0x000ce09b243105c8,0x00037f6b6be14182,0x000a16b5de334b63,0x00020b116076cef0,0x000ae2bf4fe0bd1e,0x00093754e4b48289,0x0000000000068c8a}}, {{0x0007e2c503fdc14e,0x00049309b1eb33af,0x000b5e3acfac1d05,0x000b81ebf8a894ca,0x000e0d29329387c2,0x000bf371427a40bc,0x0008957f4c315be4,0x0000000000001236}, {0x0002d22bfd1d81d3,0x000f4319c88f7e2d,0x000189361ce75d22,0x000a05df0dd13811,0x00024acba9fafcc2,0x00027313ec8d55b0,0x00094a871358de59,0x0000000000017ce2}}, {{0x0002c99cf8ff48b8,0x0002410777188c8a,0x00068c821fc35883,0x000b515120380e77,0x000fe13577d1261a,0x000862db1453c858,0x000e1cb1f6bb58f3,0x00000000000b9529}, {0x000338bb0bed7b45,0x0008003f63a416f7,0x00081208dbc793e6,0x000048b756e5af2e,0x00031c984bef8423,0x000a00f3e4d978ed,0x0009e7a06242995b,0x000000000004f4d1}}, {{0x000e08308825a639,0x000e8d3797831773,0x000f79843c567224,0x000a6a611a4e33a2,0x00005328043a2ff7,0x000e9f7dd904f86f,0x000904e29d31c012,0x00000000000c0a51}, {0x0002dae695c951e1,0x00024070c2696563,0x00060638255bc0fb,0x0000d0c12c8a1f65,0x0001ab352a835b97,0x0005eb0c7572aaaa,0x00059963df45a90c,0x00000000000d4977}}, {{0x000fe53cf0bc7d5d,0x00073e35daffd3d8,0x00005ab0f149d24a,0x0005a40f009a48b1,0x000d308a81c693f0,0x000885426a4a801f,0x000f0575e5dc467e,0x000000000004629f}, {0x000c6c457ceba67d,0x000c6356b879b5ee,0x00084a5c7d7e4e3e,0x000856eec2dd55b5,0x000880f0c80411c9,0x00001b21720f0443,0x0007b8c0b5e3e218,0x000000000006ea09}}, {{0x00042a359a9c02d9,0x0006601c2df8ca11,0x0001ea46897d0b3b,0x000341c8360fa6b2,0x0002c52bb2d6e198,0x0002efba5e67f809,0x00032af944dc63a0,0x000000000002c123}, {0x000d5d58228e0e7d,0x000b239684f6c863,0x000f4f910b494aa3,0x0008eb646594725d,0x0005793c32ddb7fb,0x000f94b55bb4f5f0,0x0002773ef3c33845,0x0000000000009eac}}, {{0x000bc0df5aa0ebff,0x00046efd26dca17d,0x000d31eadaba6e9d,0x0008a89e1830a96b,0x00013e039a029f10,0x0006fbb3b7e8e368,0x0002f11747b3e925,0x00000000000abb3b}, {0x00023cb577b95e94,0x000e2cac5818c280,0x000b36c4a5c24e15,0x000fd4d7a5485367,0x0009aa3645074081,0x0001a5f81fe2d8e7,0x000db4e86ce00ea8,0x0000000000077a9b}}, {{0x000a3bf39d563e4f,0x000f02c5b0e421f4,0x000bae31a917643d,0x00085959aa907285,0x000af658699bace4,0x0003b18e632be886,0x000667ce75d6c6da,0x0000000000069caf}, {0x000af371b713c401,0x000f0c17c66ce4f4,0x0002f4e783050dba,0x0000041623db4f0b,0x0002c74762e1ceb8,0x00071c52fe75615b,0x0002ecade8a54386,0x00000000000cacaf}}, }, {/* digit=38 [{1,2,3,..,}]*([2^152]*G) */ {{0x000ea5d38989c046,0x000c5a933aaf71af,0x00084b51a5d47afc,0x000dff8854de4972,0x000b247bec1525a9,0x00061e58da8b31d9,0x000707468a25c846,0x00000000000786a0}, {0x000d126f8d197fbf,0x000be282db8ca2e4,0x0000d8a3ccd2e3a9,0x0000faaeaeda06f0,0x0009add94b47a2c4,0x0000690766963292,0x00092cc72354f6b0,0x000000000007878e}}, {{0x000456ff7fbc201b,0x00083854b0583e19,0x0005b9f9d05986b8,0x00093894c32fc71b,0x000c9ec8f90dec82,0x000c7b9c0882fad4,0x0005e52d39990dc6,0x00000000000d71a2}, {0x0003262dabc3b450,0x000866b852e64a5a,0x000281968ae95022,0x00011545857f0497,0x000c1ccb9bc83700,0x0002bb853746621f,0x0004ed97e44e6361,0x00000000000758da}}, {{0x000e66dca895aedb,0x0007e58775856e71,0x0003edbdf1471e8b,0x0002e3da62265d35,0x000672d98b0886a1,0x0001e9c858ec4278,0x0004ceb9da8016f6,0x0000000000080099}, {0x0007a34c46f751da,0x0004f63d0878c9c9,0x00077928ee65f2b7,0x0009e126a1c1efae,0x000eebd0497a780b,0x00065231eeed68d0,0x000127bfeee3d292,0x0000000000080e03}}, {{0x000369b381ff008e,0x00068d25f6507829,0x000435b503d33f46,0x000031108b9b08bf,0x000f3fe92e910b36,0x000189ddc16477af,0x00038f6e5f6cb103,0x00000000000c698a}, {0x000953f049518733,0x000e102a092187fe,0x000b4e74068daf16,0x0005eac8fd6b76cb,0x000611ef96b455a1,0x000e433b51e37ec3,0x0004c3d1b3b3fc30,0x0000000000051d17}}, {{0x000c3efd55e9f108,0x0004ee67813dd55d,0x000e8b95d557829a,0x0007b634c8cf1647,0x000fa3556b4674ea,0x000db03dff1bde0b,0x0006b45343f260c1,0x00000000000e0a1d}, {0x000557bdaa85b25c,0x000b5af56bed0543,0x0009694c640e2d2a,0x000c5892c72fa801,0x0006a49486e504e0,0x000f78943812e259,0x000431d5e0bddb2e,0x00000000000acdba}}, {{0x0005b2c1b41a7e30,0x000e8b6e95494a98,0x000e156b8fa7f1c3,0x00012ee2183ce113,0x0000cc01d1434741,0x000d0d25f4180ec4,0x00016ddc5f8f7b8d,0x00000000000974a6}, {0x00054a8b6ee62d01,0x00072b9a7f0a96a9,0x0007a0f1f81abc8f,0x0000b82bc5671a8c,0x00000466ffaf50eb,0x000fdc348fa58667,0x000299a75ff5aab9,0x000000000007f784}}, {{0x00064348b9a55592,0x0008f24b18ccf351,0x00046d73b67eefc8,0x000977c532d340c4,0x000191002448043a,0x000960397a2de526,0x00034e1e11027870,0x000000000000164e}, {0x00056330f30da4d6,0x00014cc5f57288f2,0x000974f0c19f8ace,0x00020963266aaedd,0x0002c3ccd59f3b15,0x000a6dd5dfaea30f,0x00035a1da2e1fbc9,0x00000000000ceda8}}, {{0x0007996f48325ebf,0x0004f7914213d709,0x000270acf84435ed,0x000e5a126a34238c,0x0000701ce8c76eda,0x000656e02e566bf5,0x000fbf3562e87555,0x00000000000b4e8e}, {0x0008d6657de7885e,0x0004a5f10a503e86,0x0006a10baa0b8f13,0x000fc25cc2f2e415,0x000caf5718c149d1,0x000d6b890e973bb1,0x000f129b8825dad2,0x00000000000e2f00}}, }, {/* digit=39 [{1,2,3,..,}]*([2^156]*G) */ {{0x0009cd8cd3edcb0c,0x00022e37211bdab0,0x000bfe0383f52218,0x0007e26a1b9f8b57,0x000d7d7f72d5fdcd,0x00049c9205641e45,0x0002a15377c1bec4,0x00000000000efc7b}, {0x0007344da1d40eaf,0x000b6c657a9ff3f7,0x000acc6777a25729,0x000d1bcd020eaa96,0x000a3f6860c76bfc,0x000c7c80617534b0,0x00056b8ce5722284,0x000000000002bd74}}, {{0x00070f4fca1b2907,0x000d2aed02b6a844,0x00048854f708389d,0x0006ec4654e7c314,0x0003e7034bfd8222,0x000d6b555008ac00,0x000d44e343c5407f,0x000000000001b429}, {0x0003fda90bb8f0f9,0x000bce0702a33908,0x0003c08ba27edf85,0x00072f6d46524015,0x000d35f600437e6d,0x0003e8cc4d92655e,0x000b40a0dbaac627,0x000000000003c3ff}}, {{0x00098d832fcb2cab,0x00078bc06ecab0e1,0x0004e7cd0ece1448,0x0006fa0453c94bf2,0x0003ed1a6731a6fc,0x000c3f1fb5460f94,0x000d4eeb11656a4e,0x00000000000ff1e7}, {0x000efd2eb43b2558,0x0009059526466dba,0x0007bc3cfc024713,0x000588824fd2ce63,0x00039f2c29257bdf,0x000e97f3013df0c8,0x0006411bf621e6de,0x00000000000ebea6}}, {{0x0003b015d907e90a,0x0004e5906a35b43f,0x000f32388b4d1260,0x000ac9136f847648,0x000bbe0f1dd365c8,0x000d26c21f73b3de,0x000ae740358868a2,0x0000000000076792}, {0x000fc16ec80c7bf1,0x0008d3ecea1669e7,0x000b1ce4e42f6130,0x00091090e0062443,0x0006dd94681b6db8,0x0005a3de2d29106e,0x0006ccb40b8694a8,0x00000000000936b8}}, {{0x000fa93eb46c6ed1,0x0009f28d33e792c1,0x000af8e666ab1b38,0x0009f3bce683c5c2,0x00098371fe755a74,0x000712c1d717629d,0x0001aa5e828fc057,0x000000000007e4c6}, {0x00082c4505e4cd17,0x000035d927bad55e,0x000bbbc997dd1436,0x00099a398591dc25,0x000a4836664c560a,0x000d79298c885fe8,0x0001d7d18acd4226,0x00000000000185df}}, {{0x000755a507c76d63,0x000c69d8a925b591,0x000ef5ac5d730610,0x000ca6ddfb534b8b,0x000c6dd78a324f53,0x000a146d54e64874,0x000201336e5b46c2,0x0000000000098395}, {0x0001a5ef82624226,0x0004ca4c095220d8,0x000ae0a7c3b4840e,0x0002f64c36286ed0,0x0003c3ebb08c0ff9,0x000f00c3057b1b90,0x00036ec6bdc9b665,0x000000000009a46d}}, {{0x000c3639d049078f,0x00048d67dc92ab51,0x000e52783edc1242,0x0009baa8b87c0b05,0x000052760ef4b6f0,0x00047bf855a8a903,0x000e742e2ae75610,0x0000000000085bd4}, {0x00097e1bd11078ed,0x00093ced11ff7661,0x000e3244d9aa20e1,0x00088ff24b3e912a,0x000a1afd219683d4,0x0000d21286e166fd,0x00039c66a912114f,0x0000000000005c9f}}, {{0x00070dd4c4f3a35e,0x0006d913f92069a9,0x000aaa1c8b2107ab,0x0004e2c787c35959,0x000fe7b7b7ddefab,0x000e28e6aa55d465,0x0007bc921aaad834,0x0000000000012d6a}, {0x000d81dd493823d1,0x00072109803c417d,0x00095b2d5e30421d,0x0008bdb99c5bb670,0x0006bc7c2da71a8c,0x000927eef1cd1c2b,0x00041050189c975f,0x00000000000229f9}}, }, {/* digit=40 [{1,2,3,..,}]*([2^160]*G) */ {{0x00086c2a1c05c1ca,0x000a911a8fde5d4c,0x0008768c091692e8,0x000c275c74dfe82d,0x000c38373a506818,0x000e5f88f2b0294a,0x00083a584c4061e8,0x0000000000073423}, {0x0003f61270e03ada,0x0002d263895b3203,0x00007b3b0d15f74f,0x00059da84da7f0d6,0x000a924a09f21443,0x0009ad83576e3095,0x0002af612986e3d6,0x0000000000039212}}, {{0x000c342a3198c068,0x0005d3ee0a31c35b,0x0003fc2cd3c80f60,0x0004f4ff0fbfa963,0x000efafea65a90a6,0x000f4b9f9513f054,0x000590796ba7479c,0x00000000000932a9}, {0x00037547e06b6b4e,0x0005d93af8a64743,0x000922627b827de1,0x00071e9c1a46c909,0x000f4c9bca7223bc,0x0008cea30000643a,0x000ec2b6d967c784,0x0000000000073312}}, {{0x000ecb2626cc0655,0x000eafeb707ee40d,0x0001edb8dca9d02f,0x00016459a0d32bae,0x000a1ffb926626de,0x000578b4a9a2ff38,0x0004434e5ad96d8f,0x00000000000883e7}, {0x00041045bc252635,0x0002d1d8eecaa72c,0x000edd696d444309,0x0002faed758ae41f,0x00004a85d867e49b,0x0008cba866a9a229,0x0009822fb89dcee6,0x000000000007f09a}}, {{0x0009f15eb1bbb5c7,0x000d952ec99556bc,0x00015795c8a4dc35,0x000337c6dcc7816c,0x0009791f7cf1e881,0x000885a42e4e7b6d,0x000e41faa717aa59,0x00000000000f9c01}, {0x000171c4ffe4a6bc,0x0000ccf208d57a05,0x00042714fd20944a,0x000871b264ce04b2,0x0006cd42026a7261,0x0009f99fe66be4a8,0x000e2bc5397b7782,0x0000000000024578}}, {{0x000b87e03bf622cc,0x0002fadc79436506,0x0000be1fdf9a8888,0x000aaa40406c1296,0x000c8b658d3cef9f,0x000435baff4e6388,0x000c997262beb41e,0x00000000000fdaea}, {0x000ba84e0b8f458e,0x00045d359f7d8428,0x00016b951ae31b5d,0x000f03229498ba51,0x000a85bf35adb18c,0x000aa4bc8c67388c,0x00027a8a7a6aa262,0x0000000000072f46}}, {{0x0001e4a772f0f152,0x000520733667a853,0x000ae90cf08b2488,0x0009b27a7bc26604,0x0008eb4f0c7a7ca2,0x000f276309fefa69,0x0001337b6f351301,0x00000000000fcfb1}, {0x00022648d86fc4cc,0x000979928d9cf841,0x0009da8838c5ffbb,0x0001acbe041bef47,0x000af8d998547fbd,0x0005a0dc57d25159,0x0009332ec3a7d8db,0x0000000000087e3e}}, {{0x00088fc716a5b4c1,0x000423fb812eeafe,0x000a6b9f65779527,0x00041838fbefbe46,0x0004a4b24a05e572,0x0000c0a432b7d49f,0x0001db23b138d071,0x00000000000a85ec}, {0x00095de9d8768d19,0x0006d7cc1f3d657e,0x000b6e219733e2a8,0x00023128f56981d2,0x000eb4080a011bda,0x000999b7f68663ea,0x00080c8dd7ba7e9f,0x00000000000b6865}}, {{0x000b2ea58bc5b2ba,0x00008ba8418f2c05,0x000ab2d74f8719f3,0x00038d7bce1e82e0,0x000eb397915b4e64,0x0004cf6599e489b3,0x000affa9baea9ffb,0x0000000000042ef4}, {0x0001f2cfd470aeb9,0x000eeae3fb532a9f,0x0001d5334d1ddf3c,0x0008e28defe047ca,0x0009d24e60fe8972,0x0000f710c63a8c67,0x000d3cadacbf9247,0x000000000005e198}}, }, {/* digit=41 [{1,2,3,..,}]*([2^164]*G) */ {{0x0008597cdef10944,0x000f4294d29542ec,0x00058a58394c4343,0x0007f9158f95038b,0x000164420c94fa1a,0x0003caea8b137981,0x0003402b686e1e09,0x00000000000f9e1c}, {0x00006da6276d2e4f,0x000cacd1beecf39b,0x000bd69a9fc92254,0x000c7192dfc2b165,0x000dcee7e854cecb,0x000635cc82cdb955,0x0007d39fefc321f2,0x000000000002936f}}, {{0x000f165eb19500c6,0x000f54962c020b57,0x000116eb855d7c76,0x0009a79dd189c401,0x000d6ce517a77854,0x000d6bb9747675cd,0x0000295102294e32,0x000000000006ed1a}, {0x000926ef8530f97d,0x000353efb54e82c3,0x0002eec5a292f22f,0x000c2948967fb050,0x0009be04e909955b,0x0001efad6373615c,0x00097af1fcf82011,0x000000000006fd2e}}, {{0x000445389cf3da63,0x0002b85e1e4ab383,0x0004d8f24163478b,0x0004da1a717e0356,0x00080f1bf3dfc0b8,0x000a6fd41f1a63b2,0x000cab47b74201ab,0x000000000003518f}, {0x000a17bf41f156b8,0x00031e12511fae1c,0x0005a421fc7a58f4,0x000fb10db5665c05,0x0003b99f4d5a20e0,0x000b7dbceb5448a3,0x000b87cb1847ad46,0x00000000000fdcad}}, {{0x00040c75d27c479b,0x000823f2b5bd3e20,0x000298ef45cbe8a6,0x000f2db94256fe1f,0x0009318ddb03532e,0x00024c8e1acbfc45,0x0003db2375f9fd5f,0x0000000000037078}, {0x0002335b7531e78b,0x000251bd461e7e12,0x000e223c32f4b08c,0x000777d8845f315e,0x000697fc92c7c9f8,0x00092954081aed29,0x000fe09f2f8d7949,0x00000000000ff5eb}}, {{0x0004fbb34790cc07,0x000a4397049f47ff,0x00000e7e84e96f9b,0x0005ec1e7862c0cf,0x000834350bf1ce6d,0x000ec8d7417a98db,0x000aa86ceccd8030,0x00000000000bcab4}, {0x00032ba3b5c44605,0x000c04378b1fdff3,0x0002189e90f61242,0x0000faa8d60f86df,0x000a3573271abddf,0x0008f8032987583d,0x0003f6b0afe4ec4b,0x00000000000b69d0}}, {{0x000f8df0532bb051,0x000c5bd9a66d6010,0x000c7470f77e12e7,0x00051dfef38e9b37,0x0005754fb3fba751,0x000069b72a3348ae,0x000faf1218fa8f13,0x000000000000835d}, {0x0007a4c220543f04,0x000c02121a98ebed,0x0005ec4ceabea5d8,0x000a4be1a1eb6eea,0x0002adeb3ae51b23,0x000ea2b45b5c48b9,0x0008eaeebd305ded,0x00000000000c3719}}, {{0x00055d2a529f419b,0x00062f73471b59c9,0x0003ecf010a8f9e8,0x000497dae082cef5,0x0005c3e563bc57cb,0x000125f95dfcbf2b,0x00001922149c0fd1,0x00000000000425bc}, {0x000c9ac134356e8b,0x0000e049476de7aa,0x0008c62ed440f124,0x000c62d1256424f6,0x000541bc66fa56c5,0x0006ada140a118ee,0x0008c50d8e9ff829,0x000000000000134f}}, {{0x000b2c8bea306a01,0x000b1d0960bd7257,0x0002ca4efc9832f7,0x000cc77a98509175,0x0001e5f81554975c,0x000cff2c8b41bd53,0x000be3bdf8ab57c8,0x00000000000f5822}, {0x000ad597c5610627,0x000ae1f0ac0e6f99,0x000855b71125b2a5,0x0008b82e3cc86ac3,0x000d2b2beaee22bd,0x0002617ffc43bde8,0x0000968168781e41,0x00000000000b7ee7}}, }, {/* digit=42 [{1,2,3,..,}]*([2^168]*G) */ {{0x000956a7f54f949d,0x00074086945790c5,0x000771ce236fcb82,0x000b0c6000575064,0x00080b09adeb2c04,0x00081474f468be6e,0x000cce2f3bf32b6f,0x00000000000a712c}, {0x000c24bf8b416a6b,0x0004c292cee41c19,0x0008e149d7276386,0x000a66156f47b2ac,0x0005840b5d1be54d,0x0006e8cf62ca7683,0x00053eb52adb6a8a,0x00000000000dade1}}, {{0x00026c98ae834331,0x000b365f7d2c0d6e,0x0004cfcca31f7dbe,0x000634c986436f32,0x000133356165e268,0x000c7957d6334d8d,0x000983f17164269e,0x00000000000b8093}, {0x0008676a1037657d,0x000d9edb1fe5cc2a,0x0001cd1de0787da3,0x0005f4da691b6657,0x0001e1e2727e746e,0x00027b0296117129,0x000197bb4aa8f16f,0x000000000007f42c}}, {{0x000a6e4b3ca52862,0x000cf2af8bdfa5a6,0x000675c2d00d6d96,0x000d5ced7046d2e5,0x0007d545fd33d57f,0x00061ffd75ea025f,0x000242e2ccb6f431,0x0000000000009406}, {0x000194e235777423,0x00019f3536d60805,0x0005fe57dd0b2a05,0x000b06a5cc554450,0x000f9a9e2a66fd15,0x0003dfd0261b0feb,0x00051fdc3c057665,0x000000000000a8ab}}, {{0x00014e15511a3745,0x00067fe19901abc4,0x0000c6f09a808e87,0x000012556c4ce5cb,0x0005938c89ab92fd,0x000a587b123172d6,0x000c50a71f8a33aa,0x00000000000b55c9}, {0x0009dec34d6b29ab,0x00056ec005f6a241,0x000b67510d45fff0,0x000d67f9e26361fb,0x000321389c2598a4,0x000ffbcee7f0a2b2,0x000888d158820795,0x000000000009f36a}}, {{0x00065f3227de5d3c,0x0001e5ffec1d7642,0x000dceb00d947f3b,0x000844c649c850b5,0x000610fa337dfbe3,0x00080773d450263e,0x00066c44f7c8f402,0x00000000000e8969}, {0x0009e0325576575b,0x000a42587f475435,0x0002c020daa3c5c5,0x0002f667071543b1,0x000e06577b749e90,0x0000bee1303398aa,0x000cec030926d691,0x00000000000ffa92}}, {{0x000298023770357c,0x000dae4ee3345cdf,0x000943bb20278bd9,0x000ca667ce118490,0x000dcb69c7ead817,0x000680afeda222cd,0x000ca874ac74709d,0x00000000000d9596}, {0x0002187a0dd3835c,0x00082dff57da7e9a,0x0006d7aa1a2ea94a,0x000ba28b7fbc1b01,0x000c13d4ed0f71c0,0x0003a2ef260faab1,0x000dff6fbe3567ea,0x000000000004e577}}, {{0x000b9f236346df15,0x000f89b758b50c99,0x00075b638b06df34,0x000b3c39ee88a784,0x0001105e1ec04669,0x00088ea133f36a67,0x000aadd0f30e5d9e,0x00000000000baecb}, {0x000d89dcc4fedb34,0x000d3ec65be650a4,0x00093dd7d659e073,0x0005d29942ce52c4,0x0007d3ce28d4f719,0x0007fc9041220187,0x00055e9c962aa1a9,0x0000000000065c5a}}, {{0x00095e9750ada30e,0x00094eccb421e7ff,0x000dfa5cb406ba75,0x000da9e05a53972f,0x00007bc99fead344,0x000f77bf53a8035e,0x00078ae0214485c0,0x00000000000e54df}, {0x00053ac771ed9aaf,0x00027def45af5dcd,0x00024afc33d18821,0x0007db1c337e0181,0x0006b84671d5a9b1,0x0007d696d026a4f6,0x00022a606142343b,0x0000000000081cfd}}, }, {/* digit=43 [{1,2,3,..,}]*([2^172]*G) */ {{0x000d2a53b2756567,0x000f3feb984b33c0,0x0004e95d9895327d,0x000f97e3ca0a9a03,0x000dacc000ac177e,0x00040f51a76d4796,0x000810bad0fa6eb1,0x0000000000006ebc}, {0x000c76db6b103c54,0x00004f89eb78f367,0x000ad3bb031162c2,0x0009cfbb25e9d1c3,0x000fb4e7aef3e2b2,0x00067e8459388ea8,0x0006d7ee606c12e2,0x000000000009f580}}, {{0x0008f59540514451,0x00028cf947c06046,0x00062665be2e4fbd,0x00015c05f1835ca3,0x0002d8c79d90d001,0x000b5f791df08415,0x0008cdc0c3a6846d,0x00000000000749b1}, {0x0000ce2ed12d25c3,0x000d8d314b7d4a22,0x000dfaf9b4508139,0x0005af06855a9438,0x000ee9d02ab997ed,0x00038a5d0ea84ae9,0x000eabb87e903432,0x00000000000650a0}}, {{0x000c8f034ea36274,0x00088357540ab419,0x0000f5e32c760e57,0x00073ac14d7fed37,0x000fd186ee3d33d2,0x000a7b1d9fef6b9f,0x000bc2a94c207101,0x0000000000050bc8}, {0x00013f9560f76983,0x000e5c68959c999a,0x000056367228b52b,0x000a4fce6861310f,0x0000c828330f7a73,0x000f74fdb19bcac9,0x0002f473e3b66f7e,0x0000000000052d8f}}, {{0x0008b2d06a3248b0,0x0008e58225208828,0x00095368e614a61f,0x000e45562fe86dbb,0x00082dc5b2f11224,0x000096555a8c8a47,0x0004528a957b8dc3,0x00000000000b1591}, {0x00063a60dfca11b8,0x000161e563c57eb9,0x00024a9e6e7bbb16,0x0002de99462e7a31,0x0001c2489214f8f6,0x00074639c6b3dfe9,0x0004b56c1d8fc421,0x00000000000ef88d}}, {{0x00071f1bee09bff3,0x0004a6eda384edeb,0x0001d457a27a9c42,0x000e6af10e01b58c,0x000ae1175185c441,0x0000dfcc6ac962bc,0x0001b472d34d676f,0x00000000000a9412}, {0x000f38c043747e7d,0x000ad77dea14649d,0x00065b52576e79ef,0x000c09dd5d17db20,0x000db45a6e94625a,0x0001f8caf579edea,0x000b8ea659282a84,0x00000000000c11a7}}, {{0x000f9bf364d3e9eb,0x000407d0850b3dae,0x000e31cf311bd53b,0x000f1f891cb75575,0x00089d3b6afe68ce,0x0003b46e427a6ba7,0x000059f220f9c1f8,0x00000000000f526e}, {0x0007512e159b9fa5,0x00094edf3cccac66,0x0003e3258b2c0e34,0x000d9e98cc78d3e7,0x000b5fa48469cc09,0x000686001391bc40,0x00073a22bcdcd522,0x000000000007c599}}, {{0x0002ae0971dbb084,0x000bd9de8555bad1,0x000c9834d42cb891,0x0000285de654b80c,0x0008802be80bf17f,0x000d823bf33998d8,0x0006b64095923d5a,0x00000000000e848f}, {0x000fcca2a1ce91f8,0x00015c6e95017db4,0x00048a3538b7e8ae,0x0001be7a70558759,0x0008441da4770c3f,0x00048d4c2b652671,0x0008deaba3b06f9c,0x00000000000086f1}}, {{0x000d473962fbc397,0x000b15a4a5ce3b56,0x0003f34c786123b8,0x000388e4efe9a313,0x000aef9d074bd459,0x000ab9cb03a45c11,0x000566f68ab50b93,0x00000000000ecd9a}, {0x0008303c4d104a42,0x000f0bfb79b7f7f4,0x000a0520b1df9755,0x000aa21877390f14,0x0005e314cfb54f31,0x0008eab122de0c64,0x0004f656d904f623,0x00000000000ccb4d}}, }, {/* digit=44 [{1,2,3,..,}]*([2^176]*G) */ {{0x0007aa3a213de299,0x000c93eb83a8707f,0x000eb1f52edb04b6,0x000c77a53abe4e9c,0x000ebb9feb8257b8,0x0006f922e0a14673,0x00026cc0a6cbf7f2,0x00000000000a32e5}, {0x000ec20f9c4de649,0x00049ca417e66df1,0x0009b8c741987bef,0x0000e7a62e135de2,0x000ea7ee82c72bae,0x000776c74962bdca,0x000feb573d7f6ae5,0x000000000006ffbe}}, {{0x000a70e677b6f831,0x000b9cbc0bb18f0d,0x00037297c3884bb7,0x000b350d38064428,0x000c397a7602f62c,0x000987d82e4d2f1c,0x0009faa54bd48e43,0x000000000004f0a1}, {0x000a1b4997cc48fa,0x00005fa0c9a44d6a,0x00012729fa8ce7f0,0x0002c5b9cbd8d343,0x000813d979568e24,0x000da55fa1671eb0,0x000ce5ccae388f40,0x00000000000f376d}}, {{0x000f917fe9a26ae0,0x0003ae54d92cd055,0x000e0e9599c7454d,0x0007fd2849f6143a,0x000dacd0202d7c90,0x00092d19abb11dd2,0x000677a4913a701d,0x00000000000cf610}, {0x000f3626f0aa0d9f,0x000a3fff1e1d462d,0x0009edea6495252f,0x000f33a92cabf724,0x000ce329d1adcafc,0x0009a0e4cd571e13,0x000f867626ad237a,0x00000000000130d7}}, {{0x000f8196d845d3e6,0x0002f8a89daef137,0x0004ece7e9ffa3ea,0x00023775b80bb4b5,0x0002a45b362648d9,0x0005bfe910a587c5,0x0007d7daff503cc7,0x00000000000116d0}, {0x000600a28d48ec00,0x000916b5a471517d,0x0001f4eebe019105,0x0006cfc595abf8dc,0x0009ed0391ce8f07,0x000fcabd3c9de4ce,0x0009edaaaad03ae1,0x0000000000087b19}}, {{0x000b51557a9fd4ff,0x00034b0641d0941f,0x00049c97e60548cf,0x0005b4b00d5ec6f7,0x00015569d89ad12a,0x000ac72089be1a11,0x000df19c0566deff,0x000000000007034e}, {0x00000817b5f1bb5e,0x000e5636aeb6adf8,0x0006c2164b0bbfac,0x000f898734e9d301,0x00095ccdc6bcf4e2,0x0008a4f28daf7421,0x0002c39d39249f60,0x000000000008820e}}, {{0x000d9387d2303055,0x000ac620248118e0,0x00080c838dc206ab,0x000eb38d7f033fdf,0x000232646d6f86b3,0x000dae596ee3226b,0x0008e58c4825f6f1,0x00000000000a5bcb}, {0x0000edaef1eabcc8,0x0006f904a53484a2,0x0007fa1deed27103,0x000329f21d45f8ad,0x000a06605546af6a,0x000a93d14f20ad88,0x000174cf7a0e9619,0x0000000000091c97}}, {{0x000ae272638371ad,0x0005559edd263abb,0x000509e662e63add,0x0000d304e7f07169,0x000119b88200bf4a,0x000da801e36fc0e4,0x0002c791db560240,0x000000000002c72c}, {0x0006387b3ebbf52c,0x0000dfe960c2596c,0x00093166fd89300b,0x00080febccc1576b,0x0005c3c88f475a64,0x0007bd8ec72f4e5e,0x00055e224e7e749a,0x0000000000076314}}, {{0x00073d61157ae785,0x000ab42c9fad4fc2,0x0000e5d3107f2d93,0x000c7fdb149854b8,0x00002fc359eb0cf4,0x000ec86034a7d900,0x000e149ff0c3ea29,0x000000000009b24e}, {0x000512a0eb94d71b,0x000e0638c80999de,0x000012d24a63feaf,0x000e0f8a07ea5482,0x0002aecdec3f2fb1,0x00074025b1e580d3,0x000164bbf895730f,0x00000000000dd529}}, }, {/* digit=45 [{1,2,3,..,}]*([2^180]*G) */ {{0x00051b4cfaf372e5,0x000b9fa2db519927,0x000d4edc529b8ffb,0x000af1d605917201,0x000e782a09939f88,0x000c710d31c5fea5,0x000365e0fb15884e,0x00000000000d32ce}, {0x00054592dfab29b3,0x000d7d9f896aa46a,0x000ce02cec631ef0,0x000992dca6e73436,0x000a6fd0c08b1b76,0x0000f5c2376338fc,0x00035bc3ea4c65a0,0x00000000000b316b}}, {{0x0001e6b975664a84,0x000aa14f962e38f4,0x000c4a3248d485a4,0x00011c079e777bf3,0x000b4657c31b2c0e,0x000494de3a1705ef,0x00071802688fd23c,0x00000000000412a8}, {0x000b58909626d6fa,0x00004878fc7ace41,0x000bfc58da0a4094,0x0003c4c704b70c17,0x00087323c0087c81,0x000089f1a98553da,0x0002914f63cec663,0x000000000009655d}}, {{0x000f1be887dbd011,0x0008384e5541ec05,0x0002bbc7edd0f227,0x0003ad69beaad3d1,0x0000f51c2714e0a4,0x000ea5b0c97dd182,0x0007caac2b4cb457,0x00000000000d1176}, {0x000327be0b446dbc,0x000e318ccf36cb48,0x000fe4f5fd270bff,0x000ce43d8d292a8d,0x0008d58c4ee79811,0x0005c65a772c5fc6,0x0006695bc0f0bed3,0x00000000000cbbf9}}, {{0x00002ac6c24f6061,0x0003810586ea68e3,0x0007603f1b64b158,0x000c4d7dfbfa352d,0x00021e1c2291a42f,0x00011760abf38c38,0x0004d746e40ef60e,0x00000000000dcb97}, {0x000c4f8f01f54098,0x000f1755b105ba56,0x0001f9ffa1baf4e7,0x000d0b00945db608,0x000cf2809e1ca630,0x0006c95c5a160ac9,0x00074f38fc1113dc,0x000000000005d525}}, {{0x0001da84872cc14a,0x0009a7eba3da615c,0x000558d3935c6438,0x0007d982b93d8b2c,0x000c7cad1f758c91,0x000ff150aca8fc6a,0x0007fa5f581f19a0,0x00000000000e0832}, {0x0005d538d28d5c50,0x00038c774f18716a,0x00051c30fd1c0854,0x0006e9b8ad72b112,0x000b917986cfce03,0x00025cf9b463f9eb,0x000feabe51632813,0x00000000000dd7e5}}, {{0x000710a35bbc6ad8,0x00005a4e9f29eaf6,0x000a92c5e19e2d59,0x00084e42993359de,0x000f224d5aa30e21,0x000132c484f96ce7,0x000f5f0862e2003a,0x000000000000f015}, {0x00066db2ab4fc1aa,0x0007cab9d51492bc,0x0009b538d3bdb7a7,0x000e671c1fd96e3a,0x000e71a703b24865,0x0002add107baf4db,0x000d3083dd6cf914,0x0000000000098461}}, {{0x000b2da1393d8e42,0x00051714c1d1ba41,0x000ef78ff03cd88b,0x000ea3a6951ac80b,0x0000ac00c8377f23,0x00024cc1b5c59929,0x00062bf6efa2b3bf,0x000000000001e844}, {0x0006a668e721edeb,0x000069bda627d119,0x000d91ed1a995ffb,0x0007089c3b94ec3c,0x000e3031699ad1ee,0x0002b2453f75dba6,0x000ed48ff75f7924,0x00000000000289bf}}, {{0x000ac44be8741dd1,0x0002fcda68a7d811,0x000fb56aeb52d290,0x000e2dadce20b92a,0x000cfc69dca6483b,0x0004f98917de1601,0x000a564bec17aaac,0x000000000008d479}, {0x0009255137ea7d35,0x00025c623cb8d743,0x0009f513ea4e4bb1,0x000b7c030dcde621,0x00073a1733fdda9b,0x0002fac31f84ea32,0x000449d7afb6c3e8,0x00000000000d3897}}, }, {/* digit=46 [{1,2,3,..,}]*([2^184]*G) */ {{0x0006c80cb0000ec5,0x0007da189f30f16a,0x000d675bfc196669,0x0009ec37d8da76e8,0x0006c1ea7c10307c,0x0008c62d4b3e1d00,0x000b3ac15e20b3b8,0x000000000000bff3}, {0x000b01f1748ea86b,0x000e29e330eb12b6,0x000af2a26953e630,0x0003cb002e1eb2af,0x000bf525e4d4157d,0x000a3dff1638f297,0x000051a20f833234,0x0000000000045a9c}}, {{0x000b35a3033b3940,0x00007fe9fdde8b8e,0x0004a1bfc8bd5420,0x00049acddde6f6e9,0x00097e54356ca653,0x00009f73cc53c29c,0x000277ee15ad9457,0x00000000000e5429}, {0x000bdd741f2769e6,0x000d6f52035cdb19,0x000b835933b3195b,0x000b0ceca319bd4b,0x000b6951fd8d26e0,0x000c34d6f4e7eb67,0x000b59ac3a6f4395,0x0000000000000f60}}, {{0x000d7763c7959780,0x000c02c47010c514,0x000f6a495cc56b87,0x000be509d930f6e7,0x000d5f56cf045c8a,0x0002f1fc16bcf875,0x0007101f6456c006,0x000000000005304d}, {0x0001668b6ef47661,0x0006dd76452e46c9,0x0004266da10fc06f,0x0009fc89021bde74,0x000f4babfae0b5ae,0x000a61fd6505c6b9,0x00025a99d943c17e,0x0000000000059bf1}}, {{0x0003de8a392493e6,0x0009cbd10b8bfc25,0x00082fa94d1d5f3e,0x000be5ec0c907818,0x00071ad167ce9a18,0x0008c1c563677f4c,0x000275ccb254e2a6,0x00000000000e2c4d}, {0x000250541623e5c3,0x0003f44958cb1bf9,0x000db2f9dd62ce34,0x000a767a2ffdbd52,0x0009b0b6c22d7445,0x000c92b2e0e789c9,0x0007823ff8b6565d,0x00000000000eca98}}, {{0x0000ad4fec1eb621,0x000c36618fcad673,0x0002540e2f8dc71a,0x00039947d7ce5530,0x00095257f24b90ad,0x00098768cbf8c458,0x0008305a94992020,0x00000000000bb6d8}, {0x0007503283325be4,0x0007dfae8f1616ec,0x000fc3e0aeb8a2a8,0x0001ea9139ea0507,0x00012e39e1d8a72b,0x0009c7bc282229a9,0x0008254153bf3e47,0x00000000000c5541}}, {{0x000605d76cba7718,0x000a6fadf9be90b6,0x000490316f096fe8,0x00024ec2f9953940,0x000861203303cbad,0x00089a4be6236a26,0x000a82e4bafc3365,0x000000000005e23f}, {0x000642137e1da447,0x0005c8ccbc576c76,0x0003f63011c9e098,0x0002d5841df8dd26,0x000914d31fcde6bc,0x00026010bec24e1d,0x0002f3acaaf13efc,0x00000000000e01b9}}, {{0x0005639fc34e5a27,0x000c7c52789bb2f8,0x0006d4ce23fe7231,0x000f95aacafbbfb9,0x000dc7f6eb6d8b6d,0x000b4c9d737afdcb,0x00045357775bdd6c,0x0000000000011007}, {0x000bddf07c5f1b9e,0x000e3903e5ba1399,0x000d7d2fc919a9a5,0x00018932d7ac9e4f,0x000543ce66a8046d,0x000956410e2fe9d1,0x000f7244b5beb4d4,0x00000000000bb147}}, {{0x0006e03c443812f7,0x0005c6f6a6104456,0x00098182647d3e84,0x0009a6ab51989e5d,0x000f68f5b16842fd,0x000f7fe671b60ce0,0x0005a897324d8756,0x0000000000067681}, {0x00061f269664533a,0x0002a265ee993d1f,0x000a90ce6a02c969,0x000232334b4adb0c,0x000e1e5a8d18e909,0x0004f6456ddcd233,0x000d9b3dc5b27c5f,0x000000000007f421}}, }, {/* digit=47 [{1,2,3,..,}]*([2^188]*G) */ {{0x000b170252588bc8,0x00099bfc40c30a63,0x0001ef23d6587c46,0x000b54dc027511d3,0x0004cf3484ce4fd7,0x0009beea5f479928,0x000280655ab81106,0x000000000007392e}, {0x000148f913baced2,0x00084522e7b403b5,0x000493599cdac0b8,0x000b95877f3913fd,0x00067dd525149cf1,0x00008cbca3e06b92,0x000529992e920e29,0x000000000006d6ed}}, {{0x00097dff92ad4838,0x0001e8a46c9112d1,0x0000711ed277a798,0x00064f15cf8e4ca2,0x000a01cb3488d4ba,0x000bd7ded01b3908,0x000ae169b1fa5d38,0x0000000000018b2e}, {0x000f3694f52a1f22,0x00019619324bdbe0,0x000d1d925851b48d,0x000f42e925b3f6ab,0x00095f7e4d11a397,0x0000d9f0132169a4,0x0002e5c0fa9a548d,0x0000000000089d8f}}, {{0x0000115baf0f7c2d,0x00040240239ae483,0x000c7482d351827f,0x0007151f58ec53e4,0x000cc080d59ff9ab,0x000f782f4d397862,0x000d5873eee88536,0x000000000006c1d8}, {0x000c16042c611b2f,0x000f258bed3e5b15,0x00036e097964eba0,0x000c8ab8a482af89,0x0009e746a8549044,0x000a0548e0065858,0x000a492538d1b926,0x0000000000007cdd}}, {{0x000178ddffec9175,0x0004c9c0d5230baa,0x0004bce21493d0f7,0x00090dd985154559,0x000c8dbfb46a67df,0x000757ce3223e8b9,0x000296f39529a36d,0x00000000000b4648}, {0x00000562605aa919,0x000dc330749e8973,0x000a3ffdafa653e5,0x0000b3494083aa87,0x000321e321c68c32,0x0003e78921161f5a,0x000ccc0980deedde,0x000000000006ad76}}, {{0x0003725fda5a777d,0x00086af9a69e965a,0x000a3534516a8b8a,0x000a77f3e52375ce,0x0009a019a5932dff,0x000238091ac65569,0x000085d402f5c4df,0x00000000000d3518}, {0x0004a37271e8fafd,0x00007dcee2db4b54,0x0006c1d813edf12e,0x0005b6121bc49990,0x000e68b9808d9cb1,0x000d6ac5b40b34f9,0x000b8a98de63590b,0x0000000000039766}}, {{0x00069c8c3d7c7657,0x0005171191261c8a,0x000244a0eba69bbd,0x000344bdda57f44c,0x000ac4f0cfd2ad4b,0x000543efd674b758,0x000d063bc058a077,0x0000000000056618}, {0x000a82ca14a01b7a,0x0009d95107c74391,0x000a3c4cfae47f34,0x000af35e3f1d63cf,0x000643ab87265dbe,0x00056c6fd012029c,0x000e304f588a4ea2,0x000000000003e5d2}}, {{0x00081d2046b48f0f,0x00043847622b5217,0x000c2a7014a5d0be,0x0009da7b82c435cd,0x00025b73e01114da,0x0008b37b399c8c43,0x000ddab978fe55ec,0x00000000000337d6}, {0x00034bf111412925,0x00071e0d4ffda16d,0x0003fc3275d2e3f4,0x00062872913cddbb,0x0004f67405be2a7d,0x000a31060229afd0,0x0009d6e372202e49,0x000000000009fc21}}, {{0x0001a0d511e4c022,0x0009173fa3508062,0x000e92c1603f0953,0x000549f58493d985,0x000adc79f602f64a,0x000512b84d9ceae0,0x0001516569e37bd1,0x00000000000151c9}, {0x000c6addaeefed36,0x0004c075678c2066,0x00015cc88eb8c3b8,0x000dca3a57fb96a6,0x0000223dc3ce6334,0x00011e2770ed9082,0x0008e274f9c3aebd,0x0000000000079c0b}}, }, {/* digit=48 [{1,2,3,..,}]*([2^192]*G) */ {{0x000688b6fc0935b1,0x000f5378205dd339,0x0000b901357b7bc3,0x000c06c682e00f2c,0x0003114d5423dbce,0x00052463ef2a145c,0x000b0aa01d98747a,0x000000000007d717}, {0x000d2bf78a72f39e,0x000d29653bc4f4a5,0x00051b32471fd3a0,0x00043dcaf8e3f402,0x0000e86fe16ef779,0x0009ffdcf70774a1,0x0005c96b62e6f1bf,0x0000000000058874}}, {{0x000b3ac410563249,0x000bc2a5f8ecef60,0x000af14f01d834e5,0x0001cedc59c4301d,0x00010111d9989de3,0x0000d5b951e0f40b,0x000ab8d29d229f96,0x00000000000d1dab}, {0x00033bacd39b8f1d,0x000bd7b225cc8ccc,0x0003c9f7b44c8f47,0x00052a1f5fb06b38,0x000f842b9081009b,0x0002725128a575d3,0x000cb7fddb48afe9,0x000000000000b452}}, {{0x000dcfd459bff4dd,0x00050ae10069e26c,0x000e9f25bee973af,0x000caf27ebaad0bb,0x00073dd6119cbbe4,0x000fceefe5907bf3,0x000c7e0a723dff9d,0x00000000000f7cff}, {0x0002a3a44c0ca01e,0x000d17bc95fa21e6,0x000c0e71f388ad82,0x0007ecd27b3335bd,0x00027b8d7d49316a,0x00019058fbf08e67,0x0009ea4b209f93c6,0x0000000000059d8f}}, {{0x000cfbdc0726f5f2,0x000ba167ec88a4a8,0x00009c64d249271a,0x000e2443877e6342,0x000603462cb310f2,0x0003afcee6321bf2,0x000dcd1dbd10ee9d,0x000000000002ca17}, {0x000667ac9826886c,0x000d509465265738,0x000151279a7a2541,0x000b0f95e1c59136,0x0001757d3a630043,0x000def1e0a09b94d,0x000d41533956529f,0x00000000000d4fed}}, {{0x000c29ae93761a8a,0x0008a3459097559c,0x000f79e8fee087bc,0x0009a286ec406ef0,0x0006fee5454dcc93,0x000257f708d21427,0x00085e66a0e1a56b,0x00000000000006fb}, {0x0006c4387ea9f222,0x0000ac44f9df22bc,0x000c5644721083d5,0x000a8224fca1a819,0x0008f3ed85bf5894,0x000899b5b8586e41,0x000371d494dfb202,0x00000000000ecb8e}}, {{0x00094e8a6ed08358,0x000cf690c0cfe457,0x00092e98638a5e98,0x0008042204d98a6b,0x0005bad2eb082250,0x0005823eec87a97f,0x0003f6d307c59ed2,0x000000000000df8b}, {0x0002a9b6fd1bc660,0x000e9280ae343343,0x00077184e86c10ae,0x0000e5a24d04e396,0x0007309830fcea93,0x000afeebc0269d9a,0x00002d41dc8f0ae4,0x00000000000f14ee}}, {{0x000ef795d8c64486,0x00026efca7f7acdf,0x000411f7c32b0a9c,0x000b87fe57d08e0a,0x000a7d9a1967c9ea,0x000c2749248c01c2,0x00063911c97ed97d,0x000000000001cf1f}, {0x000b6334379af438,0x000d1541f8c0d49b,0x0006f782375b1fd6,0x000935ba6be190e1,0x000764494b4e9806,0x0003c00b6ec6c5de,0x000f15f04e2d4cb8,0x00000000000c0b84}}, {{0x000c9d81a70917bd,0x000702e75a26e455,0x0005bf4870175e47,0x000d057ee7d8e4ba,0x000d8994f44953df,0x000538367b959110,0x00029cb4a16596bb,0x00000000000ef82f}, {0x000ea0c85d7d05e6,0x000305a7642ffe63,0x000b9d7a5d2d391f,0x000b23803a4184c4,0x00020f7fcd62c7ea,0x000a8a0c660c67ef,0x0002b041e05799df,0x0000000000004d35}}, }, {/* digit=49 [{1,2,3,..,}]*([2^196]*G) */ {{0x000ffb708a3b5e85,0x00030c97c01eab92,0x0007510b2d7953a7,0x000ce807fa7d3c2a,0x000e81060874dba1,0x0007eeead69e6f96,0x000f3d6e3e0df74d,0x00000000000b0c87}, {0x000317c5146f214f,0x00028c55ae3dbb43,0x00014b4be1d3dc49,0x0008c591de7860a7,0x00066e546731a600,0x0001e45d48202f8b,0x00015a652f2d07aa,0x000000000006df54}}, {{0x0007d6371007dea2,0x00049041c706cbe5,0x000dcf6b55c23258,0x000cd27839e9d5ae,0x0003bf3c4c067dc4,0x000b7bd22dfc9db8,0x0002da85b8094138,0x00000000000d0f4c}, {0x0000b16d9a334a33,0x00092d7b340062c0,0x0002bb5502deaa2f,0x000b2c2752366864,0x00010113a85fa340,0x000b327045ddd055,0x0002ff7dfc7ab29c,0x00000000000dabf2}}, {{0x000a8373e5c690f8,0x000ca2fbce9bdf20,0x00049076d1995e9c,0x00045939f4cbaf1b,0x00092574a3bd48ea,0x00092c39a56c5400,0x00034384a39630e7,0x00000000000eef81}, {0x000361503c11fa79,0x00095f996760edb5,0x000c1bbc8ea81e13,0x00012e6966d70279,0x00052e6f7c63a0ca,0x000d13ead92a6d5d,0x00068146809d269b,0x0000000000067aac}}, {{0x000cf4e4cd35d7a3,0x000a13fc9b3cedea,0x000ac33c871e844f,0x000a58afe1ad536c,0x0008cb39149f2003,0x000edf470cec4be3,0x0005194d578c99bd,0x000000000003a356}, {0x0001980c5865f55f,0x000607a762f2732a,0x0003ce874c8a141c,0x000817f270c508e9,0x00049fdb29c8dc0e,0x0002711d35a7be20,0x0000c2fa1a0be3cb,0x000000000003786a}}, {{0x00065cdb1cddc024,0x000c41d0af6b5128,0x0006106e0f532684,0x0001951b1ea8fc4c,0x0004b1fae4826764,0x00023477bc0b9006,0x0009ce7012642f66,0x000000000005bf01}, {0x00001d44438309f3,0x0007fca1f46757f4,0x0004d56451db59bb,0x0004ef2d3868de95,0x0001044e0c189c03,0x0005e38c30533d92,0x000053ba6cf14ecb,0x00000000000509d7}}, {{0x000af6aee4d4a85d,0x000c0e164268de02,0x0001633ba7cb9816,0x000979478ab17f45,0x000e0179ed0e734f,0x000a2686746d468d,0x00085d7e68f006df,0x00000000000e3d04}, {0x00073699ad94d8f6,0x000c30913a1d74ab,0x000e2aa1b6d33ea2,0x000a79e49eadd08e,0x00017dd8f954eeb1,0x000bb26d0433f5e4,0x000e2970a6281430,0x00000000000ff5e8}}, {{0x000235f9cfa08aab,0x000eb6a352b56ce9,0x0002152b2e478d04,0x0007c7a240e6dc62,0x0002d313b4a9ee1f,0x00001a40585d5be6,0x000d5a1522c5d25c,0x00000000000960af}, {0x000459bf66d63a1d,0x000e4a3cb77f327b,0x0001a15093d3f2d2,0x0000c7d3b93fa9e1,0x00013c0383ad8409,0x000f7a220c77f1ee,0x000bfc461c93b776,0x0000000000004ac0}}, {{0x000fd3f75cd14c88,0x0002a3c7d6b63ea7,0x0002b345f341120e,0x0005d20aa0eaa1ec,0x000fc0eab4908ed1,0x000d9f260e944ad2,0x000ba371525aa1f6,0x0000000000016146}, {0x000bd29ab6e83fdb,0x00068f94019075db,0x0002a02a4fd970a1,0x0001c37cab1060af,0x0000c8cac96f6a4e,0x0002466ec357fe4d,0x000e7097a8b8ab6a,0x000000000009c01b}}, }, {/* digit=50 [{1,2,3,..,}]*([2^200]*G) */ {{0x0007eae876f30205,0x000645b0b5d68b38,0x0002f6471178cf56,0x0000a4a404a3458c,0x00059f467b6072ad,0x0006348091de8e25,0x000178a4b3570590,0x00000000000706f0}, {0x0007cba07f8d2545,0x0006d588d21aac4c,0x0001bb1a8ee3a06e,0x000e73d241bcd915,0x00022facc7ccf4e7,0x00025d2a0b8d8a1d,0x000608483c35a71d,0x000000000001ef9f}}, {{0x0009cd91f152b14c,0x00034a704015f319,0x000a64fabfbdef40,0x000301f2ccb94180,0x00046f00d8aa697f,0x00038a0173ee8776,0x0005432b5afaf881,0x00000000000832d7}, {0x0002183eafee3abb,0x000d627c27ce1884,0x000735007191c91b,0x0005ac75b752008f,0x0001e84fe5f192dc,0x0005929cecf382e0,0x000ffa90e034197d,0x0000000000015ca3}}, {{0x000596896506329d,0x00058cb51f038efe,0x00073c05f41ddada,0x000fafab41fe1a74,0x000da719f25493c8,0x0004f5cde6297701,0x0005426e9165bc64,0x000000000000c11c}, {0x000368f61fe7d95a,0x00098a2564809894,0x000e829acda88407,0x000592622b1d1be2,0x00026ecdd041286a,0x0009f952486a3d75,0x000b0f4b867e0a64,0x000000000000629c}}, {{0x000259f3facaa9bd,0x0001d11dd860d21a,0x000b8c19c604b970,0x000aff635c019302,0x0001e3a4a900d4f8,0x00078c8ba96a727b,0x0007c41426daffde,0x000000000008d152}, {0x0001e6f4fd354295,0x0004a0c0d5233cfd,0x00066c04a38eba93,0x000bee43d914fb41,0x0008f3ba26a64828,0x0004eb26f8324ea3,0x0007bf027590f3a9,0x00000000000acd95}}, {{0x000a71b96f713d9b,0x00013f4f668435ae,0x0008fef0f35f5919,0x000e86e7365712f9,0x00088a822bc0f607,0x0001299b3d588229,0x000b1a2cfbd63ac6,0x0000000000067167}, {0x0006f5a47be411d6,0x000b0750f673f622,0x00032c38df6a058a,0x0005bd169123c758,0x0006eab99b375e6d,0x000aec6a36a93d1b,0x0008186ef4f7e68c,0x00000000000cf3ed}}, {{0x0006410726f50135,0x000fd959353be170,0x000b4de98d5dc91d,0x00026f799d7a4f4a,0x000e52fe4b656a48,0x000038573ab146ec,0x000e8494fc21d735,0x00000000000f4d56}, {0x0006901ebf8c490f,0x00093e15ca04c71d,0x000ef178dcf47997,0x00079244f21a9114,0x0009dcc76132ef7e,0x000e890482eecb7e,0x0002c55b484745db,0x000000000006e43a}}, {{0x000b8d876ab51a4b,0x0001af92b3072f8e,0x000d8f5d67f2d2e3,0x000d5edc578e3a39,0x00029587fa22e51b,0x0002eba85efda70d,0x000530cfec17089b,0x00000000000af7ba}, {0x0004893a5eb2bed8,0x000bb5ac155ae396,0x0009a3394a2b6335,0x00086c2c38718a82,0x0003d63745b7280e,0x0008a79aa9d12de7,0x000bf70e8ea855bf,0x00000000000bd705}}, {{0x000260c123f30563,0x000c53ede2484b68,0x000620a80e97a435,0x0009e93962a667bd,0x000b130f2cea5606,0x000366a66c931266,0x0003b14bd6a6fca7,0x00000000000aa5ac}, {0x0004e3f2adddce7d,0x00044a025d0ef29e,0x00075ab6560ff06a,0x000927f2b3057f30,0x000a1499f8844809,0x000b9a653b001c10,0x000d05309d141c30,0x00000000000bf659}}, }, {/* digit=51 [{1,2,3,..,}]*([2^204]*G) */ {{0x000d68f9d41abcc8,0x00016a6c328ffdb0,0x000797038aa63e5d,0x0007d39063de7eb8,0x000710daf9bd691e,0x0008b5d7a998df4e,0x0004b8c7085b9e71,0x0000000000016b3d}, {0x00019da01ecaa2a1,0x000494dfce693daf,0x0007011a8e84696a,0x00004bf4491fb345,0x00014552451c2c19,0x0005e5e407c1bf11,0x0003726562cc2c3c,0x00000000000fe0e4}}, {{0x00073ecab0b13cfe,0x0002484c3630b425,0x0005d7cee5256fab,0x000125ff61af001c,0x000fbfea35255abd,0x000e0cb6e69bca56,0x0005a6384af19900,0x00000000000d0047}, {0x0001438f80a7fcba,0x00090edafde48dd9,0x000a30b2135b9aaa,0x000f97a6c8ffcca5,0x0003e5a9cc5cf14c,0x000104e054d6cec2,0x0007c1b0d678f88a,0x000000000009fb52}}, {{0x000cf7bdfab400e3,0x0009e8618ffa6a37,0x00041539f0cbda9a,0x0000d744f61edff9,0x0009eb7a476f5b1b,0x0002ee99b33df67d,0x0002cc7f1a767ea9,0x000000000002223a}, {0x0004324c9cd0a9f1,0x000f616f376f2586,0x000c0794e16b9222,0x000516ca58765df0,0x00062260ed6b8dc1,0x0004b29ba8934082,0x000bba060eb0afcf,0x000000000001d252}}, {{0x000bb25431b5857e,0x000160d6cadbf906,0x000790df51943fb8,0x0003c734ab19507e,0x0005660086b33b43,0x000eb0f434fc5340,0x00058d770ae903a1,0x00000000000f6b5b}, {0x000dc8bc8bb4bdd2,0x000d6e206e14147d,0x00079b5341d6e69b,0x000ca2f47449e081,0x000639fef8e1cfbf,0x0006fc80cebaef25,0x00061b959e37b8c1,0x00000000000e911d}}, {{0x0006b0541df5b61f,0x000b0014a0907c72,0x00060742ec5c6420,0x0007c4dc999acc04,0x00075e7ab1e3dbbb,0x0008fb11e01b7710,0x0005c2a33fefbfcd,0x00000000000c0b8a}, {0x0004467ba7747f4b,0x000ec774dc2669d0,0x0007562d1fca7010,0x000dc694d9c84626,0x000a1e772c5f5ac4,0x00083fe91bf6e002,0x000dce4922120e0b,0x000000000003efba}}, {{0x000263fbc0d157fd,0x0005bc483d4b1827,0x00037dfadf4ae121,0x000df6fcbab1fb10,0x0000f6cdfc0c5165,0x0004320fceb28437,0x000e80ab565c0099,0x0000000000062133}, {0x0007401414422436,0x000ee7850cda5472,0x0007bd0ba094b0ec,0x000805cc2c82eddf,0x0006cf244539d14b,0x000dbe92dcb5468b,0x000f1e97d43ee825,0x0000000000089fb8}}, {{0x000a494639f26e1a,0x000b5421afbe0092,0x0004dc6db28bf654,0x000cf4db1a2705ad,0x0006d128bcd556ca,0x000191ad86a3a413,0x000d242411c4b866,0x0000000000015b45}, {0x000845fec1268b55,0x000a74cc82459052,0x000da0992b42bc3f,0x000bb1c69f6298e1,0x00031933fdb59c88,0x0001308c3fe567b0,0x000dfa8a6aea7188,0x00000000000a2f0a}}, {{0x0006a4d1fcc1ad65,0x000d2d7bf2ac5a3e,0x0005e362c26e5671,0x000abaa9afa97632,0x0004b62b36ab162f,0x0006a84e97b7f166,0x00043d77b9f79729,0x000000000007dbd8}, {0x000519c3add29e33,0x000fcc6e9c1e11fa,0x000ac380a63f4305,0x000a93d3bfa90c04,0x0009d050e46afa7f,0x000c5625655846fe,0x000a65473b9a0d35,0x000000000002b656}}, }, {/* digit=52 [{1,2,3,..,}]*([2^208]*G) */ {{0x000f0e1b25d4e4dc,0x000a6372798f002b,0x000537a488c42515,0x000f9a98a1e25677,0x000ce70391c85e64,0x000f024585870254,0x000bed2def81a341,0x000000000001d087}, {0x0002a1629bafa8b1,0x0006d3557d07cb43,0x0009543a3877e0bb,0x000c5675f73ba510,0x000b9c7c670608c8,0x0009850725309050,0x000e962ab67da3bd,0x00000000000e5df4}}, {{0x00057ab93a62b1b3,0x0004b7be81fb0ec2,0x000d385405273506,0x00040e27a8d16791,0x000ad520811ebb3d,0x000f65d231806c67,0x0003d7add4bb6686,0x00000000000e20e2}, {0x0008a96c64700a7f,0x00088208b470000d,0x000907fb1a1c5c32,0x00064f8121c37e26,0x0001a598efbbbd39,0x000eef966d35ef30,0x000e46bd76a276c5,0x000000000000af64}}, {{0x0007b8ba2901e630,0x000573f40494a69d,0x0001d7e86c246f17,0x0003360c9e634b1f,0x00096ab166bbacc3,0x000fdb67e6cf72ff,0x000736477d8f2db9,0x00000000000cb644}, {0x0000821b2e82caf8,0x0007549454e1ad4f,0x000486f6c48cff7d,0x0005f0be8e7b06ec,0x00047dc40b498042,0x000ed620b862df52,0x000a648ca7d7c812,0x000000000003c45b}}, {{0x000d7620f273aa67,0x000e1169474a1e10,0x000056ab42590c74,0x000de922ede425c9,0x000a6df8a8908589,0x000a8b8e350e03fe,0x00091a0d8a5c1c4b,0x000000000003fffb}, {0x00026981fafa18b5,0x000f721cf05437b0,0x0007e513859293da,0x0007eaed0962c826,0x0004213f6004c323,0x000148b6b43d6ac3,0x00080a45e619b2d4,0x00000000000ea5fb}}, {{0x00014768f5f99aa5,0x00067314ea217285,0x000017c8fd29a716,0x000fb46a63ea8fc5,0x000890d84e5b0902,0x000e49b8a925a6dc,0x000be5e2e74f9c14,0x0000000000007d45}, {0x000cae18673b6270,0x000667b768d075ba,0x00089b2a5deeff6b,0x000223360d5b216a,0x00080a7386f475db,0x000c47746b132b67,0x00031d7f933fd580,0x00000000000fbaa6}}, {{0x000ee5b308cc45e3,0x0002faba967ac481,0x000d29b2fe96bd68,0x000c601ef5f681db,0x000ffddc580fe033,0x0007572d85c34f77,0x0004d0d30f5b66f3,0x00000000000da20d}, {0x000030e8bcc549d9,0x0002cdb2310273e6,0x000ec784d2efa81a,0x000a33f7899cd7f5,0x000fda29c3821cce,0x000e14ecf0f4e0a7,0x000839c6d7c5f32b,0x00000000000d9caa}}, {{0x0003fe55b28c2fec,0x0007ba884edf1601,0x000775572e4af6c1,0x00004152d7852a27,0x0007f26efb4c66d0,0x00022f8cb34732d7,0x000ff518b3ef8e29,0x0000000000018bcc}, {0x000ec4cab3e21461,0x00004a219cb1deb6,0x000868a49e96a154,0x00099e1d90760ec0,0x00078a94df2ef0af,0x000058f89e6fe194,0x000d9764b5dfcd04,0x0000000000023d21}}, {{0x000d7944d758c20d,0x000209a8580a957a,0x000f955204f37a28,0x0000970be07f7827,0x0000712f7b7cb4da,0x0006a7b970ac2a26,0x000f62c9b8ee8443,0x0000000000011fb2}, {0x000ff5f68230c1a3,0x0002a5daabed96f3,0x0003bdf181469c85,0x000b5b7d96cfb8e8,0x000344d9e84382d6,0x000e7da3c4d7d0d9,0x000253fa2a9ea991,0x00000000000d531b}}, }, {/* digit=53 [{1,2,3,..,}]*([2^212]*G) */ {{0x0003b2a8a65e5b7e,0x000424cc41f278dc,0x000bf1d7ec4af5a5,0x00066640fa1ca255,0x000b91e5edaf7053,0x000d3de14eeb40f3,0x000c43cdf98235f1,0x00000000000ff018}, {0x000927ebce051283,0x00074aa3228e6dee,0x00043f750dae9462,0x0000425650b2dab8,0x00026d875f1790e9,0x000e8a46ee4a8cad,0x000fb5c212029c9c,0x000000000005ed7c}}, {{0x0007539a8f390740,0x0008eadb5966f40b,0x000e0b7342eb902f,0x00073e244693a961,0x00055982bbd3a76e,0x0002ca13214da743,0x000e7646e982cd5d,0x0000000000024938}, {0x000cf856b36cb844,0x00029749206b2571,0x0006030c0c47215a,0x000d1567025bb7cf,0x000e19555c9ebee3,0x0001639bae23f0e1,0x000bd00dec383775,0x0000000000005d43}}, {{0x0002c235491635a5,0x000e4e4e52e86121,0x000459dc25e36e9d,0x00051bfb49f2b393,0x000b3f8097cf73b9,0x0008fbf057b6cb7d,0x0002119dfb8d0b32,0x00000000000ebce6}, {0x000c890c36814c6b,0x00007a31a15235a7,0x0009c26d4a535440,0x000834e6b5638766,0x000d10ee5a281d22,0x000aee4eafd91b30,0x000a763d7a282d59,0x0000000000073300}}, {{0x000f6efbfb5bea3a,0x000f878b5c14b0f6,0x0005485b973e6dbd,0x0002ab209e1759fd,0x000db4b2f68cffa2,0x0005be7f45a86263,0x000f6d71e77c516b,0x0000000000019844}, {0x000dc7fe7c7337ad,0x0009d2519d0058c1,0x000edd3b9e6ca5d6,0x00074a685b3c2a9b,0x000fc294f4492c6d,0x00069fb469306f68,0x000886552e77c22c,0x0000000000010bb9}}, {{0x0001ae09a4f32c66,0x0007beba7daac862,0x000767fe0f73dc31,0x00018f885bdbc832,0x000094d43909985c,0x0009e108b86555ff,0x000313b0b1b2b653,0x00000000000c0bf1}, {0x0003b62754d457e4,0x00021bd4777c10d3,0x0007d7f58d2fb40a,0x00057374a27f1ddc,0x000eeaaa58ab85bc,0x00076fac29a8ae24,0x000377161cb2f5e8,0x000000000006636e}}, {{0x0001f89428b5c457,0x0007f1674b959a73,0x000b96ebf7106c2e,0x000a32dc67c36488,0x000368d720a63962,0x00057a5b24949617,0x000c0f4e81df85a9,0x0000000000053123}, {0x0003624d70103a1a,0x0003f5091dd340e1,0x0000c9fe10861f33,0x00020f52c119dbe8,0x0006c94d609a5e77,0x000dccd1fd584ae7,0x000c6e476c63ba86,0x0000000000032508}}, {{0x000df9bca60288d5,0x000016bbf77cab44,0x0000fa9d18796041,0x000eb1a2b9febf8d,0x0001a25330ce357f,0x00091799874240a8,0x000f5c7a9ab575b4,0x00000000000eda3e}, {0x000c7149276e2420,0x00036360410d2e37,0x0006d4d0d5e12db0,0x000b466cc381b581,0x0008247a49047bae,0x000c58130024a98b,0x0006d26e70b4c3e3,0x00000000000ae8a5}}, {{0x000d9a7dd453995c,0x000393313a9d4705,0x000fd95bba01fcaa,0x000ef915e4dd5cea,0x0003c565dd67c0fd,0x000ed05ac902a2a9,0x000ae9d8eba4dc7f,0x00000000000e157d}, {0x00019071237f3ae4,0x00006d655d0b3ced,0x000513db82a990cd,0x000525a0652872b6,0x000fe68c0ddb5b7e,0x0001cb31caf7968e,0x00071e2ec02930f5,0x00000000000f2be0}}, }, {/* digit=54 [{1,2,3,..,}]*([2^216]*G) */ {{0x0003b3ac56ccd2a3,0x000649b23ab4e3e0,0x000d023509576972,0x0009e51e798edf99,0x0009307675c7dbe9,0x0008c0fb63854744,0x00037223ffaf5562,0x000000000001698c}, {0x000420dd9073adb8,0x000d039f45a56f2d,0x00011e9a2cdfa00e,0x000079e4af138fd7,0x000a2ee4ecc02a89,0x000bbf92fb86371e,0x000c51076d256a06,0x00000000000ae3c4}}, {{0x000340cb6908d50e,0x00092ba2e95430b3,0x000660e7e985a29e,0x000b95145bdc19ee,0x000e382e77bdf94d,0x00020b29a951d00a,0x0001f19940a5fbb2,0x0000000000058fc9}, {0x000d804932dbc0b5,0x000be682e42eaaa2,0x000400a2efd4aee0,0x000810016294d055,0x00032e326d68be15,0x000e64fceaea13fe,0x000a8ac0dfe1ef15,0x00000000000b8237}}, {{0x0004480f8fce3f16,0x000a7e59b80017bf,0x0006c7396aa46dc8,0x000172a5af5b47f5,0x0000160d7e8d8799,0x000f9a549f72c978,0x00044a1d1ce972b2,0x000000000004857b}, {0x000d15fb2758caea,0x000542545bdd6f77,0x000984fe91e9b1e2,0x000343a4e23c0644,0x00091d1fd9cd5a60,0x00070b5b3986779f,0x0005a35bd5611b35,0x00000000000f9d76}}, {{0x000b72123cb1cd13,0x000e76ee65a0886b,0x00081e4e332045b1,0x000cc382876e523b,0x0006d3bf53aac4a2,0x0007f290cab7aba2,0x0005bd5bf00871db,0x000000000001ee6d}, {0x000bcea869ddbc32,0x000334cafb21874b,0x000bcaaf9d600f4d,0x000785520b281cd0,0x000e64d9c65ea1fe,0x000a0e67be457198,0x00068aa3d1a6d0c5,0x0000000000090cc4}}, {{0x000450a44e08b4d9,0x00014cb0a365753f,0x000b82633a02b2b6,0x000210997ed887af,0x000f30d9b2970b85,0x000fb9c745fec3e1,0x0007854ce4149f10,0x000000000008cbff}, {0x000dc4bd785a06f1,0x0009f81b0d7b3b6a,0x000116390fc1ac37,0x00021de2b841eb88,0x000ad83c22e6aec2,0x000affe9162c7d86,0x00081d5504dcf885,0x00000000000f4454}}, {{0x000578651af84c0a,0x000e0d4ee3f7f52b,0x000cec289c787837,0x000ee1363ebab5bb,0x0007005ec2374c0b,0x0002fb00670e32d7,0x000899302fc73dc5,0x000000000008f159}, {0x000ba114d96a8216,0x0009d42a5478e2d1,0x000e66d84b639b08,0x0004970c8378f0e8,0x00058e2c86c5042c,0x000c7c76770c1957,0x0003a861a95e6884,0x00000000000d6fb4}}, {{0x0000a2299e18ff96,0x0001ceaf237a8503,0x0006d80455ecbada,0x000fa473f251ad61,0x0006d828578e5fbf,0x000e118adc40570f,0x0005485cc65c0dd4,0x000000000005da48}, {0x00073e60bf0732eb,0x0000fe27fc2e7307,0x0009067267d2e6a8,0x0002fa55e27fb12d,0x000810003fae35a3,0x0009800c17fcfd72,0x0002e6c74b50a3f4,0x00000000000dbafb}}, {{0x0002a6bfc8996b96,0x000bd0c62fd2c8ba,0x000a840806b7cf85,0x000933dcef3f9e43,0x000d9889ffa276b0,0x0003c88d251b1ec2,0x00052f9e84b2ba9a,0x000000000001913e}, {0x000a4507b899f92f,0x000e6bafc5e94164,0x0002238654296051,0x000cc41bed171099,0x00036c7a41c84e9b,0x0005369cd0db5b73,0x000934d4be07a779,0x000000000007bd3a}}, }, {/* digit=55 [{1,2,3,..,}]*([2^220]*G) */ {{0x0006d08f59277dc6,0x0008a3f2eff5384f,0x00049c170a3dfb6a,0x000b18a0dde190dc,0x000da26b0409af10,0x000b1d944f491b98,0x00054166080782a2,0x0000000000097e8c}, {0x000baebab71369f0,0x000d1fdbfc5f5495,0x000a70804cb1f0f5,0x000263857645ef4f,0x0006a02583638e5d,0x0005d250331bcfda,0x000285f5330ab8d3,0x00000000000c7cab}}, {{0x0004a7ee3780eead,0x0001ef16938f4dd4,0x0005af2b9dcbcc11,0x00095530b6490d71,0x0001a28a296a2d50,0x00026415c8432fef,0x0008656f254dd08d,0x00000000000d50c2}, {0x0005457026e64224,0x0003c4f5bc4553f7,0x0006183dc27db1b2,0x000dd6e65e593411,0x0002a56dc2eabab8,0x000a90e05676baca,0x000da038eea06bea,0x00000000000174ba}}, {{0x00021d43da6aa865,0x0005de6a19dcb664,0x0006a4c857b63184,0x0009b9fc6455613f,0x0004a7390d0eb4d8,0x000ea135a6cb0fe4,0x000982ade197a459,0x0000000000020680}, {0x000776554c3cb5c6,0x000b803db9be90e0,0x000e56e339783849,0x000e8d4753c196c6,0x00000b7c6ff544de,0x000a1b14259adcc7,0x0004f2c6260ec24c,0x0000000000046cbd}}, {{0x000c69e90d279f7b,0x00051a35e411c1f8,0x000aa4eec7d05943,0x000859e89a66f2be,0x000e0def8ecd7c7c,0x0004947b79908c37,0x000ce88274124e34,0x00000000000568b0}, {0x000eb0436a41e1a9,0x00070e52919611c1,0x000a98c568a44a8e,0x00039e156bd3a7e1,0x0006268f856260fb,0x000fd8293e56a34d,0x000fcbb3a1fe1613,0x0000000000067537}}, {{0x000d9811d879790e,0x000da8a15d6fdcb9,0x0006c38fcc4a52b8,0x000e38c55bbe733d,0x00051ff94a9d7a7e,0x000585ab5eff146a,0x000a5de572d13edd,0x0000000000006491}, {0x000a7bbc541e4f72,0x000a29c84e1c4d63,0x000bbb62e6c0b1d5,0x000cd9b385f06c82,0x00077a7759c3db12,0x0003bd7060c93eb9,0x000d50f1f5b0fe68,0x0000000000085ec3}}, {{0x000e87011f7cd75e,0x0006e89e48d8ba73,0x0007fdc53e3e2631,0x00033d7302c0daa2,0x000a048eefe360f0,0x000a7224415e4578,0x0009cdfd6dec89b0,0x0000000000030948}, {0x0003345fd128739e,0x000ad7cdcc2a0188,0x0002b63966c3b413,0x0000a455812b560a,0x00052ca31d8ca630,0x0003a5b5a8fa5c41,0x0004e036aa3c234f,0x00000000000c86cf}}, {{0x0004ff5664ce36b2,0x0005e9a0e15351cb,0x00019cbdd0d2f66a,0x00059eafb29777cc,0x000ae354cafdc170,0x00007c3717e40e5f,0x0009459cf594054d,0x00000000000a71c3}, {0x0007429ea783b1e9,0x0003469309e95af4,0x0004f55088c266f7,0x0004070e25823b6e,0x000d0bc27359f216,0x000925094ead851b,0x000f4e3d21bfe8b0,0x0000000000034a97}}, {{0x000a4c18541d03ec,0x0004ad927282fbf3,0x0005c034c274cf2b,0x000207f450db7135,0x000423e16d9558b9,0x0000e349cae95338,0x0002bc4f10c6d4e6,0x00000000000feb12}, {0x000eced76985b33a,0x0002f22548cd1c2d,0x0005b37b87399908,0x000f912b6167b3cc,0x00027902d2baa1c6,0x000de34ba6967bab,0x00025eebbe0b0836,0x000000000004b796}}, }, {/* digit=56 [{1,2,3,..,}]*([2^224]*G) */ {{0x000e99ecf706c6bf,0x0005c9e857f32800,0x0001e880e21c15d7,0x0008d68ff4f65674,0x0005ac339148f853,0x000dfc12f35380f1,0x00093efef0bfdd5d,0x000000000001387d}, {0x0009274bbe5eb9e6,0x000aa618ce77c94f,0x000ef0d12ae1c332,0x000f06e00dc0da6a,0x000e07603cc724ea,0x0006963c7049113b,0x0003005cf489088f,0x00000000000ede4a}}, {{0x000abae3c29bb132,0x000af77e486f79a6,0x000ea167f51170e1,0x00028ab7df36628c,0x00016704dcd6322b,0x0009a35672d14d13,0x0003b6d359977af2,0x00000000000ec96d}, {0x00053212afaa74ef,0x000f0fd6e400a371,0x0003860e13fc28c5,0x0001c7d9b8533afb,0x00028de66eb862d8,0x0006784eeefa638c,0x0002237405a9d7e8,0x00000000000a6c22}}, {{0x000fc1e6b9032350,0x000a46909994e4c6,0x0006261c6638f0ac,0x000ca05884aacaa5,0x000996995a981505,0x0002c000ee4b6530,0x000b0930e00a5ed0,0x00000000000236e7}, {0x0005ec99c1d0db26,0x0002ce696f09d532,0x0002f7914e3f9268,0x000a7b401e1e2a4e,0x00069d2d025aa9ad,0x0004ffeb19630acb,0x0004f69fab2c6ed8,0x00000000000ab758}}, {{0x000c87e27d06e6af,0x00073f9b2dba43cc,0x000cbbdd7e7ab099,0x000a4f33b8104eed,0x0000e4e1896e7692,0x000d2aa365da885b,0x000bcac2a30fec73,0x0000000000086f60}, {0x000adfed330d989a,0x00086bc8bf16d541,0x000f4b7104707db4,0x000e2f37e35610a9,0x000482f9d71c8e79,0x000e62733981139f,0x000061f8997ec424,0x00000000000a3518}}, {{0x000efb4736bf4182,0x0003f6cf0e6ef64b,0x000b24ffed39dfee,0x0007783856111dce,0x0000c0e9f2b00277,0x0007fe5073a1d36f,0x0008f1fcf4f6365e,0x000000000007fa7c}, {0x000ce2543c17ec02,0x0005509a02de874d,0x000cd3e25ee5e59f,0x000a9654b7f4e35d,0x0009805b58bd7211,0x00057860ca6b2ba7,0x000d58418302c209,0x00000000000f99f9}}, {{0x000634f7fb73c6b6,0x0002e4e6ef40fcf1,0x000c701a714f0702,0x0003403fd41d144d,0x0007e0774c37a4f0,0x000c7484a3a50717,0x00066b078e8c568e,0x00000000000fbb3f}, {0x0000fb0d6daae4e9,0x0002c169c9474ce5,0x00027d6aef77ce07,0x000968508303114b,0x0008fad0def23e8e,0x000c1c8da7a9797b,0x0007210ad14404ef,0x0000000000021ced}}, {{0x000169a6e51baf05,0x00088fde0d1b3e6e,0x0008e5407b7aa0be,0x000ad79c9eb9de48,0x000b0ffbcdac16d3,0x00020287c2707ec8,0x00055ad7e6750fa2,0x000000000009c2e1}, {0x000dcbd856a04522,0x000e43018c309307,0x000def4e0648d266,0x00023aecf15a4af5,0x000cc1b8cca01aa3,0x00043a969f085d69,0x00043047a3eaccb1,0x00000000000f3a98}}, {{0x000270a279eabd20,0x000d5c7e9ddef0ef,0x00060c66b8938b7d,0x000746db239bb82a,0x000b28ea13416bc0,0x0001309b0c811a8e,0x000b345f714ca71d,0x00000000000d4eb9}, {0x000f50441ed062cb,0x00091e0e5afdcc03,0x0009d20438aad877,0x0001e7b843343663,0x000a0eed1116670e,0x0009bbd50c8c38f9,0x00095af914fae261,0x0000000000051c19}}, }, {/* digit=57 [{1,2,3,..,}]*([2^228]*G) */ {{0x0001b38ab493e121,0x0005bde849cd1240,0x000576b3d2c358dc,0x0009e3dabe92fbab,0x00043324900a3fbd,0x00020904e785414d,0x000ba8daead1abde,0x00000000000aa5f1}, {0x0002d0438c4bd099,0x0002fd60a4f2ce26,0x000593174efc1656,0x000c78934efa243c,0x000f216a8d8c163d,0x00001617b3067dcc,0x00051e116b6534a9,0x00000000000bbabe}}, {{0x0004b6e85f0076cc,0x000c1929454f6549,0x000021b9b8ac3fe0,0x000a7c5ee25c0b0a,0x000f2e752295f5b0,0x000acac687d3372f,0x000e3cd6dadc7d6e,0x00000000000a96a8}, {0x0006465e062c14dc,0x00030ea831db66b4,0x0000548165c8c6c9,0x00017e572e3c00c5,0x000d2a5fb6ba5ff8,0x000392476b022e25,0x0005a0b611c5bcbb,0x0000000000019048}}, {{0x0000dddcc280d252,0x000d5efda99d90b9,0x0002988f9d0202d2,0x0006cd1ad14ac705,0x00031f4138808b9e,0x000dd7fb91239ee3,0x000b12d98e93d993,0x00000000000894fc}, {0x000d9440883321ae,0x000d433a92019c9f,0x000ee20fd3f674ff,0x00051280d0a320b4,0x000b4b607b538450,0x000228c2ec20551d,0x00025c6e63c766ea,0x00000000000ac48f}}, {{0x000ea4ad3f5b0bfd,0x000140372678d84b,0x0008ab3dd6009aeb,0x000bca4b79594c43,0x000baf3b75cfebae,0x0001e09c6e587850,0x0004cd534183ac2c,0x00000000000c0820}, {0x00012c542116a023,0x000a7dac2cf06c18,0x000f5e79e9f15f10,0x00009f490b0f6c27,0x0006c2c62207f6f5,0x000ff18873ffc3cd,0x000c6fbb21eb1132,0x00000000000e62cc}}, {{0x000a11bec64a35cd,0x0004f1ca74a30c77,0x000de3a654c55d5a,0x00049038d6b4b005,0x00002f7906ee3709,0x000452bbb12ba86e,0x000039aa76f77adc,0x00000000000f9837}, {0x0000782bfd430ed7,0x0001841fe306f87d,0x000ce68ff3cdd73a,0x00024ccaa7d44b2c,0x0005d86900f9cffa,0x0003ecfa022bae39,0x000980e7a138782e,0x0000000000086d28}}, {{0x000489915b0c1e42,0x0000991b8b685879,0x0005ba3b38e17597,0x000d69ea7d9931a2,0x000c7632a26bcdb0,0x000ba170f3c8441d,0x0008adf11a365c62,0x0000000000034e74}, {0x000d3f6d2f87f536,0x0009d523ca2d7db2,0x000b5fe1b40ff204,0x000c7771d07308bd,0x0007c291c2ef71af,0x000b40d1773588d7,0x00015629baa3b0aa,0x00000000000eea9f}}, {{0x000a95a8a249bd36,0x000f90ae9143a26d,0x000709bd167b8510,0x000f7a7f3b4b882d,0x000de22d9b9923df,0x0004f02b1b178e73,0x000c2fa83861afaa,0x00000000000b9064}, {0x000de7d4573c6d34,0x00022142eb294574,0x0006f55c30205aad,0x000717fe649a8b70,0x000cad53c9bbd589,0x000ecd8f7a925c47,0x000142c339b11a09,0x000000000001bbf1}}, {{0x000abd60f6eb49c8,0x0008c406a7e201fa,0x0007246dc14c8322,0x0002eff020748efc,0x000af39b58dbd440,0x0008cfb047827442,0x00078f77e3f2768d,0x00000000000e45a9}, {0x000ab42dc779cb3d,0x000229db0829881a,0x0005eb7284cde06b,0x000ce47b82775f69,0x000f63910016e434,0x00047792fe84995e,0x000eb9a35e8b971e,0x000000000007c6aa}}, }, {/* digit=58 [{1,2,3,..,}]*([2^232]*G) */ {{0x00097b7667d86ea7,0x0001b1fa064cf475,0x00026db64fb0c148,0x00002a1fa9d94539,0x000bdc6bd7eada81,0x0002f6044786aeca,0x000208caf91e3bca,0x000000000008573f}, {0x00036746e95246de,0x0006cd309fce8dbb,0x0001300c9068d932,0x0001ae0f3d530575,0x00000d1fd61e5779,0x0005ebfa626b053f,0x00097991c962c004,0x00000000000076ed}}, {{0x000013c3d6e02921,0x000c449f2499410e,0x000e2ab53501cdc4,0x0009103d5e91bc0f,0x000bcb404f68897b,0x000f7fc0263db1ef,0x0000af70efd9d842,0x00000000000c6a23}, {0x000a0390300406c6,0x000308d5b199ee1a,0x0009868ea4fe37e1,0x0003d34504dd889f,0x0001f823686fde58,0x000fc73dc0375600,0x000f42f19ab86f95,0x0000000000093f12}}, {{0x000b8a18e1e24b49,0x000143f896ca9186,0x000d7ce3f5b4c07a,0x0001632600e4e2b2,0x000f69e702d5d074,0x000e0df2b87c7db5,0x000fba1f5a3b8053,0x00000000000f443d}, {0x0005af3bc7c98ae2,0x000deeb90e22f972,0x00070953899b58fe,0x0008299a5aa335b5,0x000d4197b32afb1e,0x00055918ed78504c,0x000c720e7a79cc67,0x00000000000883b1}}, {{0x0004af5925d66db3,0x0008dbf66baa58e7,0x0001c386a0ca25fc,0x00032abeaaa466ce,0x0007e5f2733b80bc,0x000531afa605b789,0x000369e9e7e3a1a2,0x000000000003deb8}, {0x000174c1d570e84f,0x0008d36212ea2dd8,0x0008479c4475fe18,0x0004b31444e9ea02,0x000169530c1befa5,0x00079bdd19c2229a,0x000cc368feb9854b,0x000000000008b984}}, {{0x000682b315cae64a,0x000981df8d98c41e,0x0009fabd7bca288f,0x00064f91703e1431,0x000e9de0ab4ca54d,0x000dc4e0fa12198b,0x00091f160e06241d,0x0000000000066958}, {0x000b5c1e9cafc463,0x0006f808565e66f7,0x000a9467f76914c8,0x000cd934bac17690,0x000ca5be965f6682,0x000a38e9062e7ac2,0x00016ed33f6f8ad7,0x000000000005b8b5}}, {{0x000509d8741fea0a,0x000c1f041e421362,0x000c0d8899228fbc,0x00093751128ed62b,0x000acec6eae64fea,0x000a65dae041a1c1,0x0008e81f32359415,0x000000000000154e}, {0x000a9eb331e84371,0x000ec309e9f286a4,0x000765936bc21528,0x0004dd5692420c27,0x000ec4fa1a6a7bb5,0x000779e77193a41a,0x000b8c35f5f3b43d,0x00000000000046eb}}, {{0x000b5769d7b9ec0d,0x000aa3a5a366dc99,0x0005d073ce2a60d9,0x000e4aafe5355bee,0x0003ced676663e16,0x0003440036d8bac0,0x00020c403eb33ed9,0x00000000000333ab}, {0x00094bfc36e2db30,0x000739fce19869f6,0x000435b17be8c513,0x0009611921a58e5d,0x000620d5c61a8e68,0x000c81b4e8f5f115,0x000779b17f612fad,0x00000000000e562f}}, {{0x000d75f385d1b0f1,0x000f0d6a4d25bfe8,0x0007b705bfa0d54e,0x00059731cdedfc0f,0x000603d6502f9420,0x0005ce8c80c4e385,0x0000b7981a4fc5e1,0x000000000007aca3}, {0x000ea22cf2bcfc17,0x0009ef2037ef684f,0x0007e5010cdb37dd,0x000a23c71f3e4e4b,0x0009f47b504b9c98,0x0003233aaa73c8b8,0x000f68b9e33f5402,0x00000000000f92c9}}, }, {/* digit=59 [{1,2,3,..,}]*([2^236]*G) */ {{0x000a9e3a73909533,0x00090ba03ba3b07a,0x00090d7a3c9c5a5a,0x0008cfe4f0f60b35,0x000e6fcccd96f96b,0x0009dd17ab908d77,0x0000487208ef7de7,0x000000000003ec3d}, {0x0006af6a704d4f0e,0x000d09c5ad2d9a11,0x000e77d5943d9764,0x0009449470eb938b,0x000bee7d772fac99,0x000b7ad09faaf27f,0x0000a9fbe402abd0,0x0000000000057db0}}, {{0x000ca62ea2a4a457,0x0001b10c082a59d1,0x000bdd4313beafb9,0x000935b4cb291a7f,0x000313e9ce08785d,0x000f6f1c4fc2ae15,0x00024c3146fabf4d,0x00000000000c87dd}, {0x000f74ecc24bd4cf,0x0000385fdd8765b9,0x000dc418405d512e,0x00005013e7e0297e,0x000fb92df904c81d,0x0005ddccbb56ddd1,0x000f1d4612df9f29,0x000000000000e27c}}, {{0x0002069dae7548ac,0x0002986d9b05f69f,0x000025ad33463063,0x0008e7c27d9d64d3,0x000aba04e6ad9b6e,0x0008abbbe79bd66b,0x000d0477e4d0b082,0x00000000000cc540}, {0x000bdbdb8d90e2e4,0x00067f5d8a46ef90,0x00078bfd47c637af,0x000b852563fe6b52,0x000997cdd04fb93b,0x0007de47d06bb3ae,0x00061c07f011d48b,0x00000000000de78f}}, {{0x000eb7904785958b,0x0007d7830460f8a0,0x000cf49e72cbbaa0,0x000e2aa307d9c790,0x000b5aad8b6c73be,0x000848db51b02af1,0x0004765e31882703,0x00000000000f230f}, {0x000b79128735694b,0x000bd4ea6535cc84,0x00008e33135971e8,0x0007b332fd33cac2,0x0001c566914f4c19,0x000952d3b24c7b0b,0x0005f2956ce3c371,0x00000000000fabae}}, {{0x0004121555388dc8,0x0008b8a95e5c1a8a,0x000cd5dbd7b0133e,0x000df6acda40bc0b,0x00058234471d1859,0x0003c0100f9097aa,0x00067caddc0c9b78,0x00000000000feb70}, {0x000ce59ade26052d,0x000a6e3805fd0a27,0x000626ac8acaae6d,0x00099921943a0a1d,0x00091dfe627ea459,0x00006515fb47f061,0x00073e313d4f09da,0x000000000001f54a}}, {{0x000f6dd7137bd615,0x0007e0db87bc3c53,0x0002eda89127238c,0x000e9c4a3fd2a60d,0x0001c9f017e5ea81,0x000c75768190c9c7,0x000de621864180bc,0x0000000000043dbc}, {0x000fb5dd8276da18,0x000de5b090c70dac,0x000cd9057894e345,0x000d268a918bf24b,0x0008ae204f49fef3,0x000d7c356e10c52c,0x000a17f4be898d86,0x000000000002fdb5}}, {{0x0009bfc4aad5cc44,0x000a20079c69c96d,0x0008a5713957941d,0x00086660139685a2,0x0004946fbeddb8d1,0x0001aace408590ca,0x0001b67fecd9b964,0x000000000002936a}, {0x000267114a49f247,0x00065925b6235aee,0x00055e3538cd2015,0x000663d8c6fb34ac,0x000c2fc1c10d971e,0x00042b822543146d,0x00024d6e4053c706,0x00000000000492e5}}, {{0x000d356fb82e9b9f,0x000beca9872e0a14,0x000f54683a031c30,0x0007cb84e05b2811,0x0006fa234d4596b1,0x00035a7d89798714,0x000384ba78949ebb,0x000000000006fc59}, {0x0001361f78e02fa8,0x00081a303e549f81,0x00064be08532a2fa,0x0002de8ee7220467,0x000563e27035e57e,0x000d2fe6fa05c106,0x000aadaa38e86602,0x00000000000ee2f6}}, }, {/* digit=60 [{1,2,3,..,}]*([2^240]*G) */ {{0x00044971cf281b0a,0x00052c0426b768f1,0x000ef3f4445c186e,0x00012e3172c0d3e8,0x0006ee75473731d3,0x000a7ee615f49fde,0x0005fb895530f06d,0x00000000000e8b3a}, {0x0006345afdc270e9,0x00019fd14973443f,0x000f6896912e434e,0x000ae07653908d03,0x0006ba02a278e2ba,0x00021b8f8c3d0143,0x000297a0d0222e7b,0x00000000000d7ec1}}, {{0x000653659b1a252c,0x000514f120aa7478,0x000c72dfe03d7757,0x000ac5ecfe5f7a92,0x0009bbf3cec6c96b,0x000361cd5d4e73d5,0x00044ced8d233560,0x00000000000562f4}, {0x00045d3e2b7ac684,0x00022bd37d3cf9b9,0x000cb601f2d0a968,0x000535a3d2f41ee1,0x000ee8b1743e7e35,0x0005a27650353b52,0x0008b831d89dfd7b,0x000000000008d9ea}}, {{0x000718fb55d90569,0x000b306a67bd2493,0x0001471031374c3f,0x0005d5197bc62d32,0x000924c51874ee0b,0x000a1a0d552b1703,0x0000acfed1f42382,0x00000000000db627}, {0x0006189cf7edbc97,0x0006c36be4a9b658,0x000680236e8f5c91,0x00036d3b8f8074cb,0x0009718545c6c174,0x000757d213bb4d39,0x0003668e1ea3555c,0x000000000008c474}}, {{0x00063be615177c6f,0x0002773457010af5,0x0001ce08b2f26f1c,0x0000e8c9c25fe5be,0x000182dd0485705b,0x000ac280540f36ea,0x000b923d55bc8527,0x00000000000ad921}, {0x000b6da293461f09,0x0009551586cd4c76,0x00086171a05efa67,0x000605e84f0abcb8,0x0003772dd0dabb4e,0x0004e1d41354ef8e,0x0004917f1a8f795e,0x00000000000de5d8}}, {{0x000beb4ebddc46f4,0x00073ec72c64fb0c,0x0005bac2d9d9096a,0x00022001819efb1b,0x00068cdde8703c5e,0x000a87aeedf5ab6d,0x000f1975a44e9d92,0x00000000000bcf77}, {0x0009407ed3c226cf,0x0005e8191efbc92d,0x00064a74c9c1339d,0x000e58265cf242d2,0x000180b1d17be62b,0x000de59a9ae99a3b,0x000ce248cbb44692,0x000000000002dcb3}}, {{0x000a48783de6cfb4,0x0006bf3899558552,0x0009d51bfff43e77,0x0004fd32df8d1a75,0x000376d3fbbf0b1c,0x000fd52bcf16bcc2,0x0001f0d5888916f4,0x00000000000d5cde}, {0x000f03d1ac917a2c,0x000ae764ffffd280,0x000af8be538ef59b,0x0004762ccd57b860,0x00032935106234f6,0x000c642f32233a4c,0x000f34df076095d9,0x0000000000059f0d}}, {{0x00010c66eff8425e,0x000379580cdfaafe,0x000d1f7ccb185b5d,0x0005f77c327f3e8d,0x000c35353c5f5d3d,0x000258eb105d5339,0x000f79c56fb5fe5c,0x00000000000edce1}, {0x0005bd6f7b6e122d,0x0007cab7aa141541,0x0008987b379beb7f,0x0001491458d9e533,0x000caa7f0f31e124,0x000fda7abdd2448c,0x000a4dec58d3c7f0,0x00000000000c91bb}}, {{0x0002f037fabc6138,0x000b73bd258d77ca,0x0006aa4d0ec1d1f3,0x0002512e3f966a14,0x0007709d0c2d5b43,0x000658259338bfca,0x000023d142cc1049,0x00000000000636b8}, {0x0007458ca547abc1,0x000cda9ef9400a80,0x000ad926836a9402,0x00063c55cb644887,0x00011cea475bfd2f,0x00067a25fbae949b,0x000a6aa45446031e,0x00000000000dc6a7}}, }, {/* digit=61 [{1,2,3,..,}]*([2^244]*G) */ {{0x00085fa16820f665,0x0009fd699ea2d24e,0x0004f1772a862ed3,0x0004bad66a8b35ba,0x00024233fccb4660,0x000d3cf0c0c779b6,0x0007af578458acbf,0x0000000000096bf5}, {0x0008a325d9d68d07,0x00045a9724244e54,0x0005b4b1e20150f9,0x000a5b8c6be8c159,0x000c774d62c40980,0x000bde24b6230e3e,0x000204da1467d84f,0x00000000000cc862}}, {{0x000b4d1a75edabf3,0x0007567c51633fd8,0x00020dc66cdc521c,0x000c8dc9ee450d03,0x0008b41a3e2f77fc,0x000bf06898dd2b31,0x000464df6a935e93,0x00000000000a92e5}, {0x0001e3ee6beb3c9c,0x000e449afcd9ef46,0x00031a4b44405106,0x0008ad2c7ea7810a,0x000e550822b2cdbd,0x000606adcfe61571,0x000110744a4f9386,0x00000000000d9d4e}}, {{0x00006ff4ac15d783,0x0007ef1084276ccf,0x0009d3b1212d957e,0x000dcf5bfb4283a4,0x000db74017eb3752,0x00078fcf8f6b2214,0x00039afc1cdf7245,0x0000000000012265}, {0x000c5dc1b7858cd2,0x000cdcc0796680d4,0x000e05b222bc5975,0x0003a9a504cf7d65,0x0003c93ed5932027,0x000303f1b0c7b7e5,0x0006a4aaf9c36866,0x00000000000cb013}}, {{0x000bfa5cdf24bf96,0x000411fef389c07d,0x00022753fd218088,0x0000a1437f04a344,0x0009d0169369bd77,0x000377cc3c7438e2,0x000a4f6b265742e2,0x00000000000c369f}, {0x000bb384dc3d9a84,0x00060dfdbcf462e9,0x000d3f52e65bb342,0x000a0b82a9c483da,0x00042de432285574,0x000d1fabe0563fe9,0x00096658ca0e8aea,0x0000000000066023}}, {{0x000afbbacd3ede36,0x00007746325d090f,0x00094f8b4a38ccef,0x0001c2866c3931a7,0x000a783a73e7d9f2,0x000d82d13c12880e,0x00010e382e1ce28b,0x00000000000ac023}, {0x000fda6b09a40144,0x000b69802d06233d,0x000de8140422422b,0x000367efd4cf75a0,0x0000e8f2f6ed38b4,0x000e72ff4765cdee,0x00070ae0b4d72b35,0x00000000000947d4}}, {{0x000a35bb9d72eb2a,0x000c5383bda07268,0x00038c9d09f99c2f,0x000717d369f39c03,0x00011a5a39006f3c,0x000ec6c2b1bb593d,0x000202d0f07ecc2a,0x000000000004240b}, {0x00083c5449860db8,0x0001935342f6c7b8,0x0009a1541ab519cd,0x000eb09ccb6a888b,0x000785aa42c5fcd6,0x0004e5895abb7a6f,0x000582952f8824aa,0x000000000005c406}}, {{0x0001d7b0f8433a5d,0x0004359d6e052cda,0x000fea341e325461,0x000d07d7907cc890,0x000dc4ce5d800459,0x00004f40267d720d,0x0002a83262028eed,0x00000000000d7881}, {0x00055f59d844fe29,0x000fcf735fd6cf7f,0x0001c0c0179cc733,0x00006e8e19a43f29,0x000f19592b76328c,0x000b836f7b97ef65,0x000a9981325f3db8,0x00000000000d6e6c}}, {{0x000a67318a4b19fa,0x000a63667a71faf0,0x0007be6235b29837,0x000535efc62f7919,0x000b389faf7fe084,0x00071b7f65bc1652,0x00070340cf51683a,0x00000000000d4f39}, {0x0002b576e30c499d,0x00099823e7549478,0x00032769bfa306a4,0x000ee027225b31ad,0x0006fc282f165639,0x0009f61ae7533bc8,0x000803710009d2c6,0x00000000000bf65e}}, }, {/* digit=62 [{1,2,3,..,}]*([2^248]*G) */ {{0x0006c5f4c042c4cd,0x0001ceb29e44bf59,0x0004c11cc5ce653f,0x00004943d2bf689a,0x000a47428dd2d09c,0x000aafac83ab7799,0x0006e0dc558d6be9,0x0000000000087f9f}, {0x00056bc34f65dad0,0x000c793842bcd3a9,0x000241a2ffbfced6,0x00052687e6d47b5b,0x000a4c37eeee1645,0x000c412ceab304b7,0x0002c8dbb3d4e13f,0x00000000000a726a}}, {{0x00059e97675084b3,0x0008d79d88dffddc,0x00002dc16c994a53,0x000000fce7d606f0,0x000e2fa27fd3b528,0x0009436afc773557,0x0004c755b53dd3e1,0x00000000000e10b6}, {0x00077a15a41de95f,0x000bfe5832664b2b,0x000d15e689d49c17,0x000bf537af3e3dd9,0x000cf47d298c7b93,0x00012136994fafa2,0x000ff694c2ff9a21,0x0000000000033468}}, {{0x0001b740495480b0,0x0003f91e8c991baf,0x000b4c043871430f,0x0003f6dd095f5b94,0x000cddf3cad27c5e,0x00057aacfed7522f,0x000f5180bb87056c,0x000000000000cc5f}, {0x0006cac5a2f35aa0,0x000e0964def7e61e,0x000e006a84529a7b,0x000192584de66a22,0x000e075f07c5cc75,0x000eade939acaf7f,0x00058f6505c2f81e,0x000000000000e3cf}}, {{0x0001fb7f00850a1a,0x0001dbe45d81a1aa,0x0000ee7897985bd0,0x000a516b078ea895,0x0001b446476463c5,0x0001e52329f3efe4,0x00022084580e2410,0x00000000000c8ae8}, {0x000539dde4d08a27,0x00077bff4077d088,0x000c1e715cd7b849,0x000eef207e1c03eb,0x00096e654d584df4,0x0006f15964ab3d03,0x000cd5b20056cd08,0x000000000008acd7}}, {{0x0008f4a5a8f26e12,0x000538caa623c979,0x000e7d0ec3691999,0x000f856ee285bfe4,0x0006d0674ecd089a,0x0006f661277b461f,0x0009f8baa9d9b38d,0x0000000000059066}, {0x000460fe25d6fd2a,0x000d2b164340c38e,0x0003981c9e27c186,0x0003b9176e4346f2,0x00017caad5fc73c0,0x00087803d6a678eb,0x000a94103ff0790a,0x00000000000f7430}}, {{0x000dd3174fcc39a0,0x00094517075af0fd,0x000fd65c623f7ba2,0x000e9493b86f6398,0x00017f296bf4320c,0x0001082765115657,0x0009000919607a96,0x000000000002f035}, {0x0004b29394d28cac,0x0008f5d13de7c5ae,0x000ea9b2719ceec5,0x0008089c0f58697a,0x00030ca7ca20f1b2,0x0001e1be52adcd1a,0x000ba096c07f42c2,0x00000000000baa0a}}, {{0x000dc0265a01c54c,0x000233027c169336,0x0003342d9c6b202a,0x0006cd31b8b0179e,0x000a6dd5a4a7e6eb,0x000c82f110d2d27e,0x00002241682c0007,0x0000000000081075}, {0x000f1169b3430f67,0x00019f3903f514b2,0x00091dfa21d2d176,0x0005eed470bd3b32,0x0007e85a62931b62,0x0005ad640a46398a,0x0003a58ff6ef8c80,0x0000000000095bfa}}, {{0x0006e424a5742fd1,0x0003a8cd6c9f7239,0x000180484ef81e04,0x000b0f589b8ad2c9,0x00070d9c999d9c0d,0x000f84ab4692a8db,0x00006ca407fd03c9,0x00000000000cc9a9}, {0x000b5d757bfbcaf2,0x000014813a7654ce,0x0008615f305ee56c,0x000f2934fa0a23f1,0x0007cb1f8d7aca6b,0x000d10c531dfa3af,0x000c1328036f5498,0x000000000000e012}}, }, {/* digit=63 [{1,2,3,..,}]*([2^252]*G) */ {{0x00034e0d2aae29e9,0x00091a53f1a10241,0x0004dd23936a5886,0x000ed8532976d137,0x00065ee692d130ef,0x0009e7cc1cf5ada1,0x0004723ceda69d25,0x000000000009baab}, {0x00095b8627836d36,0x000237ee5baef4bf,0x000e9b1caaa769fb,0x0008ddacfdaff633,0x0009cec076939e5c,0x000fb509d575c8db,0x0006979afc8ae0fd,0x0000000000085651}}, {{0x0000da11d13ab853,0x00042a7342f9446b,0x00039f5ef3dbc527,0x0008bf07471c3856,0x000130827f3450e4,0x000779c23729e5ab,0x000d5817199191ea,0x000000000009fa9f}, {0x00077a9b9dc5fca3,0x000827d5799369d5,0x0003bee46a6f5cc0,0x0007d51e85417260,0x000dec720355253f,0x000a16268107a793,0x00031b1c14d0566a,0x000000000008bbb2}}, {{0x00016132445f3e21,0x0009ef5689c5dce5,0x0006397102e2e73d,0x00079d012eaa5340,0x0006d9271e941af8,0x000e63c34dba775e,0x00024b60f8507310,0x00000000000a686a}, {0x0006624c82f5c532,0x000dded5ca8f992c,0x000b2edebcb9407c,0x00039426d90a7d51,0x000bccd37e76e2ee,0x000412e0fe5b3e4c,0x0000489013bd08f1,0x00000000000ce999}}, {{0x00009cf56d1d974c,0x0005561d0e01b86e,0x00046be97f98120d,0x000e224b362902dd,0x00029e0a5d16d4a4,0x000e580e945923c1,0x0009544fc2bdd495,0x00000000000a8c3d}, {0x0004daa7a4671003,0x000a1aeff11352c5,0x0005a1c5b6c0120c,0x0007d3eab8f9f31a,0x00066d566c158090,0x0002e6fa7af2c121,0x00003a0082daba95,0x000000000002df9e}}, {{0x000fc79dfc540dc4,0x0004091b379c535c,0x00090bc691de574f,0x0004208176b3b828,0x0008aaba5cd3d0f4,0x000794f9fd18c211,0x0008944aed5c9770,0x00000000000f4c33}, {0x000946afeb1a61f9,0x000b9b8e67989163,0x0000523ed92edf12,0x000ef39ab5573985,0x0004b71031051b7e,0x000ac89e4175e393,0x000db8943abf4a82,0x0000000000057ffc}}, {{0x00066f02c7c0f325,0x000f899c2b4cc9e8,0x000f2b3e2c2a45ff,0x000b66b5a352b7b1,0x00043ec757ed067b,0x000d36adc3c7d6fc,0x0003a42f69291cb9,0x000000000007c914}, {0x0004d853fbc3268f,0x00006768c3c3f0a6,0x000dd7feada4c10c,0x0004b025299ea1bb,0x00091a2d4005d86e,0x00017fa60be46b7e,0x000fbeaf865a1693,0x00000000000cdce2}}, {{0x000297083b5951f8,0x0002b66fcba529da,0x000a6f9544c17490,0x000b97241b4305fd,0x000e25b6af89a371,0x0005f9e8cb2d858c,0x000ef8bab07d5327,0x00000000000d525b}, {0x00073848e93e22c2,0x00084ebf79e3bb83,0x0007a079aa9da5d4,0x0008b66cba1a65a3,0x00038b1eb8b67dbd,0x000a6436a88ea401,0x000e33210ac1b38f,0x000000000003df40}}, {{0x0000b48bcae58bd8,0x000c45f79f0de54f,0x000db929ac4cc6a4,0x000a68e11571c5c9,0x000e2474faf7d631,0x0002a924a6d072b4,0x000d7a5e043a6d86,0x00000000000b0fc8}, {0x000fb0fbc0056e2d,0x0008bf54bb7f2f12,0x00058e2455c41895,0x0009f4c5909ec050,0x0005abd164608145,0x000b1c69ed28cda2,0x0006f4bb676d018d,0x00000000000ac503}}, }, {/* digit=64 [{1,2,3,..,}]*([2^256]*G) */ {{0x0005d534448865a4,0x00079dbe04c30004,0x000de820bf917110,0x000b54670911457d,0x000b3f7a1757dbf8,0x0007bd62c9e683b5,0x00097e7b89a08a9c,0x000000000000b3fc}, {0x000ba720a0047774,0x000980ac9abfb9ba,0x00007bd7b6be79d8,0x000c335d9deed984,0x000f72603e080aa6,0x000783bb2e270580,0x0009ae70857a946c,0x00000000000caa92}}, {{0x00008763d38fe0f6,0x00001f071c986bc1,0x000413c627ede21a,0x000b12a61483bc2d,0x00001caf6dd6845e,0x000c21b9217471d8,0x00036d7b603616dd,0x00000000000b9925}, {0x000a996617818c3e,0x0007f433f065211f,0x000b56653ac9464b,0x0007386a9adf49b1,0x00092cb2944fdf61,0x000d9c0764bfeb39,0x000576bf288427b3,0x00000000000965b4}}, {{0x000b333ccbe322d0,0x000fbce23a199d59,0x000074dc302e3830,0x00000121d15a0063,0x0005f4355a1fc720,0x0007f780715fde73,0x0006913849761f60,0x0000000000018204}, {0x00074bfa03274297,0x0002575756e4ea63,0x0009809c9584a1de,0x00032763d4ce3dc3,0x000ef1d66e006312,0x0008829e6a769d2f,0x0006ef8624ddbac2,0x00000000000d2df0}}, {{0x000f606b2db32f32,0x000b59ec11596f9e,0x0004a5f37de5fafc,0x00094e131fca111c,0x000896076f45acf7,0x000732588438b917,0x0000daad71035b51,0x00000000000a5d91}, {0x000d85cad07f3bba,0x000a7efaad0e82d9,0x000f829c6ffe7ff7,0x0002426474ce3273,0x000a2aa270da9940,0x0008fa6ebd53b687,0x00041196c8bb78d7,0x000000000006e699}}, {{0x00044c83de3d28f8,0x0008b2dfc39e611a,0x00099024ec940ff4,0x0002123313aa4788,0x000b9c6acbd11cf1,0x000d54177785b025,0x0001eab4aeb5b8e4,0x00000000000d943c}, {0x00041945f056ffdc,0x000097892db846ab,0x0000f6f8e04921ff,0x00013c61cbd3232b,0x000700b6c34ebdee,0x0003de32b873e0a7,0x000302b279505ae2,0x00000000000c5a03}}, {{0x000395d621a49e0a,0x000c7430b669fc05,0x00093c4a448f25c5,0x000730c4c33493e3,0x000fca00ed3901ad,0x0004a55168c882c1,0x00027dab2e9c89d2,0x00000000000f5d03}, {0x00020231a1107ea0,0x000f946488bd7b79,0x000d5a9d2b183f55,0x0000e90aecfac7d9,0x000fac6a9e8cf9f6,0x0008bcda84afd1f5,0x00099857a20bf8c9,0x000000000008b46b}}, {{0x0005f4b3119ad50d,0x0006c1f2f6c1efc1,0x000be8ee71be11e0,0x000e4a6569c090bd,0x000adb3986d020dc,0x000f553eae4f7401,0x000bff1389799485,0x0000000000009026}, {0x0003665df6023a4c,0x000b388067aa6ec6,0x00069e9d017576cb,0x0005019459bf26a1,0x00058b6e76f68416,0x0000d2434ec125bd,0x0000b0d636f9321f,0x000000000008e05e}}, {{0x00021074c1c07346,0x00068fe1f11ac76d,0x000a3e93fcce998e,0x000015a3c5babf98,0x000d5929ea0a99d0,0x000fb7b7e7e795b4,0x0002e8c9cf68331d,0x00000000000a6499}, {0x000716aaedb25dc3,0x0000d0b7e0dd7aad,0x00064fd90a09f648,0x0003cf034f02b979,0x000a5662f0c86402,0x000058ccaf7dd410,0x0001eda3bb6088a1,0x000000000004e780}}, }, {/* digit=65 [{1,2,3,..,}]*([2^260]*G) */ {{0x0006b5199cfd1ff1,0x0009d140a0f9f409,0x0004971fd020b4cb,0x0007c2304a1f742e,0x0001195ba34e78ff,0x0007f78b4c0568f5,0x000a53e97183603b,0x00000000000f9efa}, {0x0009e6e1cb2c1b4d,0x000bae924d2c4efd,0x0004b415d4c5ceca,0x000e73f6ee37e106,0x000a5e5a1dde4b12,0x000cd64161836fdf,0x0004d87f1b92259d,0x0000000000067754}}, {{0x000befa999003a02,0x0000e279fd119411,0x000606c204c4310e,0x0007da4da44105e5,0x000a28223fe1d8f5,0x0006f2d2eb1814b7,0x000e06cf2fd241e0,0x0000000000001dfd}, {0x0001563b8cdc2810,0x000a4876a31af711,0x000bd72037bc4e78,0x000d608493a6a0aa,0x0008a88c03e75117,0x000916897dcec808,0x000c57eae1d352ea,0x000000000006e8b2}}, {{0x0001a9c4fdcf93d1,0x000650254486c9e5,0x0006796f28c8ff02,0x00058ba000f54926,0x000934009fb6fb58,0x0002bde301315bdd,0x000358b18a8e0ac4,0x00000000000f1070}, {0x000b8de4d767059a,0x0004ebeb1db7458b,0x000305d015a22913,0x00014d4e4122b217,0x0002aabccc7b1522,0x000d07571d3e673f,0x000f1794c50f64ae,0x00000000000e66b4}}, {{0x0004bef0d3847d2e,0x000aa09f8bb05816,0x000388d5b381065f,0x000c7b6076e13ec8,0x00035d5ac07f26eb,0x000ab69e6bda0b55,0x0001fabcb8132248,0x000000000001c0f2}, {0x0006ceb771ee0889,0x0007b7a466528564,0x000e55b024527048,0x00011864c1d7cb8d,0x000f2d08130185dd,0x0005ea0f0096f849,0x0009b2b4f503dd8a,0x00000000000d1bf6}}, {{0x000f0c6218b7c4e9,0x0008540336b12c41,0x000f74c446fc6c56,0x000048d9c841f0d0,0x00051d617f50c337,0x00017d3794ce6d02,0x00024300fef21981,0x00000000000f95be}, {0x000f7d33fe9f8bcc,0x000ec98de119d3a3,0x000e778f8a8c16b8,0x0005b720f9678bed,0x000d334ace309412,0x000e86e04fc5b57c,0x00003909486527b7,0x000000000006e552}}, {{0x0001aa0f2e0127d7,0x0007b4ab7a22bd4a,0x00047f417a4172fd,0x0009f95078de336c,0x0006f786924520f5,0x000f1d96ffd28fa3,0x000f0f1de42581cb,0x00000000000366e1}, {0x000e183b180aaf06,0x000febc65fa9d0a4,0x000739e25cf57814,0x0004f3a4a0822a93,0x000bfd05a0aa0638,0x0005ee3ce1c81332,0x000d00bfb12361d9,0x0000000000042016}}, {{0x000f0b32c63695dc,0x000143b75c45b10b,0x00037d16d187f9f5,0x000227df8e0a114c,0x000e73ddba245450,0x000f246455e69f1a,0x0007412007b80e57,0x000000000003d159}, {0x0007528fbc79a394,0x000ffcbe54d2888b,0x0004e47907e4e2fb,0x00070594cc39f745,0x00032b1b8da9e19f,0x000f68d2680f00ab,0x000829b765aaf973,0x00000000000e993f}}, {{0x0000b5faa7527283,0x000530a159f61ee6,0x0008e1f9dcf0213d,0x000b8ee1661a2405,0x000ec95c41b36d1a,0x00051eb56cae7f40,0x000250bc3d20407c,0x00000000000e8754}, {0x000ae69a0a837ff0,0x0000281561056151,0x00032df2869a92d9,0x000c1bf6af2a00cc,0x00042d0a56c0abdb,0x000c8959ee9a9425,0x0002f34774a7b77b,0x0000000000019cef}}, }, {/* digit=66 [{1,2,3,..,}]*([2^264]*G) */ {{0x00035e2ab65ec55c,0x000b3114a25c78e3,0x00036712a123ad50,0x00068411e7bd7df9,0x000ad6da54dbc49b,0x0000da3215b0359f,0x00087ea6e6e5f93f,0x00000000000d640a}, {0x0003244eb630ddc0,0x000f7c1a4f6cdf83,0x0008137a92bebef0,0x000eb8e3c0a631d4,0x000db756445ff44c,0x000c8880e0205b11,0x0000d304844e845b,0x00000000000b85e0}}, {{0x0005c0fc3837219a,0x000cee76894c3764,0x000faaa07cdf021d,0x000fcfbe55cd1e6b,0x00023a7ad5b9566d,0x00087a4ef5421a9f,0x000423a005838a46,0x0000000000023a2c}, {0x000326b6922fa665,0x000ed4b780011f85,0x00024bae2459585b,0x00069e937ced8f3d,0x000d8c1e1eaa2b5f,0x00089cc4d306b621,0x0007748acbbe71d3,0x00000000000f4ab7}}, {{0x000e8b5d217d418f,0x0002ee557e7c707f,0x000dffc8ed3b58d7,0x000efa4b42b3ab4b,0x000d8e53b32db9b0,0x000b1bfbd9d71dc4,0x000d3fe3a93e4e11,0x000000000009901b}, {0x0009bf805b79f71c,0x000b35f3a5304e02,0x0007d4e3dff75554,0x0007a7bef469e919,0x000278f160dcf415,0x0009189a9f03282f,0x000f2197e4b7f4c8,0x00000000000a967e}}, {{0x00083fb3cef3edcd,0x000642df6f242046,0x00054e87770387bc,0x000232b372bcc88c,0x00086e428cc59e80,0x000a1b76326ba13b,0x0005f32526ef1f13,0x00000000000dc97c}, {0x0007320a0cda3969,0x000344954867fb10,0x0004f1baa6436a30,0x000fa69be143027a,0x0003cf54f28b7e39,0x00097c2da1232946,0x000099cf0991dc75,0x0000000000052e07}}, {{0x0004ba256e3a80b8,0x0005fbdfea74874f,0x00090a65af244c4b,0x0005675aaba39901,0x0006a12be348d5a6,0x00018ac5d2250648,0x0006f9766dd428e8,0x00000000000fff9b}, {0x000ff89f1b07248b,0x000174b3b10f3ab0,0x000ac70bef37c1ca,0x00011ed5c9e36bef,0x000364cdfcdd2a61,0x000462f54a99a302,0x000b5fdbfbbe7a59,0x00000000000cc266}}, {{0x00081f8725c117c2,0x00037dc9daeefc8d,0x0009cda216a5b4ef,0x0002271ca53d53df,0x00054d1aa50b206d,0x000001e99b054633,0x000aa452bca91088,0x0000000000017fb7}, {0x0007b7c6cf80a17f,0x0007afff3af9472e,0x0007c0765e5ecd82,0x00004be24753989d,0x0006e90950c6aac0,0x0008efe5b4a5de2b,0x0009f9b46af0ab73,0x00000000000db445}}, {{0x000c5196b2aa222f,0x000d15bdb6d3f8f0,0x000389884e011601,0x00008a96ddd9e23e,0x0008467e7577ab50,0x0007555edac1e974,0x000d57e74e35b601,0x000000000009d04f}, {0x00080785cb147efa,0x000908585c6fc59b,0x00035ae9e9b63afd,0x000d1e80b684dd21,0x0009edbaddcc2739,0x000c57660e1ba788,0x00089a464f42059d,0x00000000000a7cf2}}, {{0x0002dd131270b84a,0x000dd412f64a3e09,0x000b9c94f3cfd9dd,0x000cdc2c2e964e0f,0x000d0011cb01fbe6,0x000228f23e9a3b1f,0x0009a16c30762dcf,0x00000000000be919}, {0x000e7d10046b4ea1,0x000b4732711dfdf5,0x0008160cd8dd88e3,0x0008ba0c6eceba7a,0x0001f3c3d31d8ee0,0x000716948b171153,0x000add65060b633c,0x000000000002ff2c}}, }, {/* digit=67 [{1,2,3,..,}]*([2^268]*G) */ {{0x00000725d23401df,0x000096f178dbeb92,0x000498bead595449,0x000b4b459b46611d,0x0007c72b4a58a6e8,0x0005985adafce826,0x00073321142175a4,0x00000000000e649d}, {0x000052db6dbc2445,0x0003a6bf42fe0182,0x000384cfd9aea017,0x000a58acd0291983,0x0009215492e1b0c8,0x000b5a5f0a73ff32,0x00049b895c545eb1,0x000000000006fcaf}}, {{0x000a5a0bc1e856f0,0x000f28baef5de481,0x000a8b075c84a181,0x00058d754c8267b1,0x0005ccf703932685,0x0008ee021f924f79,0x000a4be3763f30f6,0x000000000005c01b}, {0x0006ee7749647d88,0x0008acc01a3e928c,0x000c22c3ac36bfb8,0x000512e6c45e3401,0x00084ef433f61ab3,0x00021f5afa978fe4,0x000a4023e2ea018e,0x0000000000011524}}, {{0x000ecc04426e192d,0x000c692a7fbcd69c,0x000df4111d9bb7a6,0x000db2d02a8feb62,0x0002728cecbe8e45,0x000837662176c0cb,0x00082c33fcfbb0d1,0x00000000000d6f28}, {0x000d967a59df021f,0x000bc75a0f344b04,0x0001f4de7fbff391,0x00090cefa0453b03,0x000ff54c96fbf4ea,0x000f77afc5108858,0x0002fc86b46b5731,0x000000000006bf7e}}, {{0x000215c3f055a1c5,0x0002fe1d42d93e03,0x000c50c3e0aa63b9,0x00098e783686967e,0x000474a30dbf5f66,0x000d20230bb5e159,0x000f8bef86bb5bcf,0x00000000000403b8}, {0x0001c2443b169c63,0x000fbf249aac89ec,0x000e2f941f78369d,0x000960cefca9a90a,0x00088f449c4b3b80,0x000cfe09ef28e338,0x000d260cdfc61bf0,0x000000000008b22c}}, {{0x0001733d4c0dd30d,0x000af7013d596371,0x00017f590b1fdd3f,0x000898e35915f523,0x00039fd967d4bba7,0x00073558f9fbe5f1,0x000bea0aba8344d1,0x00000000000ffeb6}, {0x0009792191976aee,0x0004e928f68cbbf7,0x0007210e163722d8,0x000c4e06abb0ac9a,0x000a6895762709b5,0x0004045a401ef3f8,0x000ac355dbe9f79f,0x00000000000ef178}}, {{0x00094c375a95d7b3,0x000dd7f89c2c3b20,0x000a45fd88318202,0x000e48b12d9f811e,0x000dc7a43dd0be70,0x00018ca3a703ac1b,0x000012a4309a2c21,0x0000000000001943}, {0x0009ce1f49259e54,0x000e6d9597d8737f,0x0001541e69df2d37,0x000760df1561aaa4,0x000e2d91ee39fcf8,0x000bbcb6de1e0306,0x00074699979031e0,0x00000000000cfcc8}}, {{0x0005490cc3cc0b27,0x0002a4073f24615c,0x0003e0a87e36ac6d,0x00006c18fcec6a28,0x0005d75a73f10abb,0x0008c94883a7d129,0x00074165fd8700f1,0x00000000000732f7}, {0x00049117079dd0b3,0x00098d15d8c801e0,0x0009200404155fcf,0x00007c7120e12665,0x0001f42cc9fd9816,0x000a888cf0e486b1,0x000249e606c16c01,0x000000000001ea23}}, {{0x00014f7d981a63eb,0x000cb923e948b882,0x0000fdde16bb34e4,0x000011a6df27debf,0x0001d57f4ca2345a,0x0004196e9ba6784c,0x00026df01b370311,0x000000000001aab4}, {0x000a2240acace9dc,0x000d82ffdc977a4c,0x000a7e87839c540c,0x000c01216f09c1f8,0x000e5b9cc0b65ca1,0x000150569612021d,0x0003ea910e10e95e,0x00000000000e2ab9}}, }, {/* digit=68 [{1,2,3,..,}]*([2^272]*G) */ {{0x0008093fcd51c0da,0x000aaac58c9dfd06,0x00005aab38065215,0x0004afc2cc4252aa,0x000397c2bdf932ef,0x00049e19a08bd48b,0x000496ac8a7803a8,0x0000000000075c31}, {0x000fef0d3072e592,0x00057733dc7dec06,0x000d0f9063e4be72,0x0005b0847be21a8a,0x00055ebf426f6d9c,0x0004e9e5bfab0fdc,0x000089d60748caf9,0x0000000000069366}}, {{0x0000e5d6509e91ef,0x00048b06c17a3a05,0x0001e37973be9551,0x000ae990038aeb31,0x000b58b402ca2440,0x00077732a83bf711,0x000932b8763e00b5,0x00000000000f651a}, {0x000cf91f09ef177f,0x00070be02ab9cf6b,0x0005ba59eb97ec90,0x00072f64283f8100,0x00072365da5e7ed2,0x000dc6beb098cf05,0x000d72d90e6f1805,0x00000000000cf7b9}}, {{0x000bed14c2e5c1d5,0x0009f89b2edba20f,0x000638f30da8440c,0x000d9ce8943fce4f,0x00045a2ff9961dde,0x0006e87feaaf07ff,0x00008c69e60f92c9,0x00000000000b9ee8}, {0x000d99ec41a8cc2a,0x0005279d6d8c67c9,0x000b28385a21a71a,0x0005267350b7fc9c,0x000d8a2abab0c8a6,0x0004faf7ce9fcb46,0x000c8a57c3bfc62c,0x00000000000a8207}}, {{0x000f000e371891b6,0x000b56f101762b79,0x0004acb33b163eb0,0x000e2aaac1dc8274,0x0009f835a1b62c58,0x0009915a451410e8,0x00048d981333a762,0x000000000000c141}, {0x0009810640a6c340,0x000184d20b3d37fe,0x000e4eb008d53e3a,0x000b68c2a2645f81,0x0007add082eaa664,0x0005ff2067a6bc85,0x000fcce7467dc63e,0x0000000000004e2d}}, {{0x0000cfcf5d6b5960,0x000cc57fe04dac14,0x000998e82d998b8f,0x000bd40e0a341ea4,0x000b9c24fdba5128,0x000c1dea81adf3cb,0x000ef2b1ce8520f4,0x00000000000db22e}, {0x000911256ee6f617,0x000b2e9f05f28713,0x0000043d1376f349,0x00052d3f63bfade4,0x00006cbcc395a2ad,0x000714bd81b43575,0x000ca6fd1d7e0666,0x00000000000a40ea}}, {{0x0004ca398c06d768,0x000c23d0efae2846,0x000878540a1ede95,0x0005a253f00eeef2,0x000cd86161cea5cb,0x0004a389ac2f9258,0x000159d2b0865f5c,0x000000000009b1f2}, {0x0008e174cdba2f0b,0x000245a758a60599,0x00087073a8d80dcb,0x0005a4949d301c92,0x00061c4bb89b8865,0x00060259c129647e,0x0007d106f0665ec3,0x0000000000006619}}, {{0x000cae6e407127c8,0x000070262c90bff7,0x000ca8e9829543e7,0x000f8fb1577634a8,0x0004597668ad6514,0x000ff6ecf4678d63,0x000dfc90213b637c,0x000000000007518c}, {0x0005a2999ad1c0e5,0x00071d006db8f897,0x0004562511312669,0x0003aeadf6356731,0x000f1a366456acc7,0x000e73aeaaeaa4fa,0x000a480df51aea1c,0x000000000009a8e4}}, {{0x0001074c67a33fda,0x00086a23545689bd,0x0009b9de484075b5,0x000247b132c568a3,0x000dcc4760bbab0c,0x000ae821b129a5c9,0x000f8303eba46726,0x000000000003df1c}, {0x000f0c5101b30f29,0x0009f010813cfb68,0x000cc25f999a807c,0x00020b31fe4b6007,0x000398dd32399073,0x000abb34cda3bfeb,0x0005f123f1ed1641,0x00000000000946f8}}, }, {/* digit=69 [{1,2,3,..,}]*([2^276]*G) */ {{0x000261be9524972c,0x0005728524830014,0x000a9e4b0c851ae7,0x000fa9900e4f78b6,0x000b54a3f7a33a66,0x00065a79afd8a65b,0x00069a505d3f6319,0x0000000000018914}, {0x000675265cae6514,0x0008278367cbbd6a,0x000c906352414281,0x000b3f6f5af173f1,0x000a5ca36597e41b,0x00099f79557cb03c,0x000ef127f86cb87b,0x00000000000ad4dc}}, {{0x00092527cce78878,0x000b138a49bf4890,0x00076c4f31c0490e,0x0009eca01b2f7c2e,0x00005be8359f5f70,0x000646b3fc479a65,0x00011b6b6a22bfd6,0x00000000000cc5b7}, {0x000c9aa1253a31c2,0x000d18e7dbc638f0,0x00085601e946c9b1,0x0007e04030271eb4,0x0008e22fb3c72d3a,0x000e0d46cb08b597,0x000915860d62789b,0x000000000001d49a}}, {{0x000e171e53bdf97e,0x0008556d65155b11,0x00013206465d7fcc,0x000049f10dfaeae2,0x000ae30b70b8ef9e,0x000c6a56219750b3,0x00002611ed860015,0x0000000000012097}, {0x000714d4a4467bbb,0x000e279559d04c7c,0x000363f176594d50,0x0007323ae8fb3c53,0x0009a4111f88d6fd,0x00010a683834639c,0x000e9afc69a029a3,0x00000000000255f2}}, {{0x0006e6e51e1dd6f5,0x0009766797f569dc,0x0007480d93f86f88,0x000f4a531adb034d,0x000e5d185cfc18ee,0x00053c27bcf1cb5e,0x000569f596a59bbd,0x0000000000069002}, {0x000a4105949da385,0x00053d9433e78e1e,0x00022ac847a15a5d,0x000d7ed65d68ece1,0x0009fb2aded8233c,0x0009b750e201bbe0,0x000f25987f4975ac,0x00000000000337f7}}, {{0x0009f8de8126d12d,0x000626fb6b7bb82e,0x000f3dc00034e80a,0x00089d8316ff5318,0x00079894d65f98ad,0x0002801704800ee1,0x000537034ea3c448,0x00000000000c30be}, {0x00066423e58a8102,0x0009243c2d27d6b9,0x000c30559bd3f060,0x00040105eaef29b7,0x00017b678fc76545,0x0003012701d8f07a,0x00036554bc6f737b,0x00000000000e9473}}, {{0x0005ee6b65e3f046,0x0002a3561b3fe3d4,0x0003adfe7b57a7b4,0x000831347fb79d76,0x0001c48002ed4374,0x00044dcb0a7f497e,0x000e0686221cce2c,0x0000000000043785}, {0x000bdab4ad1119ad,0x000279ee9061f323,0x000458b83a9d33ec,0x000e85b76f7f52c7,0x00090fd6c65f1d8d,0x0001f8a3939a713c,0x00040af74ca06771,0x000000000008ebc6}}, {{0x000c37bd5d97c8e0,0x000841942c2ff6fd,0x000f5c9ed6475a4f,0x00052b5771a5972c,0x0004363c2048f3c1,0x000db8da24cfb1e7,0x00043dcd2ce8249d,0x00000000000a5ee4}, {0x00044b387eb3689d,0x000606fa84b3cea2,0x00069e100b1b94b7,0x00071368e13869e1,0x000c96f0f8a12e45,0x000d93dc039ac6a0,0x000ec9e24458ac42,0x000000000005f60b}}, {{0x0001937d698b9991,0x000c7514cc1dc470,0x0007f6d12f9a74ce,0x00022ac2fc9230fb,0x000d92e23e21f0e4,0x0006d1ac0aa50a1a,0x00049370ac46d867,0x00000000000f9f54}, {0x0006e32302426e7c,0x0002059a6b86a840,0x0004338952e5938c,0x000cff13192968cc,0x00040b342dd8d3d9,0x0001da44113e700b,0x000760fd5dc7bb3b,0x000000000002c883}}, }, {/* digit=70 [{1,2,3,..,}]*([2^280]*G) */ {{0x00067944f366244c,0x000d59e9af31428e,0x0009cbe9f6c4942e,0x000bd92582864947,0x0009b2e09205204a,0x00056b1017995988,0x000f260c727a3dfe,0x000000000008b657}, {0x000fac647b56af7e,0x0004cde35d954514,0x000e44c1af2c53f1,0x000261f36019feec,0x000966511d8ffa03,0x0001148b9afda42d,0x0003e1f63211dd82,0x000000000006f13a}}, {{0x000fe40d0b19b4c9,0x0006a3997900ec16,0x000abf1980c5bfc2,0x0005b0a661f3c579,0x0008aab1292b71bf,0x000d993f244b1338,0x000966cbe80cb9d4,0x000000000002203f}, {0x000fa9a95e9148b0,0x00053bc82a651a1e,0x0005a004b90c2827,0x000c7e7502f0003e,0x000056a38f73a388,0x00087d9b09c704ef,0x0001f393cde8a734,0x00000000000ec11a}}, {{0x0004e6a4ec3efae0,0x000e047fe47986cd,0x0007fd532d6e5353,0x000fa8b9a8671744,0x0000514bf471b76c,0x000dcf1fc9bc87bf,0x000fa837392dce71,0x000000000003ad1e}, {0x0001e59290757ebf,0x000cebbea5a33841,0x00075b7402f28c87,0x0004ecd9b1665aa2,0x0006e329df225b3d,0x000aa808de7b0df2,0x000faf18fb438e0b,0x00000000000dd516}}, {{0x000d8d8f4a6b2b66,0x0002a63f27a255cd,0x0003341f52773d72,0x0007cd965f9ce38b,0x0000635ba3005d31,0x000343662162c92e,0x000ac85259f64ffe,0x000000000008e614}, {0x000a1c59580d5fe2,0x000e397fb55baa90,0x000365cc03ff132a,0x0007325780618255,0x00086c1e6306a57e,0x00067b14c892f6b3,0x0008c5f12e4c0723,0x00000000000c83a4}}, {{0x00040eada4657ebb,0x000e31e6f9a95314,0x000a04269b290326,0x00056256e8b41991,0x000b7a4a53f9365d,0x0002b9b16e1b9c53,0x00070155dc1d50e3,0x00000000000bb6d5}, {0x000b5b1121311bd1,0x000984c270249c99,0x000f7b0846375c38,0x0005b610689902bd,0x000fa4cfc5a819a9,0x000e5b424dd5706b,0x000a87d33bdb7314,0x00000000000e69eb}}, {{0x000fd0482abbdf6b,0x0004f6897401cbf6,0x000652cc2d40814f,0x000b32939e2b43ba,0x0001bf809331e511,0x00058f8f43952286,0x000727815f6c1dc9,0x00000000000c213e}, {0x0009a038bd421fe7,0x0008ceb09ae59065,0x000d25d81924ad76,0x00015a2a20f86c7b,0x00069aa308078f48,0x000758878748a176,0x0003d7f1f46a211b,0x000000000006f6fc}}, {{0x0005626ca6bcb860,0x000ac75ba2f9acbe,0x000c234135494b93,0x0009e0b610d080fd,0x000333a99c2f3c33,0x000580aff614ac29,0x000a3aa5e23af2aa,0x00000000000e1fdb}, {0x000ca5f5b322ee30,0x00065aa603365011,0x0001b05f57ab1134,0x000524456330a336,0x000b9e025aa3a2b2,0x000a0d5cfc396b5b,0x00083babbf77faf8,0x00000000000ea31c}}, {{0x00047a49edb97340,0x0002d300b04831fb,0x0008ca060cb164c9,0x000c5420cc10a74f,0x0004eff9d01017d9,0x000aa12857f637e8,0x000114d732aa1e27,0x00000000000e2a77}, {0x0008fc5f031be351,0x000d262acf1585bd,0x0001b0dfbfbd395e,0x000c5d22e6eb2db2,0x00028d18263d88be,0x000bbd6acaec2720,0x0004c04b687353e4,0x000000000000ff7e}}, }, {/* digit=71 [{1,2,3,..,}]*([2^284]*G) */ {{0x0006ecc79d0fef75,0x000dfa6e19d09c24,0x000097d1dea89821,0x00080950ee527a58,0x000b7c4278a6ef73,0x0000798ff78b7174,0x0000cac133d867e7,0x000000000009e923}, {0x000f7954ffb5e165,0x000877431eeef1ad,0x000728c869881eba,0x000306a8d6af3f83,0x0000bbec076af7a4,0x000257ca3633bb5a,0x0006636d07623e7a,0x0000000000021c00}}, {{0x000f8db3d9e25bfd,0x000ed35ae891ae18,0x00094f42c82c0dd3,0x000b3cae63745c4f,0x0005f218d139c2da,0x000f3b0e255b8c18,0x0003fa6ab039c889,0x00000000000c644c}, {0x0008fe1e4d75d65d,0x000d9c8496f1ff0b,0x00010bc25fdaddb7,0x0008392921149191,0x000fef73f3455c67,0x000fcfb22e962e52,0x0009113818baf354,0x000000000009d4bc}}, {{0x000af695e08e48a8,0x000683a35938698b,0x0003114a51ff94f2,0x0000f82899d204cf,0x0009158780b5fcce,0x0004edd4f4ca4158,0x000c34c28f1bb73c,0x000000000007a6ae}, {0x000b281e555c9d40,0x000676d4783df7ee,0x000d1f8a08acdccd,0x000c2bcdf6d7f923,0x00000f356ca3b7b8,0x000b8e964f0a8d47,0x0000e1229894bfde,0x00000000000d3aa7}}, {{0x000d000279a1a838,0x000b77f1f985b888,0x000a43ce9b20f9f6,0x000930a5188fcf70,0x000ba3a82904b40a,0x0001510273fad79a,0x00017b7bee8d22f3,0x00000000000c2c3e}, {0x0003fdcf0848373a,0x000041fbe06e92b8,0x000ae48de4a30594,0x00090ec2d9cf7a56,0x000a9bd062c5fff2,0x000d353815d0deda,0x000eda080344abd7,0x00000000000f5cf9}}, {{0x00012d81fb28e752,0x00018093526223ac,0x000d23e13369699e,0x000d26ee94c9abed,0x0003a20b52679a62,0x0003d5fa4425b86b,0x000fc68164f9c8e7,0x000000000003b12c}, {0x0006c5fe565db2c2,0x000be6cc34bad21b,0x0002901d6245306f,0x000f50970e4963cb,0x000cf0813b31f80f,0x000f1ab8ee403ccc,0x000b92a72ab5f584,0x0000000000070f15}}, {{0x000e213ed814f6f4,0x00034170098ddc99,0x000e9c62ee04edbc,0x000b04b8660d7749,0x000b5152ad1e35b1,0x0008e92aa8b4b6c4,0x000f4e0b0bd1c24a,0x0000000000088172}, {0x0007445379f53f7e,0x000d513a76898c7b,0x000f4e73336bcd42,0x0004f973dc17e72a,0x00060a7124b24b39,0x0008a372c1b0cd16,0x00003b7549880cce,0x00000000000e7126}}, {{0x00055aa45f74a004,0x0008dc14a3abb979,0x0004a411c66e9f88,0x000f1828a4be08cc,0x0009deca5a89e49b,0x000fbb36be6e7bf8,0x000e57a7326cf88e,0x00000000000c7f6a}, {0x000da2212d19f21a,0x0005dceced37b724,0x00062d313930a591,0x0005b3fb62a62e4c,0x000793e5c0e1a7e6,0x000b8d77382cb79a,0x0002f014c9a99461,0x000000000000b05f}}, {{0x000a2dd7deb1dde9,0x000a831d31f799b5,0x0008e986349103b0,0x000362e52f04d685,0x000921c7b6511793,0x0006f47f65808e70,0x00040533fe9123ed,0x0000000000058f71}, {0x000d5dbe8f1956b4,0x00061821d30451f3,0x000e7b4e166f399a,0x000db145b2048aa2,0x000ed7811330932d,0x0008fd85f17d989f,0x000434032ae4cb12,0x000000000007d1ef}}, }, {/* digit=72 [{1,2,3,..,}]*([2^288]*G) */ {{0x000acb4203cc71b2,0x000a9070d34e112c,0x00047b523d821ba6,0x000f9b95eb8ad292,0x0006a6a45dda269a,0x000df41e0dde0a03,0x000f2aa18b528e63,0x00000000000a260d}, {0x000c22d6a6aefb01,0x000d424a67709f9b,0x0002a9971343d570,0x000e2a1968444330,0x000d131a6cf073c1,0x000e794543660558,0x000dcdb0289c832e,0x00000000000c6d8d}}, {{0x000d86ee6f475d5b,0x000d30ed1082f1a9,0x000a6711ccf28680,0x000ef0eece773534,0x00064bf0c426a35f,0x00011b2fb76adaa4,0x0004d3fbab929aa0,0x000000000009d8cc}, {0x000bb954fd395b2c,0x000dabe6d7f2076f,0x000a4cbdfe911e02,0x000cba5106ceaac2,0x000a45258697c7e2,0x0005945b0fe94528,0x000f7a7109b17d07,0x00000000000cae17}}, {{0x000ce6be22a12c0b,0x0008a6855029961b,0x000a3c801158be2e,0x000d2b4a8e92e70b,0x000f0cc9fca9f601,0x000bc2e96fd02799,0x0009b889f99ca013,0x00000000000ff9db}, {0x0006b1bd37f91ceb,0x000616ae70849faf,0x0005d65bd4da44b0,0x00092a4e0945e8f9,0x0002ecea36f6394d,0x00018a069ddab675,0x000860650b74d60d,0x00000000000ad650}}, {{0x000bf5b4a4380ef4,0x0001cfc1faedb8cc,0x000e6ba03d77f4c0,0x00085456416defe8,0x0000c58653e7f004,0x000f6f99e75de777,0x000c07dd2dcbebe2,0x00000000000d159a}, {0x000c9af1998a9b17,0x000a045dd713c4a8,0x000e1c3678ddf502,0x000756b6b962b38d,0x000bbffd3f0c3f73,0x00008ebae3cb9f53,0x000dbad723c40b7f,0x000000000000c3cd}}, {{0x00003107748ef382,0x00058a804b2f0156,0x000b319b886fb1eb,0x000f4fd353970be7,0x000712854a9131ba,0x0009713983481c8b,0x00094ab0424eecf3,0x000000000000f4ed}, {0x000648ea129bd87a,0x000a992b74ad013d,0x000692f5d2444d08,0x000b28070a5f0c93,0x000b9f5101ca6741,0x000d0f81e46c12cf,0x000288e7014d7901,0x00000000000d758c}}, {{0x0000c39f81600214,0x000686a565269228,0x000c17ee858626b0,0x00011a7d8c6ddb92,0x000b2332347b0bda,0x0009dff48b7ebfaf,0x000c83cf791881e9,0x00000000000dc357}, {0x00082704ffef2257,0x000fe2a264f8831e,0x000c9352584eb7a7,0x0008260bb47d4188,0x000c3d8170326d47,0x00005f901544de4e,0x00063cac7150a9dc,0x0000000000075c09}}, {{0x000bcfd07a0f22c4,0x0007c58805ca858d,0x000b1c2b2351e4ce,0x000c9a1349cfed00,0x00017800a980f9cb,0x000847e9d67bc7b4,0x000c48e7e6dbc0f6,0x00000000000af379}, {0x00047d63263e04cc,0x0003c80b6fc048b9,0x000808eb22fe8f7f,0x0001ed14e9dc24bc,0x00073fab87e6d2d1,0x000c630ae48d74f1,0x00020a1feca5af50,0x0000000000062d06}}, {{0x000e56ad2bfbbdbc,0x0008ff6377e3bcab,0x000f30b92835c3f0,0x000ac42c21c0cf1e,0x0009857d8edb7f85,0x000b77ed67a3e31c,0x00010b2eb1076327,0x0000000000038dae}, {0x00026ce2d0dbce6d,0x000dced7c6fb0aad,0x00066cec0d07ac1c,0x00035504569e7309,0x0007bedae3ab4dc4,0x00027e463aa82fb9,0x000a1106d37bef4f,0x00000000000f0c35}}, }, {/* digit=73 [{1,2,3,..,}]*([2^292]*G) */ {{0x00011f784b3a0046,0x000066edf5561b45,0x000c8578d54224c1,0x000ae56d8d66d29a,0x000ae9d58eb27699,0x000f9176d5f81602,0x0003b1d0c04874fa,0x0000000000052315}, {0x00067980492adf03,0x000309690930fad0,0x000146ea47ef3788,0x000725873bcba90f,0x000de902e3292d0e,0x000bc27b957efe72,0x000c093fcd598676,0x0000000000093940}}, {{0x000cdd973668c530,0x00077c68b641e912,0x00064e1ee190b62b,0x0008cbad89ce6688,0x00006c269d8eeda9,0x000f3402315f84dc,0x00034af0eb685ecb,0x00000000000c0326}, {0x000bc909db075650,0x000562e3d7fff094,0x00012e59576050a3,0x000abcfa3e050e0c,0x0007c001dcd9f02c,0x0006d2d52ccd2da6,0x00041f50aa372306,0x000000000007224a}}, {{0x000ec1f1185b9762,0x0007e4b1f8698c94,0x000d0af36ed765ea,0x00049f56536e156a,0x000109c95a75ba1c,0x0006d9af131c3163,0x0008b7268a308f0a,0x00000000000fa9ca}, {0x000f13b9ac944487,0x000b1c3b1cbccb86,0x000446bb4e60be0c,0x000c7b334396850c,0x000a048a69431b4e,0x0005820bf42f21d5,0x000a580bf948f55b,0x00000000000b48dc}}, {{0x000b86ea9a29c966,0x000cd04418b58cb8,0x0002d1612a6d4e73,0x000e22c7c65a6da4,0x00051dbeffe45f87,0x0003cc05caac7106,0x0002c4ff619d64bd,0x00000000000e65c9}, {0x0002126bd4b5ea52,0x000d123af2b21062,0x000e0691b9e9f16b,0x0007efac6478c561,0x000af6cd140ec34a,0x000a0db2e57cde95,0x000b7664b74575f5,0x0000000000075d7f}}, {{0x00078c972345257c,0x00058a9532cb266c,0x0002b89ba64976de,0x000067545b1733a4,0x0004cc6e65dd74ea,0x0006ff2aa7f37f02,0x00079e6612b1425c,0x0000000000030374}, {0x000f1ac7f7aa2f0c,0x00097e512bca4fe9,0x0003049963042b95,0x000bd29a259d6515,0x00077373034f5b97,0x0005aa640215eb65,0x0008b779da0fc488,0x000000000007e435}}, {{0x00041294c6ef7a53,0x00023ce3cc51372d,0x0009af7f675a386a,0x000d981efc9f71b0,0x000a20bea9baa9e6,0x000ef7c1fc01ded6,0x000a5cc4b7e6424f,0x00000000000f9dec}, {0x000954a122b474b3,0x0002aa0a43d0a3de,0x000a0d55c109a592,0x000a173b5d57bbf3,0x00056299978197ce,0x000ca2bb13c3f30f,0x0002e069a7820a8e,0x000000000000ff69}}, {{0x000deeb8201c384c,0x00029aca3f998176,0x0001642e9c9fe922,0x000dbd63d82750be,0x0002faa3400be031,0x0005fd54bfb2552a,0x00030374e9b5d365,0x0000000000035894}, {0x000839a12661f3f2,0x000a15a575a4221a,0x00056e3aabcc078b,0x000ada596e1e1175,0x000d0f305dc3ca6f,0x0008d7af5126e9af,0x00069391da8d7305,0x00000000000d8353}}, {{0x000cb9cfccb5f12c,0x0002c28405061c1b,0x000211e4805b5eb0,0x000944405547f7c3,0x000d3441e472789d,0x00044ce877fa445e,0x000d14feb198254a,0x00000000000129ae}, {0x00073247d16dc8ed,0x0008622b05de2de2,0x000590692ea55dfa,0x00052caa83f7f094,0x0006cefaa757fba2,0x00017d8060f6ad6e,0x0007ade1ad187165,0x000000000008e9d9}}, }, {/* digit=74 [{1,2,3,..,}]*([2^296]*G) */ {{0x000c5ac4350713f2,0x00062cbb991946e6,0x00025875bf6be408,0x00024aab6ab6c041,0x0000bc41f4b7d50b,0x0005496cf419d281,0x000ac0e2e88d7a29,0x00000000000f2457}, {0x000a357ad05dad34,0x0008e838e4a3533c,0x00068ef45f1df4fb,0x000ab1c7a5c5fdd4,0x000dde34cb8d9fa3,0x0009105fe324798c,0x000249bfa5a9d088,0x00000000000fd0df}}, {{0x000b286ea52474ce,0x000419974759bb2f,0x00039b1e3f8aef8e,0x000c58ec64941cb4,0x000a01d055758afe,0x000448db52d7c57f,0x000440c07c74cc5c,0x0000000000001bb1}, {0x0007977c86a9c43f,0x0003893162d96796,0x000ee52587841e45,0x000c57e6af18dedc,0x000f174a30894f28,0x000dd626536faed8,0x000d7b702dbd64a3,0x000000000006adc0}}, {{0x0002a70e7d991630,0x000854981be688ec,0x000de0f53a95f8f1,0x000e05074cff00d2,0x0001b52c7f9c3168,0x0001c7986111150a,0x0002ad0db2ed84a5,0x00000000000e6127}, {0x000c16b3e4d1fe2a,0x000897443d935440,0x0002c51d6c8aaceb,0x000ef4e866b5e41e,0x0005b965a67071e0,0x000e1aa7705c57a4,0x000e3285bdb58c70,0x000000000009df3c}}, {{0x0009a11de31a0e3c,0x000c6c41e4aed12a,0x000342590d5103b5,0x000ab7b8ed812d38,0x00081afb58b8f5ea,0x000efcc3a7801fbb,0x000b91be5cdba671,0x00000000000cd10c}, {0x000761b96524aa0d,0x00013882e821e20b,0x0008d1b11d20578f,0x000de2bd8a0f0393,0x000c857fd3a03afe,0x00060f767e20a117,0x000da1ebaa2aa430,0x000000000002b9d1}}, {{0x000d9fea4e493f3b,0x000e070e478fb44f,0x0000254b6a02edec,0x0002b005be36ea75,0x000f6717e06aaec8,0x0008f197782618b8,0x0000d12db1f6d400,0x0000000000016b39}, {0x000ddfa794ec9644,0x000bafe86fd4d041,0x0006bc15de0d2bf6,0x00023e70c0491593,0x0005ed4562356cbb,0x000d836efd05be7e,0x000604601374069b,0x0000000000032e5f}}, {{0x0001ebab46405b61,0x000f009db138cd2b,0x0009fd7df23c53c0,0x00047794feebab9a,0x00017fdb1e710bb6,0x000f1f65dfce4aee,0x0006cd7d5c0c61a7,0x000000000008d02d}, {0x000621234d968fad,0x0005c7cac0485224,0x0002b8dbf87d2555,0x0009a59db0aa864d,0x0008ff94f8b5b587,0x000c97f8e75f391b,0x000232a6c994ae49,0x00000000000d690b}}, {{0x000e6486f79bfa96,0x000e507c60c742b4,0x000d5aa8cb9b07e8,0x0000a09dcba89982,0x000a802ce50ca8b0,0x0002144b0a77f1f3,0x0000db6c4050df2a,0x00000000000ab1b1}, {0x000a93fc6ce00720,0x000e89025d46fd65,0x000c1e4037fdb9f5,0x0002d629ae2d5361,0x0009eff0f6a9bcad,0x0005fa5a07a15282,0x00039ce87345cd92,0x000000000000e840}}, {{0x000cab548e246919,0x000d15017e1454d5,0x0005f67186d3e9b6,0x000059dfa98234b5,0x00099985af982541,0x0005b7b1c4bf344d,0x0001ad39737ed67b,0x0000000000087c41}, {0x00069e3ff4c10920,0x000022fad8cecc3b,0x0008e45c000ca718,0x000d856404043f8d,0x0005863927a11a53,0x0008921216c1f07a,0x000c8f38d3a4f4b6,0x0000000000001976}}, }, {/* digit=75 [{1,2,3,..,}]*([2^300]*G) */ {{0x000dd4906efe62a1,0x00063bcc8842253e,0x0007a247757fdab1,0x000a1ef2571d6b1e,0x0001739a956e745d,0x000bffc16f01c292,0x00072ceffd8065e4,0x00000000000f36fe}, {0x000478592361b14b,0x0003ff49e90d1ebe,0x0001338e12b047f8,0x000b583b7240d91d,0x000c03f8387fcb78,0x00000f2d92e1a7c3,0x000a8416566c2232,0x00000000000aaf80}}, {{0x000f32d335de93bd,0x0002d7a1a522aee8,0x000b425f9e81403f,0x0004abe3d4ac4abe,0x000337f996e841bb,0x000727761c52950b,0x0007d201d991e679,0x00000000000978fd}, {0x0006e2e2907ff054,0x0007486bad5e5c68,0x00010431aa78725c,0x000eb7705757453a,0x00093939df7758ff,0x00078ea0fbb18612,0x0001d3bfdd394a6a,0x000000000006e33e}}, {{0x000c3ccc7d56f63d,0x00076db1cffd2381,0x0002131b488cf4cf,0x0001e5aa3c1db85a,0x0001ac55d391a418,0x000d270d0e5183e5,0x0005462793d5efef,0x00000000000c0631}, {0x000c80c1d49264dc,0x00008ecb40a58378,0x000aa60ec18fee5f,0x00014ab6c5830fab,0x000ca03f201ea89b,0x0008c54f64dc477d,0x00066e5604f5dac8,0x000000000002acfc}}, {{0x0003e9c742a5516d,0x0009da7f29531cb5,0x0007fe865f9eba30,0x0004ce9efae348cc,0x000cac52758dd2f5,0x0002961a45acb931,0x000fe1287b3e18d2,0x00000000000748f8}, {0x000f0554bb131f76,0x0001d1b62b340cc5,0x000b08ad2a8e1d6a,0x0008dadbe8da8486,0x000954f18276bad7,0x0004bfdad85fa710,0x000237e2cc9d287c,0x000000000002c75f}}, {{0x0004d2c2f1f927d3,0x00033283dd7ef2a5,0x000a91f40054b9d9,0x000c095870282aba,0x0008f4e36324ba08,0x0004cecf2b02b00d,0x00024e53aaddc060,0x0000000000084ddd}, {0x000a889fa3214142,0x000ca34bc00a03f8,0x0000c263c00349e0,0x000eaaacef68f74d,0x00023c0293515228,0x00042e3b740a790d,0x0001e0e0e9af5c84,0x00000000000a9f14}}, {{0x00087ba6916bcaca,0x0005bcdcdd7d6721,0x000b58247a460e0a,0x000c569c00ce5c40,0x000fc589d0c75923,0x000fa6fe6099c17f,0x0008c40335eeea89,0x00000000000a4e86}, {0x000a7415516e07c0,0x00024b7037325a9f,0x000944c467e9c1bd,0x00032efd5e26d28a,0x0008de919cbedf31,0x000bbb18d7ed994b,0x00050812df67cd6f,0x000000000006baff}}, {{0x000c3f58ee594ee5,0x0008b72f4949e0b4,0x0001e5bef192dfaf,0x0004726092a58066,0x00010f5cdb7271b0,0x0004bfc49ad5c3c1,0x000be7d4951f9e55,0x000000000006131e}, {0x0009f77a3840f92f,0x0009237da59f303d,0x000ff0c06b034503,0x000962a4d89fa660,0x000e71d824f5d020,0x000050e312610c61,0x000bfb9c917da73c,0x00000000000e6e7e}}, {{0x0003a9eb85c489f9,0x0003af2ec9ef5122,0x000d827990bab108,0x000b2387d2ac6e41,0x00020318a3b790e2,0x00084a7a0cf682b1,0x000d057fe76089ea,0x0000000000016546}, {0x000bc6c0a0421345,0x00041f987118eca7,0x00079f0cde4a8da9,0x0007774888a7e8d0,0x000a63ec5831544c,0x0002fe985bd2647b,0x0003e8b479cea3fd,0x0000000000028d16}}, }, {/* digit=76 [{1,2,3,..,}]*([2^304]*G) */ {{0x0005b08a8a2a82b4,0x000fa04baa17598e,0x0006a0661405c62f,0x000031dc6cd61096,0x000030bf87a5c4a6,0x000e497ccba2534d,0x0006657ebc6e2131,0x00000000000851fd}, {0x00018d257f3e221b,0x000e69ecae010ee2,0x0009788f9b15d390,0x000a9c22fa527837,0x0001236d442e39e8,0x000c289ce74c9380,0x0009cf8b21ba23b1,0x0000000000025c76}}, {{0x000aafc618669c84,0x00037761e10e2b1a,0x000c03aea1a1a99e,0x0000ff43dbc6fcaf,0x0006cbe0ba8aa087,0x000f1ff6a9765128,0x0005b647d46075c0,0x000000000003abeb}, {0x000f7f59840e13b0,0x000af1234c80e297,0x0000d9f885a37dab,0x0002d41d82ab780a,0x000fde426e50399a,0x0006dde778a03afa,0x0005eca2bcb109ca,0x000000000000618f}}, {{0x000adbd12143606f,0x0003e0d27500f7d7,0x000cde21714cb370,0x00078f8610763e40,0x000f47ef08feee75,0x0007d04c06e56078,0x000aa3a8d03a7f04,0x0000000000027cc8}, {0x000677d27af9cf4f,0x000056b08eb37c00,0x000a4a2b5d3fdd3b,0x000869ae3f10ba99,0x0003e500e8466f9b,0x000171b1a3bfb983,0x0000456d975557b9,0x0000000000018fa0}}, {{0x000e348941e625d9,0x000fc15d47e52aa7,0x000dc7038ccf5369,0x0006a3070cddb11e,0x00032b5a8db75122,0x000f37d6563a253d,0x000b91e8be4d1fbe,0x00000000000c0920}, {0x00045423a83becc9,0x0008308b713a8319,0x000ebb9d576c8cba,0x0005877917ee393e,0x00091528cd12a897,0x000daf6aa294792e,0x0009b94512dc8c37,0x00000000000197a9}}, {{0x000e5d8cfc9c3b49,0x000e0cfebe026cd6,0x00010748e4a52d81,0x0009d16725ebd099,0x00007a584e8d00f8,0x0001cab5894c6f2b,0x0003c8095ac9cc91,0x000000000009c407}, {0x000462695d0ed83f,0x00056265919b06a1,0x0003cfa033d1cd2a,0x00097f1815a70aa4,0x00001c5fd35a6db5,0x000d52a8bdd9e4a1,0x000fab38b8e35112,0x000000000002ef20}}, {{0x000003aa77fd8f2e,0x000b43b21dc1edb9,0x000008b1e2380339,0x000e5d30da87d664,0x000f0cd999a0f536,0x000e08f5d4ce10ed,0x0007e68949181450,0x0000000000052664}, {0x000bcdd23ee4cc2b,0x000a3cb207ee8e61,0x0002ac9dd73c4f6c,0x00040d225e0cf154,0x0001067fa0527d49,0x0008b2e21b688b31,0x000eab89308326a9,0x0000000000072311}}, {{0x000c6c4de58ef59c,0x000db2a6280408d6,0x000f4e9cd796cbfa,0x000daa3c647fcba8,0x000f4952d3a44a2c,0x000e2e2c3e1a9e91,0x00040ebc1b3d8011,0x0000000000018e43}, {0x00017ee00926dad8,0x000cceb8696ff13d,0x000436379cf7b867,0x000d6ce6c1e905c6,0x00091ed2e8cba471,0x0007c8c914e13d60,0x00084e52951509c7,0x00000000000e2348}}, {{0x000a3b1514eda4ba,0x000ac37be5d3f53e,0x000cab6203ce338b,0x00024b59d1569e7a,0x0009b4e293ab165a,0x000b7c0a4254aaf5,0x000b183c751fbd6f,0x000000000005018c}, {0x0000fe7bbd1e6c72,0x000eaacb3b8965e4,0x000a2f2ab6db69d7,0x0007258621df6d82,0x0003185f0e2a245d,0x000ddbd812af0e28,0x00002a1e7edc818f,0x00000000000c538d}}, }, {/* digit=77 [{1,2,3,..,}]*([2^308]*G) */ {{0x00042da90721f8f9,0x0009f6858b6747d2,0x00082ecd0813dd9f,0x000674e29d9194d6,0x0006dcb30a51324e,0x0008aa5492dc6fdf,0x000a923f3ecb7752,0x0000000000023ffa}, {0x000c7344981b01f4,0x00090d8efcbd58f8,0x000d0144b46e312e,0x000b0b74cf4a1708,0x000fbbf335fd04f2,0x000928c36bc0bb49,0x000d45c6b6e5bd5a,0x00000000000d893d}}, {{0x00016a2799bedc34,0x00022fb083c2a5e5,0x0000296a1d9c8cea,0x00030e747a81b965,0x000658a987376e41,0x0002829c9cd704dc,0x000d63842ae32959,0x00000000000be20d}, {0x000f531daa9bdad7,0x00053abee8e552a9,0x00078232300aac8e,0x00039b2467112ba1,0x000fbe341038781f,0x000a2f8be6f06058,0x00066e5effdca512,0x00000000000af344}}, {{0x000afa3ee32c886c,0x0006d3933b4c0742,0x000439c40f3f936d,0x0003c0f0b7e019e4,0x000fa48715d652fd,0x00039be537f8e5dd,0x000cdc0879c5defa,0x0000000000056f01}, {0x0005bfa2d160b7fa,0x0004671b2dcba45c,0x000e0bb6fffdcb60,0x0004846640b2d753,0x0000049a2cbe6af9,0x0002ab0f178a1071,0x00043841a1ce67ac,0x00000000000a76d8}}, {{0x000a317691072fc1,0x00025ab86639e0b1,0x0006a85f7a13b8bd,0x0004418d763f0bbd,0x000211a9802cb573,0x000269b8ad2cc332,0x000355e41d7db881,0x000000000002ecfa}, {0x0004e57bc1e94af4,0x0006159d6912442e,0x000356e842631b03,0x0008b6b8a7397395,0x00091cc83ae38447,0x0007ccd97e86ad7d,0x0004c6bc9b208479,0x0000000000069494}}, {{0x0006d3d1d84bf486,0x000a4bbb6725a843,0x000b1260c5ec574a,0x000dd0664bcb2d64,0x000a780d5c1bab65,0x000a61e6e755e848,0x000b4b84e6f686a3,0x00000000000bd100}, {0x000cfe4a11d7ea4f,0x000a3b34fdf84517,0x000d9afd2967c440,0x000c881f9a125f0d,0x00064aeadf8e3c2c,0x0006bf0c2b1fcce5,0x0001bebdfc54c0c4,0x0000000000009d28}}, {{0x000af84d84069bc1,0x00010e1aa844a91f,0x000628bd439b9e84,0x000aba65ddcb5d25,0x000a38009c6a3025,0x000261ee5ac8cdab,0x000430b9ee07b46e,0x0000000000006ab8}, {0x0003196ba81697a7,0x000207a36b461d0a,0x0005a884d3b0fe10,0x000f469341275a1d,0x000f1c7cf858ae4e,0x00092af3df7cb393,0x00017683c00eafd1,0x00000000000a1e15}}, {{0x000475d9329b61bc,0x00078687d0980c72,0x000d109af3ad73e4,0x00007fabbcde5b3c,0x00016ed103a56414,0x000a6ee2212ec9d2,0x000c11f858c7851f,0x00000000000818f2}, {0x000247f6c002433a,0x000a04720d42a19d,0x000f64099b42a8aa,0x000f25533723e4ef,0x0003d3260b6299af,0x000391c33d6c67ce,0x00038163a6fc9d86,0x0000000000031de2}}, {{0x00092324c0c2dff4,0x0004f585edee2c89,0x000820f42406ab00,0x000924fd85ad3203,0x00019124bffa3bd7,0x000c628682e7d8f9,0x000f5d885397c044,0x000000000007fda9}, {0x00035c11900b0d2c,0x000e6d302582e314,0x0003e1f066fcf73e,0x0006b5b63653c06e,0x000d9c70dad4b021,0x000bba93d8f08a1a,0x0002b7ccf014aaff,0x00000000000a33f1}}, }, {/* digit=78 [{1,2,3,..,}]*([2^312]*G) */ {{0x000cb198f774dfa5,0x000dd1e347819af2,0x00020411ce747fbb,0x0005ccc28af85bb9,0x000b3ae9ba11fc18,0x000bdb313c923d78,0x000b877d494d7ea7,0x00000000000af8f8}, {0x0004fe8c8323652c,0x000bdc178ccc093c,0x00006a94572bacfb,0x00047cc80a50372b,0x0000e6f901976087,0x000c2f2168147aa9,0x000b514683d4c978,0x00000000000552f3}}, {{0x000f8017d10c6b96,0x0002229d81537326,0x0007f1980aaaed23,0x000ce6e8783d1fe4,0x000df0e3c126aa4a,0x000ca4b719c14ebd,0x000f350eb1c08d6e,0x000000000001c91d}, {0x00013bd5d85a7c75,0x00064db8119bb0fc,0x000fdf5036f03e4b,0x000916835436f82c,0x000b9b18d212053c,0x000bc3497eb41ccb,0x000d8193b3fb43b1,0x000000000008c1ce}}, {{0x0007ad7a8ff88fe5,0x00031521f4af6aed,0x00033eaf4c7af196,0x0009ab7ae0377807,0x000db65f73ffad09,0x0006059b9541cadc,0x000f8253430463a8,0x00000000000043e9}, {0x00061f938516beb2,0x0001bd515f4c75f1,0x000d0a9d767932f1,0x00053567ef1b9007,0x000f1295b5fe7bed,0x0009176278782b45,0x000d9fab54ebaa03,0x000000000008787e}}, {{0x0006f626b572390e,0x000905255508b5c5,0x000fa6a60258070c,0x0005eea3095205c4,0x00002c470ef7d976,0x00040bf0afea2ed7,0x000a16f5e8a0fc9c,0x00000000000e4137}, {0x00055209e40da33c,0x00003b917537047e,0x00003ab2893cdb40,0x000bce9023854871,0x0008a8bc3a94bea6,0x000c450444620840,0x00015164a87a2a3a,0x000000000007df70}}, {{0x000cf2f10b0520cd,0x00004c38d07270c5,0x000e4dc64fc6cd1a,0x0001d8f300e953df,0x00040a7dce63abde,0x000425847b98b23d,0x00061b63e51543fc,0x0000000000043a21}, {0x000d54e8ecf42bd9,0x000ee2650a1d5920,0x00086c043a07e5a3,0x000b7048bd9bd78b,0x000df89e86bdc15d,0x000579426bad1dba,0x0005f8d7d4845024,0x00000000000287bf}}, {{0x0006ca98107f85ef,0x000615fb05303f18,0x00091aa7ab0bf32f,0x0000fa47d92132d0,0x0008994564bf7a0a,0x00029e066e993faf,0x000574bf30252517,0x00000000000d4260}, {0x000990cf5caa4f19,0x00009f1eecc3d948,0x000f8dbc962efd6e,0x0001cf1d1dd88736,0x0003b6f1aae115fd,0x0009344b97ce882a,0x0009ca7efb7ec6da,0x00000000000cc5b5}}, {{0x0003c28364de2038,0x000c48bcbf6cdce6,0x000e355114722287,0x000febf92ebe1bcf,0x00019af24c2e4ee8,0x000a861d57847829,0x0007ec618760b094,0x000000000006bae2}, {0x000de113e64c1ae9,0x000fc77c174b9e18,0x00055d1ba670f4b5,0x0004f6a58a0062c2,0x00047781acd1db9e,0x0006d86b03480c9b,0x000ef52d7c628ef5,0x00000000000b3e2e}}, {{0x000ade0c1eab3d7e,0x0000fee9e25d91a6,0x00060f30210199eb,0x0001157d2d91300a,0x000fffcbe50fd2fc,0x0001d376ee7597e2,0x0005624be3814fe1,0x00000000000dbf14}, {0x000860a341c4b797,0x0005638a107c07ee,0x00045c1dbdbe39f3,0x0004e09caebd481c,0x000bf9ace60d1801,0x0001cb8e7b28c331,0x00065ee8fba04f21,0x00000000000e42dc}}, }, {/* digit=79 [{1,2,3,..,}]*([2^316]*G) */ {{0x00060f98795275e8,0x0009d009dc2f44a9,0x000392d1d1132d95,0x000faa2ec5d91fec,0x0000f160afcbc89b,0x0007566b5461be9a,0x0009a2fdd084bb7d,0x00000000000e4809}, {0x000f69da99c8ac01,0x000bd1b461fc964c,0x00012ac0cf0d2b27,0x000332d9f09a206f,0x00036941d6ef3246,0x00087f5f6bde4c0c,0x00040044ef03fdf3,0x0000000000057b63}}, {{0x000b480bf51dac8f,0x000ea7e485158a07,0x0002c9e9ee8b46dc,0x0000dafa6fbabfcb,0x00038f09fff720de,0x00006994f04f0158,0x000d335a0562976a,0x000000000006e3cc}, {0x000d89d62ca77de2,0x00045c087ef9c0e4,0x000f0235509703e4,0x0004814d916ee937,0x0008d23d140b4fc0,0x00062028f3369c97,0x000adbb0fcd70f16,0x00000000000e1e28}}, {{0x0003a6684cfed7ee,0x00094e3ccfe8dea6,0x000d721274c869f9,0x000e2cbb605c4274,0x0005b0d809923f13,0x0009913815ee1239,0x000b6e4dcaea94b9,0x000000000008c4c4}, {0x000ec88cc6307d53,0x0004bd7aad54ab94,0x000859bdd379b119,0x0001eee68048fd9e,0x000fd57225fc6eb3,0x0008dfd3f693842d,0x000cf13e62cd85a8,0x00000000000d5462}}, {{0x000df1c3e7de2ba1,0x000ff99b5f14f615,0x000c00e1f8e35232,0x0003900ff19bf251,0x0000260925ede749,0x000ea1eafc82e5b8,0x00021e3398d340c0,0x0000000000012871}, {0x000896ddafdbd954,0x00046ea6dfb0ad7a,0x00039aa9f60646cc,0x00078bf1201299a2,0x000d32e5cebce266,0x000181e32b5369e4,0x000add2304eac86d,0x000000000003d364}}, {{0x000f357cfbf02e91,0x000a2f55f868d743,0x000049d92d19de08,0x000ff9bbb5ba194e,0x000957724703bec0,0x000e0e4fbf7325c4,0x000d7c5ab8f06323,0x00000000000ecb0f}, {0x000a0f97049bea9a,0x00069cc72e8da9e4,0x000c7a0fc237673e,0x00046e64252763c4,0x000eb8d81de3bfa6,0x000772f007a769ef,0x000a5ef5ec70031e,0x000000000002729a}}, {{0x000cc742f063ab99,0x0003b51f19bb30d3,0x000878f139d45b8c,0x000de2f987112cb9,0x0008759de2cb5f7c,0x00049bd98dc51d94,0x0001fd9d05c410ed,0x0000000000036434}, {0x00020d69ae77fca8,0x000a9d7869d68233,0x00007a8daf0bfe29,0x0008180c25910747,0x000a6ebc4ebc7f25,0x000da1d687b90fc7,0x0004935565390f3d,0x00000000000a44e4}}, {{0x000116432be8131b,0x000ebb4a2742da3f,0x0008bb7a8fda7aaf,0x000adccdd7fcf4fc,0x000337d4fcc6b15f,0x0001c7ab70b1fa2b,0x000cc9242c7b26f0,0x0000000000050574}, {0x000069eaa2593652,0x000b76ee50f421b3,0x000a5035e1a2b7ad,0x0003af18420501c6,0x000b1b6e7d2a04d1,0x000516f80c22e092,0x0005b5a393be7ee9,0x00000000000b80bb}}, {{0x0003f2ad59508de2,0x000bd9e41b9b6b62,0x0006d3eb906556a9,0x0000c8cf272346c8,0x0005def5749367e5,0x0002676fcc98a5ef,0x000659c2dea8afa0,0x000000000006ace4}, {0x000f1f5cd12db7d7,0x00090c2b707aa093,0x000d4cda421d1577,0x0000fa2a778c20c3,0x000d57af166b5b58,0x00078ce62272c3a1,0x000087e47a64a9ca,0x0000000000071d35}}, }, {/* digit=80 [{1,2,3,..,}]*([2^320]*G) */ {{0x000e3ee1ae74a706,0x00069c20fb9106bc,0x0005cf0e923045cf,0x000bc6a5cc0aa89b,0x000b4fb9f01e12bc,0x000ae1b895279c6a,0x00003cbc8e178911,0x00000000000c2900}, {0x0006736dff18cbd8,0x000579949d6eb7ac,0x000931ae3b95e19f,0x0006ee2dd2275c0b,0x0008c419f1d568de,0x0002b5a40a9e4fff,0x00096dbc759ca4a5,0x0000000000063b09}}, {{0x000eafd50b503ff0,0x00058f682715078f,0x000b7ec2b450662f,0x0008f55c51916c40,0x000b61ee081fa46c,0x00064872a98c3524,0x000faa5ab7f2c2ad,0x000000000007e555}, {0x000425ebf2c1673e,0x0003c802e0d22c20,0x0004e9f77f229a7f,0x00019087af20d270,0x00016be50784b56d,0x00072b8518d619e2,0x00076e10fdbb7213,0x0000000000049355}}, {{0x000df2627e9f5583,0x000e073c57fde593,0x000f9da9fd5339d4,0x00071f1cfb9821f2,0x0009cf6a1d68d25c,0x000d24e649427e20,0x0008b5bf3c3916ac,0x00000000000bda7b}, {0x0001a88dfb057584,0x000e2e7c5f7c7d49,0x00071c4b5c378478,0x000c472e66b277de,0x0007b2816f1e818d,0x000383c6d4413fd4,0x00053740f262af48,0x000000000004f190}}, {{0x000aa901e2868cf5,0x00009d97a9b136f1,0x000f9d37eb7a3b6c,0x00060c2548188194,0x00061d59be44c571,0x000f2b2474dbdeab,0x000b33b93a9dad81,0x00000000000ecbca}, {0x000a766b5fedf0a6,0x000ce5e1ce82823b,0x000997bad589b344,0x000273a2d82b0df8,0x0006ac8ff52fe716,0x000ea7ccdb017f5f,0x00074b7563e79970,0x000000000003f0e6}}, {{0x000fda8d824654de,0x00033487edc06864,0x00024946c59b50d3,0x0002bea10fdba0ce,0x00052c3dbf337fc6,0x0007d2a46c836bbc,0x000f714fdfb5c34f,0x00000000000dca0d}, {0x00024bebc7614440,0x0007730a0767544c,0x00067fffd43f5d03,0x000d49dfacc13dc4,0x000aae1a261ad307,0x000d98650148d673,0x000fdee008f95b52,0x000000000009f558}}, {{0x000015df21e067c3,0x0003dd084564b8db,0x000d0b4c4a73b501,0x0004bf63bc7206d7,0x000ffc3d577224bd,0x000c4924fdd37b4e,0x00096e8156d6f635,0x000000000001d1d3}, {0x000ca9d7511fd3e1,0x0009d977b3b3982e,0x000fc4c09646cd37,0x000f9c4ae811d70c,0x000ca06c7f0de581,0x00049d87fe5441d5,0x0009bb0275c92b19,0x0000000000078046}}, {{0x000cdb7d87948ad3,0x0009117cd6af6151,0x000e60b294f18979,0x0005b1d788224330,0x00031b9745257e49,0x000f3ce21fed338e,0x000896527743d386,0x00000000000b515c}, {0x000e2d7dc921023b,0x000d19fde7038e85,0x000c1b9c9ba2d99f,0x000600b36ff74dd6,0x00048302c3c95d46,0x00044b5eb8ea74b0,0x000402d560f570f7,0x00000000000fe762}}, {{0x000cf97b63daba80,0x000eea7f8501424f,0x000f397f945052f2,0x0006b8a2ad5053d9,0x0003fbcebe43c658,0x000054f1688c09a4,0x00047fde7f2a4a20,0x00000000000bbbb1}, {0x00041659e06114fc,0x00075087e48f29cd,0x0009df479d6378c0,0x00002ff7f27cac87,0x000c37b1f6e18ae8,0x0006d1deab01a131,0x000f803f0d4c2e9a,0x00000000000e7cee}}, }, {/* digit=81 [{1,2,3,..,}]*([2^324]*G) */ {{0x000643c3f46ade04,0x0007aaa03b473d97,0x00091126d04a500a,0x000ef86f37b57bd6,0x000b2a6371d2b286,0x00077ccbd95b797e,0x000a6da489ef8940,0x000000000008e99c}, {0x0007980fdcec94f4,0x000845cf9e236463,0x0000b4681fa85d18,0x00023b6ba7ba4781,0x000757de30bf3295,0x00036ca01d406ab8,0x000ac5aa10e4a215,0x00000000000dfa7a}}, {{0x000146df48d94f2a,0x000a9762a5eebd68,0x000728ae94bf3482,0x00034aeaa4f964b4,0x000ed6526f010fd5,0x000d71d72cf46648,0x0008eabc62a54a18,0x000000000004f848}, {0x000d9dd392598cb3,0x000a262c40de70e6,0x00099451ce04b75f,0x000d7466ab190976,0x000b2dd1ad3d3a51,0x000f88078f07bea4,0x00035d2a0ec4672e,0x00000000000664e4}}, {{0x0002f7cfce391389,0x000d017c563bd4e7,0x0006d61076868226,0x00049ac4cd1bfc15,0x0000d4e53d3b591d,0x000079a6ed446551,0x000eb4ca95ccf6ad,0x00000000000b5ea6}, {0x00099522fba1cf25,0x000cd600ccc9ba8e,0x000c729701bdaf25,0x000edc569c6c6e81,0x000a586abcdc5f27,0x000dbc5b6b3fc0f4,0x000fe0dbfdf3f985,0x000000000004ea80}}, {{0x000e7847d76787ae,0x00083ee6e7005dda,0x000646f5e7ea8d16,0x000df7dfc45111c8,0x0001875c23c8373a,0x000039d490c7535b,0x000a062a7e04f897,0x000000000009afd1}, {0x000cbb06099a2183,0x000fb049dd385881,0x0008a6ac539cc7cc,0x00057b9925498c29,0x0002da25daa3dce0,0x000decb7d7b9c9bd,0x0006ef6d0b70a3d4,0x0000000000003df7}}, {{0x000405f3ffe95388,0x0004eff54e8bb8ae,0x000ad0d572466c0c,0x0005bc4ed1fae2ed,0x0009ea983db1b226,0x000851454a5e23c2,0x0005064af5f55909,0x0000000000036eb4}, {0x00062710e23e547f,0x000844c72b2d0dfe,0x0003b7abb313e4c9,0x0008ad4e19c9c269,0x00053e8b8004b1aa,0x000c747fdb9cfea9,0x000e4107782d788a,0x00000000000ce9d9}}, {{0x000aeca3f9d9a2f2,0x000f8779905b5deb,0x00064a28a88ba6a4,0x000f0aa679096dc3,0x0000f558913cce9a,0x00024a2e2fdf04f1,0x000b3505300cb06f,0x000000000005d581}, {0x000679a2a74abdaf,0x000aa855c8de8c32,0x0000f6e26bb556cb,0x0002a4197740d667,0x000744c9360d6761,0x0005cc8807588a52,0x000188928ac91032,0x00000000000acdd3}}, {{0x000ac6fa45a00390,0x000933774af3674c,0x000bcfd34179ae6d,0x000205ec11875399,0x00018799c22ede45,0x000b0842ef3b1144,0x000d64fd53f681e8,0x0000000000066d36}, {0x0007de25fd86d3c2,0x0009ca2c3391c37b,0x000760d08855c7c1,0x000fa4a6ab8ab4bf,0x000bd841a6234df1,0x0000b189a2b0cd34,0x000da752441d79b1,0x00000000000fa025}}, {{0x0009e3af5a1f4313,0x0000c3c6c56185fb,0x00083406c1a4afdd,0x0009c90ae2fb830d,0x0003ec31a504b325,0x0006230bdf7cc6e4,0x000e3a83bb13c612,0x00000000000ff1da}, {0x000c261cfaa4903f,0x000010cc6c1a44f0,0x00029f13aa21ef15,0x000c75fe604a58e6,0x00012491f872d454,0x000e116a5ceadfd9,0x0004816c5575da9c,0x00000000000b24a4}}, }, {/* digit=82 [{1,2,3,..,}]*([2^328]*G) */ {{0x00087efd2e620105,0x00045c5ad791e85f,0x000885fe6de88f7b,0x0009e4998544bc47,0x0005d273c360673b,0x000a75a8c934d8f5,0x000c977fb48d0768,0x000000000005e0fa}, {0x000ee7923fcfedee,0x0000dbe01655fb13,0x0001ed409cde6661,0x00030de533251391,0x0001de9f3fc574f8,0x000e01fa5a724033,0x0004b496b25206a7,0x0000000000007eda}}, {{0x000a5e409b41a55f,0x000283e6e9380f21,0x000bd6398225ced2,0x000c8b4b843ec071,0x0002af8a23f1f2d7,0x0007923350055d88,0x000e74e848010ed3,0x0000000000055e08}, {0x000839aa213ff6af,0x0003d956ea8e93ca,0x000299a04653a35e,0x0009271cca1b5491,0x0001f1d0b7f15f7b,0x0009963fbd41d228,0x000cd8b187047b5c,0x0000000000002536}}, {{0x000a16fe10008718,0x000fd7138a03f4b5,0x0008b9afc3d67514,0x00041fd2a7cbcc17,0x0005f6073ecba29c,0x00004fa086014349,0x00053298b46d3805,0x00000000000401f9}, {0x000b314f178aa1e6,0x0009808cc4abc63d,0x0005190f1545e910,0x000c8faa75d9af1b,0x000fc2e5592d6eb2,0x000468e666f50198,0x000fc3773b9d55c0,0x000000000001a2a9}}, {{0x0004cdf21adad97a,0x00008e51a956ff23,0x0002a26288680976,0x0000fa2f974d2cb8,0x00074c6a78dec616,0x000c89d11e00474f,0x000133ee916e510a,0x00000000000f826f}, {0x0002a0e3be0ad710,0x000103fc65d3ecf2,0x00089ef785c9b19a,0x000a82e0b9196b29,0x0000a572b6f55237,0x000bed2bc4975e68,0x00025e41ea8b92b9,0x0000000000098268}}, {{0x000bc901bf39d0d3,0x000fae352fb9c164,0x0000b33959aa5988,0x000ce6fafcb7de1c,0x0004f694cad0f9ff,0x00061d6110e574cf,0x0005d8adb4671cb7,0x00000000000c8aa0}, {0x000b2a78a9127846,0x000a987cd7872df6,0x00010a813ed5d7a6,0x000531ec2cb43e23,0x0004b9e6b89f1c41,0x000e5d4d262fc310,0x0001dd7f406a0dc4,0x00000000000df3f6}}, {{0x0005300bc3a99814,0x0008c06f721d246f,0x0003df2a36c6f8d6,0x0006b7a5a44ffdab,0x000915764390c5ca,0x000747d7dc53e328,0x0001227f16917459,0x0000000000061f79}, {0x000965ef8eb0e108,0x000ae099f4e3a08f,0x0009b651d265b539,0x00043576b72f3285,0x000cc33695bd270a,0x0002249029d6bb26,0x00051f60f9202126,0x00000000000e1b0a}}, {{0x000bf8353cd33783,0x00086265d4eff002,0x00010092c6e845e0,0x0005c996be6ce254,0x00096b6056eec399,0x000a007266fd43e5,0x000fb1d328c28f28,0x00000000000f719a}, {0x000f1e2a3462b4c4,0x000fb75dcabd2f96,0x0006c939c482a7c5,0x000a522d764ab7e8,0x000dcf8a487267c6,0x000810a449458c96,0x000786af1af61b78,0x0000000000073902}}, {{0x000b7c441c7f3df5,0x000a88a390dca834,0x0004f92ea9440c60,0x000ea69bc5e82f15,0x000d4628d6f177bb,0x00068e24071f02e2,0x0000ee6260790cf9,0x0000000000066527}, {0x0001df8e5c25d23a,0x000f233639544be6,0x000c37cf5bac2371,0x0000f867807ed557,0x00019dfa452c6906,0x000d27c0d1b0ac01,0x00090cbbdb25fe06,0x00000000000a60ef}}, }, {/* digit=83 [{1,2,3,..,}]*([2^332]*G) */ {{0x000957058557b81a,0x000dc1877dfd042b,0x000fe0adb79e32df,0x0009536c78e295f6,0x000374a04cc59d08,0x0007f75edcbb5d55,0x00078ce366600682,0x0000000000061e73}, {0x000dd46741146ae1,0x0000a74170170ac0,0x00052de550198353,0x00030f8ac1c4a0fc,0x000d3cd92824d75a,0x0005e86d4d7e7be0,0x0005ef5ea0abdb1b,0x00000000000b3b61}}, {{0x0003f4e13d621f8b,0x0005a618ca06b4bf,0x0002813dfa928efe,0x00072cca3b6ce7e1,0x000e5f14bb579813,0x00073abbbb44a68e,0x000c0afc1167e963,0x00000000000767d4}, {0x000277deb88a4f9a,0x00077c6dcdfeb3e6,0x000664e1fd3b5c4b,0x00001aabfcbf2f89,0x000a67aa82774775,0x000aab9cd0be7228,0x000b4a5de7b8331d,0x00000000000262fe}}, {{0x000cce85ebd04b7f,0x0007f7a9623b5682,0x000f8d813f260bd0,0x000dec9e0f8e530f,0x00091d65dcd4f8a5,0x00039541c88bcbe2,0x00097a09fe380367,0x00000000000e716a}, {0x000184fc8c1d72cf,0x0003bbd8e34de924,0x000a19b51363e270,0x000d905351941206,0x0006f7a3c4830183,0x0003557396345099,0x0002f718283cea01,0x000000000009aaa7}}, {{0x000a56eb624d0cf2,0x0006a7b7da0287f4,0x00087c61d1ede60c,0x000d83c51f3dbd9c,0x000fa91d085ac056,0x00035262de2f4d46,0x00029e31759c9ceb,0x000000000000c9dd}, {0x0009a41b82bb0c12,0x000e8108cf9ba936,0x0004fc5060b7103d,0x00016b273d372b32,0x0007d5415e53f698,0x0006b8b0e126575a,0x000a5e546bb4c130,0x000000000004d54e}}, {{0x0002c932a7c5abec,0x000a881dd074d9bd,0x000f76c734b204ea,0x000e1f0352b58f62,0x00029c390eefb5af,0x0006a8d236d2d948,0x000be5d073f9a0f3,0x00000000000466eb}, {0x000118cb3dd8d87a,0x0004d968c04a5c76,0x00007c8586d1cdac,0x00096bb15c0970b9,0x000370ab8dda98e1,0x000039fa92af28ea,0x000ff6b912fbda7a,0x00000000000cbd02}}, {{0x000e45ea08b7c4d8,0x0001d5bcf28785c2,0x000fc63d7c5e8cf8,0x0005de6707a7138f,0x000cfb2041a48868,0x000db3060a77646d,0x0006908608695289,0x00000000000e27a1}, {0x0000f0b051870cd1,0x000794148d936eb2,0x000a4e50dd50fda5,0x0002d4db0391d14a,0x000462b0373f9d72,0x000a9992c5683112,0x000b8487b0363be9,0x000000000008853d}}, {{0x0002c578f8f683b4,0x000576c8e5a2524a,0x0007522f4370ef9a,0x0004aad50ad6f3a6,0x00051f107e269b01,0x00051bf732a3933c,0x0006df4b04395cc9,0x00000000000b0ef5}, {0x00017d2e75e44b21,0x000cd28c9fcdca32,0x00061a5012b72649,0x000f58e53ace23e2,0x000efe688f02b546,0x00091406dee5fec4,0x0004d9d8b43f6d2e,0x0000000000026176}}, {{0x0002d2ad73a4790a,0x00034daa7fcc985a,0x0000276056234a54,0x00018c59894edceb,0x000da9ac29a7fbf9,0x000372f2c470c45e,0x000d3fdfd44f6fbc,0x00000000000a1e38}, {0x00009dd8fe96aa5f,0x0003923d2400aaad,0x000c441c1c12013d,0x000488148baa4ac3,0x000ebc26e6b0c76a,0x000ef566273227e4,0x0002bbe732edcfe8,0x000000000000c566}}, }, {/* digit=84 [{1,2,3,..,}]*([2^336]*G) */ {{0x000d5d97020dd4a2,0x0005087c7dd7d118,0x000d6556f04f9110,0x00048789fff00158,0x000b909eaf1abcbc,0x000443a788ffcef8,0x000fed9905f4eef1,0x00000000000e15cb}, {0x000831894b4ea50c,0x0006cca2969ec57b,0x000ae2b1ba048b54,0x000fab787ea6e3a2,0x000ff98c4fe567f7,0x0009cb91e0d0ee10,0x000ab4c646879ac1,0x000000000007d1d7}}, {{0x00092725c84d0435,0x00013cfbcbc49b56,0x000166c387130162,0x000e05622322f91f,0x000a7662ae23735d,0x0002be7a6d2590bd,0x00017263d468fed8,0x00000000000695ea}, {0x0005986e2611645f,0x00050c50f4940fa9,0x0003729def8820a9,0x000cd041fd257785,0x00044a3d0808680c,0x000684cba25ddac4,0x00088841d8b738c4,0x0000000000053963}}, {{0x0003a8028963f3e3,0x00076b05cb83426c,0x00074bc4cf79f053,0x000b5aaefa9e4f0b,0x000d9bd075ecf023,0x000a41bfbb8061e5,0x000d967d2ba50f1a,0x0000000000090865}, {0x0004ae64b7cf3e16,0x000d97f221a788f4,0x00000b032e3ccff2,0x000eb6af6ab15418,0x0004dc87cd93085f,0x00039dbf6fd14102,0x0003643e196fdb32,0x00000000000dbcd5}}, {{0x000d4ecde2fce0e7,0x000891466c9f4fd3,0x000b63a0ee692739,0x0008c75b58655519,0x0004e65862cc291e,0x0009971671ddb715,0x000c19285153bc2b,0x00000000000954b6}, {0x00039e1aad688b1d,0x000e0985d4505697,0x000559cd349baa64,0x00098dafa5fe5e6a,0x0006f90f231d39e0,0x000afd0b53fc2604,0x000c18de5d5ced32,0x0000000000060c09}}, {{0x000b1d0586854e54,0x000cf3720b17188f,0x0005eebb9c78a9a7,0x0006e315b54eefca,0x000472b0edaa03c4,0x00077476e387e466,0x000259fc59b03dee,0x00000000000607a7}, {0x000e6b356394b5a7,0x0008b1478bceddaf,0x000e3cdb4ff0323d,0x0002f72cf272ee0a,0x00038bd885cd7127,0x0006ba31c19e3a4a,0x000b369af6415b37,0x00000000000807b2}}, {{0x0008b39051ba2cdd,0x00030dbfcfa7593b,0x00015a46addd3783,0x000851d67a19b610,0x000431ae1a67cc6c,0x000d1e135ace88bf,0x00090a74554a6193,0x0000000000042118}, {0x000bd87496a1468e,0x000277cb3268907e,0x000047feb42207f2,0x0002c21766e72f3c,0x000a880642e30a67,0x0004d2b3624bb718,0x0004ab425dc41d18,0x0000000000089102}}, {{0x000caa1ac9c2c636,0x000673180789b5d1,0x000d386a756090c3,0x000b895e99e922ea,0x00003d0bbe807951,0x000fe79c0987ea25,0x000d2a6d2f49f0e2,0x00000000000c2b18}, {0x000ed8226be989ea,0x000d8707798f36cd,0x000ebf8dc541b02a,0x0001e32bc4479412,0x000938a845f346cf,0x0005e5d924dfc145,0x000c3f210083fe45,0x00000000000a1fed}}, {{0x000faea0d2bc54ec,0x000a972fc8198080,0x00029736c6c3c3d0,0x00098bbd99e30373,0x000a0efddfca3691,0x0009147416b68390,0x0008078c35f3e4f0,0x00000000000ca7d7}, {0x0005a76575b0ee6c,0x000e9564d991dc4d,0x0003cf033490be81,0x0000dab5d635893d,0x0006f944e49a51f3,0x000233bc00427e34,0x00093e1e0bf1b56a,0x00000000000617bf}}, }, {/* digit=85 [{1,2,3,..,}]*([2^340]*G) */ {{0x000129009060318c,0x00056d23658c8428,0x0004596f83a71a5a,0x00010ec082210f1b,0x0001bfc364906dab,0x0004f2d14fb1add9,0x000443eda8b02f9a,0x0000000000056560}, {0x0004169ffc0d0413,0x000986c01479d686,0x000d5173dbdf44ef,0x0003c1d718883983,0x000e13c34fd24dcf,0x0000c15ac87a9c04,0x0005d2fe0e08ec51,0x00000000000c0f49}}, {{0x00099e97b82e73d1,0x0005db097b2c50cb,0x00071fe923d57f3e,0x00066e9420996453,0x000eff7290736382,0x0008c394043d059d,0x000925eebb5fe114,0x00000000000daa8e}, {0x000995963e49eb67,0x00007f43c78d7e6f,0x000a34a7c03b2d6b,0x000a7d66b6363576,0x000be096a954cdd5,0x000afa2fc8b70a2e,0x00095a011d5419d0,0x0000000000004fb0}}, {{0x00033bb61172fb0c,0x00008eb05c51603f,0x0000d435c61a818f,0x00073cd489576f54,0x0000535a8d57cfd5,0x0001436c4e653538,0x00022d1394731467,0x000000000005f0a1}, {0x0007992fb047bfc7,0x00099aecc7ec110e,0x000e8ab91f3e896f,0x000f6523d4221aba,0x000f2851996bdf96,0x000cfb67efef5649,0x00005246fb9f26d5,0x00000000000ef5c4}}, {{0x00016ebee78befa2,0x0003188e7ac8d2f0,0x000b37c50c491499,0x000d52918be419b3,0x0004c057621c3b96,0x000e57e597e75e35,0x000463cb1b709f5c,0x00000000000844f2}, {0x00053157dde1a349,0x0006d53608198549,0x0000450e27f360c3,0x000d348e04114157,0x00004d73eeae6dd0,0x0000ed85e5b28e95,0x000b580843923269,0x000000000006da14}}, {{0x000ce0f0a89b6284,0x000735cbdc4424ba,0x0003b0cbdca1bfb5,0x0006886c118d02b1,0x000675aaf27658a2,0x0005f6ec187ff74e,0x000d32b133be95f6,0x000000000004b1b8}, {0x000fda7aaf38358a,0x0001bdd8a8ef25a8,0x000eba5b65bc2a4f,0x000a6db26623fb02,0x0000bae15453d525,0x000f89fc9f2368d4,0x000a3e55d6a84d84,0x0000000000086021}}, {{0x0009f5565cd739fd,0x000f210520b26d6e,0x0004ac2940ef5ddb,0x0008ef88948f78bf,0x000550ad452e1246,0x000c4847040a9d27,0x000ace5e382347c1,0x0000000000033e73}, {0x000c8b4278956db1,0x000437d83d02e97a,0x000af99c625baa1b,0x000d448885679e6a,0x0005fc95919c6716,0x000c2194a0e12bdd,0x000d2d7da4420492,0x0000000000015ffc}}, {{0x000c11f07976d090,0x00025bd048bdc85d,0x0003c8a142cbe0e8,0x000a758a985ac100,0x000cf2c7ace940aa,0x000ec347d6039bcd,0x000ab7712092cc6a,0x000000000006b5ac}, {0x0003db66ec59bab1,0x000551ebcf80c829,0x000fffebfb9d4dbf,0x0003d1ad0b610f09,0x000498c28ac73fdd,0x00059750fdd3f6f9,0x0001ac650b77943a,0x000000000002d399}}, {{0x0001cfefd0dbceda,0x000826cbd2756691,0x000e925943cf3919,0x000aa0be4c58c7c2,0x000f0e488784177e,0x000916b0f603551e,0x0002e2c8eba131df,0x0000000000015973}, {0x00008eec1292bc0e,0x0000355acca849df,0x000e7c404ec832b8,0x0002c703bd3b202e,0x00056ddd8eba162a,0x000b1d93d4c5e5d2,0x000dcf66e7844a77,0x00000000000110b9}}, }, {/* digit=86 [{1,2,3,..,}]*([2^344]*G) */ {{0x0003ab751954f075,0x000f91b66faabe09,0x0001714e51539902,0x000f3a0a675f7c8e,0x000f30313a711a82,0x000aea9e682884a2,0x00005d7ac5d7b058,0x00000000000cd5ff}, {0x000d5d715b7b74ff,0x000287c29638d05f,0x0006736db974b38e,0x0003c47a17ae3a7c,0x00077009e38ae85e,0x000f9c52e91b107c,0x0008a0f3b777d8f1,0x0000000000011b68}}, {{0x00072d048b012b70,0x0009a4ae3d232353,0x000ebed55756fa98,0x000c769ec62fd6b0,0x000f62a4720cba73,0x000c1f491d586ba7,0x0005716497cd140c,0x000000000007b2ac}, {0x0007af894008277c,0x000b9a65eabb5e68,0x000cb737865439ae,0x0001b84231457d7c,0x0005901645c525b3,0x000f7b656cab62f7,0x00095c2377d74db2,0x000000000002d33c}}, {{0x000e54e4ebfecf4f,0x000b310105dfc241,0x0000ded90576b5a5,0x00068324e80fc085,0x000287dc7da6122e,0x0004728cf3b26e76,0x0001297bc183de6d,0x000000000008bcdc}, {0x000bafda0190b71b,0x0005d8b995cec24c,0x00099629f2c641a0,0x0009e6b4da5b77d0,0x00096caf9161612e,0x000f45eb68ec048a,0x0000e9e3628ee2c7,0x00000000000d8565}}, {{0x000dc37cf3c258c7,0x0005aaae2f447f93,0x000c6f7663c30e3d,0x000b2f482c1f372f,0x000d351a5f7f3262,0x0006c75a85521feb,0x000fb8f8ec919091,0x000000000002728d}, {0x000f483180d24d43,0x0005f5dd4ff4f0a1,0x0000b042bcddd9b8,0x0005b98ba8b777b7,0x0006fb7f8409318b,0x000fd31dbd971d42,0x000347ed1465e8b0,0x0000000000000f66}}, {{0x000f5311360afd40,0x000bacea0374a33b,0x000feb5ded889fab,0x00002361bb01f474,0x000a8c328b8bf6ce,0x00053d6302a5b28b,0x0005d86991b1d8b2,0x0000000000085945}, {0x0008eeb3e3866a93,0x00024f5c6e141989,0x000231ed9c304f2e,0x000032f67e76ece0,0x0002338980594eb4,0x000001b765bf14aa,0x0001340804a7c00e,0x00000000000734cd}}, {{0x00036d45a9f2195d,0x0007e5ba5288b70f,0x000e413923c56371,0x000a997602f3c65a,0x000fe08c0223c1a9,0x0007e6f1dc5c7512,0x00059748a19c3c36,0x00000000000fb241}, {0x0001d161a9f86145,0x000879f674a5f0bc,0x0001526754b42988,0x0008c4303d6f13ed,0x000d917433fb5aeb,0x000f534900fed575,0x000616e4a5ef9a59,0x00000000000f315e}}, {{0x0008596b7b07e015,0x0009c7059c585ee9,0x000cfabffa6395f2,0x000d9318d9633cd0,0x000f37bda14896dc,0x0008964dcb2abc44,0x00076ce31adb3feb,0x00000000000e3168}, {0x000ed4ab82ecfd95,0x000363173288028b,0x000f24a3fd6c4552,0x00034c91d6f69add,0x00022c34e118b5b3,0x0005984ede613e56,0x0003a18bbdbf5c5f,0x00000000000cf4f6}}, {{0x0008f4401a1165b4,0x000b4315ad7a4644,0x000672c1b06e4df0,0x00097a8baa564733,0x000446edcfcbe12f,0x0001a968ef263db4,0x00087547cf91d53c,0x00000000000c15db}, {0x0007f5c515f16ba5,0x000345d35e53a1e8,0x000a90f359724b01,0x00011ea246da3d37,0x000653f068205d3d,0x00010c00fc1ddfcc,0x0008c78169d71166,0x000000000004bddc}}, }, {/* digit=87 [{1,2,3,..,}]*([2^348]*G) */ {{0x0005418902e018d8,0x000328002f4583b6,0x00029b160f5eca39,0x000d112fb93f735b,0x0002196e3084a8ce,0x000e8c74427cb629,0x0005ff72395bdd77,0x00000000000ee71f}, {0x00030cc165e06d5c,0x000ca7cfc14d95b5,0x000ac1b9673d9545,0x0000129d213738ef,0x0001bc0b5ea366e5,0x000a067007a905d9,0x00082192cb630afc,0x00000000000bf3a0}}, {{0x0009c76f27cbedd6,0x00086e96c4aebbe2,0x00087447d6551831,0x000d2f632f9151d3,0x0004302b99e2f86a,0x000fd317105daf87,0x000c624299dbfa14,0x00000000000812cf}, {0x000ccd383b8a542c,0x0001b42e615367ce,0x000e792323a5de78,0x0006c70548fffa38,0x00077b6db825c34c,0x000f2989e1fbed77,0x0003ee850bded44e,0x0000000000081546}}, {{0x0008bd3d7d2dac19,0x000ce352e14371a1,0x000574a96d5757aa,0x000d9395a7b7719e,0x000b8544328b64d5,0x000f9c5934d5197b,0x00045e5220626522,0x0000000000074d6a}, {0x000ed277c567a2e7,0x00003f52c9eeb86b,0x00037cef0ab9cbea,0x000b3bfc9ed39349,0x0007a14c3d70e606,0x000db5876fc5046d,0x0007a181cd053e5e,0x00000000000a3034}}, {{0x00026a12e217941d,0x0008a9decf2164e6,0x000546598e5e9913,0x0009ce8aeb36b93a,0x000158fb4dc8d564,0x0002d60cfab9f77d,0x00061966b11fb6b5,0x00000000000eaaa4}, {0x00098700891e3d12,0x000dbf3522a998ce,0x00034cf7624bc215,0x00097c625e387237,0x00072d4595ee2679,0x000e5456ced5047b,0x0006feaaa41e5f55,0x0000000000078cfc}}, {{0x000abf51b7538110,0x000353fd75579f7b,0x000019e5c13ce4a6,0x00076854d208bb77,0x000ac1c9512f4c82,0x00081e9f3941aeb9,0x0003396ce0bed5a1,0x000000000003744a}, {0x000bd7c923f4230a,0x0006180eaff7a041,0x000dbb73984381c7,0x0007c1b0f8e7fd8b,0x000aaf499630f16e,0x00080a16856bdddd,0x00012be8c112df11,0x000000000002987f}}, {{0x000b02027989cfc0,0x000a60ce9ab12f61,0x000973d1a5ee6cd8,0x000b3b69a1753a9f,0x00002bae5685f031,0x000d3c06632160ba,0x000f5cdfde9ae80c,0x00000000000a180c}, {0x000f0a3aff152330,0x00023e2c194158b5,0x000e1481b10c0c49,0x000e7d12ea20322e,0x00007968c7ff67ea,0x00027bab93eb507b,0x0006eaeb300ff9ce,0x0000000000097575}}, {{0x000b71b2ec924484,0x00007325de655ef5,0x00027d8f4ae5da5e,0x00026ad89e4c34bb,0x0000ec5a615fa909,0x000c770ac8e61adb,0x000f8a5a2233d43f,0x00000000000cbb23}, {0x0003b01804f61225,0x000a4a7e6c5861cf,0x0004fcae81492249,0x00040be697e7dc09,0x000eb6f29135b0f3,0x000e89899783a7d0,0x000f55412469b007,0x000000000001bfaa}}, {{0x0003c3de6d71b673,0x000cca438634e69c,0x000f00cb40863203,0x000dedfac40dd56f,0x000e4956a5de2ab4,0x00013f84d758e95e,0x00016cfc11e39451,0x000000000006059f}, {0x0008f87a862c83c5,0x00038fd8e2236750,0x000df4ebd7b9092c,0x000b1538ea13b455,0x0003013d382702ae,0x0009ca201de1275d,0x000351470a7b7e65,0x000000000005c77b}}, }, {/* digit=88 [{1,2,3,..,}]*([2^352]*G) */ {{0x000bd58c2fd385c4,0x000d8281f6e58982,0x000c3afee2ff7056,0x000a41afd89abd8e,0x00007984feefe29f,0x000d20a64fcb0b0b,0x000cd50b0928a6d9,0x000000000006979c}, {0x0008ab27cda5c7bd,0x0001cce9c34c7521,0x0006dc0b027875db,0x000635250946a5c3,0x0006f39f53b9d464,0x000bc8b64b09a97c,0x0000d61d47bc20dc,0x00000000000d458b}}, {{0x0004b16a9cc79c48,0x00075763e36638c9,0x000ff772bf788245,0x00011a8c66b40e9f,0x0008f384b70862ab,0x0001978760624469,0x000837e7cdf3bd69,0x00000000000064f8}, {0x000fbc5f9be69c3f,0x0007895900a21f89,0x00053a9326cbd6b2,0x000fbbddd3e6e471,0x0006baa2e2a03f65,0x00085282484f52e0,0x00032c1dc462a8e3,0x000000000007e4c0}}, {{0x0008c150b5ec2626,0x00094cc580ea6853,0x000526b13f535e43,0x000604fb23480cfc,0x000a344146898665,0x00010a94595787cb,0x000c78425d7c6f4d,0x00000000000b2f1c}, {0x000940b59f5f9db6,0x000f455da8884e6f,0x000468b788890b3d,0x00081d7d99e417f5,0x000abf28fba2c648,0x0004eff801eeba5a,0x000fb720feb7b350,0x0000000000050deb}}, {{0x0002dafb4e000df5,0x0009720ebf79c9aa,0x000a041b02faa426,0x00007e78d630d2b3,0x0007fa605dcb016c,0x000d0470520021d5,0x0007e66190f3e942,0x000000000008974b}, {0x000bb7ed0e0135bf,0x0003b6710da6c4cb,0x00011bda556d9709,0x0004b8ba583089a0,0x0004ea7dbcdd192c,0x000df1097171ab8c,0x0000ed715f60818c,0x00000000000205d1}}, {{0x000c0f09863d151a,0x0004b4a6226f970c,0x0004a88f8872d167,0x0002e60a1193cac8,0x000543dda270b44e,0x000d647382ce6393,0x0006751a9e8a2138,0x000000000009d843}, {0x000abb28a3b6891b,0x0008a98a1222e3ef,0x000341bb8ccbdd0d,0x0005be5555088026,0x00017b38f0648047,0x000e249f5c39ccd9,0x000b74ea31304de8,0x000000000004d42d}}, {{0x000330dc4e7217de,0x0009c39a689bbd9a,0x00001ce7a86200c3,0x000108a8d29457b6,0x000014ed4b4dcf33,0x00015625f312612e,0x00063bcbb21f3451,0x00000000000303a3}, {0x0009f7756d9dff06,0x00004aeb0c8c0639,0x000d964999e9958d,0x0002604683b37dcb,0x0007862b08477a02,0x000d69390fa4ced7,0x0003145a49bdc136,0x00000000000c0215}}, {{0x000155abc265f191,0x000f0544874b6521,0x0007a036ebfb6d29,0x000afd631411ba1e,0x0000466d6415b303,0x000d4c2de30047aa,0x0007b13a1b676594,0x000000000002860c}, {0x0008a20d9745d768,0x00046fe140a72d14,0x0007d03c948ac2bf,0x0006df9f46f144f8,0x000bc0defbc46c9f,0x00024c075f7e7b95,0x000c39fbc9a96978,0x00000000000d7773}}, {{0x000f0ec4d363b0b7,0x000bdd2db4d34f56,0x0005740dc154bacd,0x00065cc723a57c02,0x0007d8ded62c4475,0x0002f1a9ed98c359,0x0003b20aeac6d9de,0x000000000000a98d}, {0x0004a99c9e88ef97,0x00034d9708f06642,0x0001bd570d037e70,0x00032cf49cda0113,0x000a858467e24993,0x000748e8e546df74,0x0000738b84a55093,0x0000000000006f09}}, }, {/* digit=89 [{1,2,3,..,}]*([2^356]*G) */ {{0x000f37fe6b03f897,0x00052c0a40cabe70,0x00091f1b94fec55b,0x000898c340187426,0x000636d9e57a8625,0x0008aa21169c9f3f,0x00016869d9d7f337,0x00000000000e7dca}, {0x000214154225907a,0x000ba24d49aebb77,0x000fbddce2036f3c,0x0001d01576f533f5,0x00099ef82ece667c,0x00007c14d372eee1,0x0007f6577723c0c2,0x000000000000eed3}}, {{0x000850ebff25b818,0x00013c61db976bce,0x000a1c9cf36381eb,0x000b8ca060b1adcb,0x000188e2c178ce89,0x0003bdd3c41db448,0x00042cba6339f392,0x00000000000d29db}, {0x000bbd1437baf649,0x000f53521116eaf1,0x0005d6c8cce9ea0c,0x000c984bd79fe5d8,0x000e9d45eee49357,0x00088e01f2eda73b,0x0008731a50c59f62,0x0000000000075018}}, {{0x00038b1bc1ced6c1,0x0004df323953ab33,0x000a2512b2fa2401,0x000dfd9bd32cb8d7,0x00037ecf35382937,0x00039941507c4e56,0x000a06b573960eb6,0x00000000000dd1a4}, {0x000a33b92253abc1,0x00050c625f400562,0x000bec6e4c3f3a23,0x0001e5b6220f24df,0x000827d01c6f66c5,0x00012372d9f97d75,0x00004860b1572404,0x0000000000004d55}}, {{0x000a3b570044f6d8,0x0005fc552c6c6093,0x000f9e99da8c0559,0x000375c19610b0cd,0x000bb051dad5c9ed,0x000556643f0e7b4e,0x0001d87267a304c6,0x00000000000c96dc}, {0x000cd649696f60dc,0x000dbf0ed5f9a8b8,0x00051f0009075842,0x00066f4af5a4b4c2,0x000d20644cf2ef5d,0x000ae23c00b5bed3,0x000b66f7e4543a75,0x0000000000041325}}, {{0x0006798502ee1353,0x0006c04ef7ad5a7b,0x000c6878548d78d6,0x0008a6a47591d88b,0x00046902edb49ae3,0x0002b143a27d9125,0x000df65dae3d8381,0x0000000000093a2f}, {0x00091ef1ecb7e486,0x0000807a00388858,0x000fb3b7ca4398f1,0x000c17172b1bcba8,0x00032d0033c73fd6,0x00016c28aa8d70f9,0x000ad79ea9eea329,0x00000000000423ed}}, {{0x000a6b031af68d65,0x000b59949b33d112,0x00063134f5d066ef,0x00071e788e17f2bf,0x0002da9c088188ce,0x000d8c9e9d851baf,0x0005b6e869c5ba86,0x00000000000a0142}, {0x0009ab9cc7c38dc7,0x000eceae8b1c5d3f,0x000b0c8e79b3cc01,0x0002910c374bb97b,0x0007054874831494,0x000bc6ee13e13c45,0x00047be0e6fad435,0x00000000000b54d2}}, {{0x000e68e47f9ea217,0x0003c9c85e50a3a1,0x000b0543d8520966,0x000ce81807f33dba,0x000a3db81e06cb78,0x000638d709d337d8,0x000babe223eae472,0x000000000006bf2e}, {0x0006763908bcca20,0x000662804b59c92a,0x000900c614fc9957,0x000ca1e7bc6949c1,0x00008f051155321e,0x000539f40bf2906c,0x000808b802a3289c,0x00000000000073cd}}, {{0x000fc3dc90267bca,0x000956d34bdf61b1,0x000bd7a38090ba35,0x00051135a3bfdd10,0x0005f1296bdd61d0,0x0002e9a7c4abab57,0x00003d72da68494d,0x000000000008d11f}, {0x000319b6e5281755,0x0002247811121597,0x000526a929004138,0x0003ec67521898f7,0x000996c1da75ec29,0x000f2c7b3f0cf026,0x000af8b0dbd4c380,0x0000000000034e4b}}, }, {/* digit=90 [{1,2,3,..,}]*([2^360]*G) */ {{0x000c4e9ab57885e4,0x000f3c32730e8279,0x00033a83277668a3,0x000fdbf3f5cd8478,0x00067272d4dd2bac,0x000b7577645f3641,0x000be2dd813a795e,0x0000000000050997}, {0x0005df7d4526b8ac,0x00040da054e2b966,0x00068890ccefdc5e,0x0008f31026116a38,0x0000dcd85e914c42,0x0003adc2d372af9a,0x0009e6fda6e90367,0x00000000000a8db5}}, {{0x00029349f348fe26,0x0004251a033a4db8,0x000e0f2d8a80c6e4,0x000ce49a42a266f1,0x000b82c4d11e92ee,0x000bae08a87e037d,0x00078c875be1416f,0x00000000000c5394}, {0x000064a55c345b79,0x0001651f8b907a36,0x0000a11c59759db6,0x000bd666c51b9c32,0x0004ee565de82c74,0x00082c8c3635d3d2,0x00093c6bd6566389,0x00000000000daf6a}}, {{0x0007ac96ab52d7dc,0x000dd68fe359d36e,0x000f3dea99f83698,0x00052c3fc704935e,0x000952e4e22d0ec6,0x0003e3ada1eeff1f,0x000871ba6777cb08,0x000000000008befc}, {0x0007324fc4458b0a,0x000e34ede689e853,0x000cf3cdc3eb9d08,0x00080517ab83c288,0x00052c8c1f48e0f0,0x000241aac1f3d5f2,0x0007e057991607af,0x00000000000b8a33}}, {{0x000ca2047d1f8f40,0x00004179c59cea3e,0x000880cb97b10e4b,0x0005cfdba0cf3857,0x000b3a8fbafadda7,0x000384e0b94081a5,0x000a45b91de90a33,0x0000000000027aa2}, {0x00058a31cd3d8717,0x000220747bcc094c,0x0000191551c0619d,0x000e3e9722484f1a,0x000da62d1dda9c1c,0x000963bce13a7ee5,0x00021b77fd79343a,0x0000000000083d2f}}, {{0x0009d92935034280,0x0008b3dbb3fa61cd,0x000a3f5ecd8961d8,0x0006574793ce8041,0x000783dbce4f35ac,0x0003cf6b0b2697dc,0x000164e35c5bf2e1,0x00000000000b0c4a}, {0x0008df1996e7f4a8,0x00038aa49090842d,0x0003b655f6623523,0x000e96c54d504e4c,0x0001b73310a3f646,0x000bde5dad74e754,0x000ef7ead7159618,0x00000000000aa09a}}, {{0x0005ac9c05f620d2,0x000df609deb16279,0x000a25447b2b8795,0x0003132b378305ce,0x000869275f5e4a9f,0x000b089b5f101799,0x0000c514be746761,0x000000000000c81b}, {0x000e2dd3d7fa135b,0x00030ca90a9bf94b,0x0006097de4edabc4,0x000ac9620c71989d,0x000a390aedd01b25,0x000d8cd39b971b61,0x00011a995214d779,0x0000000000065c6e}}, {{0x0003855cea5ad9ec,0x000d4a8393a23731,0x0006e8588fe37236,0x0004e0255a202691,0x0002a446bcc6d882,0x00051499b9dd9a27,0x000535c929cded53,0x00000000000cfe76}, {0x000bc0f428a70f0d,0x0009626f3d7d9b38,0x000a6acd906c92a5,0x000cc06759e6ddb7,0x0004e302b89191fd,0x00007e1f7ac2e190,0x000b4aad25c645c2,0x00000000000ab3de}}, {{0x000338669b2cb8c7,0x00071a13f19b3741,0x00031ac1789cc21d,0x0000c997044a6f4f,0x0008dca1075c00ec,0x00020ab0caf5665f,0x000effded5ca3f06,0x00000000000a896d}, {0x000378285debab1d,0x000a5032ab2b2a9f,0x000438bbbc4fc5ea,0x000b6f725133304f,0x0001977a45672286,0x000abae4f0d16d53,0x00003b00a66036f1,0x0000000000095f01}}, }, {/* digit=91 [{1,2,3,..,}]*([2^364]*G) */ {{0x000925dc8a89e47c,0x00066f2cdae310b9,0x0002591b317d8ec6,0x000f25ad750b29bd,0x0005dba15f3e9d14,0x0009fe2dd931b9c6,0x00043334db169ebf,0x0000000000052663}, {0x000c577396a26bac,0x000968859a4f76bc,0x0005596f973fb63a,0x0008d6a67ac4db88,0x0002be25d7557463,0x000db10ee5c8ea7b,0x000cd38a0f0a8738,0x00000000000e890b}}, {{0x000bf56a7de9f2ff,0x00022883533aee6b,0x0008916bc1e75ddf,0x0005fb546d0fcf42,0x000a4ab05da78f0b,0x0007b66147e6b0a0,0x000cf2cd91a869c6,0x000000000006c6f7}, {0x000593da575680e9,0x000d7c072a1067a9,0x0006a216ef99f7a9,0x000192c8f0ce9469,0x000fd11494417378,0x000ccf45adf2e7b9,0x0005684fa17cb614,0x0000000000045f03}}, {{0x000725d8721dd338,0x000930f4ca77fc15,0x000b6681d170fa2e,0x000625b4ef805afc,0x000fc015c5864873,0x0001a8c93bddba22,0x000f427091b50aa4,0x000000000004c005}, {0x00044f31df11a4ec,0x0009ff43d3745415,0x00007d532af636b7,0x000a10c82770690b,0x000b77513f003efc,0x000c3af9bd0c25d7,0x000adac0015cc12d,0x0000000000094c6c}}, {{0x000e8ca221c6ffc6,0x0008d8b70e94f6d7,0x000aee261a6327ec,0x00019ba4d3ef22f4,0x000a1999f948e222,0x000fe73027f8a712,0x000af025575e96ab,0x00000000000564a1}, {0x000b25cff3d9db0b,0x000b1045e9c658aa,0x0003561802f8c969,0x000b825c3db161be,0x000aba33a906dd23,0x0000e41f205fb173,0x000d1d9a8b5ecb87,0x00000000000ccc30}}, {{0x0002aea737bc7de5,0x000c2bed7d94c6a0,0x00033bc161f07397,0x0006af6106834bff,0x00044c4f74486541,0x0001dfc06dade8a1,0x0007bc62227a1d88,0x000000000008dc2b}, {0x000d41c50320c146,0x0001c4f1154170fa,0x0005645ed0c5caa2,0x00053aba0f1b9617,0x000d48b0ec8e98cc,0x00072d0342f68011,0x000e384bbc34679c,0x000000000009c576}}, {{0x000919b377dae55c,0x000a5d9243926709,0x000605401369e5f3,0x000feee0e35f201a,0x0003196f23f3a1bc,0x000c1d068d25be5f,0x00050b298c67f2ff,0x000000000000c3d9}, {0x000d303412559962,0x000fa5e15ab9975c,0x000533c7cf964ba3,0x0002ec947a7e2696,0x00022ac22e49a9f8,0x00006f090f02af9a,0x000cb0dfb3103fa7,0x000000000003cf8d}}, {{0x000298e2791b8ead,0x000259f5f44f9ed5,0x000ce416b16e73bb,0x000f258f9627f9cc,0x000938fd51bdd7e8,0x0006a4a7922499dc,0x000250a9d7497c84,0x00000000000026ae}, {0x000e3b88b9c7c3db,0x0009084d47d19214,0x000f52469be04308,0x000138806a52e316,0x00027f08953f9b2f,0x000fcac083fc8da0,0x0003fc22d074d292,0x00000000000701d7}}, {{0x000b913b1d418177,0x000cbb7b856256b6,0x000f3717023b8633,0x000ddd5c91b8ffd9,0x000155d38511b4eb,0x0000da525ef815ae,0x000bbd98587d551b,0x0000000000034a9e}, {0x0005ef8ce15a684b,0x000b8844811fa3d0,0x000d70ffbd583fff,0x0008bb4f623789be,0x000e404980584b26,0x0002b435ab26ae5b,0x000eb3b47a5ded3c,0x000000000008fcec}}, }, {/* digit=92 [{1,2,3,..,}]*([2^368]*G) */ {{0x00069e40601a7dfa,0x000cb70765682efa,0x0003c3be2bc6c542,0x0005ef0a6db6169b,0x00012032d5992a93,0x0006f13160029276,0x000f51b5babb2d3a,0x00000000000db26a}, {0x00039e460e4f3b3d,0x0000200c3401304d,0x0003ff9e293a0443,0x000e2ed0f9b36565,0x000934031d18a1bb,0x000fe1224e17a5d4,0x000cf5e3661047f8,0x00000000000623c6}}, {{0x000ad46943acea12,0x000a859367582797,0x00066c45ce5e5faf,0x000351af6a27741d,0x00087f929e0d5d96,0x0003f1afbeab94db,0x0001dd865ba01104,0x000000000005fb63}, {0x00040d1f1e090717,0x00038192e065294f,0x0002fb37089941d8,0x000228db7cae5f66,0x000d6a828b037bcc,0x000f301aa02eaecc,0x000a077c48a2ea91,0x00000000000f5eb1}}, {{0x0000bb651b864105,0x000154dd3bd8408c,0x0001daf9340de0f6,0x0006998ba0668966,0x000cad713bbd1ad4,0x000ca4fa5b7c679a,0x000a1cef9389aff7,0x00000000000d68b6}, {0x0009051030865994,0x000093acfff601ae,0x000275b28bea6bfe,0x0006441c66ad734b,0x00042fd3eb165e2f,0x0004e211749f144c,0x0001a3bd7f22082e,0x0000000000041791}}, {{0x0002b76266c69181,0x0004edf0ae8df2d5,0x000906801183c79d,0x00017ca1dd286917,0x0009709b678ede37,0x0000acdc60c1db87,0x00003a0288959a40,0x000000000005ca2d}, {0x000fd72975fb9eb5,0x00084e52534b365b,0x000f103241b3e4c6,0x00034f873eece315,0x000d642a67991a9a,0x000a7e8a80fb0c7b,0x000238375cc0cfea,0x00000000000d00ec}}, {{0x0005a38c81bac32b,0x000bdb67d88fb498,0x000506df3f19aea7,0x000433ede7910791,0x000a20ec085cc26e,0x0000eefb30ed8fc0,0x0008c22684a901b3,0x00000000000e855e}, {0x0003801582a535c0,0x000a23d31d6c91c3,0x00014e8637446682,0x000380e755f1af17,0x000a6c985ecfd938,0x00065084e6a8e434,0x000ec653bec9c1cb,0x0000000000070309}}, {{0x000a18c1c3a6f1f6,0x000f49a2461c2364,0x0005b210149e5bc7,0x000bfea0ae15fd0a,0x00027ac4d98f2265,0x000831902d817b35,0x0001fe9788aa4511,0x00000000000d4616}, {0x0004b65395df8642,0x0003d2a7cac2f471,0x0003af0e90c12844,0x00048d211070e2f3,0x000ab769926571a6,0x000aea1556050d8b,0x000411cf8f24a040,0x000000000003522b}}, {{0x000a6d728de1a709,0x0002e45d4ed63b83,0x000803bc165cd24c,0x00029022b267f598,0x000fc8446afe76be,0x0004d6f50791c22a,0x00077ed6ce8b8859,0x00000000000e3f1f}, {0x0000a258fb32c514,0x0006d1a72b16f0c7,0x0009dc6ac4083dba,0x000743e1cad2e785,0x00041e0e640d6a1c,0x00074648529ff0a5,0x0001fb4cd519be4b,0x000000000004584f}}, {{0x00051eecfb6439ff,0x000619ca8cc9cbbc,0x0007f10adb0b792f,0x0005d53059b2bbb3,0x0000730e5dc37211,0x0001d89988fe7ac3,0x0007a54e67ef6984,0x00000000000c8ed3}, {0x00004a045edf3ac0,0x0005e48164b3dc80,0x0006b3cd6d953b04,0x0004643beed38ce9,0x000fa3e30b3db7fd,0x000ddd484993cfa9,0x00075ddcc5e7af01,0x0000000000068401}}, }, {/* digit=93 [{1,2,3,..,}]*([2^372]*G) */ {{0x0007c9efed4b7222,0x000ab79768e9e648,0x000c0eb72891fdba,0x000821bbe0c67d8d,0x000a6909fdfcc194,0x000ccdda7537a6a4,0x00026cae6d705195,0x0000000000092b39}, {0x0004e2be194fc116,0x000ab2c5dd6af51d,0x000bd2ad4ffd8821,0x0007388397a3bd3a,0x000a8baf59c2dd3c,0x0000ec9589d176c6,0x000315d5c6219e38,0x0000000000054e8e}}, {{0x00045f27ccc6232a,0x000560683349d797,0x0004a272721dca0a,0x000181050663b9f6,0x00099733dac647c7,0x0002137c5f327d14,0x0001c703f55e4a29,0x00000000000da59e}, {0x000b58d5c8ca43e3,0x000c7baa8b4dce4f,0x000e015119c73eca,0x0008c1db0322dfa0,0x0007fd69954f99a8,0x000a29889394440a,0x00064a9060473da5,0x000000000002f048}}, {{0x000df3b38c2a0a79,0x0000190762c1ecbf,0x000c4019f47729e5,0x000849f5c47c645a,0x00056d72e7487420,0x000e11773b082319,0x00050eaeac683b8e,0x00000000000fb5c5}, {0x000722990680a985,0x0003e6d986d69658,0x000da73ac5c10442,0x000136fd94d52235,0x0009ed5b01c6d13e,0x0008fcdcc1aa7541,0x0005ee7c2014b140,0x00000000000cffde}}, {{0x0009c28bf944531a,0x000bbc7d0abb1f4a,0x000c2054201bd117,0x000defca80767df6,0x000871820908eb67,0x00074d19a6fa174d,0x00081a3215df4856,0x00000000000960a0}, {0x000602066fc6cc5c,0x0006993ed71807f6,0x0002dfba1c3883c8,0x000d56efe787e592,0x00098fe8b96f0909,0x000ab68115ae74fc,0x000e0c8fc342c435,0x000000000000b991}}, {{0x00047f2399bf97b6,0x00021c600dd569b8,0x000917d84fb94235,0x0000a27de43c1d70,0x000e616bdb162d7b,0x00029795321bf3a9,0x0008b233ce767c96,0x000000000009e439}, {0x000800714c3c1216,0x000934069cced410,0x000f1cffed0b3d13,0x000bf89c53942369,0x0009acb24e389981,0x000da473507d9c07,0x000cd9d2e5e904a2,0x000000000002f1b6}}, {{0x000ee38595e6d6e3,0x0003bfeecc6e7a5f,0x00087ab2bdd62b28,0x0004e20e81879cac,0x00089c4a27124845,0x0000749c3d0ea9cb,0x000f93ba8b6f3354,0x00000000000e971d}, {0x0002b66fa9a77846,0x000b64c2a1b129de,0x0005071339da6099,0x0000b53435739873,0x000a57040c00e6c6,0x00091a7b4b9f56a6,0x0002466de6489f62,0x0000000000053bc3}}, {{0x000554330abff5cf,0x000ae828a9dbe5c5,0x000263a5672326a0,0x000428089faa5816,0x00002dba2a1d1558,0x000197ae62da0922,0x000abba225f631df,0x000000000008f4eb}, {0x0005dcc2ee38818c,0x0001bbbadc9b2cb5,0x000ab544fb33427b,0x0006cc2759413f76,0x000121dd1222072a,0x000ac2c737b39ea4,0x000296d6baf9e196,0x0000000000075d46}}, {{0x000b2448cce42a48,0x0001555671128874,0x0000a30717d307ff,0x000207ce99ca16c1,0x00057c7a26b97e21,0x000c3ab00785fa10,0x00059f33c28658c2,0x00000000000d79cd}, {0x0004e804722ed471,0x0006f9a674db4469,0x000c9ef186db33b8,0x000722166bf2c6d5,0x000abd4c3791990e,0x000696ee1ba29aff,0x0006a5d98510cf20,0x00000000000f93d2}}, }, {/* digit=94 [{1,2,3,..,}]*([2^376]*G) */ {{0x000bbb4af21bdc49,0x00065e7cf5babca3,0x0003f75a29c95b64,0x000531d04fa84740,0x00045780efda9c1a,0x00062cb5a399e848,0x000f3b6e9c12be4f,0x0000000000094a5d}, {0x000aeeb34b3f3b9c,0x0006d3c15fe11c69,0x0009e05f576f256d,0x0006da4be294c912,0x000aa99b83983ef7,0x0001b9f6a5cf21d5,0x0007bf50679cf875,0x0000000000054d0b}}, {{0x0009b2dd4ee443f9,0x000fcc84f9171b4d,0x000ea8b580b8da51,0x000753ba05068eb1,0x0004077777efcdc4,0x0004cf44aa177ad1,0x00044e0b7f54eb7e,0x0000000000018601}, {0x000becbcecff7dd7,0x0002b1279ed4c55b,0x000e10b5af306b99,0x00058fab8cdb6cf3,0x0004a0c7614aebc9,0x0002c6d8ebc4f93f,0x00038ac5bd6cde7b,0x000000000008d65f}}, {{0x0000f0922779f009,0x000bb4da7d63a943,0x00025a4f402efdea,0x000001668841d1ef,0x0005b10366f61e8c,0x000b121e90688f48,0x000c1e38ee34b005,0x0000000000014e0d}, {0x000a8eaa6c54d224,0x000e683c1d44e6fa,0x000050a1a6ad5a9a,0x000274453715349d,0x000dc5ca18f66b73,0x000ef86e35065bdc,0x000f5d677313cf2d,0x0000000000033ebf}}, {{0x000a3669bab3aa8c,0x0001fffec66743ba,0x000af6b2298cee7c,0x0001365ee61bc95f,0x000e8948b6e23181,0x0001644be358bbd6,0x0007a71cd9c342e3,0x0000000000060a8a}, {0x000569b8813054fe,0x0000ae065519f224,0x000901053fc569ee,0x000c03b8517ae8b7,0x000173750d6e8957,0x000aee6d7c96a040,0x0001144eb2e364b2,0x00000000000ed099}}, {{0x0006635997173f0f,0x0003b71714896339,0x00025444ec94256f,0x0005f33fe56d0905,0x000638a1b2efb078,0x0000fc15add43e0f,0x000d362df35cfb36,0x0000000000090b3e}, {0x000659873829fac7,0x0000bd4970bdd7ef,0x000e315a3dccca14,0x0008a3e4a43c4f3e,0x000fd9cb4808c99e,0x000c3d0948013609,0x000223f3fef0eaec,0x000000000008642d}}, {{0x0005a811304eaea0,0x00018ffe3104b37f,0x000808bc57214341,0x000ed42cca2f1506,0x0002c421c69415aa,0x000b87b368618aa0,0x000d5f4d6a091dfa,0x000000000000e786}, {0x0009341357580c61,0x000ee0be97746d4b,0x000cd6467b049086,0x000823b7a70d4224,0x000809de860f6094,0x000cf60205928791,0x00086e7f7fca496d,0x000000000005f460}}, {{0x0007768861c39ce8,0x00007b509f7028f0,0x000fc09189281be1,0x000832a7f07f3291,0x000d8fbdcb83853d,0x000a4650d074fdec,0x00072080ed8de9d6,0x00000000000a5d68}, {0x00079ea50cb0600f,0x0009ae66666d224c,0x0008a45c66bc5d53,0x00099510da620fbe,0x000fdf866f777e2d,0x000045beb901145f,0x000008442a37e5db,0x00000000000beb1b}}, {{0x00048a2dbd606668,0x000c9bb39a179bed,0x0009439710e05c24,0x000abe3b91f14833,0x000fbd39a2bc6be6,0x0001d813ef972804,0x000d4a06737e54f9,0x000000000001a87c}, {0x000d0c4b5d0bc923,0x000b2bf88b2e5982,0x00052c33a491bb9f,0x000aedfa58af0431,0x0006ac0511b07a93,0x0007e2c198853cdf,0x000d8a9d7f416d06,0x00000000000f9671}}, }, {/* digit=95 [{1,2,3,..,}]*([2^380]*G) */ {{0x000f6957a24c76d1,0x000222e7d0a157df,0x0001697f0073308f,0x000ddc63eb317f9f,0x00015adf71d715f1,0x000858bc3f027507,0x00071a2ce33c2eee,0x00000000000da73b}, {0x00035cb76cad67cc,0x000de9ef6a709ffc,0x000c7c7ed1727cfd,0x000f5a67502de655,0x0001a47019739f5b,0x000ea7b24d11122a,0x0002e182cfaac2a2,0x000000000000a458}}, {{0x0007ab134ebd334b,0x0005196a1e74f032,0x00014e69e2323c83,0x0009c4fbe35109cc,0x00004521d7e61244,0x000d002931fad8b3,0x000229c85eb23d57,0x0000000000035f68}, {0x0000d113aed4dbde,0x0000c7c5b86677f2,0x000189b64d0338ba,0x0000456757cd5717,0x000e3a1c866b067b,0x000ba88c0eaab81b,0x0007dc72a6af75bb,0x000000000000ef56}}, {{0x000ac045af51c5bb,0x00010597a26ff058,0x00059bcfafa87a4b,0x000aff65c27f5f6d,0x0005d8d544e60b06,0x000275c32ce5ab66,0x000e7c92f031be99,0x00000000000f42e0}, {0x000c8a905adb28dd,0x000175bb28b05c35,0x00031ae347df4e7d,0x000d299f93fb7dcb,0x00086e2ccad9e73f,0x0004d4f57fcd999a,0x000c9bb8c8a6df33,0x000000000009a2ac}}, {{0x00030bea7fcf0ecc,0x0006a3afdee26fd5,0x000cc01988c78a70,0x0008ee3ba4a33026,0x000a2a883b7f340c,0x000d7412b1a6ea51,0x000b6e64f27976d5,0x0000000000091251}, {0x0008bb3d89325d7a,0x000d25f3f8f40ad2,0x000216e9116c139b,0x00073d6ad61b2cbc,0x0005d542676dde3b,0x0007d712bf08398d,0x000023d373931e8e,0x000000000007f96e}}, {{0x0004e4e1b942add8,0x000e15adf3d9957d,0x0005ba50de0860ba,0x000ce33a82d3736d,0x000e718c8aa3f9fb,0x0006ccf69f307823,0x00065b860578cf41,0x000000000001ef84}, {0x0009d5f6cc7a9ceb,0x000939ee0cf97011,0x0002f3cbdb7c8fc5,0x0009a8dc09da90cb,0x000dcbf3ccb8f99b,0x000a626321f521c2,0x0009da6bf6694891,0x00000000000854fe}}, {{0x0000917c5016c853,0x00049e44e3f85fb2,0x0000e1793eed8bac,0x000254501c4e171e,0x000cce52defb1004,0x00063100ac12df68,0x00035fb1fae2fbf3,0x0000000000035732}, {0x0007edc8c1da40d3,0x000c58d4deb655bb,0x000bfb14f6d9d28f,0x00085835a4e118f4,0x0001308772e93249,0x0004e48765abfa96,0x0007b241c7611ff5,0x000000000001f586}}, {{0x000782cfada548c3,0x0001e463031709b7,0x0005afd4d0d5166c,0x00097fff172c7d05,0x000735b193cfd8e4,0x0009df4bc7f7009d,0x000e376b9fd3f7f1,0x00000000000b46f1}, {0x0004c800fedd3a70,0x0000987c6eaa8c8c,0x000dff8047ad562a,0x0001042539eab96e,0x000779b8f5cc2a12,0x0007840dc29a6d5d,0x00030f33803a10b7,0x0000000000011a6a}}, {{0x0000457a60ad991e,0x0005e3c90a59f250,0x0005eeda9345d42a,0x000885c1a0d58e29,0x000d6816b0099aca,0x000e4718f77b9b6d,0x000c458e5c12139e,0x000000000004e4ea}, {0x0005f9c85e9bfc5c,0x00086c00c3568eed,0x000b5b4b0eba61f9,0x000ffc75eaf3eab0,0x000d42a87e32cba1,0x0007a882f5f99092,0x0005122e7b49c76f,0x0000000000029040}}, }, {/* digit=96 [{1,2,3,..,}]*([2^384]*G) */ {{0x000dbfc10083fe9c,0x000bfcf17f9dc084,0x0005e1e364b063e9,0x00054ffe437b29cb,0x0009e27ee9e2a694,0x0003af03b6628d78,0x000d6256e3b975ee,0x000000000002f532}, {0x000e1d6aa4b057a7,0x00043cae15213418,0x000003dc9b2b9ddc,0x000a959fa4d82608,0x00055ae17566902b,0x000c82eb4bad700d,0x000ea716b2c5dc14,0x0000000000036708}}, {{0x000e41b4a9c3409a,0x000849cbd62cd8bb,0x00047e8c2d4de38c,0x000bbe98f886eca3,0x00049b432990b7f3,0x00030035684860e8,0x00029ed19a3bafa4,0x000000000000e209}, {0x000ed539231869f6,0x00098f15ff660294,0x00050e66a84ebdc7,0x000de8d2955612f1,0x0006ec97a4a53ec6,0x0000d15fe2d95b4e,0x00024d868731f0f9,0x00000000000aefae}}, {{0x000253f48e5fab58,0x0006889f97859df6,0x000dee3f7bba228a,0x0001d4ea62a5c827,0x000ea3045da6826e,0x000d3d237ecba3e4,0x000358beed1da058,0x00000000000b8b41}, {0x000293271a9d4293,0x000d2730e7ac94c3,0x000f438703e7096b,0x0004cace8c1c6462,0x0001055d39de9ba9,0x000b71db3ec7c382,0x000a11c89705a82f,0x00000000000781b6}}, {{0x000606caa5686427,0x000cdc1951fb0886,0x0000daff401d6319,0x00009bb2754f1d38,0x000e0e0e2bf19831,0x0005a3da40f7db33,0x000197348c4e1937,0x00000000000840a6}, {0x0008d7f45b2f9769,0x000d11687a735d22,0x000434d1e1dee1ff,0x000773c0aa9e79d1,0x0009f56de9654a25,0x000dda7af656f6e2,0x00063fdf84666df0,0x000000000003f9e4}}, {{0x000a9c9951735edd,0x0006afe9f90d3ad9,0x000f97a0b45a07d7,0x0007d6ec36e3b706,0x000f580c8e6dd513,0x000bab45c3ea55f4,0x000d5819398b33e1,0x00000000000aee76}, {0x000d9c115c469d59,0x00071e72c8214ce4,0x0006b3ef7ac6abe3,0x0001ac198f9553cb,0x000a1c98ad467fa5,0x0000ebbb2019ac4e,0x0000a68942e16e01,0x00000000000bed3c}}, {{0x000f13cdd62e69a0,0x000461a814bf695a,0x000e4323f4986584,0x0001bfa2a4dd16f8,0x000a76fb9f2b33c9,0x000b1f1114af4d9c,0x000b45a23635ef75,0x00000000000a0891}, {0x000bef0dcdd6b903,0x0005f5d1b87ba5f6,0x0005d7ac1d6bdae8,0x000cb4543d4ef435,0x00064aa784ea70bd,0x00070e4220ed12d3,0x000483009cd34901,0x00000000000280cf}}, {{0x000bddf9aa596a1d,0x0008952c04b79c0e,0x00099a2770f3fa4a,0x00044bf1911b3184,0x0006bb897d318407,0x000e9de5dd13f080,0x00052b376dc8b81d,0x00000000000c996b}, {0x00047f465159b51f,0x00041d91e47b224a,0x0009b71ad19e642b,0x000c167eface7572,0x0001d4805ed6a441,0x0003fd6654eb9588,0x0005778fc93daf3f,0x00000000000cc570}}, {{0x0000b16f46a35f8c,0x00065a630c20c4e5,0x0001f4362772ed03,0x000aca10c0dec6cd,0x000ba9e2f55428c8,0x000bbb1705d34bb5,0x000f6e8e81b4f732,0x000000000008363b}, {0x000ca7950547e910,0x000969603fe028be,0x00047954fea1ddef,0x000bb8efc191d12e,0x0005dba97347c0da,0x000656aaaf0e463b,0x000cf0b7f7c207a8,0x000000000003f08d}}, } }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPRECOMP4_P384_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecprecomp4_p521.h000066400000000000000000015742111470420105600337430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPRECOMP4_P521_H #define IFMA_ECPRECOMP4_P521_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (4) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_SLOTS NUMBER_OF_DIGITS(P521_BITSIZE+1,BP_WIN_SIZE) #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static SINGLE_P521_POINT_AFFINE ifma_ec_nistp521_bp_precomp[][BP_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x00031a16381adc10,0x000f3f18e172deb3,0x000e0c2b5214dfcb,0x00017fd46f19a459,0x000ac947f0ee093d,0x000d50a5af3bf7f3,0x0001457b035a69ed,0x00009c829fda90fc,0x00011cada214e324,0x000274e6cf1f65b3,0x0000000000000000}, {0x000460e4a5a9e268,0x000f4a3b4fe8b328,0x0004351396120445,0x000fd683b09a9e38,0x000132062a85c809,0x00064bf7394caf7a,0x000d7de8b939f331,0x000224abcda2340b,0x000163e8deccc7aa,0x000de0022e452fda,0x0000000000000001}}, {{0x00090cf08640909d,0x000f1c99dd36bc1e,0x000b26b07ecb3fa1,0x000ae2d7a0e797d1,0x000aa83d508251d1,0x000bd9d9026d377a,0x000372a82ebb4df4,0x0003cd8e66031a96,0x000a461413a3a019,0x000f3f3417e59440,0x0000000000000001}, {0x0003d2ee331fe1b6,0x0001ab6b30fa0d81,0x0004af6e07a7b8df,0x000d19247a757e5f,0x0008fb5c9c9bfd4c,0x000dd9f1bbef4f92,0x00090d14c836216d,0x00083e26d4bba055,0x0007769f85ae35a8,0x0009338053f9f677,0x0000000000000001}}, {{0x000e9cf4d4910f78,0x0008ce976f1bd6be,0x0004316197502d2c,0x000acff10dd75a48,0x00019028ed35e8b5,0x0008d69f8b251d24,0x000d6bd0896bd46e,0x00072d891ecd5cf2,0x0005acaca3cda953,0x00048caeec8eb532,0x0000000000000001}, {0x000cfa6c0ee5f7e9,0x000c4650f7436072,0x000de49d2c8212fa,0x000f61e3867882e4,0x000bad816ad6768e,0x00061716ea67c6e2,0x0007c558fd1aae77,0x000fd4154e818be9,0x000655c0a7978aab,0x00016eeccbcfc363,0x0000000000000001}}, {{0x0008d6d77d92b8ab,0x00043a09438c8179,0x0002d8472d2f17de,0x0003c5783350ea81,0x00083a8745c474f8,0x0006432cf1257f1e,0x00062eaaaa0e9e75,0x00048e2ff9cd7e03,0x0003e483866e30e4,0x00010261aa5a41a4,0x0000000000000000}, {0x000a0825be109849,0x000fa3fe1a372686,0x00078234ce8ecf10,0x0004adc2f75dbfd7,0x000c2a029127ba85,0x00093cf941f2a5d1,0x000731ff178cc83f,0x00077b7371970dad,0x000585a55db2a90d,0x000ce95b39f00bc7,0x0000000000000001}}, {{0x000194afcf14a49e,0x0005a84b7647983c,0x000f36c498b9c6ad,0x0009bf3cd194ebf0,0x0000a11b8897f578,0x00021c1e0636af18,0x00081ed5c78bbd67,0x00077eda9f869267,0x000e027585fbd2cb,0x000219639ede19c8,0x0000000000000001}, {0x000d6f9bbc6f7598,0x000e61f46f584865,0x00092b9aa7bfc0b9,0x000e7affbce8f803,0x00079ba188aa0108,0x0003ddb44be48396,0x000ec0be4d01a384,0x000f4743970028f6,0x000a54089488e6c7,0x0000eb764515b988,0x0000000000000000}}, {{0x000fb915a75b36d6,0x00098df6fbc9035c,0x000ab2bf9c05711b,0x000a98df4617b374,0x000b9ca70393d11c,0x00092fde650b0a9f,0x0000a8356f25580a,0x00084bbfeb8e79cc,0x000a24068cab11e9,0x00090ca9977f9a7c,0x0000000000000000}, {0x000f780956b43319,0x000666bc2c6a278b,0x0005aae506d6f0f5,0x00013a79101ee3dc,0x000464efcb64c26f,0x000b655b96872b32,0x000205493100d454,0x000db9ed2d404739,0x000a371d8889555d,0x0007ac35716e9382,0x0000000000000000}}, {{0x00015b574766756d,0x000756c4140b766a,0x000a87ee130cd00e,0x000e71dde237ca9f,0x0004c6c64d36f986,0x000ec61846855fe3,0x0000c69617b88a62,0x0000747aa4191478,0x00005839d062f917,0x000fb1a3775b2fed,0x0000000000000001}, {0x0008f4b46df66eaa,0x0005c5e48292928d,0x000952eef7e3dae3,0x0008e70d2fcf3b38,0x0004f15ca91d1a2c,0x000ab5e87949e6f6,0x000edecc51365ef2,0x0001681412786eb8,0x0001ceb423c5ae2c,0x0001508868ec18bd,0x0000000000000001}}, {{0x0000208b103ed8c0,0x000cf52a553c6734,0x000dad37a0202c37,0x00046bcf0d5ab144,0x000a4f845acc60de,0x0007adff52dc2bcf,0x000c51d82fc1314c,0x000ec54d801f0545,0x0005808712dea714,0x000fb931541a41cb,0x0000000000000000}, {0x00058cc64475550b,0x000b21788f8bc00e,0x000a004a389a9c56,0x0002e2bc34cf9dd4,0x000da5ff85d06f83,0x0008c4f4e0552c88,0x00041ef30833bd47,0x0006f4f16038ada8,0x0003c429dcd227c7,0x000e2410247ed5b7,0x0000000000000001}}, }, {/* digit=1 [{1,2,3,..,}]*([2^4]*G) */ {{0x000f45f44362a272,0x00062847c0d42017,0x0004003ee6e299d3,0x000c2b186f86dfae,0x000005072cb2ed3c,0x00094a1ff8c430e5,0x000197c69058c452,0x000b30c97e9f9eeb,0x000563a1d859543f,0x0005682eed4bed13,0x0000000000000000}, {0x0001e8dcd0f160b5,0x0001397c4de39d5f,0x00069468c3199a97,0x000eccc4294f1802,0x000a3d505983ad64,0x0000e0c1709cc6da,0x000e51864a5b5c16,0x000261dc006a8763,0x0009e9f34b9099af,0x000b800fe38a58c6,0x0000000000000001}}, {{0x00059ae8d65b4828,0x0008ad5c3b72b54f,0x000ae6b62e3c123c,0x000d2e8fca4e7ba3,0x000cb7633eb4deb5,0x000b750251aee39a,0x000d3f677dcf2f5e,0x000b32a703401c6d,0x000a5d0ad9a1f1f0,0x000d234a21b83d7c,0x0000000000000001}, {0x00011dec3fd34650,0x00054d4c8a50ab55,0x000b2d5cb0b1b4ae,0x0005079b6fe6cc64,0x000eb5cdba6f0e3f,0x000ef10266dc0c66,0x000ef80e32e16ebb,0x000c5faff80cb3e0,0x000f9f041347fbde,0x00055c088b1af3af,0x0000000000000000}}, {{0x000fecd778ec8555,0x00013eb0956c3cd6,0x0005e90a57516438,0x0007f84773320ba9,0x000dfd66f6e10d88,0x000a16d04c079fb7,0x0009e6452c01f397,0x0006b339081619a5,0x00076316466573eb,0x000a315640ac72e5,0x0000000000000001}, {0x000e34d296b0561e,0x000ac0c9e92b6a35,0x000402420e573d8c,0x000d871e142cb792,0x000bf1bdbe0a1707,0x000d7310a6b250ec,0x000894a7b366170d,0x000fe4a684f16643,0x00025d9fae0bb793,0x000c96f6d42adcf6,0x0000000000000000}}, {{0x0006ae6a85f73844,0x000ee1c671907ba1,0x000014d027ea0da9,0x0001f3800efad55c,0x0001bb9d3e0160b0,0x00038df5e9e2f7ed,0x0000a5ce67c43969,0x000dd40c305dd65b,0x000c97f61533f5ed,0x00097668a79ebe01,0x0000000000000000}, {0x0009d235c3ae123a,0x0008b82c52fc6fad,0x000edd0329eea2d7,0x0007cac021e0e0d2,0x000a5887a53dcf1d,0x0005d60b2dd0a846,0x00031dd1b4f43d5c,0x00064597d8ee0e86,0x0002bdcac36cdd8e,0x000902b9d50810be,0x0000000000000000}}, {{0x0002ff15cc9efbda,0x000d0adea1bf15e4,0x000712003c28f70c,0x0009acbb183fe29d,0x000e35ff46058b74,0x0000e6fbe9505c1f,0x000949d4ed7c586f,0x0006bc96db22c518,0x000e9fa6b4caa767,0x0006b3b723ba4dae,0x0000000000000000}, {0x000d4a1dbb01ce30,0x0002733373d1589b,0x000695b9bd79abea,0x00024c417444789b,0x000a3e366b3687f5,0x00018eccb8e87edb,0x0007fa4355949d4f,0x0003b1b5225855c5,0x00040d600e111ea7,0x0002ca9912224327,0x0000000000000000}}, {{0x0001ccaa77955b13,0x000980cc45066e57,0x00005f6f02b3f9b1,0x000f381f6757639e,0x000d14e03775ce84,0x000770c3535ef348,0x0000c573845ff7f4,0x0007edbd50365fb5,0x000ae96135b16a31,0x000b1cbda8a1cae0,0x0000000000000000}, {0x000fb5af8ac6debc,0x000ccace499e422e,0x000f85f9a34dea5d,0x00099ffe8fc76f8d,0x000700f62f621078,0x00048a20afbdb94b,0x000353ffe99ecf56,0x0009d5421253436c,0x000d53ffd3fcac92,0x000092a9413337e3,0x0000000000000000}}, {{0x000cc6739bc22034,0x0002d46c578a3cfb,0x00074dd1918f2158,0x000820e4ee32d9c8,0x000ee4769c451119,0x000a52dc0b788cd9,0x000ea08ad1dce239,0x000e6c51ce30fbf6,0x000c6808b739646f,0x00014612aa8ed807,0x0000000000000000}, {0x00084f57ce386096,0x00001bd8dd33a19d,0x0006d6cf7616b3bf,0x000aa0ec8a31fd3f,0x0000f33cd7d20cf3,0x000d8c7b490a7ae4,0x0003afd25187398f,0x0001d4b82d520c24,0x00008bc63a1c99f6,0x000da20702f937af,0x0000000000000000}}, {{0x0005f3504967c9f8,0x00081372b9b7d4f0,0x00090711a09dabb5,0x00052fc0a79713f3,0x0008ebea8efb840b,0x000ba724a4b43b13,0x00089257bae703ec,0x000c5de16b6e9669,0x000a9811fd41e4b4,0x000c0fc1b18e0380,0x0000000000000001}, {0x0009bdb977d41aa0,0x00084a0964efd898,0x000049a3954725e1,0x0002567309871a1a,0x000d6462734e1923,0x0004d24ffa586e4c,0x000a7d5e1d8d7ce5,0x000f69f3efbcb30d,0x0007de3d3416e700,0x00041ee729987fef,0x0000000000000001}}, }, {/* digit=2 [{1,2,3,..,}]*([2^8]*G) */ {{0x000757d0283c0ad6,0x000745c834df0056,0x000e5caf285c0d9c,0x000faea391f23599,0x000232d4e48a9620,0x0009bdc7a7b74615,0x0002fd4f47934e59,0x000c4f65ada3d4dc,0x0000798974c81e39,0x00061064a2c57e3c,0x0000000000000001}, {0x000a38d40ea9cd04,0x00060922a435ef3f,0x000a826a53bc247d,0x000e94d33d8a1866,0x000de75ac695cced,0x000bcb2e7b2b9c71,0x00016e1d52b9aa78,0x000540f2da2b1a83,0x000881db4e2a0769,0x000e217e4c0ddd49,0x0000000000000001}}, {{0x0008396a04a1a9b5,0x00071e1d4dea3fc9,0x000f1b1b60428524,0x000875279e270a42,0x00031e46c1327bff,0x000c05c823fe0222,0x0001988e4c1b07ef,0x000346e86dbfa458,0x000ea14d7c3803e0,0x0002698c2f4163f3,0x0000000000000001}, {0x0004df73f1c64b3b,0x000bae3f77cba047,0x0009fac52f482f0e,0x00046303eabe2a5c,0x000605a86c7774d0,0x0006157561d8716f,0x0006dae76cfe4cf1,0x0006f10528e0564b,0x0008d8ad69113bb2,0x000c2f933ccc8b87,0x0000000000000000}}, {{0x000963cd234bdeab,0x0005b961fb152043,0x000192d80595fa4f,0x00021e095276439a,0x000ab3cdd8200acb,0x000b977cb97a7564,0x000f1ac5e95df534,0x000082ed91f8da63,0x0005eeb0ff149253,0x000e11676ac3e35f,0x0000000000000001}, {0x0001cccbb8a0782c,0x0008ef764987a4d5,0x000621e7649cd3df,0x0006ca705ffe9912,0x000d887d63f6769b,0x000a2f7ad40e5963,0x00074e3b9fc2e426,0x000bd597aa3dacd3,0x0000fea916df09cd,0x000c4db4a1b5ffeb,0x0000000000000000}}, {{0x0006312ffff6fab5,0x0006b5b394c36d7c,0x000ae9f8123d8c52,0x0007a4616b7fb3e1,0x000a92d9f22f9728,0x00095d4a0fd21b31,0x0002d23d7cbfded8,0x000b5c10574881ff,0x000e2bd04e830bd0,0x000fd69dfeb7774f,0x0000000000000000}, {0x000b243fcf68f023,0x00066b7e7441cd83,0x0005c91b009a23e1,0x000f85c785f70865,0x0002122e7768c122,0x000fb751856db403,0x0001836d6df94b82,0x000098df3edc80b3,0x000298e9aeea7ce8,0x0006e6048ecb9605,0x0000000000000001}}, {{0x000cad0b80b053c4,0x000883158e365644,0x0001acd6f66175a4,0x00078eba00f9062c,0x0000f302446bdc8b,0x0004ffcc5c874a3b,0x0001cc9e542baabd,0x000ca8d66f56fe73,0x000fec6e656e27fc,0x0000e12576ad29e3,0x0000000000000000}, {0x000f2114ad6a5008,0x000ff37b5e9ff077,0x000fe609c9e85ddc,0x000612f68cb97937,0x00035cc97418d8cb,0x000e6da8506bf5e6,0x0001561e4122e23c,0x00026ba1b08bd010,0x0007eb4a708cbd94,0x0000c9d309deaf41,0x0000000000000001}}, {{0x0001bba765fa9bcf,0x0003babdc21b3ff6,0x00025b55117dbb2e,0x000cd85081bffb4d,0x00081cb8cbfa61b2,0x000244b920db891a,0x000db06e819df932,0x000532ca257bcc77,0x000ade96bb81f698,0x000552846b3d2e5e,0x0000000000000000}, {0x000cc4965acbbc52,0x00019fc3317e41d4,0x000a394d289bf4a3,0x000dfcc926b6b451,0x00099fdc4795a3bb,0x000fbdeb87e6005a,0x000e9db4adbdc0b3,0x00050e680b14c0a6,0x000a1f2811642efe,0x000396ef97cb540f,0x0000000000000000}}, {{0x0005f3ef0a7bd1f0,0x000acae8e898fb4a,0x000ba953fee10eac,0x000ac34b13e74541,0x000d80a4f317458b,0x000699b6bc22b700,0x0009d659b3752d47,0x000972beec5644da,0x00015e14a99a228f,0x0008731fa64678ce,0x0000000000000000}, {0x00076f9ee24a5ff4,0x0001761a3d49abfd,0x000099dc50257cde,0x000182905bef244d,0x000f586d9a90e6d1,0x0007ebb4cb4857b6,0x00070d79d0a32ad0,0x0004bfe6c4dca5d6,0x0009e03cd5b7b143,0x00028c04a0538f51,0x0000000000000001}}, {{0x000c6fc14a74584c,0x000402292021e48e,0x0009500ecd0a9680,0x00002339ed719b16,0x000ebb81e8a19412,0x00040e8e4db85440,0x0002a313f6a53c2d,0x00082796c5c684a1,0x000636765497c008,0x00020c751837b791,0x0000000000000000}, {0x000740897b89a933,0x000f39feb6c7cfd4,0x0006675504305fd0,0x000708d724da0165,0x0003fcde5846c915,0x000cbcc847c7bb1c,0x00035875d5c58a40,0x000f531dd999d009,0x000ff3f98178ab52,0x000a7c4485d31888,0x0000000000000000}}, }, {/* digit=3 [{1,2,3,..,}]*([2^12]*G) */ {{0x000bc092fe2354e8,0x000850a2f27fd64d,0x0002ad51407fff03,0x000808402ffc14aa,0x0007fbe516b67c4b,0x000f027098449910,0x0009af3715688b40,0x000dbddce7795e2c,0x0008a5dc626ec8f7,0x00032acc9e1305cc,0x0000000000000001}, {0x00014a5956e30ed0,0x000921ce664e13cd,0x000b7485d5a678ff,0x0001d65fed6fe685,0x000152b7d0453dd6,0x0001e48dc7a066d9,0x00012560c3395f08,0x000d6053e587c1cb,0x00076afca630f2cd,0x000814f0d70553c7,0x0000000000000001}}, {{0x000a19c3686b1f78,0x0009545540d3da61,0x000fed5fc9dde90b,0x0009be8908cbe546,0x0002b931292ec657,0x000e0b221531c8bf,0x0003dcf64709233d,0x0006a91e2913f0e3,0x0003880d89929920,0x000d07ab37b02493,0x0000000000000000}, {0x000b1d587081c0df,0x00062b5f29f3ee6e,0x00013755e246f468,0x000c2e51e2652ae3,0x00046ba6a65e2952,0x000fd1b792013b94,0x00049175e7bffb43,0x000166af7dd896a1,0x0003d0d5f68a4101,0x0003a34ff29cf955,0x0000000000000000}}, {{0x000b9e5f2e5de279,0x0006be9e4c557ee8,0x000c510883da6331,0x00016eedfba63955,0x000b55eba66cb586,0x000d93dd071f901b,0x0000d11e4c33f467,0x00029c2288bdd752,0x000f22d4f3c9b728,0x000416f979cce9a3,0x0000000000000000}, {0x000f91fa66b3408c,0x0009041780ab3969,0x0001e17f9e99f2b3,0x0002825a0408a22e,0x00013e814b39af10,0x00017c70c14077db,0x000fd91116e8d047,0x00025157bba11642,0x0003d53fd072760c,0x000130f596860d22,0x0000000000000001}}, {{0x000ddddf5d1e5c64,0x000b39631d236577,0x0005fc5e812c4b6d,0x000ec807d1cccab0,0x0002c8729f1a1c38,0x000999e4061629e9,0x00088f56b4c00d1c,0x000c3cac8f29781d,0x000b02141cce3380,0x000920c7e0e0cc16,0x0000000000000001}, {0x000234580d88382b,0x000b0ad02da7d076,0x000cc82cf5ae2d27,0x0008a15c3adad7f2,0x0004d7009305d2c0,0x000e9e632a55fa7b,0x00011560b55b693d,0x0008b565732e2a82,0x000f0adb63788cf9,0x00038e2d1f605489,0x0000000000000001}}, {{0x00007e33611831c8,0x00062ce163c826e6,0x0001c1873d3e07b5,0x000df7813a79a532,0x0007451a6bebf65d,0x000789f014abc3f1,0x000cc2aa01512853,0x000bc25e7cee2985,0x000dd32f61a13543,0x000f9b061a57a2a5,0x0000000000000000}, {0x0003734e520ae3c4,0x00041544fe045295,0x000321b2f9da98d0,0x0004ac066f5c4118,0x0004f9ed8d4d338c,0x000c2ea3577c3f4a,0x000a775eee973782,0x000efa3a3176188c,0x000aa0ec53f7823f,0x0009b227eec20996,0x0000000000000000}}, {{0x000cab486125bb6b,0x000ce02028378ff0,0x0005e625f7d1c380,0x000dc7cec93bc7c0,0x000d0c3b6e1a5a67,0x0001da033baa95ac,0x000e0b126ba3c688,0x0005b900f71e6919,0x000cfb69d4bcab68,0x00090d9f859cecf3,0x0000000000000001}, {0x00030307c7f8906c,0x0006bf1f14afae02,0x00001d0c8e70d7c3,0x00031fcdd396a945,0x00035972de152221,0x0001149c59aa6c9c,0x000e743c53f3251e,0x00072a17186bca64,0x000bae52281f6178,0x000c98982b2d35fe,0x0000000000000001}}, {{0x000abaada33bf5eb,0x000334cbe9475074,0x000503921efaf87b,0x0001a3119b05ca55,0x000a4fa919940136,0x000a8bd8f158f3c3,0x0002e855587cab4c,0x000fd133003309bc,0x000a468f055eab49,0x0008de65f435935f,0x0000000000000001}, {0x0005a479ed62ca37,0x00046fb6c0237009,0x000c6558be89daa3,0x000e86cd9c606b6e,0x000dcb5426f2b48f,0x0002744bfa702fd9,0x000e9ceab7372571,0x000cd8bef4768a91,0x000d361ea2d4f5d1,0x0000ca847b5f94d5,0x0000000000000001}}, {{0x000c6a7b65b21bde,0x000fc723a29c73b0,0x000392643c39c3ea,0x0000b213f81be3c4,0x000e3ec734fa388c,0x000b26d37a33b98a,0x000332e230742689,0x000e28354ec1687a,0x0000d4b7e6935b64,0x000ba79d55aecff6,0x0000000000000000}, {0x000073362910afa1,0x0007fb8bcd336bd6,0x000b6c7a7845b5f6,0x000017305633e845,0x00076a907be72df6,0x000e65734d2814a5,0x000f113c7084b86f,0x000cd7bad9f20758,0x000f6af2a5030c22,0x0001647ff1cabc3e,0x0000000000000001}}, }, {/* digit=4 [{1,2,3,..,}]*([2^16]*G) */ {{0x00084cce9eb37269,0x000406ac65525f61,0x000c9acc4f25051a,0x0007bdd2651c4a44,0x00059571fa6bdb63,0x000cf1489d2ae9ce,0x000a821f56bdf324,0x0000e5fa827f61b0,0x00046a2449dcea62,0x000c947027c9ed4b,0x0000000000000001}, {0x00095f1c50d4d450,0x0002c227a410cd04,0x000bc9ba135ee643,0x0004257073536858,0x0000b7e39c350531,0x00016eeb65d0616e,0x000e949a694a0693,0x00069aba0dc455bb,0x000d36d721f9d7b7,0x000a041dcb7a1d32,0x0000000000000000}}, {{0x00030d330fc15e51,0x0006a88312448f9b,0x00027c12fd1499ca,0x000b765eaf5a132e,0x0008d01b2d2a5c3f,0x000e3517c807951a,0x000936a97c68ed6c,0x000f8cdd161ce67d,0x0005d9876ad5eb28,0x0009976496ac4a79,0x0000000000000001}, {0x000d912524de7c0e,0x0001e66e4dff627f,0x000a96a9194e4460,0x000ccae884a673b1,0x0005d06054966f81,0x00032269452eba8c,0x000ba7677e70b535,0x000298891e5c17de,0x000f9a70e2fe55a9,0x0004d48b39032dcc,0x0000000000000001}}, {{0x0009dc9a72f4ff50,0x000df54e86b3f74b,0x000b7fc672cd56a4,0x000ac313c91daa4c,0x00053d8b04fac047,0x000047ffb771df8b,0x000a8ad48cf7c44d,0x0008bf663542e196,0x000aa68b0ea4fed6,0x000483dbd49e0b45,0x0000000000000001}, {0x0007d603e389e5cb,0x000ee233664de2d7,0x000994f96855ef7d,0x000c5bf8c8ab10b1,0x000c2f5ab3d235e3,0x000bff37afff2ae5,0x00050de9d0fd0f4d,0x000ca6d91d5250db,0x00042da0be2c950f,0x0001c70ec3836fa7,0x0000000000000000}}, {{0x0009b222a53c1578,0x000733b1bb114a22,0x000887f6c13ff59f,0x000d5dfb2679cded,0x0001fd35dec8bbba,0x0000930770ea94d4,0x0007da8d4f0a6019,0x000d2142901c2ad0,0x0002aaa8648f142e,0x000f42252e455969,0x0000000000000001}, {0x0004f335e4753950,0x00010578c42f0d9b,0x000fda89975c2716,0x000761372c49b195,0x000583ac76051357,0x000cd0c4d54de0d0,0x000c35f47ffa549f,0x000731f21817e11b,0x000ac2b103f57a56,0x000284cde0cd7146,0x0000000000000001}}, {{0x000bb2a3bcba0504,0x00052359d22ba169,0x000ee4d727c18bc1,0x000338aababfd9ca,0x000cae35505124c8,0x000599b6e8a9cc3c,0x0003c6415386807e,0x00043919da2fc5ab,0x0001a4c6fd2ee43d,0x0007be38ead93480,0x0000000000000000}, {0x0008c66b564a97d4,0x0002177834d44e8b,0x000690ef30774807,0x0007151d926feb1c,0x0003fbe2f1f3454c,0x00048ce8e6456bd0,0x000270c04a6964dc,0x000fe8febbc7afec,0x0000f159a483b3a5,0x000aca96cb139ad3,0x0000000000000001}}, {{0x000c0e9763d8a013,0x000baa65d7b1d37f,0x000608a4b87c8c06,0x0008c2592e527b8c,0x000aacc19bb3aa2d,0x000ce5b0adb09308,0x000e0f42458761d4,0x0002d73d4f707a6e,0x0003867f8d791c44,0x000c943ba7a1a60d,0x0000000000000001}, {0x0007ffca3e51b076,0x000d23467af3d90e,0x0009427b9fa60c44,0x00054ce0e4a16358,0x0001655e4129aaff,0x000befd5ea275c28,0x0000ce27c03c7fcc,0x0000c97ca421b716,0x00069ee6f84bb35f,0x0007ec35e0436eea,0x0000000000000000}}, {{0x00033b8c99430421,0x000e3aa65723117d,0x0001482e2ca3fcee,0x0006dfdb52560262,0x00036a105a9eb6d9,0x000c0fd8b7bdc41e,0x000c58ba2f2edd58,0x000c050043d8b271,0x0009966a34a51907,0x000aee0fa52e13a7,0x0000000000000000}, {0x000c2d7066d5fc91,0x0000d462accbe2da,0x0008397028d0b78e,0x000b525e2c9d107f,0x0003dfedd5666711,0x00083957250c9620,0x0006d0f2be094638,0x00026dd96c8ff985,0x00098fe829c7a670,0x000dacfc430b6d43,0x0000000000000000}}, {{0x000aba8bae3f0048,0x0006fc5f421abd9f,0x00094ac402ce8227,0x0005bead91f2efc8,0x000d28241f32e7d5,0x0008bce170cc1090,0x00050cb19f59df3e,0x00034ac35c2de273,0x0003cf90c3e6cfc4,0x0002a784bc2847d1,0x0000000000000001}, {0x0003f87f754f1aa3,0x0003382713cbe9fd,0x00034163c334fd8d,0x0004cbe346cada61,0x000dd6aa94a54721,0x0007b9235830a042,0x000500be120acf2f,0x000d30c3e8d009be,0x000225e2751dc7f0,0x000714b7edd06e6f,0x0000000000000000}}, }, {/* digit=5 [{1,2,3,..,}]*([2^20]*G) */ {{0x000c1256fe47d13c,0x0007012fd1181020,0x000c4a469315aa78,0x000b1163ea26a86c,0x000e4be00b905056,0x0002f1dad4a0ac68,0x000e2d8c19c57695,0x0000bbc11daec6fd,0x0003baf9c6293f81,0x000d375056fba03a,0x0000000000000000}, {0x00073f08bbfc9af7,0x0006c14cc716b559,0x000b5b613b18efce,0x000f005d64d3ad94,0x00034ba83b800248,0x0009ee4cf2a375eb,0x0007d29413af2a4c,0x000525ea872268a2,0x000c082bd8d12fde,0x0006fa2d233189c9,0x0000000000000000}}, {{0x000f1bef2c1b123b,0x000c9ca73fb5cd85,0x0001a80d76a111a8,0x00025f888d3b7461,0x0003f7765b87f2e3,0x0002e36012c8ad9e,0x0009dc42c7cf6c49,0x000d7d5db366bf5a,0x0005359f96228a81,0x000772725123cd91,0x0000000000000001}, {0x0006c7a0e2cfcba5,0x00097fa38cc5da8b,0x000b43bb38eee14f,0x000f15c0770c4afd,0x00093138850f3aa0,0x000658cf7e3953b9,0x0007c8bb70f07792,0x0000d78fd38c1d44,0x00023ebe4681177a,0x000c9d704ca7518e,0x0000000000000001}}, {{0x0008fa7e4527a9d3,0x0004db4e9fda74ba,0x000404855f433494,0x000f130f65201753,0x000d719a9846d31d,0x000c651ab9661cb9,0x000b653c04c2995b,0x00031b2c3fb591c2,0x0000b91d21b65fb3,0x000c1f9233b624c9,0x0000000000000001}, {0x000eac108061f9eb,0x000a2e86d9cc5afc,0x0000e2ec8f94cdd0,0x00040675309b7d38,0x000320d2223f6f2c,0x0003be480dc1e34e,0x0007b72b364f62ba,0x00063595753dec52,0x000283d90f6639f0,0x0001d567ed0c354e,0x0000000000000001}}, {{0x00067e2e3d478324,0x000b9d2b33e93756,0x0005cc9c7d0711cf,0x000aa7c2edf0adb9,0x000b6610b704fc5a,0x000107368e770150,0x000cc4ef9af2a471,0x000afe1e566d06e6,0x000a67146814dd0c,0x000fd36c67f6637c,0x0000000000000000}, {0x000b744b33ca6a46,0x000a2ad960d19dec,0x00099ff41dbc0bcf,0x000977ca933b28a6,0x000a7951faf63b97,0x0005168f23ca3752,0x00097d901e0f16b1,0x000105f55f964ea3,0x0003c0d403b374a5,0x000d43e408ed3a81,0x0000000000000001}}, {{0x0007586c50a55f86,0x00026583c230d093,0x0009c8f1eaf61062,0x0009876910419f67,0x0006e8d67dbad2c6,0x000c3c184d440783,0x000753899fd2f814,0x00037825fefa52a3,0x000f0758545a721e,0x000498a4b823d5ff,0x0000000000000000}, {0x000e376ebd4ed258,0x00004d6a23fbe496,0x000b69ec3505f765,0x0008fe6b545afc26,0x0000e87ed2073fb2,0x0006145047af95f2,0x00053f84d27cd1ba,0x000fa35d865dc4cc,0x0007b711a9ee96b7,0x0008ec430aefdeb0,0x0000000000000000}}, {{0x000354ba169146af,0x0008c79fdb88cac7,0x0009f85e2efdc64a,0x0001012d7f3a69d0,0x00017d2bed232563,0x0004dfd89cfd4d1f,0x0008288e64d46be0,0x00089f8bf20fd559,0x0001d08641f269d1,0x0009fc333e29ffc1,0x0000000000000001}, {0x000c7dab1b832059,0x000223bbef8e949c,0x0007f10fed75c714,0x000647b0bb61d266,0x000b8e823dbf309c,0x000601c5a1f58db2,0x0009c023a71fa3e4,0x000a0b5cbdd6344f,0x000df6a6577b11f1,0x00027e6eb12db5f8,0x0000000000000001}}, {{0x000b94e9f2c64c2a,0x000dff9c4cc3460d,0x000339e03c0646b9,0x000ca76c7ae26f18,0x000612ba1712f64d,0x0006950e5f2c8040,0x000569eb5bf0fae1,0x0006185858b613d1,0x00080b1245b35ba8,0x000d9a3c93740668,0x0000000000000000}, {0x0005f1c44e1c9646,0x00061096f83044ee,0x000e69176fe10924,0x000a78875cfb2614,0x00007825516a8324,0x000065d69cfbad90,0x0001f873d71727bc,0x000185c81c530662,0x000c1471ae21856f,0x00047e68582e4e3a,0x0000000000000001}}, {{0x000ce1c67b68f07c,0x000dfa5469124c9a,0x000ccd6db2024f3d,0x0002fc6faadd52b4,0x0005124af076574a,0x000510591517b271,0x0000081118a106bb,0x0007cffda2d67e24,0x000b3b39fc6925ec,0x00012037b374e288,0x0000000000000000}, {0x000d91b81541ec51,0x000c413a683e17ef,0x000952a60eda72b7,0x000b61d80495c130,0x000f6bf06a5749c4,0x000c7cbd39872c4b,0x0001a82e01cb7ce0,0x0001726d7547989f,0x000742de944906b4,0x00009f2e02ff3752,0x0000000000000001}}, }, {/* digit=6 [{1,2,3,..,}]*([2^24]*G) */ {{0x0000872f1cba7983,0x000a9c28a369cd44,0x00007ce63b6f5daf,0x0009c12dc12c54cd,0x000a00a67eec84f7,0x000bc7a4edee7a34,0x000ea82ff4e7f63d,0x000950ab492940f7,0x000953027dc3353f,0x000be21b37a3c6cd,0x0000000000000001}, {0x0005f758ab77d6e7,0x000bab416ce18f4c,0x000b9e45e70a1adf,0x00038074a53a6ae6,0x0005919bbc5eaf8e,0x0006580a40639d33,0x00033f83c3446f86,0x0009f20b5de7abe3,0x000a42c48703c063,0x000ed659dbbfadd4,0x0000000000000000}}, {{0x00025b49cc7d0744,0x000d5ca66a4107d0,0x00009a278704a0b9,0x00027e26383562d7,0x000c28bfb3e1fb8b,0x0006132452cd156b,0x000d9a249ca82ac0,0x0005a22d3a0e92d3,0x000b19aafd34655b,0x00048d36ff20dea2,0x0000000000000000}, {0x000f6b3025835a5b,0x0008531143727c86,0x000c5c003858192a,0x0001da9352b2fd4b,0x000d25e79d62bdaf,0x0003c74903de7c27,0x000ad4718fc47302,0x00063e48286ed6b3,0x0005e2dbee1fb246,0x000857558feb16de,0x0000000000000001}}, {{0x0009f56e96a543bc,0x000d31c6bb399ae7,0x00031b99e11a37bd,0x0006c0e42fdb7dca,0x00074aad0723ad0f,0x000aae97e4f8e5ac,0x0000fdee33ad0efe,0x000675078a78e14a,0x000909b38b03996b,0x0007469ca609f2ac,0x0000000000000000}, {0x000466dcc50132b4,0x000eddd95df5a1fb,0x000a8d9a82cb91aa,0x000178685d056d78,0x000f44580cbb5024,0x000b8404125b7ea5,0x000c959397a21279,0x000b3c397b77ec41,0x00050358651ee34e,0x000febe48525c5d2,0x0000000000000001}}, {{0x0003aa997f7f37af,0x000bd0399f83a0f3,0x000f152344eac6ee,0x0003cc5d1e36ba58,0x00058bcb7b01bb23,0x000e6e01c3b95ccb,0x0003f3cbd70b3470,0x0005471f142928b7,0x000f33fe8192a8fa,0x00067751b82a4272,0x0000000000000000}, {0x000ea1f801a1be23,0x0000e029d67e2091,0x000355df0fe9219d,0x000069ec86128187,0x000e9196ceb57b88,0x000b831fc0c5d6f3,0x000b18561a90e72c,0x0006875cf51476cc,0x0009d0fdc775daca,0x000556f11fb0d65e,0x0000000000000000}}, {{0x000d755a99415514,0x00085952e4dc0b72,0x000ddaa98f7198b9,0x0002cf0597f96150,0x000e7060ed10994b,0x0005df6128c96445,0x000ea5cf35637a95,0x000b47cf25cfbeee,0x0003e924da7f8ade,0x000d5d59754f0973,0x0000000000000000}, {0x0007794536974a33,0x000bee39625b4887,0x000c916eff917626,0x000c143d7b2fe99a,0x0002b42a1f214f15,0x000a92c52323d0ac,0x000fb97a09db1674,0x00097d2bc99da798,0x000062e5a6c7b18b,0x000498e32a3a4e9d,0x0000000000000000}}, {{0x0006f0528c6a99de,0x0005f78365a5404f,0x000a6130da7d607f,0x000ce8f385d457a1,0x000127a71db8c282,0x00075b1780f22e8e,0x0005f271ed981d16,0x0000879b71615445,0x0003f2395d4c8d2d,0x00002ffbb885eae5,0x0000000000000001}, {0x0004e8a699830814,0x000f60c1a29f03dd,0x000620f1843d15d6,0x0005370351aa6497,0x0003f3bdc3d85b92,0x0005713630b15aa8,0x000b25038bafd76d,0x000aa324c45046f5,0x0008ff854c7ef0e3,0x000f873074cd9a42,0x0000000000000001}}, {{0x000a5c1655f0c965,0x000ad8760b75d0c0,0x0002d3b7a7dc8ea4,0x000d9d864941a528,0x000eb47e8ca867c6,0x0001a8847066dfb5,0x000249722cfbbbd6,0x000d270c27ad4dec,0x000e74307c896550,0x000812fcfddc8f52,0x0000000000000001}, {0x0009df50d9240b18,0x000a5431583e94ff,0x00044e5e649470bb,0x000156c0cde5a76d,0x000ad9f50c93b508,0x00099e86567b7ad7,0x000e7618f9dede32,0x000b84978d6f1f46,0x000aba70858d56a1,0x000626f5aa274be1,0x0000000000000001}}, {{0x00038150eda6a189,0x000d5498edde21db,0x00010e8c4a802c3e,0x000d570892441512,0x000a6f9b009f95d3,0x000c80e954785d69,0x0008dbfa197859ea,0x000f9a954ad6166d,0x0005360545cac81c,0x00042d01aaa83bd5,0x0000000000000001}, {0x0008a0342c362ba4,0x0008202cf6246957,0x0008c4987d0b8dd8,0x000becfec2b48e0f,0x000a0d5c621a63b1,0x000668f2b6a90343,0x0008bd4fe098700f,0x0008bd8fa8829c08,0x0007948513f0936a,0x000733ae92e72067,0x0000000000000000}}, }, {/* digit=7 [{1,2,3,..,}]*([2^28]*G) */ {{0x000f8517a4c96e5e,0x000b0e039e54c124,0x0001ec83d522549e,0x0008ead8eb02627a,0x000ef95771e9618a,0x0004f3a6b4497c2c,0x00055a41c4917c7d,0x000be8babd80080b,0x000548c7990585b7,0x000c64dabe54a06c,0x0000000000000001}, {0x000269bac978d382,0x000c6bdf9b98b02b,0x0000247e075c4ed8,0x00030716d8e1a299,0x0003a019c94edbc8,0x000c1665fb3458f3,0x000e700cd4d82fa9,0x000a2326e507ff63,0x000452b8341c9bbf,0x0000dfc9214a3f5b,0x0000000000000001}}, {{0x0001109faf34910d,0x00006e16fb098733,0x000f23db2247dc5b,0x000f53ef62c76a0d,0x00018f68431633f2,0x0003cbe6a9413972,0x000253b6d05ffc26,0x00047ed103a8b14a,0x00089d6938ee0b45,0x000f4f3310d7c6f3,0x0000000000000001}, {0x000ae5ea5e61f0fe,0x000803eba63d9ee3,0x000ff5d7d44281cc,0x0006da525a289454,0x000688b5bf3e7fa2,0x0006c91ab88b9a08,0x0009907565a2877f,0x0001737c021210a3,0x00031db551223d6a,0x00041419f277aae1,0x0000000000000000}}, {{0x000ab41a098c92a7,0x00072fa6811333e6,0x000851f03fd8fe3b,0x0008e34493163c43,0x00028174f0009cb6,0x000db83d4e177695,0x0004d1bfc734499f,0x000c56272647cc55,0x000d38b2b770d722,0x000fcea5c023f6ae,0x0000000000000000}, {0x000d52df57e5ca52,0x00065ec98ce0bb77,0x0002140495f37162,0x000d03a5ffc6d632,0x000f0d0061a4f743,0x000af61ada3e0094,0x0004b70091a92992,0x0003fe83591d84a0,0x0008b7e8b2e59f37,0x0006892e459b7561,0x0000000000000001}}, {{0x0005e28d077485e2,0x00020e97a1a0b220,0x0006679b5d8662c1,0x0000da8bd256806d,0x000925177882d56f,0x000fd447d9b3a0c2,0x000077e15eb4fc81,0x0000f15d98b7d44b,0x00021ac9944ac5bb,0x00096438b1a53927,0x0000000000000001}, {0x00015ec8db3161c2,0x000f397c19309926,0x000de0771a46014e,0x00075e027929bb3e,0x0009dcd3fad002d9,0x0008c634c3d387bd,0x0009c3f4ebf24793,0x000a2c2da2b50807,0x000e85151e2b2209,0x0005f4bb80ad2ed2,0x0000000000000000}}, {{0x000d84a6577d1d88,0x000209b195d9875f,0x0007dc25315ab09e,0x00041e59650e28f1,0x000f81b07fd77f04,0x000191d3288a8ccb,0x0001838964e3273f,0x00014aa2bd5786f8,0x000d924c29c83190,0x000d240eca2dec17,0x0000000000000001}, {0x000c94cf500620a8,0x00017a01ff5bfc59,0x0001d4396ff8b7cb,0x0004fb6ee69226c5,0x000565facfed55e4,0x000fa0b30de43edc,0x000b20ea8612b643,0x00056d93e66dab8d,0x00098f9a9e46bfc5,0x000537cf26d7b09b,0x0000000000000001}}, {{0x000ab3bbacf312ed,0x00003114377687ca,0x000ecbe360e1fdea,0x0000336e644349d4,0x000ce9701c97498e,0x000b970f76e36640,0x000d18aeb034f110,0x000d8c04737b96e3,0x000b828ff89d3a4a,0x000ceb091b279c08,0x0000000000000000}, {0x00002832632c0b79,0x000f06083c30b6b6,0x000d6d46a5784fec,0x00018a1a822c2ef2,0x000ffd16846c810e,0x000859c7f32abfb3,0x000410206687e5a6,0x0001a4731948bcab,0x0009310e425eab64,0x0006640ebb114d39,0x0000000000000000}}, {{0x000759039c7a9d17,0x000c2d4dd47b8758,0x000c1f2cd883e5fd,0x0007f9cf12cfd22e,0x000b330c8103c8b6,0x000fef902907b0c0,0x0008540db26c476e,0x000e726a64472792,0x000b090ef761ac1d,0x000f96107e57dd18,0x0000000000000001}, {0x0004650aeff40f19,0x000f9022a822976b,0x000a5007e542efc8,0x0007e6336d263df3,0x000d3e6b563a86e0,0x000fc14e677c3dd9,0x0001920cf4b81cd1,0x0001cedaf8056af9,0x0006ebfcbc28b238,0x000af30ce3975f89,0x0000000000000001}}, {{0x00090c95c3d0b9c7,0x000844b8f686b48f,0x000a746779417d91,0x000bd2f6b498e1e2,0x0002adf2e61e9354,0x0000db08d1aea1ed,0x000a497f347f08db,0x000c7871378402cb,0x000753c735de0850,0x0001f9ed5b707951,0x0000000000000000}, {0x000d045e45f819b7,0x00024591e83186d4,0x0002f07b1add4180,0x00067074059bab68,0x000ea2b0f371c1d4,0x0000e5f219b0e391,0x000f844f22e68c28,0x000679b7f960b058,0x0002502036ca9899,0x00028a1f63acdbd1,0x0000000000000000}}, }, {/* digit=8 [{1,2,3,..,}]*([2^32]*G) */ {{0x00023b6569acb75b,0x0008bff580463d22,0x000bd3d896f7a55f,0x000bc35819d6f3c8,0x000fcf8dfdd32dc1,0x0007477a57a2786c,0x000a3b0ae5589b65,0x000806de5eae9f47,0x000782fcd93f2178,0x00096dd9479ee32c,0x0000000000000001}, {0x00029435cbeebc5d,0x000d8352a35de209,0x0004ce809af5b11d,0x000a76cf080ab8c3,0x0002250478b1ce25,0x00003b3ff7216bfb,0x0004133d87f47621,0x000a4132748099b3,0x00029b68995f627a,0x0006fb62b3cf30a7,0x0000000000000000}}, {{0x0009267d43d108b4,0x000b5b0396f4d947,0x000b1e5f7f088692,0x0009c3c1fd9437e3,0x0006cb9b9b7fa950,0x000a37b6c115a75e,0x00062d05b42f650b,0x000d5b3cf510dbbc,0x000a49bf06d5fe62,0x000049824e6593c6,0x0000000000000000}, {0x0007f70f36b1fb53,0x0004a3eb94fc53cc,0x00082c0e60f6a2b3,0x0002888aea4bc9d4,0x000d37ab9ed318f4,0x000a505ae0c0fe3e,0x00082c9e94fad3b1,0x000efa0f31285453,0x000bd4be69ae4fb8,0x000003a516fe8844,0x0000000000000001}}, {{0x0005e8088591d8c2,0x000c6e24bb4a7ab3,0x000968fd3709e47e,0x000d55e3e7d95582,0x000f8783f2538474,0x0003b454e19d35c0,0x000724c4578fbe58,0x000b98f51326114b,0x00090d99b97ee546,0x000691801229b8f1,0x0000000000000000}, {0x000e4a0a2aa86765,0x000aa08b19b4b67e,0x000c220cb11d4f5f,0x000c7d426ad0862b,0x0002dd7a63508ce1,0x000aae47773236a7,0x000cce936cda4ace,0x0000808ba7a0be3f,0x000c14a5b972c384,0x000887cda4655c79,0x0000000000000001}}, {{0x0007786aa39096d4,0x000a4070017bccec,0x000926b1ae026576,0x000026855e810d17,0x00039def24d306c0,0x0008ac55c7d826c4,0x000b521e40f66cc7,0x000ae26697c9fbf9,0x000a75caf01aaaf8,0x0002a9d094aec346,0x0000000000000000}, {0x000a161f4c1b67b7,0x000e72cc3c7e5f99,0x000fefa749b88977,0x00063737d6e24cf4,0x000ed4607a910568,0x00017686854dcfe4,0x00011acac7bc09c0,0x000cc731394d9ec2,0x0009e4dd8ac76909,0x000bc7246fb612d5,0x0000000000000000}}, {{0x000d5c2ad970ea88,0x0000eb7dbc22b4be,0x00070d534e1a9e33,0x0004b0eab21921c0,0x00071b3a90f4b6c3,0x00015ce8387fd7ac,0x000ec28efad61dad,0x000f792985d577d5,0x0009ac313d175e05,0x0002d86582a5f995,0x0000000000000000}, {0x000258f797f0af53,0x0006198f53a67607,0x0008e97661c802c3,0x000001f410140442,0x0003c270534a9c94,0x000a5333d3d840fe,0x00076ed16f99ddeb,0x00021b94ff80e532,0x0002761460189f70,0x00007bce48c909c6,0x0000000000000001}}, {{0x00018e1640843ac0,0x000d435c11720f14,0x00057cebd3881c75,0x00023104876137be,0x000da25ae87bc97f,0x000052fc640f68c5,0x00027372b9f14882,0x000b4e854fcb3017,0x0009d3406b0f1a39,0x000e653db1df6886,0x0000000000000001}, {0x000c416fe50a1e7a,0x000c29b7a99148a5,0x000d660bcfe2e7c6,0x000630309213716a,0x0004b63e38c0d1fe,0x00033bb86d3923a4,0x00056213e592fda9,0x00080b360f884315,0x000db3b21dcd9fe7,0x000617bc0a7836eb,0x0000000000000000}}, {{0x00035cd63c7c9de3,0x000a91ffca828c02,0x000b3e377bfdd504,0x000496682e625999,0x000b8af1c462d519,0x0009570d96676ec9,0x000bf815f3869cb1,0x000b476a8b4fba76,0x00057597ce654eda,0x000e2235375a2127,0x0000000000000001}, {0x000e9252adfeeb9b,0x000707b233b4a650,0x000ab158faa771d2,0x000df78fbc7a8536,0x000be88e5009a864,0x000abbc52635e311,0x0008769bd53cfa60,0x000305e36a566f93,0x0000e758e66271c0,0x000b10e12e9cdd0e,0x0000000000000000}}, {{0x00092f38031c9da3,0x000f6f0dd54d0455,0x000298fe24144d05,0x0006274ae2d191b2,0x000909113fc1ead4,0x000dea702ccc54c5,0x00008c5763ea8c10,0x000635441e7274f2,0x00006b2f2578c573,0x000c3b8134369537,0x0000000000000000}, {0x000ada464a85cfcd,0x0006064c2605a588,0x000004bbf31d5464,0x00010805ca04e18d,0x00067998cccf9032,0x0008398a6f896278,0x000dacf8d2faed14,0x0002de01ea7eca85,0x000eb7d829278474,0x000eb89fe5859b0f,0x0000000000000000}}, }, {/* digit=9 [{1,2,3,..,}]*([2^36]*G) */ {{0x000a73aaf5f01aa9,0x0009abe5e08d9505,0x0009fd8bcd318e91,0x000915895b386f06,0x0004a0b5abd07d68,0x00039901b007bc24,0x000ff05c36936913,0x0003179dcef7684c,0x000125196e69b799,0x000a2823db7308b0,0x0000000000000001}, {0x0008e83616d0d063,0x0003bf0c66e267f8,0x0006d375b822f9f9,0x000dc02109656c0d,0x000530c1fc16b6d5,0x0006bf6541ba81db,0x000443cb4caf94b8,0x000a87f59d3c1a6d,0x0002afcd60e10fe1,0x000a088d7e1995b7,0x0000000000000000}}, {{0x0005b8daa50517e7,0x000dbed46676160a,0x00016e7a7e78dcdb,0x0008e1fc1b0f5e9c,0x000933cb9503e917,0x0006f78b36f2294c,0x0006ec3420442aae,0x000c01e17c7ffb2d,0x0007293b87d30fdd,0x00092836bed4739c,0x0000000000000001}, {0x00075943e2ebfd04,0x0007b784cf37b849,0x000645eaa02ab285,0x0000b0ace12a0d65,0x000ff267c93aa3d3,0x000fa6954230be3e,0x00001e1903aa7ed6,0x000c311ae0c82cdb,0x0005f0bd3c5056d4,0x00022094d54a9827,0x0000000000000001}}, {{0x0001c0660a4f2bbd,0x000c3d2fe061f455,0x000a2b6dd7091d40,0x000bf7437cc4883d,0x000f258011ddabd2,0x0001bdaba7aee852,0x000195b39f463ce7,0x000efb33b881bd7c,0x0007d695aede085f,0x000380f8fa2471bf,0x0000000000000001}, {0x0006eeab983554b4,0x000f138a6f5a6dc9,0x000b29f154f07f71,0x0007d1c7242d7a9e,0x00042f3c7f1afb70,0x000af2896b44aee8,0x000b55601f569990,0x00061e36ed07c5c5,0x0005430facca2678,0x00016ea78eb21424,0x0000000000000000}}, {{0x000aeaaabe68e207,0x00098b6eaee3177d,0x000f5c1267a6e353,0x00092ae2d01bbbbb,0x000bf3af1a4f4a2b,0x000532088e5cdfa4,0x000c8ee638a58f55,0x000bbce5e7aa2a0e,0x000a1644879c3f50,0x00025e378387c246,0x0000000000000001}, {0x00069ee8884e88e1,0x00090f8ec2984b67,0x0001f9e47bd62fea,0x000f9867e7522665,0x000cb916cb0493d9,0x000106987f5be2cc,0x000869c71156e1c1,0x0005011576bd7bad,0x000b76a6e945007a,0x0000aec18de41f38,0x0000000000000001}}, {{0x0007c59949c6f67a,0x000c897a229d2368,0x000118e3e788aa53,0x000794e3080e973b,0x000815a91046f15c,0x000ac04ed530c0f2,0x00078a4fe35eb925,0x0001fe18e7070c54,0x000f409ce7d9c57a,0x0008aafcd17edd4b,0x0000000000000001}, {0x0002850fe8174557,0x00037e234694753d,0x000c528ec7d2c45c,0x000bdd41f346792a,0x00032ca964be2a36,0x000fef3e7911d679,0x0000101c72673a03,0x000653d6358ef0bc,0x000f874e2b9caaba,0x00045ebbcc31882b,0x0000000000000001}}, {{0x00090baa505384e0,0x000993148d7d8454,0x000d948464cae379,0x000f46feac4f8ace,0x0007268d1b7c8dda,0x0000d4770e6c39b6,0x000c1955967ac571,0x00052098b74830a2,0x0008d17fe1904773,0x000191e5071ced85,0x0000000000000000}, {0x000b4f003b56551f,0x0000872a7e419344,0x0001262c90a767f8,0x00015a9791770fa4,0x0001a4bc5606e253,0x000a665041696dd3,0x000da6d7ec137466,0x000cac07c562bd01,0x000c4a92e59de1e2,0x0007068f7d29994b,0x0000000000000000}}, {{0x000172698b05a9bf,0x0000570dde3c4b9d,0x0004dad7e2ab8a86,0x000cc4fe376d08bb,0x000df2d396e50709,0x0008138716b38f91,0x0004e9a6a45d9577,0x000feda477817a06,0x0007062a4f79bf83,0x000ca12aff8e0103,0x0000000000000000}, {0x000748577bd0ea3b,0x00068ca23c2d1e49,0x00079fc968bdb9b4,0x000359089d5d5807,0x00037ae7478afb4f,0x000f6ac1a17ffb5a,0x00076fb0ad6d0956,0x0003cc73da4935d0,0x000b38ddd4e896c8,0x00091fcd942654f0,0x0000000000000000}}, {{0x000d06bf88e947b1,0x000a0ca717a0accc,0x000b428946c6ceb8,0x000992652bd2594e,0x00041806882365c1,0x0004f2f3523a8241,0x0002e27b634a60c7,0x0006f4680f2b83ce,0x0005e159f3342680,0x00053718c76ca148,0x0000000000000001}, {0x00063dec4e0c9dd7,0x000cb7d74bb74e1f,0x0004a5f09446f95c,0x000f4555c75d0662,0x00028d6e7583fd36,0x00083fa30323cc2b,0x00010012c0c49bb7,0x0009907cd3d64f77,0x000c79e69ac90f89,0x0006c12cb352bde2,0x0000000000000001}}, }, {/* digit=10 [{1,2,3,..,}]*([2^40]*G) */ {{0x000bc2a7fe05ab80,0x0001a246f49f7a93,0x00091072db7cc0b4,0x00011f97d30ac7ec,0x000169de685e7537,0x0008a2ae9aef0acc,0x000e3c46bded4c6b,0x000604789cdc4497,0x000a082feb2b2ea2,0x00078fe890cba4fe,0x0000000000000001}, {0x000edbc5c5076824,0x000298a472aca466,0x000a80660505ad15,0x0000c1cc1b16ca97,0x000dda2937bbf38b,0x0002545fac4d56c3,0x00090f07e35494b7,0x0000903e9ca74b57,0x000b43111b0c8bc4,0x0005465923f9e9c4,0x0000000000000000}}, {{0x0008b52bfb73ff4e,0x000a4d6410d489c1,0x000ae318bb528530,0x0004b71f3f7d7028,0x000970b21b686b53,0x00001ea2751f5995,0x0001322663379ddf,0x000e77c11915800a,0x000261c476db4bea,0x000ae8e89c22a1e3,0x0000000000000000}, {0x000e16965a7b1dfa,0x0009afd6426762fc,0x000532ec13f2e53d,0x000fe4131e801ed5,0x000c86963e2f9e9e,0x000f46e5098aecc3,0x000faa2b47801a35,0x00043b6f3406c3d8,0x000b57971349f37b,0x0007d749ef39f4ad,0x0000000000000000}}, {{0x000dcaceb126ca58,0x00046c5a73dec3f9,0x0000e0ffb30d8879,0x00026935e7e62831,0x000f5e074c83b841,0x0008b04291158a7d,0x000f72a08eaada21,0x000a40d05438fa20,0x00005e6ac9aa8c4a,0x000b92b755928484,0x0000000000000000}, {0x00081326c74e90da,0x000cdbf1a037a879,0x0009887e29013ab2,0x000ffd6598bd3d86,0x0003b3c803a95fec,0x000e4c50722fd839,0x0004e70129b699c3,0x0000fa72cdd65e3c,0x0000ccbba65f24da,0x0008975325682f6c,0x0000000000000001}}, {{0x0008d8231d21b98b,0x000f46eede07ff72,0x000c57dc8bc52ba3,0x00096a93bbd28782,0x000609e0a7a0e49d,0x0009fbe4aa495765,0x0004c5f79dbfb8ae,0x0005e1789960cccb,0x000b74da3d25ebfd,0x000c2e56df642b09,0x0000000000000001}, {0x0007057a2be83a30,0x00026ba759ce4dd1,0x00057744ef0ab9d2,0x000c9ee2b7115a63,0x00000d77f24c2ddd,0x000142ea1adfee89,0x0000f3fa9d5346a2,0x0007a84ecd7e6d50,0x00035caeb7a1527e,0x000c8110e6262dae,0x0000000000000001}}, {{0x000457989aea7c3e,0x000a16bd6196a6cd,0x0006f76c2cbdd85c,0x0005840dcfd847e9,0x000ec8ea001b3aa2,0x000898be24444e27,0x000397d8a0c53dda,0x0003fa5f98a5b3e4,0x0008e197364ea986,0x000bbd922c6bbfbe,0x0000000000000000}, {0x00064b7db5084e37,0x0008c954735a1906,0x0007371d65a99056,0x000bdaf052b4c902,0x0009ec2cc9668600,0x000adac668469729,0x0002f7ceb4949cfb,0x0001eda14ca03327,0x0009270923989fbe,0x0002a80f1714c9d9,0x0000000000000001}}, {{0x000da9fadd2d2e35,0x000ebe39d9c06e00,0x0007878b1c269b9b,0x00045c0350e16aa4,0x000d604f7fb31a05,0x000233dc435d57a4,0x0004a59629977c5d,0x000caa747e5387e5,0x0006980680cca577,0x000c7f3aa2473480,0x0000000000000000}, {0x0006ecf72ff177c1,0x000ea087d84398f4,0x000f8e3dbad5b5e3,0x000793b7c29bdf29,0x000d48b4ad4a2c86,0x0004cf9d25337e0d,0x000be01c858ea723,0x000fe90a676bb282,0x000306f507590c7b,0x000915155053c47d,0x0000000000000001}}, {{0x000311b42bb970cd,0x00056fa08e6727fa,0x0006285b2f7609fc,0x000807c307ce1a3e,0x000d8c9c1df6de94,0x00070b979619a317,0x000fdde052a3379d,0x000baa7d20b3870e,0x0006e443d8f7406d,0x000355511beafebb,0x0000000000000000}, {0x0002e82c90634dd6,0x0002249d51e499d6,0x000615ca9d89995a,0x00097ac7d99162d9,0x0009551034000ab8,0x00070ca9d924f35e,0x000b526853be7dfb,0x000638dc8c8aff11,0x00031fb01463b8a6,0x0004e7b55e740433,0x0000000000000000}}, {{0x0008d4f13a03485a,0x0004c5dd3ccf1850,0x000d8ab1776f2552,0x000a54a5e0bf0c9e,0x000e81226e24a017,0x0000e5b1ecb9626b,0x0006acb8b7b3bc5b,0x000414da0130f24c,0x000b2f1d94673605,0x0003ae73af8b9c7d,0x0000000000000001}, {0x0001a4baf806025a,0x00068cf7b99ef6b1,0x000b70549901e9bb,0x000cc5d4a5ca0071,0x000b555009f7be57,0x0008dbaab6501aba,0x0005c582d17b21b0,0x000d9921c7bacde3,0x00013fb4b9991c48,0x000d72c6f664c93f,0x0000000000000000}}, }, {/* digit=11 [{1,2,3,..,}]*([2^44]*G) */ {{0x00000e09c15f3e5c,0x000f97f45b409fb9,0x000ff4a01087837b,0x000d204b2bcafcbc,0x0000a0da165ec6b8,0x00011716978423a6,0x000f2f7f8295351b,0x00081f58e2d13eb1,0x000ed84592b66922,0x00025f5f9819aebb,0x0000000000000001}, {0x0007ea077d668278,0x000b9653ee2ff77b,0x00098e8334b5b359,0x0005210487baabe1,0x0001a95a5886c85a,0x00009649f4c23788,0x00056127f95c6f68,0x000aed6c6419d339,0x000be49aa657d29f,0x000da67ae0b376a5,0x0000000000000001}}, {{0x000fb32bacbbde73,0x0004f08a721e3545,0x000584020b45c467,0x000fd3a284a774fc,0x00004477afffeada,0x0006a2c4ec266e10,0x00066dc326c6652d,0x00070b3a65b94280,0x00055b8104c7d5c7,0x000d8c4b6af237e3,0x0000000000000000}, {0x0000b97b7ca1cffd,0x000435de1358221c,0x000876cab38cc7ac,0x00054cdc8f30b09e,0x0000ccb3a4f5aec6,0x0002ac30ca26a9da,0x00011038e2a6fa3b,0x0004545c20a577ee,0x000bff8e2f50fb14,0x00093158359a6d97,0x0000000000000000}}, {{0x000b8fa7bdc8384d,0x000f2859e636e718,0x000ed301cc9c465c,0x000006a5b105b2b7,0x0007075698827d1b,0x000fbe7e34565b30,0x0006110c56ecfa0a,0x000be3136324ecec,0x000a684fbfe59f06,0x00056bc39bf313cf,0x0000000000000001}, {0x0008543e894e8a16,0x0006d339681c386b,0x0001fc0aac97005d,0x000c6eaa38aa9f79,0x000a90d6089956c5,0x0005ec33374fdc05,0x0007a4eaa1631484,0x0008df64f8ad9e1c,0x0007f44336b984af,0x000859e7ad53b8dd,0x0000000000000000}}, {{0x000c8ba9ccf89d24,0x000874ddf8d1b9b2,0x00027291ffd7f24e,0x0008bd9d563287c7,0x00065d01bdb48d02,0x0001b99b973b0c12,0x000050d618319b97,0x00038420d531f686,0x000d7c201c411c3a,0x000d97468eb84cae,0x0000000000000000}, {0x000eb2fc05bf609a,0x00073e1dab9da1f6,0x00049847c3ac275b,0x0007880554d322f9,0x000fedd0cd2b7f05,0x00085bb3e74958ea,0x000fcd8d9061a481,0x0006f9ac370d5c6d,0x0004cb188a021786,0x00057aa132c3b5f5,0x0000000000000000}}, {{0x000a082d83368da6,0x0009c04ba3a92f9d,0x00018e366fb4a189,0x000dca28f8a4aa8f,0x0008c98efdf41b12,0x000e7f6ce11df724,0x0003850179926b22,0x000c0fa0bae8aa29,0x0007fa3acc87191b,0x0008222f18a88f29,0x0000000000000001}, {0x0009dda00370c8d5,0x000720c0497d2a02,0x000cdb5a6b3dc411,0x00032f0daa73c7c9,0x000505d3784e14b1,0x000d7b77b06edb5d,0x000c1f94b45f2c9d,0x0003193f38ea4c8e,0x0001706f6af3bbf0,0x000f0df22ed99a0b,0x0000000000000001}}, {{0x00097825d9e0b2bb,0x00096d1340276af1,0x000d82fe6324bbcc,0x0000475ecad6233b,0x0009a0cd8d04ac29,0x000e8e067d738cce,0x0004317aa038ad08,0x0009a7ce55aad83e,0x0006a1887d5e91f4,0x000a135efeae9285,0x0000000000000001}, {0x000fa0b6a035b085,0x0005853d153ead9b,0x000ca7f6fb4ef7bc,0x000bfbb30b798e2a,0x0006653595cf1f8a,0x000774e7d1791820,0x00048df862d39281,0x0002db1e40868b45,0x000153b336e38fc5,0x00052ce2e4b80e72,0x0000000000000001}}, {{0x000306c918831eac,0x000de7b8556b1913,0x000c579621fb2237,0x0001fa1088e011f5,0x0007511558db4265,0x000c63131310e896,0x00029cec356a91fc,0x0004b85a2f85b7d1,0x0006bc4404e3b5cc,0x000ac5c4fcc3a6fc,0x0000000000000001}, {0x000498b1e054105b,0x000818b7c971dcbb,0x0006cf66f8ee2eea,0x000fa05b49db517f,0x00012073a35daeb3,0x000d5bb674f202b9,0x00032d411842792d,0x00076cdcc487632e,0x0006568c96ca8dd3,0x000ecdfe1c986f51,0x0000000000000000}}, {{0x000595043dc23233,0x0008d9e1b752f3f5,0x000f6e2b3641b931,0x00064e0f5c02bb70,0x000169d8f287038d,0x00062f3a1b075424,0x00001bf3b8c6755a,0x000a2b642127d597,0x000c17f0c20fbe8b,0x0005263410177dfa,0x0000000000000000}, {0x00008cc560c65efb,0x000ef6706807502b,0x0007a1e8980e532c,0x0007963729a4a8b8,0x0007ccb3a4f193b6,0x0002e07ae80043db,0x0005be0346fea839,0x0009ef33f7a00da3,0x0001ea778cb41f4e,0x00096ebb760e7727,0x0000000000000001}}, }, {/* digit=12 [{1,2,3,..,}]*([2^48]*G) */ {{0x0009ba658c1f9460,0x000b18b48e1df3f7,0x0005fc03a103eb15,0x0001ad263bed592a,0x0000a127b78a3359,0x0000337c7b07e9d8,0x000d2a0349dd74fc,0x0003b1a807c5364e,0x000d92cca588d420,0x000d9e772a1716ec,0x0000000000000001}, {0x000fc1df3f66f295,0x00015742d25980f6,0x00036f0fdb08922f,0x0001fe47a583206a,0x00001c73f88168cc,0x0001b777671d2798,0x00068317ac8979ce,0x0002a98b48363dba,0x000f36b7460d4015,0x000da1c3d46c62c7,0x0000000000000001}}, {{0x0001fb046e7fab2a,0x0000e190213473d6,0x000cbb6e9b84f9db,0x0008fb8a36fcff78,0x000c47cd5e9d16aa,0x000c2601e9337a00,0x000713efe8445d72,0x00030681fd15bbab,0x00051cff90b2dd23,0x00024900ab444b21,0x0000000000000000}, {0x000de9a880ca8289,0x000e3bcb8ede5206,0x000e1369e32209ab,0x00036516b711e224,0x00025533569db531,0x000419656e59d965,0x000ee21f2d680255,0x0001d59bb004326e,0x000bb722c073cca7,0x000866aa784f931c,0x0000000000000001}}, {{0x000d262bb3ca8da3,0x00045288c7563397,0x000d10c59451797d,0x0004e594575ac7f4,0x000311006db0bd6b,0x0004d6485bec56e6,0x00089e23442953a9,0x000610efbe7ae598,0x000f1a0f166d5639,0x0004e5f91e0ed7d5,0x0000000000000001}, {0x000aca95d51d383f,0x0000d23ae1d67e17,0x0001b867b62738a3,0x000907e6a529f72f,0x00059335e44e6986,0x0001d5fbd59c1e58,0x00018393e6789776,0x000e5bc878acd1b0,0x00059b26328cd9f3,0x000f3d83306eef44,0x0000000000000000}}, {{0x0009313593b1d240,0x0003b3672b4b0a51,0x00078ea42e614acc,0x000784cd22fe0a9a,0x000a6c20faf43e72,0x000e49f3038f9c3e,0x000fb914c50987c5,0x00000c76e9b912d1,0x000dc2b7b96a89b9,0x0008de238b29a074,0x0000000000000000}, {0x00068ea377031f72,0x000e9606adb168ca,0x000e58dde885ecba,0x000177424d422e92,0x0008aa609937ceba,0x000f30fc81145199,0x000c9f99eba807b8,0x000e200db6e7a724,0x000db2dc7651c126,0x00009cb58e38f0c9,0x0000000000000001}}, {{0x0002dda36b654cc9,0x0008acdfcec83248,0x000164e7c3c6f06e,0x000ff27341f98b3f,0x000b145595e7208c,0x000f8fbf6e4d7416,0x000a519d6e691f26,0x00082c10e5fd7be7,0x000b1af42c760524,0x000f36238c97dbcb,0x0000000000000000}, {0x000a3b8e5e8a7251,0x0006fabc0a713664,0x0004fe41fe20cb31,0x0004067dc2b00d32,0x0004fa30d7f12a4e,0x0003f79c759905ca,0x000ef9b323da1724,0x000357ea84efa0af,0x00083350488b839e,0x000408f03e5cf22c,0x0000000000000001}}, {{0x000e616991835801,0x00028f75d4e1a857,0x00031b04bb8869ad,0x000fb7737091410d,0x000cdd4fad2e164a,0x0004c7cf900934ac,0x0009b433f8948c75,0x00028687541974f6,0x0008f0af013f8d2a,0x0000b59eac62d398,0x0000000000000000}, {0x0000c23b25d034e1,0x0007d927e7c611fb,0x0007596a05e54d05,0x000f8995596eb4b3,0x0005b26be4690555,0x000ae1277dbebe99,0x0006bc99c064aa3f,0x0001128fda3fad13,0x000cd244392bf3eb,0x000a481bf8fac406,0x0000000000000001}}, {{0x000d8f6c1e9aa431,0x000e3d32dbe1679d,0x0006391e1828c205,0x00026f450a2821e3,0x000a00cf3fc9e32a,0x000a2fc5a7a744f6,0x0006b70facb792c6,0x000e8edf92ab0b29,0x000d53faf8f11ba4,0x000b1e87f01ff5b4,0x0000000000000000}, {0x000e6fdf30e29338,0x00014840cefab311,0x000c4e092d034ea0,0x000be36bee8c5b8d,0x0001f39e2788cf85,0x0008f32c467a702e,0x0005e353cc3b7917,0x000f137377576e06,0x0000db55d1c5fcce,0x000d16e9cd523a0e,0x0000000000000001}}, {{0x000e8870b81dfb8c,0x0006908ea654a671,0x000c3eb3660a23dd,0x000daf70673dbdf6,0x000c19bbf5d38a5d,0x000fe1371d1e7af5,0x000e30bcc1eff610,0x000f1308bdd31572,0x0000db70b20ce33c,0x000e036ab6b3edc6,0x0000000000000000}, {0x000357b86d4f22a6,0x000b893ce6e16bae,0x000a3849b8d94e06,0x000e1675b6058ad8,0x000ed6add0f99ace,0x0003cd380c39df12,0x000e2335c645ff14,0x000994a0f6180481,0x0005a52a4c84b4bf,0x000e9849a710f480,0x0000000000000000}}, }, {/* digit=13 [{1,2,3,..,}]*([2^52]*G) */ {{0x0002ea2996fba378,0x000cf933ae1a32c4,0x000b43b79b9d0dda,0x0002636c30561bd9,0x000f9122413700ad,0x0005a779a0d830de,0x000580fda5f65618,0x00067e785d8628b8,0x000ce8b188bafa8c,0x0006d2c75df63d48,0x0000000000000001}, {0x00090afd2d7e01b7,0x000e57c72b304c5a,0x00040d7dec21b4b2,0x00094cfde0f45d07,0x00010aabbfa713eb,0x0007fa8b4fae1b3f,0x00047d2b080d24d3,0x0001142abdb36f64,0x000470df72045350,0x00047e76e433f8fd,0x0000000000000001}}, {{0x000081cbd682dd91,0x000d2c1433b543ad,0x00094641d2488d8c,0x00036e702da0394f,0x0008248288ca4d8e,0x000112c8a6461fe7,0x0004a486f063613a,0x000f77efb66bb862,0x0006e8d41511d90f,0x0009a1ce80969401,0x0000000000000000}, {0x000feced91fc3935,0x0002e83ecdac7136,0x000ee8e2857921f4,0x000ef9bbe82b293d,0x000bd182b25ab2c3,0x00097ad819ac32f4,0x000916b74b598de2,0x0004d5e666a5dd15,0x0007be0b151456a2,0x000b794dc25c5c44,0x0000000000000000}}, {{0x00087c377c23c5aa,0x000d33ca314119f6,0x0002512d0943eacf,0x000f9fd69c0e1850,0x000b7c3c6ea7ee55,0x0006291556c20685,0x00053374868b07c6,0x0009f9f339d7b589,0x000d6855b9238a10,0x000491ac6af37f75,0x0000000000000000}, {0x000b5d5b2f49812c,0x000855e7603bff6e,0x0008f73b087f7552,0x0005c0adc19b7320,0x000d355df5442e8f,0x000a4b8876b6aeab,0x000a7378dc2b22b3,0x000c26f89265f8bc,0x0006645f23dbb040,0x000f38b09ab1bbfb,0x0000000000000001}}, {{0x00011ca0d8fcc245,0x0008ea92267e1494,0x000bbfcc2abb385c,0x00029656bfd56d29,0x000075f2180a734b,0x000dc3400006f728,0x000f754023104376,0x00021bae73e6854a,0x000a8d2ddbc75324,0x0003d711770a3406,0x0000000000000001}, {0x000476594b8d6365,0x000aedeb8cb49714,0x000c86324ad6ba99,0x00016428c49863ca,0x0002a2e5cfc3d8a3,0x0009adc3e0cb62d8,0x000eff79e5f3fda7,0x000eb4f990b6cadd,0x000b0e410ae15a98,0x00000aedf394c7b9,0x0000000000000001}}, {{0x00021de1984e2e65,0x000603254887ed1d,0x00087e7535512fa1,0x0006f4ddde7dd7d2,0x000fd9cd7f2faac0,0x00009274ea570744,0x000b8cb9c92e3b10,0x000294aa3ad7752d,0x0001e25f444d43f5,0x000d6a378f2a4af0,0x0000000000000000}, {0x00007294901179cf,0x000fc01f2357da9c,0x0003c6543ad3aafc,0x0004db8aa97c6078,0x000dd86b1f882854,0x000e842c5d55c6a1,0x000e30c9aff1c67b,0x000d71107c0af546,0x00097038444a87de,0x000d8c2bb6354272,0x0000000000000001}}, {{0x00086f90f323a729,0x00082963dacbf625,0x0004056ab9d5b07c,0x0001d30212e37a0e,0x00065da9a3d1070f,0x000445a33677e429,0x000c39a6aee3c700,0x0006b968d6cd0279,0x00098776415f9a3e,0x0007bd59dc1684b7,0x0000000000000000}, {0x0005cafc1fb833a8,0x000b18657b2cb0ad,0x000af58b0bf123c6,0x000acc1e7ceb4334,0x000e5575f0e10ca6,0x000d22916c7bc194,0x00097f735880fd80,0x000604a86980d5b3,0x0002f218f0f8d8fa,0x0000806dbeec3ed6,0x0000000000000000}}, {{0x000b6c1669c31b94,0x000b37bb5eb33b20,0x000f2f86abcd3194,0x000093b3893ef395,0x000d0b48537fd7dc,0x0006863b5109af48,0x000cb076c2fca9e7,0x000fc785f088e6f5,0x000c88facfd552fb,0x0001054316685a3b,0x0000000000000001}, {0x000b6af5d1972479,0x000ccf45d30e213b,0x000db2b3881288b7,0x0008f7bff9008ba2,0x000607009e5be8cf,0x000e10b176da0a78,0x000522cf433a33d0,0x000090924737e4d8,0x000cc0a11c296771,0x0001fd3715d11b75,0x0000000000000001}}, {{0x000c391c2f2938b1,0x0006b396d1c5f420,0x0006bb17f5eeaef7,0x0006a57b7feb16a1,0x00026cc8015523f1,0x000ded6e6d4aadf1,0x000f602e23393c9c,0x000e2c8dbcb36848,0x00011e23c49f3a9a,0x000730c0c1ebfaf8,0x0000000000000000}, {0x0001b88cdd5da561,0x0002fcb4c22029af,0x0009624d6d5aa7f2,0x000db935bb120735,0x00019a8308449416,0x000467f9f185fd32,0x00057d8b4d3e00fc,0x000e187052a8a69d,0x0009e66380528c91,0x0007a42a603bc9b7,0x0000000000000001}}, }, {/* digit=14 [{1,2,3,..,}]*([2^56]*G) */ {{0x00026efe1474fe09,0x00029da3ad38a0ca,0x000ec34abeaf5cd5,0x000847ac94808b1e,0x0001587ade96127c,0x000a43fa8cfa6df2,0x000bb39bcfdb5ad6,0x0005dd4d0c9f947f,0x000772a4ebca687c,0x0009227d79e215e8,0x0000000000000000}, {0x000926e1c81cb032,0x000ffdb04fbc5abf,0x00034707ba5b9c12,0x000a347c4ee8c89b,0x00072367a152d81a,0x0004511a3a4cd565,0x000b8f1a66429397,0x000260ea13e9d0e3,0x000a19a28ee14ab4,0x000d5dea76ba4c81,0x0000000000000001}}, {{0x000f1e1b3fe2f1a3,0x0006da87421ab9af,0x000a3305ebdbbfcc,0x000cb7784b75a8e1,0x0006a4410056f8f4,0x000ff65612b5abdc,0x0004b1cd83f32f54,0x000fb989d25121c4,0x00014abed80a7bb1,0x0005ba8f200e1152,0x0000000000000001}, {0x000fb8525d63a07f,0x0002a4f5f23c02f4,0x000405911d9aa8e0,0x000dae0345abb8b1,0x0007b4834d14e7a6,0x000b31fdc5462195,0x0005dca7cbf9b75e,0x0001ee84304e26ee,0x0006a2c7d37349cc,0x000fc85a34c3afcc,0x0000000000000001}}, {{0x000cefac8c58a5d9,0x000939b188506808,0x0005985dd6ee8422,0x00094a64ab14cf0e,0x0001ac27af983cda,0x00024f6eafd12785,0x00025d8bab20f8ff,0x0004a549d9c6da3b,0x000f18f37ed810bd,0x000655f630e4c95b,0x0000000000000000}, {0x00018594e51ad76d,0x000d8952697460ae,0x000aec56660f8de9,0x00093a39294777cd,0x000bdf7dc98fde3a,0x0000c53dc363fcc0,0x00091985d2c2708c,0x00093692d05055da,0x000c4d312ebcde24,0x0000c18d0017f5cd,0x0000000000000000}}, {{0x000a3f86e5f8496f,0x0007f32df7ec8ea1,0x000d8551991f1f8f,0x0000f4eeb16ec397,0x000f5ebe5be1abc8,0x000f8233b8a1e6cb,0x00037675c403702a,0x000cbf97ecb04148,0x0006555682899a5c,0x0000280720d39958,0x0000000000000000}, {0x000312054dc27af9,0x00074dd550df7288,0x000193eb1e2f87e2,0x00073656a715c43f,0x0006ecb67dce2977,0x000aacb5db8a585c,0x000d92a6332fcd10,0x000cdeebccba4f16,0x00036c8da2b8001a,0x0007817b62765789,0x0000000000000000}}, {{0x0002d6d084e03d59,0x000c244d84ecf179,0x000c93fa7f1e0110,0x000f695cc72b1bb4,0x000921730f1b2908,0x000b0b36b38d0bc6,0x00029c0e4bf469cd,0x000c1d41428da1db,0x000d1253d7a577f2,0x00006a23b655222c,0x0000000000000000}, {0x000ba5fbd7ebe31e,0x0005209808ec8aa4,0x00049718327a5383,0x000bb2492c210a5f,0x0002eef53e1dbdc5,0x0009d3c1717e38e0,0x000d4877b41e983c,0x00012d8aedea3a07,0x0007e058b6c0e3ba,0x000fd022c8be6da1,0x0000000000000001}}, {{0x000870ab98aeb123,0x000044a353002cf5,0x0006150f34fa12da,0x0006eea20086b83e,0x000a0a2cdf13169e,0x00028616b25e80e0,0x000c5982d13e0cc5,0x00019702e01a4a67,0x000b60ef183d6e66,0x000a1f6f9172f815,0x0000000000000001}, {0x0002b57766386476,0x0001a0e6acc5477b,0x000ba422b2405581,0x00090991a9873020,0x00045310acf2c8c9,0x0008701ea796459d,0x0008c83917c30ec7,0x0009db51be44d168,0x000514c3bb42ce9e,0x00048d0b03fd870b,0x0000000000000001}}, {{0x0007edbd640c9bb6,0x0001c6f483d72a01,0x00058a225c5b0849,0x000e8697568a7e71,0x00022821bf73d7fd,0x000c765e3aef4bc0,0x0001d2e8d1daf2fe,0x000772d486e7b59a,0x000595f951edfc03,0x000ffff1683f882a,0x0000000000000000}, {0x000fc53814c4cc13,0x00014196f30cc555,0x00076a3af64c6ce2,0x0009bfff339f5668,0x000ffe438adb5544,0x000aa59ae8f3c48d,0x0006c57ce59b5441,0x000eb7bdc7b7c0fd,0x0003b8e1d8e51d10,0x000d6a6427d57897,0x0000000000000001}}, {{0x00005519264c8b35,0x00066ff272a08c1d,0x000142d545c343f7,0x000ef117b8bd86e9,0x0001c60c69c66860,0x000b54e53cb6de93,0x0000c9b9924f2f51,0x00030b949095878c,0x00016f5f1fba7e2a,0x0005817da79c3a69,0x0000000000000000}, {0x0006ad6babd55997,0x000be6d551de11e0,0x0006c45d4c33b3cb,0x0009e3dfcc4aa553,0x000821bb5c238e3c,0x000dfc012d05a1e3,0x000650684d8d4638,0x000805b7e2413b85,0x000718949cdcfd8e,0x0002efc1a85e6627,0x0000000000000001}}, }, {/* digit=15 [{1,2,3,..,}]*([2^60]*G) */ {{0x000f6a9bd09d8e58,0x00004bdca0a6cc0a,0x000d9e6d336fe5f9,0x000c9d8bd87d0339,0x0003f4d463bab3b8,0x000203e46dfb629c,0x0000ef34ea62ed4c,0x000564035458998a,0x00069592c6278328,0x00081b3c56ebb377,0x0000000000000001}, {0x0009a17aab96cc87,0x000f8ed51ce44125,0x000c62b1c658666d,0x000b6999437c7966,0x0008f0fecb36474d,0x000f725b1f7c6099,0x000396c71fdafc21,0x0006a547fb5a5b56,0x000566ae79d88868,0x0000f4130033ff0f,0x0000000000000000}}, {{0x000a6c73f41a4fd1,0x000bf46616431912,0x0009c6ffbd2fe4c8,0x0009e4fd42f313ec,0x000b9f8b100ba286,0x000e18229bbae712,0x000550161a1f1da0,0x0000032c80f2ffe5,0x000f0b1d53bfaa0e,0x00035fb83c760748,0x0000000000000000}, {0x000ed33353cf7a1f,0x00075b8b3c031fa0,0x00053c30e33c1415,0x000945a8fa62217c,0x000aa8b667de4f9f,0x000c4952fb889399,0x000b6e3b711abc77,0x000959e7e12fabed,0x00057ebfe5a1b2cb,0x0005344206e24318,0x0000000000000001}}, {{0x0005f9c5a301de7d,0x000b800d937115a9,0x0004b1412c82ee0e,0x00039cf3df5a5904,0x00016cd50327ee6f,0x000841dfd19a796b,0x0005d79c493ac5c0,0x00097275eb2319d1,0x0003b6feb4b9d447,0x000542e1eb10df1a,0x0000000000000000}, {0x00051bac56d17f38,0x0007837a907c7875,0x00082e7d67e232dc,0x000c3c225acaf222,0x00056e17100c95eb,0x000198b234622502,0x0006b8a4beb3ba23,0x0005492d30351698,0x000c0dd28973e413,0x00031b2e1155d6fc,0x0000000000000001}}, {{0x00014d7bc4df6981,0x000c45e951da151f,0x0003964143f3d397,0x00056c9c24be6549,0x0000ae1293e252e5,0x000bfda40e3aed33,0x000e72cdf82159a4,0x000f514f7b173b13,0x0000684bfa5b859f,0x000fce90812f67e2,0x0000000000000001}, {0x000a9abf7e9a0c25,0x000a823b0b3a0fbc,0x00011d2709072194,0x000b7a7f17f5564f,0x0007987f0af999bb,0x0009d6201796c014,0x000d35c45cce25a6,0x0009265843370c43,0x000a55401cbff6e8,0x0000eab503e2ea19,0x0000000000000001}}, {{0x000caabc4b5cd512,0x00034cdeccde50ae,0x000395d24049ffdf,0x0005918925068e1b,0x0003f93fb9ea4405,0x000a60ba95d141ad,0x0005981c42f76f02,0x0005946bf800414a,0x000435023138c47b,0x000f3cf314147e38,0x0000000000000001}, {0x0008bdcc69ae19e3,0x000ac73cebd917e3,0x000c35337880966b,0x000e6ede2718c3e8,0x000fd10236ae833e,0x0004797bb14f5b88,0x0001296485e76bd4,0x000a68194c12b2b3,0x000b75dc1e45112b,0x000dd88574000b0c,0x0000000000000001}}, {{0x00037d315eea24bc,0x000160f77a65b38f,0x000de27962237731,0x000bd3346f06ae65,0x0007a25b38b1587e,0x00055c6b9f2a1d2c,0x0002f34b1687394a,0x00054f27c66a0ccf,0x000866c84ecf3de7,0x000b4da4a0f4aaa9,0x0000000000000001}, {0x00066dd8b8dffeb8,0x000121bfeaeff003,0x000a80b5c3bfe941,0x0005b6a4c3fed2fa,0x000c623dfdf4718a,0x000b0791d22ef007,0x000949ccec61c6bd,0x0006e328d9cc6d79,0x00014a1530d03e69,0x000d45fdb36710aa,0x0000000000000000}}, {{0x0006dcfa61a8d3cd,0x000ff977e2649373,0x000089ee4ac6af49,0x000b86d61720bd71,0x0007848d2c5df2f3,0x00078e07afbcc66a,0x0007ceb1f230a9ed,0x0000d2f61bf5077a,0x000770c3ffbf99e7,0x0001487ae5f08492,0x0000000000000000}, {0x000ee44c464c2996,0x000d8f990f4f03a6,0x000453774274aacb,0x0005c8730ef447b6,0x000e5e02e661f55b,0x0009f13f1011e65a,0x000f4c8fe17d3ed9,0x0000dbeb35dd393c,0x000a7d1cd2327711,0x0003fb444802cd65,0x0000000000000000}}, {{0x00071a842f621fd7,0x0008594c057a1dea,0x000e1689c80fc8fb,0x00022f52adc9a8e1,0x00099c47b816309c,0x0000c495f00a960c,0x0002e200a0f356d9,0x000a87494b798824,0x000dcd587b7f9ca6,0x0009c4d76d2c396f,0x0000000000000000}, {0x00035970dd6ecf15,0x000449aee47a261e,0x000adfd394c8df13,0x000dfbec67553f2c,0x000aca43c615471c,0x000606556ef09db2,0x000a225f2e040114,0x00099dfb28da12ec,0x000812bc587a4c83,0x0001ab8cba898428,0x0000000000000001}}, }, {/* digit=16 [{1,2,3,..,}]*([2^64]*G) */ {{0x0006146954276a1b,0x0000c171344edf1e,0x000b30130812b4a5,0x000314a14896c770,0x000e796a686592cf,0x00079226d890053f,0x000869a5847ac79d,0x000cf60993a83ada,0x000e4b5fe7d156a5,0x000add7850cdf667,0x0000000000000001}, {0x0005bcbb35fb3dea,0x0000a34e2d6021f3,0x00090be93989877f,0x000303404d6435bb,0x00007e5919257861,0x000c99d1992710c0,0x0001c7987d3586cc,0x0008e8681c58c145,0x00059a487fa896da,0x0009a8b1a9e54366,0x0000000000000000}}, {{0x00029533273f3ddc,0x0009580b259ba7fa,0x000a4092fea94f8c,0x000efd38be9d56f6,0x000720f2ba425622,0x0007c0adb2a4d25a,0x00018752498a9ea5,0x000d893bbb4d11f1,0x00056b02f195ec41,0x000bca2ad72c4b2f,0x0000000000000000}, {0x000a4013f1ab7060,0x000f17521f983a0f,0x0005292b2f1ebae7,0x00075002debce289,0x00003b6cd203ad6d,0x000c3592c993bfe5,0x0005400a40b351b3,0x000e9b6bafed180f,0x000d6a9f0291283a,0x000563036cf95dd4,0x0000000000000001}}, {{0x000efa3e474a5b75,0x000e5a6d55141813,0x00008a31bd3435d9,0x0006a68b3c599425,0x000252817b3af9bc,0x0006a695a37f35e7,0x000f06836ac1d6b0,0x000b19a92f525bb2,0x000215d9b8e544be,0x00080723f1554fe6,0x0000000000000000}, {0x000e709e6109d280,0x000e367fd7bcb2f8,0x000be531b1c6fe21,0x0002d1fc5388b64a,0x000c169c0609b0df,0x000cd0fc3d5f664a,0x0003de00815f78ff,0x00049af9ff38956a,0x000e62c250aedb30,0x000af977c662b6e7,0x0000000000000001}}, {{0x000cfa5a95db7680,0x000cc333878665a8,0x000809b2a4ba5401,0x0009594f6cdc3f0e,0x000e99bbfac6790d,0x000d836074d551d6,0x0009d9ae874e847f,0x000a264b3b0b13f8,0x0003ac51f7a6ec5f,0x00021d6dd250c60a,0x0000000000000000}, {0x000e14abaa7747bd,0x000f127c3196cad1,0x00078a629241495e,0x000ded5d0cbcf8af,0x0005b83d56ec31f4,0x000c6ef029fa54b1,0x000cc516f0a12c6c,0x0000ce830e11ae62,0x000747fe9964fd2d,0x000c6756076a3288,0x0000000000000001}}, {{0x000b9a69b333564c,0x000cec5ad994fbe9,0x00091ab4f5d4d95d,0x0004dbde503f2b0d,0x0003c8b32fed7498,0x0009fa10339bf799,0x000b1e6b4c7bd908,0x0001c54e64a99794,0x000598ef7979d915,0x000f29a322ae1bc8,0x0000000000000000}, {0x00042520c237fcf4,0x000303a14c0e24d4,0x000f7ed62c67df4c,0x000ee5dfd3635dff,0x00097bcf94654c63,0x000eb529e2ea1f28,0x000969c7cff702bb,0x0003bf0591306903,0x000474be25c3afe3,0x000d8f2570e7350c,0x0000000000000001}}, {{0x0003d3d928f89c37,0x0004d9c668cfa4b7,0x00097ee2907da69c,0x000fb743bf4c3402,0x000cd4034c59cbf5,0x0009bc4b73d60ae9,0x0007664da82be729,0x0007e3800a84da1f,0x000700f12fb007b6,0x000882b546161eb7,0x0000000000000000}, {0x000e150bbd0f66b9,0x000122fc5d0def4b,0x0001ba0f43d660c9,0x0004e9263a5b4550,0x000ef33c24e5b722,0x000249e1b7ba92b4,0x000aa152b1856c8d,0x00095fe68108b2c9,0x000e766ae6e54017,0x000903a379f58c2f,0x0000000000000000}}, {{0x000980153e2aed11,0x000ca0053853a90a,0x00003bf5f23c9661,0x0009061283e91bda,0x0006236d967ae1de,0x0004f3d80708ed52,0x000bb014e9c6763d,0x0002f3d82f09bad2,0x000f8d828de34c80,0x000187805c46ac1b,0x0000000000000001}, {0x00086a0c8fd9feb0,0x000d468bed15d861,0x00036573dedab729,0x000d88e4dce7ee93,0x000d9e86caa8e75e,0x000c0d08d6110fe2,0x00082b709f0b0d08,0x000ab3fbb5af39b1,0x000c1b7910befecc,0x00062bf43fafb941,0x0000000000000000}}, {{0x0005341f232f3278,0x000c66dff5ad0b4d,0x0006270a82ebb141,0x0002897d7912e413,0x0006b6b16ad87fc6,0x000fe7c18f348f2e,0x000a03bae57af6d0,0x000a6d2d6ab02f22,0x00017c3e7efa7a28,0x0009c673423958d7,0x0000000000000001}, {0x0004f0f2ce49ed5e,0x00055b8c6c92190b,0x000aff1be7fa884b,0x0002c375de74b331,0x000f37a676c7d888,0x0001190b6b57c355,0x0009c95180dbbfa7,0x0001d7dc77b1599b,0x0007eba118f76648,0x0004aa840229ee22,0x0000000000000000}}, }, {/* digit=17 [{1,2,3,..,}]*([2^68]*G) */ {{0x000507b4b3de6fe0,0x0009064574b533f1,0x00076eaa707b56c3,0x0005e98aa9532376,0x00034611c9b6716e,0x000eb6a26112d9a9,0x0006e068430b4789,0x000e50fd96103fab,0x000509b62d215cdd,0x0000b7c4da786d1d,0x0000000000000001}, {0x0002a0af86e4be0a,0x0008383ebf635e75,0x0009175f3f7680f5,0x000b999d9f1a0d87,0x0001f04cce1e2861,0x00086e6afd75ef23,0x0004476af7240e6e,0x0005e887f56c0473,0x00094ba352837e09,0x000f469e3dc524c1,0x0000000000000000}}, {{0x000726e7d4a98265,0x000a397d1e874b3c,0x0008c78c755a513d,0x000fef1392677915,0x000e1e9e24f3ae62,0x00096cf6213d1cf9,0x00004b1f503d4fcd,0x0000f07e39bb0e12,0x000406c607195818,0x00046d3b7b9a617a,0x0000000000000000}, {0x000b43a8c35ac9c8,0x000a92f37f3857cd,0x0008ae49b6bed377,0x0000e3380827d789,0x000e2deff6865bd5,0x000758e466fdb287,0x0001f3ba0c560a0e,0x000db418a2645432,0x000aa26f5d44767f,0x000d36cc7b7f8bfa,0x0000000000000000}}, {{0x000020f87c5aeb2e,0x00035693c551e0d7,0x0004a7f0938f3f98,0x0008d4d829ae419e,0x000d8e42f19ee358,0x0004d94560e54e60,0x000ddb20bc96b546,0x00014bfcf64c2c92,0x000518fec9517e43,0x000a92773a95b0b8,0x0000000000000001}, {0x000c159b5e61b250,0x00070c6538519060,0x000d0372c4dd1c2d,0x000fd8998866b5fd,0x000ceccabb79115b,0x0000eee1fb689260,0x000b839fc8378f05,0x000677dee33a7134,0x000b9326b080c62a,0x0003ae07e602129a,0x0000000000000001}}, {{0x0000dde02f16a4fb,0x0001ca814d149b58,0x0003cc8c599eaa3b,0x000d833d43a45440,0x000afdba29de3c98,0x000b2ff2056e31f2,0x000ab3bf81e95cba,0x000649419f19b530,0x000585b648a6e1bb,0x000ff11dfbba1ed0,0x0000000000000001}, {0x0004734696bc60cf,0x000199c0250d4a2b,0x000d4759758b9f4e,0x000f68bc326d4e2a,0x000cea78113abc32,0x000d248f92840b01,0x000d61ebd87644ac,0x000ae9a32d38a8d8,0x0000c706b58a69c2,0x000561f4b942e16a,0x0000000000000001}}, {{0x0002fe7e20769488,0x000a1c068b87a199,0x00032a3459c496fa,0x000e96c391b8839f,0x0007f4914cec7211,0x00039756176c58a1,0x000aa63441905f9c,0x0008ea16377fb867,0x00042578ce2a2865,0x000cd140c73dd697,0x0000000000000001}, {0x00074ef7ab059a14,0x00031e0f7d0f636a,0x000fea67e10b4430,0x0006ef5711a15a06,0x000f717856862153,0x0002513381cfd3a9,0x000a8b9906086974,0x000a08521bae079c,0x00052ef6a1d4b90c,0x0004f5ad24ad39a3,0x0000000000000001}}, {{0x000c2d28a3a30e7c,0x000933949c694069,0x000d1f2a5ed527fa,0x000e2b5573d97d5c,0x0006aa892b500798,0x0008ac4418f1419e,0x0007bf2d1e227f12,0x000bc2143f4c8a62,0x000ae6ef99da3403,0x000679827f46143c,0x0000000000000001}, {0x000a8cba49268935,0x00038ccee58ce9de,0x00061df0ac493218,0x00075eb49225f314,0x000073000d3eb206,0x000145d79e65edfa,0x00007b1990aba7cc,0x000c916353a37685,0x000854a40d94fba3,0x000cb2e109e1b50c,0x0000000000000001}}, {{0x0000c263771f69c1,0x000d1595543d358f,0x000ef2e3d8a56184,0x0005866bc8c3965a,0x00021c100a7748c1,0x00029b46541a4ddf,0x000c5cb49ea744d6,0x0007a3a96b8b1fb0,0x0005aa7e85061bd2,0x000163e83c339e28,0x0000000000000000}, {0x000102ac6923a672,0x0004153c3e1bd59a,0x0003473bcdaf9384,0x000f589da2a6c958,0x0003af0eb1a0311a,0x00041f50baac8d3b,0x000bd2c8728d9afa,0x000fc24b4e16e953,0x0003e6d4570ad37f,0x000aac57efaaa8de,0x0000000000000000}}, {{0x0008c7fccb0a85bf,0x0003bdff198eec53,0x00029ee8af84ec04,0x000572ea125b846f,0x00025280cfc9ed01,0x000f73f2654ba803,0x000ffbf57e3b7be3,0x0004f83701a26bca,0x000d20a251a2d372,0x0003ec410f80b319,0x0000000000000001}, {0x000961197dc0e519,0x0003d8c136f93b3b,0x000000ba8d6c2646,0x00084f848d99824e,0x0003fcfbb42b20e0,0x00038715f781fef3,0x000bdd048ed10781,0x000042869724ca7d,0x000de2c203c66b90,0x00090489fab2c4cf,0x0000000000000000}}, }, {/* digit=18 [{1,2,3,..,}]*([2^72]*G) */ {{0x00038bb0c7aa46ca,0x000d2cad2e37a158,0x00054d33ad65a28c,0x00004b20d4f1caa9,0x000b180e4c9d244b,0x00070a13f58c65ce,0x0008816ecff016c3,0x00016ad260aeee75,0x000dbb7b595c36fe,0x0002944d06dfe8bb,0x0000000000000000}, {0x000c325d67839921,0x0006a5955c2a22f5,0x0001664092579a37,0x0003aac4f8e9390b,0x000722a8dbf2236b,0x0007b02d94034f2b,0x000fcd8d5de86b97,0x000fa8bc9f80729c,0x000bcbc03be296bc,0x000364ec1469f11d,0x0000000000000001}}, {{0x00048e2fcaa83f58,0x000495fafcc6105f,0x000d34073fc2c5d9,0x00042510321d1a08,0x000d83427742e304,0x000ec5f97b8068ff,0x000530da7faa8a52,0x00005d010e52ac14,0x000df5701f277a14,0x0000eacdd532283e,0x0000000000000000}, {0x000f566cbb172daf,0x00050c51771845f8,0x00066aafeeea7b0e,0x0005258081cf4ee6,0x000c71bc2c6ec8fd,0x000790d250232a19,0x00011bed4c06ab26,0x0000acd06e0bdc44,0x000734273e0fd2a2,0x0005c1c9fb738a19,0x0000000000000000}}, {{0x000b6ef22ab96e69,0x00026b8cd18dc5dc,0x000563a07bc4111e,0x000f73913482455e,0x000edcb5ec4ad0e2,0x0000caacaf21483b,0x0000f16a5a48441c,0x0005bffbf280c9e8,0x000f37a7690242b8,0x0002eed954418691,0x0000000000000000}, {0x00066d6e31428479,0x000f47fc4b8794a7,0x000a81360ec38293,0x0004d77d31e9f867,0x00042db92af31be3,0x000d799976882df8,0x00005ddd34a906cc,0x000b961ddfb3abb5,0x000bbb326a3a37b0,0x0005d4f7af85a74f,0x0000000000000001}}, {{0x0006d183b4b1bfc3,0x000143cdd1f50d0b,0x000721cf9d088770,0x000338fad247118a,0x0004efa498ee55a8,0x0008d9808733ff45,0x000faa72107a954a,0x000a392986064eae,0x0000c503bc385af5,0x00095cfc7e0cec3e,0x0000000000000001}, {0x000f6c1133ea5097,0x000685bf161ebfa2,0x000bb087e9c48b5f,0x000987c958eb481e,0x0001ea465a54c3b7,0x00081943446e92e0,0x000a8941e66d88ba,0x000d40dc6c71b0c7,0x0007f59a3690cafa,0x000130f02679ac05,0x0000000000000000}}, {{0x000c5b4b93b19e8d,0x0001b316df16919e,0x000549bdce1a1a0a,0x0001cc00d06d528f,0x000cf17722a1d1b7,0x0009c7821f1ae098,0x00007c6fc2825a3d,0x000f796a6b06d5bd,0x0004ca4366a06040,0x00072103b88040d4,0x0000000000000001}, {0x00038b6ea0266cec,0x0003d4ff03eab713,0x0008f81bfb033aae,0x0004b58cdd700e03,0x0002486b62595d6a,0x00027288e5a75ffb,0x000043649c2c3428,0x00056516d9dc3a87,0x000145473b4564bc,0x000f9a0961272b27,0x0000000000000000}}, {{0x0006ad885aea13aa,0x00022fbb0e237052,0x000115fb0a1aa034,0x000ccb8ce398278d,0x0004178f8f78a3bc,0x000403be5854a510,0x0006bcde0e2e720a,0x000edf5f632b7fc4,0x00038eed71d606d0,0x000d21f92dbc6d75,0x0000000000000000}, {0x000631ff7cd8f78c,0x000698475f524849,0x0005eafa796bd6f5,0x000fa7a4ee42bd53,0x000b8f8540687776,0x000540f9fdea3095,0x000f5bf17004e5b9,0x000834c440599d47,0x00063874f7c8a4ef,0x0006bec9a4f28185,0x0000000000000001}}, {{0x000c12a0297bd390,0x00020c5821857743,0x000e07f2b528d6e4,0x000318df51deafc4,0x0009c03086d94e26,0x0004d01fde5e064b,0x00071c1d5855c1d9,0x000cdd2d762cca56,0x00022e583500cf8e,0x0003f52279b68b61,0x0000000000000001}, {0x000b572837258eb6,0x000b88af33e25ea0,0x000ba976e7082c63,0x0000d0abef5e06ce,0x0005c8fda6ac69af,0x000f82b26435f42d,0x0005ef9369e629b7,0x00029491bb2be768,0x000ae13ca4da59b7,0x0000f00ce8846bfb,0x0000000000000000}}, {{0x0000079959682d5c,0x00076719e3233b3a,0x000c78c2194cd545,0x000e51d3c744ff86,0x00053afacd6dd789,0x00098cb1ba7a5cd2,0x0004fb918b560853,0x0009ff1bce38273c,0x000a7efa90ba240c,0x000ba73bb2e372bc,0x0000000000000000}, {0x0003a114b353d398,0x000d2df4adbd1d56,0x000e9ad940e90284,0x000fca7fe3af63ef,0x000de96feaa4e61f,0x000bf94ff4ba0669,0x0005279d7b8471ad,0x00071dda976e696c,0x00066b8800a22911,0x000f5fba44b58815,0x0000000000000001}}, }, {/* digit=19 [{1,2,3,..,}]*([2^76]*G) */ {{0x000b896b5317311c,0x000ccb025efc3b29,0x000bcd9f85c60e34,0x0005f821ae29c1d9,0x000293dcc63561e8,0x000f95824c27219e,0x000843c9e01039f3,0x00048ef0f79fd3a9,0x000ddb5a3bba44b8,0x000011f0a7f5379c,0x0000000000000001}, {0x0000be31597dedd3,0x000aaa0d73669dd4,0x00090c605d60706d,0x0007d62f262a826a,0x0005e90997b0e2e6,0x0004dc73225ac29c,0x0008be39728fe4ca,0x00038656b7a746c2,0x0008bd5a3cf46a3d,0x00080a0c58ac7031,0x0000000000000001}}, {{0x00070e2b4e96cd1b,0x00023ea39d68ac53,0x000f98a99040b26e,0x000362a9be557ba1,0x0003c202765cccef,0x000726d7b5a7731e,0x000faf8cd815e2ba,0x000ba6579cd91c25,0x000ec8fb3dafb2e8,0x000af4648049fac5,0x0000000000000000}, {0x0004b6251452046e,0x000cb296110b89a0,0x000551f88c9d1ddc,0x000bbb0b0f26d015,0x000c2b5bd39d39b8,0x000dc18ef79d52ff,0x000b527ab6d006e2,0x000a804f61d0142f,0x000be5992391511f,0x000815a3e717ea9d,0x0000000000000001}}, {{0x00029eaddc553333,0x000212246b16c20f,0x0009da31a639b833,0x0005a63d297cf150,0x0003190a2a3a8499,0x0002ca8af6260545,0x00018490cdf918d2,0x0005a5ed4b646253,0x0004fec387ca9de6,0x00010b72b35acffa,0x0000000000000000}, {0x0006d539b23d78ec,0x000a4b221e3646f9,0x000b6bf83af256f3,0x000d62f0c408a90f,0x000fdaefff14a7ab,0x000e41ce0c4069cd,0x0001cba29824953a,0x0007a382ab7eb47d,0x0007f64599eb440b,0x00074a4c148b6095,0x0000000000000001}}, {{0x0005a160c85caa71,0x000f0e79edff6be6,0x0007704970c1ae3a,0x000a395f8b957c42,0x000c85f0f181eb8a,0x0007d8f529bdf3d6,0x000d3534e626c58e,0x000c770dabfad83f,0x0003e65d7e5ada98,0x0005676430730bac,0x0000000000000000}, {0x000d0476d73fcec9,0x000d714dcf97c309,0x000a56a3252ab9b5,0x00097fc79648c08c,0x0006b897ba609ff2,0x000c446a06ff8430,0x0002d01ddb643744,0x000f97ee1218bc20,0x00048db33f9b0f80,0x0005e8b5f54bb8f0,0x0000000000000001}}, {{0x000851bfcfbb80d1,0x00082b51c40077e9,0x00087cd565dbfe09,0x000954bdd372a1cb,0x000f6bbff7b4dccd,0x000237c51d294b36,0x00003d64ce0f8798,0x0000569d6e3c2614,0x000a6224fb79e0e6,0x0004d7c33dd3b5eb,0x0000000000000001}, {0x000f054ad5a9cfa1,0x000bee5f93daceaa,0x0008aa260aa160bb,0x0005025da9f4b722,0x00004817d1e67b1b,0x000e00279781308a,0x000c2084afd2f00f,0x000c154f68e6680c,0x000c6b0f1d4b7ecc,0x000fe2b89761184c,0x0000000000000000}}, {{0x0007fbeff2b9ea68,0x00035c954c6cefab,0x000062277d67291b,0x000820637553137c,0x000e8b75730d8af4,0x00068d2250710c68,0x0007a2fbae3e7c1b,0x000f6b643e1aff63,0x000dc46991ef002b,0x00096e38ab4582dc,0x0000000000000000}, {0x000bea0d80f3758d,0x0001d6899ee62692,0x000cdd2a79a4d763,0x0002f50f2ee3aea9,0x000fb1476eea0816,0x0007c81475c4d433,0x0009d9fe82142372,0x000756c76934dc96,0x00033eb086d918c8,0x000e3056d2a89175,0x0000000000000001}}, {{0x000ef0de9496fb55,0x00076806fa762c50,0x000770bcaf6f226f,0x000a0d3e47cff6b0,0x0004eb780ef8cec1,0x00034df87449872a,0x000896382a505c84,0x00046b56a94dfc29,0x00021c7a5c037f2d,0x000659ef98ff9417,0x0000000000000000}, {0x000001c935289072,0x000f4a229e4010ce,0x000b1be023ab7710,0x00073fb44f780b68,0x0002944ddc611373,0x000ba09ab8b61290,0x000be003d4bb157e,0x000f7557730f52d1,0x000506c275d184bf,0x000c57abea8b4979,0x0000000000000001}}, {{0x000004498fadaa48,0x0009d0bea3c3894e,0x000a8f46458aa39f,0x0000008b0b3654a0,0x000ca4cd7392bf83,0x00012eb97aa46a22,0x000b9cb80e1d7afb,0x000cf74c8adcd888,0x000b51d04bb6e179,0x000b50968eb22473,0x0000000000000000}, {0x000f96d03d831756,0x0007499de9e10051,0x000ecddcd4ffade3,0x0009dbdffc72771e,0x0006b5e1bb9647aa,0x000addb508dc2415,0x000ddf40de78eeab,0x000ab1c488946fac,0x000c823824a964d6,0x0003b16f258c8749,0x0000000000000000}}, }, {/* digit=20 [{1,2,3,..,}]*([2^80]*G) */ {{0x000cc508d53fa611,0x00057fcd40894532,0x000f3eb54e960b10,0x000ea40877d231ff,0x00043e5110313bd6,0x0005209f6eb9ee83,0x000589764924e778,0x000332e258b2e7fa,0x000e2e038618a6eb,0x000aaf96067c3511,0x0000000000000001}, {0x00022156015c8ff4,0x0003a0ef974e440f,0x0008ea1f931a1b7a,0x000e417472932b48,0x00003bb75d745720,0x00096758e51bf9c8,0x000f97c7f0b39099,0x000b39d56a488d83,0x000fe1ded1fac932,0x000399aaf43ccf55,0x0000000000000000}}, {{0x000fb78344f73774,0x000a49ad3e73876f,0x0008771e37ad3158,0x00003f2cb98ec469,0x000f31bd531106f1,0x000434959ff8325a,0x00064eee47f875ba,0x0001cf224bc0a102,0x0007d33a19ccf2f6,0x000f2186ce603133,0x0000000000000001}, {0x00006e91f2869773,0x0000239179c5ea67,0x0009aa4ed3879ba3,0x0003eb977e239f26,0x00090ef091443aa8,0x00036fc4d282853a,0x000a0bb2b260d343,0x0008119fbd0756b3,0x00053a3a6e0f1619,0x000016a2af080234,0x0000000000000000}}, {{0x00000185bd1fcc92,0x000a0002ebe1f280,0x00030d3e5f23ebcd,0x0009d40f75cccaba,0x00063108edd488ea,0x000028024e152a65,0x0008296732e422c6,0x0006142e6cc11761,0x0004e44889dea726,0x0004d1b05325e95d,0x0000000000000001}, {0x000270a2e4063870,0x0004d9c29b5dcaf3,0x000d2f759d7bad98,0x000ff7c2ad7bc046,0x0000fa4e4f59d347,0x000a06be29c16d4c,0x000bb31872d14ff0,0x0002b7a5b6ec2390,0x0008ae4cc66be2ce,0x0007006b9b1fe040,0x0000000000000000}}, {{0x000c4cee52cfafd0,0x000916a99628d59c,0x0004417813a4764e,0x0003f0c49a05da16,0x000992babb644e42,0x000179a66e24dca8,0x000cbef894f6883d,0x0001ed7756c7c157,0x000ff08e144c3013,0x0008ac78b0a3e9cd,0x0000000000000000}, {0x000dabd753963ba6,0x000426be7ba3ec43,0x000d17b8f8b93626,0x000d7ac0bfcd2a78,0x000c2aeda53c9486,0x000c99eeaefc3c49,0x0003d0949fb4a9cb,0x0005db07562812ab,0x0005da4c6c0f863b,0x0009e08ec31fe43d,0x0000000000000001}}, {{0x0008d00b0f45825d,0x00075f4acb7a9109,0x000fe317cf8f4f81,0x0009a77cf8155d16,0x000d7ac3ddeef2bc,0x000aeae3c417520b,0x000e6ff44ee6fbc0,0x0008d8c238521aaa,0x0003f42c9f47bc82,0x000d2fc09b26d055,0x0000000000000000}, {0x00032ac7c6897ed6,0x000498c1e669bb9a,0x000697322f4c8aca,0x000625a543042d46,0x0003cdf16aa69334,0x000b4b67c267bda0,0x0005d6f205d341fa,0x000005daa2bd83a5,0x000c9573fcdfd94e,0x0004e81cb76afe9a,0x0000000000000001}}, {{0x00074fcede51930f,0x0001c997863b91f0,0x00092d449a3c4328,0x000c91197a68c2d7,0x0006a3b2de0b3063,0x0003e7d82555e166,0x000f427f70b4227f,0x00066c04e18d6aac,0x0004c82c2c2b9b61,0x00095a376fa210aa,0x0000000000000001}, {0x000de0f4a3a29f55,0x00023263844f1727,0x000fd0bec7770941,0x000e79f43b5f4e85,0x000035cbc9a5768f,0x0005bb2328826a73,0x0008a77da7d22096,0x00096978fe424078,0x000ae1a0514c7cf9,0x00085e77943ce3c2,0x0000000000000001}}, {{0x0000d1b4594afc85,0x0006a925e9937fdb,0x000d1cf398814c56,0x00000694cd250848,0x0005fbfd82b6ccc3,0x00047db4ae135bc7,0x000c1f18639e63fa,0x000730a5e5b32295,0x00041bb1c61f91b2,0x0009451335383b28,0x0000000000000000}, {0x000df27e3f2dca32,0x000ee40fb695c7e1,0x000c8c313d1721a9,0x0008bc93267e9801,0x0006a9aafbe12b28,0x000e34c2b180d7a3,0x000e6b65e8b79ae5,0x00047da7f03b22ef,0x00094e563552e913,0x000f4aab16538cee,0x0000000000000001}}, {{0x0006db42e9e50fad,0x00042149f7546b33,0x00057093c06f6900,0x000dbce88e00d7d3,0x0004ad9ede7428d2,0x0001940521d004dc,0x000e4970d3be2ce0,0x00031bb5cf60dc4a,0x0003df5670a6ccb0,0x000b64df04605d80,0x0000000000000001}, {0x0005f0fb0c7d8a77,0x0006951f8ad28aa0,0x000e5b908dd39d0a,0x0005f76fd67e92ff,0x00080f281077f416,0x0009ee2db2c8d529,0x000e9a09ff0b841c,0x000f9a5850f2e792,0x000e9887cd74d1ff,0x0009aa468c4978db,0x0000000000000001}}, }, {/* digit=21 [{1,2,3,..,}]*([2^84]*G) */ {{0x00045bc39568d9b4,0x000deebca99c74cf,0x000ae132b3816aa0,0x0003fb57b713a9d8,0x000e4139b0131f8d,0x00042164bbc38156,0x0005a533293d5ffc,0x000f28a54d0e74da,0x000246758970fcef,0x0005cb3ef8fd2b56,0x0000000000000000}, {0x000e59886b3941bc,0x0009ade1a4b217a0,0x00023117719aa3f6,0x000c88c1b7b4e45e,0x000c3f1294233118,0x0001ed8c9dd7dfa5,0x0003ffafa2104f8f,0x000e89ed71382221,0x000d0f8573ea0a97,0x000a81f09db9f82c,0x0000000000000000}}, {{0x00077d542b1d8c85,0x0009eb6c76648a7d,0x000ae9936fca1675,0x000c8db3d9556eeb,0x0008f1fc23af7239,0x000956a6643df02c,0x0005264fec894e1d,0x0000aaa92f802a0d,0x000d756f014a90b9,0x000e0753d197ff93,0x0000000000000001}, {0x000dc80b7f62d4df,0x0005de026f897406,0x000bf46ad6add1ea,0x000f1c5d1c416858,0x0004d6b3d82ce8f0,0x000459159df587ce,0x000ca473b92c19aa,0x0006da5bec10b6ba,0x000e0b4be600af3c,0x000cf6c81e2b9b40,0x0000000000000001}}, {{0x000c67c15f2b99a5,0x0002e78f41b12d02,0x000f7e85b9e3bb96,0x000e6c293dd82110,0x000a0b7296f35eee,0x0008b9f01a446a48,0x000f7d8d89873daa,0x000d90409d0bfd67,0x000b42d1c91c3962,0x00005e6c3afa1fdc,0x0000000000000001}, {0x000607a511880114,0x00046b3caa5f65bf,0x000ed1d7edcb6427,0x000223b76ca3eaf2,0x000c254785aeacd8,0x0003d96bed772614,0x000fe17074c3138f,0x000fc4599803c303,0x00029d4441854c4a,0x00068d2f47c7e6ad,0x0000000000000001}}, {{0x00027dadf66942d9,0x0002d934d4f0887d,0x00024ab4a3b4ff58,0x0008094d151ee4b7,0x00059df116aee58c,0x000c8ad8141ceee5,0x000c277f6cc0cd16,0x000b9d41dd2c3d13,0x00018d63c75e0cd1,0x000c06bb0767f3f3,0x0000000000000000}, {0x0003f3f369ef6b69,0x0007808f1170f91f,0x0006338ef6344906,0x000cb4597495e6b8,0x000283f524ab766d,0x000d7731127ec634,0x00075be86373e0af,0x0008d2af0e3a5495,0x00014c6819dfc2be,0x000f7affa7af5c63,0x0000000000000001}}, {{0x000892c7124cd33e,0x000b92182e71043c,0x000db014cae4df90,0x0009ceb0a4ea4119,0x000ef942ed19b706,0x0000628b68098d1b,0x00084c6cb159ff0e,0x0004d4b5184cdc53,0x000190191d032e77,0x0006b2ec68efce97,0x0000000000000001}, {0x0003436236c90d20,0x000e12c74816ecfc,0x0003e074e74849dd,0x0007be255b09c30d,0x000526507824bfa8,0x000ef7cb512aeee2,0x0002afeb20a50c2e,0x0008aa489a2c4123,0x000334adba554c1c,0x000ed1b94b601c93,0x0000000000000000}}, {{0x0001c752e894f83b,0x0001102db47294b0,0x000efd031528755f,0x0008e7a5233b9d7e,0x000dc69c62c7500f,0x00051f44711ee3b5,0x0009d94a5e280f05,0x000b11042cd8c7dd,0x0008b14370c2167e,0x0007807f4636e4af,0x0000000000000000}, {0x000598691d482817,0x000b8412f599a077,0x0000459d6b4cf61c,0x000405e26f27cc0b,0x000ddbc7fdaf5126,0x000cdbba7c4a3026,0x000b262658e4a3b0,0x0000f2e795bb25d0,0x000766509eec95e9,0x0005a452259c52c8,0x0000000000000000}}, {{0x0005f6dc2c523bd7,0x000003d082f18f83,0x000ef7ee57fec42f,0x000f2558c3c5a1e3,0x00038f0a9e89f93b,0x000efbe9151ca6a7,0x000ed767c4685458,0x00079d486204e6f8,0x000a36a1a4b728f1,0x00043b885c25b705,0x0000000000000001}, {0x000eabc2b52d4646,0x0006c95bf22f084b,0x000314aed2f78fee,0x000dd61877362fd0,0x0009044697d005db,0x0001d56d41727a4e,0x000627e07ab413dd,0x0000b5903e3cd67c,0x0009c224e9a02779,0x000806739d1d3428,0x0000000000000000}}, {{0x0004109673b0becb,0x00029788f9eb9435,0x000ae5dfb3d20da6,0x00057d88527623e5,0x00015c844e99c175,0x0006a57ec3b40311,0x0000b594aff5aa0b,0x000cea2e84adbe7d,0x0007fcbaf1e84a37,0x0008e3048c293594,0x0000000000000001}, {0x000f58bede275de5,0x000b21503171b093,0x0007b8e1c737aaa2,0x000dfceb6261f263,0x000d21e8e8701620,0x000e453d37db241d,0x000825774e79c85c,0x00066f92bc717db8,0x000b9d9ff5a2566e,0x000bfd4ae0bd7b6f,0x0000000000000001}}, }, {/* digit=22 [{1,2,3,..,}]*([2^88]*G) */ {{0x000cd0f9ef7a9efa,0x0001757bbdb01042,0x0001996a380a3fbb,0x0009e651f39db731,0x000cdf3f08146bb6,0x000679b0b6ec6679,0x000ae26608474788,0x000d883e5a5990d1,0x00061924fa5e209e,0x0001de3c755c0bba,0x0000000000000000}, {0x0007c1f82ebae92f,0x000ccf8ace9c6a84,0x000857d9026a1434,0x0005b0b7ad864d4c,0x00018f613e2210ee,0x0001165b2c86a357,0x00019fb55984d679,0x000f15401901080d,0x0009a0e8b3389ecc,0x000e608b509b98d9,0x0000000000000001}}, {{0x000a526cf604c662,0x0003afa9ed0f7a0c,0x0001dd685ac125b3,0x0007ff8f516f5290,0x000ad927c416e17e,0x000fc77cc9720475,0x000071767e1e9190,0x000f6652fcb33aec,0x0000f0d48cb2653d,0x00086c8bf16720d8,0x0000000000000000}, {0x000404c440590fcd,0x0003377f43e4e408,0x000defb22729c42e,0x000241aec3b37e10,0x00092c795c866daf,0x000f4d30790a07c8,0x000075bb2425f5fb,0x0001b7cb5830a5db,0x000c950890875f16,0x000e6591cad66493,0x0000000000000000}}, {{0x0003de8c91c31e47,0x000a2de46bc7eb7b,0x000f3de301a0b479,0x00094aa7479aa235,0x000be5191502fe1c,0x000266a8b4adef28,0x0002961e0e185a17,0x000f211c2c23ddea,0x0007d3314a5b8f85,0x0007d3d59f2b026d,0x0000000000000001}, {0x00032b1fd4f159bf,0x0003721f923e006e,0x00024a7d38b715f2,0x0000994620d23277,0x000ab6678b2917d4,0x000fa4a8245b0c3a,0x000912038e0b4172,0x000f6fdcf8c4b1b8,0x000ccd3b3eaaf19e,0x000d40f97e7249e4,0x0000000000000001}}, {{0x0007975597dddacd,0x0009d9266f6975c3,0x000599f544c22dfb,0x000c2be6db081480,0x0002aeb8ec462839,0x0009d49cd3b5cdf1,0x0006a8ba917fb29d,0x0008233b216f9614,0x000abf1a9d936c0b,0x0007878c8a45a2f0,0x0000000000000000}, {0x0005dd64a0356029,0x0008c2d1625aef0f,0x0005ff56fc705652,0x000323cb9b293d67,0x000bd02b295cca5c,0x000c7129104d697c,0x000d83fe4eb4b02b,0x0004a4e9327cc1e4,0x000f46cdc9c23cdd,0x00053f946406995a,0x0000000000000001}}, {{0x000d1e43a1e16a36,0x000514cd5be788b6,0x000f3827d2f55b7d,0x0000a3f8f594d05c,0x0006accb980d1448,0x0004ad1e4f1f6b59,0x000e7dd3016801fc,0x0007c435098ccf31,0x000c6bc2e61b9059,0x000588b12be241e3,0x0000000000000001}, {0x0000b8e2e65481b3,0x000aef410135fbc4,0x000c7a2e23221960,0x000fd4a513faa141,0x000a0357c6f569e3,0x000f4ac3eadff143,0x000f6174146f64bf,0x000c13f9a5506c59,0x0005ed7b5be845e0,0x000d0deb4721eef8,0x0000000000000001}}, {{0x000e8dfde28d4a2d,0x0001761a2d5208a2,0x00005b6ff5ebb541,0x000b58d09bebbafe,0x000a9eccec1be769,0x0004b3933ce41d83,0x000e22e31e1a1a39,0x00081430e109c5df,0x0005c36dffc66dc3,0x0006a93ad68549c2,0x0000000000000001}, {0x000135d5a197f614,0x000b4beb4875f558,0x000374737f60f213,0x000b3391150b17e2,0x000fd51cce3f02fd,0x00090f492191217f,0x000bccbadc4f8a8a,0x0005d89eef2479ce,0x000b7145781a1c26,0x000e4d791a7d8953,0x0000000000000001}}, {{0x0006a3d38b806bee,0x0002ffcbc7fbb018,0x0004904b1192a4cb,0x00039b7f571c01df,0x00040717c8035f6f,0x000f75f4a725c0f7,0x0003575b1f8427ca,0x000cefd7922924c3,0x000c3f91c6705a27,0x000f14804d6b5694,0x0000000000000001}, {0x000d6688c387623f,0x000533d1b2b7249a,0x0006a96c61952611,0x0009fa8adb7cd547,0x0006614cc5f19687,0x0000dc38a5b55739,0x000b43a1185de8e8,0x000489b0890de38d,0x000cfe16e6aaab3a,0x0009a02c0ab01066,0x0000000000000000}}, {{0x00047414fc9de104,0x000b82aed9435d61,0x00062ff16a9bd16d,0x000caf4a3b07e71a,0x0003ff9456ee752d,0x000d78dd65ea0d3e,0x0005bf864901fef1,0x0007bc9f42253114,0x000cb13ee366fd36,0x000fe6290083f481,0x0000000000000001}, {0x00032088e6e77ebe,0x000f38c5e887c852,0x000f005e149cc7b3,0x00089874e1bede78,0x000c72dfeaf32e8c,0x000cb0a4d9cb4e28,0x000aba5da48c7113,0x000b1fe289a0af7d,0x0005d0dc00d3633a,0x000801c0b05c86bd,0x0000000000000000}}, }, {/* digit=23 [{1,2,3,..,}]*([2^92]*G) */ {{0x000567a7a06de008,0x0007cf045155d807,0x000ce8bb24635169,0x000c2900cba64633,0x000c724297174dd5,0x000c3a3851e7f044,0x000f59548c830bf0,0x0003817a26f0d35f,0x0003d8b027d923f5,0x00062c2b3dd7cad9,0x0000000000000000}, {0x00094cbf6924bf9f,0x000c09986d299bcc,0x000f89ccb5adf6f5,0x00099f825aee26f4,0x00056c1b545bb186,0x0000d22aa56595e6,0x000ba5ea3953faeb,0x0003a9580b4b6abc,0x000465246d4e240d,0x000d8613b6fdf7ef,0x0000000000000000}}, {{0x0008a64cd725af51,0x000d6dda66823389,0x0001f40d7d1c8516,0x000115e05fb1f564,0x000ad7906c2d8d5a,0x000f4efe00496ac4,0x0002d973643f7076,0x0004414f58386c89,0x0002d83c2e34b14c,0x000437c00d08bc7c,0x0000000000000000}, {0x0004451656bebe71,0x0003f2219e2e5bca,0x000118227eacbf3a,0x0007e2cef1a84019,0x0002d58a5f9de601,0x0001ecfa6e192212,0x0006fb198696eb0f,0x000854826be2d3df,0x000dea0068fefc08,0x00074e77c2979102,0x0000000000000001}}, {{0x00048eb205a5b22a,0x0007d680f21ad148,0x0008e50bcbdde0fb,0x0006f6074c1119fd,0x00079f9f2e43583d,0x00065361f1d9961c,0x000463e625f26bb7,0x000f2b47c8db008a,0x0008c397787cd134,0x00029b36eea7ef32,0x0000000000000001}, {0x0006647223894ce2,0x00087adfe036fb3d,0x00067daf1eb206e8,0x000b19b372f017c4,0x000a8ad33a99ef7d,0x00055c0da806ea7b,0x000c02414bd637ef,0x000b598649739b12,0x000feed3dd282f3b,0x0003ecce69b37255,0x0000000000000001}}, {{0x000e5f81ac137092,0x0000518f81e9a3bd,0x0009720014a7f4da,0x0001f457a02bf073,0x0006be074553e9ff,0x0004351eaa3a46ea,0x00022b27e32f0dd6,0x0003b488462fd22b,0x0006ddddacafc2c2,0x00035bfb75908f56,0x0000000000000001}, {0x000987332b5b9a11,0x00044ffe94dfd9e8,0x000f9b91bc64f63b,0x00077f430dbd772b,0x000dfd580392aecb,0x000ddc69fb2fb67d,0x000314d2fdb69c91,0x000e754b9b9f9ea2,0x000f2e9c2e624f23,0x0000a3c6e677e1f3,0x0000000000000001}}, {{0x000e37a930c3bc57,0x00006f969b4cf1af,0x000df3ff74237c4c,0x000d1ea35c488b6e,0x000e084f47372a77,0x00065b61ccb75b2d,0x000a4e47577fd773,0x000dbd98a086f5f2,0x000533002b74aa9d,0x000bedfb9c8068e6,0x0000000000000001}, {0x000b7aec02da823b,0x0009baf08dcbb7e2,0x000400bf0e5f485f,0x0003a3c7f9dfd4e3,0x0007472ece43050d,0x00091a092b1134f2,0x0004c1a0e70ff8a8,0x00037f3b75a31807,0x0000f51f254e9906,0x000c2183d0367614,0x0000000000000001}}, {{0x000a39c0dd80f6fe,0x000a13cb07adfd25,0x000ee3ca4d8c1a3a,0x0007a28212986a18,0x000c5167c4c47943,0x000beb7b7306e9bb,0x00038cfc9b26c1f3,0x000b68e5bc206604,0x0003bd9665b63ba8,0x000661b9d7de6c40,0x0000000000000001}, {0x000c9e6e7c3229ea,0x000fb93cb721672d,0x0002429ae120fbe8,0x0007d3de1f64e3d5,0x000492888bee099a,0x0009c2f4894dc1d6,0x00011bda9ef3c7dd,0x000289559ae47758,0x0008fcbb34df4ae3,0x0005c440c5d0ce22,0x0000000000000001}}, {{0x000fc1fd2377e231,0x000257cc9235e4c6,0x000a8f0482692e0c,0x00027d24355728b1,0x00087856d3663645,0x000dfe4f7c7f19ee,0x000c0f9ccd7eb847,0x0001019511788244,0x000c4838c54b2a98,0x0008b89d2d46944a,0x0000000000000001}, {0x000e02a1a1d2a70d,0x000b7d63b4d27dff,0x000ab61d5fa9a970,0x000d7730420f7a7f,0x00079f4479996041,0x0001189500cc1597,0x000981b342dd1a18,0x000b0c87b154435a,0x000fe5a645fb9438,0x000a1ab34fb7fc43,0x0000000000000001}}, {{0x000f438f4b100160,0x000f22d13ff0c314,0x000d55796ecb8e45,0x0000ab873dd2e2bb,0x000789eb71d33f83,0x0003167e0b14a364,0x00002c246513aa48,0x000b03e86d3a7935,0x000b2db2bb0fe98c,0x0000d70404a0ec4e,0x0000000000000001}, {0x0004384c5c6b60bc,0x0002570cd19a5c8f,0x0001c33b468c19b3,0x000cbac39210942f,0x0007d36048a2a29c,0x000f69ef5fd4ffa9,0x000ece5cd6b0a674,0x000b1322973982d0,0x0001493bd4bce1b8,0x00083d4d6596bf49,0x0000000000000001}}, }, {/* digit=24 [{1,2,3,..,}]*([2^96]*G) */ {{0x0000db5e813acae0,0x0005831117f6d456,0x0001106059c8e19b,0x000f908ce8232c57,0x00092d0f09782c78,0x000bd0fcb64a24aa,0x00077e3d766becf8,0x000f155f53d2f599,0x000389ae2fa9a727,0x000920ff877e9249,0x0000000000000001}, {0x00085d510d2d4458,0x000dc73b4e520499,0x000aa68342be4788,0x0004f89c8a0ca8e6,0x000e8668748927b1,0x00017375ddf19eb3,0x00041d15e5f8b7ce,0x00052912af54652a,0x000b9a777a86a727,0x00003bbaf706d85a,0x0000000000000001}}, {{0x00017d39542a7b35,0x000d6953d2cbb145,0x00044a3ef5b5b733,0x00076565472126ff,0x000b2a4a1334dee0,0x0002573d17b26c37,0x0002c7ab5b295171,0x0008d328148c129c,0x000907f5aa2c72b0,0x00018b1d10e10308,0x0000000000000001}, {0x000159666154b57d,0x0005dd9359d8885e,0x0000281b6f14827d,0x0009bc4ba475f3a4,0x000c32eef44696b1,0x00082b50dbdc6dfb,0x000236a9ef4383e7,0x000fd73208450583,0x000d190b07767db3,0x0003153c0278a00d,0x0000000000000000}}, {{0x000ba905f5456251,0x0008ee5b3d8d39c0,0x000ea2a0a4462a26,0x000032f3094457cb,0x0009bab36ceff80f,0x0001b0fdf3879073,0x0009dc840209bce2,0x000df0c1c8e03824,0x000c51d81213ecb4,0x00063c2b025e0d70,0x0000000000000001}, {0x0003bb32c4b899f8,0x000ccb798bfbf249,0x00028838277f622f,0x000e5b67c2594827,0x0003c2c07c4dd5cb,0x000c19526a2c4c70,0x0000177dcd0df4c1,0x000457a743a1ed39,0x00032bea63a4c527,0x00075d1c302e78ac,0x0000000000000000}}, {{0x000fc5003828ff0b,0x000436a9841f4323,0x000c6f35f8a62407,0x0009286efc260a1f,0x000fbe74c4b2df5e,0x000cb3568b504bfa,0x000dbcf3548e5047,0x0005d92aaad71af9,0x00018241085e423c,0x0004f894d1d8842d,0x0000000000000001}, {0x00075b2a3f29b75d,0x000ec555f7834899,0x00092b31a410939e,0x000b7bc223255263,0x000db65a25c264a1,0x0008fc1aed283464,0x0005c70ecd1a9b70,0x000d90a7a2a0ea33,0x000d21f2e9f14ffd,0x000fb49566dadd7f,0x0000000000000000}}, {{0x000fa5757545376f,0x000ae164cbfd55ff,0x0008a8545451f1c3,0x0002e007d0be9705,0x000ed2a8f4c49727,0x00097ed736254138,0x000516215e864c7c,0x000bb624fc1b83df,0x0000313aaf4114fd,0x000a7a8c7f0423cc,0x0000000000000000}, {0x000ed76abc8d276d,0x000bfe3e74f599a4,0x00025d1f92d8b381,0x0005a3599e406956,0x00071869bdf5e06a,0x000ec86f625afaf6,0x000d724bbcc12cda,0x0003da7516890dd1,0x0009b69252163060,0x0002541f15a18b40,0x0000000000000001}}, {{0x000e1c4e632e5d61,0x0002987ad659b7d5,0x0003f7f338de2f2a,0x000b55a5aaeb06f1,0x000b9a60e84f26d9,0x000d10563130c6f8,0x000e760d017d58e9,0x00039e20b973fa41,0x0000eaafdb2f4acf,0x000501ec9c6ab584,0x0000000000000000}, {0x000f4549ba5a6302,0x000a98b140b89722,0x0003e099225c2510,0x000f31b19117bbe6,0x00046ba7147bd18a,0x0000f540e368bb5c,0x000eacf29d33114f,0x0007e59588a01c9a,0x000ef0e25eb2d0e6,0x00058e4bb1b8d029,0x0000000000000001}}, {{0x00057915cb5440b5,0x00088e89a3e1eb04,0x000ed12c670e08cc,0x000eab1d89133ab9,0x000f615d9bc0c1fa,0x00081504d63c4250,0x00062cd084c8e8f8,0x000aaf76dbe53ead,0x000bf1dcc49cfac6,0x000fc7007ea0b885,0x0000000000000001}, {0x000472352fc50515,0x000fa2123835c747,0x00067bab29e80692,0x000cca008379c2a8,0x000799065aafbc2e,0x000a605d2e32da97,0x0002283421bbbfbd,0x000dbdc2e1151243,0x0007a9d899c126b9,0x0007467ce3f8d643,0x0000000000000000}}, {{0x00000c97f4a1ee70,0x0000a55fa6cdb3e0,0x000fd5fcd60595ed,0x000522bda02a23c6,0x0000361844a1d76e,0x000c6c179ebaf8c0,0x000a6ccd0a47af40,0x000071e2a1156aa1,0x000a1b0fc4eb0062,0x000bb4c1c5314a2c,0x0000000000000000}, {0x000c048376702b16,0x0002ef5b4e8123cd,0x000a7d67834242a3,0x0003bc3accb0fead,0x00007e65ed32fc2a,0x000b8b44e6e71194,0x00077e9aeb1712aa,0x000039ce4f895a59,0x0009d43ed708cfeb,0x0004254957cd1ca1,0x0000000000000001}}, }, {/* digit=25 [{1,2,3,..,}]*([2^100]*G) */ {{0x0009a3fb62f03e91,0x000fc3cfe3b9a1c2,0x0008c5a528bca033,0x00096cd7b4bc3e3f,0x0008c4bd134e2233,0x00065224c739c3eb,0x00071ec25548c0a5,0x0007b0fb17f6f014,0x000aee1015fc6579,0x000448c4d69b6d18,0x0000000000000001}, {0x00074be708f600f9,0x000042a14b550a00,0x000f8e6b95a52425,0x0004e9813f438c42,0x0005181004aa1017,0x00010cd9a834ae43,0x0002105b1b67e295,0x000141438bad8cdf,0x0004d11308ec5ba9,0x00034300e8c08dc6,0x0000000000000000}}, {{0x000625d111480c24,0x00034cdcf3505fb2,0x000c306874b99629,0x00004410981e8fcd,0x000492bd0a650027,0x000a534a84249eb3,0x000e1326b6bb40b6,0x000ebe5d29140c32,0x0009956b2cb2ca52,0x000b8c77c7225102,0x0000000000000001}, {0x0002b4e077c5c4dd,0x0008846314442efe,0x00066618e794431d,0x000a933fcd3eeea2,0x00006644159656a5,0x00022dc52fbda24f,0x000542f82f45dda5,0x000e0e5075c9d412,0x0002aba0fff34a66,0x000d69512c4a1d9a,0x0000000000000001}}, {{0x000dc5b949f6aa55,0x000cb79872016ba3,0x0001df5e18d2889c,0x000aebf5e0129254,0x0003a4cd20b4cdbc,0x000f30108963d6c3,0x000c0dbc46a1dad1,0x00042c0e39b6755f,0x00007fa126ef9e69,0x000805d500d36fac,0x0000000000000000}, {0x0000b5e7bd19e5fb,0x000b3765e8dbbff9,0x000e491cc2deb8ec,0x000ab995d314c068,0x000b4e810513ad31,0x000b50dc0fcca181,0x00029580c1e05269,0x0006b6453c858930,0x0009a98b2de5a7d2,0x000b386f7a77183c,0x0000000000000000}}, {{0x000d861fc542368a,0x000a737b3c184cd7,0x00014a6e3b95c425,0x000f514e85d4a651,0x00098b665bb45532,0x00066a39b08b87e5,0x00008dbdbcbbabba,0x000ba64b561fa462,0x0005692509520864,0x000281de8b31e205,0x0000000000000001}, {0x0001bb6a74473c21,0x000932e76a8c5ddd,0x000c6ee633cc0f66,0x000f68d0c546bb80,0x00006828f4e0c911,0x000b2a4276c213a2,0x0008cb204a16b2ce,0x000d38c09aa1cbe9,0x000f3ebeebcc1671,0x00032c7a684ba9a6,0x0000000000000000}}, {{0x000a3463989cd762,0x00035114b160b22c,0x00057f2d520e3cc4,0x0000ff788707011b,0x00068b1a346a61d3,0x00084618b8d69eda,0x00020c04008115fa,0x000dfeeecaa806f5,0x0007e08436a14e30,0x00005f68bc839ccc,0x0000000000000000}, {0x000ae58e3c998f3f,0x000951d35d5af6b3,0x00038625415f29bb,0x000fd087552cd755,0x0002087ef7e8ab49,0x0006b067b5de9ebd,0x0001e74110309c17,0x0007b224505a1ece,0x000ba962991a5a2d,0x000b8879263dad03,0x0000000000000000}}, {{0x0001b7e0189fcda6,0x0008775ba885f2a7,0x000b98305b9915b6,0x00019b2753769a90,0x000638d87ac0d10c,0x00083c77c18f7acf,0x000d23964d02af25,0x000de5be92026e04,0x0005a30998f85294,0x0002d2bb22f8803a,0x0000000000000001}, {0x0000daae09876e93,0x0007b9f1b9b10415,0x000e48eb13c50096,0x000cf9ccec3e5c4d,0x000f7b6158629895,0x000aa201ea7d90f3,0x0006e88c0cda29f8,0x000f4c0d70150c9a,0x000ee70bc97d1c62,0x000b8e4fd0f68d56,0x0000000000000000}}, {{0x0003edbb844d6c8a,0x00076a792ccd3b41,0x00072527a7c1564f,0x00055b682778d6f2,0x0002167ba3cee45b,0x000d96d43a6e138f,0x000806538c932f15,0x000d4892afee6363,0x0002b82f06ed7c45,0x000fee287b4614b8,0x0000000000000000}, {0x000953f4fc1bb9d4,0x000e995150d18cb0,0x00067e23c2e107a5,0x000bfba071a733f6,0x00008ca46066c2e8,0x000cfb49871d6c61,0x0004ece39bb5a648,0x00040cf34f514816,0x0009b9250336996f,0x000c69d6e08146e9,0x0000000000000001}}, {{0x00008e517921a752,0x000ab87a6c13d140,0x000c4597b07c5d69,0x00074a68c66db12e,0x00019ca40dec9dbd,0x000a617fff4579d7,0x0005876131725395,0x000d09e3b946e383,0x000d20c852478942,0x00087982ecbef742,0x0000000000000001}, {0x000589886da1602b,0x000c3fc9ae2bbd5f,0x0002126ee978ba22,0x00075595e212b5ab,0x000a2389b739eff8,0x00063595af9d6707,0x0000f9787d12dd72,0x0003b014c3309267,0x0002f506a0067880,0x000f67060764da69,0x0000000000000000}}, }, {/* digit=26 [{1,2,3,..,}]*([2^104]*G) */ {{0x000365108b90f9d0,0x000f80765f67fb1e,0x000b1b38d141aae9,0x00024d697a9407e4,0x0003f9693e7ccc84,0x000a50e7d291d93e,0x000cd34385c13c5b,0x00066fcf73c9d94e,0x000598f4a80eb0bb,0x000b721c4d4c290d,0x0000000000000001}, {0x0000fb9a3bbeb3c7,0x0007ba326d546e3b,0x000a848cf094c6d2,0x0000e41609d2dc18,0x000266f0069ca46c,0x000c4aef799231b9,0x000abacbdbead081,0x000b272ba1959d4d,0x00049b7208e216ce,0x0002ba83cc03eccc,0x0000000000000001}}, {{0x0004c0998b5250d8,0x000c867c43b599d6,0x0004c9f6ac785a2e,0x0004ec8b59f29f0d,0x0004df16ae8c0faa,0x000b8d8f78201760,0x000bc38bb59089da,0x0007384039822772,0x000d1571c6e88e81,0x000a7b7d4e8e0cf3,0x0000000000000001}, {0x0007bc572ea0f919,0x00064539b5eb1047,0x00077d71bc88d22a,0x0004dc62d769223e,0x000adfe2b562c973,0x000173fab241cdb0,0x000603370ddf3ff3,0x000f70dbbbbd997d,0x0008a88a56d59561,0x0004be64aafc3299,0x0000000000000000}}, {{0x00045d30a00d827f,0x0006bbe20955e997,0x000cead0ee1643eb,0x000fce2db7c5ac6f,0x000ad1d2efb30bc2,0x000d9fbc667affb8,0x000bb6fb3983d3ef,0x000f70a834538091,0x0008384fd172dade,0x0003f32390fa3030,0x0000000000000000}, {0x00022aae53d2000c,0x000caf0273baad84,0x0004a6a878c712a8,0x00002615beecdb4d,0x000b0e868dba85ad,0x000964d03b5c6537,0x000cbcf8b6d0fd98,0x0006a16ca9f74a32,0x000552ffb8c5dbeb,0x000bf0f20d682f2c,0x0000000000000000}}, {{0x0009a64c8deb9f4b,0x000532674c0fe944,0x00001e88fe681603,0x000b8697595c6e13,0x0008cf6f513d4913,0x0008c1e3203b6d47,0x000b68db28573518,0x000bdfb9fd4390cf,0x0006601496c4bb93,0x0000633f388af7cc,0x0000000000000001}, {0x0005258fb2317523,0x00040dacae0a8b9a,0x000ba0560abb741a,0x0008bc6a795d005e,0x00096caa47999397,0x000ff04fef1c0b24,0x000b0926ddcefe71,0x0008f281ff3947c3,0x000027cc7cc93f3d,0x000e78773c9a3f23,0x0000000000000000}}, {{0x0001c60cc85e7257,0x00011fa52f42f768,0x0002f380ec8fe41b,0x0004893bc07fb9d3,0x00034451f49fbf7a,0x000388023d1b4705,0x00079c42053de8b9,0x000cf909c04d42cb,0x000eca57f6797b3a,0x000cf34d35027c43,0x0000000000000001}, {0x00086008351763ff,0x000f9e1103300427,0x000991707dcb32e9,0x000efb21a41fbb4f,0x000b5649d55978db,0x00004e4d7b3fa6d3,0x00012196968dee3a,0x0003561c60989b74,0x0009c91c53ee540c,0x000b9823a2ee0db7,0x0000000000000000}}, {{0x000f6a15601d1f8d,0x000406c4591dc921,0x000b36c8aaaf7c15,0x000834fd3b0d0813,0x000e544ef9e76287,0x0002fb609294a18c,0x00008d9bd0198775,0x000cd4816092b24d,0x0008b097d39d2d32,0x000b3a5b9f00f218,0x0000000000000000}, {0x000da9d6f0979e9d,0x00080741dad104cc,0x0004ee619b7637d2,0x000d71560f5a9cc8,0x000b897bb554b4f3,0x000890a210367054,0x000aff63f1f61c3e,0x000cb92963c20784,0x0009317afc9acc43,0x0005c1dadb0d3e30,0x0000000000000001}}, {{0x0004debc7af95096,0x0002bf8bc26e7cbc,0x000070bd1c43e146,0x00017181a62e8acb,0x0001c46b5339f3b4,0x000a2c14c9b646ef,0x0005de576b9f4c81,0x0004f9a155e97645,0x0003cfbba219f7e3,0x0009fb1fd4f92031,0x0000000000000001}, {0x000bcf11449769d9,0x000ea5acc7cb996d,0x0006bdb653213f43,0x0003a2cf9c396c5f,0x000777fb3075bc28,0x0009fab46fa97f51,0x000d80cd600dc1e5,0x0008ba6a57a9d490,0x000c9975b8111175,0x00067a2ad8270658,0x0000000000000000}}, {{0x0005e67b8d52ab83,0x000eb2049665d86d,0x000b56e1ced19993,0x0009c1fc7a62ba87,0x000276fc5cf75dfb,0x00054f5dad4712b6,0x00089fbe0548bd15,0x000d1ee24125ecba,0x000176a53fa18f5a,0x0004e18796b5267e,0x0000000000000000}, {0x000a0f1a17a9eb45,0x000584e4e5f968ad,0x0008e12a3e089107,0x0009c73cd6a2ba69,0x00002e23b2a1f1ee,0x00028e9adc43a76e,0x00062c6e3d7526f4,0x000d0557ab8af09d,0x00058b1d337cd537,0x000000e54434b827,0x0000000000000000}}, }, {/* digit=27 [{1,2,3,..,}]*([2^108]*G) */ {{0x00036c3a6abc7042,0x00004a11953f80fe,0x0000b4cc57cd15f7,0x000df44d3d3a8bb5,0x00015b5099398347,0x00081f3a553789e2,0x000d0115f2bce30d,0x00090b7f91f0853e,0x0007ec29320d53ac,0x00085b63e7bfbe8d,0x0000000000000000}, {0x000cdcd80232c6da,0x000d8fc636cf5e56,0x0006e4c3d9621241,0x000b84a86812f9d5,0x000287741d3de81f,0x000ab3d77eb50a79,0x00048627cc80386b,0x000a1901afee8f37,0x00095591fbf5ceb2,0x00080aed0c8140dd,0x0000000000000000}}, {{0x0002fcdd07efc38c,0x000c9ad8b1dbd166,0x000af6b6e1566c06,0x0005c4ad28998a9b,0x000b12d2005dbca4,0x00009acb17fcd947,0x000af2e6bf7b35f6,0x0000b8a8aba325eb,0x000302e3f599df52,0x00080d2bf9b973e4,0x0000000000000001}, {0x000aebd112a3c0c1,0x000c408868630c25,0x000af7c4f6ba5529,0x000d49e0f5657b1a,0x000da3fa70b84c0f,0x0009f530044d86ec,0x0003f7ec59dce6d3,0x0004bdaf73433951,0x00022dd61822c292,0x000466acb0786ece,0x0000000000000000}}, {{0x000bab3d6168fc90,0x0007cbb6b2be9857,0x0001cf2ccb017656,0x0001630304c6ccfa,0x000ab9344dbdd28a,0x00075f0fec3093b4,0x000ff2494e7a4029,0x000ca3bad1c9c568,0x000b17aa4b7bc2e4,0x0001be8844e06c12,0x0000000000000001}, {0x000748f359f51efa,0x0006b016fa4643bf,0x000de784a5c3f1e9,0x0006412db1ab3996,0x0002a042b01eeae2,0x0005a0d3a2a424ea,0x0009b9a7aeefe348,0x000b209614c9d52b,0x000556ff1e6afd00,0x0001e2290dec8fe5,0x0000000000000000}}, {{0x000dedb27f20e8c4,0x000f535a0fc33855,0x000788ccd8803e8a,0x0001f7d6e10cabd0,0x000355f889d7fa1f,0x000583e3030487ee,0x000f3dd1885d800a,0x000f09ae9a4a2fc9,0x00054fc302887b5b,0x000678d91181d3a5,0x0000000000000001}, {0x000b146d6cdca631,0x00046652f280d553,0x000e0b73d63dfaac,0x000399cd0d77869d,0x00057ba5ffe6aa8a,0x000ffc1da65c61b7,0x000738771cf6c9ea,0x000620ae124834d2,0x0006504def184b95,0x000d761c974cb47f,0x0000000000000000}}, {{0x000b12824a32cfa1,0x0009c552049f6e5b,0x0002cf47aab27c7f,0x000c49affe61e35a,0x0002247309f28abd,0x000d8f5d3d157087,0x000c6b864fe18c22,0x000addbbfad216e7,0x0006e83c0b6f0f26,0x000fd5df730de2cf,0x0000000000000000}, {0x000d5ed49aa6d720,0x0003b8bf56601c9e,0x000932a05f265897,0x000b6e7997e501b5,0x000a12ea7ac82871,0x0009ee973ffc91a5,0x0008bc4a89b5c6c1,0x0003ff7cc4ea3cde,0x000dd04f7b689969,0x000d1dbe61024f53,0x0000000000000001}}, {{0x0009c8cbe80fbbcf,0x0001820704f59919,0x000a2837d2432345,0x0001d7c57c052221,0x0004dd7abcf6f7fc,0x000ceb0c9ac384fa,0x000cbcbae19fcf70,0x00044465c2e5cd22,0x000a11ffc8ca98c5,0x0007b72231b3018f,0x0000000000000001}, {0x0005516f6500002e,0x00015b8dc7f05ee2,0x000111229aa6356e,0x0006bd0e54525c30,0x000dcfc5ecb4c0df,0x000355785f844693,0x000ab74792af79c9,0x0007357c34213765,0x00008a7b5867734f,0x00069a6d820a3083,0x0000000000000000}}, {{0x000b3a34b0a583e8,0x0004109d1c2a05b3,0x00056d185c8227f4,0x000c30eb0f8b309e,0x000e5f0d836e7213,0x0002fdae4ffef15c,0x000257bcdd2d7309,0x000dad1ff9a8d757,0x00098efcc192b734,0x000fe0e5b46f1d9f,0x0000000000000001}, {0x000ec3057c0b1268,0x000e1eea4fea07c8,0x000ac5ab201c4cbc,0x0001b75086654bcd,0x000e612c2aee9474,0x00065fa077070bf8,0x00015dd97afeaab6,0x00088802f9979ef0,0x000c9b3109eb556d,0x000e513d135fae08,0x0000000000000000}}, {{0x0009b9b53c1efab4,0x000babd37156ff65,0x000a115d2c7f8338,0x0007371c9d1175b5,0x000a353c22d6aa92,0x00079ee37be5b07d,0x00020293585421cb,0x000abe2b0a938ac9,0x0003622f3d489e47,0x000ac9ccd5811b36,0x0000000000000000}, {0x000cb54f0f506ac3,0x000feebf83fb7441,0x0007d9fa2d5527b4,0x000b40376d4a3597,0x00045e4619c87f8a,0x000b913b27d590e9,0x0001da0e8861075a,0x000dd8fb707f389b,0x000140b6fe0beb49,0x000bf7392dd17235,0x0000000000000001}}, }, {/* digit=28 [{1,2,3,..,}]*([2^112]*G) */ {{0x00082a01cdf12457,0x000bf550e3442670,0x00027cfd7b191616,0x0009bf54426bd9ae,0x000375f468d0ec29,0x00095e63540487ca,0x000f558b93aa7dc6,0x00028f48edec9322,0x0007ee742818f059,0x000d23aca5b08895,0x0000000000000001}, {0x00018972085008e4,0x0009e445a0130711,0x0005bf246e5348cb,0x0008ccf1f5c183c6,0x000f2e9a40aeb3fd,0x00087abdef0fbda6,0x00050f5daf09cee0,0x0003e33344ee90c4,0x0004044243abe107,0x000b8f02a065d1a3,0x0000000000000000}}, {{0x000b66d418145236,0x0007896ea70c3fff,0x000cb17d54fc5491,0x00042a641eaf6e4d,0x00096b15be10c7c6,0x00011efe5f993282,0x000c04930829e9c6,0x000a5f18e8613cde,0x0007985a51a7c38d,0x000b8f3536d908ab,0x0000000000000001}, {0x000ce50b447f989e,0x0006725435f6e48e,0x00060505d7413d04,0x00051fa907efc4e5,0x00091cc601ad28a5,0x000eeaf4b18fed33,0x0002e1a4338a8549,0x000b61868d3372c5,0x0003a511bce70bb6,0x000e1f5c8d75eb9c,0x0000000000000000}}, {{0x000d68d2a3e7e05d,0x0009bf6f65a63322,0x000368db479d7794,0x000e22f5738f46ed,0x000947212d465e52,0x000bb783e24758d1,0x0009d33d677a59c8,0x0005609046041b23,0x000f6497a9c2f277,0x000e7a9be5339a8d,0x0000000000000001}, {0x000804d780847503,0x000fb6bd5cd190b5,0x000d58769b6bfbeb,0x000a5b2366d25685,0x00084206ac283f9e,0x00045e93a909d14a,0x0007818e03b612f8,0x0005061fa312c680,0x000501efdeb98070,0x00043cfa3670b66b,0x0000000000000000}}, {{0x0008296f30c9bed5,0x00099a4bb11c1f32,0x00015b4084960501,0x000c50ce53a7ca7c,0x000f50a2c1da281b,0x0002c0e34f682873,0x000f21f441021705,0x000e9f354fbc9c5e,0x000d7990a0bba954,0x000ca402432a326c,0x0000000000000001}, {0x000e6dddd976d76d,0x000a57e55cac7b2b,0x000da37392c8a3b8,0x000fecd4ec1dc93e,0x00009cf4f78c92e3,0x000ff689fefedf3f,0x000abd5033740521,0x0000df4087ca092d,0x00002763eb9e4e11,0x000689f3f329b79d,0x0000000000000000}}, {{0x000d09236f94e981,0x000f3b87c2492089,0x000090559806590f,0x0006b638cb962e83,0x00043caf0b4cf40f,0x00066f61c7a2faca,0x000edaa5c1d246d3,0x000b19d9f9d7b0bc,0x000d3b97c04cafce,0x000f23bf9f27399e,0x0000000000000000}, {0x000b2a804eb31689,0x0009a2a7437938a7,0x000f3c9cd990c2d5,0x000b68b7f843ec1e,0x0005141dcc07de04,0x000fdd1e7d56eecb,0x000a099220b61db4,0x0004184b463b9f76,0x00076a6a6fd2bcb4,0x00067d87f98ad9c6,0x0000000000000000}}, {{0x00025736286ff497,0x0002401f1271e328,0x000981dcd7607683,0x000cfb7ab6548084,0x000df4da03d9c990,0x000d822ebf4ae8a1,0x00099db5f23d4a99,0x000f6315e3fb9894,0x000021f262e80d80,0x00027457b91d5ecd,0x0000000000000000}, {0x0007a0ed90d98205,0x000cf6f6b6c517c8,0x00057c5ae11bc6b8,0x00000efaef845be3,0x0005e74813e365be,0x000c8e0106700aae,0x000d776c99ef5ca6,0x0001e3d37bff71e1,0x0003a89779b96572,0x000c15ea2a31bd25,0x0000000000000000}}, {{0x0000092959940ede,0x000bb4c7bf2ceef4,0x000d604555c30636,0x0003fe5635d8d5c1,0x0008cdef0cb902ce,0x000b6f22235732b0,0x000fddf6f7cfc6cb,0x000369004df1a446,0x0004ba65bcff1dc7,0x00020adfd4756b77,0x0000000000000001}, {0x000afeaa9dfdfa89,0x0000b80d92606c1c,0x0006888e19c65eb3,0x000bf9bb4db51900,0x0008e84280b5d191,0x00077a1cb4c3d007,0x00055fc83156ea4d,0x0009f40279edea0b,0x000aa5223480bee2,0x000f264b4f70afa9,0x0000000000000001}}, {{0x00054382d016c8d9,0x000ec7826f7b17bd,0x000dce64f2832c36,0x000193ae22a16680,0x0000aaf6a85c2ab2,0x000f20270252cc0a,0x000f317cc1335b32,0x00003743776e2afb,0x000a199000deb474,0x0006bc61591f25f9,0x0000000000000001}, {0x00084eebf2800729,0x000608b06a4eb61d,0x000b23e73968bb72,0x000a3ae82e886104,0x000d27c8605d2992,0x00033bec6e418a91,0x00029d45f2b49e6e,0x000bd1f4a3f4a9d8,0x000bc4ceaeb2f044,0x000c63b1ef09fa28,0x0000000000000001}}, }, {/* digit=29 [{1,2,3,..,}]*([2^116]*G) */ {{0x000826845611f97e,0x00015b6b1ee54a04,0x000608b1dc092400,0x0009050925698b8a,0x00031b5e532ada13,0x0000c41c46df4acb,0x00090c116e05bee3,0x0009642c127307d1,0x000365a48b566eca,0x00046d5c3cffa21b,0x0000000000000000}, {0x000b8836b9754189,0x00079ea005768621,0x0007bf51510520f5,0x000bbc0ca43d38cb,0x000c9fe21891a0a4,0x000242b093687446,0x0006d618feab8811,0x00047a921f31cacb,0x000cb09d3cf611aa,0x0007d8fef9a8efc5,0x0000000000000001}}, {{0x00042c81af50749b,0x00081540e019366d,0x000d6072e7b7487e,0x0004156c32da913c,0x0003df1e87478e7b,0x000880f5ccb21742,0x0002347ca344dd54,0x000d15da2c269018,0x000993e2887d2337,0x000379604cc23f8d,0x0000000000000001}, {0x000778d40c2ec9c0,0x00027ec9dd1808f9,0x000dcd7b63f43450,0x000cf65f198a63ab,0x000d3a7a4c38803b,0x000476f99f1130c2,0x000d6b9c1ea5019b,0x00034f67377e991a,0x0009047dfa9f5ad1,0x0005dc80641e2fd9,0x0000000000000001}}, {{0x000de0d9dfa7af75,0x000eba7ea5710283,0x000dd5435234652c,0x0006f821b8a36856,0x000c319e00261b58,0x000ed079e56ce309,0x0001099e0f75ac31,0x000e2442020d51ff,0x0008b83fa0c077ae,0x000e6fc85e1f8724,0x0000000000000001}, {0x000872b798445d10,0x00032b311d3108af,0x0005040c97d2ca2a,0x0005703d4fa4c2f0,0x0006980d5eb27761,0x0005f074a536c8c1,0x000181395daa1e3b,0x000b672dad89bda9,0x0001f3d94395bd4f,0x0004b4c4a2c81ef6,0x0000000000000001}}, {{0x000924e7856ff846,0x000ee4f61f664ccb,0x0005ac67cb02e404,0x00050da76b002de5,0x000c4537e3c3c875,0x000c36c052b6b43f,0x000b204b2d5ce01c,0x00088e7f6d0e0c5b,0x000c188bbf930fde,0x000168056f87d909,0x0000000000000001}, {0x0001106b668bd3a0,0x0008dce76203aabd,0x00002fff3110182e,0x000f7d1e1307d3fa,0x000347101339296b,0x0004a22e456ed2ca,0x0002d011b668eed2,0x000b79cf95e5e410,0x0006693b0681d10c,0x000355f94e08ac6c,0x0000000000000000}}, {{0x000323242b9413a5,0x000d8925b57cdbcc,0x0004d31e6960afac,0x000cc1c8075e88b1,0x0003a4d853d5880e,0x000c2d17b4e21339,0x000c35a1d02b3405,0x000f7f4eb22a29f6,0x0001b6570763f945,0x00008a38d9e91699,0x0000000000000000}, {0x0009e262a8faf74b,0x000d89cdb707d091,0x000c28362e27b3cc,0x0000a8d2e31adec3,0x0004f2e5340b0d97,0x00076d44ac11f1ff,0x000ddee42bd388ab,0x00052165e718528c,0x000c2384a7cb055f,0x000e3bd81cae87a8,0x0000000000000000}}, {{0x000e0ef29067ec5b,0x000b3efb1759268e,0x00093d33d241c82d,0x0005ebc6b912da50,0x00004cea7d557bb1,0x000a95c0c2531329,0x000338d1728bce52,0x00023e934774d703,0x000bdaa179ff6232,0x0009c05a25267ea4,0x0000000000000000}, {0x000b3f1bf490cbf7,0x000ec049cf21d24d,0x0001567c730a18c0,0x0008c3e0f359d391,0x0004ea1bf7eca8f7,0x000252d4d89f9aa6,0x0007a2e5b2ffd6d4,0x000e70d5197d3cf7,0x000ac046e420f1fd,0x000f82fbaabfd6c4,0x0000000000000000}}, {{0x00023d833bf81b28,0x000064787960d20f,0x0001e23da2c1a82d,0x000fca0df31fd1ab,0x0000d67beaa32632,0x0009e45d2648f548,0x000d563bb162f9bb,0x000110e02089d434,0x0007082d3a10eef0,0x000cb7b7735d1d64,0x0000000000000000}, {0x000d95b89701e6ec,0x0003bbe61d29d940,0x0001c7d5b4e68b4d,0x00012a5ad78df4bc,0x00047d83302cabd6,0x00011140b2809827,0x000211a754f62795,0x00041d43610e16e7,0x00099e665f0dec95,0x000ee6baca9f0f39,0x0000000000000001}}, {{0x000657257b2d9252,0x000915208861aaee,0x0008adfc02b5d4bf,0x000f78398b2a8792,0x0002cd1929e3951b,0x0001878fc66ac2d8,0x000a1972453f26a5,0x000c0ebd963c67c6,0x0006feb8829e6f9c,0x000c986a8aecc7ab,0x0000000000000000}, {0x00030636d8df74f1,0x00011de6a5beb09f,0x000247b37675f6af,0x0003d122a04301fc,0x0003f577167d7789,0x000a69addd4d974f,0x000f8be983fc60de,0x0003627055a8d35b,0x000c83aaf95c80a8,0x000a9aa21f06b151,0x0000000000000000}}, }, {/* digit=30 [{1,2,3,..,}]*([2^120]*G) */ {{0x000c1e136664d27c,0x000e853cf04eac1d,0x000599f98901c4f5,0x000f0e3ecbc44867,0x000ee5a12a7f834f,0x000066c152851c12,0x0002df97ca61be6f,0x00027153da2c7383,0x0003e882e14acdbe,0x00030b87567338b7,0x0000000000000001}, {0x000fe8148de5b00a,0x0003a405fd56d3d1,0x000e986a7db49ee5,0x000cf7bc11101981,0x000a9750760e2695,0x000815cb90b6aca2,0x0009f299f5ace2a4,0x000d6b06b61bc3dc,0x0002e5c223b28698,0x000c0b5687880a6b,0x0000000000000001}}, {{0x000f552c0e5d59cd,0x00029aaaadcddf1a,0x000f071e91a160c3,0x000bbaf777f33e93,0x000696e836178f9c,0x00030ecc6d74f3bc,0x0002571349ec6474,0x000dbbec63ff9e68,0x000eff8b43f624e0,0x0008000d19e23a64,0x0000000000000000}, {0x00060d53484cb54f,0x0000d83eff3832ce,0x00012f600dae89d0,0x00089d2df8745dbd,0x0008a48217cd83eb,0x0005ce0f8ae79b86,0x0004021c2c4ae44c,0x000ea980ca2b0fe9,0x0004146745ab9482,0x0001c2cffa33fcf0,0x0000000000000001}}, {{0x00076fd51fd99bf9,0x0007e3a2b01fa7b1,0x0001a17875cbebf2,0x0008df20ca98073a,0x0001c738732531a0,0x000c360b05cea958,0x0008986bad316bfd,0x00009591db5fb8a6,0x0008ce8516941db2,0x000cd50df495ad83,0x0000000000000001}, {0x000d46b24a5b2933,0x000a4af0d09b27b5,0x000e34ef392f2b04,0x00028d0cc4e0cb50,0x0005bbe1270619c0,0x00002d927660b899,0x000c444a9beaf922,0x0003686effea3a61,0x000321e427cc238c,0x000fe609075147ce,0x0000000000000000}}, {{0x000e9dd164c62b53,0x0001878a3599a216,0x0000821091d05317,0x0002cda324ef2697,0x000e94950f2f16ed,0x000815b553eaefd2,0x000f8019f00612dc,0x0001930eacc547c1,0x0006fc4a1fd1730a,0x000db88252d52d13,0x0000000000000001}, {0x00077522a6c4bee6,0x0006b12deb38426b,0x000ca869197aea9f,0x000c43193823d16a,0x00028f12c9d38187,0x00031f43dad5cc98,0x000728a436529c3e,0x000863d40c6f0781,0x000da1798bfbb097,0x0001e17a19693394,0x0000000000000001}}, {{0x000a20633820f8b6,0x0008884ce6057395,0x000b9e9ac4298b05,0x000f80c79f28e7bc,0x00012abb15751770,0x000ce75763d01472,0x000afbe67296f82c,0x0002a2950d9f8034,0x00031ca6f1179141,0x0008bb87c616f997,0x0000000000000001}, {0x000f27dc8004bd5d,0x0004fc5fa5d017c7,0x0009fdb4deb95bcc,0x00051c1e39917e40,0x000cfbefa777d300,0x0006ebd51f3f36df,0x000089ed9696a852,0x000c58a6c0bc16cc,0x00093efb56723f03,0x000f77e4f7a67531,0x0000000000000001}}, {{0x00082edbf63cd0fa,0x000fb67ff0d41a00,0x00076aa53cf1522f,0x00099dda453dcda7,0x000bf634bcd8a3ac,0x000f09af12ca31a6,0x00045d3da6aee65d,0x0000b2e1c131b960,0x0001888166f3c7e7,0x000d21cb58f8b972,0x0000000000000001}, {0x000f3e0321dcdf91,0x0009a8d4da7b1151,0x000e3a95788cafbe,0x0007071e39c010af,0x0004b05cb3faf8c8,0x0008a702fbafcfc0,0x000618742c775b70,0x00068aab53d65b3b,0x000b27ffbb84f938,0x000a7508491b708b,0x0000000000000001}}, {{0x00020328d4b15dd1,0x000274b581eaa62f,0x0008fb2a285d269e,0x0006ea89604b1779,0x000933aa53ad75b2,0x000fa62691d5119e,0x00067e03e002a949,0x0000629215018ba1,0x000ae2796195dffb,0x000282dc1f93eae4,0x0000000000000001}, {0x0000977c61f7743f,0x0008f7654950f798,0x0009f0fcf77422ba,0x00070562b7dc1d4c,0x0008f0b2f76176b9,0x00094ad6c12de606,0x000d53dd34579508,0x0001fc63f78fe569,0x000a90b5214981ae,0x0005ab902dadf9f2,0x0000000000000000}}, {{0x00006fc86d7474a9,0x000491c759885f54,0x0002d4cddc55bd2a,0x00061045c35aa122,0x0007a2154985eb54,0x000f0dcbe4188b45,0x0006a7e235148dff,0x0006a2535a30d70c,0x000e2be337d8e901,0x000cf899a19ee96b,0x0000000000000001}, {0x000dc1860747030f,0x000a1d519771baa1,0x000e6bf7f8dea4c9,0x000b88d5c44825c6,0x0001648270d80fd4,0x000d7c088d619d7b,0x000e67f50ac4887c,0x0009d1ac72f9cc2c,0x000dce091aafa6b8,0x000ac9b9365de8af,0x0000000000000001}}, }, {/* digit=31 [{1,2,3,..,}]*([2^124]*G) */ {{0x000c9884018b1bd5,0x00017e335350476d,0x000f240ea34a105e,0x0007225c0ca7c1ed,0x0002e60ee9bcde0a,0x0001b7a04f8d5abc,0x000d636ed201196d,0x000fee08dcde421f,0x000648f1c3a41da5,0x00014b37a2b18a4d,0x0000000000000001}, {0x000574ca3d13216a,0x00000c8f4aa46ce2,0x0005e6cb8b142b50,0x000aeecc2cc007b3,0x0008b139d4602d18,0x000857b6e6fad62b,0x000703a0b8035154,0x00047dfe5be4aaf5,0x000e255f15b88d9b,0x000ceeb42f23b0c7,0x0000000000000001}}, {{0x00027bf41035c3be,0x000003d6c228d698,0x000ac8482db53bd6,0x000f6c6cedd6d84e,0x00055554b59c1199,0x000b3dd0d5c80a25,0x00098fd9a255d70b,0x00088ce8ece5b616,0x00010e4ff0160238,0x000e8b21f2b5b409,0x0000000000000001}, {0x0009be6e93956f12,0x00028be014bad7ba,0x0007941a6f1d6c8e,0x000374aa983d3be4,0x0001ab03efe8a93e,0x000ecc1517778750,0x000a07f3863f0102,0x00022339ade08ce1,0x0002e138fb118165,0x00037ded66083914,0x0000000000000000}}, {{0x000be450955d0f49,0x000350db3612b4e4,0x0008b05c6937d0f5,0x00091d0bc00589e9,0x000f08134602fbb3,0x00072898cb46a43b,0x0000c3f425983612,0x00092a9319d102b7,0x0002adb9889640c9,0x000f69984da61b9f,0x0000000000000000}, {0x000925b413e1ae3e,0x00046d808d55308e,0x0001e8e95f85495a,0x0001aa328926b87f,0x000e6f7c0b2cf48a,0x00097c234327b453,0x000bc1b584c452ac,0x000ac04a1db1b2a7,0x0002c2df96a4716f,0x0008b35f6c998afc,0x0000000000000001}}, {{0x000c246de542c405,0x00006abed2f33bb7,0x000d46decdec7b50,0x000afeed50c509c6,0x0007109502cf683e,0x000fa7b0916c8d21,0x000971ce284eb826,0x000b5478a9a06ef3,0x000dbb05d7e812b4,0x000fa9bdf3afd0be,0x0000000000000001}, {0x000c0e4a6519aab5,0x000d79de9fb97617,0x0002d46f889510f0,0x00025cb75085caf9,0x000f963379f4c576,0x00002dc4877679ee,0x000748161e8da062,0x0007933c7094d95a,0x000527ab96f198e7,0x0000a23cef9bb67e,0x0000000000000000}}, {{0x000254c4bef57a31,0x000f8fe05ebbca4c,0x000036d19011dab0,0x00092f09f97449f1,0x000feb784d8ec601,0x000551e5955591a4,0x00088c74b266204b,0x000fefa58c8cd4d4,0x000954c3d29f9c68,0x000262f04bf8acfc,0x0000000000000000}, {0x0005e5c9d99f906b,0x0005ebe8f2ee55b8,0x000f127eee6b4d59,0x0005b10ba97a057a,0x000c7680e692309f,0x0007c47d151a8543,0x000975bcc38cb298,0x00056b40037e7ed1,0x00069095953732ea,0x000e079710f9d766,0x0000000000000000}}, {{0x0007ef5561843b50,0x000725adb4b17e58,0x000223554b9e6db7,0x00040d6a298840a9,0x00089b9987d3e8ea,0x000c544359088f19,0x000712498c4e6798,0x0009d49555742687,0x000531911aeb4757,0x000c25edd6bd8c42,0x0000000000000000}, {0x000da2be384ee90b,0x000ed1578452ef17,0x00026ec7e64f3506,0x000d93fd400c530b,0x0006442c14bcb0a9,0x000bc44330eec280,0x000b7a321d894abd,0x000383284ca21784,0x000aabf2cbd2fe67,0x000a0b333a314bbd,0x0000000000000001}}, {{0x000deccb4cc0fcd3,0x0002b5d6f0d87e14,0x00022447f7757c4f,0x000f03b5e4d05426,0x0003dcf9d56f98d5,0x0001c6d571746b68,0x000648164a40c197,0x00086a775d32054f,0x000bbccdf9c7e93f,0x000ab95b370c616c,0x0000000000000000}, {0x000ad22f9be04193,0x00049e68cea75e3b,0x0004683245da929e,0x000316e38a93792f,0x000965e00dbe19e7,0x000e9c59fb61ef64,0x00094c5036fbab0d,0x0009e4c2c8f5993c,0x000c76d4a049b3bd,0x000c781dc2d523d7,0x0000000000000000}}, {{0x00010cba8003a62b,0x0002963dead37561,0x00024e572ee261b1,0x000924c14f710c53,0x0003a3234879da4d,0x0000242c6b2bb72d,0x00025965319d73bf,0x000c5d438ac356b7,0x000eb1ea69c1467e,0x0006ea40556d55e4,0x0000000000000000}, {0x0003bb0cfbfbdc6b,0x000292f755482f11,0x000b750229b1fdd8,0x0006dd9d36eb56b3,0x0009fd65055f0875,0x00005fbea1ad24bc,0x000b5ba29626eb13,0x0004c9855409fcec,0x000000d0af627326,0x000b249d561b2281,0x0000000000000001}}, }, {/* digit=32 [{1,2,3,..,}]*([2^128]*G) */ {{0x00097f8c2da756c3,0x00065716b51e78af,0x0004d4e4ac9bb4d7,0x000be63f12ece85a,0x0007f2c2556ca2a2,0x0002341b0c191c3b,0x00063796c15ecee1,0x00092e302dd7df66,0x000d162a4ce9cb82,0x0003dfa7f8ba9276,0x0000000000000000}, {0x000403973587aa55,0x000a9956dae839d8,0x000d9da7dcbd9d38,0x000d0fffb69b8acf,0x000544e0adb2ad93,0x000b2ad644f74f04,0x000e7d5b5de013bb,0x000f944ef674d489,0x000e01d0ea2d2bd3,0x0008aedd32d1ec0a,0x0000000000000000}}, {{0x0003c3743a6b3bf8,0x00083b2cea274d8e,0x000f6accb4a79b20,0x000ac9cff7eff159,0x000c5bd1a458b1a2,0x000af5afd8c30597,0x000e95f67ad0a34d,0x000ffcb5f547ad0c,0x0002c927ef492633,0x000118d70d201bd4,0x0000000000000000}, {0x00025271d14dfd7c,0x000f83511be77473,0x000e33f2540532d9,0x0002d9c50e1e6624,0x000b9f8f4394e620,0x00085289919c8fa1,0x000d6412359d3b9f,0x000a4c00c9ead88e,0x000626daa054c125,0x000853e0db1f33bd,0x0000000000000000}}, {{0x000ad013227cbee4,0x0005d963a674d5e9,0x0002422839e1c90e,0x0006f11c073f8abd,0x00051cbde443fb90,0x000f94add68e37cb,0x000d9cdf247fb6d7,0x0003b3ec024c71cd,0x000015c9b5032da9,0x0007607e0d83a94a,0x0000000000000000}, {0x000d4287c9083b11,0x000b167379dfa59e,0x00092871f05ea23f,0x0000a530c1fbcc90,0x000c9b670aaadfc5,0x000840b4f012b3f9,0x0006d74574236725,0x0005827f0582ac31,0x00047f13870e7720,0x0006f314a9061f10,0x0000000000000000}}, {{0x0003be466658f617,0x0009fd565e43add7,0x0004a046e438ce3b,0x0007e9edef2d69e6,0x0006c7f11d4e7b33,0x0009fce23db4d264,0x0007ee69cfe36cf0,0x0009d497797ff857,0x0000fa9f71e1b23f,0x0002d2813fdfceba,0x0000000000000001}, {0x0005801d34f0db76,0x0008b9ba1d6ad8bc,0x00038f8437efa8c8,0x000755dc58d2c493,0x0008ea5d4147adf5,0x000454e0d19f3138,0x0005174d880f0ef2,0x0006f4ab4400ed7c,0x0002f97c02972f59,0x000bb7fd1f05bd42,0x0000000000000001}}, {{0x000f26521378e02f,0x0002d730a6852468,0x000763f810a221e5,0x000f48636e9cb246,0x0004c1b9e4959290,0x00093bb4ca5e4a52,0x000f2a6103eedfad,0x0009e3ea2bb0a0a9,0x00013663d597d7ac,0x000a98c50bf00061,0x0000000000000001}, {0x00050b19a3ef90bc,0x0000ea69cbaa303c,0x00074f8f2fe993d5,0x000223c8be835b07,0x000f455e7085ef84,0x0002207ec6b0871e,0x000e48bd79a714e6,0x000daa1613ef3b51,0x00098f36229d3dd8,0x000c2d9134c94bcc,0x0000000000000000}}, {{0x00050a19f5342c54,0x000dc653d78301f8,0x0006bbf10f389ca9,0x0004326e54a5af67,0x000fdd8a13b29709,0x0008aa3fafda8b65,0x0006c2e3f7baf8bf,0x000bca4111083f35,0x000cdf78842a34d7,0x0002a973106a6473,0x0000000000000001}, {0x000155f05f4ec88f,0x000ffd8679f932ba,0x000e00ae69c605da,0x000b7c72ba823e0d,0x0009e0bbb62edf8b,0x000f7bf5bd871069,0x0004e610f36c3cf4,0x000e41a06519118f,0x00014868b2ff5976,0x0000f7b8d8554854,0x0000000000000000}}, {{0x0003e5d502754293,0x000e9ee9e0f2543e,0x000a3731f423dc07,0x0003b8bc5bf91184,0x000726f4ea8f1d1a,0x0008035844d23059,0x000c7266e29e66af,0x00082574f0c5767c,0x0001a6dd0e57d5d2,0x0004e537115bccdf,0x0000000000000000}, {0x0009f7ce1bfb6728,0x0000ccb130bc8170,0x00039a62c614cf63,0x00068e187476935f,0x00034de841f4a723,0x00011647b88ac5f1,0x000e09f54f07f6bb,0x000f505a8bf2adfb,0x000d75a5f605b64d,0x0000df9bbeb2b499,0x0000000000000000}}, {{0x000308733efc5f8c,0x000b75cdb37e83e5,0x00060b5bfda48081,0x0009f06138365296,0x0009688a8974b9f6,0x0005444cc05fb9ec,0x0005a67f252002f7,0x0009664675a1899c,0x000b6d7be11db7cc,0x000549e5e85617c6,0x0000000000000001}, {0x0000536e04ec0d89,0x000ceb7897a84665,0x000b8acad3957bde,0x000ba89439f416b8,0x000cfde12e814bb4,0x000a77e0ef45c679,0x000f35bbfcd091bf,0x0009f3ea6cc5ae92,0x000f66583ff4f9db,0x0009a867f0fed315,0x0000000000000000}}, }, {/* digit=33 [{1,2,3,..,}]*([2^132]*G) */ {{0x000487d30649cced,0x000796a5efc98a70,0x00086f3d00556482,0x000c177d81ed5742,0x000f3693c918841a,0x00044078e141f63f,0x000ad9ccb0cceba5,0x0005cd9ca803f396,0x000a3b9f81f2f890,0x000c5b4318691bb9,0x0000000000000001}, {0x00076e3095e41a52,0x0001ffb6fd45a8f8,0x000a8a0715ef8788,0x000192a0b8d73d7d,0x00086ca88981c074,0x0000f41a80dc66d0,0x0002bbb8f279d460,0x000cb55640383488,0x00052b11c10c7a90,0x000053f89b04d855,0x0000000000000001}}, {{0x0002e1e8d88792dc,0x00022e3ae581427b,0x00090f869db2e712,0x000e06689d393376,0x000702d537bfdb1c,0x0007346bbf1a9bff,0x00090f54aeeb8464,0x000273c9dd468a0e,0x000c871a654e3afa,0x0007465945d8c3b6,0x0000000000000000}, {0x0000e770af4a5960,0x000be4ac70e87a10,0x000797d6d911c87d,0x000533fb961a5c5e,0x000b8548c0001c5b,0x0009d47191b560cf,0x0009eeca65c8463a,0x000ecad37d2137d3,0x0000514ad716bab4,0x000f8789ad5bc27b,0x0000000000000001}}, {{0x000dbc583693bf30,0x000ef8d24b6766c6,0x00095890706d31b0,0x000c51cce3a35296,0x00080b8ed7618c90,0x000973ebf17cff3a,0x0009c68d473b1c44,0x0001098525e43a12,0x00074031f5036c9f,0x0001d33955ea92c3,0x0000000000000001}, {0x0006f1c314ce3a37,0x000a4064ddf24cf4,0x00070db52569e1fd,0x000405305ea2c55e,0x000d5f14297acf89,0x00046ea96e034f59,0x000622a42888331a,0x000a102ad1347dc4,0x00088a514e007741,0x0000461db8ec7cfe,0x0000000000000000}}, {{0x00023847d8cf0718,0x00021ccb2c301d0f,0x00024b1883c46a31,0x00063cce64fb5faa,0x0003cc10bc090432,0x000510506a731fce,0x0009a05134986c0e,0x0003aa30a907d289,0x00071f165d859243,0x000eeaa5074a4066,0x0000000000000000}, {0x000b1d8c9f3b369e,0x0008874f03f7bd39,0x0004a870054ed9a2,0x000756adbd121753,0x0001a9a0d0a37510,0x000529605385faa5,0x000c2eddf5c089f3,0x000a130a237e15a5,0x00074ff2cbd316fb,0x0007ee2c9d3ce137,0x0000000000000001}}, {{0x0009dbdc68f3280d,0x000657e090c25dbe,0x00024c6421981e70,0x00037a5a5d0a99ac,0x00037fc8c760c5df,0x00044d1a53e37845,0x000ff43dddfe06f5,0x000e4ab44983d93f,0x000c0915a82bb80c,0x000646c74033c3a1,0x0000000000000000}, {0x00004b5d5c7ce211,0x0001372b933ba5de,0x000ea64d116a103a,0x0006df2d3d823414,0x000619b7a1bf8333,0x0006eac1655d2034,0x0009aeedd521f9b1,0x0006d98d98725948,0x000610e8ae934636,0x000efd7b215cbea4,0x0000000000000000}}, {{0x0005d0308e1127f5,0x000cf03c8e2019c4,0x000aa0237cf6545f,0x000764372510cd18,0x00097139d47739de,0x000a85188927140f,0x00037dc9b8b5e192,0x000b2545731c10b5,0x000991ea59d03831,0x00067dea66743632,0x0000000000000001}, {0x000cc6866cf98c39,0x0009016f3fd54524,0x000592bcebafd818,0x0002f06cc34bdbb8,0x000b6cb2e7a209f5,0x0005749dab7ee649,0x00076406958e2abb,0x0009516d049dfaf2,0x000de5f7e8adfc4b,0x0007ce97062d4c5e,0x0000000000000001}}, {{0x0007da121df0699c,0x000ad3597a95de87,0x000181d213d52a92,0x00002da71c92de4d,0x000dd3803396793e,0x000c8761f332f0e0,0x0005c1e0d83b70eb,0x00048cf70527f5a7,0x000ceb82fe3e31cf,0x00029a56f1047f6a,0x0000000000000001}, {0x000ae721531eb7f3,0x000c70c79169f267,0x000d345b58d29bb0,0x0006c1daec3533a3,0x000115913b369665,0x00099820ca585f3e,0x000623473863b5d7,0x0003e2b952a9549d,0x00011f22279d7812,0x0007e6cad8cfd481,0x0000000000000001}}, {{0x000c384b610f9960,0x0009e42d4100e245,0x000c5264e577187b,0x0000ec202477a817,0x0009dc146fbb4cb2,0x000c49fc51a5dd07,0x000dd34b66b540f6,0x000418cb3114a207,0x000042a4afc85f36,0x000592a886f4d479,0x0000000000000000}, {0x00062b5959d642be,0x000c107df28ef33c,0x000c98bc18d09a83,0x000908cb61720266,0x00034bfa40c64e8b,0x0005f7d00d3266ed,0x0006699785d5c5ac,0x00070fda50cded6e,0x000a7129a0528d63,0x000df6226a01349f,0x0000000000000001}}, }, {/* digit=34 [{1,2,3,..,}]*([2^136]*G) */ {{0x0004a83b5020b6b5,0x00064ea6b7250085,0x000f5cc5dee82b8a,0x0007e307a44f4310,0x00061a979f99982f,0x0006271c95260383,0x00087bd9d4a6e7e3,0x000183121a682c2e,0x000a0c42c801461a,0x0009efc46dd1bbdd,0x0000000000000001}, {0x000ff9d53c8adce8,0x0004cbac7e6d6ff5,0x0008a2a18c9ba604,0x000457234e0b1c61,0x0001b538c1881476,0x000d20849fff1d07,0x000e3333d9430380,0x0001d1326f05033a,0x0004a49c4e89c642,0x000e640c63716450,0x0000000000000000}}, {{0x000a7c6657e0c514,0x00010e4ba5060489,0x00003183bcaf92c4,0x00051063325bb838,0x000624a227afade7,0x000d611fad61ce2f,0x0001f27e1c057fe8,0x000426a808156374,0x00051e188cc3f494,0x000e601fb19202dc,0x0000000000000001}, {0x000f5c4ba35ecd6e,0x000c838b90f28423,0x000ecc8f9f7eac00,0x0004ae3bc63ca5b1,0x0000a61f4eb49abd,0x000e5e94c7586825,0x00050828aa62e59d,0x000ca27ce17d2e20,0x000f7dcd24d94b7e,0x0004ed84ff72ff3c,0x0000000000000001}}, {{0x000dae22413fe9d4,0x000881c93ceb2c9e,0x000376b68f1c40b8,0x0004d107493ec443,0x000de2613f0552fe,0x000264177a2adbc0,0x00044456850f4d4c,0x000c024b1759999b,0x00032c490b5528e8,0x0004e4fe9cb25fa5,0x0000000000000001}, {0x0002401de7dabddf,0x00056529f2c840ea,0x0006004e218ae4f0,0x00026d7d9745c833,0x000bc1aa8e8c745a,0x000254366c2e1e3a,0x0009a65d176c592f,0x000575f2ce2f5dba,0x000390121cb70eda,0x000ad4df3bd7c9ef,0x0000000000000001}}, {{0x00052f406338228b,0x00000044f05c5be3,0x0003a7061d336069,0x000371f2e7fd3e15,0x000ddb123a32ed82,0x000a15e8eec0c29b,0x00046b80938b2d11,0x000ba2ae38c19bba,0x0000c4e7466a69b9,0x000ba8e7a0607a47,0x0000000000000001}, {0x000e250e34d513c2,0x0009900d3d611604,0x0002850e69a99aa8,0x000ea018e87aacf0,0x0008ea9b70f5d0f5,0x0009dfec50e62995,0x000ef7267ad0ad8c,0x0009fbbc4dd8a19f,0x000ef73af4e91334,0x000d0636506a6e44,0x0000000000000000}}, {{0x000533f2ba0eb14a,0x000b9fc6b2073504,0x00059889c71f37ca,0x000d3e3b2957243a,0x00033cd4ef031ee6,0x000e1fa792c82e2f,0x000936a9431aaa2b,0x00075897dee2d5df,0x0005c1a2769038db,0x0004c149337ba93c,0x0000000000000000}, {0x000ff077c9595fa2,0x000b4e92632965da,0x00073090129d489d,0x00024c2f940397cb,0x0000f08747c463ab,0x000063f57ea7844d,0x000a687de4ab15b4,0x000d7bdc8db9dfb6,0x0000393c5c4b7272,0x0002b3cc129fac67,0x0000000000000001}}, {{0x000d85352986f86b,0x000b3bb5e1a9d134,0x00096ed674c04b6f,0x0001eaebc5869197,0x0001ec13b24f0220,0x0005acb88043fe14,0x0006b2f77717702d,0x0001f913c28eb4c3,0x0008bc0cbbd9e8fe,0x000014871dc376bb,0x0000000000000000}, {0x000b182392919d22,0x0005619062a004b3,0x00084b9c0aa0d96f,0x000e6a14d38134a4,0x000b962e9b9dd384,0x000d2a3f87434945,0x000e17c26111d5b0,0x000cca088afb0558,0x0004109b67e83601,0x000ebef3372d865f,0x0000000000000000}}, {{0x000c5a0356b17ac7,0x000f616fb80668c9,0x000f7001431d3037,0x0006786061783bd7,0x000e2a8db044a7eb,0x000d63e80e687c5b,0x0006dba72619e19b,0x000b3f54433d79bd,0x000179eabd3da5ab,0x000fcebeded88553,0x0000000000000001}, {0x0001156c4d223604,0x0006fa0e48c3398c,0x000d70c895f6a870,0x0000aa32def1e5d8,0x000a3628036e774e,0x0006fa3b42b31a93,0x0003f15e7bb3f2aa,0x000fd667e0a491ab,0x0002f04b61d5276e,0x0001fdac2e330e17,0x0000000000000001}}, {{0x000760d231c36820,0x0008bd2a50426c8d,0x000d4451d722fd74,0x0001877484a5084a,0x00019395bd1ac7d5,0x000dc03d6541ad77,0x00068a254b40eaa5,0x000dc699a962f42c,0x000f2ecdd481b2b4,0x000345d9badbf178,0x0000000000000000}, {0x00090c94035684fe,0x000e517a9849bb68,0x0005822be91e8615,0x00067ca7e3c3e516,0x0004c5ebee67a9ed,0x000f03236f5438f4,0x000029ef9e45ec0b,0x0003412d001129c5,0x000bad0b64fd4f4e,0x0000e15f591e3c09,0x0000000000000000}}, }, {/* digit=35 [{1,2,3,..,}]*([2^140]*G) */ {{0x00067ca62dd9afd4,0x000678b2e8cc8368,0x000d7d6c96a2abfd,0x00075f62bb6c702c,0x000988eb9ab34b7b,0x0007b382272a8eb6,0x0005e40ee1d17286,0x000b6f600751bff1,0x000ff996b4ec3001,0x00015d7fb8efdf30,0x0000000000000000}, {0x00062d76a29a2746,0x000f091c80dd81fc,0x000c1a9825d4a2f2,0x000a4fb54ae9b61a,0x000db71a812fcb05,0x000bb96eaaa7baf2,0x000dfd9cc434e4e8,0x000b8fce567253c2,0x000b948eeceeb8e7,0x000abac787b7e9d6,0x0000000000000001}}, {{0x000566d2087a8f7e,0x000f8d816dab3c44,0x00068ad0a5ea555e,0x000ab76093fa3eae,0x000bcad51a41fb45,0x000c784a1114a732,0x0002d99cd96f3573,0x000f7808bc957e91,0x00022a461547dff3,0x000e9dd3f93d98d0,0x0000000000000001}, {0x000f5792b3bed20d,0x0003199e50e443dc,0x000ab35921f1c5d0,0x000cb763ce7e3777,0x0009ec69a2c8061a,0x0004921d8bd5a1f1,0x000d3f186d49b86d,0x0003d287849a3eff,0x00019a1d3969ee2c,0x00097e7987e8d923,0x0000000000000001}}, {{0x000e6b3554a3f3c4,0x000c8b48d7c64666,0x0004319bb26494ce,0x00023bd53c15f132,0x000a4b25b7340a49,0x0002c82187e36296,0x00076cb62a70b23d,0x00013ce0a44b3a26,0x000e1376215ada95,0x0004bdcdd5bfa093,0x0000000000000000}, {0x0006f0577c34a522,0x0002d6eb1d23f2e1,0x00074b1ae5a563bc,0x00076c1922ce417d,0x0008d8b56e586f06,0x0003d2111864665c,0x0007a1f4a9d1f08d,0x00009ad18a2eb5b5,0x000f16f69121b144,0x00055ad3dba51f31,0x0000000000000001}}, {{0x000a0990f6c14c34,0x0002ae1571f4bd14,0x000a7e981428a12a,0x0008a57064ea4bd5,0x0005ec2f56d89f54,0x0004fcfb513a99f0,0x00081deb029c28b2,0x000c16eb364a4688,0x000f6df6754a22d8,0x00039a8e7ba7c29d,0x0000000000000001}, {0x000585b840875f9d,0x0006688b87eab66d,0x00061b8a4aef8f2e,0x000968d01b210ab1,0x0007a38c32d9fcd5,0x000170203f9469f2,0x00027ba7e65bf262,0x0003268e8f3ddf53,0x000d5d6a50d743f2,0x0006f76866dcf3bb,0x0000000000000001}}, {{0x00075ceb39ee406f,0x000fddc2dbf93cfe,0x00005aa3d0f7d044,0x000c04043459ab15,0x000bfbea051fd1e4,0x0005c86723eeca2c,0x000dd90428637a5a,0x0006d3aca9d581d9,0x000277709f646127,0x000d9e5fdc588878,0x0000000000000000}, {0x0005fdeadee7c5a7,0x000b59b799ae3c10,0x0005e3595acc919d,0x000b6f6b2aa1f7f7,0x000cc519dab324e9,0x00070aa0c81054ee,0x0006840dab1fa02d,0x000ce8162c464504,0x0007fc117382d8fa,0x00079cc63a2e343f,0x0000000000000001}}, {{0x000f45643ca65cbd,0x0007305e42072e40,0x0006980bc47b22b4,0x00091f480c0959ae,0x000df17382117d00,0x000fb6755fe76ce6,0x0008195083b13716,0x00053ce928778e33,0x000eadd235784446,0x0005f288650fd122,0x0000000000000001}, {0x00032d4f966b7e9c,0x0006ec40795011b8,0x00056106a162f5eb,0x00060472439d72fa,0x000ed9a6959807a3,0x000d3315f177c4b5,0x000b196cd83808fb,0x000c21f3f41dc773,0x000518607dcca40d,0x000920d975bf1042,0x0000000000000000}}, {{0x00043d0a4a0b7f26,0x000c9bca61488d76,0x00078d40864c9a4e,0x0009191208ac32aa,0x00065e2c33dbbd1f,0x0006b041d84ce172,0x00022f6c73e5e84a,0x0000caf07f551302,0x000e0bc76bc20bdd,0x000a43482195b22f,0x0000000000000000}, {0x000f04c8745c6a12,0x0002b2bdd6ee1437,0x000b9431fd260182,0x000e54b7f10879b1,0x000a6b8d5c027ebe,0x0002358509530c61,0x00071ee3b953e075,0x0001d055e247c05d,0x000f78c21fc120f3,0x000c40b71a77f551,0x0000000000000000}}, {{0x000ca1655dd01fc4,0x00023cfcdcd83fdc,0x0006fe01dad6f137,0x000a92f448fc724e,0x00071e9506b3510e,0x0002c50316bacd31,0x000812e5b9c38263,0x0005b06a2041b525,0x000d1e51d6095bd3,0x00018f8c9f2aff29,0x0000000000000000}, {0x000e8440d9f6b1c5,0x000d8f5815a76ff5,0x0000ba6e7eb4652d,0x0000cfa7a2d772d1,0x000e12c2c10a367d,0x000122408a9134fb,0x0006be74d3fc999e,0x0007f158ed729839,0x000445a86f173644,0x0008103589b3e72e,0x0000000000000000}}, }, {/* digit=36 [{1,2,3,..,}]*([2^144]*G) */ {{0x00002ef5664a50e9,0x000569e6626b5584,0x000bb9dc4c85c34e,0x0006cac4009d6dab,0x00047cf68656c674,0x000e65ab973336b9,0x000ecf3e266a898f,0x000b5830a2ee0371,0x0007109821d57e75,0x0002643e097669c9,0x0000000000000001}, {0x000e2ad77fec8187,0x0001deddfb754e78,0x0004aaa3d5328431,0x000f5938ac9d56ca,0x0000419e9ec29fe5,0x00089e92d324185a,0x00068c4746f628de,0x00086959a461fd09,0x00039e1752cc1b19,0x000f685c4efa867f,0x0000000000000000}}, {{0x000578941d3daa6e,0x0001e81a86314a15,0x000e2ec49066a742,0x00085f37e975bc97,0x000abd59fd20aa74,0x000b001318e5e712,0x000bdca951133a15,0x0006057f57ee1259,0x000dad04acbd3b2c,0x0009e7ef3153ef33,0x0000000000000001}, {0x000d37d508c6263d,0x000d87a4e81e7b2e,0x0005a01a3eff8f36,0x000726730288c3e4,0x0009b846f52088b3,0x000f560651a99118,0x000aeef71db52e56,0x000e58e36c06431c,0x000d03f83a3f98d5,0x000adc020099b8d8,0x0000000000000000}}, {{0x000d0b7b6a8a3320,0x0007c1820c541666,0x000008d89959635c,0x0006f6b2d261e2b0,0x000b20857dc9286c,0x0008490da31aca2d,0x00001835ecf8b430,0x000769b376d5c408,0x0006c3593326d702,0x000ae359276d5c27,0x0000000000000000}, {0x000052b955ccca9f,0x000132f8bdb8b0e1,0x0001fc788aac66dc,0x0007aff377f81134,0x0005f3f5c42cf8fe,0x00063a0cd5ec56c8,0x00044e19f92551b9,0x0005a03e4e9df2c1,0x0005981a18a9c38e,0x00038410aaa01483,0x0000000000000001}}, {{0x000ab1b79d73f8b8,0x0002c67e2040bd52,0x00089ab066095a12,0x00020058f1cb78af,0x00035c77cb75101a,0x000e13361531375e,0x00075eaea159ba65,0x000a7ecbfca3524c,0x00019d039ab8ae0f,0x00099c623ac91c57,0x0000000000000001}, {0x0001430a249d36df,0x000efe8450eb5d6b,0x000afb92b30c47b9,0x00024beea9991147,0x00039e1752c3ff68,0x000fd6a6252b160b,0x00046e76256f4b47,0x0009076f7bff5746,0x0003f350ce5bbdfa,0x000da84642b5dbcc,0x0000000000000001}}, {{0x000f59f034423df4,0x0000c74c6502a253,0x00051f6b04936dd5,0x000ac1dfa20fd420,0x000a26ee480942df,0x000b8f32c2aa1793,0x0008f9fd5819aba5,0x000593ae9a68c3be,0x000809f95c514dfc,0x0005832a0100c51d,0x0000000000000000}, {0x00084df91d0b9d7b,0x00019af96dda8b28,0x0009e06515fe82b7,0x0004e7882cd87d52,0x000d3f4a8cd84bcd,0x0005a839e5e4c173,0x000eace8b4e2b402,0x00009c378fed4c2c,0x000b8a183c245522,0x00026032daca8b53,0x0000000000000001}}, {{0x00021d74b7f15174,0x000b1737719209fa,0x00000c8bba28cfe5,0x0000523f1c2878b2,0x000c0170331c9a62,0x000cd83b50a5843a,0x000131d0381135b8,0x0003a643b75eb047,0x000ef1464d2ab54c,0x0007f362ed0e42c5,0x0000000000000000}, {0x000bb20fbad15614,0x00040a78f8613291,0x000895f7e0d7805c,0x0004b54ca2a8624a,0x0000e6579a8713ce,0x000626e2cc1b0cde,0x00093c66377df41d,0x0009cd6454de0451,0x00009db1f1c3ca34,0x000d91b047b0a149,0x0000000000000001}}, {{0x0006148c3607c309,0x00072dd5c6a1cd15,0x0004ea2e6d51f4ab,0x000bb9012a38398f,0x00025cc1f09df84a,0x0009c3bace064bf4,0x000f3b1a1aeaac49,0x0008ba0e470586b9,0x00026aca2a7b1cc0,0x00037064de7e58e0,0x0000000000000001}, {0x000f70f6864c071b,0x000cebbcde808997,0x00042d9268c9d10f,0x0001f3646bf97f61,0x00099c6124289f61,0x000f65308f5fa877,0x0003b1cbe10f2164,0x000db1cfb717f6c1,0x0002178fd0705446,0x00053784aa2a3cca,0x0000000000000000}}, {{0x00032b93eb6bf0f8,0x0008d44a6f35d7f4,0x00062f74f5a61124,0x0008d968ff45509d,0x00090f78b11dcef9,0x000e0fdb4e540d2d,0x000178df19486918,0x000b775c9c48f839,0x000a4516e1546952,0x000548b05a9a422d,0x0000000000000001}, {0x0000e6542e705240,0x000ea85c40801a5a,0x0008cf4381fc9bfc,0x00026551ecff5ed1,0x00006e3765708042,0x000f10bb393addaf,0x0004c0be6d6327db,0x000ade98dcbda7a9,0x00045d1d2c9cc265,0x0001d23919800694,0x0000000000000000}}, }, {/* digit=37 [{1,2,3,..,}]*([2^148]*G) */ {{0x000136d3adf7c0d8,0x000a615150ed1e22,0x00048b602d1f12f4,0x000a438f58c86ca8,0x0006c2ad94dbc8f3,0x0001741520fd2861,0x0006926fc8f344fa,0x000aa2867b7697e9,0x00063769f3f74f49,0x0003389eafe4ecc9,0x0000000000000000}, {0x0003271ab880c04c,0x0007eceb904c8b8d,0x000cf0e8b6b36124,0x000b8dfe9dc846a9,0x000c71bd5a3dcf58,0x000bb872ef46766e,0x000ea257028f76aa,0x00037d56cad75976,0x000e6e410a7a4c1e,0x000aa4d9ef6dff50,0x0000000000000000}}, {{0x0003f21a068b1990,0x00028b83926d837e,0x00046424f5058ff9,0x000540b150a21088,0x0007bd69839e2656,0x000836bb43217215,0x0008f5d34535e3bc,0x000a61ec6b271f81,0x00014bd57f4cd40a,0x0009c8fdb8302a87,0x0000000000000000}, {0x0006b22f2553a3a3,0x0003b58b7033af0a,0x000213a07cddbf4f,0x000434d1d71e271e,0x0003ac069f3affa9,0x0004ccd448d5d23e,0x0005a3de785990cc,0x0009500536e9dd21,0x0005a1f484316890,0x0008d39f92d8e2e4,0x0000000000000000}}, {{0x000e463b75bb6ea5,0x000ed0a11789a549,0x000dd32eea4152e4,0x000b779f3244c612,0x000a765d467497f7,0x0001f2317d762ed2,0x000fb479fdc0f1f6,0x0005b625c778a26f,0x00086e4279e293c7,0x000778007cc51b6a,0x0000000000000000}, {0x0008d10c9ca3a103,0x000303626747aa01,0x0009d0d1059a4b9c,0x00047b992888178d,0x0005dee73f8df999,0x0003009b79f58ee6,0x00095bbb19efb6cd,0x000ee364f704fdad,0x00075210ba101581,0x0009e1f5ffb0008b,0x0000000000000000}}, {{0x00061dbbf0d6ad65,0x00037943121ba6f6,0x000176edfca2325e,0x00061e28f0cef68c,0x00084617ac6eda38,0x0007535e8ca77e7f,0x00023d1d31f498d5,0x0000546d78b2f36e,0x000c7d55e2c3f881,0x000891156a1cb9cf,0x0000000000000000}, {0x0004ce76bf8c0b46,0x000f73894a4c0a97,0x000e4d65f8fc178a,0x000cb9405d4f42d7,0x00089f73dac29f71,0x00028141921d35c6,0x00055dee3cb66f43,0x0003af9effca7532,0x0004e3d9ea981425,0x00042022e23b71d3,0x0000000000000000}}, {{0x000d0b7e99b465d6,0x000dcdbbc6a7f631,0x000fdb4862b8d0eb,0x0002d00e72a3f599,0x0003fff9e95d96f0,0x00098b66f4cdbc62,0x000ac921634cb2b5,0x000ec0deea0b5c81,0x0005b0a27a76f063,0x0001e02d30431834,0x0000000000000000}, {0x000c98aa1c9ac7a1,0x0007c5a7466568e8,0x000fb66755607c49,0x000ef99d83842e7b,0x0003f63d03b04212,0x000eea39bde1d43a,0x000c0a3d0947a656,0x000da642406f1e3f,0x000c396f50ca4ece,0x00002261add500ea,0x0000000000000000}}, {{0x000faccc08dd24e3,0x0002a75b2039c36b,0x0007b00e10c370cd,0x000decd44a6f8b5d,0x0005623fd6ab9f44,0x00019a1ddd85e65f,0x0007f5f2f27bfaa2,0x000934e1d6c8baa2,0x0002398cf5bc3e40,0x000936e76ebca08a,0x0000000000000001}, {0x000b72cc3defb1bf,0x0007c48e0f8a00ef,0x000b50a281abffca,0x000290112a957074,0x000c6cc0bcd2913c,0x00080828c73f9cbe,0x0002b7332c142bad,0x000b82fd75dcc17d,0x00071d9dc563b115,0x000fa46eb1fc833d,0x0000000000000000}}, {{0x000293af2196db74,0x000aa8f516dffa78,0x000ab476917c3f2d,0x000a17a44ba1c0ca,0x000771d0d213b4e6,0x000872d37a8c50d3,0x000a9d4f31d594dc,0x00020ae17df8f34d,0x00012ccecab30c4d,0x000fa5e5b7722b87,0x0000000000000000}, {0x000e6e4b1df4a900,0x0005d66c421f23c8,0x000473d466e42335,0x000dad17c61ddae2,0x000ed279fa7168cb,0x000addca2ea2657f,0x0004d479a5bdfda6,0x0009ec1a80eb84e8,0x0001a95ca1a89847,0x000f2ca605fdb8f2,0x0000000000000001}}, {{0x0000bda5161e9684,0x00055c62c59939aa,0x0001e39fae89d4f2,0x00072aef74c49bbe,0x00060180fc9e6093,0x00063da12ade7248,0x00028defa823f501,0x000a965a30e8a72a,0x0005cf1083c600ec,0x0004af9f8b968790,0x0000000000000001}, {0x000afd7d7d936a7a,0x00003b13810cfd26,0x00037d1ddbf986aa,0x0005d035eede05c2,0x00071b7ae0b88271,0x000812487895ef9e,0x000f170e50423460,0x00003054f1639f87,0x0002e674eebc0936,0x000654593b42f2ce,0x0000000000000000}}, }, {/* digit=38 [{1,2,3,..,}]*([2^152]*G) */ {{0x000a2f3a1cbc282c,0x000e19a09feeb1c6,0x000c54628c6180b5,0x000cefbae8c61be2,0x00031054eeedc773,0x000005e41190648d,0x0004925364893510,0x000a54e9064644b7,0x00026639e573a22c,0x0003b5a6074dacd6,0x0000000000000001}, {0x0002e1f28cb4398c,0x000fba11161ac99e,0x000aaf012b04f328,0x00060a6cb74a91c1,0x000690cf3c48dadb,0x0007c4e07d1b8182,0x000bed19eb0dacbf,0x0001aba090482e6f,0x000b8c6fb9ea1ef8,0x000d6d4b567809aa,0x0000000000000000}}, {{0x0006de757b8ee9dd,0x0004f4a9eb572b8b,0x000650813f9e5a92,0x000081024cddfbbc,0x0003e750529ae0f8,0x000c407a678dbdc2,0x0005c643db36c6df,0x0009adee9ab1549e,0x000add1f855d46bd,0x000aedf68182d8ac,0x0000000000000001}, {0x000e2fb66eef3f12,0x00004b24a7282866,0x00050b3c877e75f1,0x000590fae38bb301,0x00008b7b5535d2f8,0x0001b50eaef87c62,0x0000c4541ba355de,0x00098bfe96023f0d,0x000dcf2eadc15969,0x000f41ab8c033f3c,0x0000000000000001}}, {{0x0001bfbe835763b7,0x000da08736745919,0x000d000c52158859,0x000dbafd4373d9cc,0x0003efeee235e560,0x000fe980f98d303a,0x0004f012a6082ad1,0x000e567ed43eb524,0x000eddca68306748,0x000f954e531e38a7,0x0000000000000000}, {0x0000101b465ee778,0x000f8f4e95956310,0x000bcb6c6057ab1d,0x00052b140218cd6f,0x0000a217b7b093a1,0x000924c99c9b3267,0x0000b388550cfd67,0x000eda396f8cf9af,0x00035154327557bf,0x00098cf74a0d9f01,0x0000000000000000}}, {{0x000cd9335dea0190,0x00015fcbf855836a,0x0007808f96352fb5,0x0005c5cb374fc6d2,0x0001eebbbb50f586,0x0007f3a5b9a4d0c8,0x000bc6329ed702e4,0x000264f0fada97b4,0x0005e3bbcf73be9b,0x000dd442f9f14de6,0x0000000000000000}, {0x00029cdbcd6414f5,0x000db247ce590b47,0x0005be836ddf363c,0x00032e4b6a8da968,0x000c049bdb9815fd,0x000d8f7528076e41,0x000d50b097db4cb8,0x0007f829470b7fc1,0x000b6caef75b1cc6,0x000ed3d55324b1d2,0x0000000000000001}}, {{0x0002ed4b0886efde,0x0002e69216f70caa,0x000a19fc084c43fa,0x000bf1fcd447360e,0x00088b44bef17255,0x000c941e542e92c6,0x000c9462ab05687b,0x000f4a55ed27b06d,0x00006c4879438508,0x000b3f5a16cdbf59,0x0000000000000001}, {0x00090da308f335bb,0x0002c62f75607156,0x000ac3878c204f5d,0x00019a70e1d9ebee,0x00065ce18d8dd345,0x00053d4a7a6a59b3,0x000ab840d7a66249,0x000e9f8efc3edfda,0x0006a32d022f5317,0x00072a29be1120dd,0x0000000000000001}}, {{0x000bdbfdee3c7792,0x000b747684a7e37c,0x0006fd64e032b7ae,0x00031287b0371790,0x0003245ed96aa7b2,0x000bcb2d9689dd51,0x0009eceb1d9918cd,0x00053e6e8dbeb445,0x0003cd8435c2226c,0x000a212888b11938,0x0000000000000000}, {0x0001020457ce98be,0x0009fbe80ddb3555,0x000e385ff7a0d009,0x000821584b1de3c2,0x000f36cd64d47bdf,0x000d2c6d2f0d97c5,0x000126f061319f64,0x00050f118e4e9aeb,0x000dd0fd66a1918b,0x0008c9bb60247ff9,0x0000000000000000}}, {{0x00006452a69b40ef,0x000a58916404d8d3,0x000489351fe54188,0x00083228fc171eb7,0x000410e07508f15f,0x000b2d0bdc317f64,0x00075755181b0c85,0x000c4ca35cc09ad3,0x000bdec4e4688b7b,0x000ec2f6e18ec10c,0x0000000000000000}, {0x0000b91ff7109c43,0x0001353357108dc1,0x0006db397b6c17eb,0x00038d3f418ed53c,0x000a1a7d0d6f5104,0x000558963fe8aa2f,0x000629ed52f70d0f,0x00070987dde60b3f,0x000b95a72bb4ccee,0x000aae64e168b593,0x0000000000000000}}, {{0x0009ff50fcb47b0c,0x000001fc1e2456f6,0x0001c124be702b84,0x0007f671a6c9b545,0x0000e07337c72285,0x000d3661d0b0a89f,0x0007db2af0223087,0x0001d9b173b261f1,0x000c65404d0457b5,0x00086eefc1cd30f8,0x0000000000000001}, {0x000fafb34fbb3972,0x000db4c5bd6770ff,0x0000de59815fc7a7,0x000b5602342e8ca8,0x000220e1c9e4f843,0x000b0b7c5b3bfe91,0x000b313a1e2826c8,0x000988ce465ce442,0x000217ce5f2ef9e9,0x000682a10ff59077,0x0000000000000001}}, }, {/* digit=39 [{1,2,3,..,}]*([2^156]*G) */ {{0x00041390c3361b6e,0x000b58054f802294,0x0009b74e1597143a,0x000652a48a901ba0,0x0004b9b4f3635116,0x0005e2ee300afb31,0x00079f7d46228864,0x0001b66e61674d2f,0x00005aad2298ff3c,0x000bd327d6400925,0x0000000000000001}, {0x000b20dd543f093d,0x000dac4b51c2ba0e,0x000bf1d364874c9c,0x0002601310d4063e,0x000c6c8c6fbaa6b7,0x000ce6639ff8b94a,0x000066c91f488ec6,0x000524c600b8f454,0x000ff656ef37706e,0x0008a0434286c21c,0x0000000000000001}}, {{0x00077e284b1fd44f,0x0001dc37f60445d8,0x00069f0b4dfca419,0x000aa285358c7759,0x0003172cf55e112a,0x000ffea4f47f71ae,0x000412afc352eb30,0x000bc7ffc3d95b8d,0x0009ccbacabdbf74,0x00030dd4b6acd123,0x0000000000000001}, {0x000870d6326f819d,0x0001f9d1598751a6,0x000c925f0b6c6b0d,0x000c309ba890fd44,0x000f1cedd20fe106,0x000408588dc46673,0x00053cbebfbcf6f2,0x000da52fed53b541,0x0002bbf3f7b4aace,0x0008d484a22a2167,0x0000000000000000}}, {{0x000d633fc6b2523f,0x0003c8573eaf11ae,0x0005f254d2bc0511,0x0001c7fd283764aa,0x000f770135776ee7,0x0003df5ba988759f,0x00065da842051883,0x000b809c0705d522,0x0001067f4912507f,0x000fb628d91a9464,0x0000000000000000}, {0x000e6e2ac33e3aac,0x00065c0000ebfac5,0x000ced796bda6c05,0x000a32836c90c0d4,0x000d2ee187fc8100,0x000d7848e982bcb3,0x000be08290e6b628,0x00085ab586db4a59,0x000b07e2fb9a0080,0x000d56210d8de2f4,0x0000000000000001}}, {{0x0000ac7a2fd05258,0x00034c744e57f4bf,0x0002edb448a88343,0x0004d56a4c1f9523,0x0003b85d4cde6c8e,0x0003063d710bd23e,0x000833d45b52f378,0x000d2012d08a14ca,0x000ccbe55ff85aae,0x000e919fa9b95c02,0x0000000000000001}, {0x000999b76646e255,0x0001f5f355b09a04,0x00000d64b669309a,0x00089605b2bd55ad,0x000656b121bac578,0x000d693b7220d91b,0x00053ea1faab888e,0x000745d07a303444,0x000e7a52e75e36d6,0x000a7986433618f7,0x0000000000000000}}, {{0x0002484fcef15b60,0x000485fc2dc91c4b,0x000d7e9f8403b5be,0x0005ec8542217cb5,0x0003f3deede9d858,0x0008c56ddda1f005,0x0009028845902ce4,0x000cdbb111feb2e9,0x000537c2b8f6659b,0x00075d89960f5bf1,0x0000000000000000}, {0x000a9e85b9799e89,0x0001de39c6986f88,0x0000fa555ee69af1,0x000f3b270c555b9d,0x0004c62266b30411,0x00084a11940b0e86,0x0005b26112da8247,0x000fc56950bfb7ec,0x00066d81f8a57ba0,0x0003b772e0aa0038,0x0000000000000000}}, {{0x000710f55ddf9e13,0x00018f67ff0e8dc1,0x000601481b67ef67,0x00009ffab39b462d,0x000b5ad90ba1057d,0x00018d94f2f83bbb,0x0008d2eed4c7a169,0x00019ddb61a12bee,0x00096ab74dadd029,0x0003902e5753e9de,0x0000000000000001}, {0x000926dcd7de034d,0x000eab5af3e375a3,0x000eb250dce827a6,0x00008bd108623cdc,0x000d49a7d0e9c524,0x00066e3019236fda,0x00040ab55ed033af,0x000667077bc755cf,0x0006972e633b49be,0x00095334396ea43d,0x0000000000000001}}, {{0x000671c0c20009e5,0x000956db94fffef7,0x000bca8fdc30361d,0x000ebfa5860aa7a6,0x000feca2b724bff4,0x000572f34fd506fb,0x00048ff2e88a7d1e,0x000874822e19430c,0x0003c0129eb20b17,0x0003db07cc6f0162,0x0000000000000000}, {0x000244f5da60b490,0x000fbd8954a885e9,0x000f39699542bf3b,0x000c93a6a7e331fd,0x0009816b29c5180d,0x000ad960c8e85d80,0x0003a3a7931b35df,0x00092e570f2974ab,0x000904daaf442234,0x000cf25e1f700754,0x0000000000000000}}, {{0x00056e1b7ae8ee13,0x0009b65f8128c4ea,0x000e5e0d92d02840,0x00074f688ed0e1c4,0x000f9c55f66d6f3b,0x000eb2ab8035d3f9,0x0006b643bde4296d,0x000f25e29f7ea7cb,0x0007f5f239b9d057,0x0001af17e3fac208,0x0000000000000001}, {0x00063cbb323c7d21,0x0002b6d926fd3ed4,0x000ab9ee679014b1,0x0007e6093a1bcb9a,0x000dc171705931f4,0x000b0a4387f44f73,0x000c7cdd2a12e513,0x000a473ec3b73ce5,0x000ef17967f341e3,0x000a3809a474c86a,0x0000000000000000}}, }, {/* digit=40 [{1,2,3,..,}]*([2^160]*G) */ {{0x000dc98081f0b504,0x0002377f1bc655c2,0x00067de245fb688a,0x000260cdd7a61e34,0x000d89aaf28a330b,0x0004e078039aeae5,0x000a42253d349d8d,0x000438cabcfed7ae,0x000a9960f3728bd2,0x000af658af568325,0x0000000000000001}, {0x0006e52ab17d640b,0x00019d1bc21ee481,0x00026613d4c31a58,0x000c14072a5969b3,0x0005babfa75ee1a8,0x000c563bc4d35701,0x0000425d2086ecb7,0x000c9b8fafb1a4a8,0x0007ef737c2661a2,0x000c20e7afb2d654,0x0000000000000000}}, {{0x000726f329838a5e,0x000204b7a9942b65,0x0004a26b80fa33e2,0x0006f40abbf82a56,0x00026970dfcc973c,0x0001c38e96f95485,0x00019abd2bbae55f,0x000c1edd71d62ecb,0x00020adf26d97496,0x0000d917e1cf322e,0x0000000000000000}, {0x000aaf44ac399116,0x00067bb67e29ba76,0x0003d1213c21031c,0x0003b345e37fdfde,0x000dab46f2bbeb4f,0x0003442227ef5d5b,0x0005c11bdace9105,0x00060e12dac175a6,0x000cdb1cf99010c3,0x00087106f2502658,0x0000000000000000}}, {{0x00044188249a4961,0x000eb8deb1c61cee,0x0006080b71cf8ff5,0x000b75b57b2ccc29,0x000b9ffb3c6aa214,0x0000a50e70e80f53,0x000fd2ffeb156be9,0x0005a94620e80211,0x0005db41e15422e5,0x00055d2030526508,0x0000000000000001}, {0x0009e1933e619307,0x00086b5084131313,0x000b6d55898976e9,0x0003f79536a0866b,0x000b8e06bc0b2a44,0x00034e542863ba00,0x00040e4dd7a73a37,0x0008b2efa3822134,0x0005312ecb0905af,0x0008efb084f884e9,0x0000000000000000}}, {{0x000172c5ec6e6f32,0x000784d8ddaafa3f,0x000785f2ae4eb6e8,0x000db162f77d65ef,0x00085dec5c58d4e5,0x000a30bffa2375c7,0x0000bb7c92e0f7f4,0x0002294b17a00c92,0x0009107e026f93d7,0x000911ce9dc0950a,0x0000000000000000}, {0x000841c6766f1f49,0x000079724523292b,0x0000e7ddb4cb0490,0x000d47f955646515,0x000b44b2a0877c3a,0x0004c3de4bd8708d,0x0009d24b4a9131fa,0x000585e650ae938e,0x000bb2e4980176c4,0x0001820248559a60,0x0000000000000001}}, {{0x000cef71c9a9281b,0x00078b2e3e260928,0x000b15a4e8453115,0x000c76cc66031c77,0x000e2f2c06ffcc30,0x000a471db8c352a0,0x000184b9a687b94e,0x0009b19798642e1e,0x0001d84cf08e1a1c,0x000462a36c823a7d,0x0000000000000000}, {0x000b775551fedfb4,0x000c921b0d298e47,0x000071e1319e7833,0x000e6f4ce5e5ae43,0x0001348ff7cbdbf6,0x000c042f31447260,0x00061f1861a992ae,0x00020e5f80d48204,0x0008846b75b72853,0x0005ef4edf14c058,0x0000000000000001}}, {{0x00051608c9277436,0x00036641c6cf4e0f,0x000263e7b7515b1b,0x000a50636eb6d459,0x000df53679a56041,0x000b4abcaa6ef1d0,0x0005077b47a03019,0x0009d2d427efae97,0x0003dfa9162f30c4,0x000f8bc801e5655a,0x0000000000000001}, {0x000202783ac347e0,0x00001a26d59f4868,0x0003895e6664e175,0x000031f4202e3866,0x00069d2af7613aa8,0x00021cc1e58ddf28,0x000159ee13d84ffa,0x000c8f6eb59a5da3,0x0005df9b7b87bbc9,0x000771b8b6006cdc,0x0000000000000001}}, {{0x0006aa5bb86ea29f,0x0000e29e7a21c03e,0x0009e430844ee3c4,0x000584b091ca8307,0x0006afb05a033420,0x00015d7ef65dc354,0x000acb0dfae44d05,0x000bad35608c8e97,0x000a78e5d1c181a0,0x0007cad8ba90d885,0x0000000000000000}, {0x0001cba5026e7f38,0x0009593d89eff94b,0x000b88834191828d,0x000881379cd1acbe,0x000c4d9c16250e77,0x000f4d66dbf51b1f,0x000703cbf985d682,0x000998e4fae0e78a,0x000e124668125e5c,0x00095c7096d1799f,0x0000000000000001}}, {{0x000c267dbe90f79a,0x000a682de8af3a96,0x000fc2373c7d7a0d,0x00046c045ae71058,0x00067b05a94e6008,0x0009ec9a78879108,0x000973f0df20f654,0x0003d4a6c168aecf,0x00050f6bc30604ed,0x000f342722d4210b,0x0000000000000001}, {0x00089badc8348ffd,0x0005ea32767a9d3c,0x000dc1a4baa76ac9,0x000219cd3eced60d,0x0007d2d3cddf3114,0x000c14e1ea557cfa,0x000c466d40b6e234,0x000224ae183077a3,0x000e59e159bfca75,0x0004c30d62fa0c8e,0x0000000000000001}}, }, {/* digit=41 [{1,2,3,..,}]*([2^164]*G) */ {{0x000acef3fd9ab352,0x000a04dda16fb097,0x000e90de3351fbdc,0x0001f9baff197a3e,0x0003610909fc0701,0x0003d538e2bf8355,0x000fbd9d3c214c4a,0x00064b2db047d1ad,0x0000b9e3fa7800e1,0x0001033ba0bb0ce3,0x0000000000000001}, {0x000cb2552f015a84,0x000cdab20301de3c,0x000af7c3af2c8c0d,0x000fe99606c79c8a,0x000d638fb52847ee,0x0009bf56737cb586,0x00000b1ec4f260f5,0x000362ff887d36f2,0x000ed3b693913291,0x0006e3c40f0d7ae5,0x0000000000000000}}, {{0x0008a516e5648dad,0x00047202a3fb8a9d,0x000ecb3edff5fedd,0x000220d17fb9838f,0x000dc8b9ac40f762,0x0009a8311e23ad98,0x00084edfb615d6c5,0x0004e6c85dc486c7,0x000bf81a7ee5f8f8,0x000ecc58d5bb866b,0x0000000000000001}, {0x000d41ef176fcfa3,0x00078f007acce1a1,0x000d8b8126b20e97,0x000a71b3438944de,0x000134e76c73c437,0x0004a56abd9a1b4b,0x000de8db7385f9b1,0x00043115d58229b4,0x00034725891b4078,0x000c55ba8c32f815,0x0000000000000000}}, {{0x0008e051939a3b7d,0x00010361ba38d482,0x0009c9a686091017,0x00050f6456db6700,0x00031ba66d450ac6,0x000e0bdd4225b759,0x0006e52d315738bc,0x000d21403d74797c,0x000a041eb53ed58e,0x0002f948ee60c564,0x0000000000000001}, {0x00014e408d1cd601,0x000cfebde9152461,0x0004123bd5f4532c,0x00083ab7b9fe9b7a,0x0009704a01b31e49,0x00040d9c79a4402d,0x0009ff5b8e0a168a,0x00048d442aea1790,0x0001410d782cc3c0,0x0002bf2d98ba10cb,0x0000000000000000}}, {{0x000943818d1af858,0x0005d42684f68399,0x00068a5f9139d27b,0x000d03a1a3ed9c84,0x00024e699de7f9f9,0x000ddd7e41e31174,0x00089cc967769d86,0x000a0e9e00b5f6fd,0x0007b63934a6926e,0x00011c5b068a8b3d,0x0000000000000001}, {0x0007d21cfa86aa41,0x000f529a2aecb429,0x000251f8677cf147,0x000bad3bd2a35774,0x00090bedc57bbf0b,0x000a31f1dbfe5b37,0x0001e75b3cb7422a,0x0006476bcd9901bb,0x000278bd8b31cdbf,0x00082a6fb171258c,0x0000000000000000}}, {{0x0009d9b88bd44811,0x00086c7bafe985de,0x000eb018e7fc2f20,0x00037a5b53cb3738,0x0000a097f28e364d,0x0000b5541e546ab4,0x000530e972bd2ec0,0x000b65a95e020994,0x000221ddc10db4cf,0x000295000b94fc68,0x0000000000000000}, {0x0006ace5e2ed6000,0x0008ffd606613047,0x0002a24af3b853da,0x000aba583e1b87cd,0x0004618719533717,0x000d61f56ae2be40,0x00025ef5e9069ea8,0x000f94027fe98e78,0x000db6fc7d9c1583,0x00075271696c0d71,0x0000000000000001}}, {{0x000f12734c3ec92d,0x0002bb3d48fbed19,0x00049bdd26ff69ad,0x000fbf26985b989b,0x000ad451c21eb61b,0x000237a30e35f12c,0x000a3b3680a082df,0x000188ebe4c92751,0x00087a8fbc731694,0x000b03a8bdfe9408,0x0000000000000001}, {0x0006f89f4e0d5883,0x000d80de19c8b935,0x00077afef27eab9c,0x000538f8f941390d,0x0002b8c79f62a16f,0x0004a907ee9a2c1a,0x000951eb7aa5d968,0x0001fe7d75aa9877,0x0007b983b59fbafe,0x0002bab437db42c1,0x0000000000000001}}, {{0x000bf512d363aeb8,0x000e0db50c6d9411,0x0000e1101f753fc2,0x0006d62a0ded1b7d,0x0004a1ec0fcb3b8e,0x0000a9719f9cb02e,0x000fa60331be1189,0x000525c569643656,0x00081aa5691f4f2d,0x000a963a9ea530b1,0x0000000000000000}, {0x000098b88fd83f01,0x0009e9aed5969329,0x000769c1597dbeae,0x0003f34dc1aadb7c,0x0006d041d0f773cd,0x000dcc7a18555ae3,0x00057b66cab6672b,0x000c3dbd797513fa,0x000ec420f27eb3f3,0x0003c62ce13b7853,0x0000000000000000}}, {{0x00057f7ec577ceaf,0x0009584ce56b583a,0x000ce15377e1306d,0x0005b26b1e23a49b,0x000f42d98c317bad,0x000c523283ae8b11,0x00081ddf50073f0d,0x0004ab516099e7af,0x00029299e519277c,0x000c0d8cb7cfdd6a,0x0000000000000001}, {0x00029a85f4a1c822,0x000b7e9213cb42ad,0x000364e5e4a37030,0x000a3941f8a54d03,0x00050b7d507ec771,0x000db1def4d6f8ad,0x000eab3bd493bf4d,0x0009716822a9c65e,0x0005d463b7e2f601,0x000728062fa75d1d,0x0000000000000000}}, }, {/* digit=42 [{1,2,3,..,}]*([2^168]*G) */ {{0x0002ee214ad0e3d6,0x000d51de6a66c4a4,0x000c1ce94446c6c7,0x000c0d5dd2eee21b,0x000e88f8f4a8deaa,0x00055296fd5914a3,0x000dd876c3945207,0x00083798ebb4e647,0x000fd6484696a7a6,0x0001d866ec9d8ec9,0x0000000000000001}, {0x000ca34e120495f9,0x00050701e46446f4,0x0004431e6d90fc27,0x0006b7610b310d40,0x00086e5199614976,0x000e7e80f704e266,0x000aa764f7efe74a,0x0003d9535c6d9829,0x0005a23c25702e18,0x0000a0457bd92a75,0x0000000000000001}}, {{0x0009cf085024c2f1,0x000c0aff178cc9fb,0x000cd1f6670717cd,0x000588548870fa8c,0x0001a99c44c6bc4d,0x0007a4c31ed62743,0x000f88c552f232dd,0x0008940140f085da,0x000a8211a1d88681,0x00041216e4c1b09a,0x0000000000000001}, {0x0006cac59e6c3159,0x0000ba3374279c4b,0x0008991eda2c878a,0x0003b4cf84ea0b3f,0x000025e729a3932e,0x00047222c0cc5f31,0x000ba94b4346c5bd,0x000e2995032ec5c9,0x000db493f41a4bab,0x00024e7b6e042b7d,0x0000000000000000}}, {{0x000aefc5789d3eda,0x000070117b5af24b,0x000a5c6b9c3050d4,0x000dbfc9621085b7,0x0006f4c0b7973deb,0x00006f6cf4b4e834,0x000082f092a35673,0x0002d877db7b37b4,0x000c2eac8682b506,0x000eac10f86afedc,0x0000000000000000}, {0x0002caf651b8b0a4,0x0008310eef2a1934,0x00026025b8808ec6,0x000dcff1e64f055a,0x000a67192e09ae5e,0x000d785482258125,0x0007daa7d24e92c4,0x000a9c45e5162876,0x000fc7c72fb7aba4,0x000522976bb5f88c,0x0000000000000001}}, {{0x000921c0f982798b,0x0001a2079475b7fe,0x000ea0fd52e410ea,0x000e44af77d4bbcb,0x0001f260a54b0212,0x000269af2ec66a7d,0x00034794993bda84,0x00050b15e358d04f,0x00067a4d30bdfadc,0x000e912250ea3d1c,0x0000000000000001}, {0x00083de4fe7bebfa,0x0004fdfb63579e27,0x0001abe0cbad5ac8,0x000820014b8a145c,0x000a85d987c51840,0x0009eba9aacfadab,0x000291af5fccfd5d,0x000785e551a982de,0x0002bcee4372c455,0x00049c9d89842d5e,0x0000000000000001}}, {{0x0000817678d00826,0x0003072fc12b3906,0x000fabe24fd4868f,0x000b2a4f9e0b8813,0x000ccd87b27441cf,0x000e7fd0a48234db,0x000ea747d9a2a9fe,0x000c91ba0d4add56,0x000c9d0dd2d3e7c8,0x00005660e4fd17f4,0x0000000000000000}, {0x000a904f88c1be1b,0x000e5cce4c6964ff,0x0005fb6194a74952,0x0000f033d222444b,0x0008c26fbb11965c,0x00055ed1ac1d1bab,0x00020c09d970630d,0x00075b608324cefd,0x00050cf259835d15,0x000462cd49bc1143,0x0000000000000001}}, {{0x000b46239d54de36,0x00013af2871bf6df,0x000bb6d9f31a1b7c,0x000528b0f5b2569d,0x0006b9497778a81b,0x000c963043af6788,0x0003bf9954a12672,0x00059feeec8df36a,0x000d60c22b5fdead,0x00060d265f0f8b6f,0x0000000000000001}, {0x00050d0b6534b1ea,0x000703b71e08797c,0x000d2bd35e284a7c,0x000105aa68827a45,0x000902245c12e4ca,0x000f1afdb8eeeba0,0x000caa7693b8db6c,0x000824a39f45018e,0x000945d0c9d12756,0x00055f86289ff82e,0x0000000000000000}}, {{0x000f246813a5e2f3,0x0004d2dd1bc96870,0x0005743352958a8b,0x00007a9386d4a79c,0x0008b4a29091d043,0x00059ba9e47bd2da,0x000478de8a606e11,0x0008c9f2a8c27ae1,0x0002946224c1c93c,0x0003ef3adcff2ded,0x0000000000000001}, {0x0005100b79546483,0x000ac268f6c48348,0x000e4b2ec17a54ad,0x000f85818d6815bf,0x0004f425318546e1,0x00013cbacecaadf3,0x0006d908fa2a9c92,0x000e8808196d6c46,0x000ad801f4a291fd,0x000b7ecba0623fa6,0x0000000000000000}}, {{0x0007b0f39088ef39,0x000a435ae74e03d1,0x000fbdcdaf3b17b1,0x00090868e5084910,0x000019102285b63c,0x0005454d88d8e63c,0x0009e2380d185fed,0x000af9e19dfe50f9,0x0008e09d7ce8d3eb,0x0000155127749872,0x0000000000000000}, {0x0007fda1b031ef4b,0x000dfd7188feeb77,0x0006801e0f6f597f,0x000e9d1729652f82,0x0009d58dec034252,0x0003cc68d0c6aa0c,0x000a4e76779b37e4,0x00008d509f569c62,0x0000c41330558ca7,0x00056956b5657bd9,0x0000000000000000}}, }, {/* digit=43 [{1,2,3,..,}]*([2^172]*G) */ {{0x0009008a556937c2,0x000f76241f10378e,0x0004e7ecf0092193,0x00097f48f8905d70,0x000c86b4870ad280,0x000f86eb6f389aca,0x0003ffbc3b9a3132,0x000a9c6b9598fe5a,0x000429f1014fb463,0x000e06408908552f,0x0000000000000000}, {0x0000c94ae41024de,0x000a6dd0399afa53,0x0007da5ef17ac70c,0x00080b49854eb299,0x000104afd62b1e2c,0x0000b1375777d7cf,0x000794db8dbecfef,0x000ff21b1b05dfbd,0x000f1e68e47404db,0x00080928abdaf296,0x0000000000000001}}, {{0x0001636898bf4d11,0x000fb75ab01bffaa,0x000ba4b1f3e58bf7,0x00059cab50bc67e3,0x0008acea4689ce8b,0x000f1932a30d30cf,0x0006e5cb3d1d8eda,0x0005fa7949e492c0,0x00041db2db16d8b2,0x000b0610d851b96f,0x0000000000000001}, {0x00054a2b36667691,0x000ca196d36fe2b1,0x000766e2a6109d47,0x000f9263f1863dba,0x0003be92b5a5ba8e,0x000aad9918a5da16,0x0009189520c8298c,0x00010a27963af5e7,0x000b8c3b84ab05f9,0x0007bafd0103c420,0x0000000000000000}}, {{0x000e3e45f8d73683,0x000eb8ebb6d11caa,0x0000f274ee508fde,0x00020c83562c576b,0x0008510e47baeee6,0x00079b810588c571,0x000894a919ff42e2,0x00007edf259b927c,0x0009d16a223100a0,0x000a5b2acb9ccb16,0x0000000000000001}, {0x000e8415a9179d06,0x0004b594d74f07fe,0x0004fb6e0e5cacca,0x000788b708cc549b,0x000c0c62edae508e,0x000b9ef886c2847d,0x000e40664c8eee69,0x0003ed24b57a9dee,0x0002b9d44a547432,0x000a6f16f12261ca,0x0000000000000001}}, {{0x0005496bc42e6e51,0x000d33d320585033,0x000cf402bd388067,0x0003e6730074be0b,0x00043e8db4e94291,0x000f7beef462a0cb,0x000e58a8c2ead81c,0x000b97eccd5df06d,0x0005954e3501f23b,0x0004b4a8b8e4e11d,0x0000000000000000}, {0x000598c1e025da1b,0x000b09bf9648fc1d,0x000d224f8ad9987c,0x00065a60d88fba1f,0x00054d86a1d9f606,0x0006c4ad1df1e7f7,0x000e1da4acf77f72,0x0000938971a27713,0x0007fc94e0f78da1,0x00083992811d7d3b,0x0000000000000000}}, {{0x000c9cc6dd4a5914,0x000862d80be96443,0x00008c7a249fd0f7,0x0001ea54a0d2c9f8,0x00048d9e55013f6b,0x0007ab76e8d002ac,0x000cbf4462d73cac,0x000faf5cdb58c492,0x000ca322b819e5c1,0x000b840745406425,0x0000000000000001}, {0x0005f739a14940b4,0x00097d20ee2a886c,0x00035ab04c341a53,0x000f7a9d2904ba7b,0x000d9cae762f47f9,0x00007d2eaeeeb5be,0x00070ab079042e0b,0x00060a339ed63e5f,0x000c7b9658ba8e43,0x0002d18d85499745,0x0000000000000001}}, {{0x000b401e3813737f,0x000ff61118cf0239,0x000909b65cbad1c8,0x000da081fe099573,0x00028cfc70caa9fc,0x0002bfc31062db69,0x000e85af4aac9c83,0x000ba3d1d4e51a7e,0x000363dd1405fca7,0x0009117097ec2370,0x0000000000000001}, {0x00065c78edf4f376,0x000f36321b45daed,0x0003283085bc71ee,0x00018a85f5b5aa08,0x00055758f2c2f181,0x0001623497212c90,0x0006ecdfee014f92,0x0000a48aadb790d1,0x000881e12f4528d4,0x0004482acaa286a1,0x0000000000000000}}, {{0x00050bbeb7940a25,0x000eb62b0dec1d2e,0x000f7146dd0fa42c,0x00051beef911c829,0x0009947cccb28e02,0x0009505362c5e903,0x000767ef06d55451,0x0003dcda2ee6b16e,0x000b2373652d7be8,0x000cb5af116c86d2,0x0000000000000001}, {0x000d36b874b6449e,0x0002d7bb963c1def,0x000de8609229e57d,0x000375fd0ce127b2,0x000b5890dc213b70,0x000a1d88db3c82d4,0x0007b583b09ebdc9,0x000cc6b137b10089,0x000cf29a5fc13efd,0x0001907605ca17a3,0x0000000000000001}}, {{0x000665e2bbfdb04a,0x00017e4232c5cb5c,0x00026232f5f9a245,0x0007a0275981cd79,0x0005ae253d4d80a2,0x0006c00bb7783b1d,0x0004c2589b5ab0bd,0x000f6c48caf740ea,0x00082e177fc5351c,0x0000fd2b0e714ba4,0x0000000000000000}, {0x00052b5ad6ac73dd,0x0007a311881ba785,0x0004ccac10cfb206,0x0003dcbe5d449097,0x0008b8873accd901,0x00080d70e5b2cf2a,0x000440b2c2817333,0x00067c3b711d4631,0x000b996623747bc6,0x000383423c70b2d6,0x0000000000000001}}, }, {/* digit=44 [{1,2,3,..,}]*([2^176]*G) */ {{0x000b11d1789dc869,0x00016c2eed227fa8,0x000916842cb7fd9a,0x0008564ce12a5d02,0x000bee59ed474675,0x000e675f354b48f9,0x0005d69ece126be8,0x00018ce3aca2f7c7,0x000768d6000f88d2,0x00090f26ea6ff29a,0x0000000000000000}, {0x00096ef4ce69e270,0x000f2da0efb2f05d,0x000a99dc276ac3a2,0x000e0342757c443d,0x0003b390d2a5e23c,0x000e7ea78e9b674e,0x00085e132e72b987,0x0006b6c21856dca4,0x0005bed8cda17d0d,0x000237220788bdee,0x0000000000000001}}, {{0x0002364996ca25a6,0x0007ec8d70cd440e,0x000d8467c5161afc,0x000408724c9aa882,0x000b962a215cbbc1,0x000c4986c1ad6d3c,0x0001332912aaf7a6,0x000d6db2702d8369,0x000a17e017d4a1ec,0x000f2dbf2405e93f,0x0000000000000000}, {0x0000641168090c5e,0x0006fce42ae3e68a,0x00039938713395b0,0x000394a15bb1098f,0x000db97734c1bca3,0x000edfc62ae8c0be,0x000bc2f9b0452cb1,0x000304c79c90c661,0x0000dada4e625332,0x0006fc2e4ae4342a,0x0000000000000000}}, {{0x0001bd7fc156252b,0x0000ddb25b337fb0,0x000ac5d025ae1e66,0x000c26056a73c379,0x00095dede6af2b69,0x0001ae9121b7e81b,0x000754f6cd030d2a,0x0008b47d1e9a5f7f,0x00025d238c9b7c0f,0x000d32d6fa902ce9,0x0000000000000000}, {0x0005ace423d94184,0x00056f6ab6a655f9,0x0008fa78d47709a3,0x0003f5d39d32f258,0x000beab0a90b8c58,0x000bc517995d68b6,0x000ea4acae9d65d8,0x000fd569fb104a80,0x000b09db02cb3b12,0x000c624b3e1e5f67,0x0000000000000000}}, {{0x00093cbca6dca0b6,0x0004a2146559221e,0x0006c357ebc20032,0x000e73dafbe29569,0x00073f1c77b70537,0x0002b0a8e959d415,0x00055d9c50a71dc1,0x00037c9b3656d184,0x000283b617fcbc17,0x0000976acf8093d9,0x0000000000000000}, {0x0008b573715b4734,0x000173f0027024fa,0x000386bfccf3b38a,0x00095480bbc99c54,0x000668bfbf241bdb,0x000353dffbcc88d5,0x000216b7968e8858,0x000de22f661faa2a,0x000189437f0cc373,0x000c1f5601679c0c,0x0000000000000001}}, {{0x000a86967182c501,0x0001f634e40148fc,0x0001c864ffbfa398,0x0009d6d142879632,0x000443e4b6047507,0x000e1e5a879eef57,0x000d2b8fd7f7f136,0x000d19b6378838d5,0x0007815ed1c2726d,0x00042ef17abcb4c1,0x0000000000000000}, {0x000b9a5999895b25,0x000be140e558227b,0x0007f28ae923d146,0x000d00a58852f582,0x0000e60ada16c8cd,0x000158a85a7def11,0x000e5c61d1152d28,0x000d4be61bf1a55a,0x000cf413c0a31606,0x000b3cd625cdfd8f,0x0000000000000001}}, {{0x0003f2f8ccce2027,0x000fd5cd45c4a564,0x000a6b2411224a0a,0x0007a5ca2258c4c8,0x000678f855fedfa8,0x00055199f43975cb,0x000e9a39edc6298c,0x00007312684e5a48,0x000adaeb9f55daba,0x000b39c9f5f377bf,0x0000000000000001}, {0x0003e0968382a7ce,0x000869c70ffd115a,0x000ba001f2afcccb,0x000107bdfe8068fd,0x0000206868f7c124,0x000821a90928b9fe,0x000afc533728dac3,0x000b3e9edff0ac94,0x000d10c697f67565,0x000bea250773ba0b,0x0000000000000001}}, {{0x000275a2c8f91400,0x000bb4c241f78224,0x000c4fd93b4ba60f,0x0002941b616268c1,0x00020107f7964087,0x00031b438825e04f,0x00019247786625f8,0x00028de20083c5f6,0x000abde39791c6d5,0x000b3b75c25ecfb0,0x0000000000000001}, {0x0008e09f47b9d8c3,0x0009374c6bc5ceb5,0x00038e27941b3112,0x000e3235cee2666e,0x000ea8dbee896ca0,0x00030660009b498d,0x0005f8f0f2897645,0x0000fb5ee44458ff,0x000fb559aa7b5e14,0x000272ac85e138f9,0x0000000000000000}}, {{0x0009f0c6193905a5,0x00013e99256667bb,0x00027fdbbfc34892,0x0000d2c71218ca33,0x000915a83f00e563,0x000d628331bdc8df,0x0003e8128ee96b80,0x00016a5f7e06bfe7,0x00016364a2a7cd33,0x000c748cd2a08bdd,0x0000000000000001}, {0x0001d90fa51d3800,0x00020c814ecb8822,0x00000fc79208b5df,0x000f252076343a10,0x0008a14b68032c99,0x00054fe0dc71413b,0x000d97c9a173cb46,0x000c85a386e9a9ac,0x000bf160a14a40bf,0x000032849e997087,0x0000000000000001}}, }, {/* digit=45 [{1,2,3,..,}]*([2^180]*G) */ {{0x000384b0dc2ffbb2,0x000e0c16c289b477,0x0009eabe48cf9601,0x000199d671ddca51,0x0006f3fce7863b3f,0x000e01be3ea3ecba,0x000b70167c58c7d2,0x000f4893679afbf4,0x00019a4362cb78d1,0x00061515a3d7fee0,0x0000000000000000}, {0x000f2840f746e722,0x0002ef160c51fc25,0x00097156a16516e7,0x000e8398d9625db3,0x000d63f5b2c0ebf6,0x000c5b6523651404,0x000476dd10c4d87f,0x0001f40ffa318eef,0x000788025e5d3977,0x0003c298fa2547e3,0x0000000000000000}}, {{0x000523e81658a625,0x000aef8e050759b2,0x000b0377d5042659,0x000b9ae72b36823c,0x0007eff957169419,0x0009705cebf46fc1,0x000bd18b61ce7ad5,0x0007a7135b602fff,0x000f2e092fe9192a,0x00074d30a3a8e596,0x0000000000000000}, {0x0007c895ead96751,0x0006523da4889766,0x000467afe86eb732,0x000a5ee25b7a7cf8,0x00000f2568e46393,0x00079a3304b15dd0,0x00036bd203f1569b,0x0009a5e938c0d91a,0x0001da1271a34645,0x0004c688c575bf52,0x0000000000000000}}, {{0x000c62a6b633bf04,0x0003c0eaef0121c8,0x00058d7354098cc5,0x000448cc925273a9,0x0006f73c56bf4c04,0x00042b800bc52be4,0x0008d6b39147d475,0x000444cb5cfe3029,0x000d4247fb2312e0,0x0007054c4d89dd9e,0x0000000000000001}, {0x0000edd6a97a9163,0x000582ed4f4d5b46,0x000b9ca61309206a,0x000fafa93e18c6dd,0x000bda68f9bb8a3e,0x00070a52c8b2d783,0x0007728c0dda564b,0x000c0dc789e7dbe4,0x000119aa3e8a6481,0x000bed27f421a4e4,0x0000000000000001}}, {{0x00001ee133405081,0x000b94055dadf3f3,0x0008803374bd3d6a,0x0000e431a078817f,0x0000ae1298465c73,0x000a08da98aae817,0x00076bc8b779119b,0x000c1b8f7410f128,0x000bc98dcbe46247,0x0001761805980867,0x0000000000000001}, {0x0009de67dab5cae2,0x0003d2d0125b70f5,0x0008c5ad3a01682d,0x000cf59a9c7c1b26,0x000ada095cf6362f,0x000b79b1ed6482c8,0x0002b3bc253c84e5,0x000756917d1dd695,0x0008f439fdfad9c3,0x000651a63232aa5c,0x0000000000000000}}, {{0x0003a055275e1f13,0x000bce620ca4b51f,0x000765c9fcc48133,0x000387e5710e23a7,0x00041d9c294797a6,0x000fe4eedda6621b,0x0009f733bf9d9ac9,0x000e4cb8a3045df1,0x000d5c96c4f51d70,0x00041a25c50ad245,0x0000000000000000}, {0x000acd86687a04f6,0x0009bc4b6a5c45b3,0x0003f85a2b09f7d1,0x000f69420758494b,0x0007e554c9337d50,0x000ccb9c2f40c240,0x000e482c5dfc1a60,0x00016ad44e8b11e7,0x000d080e60fea531,0x0001889fd549f4ed,0x0000000000000001}}, {{0x0007e29c5ef5cdd9,0x00046b2b2e558b7e,0x0004702314f3e6bc,0x00026fae56eeaa30,0x000145ca44a1b067,0x000ea8da792ee6f2,0x0007e4c829cf9680,0x000d723cb279141e,0x000c514c645b326c,0x000b3d5e8e8931da,0x0000000000000001}, {0x000e5ed0862bd48f,0x0009404a34e74e61,0x000e1d4a98483644,0x000f45001f65c56b,0x0008e062ee7183e5,0x000a39ef75aa764b,0x000f4509012ed646,0x000742837f0ebdde,0x0009ab588faa786a,0x0008d7474accf0f8,0x0000000000000001}}, {{0x000f31aa7add26e0,0x000b5f70683b341e,0x0002190eb5f5ed33,0x000e3b2bf3278604,0x0002cdb29e4008f6,0x00042f0700c911a6,0x000f5e3688f5189d,0x0007c2de5c257eff,0x00089c193e2d4667,0x000cca5de47c9861,0x0000000000000001}, {0x000dddac10383cca,0x000803caddccaca7,0x0000778df17cf555,0x0009278c5faf93e7,0x0000e7cfbb523b02,0x0003ef004ba7546c,0x0007290d52d052d3,0x000f54a34c36c895,0x000e1b89dcc555fa,0x00058777136cbca3,0x0000000000000001}}, {{0x00060b5ef6c20e82,0x000bf430fe1ead47,0x0003a480e70d1479,0x00097c0aba684ec7,0x000549990971954c,0x000a1c5645d306cb,0x000cc85cc5c264ce,0x000739efac323d9e,0x0003b20c4465cbfa,0x000b4ee9cad749e6,0x0000000000000000}, {0x000242934808827e,0x0008a9860bc18213,0x0007a452bdb41b29,0x0006c3f651ceda44,0x000f153ca2965078,0x000e0cd8cc7845a5,0x000c9cd5913baf87,0x00050312de2e060b,0x000a1444279bfb31,0x000ff8a16f8265f7,0x0000000000000000}}, }, {/* digit=46 [{1,2,3,..,}]*([2^184]*G) */ {{0x00033bcc8924eb55,0x0002e9d518ffb740,0x0001ae0cd732da2c,0x000cfbc19a4290d6,0x000d8784c1f06357,0x000fe209893ca1ae,0x000969a85a8dedb3,0x0009c8eb2e932f87,0x000bcc740550ff52,0x0004f554bf85aafb,0x0000000000000000}, {0x000bc6372d7f8438,0x000dc0557f4f2ed5,0x0009d0c30f3c2efb,0x000ddabb262ac2fc,0x000f7a05b87d4d5d,0x000c91e745769d1c,0x0008c994d0a4907f,0x000889250072dcd3,0x000ffae1ac453a28,0x0002a8e72458000d,0x0000000000000000}}, {{0x000d9177fbc76a5c,0x0003975e3cbf7406,0x0002f09def039ed5,0x00034da80caf736f,0x0008efcc790febc5,0x0000ad47e746448c,0x0001ca336b92fa7b,0x000b90e92c64c767,0x000dfd8d6637080a,0x00032f5711517b52,0x0000000000000001}, {0x000a0257ff4a1581,0x000bc02441238656,0x000364971ed77234,0x0008b1d09b2d316f,0x000bfdf4ae5e00cc,0x000468fa8d307856,0x000805be3791c041,0x0003fa589236fc69,0x000a337620c1fe73,0x0001e737b5760989,0x0000000000000001}}, {{0x000e1990ae2c44bd,0x00083ee2175b6a29,0x00005d1fb5989698,0x0001375eaf1c4bd3,0x0009f54aec5725cd,0x00017c1f0f7d222f,0x000f9f96b74e2d73,0x00053fff253f88e6,0x000b31a11aea1b12,0x000aa32748b4a307,0x0000000000000001}, {0x00007b074c7b461c,0x000258e6e4224b52,0x000162fc7af983c9,0x0004966825052f5a,0x000f9138a0346a4a,0x000a7041242b7952,0x0000a366f5699476,0x000460c88c7d5eb7,0x0003f2b3125e31d3,0x0002a892d14ada09,0x0000000000000000}}, {{0x00001e6a21a7b432,0x000c3971b4886b8a,0x000dae7cb7883120,0x00059d28f3efe6ce,0x00028e1699713fd6,0x000252af65756250,0x0002a3acd7c4a210,0x000f7efc9c5a81fe,0x000e2a5f82fab4ec,0x0005c0924441558a,0x0000000000000001}, {0x000495dd493563c9,0x000ccadf9b0e7295,0x000ab5a8f70bb0fa,0x0005b32501ed29d2,0x00036f439adfe6b6,0x0000a6c7202e9c24,0x0006531bcd403e24,0x00064526a2b69777,0x0001dc2d590cd125,0x000b64170acdcfa6,0x0000000000000000}}, {{0x000b0bb5e03ac48f,0x0009bb5837030273,0x000a05cded5e6ec1,0x0008034dce79ed12,0x0000fc54532094d5,0x0008fcc6c534a769,0x000bca87d8be0fee,0x00041150d981f9e6,0x000222345254c456,0x000b2aa496b6e112,0x0000000000000001}, {0x000d2c8de5bb7e5b,0x000278f0be2794e5,0x0001b31bbb57b1c7,0x00001958330187ab,0x000f5dd751abf9bc,0x0002de4b57d090a0,0x0009cb74fbe565f2,0x000f83e310b95170,0x000d1301cd0ee2f4,0x00049fd2006501c7,0x0000000000000000}}, {{0x000e8d883bcef9f8,0x000be3770de7cc8b,0x00007c65e3e95107,0x000ac96f780e3eca,0x000413d615089cf6,0x000585b5b22549b6,0x0008b5facd5da79f,0x000f3c8b5c5a4c0d,0x000d6dfaa970b49f,0x00065cc025c0e7ad,0x0000000000000000}, {0x0003c64dd34154da,0x000343c797b7cd0b,0x0001f367813bc308,0x000fbf3f138ae118,0x0006f1f8c6302e7b,0x000f35ea2ee3cc54,0x0003a0b904ac34ee,0x00052596f106852c,0x0006e533ab1310ec,0x000abf763b19381e,0x0000000000000000}}, {{0x000d9a73e24c887c,0x000707461d095f01,0x0005d3ad552ce968,0x000f402b6c527f5f,0x000818672d6016b3,0x000279bc4633dd66,0x0000c571c90fed28,0x000cee78b5512020,0x00048d6ae97b4812,0x00055292fa8b91d9,0x0000000000000000}, {0x0004608b8c1577cc,0x00058615049c4716,0x00077fa05c3b187a,0x0000d33110dc1846,0x000554a923122c03,0x00015b3d3cf40b2d,0x0005e05a3843c4de,0x0006438408a6964a,0x0005f646af7c591a,0x000ae89a0f7132ab,0x0000000000000000}}, {{0x000b5e462dd556b6,0x000f3aab5e9c2f29,0x00040c3ae00c87a1,0x000aade98fdfc7cb,0x000f2f671ec86f72,0x00069dd7b2aa376f,0x000b6f90c4b07483,0x000ae5c39e831a9e,0x000ef6929b8bdb31,0x0007125a4c5224c9,0x0000000000000000}, {0x00080ab908d10b8d,0x000b7c8a32a9943d,0x00051b7d4fd0edbb,0x0008eaa89eb83ad0,0x000fb343de0ebbe0,0x000d3c4d0cc33cc9,0x000b15124b0953fa,0x0007582773fc9c30,0x000ab2c193a021a4,0x000b73ddfb881675,0x0000000000000000}}, }, {/* digit=47 [{1,2,3,..,}]*([2^188]*G) */ {{0x000f014ad29ca649,0x00075a10e7e9c3d6,0x000042dda6a91edf,0x00069276fbe9047f,0x0005a497f91416df,0x000b982ab7fce403,0x000b8b61e6adadfa,0x000d218a9fd9d973,0x0001c8c04e2c23f1,0x000cb12274d47d9e,0x0000000000000000}, {0x0000ec3de397b98a,0x000d9a272cecd709,0x00050e492db6d724,0x00082a50e32d2f19,0x000db6bf40e9c68f,0x000b25727f0678af,0x0007a36e6ae78194,0x000cbb096d1806b7,0x0001afd3feedfa35,0x000e57c17d9b9ff4,0x0000000000000001}}, {{0x00078e57ab05c549,0x00081a123d2b219f,0x000ecb0183ca3cf9,0x0008ed9f1eddfd07,0x0002f8f90e3c6699,0x000ad41bb20e0515,0x00019c77dab5c5ef,0x0002ca7830069394,0x000ae5cd1de605b3,0x0003933d6039cc98,0x0000000000000001}, {0x0000ae5b05bb2b74,0x00071168c4bf8259,0x00001a66f3efdf4f,0x000e1da4a65b0015,0x000ba0665dbdf241,0x00015f360d4c3387,0x0004e85c88fe301f,0x000c061a8e048acf,0x000bcc0119ca9957,0x0009ea8585dfcf51,0x0000000000000001}}, {{0x000c2a4869f8ca68,0x0005748af64adfdd,0x00044c661ce61bf4,0x000fa33532bda5e6,0x0004409ebd1c4df9,0x00063b107af0f45d,0x00013ef2dc8804b9,0x000a186c6c3f3d75,0x0005a7ed73f6b67c,0x0000b525bc5b72fc,0x0000000000000001}, {0x00008fa0f93430b8,0x000bf3cdf63616c2,0x000a2ed8b79415ed,0x00008df169f3be1c,0x00006a9b7669442a,0x000be581a2acda6a,0x00093d2dae365779,0x0006ea987608134d,0x00059b31b3052589,0x000d8078ebfe0716,0x0000000000000000}}, {{0x000a0e4faa59f069,0x000d33d96e52e437,0x00029f2632f3aebd,0x0000c85e4fd15682,0x000de4f3be7892c7,0x0007d9fb180a1634,0x000b175638b44c2c,0x0002e33499b53e6c,0x000cdad290b60dc3,0x0009d1cf1fcbab2e,0x0000000000000001}, {0x0001854cefb1da9f,0x000257b5b7539f5d,0x00096df1240b9d47,0x000f9e9a561ffc72,0x0000d6d9452715e9,0x0005aea9109f0df3,0x0005d521e814b452,0x000c7037d6e74c47,0x00060afbb2239aca,0x000dfe3a178a1e6b,0x0000000000000001}}, {{0x00085fac7aac5d24,0x000e6efcd816f4de,0x00001aa65b85ec90,0x00042ef288a94272,0x000527aa3e5baff2,0x0002c225dbf973aa,0x00073237d80e262e,0x000ac84d268b446c,0x0000056980d17882,0x000089041c6047c7,0x0000000000000001}, {0x000f5b36106ae92d,0x000b658d82ab92e5,0x00036754a0792779,0x00032fae5cee6721,0x000bd0394c90fe6b,0x0001825f86d43336,0x000fa2e7d57eb880,0x00022294f3c7cd21,0x00070bb4a5b81f76,0x000e5c797152fbf7,0x0000000000000001}}, {{0x000d4560b8c46ee0,0x000b73ca40a188f7,0x000b593661397fde,0x00026cffd18ba8cc,0x000c47a735170abd,0x0002887e49a94d3e,0x0002a2ec01caeb9b,0x0007426e36269901,0x000522aa9c52b5bf,0x00066af9e1ef518f,0x0000000000000001}, {0x000d742afa309fe0,0x0006f810d9df60b6,0x000084e739c300f5,0x00056da63d1a036a,0x000cd4f33c2df42f,0x0000b456fee1f0f2,0x0008f569e5589fab,0x00062492c9b09b89,0x000079adb7885960,0x000cf412b618c75e,0x0000000000000000}}, {{0x000e60d6e9faeb2f,0x000298054778495c,0x0000f99d00d5919a,0x00052dad049c1204,0x000e8b4f342e902f,0x000c225bd4b3fa2a,0x0004f48aaba21576,0x0009d33ad4b48b96,0x000a24fa9d5b26df,0x000f2799a4fd763d,0x0000000000000001}, {0x00017650a566263d,0x000e25ee8cfe1893,0x000763623662e408,0x000a4360ad7e6d05,0x0000ba65a8e233ee,0x000338261baaa5ea,0x000af51b8dde194d,0x000003aaa23ac37d,0x000ab55391298a43,0x0008f52d2a4172a8,0x0000000000000000}}, {{0x000760e887bee904,0x0009f91c8cff613a,0x0003af1d33766225,0x0002f55a798ee44c,0x0002c7171b76304c,0x00051b89de6b4202,0x000754ce995dc454,0x000a5d7e90f40166,0x00037fe2c45f5e9e,0x000d835f81a1be14,0x0000000000000001}, {0x000c04a7dafbcd8e,0x0007d22e0b1aaf34,0x000ad92815662ecd,0x000b88ed3ef4d947,0x0000190778cccdc8,0x000ea32bf7d0a755,0x00094ed615d6df41,0x00066cdce7de3703,0x0005d94b6a5a2d85,0x000869b1500a755b,0x0000000000000001}}, }, {/* digit=48 [{1,2,3,..,}]*([2^192]*G) */ {{0x000556d5fcb0ca3e,0x000bb40eb6f5de7b,0x00092b00751e1fef,0x000d985badf10d77,0x000bda78c0fd8245,0x00097cec621ec6c5,0x0009de36f6534761,0x000929578b20f59e,0x00008129148b6a34,0x000260858df1e4dd,0x0000000000000001}, {0x0002df7b80140bb6,0x000f0872cf54b64a,0x0005ba02c9e702cc,0x0006a4694fa2136f,0x000ae62ca46c9431,0x000a69d6c72a601f,0x000ff0af210ce686,0x000a108647e23ca9,0x00072d54b7301dc8,0x000b4fc0d011e4bc,0x0000000000000001}}, {{0x000c2c9272139ecb,0x0008248890056b04,0x000319a82e4c5944,0x000bd6a55d37d95b,0x00074d80dfb735a8,0x000b368732a7edec,0x000dbb960fac47dd,0x0009b7d149244f46,0x0005c8153e4ae15b,0x000dd7d6f5637025,0x0000000000000000}, {0x00023077c37f59fa,0x000e01c814ef1183,0x000d2dfe1b52b965,0x000d66c5cad600e8,0x00064cd44f8d02cd,0x000b170f04ad1f49,0x000b95d6b03da74b,0x0009721ac42809f8,0x0003fd08dc3ee705,0x0005bd69cd062aab,0x0000000000000001}}, {{0x000b883d845a0ae0,0x000afbae353f2a2f,0x000473d0adeb61aa,0x00037ae3890f51bd,0x000480f0c4103d1b,0x000087e22deca493,0x000ae96c669a58f0,0x0000d7ec27b93462,0x0005f63a771fe3af,0x0004035d6f692734,0x0000000000000001}, {0x00047ce82b6063a3,0x000a032d78ca1a20,0x000ffe80d92bf2a2,0x000357128144148d,0x00065f437565141e,0x000044794e70453a,0x000ed9d74d6e72f4,0x0002c9dec888c3b6,0x000d35b1703c9efa,0x0005564a8b5ee101,0x0000000000000001}}, {{0x000408c0ef420ccb,0x0003751466bdddb5,0x000686318317d090,0x000f5c351d77faab,0x000e6e1c56990fd6,0x00044f54fded7bc7,0x0007a03658746405,0x000acb87ac9e9b1f,0x000e1a951d060b45,0x0002d4d46b22b133,0x0000000000000000}, {0x000b308639e1f9dd,0x00088fb9f340687c,0x000545e0d0da3dfc,0x0007c0127b5897e6,0x000708cdc1322bbf,0x0003ce8bdc5bfb35,0x0009aefe13ad9991,0x0006b6cb7333e158,0x0005d1b9d92265f8,0x00065e9dfffba15f,0x0000000000000001}}, {{0x000dfc8b990a47ce,0x00010afcf7dc8ef3,0x000e84517ba6c8fc,0x0002906aab79d6ea,0x000563aab2198045,0x00005b6fc1e2c314,0x000e1c75139c8775,0x000f87b03c5339f9,0x00013db5c7dd8d56,0x000be729d4f04194,0x0000000000000001}, {0x0003ca2969a49a45,0x0003d7263734a805,0x000a96220f01659f,0x000a81ea503a05cb,0x0009a4b1e826b6e7,0x000b9124852cc317,0x000a53155592390b,0x000adcbcb9064287,0x000f6cda7ecb3423,0x000745fa7b75f585,0x0000000000000000}}, {{0x000020f9870c5652,0x0008ed2cf4bf5440,0x00043a293130a211,0x000b5775772ea602,0x00033659b8c321b9,0x000b8b914e8eddd5,0x00016d7acd2ea084,0x000600a84078289a,0x000073293df2fe16,0x000f1b7632be02d1,0x0000000000000000}, {0x000ae60c00fc41df,0x000dee1aec5298cf,0x000dc3a384668cb0,0x00039330262dc7a6,0x0008200480e942b2,0x0007f1ad6908e660,0x0004d8902ca00250,0x0009dfae47555ead,0x000dd7fb7e96dfa4,0x0004d09336664145,0x0000000000000001}}, {{0x000d1eaa79614564,0x0008f53026152677,0x0004e1ef41c569ec,0x0009c61bebc6f47b,0x0005a764d392b91a,0x00081c91fd03bca4,0x000d12e91e91f33f,0x000ceb9cb7de2868,0x0000e9b7cc6516bd,0x000c8bcc47c28272,0x0000000000000000}, {0x0007539aee683a33,0x000df86171edb94b,0x000cb40fe4798476,0x000b93f35533bd14,0x0009da702f13dc6d,0x000ba7ad4d348188,0x000a392741f6a108,0x000c52b97e5c2cce,0x000568205c383605,0x000d4f58766e7a6c,0x0000000000000000}}, {{0x000d3d9203521aef,0x0003dde5091b5f60,0x000ec304735ae314,0x000afe69e360b755,0x000f3119298c9f78,0x000c6a7738e3ed2f,0x000298a24d640365,0x00078b486bf006b1,0x000e9050b3448a96,0x000ac46d50f02b81,0x0000000000000001}, {0x000b1ce68a1d8699,0x000b8559ff13a9f1,0x00023011f5efc1bf,0x0004e57b1d2b17a5,0x0008efdcb9ac6bec,0x00009c3a1153d5a5,0x0006b2a4b16461a1,0x0005a5edc709e6c0,0x000d62c80c93e99c,0x000b0218529aa94e,0x0000000000000001}}, }, {/* digit=49 [{1,2,3,..,}]*([2^196]*G) */ {{0x000e7cc655ddb9f3,0x00013549c78f7abc,0x0006489c7f6e90f1,0x000e52627145775f,0x00027c353f1cebe8,0x000a2f29fc36a4b9,0x0000acc3ef5baced,0x000fb8074e6a3d4c,0x0008d3fd643a9c64,0x0004c070fffe4c63,0x0000000000000001}, {0x000fbd2cdf57826f,0x0005bd9bf19e6e5e,0x0007942ab0ce8665,0x0000c790e82b0e8c,0x0001e2f2b552cb1c,0x00090a098c9dab8e,0x0009810a67eba463,0x000c6a4756fc9b4d,0x000e8cb25c97785e,0x000215f5f5b6c18f,0x0000000000000000}}, {{0x0002bf06c6b067f9,0x000a2b3dcbcaa8f7,0x000559f9fa4cedc2,0x00001ff4707cbdc6,0x0005eb59f1a1d653,0x000b9620b3fc409d,0x00091f76c53a5feb,0x000e766a3eea48b5,0x00013597ec3fc458,0x000a5eb4cf309e19,0x0000000000000000}, {0x000b24162ae5ce89,0x000e57dda1da6f8b,0x00092393366cd895,0x000d0cbc02de8414,0x0007365ce8f0759a,0x000cfa2564893b65,0x000a74873186b40b,0x0004d0156cb04fbe,0x000490f66512a03d,0x00036b328165e70e,0x0000000000000000}}, {{0x000d63dbde7982b9,0x000c29e4cd39f5d1,0x000aa87372309f98,0x000951ea561fec44,0x0001afd07b42ddc9,0x00045755866c4665,0x000b2e07bf78c6a3,0x000e9284f87ca447,0x00035d4199cdea2e,0x00049a677e175372,0x0000000000000001}, {0x000229ff95010f5f,0x0003cbc8f306c814,0x0001a7861e7a79e9,0x0002d63c05616521,0x000d995f90f64784,0x0000e16cd8cf737e,0x0001408ff0413e3c,0x0009c3a4f30dedcf,0x000a0a6b443a170a,0x0006e0cc49b5c711,0x0000000000000001}}, {{0x000ac308c74d834c,0x000a8dd825f7406b,0x0000fbb496f34b0d,0x000075e1de870fb5,0x000227841bcf2365,0x000b8e05ffd3c983,0x000e33dc39c86d83,0x0009f0fd6d0e74cb,0x000d62a5a8904ae1,0x0008c32b1e28056e,0x0000000000000000}, {0x000d2a2671b67c79,0x0004494c1cde5597,0x000c0326e9105031,0x000b1ee150606033,0x00061f18317b0423,0x000cc474ed398c9c,0x000df4796a972375,0x000696b52ef07eb4,0x000ed96071372ae4,0x0005ffabf9d1feb1,0x0000000000000000}}, {{0x00045b8e28f19059,0x000286054435bd90,0x00012ddcca1e377c,0x0009f510d747b1a8,0x000d3775c0ea63eb,0x000865c7834fcce9,0x0007bbad37d19f75,0x0007bbc7cb402eb6,0x000530a0f5327111,0x000908600a1a8bd5,0x0000000000000001}, {0x000abbe5e02132c6,0x000b17b10fe3c6dd,0x00011b655993587d,0x0008aa4f1c163208,0x00092e7539751ad7,0x000229bfb751c187,0x00003ce5719f77dc,0x0009dd5c3eedf84f,0x000b8c257bb9c60b,0x000345e60da1b9c4,0x0000000000000000}}, {{0x000e7d40935779ea,0x0002b583ea2a70e6,0x000137328e54c9ba,0x000501ecd4654390,0x000e5d733683ab93,0x0009f374dd118e98,0x000b90700d407bd8,0x000c13b0afb65295,0x00048095857db6bf,0x00070895fc47c66b,0x0000000000000000}, {0x00037df304273762,0x00053684543a49aa,0x000af1483095c127,0x000176dbbf08a1c2,0x000fbbab267dccb7,0x000bd6efdfa7bbd2,0x000abfc8aeeb27ea,0x0008c902ad03e86e,0x0009e682a4e44e71,0x000fe0064991f1f0,0x0000000000000000}}, {{0x000aed77f4d8e151,0x000d64f6fa111299,0x000d4feb2e79c04e,0x0007b4f97a120999,0x000d370550af65d5,0x0001340660d07357,0x000084ce4afb7c64,0x00040826e57205ac,0x000a7fc0bae197ca,0x0008238f07d6803e,0x0000000000000000}, {0x000454a02cb353a2,0x0000deb5cdf6d6af,0x000f3bb89c8b32bd,0x000b355a1bd8c3f6,0x000e63db355ab5de,0x0005c6b3982f043a,0x000910f0e90987dd,0x0001380521adabe8,0x000fa044a4bf6a24,0x000fd8fb752ed23d,0x0000000000000001}}, {{0x000fdd1be70b4926,0x0009a826f6dba658,0x000cb4e95121bc79,0x000f676af00f6eae,0x000cee75a521d56d,0x000eca7d7729d333,0x0002e5027fb68ac4,0x0004a49aec5f206d,0x0006a988faa272aa,0x00047f341efc691b,0x0000000000000000}, {0x000df0f078415461,0x0006ca3afd9193e6,0x000e7785c7d78268,0x00030f1e3c2a9148,0x000aaa49f1fa54c3,0x000e96229782ded4,0x00093b6b845da08d,0x00020729c99179a9,0x000904b0df8fef02,0x0009cee6016c6aad,0x0000000000000001}}, }, {/* digit=50 [{1,2,3,..,}]*([2^200]*G) */ {{0x0008c22f80cbfbe4,0x000130943a347193,0x000e2773aac837e8,0x000010c64a3c4f46,0x000be2b750229f24,0x00007131ff138446,0x0000ce7731813b90,0x0000e94672d6c2c9,0x000dcb075dd149a0,0x0006d07531381b69,0x0000000000000001}, {0x000b38c7be8e6de0,0x000a9739ced7c6b6,0x000a61fbc4fb63d5,0x000fe4d18f6b6bae,0x000bd6ae1dbab075,0x0002c3dbf8c1ebed,0x000b0516dce109a1,0x000e4a2962c4c087,0x0000db685a1e1733,0x0001ad9f800e79f4,0x0000000000000001}}, {{0x0003feea78bb9ff0,0x00046e4fde5cbe66,0x0003f440437dd027,0x0002a08933232942,0x000e421f2f6038cb,0x0008d7b95a50b4f0,0x00073ae18c0b0f4a,0x000bc9451cc035a4,0x0005154ba8955b22,0x000d349d1fd0859c,0x0000000000000001}, {0x000f04652c1a8bcf,0x000b73e19db868af,0x000eea574f2961dc,0x00027664f8c3e1f9,0x000839b512b73f43,0x00002a0ec5b683e4,0x000b38a0fb615a0b,0x0001b1e55bb87991,0x0003094173f71955,0x000d3c0ba8f16419,0x0000000000000001}}, {{0x000ed0fcb63247bd,0x000c61e26950f920,0x0008ac76960a5916,0x00049cfc2ae5b02a,0x0008cda5eb1a5171,0x000118595b5c8f4a,0x000c88e0004518e9,0x00089dcbce699e0c,0x000dca7cdb0b0583,0x0009678f7a0d455e,0x0000000000000001}, {0x0003e3080d452c74,0x00067cd9ebc5ab77,0x00092748ad132f85,0x0000eb812f890896,0x0009083d0c649d6e,0x000d13cd26dc1732,0x000539d6815ffdae,0x0007727168b4775e,0x000ad256509166ff,0x0001747a36c1d3bf,0x0000000000000001}}, {{0x000e6e936a559258,0x000787f262712646,0x0007ee8f55296d6c,0x000b44326540e78b,0x000ef2fb8850453e,0x000e4739b6073a9c,0x00032c19bbfb39a0,0x0005bec805ba5b65,0x000b74df44331c49,0x0009d3002e8ec8ed,0x0000000000000001}, {0x000d7ba6c48685b3,0x00073d4bae18cecb,0x000a9e818b43a66d,0x000e109d5a439da7,0x00084e2bd60c3422,0x00082785ad715748,0x0009a5bf6bd330b4,0x00066c8383da8c0c,0x0009a00bf0007cc5,0x000256a489783e2a,0x0000000000000001}}, {{0x0004a8e407a2ccd9,0x00086ad221fba29d,0x000fddda1e9d46ad,0x0008643114fcb5bf,0x0005a60db0e24f96,0x000659be98b0468c,0x0000c785c91bca8a,0x000b1e072204cabd,0x000ebbe04d9453df,0x0007688aef77cf50,0x0000000000000000}, {0x000b62e349b426c5,0x0004467872d194b8,0x000ddbd4e1c43334,0x00024117aad0f260,0x000ea7d8cfb9c423,0x00083e18f4bd6c92,0x0008dd5687682258,0x000359ac483a7289,0x000ec708225923bd,0x00062148de2e57ff,0x0000000000000000}}, {{0x0004d07f78796d38,0x000a0307a33d42f6,0x0008948a2a44d434,0x000f90db03ccc6f0,0x000696ff7592ebb8,0x0007ff2ae969af49,0x00014fcec7fca3c8,0x0000d6cec6f56874,0x0009ae9c6b325541,0x0003ea961c98239a,0x0000000000000001}, {0x00084bbf91f7e4e9,0x0009ac472d023742,0x000d63ca5a686ea8,0x000614346cd552ac,0x000072fb24ab8e61,0x00080d3677dc07d1,0x000c8c0d1833f7c8,0x000717c50635d225,0x000f8a2192bf84ae,0x00027f2e83c678c1,0x0000000000000001}}, {{0x0007ea965c0d1be3,0x000dffe0762dd1bf,0x000d60aa7917e003,0x0002fc7262c54da8,0x0004421eaa7edfa9,0x0002c86ea7ff6dc2,0x000473729f82d5e6,0x000d535c6df46821,0x0004bda6bb69bc00,0x000b33f34e260149,0x0000000000000001}, {0x00096ecec3563dba,0x0004fd12da169210,0x0002f945903cc5db,0x00014cb4c4f95586,0x0007af70f6fbb150,0x000a6967e23d80e4,0x0003ebeadb489f20,0x0006a009490665a1,0x000afaa96a28958e,0x000a31da82221f9f,0x0000000000000001}}, {{0x000b5dfd8f4cc713,0x0009de59f2c453ba,0x0000c9b2cc1e3fa6,0x00033c17b6318b0b,0x000e92d5d399a56b,0x00008f8a6f6dc3c1,0x000b7f39e28633ff,0x000ff1fbcd4351ff,0x000013e8c77388ee,0x00066a953e5ebf9d,0x0000000000000001}, {0x000bfd2f419a3879,0x0001d195e5a481bd,0x0001ef3e1ae017a3,0x0008b706b5b37267,0x0003f748e8ba9898,0x000e9de7d3391698,0x0007cde6e3e3c930,0x0009ee4ca324e7e3,0x000b6a772ae3cdd9,0x0004235fda48d82f,0x0000000000000001}}, }, {/* digit=51 [{1,2,3,..,}]*([2^204]*G) */ {{0x000ce56e11c7765f,0x000fe4cfdef6377d,0x00035b399363df3d,0x000ca630a715e9e9,0x000a21011f820ffa,0x00022d3bc633f64d,0x000dab0c59875522,0x000dc95736a8523a,0x0008fef5b787c715,0x00032a66393c6305,0x0000000000000000}, {0x00034ecf897f6f48,0x000d40891f4ace54,0x00051c5f6bf7708a,0x0007ca62fe89ee25,0x000eae6011a07c37,0x000028c949d24cd2,0x000ab99c094a1a4d,0x00031fed19d9cf84,0x00051c154036f7f0,0x0003d437b50c3205,0x0000000000000001}}, {{0x00036aa0bf5fef4c,0x000b4bb069d26c89,0x0002e3dd1d0d3718,0x000bf3daeaaab400,0x00076315a34c426e,0x000eb5f38604c676,0x000805197e2eb1b1,0x00037226db1abc31,0x0009ad73df5e17eb,0x000d3797d098f510,0x0000000000000000}, {0x00082cf0882acea0,0x00006b48806f5a59,0x000abd275055f094,0x00049a504db94328,0x000ec38e43c40b3c,0x00082b99e608d386,0x000cf443b07fe475,0x000b7186cac29089,0x000d982cfac474a1,0x0009aa7b0368d422,0x0000000000000000}}, {{0x0006f1287e600c1a,0x000cffcc5624ecb0,0x0002d1ca07fb78a4,0x000a1f9666cc7bc9,0x0008539fb634b6eb,0x000c73e361397798,0x00014a496c8d68c2,0x000d7ca4181be620,0x00069a299a451732,0x0001c06004061fe8,0x0000000000000000}, {0x00029e4b308242d0,0x000a13eeecee128a,0x000f659548ea451c,0x000490cf14707b99,0x000362f80a26ba79,0x000292eee64971fe,0x000871b89c8fc38f,0x000d6dc0d122e55c,0x000979f11919fbb1,0x000f85c98fe350a4,0x0000000000000000}}, {{0x0006cb60e51b31a9,0x0009c2f6d82cb3ba,0x000f86e04fd98949,0x00087bb6cb66fb0c,0x000cb7e6257cf354,0x000caa5a38dbe642,0x0007ff70132dd977,0x000a9fe7cec8cf0c,0x000f2a9f98b24a15,0x000c7552eb7ce954,0x0000000000000000}, {0x000aec9e842f8ae5,0x00096d766fc55447,0x00099065768ced0e,0x000adad9493166bd,0x000c328be045e2b9,0x000e70d305222a08,0x000ec1d4f554727a,0x0002fed1873d61d8,0x0001c46d541e23d8,0x00042ef348b3f19f,0x0000000000000001}}, {{0x000ccf976377d19f,0x000f1cf68ff2fc1a,0x000d98b274ba0faf,0x000788c074f0bd37,0x000a798f5cd04250,0x0003cafaaeab508b,0x0009fd1e881c2856,0x000dd63706ee8361,0x0001b79794f0ad14,0x0006f33d5c0505bc,0x0000000000000000}, {0x000090b50612a9e3,0x0003e3a662f706ea,0x000cdebf25eed8bb,0x000d3a7d888eb094,0x000fdc87a6c4d17f,0x000574531e25001b,0x0007e6d823c00762,0x00014c6a486f9d98,0x0006d2d6573a4d0f,0x00074c191e9a8851,0x0000000000000000}}, {{0x000d58220482e6f9,0x000c77488e8bdb82,0x000ba1084c7aabd7,0x000ae76567c7272c,0x00079ab82a151ca6,0x000826c75c1ca84a,0x000434806316ad0a,0x00040dd7f329f3c6,0x00033bd2dde3d6a0,0x000c43689c3e453f,0x0000000000000001}, {0x00061be6ee98af37,0x000291b8361cc48c,0x000b8a7b622624c3,0x0000547d4c3e4e24,0x000c937a21d5f3c1,0x00007a153ffa09bf,0x000a63d54fa325a4,0x00048d13bea75c7f,0x000e1e55bfb7c45a,0x00055a1a8b85312f,0x0000000000000000}}, {{0x000094bb55dffec6,0x000b1ee483a0b1a7,0x000e63531718eed4,0x0009354c0be15b59,0x00029a3b937fed84,0x000295e4506353d0,0x000205f7b6d68fbd,0x000e59b3375fdbda,0x000b4aaddd0cb573,0x000348c879da0f51,0x0000000000000000}, {0x000afd066ea2106e,0x000ee293d8c45af2,0x000bc67374a1f66a,0x00016d7c0fd1fd2b,0x0002493231dcd541,0x00019502a277efda,0x0003c7872e2fab64,0x000a95c3d06567be,0x000fa48d7ff41d2a,0x0001cc69c52d2e6d,0x0000000000000000}}, {{0x00046d25ca0b12ed,0x0003e7af11f36102,0x000d246f5c00ca56,0x0005f2713dbda22c,0x000571517fe92c1f,0x000e558aff5b82f3,0x000852ec7e4811aa,0x000a0a7d7a0cfe93,0x0009a571e80c69ef,0x000d5ecf0c8dc85a,0x0000000000000000}, {0x000629e0362ea61b,0x00019570463933fa,0x0004d8bdb2997e91,0x0008d16c1670ff63,0x00042ac0e352c375,0x000bf5c218c31489,0x0009269789d4077e,0x000eedd9111468df,0x0009e59bdc949bb1,0x000694a97ced001c,0x0000000000000000}}, }, {/* digit=52 [{1,2,3,..,}]*([2^208]*G) */ {{0x0000e658f63653aa,0x000362a4e263b15e,0x000f1a72f5cb787e,0x0008dd85ade21c8a,0x0009351d6c477346,0x000ea4254fd69f8f,0x000c982ae15e0af4,0x0005dd836935db86,0x00023278398d3a2d,0x00082c5ffb0769dc,0x0000000000000000}, {0x0002ae6ecd27779d,0x000456043db3d94c,0x00073642e7c09230,0x000692df6f9dd795,0x000422cd985762a8,0x0006ac0a49a83e72,0x00059cfa2e9e20f1,0x0000d0093708d3fe,0x000c84d0b10a4692,0x00035fa5bda12a10,0x0000000000000000}}, {{0x0009924edfb9aeab,0x00028a46d2968a10,0x000fe84ed7a9147a,0x000478aa49744c91,0x00030fd88965188e,0x000dc8d99e65a34f,0x00006f221fd955c8,0x00027ea7cd997402,0x000f83ab9dedce89,0x0006e8a7c26d23d4,0x0000000000000000}, {0x000728e182c8cb8b,0x00078b0fa5f32091,0x000760a4e2a3ad9d,0x0002b50f65aca369,0x0003d46ee027e681,0x0005a7e2b8db993f,0x00003752acac076e,0x0003a179054a6029,0x0007bff0fddbfa0d,0x0008feee0dfeeff8,0x0000000000000001}}, {{0x000e1e66266af2df,0x0002e36c081c96d8,0x0002c3c896d714ef,0x0002acfe977ac59e,0x0001a95d1b3f90be,0x00003c79555da335,0x000ac68d1f4138b3,0x000d2dc5e8301aff,0x0007f5144ad06837,0x0000d0ff81349a59,0x0000000000000001}, {0x0003ebad0af48caf,0x0005e5d9aadd9976,0x00026bfaeb96c7e8,0x000c9ceb03564b50,0x000254586ab1371e,0x00038a2ddf7b0228,0x000ca35a77209961,0x0003fd9f60e7f5a6,0x000f0eb7073273c4,0x000a1bce76f5e62d,0x0000000000000001}}, {{0x000a60a63bd16196,0x00077f090aae19bd,0x000e7638c32cb3f5,0x0002a6ddf59abf93,0x0001d3548613634b,0x0001b5e6513c50db,0x000b5bd49476ec89,0x000a83b636d2f4bb,0x000071e3a3dd95f7,0x000ef977c02f69d5,0x0000000000000000}, {0x0008603799531d83,0x000ec49c9ad3cfc6,0x0004e50cb9635f1e,0x0003ca9d26b39588,0x0006f3bd6a0e5d70,0x0008ef03a93fe903,0x000aad2605b0ecc0,0x000b6abd3a9b070f,0x000a81977f3494ea,0x000831164f95f67f,0x0000000000000001}}, {{0x000d576c129bba19,0x000dc781b1958f67,0x0004c725830444b8,0x000d772989a02957,0x0003160191e1f14a,0x000b3aba62ef31af,0x000a9c026782cae3,0x0005e2df9de1d797,0x0007d5d393897669,0x000e09de2e3f7f60,0x0000000000000001}, {0x0002f590d9230f6d,0x0008e59ce71ff8f2,0x00065bfab0b97ecb,0x0005b773840ae894,0x0005df550efa55da,0x000a03525e361e4f,0x00032a275d9fd4c6,0x000f30d16226c4bb,0x000512eb88ebc1cc,0x000a048dd37790a6,0x0000000000000000}}, {{0x0005c82e7c82fe0b,0x000b6b153f48688a,0x00079cad28ce32c1,0x0004dd65d7330f19,0x0005fd6ce0841643,0x0004ad25ddac7886,0x0007705833e0df48,0x0008294753bb4502,0x000ad8dbbbf63937,0x00019b436c10a463,0x0000000000000001}, {0x0005b7516a304d40,0x0008185865f25816,0x000cfc1c163a4965,0x000ed7eed35d77f6,0x0002d2246fce8e80,0x00064fa59660ff02,0x000081304ce77dc8,0x000c6fc813dd85ee,0x000db13057fabb84,0x0008d66a509ef64a,0x0000000000000000}}, {{0x000ae85bb3c1e90e,0x0001923787b4a031,0x0009e575e9892a6e,0x00074c2ebb769eea,0x00063064d9df4bf8,0x000e1bf584f54d2f,0x0007ecc49f863e83,0x0003213fe023848a,0x000c07e3d527042f,0x000c51626ab6da53,0x0000000000000000}, {0x000783a377f5ac26,0x00010cfafa402a74,0x000f762b70abfb39,0x000eac42e208b3a1,0x000497274db0b567,0x000b54ede1f18ddf,0x0001de4808fda6ea,0x0002ceac81237a87,0x0007edd6e7428e9d,0x0000cb9fb5801abb,0x0000000000000001}}, {{0x000205d81676b493,0x0001cfe8f546e257,0x00087afe8b644287,0x000676bad5e346c5,0x000f4a964afa3748,0x0001422f71ca39ba,0x000328b0e9e0a58e,0x0001d31cca18d62c,0x000787f6507714d7,0x0009ad810168e375,0x0000000000000001}, {0x00030f78aa1440c8,0x000f7e509d6354b7,0x000beae80e0ec14f,0x000f7cc09793053f,0x00025b6b1fd1b019,0x0004558d48e4fca0,0x0002aae7ed4a0374,0x00070e2db1c48699,0x0007f4b02f033375,0x000af43011764955,0x0000000000000001}}, }, {/* digit=53 [{1,2,3,..,}]*([2^212]*G) */ {{0x00015e37a2d438c7,0x0006bb436c808cd7,0x000782325918615d,0x000d68ce58c6e6b2,0x00075a40e8f75ca6,0x00001da381c4c378,0x00055d9be962879c,0x00075dd3d4cf58a1,0x00099fd85847d5de,0x000e158f7f76b4ee,0x0000000000000000}, {0x000c9f66a4cec18d,0x0006e45302a76bd4,0x0001b679cdf64708,0x0002c24293b84a7e,0x000a092243bc4d41,0x0005c3c375519ccb,0x000d06b585371f2d,0x000590f4c0f28ba3,0x00073b4091daa768,0x00073c6342e78bf5,0x0000000000000001}}, {{0x000dcb7fa9fca3c3,0x00047144679a2a9d,0x0003be369b38069c,0x000a82620de84dbc,0x00098d5e1f28d82c,0x000205de8989e877,0x000abac84051f10a,0x000ac26a5b9c5c22,0x00074ecbb99bba5f,0x000253359fa6c2dd,0x0000000000000001}, {0x0002ac09a82c210a,0x000b422ac08c572e,0x000c5c720e071535,0x00095966a7bd1c3d,0x0003a0a4b0c9e18f,0x000faa6c6449a62e,0x000bdd44f85595c2,0x00047bb9f75f529c,0x000f46a6493955cf,0x000622defa5af650,0x0000000000000001}}, {{0x0006df335e8acd01,0x0009b6996f91a727,0x0008be8a5f6bba5b,0x0006ef24a13311be,0x000b7fe2a95d51f2,0x00084a38b4ee11ba,0x000caf93233a4f76,0x00073771e4762ff2,0x00024adb050176c1,0x000a9e7e6a96ea5e,0x0000000000000000}, {0x000540fbecee1541,0x0003f39f444fded1,0x0006ce01534c5cef,0x000a886125f5b460,0x000b437e2199b1d8,0x000a994fb5a77157,0x000fcae599e6b65e,0x0002599cf24da91d,0x0009f0d7248964c9,0x0007ac171d21915d,0x0000000000000000}}, {{0x000ca4b8955dde0b,0x000f850c9b5cc251,0x000b99572d6cb500,0x000f8952b82356c8,0x00088575ebe209ee,0x00089253a4607df2,0x000ff9ba421a6b33,0x000799f0eb4dd513,0x0003ed789c84b56b,0x000293e6a5c4d425,0x0000000000000001}, {0x000ff217c0f18530,0x0008986930ae0198,0x00012fd1e778abc5,0x000f509594fad4d8,0x000656733dccef2f,0x0006afad83f10fab,0x00078f717d75c593,0x00018a1a313cd995,0x000cd73871602741,0x000f5446078ec40b,0x0000000000000001}}, {{0x00034871165b0407,0x00041aa1bdd6d509,0x000fcc9e894c7b1e,0x000369e1389494fd,0x00087f5116c5472d,0x0000a1b0d04b3663,0x0000b4c49058303b,0x0002bdbdc1d8cd26,0x000ae8f01c121d9d,0x000dc1d8c7270b76,0x0000000000000001}, {0x000d922f0e06b7cb,0x000f07bd16843c5d,0x000c01dd32245ab8,0x000fa9f6081477df,0x000c2db624f56ea9,0x000b2fb3e2bccdb5,0x000cb3b768793cb3,0x000c8d894f04384c,0x00010a3af20b15d0,0x00045ab5af8411db,0x0000000000000000}}, {{0x0006b9ed8590e4a5,0x0008a58a2974d283,0x0001c7668bc64c35,0x000acc81cd837cfc,0x000fc7b9eb02f729,0x000fee9d6ad1171e,0x000a8d7ca7eeb433,0x000a79ea2e79ed5e,0x0001fb8522e38381,0x000cc8162a76e7a5,0x0000000000000001}, {0x000c67543c98a4ea,0x0001f713941c4de6,0x00081dc75d38a3eb,0x000374ce9c459cdd,0x000bdd7ff2d1d555,0x0000d7b03a560a54,0x000ad6193d7f976c,0x000099ff27e977d0,0x000749edcba5d394,0x0002c6804ed826ed,0x0000000000000000}}, {{0x0003e3bd3291cd15,0x0006a26271a72635,0x0001ef4581082f50,0x000cb6109637a812,0x00043e376f158b63,0x000e1fb8b4f92150,0x000fd4238523b166,0x000edb09ffe09019,0x000a7d8e27b82fb2,0x0001989a4df94f9f,0x0000000000000000}, {0x000410feb007ca74,0x000ed314198cb45e,0x000e234a35b4b72c,0x000c1779579fdfb5,0x000da54f63558ebf,0x000b68211f279305,0x000b7f7a88ea265f,0x0000914728cae4ca,0x0002ed65205137c3,0x00045ed6df45a086,0x0000000000000000}}, {{0x0001cfb71cb23bf8,0x00067b25479ac001,0x0002f48bcdb785ff,0x000da267c454fd25,0x000154e460f65f62,0x0006fa21e0ac759a,0x000770bdb56d239e,0x000db91d7ccefa07,0x000f07f46fe275a8,0x000527a152927368,0x0000000000000001}, {0x000969a0d74d64a1,0x00059c36f066b2d7,0x0003a664061d81a7,0x0008c41d929c3e1c,0x000a4033ad63b5ba,0x000387b665fdb5a8,0x0002e2c2b433c84f,0x000e4f2d4d931e74,0x000631141b030d2d,0x00086de3845c248d,0x0000000000000000}}, }, {/* digit=54 [{1,2,3,..,}]*([2^216]*G) */ {{0x0000c039d020c1dd,0x000d44ab7b690765,0x00026b42700b4f64,0x0002c1e20576d051,0x0009e70d2ad712c7,0x00015f46314322ae,0x000dfb189904b573,0x000124905a45ef02,0x00026cce68a7b470,0x0004ac5f0db2cade,0x0000000000000000}, {0x00042cd205524778,0x0000d86fcfeb993a,0x0001cc7f2d2ee992,0x000c209546bdb299,0x000531516a6eab71,0x0005f1492f99e62c,0x0002cf5197ae7709,0x0002013e12e8e95c,0x000b78cb72aad7be,0x0000320e70b96760,0x0000000000000000}}, {{0x00011fae297851e8,0x0004f69afd113575,0x000ab322fa242843,0x000f361ecbe5e3de,0x000b7c1b08880d89,0x000a50aa80c1fbd2,0x000104d9e40537e6,0x000ed4f51df57fdf,0x0008a6cfbe707164,0x000f36d887e3d0b7,0x0000000000000000}, {0x000365e7f9a5983b,0x0003c6129d87d996,0x0002952186a64aad,0x00009284f8224d3c,0x0007bc689c1d4452,0x0003f44aec2c194d,0x00057e00e7c6b2d0,0x000de28c9eb3f18a,0x0008b7de6fac4981,0x000009552159064b,0x0000000000000001}}, {{0x000147285c5f1e84,0x00054bbe273f4c79,0x000ec66bd4d71c06,0x000771b4dd0505e9,0x0002d4c891619ed4,0x00021a0542316ff1,0x000ffae0c65ede48,0x000db678c0c5a23c,0x000bbf48abf05e02,0x00032691ff4f9e32,0x0000000000000000}, {0x0004ec586f495f39,0x0007665c351b2d94,0x0003939c0c800e74,0x0000a9b2fe310474,0x000c05e63ba55b78,0x00011119c911cfce,0x0000043322972c9c,0x000235f5ba3b0c8e,0x0002b78daa0946bc,0x000a82622257dc22,0x0000000000000001}}, {{0x00053147b3b22c3b,0x00004897a83e73cf,0x000d11d0f510fba4,0x000de4abfcf9128e,0x00047095c92d56df,0x000f3cd334bcfa2a,0x0000038a5b6f4d4f,0x00095df73169a249,0x000aba80e663bcbc,0x000c64a47769e841,0x0000000000000001}, {0x00004365a62c4cf6,0x000531a582938f21,0x00043321e6dc439a,0x00061253f7387146,0x0008352424fe3ee8,0x000a676302135902,0x000702fe71ab2ae0,0x0005f460396ca837,0x000882e04f7bce51,0x000f93d936239901,0x0000000000000001}}, {{0x000dc17de84a8cec,0x0000802c374c6c6c,0x000bd6a5b20e3454,0x00046c40337b0f58,0x0003431d7aff9402,0x0001dba6a849292d,0x000f90b37486a260,0x000c12d61cbe41a0,0x00033f828782067d,0x000486ebc39fcd30,0x0000000000000001}, {0x0006818da93cb68a,0x00039ef42673be02,0x00040e906d3f2e27,0x0000e1f1d8ecf6f0,0x000655c024d3837b,0x000417cf596708c0,0x0000946c57882083,0x00058942a1031702,0x0009752bc7086a40,0x000474bd8d65b027,0x0000000000000001}}, {{0x00057bccc2137aff,0x0003cdce9d3ef437,0x000021aa7d7b10a8,0x00014071804bf03e,0x0005009822fa479a,0x000c4d2fe91adecf,0x000bad18fc3b061e,0x0002ffe82ea4479f,0x000b0bed7b70c576,0x000d5c8a667da425,0x0000000000000001}, {0x00036c22b574750b,0x0001a79beeade4d8,0x000d7c41634d28e0,0x00030d7e124715f6,0x000b28e33c4f983d,0x000442a0682ee2bd,0x0000a48a18cfc1f5,0x0009a6cb16376839,0x000ecc58844abd78,0x000383bd6682cba8,0x0000000000000001}}, {{0x000c36944a224339,0x0002221a86a3568f,0x000a933230388a55,0x0002ca0cfc1f186c,0x000051f24d4d5f8c,0x00053ac024a82a69,0x000e4e0b6761f2a7,0x0006b4a03fa98a0f,0x000862d5fd1d2058,0x0006922bcb9949cb,0x0000000000000001}, {0x00085574f50da47c,0x000f8cb1192295a2,0x0002436f1d423eb5,0x000f6ae23f4febd2,0x000640f1f266f842,0x000e94d3498091b2,0x00016f1f4561f25e,0x000c6e303b526f4a,0x000bbc14e80ed7ff,0x0009ac6f957c1908,0x0000000000000001}}, {{0x00089a398d206da8,0x000e6a92326c61c3,0x0000b658149c80b1,0x000f4f6423067f4a,0x00022c96735aed5c,0x0003cb53c31cf4dd,0x000c7214b478ba14,0x000d3b1bbb1eb353,0x0005aa79b46f2e84,0x0007d44a4fa3d67b,0x0000000000000000}, {0x000d31f07cf711e2,0x00031e5402e45d5a,0x0005565057819f0b,0x00050ebe214cdf81,0x000e63efd8e063fd,0x000c82d63ad808de,0x000d0ee39ccec300,0x00085249be7d39df,0x000e9271ab6c788e,0x000a727ffa3cadeb,0x0000000000000001}}, }, {/* digit=55 [{1,2,3,..,}]*([2^220]*G) */ {{0x00061361be3ee97b,0x0006e1f3125658fd,0x00096b636a1d69b6,0x000b9e470c7ac9e9,0x0005bf9bb3617e69,0x0002050a8c1b1e89,0x0002213fa5a11a51,0x000bc2919affa249,0x000be1b1008d55c3,0x0003926dcf2c08c4,0x0000000000000001}, {0x000fb57fda93efc6,0x0008276ce4aac2b4,0x0009277cab16292f,0x000e677dc90518a9,0x000ab0432d015144,0x0005d9214eea4408,0x000b8a649b20eb23,0x000b48a45d8a2560,0x000cf7d1d37dd269,0x00049d71a47616ce,0x0000000000000001}}, {{0x00034d86d189072b,0x0000b9475ac257a7,0x0003a9d12f132433,0x000adf08cecaa5dc,0x000dc33641cc3048,0x00040352a6bfcc4f,0x000dac876f01bade,0x00035bd7dfb06e93,0x0001d4494c0e1ca5,0x000219b51965b8b2,0x0000000000000001}, {0x000f90e9be7f6998,0x00040776cb857a46,0x00031907caf1b517,0x0007040038843e17,0x00014b3c14ab5377,0x0008c99d12b47cfe,0x0001590d18daa185,0x000f84db2817d455,0x0008544bbc4d8f7e,0x000ee1752b595c5a,0x0000000000000001}}, {{0x000718c9c3382876,0x000798d016412ea8,0x000c7059eeb3d459,0x000e910707afd251,0x000366ae603f57f6,0x000f1d424b7c29b3,0x000f4591f08b6d11,0x0004fa0b188406f8,0x000a09ce46dfa46f,0x000f3e1ee6193a22,0x0000000000000001}, {0x000ef37aacfd9628,0x00044abc282a7b59,0x00016eca5fb04908,0x0002a4a0fa414af6,0x00010748c915edd4,0x0003d4af5a6f1ab8,0x000aff331ef86bba,0x0006d8ffc35ce768,0x000278d36b6c4e53,0x0006238f61ddd56e,0x0000000000000000}}, {{0x0008204ec1fe994f,0x000a401febacf810,0x000a1fbe66e0a0c3,0x000654b72570b727,0x0007b5299d8ae343,0x00058b323a83e064,0x00034d13d86ee0d1,0x000be946224b7585,0x000a38321cb77d0e,0x000ea9b845ec39e9,0x0000000000000000}, {0x00021327ccd07b3e,0x000b9c13edfc5044,0x000efee69b80c4b9,0x000b9736ce07a452,0x000de2779de28110,0x0009cb506b810433,0x00009831468d2371,0x000fb54615eed293,0x000a72f30895d360,0x0000822a939f9fa6,0x0000000000000000}}, {{0x0003613a0bad2c78,0x000a2841479bab61,0x000ae853dfe64b3b,0x000c5d69d7d5f8f3,0x000913c023c98edd,0x000e51c064c2af1c,0x000caf23e811beb5,0x000a297f73a13e28,0x0002c2db1b2c63f7,0x000869272783c6e9,0x0000000000000000}, {0x0009e33e7c2b0e8b,0x000a6e2930859a4d,0x00021c82319f96d2,0x00062855234b3a37,0x000cfe1e952c7999,0x0009fff526834c3f,0x00082932d66290aa,0x000ed0618b6fc1aa,0x000f51b1765d795b,0x0000fa7ad3a784d8,0x0000000000000001}}, {{0x000b99ec5345605e,0x000d705b03ab3b6f,0x000d514df02df673,0x000d979497926d51,0x000327f3cad9968b,0x00007b8edfa7bbd7,0x000fc5c1dee65278,0x00036db8f1709072,0x000d430f38a088d0,0x000f9df3373c9bfa,0x0000000000000001}, {0x0002932b26523f7a,0x000a4698ce826d56,0x000d64992b915d43,0x000f137e0e1471fe,0x0006811a1c25612c,0x0007e5e74619907c,0x0000f455dcff6a59,0x0006fe503afcb4d1,0x000af47382daf8e9,0x00085e51a1e9e2bf,0x0000000000000001}}, {{0x000c899ed52c7ebf,0x000805309ddc9f57,0x000f9ec0561000b8,0x0005599061be65ad,0x000c7c6ac2e8bdb7,0x000546a9f7f8f392,0x000b38f709f90fbc,0x0005b81ee256aa4e,0x0000cd9ffe3bb73d,0x000ad1e54f791392,0x0000000000000000}, {0x000e432eaecfeb4f,0x000efd7d99d4376f,0x000ecbf257042314,0x0006524d0d11bf19,0x00070c070e8811a2,0x0009bb46ac80db71,0x0005deced6976256,0x0001f5d4f1996e7f,0x000c6d1bc35c855b,0x000b7fcfaf131b63,0x0000000000000001}}, {{0x0007faf89dff5e6d,0x000701e289504c4c,0x000c21c143d7c67c,0x000b8b1051104808,0x0001a8547ea3f429,0x00042d1597643f8b,0x000c20d8e30463a4,0x00019700b9ca1322,0x000c7c74112313e3,0x00021d429e582d53,0x0000000000000001}, {0x000df174dc25e320,0x000421f30a9c65a6,0x000cca7bd70734a8,0x000970e912f441c1,0x000b0da35c85642e,0x000fbc6108990f29,0x00004f9201a5ca87,0x0000b4ba5b8a0067,0x00032f15dd79c420,0x0001dcaa2c572053,0x0000000000000001}}, }, {/* digit=56 [{1,2,3,..,}]*([2^224]*G) */ {{0x0009f88e8ef42daf,0x000fa3828b99d9e1,0x00051fa512ec2bee,0x0004d684d33e3c3c,0x000ae34a6c37abe1,0x0009d4bea55b5936,0x000e6492802583c8,0x000098da605bd938,0x000288cfc1f04542,0x000ed0659c47e455,0x0000000000000001}, {0x000ddaea5046a68e,0x0003e422472a49b9,0x000c2da95690aefe,0x000dcef36e21cee3,0x000eab14f0abf0c7,0x00064941e198c3c9,0x000fcf64819eee0b,0x000dbfe77fa8433c,0x000c3b28a2f7686d,0x0009c3dbfd233403,0x0000000000000001}}, {{0x000b7107c522fbbd,0x000c42e8887082c3,0x000cd304c29d218c,0x0004d8477a96d44b,0x000ecee7f483ff1c,0x000951d19c530d4b,0x000d68d4d6bf1fdc,0x000fe03d009b71d2,0x0005537694d3bd1d,0x0003c3db4cb1a2c4,0x0000000000000000}, {0x00086f0e3fa15f33,0x000388caf5fb4c5e,0x000b2f14ba7715c3,0x0002610381191db4,0x000e0f68a08e3384,0x000342059cb75d25,0x0002bd292f767fcd,0x000a7a696b414dec,0x000dfb67016057d6,0x00035999c277b18a,0x0000000000000000}}, {{0x0008ba73e1f475e0,0x000dd3f1b783f77c,0x0007375b491b116c,0x0007d166e4a377a6,0x00011bc5434f7131,0x000a2dbe9d40b215,0x0001220856a6b5e6,0x0007b890e757f7e0,0x000f02578a944660,0x0004883ff77008f5,0x0000000000000001}, {0x000a3e2632a212b7,0x000302b8f038a3d8,0x000a306506181a49,0x000301702b3192c1,0x0002c30f8e6d2d73,0x0002a0c5b0c340d2,0x000f8bfe6e8c90fd,0x000e8d703d0478e5,0x0005135b5979aaf2,0x00034da81fa7add8,0x0000000000000001}}, {{0x000f16b10733860a,0x00007e088e20bfd6,0x000859fdd39b30d0,0x00096072d4c40b6e,0x0007d0a59d2a4c91,0x000f5b531a3c4f60,0x00005885c546c30a,0x000ddc1d5df2fdc4,0x00026f4df2971b1a,0x000bb67cb15104fb,0x0000000000000001}, {0x000f74646d17eec9,0x000e3de3bee8f39f,0x000560fc63e96143,0x000d7aab2e0395d9,0x0003f099cc808fd9,0x000e3c3dca422f15,0x0002c61efabb0d74,0x0008d736943aed2c,0x000d74e4178f87c1,0x0003d1b76afadf96,0x0000000000000000}}, {{0x0009583eea912fe1,0x0006a5587f3b9010,0x0002a020829ea8e9,0x000b82ec346b73a8,0x0001f44eda406972,0x00067b4504fbb553,0x000e7a6189bcd268,0x00039bdb40c39e05,0x0005c436a03e5e06,0x0007019eedb498d3,0x0000000000000000}, {0x000662e3f77764f2,0x000cda79a7c8507e,0x00040c75e0594299,0x000bed938a93a1fb,0x000829d1bab3f2df,0x000df99ce48d52d8,0x00032fb8c4092f5f,0x000036b5fa768aef,0x000201a9ee7997be,0x000ca0344038e8d5,0x0000000000000000}}, {{0x0004ae17c6c4ef83,0x000409ab5b4b2b20,0x000c4c863d0780e0,0x0003a003f73d00d9,0x000f7d17b97edd24,0x000335ec2eca6e6e,0x0007def3f246d97d,0x000f0e2518ced6c0,0x000f728fdb8b0595,0x0006dcc1ccb10bfd,0x0000000000000001}, {0x0009f012dd02f504,0x0009d50a767d8e86,0x0001bbb0510be6fa,0x000cdab7deeebbfe,0x000f08332cdf98f4,0x000468782175d651,0x000610add0fc83f5,0x0004965277afa428,0x000ff5c3438635dc,0x0001fc0961df5b9d,0x0000000000000001}}, {{0x00069bd3ef1fabd9,0x00064fe7b00b747c,0x000195c6097cd6a8,0x000470709e13f896,0x0002cf79709fe958,0x000b72450de744f3,0x000df3f80fb1524e,0x000527ea0bf24b8d,0x0001b2774e7c3f06,0x00031ad38e7aad24,0x0000000000000001}, {0x000b784c1f4489c7,0x000f2a889f589505,0x000a5a3175ee6df1,0x00047a68c157fe56,0x000497f7b784bd67,0x0005ed8ff0792025,0x0001528aca7e0427,0x000d473d7c41594f,0x000cb017e35b5669,0x000f1ce78bb2a52b,0x0000000000000000}}, {{0x000290556eb6cb2d,0x0005feea12a072e4,0x000d082bac976238,0x0007c4331be16424,0x00021f06c7a59869,0x000de72b68a812dd,0x000652502f900697,0x000d9acaec02a2e5,0x0009120c4a89c7ef,0x000a1bdf713a324f,0x0000000000000001}, {0x00067220e1027a34,0x000cabc964145333,0x00029a9fac99b048,0x0001c2850e9e757a,0x00057de9cc170cb2,0x000d017c03bef969,0x0008cbf0f3534a37,0x00085a627fd6a9c1,0x000c29da8ed78ac5,0x000ae4ef092acab9,0x0000000000000001}}, }, {/* digit=57 [{1,2,3,..,}]*([2^228]*G) */ {{0x00060edf11bb374f,0x00007883a0baf3f0,0x000eb8cb2a326de7,0x00095554f5a8d631,0x000236ba14fb5cfa,0x00053769e29d950c,0x00043eac3b6e6d4c,0x000400e396b6857d,0x000b3b40a28cc2c6,0x000f0142ca52de79,0x0000000000000000}, {0x000536d43744d95a,0x00080dbb696fec4e,0x00086879c7360fe9,0x0006d4736a564e15,0x0001262e7ce9d679,0x0004cced89ee75c8,0x0005fe2dd4f732cd,0x00004a4d97d2a3a7,0x000e046cc62def6c,0x000c590bfe781afc,0x0000000000000001}}, {{0x0001e39da3d53729,0x000c68258dcf68b5,0x000b1289a021c50c,0x00028ef654112229,0x000f4c73b83c7489,0x000a0ebdbdf0df33,0x00033245f1663936,0x0006bdfac3bf0988,0x0001bcc9c21bceec,0x000bcb64a15de987,0x0000000000000001}, {0x000fb2f27cba002c,0x0002f0ce8d66f97e,0x000c4f49e106a48e,0x000720d60d05177f,0x0001b9e35427304e,0x00008c355b746f84,0x00061577b7b7cd5e,0x0008586eb9a88122,0x00003b21c38ce383,0x000aec02872c5a8c,0x0000000000000000}}, {{0x0003ee736c032ac5,0x000efdfdb4c3d4de,0x0006ff01d94dbf41,0x000a0bb5ee1889b9,0x0009e7a8dc456a87,0x000c2bb8ca379bb9,0x0000100b2eae0668,0x000d2063b0184325,0x0006daafabf5c71a,0x000da2051e835c68,0x0000000000000001}, {0x000eaacab83acf78,0x000761a09a5ec30c,0x000838055c361c20,0x0002e34e4fa05860,0x0001b9a7a3c102c4,0x000f91746c97086b,0x000c731ba10529e6,0x000e8a7f6450292d,0x00076f3144af4061,0x00077cacdce041a7,0x0000000000000001}}, {{0x0004b67237f032bd,0x0003fda08c68528a,0x000c719571479a5b,0x00011c75d8054fed,0x000bf503c35807c6,0x00037b9ea9e88e5d,0x000c9422b4c4521b,0x0002950eb17e75f1,0x0008eca427950847,0x000c0f845c91f923,0x0000000000000001}, {0x000c1e80ea8c1010,0x0002e1978ae396a0,0x0002c0d00f914b24,0x0004e43fb47bf7bf,0x00034b416e50ae94,0x0007c8d114906c36,0x0000ad0347f03a3e,0x0006a6eba25165b0,0x00021e9dc53a14e2,0x00076911eb83f4f5,0x0000000000000000}}, {{0x000bb95adc5ef776,0x0008da0ab8c5f233,0x000a4ab915fb3034,0x000423a63a5dffb8,0x00063715aa2304a4,0x000018304840df01,0x00037b80028296bc,0x000854f7402fb23a,0x0006ebdeaf3e5fac,0x00005463cd3d8406,0x0000000000000000}, {0x000c9468fa481453,0x0003a0abd61a0348,0x00047c025f468b21,0x00090d7078cd984d,0x0005284e72a10788,0x000156fa2b542f64,0x0003b3c956017512,0x000991f2c57b982f,0x000989b3c05c1c45,0x0001ce6eb96dccdb,0x0000000000000001}}, {{0x000c0c76c91a3d86,0x00001a3cab8eb5fd,0x000752ec9cff796c,0x0003f81d37bdda1a,0x000e12c746df5d95,0x00027c38d512fd50,0x0004e23ce093d983,0x0004adeb3545f200,0x0008acce0db1764a,0x0004097d3ea0eee0,0x0000000000000000}, {0x00057c8acd0df62f,0x000a235a3f7e354d,0x00043547a0eeee98,0x000831405ee1adbc,0x0006a916c043f6f0,0x000e4844ab1da766,0x0000728cc7b74a71,0x0007192544b4fdc6,0x0009d41decd4aad8,0x000497605d2bc303,0x0000000000000000}}, {{0x000c16253894ed63,0x00072cd0f6a2350d,0x000412983f7baee8,0x00009f78d054975c,0x000d7bad42e9614f,0x0005f2ac60d67eaa,0x000622d671f099d8,0x00021f07bed1e830,0x00081424aeea7845,0x000f7592014c5f2e,0x0000000000000001}, {0x000619d3fbb4d7a6,0x000a9269d1beee9e,0x0002e4ef27debfd4,0x00069156fc40ac5c,0x000b31c86af27730,0x000f4aa3fc30b8ff,0x000bfd86f500b895,0x000c9dccb88b68a2,0x0003b7832b9f66f8,0x000853497ba1895e,0x0000000000000000}}, {{0x0000b0ab29d3bde4,0x0009c71ea0d8e5cf,0x0004b6204df30d49,0x000d3f548f748b9e,0x0006eba95c754c4d,0x0007ad6cc9c44387,0x0009e2d08e10896d,0x000ea9428b4a544e,0x000fe71891a2d3e1,0x0006b905c7660eb6,0x0000000000000000}, {0x00066e6414125179,0x000e2877106f8fb3,0x0002d9d82f542b36,0x000b4eca63743c2e,0x000cfc887146aaf2,0x000ed669e0b28d08,0x000c885c73913714,0x000914ee1f56da28,0x000d4479d84424da,0x00015e3364622742,0x0000000000000000}}, }, {/* digit=58 [{1,2,3,..,}]*([2^232]*G) */ {{0x000bd25b5edea690,0x000347c3abc5bd1f,0x00078a11d29a3138,0x000c6d62f2283223,0x0007b4af4ece3ada,0x0001c75e4372b0dc,0x0009560a7308e28f,0x000d0ea7127d9913,0x0000172da9cb3c31,0x000c36c69386a7ee,0x0000000000000000}, {0x0003be2a2cae0b56,0x0000778293313929,0x00041cdee07af8d3,0x0000895f4118b415,0x000b9b3a9502ad6d,0x00004e1d44242767,0x0001a843924f3834,0x000a3c5c40dce7a9,0x000443e9e0f30db5,0x000c5338df60b62d,0x0000000000000000}}, {{0x000d88264070b39a,0x00060f5a265bdb95,0x000717063ef771ed,0x0004ca000dd813de,0x0005a4d348196d97,0x000def16129d2691,0x000bcbbfcdfb3523,0x00057290d6981eca,0x0000c5d2444e08c7,0x00091c65a063c65c,0x0000000000000000}, {0x0001941d0c9b7cd3,0x000cc0a5845e0e75,0x000c51c09cc90c04,0x000ce8aff11f3a2b,0x000303944ca09536,0x0005cb9d10d614a2,0x00062674cf73a00e,0x000639b5262911f3,0x000379f49e681d43,0x000ea07634bb0927,0x0000000000000000}}, {{0x000aea3b47740815,0x000ede22e76e20e2,0x0007e03afde6eca1,0x000f70d608d1c44e,0x0000b88d585444ed,0x00074d298cd8ec39,0x0001146c4c3f6754,0x00073274110e9ce2,0x0009cf1f4b12ae7e,0x0004fa67e9f4b4ce,0x0000000000000000}, {0x0002ef9318bf7948,0x0004cb3efdaff610,0x00059bd31047a8b9,0x000fad7c4b8b1235,0x000a02488482725a,0x0003b462badd939d,0x0009f8945cb99ab4,0x000c0f6b65c66a4b,0x000e97dd0bddb4b1,0x0009d75a1f797639,0x0000000000000001}}, {{0x0000ec0aca9d0f94,0x0002fb13ee984570,0x000e5ad047be55b4,0x00073a0845bc6993,0x000ffee41f2aee8f,0x0003c832041ac680,0x000bb4a740b12fcd,0x000521ebc1645e36,0x000dfcc7735a45c9,0x0008ef92b0fbdab8,0x0000000000000000}, {0x000805ed4e45e0eb,0x000584829d754db5,0x00036cc488a6c810,0x00060f1ec9632468,0x000c0f2ebc30d39f,0x000e960758390502,0x000f4626d1feec9d,0x0004f944bca363ad,0x000375dbfdeea282,0x00050ba887d0959c,0x0000000000000000}}, {{0x000857ce82a61386,0x000fab480b18fa40,0x000223002b9297b0,0x000f9b41f698e6a5,0x0005eb688e33b253,0x000cc09f30bec2ad,0x000eeb6333a5ffe4,0x000bc81e94524303,0x000091b660b277fb,0x0008fd03ed404dad,0x0000000000000001}, {0x0005dd59faaf5be9,0x000abe017edd5410,0x000aaa4856720e0a,0x000d987f4b1178d8,0x000fe5e556ef405d,0x00081f659d8f4002,0x000f7836cb450ed9,0x000350d35c2f69df,0x00095c15741d4705,0x0004c982d30172da,0x0000000000000001}}, {{0x000f854cfa0f1b9c,0x00036c27f5709e7d,0x0002fcca4c8efcec,0x000a965fa53691ad,0x000f70705ad9f4c9,0x0006ca89080d5043,0x0005cff60c807ea8,0x000ff2e47ec8fa95,0x000846288bda4094,0x00003dd7b4f68fa6,0x0000000000000000}, {0x000c953f0c60b7aa,0x000060469787d616,0x0009579f0ed52085,0x000faf3c529ad3be,0x0006f18223d47482,0x000c07ac1ad869d6,0x000437b5cb0dcd56,0x0004dc765feb592a,0x00004a294944df05,0x000184cb4ad2de82,0x0000000000000000}}, {{0x00003d153000960d,0x0008f85dc5ffb696,0x00009b3d9302c4f3,0x000fd9668bf9ae36,0x000a25bdc3c8ecf4,0x0005c1a7bbfdb2a9,0x000393a4a4463083,0x000a4d41df85c97b,0x000d92cc6610ea8e,0x000bee7a14446540,0x0000000000000001}, {0x000fe7092ab307cd,0x00055b75f48236e0,0x0009f206af987311,0x000191b95f1aca72,0x000b01a57a7e9b13,0x000784300caa5513,0x0001b4e8ad08534f,0x000e7a92df980dd1,0x000edd78871ce4ff,0x000f2fbe3e6a8b6a,0x0000000000000000}}, {{0x000cf8b0ae3366de,0x000c06074154422f,0x00007a17d21e5dad,0x00001e78c237ee85,0x000d108f5fd2183c,0x00098eec2dada49a,0x0001c303e35f7659,0x00091f2075445a12,0x0007426d8f5fdddb,0x0006af1dd7a92c53,0x0000000000000001}, {0x000c31da2f658936,0x000e72228504949a,0x0007646877ed3189,0x000cbac9e04fe426,0x00093f8802494ee0,0x000975ea85d9fdf7,0x00038fb0c9c6045a,0x000802b88cb118cf,0x00057e39ea12c877,0x0002548e571e0697,0x0000000000000001}}, }, {/* digit=59 [{1,2,3,..,}]*([2^236]*G) */ {{0x0001f89eed993384,0x000860d77e7f7ed9,0x000e9a249862cf0f,0x00026963705ade19,0x0005d0f929eafa4b,0x000a12f7eef6f18b,0x0009d590ff1861d1,0x000d6b67d2954ef5,0x000540dd418bcbd0,0x00096e83b51e5170,0x0000000000000000}, {0x0000a67de6f33ef5,0x000d0f090cb0d50b,0x000b8b3eeba89c8f,0x00026dc5289c0d96,0x000e0e6dd7431a8a,0x0000a660c8afde18,0x000cfa02cc76374f,0x000b7654494d397b,0x000476b8fd958a15,0x00097d53a314e324,0x0000000000000000}}, {{0x0005d2d913938d7d,0x0006d9d471ad5a92,0x00018a88bdce6ad3,0x000b90be599734aa,0x00099aa6c0fb7b20,0x000eda14b233c887,0x00024ee7dad41f1c,0x000cb7c643d13bb9,0x000e7d84ea63db6f,0x0003a846de4666cf,0x0000000000000001}, {0x000e6128e81e8c45,0x0001464a9235f4eb,0x0002db34ea2780d1,0x000ad3e8b3ecdbc0,0x000f8cdbe120731f,0x000f4318097ab5eb,0x00079ebbf1d4990d,0x0007e93c15830f8e,0x000c40a1cfba03ee,0x00068df76de664ef,0x0000000000000001}}, {{0x000267eeb458a4eb,0x000e492a1279f17f,0x000c76f729af11c0,0x0007339e92b8f2a3,0x00014e00c8ca3543,0x000dbcc01641f96b,0x000755e449dde571,0x000a0a0df11e5fa3,0x00031770742dc646,0x0006f53610d1c65d,0x0000000000000001}, {0x000e5b808553c438,0x000499c99fe83176,0x00019eef1a061f75,0x0007deb8d4c21a60,0x00033192fdd7ecc6,0x0003250ef2ec37ce,0x000aff8f6ed93441,0x00058d1e9777ac4b,0x00083407f0d67d5c,0x00079fd1b5287171,0x0000000000000000}}, {{0x0009d6152b9c90b3,0x000aff28f438100d,0x0000a2146e64ecd5,0x0009ad5b7e0c0df1,0x0003f6775181b0d1,0x0003c7a1b8151d7c,0x00035c338a3ef9f4,0x000e1fdd81712dd2,0x00034726a1f2597e,0x000cb3083971de47,0x0000000000000001}, {0x000c041200d9bef5,0x00067c85ff590dfa,0x0008b72aaea952b7,0x000265e7843ae9c1,0x00032307d7542004,0x0002dea503395a89,0x000e1eec7f73a8fc,0x0004b86c7eb53399,0x00021cf862926b2c,0x00019347a4f0820d,0x0000000000000001}}, {{0x0004f7b384cd7297,0x000acc1a4787e2cb,0x000a5590739ea069,0x000be73fa99d3f7a,0x000e7cf6cca23601,0x000960cc53aa83e6,0x000b86b5920b1173,0x000fa7ac9dbe20e0,0x00068bb6f6b3ef99,0x00064060ac6c56f4,0x0000000000000001}, {0x000626c189f97eeb,0x00092eb7dd82a1dc,0x000142f8425008f8,0x0004b241705cbf37,0x000c04c8483d101a,0x0002075cfd275951,0x000f282a7dae45a8,0x000263c98e81a9d9,0x000c331b130bf290,0x000c95c5f55addef,0x0000000000000000}}, {{0x000ac9a1c36e3c24,0x0008e09fb461cd04,0x0007bca251b2abd0,0x00098ad8fa6e8384,0x000087e953f04f5d,0x000d9f6c57ca3dcc,0x000f179679c5992f,0x000cc9cf93cdfac8,0x0000d1a320e29622,0x000580703c650a05,0x0000000000000000}, {0x000188e58d397fdc,0x00021860a160b5c1,0x000be9a3f426d729,0x000f8747311911d3,0x000b78a79eb1a864,0x0006b881dee2ff5e,0x000fc87ef83107b6,0x000ed139997a8784,0x00080e84fd894e5e,0x0003aa1a2f41979a,0x0000000000000000}}, {{0x00031707560bd53c,0x000c9501712fc58e,0x00010e30ced00607,0x000465e677b023a2,0x00067620a31c653b,0x0008ea62e5b10af4,0x000d99048d08ca5a,0x000d65af877831dd,0x00029f5ab5be8899,0x00028321d38a082b,0x0000000000000001}, {0x0006bb42378c6e38,0x000fb8ba4bc4d5d5,0x000a4ef2e4b28b7a,0x000b41f7c314822c,0x000a2882d9a51ae9,0x000e6c2280f2b327,0x00019697ce965ab1,0x00075708dae4a49d,0x000f1175eea346d9,0x0000e9572d2fbccf,0x0000000000000000}}, {{0x0007d4bad9839247,0x0002744af0bab5bd,0x000cd1e04b0ade61,0x00080a7fe21c3a53,0x000864b9871244ec,0x0003f6fd1428f483,0x000889d63b180bf2,0x0006acf748b0e2b4,0x000a061072996dea,0x0006607cdec9d5f3,0x0000000000000000}, {0x000a9858e242fc0a,0x0001fa2d38ce4fc2,0x00087521e69c709b,0x0005bae8f5996fd9,0x0005e131ac99f4d0,0x0002578fe3c3bad7,0x0002279c9d139206,0x0004b6fbac903ada,0x000292885696da36,0x000ddbd02ce1356c,0x0000000000000000}}, }, {/* digit=60 [{1,2,3,..,}]*([2^240]*G) */ {{0x0001074e0ee1b4c2,0x0001a0ff10eeb73d,0x000c77549f2e087c,0x0006808a5e2e0837,0x000e948c7156c74d,0x000c13bf7c11f82c,0x000a51472ee287eb,0x000b28c4e6f906f6,0x0000fef0b165038c,0x0002d8b6f1c9d932,0x0000000000000001}, {0x000d310ce2cf5a19,0x000c08add6b6df57,0x000dcd4cb28cd825,0x000e1cbe48bebf85,0x00051f1d5aa6a644,0x00008ba85cbebbd3,0x0001bc84d8a2aa19,0x000d343d2d77518b,0x000a9098229b988e,0x000a9f940fc8d07e,0x0000000000000001}}, {{0x00096ebc173a5d8b,0x0000ed54a67c958f,0x000ef67809a984cd,0x000abb728dd8453d,0x0009f4fe5f363de0,0x000e4fc4614b7360,0x000fee4aab1b83c8,0x000606d2158cb989,0x000096597fe56f7d,0x00057270734a0c52,0x0000000000000001}, {0x0004ef503a18dccd,0x0009b732b2f44d09,0x0002c29898debd6d,0x0005ffd4e0ef3ff7,0x0003830b99ae2e5d,0x000dd5fca5e1c94a,0x000e97015b084de2,0x0000e94504be6d08,0x00079eaed90fe0fe,0x00051eafa2897ddb,0x0000000000000001}}, {{0x000dd470cee4255c,0x0008ea907208e445,0x0001157ba3e551b3,0x000f94c51b72b693,0x000b183c616c9cf9,0x000fe84fcaaf1c59,0x00077c97ed67f1d2,0x000a1d1e1a09f1bd,0x000c2f47751550da,0x00038d58d345e7ba,0x0000000000000001}, {0x000d95b5f854d3f8,0x0004daa404c99ba5,0x0005a1bac7d29f41,0x000da46981c9d673,0x000652c1bc49956f,0x000e505f2a66bdcd,0x00081069783eab5f,0x00036f9996ab9237,0x000238170a7330e6,0x000670fa70e33da6,0x0000000000000000}}, {{0x000e86a58386cf1e,0x000572f15be04bfe,0x000e35f663e32b87,0x000f5c5294b48632,0x0001362fb4267165,0x00007dadeb7d3b94,0x000012e189d86c34,0x000d63e5f7805689,0x000b7e33561c7907,0x0003c0c0dc085fa2,0x0000000000000000}, {0x000cbe4f2b4f6916,0x0002f30cfb081da9,0x00011fe0a525ac2d,0x000bbd4632662679,0x000223e344c2d8fc,0x0000a08757b1ff41,0x00001c0a48229e9a,0x000456b8c92c6f71,0x0009a086c4af0e80,0x000d74c21360d8bb,0x0000000000000001}}, {{0x00000ce7164d30ca,0x000fedb34ef3a45a,0x000800620f8ac5c1,0x000c7c79ba6237c0,0x00088ff56f44997d,0x0008ab94745563d5,0x000df21b2b00a9ae,0x00086a286295b8d1,0x000426dbb4cf9b37,0x000ec830b7004300,0x0000000000000001}, {0x000a97f98f792db1,0x000f9d5a4e4b251f,0x00061b4d385d3a62,0x000b4cdaad987701,0x0002341727a73b90,0x000c4abf7e84f908,0x000f0ded814c4a3e,0x0002c453671bed3d,0x000a888690c8945f,0x00019a94087855dd,0x0000000000000000}}, {{0x000e5f28e7fb0752,0x0005ca705e5e780c,0x00093ca952d3af74,0x000eccdc7351cb28,0x000bfc12e9837fed,0x00014b93567e7bfb,0x000546247999f34d,0x000a3f729887c629,0x0006edd285692b0d,0x000fc9812e383cc9,0x0000000000000000}, {0x0001bc941d72f110,0x0009ba70199860ef,0x0002d090c33493b9,0x000503ff279e0c37,0x0005c3fbe286bbe1,0x0006d81c3e80f646,0x0008d3a0a9257bf0,0x000e402ee72a2a44,0x00092b91c6a5669f,0x000ad95315497ce5,0x0000000000000000}}, {{0x000b397c9c0b3f5e,0x0008573318572b93,0x0000e667f17a3327,0x0000b9137af5bff7,0x00017fb65a96b2e6,0x000188dfee9e25ef,0x0002c9edd117ab29,0x00015472d03d830a,0x000512ca1063aa4e,0x000adf9593f42bd8,0x0000000000000000}, {0x00043be475ba796e,0x00023dbbccf7b7a1,0x00080d4a4b140a81,0x000247748562ea6a,0x0002f53e144c7e84,0x0009ac8b6fa39d88,0x000b1eab451fe154,0x000ec4538f34ffe4,0x00076cc290527aed,0x000d83bcd8efdc10,0x0000000000000001}}, {{0x0000c5c5bcdaef57,0x000720046d980167,0x0000601ff33f7b5e,0x000e6b0aa07084cc,0x00007791af83b900,0x000dd856fdd2391e,0x0008d880430654d2,0x000f826068896340,0x000a4b443c176e8b,0x000c4e18c663e62f,0x0000000000000001}, {0x000d8ae0441a598d,0x00065c950e8cec48,0x0001316d53d11b80,0x000cd6863a5ccc8c,0x0008ced41a668fee,0x00076ba771bb4164,0x000b49a9a4bb4b6f,0x000e370974d5a9b2,0x0000485def9f130a,0x0001b84c25f49d20,0x0000000000000000}}, }, {/* digit=61 [{1,2,3,..,}]*([2^244]*G) */ {{0x000f43bc2dfb404c,0x0008b314169ebb20,0x0004d9ce016776ec,0x000b6f3c40cc814f,0x00075de6701fd64d,0x000be16687bc27b3,0x000c8ca41b2641f1,0x000e5c7ebdd8aaf1,0x00021918a667e429,0x000d9384d2d4cd92,0x0000000000000001}, {0x0009667398bc8b35,0x00026c502a6f1f65,0x000612fc65ae7726,0x00047588d1717c45,0x000b0cd0bd27306b,0x0007b68702fd9dbc,0x000a43a5beaed3af,0x0008d9e3bfb560d2,0x000c14b9b618c615,0x0002421dad1537ee,0x0000000000000000}}, {{0x0009e7889bf8b6ea,0x000292e957ebe27b,0x0002bd715ca3ae1f,0x000ea4756ae08fea,0x000f5cab67aaf3b2,0x00047caa37f247c9,0x0001b8953af0925d,0x000557e7bd1f409f,0x000979eb14ee5b8e,0x0008bb0e2890300b,0x0000000000000001}, {0x00078d6b71ea9467,0x0000c63dfcb1d01d,0x0008e6aaf05595db,0x00006ff49217ec90,0x000b8ab12df36451,0x0004207aff8489ad,0x000b85d257b835bc,0x0003706e08a1abbb,0x0002a5b7d71ad10a,0x00056ae224792f6d,0x0000000000000001}}, {{0x00028daca765356a,0x0000ee74680323bf,0x00005f51f95b6f29,0x000c6656c3eab37e,0x00038ce239752348,0x000cf8aff4ec8ff2,0x0003adc6745b80af,0x000e56c344a76be9,0x0006011d48a9f827,0x000ed4a3e016c1c3,0x0000000000000001}, {0x00096e22c7a80fb0,0x000891624b09ab2c,0x00049f6d4616a383,0x000b275d1cd7006e,0x000adb9075332618,0x000586e58c4079b5,0x000645e2b19bf36f,0x000f76906dc5820f,0x000f6bdd7a51a11b,0x000b67dd8137d034,0x0000000000000000}}, {{0x00095b8b650fd71f,0x00014965b39aaa82,0x0001270c9510690f,0x000b3a9f763e6fce,0x000be3f839143baf,0x000866c1890dc990,0x00074c8a0d6a0e73,0x0004b520d476087b,0x00081006ed8910a1,0x00052b16e6fb91bd,0x0000000000000000}, {0x00057756a63f7354,0x000a1ebe4b13d097,0x0003f1884cec54fb,0x000503924519ff97,0x00059fb9e4f42689,0x0002ce5e202d309b,0x00098e0004b85f0f,0x000b05c20b1735d8,0x000add1fbd4f54e0,0x000dcb178e2a7f34,0x0000000000000000}}, {{0x000b4ec871f1c2e0,0x0003b5de22756058,0x0000837f536100e3,0x0000c16f1ccaf424,0x00056dcf857da01f,0x00038c07ebb5fb6d,0x00096a096d6242a9,0x0003055c2b2c30cf,0x000a782e55f66ac8,0x0004f012cc9c2c3a,0x0000000000000001}, {0x000506352d9bc635,0x000b06aeaaa56b9a,0x000095186c35174d,0x0002167f537385d7,0x000cf421a089f0ea,0x00022c37dc99678c,0x000356bf33a69466,0x0003e97eafc66d63,0x000e3c0197b16669,0x000d912a0fa3fee5,0x0000000000000000}}, {{0x000a52c892d50f2a,0x000dfd8fc48ea89f,0x0004b09bae86a680,0x000a1e1278d67917,0x000370f37ae3b7ce,0x000f51107a8383d3,0x0005c8e157913dc9,0x0004c347e479bbd0,0x0007dfb63e7f7f02,0x000ac4a32c2410c2,0x0000000000000001}, {0x000c5983d275b47a,0x000f3ebc8a42a9a0,0x000db0533ac31f03,0x000cb9b707b4440f,0x00064522041e91b5,0x000076367218816d,0x00023be78c44489a,0x00060289668fa7d8,0x000b7bda9a033e06,0x000c041bf9880e14,0x0000000000000000}}, {{0x000df487e3ac46f1,0x00026f6aeda132f0,0x000f9138020c745f,0x000a8841334fb2d5,0x000c66722bd6a712,0x0005a1ea4533d309,0x000636323c57e66d,0x00008eb26f26bbe3,0x000fa479b5dc3fac,0x0008f02e50177e02,0x0000000000000000}, {0x000c92b56635aa25,0x0007f4d610ada23b,0x00010104e5566f0f,0x0004f4b30ea26b57,0x0004efd9675fd322,0x0001af8f50ca2f0b,0x000382d177aefb1d,0x000538151171ef73,0x0003347891a319cf,0x000711dcdab779a2,0x0000000000000001}}, {{0x0002b024db8d3d78,0x000aa5cc47fd4499,0x0004ca3c2ae301e6,0x000f6635a239d460,0x0001e72a93968b59,0x000f3e7cb493da74,0x00057a0e451c8476,0x00090539a4ae9584,0x000df123a0ccc6f4,0x000f3e4b36ee4a70,0x0000000000000001}, {0x000bf5964aec0226,0x0008d0d54e934ea5,0x000838881f3a4f9d,0x0001904c5759057f,0x00054f74d21e3d23,0x0009110e0965fa28,0x00025473e3fbb9d0,0x00066659568773f8,0x000e05953c3213d4,0x000de0c6c9fbf74e,0x0000000000000001}}, }, {/* digit=62 [{1,2,3,..,}]*([2^248]*G) */ {{0x00023dd4a823eac8,0x000e2984db5faf62,0x000d39d495d0b0f5,0x000841ce0a14e52d,0x000cb365ed8de723,0x000bcb1fe9b4ef0f,0x00047ee3aa7d5d2d,0x00032d33c7e0b190,0x000d3b9dde2978f5,0x0005329dbc97d12a,0x0000000000000001}, {0x000d165556c00ac2,0x00057fb3172c7a02,0x000beeb32c48804b,0x00099dadad774958,0x0007934b2bc9659e,0x0003fd281f90ab3c,0x00013abe477effe3,0x000378b329a3faa7,0x00036cbb9f3df235,0x00014562e824d0ac,0x0000000000000001}}, {{0x00078de5aeb19662,0x000d1f458b071bd2,0x0000313ed9b5b584,0x000ce5fe5f476cd6,0x00077007678c1c54,0x000258964a6d145a,0x000420c0c62f8fee,0x0008595f7056fa68,0x00089119263621f2,0x00019c5d8cf9f82d,0x0000000000000000}, {0x0000243d2e6cb7a7,0x0008d78d5a87bb13,0x000c4e517b3bcf90,0x0000f65dd0ef67bc,0x000d930e5dd35ba7,0x000eb9fb0741af2f,0x00075eb448314eea,0x00003702fdd3f71f,0x0002c0a91bac4835,0x0008e91ebd11ec1d,0x0000000000000001}}, {{0x000160f761d5cda1,0x000d737ebbdcd5d3,0x000d7809f98ac1a9,0x000dcdbd555d558c,0x000fa398a682b263,0x0004f2c8dcb516cf,0x0003f1fdc39fa308,0x000c8f35f0892119,0x000b1a2e7b6b0e00,0x00060305cb4b78de,0x0000000000000000}, {0x0005dc3804225ef5,0x000a4dd0142d36ef,0x0006183af50e0ed5,0x0006c670fcbeb371,0x0008629b90cb9a81,0x0002af3261b35739,0x0008aa6b6e9823af,0x000fbd19a0ec458b,0x000311a98270a0a9,0x000299fe388efd5b,0x0000000000000000}}, {{0x000bf04df8057734,0x000b1031cb2cfcf4,0x00013e25b6e0c3ad,0x000fa4cf3dd2ab40,0x00007758e2edfff8,0x00031ad907feffd3,0x000b4564baf111bf,0x00073c4f6a12eba1,0x000fad75513a8160,0x00074de7fc43bd94,0x0000000000000001}, {0x000d44eee593810b,0x000f1e369ffff5b8,0x00064f19da65334d,0x00021d0f5c2b9ceb,0x00091c5ca3390013,0x0005689acf02b87e,0x000bf7c3a49c8b54,0x000093f7ed7c049d,0x000a0a1d58d27784,0x0003d7726f20ba73,0x0000000000000001}}, {{0x000ec366cfe8b8dc,0x0005109510bbe0e0,0x000aea6451541d52,0x0007f0a613f8478f,0x0000f85f758544a0,0x000f2b250e479f86,0x000b98246494bdaa,0x000483bd40872db5,0x0001ef43cbf9eee7,0x000bc8abec7ccf7e,0x0000000000000001}, {0x0005c21b7bfcf30c,0x0003ee117f493af1,0x000fdb4b0534832d,0x0001fa1bf55f45c9,0x00078f7e3c1efc43,0x0008a7de78a32d11,0x000dc3559e7ee791,0x0004e7a865c863d0,0x0007e1e671e05898,0x0005634bd3bf85ef,0x0000000000000000}}, {{0x000d81691c2ab48f,0x0002541bcc0607cd,0x000da791a7f87cac,0x0008347771261610,0x0008e3bac250c120,0x000659e04001e2db,0x00052cf1b9282899,0x0009b392289990cc,0x000164d7d417f75a,0x000945df41fb11a9,0x0000000000000000}, {0x0009c07103c6ae84,0x000480fee72710d4,0x000b8360a2b9d155,0x0000e0d3d7e07da2,0x000d149f0388daf1,0x0002f71dfdfd1523,0x000418130ff86f14,0x0009f7346c3e8b09,0x000b2e35c5e699a7,0x00052b1c1fdc6ba3,0x0000000000000001}}, {{0x0003345adc3b52d1,0x00068ceb5ac071d1,0x000e11041a7e60d2,0x00074a2a70677323,0x00040734a03353e1,0x00041105a4c9d8da,0x00044e1f19873918,0x00091f314a743285,0x000322e1b26f9179,0x000d3d1613ed69ba,0x0000000000000001}, {0x0004543cf00ed5fb,0x00053fab663cf4cd,0x000be8cc8843f104,0x000f74fe45dc2276,0x0004319b78ce0e03,0x000389520a05dc90,0x000cbb592960d2ca,0x00026ed0dfe3e1c7,0x0009036fca8841aa,0x000549d9ea193025,0x0000000000000000}}, {{0x000d95d4b57fe6e7,0x000237e45eed99e3,0x000ddc0cb978fe19,0x00073f687eb46e14,0x0006f57bdaf6e4df,0x00047741a18670ac,0x0004925a46fbe2b8,0x000282f9632d0245,0x0002e144fc15a10d,0x000815c55aed10af,0x0000000000000000}, {0x0004dce0659c9bac,0x000b25a506cebbc4,0x00048b6559b03aaa,0x0008048a933863a2,0x00020d37a9de4c34,0x00020f440226cd5e,0x00074e9ee95db69c,0x00082f425e1eff1c,0x00033a6f8d820bb8,0x000ef06f95cad219,0x0000000000000000}}, }, {/* digit=63 [{1,2,3,..,}]*([2^252]*G) */ {{0x000e4e5c561d5097,0x000b584aedde8b8f,0x000aba27830c0d36,0x000c7d59c0f869dc,0x000b714a35cbc32b,0x0004bed4bc22d71a,0x000061f00680d9e0,0x00033bf0836adf25,0x0000d7fedb3d768c,0x00095c616b984e3b,0x0000000000000001}, {0x0008c5d5c16b3659,0x0009b2bd923c283c,0x000fbaf03219a32e,0x0005bdb0f0d8e95a,0x00027d3039b5fed1,0x000c59ce26d89427,0x000676fa1dec9a4c,0x000121992696f0b3,0x000260c98b8c7cfb,0x000541c1c9792927,0x0000000000000000}}, {{0x0002f821dc52854f,0x00009f01e839c81b,0x000f9520b0acb7e7,0x0005ef6ec4857ab9,0x0007209f9eda63a8,0x0006daca6651f475,0x000d6976e7173379,0x000240b37bfaccec,0x000b4437229f4ce0,0x0001910fe8a0ffcb,0x0000000000000001}, {0x0007819702adce4e,0x000559cf2ed75ea3,0x000524a7d80f948f,0x000a15733e1fceef,0x0008e25fd5510058,0x0004c29ed3586531,0x0004e51cb7d9fa11,0x0006f171b487caa6,0x0006163b82558054,0x000686de74000000,0x0000000000000001}}, {{0x000b150deff72861,0x0006369a87c08222,0x000222ff210ad76f,0x000b4d66f2177234,0x0006ffb6d673f874,0x00059b847a7a63aa,0x00088181fb601b85,0x00061d5a56e17f52,0x0009cad3b2dceae5,0x000b7064799ea515,0x0000000000000000}, {0x00071777678fbf96,0x000ee3fb840953c6,0x0006c82ee1fe6943,0x0000476345986586,0x00027b2c01a1da88,0x0001dd9ed1d2e620,0x00093b57ac9ecf98,0x000aea3ed52ca86a,0x00083c732ab42d43,0x0005274badd57297,0x0000000000000000}}, {{0x000860f86c3463c3,0x000fa451b92975d3,0x000e9c89aced751f,0x00082df00fff3b8f,0x0004d44ceed1d22e,0x00022e7d389ef4bd,0x000e91dec43e5b63,0x00003ac6cd725daf,0x0003c7139385f22e,0x000deeecc87ca1c2,0x0000000000000000}, {0x00051580221e0fc8,0x000941fbf97dbfd6,0x000689ac9e872372,0x000740f84611974e,0x00046e04ba0c6ce7,0x000419caa07a8f97,0x000565905b0cdaf7,0x0003cd2570033075,0x0003b2c015af7e40,0x0003287d54b47d8e,0x0000000000000000}}, {{0x000087653c1971e3,0x00077f0a153e5f28,0x0003ed97c2828991,0x000095935157a12d,0x0003722663e4ec8c,0x0008ec4fe824b403,0x000dd44aff641d97,0x0006da087485323c,0x00044e2cb2c2b861,0x0006eba170078d74,0x0000000000000001}, {0x000b5b83303bc746,0x00013dec62dad85e,0x000eb52890ef39fd,0x0007414a67a192cc,0x000ca32294492ed1,0x000e1460a8a16787,0x00024c190537d3f9,0x0004d8dd49fa5c1c,0x00025dcc6564966f,0x000872ce77f122af,0x0000000000000001}}, {{0x000f907cb543fab3,0x000c69a83a50077e,0x000cb4bde1d63e29,0x000c33fc44a3bb56,0x000f82a91020da98,0x00021551aca18ce5,0x0000524e8061c783,0x00030bbde84c8ff8,0x00080aaffd7e7a07,0x00025503d2cefb4d,0x0000000000000001}, {0x000d489c09cd7406,0x0003bbf72e670d86,0x000584e3d6cd578d,0x000c5357fb7dc505,0x00078eb6069dbc02,0x0003d4fa59d19b85,0x0000398d29e9ce8a,0x000efb99649fd29d,0x000ce49c616fbd54,0x000860686cd02ccf,0x0000000000000001}}, {{0x000b5280bf38c012,0x000b16e5d0e927a5,0x000e0fabbb77cb27,0x0009a5fc1a89a6d3,0x000a92cdb34cf1fa,0x000464dc9a9cf793,0x000eb464387be7aa,0x0007fbfde96cd4d4,0x000232f3e162772a,0x000656aee57c0a02,0x0000000000000000}, {0x000a4f88de057838,0x00017126373b6048,0x000e4a0f6263ace7,0x0001d00ce841a9eb,0x0004964f3fadfdda,0x00053a6795df2847,0x0007970db46fe5d6,0x000fc5cc5ee32eac,0x000634cedbf5f3ce,0x000fca10e755fd0e,0x0000000000000001}}, {{0x000aeb844e0e5a47,0x000278171b725206,0x0003ef95a8f2f67f,0x0001fdfb411d7c3d,0x0002cbc9db5d5134,0x0004cd3d499c831f,0x00090a75fa0db406,0x00072c8d72cfb8bb,0x00070a986050fdef,0x000f2a584d26e897,0x0000000000000001}, {0x000357b6cd8cc5f7,0x0006b375fe114c8a,0x000aa2296d0e1fc2,0x0007cba1e2fe623c,0x000b8ca73315ce03,0x0007e86db236843e,0x0005e04b5b70ddfb,0x000420198f9d4b15,0x000535cfa0692139,0x0005a2aa06d43751,0x0000000000000000}}, }, {/* digit=64 [{1,2,3,..,}]*([2^256]*G) */ {{0x000cc45663bc9f5b,0x000b2868f57feb89,0x0004bd3cbd6a2543,0x000a5e560bf63c0e,0x0000e648f4a5666d,0x000591427cb7d9cc,0x0005977ab848b1a7,0x000af4656829e85c,0x000ae8f7a4025667,0x0003b4ab876527cd,0x0000000000000001}, {0x0004ed81840ffbcd,0x000e4830db96c420,0x00026c352dd1b3e5,0x00003369497308c9,0x000023370174e547,0x000c6d8497a95345,0x000ecbfae86058c7,0x0008a32e4cdcae7a,0x0004e9eb567daf0b,0x00085eaf8dd7df3a,0x0000000000000001}}, {{0x000deae24e7511a4,0x000762cb23734ed7,0x00066bcd84d23939,0x000c037c989a46bd,0x000c06543988385e,0x0003f08c8acc808e,0x00000e7680dc66ca,0x000e4c3c5332a768,0x00063204acc98ee9,0x000db0a0ef46de86,0x0000000000000000}, {0x000b4a4e27fff289,0x0007eeb14e22b305,0x000e9d3141e930a3,0x0004f15435f5cd09,0x00052f55ccf3f336,0x0006c9377055f313,0x0000f610c74549ef,0x000c8d0207da4bf8,0x000b6ee97b1c2b15,0x0000920992fd2caf,0x0000000000000001}}, {{0x00043f2525d2ebb4,0x000811edb2cca106,0x000c996f27900e32,0x00092edb6f6af92c,0x0002dbdef8275bf9,0x0004dd3d26338446,0x0004401818a7ff9a,0x000d60e7694d8e21,0x00054e87fa7aec62,0x000f988bdd22449d,0x0000000000000001}, {0x00063c9fbe4e6775,0x00026d7e7ff11afb,0x000c6b3e18f7eec0,0x0005c983e08b80f1,0x000b75d6b5a4c84b,0x0005f99e3a4b0fd4,0x0005a7cfc4904ce8,0x0006c336a99a7afd,0x000e4a736ba1e62f,0x000595be20ba2924,0x0000000000000000}}, {{0x0008c92f010fc781,0x0002463423f6e871,0x0005f129e35dae8d,0x000d59f4aeff7db0,0x0000c963932f5dba,0x0005e468db3cf82c,0x000e23c6b7d10e1f,0x00006e08595910e6,0x0008880e8c76fb1b,0x000134e8c1259453,0x0000000000000000}, {0x000506649d87b671,0x00014c272ea4f089,0x000aa2740669dd1a,0x000622f8a6cc0d62,0x000e392244f6f191,0x0003dcbd9dd28338,0x0000c61a8dd7166c,0x000e4930a90ca39c,0x000d41296b979b8c,0x000037aa5c88b76c,0x0000000000000000}}, {{0x00051d16f31cd955,0x0003fd720fff5e54,0x0006c62e42ceacd9,0x000b72856f74fc83,0x0002b8a51db93ff9,0x0006ca983e7b6bb4,0x000e06f8fd893a36,0x0002491c6c8908ee,0x0008e9f64e123094,0x0005764984e58063,0x0000000000000001}, {0x000ad9aba979f347,0x0005557b9d835c0b,0x00089b7877984846,0x000ce8c3c6bb325d,0x0002e0fb571c388f,0x0007185f17237c5f,0x000ac5737bcf4832,0x0005f037df6f53b0,0x000b6f7ae34a972e,0x000821f685c7b273,0x0000000000000001}}, {{0x000e5575bc0dd4ad,0x00028eabf66053ac,0x00054861cbd6dc53,0x0005b123ea9fdaff,0x000c00ecf823c855,0x0005d8934d09e411,0x000eb090ae97a01a,0x000591dabc9c170c,0x000f751f273c40a7,0x000f0f52861011d8,0x0000000000000000}, {0x0002bc9a33075cd8,0x000bb779de4fde35,0x0002eb1b199f0130,0x000e29003c4457b6,0x0009ff04878d3a95,0x00004ebfeec1a9dc,0x0007d0d097a6545e,0x0008673c7b41f5aa,0x0007894e63c5c4ce,0x00005b385d1700a6,0x0000000000000001}}, {{0x00046d7efcbdeae0,0x000fbb2f349cfbe6,0x00022f14a9cfd187,0x000ef46f7fb5a2ff,0x000d8084df701781,0x000b2e7da6ada115,0x000273537b36285a,0x000d779e5cbe2143,0x0007b1bb342159b5,0x000321182d17ef98,0x0000000000000000}, {0x000974b9395d5c1b,0x000a203e9046670c,0x000c9fa51be4f31c,0x0000167fed87df23,0x0006d7ab1aee3553,0x0006c8a7b334d671,0x00037b8b3f821601,0x000677ee013df3eb,0x0007a3a1013ff132,0x000a7ed7d1a2e9a5,0x0000000000000001}}, {{0x000b3fd002806466,0x000fd4605cfac818,0x00085d2f0b811efd,0x000167145bb41efb,0x0006e3c03cac7ee2,0x00085c4b2dade36a,0x000220dcd3725a14,0x00032cf525a550bc,0x00014db66b11c84f,0x000013664e47ace3,0x0000000000000001}, {0x000a48858e7d464c,0x0002276f7bbfd1a7,0x000e24ada567d04c,0x0006a941adced466,0x000c270addbb103a,0x000761ca82f14e02,0x0004d0794b62798c,0x0007a0bec3f90326,0x000caf618966e8d4,0x00021a1f211c02e6,0x0000000000000000}}, }, {/* digit=65 [{1,2,3,..,}]*([2^260]*G) */ {{0x000c24408b5b4bc1,0x000d861e48c2aa26,0x0008746f93b2fb6c,0x0005f018515690c4,0x0008d76a3c1b771e,0x00093035c899fbb2,0x000d18ac338e0049,0x0001b4e7f02fa3d8,0x000fabf9b804c035,0x0002f83e6175e309,0x0000000000000001}, {0x000830680485a054,0x000962c1a8a622f6,0x000f94a3f3450d94,0x0007a83e0a44d62d,0x0000105319e21805,0x000a4a1ebdd2bed2,0x000f4863d6076c13,0x00034672ca137368,0x0006135e4ef4b1a4,0x00020b6692537ff9,0x0000000000000001}}, {{0x0001b7a5e08fe30e,0x00029eb048815ab8,0x0002e0a161f11e12,0x0001801becb84207,0x000ad5b394a58f8e,0x0007512807890edf,0x000f675b3e4e4773,0x0008c99841055d81,0x0003ed35c1050ce1,0x0006c217bd56acf4,0x0000000000000000}, {0x0000d6c8c5a1e005,0x000ddbaf53db5dcf,0x000c6ab4e4f6ee72,0x000e686032c8481a,0x000415c545af61b4,0x0003595ad60e7c0e,0x000f59b261ffe75c,0x000cf66fa7cfbf47,0x0002e7097fa1aaf6,0x000a8386b7977f21,0x0000000000000000}}, {{0x0000029a7619e46f,0x000f29f5c333074b,0x0009e45f3bb1eec5,0x00035aadf8396133,0x0000825d3e2a3176,0x00034ef799bdaba5,0x0007f38574f4d09c,0x0009085e808678d4,0x0004a57483db0387,0x00054465ae9f6d1c,0x0000000000000001}, {0x0002fb74fcaebc4b,0x000ef4b901e46eb5,0x00068ec4a861868e,0x000f51a07bab1199,0x000748f19df109f2,0x000d75da4f6a75a0,0x000f255613859652,0x000e60c8067759f7,0x000b663826b7b569,0x000f450533f4d440,0x0000000000000001}}, {{0x0008e66704c4911e,0x000b5ad20de07d3b,0x000dab27e9b7aafa,0x00052dbe3fb66eb5,0x000cf7ce856345ac,0x000025496cdf84c8,0x00082f095b8e1e29,0x000e8e6db4cd7761,0x000b0faa321aaa54,0x00088ae73fef003b,0x0000000000000000}, {0x000d643fd4fac454,0x000c4870e138d616,0x00069ca59b85612f,0x000a26a00889a9e6,0x000c093e3dad6fb3,0x0006ce66bb43df1b,0x000244dae036271e,0x000c05182a82fcd4,0x0002559d8958ca2a,0x000a7526838c8510,0x0000000000000001}}, {{0x00084b954cc2f383,0x000a776cd88b3801,0x00070c99422dcf3b,0x000bd45086f66f43,0x0005f7b81c0e8bc4,0x00004cad2493575c,0x00070ce4091825d7,0x0004f1ff4bbf4b9f,0x000d28bd9ac2a0a2,0x000c23e5ebf7a3b5,0x0000000000000000}, {0x000270e7ebdf9c15,0x000050eb783548eb,0x00081562bc5fd0b1,0x0005f68896b8a59a,0x00073bc130375edb,0x0001c5bd938ab1fc,0x000c19c89b28feaa,0x000f8d6e4b1c7f18,0x0009f7384e98a494,0x000a3f55131bf640,0x0000000000000000}}, {{0x000a27923d9331dc,0x000f04ffb6351b25,0x0007f29f1e1c9bc2,0x00069b7d91e80528,0x000d48a56cb26370,0x000d9a9a20ff75d6,0x0000b393f52dd397,0x0003703dee3c5227,0x000f9c1c267288a6,0x00083849651d4713,0x0000000000000001}, {0x000d56c853c2dd2e,0x000a93bc1a8d521c,0x0008735173646598,0x000967ee4685de4b,0x0004cf35701ef418,0x00080b116b6dbbce,0x0006b03c5acf7cf3,0x000fe839b4243541,0x000841fbd8d1a9cf,0x0003a6e1730d1f15,0x0000000000000000}}, {{0x000fdbea99958b96,0x000e01f76bf65ac0,0x0000c6778adf573b,0x000d0f51ffd85a6f,0x0004afe98c72d927,0x00087e8ec8173887,0x000d76d032ae57d1,0x0004df95e88800c6,0x000ec4042dee55d1,0x0008e8cd5760c30d,0x0000000000000000}, {0x000eac1084c10f00,0x0001c37bdb463a14,0x00076281603cbf77,0x00034037d48543b5,0x000f3b965ac3efc6,0x0009a7be5b6e5426,0x0003d0f87fba3664,0x0004ddb5ca9f2e20,0x000052649abbc317,0x0004b72eb6083655,0x0000000000000000}}, {{0x0001bc4f61438294,0x00002964a43b5d5c,0x0005d7c26171c634,0x000967cc93c0fb82,0x0004b96145dca1b7,0x000b5c4ddfd06836,0x0007f0eec5bd3c73,0x00082d7bf8f0d500,0x0005b93c7771d6fd,0x000475f222990f21,0x0000000000000001}, {0x00026e01b4722367,0x000926340c9a0a1d,0x0007edb2bec04b5b,0x0005d17d0417ca25,0x00072b41c7280efd,0x0003c942f670df33,0x0007910fbfcef999,0x000437ef3a577e3d,0x0004d4c9039005c5,0x000edddb0ceb3a8c,0x0000000000000000}}, }, {/* digit=66 [{1,2,3,..,}]*([2^264]*G) */ {{0x000a3a0634a3ce07,0x0008f38d14324956,0x0002232fc3562771,0x000d389e5a0479ef,0x000b882744b806a6,0x0000bd687af4d435,0x000d3172792b960b,0x0001f792e60e4cec,0x0009dcb17063be91,0x000c5902f6ffb4b0,0x0000000000000000}, {0x0004fbf6f215ba3d,0x000918e7c66f8fb0,0x00095b38bbb07b90,0x000022d201c5b207,0x000344fdf3937c67,0x0005a11142ee01b8,0x000cb5fc7b97506e,0x000c2ae4043311b8,0x000e1937f2450b7b,0x00045fa26a70cfe3,0x0000000000000001}}, {{0x000fdc4396bfa539,0x00092b7edbcb88f2,0x00019d35421db912,0x0000a538d5dee79a,0x0003b035e9ea2a42,0x00021709fe9cf14f,0x000a5b749703f94e,0x0002495b47e8690c,0x0002ef0574deb7af,0x000dd4b09d6324cc,0x0000000000000000}, {0x000f7df3b9fe6e0b,0x000f9e25c764e67f,0x000b9153d851593e,0x000822d7ef6d9489,0x000c9238e5449117,0x000bd3333b1e34e4,0x0006cfb58cc8198b,0x000b7b487650416c,0x000068c07a8085b4,0x000b7b5e20cc8eb3,0x0000000000000000}}, {{0x000af6a4691425a8,0x000eb7a958bb9efe,0x00085a7002151b0a,0x0006a8775208123e,0x000055575f5446b3,0x000528fdeea0c896,0x000a43b1b4d824bd,0x00096f550c5c7315,0x00050cdbb6610168,0x000b9c3638cd4a93,0x0000000000000001}, {0x00039bfed8d0ec30,0x000230c0cb3e1745,0x0004b3cb7f69dddc,0x000a60a97d0d2a3a,0x000c6d61d74827e9,0x00048c2e237c10e2,0x000c78dae64ccf95,0x00031e036445ee96,0x000bee13f244e4cb,0x00012ec220b81c78,0x0000000000000000}}, {{0x0008b837d4bef687,0x000919e15922b2f9,0x000c8afde9c62c29,0x0009534c95a1a3c5,0x0008f604b1043ffe,0x0007a01a13fa2f63,0x000393b04cd8a8d2,0x0006e26fd0c22660,0x0000808a072545d9,0x0003871dd10699cf,0x0000000000000000}, {0x0007dfe3a4ea56b7,0x000094c38223ef03,0x000e8b66c87d36e2,0x0002766ee28405ae,0x000f0a065b535e3e,0x00084a317ded4b87,0x000866d3f53ac0b0,0x0007a0ee55860ca5,0x000a7080382b21bd,0x0002f3ff1d58cf1f,0x0000000000000000}}, {{0x000760a0d077a674,0x000256d1eb02b933,0x000a86e63e76464f,0x000e22b473632441,0x000db481034e4b15,0x000914ef870834a6,0x0004c2dffa8bbf34,0x000d9d0466943feb,0x00031a2dbf893cc1,0x000615fa26911a87,0x0000000000000000}, {0x0002f76d13211f86,0x000b53e5f9871239,0x000bd8e3f6da4b87,0x000367de3555d6f5,0x00095ebc54c2b323,0x000413dbb2bd8e48,0x000ddef4e974c105,0x000de08da1d15f48,0x000eb47f901deb65,0x0004f245e4c32880,0x0000000000000001}}, {{0x0005b2c93a39a68f,0x00012def13c9b690,0x000a5eaf60ed34ff,0x000eed4546115d13,0x000acc0704820ad4,0x0000c499c60761b0,0x00013af5dd51e45f,0x0007a978e5524abd,0x0009f811db1ec09b,0x0005900dab7d3aa7,0x0000000000000001}, {0x0005f21e6490481e,0x0009c0ea3d3b19a7,0x00068df5edf0364a,0x000c93c95e1d6b4a,0x0008333e2dcc0b44,0x000a8fc7be078322,0x000350437cb9512e,0x0005c965c20fe9e1,0x000d3176a887068c,0x000004e870a54162,0x0000000000000001}}, {{0x00005c3b211947b8,0x00027fda98024305,0x000832a6aa27a459,0x00057be3feea006c,0x000ba0bb599ef407,0x0009c187eff74059,0x00032aa4ef6180b7,0x00072b398f55afe2,0x000cc5ddc46af4a2,0x000e611d5ea71271,0x0000000000000001}, {0x00085981da5484c4,0x0002661fa0fa34a4,0x00025e8fb282c8f6,0x00009d9542344d00,0x0005e720cc73e773,0x00081ad0388c6b65,0x00097a5b5f85f411,0x0006173a273c5fde,0x0000126c0a036ea1,0x00030085c778a65a,0x0000000000000001}}, {{0x000dd3a67c2984a5,0x00072c7824703af1,0x000bf0c69c5b39c7,0x0000901a46f942bc,0x000f89e0174be31d,0x000b6326f7d38bdf,0x000eadb91bfcc1ea,0x0002541868bb8787,0x000a48a8ba038566,0x0004606d8787616b,0x0000000000000001}, {0x000e290f5d5f8e88,0x000eb41d33d54569,0x000662b634f1ba52,0x000fc5049dfd1d1b,0x00059be51c909876,0x000b7406ba93e420,0x000475a49355b9dc,0x00048963ea182651,0x000985ceebcf7670,0x00062eaa85c80508,0x0000000000000000}}, }, {/* digit=67 [{1,2,3,..,}]*([2^268]*G) */ {{0x000b5648e1eb2291,0x000ba734c2f6e413,0x0008535398b202b7,0x000a8b23ebd7f177,0x0009fd3b0fc5e7ee,0x0003df55ddc7a0f1,0x000261d577641e2a,0x0008f496646ecb9f,0x000f2be9c112454e,0x000e02c23da6a9da,0x0000000000000000}, {0x0009d35c52fed679,0x0007671efd66d8e5,0x000904f29b91b401,0x000c352b084f27ae,0x0000123e88566129,0x000229faaea32636,0x00087f4c04620cfd,0x0005535f695ec91c,0x000fc2a2127c5854,0x000fa1c94873fa3c,0x0000000000000001}}, {{0x0004b028b8f44cc5,0x000fa18c73e470d1,0x00046af781c684d5,0x000aadf0eb44feae,0x000604610320e3e3,0x0008fffa44fd9c59,0x000908270d9d9d3d,0x00088a6283f3ebbc,0x00060d649fcec534,0x000e1d44a603fadd,0x0000000000000000}, {0x000740ae33023df3,0x0000135f6a91ebce,0x0003780772b2000b,0x0004747ae7ea71ec,0x0007f6f03b13d0e5,0x0006603e33fc299d,0x0000d28b6e9df68d,0x000a2043747f8604,0x0006089683aeee37,0x00024e9926fb8de4,0x0000000000000000}}, {{0x0006c9f15018542e,0x00079fb1f6fe5f6f,0x0005889ab7c13ba5,0x000129b7c5358418,0x000a9ac0306d8ad0,0x00008b37c84cfb84,0x000acf7da701dcb0,0x00014bb42427b3eb,0x0006e318d3d02d27,0x000958db234da419,0x0000000000000001}, {0x00031a9f2e6d1d68,0x0000ba7009240e02,0x00063eb8c05422c8,0x00081b3a6ec6a77b,0x000bc58689a5aa19,0x0006306dfb930061,0x00007013549ec203,0x0005410416293e63,0x0001a4d303fabd7a,0x000ac172f1e81c7f,0x0000000000000001}}, {{0x000b9ad3970b9e18,0x0000bf6af8e430ab,0x000f59d55e652348,0x0002bd614bc56b8b,0x000183df0a6ecc07,0x000ee1786d25c98f,0x0003feabcc84059b,0x0007b20a09a6f26f,0x000d600ce79a2dfb,0x000f39cf2e6f0393,0x0000000000000001}, {0x00072a39f3507cb8,0x0007042b1470af9b,0x0007da313b04804a,0x0000e590e67c9622,0x000cabec90cccc29,0x0005e76e6a796f29,0x0001637cadb620bf,0x000d15b03af38ec0,0x000dcf7634087520,0x0001906c0ca6b7d8,0x0000000000000000}}, {{0x0007eccab473c8b5,0x000354c80ff211e0,0x00045d2bf3c3aaa3,0x0005bdea352cfb52,0x00016f804d4fc256,0x000e5ad706ca34f0,0x0006619c96cff608,0x000490525e689857,0x0004163c78de4a6f,0x0007e4b87dad9b7c,0x0000000000000000}, {0x00035a48ce31e1e3,0x000c4a6aef85129a,0x0002e4b9afe02466,0x000a8b4fb7e5c1b3,0x000e4ea65ec8abb1,0x0009979db25393ba,0x00064b047eeb2086,0x000d6e5e56906ac0,0x0008d958b203281d,0x000de4155ed9842b,0x0000000000000001}}, {{0x00019bc174c6d988,0x000cf4d9f702e572,0x000883fd073431fc,0x000f7c52e0996638,0x000331a7f7f18050,0x000e9196a2374342,0x00087a7400e71f3a,0x0003791b5d724c12,0x000499ca89fe518a,0x000e565820d945a9,0x0000000000000001}, {0x00035b7cb9fac00e,0x000a632b3417a9e4,0x000077b9768bc095,0x000afb46dde432fd,0x00032553ea0ffde2,0x0000725529dbe056,0x00071cbdddb8ca1c,0x000edb41a198fcb3,0x000f5060041dd314,0x0009a1fe368a743c,0x0000000000000000}}, {{0x00059195e6de2d3f,0x00030ea9f4518076,0x000e3f066c30b9f7,0x0003bd981db2f294,0x00046e95c601e580,0x000782f5d49b6ae4,0x000f2a24bea15da5,0x000d57d82c482be0,0x000747b852b55a3b,0x000400c12ad66ee4,0x0000000000000000}, {0x000106fc9ab22be0,0x000f3ff85e4be397,0x00064c04ee049a9a,0x00068c1771b2f4aa,0x0009c56a4f6e25c6,0x0006c0243a7cc3be,0x000082558b6f8b1c,0x000d25ba47737910,0x0009a82551abc22c,0x00044f195c4a902e,0x0000000000000000}}, {{0x00037e57ac34630d,0x000fc2c030f2d54f,0x000b84aa880649ef,0x000b55a13ad19d77,0x0002091bd296d1ca,0x0008f7f0b28c0816,0x000d7580c469726c,0x00021840b8cfb847,0x000fd3c1cc59a8b1,0x0008b90e2778fdc8,0x0000000000000000}, {0x0006cc1f42f98900,0x00026c3bf2f82644,0x0008d5f8bb74fc86,0x00077c747df08423,0x0005d41c77ea13a8,0x000556d8fe471d93,0x0008287e98cde5b5,0x000c068f4d40279a,0x000305a88e400538,0x000e77c091d74bdb,0x0000000000000001}}, }, {/* digit=68 [{1,2,3,..,}]*([2^272]*G) */ {{0x000190a6f12cf864,0x0009e0eee766f86e,0x0005b775cd536070,0x00057c69d4566a98,0x0005745df1e07e40,0x00047733f9c06722,0x0006e2b1b1c2a5a9,0x000fc80987a24bcd,0x000f4061ae7293fb,0x0007d711f7042b89,0x0000000000000000}, {0x0003c1b0341e791c,0x000537daedd9c1c5,0x000495a12d7c48bf,0x0002d4a32c8c9765,0x0005a662fe9dfe7c,0x0007c6bad9faed52,0x000660c5c4df70a2,0x000bba7fb07624dd,0x00091b1d621abac8,0x000771b618ce5d4a,0x0000000000000001}}, {{0x000c915030a7a399,0x00068b673999f751,0x00008c22b2afe146,0x000bf6a5fc300d5b,0x000b3e178c0bceca,0x0009d38258020b90,0x000176381c171fe7,0x000e86f32623a2f1,0x000f64b9bf3a66cd,0x0002c55668f5ac6f,0x0000000000000001}, {0x0001812516e735d9,0x000aea3ea58c5dac,0x000356a5f10de279,0x000295b07e9f7153,0x000f586ce9eb4d08,0x000daab1a3f7c783,0x00000a0030b2d7c4,0x000c2198f3166033,0x000184aa9d0c0475,0x000b11a6fe88caba,0x0000000000000000}}, {{0x000ba5c8d0193b1f,0x0007644c52e9d2ec,0x000084d971b1a2c0,0x0000ba2904071452,0x00016420810c95b0,0x000726c12ee37ace,0x0005cdbfb3b34658,0x0001ddb8f12176e9,0x0002665465a782ea,0x0005989e91fb9ee1,0x0000000000000000}, {0x0000c16d55245f9b,0x000a5ab01d1b1ade,0x000186cc016cdfa5,0x000f20c1907f643d,0x000b819ce2692951,0x0001e463db499758,0x000551bae173a15a,0x000c9960164a1a60,0x0005b509da7db4de,0x000254d9cec8875c,0x0000000000000000}}, {{0x000b44e11c323d06,0x000fd5d6d986113f,0x000894e506cf902d,0x00052247fd0b1d00,0x000a2782247b185a,0x0003bd1827ee7a96,0x00075cc817a81ab7,0x000d58e21da1b5a6,0x0006b1f8c96f3b0a,0x0005eb0b4feab1ba,0x0000000000000000}, {0x000e1e70f2721b75,0x000160a2caaa6a94,0x000c595ff3de4a5a,0x000a75c84e2aab67,0x000e555f145b7c4c,0x000c6003a47731be,0x0008f07e7fe03b5f,0x0007c95ac06b0bfb,0x0000ec8f9062bb21,0x000d58a73aafef97,0x0000000000000000}}, {{0x000123c6709431e0,0x00010ae6e4e2793d,0x00084b28d12b01b7,0x0007bca51962e973,0x000f98e6a52dea7f,0x0002d8bb8dd35519,0x00063c8d202bed1f,0x00009ec87640cd7a,0x000e8802cf11aa3f,0x0002789d1734b8f7,0x0000000000000000}, {0x00015a8a3e8d859e,0x000534ae889a29d5,0x000da86637742cb4,0x0005ee22c15c8252,0x000ad4f9397a87f5,0x00093d8a684e2ab5,0x0006af7ba63ff2ec,0x0004f0fe6a52e297,0x000effff8321e195,0x000d2957562f8dbd,0x0000000000000001}}, {{0x00023e7069e42e0e,0x000d2239c3ca8089,0x00005746ae0d546f,0x0009bcbb8ee8194a,0x0005279f5c84f339,0x000373c06a06d19b,0x000c70d34e701108,0x0008ba438171e418,0x0007c7306769b5b5,0x000064bf193f46da,0x0000000000000000}, {0x0005544b033a42d2,0x00061e556329a54d,0x0006aab67ee7a477,0x000c61bcc63287d0,0x00034397f22f1672,0x00021907d612d307,0x000ccf64c77cc188,0x000f80df2be0b759,0x0001db9d853899e4,0x0007cb0c4b9b73aa,0x0000000000000000}}, {{0x000ff9f36c3349d4,0x000c3db537864c16,0x000d990835ee2990,0x0003c5fb1d408a12,0x0004b5ff931b6504,0x000452158a1b1e0b,0x000db8a2c29f72a6,0x0009d61be31c5985,0x0007a2320489621d,0x000480174d202617,0x0000000000000000}, {0x000294c195148880,0x0009ed88751bd34b,0x000f46ac8a70ae99,0x000917e5c0560f97,0x0002525c8ba24922,0x00048c3502a88bf3,0x000ee6a458ba7134,0x0003f607a14e42a8,0x000dd29054842573,0x0009c1acd66ae0e2,0x0000000000000000}}, {{0x000edee700e2b9a1,0x000ca05fd3e47e10,0x000775354363597f,0x000b8ab9d14d9e5f,0x0009809ae6cb63e8,0x0008a4dd84740965,0x000dd249f1a5c96c,0x0004d2f79af0cb6e,0x000166e5361d2b7a,0x000692fe3d22a60e,0x0000000000000000}, {0x0002fa6f8995a329,0x0006e396d7a363f7,0x000d92f57cc488ad,0x0009d1958510a286,0x000c0b888aa8bf0a,0x00042decec317136,0x0008b9bdf9fc71bf,0x000ac0298d41b6cc,0x0009ecbb249e5d99,0x0004db314b57f810,0x0000000000000001}}, }, {/* digit=69 [{1,2,3,..,}]*([2^276]*G) */ {{0x000d708c668b7357,0x000d96ce839038b2,0x00020e1ea62ce28e,0x000713c58763eab5,0x000e2c4523fd6ed2,0x000eae1cb271027f,0x0005e4f9c4b8cf67,0x0009601ad02024a9,0x0007d73ac0716494,0x00064337442ffcdd,0x0000000000000000}, {0x0007851b23ec84bf,0x000beedb8574d7b7,0x000286ebfe9b645b,0x000e45ce0c8710d8,0x00056a79aecb4766,0x000f379f83c2d312,0x000bbc5340ea164b,0x000df851521a164b,0x0009d5d5e1ac3081,0x000081b205779b7e,0x0000000000000001}}, {{0x0003e4b56c489ffe,0x0000450823173431,0x000479ae5276717f,0x000cb05ce3d436d8,0x000ddf2257834d02,0x0007cf804300a63f,0x00048d555acde6aa,0x000b3233d0de457f,0x000aa55b4de5db66,0x0008a60379d9ac81,0x0000000000000000}, {0x000e90717067058f,0x000132c47bead613,0x00090e8a449f2111,0x0001c278b92dfa6c,0x000a20e5052e4286,0x000d62ef7fbb21a8,0x0005d03da29cea2d,0x0002b105405706ce,0x000dda27b321921a,0x000d13a8070a212b,0x0000000000000000}}, {{0x000d23cf55c45926,0x0005b98778f5f299,0x0001705a5c8c8b02,0x000b88f43919b71b,0x0001fcb92372e0d5,0x00043296e160fa37,0x000a4970a89cc719,0x000334a3ae695fe1,0x00051e4b95dec2f9,0x0004d6275a594212,0x0000000000000001}, {0x00047e08dd859c11,0x000f2faa12f1b2ff,0x000ffb55ea0ad152,0x0005927a2d49016e,0x00063e898a743956,0x0007e768ee6cdbde,0x0009ce79201bbe74,0x000b64e8832a0a06,0x000cff0774d3af5c,0x00081d58cc25a522,0x0000000000000001}}, {{0x00027f0e1b46fd00,0x0003f1c1b9a1af5b,0x0003c2c754fc491a,0x0007d3165cbaab1f,0x000360310665c2a7,0x000a6d64bd760e64,0x0004ce1abfa1968d,0x000d2b0e1701fb5f,0x000d3c4d7b466c4e,0x000f912ebf21257e,0x0000000000000000}, {0x000f6e44d2ef47a9,0x000cdeddd0d09650,0x000acd3234c8ca37,0x000cba5fb7244def,0x000f3acca56c2d39,0x0004d3ff0e42e4fe,0x0003498d03959e10,0x000b101ed923e651,0x0000842e240deada,0x00047140cf65c53a,0x0000000000000000}}, {{0x000420de7a3cca92,0x00078c40b5d961dc,0x0000669c0650c56a,0x0006512b20ea2fcd,0x000c80cfdc1ced7d,0x0002dc4c42793f28,0x00014af2a2c66b61,0x00038712d0f465ef,0x000a3e10f498de28,0x000eefd43378b1ab,0x0000000000000001}, {0x000182339af2de22,0x0000f52743e62529,0x0007cb967f975c8a,0x000a495f3b942e5d,0x000442c93c4c7a6f,0x0005ea4e81af911e,0x0001c3361393032e,0x00046ad975cf453b,0x0008fb85fbd84437,0x000e9f19bef58359,0x0000000000000000}}, {{0x0001c8a03a758373,0x0002ff5d3c5d987b,0x0008d28755f9b053,0x000696c9a6811aec,0x000671a05c762526,0x000b50917885c6fe,0x000e435b1cd97329,0x0007d6424b129ce1,0x000fb69b5d25c001,0x0005bf8fd3449e7d,0x0000000000000000}, {0x0003b3b4745aa0fc,0x000a304f13caa8db,0x000c42581d38c65d,0x000a26e3f1637449,0x00075086fb17831b,0x00070bccf51f20a3,0x000ec67794f66bbe,0x00008759114e8fb9,0x000e55fefba15c3e,0x0006b06274e840ba,0x0000000000000000}}, {{0x0001392a85eee65b,0x00037ebdba8a73a9,0x00057c70feb31623,0x000f9841fe6064d0,0x000abb8ea58571cb,0x000f4d78e10f9265,0x00010194ea34ee68,0x000ee932bccc86c6,0x00018b05ba4d88af,0x000c7f1b666c9e95,0x0000000000000001}, {0x000bfc49e59e8fd1,0x000ae405208c75f8,0x000d373c5a99df54,0x000a977279933e71,0x000da64aa0b3f5b8,0x00036d2c0da96b6a,0x0002eed5227ca046,0x000b6e0ffb64c414,0x000baa05111d0f26,0x0006496cce8a3203,0x0000000000000001}}, {{0x000c440343aef952,0x00019eda15115cbf,0x0004c0ca17c7be65,0x000b899e1e404697,0x0006bd56cb968d39,0x00077f25afafaffc,0x000e8460c48baa89,0x000cb8ddcae733c5,0x0004e7b4d8db3dd6,0x000d4730c42ef0ea,0x0000000000000001}, {0x000ded4336e0e996,0x0007761c36485b3b,0x0003a9ef9b460a85,0x000ea119c163b2e2,0x000f8699c32d39ca,0x0009afc21d6fbf2a,0x0006105b2f30acbc,0x000d2782e1795cd4,0x000bd0296c5de1eb,0x0003f540db331e94,0x0000000000000001}}, }, {/* digit=70 [{1,2,3,..,}]*([2^280]*G) */ {{0x000566c4dd75c1b4,0x000a0570856265b3,0x000cbace31affa63,0x0002b4ed64645336,0x0006de49945b2d79,0x000ffedb2ccdc41c,0x0001239fc3fec1e4,0x00056c094341fb38,0x00028185bb5868f9,0x000adaf680572da8,0x0000000000000000}, {0x000e0585aa2d876a,0x000b95480f8f0fbf,0x0005be334d530bd3,0x0002f278c2d3c86e,0x0006b676d6c82d76,0x00039dec8e1488b5,0x0003e4b756194ec5,0x00094e5ad8a2c0fc,0x0001d4129e01cce4,0x000c459cb7e94c1e,0x0000000000000000}}, {{0x000e172f71314c57,0x00073776d707122e,0x00007937b43cc86b,0x0005775ac42e1bf4,0x00055e0abab130a1,0x000a4930e58a6f41,0x0005a237af5f75c8,0x0004f7ffdb8ee4d2,0x0008fe7af47745ba,0x000467da1f09c11c,0x0000000000000000}, {0x000ab833ab90a6b8,0x000669bed4019358,0x00007b7fe4d74f45,0x000d834f00a5516c,0x000f035a36d318fe,0x000f8a31bb46f3d5,0x000972946e1df3bc,0x0001ef24a7e886c9,0x00085864c383ab5e,0x000a5b85a50c0d32,0x0000000000000001}}, {{0x000d65b66d82688c,0x0003872c2925e382,0x00080fde81ac79d0,0x000a2b38a2432027,0x0005fa34422b6bc3,0x000948d55e24a659,0x0004efa7ed8f149b,0x00071011867cfac1,0x000bd1e94e578bbe,0x000803efa0276501,0x0000000000000000}, {0x000f7389f88ed003,0x00099b4f58dfa2c9,0x00027af2024d3bff,0x000a0ca5e0ca7fb1,0x00083782dbf7ba09,0x0009fa5d6101098d,0x0005231abdbaa4b1,0x0009c03b0d70ddb8,0x000cba60cbb85949,0x0003ba8d596ce326,0x0000000000000001}}, {{0x000ec042211830fd,0x000f78b67d56f78a,0x000d0dd5f0085f0a,0x00077ef6d1879493,0x00009d412929cede,0x000f8f47fc6254c3,0x00038136cfbb6a12,0x00090a561c304af6,0x00064012770283e0,0x0006e8c77dd363b1,0x0000000000000000}, {0x0009730231689c1a,0x00078a2910104065,0x0006adb22ec70366,0x00007eaa5919dc9a,0x0000eff75ea6bb96,0x0001b154022f103f,0x0002e9dc4300dcfa,0x00023ebbf1abfdcf,0x000c7610a1be47bf,0x000ee8e48e43b23b,0x0000000000000000}}, {{0x000366222079ff20,0x000dd6c255282fb1,0x000e5f65eafcf45b,0x0009b30515c02959,0x000efd5074c2f0d5,0x000460bf3169d34d,0x000d88198c4daf0f,0x00042d35aae9cd4d,0x0006f8fb3a3e2b92,0x000e5b7ee19179cd,0x0000000000000000}, {0x00015c0c8bdd26b4,0x0009fc2499885330,0x000c27ee4ed9b18e,0x000e30d901ee8c44,0x000a438c4d057961,0x0007a847d74e4722,0x0005e9ebd34c3ce2,0x00049ec1f371fc17,0x00062cfa628ad626,0x0000258cb8ba2199,0x0000000000000001}}, {{0x000414eef61746f8,0x0002f44b16d63548,0x00091c53690466a2,0x000700b4b9b4826e,0x00069ba41d6fddfa,0x000f48b184a9d1c2,0x000af1a9a1ae5623,0x000688445e2f1d66,0x00028a0ef16e7621,0x000ea0a509e87455,0x0000000000000000}, {0x00016c4ebf9d1f30,0x000002405c88d64d,0x00021995ea2cb159,0x000476f59206340d,0x0007fbdb47138c1b,0x0001fc51a673c4a8,0x000c132d81d7d81f,0x00033035e2c568d2,0x0001981e0c2e86c3,0x000c9f25fcaa15dd,0x0000000000000001}}, {{0x000b2a49ca5dfb81,0x0008d370aadb7c4a,0x0009f4ebf1398343,0x0004d610d25c9ac8,0x000b49c7f0f75d8d,0x000cfed5c3ca14e0,0x000cd7f4d6f7590d,0x0007d93cbfaa36f5,0x000dce79a65cb3d1,0x0004b4bd97f1011d,0x0000000000000000}, {0x00001207087dd6cd,0x00049477a85a518b,0x0007671964d279a4,0x0001d11aff88af2c,0x000a1dbb6c2c5f27,0x0005ba326b82395c,0x0003c2898f431018,0x000463dc513c0cb7,0x00069f2786b20305,0x00061fc5c18db944,0x0000000000000001}}, {{0x00080adc636061c1,0x0006244e403a263d,0x000ad04e1deab320,0x00059720dcbb6130,0x000d66e8505322a2,0x00060fb3f5231b1a,0x00049e1cd79b6e2a,0x0006179c366e663d,0x000c6ea0d01277eb,0x000473883c4ffde6,0x0000000000000001}, {0x00040167fca5210d,0x000d95aec71f687e,0x0001c63bde59a231,0x00074dfa4af79a44,0x00060fd79e68ddec,0x000b613ae2a19527,0x000036b08e61ca70,0x0003e30d2b549e73,0x0008fb383d922e0f,0x000aa028c146216d,0x0000000000000001}}, }, {/* digit=71 [{1,2,3,..,}]*([2^284]*G) */ {{0x000090e2290855e3,0x000c63856faf70c3,0x000a537fff7cf9c3,0x00002007d0317a7a,0x00010dc853b3261c,0x0006ccdf2c616875,0x000385cd6f188d53,0x000a2955fa1d26fd,0x00087bdaef2d7d6e,0x000b0f3173148e30,0x0000000000000000}, {0x00084c9a254216ed,0x00047cc0770de6d7,0x00035e4c8fa4bf8c,0x0000f637aece660d,0x000adedb7b99e891,0x00082ce72b5ced4f,0x0001d4d0fa07446a,0x000194600c851570,0x0004ffcea4152f30,0x000c96f31c15edf3,0x0000000000000001}}, {{0x0005b1c7831bdcc8,0x000d027bafc7d23f,0x00050c19efdbe5d1,0x0007a7533cdce225,0x000573af279d2535,0x0006015a5e144120,0x000803b571412097,0x000eb203384ac91c,0x000edd68012ba72d,0x00091d825c3d8d2b,0x0000000000000000}, {0x00023553a39f8385,0x0005b8eaf27fe164,0x000c4539fb7ef933,0x000adc9ffa5830e5,0x000950a5e503466b,0x0003a2a96a1dcbb8,0x0001a89a62dca0dd,0x0001d5f98db48a88,0x000554b9506e0a31,0x000dcd69efeec8e2,0x0000000000000001}}, {{0x000b8cbe4b97fc6c,0x000e5a71915ba245,0x00044263935f5290,0x000ce189775a8de5,0x000cd0549c8def51,0x00027c89477b9645,0x00047cfbc54728e8,0x0000c7cb6412bf4c,0x00016bf97806ea22,0x000feea61b447d92,0x0000000000000000}, {0x000a3fafee06d0a1,0x00032a2cf4c624fa,0x000baceff4ee9dd4,0x0007411d429aa2e7,0x000d154759f7bffe,0x00091cde409d4d9c,0x000a9a31ac9508e0,0x000deb0f736891db,0x000c17f78c058b52,0x000b43e218c9736e,0x0000000000000001}}, {{0x0000f4f238352945,0x000f07d445a023b0,0x000551441addd54c,0x00008f85e62fb5bf,0x000ffd275f3aa334,0x00001eb4ed1f4e87,0x0000af1b08c2f8d7,0x00093b5987facbec,0x000542336f0bc311,0x000587219a8c1237,0x0000000000000001}, {0x00052f04dae724bc,0x000e221a68b0a55d,0x0005bdff6f9d5fa5,0x0007e3f2da24e831,0x000628b43c649948,0x000a393f548cc549,0x000acee934d621cc,0x000e0ce12d1b52e8,0x0000b93c4f0e6025,0x00077116663ffdcb,0x0000000000000001}}, {{0x000b53f717a44956,0x0002c65fee76e1bb,0x000ae70d2da363ec,0x000cd6887a61f9c3,0x0002283a4e23325b,0x000ae6d909c60aab,0x000702a1dcca3dd1,0x000938d6a31c5517,0x0003e01f167bc2d3,0x00067596be65d549,0x0000000000000000}, {0x0007978a4e132cb0,0x0005df10adf1702e,0x000364f7e05324c1,0x000693e3866569f8,0x00082e303b6c9df3,0x000298933d134854,0x0003d7696e64c215,0x0000f465322046cb,0x000e839e686c1c09,0x000b7f8ac2e6f682,0x0000000000000001}}, {{0x000e71627b708629,0x00012bf54385d85d,0x0007bb4ab478b057,0x000a3b2ccc6b5489,0x000f67fa6f6a05a9,0x00073cd5233bfef8,0x000c4c4f505a80c7,0x0006a3fe8c185c9c,0x00059e110f37ae33,0x00054cb440dc7a62,0x0000000000000000}, {0x00050c98bc7b0e1e,0x0005a04b3793331e,0x0003b8d31034a8aa,0x000c95dac900df01,0x000fd52027ee1c99,0x000b5be3aeb891a1,0x00042f3b68574224,0x000ae00bb37d5ba8,0x000a7f31f3f36375,0x0008c304743a2813,0x0000000000000001}}, {{0x000c7e03b7aa645a,0x00091f7e39a28977,0x000995d7d443d68e,0x0009f39216c442e1,0x000b376cc21c4025,0x000705644f75967c,0x000592e3b90bca20,0x00056be0ef613507,0x00097f2f7456e836,0x0004b46438409baf,0x0000000000000001}, {0x0005a21df85e1c6c,0x000b0ab454500393,0x0004c5912b476c6d,0x00065a0d1aa49d94,0x00059cdd7e7069d5,0x00090a402b7eeef8,0x000283db40b228bb,0x0005dcdf2c268733,0x0005a42d37d44810,0x000b80e5d1af0360,0x0000000000000000}}, {{0x000c14cb537e819c,0x0005f2b3bf6b7569,0x000cc275187a0bac,0x000925ef6c2d559b,0x00025a54533380eb,0x00019f0d6cd0382a,0x0001433bbf74a021,0x000bbd994d4caf68,0x00027772c53999a9,0x0003af249226a38d,0x0000000000000001}, {0x0006a46b5b493127,0x000bee887c8f7779,0x00045dd063eabbf7,0x00029199a0a8e117,0x000918d22e28aea4,0x0000ecebe77e69a9,0x0007cecb0ed2deab,0x000637aa98d20edf,0x000a194790e52888,0x00060c73078fbd0c,0x0000000000000001}}, }, {/* digit=72 [{1,2,3,..,}]*([2^288]*G) */ {{0x0009af391a8697ed,0x0007fe5bb7320546,0x00080d05ad03f5f9,0x000f9b7973b1a3ca,0x00033b52add9800a,0x0003cc487ccc82c5,0x000f71a0da2ae069,0x000c060c7047e46c,0x000a21503aeb64ab,0x0004ed0075b1d33a,0x0000000000000001}, {0x000a2bed91298551,0x0000c49a79f6b129,0x00022374a19da463,0x0001305962f001a1,0x000a3a3cc4dcc90a,0x000188b4cc026cef,0x0002ff30fbb1d3fb,0x000c36e3761cad09,0x000dbdbdc6354b93,0x000b2ab73317cff3,0x0000000000000000}}, {{0x00003f3665635e4e,0x0004e17fd85da26c,0x00052fd006ed5f69,0x00032d252f043a61,0x0005c8bc9cc74510,0x000f5370ca9348d5,0x000540b56333c4c6,0x000bc9a5ca533610,0x000d8071b716d25c,0x0002367337f70a39,0x0000000000000001}, {0x000db6fc5387c11b,0x000cfd3251b14397,0x000d84aa2bfdb755,0x000e38100cc3e62a,0x000046071f1f89e9,0x000e7012d9e47fb1,0x000e6ad97ec5c7c3,0x000698bc4de4f6c7,0x0000c6a07a4e7cef,0x000198a03a3a1224,0x0000000000000000}}, {{0x0003b8713123ec24,0x0000419a51d2d151,0x000c8ee7e2c9c855,0x00039f110d3d8f17,0x0008ce870e320ac3,0x0000d4e71030e599,0x000ace1a5cbbd4da,0x0007c15bfcfe41d9,0x000408b36096093d,0x0006b26a0c56d39a,0x0000000000000001}, {0x00035ac9181317f5,0x0008d46d26280ae2,0x0003c29370c4bff6,0x000addee48f7eaa2,0x00030f605627b203,0x0003e03ba6674883,0x000cdd81ae186660,0x000d8bc04a9667b4,0x000cbc45ee0c1b5b,0x0003d34e81dc5ff7,0x0000000000000000}}, {{0x00063b161dddd94b,0x0003d7c93f0cc576,0x00022d6ac11071af,0x00012d84b9149bdc,0x00088e44e4632e63,0x000448cc8ec50d4c,0x000f89a6c85277ac,0x000e128700eabfe4,0x00042928ea38e5f2,0x000e293e261880b7,0x0000000000000000}, {0x00051028cc113b68,0x0001919b6a14e2fa,0x00082dfd5da09549,0x000ca662e13022a3,0x0002996fafc24233,0x00018dea4f505fe4,0x0005a2d96182166a,0x0000199ba55815ea,0x00077232622a4ac8,0x000311b13c3b8133,0x0000000000000001}}, {{0x0008673adf41d204,0x000e2a0a390575d9,0x000dcb844f35fe0b,0x000b6f4f917550d3,0x000fc6ecf7285d09,0x000925f580342d9d,0x0008746022d9fb4c,0x0001b6b73d4bc619,0x0004aa1c30d7a3bb,0x00003bf32bccb3c5,0x0000000000000000}, {0x000783e73d6e9052,0x00006db6e57f7b8e,0x0005d1afd274f869,0x000318770758e016,0x000290175b314342,0x000e6d25df464413,0x000da9ee1f0d5093,0x000297855e553138,0x0007c7b64937a717,0x00057ccbf262664b,0x0000000000000001}}, {{0x000d9056eeba30b5,0x000355a8c404c7b9,0x00039ffec5e11fca,0x000c3ac7b4f4c637,0x0001ace1869851e4,0x000e1816afc7de47,0x000d517fb7e6978f,0x00040e256f62bd56,0x0004bb4c53034a6f,0x000aa98eb4b9ad2d,0x0000000000000000}, {0x000fd2909662ab1d,0x000c55f8463596cd,0x000074f62f74b11c,0x0004dfc43f12c5ee,0x000ad69405653ae5,0x00089f1d6e4668a4,0x000187ca431697ab,0x000831cc4eed080d,0x0003a69f7d775edf,0x0004e434435eef6f,0x0000000000000000}}, {{0x000a1403851eb93a,0x00085c9ae49b53f2,0x000926a512455b57,0x000ca729dbef4a6b,0x000b8440248e399a,0x000191c77a9a0e66,0x000873c8f27a8296,0x0005408861a08ed7,0x0002bbe9c5e3865f,0x0003549235be42ba,0x0000000000000001}, {0x000a46fbe3334020,0x000abf1524bdbc9e,0x000b376fa382ce55,0x00075b35cc1fb214,0x0000910d13b19369,0x000cf5d3212ad3b7,0x000c7e93b691b3bd,0x0001ba22d0312eb4,0x000285b3975e5da3,0x000c999e2ec96eee,0x0000000000000001}}, {{0x0005bf15f46be575,0x000a1061cb09c821,0x000ae2de789e5912,0x000cecccd84851c6,0x00001b95ccd21d74,0x00032dddf26a2851,0x00049210122d3f6d,0x000f02c5d952db55,0x0004be99796a4aa1,0x0004078cde88aab2,0x0000000000000001}, {0x000d753b80855f9f,0x00078288aff9b92c,0x000f7cdce61cc49d,0x00048cc3dac4e445,0x000cb0ac2a937fad,0x0008c5bdda956fdf,0x000bb3e81841ce29,0x0005170e6c819f12,0x000efd73ecab58ad,0x0000f476a3a48130,0x0000000000000001}}, }, {/* digit=73 [{1,2,3,..,}]*([2^292]*G) */ {{0x0004f332dc67a3c5,0x0003213d82a4383a,0x0000fc0621356af6,0x0004ca32ca05acfd,0x000c1e80103ea886,0x0009dd0ff4c2e9c7,0x0009d764c64b7589,0x000680c128a8c988,0x000fdb7cd881a125,0x000ec5f09f58ad77,0x0000000000000000}, {0x000ecd4f9cda86d6,0x000c4c41a633a8c6,0x000847c2f58ecb1f,0x0007b29592dae51a,0x0006e268f50e3a7d,0x000a27de2a3b5eef,0x0006d540d7a599e3,0x0000d01f9b571491,0x0005e52e5204fbca,0x0003d9eb48615c67,0x0000000000000000}}, {{0x000d9eaa867420c4,0x0002f7f5caa2ddb0,0x000c31038c0ddc32,0x0001596a08fb4b57,0x000a6d9ca6980a65,0x00095c78a8ab32e2,0x000ba78e5808eeac,0x0004f5f9923d5a32,0x000ad1c8d3bbece3,0x0007098f8b845926,0x0000000000000001}, {0x000843645beef787,0x000fa28875d75316,0x000e13608c5a90e9,0x0005556eaf90c364,0x000dacc40e05857e,0x000c5012b59e332d,0x000230b2b76768f9,0x00032932d53c8a76,0x000999fbd573bdff,0x000840eee9300114,0x0000000000000001}}, {{0x0002362363f6901a,0x000be66748446167,0x0005f5c47c0db36f,0x0002fbb39fb54024,0x000e344525a7871f,0x00071375bdbedf63,0x0000bd89f085fb8e,0x00001c59b6e647d5,0x0008031fa2f2ea43,0x000d9b58012b6657,0x0000000000000000}, {0x0003015fd48eca8d,0x00082cfde2151d47,0x000e4d908c99616e,0x00004977d4ec3b2f,0x000f513df9ad204a,0x000b66641e3ee923,0x0009df2175bb5d92,0x0004cdb5c3c90fcd,0x000de8809fac5725,0x000985c6981a627f,0x0000000000000001}}, {{0x0001a0d912586411,0x0001b0d49fbe5702,0x000bb57b277de5b2,0x000a4b2d7291e7e7,0x0008c16da29ce1e6,0x0008f8b71f4426f8,0x000fbf76a6ebaff6,0x000cab510adb9995,0x0004b996a6ec18d2,0x0003bc3ce11f1f8d,0x0000000000000001}, {0x00004c4051321f3c,0x0003af34703d798e,0x000dd55e68b6b0a3,0x0007f09cb14161e8,0x0005357558d9c473,0x000d9a485a90c00b,0x000dac2508e73fc9,0x000ed252e5f5bb09,0x000b1efcb4ba2132,0x000593c58bf23933,0x0000000000000001}}, {{0x000d1217cba9c6d8,0x00087cb7a562f7c7,0x00004fa0d0ea0e23,0x000c05e3acd8379e,0x0006d159e80cdee0,0x000029ffd63834d6,0x000500f3ee777b61,0x0007b75be130d659,0x0003756de768a261,0x000a541b809584c6,0x0000000000000001}, {0x000af54a67204972,0x00085857b547d484,0x000954a25746036a,0x000bc1881e0295bb,0x000d3d231831b4de,0x00002708fd517190,0x000b1e9571812770,0x000c3e25dfa6c88c,0x000fb3c57a9f5467,0x0001d404949d8103,0x0000000000000001}}, {{0x000a34fad1eabbbf,0x000de71fa7ad8210,0x000d67acfecf1047,0x0005ec7ec527279f,0x0007906ba2abc3a7,0x00066a25ce54f7d9,0x0001e7d558ddfb44,0x000ba77bccd91efa,0x0005405027796dc3,0x00072f9ae8e511f6,0x0000000000000000}, {0x000feaa4cfcc2a79,0x000d60cf749b854d,0x000ac1632a7218b2,0x000a7ce21f4e0ce3,0x000550325628caf5,0x0006b7d84c8e6b8a,0x00081d8e5bd9a461,0x000bb7affd9d5730,0x000dca775afff520,0x0006a52e629d73fb,0x0000000000000000}}, {{0x0008f6b8297fa26e,0x000d76f386ac99ac,0x000ce235f3a2acb0,0x000620801a076df3,0x000c62031f455ef8,0x000d6e488b1627c3,0x0008ebc5bf3c9afb,0x000c4512c254ea59,0x000abb87bcef237d,0x000cb4dcacb5a5ed,0x0000000000000001}, {0x0008e7718ef189e7,0x0004207cf70cc015,0x000e9a66810fd747,0x000d69bb7c99d1b5,0x000454409a3962cd,0x00014e1d3b541825,0x0008bec33aca5afe,0x000a9c5e4a92268e,0x000bf2e95060a307,0x00093a289c336375,0x0000000000000001}}, {{0x000781a84aba36d2,0x000ad7584291d55b,0x000992c0a266ea73,0x000e02af20e9954c,0x000ca4d73d175169,0x0001612ee12718e0,0x000cf1ded50926de,0x0008c1060d91c638,0x0007dc332b5998df,0x0002624eb7dc884b,0x0000000000000000}, {0x0008eae21aadf4bc,0x0005c2a9f4bf2cd7,0x00086c74c6b37272,0x000a4de4b5b5158f,0x00093ba4800d6736,0x000138590e451f46,0x000263ed2239cb95,0x000545bdc4c56f5d,0x0006676d4c0f8acf,0x0004038bbd0743d0,0x0000000000000001}}, }, {/* digit=74 [{1,2,3,..,}]*([2^296]*G) */ {{0x0004fe80d04c169d,0x0001452da244cb71,0x000cda8b72206f04,0x0005887084ee9fa6,0x000920e111da7c3d,0x0003bb35ef1c2673,0x0008e61906e57c45,0x00073eebaa206a85,0x000dd3b5bf458238,0x00015dcf71c4a720,0x0000000000000001}, {0x000605cdd81e2955,0x000ac0e98756fb91,0x000f0286c4ccda7a,0x00017819b4372718,0x00031dae0a5d8a40,0x000720f8cb219351,0x0003217261dafa40,0x00006fb18c8c40e0,0x0003c7d483485194,0x000d46e02770cacd,0x0000000000000001}}, {{0x000b16ebe5676f0c,0x0006e7f47e5b4652,0x00071c81701e6ae3,0x0007f8d6e3a4cc33,0x00067b29431c31ae,0x000869125faeb29c,0x000fd62e16be2afb,0x0004934ce6d0052c,0x000cd74901063882,0x0002e62b021800e1,0x0000000000000001}, {0x000a39e3523a9de5,0x00076121f34b3253,0x000d9c36b4aaa3b5,0x000b23992e0442ed,0x00023d2725144419,0x000ced8d6e4d3747,0x00011186d58a7080,0x00050cd63ed11b1f,0x000c6faa6d7a4d0b,0x0002559c897561f4,0x0000000000000001}}, {{0x000657d806465325,0x00095fd29c362706,0x000e70b9e028365a,0x000fa40d084d6b18,0x0009d80bbbcfec68,0x000a06728aae56df,0x000361eb62533738,0x000dc77e1c92bd4a,0x0004fbeefd3c11b1,0x000cfba52dffafa9,0x0000000000000000}, {0x0009acb1f00a47f4,0x000024e668d3f2f1,0x000095d2d5d23cbf,0x00076b697f105b84,0x000da5b550d7489f,0x000c9d3a15e73345,0x00093e0d2b26a8fb,0x0001e4494adfd6a2,0x0008e6417e038745,0x000fb0b051833181,0x0000000000000001}}, {{0x00013685fee3f167,0x00059193a123f397,0x000f28bae616ef5a,0x000d2c6567b33050,0x0004dae5b6596da7,0x000481adbd59fc9e,0x0002c1618dde4a40,0x0001f2a194682fe9,0x000c05bc15adc043,0x00013edb30fcceea,0x0000000000000001}, {0x00047d7a2900c6ea,0x000e954cf35b8dee,0x00074908606c425e,0x00094a88cdac359e,0x000fbef2c858622c,0x000d0f745810d20b,0x00041d71ca77f658,0x000782f59f1e4267,0x0004af36c640314c,0x000e35ec0709c829,0x0000000000000001}}, {{0x000c5c739f094c18,0x000b75fcd89a8d55,0x00071a4d047c0dcd,0x000ef9a3d498ccfb,0x0008f669e7edb8ba,0x0008d6b13c20d8ae,0x000a564d16a48c79,0x000250d241703f4c,0x000680ef9509f9dc,0x000970b2c17a388c,0x0000000000000000}, {0x000778808942861e,0x0009abe8d8d33c23,0x0009bd2fb189dd26,0x000112581e8769b1,0x0009d657bacd662b,0x00084fbcaa8521c1,0x00091c546adc05d5,0x000c68fad3f4e938,0x00057bce78617aeb,0x000701e39a422608,0x0000000000000000}}, {{0x000d79f624f8eb1a,0x0008e9c5d103b9cf,0x00071b65a5829554,0x00034991b8462f3d,0x000b51453c2b2409,0x000cf62fb341c087,0x0006cdb37eea50d1,0x00027ada571b02ab,0x0009e677d1b49b69,0x000004b52dc4d6da,0x0000000000000001}, {0x00042f171b839d5a,0x000765b6cceda32e,0x00009960889dbcc6,0x00040e8e2e336d9f,0x0001f34cefd7de54,0x0008bc6b5ab410a8,0x0000cbb91782d60d,0x000a95e22f3046d8,0x000775cf7c99291e,0x000282ca473be09e,0x0000000000000001}}, {{0x000b6a03ba3e1ec6,0x0006b7fefa851ec2,0x0003a92f6680a7bf,0x00075deabf4905c0,0x00096ff483a6ae8a,0x000c163b2b784673,0x000be098999b6fbd,0x0009c4a535388968,0x000b8e919419a12c,0x000b0bd87c889640,0x0000000000000000}, {0x000f69e3681b9e47,0x0008fc5971b3c868,0x000bd601db453ea0,0x000aee960ff01a96,0x000a0347158b6a72,0x0008994151ef1dc3,0x0007de4b70d9ea4c,0x0005a29068423993,0x000e4276c73a1788,0x0008a834f8bee71a,0x0000000000000001}}, {{0x00059366b70a0b8b,0x000d60abadb72457,0x00087caf5b975b84,0x000cc3f1983f793d,0x0002e94d8de541ce,0x00090b687cd8885c,0x0006b6cd952f2acf,0x000016cc05b6d504,0x000f97cdb266e5bb,0x0007c95959c78452,0x0000000000000000}, {0x0001e70e0efd1f63,0x000528c8989bfc93,0x000c244410e36663,0x000645d5f14f2667,0x0008cf8059cc8bca,0x000d2134f71c94e0,0x000ba7b1d1a84e91,0x000e21c35b983489,0x00003bfc5dddbab1,0x00099886156a8fa3,0x0000000000000000}}, }, {/* digit=75 [{1,2,3,..,}]*([2^300]*G) */ {{0x00083fd796b1a72b,0x000c549640b910ec,0x0001f3c076c5166d,0x000b7e4e553ff932,0x000e97e2f7e676d2,0x000a2cdad5097c11,0x0004bc0c5cedff5a,0x000757d09eef397f,0x0007434958d95f66,0x0004eee32eada9e7,0x0000000000000001}, {0x00041f85b3f06836,0x0003aba0e3496ce6,0x0007931548ea6b77,0x000149273aecbf5b,0x0001858c42c5d2ef,0x000ddc70d91528b8,0x0008d341c157c1ef,0x000a690e10df0a32,0x00064f5d30760fd8,0x0000d14ec3b44ea3,0x0000000000000001}}, {{0x00087f011572bb6c,0x0000d126f1e48db1,0x0000d05c4b7b6201,0x000a2ba1e0fbe5e8,0x0000224d802f13f0,0x000e0b8698189e96,0x0001b4bc0b8af43d,0x000c706b742b2859,0x000d9196336bf7ae,0x00007fec0d2fd363,0x0000000000000001}, {0x0000b0b6ce7179b1,0x0007cde982e3e244,0x000d814a6fad99d6,0x0007d3497edfbb4d,0x0007a46c6afc84ac,0x0004cd907a63bbd7,0x000909a18bcc3d68,0x000d756b5193f098,0x000f37ab5d6e0581,0x000ffb06adf4d102,0x0000000000000001}}, {{0x0000415e4f4b1ce2,0x0002f16bd8544ce9,0x0003e7600d6c664d,0x000d9aa401912f05,0x000dd3e0c268e1e8,0x000f14013443dcda,0x000f59cbf936e212,0x0004b8aaec39252c,0x000d652c200b8cef,0x0000aac64c11e47e,0x0000000000000001}, {0x000c08e2e7a2dfe0,0x00048459176893a7,0x000c7c5a8f0afe8a,0x000e999b6f043d0d,0x00000b3c3cfd6e33,0x000b4fbc5e2a496c,0x000f5eee2690de5c,0x00073d2db4511dfa,0x000fecdd2743e927,0x0004f4ade6a1948b,0x0000000000000001}}, {{0x000039609cadf211,0x000339488fdf258d,0x0000e39945a1e037,0x0009a8444d16fa60,0x000c454408c23f53,0x000ef729fbf7f8cc,0x0001fe369b8abc6b,0x00053dbd87a47666,0x0000f6266a890341,0x000de3c7b4bcd279,0x0000000000000000}, {0x00006e205ec9aa47,0x00063cce1af477a4,0x000f7fcf64572e77,0x000c931743d00999,0x0003902adccdc1f7,0x00041be26f8b87a1,0x00006779ffcb96f5,0x0001c0636264bb59,0x000484331c0db1d6,0x00076e5585c8ae19,0x0000000000000001}}, {{0x0005899b377cc15c,0x000f315fff92e2e8,0x000a8cf599eb4a44,0x0002e4cfca1a3e87,0x0003f205f34e217a,0x0009eb1362e4f28f,0x00061c84aa7c205e,0x0006fa76515b6ace,0x00083aca37e55058,0x00030435e870f8ec,0x0000000000000000}, {0x00002203ed113de7,0x000655318327d42e,0x0005d903904004d9,0x00094adb7cd1d2f1,0x000ebca1242c89d2,0x000af2a1423b5bb4,0x00066f393818e824,0x00079a30444115e3,0x000183b2cd6a53de,0x00047bfd324d8249,0x0000000000000001}}, {{0x0001ee196db2cf29,0x000718a1d049034d,0x000acaf386ae53d6,0x00006d746605e4e6,0x000c4458e136fcc3,0x000b7a1ac677dc40,0x0006ee4bb331955a,0x0007b95c386ed47f,0x0006640fb4384103,0x00081000a37bb752,0x0000000000000001}, {0x0008cc55b8f1bcdb,0x00025171d84cd78b,0x0001b8eb12ee7e03,0x000bd8c564c45f59,0x00076c2283df12d7,0x0008a36461b03bfc,0x0000c8cafd6fc812,0x000ae72b6275a058,0x000438282511c376,0x0008780ca3213fce,0x0000000000000000}}, {{0x0002c0f6f353cadb,0x00056c17179cb81e,0x000af140db008101,0x0001bb5e63cd1fa8,0x000b0729533d8217,0x0006676827544c77,0x000fe1b0143af56f,0x00045a759df2599e,0x000962b593accffd,0x0007a3c61321e555,0x0000000000000001}, {0x000e58a6aa5358dc,0x000739bb4d42d566,0x000e6ef3760e0cfd,0x0004fb370620ef46,0x000c2253e0f9e680,0x000b5c8c64f4e9cd,0x00008daec6f6658c,0x000504153037a80d,0x000215b47cc959be,0x000e4e7aaaa8653d,0x0000000000000000}}, {{0x0002bc233166381e,0x0000199700029af5,0x0003201dddf2a837,0x00085cdad02e2c74,0x0006daea6cd36d88,0x000c3f784e7e3512,0x000e882fa40cea6b,0x0001eec16a3a5130,0x000c43706ace2f12,0x0009ccf3c3a16a13,0x0000000000000000}, {0x00064823f9e7a6c2,0x0007bae8e4729ac9,0x0003fe54edfeed8d,0x000a4e7bcfba42bd,0x00039e917bf88ec6,0x00004163c606be20,0x00009b017d5a63a6,0x000c276869bd6bdf,0x00094144ff021410,0x000a13f038cdd94b,0x0000000000000000}}, }, {/* digit=76 [{1,2,3,..,}]*([2^304]*G) */ {{0x0002f8bd1741a941,0x000d4f3177637189,0x00060a2c8b16c0b1,0x00012ea49a688a19,0x0004556eef3eca0d,0x0000c833814746c3,0x0008d8b842db71e9,0x000b1bf4ae9e3fdb,0x0000ee706bc576b9,0x00054e85a8de649e,0x0000000000000000}, {0x00032799b9f19edf,0x000975259805923c,0x00076f95241c4760,0x000d3b18d6c8d637,0x000fa677dee0ddd3,0x0002ad9334e5bcea,0x000ceb27ca464781,0x000594d56dac3990,0x000338deb39d6e55,0x00096c7a9d83d78e,0x0000000000000001}}, {{0x000d7b49014b2147,0x000f134215e0ae52,0x00084df8cb33a781,0x000b10bfaf858985,0x00065449e13a9c3a,0x000859368bea1a4d,0x000d78c2c8134dfb,0x000ba7d94439b51f,0x0003f1c754b1e6f5,0x000d464cf5d47b00,0x0000000000000000}, {0x000c286403cdb3ba,0x000c15d6597a8e6d,0x000e5e853fbe3d2a,0x0004c9898bd192da,0x0003c76032d13f80,0x00038d5e8bdb66ee,0x0007ea1349bcb167,0x0001e4001679e16c,0x000f1f584d22ec20,0x0007b7d9f317a982,0x0000000000000001}}, {{0x000196d862941c7f,0x00015fd4c9380d4d,0x0000a23a9cf4968a,0x00039223ad85ace8,0x000b20fbe77f6374,0x0003ae3be886de7e,0x000a36dd5eea175a,0x00061d0a78e19da4,0x000a64f9638a5733,0x00007bdb82dd1f3a,0x0000000000000000}, {0x0007fe74ebe49201,0x000a7702be0b4d0b,0x0000cad19bf2f6ec,0x000d6c0b5b514f13,0x000c08518708375c,0x00035c8f337b8d0b,0x00055fc06adb3974,0x00083bfc4b137fa3,0x00045b3d91207a07,0x0009d53cd23a6fdf,0x0000000000000000}}, {{0x0000a67f092fe026,0x000e142efbca10ec,0x000cc433a343767e,0x000f6b9e68131944,0x000e836fcc884370,0x0005328231b4d1b5,0x000895d85b956e68,0x000117afd7ce3e4b,0x00028a48e23cd96a,0x0007756cbf1cc4fc,0x0000000000000001}, {0x000c45bb98d0ddee,0x0002774201b8565c,0x000b4f52020bec2c,0x000bda65cd76ab62,0x000ae2fb221ac3aa,0x0007ba962fd348e9,0x000e7c381d5e875b,0x00068ae119edacdd,0x000b495d57186eb9,0x00056fdf795bd0d5,0x0000000000000001}}, {{0x0003ca5ab59ddb41,0x000f7f1ebc9c6cc7,0x000f57e85f634cbe,0x0005a16eddf122c7,0x000c8a63efc695ac,0x0003541555a07f9c,0x0002a4d80e98783f,0x0006230998aabf3c,0x0008cb24667129fc,0x0002de1b3b8ba86c,0x0000000000000000}, {0x00062aec0af56692,0x0007719a7045c1fc,0x0005b9718436f251,0x000c9b5d581f4e26,0x00069b5489f5725c,0x00051e7c1aa8e91e,0x00028ec256fe93ea,0x000487a680376ebe,0x00030e63df392cad,0x0009887cd96ae342,0x0000000000000001}}, {{0x000e42367a9d725f,0x00039383477d80ab,0x0009bf84781ae655,0x000527eaf1389d3f,0x0004102ffac6350d,0x000a3b0583300052,0x0001cf3332af83e5,0x0006d633aac030a5,0x00033508c7e87b5f,0x00094e54cf554461,0x0000000000000000}, {0x000f352ebddfa61b,0x00025e3d5e304a79,0x000673478bec8a85,0x00072acfcd082890,0x000446528a7ef652,0x000120a7a607746b,0x000c8aaaa126f2d6,0x000e0714c411ed8d,0x000219322242ecc1,0x00076f4dd29b9909,0x0000000000000001}}, {{0x000c19050d8003bd,0x0000966c18887790,0x000653ed598ed239,0x000bbd18179a89ab,0x00050e32e18d6ebb,0x0003a242275a6e33,0x000cf9fda141c240,0x000cba7fbc6f732a,0x0007d9042bdcaed5,0x0004cddd17f09749,0x0000000000000000}, {0x000dc494bed8e1aa,0x00072f9b4efbdcb4,0x000846e40ceacaf0,0x0008e7a08c964b79,0x000b697992c6dba0,0x000a31236d2a3b33,0x000f13c67e503cfa,0x000758371b2297ad,0x000a30fe4d1b0d5b,0x000937f2f3ba13a0,0x0000000000000000}}, {{0x0001e3e792f54f5e,0x0002d66e1c349e9d,0x000411c782a7cb86,0x0004b067774f6f73,0x000f3d88b7029f91,0x0008ac9342be145f,0x000fba10730a2fc6,0x00017ace014c77dc,0x0006ebecfe34f062,0x000f04b7a85b9087,0x0000000000000001}, {0x000e45d39d99da4a,0x0006122af68cfe2b,0x000beab553aeda14,0x000338ecc8cf47bb,0x0007a9f26575d185,0x000dafc93ebcf570,0x0006b569b4f26152,0x000a1c5170968500,0x00059575a58e4408,0x000d43a451b6b327,0x0000000000000000}}, }, {/* digit=77 [{1,2,3,..,}]*([2^308]*G) */ {{0x00031eea8652aa77,0x00075a9b33eda2b8,0x000ccb42fd2dd1ac,0x0005ab8fe55769fc,0x000ee2ea2c9e4a86,0x0008effb93c60208,0x0001522321dff3f2,0x000e5124fb782d6b,0x000f961e96e29dc3,0x000a6d2f39193c4c,0x0000000000000001}, {0x0005e63b7e317479,0x0009d667da851f03,0x0007183aa797e9f3,0x00059f9fe886c75f,0x000d96d9e68574aa,0x000ee25277706045,0x000aa94b18ceb8f2,0x000d5bc3971ae4bc,0x0007b608157fc8f0,0x000150dd6428487b,0x0000000000000000}}, {{0x0003f45b89aa7776,0x00091f2af99e2d25,0x00076414d1e112b4,0x000800014a8e2b12,0x000ffa17691a71c3,0x000bd4233ab0f6f9,0x000bd49cf4e764a4,0x0004012735f0ccb8,0x000037d3dc7fc071,0x000ae03da811ddf6,0x0000000000000000}, {0x0004a8fb960d3228,0x00048eb39e1a42f2,0x00007ea05b5a3c40,0x000b7bd9d581bb93,0x0008feeb6ce36fa0,0x0000329bb28b7b8d,0x000e608fcc8cab6a,0x000504c03b085c44,0x000593cce3f2c4c9,0x00093bb2ef5a3d51,0x0000000000000001}}, {{0x0005eee4a29b9e00,0x000dc20740482d3d,0x000e9ca5a465e210,0x000dbcf9b04be3f8,0x000cf79a10d11c21,0x00098890d16c757a,0x000df4eccacfdb2e,0x000f11b8ece9836e,0x000bc4d7a9a35695,0x0009ee2c9b7d003b,0x0000000000000000}, {0x000e2dd26ff13203,0x000133cc51c6bc72,0x0009ca679c2a2da6,0x000951011dc4426e,0x00093bedba6ea308,0x00088d9217c2a099,0x0000e9979694eb83,0x000d521e97150620,0x000035d356c66be4,0x000161e2cef90abf,0x0000000000000001}}, {{0x0002a5d7a2fe5424,0x000c5abd77fdcc05,0x0007ae8084591e67,0x0006481030c17511,0x0001f92e55b534fb,0x0006bd1eba6c21b3,0x00096514d056aef9,0x000df597cfd93bd8,0x000c4de2939ce9f5,0x0004ef6737cbaf10,0x0000000000000001}, {0x0006ccf17f5b4aa6,0x00049ba070d7b272,0x00033084cb0ef8a2,0x00018fa7fece71d7,0x000e7f11b328ddbf,0x000b8c5b898e7f8f,0x000699bc5842d33d,0x000944b7141938ef,0x00039a13d619477d,0x000d5228db36f5cd,0x0000000000000001}}, {{0x000b8747f420dd4b,0x000fb52bb177eca6,0x000f43dcaa9b6760,0x0007a3f15a0ec05a,0x000736800fc5d305,0x000bb74572a151d8,0x00065a96cf22ff7d,0x00019519394cd42f,0x0008227699f90840,0x00068419e24fe2e2,0x0000000000000000}, {0x00025578363927ed,0x000574db66d688d6,0x000d409ddc1459fb,0x0007f82b70d69f87,0x000cb67c0931340b,0x000a17e9ba495398,0x00095f5bb6fc86af,0x000372330a201b0b,0x0002bfb684331f96,0x000759b31f0fa4ba,0x0000000000000001}}, {{0x0008a9686e50ea9a,0x000fa53caf16bb29,0x0001e6775d854b08,0x00037450aecb3742,0x000a7e3971ac67a8,0x000916720ee3a053,0x0007ef527af5a2ad,0x0008c78907d26a51,0x0000187ff88dddeb,0x000580501085ffc1,0x0000000000000000}, {0x000bd54c631b5ef7,0x0000a533ff81bdf1,0x0000234fa962cf5c,0x000a7f99121d8411,0x0004d769fb90a1f3,0x0005f3f42e621b7c,0x0007e5f02655798a,0x000d995fc9fe9a95,0x000560ed712fc645,0x00059000f20fc194,0x0000000000000001}}, {{0x000ca8aff309b100,0x0000c85dcacc4c44,0x000282732cee9318,0x000efc73a9f020ed,0x00070ac2ec46ccda,0x0004edd612a22d61,0x000fb7673b4cf6d2,0x0000510828deb00f,0x000a061d4c49e843,0x00016c8aea6c342b,0x0000000000000000}, {0x000ffaa28b87e79b,0x0001bb9617a5663f,0x00097f1ba9e99062,0x0002ee20742a4b1f,0x0000500e34cdf43b,0x0002b6de4ad6c0ab,0x00002eba08ef6f81,0x0004e0bbfd3a6364,0x00094460899a3582,0x0008335d3e07b17d,0x0000000000000001}}, {{0x0005a71e395d239e,0x00026a160db974ae,0x0004df55ba5b2671,0x00091fe0f2bfd214,0x00027e4215d39cf2,0x000849498b3dc0a6,0x0000c7dfec311ed8,0x00029fbb50995b22,0x0005f9ca4a3d83cc,0x00085332f62dd6c5,0x0000000000000001}, {0x0003278db69ec48f,0x000c56caebf5d4e7,0x000e4ab979b38b01,0x00005e1e7e210f66,0x000e800e35bf7fe3,0x00041625bdbbd247,0x000140764eabbcaf,0x000ae49d3fb6b3c0,0x000bed09dc31a840,0x00044a6c67185e6e,0x0000000000000000}}, }, {/* digit=78 [{1,2,3,..,}]*([2^312]*G) */ {{0x000976185cedb78e,0x00000d5ac29ab973,0x0005376ef5010492,0x000fcfdeb7cabe96,0x000e82ebeaa6eb29,0x000856863e849702,0x0002b7dd5820c1d9,0x00080b85b8b6adb3,0x000cc2bebcb2a1da,0x0001cb911240a24e,0x0000000000000001}, {0x0009339d66471f42,0x00086865738f288e,0x000ec9ab31ac9389,0x0006dfc0b78b477c,0x000d22531d4c9b75,0x000957b1f72bea7b,0x000f90819668750a,0x000023544082b7ac,0x00010dd35fa97aa9,0x0000657c9376d4d3,0x0000000000000001}}, {{0x000d393a7e12c9a1,0x00087315af1e7695,0x0005dad48c909f6c,0x00065a7e168b010a,0x00026d86fdc5603c,0x0008f52d5373f51c,0x000a497697c8b7d8,0x0006670982debc64,0x0009f942aaf7a067,0x0000beb15cc57a80,0x0000000000000000}, {0x000728397fd456a4,0x000c8ff5563ef971,0x0004e73a2dd305f3,0x000cc516a80ae4a1,0x000352258160b828,0x00008533e6e74db7,0x000028314ad68011,0x0007541598a03b32,0x000c3d815763ab10,0x000089f632644f56,0x0000000000000001}}, {{0x00096953520ee092,0x000306d200f67521,0x0008a20dfb41aa95,0x000ecbdc450070d5,0x00044a73c2aa2e56,0x000cf15e09936979,0x00039822bf1cc5f8,0x000ba98dee98b81e,0x00049763f39d2614,0x000dce88bf80d042,0x0000000000000001}, {0x00090be494194f3d,0x00009eeb5f7526ea,0x00042892f629d76e,0x000de6b9665e7661,0x000e4db45bef0dd2,0x000f0c29ede66edd,0x000cdcbd947a3fe0,0x0009dc0bb66739bc,0x000aa185f9760092,0x000d98f355b62fee,0x0000000000000000}}, {{0x00095d178d8fc8db,0x00088ab909e6143a,0x00089b7600c18603,0x0000f4aa942112c1,0x0008b5a1967f7a08,0x0003543a0e5057c0,0x000cafbf9ac78fd1,0x00049408a20a1598,0x000b58bcdfa7974b,0x00036217ad4e198f,0x0000000000000000}, {0x000138c5bd603cb6,0x00072af896026457,0x000ea9d78b2185f1,0x000482318652917b,0x0008b9b757159621,0x000f2c7ae3b7470a,0x000d10f532d77474,0x000d6b40b8bfc96f,0x0004da23277081db,0x0005192cd44f13a5,0x0000000000000001}}, {{0x000210b018203491,0x00081f7f56d37ef1,0x0003499eb28c2bde,0x000d16d800ddf3bd,0x0001a8ad11d2638e,0x00081f6ac5a19953,0x00073cbdac06d819,0x00089e5df343701d,0x00080e56132b9d88,0x0008f82b847a3187,0x0000000000000001}, {0x000ae2fb5a3b782f,0x000dfec66b9766a4,0x0003802b7f84c2ba,0x0002adc75633f423,0x0009ba300fd1c729,0x000a85bdc16e7491,0x000bea7ecdc049f9,0x0008cba7fd0e8182,0x000a5a9aa8bce3aa,0x00008a0977d90d48,0x0000000000000000}}, {{0x000ee51072d71e54,0x000e9e2a68ca9bef,0x000a9707bfc11ef4,0x000ae91635e6d8f0,0x000dd87435cc0e00,0x0002d6a89b217b9e,0x000c5bada1452b8b,0x000d602de29b175c,0x0003f43b9bd73fb3,0x0000724373642133,0x0000000000000000}, {0x0002c3dc04031002,0x000c73ba54808162,0x00084fe7d46fa018,0x000e61eb44ff91a6,0x000448f89778fb3a,0x000d0dc5c96379eb,0x000f26ee0588d9eb,0x000aafd623f750bb,0x000b6e0aafb4a855,0x000ab06c0e1eab53,0x0000000000000001}}, {{0x0001292993c3f0c9,0x0009243ce8e0477f,0x00002cd6d125a6a7,0x000424b8f8d2f4dd,0x0000e036966f98b0,0x000b28d9609c6ed4,0x0006f54dde908ae8,0x0001261395876628,0x0001a89f477ea392,0x000b89a6253dab22,0x0000000000000001}, {0x0000776cda9e2906,0x0004dd51a83a13fd,0x00024cb69c0833d7,0x000afa9f2d0d7515,0x000d5068104d274c,0x000b1536c256cfc3,0x00005c2c5a3bb4ea,0x000e695b252297e0,0x000674ad5032178b,0x0007afaaac5118a0,0x0000000000000000}}, {{0x000b5f87444140a9,0x00070937761e89c1,0x000052402d8c768e,0x000e0d8fa7063fcc,0x000065032ca28437,0x0000560b81d70497,0x000a63bfcc5af72e,0x0007abb68cfddac1,0x0007b3b85e89f391,0x000e3880d7454a25,0x0000000000000001}, {0x0001d4cbebc9cca5,0x00014fe965181800,0x00064d65a9766b10,0x000646ec511b3639,0x000cc26e7c4e0d56,0x00094ae11adfae8d,0x0001a6886e8d406a,0x000547bbf4ad6e9a,0x000e8901b3004a68,0x000c8d5981c48013,0x0000000000000001}}, }, {/* digit=79 [{1,2,3,..,}]*([2^316]*G) */ {{0x0003223ffb7f0034,0x00056eeed01f7ec6,0x000a95759d3b10c6,0x0008fe9fc8ceacdd,0x00036b6ab8ec35f6,0x0008c0b21550e979,0x0008e1de4ccc3b92,0x0007fc6be17e92be,0x0001bdb6320828c7,0x0009d213352a78b8,0x0000000000000001}, {0x0009b3c1ecfa9e13,0x000b3a0b5daa423d,0x0006bf95aa594567,0x000fbfb5a3d149d4,0x0003d4e9979588d0,0x0001e08ca45e636b,0x0005c358fa3b11bc,0x0003552e11b17364,0x000b67bc8931ab99,0x0002d3ce614c5f0d,0x0000000000000000}}, {{0x000ed714844f3544,0x000cc4bb9010843a,0x000996ac0026321b,0x0003453553c74ad5,0x00041741982c7cb6,0x000196d8fedc48a0,0x00020d244c9f0921,0x00070a8fce97fabc,0x000a6d44732828d2,0x00060bcab0c77562,0x0000000000000001}, {0x00061da3943969d2,0x000d674b749d7b3a,0x0009df6dae1fb5b6,0x00005c30ec275083,0x000ae7da1a9284fd,0x000c82a28eb7bd6d,0x000a71d66cd19bae,0x0002d599b2c6a08c,0x000faa1546c312c5,0x0007f06795e3065b,0x0000000000000001}}, {{0x000fff9188aa7d8c,0x000deb80ad064a0a,0x0007114ab9689af5,0x000fad0b4dbde778,0x00055fd29cd3c099,0x000d379d42525d60,0x00016d04df50e85b,0x00053602e006dfc1,0x000e6c63f374d96b,0x0000f26509a7f32e,0x0000000000000000}, {0x000822c176aa9790,0x000f58fc039cb1ee,0x0005872cad56c2fd,0x000e8ae0ea665324,0x0004daf2e64bf3b9,0x0008f96bb4b8314c,0x00090e063c57f41a,0x000d5149d3063df9,0x000ba61281d5f9b0,0x0004ba3d6cc9c608,0x0000000000000000}}, {{0x0005d4a76da49005,0x000c3b224e91125c,0x00062ab184a74621,0x000b682a17406495,0x00053c3f7c8cdedf,0x0008e38d4416ae20,0x0009c28df044060d,0x000f86143e5739ed,0x00095f9f7f327b97,0x000872538531478b,0x0000000000000000}, {0x000b98e468155010,0x0001fc05661b3943,0x0009ee23198c1bcc,0x000744fc64ff1647,0x000560f20d871115,0x0002c9feeacdf5ac,0x00070b263cba9c39,0x000badbac8fda72f,0x0001aad35365c71d,0x0002f99d51687d17,0x0000000000000000}}, {{0x000acd4ec9302acf,0x00046876812a6969,0x00062f921abd47ef,0x00030834c8ee3434,0x00087c08c033bb79,0x000e51d0a2369c3e,0x000c1fbd98cac8fe,0x0006a309b704c675,0x000a173a43fcbb3c,0x00009432c4949569,0x0000000000000000}, {0x0005e781f2ef36de,0x000e3479bd3a702b,0x000d74e86eb68837,0x0003849622881aa5,0x000ba91b89a84ecb,0x000caeee87dd2964,0x0000f40b0230b757,0x000e7853cadc83a1,0x0005f5ad1465657a,0x000e75100e5033e4,0x0000000000000000}}, {{0x000e44f3911651e4,0x00088f7f22b492d2,0x00072f850dbf1662,0x0003ab2a45a14853,0x000e1480b82ee674,0x000ca609c8235a84,0x00085d8422668b9b,0x000a5d6f0bf02f4e,0x000afb880792321d,0x000cb82c095f0261,0x0000000000000000}, {0x000bc2f5725cea9c,0x000e1f43f99381e6,0x000e6089c844a832,0x00000aa951ad7011,0x000282a695207656,0x00007e689c114477,0x0000e537bb9a4c6a,0x0009df06eaf0cd7b,0x0007c474d7895232,0x000f0710d2b00b77,0x0000000000000001}}, {{0x00093c8e0aebae92,0x0001a4248ef98180,0x0005353d71384b97,0x000564228ab8dd10,0x000ee9e95615cf3f,0x000dbed91f163427,0x000ff8c7cd8d83e1,0x00002a117b26a05b,0x000d651309094b7c,0x0005fa8d73f3a728,0x0000000000000001}, {0x00045cf4f3fc6c29,0x00069a5dd01b3bfb,0x000e3b24278a983b,0x000ba6e8dda15e64,0x0007ceabdafeb0be,0x00028dd1f4ce3cbe,0x00083c003c3a01ee,0x0004286b68f03154,0x0003661bd44cc13c,0x0006d7a5a2b18a65,0x0000000000000001}}, {{0x000f4f2d2f859a83,0x000584cf466ff03e,0x00078dc82b847044,0x000110dcb52d320e,0x0007adfe140d78b5,0x000b45fd46e07b11,0x000943939af65810,0x000f26b6d5c5bda1,0x00091095a8309f53,0x0000d4aad23c7d80,0x0000000000000000}, {0x000dd82bca9e7ca1,0x0001551ee78b6090,0x000453fc776839c5,0x0001d0262966b875,0x000729e2a29966bf,0x0008c49cfc825d3c,0x00009961345ab1d4,0x00007e6049f3ad60,0x000007da4f1b3985,0x000c382c8f36cb0b,0x0000000000000000}}, }, {/* digit=80 [{1,2,3,..,}]*([2^320]*G) */ {{0x000a284c690646dd,0x0003eedcd5cc91eb,0x000ea471fd6292fa,0x00023a125841cc32,0x0002e35810a749fb,0x00061336484e18eb,0x000b6f65228a2bfd,0x000207542e7452ca,0x000526cd940c7469,0x000d2936b9b32962,0x0000000000000001}, {0x000573e4f063ef2a,0x000418ca996c2a17,0x00033e1f9c1c3d42,0x000b3cbf970fbd47,0x000088c0b1561246,0x0006e93234f08535,0x0009d7f8ff901881,0x0000aa556f8574d9,0x000a5d989d3b1d29,0x000ed0ab78218edd,0x0000000000000000}}, {{0x000233d6557077d6,0x000f2b32cea9ff87,0x0006963e65db1454,0x000b05b7d5f2627e,0x0005a68cad15bd15,0x0009679cfef2c921,0x000cc1f982da4ecf,0x000673910763dd21,0x000110fdc3925aff,0x000a3cad0858b1ce,0x0000000000000000}, {0x0000c51bfdb7b566,0x000e8b88f58f7516,0x000713a7cf39e39e,0x0004ac365af813ed,0x00040a788e43e8ac,0x00010b5e01e789c0,0x000ddf33d0cb49ec,0x000a3f2d9bd726fd,0x0006e3c30504e525,0x000e51a456acdf77,0x0000000000000000}}, {{0x000707d7da6499d4,0x000c004b6d85bc23,0x0004b483dd72372e,0x000b15c9838f63c9,0x000dd40b6584e869,0x0005bb5ad6291644,0x00069be693ec1c90,0x0007b5c6018dc109,0x000c9c113b81150c,0x00040bbd460de804,0x0000000000000001}, {0x000d558a1b81757d,0x00046da356589b5a,0x000f093ea9cf88e0,0x000cd54eede9de0f,0x0001f19ec3f8839a,0x0004ec243ffcbf45,0x000d0d1f8b02c0e4,0x000a42d2cc07981f,0x000363b43f4701bc,0x0007f930f2e9e43f,0x0000000000000001}}, {{0x0006b0772d9f5845,0x000f28a8c7c3d700,0x000c1d96b231ba3f,0x0000f432c17a4f5f,0x00014ca88f653da5,0x0001ac5da9fce5ef,0x000105dd10257bb3,0x000206b910de18d3,0x000d121d64f95008,0x000e83748b9a298e,0x0000000000000001}, {0x000dc94560ad3e4a,0x000b34cda193affe,0x000f39dff5030add,0x000d72c1a3a58a0d,0x0001ad7c02e84586,0x0006dddddd7190f7,0x000431dd7f7815ab,0x0001b059af2893fd,0x0006d66ebdb90a30,0x000ac5b55b254562,0x0000000000000001}}, {{0x000a7032755a2cc5,0x00087b60173b4c02,0x000853a0c8b700e1,0x000d3fcbebfa5d41,0x000106636a248a74,0x000d439df17f1529,0x0001a48433bf866c,0x000ed52b92a93d36,0x000de5dbf96508fc,0x00064c08fb48dbcd,0x0000000000000001}, {0x000e6d70757d607d,0x00099aa287bad741,0x000aca83d8bc1d01,0x000a6deb3248272c,0x0006281490886dee,0x00003b3e7ed5830e,0x000b8f50b5515018,0x000ee61ae410329b,0x000dd209b1b1ec67,0x0009f79d8f057d2a,0x0000000000000001}}, {{0x0009240ac4aeeb4f,0x0009de701cba0d15,0x0001e2030d5be49e,0x000f5b9fa8d80ea6,0x0009e389aa0a7891,0x000f08f46a281d5c,0x0003d8942c2a6a9b,0x000dcae5c6263013,0x0006ed6f226d80fb,0x000e7cd744527397,0x0000000000000000}, {0x00064112eebe5a16,0x0005561ba10f054b,0x000076de3983c715,0x000338a0051c721c,0x00017ed93ec2b1b6,0x00040d08e30b18e6,0x00086d02546a805e,0x000b289546bf39d9,0x00029a40d87fe36c,0x00003828ca6d96cb,0x0000000000000000}}, {{0x000888aaaf08b61b,0x0004baeb89b8a3b8,0x00013c31ce0504b2,0x000084891577d88f,0x0001501541da01d3,0x000be18906c31edb,0x000cf8acb88a0c0f,0x000de0a54814b123,0x000d30b10ce17eb8,0x0003c65435ad1112,0x0000000000000001}, {0x0003c3081d6e0b2e,0x000bd1198cbd6e7a,0x0009feff60218481,0x0009559a8a4e33b7,0x000ae242155d34dc,0x000458dbdb49b265,0x0003688660033750,0x000853753ede19c3,0x000b6969aac09e0c,0x000a5225b275670e,0x0000000000000001}}, {{0x0004c030e13db910,0x000b8e4bb182d8fd,0x00024d5733c45ba7,0x000e09929bbae322,0x000c5e18395c5857,0x000beb34317a4b7e,0x00065979d2ffacfb,0x00000dac7ff47099,0x0002ac181634b33c,0x000b325a113dabd2,0x0000000000000000}, {0x000f6d0b44a18451,0x000ebd4b60b5e31a,0x0007c6c236a60067,0x000b1be8ccf47b3d,0x000a21dbd1cc7199,0x0004932466e888eb,0x0001dee034c21f8b,0x000ff9da169619ff,0x0007e95c7e040c95,0x000b5a9dbe56efee,0x0000000000000000}}, }, {/* digit=81 [{1,2,3,..,}]*([2^324]*G) */ {{0x0008f08161486b22,0x000be755ab4efe68,0x00048d9609c012b1,0x00098843db068e78,0x0002d958488ad0fb,0x0003f6d23cff5eda,0x000c41d3ec7372a8,0x00035d185ec0b176,0x0006314a5925e490,0x000a3de4ff957947,0x0000000000000000}, {0x00029cc94c1b43aa,0x000d43d2ad417dd5,0x000360ab4fa2dfe7,0x000e9eb552cc454d,0x00035a4732c24fb2,0x0008d1e843cf82a2,0x000ab8e67bb7a406,0x000191877eafbca2,0x000574ab099566cd,0x0009f922f9872f62,0x0000000000000000}}, {{0x00085f8208bbe4fe,0x000ecc287db7bb2d,0x000e568667e702fb,0x000cbeb7a157f36d,0x000bf484f3352f4e,0x00058da014941bbf,0x000586c3d5fe38d5,0x000a8a8ef1b37b22,0x0005949627a9e7fe,0x0004740c422ebeba,0x0000000000000000}, {0x000c2ec0fe63724c,0x000be0eb88269034,0x00016f607ed8c7ff,0x000b235b0a729f09,0x000b2fb783d219ca,0x000a1f91a0e85a3b,0x000f36eaf1659ef7,0x00023c3d4be9067e,0x0005e5bd92b43e99,0x0001e3e81391aa3b,0x0000000000000000}}, {{0x000cdab06c0f497a,0x000ba682d62fd58a,0x000624d8816a960e,0x0006c48669b75099,0x0001fb169d6d2670,0x0009d5b924784941,0x000361b9811c3888,0x00005ccc21278392,0x000173173a0f5de5,0x000862da0030f596,0x0000000000000000}, {0x000580503b5bd1a6,0x000460a53f77d734,0x0009ac0fc516703a,0x000cc1b1f0c1292d,0x000599d98d3204b9,0x000365fabf012bdb,0x0001f82c240390bf,0x0007f3c05cb807a9,0x0001aacb4486b03f,0x0002d4bf3cd7e64a,0x0000000000000000}}, {{0x000cf4fb66902a59,0x0006522d970cf058,0x0008db985646108b,0x0005bd091c524ec7,0x0001c8ded01bac37,0x000a7571d5eaf41a,0x0003ae41513bf75c,0x0000831a58ce8343,0x000b5c1d0b1cbad6,0x000a127e3558b4d4,0x0000000000000001}, {0x000c5bcaa2423577,0x000e95cd90416c5f,0x000f9cd3e851fd11,0x00043cec77429d71,0x00033818263e74b1,0x000b0bed2ab694e3,0x0009d3b078fef207,0x000322c62d90900d,0x00013057fb2dcc39,0x000b0aee2cd8c7f7,0x0000000000000001}}, {{0x000ca837cf1af373,0x0003ae0bc7638546,0x0005fbd88b9c057e,0x0000f14623993437,0x000d8418b02866d1,0x000938602b2a7398,0x000d172bab8e8fb6,0x00001960cc17eb57,0x0000f437b4d86f8d,0x0000c3266073d8a3,0x0000000000000001}, {0x000b4a64de3a3170,0x000d07d300586858,0x000590b48d2c8237,0x00064608c48f8521,0x00055a4fad372745,0x000ad1664c3cb9d0,0x0000e5148678bfbc,0x000ce1f67995bdb9,0x0000ce6b82ba0137,0x000865e65d5e9060,0x0000000000000001}}, {{0x000a3697b62e274a,0x0004f036666b6cc6,0x0004615de0a77111,0x000d1a544656bc00,0x0004cfe1b0ffd27e,0x0007b011fe7a367a,0x000028f9395287ba,0x0000e474d2cd1539,0x000df81c967ab663,0x000809d416f7d850,0x0000000000000000}, {0x0004ff0171522411,0x000cb614e9eb99cd,0x000efe5013168ce9,0x00000068878690dc,0x0003ea58b25b4f05,0x000697bfbefe708a,0x00061484cbc18871,0x000fd61b572d109e,0x000507a67ea6e538,0x000c108cf0642bcd,0x0000000000000000}}, {{0x00073712d28f1037,0x000dcbb85bee07b2,0x0002d427b383b0b0,0x000886a4c921569c,0x000a22bb54a08b63,0x00016efd18019f62,0x000be30e896a901a,0x000b1c79b63790d0,0x0007550d4ad3f339,0x000c014ebb2a7324,0x0000000000000000}, {0x0000eb80b7360646,0x0004292a8064819e,0x0001aa8d66966eba,0x000cb5433c6786ce,0x000c176010116f6a,0x00042b7f40b26c85,0x000bb51bb431c00e,0x00079fd699bb4a71,0x00083711f2c2acd8,0x0008a64b1e3905a7,0x0000000000000000}}, {{0x0004f281744c4f31,0x000fb974f0427525,0x00022ee390de534c,0x000caed9f368e25e,0x000470d3f5a1ebc4,0x0006bb7427d70104,0x000830891f024042,0x0006993cd5f37f0d,0x000a9d89f4ebe578,0x000c7b2549a02c1b,0x0000000000000000}, {0x0005527d2ef3c160,0x000aa733afd2d857,0x000200435a36240e,0x000dbed50df72a8e,0x00064e9f3dcc7104,0x00084041401f5c34,0x000b281791b398c9,0x000ad77cd49e1581,0x00029530ca203aa2,0x00024a7004073823,0x0000000000000000}}, }, {/* digit=82 [{1,2,3,..,}]*([2^328]*G) */ {{0x0004b896de83f7b2,0x000dd1b2e000727a,0x000d43d965547a68,0x000c1f1e1ce79a50,0x000e5ec87252c6ab,0x00060d6a5ae7160f,0x000985fdcf45caab,0x00091b3180d9d235,0x000646ab8f898256,0x0009f0446d6798dc,0x0000000000000000}, {0x000ec719b8387586,0x0001de5f9db6636e,0x00038f4a187cc943,0x000ac366ef383b03,0x000022fa366743db,0x000760fac1cc0b0d,0x000265067948b1b5,0x000693934495e8d4,0x000c64b8f4f88921,0x0005281cd8ec2ed3,0x0000000000000001}}, {{0x0008479d81fdc38a,0x00096a893e0d1c8a,0x000972cecee045ea,0x0000ed0b37445b26,0x000bf1c0a16a9b25,0x000509c76808e477,0x00070c4c826b6837,0x0008008a3f9fb748,0x00088d0f74d58040,0x00063d18d474fc4b,0x0000000000000000}, {0x000a143fb2178ecd,0x000ee2726dcabd2f,0x000e017d3cb36d39,0x000d77e2d8d9e011,0x00069332c865043b,0x000231a13fc89650,0x000e078f7a775c43,0x0002e93c91cf1e3d,0x000d48604e0f7c89,0x00031d2709749250,0x0000000000000001}}, {{0x0006fca2f24da625,0x000adeacc535625c,0x00020bfcd99308f2,0x000732872a2697fb,0x0007578b9abdd39d,0x000d7e3c3e30d29a,0x000dc63c314955de,0x0002de0cf2a14e6d,0x0002e4f4d6b0bbff,0x0008423dc75d4cf8,0x0000000000000001}, {0x000dc6563086abd4,0x0007f2e300951d8c,0x000a989054197751,0x000a88edbb68daee,0x000ee17db6bcc0fa,0x000d996d71fcc36f,0x00038a1dafea4a84,0x000fc8d72ef68c32,0x000c6b07cf974baf,0x000b2a140ef1e1e5,0x0000000000000001}}, {{0x0006034713a3e42b,0x00008cfb50e4479e,0x000f617634a25363,0x000ba17f9549272f,0x000163e264556302,0x000db056ef0f6ed9,0x0009449c67d2e92d,0x00027bf608bef04b,0x000a41494e0fd2d6,0x000ecafaa0f9ad5b,0x0000000000000001}, {0x0000394a908a0374,0x0002739ed3e6c1ac,0x0002bf950e49017e,0x0006ca69441c9b0d,0x0003c717b7978985,0x0006f1bf123315b5,0x000d5ffc5bce1316,0x0000f7b0dacbdc85,0x0005306a73236570,0x0000fc22ce0f19f8,0x0000000000000000}}, {{0x000a6e6af09b8eae,0x000343b43c513568,0x0003425270500040,0x000fb4508580e8a3,0x000b307fa3d1f99e,0x000113638a6f65cd,0x000be36db7f5ca63,0x000ede447eb7ec8b,0x00022e6ed48cec2c,0x0007bb1afd7c927f,0x0000000000000000}, {0x000c11f9a334fdc7,0x00026ae8011e9b06,0x000ba4fc7ee152d9,0x0005ebe2d92b45f4,0x000643466d3d6908,0x000a09e637a743ca,0x000aba719664e4ce,0x0003162cc6d5e41c,0x00060cdf202e7dd3,0x000c307d09d0c5c7,0x0000000000000001}}, {{0x000b621fceac0c99,0x000cd9f0c6398393,0x000246af19db94f8,0x000def03f4511189,0x0007e278282d9eea,0x0005d51872d67451,0x00069251c97cb275,0x000152306520f8d9,0x000f0746e9696ce9,0x0009ec26638c1b12,0x0000000000000000}, {0x0006fbb28d6db318,0x000282f1e3fd8169,0x0001638aa745ba97,0x000741cbd6f6afe6,0x000674be06f9a37c,0x000f0e4d5ef37aa1,0x000c66c847151102,0x00086ff305cd0c0a,0x000dec0bec87dfaa,0x0006e29a33525521,0x0000000000000000}}, {{0x0009e94294764d17,0x0002085b396e5ed1,0x000a114f1c4a72c2,0x0007528c8545f538,0x000963b0d0aaa085,0x0000ee6c82fe930c,0x0009cc321991f876,0x000bfd79b22e04e6,0x000e404e5103af68,0x0009a8126bf818d5,0x0000000000000000}, {0x0006f18c56b9245c,0x000be8cf2d749759,0x000d0534792607af,0x000737082c9ac67b,0x000b81d246c242f3,0x0004a1675a873285,0x000b8be65c0f0c83,0x00031f4367aaf8a7,0x000eeb7fdd2c4760,0x000b71b7bc940b35,0x0000000000000000}}, {{0x000e474b29bda866,0x000e2b3a2640ed4a,0x00021f91da93684d,0x0005df67424bab62,0x000b550d60209995,0x00096c99d55193b4,0x0003c748e9f27481,0x000631e6b3fe7e7f,0x000f47f4e257248f,0x000f8f56db9ba373,0x0000000000000000}, {0x000bc357ebc4dd12,0x0003a33556892c48,0x000b72124cffa435,0x000e35056ea40bee,0x000a1b37aa3c71db,0x000ddc96c72e951c,0x000291c71de6fcaa,0x000ff88244eb58ae,0x00089a7bf96fd42a,0x000eb41c5d8ae97e,0x0000000000000001}}, }, {/* digit=83 [{1,2,3,..,}]*([2^332]*G) */ {{0x0008ac7511fc1235,0x0005af51e9a589c7,0x000c09d63e56a5f8,0x00055b518ce24a89,0x000a75441652a9b6,0x0004ffab489b445d,0x00071289523b0e9f,0x000290aaf7cb23e7,0x000c9bc7899234af,0x0001dda65dc198b5,0x0000000000000000}, {0x000eeaccabd5a6f7,0x000d5900e72c44fa,0x00047a63782a2bbb,0x000393bbf531aecb,0x00009c7dda45067c,0x000719fa6f31630b,0x000f3a0c95e46b2e,0x0004deaf5d70f849,0x0007dd5d46829965,0x00096c286bc1f082,0x0000000000000001}}, {{0x00012d5838ca6af1,0x000964e9241a8a04,0x00024077ab2ac6aa,0x00089da3e1536c1d,0x00001df56af4aad1,0x0006ef9e57fbfb6e,0x000b17f8ca8e6244,0x0009cbcb351a7c9e,0x00085fb54f3eda4f,0x000c296970873909,0x0000000000000000}, {0x00056d8d32e5fdd1,0x0006814d7980be46,0x00065dbc6a68d7ed,0x000cebebe9b6528d,0x000269dfcc27d433,0x00073aec8225c88d,0x000d90643f7caaf2,0x00041c78327e8662,0x000763fdae4a09eb,0x000b0ead9bd2f604,0x0000000000000000}}, {{0x0008f42a8c29bd6f,0x0001879cf21db610,0x000555cfe2bddcfd,0x0004d452af269c11,0x000fcc4011856e7b,0x000e6e45593cb7c3,0x000b215415957c0f,0x000d3b983b2c8996,0x00012f953be5cf31,0x000f7078abc3a003,0x0000000000000001}, {0x0002c0d6b39b80ab,0x0007b2847e724ed5,0x000cfdfc83942bcb,0x000c1c0a2ddac314,0x0001da690e67e2aa,0x000310507c60736a,0x0008b8515f2f407e,0x000203447dd4a30b,0x000208fe5f3ddc7c,0x000470482e113587,0x0000000000000001}}, {{0x000d7682eb5538d3,0x00058bd8734ac8b7,0x00075fcdec6d3223,0x000ffc3556d9d86e,0x0003a6c363b61e72,0x000d03c2ead1066f,0x00074fd7095dbd73,0x0002b42f9972cd16,0x00070acc2acc3e68,0x0006fd80c7114993,0x0000000000000001}, {0x00049c09589c235f,0x000294e10709485a,0x000e55bcaedd0d2a,0x00084da3a073e38c,0x0004725346561d28,0x000ed8195e95d347,0x00001ec990b2c19b,0x000817664aecefe7,0x0005f12464c59ce8,0x000f85a23cc1c6cb,0x0000000000000000}}, {{0x000fb48cd5b9dd85,0x000ea5640b16ec8e,0x0004991733d00d1c,0x000e2230142b823b,0x000d1646ff2bfccb,0x000e87a4efbbe898,0x0007933417bfbbcd,0x0002ac0c744278e4,0x00079c8483d8b4b3,0x000fafae62ecea8b,0x0000000000000001}, {0x00063d47c065003b,0x0004185cb3cef55d,0x000bfcfe8d3872f3,0x0009112c490c5e61,0x0003b1e7d4274313,0x000517366c9c6308,0x000bc9bb53389bc7,0x00025afa81750fe0,0x000afda6e1b71dc2,0x000c6a9aba51c85b,0x0000000000000000}}, {{0x00000e070af57b1c,0x000441246548fb7a,0x000c563ead66464d,0x0007508f0851b47e,0x000f31999ecfeae6,0x000f85797a3840b6,0x000c74080d60c378,0x000f3eaf1e242bf3,0x00003ca35d886cbe,0x00022754c9a357ba,0x0000000000000000}, {0x000982d0aaae9f75,0x000176d1b4b6ca3d,0x0007980f7d421826,0x000979133a61fcc4,0x000cb63f41cac3bc,0x00079bb4b9516419,0x00033cd18a279569,0x00075e18895b57d5,0x00063599127b0d23,0x00063dbbded01670,0x0000000000000000}}, {{0x000342ad817f361c,0x000cb1bd9eb81b06,0x000c7b97a0843c43,0x00083f804f029e13,0x000b3486644af0ff,0x0002a64dc632346d,0x0002a39cc0dcbed6,0x00056457b2ff9c5a,0x0000fe8536001cce,0x000def7d14af048a,0x0000000000000000}, {0x0006c4115861eef1,0x0006a14bad6b1ac1,0x0005dee3e9d201f9,0x0002b396cf147ed1,0x000f4643f8a21b3b,0x0004c9915584149b,0x000a893cfd7ba449,0x00027a8a4eb7aef9,0x000cc4fa992b1d31,0x000eec6c99a8fa7f,0x0000000000000001}}, {{0x000a8d985f7ab9a0,0x000b7d39a70c2f72,0x000f6f8acabea7d5,0x00095d0273f642dc,0x0007d8a54bc56deb,0x000a63f1883f3cc3,0x0004b831ef1bba05,0x0008e112f14c8c07,0x00089737917f937a,0x0004874d335ca229,0x0000000000000000}, {0x0008374f770af11f,0x000cad8ee96d7e99,0x000bff9e11a7d432,0x00056384e6665366,0x0004a9b692423f6d,0x00075f044efc7e34,0x000ee60ee1b3dddf,0x00039cd00df7a827,0x000529eb5b2612c9,0x000cd7c4ffa6a13d,0x0000000000000000}}, }, {/* digit=84 [{1,2,3,..,}]*([2^336]*G) */ {{0x000c16671a6774f1,0x000af03753ce5839,0x00054c5f8c07356f,0x0001afc71165a356,0x000f9d6adf86cf5c,0x000a6b4966903b89,0x0009f4ebff86c3fb,0x0004a87b0151b151,0x000efd27bbe4f95b,0x000b040513d26385,0x0000000000000000}, {0x000622a63fa5d90d,0x0008d92aca99c7d4,0x0001d6acf3aa6efd,0x0001b7387e55d6dd,0x00010db119c2295a,0x00011a67dad9703d,0x000eedb427c0f52d,0x0001e055192fe412,0x0004a5758174c7a3,0x00055cfd4b1dde40,0x0000000000000000}}, {{0x0000d119f7fe9853,0x000fe49990254b37,0x0008a86cb40764d3,0x000820af39be0e2c,0x00027458321b04b9,0x000c2ba583294752,0x000ae89a07a5c7f2,0x0008fa6d520652e9,0x0005604c9bdc0eee,0x0000c06f2e484243,0x0000000000000000}, {0x00014a30a2bfa81c,0x000cbd6640003017,0x000ab87a938a3f37,0x000e1c91f3132874,0x000e57e9d7ac6ecb,0x000e33fb881734fa,0x000073b600765b07,0x0009428cbfb5edfc,0x00029028585e9a20,0x0001e077ef7692bd,0x0000000000000000}}, {{0x000cf34a0d6f6ffe,0x000370c22b280291,0x000e87a26b1fd975,0x0008088a662b3666,0x000eea746601046d,0x0008edbdfb0988f2,0x000f2131f7fc1ebd,0x0009266b6d41f4b2,0x0003c1c020089694,0x000be27c849de8c8,0x0000000000000000}, {0x000bcda37f3a594e,0x000726480ec74a90,0x00026216e2ddde9d,0x00064b02bef16495,0x000aafba3c749a5c,0x000a872930c3f630,0x000654a8695df3be,0x000cb5372491b21d,0x00017f3b3a2f3f6f,0x00094613fe01cfe9,0x0000000000000000}}, {{0x0008937b47b39090,0x000415bb7112fdec,0x00066e9e19d3ed5a,0x0006597801eab0fa,0x0005e740c409bbbe,0x000050b19bba9267,0x000df2c3e8b56daa,0x00012fbcf099e6ee,0x000195262a55e069,0x000ee2f2c7d1e980,0x0000000000000001}, {0x000c1384c013e53c,0x00074951ffea5bee,0x000d0ad477deaca6,0x0004ee3245756473,0x00030808642161fd,0x00050c8b97a30694,0x000340f405f653b8,0x000d5a543cae9de4,0x00031ca24347d550,0x00092a75f4312ea3,0x0000000000000001}}, {{0x000c8162c746ef6f,0x000f6715dbf9ea58,0x0005523d8217dd87,0x0000b2c52bc5b0b4,0x0005db8903ecd878,0x0004296f75f92e78,0x0003c6e6397e4045,0x000e84bad1cccce3,0x000b82162d3c5f54,0x00009333f935ae95,0x0000000000000001}, {0x0004ff1c33e26a2e,0x000785b4ec10e1f5,0x000a1634274c2886,0x000b5d5ee5822d49,0x0002fbe9122e0bfa,0x00003c2cc2955a06,0x000e08e579ad9b7f,0x0001dd6ee255f2e5,0x0004f08f71b65e70,0x000c9dcd7d23cb93,0x0000000000000000}}, {{0x000927819d85c389,0x00088dd986cf5001,0x000eb6ebdddab174,0x000a1e388628281f,0x000014511bc0392f,0x000b79c2a5e1691b,0x000d866b842f8440,0x0000343c71a48805,0x0002ac5c5d5d795d,0x0004aaedd8558804,0x0000000000000000}, {0x000896067875f110,0x00080b0d43dab8fa,0x0009a3104ecd6f15,0x00017c31840b3b59,0x0007841201091767,0x0008de871b2243eb,0x0003f7be2323a388,0x000f764799c353ac,0x0009d244edaf476f,0x000513c595b87c99,0x0000000000000001}}, {{0x000800832e6fdb7c,0x000df2ceb7712003,0x000625cbf7ec3398,0x0007b9eb4c74b442,0x00090424f2515df6,0x000abc10516b9778,0x0005df82462b4902,0x000a6d60d9807c8f,0x000606aee1bb838c,0x00030e1e7a2ff1ff,0x0000000000000000}, {0x0008fce9b8ce853f,0x000b7049a4c20923,0x000ae2b39f773f7b,0x0002f55bcfbf4b1e,0x000b07309ae9653e,0x000cf869d6026775,0x00099fe1b0e83daf,0x000202f8a21d72ed,0x00037619de81bf7a,0x000b7b2bf238b7d7,0x0000000000000000}}, {{0x0008ca9dd54298a1,0x0000e1308270c47f,0x0002be3ff9743378,0x000471b0b186cdf8,0x000b1747ce696eb6,0x00015fe31005f60a,0x000ac1b5a457da88,0x000f4901af0f6bb9,0x0002f972c925bd14,0x000186acd8b58a65,0x0000000000000001}, {0x0000f355372184c6,0x0005e1f7ba0c693e,0x0005b11db3d6dbda,0x00051b89e46fae1c,0x000c97c0b46b0f1f,0x000cc037caa48d5e,0x0000355bdcc75991,0x000f28784dc0e5f4,0x000837eadd1a3fa4,0x0009eeb5a1926d0b,0x0000000000000000}}, }, {/* digit=85 [{1,2,3,..,}]*([2^340]*G) */ {{0x000847fc397e26dd,0x000de02cc0ff17de,0x00063e6fe388ee8b,0x0001e73a774123d0,0x000daf8cb9f5597b,0x000b938535ee20c8,0x0000d7da8b1bfac8,0x0008e2a819363df1,0x00079861ae7d4273,0x00003eaf0a677999,0x0000000000000000}, {0x000611141de00c8a,0x0001d2aefc5b58bb,0x00033633ce29b3d9,0x0004bfef0d5e3306,0x000d78956c10a254,0x000fa84101beaa2d,0x000f9588ba22402c,0x000e0df8f46296a5,0x000c7018734ace12,0x000ca8e0e00d25c6,0x0000000000000000}}, {{0x000c26d9a28cda66,0x000ac34788e2808c,0x000a2e3c895ddb52,0x00092cc3305bc55d,0x00086ee8076376e7,0x000da2d9cb5f9d99,0x000f0d8aea185a30,0x00068ef462b956f8,0x0000f61c2096bebd,0x00044e7be11b5930,0x0000000000000000}, {0x000ea58bb15fdd13,0x000d5b2585fb779d,0x000d75c3d978271c,0x000e827a5ac1a4b5,0x0006c6fe4d4804ee,0x000f66c09f0147df,0x000b3203f6a4c217,0x00081eeb950292c3,0x000da3f441776841,0x00071712f688beeb,0x0000000000000000}}, {{0x0004586de8027c8d,0x0003b7dc25b073ea,0x00049b36fccf2477,0x000032458466e794,0x0006f36f854043cc,0x00051e24c902d71d,0x000ec681a81ea4c2,0x00060e710d119e39,0x000dfa8e50e27e69,0x000bc96885ae0f44,0x0000000000000001}, {0x00072cc7ee3e54e0,0x000e54b8224b0f78,0x000e5d4bd3db5696,0x000d27cc64ead37d,0x0009b5b2f36d2cba,0x00021210e2a45e52,0x0002c8d788fbf745,0x000440c5440be1bd,0x000157b392b99018,0x00045deeecc510bc,0x0000000000000001}}, {{0x0001f34441941c1e,0x000786af242ed224,0x00082ffb7bd73f71,0x00040040ee8f684b,0x0000b0e0a77660b9,0x00055090773cb918,0x0003b4341ff934d0,0x000efe154397d7e6,0x000566086597b1f2,0x00038e115dad8d73,0x0000000000000001}, {0x000320279e97eed7,0x00092b44ad3c59a0,0x0009546c02d95d0b,0x000317d617644016,0x000b3b1278de80cf,0x000150eec20cc035,0x0004047a454911ca,0x000eb15350f140f3,0x000297dd664a854c,0x000c1545fd389a24,0x0000000000000000}}, {{0x00054c6d42f4ddeb,0x0001a5d46442b31b,0x0008eb97dd3c9497,0x000f35259e3e1ff6,0x00049058db0b2e2d,0x0006968077e0b694,0x000456e4ea6ec9f4,0x00098457796aba76,0x0005412cc7718336,0x000c5eb4e4306f25,0x0000000000000000}, {0x000f4a91bf2060dc,0x000e9a57dadc33ce,0x00051f56adeb934d,0x000b29d22e8fe341,0x0000f85723b5e49a,0x000ee66b41fabf52,0x0005253bffe67611,0x000c50202f550a60,0x0006d250b9e49468,0x0001a2956ea13fef,0x0000000000000000}}, {{0x0000dc097ea2b524,0x000c5eb5323240e3,0x000082d33c53dd49,0x000c5d6917c692b6,0x000337e9d695a12b,0x00078372d602c7fd,0x000ef2985e92117b,0x0008ceacebcbefa0,0x00068cc3e9b4e8e1,0x000db3e3e50ee13d,0x0000000000000000}, {0x000980bec0d2f5e3,0x000eaa9b062f585f,0x00083ee3b5103eda,0x000605534f1f8028,0x000add292d29ee4a,0x000f9ba28df95f8d,0x000d134fb5785f57,0x000f0fe162fe54b8,0x00047f0902bd8287,0x000de3769ce1a122,0x0000000000000000}}, {{0x0006e3d538c32c91,0x000eb774341e7141,0x0009e6b225ba2b4e,0x000824dcff742236,0x0004d5e3b9c67d3c,0x0006e4276dd54722,0x0001d2dcc105d46c,0x000392da4b3a8a00,0x000e2f3953b25248,0x0002fecbb5174b67,0x0000000000000000}, {0x00008d720508826b,0x000b9b4e2e807123,0x0001bf6b1169562d,0x0006d2acb14e6841,0x0008cbfd3257245f,0x000189ac1c8cdf45,0x000ee493f894fd3e,0x000fa59cbf0ab5d6,0x000476d8e672a0c8,0x000ed9fbb78753d8,0x0000000000000000}}, {{0x00039334c1cd9788,0x0008ab0560e3e74e,0x000fa2ff6e2c62b5,0x000acd7d25b0cfee,0x000c456f469aee3d,0x000a862fad6476d0,0x000688f0d8d2340a,0x000b648a9494468a,0x000f4ed209d4d2fe,0x0008a93e7c5890e9,0x0000000000000001}, {0x000cdd07e3f60721,0x0002466078437612,0x000ea1835868d6d1,0x0005ba6a85400753,0x000f7f252808d5c3,0x0007b45d6857ba4d,0x000d683048ddde70,0x000c759393e38c60,0x0000c630e919b183,0x0007209017172576,0x0000000000000000}}, }, {/* digit=86 [{1,2,3,..,}]*([2^344]*G) */ {{0x00060ead50b81885,0x000bcef73cb6f0c1,0x00053fb7eb3e2cd2,0x00062b319bb7bc05,0x000a38a471706b6b,0x00046c6b42daf298,0x00005e59d404cf98,0x00048fac2e73085e,0x000ff0af6c53893b,0x000de9e3d8eea7a8,0x0000000000000001}, {0x00034470acd5b055,0x0000c4c1af94ede9,0x0004fba6b3889b3f,0x00023ee49af80496,0x000f0d89fd53a3e4,0x00053cc302793fad,0x000b36dcd463b613,0x0003782e102e51fb,0x000c63732d6d1c6c,0x00059dc97f604bbb,0x0000000000000001}}, {{0x000db31484a7e177,0x0001740a1bc3a05f,0x000c265e95ebda07,0x000546d643b1d3c4,0x000c2611b9709edc,0x00015784fc807b04,0x000e5bd473ceec4e,0x0003c97fb33e58af,0x000d6d5327b94dc5,0x00062a914fc6dc39,0x0000000000000000}, {0x000cbcf73d880ddb,0x000029df80627a67,0x00091ccf95a67d3e,0x000ec7aefd91b52d,0x0003aa855273ca53,0x0007213a95113157,0x000b98a49db550c0,0x000b470643affa5f,0x000f0628a0fa67f5,0x000d2cf906186e6b,0x0000000000000000}}, {{0x00039cff07a9f5bc,0x000b27814ba6cdbc,0x0008da0e67469efd,0x0004ccf0a198fcd4,0x000cbf71a6e5b71a,0x000500eabe51b9c8,0x0007908463c5cf80,0x0004962539aa0260,0x0001de61db956e33,0x0004f9e2c1ac338f,0x0000000000000000}, {0x0005f37dc080da53,0x000c1c2a74369386,0x000025722593f4e4,0x000a4e09b626a8d5,0x0004b1e7f8c96db6,0x0002c5a75c187079,0x000cb91e644a3045,0x00024e7eb18af641,0x000fb48086d9cefa,0x000b4dd6532fa3f7,0x0000000000000001}}, {{0x0001be067e3e2f37,0x0007737f152d2c7f,0x000242f8dec8659f,0x000c7d958df47d63,0x0001b91c63b0acba,0x000c2c6ad3f62088,0x00099adda54c0028,0x000a3012f6937019,0x00014f4c499516f6,0x000da068d44cb73c,0x0000000000000001}, {0x000209ec58d1b414,0x0008e876dcc7401d,0x0009323106751dc5,0x000f75f24e14fe98,0x000ac88f5086e5a4,0x000294dbdb4ccd6a,0x000be99edf86543f,0x0003767f48ab30e3,0x0007667c622dcd0b,0x000d7fd6615681d8,0x0000000000000001}}, {{0x0008c453ac10be58,0x0006d75a48dfcf2c,0x000c4944bc5042f3,0x000e7ad5c9cee1eb,0x000996c45d109bc9,0x000689f02d424fbf,0x00023528e926c326,0x000e84ac793d58e5,0x0008eeaddb5a4ed0,0x0005d31f9ea2560c,0x0000000000000000}, {0x0007ba171a6ebc35,0x000d39e242ba28da,0x0000694f0cc97464,0x000d7fb496b0d2fb,0x000d7e1b5b66b3d8,0x00001db81788dc1a,0x0003854dd5fe4e9e,0x000f9965063e6021,0x0003751c74ab4631,0x00006945420e7941,0x0000000000000001}}, {{0x0005b110bb6dcc9c,0x000e9d1e6c13e60d,0x00058585159a0842,0x000b46fe443356f4,0x000853b25c086265,0x000ebbff20877291,0x000136ec71c4d1d0,0x00003ebeca5e79c2,0x000a0af3b3a96ed2,0x000f93012e330a32,0x0000000000000001}, {0x00017ed67dacd4b6,0x000ceade583a567d,0x000316840b4e5703,0x000c414303d396ce,0x000ed6970ea480cf,0x00063761b9b1974c,0x000788f3de4383da,0x000ad07d6726e400,0x0003056bda545993,0x000385d3fe822ea3,0x0000000000000000}}, {{0x000285c58225166f,0x00072d2451ec99f6,0x0005efbddf5101b0,0x000dbc066e055890,0x0002c29985ac7cd6,0x000f1839b6caca94,0x00093cafd8d9c1ce,0x000b177ba7911d6a,0x00098fc762e30d5d,0x00067686b89a78b5,0x0000000000000001}, {0x000dff4557a32b93,0x00037e16c6af191e,0x0007ad7362550f1a,0x000983cb772b5537,0x000b0746f50f2068,0x000dbb42f7ee6b8c,0x000f0cdda882070d,0x000a732384a13e83,0x00055b3be67dc4f2,0x0003cf20d84f4cbc,0x0000000000000001}}, {{0x00007348004e40c0,0x000448f78fb0602f,0x000c2ac8aebb2604,0x00064b78277ca03f,0x000eb2c6f473d278,0x000cb793a9eb1664,0x000e2b358eee9a37,0x000194f18cbc9c2c,0x000f6078bc87a3dc,0x0006220e93cd112d,0x0000000000000001}, {0x000d1ed5d96d6d2f,0x000b72be10752f3f,0x000d1e476660c38f,0x000b1d6d9b093c35,0x00026d898dff773a,0x0004b445df00e4cf,0x000d1ce422c1136c,0x000db6e821b59ee0,0x000de6252e82511e,0x0002f481c804e41a,0x0000000000000000}}, }, {/* digit=87 [{1,2,3,..,}]*([2^348]*G) */ {{0x000d7989af2b44ed,0x0006f91b1a9086f8,0x0002b4d5672b30f1,0x00072009919c3dae,0x000003b6ec0a964f,0x00012b7f4f64ce56,0x00076bfe0f0d4fbc,0x00043eb40f821444,0x000cbb4480332a8a,0x000f3ff375566080,0x0000000000000001}, {0x00018caf35e5d712,0x0009aba53d6591e5,0x0004f1b1b50e170d,0x000f9eca3e56ed3e,0x000288dfe4cc67c4,0x00059c7726fa0dd0,0x000a0660a01f234a,0x000a704007db6c8f,0x00070b32e8366767,0x00096994810fb845,0x0000000000000000}}, {{0x00092a1897b4c0b5,0x0009027fe35612df,0x000a5105c7f9f97d,0x00021853ba021326,0x0005dd2cadb219c5,0x0003ab9d259b3ed4,0x000857fddadc1ebb,0x0004addab0607b4a,0x000ff916fbbc92a3,0x000721ee7e6c527d,0x0000000000000001}, {0x000ba1dabc6f5958,0x0000087b0e564aa3,0x000b9c963dd27f6c,0x00028eca3c030970,0x000c23cd7a457768,0x00017b833d0834d3,0x000be25f44c50d54,0x000a153d4a6bf0d8,0x000e9c71da49590e,0x000d43f3a30dc247,0x0000000000000001}}, {{0x0009bd585a57c01e,0x000ee844d7078c7b,0x0006c16cb258be3e,0x000a3282f9caf55b,0x000e08d004fc2ebd,0x0009db3ca2d054d0,0x000ff89010ddde2b,0x0006615b9b156d6c,0x00000ee87cbb5e96,0x0000965826673f04,0x0000000000000000}, {0x0005c973c58e4e2f,0x000bfed17990af45,0x000982806a235d03,0x0003a7e6203578b6,0x0002679d20d4837e,0x000fa09a67212915,0x0001e993e548aecf,0x000034e7752d33de,0x0008c0133b8d99be,0x0005d644443ed88b,0x0000000000000001}}, {{0x0005d09795891669,0x00055ce0c6b8f799,0x000cdfa7a67baad2,0x0009a5462a84102f,0x000ca5fff322b2ed,0x00016895f0238b4c,0x000e1fc27a1fc8f3,0x0007399300db4369,0x00016f718708ed71,0x000aa4931503fe5f,0x0000000000000001}, {0x00040da9e1ff0c6b,0x00022af9967269a0,0x0005871908b86944,0x000801c88350fa73,0x000f680cd1b5d61c,0x000f0b415826cc63,0x0008b363474f5f7a,0x00027800e5401e93,0x0002305262f20f7f,0x0005e6d27bb44c56,0x0000000000000000}}, {{0x000dab714dbca0be,0x000450d634bc786d,0x000d2802c42f3afb,0x000ef6e542d9994d,0x000946669336b0ea,0x0006a8fe65059b68,0x000f702cce1812e5,0x00030e3c70e359c5,0x0009fd5b9f2069d5,0x000093f3f0186d75,0x0000000000000001}, {0x0006d10e2b40858b,0x000a417e22a4fbc2,0x00013ba0de831401,0x000d41a31a86b763,0x000893ad0b78b7c2,0x000aacf20f1564cd,0x000bac0041297947,0x0004ac69dc2da24d,0x000ba071987933c2,0x0007176068dfbd75,0x0000000000000000}}, {{0x000c8b4eb4601064,0x00099a991f16e053,0x0005bcf58e425bfa,0x000b1e6fefc21bff,0x0005da04d7e97cf6,0x0003f93bddaedacc,0x000336130ff2741f,0x00028f428d033ae2,0x000b98d58f0cc054,0x000281be6796c6ea,0x0000000000000001}, {0x000562d3cd261bc6,0x000c4e652831be2e,0x0007f84fc06f2ac2,0x000b078d9ca13774,0x000d2b248e882f5c,0x0006981dfa0231e8,0x0005f7dcfabfd673,0x000f3658f51759de,0x000d6a68de41452d,0x00038358c049f993,0x0000000000000000}}, {{0x000dba36a11f468b,0x000ddefecb4596c7,0x00004044ba328343,0x000e3d89658e943c,0x000955f5e1aeb372,0x00008650d658c0f4,0x0004309aed6ff5c1,0x0000ad875f7bb480,0x000c35156e670707,0x00066875cf1c6033,0x0000000000000000}, {0x000bceb289713705,0x000a8a9a03fa8061,0x000cac052e91978c,0x000b61eb6bb99c20,0x000e50fb8f33460f,0x000ec61a887398ae,0x0007437f45e3c633,0x000fcf4c74c22971,0x0004691a2d9b4866,0x0009004647f4a64b,0x0000000000000000}}, {{0x0004f3cfa7e54e73,0x00076a7075c33047,0x000b446bdd4b3ee5,0x0003371a1b7efe90,0x00013826a3c98a14,0x000412cdba45fcf1,0x00048a44b5601caa,0x000206ebe3f76143,0x00050e4439f111b6,0x0008451f6bb4a9d7,0x0000000000000000}, {0x000c0d59b5f2d48b,0x00029bcb29ae2863,0x0003a9a3c78e216b,0x0007856c2465c5b5,0x0004736d155fd956,0x0001ce6b07dfbfe0,0x0008361c3a4fa43a,0x000d0e9f03c0f19b,0x000e803f9b21f548,0x0002f885460ccb9d,0x0000000000000001}}, }, {/* digit=88 [{1,2,3,..,}]*([2^352]*G) */ {{0x0006b287cbed671f,0x00071c978130d6d2,0x0007aadd881d433a,0x0004f45fb4ad7bb1,0x000d7b1940d6b52e,0x0002d44569722e2b,0x000de70f91dc84e7,0x000ed42546436d3f,0x00047e41abd1bc41,0x00010f544a7be2b8,0x0000000000000000}, {0x000e82545325818a,0x0003cf3d8e5d2be2,0x0005f30317d1c986,0x00015ce098fb8ec2,0x000158947db8581f,0x00055d8793f3e6c3,0x000f50843a7feb50,0x0008ac153d3d8417,0x0004329e7248bbc3,0x000d2ffcfbcb0366,0x0000000000000000}}, {{0x000b91e88872c802,0x0009859329a6f390,0x000332091e85e0fd,0x000d0a1fc7233994,0x000c07172741e069,0x000870fafc953488,0x000d8073b040fb91,0x00089e841e1bbb2f,0x000f582161687272,0x0007bfa72dc0f548,0x0000000000000001}, {0x000c2f4044695d52,0x000e9fc898f3ae4e,0x000d6d16346893df,0x000cc356cfc2a2d6,0x0008f9780e14adcf,0x00040c34a952a0f5,0x000bf1f1f74017fe,0x000ae85cc7e49637,0x0002400547db8273,0x000eafd4e119d7f7,0x0000000000000000}}, {{0x000a5355afe08a2e,0x000687a2f29baf29,0x000653058a23e11c,0x000110b2ab5abb63,0x000e4ead1d1b9533,0x0005d1b7b6254324,0x00074059ad5a8616,0x00090712ab62d100,0x000e9d5016f88f2a,0x000afeefd62c6b78,0x0000000000000000}, {0x000d2d42ce0d173b,0x0009198d15289e62,0x0004baf7b535d68b,0x0008566e4a9af773,0x000402c278158bfd,0x000603f6310f0f5b,0x000331a366d639ea,0x0007457655beed79,0x0004b46175b5f4bc,0x00048f6ced012274,0x0000000000000001}}, {{0x000b20efdb706d0d,0x000c40117c40b081,0x0000a6d9c2aec008,0x0004d3e0693270e3,0x000674266a5ea611,0x0001ebf62144a6af,0x0003d45ee3917e38,0x0008c35ff5d67fca,0x0006e79dba352604,0x00081a7e7bfed40f,0x0000000000000000}, {0x00006eb8dc692380,0x000fe33343c5a20c,0x0003e67d0a53418c,0x0008959e15eb001a,0x000ac0ead5e7c7e4,0x0002e4162f0962e6,0x00017bb3e28513c3,0x0004317568fafb81,0x000912ceb3a2e303,0x000102559381740c,0x0000000000000001}}, {{0x0005f372c77f1047,0x000b3d958eb7b744,0x00069ac2a8ab1157,0x00057d2ec5015809,0x0007f4db5c158ff6,0x000e3fc15a71737f,0x00048e949735c5de,0x0003845758233ed6,0x000e91137608f198,0x000720cc72b9199c,0x0000000000000000}, {0x000b050528cb006d,0x000ac29d53a71cfd,0x0009a1f2ad6eb262,0x0006c829676f56dc,0x0003dd6ddbfb591a,0x000c61cac801979f,0x00031b13cd6cc83a,0x0003cf1a5e5c85bc,0x0007cff1f95623b3,0x0004f7b2cd595d6e,0x0000000000000001}}, {{0x000699fc8b3dab7b,0x000229f393f97b3f,0x000012376dbad08a,0x00038a797638cccb,0x0006110a40e7e328,0x000e3d1acf08dea4,0x00003f85adfc07de,0x000fffa8d9d37eb4,0x000db3ca114eff2b,0x000b41dd72c79e23,0x0000000000000001}, {0x000822fbbe3ad3af,0x000ddd71461cfcd7,0x000d3d8f03aedaa8,0x000f069c35282be1,0x0009283f776eb004,0x000746b05b9838ad,0x0002fcc85c205f31,0x000bd9143e61b0eb,0x0004e7f4435b3321,0x000a673088e100ce,0x0000000000000001}}, {{0x00052e132b686982,0x000419eaf166734f,0x000edb4ffc59ba11,0x0004fda13f9e0e45,0x0000c12226a0efde,0x00070adf716ee2a5,0x000402012f467257,0x000f2ecf2b32d94e,0x000205b1386ade63,0x000b3bc779c31b50,0x0000000000000001}, {0x000cbbdbe0875f47,0x000a208dcda3e65d,0x00048b61b40cb945,0x0002b16480725e0f,0x000aa186079b7359,0x0007e306ab144462,0x0004b09effdc0e10,0x000a76ab4395ae17,0x0008c3ddeeefeec9,0x000216cdb5d669d6,0x0000000000000001}}, {{0x000c70f6d4b2fef7,0x000c0c92ef06acfe,0x000790f3344c38aa,0x0000fed753c30edf,0x0003dfc8006501b4,0x000df722f2f6da80,0x000c340284a42e2f,0x0002a0f154005cec,0x00082f0dfb36ac65,0x0007bed1506b21ef,0x0000000000000000}, {0x000d76b785906061,0x000edca1c3d7b884,0x000307e9a89c6050,0x000e0ccc1519baa6,0x000663495eff88c7,0x000a17475b22e916,0x000c39e69639f1ce,0x000b1f0e827f8c53,0x000066355ede8121,0x000d5b91249281eb,0x0000000000000000}}, }, {/* digit=89 [{1,2,3,..,}]*([2^356]*G) */ {{0x000ccccf35a37229,0x000465167517203a,0x0001bf938eaa2ac7,0x000d73d683a983dd,0x0007f598a6f1db73,0x000235f9ed630b4f,0x000f332db784cb56,0x0003b330540f52bd,0x0005843b0221e5e8,0x00044a09499b4ec2,0x0000000000000000}, {0x0000fb3cab0a1b02,0x0008968b6e52dc01,0x00022c046dc60a24,0x000695beae1e187a,0x000d3006acf49482,0x000960f10535934b,0x000df011e1d0143b,0x00085de371d84cfd,0x00082841456c439e,0x000585582ff3b564,0x0000000000000001}}, {{0x000e94ac6fbf17fb,0x00044289803b61bc,0x0002e798f31e8afe,0x0005e43d9a42f37b,0x000f377aef7a7947,0x00003a6947a8f685,0x000c1b4969c3b8c2,0x000b9c542cdbdf0d,0x000501682c76bc8f,0x0006972a768660ff,0x0000000000000000}, {0x000f9daec5f3009b,0x000325c4a46652c8,0x000b09499ac89b1c,0x0003ccd5721c0cae,0x00098da46e3445e6,0x0002db691caca0b9,0x000845a793a1fc73,0x000ad927f614049e,0x000024bf07aea310,0x0007245359be8b80,0x0000000000000001}}, {{0x0000db1596cc9e80,0x0009a231d0f49f13,0x000f1d499d6bd9c7,0x000757ac7ea9b7cf,0x0005305a4d545367,0x000f2c85480a42a4,0x00029efd461a5b51,0x000fe691c9e6b8ed,0x00090ea1ca549541,0x00058f09c0153e64,0x0000000000000000}, {0x000525f593f9a0ed,0x000edbc140a1f67f,0x000f5bef166a98aa,0x0007a559750be5c2,0x000fb8cba58b2d45,0x00014d93d0c5d96c,0x000723470bfa2f95,0x0004f6b79058b86d,0x000d58f11a8a7858,0x000fe32b2d0ad418,0x0000000000000001}}, {{0x00016f6d1a0d42ca,0x0000a7c2c062afb4,0x0001630676c3dacb,0x000c297ad74ee6b3,0x000d18f736e4995f,0x00064edc2548a7a2,0x00031596b5d5f53d,0x00040e945b2c8330,0x000587c06dfaa52c,0x00037c462a8f05b0,0x0000000000000000}, {0x000cd636b4f0d870,0x000b2b0835ddc02f,0x000d233347086482,0x000bf92bc7f1c7b2,0x00050d5f30c92b32,0x000ce136c0491539,0x000254d29288cec9,0x000c34eb38494ac8,0x000ba2a1b0b3117a,0x000c473a85376a14,0x0000000000000001}}, {{0x0002a61629b67537,0x000edcfef26d3aba,0x0004bac42f2af22b,0x0004da8b32bd0514,0x000be474d59e6af5,0x000c190f17846ca3,0x000f3e17e7c79bfa,0x000a13543ecbaea0,0x000e74acd0ff996b,0x000cbde27a5f5aab,0x0000000000000000}, {0x000ccc73ffeccff0,0x00082b1e746179a8,0x000b19b717d62af8,0x0005045a4e0895be,0x0006b8f194a8bb25,0x00089f1cd50b3736,0x000f2a57b3da3e10,0x000691e4f67468b1,0x0008976ca9c4602f,0x0005e53ed98ad969,0x0000000000000000}}, {{0x000f79bf523ecdd9,0x00097ebf36d74486,0x0000fe48147bf45f,0x000868d46235b3ae,0x00073a9b13d93d40,0x0004e9264c45fa91,0x0008c79b5705f4c3,0x0000fd4b166fd0d5,0x000aca2edaf4ff87,0x000955b68a488f7a,0x0000000000000000}, {0x000f3e0b19951fb2,0x000c26747dd972f5,0x00092d84bc8f6fc0,0x000255f7088102b5,0x000c984970893201,0x000a6791707f6288,0x00072769309b54e6,0x0006389f4da5d532,0x000c1eb23c48b5de,0x000d1bac794b858f,0x0000000000000000}}, {{0x000e2d8dfd2d5a87,0x000e5a708c918328,0x0009b9fb00f1dbe8,0x000fe9c7a3695cb8,0x000749205b4caaea,0x00056f204bd6ec0b,0x0001a73a9e0254c7,0x0004152441cfd51d,0x0000d2b8b0ca9156,0x0004dee3cdd9e937,0x0000000000000001}, {0x000ab13754dec146,0x000b5d5322d78e9d,0x0000adbfc5578b8a,0x0000ce27a2b97f9c,0x000b49cd573f2d5d,0x0006ee23d2e94e39,0x00061ea213bd15a0,0x000e561b9d34708d,0x000fb576c6271f59,0x0001669ae9450741,0x0000000000000001}}, {{0x0001a66376c54f37,0x000a06b888102e23,0x000430b0efaaecdf,0x0003b1e3d888793c,0x0004f8beed2dbb12,0x000ea5e72a8887df,0x000d4aa2425e9853,0x0009d98e93f3ccc7,0x000cba97fe918171,0x0006b08ea6eef307,0x0000000000000001}, {0x00019b171f51c344,0x000d5e5d9f40be57,0x000fea96313e16ec,0x0001461efe1e359f,0x00043de9904f3d9f,0x00081bb7a038f6d9,0x000ed552c5787d58,0x000a67fc2cd9a74e,0x000643f377ccb483,0x0009db7070b5762c,0x0000000000000000}}, }, {/* digit=90 [{1,2,3,..,}]*([2^360]*G) */ {{0x000188556b53942b,0x000736bd7c7672ca,0x000a466705820ced,0x00039ba4b83d6897,0x000af174ecbf7e3f,0x00003dc58b34188f,0x000b453db5dba0b2,0x000ef54df32d5206,0x000d08e3c52fcf51,0x0003732f551f3408,0x0000000000000000}, {0x000937ade92603b2,0x000b6a7f7f5dfd6b,0x0003151876b632c9,0x0009040d3ee4a789,0x0007441b009fd7a5,0x0008b427fedfc2d2,0x0007f921c0ceded6,0x0002220fc8f207d5,0x0000f675383c79a4,0x000d6f410a2e837b,0x0000000000000001}}, {{0x000fb8b792ff9c0f,0x00062d82addc4301,0x000b9cdf1d9fdb00,0x00042255b1cf25ad,0x0009daaea42ebb5a,0x000dffd105199066,0x00001d688f207641,0x0001da7769bd6130,0x0004ea507a275aa1,0x000073ea612e43e0,0x0000000000000000}, {0x000f18b4b24386fb,0x000f72268a5e0821,0x000ad126436a7554,0x000ba02f714fe1c3,0x00019b7c7cde45b5,0x000c576f09f2da35,0x000aef34fb328e0f,0x0001a0386e0f185f,0x0007a6bb32adc73d,0x000733da21be9ac9,0x0000000000000001}}, {{0x00023d540d542b80,0x0004cc500040b26a,0x000e6a09fa7f8755,0x00027fbb548aea96,0x00065fa1d8c060cf,0x000943cfee1a6187,0x00061bce6a8c7ea1,0x000d99730b0b20bf,0x000eac170744528d,0x000423d049742c42,0x0000000000000000}, {0x0002bba636da345a,0x000a62e601cd801e,0x000c9e240a6cbeef,0x000103af8106469f,0x00007c7109e54da8,0x000b9a3ec3dcc449,0x0007788e44b6df8d,0x000d0e67c93ee34b,0x000e8347b4a58495,0x00037223b5096e63,0x0000000000000001}}, {{0x000417e035b970b5,0x000ca1b60364c1bf,0x000ea847f52dda37,0x000517fb28527f5c,0x00007a1e399f798d,0x000452c79fff102f,0x000688a87dfab3cc,0x0006490b0295c5aa,0x000d17acd0dbc605,0x0005acb4f6972c3d,0x0000000000000001}, {0x000fa35559042635,0x0004e33a903ffa23,0x000c46f6e3526281,0x0007bc6b1cec4214,0x0004bca2e1dc8726,0x000b50045720b747,0x000c697f394811de,0x000ba5001f3d4304,0x0009ea7fd0f7a5e2,0x00090dead3d0124c,0x0000000000000000}}, {{0x000e47c23d19de00,0x0009afd475bc3cb7,0x0001acc6490ff459,0x0009f5dc39b1950f,0x00064d14540f1ee0,0x0001b75050e51c95,0x0005647bebd088ff,0x000f240dba4c1789,0x0009b95e8097400c,0x00085b5d4b842055,0x0000000000000001}, {0x000986a76d06fbfb,0x000d7fc2ffb65385,0x00018e264c5a478e,0x0005a2784841d184,0x000fe21d9e8a017a,0x000bf52154297fe2,0x0007dad072d6d911,0x000eae77c8ea8832,0x000786b6a02d1fcb,0x000e682555450013,0x0000000000000000}}, {{0x000de731f9f48a0a,0x000a357753cff617,0x00073655403972b7,0x0000484d28d73a10,0x000c846d46c140c7,0x00055b7ef1516a9d,0x00014890b5525944,0x0005f418ade1b816,0x000a465f264a9164,0x000ed37693e9a176,0x0000000000000001}, {0x000e5c3bfdcbca2f,0x000121dc135bc4e5,0x0003d39b5c7ca946,0x000be46855877498,0x000879fb5d801318,0x000afd92b1e5cb62,0x00024aecd7f80343,0x0004a3835c8434ed,0x00025764c6aa7d95,0x000a0241780668d3,0x0000000000000000}}, {{0x000c0928cf2280c1,0x000f2c37933b1734,0x0006bae2a2974a56,0x0001e8bdb1d26ac8,0x0009c84c336cb6bd,0x000ca41014cdaa1b,0x00024b87838c44fa,0x000f525239cae2ce,0x000cb0507515f204,0x000993dbd0e0a58b,0x0000000000000001}, {0x0001411bdc3926ce,0x00087f3e15aa5363,0x000ade47bf68672c,0x000028e493da50d5,0x000120048f8cd148,0x0005ecfaeb03c756,0x000e1347b7867aab,0x000ba0208953afcd,0x000be9b23e2411e3,0x000a2e848d40b424,0x0000000000000001}}, {{0x000583ec08d4ad28,0x0007687b7ba7d916,0x0002b3f0b4e2bbb4,0x0002caace0e4b3fb,0x000b0e6fb63a6917,0x00000520c822aab4,0x000f41f7930e37aa,0x00046bfa91da4dcb,0x0008bd604f521a69,0x00040fa707c1f0b8,0x0000000000000001}, {0x000520b880d23952,0x000bb822333018d8,0x000aa6a00bca6bc2,0x000f3469011553af,0x000c20ed5fc0a5de,0x000ee0e8c5bcfec7,0x000476e2f464224d,0x0002d844542e8adb,0x00009924fd3c1bdb,0x000f2fac98d161a7,0x0000000000000001}}, }, {/* digit=91 [{1,2,3,..,}]*([2^364]*G) */ {{0x000c9a655367407c,0x00001acf48b04d30,0x00004344830b68ea,0x00058a53174d6fa7,0x000f59044eeb31ac,0x00087d51a60524d6,0x000a344fb882d4df,0x000d1ed41d08aa0b,0x00086b6aea85fb93,0x0007f27fa57f4860,0x0000000000000001}, {0x0006f6fa7b7febd7,0x000ef92aae956259,0x000abc183c404813,0x00011be4ded30d2a,0x000e220b7ae966a0,0x000c3e6cfc88e77b,0x000a92b77d5e0cab,0x0003d7f99c6dac06,0x0000a6be4c76c302,0x00032d1d55150da8,0x0000000000000001}}, {{0x0000d37f0300cf42,0x000564d1a1ebfaea,0x000bce4cf04b07ea,0x00084f2b4677d784,0x000db14a4f867741,0x0000b95ce93b8741,0x000a31735b5960b0,0x0003d2c80a76fae4,0x00022c4d123107ec,0x0006cd8678a9d705,0x0000000000000001}, {0x0004b58dcaec13d9,0x00067d88c3d5f230,0x000f847248f45f52,0x0003da2628ef4e85,0x000e37945a7b9c0f,0x000a2da387ea2c17,0x0008e98e84de9888,0x00038290c88f211a,0x0004ce3667557434,0x000040ca4612f56b,0x0000000000000000}}, {{0x0009e872c584974d,0x0006ca75132450c3,0x0006c420ca2dafbb,0x00069da0e632e68f,0x00018e1d45c5a963,0x0000394fa7a8601f,0x00098adcea6c9852,0x0001b23e3c6dad95,0x000f0655b2b99628,0x0001992529d81db4,0x0000000000000000}, {0x00000b6625e14e8c,0x0006611065dd0a46,0x0000a833140f2868,0x000735d82490f09d,0x000326d182482735,0x00074f69a678ac02,0x000e336a3425366d,0x0000093a8f215358,0x000644f6ddf3569b,0x000d19beff776a6e,0x0000000000000000}}, {{0x0007a73bd7975b73,0x0004ba1e3ef4b56c,0x000835871e0104fc,0x000ed4624759b57a,0x000eed3c95d4d9b4,0x00029d8353648a71,0x0006bedece81ad28,0x0001452c12f2b2a5,0x000ab19b8b67ec3e,0x000ccd3f8f88bf35,0x0000000000000000}, {0x000062e0d5c7f0b6,0x000dd34abff69676,0x0009b89962a6641c,0x0002be1c0add12e1,0x00014a078191a9f4,0x000c488cf972d9da,0x00090e9607f65fc7,0x000d5cdadd7da7e7,0x0001ca37f83b3584,0x000dd43c6df02d38,0x0000000000000000}}, {{0x0003f8ca58799292,0x000601d1cbef0700,0x000f41308b0cefb1,0x00090de4387a468e,0x00035f90ae8d18bb,0x000b356306c0a768,0x0005e167044866de,0x000114237a5a47dc,0x000143e3b4bbc084,0x000c1c6d0277c186,0x0000000000000000}, {0x000c81887bc12544,0x0006af4b6c2a8e8c,0x000ba5958fe82cbe,0x00067cd479340299,0x000d360f1809e7e6,0x000de77ee94fcc0f,0x0009d25d201341ff,0x000fac2af6e20977,0x000dfea19f8974a2,0x000fba7a5252c712,0x0000000000000001}}, {{0x0001e6367ded4905,0x000fd6fd8b41173a,0x0000c717ef3cdcf0,0x000608fdb3300d01,0x0000d527d7c8e07e,0x00039cd9ece69c0a,0x000677211bdaf48d,0x000b5d520c7fa557,0x000bf842692f3c61,0x000055814bffe31f,0x0000000000000001}, {0x000c94502a0e0f49,0x0000528193bb953d,0x000d7bdda5ab1a23,0x0007c4a219650b25,0x0000f78abb7ba4c6,0x000eb157bdb9dbe1,0x000ace6b3d0ff943,0x00048180c4dc1a32,0x0000124b69e9b36a,0x000da7fee72796eb,0x0000000000000001}}, {{0x000530dbdddc111e,0x0004131a0423e417,0x0002a2fcd4c890b5,0x000685a6ffdb8021,0x0001c68bcc7cf314,0x000fb29a153281e3,0x00090775f2e2a729,0x000fe4fc20716627,0x0005fa8915460a5d,0x000b7744dbded762,0x0000000000000001}, {0x00058330ded93a3e,0x0002ad9ca2943c52,0x00031d21ab8030d0,0x000fe30e76f64897,0x0002b30fd418c647,0x000815868a20f82e,0x00098d35bf8cbd5b,0x000facccde412b85,0x000358ff02bb4ec8,0x000fa54fb1673bc1,0x0000000000000001}}, {{0x000aed08c7bd3b0c,0x0004e546195fa3ed,0x000c31c13efbcb9e,0x000f2eaeb2cc8a6a,0x000a1912ca200483,0x000f0ff27a5ee60f,0x0000a7b9e9c56cff,0x00044977503cdac7,0x00064deabbda5a3e,0x00038efe3a9fcba5,0x0000000000000001}, {0x000821113784eeb7,0x000a12560a5e577e,0x000ae4b9aaf4ec38,0x0005c9a38358d926,0x000497b69c24b1cb,0x00007485410e5464,0x00026fb660a2d50c,0x000987263ee5a4c4,0x000b3ba20c286e0b,0x000ae54bed6c50f7,0x0000000000000000}}, }, {/* digit=92 [{1,2,3,..,}]*([2^368]*G) */ {{0x000e2418ebe8f2ee,0x000f4560bac026d4,0x00008c6a85ee3153,0x000c7d7d8e05a0fb,0x000d35867d053abe,0x000ebaaa06ca6918,0x00022207d8627f01,0x000fdfe74b9c6ea9,0x000478deb27dc332,0x0006b633ddba7b54,0x0000000000000000}, {0x000eb3b84da8ae44,0x000dced254321c2f,0x000ae0be12cbd92c,0x000b5fae91edd7e2,0x000adacef448565a,0x0003f288c1607c22,0x000ea8d01e22b70e,0x0004e3598c73a3ba,0x0009cd9f6c24e3c9,0x0007a5595791d3f8,0x0000000000000000}}, {{0x000cd049d3a9026e,0x000dbe859af0b3a1,0x000d9aa6b9632b70,0x00029dc483656cba,0x0007d02bc7ba1a52,0x000fc68a06574b48,0x000470a9518ff35f,0x000aaf20c720ad36,0x0003bb49ecf8b908,0x000f66f8b9d88aee,0x0000000000000001}, {0x0004ae92aaca41ff,0x0009e2ff799aa5c0,0x00048de6d0a352ca,0x0008f5f2eb0f3051,0x000fea98f1062e2b,0x000285eca4dfe726,0x00044d322419400c,0x0001441ba1f95272,0x000c0f6113ec0c84,0x000b67f7b093769a,0x0000000000000001}}, {{0x00010c16516e4d3c,0x000611e277c39f9f,0x00040673dd719aec,0x000e007e471514eb,0x0006cb0a884f04c5,0x0007cdfc977e1e7d,0x00096fd19b101b5e,0x0008b661589b4413,0x0006ee58455ad5da,0x00030384dfd6a666,0x0000000000000001}, {0x000dcee7cc09a195,0x000f049d8452fc3f,0x000453637f0d8b3f,0x0001dc43d12fc712,0x000f4b97aa7b885d,0x00030970db43c87b,0x000015eb8214e6b6,0x0006a5744b5ac5b8,0x0008d3fab8987808,0x0008438a227d82a5,0x0000000000000000}}, {{0x0002d58e6de7c70e,0x000a184fd2b399ce,0x000d46ffafde56a0,0x0003266443a772e3,0x0009e5e99ec73618,0x00068acc975a652a,0x000b99dda22ced10,0x000f17534159829e,0x000ab0176c94c616,0x000fbda334609df6,0x0000000000000001}, {0x000e586ebac6018e,0x000f2f03144a03f0,0x00070d82d13df49e,0x000fad35f054795a,0x000bfca4e83c93d4,0x000ccd2e817178dc,0x00006d906f96d5dd,0x000999860a4c0599,0x0007c4473b0cc898,0x0002a9c7a2422f0b,0x0000000000000001}}, {{0x0002b09542f251bc,0x000e9c6a4a88693c,0x000ca160d5142fa0,0x000a8912377d1615,0x000e8a6efbddaae6,0x000a4c058235658a,0x000f27a6a6dd7c56,0x00070769ea7bd61f,0x0006f5dde4e365fe,0x000d56d5c0ff87a3,0x0000000000000000}, {0x000ceae2e0074d51,0x0000c081ba44424f,0x000d9e0eec434166,0x000bbc85793c6ecf,0x0000cfdda19dc769,0x0009ff9b44e244b1,0x00055190f00a8e3e,0x000a30e6f1e94105,0x0002df24f630f9cd,0x000164028859bc1d,0x0000000000000001}}, {{0x00091d8b229586b3,0x00062d4212a9d0d7,0x000a44dcf82dea37,0x000886a8066a0e31,0x000c8d5c7f9428cd,0x000e7fa7c681f5e4,0x000db54aa6ccbecd,0x000e8442c468c6ab,0x000eb0d35eb4fd66,0x000ecc62bfda1f45,0x0000000000000000}, {0x00043fbb4e2cb5f4,0x000b78f0a96488d5,0x0000f4585ef033e7,0x000ccf9f3f7c9386,0x0002c56f736843a4,0x0003c2a98300d2f8,0x000d0e9651445c74,0x0006ad9774234178,0x000b0d7d2ff89fee,0x0002dc8f018f3a2c,0x0000000000000001}}, {{0x000a0b1e42fb1d75,0x0005875ba8ec633c,0x0009652adf59ccbb,0x000c9a8c4da98461,0x000058421fa35715,0x000861494cf70c21,0x0001a367a4a6e22b,0x000f1f29e364cf7f,0x0002eb8412063103,0x000046241f101761,0x0000000000000001}, {0x00035295fd113dfe,0x00087ca26d83dc56,0x00009b60485e1379,0x0006992ee53da791,0x0003f63e81d304b9,0x0005e83c82169ed5,0x000cdfc2181cd77e,0x0002864256eb4e4a,0x000dd24e836cab6d,0x0000560017a3ed5b,0x0000000000000000}}, {{0x0000d40ea7dbd218,0x0000bffd292d5f99,0x0000b3c033efe2aa,0x0003caf5350ffa07,0x00062cba18d05709,0x000de1ef348e77aa,0x00050628dcafce95,0x000654c13b978d30,0x0004b7581a218420,0x000aebc1eed7a302,0x0000000000000000}, {0x000467c3cff7787c,0x000cc65919f6e7d2,0x000e4ef4ee66f3a2,0x0005339dd95dc335,0x00083538624188b1,0x000c9f6ee9c47f71,0x000c2d00164075ad,0x0000fb8c9b9b8fc3,0x000ab425082f15ec,0x0003706da80b242c,0x0000000000000001}}, }, {/* digit=93 [{1,2,3,..,}]*([2^372]*G) */ {{0x000981c54aaf54da,0x000345cebb5e6933,0x000544b1b1632546,0x0001b01f84cafbc6,0x000115cddc181798,0x000378ad86aa1393,0x00075fe68cbb4941,0x0009588ce3ac7e26,0x000708d627f2694e,0x000a9deda381ddab,0x0000000000000001}, {0x000d5f56fe3c020f,0x00064c1a13df6f31,0x00002f2a54ccdb45,0x00018f47586ae362,0x000f6db9ebb1f191,0x000b71b6517fa3e3,0x000f8c282c695b00,0x000758306aa882ec,0x000bb71fac8a72bb,0x0005351671f4f924,0x0000000000000001}}, {{0x0008318350691a0c,0x000b269d0103c9cb,0x000bca486ca47a18,0x0001af062d151fe9,0x000e7c2bcd6c38a3,0x000a2dd4944c38da,0x000d5e2d0cab5f56,0x0001aaffb6b80e8d,0x000b4ab87f1aa045,0x000baad7ec926bd1,0x0000000000000000}, {0x0001499620b24214,0x0007f0d276179361,0x0005f42f5e14dbe6,0x000a3745bdaa4d19,0x000b02770c1ff9ae,0x00030746fe336a10,0x0005a19965986ef7,0x000598b61ae7500d,0x000c2b7c92c56a5b,0x0007c0f20ece26fb,0x0000000000000000}}, {{0x00087e69d72ded5b,0x000cbed0493c7849,0x00059557a83ba0a5,0x000cabc475bbdb17,0x0003d65e4a623f2a,0x00071fb7df8bf3c5,0x000f576c8eb2466d,0x0003c6d8140f7545,0x00002bd4e620a012,0x000cb967837a469f,0x0000000000000001}, {0x000871f9216cfc43,0x000a4dc25382488b,0x000ef93af7d4b3a3,0x0003ed77dbf730c3,0x000a6f764526ebfd,0x000b6152b407f935,0x00025711c016476c,0x0003dee3ad5a2bf3,0x00009ed5688aaec7,0x0007cb5a614fc9fb,0x0000000000000001}}, {{0x000d2983eb57fb01,0x0006f8090fc8d49a,0x00055cd8ed43313e,0x000063128651d168,0x0009d55315e356a9,0x0003731bdb591a91,0x00090f35172884d8,0x000ce2ac6b9b209c,0x000e9deccfbd125c,0x0004c67d19839d92,0x0000000000000000}, {0x0007835fb081749a,0x00038c29318405ed,0x000c88969fe7858c,0x000d9e6b39c13839,0x0001a193b85889e3,0x0000167b73a0e542,0x000e3a6c6ebad78e,0x000fea5061213cbb,0x000f99af7a8cbcf0,0x000934dbdf82d320,0x0000000000000001}}, {{0x000dd97cee516977,0x000fc49266fa93ba,0x000b3371de037896,0x000f3467c9ec4ba4,0x000bff13f9988671,0x000c0500963fcb88,0x0009447add0b56dd,0x0005dc495e382a32,0x000c531e8e3d8f13,0x0003f8ab53419d64,0x0000000000000001}, {0x0005999b06e01bce,0x0004ac4c86e9d1b3,0x0001acac55379f5c,0x000ed5f60cf793db,0x000deecc778efaf8,0x0005438ff64587a9,0x000da09df4f7f063,0x00095b550b56ea7d,0x000d4a2f2118371b,0x000897f5ee846337,0x0000000000000001}}, {{0x000e73c876ead4f8,0x000074f77e1ef006,0x00068e9d113a8d10,0x00068c4c79701512,0x000c8af63c9e4975,0x0001a355ba1ddb87,0x000a7f69e6cd38b6,0x0001a9ae068bd113,0x000bc3a633214952,0x000e40b4f3b0cfc9,0x0000000000000001}, {0x000dc3573f4bb5e4,0x000ce2ef087b7068,0x000ffeeffd386368,0x000053bd77e46931,0x0008c8fd63c43732,0x0009915ece7b6a54,0x0009d1980b122996,0x0000807d3a509f62,0x000abb80ee8c76fd,0x000ea6d20af82699,0x0000000000000001}}, {{0x00023cc70a1b7646,0x000fb2fea8f69076,0x00051b6f61d27313,0x00053b59960e18ea,0x0003b52c79117607,0x0003c4870ae1dead,0x000b0ba34bd1f16b,0x000eb6ec0bc7a291,0x000e48716fbdf694,0x000f3b9ceb0fbb83,0x0000000000000001}, {0x000f4df150c14682,0x0004d73e71ecfad2,0x0001f4eed11e2bf5,0x000e8f7ba0e6130a,0x000d0ee611881177,0x0004b3748fb1ee0f,0x00018bc0f1b2681f,0x000d95b14d7b81f4,0x0005715bb9df9123,0x00010458047bf5c1,0x0000000000000001}}, {{0x0007c0378bc40ed7,0x000325851811caa9,0x0000425fd5a042ad,0x00083181ae223e37,0x000dcf721e5a193b,0x000e3457f090e949,0x000bab83df6a8520,0x00045f22447cb654,0x0000dfbcc720ad35,0x00030064eddb51ec,0x0000000000000001}, {0x0007e2d48a4ebf78,0x00086d5a22dda9a9,0x0004ad7ed63a6603,0x000bdfd6f4eac86c,0x0006ea0b3cfe90e9,0x0009746e43f3d057,0x000247c38598edeb,0x00066c63f53c5a4f,0x0007de7ce9110d7d,0x000580edc5628f93,0x0000000000000001}}, }, {/* digit=94 [{1,2,3,..,}]*([2^376]*G) */ {{0x000ceb75a39240f6,0x000cd422d17ed307,0x000816d46db1d003,0x0000a452acb6fef8,0x000cb9bbe93acb00,0x000e7044e1a33425,0x000fc32d94105ed8,0x00077b448d72bf04,0x000527b278a8006d,0x0003f3ce1c27af77,0x0000000000000001}, {0x000e21a0404fea41,0x000ba2bea8a562ed,0x0007dcaa390fe905,0x000e3be58bd01814,0x00024ad37906a8c2,0x0004147c934bd6ba,0x0008700ab35993ee,0x0003eb32c19654b1,0x000e9fb6dc4b6283,0x000fffefce4982fd,0x0000000000000000}}, {{0x0008ddce89d919a0,0x000c8653953842cb,0x000510be22ec94ea,0x0004fc6818af52b2,0x000d36cd384c6520,0x0000918e38b08bd4,0x0008cd3bbca8f664,0x000f9b3d5866c2ac,0x00015b5a22e4fdae,0x00028fcebfa696bd,0x0000000000000001}, {0x00086becff5dbeff,0x0002b0a9f4f0a089,0x0002781857ab5bde,0x000f7d34f623a384,0x000ab2fc32d5df48,0x000357b29a5aed2e,0x0002a4f85d8000c3,0x000a47c091a8d7a0,0x0008c875883e2289,0x00004c78f3991d74,0x0000000000000000}}, {{0x0006929bd70c6394,0x00085f2018c22473,0x0004be72094183d0,0x00086c43b8504d5a,0x00086b6f18e21a1b,0x000ad297dd4ff469,0x0000f368a9142ac6,0x000e09fe86beaf09,0x0008c552b3b6921a,0x000bce953006e93c,0x0000000000000000}, {0x00072ac6e0006309,0x00015780956c6baf,0x000c4c2c5f7fa741,0x0001eba55e9870c9,0x00060f57cfca17ec,0x0006e490ccc10b4b,0x0008a9db0618cc6a,0x000131fe5f0039e9,0x000970dbcf0f5361,0x000700a442baa6b1,0x0000000000000001}}, {{0x0003ec842981eb23,0x0008fb16678799e5,0x000db8c26f2eb3f7,0x000307e41091298b,0x000c2265d3b22e09,0x000829161a79682b,0x00094108a62536ff,0x0002002fb6dedea9,0x00079fdbc3d369ec,0x0002baf58b2f20ca,0x0000000000000000}, {0x00056d9fea698757,0x00041a61419646f7,0x000308b017c99346,0x0002b76a5de627fc,0x000cb23ee7d29bea,0x000ab47900ba8603,0x00096bb85c794766,0x000df41684cc004b,0x0007656ed94d547e,0x000e302003142b8b,0x0000000000000000}}, {{0x0005cdf0222a69bc,0x0005e1e346fabbc8,0x000e07629de2b094,0x0005724f76a1e2b5,0x0006b43bc885c45e,0x000d1f53506f8c50,0x000458ec4a247aeb,0x000ee8c49a8e9759,0x000961f24ad9f81f,0x000c780789ce81ef,0x0000000000000000}, {0x000ac3a5a536c8ac,0x000fe30d120ebbbd,0x00029a29c912f38c,0x000d27e5470f8673,0x000f785f54b6aa93,0x00069bc2c6347ce7,0x00091c1681c6e838,0x00015f8951322402,0x00054c132d778a68,0x0009133565718293,0x0000000000000001}}, {{0x000f8e71a3d24acd,0x000de7f8ccaa4039,0x0004a565eb389f9f,0x0001445b3a88c7c8,0x000b1b88e20b6224,0x00022d8db00479b1,0x000369096695cdce,0x000d48a7013202fe,0x000e3713baba6a66,0x0009b65be868e0af,0x0000000000000000}, {0x00018718a6375d71,0x0003fe3e38b8c6c5,0x000ee16d3bd00a61,0x0001a73a8bab2dac,0x0001decd0dde75f5,0x0009a19d5d5d598b,0x0002f5dcc2ed8e1f,0x0007b66c768674ed,0x000717b781a03645,0x000cd5eb14d9fd45,0x0000000000000001}}, {{0x0009a4c40a33f00c,0x000d2d3bef2c63e1,0x000922215ae57c68,0x000763ee03e85348,0x000337a4a0d2cb54,0x00047d23204381fb,0x000be443d9712227,0x0007d96627f6c828,0x000fb6b5f6d1199b,0x000a433d2170b3ab,0x0000000000000001}, {0x0001d3366971bb69,0x0007a38c946a2ebb,0x000b29fb103a111d,0x00047d3675997def,0x000fd82824e10a96,0x00029d6d05a45fde,0x000500fa9b94f37f,0x0002317e08c1e35c,0x0006ed9214c60102,0x000ee0a2afcd4a2a,0x0000000000000001}}, {{0x0003291f02ce62ff,0x0005b8a731176ae1,0x00053e5b4c8c2f09,0x000d5a2322d8f01b,0x00092f09c90539b8,0x000c4c22646cfad1,0x0008df5016016f3a,0x0002500c56f4c2d4,0x0006618c9bed5731,0x000f52249d380720,0x0000000000000000}, {0x00052bb2164b93c6,0x00009ba854f0dba7,0x0002bd9fbffad821,0x0002cee339d0e928,0x000515cfc63fee61,0x0008541bf33aca9e,0x0001f0f0fd5f8231,0x0008dccc44f51df1,0x000e26d92e5d7f0f,0x000334dc204c43c8,0x0000000000000000}}, }, {/* digit=95 [{1,2,3,..,}]*([2^380]*G) */ {{0x000df775a4cea698,0x00057fa877dfb590,0x000f628f95d0e8c6,0x0004b622c58775b2,0x000e755966c521f9,0x000b826bcad94ba3,0x000585e536e18362,0x00056a8bf64e1429,0x000c0d065ab9cff4,0x000c6b7ad254f1fd,0x0000000000000001}, {0x000be22413e6824f,0x0009f5a869cd6010,0x000399cde94b5cc4,0x000c96f6029dfb84,0x00068c7d0822053b,0x0006cb5f4bf3d33d,0x00090bad70bd72fb,0x000c5f85b78281e7,0x000fbd3aad6b87dd,0x00067e9bddab2fd6,0x0000000000000000}}, {{0x000f0963f658551e,0x0002ea1215b91acf,0x000276c4b8c7ce3e,0x0002c599ae4d76fd,0x00006cf3a3b9f27c,0x00006667b3985a81,0x00095ab3dd5545f7,0x000e9ae8ea63e5bf,0x0008eb3015a494d9,0x00014b36df8e2aac,0x0000000000000000}, {0x0001e0605f96eb43,0x000d54ec384ae024,0x000bfb3e2ee19fc3,0x000c041bce0a2d7c,0x000b57e0aa0d1a5a,0x000f6adf1022b978,0x000452550508726c,0x000b77d6d81e1380,0x000536c9802fbac9,0x0007d16666d2c234,0x0000000000000000}}, {{0x000d75964c31ca58,0x0004e22c167fba0f,0x0006865896879fb3,0x00085f113d2ac14b,0x000fcf92650326bb,0x0009815c6ae567c4,0x000703330478f2d0,0x000c2d4e045bb2da,0x0004917027450186,0x0001cb3d6ff5bbeb,0x0000000000000000}, {0x0006aee5ed6230d6,0x0006f57fa7f974a9,0x000d445b19954b86,0x000cc41b7edd540d,0x0002f6672b9eada3,0x0005adb45c3c302e,0x00085355ea3de1bf,0x000a70efd3fa201f,0x0002e28049bc11d2,0x000a9e4d97e0553d,0x0000000000000000}}, {{0x0005aaa83e0b7193,0x000ef4020dd38cdb,0x0000a2db89cf16c4,0x0008b727a5cd426b,0x000baf5617c8e43e,0x00043d6e5823ddc0,0x000180e259e17f2b,0x000506737413c826,0x0004e741255f63ef,0x00009623e6163c43,0x0000000000000001}, {0x00095e5ae0c64c88,0x0006e547505a1996,0x00074ec16e26e1e3,0x0001814a43d8b0e2,0x0004c037ed439483,0x00075672e85b1a10,0x00064a05bc4b4563,0x0004f4e8604b9fdc,0x000d8d54cdb5b099,0x0008d7035e5850a1,0x0000000000000000}}, {{0x0006358cac1e1dd9,0x000326ae97ec9d6b,0x00096931bf3f89cd,0x0008a8a20db33ff8,0x000f15df6988b172,0x0009cd5efc8b413b,0x000bb187876052fc,0x0004662d8014980d,0x000d9235f7d44d41,0x000edff0c8921456,0x0000000000000000}, {0x0002553d46a6bdb6,0x000a25d43349dd7d,0x00098c5095dc275f,0x000e81697e9d6a23,0x00021486070955da,0x000de66e5e004d62,0x00061fc887538530,0x000b0cbeddeb407e,0x000968acbb1e576a,0x000ee36df6504685,0x0000000000000000}}, {{0x0001376b4df2834d,0x0009122c927fc01d,0x000cb3e3200f4b1b,0x00077db8d6a633a1,0x000324c991410544,0x0009a4d4ddbf0c1c,0x0004f89da008df0a,0x000df68e550730c0,0x000e5c51e1a10f51,0x0008da410315475c,0x0000000000000001}, {0x000c76b031581137,0x000f3f4ca12b9bde,0x0004e3a329753a8b,0x000499c86ef86a89,0x000c838a372fcc5a,0x000ec44e4a97d666,0x0000ea241b991236,0x0001650c8dbf9560,0x0007627fd4eb71cc,0x00078654f79c844c,0x0000000000000000}}, {{0x000ce7225c38fca0,0x000cf6f1a6e96969,0x0009cc6268e77785,0x000308efc7d8303c,0x0008a6b0e52762b8,0x0004bf9968cba9dc,0x000db7c416fd26fa,0x0000e7d932fa8c4c,0x0002063b5de7df0b,0x000a1bd8e36d9447,0x0000000000000000}, {0x0002f11b9d88f945,0x000b6a528d0c6d85,0x0000491c222e34eb,0x0005246f572cf3b4,0x000826a507a97323,0x00051b49545419c4,0x000f246a45d14681,0x0008555cac591e9f,0x00067c66c74cf909,0x000c814d10852a3f,0x0000000000000001}}, {{0x0004d6495109aae5,0x000c4b86a81e7f4d,0x0004316eb1054df2,0x0006877c19b90005,0x0007963ac12d941b,0x000bdc46a9dbe383,0x000befbe68280f87,0x00071d97d1dc04af,0x000aabbcc64f8fe9,0x0008543ef9d7ecfd,0x0000000000000001}, {0x00056ebb21998e32,0x000ab05f744a3f42,0x000c6587a4d462bb,0x000c14a18de305cc,0x00056d2c0e8c5f7c,0x0007f552fd1c2fa4,0x000165b93096db0d,0x0003eef9e935df5d,0x00013440e0a7d4ef,0x00020c2ecbc3b683,0x0000000000000000}}, }, {/* digit=96 [{1,2,3,..,}]*([2^384]*G) */ {{0x0003ac5243ed86b5,0x00075f9805e79dc4,0x0002bee2dfe95a21,0x000284b06125c31c,0x000a0103195082b6,0x000cedfa4a2264eb,0x000afa325bc143e8,0x000ae3ae24853199,0x000ebe96963067c6,0x00096c54a7cecdeb,0x0000000000000000}, {0x000e3a5229434e36,0x00055f3a1a50446d,0x000644f2db4f7215,0x000ad43f6dc38924,0x0002239beb126b72,0x000840de05e7dd77,0x0002862d6caacd0d,0x000bce6fa639c67a,0x000087602ba53021,0x000679ec9b598271,0x0000000000000000}}, {{0x0005ed4dab9a7e9f,0x0006797aaab2f5b7,0x000301593051ee37,0x000962a30b02f44a,0x000a1d622cf13021,0x000a7dfa0555a3ee,0x0006aca4fcd685c9,0x000ad2e750777a2a,0x0006aa905bd4c914,0x0008ffeec52d7b1e,0x0000000000000001}, {0x00095204a3f6fa1e,0x000c34539f85e4fa,0x000e8ddc16e36eee,0x00044a9e74599d1c,0x0007ab343c6c5502,0x00007951ae714c01,0x0005c8c4503f92db,0x0006830499e544d1,0x000188a7b94680ff,0x000147d6c4809fe7,0x0000000000000000}}, {{0x000e6ff25ab97af1,0x000ec754ac7f57b5,0x000607a92403e802,0x0000eca9aece9592,0x00080834b57b8bd9,0x000e2fcd37a127de,0x000ed63155d3ec1e,0x000f99b11a3b9b54,0x000db302a147172f,0x0005d9290b10d36a,0x0000000000000000}, {0x000eee6089f16e1a,0x000772f210e83cea,0x0002496230bbfc3c,0x000c1fbbcea01caa,0x00032cc99a5937d0,0x00074603f91be511,0x0003cfecb00c641e,0x000ef833255bc0f0,0x00085cab2f6311c8,0x000c7fcc61e9c871,0x0000000000000000}}, {{0x000f147189a2546b,0x00070bf89fcfd41b,0x000a403ed89c0790,0x0003f861a107b324,0x0009b4dade6e318c,0x00032b6327665e9f,0x00016ecb408e3b33,0x000c11ee2181f62f,0x000ba590467bbd1b,0x000a0f4b5440b9d0,0x0000000000000001}, {0x000b1aa7ade86660,0x000d1a8a32a33d9c,0x0009ae722d5edb96,0x0004c7770654bd1b,0x0001d03d0e5a5166,0x000b01ee816a4a63,0x00015843d1d9344f,0x000c1e1821b3c769,0x000c22520be2d285,0x000fe7e0834d6faf,0x0000000000000001}}, {{0x000a30d8168852db,0x0007853d06621fd0,0x0000e561a31ba03d,0x000e2351f7abbee6,0x000bfa802185d2d6,0x000a8cb11d19a8eb,0x000b4f2b7623f602,0x000f149b3db4a55d,0x000399a66e1d6eee,0x000dded7de613b1a,0x0000000000000000}, {0x000694da4aed0861,0x00013409999d11ea,0x00021cefe8e175cf,0x000ca47b4e5a0420,0x0008274d934ac552,0x000e270720e741b5,0x0003c0a8bd69787c,0x000e75f9cc756f74,0x0003e654e1ea2208,0x00040979701ca5a9,0x0000000000000000}}, {{0x000d12f4d256a679,0x000fb6f240706408,0x0001c6799f2d7255,0x0002b1c7ad7d86d9,0x000c6259fb2898c3,0x000dc9f2eb172083,0x000f61ec85a5a26c,0x0002303eee79dca9,0x0003cc24582cff2b,0x000018aea38a1c28,0x0000000000000001}, {0x000fee514ac3447b,0x00004db0b385f6f7,0x000785b0f880a482,0x0006256aaff858dd,0x0005224f69e65ae6,0x00099c8d9092f5e3,0x000a4d5b2e1cceee,0x00065201f6ee40cf,0x000abc908fefbb83,0x000f4461f21689bc,0x0000000000000000}}, {{0x0006ba04a3b21865,0x000b257a4daf424e,0x000a3bec5e4ad4b6,0x0001bf9b577cca5f,0x000e764bad272e02,0x0003f73ae3883e3d,0x00078df5e21be44c,0x00046e6d9107b020,0x00009a9e8ecf5414,0x00062dbf7ce0cbdd,0x0000000000000001}, {0x000ed268a93dd876,0x0001345efa0e6741,0x000a124edec5cb04,0x0002301ceb5830ec,0x000c074b8d138854,0x0003717a195a4b92,0x00078d388cdf3e4c,0x000aa6e0172f6f1a,0x000474fe593756f7,0x00063e14f10ad2f4,0x0000000000000000}}, {{0x00056d8ef5183d33,0x0006d4aef07505d7,0x000fd1d5c09dd4c2,0x00026645b43bb4e7,0x000876a817eb253c,0x000209c32af92f54,0x00083a63e205a086,0x000d802502f8b9b8,0x00069b5a7a6f9cb8,0x000e8d87089ec121,0x0000000000000000}, {0x000c2981d5c3f78b,0x000fd7c0b6dcff4c,0x000e2051e1d39135,0x00056f990f800ca1,0x000bbae12c766764,0x000fc5fcbf987a86,0x000db02cbf344cfd,0x000965a4f55ea853,0x000d8cf4b24b115f,0x000ddb28cffa2bf4,0x0000000000000000}}, }, {/* digit=97 [{1,2,3,..,}]*([2^388]*G) */ {{0x0004c9f1b01bbcb1,0x0008c564ba5d43cd,0x000b6d345ac26289,0x000156220f11b91d,0x000dcfa53c395f80,0x000e8f0647eb32e3,0x00071de125c49a24,0x00035c7837015374,0x000bc6a877a9741e,0x000a3e1c5d3aa600,0x0000000000000000}, {0x000eae31d5cbf2fb,0x000ff21336f73218,0x00063097ec47555d,0x000e41ac8f16a8d5,0x00010c063790a928,0x000842e2a872cf72,0x000d214bed4668e2,0x000e7b5aab91e7f0,0x0002089cbbd94783,0x000d7755df6f3c47,0x0000000000000000}}, {{0x000c45be80c5ceff,0x0008b5f3a736f81d,0x000f684853db7b94,0x0007af37a1d8a120,0x000c1e37602997de,0x0001ba866cadb401,0x000496a24e3e6caa,0x0002c3eae9d6cd94,0x00074e14e06f82a8,0x000343069d99834a,0x0000000000000001}, {0x00060baf525e3e5c,0x000adc3855bae42a,0x00020017824fbb6a,0x000d2439950ab7cd,0x0001396b971049df,0x000925d16b65cd1e,0x0000815f2ec4dd14,0x00099059e2e1d82c,0x0007231633ba03a7,0x000c17f35a3c602f,0x0000000000000000}}, {{0x0005cd392892c72b,0x000067c79588a466,0x0003e61043554996,0x000e4fea3dc40ec6,0x0006245b592ed7ab,0x000d5fddb91366af,0x0005bcef5cf9183d,0x0006f2afe7d93c79,0x00038f789bd81e98,0x000a24ae25969d23,0x0000000000000000}, {0x00015df628bff28b,0x0008b0238f67e086,0x000debae13d569b1,0x000537b081c52561,0x000e3e637e8d5f7e,0x0000b558a9b4dba0,0x00092e9e6c338cb1,0x00054c7742924ded,0x0001b877e357069a,0x00077dfb12df7675,0x0000000000000000}}, {{0x000eac10daa6fc06,0x000a451d0d93fa05,0x00030dbe3663fb80,0x0003df5569a67246,0x000583a7b7740137,0x000a1bf5763b688d,0x00007976f4ce0d19,0x000972348a80c203,0x000296b9dd874e74,0x000ad726fc872424,0x0000000000000001}, {0x000626a33acca649,0x00019c0b206a34a4,0x000597e1cfe661fc,0x000915e61f98c11b,0x0006400c41adb010,0x000ed21859bdcb2d,0x000247507de82c2f,0x0007ba1295daeffa,0x0000842d673a4f29,0x0001721fc083b457,0x0000000000000000}}, {{0x00034490e59e8714,0x0004db94a827c594,0x000be5c43f7b8f49,0x0005c1ed99f38332,0x000c89e5a5eae6d0,0x0007a328c3f873b0,0x000b195eb0205cc5,0x000957c8e1b9bcde,0x000a9c05764ec15f,0x0003785ee6082c58,0x0000000000000000}, {0x0006efc5f7d22a96,0x000c221343eb9e1a,0x000752365f225594,0x00006ed92aaffd4a,0x00047b4ac0a51a79,0x00034752a1b444db,0x0000b01d86935b36,0x000ff91905b43171,0x000a16a9f33a34ae,0x00098febd2ea9993,0x0000000000000000}}, {{0x0009425bd3be24b1,0x000ddf604bb70186,0x00004732993f7d31,0x0003e481243d40e7,0x000cdd085631cbfd,0x00020a779443a447,0x0005a3d17a4bd6e9,0x000c2ba013a6f159,0x000091ba40454351,0x000bd45892d66dc6,0x0000000000000000}, {0x000413e025588ac6,0x0006b5fdc28cccb3,0x0001b7df9aa499d4,0x000dec43b5bc5fae,0x00066d0478edbc5a,0x000c5c7523db595f,0x000f66c3689cc921,0x000369286e3460ae,0x0009f5650aae055f,0x000ecf05c2d82ed3,0x0000000000000001}}, {{0x0002dc4c335595b5,0x00087d3146806d12,0x000280502c85e0da,0x0006080ca34c63d6,0x00057bee19e4fbfb,0x000b329c24618627,0x00059c63cee44932,0x000729a1018b673d,0x00038096ab196705,0x0008deabcefcd004,0x0000000000000000}, {0x0008d702c45db29c,0x000164a83c7ff2f7,0x00004bdcc8d9c10d,0x0006a51badde1985,0x0007b3d628a8f0d9,0x000238514e884060,0x0003ad2af9123d94,0x0001c02c79997897,0x000547f0e64e4ad3,0x0009546706bd2921,0x0000000000000000}}, {{0x000474c793f4e626,0x0001b9f27eccc505,0x0004061bf3c9bbd8,0x000776661385eed6,0x000ca2d5cbcfee54,0x000b0a8618a0f415,0x000c45418675f88a,0x000e0d5df7ae47e7,0x000f8808275324e3,0x0005bfe818ccf0e2,0x0000000000000000}, {0x000d8f452acbfbda,0x000031ef224de6c2,0x00070dcb7f79ce12,0x00097b18d958660b,0x000224dfd1c89c45,0x000d69ce10da0fa5,0x0001b65989afa822,0x00094e1b3fa146e8,0x0002ae217dcac503,0x0006327d3eef4183,0x0000000000000000}}, }, {/* digit=98 [{1,2,3,..,}]*([2^392]*G) */ {{0x000f424e1d9c6487,0x0001fab2d1847091,0x000c18abe11482b3,0x00002a204548d244,0x000d2901117bfc9e,0x00086c34a4b1dc1c,0x00025a48ee98a6d2,0x000cb76b3ae604c3,0x0001c8298db518ae,0x00008fb7194b2498,0x0000000000000001}, {0x000055d976a5cca1,0x000a2cc7061a3bfd,0x0005a667bf88a107,0x00028dc3af0a63ac,0x000873e8641fb210,0x00040a558da80d94,0x000fc0963f8d8c7d,0x0009ccc465473acc,0x0005ce362fbd5307,0x00081d15006f15e8,0x0000000000000001}}, {{0x00022141cc3287fc,0x00038266149a76c1,0x000fdcc4f6ec602d,0x000673e316b23844,0x0002f7ff0591cea0,0x000226449753082d,0x0008c9cafeaf6b58,0x000801a84f6bca52,0x000738672e240363,0x0000fb54c4174c43,0x0000000000000000}, {0x00005f340ab8f558,0x0003c50b6de62a42,0x000c67ea2a5a8485,0x000584f292e0d583,0x000976bb7a441296,0x000e6eb31fa9f0cd,0x0005886d0d33dfac,0x0005ca9b5dbb850b,0x0003bbd95e75a3fb,0x000aa9fc35ee4214,0x0000000000000000}}, {{0x00048296df946f82,0x000d1ae0f7178948,0x0009fea01e8f3835,0x00032c83af761a04,0x000c81060dc76c7d,0x00037519156c5ff4,0x000bd4aec6a8a45c,0x000cdf6166cd6f1d,0x00042edd4a64bcec,0x00087353c4d352a9,0x0000000000000000}, {0x0007c5d100fac674,0x000db9e757c12a95,0x0005aae530260819,0x00099d6efbc64c70,0x00069b00bbd4972a,0x0000b755c13bf68d,0x000c9bf125fdc71f,0x0002e7e830894502,0x000fe09937e20c9f,0x00002b5fa7bc0dae,0x0000000000000000}}, {{0x0006f3e4a3b653b6,0x000d1a688f6e0a4c,0x0009e0c6a622a9b6,0x00092759febdd4b3,0x0007de14d66ca7fb,0x000a2edb8e3d698e,0x0001ab808ea4d110,0x00080f85570610b2,0x0004c29e8f8405b0,0x00027dadf7ff6310,0x0000000000000001}, {0x00057c2f52f741db,0x0008e2e671ed8847,0x000d5288875b3801,0x000d96a8629331d9,0x0005a7e602196279,0x0001f2dc09559eca,0x0008fe5f274c1468,0x0006483d04249681,0x000f5286b1c8246f,0x00077944ba105276,0x0000000000000001}}, {{0x00065afeabf73b11,0x0008c74def9ab376,0x00022e8ebbf2f73b,0x000cbc3cc29566a6,0x000e491e3c34a56e,0x0005e3e30062fb22,0x0008f34bd61c9faa,0x0006ad9002a6b766,0x0001e57f55fbc947,0x00052212e9e41cf0,0x0000000000000001}, {0x0000895f7a4eff76,0x00077650f0c0269a,0x000b638552f2435d,0x000cabbe1734cb6d,0x000ac1912708cc1d,0x00051cb37cd08219,0x0002a65eea8444e1,0x000bbf996f86f52b,0x000fc6bb767f7430,0x000d61b13f4e2c8e,0x0000000000000001}}, {{0x000d5ccc9d50240d,0x00084d2e5496b2b0,0x000f884405e473c3,0x00057903c51b5ae8,0x000d55afcc0675e0,0x000125af4b250a76,0x000937bc2b1d7e99,0x000a633470b9206a,0x0000cfe28137ad4e,0x0002cd8906210714,0x0000000000000000}, {0x000877153680ec3c,0x00019913626b5dae,0x000bd89f532b2d72,0x000d578470af1c82,0x000b3f975bb94d7b,0x000f53a6076b8092,0x000db22bb5b744d5,0x000f43f924c34cb2,0x0006114e078b5812,0x000fb3e3de49501e,0x0000000000000000}}, {{0x00028536905d5e34,0x00092fdd83e93bc7,0x0001a64b28a1f75a,0x000a170fe5a66cb3,0x0001e6a59754016b,0x000c5178f6263ade,0x000bc78f0892f5d7,0x0002723285c0f5f3,0x000ce420f8de3807,0x0004c264b36ac9d2,0x0000000000000001}, {0x000334fb73061393,0x000f6bbeabea50b7,0x000a60e0b4b57374,0x000565e15377dc7c,0x000ef0ff94b0e964,0x000e47e49a96f0ea,0x00030ac68d3dc2bc,0x0009347ee5d6453c,0x000eac1f6901d599,0x000086abf91bda19,0x0000000000000000}}, {{0x000d441660f7e89b,0x0004d20a8f4b5442,0x000f7bf31e592476,0x0002835026e4af60,0x000359fc53bdf7be,0x00012726ea080568,0x00075b1726e147ea,0x0001ca2a0207d5e1,0x000322cae833e591,0x000e936cba51a14d,0x0000000000000001}, {0x000a1d6534e7b937,0x00065ce0948dd2da,0x0002f88e2acca2b5,0x00091e6c94ccb3a4,0x000c7d8fe477585d,0x000807f46db59ceb,0x000b940f42378210,0x000e402ecff0fc9e,0x0007bc598d173f94,0x000f16af975145bf,0x0000000000000001}}, }, {/* digit=99 [{1,2,3,..,}]*([2^396]*G) */ {{0x000942a4c75e9fe7,0x000c673dad29e115,0x000e6be55a2350de,0x00045659ca3c399f,0x0003c87e22652712,0x000bd4c4458f51c6,0x00057db758ae1a11,0x000c547db810319b,0x000c8ba847d5c89d,0x000239959a5bbe62,0x0000000000000001}, {0x0003d490f3876f02,0x000521482b690e8c,0x00083aada0850d48,0x0004a53582c13331,0x0007bae5a342545c,0x0001c50d6f31c146,0x000d97c2d093b815,0x000e82d6fbdb84a7,0x00053468edb41ffb,0x0009e6ae0e9fad49,0x0000000000000000}}, {{0x00060773f6c223a7,0x000ee1e8255739aa,0x000672547b158459,0x0000639d3f4e65fb,0x000635059b89e003,0x000ffb7b9ac29a4f,0x000cad3267e18233,0x000a7f7d6bbb6854,0x000d91b6e79c3b99,0x00065ebec22c4720,0x0000000000000000}, {0x0002fbb0f6be8071,0x0006dc307d9b73d7,0x000c6fa2f527f8c4,0x000e537cfbf3d06f,0x00018d7888122d62,0x0001ea61a84ebd38,0x0005532479a6f831,0x0004a4bf3325eafa,0x000717809c7a3155,0x0000399520a8095a,0x0000000000000001}}, {{0x000b807898f2ae67,0x000d7e4f60fc8927,0x000bd2ecac1c97bb,0x00075b365b008578,0x000f53b54d53eaaf,0x000e5a0ab86540b6,0x00009c6ac54c1d9c,0x000267e6b65d52d9,0x000a061126607ea0,0x00011c0a94e0f97e,0x0000000000000000}, {0x000dd52c7077ac64,0x000e6849bb24e97f,0x000e60101c7fc9b8,0x000e52f0dcbe3ce9,0x000023c779930c2a,0x00050df58185f016,0x000a6864a7c2cfea,0x000d52f720dc8c89,0x0006aecf1e2d3b3f,0x000fe51ac6cabd56,0x0000000000000000}}, {{0x0002f47341f417ba,0x000cd8bb740324e4,0x000e45bfed89909b,0x00089a7fe9550616,0x000b7861f9828778,0x0008946a71446a53,0x0006502fbe6cdbfc,0x000f70373dcf7291,0x000b59a0e59c8ba5,0x0004ed07606ee31a,0x0000000000000001}, {0x0003f237a7cf7e71,0x000f61b5ddd50efa,0x00056f3a63a0f211,0x0004dae68319e664,0x00090e5acc6a3312,0x000d6c5fe3f2c7d0,0x0005f435cc8df625,0x000420f4229fa016,0x0009c92c95adf8ff,0x000c03d951affc2e,0x0000000000000000}}, {{0x0008e856f1a63237,0x000c38cfb4864e09,0x000a9b6c8ef2a48d,0x000565ee070c9954,0x000b247d25c31c3e,0x000d383653eec5d7,0x00033815ac0ce45d,0x0001d40035f31f5f,0x00016fd77486c728,0x0002145bbe546eb5,0x0000000000000000}, {0x000f8a00f9535f58,0x0006793f432f2f0d,0x000a22b5ed0740ff,0x00046e71ff907935,0x0006ed013a6683d4,0x0006c4dc5feeee1f,0x000e49d371167831,0x000c07fabe848ed6,0x000dbccd8d710493,0x0003939263e99e29,0x0000000000000001}}, {{0x0009123d0b7caf2a,0x00010c9813e058eb,0x000b14ecd8d170c4,0x000aafb543a445ef,0x00066b13251ba12c,0x000a58ee44692c76,0x0009f4193734f736,0x000a0ff39b6d1ecf,0x00049d16c582e2c3,0x000a54bc874e11dd,0x0000000000000000}, {0x00086c1422f1debe,0x000be6be161bed99,0x00094c11992adb85,0x0007d02a974392b1,0x000dc1355dd0b472,0x00001779ff9ef84f,0x0008dc1dbbcd1c30,0x0007615360f70921,0x000cd90cece2bff5,0x000a085b2b4772a1,0x0000000000000000}}, {{0x000bac8ffc9b1cbb,0x00041fbeb1c7a5f9,0x00032bb744d70f6e,0x0006377a1f50a7aa,0x00008611c61b42a6,0x000ce936f3324a60,0x000a084c3dc201c1,0x0002b70db700c5bc,0x000f0caf347988c8,0x00025e2dfe3675fe,0x0000000000000001}, {0x000fee427e9f9424,0x00069a165d8d1c76,0x000dc1fbe1e937f2,0x000db180dfee35cc,0x000b55475d4c9745,0x00036d0a2fefc6cd,0x000476726ccd4e8b,0x000f3783e580f7ab,0x0005d079b31ff3c1,0x00009ced18ab19ce,0x0000000000000001}}, {{0x0000806a0ffa1183,0x000b368c8ad93735,0x00045322006bc207,0x000356cef3feb2a7,0x0000d9772041b29b,0x00015326534db436,0x000c3a4ffd400337,0x0004525bb0cb62b4,0x0003dfc1aef8cba9,0x00023c5f95e7e7b2,0x0000000000000001}, {0x0009f0d5faafe7a7,0x00079f056236883a,0x000e0f2e02fe7ca4,0x00020a75821e669e,0x000fc3208dc12d93,0x000c95bd4d2a90f1,0x000127ab836d5d0a,0x0006a56f1f5b0f15,0x00053533b35a8c80,0x000e1db5d6ee484b,0x0000000000000000}}, }, {/* digit=100 [{1,2,3,..,}]*([2^400]*G) */ {{0x000b291af321cc48,0x0000d263480c29b1,0x000ec9060276afae,0x000489d0d90afac7,0x000ec62d3da37067,0x00088f38b3e31b78,0x0007f35ff5fafe7d,0x0007885361013dfa,0x000270f897a6237d,0x000c2a42a2eac980,0x0000000000000000}, {0x000b6527c69198d0,0x0008c038b2196095,0x00056c8573aab3e2,0x000c299349dbf002,0x0009c016fc238b06,0x000c26c63dc550c5,0x000712822cb43957,0x00044a5765b7d6c8,0x0000be87f42f34ea,0x00061a9436ed5036,0x0000000000000000}}, {{0x0006c0f3c9200410,0x000c1523b6d0c7cf,0x000b2a524b701323,0x00080e1d445c4f05,0x000cfb721bd24fb2,0x0004d74f5043a450,0x000c3ca459a36903,0x0001f8a997769ed3,0x0004569349bd35cd,0x000fa7a1b94559af,0x0000000000000000}, {0x000479e9fda50d86,0x00039193e5dd5ac7,0x000fcfc382ffdaf1,0x0006e937727251e2,0x000819f976e0e477,0x000e0dea37faf936,0x0002b3218ec38c97,0x00020308bb264566,0x000441534d581e3f,0x000046c275dc071a,0x0000000000000001}}, {{0x000cb5968e20ed2c,0x000a52702c5bb89b,0x00033f897addfb47,0x000f030ce16c51a7,0x000945e8bc092078,0x0000a224a9b9a4c1,0x00074fb0d2a2dbea,0x000a00b01506244c,0x000403180ef3b3ed,0x0000d544f09c72f4,0x0000000000000001}, {0x0007f0289c261b7e,0x000d803c0211ff4a,0x0001ffe93b188323,0x000b503181a127a4,0x000960bd651117de,0x000f238b1565ffd2,0x000706280cef133f,0x0004ddb33d18643d,0x00057a46393ccc6e,0x00011d1fcc4678c9,0x0000000000000001}}, {{0x000cb18067eb6c9c,0x000904e0e232321c,0x000c2c362eb5eae4,0x0004f20ada675b34,0x0009513d2fa912c1,0x000c8c7ff960f4ae,0x000ea3278df20646,0x0004b702cc146790,0x000b87bb57608da3,0x000f1fadae0fb9e2,0x0000000000000001}, {0x0006a843b0ca7a84,0x000ffac89f77d5a2,0x000265d14c35a368,0x000486e7957c89a9,0x000f9514b7e05bd1,0x00037cf3d5a9030e,0x0002008b9ea39985,0x00050c45cfba4fb3,0x0008d5a1561ff956,0x000bc01cc6a56407,0x0000000000000001}}, {{0x0005bb52ea9ac7ec,0x000e28f7ce0ec366,0x0004c059fd569d2f,0x0000e89276b354dc,0x00013674b639e129,0x00051c92206d8283,0x0005fd8d62852509,0x00083a0ba16eee81,0x00023ff408ee3851,0x000e736678fced53,0x0000000000000001}, {0x000a8b28dba67d24,0x000216ba84ecb673,0x00034998afbbd048,0x0004e06cfb264967,0x00064c024c958fcd,0x000c3e07fdd668c7,0x000e902ee5004559,0x000c7be484240ea9,0x00085d1cbdf78504,0x00001fc315ffe9b1,0x0000000000000000}}, {{0x0003f67e6d554604,0x000a7edbdf25d6db,0x0004a86faf823503,0x000561d458cbd82a,0x000fd50ad1fb2727,0x000d57e2f00994b8,0x0006a571b2b47251,0x00025dcba3cd1573,0x0003351634df5819,0x000f90f716e579ec,0x0000000000000001}, {0x00015c741fd15e62,0x000782e4509eb436,0x000bb1dede8ef754,0x000e32d87a793f6d,0x000cb27d972fea02,0x0000af4ace00b65e,0x000665980ede0c9d,0x000f6c809dcb9681,0x0003f6f1f979a653,0x000fa70638c8e694,0x0000000000000001}}, {{0x00069573569a82f9,0x00074c79907894c3,0x000923a4f546a942,0x0003c148a698895f,0x000c357afe3d1621,0x0000597be114eca3,0x0008bde57638ac14,0x000ab1f30c4d2325,0x000c1e648b9d09ce,0x000b5b544e3974e2,0x0000000000000000}, {0x000a45f392d296b8,0x0008740111ad4028,0x000c3e262fdbe28f,0x000c3453830a9ee4,0x000ae0fdaa4f4e3c,0x000db8b9c8044def,0x000827b06665f64c,0x0004b0bfa5e94a06,0x000288ab3926f336,0x00095cd9d3c3ecaf,0x0000000000000000}}, {{0x000b181f2f210670,0x0009ac047db30c5e,0x000f0b9977abb73f,0x000685fec5355db3,0x000cba356655da26,0x00050bb7fd48c1a2,0x000094ac2c2dc459,0x0002437ff8a8e766,0x00026425d80146ca,0x000d215b7aafe50b,0x0000000000000001}, {0x0008a54b77260e44,0x000200683c3c461c,0x000806c758fee244,0x000ee02fb90af5d8,0x0005167ac6f6571d,0x000f1dfed253aeab,0x00051fc762d73380,0x000f059d556559bf,0x0001430491432973,0x00077ebf133e93a9,0x0000000000000001}}, }, {/* digit=101 [{1,2,3,..,}]*([2^404]*G) */ {{0x0002ff226442343f,0x000cd833f176501e,0x00095759918597f6,0x0008de415f1a7fb7,0x000e4316d41dcb51,0x00029d89c6966644,0x000513d7775eaca8,0x000a9d45da4eed7a,0x0002852aadd14ef8,0x00062ec016fff623,0x0000000000000001}, {0x00091f95c7b230dd,0x000a732cc46d0d07,0x00004775f23d4641,0x000d9d15b9dcdfdd,0x0007a727ace99c9b,0x00077fe3e5aec6f6,0x00023beeac1ee2fa,0x00008f21d63275b9,0x00065885355852cf,0x000ce1be6d4550b6,0x0000000000000000}}, {{0x0006e321251c61dc,0x0002560a1fff242c,0x000a45d55894b5a6,0x000bc8f1bc1ece0d,0x00099655945af852,0x00081d51a6f4152e,0x00048184573b7d9f,0x000f69e42e8015c7,0x000b2c20669dba53,0x000e9f9624512355,0x0000000000000000}, {0x000c96019553b866,0x000abe8a5146d011,0x0006c8e83c7c8d9f,0x000d33f93fede45c,0x0006fb87d2fad3d5,0x0007a48456e1fe30,0x000e6e9f030c2436,0x000ab8f59e2c2aa7,0x000e2ecee8097392,0x000ce7dbed7e8f7a,0x0000000000000001}}, {{0x0009869c0eb3066b,0x000607798fe984da,0x000507796822415b,0x000b35e4cf4e7bb0,0x00043514e2eac3dd,0x0006f5f2ec73d5e0,0x00073c55dac4fc5a,0x00009ae9d9b66b29,0x000e7849157dbfd1,0x000a5482a9437d4b,0x0000000000000001}, {0x000c4e943ae95512,0x0006cf652253cdb5,0x000d6ec12d70a741,0x000569eacfb8355d,0x000eedc557ace0f2,0x00079ed65a726737,0x000cbaa427929f79,0x000f9f7b12d69985,0x000f61768135719d,0x000ae5a402492b60,0x0000000000000001}}, {{0x000feaf2d1e3892c,0x000ab68c7ed96e8e,0x0003cb959b9f3e2f,0x000c2e34fe65989c,0x00089b397dfd24ce,0x0005a4f7a72a8210,0x0003d4d194fcfc29,0x0004009eac36cd18,0x0004df54ac2005f3,0x00037ac4355ce338,0x0000000000000000}, {0x00018f15a5288002,0x00084aab158f0c62,0x000919d3c1cc9db6,0x000c654f22157c5c,0x00061a5d7e7c5733,0x000dc89cd41bb67f,0x00046690cac1f786,0x000f2b55f183f6e7,0x000f41e4cb445fa4,0x0005a969c4dd429d,0x0000000000000000}}, {{0x000f3df64800b6f3,0x000d7480b73133bc,0x000b600425660d57,0x000b837e3aef4df6,0x0005fb5d2c2dd02d,0x00011fe018b03d5a,0x000c71322317085a,0x000d374ad3a452d3,0x000a4d81aa830346,0x0004a3299709ce7b,0x0000000000000001}, {0x00016776ed8701be,0x0009a6af0a211f00,0x000ee5799e2d0b99,0x0004ffaa89dc73ac,0x0005974371ca9e1e,0x000e0cc77bcb98c1,0x000c6b4ceea4b327,0x000a8308bd6b7617,0x000c8a4f2fabfb14,0x0006930491f45b7a,0x0000000000000000}}, {{0x000d9bdcbcf79471,0x00074d3dd4ca53d8,0x0001af7d8d51306c,0x000b82f03e680d58,0x000a7884ca0be9c6,0x000c62e3720aacdb,0x000ad9ad633f5955,0x0000c84d067a1c4c,0x000e24eee54e3c55,0x00019dbe3f67b54f,0x0000000000000001}, {0x00099b839c026b9e,0x000bc7d75cb7b6b9,0x0005e6b4aa8a5275,0x000156cdfaa9f40a,0x0004a1992d1c2e6b,0x000b18092816e51f,0x00027a900c94afd0,0x00010f9d0fb16b34,0x0008f98b409eefa5,0x000aaed3cae46309,0x0000000000000001}}, {{0x00060d5e996dc11b,0x000619082845b56f,0x0006ef36f7ab0ecb,0x000d028f81fdfa6c,0x000060da295844af,0x0009596e31cc9ebb,0x000308c32eb79211,0x0001ea951754105b,0x00008750f063690e,0x00083b8a021ee964,0x0000000000000001}, {0x000d813e43ebc1f3,0x000af78ecca7ac06,0x000d8eb52a4c2d59,0x00067d3099d75877,0x0005b00d48668cb3,0x0002755481aaf570,0x0000b8ddd277a751,0x000dd4573c6cfa3c,0x00075e83624bf68a,0x000ee89ee03e9ce2,0x0000000000000001}}, {{0x0001adc31d17fe65,0x000ba5bb3a93b688,0x000b603dd9e8ce1c,0x0008b0cf4f5b70c1,0x000175f958dd3aed,0x00070f44e15eae25,0x000177aa5b942f5b,0x000302efb949c526,0x0002ba3a2c8dd115,0x000b89f9288a9513,0x0000000000000001}, {0x0005972ebede20db,0x0005b1bc841aedc4,0x000933a99b87853d,0x000597276e1536aa,0x000a0238abf3c852,0x000485ab1105488f,0x0006d521debe07d8,0x0002f1ad18f16d6f,0x000d3c55a54637f9,0x000804a2b58773df,0x0000000000000000}}, }, {/* digit=102 [{1,2,3,..,}]*([2^408]*G) */ {{0x00085142795b0fc9,0x00032b75a8973a1f,0x000125d27c2f65e5,0x000245efb7e6ca7e,0x000a3d37a1c1d680,0x0008ed8871c0ac3f,0x000f92273ed1f61c,0x000f1c0619b125a3,0x000c151e1baaf99b,0x000b5fb9c92ca12f,0x0000000000000001}, {0x000d45f1302c2800,0x00028a46eca65c4c,0x000181d940c2f16b,0x00008156dae561c3,0x000ffdb51b5dbdef,0x0007d0f3f05aff9f,0x000216756731470d,0x000d3e4323b09f64,0x000c256f1c5c736f,0x000c46af757ebac2,0x0000000000000000}}, {{0x0008b99d3a5cf086,0x000a6f7dad9f189d,0x0009613956296f2e,0x00029ebaf5d410b4,0x000d4c6b1f46d86c,0x0001709ad92dbba6,0x0000cc09de07504b,0x0006c7c9ec95eea8,0x00007648647d01eb,0x000b3919b1d6cd99,0x0000000000000000}, {0x0005f9f34e61ba7e,0x000eff53cc24a00a,0x000672781ea5e367,0x0005266f275cfce0,0x0009992d98139edc,0x0002c0efd50d9e20,0x000de18f3d9cb26c,0x000b647d23fe687b,0x00054a71ad97b9cc,0x00027a258eaff20c,0x0000000000000001}}, {{0x0008f39dfcb8ed4b,0x000811922f1fcd37,0x000a2846f7edab95,0x000566857a64449b,0x0005d6755b91a9b1,0x00033e748b542e81,0x00055f4eecb18a57,0x0006c4663a3a4f59,0x00052acaf4bb5b32,0x00079a0d2cfa0bdf,0x0000000000000001}, {0x000a0b89e0ca131f,0x000be75df1d52db6,0x000534480e6cb8fa,0x000be7af1d438291,0x000ad1a493673eca,0x000a16c7e34998f0,0x000d3ab56804db13,0x000479fc142bd461,0x000daa988aca4c3a,0x0001acd3bd93e84a,0x0000000000000001}}, {{0x000cbad8f99ea394,0x000cf3fa23022a30,0x0009f3a186b0f3c6,0x000e922b33420e3c,0x000c1bffbbdb1dc6,0x000aa59cdeeac227,0x0003dd943d5b8787,0x0005513a5be5e367,0x0004c0fefae77a5b,0x0003518e4c10fcbc,0x0000000000000000}, {0x00024505728229a8,0x00014b020fe0ed2a,0x00039e8625b5e8e9,0x000ac893dbd2dbf4,0x0002a5bf5b95c3df,0x0009c6d879c2cfde,0x000a75fca30a3152,0x000f3ac05ce905a9,0x000445553894b84c,0x000dc2eb87696cb5,0x0000000000000000}}, {{0x000c1e6489e4e3ff,0x000e40fadb280ee1,0x0009bea8383ad81c,0x000e1b3d235f576b,0x000a3198405d1a52,0x00058352c1e2f66a,0x0004288cd9077fa6,0x000dbd50c9d00a90,0x0009bd9a7d893793,0x000b363fd16ecce4,0x0000000000000001}, {0x00020eac52973702,0x0003e0c70e76207c,0x00006b2a996d0f74,0x000f4f6a44bb0744,0x000df28bc6807b4d,0x00017b088a4a4664,0x000ec1355d57eb8f,0x000182cf9ce6cfbc,0x000610a314e418de,0x00010173ffff5e3f,0x0000000000000001}}, {{0x000165051d386e1e,0x000bd47b826f3a9b,0x000a1c2b86d2360d,0x0009b8835ea5cf34,0x0009783bb9260611,0x0002b789b3e982a5,0x000e987100210011,0x00097fc2b9ab3e6b,0x000ba0e81d76b916,0x0007fbcd1d8d4518,0x0000000000000000}, {0x00091e776c559b38,0x0004c1e4fe7c517d,0x0006b3ca068cf1e7,0x0001a6fbc371e38f,0x0003b1539a3d7c5a,0x000cd0c3d50e8468,0x000c7e40ea4660b7,0x00012b9d873faeb0,0x0007f3ea3f2ff663,0x000c8c52e58fcf13,0x0000000000000001}}, {{0x000e0d1c0e7b0a6e,0x000182d5a79223c1,0x0002d07160d41c08,0x000de95d46cca38e,0x0004d00dd9df759c,0x0001f3ff3dc94e0c,0x000ad18e4b33fc34,0x000d2cfdbdfdd807,0x000c70a120714770,0x0005cb86265c3704,0x0000000000000001}, {0x0002e095e7588e93,0x000bb0fc7a7538c8,0x00049b1bf8ce184d,0x0006eac46bad884f,0x000da577205521af,0x00073592b9bc40d1,0x000dae6302c8fae5,0x000e9a408dc07f7a,0x000d86c203a973c3,0x000db4c1145f0edb,0x0000000000000000}}, {{0x000b134fd6bc3c71,0x00030305a92256f9,0x0007ccfce0b23245,0x000ca36a6d8cb621,0x000236d0ef54fd61,0x000a182b1b210c1e,0x000e2c48ae4f2531,0x000aa16671b7b1f2,0x0001cf556d29f38d,0x0001c83fa6c8eaae,0x0000000000000000}, {0x000a18df67396e49,0x000978a098406db9,0x000d15a5ed3d588a,0x0008786d781ea818,0x000c4ad06fce15e6,0x0006d7a550f98680,0x0004140981589bd6,0x000f7ff83976d3ff,0x00088eabc6ffe6df,0x00031647479f189c,0x0000000000000001}}, }, {/* digit=103 [{1,2,3,..,}]*([2^412]*G) */ {{0x0000d7e3378fb507,0x000c9bb0731c42eb,0x0005dc372a3657ba,0x00074ab3d967282a,0x00057f9ac8856a93,0x000b740967bdf210,0x0003024fec8274b3,0x00015596459a5693,0x000d21c1794a1687,0x000a98ef7bcfc7c8,0x0000000000000000}, {0x000af7b9ab0a89f0,0x000a24bfd8b660f9,0x0009cb13ed97b728,0x0000fd15ee5e0227,0x000febd3b7d28a45,0x000367bf5b972ff1,0x00091b608f71ea2f,0x000f496276edaa41,0x000a6a4c152d016b,0x0000bf52e7daddc4,0x0000000000000001}}, {{0x000ed176dc4c781a,0x000f2149979e6d8c,0x000b3c390a71d8f2,0x0009ec42d1cc9018,0x00013805d407dff4,0x00092c79f656592d,0x000250a69b4fae8b,0x0009ea40b75d7816,0x000e49fbb9c23c18,0x000630012080c698,0x0000000000000001}, {0x000297ec2f3d27ef,0x0009b4394adc76de,0x000084a2dca39d2e,0x0004162fa4a3c98c,0x000de4df52d9fff5,0x0006af6c27847a48,0x00049729a4d9dcca,0x000b96ed3609128a,0x0002001168323c41,0x00051e81fed2290a,0x0000000000000000}}, {{0x00023ceeaf6fda5e,0x000fb751aba8d27a,0x00058878762241c7,0x0009d28160069d96,0x0001830ade2dd51c,0x0001c3eb509b6317,0x000cb86f909879a9,0x000dee7eb48aca8d,0x00028bf799244bc3,0x0009202a06470538,0x0000000000000000}, {0x00015f7fc2843df9,0x0002f53ba48f85a0,0x00095ae129c2b6a1,0x000ddb2a444e10a6,0x0006aecfba54d8ae,0x0007c39b4f0e8bdf,0x000e6010a72c4d1c,0x000d5cdfd0f373b3,0x00068c9e099b50a0,0x0001c8bed1929d51,0x0000000000000001}}, {{0x000c2c46683ba5b5,0x00057c57128a2090,0x000dbf610a813452,0x000009fdd16c4a33,0x000c78f1d5b65bff,0x000560ad02b49af8,0x000ea450eb8499df,0x0003a52dc630fb45,0x000da8ac57e35202,0x000fb72fd6cb3d8a,0x0000000000000001}, {0x0006d77839d10202,0x000f1f4a52a42a8f,0x0004175b2fd3f44a,0x000ac14905fe7f14,0x000701757d0c0079,0x0008ae6d1c475fac,0x000d56b7bfd93878,0x0001b7dbf13b33f3,0x000d1df20cacad13,0x0006098aef62c8eb,0x0000000000000000}}, {{0x000224c02776a096,0x000fdf0428bd2668,0x000824486a9c4320,0x0009f3de8bb8cb98,0x00008a99c85515ad,0x00087cd9c5ea0fc3,0x00030bd0c213cb33,0x00075f7ddf36e0e9,0x0008b09a16a3e9e2,0x000ff92ba0c69ed0,0x0000000000000001}, {0x000dd8b8dacd787a,0x00044526b1b4ed23,0x000c4fcde2872824,0x000a0aecc5884baf,0x0000edf7e8ded34b,0x000a4bc010f4ef7d,0x0007a006485cbfe6,0x000ba70311a2f225,0x00032199cd733758,0x000ee0992d474968,0x0000000000000001}}, {{0x000d4dc4b29d1e7e,0x000ced039d3b8a01,0x000815590ff2c2bd,0x00021d5655ef3773,0x0006fddb06996f34,0x0006f2915cab4832,0x0005a14903f506e5,0x0004bd51fa3522da,0x0009df3d4ada1113,0x00041c2c8aabe985,0x0000000000000001}, {0x000708b80fba1a02,0x00028b6a0afd8d60,0x00058773df43d0b1,0x000ecec358a258ce,0x0008b0ae7440af59,0x0000e74789fcab99,0x0007429cf7b8fd56,0x000584c72e545e3c,0x0001897264b148aa,0x000a07b9a2d9b131,0x0000000000000000}}, {{0x000edce9ca1286ed,0x000ff3a46b7fad16,0x000535c9d7d2b840,0x0003708d5ca958c2,0x0005420c1e063332,0x000713a6fa0fa9a8,0x000918405a51ff70,0x000da85f855da776,0x000d1bea73da5e0f,0x00064183a6508fa4,0x0000000000000001}, {0x00083d4f23ca730b,0x000725501529af4b,0x0008000d1b6d21a0,0x000a7b3eee3507cb,0x00022a88a07a33b4,0x000540f9d09c28e9,0x0004983b28faa40e,0x000f54edb432d0fc,0x000ce23569311803,0x000d266759b9bb64,0x0000000000000001}}, {{0x000fd03e2a0c4500,0x000d5cf3f782f796,0x0003ffeae620bf4a,0x000ca0158514f603,0x000545633e085e39,0x0004884fbea88f4e,0x000882a85fc77f29,0x00012678c646f605,0x0009ba323a505f9b,0x00029223217b4379,0x0000000000000000}, {0x0002e8744f4170bf,0x00081a29194f6c03,0x000a932a7916cab1,0x000fb0f9f60ec063,0x000ff217a0ff0b94,0x00003ea56b8f066a,0x000ed4a56ee8b26d,0x0005efbf8ce2c1ff,0x0002eb114ed13051,0x00043d7447433992,0x0000000000000000}}, }, {/* digit=104 [{1,2,3,..,}]*([2^416]*G) */ {{0x000affb50d183763,0x000c1c5fc7f37a88,0x000a1f73a2f170a0,0x0001192983474ff9,0x0006b4738ed4fea8,0x0004d293dcdd7868,0x0000cd916188a232,0x000bc585fd523667,0x000b67188a2e54db,0x0008ed10b37344d3,0x0000000000000000}, {0x000548b086336003,0x000991fbe0b348b4,0x000ef3cdca5ad120,0x000cfcd2034c9a59,0x0004f56699960d16,0x0006df1f5f10f252,0x00000324733c5f1f,0x000a757f84ed98a5,0x0002f7eec2ce4fa9,0x000ae3d296f3ba03,0x0000000000000001}}, {{0x0004e9382b32007c,0x000d81cd77eae7c3,0x00013604a2dad7f0,0x00043d13d0e3fde5,0x0004c6cb59871704,0x000a8441d1c5f3e6,0x0002361adfd909c7,0x0004efba78610053,0x0001559070eb9abb,0x000708ee4fe6fb05,0x0000000000000001}, {0x00079200ca4f6cc8,0x000579128ad5ec75,0x000c265973749006,0x000f0a7f8cf2fa39,0x0002ddb548c37c9d,0x000da31069648b65,0x0006a7e075eeef13,0x000504d0e4093491,0x000fd613bea6b782,0x00055bba92eb2c08,0x0000000000000001}}, {{0x0005ab4da4a4107d,0x000f0dbf85411a8b,0x000a933992a7b991,0x0000accdce47a748,0x000c5662f2eb8c82,0x00064b5fdd12508c,0x000db73adddfe6b9,0x000af97a44a31358,0x00044c5ddfefeaca,0x0003403a084f6ff5,0x0000000000000000}, {0x000ad406fec21428,0x000e8954cddbeba4,0x00092a7fe19ec844,0x00084bffa4c49f5f,0x000ec8eb76b96304,0x00014948f0f75a70,0x000dff2c139503c4,0x00032fdf031b7606,0x000fa11a5ead6208,0x00047ef7a1eba7c5,0x0000000000000001}}, {{0x00073a3dabdb3534,0x0006dd5d8f611c69,0x000799bf33f3f4e8,0x00026f63749fb625,0x00092667bd3584a3,0x00060fa9fea81613,0x000999ea3a8de550,0x0004dd75d71ac4af,0x00078319418b1e64,0x000c67e995c857c8,0x0000000000000000}, {0x000c7afa552eb541,0x000a7222bb4a0732,0x000c7e0e1a608c59,0x00009057e1132506,0x0009c5c6a19981fa,0x00019205096b7bf3,0x000a7d38ab7490c4,0x00099e016ba7462b,0x00007f474dc3595d,0x0006636a3d8c9f12,0x0000000000000001}}, {{0x000058d88f35f241,0x000a59b2e8d2532f,0x00015502597aca02,0x000fb1e8bd7d1caf,0x00055680e361da0d,0x000ed31cfd9355f1,0x00047c0b0064d2b2,0x0004f348830f3080,0x000b7440fbffaf7d,0x000a5a553b98e17b,0x0000000000000001}, {0x0000f6eacb637570,0x000d4925881bc39f,0x000d655e7e9a7105,0x0002f09a033db883,0x000e97d5a4975dc8,0x000036e619a17847,0x00079d0e9b209304,0x000434fdadf80484,0x000412216e6c7daa,0x0000eb152f330b19,0x0000000000000001}}, {{0x000362cca8e2db27,0x000b58fb4260cc2d,0x000e2d527b899614,0x0001f0b467cb8aa3,0x000d1ef71b82f08c,0x000dc68072c4649a,0x00098aa11a9313c4,0x000165002fbe1ac2,0x0000bf5399f23796,0x00024b537dfdd6e9,0x0000000000000001}, {0x000f6c830ade2b53,0x00074af2e76469fc,0x00051f1bc5f4ed41,0x0000406c3a450f7e,0x00002b53708a683c,0x000428a6e3aa7dce,0x000c0df44b377b62,0x000e9c1a58f5f1ab,0x000c5458b0f02c35,0x000b16ea8718da27,0x0000000000000000}}, {{0x000134d37c05c59c,0x0007233d57586878,0x0006cf5af7409f53,0x0008ae6dfc4fd018,0x000e8b54df4cc39a,0x0005f3046db1d402,0x000312aeece717b2,0x000da13a0c5d98af,0x00073d6305f96c47,0x000587c80a3e3a7f,0x0000000000000001}, {0x00027d5a2516f5d0,0x000f9338bbf8fa7f,0x0002109c7d0c4360,0x0006004be57b26a1,0x000da32aad5aeeea,0x00041aa5daf9dede,0x000b0a16abc83073,0x000088080bdafdd6,0x0004fa8814cecd6e,0x000f5f24b2b7fe1d,0x0000000000000000}}, {{0x000cc19d6d74494a,0x0009296d31ebaa05,0x0003edd43b02f30e,0x000c79aac72cbbb4,0x000d57829df3e827,0x0008bb62624e4cf8,0x0004f05ffe745fb9,0x000950b350aaad89,0x000ea5e2db566ef1,0x000e1e37f6dcf4f2,0x0000000000000001}, {0x00034202ee7f3c59,0x000ed5d748da48fa,0x000e1cf505b68fd9,0x00031b86c7778cb3,0x000dbdadb45073af,0x0004b6e80bfe717f,0x0001ee413036b30b,0x0003482b138b2c3f,0x000e1ed1e4fc0159,0x000e84d788bd2771,0x0000000000000001}}, }, {/* digit=105 [{1,2,3,..,}]*([2^420]*G) */ {{0x0009afb73836ce2c,0x00035d1c0854627d,0x000acf6649f2eb9d,0x000acf4c38a8a9ec,0x0002178be52c0095,0x0008f6e06df7d7ea,0x0008285115ce7bb4,0x000b7f232680bedc,0x0004103a6e51e8f4,0x000aaa09aa0bc0d2,0x0000000000000001}, {0x0001c4bc539f42b1,0x0009f1f757159ce1,0x0000e9e10c0bc8d0,0x0007345be3621884,0x000d1822e5e0a60d,0x000ae792acddc802,0x0006be0f49763d76,0x000dff0f1717868a,0x0004437867cae1bc,0x00070e8bfe19f269,0x0000000000000000}}, {{0x0001b8994b02326b,0x00031ce496416ae0,0x000dc0825cea213f,0x00050bdf0281aa93,0x00059236853f9e44,0x00041e294dc8c09e,0x000b03a595c72a58,0x000c2bc6e5381e14,0x00020b03546b3008,0x0008eca57d1874ef,0x0000000000000000}, {0x00051a61ce5948af,0x000925d36a169359,0x0001712f7655b84b,0x0002f3fdc1e05016,0x0009aa758020ba42,0x0006927405b02281,0x0009822fced2aa8b,0x00019ae63d9313a7,0x000d9c07887cbebb,0x00065e13e45febcd,0x0000000000000001}}, {{0x00034f1f7e499842,0x000a48878049fec4,0x000692a3fe1f0c9c,0x00048261277fbbb0,0x00032263dc0fe7ad,0x000e09052ac6fec0,0x000683804d38aeb7,0x000d6c55fb1237fd,0x000bce4b453925e9,0x00056ac33e2d8263,0x0000000000000000}, {0x000a764c5c6d3730,0x000ed9705b2adb70,0x0003bab4631b9f1b,0x00014535b4850149,0x0009c2385e82937a,0x0007aa5ebdcd9ea7,0x000656517e5b5eb0,0x00078fb6885fd321,0x00087f791c6b2bd8,0x000bcad44bfcfcce,0x0000000000000001}}, {{0x000a7c1bbda99502,0x000d13ad86ee95d4,0x0001edd6edef741f,0x0001221485b8fada,0x00062b65b3c0a089,0x000583aac0300922,0x000ec2e6716727e3,0x0006d6729d8a817e,0x0002ad34233bfe29,0x000806779921dca9,0x0000000000000000}, {0x000373f0b0bc37c3,0x0006835632a2bfc1,0x000a8cd4f472c2b1,0x0004b6c9a4cedeb1,0x00076180690c132a,0x000eca05f9fa510c,0x0004e0551eb02c41,0x000e63213fc52e0f,0x0001b429bb6165cd,0x0002bc1fdd188cd9,0x0000000000000000}}, {{0x000629f7658d599b,0x000b1e87d39d0d52,0x000caaa997607dbd,0x000fcf23eb7d6dd2,0x000857e0cd30a02f,0x0003ecd22778d510,0x0005c5e961e1f158,0x00068aa70a145465,0x000c8fb1ff96ec7c,0x0009b464d2f55e62,0x0000000000000001}, {0x000e904d20ac7941,0x000e4f0bec2602b6,0x00080f6effaef59a,0x00060688330793e6,0x000db2442ae08549,0x0005e3d773ff5a5f,0x000cecbc6ac0199c,0x00012fa7a795cacf,0x000d6f9bfc57e52d,0x000ce32e4eaeafdf,0x0000000000000000}}, {{0x000eeeccbba2a7d7,0x000ad1d77ed0ffef,0x0005e752d769db74,0x00015b240b6200a7,0x000597b48ab8cfc3,0x000f97504538ef48,0x0005a2e980da41b6,0x000c0010c2010969,0x0007fe53f0d2b23a,0x000a1efe8b48887b,0x0000000000000001}, {0x0007b952e8dd021c,0x00026e6b8cb163c9,0x000d62feeed16bdd,0x0007e3db6129cfd5,0x0009dcfa4489e9be,0x000f551707d804ec,0x00012a2adb1fbcf8,0x000c05be22830553,0x000c9f74b7d87937,0x0008d7e5edd3be33,0x0000000000000000}}, {{0x0004b2f4546a8f7e,0x000d2a223a807885,0x000155358a6954ae,0x00086e4b30349ae5,0x000a5982c7a2aae1,0x0006ca4f6415564a,0x000013abb73fd2e2,0x00092d10cb063fca,0x0006104963b01aea,0x000bbcd0f1f68f33,0x0000000000000000}, {0x00069aedbf43f1a2,0x000ebe1ef2c9b47f,0x0003246ee727e6d3,0x0003f5bd1a5a6120,0x000987e829b05fc2,0x000b70444c023806,0x000f0d6e903fa23f,0x000baba52743b14c,0x0009994d97e9872d,0x000a52cbf74f834a,0x0000000000000000}}, {{0x0007ea3240feb8cc,0x000792ae77094407,0x0001201418e13db8,0x0003920cbc07e7f8,0x000aed56c93837f4,0x00013ae3d2a87da3,0x00044b8ddc44f1df,0x00069328fcaa2209,0x000b928d8e381964,0x0007313e55f26bee,0x0000000000000001}, {0x000ec4f451bd8008,0x0007bdfe195b7e42,0x000e12b70e68b680,0x000159222b99f5fa,0x0000c4e0659127ea,0x000efe86909b5076,0x0008c58b9b667112,0x00047b7026cf16a3,0x0007373740ea01a9,0x0000153963989580,0x0000000000000001}}, }, {/* digit=106 [{1,2,3,..,}]*([2^424]*G) */ {{0x000546c7f70bcb2f,0x0007212027084052,0x00013f0d6d83c3eb,0x000eaca7142e7b62,0x00029f973a763019,0x000be00c2a025efc,0x0003eca6f6199ab8,0x0002b5618bcc0394,0x000b02749fbfb9ab,0x00013c0ae9ab795f,0x0000000000000001}, {0x000f295b93c3d712,0x000bf1ab6d0e9f50,0x000bf53d7cb083d8,0x000d744e07076abe,0x0005a51a53561f29,0x000d647b915c2fc1,0x0009ead253f84287,0x000e91bd9d6251a2,0x00006dd74006b7bc,0x000c92c770e4efe1,0x0000000000000001}}, {{0x0002703ae4d5c812,0x000427e95afaa341,0x000271961d1eb61e,0x0000fb71509a4412,0x0007bef04644ecf6,0x00044d4556d64abf,0x0002a7bfd03e651f,0x00094add4bdd9b05,0x000438d74bb2156b,0x000fa36c6c16572a,0x0000000000000001}, {0x000ae16f96be2911,0x000d52afa2d73a0e,0x0005bc81a5a44951,0x0000fc89324d90b4,0x00018cab36337849,0x000cb411d87db838,0x00021f7d6cb710ad,0x0006ad26521480af,0x00094a666f370ca0,0x000375d8bc966e31,0x0000000000000000}}, {{0x00082baa7d62ed15,0x000a2a0c35293a3e,0x00068a91eba6b63e,0x000715c2cd81a65b,0x000ed39839d20270,0x0001cd1c736c49a2,0x00023b8eae3fee67,0x000006012e0a11a6,0x0006b901f0657746,0x0003944e0864a739,0x0000000000000000}, {0x00089e4689d04d8a,0x00060efa98dca953,0x000708ea3f1bf018,0x000f379e0740bbd3,0x000ab07cf1111586,0x00040f6bae4389cc,0x000c0c62ec14d78f,0x000a8ca2edc050cd,0x000eb9e22353ae3b,0x000221497d609a22,0x0000000000000000}}, {{0x000dc15d0ed0cc63,0x0001ce35b540e1bb,0x000973de7aa979e9,0x0005e965745fa684,0x0008a999e957c84d,0x00071ead702675f7,0x0002beeec63eb2b6,0x00062262a9349f4e,0x0005b027fa151a2d,0x0005b45a63374388,0x0000000000000000}, {0x000ade9fdcbfe121,0x00019964a13f4063,0x000ea6e576b23957,0x0009fa2021e1e294,0x000f93e8e8d0c1a3,0x000627a8aaeb1db8,0x0001c83a239f73f2,0x0009dc2704f34ba1,0x00053062be1591a1,0x0004c975cd21326d,0x0000000000000001}}, {{0x0006b8fb25e6414b,0x0003f3c35210ef6c,0x000fcf4305218c66,0x00044c1aba52d092,0x000ad9ddbd46b892,0x000a630015bf7459,0x000b32b246737751,0x000ced081a65d447,0x0002e2e5f643a94b,0x00044927f131866d,0x0000000000000001}, {0x0004645014a53592,0x0009ee4e5661d1ca,0x0009024d9b573293,0x000159f5f55c84df,0x000a0100b8c24f2c,0x0002de6a0aef0178,0x0009e7eedb7e96ff,0x0002067fc1f195df,0x000897eb377d8a42,0x000f1229a3daed81,0x0000000000000000}}, {{0x0005287cf2f5961b,0x000cef9beb6f8461,0x000a7eaedc75201f,0x000d39dfabd8969f,0x0004252116284485,0x0002945b419a298f,0x0000f03b98d985bc,0x0007be292f990254,0x0007d1f59fb5c829,0x00002d379bfc2592,0x0000000000000000}, {0x0001179af2527211,0x000f2724128932bd,0x000920719e949c7f,0x000f184c1ce441c4,0x00091d4d77a7c7bd,0x00086d6826d00ec0,0x000125b3901be8d2,0x000c6d7da5fd8de5,0x00084f0587b71c09,0x000ecbd13d8a200a,0x0000000000000001}}, {{0x00034258888b309d,0x000da5700df117ec,0x000eecc1e03d3856,0x000d69afef5df311,0x000ced3bd1e65823,0x0009ca00a3d94409,0x00053de41e7eb569,0x00002f1291722236,0x000dbd2ee0ded7b4,0x000a909f40f6e980,0x0000000000000001}, {0x00082d95c76e2f3a,0x0006d18779f8f974,0x000021eeb4e7e5b3,0x00070089298e7654,0x00003aa90b7f11d4,0x00020fd2c120d0de,0x000ddfdcf3b2e6f9,0x000134293b957e6e,0x000d5361a94456e0,0x0004bc62d97be2a1,0x0000000000000000}}, {{0x00047691dfe1ac32,0x00095bb25141cf40,0x000cb8b02c59109a,0x000eb57046b0d286,0x000a8b7de816343c,0x000109a4f745b33c,0x000bf34e4de2617d,0x000950869270fe1e,0x000a3a1b01ca6170,0x00012e38634a9ad0,0x0000000000000001}, {0x000f079109fbe1e8,0x00071bce15260c38,0x00059aca1efc1bab,0x0006c7ad5da68584,0x000030bec54d9816,0x0009a9c32e8f4612,0x0001154d88a51704,0x000ebe8180a7efea,0x00008abc6ec5ede1,0x000d7de0d26459ad,0x0000000000000001}}, }, {/* digit=107 [{1,2,3,..,}]*([2^428]*G) */ {{0x000019394140932c,0x0009a362bec3a200,0x0005ab884c7a2c57,0x000cab2ba06cf4c6,0x0003ee7eda004083,0x000107bb12f5f6cd,0x0008a0ae8649e92a,0x000a5a344683492e,0x000cfb24291fc3fb,0x000c3894cfd1718d,0x0000000000000001}, {0x000751b1b1d1f30f,0x00043fce22373903,0x00023da45dac2f10,0x0000105df9307b4a,0x000892b6d1b2c311,0x000f645131b39e6a,0x0006331d8e317be2,0x0000b2f395de9046,0x000d56345f1e436a,0x0001b0547fe7481c,0x0000000000000000}}, {{0x00078f4b7084325f,0x000727f8bc0fa450,0x0001eb36b7bf5948,0x0004268cea0106cf,0x000e8c80e06d4c70,0x000c216323300186,0x000b3016e94d5075,0x000d882e86c372cc,0x00048a28a053b8cf,0x000343d171001931,0x0000000000000001}, {0x000c0287664ae003,0x0002766d8c63b224,0x000b8220989c0738,0x000b967cd418521b,0x0004152d761e7a59,0x000fa019e4601efc,0x000f11b41cb4d7c0,0x000dcac0131d9d52,0x000c991e4e27a162,0x000789975ffa76aa,0x0000000000000001}}, {{0x000adcdaf64c0019,0x0002a5ef0c2175ba,0x0001cfec89a01d6c,0x000b25fa94296a25,0x00089c7ef16afeec,0x000c007e24585f16,0x000bbbc143cb4742,0x000531bcdafbbc24,0x000013773a99937c,0x000e19b7d849db6c,0x0000000000000001}, {0x000e83417610eec6,0x000e934e9e9d81b9,0x000af4480e73d7b1,0x00086003aa3fea2a,0x00079c57f5c52d5f,0x000495c2aa9268f2,0x000922e4d082c9f5,0x000448a981d714f5,0x000bdf27622c6821,0x0001ae01e6436230,0x0000000000000001}}, {{0x0007602120347ad3,0x000dd3e9ad407753,0x0002f89c76c52251,0x00044aaf5957d5e2,0x0006157c28051b58,0x00069eb597630bd3,0x000a387acac6af33,0x0002aad0ef875611,0x000ccba64de2edc3,0x000ff1731d170b0b,0x0000000000000000}, {0x000557f665f21957,0x00064548e1ee52c2,0x0000cf955615f44f,0x0002bf2c64b6036a,0x0008d89213e751e5,0x0005aa570d34bd85,0x0005ae3bf1cb2e71,0x0003f29e703acc20,0x000a34a47fb1911e,0x00089578616fc498,0x0000000000000000}}, {{0x000dc828f86252e4,0x000d09ec8dfb2555,0x0005077092f2430a,0x00078d5b0c56862b,0x0002f9b2b116f869,0x0007b998e4dcbf23,0x000fbcf91af3491c,0x00056f1110038af4,0x000e0888ba8f38ec,0x00043daf07963a9c,0x0000000000000001}, {0x0008da925a008487,0x0004f369188e0311,0x000ec8e641278107,0x000a270db9969754,0x00072aaa78c429c9,0x0001a344c1da5196,0x0003087bd58c2f7e,0x00088aeffcfb4dad,0x000fbcec5f2532f6,0x000a809230f905b4,0x0000000000000000}}, {{0x0000b4a0ddb8dfab,0x0009deda0e27481d,0x000949ab745b2f9c,0x000dc2842dbe3df2,0x00059b98be5c35da,0x0002ed3249c0c912,0x000dc475c0841958,0x0005a3cc60128529,0x000078110f67e016,0x00017fe4fa3624ca,0x0000000000000000}, {0x0006abd2bfebf71d,0x000617fcd7e4413e,0x000ac8bf7c39197b,0x00022ac8be897f87,0x000878bd60d51691,0x000ed69bb2587c48,0x000a51aae1defc49,0x0003d1f77705c7ae,0x00021ab01c739c3e,0x000801dacd9f17c4,0x0000000000000000}}, {{0x0002a912967cbb3e,0x000f46687e4df221,0x00007e4eef350ebe,0x000e38a4de052972,0x0009d5282d27fb20,0x0006e64b3686af97,0x00067350cb71692e,0x0008437b220d3baf,0x00042c826bce6850,0x000642d60e139b00,0x0000000000000000}, {0x0004eb43ead3cd1c,0x0007d1cbedb5fe6f,0x0001b45fb1ca7933,0x000a503cea7b46bd,0x000fef3868c8b110,0x000f9fe2cde99fc9,0x0006dd89f348e20b,0x00022d25b6cd54cf,0x00051adcb2128528,0x000ea79e7afb9c6c,0x0000000000000000}}, {{0x0001fc12e7ca5055,0x00025e91d6adbf30,0x000587a0d31dc42e,0x000cc8a9cecd10d8,0x0009d8d1b41ccf88,0x0003b3f96490bd95,0x000e028999c5a513,0x0004c3a0882547be,0x000fc3438b39f5f7,0x000fa75af39ed4d4,0x0000000000000000}, {0x00002b54c1f9ad9d,0x000dbd0a29ee5fbf,0x00057045bbc4f0d6,0x0000fce2e6fde293,0x00033040027dfc7d,0x0003be51ffcda45a,0x00054869841c14d2,0x000156ff1e336d04,0x000a634d9fdc8522,0x0003ae619b696b5e,0x0000000000000001}}, }, {/* digit=108 [{1,2,3,..,}]*([2^432]*G) */ {{0x000019f2fc6beb7f,0x000666646b70deb9,0x00090a5717d2e533,0x0006810fd38f5274,0x000233bb33bad791,0x0009b6b88efd9526,0x000d5745dad71c05,0x0004ca300788fe6e,0x000ed4a6a21a98ac,0x000e10eeff58916d,0x0000000000000001}, {0x000da52e803a67cf,0x0007d398c1a5fc48,0x00042b185c01901e,0x0004eda6cb2700b0,0x0004eeec867cdaca,0x000dcb7e930a19ae,0x00010a288471dcc7,0x0003198ed17517e0,0x0004e8756bb36f68,0x00027df915ed36bb,0x0000000000000001}}, {{0x0009d95ae2bd1168,0x000fb9d6f73873c0,0x00027b3bc9e7cafd,0x00005fa81f14d40f,0x000ed4eebf4e66fc,0x000bb6036a4e6b76,0x0009e3f736cb7387,0x000b2277b08a58e1,0x00055c0d7a4986be,0x0004d18f830adabb,0x0000000000000000}, {0x0005e59f982356bc,0x0000599a3ae563b2,0x000d06e16bf18997,0x00088dac7505891e,0x0004c76b3eb973d6,0x0006498b2d10cb08,0x00074af2d6e8e95c,0x000a503f71b8afa5,0x00066999bc16133c,0x000bd76f3443fa99,0x0000000000000001}}, {{0x0009cc5a1fdf300d,0x0000ede5aa101a8c,0x00053342a7d32907,0x000bb4fe852398fa,0x00036673ceb9c007,0x000c9247b3a94312,0x0001ee51cb682683,0x00075c07f2ef115b,0x00083b0143f6486b,0x000d101585ec3771,0x0000000000000000}, {0x00080da54d84cedc,0x000e569a2e8c0006,0x000e94c0472e41a7,0x000a41c1b7c713ec,0x000e5742d18ccf2a,0x000df3c3763e3162,0x0006b9977417a84e,0x000f165b44c75791,0x00045d988246f2e2,0x00095c8287828d1c,0x0000000000000001}}, {{0x000f9c015fdb1c06,0x00099f25767d4418,0x00077c536b749d61,0x00054bfdb54e847b,0x000237979776c1af,0x0001eefa220b8386,0x00018acdf9bb4a75,0x0008ce45beb5028f,0x00030f98a7dd8621,0x0003023f055e3ab9,0x0000000000000001}, {0x000f321b72c7f6a2,0x000659eeb57c141d,0x0000b2255cf53902,0x0009dbecf2a776fd,0x000e6453cf8ab4cc,0x0002d5647863e94e,0x00049fe93a4007af,0x00039cf116d00271,0x000dc8184a637605,0x00061de7465f7317,0x0000000000000000}}, {{0x000dae8508371ab1,0x0009f5759cf42671,0x0001705cf63d991b,0x000e90ca5edd0265,0x000af5c715a86e95,0x00096331dd94a89f,0x0005808565c73b46,0x0004c9ca8a595723,0x000561170be646eb,0x000a57b5fc879ce5,0x0000000000000000}, {0x00080540adb44437,0x000abb97c57c16dd,0x000be7baf4488307,0x00019e753dbf21d2,0x000ac5be29dc51e1,0x000df21c9ad3cc57,0x000a9aa74fbb9193,0x000a11ec7b8e665f,0x000c01bfce350115,0x0009909f2c73b53a,0x0000000000000000}}, {{0x000744ab95b71183,0x0005aa6c81566c3d,0x00033310fbbacd74,0x00006a2dd55a7d6d,0x0002db05de914221,0x0001ffd4282301fd,0x0008cf7489b2de85,0x000c6f0a02baf309,0x0002ce9af0a85604,0x000261197b0884c2,0x0000000000000000}, {0x000e2c60da7deb89,0x0008d4b2f2e54489,0x0002e5dee75d5785,0x0005e0e953899934,0x000ecd968f2eb742,0x000229cbd8cbbbd2,0x0008dcc6b871d5e3,0x000490c7582e68a9,0x000cde3999720429,0x0005eaec58ffb639,0x0000000000000001}}, {{0x00028ab59549216b,0x00005d61d82596b8,0x0009fa679fcfc930,0x000ccf438ed2cad9,0x000a40190b3069f6,0x0007f5af4bb6d49c,0x00002f9e7c50f6a7,0x00019940efdd8671,0x00002add96c554a6,0x000e007d80786684,0x0000000000000001}, {0x000ad0fb54ef0a37,0x00046af5d15fc57d,0x000b825452e8ccd9,0x00044232c710cb6b,0x000cf88855ecdc6f,0x0001d6d2b8f40b3c,0x000436e2bc3e510d,0x00007b1ff42aeddf,0x0000ed88484552b4,0x00075c1505c18430,0x0000000000000000}}, {{0x000a55f734e8c16e,0x00026ef042fa2f6e,0x000b24c1848ab1d2,0x000acbe86862a1dd,0x000651f4168e7413,0x000d596e07914083,0x00079ca23961d189,0x000e6d53679701b3,0x000cf35fa05ec7b7,0x000d20d7f6b70713,0x0000000000000000}, {0x00018785b4c707b1,0x00038676095f2dbc,0x000e28a0370a0054,0x000af09e50c89610,0x0000f144bba0bfee,0x0004cf6dd7455cf1,0x000e722f509d9783,0x000b05c279e5f94f,0x0001244fe8092deb,0x000153b314f061e7,0x0000000000000001}}, }, {/* digit=109 [{1,2,3,..,}]*([2^436]*G) */ {{0x000803868bfafe94,0x0002ddeb7719717f,0x000911e1ad005b4c,0x00076f1e0df34f87,0x000b29958d5da570,0x0005d1ebf66f49ec,0x000f5712ca7b49e5,0x0005b2ff1b32fcb4,0x000f97d3d42a971c,0x000804838bb32749,0x0000000000000001}, {0x0002e7908789eb65,0x000af786529c3ba5,0x000e71594737ddd9,0x0005400f6dd64d51,0x00039922bf016830,0x000db4bbaa21ca42,0x000935d8c94ee851,0x000c80623440afda,0x000110efc0a576c9,0x000396d79f58dcd9,0x0000000000000000}}, {{0x000b38ccc9df95f7,0x000d1849ee6062ae,0x000164333dec1411,0x000e81b4a4a4727a,0x0009c74b241dc566,0x0005069fb7290aa5,0x0009d322865cb6d8,0x000ecbd648392838,0x000909864ce3c8f7,0x000ac9fef248d28c,0x0000000000000001}, {0x00061d435126259d,0x0005a6b96bec8542,0x0001f509bbc62a6f,0x000ddbc8b43f9c90,0x0005e94118466c53,0x0002a386779ad388,0x000db58d109dd2e2,0x000aeef4f2af60b6,0x000bc0cd7adf1adc,0x0008220fb47811d5,0x0000000000000001}}, {{0x000f1b4d9b2b9d58,0x000635d4601e4549,0x0005712ad28d37e9,0x000e19b42c3143dd,0x000fdc6366f04af7,0x0004b34637aa565a,0x0005b2ac12b452bc,0x000277fe7f5bdd13,0x000c6ff31feea8b4,0x0000c45cdaec8e9e,0x0000000000000000}, {0x0007813178366af1,0x000e83664c221b3f,0x000afac4ecd652c3,0x0007c4666da93d03,0x000652ceac0d6cfa,0x000b1a4cf4039d2b,0x0005c58a6eb1946c,0x0007422c9b53a228,0x0007349ed1b4d836,0x000afa4c55a379cc,0x0000000000000000}}, {{0x0009ee173ac4010e,0x000fb942f467a4b5,0x0005770a30141b66,0x0004198802513df6,0x0002c7e0148f2f1d,0x0009a1b6c6f54abf,0x00056f2bb47b51bd,0x0004f5846505fba9,0x0002a3ddcb02618f,0x000a7b69ec8c6450,0x0000000000000000}, {0x0004b69533aa9231,0x000b0804316d8f19,0x000006107c58f7bc,0x000310f29f43afd0,0x000e7a15ea5dc32f,0x000849a363e2b91a,0x00074452b4966c63,0x00071d63455b6a45,0x00039b535b8835c1,0x0005091ae86f54cd,0x0000000000000001}}, {{0x000de1ec8614daa5,0x000f0834c4db4a7b,0x00048a29f6ba70a6,0x000be231587d1015,0x000bb998c9a2049d,0x0005eedcf88aceaf,0x0008878e6b738f7e,0x00019b693ecfcab0,0x0008dd1ddb374ede,0x0003be7a6cd94f00,0x0000000000000001}, {0x000bd130c16a2f12,0x000343c20757ed83,0x000228e06b217bff,0x000046a91bef19ad,0x000400e88da5cc51,0x0000a9f961011b58,0x0003f9049ae6f047,0x000e9d079a03c6f8,0x000401435912f072,0x0007490b78fe3f9a,0x0000000000000000}}, {{0x00081fdfff4245fc,0x00050168c14a6614,0x000764d4d2b84edc,0x000aaa60be356501,0x00030e6771588736,0x000714d50c0c40e3,0x00029157b8fe8875,0x000a9215aac4fbdf,0x000b4091b549e25d,0x0001ad442d2b0058,0x0000000000000001}, {0x000ee6a91c584138,0x000d84934568ba88,0x00010dd1585307ef,0x0009b046cb644b24,0x000dc2bd376e1321,0x000cecc49bef0c68,0x000f76556c2d2d1d,0x000d810f8810c907,0x000a20da5052b3dd,0x00079ec3448a3c1b,0x0000000000000000}}, {{0x000084366f4dadcf,0x00087f5cc0a55e0e,0x000a139c3fe7ef01,0x0003f2e749d53f7b,0x000ffd809a727542,0x0002e74f9e5a94a4,0x0001929541f08d0e,0x000114dd07932254,0x000f53ad14915984,0x00078a408f5bb7db,0x0000000000000000}, {0x000b74adedde4d64,0x000eeb46e287111d,0x0001ad3605f3b22d,0x000070fc8863541b,0x00093fdd530f51fe,0x000f3d69c04af47e,0x000f551d93cb6477,0x0002bc684cde6d16,0x000154a9f50cd685,0x000e9f16ac0cc2b5,0x0000000000000001}}, {{0x0006190bccf09089,0x000de2a4a386bf1b,0x00095703cbb17c47,0x00013d223bf84891,0x0007a124742673f0,0x000290f2b86fdb82,0x000f44e50e9b7e10,0x000ecc65826079a8,0x0004d12b589a9228,0x0001b683a119d1ab,0x0000000000000001}, {0x00025950f93cc637,0x000b7a6b02229a2d,0x000fb0617d538c46,0x0001dd7b6bc581dc,0x0005b6b522d590ce,0x000133e3f5d0dcdf,0x0005bdf5cce47e79,0x000e21b8ecd0d71f,0x000ac21b717d9aef,0x000b887b6090257a,0x0000000000000000}}, }, {/* digit=110 [{1,2,3,..,}]*([2^440]*G) */ {{0x0009fcba235d8a1e,0x000ca359a63f98f8,0x000f60025c086d07,0x00018d4e590915cb,0x000c915cc7c3b68c,0x000933480185575e,0x000511ae8d10d820,0x000082704b904789,0x000a4e997db2e76c,0x0008c3f5824d99f6,0x0000000000000001}, {0x00053628d8f32dc9,0x00000ea757555069,0x0008537e14185044,0x0007f7a0609d8295,0x000c55da70118c7b,0x0009ad1223c50379,0x0008629c936f6ea7,0x00054f7f839cbde4,0x000f8def61ba0172,0x000f5c1bef09ebdf,0x0000000000000001}}, {{0x0002eeedc5fe3f41,0x0004f9330d665ae8,0x0003f5e64a30753a,0x000e92f39e477096,0x000aa07f9d297ef9,0x00048c3ddf388062,0x000e61e60ab0df5c,0x00095a47567e55e6,0x00066d0129872a6f,0x000953425f368c3a,0x0000000000000001}, {0x000b7cc7bf66ffa4,0x000f16b2825eba03,0x00090e67535ba3ce,0x0004aef14aec5704,0x00001511ac67bcc3,0x0001002739d95c0e,0x00029220f4f36575,0x0001465557ab45e9,0x0009abecf1baabf9,0x000fe98337c9760e,0x0000000000000000}}, {{0x000025751d2b325a,0x000cde6a01039da1,0x0005ba8462228499,0x0003490747232500,0x0001a523417ab4da,0x0003451baf54b07c,0x000516f3fa7e4ffd,0x00042fbff2147ce5,0x0003f1b0afc522cc,0x000cb395c7010ca3,0x0000000000000001}, {0x0005ed5f55af51c6,0x00015b980e568466,0x000a5a1b30bd5964,0x000bb04e8834a37b,0x000becf282494fee,0x00040dc6ceb29d17,0x0004a868d5399a53,0x000276012bcea50f,0x000c769aa83faa31,0x000d8e6550a0654b,0x0000000000000000}}, {{0x00066fa0ef4dbc14,0x00071d134a53f7ec,0x0001ee39cdaa7b28,0x0009b3f183070c04,0x000c76da77991974,0x000916f1eb867841,0x000b27421e5438ae,0x00051b0e12d8e409,0x0005e08b83842a6e,0x00094374b9e008de,0x0000000000000000}, {0x000a4cba763a6340,0x00013308e07acdfe,0x000db2143a906789,0x000fe6dd815c887a,0x000e2a9d2043c85f,0x0003ceab79a68d05,0x000986393674d33d,0x000d12ee73ca7a8a,0x00003b9bbd54b7af,0x000b702eead11264,0x0000000000000000}}, {{0x0000b987f57f80d5,0x000d4367c06145fa,0x00034438e79fd55d,0x0000f9f8e8ca9c52,0x00036810f12c2fad,0x0003ec5af1a97a71,0x00085613d0eababb,0x000aecb3da01b7b5,0x0000150798aadf26,0x0008029cce9cadbb,0x0000000000000000}, {0x0005a72e54383960,0x000decd025e95126,0x0005b2c914390e3d,0x000864784955e972,0x0008cdae63ed0053,0x000aa5ded860c28f,0x0001dd80fb99e774,0x00020f07854bb74c,0x00091581c2caae0f,0x000d48069f6ba766,0x0000000000000000}}, {{0x000f135836126647,0x0004208b738df6f5,0x000786c7341e91f4,0x00084ed91ae2188a,0x0000b08e3293bda3,0x000e09af3119b1a0,0x0003662652676669,0x000fd07b9f37322f,0x000ae129d764ea40,0x000b85c16a911b11,0x0000000000000001}, {0x000021aec95ad18b,0x00080eeb3197c759,0x000dfd4a4334daed,0x000ff78d606234ad,0x0003ff98a1d73ab3,0x000c9cac669f90a4,0x00063cf99bed1762,0x00028f03fcd45e80,0x000b17bf750672a2,0x000879027e080bfd,0x0000000000000001}}, {{0x0006a647cfcf8e23,0x000d745dafe04723,0x000c3212b4d30081,0x000945780f548f13,0x000a0d885e14f51f,0x0006ed3092941059,0x000651e189c478f0,0x00007a26e8c75042,0x000a14b52f36b6ee,0x0001a032dfdec009,0x0000000000000000}, {0x0008ca67379eb582,0x000b6f527f0a50be,0x000adaba76e4c6be,0x0009b987fc7fd1fd,0x000a047c90091990,0x0006d6f45b992155,0x000e37e2da697e00,0x00011a38bcd1740d,0x0009b93e8ce3867f,0x000b60503be8b250,0x0000000000000001}}, {{0x000c16ca71ab9de2,0x000d4b4d3bbd16e8,0x00053785c45519f4,0x000fab776454947e,0x00019d9b9416f1aa,0x000337e34e6883b4,0x00041570208ba8ab,0x000cab67774a7e58,0x0008ac5165a84d18,0x0003a977b69d3110,0x0000000000000000}, {0x000e5bcfd652943f,0x000743cd5e892a91,0x000502744c85aa27,0x000bb91ba0414bf5,0x000f8bc4ef773e26,0x000f9e301b8bcd45,0x00028983589038c8,0x00019a5f5e5a30d4,0x0005c6671a609f77,0x000a3aade09eb4af,0x0000000000000001}}, }, {/* digit=111 [{1,2,3,..,}]*([2^444]*G) */ {{0x0008fa162e0dbf60,0x0003f486c08a442e,0x000d94f9cd2b15f8,0x000f2a2350bb6a89,0x0005b606cc5727bb,0x00003f198a74b132,0x0001a6f73b79d3ab,0x0001c95046a9cf73,0x0005ed71e298efd1,0x000274d622bb2409,0x0000000000000001}, {0x000c383b3b59eae1,0x000e81b2f1927508,0x0000d888be6e14de,0x000fb612ce4b12e8,0x0001378248f53213,0x000330dbca43092c,0x0009ef5e40c52b24,0x000e9d869889952b,0x000c05f4131f1126,0x000503fd03ae1dfb,0x0000000000000000}}, {{0x000868b8bbdfd1e3,0x00069e244e266c6e,0x0007c7bf40b05a43,0x0003b7e1e296776b,0x000e22cfd9c18aed,0x000ea90d63ddbc31,0x000929198abb7bc1,0x0005791f36a5e50b,0x000737c71c2f87e5,0x00024f75c6d8e7fe,0x0000000000000000}, {0x0004c9eb7d596ad7,0x0001e1a0fb486ad5,0x000d820f02c91d1e,0x000160179160a67f,0x00057f1163f25e5d,0x000cbc9a928b61c5,0x000df9b84ed79f2f,0x000854ba69556a33,0x000c5cb8ac8febe1,0x0009a7ec5a344343,0x0000000000000001}}, {{0x000a1f2d5d90dce2,0x00048086d7fdecb8,0x00005e3d618ccc17,0x00081c1e93d5b7f5,0x000a9cc469c44a02,0x000561bd59d9df3b,0x000788578aa5fba5,0x000f6a295757cdc7,0x000387a16bd50e1c,0x00029d1a6695b773,0x0000000000000001}, {0x000b40770bcc13d9,0x000a0b4cb7c0701f,0x00058a0433c71ad0,0x000e93cd5406bd3d,0x00098c999eda26c3,0x000092f416481951,0x00047a1b9bfd4b10,0x000f450e0ae46263,0x000aa14d201a717d,0x000a1f0cadae7402,0x0000000000000000}}, {{0x00025a8ecef36f15,0x0000495828c615a7,0x000ac113424f603a,0x00042c1687a77e81,0x00098761c2762346,0x0009b1a4749d0db2,0x00097828ac3391f2,0x0005050c5b69143a,0x00078b0a25ae0092,0x000d6c144730edc5,0x0000000000000001}, {0x000bfa3844e6437c,0x000f55606aeb933b,0x00097e413566e3da,0x0001c1ae4263527e,0x000823a0378934ac,0x0002143f588c3363,0x00027262bb7d997b,0x00082419935b6941,0x0004eeef99cb555c,0x0009b82ef7f7cb72,0x0000000000000000}}, {{0x000f0062dfac9c48,0x00002d81a18ce131,0x000ddcf23a0713ab,0x000a1fcdc4c43fef,0x0007bce6f244518e,0x000ad87348b34742,0x0006967b2b850180,0x00045248a8e5aac5,0x000029c18af90606,0x000027d44e26ac08,0x0000000000000001}, {0x000cb47b7d6fa01c,0x0000fa06669eb12a,0x000ba3426d87d938,0x000cc362d25b1811,0x0005c938c9a5e9c2,0x000513be5311d61f,0x000c741f99e49306,0x000858e6ea44630f,0x00001034df68ea15,0x0009fda601eea831,0x0000000000000000}}, {{0x0001335ca463c947,0x000056d6526151f8,0x0003c494f0f999ff,0x00082dc10a7433ca,0x000067fa3bcdc41b,0x000c803bb39af11e,0x00031fc0ac7bb35e,0x0005b5e185aa457b,0x0006ab2cbed55591,0x000c973304481958,0x0000000000000000}, {0x000c07b3b2112108,0x00057bae813666bf,0x0008eee1f424f0a9,0x0002122582cf0958,0x000314daeb7bdc33,0x0004de4e23458ec0,0x000a768d0f97884e,0x000a1655c201fc50,0x000f1a537b424f36,0x000a6c0cdff48114,0x0000000000000001}}, {{0x0007e2caf6bd29ac,0x0003376357d313a7,0x0007372bec99c462,0x000dae50c449ad64,0x000a9851fff00473,0x00047fec5d20efdd,0x000826de033e859f,0x000f46311785804a,0x000104e3184caf5e,0x0001ecedcc25e31e,0x0000000000000001}, {0x000e47c0beec6da0,0x0001b1920715db74,0x000ae32e6188b124,0x000b5dfc6ee77c87,0x0006b132638e4040,0x000b86b665e1c6f4,0x00028fe14b060006,0x000b71efffb869b7,0x0006eab86370f188,0x0003e80379ec88c1,0x0000000000000001}}, {{0x000f8cb24f3b637b,0x00076af131c20322,0x000815ccfff0c2b0,0x000fbdbff056364e,0x00060c8028853dbd,0x000af0ee0841ab57,0x000da56ca93ac088,0x000d301350923094,0x000228a255054010,0x000a058e7dde6774,0x0000000000000000}, {0x0005176aa5c512c3,0x00020d3779fd868a,0x0007658fb3dbe164,0x000cf13041f45c5c,0x0005049dea64d110,0x0003f6746e19e0e3,0x000a39087ca45757,0x0008108ab4e2fe7d,0x0009cce4e874c545,0x000b791d64965ce3,0x0000000000000001}}, }, {/* digit=112 [{1,2,3,..,}]*([2^448]*G) */ {{0x0001f7c72b336855,0x000f76e247b483cf,0x000202781dc97b6b,0x0005bb58c0f81747,0x0000c92efba888b6,0x0009612af59611a6,0x000ccbeaf54a57cd,0x000ef8689ba520d7,0x00091cc366d3cbf9,0x000056dc1abfe905,0x0000000000000000}, {0x000a04beccd53894,0x00021b1e600b02d4,0x0006c3ebe8f2a150,0x00007cfe9586be60,0x00062f4028af5b85,0x000d392e8954dda7,0x000dadc519d37584,0x000b58c3813ebde8,0x000557ce681db641,0x00006323fa3b9991,0x0000000000000000}}, {{0x000327209a17e11d,0x000d294da0ba85ba,0x0002e3b7145fac1e,0x000fef1248cf218d,0x00034de112f175cb,0x00094a8f1676f3e2,0x000f9c2657870861,0x000518958d56de1a,0x0003dbcba495c76a,0x000cbfa5e9c9c9dd,0x0000000000000000}, {0x000fcebaff9f1e95,0x00070930a1b712b1,0x0008296f1f273d82,0x00071eddfa6e1f41,0x000af7dd190815ef,0x000f6fda9bc4a2f8,0x000482585b1234b2,0x000e23556036541a,0x0001ac1cc79e6b22,0x00079988ea71f991,0x0000000000000000}}, {{0x000a9c0f0a888100,0x0007d24e7957d723,0x000347cf9592bff9,0x000365bb77516430,0x000532639eeab522,0x00075ffdcf80bee0,0x000715b06a25a527,0x000f841be2cacf87,0x000bc301ef1a4c9c,0x000be09159817e68,0x0000000000000000}, {0x000ae077a00f18c6,0x00066d4baba09883,0x00026a600e57c245,0x000d614baadec7ac,0x000df9f1c7a24538,0x0006e61c4241b694,0x000e25d7cba200ff,0x0002e6c811de028a,0x000a7a2ca09bc137,0x0004b214e3d38684,0x0000000000000000}}, {{0x0002cc5d8d86efa4,0x00086c8ee779a0a2,0x000fd2159545dd5d,0x000c7262fd5e2c81,0x0008275f13cf7ab1,0x000759a0b74f36ad,0x0003c0c8c3ddc91e,0x000d10948a51d222,0x0007160cf9b2c7f7,0x00060f285822b597,0x0000000000000001}, {0x0001e962392851c3,0x000b50d7c127ef1a,0x000d984c5287e5e2,0x0005ce7d3999dfdf,0x0006fd1373907aad,0x0007f8f0825c8472,0x000b5c55ebbc32d9,0x0002bd51b3a068dc,0x000935287a1b4f59,0x0006c8f3eb9dca36,0x0000000000000000}}, {{0x000e20e45266c880,0x000d20d089ee45a2,0x000924531cdc6e8e,0x000f7ce2e1fa4436,0x0002517f9a18e676,0x000d570398bec610,0x000dea4d0f9eb1c1,0x000c9914ddf30f65,0x000cb21d0d421e9a,0x0002d38fb5fd0304,0x0000000000000000}, {0x000db46cd0b507ab,0x000ba53f3ce83b8d,0x000a8aca81c50a03,0x000245a83198cc38,0x0008bb4ffb6faabe,0x000c93601934e1ba,0x000061b676968674,0x000710e9ebcf5033,0x000185f4475389bc,0x000687b9bd9763f5,0x0000000000000001}}, {{0x00029514447f1de3,0x000d950771604321,0x0003a8cfdfffb078,0x00022ba412e08811,0x00097ef9f248a108,0x000b82c1196accaa,0x0001f8d1787041bc,0x000ec8430565e6d4,0x000eacea7ff3e1c3,0x000896b9bec2206b,0x0000000000000001}, {0x000508946b504e8a,0x00067cc71474da28,0x0009ad4094d373bd,0x00068f87798411db,0x000b0b90d5d507cc,0x0000617d88846f61,0x000a437ea42aac2f,0x00012a4ea205a926,0x000adcb25d613e80,0x000fb7ef615aab09,0x0000000000000000}}, {{0x000127afd82f8260,0x000f4ea3f09c69bf,0x000b49f3f0e43a3e,0x00052457b8b9c3f9,0x0004fe6ce00409f0,0x00044efa3e31f441,0x000e3e0240cf1253,0x0001f0b4a170983e,0x000d166b0cc9e8c1,0x000b455417a2207f,0x0000000000000000}, {0x0000fd522cdf167d,0x000b48039daf9a36,0x0007cdbcd7341cc4,0x000c7db3b7805076,0x000641b0db786edf,0x0006ea9b69b8bccc,0x000eded2a4e25e3e,0x000651b8f0911cf0,0x000614b601e95ba9,0x0005000aeb19e877,0x0000000000000001}}, {{0x000c0c51d56f967b,0x0008dddbb7684495,0x00035dbc45f7bb76,0x000f9e6deda49098,0x000e73639006a39d,0x000878e5a247f77e,0x000cd83d141b2c8d,0x000804a47e332c8c,0x0009dc7a02d4027f,0x000b1b9934bb002c,0x0000000000000001}, {0x000777a838efe004,0x000368d9919c1d8d,0x0009dd721650f685,0x0002b1de892863f1,0x000d78f2b25a32a9,0x0002a4320690ff3d,0x00005a4af7bb8bc1,0x000cd763efcfe035,0x000701c70cf4f256,0x000443ef26775353,0x0000000000000000}}, }, {/* digit=113 [{1,2,3,..,}]*([2^452]*G) */ {{0x000e0800cd422057,0x000077d1b7504d49,0x00004fd80e159ebe,0x000a18a8714afb4f,0x000de28810d8b90e,0x00019cff83f02c3c,0x000eb9e19367a867,0x0009952bac438786,0x0000e0748ecceb4e,0x000faa55aefa6646,0x0000000000000000}, {0x000aa315b1f2623e,0x0002b544f96e097a,0x0005dae237e7a5db,0x000873d0a9362519,0x0005569799223163,0x0001a58ea84d0fbf,0x000d43fd3bb728ac,0x000f100cfe43661e,0x0004f55c6f1cd21a,0x00091825dcbe9fa2,0x0000000000000000}}, {{0x000fc794a5858d75,0x000a4affcd84d641,0x0005082ece4f5985,0x000b4853cf3bb3f4,0x0000bb1d8af65850,0x000953dc3e670d98,0x000424ef579458a6,0x0008ac2f2e4a7963,0x0000d771e540b685,0x0009be1f5fed2292,0x0000000000000001}, {0x0001be223c4864af,0x000fbb662c4dc573,0x000a57017521419c,0x000c0240d65099ca,0x000b13af88f3bfbc,0x000bc4861e1643ac,0x00067ed67405bcdf,0x000d9351f1c835f0,0x000d0e188cb8018e,0x0001f8d276f971ee,0x0000000000000000}}, {{0x0006a9e449621f3d,0x00052e91ee418d60,0x0007e5ea0e7d2dd0,0x0006f73c92e787f3,0x000cc4508ea4869d,0x0002d461acfe248e,0x000bd24529ffcc1a,0x0002f90dc5dc22dc,0x0002f8abba336456,0x00056cd254e4f954,0x0000000000000001}, {0x0000aa036c0262fa,0x0002edc4f4234a99,0x0001031cef9b59ee,0x000145d5d5d4b081,0x00087df2c037b984,0x000a2d6af2c7b077,0x0006ff431d568532,0x000e309a7c9b6d5e,0x0006a3ee9bb40c66,0x000c81af9db41cda,0x0000000000000000}}, {{0x0000f6f067a194c8,0x00066d7ad7abcf3a,0x00041cf832b531ca,0x000f470a4ac4965a,0x000cbe00766a00f9,0x000432af80a92657,0x0008968ac40c892b,0x000cbd44ededa94b,0x0008d46204be8b74,0x0005dd98f760bd2a,0x0000000000000001}, {0x0007f464f2479db1,0x000c0fdb3e7dcb2a,0x0001a96b28900b58,0x0000a2993c1d7ee5,0x00057bf0ce9357a3,0x0001f5d39eb49f5f,0x000fb8b8f0c1970f,0x00060718d4faac9c,0x000ec4ed9e1c25a3,0x00004bb0d7504b66,0x0000000000000000}}, {{0x000c9e1b2fe9b1f5,0x0008d34221feb754,0x00042a589958e706,0x00008c19119e3c31,0x00021ac738645a87,0x0004d7be72a33383,0x000a72a39907dc71,0x000beb5759bb91f8,0x0009abd4b13e9374,0x000b96398db67d76,0x0000000000000000}, {0x0000945a75d3799d,0x00031dd530ad32ad,0x0000c605c645aa0c,0x000c247141d0f230,0x000876cc8fca8350,0x000943188b899279,0x0001484afb9ffa8c,0x000536d0aa571f07,0x0002b7a0c7fbe8ba,0x000c736f36c17e51,0x0000000000000000}}, {{0x000618a7bb29e0e4,0x000c09c2bff10aed,0x000781dbe57f3993,0x000965b0e2b9baeb,0x00005cf5dc5bd4b3,0x000ce5975c6e0f92,0x000471ab0fcf2bf8,0x0002a2d43bae9f5d,0x000bcafa18f22cc7,0x0005911e3b357902,0x0000000000000001}, {0x00057df200a9fe3a,0x000b50d956c845fd,0x0007f211bf361887,0x0009b4007c382ac0,0x000ee4f517e7f4f0,0x0008256df5e905bd,0x000fa86a9368d1c3,0x000a7df56d37c426,0x000efab6ec26a5b8,0x0005cdfe9cfac9c1,0x0000000000000001}}, {{0x00082202f99826cc,0x0004867eca10dd40,0x00071f5c4e281cfc,0x0007b5da880b8221,0x000325e5cd3e67f8,0x000671c0e0906564,0x000df4bd6ef65d7c,0x000c8a693695da96,0x00076e79dcdb1aea,0x0005bd96f080eaaf,0x0000000000000000}, {0x000240c6e69e5a49,0x00080c138884ae0a,0x0002f7e55e87844e,0x000a57d17ee0d45e,0x00033a1990475a82,0x0004fc5139e3efb1,0x000093a8d1fcb820,0x0007e2fdf23f8eaf,0x000aec2eac127538,0x000a0742581e77ed,0x0000000000000001}}, {{0x000de604b9db6d8d,0x000262da62b65572,0x0009db8d0d3fb7d9,0x00067b7f8e9c2aa3,0x00074f2912d3c9b8,0x00079e6d831a5ad6,0x0006f3cc6935b1c2,0x00009a75e08b8223,0x000aaa28cfcf8f6f,0x0004f75ff407271b,0x0000000000000000}, {0x00024706c120a90c,0x000b4f991d9aa4ab,0x000767e06952ed85,0x00006ffc0793e3c1,0x0003d6115d975f7d,0x000c57472c131644,0x00024430b8651df9,0x000bda1a64f28b97,0x0006db846f1bbd8d,0x0002f562aea1650c,0x0000000000000000}}, }, {/* digit=114 [{1,2,3,..,}]*([2^456]*G) */ {{0x000d810c86eab937,0x0008e6e6eb51bdd5,0x0009bc2e3a0e4219,0x0007e391c4b3dc48,0x000736ed77fe5eda,0x0005e60972cd0e3d,0x0001aaa05f70f41c,0x000db07669f426a5,0x0005914839830a47,0x00029045b98cf434,0x0000000000000001}, {0x0009d9c576932524,0x000409f4c3b8bddc,0x000d467dc9295086,0x000bdef23e6cf0fa,0x000729684c1e0fbe,0x000c3a23011daa3a,0x0008c4ef40ca0da8,0x00034dda12c0850f,0x0002c5e51990ccbe,0x000494c2f0adaf8f,0x0000000000000000}}, {{0x00087b36a390065e,0x000c93a9bb0064f8,0x0004572329d651f2,0x00010e01d988aed3,0x000be48541e9e6f5,0x0000ac10a8abc023,0x000b700a8621efc9,0x0003eb208400f943,0x000d85b1c768bb3b,0x000f42634af0db64,0x0000000000000000}, {0x000e0a10a250b4be,0x0000634e42e593a7,0x000adef0026acaa8,0x000002da6f2f96cb,0x0008dca66aa2e955,0x0005a69e8157271d,0x000f32666dc76291,0x000c378977ddcf29,0x0000e5eaa07d6619,0x0002a548e47a94e1,0x0000000000000000}}, {{0x000cd510985c6ead,0x000d1cc399a1876d,0x000fc77243f5c966,0x000c3b2c4abf82c9,0x0001efaf22c713ae,0x000a22e1704988df,0x0002a2d8f28a287a,0x0000f724ea967d19,0x000ed48e76179ade,0x000ff318acdc5b8c,0x0000000000000001}, {0x00063196ac8ad685,0x0002708e70052b0c,0x000d8ff45f4a08be,0x00064862e9bd37fa,0x000efcc39748e461,0x000dcfa2843cc067,0x0006ae8688367317,0x000b8aabfd38c458,0x0005642ea85ecef5,0x000873af78e84b81,0x0000000000000001}}, {{0x000b763fd4a23b33,0x00004ce905f61100,0x000ad5b3ffa31c96,0x000817bf059b27d0,0x0004f957d997fe85,0x0008adabfcc9cea6,0x0002fa1bf24cb58a,0x000afe218a3174dd,0x000ee69ca08cb0de,0x000fdf310fed00cf,0x0000000000000000}, {0x0006e131eb000160,0x000a4d18c779a4d6,0x00013180dd747a1f,0x0009340c23f27ad3,0x00004df4a2f35316,0x000ec77b35a8c2be,0x0007fb23a1f8aa1a,0x0009e69edc272eed,0x000d58ddb6110abc,0x00042ae7590226a5,0x0000000000000000}}, {{0x000f3cc8ae818a77,0x000f54ede150dbf6,0x000c2f06bc371295,0x0006ab2d173c2266,0x0007fda0b8b46bd2,0x00070909e3958aad,0x0005242beb035184,0x00006b5aad800c13,0x0003a70dce6b782b,0x0007761ebe42a4f4,0x0000000000000001}, {0x000ee87f40792877,0x00080b5c7acfe8e9,0x0007c5775efcb053,0x0007bf0a2d540e71,0x0008c839d644d450,0x000d1ff451c6b81a,0x0001b7ea45f8834b,0x000306bfc9c3c653,0x000cabe92f1a607c,0x000c13152a3731fa,0x0000000000000001}}, {{0x000ad1ff805361f9,0x0003b3536327ce4d,0x0005b0b62672d1bf,0x000ddf3847367af0,0x000278798d158f13,0x0004fbc252a948f1,0x0006fc03d0fe92b8,0x000c0138676b978e,0x000ea4ba8ef9334e,0x000f98b13cf22496,0x0000000000000001}, {0x000ac5c627d693fd,0x00015f19d6d21fa8,0x000b4a2fb70b6705,0x0002c39928de441a,0x000db0fd9e912476,0x00096888c13371fc,0x00013f185fb68ee8,0x00092d86c189d0e2,0x0001cf6facea1f84,0x0005b949b94eff15,0x0000000000000000}}, {{0x0003e85508c930d5,0x00050167c798885c,0x00018ef2850f4f27,0x000547f00d7f6b01,0x000899cb15ed2f40,0x000bc417a989d6f1,0x00008165c9378941,0x000bb0e0c28f2218,0x000839d9572ddfe6,0x000d6ab0b70e2e95,0x0000000000000001}, {0x00092c31b5a755fc,0x0005623261be8d00,0x0002ed776ec81547,0x000ed7b92bc72da3,0x0006d943fbdb47af,0x00096c45167b5a5d,0x0006fef44f208158,0x000d5bd5c28e23f0,0x000da432e8f4f6c6,0x0007b3355da25eae,0x0000000000000001}}, {{0x00076c8ab8c349a0,0x000850693d15749f,0x000d18a6991254fd,0x000f60f54944e4ef,0x000febc73879cf78,0x0004c63e00125696,0x00042f68e1e2dbe0,0x000b688fd93a88e1,0x000f1e83abbe7321,0x0003aaa7b2fa13d6,0x0000000000000001}, {0x000caa293a9d97c5,0x00059519ff3b97cb,0x000cedb5893b39ad,0x00064ed07e59369f,0x0003315852af3473,0x000d5a40d47c32e9,0x000386582768fe34,0x000453f8e4c60653,0x0004a96dcf43bf2b,0x000e332542e1828b,0x0000000000000000}}, }, {/* digit=115 [{1,2,3,..,}]*([2^460]*G) */ {{0x00011a7aae3fec0f,0x00081883626ec806,0x000aebe504491b56,0x00031dd2ecc113fd,0x0001068171e0f3fc,0x000d2fbb6b5fdadf,0x0000ee0e94a492b4,0x00090723f06e06c2,0x00016b906e2fed2d,0x00033b2f32d5d083,0x0000000000000001}, {0x000731c43f27e685,0x000c912924bed063,0x00058df5bd8f8996,0x00080e3a04d16a64,0x000303ff6f14cb47,0x000f56c8175aed03,0x0003011b62e0f3ec,0x000eee8bd1d8f816,0x000a055be5c28fa8,0x0005635edb8d9c9f,0x0000000000000001}}, {{0x000eb4c2e9d6a36d,0x000f1c0e66e6ba0d,0x000058a747cb2451,0x0004b10a20962d66,0x000e1da104e82021,0x0004693d32e594ca,0x0003bb7f837609cb,0x000e53eda7c5059d,0x000b602751dd16ca,0x00007ac67ede2a3e,0x0000000000000000}, {0x00038202cc49b145,0x00003535c208aec8,0x00056079145b2fb2,0x000814d455be9713,0x00082fd8f0bb395c,0x000c755426c09f67,0x0000b748edafadbc,0x000deaf4bc3a4ecf,0x000bff049553943e,0x00057ee542c407a2,0x0000000000000000}}, {{0x00058193376e77cb,0x000e72c0bba4380d,0x000bc54c3a89ddc3,0x000dd63a1bbc6d0f,0x000bf1518f660f2c,0x0007e5bf5faf2f62,0x0004682bfe7727a2,0x000da33defeb7b16,0x00032b5ef40ec257,0x000a0e902b2e8961,0x0000000000000000}, {0x000ab468387524e3,0x00024e69a88271e3,0x0004545479e82998,0x000121a7373761e0,0x00093e3b1f753397,0x000463acb40aaebe,0x000cb721af707dad,0x000c14e152331d6d,0x00065553048e5280,0x000612aaad009d91,0x0000000000000001}}, {{0x00092b39f964e28f,0x000fa7cfd7976897,0x000f279c07ec556d,0x0001cf40d7670e8c,0x0007b5e04abdedad,0x0006fcc19990b137,0x0008572f5067ad94,0x000a28101c966a08,0x000b5e33c2ad58ac,0x000eb0e333e24c43,0x0000000000000001}, {0x000f0361a475ac89,0x0002dcf79463ef54,0x000dd053538c22ce,0x0001013b4e6817ca,0x000b44b01a6e12bc,0x000d109d85844a6e,0x000b985bfdaef54a,0x000f6830be544481,0x000fd8dd0297f121,0x0007cb6d0b67a68b,0x0000000000000001}}, {{0x000ba65ede23b338,0x00026845dcbcdc45,0x0000a0b1cdddd83e,0x000092ea63968b4f,0x0004b71e6e72d35e,0x00046c5ed03f1ddc,0x0006efc5a166bbfa,0x00090de0b5f6b7c7,0x000445136c1387b7,0x000ba78923450ab6,0x0000000000000000}, {0x000a850194005e74,0x0009c00cae44ea99,0x000e5e17b631e4af,0x0001c80d51c0dae8,0x000120c3cbe08ee9,0x00023c8041a40936,0x000ada73446b0eda,0x000643d14026f215,0x0006fbac37813fb6,0x000fc70031b68bb2,0x0000000000000000}}, {{0x00075ab901660b40,0x0001e645ee7e0ee2,0x00037b06a37399f2,0x00080496e9bd12b1,0x00026a5d50d58960,0x000c1e3f3705ba3f,0x000274a1d4a00817,0x000d2d00866a4d39,0x000f146bf0317c40,0x00024e2ec71ea064,0x0000000000000001}, {0x0003c199f5c7f563,0x00062e4f78f16893,0x000a194ad2a3fb13,0x000080225259655c,0x000bc5898f9da5f4,0x000553edffd8a6c1,0x000e20b2793c4797,0x00041ea73083e26d,0x000a2971a533d937,0x0000e54fd22035b2,0x0000000000000000}}, {{0x000f9d4de9a27585,0x000400debb5987f8,0x000d526ec09e3156,0x0008bd03e0023f66,0x000aed7d715cc557,0x00058cc9c03099f2,0x000506b4417ca0c8,0x000d23b4df572ea5,0x000c5dc147420ffb,0x00032899652bdfe0,0x0000000000000000}, {0x00031987cf8e9148,0x000b259461ad7d0d,0x000c859a4a7e6bba,0x00030e2b3d2a289c,0x000e9be629139087,0x0003904cf1cf6e14,0x000cca9dab045a7c,0x00082a43de3eacb2,0x000d82c3afa439f6,0x000decd187ae70d4,0x0000000000000001}}, {{0x00087b4497808581,0x00012be293d33455,0x0004ce4906c6f8ad,0x000a66938d521bfa,0x00046a914bdb3b26,0x000ae5f6e99dc3e7,0x00059dbb0881c2e3,0x00009191a1b5ac25,0x000c6a97a72e5343,0x000ddd07226ad4a6,0x0000000000000000}, {0x00039e249234483b,0x000669419af2063a,0x00042122752c72bc,0x000aa7e19a44c7a3,0x00011188ac573c28,0x0009a3360e14ec6b,0x000bc0bc86245880,0x000741e192993af7,0x000d8d75742bd481,0x0006cd8768555ba8,0x0000000000000000}}, }, {/* digit=116 [{1,2,3,..,}]*([2^464]*G) */ {{0x000ebaeb9266fcb3,0x0006c49166afc8c7,0x000b1a4fb9f8df09,0x0003a2759ef63e0b,0x000ded0e62d1d0a6,0x000215cb79a13c16,0x000942482d5b46ef,0x000a5cf390334543,0x00039ce21c9b239a,0x0000a2fcf03ed34a,0x0000000000000000}, {0x000466a8adf517f0,0x000775523be0b6d8,0x00074759167493a7,0x000284c64894bb12,0x000e2864e9ca25e2,0x0008b7f98fd07d26,0x0003fdb6d6620610,0x000ef64b5a668e1e,0x000d31c44a0ba6ca,0x000891dac14a11ed,0x0000000000000001}}, {{0x0007e005c5b2f805,0x00010b6d99c24dd3,0x000813da1409fa02,0x0008bf13d53cbcd5,0x0005bb6d8655f948,0x00021f224e5b2d05,0x00077dd3ba305b4b,0x00005337f568059a,0x0008b4b1e783aa9f,0x000d6ce8c56442b8,0x0000000000000001}, {0x0007e0acb71f23b1,0x0007f2e0e90fde9b,0x000336f8ff1da186,0x0004751614e3d072,0x0003187e51c7e8e6,0x0007ef17101ca72a,0x0008a9761c42d892,0x000ebb69cc0c641d,0x0002903e96138250,0x0006b8d2873a54c1,0x0000000000000000}}, {{0x0007b97b6b68155f,0x000799e78b707b09,0x000e1f75bd19e80f,0x00035096285e6628,0x000d9b8661ae0f1a,0x000fe90a8911dc8a,0x00018180a1d7fb12,0x000733dbb76ae258,0x000085cc47bdbf1a,0x0008c417eada4711,0x0000000000000001}, {0x0006498715c0f18b,0x0008cd3093549e44,0x0007888a48d3a384,0x000a0d971c9394dd,0x000f79cc4aa385aa,0x000d44729501e42f,0x0002ea4042d9ad6a,0x000c1e43ab081b30,0x0002a374ef11901b,0x0009de3ad60e42b4,0x0000000000000000}}, {{0x00023f47f06415e1,0x000ec51fe7219c05,0x000bd8a88f411a49,0x000308976713e8b2,0x0006ee0f84892d3f,0x000957e9fa410c61,0x000903d60b015584,0x000f41fc07f1fce0,0x000fa3ce182117ef,0x000654b039b5693f,0x0000000000000000}, {0x000f700d59c0d688,0x000bcc693fd9aa04,0x000b8b0e7fea0743,0x000182c181c35812,0x0008864896cc8fcb,0x000c77cf499f019f,0x00010bba6594c508,0x000e88406e142c41,0x000b45fd50fcaee7,0x0009894dc1ba3eb8,0x0000000000000000}}, {{0x0007488ba3fe2367,0x000752106ad62ea4,0x000980bc62d3b8ad,0x000328ef733708df,0x000d47b00f88c069,0x000f6bb0176a2cf3,0x0009f6480ef1ba36,0x000ac0712001822e,0x00032f8aac418a68,0x000ff326047c12c9,0x0000000000000001}, {0x00039bbf3cc8d8c5,0x00091d5e4cf0789b,0x00042078d73c679f,0x000b71a650f7aeca,0x00082a530b74abff,0x000a71711bd8405b,0x000c3bb0ac95d510,0x00094cee94894b3c,0x000906c5e7b66990,0x00030a027cdba56d,0x0000000000000001}}, {{0x000c446c47eef0c8,0x00044a0878421c07,0x0008722c55cf2755,0x000ec763424a48fb,0x000f4f6b5b3b9028,0x00078d4fe3ca8f7b,0x0003f4277d82e20f,0x000fbc6300a704e2,0x000a908b8f5f71bb,0x000b090bc8e8a53a,0x0000000000000001}, {0x000dcad6549fc8da,0x0004e635d31de3d0,0x0009ac9c9dae5fbc,0x0005d812525deba7,0x00028465a1ffb0b8,0x000039c002085422,0x000d1431962a343c,0x0001729577d460c9,0x000befcdb0fe4b63,0x000f982552806705,0x0000000000000000}}, {{0x000c16470afeefa0,0x000c0df482969752,0x000988294a6b7345,0x000192c323f56fda,0x000ece866a0fbb9d,0x0003fb58e433eb87,0x00044e600bdf291f,0x000bc9a43f5fab4d,0x00060683951124ce,0x00065a7c641677f4,0x0000000000000001}, {0x000ce490f8bb04ea,0x0002e7ad3382ee72,0x000272231533e6b8,0x000186b13ffe5f10,0x000cc8faf0cc5e1a,0x000c709ed2b173b2,0x00067e514381962f,0x000cd58bc198455b,0x0006402864604346,0x0009d46f62db1463,0x0000000000000000}}, {{0x0007bb607e896c28,0x000e0a894887a4bc,0x0006eb1e97614230,0x00003e71e2c653f8,0x00096dded494be93,0x0008ac95d09fc0dd,0x000bea563fba0619,0x0008f3c1624d738a,0x0009df64d4a0ea98,0x0001d5c6ae182338,0x0000000000000001}, {0x000eeeb900454516,0x0006377d7a8b0a7f,0x000a9c345a7de36c,0x000100d5611067e9,0x000806bcdcedd0a9,0x0002b5dec6f6c68c,0x00051f38d7d4a349,0x00022d5061b9ad36,0x0005c9ea7f739c0f,0x000ee734e6cedbd1,0x0000000000000001}}, }, {/* digit=117 [{1,2,3,..,}]*([2^468]*G) */ {{0x000eb05013cb5aab,0x0009afca55bd420f,0x0009c3c71fd8695f,0x00000cafcc6e5ed1,0x000728edc89ca3d5,0x00076471854e21b8,0x000201f0ff872ac7,0x0003e23036d8ee45,0x0002c13f7c8bee8b,0x000707a1d51a1e5f,0x0000000000000000}, {0x00022b011bf68532,0x0000cf529ed8e280,0x000b8a477a52b6ff,0x000cd2f63b6e8238,0x0007c291c55c9cf5,0x000f4796ab42ab24,0x000c0989f93937b3,0x000bca7b47aa5dbf,0x0006f0a6b7620e79,0x000f58dd4ea00729,0x0000000000000000}}, {{0x0004f87aac9cea1d,0x000fabffc3ba2342,0x000a3b2b167162b1,0x00073da5b86c7978,0x000769b5f991d83e,0x000cb3d9088d484c,0x0004542e085b4392,0x0004eba2ea8f2806,0x000c46cb82b91d2b,0x0008c0e83321f8cd,0x0000000000000000}, {0x00097601a9d31426,0x0009ef4a0c50dffd,0x000fc4b8056305e9,0x0000c1c8a29f6e86,0x000d4be1babedf5b,0x0005e98d4d558d2c,0x0007fd7d17d7bc87,0x00009a0a33b745e5,0x0008c2a2bc3cf9b6,0x0006235277b76d2d,0x0000000000000001}}, {{0x000ad9eb395de05c,0x00050bddffa75224,0x0008d48f88a50e57,0x0005bffe3c2175d5,0x000aded74a44ab8f,0x000f36097483dc36,0x00041e5290fdaaf9,0x00051f0f28ee6aea,0x00006d6a082ff0ae,0x000068e3568c35a6,0x0000000000000000}, {0x00052b137174e56f,0x000a242808c3c521,0x000cee713ccf3a0d,0x0007f4523126e210,0x0009790a26049fad,0x000293cb237c8c65,0x000391754b82c700,0x0005060129b75ceb,0x000ad78c9cbc1be8,0x000452fab6d7a60a,0x0000000000000000}}, {{0x000614e7a62b479f,0x00091b1806f1503e,0x000c937295d07735,0x000468f3b432690c,0x000027af2bc376d3,0x0001568b1fc765b5,0x00004c84508081cf,0x00093b08d2fa4f2d,0x000aa23530d43841,0x000eddd4118eb0fd,0x0000000000000000}, {0x00095d916a74bf7e,0x00052f879c30fb73,0x00033e906c3732a6,0x0009ecd6d707078b,0x000764fe7914feb0,0x000164429576e244,0x00070601ef70830f,0x00038d1a94c290ff,0x0007e067e8e38b39,0x00004d7b7a7e7934,0x0000000000000000}}, {{0x00092dd8b3c6e87d,0x0006c49275954a31,0x00016b291ceab935,0x0002ae4fca80283b,0x0002ae3f769e974a,0x00047d8e3a1a96a2,0x000875bc17f080fc,0x000a5eabb84f45c1,0x000e2f2661df31c8,0x000663147f43e69b,0x0000000000000000}, {0x0002716571c12164,0x000b5580b0b11754,0x000bedf056c51a6e,0x00019d3572bd29fd,0x0006ce46ac6d5756,0x000d711d909ced7c,0x00056c0ec115b51f,0x0005ebe8c1ea4d63,0x0005d77cf7a0032e,0x000ddbec9919b1e6,0x0000000000000000}}, {{0x0002437a972f2c78,0x00015b5e5010e549,0x000fb968e48079c6,0x000ee7041338af95,0x0007cad3cea2147a,0x00063a330c01aad8,0x000ecdd3002cfb58,0x000bf58e568343ac,0x0007567e97251d0a,0x000b568be5a71fbd,0x0000000000000001}, {0x0003982ec0a47e47,0x000862df20207b07,0x0002c656e08dda4d,0x0005ad59afe9aa6b,0x000ee04d8bf8d524,0x000d84cab42cc2b5,0x000ee837ff8c6d4a,0x0008b691af448525,0x0003b100c345fb36,0x0000d061abec1e80,0x0000000000000001}}, {{0x000c9cc4477a0393,0x0002f0a9ecb165af,0x0008a80444bd4fb6,0x000a9d4dd001619b,0x0000b10c19a21051,0x000801b4ef3f9384,0x00076219bc4d71f3,0x000ea7190314526d,0x000da93e188e8697,0x0000967b67776acf,0x0000000000000000}, {0x0006ab2717f542c5,0x000ae82426abc0aa,0x000641af35023777,0x0005dcf6c7153a96,0x000977e0ee60ca55,0x000c371732ddcc64,0x000063579dd744f3,0x0004f34c496af4bc,0x00000f9df0536028,0x000b1c2a26167cf5,0x0000000000000000}}, {{0x00061fdc0b1fc134,0x00059fe59da03f7e,0x00051831e7698bd3,0x0009f81df982fb68,0x0001c64253ce4407,0x00084a0c0fffbd0a,0x000fd2724ab08376,0x000aaefd7b900fa3,0x000017be08cd54b9,0x000359398932034f,0x0000000000000000}, {0x0008bfed571b358d,0x0006e5bd73f12c5f,0x0007574722cbd9b4,0x000789de672fc532,0x000cf9d4c5de795b,0x0008e00647313e84,0x00001e2002f19344,0x0007649a15d6dda4,0x000a4f04c96114ef,0x000ac34a9dc08537,0x0000000000000001}}, }, {/* digit=118 [{1,2,3,..,}]*([2^472]*G) */ {{0x0005e5ed4ea72f88,0x000dc27eafbd5d75,0x0008274c8f222817,0x000e4b956ed11c56,0x0002ac506cd96a0b,0x000c56121cfca3c6,0x000e3c5160f64376,0x0001cd969d9794e1,0x0002818ba2a1b9ac,0x000bbd5d12cb946a,0x0000000000000001}, {0x000065269838f81f,0x000a256eaf242367,0x000743908912f4af,0x00048d332342e954,0x000f75565f855ec0,0x000e4ec59a3a8816,0x000505255b015d48,0x0006bf898ef06a71,0x000af90ae385313b,0x0001d5415dc8688b,0x0000000000000001}}, {{0x000115486df6f2ba,0x000803b08c738eec,0x0002302443593e59,0x000e60eb4f00e934,0x000e57c91438ebdb,0x00080e89c523e859,0x000d75cba0053e05,0x0000d11317c9b329,0x00035e5703d38955,0x0003845aac6426d2,0x0000000000000000}, {0x000349105fa06b94,0x000e9b21c69e6c42,0x000f70eb1519a81d,0x000827ae2990539b,0x00048fe9bf0bbafc,0x0008dbb3c1ee9dd5,0x0002a908c4d4274b,0x000cb7224476f3be,0x00028346b6e6842b,0x0003ad39da0c7384,0x0000000000000001}}, {{0x000a9a342fa007b1,0x00065415bb7a90ea,0x000dcc6aa0c26771,0x000a1f0bc720264a,0x000b5e93f7bc1986,0x000bf6b3fca182f9,0x0009a7b5c22f84c1,0x00087bdec7ad14eb,0x0008902c942c3b07,0x000a69d7973e7810,0x0000000000000000}, {0x000230ff44676602,0x000d3064b8821220,0x000d730a5228928d,0x000ea087c0f54e1a,0x0000abe8035de528,0x000d9e98d62188b8,0x000d85f12fe3f391,0x00095d1c13b3c4b4,0x000c9a4940436d0a,0x0007d2cc5f243602,0x0000000000000001}}, {{0x000c484e2708d61a,0x000e14446b62d85c,0x0009c0fff451d84c,0x000a49ca08f1ae70,0x0003d71899e1ae53,0x000709a90d9917f9,0x000f39b12fbb0503,0x000038af72a2045e,0x000817cd90b8cc9a,0x0002f352b4ed83f0,0x0000000000000001}, {0x000a71d48ae023ef,0x000d8744e50d53a7,0x000192ec22667e7a,0x0002e19437867d3b,0x0007124825f0cce3,0x000aa41f07fce902,0x000fc674b8262125,0x000d1f602e03c9ce,0x000f93cc0c071ae6,0x0003fae4c52caef9,0x0000000000000001}}, {{0x000d102ba58b5201,0x000cb021f49742da,0x00078984de6430a2,0x0005002098f1e552,0x000c9b804a37766b,0x00095479cd052eaa,0x00083f87dcee9cc2,0x000ce159b125b614,0x00001a384dc69331,0x0002e4ec5a2f8699,0x0000000000000001}, {0x00049fffc681e26f,0x00001b52ea90f687,0x00080117445f69ef,0x00093fb5f32e704c,0x000d36110b81abea,0x000a3e64f4ffada3,0x0000ff99dcba475c,0x0000eb1b968c2040,0x000ded29d4be59cb,0x000ba78061ed859d,0x0000000000000000}}, {{0x0004949755c59603,0x000c796691a84904,0x000a8445d0aabdba,0x0002396cff6a7bd7,0x000562547f935def,0x0009038b91c344b0,0x0001f20274812ef2,0x000e1fe565e5087b,0x00074866fd902829,0x00032844aad6b8f8,0x0000000000000001}, {0x00092e9251d05a0d,0x000328420cd4a328,0x000e00dfce4ccaef,0x000beca3a94d516d,0x0000fce64bd11bb9,0x00054cb1e99e5269,0x000cfc1bfec9624a,0x0004e634fe2023b3,0x000e53481128c3b5,0x000cd2258147276f,0x0000000000000000}}, {{0x000e9ad8d783865a,0x0008e5a58d54402a,0x000e236d64e3be62,0x000daf46f4aae16f,0x000049ba7000cd7f,0x000deb437c36e86b,0x00025e5a9179d63e,0x000fb30e5ec5adff,0x000fc4d691408156,0x000d8b4dff418608,0x0000000000000000}, {0x000c4eed479219ce,0x0008e4d5ead8e114,0x0005f4f71316535a,0x0001c636b70e9489,0x0008aa2310479eec,0x0004e1dcd4f2eb70,0x000474c99b5134b7,0x000ce4754e99035c,0x000218919b4c0dad,0x000e1d1dd3f97981,0x0000000000000001}}, {{0x000cc18c358773b9,0x00036bf6385f12eb,0x0008a0c24ba8caf5,0x0003093cd83891ca,0x000f5b8c3762108b,0x00041e3399b26a0e,0x000fadfca8c426db,0x0004173bf6760263,0x000a6677ad40bf58,0x0004eca4760acdd8,0x0000000000000001}, {0x000c42b8b4207fa1,0x0006dc5a60d34efb,0x000a367e08d67868,0x0008cead3e942c85,0x000409d289bdc2dd,0x0004b034c3a6d1bb,0x000889304955940a,0x00080034f3684e43,0x000808a7cddeee0c,0x0001148f3d9aa263,0x0000000000000000}}, }, {/* digit=119 [{1,2,3,..,}]*([2^476]*G) */ {{0x000df4a3fd3e1bab,0x0006287d84daca3d,0x000d7eaf57017e3e,0x000d1a4e4870b354,0x0004c26a3e3ca9fe,0x000ce1ea5e5710e0,0x000709e17a2ff920,0x0000f8a3bc06ee67,0x000788ab8c019a66,0x0006f43d909c0fdb,0x0000000000000001}, {0x000c0c61eebda5c3,0x000395c130704b51,0x000762ffbcb5d086,0x000f660bf6639983,0x0001646d9fb03337,0x00065cf06a8fa37c,0x0005f2e3f14b6d28,0x00088227d360e736,0x000a48fcdc5c3e58,0x00059e8c2eaf07b6,0x0000000000000001}}, {{0x0001ce2b5f2dc50d,0x0007e39f8c4d01b0,0x00078d34284f417d,0x000d157acbf04214,0x000c0c4238071f59,0x000b0a1e05f8a594,0x000d81bbaf85cdc7,0x000d1d1329e8c9cf,0x00068fc55c9be4f2,0x00029b5c20884e31,0x0000000000000000}, {0x0009fd4109cb4727,0x00021d96d542276e,0x000d61e57db16c16,0x00052da58656adf3,0x00089d546ecce2da,0x00041508ee2098e0,0x00011997499c874b,0x0006f525839d9cf3,0x000de08e59654896,0x000e511cdd85c0a0,0x0000000000000000}}, {{0x000db13610c4d993,0x000192018344e51f,0x000cb8a7e81016f0,0x000425ff1ca2c27e,0x00047a8df5318c36,0x0004872bcd56d5d2,0x000d142a2e0d2618,0x000a83feb22e4866,0x00013dac70999b14,0x000ed007863be6ab,0x0000000000000000}, {0x000023bbbd62b467,0x000e6ef8f48d21ce,0x000ea9c5f9c35940,0x0009af532bd76e0a,0x0000f8ff97911a1f,0x000efcff41750c50,0x0007cfa3985ad13d,0x000136812ef99c02,0x000319ee534694b3,0x000b9d9722dca85d,0x0000000000000001}}, {{0x00040d25bac4c923,0x0005026132b9fa82,0x000ddc2ef3e74ec9,0x000151b0a9db4e16,0x000ff5ad95c1429d,0x0008144cde9bb57b,0x0000c02f2a19e480,0x0005655b0b6aef98,0x00038725b1f2df6c,0x000672346457ed21,0x0000000000000000}, {0x0003077ffe12bd18,0x000e682804b9bb8e,0x000b8a3a7328db75,0x0007b6f50cb1bbec,0x0007a823e8549b58,0x000d7be7a7e70575,0x0007103b60b8617d,0x0004131d7bc32367,0x000713f91128ac22,0x0000deadb3b9bf03,0x0000000000000000}}, {{0x000b46eea58e4f6c,0x000e8500cef9c4a5,0x000e36179b50381a,0x000498cb317e7dbb,0x000df2d824ab9ac6,0x000aa97d96328707,0x00068fd80e79f5f6,0x000ee03799c5c193,0x000688d4b109d20b,0x000fae5dfd91a5a4,0x0000000000000001}, {0x000e4aa8649aaa1b,0x000caf8a4a894ffc,0x000f0a6af855f3c5,0x000fa6ef0a082826,0x000564cf46392869,0x000d9060255a7500,0x0007688b437590a1,0x0005fa2a21425afd,0x000dd69d65b91f19,0x0008045302895146,0x0000000000000000}}, {{0x0009a872aecfc094,0x000c8cde3af050fb,0x000ebe6b500bec0f,0x0004d4b7e7c4ef2e,0x00094b38a6c4228e,0x0004f9fb0e82362d,0x0000dbf4e229d20c,0x0003a6e45bdfa369,0x000b1c90f730c74e,0x000306f2fc481fa7,0x0000000000000000}, {0x000e496c4b887a36,0x000e6ae46148f8e5,0x0004268188f16f8a,0x000cf1b360936452,0x000ea828f2ec9dce,0x000a581be5eec097,0x0000a093e062b3a8,0x000e4da12b498543,0x000b50541562092d,0x000eae33c27b17cb,0x0000000000000001}}, {{0x000bed4ffad0684c,0x000bb264e57bfffb,0x0009eb6b035825f2,0x00013466fd8b6643,0x000ab9c3537903c2,0x000b0366be7313de,0x00096ae2121723c9,0x0005953e87c3ac29,0x000b6974bbd38278,0x0003e43a30236cf9,0x0000000000000001}, {0x0003b2707ffdea7f,0x0002da68809f795f,0x000374c5228ca4a1,0x000ef9a132cc5a86,0x0002bae5f8c0d15c,0x00061ce20672616f,0x000abed75c41da6e,0x0006a5fc5af7de33,0x00076a4d15065912,0x000ed44c16e78857,0x0000000000000001}}, {{0x0003498018e534a0,0x00031b029f064c8f,0x000b893aedc07be9,0x000b0eea14f71f6a,0x000eee179067b242,0x0009f6bf528af895,0x00020985e852a279,0x000b94bc19691d5c,0x00005deba296ab7d,0x0000b231b9475f76,0x0000000000000001}, {0x000c45d63f8d3bc5,0x000aab0d9145a0f8,0x000bc0cd8bbb3a1d,0x0001299d614875d3,0x0008bad650d624f5,0x000b91d8407baf74,0x00054a383b9d385d,0x0006840ae765f5cc,0x0005a54bdbe2653a,0x0002865728a0edab,0x0000000000000000}}, }, {/* digit=120 [{1,2,3,..,}]*([2^480]*G) */ {{0x000e419064732d33,0x0000fb9f1fdd6e2b,0x000b458dd169ab15,0x000b79def3f55fa5,0x0001fd9b88ebfb1b,0x000b8b17a8c1d98e,0x000e6b37f6beb8b7,0x000dbc72340b6c86,0x0007c19d37bb70ed,0x000f6867a99418dc,0x0000000000000001}, {0x000a4a09f22c0fb3,0x000bb19cb6bc1256,0x00077d8b51c8ded9,0x000574809f35ca45,0x000bef1168ba7eb2,0x0002cdae11770b52,0x000ff68ed4f42bd1,0x0003d326b225de9d,0x00037f1445631a8c,0x00012cb14a3c371d,0x0000000000000001}}, {{0x000b0b95f0603f03,0x000fa7f969adad66,0x0001acf774657813,0x000a2615220707f6,0x0002f71d4cd53712,0x000f82a44a2fd4ef,0x000773fd9e262931,0x0002f763ad200681,0x0009b206fe31fd70,0x000765c3a8767fa9,0x0000000000000000}, {0x000a7f8ce84569e5,0x0009a821c3dd4741,0x000e90e3290cc915,0x000cf99306b623fa,0x000d7531760ae9e8,0x0009e7cf282874af,0x0006e1ae6527ae8c,0x0008f99eef73293d,0x00037109e03d3d87,0x00036ee1efdba892,0x0000000000000000}}, {{0x00051928ed074ce9,0x000b292af7a58dcc,0x0005ec5d4bdfb374,0x000cdd85d01fb1db,0x0006e626365656d8,0x00074fc478641e47,0x00016a5e28d244d6,0x000adbaa94ddb39d,0x0007fdde95fd5183,0x000b47ea66d8626b,0x0000000000000000}, {0x0004c9d4962ab02a,0x00021388f7fd2b57,0x0006c23d66031232,0x000a1a6ab2ca0c2c,0x00017664a406bce3,0x000f5497442ca199,0x000866b6f2fc1498,0x000a41cbc3b0ab32,0x000557ca37a277ae,0x000af01602653825,0x0000000000000000}}, {{0x000db75622a8dfc2,0x0005479be9e5c74f,0x000548d39ec29bd5,0x0007942d29c79da4,0x00079c4bc1f5df3f,0x0004a7cecb948e1f,0x0008793b63229ed3,0x000939c1a7d67689,0x00057ad78be3b341,0x00052f2801351b91,0x0000000000000000}, {0x000cbeae6fece889,0x000b3085ddee3b59,0x000eeab1d348140d,0x0006bba941a033c2,0x000b685703aafb67,0x0005046b6423a9d8,0x00075dab832a7c83,0x00015b8c259b9e24,0x00018a6bbb51f863,0x0003a253eb5dc8db,0x0000000000000000}}, {{0x000cca37a85cafbb,0x000b3657f26e3623,0x000787ec793c4d2a,0x000337f7520b9137,0x0000dbcfb7906436,0x00018cfaf22caa7a,0x00044625a502d754,0x0000066c6a130ba1,0x0001212f51d083e4,0x0004ebb9541e99d2,0x0000000000000000}, {0x0009384f4e2ab22a,0x000ff707cf7953a3,0x000aa5f9b05bdfba,0x000626e81b083e95,0x000defb350599782,0x00092399d206f421,0x0008bd9415729d3e,0x0008cf10387904ad,0x0006e0bc19370ad7,0x000b48f2c002a076,0x0000000000000000}}, {{0x000b8bb85d8adb3e,0x00067b9a142f9bd6,0x000fc51be0f979dc,0x000cb118f84e32d8,0x000a7f5b6ca36f9c,0x000a900f565e79ab,0x0003143fcfd2df63,0x000122db9b751516,0x00086015e5f85f9f,0x000bf0e7c48af6d8,0x0000000000000001}, {0x000cbc466d0dec7f,0x000fcfc13f4daf5d,0x000613ac2b0043ae,0x0007d2ec60909041,0x000eff4b79cb6956,0x000e04188e57b5e5,0x00045aa9dd05dcf8,0x0007cd8106c6759c,0x0004b84b0c6c633a,0x00041ee796334569,0x0000000000000001}}, {{0x0008ed21f68b4a3f,0x0009e0f39b982afe,0x000ef033664df945,0x0006109c1245ad2f,0x0004d6578f9c34c2,0x0008e9fc097b7383,0x0007b3121a085c72,0x000365666df584bd,0x0007af58ed558596,0x0007e9fd1e18ec9d,0x0000000000000000}, {0x00017df29af6bc16,0x000dbbf468848de7,0x000d747cd3b7c888,0x000801a051097e9d,0x000f68bb9b824e70,0x00027a8a5f172bbf,0x00074f9f45d5351c,0x00080ba6fcc24020,0x000d4e050d7e5a57,0x000cebcb9d2f1cc1,0x0000000000000001}}, {{0x000b990fe3b9d773,0x000eb81096bf3df2,0x000eb580e653b2d5,0x000cfd31a2ad7396,0x00065cddd150bca4,0x000cde916b4cdae8,0x00019b56ffe74e35,0x00021e7dc0b21b6f,0x00099d8bf333016e,0x000eb146cec318c7,0x0000000000000000}, {0x00030acdbab36d51,0x00089ddd1e911c98,0x000891db5801a0df,0x000f1a5d646bbddd,0x0000ac4d27510e25,0x00044af2f910d55b,0x00024a75bcea08e1,0x00037ae5f37d50da,0x000d372739ad211e,0x0002a2d9d5c41773,0x0000000000000001}}, }, {/* digit=121 [{1,2,3,..,}]*([2^484]*G) */ {{0x000ce74763660052,0x000da3e409da1731,0x000098b5f715b328,0x0003538d607382a2,0x0007bc3ee7b0651c,0x0006d5eed9abf1dd,0x000eb18e8c0d16d9,0x000e3fe464dc1a4c,0x00030d6fa6b9f8f1,0x000cfa359d987d0c,0x0000000000000001}, {0x00047d09810803ed,0x0007b5b97b578929,0x000cc27fc5005d73,0x00040feb2087e2c1,0x000b7dd0d960662d,0x00025ee555f37345,0x000d7c17f3858a72,0x000a0cf2ae739ae8,0x00000ee77dcf4e1a,0x000c12649e41ecee,0x0000000000000000}}, {{0x0008de672d619b61,0x0000ea8326922a80,0x0001a0841b015626,0x0000f8a963e3e317,0x00037806aeb44acb,0x000d9d8a14334837,0x00026bd761a3419a,0x000d2e7a343fbffd,0x00086e32c6d361b6,0x00023ef433219c4d,0x0000000000000000}, {0x00025620f22d4f25,0x00067dd5c03d381f,0x00080f734643a87f,0x00006c5ee876505e,0x0002b491baac4e49,0x0003e07deb178a01,0x000ad060f735b869,0x000576ce5dd8d75f,0x000dd4cd9c97cb18,0x000cbc634bbb55f5,0x0000000000000001}}, {{0x000b9733710e8e01,0x000e73a5711788b8,0x000bf8afcacf73a9,0x000d6725ee57149b,0x000e7fe486c64e2e,0x000322f9087bd5a6,0x00009af08709418b,0x000084990390cb99,0x000a6bb3ab911d03,0x000d2868a69e665b,0x0000000000000001}, {0x0005e749b382f6d2,0x000a9a1034406b89,0x000826ec06265b52,0x000e64e9aec95b07,0x0003982f9a9c5d16,0x0000698b37d7e83c,0x00050d8bbdbeb42b,0x0007c82f4fbc8ae9,0x000adc1e63d423d5,0x000b249310802372,0x0000000000000000}}, {{0x0007033614a6d5dd,0x000fddc5f2fac137,0x000e014aa4b4dee5,0x0004a9b72218fde8,0x000c10e229612a68,0x000cb5b99f1d9b66,0x000eff01796c1307,0x000ec087152271c7,0x0009f171d27930b1,0x000dd53091f21ad1,0x0000000000000001}, {0x0004c873e4172f54,0x0006ecbd512368a7,0x000d3ea21d4bc31a,0x0003a95f62eff689,0x0007c73a33474bd4,0x00088fa97a141350,0x000b4d3b01846eff,0x0005fbac8f6a8f06,0x0009ddd58dc2a301,0x00001f7b911f1a15,0x0000000000000000}}, {{0x0002e681058bcd0b,0x000ecb766f6bc98d,0x000866fedccaaef5,0x000b2e2473204d11,0x000f6e18757016ad,0x00011d59effc1a8a,0x0002050629e88cfc,0x00093c7bdc024782,0x000a9b2aeb9bb00e,0x000336991f06d2c0,0x0000000000000000}, {0x0001568955531744,0x0008281170681859,0x00050d7be99cf6e1,0x0008cb9d185c0963,0x000f49cfc22a2afc,0x000f9d20626a2a56,0x000ad87b48f04b95,0x000bd1441cc30d3e,0x0003e9b72d43f56f,0x000e3b3843d17383,0x0000000000000001}}, {{0x000e873b05f77e97,0x00071d5ebf3c8d2f,0x0005b9ca7cc32fe3,0x0008798cc245b054,0x000e6eaf83f8b265,0x00061d87bdf09afd,0x00048a529e1b9707,0x00001501c97ba4fd,0x000ca96655ab0a10,0x00042f0ec7beee1d,0x0000000000000001}, {0x000296b82c7a9289,0x00070c171dfdb228,0x0001dac3a3a171bb,0x000b7ea6ad9a13af,0x000251fe361dde21,0x000cea9acd2f8b81,0x0008480e8df3c1ec,0x00038a5f495ca4b4,0x000fd225cb8ecc78,0x000454bc6bffc707,0x0000000000000000}}, {{0x000af33412f12687,0x00015e41163cf0f3,0x000967fdc5a6a476,0x0004235cf9f62e34,0x000b314d06a6a848,0x000820f5665619a2,0x000f11a14ea427a8,0x000ce9a80c44b6a1,0x000f92bed7985fca,0x000dc713540bdff6,0x0000000000000001}, {0x00065826c0cb51e6,0x00030220ec95e76a,0x00064aea77a786d0,0x000cb5ba9e93c602,0x000f020c5b781189,0x000e7b4655282299,0x000e97af8ea95e4d,0x000a8a80a0f194a4,0x0006433581c41d62,0x00066e34a29ca8e3,0x0000000000000001}}, {{0x000cef36ab807b63,0x000040cdf4c99984,0x000c211953a5f8d7,0x000ab4c0faefc5ed,0x0005ca17066a1563,0x000fb2c0940c339a,0x000b1e8517a5667a,0x000c3d2a94a0b135,0x000185e4d4526e2e,0x0001b53c05d493d9,0x0000000000000001}, {0x000c5ced3676f843,0x000195ff470fab2f,0x000ed29f4a221ddb,0x0000868b2d94f5fe,0x0003caf8fcc5069f,0x000dcfc1418631be,0x000998943a070623,0x0009bafa5f731c9d,0x000c5c56c1cc4a06,0x000a82f502e626e1,0x0000000000000000}}, }, {/* digit=122 [{1,2,3,..,}]*([2^488]*G) */ {{0x0009edf282d019ec,0x00099e8e335e18d2,0x0004ace8ce0e046e,0x00001d0f72c0503a,0x0007e9c6d09e242f,0x000998b6c2fcb456,0x0000be40686ceb13,0x000db8fca6af9143,0x000c77e852236ef5,0x000ba3718e1a2901,0x0000000000000001}, {0x0005ae430ab427d9,0x0003d8a843a1b6ab,0x000c9500fb6025f6,0x000b9cb8d803e788,0x000fcea023d9bfb7,0x00003f3ec5cdad70,0x000188da7e50d4c8,0x000f9eb540fd9c07,0x00014ab57822ee2a,0x000574aff12ba00d,0x0000000000000001}}, {{0x0003c20dbe0952a3,0x000480b6013f7fd5,0x000447348d109d4a,0x000fe6fecb6a7da1,0x0006564e8c529d8b,0x000034045fa60672,0x0003ee2a8df68fa9,0x00021796dbc7ff3f,0x000a130fededc279,0x000fe24c3f368ae9,0x0000000000000001}, {0x0002961eb9eed66d,0x000919ed55f27279,0x0000068193a9b014,0x000f317444cb0bf8,0x00096e22227ee32e,0x00047c8b854cb4a8,0x000bf6dc6a73b281,0x000d6804296e2ed1,0x0003e6f8a77be001,0x00084c89b143ab22,0x0000000000000000}}, {{0x0008d791f2d40215,0x00003b05d1fd525c,0x00037b16b3ca30ae,0x00070792a856131f,0x000b7639faf0f678,0x00006b7cf12eff42,0x00098ab7a44f2173,0x0006714e846ec06d,0x000eac350874a266,0x000b56e5920dc3ae,0x0000000000000000}, {0x000d703e34853d1e,0x0002cd53a7cce717,0x000410bff4f394e1,0x00074ecb0bba0cc1,0x000de8fa9da2c436,0x000f5e3f74e2caa0,0x000cc28b148d1eb1,0x0009fc1ac5bad585,0x0001220666fb73af,0x0000c3241a57ee07,0x0000000000000001}}, {{0x0000e99218ea1f1f,0x000ccf21044500ec,0x0000c873630cba88,0x00064f806fd4e4b8,0x000a7056645dd457,0x0002ed87394551a9,0x0008987025ba6b17,0x0005dd01b45fa9a7,0x000ccea3a1f9f135,0x000592807cbab8d2,0x0000000000000001}, {0x0006c96e8e24e119,0x000d921a51e8134c,0x0002ab9759957065,0x0004035ca89e1baa,0x000df057c2aafabc,0x000c0890aa1a6716,0x0006bd3f802387d9,0x0006a39383e5c778,0x000601e4e1f62705,0x000096f226577900,0x0000000000000001}}, {{0x0001d3b5076ee66b,0x000068e996c31106,0x00063f8bf5d922ca,0x00008ed44203a2fa,0x0001df0821d991eb,0x00019d54e602f04f,0x000bf35cd4ee7bb8,0x00015f2609e3729a,0x0009e8e65b2fcd60,0x0001df9e9c109298,0x0000000000000001}, {0x00058eae5edc3042,0x000fe31ba09cdc97,0x0006f52853b56fdb,0x0003df0f5ca36adc,0x0000a54940d61878,0x000902cef58665ba,0x0004efbb68e67641,0x00036806e0aaf0f5,0x000194a89e785e8c,0x0008883379ceb241,0x0000000000000000}}, {{0x0001a19f7b341ee3,0x000076e0e5354bd1,0x0001806a485286dc,0x000d2bf681431840,0x0002c82334b1343e,0x000b6908add258b2,0x000737bf47a5dbe4,0x0007303c531a0b11,0x0003a29d6501615d,0x0009313aaea01e10,0x0000000000000000}, {0x0007b22b906a725c,0x00024ad4ce011033,0x000bf242639d28fc,0x000fa39cd38de6c9,0x000a72beeb0f8fd8,0x0009a0ad9b93380e,0x000c8221fc799b7c,0x000be51116d9d8de,0x000a10526402ca53,0x000777aa2c9ac3b1,0x0000000000000001}}, {{0x0001a723455b8da2,0x0001d0c7c777796b,0x000fb41cc9b1644a,0x0000ef5ce0972939,0x000637a26ddcdf7a,0x0008cf1a639f0844,0x000023a3ce642ca3,0x00098f7db827cdb3,0x0005279eee7f6f0d,0x000565523e47e762,0x0000000000000001}, {0x000fd1b034828d4a,0x0000721a61eafcaf,0x0001ce95f4ec0ae3,0x0003ba2db4a66fba,0x0006525e6f06fee9,0x000817b26fcb0ef3,0x0000265db68ac06f,0x000f74e811cb24b3,0x0006550f9c2bf885,0x0003940f2d2fcd83,0x0000000000000000}}, {{0x000e8955d1b109b2,0x000e1de1d0f381d4,0x0006407a6cf45a79,0x000f2393e689a76d,0x000d3d92aed2a407,0x0005547cc6ac261b,0x0005e0b9e62fcac9,0x00081e2910774983,0x0003d6780dde8f90,0x0003c5c4cab77f7b,0x0000000000000000}, {0x000e052d3f3dc82c,0x00039caa1aeecdbd,0x00024153092958c9,0x000c11b7ca5c0f7b,0x00027c92847965c0,0x000732af643698d8,0x0000367351c0ba1d,0x000f1b1bf491a3ee,0x000df3514ec2302c,0x000b4c4436d640af,0x0000000000000001}}, }, {/* digit=123 [{1,2,3,..,}]*([2^492]*G) */ {{0x0004265bd7179d88,0x00032014b97128c5,0x000fd3dafdfe0b08,0x000b1956b3fd6699,0x00091416a87bbb8b,0x0001dd4344038f86,0x000566c88826c840,0x000f07a8a4b77456,0x0007671e1b2fca59,0x000200797dc52a03,0x0000000000000000}, {0x0007843bbe8d7f70,0x0004f9ee9b4c465d,0x000303b1652fa39c,0x000ae7c4c4a55ae2,0x000263ccdcb67c15,0x000a17fd06da8ac5,0x000c10d8d1d1e927,0x000e5bfc6232685a,0x0003162cd048bbb8,0x000b11c2cffebb23,0x0000000000000000}}, {{0x0002cb202ec3c178,0x000285de81ad92d1,0x000b71b77497dfd0,0x0007a8a10c150a03,0x000bbe99f4ad3f59,0x000f4533b0aef51d,0x0003b27838ed4931,0x0008ffc95a8ebcf1,0x0002cefcf5623ddf,0x00010737c166832b,0x0000000000000000}, {0x000e740d8da2ff7e,0x000624f3d3ab048c,0x000376415ced03ed,0x000fbe5676391c7d,0x00081671ffe7b22f,0x0000390438cc5f49,0x00084a5ae289dd49,0x0008f9a1f5bbef09,0x000b05c4941c6652,0x00083aef77ff073e,0x0000000000000000}}, {{0x000604a9bc6900b6,0x000878e5f51ce9df,0x000b763f98cad97f,0x000f5a1389d3ab54,0x000ab3d0efdef6fe,0x0009be5cf0df2543,0x0002a0d518696763,0x000134850193d832,0x000860abf9047761,0x0004b4f04b3d8de0,0x0000000000000000}, {0x000e57c44a551894,0x000a3fa66238e065,0x000d140af7878a12,0x000de14d55dcc858,0x00061c7b391cc65f,0x000d7dbf324d8825,0x0005d09aa74e78f2,0x0008ed166a4503f8,0x000da0c2a7ad860c,0x0002048d8fe387e6,0x0000000000000000}}, {{0x000505ddc7162a8e,0x0001fb5ed0deab66,0x0005e972cc689dc5,0x000e495fb69dc78b,0x000ca3f1826690c6,0x0005f6186896d605,0x000fd32f66789288,0x0008863f96f8edfb,0x000e644e5dece22e,0x0009b7f857a4d564,0x0000000000000000}, {0x000691ddbeebfc5d,0x0005901566a70055,0x000e1f4e6067fa43,0x00086e62796a672c,0x000b4e5ee14cf308,0x000b327c1a40aaca,0x0002fed3294bd689,0x0009103e56992c00,0x000b1323df8494f5,0x000d7b51fec2bb9e,0x0000000000000001}}, {{0x0009f1b91641749a,0x000415c17bca5ff6,0x000c6d3a845d2248,0x0005f9b6f404856a,0x000cbf400b63630d,0x0003b4ba273b60be,0x0005d238fa843e67,0x00015df9fe916d32,0x000747b338f22dd6,0x000213df0dde0478,0x0000000000000000}, {0x0000235c1fe8e923,0x0003196a6c0855b8,0x0009e7caa33347ee,0x000bc0a45596b47b,0x00011e3fa8377c58,0x000acaedbc6f8b16,0x000fc365c99edd72,0x0002dbbec0f6e0a6,0x0002b70a4b7723c1,0x000a4bf65f3c20c8,0x0000000000000001}}, {{0x0004bf14c1a4d603,0x00062d773ba946d2,0x000a858973ed2e17,0x000af47e821e4637,0x000c4e2f1b685a3b,0x000a24d7fe743f00,0x00011c916f0b3711,0x00019d3f29631796,0x000070eeb3ea27a8,0x000fcf9d0e9d8d24,0x0000000000000001}, {0x000a9e0cc6d6de0a,0x0007d8c5fca34ad4,0x000c81d46494c7d6,0x0008c618856d1751,0x000ea22fc514e835,0x000e085f741c8235,0x000c321d004a049d,0x000bcb516087e553,0x0002d6363ccbbe68,0x00083e572fe7f6b5,0x0000000000000000}}, {{0x000e20ba96faf5c5,0x000e8d8c8a0cc4ab,0x0009b5c593a344d4,0x000c6c34af049395,0x0005aa8d456d94a3,0x000ed953bf7c9473,0x000962cd0b8cc1dd,0x0000c01bb3088b5c,0x000c82c42c7d7139,0x0005bd26c576d9ee,0x0000000000000001}, {0x000ee2f364e79144,0x000e681f5a9a561f,0x00014c6812d4021d,0x000e552f50051d32,0x000f6a99f35033a6,0x000e505a2349153d,0x0001622a1be8e97e,0x00067971f625164b,0x000d441d9fc2328e,0x000d2eb0550478b4,0x0000000000000001}}, {{0x000769c73aea3c08,0x000df9a9593240cb,0x0004e8217f3b057c,0x000ceca2220054ab,0x000c95ba1c2a734d,0x0006500d1322b719,0x000ec571b4360381,0x0006f76e87cb0ba1,0x000c5938559db2c7,0x000397be033b5877,0x0000000000000000}, {0x000b6a77feb075ca,0x000d9cc6a6cde3dd,0x000e49872538f578,0x000e469feaf37819,0x0002ddc9c48cda10,0x0001a6e5450f9883,0x0002d31bf05ea5f5,0x000375cd216a195d,0x0008007e689987c4,0x000cbc358f3e07d1,0x0000000000000000}}, }, {/* digit=124 [{1,2,3,..,}]*([2^496]*G) */ {{0x0006a73f6f2770c4,0x0000f968ca281cd6,0x000827efca6a0867,0x0003a96b180e8f32,0x000809979b757eac,0x000d9223bfbff7df,0x00047dd166015fc2,0x00065475a88730d7,0x000ce16229ea9d12,0x00076d23756de3fb,0x0000000000000000}, {0x000ed537bee27c6e,0x000943e46c7c15a8,0x0004b3f87656d7df,0x000a9213335be530,0x00076cb0ee208db8,0x0004f5fc16b61ee3,0x000c1114ee85495a,0x000253ced62c2d47,0x000641c92453ad35,0x0003e4e1a21d73af,0x0000000000000001}}, {{0x000483ff2c9de102,0x00017f0cb9492bab,0x0001999673c19107,0x0005c7a75ba40ad7,0x00022ec8c1ec861f,0x00078704457a9540,0x0001194ab6d023c8,0x0000daf5008c607c,0x000d394925361233,0x0005ab5bf20a934a,0x0000000000000001}, {0x0008ed3301b16277,0x000b31045574d7ab,0x000ed11cb44f38e3,0x0001af67ab10bb4e,0x000d033cee10ca51,0x000549874c9fe7c1,0x000392d6999489f1,0x000ffcfe4a15a85b,0x000b006a13684dec,0x0007b8baefda3eb3,0x0000000000000001}}, {{0x000e82cbfe7306a8,0x00002e52832eb494,0x000b381c8b461b41,0x000a6e877f0afbca,0x0006b8482ae88f1b,0x000709eb28c8cc07,0x0000cd45fc8e5ced,0x000b1363d1cf0c64,0x00093a63d6be8f78,0x0001407a8e7f6a49,0x0000000000000000}, {0x000fd703c088bf64,0x000708b3415df01b,0x000f82eeb2c8b57f,0x0003ed35407aa69d,0x000449767c6b4a72,0x0002e1a8184dbc3f,0x000d25edffc3e965,0x0003e8855e29ad89,0x000c695a889f2e49,0x00025dae2a995ab2,0x0000000000000000}}, {{0x000c300d63dacf22,0x000f84149cc93249,0x0004f71e87a984e1,0x000ebeada635f884,0x000cac51f48942eb,0x00076c6b878d815d,0x000587460dede95b,0x000883c91cf8c3f2,0x00013e9be5375387,0x00076d4ce987a56d,0x0000000000000000}, {0x000fb20151675f42,0x000bf54bf1c2d622,0x00022da7f9e8bc4a,0x000051b0e7b83f3a,0x00073eda536a6e42,0x000ce8431a9d89d5,0x0002b7a64d23c5a3,0x000007a6be7b3eec,0x000672919b5fb43a,0x000c454a7d18005b,0x0000000000000001}}, {{0x0009f484a29e97a0,0x0005e90aa411ba92,0x00016fc135a72a99,0x0006cfa3c8dd8a3a,0x00066efeed6df222,0x000e66eb40ebb1a2,0x0000f8ad15ad7b0b,0x000e0c3a19929e39,0x00051e3404d13a05,0x000175cf393bacd1,0x0000000000000000}, {0x0006cdbeb4d89814,0x000b884f6ce10295,0x0003138d1321a20d,0x0006528c4bd065b9,0x0003d082878ee395,0x00029465651ab383,0x000cb4e49e6b0dcc,0x000710248d30e955,0x0006e01a51ae9cc3,0x0002fc5567eab89e,0x0000000000000001}}, {{0x000c59218072f54a,0x000195bad5f014fe,0x000deabd55429cb3,0x000b2ab5fb9c1406,0x0006cf39524ff8ca,0x000fbb57c01480bd,0x00018cbc932f5376,0x000c9e4e5da034f1,0x000fb16c36eb8d83,0x000048c80fc4eaa6,0x0000000000000000}, {0x000668aa11e1cfe6,0x000d4f614afa98be,0x0004cadab479a412,0x000864b0b94d7822,0x0002651053a74933,0x000dd43fe6424e5f,0x0004f2c600bdaac3,0x000ec0b432ccf8a0,0x0004d82574257110,0x00024e58edc3e12f,0x0000000000000001}}, {{0x000d5163c2f29845,0x000271b8856ff717,0x000a79d0557c5c08,0x0001484032810d21,0x000a5a6e95174165,0x00093b8782ce8f06,0x000a6f7f14b15d03,0x000ca398eeacdf3d,0x000eb31c7c040c1a,0x0003ace9ed34f4d2,0x0000000000000000}, {0x00086bac2cc4ff50,0x0008d5294f7bd063,0x000ec0b7a55f986d,0x0006868155592285,0x000e215833824965,0x0003366d9a307162,0x0001de9196efa150,0x00076afbb75f7833,0x00046ce65ce11aa8,0x0002f7a207e31942,0x0000000000000001}}, {{0x000d6129f7d0fa54,0x000150bddf5a7cf8,0x000b4988625b2f43,0x0009bbfb3c2f3809,0x000f5b080f7b3129,0x0000ab0abb84ed45,0x000510d824f7bed2,0x0006d6447243533e,0x000c576b7b64fbbb,0x000e16caa9ee8267,0x0000000000000001}, {0x00053a269ea0b07f,0x000e06f68fe62242,0x000a777b6874572d,0x000d5f86cf599bf5,0x000fe2a811045a16,0x000873264294a33d,0x0007a04ac970a0c0,0x000ceb2b7d05d686,0x00029a28a0e51a57,0x000bacbf79a38ead,0x0000000000000001}}, }, {/* digit=125 [{1,2,3,..,}]*([2^500]*G) */ {{0x0003efe866dc2f62,0x000853cb9e407c10,0x0000e6c71edaaa13,0x00018f751b70a2af,0x000b0cf7e3e825ae,0x0005c36a5a1ec11b,0x000487f56ab4b564,0x000a86df052ea4e5,0x000d750313868ef9,0x000e60ee422740c7,0x0000000000000000}, {0x000ee652bd47edd5,0x000397faa97f40b7,0x000294d2d1ba3dd7,0x000344d3453daecf,0x000d324bd3f56e65,0x00078c6f611c9985,0x000e24f2675985ec,0x00038b4060d38ad7,0x000dfb7496c92821,0x000be627a6ad57ff,0x0000000000000001}}, {{0x0009be6a7e5a166a,0x000d06313031bd58,0x000704962d984289,0x0002ec5b522512df,0x000386a669eef493,0x000fe747674db075,0x0004dbaabd7aebbc,0x0004d27fb22ce794,0x000e70494458ef81,0x000fadc96805636a,0x0000000000000000}, {0x0005b60c511b3ff8,0x000584915adb1e6c,0x000f8937e8e108c6,0x0008406d64ea3a9f,0x0004461d268f9ab8,0x000e3ff279d6126f,0x000d3b3ed1f3032a,0x00023a1b63af22a5,0x000caf9282fd7a53,0x000d99f7a42a7590,0x0000000000000001}}, {{0x000dfb005014a6bc,0x000d36179f05f79f,0x0001f0a00c591c70,0x00009f861bdb8aa0,0x000851877e4cc13b,0x00004921bdab098b,0x000265f47ca34718,0x000478a5d59cb874,0x0008aac74eb734d8,0x0002f6a87e5bc7bb,0x0000000000000001}, {0x0005dd559082ec4f,0x000fd3340b409a63,0x000e395e6174cff9,0x00035fdf83237476,0x0006e995df5d90e4,0x000535beb0acf902,0x000ddc2f60fe3f20,0x000821d68a60c3ba,0x0008005435d079f0,0x00084ef7a20c388b,0x0000000000000000}}, {{0x0001ce9624902c85,0x000dacee54d7fc06,0x0008e982883e676d,0x000cea68fc5997cf,0x000b94f3d06f1e8c,0x0007b80d8242831b,0x000ec2e625c36045,0x00015466a1d87389,0x000c5009313ff25b,0x00045efb5d45d1f9,0x0000000000000001}, {0x0004e32c6f246301,0x00064608ec78b5ab,0x00053a9c0b324014,0x0004ddead5ffb795,0x0008bf933bdcc559,0x0005249289dc110f,0x00047d25d52f652d,0x000d95ab06c0cb41,0x000bbff17968adb2,0x0002664039be6fa1,0x0000000000000000}}, {{0x0006c159dee64527,0x000d486c1da85118,0x0002ffecac887f87,0x000401c5326e8ac4,0x000fe68a082d270a,0x000b17b4ec0bd703,0x0009b1a9fe82427b,0x0008f75c6b25d502,0x000ac56e28859df5,0x000bc70f97f9bffa,0x0000000000000001}, {0x00073b932e4e3e21,0x0005f8e721dc13af,0x000825bde1498f11,0x00080fd3102f60c7,0x000f292e5a9e9f07,0x0006a4edbc9fcac3,0x0008f2651ae44279,0x0002622ca1bb123f,0x000a4ca103d2d6a7,0x000ca577d0f1994f,0x0000000000000000}}, {{0x000e577af10e1302,0x000156bf557eaa33,0x000ca7cba0f98005,0x0001e9d6e3d41486,0x000ad3a30b9f973d,0x0009856b55aa3443,0x000724f819219409,0x0008250cf13f0ca4,0x0006f0f69ba1696b,0x00063bba1deb1e9b,0x0000000000000001}, {0x00037cb6672f9435,0x000d7e7437eb08a0,0x000579149c6faf55,0x000e4c6943f7c61c,0x00026eba03e36921,0x000a3ade34c342ab,0x000052386264eb60,0x0000ffc57653cf12,0x00070eec7914e6e2,0x0004912d67845657,0x0000000000000001}}, {{0x00006fc3e072e1bd,0x00066e9739a62b31,0x0006ea97e6ad1669,0x0002aa2bbc843284,0x000871768bc4f0fb,0x000a51f2d1bd1f5f,0x000245a8890f99b0,0x000b6a0000aa5f53,0x000547c1538e0dc0,0x0001c33dbece2149,0x0000000000000000}, {0x000b56de17b97c51,0x0000fccb15a8e3ea,0x000c00352a78e0ff,0x000e7d480dae3bf3,0x00092273cee30716,0x0000962a4283dde8,0x000e674e18ae53b0,0x0002b8c78835cb2c,0x000faee271217641,0x00046294e0f5e7c6,0x0000000000000000}}, {{0x0005697612d854d6,0x000590266d871a78,0x000015aa94be7df9,0x000482ac4e8bbf72,0x0007c12880439150,0x0003495f23aa4b2f,0x00074815ef777bb5,0x000838a798c004a6,0x0008a425cc7aadc8,0x000c432ccb5f5730,0x0000000000000001}, {0x00006af85640f288,0x0003a6718ebc6cb5,0x0002c50bba9dd21e,0x000e3c4d56098fde,0x000a4a8a721857b6,0x000218f9c402f4d7,0x000a6f255530e5d9,0x0000bf7b3c63a541,0x000f0181b97421bb,0x00023de7a08f2804,0x0000000000000000}}, }, {/* digit=126 [{1,2,3,..,}]*([2^504]*G) */ {{0x00061ebad9ee2c24,0x000dd46aced3ddaa,0x0000bd3e3fde5fe2,0x00020569fe14f9f4,0x00088d818d1a2095,0x0002f0bdc9b4968b,0x000e3de0b8b77328,0x0007fe9e8edc6520,0x000017cf0272ff76,0x000eda0f65dc99bc,0x0000000000000000}, {0x0009b50b03dc034f,0x000ff04ea634ab0a,0x0007b191db6e6308,0x000a9de7ee04399a,0x000e6da7bdea8dde,0x00054c55ae492d45,0x000f4e939e666b7b,0x00090c925a51f573,0x000f916220292c15,0x0002d380fc7f5071,0x0000000000000001}}, {{0x000639a92b83d191,0x000b3a1ce7b1b453,0x0000d260e431474f,0x00032954aefab808,0x0006dfaf9e670c4e,0x000e42d0d7b5bae7,0x000bfa89eb4687fd,0x000c7d89b1ca5f45,0x000ecce4fba638bb,0x0008a21de873fcc0,0x0000000000000001}, {0x000c9c2b49165fd5,0x0005fb318f9f9636,0x0006f676d6c2cb81,0x000c633a7560919e,0x00011e2d4752541c,0x000199c5999a79e2,0x000515dfbee081ee,0x00053107dec5265f,0x0002bdc9ed0ea4e2,0x00041c5a539ab36f,0x0000000000000001}}, {{0x00009de7ecb2ac56,0x0002d837bb7a345c,0x0004863cfd4369c7,0x00077c66a5755a3b,0x000682ccc872cef3,0x000bc1363c743442,0x0008b997f1a0d907,0x000d72224eed734a,0x000d1850457f924f,0x000f3bbd996258f2,0x0000000000000001}, {0x0004953714391350,0x0002a08de1fb04ea,0x0009bb0ca7d3f0e3,0x00020e2fc4a54760,0x000d525812eece55,0x000dc3c7c680f4ea,0x00064f097079b269,0x0001e81a267b891a,0x0002df53061afa20,0x0007339d7335dbc1,0x0000000000000000}}, {{0x000fa11c22d57017,0x0007061bfc65866f,0x000e25c9a781f882,0x00052d54eb5d1a25,0x00034e5fcb1fe128,0x0008c5dfb74f3317,0x000cca2e48b7e54d,0x0005e9b41639cfad,0x000e1f8c2193402d,0x000348c49e8f71b8,0x0000000000000001}, {0x00033ca43943f50d,0x00016ce98a1f644e,0x000bd595ac8a7cb4,0x000d4eb1e328cd45,0x000e8ec3fd8cbf8f,0x000eb626b0f768cf,0x0001524476b1bbc9,0x000d8d0ffe31069d,0x00025aa89220edd8,0x00063660b3755829,0x0000000000000000}}, {{0x0003a78191abe914,0x000aed083110e37c,0x00072de9a657b228,0x0003d434d0dfafec,0x0009778c8ba568ce,0x00021f193e09ab8a,0x00032b59891165df,0x00090a0e20c8f7ac,0x0005b8a1f64088c4,0x000b717ed2f2d69f,0x0000000000000001}, {0x000ac4849a39a0ab,0x000e9224368b5d72,0x0009a57abd9c0589,0x000f04bfeb21218d,0x00049bfe57f2080a,0x00082fbca66b72d8,0x000f0c09eaa93852,0x000e04db305e15a6,0x000bb2bcc4365052,0x000d0e18047907b5,0x0000000000000000}}, {{0x0003c1031f4f778c,0x0009bbc5cc621ce8,0x000ac957c67434bc,0x000a368627bcbc47,0x000adace0a905430,0x0008aa0831ed2cb5,0x000c11d0f4f5d323,0x0001c48e91c91fa3,0x000229765edbfb35,0x00032bdf2591e498,0x0000000000000000}, {0x0008e455572bcfd0,0x000ecba53bea9ae3,0x000196518c997db1,0x0005c33258970b56,0x000a3c6b46d1e689,0x0008e44ad30fe772,0x0005dd6482160561,0x000b86d1933faf1a,0x0005a53d718ae6de,0x000e4e4345a6badf,0x0000000000000001}}, {{0x0009f15950170034,0x0008a7d9e0681bfb,0x0002dc602830c283,0x000e8af178838dfd,0x000987d3f8bcc134,0x0008904081cb94f3,0x000a460c0da2bca6,0x000f718b8913d63c,0x00022ed274e647de,0x000ff3a58fd52338,0x0000000000000001}, {0x0002950ff4836dad,0x000fe4a51fa111b5,0x000e13de206b61a9,0x000941373ab42508,0x000c7bf8c1651d7a,0x000dbd9276666a02,0x00056dcdd411c37b,0x000f5a9ab3e87536,0x0000f464671775e6,0x000bc59bc827eaae,0x0000000000000000}}, {{0x000eafce57fbc903,0x00072ba11885f40d,0x000d640aa98f9421,0x000bfcf817ce6b52,0x000389d8e40bcdc1,0x000c804e7d14a7d6,0x0008fa880e955163,0x00034af7c92b6304,0x000fd685115381b0,0x000faf73ec6a9688,0x0000000000000001}, {0x000f85d1af3848b2,0x0008716ba36666f4,0x000fbfc6c17f47de,0x00003b35f9474540,0x0004b72b1ddc670e,0x000f48bdd3ad6387,0x000d7cfd249ea687,0x0009c16141926a15,0x000d8d963e9d101f,0x0000771b9b1c2fac,0x0000000000000000}}, }, {/* digit=127 [{1,2,3,..,}]*([2^508]*G) */ {{0x0006bccc65f30461,0x0006e44b51d15f3b,0x00061b0ed084d989,0x000f84c9df4f3be0,0x000626ed8e29bced,0x000a49395cf45bde,0x0001bfb128499bea,0x000d30e7b9a9812a,0x0000016d9442e44b,0x000577251b4710e5,0x0000000000000000}, {0x000c58ea8faa5f8e,0x0006398972e1afb4,0x0002d603c3a6a3b7,0x000090f464b41953,0x0003e1c1cc6d5ad6,0x0009fc4551644bda,0x0003bf0e003b3c67,0x0004879a2d4dc4fe,0x0002492059f3993d,0x00089490933a0bd0,0x0000000000000000}}, {{0x0003d39ba21abe88,0x000b8dfe497366b8,0x0003fb2e32d1a08b,0x00040dcc68fadea4,0x0009bc78d9e5b900,0x000999242f620135,0x000e38d4ca94e098,0x000f3e9a937783f1,0x000c271edf5e42de,0x000cdad3d42e09c5,0x0000000000000001}, {0x00014caf1b7e4897,0x00092052b710207f,0x000840b578b42fb2,0x000c859d4e0acb78,0x000efbd1059c69f5,0x000fc0d187f5ce1f,0x000018dd99b98e1d,0x000fd9d695b6b702,0x00087f7037056ff1,0x00080b73121d9b11,0x0000000000000000}}, {{0x00078d674ce9ba28,0x00098667edd1931d,0x0007a2c798ce814e,0x00054444ef1eef63,0x000bbc4342cdf2cd,0x0008690dad1f9bf2,0x000e17a85c72b72f,0x00027215c615b685,0x000ab98eb37dbb69,0x00072850ebda62ab,0x0000000000000000}, {0x000b543dc482d1d8,0x00066dc72bee2f05,0x000576c719cbc26f,0x000bf9361970fe88,0x00012aede3868858,0x000d0a81339054e9,0x00050f3227db12ff,0x00054f85925da234,0x0007c4995e06e9ee,0x000343899d0c96c8,0x0000000000000001}}, {{0x000622bfd7a6e63b,0x000ca212bebe9c89,0x000487abee2cafd2,0x000143f4d290457b,0x0007d05d13bf4c04,0x00067f0ae3716aab,0x000a3097740d4130,0x000debe6d02d5925,0x000ef2c2714370b8,0x000fcffae20be9e8,0x0000000000000001}, {0x00009dc727eac0b8,0x000802b463618a8d,0x000e00f824949d83,0x00021e8850666aae,0x000a354be3730d5a,0x0006ce164b258522,0x000386cbf3fd223a,0x0000b7ba5ba4fefa,0x0008ecff5479bc6a,0x000ec6ece410bb37,0x0000000000000001}}, {{0x000fb0fd2b03ceeb,0x000c34d346742d91,0x0007fb1da808f925,0x00014c3e50e576d5,0x00045dde45aec274,0x0007634b06ff5225,0x000e8f635cfee4ae,0x0006af16b33722c1,0x000b6c9512df9861,0x00087905f5ba1ed3,0x0000000000000001}, {0x0006849e44fd7308,0x000ca8c188190c88,0x000568eece8b82ee,0x000afcede37dce03,0x000956f0105616d6,0x000fcd4f42159b96,0x00016a63204d42e3,0x000f90e66b95446b,0x0003ff7137d7895f,0x00015f08ed8c3b6a,0x0000000000000000}}, {{0x000080c877cdc551,0x00063fd88170e394,0x000069a5394fa226,0x000fe13aafd4abd3,0x000aac77685a1a56,0x0002270caf504acd,0x000b15ab3b28bcb6,0x000ff30df2535d28,0x000dad1836a25af3,0x000fa6c25940501a,0x0000000000000001}, {0x00072e0f5dfd0431,0x000680aa3b20ecdb,0x000be825e1b5fe43,0x0005a5c2422130db,0x000f0dc02a5e8b8e,0x00053d6d0a6ed0ac,0x0007b39bd52bad22,0x000defc7beec9197,0x000d80e249e46059,0x0009869fd32b5153,0x0000000000000000}}, {{0x000d5488a9c159ea,0x000c7c99f362daa9,0x000520e4056562a1,0x000f58587c3780d4,0x000cf122d12decdc,0x00066fa3df2e094a,0x0006c99c7f2dc2a5,0x0005a3f3e1f8fe88,0x000ead106c542a2f,0x0001bd548c70f9bd,0x0000000000000000}, {0x00025e9e39905a6d,0x000d9b4651431540,0x0007d3343ac64109,0x00071e3dd6b3d33e,0x000a550593155d88,0x0005e988444776c0,0x00092c204b5ef211,0x000132ec6af46f8f,0x0000975bc42ba82e,0x0000ec605e3e60a7,0x0000000000000000}}, {{0x000ebdae497fc314,0x000068fcc42342b8,0x0002e8a76fa0addd,0x000d98aa1ba58a99,0x0006f585d2056972,0x0001a667125a290a,0x000e664a47990be5,0x0003e44696beab19,0x0000ab4a22f64d1c,0x00054a0b8ce48449,0x0000000000000000}, {0x000cf9a538895145,0x000e7e3b3fd1990a,0x0001c1f1592daaaf,0x000016843015bdb3,0x00095b2dbb2d0adb,0x000f77ef5d670d12,0x0008bf1b3f98aca3,0x0003b5280fd35140,0x0007a58660b5ee9d,0x000f86e58791223a,0x0000000000000000}}, }, {/* digit=128 [{1,2,3,..,}]*([2^512]*G) */ {{0x00031c51f5b59b03,0x000c7665ab584951,0x0008739b754d5115,0x000b253e840523eb,0x000078a1f77e3b96,0x000742a046765d97,0x000823d7e942e5b8,0x00080b3194bd1539,0x0002679bf560b997,0x00061abda6ff32b5,0x0000000000000001}, {0x000820e93e66dad8,0x000f2c881e08a892,0x0007e5fd839208f9,0x000d25804e86968c,0x000fc76aeb554305,0x0004c686c9b44037,0x0002e51b80d02e02,0x000e5774d5a620e6,0x000000eae653df90,0x00072ac9b31961f0,0x0000000000000000}}, {{0x000f8d7860917b4f,0x000bb3357359429f,0x000995f4b0a05d76,0x000e0f1c58d0fe01,0x0002921dccd2ee40,0x0000ab0ca33af9c6,0x000637c074069c34,0x0002098a102fa30b,0x00037701844888bc,0x000d6cb2e96e33de,0x0000000000000000}, {0x00070d506a96d190,0x000f2ce57ed3ba0f,0x0002492cf26e59c4,0x000305995879a0eb,0x0000675760ae93d1,0x0009f9d0d04103b2,0x000d618a2b740898,0x000e723e7b444b0a,0x000b80451ab5c813,0x000616305a1f27eb,0x0000000000000000}}, {{0x000b480b60680f46,0x00097a71a65ccb4a,0x0002360920f061e1,0x000428aeb306dab3,0x0005aee5267509d9,0x00058e47b1cbaf9d,0x0003350d9a6f7e9f,0x00035af36c30696a,0x000ff438c1f66ddb,0x000119d4937e17ea,0x0000000000000000}, {0x0009df61e7821be6,0x000b8322655044ac,0x0001ae7bb1e106e2,0x00039508343bc8e6,0x000a2bc1e06e0991,0x00066bd6b8166453,0x00044e23756d0eb9,0x00003795c5a1b4bb,0x000605deb625fe17,0x000248426f42f1b7,0x0000000000000000}}, {{0x000ebb49b8b6d8d8,0x000c9576edd0b2c0,0x000089746d87ef78,0x000ee54686ff89a1,0x000cd51992a8e30d,0x000fcb70ff8362ad,0x00008d8883f2631a,0x0002a13e25b5a551,0x000d32baa9313847,0x00049764387fbe1f,0x0000000000000000}, {0x000652373d0f2fcd,0x0007e9e1299928e8,0x00016c54d21ce8fd,0x000e62d7938b0123,0x000ce4d602bacad0,0x00055138cbf9df41,0x000e0e625dfe098c,0x000dbf9a6851bc01,0x0000b0da12bdbc63,0x000aec8b07cebaa7,0x0000000000000000}}, {{0x0006a52b356ba3e0,0x000fa486ee1abbf6,0x00074bf145f1f28e,0x000ef4af39b6c538,0x00084376c3d3f698,0x00007cbe4b46d363,0x0003db26e35a57f0,0x000ecc45a1933b62,0x0007b9610a9a44f8,0x000057b84f95bccb,0x0000000000000001}, {0x000bdacb48b9bb6b,0x000642a5eb931fe7,0x00097c327f5fbd2e,0x000a3062ea3deca5,0x000a3dad9ef787fc,0x00092f83b35a8216,0x00042427945728d9,0x0007537c6394f3cf,0x000b615698a93762,0x0001f468793ceb99,0x0000000000000000}}, {{0x000217c6562eea14,0x000a6a042cb3da1e,0x00060f9ac91e9595,0x00013fef00e33063,0x0001954b4b6c8a05,0x00007e6bb37592ca,0x00018fef0e569527,0x000f4449441c7534,0x0003c8e93a050abd,0x00050bb02598e0eb,0x0000000000000000}, {0x00044683d956af18,0x000340076bbbf06c,0x00006b8e5826911d,0x000bd47b4442693c,0x000bdbfb4883b7be,0x000a67f8d229f111,0x000eceec785481be,0x000d18ec8ccc0a58,0x000ed2b1cc9fd671,0x000ee9b77fbdfe40,0x0000000000000000}}, {{0x00033f2848525772,0x0002def8aeb9f6cd,0x0009c738e373fa1e,0x000ca3f54bf1bb33,0x0000dd3b12e5c621,0x000856fbe6604112,0x0004fa2d98399489,0x0000ba4686140d31,0x000be8a65034e7d6,0x000fc1d2c9034f2b,0x0000000000000000}, {0x0002e0e02cbac5de,0x00036d1bbef4bfe6,0x000db812e9ceffa7,0x000c4f097569d138,0x000c2795f975ff41,0x000cfa1a794c9978,0x000e1e65c9b377a9,0x000e6d66f7a547fd,0x00058785dc7270ac,0x000b34d6e188dec1,0x0000000000000000}}, {{0x000a511d09de2eac,0x000031698e16faac,0x0002e96a74ccb4d0,0x000b85017b609854,0x0005887d91373679,0x00039fd4a56f39c3,0x000f60f3aea2bb2a,0x00084e8edd3fc7ee,0x000e1d001d481288,0x0003732f4d1fa989,0x0000000000000001}, {0x000629c27855b7b6,0x000652d6fdccbf0a,0x0005f32800f6bc14,0x0007f62ad29c1358,0x000dbf3a9fdce69e,0x000aa9f4b69418d0,0x000e5fef492796fd,0x000332f4a27a525a,0x0001a7293d91d135,0x0006fadc6b1bb1cc,0x0000000000000001}}, }, {/* digit=129 [{1,2,3,..,}]*([2^516]*G) */ {{0x00076fe9e4b410aa,0x0002e2e46e8257e7,0x000285dece1c90ea,0x0004f07e02e70a0d,0x0007d9e22652fd2e,0x000325ca4b7fb066,0x0001305e36daaa95,0x000feebe9d3d04df,0x0000e3be0fcd0755,0x0005f74f74e60357,0x0000000000000001}, {0x000a7ff33f158714,0x00012737b93b28b8,0x000a408dc4f02791,0x0009c78d219fcf52,0x0008fbf0f03e3758,0x000d6cdb0c0bb10f,0x0007428d517b4d78,0x000d37e06b1f9904,0x000f8786ba69f3ae,0x000b508624d39698,0x0000000000000000}}, {{0x000314e66fead340,0x0009f5c35e0de977,0x00086281b424220d,0x00095c9d69b8f421,0x000075fd90a74e5f,0x000c09fc499a89c7,0x0004b64e12f34808,0x00068c161166a676,0x000f40cf1886f3c3,0x000c4968ad8aaa55,0x0000000000000000}, {0x0001f4bec36790bc,0x000d77489002d4f9,0x0001759ca38e8177,0x000e759ae14e5a1f,0x000289005868dab2,0x000a1dff8ca02b41,0x000a4d82b9cd06ea,0x0004578741ea12d6,0x000343e8d641aef6,0x0002d4c6a85c8b1a,0x0000000000000001}}, {{0x0007c33639a0b3f1,0x000010f791b828fa,0x00069b98b785836e,0x000f9367ba2d3b6c,0x0005ecea4290d504,0x0003dd0621586083,0x000de6622ac6245f,0x0002d8153e71208b,0x00091cd77d2a1a55,0x0007ebc7df7c52cd,0x0000000000000001}, {0x000fe4e1268ac84e,0x000d05fdf620f30b,0x00078c9c26de9aa6,0x000fef3a7d0e875e,0x0001f45acf57d581,0x0009769d1b4f2f3f,0x000f8a2b516d4fb8,0x000ca50e2afa7161,0x00069ea98a831731,0x000a4069e2a679a5,0x0000000000000001}}, {{0x000573b5ab69b37b,0x00099e464e098a37,0x0004b6ae9bd2eac1,0x0007e83941109e44,0x000b3638c710996c,0x0005b0374099e6be,0x000e0cd0943a1c3a,0x0008fab6ecb18490,0x0009f0eb14e71bae,0x00011229f06246b6,0x0000000000000001}, {0x0006e2d865b8fa8c,0x000e4ba2a3d8ca53,0x0004c428120f4f50,0x00003e5bcb6eaa4c,0x0006c69871129b42,0x00018bdacf6da13d,0x0006a314f621f852,0x00031ea900e85204,0x000d280193a13fa0,0x000437167b70a8c7,0x0000000000000001}}, {{0x000e47d41aa029d1,0x00083c1c1e4e8c82,0x000819d110bf6923,0x00080e340caaa47b,0x000e4f6e315e8cb2,0x000865960449f5a7,0x0002a736db3e3bf6,0x0008b38233a8c18d,0x0006ab95cab54c2d,0x0007b4670af6e721,0x0000000000000000}, {0x0009cd8d15df2f21,0x000c9e95f873ccf7,0x000d4ae259b8946e,0x0003026a352c8cec,0x000c84b6773b4638,0x000327edc3574f14,0x000980243f9e1167,0x000c58a2e8d3fc2d,0x000e789b426360b9,0x00084beac487c72a,0x0000000000000001}}, {{0x000a504d7a128f19,0x000bec706161d077,0x0008d3f449e0d717,0x00027553cd6aa437,0x00023bfa097584c3,0x00031032e9ecfed0,0x000de734abfe6661,0x0005972524c62301,0x00068a20ad67cd7b,0x0001d7d8e4bd981b,0x0000000000000001}, {0x000dd411d75c8560,0x00020a136bd0f9a0,0x000e9c06f6a8521a,0x0001770134117a07,0x000c6625cc2c0b14,0x0006f01c93534fec,0x000bcd3698e9742e,0x000543a9724acea5,0x000820ced54b554d,0x00005a7954cbcc77,0x0000000000000001}}, {{0x00060a7aed1a8afb,0x00037a6526a7b404,0x000f752335e80ab0,0x000a8f65f14c43bd,0x0004f9b989eabd11,0x000976a80f23fa92,0x0000171f16dad870,0x000d3baaac454e44,0x000f34704b9635c0,0x00051b0e1ca863f0,0x0000000000000000}, {0x000fcc07647c957a,0x0007e8420a4e5f40,0x000cec847e324cf5,0x000db2fe1f189869,0x0009827f88deeb20,0x00023c17a4487124,0x0009568284e63444,0x000010b9bfa3fe02,0x000626ee2d426c18,0x0006c496cbf2d807,0x0000000000000001}}, {{0x000a48e1016cc257,0x000e7a08472093bf,0x000b7492e4ec8ac9,0x0001bd1c471d73ed,0x000a7243428ce53d,0x0007d49d1740adec,0x000c66dd60077c0b,0x0005737593cb7a95,0x0007c6f6ef237e1e,0x000660a7929ff06a,0x0000000000000001}, {0x0004bcc2e6c3da59,0x0003e87b3c416f89,0x00021231992a493d,0x0006d0824c0a5993,0x000e60d5c6c61f37,0x000a3430f29e1550,0x0005e81f1d1beb92,0x00027b6bc5ab11f9,0x000858c60a78bae0,0x000f95bdd9ea9017,0x0000000000000001}}, }, {/* digit=130 [{1,2,3,..,}]*([2^520]*G) */ {{0x0008b69f6c0a103c,0x00014cb96747cd0b,0x0009e707ed23f30c,0x00092336029690c8,0x0002b884265ced12,0x00087e627555cfec,0x0008f62a097ab7dc,0x000df635118ea555,0x00070b69e23dda1a,0x00011d1b70ffff57,0x0000000000000000}, {0x0002606bce985157,0x000cf38c9c6bbd4f,0x00058d1b308ccb92,0x000fb6fe2ce6913c,0x0005b1967bfefbbd,0x00053132fce5cb51,0x000b2f22527584e4,0x00082a1591dfc389,0x0002d57610460d61,0x000dc57498b0d160,0x0000000000000000}}, {{0x0008cffee5938175,0x000028a135a61fb3,0x0002c9fe1a18ac17,0x000b968e30418249,0x0000b4c958b813ec,0x00023285e86f834a,0x000b05e54df836f5,0x0008f77b5fb229e4,0x000371505e864d89,0x000fb3cce3c32e48,0x0000000000000000}, {0x000a0e5e3ce8bcd8,0x000dc2fb74fd48c4,0x000875aaa2018996,0x000827185e9f86f5,0x000196642422b5eb,0x0006d6f0dd874310,0x000f5719d7e7982d,0x0005346044e6cb46,0x00002d250a348c67,0x0009ec517508afdc,0x0000000000000001}}, {{0x000145140a7a865f,0x000095ded9f8c118,0x00040df2b19ba498,0x0007dec03834dace,0x0009e3687e664a0c,0x0009d971f2feee9a,0x0008796a032ee720,0x0003a0b2cc310714,0x000067d48b65bcec,0x0007f5d8c2af6546,0x0000000000000001}, {0x00015c856b094864,0x0004f779c821c5d7,0x00062cf6310bebe0,0x00086c833844c220,0x000322644f899899,0x00080ac439439357,0x0009f2dfd741ec2f,0x000c3022b589299a,0x000663af1bcf4790,0x000a46767587f6f5,0x0000000000000001}}, {{0x000cdfa0667f8929,0x00055eda7b7826f1,0x000dd93845997fea,0x00073f54c39699cc,0x000d85971fbd417d,0x000631f8049f08e1,0x0003b8e65a870ee3,0x000aa3cdc8e351a7,0x00099901454f69b2,0x0002d659cbe0fe85,0x0000000000000001}, {0x0005bfaeb9c77879,0x00078817f6a7aa08,0x0001e5f6c61e07f9,0x000a5dffb271762a,0x000df5d3e3cd3cc6,0x000eadd52e895eb0,0x0003b342cd665b46,0x000393078c5b9252,0x0006202122ebcff3,0x0005f4777dd50c48,0x0000000000000000}}, {{0x0003fcdbd57bfa90,0x000d1b118dee98fe,0x0000a524ceccfc4a,0x0007420c6d1ffa5c,0x00053919d859de0d,0x00081fb74544af55,0x0007c3f0981d6def,0x00076680c297a17a,0x000d22135e0cc4fe,0x000d15de36e57af6,0x0000000000000001}, {0x0008ae03fd78b0a1,0x000c06ac0c41950b,0x000c994e2c7c2638,0x00075a944523ebb6,0x0002bdb72a76549b,0x0007a73d0573310e,0x000ae4c8ce6d6b85,0x000e4309eb9e1e23,0x0008aedc0842f06a,0x0006ededf71264f9,0x0000000000000001}}, {{0x00047c62f7f81bbb,0x000568d4c38f8cbe,0x000085a52c049173,0x000151d87d057b19,0x000462de5c929612,0x0004036de18a4ea9,0x000290b0a8300ddc,0x000e195518bc5a6e,0x000e21097894ed83,0x000a74d8dd898c35,0x0000000000000001}, {0x000eee2e29a47676,0x000325c0b89ddfd0,0x0000c5c995a8a7bf,0x0003e514a5131a24,0x00078e5998b6e957,0x000ba59336939798,0x00032157906f3c87,0x0001093cead5ff51,0x0003bc2e1b76588a,0x000a055abc03c824,0x0000000000000001}}, {{0x000c9d2081074b7d,0x000b4b234d223107,0x000c6fe7d17524b8,0x000b3e26469a9182,0x0001d35461f18688,0x0008f9ef1eb0f49d,0x00072164bb2130a7,0x00069240661ee72b,0x0004674d4ec1e4e4,0x000df195346b1529,0x0000000000000001}, {0x00094d4cd2beae09,0x00021cf533e3fea5,0x00099051c26db75a,0x0000237aea1a808b,0x00066230cfcd19c1,0x0000aedfcfe63965,0x000965518cdd9349,0x0000446502d88c39,0x0006de0650de6be1,0x000c487b3640aa4a,0x0000000000000000}}, {{0x000315f2c4f3b202,0x000844f2e07c55f6,0x0009040fc8f62ee6,0x0006bb02af168881,0x000eea1922677aec,0x0003b90132968e4d,0x000b75f92b21f9e5,0x000b4ae4c1d62b9c,0x0000f373265408d1,0x00013d70be8f94d2,0x0000000000000000}, {0x000c00995b2d1ac5,0x000acf4e16ae2b05,0x000d04ee882f20b5,0x000b5e061f8c5834,0x00040c9dbfe4135d,0x000f7b55b63a42f5,0x0003b47500e266e3,0x0004da6911e652ce,0x00043c4db0c53d0a,0x0009946052a6d7ee,0x0000000000000001}}, } }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPRECOMP4_P521_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecprecomp5_p256.h000066400000000000000000005155041470420105600337500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPRECOMP5_P256_H #define IFMA_ECPRECOMP5_P256_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (5) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_SLOTS NUMBER_OF_DIGITS(P256_BITSIZE,BP_WIN_SIZE) #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static SINGLE_P256_POINT_AFFINE ifma_ec_nistp256_bp_precomp[][BP_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x00030d418a9143c1,0x000c4fedb60179e7,0x00062251075ba95f,0x0005c669fb732b77,0x00008905f76b5375}, {0x0005357ce95560a8,0x00043a19e45cddf2,0x00021f3258b4ab8e,0x000d8552e88688dd,0x0000571ff18a5885}}, {{0x00046d410ddd64df,0x0000b433827d8500,0x0001490d9aa6ae3c,0x000a3a832205038d,0x00006bb32e52dcf3}, {0x00048d361bee1a57,0x000b7b236ff82f36,0x000042dbe152cd7c,0x000a3aa9a8fb0e92,0x00008c577517a5b8}}, {{0x0003f904eebc1272,0x0009e87d81fbffac,0x000cbbc98b027f84,0x00047e46ad77dd87,0x00006936a3fd6ff7}, {0x0005c1fc983a7ebd,0x000c3861fe1ab04c,0x0002ee98e583e47a,0x000c06a88208311a,0x00005f06a2ab587c}}, {{0x000b50d46918dcc5,0x000d7623c17374b0,0x000100af24650a6e,0x00076abcdaacace8,0x000077362f591b01}, {0x000f24ce4cbaba68,0x00017ad6f4472d96,0x000ddd22e1762847,0x000862eb6c36dee5,0x00004b14c39cc5ab}}, {{0x0008aaec45c61f5c,0x0009d4b9537dbe1b,0x00076c20c90ec649,0x0003c7d41cb5aad0,0x0000907960649052}, {0x0009b4ae7ba4f107,0x000f75eb882beb30,0x0007a1f6873c568e,0x000915c540a9877e,0x00003a076bb9dd1e}}, {{0x00047373e77664a1,0x000f246cee3e4039,0x00017a3ad55ae744,0x000673c50a961a5b,0x00003074b5964213}, {0x0006220d377e44ba,0x00030dff14b593d3,0x000639f11299c2b5,0x00075f5424d44cef,0x00004c9916dea07f}}, {{0x000354ea0173b4f1,0x0003c23c00f70746,0x00023bb082bd2021,0x000e03e43eaab50c,0x00003ba5119d3123}, {0x000d0303f5b9d4de,0x00017da67bdd2847,0x000c941956742f2f,0x0008670f933bdc77,0x0000aedd9164e240}}, {{0x0004cd19499a78fb,0x0004bf9b345527f1,0x0002cfc6b462ab5c,0x00030cdf90f02af0,0x0000763891f62652}, {0x000a3a9532d49775,0x000d7f9eba15f59d,0x00060bbf021e3327,0x000f75c23c7b84be,0x00006ec12f2c706d}}, {{0x0006e8f264e20e8e,0x000c79a7a84175c9,0x000c8eb00abe6bfe,0x00016a4cc09c0444,0x000005b3081d0c4e}, {0x000777aa45f33140,0x000dce5d45e31eb7,0x000b12f1a56af7be,0x000f9b2b6e019a88,0x000086659cdfd835}}, {{0x000dbd19dc21ec8c,0x00094fcf81392c18,0x000250b4998f9868,0x00028eb37d2cd648,0x0000c61c947e4b34}, {0x000407880dd9e767,0x0000c83fbe080c2b,0x0009be5d2c43a899,0x000ab4ef7d2d6577,0x00008719a555b3b4}}, {{0x000260a6245e4043,0x00053e7fdfe0ea7d,0x000ac1ab59de4079,0x000072eff3a4158d,0x0000e7090f1949c9}, {0x00085612b944e886,0x000e857f61c81a76,0x000ad643d250f939,0x00088dac0daa891e,0x000089300244125b}}, {{0x0001aa7d26977684,0x00058a345a3304b7,0x00037385eabdedef,0x000155e409d29dee,0x0000ee1df780b83e}, {0x00012d91cbb5b437,0x00065a8956370cac,0x000de6d66170ed2f,0x000ac9b8228cfa8a,0x0000ff57c95c3238}}, {{0x00025634b2ed7097,0x0009156fd30dccc4,0x0009e98110e35676,0x0007594cbcd43f55,0x000038477acc395b}, {0x0002b90c00ee17ff,0x000f842ed2e33575,0x0001f5bc16874838,0x0007968cd06422bd,0x0000bc0876ab9e7b}}, {{0x000a35bb0cf664af,0x00068f9707e3a242,0x000832660126e48f,0x00072d2717bf54c6,0x0000aae7333ed12c}, {0x0002db7995d586b1,0x000e732237c227b5,0x00065e7dbbe29569,0x000bbbd8e4193e2a,0x000052706dc3eaa1}}, {{0x000d8b7bc60055be,0x000d76e27e4b72bc,0x00081937003cc23e,0x000a090e337424e4,0x00002aa0e43ead3d}, {0x000524f6383c45d2,0x000422a41b2540b8,0x0008a4797d766355,0x000df444efa6de77,0x0000042170a9079a}}, {{0x0000b650bc6fb805,0x0004effe2e6b808b,0x00083f5495882e07,0x00072385ef2f7c2c,0x00004d63c80e103b}, {0x0001bd652a23f9b6,0x0008eb0b6587f2f1,0x000580e9e3670c31,0x00021ff5c4623bb1,0x00004edf7b261efe}}, }, {/* digit=1 [{1,2,3,..,}]*([2^5]*G) */ {{0x000fccfc5e3a3d83,0x000c1079dfbfd8c5,0x000ad0197befd904,0x0002a48c6d6a58fe,0x0000922707799553}, {0x0003e6ddbef42f56,0x0003e80a990809e2,0x0009a2e407e449b6,0x0002a41b969c1aad,0x0000231d792f591c}}, {{0x00096f305968b809,0x0002789f73b9db6d,0x000c61e01380a091,0x0008c6eda70b83c2,0x00005fb8394e69b3}, {0x000651280edfe2f2,0x00096faeaf829a3c,0x000424bf88f726bb,0x0009706010a4a078,0x000096720442e844}}, {{0x0008d2333e12b701,0x000b09dd329b802b,0x000bc354d6d490a4,0x000a0d04f356cc6a,0x00001eddf7fe0a0d}, {0x0008328d87fd1d83,0x000ccd0258131e20,0x00029bca2fd2f4f8,0x000b70d3b48cc47c,0x0000f2a78b3541a2}}, {{0x000cb817a2ad62aa,0x00090c62ff5463c5,0x000ad9db57ef2b6b,0x0006169749bba4b3,0x0000d311f2ce6d5a}, {0x0008087c2ff3b6df,0x0002467834ffb77a,0x000d6b138b46feaf,0x00018808aa266d75,0x0000a38d321dc008}}, {{0x000fa1ae3451a09e,0x0002dc117423c04a,0x000cf56ee7cc6910,0x000a24a76be3aa51,0x00007577d588d844}, {0x000ed8cdb77f3410,0x000c23ae4a2a266f,0x000782760cfa258d,0x000d4a53a7a98cda,0x00004b48868ceaf7}}, {{0x000affc4e6916c6d,0x0006b11842dac0f2,0x000b4d1576fb9495,0x000b8f9034bcb624,0x0000e2efdc8692ef}, {0x0007eceac793c87f,0x00058dc6fdcdd66f,0x000a1c50102f0262,0x0006efa0d3235c9a,0x00006e494971b466}}, {{0x00036d19c0859c3e,0x0005d269386a0827,0x000a87b3389ea551,0x000236125071871a,0x00009d82f60504e8}, {0x000612442e855f5b,0x000d895e00d87834,0x000e7e62b209f50f,0x00037b1d9e03aae6,0x00004b4959f0e5be}}, {{0x0008ffa696946fc7,0x000849cba56d486d,0x000f35a1550fbc6d,0x00062c0e3d423e90,0x0000c3da19630dd9}, {0x000fdb03cfd5d8b3,0x0002589dfca5e673,0x0002305aa0704b7c,0x000e53c6ce581ff5,0x000099d49ebc14d5}}, {{0x000afbb10e6d9501,0x0004d2bf970a7966,0x00054ca2a37e4a4c,0x000a1013d0c8559d,0x00003d628660ee39}, {0x0003c38d3bd15e94,0x000d44a80bcc15f5,0x000d8f608014b8be,0x000feed0674c77bf,0x0000dfab987093fb}}, {{0x0007c367b92d4531,0x0002149a26c024c9,0x000d14a39d2c271a,0x00000550eb4b2b89,0x0000198de20532e8}, {0x000ea75799b80d93,0x000b5f826ae59eab,0x0000061ecab6e0c2,0x000fd89a004eedd1,0x00001a9f43a199c4}}, {{0x0008b75b5498a7c3,0x0009f9f64c2d734c,0x0005b1677aeccad8,0x00096865dd54fa29,0x000083902a0e4c54}, {0x000276feb9d33a9f,0x0000bf55286978cb,0x0005c163000aedca,0x00050cb01d14594c,0x0000eba17076cf7d}}, {{0x000496d6ec293cde,0x0006ae7051f5380a,0x00049140a733dbda,0x000bf5237e388db8,0x0000e4b32b13946d}, {0x000fda9cae368d14,0x0000bdb0b2f3b1c4,0x0003ac46e5001a7b,0x0006562df593742e,0x0000af675f279b3e}}, {{0x000ffdcc01b0a469,0x000ef3f843c21a1f,0x00038e81a07ad675,0x000da82cec2d0767,0x000010aec763a8b7}, {0x000d740a4509ba71,0x00033c7b821613b4,0x00091f1e50570107,0x000d902d75c8f715,0x000034c1b6f1dfe1}}, {{0x0007c44d67826eb7,0x000f3c379637b20e,0x000e03a5d1212d3c,0x000a25f14f67877d,0x0000538a2fcf02ba}, {0x00037a19d252415f,0x000f7eb4b587133c,0x00049d1d97db3904,0x0004b96d40d7574c,0x00001126b9a9801c}}, {{0x000aeb9c56729fc9,0x000857a8bd8539a7,0x0009d10c621a5944,0x000afb47c6da5d04,0x00003a4c4a955197}, {0x000539c259338612,0x000a07494d9dd185,0x000e7bfa94994bcb,0x000236cf033de14c,0x00002e9b000521f9}}, {{0x0008110399492969,0x000aa61db1b544e3,0x0006eaff55b63827,0x00028fae5323ed20,0x000042370d3521f4}, {0x000af2ee0d985a17,0x000b0239846df2ca,0x0006312f8192cc64,0x0001080c0b8f47ae,0x0000dc61f9206620}}, }, {/* digit=2 [{1,2,3,..,}]*([2^10]*G) */ {{0x00081e144cc3adda,0x0005e7be82cf4f70,0x000dd6472d5ffa1d,0x000862e9890b6c0e,0x0000da26e1aded17}, {0x000271563483caaf,0x00083f6077fd276f,0x000466e3ce6924cd,0x000d1e15a7fe980a,0x00001c794b1a1902}}, {{0x00024b9eb7926b83,0x00039dbe55093d2b,0x000dd640bbff88cb,0x000d45a0f399afe4,0x0000c5fe1305f76e}, {0x00062f43764fb3df,0x00074151b62d6f35,0x0009ce5f37b5af31,0x00090ee5bd0bc7d7,0x0000daf6b21dc668}}, {{0x0007fe891e5d7d3f,0x000683a076783202,0x000dfdd61f14b7d1,0x000f48088497b3c0,0x00007c2eec11a8c4}, {0x00073f43756e621a,0x000f7825b948aa55,0x000878572c013a23,0x0001837c03b34563,0x00000472beb053a4}}, {{0x000b0e5ab4b35a24,0x0001b5eeaacf6772,0x0005b95801d8b600,0x0001da328f7ce479,0x0000a20ed2a81fb8}, {0x0005cd44fec01e63,0x000c77ff50ad9f68,0x0002d97fd3ed7ddc,0x0004f9160fd2640c,0x0000a2414271b82f}}, {{0x0002cf983dfedc91,0x00047d87631a29ae,0x00029c8d2f843713,0x0002729f57171174,0x00008d15867246d9}, {0x0003ecf69769bb7a,0x00062479ab828305,0x000b0f4b2c55eb85,0x000524bef7791c21,0x0000a5956badd491}}, {{0x000bfa1c5c5ea50e,0x000b8796068184cf,0x000d50942d3baf14,0x000662463984030d,0x00004b7839d2716a}, {0x000f794e7de6dc08,0x0003e22aa7ced5f1,0x000acfeec5cd0f4d,0x000606d295f3f159,0x0000d933553153e0}}, {{0x000533b3cef0d7d8,0x0007abbb4381e652,0x00080f500d94f7b1,0x000bfb038752be0e,0x0000e6e24891e9c9}, {0x000169716caca6a2,0x000818531ad9c975,0x00051ade1866c49d,0x000407a917e23971,0x0000d016ec18037c}}, {{0x0009862d5d721d5b,0x0002abd3a1828000,0x000a2cda40c3357a,0x00008477f3a83b7a,0x000058ae74fa6f83}, {0x0001a812e6dad6be,0x0001143d6c5b2a91,0x00096c4d8de28605,0x00024d6bdccc41f9,0x00007312ec0eae1e}}, {{0x0006e3960e913af1,0x000e88bf140d903f,0x0004890b8b2b58be,0x00024e8deff02535,0x000055810069d2e9}, {0x0005db493c95e5ba,0x00003ae20eb8b575,0x000b6d8e03fac42f,0x000efef377c8c109,0x000043e2b474b47c}}, {{0x000b2fbfacfa4591,0x0008b1b5aa6b5f57,0x000db2092874b149,0x0001daa9e89acac4,0x0000362bf8def438}, {0x0006830b76328a07,0x000028572ae425d7,0x000132f7d38188b7,0x0002c9443e941429,0x0000895a29f92dd4}}, {{0x00078dd5e22cbb29,0x000ae6bb4391cbde,0x000a4273bf449c85,0x000a18b289f357b6,0x0000fce23fdd8e84}, {0x0002730939eb3b47,0x000ba6c32280cfc3,0x000f1346c8b3d982,0x000fc8eac234bad5,0x000081954b4e0769}}, {{0x00068feaae6ee702,0x00053602b0c96faf,0x00094052a78f4cc1,0x000d805e3321a86e,0x0000fb3a0d6934d5}, {0x0008f3bb25a43ba1,0x000109ee2951f3b9,0x000b0612a30bf803,0x0001d06ffee43321,0x00002f775e43eb82}}, {{0x000f805f57209b51,0x0003e952ac8d4fdf,0x000969a6f9bd65ac,0x00075ef2a3abd3c7,0x0000359927f05237}, {0x000463f88d2e8610,0x0009623287c3e09b,0x00070eb7a661d219,0x000684821e64495a,0x0000afbbb1dd67dc}}, {{0x000e3d3acff89f9f,0x000de852251f7418,0x00084658b227f16a,0x000f7ded5bc6e4eb,0x0000066b9c9e90a9}, {0x0009071800a7f873,0x000d2a72862ac236,0x000776da5383ddc0,0x0003182b48465d8a,0x0000d82f64f8e2d8}}, {{0x000104b87453b283,0x00088387344d5852,0x0007cfc08073e812,0x000088000e78e481,0x0000a82ed47c9362}, {0x000304c88de46a44,0x000d17fadf4ae222,0x000c8e108666c94f,0x0000fa00b2d08ea0,0x0000b2955b949e05}}, {{0x00012e76e6485b37,0x000b071c52f8f8d1,0x0004a2f6d4d3e24d,0x000550d8e3ee4168,0x0000161957d91d95}, {0x0001283cdb12a6c3,0x0001fe50e1641963,0x00066cc73bf3fa88,0x000c38c6254b6331,0x0000aefa7aedee8c}}, }, {/* digit=3 [{1,2,3,..,}]*([2^15]*G) */ {{0x000fe623b36f9fd2,0x0003dde19fc079b0,0x0008482ef26543b2,0x000824f36e64a095,0x00003f63771bb095}, {0x000d596b6a1142e5,0x0005e35aac0b14cf,0x000081dd55ea6aac,0x00012a36a0e8bdf3,0x0000fb89d79503dc}}, {{0x00065fce3779ee34,0x000d7d495d9e0f01,0x000284e7ae00e7f9,0x000218dfa4efa220,0x0000564bade87ac6}, {0x000312ac4708e8e4,0x000b671e9adf90e6,0x000684b9f4f5725f,0x000415a95f55ae3d,0x00007f7ccb15e94b}}, {{0x00077e5522e6b693,0x00038bcd6c18da3a,0x00024fd5669c908c,0x0003f6ef1b9e48d9,0x00007c64e36da4bb}, {0x000dbdfee478d7d1,0x000bf193f7a05a4f,0x000cd16dfba75c8b,0x00015174bc1e8456,0x0000fb08f0856fad}}, {{0x000890361a341c13,0x000fdcfd61423617,0x00033316c3604dc5,0x000921d22295eb85,0x0000dbde4ac74af2}, {0x000fc5d1c7eef696,0x0005714f4fa1898a,0x0003c21ca5889680,0x00030aa500216020,0x0000f0d1f30a0ef7}}, {{0x0001b4b12cfe2978,0x000ba92f74e54820,0x000e874e83eee129,0x000c4161fe114ec9,0x000099b055d12c5f}, {0x0007a643a39c8cf8,0x000df8963cc94e47,0x00033f86382f09ef,0x000c62efd3fd8fd3,0x00005132b2b5c949}}, {{0x0008b1dbe7a2af37,0x0008dfb74a72bd9b,0x000879697ec51caa,0x0007d549937a4b63,0x0000c9a9d215c268}, {0x000e44f6ef5f0145,0x0002990c69001773,0x00042161e8abcf41,0x000f29e87bd02281,0x000003937564cb6f}}, {{0x000072232398baaa,0x0001bcfca031766e,0x000029cf2205fee4,0x00090d049f53417a,0x000088c68b8e0238}, {0x00050417337aaa82,0x000ceeb384f4bc27,0x000aba92f9ed364a,0x000a88c0816f8529,0x0000e9e194124e38}}, {{0x000770977f7195ad,0x0006ddeb838ffabf,0x0004f012d8ec8616,0x000b3f1a1285a8bb,0x000068835046a3ea}, {0x00024f8309004c28,0x000593ffe95eee5d,0x000223ea4a96e4b7,0x000a528cdffe12bd,0x0000f5c2ee636739}}, {{0x000e1dda1887395c,0x0005d32a65deecac,0x000a9552940960f3,0x000a35d611ff5c3a,0x000058215b13c1e5}, {0x0009b58f0e1a5240,0x000bf590dfb8d48c,0x000d95662b406856,0x000f82c7605e049c,0x0000dd036eea33ec}}, {{0x000333959145a65f,0x00080a4063373d61,0x0008a52a0cd9bc36,0x00058f92d11be32d,0x00006877b2887a1c}, {0x000819bf5cbdb258,0x00085e090249837a,0x000990e5f2a4fd1d,0x00011ae22a7de774,0x000040fa5a0f9455}}, {{0x00093277946d3f97,0x000397472273fe28,0x000b6ae86e132bd2,0x0000677eeb510c1e,0x000077708c660595}, {0x000c8cd1297029e8,0x000c3bf9305e18e2,0x00085d6d92c61095,0x0005306466c2586b,0x0000ac06c375a1ea}}, {{0x00090b36b0cf82eb,0x00057615b5e7e58e,0x0009c145a6438d24,0x0001ca57b1f8fc66,0x00000d8b2dae6f1e}, {0x000dadbd9184c4d2,0x0005d93d997654d5,0x000147d473dbb18d,0x000608ea3e0f56d1,0x0000afa8c8dc0a48}}, {{0x00039ad653ae3263,0x000a774cbb438712,0x000d4c08314bcf72,0x0004af5737650e20,0x0000df86536410ed}, {0x0006fe7b53ca5557,0x000d3bd5d538d2d8,0x000d38468688cb00,0x0007b65f81bda31a,0x0000ccfe3cd60116}}, {{0x0008c07e3533d77b,0x00097e341c9926e0,0x0002dc4edd7222e6,0x000cf7ed60ec3d8d,0x0000dfe0d902c476}, {0x0009ab61d056605f,0x000596a8551f1fe5,0x000fb8d8ca9ea9df,0x000b0f9489941e47,0x0000eb874ec3a7f1}}, {{0x000181060a716760,0x0008f66a8ad161fc,0x00017231ee852d1a,0x00011f172bbd6564,0x0000d6de7bd3babb}, {0x0006f88c8e347f89,0x00070bd99cc36fde,0x0000769501c58754,0x0003b9e8e54ed034,0x00007f0f335096e8}}, {{0x0006aa9bd7638026,0x000005303da1ed40,0x000e62ec4c21486a,0x00033e01ae291ec7,0x000022a04933f993}, {0x0000c9dbb7a8ee0d,0x000b9c01aedb7fd8,0x000be74ecdc2ed3b,0x00071e65c35a1208,0x0000540cb1b169f6}}, }, {/* digit=4 [{1,2,3,..,}]*([2^20]*G) */ {{0x000746a584c5e205,0x000169dc7035a7a8,0x000548c9b267e4ea,0x0002f3093a15cfb9,0x0000e6e21359bd01}, {0x000cc6a8c8f936e6,0x000455c241dcdf31,0x0005efb868af84d0,0x0002cb03990a6f34,0x0000fef4e6219b96}}, {{0x0008f09257226088,0x000a931cf5c6f636,0x000b4f7ac131260d,0x000828c0eb353bfa,0x00005c78880b7eee}, {0x00081ffc3bdf24eb,0x000b45c3c5a84c15,0x0004e6f405bff75c,0x0000c985e8c83fa1,0x000081d1c0fb295e}}, {{0x000e23d442a8ad11,0x000cf6b9c164f2ef,0x0000aa5e5c3816a7,0x000e6599df2d8bdc,0x000091ae46f220a8}, {0x0007f8700611c5bf,0x00070f1099488366,0x00069595283171ed,0x000a1243a2ecf8ca,0x0000a4a73efe48d1}}, {{0x0007cc8f43a730f8,0x000bb3ab590efcde,0x00003240be89b6f3,0x0005db4823f529ad,0x00002b79aff18bea}, {0x0002856962fe5de3,0x000b30c591f3568f,0x00028a8580c590ad,0x000f4befc74a144a,0x0000b662498e3203}}, {{0x0004ed082dd1b6ad,0x000797b703af48fc,0x0005d6aaa5783a13,0x000d425463cb9a00,0x000031ec55d406ec}, {0x000d33f8e9a76414,0x000cc98d9e7a9f8e,0x000887493625453e,0x00056663beade4ec,0x000042b80509a795}}, {{0x000cf0d6c39765a2,0x000d8c3cca0b91e3,0x000953b50a2db3ac,0x000f1a088f2f08cb,0x0000414582cef43c}, {0x0008bbc60eee9a8a,0x0001d29aa0428dec,0x00032f5d554c79f0,0x00015f381cd5ec65,0x0000672303b6f82e}}, {{0x000582d3bfab839b,0x00037f8adade46df,0x0007a1bc392474e0,0x00097886a7766a14,0x00006940f54bdc0f}, {0x0008ef2f2759f255,0x00095719f4c64473,0x00050c3459dd9578,0x0000d4d859b7f407,0x0000e788bf302218}}, {{0x000afa8719c05631,0x000cac5fc79f376a,0x000750cd3cd8ad2d,0x00008e203fdb9fcb,0x00004ff052f5418b}, {0x00084cf3e2d65208,0x0007944ed509f750,0x000f25b987ebdf0f,0x000837743bf0f2d3,0x00006ad71d02354d}}, {{0x000c9fdfd67ca259,0x0007d0f2015ca839,0x0007b2a65023e626,0x000cba9414a7930e,0x00002dbe373413ed}, {0x00081ee64c2200f7,0x000f1446f2f3f649,0x0001367bb94fb9cd,0x00033091411a6a3f,0x0000985c191ca1e8}}, {{0x000fe9226f435728,0x000add824758b827,0x0009094c1dfd3ab5,0x000d67b15dd23a53,0x00005c0e37ae6623}, {0x00079727be19ae06,0x00067f0d36b5575c,0x000b1ff7e616a339,0x00045341ebb3c826,0x000035b9485740ad}}, {{0x0003c6037e2efeaf,0x0001134a96f6c812,0x0003e4a958d49b50,0x0000fe566a346b97,0x0000176b5bba7de0}, {0x000fa3b82dfa945b,0x000559e429ae1c58,0x0002b187c2eb27a9,0x000bb9a7c67a67a1,0x0000155ba8392298}}, {{0x0003cdada430c0b9,0x000daa96dac692bf,0x000ac326a4702850,0x0005e4391cf0a515,0x00005de4f4a3b8c2}, {0x000ad09e265c17ce,0x0003287b3881b01b,0x000fac5ca24e4546,0x0007a5f43e583ce1,0x000017cb3194ead9}}, {{0x00042073d99bcfab,0x000c38becf6df1a5,0x00045956959db703,0x00090f7e455142d2,0x00000ee51445901b}, {0x000d451e26d994fa,0x00037360caaffc05,0x000a639b17a6062b,0x0008b03f1ded5f4f,0x0000f9303497335b}}, {{0x000924374dcec468,0x000cd4c2b73f6cc3,0x0006cd99c33cfc02,0x000f8902917844f2,0x0000819dd9651773}, {0x0002aa60871f4274,0x0005b6f01c340957,0x000f1f5af8e0cf36,0x000e503fa52988bf,0x0000eb357eb275e8}}, {{0x000248a21fd08616,0x00043bd5a4b63d8f,0x000e2a6bfade3bd6,0x000c5f6b56c953c2,0x000099cd2b5887d6}, {0x000e1be47d05e8f9,0x000318f53732debc,0x000852b081a4fbb1,0x00087a07163beaa5,0x00002c49e6d7ec69}}, {{0x000c8c4868af75df,0x000e55c8c7ead9d0,0x00081ecb0d7325cf,0x0004ecbb471996cc,0x0000f5d55f451182}, {0x00045411977a0ee8,0x0004f22038c6be31,0x0004bb4955085c4c,0x000081ad5335bff9,0x000094ad8a748e2a}}, }, {/* digit=5 [{1,2,3,..,}]*([2^25]*G) */ {{0x00034b22c11bb373,0x000dbd4c74a35402,0x000c5f25d2d0366d,0x000142c9a968daee,0x0000660106897b63}, {0x0006d2c68d7b6d44,0x0008cc84294207cd,0x00068b1eea8f74f0,0x000ee4a275140477,0x0000b5f7e8a3e62a}}, {{0x0009f0b879fbbed4,0x00069a9d1869f236,0x000766f450ff0ae8,0x0000fc1251d75956,0x0000984d8c06be8d}, {0x00095a6d21008f03,0x00000a1a1c497ecc,0x0006c50f329bd54a,0x0002517b9828c5d2,0x00002c0087c81d0d}}, {{0x000eb6662b5f3af3,0x0000dabb373447fe,0x000f35cb1cefab56,0x000eb9149de60e19,0x00009f8db14457f0}, {0x000cc5b3c61bfd60,0x000d41216703ffae,0x0004e1cc2a5a4d41,0x0009537f8fabed22,0x0000d5a8186871ad}}, {{0x0008ea601799a527,0x0001486d2952190d,0x000ff2a7ca20cec4,0x000d36c062ffb27f,0x000041b32e5e9f19}, {0x00081814eb57d471,0x000406aef06bf80d,0x000ecb5887a2d0ed,0x000f5af9735fb01c,0x0000641caaad6061}}, {{0x000d171656e8c3aa,0x00027acd0705ae2a,0x000b6055cc0e2a46,0x00026d606f6a8aa0,0x0000f4513d7cb65a}, {0x0009e14d616d5bcb,0x0004c1253b1f3f54,0x000ce243a64ee395,0x000e7738b10bc1b8,0x0000cbeace6413a4}}, {{0x0002256f779d6a77,0x000ca9e7284e68d3,0x000f3b15320423b4,0x0007036e19aa1b38,0x00003d0b6c2f444f}, {0x00061489c64e6a37,0x0006c72562246661,0x00033156399587c3,0x00002dff5277fe61,0x0000174ad4b16565}}, {{0x000fc920133918d8,0x000e32c9ef97ec1f,0x0006cbb9a15d9bf5,0x000f5cf885b542fc,0x0000abe6453d720c}, {0x0005dced4ec68aba,0x0003879c24a34e71,0x000bb61cf57a6761,0x000002d88ed52a31,0x0000ba824459437a}}, {{0x000824f20151427a,0x0005f24302067f99,0x000112357206828b,0x0004ec0a9097d7e1,0x0000cf9a2f2a9e41}, {0x000c9da279153564,0x0006c01efee3dbda,0x000b288e27e0734b,0x00009c14fab5bbd2,0x0000c630fc5362dd}}, {{0x0003e66bd70a5e18,0x0001505de7136d88,0x000d8487d9bd884c,0x000404c8d9d445d4,0x0000440cd8b8eeae}, {0x0000f293d26f83eb,0x000f72a3c5e4a3cd,0x000fa2ca73fd9452,0x000096b3a078663f,0x0000feadd29b0d4a}}, {{0x000a559d68432ba6,0x000b733915db13ae,0x000e8da08940043f,0x0005bae76c7c94e2,0x0000b1630c4a4306}, {0x000546d19f06c75d,0x00015eb35abdd6d8,0x000157d8e7e1e98c,0x000074a51c9310f0,0x0000ef84328c6fa6}}, {{0x000993c3a7a4e0e9,0x000f0d79d314765b,0x00019eb24fb8f4ae,0x000c8bcea2c50e2a,0x000025016e64891b}, {0x000afdc3ad1ece76,0x000c908fabe28f70,0x000f6132b0abba84,0x000d76aa9922c815,0x0000c021373bd076}}, {{0x0002615a44539610,0x000b993d112c00af,0x000cdd6521705494,0x000cb30032e12aa1,0x0000ebfa612046d9}, {0x000a9f31b63728c8,0x00025e022b059f03,0x00077c5c98f3618a,0x00077c55b24d903e,0x000037838a3f2acb}}, {{0x000cbd98fceb0471,0x00052f8b11a1fe65,0x000ec802fde872ef,0x00081d8aba0d3d8f,0x000039f1d32aa9f3}, {0x000aed9c587958d1,0x000ca9f6a7da0721,0x0005d9d06066a015,0x000a1ef59ec4e3ed,0x000044285717cbac}}, {{0x0000fffe298cdf56,0x00041b2e51b666fe,0x000d3afa43f61bea,0x000e2f1d372117ba,0x0000521a09d4f656}, {0x000c966e8a58fe76,0x0000fa47ebc7b3b8,0x0004be57325203a1,0x00003c9e81588d5c,0x0000132e2f37f49a}}, {{0x000b0130f8c2c991,0x000fe17725c2ec1a,0x0000a980b60e8968,0x000cb1d1a4a59394,0x00005ed15b030e9c}, {0x00054cc64a00bec8,0x0002c168738277d7,0x0001fb65190d09c3,0x000e52a94fe02dc3,0x0000372cd1a9c94a}}, {{0x000107a1ac2703b2,0x00084bc857b58537,0x000daccd1b49258d,0x00052937df14debc,0x00004ab68d7e4ae8}, {0x000b5d4734e59d08,0x00084495cc807ed8,0x0001db9b35f8740c,0x0005be04aedd5a29,0x00000b360f8cfb99}}, }, {/* digit=6 [{1,2,3,..,}]*([2^30]*G) */ {{0x000c68da61a76fa3,0x000d9a1554dc55d5,0x0003b279c598b441,0x000efca39923b977,0x00003331d3c66bf9}, {0x000848e298de399d,0x0006d1a27f562d4c,0x000b8ab70cfdb8e7,0x0009b9c4c855ea57,0x0000cdb9daf3f787}}, {{0x00007367f636a38c,0x00064e76d5cb4c4f,0x000b68b8b9f943fb,0x000a1ef03510baa8,0x0000246780b5ed07}, {0x00014156d549fc2b,0x0000b07781ca3c05,0x000d95413c2953f3,0x0002e2e55e2c69d8,0x0000300fadd2bd28}}, {{0x0001163c27901b4b,0x000fd99b8bf3a14b,0x000c6da0afd9236d,0x00029692b091eccb,0x0000b1dac700ad1d}, {0x0001d53a91cf76e1,0x0002c31f1ee780e6,0x000efcf774110a41,0x000d761d87c3ba13,0x0000f374bb4ef450}}, {{0x00086024147519ad,0x000b56b372f02028,0x00085ebc8d0981ea,0x0008e8d9d4a7caa7,0x0000953c50eabdf5}, {0x00061ccfd590f8f8,0x000ac4e6c9179d63,0x000eb64cf72e9626,0x0008f2ffd9611022,0x000063ebb7f1eb28}}, {{0x0000a0a097e4403b,0x00056985466515e1,0x0007d4826cb3d0a8,0x000838d8d8e211d6,0x000039af66ebb9d2}, {0x0004588bd475ca8d,0x0005f077b80ba5f9,0x00027c26ce06b796,0x0005e02edb1485da,0x0000290d33bce0fd}}, {{0x00002f31306583d2,0x0000237c622e6862,0x0006a7bc805b10da,0x000e439f9aaa0f07,0x00005e94efbaf8f4}, {0x000c9b7fa3dc26dc,0x0002d6ff03c58a35,0x000c394cee0e5fb9,0x000e5fe77e3843eb,0x0000ede65964361d}}, {{0x00075090c22b5403,0x000a87c267d4bf90,0x000b0d6932cde42a,0x0000d98a18f9ed5a,0x0000ba62aa69e466}, {0x000f97bab9ea96a6,0x000283b60e32b24b,0x0004d9bd55d03964,0x0006a3ee6a45067c,0x000066c5b9eded4a}}, {{0x0007cf5678a31b0f,0x000d4998b620877b,0x0000fb396d50301a,0x0002a5834257c5c0,0x00009fb18a0f4e67}, {0x000d8ebe8758851b,0x0005ad99ba44ff8b,0x000fd93b71e64e4c,0x000b8b9b8eaedf7d,0x0000a2f2a98b4e76}}, {{0x000a2f09b56ddbdb,0x000bda2f1cf3ae02,0x0009dff0d1339b5a,0x00043d42b569c783,0x00000b9e865aee9a}, {0x000ca4177bb064e9,0x00026d249f634ff8,0x0006f689a145a281,0x000f5daab7beacf8,0x0000bafec2791d35}}, {{0x0003fddae57c7b7a,0x00017b932522bba2,0x0006d4aa3345342f,0x000b615d9c80fe55,0x000003907bb0525b}, {0x00010e1ff2189336,0x00044a52117b38b0,0x000f2e6eac066b65,0x0002b22e14192094,0x00006a27dca6d32f}}, {{0x000b121fbabbe926,0x000b81330076b2e6,0x000890015281850f,0x0007f4a93581ec97,0x00009b1ddedd5ff7}, {0x000b18fab1051053,0x0001789ccfef7cf0,0x000914009953ced3,0x0008ad0151f85feb,0x0000c9f1b87b8ed4}}, {{0x00007e0e90fb21e5,0x00006ba7fca1a18f,0x000cd67b500fd2b8,0x0007f6d0387f2795,0x0000b89a4e823970}, {0x000ad3f894407ce5,0x00041c2261328f83,0x00006c13ba0025b9,0x000025779563c7f9,0x0000f548f319e7bb}}, {{0x00089494fde0c1fc,0x000e25b6ec20ff75,0x000e1db6cbf8a1ab,0x00058eb02278fb87,0x0000447ad7af5ed6}, {0x000aa3803d0ccf24,0x0008419a7c0348d4,0x00017cecc80acb33,0x000d825bc7c89e6e,0x00006736b8b43be1}}, {{0x000f742d43b5eaaa,0x00063fa59b852126,0x0006bfd45054a076,0x000a8efd0d5e3612,0x00001f8fbd7d84f8}, {0x00080f5d563fccc1,0x0005e280a9283176,0x000b578cf48ca505,0x000514d00b81b227,0x00000aad9183994a}}, {{0x000301f358bcdc04,0x0008ca9d47f8e63f,0x00043d43a07689e9,0x000903df689e2f4f,0x0000d542a16d0920}, {0x00093d59ca0a7072,0x00056ac68065aea2,0x00090008cd061fe4,0x000db5f033bf1b00,0x00009749558e08a6}}, {{0x000d3a7c35d87949,0x00077356bae50ee6,0x0003322fd042e655,0x0009670f59698d64,0x0000379ae15e0a61}, {0x000ae62fcc9981ea,0x0000cd2934c664b9,0x0004e65ebaed3d63,0x0004278454b3025e,0x0000b09f64899950}}, }, {/* digit=7 [{1,2,3,..,}]*([2^35]*G) */ {{0x0003a1222248acc7,0x000ec264e366b208,0x000fdee281f6ec0e,0x000bb4e659b7045a,0x0000a823a4156430}, {0x0002a04e1900a791,0x000ab9ee65762459,0x0005ea54acde09d4,0x0005a742b6463f4b,0x0000efe9ed3e3ca6}}, {{0x0006dbe305406dd9,0x000f4d5d1957e27a,0x0007d4d8f8eb7dc7,0x000de4654a687638,0x0000c47940a57762}, {0x0005b5d99b307781,0x00065e793682be4d,0x000c740e325380c5,0x0004ae502d37f3da,0x000040deabe2566e}}, {{0x000d067afd32acfd,0x000a11f71ccf4481,0x00096f2dad8f0fcc,0x0003f90208dd0cb5,0x0000049d7316aad9}, {0x000263d42ab580e7,0x0000b3f707b4c79f,0x0005e0eda09411bb,0x0004021cfde1ff83,0x0000270749100f03}}, {{0x0006126c49a861ec,0x0005214f0d06eaee,0x0009bfc17024f3b6,0x00038091a3f1e8c6,0x00003c3a8ea67686}, {0x000752cb103d4c8d,0x0002c218b36b3400,0x00051504a02bc461,0x000bf9f67f75eb76,0x00006848b57a02ae}}, {{0x00002e6c30fa92bf,0x000caa552784bd98,0x00083169b5a70d96,0x000227a085c4ea3f,0x0000a9423bbf6908}, {0x000be12fe97a5b9f,0x000881b991182ffe,0x00017884685da604,0x00018dacbc2f7f63,0x0000d96bc7181532}}, {{0x00081db1782269b6,0x0008c597e5509583,0x000385153ae34bf7,0x0000485b5c60645f,0x0000f0e96b043088}, {0x000021577884456e,0x000b89310ea7bf6a,0x000fad2deb3b5688,0x000d4c37c9429504,0x0000020f0e5f7896}}, {{0x000a0ab0976505f7,0x0002995e2ec5730b,0x00031ab71567f681,0x000b9ed706201063,0x00002cfa977b1d22}, {0x0005ead8a2373da8,0x0003fba45a6833e5,0x000029d15a8d0d5f,0x0009f33a1d8f9c03,0x0000f34f1cd7c55b}}, {{0x000428dbbe5a1a9a,0x000e9126bd67cca4,0x0001058268187fd5,0x00019f6036973a48,0x000039b666458bd6}, {0x000deef2d65a8087,0x000f24636b196d42,0x0005d564c4969044,0x0000778611ee47dd,0x0000b2f3a4a42873}}, {{0x0007d45300eb294a,0x000d769c14949415,0x000a47aa92b2a656,0x000ea42000dd76d3,0x00002864e5046243}, {0x0006c47db89842e4,0x000721479fb78271,0x000b2f6dc12dfd7d,0x000d66fb9a2c56e0,0x00006be862b17f85}}, {{0x000d8dd0f82b2148,0x00097103cbc603b0,0x000d79e19460c34f,0x0007f8732e5c0318,0x0000b8888bb28411}, {0x00037dcc07226779,0x00088c1c0f278f3c,0x000f7a0c610d21be,0x0000e0447c8468e0,0x0000bf022143decc}}, {{0x0007d1242b48b998,0x000cc84240960baa,0x000fb5cfb1bcb665,0x00010d0b847cd6eb,0x00007c2ae571ad4d}, {0x000b1220de367261,0x00082fdfbd21f1cb,0x00079d460e7043c6,0x0002cb3bd0826a4e,0x00001f5e5985bd1a}}, {{0x0004160b7fe7b6e0,0x000a400a3fb29755,0x00028ca1e7d16189,0x0008ccd73e9beae3,0x0000dd04b97e793d}, {0x0003c9b506db8cc0,0x000ecf38814ca9c8,0x0004b45e65cd47aa,0x000a8426fc430db6,0x000079b5499d818e}}, {{0x0001102c1c24a3b9,0x00078c161c1aebb0,0x000f00a4aca24e56,0x000c7a803eea6936,0x0000ad76ee906176}, {0x0001fc2538e0ff72,0x00094604b3b09745,0x00049cfd794f8980,0x000f694311436e32,0x00007b4a7bd61224}}, {{0x000d21ae0ac29416,0x000462d3193703b5,0x000c992d0279b025,0x0001f2d307c052ca,0x0000aa7cb934fa8b}, {0x00025800d37c7a50,0x0007342d54225a18,0x000d2ef9213380c3,0x0003c692ac2d66d5,0x000035a70c9030c6}}, {{0x00025dd4ce4f152f,0x000109df7c06c160,0x000e4bb141f419a7,0x0004cd7d5b221491,0x0000c43c6cd739fb}, {0x0006591925d6b2de,0x00028218659849f0,0x0001b16294b37d9d,0x000e04ac54a971d0,0x00001a9c2a031d50}}, {{0x000b78571ba18615,0x000c80c8f93d5109,0x00033bb9348b22d5,0x000d0898fa84a786,0x00003fba6baaaebb}, {0x0007df3e5eea7d82,0x000648ca71587ff2,0x0006f1a05521c879,0x000ee499d5133bce,0x0000d50cd541d0eb}}, }, {/* digit=8 [{1,2,3,..,}]*([2^40]*G) */ {{0x0006d65533ef2177,0x000453ca2e87889f,0x0002b41677158c7e,0x00057f8b670dfbdc,0x00005910a01f44c2}, {0x000bf07cf88577d2,0x0000c45e2acef336,0x000a23d852224525,0x000f580ed92e8d7c,0x00009f8be4c4b812}}, {{0x000b2452133ffd9d,0x0000b30f1a20fbb9,0x000a1f52a39a8b2f,0x000df7784bc97dd5,0x00006aebf57740ed}, {0x0007acb76ccdac60,0x000c1586ff273225,0x000de7dd1af4d36e,0x000c168eaa8863f8,0x0000045d5cf88647}}, {{0x000414351facc618,0x000d668a25bcc51e,0x000f872edbaf2647,0x0006590f5271a00f,0x0000f32ef99bd2d9}, {0x000488c7593cbd4c,0x000c42b82fabca12,0x000eb3f16ed266c5,0x000fe24a2f78ad14,0x000034049490d47a}}, {{0x000d574c005979da,0x0001ca40e350a6f3,0x000e2ecf9c2072b4,0x00044e5ca5c1568d,0x00008c8bf5c45153}, {0x000e555114df14a7,0x000d8dc5ec6b97ae,0x000a85418d4374a4,0x000f78054cc28f2c,0x00001cb9e2843c41}}, {{0x0006702094704963,0x000dbbd2381509c1,0x000dd4398a489a5e,0x00069694dde4648e,0x0000ca7b94ab0111}, {0x0005d682ad636a41,0x0004f8dc5f1e3c38,0x000a219436702702,0x00069dfc1965deaf,0x00008666e16710be}}, {{0x000fd350369c8e10,0x0002b9dc843b6792,0x00002e2ab9271aa6,0x0003838711a4b14d,0x00002b2a3e27ee1a}, {0x000e35f0e2b379be,0x000bf652ab25b226,0x0005601063d3de39,0x000876cca6d4c93b,0x0000ced0cf5a95bd}}, {{0x000b4ca2a604b3b7,0x0003ca61676245be,0x0008b806e56f6518,0x000480852f5a7097,0x0000aa3978781dc4}, {0x000ac2a0e01fabc4,0x0004e37d99f9e13f,0x000211ffe7c6ee8a,0x0003eae51384ee05,0x0000ff6976d5bc9d}}, {{0x000507903605c397,0x000e3142c96c8910,0x000923684f0843d9,0x0008938374493416,0x000032caa306a0a2}, {0x000c27061160170e,0x000b637fbaa3b2e8,0x000eda3acc32788c,0x000e0659cd818ea6,0x00002e9423a7e2b2}}, {{0x000492316e043a20,0x00011dd3d209dde0,0x00031ebe898a4526,0x000abdeaf9f61bd4,0x00000919f4dbaf56}, {0x00017db6d8774b1e,0x000b78e0e309e424,0x000df81ea5fc5279,0x000c7e84aa40613a,0x0000f419edb9c627}}, {{0x000759239ef620fd,0x000fa4fa29c43919,0x000416d839d47283,0x0002687e428fa39d,0x00001a7c251f9f30}, {0x0006e1cd746218f3,0x0007e10d967e4607,0x0000ae61ff3ad6ee,0x000929cbb5f434a0,0x0000cd2c019b0d4c}}, {{0x000d0537a4af00f8,0x00064a294614fa24,0x00082182e3f93892,0x0009468d700c1839,0x00000133443ccc59}, {0x0007106ec87c9255,0x000bbed6665cf039,0x000cca8b562bd59f,0x000a3098414348c7,0x000074c7620ef9f0}}, {{0x000d39b0260e52a4,0x000c506533256967,0x000ca7954d42585c,0x0007b2cd9bd60521,0x0000fa20877c1ed5}, {0x000eff8e34a0bbeb,0x000bd4f6ef6460c1,0x000af848356b0040,0x00061378be2b24b1,0x00002278164a5531}}, {{0x00042e2bb8b6a071,0x000eba23f86a95be,0x0004ce47064be74e,0x00076a973d74fd15,0x0000c2d2857e8dc0}, {0x0001c575a8878682,0x000b1de64818b1fa,0x0004e896738df8e0,0x00076cb88e52f9c3,0x000074b4f01ab4cc}}, {{0x0001ec2c11c208bc,0x00098e3a723459c8,0x000a089d8240207d,0x0000718957eb80f4,0x000086960bce137a}, {0x00054fd7f1a932c2,0x0004b3f2fa17de11,0x00011c0ebb517fe7,0x000d360d5d945571,0x0000aa33789a0929}}, {{0x00005b4f8b7559df,0x000c0ae292003f5c,0x000532acc0be4c7a,0x000284ed6d3ef756,0x00006c3ed88dea7a}, {0x000b0a8f46ec59b3,0x0004bcea6c83e463,0x000dc836b531d9b1,0x000f0b0d6bdbafc2,0x0000ee501e95ab27}}, {{0x00075455922ac1c3,0x000c752b3f638df2,0x000de57c4a7b3ef5,0x00008b5e77b21471,0x00001682c10b34c0}, {0x00024f04bd55d319,0x000587b61c71c768,0x000a5089db6d1c08,0x000d3ea1db0903c2,0x0000c092172a84e5}}, }, {/* digit=9 [{1,2,3,..,}]*([2^45]*G) */ {{0x0005035ea6c39976,0x000a62610bef5ace,0x00080dd3954259aa,0x000a398f18bb3f3c,0x0000910b95bbfc3f}, {0x000f51043e09aee6,0x000f47675665fce2,0x00072db61ced56c9,0x000e68b0e265acd8,0x0000982812f0e9fc}}, {{0x0003d931341ed7a4,0x000c67b59d49b8fa,0x000b8c4a44223272,0x0002e3fdcb194783,0x0000e413c022d130}, {0x0009127e17e44ceb,0x000483b3adfb6d99,0x000aa96caee86bf7,0x00047d46902fe625,0x000073540e595aae}}, {{0x000ef6c872b4a606,0x0003e613521bcc50,0x0003e15d1ab2a34a,0x000511d9c5c19098,0x00001dde5dfb9905}, {0x000f6219f2275f33,0x0006151d894be417,0x000b0bdaa0750c8b,0x0009bd45b04ab978,0x0000bfd9fd475858}}, {{0x000bfabaf95894c5,0x0006d76b2241aafc,0x000dda48b7b9bdc0,0x0004df9af983625b,0x0000977faf2f3fcb}, {0x00042ef052c4b5b7,0x0000967591f0bed0,0x000f24ec79fe87f7,0x000f1b589c73ca22,0x0000d37fa9f564a9}}, {{0x000148045ee2f40e,0x000e616b60cfbd78,0x00049a8c475e354a,0x000535fe0b58a18d,0x000040e94e3da359}, {0x000a59f62accd765,0x000a3c762837bd4f,0x0008c277b05cf466,0x00074065abda9944,0x0000a9e01bf98b13}}, {{0x00055e6f2606a828,0x000110f2fb57b51e,0x000a4e37ce25f706,0x0007062cef6c2ab1,0x000064e359dddcf2}, {0x0006b187ce573162,0x00001a96b23d479e,0x000f16df72cab250,0x0008b5cd4898628e,0x0000056538d0f375}}, {{0x000a0c3d41d3bd3d,0x000837a26bdeef69,0x0002edf9fb533b8c,0x000af012801d97db,0x0000c4a826ab1877}, {0x00058513d590dbeb,0x000b3e4e93576c1c,0x000b3337484632f6,0x0002e6236d36b779,0x000046833e44bbca}}, {{0x00064880a750c0f3,0x00031e548e83cc7a,0x000110f0539bacfe,0x0005880d418c760c,0x0000e4daa4ce1f11}, {0x000e7b55ffc69ff6,0x000c320531272733,0x00022df9446f147b,0x000b7c285b2434d7,0x0000a444f6646fc6}}, {{0x000e4bb346ac9cbf,0x000339811bb2008b,0x0001540c12e6cb02,0x000e46b6ccc747f4,0x0000119334febf6d}, {0x000ffe9cc97fe6e0,0x000bf3d828834e6b,0x0003dd1c77f4b578,0x000495459db72275,0x00005843cd82066b}}, {{0x0008cd5dbf2af333,0x000e7f6b0eab7cb8,0x00040d844ded9566,0x00067fa1caf5488e,0x0000ae59bd6ace1f}, {0x000ad33dd82429e5,0x000b6c4467c7acf4,0x00083d011cc7ebd2,0x000db7a4f6e95de7,0x0000197e39166e92}}, {{0x000031885e7a4af1,0x0000e7a6878dd4f2,0x000051913291bf9a,0x0000349dd8b6eebd,0x000074f5125036be}, {0x000364527f601893,0x000d5b37ec732ac3,0x000fdb42ed8902ee,0x000421246166a11c,0x00001c4e3b837076}}, {{0x0009dfdbc6ebdfb0,0x000589de549b7de2,0x000f26a64a1ee450,0x000980fd7181aa3e,0x000003179eedf2f3}, {0x0004d30fd71bc789,0x00042e86a5831bce,0x000b85711eb842b1,0x000405500125dc5e,0x0000f5869848f11f}}, {{0x000089eb833eccba,0x0009dbc51c795b5a,0x000be0e93c1b3077,0x0001724581157f9f,0x0000b487d69fb29b}, {0x00051082222f24bf,0x000c06dd35dfc725,0x000c24afe338cd22,0x0006eca2010e6f5f,0x00008298f16581d4}}, {{0x000f723042389edd,0x0004d54b19722ce7,0x000251d75df7de0d,0x0008c7e8ea2e142c,0x000022a4d38c4e8e}, {0x00058566c29c8bcf,0x000d2d1e201ee999,0x000c885c99fefdbf,0x000c6fc97d946eda,0x00006ea9768c38ea}}, {{0x000a8e974e75a2ec,0x000dedac968f9aac,0x000306befcda6fc1,0x0007f87f6651bf46,0x00007445e4f8b2ed}, {0x00012d8d1571ac12,0x0004baf3a679584a,0x0003fbc43684846c,0x0004f2afc622a986,0x0000f9e101e0a681}}, {{0x000465ac3f16ea83,0x000d82f1d11c7a1a,0x00068a172115a461,0x0006981767dd956c,0x0000392f2ec013a4}, {0x0009ccde526cdc7f,0x000b32292b81c7a9,0x000d391988e537fd,0x00052c86d8cf69a6,0x0000fc5ff4414468}}, }, {/* digit=10 [{1,2,3,..,}]*([2^50]*G) */ {{0x0004f7ea90567e6d,0x0006e6ae5cb797b1,0x00010903d513257b,0x000723b5454a3c9f,0x00008d2c9ae39bc3}, {0x00093246b29cb44f,0x000c87c8cbac38da,0x000918e42b540a21,0x00014dabbfe43501,0x0000ffa707b46c36}}, {{0x000e05b1cb76219d,0x0000a1567e7e56c2,0x000c4c9100ec0bf9,0x0004d917076f8661,0x000067b085c8abc0}, {0x00004595e93a96a9,0x000a6bdc249a9fb9,0x000dd0bb77526c1e,0x0006947d44d367ec,0x000053999182dc0d}}, {{0x000c583a4c506ece,0x0007f1acfe972ccb,0x000f1aea2957ed18,0x00062cabaed83312,0x0000f2a6cb563253}, {0x000de428e195c43b,0x00095e6050c6130d,0x000686a5dc842025,0x0004a77da972a708,0x000052999a29508b}}, {{0x0009167ceca9754a,0x0005ab7939a083f4,0x0003fd0bf426d2cf,0x0004e18555e35572,0x000096e6d0764f14}, {0x000a8dd87880e616,0x00058508e4d54768,0x000b65e151554381,0x000f9fa9d7e772b1,0x00003439dd70c302}}, {{0x000f8e1698e04cc2,0x0002f69005c8b11d,0x0003c6179877be20,0x000c0512749e8c4f,0x0000dbc9d0a9853f}, {0x0004f939454d9370,0x000db4800e1b187d,0x0005e68e8e682ce9,0x00085ba9129ad816,0x0000fe29735be7f7}}, {{0x0009ccf3a4434b4b,0x00006a7954dc3101,0x0004972a7a345811,0x0008dcf9dac80de3,0x0000043d05524f6b}, {0x000319e11137b1a0,0x000eed5cc03f021c,0x000ea5ad400a754c,0x0005b60aa2c794cb,0x000093e67f470c01}}, {{0x0000351d598d7107,0x00065b3a4da420ac,0x00071de1f272c416,0x000b0f6b82fe1aca,0x000046e79f348f54}, {0x000c7364b573e9b5,0x0006ad4b50406e7f,0x00098d87b75d03f4,0x000da10c1cc36d0b,0x000013ba3f16f472}}, {{0x0003145983c38b5e,0x000b837abc8b859d,0x000ff7be6b14f176,0x000a594793fb9dca,0x0000be5a56015a66}, {0x0001dcd9f87dc596,0x00039bdbf5607cec,0x000eb32577c595cd,0x0005fcfb543b2226,0x0000908064724c93}}, {{0x000b70678a6513b9,0x000a0edb1943dca3,0x0006e2dd892ea4a2,0x00089372642216db,0x0000b45d0b52fd57}, {0x00070dbc69d11ae9,0x0008bc57595f114e,0x00077c2721477dd1,0x00059c2c2208b4ec,0x00005c5b4d86b68f}}, {{0x0001fa47ea67c77a,0x000f43ea810cfe54,0x00001d374952bd2a,0x00036dd91fef568d,0x00003a1c621af113}, {0x000d5a9c7ec6d792,0x000f1225c3425ad0,0x00069601bff7038a,0x00047ce03c6689bc,0x00005059bc765e87}}, {{0x000c80676cb25661,0x0001a24892d99a75,0x00008fe458f76acb,0x0007d86ae7b9cc1f,0x00009ef73297a490}, {0x000ab715f228bf03,0x0009517032d72db4,0x000abe3c0f3cdea3,0x00025bdb1f482edc,0x0000baf76b4eb863}}, {{0x000688eadd70482e,0x00099b4a4e8a6aac,0x0008a6eef708de92,0x000c4295b6dd7375,0x0000a4bf353525b3}, {0x0001f2c87912868c,0x00052f09297a1004,0x000f3860ab1b1be9,0x000f4a59ae23c5a9,0x00004f0f83a115dc}}, {{0x00027bf8538a5c69,0x000cf9abff17c71e,0x00071e3da195c63d,0x000fa06d3152851b,0x0000cbdfda88a680}, {0x00076ca849d7eab8,0x000abc2732719db8,0x00008dceaebe2764,0x000b6fe63357e3f2,0x0000c5bd833d65b1}}, {{0x0000d7c2fa4f1264,0x00051c99a2327590,0x00025e0c308a3b86,0x000edee478b6bfdb,0x000082cc2c2b1db2}, {0x0007e645f321bb80,0x000b9a8005b437df,0x0008c19588a93821,0x000d0a3fa2f10ccc,0x0000d3322182c269}}, {{0x00014df3fd165e81,0x0008f61f8811ba55,0x000ef9f00499fd6a,0x000e8a62cd1fe0bf,0x000020a4bb989ad7}, {0x000d0955f4a5ac5d,0x0000c5a7a2f0f2ff,0x00017baf1cfd174f,0x000089042301ba9d,0x00002fa487b47f22}}, {{0x00052381d531696e,0x000fa8cdde69b934,0x00086afc757201bf,0x000ea7fde922519a,0x000030438969d35c}, {0x000c1e18555970de,0x00084535935e7608,0x0002ea38b8267dfa,0x0008b4f4c60a5732,0x00000bf7978604ef}}, }, {/* digit=11 [{1,2,3,..,}]*([2^55]*G) */ {{0x000ea68c094dbb56,0x000e7968d4106233,0x000b3002db77d062,0x000d57de719bbc58,0x00008e7dd3d9dc49}, {0x0005740013a5e585,0x0006ec9e3c1b8d82,0x00099b6ab2131174,0x0008f1bcb0a2a77c,0x0000c48a3b412f88}}, {{0x0003e91991724f36,0x000bd9cbd686c791,0x000d4fc1e5eda799,0x000d547db595c763,0x0000b63b80c0c4fe}, {0x000fc697e5fb5166,0x000a70f1c9646ea0,0x000a92ca5737708b,0x00067a3628745f11,0x00001f37958fa869}}, {{0x000fd610979e6b3b,0x0004e3d407235320,0x00080bacc1d0bd3e,0x0005145ac006fcaa,0x00001d9c60f82002}, {0x0007ed0af780b927,0x000e10a9ce31610e,0x00020b54bf5bf446,0x0006c2d41c011d3c,0x00007f76da189159}}, {{0x0009b2caa6650728,0x00046fd324ef9af3,0x00027bd3178322fa,0x000aafbd153394c3,0x00001d5f271b129d}, {0x0000c42f48027f5b,0x000bd536e717c72e,0x000369d0faa40cdb,0x0004e6445a657a2d,0x000003bbfc59a7f7}}, {{0x000d5429b6a42eae,0x00045daf41b97a04,0x0006b0b89fa597e8,0x0003dd6c58ec2772,0x0000d8eb16ae30d4}, {0x000e5e1ec9dcf577,0x0000f97cff8165e1,0x0006e2b22b7a770c,0x0002b6ae6d918f9f,0x0000c277a9b364e8}}, {{0x000c4180d738ded3,0x0000b0de572946a8,0x000a816756f1a5bb,0x0003d4c10230b98b,0x00002c6f30c412b3}, {0x000129dd8fffb620,0x0007b459bf057559,0x0003b67766a281b4,0x00073a77c1bd3afa,0x0000709b38078299}}, {{0x000e0c1da36cb47f,0x000a2e0210f00875,0x0003787c8fdf5b7c,0x00041e8e0c7e4d3a,0x0000043f5271b1c7}, {0x0001b006d74d72d5,0x0002e8b45ba976df,0x0006b797a0514df7,0x000c395ecf7c3e0a,0x0000e30b2862deaa}}, {{0x000b232a3326505c,0x00022e1d41bf8c26,0x000e32afa38d6927,0x000a864459453eff,0x0000e8143ae3cb3e}, {0x000c1fa7e6ab6665,0x000fd2286264932e,0x00036f8ed6cd2d22,0x0005baf59a46fe67,0x00000bf0d00eeca8}}, {{0x0008f7d605238a52,0x0002248496ab15c7,0x00010acc1e9d8784,0x0004e2afcf75d0d2,0x0000948f2297c8c1}, {0x000d76de8daf0cb3,0x0004703be800e81f,0x00078d30cd02d11e,0x0009cadc4df35187,0x0000482bc96c6513}}, {{0x0005852877a21ec5,0x0006bf537a940b82,0x000a9a6a2300414a,0x000bffef1cba4021,0x00000824eeec6943}, {0x000fcecf83cba5d5,0x000843b4f3c0a0db,0x000f24dd7f953814,0x0009dd1174416248,0x0000322d64e34fb0}}, {{0x000cf278a448bbc2,0x000fa85251da56b6,0x000e79b240ca898d,0x0001a77082cad836,0x0000e7b9ed33a8e5}, {0x000318a43e1c8025,0x00037bf8689ddc7d,0x000071b1a4750e52,0x000dc14887a072f0,0x00002090f87d14bf}}, {{0x00073843d9325f3b,0x00004371cb845744,0x0001e36c5a9bef2d,0x000f71c7d2188ba6,0x0000bd6a7d87602d}, {0x000a9028f61bc0b8,0x000ceed0b6a1ba3a,0x0006e8298f49085e,0x00001d0bc625d6ae,0x000032b0b1e22e9c}}, {{0x000f2196196bc6e2,0x000bcf097efd5beb,0x00087293a0e66736,0x000cddf128f3b8ea,0x0000998e4058addf}, {0x00031b85d16c9619,0x00009418f05655cc,0x0009fe81987a434e,0x0000c59e94aaccdc,0x00004a486c235649}}, {{0x000c447f1f0ced18,0x00031492dd2ba337,0x000a08efa800cc79,0x00041dcb93151dbe,0x000020cf3f95e0a7}, {0x00082dc1c0f7d133,0x000054dde6caff19,0x000f96ee3ef92196,0x0000c6ead7d97245,0x000019c8dbe59dea}}, {{0x000385bde259ec84,0x0009f0f67b0d1ff2,0x000661cfff6b0836,0x000f5bc4cc65b006,0x000067e635914230}, {0x0008c802dbed3d35,0x0002a1920da6ce46,0x00037479f7b98426,0x000de0e4d2574215,0x0000c8aa88cd7bb8}}, {{0x00038717b82b99b6,0x000ce70eb624d3ea,0x00095d46675922d4,0x0003462f66ec543b,0x00006e673cd1ee1e}, {0x00067c4b5f2b89a4,0x0005e90e5cd36afe,0x0000a2ada3de9c1e,0x00023b4c278bb631,0x000020fa3844bdb3}}, }, {/* digit=12 [{1,2,3,..,}]*([2^60]*G) */ {{0x00096796424c49b9,0x0007d7c241c9646f,0x000f68b49f888dfe,0x000f20512d4b9324,0x0000a6b62d93571d}, {0x000b26d179483cb7,0x00022511fae281b4,0x0003aa51f666f963,0x000d166281b3e4d5,0x0000f96a765ef3db}}, {{0x000d37c051af62b9,0x000a7bf944968553,0x000d59aa1e9a998e,0x00081350844f9fb0,0x000083fd55976afb}, {0x000c0ca65d698049,0x000ddea5ff2d9670,0x000d8623b732b22d,0x00078247640ba95f,0x0000f61916436351}}, {{0x000b4e0bdefdd4f1,0x0005e366e401f167,0x0003bbec06995846,0x000c214aa368aba7,0x000021487098b240}, {0x000323318969006d,0x000e11fe53d1378c,0x0000c4361cb4d73c,0x00012a8f50a80e13,0x000067f59524ef52}}, {{0x00081088cad38c0b,0x000fbbd68ae2332f,0x0008e27a3471b7e8,0x000b0ca6ac3fb20d,0x000054660dbc36b4}, {0x0001e11a6fd8de44,0x000a637799ef123a,0x0006ac17c44dbffe,0x000cef0540b977ce,0x000095173a8ef60a}}, {{0x00037434573eab0b,0x000b21ac6031eb44,0x000dd9afd11570df,0x00023147d9b45b44,0x00008066addd2067}, {0x0002ad8f8a3f0b44,0x0009a0ace2a215f9,0x000b38b809e0e489,0x0000527dcd0aadfa,0x00006506ae957020}}, {{0x00069f78fca399da,0x00016207bb63429a,0x00088f582fe9e27d,0x000f6e4c655ed687,0x0000426d7494db75}, {0x0005c02ca81c66da,0x00070531d4251869,0x000ff48ba84fb8d2,0x0002469a3a8956de,0x0000f1d0d57166d2}}, {{0x0009565352c4b5c2,0x0001390bc3e25a05,0x0006f9f5f4926153,0x000a9b609f7521f6,0x0000baef6bfe70a4}, {0x000fa6509ed3561b,0x0002e84b230ce7e6,0x0004cdc691137023,0x0004157151659bd0,0x0000db83c64a007d}}, {{0x000284d391c2a82a,0x0002758308e89ebb,0x000f1edcabcdd486,0x0006c7606f16ec83,0x000013e2c38095dc}, {0x00056f04a057a87a,0x000006b48f982ab7,0x000651c44a876550,0x000e01a252face68,0x000052b540c81765}}, {{0x000a1a85ca37ff0e,0x000bed2f1c8fcb35,0x000a26112e1a04f1,0x00077d438816ce15,0x0000206a111e95b1}, {0x000b6048a4241497,0x000704752cfb3c10,0x000f1dbb8c6a3f56,0x000dfb4f16a37a47,0x0000c372f9b431a3}}, {{0x00005b5c20b4d2a0,0x00050c662a67122d,0x000ffc9e9ff659cf,0x000683ed57c128e8,0x0000fbb15859e987}, {0x0000df247319a2b3,0x000a074be470add7,0x000a7b3074b98bab,0x000f30c03d747356,0x000042e696e6efeb}}, {{0x00048f7864ac537c,0x0008e6940d3df84b,0x00074c7ae0471340,0x000033414db22d61,0x000073a1c444c213}, {0x0004ea5ffdd93ec9,0x0006d102783e18ac,0x000c3e83f724fc75,0x000bf50fe13fcc91,0x00002a8c2c9808f0}}, {{0x00022fd8f67f6de6,0x0003786931777f2e,0x0003eca95ab01883,0x000f2ac66d1db686,0x0000bb7732b91b5e}, {0x00027c6915f80ced,0x00018f90efd84fa9,0x0006b48ad6fa1d6d,0x000428abd75de845,0x00002cb507b545b6}}, {{0x000f82ae255d7eca,0x00030460e204a72c,0x0005b0a4452025c2,0x000ed970ae542d7d,0x000085143113305a}, {0x00015f5a14bbfe81,0x0006285365fe9583,0x000d950403f36182,0x000da2b2b3a36b66,0x00002c7b3348cf4e}}, {{0x000b4d1e744119d4,0x0009429a71e7a545,0x00017fcbf4c93b16,0x000d84edbb908c61,0x0000dc97320f35a3}, {0x0004f856bf88105f,0x000d2b51bc1f94c0,0x000013af3452e1bc,0x000e231c41ff50b3,0x000007af446124d7}}, {{0x000e57ca3d24f6a1,0x0007e345a763bdb9,0x000cfbb5f8a8246d,0x0004db63bd2a6d98,0x0000dd8e85e96ed0}, {0x000da42c01f420b6,0x000304407bc776f2,0x000f548f57ef0547,0x00064a1e98ba7faf,0x0000b7afbef5d30b}}, {{0x0002fc516a0d2bb2,0x000bfa6234994f92,0x000c62c8b0d5cc16,0x00067f7241cf3a57,0x0000f5e69621d1b6}, {0x000c70bf5a01797f,0x000c709561925c15,0x0001fdb523d20b44,0x000f7a14911b3707,0x0000648f9177d6f0}}, }, {/* digit=13 [{1,2,3,..,}]*([2^65]*G) */ {{0x000c8b8fac61d9a1,0x0002d3c6fe8a027c,0x000bff5037d25e06,0x0002f7d08805bfe5,0x00003271e6c7ff63}, {0x000a6c0232f76a55,0x000d201ef42655dc,0x0000a51788957c32,0x0001739e728bcba1,0x0000ea60412062c5}}, {{0x000462bb4d8bc50a,0x0006091957709ad5,0x000412a68181c0b1,0x00048c4bd4fe1c78,0x0000e0341bd60dff}, {0x00045cf7003e8666,0x000a2a24a41bb6bc,0x0004c24c2f11a6de,0x000b67f407151ad0,0x00002c9d27e3a5b7}}, {{0x0005719a8afd30bb,0x0007da826dce3286,0x000a8fbe08679832,0x000ad32f04e891c4,0x0000b6b6e1c9bf56}, {0x0005b11471f1ff0f,0x0008ce15baf00a69,0x00096c43ed76c338,0x000157118edb95be,0x00002beaaf580794}}, {{0x000b12e523b8bf60,0x000b8f910c1b0a50,0x0001675888009eb5,0x000abdf535af824a,0x0000f835f9cfb2a2}, {0x00029312afceb620,0x000a169d383ff59b,0x000ac02b0c797df2,0x0000caeb3f5fb066,0x000029d4c6fdaa2d}}, {{0x000ebd1e0a1b12ac,0x000cb70ba95f87a7,0x0002ae9cb1e4ef88,0x000402cc33345cdc,0x0000ecf1276c1cc8}, {0x000012e1b39b80f3,0x000d05c33ba4687c,0x0009661c2fd90d0a,0x00029e73ef5a675c,0x000068fc88f10174}}, {{0x00026052b7ce5421,0x00096472bde1b822,0x000d2f4dae6d4ce9,0x000b2e43e16ebe09,0x000080ff42e63b92}, {0x000cc022c34a1c65,0x0008f22c46c2c59b,0x00014a8a23803d6f,0x000b27c8aff74f5c,0x00005aebf8060a08}}, {{0x000970e2fdd23cc0,0x000c5682e971b956,0x000e86ebcb80288b,0x000939e6e6d91e9a,0x0000564c83f8c9f1}, {0x00032a239560368e,0x000a249c28e25519,0x000a158c3e893752,0x0002622b03cee5a6,0x000012d656be4964}}, {{0x0002010f5b343bcf,0x000a02f142fe58af,0x0005f4bdf0f2e400,0x000aa84483bfdea8,0x00000b1d093f3bfe}, {0x0001b95c70816030,0x00093dba10972ea0,0x00038f3a6e943e4c,0x00063647be92adb4,0x00000bb7742e5bf6}}, {{0x00014576be5f7de2,0x0008a2263c9e4ed7,0x000cacb36d93006f,0x0008abc073694cca,0x0000ff7a5b45ae11}, {0x00053f1cd871236b,0x000d12aa6d523cce,0x00098d76df156a39,0x000d38ecc5f271b1,0x0000c615b7031383}}, {{0x0004fb486df2a61b,0x00073cf7b4a2137a,0x000d042ffa1ed9c0,0x0005ec02e460e27b,0x00007f5e2fb0f62f}, {0x000ec6bcc2423b79,0x000f2a63eea77aa6,0x00050a6e175ce0a7,0x000c9ed7a45fb1f2,0x00003bc919d753cd}}, {{0x0000af231f63950e,0x000034caa2c96793,0x000ac7e62a77797c,0x000aeb726e80ee27,0x00001e6e62738b28}, {0x00078b0b3c9fef02,0x00004d5f90be6361,0x000ce51cfaf7752e,0x000e1f74ecaf18ee,0x0000864d0edea806}}, {{0x000ccaaddce33450,0x0007012a4350ec2f,0x000598bdc2a6811b,0x00012896760ff1ac,0x000054d652ad1bf4}, {0x00051d492a210056,0x0000d3110fdf0a11,0x00060100fad7f397,0x0003622c95928c19,0x0000c91c825dbf03}}, {{0x0005b7799eb6df0e,0x00009386b7791778,0x00017a48e26c3cc5,0x000f30545ed98864,0x0000990b4e4e7d6e}, {0x0006b7e2586abba3,0x000529c96e9a0f45,0x000eb4206239ca6a,0x00090ab327459ce2,0x0000a4c3313d002b}}, {{0x000125dec3f1dec5,0x0000411178da19e6,0x0004a673807b1f04,0x000dcd893ededa90,0x00005187a5a5bebe}, {0x0004722eb329d415,0x000ea170b391f7d0,0x00099f828f449099,0x00076dad317a69ca,0x00000c3db2b84a49}}, {{0x000b69b92222f1f5,0x000a1cf7ae703806,0x0005217ee5a2459c,0x0005ac1789f69ca8,0x0000f232b5f33dc8}, {0x0003ec548e9e5167,0x0006c197eb31660e,0x000fcca23124b4e4,0x00024ea0a0cb13aa,0x0000bd63ba4f2132}}, {{0x000481b7bfe71786,0x000e05405868b674,0x0008c867d4e1deba,0x0000e9a61b2821c4,0x00009c15b35b13b3}, {0x0001666368710884,0x000cd220b1ff3b4a,0x0003d9f4de5e29f5,0x0006750b82bb3523,0x0000e07633358cdc}}, }, {/* digit=14 [{1,2,3,..,}]*([2^70]*G) */ {{0x000f5c7a3e6fced0,0x0005f45fbdeb0d53,0x000339a70e8cbbdd,0x000b81f85c01df13,0x0000ff71880142ce}, {0x0008774bd70437a2,0x00019a0bda6a4c4e,0x0008bd26e5fb3289,0x000521fcdbebd2f1,0x0000f9526f123a9d}}, {{0x000305192c4d6840,0x00057612efcd40ce,0x0009cae208b04d72,0x00056cb9dcda366f,0x0000edc4d24f0588}, {0x000e6bf854279005,0x00058c09dfea64f2,0x0009bf26c3de8129,0x0005a9841b448737,0x00000b62c6dbdf13}}, {{0x000e3b4c72dfe67a,0x0005f0e19fdfd4f8,0x00013bd35c416b0f,0x000b9d78b9098d4c,0x0000c11118ab5b8c}, {0x000a318f00628413,0x000f59f356f4f598,0x000177a0cbfe0602,0x0005374ae3637e30,0x0000409774791136}}, {{0x000fb5ed005832ae,0x000ab1042e4f0db2,0x00070f8ca5f5efd3,0x0009cbac4ffdc6ed,0x00004645d0c952da}, {0x000f58bc9001d1f8,0x000bce1172059596,0x00098a08452c8f0b,0x0009de7d4aa0d2e3,0x000015bfe3a904f4}}, {{0x000443f23885e5fd,0x000918433aab97e5,0x000d4e604f72f8f9,0x0003feed00b154e4,0x00000b35e6bb5e17}, {0x000a0489164722d3,0x000b58761ec857b2,0x000a838323e3c665,0x000e3b3bdd13973d,0x0000c8b1a1ea3daf}}, {{0x000ace654317cac3,0x0009221771b34497,0x000dfe8b8be600ab,0x00010f842e409eb0,0x000086a67d769423}, {0x0008d8d4431cc288,0x0002185dc5242554,0x000c4be32a7cff14,0x0006e0cd60f5a193,0x00003ebd5c95071c}}, {{0x00080a7b1fd2b0bc,0x00059bec33e8ba3a,0x000743fb39b3ad39,0x0002f9f3868d6179,0x0000fd169fdbdb46}, {0x00099d79ce0a6af4,0x0001a42d3ff8d3b4,0x000c3e1b255dc1cf,0x000473c4fb9e6cc6,0x00007e6961daf69a}}, {{0x0003acce548b37b2,0x000264d4054954eb,0x000341b4fb38e754,0x0007fa6c3daa517b,0x0000f6928ec890bf}, {0x000b32386ce6c413,0x0004e0adadcd0496,0x000b5faf901be1c5,0x000985904e67e74b,0x0000cbaf679115c9}}, {{0x000214550ca42470,0x000ae7dd30aa8cd1,0x0008fee24ba1aa47,0x0000e82f81ddf1e5,0x00003452936eec9b}, {0x0003b81243aea965,0x000ec5c3d0e58bdc,0x0009483619a2919a,0x000ccf4ea640ec10,0x0000ac86d5bbe0bc}}, {{0x000d918c36cf4406,0x00076939719cf892,0x000218b64aed3e83,0x0000dd507b08d2c0,0x0000f1bcbbb2e979}, {0x000d6ed60919b8eb,0x0000dac1f9eb4a84,0x000d5daefd890079,0x0002c5484941aa0d,0x000022fe40b17fd6}}, {{0x0005ba2157f2db33,0x000f5e28ca9c97e1,0x000b9f454bda2fc8,0x00072e2d050da437,0x0000d57eb575379d}, {0x000eba2fb5ee9973,0x0002b11538cae9b5,0x00032797401648ca,0x000bb702bb76f6f6,0x000038f14b92f3f4}}, {{0x000226ad7ab9a2d8,0x000cfdfae958524d,0x00051d8c29c00090,0x00062c8ba5f53987,0x0000afcbcddbab82}, {0x0002729e99d043b6,0x000b4ebc943a5739,0x000862935ef51263,0x00017b3feace9320,0x000039efc04106c8}}, {{0x00054b366b4be7ad,0x000db4a37a1e1fe0,0x000d75cd93f25a9d,0x0001b5239ef1ad78,0x00007b58f4a2062c}, {0x000f9a9ff563436b,0x000938af51e76f74,0x000e97fecf718ff2,0x000c09a234d31315,0x00006a8e2b1d92f1}}, {{0x0003aa8327720c15,0x00026a092cc8a7f5,0x000746c4d956ca32,0x0003923f03d64a28,0x00001fe1782b6d0d}, {0x00034db3c832c80a,0x000bcda2e3b4d19b,0x000104ccc60dccc5,0x0001fc845dd62e0a,0x00007ab1de2020b2}}, {{0x000ae0b3893d123d,0x0002e15ee71cb293,0x000a9468bf7b7578,0x0007438aa3c61442,0x0000686123dab15d}, {0x0006891a7ab4116f,0x0007b4e6a4598c61,0x000e5fad76fcd72c,0x00046abc21911077,0x0000b6a20e8604fa}}, {{0x000be7d341d81dcf,0x000842148379e839,0x000026eadcddb688,0x000c5dea6211a1f7,0x00003b25760e4d1c}, {0x000c8f6a7a73ae65,0x000e11d5b48340cf,0x000a50ebc83879a5,0x0008fa75acb1ed41,0x00009a60cc88c07d}}, }, {/* digit=15 [{1,2,3,..,}]*([2^75]*G) */ {{0x00030b665c7322db,0x000103c1b3fb4395,0x00072f685cf12cc0,0x00091d170b018601,0x0000915ee22cb583}, {0x000f03ba317db248,0x000897b8ffc49afd,0x000d3d05087dec65,0x0000e6ff46597be4,0x00000a1c1ed80650}}, {{0x000a7b397acf4ec2,0x00003ea8b6403e22,0x0009692850426c40,0x0006703e3295a64e,0x00002aabc59c6a45}, {0x000714c5f5942bc4,0x000dba3182edb929,0x0004152ba9a6168b,0x000367e216a66510,0x00006908d03f6926}}, {{0x0008ac6c2babcc13,0x0008ce81ae8d52cb,0x000f1a7114748d44,0x000ac42844f03f80,0x0000db784b328df4}, {0x0008f122df1fe365,0x0009a33cc7c0ad91,0x0005e5555e40f25b,0x0006f8f700d0e73b,0x0000c28fa0900332}}, {{0x000d8745a1251fb6,0x0008672725c7a9f5,0x000ffe89e967747a,0x00035db95c33e531,0x000009d211049649}, {0x0006ca82fe122271,0x0005f426469dcafd,0x00093183caf9b5b9,0x000fef1e9ee04c56,0x0000084a333d8146}}, {{0x000b1c8321a518cb,0x0005dbce226f56da,0x000acb9fafd4439a,0x00071b30b30d194f,0x00005052f3125835}, {0x000641012afd4761,0x0001f3fe624a1442,0x0001c92e6d02e417,0x000b52ec394f6553,0x00006d4bf5ae4bc0}}, {{0x000b88210395755c,0x00039ec1df80ce06,0x000f55e96117ce63,0x000d1e3efae513ef,0x0000f36cba7bd7fe}, {0x000eca9a40ebf884,0x000f73d37e127340,0x000bbf9ffe6ec1bc,0x00005e8a51b64e86,0x0000e0dbb58cb40e}}, {{0x000d0bf5f8b8a84c,0x0005c66f3ede120a,0x0000ebc2cbfa00f3,0x000e3ae8c6064ec3,0x000039e40b8e3001}, {0x000f7cde7b1cbab5,0x0006b4a562849614,0x000857a19cd4420c,0x0006cb3446a8f316,0x000019b93b236f70}}, {{0x0009933aed1d1f71,0x0003405630909664,0x0002e39cf566eaff,0x000124245057f0ad,0x000048ff65b2f832}, {0x00089d4cf94cf0dc,0x0003920c58b3042e,0x00061aa0d319bec8,0x0007ac6a26762653,0x000086fa3034fbc8}}, {{0x000e5b80863b6647,0x000accabdb533805,0x000feff918be7ac6,0x0002062f7d70505d,0x0000dea8bd105896}, {0x0005a3b410e3c4e4,0x00097c603ebf2800,0x000ec15d224a4f0e,0x00041d8c4fd5ae4a,0x0000dc253f84f966}}, {{0x0007b9c7ea2ee345,0x000bb9cc3a71359d,0x0001ea37a3fd0d94,0x000c876b53c31c3a,0x000033425fb1f818}, {0x00099c3810156e0e,0x000350c164487cd1,0x0006425420ea020e,0x0005ea0557ba094a,0x0000657e7e87465f}}, {{0x0003ad1fbc824398,0x000b7896e9fdea72,0x0001c33ffc726868,0x000231597c913c51,0x0000a3fa8e362114}, {0x0000e5608445b3e7,0x000488d098d32a6c,0x000ea77d42c4cd88,0x000f710bf51faf2f,0x000009f208aeb1c4}}, {{0x000d2ab5c8b06d5c,0x00023e4eac46fc83,0x0006f7779b1a785a,0x000504f99315bc84,0x0000f31d817af9ea}, {0x000fe6a15d7dc85d,0x0003e4016b332391,0x0001cb4c72f132b0,0x0005a059547fe318,0x0000b66d8a735015}}, {{0x0004843f45aac50f,0x000da1eaaad05b9e,0x00054eea0c31e042,0x000a567e8c0b345a,0x00000437b95862c7}, {0x0001ce8fe1d348b4,0x0008a3786432e453,0x000510d38e148937,0x000b0095e19c4a3f,0x0000df3f0170e348}}, {{0x0000e8b593d070f7,0x0005e255625d59cd,0x0007a03994375751,0x000eeae51fdda75b,0x0000bb6e6b09dec1}, {0x000b662334c0922f,0x000e1cf41b79729b,0x000f324023df631d,0x000c8711abf3c578,0x0000cb4666d8cd33}}, {{0x000b445735e843cc,0x000cd7379134b805,0x000ab9f872a8e890,0x0002b62bc7c10c52,0x0000bb5e1ed780a9}, {0x000a2d9dc2c4efe8,0x000e2e8cc7bdd6ad,0x000418a74fccf504,0x00080be50115acb2,0x0000dd90e07452bd}}, {{0x000d7e1adc1696fc,0x00024acd72d06b66,0x0001b743598ebe59,0x0005eba5f24550cc,0x0000e23139474b9a}, {0x00022d4db067df91,0x0005baff9b00234a,0x00000c9c198dda09,0x0006950bbc75a061,0x0000560a9c8a39cf}}, }, {/* digit=16 [{1,2,3,..,}]*([2^80]*G) */ {{0x0000f1cf1c367cab,0x000b190fbc7de405,0x000a110329bc85a9,0x0003a8f373c4a2e1,0x000064232b85d039}, {0x0007eb0167dad297,0x000124b78ab2f557,0x00029348b1604f30,0x0003419baa94afe8,0x00007fbd8ddb1654}}, {{0x0004802fcf0a7fd8,0x0008d488b01e31f1,0x00052b49842fd078,0x000200f1d78d6d99,0x0000eb572d987ac5}, {0x000a44c4d194a88b,0x00090a017e66e0a2,0x00088aefcd2b63fd,0x000a10c8efc6c8f8,0x000076f6bdafa881}}, {{0x000932c68af43eec,0x000db03d00bda2f7,0x000b061f55502468,0x0005ad25dc978f2f,0x00009a1904ae8c81}, {0x000538d470c56a4f,0x000e293d8cedd3af,0x000108ef3159abc5,0x0001773a37245f20,0x0000a17081f123f7}}, {{0x000a9b2b4b4b67c8,0x0000680206041fe2,0x0008058d8c1d10df,0x000fbb1d64abfcbc,0x0000943b9b2f12a0}, {0x000d9143b3def048,0x0001cce775ff90ee,0x000bc904085ab3aa,0x000dfae05fd4ca7b,0x0000b34a56562c75}}, {{0x000acf88e2f7d902,0x000757be32cd5c18,0x000eb5ee9fdbf33d,0x000114ea085cd7d2,0x0000d702cfbd3201}, {0x000ebdb85c88ce89,0x000b8e01d617b6e0,0x0007333ac23a3ce3,0x000b6aa041618e56,0x0000dd0fd8fa57ed}}, {{0x000610798fa7aaac,0x00043073aa4eb2b2,0x000d6b19b41209ee,0x000caf31570359f2,0x0000be6868dbc577}, {0x0004bdc32c04dd3e,0x000defeee397186c,0x00086c0cfa6c35fa,0x000fe1d4a1b312f0,0x00000a5ccc7b9461}}, {{0x000f3a36fa6110cc,0x00013b93561f516f,0x00057522b74fb1eb,0x000dc5ac0c904784,0x0000fd321052bb8b}, {0x00084a2cc80ad571,0x000576a9b6372d68,0x000f4e8cd7c27fc3,0x0002f02461baedad,0x0000d56251a71724}}, {{0x00011a9431dd80e8,0x0009f3306cd9b840,0x000b3b730eb7c7cc,0x0003d2a0fadd29d1,0x00003858b5c7e37b}, {0x000d193b6251d5c7,0x0002a352d952bf4c,0x000fbc0511cca1fd,0x000636566157a490,0x0000990a638f9b98}}, {{0x00081a321175ec17,0x00057e018109892c,0x0008be3169159a50,0x0002e5570130532d,0x00006060c21b26fa}, {0x0002dfc6b6f0f228,0x00044a01a671074d,0x00070bd8e9725fc6,0x0003fdbf6679b927,0x0000fe6605057c9b}}, {{0x0001154b6e00a84b,0x000174890e60ce71,0x00060988fd9fe7e4,0x000004210bc6c345,0x0000dc2ef531859b}, {0x000d868d5c890ee1,0x0006019c47dcdcf0,0x000714567893115e,0x000a53d97966fbee,0x000017813356c85a}}, {{0x00030cc732043499,0x000d04a0679c71d5,0x00061e031c9df473,0x0005fe3572f00142,0x0000786b71fb2f13}, {0x00005fa6b64e56fd,0x000835219c46ed65,0x000f53d71e2fb48e,0x0004053dbec45bed,0x00007d782f39589f}}, {{0x000b66b73ed09660,0x00082886032b350f,0x000390493968e4b0,0x000dbe5a16ed6e88,0x0000a83ce84a121e}, {0x000fc10a3d9cda09,0x000505ce67fb7c86,0x00037dbf65a40a6d,0x000282dcb8cda7f9,0x00005b44768f51f6}}, {{0x0003c8a446cd7f44,0x000b506d52a60651,0x00023866c158c423,0x0008ee31503261c4,0x0000b96f570d3c14}, {0x0009cc7239a85237,0x000625ac4b8b5daf,0x0004bf7f6611b597,0x0004436e3981db72,0x0000e7d0f78d7afc}}, {{0x000101ed6fc38377,0x000eee1b3a09984f,0x000942626340bf99,0x0006184b96036f06,0x0000bc878ab7c7da}, {0x00016441c6fb0358,0x000e2182fe9fb374,0x000c7a67ac65bd5a,0x000d7c9b9c2fb86c,0x0000d1b19afdce68}}, {{0x000b80c8ce59954f,0x000388222ac03d1a,0x000f878dd742c5a9,0x000a984ddacbf894,0x0000c085118d7d54}, {0x0001dfa21e38ec27,0x000aa6f4ff7ffb0f,0x000a888fe1c7b59c,0x000889288752397e,0x000005d270d210dc}}, {{0x000692a87dec0e16,0x000d97b39d00e5aa,0x000cfa0b5010ded8,0x000a281b1b80c854,0x00006beb87700f8e}, {0x000f5313476cd0e8,0x0005308d394950d7,0x000479fc6a63d0e6,0x0007419a09eea953,0x00002ae98927499e}}, }, {/* digit=17 [{1,2,3,..,}]*([2^85]*G) */ {{0x000b9105ca7d8669,0x0001aadb3b34ab58,0x000eac0bc582967e,0x000af4f9ae4447cc,0x000019c667d0bf56}, {0x00017b160f5dcd7b,0x000f2dcaadbc9aec,0x0003467f5ec697b9,0x00032e5b98f34146,0x0000187f1f859671}}, {{0x000dcb6ec7fae9f1,0x0004dfb66e5aeb5d,0x000445d52995f271,0x000620cee95d8e69,0x0000b6c2d4619e27}, {0x0001c318129d7161,0x0000f958c1aa3262,0x000f4af63b03909f,0x000df67c468ef91a,0x000062c42a00ba5c}}, {{0x0005eef9c053df72,0x00079300ea6fe8cb,0x00049cffb8de25b3,0x0009bbbb03fa92c8,0x000042e43a808416}, {0x00051f4dd6f958ec,0x000f34445a8de4fa,0x0000d89496925a77,0x00039026e72a50e9,0x000066648e3eb1f6}}, {{0x00096f31711ebec8,0x000f4e98fdc46c3b,0x000b4411f2da40f1,0x000bb6399774d357,0x00007c8bdf495b65}, {0x00089e3c2eef12d5,0x000aec7471f3da3a,0x00012c594de95bb9,0x00056b100f225bd8,0x00004907c5d7b75a}}, {{0x0004d2945c1dd539,0x0007931debb5699e,0x0007f00e0cadc589,0x000a0e4f49fcc7a7,0x00003057bc0373e5}, {0x0007ecd027a4cd18,0x00034614011a2f8b,0x000677c68114734b,0x000f4f67a01db767,0x00009d9be5efe273}}, {{0x000ee5931fba2393,0x000368bd91d1e0de,0x0001a3c1df47424d,0x00033adf8886f407,0x0000f7d41e8d8192}, {0x00023c2cf6eb9980,0x000f609a287f7086,0x000c9076286bb49a,0x00054b942bb24963,0x0000ef6eea555a96}}, {{0x0004a2e649d4e574,0x000fd917526e4add,0x000b44ac4cd53a2a,0x00031d8526233020,0x0000028746afaa2c}, {0x000839064291d4c7,0x00017e5ad9095131,0x000185681bf48f15,0x0004425ce57f597b,0x0000c3ac1b0b854d}}, {{0x0001db6f79588c00,0x0009b55768cca80d,0x00054438afa52fc6,0x000a4f0b4df1ae7f,0x0000cadd1a7f9b46}, {0x000a6b31803dd6fc,0x000495eaae35b40e,0x0002e4e16488e4fa,0x000c97df047d5538,0x00009b5b7e0ef6e0}}, {{0x00072d0b611c24be,0x000480a8f351c199,0x000cf64211d468e6,0x0004910b7580697b,0x0000c9dd0ef68fbc}, {0x000d2bf956c2e32a,0x00043cddf94e5b59,0x000ee766573dc686,0x0006c45d5e2321bc,0x00007b4f8effe9a0}}, {{0x0008f17cf41c6e88,0x0009837b925c03cc,0x000d2427cf1f03c2,0x0008e4439c19cc66,0x000023d24bafb6c1}, {0x0009013901f0b4f7,0x000188941c2e32ef,0x00028092e684360f,0x00032e9ebaff522c,0x0000891e4e3956c9}}, {{0x0008f82d8d38a9b9,0x000057de1391174e,0x000c175dd2e97c60,0x00003535709850a1,0x000069041a0c2ae5}, {0x000533b76a2086b3,0x000ba7c2e8fecbfd,0x0009dfb67d6bba71,0x0005d982d58ee609,0x0000a8b342d364a8}}, {{0x000bf0502f40d9ab,0x00077c318a4df83c,0x0009c26744681c46,0x00092de85756180e,0x0000e79d046c8470}, {0x000480a78bd01e0c,0x0003b2a51db9af1e,0x000afbab66dd359e,0x000198a2ce3821e3,0x00005cee5b6d7733}}, {{0x000d8fc3b922bf8a,0x000fac29b133671e,0x0006e99c4e4d8c09,0x000eb9e7eb12393b,0x0000ff3974d2793b}, {0x00094052c18df9b0,0x0003910071390374,0x0007a0b95c5c3a29,0x00096b6a77234fe3,0x00002c29a21b661c}}, {{0x000fe2e34d74e31b,0x000f8bf79ab65a52,0x000feeb8fa352c30,0x000304e7ff6c5aab,0x0000fbe8ff0a5c97}, {0x0001ce6a79046089,0x000a34fca249d608,0x000e5e2001f812f3,0x000ee80b24bc9ab9,0x00001022c67c8012}}, {{0x000e7d7cc5f43941,0x000c3536e142184d,0x0004aa60ab5551b5,0x0001d51e89b212d3,0x00004a96feb05005}, {0x000ef740d12bb0b3,0x000030b9677e4e21,0x000f7731dc522f02,0x000d315b12e4672d,0x00009f80382ab326}}, {{0x00038b67c4a658ad,0x000870e72182c127,0x00098e44fb3c4763,0x00085e6b77be4687,0x0000c047df2e7a7f}, {0x000d4c55e59d92d3,0x0005b8e64d8d2439,0x000ca9b16cedca47,0x000dfe7724cd0d87,0x00005e4fd59d5540}}, }, {/* digit=18 [{1,2,3,..,}]*([2^90]*G) */ {{0x000344f3a29467a3,0x0009951eba6d9894,0x000e5c2f2de81e94,0x0007b3aaea066ba5,0x0000fc8a61438c8c}, {0x000f88f06d0de9fa,0x00049b75ce0a7adf,0x000bc87d5bbc11cf,0x000de1ffbb7accfb,0x00001458e271badf}}, {{0x0003668e039c2560,0x000b7c17fd5d1cb4,0x000aa062b5f26fb8,0x000f04eee426af79,0x000072002d0d78fb}, {0x000a237e84fb7e3e,0x00002c82133d4c9c,0x0007e4181b401d8a,0x000151caa525926d,0x0000943083453dbb}}, {{0x000ad1e6ee7c983a,0x000c141328f52f5f,0x00078d5f7eb0f9d7,0x00026efba68b441d,0x000006b3b9ed5bc7}, {0x0000255593e1ff1d,0x000d0fbec115a255,0x000a8f046552dd43,0x0001325c48a7abbb,0x00004fc56a47d0bf}}, {{0x000da31be24319a2,0x000bc095a8e7f92d,0x00078218503f7d28,0x000dbc852fe84098,0x000076ddafe49c24}, {0x00054961d7a64eb7,0x00090f1dbe4280cd,0x00038d2d5e436088,0x000035bf81a87784,0x0000e4d52a8f5169}}, {{0x0001cefba04b5d1d,0x0006524c735262f2,0x000c6171f9a44270,0x0006afef07966c33,0x0000b7ba891ee081}, {0x000ea59033745a93,0x000090a78f67306f,0x000251bf92aacf7e,0x00008685aa3883ad,0x000045aede956bd7}}, {{0x000d5b11d59715df,0x0001e788983e19e3,0x000f1f248c7eaa76,0x000d82f5a730b0ab,0x0000bab8085eae3f}, {0x0000d2153765b2f5,0x0003aa127f3d65e5,0x0007b1b10bdd4e08,0x000fd34cf3c07439,0x00009f8090d01b59}}, {{0x000e17d98119f103,0x000d188c36a6dc1d,0x0008e23df74353c5,0x000592e4aaf33a3d,0x00001e075c0a8baf}, {0x000a03a46d1ca3c2,0x000c27b660c70f7c,0x000fe2e5999c5e3a,0x00000550d0241388,0x0000e9a6be14a7ec}}, {{0x000fd9d615faa8f2,0x0000768554ed7b15,0x000a448828fa1eb4,0x000f325bb4447e7a,0x0000bb2d0d1229ff}, {0x0002a646caa6d2f2,0x000e02e7351b075e,0x000506c628eb879d,0x0004dc9cd5624e9a,0x000018eaef0c87e2}}, {{0x0009695241fbd6f3,0x000fd81c1223ac44,0x0006aac6f67c9b16,0x000720e6868f21b5,0x00004bd8fa428bcb}, {0x000bd33b6691c76d,0x0005681a797306b6,0x0004078db6c92476,0x0001cb9a12444ca5,0x000002e91aa3d105}}, {{0x000684744ddfa350,0x0005dab3f74737e5,0x000e96cf49ccfc5c,0x000b8f9ac1df3f1e,0x0000c0571a13b480}, {0x000b3d54b3a7b3cd,0x00088dcdbb992fbe,0x000415b3a35c0366,0x000d9982a0f5dcb2,0x000057759b51413e}}, {{0x00079c00b33d3f8b,0x0005c064e4090773,0x00029c8f6421883c,0x0000c77d0873d76c,0x0000fa433a48274c}, {0x000778f23a5891e0,0x000535e2de0456dc,0x000b517ced663bf6,0x0006c2488fdb485d,0x00000bba55e19b22}}, {{0x00047d83d30a2c5c,0x000e378a81dc1fe6,0x0001a4a9b0857f77,0x0003f451d5a33413,0x00000a94af9e9d39}, {0x0005c0bdaa6ec1a9,0x0002f8d2d7edbc3a,0x000614797ba9fe49,0x0005332b4335b4bb,0x000091c4d6902f83}}, {{0x000eee78a058fb62,0x000cdb09121aedbb,0x0004dddceb9d19dd,0x000bc4841bb45bd3,0x0000dbc80b920964}, {0x000137d1d6cb654b,0x000a983d01c54ed9,0x00028e22e1b9016d,0x00046aafc501bc65,0x00002d2f8821cad6}}, {{0x0008c28d2f01cb3a,0x0003375db0b15325,0x0007d0db493d6eaa,0x000492a19a2b0de8,0x00001e48f0478fe8}, {0x000faf6c508b23ac,0x000975d53549f747,0x000f9b838f137571,0x000cf4df5e58e2fc,0x00007186cef67fd3}}, {{0x000fb2f286bad396,0x00033dcad1e25e76,0x000c7e904bad9efe,0x0005a500e75190ed,0x0000a6f063e6fecb}, {0x000ed85aed8acc3a,0x000bcd20af6c5150,0x00069dbfab56ccfb,0x0000a8de0d1e982c,0x0000bf5628b1c7e1}}, {{0x00068cee978a1d35,0x00032ab92d0477b8,0x000a5b862e3a68b3,0x00041d0102979487,0x0000f0606c38a61d}, {0x000be276f9326f11,0x0004b6fe3c2e2814,0x000df73512f521c1,0x000e4407464d7dac,0x00000f5f9d3877f7}}, }, {/* digit=19 [{1,2,3,..,}]*([2^95]*G) */ {{0x0001244c5f95cd80,0x0000f4ab95f4b06b,0x000e5836dda8c8af,0x000ffc1bae59c2b9,0x00007d51e7e3acff}, {0x0005e6ac2ccbcda6,0x000f2528c3e001e1,0x0009fead43bc1923,0x000710e3324577a4,0x00001a1b8848aa7a}}, {{0x000ee31b0e63d348,0x000229e54fab4fe7,0x000e7b5a4f460057,0x00083140493334d5,0x0000589fb9286d54}, {0x000f5cc6583553ae,0x000a025649e5aa70,0x0000446520879094,0x000c4eec90450710,0x0000bb0696de2541}}, {{0x0005247d95ea1682,0x000a0970764a172a,0x0009781691758fad,0x00001b8c803a511d,0x000099cfe2efe77e}, {0x0001e17b0a98927c,0x000060014495652a,0x00075b56a2e26e1d,0x000f94bae0af9f71,0x00002e22a81964b9}}, {{0x0001a3ea2dee7a63,0x000c434b2284758c,0x000aba6addcde2f3,0x0000a77ba445d24e,0x00005aaf668a6cee}, {0x00004a9e5aa049a6,0x000d31103e847e0b,0x000afecc3e74083a,0x000f7a5eb183ce40,0x0000b89dea04a043}}, {{0x000b1eda4f7e665e,0x0009c23df8e7afbf,0x00012c2f4403cce6,0x000c33d49cc83f13,0x00001cc2367571a9}, {0x000a6c0db92faac1,0x000ddc3befe17ab6,0x0003a0f36acd15e0,0x000e096f8ed98858,0x0000821de7715f9b}}, {{0x0000e0399375235e,0x0006d9917970b99f,0x0004ec0677614c84,0x0005201ec93ce952,0x000040e7bf97b122}, {0x0000631ee4c47744,0x0009fb04914cb567,0x0009dd2266f03847,0x0001f8896e9429dc,0x00003489b6ccc57c}}, {{0x00022a5c5f264649,0x000b1442809a7b97,0x000644810ca4c3df,0x000f81ed10986723,0x0000e495172cc924}, {0x0006968a2c5bc14a,0x000ec8de6b7aef4a,0x000a2cbb5750eac4,0x000445ae01884d52,0x0000c40830b94a5f}}, {{0x0009d23fe67ba665,0x000043cf2f340e29,0x000fcf9139145076,0x000ddaa45b5ea997,0x0000be00843dbd7d}, {0x0003e05d53ff04d3,0x00032de91ef7358c,0x0009ec1a0bf7ccdc,0x0009977d684dbfb6,0x000067e7cf2b01fd}}, {{0x000f1076103adf86,0x000c5e8e98108c54,0x000bd3c9b2d813d6,0x000a7651466fa85f,0x00008c65d22a0e1c}, {0x000aa40255f9164e,0x000df1a864b2b81b,0x0002ca1415b34c3e,0x000dea5602209b12,0x00007d7248f685ba}}, {{0x000d227cc2338fb4,0x000950e2615346ff,0x0001a007689ff6fa,0x0003af7e57077933,0x00003d241c546e1f}, {0x000b97dde9b62a31,0x000490ae30eafdcd,0x000bddf7d6a06e98,0x0003c4b9bf16804f,0x000070471a2e3616}}, {{0x000e207a6469d438,0x0000af753a85fd23,0x000b5ca72cb9f5f1,0x00078b5e2625d4fb,0x00002e4e54b37b1c}, {0x000ca5378b9e8143,0x0000e25b817a2cd0,0x000cfd965fcd4405,0x000974868f719f30,0x0000164471a0848a}}, {{0x000a8ae3113655ef,0x000a67b83180ff5b,0x000e0eabefa2c6e2,0x000a962c48271977,0x00009f3c556237fe}, {0x0007022a42581cb1,0x000208f710e3340f,0x0002e5aa8e1de0bc,0x000940de640adef6,0x00006b2389159428}}, {{0x000738f25f653f59,0x0007a764f6355045,0x00011ffc3e42b8cb,0x0004aa24f89406dc,0x0000959314546b3e}, {0x00049f3c97400525,0x000105ffc48b81c8,0x000f67a492c9cf4c,0x000c621299e52177,0x0000869f6e4100c6}}, {{0x00019e455950cc3a,0x000bb6b66bb83616,0x000ac6d84c71d665,0x0007e34a034b34af,0x0000987f83385e4c}, {0x00027727a79a6a7a,0x0007426d6c23a074,0x000167e1056e5d01,0x00084dde50b97638,0x0000a6c81f0888aa}}, {{0x00086f75fe015763,0x000caea51395b841,0x000f3f8d4446e276,0x000142c3c5ef8105,0x0000d7f7df6a4f7f}, {0x000b565f9ef16565,0x00042c414ef67c69,0x00029206087efa42,0x0001ae9b7e620d3d,0x00000b1de34beec2}}, {{0x000f3b7b0dc85957,0x00082f1d9f2e0ca1,0x000dd82a727de460,0x000447aaf3bf39ba,0x00009356a79d5862}, {0x0002345f5f9a0529,0x0008839a42f9c060,0x0004d40fc1a8b0f8,0x000368253eee4284,0x00003b0bfe5de5b6}}, }, {/* digit=20 [{1,2,3,..,}]*([2^100]*G) */ {{0x0003a5dc8de610b8,0x000ae7e223ce0f89,0x000ad6dc5e8c515f,0x00028ef774bfa64e,0x00009d20f96125c7}, {0x0000966098583ce0,0x000493f2a7d77a1e,0x000304d4aa2eedb9,0x00082d1b2820974c,0x0000842e3dac0772}}, {{0x0000e9d74cd06ff8,0x000f2ca3eeaca101,0x00063aa2b9c17c7d,0x0004fef4c86cd380,0x0000595c4b3f3461}, {0x00000ca990f62ccd,0x0002fa0c3be5a3de,0x0008ce9f5d9bed21,0x000443a886078adf,0x0000db27ce42cd44}}, {{0x00097befc15aa1ee,0x0007d54b07455a30,0x0009a5f1240d1254,0x000ee57bad470651,0x0000d03f7188439d}, {0x000bb6c4a02c4997,0x000d5ffe71d20794,0x0003adcaff725083,0x00030fbcad75190f,0x0000f68ea1cb3729}}, {{0x000581d26ee83821,0x0005259d638e9c7c,0x00028ae3dcf17dcc,0x000047de8273abb7,0x0000d1129270821f}, {0x000847750491a746,0x00019de0dfb91149,0x000a435ab687fa76,0x000e3ecc2580227e,0x0000b8bdb94f1ce7}}, {{0x0006d8af7f91d0f2,0x0001882a57289c80,0x000d767543b61b0f,0x0004c62640032d94,0x000073eb5de67d83}, {0x000abf77b4e4d538,0x000f5e4017772988,0x0005071b3b7ce66b,0x000a981fba6b3271,0x00002413c252d3a1}}, {{0x0007b7e3cc8ac855,0x00078d02753b7553,0x00037df2f8d725f5,0x00031dad05ff64b7,0x00005fe871346d25}, {0x00004a96ab6b01c8,0x0008fcd9372457ce,0x00086699b69a02a8,0x000231cf82ac35cf,0x0000242d3ae1cb4b}}, {{0x00035269be47be0e,0x0007eb28fea169c4,0x0006c67e5323b7dd,0x000e461a5538ba3a,0x0000f921d70fd378}, {0x00061fc3c4b880ea,0x000df8940a67f929,0x000f0ff393f6f914,0x000f9c0990eb0afe,0x00006c2921090eef}}, {{0x00003a553fb2b560,0x00074e057f78b23a,0x000e490d96ce141e,0x000e75796525c389,0x0000bc95725a31a7}, {0x00067911220fd06a,0x000ba08b0bd61ec5,0x000ebeba9716e3a3,0x00066f91cd6bf7e8,0x00007326ca75ee6b}}, {{0x0003d32343bf1a9e,0x000757d1a6b170b6,0x0006865b48fd3bd2,0x000fa12454879c31,0x0000e959ff7a458e}, {0x000dcf89706dc3f5,0x0001c64e4b2e0461,0x0008843c8737db0e,0x0006f5b92626802f,0x00004498bbcc745e}}, {{0x000352b5acf6e10e,0x000ccfe652c35341,0x000577a7fc50343f,0x00023c6af3792d18,0x00001a4c6188f168}, {0x000d0cd33425d0a3,0x000d6b7bc47f9b26,0x0006bb20b306399e,0x000054fa792f3370,0x00001219614c8111}}, {{0x000428cd5f30851d,0x00065a4f66304c1f,0x0005d48a494dfed2,0x0000cd7df53772fc,0x0000d2d5a3063326}, {0x00015bdd44cc7a57,0x000d4d12533a5741,0x0003057c94ba6b20,0x00020dc0e93cb824,0x000094c486a84de3}}, {{0x000355699f241d77,0x0006901a349d6095,0x00089e491ee4adbd,0x0005459b35bf6aaa,0x0000f0076f4836f7}, {0x00018ba9264da3d1,0x000d52a7a28bd19a,0x00061c9716eb2d2c,0x000a5dbdba941f87,0x0000550518bb3be4}}, {{0x000d97302f1cd1e1,0x000b0dd212a4c232,0x0009802f7ce87eac,0x000dbd5e4c8c73e6,0x00002ef02902fffd}, {0x000c74e1bcea6e23,0x00040cb92cbb941e,0x0008f9d05d0b5402,0x000aae509fb9d47e,0x0000bf1615a22992}}, {{0x0007007eafbb1e1a,0x0006475b7a93b249,0x000b68d78d75c9ce,0x0003959558352def,0x00002f26699c23f6}, {0x0001ecfe469b17ae,0x0009072d3ec2eb91,0x000cb113f6254577,0x00098caea47de782,0x0000be4b0872e1fa}}, {{0x000e675b055cb405,0x000b477b5167bdb8,0x0002fb863898f8e7,0x00001f9cc65651b8,0x00006544814bd88f}, {0x0008e95263a75a91,0x000f0a22fcdab092,0x0003bd37ccfb6836,0x000664551d14db3f,0x0000d3837fbc6ad4}}, {{0x000c982cf7d62d27,0x000cb3ba815020d3,0x000763f9e1f36e29,0x000006d8ae0bf092,0x0000a527e6b8d3a7}, {0x0009097581a85e38,0x000f5c158be5b4a8,0x0007d726e1f1a520,0x000862798db37d16,0x0000802786e9113e}}, }, {/* digit=21 [{1,2,3,..,}]*([2^105]*G) */ {{0x000149e36f09ab05,0x0009fa10bb5befb2,0x000e2099803f163c,0x000bab8029704506,0x00006f0af006b5a3}, {0x000cfec70880e0de,0x000ede3d913f7af4,0x000ceb4bd7332a66,0x000f5452e6c84a7e,0x0000dc4a79b7c228}}, {{0x0007dd0c55c44969,0x000695bbabd2c37c,0x000d7f363a6a9635,0x0001decb7e63f2ad,0x0000dce3782be73f}, {0x000a16ab2b91f71a,0x0002bba0163ce1e5,0x000e515ade448982,0x000ecf52759c32f6,0x00005e2f1f92615e}}, {{0x0009be7abded5516,0x000868b744107451,0x00010d9a903d358b,0x0002b6ed00b10b0e,0x0000392b0b188da5}, {0x000a2980b75c904f,0x000db8f7f96c6744,0x0002cf932c305b0a,0x0006c9142e421d18,0x00006fc5d518e463}}, {{0x00047c9d64cc78c4,0x000b5b6cb27b7958,0x0008022ab6c50621,0x000a1cc7099bf8df,0x00008f862ec004ed}, {0x00032ede1603c166,0x000efc9a9450d127,0x00029b4fc19a80e0,0x00051582257f54b4,0x00006d3b2c6a5460}}, {{0x000f87e822e37bef,0x0003353bda4e6ca4,0x000190aeb73f237b,0x0002840747f3a241,0x000006fa370704cf}, {0x000bb6efc621c127,0x0003d0b80ec60a6b,0x000a556f35d624b6,0x0000a7db0724257b,0x0000fa0c354ae2d2}}, {{0x000fa31e3229d41f,0x0001a4531bd4e921,0x000d38209a929c65,0x0007bc94156027a6,0x00003d69f745bdb9}, {0x000d19a168336319,0x000d73d51be38906,0x000511cd868a34c2,0x0002a83b59583b0e,0x00009ce6bfe8dc13}}, {{0x000daaaffcdb4631,0x000a24a38b083fac,0x000a9078d658bbc1,0x0005de02a801f8f1,0x0000567bcf97ab85}, {0x00098e03572359bb,0x0004d659e68be084,0x00023807ccf0353e,0x0008a20b86e9c87d,0x0000c08728dd198e}}, {{0x000b7bc453cadd69,0x00072c0bc1f88de2,0x000abd3af203900a,0x000ffb2cd86e47a6,0x000011cac131502e}, {0x0000242ec965469f,0x000139e0017e2d55,0x0009798850e9f769,0x0001ee733f078f65,0x0000b87d44a3cf75}}, {{0x0000e4bfc25419a6,0x0002ebff3cfde179,0x000b6e83f3646720,0x000fd268db638625,0x0000cc69f23ccad6}, {0x000e45a6bc68bb94,0x0005e97f73340219,0x0005dc97ce43d79b,0x00049a3d44536846,0x0000b9eea326a0b9}}, {{0x000c6ba6102d0212,0x00080f4461ea1b96,0x0009f19a8eaafac7,0x000875b4b85c41c4,0x000075c28e4ef538}, {0x0001a9ddd2e54e03,0x0004d605618b3545,0x00036cd246991adb,0x0002162b8b4bcd7b,0x000072a4f8c86f37}}, {{0x000bd73a6a5da60f,0x000fec4c9ff0c890,0x000536e576f083d9,0x00024304e14d94f0,0x00009ee1edb9aec8}, {0x00041ec8bdcf8e7c,0x00004b041e265712,0x000fff040a5db827,0x000201da0b9a99e3,0x0000aaf21de3c271}}, {{0x000b2e14f0dd2e8f,0x000e1a377ac7b4e2,0x0007a2198e77e7c4,0x000eb779202c3f0d,0x0000759b80018200}, {0x00026eddcfe314e5,0x000403d5cf99c875,0x0005138b6eb84c52,0x0003f461b52ace51,0x0000aa7ff8c73fca}}, {{0x00013c3b9791a263,0x000a9dd58b16ff0b,0x000aad2de960022d,0x000619abd55c9257,0x0000baaaaa4230fe}, {0x00023460d881efdb,0x000f96325e2a9a4b,0x0005c18d4506416b,0x0007afe1381e7603,0x00003bb68bfa2781}}, {{0x000b8bf5116f9379,0x00063126894315bf,0x00019a2c87c64a58,0x000462e1e25cc384,0x0000fd6b0c51335f}, {0x000ba3ce8ee0e0e2,0x0000098c21fa4bf0,0x00066bee06f6fba6,0x00054437d57b39ae,0x000092d513042672}}, {{0x000105dbab093b30,0x000902839986f451,0x00074a89c012f59b,0x000e978a91580234,0x000048c919c2de03}, {0x000a2b591071cd58,0x0009834970a5c476,0x000b7994b791ed89,0x000ffd09bd9042e1,0x0000eaf517a21057}}, {{0x000e2a2d551ee106,0x0008127e09a66066,0x00001148d87a8f1d,0x0003fda0d08bab2c,0x0000da8e4f1a24f3}, {0x00017f0cf9a4e718,0x000fbbf5cb19466d,0x00062ecc0ff50200,0x000ac45ccf97d8d0,0x00000c0d9b001d80}}, }, {/* digit=22 [{1,2,3,..,}]*([2^110]*G) */ {{0x0007ceb1bf4581ca,0x00060ca7b1669885,0x0009722ace635e18,0x000006878ddd2265,0x00000903c4cbdb68}, {0x000458948f214029,0x0004296abda2366e,0x00040319031b49c1,0x0003fda29c4b09e0,0x00007197ca4629f4}}, {{0x000de1cf3480d4af,0x0006cc8acf1a03e2,0x000295a9cf0d8edc,0x00097d023e330368,0x0000add5f69b546a}, {0x00097ad96f8acb1a,0x0004c71bdae28955,0x000dd43f4bddd49d,0x00041976fcd52821,0x00005a4541306191}}, {{0x000c79f439f29cfa,0x000fadd82a3bfa32,0x000a2c1b17bf321b,0x0006185f127f54ea,0x00008365f2e935e9}, {0x00029024d0ef8dd1,0x000149228c4a852d,0x0005afed3395ce2c,0x0008e3a69f44e821,0x00006c1f898c2745}}, {{0x000b6bfc360e25a8,0x0004875a1a788ce9,0x0001732f4e642519,0x00057a1dc756a848,0x00003c0440fd432b}, {0x000b3f1d720281f6,0x000e7135e051c670,0x000052be72205910,0x000a397ed14b0edb,0x000097b3d282568e}}, {{0x0009005dc4532331,0x000a1fac4bcfdef2,0x0003d55acc208c47,0x0002075057a3feac,0x0000723725da02c1}, {0x000c62733eb0fec9,0x000b2b3c63bb9c31,0x0003058384913ccd,0x000d96813e542b07,0x0000d48e72ac10c2}}, {{0x0004ec4d9bbeb3da,0x000337b2921c5442,0x0006d37c534ceafe,0x0006afbe68022e29,0x000028e0a2bd59f1}, {0x0002dd9bc3f9d739,0x00092af3e1fffdd8,0x000736dc46939a8f,0x0008e6c5cff45c31,0x000010f56430892e}}, {{0x000b349dfe392607,0x000703549093de09,0x000853b02984612f,0x0007030cede28167,0x0000d809bb499d17}, {0x0006bfb2756c4f00,0x000a93f02b80450b,0x000ad9561c59ff9b,0x0002c73e69545720,0x0000c7cf0be3331e}}, {{0x0009b9afb3ff9ed0,0x000b17f6515c2e59,0x0004da44928c2e0a,0x0004521cbee4fd47,0x000071279a44f364}, {0x000ff6601fbe8556,0x0007ffda51c497ab,0x000597c0b3ee394e,0x00034ab90385f667,0x0000e9fccc7027ee}}, {{0x000d419362fb228d,0x000136aa0be4ced2,0x00094b197894637c,0x0001e7aa4fc55eb2,0x00009cbac1dcd4ca}, {0x00074800ccdb6ce3,0x000550dfaa49068b,0x000033b78ca4c556,0x0008a7b835382176,0x00005db7525f5ce9}}, {{0x000927274fd1997f,0x00010fadeb588cf5,0x000db260c987d203,0x0003bd6647c6c3d4,0x000008bb13c88554}, {0x000eb1056fad695f,0x000d78334cc7566e,0x000dd1db239e17dd,0x0002ff9a97b3bb7d,0x000091199d9b1c5a}}, {{0x000a437bdc47fe45,0x0002ff3751f0402f,0x00057d48535bd252,0x000cb63c2281b7cf,0x00000083ea5df607}, {0x000e480df6d730de,0x000db1bb06a26f41,0x0001fb48a1164e47,0x000da6f9040c2239,0x000012df252ba23d}}, {{0x000de9314092ebb4,0x000d028e240c0b89,0x000d2f064f17256b,0x000b148f89a7f393,0x0000f57841f21ed3}, {0x0004405e708d8553,0x0001d3f1c3d04ee1,0x000d7eed5856aae7,0x00027098e5424fbd,0x0000333e4efa3ab4}}, {{0x0002b5148f835b12,0x00030adaaba8f9cf,0x0007beade4a70faf,0x00003280d2e24fed,0x0000b1e4e6735f04}, {0x000c0b91fb3ceeef,0x00054a54b0b4eadb,0x000d4a188b817b08,0x000e5f24a787257f,0x0000f13304713482}}, {{0x00012ec4efe42dc3,0x00029664b2bc3120,0x0008f9cb97251b2c,0x000465696c2e6b79,0x0000543376a6b8f3}, {0x000e8416fbfb6a97,0x00039cb91a03337a,0x00002d855e0893a8,0x00073ee3744e9d7b,0x0000e673186906d4}}, {{0x000996f3ef143db6,0x000dd99378bc9509,0x0008ccc899cf1e82,0x0006be559cd09b0b,0x00004b4a2fcb2cda}, {0x000a8b31bcd55df0,0x000d2507cb37d3bd,0x00010e49bfec4e87,0x0004453d48a85eb6,0x00002fbe1bd1f9cc}}, {{0x0007adedda492f81,0x000a682972053bc7,0x000931b4cc11a3ae,0x0004bb4e89a3e734,0x00007512e2eaf569}, {0x00049f3177bf8b6c,0x000948c7ff3e5dc3,0x00011145d232ea4b,0x0009c2dc4f9d16f5,0x0000cf109a3f3b37}}, }, {/* digit=23 [{1,2,3,..,}]*([2^115]*G) */ {{0x000857080eb24a90,0x000d488e0cfd60e2,0x00059cdb87bedfb4,0x0000a9721ebbd7c2,0x0000b0da855bc639}, {0x00004dbde314c709,0x000bdc32e8462b4d,0x00062fc9ecdbf1fb,0x000ab6a3833eabb1,0x0000939b48c40dd3}}, {{0x0002c1f711b0eb9e,0x0007980ab9549689,0x0000792dbb905f2c,0x000125cce26309a2,0x0000c8ac9b3e684e}, {0x000d8b6b40a24474,0x00015fe3fb24486a,0x0008e3b3f60121fc,0x0003941626fccf1a,0x0000e568622aad1f}}, {{0x000bb22236f4a982,0x0008e66800bb5cfb,0x0009a77740b0c59e,0x0009482ac69a8f5a,0x0000b33f804f6bec}, {0x000929532e6c4662,0x000f2e599c73b372,0x0005c31cc68956d0,0x00084e847a249f15,0x00004d80f0e01ce2}}, {{0x00046c64a8a3d626,0x000fc47743d25a4b,0x000f7e4338469c4c,0x000848cbb3a13d88,0x00002b23a1061be5}, {0x00096b4a63d1a4c4,0x000a3d183f3ee835,0x000afb01c454e7fe,0x000638243fce6117,0x0000e65e5e65c4c3}}, {{0x00030e3dc09508b4,0x000f34317655b7e8,0x000690355faf6d2c,0x000ed632606cebdf,0x00008bb92b410c3d}, {0x00054845c7cf8929,0x000945d5f01f65b7,0x000401d69f6cd7ac,0x00087832c30a5996,0x000012686517d921}}, {{0x00077176add85450,0x000672c49b66e5db,0x000421d771b71cb6,0x000fead856073968,0x00003840fe883e3a}, {0x000dad51ec699775,0x0008e07f6726b391,0x000ca160cae243fb,0x0005f4788ac87be8,0x0000174cced9ce35}}, {{0x00067f8ff81578e1,0x00008045447d7520,0x00005aa6f7862215,0x000c77b0c22fcf05,0x0000030f0a67bed1}, {0x0009f151f0bd7390,0x0007e6debe8531f2,0x000677e982d7989c,0x000fd55c070e728e,0x0000a817bd306e81}}, {{0x0007eb6cbc613e57,0x0004d97ea61cc1e1,0x0007eded533131d5,0x00011abf69d39eaf,0x00003c2f4354e6af}, {0x0002493a4a375fa7,0x000c4833c5c24ca5,0x0006e71cf5f06787,0x000666114e091f3e,0x00006451f57fb746}}, {{0x000e082e1539388e,0x000f959a9c6b01c7,0x0006bacfbfd286f2,0x000e52b458104117,0x0000580f07d1bc3d}, {0x0006f75884d772fe,0x000760bb9d4fdcdb,0x000083011d75c3bb,0x00098cfc6c2e4edb,0x000018789a3ad9c2}}, {{0x000ab8495fe1347f,0x00087f24503c5ee6,0x00086dd6bab0f6c3,0x000ef4907e3ffb44,0x000000b6c757002f}, {0x000f9a6a78629992,0x000c9ed89e2648bf,0x0008419eb85e5a06,0x000f1666d311af3d,0x00004f3ad7854733}}, {{0x000551311820d440,0x000c86c4473a5e20,0x000d80eef0c651bc,0x000be51d230c2b9b,0x000042c4a1207515}, {0x0007ca0bfe9e2841,0x00081369827a4251,0x00038699de8f6057,0x000d05084f04f016,0x000074618ee02bc6}}, {{0x00003fc6c68d6876,0x000cbff052c75e3e,0x000d16e7a3e732c3,0x00074692d0efa66e,0x00003d92b27165bb}, {0x00082badd44867cb,0x000e48c081b8ffcd,0x0006c8785a71b4a9,0x0002cfbc1676a773,0x0000e2c06174d893}}, {{0x0001a4b9eca1c9f0,0x000c8ce5e5357bfa,0x000eec30a960bc1d,0x000d38e267d9f317,0x00006fb89ef6c257}, {0x000999ad364a26d0,0x000b26eaab582328,0x0005ba59669b794c,0x000a94ad28ab1fb8,0x00005dcbff356d0a}}, {{0x0006d282bcffbc46,0x0006a6eadb7a5337,0x00035ae69708817a,0x000fde0ff50e05cd,0x00003b5fb75d4bc7}, {0x000e953e7fe08c4a,0x00045583ca1871c9,0x000e81c5cb4d8bfd,0x0001383e8d788245,0x00005f5e93d80474}}, {{0x000160f293c9f316,0x00038864d7a7426c,0x000bbba308eb5633,0x0003025e1164023e,0x00004c2bae38fd5a}, {0x00001e1265aff7bd,0x000f96fd4b148006,0x000075a9c52d8a87,0x0004c58aba20e746,0x0000aa32bf94e123}}, {{0x000bdef694db7e04,0x000779fcddc680f9,0x000b8dce1edca878,0x000ba111981c3403,0x0000274dcf1b0e10}, {0x00043b86def6d1a2,0x0000cbdb1866f727,0x0000c6f58d25b167,0x0007f5a4491e8c05,0x0000be2b2aba7fbd}}, }, {/* digit=24 [{1,2,3,..,}]*([2^120]*G) */ {{0x0005c9dd111f8ec7,0x000d47c4e7603e0e,0x000392a51bcc33f8,0x00092d002f9a91bd,0x0000da4a7963132e}, {0x0000ae30bb1151be,0x000722e322511a0b,0x0004e9e7854febac,0x0000b80a3a508269,0x000058ffec2c4fe4}}, {{0x000349d29c4120ba,0x000f20d0d915fbb8,0x00010ba519f94391,0x00091124074fa754,0x000066adbf6b50a5}, {0x000543c34bfca38e,0x000fd9e1ccfcc164,0x00020219ce0f2755,0x000979b9da0f53e8,0x00008234499a6b49}}, {{0x000c513516e19e45,0x000775c4d5937b23,0x000e71ef656e2e84,0x0004c54f727d735c,0x0000b6304a7479a4}, {0x000a7363ab7e433f,0x00000e742f836638,0x0007fc19f1adea47,0x000697f054b8545b,0x0000935381baa1d0}}, {{0x0004f9d918e49366,0x000652513982b550,0x0004d9cb965035ef,0x000508a553a0c26f,0x0000cb10d571ea85}, {0x00057b7a242da112,0x000d472b726848d9,0x00002a96b16a4d3d,0x00063b1d7e637c85,0x00007c7032b930d4}}, {{0x0006b7d5846426f7,0x0008b47d441d5536,0x0006fbf48e7d09e8,0x000d7ce10b404d73,0x0000fa003d15784b}, {0x000614f17fd95965,0x0000e5cb98db25f7,0x00083a76a49e0e0a,0x0000f7dc65957b2e,0x0000d40da8e1ddbe}}, {{0x0008bb4a595939dd,0x00085874021737f6,0x000ad76120355647,0x00095ebe740e7c84,0x000089bc84460446}, {0x000da5d85a9184d6,0x000b3fc0b074f7f3,0x0008a888e562563b,0x000e7ba6d2e6aaf8,0x000012d8643761fb}}, {{0x000bba354530bb24,0x00078b0869ea9fb3,0x000431163bde3ef7,0x000a3549bc90460b,0x0000d03d7d324819}, {0x0004f9e43b6a782b,0x0006ec88a68633ae,0x000ffedd9216db30,0x00083fe1dd88e000,0x0000280da9fc2bd4}}, {{0x00086913e538cd75,0x000c3e08ad53458f,0x0005d15ffa7001f6,0x0005dd02b8c6e6bf,0x000048234a451121}, {0x0009d2d3d5b40458,0x0005ca904190ff5a,0x000607f8bb0ffeeb,0x000729d5a3aca448,0x0000cbd665cb0a06}}, {{0x0003573f37f59371,0x000dc1e4fca5a37f,0x0008ab0fceb0f6c7,0x0006ac1965a554ac,0x00007fbf56c37467}, {0x0006bd9acf7d720d,0x0007402247662e2f,0x000d53bef41fc8f8,0x0007d0817a14b385,0x0000ae327a64d76a}}, {{0x0005c891f5f82dce,0x00068361079e515d,0x000a353309a7f67d,0x000e1ac8da81e311,0x000044990c52b18b}, {0x000ed95af103e596,0x00072dac9261c7d5,0x00094b8d3ece8aba,0x000e835e82b09993,0x0000830f09a76adf}}, {{0x0001ac194d7d9b17,0x0002582e7f1743c4,0x000da0fca5bafdd8,0x0007ad6f0614c15f,0x00004b043a818ae3}, {0x000afa19e71734c5,0x000e4c450f2e3ba6,0x000e242b115d5437,0x0003c1fa5883fe67,0x0000143bdc27c195}}, {{0x000ce7c6b53f5f95,0x0004cb176d99a2a9,0x0005c081b6424659,0x000ee661298d36b9,0x00003505bb86d9a9}, {0x0009e61f2ba70b0d,0x0008bafad4533f6f,0x000eb4a6ad07e16c,0x000c8dcf1694bbe7,0x0000febceda0cb0b}}, {{0x000d7f2b1f3390b4,0x000c65b61272c676,0x000e127a99f7a1b8,0x0007bf0ebebfc9c2,0x0000602500c9dd99}, {0x000771c4711230f9,0x000b720f09c17f09,0x000e5e38b058eb37,0x000bc01b693d4bfe,0x0000289eb1fd653c}}, {{0x0002b391770f5a7b,0x00005e44eb82a44d,0x00069712ae4d4d79,0x00020d92e69d1e3f,0x0000f11c4d75c6a8}, {0x000f3e542c4224c6,0x000be49d941cb5e7,0x00050e878d6b4e81,0x000c53fd72bd1654,0x0000a61e28b4e25a}}, {{0x0009dc7ab952578a,0x000186e84d0b54da,0x000872042b5423df,0x0006df08b64eeb9b,0x0000c205782f990f}, {0x00096eb21f4c77af,0x0003bab273af4ff6,0x00036b3f11a79c3e,0x00027939bc922e94,0x0000f807ef9c6d9a}}, {{0x000a8f833f6746cb,0x00054ea990cac7f3,0x000ddb0a921e46f6,0x000554e15fd5c5ca,0x0000d41f01728614}, {0x0004434426ffb589,0x000584dbc204346f,0x000969b7f8055943,0x00039a63dd20fe5a,0x0000d59e9577899a}}, }, {/* digit=25 [{1,2,3,..,}]*([2^125]*G) */ {{0x0000ba9b733aa5fc,0x000b305af2353c2f,0x000ac82a5dece47c,0x00018a38e3f715a2,0x000097ba641e203f}, {0x000550409c110608,0x0004c6af512dc3af,0x000f2814656ea2c0,0x0004947ac28daff3,0x00007fab43b159ef}}, {{0x0001641d4c5105f3,0x000e3d7fbd650989,0x000e6bdb01ae80f8,0x0008606d67225fbe,0x0000b433b59afc4d}, {0x0006db693e856387,0x000273e9862f44e6,0x0005c32ecf7b5925,0x000f506b78515766,0x000002fefd81e362}}, {{0x0006a5c97290293f,0x000be388acbffe75,0x000916bdabf04a19,0x000bec0bbbb9cf5e,0x0000489527481f93}, {0x0007ec32a5923d75,0x000bade0c370dee0,0x00019d8fcc7bc949,0x00093f6d51217504,0x00004f5d4768fdcc}}, {{0x000475d0fefb0c3a,0x000aa6d7c35d3754,0x0003798a4d48fb56,0x0008e60070b63336,0x0000e89f3d32fdb9}, {0x00089c86363d14cb,0x0000b7abd27d970b,0x000d5a0218981752,0x000aedebf7d47444,0x00003083bb07ac72}}, {{0x000a2ffcc5e62e9f,0x00046edb02a40acd,0x000120c763b8b7d7,0x000063b700741c66,0x000077e84806d974}, {0x0000678a5e3d4647,0x0002d6bf35a30d31,0x0002f9043de68b1f,0x0000cb5ae83028d3,0x000024e4717c17cb}}, {{0x00041debe949a447,0x0007e46a4fa53897,0x000047bdc638e938,0x0007c9cfe6419ca0,0x0000047f6491aea5}, {0x0008a9041fbab170,0x0008576bdba254e4,0x0002afddcda8e0b2,0x0007bfe807eebcc7,0x00007d3336df4257}}, {{0x000563b4f3011dbc,0x000476610c03fae8,0x00081af0bda33776,0x0008ebed4f6f2a63,0x0000277984d99537}, {0x000a10c5751d2b2e,0x00089a4bf3f45ab0,0x000e3caf370a18bb,0x00036058d07ad4ea,0x00008ef5530cc430}}, {{0x000c244bfe209256,0x00032fdce86762a8,0x00038706391c19ac,0x0004f5fa96a5d5dd,0x00001d587d481d32}, {0x00073a2a37173eaf,0x000763778b65e876,0x000bab43e2384800,0x000fbd20f8441e05,0x0000a11fe133621e}}, {{0x000389a8391d54b2,0x0008a8afe546edd0,0x000e60bbddac74c0,0x000b876525a4ad5b,0x0000419ac96b0ad7}, {0x0003a0277eee51b9,0x0005e239768d078a,0x000d48035e86ecf3,0x000a5b3b0a259d8f,0x00004db43cc2d29c}}, {{0x000772e81685d7b3,0x00018f34a976047b,0x0005f48ef23f27d8,0x0005c3927608e291,0x0000b0b43fad521d}, {0x000fb2663ca72840,0x00041d4db8377613,0x0003b526b7f5729b,0x0003d187b1489858,0x00000b732a6bbadd}}, {{0x000a25b90f8550aa,0x00027c8dae9d4fff,0x000fbb232254db3d,0x000f0eb8cef963c1,0x0000d1cb48244bfd}, {0x0006ea1958773c2f,0x0003110114f184d2,0x00051e67e5862266,0x0005c5fadb3a87f0,0x00003185723a69e4}}, {{0x000f4262048e3968,0x0005b83d9de48e02,0x0001e85ad436b50b,0x0008d6778d348147,0x0000b01ea6b5005c}, {0x000afee97015c07d,0x00087e3ba2aed3c7,0x000d3a1d246cdf1a,0x000ff3aa42e50183,0x000054b52698541d}}, {{0x000c4f948a48e22e,0x000df0335a96e120,0x000151c7bf24977e,0x0008d7baf3442336,0x00002815a80b3664}, {0x000deba66e0a6b21,0x000f717515e8b4d2,0x0003ff24a783a84c,0x0005d968424c0bff,0x00002dd1bb648e1c}}, {{0x000cf304e23e9bca,0x0005726e36243f24,0x0000b6d614387f81,0x00077b86a46a033b,0x0000f1bc8462b2d7}, {0x00001ba527de79c6,0x0003e261bbb625c4,0x0007b4bc70e1346d,0x00062eeb96c44b28,0x000058493c7b2545}}, {{0x000e9d8fdd41d983,0x00018cc7c7fbfcb0,0x0008fa4d98be980c,0x00088d772e86506f,0x000056b14ada48cb}, {0x000ccefea6178f26,0x000d18bb0e35fd9f,0x000f391a9c84a620,0x000c055c75367c62,0x0000a83a5c683100}}, {{0x00049feb8a24a205,0x0001a52ca53f23f9,0x000fb485317ebfed,0x00005d4b691bbebc,0x0000617ff6bb278a}, {0x00034c5e3c99ebdb,0x000d6784156a241b,0x0005d67dffc64242,0x0000109206482f69,0x0000967ce0f9e27c}}, }, {/* digit=26 [{1,2,3,..,}]*([2^130]*G) */ {{0x0000f0441c23fa36,0x000061989a2eb448,0x000a29ca7b4712eb,0x00028bdccbba0f93,0x0000e205c1536194}, {0x0007957b36416860,0x000d45ac8b4e90db,0x0004e03500432691,0x00051707a759acf6,0x0000514d89c9c972}}, {{0x0002c6bc4fe3c395,0x00031c7bebdfe3b2,0x000693459ba4a815,0x000b11a23ab6b725,0x00003bc377064922}, {0x000c8ab5afc60db8,0x0004a0b9f2a34645,0x0000fc507aa02235,0x0002e6d2a2954cce,0x0000c2731bbfce1c}}, {{0x000efb6d9790ed61,0x000c96aa793b5066,0x0003e042ea77a0cb,0x00074b0a915f3c22,0x0000c5def0479c58}, {0x000007873b6c1da8,0x00027cd8557a0e83,0x00060f3b155cf85d,0x0000628f7c7c7604,0x00007052acbc6e58}}, {{0x00091c2e48fb8898,0x0002fb8a9d066a70,0x00082a0e226882c1,0x00052d224986631b,0x000044ed736b5181}, {0x000476fd86e27c75,0x0009b4afefdc282f,0x00019e34da04edac,0x00078b3b256ebc61,0x00006a413e95787d}}, {{0x000b6a20d645fd62,0x000dd61d314816ea,0x000079ae9632cbd8,0x000cbbac1bf7cf62,0x000057ee5c8133ec}, {0x00034a81680ac730,0x000872c77aa0bf6b,0x000a0a1d1aa084e8,0x000b167b5a864e05,0x0000641f6db359a1}}, {{0x000095dc8385050d,0x00050f4b441cf01d,0x00027706a0d54a5d,0x000b7d5a37ccb409,0x0000f008f5515d7e}, {0x00034f35bf716c71,0x0008541bd6ca74eb,0x000e6fa0257a65b5,0x000a09df345e4835,0x000091f913b98342}}, {{0x000d46da670ff1d2,0x0008ab97a1cc1554,0x000d9749324833d8,0x0004986fa6ab3cde,0x000015e0371a9926}, {0x000d592e56d74ff8,0x0004c3b5e1ec549b,0x000e93cb958a8caf,0x00083bbc6087a323,0x0000b054987d648b}}, {{0x000061d5a74be506,0x00047ea16ff582ee,0x000bfc8a2e41781c,0x000e2d80b0c81e99,0x000024f4d696b547}, {0x000545dbdcc9ae4f,0x0005509b1e8e3a83,0x000c935392573dbb,0x000797582960c4a6,0x000001059ae4ae18}}, {{0x000a238013ff83b1,0x0002ead69d08c431,0x0009589ea7c0018b,0x00019f89aeb52a4c,0x000021f41abab1cf}, {0x000bcbaef0f59585,0x000b2be8fbdc0cfb,0x00015aa318deb3ae,0x0006fcc2b954081f,0x0000acc09b39c0c0}}, {{0x000bfa86d518ffb0,0x0006930f124b775c,0x000e81d0fdecee1f,0x000b2f9a402804f5,0x0000e8225c52a0ee}, {0x0005d39fee9e867d,0x000f2b505454884a,0x0007a70d19540428,0x0002a9e2bf2e2010,0x00009917c3c7010b}}, {{0x00042fa3d843d538,0x000593ef927aa98f,0x00084ca7433777cc,0x0005dd4440cdbecb,0x0000c22f9639dc7c}, {0x0002b70c8d947081,0x000cb814364f4bc8,0x000f59b7e7e0b43f,0x0004c4186d4e2486,0x0000abc895e5d6bf}}, {{0x0001e274d559d96d,0x0002e8db6c013815,0x0009921af4f18c0d,0x00002879a3aa836f,0x0000beab27c5c046}, {0x0009eaa7040bf3b5,0x0004c614b091242b,0x0004baf5d39c479e,0x000944e38ede2b0e,0x0000bb192b840a53}}, {{0x000572337e440d7b,0x0008fde23f68896d,0x000c64918685c5fd,0x00080c05b1a26dc2,0x00009390e318ad65}, {0x0001c4e7dee5b9b3,0x0003aeb04f6e8791,0x000065aa6b90c505,0x00028d07b942a18f,0x00004acdf2a4ca09}}, {{0x00064d39de40ca36,0x000f72f3857e733b,0x000ed92f71d4b6d6,0x0002485e2be8e9b2,0x00004ca7048177da}, {0x000ae9b8da993153,0x0004dfc698a4c65d,0x000958c279c14517,0x0000975a296b94ff,0x00008684e0873950}}, {{0x000e34b3390ff239,0x000b4e7d18ef7872,0x0007fe7b1968ce4a,0x000e2a0b4a745e62,0x0000607b0a15aff3}, {0x000818eeb40e3a5b,0x000410fa8d7a1b05,0x000ed48096ac6220,0x0005f205b9058571,0x00002432ef1a7cb6}}, {{0x0009f973112795f7,0x0007284e6ee1715c,0x000b66bcde824443,0x000bede5cb4858ec,0x0000c1367361baff}, {0x00015955dbec38e2,0x000c188ad1535466,0x000e0952f51c0782,0x000fa87ba4c53ac6,0x00007e6782a3b21d}}, }, {/* digit=27 [{1,2,3,..,}]*([2^135]*G) */ {{0x0009740e2c2bf152,0x000589e99704feb0,0x000fbc565627a220,0x000de8cc8d73d0c2,0x000023eed8fe20c8}, {0x0002583a8363b49a,0x000929c2b0a61ee3,0x000dbc85c1a0b6cb,0x0001aba9f7c3d290,0x00008dfbb97bef4c}}, {{0x000236e846e364f6,0x000c7ea50ca0c16c,0x00026b86d7f33527,0x00070c6481077509,0x0000c2a36096598e}, {0x0005e52f024e9245,0x00044db4afcaa675,0x000831790e0fa07a,0x0000d5c5c3ce7d66,0x0000b4ef350f6cbb}}, {{0x0006b2da6dc1d29b,0x00094871e1444280,0x000f49276d303000,0x00004af1feb333aa,0x00005583b9f770bc}, {0x000be7895695f204,0x000149d012b51db0,0x000f61643fc84181,0x0001282409f27205,0x00000d3417515883}}, {{0x0004c050f15dde91,0x0007fd5f2b820521,0x000e82b62a47a76a,0x0005eeab254d3062,0x00001a05fe04ec95}, {0x000f46e9d529b36f,0x00009f9e3df67eaf,0x00031769855ab130,0x0007acd463e37199,0x0000d251439bcda4}}, {{0x000669c72ba075b6,0x00055a4690158c3c,0x0009f8ba889f78b5,0x000ed6f706aade3e,0x0000d8bd566132d7}, {0x000e63b805f08d67,0x000d53bcc1b525f4,0x00025d8477f48200,0x0000a7de801968b0,0x00004afac04f7cbe}}, {{0x0007598a9d82abfd,0x000b16c170f5e2a3,0x00066b0875f188cc,0x000ad9b168220050,0x0000a22c21397155}, {0x0005d3afbddb4799,0x0003dd715b99151e,0x00097cb2e4b606b8,0x000b65ba73b54bf9,0x0000a1bfe43cecd8}}, {{0x0002522cccc18ad5,0x000da1a6e0277973,0x000c2354daadf3f8,0x000689a7382c9317,0x0000ce1680d2818b}, {0x000bbfcd9ecbee97,0x000bacae62ac359e,0x0001ac38a4330689,0x000ee8455ce5b4c5,0x0000921dfeb6e238}}, {{0x00022f3dbfb894e2,0x0006ae274b18e131,0x00058aadfbe9b79f,0x00035165a49de5ca,0x0000495775831487}, {0x000ef61bb9390993,0x0009f6d13694111d,0x000fc253b1d6a974,0x00015e1474b4ced3,0x0000a1485e67c5db}}, {{0x0004ddb0f5f27cac,0x000ae80d59ff6599,0x000601023e85461f,0x000bfb3f05481a66,0x0000665427bbc9eb}, {0x0001a697587fd52b,0x0007dd49efceb057,0x000420688935289f,0x0006aeb1becc60ea,0x000022639d9c3a78}}, {{0x000dab61430c9ab7,0x0002b238e9975afd,0x0008042ae0bdd41d,0x0004cb8094743041,0x00001f9addb3dddc}, {0x000c016c52dd907b,0x000c79e2047f7090,0x0001011a6d9bdf44,0x000c7836f1fe801b,0x000063accbd89acd}}, {{0x00076680448087c4,0x000f31432dae264c,0x000f9bf47ac30903,0x000d02f851b26600,0x000000ed311acdd6}, {0x00079fef8fd24247,0x000a8a6da98b045e,0x0001e673afdfd974,0x000167d5c9f6410c,0x00006f2e733cb2c5}}, {{0x000acab4baef62e3,0x0002785b91e87817,0x000e576109f5a220,0x000e036666ebe66c,0x00002ad31f4273bf}, {0x00030a425bcf4d6c,0x0002915056e66283,0x000332156ea95059,0x0002d699811c89e1,0x000089cf1ff4c11b}}, {{0x0005acbc46d7ce17,0x00071b085877889e,0x0007a50509a515bb,0x0000358ac1a03d0b,0x0000d3e738b62926}, {0x000c2ce2a6cb0ebd,0x0004bf7adc79861c,0x0000163766f2e295,0x00008f91c4d45133,0x00009fd2c812ad59}}, {{0x000337ac0b7eff35,0x000e75e48b3c0ad7,0x000f13a5f8552225,0x000cbe96f78b0c73,0x0000e70062ed2349}, {0x0005048e7073969a,0x0009233cb3d26b8d,0x000caa20f392d2a2,0x0007074e4f727c4e,0x0000068c99ecccde}}, {{0x000d65861a023efa,0x000419e5246e1888,0x000563ec01d72aab,0x000a4309a26348e5,0x0000097196463439}, {0x000d54badb9b5b76,0x0001645a524b567d,0x00038e60873fac1a,0x000f482fe97ef7fe,0x000008748d29f384}}, {{0x00086ec1ed66f181,0x000bc61fce43ebde,0x000bed74d225d906,0x000ab74cab07d6e8,0x00006e4617f37855}, {0x000aaddb2fbc3dd3,0x000f5aeddf5b6568,0x000cf2fadedb5484,0x000699578f20e86d,0x0000516497c915f5}}, }, {/* digit=28 [{1,2,3,..,}]*([2^140]*G) */ {{0x0003fecfa181e695,0x0000e0d69a98ef0a,0x000eab95d9ea02f8,0x00002162e9cf8e66,0x000020f2beb74720}, {0x000540a1df843618,0x0000f1fa6d5d621c,0x000f5f6ff1203772,0x000ef2ee3c7b510f,0x000017a069c2bb2b}}, {{0x0002fb6b294cda6a,0x000519039f348357,0x0005cbb216ce9bf7,0x0000d980e012f009,0x00000aecc1c7063f}, {0x0001c3af02909e50,0x000f48ce9cdc57c2,0x000e336f8c7d59ec,0x0005f42732b8448a,0x000056e37233f4f8}}, {{0x000b53189e800ca4,0x0006d45208fd8a10,0x00014ba3750fe0c1,0x000acc5e43c0d3b7,0x000027d200e74189}, {0x000e24fe616e2c00,0x0008ee1854c105de,0x000342a739c25f4c,0x0009524d3222a58f,0x0000807804fa027c}}, {{0x000653a4f0d56f34,0x00078a28b805c222,0x00073434b961e404,0x000a18ec03f8b04a,0x0000c966787eb712}, {0x0006c42864fee422,0x000a3b0ece5ccc19,0x00031c159c1be93d,0x000655887d9f22c1,0x0000bb6d593fce45}}, {{0x0009ec9b809b7ceb,0x000b32c72c2c22c4,0x000a0bf368a41486,0x000c68d13b9420fe,0x00003d36eea566da}, {0x000c08a328cc987f,0x000b4a3264616fdd,0x00010dbba0a3bcd2,0x0004c38103c49dd8,0x00009d81a293b78a}}, {{0x00065ade4d559419,0x000da03840873de8,0x000f18b9bdedafa5,0x000267df414abb4e,0x0000ee9ea438aee5}, {0x000aa1637a55a4a5,0x0003b15f93b9260f,0x0009c3598eb19a51,0x00078e01d7ebd29e,0x000023fc56d69321}}, {{0x000070cb98fe684f,0x0009224a1458501d,0x000bc6b3fd60fbe9,0x0007cab45761c892,0x00005384859ee6f2}, {0x00071f7b59e763bd,0x00088b5a8e5e4b02,0x000a482923d4606a,0x0004454eda5d9b05,0x0000a7731d1b6fec}}, {{0x000369390d458714,0x000fc6166d8da3e3,0x000a90403e976403,0x00063775c3368289,0x0000bd17983b2f1d}, {0x000679ed5d2c53a7,0x00088dcf3b87a616,0x0006a694e5ec4bcd,0x0007e53e6d7613b6,0x0000460fc7753fc2}}, {{0x0009b8295caabee0,0x0005889501e37046,0x0006ed265de024ca,0x0008b26bdadc0607,0x0000cb1236b5a0ef}, {0x000ddbf0972ebf9d,0x000452aca4324065,0x0004aff76f1dd387,0x000d23d88b97cf74,0x00001359afece8e3}}, {{0x000ba2b91502cf37,0x0007984db75d52a3,0x00030b1c92c3832a,0x00060b94a12dddde,0x0000802eabd531fd}, {0x0007327a37fddab7,0x000b8aafa9733370,0x000e6f91a65d6f2a,0x00030ac525c5b811,0x00006aeb0c9cf465}}, {{0x0005ff62f93a6750,0x000405f48679e881,0x0008ae884a6ec968,0x0008736dcbb55635,0x0000af61472e19e3}, {0x0004372a5f696be1,0x000a5f22fb707233,0x0006cea90c65e57e,0x000b2a168da30c94,0x000036a8a8775681}}, {{0x00081dc0f9f44d43,0x000ffc46585aad5e,0x00047d1b1f09a695,0x0008b1a1649164c4,0x0000b4b36c8b79dc}, {0x000177b3b6b234cb,0x00046730d9d020d4,0x00080531d096a250,0x00095c5611b9b8ef,0x0000a904b3c14bb4}}, {{0x000d9d493a3147a2,0x000c7a5655451192,0x000f072129f30a5d,0x000c1370b1f9cb6e,0x000099585462d87f}, {0x0003effc17db9ba2,0x000cab1644a8d332,0x00049ffbccb18548,0x000683f8a306d44f,0x00008d658f16c2e8}}, {{0x00060cda99f8c71a,0x000aabf742ff44ba,0x0004b3f9967b7abd,0x000160c6310f9c91,0x0000e430a339412c}, {0x00076d388ace52f4,0x000412d7067d1e67,0x00007cd1b4bc0fa2,0x0002c0c3c286aa8f,0x0000cb8f38ce985b}}, {{0x000be808c3bff364,0x00021263e57583cc,0x0009bdcd1005a0bd,0x000b6b060d7dda25,0x0000a1c56433a5ca}, {0x000dbb99fe4fc88b,0x00081c97bbb52b7b,0x0002321ae09418e2,0x00064e28274fb4a1,0x0000137007e0c87b}}, {{0x0001fe1c63c4962c,0x0008d81fdb258053,0x0004c2b6b50541e8,0x000fca1c1291a1fd,0x00000693a1866df4}, {0x000604e0117f203b,0x00025a99b8d0b2c4,0x000212c44245f196,0x0002a7fedc20aac6,0x00001ed4e57020f5}}, }, {/* digit=29 [{1,2,3,..,}]*([2^145]*G) */ {{0x0000fb6700a1acd0,0x0003fd999681b556,0x000b4e1bae823fd7,0x0000a3da915d1f6c,0x0000d0301186ebe0}, {0x000b0c989fca8cdb,0x000b49da0e0b744f,0x00031d76f970d01d,0x0009695ad8c56479,0x000015737c0a659b}}, {{0x000384ece53c2d04,0x000d1e4606daa12b,0x000ec12b0779d897,0x0001ad653e47b073,0x000062dbbba9756f}, {0x00009f2cafe37b68,0x000f6cce2e1769fe,0x000f607fd273d1eb,0x000c250ac1d5383c,0x0000035f7ff92e10}}, {{0x0002d5a2093c22a9,0x000145703aedca44,0x0003287b6ebd0bd3,0x0008b9a08f2afd65,0x0000bb88bac9d1bc}, {0x000853875c1e3b2d,0x000ffa11447cfbaf,0x0005c4c8dbd2ac94,0x000207586d816cea,0x0000c3aa800f8dc3}}, {{0x00034c77e6c55202,0x000fbcb9ea58854d,0x00086666dc27df9e,0x000a85205f2369d6,0x00009d1febf2417a}, {0x000819e93470afed,0x000912a27f9e9846,0x0001e65043e6a966,0x00080954d008a2e3,0x0000ba7ced06cb76}}, {{0x0003e41d07fa53db,0x0009c4e35bc526a4,0x000da2f8c3154a78,0x000f99cb768924e0,0x0000a964a2bd3613}, {0x0008d35ba1d16c4f,0x00010b54d0575a54,0x0006402052e1bfed,0x000f290f992136bc,0x000039cb9157156d}}, {{0x000e64699b444ad9,0x000d340504c5c913,0x0002e53dbddfce99,0x000536c8482a99d4,0x0000aaf2c2661aff}, {0x000f7962664cf67c,0x000931393e2bee90,0x000225bb074ab5c9,0x000d6c3ad0faeae6,0x0000355648ced63d}}, {{0x0001d271d91cf9d3,0x000d8377b20ae4e3,0x0005e1327cb35d4f,0x000e7544de1e4505,0x0000298e31b58703}, {0x0007237de0133394,0x0000e3d101c65508,0x000aab0dc32cbf30,0x000bb9870dba22e8,0x0000a52623d7d155}}, {{0x000f541338d6e434,0x00030541d5ccecaf,0x000bc88ca56f7dd7,0x0002c375d426de96,0x00008d94f6bded3a}, {0x000a3bb2ef8279cf,0x000a1b1867f26354,0x000225151d575465,0x0000d7ff99b0ff95,0x00003e19d89e9450}}, {{0x00035acc85dcf572,0x0008a88f5415dbf4,0x000c558076174565,0x00056f06367e9a17,0x00002d077a5ea90c}, {0x0002258a2e04e763,0x000e3e06e405fbf7,0x000e6f954ba965d3,0x000a742724d06fe3,0x0000e47d475b1251}}, {{0x0000151e0fb82f76,0x000675668ac2b8ba,0x000d711b00d16072,0x0002f2022ba25814,0x0000addf557df3fe}, {0x0001e1c6b9c94354,0x000a773826bd2b83,0x000240f89ce3a060,0x00003a53fa11c11c,0x0000f9cc8d8d56e3}}, {{0x00031f6641f82c90,0x0004dffec7564b93,0x0009158abd97c7c5,0x000a7ff5ee6d1f1a,0x000054493a385c3d}, {0x00005f5eb7d96df8,0x000764473a39a57a,0x000e16d55a3afd44,0x0006adc2a4d9c488,0x00003e144f675f87}}, {{0x0003268e32dd620a,0x000ec27849a292a8,0x000378882913ec99,0x000cfe4dd8fdfa2c,0x0000f96f33f8e6f8}, {0x00037e5dc3fa8a51,0x0001a0b03a1dc067,0x000f037b0236bb53,0x000a5323e59f2989,0x00003f9b5a7e9a12}}, {{0x000ae9559029aa6e,0x000b7a4db2ed50d8,0x0008f373dd74e292,0x000b372b9c335584,0x0000c018db78c45a}, {0x000690269cc53a8b,0x000c6a8798641f44,0x00013475e8c4b628,0x0009f56c743d284b,0x0000f4a933923de1}}, {{0x0004f47f0cefa69d,0x0009d45468664a8a,0x000f603c1dc8e4cb,0x000ac4659ba69b23,0x0000ab4d601e87b7}, {0x0004337c1ebc8d9d,0x000382b4074ba6ca,0x0002fb7339fa6585,0x000ea94a4b4f8190,0x00002bb5d7b7525d}}, {{0x00092d5f81f95671,0x000a3d698470eb2e,0x0004c81eb54cb95e,0x000c644f2acb28e0,0x0000c1ebfc508cee}, {0x0009fac06e074235,0x0008e7fa0c858f79,0x000f4db4472225f9,0x00009160cd861634,0x0000ec36159c52c9}}, {{0x000f6ce51efb3108,0x0004158df5be0d0d,0x000158e59cb5b2eb,0x00033656459e2936,0x00002aae2b99466e}, {0x0008a39411aa636f,0x0004e4c0a933fb65,0x000f026b77152ecc,0x00011f010c758a49,0x00004837f98bb093}}, }, {/* digit=30 [{1,2,3,..,}]*([2^150]*G) */ {{0x000523a626332d5d,0x00028561bb44994f,0x000845ea27bc3883,0x000089305ed4b03d,0x000039d3ee292a1f}, {0x000fdd3e7676b0dc,0x000f3b7060176561,0x00064f9a8620e35f,0x0001f676ce424ff2,0x00004c341a09a268}}, {{0x00031769bb816483,0x0005353120d000f8,0x000cabc62d69eb48,0x000cb1a17d75f44c,0x00004a07f82e749f}, {0x000f787bbfb55541,0x000052e283f82c3a,0x0009213a0b06ed4d,0x0007b44722889fa1,0x000062b085eecf3c}}, {{0x0000ddaeb300f7aa,0x000c4db5e80136d9,0x000d5244c9dcf7df,0x000aa1c45cb26874,0x0000127ee79d48e3}, {0x000cc53575f1dbba,0x0004e0e6161e488a,0x0002650d095037e8,0x000215b7e5928329,0x0000be67d99b4938}}, {{0x0000d2f7189e71f4,0x00081ecf91e73267,0x000757a21c643874,0x000ce4d5758e57db,0x000027d09f8690a9}, {0x000308f38384a7a9,0x000420732b99846a,0x000845819aac3acb,0x000e030e94100917,0x00005cba11237ce5}}, {{0x000aa377378058e6,0x0000a4411154eb81,0x000828ac741c746a,0x000b29410c73bcfb,0x0000439be91fd972}, {0x000b4b043a2fbad0,0x000f82b5e8404bf3,0x00097bd4c39e6dad,0x000ccb4f71640863,0x0000f7de5687f1ee}}, {{0x0002a73f37ec3c39,0x000d4d59eba0db33,0x0004d3257c65259b,0x00038f9291709cdb,0x0000a793b264d389}, {0x000e34be43756f0e,0x000dbafb56c9f39f,0x000208b272f76bdc,0x0002c2bf37867a61,0x0000a1d4307e8997}}, {{0x00044878a429f4f8,0x000b5b516609d0a7,0x00069b5df0649712,0x000af23826ba57e7,0x00002335df29fc7a}, {0x000f0675c93d9950,0x000a68677be62389,0x000d9951b59ac367,0x000ccea77985ff21,0x000038956fb85011}}, {{0x000851aaaca5e9b7,0x0000e6713b9797b7,0x0000a61f6518aa52,0x000b68c357e8c715,0x0000842e7e35c2c2}, {0x000af656868a5489,0x00025068fc818dff,0x000917733d963bd8,0x000327d4da5c8b65,0x000027091000b247}}, {{0x000db942f6d0d97b,0x0000943b9373d6ff,0x000d36db605c3ee4,0x000c3e02e541ebff,0x00007415a977e1dc}, {0x000682e163aa2f64,0x0003ef3af218e383,0x000fdbadb46febdd,0x00021a50a0507eba,0x0000ca8ab4e0e52e}}, {{0x000832e1b7cfb737,0x0001cec354c9a3f0,0x0008eadca7a8afe5,0x0002bb3e91c97e37,0x0000449c59a1c3b3}, {0x000c3710b1c4655c,0x000a379da87ea619,0x00038d96a692e4c6,0x0000ec3f3f5d86de,0x00005320f42dc08c}}, {{0x000f2bc8fec5dec0,0x000f84d6786c92a6,0x000ffa084a71383f,0x00071587588c06db,0x0000d85f5ca6857e}, {0x00011b3b6c774d40,0x00084c3521a8e873,0x00029fe0f672357c,0x0008cde5fe74615b,0x00002bc51105b715}}, {{0x0001e48a105fc8eb,0x0009789ba48c37a0,0x0001c2180769d754,0x000387108c6fe1d5,0x0000032dd3467bd1}, {0x00026db020b0aa69,0x000f7664c73c9538,0x0000cf95d05137e7,0x00028a366302c466,0x00009004e1242cef}}, {{0x0005b284f9735368,0x000e535b04ea824f,0x000a03089b43e299,0x00042c472c88f74d,0x0000269d57ac5a2e}, {0x00063fc6607b38e8,0x000ea9390b0c7c1e,0x000ee2869e89e2aa,0x00097447c740da1b,0x0000556f6fd2f3fb}}, {{0x0003995a4b6bed1a,0x0004f7095c541a0a,0x000a73ce92dab579,0x0008a666c6a1ff2a,0x0000dd0a54bede43}, {0x0006b1afca906cd1,0x000619de10dd160b,0x000633da325fc601,0x000d5a248e9c99d3,0x0000fe3f746258a4}}, {{0x000edc88be85c1d0,0x00083ca09cb6c253,0x000e3055add3d0e4,0x000dbfb997f6879a,0x0000c929ad007431}, {0x000621584d2db42b,0x000e578828cdcef1,0x000bd4b66b50df3e,0x000b039589da9d6d,0x0000c4fd2e4899c2}}, {{0x000c9a7d298c241d,0x000986807cfd214b,0x00064eadbe3b697b,0x0009c51f1c780245,0x0000de8cdd084814}, {0x000f0a75a4d2604d,0x000e9c1538af946b,0x0005b1fcc27154d7,0x000f81c5cc9230de,0x000088519ea36864}}, }, {/* digit=31 [{1,2,3,..,}]*([2^155]*G) */ {{0x000dd1a7cb1282c7,0x00064e46973ab828,0x00008d6b2a08d762,0x0003f2fbaf8d40e7,0x00002571fa1bdaeb}, {0x000732ff22dfd98c,0x00064087108d85b1,0x00088207a87ab01a,0x000754eaaafea859,0x0000cc832f929f00}}, {{0x0001185ca8d9d1ae,0x000cf987ded2488f,0x000c46124adf2c77,0x0005f37f3039f060,0x00005d70b7651e09}, {0x00086506260e70ff,0x00070750d10582d5,0x000bac36439d75ea,0x0003289cf3d0b175,0x00003a7564e11d01}}, {{0x0004700ec3128c2f,0x00019e383f4994ab,0x0003024eb6c76d86,0x000c68ec36b150c0,0x0000b43947843daa}, {0x000764a8dc796230,0x000db440fbb2fc68,0x000c5ee0d5b86995,0x000bd3d66879bfcc,0x0000522894295aa8}}, {{0x000a43e3fcd3efca,0x000418088e9ab24a,0x0003d46eadd26c03,0x000a6f05ef4dc9bd,0x00002f99d592a4c6}, {0x000d3552f1da46cd,0x000d4afacdd1ddab,0x000d4057872c3f8c,0x000b94090c4eee92,0x000028bb4209a623}}, {{0x0003becee8314f30,0x000ddbea298f5e7c,0x00080acec1c068ae,0x00095b08d381f17c,0x00003b56be8e3304}, {0x000b8f29222882d6,0x000664af8bf7aeff,0x000c57d8c95ff38f,0x0004eff0e32d351f,0x0000635be5277b44}}, {{0x00092d2e7417ce17,0x0001270ee7f52427,0x00067a41eff42bc7,0x000a57aff4dc6d5c,0x00007709b7b90882}, {0x000731dbe217f2cb,0x000cabb721773554,0x0001dd0592af2a8c,0x000476a8eee76959,0x0000b2930c9fbba6}}, {{0x0009126cecdaa7af,0x000d1b13247b174a,0x00084c1c4fc8c7e0,0x000c3a39c110d234,0x00008eb8758731df}, {0x0000212c00674527,0x000e0b9b926c022f,0x00042daf43f6f69e,0x000de399032da0ef,0x00009f00adef3f80}}, {{0x000dddaf176f2c08,0x0004625726581e6a,0x000342ffb01ca460,0x0008d58a404ded85,0x0000cf60f96c4183}, {0x000691cc9071c4aa,0x0003944428039bbc,0x0009c0d81fd58874,0x000f7ef7101c8580,0x00007fb754d2c456}}, {{0x0009ff4c1e99d816,0x000643c617c0f855,0x0008c6ba708e1a7d,0x0007945398fd4324,0x0000ffedd9231283}, {0x00059d2d629d2080,0x00053490530e8a6a,0x000505989a9d141d,0x0004ee42f6fc1838,0x00009bf250d479d9}}, {{0x000a1d5af71013f7,0x00049bedc9466af7,0x0007370a0e68216e,0x0001cc84cba30bd2,0x0000981afbff7042}, {0x0006a679449f0e1f,0x000d1a47edae0249,0x000feca2286cfc4b,0x0008fa4073c936b1,0x00005694612f3f8f}}, {{0x000f9e12cb7191e8,0x000865b08ea6ec14,0x000332bb978ea1bd,0x000e24bc65aa9b46,0x00004cc22b43f80c}, {0x000e9e9d49d5bf18,0x000599087da40098,0x000f6e357cd4ec1c,0x0004b7bc9d07c5ae,0x000039a02691f8f6}}, {{0x000d6715bde48f8d,0x00025189bc7dbcad,0x00009ee8ac970387,0x000ff78d45299ec7,0x00001287ee3545aa}, {0x0008874db1dbf1fd,0x000ac90c88d67d1f,0x000368313ea46588,0x0003ad90ba649a84,0x00005fdcbcf30d54}}, {{0x000643037577dd85,0x0003d9c5fe88f795,0x000bdc13283b82af,0x00039e4c1bea26cd,0x000089fa086ec043}, {0x0009538b13799dff,0x0000e295d034033e,0x0009ddcca85fa8b2,0x000333ef17f73fbd,0x000032bd123cdb66}}, {{0x000e9959890272db,0x00098e713a10cf3d,0x0008227b875f3432,0x000dc7ae13479fe2,0x00008561eaaaefac}, {0x00097a08332aafd7,0x000503809b62a6a2,0x00063036f9b0d8bb,0x000da862fa1cfd0c,0x0000a16eb562d64b}}, {{0x0004ec13cf482834,0x00055c8a705e4cc3,0x0007d4f84b09daa2,0x00029d91e9d0d05b,0x0000df6ef651b389}, {0x0000763aa21ba469,0x00081293f8fbe16b,0x00020aabfc6b1d17,0x0009797ff5b602d5,0x00004d671be53393}}, {{0x0008e8a2ac13e274,0x000f0eb1a9f5f7e4,0x0001f0a624494f6d,0x0008f0adbf84eb98,0x00009badc3293643}, {0x000a541004f7571b,0x00002f1c94ee50be,0x00027bc31bac67d1,0x000e27753d73a1b7,0x00003d01cf2e0686}}, }, {/* digit=32 [{1,2,3,..,}]*([2^160]*G) */ {{0x000e50f6d3549cf8,0x000f7acd665ed433,0x00011fcb46f33696,0x00085fe95bfdacce,0x000010ee2532f7c9}, {0x0000fe17159bb2cd,0x000da58b357b6545,0x0009fea72f7dfbeb,0x0007445b057e74d6,0x0000485717b62731}}, {{0x00042e8ee36860ce,0x000c6113c22d896c,0x000104213daf04df,0x0004e93adbb7b744,0x00005fd5fa1ffd39}, {0x0005d941a4e0551e,0x000d38d101516823,0x0009845236772cfb,0x000a97476071e309,0x00004e879df3a56b}}, {{0x0000aa9b898fd522,0x00079e9af1a76c8d,0x0004f03f82fb38a5,0x000c6fc1f2b9a93b,0x0000b1aad44e3f0c}, {0x000332e7cf2c0846,0x000ea367d26d58b5,0x0006e4a8d1c57d96,0x000b69c297eabdfa,0x00005a947eeaa0e2}}, {{0x000afb0285b94916,0x0007be4c705eaaaf,0x000d9caab01a0be8,0x00033f9f1d4f5d2a,0x0000e349a4b237a2}, {0x00012464a1c6a163,0x0005f9383260cf1c,0x0006d5471d99e6b6,0x00089bba3d43665f,0x00006974d052f8cc}}, {{0x000b616fdd5b8549,0x0007c728719ff535,0x000921cad592549c,0x000ef85231468606,0x00008c8ce34c11b1}, {0x00037e7e9090b363,0x0008dbf7bbb728b9,0x000d8797467fc3ab,0x0003fde2337097a9,0x0000e5adca22970e}}, {{0x00049a1cfe89d80f,0x000cea9c8371c26c,0x000d066d2b42c026,0x0003edda6c013ada,0x0000b8f722946a4f}, {0x00079ecd850935b3,0x000ca631e1b308b5,0x00019853434c1a74,0x000f259b5fe596ac,0x00009ff21f711f24}}, {{0x00068a7b3f85ff0f,0x000c2a888044cdcc,0x000dbe894acd21cd,0x0000d3c6719b2e05,0x0000ae1d3d97b826}, {0x000dece8a1c5d92d,0x00040c52077eedfe,0x000dd13edbca01a9,0x000aacf085549c16,0x0000c5c3baf195eb}}, {{0x0009e148f9290579,0x000630c853df27f2,0x000e9c5ce7a64ae0,0x0002a4956cd18358,0x0000d9cce836ed09}, {0x00059796e93b7c7b,0x000181bb9e27cc6e,0x0009e29a0e1e4709,0x000644070b3083aa,0x0000f181a75e785e}}, {{0x000063fbe7b643ab,0x000796085760cc17,0x000214c9e7872e1c,0x000637d6b0fffbb4,0x000018bbc0f22bf3}, {0x000de0c722591c92,0x000928c29e0c8b17,0x000304f201edeab1,0x000fb67fbfd98ef4,0x0000d1dbb6bbc77f}}, {{0x0002c658ead09f79,0x00050780d14df53f,0x0001b66bc1335e1d,0x000fc7d9cc20e0cd,0x0000b670a384be0b}, {0x000dc8128efbeedb,0x000bd326a6e5ce53,0x0008e9a630c74e77,0x0002478604e0d2b8,0x0000ab38fcac3dc2}}, {{0x00016d3c7141771f,0x000a3f226b662556,0x000ca63a9a86691a,0x000f2aea19fea4b3,0x0000c05dc439e672}, {0x000e786718ba28fd,0x000acc66b984a9c6,0x0003702f207b7995,0x000efe3f434f551b,0x00006f62130aa84e}}, {{0x000e8c85c0a3f1ee,0x00019c87c37f8ed6,0x000e3b78dbcad249,0x000a461dfb62bb9e,0x0000ba8e478abceb}, {0x0008cb0eeaede4b8,0x0007f976deb637d3,0x0006147fb0bc498e,0x00060932944c046b,0x0000b123f36771f9}}, {{0x0007987b5b41d786,0x0006ebf0c4f84b0e,0x000b80ecdea7df90,0x0007e554d03560fa,0x0000cf306f75b1db}, {0x000fb5689fd4773f,0x000f10f9be330d59,0x000352da4ab254f3,0x0003ee28a09a9277,0x000081862f6541ea}}, {{0x000dcc7de79dc241,0x0002458f69cda155,0x0001850dff1168a3,0x000848aac215950d,0x00005c8295bc204c}, {0x000aa367d8184ffe,0x000d50447bdbf661,0x000e4a59ec396228,0x0005e531cd5143bd,0x00003a26e3c4beab}}, {{0x00001579f759d014,0x000f3eae4fdeb59b,0x0000ba8c0a2923d2,0x000442d832775769,0x0000bf7e38b84f51}, {0x0002563b413fc268,0x0002f9e53b36b681,0x00089f66dedb7d36,0x000415cfa585c4c3,0x0000e1adc31d4bd3}}, {{0x000a13f1402b9d0c,0x00026c7bc863d3b3,0x0008c3e6e573441c,0x00057d8b301ec457,0x000026fc9c4cadaf}, {0x0001bfd7493cea35,0x000ecaf8145696e7,0x0008c608fd05d4b3,0x0002768aca2a8a6a,0x00003ef07f65725b}}, }, {/* digit=33 [{1,2,3,..,}]*([2^165]*G) */ {{0x000c9d646ac49d20,0x000b83137aa9a6b5,0x000225a3842c77c0,0x00090724d000fc68,0x0000f63cfc82fe1e}, {0x000b01bc6441f959,0x00095c8e448f22d1,0x0007fb1ba7d38f71,0x0008df0b33fa5f78,0x00004dcfda1a9015}}, {{0x000de10296c36eff,0x000192c4da77211c,0x0007836da7ee8967,0x00060ac617d270a5,0x00000cd9c328cb75}, {0x000cbf7e455fe908,0x000afe7334f301fd,0x0007de4ec3fb53cb,0x000fcff81e2ea44e,0x0000adab3ad8b384}}, {{0x0008a2b599ff0f94,0x00074104fc6b0177,0x000694ff368a923d,0x000f121bfa44dfda,0x0000f7199dc37667}, {0x0008ff6e46f2a79c,0x000d29f8131dc06d,0x000b4ce7c08b5dea,0x000c3d42519a59ab,0x00004f710bd742ae}}, {{0x000368b4ed80940f,0x00058a6fcedd3014,0x00097579f67e6d05,0x0007f58c208c49ca,0x0000e3d7a8292359}, {0x00032027e096ae27,0x0006b4b393665e20,0x000dcdffcb1f3e1e,0x000e82b6da26f32f,0x00009422f1dd097b}}, {{0x0009c748c878145f,0x000e49c635655054,0x000cf2d5e67f14ed,0x000d0f32ddf78c9b,0x0000faa843058201}, {0x0004a9dd1b2de28e,0x0007254be41447d9,0x00082755bc09c4be,0x0003bccc80e178ca,0x00003251d113697c}}, {{0x00009d35001417b1,0x000e4962ed5e2bbe,0x0009f46c3795e84e,0x000a2e4b79d1ca27,0x0000f7f8a3b93836}, {0x00000b14a64dc32e,0x00042f84f7396922,0x0009155c0c842433,0x0005071110da07cc,0x0000e8fbe62394b0}}, {{0x0005391035703ccf,0x000950c7e24d2f6a,0x000fcbb9a9899bf6,0x00075ad3f7f248bb,0x000065027dfc5558}, {0x0006b69ffff3b37b,0x0003645b4431a7a1,0x000afd67967b6eb5,0x000cde69d7e1d249,0x0000d819babc10fc}}, {{0x0002cfb9db3b3818,0x000e54df0a4b263a,0x00004e61f9c3a2de,0x000324f28d06e97d,0x0000b1adfbcc2449}, {0x000d9397e053a1bd,0x000696daf7076ec1,0x0000ac7abee2be5c,0x000173b0ba1e1481,0x0000d2ae779c530f}}, {{0x0008e703b9f04267,0x00059c84f17c3e70,0x000b70a0be5b02fb,0x00065cbf4ff35be3,0x000081b3c600b155}, {0x000636a6e124c3a1,0x000a7b496784e76c,0x0003f0370bde81eb,0x00045d9412f8e244,0x00005d42362a99be}}, {{0x0003ae2a4af76c14,0x000bc8276fe70f50,0x0003a33c6550e66d,0x000f84d1e0c1fcbf,0x00002be231046629}, {0x000743e516ace497,0x0007d36a2262edf7,0x0006ca192ce43666,0x00013e71ac703644,0x00003631cb5b76fe}}, {{0x00082d4a160bcfa6,0x000558ceb1f2d47f,0x0005a8d25258fb07,0x000c9cef818e8fdf,0x0000685475ecfd31}, {0x000385ae1e9b13f4,0x0004b0508bdbcef6,0x000f1f90de0a4259,0x00081e1ad7ae16ae,0x00005a155efa3f8a}}, {{0x00007c28034b95e9,0x000587bdc5608ca4,0x0009807e8c93eb97,0x0004eabec24e8d33,0x00001b734d76d64a}, {0x000ce398f668b26c,0x000a541823d5d0fe,0x0009e4e004822cc4,0x0001adf953bc32f0,0x0000a0a7c60c6d86}}, {{0x000d4470f33e712d,0x000555a87cb04c74,0x000962db43cec1e0,0x0006a98cec0610e5,0x0000971af1641a25}, {0x000c983a2ef4ac95,0x0003874e9d00a044,0x00073d881caa1da6,0x000c8bab972d8346,0x00000747c5a53a26}}, {{0x0009982a3e25566d,0x000d48e1b8960434,0x000b2d24beef9075,0x000a547c7bead092,0x000099f72fbda21b}, {0x00009315005e541b,0x0007eece3205b93e,0x00062f2f62a7a983,0x0000a63b388ed114,0x0000488b15ade346}}, {{0x000cd67969d56af1,0x000ccfc58a8b43f6,0x000e703779e0d872,0x00046c301c1509a4,0x000003d1a1318ad6}, {0x000e37e9d0624278,0x000c39bef78c078e,0x000e661424e69c5a,0x000d81d21ec00136,0x0000de1ecb32634c}}, {{0x000d97a205b9d8b0,0x0004056756d40435,0x000f8210e6eb8f06,0x0009ead5e88a8bb6,0x000070ef12dec9fd}, {0x00095053bcc876ae,0x0007c7404ce34d84,0x000a1db5e12a7533,0x0005acf22b49e1b8,0x0000c1f2051f4bfa}}, }, {/* digit=34 [{1,2,3,..,}]*([2^170]*G) */ {{0x00081b5c4e83d33c,0x00089efd488b43ed,0x000eb4d0fd9f3587,0x000393564a620f9d,0x00006927bdc6c6a7}, {0x0008df79f9e0f036,0x000e9cd7e1a945c2,0x000a348f12868661,0x0008e01cf4e8d0ff,0x0000bd4c28499853}}, {{0x0006e8c06d75fc1f,0x00064249a89f5603,0x00045e7dd2dcf7bb,0x0002a691dd1d3de2,0x0000578dc4cdbd6e}, {0x0008903df2ce7a06,0x00083c39afac4c02,0x0006404abaee3628,0x0008187c847c3114,0x0000304c0d904e97}}, {{0x00036c327d02dccc,0x0001ba68bcc2fb68,0x0005e912d5ad0098,0x000cfd5b24b44c00,0x0000c83d210411fd}, {0x0007ec1666fba0ca,0x0006747546353652,0x0006da9c26994819,0x0002b25cdcb1a855,0x0000593426821a73}}, {{0x0008b33070d3aab6,0x000b3a2cd5e5e4ac,0x000fc91732643672,0x00013ef2eff79b1c,0x000065ca49bf0a7c}, {0x000da59b3efb9983,0x000cd52f13415a8d,0x000f9a5308a5b922,0x0004d77e9ebbab3c,0x00005986e7c256da}}, {{0x0004cbd8088b454e,0x0006ba9e0c8a63ee,0x0002447cbdb7f32f,0x00019ad377d4186b,0x00003e982abb3702}, {0x000c1e4c2a2a5938,0x00048773f24f06cc,0x00085942372c3686,0x000c8f213b4da795,0x0000bbf1d33f5040}}, {{0x00087d0ad886aac2,0x000a9771b64503c1,0x0004045ab5c16878,0x000aed907dfc6fc7,0x0000c6360bf9800c}, {0x0005bb5b9c972a3d,0x000dac9a6dba2429,0x000a79aa6c9e6f88,0x000ac1c0ffbf2492,0x0000e29d50b11c26}}, {{0x000fb68d84d835d2,0x0009661dc1e6b1f0,0x00094f8d7c90caf3,0x000b91f2e5b04675,0x00006897ae285012}, {0x0008a08a4d6755dd,0x000b3991fbdabcf6,0x000bf17e8403ee41,0x000d64a33e343e3b,0x00002c7980e379b3}}, {{0x000cf4fda79e5acb,0x0009d630215f534a,0x00085756e68b83b3,0x000cb1ac748b2ed0,0x0000031725995d37}, {0x000841ac5ccc2c46,0x000add9d50696735,0x0001754bd7d7dc96,0x000dd54147e410fd,0x00005296e953399d}}, {{0x000c9a1deb8568b6,0x000020fb3d321e71,0x000f8fb81a35daea,0x00096a88b6f2662c,0x0000d51afe8f4906}, {0x000ac6e51803a198,0x000f0621908081be,0x0006f463ce3d24b7,0x000ee7f27cfd9ddf,0x0000c6865caf2284}}, {{0x000f169d23233f3a,0x0005d7cb637fe00d,0x000a0cf6c3e32279,0x000bdc7f897c0e1d,0x0000651f5d8d1d6b}, {0x000af191a230c767,0x00025daa5e4add61,0x000abcd7ebd52727,0x0008dc5a753636d0,0x00008bdd37ca70bd}}, {{0x00027c17078c4322,0x000c977fedb7cddb,0x000290570e1961b9,0x000885fedc2f5cc2,0x0000c3fefca39cbd}, {0x0000a36c2af389a8,0x000d3da71ceacf88,0x000aa846396c610f,0x00090a703977a932,0x0000eb776400586d}}, {{0x000b3edf0290a8fd,0x0005fb47c387831a,0x0004efb4fcae8196,0x00010ddad7dece18,0x0000cfc53b417491}, {0x000f23c4cb632f9e,0x0005d91f80676698,0x00084180ac42a1ad,0x00026ed116a81d62,0x0000bedf5f9c9013}}, {{0x0003f0ab2cf89408,0x0007ef948f519163,0x0002653c872b0b17,0x000a04ad28dc3078,0x0000882984a5b903}, {0x0005d0c6a19d2bbd,0x000bb6f782cbb809,0x0009070644b9e7f0,0x00043baaf739882d,0x000012be0ff5b326}}, {{0x000f28b638a7e819,0x000ec980ddc39561,0x0006f247a54155cd,0x00010022db4a96d2,0x0000d774e4ed787d}, {0x0006e2e078637d27,0x000cee0ae06a1a9e,0x000cfa3541c363e2,0x00098d0493483ee9,0x00006843cb3ef74b}}, {{0x000f1bc789a283b1,0x000d780836f40491,0x000e5402d72d3ac3,0x00073d9a1c5ea388,0x0000b192421e5cc4}, {0x00099989dc84cacd,0x000ccc6e75b85c0b,0x000191ce2b0a8482,0x00092f939961d03a,0x0000a3bc8663d837}}, {{0x000c4cdb30cfb3a6,0x00010c9db4c8d7e0,0x000c8d9df6d09b8c,0x00066ce0ba1a4207,0x0000fd495f77c52c}, {0x000169f275264daf,0x0005f57d8362fb0e,0x000ad722280c2b74,0x000c7afdd987f749,0x0000dc229b03398e}}, }, {/* digit=35 [{1,2,3,..,}]*([2^175]*G) */ {{0x000ed8452666a58c,0x000026a9c3c2b0d1,0x0009064084bcb6e0,0x0003ff7c57411c26,0x0000fc20755d3556}, {0x0001c505294dba30,0x00068b7dd31ea08b,0x0001eca74a30ba28,0x0002b9d70ba90e99,0x000094e142ce762c}}, {{0x000783e979f39254,0x000a6f4c89a7b81d,0x0001bf7fa1efd130,0x000a9e125c2144fd,0x0000b2969045b265}, {0x0009634b9db65b69,0x000173599d8aed8e,0x0003563f335c82e3,0x0008ab4aa7a54f40,0x0000df088ad922c3}}, {{0x000b066bb3fd30a1,0x000adff0354ee5cf,0x00024e36c429169d,0x000e1d709cf85235,0x000036f4fb31155b}, {0x000af011fbba712e,0x0003706ba1a14826,0x000aea73e6ef0f0b,0x00044df9928b3177,0x00002bf6af33eaa2}}, {{0x0004f124237b64b8,0x000963ecfd078d08,0x000845dd8688ebe9,0x000324d7b8a70cf6,0x000008fc59cdda4a}, {0x0002b2ba3585862b,0x00053df29386a903,0x0001ec29bb66825d,0x000dc805a5a8db43,0x0000b143a98ea1e8}}, {{0x00094ce12ae381b9,0x000bf6ccda9035ee,0x00006eaca3a7f176,0x0004df363a657e46,0x0000ae5a380d3cd0}, {0x0008d15ed251b464,0x00008aca5e649bec,0x000f20f071f5d6d3,0x000285f47b3b359f,0x0000d65f03537e4b}}, {{0x000ba24f111661eb,0x00040105eb049e93,0x00024b578edced48,0x000068e6dc9ba1f4,0x0000f8f66b8983e9}, {0x0004df4d7ed8216f,0x00069e2cbecf872d,0x000e73754bf07f37,0x0007075281d89998,0x0000ec85fbc7aab8}}, {{0x0000deea5ba5b0b7,0x000dd2d052999a3c,0x000b02d42e6a116c,0x000cb63e9775fee9,0x00002b0520111545}, {0x0006f7d31a3b4ea6,0x00082bbd9b32bc50,0x000b12a97e589307,0x00067168bc5f37e4,0x0000b000c06aa73b}}, {{0x000bf22765fa7d04,0x000fdd6a537013b5,0x00080db9859805be,0x000ce327a5e29d42,0x0000f53916fb76b1}, {0x000f61f33ddf6269,0x000e1085d103714f,0x000809ee34206238,0x000b1c8c50d4b7e5,0x000099f450e15f8e}}, {{0x0006051e4c79e9bf,0x0002d66a9fea658a,0x000be7b231394cb7,0x0008fd37f31ed5c6,0x00004c88f374aa6f}, {0x000721f4aaa499e0,0x0005e3fb2a6b0fb0,0x00092851d68b3a7d,0x000913a788097d3a,0x000060e7f8ae96f4}}, {{0x000be731a3a93bc2,0x0005821adc1a82ee,0x000030efd42bbf46,0x0007bba10b6fa4ef,0x000047aa4c7a7b09}, {0x000c632f60c77da5,0x000a7223523e8b8d,0x0004579cf6ffbc26,0x0000f654f6ff1134,0x0000825653ce8025}}, {{0x000097ebc1aa2b92,0x000317a0333ab2dd,0x000a0db380788939,0x000612fcf55e7137,0x0000648487f992c1}, {0x00013363fcef2614,0x000cceabf129dad0,0x000276be26239c81,0x000ad34ee761de9d,0x000006a7a345eda6}}, {{0x00067ba4a493b31c,0x0001dbf7f0264bf3,0x00095914b54f20a5,0x0006abf696e06297,0x0000ddab96e4bf23}, {0x000c70aed25ea138,0x000b01cbbbe74ff2,0x0008544c5fa1d09e,0x00031708fc8c8746,0x000047a670de96b3}}, {{0x000421e64bcb626e,0x000746dee0b5f133,0x00010346caea638c,0x000ed2f6e7680bb3,0x000006f4098b5d4c}, {0x00014527512a30b9,0x000d5589a59a0996,0x000d0c180f3d867f,0x0004ab9e73254f52,0x0000063d8a3c33c7}}, {{0x000c595d314e7bc2,0x000b267899ededa6,0x0001ed5d32ee7464,0x000612fcef423c0a,0x000017e76ea89cc7}, {0x000ce1fe7cda917f,0x000a9a893f1627cc,0x000c74f6b12d8016,0x000e60ccd6de849f,0x0000a5817e3e3144}}, {{0x00041640821ee4c9,0x00037bc619921f35,0x00072879f1583eab,0x0007b1e490caf61d,0x000098ad9f4876ae}, {0x0001950a41157f70,0x0006e8da3a7e1e18,0x00026b95fa9d7e1e,0x000a10963784eb84,0x0000ee4ed6e542e2}}, {{0x0004cc5ac751e7b7,0x00028d4211bdb79d,0x000de4fc693f9647,0x0000641c72d3d2c8,0x0000b69cbf64f44f}, {0x0000ca2f4bf94e19,0x0008612894e23da9,0x00017d60b1a5325f,0x000b5c7a437f6c79,0x0000be7048726c9c}}, }, {/* digit=36 [{1,2,3,..,}]*([2^180]*G) */ {{0x0009976e1337c262,0x000db73d68e5949c,0x000b768d96faadeb,0x0000697e158614f1,0x00002dfa557bcc4f}, {0x000da17be93c6d61,0x00019504f5b9ccd6,0x000694da124866c6,0x0008c61121353c8d,0x0000c6ca5801140b}}, {{0x0004a7dd4b79bb87,0x000ae2c878c8f160,0x00047b8e8aee806f,0x000053c4144f118d,0x00002edf52c049f9}, {0x000a84e2127015a3,0x00006cb7cef3ebfc,0x0006deec89051d0c,0x000d7456e8fe5829,0x00003b2818871010}}, {{0x00060ed9aed9f40e,0x0000732a8c99bd56,0x000c371ea70ca6ad,0x00009ce4978bfb95,0x00005464d0e50031}, {0x0002fdfd9e535ef8,0x000718c9185b1af3,0x000b42488abf57ea,0x0006fa6d7a741712,0x0000e0296a869728}}, {{0x0009383171b445fe,0x0002a131ad4c0107,0x0003987e89bcf21e,0x000c8eacdfe205c9,0x000063f4153a92e8}, {0x00062a930add43df,0x0002d980f05a7294,0x00006e96862ebb14,0x0006b05f3954e53b,0x0000e1d75ae142cf}}, {{0x000416e1f017d5eb,0x0005c674e99b8b57,0x000f488a03753339,0x00095dbe6d94c0e8,0x000093a787b8c16f}, {0x00051a2dcc99ccc0,0x00039aa47c1dc3ac,0x000dfd8d5c134b41,0x0001edf28fcdafaf,0x0000d57bd8e10b83}}, {{0x000fbccf0bcfc46a,0x000e15cffee69276,0x0005d915b3a822ac,0x00076b928ed2fec7,0x0000145c11463594}, {0x00081538be17bcdc,0x0002ea6c3d8ff61a,0x00016c82f01e867c,0x0009af9634e15d65,0x00001437bd32948b}}, {{0x000d2006c19d4c7d,0x000711b1e976d2fc,0x000f237e8a0f3c43,0x000bb120545ff694,0x0000d10ec4090bf8}, {0x000696cac7cd3e1f,0x000b6f24bfe64f89,0x000af7706ed3714e,0x000c31463eb1d85f,0x0000cbd604eb027c}}, {{0x000c6c7af8685c8b,0x000d7f8f01aa5f95,0x00074692ad4c1c8c,0x000068144bbe3225,0x0000800347984a4a}, {0x000c6e52eca3cdb7,0x000b7c04d3997c8f,0x0002bc5cfea1db16,0x0003d2405bc82e8f,0x000063d518064479}}, {{0x0008eddc355363b4,0x000fb8820d6e16ce,0x00061a5084af2f70,0x0004728b7ed4d276,0x00001d3444f1d195}, {0x000a2b438da9649c,0x0005eeb4a20017fe,0x000b19c3d9bf6935,0x0000a5e13b5f916a,0x00000519c159c936}}, {{0x0001ae92e42e1716,0x00038d41ccf9c257,0x000c8854fcb31ab6,0x0002a0d7f3c576b5,0x00006e5191c26239}, {0x0005a1c6cd5683b8,0x0002e06fe6897156,0x000e2fda6484b028,0x0000a473a25d6767,0x00007ba21df0a65c}}, {{0x000e49ca70684d10,0x000133e80c3dde74,0x000a5c34d3ae8766,0x000c355984a2a916,0x00009a83eccb8298}, {0x000867caa4ca4c09,0x00002375b8ff9a19,0x0000396dc0208561,0x000e636296328bf7,0x0000c9ddc4d6e6fa}}, {{0x000c1b808bd98d05,0x00041575f2404451,0x00075d270644b1cd,0x0006bd1907eb3373,0x00006c8bebe4a228}, {0x000d2acc4632b46f,0x0009bfd60242c713,0x0005c754617da427,0x0003dd413065b7c9,0x00008239899af17a}}, {{0x0003d260b083b6e6,0x000aa6f6a54d9468,0x0002074dd0a3752e,0x000592e8bedc2375,0x000037622fc9e822}, {0x00005136be55d3b0,0x0004324d006dea00,0x000fc02709f5e12f,0x0009e6529486a964,0x00009ba0d0c92339}}, {{0x00058473a9770805,0x0007bc6a6ab63638,0x00082261e4cf8e1b,0x000806419a5c6c04,0x000017a9ad135ce4}, {0x000d40c056aa7aa0,0x000ae56c61b02792,0x000b19e0c4c7c6ad,0x00067ff19cb178a4,0x000046d5c4fe4ba2}}, {{0x00026ab121550b37,0x000a5147ce84d3e9,0x000ff722ae4975e4,0x0002a00a8be0f95e,0x00001e4702cdfd4f}, {0x0002acf3cb7b2807,0x000cb8272d7313b9,0x000a9fe5cc588716,0x000e42162c7bf3da,0x00008c008f352a79}}, {{0x000963f4c8303203,0x0000603203e3f3b7,0x000327afb842c7aa,0x0009b67f22ca0ae7,0x00008e13092c6760}, {0x000fb62757558f1a,0x000157eca8c173b8,0x0003316273cc3e83,0x00023444174474f6,0x000077989cb63c40}}, }, {/* digit=37 [{1,2,3,..,}]*([2^185]*G) */ {{0x00017f4b0166f7a3,0x00079eec74e6ae83,0x000874bfdfbd3e3f,0x0003a3cdb516ace0,0x0000d846019f681f}, {0x000ee5c7c1620b02,0x000d0b63c5010b12,0x00068c51eba68b4d,0x000b5b8c03cd3266,0x0000a6279f76e0bc}}, {{0x000139f8f5fcda83,0x00048dee5bfdfd8e,0x0003f9f77f3e558c,0x000969a76cbaf4e3,0x0000a4c97a4a1771}, {0x000e84bf6dce6a73,0x0005e3e6c2d1da27,0x00059a6e9ff373d9,0x00062cc115193cd7,0x0000f9b702593d22}}, {{0x0006fea87baa6279,0x0001672aa6801253,0x0001e5dc958c1fec,0x0001b8dc29b63760,0x0000e3c3c1d6e9e0}, {0x000127b2bcfe0b0f,0x00013a12f50defc8,0x00079b3973510710,0x000f207ccd6cb148,0x0000792f805e8a82}}, {{0x00084911a335cc88,0x0009ea5913e48c31,0x000b32919563459b,0x0005ac9b920d61c7,0x000005ab8b720242}, {0x00012da8d006086c,0x0009fcf5c0fd2ac5,0x0002138d76ca4846,0x000442efea51d8ac,0x0000b647545f44cd}}, {{0x000f521e447f2c48,0x0009e04291f0a3f4,0x0005926de81b8da7,0x00002f5680bc467d,0x00004f21fd5b4a12}, {0x00031814e9df3d85,0x0009e9ab8d341d1e,0x00019aa4a1ca4861,0x000366309ddeec5b,0x00009f72f7e9d329}}, {{0x0002466cdedca850,0x00001a09538c9f1b,0x00011115d140bb71,0x00059eac8ae8515e,0x0000d63ff676f03f}, {0x00055517d234afbb,0x000dce208fc1755e,0x0008a4b5d61c2db4,0x00030efa9859cef2,0x0000dd6d4fce4af0}}, {{0x000e67f906151e50,0x000f55e106493f39,0x0007cf7b7cea27f5,0x00062ddca1d4e1c1,0x0000c326d122fe23}, {0x000ac337dd35df39,0x00093396dbdf05f7,0x000b7db1c0c3b763,0x0004a87912f5ac03,0x0000dea4b70ec9ed}}, {{0x00053e453544774f,0x000b4adba2bc5110,0x000e371f5834d0ec,0x0003bb5215d7f7ba,0x0000cfd57c05c866}, {0x000383dd6901b1d3,0x000485587dc3ded2,0x000625f623b49fbb,0x000762cd44a08d07,0x0000ee4d65bcde9b}}, {{0x000fe5bdf53aad08,0x000564604a673e56,0x000a261a051314de,0x000c90b86ad98607,0x0000b7e021297afc}, {0x00011273b72aec51,0x0005b4f9f509cbf4,0x000484b5713c85d0,0x00095bdda56845b6,0x00003cb1642c3d09}}, {{0x0004b6e717815de8,0x000027e131d15a99,0x000c023aad995c7a,0x000ced48b46df226,0x0000cfd094df02af}, {0x00043cdced6a8867,0x0003afcabe757bc7,0x000ac9390b7d70ec,0x000a8fba6c9e47dd,0x000020694260310a}}, {{0x000b3263e8f793c6,0x000e6de3b289a607,0x000915b21a541166,0x000da6944ff2924a,0x00008bea907158ec}, {0x00037b4402928970,0x000e4b768423d85b,0x00013bbbed2a508a,0x0001f4d10bb79da4,0x0000262f48106149}}, {{0x00080f55464d0ebe,0x000687a613a7d17e,0x000c97dad89d3e1a,0x000be697791260c8,0x0000c2ff220c4f0c}, {0x0004ac2e9e6bc105,0x000827cba305ed98,0x000624fdce3c53de,0x0000ec4bbaf9b283,0x0000e9451cd6485c}}, {{0x0009f63b7abad118,0x0001e3a46189fdfc,0x0007037b7c7ec3a9,0x00070fc9ebee42f6,0x0000247f5054dac1}, {0x0008f8d397583e59,0x00067c3f8c2efc51,0x0005edcb1e7d24de,0x000efba54832669c,0x00004bba48488c2c}}, {{0x000756db1761ec84,0x000864b97e551f13,0x00096cc28e53c8b9,0x000a8d72aee3f840,0x00008c361a0d20f1}, {0x000672d8c31190a9,0x0000701855d4a98b,0x0003f4b2a7bc1e7d,0x000bc3942cfb07bf,0x0000bf44a3fc2a28}}, {{0x000976299da550cc,0x000956baa042eba8,0x0008c2f9db2c1781,0x000a9d7068b08278,0x00000fa414654869}, {0x0009e39d50b693f4,0x000c588e2c5e73bd,0x0008f9f62b79e2a9,0x000c7bb1cb8de40f,0x000015b04ee5ea50}}, {{0x000137d0d63d1fae,0x000122a9d89f64e5,0x000436309658fc05,0x000a606889487450,0x00009ae30f9b598d}, {0x00010d1818baf918,0x00060b6a0c202ed7,0x0001a6b44e27e9e0,0x0007db9e28dcfb1c,0x000083acb6556ac5}}, }, {/* digit=38 [{1,2,3,..,}]*([2^190]*G) */ {{0x000728dc2c6ff707,0x000f55dc22358735,0x000e277f979d6122,0x000cc6b3f5d00319,0x0000ee84e264ded8}, {0x000afb063cd880a6,0x0005d574af6091a8,0x000de7f423f3ea7c,0x000151acfcdc8402,0x00002d07930131aa}}, {{0x00083f9dec31a21e,0x00028ad9d573b02c,0x0007be365988c8b2,0x00034d73e983aea5,0x0000968734e446f8}, {0x000ea8f5da6309bd,0x0003f1f1ce169137,0x00044092110f3a62,0x0001b4a82a9ea2ca,0x0000f94739f2b46f}}, {{0x00065a434a35ea84,0x00070d4412f61df1,0x0008836c33418e0f,0x0009651af1f8af51,0x00002ceef4d530e1}, {0x000ca0b543a1957f,0x0004986cb1235560,0x00098ed30c33761e,0x00097c76624b1ffe,0x0000772f4c000909}}, {{0x000410ef4f8b16a8,0x000e447b266a56f8,0x0009c87c197241af,0x000b1a8a406b8e6d,0x000003f3e034d42a}, {0x00009a804dbec69c,0x00067bbad05f7f03,0x0008e197fa83b85f,0x000dc106097273ad,0x0000097440f1067a}}, {{0x000b6dd418e7ddd1,0x0003372f19d6c507,0x00027eb4d39888d9,0x0008846eae26be0c,0x00007b53ed40babb}, {0x000021b2b01ae4fe,0x0006ef488682fc27,0x0005e2d8788462e8,0x00029adee096ec21,0x0000b2fea9bb242e}}, {{0x00000c756b95bce4,0x0006216da680bbcc,0x0002142525ec0390,0x0002d239162ee672,0x00003132b63c6a89}, {0x0003ff22f3263bf6,0x000c3cd0a1424bdd,0x000415ccbd5b3733,0x0004e9f92eaa8244,0x000063e8924ed547}}, {{0x000ab35ce7c42d4d,0x000eb2feab100d38,0x000111b459fd493e,0x0005c276056b6d82,0x0000a11dae243efc}, {0x00002785545a7fb2,0x000c20d507e6dc74,0x00066fa58bdb2601,0x000c29f21dfeeb70,0x000014369a859ae8}}, {{0x0007fa0b311898c7,0x00045d0eac653f74,0x00014d0bce2a272e,0x000ee2dbba5851f9,0x0000a1a966134a43}, {0x00067cea1c8cde9a,0x0008d271abe3e5a3,0x0001615cd9d958ba,0x0000b053ff7eb63d,0x00002280dcf95ae2}}, {{0x000d566d4312483b,0x000cb43e216f8c0e,0x0000444935179a95,0x000a211c185fec17,0x0000306333a04991}, {0x000ecdb0081a726e,0x00056fa89bbbd801,0x00091b6b90149b0c,0x0003a2cfe9065a43,0x0000dc92787b633f}}, {{0x000d9e37a6a308bd,0x000f7c2767d3d6d9,0x0008cbeb66237582,0x000d9db74a8bc6f3,0x000094d3f1b9cb6f}, {0x000735bba21f248e,0x00048cd1efb092a9,0x000b03284272ad0e,0x0002249437b69c05,0x00007f047034948c}}, {{0x00068a9e9adfe1c3,0x000d014e39bb9ae8,0x000fe378f3984403,0x00062885875720f2,0x00003f901e0ea44a}, {0x00025fe3652438c6,0x00063dd1f20bea11,0x000bf7fbdae9ec4e,0x00079bbe740d9ebe,0x0000dbd3ddca2dbe}}, {{0x00044a43794f8dcb,0x0009983c5c362663,0x0009d10a0dcca923,0x000df27d6b6bbf3f,0x0000320c5cb31d9b}, {0x00028ff47b50a951,0x0001bef03371620e,0x000100153933e3b0,0x0008d6e081bf8599,0x000083be9a0d3a8c}}, {{0x00043d77613aa81f,0x000f95fe65848a94,0x000b10288801007f,0x000ee780fc4dbc7f,0x000058280d4d86be}, {0x000d82f7c978c385,0x0000bde44d7b14fd,0x00060252fdf1204c,0x0006a5508a1c8441,0x000091554cb11764}}, {{0x00081ea77b46a081,0x0007b74806997ddc,0x00033f683cf5a647,0x000c6033a8cb3466,0x0000b867e6ba2363}, {0x00011141f60558ee,0x00024f41450e4392,0x000630e8bcdbcdd6,0x000b429fc04601cc,0x0000a7c66d677038}}, {{0x0008820fbeee3f97,0x000fd9091afd34fc,0x00031f35c93e5348,0x000924064b9be59a,0x00001f37864c7e3d}, {0x00034e0943aa75e5,0x00085b8ff6e402fb,0x000cf0d19a18c9c5,0x0008a6b80f31b133,0x0000c9682db58351}}, {{0x00085c341dca5663,0x000aa8622aa3b6c1,0x0001b6dfb7de7fed,0x00028869e84d9290,0x00000a02b0eac4ad}, {0x0001daa2fd3cf36d,0x00070f89e59fc7c8,0x000496733d131954,0x00012ae2be8184cd,0x00005f449ec63d34}}, }, {/* digit=39 [{1,2,3,..,}]*([2^195]*G) */ {{0x000ec644cd8f64c3,0x000ff79d7b51c492,0x000c7525658a2d78,0x000016dced1fc51f,0x0000e658aedbf433}, {0x000942e05da59eb6,0x0002addc37220b61,0x0002e7f87ba3d60a,0x000b6e1c311cd174,0x0000473ffef56b01}}, {{0x000604f692ac542f,0x0000327b91d38303,0x000aaf9bdf079ffe,0x0004fa29f63e6315,0x000099ee566e1f34}, {0x000661fd62191997,0x0006648ce41c8a1d,0x00074d9048c883bc,0x000b1aa065118f3c,0x000013889ee7faf8}}, {{0x000f697960eb8c77,0x000c72de04d3c035,0x000ad9228f1599f2,0x0001ab192450f8d2,0x0000d48129c2829c}, {0x00085e13a50afc95,0x000713a96ee024d7,0x000fb6d7b2745ba2,0x000a42456534013b,0x000036202676bad2}}, {{0x0003f8f81a1b3bed,0x0004fe2764a0972b,0x000c4f5f74f3ce14,0x00085b12d0f1cc28,0x0000eee0c0e97f39}, {0x000adc0d39e25c35,0x00007467a0807df4,0x000cf5a584061982,0x0005fff40ebc9361,0x000027729a6922ad}}, {{0x000398a4a9eb3f0a,0x000e9b99a48fa691,0x0004b5b3256c1dbf,0x0005fdfa87e1b91b,0x0000d639614f378b}, {0x000243ec26b53020,0x000c3ccb4c10437a,0x000e070150275878,0x0003c00e81e4a21d,0x0000c6265c9850df}}, {{0x0000937b1b76ba6f,0x00045d2026dcca6c,0x000d9ae0a1a2eab8,0x000025c1715e1519,0x00001ad919aaac4a}, {0x000dfb807ea7b0ef,0x000e4ed9eb8935b3,0x0006d08abedf5496,0x0007309932e5ff2d,0x0000314874f15bd2}}, {{0x0007149a8c25ff63,0x0006482e6569c832,0x00068fc3829bf255,0x000ad56012f5c6cd,0x0000e67e8bd6b982}, {0x00075386ecdca88a,0x000621753a045e3a,0x000db3256f297eaa,0x00005470121e5405,0x0000b9697d590851}}, {{0x0006a753f73f449b,0x0007dd44fc79efb2,0x000c0dc4d1d1c94f,0x0000cf99f0fbc53b,0x0000747ea0be698a}, {0x000c3fe228d291e6,0x0004e3c129d65218,0x000acc51635b804b,0x0006689ac859b8d1,0x0000c10697df5d6e}}, {{0x0007171f6bdf1bf4,0x0006bacb0d8fe5d2,0x00096a31b0b77b87,0x0001039a95471d84,0x00006a50dbb7f16b}, {0x0003f977b865bff3,0x00063b1c198c2a4f,0x000702ea6848195e,0x000228191ad08821,0x0000f20b43779035}}, {{0x000438f0876fd4e6,0x000723d2f383c38e,0x0000934cb45f0c30,0x0006edc03cc2ecb1,0x0000a8f24398c9d4}, {0x000431b65ccde7b6,0x0007c7e76a6ff16b,0x0003484d741e2cd1,0x00044a59c8cf8f4e,0x00004426efde3152}}, {{0x00098093a69fc01b,0x000b4aa9dfc2e6ec,0x0006f2a557e20fec,0x000fdeacfdbb07f5,0x00001cd6868bbbdb}, {0x0004995986eb9ed8,0x0004bdd0955e247b,0x000c7a20174785bf,0x00080d08f74f61c0,0x0000861a15bdd01a}}, {{0x0008e44fc94dea3f,0x000eead6a0b01c0a,0x000113cef34c8cdb,0x000ff9a19c384004,0x0000d32fba505490}, {0x00090f6795dcfb75,0x000333588baf58d1,0x0001fc1c0fef01b0,0x000ac94e6d1d63ca,0x00003173f9740a41}}, {{0x0007e4182997cc14,0x000ca3720c9c5463,0x000de5d4508c5a96,0x00075a38bce01c11,0x00009d623e54dfdd}, {0x000a4680fb2a3acc,0x000e719c25af8c72,0x000a92421cc53bbf,0x000cf2598eba7978,0x0000d61f28c63bde}}, {{0x000402aba16f73bc,0x0003ccf9b9fc2b1d,0x0006ef7bf2fb3101,0x0007446d51e60e44,0x0000731021c791e1}, {0x00047244fee99d47,0x00068ac5c1ea9d3b,0x000ea9af74bca48b,0x00083a00f5f514bb,0x000051f55a6074c2}}, {{0x0009fe8662595c2b,0x000661a807732389,0x000d1d43b495d672,0x00065ed6c971d2b0,0x0000518637d43b7a}, {0x00053bad98c99cec,0x000954d39f5b30e4,0x0001ce415ba6e0d4,0x00082337db02a643,0x0000d909c7db6e1d}}, {{0x000251acb452fdbb,0x0004a0f306506e30,0x0003548d931ee696,0x000f5b00b3e50893,0x00008949a50a4b0e}, {0x00083263c88f3bd1,0x0000cb1d9989208b,0x000d4df03ab147c3,0x0000c5dd6515fd44,0x00007a12f75f72eb}}, }, {/* digit=40 [{1,2,3,..,}]*([2^200]*G) */ {{0x0004f7881fdad909,0x00057d2cf6ab2591,0x000054de5cf638f5,0x000350290bc03fcc,0x000032811a7a8b06}, {0x000b3309bbd11ff0,0x000fb40449742f00,0x00051d26676108a6,0x0000c1801bb9e0a8,0x0000dd099bebf899}}, {{0x000dd8a58d6cd461,0x00057e6634d214c6,0x0001bc3289cb633b,0x0007e5b1305047f8,0x00002ede0e236a17}, {0x000ca62065a6f4f9,0x000cd7be487b332c,0x00047ed1cc3a47ec,0x000b13e41eb1870f,0x00009e66e5977598}}, {{0x000a6777b0ac93d1,0x000d68f5e0d7ebd6,0x000f5492ba6e37b0,0x000f3a1516c09676,0x0000e4bf888aac05}, {0x0002ce04df0ba2b4,0x000d1062341bcdb4,0x000acac20935d5cf,0x00000e4a30333382,0x000029438c49198b}}, {{0x00038be67e573e06,0x0008e084c44bfb28,0x000c1c2c505891db,0x00044b3131137396,0x0000aebfa4039584}, {0x000dce9e56e55c19,0x00029caa46d0ac9c,0x0001fe8eb7148ced,0x000f4c9e10c7efb6,0x0000fd835db8f97c}}, {{0x0006f56c17706169,0x000d79da9a2d6c62,0x000730e455351909,0x000a79558e6825a3,0x0000d8c8bc093ef0}, {0x00078b6056becfd1,0x00039090b36d543f,0x0004432f933f1325,0x00050272ad499779,0x0000386493c5721f}}, {{0x000eefa5abea82a6,0x000933fe62d43794,0x0001ef6068dc611b,0x000e6909f1af3728,0x0000af546c899839}, {0x00078c7c977ec238,0x000c3d5c05766255,0x000d1a4c0a8de294,0x0004d462ddaf0f7c,0x0000243fc70cf95f}}, {{0x000f400b008733a5,0x000d012e1f57e566,0x000509cd0cba0697,0x000d8c4537c2b240,0x0000f989c69a7353}, {0x000c9724c3c2b2fb,0x00084f031fa87dbe,0x000d5d11f90e02fa,0x000dfc44d15c53cf,0x00003404faef8314}}, {{0x000a109081e9387c,0x0006cc935828a36d,0x00040b015fb9780d,0x0006fa15940332e5,0x00009d7b51ca0f46}, {0x000cd41d6d9f6711,0x0008a1a2ac17faad,0x000201e5fba6c1e2,0x00062af66a7833ed,0x00009d9971a090f4}}, {{0x000c3a9f327a07f6,0x000ae490937df02c,0x000b3afa5efb27a9,0x000be421451e96b1,0x00007e24de8f1883}, {0x0005d4770869e549,0x0003d4a3856a1ad6,0x00032e880d36291a,0x000fde770a1abf71,0x0000511d0a39e28d}}, {{0x000d650f8d1cac45,0x000b1d16bda5fdee,0x000abbe46eb99194,0x00076c653b19f71c,0x0000f45af5089b92}, {0x0004c6126ee9d77a,0x000a6c02ca5dd078,0x00032e720f7a1558,0x0003f7161d6c59f0,0x0000e3ffb95e70cf}}, {{0x0005facc72a4be52,0x00062d8480899b18,0x0007afea9f66de23,0x000c1c9a14d07c71,0x00005bfbfc04d551}, {0x0000ecd4cdf3d880,0x0003647f73c42cef,0x0002d67f78cee2aa,0x000a21c10a7d3d72,0x000090037a294564}}, {{0x0007987fa9ced27b,0x00037a9e5dbce656,0x0000d8e8c36b2d88,0x0000d044bdeec638,0x00005e6a6b18bc30}, {0x000e9b9592bef367,0x000f7e81b7497ba7,0x000ce596b2b373c4,0x0004cbd84b5e01f0,0x0000cc51c6330bf5}}, {{0x0007bb84f3815c4e,0x00033aa9017e6ac0,0x00085720addb9f62,0x00083751e30228ca,0x000059d63f65cb75}, {0x0008e777baad2d02,0x0004b42f5d7369e1,0x0007749832cfdb78,0x000d51e25dd53df5,0x0000f80e7cf0042c}}, {{0x0006bafec695bb00,0x0008f13c78ad4bf5,0x00082abb022da1ca,0x00049e0f9c4b1311,0x00002ea555aae7d2}, {0x00083f25e05d9e30,0x000f70382afa8685,0x000080408e09cdcd,0x000658df072ec787,0x0000a317847cbf75}}, {{0x0008d7f4d6ee4ab7,0x000e2570c3dc43f1,0x0008c9b2ad3ac8cd,0x0000f0e27e49070b,0x000016709a835a4c}, {0x00052b0916a26b1e,0x000e6e0711779308,0x0006948683cc17fc,0x00055c54f5e3d459,0x0000e0341ac828f6}}, {{0x000f462060b5f619,0x0003ebd057c2f431,0x000e1bf65a56f46b,0x0001fea48dca6c47,0x0000a38783ed1bcf}, {0x00033a9da710718f,0x00063e0aeaf67a5d,0x00029d1875a77998,0x000732da87314d2d,0x0000a0edc3fb687d}}, }, {/* digit=41 [{1,2,3,..,}]*([2^205]*G) */ {{0x0004849cb198ac73,0x000cdf2646651c89,0x000200678a884a93,0x0004e5fda964ef9b,0x0000c351b8730983}, {0x000ef9fe2c4b44b8,0x0006b326790cafb2,0x00002264a580f6c4,0x0004e2384805210b,0x0000ba6f9e2c2a19}}, {{0x00034abd3c095f18,0x000e64b76d7139d9,0x0003e698404b261b,0x000b109d2e6970e7,0x000079fb23bde5fc}, {0x0006c72dfd754907,0x0004f1bcf1c11150,0x0005e70073a97d08,0x0002a6d3201d82bf,0x0000f0ac52fe9823}}, {{0x00001fb319d76820,0x00090a982feeb251,0x00061b344b029312,0x0001fa51c1c9b902,0x0000e008c5bbfd37}, {0x000dd1c0278ca331,0x0006d5aa53b1d866,0x00013a2cf666f76a,0x000836d5cfb77960,0x0000d3a1aadb3521}}, {{0x000131a567193ec5,0x000a95f6e70b76b4,0x0001eebddaf3c305,0x0008314587bd3903,0x0000709def8c1bbe}, {0x00099830eb2b6692,0x000b675b70295705,0x00064ac164d80ce1,0x0003ab638a7da803,0x0000f431d23de1c8}}, {{0x000276638235d4e4,0x0007096e3298e781,0x000175bc81c62bd6,0x000d4d4378660c3f,0x0000d04e18957afd}, {0x000160185a8068c5,0x000142b29a8532a8,0x0000d8a3bdb58e4e,0x00003b98a65b86c7,0x0000f0e6f4ee8a04}}, {{0x00092b73f894ae03,0x0005875f18ce2c24,0x00053cad0f59df3e,0x0002944cb740d28f,0x0000eb585fbf4f01}, {0x0000c8632c7f717e,0x000acf943f4c17da,0x0007c51d2eb8c795,0x0009486ee23fb5f6,0x0000f18757648889}}, {{0x00011a4e822f0d08,0x0000da8704f83ea0,0x000c6820fbc647ad,0x000bec3b315b3550,0x000063dec3e37e76}, {0x0005d3af017bfc7f,0x0008a76b822901ff,0x000bd0d3b2005443,0x000d0e167fca370b,0x000063dde656f5e3}}, {{0x000bc15adf7cccff,0x0005efa1e1b075d9,0x0009bc17e81a3e5d,0x000d429c39e44424,0x000037dccb37ea7f}, {0x0004873907fba12d,0x00097a372904da65,0x00083a6c535daa6d,0x0005be3564cfc662,0x000009fa4f71a939}}, {{0x000b3b56aa39dff0,0x00029f8e4d8cb510,0x0004c4b9f59b43da,0x000c01a8ce31fd9e,0x0000e20be26c1303}, {0x0007182e8ee47c94,0x000b3db981011818,0x000e14ff6d9687cd,0x0005723a520e4da1,0x000029808bac836d}}, {{0x00046996d16768e9,0x0009d28bf217174d,0x0004e490d9fc4ff6,0x000979e7705a9415,0x0000d96dd291d2d9}, {0x000d9d8ce5d72c41,0x0004b11c714f77e2,0x000e4a03e9d06c5a,0x00028af2aa513679,0x0000386b3c2130ff}}, {{0x0002d69ea40dc3a4,0x00026ecc018f26a4,0x00070f04adc84ad2,0x0002ece5c36c7b32,0x00006ba6d4790fa7}, {0x000d1c593e58a8e2,0x0000f20c088c6c37,0x0006e86daa239473,0x000038a3be4263cb,0x0000c417d369126d}}, {{0x00023bb440e22296,0x000213ef4d04cca5,0x00011ec39324673a,0x0008d34f3adf343e,0x0000136d7f23c596}, {0x0002899b053a9270,0x0001ae067ecd7a7b,0x000779cd93eaa266,0x0005ea8549b9c802,0x000061d7940c5338}}, {{0x00041fcaaa2902bc,0x000924f69ad3e071,0x0003f9ffd539ad79,0x0002f6e6453f9481,0x000058d3c48f75bc}, {0x0006fad5dc64e964,0x00097240e354b332,0x000a1e7a93aafcaa,0x00089fdd1b0903ac,0x0000ceb97675211b}}, {{0x000de4687032d585,0x00030e2c79e01eb4,0x00004ef23c54f3d8,0x0001b3b7818df45d,0x00005faa9c8b73d4}, {0x0004f6f89b95355d,0x0009e7415c84ced6,0x0000ebad34860d2e,0x0005be8fdb9bd205,0x0000b53e0cd3685a}}, {{0x000ca5fabfae1ca1,0x000c0a21459b919f,0x00066a4d2937afaa,0x0003318e0ca91c1f,0x000094cc7f333ec1}, {0x000143a8aa116906,0x000ca9b59e08ad25,0x00050860abe40ad8,0x00034bd7d60d9be7,0x0000c53b00926bf4}}, {{0x0007080eb6b242d6,0x0002db71e246832d,0x00031139dd30bd02,0x000e531027991bbe,0x00008797e91a62e4}, {0x000e20a6b4e185ab,0x000d92d9b707423f,0x000f7811b82f2c67,0x00095c75c817684c,0x0000d53005eb45bb}}, }, {/* digit=42 [{1,2,3,..,}]*([2^210]*G) */ {{0x00049be9d8e68fd9,0x00028b044320e5f6,0x000c33398db0f053,0x000fae66fde9b3e0,0x00002f4209bf6c8c}, {0x000afcc1a739d4b6,0x000f428ab8dee9d1,0x000c6f1d009aea75,0x000aa4b4375fb5ea,0x0000420b560d08f7}}, {{0x000499c6254dc41f,0x00038a837e7e9eae,0x0000524a77e29392,0x0005f184aec08c09,0x000082b921a7d6f5}, {0x000962e1402cec5e,0x00071a2f30e7493c,0x000b879cb9f17ca1,0x00045edcd783e8e9,0x0000a3d8c153a6f1}}, {{0x00015e75e0dee6e5,0x00028c628aa2dede,0x00061bb9374f2487,0x0002e083e9c4fe78,0x00006d4822ab187b}, {0x00017cfc59826f90,0x00092408169eb664,0x0009ef885ca26096,0x00038fedf69d06c7,0x00000031f8adc7d1}}, {{0x00046e60ebcf7262,0x00014231470e103c,0x0007c21094482b83,0x0006ef4f6dfaca48,0x0000e0ace9782e66}, {0x000a9d31f8d1f420,0x0001574944d23246,0x0007f334b1b1e83f,0x000d8113dfa63aa5,0x0000cf8daed9f025}}, {{0x0008ea800ee11c1c,0x0003f5e3dd7530d7,0x0008c43c5eb053cd,0x000662db65b13ed5,0x00003ad49be7d151}, {0x0008e41b64279905,0x000d207eae1e99fd,0x000abb71e12cf15b,0x000d0dd9ad4f1b1a,0x0000143e74d57545}}, {{0x0006336c88bdee1c,0x00059876767c3026,0x00073199625f2930,0x000950dc078571c6,0x000088690b3ad552}, {0x0002c2d852705b44,0x00040e09552d274f,0x0006575d1b0bf8d4,0x0006513628beeb98,0x000007be238bf864}}, {{0x0003049a639fc6b8,0x0009060036250e5e,0x000cc1646e75c35d,0x0007398cf35bd85d,0x0000bcaced2ec262}, {0x000cf1db55367425,0x0006ca9e068be22e,0x0007909c5013dd89,0x000505c7f411cb8a,0x0000757ac98d61dd}}, {{0x0001f0d1e935abb5,0x0003c54de37a85de,0x0009cebb5defd10b,0x0004be68d9e39236,0x00004d5ef9bc6132}, {0x00041ba74f17e266,0x000818c1dde44d63,0x000d918fdc0a0e3c,0x000a1346d7758187,0x0000687601562ca3}}, {{0x0003e9cf36658f0c,0x000bb1f8057ec731,0x0006a835ac433ef1,0x00094bc53262461b,0x00008f053993c863}, {0x0008cdfe983c4a11,0x0001f3b7b931ff39,0x000b9045bbf5e816,0x00046b83193c46b7,0x0000e4ebf5db4a6e}}, {{0x0002a6043a24fe7c,0x000e3fb3492bf994,0x0002fde0529c1191,0x00032cdf66244990,0x0000792a7ad2713c}, {0x0008ad8b737982c6,0x0009421e60e32fd8,0x00083591a7e3a031,0x000455a9b0de4473,0x0000df141eee310a}}, {{0x000a039e6d6f4714,0x000ed198d12eaec1,0x000eee5ac14b2ba0,0x0004ceabc1a1603a,0x000001f483720b96}, {0x00037964fd03f663,0x0009ad8f3f122ee4,0x000380f183fdb4e4,0x000d163ef267f629,0x0000e8e9670bda64}}, {{0x000180c207674f17,0x0006c3ae8fdbbc19,0x000aeb71e112e09a,0x0001c7296675546a,0x00009432af25101b}, {0x000558fde2ddec64,0x000f1357753fd5eb,0x000e1158a81392d1,0x00099167a76b973a,0x000016fbbff8a899}}, {{0x000fdfd0d4a9dcf2,0x0008744ddf129e65,0x0008568667bc29e4,0x000fe29c1a92d93c,0x000073c69058e98d}, {0x000e418cdfaa6b88,0x0002d061c69f69fc,0x000f75e27606bd82,0x000a1ec2d495a06a,0x0000ed3d505ed873}}, {{0x00028416ab25b6a0,0x00072b1a4523af55,0x000c99e03c6c0ffc,0x00091bab18827b21,0x000060e864890346}, {0x000f90f93c7f3988,0x000b02f8d10b5207,0x000d0f9e39f4a96c,0x0004f55d71cd793a,0x00004f435d37c3a5}}, {{0x000c55b8e33787f1,0x0005963846734b03,0x00051b9f0ef42f97,0x0007c2ef7304f750,0x00008aca1dc841c8}, {0x00020a72d4bfe80d,0x000c353e732c56f1,0x00037ca16fd823b3,0x00096a41bccfe475,0x0000f6c9c74eb5a9}}, {{0x00032c7904fc3fa4,0x000587e3636aee73,0x00091d9aa14a23f4,0x000540838659c3f0,0x0000a995e5df12d8}, {0x0003becf3a5598a7,0x000741eaa99520a5,0x00004e03c56534b1,0x0002682ed3dca4bf,0x000016c563b48d56}}, }, {/* digit=43 [{1,2,3,..,}]*([2^215]*G) */ {{0x000dea7e0f222c2d,0x000ba2e651425043,0x00016cd30309d42a,0x000eebc4fe9ddd92,0x00006539c7ddf87f}, {0x000a57c432ac7d72,0x0000127fda1003c5,0x0000698de72692cf,0x0003b1cc28c85f28,0x0000331fb469ec28}}, {{0x0008eeae457a4773,0x000bbe6ddc05a015,0x000c41671d19857d,0x000d588326522418,0x0000ffdfc7e6c2c0}, {0x000525426ee7cda3,0x0009af02c3a83a3a,0x0003bbfc8341b086,0x0006917023bf4272,0x0000d15002a44452}}, {{0x000b2f687500b96e,0x00064dcd9425c961,0x000615433795510e,0x0000282308172978,0x00005d0145545445}, {0x0003302bf690cbe3,0x0001431eca675bd1,0x0008038a444e4883,0x000f0243306bc72b,0x000051d151eef57b}}, {{0x000324c85edfa308,0x000407d4f3da5ef7,0x000b50c862597655,0x00096bb52f5bc0dc,0x0000f6927b0c832a}, {0x000e1ba55f2f94c5,0x0008e44b45fad08e,0x000aa455d6a996f9,0x0001f79133cb8da8,0x0000d0721ecc58dc}}, {{0x0004e1f9a8764417,0x0003a47a818df3d4,0x00003edde82bc0c1,0x00025fc3ddc11706,0x00007163f2e7a25f}, {0x00002caa3bfaa53f,0x0001f2256982b54c,0x0006f37dcbd1b250,0x0004a4d4e1728c1a,0x0000e36c214714c9}}, {{0x000e7e9262a35393,0x000d3670d59ef3ca,0x000c5e1b978a49d1,0x000c1c07de0f63c1,0x0000072c30c99cb7}, {0x0008a5277c850e61,0x000f0f6a3de61d27,0x0002ca7ad84f15f8,0x0004b836a8bb4559,0x0000912e3eef4d42}}, {{0x000e2d490e317342,0x00065fca007cc1ff,0x0003f77e891b1f12,0x000c883459b1d0ae,0x000062b051d66425}, {0x0008f765c51e2741,0x0002204e6146cf5c,0x0004046b5997481e,0x0006bd5fc1198bd8,0x0000cb0a6bbf7f7a}}, {{0x000a92079e5fb67e,0x000a90aa725e6ba7,0x000f5d837e1331fe,0x000e207080ccf57d,0x00004cae01e5ff72}, {0x0003ee60412a77db,0x000c2f449025d924,0x000ef5a3106ff7ca,0x0007a80e75f7cd23,0x0000c957822bddef}}, {{0x0007ad11b7f30b08,0x0005b629dcf9c473,0x0006ae160525ab2c,0x0006e0163f4cc118,0x00005076713f3e6b}, {0x0003180f6998bcf4,0x000371c8d8d8d9be,0x0008c005493d91da,0x000768b902ce661b,0x00007e7924db4a8a}}, {{0x0008086365e668b9,0x000a1abda5fbdc98,0x0005f1fbeada8dcd,0x000fc32c146b4c25,0x0000cfcde2a5f34c}, {0x000453e7e85d1e48,0x0009792358b5acbb,0x0000823ff9ca0967,0x00011d95fc2d9624,0x0000d65adf78c11d}}, {{0x000fd177e19a46f4,0x000746161156323c,0x0007d33630948a7a,0x00079d10d06b977e,0x00001c47ec1e7025}, {0x000998e59e9260b4,0x000406c242609455,0x000bc3744c865e44,0x000149f93021ec13,0x0000981994f0d92a}}, {{0x000230cb0ce1c552,0x0004ebbfb6078cf7,0x00016363b5b534d0,0x000e82ce1ef1130e,0x00007e0aa7ad4999}, {0x000ac2d79362c410,0x000091bb6cb0ce1d,0x00023df2467920c9,0x000f281e648d6322,0x0000f7d9eefe32e8}}, {{0x000f264d66f51c09,0x000acd9ccea59766,0x00021e232644317a,0x000737139b37bcd7,0x00008bdde0c49daf}, {0x000c758165166bd1,0x000592802108c2ec,0x0007aa66f0951a28,0x000a27d39fbf2499,0x0000a2f6862eb62d}}, {{0x00057f10296f4fd3,0x0003ba51b4367755,0x0009508051dca76a,0x0007f1c3e98f60fb,0x00001ff32eab31cf}, {0x0007bf18d2c714bf,0x00083e9d2aca643e,0x000dc2d2364b5c33,0x000b9ab9fd9ccc6a,0x0000c2397edbc721}}, {{0x0001fc764465367b,0x00047b098f57ab65,0x00082376fe438701,0x0009285a91d519d3,0x00005afdb0b03cad}, {0x0001875138d55231,0x000e0aecacfb457e,0x000484f49a92beca,0x000c2af762f6e811,0x000014b5c86eda16}}, {{0x000f39afa8338349,0x0002163285626943,0x00070fc102295172,0x000e6cf1d63dd541,0x0000f5fa5903ecc2}, {0x0008725e77d9a3b0,0x000a6384ebe0b66c,0x00045e24a11235ce,0x0003b106a8c11858,0x0000137b286ebd09}}, }, {/* digit=44 [{1,2,3,..,}]*([2^220]*G) */ {{0x0007d6ac42bd6d29,0x00082b1f96aedb56,0x00043b28e6df8646,0x00023f7efe5b1a48,0x000061bbb05f379b}, {0x000f5f070a6a26b8,0x000cb28e6e39b6ca,0x0005fc8d370686c0,0x000dc900da06cf89,0x000004d88113363f}}, {{0x0009ce74462007dd,0x00047cb5f5b763b9,0x0005edde7b8ab48a,0x000fd9cec673d2f5,0x00001567f755cfae}, {0x0001b6b0887bcec5,0x000e9178f3c24638,0x0006266cb694497c,0x0004130e6525e31e,0x0000931de26b97d6}}, {{0x0009da11f17a34c7,0x0008b35a145614e4,0x00050363b5420ab3,0x000b6e476372412f,0x0000b15d62433fab}, {0x00040b1e274e49c4,0x000456b1860aa0ef,0x000afe5a45cf5074,0x000e9a96583fbf66,0x00004240511347e3}}, {{0x00055021a93507a4,0x00074d3c06cf142b,0x000ec3f40b4cd118,0x0003c29f70e76a91,0x000084e81ad8e755}, {0x00087b5272e9d6ec,0x000506ff514a830f,0x000192a8eea1c93e,0x000359a7cc2adcc4,0x000077e27e302f45}}, {{0x0008b1e48ac28403,0x0004bcba9477b535,0x000946b431831129,0x000819aa58f990a6,0x0000098baf9cab41}, {0x000c1584198da522,0x000bf46bfd1b66c4,0x00036a908ab4fc17,0x0008380f0a4c3cbf,0x0000ae9e34b78cf7}}, {{0x00040ec0ccced589,0x000b7da44f9845eb,0x0001812c625cd4b9,0x000650b3e0645887,0x00009f80d55a6cef}, {0x00040c9ce6dc1532,0x0007b86655215713,0x00007014d138d511,0x000b918cdb45bc4e,0x0000f34bb38a4b60}}, {{0x00099e84a34f239b,0x000c090402d54174,0x0003aa83215fdb83,0x000db1075f46bf43,0x000061e15b013215}, {0x00059d4a127f89a5,0x000bb7e816daaabe,0x00018b6925d541e0,0x0000265aba0659a6,0x0000532773367266}}, {{0x0009cf2d0c051995,0x0002aae784548cda,0x00072a182502fbc2,0x00037270bda9dff5,0x0000f9b71b8b158b}, {0x0003a592b82dd077,0x00052523032ee0f3,0x000505a327630273,0x00009f0fe1a721c4,0x0000b6e3e8367964}}, {{0x000155d3f6effc78,0x000f1c90f0c7023c,0x000ec2c5d1fbd69f,0x00027365d7da8abe,0x0000813872c57e86}, {0x000c2c655f5e228d,0x0008e0923b419f3b,0x000a307ca1148286,0x000ee495d75c741a,0x0000a92c2584f24e}}, {{0x0007732edc665d13,0x00017939ef1b2635,0x0009680899fb5b73,0x000c524db720fb94,0x00006f75f2c63138}, {0x00093ec48d3cb97f,0x00047d261726f8b7,0x0005c4ffb8dff1d4,0x0008700b65791b88,0x00007c79e2ee1a3a}}, {{0x0001028754c92e1a,0x000a2f0fef3408dd,0x000f55919ca90b57,0x00086a7a9b84ac8a,0x0000a95e0e28d936}, {0x0007315167021a4e,0x000940d5ff984673,0x00092e7066cb6a0d,0x0001a60cc4801a10,0x0000dcab23b1c5e6}}, {{0x0006356ea37ba9e7,0x00049afff55db4c6,0x0006cc8621adc841,0x000ab680080ef959,0x000056c85b8dd647}, {0x00094aa1db9c2153,0x0000f013b1a5c9db,0x00086c9032dd36db,0x000884ae6ac61c42,0x0000fd32f88f76cf}}, {{0x00090fca06d107eb,0x000d076611377f12,0x0007b4b38697261f,0x00012f6bb5be4e94,0x000049826b6ebb79}, {0x000dfe85ba8bffb2,0x00005e3fa8e4019d,0x000bcfe7fb1af790,0x000aea52e1bdf201,0x0000ed3ca8ff1169}}, {{0x000da8cd745fff18,0x0005e9b9924e3bef,0x00051138170b9e9b,0x00053525df48cfd1,0x00004f93fe3506bc}, {0x000c5a9b279a6c36,0x000478f96132aa42,0x000b6aea5651da6c,0x0002a250368c8b01,0x00004e44c480c786}}, {{0x0009947d9de99a88,0x000d493477bde17a,0x00019e287c2e61b2,0x000134d7f684d41d,0x000043c21237e358}, {0x000e2e904f7e8aba,0x000915f27aeee2d3,0x0001858c4bf93ffe,0x000dbe89830d1d7b,0x00008f449652106a}}, {{0x0007bc035d0b34a2,0x000b6327c0a7e341,0x0000362d1440b386,0x0009436fb7262dac,0x0000c41114d00cdf}, {0x000cef1ad95a0b12,0x000847d543622ba5,0x000e486c9c09b37a,0x00029706d6cdd201,0x00000477abf62ff9}}, }, {/* digit=45 [{1,2,3,..,}]*([2^225]*G) */ {{0x000dcb3292a92874,0x000637b092c7a004,0x0006c0605ddc15cf,0x0007afc83a846480,0x0000a68df707db99}, {0x0004e4505bf7dd0a,0x0008eccf7f8c9c13,0x000b5f8afa4e63d3,0x0001cc06e6517f41,0x0000a8b93434d7bc}}, {{0x00064717af715d2e,0x0003f0134a96c417,0x0001ec956e2f7f59,0x0003034c1873efa4,0x00004e7b4f757821}, {0x000ff9788d5374a6,0x000320823d5be5c8,0x000ee8fe22b915e6,0x0006518a6bc755b2,0x0000657624d47112}}, {{0x00000e07442f1d58,0x0000e6e0e3abd6f8,0x000c64047475607d,0x00083d02807f16b7,0x0000858e1e427498}, {0x000120b8231ee10a,0x000ac38a1ece5859,0x000aa73a41b80e7e,0x0003ac2b72525ac6,0x00007cdea3e24442}}, {{0x0007b11e51732d26,0x0007c538fc0e5747,0x00039eec5dfd6eb2,0x000c56fc43b0cc3b,0x0000af127792b36c}, {0x000852d06c425aef,0x000b6c221b9b70b0,0x000826d9c6df92f8,0x0009c27c8d4f9ece,0x000059aba7ca4935}}, {{0x0002cf152bfda056,0x00090197b98cd2eb,0x000a1726fe0e4c4e,0x000e3cbd35076cf8,0x0000c06085b8db11}, {0x000c4d74463ba14f,0x00021030238c15c0,0x00027536d9d292f8,0x000c1d2311ee8b37,0x0000eea86f0aeaed}}, {{0x0006054afa05dd8e,0x00011caf119ea7f9,0x00064bb5926dfcf2,0x0002b8020ef2e305,0x0000f4dca5141cb0}, {0x000838a65d306723,0x0004cd657e86cda7,0x000d595c88b08d53,0x0008361c5b439546,0x00009b58725725cb}}, {{0x00053931a62cc262,0x000630c0e052fda8,0x000c633f323c69b9,0x000d488227df15bf,0x0000ac788483bae7}, {0x00078f9187d073d8,0x0009167f807d4878,0x0006e6d8f6c2be91,0x000a42f65861d833,0x00008b8974d4e528}}, {{0x0002c2e421d3aa42,0x000cc84fa840c37e,0x00054e41cf926407,0x000643f8abc03d14,0x00006605ecd5f7af}, {0x00041a6d6a5eabf5,0x0003d16b668e2423,0x0000101021edb84f,0x000d8c8836edb804,0x0000b337ce7e45e1}}, {{0x000a2dccc78cf662,0x00044fdbff77666b,0x0008d4668b301817,0x000a2a6d4dd0db16,0x000059455d03dab3}, {0x00064c5cde3acec5,0x0004c3adb276f585,0x000303f657714192,0x000f7b027d725d8a,0x00005deb6ca36f38}}, {{0x00005d73272d8383,0x0009ca6295c5864d,0x0002fda32e22924f,0x0005445189593f6c,0x000030d7189e184b}, {0x000a62cbde1f7140,0x0004e5cb1a6379ef,0x0001c833235771c9,0x0008542f4826b864,0x00000a894fbc8cee}}, {{0x000cd0a1058a3184,0x000538053a9adcda,0x000c68de2369cf3f,0x000d9f86c3de5031,0x0000653a5767c4b6}, {0x000dd5aaa4e5c975,0x000167ab3c741688,0x00065c2835be80aa,0x00009120cefe7cbc,0x00007f95f1356867}}, {{0x000b6de34eaacda9,0x00079ba0f1dec240,0x000438e55d9e116e,0x0002d73be45ec779,0x00001787c9e26f75}, {0x000532bf129ac2fd,0x00078a36e22c897f,0x0009fb8f3d307b7c,0x000b27c194067574,0x000014f95d0e57fd}}, {{0x000360416df4285e,0x000af0c56ae21625,0x000c5cfc3b0c9bab,0x00005593032b19cf,0x0000497e5c3e9752}, {0x0006bb4164bda960,0x0009a0b74da11209,0x0003826ba1ee4241,0x0006608fc3624340,0x0000c8f0069dc09e}}, {{0x00074a15b0ec6f5e,0x00037289b2b8c44b,0x000d6fc7347989fe,0x0000aa945f848458,0x0000c362a70d61c7}, {0x00098a7b3a8ad418,0x000ffb63db51070c,0x0004c35f473a20fb,0x000dca6d2c2173f4,0x0000a56149e1acc9}}, {{0x000c36f35d33ae72,0x000330bb5a94a395,0x000afe84b200ea12,0x00076a00c789bd0b,0x000043ef52d29192}, {0x000c577e23ae233d,0x000ed460d1ec3934,0x000fa76a4b93807a,0x000490e72a53b1f8,0x00008914cb193ca4}}, {{0x0006b86d23ddc820,0x000c7e0143f04c07,0x0007af2c503fd344,0x000a4fa95362ff31,0x0000add3db7e18b7}, {0x0003e3f8260e01bc,0x000494a1cc919c67,0x000f2e433fbeb49e,0x0001ead1351bf292,0x0000755e7ed45114}}, }, {/* digit=46 [{1,2,3,..,}]*([2^230]*G) */ {{0x000db47f23206d55,0x000fcd2601522bf5,0x0008ff89a2f6d341,0x000457c7b876533f,0x0000157c30c878fa}, {0x000c5c52d4fb936f,0x000bf6518cdc7517,0x000847a64ef22f7a,0x000a88eeb483e6bf,0x0000508455982e0f}}, {{0x00059d8df7304d44,0x000bbf210e8eab96,0x0003fbd60b71bcf1,0x0004de69a2438bd7,0x0000595cd1f9d11b}, {0x000329a4835859dc,0x000cbdbb6e569c0d,0x000928a4e4a0f0d2,0x00015406038e5edf,0x000094296224f5ad}}, {{0x0003840a70c6ec41,0x0007d031119508a3,0x0008ab2029e8819f,0x000a27dd209d9670,0x00000d7c4e7de943}, {0x000b317a29b49a1f,0x000256627d1f372f,0x000df39ec57a67fb,0x000f170912561e7c,0x0000a3ce6f35f7c8}}, {{0x0003462f23f2d925,0x000d10b940789121,0x0006cde206cab71b,0x0004bc1bdd0a6317,0x00004c9b20d3e4d5}, {0x000d8aa9f2ac02f8,0x0006a06eedb03cd2,0x00008643403f8e61,0x000db947f68e1693,0x000031469c612dd3}}, {{0x0007465653f3c5f5,0x000ea040feb1fe7d,0x000b7edfe283dd45,0x00031141fe599bf3,0x0000ff039add0379}, {0x000995b4e96fa49d,0x0001d3e25094bf76,0x000c83f742640b6b,0x000ac2bb096341c1,0x00002bec885ca560}}, {{0x000df248f9813540,0x000c3588a2598521,0x000a0992c587e23e,0x000407cbedf281d7,0x00006930a5538961}, {0x0000debbe5bbe21a,0x00048491817f0932,0x000065160a7ffa5b,0x0002a946c8b4d909,0x0000c4f39939ff6d}}, {{0x000b2a3cc53da664,0x0001b17a9b4e2e4e,0x000e05b2c04708a7,0x0002019bfdc7b20d,0x0000cdc9aee8907a}, {0x0008dfc6c475566e,0x000a67be1691e5cc,0x00005c3fd2b83cbf,0x000eaf895833a74c,0x0000e938a7323b0d}}, {{0x000a1583ae9c1bde,0x0008037ce2407aa7,0x000ab38b4e0af6d9,0x0008ca054342d928,0x00008b75007ea1c9}, {0x00086afe02358f2b,0x00063a921228efce,0x0001c67fc31b8b85,0x000d58552a19120a,0x00004069ea593aea}}, {{0x0006205c6ffcfe64,0x00066a39418a3b82,0x0008521fb2eb3125,0x00061584b4a9e1c1,0x00008614dd91b610}, {0x00062bbeea7475fe,0x0008c8ead16204c3,0x00010a876916ab96,0x000ec38a7975bc03,0x0000a4e7d12ccc77}}, {{0x000d6e27fa03cb3d,0x000a3fdd7d883232,0x000cbfc5ddb938e5,0x00080e34c1d2cd2c,0x00002f45c137f3a5}, {0x00020b57883e6142,0x00089e7c5f265926,0x00067e1e35fd27e6,0x000aaef39e45a915,0x0000cc71d2d64d8a}}, {{0x00093c706ba8e6ff,0x0007223deffd6ef4,0x0002b5a4f05c07bf,0x000e9bdebf9b4d9c,0x0000958147f1d038}, {0x000cee03e5561c4e,0x0009994a6afc5af5,0x00072168b8d0b5a7,0x0007fcbde22df137,0x00005d249c6b8409}}, {{0x00090cde36d07576,0x000179a293824a90,0x000b48ddff722d7b,0x000f439b7fb04c04,0x000028ad2a84be16}, {0x000bfb520226040e,0x00007104b6c4cd3f,0x00003c1886c34ecb,0x000aaf50c0754ec9,0x0000c336b090d23c}}, {{0x0000b4295c69248e,0x000d1ed9030374c7,0x0008cc87a8813259,0x000a94c3e330684b,0x0000689371cf11a7}, {0x000bbf7fbbbc20ba,0x000cc5f9a6e252bf,0x000413e6d73a8543,0x000031c7bb2fdd7e,0x0000066b3f065cf2}}, {{0x00062a21e206ee56,0x00002c49a633473d,0x000f6b2c3f1e2748,0x0006ea27ab956ce9,0x00001830b48c2b60}, {0x0006846e78e815f7,0x000edc02082a67cd,0x0002ec365fe40139,0x0006aae2bbbfcb95,0x00004c11642db983}}, {{0x000b89c44f489710,0x00076d660683cf61,0x000d431bde2d700f,0x000f4a72ef285cd1,0x0000593b24e9bdeb}, {0x000bc5b0561f8a1a,0x00000a16f2564084,0x000f6d27784ce74d,0x000dfdfcbc79d309,0x000094fe2fee139b}}, {{0x000439e558df0194,0x000a6c712b279f51,0x000185a24230da4b,0x000f50118919e355,0x0000dcefcddc4b78}, {0x0000fb2a47d4c5ab,0x000f030e009ea7d9,0x000eed27355ac9ab,0x000faf4d2fc35974,0x000072d824d8bea8}}, }, {/* digit=47 [{1,2,3,..,}]*([2^235]*G) */ {{0x000b2b5ef7d92893,0x0007e97f015a549d,0x0000493b62480d4a,0x00033131d5590bc4,0x0000a55b52e9f780}, {0x0008115309eadb09,0x000a02e5c62540eb,0x0006a3d5adea7de5,0x000d60d4d631f0cc,0x0000d5e9d7d23e8d}}, {{0x00060411e84e0e5b,0x0002fea34c931968,0x00073a732a5db84d,0x0007c049d5bb1970,0x00008d2fe571bcfd}, {0x0005f36f3eb82fab,0x000c4dff8b584577,0x00074c1108cb20cc,0x0008996659b65f83,0x00008b4a422e30c7}}, {{0x000ff87aedbae9f1,0x000926880a54c925,0x0004d0e717daf0eb,0x000cf58284ddf59c,0x0000581cf93416f8}, {0x000a8873ac1f4527,0x00098b6aeffe3eec,0x000fb8dc3b417fce,0x00040035918046ee,0x00003d318ac72209}}, {{0x000cda3af2ebc2fd,0x000cfb4efe24c4f4,0x000cd10b1a0af843,0x000e0383b857c19c,0x0000dc9d1ec614d3}, {0x000c8bb62771deb1,0x000a81c5aa817bde,0x0002391ae829277a,0x0004ca6af18dd683,0x0000740f316d71a8}}, {{0x00012d8e12b31f8c,0x000b577736e6dd4a,0x0008935e8577e29b,0x00086c6353722ba8,0x0000a1d3729c15f2}, {0x000b6a239a3e0358,0x000f53b03a9f86c7,0x0000d536e6e5250b,0x000831f9d98930fd,0x0000c4cbbac7a0c3}}, {{0x0000910cab91f1eb,0x00039d1cd2162d50,0x000d02252bedd9e4,0x00017a2634b74fed,0x0000d60f8e1c2586}, {0x000537b9e05614a8,0x000667af5fc5d8c7,0x0002bd926fd26c76,0x000fc78660b58158,0x000070192452cf07}}, {{0x0006ccfaf64ecb6b,0x00069bd72775afa2,0x0000f695ae6054f9,0x000fde0bcbab5b14,0x0000c71b4a59348e}, {0x00052becc96d9633,0x000f2e5d9018fc2e,0x000568771150abf5,0x000f838d182fa604,0x00005b4c061a0339}}, {{0x000e99aeeaf8c495,0x000d1e24d7288928,0x0002b156cee7aa73,0x000a1cfc5007c2e7,0x0000fcf57c63d408}, {0x0009e39b6057604e,0x0000e2868bbf9f71,0x000103e2d7d343c0,0x000ea14cca254b7e,0x00006eb38aad131b}}, {{0x000a04e5f40ff526,0x000f9cd2914ac624,0x000d3bfd63611d7c,0x00063a57e8b42b1f,0x0000cde40fe5a850}, {0x000c449178b7e5bc,0x00006972cc137811,0x000b461354cb6093,0x00056e3579125e33,0x0000a102ef848a4e}}, {{0x000e3520a981b0d0,0x0003bd1a41a40ba4,0x0009fab9c1c354cb,0x0008d51aabaa3adf,0x0000701a7d153c41}, {0x0007cefdcf2b9218,0x00033cf48061dd1a,0x00025cce66ceef0b,0x000e339083b598de,0x000090a54c8690a5}}, {{0x000956640ac1807d,0x0005b4da0b1ec535,0x000b82421d4c1e56,0x000dfff4b33f97e0,0x00000bd23184b41b}, {0x000b42e147b72e1a,0x000f5777104c53a4,0x000fb530df8d39f5,0x000fdc96e64e64d3,0x00007a6ba67f6074}}, {{0x00018db4f6d01b11,0x00027f11e8a04057,0x000591a3be73c6bc,0x0005319c11bb8ca0,0x00002d09a5a1acc4}, {0x00074eee7de13f4c,0x0005444fd682cbf1,0x00048af70177e2be,0x000b7ba5f574cb1c,0x0000e5966935961c}}, {{0x000e84ebc6fab9f1,0x0001b80f6474989f,0x00002a1bce70ce6b,0x000fd3ae9ff3053b,0x00002ef4866a9c0a}, {0x00057f9e3411a268,0x0000fb485b9822d9,0x000e201190b41d88,0x0008e0020e56d04a,0x00001e3d01fb2852}}, {{0x000ed6c048752a14,0x000e601341b4c59e,0x000c6b09241f2702,0x000b232e35903b9d,0x0000291aba85f5b5}, {0x000aa70a653d61da,0x0003af2eb51e8173,0x000b93f8fd1b648d,0x0004fd91b7ce065a,0x000055408ef39e2f}}, {{0x000ed0985e341605,0x00032a03cde21fa4,0x00084df2da26d7dc,0x000107cdac0848fa,0x0000e9a28d66b697}, {0x00004d914ea0ea1e,0x00075ffe5520a880,0x0009b139ca8d1542,0x0008606f422dae63,0x0000edccc0eb4b5a}}, {{0x000624f8be762b49,0x0000758e3413b33e,0x000d805fa2a9ee4d,0x000fd7068e636967,0x0000848949c0db8b}, {0x000d7e5d23a84178,0x000d73e29da55308,0x000ee471f892f3b1,0x000089495c139e3d,0x0000631594e5757e}}, }, {/* digit=48 [{1,2,3,..,}]*([2^240]*G) */ {{0x000e2ea1f095615b,0x000664e68c331083,0x0008818be0a28ad7,0x0000ccbbfc02523d,0x0000585113ba3585}, {0x0005f0b30df8aa1c,0x000b8ab7e3ac7d93,0x0002f00cbaddda07,0x000f6bd2c3429955,0x000033ed1dee909d}}, {{0x0000d483e07113c9,0x0008ed8b63ae2dc4,0x000684c2b6e4a5d3,0x00026bc582a94b79,0x000032b33d4f22da}, {0x000f6510dbbf08dd,0x000894c23a52f534,0x0005bdc9b211d07c,0x0005573eeece0fee,0x0000f178169c7015}}, {{0x000905a83cdd60ed,0x0004d1170184abe7,0x00023642a50602fb,0x000aff989886cdb0,0x0000568d09176e1f}, {0x00022c70259217fd,0x0008f43141e45b19,0x00095f86e93831cd,0x0008280fca35870c,0x0000ec2057b268ae}}, {{0x0008925913cc16df,0x000cf1a26f5a568f,0x000f499ae18bc5b6,0x000e83efa413bef5,0x00008835dedb3f0a}, {0x0000bd865a40ab05,0x0008c94b377eb6e6,0x000084a696559643,0x000de06cd8562592,0x0000ce433b99f23e}}, {{0x000523d42e06189e,0x00006e3aff13860d,0x000b20650bf07794,0x00000c2b616dcac1,0x000066dd6d201313}, {0x000fd67ff99abde3,0x000097aac50dd4a0,0x00046b2d7c990355,0x0002aed22ecf8b7c,0x0000333b1e86abf9}}, {{0x00065e784d6365d8,0x000f0f759fb8c0da,0x000e81930bcb7443,0x0008aab5c712b17a,0x00000428dffcc6e0}, {0x000afefa4faf8433,0x000dcfa9855ff19d,0x0003ac7ceced8538,0x00071df0ac409cbe,0x000058c1fb6b82da}}, {{0x000def7be42a5821,0x000055046be6efec,0x000e8dba9d3fc608,0x0001ffb9af13c809,0x0000e6c984774149}, {0x0004925d30c31f70,0x000aac2a21223b57,0x0000859e7b7eb72b,0x000942776a0dacef,0x00006fec31421900}}, {{0x00094b07e50122b3,0x000b1af07ca53247,0x0003fc97bdd744f8,0x000d9d00a12f08d6,0x00009650f1aa6626}, {0x00047f71fa38477c,0x000914dc124f101b,0x0006eb58a3d815f1,0x0008865569ae95b2,0x00003cde18955fb1}}, {{0x0002fbbf4737f217,0x000af209f5ac7ec6,0x000f9adbed8dba5a,0x000767b4b5d7a9a5,0x000007d28f8161dc}, {0x000460bcaa999eab,0x000c6c92e4cc7711,0x000d4bf2dba7b174,0x0002788c4bab6618,0x00008f0c9819b8bd}}, {{0x0008932790691bf5,0x0008b6b736ae9d65,0x000d63b6eed61058,0x00088f212c2f04c0,0x0000cf06fd6163d4}, {0x0003facd9588e411,0x00021b93257e9736,0x0007acace1f9bf76,0x000ecf99d1ffc466,0x0000cf4a1aa1a061}}, {{0x00075b2c0519a238,0x000dcf6952e328d6,0x000294a8a9ebf94f,0x0003f5728bb767a2,0x00005512b4e7e0af}, {0x0008ba899b16a0de,0x000bda7548a71895,0x0006be61595c2430,0x00074bd30d1b10a1,0x00003ebbb9865bfb}}, {{0x0003f5eb2e636456,0x000724c8423207b5,0x00014d5cfbe57e54,0x000aca7779c21672,0x000017969cd629a3}, {0x00068cd8a7017a0a,0x000a1e9b7ee8d176,0x00016177677b4d19,0x000a71b8fd0e939c,0x00008c4f4f075968}}, {{0x000b865d2fdca23e,0x0007ec8ef89581ee,0x0009056145a15ee0,0x00019a968fa10a01,0x0000ff5b8f0680ee}, {0x000cabbcb1c8a0ef,0x000cc8c838f9f0c0,0x0004a14c02e1ee9c,0x0008e41587d8b88a,0x00006f278971ff69}}, {{0x00034b3bf44da801,0x00094ab32e66519d,0x00078a000283834f,0x0002f65e60879762,0x0000e62960e72731}, {0x000b27be6901c550,0x000824fdbc1f9b87,0x000acc27d80e7853,0x000b5abbbc09512f,0x00006394239ac143}}, {{0x000646e9e2fce99d,0x00004e80857f9c4b,0x00043b52a68a2108,0x00084236d54e4436,0x0000e8d6d63dd8eb}, {0x000156342146a0a4,0x00021eaa36227032,0x0001387878ba826f,0x000d36e27a58bd86,0x00003b6c03c50281}}, {{0x0007a952f41deff1,0x000ad63b89b702b3,0x0003ff9510e44a59,0x000af4573257dc14,0x00009c02205e752b}, {0x0003069c4b7d692e,0x00031d1502ac46c2,0x0002208462e6392c,0x000b628057b1a21b,0x000051ff946ec1b5}}, }, {/* digit=49 [{1,2,3,..,}]*([2^245]*G) */ {{0x000cb51566c5c43e,0x00085597f0466e85,0x00094d94acff9c91,0x00027cb354e90c49,0x00000a3933301479}, {0x000fac10dc1eb2bf,0x00013ff319fa8427,0x00096527488cfd8c,0x000745f2d4e68401,0x0000a2e067e57aaa}}, {{0x0002a7f3e5f9f11f,0x0009e6cb3b8eb6d9,0x000f800bd9afe153,0x000e185d1a6dd7dd,0x00006c13cc1baf17}, {0x000c58e325fc3ee3,0x0000731dc3b215f6,0x000a3d3e77109540,0x000e2ce68e7c07af,0x0000f8417a1c4c7a}}, {{0x0004772813b230d7,0x000ea7344427ec23,0x0007fc56a634d0f5,0x000f76a1548ab1d7,0x0000fab17513e06a}, {0x00010a74f7c4f830,0x0004220a67d9b62c,0x0001209a0a7d2edc,0x0009f01c40417092,0x0000b9815a0face5}}, {{0x000589b319540c33,0x00097283d6f82842,0x000ae9fcb18490f5,0x000ba072731f84da,0x0000db6d960f3683}, {0x00063bb146110697,0x000e9788bf05c85c,0x0007460d2b19436a,0x000db1205459df34,0x00003f6e095511a7}}, {{0x000938eb6357f373,0x0008fbd8aa62dc7f,0x000a979fcc5d00f7,0x000a999878dcb92c,0x00007e83eda1b023}, {0x000e2731560bf3d1,0x00090d0fae616b23,0x0009414bd1086e45,0x000ea1682483169a,0x0000b956bc100ea9}}, {{0x000bb91c31b9c38e,0x000a68ef57b57b85,0x0003bab6f0c5aa90,0x000684fedeb169af,0x0000610ad740d373}, {0x00070df02ba8e15d,0x0005bca7f771f138,0x0002c036c0337edb,0x000e8114acf747b6,0x0000921d57786b94}}, {{0x00064392c422f7ac,0x00022d348898dbc8,0x0005bfcd1fb63536,0x000e10c3084668c4,0x0000357c9e3eb315}, {0x000b5405b2e5b8ce,0x00010102b9a4b173,0x0000fb1997e94693,0x00062a37c890eb7b,0x0000c225a84b61b6}}, {{0x000a3c8ee3c76cb3,0x0003a32a1f6ef306,0x00063e9563cf1162,0x000c26b6d5ab6468,0x0000b8a4cbe8c005}, {0x00029a59ce6bb278,0x000184d4b16fdcd5,0x00023798dc4afaa5,0x000fab30624a2679,0x00005e56df6eb307}}, {{0x000893c2bf296984,0x000497ce76030281,0x0009a558f91fc19a,0x000f7735a5dca3ad,0x00000ceb3fa8d50b}, {0x0006060bc9ba369d,0x0006897888c21baf,0x000a34c07927e103,0x0009800936bf1986,0x00004cf10c2934ae}}, {{0x0005334859dd614c,0x000a58d0c8ee3a3e,0x000cd51d59c475b5,0x000325a3080d1f07,0x00009c0d0a7788b4}, {0x0008691c234296f5,0x000444887fb61ac9,0x000ea9cf22a0a83a,0x0002f5065114270c,0x0000230a6e8f2480}}, {{0x000bf0f72e3d5c1e,0x00056f21439ef7a2,0x000e303343771744,0x0002f91edcbf259c,0x00000030a795ce20}, {0x0009ebf1202e9ca6,0x000c15e6e5916f2d,0x000dac4f8e79dde6,0x00004d952072aff1,0x0000c8d087f1b9b4}}, {{0x000c73dbce913af4,0x000b058a07cbad0f,0x000f00c8a909e587,0x0006abd300da84d4,0x000025cd048f5446}, {0x000b9be90e9d8bf9,0x000aae431b0eb59c,0x0001aecff991616d,0x000c3b43aa117a53,0x00001af92d3e9f4d}}, {{0x000c292e93fda293,0x0007b97d91bc9b1e,0x000ace1e676bb6c1,0x000ae34509d95faf,0x0000653fe47ee855}, {0x0000b280f680e752,0x000bceb6c26c7318,0x0006d423675eefd1,0x0001d884cdf29fb6,0x0000d70a9978b582}}, {{0x000e20720445c36d,0x0001898771747a3e,0x0009f73e971d1ac8,0x0000803fc539f794,0x000005cf3d8682e3}, {0x000e20b7b1c7129b,0x000fa69e61f28758,0x000544c2dffadcc1,0x000e53005d3a2f59,0x0000e16f5c24fff5}}, {{0x00065b8aad581350,0x0009037aa5be73cf,0x0006fd6a0622c211,0x0008cf79373b3f64,0x0000e029db50d397}, {0x000c43794fba0377,0x0006f20797a68bdf,0x00030d38eaefbd68,0x000463cfa5382bbd,0x0000627cfbfc85d7}}, {{0x0000fef4e4ca4631,0x00072566cc63b233,0x000780900bcef728,0x00027dc161d2cacf,0x000035dc5396b548}, {0x000052e27bf1bc68,0x000f87dfa06c638f,0x0003321da10a224e,0x000c8f6973586d6d,0x0000b0c5738a6152}}, }, {/* digit=50 [{1,2,3,..,}]*([2^250]*G) */ {{0x000ba6b23a5d8961,0x00056fe4364e9910,0x00033c6771fe19e3,0x000fd05e1da8c39a,0x00005b4488b39fd9}, {0x00092541a1f22bff,0x000fbb8163e81f43,0x000e5658e920a8a6,0x00039a4fd1b24907,0x00002c4f79da6ec8}}, {{0x000619c76497ee80,0x0006c717370e8b5c,0x000cf68e15d2b0ac,0x00079298204cb64f,0x0000bdec21162bc6}, {0x000ccefa63b10110,0x0007e0de1ac56973,0x0000e0c8bf9e3fa9,0x000cb45efb693e3d,0x000037248e9d2d4f}}, {{0x0004e2ab20364e46,0x00088770b20dd369,0x000d77d1c6269971,0x0000a50183291b6e,0x00009aada7fcd618}, {0x000054bf185509bd,0x0005a870107751f9,0x000b96d8dfd7e845,0x0007ee06a2308a7f,0x000053e48d2f8dc8}}, {{0x0002dc91ec34f9e7,0x0004c38106038080,0x0000cb4f3d8772d3,0x000128cf06d66c53,0x0000be5ed0e3475c}, {0x0003c1931e82b100,0x0007c9ff6b4ccb9e,0x000a1b45ec63d285,0x000bcab92118c692,0x0000aec44147285b}}, {{0x0001afbe8316c455,0x000cf6700b8b3707,0x000ff8578982be4f,0x000fa73d5d177c64,0x0000ec4058319a82}, {0x000e37bcfa86678a,0x0003ff0312845518,0x000bbb74c24e809f,0x000de5912f39604b,0x0000d4b4f7060c14}}, {{0x000f4868eb6e843f,0x000abc4ab3aba3d6,0x0003cf2dc6415834,0x000c3d128a81514f,0x00003b496304f3e6}, {0x000ae90987dd2f21,0x000ad10bce559119,0x000149ed6437a6d8,0x000332b31cdd6b9b,0x0000b77791d16871}}, {{0x000b650e16e05e91,0x000084e746409c34,0x000a3f029965a774,0x00077c93fd22fbce,0x0000eb6a9689f952}, {0x000a63d7bad84f61,0x0001e58f2fee2520,0x000840d48ad91720,0x000cbdda92c1669b,0x00002109c4abcef5}}, {{0x0009ae71e29a3efb,0x000f9c93302efc18,0x000aae10ecbe906e,0x0009f820107914ce,0x00007a23f35668e1}, {0x00075c2efd2119d3,0x000eccadc9c8e9d8,0x000a1711303198c6,0x00003835591bf64d,0x0000cf0bbf86d443}}, {{0x0003027aad991c1a,0x0007e49be4b7ab29,0x00072da90598d0bf,0x00083fec94a21ab9,0x0000da4cfde1ecfa}, {0x000b9c0fbcec63aa,0x000163219a3493d4,0x000652a557ca617a,0x0002dff00424eb6a,0x0000f9346ea8b856}}, {{0x0004d79023814615,0x0005411bc478c3e0,0x0000b3ef2b1643ab,0x0001b6792becfa39,0x00004476778fcd2f}, {0x0000c4d66bf3aafb,0x000a7c21c65a8daa,0x000a13ac32bc1287,0x00090a3e182910b5,0x0000b04730140b07}}, {{0x0006947d17d4e0b1,0x000eedc3a47b8376,0x0006fd0ffc5772be,0x00095e665a50db1a,0x00007f904ba55b09}, {0x00043832883487ec,0x00030270aaedcee6,0x000cb1fd9f56db7f,0x0004d4a738d94f46,0x00008fa426ad42fd}}, {{0x0005bb72b7247593,0x000182d4c63aae48,0x0007d6f2c945353e,0x00010952159d07de,0x000089caef37ec5b}, {0x000bb53db65ef147,0x000e6d99de434a8e,0x000f2405f2dc2cb7,0x0008a3116fa3ed83,0x00003429bba31420}}, {{0x0008febd56daf065,0x000afa837f6908ed,0x000b6e05a8d98277,0x000abd4947c636a9,0x00008c8a77b10d58}, {0x00096a45f121e4ff,0x00062076d3d3f454,0x000fb0c5d16cd67c,0x000b46fcbd1958e3,0x0000be185ed28e1e}}, {{0x0009760ff79d2ee9,0x000f639e7832b7ef,0x00005b499dd4d06a,0x000d316d025001b9,0x00008fe1c6285b61}, {0x0003980c5f128050,0x00083009cd9aa9f8,0x0004eb16d376e3b7,0x0002dfa322b09f51,0x00008e213122c383}}, {{0x0008626dc4ad4f4b,0x00019ddbc0b6aea6,0x0002e90655dc5168,0x00088df76697bd60,0x0000eeb3ea63c378}, {0x000a2f2145691136,0x000c435f44841ec4,0x000e44df2e48b820,0x0009fd3fb560949a,0x0000ca13462f2cc0}}, {{0x000d590b01e6e274,0x000da180b2dcb618,0x000aea4a9047e2cc,0x0003a491b299b504,0x000012c9e1edfa40}, {0x0008a36794075521,0x0006e332b8e388d2,0x00068de1949c5013,0x000b972a1b6fcce6,0x000078851bc85122}}, }, {/* digit=51 [{1,2,3,..,}]*([2^255]*G) */ {{0x000d46d95a7b1a29,0x0005ac6341fb197d,0x0004c2ece9c4e7ad,0x000f89b26eca2948,0x0000211e48a6e7f4}, {0x0007f6ec78ef1f42,0x000fe65745861499,0x0003eede82b2c090,0x000017f7286a6e1c,0x00005f92e472f60e}}, {{0x00070af3aeac968f,0x0008d4b63266b4e3,0x000ac5664e4f7fee,0x000cbec4acd4c2e3,0x00008910bd3beb38}, {0x000e50cc9c0726e3,0x0009a97b40bf1c3a,0x0005a5a1b1530956,0x0004cd40884b7ffd,0x0000890896b1f831}}, {{0x0007d205ffe7b376,0x000ab747d2da090d,0x0004fc5193b7f3ef,0x00071e42cb525fb5,0x0000e220933566a9}, {0x00060dfb486d440d,0x00056fe13465ddc1,0x000e4c1517fcfec4,0x0002b4b3da7e4e76,0x00006fa48a2a8d30}}, {{0x0003c9f82e4c6346,0x0003da4464f85ced,0x0001dca258efb831,0x00012b8706381b7a,0x0000cd15a3cba2a4}, {0x000a8fdbfcd8fb51,0x000f5e54cd229347,0x000d8932f31db2ee,0x0001afb4aeb11ef8,0x00001e7c1ed44441}}, {{0x00065ef12045cf9f,0x000eaccce8bdae40,0x000cf65256fcb2ca,0x0003112fa0ba4ef2,0x0000683125ebb72c}, {0x000a4eae312410e0,0x00076cd8e830a01d,0x000fb3f0767e2867,0x0009a5abd9575298,0x00005f11e11eef64}}, {{0x00084f5903fa2711,0x0002a9da921e9968,0x000b01e54e6da0fd,0x00014e96f2f2695d,0x0000ee3e9bd78762}, {0x000181ce27a94979,0x0003fe215e04a26e,0x0002cabca36d254e,0x000613b2f32a6c25,0x0000948148810b57}}, {{0x0001058fa28a7e00,0x00050bf5ec74ea96,0x000229666c726cf2,0x000799e74d55c8db,0x0000bd9abbfa57f5}, {0x000ef074dfc47b3a,0x00026c52f91d7479,0x000a8bde2d9c65fc,0x00027fee0283fe36,0x000032a8b5f1d4b7}}, {{0x000b43a43228d831,0x00003ad63f99ab41,0x000a5122924ae1c3,0x0002b47e525f1a46,0x00004af860fdd26d}, {0x000ef613f714aa18,0x000d6b78795ed6ba,0x000a9d694f51865a,0x00052753e21fcee6,0x00002ceb1de0a37b}}, {{0x000d27d483076829,0x0003510566da8605,0x000f2d7ab745aaba,0x000823557cae36bf,0x00001332ba1db127}, {0x0003638f3429f438,0x000f6c462929cb5c,0x00018b7bd43a21c4,0x0000c669bc95352b,0x0000c2addf4678cb}}, {{0x0005bfd2f9fd51a3,0x0002181b97f74a66,0x00036ce507f2f1fe,0x000ded9ad05d69ad,0x000014fc2a4b44f4}, {0x0003d8cb55fc5c6d,0x0007efb1e23dd559,0x000453ccee3510ce,0x00063129b7be6937,0x00003541b7a39fae}}, {{0x000cbcad7154cedc,0x00067f52651ab013,0x0005e642e949b285,0x0004a343b41f6e9f,0x00003a3462a46ed9}, {0x0006cd6222b24dc4,0x0009c28c9c26f3c8,0x000dad3b67578fe8,0x00040a6ac7bfa12e,0x0000112c5d7c8479}}, {{0x0006525eca445df4,0x0001ecdfa4c69929,0x000a6d3bcf1af24f,0x000cc7b5b4eb61eb,0x0000560910cd8972}, {0x0001c32093eaa327,0x00090d3c67bb5475,0x0008711100183134,0x000a7dcbd90ce62d,0x00005fc863ac38ba}}, {{0x000f8b64ae3a2787,0x0005a37cdf658fe1,0x000be0492160c530,0x000d81b2f029e733,0x00009a68042ea75c}, {0x000094a5b3f3ada8,0x000d965c32501d8c,0x000792e225d723bb,0x000ea988b958ffa5,0x000029fa987311c1}}, {{0x0008a4176a9f05d0,0x000b9011d488711b,0x00048a65e06ca4e4,0x000894543bc62ba2,0x000017535ffc9290}, {0x00084ce406851d75,0x000f40e960b4840b,0x00028fd34afa3acd,0x00092c5c3394af71,0x00004eb4d5b7ac0f}}, {{0x000a73e4a14f8366,0x000790946328923e,0x00017a4dfc8cc8c5,0x0009296e3f117fe9,0x0000372f934572ce}, {0x0000249c29ba567e,0x0005ac829cca7500,0x00002ec7acbd437e,0x000d168c63aaabdd,0x00009b2f90d5b42b}}, {{0x000e87355dbd4b3d,0x00079639bbb1db09,0x0006519621f87992,0x000573e83e47e51c,0x00004ef0fb7943fb}, {0x000b9d8f1bfb12a4,0x00082e5e8b7227d3,0x0007b90146ab877e,0x000b644eebdc9d15,0x0000c2110057aa5c}}, } }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPRECOMP5_P256_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ecnist/ifma_ecprecomp7_p256.h000066400000000000000000016472271470420105600337630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ECPRECOMP7_P256_H #define IFMA_ECPRECOMP7_P256_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (7) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_SLOTS NUMBER_OF_DIGITS(P256_BITSIZE,BP_WIN_SIZE) #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static SINGLE_P256_POINT_AFFINE ifma_ec_nistp256_bp_precomp[][BP_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x00030d418a9143c1,0x000c4fedb60179e7,0x00062251075ba95f,0x0005c669fb732b77,0x00008905f76b5375}, {0x0005357ce95560a8,0x00043a19e45cddf2,0x00021f3258b4ab8e,0x000d8552e88688dd,0x0000571ff18a5885}}, {{0x00046d410ddd64df,0x0000b433827d8500,0x0001490d9aa6ae3c,0x000a3a832205038d,0x00006bb32e52dcf3}, {0x00048d361bee1a57,0x000b7b236ff82f36,0x000042dbe152cd7c,0x000a3aa9a8fb0e92,0x00008c577517a5b8}}, {{0x0003f904eebc1272,0x0009e87d81fbffac,0x000cbbc98b027f84,0x00047e46ad77dd87,0x00006936a3fd6ff7}, {0x0005c1fc983a7ebd,0x000c3861fe1ab04c,0x0002ee98e583e47a,0x000c06a88208311a,0x00005f06a2ab587c}}, {{0x000b50d46918dcc5,0x000d7623c17374b0,0x000100af24650a6e,0x00076abcdaacace8,0x000077362f591b01}, {0x000f24ce4cbaba68,0x00017ad6f4472d96,0x000ddd22e1762847,0x000862eb6c36dee5,0x00004b14c39cc5ab}}, {{0x0008aaec45c61f5c,0x0009d4b9537dbe1b,0x00076c20c90ec649,0x0003c7d41cb5aad0,0x0000907960649052}, {0x0009b4ae7ba4f107,0x000f75eb882beb30,0x0007a1f6873c568e,0x000915c540a9877e,0x00003a076bb9dd1e}}, {{0x00047373e77664a1,0x000f246cee3e4039,0x00017a3ad55ae744,0x000673c50a961a5b,0x00003074b5964213}, {0x0006220d377e44ba,0x00030dff14b593d3,0x000639f11299c2b5,0x00075f5424d44cef,0x00004c9916dea07f}}, {{0x000354ea0173b4f1,0x0003c23c00f70746,0x00023bb082bd2021,0x000e03e43eaab50c,0x00003ba5119d3123}, {0x000d0303f5b9d4de,0x00017da67bdd2847,0x000c941956742f2f,0x0008670f933bdc77,0x0000aedd9164e240}}, {{0x0004cd19499a78fb,0x0004bf9b345527f1,0x0002cfc6b462ab5c,0x00030cdf90f02af0,0x0000763891f62652}, {0x000a3a9532d49775,0x000d7f9eba15f59d,0x00060bbf021e3327,0x000f75c23c7b84be,0x00006ec12f2c706d}}, {{0x0006e8f264e20e8e,0x000c79a7a84175c9,0x000c8eb00abe6bfe,0x00016a4cc09c0444,0x000005b3081d0c4e}, {0x000777aa45f33140,0x000dce5d45e31eb7,0x000b12f1a56af7be,0x000f9b2b6e019a88,0x000086659cdfd835}}, {{0x000dbd19dc21ec8c,0x00094fcf81392c18,0x000250b4998f9868,0x00028eb37d2cd648,0x0000c61c947e4b34}, {0x000407880dd9e767,0x0000c83fbe080c2b,0x0009be5d2c43a899,0x000ab4ef7d2d6577,0x00008719a555b3b4}}, {{0x000260a6245e4043,0x00053e7fdfe0ea7d,0x000ac1ab59de4079,0x000072eff3a4158d,0x0000e7090f1949c9}, {0x00085612b944e886,0x000e857f61c81a76,0x000ad643d250f939,0x00088dac0daa891e,0x000089300244125b}}, {{0x0001aa7d26977684,0x00058a345a3304b7,0x00037385eabdedef,0x000155e409d29dee,0x0000ee1df780b83e}, {0x00012d91cbb5b437,0x00065a8956370cac,0x000de6d66170ed2f,0x000ac9b8228cfa8a,0x0000ff57c95c3238}}, {{0x00025634b2ed7097,0x0009156fd30dccc4,0x0009e98110e35676,0x0007594cbcd43f55,0x000038477acc395b}, {0x0002b90c00ee17ff,0x000f842ed2e33575,0x0001f5bc16874838,0x0007968cd06422bd,0x0000bc0876ab9e7b}}, {{0x000a35bb0cf664af,0x00068f9707e3a242,0x000832660126e48f,0x00072d2717bf54c6,0x0000aae7333ed12c}, {0x0002db7995d586b1,0x000e732237c227b5,0x00065e7dbbe29569,0x000bbbd8e4193e2a,0x000052706dc3eaa1}}, {{0x000d8b7bc60055be,0x000d76e27e4b72bc,0x00081937003cc23e,0x000a090e337424e4,0x00002aa0e43ead3d}, {0x000524f6383c45d2,0x000422a41b2540b8,0x0008a4797d766355,0x000df444efa6de77,0x0000042170a9079a}}, {{0x0000b650bc6fb805,0x0004effe2e6b808b,0x00083f5495882e07,0x00072385ef2f7c2c,0x00004d63c80e103b}, {0x0001bd652a23f9b6,0x0008eb0b6587f2f1,0x000580e9e3670c31,0x00021ff5c4623bb1,0x00004edf7b261efe}}, {{0x0001dcbd53c5c9dc,0x0005ec0a177b9709,0x000fe2dfff17624b,0x00074df0f139752c,0x00001a35c0b2c7a5}, {0x000314693e79987e,0x0000089cb80e227d,0x0001883bb0575bf3,0x0003cf4f4e247f0d,0x0000bd512271274c}}, {{0x00051c856ada97a6,0x000d2f8b403e5f3e,0x0002e29794afc964,0x000bda46f247ab41,0x000075abd1bcf80e}, {0x000bd725e485a1d6,0x000f2f4f0b3c66a2,0x000847bba4b2a5ca,0x00094cc626927f1b,0x0000c6fc7d965023}}, {{0x00012baa5659ae8f,0x000935e1a16efea9,0x0002c41ac68363ab,0x0003fbc884227775,0x0000e545c291897c}, {0x000e9e7dc4c696bf,0x000a0ba977c52d36,0x0009508c15806244,0x00097a95665e9be3,0x0000720ee265d125}}, {{0x0009129d2337a31e,0x000e2f862bdc8a97,0x000d283ba5916868,0x000b4d248099d95d,0x00002d1eeb7de5bf}, {0x0001c417884005d5,0x0007afffcbae82ef,0x000a95e66a2d4ec1,0x0000d04161c53f8a,0x0000ee104e215fee}}, {{0x0004cecc135b208e,0x00046783f47d562e,0x0003f3b3074e1b26,0x0002fb8d2a506c5a,0x0000cead9f5a1676}, {0x000d4b2e286e5b9c,0x000fc3bb3c61f29d,0x000ac29a41b0fadb,0x000fa2ba75023e7f,0x0000086d5f289477}}, {{0x00011352f6f3076f,0x0002f3912a9a0fc6,0x000f8ba3dc99ffa2,0x0008a37a0b0685d2,0x0000dc777e9d9335}, {0x00087bb35415f047,0x0009dd23fea494a7,0x0003a35b5640c2d6,0x0000742de917da15,0x000093e8d07cd5cd}}, {{0x00076532de45068a,0x0007fe2e1f6ef4f8,0x00058406937c7a7e,0x000f4230825fa2a3,0x0000f2cea7cb727b}, {0x000a4fb9e4785a98,0x000ba7299f4a0360,0x000ac2f71e5fda49,0x00066ec8068e1371,0x00003d0687c10776}}, {{0x00083b215d02819f,0x000f50dd9a356d38,0x0002b469f6d0d754,0x00011471d7cbf91d,0x000097b23301efc3}, {0x000d750b24bcbc75,0x000938a1e356a551,0x000cb750111ea494,0x000b8a2669f03193,0x000095dc55f1a737}}, {{0x00019acd837879f9,0x000e5d6b67b0a4a3,0x000f1f3af6fc1b49,0x000a2e5395993332,0x000066742ebf5432}, {0x000c9feb49662287,0x0001d3f439504b8d,0x000b731ee96cc631,0x000967a2068859c9,0x0000b948dc3c6f79}}, {{0x000ad32ed1f80089,0x000a48b1753861e4,0x0007ff6fbe6c9267,0x000b0f8ac7c5eb85,0x000094baaa8e5f2f}, {0x00014e11d248018e,0x000a828ac50884cf,0x000a944f55a39898,0x000ac634fde97b5f,0x0000d178031b12e5}}, {{0x0002af497e2feb49,0x00071ebf7313042c,0x0004ffdd7d36a42d,0x000769b9d2c9eb08,0x0000f8aa54bbef7c}, {0x000b7ba09895e702,0x000fbdb7fb589200,0x000eb4cbb3bd0c66,0x000e310d97d10878,0x0000d431068f84bd}}, {{0x0003eb7172ccd1fe,0x000750a6a8924b52,0x000e153eb7323cb2,0x000b96b7082ec0cf,0x000097f6b6bd2aad}, {0x000393ed1a83da1a,0x0006e04b2a681d3d,0x0000cb71ea6a7f9c,0x000277aa688b482d,0x00009b4cc5fe0585}}, {{0x000b46acb66e132e,0x00092d9258805e5d,0x00017b9e2f1be963,0x000d47b44a702703,0x0000266f95a28603}, {0x00066735c2088993,0x000772fb18a398db,0x0007c619f9047244,0x00021b5a96693977,0x0000798142a5a3be}}, {{0x0001cb13298b343d,0x0008e44f65a1b424,0x000c77acda3a14e4,0x000c3bf5f4d6cd3a,0x00000288cb622b6f}, {0x0008c2f1c040abc4,0x000dc6bf9b4ad5cc,0x0003aa441b675511,0x000f729667da379b,0x000060d45ce91601}}, {{0x0003c696755ff899,0x0006b73017e6e2f7,0x000f7600ddd3cf7e,0x0007b3fef5689d3c,0x000048dc4f941fc8}, {0x000fe814ea53299f,0x0001a8eb6028d9e9,0x0009803fc2d921ca,0x0007450aecedfd0c,0x000038ae8923d7b4}}, {{0x000fccfc5e3a3d83,0x000c1079dfbfd8c5,0x000ad0197befd904,0x0002a48c6d6a58fe,0x0000922707799553}, {0x0003e6ddbef42f56,0x0003e80a990809e2,0x0009a2e407e449b6,0x0002a41b969c1aad,0x0000231d792f591c}}, {{0x00014560f6645343,0x000c1b68f1038715,0x000578ab985ceae7,0x00010c7c09c4ae65,0x00003ec68692044b}, {0x000832b3a8ec1f1b,0x0007a847d5ef6ac4,0x0003f15745509d12,0x0003c44909604f76,0x000016c4304732f6}}, {{0x00020147ca23cd3c,0x0005e391849db6ab,0x000678d94caa7a5c,0x000e639b0673a375,0x0000982ddd59d303}, {0x000000b5db6f971a,0x000ecf876f92fd7b,0x000569426bba2cb1,0x0004f8277332a33c,0x0000159100cf70d7}}, {{0x000847fdec67ef5c,0x0003633e76b7fd16,0x000c2b4c8742ee46,0x0005204b8e4134ef,0x0000a640b8702a3e}, {0x00001908ceb6aa92,0x000c347852d5653a,0x000237af7313c300,0x000af804e4ab126b,0x0000ba90162abb47}}, {{0x00058d6a8219bb73,0x000ceb06c57f3d5e,0x00057576ec691d0b,0x000dc2dae4cb10d2,0x0000569656d054a3}, {0x000aebd94cda03a4,0x0002d62bfe13e5eb,0x00051a0c6934e82d,0x000526050ac0bae2,0x000080b9e121d6da}}, {{0x0007bc58cce08b52,0x000c5f178d550046,0x00077d806b636458,0x0004eba5748baea6,0x0000763a387ffa39}, {0x000448a7d3cebb65,0x000e1f20d850a12b,0x00058462ce7adda3,0x0008a8a63ebce515,0x00008b36143b2008}}, {{0x000c3ca4d63c0eea,0x00066fe948ce8a2c,0x0002ef33b5123311,0x000d6bd463fd8522,0x0000df0c7dd1c603}, {0x0002d3bfe7765e5d,0x0008ef3804090ec3,0x00059319cccaab35,0x00034cedaa84d68e,0x00009a4c2816c80c}}, {{0x0009488a059c1425,0x0004af0b9346a9d8,0x000fb36646f5ae71,0x0006abb68f237d16,0x0000853e4c486318}, {0x0007d2363c52f980,0x000681828876e2d8,0x0004e7b1c2ec4a76,0x00040847b864fae1,0x0000c0bc0e569192}}, {{0x000681db82e9f3e4,0x000b9f25e13ce4d7,0x000f2728083200f0,0x0002274909984c66,0x000062d7b00b5f73}, {0x000a188f26517980,0x000c36ab1c34d90b,0x000f5435974c6e18,0x00002fab256ea35e,0x00003466612d1aa7}}, {{0x00060492ed22e919,0x0004df072822624d,0x000ce22716fdfe0b,0x00014f5eca111539,0x00008100a506b016}, {0x000daa2a35c628ff,0x000dd87e9a47b6b0,0x00057d9ceb6f94d2,0x000a7ad67732591d,0x000070bfeecf3884}}, {{0x0005ccfed2bad016,0x0002bda6a5c75fb3,0x000a92f8fa155cbe,0x000e4362e2594c30,0x000049c89cebbfaf}, {0x000667de9ff257af,0x0001032c50aed158,0x0006014cf9b35961,0x000d3c5b00b20b90,0x00003a8cfe479bc7}}, {{0x0003ffd248a7d061,0x0004778873fa4ff2,0x00074598180c5bfb,0x000994a7d9ad9005,0x000079c85db4db01}, {0x000b06261a6966c4,0x0002aadce5a8ba41,0x000e6a3184d82d05,0x000da05e91cd3ba5,0x00007795f4fd5b2d}}, {{0x0007c1fd55a897c5,0x000b629110fbecfd,0x00081d3b0009194a,0x0002910f0e2046e3,0x0000f3425f6f98dd}, {0x0006687730d50dae,0x000b6b083b7fbfa0,0x0009d34170423446,0x000429597a247dd6,0x0000b629f91187ba}}, {{0x00026ccd5cd79bfe,0x000ab46c6e181ee4,0x000477f580032940,0x0002773b1e8ae057,0x000094f7d354d823}, {0x000cb96782ba21ad,0x0009272b33a5c747,0x000f80c81c525446,0x0006b4a72ef6dec7,0x000073acbfefcd9e}}, {{0x000b5b149ee90d9c,0x0009e06e9eba4075,0x000f825e0785c339,0x0001dbe1030d5bab,0x0000ec684c464293}, {0x00062c9c1586e630,0x00065ab43f2b42ab,0x000f7835d45431d6,0x00086557c8b2c055,0x000033da338c1b7f}}, {{0x0007513caa760974,0x0008f6c83906283c,0x0005af2c70a624fa,0x000bfd2b20afec71,0x0000b9699752ba78}, {0x00055ccd921d60e9,0x000febaeca132207,0x000ed93d49b944e0,0x000d2674819d515d,0x0000bbff86efdddf}}, {{0x000413077adc612c,0x0008fbd803a06b34,0x0008805bda749652,0x0003ac5a1baaa76d,0x0000840390307034}, {0x0009f66175adff18,0x000b37d8c5b739f5,0x0009d75e30b26d7f,0x000cc22875f5ce52,0x00005efc7e9c1325}}, {{0x0000b421ff6acd3a,0x0003b3dc69092195,0x000766127ffe7048,0x000b2b5f4cd0b228,0x0000bdbe608efb7d}, {0x00092285e1109e8d,0x000724645b5a837c,0x000818ed826147d2,0x000a357d78f592f7,0x0000394077fc247f}}, {{0x000c2d0488c171a0,0x000a136852780fb9,0x000b1fa6aa78bfba,0x000ba7edfbe268d5,0x0000dceb8db2b7ea}, {0x00080899ae2b710d,0x0005d4449c96bf9e,0x000143a46efde7ae,0x000c1273b7716bcc,0x00007d3419593628}}, {{0x000ec1c3b3f64c9d,0x00094e5edf3f508c,0x0004318d4e20bc0b,0x0004430a1deb852f,0x000020ebe0e2c3fa}, {0x0004ea773241ea3d,0x000b8e1a5f65370b,0x000681c6261f1511,0x000c2cc9a5e23d82,0x0000731e38472f54}}, {{0x000f36e834459048,0x00092f45f9c02692,0x0007528b72e0ec46,0x000542105a3201c6,0x00008f77f3550e5e}, {0x0008d295864687c7,0x000db2df3562f67a,0x000bec39e23b92ea,0x000f8cec27014b9b,0x0000ef2f2270c0f0}}, {{0x0009638546c4d8de,0x0003b2f246799735,0x000c8acd95f9c3fc,0x0004afb12e8beda8,0x0000c3a318e10663}, {0x0007f41c31cb264f,0x000e622113f28016,0x000afe1973db82f6,0x000282c155bcd2dc,0x0000ba1da5a33465}}, {{0x0005b8eb212cf53b,0x000e48557c5fa042,0x000c4d56c4f2e512,0x00085111286ff925,0x0000b8a0feb9e26c}, {0x00070d2e7d6107e1,0x0004d76265aac28f,0x0001936b17ee0c44,0x0005eb2df277a41d,0x0000a556e3ffa959}}, {{0x000bbf9e73056835,0x000eb7ef5be6258b,0x000c814c131eea5b,0x0000dcbdeb0e4a46,0x0000cee8449f7b73}, {0x00095c5a0182bde2,0x00077e27a6b4eab4,0x000e518caee759f8,0x0003f4a2cf6a6880,0x00005e80140114cf}}, {{0x00041407e8d7a14b,0x0009e556f36a8fc4,0x000600044bb1ff3c,0x000e62ba84438514,0x0000a3f0c4b2451a}, {0x000c25b1f9af32a8,0x000631f2214bdfca,0x000b596ac01e0db8,0x000c07ce9a5bc2a4,0x00003927681826c2}}, {{0x00032e77acaca28c,0x000707385b293ec8,0x0001eaf381bfeea5,0x000ccb468212e3fd,0x000013298312acf8}, {0x000f2db2aac9e59d,0x000ce661782ab909,0x0009b7a015748060,0x000625f5ab2632c7,0x0000a44c6c6d0017}}, {{0x00000e8a7ea82f03,0x000db4299aaff26c,0x000d78be199cac80,0x0002cda66fe3b67e,0x000005f725f948d0}, {0x0001bc4623fb21b0,0x000e7a6319ad33ed,0x0005ffb3efa70533,0x00074117ab562dbe,0x0000637499456674}}, {{0x0004ed65c46aa8e4,0x000368d063d169d4,0x000d17c362100d5d,0x0003b78b9727eaa2,0x0000c2bab1bcadd5}, {0x000e90c15426704a,0x00030837ebeaa084,0x000e477f8778afcd,0x000a8ac651f7017c,0x00000624998e6fb7}}, {{0x0006828ed8a6e19d,0x00057189d9c7dc1e,0x0001c39bc33fc233,0x000914326f8fe267,0x000040c4cce8c6f9}, {0x00035bbf80e75ca0,0x000022adff2cafa1,0x00051ad9612c651a,0x000832c40a04bd4f,0x00004820109bbe4e}}, {{0x000eb1a7f4c04cc9,0x000119404f843667,0x000ceb50a5955662,0x0005f9e1cdf6537e,0x000094a44a72b833}, {0x000f819dbeb9b690,0x0000eed4350dd7fa,0x00044bba2473c568,0x000bf3b6658466da,0x0000d1bc780872bd}}, {{0x000f175a1962f910,0x0001ed58f5a7e535,0x00089a2336ed7e06,0x000413177aa4c020,0x0000dbcb03ae539b}, {0x000424ebb32e38e6,0x000f0806701ee3dc,0x0004be9ee6472e5e,0x0000097d47ff9881,0x0000b60cfff95ace}}, {{0x000d9319ff91fe50,0x0000f0518eedb8d3,0x00082cb26039c480,0x00068d95c3763291,0x0000763a43482fc5}, {0x00004d5383e76ba9,0x000ff24e8197707c,0x000230de0ac98b92,0x000b7002bf7c8f91,0x00000876a01d0959}}, {{0x00096f305968b809,0x0002789f73b9db6d,0x000c61e01380a091,0x0008c6eda70b83c2,0x00005fb8394e69b3}, {0x000651280edfe2f2,0x00096faeaf829a3c,0x000424bf88f726bb,0x0009706010a4a078,0x000096720442e844}}, }, {/* digit=1 [{1,2,3,..,}]*([2^7]*G) */ {{0x000cb817a2ad62aa,0x00090c62ff5463c5,0x000ad9db57ef2b6b,0x0006169749bba4b3,0x0000d311f2ce6d5a}, {0x0008087c2ff3b6df,0x0002467834ffb77a,0x000d6b138b46feaf,0x00018808aa266d75,0x0000a38d321dc008}}, {{0x0008ffa696946fc7,0x000849cba56d486d,0x000f35a1550fbc6d,0x00062c0e3d423e90,0x0000c3da19630dd9}, {0x000fdb03cfd5d8b3,0x0002589dfca5e673,0x0002305aa0704b7c,0x000e53c6ce581ff5,0x000099d49ebc14d5}}, {{0x000496d6ec293cde,0x0006ae7051f5380a,0x00049140a733dbda,0x000bf5237e388db8,0x0000e4b32b13946d}, {0x000fda9cae368d14,0x0000bdb0b2f3b1c4,0x0003ac46e5001a7b,0x0006562df593742e,0x0000af675f279b3e}}, {{0x0008110399492969,0x000aa61db1b544e3,0x0006eaff55b63827,0x00028fae5323ed20,0x000042370d3521f4}, {0x000af2ee0d985a17,0x000b0239846df2ca,0x0006312f8192cc64,0x0001080c0b8f47ae,0x0000dc61f9206620}}, {{0x000fb5bc2da7de94,0x000ecff8d3beb830,0x0008a9641d0e643d,0x000501f1ee77ba18,0x0000e8aa3aafcf6d}, {0x00065329a49110f0,0x00062dd6b220f9fb,0x000c3ea5ad18317f,0x000c4a7e3ced4152,0x0000d296a147d579}}, {{0x000a53eed4c37174,0x000efd0ed2a335d6,0x000543aa59f8240c,0x0004b44c0d4d05e5,0x00005d5bbfc1d33b}, {0x000cc73137fd28e3,0x000f973b3ffdfa04,0x000f51ef2862ac6e,0x0005a2103ff9f531,0x00004d5e0fcec73f}}, {{0x000682008913f4f8,0x00016ac93d95f252,0x000a6b26cea20ed6,0x0007afd1ed38b46c,0x0000662dcbd6a432}, {0x000295c725d2aaaa,0x000eee52dcda6daf,0x00017daccbad2752,0x0002318210e7210b,0x000037f7913751e8}}, {{0x00081e144cc3adda,0x0005e7be82cf4f70,0x000dd6472d5ffa1d,0x000862e9890b6c0e,0x0000da26e1aded17}, {0x000271563483caaf,0x00083f6077fd276f,0x000466e3ce6924cd,0x000d1e15a7fe980a,0x00001c794b1a1902}}, {{0x000368882a8042c0,0x000fcd278298e521,0x00097a740d931cfa,0x00007c069a0ae0f5,0x0000adbb3f3eb591}, {0x000951e5eaa8eb87,0x0004a1b48e78983e,0x00003f2c5e663a8b,0x0001e1a631cc0d8a,0x0000577c11e81e27}}, {{0x000385c08369a907,0x000aa90eb4f833b2,0x0008eac802990c59,0x000014119a6145c6,0x0000a786d629ec4a}, {0x000adbe20ac3a8dd,0x00008aba2d3033fa,0x000a4f56531a2178,0x000fba509d2742db,0x0000b2ce9e425aa0}}, {{0x000334b168984df5,0x0006e38796388cef,0x0003720f0e81dce1,0x000beca6e6949c26,0x0000c56feb04593c}, {0x0005601fde58c84a,0x00068eccb3148bff,0x0009a8a7874e2411,0x0008681cf01b614c,0x0000233e35ef44c9}}, {{0x0006bf38bd7aff18,0x000a9d81b146b315,0x00028a9151b5ee4c,0x00099dfba1ac41d6,0x0000f3a8f9d7d896}, {0x000b9c9a0748be7d,0x0004d92e621f7329,0x00010a8371d391c9,0x000435151e6b214d,0x0000255f53b1947b}}, {{0x0009e04f1788ee3f,0x000eb86938a20766,0x0003a01c0c14f27a,0x0008079b47a334e9,0x0000f627439c9366}, {0x00085d8ca2a59655,0x000286e9b9b37a09,0x000f972e83d9a554,0x0002fd723eb80b4c,0x0000c1c33bb9fdf7}}, {{0x00058d474a861082,0x000fce4c5d900c4a,0x0006d4c80f8048a8,0x000e60c3c7c924e8,0x00008c889de256a1}, {0x000662eb214a040f,0x000747e1034757e2,0x000ac748ae8c48e9,0x0006f19774286280,0x00001c24023086b0}}, {{0x000d4c35f74040ab,0x00014ceac957ac2d,0x000c4ec23409aeb7,0x0006eb9fbad78255,0x0000359ed623a7b7}, {0x0004926ed6f4a607,0x000edb912de31274,0x000705a59e21e8d7,0x000c0e72575a59fc,0x00002f1d4df5d2db}}, {{0x00024b9eb7926b83,0x00039dbe55093d2b,0x000dd640bbff88cb,0x000d45a0f399afe4,0x0000c5fe1305f76e}, {0x00062f43764fb3df,0x00074151b62d6f35,0x0009ce5f37b5af31,0x00090ee5bd0bc7d7,0x0000daf6b21dc668}}, {{0x00067ec6063540cf,0x0001f5f9cb8f735c,0x00099c6ab50b259c,0x000c84c8734f9a3f,0x00008cc13d693a7b}, {0x000b305c52176597,0x0003dec12a5480c1,0x0001345fefe5364d,0x00097f4d87045e68,0x0000f8efeb1c82f8}}, {{0x000f1e5d59233595,0x000d039b9fb0e8cb,0x000859b98db0cea9,0x000cc5bc5b34cf49,0x0000e583c56f4403}, {0x0001a2dd48185b77,0x000dfe52178711fc,0x000105b8bc93fbc7,0x0000c7d7e7a05805,0x0000b4d4d594b826}}, {{0x00030b046eb842ab,0x0009cbdae56de339,0x000f7fdfc8e844a9,0x00017584ef3a9e13,0x00003768f83136ca}, {0x000f4e04e09e61c1,0x000190c7cddc2821,0x000945fcd414dc3a,0x000ff1c537943754,0x000051b6eefc3555}}, {{0x000d6136339c0831,0x0005cfb64701b31b,0x0009604ab39ff815,0x0004426c3388d2e2,0x0000e19084bb6b10}, {0x00054c0eccd47ef9,0x0004ba5dfb3017cf,0x000daf9f68969338,0x000958d9d023fb47,0x0000222840c0d91d}}, {{0x00008f5803bac625,0x000ce79bd45f4391,0x00063c5810b7dd91,0x00004f8651e827ca,0x0000c5d75f6a09c1}, {0x000c7381f2dc308f,0x000ee98454be7d5f,0x00017b03120faa7b,0x0002aba5374beea5,0x0000036b9b254269}}, {{0x000610939842194e,0x000d69d05295c510,0x000b42ee0b7e2353,0x00011c1c8c1d5cef,0x000004884ebe8ce8}, {0x0005d817419f40e7,0x00023995c241f1f7,0x000c556465b0ac16,0x000f96a20921bbc4,0x000013520c2fd33c}}, {{0x0005a5ce98c51002,0x000d0ddd0f5ab4a6,0x000a2e78b6cec871,0x000a5f051f0b7f9b,0x000024a8434ee3a2}, {0x0007f6125f5c46fd,0x000b78545ec02682,0x000bb5cdc6a22bed,0x00098e55ae5fa0b1,0x00006936830ccb9b}}, {{0x0007fe891e5d7d3f,0x000683a076783202,0x000dfdd61f14b7d1,0x000f48088497b3c0,0x00007c2eec11a8c4}, {0x00073f43756e621a,0x000f7825b948aa55,0x000878572c013a23,0x0001837c03b34563,0x00000472beb053a4}}, {{0x0002e270ac69a804,0x0005b51e54f6f422,0x000ffa59134096d2,0x00027ec0a648cb8f,0x0000e87acdca9b65}, {0x000e037e285ccb47,0x0003e0ddcf520575,0x0000ff719188089e,0x0003693a96c9a887,0x00004a56cd88fc7e}}, {{0x0004ee21726931ae,0x00075660ecfd41d0,0x000818e180bbbb2c,0x000886c6ef6de524,0x0000421cc52c7d57}, {0x000d208bea87be65,0x000361cdd682f127,0x0009b63f716a475d,0x0003b64db1b68443,0x0000359b3dc40f11}}, {{0x000f1de8bf06e31d,0x00040d383901dfcc,0x00017e7d21fdf8f4,0x000eee40775cad50,0x0000fc3a59828d11}, {0x000c8a0b1ecff106,0x000bc84005496ec9,0x0004f8d73ee6ed6c,0x000ab955ad7bae1b,0x00001b4f11e400aa}}, {{0x000d69bd4eff2d71,0x00013288b60f7b32,0x000a1e72388ae677,0x000e8c059461b437,0x0000f3d4789670aa}, {0x00018c07f9871da6,0x00089635e2788691,0x000541dac35fbda7,0x00045f138f3641e1,0x0000794b13b20dae}}, {{0x00064ac09cc0917d,0x0008f68540fd0650,0x00022767127c5372,0x000a033d2d4c8eef,0x000023a9f8171785}, {0x000952852650359a,0x0000d4a1acad98c5,0x00055bf5cfa09ad0,0x000083682d5a290b,0x000040f1c67e19b8}}, {{0x000752edcc18770a,0x000ee825c3a53a5c,0x000b153ed4baf1f2,0x0007234bd63f7421,0x00002383e4852f64}, {0x000620a2646d19a8,0x000b83c83ffde7bf,0x0006be9f156cb44e,0x0005e92f7267c94f,0x0000b2dfd7c406bb}}, {{0x00072f2a672c5c73,0x0007dd53c5e2b870,0x000435932eacb11c,0x00093bf2dac29dff,0x00007bdb99d74086}, {0x0002fb62899c20f7,0x0001d47ece24f6e6,0x000577ce33535d51,0x0005f28bdc6b88ff,0x000026693bd89057}}, {{0x000b0e5ab4b35a24,0x0001b5eeaacf6772,0x0005b95801d8b600,0x0001da328f7ce479,0x0000a20ed2a81fb8}, {0x0005cd44fec01e63,0x000c77ff50ad9f68,0x0002d97fd3ed7ddc,0x0004f9160fd2640c,0x0000a2414271b82f}}, {{0x000df2c6a8ea8208,0x000b722cc25417d1,0x000291426b2b50d3,0x000e3883856cbab7,0x00007fd26ae84f5e}, {0x00096cc02bee4ba6,0x0003a6820fd69cb6,0x00012e9855312180,0x000a0945dfc26902,0x000066f7ffa760f9}}, {{0x000cd33bccd9617a,0x00041a7730a3c503,0x000db0786365dede,0x0003bbd98c63555d,0x00006c3200f9c9cd}, {0x000fb2ce5e35efd0,0x000b5555a1c1060f,0x0000b375199a4e25,0x000bf611d95375f7,0x0000a57354a160e1}}, {{0x000ae4bf8e4b0651,0x00041e53022becb3,0x00092ed9607a834c,0x0004ec0cd300b386,0x00006a6f79271ee1}, {0x00063c66a8649edc,0x000dc69f3e148f10,0x000a7b3ecfbcdfcf,0x0002f06cfb97c100,0x0000ea49b3d3130c}}, {{0x000044fe9d964888,0x000e0182a0c1462d,0x00091e9e94b53d52,0x000a0904b6ddd303,0x00000ab7b4931741}, {0x00015d427d3317fc,0x000a5a64671eec0e,0x0009c5b928dfc1dd,0x000330d3cc5d5fd4,0x0000995d53df674a}}, {{0x00041ec090090ae0,0x000cedb06830302e,0x000c996902278a0c,0x0008da1d025932fb,0x0000c32fbd2b80d6}, {0x00046daf341a6c11,0x00090bef68a0d791,0x000774b3aae0ba13,0x0004d7b6b8a5638d,0x0000cf307bd980ba}}, {{0x000bdc719803511c,0x000ac888c3bec033,0x000c6d05ea9f97b3,0x0009ea7d68aebc85,0x00003b88a9dd9391}, {0x0000748c48b0ee35,0x000bb7a746c12d30,0x0006d57f37506bc7,0x00091aac48437c6e,0x0000bd715881feaa}}, {{0x0000408c1bc52257,0x000ab719226da4ed,0x0008d2d43d0b946d,0x00059aa09ecd6275,0x00005c8485a97517}, {0x0005f499ce4177a4,0x000e39c10c3db0b7,0x00067fcd74fa61a1,0x000fa88062d300a1,0x0000df3874cb50f0}}, {{0x0002cf983dfedc91,0x00047d87631a29ae,0x00029c8d2f843713,0x0002729f57171174,0x00008d15867246d9}, {0x0003ecf69769bb7a,0x00062479ab828305,0x000b0f4b2c55eb85,0x000524bef7791c21,0x0000a5956badd491}}, {{0x00096c29fe20ebae,0x000b052a5ad3407a,0x0001d9d89f27168b,0x00027963b60ab3bf,0x000045c51f0510e7}, {0x0005276099b42210,0x000c2557a159dfca,0x0000358958dc6407,0x000c320ead833591,0x0000a9db9579c55d}}, {{0x00036d3df61bc767,0x000fcf778cdbe407,0x0006ea28f13a619b,0x0007b3fdd921a4c5,0x00006a524339fa64}, {0x0001891ac5bdc5d3,0x00028ac7dc012359,0x000df8453ff4a1a7,0x00065f6905e26162,0x0000ac045e0163b2}}, {{0x000341bad53dba78,0x000c037b625a8a3f,0x000e311898ec269c,0x000120571a27823a,0x0000fb4f9a3d5e96}, {0x000f823ff9875cf9,0x0006cd442a9b804a,0x000c6267923224f5,0x000db08c4d3b9eec,0x00001da22fc30e7d}}, {{0x000324d6c04a661c,0x00059e376d17a370,0x00044e3579710d3b,0x00001c2d8c98f030,0x0000364ebbf24227}, {0x0005d517733d61c0,0x0009cea826c3347f,0x000a25548d55644b,0x0000a780c6e0ad55,0x0000aa7641d84422}}, {{0x000ec81318106601,0x0007ce4b40431438,0x0003e02739dfa650,0x000fb200b515d8cc,0x0000b6066dd38d8c}, {0x00045919c9efebdb,0x000ef21c1ff4d3b0,0x0007607d3425d4bd,0x000083afe5af19d5,0x0000bf773f804481}}, {{0x000bd6994b03ed1e,0x0002834cc5468435,0x000e420cad9ad1de,0x0006dc4cf423fc00,0x0000ed26d8180309}, {0x0000be7a4db09d2e,0x000cb60622f7d7f6,0x00096c729f47f569,0x00071505925fd772,0x0000ff2db2706ca2}}, {{0x000d014b913e759b,0x0005dff4de93a6fc,0x0002068e153da478,0x00052d64616d79c3,0x0000187d6657cdf3}, {0x000b6501dc90b596,0x00031daa1b26f7af,0x0000c0a848170e94,0x000dfa68e3bdd870,0x0000e8d345fc482b}}, {{0x000bfa1c5c5ea50e,0x000b8796068184cf,0x000d50942d3baf14,0x000662463984030d,0x00004b7839d2716a}, {0x000f794e7de6dc08,0x0003e22aa7ced5f1,0x000acfeec5cd0f4d,0x000606d295f3f159,0x0000d933553153e0}}, {{0x0008ec5776c57224,0x0001eb5f290cc7db,0x000f425a9dc467e6,0x000b7294297e704f,0x0000be924c14cf7b}, {0x000c5aea18921310,0x0003a705c9920d5d,0x000305ac58bf8a8e,0x0007a873a0b0647a,0x00000c9ca4e9a8c7}}, {{0x000e80f83774bdde,0x0001a57344855dfe,0x0004a69a96313160,0x0000d6c1b524ae91,0x0000bc2ffb0b4e30}, {0x0003db77cfa46a5c,0x000e61653b5052c9,0x000bc580a71e6161,0x0002527574fc57a4,0x000009015dea1bc1}}, {{0x00047b2d174d7aa6,0x000893a15d044b7b,0x000fa07ed4072d8e,0x000fb18eb7d47fd6,0x0000f2b9ffa4dbda}, {0x00016153760fe8aa,0x000f506c6c1318c5,0x000a2d0717a96e6b,0x0005cdad7a04100e,0x00001914e9babe2a}}, {{0x000e357d8a3c5cf1,0x00031abb2b135726,0x000ae88dd1197ecc,0x000efe5c0d7f7f31,0x00005b20d1b0dbb3}, {0x000aa26705840398,0x000927dc9747cd06,0x00055d8152277c96,0x00032a3ca6958778,0x000099ea238d188b}}, {{0x000228b760c1c9d4,0x00015b5c18da37d9,0x000f6dbc5c7efbb1,0x00005b3f0d1bc819,0x0000875384b47e69}, {0x0000baa3ba8cd86a,0x000b22905de0c7c5,0x000231952b0ce40f,0x000e25d08406737a,0x0000912a2636f43d}}, {{0x000ddcceb5b76c16,0x0004c6fc0ab49c38,0x0002c269f746f528,0x000620f2a63a50d6,0x00000049c55f9458}, {0x0008f823c2f7c9eb,0x0002e17d5cf3e7f4,0x00001f4696bd9904,0x000fe03b1317a887,0x0000d3fe2ee4a449}}, {{0x00079ca12ef3d36a,0x000b9e7ea5de421e,0x000ff36f79ee3c36,0x000228448198b5cd,0x0000ff4f96866b82}, {0x0009dd0c47adb7e5,0x0002b32e7dfa15e1,0x000ae026a45699b2,0x000f4cf0680c8b1f,0x0000a347a48a50db}}, {{0x000533b3cef0d7d8,0x0007abbb4381e652,0x00080f500d94f7b1,0x000bfb038752be0e,0x0000e6e24891e9c9}, {0x000169716caca6a2,0x000818531ad9c975,0x00051ade1866c49d,0x000407a917e23971,0x0000d016ec18037c}}, {{0x000ccc900eac3f90,0x0000e2ed4748a407,0x000c98e0d835f628,0x0002ebcc54c3471c,0x0000e969937dcb57}, {0x000c8e88f30c9cbf,0x0004473c46611b16,0x000502caba606ae7,0x00064e57aa689b35,0x000089014af3d9bb}}, {{0x0006a9c31c71f7be,0x0002496ffe5c202f,0x000cec3a301f95aa,0x000a447fc0601453,0x0000b9912383f498}, {0x000935e5d91ba877,0x00009b564a19ae9a,0x000d44e69c6ac628,0x000d451a8fe81c3b,0x0000c8b46800dd11}}, {{0x000251fea5b8e69b,0x000d15b75fbcf772,0x0007ff0e5aeecb3b,0x0001306aca333188,0x0000e5d49ffc9f0a}, {0x00013aae5c8646f1,0x000810e19980582c,0x000abbd94dbaa12e,0x0006637f40f31af7,0x0000f13f5a82dfc7}}, {{0x000f1eeaceb4fc02,0x00023e6f0f425d81,0x0001370c83625600,0x0005892b67d6d775,0x0000608b69823e80}, {0x000d2fc05268301b,0x000890309212cfc0,0x000d0e1c2a6943d3,0x000c75692a90c21f,0x0000209f113e7f1d}}, {{0x0005e0697bf1298a,0x000f819d639eefcc,0x0001e8c6fcbdb672,0x0002e53009c116b8,0x00003ffdde3ba7ce}, {0x000baaaa914d3ba5,0x000f38df85eec53f,0x000ee0751836d500,0x0006fd898dc71b66,0x0000a3d7005c1451}}, {{0x000634d39eedbbab,0x00075455a46d21d3,0x000d7eb0c35cd2e6,0x000b3e18cafe65f9,0x0000da3ce9eb0cef}, {0x0007a602c9cf7a47,0x00040bcb8773ddc1,0x0007548df01572ee,0x0000e3392b2b018c,0x000032fd30a18460}}, {{0x00009c716543a402,0x0006dede3c6ce221,0x00024e6149acafd3,0x000ca0db20685268,0x0000a4544a9fa25d}, {0x000526291d60b063,0x0008f87535452598,0x000f13b27281b7be,0x000eb4bc667b1a90,0x00003a83affc40e2}}, {{0x0009862d5d721d5b,0x0002abd3a1828000,0x000a2cda40c3357a,0x00008477f3a83b7a,0x000058ae74fa6f83}, {0x0001a812e6dad6be,0x0001143d6c5b2a91,0x00096c4d8de28605,0x00024d6bdccc41f9,0x00007312ec0eae1e}}, }, {/* digit=2 [{1,2,3,..,}]*([2^14]*G) */ {{0x00012e76e6485b37,0x000b071c52f8f8d1,0x0004a2f6d4d3e24d,0x000550d8e3ee4168,0x0000161957d91d95}, {0x0001283cdb12a6c3,0x0001fe50e1641963,0x00066cc73bf3fa88,0x000c38c6254b6331,0x0000aefa7aedee8c}}, {{0x000fe623b36f9fd2,0x0003dde19fc079b0,0x0008482ef26543b2,0x000824f36e64a095,0x00003f63771bb095}, {0x000d596b6a1142e5,0x0005e35aac0b14cf,0x000081dd55ea6aac,0x00012a36a0e8bdf3,0x0000fb89d79503dc}}, {{0x000c33af72e34d46,0x000fb10eec35f615,0x000dea34e0bd9ea3,0x000698bc12bc5bc1,0x000086584c9a9ae4}, {0x00095d38c97b942f,0x00095e5c756213ad,0x000737f894609561,0x0008b5ae94a4aef2,0x000057594c7271c7}}, {{0x00065fce3779ee34,0x000d7d495d9e0f01,0x000284e7ae00e7f9,0x000218dfa4efa220,0x0000564bade87ac6}, {0x000312ac4708e8e4,0x000b671e9adf90e6,0x000684b9f4f5725f,0x000415a95f55ae3d,0x00007f7ccb15e94b}}, {{0x000851b8d9465810,0x0003bdf4a0127322,0x00084dae0f0d1313,0x000c6da3510f6965,0x00003a7c1713c9f6}, {0x0007f38e475381a1,0x0002758233345be9,0x000e17ddaca1ba42,0x000c0fe83cc5c70b,0x000058b14941b918}}, {{0x00077e5522e6b693,0x00038bcd6c18da3a,0x00024fd5669c908c,0x0003f6ef1b9e48d9,0x00007c64e36da4bb}, {0x000dbdfee478d7d1,0x000bf193f7a05a4f,0x000cd16dfba75c8b,0x00015174bc1e8456,0x0000fb08f0856fad}}, {{0x000abf9842e9f302,0x000f3eab83af8a7c,0x0007f2a6aa331d4b,0x0000e3b272cfba01,0x00007560abca3aba}, {0x00033870e3a6b750,0x00026b9f50f594b8,0x000fdf6d025c6aea,0x000514803d691db5,0x00003b77509e6333}}, {{0x000890361a341c13,0x000fdcfd61423617,0x00033316c3604dc5,0x000921d22295eb85,0x0000dbde4ac74af2}, {0x000fc5d1c7eef696,0x0005714f4fa1898a,0x0003c21ca5889680,0x00030aa500216020,0x0000f0d1f30a0ef7}}, {{0x00044d4196224f85,0x0004e74d079d8e8c,0x00048f12375a4ab9,0x000ad829085ecc7d,0x00006f04d316bf65}, {0x000bf1cbda602b24,0x0002b9612c69e220,0x0004fd06b73ee174,0x0000d136008fc808,0x0000000efa031138}}, {{0x0001b4b12cfe2978,0x000ba92f74e54820,0x000e874e83eee129,0x000c4161fe114ec9,0x000099b055d12c5f}, {0x0007a643a39c8cf8,0x000df8963cc94e47,0x00033f86382f09ef,0x000c62efd3fd8fd3,0x00005132b2b5c949}}, {{0x000a3ab516eb17bb,0x000f22c7372b7e06,0x000896da673bec06,0x00040f34f74f55ba,0x0000b4afef93e9eb}, {0x000bec8e61d66b0f,0x0003ff29300b2d75,0x0006baa5a02bda4b,0x00043f9bbaa8de02,0x0000f54befe907f4}}, {{0x0008b1dbe7a2af37,0x0008dfb74a72bd9b,0x000879697ec51caa,0x0007d549937a4b63,0x0000c9a9d215c268}, {0x000e44f6ef5f0145,0x0002990c69001773,0x00042161e8abcf41,0x000f29e87bd02281,0x000003937564cb6f}}, {{0x000fd56ed6def63f,0x00018d53106c9813,0x0001f7ac153cf648,0x000faea91a35bd43,0x00001e274de53e65}, {0x000fa3c44cc78808,0x000afc256981f63f,0x000a420e0411a426,0x0008fe3698b9fd93,0x00009fdddc12e53f}}, {{0x000072232398baaa,0x0001bcfca031766e,0x000029cf2205fee4,0x00090d049f53417a,0x000088c68b8e0238}, {0x00050417337aaa82,0x000ceeb384f4bc27,0x000aba92f9ed364a,0x000a88c0816f8529,0x0000e9e194124e38}}, {{0x000f44a3dafd2d50,0x000597ed98d857ee,0x00007f9b135d1fae,0x0005c650628c0923,0x00009d84aaed6cba}, {0x0001bc788aaa6917,0x00093fe6cb036707,0x00078ac012dea57a,0x000a516fe11bb43d,0x0000286418cefd7a}}, {{0x000770977f7195ad,0x0006ddeb838ffabf,0x0004f012d8ec8616,0x000b3f1a1285a8bb,0x000068835046a3ea}, {0x00024f8309004c28,0x000593ffe95eee5d,0x000223ea4a96e4b7,0x000a528cdffe12bd,0x0000f5c2ee636739}}, {{0x000aaa5dd968198b,0x0001c2413a6c5cb4,0x00036d903fa131c5,0x000d8da3d46a9095,0x0000270f0d3f8606}, {0x0007564a053a3bc5,0x0006ca86caef518c,0x000b5efd0088254b,0x00045d63ba8cb40a,0x0000c59900e96059}}, {{0x000e1dda1887395c,0x0005d32a65deecac,0x000a9552940960f3,0x000a35d611ff5c3a,0x000058215b13c1e5}, {0x0009b58f0e1a5240,0x000bf590dfb8d48c,0x000d95662b406856,0x000f82c7605e049c,0x0000dd036eea33ec}}, {{0x00071acc33156b3e,0x00096a80172ea501,0x000dc8eeff09d24e,0x0004ed6e1f72c676,0x000060caadd3e3d4}, {0x000f8a6979b1d8f6,0x000c37788d26006e,0x0006feec060908a1,0x00094e0e08f95b26,0x000018427c282e8c}}, {{0x000333959145a65f,0x00080a4063373d61,0x0008a52a0cd9bc36,0x00058f92d11be32d,0x00006877b2887a1c}, {0x000819bf5cbdb258,0x00085e090249837a,0x000990e5f2a4fd1d,0x00011ae22a7de774,0x000040fa5a0f9455}}, {{0x00074be6558842d7,0x0003a7f3d0a630b9,0x00042e46d70df8c6,0x0008230c80352075,0x0000251fe8054ecc}, {0x00034cb5e9aac9a8,0x000470045d71e591,0x000cb1d4e11bb093,0x000c90d3e5d9b5db,0x0000d97a90612def}}, {{0x00093277946d3f97,0x000397472273fe28,0x000b6ae86e132bd2,0x0000677eeb510c1e,0x000077708c660595}, {0x000c8cd1297029e8,0x000c3bf9305e18e2,0x00085d6d92c61095,0x0005306466c2586b,0x0000ac06c375a1ea}}, {{0x000dc39a13046683,0x0004d7f89606a365,0x000c7228de4a9c88,0x00030335a4898fac,0x0000e2347ffb4ca8}, {0x000fb77ea7d23a38,0x000ce72a71cda5f6,0x0006a44d32fac257,0x000d79e908bef87e,0x0000ff87567091d3}}, {{0x00090b36b0cf82eb,0x00057615b5e7e58e,0x0009c145a6438d24,0x0001ca57b1f8fc66,0x00000d8b2dae6f1e}, {0x000dadbd9184c4d2,0x0005d93d997654d5,0x000147d473dbb18d,0x000608ea3e0f56d1,0x0000afa8c8dc0a48}}, {{0x00053e8bc36742c8,0x000e6ea0ed902753,0x000477b00898f427,0x0001e2a6f4947e3e,0x0000ad8848ab0874}, {0x0003c38d74a2a464,0x00095ba17ba26c70,0x000b9a9e45e3e05a,0x0006ec81fa6f664a,0x000074a2d9a7841d}}, {{0x00039ad653ae3263,0x000a774cbb438712,0x000d4c08314bcf72,0x0004af5737650e20,0x0000df86536410ed}, {0x0006fe7b53ca5557,0x000d3bd5d538d2d8,0x000d38468688cb00,0x0007b65f81bda31a,0x0000ccfe3cd60116}}, {{0x00047e06c4c1fe61,0x000a198bbb79cf4f,0x000d45a14557e1f1,0x0007c4e93b974f30,0x000074a1d2d1baf9}, {0x0003b30c51fbf539,0x00015e68b2257a00,0x0000f4173d894099,0x000152cb0aa7b71c,0x000075797ca320a7}}, {{0x0008c07e3533d77b,0x00097e341c9926e0,0x0002dc4edd7222e6,0x000cf7ed60ec3d8d,0x0000dfe0d902c476}, {0x0009ab61d056605f,0x000596a8551f1fe5,0x000fb8d8ca9ea9df,0x000b0f9489941e47,0x0000eb874ec3a7f1}}, {{0x000ea867ee0d98fd,0x000b0bf61864fe5f,0x000c031d4201ad34,0x00082175d8fe4737,0x00005f49faf495f0}, {0x000b291c7f4a40c8,0x0000f30ddd92db0f,0x000d769872e69d9c,0x000b86f54e105449,0x0000a24911df662d}}, {{0x000181060a716760,0x0008f66a8ad161fc,0x00017231ee852d1a,0x00011f172bbd6564,0x0000d6de7bd3babb}, {0x0006f88c8e347f89,0x00070bd99cc36fde,0x0000769501c58754,0x0003b9e8e54ed034,0x00007f0f335096e8}}, {{0x000e1ce4924867ad,0x000f90b84917e4db,0x000b09a79bd5f51a,0x0003d7675300403c,0x0000b3fe0f9cf174}, {0x00094d8556fa9db6,0x0008c3412fbfed78,0x0007b9291fa26216,0x000233f63be0dbba,0x0000ca8b8c06c9fb}}, {{0x0006aa9bd7638026,0x000005303da1ed40,0x000e62ec4c21486a,0x00033e01ae291ec7,0x000022a04933f993}, {0x0000c9dbb7a8ee0d,0x000b9c01aedb7fd8,0x000be74ecdc2ed3b,0x00071e65c35a1208,0x0000540cb1b169f6}}, {{0x000ed4ecf84f6c7a,0x000b8d090f43d16c,0x000239db48561fb9,0x000d93de693d796f,0x0000736f92917bd0}, {0x000d9292c1950ee1,0x000346dc11b307b4,0x0006a878eda17754,0x00008a95dfbbaa7a,0x0000c70cb295decb}}, {{0x0008c8b6f0f7c500,0x0008854dcc6dfba2,0x000b78642a8eba2b,0x000adf5ff8e89a36,0x000070c1c8ef6873}, {0x000c3716484d2e49,0x000e7d414129bbd3,0x000d93b0bfb78318,0x0007f69621a39c6a,0x000079d74c339e91}}, {{0x000564761fb04286,0x000a5ee624d4fc19,0x000ae86fd4d78954,0x000b13594896e0b8,0x0000667ac0d291c8}, {0x000051243bcf832f,0x0006b00101379f18,0x000ba8aa7fbadf8b,0x000e84d69b4089b3,0x0000ac4baced687c}}, {{0x000088d977eab403,0x0005f760b3909164,0x0000dd55351f4c5b,0x0001c9a238238f34,0x000058566c40b1d3}, {0x000d69e5068f5ff5,0x000c8aff6b063a5a,0x000debff0f31435f,0x0003315e549a5bd6,0x00009e5f0b7c5e01}}, {{0x0002fb898559acf1,0x000e3db79b505d49,0x0009f66aa96018c2,0x00014f45f4a48f60,0x0000943b3af5900a}, {0x00096df15a40d39b,0x00039c20f7c5c224,0x00098404cb2a4468,0x000b76c6a35afa3b,0x0000ec75726af5d1}}, {{0x000a163bea064441,0x0002e724b6f2b67a,0x00038c8ab27e95bb,0x000e172c20e3e9d2,0x0000213754eedd6a}, {0x0001020716e0f742,0x000edfc095c28c43,0x000ac29326679c82,0x000a760eb3adf4d0,0x0000cc970d321bb7}}, {{0x0001f2f740f0e66f,0x000a3b6b23cc70c7,0x0000a8bd7545c616,0x0007215528cfcbb4,0x0000f8396341ab27}, {0x00027d9025ac99a0,0x00002b63e33b0491,0x000d84519d314d4a,0x0004bac8c310e728,0x0000fcb8983b3bc8}}, {{0x000226138634818c,0x0003f44c2e0b2cc5,0x000dfdba3501814f,0x00018c37e181aa54,0x0000fd58ff1a7597}, {0x000db14d3b507a84,0x000e850bdad8f90c,0x000e5f9aa57bd478,0x000854e9c197e250,0x0000db6eef9240bc}}, {{0x000f21ad1fc0654d,0x0002b1269d732cc8,0x0007f49f9c71cc96,0x0007931cfbb20407,0x0000de925729a56b}, {0x000d6a3f97ad8f78,0x000f124de3bd9abe,0x00040a800e6c19d3,0x000f070dce92f4a1,0x00005f44d1e9337a}}, {{0x000c08b09d64c52b,0x000f45df97495953,0x000735f7da1b5e49,0x00076a836a8fb852,0x0000332b6dc4add6}, {0x00088a0b4511aa47,0x00026bd5cc55558b,0x000cd52bd0978875,0x00096aa6b43b9cd8,0x0000f0bc5a132a26}}, {{0x00012d4c11f61ef0,0x00043a83e79e146e,0x000bfca159ce1075,0x00053f08ec73d96c,0x00009ff29ad5b496}, {0x00072bde7da946e1,0x000bde80a4f2e31b,0x000598ce4ebf9eb3,0x000e80c1aabd0817,0x00008b5fef463f37}}, {{0x000cdd35958cd79a,0x00047d373114d5d5,0x0009357263580a1b,0x000760036e4c91fa,0x000038c534e8f20d}, {0x000e40a2ff5845be,0x000cdd78177f7088,0x0007f9920e5bb40b,0x00005c6f06a7a885,0x00003cc3e51c968f}}, {{0x000b7fee5682d265,0x000f5ec7f87c1d68,0x0001951ab5206f76,0x000719f111053004,0x00008ec52c224b5a}, {0x0008f990f75cf9ae,0x000eda82d0d5f348,0x0008895abf411951,0x000b1347ee75be61,0x0000ae060d54d8aa}}, {{0x000df737fb54dc25,0x000ad59636499ae1,0x0000550811f3e391,0x0009bcd42ec32afe,0x0000bd450efd491c}, {0x000fc67981eb389e,0x00075a0550d5367e,0x0003ce75ced7e192,0x000522562e776bab,0x0000890e308ff24c}}, {{0x000b682feccef760,0x00058bba6d92b961,0x0002375c48b8e11f,0x000cfa8f2ccc4c2b,0x0000d7f7a52e2f86}, {0x000d30a9efe5633d,0x000a8451f934fd94,0x0004e6a002d8d246,0x000c4f5234c6e324,0x0000e2b5b0eadec8}}, {{0x0003c5abf776f5b8,0x0000e0357b052ce5,0x000bf3f7a6f72407,0x000a9f3259371771,0x00007d2501cc40c4}, {0x00052e187b053405,0x0007d1624c324405,0x000facddbb7bf7cc,0x0007eef155a6ce22,0x0000a4228cbd8983}}, {{0x000d6d6fd4fd6717,0x000e52daa10eef87,0x000c0eb96a233687,0x000be60562224403,0x0000632d184fbf19}, {0x000f8e940735ff4f,0x0002d00931f105d0,0x000fe3f183a3e6e1,0x00020641ccde6ada,0x0000381366bbfe51}}, {{0x00022a960167d923,0x00084529f18c24c2,0x00053b11462f9d6f,0x000043112397c003,0x000034d89dd1f808}, {0x00063ba2a4383ce6,0x0006fcf92ba0d9ec,0x000be74c0cec8e93,0x0003919b8b4288c8,0x00007d6912f705d4}}, {{0x0006c461b9131492,0x000f1a4e02da7b99,0x0002de59436aae2e,0x000545968aa00397,0x000084ec70d6ec6d}, {0x000b2d061391d54e,0x00061e114e92f3d2,0x000482dff69c5d5d,0x0003c4de0f00b5b4,0x00001596fa6d5bf3}}, {{0x0005b5696a71cba9,0x00026dcadeb71059,0x000cd8471944938b,0x000fe11282da4cfc,0x00008ec05f39d37b}, {0x000ce1b0698304a7,0x0003b1bdf79be171,0x00021dec12d69144,0x000f7160cd3b741b,0x000012ecd8b86a15}}, {{0x00000a700fd56e19,0x000269527c188d4c,0x0003e42e102ec969,0x000e0991c449374a,0x0000176fbaba392a}, {0x000f1ba44b7b6187,0x000981de491c8726,0x000b582c0b4d7aae,0x000a3a891df7b907,0x0000e116c315f60a}}, {{0x0000f81466265d74,0x00020df7adf09927,0x000738f7fb15b6fe,0x000f95be33b2d3f9,0x00008553aba16d70}, {0x0002ac8c21e94db8,0x000d3dc0bbee2cc7,0x00040478f795ac38,0x000e548a1be4492e,0x00001bd3394852bd}}, {{0x000dbe956b3c4f2a,0x000ef04177cc63c8,0x000010fc1017a99c,0x000b20f47bbddb4d,0x0000cf9b00c5b2c9}, {0x000bc8d47173611a,0x00080c7d756f2970,0x000d541a21a4cbe0,0x000f4366d9f4aa67,0x00003e8b689f9c2c}}, {{0x00066da4d88f1dda,0x0004dad35deaaad0,0x00078ca67c604f16,0x000e05dedc072044,0x000010dfae15a02c}, {0x0001c76af36f4e47,0x00023f3f8f48eceb,0x000c8a68c994b229,0x000c9d4f9ed77b77,0x00004f544eac1744}}, {{0x0005bb98113a7572,0x00046a9885e482d0,0x000a7865f4ef2d2b,0x000a51fe332be51a,0x00002b76b18490d1}, {0x0002310443516830,0x0006a3f22840308a,0x0001ed9479d86189,0x0003bf5959ddcd84,0x0000def0c94154b7}}, {{0x00054174c7c15e09,0x0001aa277c32f010,0x000dccf5f539bfb0,0x0003bd5699268ef9,0x0000f5796a59247a}, {0x0009de84f157269f,0x00048a30196b8b83,0x0008a5a91c825c1e,0x000fe57ef0aabcdc,0x00004a8ce6d398b7}}, {{0x00035a770cbac78d,0x000b26b239581cce,0x0006cb01183488e9,0x0006573341a070d7,0x0000a6c9d077e1b2}, {0x000fb30dd648c523,0x000c22fb9fd1b701,0x000563086994ca02,0x000baad69331176f,0x0000d2b810047856}}, {{0x00048c85963a46e3,0x0005799e61c7e89f,0x0008517b4658ab87,0x0006563e296f874b,0x00006c4fcdd2c1bc}, {0x00027a1a3906def5,0x000712418945de52,0x000d96cde9fe95f5,0x0000ddd0c91e81fd,0x0000adbe47f2a448}}, {{0x000370f396de2b60,0x000bf0ecc7bda009,0x0001d067298583d4,0x000984f44f6b57e5,0x00003d6b078556b1}, {0x000dd93b0b64912e,0x000335687b0927db,0x000ec20a99b3a343,0x00087b2dba646151,0x0000c93db80df281}}, {{0x0008c2466e48bdd8,0x000891ccd78e00ff,0x0002506032514f2f,0x0001566ba11f4fe1,0x0000a22cd41a43fa}, {0x0008df4b283e4c6c,0x0008cb39783fa4e5,0x00025980978c2985,0x0007dc9235aee2a5,0x000016284b5ce022}}, {{0x00079161338830dc,0x000b12123fcaa5f5,0x000c546f86d4b8a6,0x000d35636ea68af9,0x00001d36874ba608}, {0x000e4958d436d13c,0x0000cfb080afcd76,0x000ad3fb5d4d9c22,0x0002dfa65c1728e8,0x0000f1ebe4e73d57}}, {{0x000746a584c5e205,0x000169dc7035a7a8,0x000548c9b267e4ea,0x0002f3093a15cfb9,0x0000e6e21359bd01}, {0x000cc6a8c8f936e6,0x000455c241dcdf31,0x0005efb868af84d0,0x0002cb03990a6f34,0x0000fef4e6219b96}}, }, {/* digit=3 [{1,2,3,..,}]*([2^21]*G) */ {{0x0008f09257226088,0x000a931cf5c6f636,0x000b4f7ac131260d,0x000828c0eb353bfa,0x00005c78880b7eee}, {0x00081ffc3bdf24eb,0x000b45c3c5a84c15,0x0004e6f405bff75c,0x0000c985e8c83fa1,0x000081d1c0fb295e}}, {{0x0007cc8f43a730f8,0x000bb3ab590efcde,0x00003240be89b6f3,0x0005db4823f529ad,0x00002b79aff18bea}, {0x0002856962fe5de3,0x000b30c591f3568f,0x00028a8580c590ad,0x000f4befc74a144a,0x0000b662498e3203}}, {{0x000cf0d6c39765a2,0x000d8c3cca0b91e3,0x000953b50a2db3ac,0x000f1a088f2f08cb,0x0000414582cef43c}, {0x0008bbc60eee9a8a,0x0001d29aa0428dec,0x00032f5d554c79f0,0x00015f381cd5ec65,0x0000672303b6f82e}}, {{0x000afa8719c05631,0x000cac5fc79f376a,0x000750cd3cd8ad2d,0x00008e203fdb9fcb,0x00004ff052f5418b}, {0x00084cf3e2d65208,0x0007944ed509f750,0x000f25b987ebdf0f,0x000837743bf0f2d3,0x00006ad71d02354d}}, {{0x000fe9226f435728,0x000add824758b827,0x0009094c1dfd3ab5,0x000d67b15dd23a53,0x00005c0e37ae6623}, {0x00079727be19ae06,0x00067f0d36b5575c,0x000b1ff7e616a339,0x00045341ebb3c826,0x000035b9485740ad}}, {{0x0003cdada430c0b9,0x000daa96dac692bf,0x000ac326a4702850,0x0005e4391cf0a515,0x00005de4f4a3b8c2}, {0x000ad09e265c17ce,0x0003287b3881b01b,0x000fac5ca24e4546,0x0007a5f43e583ce1,0x000017cb3194ead9}}, {{0x000924374dcec468,0x000cd4c2b73f6cc3,0x0006cd99c33cfc02,0x000f8902917844f2,0x0000819dd9651773}, {0x0002aa60871f4274,0x0005b6f01c340957,0x000f1f5af8e0cf36,0x000e503fa52988bf,0x0000eb357eb275e8}}, {{0x000c8c4868af75df,0x000e55c8c7ead9d0,0x00081ecb0d7325cf,0x0004ecbb471996cc,0x0000f5d55f451182}, {0x00045411977a0ee8,0x0004f22038c6be31,0x0004bb4955085c4c,0x000081ad5335bff9,0x000094ad8a748e2a}}, {{0x0002341ada354383,0x0008d49b8c4e5c3e,0x00017cf34f4a9fc8,0x000e108eeb355a9f,0x0000f311e0e9c91f}, {0x000003892ab98919,0x0000ae8ce9a9c2d2,0x000c53bee257bdcc,0x0004398b2d978988,0x000027ce89b5dba1}}, {{0x0002cca523db2808,0x0009d0d43783b0a3,0x00097d16f5c889f8,0x0002e7d03e04b348,0x0000cdb6e7888f5f}, {0x0001cf0179c8e744,0x000208211d606ab9,0x000851200d8874e5,0x00040ab948d4d5ea,0x0000076d41f26f98}}, {{0x000263c47b517ea8,0x000cb0685e5ec20e,0x0000631a079a448f,0x000346655f6f78f9,0x00008a790b2279e6}, {0x0000c7d80969fe8f,0x000351491bb96216,0x00095752654f92fd,0x000e7ab6645c235c,0x000044cc5afaea3c}}, {{0x00083278b1e68b79,0x0009a03f29d3f762,0x000d03ecbc731ad7,0x0007a76e5a9ca957,0x00006c0d50cd1bc9}, {0x0009fe79b4f7f248,0x0007bd9967efc466,0x0002c208dfdd781d,0x000cb2f892c7c35d,0x0000bf64f7d2e545}}, {{0x000862c467be912a,0x0009273d30ccc01f,0x000b83ec7f4c85ee,0x000cf87fa6f4be6a,0x000007a3c1cee3e3}, {0x000ef450c00beb33,0x0002d00d4c3e87f8,0x00008bf5b30e2c2b,0x000f51eaa00b94fe,0x00002c133aac224e}}, {{0x00016bb32e5685df,0x000868e6f54438df,0x000c5ebc668a9e06,0x00035e595aaff7cd,0x0000894a646278b1}, {0x000350a09e27ecf4,0x000e18f7179df316,0x0007861baeced201,0x000e2deeec273ce9,0x00007ec2caf1693b}}, {{0x00097c4f68367ced,0x000aee5a5755fa4c,0x00098a979e4f47d0,0x000c7c47de815db2,0x00007eca65a9177d}, {0x000bb7149ded0a33,0x0004cb34d3c520fd,0x000858a334cb2aad,0x00040efcf31d2860,0x0000b6873efd24aa}}, {{0x00034b22c11bb373,0x000dbd4c74a35402,0x000c5f25d2d0366d,0x000142c9a968daee,0x0000660106897b63}, {0x0006d2c68d7b6d44,0x0008cc84294207cd,0x00068b1eea8f74f0,0x000ee4a275140477,0x0000b5f7e8a3e62a}}, {{0x000717789070d267,0x000e6d1c8bc7c6a7,0x0009e1f17a1f28e4,0x0008e07a5f4f0646,0x00008fc242b6bdb7}, {0x000c5928b0588f1b,0x000c6535921ec9c7,0x000e5ae35b6b7a0f,0x0008641c5bdb91bd,0x000042c485ec2ff1}}, {{0x0003e13dbab98aa3,0x000b717b1024a111,0x000462d3ade9d469,0x00078cf3f48b37c0,0x0000752e537ac5c0}, {0x0006add15544eb9e,0x0006a0fba279e3a8,0x0002001b5f013aea,0x0001aaab5bb76cf2,0x0000617ba15d0289}}, {{0x00082a6936219d36,0x00044e51cb19d391,0x00007a74c5ce1f19,0x0001bc678f8598bf,0x0000d7158f282cbf}, {0x0006b21e300ce18d,0x000f5d11275d3b84,0x000239b9b35fba62,0x00093f8fe25c36a0,0x00008beb35eaf05d}}, {{0x0002bb01f7e320d9,0x0003dda320ea4db0,0x0001389a30641c36,0x000e3cdd95fa5d82,0x000026997491fcd8}, {0x000ef17ceb6c1434,0x00019933762b316f,0x0008b17f867fcb84,0x0008217b837e3511,0x0000b92552fdfd24}}, {{0x000c70e46aca7930,0x0004e579311bae6b,0x00002f7161cf0b0e,0x000e4d8dc631be58,0x000099bdc6fbddbe}, {0x0002bb20caf8b051,0x000a62d63df2cc35,0x000c4f408f74d505,0x000b2da9876d4b91,0x0000ce18473ae229}}, {{0x000759783abdb4a0,0x0006dee84b184950,0x0009e67dc850fbcb,0x0006d86325236e60,0x00004d831d99336c}, {0x000ae3bfa12d45da,0x000da746e2468dea,0x000f5f31ee425f8c,0x0003b6e004c17524,0x0000ca16d904d62c}}, {{0x0005a6a9152f9347,0x000d7d0e12c10dc1,0x000477dacf1235e5,0x000006533c06ecda,0x00006be873322ea0}, {0x00078310c0cd3130,0x0003a614260dcf3f,0x000b22d153c52455,0x000a2031a756f8ca,0x00003ee10d177827}}, {{0x00059b21994ef202,0x0009438ae318d1e0,0x0006990102a653b6,0x00084a50d5eb582f,0x000079739f729f5f}, {0x000663c8b799336a,0x000c803c37eb5da4,0x000dbfb2dfdfdf14,0x000f9a92d8a9dca1,0x0000b40cff117d48}}, {{0x000b383d20b42d5b,0x000eef78845fc018,0x000ba9df0f9a810e,0x000df890af3753bd,0x000090bdcfcc31df}, {0x0000591f01ab782d,0x00009af12a881872,0x000c14401c823f21,0x000be2d51b80f30d,0x0000e248f78cb2df}}, {{0x00044e50cafe751d,0x000c04dcd221ef5a,0x00085402473997c9,0x0004ba62fd86d1de,0x00005b53add709b8}, {0x0007a11dcedd8d12,0x000854b32c84008d,0x000dde8b1406bd1c,0x00032f3d4472ff05,0x0000e25f2ce1ce2b}}, {{0x000dd5e29dfc254e,0x00054b98b267bec0,0x0002df2ad4455fcf,0x0003962b4d43a5c7,0x0000a70e6bf28a75}, {0x00061695820f3bf6,0x000d3e37f68f2aad,0x000e5ac83f410d2d,0x000eec10fb7dba7b,0x000036bb64596ec3}}, {{0x0004ea39754e21c0,0x00068d63c3732710,0x00009db9abc87a3e,0x000da7483351d741,0x0000fa724e360134}, {0x0004c29b0720b169,0x000276aceead9ff4,0x0006929a62dd0cf1,0x00092ac942758ce2,0x00006c5db934766a}}, {{0x000d4c05f18395e0,0x00041f80d032cec7,0x00086075bd3f2274,0x0002db7a68b37acb,0x000074764ddafef9}, {0x000e9507bc7f3893,0x000089756460ded1,0x000a48157c580c85,0x0007b37eeec2a47d,0x0000f0b4e7fb2c58}}, {{0x0006de8a9f19c539,0x0002d974e34e231c,0x000508fa95717bd7,0x00012449e1d216f1,0x0000f1123626adaa}, {0x0005e31823b73482,0x00058c6340698014,0x00097c2584dd8f0d,0x000431c3d82fc722,0x000076fcfeebcee7}}, {{0x0001b5e2bc0aea9e,0x0004fe3294318eb6,0x000e4b87e4f668fd,0x000f0a23a32ab138,0x0000137451853d0e}, {0x000f7e6853ac983a,0x000dc8e78a571a46,0x000a96dd1c3bdf42,0x0004600cf207852e,0x000010649ba91638}}, {{0x0009f0b879fbbed4,0x00069a9d1869f236,0x000766f450ff0ae8,0x0000fc1251d75956,0x0000984d8c06be8d}, {0x00095a6d21008f03,0x00000a1a1c497ecc,0x0006c50f329bd54a,0x0002517b9828c5d2,0x00002c0087c81d0d}}, {{0x0003ce60c1cdb260,0x0007557ca2059bac,0x000b1fdcdcd94d94,0x0001491b1bd5989d,0x0000eda0108a3d8b}, {0x000661056152fcc1,0x0006d7192b339506,0x0002e05a4c2f037e,0x00062eceffb41ac9,0x0000105f6c2d2f6c}}, {{0x00035008733913cd,0x00026f3adc4068e7,0x000a278e9cce8616,0x0002922407a94238,0x000013c1b9dfab21}, {0x0007ec71c74cf5c3,0x0008c1a4c1b493ed,0x0003a11f18887dc4,0x000cb60830ff304b,0x000058c5a3c88937}}, {{0x000c404890228299,0x0006ab798f79027d,0x000be6ead40e9397,0x000a5d00ad333738,0x0000c23f6bd834c0}, {0x0001a35fbffd8bb2,0x0008f949d3ddd171,0x00025d93a60fcfb4,0x000967e9c8ef4b78,0x00004233cffc0a8c}}, {{0x000e46ce6d982af4,0x000ea7544d7c67ad,0x0008bd087ebb6bf3,0x00028096b9ba763d,0x00006fe382d8dc61}, {0x000a7e8b5bdbd756,0x000158f228febd39,0x0001c4300ab38133,0x000eaba709a77cce,0x0000a247e575337c}}, {{0x000f21b636288bec,0x000408a7c3058f34,0x000919e049dfdca7,0x0001f7adecfd1bea,0x0000df2688e4e199}, {0x000df44d0f8a67ee,0x000a2b58d010e607,0x00024f8f4d985df4,0x0001ad77f834c50c,0x0000976ef5780bf0}}, {{0x00095aca1c323732,0x000a534c0a135363,0x0006bd5bc351027a,0x000bedb2f1b5d65e,0x0000b539e24423de}, {0x0004cec0eaa1d710,0x000d661dcf65d499,0x00054c7402a83381,0x0005ee5f1aed2f7b,0x0000bea3fa5d6dda}}, {{0x000b68436cc61347,0x000350a443dd9d4f,0x0003b7d2a8eb9bbf,0x0002578c500e2e38,0x0000aad621ccb775}, {0x0004d740a8f7cc07,0x000d97562d656928,0x0009758eee820c2c,0x000c2d4f9531b949,0x00003e95ca5dee0c}}, {{0x00090abfbaf50a55,0x000b184e0750f617,0x00076b005df55e76,0x000dc79c516da7f1,0x000075553bbca2dd}, {0x0007ca3553afa736,0x000bed55c25137c8,0x0003e5d35315f3ff,0x000f288846442aaf,0x00001b91149c495f}}, {{0x00095d3fa326dc3b,0x000e68fc2cea23cc,0x000a37d591df4da1,0x000e1d74bf9adcd0,0x00006710053e20d6}, {0x000667e618344d14,0x0002606445af96f9,0x0008dbc3acc7ce04,0x000a5b602d8514d6,0x0000ea109e4680b5}}, {{0x000a7acb40961bf5,0x00071aa56bfa5741,0x000b765d14ada593,0x0005822feb914502,0x000061e97bf36ad1}, {0x000a5b6da3982f5d,0x000ce546f468bbc4,0x000612d200c2659e,0x0008dfe8e7e6aa59,0x000083dfe217c19e}}, {{0x000c45fb835398c3,0x000f838a41c28530,0x000f5dcdb6106a8b,0x0008ecf1e8f9a635,0x00009707137fae49}, {0x0003834d8249f00d,0x000edb2537a070c2,0x00061c0c29f14b58,0x0004a70043c3655f,0x0000c5926d6d9a19}}, {{0x00003398e77738ae,0x000f1ba46426ddec,0x0007f6e86d07a63e,0x0002404e58e79cee,0x000059b045adf32d}, {0x00084e520fa03389,0x00085aff5acec5ec,0x000a3831397939ac,0x0008847310a4e3b4,0x0000115fba31f9d9}}, {{0x00010c25fadf8c35,0x00027e19c0e28dd7,0x000fe502266be38a,0x0001b8842a279c4c,0x000097bb5305e24e}, {0x00086b7c153ca7f9,0x0002e07d63bd3cde,0x00060d21ea8d30fb,0x0004ab1c905f92bd,0x00008e7ffb70b9a5}}, {{0x0007df8e9726a306,0x000f4fce3533d714,0x000f1ec40b5e216f,0x0003fd5550b7992f,0x0000b613b8801e95}, {0x0008dba792d56100,0x000aa190fbe187b8,0x000f581da2ee1270,0x000a9502f4e2dc2e,0x000016530e4eff82}}, {{0x0003dfd8fd6ee891,0x000636848fffcbb9,0x000a47adf16d3d98,0x000a71500eff241d,0x0000b9754a01ad47}, {0x00066df70c33b988,0x000e5f34186e8f92,0x000d24132aadc87a,0x000eb98d2ce8e14a,0x0000a47cbfc99946}}, {{0x000eb6662b5f3af3,0x0000dabb373447fe,0x000f35cb1cefab56,0x000eb9149de60e19,0x00009f8db14457f0}, {0x000cc5b3c61bfd60,0x000d41216703ffae,0x0004e1cc2a5a4d41,0x0009537f8fabed22,0x0000d5a8186871ad}}, {{0x00074f7d22da9a9b,0x00081c8a9b0df107,0x000c32cff45b8a67,0x0002a529c2e722bd,0x0000f71b5f5e3720}, {0x0007f2f69fc4db96,0x000c165d01e195c5,0x000904635b6dad34,0x00088c1e0bd13fcb,0x00001751253d63a5}}, {{0x000299781af2c2d1,0x000471b9d7dad85c,0x000533e8dc0f7d9c,0x000311738a34ae08,0x00005c4cb08411d8}, {0x00032858e121e14e,0x000da5000a5f97f8,0x000256274eea7dc1,0x0005bf2c6059b65d,0x0000c9beacf99507}}, {{0x000aad71df978283,0x000578937877173d,0x000646f3cbf851cb,0x0003528083c59401,0x0000bad30cf80c6d}, {0x000b202496bbcea3,0x000ee8a1e8bafeb2,0x0000660293cf9fd4,0x0004f8a26de7ff1c,0x00009c81e9e7e9ed}}, {{0x0000cb97b390d355,0x000d464aab27d8be,0x000ef64f801df2bb,0x0001dcee8c1a65c3,0x000067291d1c16ed}, {0x0009c6c5f5406d3b,0x0008aba8e23f9549,0x000096ece71fdda3,0x000d161feb320ed5,0x0000e7ba92c7a66d}}, {{0x000d36bc6fb5a7df,0x00097d2dd0e04608,0x00097a36ae3eea15,0x000e1d85b0a3eb8f,0x000059814cd0c83d}, {0x000c5b01c33c23f3,0x00043faa413656c9,0x000316551a96c1da,0x000c8f16bf2074de,0x0000b866e7b4f756}}, {{0x00027d81495ed6bc,0x0002f682dce77277,0x0008610f3b239424,0x0002a3cab8454e75,0x0000243ce85457d7}, {0x0000d71dbbf370fb,0x0006c8e0f7ca7b32,0x0007b523fff9afa3,0x000d415119d1e0ea,0x0000997f8cbb58c7}}, {{0x000cd2a37bbb1840,0x0009a45d1fa6285b,0x0009634cb51dcec4,0x000ef16ade3b64e2,0x000080c94a726b86}, {0x0003db12283fbe37,0x0007ea9315edba58,0x000964bec902bddc,0x00030097c1ccb386,0x00008f4ead026258}}, {{0x0003a4956f908239,0x000fe41d777b4bdf,0x0008bf760ba0f507,0x000b01791d71c3f3,0x0000633d5102b625}, {0x000b743b8c9de617,0x0003ede7472003ec,0x000ce1cb2b475125,0x0002ef2f9defc974,0x000074a4f6a70bd3}}, {{0x00085f773848f22f,0x000603f8558eaca3,0x000c471f953dad71,0x000bc6bb7b34b093,0x0000530e06a09644}, {0x000b1ffdd59d31ae,0x000e28daa7953d9f,0x000cc88d74382e0d,0x0008ff365c6f4bd5,0x0000aa392d62a18c}}, {{0x0003c67648024ee6,0x00022c2fabcd9420,0x000aec835188763f,0x000d54480f87acbb,0x000032c96e1529d8}, {0x000a60e4c00a95ea,0x00004011e9fa29b0,0x000b772232ef17f4,0x000e3256c0e1d115,0x0000aec2c62b4b04}}, {{0x00088d83d84e58c4,0x000c558571dbd356,0x0000682a62af5094,0x00007c0fff7e1976,0x0000cb27078239a4}, {0x000c5474ff0e321a,0x00057b34c8ff0f59,0x000bc1ba7169f34a,0x0005438bff109652,0x000025423b823583}}, {{0x000d5d50ac8b7823,0x000bfdb3c8925d55,0x0008bb642ff6622e,0x0003dc18fce7416b,0x00001d6998c99d7e}, {0x0008004cadcaed01,0x0002c81d053cdbaf,0x000630ec6801b014,0x000c8e84b189fc59,0x000020e9934bf762}}, {{0x0009aa4fdc6a4043,0x000e7190994853a2,0x000e8968119d8e01,0x000d370cfcabf1d7,0x0000321a50d7e132}, {0x0006863e9a861112,0x0000e6a3bc65d049,0x0009f8eef8c0cde6,0x0001418f866c49fc,0x0000066350f1f7f5}}, {{0x0004689e56ddfbd6,0x00079e32983a4f8a,0x0003cb8cbea1b0c0,0x00029ecb31746287,0x000058deddc8d932}, {0x000af4d0f64ef589,0x000ce30cc7a865ef,0x000047d70fe43287,0x0006c91ebc0c723d,0x00002efa53a692d2}}, {{0x000845794b565268,0x000e8961002d06e7,0x000dcb10f415cb80,0x0009fe09e5c56576,0x0000bbb69837f925}, {0x000795b9abc26689,0x00038e678fb14fe8,0x0007da2b9b5d4f53,0x000804d601f3be7b,0x00008da59e3313d6}}, {{0x0008ea601799a527,0x0001486d2952190d,0x000ff2a7ca20cec4,0x000d36c062ffb27f,0x000041b32e5e9f19}, {0x00081814eb57d471,0x000406aef06bf80d,0x000ecb5887a2d0ed,0x000f5af9735fb01c,0x0000641caaad6061}}, }, {/* digit=4 [{1,2,3,..,}]*([2^28]*G) */ {{0x000824f20151427a,0x0005f24302067f99,0x000112357206828b,0x0004ec0a9097d7e1,0x0000cf9a2f2a9e41}, {0x000c9da279153564,0x0006c01efee3dbda,0x000b288e27e0734b,0x00009c14fab5bbd2,0x0000c630fc5362dd}}, {{0x000107a1ac2703b2,0x00084bc857b58537,0x000daccd1b49258d,0x00052937df14debc,0x00004ab68d7e4ae8}, {0x000b5d4734e59d08,0x00084495cc807ed8,0x0001db9b35f8740c,0x0005be04aedd5a29,0x00000b360f8cfb99}}, {{0x0005f5d5fa067d1d,0x000ec668960cae91,0x0008edaac4134b57,0x000435ed3656d6a4,0x0000ac1e3e5cc1d7}, {0x000f869d81fbb26c,0x000bf26c33d4674f,0x0004203e8449ed3e,0x000f49c5138705d9,0x0000cde538c7eeb6}}, {{0x000c68da61a76fa3,0x000d9a1554dc55d5,0x0003b279c598b441,0x000efca39923b977,0x00003331d3c66bf9}, {0x000848e298de399d,0x0006d1a27f562d4c,0x000b8ab70cfdb8e7,0x0009b9c4c855ea57,0x0000cdb9daf3f787}}, {{0x000f8c2019f2a596,0x00036b4fbc747bdf,0x0009173ddb3ce5bb,0x0004398a907f688a,0x0000cd3d0d3f5a75}, {0x000c4d6efed021c1,0x00005a77339a92ec,0x00088c64a09a9f9b,0x00015877ca6b1571,0x00000c2996854899}}, {{0x000a229ed6e82ef1,0x000355ebaf4e5859,0x000ad67ae16f338e,0x000bb3fcd313875e,0x0000c73d22864ef0}, {0x000513174a5c8c7d,0x000faf69ad6a4cb5,0x00066f87e01cd296,0x000320d04d00dde9,0x000096fe447db7b0}}, {{0x000c06e88fbd3813,0x00042c35a493342a,0x000f1bbcd02cd4a8,0x000d4cb8fa89de54,0x000041d63675575e}, {0x00057fbd238202b9,0x000a1984ead9ebe3,0x000436ea0600b4d1,0x00051b335c9f4452,0x00006fe0a3a33707}}, {{0x00007367f636a38c,0x00064e76d5cb4c4f,0x000b68b8b9f943fb,0x000a1ef03510baa8,0x0000246780b5ed07}, {0x00014156d549fc2b,0x0000b07781ca3c05,0x000d95413c2953f3,0x0002e2e55e2c69d8,0x0000300fadd2bd28}}, {{0x0007b5087e9189fa,0x000c542dda2781fe,0x0000a5904db17375,0x0008e582f7d896cf,0x00000e57c5b8be34}, {0x00011d3f40e3c80d,0x0000bdb705c5a610,0x000fedec3b118932,0x000c1c7ed9309e50,0x0000cf14a111d6d5}}, {{0x000265b556913429,0x000401049dc7056c,0x000bae20ae8e0850,0x000db3831329f5c9,0x00006c8b3e969dcc}, {0x000f838fb4ee6b40,0x000b41e8ccf08c5f,0x000e050c6fc5a9ae,0x0000807417b764fa,0x0000953c3d700452}}, {{0x000268238dfe7e82,0x00050bb79d4b2137,0x000e7cf2dea417e1,0x000fcc39641f1c76,0x000071e305a0a0bc}, {0x0007dfd7253ecbd7,0x0004dfca6186624c,0x000866e9c2f552e2,0x0006105bf84ecd4d,0x0000396770a668d4}}, {{0x0001163c27901b4b,0x000fd99b8bf3a14b,0x000c6da0afd9236d,0x00029692b091eccb,0x0000b1dac700ad1d}, {0x0001d53a91cf76e1,0x0002c31f1ee780e6,0x000efcf774110a41,0x000d761d87c3ba13,0x0000f374bb4ef450}}, {{0x000e2f20d188dab3,0x0000c4b885ef5e78,0x00014570fe3968ed,0x00052116c0568e73,0x0000161633831170}, {0x000e7e24f0c8afe3,0x000faeea78da18e1,0x0005d8a514caa75f,0x00037052db67f27c,0x00006a44d869f505}}, {{0x0005bda0333974fb,0x000d77a70146d72c,0x0000ef9215db516a,0x0008e48470528121,0x0000ff17a8fbc9c3}, {0x000814e12476da14,0x0002f3c1698078f4,0x0004d4bcac1e1661,0x0000de5e5b386f42,0x0000c274e8808574}}, {{0x000b88d6c2f5226c,0x0003950d7ca8b6a9,0x000c4170914d1b94,0x000518980c85fc1f,0x00001da368c14c6d}, {0x00085ced5113cf71,0x00034a34708f2b07,0x000cc3f880670f63,0x000c8f36e2376715,0x0000b480cfa60c72}}, {{0x00086024147519ad,0x000b56b372f02028,0x00085ebc8d0981ea,0x0008e8d9d4a7caa7,0x0000953c50eabdf5}, {0x00061ccfd590f8f8,0x000ac4e6c9179d63,0x000eb64cf72e9626,0x0008f2ffd9611022,0x000063ebb7f1eb28}}, {{0x000b7616aca8ee7c,0x000917b403586e6a,0x0005feb0d97d10b3,0x0002795687d3771e,0x000083e50e54265a}, {0x000a9fec954b3132,0x0007110d1f618f75,0x00057d0e0cc2e8f4,0x000207d5ba81c565,0x00005f9680c5eaf6}}, {{0x00066094354080b3,0x00054bf2fe1cf95c,0x0007d98fa5225bfa,0x000f6095c004e25c,0x0000561bf1c319aa}, {0x0009f17ba1514741,0x0004a04f6eca5e6f,0x0009acb1edec2f93,0x00049354e368a126,0x0000332d9e41cdda}}, {{0x000cf69df23de05b,0x0001509339a060d6,0x00069392366d17da,0x000a6cefcac9850a,0x0000cf057fd9d7c6}, {0x000c8c5f0b5662c7,0x00086cba4f24c3c5,0x0002b69ff25318dd,0x000c00f0e8cb7508,0x0000c23b3ee8e728}}, {{0x0000a0a097e4403b,0x00056985466515e1,0x0007d4826cb3d0a8,0x000838d8d8e211d6,0x000039af66ebb9d2}, {0x0004588bd475ca8d,0x0005f077b80ba5f9,0x00027c26ce06b796,0x0005e02edb1485da,0x0000290d33bce0fd}}, {{0x000cc47f34fb0fa1,0x00080fb1ab09a40b,0x00073bfe3b4760cc,0x00013c7fca0993a2,0x00003e4fe08070b2}, {0x000b992fdb05163c,0x00004c2b19b63bcd,0x000f2e3e28c484b1,0x0001b35acb815faa,0x00006905936789ff}}, {{0x0006f9d586e74e18,0x000ce7b80484b2ad,0x0009c3ddb488883a,0x000d30f58aa2c736,0x0000ab74e6a1f9af}, {0x0002d285e21beb19,0x0009a18c42f910fc,0x000cf40c33484518,0x0001d8a77427dc53,0x0000de0781ac91bc}}, {{0x000e858693807e1b,0x00069e81ccc78fae,0x000835b84a386532,0x0008d352c30ff26f,0x0000604437bbd3d3}, {0x0008a985ca1823d5,0x0008b3be0324b3fc,0x000684a33b82f7ec,0x000f7d9e36d761cf,0x0000a01df0eef29b}}, {{0x00002f31306583d2,0x0000237c622e6862,0x0006a7bc805b10da,0x000e439f9aaa0f07,0x00005e94efbaf8f4}, {0x000c9b7fa3dc26dc,0x0002d6ff03c58a35,0x000c394cee0e5fb9,0x000e5fe77e3843eb,0x0000ede65964361d}}, {{0x00022f6a19935459,0x000594d671bad27c,0x00069c28eab01cc3,0x000375d3fa2877a1,0x000025ef904beb08}, {0x000a3cf53aa0b32d,0x000aa1c49d7a3b2f,0x00005e27fb27beb5,0x00070ce60e1834d1,0x000060897891f685}}, {{0x0004ce0d6fbc2acd,0x0000b15ff5512309,0x000ef119c738037a,0x0006ba0a73b1bb6b,0x0000cf6c431bef50}, {0x000fe7be3ef104a2,0x000bea06562800e4,0x00092043eebdd9a2,0x000108653a81c387,0x00002ad6eced3b59}}, {{0x00013c039cd297dc,0x000d45bda5d99fb8,0x000104b968ec7e16,0x00050f6834797c0d,0x0000c11a2e83c511}, {0x0005a5396ee63809,0x00053ea3874296ca,0x0004dfa7d054c865,0x00020725946852d5,0x00007c422e7af4ab}}, {{0x00075090c22b5403,0x000a87c267d4bf90,0x000b0d6932cde42a,0x0000d98a18f9ed5a,0x0000ba62aa69e466}, {0x000f97bab9ea96a6,0x000283b60e32b24b,0x0004d9bd55d03964,0x0006a3ee6a45067c,0x000066c5b9eded4a}}, {{0x000dcd98edbd7cc8,0x000746ccd753fa3f,0x000e6b64f4660bb8,0x000b3f1ae9082021,0x0000a56a714336bf}, {0x000e0965726d47f7,0x00019b1a9a7fabfc,0x000b74a379eed01b,0x00066cc0e9cad44e,0x0000b2524ccc3e96}}, {{0x000683b8f4b002f6,0x0009e1f4fc206a29,0x000338accc2200d7,0x0009756f3af47a3a,0x0000539a4fc47128}, {0x0001c14c33c7fcf7,0x000b57be322bcec3,0x00046f6237eb6799,0x00099aa19ef4e966,0x0000b7a26a5c4d72}}, {{0x000f08d403f46f2f,0x00022a0ec0c7cb37,0x00032142f94b8fc4,0x000a79cb8514e3c3,0x00003ed2c34d80d2}, {0x00080afb639126c8,0x000063553ade8d20,0x0007e2b09f7b6be6,0x00002ab950aa9f1c,0x000047ff958e410f}}, {{0x0007cf5678a31b0f,0x000d4998b620877b,0x0000fb396d50301a,0x0002a5834257c5c0,0x00009fb18a0f4e67}, {0x000d8ebe8758851b,0x0005ad99ba44ff8b,0x000fd93b71e64e4c,0x000b8b9b8eaedf7d,0x0000a2f2a98b4e76}}, {{0x0000cbae8053433d,0x000f6d2c95857d79,0x000d8f5edc8e7259,0x000e1c88c5c476cd,0x0000106b953bfa9f}, {0x000775b0eff13a96,0x000a8057b9303c5c,0x000b70cbd242442b,0x00089a89f458d4c9,0x00009b7144903cdb}}, {{0x00046f60e2ed7422,0x00052006749341ee,0x00054c304573f104,0x00050291e154ff9d,0x0000ad0436aad3a7}, {0x000aa2d431a8121d,0x000ab86f11edee4a,0x0004a0eb7cd38b3a,0x000e5787d49ea603,0x00002b773bec7e85}}, {{0x0009ac49b5c1f14c,0x00097e54df2b4a55,0x000a41891c444be1,0x00078753aad704ed,0x0000d927bed1eb5c}, {0x0008516e48c8a348,0x0001cb546669eb3c,0x0004df8ec1b7ac81,0x0008649815f89659,0x00007c6a79cf9227}}, {{0x000a2f09b56ddbdb,0x000bda2f1cf3ae02,0x0009dff0d1339b5a,0x00043d42b569c783,0x00000b9e865aee9a}, {0x000ca4177bb064e9,0x00026d249f634ff8,0x0006f689a145a281,0x000f5daab7beacf8,0x0000bafec2791d35}}, {{0x0004c654265aa91f,0x0003135efe422805,0x00039dec7a4b1830,0x000ea47887b0e696,0x00004b8f6ae2d52a}, {0x00093cc971a8a130,0x000d4c934d07fb92,0x000acbc293f159e5,0x0001292c50e9b109,0x00008eb65e67154d}}, {{0x000f58930b75c3ed,0x0001c4491c934fef,0x000af62bb0bb82fe,0x00049f08ac377a89,0x00007b514916685e}, {0x0009a7b04497f19d,0x00094a7ad13fabca,0x000c86ed61b35ed0,0x0006f09b601e213e,0x0000a91fcba9e0c7}}, {{0x000507bd7ab27e14,0x000523945b7b9e28,0x000fc98277c19a55,0x000b912b43f0a1aa,0x000043b4fbd7aa55}, {0x0002e656962c88f7,0x00045e0db0ca962b,0x0008d6c4f139da8d,0x000824493f05dd1b,0x000079cdff7880b9}}, {{0x0003fddae57c7b7a,0x00017b932522bba2,0x0006d4aa3345342f,0x000b615d9c80fe55,0x000003907bb0525b}, {0x00010e1ff2189336,0x00044a52117b38b0,0x000f2e6eac066b65,0x0002b22e14192094,0x00006a27dca6d32f}}, {{0x000f993048b37172,0x000a9178ae1c69c7,0x0004f1d6bbf5a989,0x000e4e29fa905856,0x00007ec6e15f31fd}, {0x00003737276e7fc9,0x0008f9d6bf024cce,0x000cdd97964086d7,0x000630ca72f0464c,0x000009c3566d7775}}, {{0x000bc6b75dd7125f,0x000697a0428d1c07,0x000eb6b9db4c6bc9,0x000431607ece52fd,0x0000ca56513a2c95}, {0x0007181d0e8bd06b,0x000716bb46ea15d9,0x00052b624384dd31,0x0002faa441ea2039,0x0000cf70deefe7dc}}, {{0x000016e6628e8c30,0x0007b60a7522372b,0x000344ee207a0d66,0x000eeccf05751b0a,0x0000ec09a48118bd}, {0x0003d4ed83dce467,0x000d29d2fc6e6e4b,0x000cf044c43a6316,0x000fb7399d898956,0x0000c7f44551e3e5}}, {{0x000b121fbabbe926,0x000b81330076b2e6,0x000890015281850f,0x0007f4a93581ec97,0x00009b1ddedd5ff7}, {0x000b18fab1051053,0x0001789ccfef7cf0,0x000914009953ced3,0x0008ad0151f85feb,0x0000c9f1b87b8ed4}}, {{0x000a1a14a7eadcb4,0x0001122e71cfc9ab,0x0002e4f83928e750,0x000bd3aaede7273a,0x000067e10d15ce3b}, {0x0002ac3b955dcf05,0x000d83d5e527f344,0x00077f474ba96307,0x000ff0a763a10efd,0x0000d744bd0ba6e1}}, {{0x000282aa777899e0,0x000fd03f3cded287,0x000b07d31e20eda8,0x000de46a7e75bb50,0x0000b7e2a946f379}, {0x00064ad19f593cf4,0x000ede76ef1d31cb,0x0002d609c7b1a9e4,0x000650a18c9c9db6,0x000039bad6e2779a}}, {{0x0009066e032f1445,0x000898b2ec6a219d,0x000a12f781db632b,0x000265af0d0fd4fd,0x00006fb4c2d7a25d}, {0x0002ee1255a03f19,0x0002596af1765f4e,0x00068bc9761cd6af,0x00088e50317ba8d0,0x000027d6babb64b9}}, {{0x00007e0e90fb21e5,0x00006ba7fca1a18f,0x000cd67b500fd2b8,0x0007f6d0387f2795,0x0000b89a4e823970}, {0x000ad3f894407ce5,0x00041c2261328f83,0x00006c13ba0025b9,0x000025779563c7f9,0x0000f548f319e7bb}}, {{0x0006b8feac6d1135,0x000bbe813c762b4c,0x000e1f4b9a67e3f9,0x00050de982717c3f,0x0000886581976d80}, {0x000640cf7f06f200,0x00062a66ebc299f3,0x0007a1e08dc61021,0x00071b52f2c17576,0x00005660e1a59998}}, {{0x00017626d3c46934,0x0006f7ed7bea6b0f,0x0005b226df0e7d62,0x00013b851758c7b7,0x00000a886285f916}, {0x000baa7bbb38ce0f,0x0004cddcad81889d,0x000c9671fe0404b6,0x0003750ebccd3a8b,0x0000bf9a358de1f5}}, {{0x00069b028f33398d,0x000ca2e90f655dc1,0x000ab1eb1b07ec11,0x000389de7f3b4afa,0x0000970195f2f175}, {0x0005cbe0181e6402,0x00020643313d52b0,0x000f31f82f5debd6,0x0003c5561481545d,0x00003e03b335a9e1}}, {{0x00089494fde0c1fc,0x000e25b6ec20ff75,0x000e1db6cbf8a1ab,0x00058eb02278fb87,0x0000447ad7af5ed6}, {0x000aa3803d0ccf24,0x0008419a7c0348d4,0x00017cecc80acb33,0x000d825bc7c89e6e,0x00006736b8b43be1}}, {{0x0007b60c0432f963,0x0003aeb5442fd65d,0x000ff69a2ddebe7a,0x00012249a253077d,0x00007a56d9432cf3}, {0x0008aedf2350d0a8,0x0005837b0d9a8bab,0x000c65cae13c3f27,0x000a884664957c44,0x00008b4408a42e71}}, {{0x000e5a35cb026649,0x0000f686c72edb88,0x00082d53e5d4c0bf,0x0004315a3d9b62a6,0x0000b605ef49b2ad}, {0x000c202c69645d0f,0x00097a1b66e771ba,0x0008f4dc4a115f03,0x00078c0e2c563a15,0x0000715b3a13d12a}}, {{0x0000a48d413213a4,0x000d804becdb8f7f,0x0008587f52035806,0x000a71acd34a995d,0x0000d8c3079df6d3}, {0x0002a678d95a8f6a,0x000d52110d0d1b2a,0x0008fba3fc58c9d7,0x000f683eee81d5cf,0x000042be3c0ac7cd}}, {{0x000f742d43b5eaaa,0x00063fa59b852126,0x0006bfd45054a076,0x000a8efd0d5e3612,0x00001f8fbd7d84f8}, {0x00080f5d563fccc1,0x0005e280a9283176,0x000b578cf48ca505,0x000514d00b81b227,0x00000aad9183994a}}, {{0x0007b62b7bdc9534,0x00021bc086ddd9e0,0x0005eee779f0f6ff,0x000df0c9d1ccff65,0x00005475f799bef7}, {0x00028fa86f702ccb,0x00045f021f073faa,0x0008fa8c692e6090,0x000a2c39e629687f,0x0000d71419ba036e}}, {{0x000e1cc6028da9ad,0x0009f251f573171e,0x000a997f45352fe1,0x000d5f28ff236e3f,0x0000831b6ca75749}, {0x0002e1de350e2c27,0x0008ae0ce4037c87,0x00074f5cbc56240d,0x00072889deb07769,0x0000d50ba88061c3}}, {{0x00094265a3a2518a,0x000926303d43d6f8,0x0009e5696cf81779,0x00007ab10a047161,0x0000b049ff6da5e3}, {0x000f9b0feb13ec70,0x00079d8ff90ce4cd,0x000fa96afd5e9711,0x0002a2f6f64d069a,0x00000d0bf5e9d201}}, {{0x000301f358bcdc04,0x0008ca9d47f8e63f,0x00043d43a07689e9,0x000903df689e2f4f,0x0000d542a16d0920}, {0x00093d59ca0a7072,0x00056ac68065aea2,0x00090008cd061fe4,0x000db5f033bf1b00,0x00009749558e08a6}}, {{0x000fc59c1d5d0340,0x000667e215e074b5,0x0000200e6f712e9f,0x000588fd520cbd86,0x0000229acb43ea22}, {0x000e14cfff0c82e2,0x000239c69e739cd1,0x000ccb98987684b6,0x000493ba85e61c96,0x0000d5dbb02c3d06}}, {{0x000d33ae86b173c3,0x0005779ff0e3f22a,0x0000d0c10e8e41ea,0x0008f8d1d2d725dd,0x00001f39088332d2}, {0x00071e17829839ea,0x0003a502ae587b3f,0x000fc61150cf691b,0x0003144f658dbdbe,0x00005cd6ee653ab5}}, {{0x0008d7b5f1d23474,0x000a0cc2253a206c,0x000389e08794645b,0x0002889517d8ff58,0x0000fa20deedf847}, {0x00072d8d797770a6,0x000d5f429e26eba0,0x000af82797360c91,0x000ce31200a3b380,0x0000a1c9150e2dad}}, {{0x000d3a7c35d87949,0x00077356bae50ee6,0x0003322fd042e655,0x0009670f59698d64,0x0000379ae15e0a61}, {0x000ae62fcc9981ea,0x0000cd2934c664b9,0x0004e65ebaed3d63,0x0004278454b3025e,0x0000b09f64899950}}, }, {/* digit=5 [{1,2,3,..,}]*([2^35]*G) */ {{0x0003a1222248acc7,0x000ec264e366b208,0x000fdee281f6ec0e,0x000bb4e659b7045a,0x0000a823a4156430}, {0x0002a04e1900a791,0x000ab9ee65762459,0x0005ea54acde09d4,0x0005a742b6463f4b,0x0000efe9ed3e3ca6}}, {{0x0006dbe305406dd9,0x000f4d5d1957e27a,0x0007d4d8f8eb7dc7,0x000de4654a687638,0x0000c47940a57762}, {0x0005b5d99b307781,0x00065e793682be4d,0x000c740e325380c5,0x0004ae502d37f3da,0x000040deabe2566e}}, {{0x000d067afd32acfd,0x000a11f71ccf4481,0x00096f2dad8f0fcc,0x0003f90208dd0cb5,0x0000049d7316aad9}, {0x000263d42ab580e7,0x0000b3f707b4c79f,0x0005e0eda09411bb,0x0004021cfde1ff83,0x0000270749100f03}}, {{0x0006126c49a861ec,0x0005214f0d06eaee,0x0009bfc17024f3b6,0x00038091a3f1e8c6,0x00003c3a8ea67686}, {0x000752cb103d4c8d,0x0002c218b36b3400,0x00051504a02bc461,0x000bf9f67f75eb76,0x00006848b57a02ae}}, {{0x00002e6c30fa92bf,0x000caa552784bd98,0x00083169b5a70d96,0x000227a085c4ea3f,0x0000a9423bbf6908}, {0x000be12fe97a5b9f,0x000881b991182ffe,0x00017884685da604,0x00018dacbc2f7f63,0x0000d96bc7181532}}, {{0x00081db1782269b6,0x0008c597e5509583,0x000385153ae34bf7,0x0000485b5c60645f,0x0000f0e96b043088}, {0x000021577884456e,0x000b89310ea7bf6a,0x000fad2deb3b5688,0x000d4c37c9429504,0x0000020f0e5f7896}}, {{0x000a0ab0976505f7,0x0002995e2ec5730b,0x00031ab71567f681,0x000b9ed706201063,0x00002cfa977b1d22}, {0x0005ead8a2373da8,0x0003fba45a6833e5,0x000029d15a8d0d5f,0x0009f33a1d8f9c03,0x0000f34f1cd7c55b}}, {{0x000428dbbe5a1a9a,0x000e9126bd67cca4,0x0001058268187fd5,0x00019f6036973a48,0x000039b666458bd6}, {0x000deef2d65a8087,0x000f24636b196d42,0x0005d564c4969044,0x0000778611ee47dd,0x0000b2f3a4a42873}}, {{0x0007d45300eb294a,0x000d769c14949415,0x000a47aa92b2a656,0x000ea42000dd76d3,0x00002864e5046243}, {0x0006c47db89842e4,0x000721479fb78271,0x000b2f6dc12dfd7d,0x000d66fb9a2c56e0,0x00006be862b17f85}}, {{0x000d8dd0f82b2148,0x00097103cbc603b0,0x000d79e19460c34f,0x0007f8732e5c0318,0x0000b8888bb28411}, {0x00037dcc07226779,0x00088c1c0f278f3c,0x000f7a0c610d21be,0x0000e0447c8468e0,0x0000bf022143decc}}, {{0x0007d1242b48b998,0x000cc84240960baa,0x000fb5cfb1bcb665,0x00010d0b847cd6eb,0x00007c2ae571ad4d}, {0x000b1220de367261,0x00082fdfbd21f1cb,0x00079d460e7043c6,0x0002cb3bd0826a4e,0x00001f5e5985bd1a}}, {{0x0004160b7fe7b6e0,0x000a400a3fb29755,0x00028ca1e7d16189,0x0008ccd73e9beae3,0x0000dd04b97e793d}, {0x0003c9b506db8cc0,0x000ecf38814ca9c8,0x0004b45e65cd47aa,0x000a8426fc430db6,0x000079b5499d818e}}, {{0x0001102c1c24a3b9,0x00078c161c1aebb0,0x000f00a4aca24e56,0x000c7a803eea6936,0x0000ad76ee906176}, {0x0001fc2538e0ff72,0x00094604b3b09745,0x00049cfd794f8980,0x000f694311436e32,0x00007b4a7bd61224}}, {{0x000d21ae0ac29416,0x000462d3193703b5,0x000c992d0279b025,0x0001f2d307c052ca,0x0000aa7cb934fa8b}, {0x00025800d37c7a50,0x0007342d54225a18,0x000d2ef9213380c3,0x0003c692ac2d66d5,0x000035a70c9030c6}}, {{0x00025dd4ce4f152f,0x000109df7c06c160,0x000e4bb141f419a7,0x0004cd7d5b221491,0x0000c43c6cd739fb}, {0x0006591925d6b2de,0x00028218659849f0,0x0001b16294b37d9d,0x000e04ac54a971d0,0x00001a9c2a031d50}}, {{0x000b78571ba18615,0x000c80c8f93d5109,0x00033bb9348b22d5,0x000d0898fa84a786,0x00003fba6baaaebb}, {0x0007df3e5eea7d82,0x000648ca71587ff2,0x0006f1a05521c879,0x000ee499d5133bce,0x0000d50cd541d0eb}}, {{0x00015d6c5a3ef169,0x000d2a079221c821,0x0005da81c993eff9,0x000d8554da2c5e4b,0x0000a89dbdc1033f}, {0x0009ebf2b892891c,0x00009d14a4d56081,0x000fda42153902b2,0x000283aac35051d7,0x0000c6ab88621c83}}, {{0x000a133f74cff170,0x0003ecb813f214eb,0x000665bee240aaa0,0x000d73cfbb65406f,0x000084b1fe4a425a}, {0x0005d16d081f6a60,0x0008eef82c90009d,0x0009eaa2235304fe,0x0001e3f20346d5aa,0x0000ada9f07ac1c9}}, {{0x0001678968a61446,0x000ba7b31a1ea6e2,0x00081fbe154c1f77,0x000c4a76bb787e57,0x00001bd2ee1431f1}, {0x000a1e9781105fc0,0x000f7b2f8e80f25a,0x000ff919b9cf2971,0x00096e26d15412cd,0x00001db4ebe34bc8}}, {{0x0003e23b40df1cf8,0x000314e971b47d9b,0x0009cf9215933737,0x0000643f57bd1466,0x000065daedf8c1a1}, {0x0000bd3832791254,0x000ef4ecdaab3eb7,0x000755cafbc3d5b9,0x000f0251e3ed7e5f,0x00009699f55141e6}}, {{0x00070e1d4a7a15b6,0x000a8aac87e71857,0x0003133ea08f3587,0x0000fbd52018db47,0x000074ce71964fd3}, {0x0009835088b3e0e6,0x0008fd0d47a17b8d,0x00074a3c47a0356a,0x00066c3d9e765964,0x00001ea48a85f669}}, {{0x00077580f3e48342,0x0001f7a9afcb3041,0x0009a67b3fdbb21c,0x0001a8556fa17f2f,0x0000a6b2421c245c}, {0x00027944af02291c,0x00056a5804fe64be,0x000f08fd7ade465c,0x00003acdffbd39a6,0x00004efa84d6a144}}, {{0x0001b2a442b0f5c9,0x00073f997736a1b9,0x000e90e16b748e31,0x0008bffd1b62bfce,0x000007ae2719b207}, {0x000534b0c9bcddd6,0x0003d9adce83df31,0x00026846a043fb05,0x00039339031043d8,0x00001a9c0d71144f}}, {{0x0008046477184276,0x000b0e830f8bdab4,0x0009a1347df17ff9,0x0004ade08d7ee8e4,0x0000ac71e23f1c1d}, {0x000b9fd1defd73c7,0x00074bbbfec5c8cb,0x0007ef8ea1984065,0x000f2fc9db1cb59e,0x00008aa8296d4105}}, {{0x000b7f0a3738c290,0x000abc3250a3a3d9,0x0005e4caf0a2f235,0x000f7a55e506f644,0x0000974f73d33475}, {0x000bba35ba2f5a80,0x00036af40066d37d,0x000d73e2c542c6e6,0x00033e26d99b53c5,0x00006060d7d6c3ca}}, {{0x000f1c2065fef4a2,0x000ddd5b92e3cdbe,0x00070835077e60f7,0x0001bfb7c549f026,0x000001b3ad054f12}, {0x000c2a10334fc145,0x0008e44552f65fca,0x0006530828a9a9e0,0x0002892dd8a1d397,0x0000fc0738fc9d4f}}, {{0x000244d17d2d8c38,0x0004f0830684787d,0x000f73ae5effc634,0x0009a4dddb96dde4,0x0000efb14b197254}, {0x0003eee2245ae7aa,0x000e4a11f13e6eb7,0x000b01f5dbca4061,0x00052c1577421d30,0x0000a688b25182e1}}, {{0x0008e71bd3502bad,0x0003e4de75a06760,0x0006125e54ef41f2,0x00043ee08dde5efd,0x0000e48482674095}, {0x0008d9865cc22950,0x00016e0edfa21f19,0x000f35fc7428a377,0x0003c74f9697a2ad,0x00001a43c79f7cac}}, {{0x00070590fd3659a3,0x000c8b7f2d9ab05d,0x000f984d38927f30,0x000a451023d1ac8c,0x00002125ed332897}, {0x0002dad3d4142055,0x000293fa82a9fb57,0x0000a558173000ef,0x000ca4fc0868e9f1,0x0000b61fc67bb0b3}}, {{0x0008d5b7cae440c3,0x0001102b7531c125,0x00093232121c08b4,0x0008afc61a8955de,0x0000568faf85d140}, {0x0005e999ecf965b6,0x00088917276f71b1,0x0000cf9e2f14ed24,0x000c7e66f4caa182,0x000081b20b278d83}}, {{0x000738dc6c011203,0x00037e70e0db6cde,0x000afe18c71db081,0x000be765fc064474,0x00004619053429e2}, {0x0005ceadb2a3b15d,0x000e0b4c70738061,0x000d2d3670a49a19,0x0008a93e1b84c88f,0x000074bf462d33fb}}, {{0x0006d65533ef2177,0x000453ca2e87889f,0x0002b41677158c7e,0x00057f8b670dfbdc,0x00005910a01f44c2}, {0x000bf07cf88577d2,0x0000c45e2acef336,0x000a23d852224525,0x000f580ed92e8d7c,0x00009f8be4c4b812}}, {{0x000baa7076fe12bc,0x000aee1537f9dd9e,0x000bdfb463f2400c,0x000b405aa9352817,0x00000f9843127883}, {0x000ede10170911db,0x000a84d4b17f5590,0x00026b8d27562f5b,0x000d5931fa1df218,0x000040b796b1bd80}}, {{0x000f1973467ba92a,0x000b570954b0d65b,0x00078f15d8c9b46d,0x000960f7c8a0f30e,0x00008f3a69b25a4c}, {0x000660f61e4ce9b9,0x0002dea6790c4242,0x000986416bf06aab,0x00022536706f8eec,0x0000e56dec22a9fc}}, {{0x00046f49a9898d9a,0x000ab633cdef527c,0x0009e4297d799e77,0x00073384eacc167d,0x0000bb61ceb0b1cb}, {0x000e8a7f778443cd,0x000059de2fe6bee2,0x00003bb6f3bb42bf,0x000df5fbed86a130,0x00003918e6da781c}}, {{0x00032719a5103f11,0x0006e50eac064bee,0x000dcc1195243efc,0x000a08a8e122cb6a,0x0000b7faa84d0b80}, {0x000d1bd6dfcd08ca,0x000d6be427de32c3,0x000263c83129dec4,0x000efef8ab679c1d,0x0000fc83cb86ef64}}, {{0x00060882fa6be76c,0x000a5328cbfe85eb,0x000618dda892585f,0x00026e0154d3edcf,0x000044f601bfabaf}, {0x0007d0b2be1fdfdc,0x000c61137fee7bf5,0x000b591a8a833bd2,0x000055d353af362d,0x000076f26dd1562a}}, {{0x000e47d3fdf5a517,0x0002e5c9cab01d87,0x000e0586e7afb5f9,0x00070921bbf58f89,0x0000c72c0187d843}, {0x000aafb99b5c3dc4,0x000cf844aeb0a9a5,0x00067e482a48a0f1,0x00059a3178b7ddb6,0x000053985e9ae23a}}, {{0x000c86001b25dd8c,0x00083b897c8a4a54,0x000a90cd90dd37f4,0x00030c9f8aa6100e,0x00008892c68d6d58}, {0x000efc0ef514ca5f,0x0008f72c9ee6eb4b,0x000c40d5f478eb67,0x000649abca20dadb,0x0000015de22cde4f}}, {{0x0004de0eaf4b8a5d,0x00097bc60e32aa6a,0x000d15e7068cfd9c,0x00009c968a4b017f,0x00009f0694bc27dc}, {0x000cad5ba708bcd2,0x00093bb95c2af6c3,0x000c0a58f5cd2ba6,0x0008708a28c1d333,0x00003e274e3cbc77}}, {{0x000692ddfd20a4a9,0x0002f1a6665344c3,0x000a0757d091c5fd,0x0003e9dc0bb69109,0x0000072e8b9f6734}, {0x0000eb080848beca,0x0009d9fd36cc31d4,0x000ed43f595bd480,0x0000be61a77c6165,0x0000fccd127ce0d4}}, {{0x000c82d1cc1884bc,0x00009d4753b4eccf,0x0008e099fc85ac20,0x00039007a6caac65,0x0000f46369ec4b27}, {0x000d049506467ea2,0x000217cdeccce2e7,0x00080143a481b63a,0x000b882029abd8ed,0x00008bfe3c7dcb00}}, {{0x00010090643d84a3,0x00087bd110413bec,0x0003a34d6885f366,0x000ebeab02432cf8,0x00002f7b360a19ce}, {0x0007837dad1fe7ac,0x00089441a0b0f06c,0x000d4755060a157a,0x00001fb04970e9e2,0x0000d2bd553e71b9}}, {{0x000f82f33e24a0b2,0x000fd2565079ff57,0x0005f58259cbee23,0x000661f6353427eb,0x000076feec50948d}, {0x0002bc6da10032b9,0x000d60e72a53d1b6,0x00020e7ba718351d,0x00018d0345207624,0x00006368fffca001}}, {{0x0002d26150a49e46,0x0005df04706b00ce,0x000b196d00c28b63,0x000b7c5ad65a4658,0x0000c8455fd4c9f8}, {0x000895f2d71867e2,0x000bcdf9f38ce90c,0x000f6ec045c0be31,0x0002510a37a15ed8,0x000039639e7acd85}}, {{0x00053159c7c4c6b6,0x000077409af7d897,0x0007132fb603aa3c,0x00023858d53d0c00,0x00008d12af806849}, {0x00007e7bf5d92796,0x00054ada74cebe06,0x0007e8ccb9aa5005,0x000f5e881079cbba,0x000010c71d205f4f}}, {{0x000e1a75aa07093f,0x000ab75da47c9e2e,0x000e75401ca84004,0x000591174d39513d,0x0000938f757ab311}, {0x000761800a43421b,0x000157bc78c89619,0x00017127639a2536,0x000f07778f710a0a,0x000028446eb3d1a8}}, {{0x00081bfe3b6a6611,0x000dd6d279f71847,0x0009eb6627751cb1,0x000ea7e8ff95d6c5,0x000086d90b768d3d}, {0x000b6c1dfb4f754b,0x000a7b2801dc0e4b,0x00054564d5c5cf56,0x000f131561e4521f,0x00004fb8c61a0dd7}}, {{0x000963033ff98c71,0x000abf17769cf884,0x000fdd80a9619fff,0x000e63e8090bf61b,0x00004d9a149522cf}, {0x000c3606f6df9ea2,0x000d018f17eab354,0x000eb3480dbcf770,0x000a26007db7c879,0x000013dbda8759b6}}, {{0x000200b29fc81b30,0x000f171d87c1ac4c,0x00081aa9eebc3e09,0x0004fa9179953014,0x000051b92e192e11}, {0x00092e9ecb5537f9,0x000b990c7483df8f,0x000deb01644b1b2c,0x000c2c1711455a2a,0x000064b685711a10}}, {{0x0009d99cec036235,0x00059f3271ea4f15,0x000ee48490553222,0x0001036231bea3c5,0x00007a54f50c094f}, {0x000421d9598b3525,0x000c17412ab43e2d,0x000c3a912e865a49,0x00065d82998a251c,0x0000d0928085c74d}}, {{0x00059084088567a3,0x000def214a6173f4,0x000f0c13deb6b280,0x000b805c9adc34ca,0x00009d129392561f}, {0x0003a5ebc6edfb49,0x00016e4d210eb2dc,0x00086ae727485b1b,0x000b87762e0400e1,0x00001e32d5cfeeb3}}, {{0x00074d74be59224c,0x000bb16d55f36df5,0x000d6ed33ebc88cc,0x000b0f66c2e6d0ca,0x00006e21e7dcd3e8}, {0x000840e5bcc36bb3,0x000e4da74f692cc5,0x0005193a89292445,0x0004135be8d3214e,0x0000ec23629bdf06}}, {{0x000ae85b134defa9,0x000f8bb2d475c7e9,0x00063c00d6073b1c,0x000ac429ad615e28,0x0000e29493de25f4}, {0x0001dea4e9acf4f7,0x0008350db88dc32b,0x000da916c3e1f01c,0x00003e405d70ea04,0x000014b0d0b48658}}, {{0x00093fc9920cb5e5,0x000742c7a3ac4bd4,0x000ec92355b44b1f,0x00055352a77293bc,0x0000ee06e881d378}, {0x0008173da621607b,0x000be9f5d290ceff,0x000f734ac2bb03e4,0x0007317945106aa6,0x00005056605825c4}}, {{0x000920ce079afee3,0x00003789831f5945,0x0004a5ae5686e17a,0x000d462966bee8b7,0x00008a673a24e258}, {0x000c1f283141c954,0x000ece96e486bd1c,0x000e5fc783b2ecf4,0x000a7a8d3aa89674,0x000015ec10c6482f}}, {{0x0004419805033800,0x000ad314b3921523,0x000caecae513d917,0x00080bb0b52f4e63,0x00007bf22ad2dc77}, {0x000e8a1e4306839f,0x00016dd7feaae761,0x000c778f11b3be96,0x0000f55fe728de74,0x00001fa0bdb4e007}}, {{0x0005a316ec3f510d,0x0004029804758520,0x00030ebfd2c7e4a1,0x0006440e3c19c06f,0x0000b1c1f39a4b7e}, {0x0001a755dce364a2,0x000be58f5be3fe29,0x000fea38cb7b22a3,0x000e170cd2c30237,0x0000930967a4e17b}}, {{0x00009de0c061c658,0x000c6dc6ed4487f0,0x000afb1ebcb014aa,0x000687c9bd1cb43b,0x00001bd8b5ca82d3}, {0x000b87ef01a17aff,0x0003f710063b1cda,0x000fc819321f37ac,0x00015b6a6c567642,0x00004753e7146a60}}, {{0x000795ea15b0a44b,0x0006d958a958020f,0x000b675b58f37c8d,0x000ae9b3b7e89ba4,0x00004fb0c0cbfc31}, {0x000e639a7ff1f2e5,0x0003119614fbed95,0x0007151ab9880f5a,0x000cdb8eb6ff0294,0x0000bc5118cf868d}}, {{0x00020554c20cea5a,0x000d74c4d69ad8da,0x0002d599bcac2776,0x000b502ccb22c162,0x00004ddb65408a9b}, {0x000f1511b4941b44,0x00042efba5882c4f,0x0008345e0e1ff19b,0x000fc3f5034363c4,0x00005542e3d5e29d}}, {{0x000cb91349f7aed5,0x00003fca8420f197,0x000aaf6d83b2b5a0,0x0002b62c175ee823,0x00004dcf42185af3}, {0x000430727d6561e7,0x00046175b1e20ba1,0x000807db5879d5ee,0x000bcd57c4367399,0x00007a544560cd55}}, {{0x000ff130105c0720,0x000f8dda7da4e6c2,0x0002d35c118f7a99,0x000c824c3018200e,0x00006a53ca0d9cc6}, {0x000cc1ef1aa1d9e1,0x00043a75b1e8aa21,0x000be9fdc3241433,0x00055a1a6d13280e,0x00006bd173fa8a47}}, {{0x000b2452133ffd9d,0x0000b30f1a20fbb9,0x000a1f52a39a8b2f,0x000df7784bc97dd5,0x00006aebf57740ed}, {0x0007acb76ccdac60,0x000c1586ff273225,0x000de7dd1af4d36e,0x000c168eaa8863f8,0x0000045d5cf88647}}, }, {/* digit=6 [{1,2,3,..,}]*([2^42]*G) */ {{0x000d574c005979da,0x0001ca40e350a6f3,0x000e2ecf9c2072b4,0x00044e5ca5c1568d,0x00008c8bf5c45153}, {0x000e555114df14a7,0x000d8dc5ec6b97ae,0x000a85418d4374a4,0x000f78054cc28f2c,0x00001cb9e2843c41}}, {{0x000507903605c397,0x000e3142c96c8910,0x000923684f0843d9,0x0008938374493416,0x000032caa306a0a2}, {0x000c27061160170e,0x000b637fbaa3b2e8,0x000eda3acc32788c,0x000e0659cd818ea6,0x00002e9423a7e2b2}}, {{0x000d39b0260e52a4,0x000c506533256967,0x000ca7954d42585c,0x0007b2cd9bd60521,0x0000fa20877c1ed5}, {0x000eff8e34a0bbeb,0x000bd4f6ef6460c1,0x000af848356b0040,0x00061378be2b24b1,0x00002278164a5531}}, {{0x00075455922ac1c3,0x000c752b3f638df2,0x000de57c4a7b3ef5,0x00008b5e77b21471,0x00001682c10b34c0}, {0x00024f04bd55d319,0x000587b61c71c768,0x000a5089db6d1c08,0x000d3ea1db0903c2,0x0000c092172a84e5}}, {{0x000ed5bc00cc638c,0x000aa1278fc2dd7c,0x00037f8d61a2015e,0x0003ac6e8e52886a,0x00004577870a7993}, {0x0004cce2c51211a6,0x0001c4c20498b3fe,0x0008db5e5ad9b10b,0x000fc330d87a4fd2,0x000098cd1059aca2}}, {{0x0002d07e91b536de,0x0001beba09d64f11,0x0007c396fceb982f,0x000b235c157b2c19,0x000023c2d425b66e}, {0x00057d93f330d370,0x000179108deb480c,0x000199ce5b3a4c8a,0x0008d4702388decb,0x0000b019211b944a}}, {{0x000a692840bb3366,0x000c4669fa7b24f2,0x000c9c3007c353bd,0x000f177a20d6fcde,0x000025fbe30013a4}, {0x000b61adbc173281,0x000f99515621a2b1,0x00020ff46008965b,0x00091c39690939c6,0x000082dd27d9717e}}, {{0x0005035ea6c39976,0x000a62610bef5ace,0x00080dd3954259aa,0x000a398f18bb3f3c,0x0000910b95bbfc3f}, {0x000f51043e09aee6,0x000f47675665fce2,0x00072db61ced56c9,0x000e68b0e265acd8,0x0000982812f0e9fc}}, {{0x00011c6ce8009982,0x0002990360d929be,0x0004ad59072bb175,0x000bc00c1931975a,0x0000ba2f548bfc1d}, {0x000eebbe490ebe0c,0x000cbfae11c07fe4,0x00003ba3712a0a4c,0x000dd7b197cf81e9,0x0000f7d4aa99e1c6}}, {{0x0006bf43fd5684c4,0x000f40360aa192af,0x000546a822b26eec,0x0008fe7d960f3000,0x000007b3c44359ad}, {0x000e5fe249c82ba0,0x00072463744c86ca,0x0009162729e0faec,0x00061587f551e894,0x000033f93446ceb0}}, {{0x000b0d18be82e84d,0x000daa582fef1e5e,0x000e921fa89967f0,0x0009b9ecf687d5a6,0x0000fee4cf4a37a0}, {0x0006965b493c465c,0x000bb635c03094f0,0x000f05e9f638b9a1,0x000724b666786466,0x0000caf6809804da}}, {{0x000b690768fccfce,0x000cd835b362ca2e,0x000fdfccef402d37,0x00098f2efac0d0e2,0x0000fc9cdf09638d}, {0x0002b72d1669a8bc,0x000b9774ccbd2af1,0x00034870e33c536b,0x000ac970b21909fb,0x000038fa2f83df25}}, {{0x000f02bbf81f3f5e,0x000dcf7e458174c5,0x0003c54ae0525a5a,0x0006c4a8d2aaba43,0x0000d9775dc606a5}, {0x000738ac0edb37d9,0x000dd6cc1f51d320,0x000600d7625fdb6e,0x000d761c661d1710,0x000031ec1f44dd1e}}, {{0x0001d6219ee43f1f,0x000d70829d9765c1,0x0004be6e85cd57c3,0x0003bce26c91a398,0x000008d930a7b0c5}, {0x0009e5bc016e4eae,0x000831d43d2b94bc,0x000701155d391683,0x000714a86c5ad773,0x0000037762700b00}}, {{0x000c9ecaa80ba596,0x000a08538e517f01,0x0008128af3083411,0x00014b370370f1e8,0x000025cc3dbf1dec}, {0x000666c01ac3107f,0x0006e5057ac3fef9,0x000be5df7b2a8d57,0x000923c0f2629992,0x0000579c8e5f0353}}, {{0x0003d931341ed7a4,0x000c67b59d49b8fa,0x000b8c4a44223272,0x0002e3fdcb194783,0x0000e413c022d130}, {0x0009127e17e44ceb,0x000483b3adfb6d99,0x000aa96caee86bf7,0x00047d46902fe625,0x000073540e595aae}}, {{0x0001d7b1b4a158cc,0x000d67e2a3693280,0x000d9f197e571c99,0x0000ad80cb76c010,0x0000308c289f167c}, {0x0009dd3eb7958f24,0x000bf00879b1a6ef,0x000df0636a7226df,0x000eed2cd0b3627e,0x0000efbce6cbbc37}}, {{0x0002a058d6990216,0x0009172566e375f9,0x0001ad23a586d4c7,0x0008abd78ca5f176,0x000050d86fc7465a}, {0x000d457842ba251a,0x0005a22349337a4e,0x000aad6576b65e3e,0x0003690f1543b731,0x00004cefe996bfec}}, {{0x000da909f47befbc,0x000a81312d13b587,0x000f1cefe6562e9f,0x000cf5e691ea59ef,0x0000c30477ac5fc4}, {0x00024610b0ffd3dd,0x000a8b355956a163,0x00024ec24a1f16f3,0x0001298b148d5342,0x0000c834e7cc9770}}, {{0x0005e75b2c69dbcc,0x000843c3da6c7bfc,0x0009102713aa77a2,0x000c551e0df03cca,0x0000bd5ca4b3806d}, {0x00058076db476cb9,0x0001cf37a31ee1ca,0x0001af416fde15d6,0x000db5649af520f4,0x00006c5c5b20d342}}, {{0x00043b7eb4ceb9be,0x000f6e77371a155c,0x0005d43af2e99300,0x000d713d2987da67,0x0000f2bc1c16599f}, {0x0004b7b9342f6b2e,0x00019c8e71f09689,0x0001f3efc201eadf,0x00070413479d9f4a,0x00000f8a743502a9}}, {{0x00044b6b3eba40cc,0x000901c1e0d0eafd,0x0009d505ef9739f2,0x00063d4091471a61,0x000015f9c975d7c2}, {0x000728583afbe332,0x000ee4f1e0925be4,0x0001a9d11a3b6d6a,0x0004d2c76526b975,0x0000ec5b26dba4ae}}, {{0x000f4d902f6fb8d2,0x000176912164eb66,0x000ef30004063c56,0x0003f0cb7050c180,0x000088d1c340aa5b}, {0x00068d607806fd8f,0x00045bbbf50fe87c,0x0008d6627b2f7f9d,0x00013a35972f3aac,0x0000854777500e8c}}, {{0x000ef6c872b4a606,0x0003e613521bcc50,0x0003e15d1ab2a34a,0x000511d9c5c19098,0x00001dde5dfb9905}, {0x000f6219f2275f33,0x0006151d894be417,0x000b0bdaa0750c8b,0x0009bd45b04ab978,0x0000bfd9fd475858}}, {{0x0003e30ee9120b67,0x0002b3a4743ef101,0x000d14d9e2b51af9,0x000d327a96ffae48,0x00001dc0dbed98a1}, {0x00062d20180cca4c,0x0007035689639149,0x0007bc4441ae6067,0x000c79ccf227b143,0x0000650c83c89962}}, {{0x000c7ddfe7ccfc4a,0x000c7b929d4823c2,0x000783c33f925c89,0x000759a460f74b06,0x0000c2c8d4a45904}, {0x000b407b807bba06,0x000d09ff8f3afb40,0x000ef64a49d1e362,0x0004b2433e9681cb,0x00007ece5fa932fb}}, {{0x000a99b739f10e3a,0x00095f5259256900,0x000e2d041c3341ca,0x000ddd4e18a626a9,0x00005a83685c9580}, {0x0000c819d7de3cd3,0x0005f062cf9cf347,0x00010edb0edf0258,0x0001aec43522fac0,0x0000031413543a4b}}, {{0x000e02adb22b94b8,0x000921eaa45bc792,0x0001e1c63993d8ae,0x00088a0aad6cd3cd,0x00009529ca845ce6}, {0x000e3aae572a2530,0x000802a21efb2cce,0x000430358e02b643,0x000504a7091b6ec9,0x00006d1b1fa9d7db}}, {{0x0006d32c47447335,0x0000e79f9e345884,0x0000ef6ca40517c7,0x00003edf65655f13,0x000026e448941f35}, {0x000bd177ee4a9765,0x0003421363d18467,0x00069e0411d9dc91,0x000f5188d24c33b0,0x0000eb5da0a7cdf7}}, {{0x0003cb1197b994f7,0x0004b843eae91c0f,0x000097ea53c95a6c,0x0008670766ffc9a6,0x0000bea40944723b}, {0x0001f734db378f9b,0x0000337b77acb48e,0x00024ad4670025b0,0x000a84e43dc8e7af,0x000098a15acc6d00}}, {{0x00038ba2743b0043,0x0007034415ee3adc,0x00062d05ab1c7f4f,0x0003b6ba43df8f1e,0x00002618905cd76a}, {0x0000bb5a23a0f46b,0x000aba01918c2fbd,0x000743f945bc971d,0x00022ac801d94ab4,0x000094df65f176ae}}, {{0x000bfabaf95894c5,0x0006d76b2241aafc,0x000dda48b7b9bdc0,0x0004df9af983625b,0x0000977faf2f3fcb}, {0x00042ef052c4b5b7,0x0000967591f0bed0,0x000f24ec79fe87f7,0x000f1b589c73ca22,0x0000d37fa9f564a9}}, {{0x000841a15562627c,0x00030243b0342710,0x000c686092c01a61,0x0001f55d135c562b,0x00002ca17164b03f}, {0x0006c2d3eb81d82a,0x0009ef6df13ec996,0x00072b43bc02abf4,0x0002afd7b34bd78f,0x0000ff6218fd60c8}}, {{0x000726c8d55b9d21,0x000989e9bffb0aa5,0x000b9e72adc0adbe,0x0001118097549cef,0x00006755712adfb3}, {0x000f984f26847f99,0x00074fb30cb7dd8b,0x00071ef9cbcb8e38,0x00063f31fd32a751,0x000077f3fc7c89b3}}, {{0x000af2bf4babda01,0x000de7113c8e116e,0x000def526feab68b,0x000a02c1e3f064b7,0x0000ac30885f0b3f}, {0x0006e7b40142d9d3,0x000300921c0b1c5a,0x000a116a3839b560,0x000e6d18f301fa36,0x000080e1107ffd9e}}, {{0x000ead858854be16,0x000e6bd4d49d7945,0x00029c2ef4111c12,0x0006f58ce3b1ec3a,0x0000356d404ed361}, {0x0006a8f594d320e9,0x000d6651ccd29f0d,0x0008fdde40989316,0x000bbbdc32117a0f,0x0000abe5cc6326a9}}, {{0x00060fb9723f6711,0x000d6f3d593ccff5,0x000ba069621b2a12,0x000384d4cb18da24,0x000086e2220d3543}, {0x00064e088312c29f,0x000827dc7752722f,0x00085ee8994282a9,0x00069f72467bbf5a,0x0000435c651e1007}}, {{0x000153943b3a50bb,0x000b6a53efbcc9ff,0x000b0c5b77132130,0x0004cb81bfe063f7,0x00000179a7dfea99}, {0x00064b3c85f455b2,0x00086f6e006212d0,0x00075d6d94725932,0x000cc7d64e590bb8,0x00002dd6225cd92b}}, {{0x000038eb9c3bd6dd,0x00062bba27c8b658,0x00062c45d00cdb0d,0x00007c3c68133710,0x00008515b8cfd334}, {0x000699e8cbb5ecf2,0x0008a608d7d8cb8f,0x0003e00db8c4347f,0x000d190c11850abb,0x00000a8dafe0cb49}}, {{0x000148045ee2f40e,0x000e616b60cfbd78,0x00049a8c475e354a,0x000535fe0b58a18d,0x000040e94e3da359}, {0x000a59f62accd765,0x000a3c762837bd4f,0x0008c277b05cf466,0x00074065abda9944,0x0000a9e01bf98b13}}, {{0x0007798326aad8d2,0x0004a396f7e79d45,0x00053e292bdef495,0x0003e74fb274a2c2,0x0000800bf0a3cfe5}, {0x0006d3144438fd49,0x0002ce259f9a2242,0x000f66264ef23392,0x000faab188503c03,0x0000e5e7f140f9fd}}, {{0x000b76c5fcc1aba9,0x0007c9b5bff8565e,0x000b6d3faea63254,0x000c1ac587c087aa,0x00002b639eafce39}, {0x000e782953b135c8,0x000dc25268ef0706,0x0000e74697308912,0x000e74d99e92c709,0x00003b90f531bc35}}, {{0x000b3d0244975b3f,0x000721965d724750,0x0008dc751f3a4435,0x000fef279c67749c,0x0000f18cdffc23d9}, {0x00038332028e2472,0x0002d3bfbc79c401,0x000880a8496e280e,0x000151d60417bdd0,0x000063c9f3d4a568}}, {{0x00015b32d2ce8114,0x0002b8291d2136be,0x0009fcfdb846dc0c,0x000b9a1cfa0ecb78,0x00005a0beee17535}, {0x0009f0796d69af13,0x0008299ab6dcec8e,0x000e2e09f31a7c5b,0x00054ba36d45eff9,0x0000cf49ef20cee9}}, {{0x0004cf3086cff9bc,0x000079a3360f6be3,0x000bfbd1d88dbd49,0x0005515e96b8cc0d,0x00001e5f7c08b7e2}, {0x000b21428819d98c,0x000bbaea9dcb0547,0x0001d68c8c770dd9,0x000ba7eef0d4c704,0x0000c2b9818d3cb9}}, {{0x000bc76fe86c6072,0x0007302a9a957fc7,0x0004dab636b7b933,0x0007bdf948dc27d1,0x000049dd198fae04}, {0x0006584a981a2029,0x0007aa893387e835,0x0005c72093531dd1,0x000b598be11f90c8,0x00003d2fe1f72a52}}, {{0x000bfe2ec6d6b975,0x00046d0aa5de8225,0x000779f5f9cf6d6f,0x0001f3411459cb54,0x0000649cddbd6aeb}, {0x00035793f26ce5a8,0x0001d50f431e3213,0x000b84c6fc289a10,0x0004d6d59dcfda73,0x0000497381a6e3ac}}, {{0x00055e6f2606a828,0x000110f2fb57b51e,0x000a4e37ce25f706,0x0007062cef6c2ab1,0x000064e359dddcf2}, {0x0006b187ce573162,0x00001a96b23d479e,0x000f16df72cab250,0x0008b5cd4898628e,0x0000056538d0f375}}, {{0x000865ef15d31016,0x000a01b553d7a7df,0x000d1429480c5533,0x000cd5d66e19974e,0x0000620742013c0b}, {0x000d9c4edc454181,0x000eb1cc4a9d21d1,0x000c462f0005b859,0x0000c7cf01f630a1,0x00005d06cf402682}}, {{0x00024ee3484be472,0x00062a0c902f9f7f,0x0000bc4532ff33e9,0x0008dae0bdf4575a,0x0000378dfaf3aa23}, {0x00020ec856720f22,0x000b767972912724,0x0008a15582ad9d95,0x000aa8b1242cc676,0x0000e287f8b7cc86}}, {{0x00073d0990cecaa7,0x0000f75d40807968,0x000f0cd84ade55f8,0x000d01b645eea321,0x0000a1efa1024e17}, {0x0008420037cc0618,0x000055d43e12f685,0x000218710682e05f,0x0002fbd9c3699427,0x00005cbba4dbf7cd}}, {{0x00097297a3cd22af,0x000b5a628397726f,0x0003165ed9f8cd5d,0x0003d327b93ab9c2,0x0000f5f5dc002282}, {0x000e4b5654a446d2,0x000f477257bac1e4,0x000766a56d1a9496,0x00074a4387ba94de,0x00003608bc8721ec}}, {{0x00022d76688c4d4f,0x000117373abd16a5,0x0002efaa39d6b428,0x00017fb62f07acb4,0x000073e00f8d3b90}, {0x0005fec49421c3e1,0x000b2dcf26783617,0x00020f09fc4e44f9,0x0006cf66df436b72,0x000072755fb4aa8b}}, {{0x0009d57446139cc3,0x00022fe0208fbab8,0x000e5d3990a0a6e0,0x000f0b9dbb63e211,0x00003ecaa12d8977}, {0x0008b21f7c426641,0x00029b65d08a5959,0x000502526b3e91b3,0x0002a8f35822eef4,0x0000dcf0176820a8}}, {{0x000598f3d589e023,0x000f81d63d2c50f8,0x00071cd07df0478f,0x0000cd5b8068bd15,0x00000c3aa5007967}, {0x000fd4b941ade7f2,0x000c1279001125e8,0x0003f9ff03d1debd,0x00069c45b6dcbd3a,0x000082736a4993de}}, {{0x000a0c3d41d3bd3d,0x000837a26bdeef69,0x0002edf9fb533b8c,0x000af012801d97db,0x0000c4a826ab1877}, {0x00058513d590dbeb,0x000b3e4e93576c1c,0x000b3337484632f6,0x0002e6236d36b779,0x000046833e44bbca}}, {{0x0003913f7fc0586d,0x000696bf47193789,0x0001855dc385315f,0x0001fda2c56293b3,0x00001416d4f54906}, {0x000ab7851047213e,0x00011040c996beb3,0x0008b1d0c447f6e6,0x00022df06d310d63,0x000028a41409ad15}}, {{0x00076cb82003f867,0x00069bcdbca3685a,0x000a4c455610d07f,0x000eebfff660219c,0x0000df39b883ea10}, {0x0005f96e22db2188,0x000a88a34c44b925,0x0009f92768cc6d9e,0x0003354d4ffb8685,0x0000fa15eb2d0d07}}, {{0x0003845cf2c24b5a,0x000eb2f9c3badf55,0x000a7ceb389f66a9,0x000685ef22b5b9e4,0x0000ffef809ae134}, {0x000e1c68eb8fac22,0x000b08aec98e3e53,0x000a43bcb93c1e4e,0x000a5196b91ec532,0x0000dbfa947d2d74}}, {{0x000d190ca84bad76,0x000f4d58e65ce065,0x000cb6e31fb13919,0x000c3edc41718bf1,0x000088969f066d05}, {0x0004ce721264d452,0x00095367532bd4f9,0x00045a39dfdfb65e,0x000f3b3b1be8b109,0x000029f789c4b8ba}}, {{0x0001f3e6f49f15d1,0x0008807f0792d8f4,0x000a6e867678ce82,0x000c89b69ace82fc,0x000006451aee01dc}, {0x000f7f019fc32d29,0x000c200c52d21bb4,0x0009ea44564633df,0x000704ff13549aad,0x00009a3bf518b323}}, {{0x00025a2534d4dbc4,0x000182a2fea30c96,0x00030fc1a45b8f1d,0x00073436ec21a1a5,0x0000bac9c2ade5bd}, {0x000d76a7b4e35876,0x000db182d9e35996,0x00007f13d0045cde,0x000a40baee24b912,0x00006452e97f7345}}, {{0x000b0549f950cd0d,0x000107fdd07516e5,0x0002496639cc72fb,0x000cca9edd61e766,0x0000e4caa4ec043c}, {0x000f57a55c7ac17f,0x00032a85e24d11b1,0x0006081e7779cbd4,0x00064288030f86e4,0x0000d4a60337e20f}}, {{0x00064880a750c0f3,0x00031e548e83cc7a,0x000110f0539bacfe,0x0005880d418c760c,0x0000e4daa4ce1f11}, {0x000e7b55ffc69ff6,0x000c320531272733,0x00022df9446f147b,0x000b7c285b2434d7,0x0000a444f6646fc6}}, }, {/* digit=7 [{1,2,3,..,}]*([2^49]*G) */ {{0x000465ac3f16ea83,0x000d82f1d11c7a1a,0x00068a172115a461,0x0006981767dd956c,0x0000392f2ec013a4}, {0x0009ccde526cdc7f,0x000b32292b81c7a9,0x000d391988e537fd,0x00052c86d8cf69a6,0x0000fc5ff4414468}}, {{0x0004f7ea90567e6d,0x0006e6ae5cb797b1,0x00010903d513257b,0x000723b5454a3c9f,0x00008d2c9ae39bc3}, {0x00093246b29cb44f,0x000c87c8cbac38da,0x000918e42b540a21,0x00014dabbfe43501,0x0000ffa707b46c36}}, {{0x000e3f1d4e353b7b,0x00043f46b0a00ce4,0x0004b73fd062d8a1,0x000ffcb408d5ab57,0x0000c41d1ca83273}, {0x000e1e76be77800a,0x0007256550313538,0x0009b331a71fe8b3,0x000f727cd916216b,0x0000d825d0c5b388}}, {{0x000e05b1cb76219d,0x0000a1567e7e56c2,0x000c4c9100ec0bf9,0x0004d917076f8661,0x000067b085c8abc0}, {0x00004595e93a96a9,0x000a6bdc249a9fb9,0x000dd0bb77526c1e,0x0006947d44d367ec,0x000053999182dc0d}}, {{0x0000ee99e240d181,0x000ca4b944666136,0x000e5325c057cdca,0x000e3bd7667cd12f,0x0000fa297b531974}, {0x00081e7db083d762,0x0006d206bd15fa40,0x000c19f8c31993be,0x0003576949269b14,0x00001468d72c9d92}}, {{0x000c583a4c506ece,0x0007f1acfe972ccb,0x000f1aea2957ed18,0x00062cabaed83312,0x0000f2a6cb563253}, {0x000de428e195c43b,0x00095e6050c6130d,0x000686a5dc842025,0x0004a77da972a708,0x000052999a29508b}}, {{0x00090b910a5a8bda,0x0008696864dad9f0,0x00067dbc1ca91d24,0x00064bee6a93be3f,0x0000cae6fbb95f47}, {0x000c6e0d21411a01,0x000fca0a4ad81563,0x0008c803028fa787,0x000f07c524491c90,0x0000257ba0e5c795}}, {{0x0009167ceca9754a,0x0005ab7939a083f4,0x0003fd0bf426d2cf,0x0004e18555e35572,0x000096e6d0764f14}, {0x000a8dd87880e616,0x00058508e4d54768,0x000b65e151554381,0x000f9fa9d7e772b1,0x00003439dd70c302}}, {{0x000802fc14e35c23,0x000c1341333cb93f,0x000d4f36271735b7,0x000c8dd3a2510416,0x0000f4d069bef433}, {0x000ae01f78f5a7c7,0x000e0c4eed070d83,0x000e10f8350a8ffb,0x0008e1574f890676,0x0000d0809670ddaf}}, {{0x000f8e1698e04cc2,0x0002f69005c8b11d,0x0003c6179877be20,0x000c0512749e8c4f,0x0000dbc9d0a9853f}, {0x0004f939454d9370,0x000db4800e1b187d,0x0005e68e8e682ce9,0x00085ba9129ad816,0x0000fe29735be7f7}}, {{0x000f40c5b9e02b75,0x0001e5ee04e85303,0x000d6632ba37c969,0x00045b0f46cc2034,0x00005ef72b2e6ac5}, {0x0005c1f7b91b0620,0x0007bb33e821abec,0x0009f41170a79e1c,0x00075abb04b4283a,0x0000de1f28ffd2a4}}, {{0x0009ccf3a4434b4b,0x00006a7954dc3101,0x0004972a7a345811,0x0008dcf9dac80de3,0x0000043d05524f6b}, {0x000319e11137b1a0,0x000eed5cc03f021c,0x000ea5ad400a754c,0x0005b60aa2c794cb,0x000093e67f470c01}}, {{0x000fee9c97e3f6b8,0x000436da746172cd,0x0009806b9c10bcab,0x000f46bb02d2fcb5,0x00005185e8a21de6}, {0x000931f0eb6c4d46,0x000d74fa5b0439e6,0x000be7eb84d4440b,0x0009bbf418786e34,0x0000380e521fd725}}, {{0x0000351d598d7107,0x00065b3a4da420ac,0x00071de1f272c416,0x000b0f6b82fe1aca,0x000046e79f348f54}, {0x000c7364b573e9b5,0x0006ad4b50406e7f,0x00098d87b75d03f4,0x000da10c1cc36d0b,0x000013ba3f16f472}}, {{0x000af26abb177dde,0x00079891d56479d0,0x000232173f82ab56,0x0006184b6768a972,0x0000fbb3bb16c1f6}, {0x00011dba6d183586,0x000750916d3ab29c,0x00088e290519e279,0x000a7f74dc18f091,0x000048e86e3f8b0c}}, {{0x0003145983c38b5e,0x000b837abc8b859d,0x000ff7be6b14f176,0x000a594793fb9dca,0x0000be5a56015a66}, {0x0001dcd9f87dc596,0x00039bdbf5607cec,0x000eb32577c595cd,0x0005fcfb543b2226,0x0000908064724c93}}, {{0x000440381e9ede3c,0x00040af6df0a7f2e,0x000073b11243c389,0x000a61bc605bb11c,0x0000d06a5427a6a4}, {0x000894949d4e2e5b,0x00069af668802916,0x000a8503533649d0,0x000f4b0fc0c885e9,0x00004e52114ac410}}, {{0x000b70678a6513b9,0x000a0edb1943dca3,0x0006e2dd892ea4a2,0x00089372642216db,0x0000b45d0b52fd57}, {0x00070dbc69d11ae9,0x0008bc57595f114e,0x00077c2721477dd1,0x00059c2c2208b4ec,0x00005c5b4d86b68f}}, {{0x000fc6342e532b72,0x00027ae35290b8c4,0x00001ecbc386ba42,0x000fd6db5dda42d2,0x0000353dc8bc0e38}, {0x00085ea68f7e978d,0x00015ad6d11f9a0b,0x000f6886d96ec568,0x00014c8e279d6ce5,0x00003fe03ce0cb19}}, {{0x0001fa47ea67c77a,0x000f43ea810cfe54,0x00001d374952bd2a,0x00036dd91fef568d,0x00003a1c621af113}, {0x000d5a9c7ec6d792,0x000f1225c3425ad0,0x00069601bff7038a,0x00047ce03c6689bc,0x00005059bc765e87}}, {{0x00065b2f2086fbfe,0x0005a6916078fa49,0x000081d6cf6840ea,0x000644f7ac762070,0x0000600da3295328}, {0x0006f63529b8a80f,0x00073d7d6f3e0191,0x00064ca7ce80e485,0x000b0b39eb0fe8d6,0x0000017637cd7b43}}, {{0x000c80676cb25661,0x0001a24892d99a75,0x00008fe458f76acb,0x0007d86ae7b9cc1f,0x00009ef73297a490}, {0x000ab715f228bf03,0x0009517032d72db4,0x000abe3c0f3cdea3,0x00025bdb1f482edc,0x0000baf76b4eb863}}, {{0x00065e010089465d,0x0008be77c596d490,0x0003dbd953bab5d2,0x000498a636c3a619,0x0000ef5d2958246e}, {0x00058b9286b24756,0x00096d80862bb22c,0x000992388a0b9393,0x00014bd002c83af0,0x0000de01f9c4acbe}}, {{0x000688eadd70482e,0x00099b4a4e8a6aac,0x0008a6eef708de92,0x000c4295b6dd7375,0x0000a4bf353525b3}, {0x0001f2c87912868c,0x00052f09297a1004,0x000f3860ab1b1be9,0x000f4a59ae23c5a9,0x00004f0f83a115dc}}, {{0x000cca397f6306a7,0x000df8a3a4b03c7e,0x000a1d8a2744c44a,0x000577f9cd13a0b3,0x0000cad0a1ec256b}, {0x0003fcd33791d9ed,0x000ca4b2e05fea65,0x0007affa29cc2a05,0x000441a3b391dcfd,0x0000db7091f86b05}}, {{0x00027bf8538a5c69,0x000cf9abff17c71e,0x00071e3da195c63d,0x000fa06d3152851b,0x0000cbdfda88a680}, {0x00076ca849d7eab8,0x000abc2732719db8,0x00008dceaebe2764,0x000b6fe63357e3f2,0x0000c5bd833d65b1}}, {{0x000b4f59837fc0d8,0x0008279cf00fccc3,0x000df39909b641ba,0x0006b0f428243ddf,0x00003a594c482078}, {0x000451a526c45028,0x000deadb3f93b712,0x000ff0ccd9d39438,0x0004c37db261e3e9,0x00000344e3d607af}}, {{0x0000d7c2fa4f1264,0x00051c99a2327590,0x00025e0c308a3b86,0x000edee478b6bfdb,0x000082cc2c2b1db2}, {0x0007e645f321bb80,0x000b9a8005b437df,0x0008c19588a93821,0x000d0a3fa2f10ccc,0x0000d3322182c269}}, {{0x0008119e246b0e64,0x00049349fd1720ab,0x0001aa100b39781e,0x0001689293231eb3,0x0000b779c97fb032}, {0x00019e1c84705003,0x0008dc4c869d4b3f,0x000a6bbcc45b7efe,0x000bc1ab84f38aa1,0x0000b59cb15e2fdd}}, {{0x00014df3fd165e81,0x0008f61f8811ba55,0x000ef9f00499fd6a,0x000e8a62cd1fe0bf,0x000020a4bb989ad7}, {0x000d0955f4a5ac5d,0x0000c5a7a2f0f2ff,0x00017baf1cfd174f,0x000089042301ba9d,0x00002fa487b47f22}}, {{0x0009efeb1dc77e1f,0x000831c996829cb0,0x0006067bbe956693,0x0004559c5469016c,0x0000d37857551c24}, {0x0006cbe81796b334,0x000618e87f8b2b6a,0x0001b01b462d550f,0x000e11db763e1c7f,0x0000b93cfea5b1b5}}, {{0x00052381d531696e,0x000fa8cdde69b934,0x00086afc757201bf,0x000ea7fde922519a,0x000030438969d35c}, {0x000c1e18555970de,0x00084535935e7608,0x0002ea38b8267dfa,0x0008b4f4c60a5732,0x00000bf7978604ef}}, {{0x000ab28c06fece4c,0x000dd4e7b49d1a0d,0x0006dab28d405991,0x0008fb0542b6d270,0x0000b228da469161}, {0x0004164107d1cea6,0x000370f5d8f1224e,0x0006e41cdeb9fdab,0x000146602ba3860d,0x000076a72c5fb1f7}}, {{0x000dd984d6cb00b1,0x000ace2e8d7cffd6,0x0001c7936cef9c5c,0x00072e91bbf5d764,0x0000b95b230fe8f7}, {0x000a92ee8ac25b1c,0x000b7a18b7c6f765,0x000cc8966ceb04cf,0x00000367944cef0a,0x0000bb3c958034c1}}, {{0x00071a1a43ff93c7,0x000731e358a99c99,0x000d9bc825bc2db1,0x000051d5b4862ea8,0x00000ebfbfb9201e}, {0x00064c792871591c,0x0005f42d0219afdf,0x000d8f03cea5bcae,0x00033c1e536c552a,0x0000d6c3f4e676aa}}, {{0x000f6230bca6de32,0x000991e706fdbeb5,0x0009059d4dd20dd9,0x000c4e70b3ff9dac,0x0000d7b29029cccc}, {0x0000a59ce98840f7,0x00001410680a8a09,0x0003379a5a5d947e,0x000155d9ae346a92,0x0000dbc84fa228a3}}, {{0x000d91654a1aff29,0x0009aa78fb9bfd40,0x00029f95eabf318b,0x0007f9c0152ed830,0x0000fc1dd78558ad}, {0x000791513595c172,0x00086f62b3a95fa5,0x0003055b0b950466,0x000125707b5b24ff,0x0000e995e35ba84f}}, {{0x000cf697e9bbcfb2,0x0006c86d96e387da,0x00095a75c95d0c1d,0x000f2145726e3c2d,0x0000c3c9001ccd27}, {0x000b5616c973f57b,0x000bf52216431dea,0x000ef79d4108b7e2,0x0008c5afee9859c4,0x0000d62b88af0d4b}}, {{0x00029c4197c75d61,0x0002a7076febb4dd,0x000f2df11266a6df,0x0009ec8512d0ea4b,0x0000320c24f7b0cc}, {0x000e0e101a595966,0x000b8ff9aaac6bb1,0x0005aa6c98317c5b,0x00088f05bb405e38,0x000013439c1ef079}}, {{0x000049f16a66e918,0x00007a1b0e0dd730,0x0004c28eae97f282,0x000c61c131e00330,0x000020ab732d26ba}, {0x0009ef9287144234,0x000a6db10cb2b2ac,0x00086a4cc54ecfff,0x000d494781476ef8,0x0000b2c87b61b2f8}}, {{0x000cd200a44295d8,0x0000d8c6b044e857,0x00096757c707d7d2,0x0007142e8521f9f5,0x00007448f03e7b2b}, {0x000bc455ebcd58d0,0x00099122d3c113a9,0x00007664279bcced,0x00067d3c6442479e,0x0000cf227782df47}}, {{0x000aee471d444b66,0x000f65084a1d5e61,0x000d3eaf6211236b,0x000bf51e15bc9a4f,0x00008df2c350b622}, {0x0004f0f59bf4f363,0x000ba7f34d739e67,0x000497b1df883669,0x00003b948ac1b831,0x000023b925d81067}}, {{0x0006f4274082008c,0x000a08482bcb2215,0x000173479effc521,0x00048f9c6831bf12,0x0000aa2529084739}, {0x000102a8f1b3c4d1,0x00011d9bec0d84d2,0x000a546efcf64dfc,0x000ef1333febad78,0x0000f621ec38b73c}}, {{0x000d627373386156,0x000aa1d8edf66aec,0x000e86b66162082a,0x0005db233a811919,0x0000023a2523299b}, {0x0000c3abbf04b89f,0x0008be749a44f5bb,0x00013de3b6735eb6,0x000ccce0e058c547,0x0000df2593f1c3d4}}, {{0x000414efdd236675,0x000aaa2015ee1b8f,0x0009625ffdd52aac,0x00018bee31b517bd,0x0000ec9322dddb59}, {0x000ac85a96f5294d,0x000291a0666abc73,0x00008ac4282aa5bf,0x000dfb79755810bf,0x000021cdfd6591ce}}, {{0x000b57b67f8be10c,0x000b96ffa726918c,0x00032de93365d1a7,0x000d016435c50465,0x00000fc5e10e674c}, {0x000fcf89cbbb1423,0x000a7fc506926e51,0x000bcae221d436e5,0x0003b8466bffff3f,0x0000148c2fe2d55d}}, {{0x000fdc9233222fa2,0x0002c419fb6b52c7,0x00025497789ff109,0x000ca71cd6db9925,0x0000e85a1613cf12}, {0x000547cdc810bc9e,0x000ebd257c22add2,0x000d6b19bea3f458,0x0001a5842c1fbe27,0x0000d07e6b5f4048}}, {{0x0001d4286d2e0f86,0x0001ae8a9fd56ada,0x0008c1b49e592012,0x000afea2c936af70,0x00000f30fee8b4bf}, {0x000ad06858e6a61a,0x00069fd374d06637,0x00088defbce4c776,0x000b6599d54b2d71,0x00008c9d251956a6}}, {{0x0000f5eb24fe1dcd,0x000d9b73f24c58fc,0x0006507059eaf9de,0x000728d90d588b33,0x0000e5b62c67f2ec}, {0x000cfaed3c2b36ea,0x0004634435da5c72,0x0007ee145868c19d,0x0005b0e8605f93e1,0x0000a60c4ef17a5d}}, {{0x000bfd23b60c472f,0x000bfb1d3049bcf5,0x0003895c9af4ef13,0x000821473f44fce1,0x000029b382ffcbc9}, {0x000b85373efaef69,0x000c18c96f401bfc,0x000191e24cf56ac9,0x000dc247adf1097a,0x00008035f454f8a8}}, {{0x00071b91e750c846,0x000bfdc6c469f40a,0x000bc19c1c57f7b0,0x000db7e9a0e79c6f,0x0000b0f588a048eb}, {0x000d084a07c4e9ff,0x0000bb27de145d3f,0x000e08dccc383011,0x0003a21e4929fe33,0x00004a5ad2530bb7}}, {{0x000c2bf490f97ca7,0x0005f7a1ce18de86,0x00044478d288f09c,0x00003fc64bb88618,0x0000840fa433eedb}, {0x000fdd25a631b378,0x000e247c8b7d1269,0x0001c626694761f1,0x000fa77c0c2e1748,0x00005e16ea2bdaa5}}, {{0x0006033924910480,0x0003f4d402d7ccd8,0x0006a865c0c2f696,0x000a876336f7dfdf,0x0000a2a463cb5c02}, {0x0009be7bf2f12ee2,0x000246bad988b0e2,0x00023c1d7f0a2200,0x000c9807f87e0391,0x00001669c55528a8}}, {{0x000980392f145296,0x000c03954df3186b,0x0005a46f6d3d056c,0x000557cf03fd5817,0x00003e34ebe71558}, {0x000edee5b80cfa5b,0x00002401dbd1e13f,0x000a9d667e872a12,0x000692a2657616e8,0x0000c8da4b7908d6}}, {{0x000b9bb1b703e75a,0x000634338363370f,0x000ef7bff6773b18,0x0007d978dad378ec,0x0000ac787ee39567}, {0x000ea8b0437164b0,0x000073fe795e4801,0x000e5eb73f430ad2,0x000c0eb164154d8e,0x0000884ecd8108f7}}, {{0x000c0965f5206989,0x000db4f7b8d90e6e,0x0005a68b9640631f,0x000f4e02fd34fca3,0x0000c5a4b66dd40c}, {0x00054bf80b6783d1,0x000e2a320a109494,0x0000a39b280e701f,0x0007db7d1a564a1a,0x0000436d53d42058}}, {{0x0006e6d6556c3629,0x000052455d7ef509,0x0007230f9bc23a3c,0x0002fcaa7aee5480,0x0000ba1cfa6b2ae8}, {0x000057a99c5d7062,0x000b642315c9833a,0x000a72f128be85f4,0x0003cdb083179a66,0x0000fc77d5dedcc7}}, {{0x0008a805616ee306,0x000f87ab108322b8,0x0001270cdfb09548,0x0009ab2ad6ab0d51,0x00001f6c57ac924d}, {0x000bf7290aecb08b,0x00085df784a4a0f7,0x000af1d03849f87c,0x000acd77c79c15cf,0x0000bf9f6767463f}}, {{0x0002c65765ba5436,0x000be2ea60dd9150,0x00043ecb318ce3ca,0x000eeb85cee6ac6e,0x00003e4e910c8f2a}, {0x0004fa3c85932eeb,0x000a9c90c44d2623,0x0008a50f696883e8,0x0000de79b9e738a1,0x0000fc62b2aef042}}, {{0x0007d906d3e1fa9c,0x00083e05b8a3d22a,0x0002b9c011711561,0x0006a16a0c9926bb,0x0000739fcc7a07e7}, {0x0009157165e439a0,0x00026a9063d8540e,0x000e927a306353a6,0x000e7f84d9559461,0x000013b9b26e2e0b}}, {{0x000ec3b973497f10,0x000e093ebc2d4fea,0x000af058315c0f94,0x0003406af5f22733,0x0000c2af206c61f3}, {0x000bdf14457397cb,0x00071abcbae0d25d,0x0008153062e8ed01,0x000d6833010938c2,0x0000aa9933898c6c}}, {{0x00031823b0ec7de9,0x000ac8df05df0851,0x000c3b6831e1b822,0x0004cdcc14842fa5,0x00008fe977eceba3}, {0x00016c20d5e88732,0x000a9d0d427dfd23,0x0003fc961e48d839,0x000a5e295b221862,0x00004ee56e7d46fb}}, {{0x000a55b91e4de589,0x00054fdea2889184,0x000dcc943a7488ca,0x0000fc1723862ea8,0x00002d762b3149dc}, {0x0004a12091ff4a95,0x0009bcada2743c44,0x000d8eae2581113f,0x0001ea69de0a4530,0x0000e0fcd862f6b4}}, {{0x000ea68c094dbb56,0x000e7968d4106233,0x000b3002db77d062,0x000d57de719bbc58,0x00008e7dd3d9dc49}, {0x0005740013a5e585,0x0006ec9e3c1b8d82,0x00099b6ab2131174,0x0008f1bcb0a2a77c,0x0000c48a3b412f88}}, }, {/* digit=8 [{1,2,3,..,}]*([2^56]*G) */ {{0x0003e91991724f36,0x000bd9cbd686c791,0x000d4fc1e5eda799,0x000d547db595c763,0x0000b63b80c0c4fe}, {0x000fc697e5fb5166,0x000a70f1c9646ea0,0x000a92ca5737708b,0x00067a3628745f11,0x00001f37958fa869}}, {{0x0009b2caa6650728,0x00046fd324ef9af3,0x00027bd3178322fa,0x000aafbd153394c3,0x00001d5f271b129d}, {0x0000c42f48027f5b,0x000bd536e717c72e,0x000369d0faa40cdb,0x0004e6445a657a2d,0x000003bbfc59a7f7}}, {{0x000c4180d738ded3,0x0000b0de572946a8,0x000a816756f1a5bb,0x0003d4c10230b98b,0x00002c6f30c412b3}, {0x000129dd8fffb620,0x0007b459bf057559,0x0003b67766a281b4,0x00073a77c1bd3afa,0x0000709b38078299}}, {{0x000b232a3326505c,0x00022e1d41bf8c26,0x000e32afa38d6927,0x000a864459453eff,0x0000e8143ae3cb3e}, {0x000c1fa7e6ab6665,0x000fd2286264932e,0x00036f8ed6cd2d22,0x0005baf59a46fe67,0x00000bf0d00eeca8}}, {{0x0005852877a21ec5,0x0006bf537a940b82,0x000a9a6a2300414a,0x000bffef1cba4021,0x00000824eeec6943}, {0x000fcecf83cba5d5,0x000843b4f3c0a0db,0x000f24dd7f953814,0x0009dd1174416248,0x0000322d64e34fb0}}, {{0x00073843d9325f3b,0x00004371cb845744,0x0001e36c5a9bef2d,0x000f71c7d2188ba6,0x0000bd6a7d87602d}, {0x000a9028f61bc0b8,0x000ceed0b6a1ba3a,0x0006e8298f49085e,0x00001d0bc625d6ae,0x000032b0b1e22e9c}}, {{0x000c447f1f0ced18,0x00031492dd2ba337,0x000a08efa800cc79,0x00041dcb93151dbe,0x000020cf3f95e0a7}, {0x00082dc1c0f7d133,0x000054dde6caff19,0x000f96ee3ef92196,0x0000c6ead7d97245,0x000019c8dbe59dea}}, {{0x00038717b82b99b6,0x000ce70eb624d3ea,0x00095d46675922d4,0x0003462f66ec543b,0x00006e673cd1ee1e}, {0x00067c4b5f2b89a4,0x0005e90e5cd36afe,0x0000a2ada3de9c1e,0x00023b4c278bb631,0x000020fa3844bdb3}}, {{0x000d63b0eb919b03,0x000d774b96200ae1,0x00074290cd74ee51,0x000510095458d0a6,0x000024c930f7620a}, {0x0004d19fbac27d45,0x000a4bedeeac2d1f,0x000679ab84086e8c,0x000ec3bcdd211b9b,0x0000970167dc090f}}, {{0x000f2c9faf1fc639,0x0009a28c8bb43420,0x000f1fe4a616d333,0x000739ed65364c57,0x0000343e877e5e5c}, {0x000176be970e78cb,0x000eb05336275795,0x000cdfc1ba36cceb,0x0003264c7c738009,0x000039a2aff63fec}}, {{0x0001ba16224408a4,0x0001e47cfc5eb7ff,0x0008bc493cc856e9,0x000726c1f102e7c1,0x0000613ab746091c}, {0x000e89cc420bf2b3,0x000660337ec2aa25,0x000025fc700a5317,0x0003dca2be9f437d,0x0000316fb859e6fe}}, {{0x0000af59ac50814f,0x0007aa8e42232752,0x000bec5a0fdf95e7,0x000e5cc7e7df2a56,0x00007022f7ecf159}, {0x000eab1cac1fe8ff,0x000b4745116893ee,0x00067dce68040188,0x0002988ee8aa8ad9,0x0000a0e79e82abc9}}, {{0x0002cfc2064cfd1e,0x000dd06519346733,0x0003bcbea339c31d,0x0005c5919b28d52a,0x0000e74c82c7d6ae}, {0x000d05ebaf28ee6f,0x000bad7190280927,0x000b3028982cecf2,0x000e281b0d353edd,0x0000e4bb978eddb2}}, {{0x000b990640bfd9e7,0x000712f62108bb5b,0x000ffdd56d226e27,0x0001b4dbf0098502,0x0000756758a9ca1b}, {0x00062a35285fe91b,0x0009dc9cd140c32b,0x0005cb008edbc546,0x0008f16e47a013af,0x0000ca7e720b73ce}}, {{0x0002ab817a91cae1,0x0004f8e27f63e10b,0x000a3ddf9b89aab6,0x0009726b3074a7db,0x0000c20ce09430c2}, {0x00017b45fcf7e33a,0x0002f45ceb426b99,0x000633d19e679374,0x00047378fc22155c,0x0000d1adb3d67485}}, {{0x00096796424c49b9,0x0007d7c241c9646f,0x000f68b49f888dfe,0x000f20512d4b9324,0x0000a6b62d93571d}, {0x000b26d179483cb7,0x00022511fae281b4,0x0003aa51f666f963,0x000d166281b3e4d5,0x0000f96a765ef3db}}, {{0x000b5bf074a30ce2,0x0006e05a32e6a7f8,0x000237ed4d7f5210,0x000a2b4f9e090750,0x0000f21da47a096f}, {0x0009cb4eec863a09,0x000d0527620af3e1,0x0007c1cf8d18f77f,0x0002840505c81c40,0x0000998db4eab6ec}}, {{0x00089e5c247d44d3,0x00010f4f3d807e33,0x00078a6c71250714,0x0000bea4ba01104a,0x000012874a0a6772}, {0x00059a6759443709,0x000fab2c0bddded0,0x000c108e3d6123d8,0x0003e9156b717b51,0x0000bb7940e97062}}, {{0x0002d5984ac066c6,0x0002868c69a0794e,0x000d99dccf5954a9,0x000516c8c524584f,0x00000e639fd11012}, {0x00001257de792488,0x0004712fc6d7c2e6,0x0003b5d32e9ef640,0x000b89cc4f28082a,0x000065ad32f4768e}}, {{0x000331b13fb70b6a,0x0000f5599b27ac02,0x000bd082c037b44c,0x000d007a860fc460,0x00002e257466980c}, {0x00087a81da0263ef,0x00043d10f3d6ee33,0x000f24a32931bfb9,0x000b856b687270a1,0x0000140e65eba494}}, {{0x000df91b2f1ac7a0,0x000b760fee274f4d,0x000c228e5f99eaab,0x0003bb57f4008a49,0x000090be4401cf71}, {0x000fbe45004f022a,0x0001b69e1af6ac91,0x0001daaa5d838c2c,0x0002c036c7d20b0f,0x0000a063ac1bbbb0}}, {{0x000a42259558a787,0x00091435da2f0938,0x0004410dc5343c66,0x00080426f67b1803,0x0000cc1e424f4510}, {0x000543f16dfbb7d8,0x0001db5bd59286a1,0x0003dd03c921fa94,0x00051e1dcccb6eb3,0x0000581ddda3843f}}, {{0x0005fcb81d73c9e1,0x0008fa5e97ab5493,0x0003a6bab6d07e97,0x000e113dc7b30acf,0x000047ab1f3270be}, {0x0008e3d9fafdee4f,0x000a638a8b950aaf,0x000f13871fab3dbc,0x000a48505df4b36e,0x00001f4e9cbf88d5}}, {{0x00024d366b33f1dd,0x000f8ce445c09bcd,0x00093ff613b97b81,0x00061612926549ba,0x00009c341cf1dafe}, {0x000a76e16efb6f3b,0x0009b05b953cfb30,0x000fffb9fdf24b8c,0x000b95dbd52afec2,0x0000bac5ff8919d0}}, {{0x0001b87459afccd8,0x00033743265243c0,0x000b5d78e6bd4514,0x000a7d0473453055,0x00001088fdb9554b}, {0x000a52c1e269375c,0x00036dc5ec10ada0,0x000bfbc11f9f037c,0x000d2f0066060794,0x00000a630bc89c40}}, {{0x000797eab64c31ee,0x000a945071445efc,0x000a6790cffdb1da,0x0001bf161242871c,0x00009609d82c69bf}, {0x000859500d24fc90,0x0003e51fb417db89,0x000f7bbde9c75033,0x00085c51830a91fe,0x0000ce67dc8945f5}}, {{0x0000ed44763eb501,0x0001b1ab0d669a73,0x0008748f324a0e22,0x000291543b639364,0x0000982daa17d3c6}, {0x000a9f78bbc55499,0x0000ef36384e6f00,0x000977f507a1783e,0x00002a58346323de,0x00001ab688e42455}}, {{0x000b6b56d0bdd662,0x000e44b71229331a,0x0007c352f0a6ef32,0x0009d2f028150efe,0x00007e04350ee7b3}, {0x0008acdc1070c828,0x000300c9feef2a3c,0x0009f3729fb2034d,0x000548ad72962170,0x0000df290bfe2cb4}}, {{0x0009f33fc2e43263,0x000d2eddf03202f9,0x000652fb53b30076,0x000f7b8b21f8cf0c,0x000014fb49f1d91c}, {0x000eca52f7007501,0x0003612a4575a013,0x00030fbb02b9e3c2,0x000771d5355557af,0x0000ada35168c77e}}, {{0x000ecb27b1356705,0x000f2cfc202e45f6,0x000d1be9fe85d19d,0x000343bf1b50c758,0x0000ebf2c0b3ad2e}, {0x000fe4eabc199c90,0x000256bab0ae1531,0x0001fec54c703259,0x00018816ab2e486c,0x0000f87fda804280}}, {{0x00046fc609e4a74a,0x00031a667f91dc9f,0x000d834362a44a14,0x0009581c3d8b95b4,0x000001e4bd167bd2}, {0x000293273483c908,0x000127c7b5987b18,0x000aac07ea79c6aa,0x0004e63f3983c6ea,0x0000f18181f16e0d}}, {{0x000d37c051af62b9,0x000a7bf944968553,0x000d59aa1e9a998e,0x00081350844f9fb0,0x000083fd55976afb}, {0x000c0ca65d698049,0x000ddea5ff2d9670,0x000d8623b732b22d,0x00078247640ba95f,0x0000f61916436351}}, {{0x00027eeacee50437,0x0002beb10f020bfc,0x00043fb05ae419e7,0x000a29a9c028d189,0x00001f01cf86f13a}, {0x000737e8887a132f,0x0008763184107790,0x000db795e6751330,0x0000b1a819e8a37d,0x0000ecb8ef6cad10}}, {{0x0004a223021926a4,0x00092f9b4c1c59f7,0x0002ad0abb7c28a4,0x00059cad1a733f91,0x00002a910af41a56}, {0x000c6e07bd68cab6,0x000816d70ac83842,0x00053aaeb2b57fa3,0x000b182a6707a83c,0x00002c1c510c5b4d}}, {{0x000c1fbb2d09dc72,0x0002066bd23b8de2,0x000b27db6c3dfed1,0x0003da727d039bd5,0x0000fb2f0f130324}, {0x000a07b80be73992,0x000dff9f27a8f855,0x0009bdef7ed9327c,0x000d8880bd99c772,0x0000b67125e48250}}, {{0x00026e88670ced73,0x000f931bd3b4784b,0x000c85cbce3dfe41,0x000a9d6e353a06bc,0x000002e290990178}, {0x000bf11a6eac16e3,0x00007a2b3aac860a,0x0000afdab7644700,0x0004c116ff9d1985,0x00005bdd6a62db2d}}, {{0x00094b07e5c9ce97,0x0002b0af346ee825,0x00065ad4a0f379e5,0x000825f08b31e3bc,0x000010c6b12967c4}, {0x00066f971954cf1a,0x00026d0aa21551c9,0x000bd23a8b1cec79,0x000e857f15598986,0x0000e2ff99d99452}}, {{0x000953c340ceaa2d,0x00045e2e9333d8dd,0x00086f06d2635527,0x00054545d4e5f985,0x00006bf94a9c7cab}, {0x0009a0ab76a9af0c,0x0002fa095af733c5,0x000389ca052740ab,0x0000cb0444de8a24,0x0000c6f9864306da}}, {{0x00041a76b2515cf3,0x00016585c749b5a7,0x00083de9771c4160,0x0005f548350d4fe6,0x00001d6152493d0b}, {0x000c5e1fbce090b8,0x000d7bcb2a5b7a0c,0x000d84c35aac927e,0x000e266920de4920,0x0000c06a0b6a2b4d}}, {{0x000d58bafe7ddf39,0x000d31e6e55bd34d,0x0000696e755851fe,0x00005f4139561696,0x000040304b2ef227}, {0x000f861b0a2a8600,0x00020e7cc9816f43,0x000b64a96cf12128,0x00083c121862120a,0x00009215b9ab7893}}, {{0x000b30537387c09e,0x000e103ee760311e,0x000f7ea19c5832fc,0x00055050358f5832,0x000001d3c3571d53}, {0x000ee41da48ea80e,0x000def4fa4c11ca5,0x000f1e1c734e71e8,0x0004a4512abd257a,0x00003afcdec0153f}}, {{0x00084d700235e9a6,0x00042c4c836f9d5c,0x000332de50308d3f,0x0006ef60a66b0489,0x000010dd399e9e56}, {0x000a460d1ac16352,0x000b00a2c0dff8ee,0x0004a48c584cbb3f,0x00015020afb488e7,0x00009738198f326b}}, {{0x000747fa6d74081e,0x000475a262142a17,0x00088c5fe60ea4c0,0x00026b73514bb41f,0x0000dd645685e834}, {0x000cbec96460b259,0x000dd8dc115ed5d6,0x0007840eaa12fd0c,0x000e3135bc3ed269,0x000069876a936331}}, {{0x0006217472ff5805,0x0004fad4139360c3,0x0003b8b92f422970,0x0004f5fbd99ef0a0,0x000001c73181144f}, {0x00009b318464945d,0x000ba4c5c6be1590,0x0001a36606d5e594,0x0000215d58701132,0x00001e184b20898d}}, {{0x00047524c6a7e046,0x000ae5550b655ba0,0x000c0a9a547fa1e2,0x0002363419daf048,0x00006362953dc243}, {0x00044b15cb12a88b,0x00097b646188cd07,0x000c2c0c0561b6f9,0x000099a99415a566,0x0000e3f0859bf83f}}, {{0x000c5beb92041b8f,0x000636477d0d9141,0x0002c7a9401ae38c,0x0000dada8b71f3d1,0x0000ab5b320665c7}, {0x0007492487443e97,0x0000290d134976ae,0x000460a378595a31,0x00038f88dbeda87d,0x0000f7ad0828e45a}}, {{0x0004db61059705ab,0x000a36b9c697ed1d,0x000b38bd5a3dd492,0x000bb69b92ee3a6e,0x0000ab2609e17cc0}, {0x000fe896e70ee822,0x000df3e6b7e37fc4,0x000d26fcaeff2c56,0x000b457b18959e34,0x0000517ab66a89d6}}, {{0x000b4e0bdefdd4f1,0x0005e366e401f167,0x0003bbec06995846,0x000c214aa368aba7,0x000021487098b240}, {0x000323318969006d,0x000e11fe53d1378c,0x0000c4361cb4d73c,0x00012a8f50a80e13,0x000067f59524ef52}}, {{0x000e21e9e70c72e5,0x00090566d2fbf145,0x0002397f5b2e52e2,0x0007ddf4eaba4a03,0x0000e56937bce31a}, {0x000f517456c61e10,0x000aa8b0a38868dc,0x000a8b755bc2e954,0x000cdee3552fa760,0x00003442dae73ad0}}, {{0x000e747ceb26210c,0x0007b87baef937ff,0x000a3de31983545e,0x0006dacb8c853586,0x0000621dbccbacd4}, {0x00042e959266fbbf,0x0006439d471c82e4,0x000cdad96a3514c3,0x000def4a11b77162,0x00000cb3b3ddcf9b}}, {{0x000dbce478e2135c,0x000efda353423fcb,0x000677af67547b5c,0x000986e97e81f18a,0x00008c2bf83e8817}, {0x000eaaf455809854,0x0005893b45cbdf07,0x0007b4cacc68d1f0,0x000e85d06aa2fec7,0x0000c1d8afc44a7a}}, {{0x000c3fd9eb45ab26,0x000b74b22e74db41,0x00015958a5b234b5,0x000fa07a253decf2,0x00007e0606f004ed}, {0x000f070ef751b115,0x0005a6f06dceabbb,0x00039f6b4f352f17,0x00048e8fc4b6af68,0x00003ddf9a8e9598}}, {{0x000c379c21520b0e,0x000ffbd5d1b6da49,0x00049c7f790864fe,0x0002d74f055d235f,0x000051e4e6b8796b}, {0x000a67f5c9dc340a,0x00071ca7c620c361,0x000c756d05ad53c3,0x000e133a1d658832,0x0000d60d9122bb67}}, {{0x0007bdf0eeec8c68,0x0000878a1821d6c4,0x0000995244a27fec,0x00005f881f7415c3,0x0000effdf0c02cd8}, {0x000ec1c65842df85,0x00088319a901db70,0x00042b5298821b35,0x00028622ee56eede,0x0000bb39592736e4}}, {{0x0003316fd6f7140f,0x000acd8e81f7d118,0x00002d962f9fadb5,0x000323801d5e0c5a,0x0000dee4dc00b601}, {0x000740735d7620e5,0x0003a48c0012bed1,0x00055449a04e3c2c,0x0006c44ee29da734,0x000062cdef4e1a83}}, {{0x0002a5f477010973,0x0008cf88d0c28f68,0x000bb86dd617125d,0x000286648fda2457,0x000048abb8f589f7}, {0x000eab599d94bbd6,0x000de684d160eb10,0x000c8f41ad51ba28,0x000f4a4be0e51c30,0x00006588b4573254}}, {{0x000bf01fad097a5a,0x0007c10e815d147e,0x00011de5649883ea,0x000a6d444d60ba8a,0x0000970de6f227a7}, {0x00014245e17fc196,0x0006a12140572be4,0x0003e723fd833c65,0x000e9ab375813b36,0x0000820bb8946a52}}, {{0x0006970d875d56ae,0x000b71fbf6bf7e7f,0x000083c12d6a0a9a,0x000b6374ba8790a3,0x0000baeb23e4ae7e}, {0x0005c3ab99a907a9,0x000f726bf40ba868,0x00002cd9ef1e7454,0x000634eb73a027c8,0x0000a8a927cdfef4}}, {{0x000f60c08191224d,0x000b0e4ec091e1b6,0x000e38d84c4126eb,0x00098511dff4dc4a,0x0000e3f57dc1f2ef}, {0x0004337d446a1dda,0x000fe59e77f63496,0x0001d13f57bf2179,0x000e26eff105278e,0x0000304ef0414eea}}, {{0x0005e47d19dfa5a2,0x00035fad982bfc6f,0x0003715f5db007de,0x00029e08205ad161,0x000051e672998895}, {0x00051841ae98e78c,0x000c671cac327270,0x000f410f5f818537,0x00039308a15b7eb7,0x0000474357041f62}}, {{0x000dc5ac242316b4,0x000c9bf4aff592db,0x0009a8ec6abe060a,0x000b942e8c38fe90,0x00003e514e5a116c}, {0x000fa3807d784f90,0x0000f4b5b3572078,0x000adea3d1161a88,0x00010b5283ce7913,0x0000756c3e6cc6a9}}, {{0x000fe01aaa79697b,0x0008a6391db160bc,0x0009b45a004a73b2,0x0008d92d8dad4718,0x0000fac0dd0f8d5b}, {0x0003af57d3d2ec27,0x000cb07bd3af34ab,0x000550ded6fa2fc2,0x0009132ff4009266,0x000019b3e878fd5b}}, {{0x000a4966d17fbc7e,0x000993d2b24ea573,0x0006769370cd1a70,0x000f2054e2c5cab2,0x00007050b079f669}, {0x00048b61ede9046d,0x0000c7662659fbe9,0x0000124c5a053005,0x0006c788cbd4edf1,0x0000e2646e5ad6c0}}, {{0x00081088cad38c0b,0x000fbbd68ae2332f,0x0008e27a3471b7e8,0x000b0ca6ac3fb20d,0x000054660dbc36b4}, {0x0001e11a6fd8de44,0x000a637799ef123a,0x0006ac17c44dbffe,0x000cef0540b977ce,0x000095173a8ef60a}}, }, {/* digit=9 [{1,2,3,..,}]*([2^63]*G) */ {{0x000284d391c2a82a,0x0002758308e89ebb,0x000f1edcabcdd486,0x0006c7606f16ec83,0x000013e2c38095dc}, {0x00056f04a057a87a,0x000006b48f982ab7,0x000651c44a876550,0x000e01a252face68,0x000052b540c81765}}, {{0x0002fc516a0d2bb2,0x000bfa6234994f92,0x000c62c8b0d5cc16,0x00067f7241cf3a57,0x0000f5e69621d1b6}, {0x000c70bf5a01797f,0x000c709561925c15,0x0001fdb523d20b44,0x000f7a14911b3707,0x0000648f9177d6f0}}, {{0x000acafe60b7cf78,0x000004a9d8696dc1,0x000ba8ac425860a5,0x00029dd6fc6f09e7,0x000028c5bd0e148d}, {0x000435edc55ae5f2,0x000ca0117411ac6b,0x00024342ca527f56,0x000c0d74d5045efd,0x0000c4c0a3590b67}}, {{0x000c8b8fac61d9a1,0x0002d3c6fe8a027c,0x000bff5037d25e06,0x0002f7d08805bfe5,0x00003271e6c7ff63}, {0x000a6c0232f76a55,0x000d201ef42655dc,0x0000a51788957c32,0x0001739e728bcba1,0x0000ea60412062c5}}, {{0x000964ed0b8892be,0x0002b301bb74fc4e,0x000c486269ea1768,0x0001018265c5aefc,0x000060cf82f9b3e9}, {0x000f797d4df55311,0x00017deeefe257ad,0x000306eb1235b59a,0x00092d50adcf583f,0x000005c27534d094}}, {{0x000914bb5def9961,0x0003133dd1e74090,0x0003d5e761cb69c8,0x000012b1e9c1d39b,0x0000f3338ee0ccf6}, {0x0005d0d2f5378a8d,0x00065f00cd21b1e9,0x0005fe290acf4c2c,0x0008ad9e984240eb,0x000066c038df4808}}, {{0x000264af94d70cf7,0x000f0314bf7e804d,0x00033ed02bdb802e,0x0005d91fb54de243,0x000040461e098563}, {0x000b2c8365e9383a,0x00029fdef6524113,0x000b956c1ea762c8,0x000fa3aeec6e2e47,0x00003d814bf05620}}, {{0x000462bb4d8bc50a,0x0006091957709ad5,0x000412a68181c0b1,0x00048c4bd4fe1c78,0x0000e0341bd60dff}, {0x00045cf7003e8666,0x000a2a24a41bb6bc,0x0004c24c2f11a6de,0x000b67f407151ad0,0x00002c9d27e3a5b7}}, {{0x000423588cceff67,0x000f1b07ed692e96,0x0004d0d0d8594c54,0x000867a578e73cc8,0x0000b4e10566f532}, {0x000c0d5b5ec995a1,0x000504289a54a348,0x000fbd777bf4b9d5,0x00091d8ba155a658,0x000086ed7a82a844}}, {{0x0002b30614c09004,0x00017d00c24bd499,0x000c4bfa1da98d12,0x0004bc3f534dc87e,0x0000a5ff67477dc3}, {0x00096b81d7ea1d7e,0x0002a0a6d20868c1,0x000cbbd6e38cf289,0x0005b61d56cd09e3,0x0000c72e27f2205a}}, {{0x00068f5a44f77f7a,0x000d143c52bc15ea,0x000f0e6097aa5f9f,0x00032ae6ff676f94,0x00004cde963ce2d4}, {0x000a0c0eee470afa,0x000dea3f5ec88caf,0x000a3123184137d0,0x000ccf4bb40411fa,0x0000239c1400f7f7}}, {{0x0005719a8afd30bb,0x0007da826dce3286,0x000a8fbe08679832,0x000ad32f04e891c4,0x0000b6b6e1c9bf56}, {0x0005b11471f1ff0f,0x0008ce15baf00a69,0x00096c43ed76c338,0x000157118edb95be,0x00002beaaf580794}}, {{0x000b09ec3076a27d,0x000e1416545d152d,0x0006d6f2e5e82908,0x0004e0d2c4127235,0x0000c9c964301fd7}, {0x000b88d519bf6156,0x0005a5a2274e66ce,0x0005e2fa0e29ecd7,0x000e66da0473c4bf,0x0000b6eb671c4284}}, {{0x0007932b88756ddc,0x0002317e3e61e8b9,0x000e1c4a4ed4e865,0x000c0e02dd14993e,0x00000aaee18197f8}, {0x000edb96c168af3a,0x000f139ae87515c4,0x000adb4366563c7b,0x000ac00dfadb6f20,0x0000d55e8ca3a042}}, {{0x0001ed8b76da1f56,0x0006458acb94975a,0x00006028210dfa46,0x00051e2dd7f7e3ac,0x0000813e66ab72a0}, {0x000ae1e350cb901c,0x000590cb7822b4cc,0x000ab3b87b653d65,0x000fcf82484710df,0x0000d7ee5385b670}}, {{0x000b12e523b8bf60,0x000b8f910c1b0a50,0x0001675888009eb5,0x000abdf535af824a,0x0000f835f9cfb2a2}, {0x00029312afceb620,0x000a169d383ff59b,0x000ac02b0c797df2,0x0000caeb3f5fb066,0x000029d4c6fdaa2d}}, {{0x0009bc1afab4bc58,0x000ed6783247d405,0x0002d3605833f5c6,0x000433353466308d,0x00003387892534d8}, {0x000b30fadd9419a0,0x0009afe3fce8d973,0x00009aac6bcca109,0x000f110817831508,0x00001b7f21a540f0}}, {{0x0009219909523c8b,0x000ef3a1c74165c2,0x000c9e55aa62f648,0x000479d8598d4f60,0x0000ce9141bbe4f3}, {0x0007d8435f9b9887,0x0001c20475b69af9,0x00091476c0210da6,0x000833cc076e2291,0x0000520dbd9b4fc7}}, {{0x0002cfec1ab1bbdd,0x000e0c6509386a6b,0x0005d7bc4ef8a65b,0x000dfca285554080,0x0000a389397bd11f}, {0x000bd3674660876b,0x0004045dff35a9d5,0x000f5da9411d67c5,0x000b30baf7d148a4,0x0000b8d4c4070bbe}}, {{0x000ebd1e0a1b12ac,0x000cb70ba95f87a7,0x0002ae9cb1e4ef88,0x000402cc33345cdc,0x0000ecf1276c1cc8}, {0x000012e1b39b80f3,0x000d05c33ba4687c,0x0009661c2fd90d0a,0x00029e73ef5a675c,0x000068fc88f10174}}, {{0x0006761196a2fa2a,0x00071d5b312ed30c,0x000f54a31931b981,0x0005411a01000c72,0x0000203d2c906eaa}, {0x000dee098939db32,0x000c1e606c02f2ab,0x0001ff643e37d6c2,0x000ca3d292157452,0x0000781b3c4f7e2f}}, {{0x00000b07850ec06e,0x00089d3a10cf6643,0x0004ab39dac5a38b,0x000bb8b233188de3,0x000077057e53072c}, {0x000c042b59e78df5,0x0007cd97de52bcf0,0x000e0ca4a4cfc91e,0x0007bbf661a26c3e,0x0000620a4c24b850}}, {{0x000d4aa049f842cb,0x00046540e82b4b44,0x000c6f156ceabc5d,0x000d71806710fd15,0x0000e5ae52c13db1}, {0x000e7e6334957f10,0x000031144a7006f1,0x00096447b57e388f,0x000a12fb69bb2fdf,0x0000f78ebd373e38}}, {{0x00026052b7ce5421,0x00096472bde1b822,0x000d2f4dae6d4ce9,0x000b2e43e16ebe09,0x000080ff42e63b92}, {0x000cc022c34a1c65,0x0008f22c46c2c59b,0x00014a8a23803d6f,0x000b27c8aff74f5c,0x00005aebf8060a08}}, {{0x0007d587135593fc,0x00066be570cd6609,0x0008c860d32e6eff,0x000162984e6a102a,0x0000d18589162eb4}, {0x000e99d6d97e1340,0x0000dd8447ce7cea,0x000c50273d42c6b7,0x000e1e59ddbb4ab8,0x00003c612df3cf34}}, {{0x000ca1504b6c5a08,0x000898f0e3a384b9,0x000986c0035216f3,0x0008fdbec2d2bcbd,0x0000bf546da51922}, {0x00055a44cd623c3e,0x0007702b8e5ad1c6,0x000a0bfe7366ce71,0x000e8d4cfc84b4ee,0x000001d5cefaf443}}, {{0x00045d9036520f83,0x000162d40e988ec0,0x000559a04dfb3c3d,0x0006b0dbac4ccecc,0x00005eccae5540ea}, {0x00032dbf8a5a0ac5,0x00059b699700180b,0x00026bca0547972a,0x00025a53765801ca,0x00007e09d0ef647f}}, {{0x000970e2fdd23cc0,0x000c5682e971b956,0x000e86ebcb80288b,0x000939e6e6d91e9a,0x0000564c83f8c9f1}, {0x00032a239560368e,0x000a249c28e25519,0x000a158c3e893752,0x0002622b03cee5a6,0x000012d656be4964}}, {{0x000554e63e3bc1da,0x0001a5044ff74b47,0x0008daa07c719b6a,0x000dc2af24d30ae4,0x00003f3755768c1e}, {0x000bf760700d3607,0x0004122ae4e29a47,0x000f1fb4cbb1a182,0x0005f4b2e275a389,0x00002b1aa240968c}}, {{0x000eacabe063f644,0x00037ce47a09a75f,0x000d07aca9b392f4,0x000d0f942415091a,0x0000b0c591bcd26c}, {0x000ddfd92f1169ae,0x000b6cbf23922d42,0x00091a2af63aeb1a,0x0001d93de9e87706,0x0000be79af8b9802}}, {{0x0002a4e40e50acf6,0x00074f01d665cfdf,0x00031be1ff0a98ad,0x000da08fb640bf18,0x0000fe8bd2fe0e9a}, {0x00003a16cafbc916,0x00092308e08c94c1,0x00080ff4f170f875,0x0001f1fde2d2ab97,0x000066466bca5b20}}, {{0x0002010f5b343bcf,0x000a02f142fe58af,0x0005f4bdf0f2e400,0x000aa84483bfdea8,0x00000b1d093f3bfe}, {0x0001b95c70816030,0x00093dba10972ea0,0x00038f3a6e943e4c,0x00063647be92adb4,0x00000bb7742e5bf6}}, {{0x0007083824297b45,0x00000584455f136b,0x000c7d69e9d0e558,0x000e765b48cedcf1,0x00003a9e4817a256}, {0x000b0e065eb24132,0x00046fc407a70402,0x0007f5492dadbbb8,0x000294865cd5a48d,0x00001d4429394bae}}, {{0x0007ce63b5f1cc41,0x000abe872e626691,0x00005f24437ae52e,0x00074fab087b7229,0x000020770862e6af}, {0x0004e491058edeaf,0x0002c638ca1d4b64,0x00038591c827510e,0x0000629cf2b70460,0x0000fc8b47bee635}}, {{0x00020e61b4d5e634,0x00025d961b4b3ae2,0x000d16bedbd86474,0x00047b210c107e9b,0x0000270352a51271}, {0x000ffe664cfc50e9,0x00098e36cb427d17,0x000dc5f9a50dee01,0x00062b768a762235,0x0000a08d5376f53f}}, {{0x00014576be5f7de2,0x0008a2263c9e4ed7,0x000cacb36d93006f,0x0008abc073694cca,0x0000ff7a5b45ae11}, {0x00053f1cd871236b,0x000d12aa6d523cce,0x00098d76df156a39,0x000d38ecc5f271b1,0x0000c615b7031383}}, {{0x00038e8de3eee6b3,0x00087b910d91a545,0x000d278bd58c7753,0x000cae01e5bdbc58,0x0000cde4adfe963a}, {0x0001fd25302169cc,0x000fe989ed8bb188,0x00096a0ee8ca60f9,0x00083ce1999458ff,0x00001141f046c6c2}}, {{0x000408d6dfafed30,0x0003396615887677,0x000726fa033a0165,0x0006da3c9c15ec0b,0x000090cfd936c9b5}, {0x0004baea3c40af51,0x000bc21129f1e34f,0x000207ce83469ead,0x000ef9bc51674a1e,0x0000e293b24d83b1}}, {{0x0003d131e6c0bb48,0x000510776d351717,0x000e6f9221900469,0x000a2267980e346d,0x000073554cc74dd9}, {0x000c627cbf18a512,0x000b1032c0810316,0x00046834d4d93651,0x000f80007f277139,0x0000c08d7b450cdb}}, {{0x0004fb486df2a61b,0x00073cf7b4a2137a,0x000d042ffa1ed9c0,0x0005ec02e460e27b,0x00007f5e2fb0f62f}, {0x000ec6bcc2423b79,0x000f2a63eea77aa6,0x00050a6e175ce0a7,0x000c9ed7a45fb1f2,0x00003bc919d753cd}}, {{0x000f56f871942dfe,0x000e9859ad669271,0x000cb1a782372ff6,0x000a827f4c2b9633,0x00003e291023838a}, {0x0001611e4e8110ce,0x0004530198cea7ed,0x00020efe02a2d70d,0x0001beddf132e867,0x000061a896346a47}}, {{0x0003a85825808bd3,0x00070fd6e902796d,0x0006219d151dc3cb,0x000d32343c768a91,0x00006cd7685d2ad7}, {0x0009d05b22922a44,0x000e9ba29660e3db,0x000d2ebc76494c87,0x000f8db0ac91dfbc,0x0000deb57a085107}}, {{0x0001f59c3d12a732,0x000c85c2c51d4227,0x000797bcb5f71687,0x000eb0ab1f50c605,0x00009ed0ed9f6d34}, {0x0005b474683c2eb9,0x000507447c46e5fe,0x0002071674956eeb,0x0005eecb163a4371,0x00003fa2fed9248c}}, {{0x0000af231f63950e,0x000034caa2c96793,0x000ac7e62a77797c,0x000aeb726e80ee27,0x00001e6e62738b28}, {0x00078b0b3c9fef02,0x00004d5f90be6361,0x000ce51cfaf7752e,0x000e1f74ecaf18ee,0x0000864d0edea806}}, {{0x000e38397c69134a,0x00064b2912936de2,0x00060bae05a42c31,0x0009d1277792196a,0x000024de3470b759}, {0x00074aab75d49411,0x00061d501ff049d3,0x0007974cf9890058,0x0001158f16d40eeb,0x0000033860bddd8c}}, {{0x0009ac82094cec3b,0x0007903b770cb6c6,0x00059590d9976fb8,0x0001fc6dea026c48,0x00006acbb473562d}, {0x000c46144569d857,0x000627f0891d7cd6,0x000d5a17dc3190a3,0x000bc856f5319548,0x0000d9199674749a}}, {{0x0004837dd1c8a206,0x0007cf6834196510,0x00094022e7e5410c,0x000ac2358c3ca8be,0x000005c3197c145d}, {0x000750101683d546,0x0004f95b12343fc0,0x00081277f1d7127c,0x000adab0b8f87c94,0x000077db2a9465a1}}, {{0x000ccaaddce33450,0x0007012a4350ec2f,0x000598bdc2a6811b,0x00012896760ff1ac,0x000054d652ad1bf4}, {0x00051d492a210056,0x0000d3110fdf0a11,0x00060100fad7f397,0x0003622c95928c19,0x0000c91c825dbf03}}, {{0x000b2a2ce309f06b,0x00091a27204bc8c8,0x00048e32efdb27b5,0x000f1e2223eaa508,0x000093e4b2f97bfa}, {0x0008ae644aa3dedf,0x0009d015d573c530,0x000979707317a666,0x000957d888ce231a,0x0000141c1e6fd5c4}}, {{0x0007de5619063736,0x000e8b999595b53b,0x0009e5c36858dbad,0x0008422cbb47b2a5,0x000060318b43cf4e}, {0x0001ccd12ba4b7aa,0x000b58c8282abd16,0x000b2130df399daa,0x000d7c7587633aee,0x0000465311b7a38d}}, {{0x000eec864d3779b8,0x00062d64c1715f75,0x0009144283c5d047,0x000c29074103712a,0x0000096a89210e2f}, {0x000ae9d23b3ebc2e,0x000ac580cfd6d3d2,0x000b01f6c90bdd6d,0x0002db72dbb7f3c5,0x000068eded5c102a}}, {{0x0005b7799eb6df0e,0x00009386b7791778,0x00017a48e26c3cc5,0x000f30545ed98864,0x0000990b4e4e7d6e}, {0x0006b7e2586abba3,0x000529c96e9a0f45,0x000eb4206239ca6a,0x00090ab327459ce2,0x0000a4c3313d002b}}, {{0x0004806f6a3f6fbe,0x000ea5c251dd2a11,0x000a784d3ad5cad2,0x0006d4b2c1f613f5,0x0000c7bfad014976}, {0x000cd333e23cb3ba,0x000425a64b2d04b3,0x0005891063979fe8,0x00027e792e27207e,0x000060c43d2415b5}}, {{0x0009082be7cf3a64,0x00027c9672742dae,0x000a0a8a9cc86ba9,0x0008b3b28a2ce8ae,0x000004ca6d9aee98}, {0x0009c5d005921b83,0x000114e79bf9fd7e,0x00075ddc2f56297f,0x000e877163b4600d,0x00000b23616d1f2b}}, {{0x0000d21bfe50e2b2,0x0000c1bfede14b07,0x000ac4ae07ef8cfd,0x0000338dba00112a,0x0000a3e7d01d9ebd}, {0x00077ece38d9d1cc,0x000ddc5d2de39952,0x0003ca8c9b500249,0x0003aec912b820f1,0x0000879811547779}}, {{0x000125dec3f1dec5,0x0000411178da19e6,0x0004a673807b1f04,0x000dcd893ededa90,0x00005187a5a5bebe}, {0x0004722eb329d415,0x000ea170b391f7d0,0x00099f828f449099,0x00076dad317a69ca,0x00000c3db2b84a49}}, {{0x00077843757b3927,0x000d3a3ca05ae9ba,0x000e593d4326caef,0x000d1308e5293bf1,0x0000842a9377d98f}, {0x000bf965f96b10d1,0x0005f6a8cd05e694,0x000f0c7fc373a9df,0x00072e897d1e51e8,0x0000d01979073fd9}}, {{0x000d8585499fb325,0x000927a8aeb70064,0x00008eec57b67bad,0x000e1ccd3eb9772d,0x0000fc047a71baba}, {0x000d159e54a64bb8,0x000b443497e40577,0x000e0608d8862201,0x000aac2d6b4e282c,0x0000b687b7d8b167}}, {{0x000d3678b2ecfa91,0x000d990c3c386ed4,0x000e5c42b24dfe62,0x000a9f91862e103f,0x0000ca73dcae5732}, {0x00038b776bb87ad6,0x000b9242b81f35f0,0x000fd90cd674976a,0x000091ef2bde7eb0,0x0000efc172f07fdf}}, {{0x000b69b92222f1f5,0x000a1cf7ae703806,0x0005217ee5a2459c,0x0005ac1789f69ca8,0x0000f232b5f33dc8}, {0x0003ec548e9e5167,0x0006c197eb31660e,0x000fcca23124b4e4,0x00024ea0a0cb13aa,0x0000bd63ba4f2132}}, {{0x000d7cc290a7f4fc,0x000d4286b461affa,0x000a407af6b409c9,0x00007298ab809fff,0x00003122eee868ac}, {0x0009e504ef24d7e7,0x0003ce2a581117bf,0x000902e015d92979,0x000850e19bc86702,0x00006bba5daa9c8a}}, {{0x000669cda94951ec,0x000ca6b8d418e9f9,0x000d426a44b6af58,0x0000273a32107417,0x000078e66aa5dde6}, {0x000c0834a53b9649,0x00086f6023300516,0x000c5c897fc659d3,0x0005de7ab55e5c58,0x000085099b3138bc}}, {{0x0009efcc52fc2384,0x00082ac1da3f061d,0x00083fe08712b272,0x0002f7bb65814992,0x0000954ac94f8aaa}, {0x000ada47fb2e74f1,0x000ea89926b085c0,0x000d1af5bee8ba98,0x00015ed4f9d37d23,0x00004ccdbf9ca9b0}}, {{0x000481b7bfe71786,0x000e05405868b674,0x0008c867d4e1deba,0x0000e9a61b2821c4,0x00009c15b35b13b3}, {0x0001666368710884,0x000cd220b1ff3b4a,0x0003d9f4de5e29f5,0x0006750b82bb3523,0x0000e07633358cdc}}, }, {/* digit=10 [{1,2,3,..,}]*([2^70]*G) */ {{0x000f5c7a3e6fced0,0x0005f45fbdeb0d53,0x000339a70e8cbbdd,0x000b81f85c01df13,0x0000ff71880142ce}, {0x0008774bd70437a2,0x00019a0bda6a4c4e,0x0008bd26e5fb3289,0x000521fcdbebd2f1,0x0000f9526f123a9d}}, {{0x000305192c4d6840,0x00057612efcd40ce,0x0009cae208b04d72,0x00056cb9dcda366f,0x0000edc4d24f0588}, {0x000e6bf854279005,0x00058c09dfea64f2,0x0009bf26c3de8129,0x0005a9841b448737,0x00000b62c6dbdf13}}, {{0x000e3b4c72dfe67a,0x0005f0e19fdfd4f8,0x00013bd35c416b0f,0x000b9d78b9098d4c,0x0000c11118ab5b8c}, {0x000a318f00628413,0x000f59f356f4f598,0x000177a0cbfe0602,0x0005374ae3637e30,0x0000409774791136}}, {{0x000fb5ed005832ae,0x000ab1042e4f0db2,0x00070f8ca5f5efd3,0x0009cbac4ffdc6ed,0x00004645d0c952da}, {0x000f58bc9001d1f8,0x000bce1172059596,0x00098a08452c8f0b,0x0009de7d4aa0d2e3,0x000015bfe3a904f4}}, {{0x000443f23885e5fd,0x000918433aab97e5,0x000d4e604f72f8f9,0x0003feed00b154e4,0x00000b35e6bb5e17}, {0x000a0489164722d3,0x000b58761ec857b2,0x000a838323e3c665,0x000e3b3bdd13973d,0x0000c8b1a1ea3daf}}, {{0x000ace654317cac3,0x0009221771b34497,0x000dfe8b8be600ab,0x00010f842e409eb0,0x000086a67d769423}, {0x0008d8d4431cc288,0x0002185dc5242554,0x000c4be32a7cff14,0x0006e0cd60f5a193,0x00003ebd5c95071c}}, {{0x00080a7b1fd2b0bc,0x00059bec33e8ba3a,0x000743fb39b3ad39,0x0002f9f3868d6179,0x0000fd169fdbdb46}, {0x00099d79ce0a6af4,0x0001a42d3ff8d3b4,0x000c3e1b255dc1cf,0x000473c4fb9e6cc6,0x00007e6961daf69a}}, {{0x0003acce548b37b2,0x000264d4054954eb,0x000341b4fb38e754,0x0007fa6c3daa517b,0x0000f6928ec890bf}, {0x000b32386ce6c413,0x0004e0adadcd0496,0x000b5faf901be1c5,0x000985904e67e74b,0x0000cbaf679115c9}}, {{0x000214550ca42470,0x000ae7dd30aa8cd1,0x0008fee24ba1aa47,0x0000e82f81ddf1e5,0x00003452936eec9b}, {0x0003b81243aea965,0x000ec5c3d0e58bdc,0x0009483619a2919a,0x000ccf4ea640ec10,0x0000ac86d5bbe0bc}}, {{0x000d918c36cf4406,0x00076939719cf892,0x000218b64aed3e83,0x0000dd507b08d2c0,0x0000f1bcbbb2e979}, {0x000d6ed60919b8eb,0x0000dac1f9eb4a84,0x000d5daefd890079,0x0002c5484941aa0d,0x000022fe40b17fd6}}, {{0x0005ba2157f2db33,0x000f5e28ca9c97e1,0x000b9f454bda2fc8,0x00072e2d050da437,0x0000d57eb575379d}, {0x000eba2fb5ee9973,0x0002b11538cae9b5,0x00032797401648ca,0x000bb702bb76f6f6,0x000038f14b92f3f4}}, {{0x000226ad7ab9a2d8,0x000cfdfae958524d,0x00051d8c29c00090,0x00062c8ba5f53987,0x0000afcbcddbab82}, {0x0002729e99d043b6,0x000b4ebc943a5739,0x000862935ef51263,0x00017b3feace9320,0x000039efc04106c8}}, {{0x00054b366b4be7ad,0x000db4a37a1e1fe0,0x000d75cd93f25a9d,0x0001b5239ef1ad78,0x00007b58f4a2062c}, {0x000f9a9ff563436b,0x000938af51e76f74,0x000e97fecf718ff2,0x000c09a234d31315,0x00006a8e2b1d92f1}}, {{0x0003aa8327720c15,0x00026a092cc8a7f5,0x000746c4d956ca32,0x0003923f03d64a28,0x00001fe1782b6d0d}, {0x00034db3c832c80a,0x000bcda2e3b4d19b,0x000104ccc60dccc5,0x0001fc845dd62e0a,0x00007ab1de2020b2}}, {{0x000ae0b3893d123d,0x0002e15ee71cb293,0x000a9468bf7b7578,0x0007438aa3c61442,0x0000686123dab15d}, {0x0006891a7ab4116f,0x0007b4e6a4598c61,0x000e5fad76fcd72c,0x00046abc21911077,0x0000b6a20e8604fa}}, {{0x000be7d341d81dcf,0x000842148379e839,0x000026eadcddb688,0x000c5dea6211a1f7,0x00003b25760e4d1c}, {0x000c8f6a7a73ae65,0x000e11d5b48340cf,0x000a50ebc83879a5,0x0008fa75acb1ed41,0x00009a60cc88c07d}}, {{0x000bdceb18762621,0x000002af4ee91b73,0x0006e1d072b0d79f,0x00052f7bcf3b0bd4,0x00007d6af9df45d1}, {0x00004616d7364517,0x0006e6b0bf5a7352,0x000999b9d43cbbd9,0x00039840833a5bd5,0x000002614f15b72e}}, {{0x000f01a59c3e9f87,0x00075e6b3d160aad,0x000ddafad40200e7,0x0002e16a22bdd3de,0x00006dedaf4a10d7}, {0x000807c4bc2e88f8,0x0000946dd5a549ef,0x0008d59e96ba8129,0x00034921a4077a7d,0x00007b6a2e8002db}}, {{0x00099971b4e598eb,0x000e56fe4b1dd567,0x000b267c5f499ef1,0x0006cf8978d3aefc,0x0000582b557d3578}, {0x000b2ca1715cb07e,0x0001a480241d32b3,0x000571ecd4c3de6a,0x0009a883b5ffedcb,0x0000af53901cd2fe}}, {{0x0008d4ac3b819900,0x00029e0cc8fedec9,0x000b427b91cb8372,0x00066cfe0b0491d2,0x0000f2386ace983a}, {0x0004d1eb32912137,0x000de9a62ae4930c,0x0003e89e3a2f82b2,0x000c7f07233853f9,0x0000f8063ac81777}}, {{0x000b56759ad2877c,0x0001d865c754ff0e,0x0006e9a846f45464,0x000fc326fe701a23,0x0000586ef16c6e40}, {0x000b6e024bafad93,0x000234da906a3f62,0x0003276a0c8b42bd,0x000852998e1eb4da,0x00000d0e5fc36cbf}}, {{0x0002ae1e8b4dfd4f,0x00069301cbac1b6b,0x0002a39acd754d5c,0x000ab87609762911,0x000086b599a83ba4}, {0x000dea799f9d5812,0x0008a2fafeaa26c9,0x0002505a50473b1a,0x000322f469af553b,0x000027d16d7f6a43}}, {{0x000f73cad3d97f9a,0x00047f1374553316,0x000954e7c52bf3bb,0x000410f53eafeb09,0x0000721dfee7d732}, {0x0009821141d4579b,0x000bfa3bd435b492,0x000fa60153411321,0x000f0dffb355aa17,0x00004e7ef4ac8e42}}, {{0x000c97c593710000,0x00007f759c18604a,0x000db6b65e1c48c7,0x0004953f62ecc5a5,0x0000a78b17338a21}, {0x000819dbcc8ad945,0x0006889c34006be1,0x000b4840a70dc04f,0x0001bff62557b4a6,0x000044c6adeb0bd2}}, {{0x000f24e907a544b9,0x000aa13da2106a00,0x000e4994ba7520dc,0x000d706e939b7511,0x000018b6ba74c275}, {0x000e0fc644be8924,0x0006bdaf6c42d3e5,0x0005c13fe707a981,0x00054a20145567f1,0x0000818ebab2130a}}, {{0x000d3ad58d2f767a,0x000d37e7c77328aa,0x000afcc98dc5267f,0x000d4aa919cc88c3,0x0000a2e6ab0cdb8c}, {0x000ec04d0c63eaaf,0x000429ffa832d46f,0x0003a631fa1cb92c,0x0008b2778dd178e4,0x0000b5ae1ce2dc78}}, {{0x000fb906e77de048,0x0000706dbb9768b4,0x00017c01d7992bcf,0x000e01096e6a13c4,0x0000d96332d3956b}, {0x000c93a413aa2b94,0x0005bc98c8a5902f,0x0005f113799a4d91,0x00028112c2940756,0x0000072690f61e4f}}, {{0x00007cf02ff6072b,0x0008dad98cdc36e6,0x000f56609a47d2ca,0x000da00f471d1ef5,0x0000cf86624a264a}, {0x0000687aa9e5cb6d,0x000147401c6cb70c,0x000a61435c98124f,0x000ea5b189635fd4,0x000028fb8b079d98}}, {{0x0007c2a40c251f81,0x000792da44beb9a6,0x0009b542388cd5d8,0x000dc1337deb96e0,0x000050467db74287}, {0x000debbcdabb8397,0x000281839a3ee161,0x0002d202ba79e974,0x000d964b8dd3c265,0x0000b3e67f859f97}}, {{0x000d78fb1cb6ac9d,0x000dfa1d0d455aa5,0x000a5bf95ffa13e8,0x00005d669295dd2b,0x000068bd1f909aff}, {0x00086f926d783f2c,0x00033c3aafc1af0d,0x0007da97c543a59b,0x000e457fcf81d27b,0x0000990a057925de}}, {{0x00075b8519cce2c4,0x000f6e13d8633e67,0x000c1605cfc9af71,0x0005e8374a4a6f47,0x00006ba42456fd20}, {0x000eea4d3fd524d4,0x00012de1acc2a06f,0x0004e2b421e72464,0x000024b53816f133,0x00009e5918ed22f0}}, {{0x00030b665c7322db,0x000103c1b3fb4395,0x00072f685cf12cc0,0x00091d170b018601,0x0000915ee22cb583}, {0x000f03ba317db248,0x000897b8ffc49afd,0x000d3d05087dec65,0x0000e6ff46597be4,0x00000a1c1ed80650}}, {{0x0002a9678bf030ed,0x0009805601488490,0x000362426fb5e9c9,0x000c3f9dae0a9263,0x0000caeecf579e30}, {0x00087bb518d0c6b1,0x0002bb985b9dc0d8,0x0007bc3819918115,0x0002019d186898ef,0x00008168ffbaee46}}, {{0x000cdaa2502753c1,0x000641407c419a04,0x0003564e5bb279e2,0x000016dacb03aaf2,0x0000833658281e61}, {0x000b8c4eb8098772,0x000dca0e672e8684,0x000ee5867b336e18,0x000fd1cfb601f034,0x0000733edbe3341c}}, {{0x000809a26025c3c4,0x00065350df88b15e,0x00002fd8ee6e981a,0x000e9b5237623785,0x0000791f2164c12b}, {0x000678925f02425c,0x0003ba974443b725,0x00041cc52ec86319,0x0007f1bc0ce882fb,0x0000266ff7fb25c0}}, {{0x000a8c3017025f39,0x000c6b9579b43d4d,0x0003716ecefcf628,0x00016dcc4d00161f,0x0000c27ebc4f8011}, {0x0000ea11da1767e7,0x0001d7004c575eba,0x0002373b7fe15145,0x0007abcace6df68c,0x00005c3dffecdbc3}}, {{0x0002a73ddc925fcd,0x00005f65ee0b3dc3,0x0001cbfebb679c84,0x000a28a15a329545,0x00009889769c76e9}, {0x000ce7fb28ad2470,0x000400894d79ec20,0x0005e3ea7e99146c,0x00003171457d7c9f,0x000097b266238030}}, {{0x0006ae6cf9f82a81,0x0009338f473adb7f,0x0003856c3319decb,0x00061b963ab38628,0x00003e3172fc06a3}, {0x000f8dc7d5a006c0,0x000675fba7522959,0x000c22c9e2dbc27c,0x0008b2c1227ab287,0x00006f61f7571a26}}, {{0x000b97104779ce2a,0x00016aadcb1d1b6b,0x000aab2d5aca8381,0x000f12897ae0bcae,0x00005c14ee7fbfb9}, {0x000c583f17a62c70,0x000c173759f6aa00,0x000c9a88f39eb962,0x000c5e1eeba1d486,0x0000ab6c37adf016}}, {{0x00047dba28a0749b,0x00063e519165a2a1,0x000810715246c20d,0x0000b8a068d1b1d3,0x00001e7018d24816}, {0x000b1faf380ff628,0x000d73cb2c1e03f5,0x00091a7daef7fb1d,0x0005616ab539a8fc,0x00003ddb70873f9b}}, {{0x000e211fe7df7a4b,0x0001563f6f40c550,0x00076879ca7cd07f,0x0001da00de363529,0x00005f83f8695574}, {0x000d25ef3d8ac3d1,0x000f52819f024ea9,0x000f4a5646fe2066,0x000de33ab2b9c2ce,0x0000e155d966ffa2}}, {{0x000a19bc3a72d004,0x000b4513c31b0eb0,0x000c646374037665,0x000638efb2b6bf04,0x00005c34d6e48cdc}, {0x000e10ff01fd7967,0x00018e3667b856f1,0x00021d0c04dfb810,0x0006ab70eda25390,0x0000a94e9fffa06c}}, {{0x000b0d9bb9aa8822,0x0005cc05fd102d3b,0x0001ca64eea20e4e,0x000cbdcd7eeb5f1a,0x0000fa6b43ce6327}, {0x000e3cf3aa91121f,0x00094a34079bb577,0x000e02fc08c6bd5e,0x000bf7e7e5ba3960,0x000016dd2c480141}}, {{0x00076d980101b980,0x000db82f0f66b572,0x000c3eff3760883f,0x000b4089d7de754b,0x00003b606435dc2a}, {0x00053dfe05beeac9,0x00022c3325cdcd6e,0x0004f03c3f2f1e86,0x000c1b4d0f792177,0x00007ca7221d552c}}, {{0x0006afe1cd19f723,0x000cc183fbeb5a0d,0x0002c403ca20915d,0x0004426fda4b4083,0x00002738eddee425}, {0x0001df6b5eccf1aa,0x000188bbe1f0469a,0x0000dfc934b5aff4,0x00062791359d7f57,0x000018be23690088}}, {{0x0000fbab00ed3a95,0x000423cdf8bea5b3,0x000c5679734c6137,0x000ae1dc5c5f46ab,0x0000cecf93e082a8}, {0x000be41a968fbf0c,0x00025a5c7f3d7d3d,0x00087a9c7d23d458,0x0001ca328f69a0c0,0x00002d7547207447}}, {{0x0009f4a4eb732ec8,0x000d31ca6bed36ec,0x0004578926c943bb,0x000c06564535e1f2,0x0000b84a8eb77e2a}, {0x0006cd32499dd5f3,0x000dded04e57e093,0x000305d9d12053d7,0x0000a21bdd0076e4,0x00004a527b94f67f}}, {{0x0004af09cec46eaa,0x0000c58b9bc7e79a,0x000af2f75b15347a,0x000434cbd2796f35,0x0000c957990e051c}, {0x000dda3c33a655d3,0x000e58514aa32669,0x00053dd415d503c2,0x000f78afa1133737,0x0000f0546733b754}}, {{0x0005677496125bd4,0x0007f775006cbf18,0x000037899fb0023c,0x000a57ba0f072f3a,0x0000222b6eb4e4ae}, {0x0005e767866d25a6,0x0007e837aa6f3dde,0x000f1cdb8b6eb04f,0x00083bf315591a2c,0x0000dfb4f418d4e6}}, {{0x0003ea448ee1f3a5,0x0006b5a2afd57e92,0x000ea49489604d9f,0x000d2f6e1d4a3340,0x0000b45f1f5044cb}, {0x00083764acc757ed,0x000793d68ff75faf,0x0000e404ba7cf9ab,0x000fdebad62f69df,0x000065f33c2e2bda}}, {{0x000de15a377b14ed,0x000abe39f60cc365,0x000e681486bf5463,0x0003a792030d2d2c,0x000095867f0b6f84}, {0x0000244ef5ab0172,0x00012ab55d12d39a,0x0006391690bd2d8c,0x000c8aa9503db341,0x0000d4e25b117660}}, {{0x000b3b5e224c5d71,0x000c58616919760c,0x000142552fa3baf8,0x000bf58fbca1138d,0x0000ab18bf18669e}, {0x000f53e9bdf25ddf,0x0002db6cd15455e6,0x000e8908004cc0bf,0x000ac0695bef4995,0x0000e9459a9004a9}}, {{0x00089cacce9bb324,0x0001b7de8285ad2d,0x00051bd4bddea65e,0x0009a722ed8c35b3,0x0000150ff364c0e1}, {0x000c801345f4e475,0x0000d03a266c86e3,0x0005b1f133bf21f7,0x0005172ae110d485,0x0000d6aaf6a57262}}, {{0x00012e1813d28f11,0x000d6ad7a5231e0f,0x00044a17b6000e11,0x000a00b7d8deefc7,0x0000e990b4824c05}, {0x000daee93e976d58,0x0000c6610d6368fd,0x0003dda88696241d,0x0009463204e7c389,0x0000bccfa65ea3a6}}, {{0x00025b4c5cd14112,0x0002df3658b1b594,0x00084cf93701b404,0x000d60c3e56bca47,0x00007de5f15afe68}, {0x000cfcef8d53f19f,0x0000b40a730d4ab9,0x000ee0a8addb1031,0x00019c7fa73cd14e,0x0000d54874942497}}, {{0x0006316a8123ef0f,0x0003f7f9543849d6,0x0009e785473c32db,0x0005063e2ed2090d,0x000098a932a8d9f0}, {0x0003cf60c6aa20a6,0x000415279bb2c5d3,0x0004a73079a32ba1,0x000dbd1e3202cb77,0x00004ed4bc548c42}}, {{0x0001a06d4caed0d9,0x0006871d22b3c20f,0x0003268d7b802140,0x0001264426ca04d1,0x00002377007b5f4d}, {0x000cbc371f21a855,0x000aa82369ba4204,0x000c858f918461b7,0x00056970c07d313f,0x0000deb5a5132bab}}, {{0x0009d46d5eea89e7,0x000398437f4bd595,0x000fe254ffdff842,0x000321821071e43c,0x0000241769705468}, {0x00088b9102cae3e6,0x000d91965dff5d82,0x00078d8472d143e3,0x000730a0c9a376a0,0x0000fc0da3186028}}, {{0x000eadfe45083a2c,0x00079e5b4bcda2ba,0x0004b8e7f66bc721,0x00086a6c826442d0,0x000019f54522c4b5}, {0x0002c495b7eeed57,0x000d0aa9dfa16018,0x0003884add9954ec,0x0000413403a8ecc7,0x0000fb17de30bb39}}, {{0x00064c5abb020e8c,0x000359c4eec7694b,0x0004793e53d18c18,0x0002e5dc4673ef1c,0x00007b8aeb5c5609}, {0x000ca43f0f8c16bb,0x000c2679b2f63aa1,0x000a205c9224ed5e,0x00028a5d56eeaf55,0x0000fe115bafb8e0}}, {{0x00008493927f4fec,0x0003b59aa7c597e6,0x000e90a51f91fbf9,0x000822d85af7696b,0x00001277b7938ccb}, {0x000656ee7a759524,0x0000528da5f5395b,0x000a4454f00df7de,0x0003c0c9c231754c,0x0000ec971f4baa2d}}, {{0x000c507e75d9ccc5,0x0009edc9030645c3,0x000b44bdc63b7be8,0x0006a1e7e09c665d,0x00000d60da1b841c}, {0x00065ee08df1b120,0x00097ff089df6f9b,0x000e8013d3873487,0x000cc89c331a663f,0x000017f5de95f42f}}, {{0x0007866e8e575672,0x000ed9fcdb184307,0x00012e174c9f781c,0x00052a18131dda9b,0x00005d84aa3aa037}, {0x0009e094d0c0ce2b,0x000ae2bebba545e0,0x0007284c71564008,0x000baa47e8ad31a8,0x00007c4b46d47e7b}}, {{0x000a7b397acf4ec2,0x00003ea8b6403e22,0x0009692850426c40,0x0006703e3295a64e,0x00002aabc59c6a45}, {0x000714c5f5942bc4,0x000dba3182edb929,0x0004152ba9a6168b,0x000367e216a66510,0x00006908d03f6926}}, }, {/* digit=11 [{1,2,3,..,}]*([2^77]*G) */ {{0x000d8745a1251fb6,0x0008672725c7a9f5,0x000ffe89e967747a,0x00035db95c33e531,0x000009d211049649}, {0x0006ca82fe122271,0x0005f426469dcafd,0x00093183caf9b5b9,0x000fef1e9ee04c56,0x0000084a333d8146}}, {{0x0009933aed1d1f71,0x0003405630909664,0x0002e39cf566eaff,0x000124245057f0ad,0x000048ff65b2f832}, {0x00089d4cf94cf0dc,0x0003920c58b3042e,0x00061aa0d319bec8,0x0007ac6a26762653,0x000086fa3034fbc8}}, {{0x000d2ab5c8b06d5c,0x00023e4eac46fc83,0x0006f7779b1a785a,0x000504f99315bc84,0x0000f31d817af9ea}, {0x000fe6a15d7dc85d,0x0003e4016b332391,0x0001cb4c72f132b0,0x0005a059547fe318,0x0000b66d8a735015}}, {{0x000d7e1adc1696fc,0x00024acd72d06b66,0x0001b743598ebe59,0x0005eba5f24550cc,0x0000e23139474b9a}, {0x00022d4db067df91,0x0005baff9b00234a,0x00000c9c198dda09,0x0006950bbc75a061,0x0000560a9c8a39cf}}, {{0x0006d3e99e0925f5,0x00061322375acf00,0x0006af5ba2dd74a9,0x0004f1758b446ab5,0x0000029268430b9b}, {0x0004cb41aeaffa32,0x000f7b9587c1e2c3,0x000d1350c8b17203,0x0006044d559207ea,0x0000b66a2161b7f9}}, {{0x000325efe51bf748,0x000dde4600940850,0x000da2f259c4f579,0x000f32dc87b92a76,0x000089de4e0efebe}, {0x000ec06646083ce7,0x00054fe127736900,0x000344110be2a033,0x000d203dd1da35c5,0x000057568b82802c}}, {{0x000977900f7e6c85,0x000ebfacd2f07555,0x000fde37538e8b94,0x000dfcaea1f3af03,0x0000e11a1d8c5881}, {0x000b02ec1e2f2ef2,0x000ba605a6c5b3a6,0x0009a0b2d193d2bb,0x000846125ffeee33,0x00007b6a724be0c8}}, {{0x0000f1cf1c367cab,0x000b190fbc7de405,0x000a110329bc85a9,0x0003a8f373c4a2e1,0x000064232b85d039}, {0x0007eb0167dad297,0x000124b78ab2f557,0x00029348b1604f30,0x0003419baa94afe8,0x00007fbd8ddb1654}}, {{0x0000ea5b964e39a7,0x000c60d3c76edab5,0x000d11964d4c29e3,0x000c2f10dae67c56,0x0000307a8c055ffc}, {0x000c1aa91708c3b5,0x000bd8bf0eeb65bb,0x000a34db7a151e62,0x0003a81cb533816f,0x0000139e05cf2940}}, {{0x00051b494a7cd2e1,0x0000f699336c6ff6,0x0009a896a5671ffd,0x000cef5f5fd2cc97,0x00001e893a8e8148}, {0x00006a165cf7b104,0x0008850d84859889,0x00035b3de81b6717,0x0007993c0deb358a,0x000023ac85601d29}}, {{0x0000d87dac50b74b,0x000ea869734caf58,0x0004e28fb28b2b89,0x000739e9a3b93687,0x0000b2c9190d5f3f}, {0x000691884a9d5b7c,0x0004be770374199f,0x00038efe27ebe232,0x0002d23442e10707,0x0000f9f3f578f908}}, {{0x00069e1096187086,0x00046183f9b1719f,0x0006a21afcc9e836,0x00041f8c203a9536,0x0000aec5d6d668b1}, {0x000f78a994f04e95,0x0007d71245b0ee2d,0x000e43f4fb39ccae,0x000a986875a4a997,0x000007dfe122b2ce}}, {{0x00081cb489b03e9c,0x000aaec414fa4fbf,0x0001b3ae5db86ec5,0x0003fe3ad444f9f5,0x0000a7d33d6d914e}, {0x0002f5c0ae6c4d0e,0x000d93969568a9c3,0x000a7467ea9ca1d1,0x000ac5b8043c311a,0x0000832e75dc21b5}}, {{0x0007aea5232123db,0x000bb5ae86db314b,0x0004668ed08307c8,0x000c3856e7165caa,0x0000170458c64d3e}, {0x0003ec6c19bb9866,0x00064e0304ed4d2e,0x0009f9722c5f3484,0x000c0a317695a06c,0x0000c7f7317acab1}}, {{0x000940e9d6d2e8b4,0x0001149f7c976295,0x000713885d318b8c,0x0000fde245320497,0x000068d834be8a44}, {0x000e5b2bfba796e0,0x000b6d71f116d81f,0x000b66e53152364d,0x000192bb8c7c59b5,0x0000b12c61b2641a}}, {{0x0004802fcf0a7fd8,0x0008d488b01e31f1,0x00052b49842fd078,0x000200f1d78d6d99,0x0000eb572d987ac5}, {0x000a44c4d194a88b,0x00090a017e66e0a2,0x00088aefcd2b63fd,0x000a10c8efc6c8f8,0x000076f6bdafa881}}, {{0x000314bb46c2397b,0x0005aded2819187f,0x000764d34004cf56,0x000708f9ea570438,0x0000ba4521828084}, {0x00045711171121e1,0x0001d7c9b6710647,0x0000f7507ad7b7eb,0x000bd1cacfbc4073,0x000078cd8c6d7ad7}}, {{0x000e101b2a672385,0x00075f9c14f2bf0b,0x0006620753556d36,0x000609c04b7831a5,0x00008ca59bbc9d9e}, {0x0005392a569a73b1,0x00084698f6c94bc4,0x000add755517a52e,0x000b8475643da5ae,0x0000aed0cd53a581}}, {{0x000ff8480af13722,0x0003d1ba5d1fb9b4,0x000f98d31244c311,0x000c2a0a5dacbef5,0x0000c3323e86375b}, {0x000ab4a5594b1dd8,0x000b4eb4797e17a3,0x000886a19a1928bf,0x00074a683af245e4,0x0000979d546f2b5a}}, {{0x00026bc19f9e9676,0x000288fbbf4ea0f7,0x000707d40d9d0315,0x0006e06fd6f51db7,0x000033084d9c3f6e}, {0x0009cdc55667eaf7,0x000abe44d56fedcd,0x000962b1473b7f92,0x000cbf8b2e39b64e,0x0000d408f6f6671f}}, {{0x0004ddc164a89bb6,0x0001def3bd05cc63,0x0008decbb74a42bb,0x000595b280dbb242,0x0000103f6bba02c8}, {0x000f581355a5752f,0x000710946674fa2b,0x000a0223b562f96a,0x000a245e4ca16d6d,0x0000e4781a018d3a}}, {{0x0003075f8dfcf8a2,0x000a756698259eea,0x0007d3fd8a284f0a,0x00091e93fca25086,0x00000757b5f469d6}, {0x000402093b8a5ded,0x00091bc06da6f2c2,0x000739c33d3f9335,0x0006e44178293eb2,0x00002a3e7718cd68}}, {{0x00049f4cd941534e,0x000b03c71c0ea76f,0x00097f7e30d37406,0x0000dd372d93973b,0x0000c17e23a9d7fd}, {0x00005516f496ba27,0x0001c6ad50e7e329,0x000e7eff56a69317,0x0004cf54e539a283,0x000052737e788e1b}}, {{0x000932c68af43eec,0x000db03d00bda2f7,0x000b061f55502468,0x0005ad25dc978f2f,0x00009a1904ae8c81}, {0x000538d470c56a4f,0x000e293d8cedd3af,0x000108ef3159abc5,0x0001773a37245f20,0x0000a17081f123f7}}, {{0x000fb2b10c8c0f59,0x0009b065054727b0,0x000c3bfa72102c3e,0x000d95c94564df8a,0x00008102033e09da}, {0x000643ff1d18a13b,0x000127fc5af06989,0x000eaafd835eebd9,0x000e97578d096afa,0x00007a893428ef3d}}, {{0x0006e8decf2a73a0,0x00078e5519942a20,0x0008d53a2066a639,0x0004aa3a6a088ab9,0x0000ce7c67c2d112}, {0x000c671759a113ce,0x00026f6f67fa48ce,0x00036727be3b373d,0x000d807455d479fd,0x00005a428ef813c0}}, {{0x000dbc81c86682bd,0x0006e8d02b2ab853,0x000bc329ab78d272,0x000147daf69bed8e,0x0000b6b40b3f93b2}, {0x000a77db8c4961f6,0x000bc0e5e0abe42e,0x000e8b05eb1a12f7,0x000a8040ec527479,0x000080273925ab60}}, {{0x000ea5f16b1bd5e5,0x000ffde30ad36bfe,0x000353b9ef957e41,0x000feb7baf664e6a,0x0000c87331276d14}, {0x000f98cb65f57cb1,0x00014e0cdd414e87,0x000881440db60a62,0x0002aa57c16865a6,0x0000093ef1a56ab5}}, {{0x000afb53f4ece64e,0x000d9604551ac095,0x00026b8cd6a6bb02,0x00068975d44b4e0b,0x00005f9a99ad9712}, {0x000c42511a7de841,0x0005eda469ddc08e,0x0006c90a28356809,0x000831637bfba16c,0x0000cb9c4a0ce229}}, {{0x000cbbabb2eec644,0x00049a03adbe93bc,0x000e86ac4a0c23b6,0x0001e61f7aa00ae0,0x000070b941f3c140}, {0x000d6799df435742,0x0008ef65d8105ad8,0x0007fbd814ccfb8a,0x000209fbce80e3aa,0x000073291adb508d}}, {{0x000b46b42a92806b,0x000bf86ab44af5c4,0x0000bc9f8810684e,0x0000539591640bca,0x00005efcdfd0c4b6}, {0x00089076e9edd128,0x000054d792f916fc,0x00003116de29d0b5,0x0005a4245fd01c9b,0x0000503523648176}}, {{0x000a9b2b4b4b67c8,0x0000680206041fe2,0x0008058d8c1d10df,0x000fbb1d64abfcbc,0x0000943b9b2f12a0}, {0x000d9143b3def048,0x0001cce775ff90ee,0x000bc904085ab3aa,0x000dfae05fd4ca7b,0x0000b34a56562c75}}, {{0x000c94a10358560e,0x0001be5c28aa41ff,0x000c7eb152d8a507,0x000f5d0915a0fc4c,0x00009efab066f6d0}, {0x00047a9d19e9b915,0x0004b276154cdbab,0x000fede0d8cfed74,0x0004eec54357ae2c,0x000020630df69f5a}}, {{0x0009f7ce382360f1,0x000978bf58572575,0x00058d46cb6db05c,0x000b7a1917d61d6c,0x00004f8e4920d20c}, {0x000727a11c203407,0x000f3f7ccbb6b68a,0x000e09a200386f86,0x000a34ec8bc6ccfe,0x0000d76ff4b2b7ee}}, {{0x000ebe7db15be7ac,0x0004189f0302a7bd,0x00019336467a0805,0x000ebd96bf0ea9c1,0x0000824446822837}, {0x0008e8b20d841b88,0x00085bb8a54f32bd,0x000b20236127a054,0x0001fa03dd4ca663,0x00007714718a0349}}, {{0x000caaaaa8a5288b,0x0009ff23a1c94dab,0x000220e0c91cc0c8,0x00044984c72c6a3f,0x0000cc20bdfc2321}, {0x00042daa20ede1b5,0x000c24a005156e2f,0x0004b8c4bc441f00,0x0009a46f46a5b673,0x00007409503cb56c}}, {{0x0005261e4585d453,0x000d3734e6429f73,0x00070ee6c9231fae,0x0001bee158a176be,0x00005f1068dac350}, {0x000f900a2d261155,0x00029f0afee36bee,0x0002420a1649406f,0x0004abef43a60abc,0x000009002a825aee}}, {{0x00036a53ff3571bf,0x0007937927c1b468,0x00033c71624f98b7,0x0001957254256a45,0x000027abb0cc07ee}, {0x00064fc5c6d5bfd7,0x000180cd7a77d7cf,0x00098f5346915c75,0x000b5f69f5901287,0x000072b0da9681d8}}, {{0x000260c2e03fa69a,0x00099be1a3741244,0x00006b96036cf0e3,0x0000f5ce7c1633ef,0x000071a4c56071f9}, {0x000125133c673db2,0x000053e8c1317a94,0x000f6c734c0bea51,0x00000141a8a699d4,0x00005e78c88541ed}}, {{0x000acf88e2f7d902,0x000757be32cd5c18,0x000eb5ee9fdbf33d,0x000114ea085cd7d2,0x0000d702cfbd3201}, {0x000ebdb85c88ce89,0x000b8e01d617b6e0,0x0007333ac23a3ce3,0x000b6aa041618e56,0x0000dd0fd8fa57ed}}, {{0x0004702b57872b88,0x000ee57d5fe127f7,0x000cf3d402ef26b4,0x00067a15426f0a57,0x000047e2ad1e5a60}, {0x000d9a009996a74c,0x000c6a26115cd474,0x0006f4d4316a56ac,0x0005b642a615c3d1,0x0000c3fc9666adb8}}, {{0x000da73ce07d1b0c,0x000198ad4178386b,0x0002617f4d82910c,0x00076f524f82cfcd,0x0000c2f5e8eaf691}, {0x0002550b8c30ccc0,0x000a1a8e575a8270,0x000ab94597b856ae,0x00038ebb822fefb1,0x000085928bcec24e}}, {{0x00002ecba8f4b4d6,0x0009a0b4d58b5d04,0x000227e7ac07cd4b,0x00086efd8dffd529,0x00001d44d0c91bf3}, {0x000dc2b135e6f4d6,0x000b879410efe486,0x0000088b5680962e,0x000686461bd343f1,0x0000aa7607742e28}}, {{0x0003d118fb98871c,0x0002fbc76aff8046,0x000e03614cb26f5c,0x000dee14ab8eddfb,0x00008eb579c80cf2}, {0x0004c15c93bae41a,0x000c9aeca3b2cc00,0x0001e9ab146fbae5,0x0005c0c71235cf0f,0x0000dfba9353ec28}}, {{0x000d013f216c980b,0x0008479e0bc188de,0x00097a237c8ac4fb,0x0008e6f29b89c6fb,0x0000697b7814922d}, {0x000c639ddb945b56,0x00078094c3a93142,0x000266c90447b06c,0x0000466dcb364272,0x000033aad0909385}}, {{0x000936bb57c64779,0x0004594dbcc6a36c,0x00091a67b871f8b6,0x0006f498d0fb62a5,0x0000d40e08251d92}, {0x000eaf6f2d84b5af,0x0008b565b6443111,0x00083188b228993f,0x0001961ccbf5922c,0x000087b30ac2df3e}}, {{0x0008b317642bca8e,0x000e72800f17b865,0x000bf94451a032d7,0x000252251dcae579,0x0000ba6b8ef34a2e}, {0x0009cadd44856928,0x000e0986e9be5c8b,0x0000db44884bda40,0x000188516d16a42f,0x0000ec80051214d4}}, {{0x000610798fa7aaac,0x00043073aa4eb2b2,0x000d6b19b41209ee,0x000caf31570359f2,0x0000be6868dbc577}, {0x0004bdc32c04dd3e,0x000defeee397186c,0x00086c0cfa6c35fa,0x000fe1d4a1b312f0,0x00000a5ccc7b9461}}, {{0x00078aa1536189f8,0x000f3a6df571c322,0x00094560e1126c55,0x0006e08f71a602b1,0x0000b2d7405b24bd}, {0x000939e3738be712,0x0009fa4d97a98481,0x0005ba915b5090b1,0x0008a9f16c65a3f0,0x00001863ad3cae44}}, {{0x0002679a7aae5d37,0x000c9de5c1c4d24e,0x00005b6297076013,0x000fbabd50f8babb,0x00003c1abe2de66e}, {0x000b422f2488af76,0x0002063ba575efd4,0x000a69457e4105d0,0x00073b1eb60a8b53,0x0000221000929459}}, {{0x000547877a50ec69,0x00067a37a72cfb25,0x000e18e7abf0392f,0x0000af10a7a19c4b,0x00000d8ea16b5b1e}, {0x000a293ef953f575,0x00056dc5465a7582,0x00051071790a64d0,0x00041f7a79c497e2,0x000060dbb7c68cb6}}, {{0x00032864b66abfb6,0x0004f90309001d8e,0x00084941ad26f52e,0x000957bee3f64355,0x0000d3b3730b69f5}, {0x000a62f4789dba54,0x000532b5c9b79ff2,0x0008f9a0e91fcb81,0x000cb5b446cb7d6c,0x00008f625c179b7e}}, {{0x000e8011c6219b80,0x000928ac2f23baba,0x000e20588e7a562d,0x000051e1b4873226,0x00006ee1cad775af}, {0x000ae43faff79f72,0x0002452ee9e0da29,0x0005f4bd0c141a41,0x0004f7fe127f6f19,0x00009c6ab4f272f3}}, {{0x000147730448112c,0x000124a386567b7c,0x00031501082b51af,0x000cd36bf2028a2f,0x00009a4a0202ea88}, {0x00095d8257e5818e,0x000fd4519b16f63e,0x000a910bfdd8efa0,0x0004a90d8973e00d,0x0000d49d0783c0fe}}, {{0x000ac5eb7caee1e4,0x000d67f4da57ac3a,0x0006669b91033898,0x000aa002145c0e5c,0x00002daa68901aa2}, {0x000c15c1a1d885a8,0x000074b76817629c,0x0008f8f2825572ec,0x0004900312e4359c,0x0000107f8ce01965}}, {{0x000f3a36fa6110cc,0x00013b93561f516f,0x00057522b74fb1eb,0x000dc5ac0c904784,0x0000fd321052bb8b}, {0x00084a2cc80ad571,0x000576a9b6372d68,0x000f4e8cd7c27fc3,0x0002f02461baedad,0x0000d56251a71724}}, {{0x000d209c955bef4d,0x000136adb0470b80,0x000c74feedf02cad,0x000a4420d7cb915e,0x00002503375e111b}, {0x000755edf53cb366,0x0001d368551b9671,0x000a025a454dcb61,0x00044506d69aacc8,0x0000be946c7477ef}}, {{0x00046d1a995e0941,0x0006d51e04d87199,0x0001e311365e848f,0x000503d62f33006a,0x0000541c7c1601de}, {0x000c9faf4acfade6,0x0006e4cd0b714daa,0x00051cd770e58589,0x00016cf44fd8690a,0x00000fc20ed60310}}, {{0x00004eca42768678,0x000bb4f3499358b4,0x00036e5bd46f6c3c,0x000b46c77ca007c6,0x0000018f5e5fc458}, {0x0002270e47b668f5,0x000d9e14f203a120,0x000ff9b4dcef48cc,0x000ddcd3f98bae62,0x00005acc0361589e}}, {{0x00012af64db44442,0x00049ecdd4803fe7,0x00030978a19e9d63,0x000733c08bc047a9,0x0000dbf24ecc1280}, {0x000e38c2cd706b27,0x000ac59017b93c0a,0x000e0f5ae5b012a5,0x000fa2c943c38c72,0x000086167eac7176}}, {{0x000897d594881dc3,0x00089fb820c1e5f9,0x0005018de6b5efad,0x0006ce82179093d5,0x00009ad7d323bac5}, {0x00022e02cfc0e816,0x000196d89daab551,0x00064fa09117c466,0x000ddcd62d01e1cb,0x0000a309b4e9e9c4}}, {{0x0009fb7abea49b1e,0x000c30e2c6c5fa97,0x000afde7ab4b1d27,0x000357dd61c2c423,0x0000b6614f97786d}, {0x000816b7f6f7459c,0x000e49360e7b4a5d,0x00009914ce431a44,0x0003d7cc27a032c3,0x0000ea5d68b8aede}}, {{0x000f6653a0a3f957,0x00060ceba27b3668,0x000728fe98936941,0x00056219981fade4,0x0000102c8a0fa093}, {0x000310e235d21c8d,0x0000eefb7f7bbb80,0x000958a67505e55d,0x000feed0a9081112,0x000067e106b1d851}}, {{0x00011a9431dd80e8,0x0009f3306cd9b840,0x000b3b730eb7c7cc,0x0003d2a0fadd29d1,0x00003858b5c7e37b}, {0x000d193b6251d5c7,0x0002a352d952bf4c,0x000fbc0511cca1fd,0x000636566157a490,0x0000990a638f9b98}}, }, {/* digit=12 [{1,2,3,..,}]*([2^84]*G) */ {{0x000692a87dec0e16,0x000d97b39d00e5aa,0x000cfa0b5010ded8,0x000a281b1b80c854,0x00006beb87700f8e}, {0x000f5313476cd0e8,0x0005308d394950d7,0x000479fc6a63d0e6,0x0007419a09eea953,0x00002ae98927499e}}, {{0x000b9105ca7d8669,0x0001aadb3b34ab58,0x000eac0bc582967e,0x000af4f9ae4447cc,0x000019c667d0bf56}, {0x00017b160f5dcd7b,0x000f2dcaadbc9aec,0x0003467f5ec697b9,0x00032e5b98f34146,0x0000187f1f859671}}, {{0x0007a1d214aeb181,0x000c641432f790fe,0x00091a0c41506af3,0x000bc3ab5565f9e5,0x00000d41a77c44f1}, {0x00065e4a84bde96b,0x0008420a6a1ca09d,0x0007f9ce742f060d,0x00039eb52a3bfdf2,0x00006bdb65ceb3d7}}, {{0x000dcb6ec7fae9f1,0x0004dfb66e5aeb5d,0x000445d52995f271,0x000620cee95d8e69,0x0000b6c2d4619e27}, {0x0001c318129d7161,0x0000f958c1aa3262,0x000f4af63b03909f,0x000df67c468ef91a,0x000062c42a00ba5c}}, {{0x0002343753b9371c,0x00099f1f9cd72f68,0x00045db9629cab45,0x000998971623abb2,0x0000507db09ffd79}, {0x000f652af036c326,0x0007a5018e5c4e2e,0x0008be35086f0cc7,0x000327610a73d4ab,0x0000519b397de826}}, {{0x0005eef9c053df72,0x00079300ea6fe8cb,0x00049cffb8de25b3,0x0009bbbb03fa92c8,0x000042e43a808416}, {0x00051f4dd6f958ec,0x000f34445a8de4fa,0x0000d89496925a77,0x00039026e72a50e9,0x000066648e3eb1f6}}, {{0x0001957173e460c5,0x0004e0704590b2ab,0x0001c71621bbbce7,0x00065d70a90dbddb,0x000005e399e65cdd}, {0x0004dcb57797ab7b,0x0009ba2ca8e86843,0x0003336c160ad35b,0x0000149bfdb1e0de,0x0000bef99ec88b39}}, {{0x00096f31711ebec8,0x000f4e98fdc46c3b,0x000b4411f2da40f1,0x000bb6399774d357,0x00007c8bdf495b65}, {0x00089e3c2eef12d5,0x000aec7471f3da3a,0x00012c594de95bb9,0x00056b100f225bd8,0x00004907c5d7b75a}}, {{0x000c5f08db60e357,0x00068a833319a93c,0x0001683c9743e3cd,0x00007e0dad5c41f8,0x00000c1e7da0c341}, {0x0004a39a6be09070,0x000586d0b7d30edc,0x0002bfa6036d4703,0x0004148c76da0327,0x0000b4a07ea0f08a}}, {{0x0004d2945c1dd539,0x0007931debb5699e,0x0007f00e0cadc589,0x000a0e4f49fcc7a7,0x00003057bc0373e5}, {0x0007ecd027a4cd18,0x00034614011a2f8b,0x000677c68114734b,0x000f4f67a01db767,0x00009d9be5efe273}}, {{0x000cb2e089808ef0,0x000dd59e4107d225,0x00011b9c9f1f7a27,0x00015953afc76182,0x0000361bc67e6819}, {0x0005d0b7f071426a,0x0000470725672a86,0x0006bcabd6a3c181,0x0001bb9e3bca1e0d,0x00001b02bc1e0859}}, {{0x000ee5931fba2393,0x000368bd91d1e0de,0x0001a3c1df47424d,0x00033adf8886f407,0x0000f7d41e8d8192}, {0x00023c2cf6eb9980,0x000f609a287f7086,0x000c9076286bb49a,0x00054b942bb24963,0x0000ef6eea555a96}}, {{0x0002d7236f5defe7,0x000be6f991765f6d,0x0008ce0c7fa9922d,0x00055dfc8c5ecef7,0x0000b44589e2e09b}, {0x0003bca9ea837700,0x000f2ab71547e11b,0x0001ddcc0d7fa2c7,0x0007072a3dd6fa2a,0x00009acb4305a7b7}}, {{0x0004a2e649d4e574,0x000fd917526e4add,0x000b44ac4cd53a2a,0x00031d8526233020,0x0000028746afaa2c}, {0x000839064291d4c7,0x00017e5ad9095131,0x000185681bf48f15,0x0004425ce57f597b,0x0000c3ac1b0b854d}}, {{0x0007dc3c093c171c,0x000364f42b656558,0x0005996cbae7acb2,0x00091a9a338adb95,0x00008e656762051f}, {0x0001fba28b8d0b1c,0x0006f6c10a906671,0x000232a8015d7413,0x000d23b0cdd7eb3a,0x00009e2f0802191e}}, {{0x0001db6f79588c00,0x0009b55768cca80d,0x00054438afa52fc6,0x000a4f0b4df1ae7f,0x0000cadd1a7f9b46}, {0x000a6b31803dd6fc,0x000495eaae35b40e,0x0002e4e16488e4fa,0x000c97df047d5538,0x00009b5b7e0ef6e0}}, {{0x000d2d3957626499,0x000737aea3f66b1b,0x000c6f896a9604ee,0x000ad0a646ff276d,0x0000bf0e7f5b860b}, {0x000c8217cb44b924,0x00036ea9c1822d92,0x00054a5fda2f5ce6,0x000da690a2afb191,0x000082e474cd5801}}, {{0x00072d0b611c24be,0x000480a8f351c199,0x000cf64211d468e6,0x0004910b7580697b,0x0000c9dd0ef68fbc}, {0x000d2bf956c2e32a,0x00043cddf94e5b59,0x000ee766573dc686,0x0006c45d5e2321bc,0x00007b4f8effe9a0}}, {{0x00018dd7280f8553,0x00005baec688fba9,0x000400f42bbaac26,0x0006e473b3f00f33,0x0000d2dba2996f2e}, {0x0001a94985093755,0x000f7ea423ccb6f7,0x00007e6fb8f33031,0x00054bb09b8dd048,0x0000163cfe5acdb9}}, {{0x0008f17cf41c6e88,0x0009837b925c03cc,0x000d2427cf1f03c2,0x0008e4439c19cc66,0x000023d24bafb6c1}, {0x0009013901f0b4f7,0x000188941c2e32ef,0x00028092e684360f,0x00032e9ebaff522c,0x0000891e4e3956c9}}, {{0x0004319ac445e3d2,0x00076ea743815126,0x000e9c50a553432e,0x0008c7c6eeaa6967,0x00007ced28482e62}, {0x000d3757a4afa571,0x0003d484c1503f96,0x000bd9923de0a14c,0x000422264a24eb38,0x0000df18da0f5177}}, {{0x0008f82d8d38a9b9,0x000057de1391174e,0x000c175dd2e97c60,0x00003535709850a1,0x000069041a0c2ae5}, {0x000533b76a2086b3,0x000ba7c2e8fecbfd,0x0009dfb67d6bba71,0x0005d982d58ee609,0x0000a8b342d364a8}}, {{0x0007649522f9be32,0x000bbf1f49a83bc0,0x00054ec42690c075,0x000dc760e1aee838,0x0000a7dbf4437689}, {0x000fc0e3faf40783,0x000eaf11862cc004,0x000a1b7b3b2f02e9,0x000c80c10a5e0fa0,0x00000aca623b936e}}, {{0x000bf0502f40d9ab,0x00077c318a4df83c,0x0009c26744681c46,0x00092de85756180e,0x0000e79d046c8470}, {0x000480a78bd01e0c,0x0003b2a51db9af1e,0x000afbab66dd359e,0x000198a2ce3821e3,0x00005cee5b6d7733}}, {{0x00030d46ffd9fbbc,0x000876c610b7e08b,0x000e262cf6e5bc69,0x0004c13343cff29c,0x0000a2e4e3628b91}, {0x00064c016de36c5e,0x000c62e2b829011d,0x00085aaf8e0b10fd,0x000e969894298166,0x00007511709030ed}}, {{0x000d8fc3b922bf8a,0x000fac29b133671e,0x0006e99c4e4d8c09,0x000eb9e7eb12393b,0x0000ff3974d2793b}, {0x00094052c18df9b0,0x0003910071390374,0x0007a0b95c5c3a29,0x00096b6a77234fe3,0x00002c29a21b661c}}, {{0x000f1d6141ecf611,0x000e2bb22f53c3aa,0x000d513579195509,0x000d601959740422,0x0000b083822637be}, {0x0006e35e07289f09,0x000bddd86effcd7d,0x0000f9cfa1f94c48,0x00097d38bb1f82eb,0x0000ee0b7e6ab2eb}}, {{0x000fe2e34d74e31b,0x000f8bf79ab65a52,0x000feeb8fa352c30,0x000304e7ff6c5aab,0x0000fbe8ff0a5c97}, {0x0001ce6a79046089,0x000a34fca249d608,0x000e5e2001f812f3,0x000ee80b24bc9ab9,0x00001022c67c8012}}, {{0x0009c5d30a713a1e,0x000fa4ef0f93e83d,0x000fbf9284876e3e,0x0002a3e9777029c1,0x0000f7a6bb49ce7d}, {0x0007228dfa2a659d,0x00080877a48fb806,0x0005d0f3fd5cd339,0x000c2aeea4fd8f02,0x000067d2e35feae7}}, {{0x000e7d7cc5f43941,0x000c3536e142184d,0x0004aa60ab5551b5,0x0001d51e89b212d3,0x00004a96feb05005}, {0x000ef740d12bb0b3,0x000030b9677e4e21,0x000f7731dc522f02,0x000d315b12e4672d,0x00009f80382ab326}}, {{0x000630c39024a940,0x000897319452dfb8,0x000a3867caacb96a,0x000fcad68a3961ed,0x0000c58e2b077c4f}, {0x0005d634da919fac,0x000a315e22893d54,0x0008bab10ef79b69,0x000c3694bc3d3d80,0x00008ab300805f82}}, {{0x00038b67c4a658ad,0x000870e72182c127,0x00098e44fb3c4763,0x00085e6b77be4687,0x0000c047df2e7a7f}, {0x000d4c55e59d92d3,0x0005b8e64d8d2439,0x000ca9b16cedca47,0x000dfe7724cd0d87,0x00005e4fd59d5540}}, {{0x000ff18e4bcf6b1a,0x0004895018faf8c1,0x00063c949856d628,0x000408a33f665c32,0x00006a76dd741f21}, {0x0002334cc7b4f79f,0x000116720e4a17d3,0x000d9bed5a1d0312,0x0005d0bdb6661d81,0x00000d6fb0301db1}}, {{0x0001ad51fb747d2c,0x00087033762b7fd1,0x000efaf5aab50f95,0x000bbe6a7e711bfb,0x00007393278ffef2}, {0x000a2440df6f9be3,0x000b41efd215e29f,0x0003d6fd99092757,0x00078bbe60e3114f,0x000038542d43acfb}}, {{0x0003f0838961a0f4,0x000e586987ca44a2,0x000863cc61426ead,0x000b78f6e6ee2e4a,0x00008059420a28b8}, {0x0003ad87396e1dea,0x000798c5aad13030,0x0008f50665c8bdc4,0x000bbc9e40e11f5c,0x0000bd6e7692d246}}, {{0x00040bb23330a011,0x0004b34eafa068aa,0x000e02c21d23f5ee,0x000d062bbee3155d,0x00008dd4397e1d8d}, {0x000939a122d7b44f,0x0009b33870d63ba1,0x0004fe3f8e6d3b40,0x000cbe9e620f701c,0x00006bba1a6c3a50}}, {{0x000bde5cfc0aee0c,0x0006008c50bd4a78,0x00063c9b2847edc4,0x000acafaa2439cad,0x0000eb4a728d0fc2}, {0x000e40e26da033d0,0x000d03e02683a419,0x000ccf7256cc3889,0x0002081cd28559fd,0x0000fd7e0f18d13d}}, {{0x000733b1f0df9d48,0x000322b5e4f301b9,0x000304fd48cc2c5f,0x000aa6c3053bfa3a,0x0000e87665c8a9f1}, {0x00029ecd73dc965f,0x00044e9023db087f,0x000ce28b415ace45,0x0008493370e3092b,0x00009723443a6b1e}}, {{0x000662eb72d9f264,0x000eb0e47109beee,0x0003289d0b19396d,0x000e3245b1fa73e1,0x000036cf77e94e58}, {0x00033b3e990ef77c,0x000c5b11fc250ec8,0x000c332ce7373e3e,0x000855fe0eda870f,0x0000ed049714d7ea}}, {{0x000f7857e977ca05,0x000a8fdd5d2bf85f,0x0005af461b66ee8d,0x00087ca5e3795090,0x000087b9090e66d4}, {0x0008a1b32ba0127e,0x0006341615ac6a19,0x0006ef2f2a7720e0,0x000b3cc23f349999,0x0000f5f64b5270bc}}, {{0x000a96292b8c5599,0x000fd9740a0fa526,0x000bdc0a50c14aab,0x000ef37d41a9e3a6,0x00007d521072c48a}, {0x000bd303e7c253b2,0x000a27fdedc1cf16,0x0003aab2ecc834b1,0x0000ff5362c6e537,0x000064ed85ee5f59}}, {{0x000d9c066d41870b,0x00009787ba097a46,0x000d44635a50c20b,0x0008db685e7e51e3,0x00003b3e080e1e2d}, {0x000e558a179e9d94,0x000934a76781bed1,0x00040864f2daa3f7,0x000cb50372baf23a,0x00006900c548fe75}}, {{0x000171ef76765d05,0x000245c87502b95f,0x0007c99bd4ad726d,0x000fa7dec769da4d,0x0000e2ddd1a136cd}, {0x00017fca93e6dea4,0x000b53771123c221,0x00008a3a2e8a2583,0x0001127e2f6089fa,0x0000809d5edcf0e1}}, {{0x0004aa3da7a095ed,0x000056f5aadd3b41,0x000e8b84a9049acf,0x0009b2a8d46a4d6b,0x000066b19648732b}, {0x000c2a0de6e95555,0x000865bd87705c2a,0x000d28921cf52d09,0x00036cc5a15fa60f,0x00006ccb81edb275}}, {{0x0008ab89f4ccbb8c,0x00021b2217290f0d,0x000bed10ced5f44d,0x000b8a8314198800,0x000094348a4dd735}, {0x000e9c429ef8479b,0x0002b14c693f79f3,0x000143a144c13a4e,0x0005c382c9af568e,0x0000c51779a929ac}}, {{0x00079922774856f7,0x0004fc1bf55f05e1,0x000f19e166e52fb0,0x000b263eda4225e4,0x00000f4728b1f5cc}, {0x00018d1b2947f224,0x0005e81d6fb95d21,0x000f0eabdc827ea1,0x000dcf4412328d8c,0x00005ee9fb243ef9}}, {{0x0000421bb937d636,0x00056c4b37a68e70,0x000ed7b68df8ff2d,0x000f5944c0d5b25c,0x0000537c1f027308}, {0x0006a263b37f8e84,0x000b9eebc6ce25ce,0x00028d72c170e9a9,0x0004bc9d03795287,0x000045b0e55c5015}}, {{0x0000e0683a7337bd,0x00042fecf2494b7d,0x000a2b71f1e3416d,0x00026c54840eff66,0x00000d9a50b837cc}, {0x00081506fe28ef7e,0x000543324c7fe219,0x0009b52633cc5ef1,0x000474420f345576,0x00002ade2f2810bf}}, {{0x00020fa458d36710,0x000c2dc4847b28cd,0x0001941e31549722,0x000ccb6dd01e5559,0x0000e6fbcea27128}, {0x0001e6b3bef0262d,0x000bbf54e103ae1a,0x000c052ecfa8c472,0x0000e8a539c0a872,0x00007b2736a2a349}}, {{0x000e1f1716843491,0x000e22e19b97143f,0x000980aff36b4722,0x000674cc05922790,0x000075c9c88ae13d}, {0x0005b226e6bfdb1f,0x0001cedb4b46a7de,0x0004a6e445ea5b7b,0x0007e5e5570191d3,0x0000cf60d2f924ff}}, {{0x000392d677819e1a,0x000e0a5a29e8614a,0x000c85f3f7be74c7,0x0003370b50fece63,0x0000ca2e2a9e6cab}, {0x0000388122a6fe3d,0x0002b82a04a87f70,0x0007aed57db69f70,0x00086eca77935dcf,0x0000f16207d5d91c}}, {{0x00049ab63ed9998a,0x0004077ddf962fca,0x000344072a3125c4,0x000b5565dd8a8624,0x0000023dda39ec3f}, {0x00041fc0c743032b,0x0000ae438639421b,0x0003c1b074f2120c,0x00071a4b7cae51c8,0x00002370cab7ac21}}, {{0x000d9626cc820fb6,0x000c585a44bf2eb2,0x0006598f059feee5,0x00005134620fca5b,0x0000b922caede314}, {0x00045ad106bed4e9,0x00054fa1e9abff87,0x000c29487546e71f,0x000530035c1e481e,0x0000509216cdd936}}, {{0x000306785c9a2dbc,0x0001abe8606fc7ca,0x0004c651dd6ae515,0x000f9549dbcae6e1,0x00009536e245bc32}, {0x00035a934521b032,0x000c678756ffa905,0x000edf03cf39c526,0x000034183172ec8a,0x00000a8075f0fe0c}}, {{0x0009c62640264225,0x000fd4b9d076f22f,0x000ef29508dd1077,0x00000b444c742a3b,0x00005b9502ed8a2b}, {0x00014b486a098170,0x000c47bb4071a59e,0x000e0592fa39dd3a,0x000f5b55137f663b,0x00007fcafd4c9e63}}, {{0x00052ee346eb2263,0x0005bc2facb79636,0x0001add267dfab08,0x000c43f73bf2b869,0x00000d7454122b46}, {0x000e73ef2c2d065e,0x000ff42eeac905e8,0x000209d22ff9b89f,0x000a2b4fcbd20597,0x0000b740ffbbe14e}}, {{0x000f913a8aef5181,0x000beff4cfa2c71f,0x000b360487bfc74b,0x000af10716680cb6,0x000021b2cceaef79}, {0x000c836a01eb3d34,0x000a1f79077bbff3,0x00004bbcf50eb1c6,0x00061d648c32d6a0,0x00007a59316bd64f}}, {{0x000147f931020167,0x000424d125766068,0x000bc6b9112c5f65,0x000a957fb071a7c9,0x0000c2da0c5de23e}, {0x00045b6d4a1dd5d1,0x00068122b13cf4fd,0x000f57a483e7ad9b,0x00088f242ca118e6,0x0000c2e94a716f82}}, {{0x0008f075a97d231b,0x00069d83875899e6,0x0008727277c80de9,0x0000160ce0f5d005,0x0000e5d95c2c9c4d}, {0x0005cb19c2492eed,0x0000704d6fb3921d,0x000f988d342192dc,0x000e847c84dcd132,0x0000e26d620717b8}}, {{0x000dcb6137c7408e,0x000556a266dac466,0x000bebf1b9a38d7b,0x0004e29ef5cb0683,0x00005cdcbbfefd01}, {0x000376df65965a08,0x00026bb3e95e30aa,0x000ee6f2060fe88c,0x00009fb3fd0b6166,0x0000827dcdbbf41f}}, {{0x0009d240c56c6904,0x000d9db7641dbf8a,0x0006b662b40265da,0x000c9b122b05bf3a,0x000066d1dfef1478}, {0x00069621484469b5,0x0008b2df8f9faa61,0x000b8bf510db6054,0x000ce8737bca023c,0x0000effe34671371}}, {{0x0005264ff112c32f,0x000c8b971fb2e8f6,0x00075080d8a9c736,0x00059ab4f194707b,0x0000c3f2c5b7839c}, {0x000777e5aeb49c20,0x000dda1addfe1d6c,0x00035affcf3db034,0x0001fdd76fee5a55,0x0000853ac70b9225}}, {{0x000d5948b2a29d5d,0x00067de00ddb37e3,0x0002c328b28f1f45,0x00073ab083c1b5f4,0x00008ef1d90b493c}, {0x000626041dc61bde,0x000c47ee2f8a96fb,0x000946a5df74e8a9,0x000cfc9c605a802c,0x0000ed48d661839c}}, {{0x000344f3a29467a3,0x0009951eba6d9894,0x000e5c2f2de81e94,0x0007b3aaea066ba5,0x0000fc8a61438c8c}, {0x000f88f06d0de9fa,0x00049b75ce0a7adf,0x000bc87d5bbc11cf,0x000de1ffbb7accfb,0x00001458e271badf}}, }, {/* digit=13 [{1,2,3,..,}]*([2^91]*G) */ {{0x0003668e039c2560,0x000b7c17fd5d1cb4,0x000aa062b5f26fb8,0x000f04eee426af79,0x000072002d0d78fb}, {0x000a237e84fb7e3e,0x00002c82133d4c9c,0x0007e4181b401d8a,0x000151caa525926d,0x0000943083453dbb}}, {{0x000da31be24319a2,0x000bc095a8e7f92d,0x00078218503f7d28,0x000dbc852fe84098,0x000076ddafe49c24}, {0x00054961d7a64eb7,0x00090f1dbe4280cd,0x00038d2d5e436088,0x000035bf81a87784,0x0000e4d52a8f5169}}, {{0x000d5b11d59715df,0x0001e788983e19e3,0x000f1f248c7eaa76,0x000d82f5a730b0ab,0x0000bab8085eae3f}, {0x0000d2153765b2f5,0x0003aa127f3d65e5,0x0007b1b10bdd4e08,0x000fd34cf3c07439,0x00009f8090d01b59}}, {{0x000fd9d615faa8f2,0x0000768554ed7b15,0x000a448828fa1eb4,0x000f325bb4447e7a,0x0000bb2d0d1229ff}, {0x0002a646caa6d2f2,0x000e02e7351b075e,0x000506c628eb879d,0x0004dc9cd5624e9a,0x000018eaef0c87e2}}, {{0x000684744ddfa350,0x0005dab3f74737e5,0x000e96cf49ccfc5c,0x000b8f9ac1df3f1e,0x0000c0571a13b480}, {0x000b3d54b3a7b3cd,0x00088dcdbb992fbe,0x000415b3a35c0366,0x000d9982a0f5dcb2,0x000057759b51413e}}, {{0x00047d83d30a2c5c,0x000e378a81dc1fe6,0x0001a4a9b0857f77,0x0003f451d5a33413,0x00000a94af9e9d39}, {0x0005c0bdaa6ec1a9,0x0002f8d2d7edbc3a,0x000614797ba9fe49,0x0005332b4335b4bb,0x000091c4d6902f83}}, {{0x0008c28d2f01cb3a,0x0003375db0b15325,0x0007d0db493d6eaa,0x000492a19a2b0de8,0x00001e48f0478fe8}, {0x000faf6c508b23ac,0x000975d53549f747,0x000f9b838f137571,0x000cf4df5e58e2fc,0x00007186cef67fd3}}, {{0x00068cee978a1d35,0x00032ab92d0477b8,0x000a5b862e3a68b3,0x00041d0102979487,0x0000f0606c38a61d}, {0x000be276f9326f11,0x0004b6fe3c2e2814,0x000df73512f521c1,0x000e4407464d7dac,0x00000f5f9d3877f7}}, {{0x000616b269fb37d5,0x00042de62de5ce8e,0x000dd4153aaf7380,0x00049b5ba111754f,0x000015759ba8770b}, {0x000ebf8aa423a61a,0x00012d41fb928b09,0x0004c8936592245a,0x00010d7cba8ec19b,0x000087e91e44f367}}, {{0x0004ce43d34a2e3f,0x000dc43b5d611fd8,0x0009186c7ee3759c,0x000259995bc78c61,0x000019c380abbb97}, {0x00021aade744b1f6,0x000000f8056bc0be,0x0003efe11a7d222b,0x00025314be6157b2,0x0000fab2b4f6cd68}}, {{0x000ea5f4bf1d7255,0x0001ff6c950fad33,0x00077af069c1d8ee,0x0003e1044ee78aa3,0x00004f489bbe4a11}, {0x000d634992fb7e89,0x000a12a443478f11,0x000020e000169a7a,0x00020a8d49d4af95,0x00005945723708e1}}, {{0x0003878a4d32282f,0x000c58020ae7b6e3,0x000a9b750e36e029,0x000818f05847fb37,0x0000876812da29e3}, {0x000138ed23a17f08,0x000070b3950e84ad,0x000d67ae06d7b448,0x000af65fa8aef42f,0x0000d3eea24d2333}}, {{0x0002075b15d5acc9,0x000f2d815bc40d05,0x000a36cf2c6d9c79,0x00006ffdcafd88df,0x000008ccbe2c8aa9}, {0x00022c4ba35afce8,0x00007d6abf0b6387,0x000c335c15a3da8b,0x00099aadce252cc9,0x00004e7f0dee5aa7}}, {{0x000a522b99a72cb0,0x0007876180162101,0x000f3653e06de6e6,0x00054a5ff8c7cde6,0x0000a821ab5c7a67}, {0x000a52b7cb0b5a2b,0x000c190487907e3f,0x000ce053aa7fb121,0x0009af6a72502006,0x0000490a31fb4e92}}, {{0x000e47d62dd61ad3,0x000c3be01371e17b,0x000e3cbba781a961,0x0009b9e063bfd3da,0x00005647406af73c}, {0x000957b2736a129c,0x00022d13f256f50e,0x00019fcc5a631370,0x0008b5d436ee653a,0x0000f2bdb2aa7a4c}}, {{0x0001244c5f95cd80,0x0000f4ab95f4b06b,0x000e5836dda8c8af,0x000ffc1bae59c2b9,0x00007d51e7e3acff}, {0x0005e6ac2ccbcda6,0x000f2528c3e001e1,0x0009fead43bc1923,0x000710e3324577a4,0x00001a1b8848aa7a}}, {{0x0006e08700230ef6,0x00015d19adf8f9a8,0x0005ad8f20af585a,0x00014c1645f361f5,0x0000e676223a6c36}, {0x000257c4e774d3fe,0x0002cc102d1b23cb,0x000126aa582a3851,0x000ee3bbcddd887b,0x0000716998ccefd3}}, {{0x000d571fb1675839,0x0008416c8f8a4239,0x000a27519dd011c7,0x000b69971c289569,0x0000ce0a3b862d64}, {0x0007289d5ec67385,0x000a3840ef6b8c97,0x000453419a3b49f9,0x0002d5308c14c99a,0x0000c00295b5cf0a}}, {{0x00014fb1d4bcc766,0x0001e59a88f15244,0x0000d110fb07691d,0x0009f317f43263f7,0x00004ada5e117abf}, {0x000f94e5b544cf50,0x0005fd2713feafd0,0x0000c74f4b4a13a1,0x000e45b99b7d6e25,0x000097f2f7320324}}, {{0x00037d8affa8208d,0x000b0c29aafc994b,0x0003a607fc3c31b0,0x0005d56da746517a,0x00008e1b8c2ce695}, {0x0001815c8418682f,0x000e8dc91d97716e,0x000996982541d487,0x00002d58a04669c6,0x000039cab1673a65}}, {{0x00001a0e68db0554,0x00087a3338d50258,0x0002afa84f356975,0x0002d170c8c0aaee,0x0000f6985d43b656}, {0x0001f15132ed17ab,0x0004104365fe351f,0x000b1f066510ed0b,0x0003dbf3f98138e5,0x0000c9d95d6e2df0}}, {{0x000cf6e19abd09e2,0x00012ff17edba83c,0x0004a06ce0b4097c,0x0008fd38a5c478d6,0x0000ddcc3fd744a5}, {0x000503d9e8153b8e,0x00019774179bd449,0x000d9120c3324fd0,0x0004dacf5d47c8db,0x0000b86016314fa9}}, {{0x000bdd1972f07f4b,0x000e227bbceb5817,0x00011e5a6e5579e2,0x000047d6847a1f5f,0x000039ed2562c3cf}, {0x0006417a2f62e55f,0x000e2bcf82a2e107,0x000eb29f96b9ab38,0x000a455bb7c3197a,0x00006d17da407227}}, {{0x000ddbd0f968c006,0x000ba00c880bab53,0x0009ad24da03da7e,0x0000d01b2396246a,0x000012c040161ec6}, {0x0000493109f5df10,0x000080af755070d1,0x000b9a9b3fbda403,0x00041830b93f95c6,0x0000c74ec71007d9}}, {{0x00055646edb951fb,0x0007cf22c2829417,0x0008d11965f4a9d7,0x000e7c07870895b3,0x0000c593df45228c}, {0x0005bd46af3641a8,0x000abd9b3dccc78c,0x000e333047802200,0x0007998dc73f328b,0x000047ed87de1ffb}}, {{0x000974e6d6711921,0x000ace16f60ff85c,0x000c387971e14100,0x000da435cb0d5a95,0x00008923bbaab022}, {0x000e899bbe7e86e1,0x000e116067bfef2b,0x000d5ce3e4a1510e,0x000b90c98c815484,0x0000af777f1092a2}}, {{0x000b4004ef657241,0x00092c0ca6fe9fbc,0x0000029943e04a4c,0x000cabeb3e2cb555,0x0000f3a93c56363e}, {0x0000efe3923555b8,0x00089e1751ea1fe0,0x000b69357744bedd,0x00018abfb2db596a,0x0000dbd736675e66}}, {{0x0003099df1ea40e2,0x000b37d61e6499d5,0x0006eb812b3f24a0,0x00040bb088a19859,0x00002c8361b77629}, {0x0001f97f9c0d95c1,0x00027e43cdae66f0,0x0002b15c38846117,0x0005cc01599a7fb7,0x000035a7536520d9}}, {{0x000f0f75f7ae2f68,0x000d57fa6da22dcd,0x000d441b615fc6e1,0x0006b601ca829ad1,0x00004c10cf884a10}, {0x0006c95a73fbbd0f,0x000a5d8f6ee8a9b2,0x00025a0437f24e0c,0x000dfd58b459371e,0x00008a74fcaf36f3}}, {{0x0006585c9f842969,0x000aabc278b01ed4,0x0004fcbd07fbaa8f,0x000a5f18e96cd46c,0x000040a120303b60}, {0x000e12055a4aec84,0x00049bd742f034aa,0x0008c68ab550e9a7,0x000ec6394456d722,0x000092f8868e4e25}}, {{0x00015adb2d8f3984,0x000c1b84c9536829,0x000b917d6f13b51c,0x000ee18da90ab85b,0x0000b6155608ea3d}, {0x0004e850a52c1c82,0x000500b75fc4578b,0x0000bb3c6eab1a69,0x00009440c14f3caa,0x000020f448ad8216}}, {{0x000ee31b0e63d348,0x000229e54fab4fe7,0x000e7b5a4f460057,0x00083140493334d5,0x0000589fb9286d54}, {0x000f5cc6583553ae,0x000a025649e5aa70,0x0000446520879094,0x000c4eec90450710,0x0000bb0696de2541}}, {{0x0001fdeb9718710f,0x00080374a9f55a17,0x00039bdc138f1bed,0x0000cdd8c582e1ba,0x0000c457b0b808cc}, {0x0007fd4883841e20,0x0009387253819a18,0x000f843958ec25b3,0x0008972553ed0596,0x000095c76616f6c6}}, {{0x000c85c4bdc56104,0x0003d79eb301917a,0x00078bdccb2885fe,0x0006991fc655478b,0x0000a9fc894259e4}, {0x000f0cd3ce299af5,0x00035df38b20bb7f,0x0008ddb8f195be9b,0x0001b91a929c87d3,0x00005fcc99d021a5}}, {{0x0005b4c721a4593f,0x0004868eaac22b69,0x00089f914ed1e9a1,0x0009100b63d71c74,0x000098ba31d68118}, {0x00013739b128eb4e,0x000df448af4a8029,0x000418dd37801214,0x000241fbd2e22b55,0x0000ffb3c0eb3998}}, {{0x000077cc7bf3827e,0x000a67f8238fdfa6,0x00064d554f2165bc,0x000b981e37cf6885,0x00005f825c4ea81f}, {0x0004f67ffed4d6f5,0x0008650a34b043cc,0x00041faf1bc60957,0x0003b63aa8fcf950,0x0000659f053b5177}}, {{0x00082c36044d63bf,0x00081cdb0ca0e875,0x000b2bcf6a608940,0x000cfb9c993e0fbf,0x0000c64a71a35985}, {0x000da8083dbedba1,0x00021be67df715c4,0x0003defde804ae11,0x0000d3ca4c9658a2,0x00002002ddd6156e}}, {{0x000ae895dd21b96d,0x000aff44624de68e,0x000c8897a8b99f28,0x00076d3ae008081e,0x0000d0a93043712f}, {0x00075224e233de42,0x00010b36a8a59623,0x0003993d9192445b,0x000a8f8bf9ff7402,0x00001f37bf44aad4}}, {{0x0004349f8bd2bbd7,0x0008d868195d340a,0x000fdb6f11d902cd,0x000f1bcd27bbf1e5,0x0000a5ab088824f9}, {0x000ab06f7a09e03c,0x000671f2c123c466,0x0001b66572f8a197,0x000a7c1a355dc704,0x0000b840d134ece2}}, {{0x000ad9f7db326750,0x000307a06f1bb600,0x0001f609478fea13,0x0007aa5d032269b3,0x00007753ef583ec3}, {0x0005aed9c0bea786,0x00095c3f45240348,0x0007f726d41bb398,0x00081fa940376169,0x0000109beb43f394}}, {{0x00011ea3b6d1145a,0x0009085826548041,0x000e66562b6271ea,0x000d9bc19615e624,0x0000255494677b6a}, {0x000985e99bfe35f8,0x000ffb51cdf6d9c4,0x0008818329770ccb,0x0006d0fc32701392,0x0000777d45fa86b2}}, {{0x000da22d847999db,0x000613525d329bbe,0x000a959a103aa33b,0x0002339b7b96d428,0x0000b3786e5e1e5d}, {0x000d3ce6961f247b,0x000e52f93d3faeb5,0x000a7ae4f20aa85a,0x000aa7ecd1ad3dd7,0x0000f6688f1281ad}}, {{0x0000e867469ceadb,0x0003809fca48b1b4,0x00054bbc71904c52,0x000fa1eb7312af4b,0x0000e24bf90093af}, {0x0000790bd98764be,0x0006c26e299ebe5e,0x0008fe4c7a0f45f1,0x0003e56af0d2c26b,0x0000f170db26ae8a}}, {{0x00061a029e0ccc17,0x000df0ad36ca0e8d,0x000173822cd53e87,0x000e54c28c6623c8,0x0000ee1767e1496b}, {0x0003259648945af4,0x000ce5c8009c89f1,0x00061ab8c9e45a5f,0x0003856f2febd91f,0x00003f6bc86ca275}}, {{0x0002348f2142e791,0x0009b6e6238a8779,0x000839d9b17d8925,0x000bdc6536d2f64a,0x0000f428fce86a1f}, {0x00096010db06dfe5,0x000100a3a3cc1c10,0x00030f41bbfc16bc,0x000ccea9cbd9ec9b,0x0000b5da0d650138}}, {{0x0000a4856ef96a74,0x0008582bf842ec1d,0x0003f700db47eb84,0x0001e026deae32ec,0x0000e43c42cea118}, {0x0002a31d1a4aa2a8,0x00084004f3cea1d7,0x000fe8a7a440d466,0x0003648d6a2d3b45,0x000020e52e37b128}}, {{0x0005fcf25e51b09f,0x000e3023d15929ac,0x000ebf90e180cd2b,0x000180b9892171a1,0x000097c4c886c132}, {0x000c724c03dbb7ea,0x0004618cbbe49f1d,0x00067d153ae04376,0x000aeb5b0b2a3607,0x00008e2f4d6c49cb}}, {{0x0005247d95ea1682,0x000a0970764a172a,0x0009781691758fad,0x00001b8c803a511d,0x000099cfe2efe77e}, {0x0001e17b0a98927c,0x000060014495652a,0x00075b56a2e26e1d,0x000f94bae0af9f71,0x00002e22a81964b9}}, {{0x000f9fbd90a060ab,0x000b0af380854d0f,0x000776bcf496a27d,0x00009d82305401da,0x00008cdcef7225f2}, {0x0000f37436a0bbaa,0x0007d686004961ba,0x0003542cf263fa10,0x000537f2beb98eda,0x00002d4d14b75849}}, {{0x0009d6812e9a1bcd,0x000b8f6e3268989b,0x000ace63861d9075,0x0003fe652c6aa999,0x0000e4e4a56620f4}, {0x000144ad673c0175,0x000e1f6e05eae5e4,0x000d1bd56667417a,0x000711113416aedc,0x0000eb36201d6693}}, {{0x000c5043a1aa9145,0x000926dc59752d7b,0x000c8125c175a129,0x0008759900e0f23f,0x000069ef68c61198}, {0x000db6363a113b4a,0x0005f88357669012,0x000412deae3bd3f5,0x000e5c05c94a5276,0x0000d9e2a0a4a735}}, {{0x000984c508b65e9e,0x00008df1a0d1405a,0x000ba80dabde4a1d,0x000d2d3a9433a1df,0x00009192ffa7440a}, {0x00096965099fe925,0x000bbb27a54a9f64,0x00090da6125ddb65,0x000819c78279ddc5,0x0000479a99a4bde6}}, {{0x0004e05013fe1620,0x0002632d471bd0e8,0x0000e089fbe11dc9,0x000025df0b0c45fc,0x00004fb15b04c144}, {0x0005fc213c999279,0x000fade2eb35a61d,0x000dacbb4a033e9d,0x00049d68185d5cb8,0x0000a88e26616445}}, {{0x000af6254671ff6c,0x000a9fa58603f717,0x0007773c04bd4241,0x0007e846fba40be6,0x00001d933d32a284}, {0x000acf3689e2c70c,0x000686bafd31f4f5,0x00073f6e592aab0e,0x000933b98d76aa34,0x0000c6641dc53141}}, {{0x0007757d31e535ec,0x0005c7c2ee11cae2,0x000029ffa04cc43b,0x000a2bcd1f96752e,0x00002150673a4cc7}, {0x000c1e08d68b0139,0x000f5df298f33b03,0x000804464a9d6816,0x0001248bfbb529a2,0x00005a52faeedb22}}, {{0x00021600e1cb64eb,0x0005ce7fc9fe55b3,0x000b0fb93004828f,0x00091f63394b821b,0x00006293a2de5f1a}, {0x000ef21d145d2d9a,0x00031b8fa603de35,0x000cf252dbe6225b,0x0008c160fc8f6b32,0x000028e52e6b17cf}}, {{0x000c89b4c371e6da,0x000496ef0f289d1d,0x000292f81cebe067,0x000082bde05d09a4,0x00008303593d53e3}, {0x0005b0a7e37a9bb0,0x000e2b8faec3a171,0x000c9b1028c56f61,0x0001f05250743133,0x0000130cefca4443}}, {{0x0009fa0bd865cfbc,0x0007fc5f1dd75603,0x000be72244b03e57,0x0008f580edf2e4ba,0x0000752496dfa198}, {0x0002d3b564beb6b0,0x000039a1c608d157,0x000f601260db1d11,0x000f33568d193416,0x00005ae9668f354a}}, {{0x0006d37c92544f2b,0x0002f35837d519de,0x000514ececc08435,0x0000661bb6869c1a,0x0000633e728de1d1}, {0x000d69f936c581cb,0x000dc439c4f9f15d,0x000448a5b96e7b8c,0x000bbaae676f482e,0x00002ca7d5cad916}}, {{0x0002541f50240258,0x000964c2d937d55a,0x00062189f47bc576,0x0006f8fd31b92a03,0x00003f3086f6f781}, {0x0006d94b587579ab,0x000780e76c5ff9f4,0x00000ffcfec2d22d,0x000c2b77d57461b0,0x0000b7e65f9e64ff}}, {{0x00094776652a220f,0x0008e696c9817c7c,0x000effff361618f8,0x0001626021701d89,0x00002c8ff8f6c314}, {0x00013ad8efb4d3e2,0x000fae176d952da4,0x00067d51c937b5ad,0x000ac902867d342a,0x000062b9b1038eb3}}, {{0x0004fe4c43ff28b8,0x0006ea664e7a4e31,0x000a565c27647662,0x000830be90e40bb7,0x0000588993b41acf}, {0x00001d68f938829a,0x000d9edd7d4cd7b5,0x000cd34c7996627e,0x000e8c97d44a6290,0x0000832749a93833}}, {{0x000917d4bf503533,0x000b256765fb2e18,0x000d5ab6685dd726,0x0005fe24fe65d693,0x0000ddbacedc15c2}, {0x000d9a412f22e85f,0x00067d06f6bca799,0x000ca1637e2a2486,0x00030a04f1ee5643,0x0000da2828c51ece}}, {{0x0001a3ea2dee7a63,0x000c434b2284758c,0x000aba6addcde2f3,0x0000a77ba445d24e,0x00005aaf668a6cee}, {0x00004a9e5aa049a6,0x000d31103e847e0b,0x000afecc3e74083a,0x000f7a5eb183ce40,0x0000b89dea04a043}}, }, {/* digit=14 [{1,2,3,..,}]*([2^98]*G) */ {{0x0009d23fe67ba665,0x000043cf2f340e29,0x000fcf9139145076,0x000ddaa45b5ea997,0x0000be00843dbd7d}, {0x0003e05d53ff04d3,0x00032de91ef7358c,0x0009ec1a0bf7ccdc,0x0009977d684dbfb6,0x000067e7cf2b01fd}}, {{0x000f3b7b0dc85957,0x00082f1d9f2e0ca1,0x000dd82a727de460,0x000447aaf3bf39ba,0x00009356a79d5862}, {0x0002345f5f9a0529,0x0008839a42f9c060,0x0004d40fc1a8b0f8,0x000368253eee4284,0x00003b0bfe5de5b6}}, {{0x000dd02c024789cf,0x000951b57bfc5434,0x0003398df90dca9e,0x0004ba9aa898e224,0x0000607c835794a9}, {0x000be97c2c99b76f,0x000628c29302bb07,0x00003a88c6576ba6,0x0001054d79efcce7,0x0000259ced8a6a0d}}, {{0x0003a5dc8de610b8,0x000ae7e223ce0f89,0x000ad6dc5e8c515f,0x00028ef774bfa64e,0x00009d20f96125c7}, {0x0000966098583ce0,0x000493f2a7d77a1e,0x000304d4aa2eedb9,0x00082d1b2820974c,0x0000842e3dac0772}}, {{0x00072a33b9e2d7b5,0x0007748218ffe4d9,0x000149d917cc60b2,0x000ecc3fc7083884,0x0000c04346f7f461}, {0x000fdf2614650a98,0x000741f666acebe9,0x000babc835e35b53,0x00093de45613d188,0x00008cace3b45e1c}}, {{0x000a3753de92e23f,0x00076fbbb6e3209c,0x000b1487eccb03cc,0x00041edcb90f03d7,0x0000a9c2a39b7109}, {0x00038236724ceedd,0x0007492d0323756c,0x0005e038e3a90225,0x000590e150e519ea,0x0000cba286697427}}, {{0x000237f788907328,0x0008d3fcb4d9e549,0x0003480d6c443bef,0x0001861884d8a6eb,0x0000a35b6a1b048b}, {0x000471665e9a90a2,0x000d453006c0b4e4,0x000e9ae3b45bf380,0x000b716f3f820d4f,0x000044a35a0b79a3}}, {{0x0000e9d74cd06ff8,0x000f2ca3eeaca101,0x00063aa2b9c17c7d,0x0004fef4c86cd380,0x0000595c4b3f3461}, {0x00000ca990f62ccd,0x0002fa0c3be5a3de,0x0008ce9f5d9bed21,0x000443a886078adf,0x0000db27ce42cd44}}, {{0x0004a6658926ddd8,0x0009108015b8ed37,0x0001f7ab8138b2d4,0x000b7a086c6579de,0x000088b9aa143020}, {0x000034e3a96e3551,0x0008e30fbe9ad3ec,0x00021367aba65b0b,0x00046df64c8e50ff,0x0000f508ea41b04b}}, {{0x0001a49747c866c7,0x000d9518a0629856,0x000dc3608bbb1e5f,0x000026b0ff4e8bec,0x0000f55cded90184}, {0x000ec95f38c85f0f,0x000e9bc3b8c38d73,0x00012b66f5b589fd,0x000e00ce95dd980f,0x00005bd1a09fe338}}, {{0x0003ae55e915918c,0x0008c6f8a46b6516,0x000ebf99c6158d6d,0x0007eec466b538ee,0x0000a8761f77ca47}, {0x00049c29ebbc601e,0x000100c3ae2faf34,0x000e63752ef3b0f4,0x000a50ca6c577d5d,0x0000916660244682}}, {{0x00097befc15aa1ee,0x0007d54b07455a30,0x0009a5f1240d1254,0x000ee57bad470651,0x0000d03f7188439d}, {0x000bb6c4a02c4997,0x000d5ffe71d20794,0x0003adcaff725083,0x00030fbcad75190f,0x0000f68ea1cb3729}}, {{0x000c8c7b7ffd977f,0x000490761a22e747,0x0003ffb83ec104c3,0x000db69395ebaf5a,0x0000b3261f5d4b63}, {0x0004960d883e5448,0x00000cc2eeb85354,0x000d65f9913520d7,0x00095a88f6337bd3,0x00003997db2f81cf}}, {{0x000f1060dbd2c016,0x000abf9ce934ce6f,0x0009939214f8eea6,0x000fc6f46f7c4b0e,0x0000236a324be753}, {0x0001f84a16022e9a,0x0007a3d1dbb265a4,0x0004cef9c0c18d87,0x000c73d3c556402d,0x0000042810910444}}, {{0x000f15e9afdfb3cb,0x0002abdfb6df68e4,0x000823d9749a5614,0x000c29f9bc1bd45f,0x0000ceb59719a111}, {0x000455fb269bbc4a,0x000e49bc5d62366b,0x00018b0867cd85e1,0x000fb92743c41c4f,0x00004b4099135294}}, {{0x000581d26ee83821,0x0005259d638e9c7c,0x00028ae3dcf17dcc,0x000047de8273abb7,0x0000d1129270821f}, {0x000847750491a746,0x00019de0dfb91149,0x000a435ab687fa76,0x000e3ecc2580227e,0x0000b8bdb94f1ce7}}, {{0x0005dc93bf834aa0,0x00094f6c7e4b4c5b,0x00036bcad0437181,0x000f8dc284e00a37,0x0000d88111821ae8}, {0x0000f82f48c8e33c,0x0004e1bf40dbf9cf,0x0002733e5a11fd07,0x000bd71ceab0dedc,0x0000560a8b64e986}}, {{0x0001fe23929d0979,0x000002f188f148dd,0x0006fcdac3885b29,0x00046b7f2ae613da,0x0000054303f4662a}, {0x0001e440738042ae,0x0006ddaf6449b687,0x000c9df1b98e6a97,0x0008f8f8bc0650d1,0x0000f3d645216e09}}, {{0x000ae82b6d72d285,0x0001a5d8408003fb,0x0008efc1c77ca9db,0x000b4a3a112cffa5,0x000018d761d1564c}, {0x000740ef0d1b5ce8,0x000c69eb178569b5,0x000f53382717039c,0x00095bbfe29f9022,0x0000e54ba56ebc7c}}, {{0x0006d8af7f91d0f2,0x0001882a57289c80,0x000d767543b61b0f,0x0004c62640032d94,0x000073eb5de67d83}, {0x000abf77b4e4d538,0x000f5e4017772988,0x0005071b3b7ce66b,0x000a981fba6b3271,0x00002413c252d3a1}}, {{0x000c8c4e0e8ad934,0x000e1fab868d5b7f,0x0003946f3b5679ae,0x00050a71f9d2fa2b,0x000058897dc9685b}, {0x000c93089d0caf3f,0x000e88642e921e98,0x000bdaf1839564c5,0x0002e52b77729a0d,0x00009170723479e8}}, {{0x0000317e4515fa57,0x00048b0c790f680c,0x0002e0765f85cff8,0x000b3257a82aab6d,0x0000446bca9a5c82}, {0x00007aa6d63184f9,0x0007962803a65de6,0x000be80357c1a46a,0x0001f84218313dae,0x00002113ffe573c5}}, {{0x000e08312e7e46ca,0x0009b6126bd54b38,0x000c07e0469d0a37,0x0002675b3f324b73,0x00000c22f682fda7}, {0x00000514d2c7d8fb,0x00031be2cae58f2c,0x000f0f277bc45ced,0x000a9831c6cf07a8,0x0000c392312ceb99}}, {{0x0007b7e3cc8ac855,0x00078d02753b7553,0x00037df2f8d725f5,0x00031dad05ff64b7,0x00005fe871346d25}, {0x00004a96ab6b01c8,0x0008fcd9372457ce,0x00086699b69a02a8,0x000231cf82ac35cf,0x0000242d3ae1cb4b}}, {{0x0000f65d62105e5f,0x00093d29be61713d,0x000fbef09bb222bf,0x00082f02f9a79e6c,0x0000c24d8d4c5d67}, {0x0007085d41299673,0x000cac3c2a435db7,0x000d8d9a3db81c3c,0x0000266d655fc005,0x0000f5d057a84298}}, {{0x000f56d88c546946,0x00053b09573e1157,0x000adffd1b26baba,0x000382ccab03b022,0x00000a412c93d69f}, {0x000e98b54b25039c,0x0002a87e714ded76,0x00000b594d4ee67d,0x00009ac77396487b,0x0000e41977689ef7}}, {{0x0006f851c203a40e,0x00060afd8f9140f7,0x000578dd230d352d,0x000f3ccf196d3d95,0x0000a4bb3d857cc3}, {0x000bd03b98e782b8,0x000f8624920d42a5,0x00056fcc8ac958c3,0x000e5e3838134cfc,0x00006ec4cd009572}}, {{0x00035269be47be0e,0x0007eb28fea169c4,0x0006c67e5323b7dd,0x000e461a5538ba3a,0x0000f921d70fd378}, {0x00061fc3c4b880ea,0x000df8940a67f929,0x000f0ff393f6f914,0x000f9c0990eb0afe,0x00006c2921090eef}}, {{0x000416651b8d9a36,0x0008affb0db1ca80,0x00082e7ce42531bc,0x00074112ce4718aa,0x0000e1999143f574}, {0x000b13dd5d369463,0x0005c68f0194d5f1,0x00010d2308255dc6,0x000988ac9df4cd87,0x0000453c20f438c1}}, {{0x0008dc089a6ef014,0x00005857df859af9,0x0001ad9244dbcc3f,0x000045f48056015c,0x00000448da610493}, {0x000926d4ee343e2f,0x000ca0e8a301f629,0x000815b3f6343f1b,0x0006faffc9349140,0x0000882a424ce8f6}}, {{0x000d5f4e7db9f57e,0x00095c384c273a12,0x000c660b17dfba38,0x00021b9a904bfd6f,0x0000b6c5db40773b}, {0x000ee661cdfe0491,0x000e34540f29c350,0x000ec6aad9baac0c,0x000baaac57b6aba5,0x000067ce8c31a7c1}}, {{0x00003a553fb2b560,0x00074e057f78b23a,0x000e490d96ce141e,0x000e75796525c389,0x0000bc95725a31a7}, {0x00067911220fd06a,0x000ba08b0bd61ec5,0x000ebeba9716e3a3,0x00066f91cd6bf7e8,0x00007326ca75ee6b}}, {{0x000851ccd090c436,0x0003912c39883d9f,0x0004b7be4561e8f1,0x00037af0490b6a90,0x00001690ce164107}, {0x0009a370f009052d,0x00002026092e299e,0x000fcdc0f258758f,0x000cd1cfa255f3fd,0x0000bc9fb2090e1b}}, {{0x000dd6e246518404,0x000465c59abc35f9,0x000ca4938dca45a8,0x000f28d03d396fec,0x0000532da0af97b3}, {0x0005ea51999a6bf9,0x0009ce6bf2eec413,0x0005be0933aa9505,0x00052e677cef063f,0x00007d1a0f939431}}, {{0x000ebba2e1c21dd4,0x000bec6797c42cb0,0x00000101ff41b29f,0x000a8986e17321b3,0x0000422b0ea10d79}, {0x000901c92f1bfc4c,0x000f21e10ed949e4,0x0002926b806ab1f8,0x000ec1c4d35577db,0x0000a349d39f56e8}}, {{0x0003d32343bf1a9e,0x000757d1a6b170b6,0x0006865b48fd3bd2,0x000fa12454879c31,0x0000e959ff7a458e}, {0x000dcf89706dc3f5,0x0001c64e4b2e0461,0x0008843c8737db0e,0x0006f5b92626802f,0x00004498bbcc745e}}, {{0x00073faa29e24afb,0x0003c0aa87a13594,0x000573acefcc3c45,0x0009654d2c4bf500,0x000065b514ed8dd1}, {0x000e7cf2193e3934,0x0001b5444d97e46a,0x000ff38ed60e9a4e,0x000f02a7594e9600,0x00003d84d2f4a0e0}}, {{0x000b141ee398a212,0x000ec3bcc5be8b6d,0x0003460eab88a56a,0x00019aea1aa52f37,0x00000da1a56360bb}, {0x000999d65bf0384d,0x00038d5a180efb54,0x000737b0471a14d2,0x000e91ec44db7b21,0x000084fcb18d1dd8}}, {{0x000937bfa44b4794,0x00091c98fd4f80de,0x000f087275350549,0x000f52dedb12ab28,0x0000c58b582e5f3e}, {0x00036d88327f246f,0x00095d7df320bfb2,0x0006024f2c3a3bfa,0x000432fcd96c59b9,0x0000c293a546f4e0}}, {{0x000352b5acf6e10e,0x000ccfe652c35341,0x000577a7fc50343f,0x00023c6af3792d18,0x00001a4c6188f168}, {0x000d0cd33425d0a3,0x000d6b7bc47f9b26,0x0006bb20b306399e,0x000054fa792f3370,0x00001219614c8111}}, {{0x000c06487f5d28b0,0x0001962277fd864e,0x0006aed5f11392d9,0x0009d9b5aa7942bb,0x000080094dc47e79}, {0x000588c208ba19bd,0x000eb512f2844afa,0x000f5799ad3e7570,0x000491fbae64e602,0x0000eebe7f0214b9}}, {{0x0000f98e5c298ff6,0x000dd678361f3030,0x000cb9a1617f561b,0x000490952ff31298,0x0000233c3bcb562d}, {0x00015a192e3a2cb7,0x0001763651197bfa,0x0008c53b1961bcfd,0x0004b9cbdd29bf2c,0x000039704dff2284}}, {{0x000fb587e7b754b2,0x00018806c9b97dac,0x0005044522336079,0x000783c7eb88c923,0x0000983e996a52c1}, {0x000e529958d881dd,0x0002562c7b3cdd4a,0x0000b52d1026bae0,0x000cfa6a6f919396,0x00000980f9162696}}, {{0x000428cd5f30851d,0x00065a4f66304c1f,0x0005d48a494dfed2,0x0000cd7df53772fc,0x0000d2d5a3063326}, {0x00015bdd44cc7a57,0x000d4d12533a5741,0x0003057c94ba6b20,0x00020dc0e93cb824,0x000094c486a84de3}}, {{0x000d4cef21496e4d,0x00081c696331e925,0x0008d812ff951d19,0x0004aac810e2de3e,0x00000a4725a08929}, {0x000a2b50e3bab661,0x00059bad306f513b,0x00004c49e462caff,0x000b0bd2dc6d59af,0x0000aeb8750f0b84}}, {{0x000f12f2f7d0ca2a,0x0008406acf2fc034,0x000facc2f6d2e812,0x000606e01f4f8321,0x00001170c04940ef}, {0x0001d4f7805a99ca,0x00062c26aba5fe0a,0x000531f40bde56a3,0x000107bb1629d035,0x0000c212c2c3afa6}}, {{0x0006bf315697be5d,0x000b5c63c7c130a0,0x000cdadaf6f0545d,0x0005ba8d8cb8427c,0x000052e379c7c701}, {0x0006147f462c23e6,0x0007e6bc24b0c4f5,0x000856d4fd44a429,0x000cdf5c73d23ae2,0x00001cedd8c6832b}}, {{0x000355699f241d77,0x0006901a349d6095,0x00089e491ee4adbd,0x0005459b35bf6aaa,0x0000f0076f4836f7}, {0x00018ba9264da3d1,0x000d52a7a28bd19a,0x00061c9716eb2d2c,0x000a5dbdba941f87,0x0000550518bb3be4}}, {{0x000e2f057d0b70c4,0x000e8d133ba3d0e8,0x000416aeceea8612,0x000061414670f044,0x000024db6c370775}, {0x00039d116213fd1b,0x000468a3478fd960,0x0000c5021c61e7fa,0x0006dcf805bdcccb,0x0000dd6f3a8bcc61}}, {{0x00096675d97f7e2b,0x0000ff0bf4b60600,0x00091627a31db0fc,0x000fb073680ed454,0x000099a3c672d741}, {0x0005f5536b1ff923,0x0007212b388de9bb,0x000fcf2632973857,0x000b47ab8a2ce750,0x000085346d49c4f7}}, {{0x000c5ef31631f9e0,0x000103a57a29be86,0x00023f821bf91da2,0x000354c3b1f7967b,0x0000f7d00d2770db}, {0x0006c3bd8fe79da6,0x00007525c9968ffc,0x000ff632acc5e8c4,0x000527e640991dcf,0x00004d97e8cc7112}}, {{0x000d97302f1cd1e1,0x000b0dd212a4c232,0x0009802f7ce87eac,0x000dbd5e4c8c73e6,0x00002ef02902fffd}, {0x000c74e1bcea6e23,0x00040cb92cbb941e,0x0008f9d05d0b5402,0x000aae509fb9d47e,0x0000bf1615a22992}}, {{0x000f279f8a7a838e,0x000025615660ad40,0x0001f6fa111aea63,0x000ec8df52e6f1a0,0x0000f0469961dc2a}, {0x000bec9d8080711c,0x0009dfdedf76785d,0x00021c126e1aec60,0x0007322ce797b5fa,0x000066e898fc5e52}}, {{0x00069c408811fdbf,0x00073fc7f08239bb,0x0004f41388bfe1ef,0x000f97d8e7a39317,0x0000ba8ad1ec58d1}, {0x000d0cebfd2fd5bb,0x0001bee60d61bc21,0x000d222530b839a8,0x0006b2facf7658af,0x0000526bed95ae39}}, {{0x000bbc2385644641,0x00077c45bc73ccc1,0x000188a789e3ff94,0x0008f7bde9bca358,0x000038b8ee0e73bf}, {0x000234c4123c4899,0x00086a6432975c7e,0x000a15fa366e6936,0x0009267629eeee39,0x00005fab88239e2a}}, {{0x0007007eafbb1e1a,0x0006475b7a93b249,0x000b68d78d75c9ce,0x0003959558352def,0x00002f26699c23f6}, {0x0001ecfe469b17ae,0x0009072d3ec2eb91,0x000cb113f6254577,0x00098caea47de782,0x0000be4b0872e1fa}}, {{0x0005ed78cdfedb1f,0x00070e211a74ec2d,0x000d244c5a535c07,0x000a75a678109b11,0x000017c8bfcae299}, {0x000412efb11fbc42,0x000274ab3f65b651,0x000f78243ea0b548,0x0001d4b8dffd950c,0x0000e719e57ee036}}, {{0x000f085304ddc5b8,0x000ccdaba2ea9007,0x0009d28a9095e8c6,0x000002da33cdb43f,0x00005b95cd962283}, {0x000c819b97447336,0x00089c7f5783bcd6,0x0009038e429c5f53,0x0000180c49b2fad5,0x00008349cc19bbe1}}, {{0x0000c1d21830ee5a,0x000e49bfa297cc49,0x000de1a9436f9c4e,0x000cdbb8fd729448,0x0000adb13a8ee8f2}, {0x000aaa081313dbae,0x0007e2152dd8515e,0x00053dbf8c76bb46,0x000142557f8d75a6,0x00004d8c4d2914ac}}, {{0x000e675b055cb405,0x000b477b5167bdb8,0x0002fb863898f8e7,0x00001f9cc65651b8,0x00006544814bd88f}, {0x0008e95263a75a91,0x000f0a22fcdab092,0x0003bd37ccfb6836,0x000664551d14db3f,0x0000d3837fbc6ad4}}, {{0x000b538ff4f94ab1,0x00025d7fb8f27c5f,0x0005c52877243c71,0x000d1bdf13d60ca8,0x00008cfb7c75bb8d}, {0x000bfe6729082196,0x000b3d5144ab82f9,0x000f4b42f35c4592,0x000dc3f2734f379c,0x0000bac55e7ec60d}}, {{0x000811e94dea0f66,0x0004818cc1a3b5cd,0x000e660f8259ecae,0x000ff20a0e836e15,0x0000c639ea66e02b}, {0x000b8cb7e1026fd1,0x000b532619428721,0x000f01da39e73b50,0x00057fa8c7097477,0x0000839e6a69268f}}, {{0x00094155150b8057,0x000e892c7097571b,0x000084b951892389,0x00095c1d69c18e4a,0x0000014c5132e5b4}, {0x000db361b07523ca,0x000d8c1c64fa4780,0x0002c105a2f6219c,0x000360238b81b060,0x0000b4f4f20fdc8e}}, {{0x000c982cf7d62d27,0x000cb3ba815020d3,0x000763f9e1f36e29,0x000006d8ae0bf092,0x0000a527e6b8d3a7}, {0x0009097581a85e38,0x000f5c158be5b4a8,0x0007d726e1f1a520,0x000862798db37d16,0x0000802786e9113e}}, }, {/* digit=15 [{1,2,3,..,}]*([2^105]*G) */ {{0x000149e36f09ab05,0x0009fa10bb5befb2,0x000e2099803f163c,0x000bab8029704506,0x00006f0af006b5a3}, {0x000cfec70880e0de,0x000ede3d913f7af4,0x000ceb4bd7332a66,0x000f5452e6c84a7e,0x0000dc4a79b7c228}}, {{0x0007dd0c55c44969,0x000695bbabd2c37c,0x000d7f363a6a9635,0x0001decb7e63f2ad,0x0000dce3782be73f}, {0x000a16ab2b91f71a,0x0002bba0163ce1e5,0x000e515ade448982,0x000ecf52759c32f6,0x00005e2f1f92615e}}, {{0x0009be7abded5516,0x000868b744107451,0x00010d9a903d358b,0x0002b6ed00b10b0e,0x0000392b0b188da5}, {0x000a2980b75c904f,0x000db8f7f96c6744,0x0002cf932c305b0a,0x0006c9142e421d18,0x00006fc5d518e463}}, {{0x00047c9d64cc78c4,0x000b5b6cb27b7958,0x0008022ab6c50621,0x000a1cc7099bf8df,0x00008f862ec004ed}, {0x00032ede1603c166,0x000efc9a9450d127,0x00029b4fc19a80e0,0x00051582257f54b4,0x00006d3b2c6a5460}}, {{0x000f87e822e37bef,0x0003353bda4e6ca4,0x000190aeb73f237b,0x0002840747f3a241,0x000006fa370704cf}, {0x000bb6efc621c127,0x0003d0b80ec60a6b,0x000a556f35d624b6,0x0000a7db0724257b,0x0000fa0c354ae2d2}}, {{0x000fa31e3229d41f,0x0001a4531bd4e921,0x000d38209a929c65,0x0007bc94156027a6,0x00003d69f745bdb9}, {0x000d19a168336319,0x000d73d51be38906,0x000511cd868a34c2,0x0002a83b59583b0e,0x00009ce6bfe8dc13}}, {{0x000daaaffcdb4631,0x000a24a38b083fac,0x000a9078d658bbc1,0x0005de02a801f8f1,0x0000567bcf97ab85}, {0x00098e03572359bb,0x0004d659e68be084,0x00023807ccf0353e,0x0008a20b86e9c87d,0x0000c08728dd198e}}, {{0x000b7bc453cadd69,0x00072c0bc1f88de2,0x000abd3af203900a,0x000ffb2cd86e47a6,0x000011cac131502e}, {0x0000242ec965469f,0x000139e0017e2d55,0x0009798850e9f769,0x0001ee733f078f65,0x0000b87d44a3cf75}}, {{0x0000e4bfc25419a6,0x0002ebff3cfde179,0x000b6e83f3646720,0x000fd268db638625,0x0000cc69f23ccad6}, {0x000e45a6bc68bb94,0x0005e97f73340219,0x0005dc97ce43d79b,0x00049a3d44536846,0x0000b9eea326a0b9}}, {{0x000c6ba6102d0212,0x00080f4461ea1b96,0x0009f19a8eaafac7,0x000875b4b85c41c4,0x000075c28e4ef538}, {0x0001a9ddd2e54e03,0x0004d605618b3545,0x00036cd246991adb,0x0002162b8b4bcd7b,0x000072a4f8c86f37}}, {{0x000bd73a6a5da60f,0x000fec4c9ff0c890,0x000536e576f083d9,0x00024304e14d94f0,0x00009ee1edb9aec8}, {0x00041ec8bdcf8e7c,0x00004b041e265712,0x000fff040a5db827,0x000201da0b9a99e3,0x0000aaf21de3c271}}, {{0x000b2e14f0dd2e8f,0x000e1a377ac7b4e2,0x0007a2198e77e7c4,0x000eb779202c3f0d,0x0000759b80018200}, {0x00026eddcfe314e5,0x000403d5cf99c875,0x0005138b6eb84c52,0x0003f461b52ace51,0x0000aa7ff8c73fca}}, {{0x00013c3b9791a263,0x000a9dd58b16ff0b,0x000aad2de960022d,0x000619abd55c9257,0x0000baaaaa4230fe}, {0x00023460d881efdb,0x000f96325e2a9a4b,0x0005c18d4506416b,0x0007afe1381e7603,0x00003bb68bfa2781}}, {{0x000b8bf5116f9379,0x00063126894315bf,0x00019a2c87c64a58,0x000462e1e25cc384,0x0000fd6b0c51335f}, {0x000ba3ce8ee0e0e2,0x0000098c21fa4bf0,0x00066bee06f6fba6,0x00054437d57b39ae,0x000092d513042672}}, {{0x000105dbab093b30,0x000902839986f451,0x00074a89c012f59b,0x000e978a91580234,0x000048c919c2de03}, {0x000a2b591071cd58,0x0009834970a5c476,0x000b7994b791ed89,0x000ffd09bd9042e1,0x0000eaf517a21057}}, {{0x000e2a2d551ee106,0x0008127e09a66066,0x00001148d87a8f1d,0x0003fda0d08bab2c,0x0000da8e4f1a24f3}, {0x00017f0cf9a4e718,0x000fbbf5cb19466d,0x00062ecc0ff50200,0x000ac45ccf97d8d0,0x00000c0d9b001d80}}, {{0x00071d8033f28764,0x00063d5cc3dbe877,0x000c9bc1db0186ec,0x00060e18e8bb803b,0x0000d1395ccaf6ef}, {0x00062d6186244a03,0x0002e10a5b53a73c,0x0001b7eab918e5f2,0x000e51bd4878ca74,0x0000038d71b0be03}}, {{0x00004b7a93c32461,0x000990b9b4cd8402,0x000d6421821ab606,0x000191e5fa6e2bb1,0x0000de6ad0f03d56}, {0x000aa88ff1929c78,0x000ae40e87b5570a,0x0005f0cccc6df4c6,0x000c015e8a74f2c6,0x0000b972fd666f6c}}, {{0x00036b60b846531f,0x000520a5e4753fff,0x00045b6c5ba7e45e,0x000d9c94a1d10e41,0x00001f7f91b4e046}, {0x000a69244de90d77,0x000a8199c15e0317,0x000d73deb951a1d4,0x00024f21f78046c9,0x00004c828296ab82}}, {{0x00078fce7560b907,0x000137e824ceaa67,0x00042eba8b4073e6,0x000f388f0d693cd6,0x0000ce2e57acdcce}, {0x000c7891df1ad467,0x0001998346fd89c2,0x0002fc17783a0692,0x000f1cbd715d72da,0x0000b6dd71df5b6c}}, {{0x0006d0a73fa9cb0d,0x000d628bf5a9c60a,0x0002c8c82edd3992,0x000f4ff380ddd083,0x0000182d41172a0b}, {0x0007438d9a528dba,0x00092af539947d9d,0x00019987ce8b1a0e,0x00059d3dd6e5fe0e,0x0000cb8df03b90b0}}, {{0x0003a328300129f8,0x0001e8c43bfd5370,0x000e540511f63766,0x0008c53cbd191300,0x000012fcc62fbf5a}, {0x0009d5f29fb85da6,0x000a094759e83f96,0x0000726b772f4e00,0x000208e26b6e5279,0x000017bbc879bdbb}}, {{0x0008bb997aee3170,0x0006e81536a8511f,0x000c09b9b812a409,0x000a7a137dfe593a,0x0000682238fba8c9}, {0x000ead6aeccb4bdf,0x0009792ba6337072,0x000ff9d336a34e9a,0x000b61d82eaec26f,0x0000b7535130d4d2}}, {{0x00045ff1d7aadabe,0x000ff5f6a67c1a04,0x000cfb26f65d3825,0x0001d58e62fb0891,0x0000f1e0fa63c7d9}, {0x000c7ba33db72cdc,0x00093a7c74b247e7,0x0000a503c017cbc0,0x000a417c931590f5,0x0000ac54f61216ba}}, {{0x000d380b2369f0f0,0x000d23c761519b6c,0x00062a9c697d3a70,0x000f515f9dd6fc98,0x000044c4ab212312}, {0x000a0fd834a2ddc6,0x00026c7b826d035e,0x000fce49049e6b86,0x0006e9503d688362,0x00002f2497b137e3}}, {{0x00005b6c64582934,0x0006a8d10af704b0,0x000e617b836bb527,0x0003d46cf2dc138e,0x000070d2d35f004b}, {0x0000832feeb1b77f,0x000895657f9c0679,0x000f600042bb75c3,0x00018ae70bd4edc0,0x0000e797ecd119b0}}, {{0x000ec2a753aebcc9,0x000c3939eca59b5b,0x00095ad09daf9f3d,0x0002fc46bc6833d0,0x00008abdd526aa4d}, {0x0000a318d168be52,0x00000325a23cd984,0x0006ecfafcf7c10e,0x000f1885c02aa07e,0x0000462e7e6d5bfd}}, {{0x0008a8ba0cc3f125,0x000d6c672a29ab2d,0x0006f2cd368dd485,0x000d8d2203975259,0x0000d3eea67f0cf3}, {0x0001a81e6602671c,0x000f54026c0c810a,0x000b50f858f144a3,0x0004a3fc753a6d76,0x00004dc21e9245cd}}, {{0x0002dea521d03782,0x000de5011c6fc526,0x0004c19ea802b8e0,0x000aebfba19cbb0b,0x00001db64b60bf0a}, {0x0004ee970342f9d6,0x000dbbc44a141f39,0x000fd0baa93a10ae,0x000e6547eed31b3e,0x0000e7c824e7d154}}, {{0x000fa819966e7eef,0x000715b7920dee23,0x00090aad464ec4aa,0x000ad43d44462d2d,0x000044dd196cf277}, {0x00071f1bb46b6a1a,0x00035d8850908d64,0x000a977b41e65d31,0x0001ee93a800f513,0x0000ca9d721a797e}}, {{0x00085a0fcff6a17e,0x00023eca7cee9a5a,0x000504be39970a3f,0x000ee1db9f0d6bc9,0x00000c504bf8dd24}, {0x000d95677fcc2f46,0x000705bb5fc47e09,0x0009286aaef1a522,0x00028ab45d4fb18b,0x00006fd0c5dc6490}}, {{0x0007ceb1bf4581ca,0x00060ca7b1669885,0x0009722ace635e18,0x000006878ddd2265,0x00000903c4cbdb68}, {0x000458948f214029,0x0004296abda2366e,0x00040319031b49c1,0x0003fda29c4b09e0,0x00007197ca4629f4}}, {{0x000dd1e274983d81,0x000e45717c8f8073,0x00061f9d1da1a3bd,0x0001ceed3d4da203,0x0000332d0815c7de}, {0x000f7a3aa6d0e10a,0x0003554f1c4a9b7e,0x000d3556717db2e7,0x000e710f3dffae4c,0x0000aa2f407856f4}}, {{0x000759e7ace3fc7a,0x000ea5a8d8c68966,0x000834e0e9594eac,0x000420ede3bd8b91,0x0000fe4ca53f48c0}, {0x000e856e6ee81c69,0x000adb891a3afdd7,0x000e638298f671be,0x000c9f67a58f2bfa,0x0000ab186fc2c11a}}, {{0x000b36910b5be761,0x0009eb040bcd8d6e,0x00073de88046b773,0x000e03bcb4529fcb,0x0000df0fefcdf26b}, {0x00057a6bcfcd0279,0x00052b3165caad77,0x00099a4d9a8786c7,0x00004b59db1e347e,0x00009ee86e0406c5}}, {{0x0002dddc15c9f0ab,0x00039295989e5b7c,0x000d08fdadf87a73,0x000701a9ece47c03,0x0000074d3de5d5fc}, {0x000790351a03776e,0x000a4a6080072040,0x0001531852bb1f77,0x00044645c58f4fe1,0x00006df62f7566e6}}, {{0x000d1beed51275ad,0x00065f0f483fefb3,0x000c2bedf5de47dc,0x0008a0a932d98e97,0x00005c11927d219f}, {0x0001200a73a294ea,0x0009fdc201729d75,0x0006f506a5f88434,0x000d48328d9fd3a2,0x0000890cd323d1dc}}, {{0x000aec170f4d3b44,0x0008cffc8d000aeb,0x000d57838fd1a136,0x00036179d9c24057,0x00005929d26a8bac}, {0x000d06025b15ca6a,0x0000ce4744465a2c,0x0001e51344b3c83e,0x000f407aac7578ee,0x0000418f5d7691e2}}, {{0x000fc8a213ed68b6,0x000cf10a52246936,0x000f09b53860ae7e,0x00098d03660335de,0x000041b28982d79c}, {0x00038e101110f35d,0x0001948b193729bd,0x0009164f479c26f4,0x00027294dae5199d,0x000085a2310d265c}}, {{0x000dd5d4b07e2b19,0x000afd9ea2217173,0x00005ab14d144c4c,0x0008f158b04ea411,0x00002dda5438e80d}, {0x0002fa8cf03dce66,0x0004ba22cffce998,0x000ad88c48b5ea96,0x00095c97f4ea7f3f,0x00002db773eca5ba}}, {{0x00002fb93f245674,0x0009f15257cad20f,0x000cab987fd46c69,0x0002f4cac74cc78b,0x00006f31c019ceca}, {0x000db59888b219e5,0x000791fccd0240ae,0x0001f816ce50ecc3,0x00000bcbcd9dad91,0x000083cc1ecddb9b}}, {{0x0002e66a483bf119,0x000521b2c169f3cd,0x000e9fa28fa08a6f,0x00011f6375e2454b,0x00009a7ffeceb6d0}, {0x000bddbc4ae62da7,0x000dc74aef5d6a3e,0x0004d05bc6cea00a,0x0002523b5fb98d9d,0x0000cba14244560f}}, {{0x000cc21208490def,0x0002ccfb287949b2,0x0006fb16f1ca66ec,0x000db28f1166b71b,0x0000ff63e0955fe5}, {0x0005abe8b2610bed,0x000f69de3df4b834,0x0001c32b4b732ed7,0x00027c3e24ed5021,0x000010d8a6a548ff}}, {{0x0004398ed4de248b,0x000d60488927c107,0x000673e13d7cedac,0x0000aef4aa6bf885,0x000046bae921daf3}, {0x0008472fcef7ad8e,0x0007f4b35e970708,0x000e299866115160,0x000c78dcfe8f26dd,0x0000b84c4c8b5a34}}, {{0x000c55c164e1214b,0x000cf147bb03c1ee,0x000a96835891be86,0x000e9eefab4d100b,0x0000f01e9b955c1a}, {0x000e139b186ebc0e,0x0005a5b91bca6b4d,0x000d93854d5c74c2,0x000fbb7086a99cc2,0x0000ed62a7c87a9d}}, {{0x000ed6f76b7618a3,0x0004d3b660628778,0x0005186dbbff750a,0x000d131cb7be22b6,0x000069dfbf0fc3a6}, {0x000b26c7191a321c,0x000880ed718ec7da,0x000cfd1839edac3f,0x000692fc142b36d0,0x00008af82f73c991}}, {{0x000e4d897ce0b2a0,0x000fc3a55cdfb3d1,0x000b81afee6d7c87,0x0009d835846b9568,0x000018d12afd3c23}, {0x000620801206e150,0x0003a3b882c62b2c,0x0000162d5e0e4245,0x00062a854470a3a5,0x000081574787017a}}, {{0x0003fb4820357c72,0x000e4f1458ad18bd,0x000b44aa1992039a,0x0002817a1df3c525,0x0000d7803580d3d5}, {0x0007e4dc77ad4d4a,0x000859df4fc458cf,0x00071205ed49a799,0x0004a9a465a8b51d,0x00000ee0ea704925}}, {{0x000eecfab7bd7712,0x000315c262b94b5e,0x0009d61e76c87307,0x0000d2bc5bd6483c,0x000033d6d5452146}, {0x0005626fc195bcc5,0x0007b4d78b63d20c,0x000ec8ef32544595,0x000781903fcb3d17,0x00004b690d196b8f}}, {{0x0002c8a212306466,0x0008a84f418c82fa,0x00030ba43f51aabb,0x000df79f4fbec11a,0x0000a5acf73d43c9}, {0x000b357d635b4d5d,0x000d1cd5c1da1da2,0x0001af0ddc3de68d,0x000f98d689080bd6,0x0000ea5938ba665b}}, {{0x000d71afe637294c,0x0005e5a81cd80231,0x0008e63b501968aa,0x0007e851252d5004,0x0000446bc532ca00}, {0x00050a696d6134bb,0x0004ee09a05cef8c,0x000a3291a9361fbf,0x000a21417f85a6dc,0x0000178d549af251}}, {{0x000374ba4df39156,0x000ecfd5d60887f6,0x000e35102566ce1b,0x0005e1e25cba4d7d,0x0000b745f8fb8c5d}, {0x0002af663122edfe,0x000c5b989a898840,0x000ba31563190f9e,0x0009a46ad3d387eb,0x0000f385adaa7c46}}, {{0x00081de3f642c293,0x0008610ffb88b082,0x00029254620be088,0x000262c353dd4ad5,0x0000f1627deb377a}, {0x000a013eefcd6385,0x000624cc77c3a5fa,0x00048f55e8f3bf62,0x000b9de2618f65a3,0x0000787c0dcefefe}}, {{0x0003aa2d9a23e449,0x0002be10690df167,0x000f9110888dfa99,0x0006488ced1b362b,0x0000193cecacaf48}, {0x000327d2d738fc52,0x0007775fee6cfb34,0x0004079a56697b03,0x0001ac0f485da0c0,0x0000cdf57354feaa}}, {{0x0004420bd55659e1,0x000b3376090c7694,0x0003b591a7973e32,0x0000ca76bb4fe116,0x00000441aedd196f}, {0x0001f4a045ad915b,0x0006f4afacb13b43,0x000fdbbd86c11b43,0x000acc80b0c7db71,0x000064293209da65}}, {{0x000e6e89c92b2350,0x000e6b3993a14baa,0x0003dd031a73bbd0,0x00081cd06d60ec69,0x00003cab91b71568}, {0x000862f1db3574b2,0x000544bb061ad615,0x000181e06485b018,0x00075707434988a0,0x0000cd61ad4e1c0c}}, {{0x000ed5a2ff9f403a,0x000ac22390293eff,0x00017b70d8dc98d8,0x0000148206021e1f,0x0000fbec0cb5f510}, {0x000716480130dfa7,0x00051a02dcf59fed,0x000b10fc0306dc2b,0x000f50d8f06620fe,0x00008d1e1d5ca57c}}, {{0x0008c5a192ef7106,0x000adb7431f9adef,0x000250c9e88afbd4,0x000c071e1f740764,0x0000e31318e158be}, {0x000c4b824f89b4e2,0x000828c36a2afd4f,0x00024baa765a5dd8,0x0006502f1eccfff0,0x00002a21cf2eba94}}, {{0x0009dee42a554f77,0x0004902ec4ba95d2,0x000adb73d828983a,0x0008391112a1f78b,0x00009ea8898127c1}, {0x000a5a7d065fd831,0x0001a262a0bc8969,0x0002b5127f49af79,0x000dbcecdea8b6af,0x00000e913e1664c2}}, {{0x0009d14bc21ef518,0x000acce572925123,0x000bbcc3be51c3ce,0x0001e5f95ff06847,0x00006b46e1f3d7e1}, {0x000ba2380041ef4b,0x0004b262342e0ea6,0x000d294d4d72fe50,0x0002c8dabc6dfd31,0x0000be017a2c278c}}, {{0x000fa09b389328ad,0x0002001771b5b1fc,0x000b045bf322fbc6,0x000d0034c0d06360,0x0000b652edce0e52}, {0x000932c03ec6627f,0x000cd1ee50e350ef,0x00037a90dde1b3b2,0x000a956ab7bdc5dc,0x0000ea6721421e33}}, {{0x000b5cb4f2999aa1,0x0006a8cbf0dd6482,0x0003405bb38476cc,0x0009ec83ebfacb17,0x00005cdafe7f5236}, {0x0005ba4d935b7db4,0x0003dc99a4cdd42d,0x000b5545b648b600,0x000faf385101bda3,0x0000bf2c38addd67}}, {{0x000dc634442449cd,0x000963ad4fb8b1aa,0x000686d82e0e9921,0x00066b8c552313aa,0x0000ee635fb165d8}, {0x000224a18ee6e8a7,0x00067d42e02fbc3c,0x00074cd08eed748a,0x000adf770f930ad4,0x000074ea6ed6ff24}}, {{0x000de1cf3480d4af,0x0006cc8acf1a03e2,0x000295a9cf0d8edc,0x00097d023e330368,0x0000add5f69b546a}, {0x00097ad96f8acb1a,0x0004c71bdae28955,0x000dd43f4bddd49d,0x00041976fcd52821,0x00005a4541306191}}, }, {/* digit=16 [{1,2,3,..,}]*([2^112]*G) */ {{0x000b6bfc360e25a8,0x0004875a1a788ce9,0x0001732f4e642519,0x00057a1dc756a848,0x00003c0440fd432b}, {0x000b3f1d720281f6,0x000e7135e051c670,0x000052be72205910,0x000a397ed14b0edb,0x000097b3d282568e}}, {{0x0009b9afb3ff9ed0,0x000b17f6515c2e59,0x0004da44928c2e0a,0x0004521cbee4fd47,0x000071279a44f364}, {0x000ff6601fbe8556,0x0007ffda51c497ab,0x000597c0b3ee394e,0x00034ab90385f667,0x0000e9fccc7027ee}}, {{0x000de9314092ebb4,0x000d028e240c0b89,0x000d2f064f17256b,0x000b148f89a7f393,0x0000f57841f21ed3}, {0x0004405e708d8553,0x0001d3f1c3d04ee1,0x000d7eed5856aae7,0x00027098e5424fbd,0x0000333e4efa3ab4}}, {{0x0007adedda492f81,0x000a682972053bc7,0x000931b4cc11a3ae,0x0004bb4e89a3e734,0x00007512e2eaf569}, {0x00049f3177bf8b6c,0x000948c7ff3e5dc3,0x00011145d232ea4b,0x0009c2dc4f9d16f5,0x0000cf109a3f3b37}}, {{0x0007a88a1f258972,0x000f81b5d4d8e75e,0x000f3ed5c7ac6961,0x000dfbc3e1077308,0x000008a54ec2a892}, {0x0006e1978660710a,0x0006837df2c8be82,0x000704da50cf70a9,0x0003fca18a7340ed,0x00003eeb9a9a8ca3}}, {{0x0006233169bca968,0x0003ada6aafb49d9,0x000c2fa9404d286d,0x000fb3409606eca0,0x0000869d0d5a3ff0}, {0x00037e5d0150d651,0x0003140c14c9a999,0x0008e2d49a92e250,0x000e2b556bf94510,0x000052a733ab2f59}}, {{0x0003d588434a920a,0x0002c22103c5b432,0x0008dbf9ac0af8e9,0x000df1c67518ef93,0x0000184307423a9c}, {0x00094aa5447ab801,0x0005b75a3d61350a,0x000411a9ee5e5a32,0x0000c564ba507f68,0x00000581fc1694f7}}, {{0x000857080eb24a90,0x000d488e0cfd60e2,0x00059cdb87bedfb4,0x0000a9721ebbd7c2,0x0000b0da855bc639}, {0x00004dbde314c709,0x000bdc32e8462b4d,0x00062fc9ecdbf1fb,0x000ab6a3833eabb1,0x0000939b48c40dd3}}, {{0x00098a7cb0c9c8cb,0x000fd1c4375c5aaa,0x000f1c90f75105f2,0x0007bf1eee50575e,0x000031e0660723a1}, {0x000d275d4b6d45a8,0x000ce2ec89965364,0x00091c65bd363f3a,0x000b4735d2123943,0x000045647666bb41}}, {{0x0008ecc37107c78e,0x000a770c2a6620d1,0x000d0d845acff3b6,0x000f9f42f975d99b,0x0000f0a0c479a178}, {0x000965176b6028e0,0x0004248612d41a41,0x00038af55c49ec67,0x000a365b6ac4f273,0x00006145e627bee5}}, {{0x0005d07e75746b54,0x000d840c78be33e9,0x0002ff8e21c1e1f6,0x0000ad567833ef22,0x0000bedcf6af4918}, {0x000e9c13d7a4c8a9,0x000bdddfe7606b37,0x0003a5bbc2748887,0x000e7467055123aa,0x000054ff2260bbb8}}, {{0x0008ab197c3dfb92,0x0000af168154c42b,0x000b5069255a549b,0x000bcb8d6748e7c1,0x0000775780f8fc5c}, {0x00080b8e1c9d7c80,0x00013fdbcd564eab,0x00069eace8c69dae,0x000b5a47e6b4fb99,0x000002f1085a705c}}, {{0x000ca446d3fea556,0x0006948105684e23,0x00062f27db4ae9c8,0x00028be7bfb91b2a,0x00000deb4ca39bac}, {0x000d8947de6c34cb,0x00089494587da892,0x0003f8a5b4ee6825,0x000384e14ee14e1a,0x0000b113eaad8700}}, {{0x00003b92115b4c9e,0x0007a908cad181ca,0x00018179a7c163d3,0x000080e912a118aa,0x000009ed751686e3}, {0x000e3fa26f516cac,0x0006ce732f91a676,0x0003da8b4753cacf,0x0008a991592aea83,0x0000626f4300cbea}}, {{0x000c899a7b56eaf9,0x000ba4ef7316ef9d,0x000818a8600c0e52,0x000e46cb1e4e24fe,0x0000d31e20e5538b}, {0x000932d3ed689748,0x0007fc4e87c422eb,0x000de9aefe44bbc0,0x000344c121086e0d,0x0000e6b9cff934f4}}, {{0x0002c1f711b0eb9e,0x0007980ab9549689,0x0000792dbb905f2c,0x000125cce26309a2,0x0000c8ac9b3e684e}, {0x000d8b6b40a24474,0x00015fe3fb24486a,0x0008e3b3f60121fc,0x0003941626fccf1a,0x0000e568622aad1f}}, {{0x000ae0d196aa5a1c,0x00065041b5fbda7a,0x000b318b7e0df8c7,0x0006e8851465d926,0x000029b6e563ab13}, {0x000b48b711484633,0x000334454a762c2a,0x00003abe4b5738de,0x00058e24ccf9a05a,0x000077c02963427d}}, {{0x000f0b92bb39c1fd,0x000c1608d8c573f5,0x000fbb80514373f2,0x000cfb0cbfd31400,0x0000f18fb2153afd}, {0x0007f4242b3523f1,0x000d77f650fb81a5,0x0000a7d7ce958532,0x0006be9a8dc8b68b,0x0000b75dfb725016}}, {{0x000f7c92d7d1413a,0x0004f834f59790e4,0x00008c3e867e2d6b,0x000ec0afd4f4f9a8,0x0000f8237e175281}, {0x0005fdc84687cee2,0x000185b26c0925ab,0x000ea7650c5ded6b,0x00017f6e4a5aecc8,0x00003b73e5c34cc4}}, {{0x00043183037bf522,0x000558c725d72bfb,0x000b3e5d7b61e6db,0x00088e6efd4060bb,0x0000e014701fbac4}, {0x000cf9a360aa449b,0x0004c9634d08ac75,0x000fb15efb70cfd0,0x00006bf591536dff,0x00002c37583807c1}}, {{0x0003fdcf50225f97,0x000c40e12b03b429,0x000a8bf64c52e175,0x0003c68649c3bad0,0x000045a8ff05b8ae}, {0x000e5a358321bc3f,0x00061bc4df4830d7,0x000ea5058b1732be,0x0007442f217993e9,0x00007a71cdf2e4fd}}, {{0x000533e894c5bbba,0x0008c9d8308286cc,0x00015c2446915c7d,0x000ce506aa2d0558,0x0000eeee592e9b22}, {0x0009d13781354864,0x000ed6b76f2f89e3,0x00036e8f53a275c1,0x0009f59b6bcc1be0,0x0000df69b219e470}}, {{0x000b2502d0f39aaa,0x000a75a85947a188,0x000e0f4fa622118b,0x0005388ebf520ffd,0x000040e9f29e860e}, {0x00051eb22b57f0fd,0x0008ae80644a7b6a,0x000f095fe849a33b,0x00000180e5d16f1c,0x0000754b54fbc55f}}, {{0x000bb22236f4a982,0x0008e66800bb5cfb,0x0009a77740b0c59e,0x0009482ac69a8f5a,0x0000b33f804f6bec}, {0x000929532e6c4662,0x000f2e599c73b372,0x0005c31cc68956d0,0x00084e847a249f15,0x00004d80f0e01ce2}}, {{0x0001dfb988baf015,0x000d8bb16647cd82,0x0004cb960e6331a7,0x000ca4ceb8ad3309,0x000093cca39191bb}, {0x000ac8d265674566,0x0009604b6490384a,0x000b6c8f640fa030,0x00055f37834cd6da,0x00008a7318d9f91e}}, {{0x000d04efc4d31579,0x00019bf3bdeaa00f,0x000a57172b56f8ab,0x000db2714f56484f,0x000048c5860d50ab}, {0x0005df00ebd4f086,0x000cae82938e342b,0x000df5dd03e5168c,0x0005161aedc1ceb0,0x0000bbbc6da45732}}, {{0x000d486605daaa67,0x00074b9a6c9ec7bf,0x00024fb8946fd72b,0x000fbc74847fb1a1,0x00005959cbe12d8f}, {0x0009f65c8a588eea,0x0006180b499d4257,0x0009a5df1368c92e,0x0006044a4ef6cd99,0x0000a73bb80336fe}}, {{0x000a70d6457d188b,0x000adb7a388bf347,0x000cd601386eda86,0x000fb207cdff060c,0x0000eb1b6c880053}, {0x000238799240a9f2,0x000f576189b20b02,0x00066193a1bbb384,0x000c7e6695e71e90,0x0000eb5009726ffa}}, {{0x000a9c04a7d2caa5,0x000155aaa2900654,0x000476e8f6f3fb3d,0x0005e4335db041ff,0x000040b8b0c14229}, {0x0003ac905e214f55,0x000a06a0b638a5c7,0x0009e680b9a74075,0x000af9de4b1090ce,0x00007a5b479bb8d9}}, {{0x00048e726bfe65cf,0x000b8290c3070dca,0x00069e72e097e391,0x0009ab783c462e66,0x0000505be1ef6255}, {0x0003ea1e3a3035a8,0x00061cd50da85fbe,0x0006407f26431ebf,0x0006b87d169d5c1f,0x0000d838a95e0fce}}, {{0x000fa7f650006f01,0x000340c0fbb22a2b,0x000f9ad96dfd7dad,0x0005f982452495cc,0x000083bf494e9563}, {0x000df434a7bd989d,0x000bd543109502d5,0x00043f53e505385c,0x0004a90d98e67dfd,0x000061e1a6d200c3}}, {{0x00046c64a8a3d626,0x000fc47743d25a4b,0x000f7e4338469c4c,0x000848cbb3a13d88,0x00002b23a1061be5}, {0x00096b4a63d1a4c4,0x000a3d183f3ee835,0x000afb01c454e7fe,0x000638243fce6117,0x0000e65e5e65c4c3}}, {{0x0005ea1ef74c45bd,0x0005de32850641d8,0x000da7da92cfbfa6,0x000fbac8b078f53a,0x0000985fe38bc752}, {0x00068fe5a0148b4a,0x00068d78136deece,0x000b729ce6f9a55c,0x000bc3832dccc4d2,0x000027e0dfe30aaf}}, {{0x000445212b4603ee,0x00008b706d149647,0x000a9d412a876c55,0x000c33ff145fcf69,0x00002ab75b80d479}, {0x0009a761a23ff976,0x0001fd359d1012df,0x000835f22c613899,0x0004d90e51c7aefa,0x00009a79cb220fcc}}, {{0x000350d594cc7e13,0x00030350ab79f57f,0x000ff594a3079ca6,0x00062af26fb6149a,0x00005afec029d59a}, {0x00046f406ed2c6ed,0x0004ad939a579bee,0x000d1797e58da173,0x0006c974c504028f,0x00008853e7d2ccea}}, {{0x000508da35fcd5fe,0x000b695ccaeb4065,0x000e1a9628965df8,0x000cc32f2da85012,0x0000e471b95a1cf1}, {0x0009bc80a08fb758,0x000501de3591cef1,0x000ef4f88704958f,0x000a5ea867f8b23a,0x0000d7493856a9f9}}, {{0x00055378c9049f43,0x00034b92d8b61b38,0x000e2bd6b5be948f,0x00054da96f725db6,0x00007a222bcc58c4}, {0x0001abb8809bf618,0x000b9346f18de7c6,0x0007c0d1c46f07fb,0x00007a7b567a7ae8,0x00004a461c8fef3d}}, {{0x000dce6d9278d982,0x00037dfc73e10a5a,0x0004321c324d9481,0x0007062f3528b605,0x0000e03fdde892ea}, {0x000061947b533c0b,0x000e7ca3c05510e6,0x000b62b8f1a8bc73,0x0004e2fe58d4b21b,0x00002045a74084a2}}, {{0x000d5afbd76e195d,0x000c9938a8103ab3,0x000e3d5cb478dd1a,0x0001e39ffab3936e,0x0000fb693dbf2b36}, {0x000449651dbf1a78,0x000e88a2e762f969,0x0009bba9acab4b4e,0x000d9668c92f25d3,0x000050e61bd71464}}, {{0x00030e3dc09508b4,0x000f34317655b7e8,0x000690355faf6d2c,0x000ed632606cebdf,0x00008bb92b410c3d}, {0x00054845c7cf8929,0x000945d5f01f65b7,0x000401d69f6cd7ac,0x00087832c30a5996,0x000012686517d921}}, {{0x000f913b78c558ff,0x000ad8afdaa9380b,0x000f169d343c0bae,0x00020a477f61d554,0x00008da07e49e5ff}, {0x000c49da8a90ea83,0x000b53a29b21b676,0x000d8d27681c1ff2,0x000982083297ac2a,0x0000001122fea89f}}, {{0x00094be6718e4488,0x0001fc3e6e13e1d7,0x00026b5ef246c148,0x000cdcd6646ef85d,0x00000f5091f08069}, {0x0002e2f724bdd38b,0x0003d471e8c7c599,0x0000ff2a902e915b,0x00019fe6ff320a0d,0x0000f886487f384d}}, {{0x000e6a6c93f72d63,0x00029ad800eabbe1,0x000acf117d5f75d1,0x000355ca40a09fe7,0x00002c8cdd5a581a}, {0x00019927023c4994,0x0006f8ec39017422,0x0000e83f0a8afe5d,0x000eac1691afcba9,0x00001bcaa034b8f8}}, {{0x0005ff98d2668d5c,0x0009bad81965e38b,0x000c6ce110715281,0x0004355bc8fc7c03,0x0000bbee6e34b650}, {0x0000fe80cdb9808a,0x00065e3ed31506b0,0x0000b501817d6e06,0x000aee8e9d38c64d,0x0000b8bfd57244dc}}, {{0x0004a59513aed8bf,0x000c414bd07a4289,0x00042b582f77f3b6,0x000fe5cbdecb8f8e,0x000010e2fa9c2390}, {0x000502262a2f201c,0x000f90ee32b0efb9,0x000a789a84d59ea4,0x0002c4187f77286d,0x0000f98a2d0b7949}}, {{0x0007239720943c28,0x0004b990b9d0f957,0x000f2884aba044cf,0x0000aedaa8e82395,0x000034de6ed8278a}, {0x000ee9a5f25bd125,0x000a1f7ab271c8e1,0x000d00b769259cea,0x00032a2e6d97a277,0x0000c0c6eeaf4378}}, {{0x000c20f5606b81d7,0x00049d991ee55232,0x00032d951abd7b37,0x000363dd2bfe3586,0x00008f8514708ed9}, {0x00073f0f30c3282a,0x00000789230b9518,0x00098967f0da8ac8,0x000fb49ac7789c53,0x000069b8f805dda0}}, {{0x00077176add85450,0x000672c49b66e5db,0x000421d771b71cb6,0x000fead856073968,0x00003840fe883e3a}, {0x000dad51ec699775,0x0008e07f6726b391,0x000ca160cae243fb,0x0005f4788ac87be8,0x0000174cced9ce35}}, {{0x0005966e58ba37d6,0x00021817335d98a3,0x000fbc7bffdcc8da,0x000983fb75283083,0x00008e419d539c96}, {0x00039f402a403801,0x000f0fe977bc409a,0x0008edea688940fa,0x00047db640a94b8f,0x0000e22cd17fd115}}, {{0x00068ce59ffc3e20,0x0005c1dee4e7e285,0x0007cb36360aa1b5,0x000bf2c67497c883,0x00006fb438a105a2}, {0x0007ec4500d8e20f,0x000c1670db103035,0x0003b7cfd1ad9095,0x000d278f589a05c7,0x0000544607e780d6}}, {{0x00093b1a20ef103d,0x000f9ba6577b17ba,0x000a214a0ad85912,0x000da495c91cf66f,0x00007d49c6cf7990}, {0x000ec8d20bb569d7,0x00027effbc33ecd9,0x000ed0467bd4b250,0x00028bb056ca5a6b,0x0000916a1f7cb637}}, {{0x000497d53a4f5668,0x000417b56810d4f9,0x00094a6218973466,0x000c6878e1da7404,0x00002546a940d011}, {0x000cb19c61ac1625,0x000c5bad0d3e1f3a,0x000b7ea4352f8fa9,0x000124c5356523b4,0x0000a16ad61fe608}}, {{0x000b87f4faed184c,0x000c9029f45fb0bc,0x000c6b1fc5f236b1,0x000ce3142c76070b,0x0000644324f28aef}, {0x0001d595c5d84462,0x0006f3ae19798e19,0x000a59cc7c020807,0x0001ba8dcaee553b,0x00000ed6d6bc2cb8}}, {{0x000ba19b6efcffc7,0x000827c0b87c0952,0x000aa30bc60f12d6,0x000f4ddee2c7c49c,0x000067238b807fbf}, {0x0003921501b5d92f,0x000ed2a37737ebc7,0x0001975433279e3d,0x000b4dafc12bc86d,0x0000a94dc6ffa40d}}, {{0x000b41a530ccbbd2,0x0006ca8235257392,0x000d98d0c87c8214,0x00074c852f984c05,0x0000ae57d737ef69}, {0x000f7bf3042a6dd3,0x000fe9647a649377,0x000ca9767b1a007b,0x0002d5caa9079a0c,0x0000d81a25c268f7}}, {{0x00067f8ff81578e1,0x00008045447d7520,0x00005aa6f7862215,0x000c77b0c22fcf05,0x0000030f0a67bed1}, {0x0009f151f0bd7390,0x0007e6debe8531f2,0x000677e982d7989c,0x000fd55c070e728e,0x0000a817bd306e81}}, {{0x000d830b0f2ac952,0x000a8b20e64ec110,0x00029cd9a48d0995,0x000945ef3e00e177,0x0000a570c20fd556}, {0x000bcfd4e86214dc,0x00020f615498912d,0x00030d76e2d014ee,0x0006d095e2b1e635,0x00005135ae5bd0fd}}, {{0x000273ad4f3049fd,0x0003170874770066,0x000c6e5fdbb8e989,0x000e6b5dba1ddb14,0x0000ba3788721f57}, {0x000e0a65a72f2cfd,0x000eabea56425aae,0x000872c371208bfb,0x00022425c6aa3b67,0x0000726e08413f93}}, {{0x000daa5061f16587,0x00016f0cd2b31854,0x0003d50dec0016df,0x00001752a3f23e83,0x00003b681d32bbd3}, {0x0006dc43ac343c03,0x000d557164212f04,0x00017eed49c847e7,0x0009c6b1e13c9109,0x0000fc9eebd93a1b}}, {{0x0006a727fe02299e,0x0001494f33190f81,0x00045c5be6335ccc,0x00066d5820179f47,0x0000647b783722f0}, {0x00049de02cafb8aa,0x000f5cc2ecccc22e,0x0000e8282299bc2f,0x000204fa8feea26e,0x0000627278c9e893}}, {{0x00097337933e47b6,0x0002ce766402a7e1,0x000440d9ff4ff6b1,0x00080844d8be0a98,0x000058f5c2f98938}, {0x0005677c95b3b3ec,0x00087137b6ff90b7,0x000c47c29fa04426,0x0005b1477b039b43,0x0000ca95dd44a644}}, {{0x0008ba42333fc4c2,0x0008d736a1b10b49,0x0001d4b2e274f8e6,0x0001994ca348fd5f,0x00004d3be78c8f10}, {0x000f858ca14f530f,0x00026b982e518535,0x000e1bf62a6e7f16,0x000417947c851236,0x00006a7c58ef3448}}, {{0x0003703f9374ab69,0x0004de564145583f,0x000526d50864f919,0x000495a3bc3f4822,0x0000f323c80a262a}, {0x000a7ae3f046a9a9,0x000e4f8a039aaa97,0x000aa0ba670da183,0x000c2ccb68f71c52,0x0000be0fe51b1459}}, {{0x0007eb6cbc613e57,0x0004d97ea61cc1e1,0x0007eded533131d5,0x00011abf69d39eaf,0x00003c2f4354e6af}, {0x0002493a4a375fa7,0x000c4833c5c24ca5,0x0006e71cf5f06787,0x000666114e091f3e,0x00006451f57fb746}}, }, {/* digit=17 [{1,2,3,..,}]*([2^119]*G) */ {{0x000bdef694db7e04,0x000779fcddc680f9,0x000b8dce1edca878,0x000ba111981c3403,0x0000274dcf1b0e10}, {0x00043b86def6d1a2,0x0000cbdb1866f727,0x0000c6f58d25b167,0x0007f5a4491e8c05,0x0000be2b2aba7fbd}}, {{0x0005c9dd111f8ec7,0x000d47c4e7603e0e,0x000392a51bcc33f8,0x00092d002f9a91bd,0x0000da4a7963132e}, {0x0000ae30bb1151be,0x000722e322511a0b,0x0004e9e7854febac,0x0000b80a3a508269,0x000058ffec2c4fe4}}, {{0x00092fcd1e0cf9e1,0x000db0e7b2e8f855,0x00035584edea75f0,0x00092ab04215cfc1,0x000074fc7273f570}, {0x0007877eb930beae,0x000a7eb02a5ae727,0x000241b9b504cacc,0x00095419fe08f7f5,0x00007fb62f56d5ca}}, {{0x000349d29c4120ba,0x000f20d0d915fbb8,0x00010ba519f94391,0x00091124074fa754,0x000066adbf6b50a5}, {0x000543c34bfca38e,0x000fd9e1ccfcc164,0x00020219ce0f2755,0x000979b9da0f53e8,0x00008234499a6b49}}, {{0x0008b769d4c54230,0x0000b0521c49cfb8,0x0008700a19e56eb1,0x00058a418e0b5ebe,0x00000cbaad6f93cb}, {0x000fbded92a5e67d,0x000b4f347f11e923,0x000c0585bca4979a,0x0000e2b9162d856b,0x0000d6254b07c3c7}}, {{0x000c513516e19e45,0x000775c4d5937b23,0x000e71ef656e2e84,0x0004c54f727d735c,0x0000b6304a7479a4}, {0x000a7363ab7e433f,0x00000e742f836638,0x0007fc19f1adea47,0x000697f054b8545b,0x0000935381baa1d0}}, {{0x000ab2d799e9a748,0x000e2949f729546e,0x00090055a96239e0,0x0009b04a274c6b70,0x000035142c41020c}, {0x000667aa2e8807fe,0x00043aa3d39ea405,0x000fc72f529f2c08,0x000b3bec555d6442,0x0000856e0e8dbeac}}, {{0x0004f9d918e49366,0x000652513982b550,0x0004d9cb965035ef,0x000508a553a0c26f,0x0000cb10d571ea85}, {0x00057b7a242da112,0x000d472b726848d9,0x00002a96b16a4d3d,0x00063b1d7e637c85,0x00007c7032b930d4}}, {{0x0002b18e4136a147,0x000cf78e32bfbdc0,0x0009c3c03bacf969,0x000c4f598d89a3dd,0x0000b92420a93bec}, {0x0001f78c64d565c0,0x000010f28295d4b4,0x0003d051a9f969d0,0x000585ec7f7f76b1,0x00008945e1ea92da}}, {{0x0006b7d5846426f7,0x0008b47d441d5536,0x0006fbf48e7d09e8,0x000d7ce10b404d73,0x0000fa003d15784b}, {0x000614f17fd95965,0x0000e5cb98db25f7,0x00083a76a49e0e0a,0x0000f7dc65957b2e,0x0000d40da8e1ddbe}}, {{0x000c405050bad247,0x000d52aa4823f2b8,0x0008365a78918426,0x00068fbaeab3dda3,0x00002031717ec91b}, {0x000d69960a94120d,0x000d199eaeec8b00,0x00060aafd478a255,0x0007b2ef656a5f6f,0x0000fd7cb762dee7}}, {{0x0008bb4a595939dd,0x00085874021737f6,0x000ad76120355647,0x00095ebe740e7c84,0x000089bc84460446}, {0x000da5d85a9184d6,0x000b3fc0b074f7f3,0x0008a888e562563b,0x000e7ba6d2e6aaf8,0x000012d8643761fb}}, {{0x000dba7f64085e79,0x000399aa8511465e,0x000a2d188b230f30,0x000648c3388426cd,0x00000885735db666}, {0x000ff9a652f54f6d,0x00038fae2bf06f02,0x000f5eee365c8229,0x000d6fa816ade062,0x0000cdbdf44ccc56}}, {{0x000bba354530bb24,0x00078b0869ea9fb3,0x000431163bde3ef7,0x000a3549bc90460b,0x0000d03d7d324819}, {0x0004f9e43b6a782b,0x0006ec88a68633ae,0x000ffedd9216db30,0x00083fe1dd88e000,0x0000280da9fc2bd4}}, {{0x000cb8a1635e7417,0x000a08be02a732a7,0x0007ae030fe14008,0x000ce8cfafb3341b,0x0000fd508e7cadd0}, {0x0003219d607ad51e,0x0009ad40964a72c8,0x000878da20f229c0,0x000b853be2c3361c,0x00000c96743cab2a}}, {{0x00086913e538cd75,0x000c3e08ad53458f,0x0005d15ffa7001f6,0x0005dd02b8c6e6bf,0x000048234a451121}, {0x0009d2d3d5b40458,0x0005ca904190ff5a,0x000607f8bb0ffeeb,0x000729d5a3aca448,0x0000cbd665cb0a06}}, {{0x00034e0425830687,0x000b83f6e68387f8,0x000c1224802da2ae,0x000efbfb763e5d05,0x0000230378fd5a8a}, {0x00080b571e8e5cae,0x000bd3b6252493bd,0x0009c552e53ab041,0x000e653b8605136c,0x000084d402db5524}}, {{0x0003573f37f59371,0x000dc1e4fca5a37f,0x0008ab0fceb0f6c7,0x0006ac1965a554ac,0x00007fbf56c37467}, {0x0006bd9acf7d720d,0x0007402247662e2f,0x000d53bef41fc8f8,0x0007d0817a14b385,0x0000ae327a64d76a}}, {{0x000a065c48182672,0x000b17c1bbc16ad0,0x000392a9233aa189,0x0005ea44970b5227,0x00001699a1c4d153}, {0x000779cc2d7a7fda,0x0008f9c83cf2cd20,0x000c0b8c7e318605,0x000e4cfb69440b72,0x000081497d81b9e0}}, {{0x0005c891f5f82dce,0x00068361079e515d,0x000a353309a7f67d,0x000e1ac8da81e311,0x000044990c52b18b}, {0x000ed95af103e596,0x00072dac9261c7d5,0x00094b8d3ece8aba,0x000e835e82b09993,0x0000830f09a76adf}}, {{0x00029b488172d014,0x00058aff9e02250a,0x000a6329a8b20bd6,0x00092078a7661ee8,0x0000520304e13fce}, {0x000da1f2b47f7ef2,0x00083bffc540ae45,0x00064f874e07f528,0x000f38d799700934,0x0000244c2cdc6fa1}}, {{0x0001ac194d7d9b17,0x0002582e7f1743c4,0x000da0fca5bafdd8,0x0007ad6f0614c15f,0x00004b043a818ae3}, {0x000afa19e71734c5,0x000e4c450f2e3ba6,0x000e242b115d5437,0x0003c1fa5883fe67,0x0000143bdc27c195}}, {{0x0008b53fc5e89202,0x00087a9cee08542b,0x000486e08363bf9a,0x0000d1e2375f10c3,0x0000037543bac5e7}, {0x000bccc625640b46,0x000e2bc62c3b7109,0x0003f26eacbc1051,0x00042498455fed80,0x0000badceac4b372}}, {{0x000ce7c6b53f5f95,0x0004cb176d99a2a9,0x0005c081b6424659,0x000ee661298d36b9,0x00003505bb86d9a9}, {0x0009e61f2ba70b0d,0x0008bafad4533f6f,0x000eb4a6ad07e16c,0x000c8dcf1694bbe7,0x0000febceda0cb0b}}, {{0x000dcdc53868c8b3,0x0002086107a692d3,0x0009b4e64174311a,0x000cb61109e07c68,0x00000e4587f5df3d}, {0x000ea310811b3b2d,0x000c3cce43ea841a,0x0009a78036144d41,0x00092f764c45812a,0x000003d37200e158}}, {{0x000d7f2b1f3390b4,0x000c65b61272c676,0x000e127a99f7a1b8,0x0007bf0ebebfc9c2,0x0000602500c9dd99}, {0x000771c4711230f9,0x000b720f09c17f09,0x000e5e38b058eb37,0x000bc01b693d4bfe,0x0000289eb1fd653c}}, {{0x00046abd51b9cf59,0x00020f0121afbecf,0x0000dc274d2aa9c0,0x000a3ba6aaf7d2e9,0x000009e4ea0d8b95}, {0x00004966f32dbdb8,0x00000b030b3ee6b7,0x000b617e2672188a,0x00009e6effe5b3cf,0x00007e947defc827}}, {{0x0002b391770f5a7b,0x00005e44eb82a44d,0x00069712ae4d4d79,0x00020d92e69d1e3f,0x0000f11c4d75c6a8}, {0x000f3e542c4224c6,0x000be49d941cb5e7,0x00050e878d6b4e81,0x000c53fd72bd1654,0x0000a61e28b4e25a}}, {{0x0002094e6f1cd952,0x000ced18673f3327,0x000fc14647512f30,0x00077b12f7a4ca5a,0x0000f0956568bbb9}, {0x00047caa82262004,0x000cdac07369586f,0x00013acbe02c868a,0x00054c0ef2b845c6,0x00003d7563e43860}}, {{0x0009dc7ab952578a,0x000186e84d0b54da,0x000872042b5423df,0x0006df08b64eeb9b,0x0000c205782f990f}, {0x00096eb21f4c77af,0x0003bab273af4ff6,0x00036b3f11a79c3e,0x00027939bc922e94,0x0000f807ef9c6d9a}}, {{0x000ea3d778f22a00,0x00085b5e746982ac,0x00018ee7dfb10b2e,0x000a2fc0b1698028,0x000011afff4c91c1}, {0x000d126ad124418d,0x0005172e295f95a6,0x000f4db7531c081a,0x00046166bb283af2,0x000011554104acef}}, {{0x000a8f833f6746cb,0x00054ea990cac7f3,0x000ddb0a921e46f6,0x000554e15fd5c5ca,0x0000d41f01728614}, {0x0004434426ffb589,0x000584dbc204346f,0x000969b7f8055943,0x00039a63dd20fe5a,0x0000d59e9577899a}}, {{0x000971c8ad4cf4b4,0x000feffb8fb8f1b0,0x000340ba40344885,0x000758b071ac3c65,0x000008d0596f27fd}, {0x0008ea498c364b09,0x0004751e8ab5e7c7,0x0005d9002a4aac4a,0x00045529e1d56048,0x0000acd518b18844}}, {{0x000688fd06f56c0a,0x000d3f027972e4ca,0x0009a609da48af70,0x00070dc91f0f045e,0x00009dd82ce8e612}, {0x000ca63a0ef18d34,0x0004fd6ca3bd8903,0x000f47d039fb7ee3,0x000e8e67b4a09cab,0x0000cdada015c67d}}, {{0x00037499355a244c,0x00058f2151a95200,0x000b4efcbe77fd2b,0x000e24a95d6cf666,0x00005a0cad09a2cf}, {0x000fe5cef8118650,0x00089ea5cc3d104e,0x000b58dbcf52813e,0x000b11855683dc40,0x0000338ecde175fc}}, {{0x000563774921592b,0x000d09bb9d31f9a0,0x0009c5459b4f1261,0x000f52a51429b74e,0x0000e182e701ea71}, {0x000b07cdfc50573d,0x000992be8d44d3a3,0x000ab65d39ba1afd,0x000801cbcfd2cb52,0x0000f11d54879571}}, {{0x00003ee02a2404ab,0x000371088a710994,0x00004ae71497406f,0x000361e947940950,0x0000db420795812c}, {0x000a30fd88284423,0x0007ccb5ed1c2b72,0x000a40015283add2,0x0005efc7c0e20066,0x0000e3be64138b29}}, {{0x0007dc1e038a6759,0x0002fc5c6320ac12,0x0000d2c53729deff,0x000cd327df8fd4a9,0x0000b74b0ecf81e7}, {0x000a623dab407e5c,0x0004b6b340c65cb5,0x00028392ccdbd361,0x00082fe184415a7d,0x0000184c1d9a96f7}}, {{0x0004f1981d3a80f5,0x000178e02432c320,0x00049e0c1fde0c84,0x000a7328203b3e81,0x0000904bdbb58053}, {0x0001dd1101b68053,0x000c19aa6d4930fc,0x00017408743c223b,0x0000086ed671417a,0x000011469a105997}}, {{0x000b6845e43fc616,0x000580d3ab57b189,0x000181da8f328237,0x0002b7efa34b67b1,0x000021ed0b2f9ee5}, {0x0008de1ad9906763,0x000b26d540659b17,0x00038c201d51de67,0x000f5bfa2c27c475,0x00003856ec868a40}}, {{0x000fc15be6cdcde0,0x00039f0c6f892522,0x0003e30a61e603f3,0x00053e7994edc310,0x000033a00db220c8}, {0x000a409f7bb7fd76,0x000de62d18f6d3cf,0x0007fe29570f8781,0x0009f35bd8298068,0x0000eef4c32b9566}}, {{0x000303b2f7e85c33,0x000141988f9b86a9,0x00038acb55fce462,0x0002122b935bf6c1,0x00000ea7d6755661}, {0x000b5f4e51ab9a22,0x000a8e067c78ef1e,0x000ca9ca60587c98,0x00005793ce1b3c77,0x0000a553d4d74b5f}}, {{0x00082364da29ec28,0x000339c57316c789,0x000d80d47dbdd5d1,0x000391457d6e6b2c,0x00000b460d07e9e7}, {0x0008cabf963c31e5,0x00037c4d32fd9864,0x000f7c68767f9f63,0x000ea6baf42a9dfd,0x00005f292a35b015}}, {{0x00068b2cd21ab3de,0x0001e393d39289e4,0x000013af9e504f02,0x000acacb21e1d4a5,0x00003283f79a2c28}, {0x00035f6226bf99fc,0x00034e291e69f38b,0x0000c162de835427,0x000dbda1673a15b2,0x0000101dc76704fb}}, {{0x000b4c2255bd6178,0x0002ec2a91548323,0x0006793876c96969,0x000e2346e6586062,0x0000e01db0d38c88}, {0x0002873893a55595,0x000af7a3e14933c4,0x000cf35f87630f04,0x00073265d80805dd,0x000082ca080c7dfe}}, {{0x00056e10b1894a02,0x0001b81c68c02c71,0x000b115b59203400,0x0007f2cd225d00c8,0x000037f9c22a3b90}, {0x000f32f4470e2c05,0x000108be4e950ea2,0x000ae5463b725f7c,0x000c03bf1dcafab1,0x00009ed51876ba2f}}, {{0x000f316d0115d4d7,0x000f63691599f6e0,0x0007f0a415180b12,0x000cbfa57e32c952,0x0000b0b081e18e0e}, {0x000aa8abf4f0dd06,0x0006ed2526966dba,0x000f864fe99b289c,0x0003ab19b7755edb,0x0000974e2b1d6cad}}, {{0x000bee206ddd6572,0x00010ff3a96d35db,0x0006be758e7cbdd1,0x000f5d6838196807,0x0000d737e7228c91}, {0x000ab6286ec37766,0x000d345fa7a15f83,0x000ef093398aa649,0x0007b19477ec3772,0x00006f52b1e698c1}}, {{0x00058fbd803738b6,0x000784e86aa49eec,0x000b5149291aaade,0x0009740b1ae617a5,0x000032721221bc45}, {0x00028f0862c51290,0x00093321a4a07e0e,0x00041c88f0a8f79a,0x000e3ae26d166450,0x0000571b80553233}}, {{0x000ccdec95207114,0x000cfc8b84bfd1b0,0x000fef31455a9e4e,0x000f2b5426bd39a1,0x0000f5f638eaeb93}, {0x0001ed32bf9341bd,0x00007d42d5a9ba2a,0x0006dc7c5d63c132,0x00085102964a8931,0x000017596079a511}}, {{0x000201ff9e6ed353,0x00053736925ad8a9,0x000581af7b7b5ee4,0x000050da83fbbc99,0x0000076bc4094eeb}, {0x000c98c02dec312a,0x0007838dcb785511,0x0009c08c9270de89,0x00006d8cf4cf9c53,0x000070cb65ed8d3b}}, {{0x000c10ecfe57bbde,0x000555a0c2b5b12e,0x0001c67bd82c7b65,0x0002cbfdc7d5cd16,0x000032e89868e3a3}, {0x0009444d11a5529a,0x00018427fa1a7aba,0x000a1770ae964ed0,0x000fcc7528392d24,0x0000152ce2cb2c72}}, {{0x00053a48ec07649b,0x000f959dd4537145,0x00064b11018b4c28,0x0007a23a32b7147b,0x0000871bfa5de6f0}, {0x00012e59e2e3c9b3,0x000514aa90f6b671,0x000539006fbf250e,0x00066fc77aedb8bd,0x0000b0cdf9b0172a}}, {{0x0009feaf8c511875,0x000c241e4da7edf6,0x00011434505bb67e,0x0002b0f7df0f3208,0x00006facb080b979}, {0x00007e98f6229e49,0x0003c26fba0ff3e0,0x000339d7962d103f,0x000ec0bf33bef7b0,0x0000841357c459bf}}, {{0x000bb59c34e67058,0x000affdaa84cfa8d,0x000108537c3c7180,0x000e5a795872fca4,0x0000750cc3c132a3}, {0x000c69db7275d7d1,0x000b1e59b2e9b61c,0x000cbb493ffa0168,0x0002d8ba032abc6e,0x0000d86dbd33c908}}, {{0x0000b67e28ef5ba5,0x00097b18e169ae1e,0x0006bbd202c9a469,0x0001d1becd0e331e,0x000071b360eff5e8}, {0x000ea58101c1d454,0x000dd8880452cd9f,0x0008dd4466651788,0x0001d0699726351f,0x00004bed02323728}}, {{0x0002b2d33da525d4,0x000dd3144fd8094b,0x000c1061df193678,0x0000f478ab5ba4f4,0x0000343b5fb1ccbe}, {0x0002371638127137,0x000d87611d93a870,0x00021e1d747bf6d2,0x00077cd6729b8cbd,0x0000484d4e14629e}}, {{0x0006eea60dbac1fd,0x00040a06a2f7830e,0x000ca535b23d8c48,0x000a9ab96714b050,0x0000c8d3645bbd97}, {0x000f9fab12177b4c,0x0003934d5d9c106e,0x000ab360bf79bf46,0x00044e6537a349a6,0x00007c54254600c7}}, {{0x000a047e5911a766,0x0008047f1ee7b3c7,0x00056ab4261ffa5c,0x000ac8b5aed36f8f,0x0000a0d41b103ff9}, {0x00069f5cc30d3577,0x0000fb72be9668f4,0x0003ad461be9adf8,0x00041aacd926fe90,0x0000e89e3903aca4}}, {{0x0002de5facf69d43,0x00061775344cf0f8,0x000e36d04363b7e7,0x0009a53894f312b2,0x0000c6cb4fe41d1c}, {0x000c3394008e1f2c,0x0009649f326c85d9,0x0008c5e065e9a85e,0x000ba91c35c60a67,0x000008b94505f86f}}, {{0x000c02c89f71f0f1,0x0001ef3da3c0de40,0x000125dedad8f3e3,0x0001832ea5096b42,0x00003879cbfb7379}, {0x00014a56b306a0b0,0x000667646c5e6f47,0x000726368359c2ea,0x00031efacf894307,0x00007a5893565ff4}}, {{0x00061d168754ab0e,0x000c8f429a7624d6,0x0008ce769801fce1,0x000a2ae068a85fa5,0x0000dc35c553d5ec}, {0x000276fa3f660d1d,0x000de8fc7167ea31,0x0008db0aea0184eb,0x000e113f20f21a1d,0x000096d096026c35}}, {{0x00002b5f8c2a25b9,0x0008759204b6edf4,0x000b4e34c1bb772b,0x000459c0cbeae219,0x00003109d80cfa08}, {0x000ccf78ef59fb59,0x0001f807096354f7,0x000f3ba9b3b438fe,0x000a920e28c65931,0x0000cc31b477ad9d}}, {{0x0000ba9b733aa5fc,0x000b305af2353c2f,0x000ac82a5dece47c,0x00018a38e3f715a2,0x000097ba641e203f}, {0x000550409c110608,0x0004c6af512dc3af,0x000f2814656ea2c0,0x0004947ac28daff3,0x00007fab43b159ef}}, }, {/* digit=18 [{1,2,3,..,}]*([2^126]*G) */ {{0x0001641d4c5105f3,0x000e3d7fbd650989,0x000e6bdb01ae80f8,0x0008606d67225fbe,0x0000b433b59afc4d}, {0x0006db693e856387,0x000273e9862f44e6,0x0005c32ecf7b5925,0x000f506b78515766,0x000002fefd81e362}}, {{0x000475d0fefb0c3a,0x000aa6d7c35d3754,0x0003798a4d48fb56,0x0008e60070b63336,0x0000e89f3d32fdb9}, {0x00089c86363d14cb,0x0000b7abd27d970b,0x000d5a0218981752,0x000aedebf7d47444,0x00003083bb07ac72}}, {{0x00041debe949a447,0x0007e46a4fa53897,0x000047bdc638e938,0x0007c9cfe6419ca0,0x0000047f6491aea5}, {0x0008a9041fbab170,0x0008576bdba254e4,0x0002afddcda8e0b2,0x0007bfe807eebcc7,0x00007d3336df4257}}, {{0x000c244bfe209256,0x00032fdce86762a8,0x00038706391c19ac,0x0004f5fa96a5d5dd,0x00001d587d481d32}, {0x00073a2a37173eaf,0x000763778b65e876,0x000bab43e2384800,0x000fbd20f8441e05,0x0000a11fe133621e}}, {{0x000772e81685d7b3,0x00018f34a976047b,0x0005f48ef23f27d8,0x0005c3927608e291,0x0000b0b43fad521d}, {0x000fb2663ca72840,0x00041d4db8377613,0x0003b526b7f5729b,0x0003d187b1489858,0x00000b732a6bbadd}}, {{0x000f4262048e3968,0x0005b83d9de48e02,0x0001e85ad436b50b,0x0008d6778d348147,0x0000b01ea6b5005c}, {0x000afee97015c07d,0x00087e3ba2aed3c7,0x000d3a1d246cdf1a,0x000ff3aa42e50183,0x000054b52698541d}}, {{0x000cf304e23e9bca,0x0005726e36243f24,0x0000b6d614387f81,0x00077b86a46a033b,0x0000f1bc8462b2d7}, {0x00001ba527de79c6,0x0003e261bbb625c4,0x0007b4bc70e1346d,0x00062eeb96c44b28,0x000058493c7b2545}}, {{0x00049feb8a24a205,0x0001a52ca53f23f9,0x000fb485317ebfed,0x00005d4b691bbebc,0x0000617ff6bb278a}, {0x00034c5e3c99ebdb,0x000d6784156a241b,0x0005d67dffc64242,0x0000109206482f69,0x0000967ce0f9e27c}}, {{0x000375121c80b5d3,0x000c731ecca065db,0x00038a07e2e7a563,0x000854b56ffc4e52,0x0000d6c296662ced}, {0x0007d1aaf70b8855,0x0008dd686459e99d,0x000c8ba5bafc3bad,0x000aa34c78bf460c,0x0000a43951968955}}, {{0x00017a85fe4e3142,0x0000dcb8906ff8b5,0x000061b23e60234d,0x00059cdfe542acf2,0x000087e191f8b4cb}, {0x0007ddc09d877d88,0x000b946789412185,0x000e05ea41c23478,0x0004fe3bf0c056b6,0x00002da4b5430159}}, {{0x0006791fadb86087,0x000d0b74cdf6f752,0x000b90a34049e832,0x00010c343581ccc2,0x00003639eb90360b}, {0x000331fe1e4a71b6,0x00032072f9194fba,0x0006790326ffd6b9,0x0002ce0e53271c65,0x0000720644551427}}, {{0x00034a3b23358342,0x000a70ef6860c0f7,0x000e2bb0d9526205,0x0003faab8be71704,0x0000418871e22f38}, {0x00076814082c1576,0x000fc9c20073d717,0x00087e728cc914ac,0x0005fd9186c1ebe5,0x0000fdb3c22c1bcd}}, {{0x00014a6f2f9f8e93,0x00031fec49d230d0,0x00005a8d9963ece2,0x00029a562025c596,0x0000987444549f89}, {0x000ff6512bf476a1,0x0007f9cf7d9101b6,0x000be56ca598a64d,0x000615c7ec774993,0x00000899785dbb33}}, {{0x00092fd02eee3ad4,0x0004f0145270b8a0,0x00012b675a86b3d3,0x00040ef23d98c685,0x0000b8bc785a2ebb}, {0x0001f54413f9cdef,0x000e3bab56647d30,0x000bfec23a5e4fb4,0x00020c2d2b252d1c,0x0000cd576bcd1771}}, {{0x0007d3e83731a34b,0x000e3d836e8e0442,0x00012ca7c2bb9028,0x00073a036acff8b6,0x000088fe5f083d9c}, {0x0006bc6edea4eb34,0x0003088eec77be2a,0x0007106e143b9313,0x000a32b41ff566b1,0x000069e9172a54ef}}, {{0x0000f0441c23fa36,0x000061989a2eb448,0x000a29ca7b4712eb,0x00028bdccbba0f93,0x0000e205c1536194}, {0x0007957b36416860,0x000d45ac8b4e90db,0x0004e03500432691,0x00051707a759acf6,0x0000514d89c9c972}}, {{0x000147fa8e67fc38,0x000b2b2085be1701,0x000284e579e2e0b8,0x00066455651824ac,0x000090d4325f4893}, {0x0005e6ec55e68a39,0x000ab339c85a8a7c,0x00022b655bf12e90,0x0006ffa1846b85f9,0x0000a54ce4d9bf4d}}, {{0x000e83af1a142952,0x000c9285d4f9d7f4,0x000ffdaba916f955,0x000152c57bb0e099,0x00008a430350ab0d}, {0x000ffa2b8a9cef88,0x000e39ec051a0a36,0x00068e6725517407,0x0007fb1c796096ea,0x000053db5fc7b3c7}}, {{0x0004ba9e864a51ae,0x00088e8a1b8b2147,0x000120a286c26769,0x0005da9c82362694,0x000061e9a496383a}, {0x00050039f84216d6,0x00074d43cd857dd7,0x00012c659ab020d0,0x0002ad3437ae48da,0x0000449c2ec46545}}, {{0x0004c1c2cf9d7c1c,0x000a2e95e5abcc7c,0x000ae170c1320886,0x000661fb7b9056be,0x00008a5b2519bc0d}, {0x0001432c11d23031,0x00020f03769f4ed8,0x0005398287da6691,0x000d022ac7a5fd84,0x00004dada944bccd}}, {{0x000c3217ef6b0d15,0x000a2c933f228b84,0x000440b8252a9477,0x000d5e0ef6728afd,0x0000c3bd859bce4b}, {0x00080f5f22c2d3e6,0x000057bb6cc5918b,0x00095a11c368d504,0x000a70566142a126,0x00000ac583b4b19e}}, {{0x000bb980eab2437e,0x00047e2654c8317c,0x000d8307f8cc08c5,0x0009931e2d6520e6,0x00009f147f437428}, {0x0007d14d2fd6cf16,0x0003cd4fcbb05f9c,0x0007341f7a3ecd06,0x00015c4d83fef08e,0x000043f23a09a631}}, {{0x00078abe65ab743f,0x000045edc89cd38a,0x0000df568bf7c75b,0x0006814dd8752e53,0x000085c4a77d308c}, {0x00055b2e68acf374,0x000d6b32af854c99,0x0005cf493a544df3,0x000feb0b8ec3f5a2,0x0000d8f27645a622}}, {{0x000f7aaf0dcbc49e,0x000890bbb45b7bb4,0x0002ca2e57de551f,0x0006eeefd0f3e49f,0x0000ce58709ff5c7}, {0x0000edd167d79ae1,0x0002ea7d7ec13292,0x00030af91039df8a,0x000b59e46206c0bb,0x0000ff5e2f532676}}, {{0x000a0396ea51d668,0x0005007d7a2611f4,0x0005a9b24506c144,0x00019de0da570575,0x0000fc8cc329f1a3}, {0x0002d4d9433d67d1,0x000f5a7dd2968364,0x0007bde077fa5cb8,0x0006fb476591db9b,0x00003173d2551971}}, {{0x000599dd5b340fff,0x0006c0fe76c5ea30,0x0008f5adcfc6b529,0x00028c2c6968c8ab,0x0000723c7f6801c9}, {0x000c3219773d4025,0x0002cb51dd474203,0x0002be23cdf7c6aa,0x000e86ed49e37a55,0x00007febee85b5a6}}, {{0x000bee47bd8e7397,0x00043e63bf75c5ec,0x000fb892379d4499,0x00012fa68bd00f38,0x00005d48ee540533}, {0x00077aadb5cdf33b,0x00058c696769554f,0x000fd674e3396e89,0x0003e47fdddbf2d3,0x0000bb8f6ef49d0e}}, {{0x0000651cbae2f701,0x000583aaa8eb51b9,0x0001df499efc4bc0,0x0007a57ecd8689dd,0x0000aee99a832f36}, {0x00085b9ae8274c57,0x00050d30b39c95d4,0x000c1ef816c14d44,0x0002ed4afea90bbc,0x0000c5f317b1459a}}, {{0x00010754ef442271,0x000ecc20f4960121,0x0009853cda17bed6,0x000ce6fcdfe42481,0x00003793299071e2}, {0x0003078dbbe307b4,0x000e36ee99363c1f,0x0003caa206dd1c20,0x00040de3ee4b5742,0x0000ac3793bcefb8}}, {{0x00038ebed1f8ca0c,0x00078ebb25a29344,0x00069896f3e54665,0x00043d0415af0ec0,0x000013eddb15a5aa}, {0x000204fd49eb8f61,0x000cc74f16707a04,0x000fc0558d0d5bdf,0x000ade2697e28656,0x0000020737111ceb}}, {{0x000e6900647a82b8,0x00040f40054f5f87,0x000853803908e0ed,0x00025229f633d479,0x0000ed13c9aca28b}, {0x000f6761f460f648,0x000ab6d063363e2e,0x000c4979b53930b9,0x000596b47073ac8f,0x00004380e0edecd5}}, {{0x0002c6bc4fe3c395,0x00031c7bebdfe3b2,0x000693459ba4a815,0x000b11a23ab6b725,0x00003bc377064922}, {0x000c8ab5afc60db8,0x0004a0b9f2a34645,0x0000fc507aa02235,0x0002e6d2a2954cce,0x0000c2731bbfce1c}}, {{0x00008ab18a0339d4,0x000cf735436cf396,0x000992b4fac7a658,0x000fd4722c2b07cd,0x0000e83daed340dc}, {0x000c7be2f39ea3e5,0x000f60a56d2e8a34,0x000dd8038ef0c005,0x00007512731f6a6e,0x0000721d7409e3cb}}, {{0x0001511fbeeee1be,0x00030f1d0c051ea4,0x000c07d35d1ef5e7,0x00049262feefd173,0x0000530a00b6a329}, {0x000b7fef15ebfb03,0x000ca322491a5d55,0x0005b3237549de03,0x0002b6c7b5f60274,0x0000632a3a24ab6e}}, {{0x000ba890ef59f78e,0x0002e9e52b9a0d3b,0x0006314470dfc644,0x0000b03dc7969972,0x0000f03391893be2}, {0x000735db13839481,0x0002b0dd7d7d0c92,0x0003ed068c1fc29a,0x000bdc5485b69740,0x00003bfaab3bac93}}, {{0x000c6a90deeaf523,0x00021c641c15410d,0x000c504c4b003fb0,0x000a76e384978c5b,0x00007640487b64a6}, {0x0001bc6222a77da2,0x00073e47eb110599,0x0001b432c62260a5,0x0003e9a7af6613f2,0x00002f3acc9cb495}}, {{0x00049228e41d155c,0x00077ac059ef5293,0x0008844114d02456,0x00078ef02017554d,0x0000e8055d0659a1}, {0x000d1aff62045490,0x000ec7066759cd77,0x00072c229a0a00a3,0x0006b0471071ef02,0x000009bcf6bd3c4b}}, {{0x00038a822305177a,0x000ea1645bbf2a26,0x000a7a3c0d51d59d,0x0003ee081142fdc0,0x000017eca6dec706}, {0x00087ed60d9dcec0,0x000120ad24550bb8,0x0007102bad6d28e5,0x000408ebed6308a6,0x000042c31148bffa}}, {{0x0009ac58aa68e305,0x000bc483513efd09,0x0002d8f0c7a6a3d7,0x000954afcc6b75ba,0x00004dacf966e78b}, {0x000696fa4a9af892,0x000fe6ac98ecf645,0x000a67a203a41193,0x00062621b8b3f622,0x0000d0b1e0fb9dec}}, {{0x000919240be34e8c,0x0006d1907f3527c8,0x00056702bc7162b3,0x00069bd0188ec1a9,0x0000a132f7e9f937}, {0x00044f90e2025b4c,0x00084c62f14c3ece,0x000e3cc1167aaec6,0x00050ded74141822,0x0000f9b75c43ff9a}}, {{0x0002b164d348272c,0x0009d959d56d02fa,0x000762916bd99d61,0x000c7ffc4f19db18,0x0000c7cce5109c1a}, {0x000ebaad846bd832,0x000c892028494d59,0x0001f4ca98775a9d,0x000f10e7ec4ae16e,0x00007eb5875da893}}, {{0x0004d51662cc565f,0x000a1db4138d0028,0x00032a59482353a6,0x000c46e9c7aaaaaa,0x00005528b5f95669}, {0x00002312f23c5ff3,0x000a3affa3a1f322,0x0002ddda0e3e8147,0x000bd4cb423d5c20,0x0000d6414ac9b871}}, {{0x00082e1a51a168a0,0x000148ae5448586f,0x000233eb8b712c67,0x000ca99a2e4bd176,0x0000188223a78811}, {0x0005e21f7c18de1f,0x0000c27bb286553c,0x00051e9297682e45,0x00034e4ed036b30e,0x0000487211cdc9cb}}, {{0x00042770c24efc82,0x00049ef737a40d09,0x0004cdd280349fd0,0x0005214d1c9dd251,0x00009c135ff50da9}, {0x0004508f78b0b6f2,0x0002478c143cea6e,0x000e21e65176f5dd,0x0008c3e81484184b,0x00007f7525d07df3}}, {{0x0000e09748ab1a42,0x00003efe44331fb7,0x000f75af29cba50a,0x000ea85846c7a615,0x0000a7c2c577ee73}, {0x00066a43f0a449a3,0x000b7d90fc3d42e5,0x00061d05745474c3,0x0000924447be3d8b,0x0000e9d1cf16a4ec}}, {{0x000e453f380a6e68,0x00011b1437c21603,0x00029610a0b86e43,0x0007f6fa4173f2ef,0x0000fa729a8703d5}, {0x0006f6e6c9c217e3,0x0009619195243e18,0x0003d4fb1be1d307,0x000f7162a62a7015,0x00002ed3e35068c2}}, {{0x000027f9eb1a8b70,0x0007c5b22fe8d785,0x000d6a191bc37eb7,0x000816466b34f0b9,0x000008a89af9a05f}, {0x00028fb7d42c10ab,0x000e99b3f6b819b0,0x000a0ade37fe8c92,0x000a7ba8907cc0a5,0x00003154f52059d1}}, {{0x000efb6d9790ed61,0x000c96aa793b5066,0x0003e042ea77a0cb,0x00074b0a915f3c22,0x0000c5def0479c58}, {0x000007873b6c1da8,0x00027cd8557a0e83,0x00060f3b155cf85d,0x0000628f7c7c7604,0x00007052acbc6e58}}, {{0x0002b80907eae66d,0x000f7d721c890921,0x00045ac1c3cb068d,0x000dbad87941aedd,0x0000e8d5c0dddaa0}, {0x0001fdce3502e6ed,0x00007d89a084da42,0x000c24bfbc894420,0x0000eea307ba5ef0,0x0000a212bebf0bde}}, {{0x000a24bf82ce682c,0x000547f71fe4ea2d,0x000fad8de058d381,0x000faa75a024625f,0x0000d7b05dd6adce}, {0x000f8ed1d9f54ec8,0x000832d3b5cad442,0x0006b2ce28be3d61,0x0004c062220ed0e0,0x00002699a5f9b0da}}, {{0x00006f571c0c3a75,0x0009bd34180c3ff1,0x000d7d3758f580f5,0x000674febb120e22,0x0000e5782cd39513}, {0x000580c99c82a70a,0x000e75ea8c4c2275,0x000415e70e8359fb,0x000013b3b48db87b,0x0000acf2240b00c6}}, {{0x000ccf5e4652f1d2,0x000ab56157b29faa,0x00061ec50bd6fdd2,0x000d5284f4fb1f62,0x000044e55ad676bc}, {0x0009305047d320ba,0x0004c181263f881c,0x0008fb8ee1ca983d,0x000963954e9a4427,0x0000d2dbc0fd96e4}}, {{0x0003aa29268b3de0,0x000ae6e0609a723f,0x000f442520d1ca29,0x0007ed794866aa6c,0x0000b59f3e301af8}, {0x000e5ff7f4a6c51d,0x000191dc2f7ee234,0x00094d81fa8768fd,0x000ce10afc73320a,0x00007f84282d6938}}, {{0x0003c0e0546063ea,0x0001bd61abc6ae0b,0x0009ac4007fbadcb,0x00010c35d7a2c936,0x00005978d0a4e67d}, {0x000211e4f85eaaca,0x00015acac681290f,0x0008384cde61e2ad,0x00030f0e12522538,0x00007fb68ea6cfde}}, {{0x000b9363daed4c29,0x000f9606f7897a59,0x000a6d90a80a9aa3,0x000885240c1ea5f6,0x000048364d3e14d5}, {0x000bc6070985182c,0x000d73310895062e,0x00029c2f5a6db5b0,0x00037da4a12175e3,0x00005f25bd350ea2}}, {{0x000c5242d0a4c230,0x00046bb3cc527915,0x0009e2c92eb5d26e,0x000cf8369a9116c0,0x0000c527f92cf182}, {0x00019382aede0ac3,0x00083cc349399e59,0x000a34361b292220,0x000fe60c9d896299,0x0000c81836df1905}}, {{0x000b57fa001ec5a8,0x000b20dc5dba4bfe,0x0004a1380e993f5b,0x000a03c788410972,0x0000a0369abb2fe9}, {0x0008d608c927db84,0x000f54655741ea06,0x000b6c7eabf5f37c,0x0009cb07d402a204,0x0000551c295aaf25}}, {{0x00071e7ed77ee8ba,0x00005309d5c7698b,0x000e780cabddf7bd,0x000ef3c201c22c34,0x0000b04f7d8ec295}, {0x00072944313a8cee,0x000bb2ca4cfe1c94,0x000a7a97ae532e4a,0x000d5aa9738f80d0,0x0000c088c898580f}}, {{0x0001ecc42ce9e515,0x000d625fdd2a612b,0x000e7f8398f9840f,0x00047fecda78c001,0x000046b3d3b3ce05}, {0x00019a980d309162,0x0007384c20c42717,0x000c786084549710,0x000a4c8f8f94785b,0x00008c7d484477e2}}, {{0x000176788a2ffe41,0x000518e169a5fce0,0x000f9c93adc506a3,0x000e07fea108617a,0x0000ed2436113fa0}, {0x000aa92a3d694e78,0x000d6f50bc7496ea,0x000114db4c0f43b4,0x000fd44e6aa58c64,0x0000218e8eafc000}}, {{0x0005dfb185f88448,0x000a9557abfbac81,0x000bfecdfcd7e90c,0x000c49a3d16655af,0x00000f3271f885ca}, {0x0009aa7d0e62f477,0x0000d60a48e57fc3,0x0008f101e88d519d,0x000815e9559ac4d2,0x0000981d9ea3a9ae}}, {{0x000652c9ac382032,0x000f37657fe55c38,0x0001f541686eaf87,0x0007b5368fc472e2,0x0000afff39d07e59}, {0x000bb07256d4eab9,0x0001f285ab893adb,0x0001caefe2259869,0x000c8aa5f8112a04,0x00005df02e435064}}, {{0x000356ec7004bf30,0x0004db83c7de4d63,0x00009a7b7230a08f,0x000d2dca27b27087,0x0000d1c4cc4cb9ab}, {0x000c66e7550fee88,0x00071cf7247e8a0b,0x000b5b7e7369cd4c,0x000f7af5562e8492,0x0000fed0da0d802a}}, {{0x00091c2e48fb8898,0x0002fb8a9d066a70,0x00082a0e226882c1,0x00052d224986631b,0x000044ed736b5181}, {0x000476fd86e27c75,0x0009b4afefdc282f,0x00019e34da04edac,0x00078b3b256ebc61,0x00006a413e95787d}}, }, {/* digit=19 [{1,2,3,..,}]*([2^133]*G) */ {{0x000061d5a74be506,0x00047ea16ff582ee,0x000bfc8a2e41781c,0x000e2d80b0c81e99,0x000024f4d696b547}, {0x000545dbdcc9ae4f,0x0005509b1e8e3a83,0x000c935392573dbb,0x000797582960c4a6,0x000001059ae4ae18}}, {{0x0009f973112795f7,0x0007284e6ee1715c,0x000b66bcde824443,0x000bede5cb4858ec,0x0000c1367361baff}, {0x00015955dbec38e2,0x000c188ad1535466,0x000e0952f51c0782,0x000fa87ba4c53ac6,0x00007e6782a3b21d}}, {{0x000903d4ed2dbc25,0x00082c3b2d83682f,0x0007e93350eba59c,0x0006d73e9dc84d9c,0x0000f9b21b05eb22}, {0x000d394af267bae5,0x00056e2e15aee33b,0x0008ec500aa86cc2,0x000657ff0bf67d6a,0x0000846aa4549630}}, {{0x0009740e2c2bf152,0x000589e99704feb0,0x000fbc565627a220,0x000de8cc8d73d0c2,0x000023eed8fe20c8}, {0x0002583a8363b49a,0x000929c2b0a61ee3,0x000dbc85c1a0b6cb,0x0001aba9f7c3d290,0x00008dfbb97bef4c}}, {{0x0004d4c65c7c2aba,0x000742c5ea84afb3,0x0003c4ab51d4610e,0x0005c3e93f6d1b97,0x00003cdd7ea345ba}, {0x0004983064417ee3,0x000c7d6bdf2b6051,0x000f726c31459b23,0x000549f3b2c3415c,0x0000a82963562d63}}, {{0x000901fab192c181,0x000e6030164f294f,0x000246ba6ec5fcbf,0x000a0cd2e2fcb7e2,0x0000e7c88b3321a1}, {0x000dd93c92d88c5e,0x000d3106fb5972c7,0x000f60f1441c2148,0x000f30747dd4f5a0,0x0000d9b52b343960}}, {{0x00049ebb0a5b358f,0x0001ae7e2ed66c83,0x000a462dbb154c5c,0x000b68dad5eccfed,0x00002d6dbe51de66}, {0x000edf38665e5b22,0x00035b7f5723426a,0x000cbb386488a851,0x000878f5cc43b38b,0x00007ad0af3f791d}}, {{0x000236e846e364f6,0x000c7ea50ca0c16c,0x00026b86d7f33527,0x00070c6481077509,0x0000c2a36096598e}, {0x0005e52f024e9245,0x00044db4afcaa675,0x000831790e0fa07a,0x0000d5c5c3ce7d66,0x0000b4ef350f6cbb}}, {{0x000afc4b6205969f,0x000206c7854f2c4a,0x000983b4842563f0,0x000754116aced51d,0x0000eb356d989949}, {0x0002c81d1a39bd77,0x000f76934ae98c2a,0x0007904da8f44340,0x000925a48cf91c44,0x0000340185f7f51a}}, {{0x00000fb7409ab463,0x000650e289b22f8f,0x00088e5d1057e78e,0x0004e1d3e5022ca8,0x0000c87111acdede}, {0x0000e1c7809460b4,0x000231c9abc75b9b,0x000cc1dc9e751c85,0x000a084b944e28c7,0x0000f201ffa5d3cf}}, {{0x000905c3e6721cea,0x000a30b3674c02fc,0x000810da4d52d70d,0x000d98bdc2e5ca18,0x0000984b273fc69d}, {0x000252784de5ca41,0x0002b852dec463b9,0x000e3de092f1c987,0x000c2f08b03593c2,0x00009d70b01a813d}}, {{0x0006b2da6dc1d29b,0x00094871e1444280,0x000f49276d303000,0x00004af1feb333aa,0x00005583b9f770bc}, {0x000be7895695f204,0x000149d012b51db0,0x000f61643fc84181,0x0001282409f27205,0x00000d3417515883}}, {{0x00096f5674198335,0x0002363b7b08d791,0x00056700c6059e25,0x000ec434da18171c,0x0000758ee57028d3}, {0x000771d013b0ea65,0x000b04c5e9b97da2,0x000305d80fddf524,0x00063f2df4faf824,0x00008f5c1bf8a977}}, {{0x00037f17c696042c,0x000b8a2538dea5af,0x000a42600d4cba22,0x000888611cb9959e,0x0000d105f423b069}, {0x000cf19ddb81e743,0x00092157b8cab1e1,0x0009db885472f2d8,0x000130d86fb008ee,0x000065cd5703f26d}}, {{0x00002bba2be70539,0x0005eab9a6d6284b,0x000f7a530dcbbf7c,0x0007c7b425559c20,0x000061f2dfaa8876}, {0x000943570dc80c4f,0x000300784120e2fd,0x000567122104d6b6,0x000d768f592bc153,0x00006bc1247e688a}}, {{0x0004c050f15dde91,0x0007fd5f2b820521,0x000e82b62a47a76a,0x0005eeab254d3062,0x00001a05fe04ec95}, {0x000f46e9d529b36f,0x00009f9e3df67eaf,0x00031769855ab130,0x0007acd463e37199,0x0000d251439bcda4}}, {{0x000354723d695ead,0x000d46e589b5ca9c,0x00087d08648ce626,0x0009479b5b64c7b1,0x000002e179582207}, {0x000e98f7198111d6,0x00057cf9c3cc8b58,0x0004089b090ca630,0x0000fef691fe72f3,0x00000941af25c7c8}}, {{0x000c0a222eb51e58,0x00042a9cf09aa09b,0x000159f06c0bb724,0x00060db6a8077f80,0x0000b5c989f5ddc5}, {0x000f316512e1f433,0x00047d08ff6219d2,0x000d20b4e02eac55,0x0004e0d12ab84c07,0x00007d1e11606d4e}}, {{0x0003e1aab7b19a8c,0x000e1ef8cd45b644,0x0005e03daf08d067,0x000915a3adf3e968,0x0000f15a10f0792b}, {0x000cce5b738a4250,0x00059636b2fdf44b,0x00050d605ebe131d,0x00049d9406884178,0x00009684eaab40d7}}, {{0x000669c72ba075b6,0x00055a4690158c3c,0x0009f8ba889f78b5,0x000ed6f706aade3e,0x0000d8bd566132d7}, {0x000e63b805f08d67,0x000d53bcc1b525f4,0x00025d8477f48200,0x0000a7de801968b0,0x00004afac04f7cbe}}, {{0x0002c2b7e63d6900,0x00000223cdb843ed,0x00084d3feefb6bbf,0x0005a44fec3cae28,0x000065ecce6d75e2}, {0x00094ce69f790713,0x000ed44b86666c22,0x000b69d8f0d9a8e5,0x000af72009f23817,0x0000c29f8fef5dfd}}, {{0x000528febae68c4c,0x000170c5ba219067,0x000dd1aec5b38563,0x000c77940df1191f,0x0000f37825c8fba4}, {0x000f980beb11454b,0x0000b0c1b06677ef,0x00089a1c740a1a99,0x000be038018980f8,0x00009c52aea26c24}}, {{0x000bcce45650ef47,0x00001aa29ac705fb,0x00004c470ae000f1,0x000c25184b71724f,0x0000cd4fde289bb5}, {0x000b22ae88408697,0x0008efbd06866477,0x00016dfbaa886885,0x000776823cc02e11,0x00006cd5640487d7}}, {{0x0007598a9d82abfd,0x000b16c170f5e2a3,0x00066b0875f188cc,0x000ad9b168220050,0x0000a22c21397155}, {0x0005d3afbddb4799,0x0003dd715b99151e,0x00097cb2e4b606b8,0x000b65ba73b54bf9,0x0000a1bfe43cecd8}}, {{0x00028092a67d48a1,0x000df31fa9e21c31,0x00043a34acd6a671,0x0007d3aec3312a0e,0x0000d93563965ef4}, {0x00024898fea73ea3,0x00047035afb25ea0,0x00065b54c8247b36,0x000148858300a652,0x0000286662fa22c7}}, {{0x000d76bb4ec4c20e,0x00062f3fe3fdb77f,0x000d8c7e8f0a12fa,0x000aa81845bbf541,0x00004d969cb3ec10}, {0x00053b743e232a3f,0x000b47f8a45a4c00,0x000d81c8fdc7a3fa,0x000aff4c4261c520,0x0000d4b3454a00ea}}, {{0x0008f86d36e30622,0x00078143ff0276d4,0x00076f42e626c527,0x000eac338174deaf,0x0000267aa868407c}, {0x000635172e572d59,0x00072a7330ebfad7,0x0008d8657ab861af,0x000a5210a1c8c741,0x000088821cbb0289}}, {{0x0002522cccc18ad5,0x000da1a6e0277973,0x000c2354daadf3f8,0x000689a7382c9317,0x0000ce1680d2818b}, {0x000bbfcd9ecbee97,0x000bacae62ac359e,0x0001ac38a4330689,0x000ee8455ce5b4c5,0x0000921dfeb6e238}}, {{0x000bef8271d1ca55,0x000798aabd183972,0x000a3e5e33e423bc,0x000d6607b09f3f44,0x0000da886aecb444}, {0x0006634a99643755,0x0003199cd0ff6820,0x000a515e9356a2fa,0x00079a5f0faa24db,0x000036e1f5d0321d}}, {{0x000913a5c04e4ea9,0x000e46f11513d3b9,0x000fd1d94d549dcf,0x000c675e227bf579,0x0000f35afef443f2}, {0x0008d24f1314f53b,0x00081abcd822d263,0x000f48db062baf94,0x000bb1a542de294e,0x00003eb6a05ac5f6}}, {{0x00010ae1208e16aa,0x000558363e2423c1,0x0004be00b1a4d15b,0x00090c9071684416,0x00008e2482596f46}, {0x00073a290b170cfe,0x000062f191f45487,0x00047aa97a1bef33,0x00014690f418d092,0x0000a06028f28be9}}, {{0x00022f3dbfb894e2,0x0006ae274b18e131,0x00058aadfbe9b79f,0x00035165a49de5ca,0x0000495775831487}, {0x000ef61bb9390993,0x0009f6d13694111d,0x000fc253b1d6a974,0x00015e1474b4ced3,0x0000a1485e67c5db}}, {{0x00067b4147c15b45,0x000b2bc61301e796,0x000094381e34f553,0x000a20b32b80f817,0x00005d8bafdc23ea}, {0x0007995f1c0e74e9,0x000e5bba289c5a98,0x0004c82515a9b292,0x000b09b13cd4b2eb,0x00008b5d2446162d}}, {{0x000bf66683425204,0x00097aa862d1bb47,0x00006abcd08d6894,0x00000dd1f349c7e9,0x000054ce9862d7bf}, {0x0005c9eb55b803b2,0x000a11e3c16dacab,0x00073bf12b03468e,0x0008873c24213dd2,0x000011538eb91587}}, {{0x0004a2f731dea2d9,0x0001e4ed7b2a198e,0x000a664fed5856cf,0x000290f6a632eb13,0x000032cd90a4da41}, {0x00095d4c0c4ddc0f,0x0007447fc2c9850e,0x000076bcbc0f422f,0x000285f68cbec486,0x00009e7c0c1bd6cd}}, {{0x0004ddb0f5f27cac,0x000ae80d59ff6599,0x000601023e85461f,0x000bfb3f05481a66,0x0000665427bbc9eb}, {0x0001a697587fd52b,0x0007dd49efceb057,0x000420688935289f,0x0006aeb1becc60ea,0x000022639d9c3a78}}, {{0x0006220361ecf90e,0x000f455064631a8e,0x0005c2b79001f23d,0x000db504ae9b5d0a,0x0000bc9cdaeb8149}, {0x00064a1934aa7289,0x000e1e9b60f3b331,0x0009cfbfd750eb00,0x0007f5ca91615b9b,0x00007015cc07f45f}}, {{0x000c4a5bf5151dff,0x0000c07118f2b462,0x0003fa42c21adcc4,0x0001aae60c545b04,0x0000c21aa55d96be}, {0x000c32f4e51ea80e,0x000f459b5d8de84b,0x0008f1b5e3dae45e,0x00017cdb73c7ebc3,0x0000405a74bc8ae6}}, {{0x000e9c69f1c56bdb,0x000799f196a4bb1a,0x00075092b8c176b9,0x0000331448f31168,0x00005afe3df4f976}, {0x000fd49145813e50,0x0009e2b34226a8da,0x0007ff57f687fc4d,0x000b46f2dfc92d4c,0x000004e3fc1401f1}}, {{0x000dab61430c9ab7,0x0002b238e9975afd,0x0008042ae0bdd41d,0x0004cb8094743041,0x00001f9addb3dddc}, {0x000c016c52dd907b,0x000c79e2047f7090,0x0001011a6d9bdf44,0x000c7836f1fe801b,0x000063accbd89acd}}, {{0x000e2351272a95b5,0x000756276ac8cfc7,0x000d7eef70c66771,0x000b3dec0d3709e2,0x0000add2b06ea685}, {0x000d32d14ea5d65e,0x0005ad7dd506363a,0x000b4aac6f8e01f0,0x000465e9ea221375,0x0000d2a2bf9ed353}}, {{0x00079b5e9d3a7c31,0x000671b7f34b439d,0x000c4ba758e0ee5a,0x0000c7bf3dacf51d,0x0000d3d1773fb331}, {0x00071127747ae836,0x000fb97d6b40a8e6,0x00096140031f4315,0x000767a521cceecd,0x00007246f1256535}}, {{0x000cc5aef0c31335,0x000d2e16693b702f,0x00029b749247cc45,0x00020fad484e49c7,0x000022cef7e02183}, {0x000f40559ab93b3c,0x0000df181071e56e,0x000330ed0225fba1,0x0002f673bd659515,0x00004be69d5dddb3}}, {{0x00076680448087c4,0x000f31432dae264c,0x000f9bf47ac30903,0x000d02f851b26600,0x000000ed311acdd6}, {0x00079fef8fd24247,0x000a8a6da98b045e,0x0001e673afdfd974,0x000167d5c9f6410c,0x00006f2e733cb2c5}}, {{0x000ebb52a6017539,0x000c357c2d491ada,0x0000bfd24b286514,0x000922487696701e,0x000050c547e94478}, {0x0001969e5d32bfe8,0x0001f50d6c3ed1d4,0x000e27f3a30bc147,0x000e0c0f3679fee0,0x0000f64a7dd24a6e}}, {{0x0009937633dfb1fc,0x0004d77f25472fe5,0x0001ea646ea82c39,0x0004510bdfdf1a66,0x00007ccc59279085}, {0x000796281761e131,0x000f8196885c8217,0x000ffbd70da57596,0x00036fac17e84928,0x0000e6e0a413671d}}, {{0x000872c4152fcf57,0x00002e77e75461ae,0x0004dff09441c87b,0x00017160799dd5a3,0x000066b4e44f8a6b}, {0x000a51211f1c7924,0x00030be35c3edc06,0x0000c469eea02ae9,0x000f5ca5ca4d6de9,0x0000df4368e96e4f}}, {{0x000acab4baef62e3,0x0002785b91e87817,0x000e576109f5a220,0x000e036666ebe66c,0x00002ad31f4273bf}, {0x00030a425bcf4d6c,0x0002915056e66283,0x000332156ea95059,0x0002d699811c89e1,0x000089cf1ff4c11b}}, {{0x000391304e60cc0f,0x000c5625d37575b6,0x00026e562ce811e8,0x00069f130e43fc2d,0x0000bb30b4c508d3}, {0x000f82c485281182,0x0005ad285911634f,0x000358f287c6fe08,0x000c095f2830c099,0x0000e60a95e865e6}}, {{0x0007d3d9b785dbf2,0x000b8759bce70840,0x000f61239530889a,0x000e3cd228e0e652,0x0000b6d14618879b}, {0x0002c0451a7bbf7f,0x000f86f24a64e690,0x000bc6da030ad99e,0x000abf76d9317a98,0x00004f877f4bb596}}, {{0x000f62d4c44f1190,0x0006e9b77416b05f,0x000aed63b4555f53,0x0002a9c7c0d0598c,0x0000cd2b7cec358b}, {0x000287b46945fa35,0x0000867c87913f33,0x00037bd08f8785b2,0x0009d7754a7a6196,0x00004d4598c68be7}}, {{0x0005acbc46d7ce17,0x00071b085877889e,0x0007a50509a515bb,0x0000358ac1a03d0b,0x0000d3e738b62926}, {0x000c2ce2a6cb0ebd,0x0004bf7adc79861c,0x0000163766f2e295,0x00008f91c4d45133,0x00009fd2c812ad59}}, {{0x0003738b2b836a16,0x00001c0d6622e5a8,0x000c19af1855b41a,0x000acab86fe3177c,0x0000465c2005dd99}, {0x000c23f6974b99e0,0x000ba2717cbe46e5,0x0002be65875a7cf8,0x000c984d2ebc3f06,0x000094b44475f209}}, {{0x00085edb940cb5af,0x00018cc82f104af2,0x0000526fa6706d79,0x00013fd8c8776c03,0x0000a8e6f7790da9}, {0x0009d34591ee4f0d,0x00067027416677ea,0x0006714575f46e33,0x000fe14bdf98bbea,0x00007c08b47562a1}}, {{0x000303c1c08ad635,0x000ffc845e7b46cc,0x000f36bf79954343,0x0003a6cb8fbdb548,0x0000b82c392dc827}, {0x00012c4928435d5c,0x0000b933038008f7,0x000da054a071cf0f,0x000b5c074c2d24a8,0x0000b0e720203c46}}, {{0x000337ac0b7eff35,0x000e75e48b3c0ad7,0x000f13a5f8552225,0x000cbe96f78b0c73,0x0000e70062ed2349}, {0x0005048e7073969a,0x0009233cb3d26b8d,0x000caa20f392d2a2,0x0007074e4f727c4e,0x0000068c99ecccde}}, {{0x000651fb87a29137,0x0004ccc252f0fcd5,0x0006cd3e4ea3e3c1,0x0002e7077d92df3b,0x0000a41414435a73}, {0x000951aa71ff4939,0x00022bd37cf6a895,0x000cfeefffe980c9,0x0003e8b5bd5e64de,0x000010dc2aa344c4}}, {{0x0003f26cca9f54d3,0x000b6303f6dbcb40,0x000eee67c928bbdf,0x0001c30c37951ea9,0x0000bd61a5327996}, {0x00038e6395c9a791,0x000d51eb352d09a2,0x0008756316940ca2,0x0000d16d1e5c5ec1,0x0000e19742c2e1b2}}, {{0x000d90823fc2e6e0,0x0009089591494633,0x000ed7da5a76e29a,0x000d5161069d9c84,0x0000baa11cf5dbca}, {0x000ec64961849da5,0x000f5f3d8c28d01e,0x000a2ee4493b75f1,0x00055807bc4f9f1c,0x0000a26322d50e00}}, {{0x000d65861a023efa,0x000419e5246e1888,0x000563ec01d72aab,0x000a4309a26348e5,0x0000097196463439}, {0x000d54badb9b5b76,0x0001645a524b567d,0x00038e60873fac1a,0x000f482fe97ef7fe,0x000008748d29f384}}, {{0x0001794c486094f9,0x0002fbf3a8d6b057,0x0000b0e25869254a,0x0007d7848a8dd131,0x00009ab9f402aa3f}, {0x000c68a6706c02e5,0x000c19790e6c0927,0x00071376c22b5e76,0x0006571c3252606c,0x00003a5769059ef6}}, {{0x000f852edffcf3a5,0x0003ec0a6f558d63,0x000519b9eb4d2ed0,0x00069a8b3aa8de12,0x0000d38e9c46e0a5}, {0x00028bf303747e2b,0x000c45b5c18d8715,0x0006bf923a208e77,0x00039eed129c88ca,0x0000cbf19806f028}}, {{0x000f030273231941,0x000b239ca59d9b9b,0x0006695203b055a8,0x000f24a46b23120f,0x00009789f1f597e5}, {0x0009468aaf018013,0x00005b69d59c9c49,0x000f4c07972ee119,0x0000485bd39595ac,0x0000ee11ecebe0cd}}, {{0x00086ec1ed66f181,0x000bc61fce43ebde,0x000bed74d225d906,0x000ab74cab07d6e8,0x00006e4617f37855}, {0x000aaddb2fbc3dd3,0x000f5aeddf5b6568,0x000cf2fadedb5484,0x000699578f20e86d,0x0000516497c915f5}}, }, {/* digit=20 [{1,2,3,..,}]*([2^140]*G) */ {{0x0003fecfa181e695,0x0000e0d69a98ef0a,0x000eab95d9ea02f8,0x00002162e9cf8e66,0x000020f2beb74720}, {0x000540a1df843618,0x0000f1fa6d5d621c,0x000f5f6ff1203772,0x000ef2ee3c7b510f,0x000017a069c2bb2b}}, {{0x0002fb6b294cda6a,0x000519039f348357,0x0005cbb216ce9bf7,0x0000d980e012f009,0x00000aecc1c7063f}, {0x0001c3af02909e50,0x000f48ce9cdc57c2,0x000e336f8c7d59ec,0x0005f42732b8448a,0x000056e37233f4f8}}, {{0x000b53189e800ca4,0x0006d45208fd8a10,0x00014ba3750fe0c1,0x000acc5e43c0d3b7,0x000027d200e74189}, {0x000e24fe616e2c00,0x0008ee1854c105de,0x000342a739c25f4c,0x0009524d3222a58f,0x0000807804fa027c}}, {{0x000653a4f0d56f34,0x00078a28b805c222,0x00073434b961e404,0x000a18ec03f8b04a,0x0000c966787eb712}, {0x0006c42864fee422,0x000a3b0ece5ccc19,0x00031c159c1be93d,0x000655887d9f22c1,0x0000bb6d593fce45}}, {{0x0009ec9b809b7ceb,0x000b32c72c2c22c4,0x000a0bf368a41486,0x000c68d13b9420fe,0x00003d36eea566da}, {0x000c08a328cc987f,0x000b4a3264616fdd,0x00010dbba0a3bcd2,0x0004c38103c49dd8,0x00009d81a293b78a}}, {{0x00065ade4d559419,0x000da03840873de8,0x000f18b9bdedafa5,0x000267df414abb4e,0x0000ee9ea438aee5}, {0x000aa1637a55a4a5,0x0003b15f93b9260f,0x0009c3598eb19a51,0x00078e01d7ebd29e,0x000023fc56d69321}}, {{0x000070cb98fe684f,0x0009224a1458501d,0x000bc6b3fd60fbe9,0x0007cab45761c892,0x00005384859ee6f2}, {0x00071f7b59e763bd,0x00088b5a8e5e4b02,0x000a482923d4606a,0x0004454eda5d9b05,0x0000a7731d1b6fec}}, {{0x000369390d458714,0x000fc6166d8da3e3,0x000a90403e976403,0x00063775c3368289,0x0000bd17983b2f1d}, {0x000679ed5d2c53a7,0x00088dcf3b87a616,0x0006a694e5ec4bcd,0x0007e53e6d7613b6,0x0000460fc7753fc2}}, {{0x0009b8295caabee0,0x0005889501e37046,0x0006ed265de024ca,0x0008b26bdadc0607,0x0000cb1236b5a0ef}, {0x000ddbf0972ebf9d,0x000452aca4324065,0x0004aff76f1dd387,0x000d23d88b97cf74,0x00001359afece8e3}}, {{0x000ba2b91502cf37,0x0007984db75d52a3,0x00030b1c92c3832a,0x00060b94a12dddde,0x0000802eabd531fd}, {0x0007327a37fddab7,0x000b8aafa9733370,0x000e6f91a65d6f2a,0x00030ac525c5b811,0x00006aeb0c9cf465}}, {{0x0005ff62f93a6750,0x000405f48679e881,0x0008ae884a6ec968,0x0008736dcbb55635,0x0000af61472e19e3}, {0x0004372a5f696be1,0x000a5f22fb707233,0x0006cea90c65e57e,0x000b2a168da30c94,0x000036a8a8775681}}, {{0x00081dc0f9f44d43,0x000ffc46585aad5e,0x00047d1b1f09a695,0x0008b1a1649164c4,0x0000b4b36c8b79dc}, {0x000177b3b6b234cb,0x00046730d9d020d4,0x00080531d096a250,0x00095c5611b9b8ef,0x0000a904b3c14bb4}}, {{0x000d9d493a3147a2,0x000c7a5655451192,0x000f072129f30a5d,0x000c1370b1f9cb6e,0x000099585462d87f}, {0x0003effc17db9ba2,0x000cab1644a8d332,0x00049ffbccb18548,0x000683f8a306d44f,0x00008d658f16c2e8}}, {{0x00060cda99f8c71a,0x000aabf742ff44ba,0x0004b3f9967b7abd,0x000160c6310f9c91,0x0000e430a339412c}, {0x00076d388ace52f4,0x000412d7067d1e67,0x00007cd1b4bc0fa2,0x0002c0c3c286aa8f,0x0000cb8f38ce985b}}, {{0x000be808c3bff364,0x00021263e57583cc,0x0009bdcd1005a0bd,0x000b6b060d7dda25,0x0000a1c56433a5ca}, {0x000dbb99fe4fc88b,0x00081c97bbb52b7b,0x0002321ae09418e2,0x00064e28274fb4a1,0x0000137007e0c87b}}, {{0x0001fe1c63c4962c,0x0008d81fdb258053,0x0004c2b6b50541e8,0x000fca1c1291a1fd,0x00000693a1866df4}, {0x000604e0117f203b,0x00025a99b8d0b2c4,0x000212c44245f196,0x0002a7fedc20aac6,0x00001ed4e57020f5}}, {{0x000f575f8547be3b,0x000cf9e45f98fe48,0x000c501000a7033c,0x0001d99b45d3a918,0x00002a6cd6b561d4}, {0x000b4f557933c6b8,0x000cab0d7ffc60bb,0x000d626b6a7538eb,0x00025a1ea3ab8d8c,0x0000273a484b6016}}, {{0x00098450168e508a,0x0001f9a94abd8885,0x000b0a6718cbc9bb,0x000ffbd13ac792fa,0x00003995b1a0c9eb}, {0x000668e1239e1525,0x00086bb8dff4e711,0x000f179635689255,0x0002533bfc7dabdb,0x0000b59fe5b03de1}}, {{0x00020eb34a9f7aec,0x00021751efe47e33,0x000be2f37e5e8cf7,0x000ef6bea003bcd9,0x00000f551a176c08}, {0x0006268038f67254,0x00052d92d3b65660,0x000cbd6861dd38e3,0x000da7c7dfce7cc3,0x0000e549e04a51c5}}, {{0x000f93b08b193400,0x0004cac6d89d4058,0x000159cc7c2fae6f,0x00001c4bad8a8c8f,0x0000ddba4b3cb0b6}, {0x000c7b51dd95f8c7,0x00075ea5c255da4f,0x0004a8c4c1d163cd,0x0009cdc0707d0627,0x00009d9e0089802e}}, {{0x0009ebfe6ddd5053,0x0004850bed1a02a2,0x000327d5737064e7,0x0000bc0f6bae65a7,0x0000846f5f228392}, {0x000749160df1b9b3,0x0004fd1da29f87c3,0x000d1743c4cfb289,0x0007c5e0a478ca4e,0x000090c60306edd4}}, {{0x00053128c0a78de0,0x000a1e85df708f3e,0x0001b6582ccd02bd,0x000bd1d6c75c03a6,0x0000762921cfc0ee}, {0x0000823d85010c02,0x000ae044cf1fd34d,0x000b5e78ad73aaac,0x000f3fdb4159bba3,0x0000287c7f805826}}, {{0x000f742580b1a014,0x000d20423b794aea,0x000dea144f080415,0x000472a12622cda7,0x00009ea499699d62}, {0x00091ef571f3913f,0x000405b25a8ab429,0x000b79e8f0610f21,0x0005a157adc58530,0x000090e3df6f7a06}}, {{0x0005deb43e2e0349,0x0003b44024aa5d0a,0x0000c9f7f53fb5a3,0x00065618628c686b,0x0000c69c29d3c563}, {0x0001febbace47b69,0x00090ea5a2ec5a23,0x00063853ebdce028,0x0008a975da1fac94,0x00006812c52e09e7}}, {{0x000577157151692d,0x0008098e1c44d3fb,0x000399be1eb2721f,0x0008b7f050608732,0x0000a5a5512a979d}, {0x000d55dc6f567809,0x00037dc7a7f4737e,0x000941a03e20d300,0x00083972ce7301f5,0x00001ef52167d30f}}, {{0x0007fc14092d85f7,0x0005ec49e41a2872,0x0006a4d8172d223c,0x00087d37cf30a2ba,0x0000c08620a2030d}, {0x0004c7dfc588b090,0x00095874bbb00484,0x0004c0495728cd49,0x00058fcc1281eee8,0x0000769b5baec319}}, {{0x000228bf99c24714,0x000ad91eb110665c,0x0006d7024f2d8a11,0x0005a10594f494d3,0x000082ded8c0dcb2}, {0x000a9d8dadd48854,0x000eb1d2b547c958,0x0000af5507004477,0x000350ca45f6ef2a,0x0000fc739d66f8d6}}, {{0x000af27786f08a98,0x0005c2c2737f75cd,0x0004e26708700bb2,0x000fef055a71411c,0x000010188c195076}, {0x000d0c9abcd3297f,0x0007048108ebc251,0x000ceed30ae4c896,0x000ceccd146de718,0x00009d4f07bb986b}}, {{0x0008ed583fa1e08b,0x000e0eabd1fb5ad9,0x0003b11967780d33,0x0008c43330513c90,0x0000a11de9f547bc}, {0x00034da02c2d064f,0x000cb48de23b6843,0x0009089d87ecf360,0x00034b67a1b4740a,0x000028fa43aef367}}, {{0x00082cbea4570b35,0x000b55ebcee9f2a4,0x000694cd5ee65d68,0x000d32488d0036b9,0x00003edd0e987885}, {0x0003307beb9bc6d2,0x00077f5c6768e37e,0x000f2160fe9abb90,0x000da62396ccd551,0x0000500888c67336}}, {{0x0009ed9926fce430,0x000704da2930383f,0x0004cb227809dd1c,0x000b3830f6f5968a,0x0000d700c7f73a56}, {0x000ea33ab64a0652,0x0004f338df801825,0x00063f57faab9b73,0x000633f516100d9b,0x0000574395a47a6a}}, {{0x0000fb6700a1acd0,0x0003fd999681b556,0x000b4e1bae823fd7,0x0000a3da915d1f6c,0x0000d0301186ebe0}, {0x000b0c989fca8cdb,0x000b49da0e0b744f,0x00031d76f970d01d,0x0009695ad8c56479,0x000015737c0a659b}}, {{0x00033e8a8b484e77,0x00090a26dec7dc99,0x0001f0136b2fdbdf,0x000ddab349e9a49f,0x0000860368ee0fdd}, {0x0002c1cf9ad3e183,0x0007389f4e79d93d,0x0004ff1b66d6c5f1,0x000d8c4a544d91b2,0x0000e12a5ec2e16c}}, {{0x00074e9a56b872f8,0x000c7cf68ea25435,0x000560ef7a1ad550,0x000a8ae89e37d23f,0x0000c54b9cb49d47}, {0x0000a4a088ac342d,0x000b4576c6d046d4,0x0009689e9ec450c7,0x000717e589e31c1f,0x0000acf260388781}}, {{0x00037c6c8cb6b42a,0x0003196ef381a892,0x000f078251326fc9,0x00022cb5d56c6db5,0x0000cba2eeb1449e}, {0x000887a633c30000,0x0002d7cbcf7174e0,0x0006cf1becb6cd17,0x00099b309e81dec3,0x00007a18a6d60ae3}}, {{0x00026799edce57e9,0x00044f001d41b36c,0x000a1f2c652b892f,0x00070a4884ae5d16,0x0000b3294257fcc3}, {0x000daf2bd2e21df5,0x000cb2470a993120,0x0005db32e55298d2,0x000635bb78af6ca0,0x0000c76a331b01f5}}, {{0x00061fff8a4f29c3,0x0000a68f8d49aae8,0x000b1321c70dc924,0x0004ce660e649f81,0x0000d2c801bb792e}, {0x000f772425218760,0x000c416c79b1f479,0x0003e5bc90bed93b,0x000049a67fbc0526,0x00001e8e630521db}}, {{0x0006738c6f3431e1,0x0002d326754176f2,0x0008c877ce609cb0,0x0003cba10cff2d81,0x0000f0e75ce886a1}, {0x000ca641158544d7,0x0008fcb71ed0f4fd,0x000aa47555d777e8,0x000b3fcc233737a9,0x0000b4531935527a}}, {{0x000f68839f05ffea,0x000fcd82574edb59,0x000292d1b8f4f4bd,0x0000862ce3450cee,0x0000a448a1301ccd}, {0x00091b3f7914967f,0x000a2908a5edabce,0x0001042e74537f09,0x000a33b812421ef5,0x0000af5cebddc0b3}}, {{0x000fd874ca6b39ac,0x000c42efd342730f,0x0005c8edb70fb72e,0x000a512b4735f9d7,0x000011f21588278a}, {0x000f635bf3bfebf3,0x00043bd9601fc459,0x00020cb733a1ff0b,0x0005a399d12823c4,0x0000e9af3e26c291}}, {{0x0002c72b41c34403,0x0005b3039a5fe0c8,0x0008795a3175239e,0x000c60b1084b8a55,0x000028d0a1e001e5}, {0x0005f2ed3788a049,0x0005d6c11a9f0a49,0x000d692d625d8ff1,0x000fe465155f059e,0x000054fa107df425}}, {{0x000abf2e98aaa995,0x000046b0f88ad16a,0x00054026a90cd8ba,0x0006d2457f4782c1,0x00004ee0734a2af5}, {0x0009e5445b4147a9,0x00010a52816cbcf8,0x000b62e773d102f2,0x000ad7d808517e39,0x00002e25421f9169}}, {{0x000d871bb608558c,0x000e36d4ff9bd721,0x000f2763e60e4eba,0x0002464ba1081941,0x0000a2e45bf11ee3}, {0x00072ec2bfd7a5f1,0x000f64d0b12d66d1,0x000be70dc528a8f2,0x00083cd17f1e38da,0x0000d5d7316af939}}, {{0x000184adf423e315,0x00015edb1a1051b2,0x0005bcab9cb41729,0x0008efd054ca9362,0x00004396860f9899}, {0x000f6c4a54ae57ef,0x000ffe648e9d4e53,0x000faf6bc0ffeb58,0x000b8a0bbdaadc6a,0x000088ae7979a3bf}}, {{0x0001d44d2359ed9e,0x000313544ce2209f,0x00051e569ac68dd0,0x0000971378da47fd,0x00001abd8610cc80}, {0x00018d9343b6e3a4,0x0008740a1bae23ca,0x0003f3e67480797e,0x000dfc91f0c71753,0x0000489697046e6c}}, {{0x000105552a82e8de,0x000498460cdc8ca2,0x000037178b2caf78,0x000b576c1b7b62e9,0x0000fc09d2dbb514}, {0x000f9ee9113be5c0,0x000fb3f9271c5f2d,0x00083fc542fbda78,0x000141e09a81af8f,0x00006b138668afb5}}, {{0x000480f43e3865d4,0x0007dddf47d938f6,0x000205ff772dd77a,0x000ad8b2a8e9714c,0x00006d449d8dd088}, {0x00019ea185d706fc,0x000b07dd7f629266,0x000bc2031e47e02e,0x000ac927f120a78c,0x000018bef01598d4}}, {{0x0007a9c6bdf22da8,0x000f10dc82df18f3,0x000703651efbc432,0x0001a5452cef8e5d,0x00002887ba159988}, {0x0009ddab920ec1de,0x00030c3e8d3b7cec,0x000a88747d0d7e8c,0x000534645bc3954c,0x0000deaa2e17fd53}}, {{0x0001d936cc874756,0x00020d2383bd461b,0x000903546d92a52e,0x0001129abccb59d7,0x0000111a7619d14b}, {0x00084feb3d5f6126,0x000d00e828ec0ae5,0x0000870305ea69b8,0x0001fe0c07898554,0x000049cab050c482}}, {{0x000edcf8bdce214d,0x0001b6af736125ec,0x00038b9e2b5622f7,0x000a763e1227aa70,0x00000efb2747c20f}, {0x000f88b79df975b7,0x0005a999503e817f,0x00038ec46856bf28,0x000f6e44d5351f50,0x000040a52c66c42a}}, {{0x000bb152cbb1a3f8,0x000d97a834292e38,0x00066bb74c3eb99f,0x0008fc4a4fcbf1dd,0x000080784d74de5e}, {0x0004c1cb4e7a0be1,0x000dad15a72fddc8,0x000ec30e18780510,0x00073e34bcf1af81,0x000041e50a81a610}}, {{0x000571847be87ae0,0x0007f76a43720d95,0x00007c3d368a6141,0x000332f57e7e87c6,0x000043afaf85252f}, {0x000e1211552a4d28,0x00023b4d4ab4cc14,0x0003816a4b6dee69,0x000a2936ab74c8a0,0x00004001ae4ef394}}, {{0x0008344d795fb455,0x000d679f55a55bed,0x000ccdffc57326e7,0x000a0479533ce04a,0x00003473caf8993f}, {0x000eb93a13df4c82,0x000677cbe46f7906,0x000e4ccf8a73e51f,0x000dbcb1ab3ae10a,0x00005614508aa5b3}}, {{0x000f96211a71b27b,0x000abbb7fa3961ef,0x000d7f3efdf71412,0x000d29031ba6b82b,0x00000b9c41619180}, {0x0004552014cdde5e,0x000a427b4bbbeec1,0x000e988f3702c624,0x000d034b15e8c2d3,0x0000e3bcc6e84f7f}}, {{0x000822a42ac6c853,0x0005edf9f2b79d00,0x000de1e582db0cea,0x000b61a7cad2ab42,0x000046ed5265d6fb}, {0x00029951a2faf097,0x00000c25612eb396,0x000f564902fa8a58,0x000960c0ae04da7c,0x000056629087eea3}}, {{0x000f5c53d080847c,0x00089241d4f63609,0x000961a63cb081d3,0x0006fbf4fb381077,0x000020c5984eabb6}, {0x000aa7cf902f245a,0x0005ae536b1e3d40,0x000b3134f9cb1273,0x0001aebeda24da99,0x0000fbd9c69fcd01}}, {{0x000e30ac7088c7d2,0x00001207389f9a16,0x000407a535ab6571,0x000eaafb09547fe7,0x0000322f9d76fdc6}, {0x000f22d7430de4de,0x0006068ca9a9c0f2,0x0008e58681938269,0x00020337f1eff191,0x00003b5b636386f4}}, {{0x000f9803fbc43419,0x000fcb5eed4e146e,0x00082e41d359f2c7,0x0004c20f35744e74,0x0000a9ac3ed83b22}, {0x000a6fe91fc50ae7,0x000b5613fa7c9161,0x00032f15a89ccc66,0x000d0319268b14c7,0x0000cd6f4e32467e}}, {{0x0009869ce56b40e9,0x000c302dde98fbf7,0x000ee2cd7f93e094,0x000d425fe0c3a8ed,0x00000f3ffc14268f}, {0x000fd5608241aedd,0x000730b1afe881a7,0x000310d5295ab7ad,0x000c42701270563e,0x00003ffdeb1d9d9f}}, {{0x0005c91d11a8594e,0x000751cf6db8c8f8,0x000b5dfd02e74d25,0x000c85a29c7ca302,0x0000389cfbf49143}, {0x0006405941768d8b,0x000453bf825dd01b,0x000cd17e24510399,0x000e791c4ee16656,0x0000ea3c2846a037}}, {{0x000c06ed9a475207,0x000a3f8524044e1a,0x00087648afbfe18a,0x0000d8e615f8e280,0x0000301e47f29d15}, {0x000f9ddb299b9777,0x000b35b7831479f9,0x0007c90e776697a7,0x0000b4a0d674687d,0x0000afffe0403721}}, {{0x0003e4b28c22cee9,0x000779fd55ae5aef,0x0002a5d6aefb0ecd,0x000356bcea71320d,0x0000cfb5fa191db6}, {0x0000b57f36e1ac55,0x000ce6cafb7d395e,0x00008c4db008fa9a,0x0004773f6cdf7053,0x00001527a37e5ed2}}, {{0x000ee305bd213110,0x0002909c90d7ba0d,0x0008696d36ed41b2,0x000a80c5f6b7587c,0x0000db8eaa83ce83}, {0x000fe37b24b4b6f6,0x0007f22d1f0dd297,0x00098dbd9fe58afe,0x000527373587368c,0x0000bc226caf454a}}, {{0x000384ece53c2d04,0x000d1e4606daa12b,0x000ec12b0779d897,0x0001ad653e47b073,0x000062dbbba9756f}, {0x00009f2cafe37b68,0x000f6cce2e1769fe,0x000f607fd273d1eb,0x000c250ac1d5383c,0x0000035f7ff92e10}}, }, {/* digit=21 [{1,2,3,..,}]*([2^147]*G) */ {{0x00034c77e6c55202,0x000fbcb9ea58854d,0x00086666dc27df9e,0x000a85205f2369d6,0x00009d1febf2417a}, {0x000819e93470afed,0x000912a27f9e9846,0x0001e65043e6a966,0x00080954d008a2e3,0x0000ba7ced06cb76}}, {{0x000f541338d6e434,0x00030541d5ccecaf,0x000bc88ca56f7dd7,0x0002c375d426de96,0x00008d94f6bded3a}, {0x000a3bb2ef8279cf,0x000a1b1867f26354,0x000225151d575465,0x0000d7ff99b0ff95,0x00003e19d89e9450}}, {{0x0003268e32dd620a,0x000ec27849a292a8,0x000378882913ec99,0x000cfe4dd8fdfa2c,0x0000f96f33f8e6f8}, {0x00037e5dc3fa8a51,0x0001a0b03a1dc067,0x000f037b0236bb53,0x000a5323e59f2989,0x00003f9b5a7e9a12}}, {{0x000f6ce51efb3108,0x0004158df5be0d0d,0x000158e59cb5b2eb,0x00033656459e2936,0x00002aae2b99466e}, {0x0008a39411aa636f,0x0004e4c0a933fb65,0x000f026b77152ecc,0x00011f010c758a49,0x00004837f98bb093}}, {{0x00002c4c753c45fb,0x000649c840feddfb,0x000f8a3e618ca81b,0x000dbbd46fd09ab0,0x00001162ade97733}, {0x000ad20236e3ab64,0x000572a563267070,0x0007cbc7af88cdaf,0x000271c5fc871999,0x000042cd4528b665}}, {{0x000f364b71698f58,0x00021f7b605e7807,0x0003b2cbb6ba418d,0x00086f7d20b00fa0,0x000083eca385a543}, {0x000e43ff3437f24a,0x0002048bb33cff0b,0x0009df765e910b43,0x0006f6a963a12832,0x0000c1dd5575e2fe}}, {{0x00010f924a0a3fcd,0x00041881c3f95576,0x0000dac9938e17bf,0x0009179ba84fafed,0x00004a222c429eeb}, {0x0001dbe13f542b66,0x000d8425d457c79c,0x000ebb7791fc65e0,0x000f608ffb754f1d,0x000038d8fd0fe08a}}, {{0x000523a626332d5d,0x00028561bb44994f,0x000845ea27bc3883,0x000089305ed4b03d,0x000039d3ee292a1f}, {0x000fdd3e7676b0dc,0x000f3b7060176561,0x00064f9a8620e35f,0x0001f676ce424ff2,0x00004c341a09a268}}, {{0x000fd2f69beb6e85,0x00031d700d03fb6a,0x00083a14f3a50b99,0x000bef7840b2ad0c,0x000073207bea4085}, {0x00082e309fe7e5b9,0x0003ab40a7e15af8,0x0003056e2957678a,0x000c09872d4bdd54,0x0000c1b26b49df13}}, {{0x000861cf405ff065,0x000cf86e828b1c30,0x0006933fcebac86b,0x0009479791a97163,0x00000e7c2becaeee}, {0x000a095fa90d7679,0x000b5670ab7bc3d4,0x0007b056dae60eb7,0x0002a987633a6439,0x00003a21f33a0501}}, {{0x000370babb886433,0x0006f2e21599663c,0x00076167191df36d,0x000bf0e83ba8358b,0x000081eea1da28f3}, {0x000f1ba39966e6ca,0x000847295492b9b2,0x000b26b7f7c464a2,0x0009de6fd5f70a09,0x00009aba1fa9be00}}, {{0x0001f22369b87ada,0x000892fca556857c,0x000b064663c00e5d,0x000af17ad74cab90,0x00007112386f50fa}, {0x000e1986d9bd5f51,0x000849c3463f7435,0x0007bd4b22dcc7e3,0x000f31cc7df748ca,0x00003cd4c08adec2}}, {{0x0005df8e32377106,0x000e6bd2f7b00d3b,0x000aa082b0dadb26,0x00066e3f5966abe4,0x000066ec8de950e9}, {0x0001ed5ee5242161,0x000b31dab0b61bfd,0x00086d6bacd93c59,0x000195558a8435d1,0x0000b7d34d2259d1}}, {{0x000e46022caf46b4,0x000f5a96fe4f5936,0x0008f474e6a45dd8,0x000f15b7925434b9,0x000014104124053e}, {0x0008d1241de97bff,0x0000cd80bef471cf,0x000db0037b8547b6,0x000dfec47d3970c4,0x00001bcd329eef20}}, {{0x0002e0910caad676,0x000ff531a1e131a9,0x0004fc8401f59195,0x000c6bdbb852e05f,0x00003e297caf3a72}, {0x0000b2e49abad67c,0x000c2d3db0d93c2b,0x000ef1d406ec405f,0x0006fc1c14a5307f,0x0000cd19846e8089}}, {{0x00031769bb816483,0x0005353120d000f8,0x000cabc62d69eb48,0x000cb1a17d75f44c,0x00004a07f82e749f}, {0x000f787bbfb55541,0x000052e283f82c3a,0x0009213a0b06ed4d,0x0007b44722889fa1,0x000062b085eecf3c}}, {{0x000cb31e0dd3eca2,0x000cc52f13a5bcae,0x000bac297c6237fb,0x00054aac2b6b0327,0x0000ae1cac5d917f}, {0x00007d47845ae4f6,0x00026e5972e04748,0x0007915bbfec7dd9,0x0007ca63bd25411d,0x00006f85dc539490}}, {{0x000b888bdbcf0ca3,0x0006af279e9fd981,0x00054e934d75f5da,0x00034ae28bbf2470,0x0000c6ff6e5b1db1}, {0x0007cf4047d26e4d,0x00078049ec37795b,0x000d945aff370f7b,0x0002bbf6712d4dce,0x0000f30b5ecd9564}}, {{0x0004c624896246e5,0x00069e90bbd19b03,0x000fedb735652c01,0x0006139b38636f87,0x0000e32f8475135a}, {0x000b312cf933c835,0x000dca7f47e60703,0x0009c2415d05bb76,0x0006f8325e4f0c94,0x000069e5622c250d}}, {{0x000eb3a6568013e8,0x000ea2f243fcbbe9,0x00042734a8dbd203,0x0009841dbd7694b3,0x0000f6d12f8c6afa}, {0x00010a2c9eade291,0x000337dd0f18b986,0x0001c0d46bab4f32,0x00042a4779737b67,0x00000b6a7c6e3e0a}}, {{0x000ddf33035b41cc,0x000ed9c45895fb19,0x000c857e5d336343,0x0007d4a1fe493854,0x00004d506bf6e4e5}, {0x000c8cbbbc33f758,0x000a1262c77d3cd8,0x0001a28237281f08,0x000e32883f4ea6f1,0x0000895041f1fba2}}, {{0x000ea499c438edfc,0x0002d1edba44fcdf,0x000ba50f07678dcc,0x000c1b307b3b87e2,0x000013888f003948}, {0x0005ad41140af420,0x0003926ed1a7c213,0x000f6695f8e5104f,0x000120f24430cb88,0x0000ce0637b6d73c}}, {{0x00001e6fe631e8f0,0x0007d7bdd24bb2db,0x0009ad44f1c5563d,0x0009f98daea3ba36,0x000000c81b68187a}, {0x000a951aae1fd9a7,0x00071d5aed8a5f48,0x00098c622e35626c,0x000503b095276304,0x00006d17634e73aa}}, {{0x0000ddaeb300f7aa,0x000c4db5e80136d9,0x000d5244c9dcf7df,0x000aa1c45cb26874,0x0000127ee79d48e3}, {0x000cc53575f1dbba,0x0004e0e6161e488a,0x0002650d095037e8,0x000215b7e5928329,0x0000be67d99b4938}}, {{0x000944b3f8e10652,0x0006130e89243c7f,0x000530136ed908cb,0x000168e8ee8fd56f,0x0000227b7d5f7ffc}, {0x000c893b5cd6dd54,0x0001662796e84f55,0x00018e12c82225e1,0x00051a1c6cead1cb,0x0000381ae0cc4f5a}}, {{0x00013d37fafa4c8b,0x00015491aac03459,0x00069264c3d91808,0x0000cce347871f3e,0x0000ea9dd3d64f4f}, {0x000d0673eadd3e7c,0x00074573bcd8bda5,0x000a2486c0033c1b,0x000ee6655893795d,0x0000b89ee5c46abb}}, {{0x000a8f322532e5d5,0x0000227dfc4c8fe0,0x0006726dbb6410ff,0x000dc7119b9d5822,0x0000ec25669ca2b2}, {0x0002e064c3beb017,0x00000acea556af4d,0x00083487a852123d,0x0003ea9e9470faf7,0x00005a7ea04c664b}}, {{0x0008f356798e4ba6,0x000567d0e0914ad7,0x0002904039214e6e,0x0007496420b488b1,0x00004049e0b5c295}, {0x0005af13ae9841ff,0x0008c0b662a603ef,0x000453458dbe4ca1,0x00072156845c5ffa,0x00008dabf1a00b66}}, {{0x000f0aacce2793bb,0x000e15ec47c1b650,0x000234fa971db851,0x0006cd8eb78f3e3b,0x00000c60f36ac010}, {0x0007121774eadbd4,0x000f8e3238630542,0x00008697625367fa,0x000ad13541b5c9cd,0x0000ff069e31c507}}, {{0x00052568776e6676,0x000c523c6bb57414,0x0003a8a876e76142,0x0008367bf307121b,0x00000e7363ef8450}, {0x000450eb7366d800,0x000a4837dbdf5741,0x000d4316fe4ee14c,0x000825a765eb9b69,0x00004548dca8ef43}}, {{0x0004e4c5ae888eb9,0x0000c6e9ac999c9f,0x0006ac029733abb5,0x00038e4aad3c20ba,0x0000b8dd3d3bba3e}, {0x0004c920bc5d11a2,0x00077c5f88a3a9bb,0x0001d3cb8f20127a,0x0000a62f52b06e16,0x00006c1ff098afaf}}, {{0x0000d2f7189e71f4,0x00081ecf91e73267,0x000757a21c643874,0x000ce4d5758e57db,0x000027d09f8690a9}, {0x000308f38384a7a9,0x000420732b99846a,0x000845819aac3acb,0x000e030e94100917,0x00005cba11237ce5}}, {{0x0004f7fb00009c49,0x0006fff28b5f6f3d,0x00097975db8396c2,0x000ed521a9ae431c,0x0000d7ba8b075d9f}, {0x000f09f34f485b64,0x000c24122516338c,0x000d471febc0ddac,0x0008c96450da1205,0x0000c3a6250a28dd}}, {{0x000d103d1295837c,0x000f7807eb2f69c7,0x000b41491a2893e4,0x00023516e1e1debd,0x0000630745c1e138}, {0x000109e48661ae16,0x000b8a2b2674c892,0x00028d6b58d17e7e,0x000f9da0ec0f87c3,0x0000d8586465079f}}, {{0x000243e19115ead5,0x000dfbac4fcf6cdf,0x00029f25b1ce1393,0x000a04dc960ed09c,0x00009be4d8eed388}, {0x000e06cd0def72b5,0x000d903427480d46,0x0006d4a3db923db5,0x00099ea7d3aacd93,0x000058519cc5b0b0}}, {{0x000ebf8827097ef5,0x000b8054f55d3ea8,0x0002ed089259353d,0x000a7c34c89abc6d,0x0000c548b69de096}, {0x000f616994b995dc,0x0005e5845601d587,0x0001fd9f04d1531f,0x0006c9b92ab31e45,0x00008b57bb325adf}}, {{0x0000fcb1cd5ad73c,0x0005a144da4f6844,0x00062beb8b9c860e,0x00097e6ab286aa84,0x0000c6b9000af467}, {0x0000da420c8a471b,0x0000c7ff7fafac82,0x000b5da7769ae05a,0x000b7a09163f39bf,0x0000d03e590dc73a}}, {{0x0002b5eb2940d9e2,0x00062b9af5647e86,0x000e3033d3c663d8,0x000bc6b8309031bd,0x000098231b2f42c5}, {0x0000d2c552ad093f,0x000c0f8546954209,0x0001f0d00a4799d1,0x000b451a88b5d6d3,0x00008b4082692f26}}, {{0x000b1edf1bd72186,0x000aeb24c86eec29,0x00095ea65d491c53,0x000f1572fe588f33,0x0000f3764f7a456e}, {0x000116dcdc348009,0x000631e33955db43,0x000ab286bcdbcd45,0x000d7c5fdb554074,0x000048c7a52618c5}}, {{0x000aa377378058e6,0x0000a4411154eb81,0x000828ac741c746a,0x000b29410c73bcfb,0x0000439be91fd972}, {0x000b4b043a2fbad0,0x000f82b5e8404bf3,0x00097bd4c39e6dad,0x000ccb4f71640863,0x0000f7de5687f1ee}}, {{0x000c5a1d2ffbfc15,0x0009fccb64515865,0x000b32558f74211f,0x00012e16368a88c0,0x0000b539dc2ead78}, {0x00083d02f3af6f6c,0x0007d9934ece5794,0x000c9e9835213207,0x000b8990b9650fdc,0x0000a989eca6ee42}}, {{0x000c829d6f62f995,0x0008fc2a7c0c6a44,0x000a0cb0a8f06a30,0x000363fea2b3a098,0x0000c547b710eee8}, {0x00040e1682afe112,0x000a5b41c0a8461d,0x0000d5d369e0fc77,0x000f6359e4aefde2,0x0000916e52052dd9}}, {{0x00052e83f883faf0,0x00092b868d35f59e,0x000a19881396f963,0x0001a6c902a9df4c,0x0000fc96822db240}, {0x000758766f1c68d2,0x0003db476c0d4123,0x0001f5d9010fc6de,0x00044ad8b6b57984,0x0000ba8446d1a24f}}, {{0x000b920ef4a9975b,0x00037330435fa237,0x000b7e7b560bb600,0x00039126f4ab5acf,0x00002ac509833435}, {0x000ee2fb0d1ea67c,0x0009b4c56230f036,0x000838ae6ae779a6,0x0006ef99bff8c8ab,0x0000d83ca9a5b38e}}, {{0x000bef5e33deed3a,0x000e601892a8bb27,0x000dfbd3ee6356f6,0x000c9d1f3be6cc7a,0x0000ecbc81cd3d1a}, {0x000b909e6e861dcc,0x000393f5f801e4fe,0x000346e5790a247a,0x000c1a41c50acb27,0x0000e29242f061ac}}, {{0x000214a2f998a912,0x0001b4baf27b04dd,0x000c26722271ee9b,0x000ce55e3027d1e8,0x00001d1645c3820d}, {0x000242c7501779c0,0x0007fa0e8009086f,0x000187129f006140,0x000bd0f23ce47760,0x00005bbdedb0fde9}}, {{0x000483225d984730,0x00055c658427682f,0x00066ffa1f207fe8,0x00099db6fdd7ba41,0x0000c3140569eed7}, {0x000048f4107e28f1,0x0001312168400db8,0x000a3c06e74ed387,0x00013464489f8f56,0x0000e1c005b22777}}, {{0x0002a73f37ec3c39,0x000d4d59eba0db33,0x0004d3257c65259b,0x00038f9291709cdb,0x0000a793b264d389}, {0x000e34be43756f0e,0x000dbafb56c9f39f,0x000208b272f76bdc,0x0002c2bf37867a61,0x0000a1d4307e8997}}, {{0x00053308bdf623a6,0x000a2441fb7d8c59,0x000ddfd955f5accd,0x000be79afa941832,0x0000ad40c5a6fde9}, {0x000ba89aeca8709a,0x00008c248a9d43fa,0x000637a76c64a7cf,0x0001ba7662025272,0x0000ee1c791c2b8d}}, {{0x00098fd21a843b21,0x000d7d005cb1f0f7,0x0000d8abe56e4ed4,0x000326255f77801f,0x000097b04cf44522}, {0x000b31ffd42c13f0,0x0002b40f933d41f9,0x00060bad45ef7feb,0x000f8927326f425d,0x000027ecdb28c92c}}, {{0x000e4d14e3352feb,0x000ec3591b9004aa,0x000da7d6008414d2,0x0004ebaed6124eb7,0x0000985b931fd13d}, {0x000d3ab96bf36f90,0x0005bbdf51dfa592,0x0006c177d012dbed,0x0009cfa57963c0df,0x000010ec86987ca2}}, {{0x00000f6bf926dffa,0x000154bf6bc2ba17,0x000da11f57c9fdbd,0x000e753c18dc8f64,0x00006074b7b7938a}, {0x0000066e84f44a48,0x0008527b954e1427,0x000f38e9a99998d3,0x00001641be8ab2b4,0x0000bb55bbf95c01}}, {{0x00072b40ea2ab303,0x0000c73d68ddf734,0x000c2e1ebd365a34,0x000719901a716819,0x00002f49e3764061}, {0x00057f101d8b4d66,0x000bc6b47700b73c,0x000d8826a03c8423,0x000637d21d0bc8a4,0x0000004213cabc0e}}, {{0x00064a1c1c06681f,0x000eff018e50f78c,0x00042b2b316e0a16,0x000f5741cbdf91db,0x00008f4ffcfd0d36}, {0x00071cd4cc5e3e06,0x000a4129e3e0cdcc,0x000b2cbf1d55c7cf,0x0003cb6cdb6ba00f,0x0000aba000624bce}}, {{0x000db30d232cfc4d,0x000e058a3cef501c,0x000e091499ddcf12,0x00025632d2cf9c87,0x0000c5d7ec7fc976}, {0x000986e0b50d7dd6,0x0007207f112a6447,0x0000ae9f688fdbaf,0x0007dff8c9822ab0,0x0000abfb950cd3d2}}, {{0x00044878a429f4f8,0x000b5b516609d0a7,0x00069b5df0649712,0x000af23826ba57e7,0x00002335df29fc7a}, {0x000f0675c93d9950,0x000a68677be62389,0x000d9951b59ac367,0x000ccea77985ff21,0x000038956fb85011}}, {{0x00048cbbb734e37e,0x00014be5b26f608e,0x000b1a0d9c08c0bf,0x00031837bbdd3bf9,0x0000ac7d898f0483}, {0x0004bafbc1a6dea1,0x000f072aafdbc95c,0x00035c41afdd0e2b,0x0001d530373cbc82,0x00004303f220b6f4}}, {{0x00036210408f237b,0x000a3cd2d1edba06,0x000abb6a2cad3b09,0x00017a9667855a52,0x0000a9157dd5a8b4}, {0x00035074f013efbe,0x000aca38c4a2fe7f,0x000a643451b112c4,0x00080ac1406a609b,0x000053cba344993c}}, {{0x0006063ded40d232,0x000d34908e254546,0x0003c3c313d5f1f4,0x0006247ebefe6240,0x000074ea0b52672a}, {0x0008d99451d1b71a,0x0002ef79cf79ff81,0x000ce37f580e8264,0x0001fd0165df1373,0x0000744ef509e3a2}}, {{0x000e7f5cf551396c,0x000dc68c676b73f1,0x000442c36c616898,0x00017ca71c28c78c,0x0000fe5e5591e0a3}, {0x000d8187051f476d,0x000544f034421242,0x00044d0f656fad2a,0x000f4d562068bc0a,0x0000fa2cd6f9e6ed}}, {{0x000813ad15d15174,0x0001f77d44f50f43,0x00039b35f61214cb,0x000c199399aa29c6,0x00002136d7194c51}, {0x000711b084172219,0x0002c2545a579774,0x00050582d0a5546b,0x0005bbf0624c4111,0x0000ec5c4198bc55}}, {{0x000dcad771849f1d,0x000431d7bf6f2c87,0x000116eb2b0c932c,0x000bd29aa5cd3e89,0x0000378c25b21ca7}, {0x000a0da9e6e3e319,0x000d268ad5d0c612,0x000c6edb80417a54,0x0007cd70451e4a22,0x0000fbfe01a44282}}, {{0x0002505ba9384a2d,0x000d94ad69c12fa9,0x0003b35a621b8596,0x000671bf4fcc4998,0x0000e09376142754}, {0x000ccc8f7bffe6d9,0x000ecd94263d2f14,0x000f3ec3027566bf,0x0006ba25b4e9c62d,0x00004f1d7d5ce6ea}}, {{0x000851aaaca5e9b7,0x0000e6713b9797b7,0x0000a61f6518aa52,0x000b68c357e8c715,0x0000842e7e35c2c2}, {0x000af656868a5489,0x00025068fc818dff,0x000917733d963bd8,0x000327d4da5c8b65,0x000027091000b247}}, }, {/* digit=22 [{1,2,3,..,}]*([2^154]*G) */ {{0x000c9a7d298c241d,0x000986807cfd214b,0x00064eadbe3b697b,0x0009c51f1c780245,0x0000de8cdd084814}, {0x000f0a75a4d2604d,0x000e9c1538af946b,0x0005b1fcc27154d7,0x000f81c5cc9230de,0x000088519ea36864}}, {{0x000dd1a7cb1282c7,0x00064e46973ab828,0x00008d6b2a08d762,0x0003f2fbaf8d40e7,0x00002571fa1bdaeb}, {0x000732ff22dfd98c,0x00064087108d85b1,0x00088207a87ab01a,0x000754eaaafea859,0x0000cc832f929f00}}, {{0x000950e36ff3bf0c,0x000f30b34638964d,0x000d7585f8ad20f6,0x00019e8d9177b3b5,0x0000f839761af3f0}, {0x000c5b38288c545c,0x000a53116bd1582f,0x0002120ef2f8e4e9,0x000d23391e1b2f33,0x0000f568724ea17d}}, {{0x0001185ca8d9d1ae,0x000cf987ded2488f,0x000c46124adf2c77,0x0005f37f3039f060,0x00005d70b7651e09}, {0x00086506260e70ff,0x00070750d10582d5,0x000bac36439d75ea,0x0003289cf3d0b175,0x00003a7564e11d01}}, {{0x00004cd2f52d2a7a,0x000a42df565a182f,0x0009fb2f74fde149,0x000897180c5eeca7,0x0000b491d7bc2ddc}, {0x0006c18c6312c7fe,0x000c8aa41a5799d7,0x0005363a0ca0d5f3,0x0002c191207325d1,0x000082aa2669eb25}}, {{0x0004700ec3128c2f,0x00019e383f4994ab,0x0003024eb6c76d86,0x000c68ec36b150c0,0x0000b43947843daa}, {0x000764a8dc796230,0x000db440fbb2fc68,0x000c5ee0d5b86995,0x000bd3d66879bfcc,0x0000522894295aa8}}, {{0x00040a51e6a75c1d,0x00053ea7d817b51a,0x00077459724327c7,0x0001633663018207,0x00006fdbec467fa7}, {0x0009dfb13c90f48c,0x0002a86ef26320c9,0x000f64eebd6ac527,0x000c3206a50bdcfe,0x0000d87b28246fdf}}, {{0x000a43e3fcd3efca,0x000418088e9ab24a,0x0003d46eadd26c03,0x000a6f05ef4dc9bd,0x00002f99d592a4c6}, {0x000d3552f1da46cd,0x000d4afacdd1ddab,0x000d4057872c3f8c,0x000b94090c4eee92,0x000028bb4209a623}}, {{0x0000711745edc116,0x000cddc8755850fc,0x0009d1e649dd9ad7,0x0000f96e6931fbb4,0x0000c77a0a3298bd}, {0x000a6296baf7cb10,0x0001ccf72d2262b9,0x000639071cf065f9,0x00032f7203cce979,0x00009ae4885f9cb7}}, {{0x0003becee8314f30,0x000ddbea298f5e7c,0x00080acec1c068ae,0x00095b08d381f17c,0x00003b56be8e3304}, {0x000b8f29222882d6,0x000664af8bf7aeff,0x000c57d8c95ff38f,0x0004eff0e32d351f,0x0000635be5277b44}}, {{0x0005276a5177900a,0x00075685875204d1,0x00015796c4e1dbb4,0x0007bebb475622c6,0x00006fa038809186}, {0x0005d562844c6d0a,0x000a63a2477ded7f,0x0003721d6c633cf9,0x0008e656be5c402d,0x0000f312eb889fd6}}, {{0x00092d2e7417ce17,0x0001270ee7f52427,0x00067a41eff42bc7,0x000a57aff4dc6d5c,0x00007709b7b90882}, {0x000731dbe217f2cb,0x000cabb721773554,0x0001dd0592af2a8c,0x000476a8eee76959,0x0000b2930c9fbba6}}, {{0x000e0477d930cfc2,0x0001196fd1f4863e,0x0009af7e14c262ad,0x0004f6d4765bc803,0x0000519834b7ba10}, {0x0001b4cd105f961c,0x0005163bca547cd6,0x000a1f17ca5415da,0x00012bb78280a088,0x00004968949e3295}}, {{0x0009126cecdaa7af,0x000d1b13247b174a,0x00084c1c4fc8c7e0,0x000c3a39c110d234,0x00008eb8758731df}, {0x0000212c00674527,0x000e0b9b926c022f,0x00042daf43f6f69e,0x000de399032da0ef,0x00009f00adef3f80}}, {{0x000db7181236c972,0x000b1ee0781f6210,0x000e4137274f7685,0x00053e2df7da7ba3,0x0000aae38b1d1a15}, {0x000e222f6dd9d1bb,0x0007ab8b64871688,0x0002edeaa5769544,0x000569978d21274b,0x00002818fa5ce859}}, {{0x000dddaf176f2c08,0x0004625726581e6a,0x000342ffb01ca460,0x0008d58a404ded85,0x0000cf60f96c4183}, {0x000691cc9071c4aa,0x0003944428039bbc,0x0009c0d81fd58874,0x000f7ef7101c8580,0x00007fb754d2c456}}, {{0x0003c5cd51805e1f,0x0008c299dca8c95f,0x000eaf500ab4ccd3,0x0008924e03d20b47,0x0000a3165c2c7b80}, {0x0008b54e160e552a,0x0009f019d11f005e,0x0009a4a7adc4972b,0x000fd681a6972e0c,0x000052c258fd7840}}, {{0x0009ff4c1e99d816,0x000643c617c0f855,0x0008c6ba708e1a7d,0x0007945398fd4324,0x0000ffedd9231283}, {0x00059d2d629d2080,0x00053490530e8a6a,0x000505989a9d141d,0x0004ee42f6fc1838,0x00009bf250d479d9}}, {{0x000d3b1b38227904,0x000053b8971c223a,0x000f7fa626c5926c,0x000989209efc7e75,0x00005d66a6d5ec2d}, {0x000d663987d2792d,0x000c6eb31d2b4422,0x0002cb9e64a73caa,0x000a84206c2ac1a3,0x00009445c6061aeb}}, {{0x000a1d5af71013f7,0x00049bedc9466af7,0x0007370a0e68216e,0x0001cc84cba30bd2,0x0000981afbff7042}, {0x0006a679449f0e1f,0x000d1a47edae0249,0x000feca2286cfc4b,0x0008fa4073c936b1,0x00005694612f3f8f}}, {{0x000b723901515ea5,0x0005249cf038d063,0x0009e50594c6c77a,0x0007c01361e360ab,0x000096cf171f76a3}, {0x00053fa6530ae7aa,0x000d6792a7a6800f,0x000db81c90f5e631,0x0000b9bcc29c24ef,0x0000269e868df9c4}}, {{0x000f9e12cb7191e8,0x000865b08ea6ec14,0x000332bb978ea1bd,0x000e24bc65aa9b46,0x00004cc22b43f80c}, {0x000e9e9d49d5bf18,0x000599087da40098,0x000f6e357cd4ec1c,0x0004b7bc9d07c5ae,0x000039a02691f8f6}}, {{0x000eb62c6d8607f9,0x0004daa995e4c5e9,0x000b48317759689f,0x00017ce0464669bb,0x000021474c074024}, {0x000135b2a354c8c4,0x0002412fa4b5cabe,0x000311fe8d51e52d,0x00014bac74109653,0x0000f774535f8645}}, {{0x000d6715bde48f8d,0x00025189bc7dbcad,0x00009ee8ac970387,0x000ff78d45299ec7,0x00001287ee3545aa}, {0x0008874db1dbf1fd,0x000ac90c88d67d1f,0x000368313ea46588,0x0003ad90ba649a84,0x00005fdcbcf30d54}}, {{0x0006d43810d5ab00,0x000904d7e5cc90b4,0x000337c336739d8f,0x000c40021c1a580d,0x00000a6116268e67}, {0x000413b379f0a1ff,0x0004f9e2ab9595ef,0x0005f199cfe12660,0x00091277578b852f,0x00005c0032a1cb84}}, {{0x000643037577dd85,0x0003d9c5fe88f795,0x000bdc13283b82af,0x00039e4c1bea26cd,0x000089fa086ec043}, {0x0009538b13799dff,0x0000e295d034033e,0x0009ddcca85fa8b2,0x000333ef17f73fbd,0x000032bd123cdb66}}, {{0x00088a7858b044cc,0x00019aa9e39755ef,0x000d855591f0d69c,0x000db195fd9cc340,0x0000774df733785d}, {0x000e9f6d3bd2e1c7,0x0000385dfed05dcc,0x000ed09c4eb30da2,0x0001bceed7f5bbd3,0x0000d42a35cf2a9c}}, {{0x000e9959890272db,0x00098e713a10cf3d,0x0008227b875f3432,0x000dc7ae13479fe2,0x00008561eaaaefac}, {0x00097a08332aafd7,0x000503809b62a6a2,0x00063036f9b0d8bb,0x000da862fa1cfd0c,0x0000a16eb562d64b}}, {{0x000f5f678e62ddc9,0x000377fd752b3f5c,0x000437bbe2267c45,0x000074ce361b6b5e,0x00005c595021354e}, {0x0005f85f2b254d9a,0x000c8cb52b4eec72,0x000425fb5844b617,0x0003124d8554f5cf,0x0000b67703ecaf9f}}, {{0x0004ec13cf482834,0x00055c8a705e4cc3,0x0007d4f84b09daa2,0x00029d91e9d0d05b,0x0000df6ef651b389}, {0x0000763aa21ba469,0x00081293f8fbe16b,0x00020aabfc6b1d17,0x0009797ff5b602d5,0x00004d671be53393}}, {{0x00098cf4f5792fac,0x0006512152617c7d,0x000c5a6d47c5e0d6,0x00074cdb19a631a7,0x00008511a633a452}, {0x000621ca5a60d998,0x00084f5e48cb0c16,0x000ddee08f7fbab8,0x000f3c2b1e6ca2f7,0x00003bd08cf67867}}, {{0x0008e8a2ac13e274,0x000f0eb1a9f5f7e4,0x0001f0a624494f6d,0x0008f0adbf84eb98,0x00009badc3293643}, {0x000a541004f7571b,0x00002f1c94ee50be,0x00027bc31bac67d1,0x000e27753d73a1b7,0x00003d01cf2e0686}}, {{0x0007b1b55fd0b8ba,0x00035eec317351b7,0x0000e72b7a099d18,0x00035e802b1fb767,0x0000dc88b3448e16}, {0x000216af989d9051,0x000019b58d0134e8,0x000e55a93c2e68d2,0x000f4001f81c926f,0x00005f1462a9f296}}, {{0x000d375ea3d62f2e,0x000221c8977d1915,0x0007b26f6a17765a,0x0007a49559710ae4,0x00000bd29c933507}, {0x000976d08d84858f,0x000479ced5c1615f,0x00034fa56370dfe8,0x000573cbc7503ca7,0x0000bb9f1ed81ac4}}, {{0x000ec53060dd7ef1,0x000d5e65797995d7,0x000a08235eef2dac,0x000a3d44511af3e2,0x0000e324aa42f4ae}, {0x0007e71e6e676710,0x0000bf52faf7550e,0x0003cc62abccd519,0x000b5df880d31622,0x0000d402c7e2b32e}}, {{0x000c039306a5a3b6,0x000d36783a1ba40b,0x00053cdd44e0a41f,0x00063841e8d39a02,0x0000480be2727388}, {0x0005e1d2285f3821,0x000fdc0b5c36ee36,0x0000f4d82188d8d8,0x00029a24ef1a481f,0x0000a8f43e1b487d}}, {{0x000226d77aefb3a4,0x000dde72c2538168,0x000594df1f69a751,0x0004674e04359ae9,0x000075ffd7e114c0}, {0x000c2b13844e95c1,0x0007cd12ef94b5a2,0x000063d0085caf64,0x0003110ecd2a9ff1,0x0000dd2e22933843}}, {{0x000e09d73d172440,0x00068fc653f138f0,0x00020e21c3ede774,0x0009eaae4459f5dc,0x00000db2ffa6a859}, {0x0002c3930cfd9057,0x000435c112a61168,0x0008bfe954934d07,0x00041a4df063c556,0x000079a440a716c4}}, {{0x000f21897d6fbdcf,0x0006f0776aac0c23,0x00012e8dbd3a5cd8,0x000e8cdee37f72d7,0x0000b28c70e16f74}, {0x000c728b61301a0c,0x000813724354ffe0,0x0008ffedca628216,0x000de8bff4cb0076,0x000051b3088c3b02}}, {{0x000147c3902dda59,0x00066e6973b4a5a8,0x00057457e35d2f70,0x00011acac2efcfc2,0x000033f48d517006}, {0x000af884912beb26,0x0005b62edf94c365,0x00032f34b7f5a4de,0x0000746646ba7c0c,0x000032c6af412091}}, {{0x000f2e3753e43a97,0x0006b4d4e23f58d4,0x000ede6a670e1d21,0x000b60424bf729af,0x0000f4a94d8e10c8}, {0x0000a968d4faa6a0,0x0002b066b690aad9,0x000b6dbfdd9ed0b3,0x00043152fcd37b78,0x0000b64615e8bd2b}}, {{0x0002048cfb9fad53,0x000cf40b76bd228e,0x000dad7bcbeaa386,0x000f5dfd6681c890,0x0000e553fc336d38}, {0x000db9b9d5f97505,0x000a828c5b0ef27c,0x00047c39b3e85c52,0x000827c90795af52,0x000047831ec0ddd6}}, {{0x000a2274a82f424f,0x00078e47f89df327,0x000c7392c36919c7,0x000efdf478391943,0x0000101b9ab1316f}, {0x0009e9c1c5009d2d,0x0002ccd18345bcdc,0x000ce77c7fb55ea1,0x000b3d25b5e231a3,0x0000e6b4528a2f2c}}, {{0x000a3339bb26f5f6,0x000da44d85b610f6,0x000197e541e85db8,0x000ea863697a0894,0x00005e18cc107cb4}, {0x0004f50a471fe6ea,0x00098f13439ca38c,0x00007318bf031747,0x000b3cb3c4a6bac0,0x00008da3ee5bdecc}}, {{0x000b31c558216b17,0x000bbf79e6c20555,0x0008eed3c90c7810,0x0001262b669f4dfe,0x00000398ec950fac}, {0x000449ef701b2350,0x0003eb94f395a96a,0x000cb74310ceecdb,0x000c64285fc368d0,0x0000d37bb5216a18}}, {{0x0000d38b880d2dd4,0x000b25930d570511,0x0006235f5a60f177,0x0006b93da34a67f3,0x00007f5e17c58381}, {0x0004b57db394af4c,0x000cb036f789c766,0x00027b47239ba215,0x0004b686d2ca0e2f,0x000042647efb73a8}}, {{0x000754564488f1d6,0x000894cf85d544bc,0x000e4df63aa92270,0x000ced121a01d553,0x000049c0c51bdb46}, {0x000d64e3cffcb6c1,0x000e40f71d966bf0,0x000c194a0e3bf93f,0x00055465044558bc,0x00006ae33727afdc}}, {{0x0001adf5ca48f3fb,0x0006322a9b84bfc0,0x000099e4a64352f0,0x0009c01ee54da1c1,0x0000bda54e9aa1b8}, {0x0003df56f6e55fbe,0x000340176f88166a,0x000b7b5ff1ca44a2,0x00049fb36afd88df,0x000034c24386611d}}, {{0x000bb75861421033,0x000aef34fc4d7eff,0x000c1b1226704ba1,0x000ce94c2a468f10,0x00006b3a610bc6aa}, {0x000c0a775a0d0508,0x0006bce33e32abfc,0x000fe09be066f919,0x0003514e905ef429,0x00009ee25bb28376}}, {{0x000de22fd29dc766,0x0008d6f172602a3e,0x0004b41267fd32ed,0x000fc7acadcf6828,0x00003422f0907951}, {0x00024f40807e199e,0x000042ad4490562b,0x000b2b1b4fe9ce5d,0x000d0ce2f51b100d,0x0000b361400c4541}}, {{0x0004a052680813be,0x000c761b08d6bd2c,0x000205558527aa55,0x000bebc9f8a40ea7,0x00003eea570043d0}, {0x0003817a0ff58b3a,0x00047a69e6277b85,0x00069b5d6b67d3f6,0x0003ec6b76bbb9a8,0x00003afeb82f4672}}, {{0x000416d3e5548920,0x000d430e2a455f24,0x00032a2a08413b53,0x0007b199c56aee90,0x00009432bf6eec36}, {0x00050c6daf0ecc11,0x00054bc920485528,0x00081130749ebce5,0x000597cfb66ba654,0x0000b84f7977f298}}, {{0x00004818d1d7a0dc,0x00027a6fa5567959,0x0009e5d35d9fabe0,0x000576e40f9c59ba,0x0000b1771c2b6247}, {0x00047cae9a6312bd,0x000f852dd8c5542a,0x000794716a34b355,0x0000942df94de00d,0x000046124aa6c623}}, {{0x000435d68afe8b4d,0x000f9c0d8ea156b7,0x00018689827f2053,0x00090e42b77e1473,0x0000bc3dd4744794}, {0x0009842c03b0c057,0x00030921bc96951a,0x000202e0a8b1b3bb,0x000d563573b3462b,0x00007e4665db7254}}, {{0x0000dfcd23e39845,0x000c9bd1423608b7,0x000114ba7ab86e8b,0x0004f25a3e07f857,0x0000ac71689fb0ef}, {0x000a3840139d9af1,0x000866644af088fc,0x000d74f4a72733f8,0x000c7ae122f72a65,0x00003931577b5626}}, {{0x000d9eb70f8d5a4d,0x000707bbb228d5b5,0x0001c0b32375adde,0x000ba961e88b860c,0x00001f568c4e73ed}, {0x000fc835459df02e,0x000a2fcd9a7e1592,0x000473b0a2beac0f,0x000c47d0a6fdb81b,0x00003224c6fefe8f}}, {{0x000d00ee87edf5b7,0x0001b0e77cf5680b,0x00042d1b230385f0,0x000d7779ab98c04d,0x00002d191d343816}, {0x000daca0917d9e55,0x0008cf8fed7f1564,0x000bb3896394eab5,0x00098e5209aa8d7f,0x0000564f3ba0e6ac}}, {{0x0001d05d73654ef8,0x000393d78d74ead2,0x0004973a068d1a9c,0x000329e1e017086d,0x00003da3500c6e6d}, {0x000fca468ae01189,0x0009402da0696a3d,0x000ab8302a1b9a4c,0x0004357b2ff9c7eb,0x00008af07c4244ba}}, {{0x0007326995f0f9ff,0x000f81b58bc68599,0x000625a2b467fadd,0x0008cc57e4495abd,0x0000dd2d01e23c3b}, {0x000ae28c693f9fa1,0x0009248f79992c38,0x00061f5834862232,0x000cc987bf738e21,0x00005ee2fa7665e8}}, {{0x000c8455777e1891,0x0000356f2829a1a5,0x000762bd5cc10bee,0x000da87ad95c56da,0x000052e2214f9d91}, {0x0000e727cb23c74a,0x0000090c66df975b,0x0005ffc53fd5d767,0x0002ae15b5b8ad22,0x0000b6dff749aded}}, {{0x00067816f4cbe9d9,0x0008da574bd7ebd5,0x000a881fa0ed8b24,0x000c6fb1c246fe81,0x0000156480653db9}, {0x0002b085b8628093,0x000125858d7bd7c1,0x00009e92a1facd1f,0x00025f4693747caf,0x0000b69dcba489a4}}, {{0x0008e9f967365efa,0x00024801f5c90be2,0x00083352f57300eb,0x0002b6f3b8ac6ad5,0x00002cf1f8a6d05b}, {0x0009b744dcc40cc3,0x00057da523fb7c0c,0x00099cc4dfee38c4,0x0009c6849a4dec10,0x000025c377f99f06}}, {{0x00058ce476cc9ff0,0x000cc6d4cb63e124,0x00072289b580e0b6,0x0006dad561c8b790,0x0000377f264a619e}, {0x000536288e591a5c,0x000cb523ca2b2668,0x000df4533a453a7b,0x000f78ca9536d2c1,0x00008e50f307e972}}, {{0x000e50f6d3549cf8,0x000f7acd665ed433,0x00011fcb46f33696,0x00085fe95bfdacce,0x000010ee2532f7c9}, {0x0000fe17159bb2cd,0x000da58b357b6545,0x0009fea72f7dfbeb,0x0007445b057e74d6,0x0000485717b62731}}, }, {/* digit=23 [{1,2,3,..,}]*([2^161]*G) */ {{0x00042e8ee36860ce,0x000c6113c22d896c,0x000104213daf04df,0x0004e93adbb7b744,0x00005fd5fa1ffd39}, {0x0005d941a4e0551e,0x000d38d101516823,0x0009845236772cfb,0x000a97476071e309,0x00004e879df3a56b}}, {{0x000afb0285b94916,0x0007be4c705eaaaf,0x000d9caab01a0be8,0x00033f9f1d4f5d2a,0x0000e349a4b237a2}, {0x00012464a1c6a163,0x0005f9383260cf1c,0x0006d5471d99e6b6,0x00089bba3d43665f,0x00006974d052f8cc}}, {{0x00049a1cfe89d80f,0x000cea9c8371c26c,0x000d066d2b42c026,0x0003edda6c013ada,0x0000b8f722946a4f}, {0x00079ecd850935b3,0x000ca631e1b308b5,0x00019853434c1a74,0x000f259b5fe596ac,0x00009ff21f711f24}}, {{0x0009e148f9290579,0x000630c853df27f2,0x000e9c5ce7a64ae0,0x0002a4956cd18358,0x0000d9cce836ed09}, {0x00059796e93b7c7b,0x000181bb9e27cc6e,0x0009e29a0e1e4709,0x000644070b3083aa,0x0000f181a75e785e}}, {{0x0002c658ead09f79,0x00050780d14df53f,0x0001b66bc1335e1d,0x000fc7d9cc20e0cd,0x0000b670a384be0b}, {0x000dc8128efbeedb,0x000bd326a6e5ce53,0x0008e9a630c74e77,0x0002478604e0d2b8,0x0000ab38fcac3dc2}}, {{0x000e8c85c0a3f1ee,0x00019c87c37f8ed6,0x000e3b78dbcad249,0x000a461dfb62bb9e,0x0000ba8e478abceb}, {0x0008cb0eeaede4b8,0x0007f976deb637d3,0x0006147fb0bc498e,0x00060932944c046b,0x0000b123f36771f9}}, {{0x000dcc7de79dc241,0x0002458f69cda155,0x0001850dff1168a3,0x000848aac215950d,0x00005c8295bc204c}, {0x000aa367d8184ffe,0x000d50447bdbf661,0x000e4a59ec396228,0x0005e531cd5143bd,0x00003a26e3c4beab}}, {{0x000a13f1402b9d0c,0x00026c7bc863d3b3,0x0008c3e6e573441c,0x00057d8b301ec457,0x000026fc9c4cadaf}, {0x0001bfd7493cea35,0x000ecaf8145696e7,0x0008c608fd05d4b3,0x0002768aca2a8a6a,0x00003ef07f65725b}}, {{0x000fbd27824fc56a,0x00077328907707a5,0x000c483493467521,0x000874bbf69fd5e0,0x0000613ddd456aa7}, {0x000c19c5450d8660,0x000c8f84a4817f78,0x000fce23946f4409,0x0004b99f1d192890,0x000016c4168b2ce4}}, {{0x00023f0c74359787,0x0007b0e30e19bae0,0x000fa6fafb152c88,0x000e602c241645e3,0x000035d95c1f4823}, {0x0007573039553173,0x0009c03b49950319,0x0002746000b4b02a,0x000507d76bf55970,0x00002c5cc53daf57}}, {{0x0006d1f606241297,0x00042a5e2b5ee8af,0x000082d72b7bc5d6,0x000779c814b0485f,0x00006f267f33e196}, {0x000630fb36eed930,0x00073bf56803626c,0x0002736a055230cd,0x0005f178837949ce,0x0000d792d60aa6c5}}, {{0x000dbfdd5c7c5d2f,0x0006172b342d0318,0x0008de38ab38f8da,0x0008414569bddc7b,0x000025b588891c94}, {0x000b2842946ad608,0x000d69d1707eb2d5,0x0006a4509854f29a,0x0008372a5159dc2c,0x000099f94c0d7189}}, {{0x000dc51f4a55b03c,0x000d75e3b2d5cf6a,0x000827b51261762d,0x0004418cc4301204,0x0000d22a11486021}, {0x000d61a247c9569c,0x00031152becace2f,0x000a716d459a5097,0x000dceac835a1163,0x000026455edd87de}}, {{0x00036e049ce89e7e,0x0008ec890cb527f5,0x0003c2aa11890853,0x000bd2508909abd8,0x0000cd3142bfab73}, {0x000bf59b3f5ab84e,0x000812bea4c66a85,0x000a4541f3c320a6,0x000185cd8dc5386d,0x0000af34eb197c41}}, {{0x0000129977c97c4f,0x000ad57eb9fa1c78,0x00022c4785ff9bee,0x000414b24d0524c8,0x0000d8eec2b361cd}, {0x000194ef027458c3,0x0008ed1be115fbde,0x00066d6f4b4ff531,0x0000c933f874d948,0x00005c75015e21ad}}, {{0x000c9d646ac49d20,0x000b83137aa9a6b5,0x000225a3842c77c0,0x00090724d000fc68,0x0000f63cfc82fe1e}, {0x000b01bc6441f959,0x00095c8e448f22d1,0x0007fb1ba7d38f71,0x0008df0b33fa5f78,0x00004dcfda1a9015}}, {{0x000b3395f6d4a09f,0x000bfe52b826c47c,0x0001b930a6b4f355,0x000f684d100f5df5,0x00004512fad8f668}, {0x00081d5206c4c74f,0x0003db4d2e485467,0x000085c2dd021d4d,0x0000a7594a54c2ca,0x00001dbaca542085}}, {{0x0009326490a1aca3,0x000c11526b0263c7,0x000979258cb64dd9,0x0008468b772591a2,0x0000f58297078d97}, {0x00070d17c213ba70,0x0005e8a0ced4d66b,0x0000338c1c28febb,0x0006f36b911831c1,0x0000d54e389bf012}}, {{0x000d4604af206ee4,0x000637e97cb97048,0x00064802e786c88f,0x00011c94375ae1ac,0x000069bcfe2153ec}, {0x000340d470622302,0x0007a5b4a3acfc9b,0x000ef45ace743bb5,0x000188de00b4aa59,0x00009a4ef2379edf}}, {{0x0002efeb483689bc,0x0005913ac2624024,0x000a6db722575d3f,0x000be2330037c80c,0x00009fcce8358864}, {0x00012ff0149362d4,0x0001dc4ae97184a1,0x0005cf86c95e5758,0x000a2edfa4b1a894,0x0000525a7344b024}}, {{0x0008b628f3383609,0x000298edf32be76c,0x0008b1aec483ff59,0x000a20d7e8e90a29,0x0000caab339036d9}, {0x000d2fd668927090,0x000cb55a1d415c09,0x0004a43942496b4d,0x0006c193f5fb1ae2,0x00008c750496fa8f}}, {{0x000d1c2c905d85f7,0x000f9733ae57caea,0x0007cdd94e9d7f78,0x000930b4c9a65cf0,0x0000389359d14b55}, {0x00009b7367e45f70,0x0007cb7e7adcf587,0x000b728181f20306,0x00003382444bffc7,0x00007303b35baac8}}, {{0x000e4e4d13b7ea1a,0x000440e741801e1e,0x00070ef70e6489b2,0x00089405f2c6107e,0x000016554135dd10}, {0x000befb7af4194e1,0x000c7e89bd9c555e,0x000895856533c1c3,0x000c15635b9b5789,0x00005fb3cd2667f5}}, {{0x000ed45526f09fd2,0x000c6128240a057f,0x0002bfd8de8a4f10,0x000a317332efc4ff,0x000014e77a0dd35a}, {0x0006d7314faa40ec,0x000b41e5f1863289,0x000a1813e767867e,0x00079509adf8f117,0x0000b6cda7914741}}, {{0x0001b6d349d51aa0,0x000ee3c7b8e9b752,0x000a096dff56b5a9,0x000024c6f1e5c932,0x000083667c4a3635}, {0x000a13518087f2fd,0x000c0136e45d365e,0x000aec989f1b8eaa,0x000258f8a0e48473,0x000075a324be42c9}}, {{0x000d00101dae185d,0x000acb7a94bcb7b4,0x000d8cb0b45434e0,0x00049e254339affb,0x0000cc4569fb98ef}, {0x000318a09a512993,0x000682b025d87789,0x000e8579281b4d20,0x000af7c64aa418fa,0x0000e50258fdcd7b}}, {{0x0004cdb2996864b3,0x0008ef485fa4dce8,0x0004c6a5aa2e6708,0x000d39828b2bb653,0x00001a7ec6bf94b9}, {0x0007766d6bc20da4,0x000c467611901d21,0x0007010634acdb5e,0x00029b2872632873,0x0000d24ee7c6128c}}, {{0x000ebd3a19fd8680,0x000cdb8ddd3bc072,0x00064d852612e481,0x0004abb4e1d7541a,0x00000ef95acc4c6c}, {0x000d2edaa0a6c469,0x0005b37747901536,0x0003fda106129408,0x0006f1c4af25e834,0x0000ff9d98e8d25d}}, {{0x000af7c468b8835a,0x000ad30ecea70746,0x000cf4a81977a31c,0x00037a05096b80c2,0x0000a9868340458c}, {0x0009bf3a6bd9d340,0x000b33c5d8546af2,0x000133b5e6a62fe9,0x00084850e6c304b7,0x00004b601597d6e6}}, {{0x00096df5579bea49,0x0007cceedaf14cd2,0x000bcc5b110e35ac,0x000cf874c4c5fde3,0x00005f9ee8b19412}, {0x00059ee82b6eb0fd,0x0004c5c2aadd2c94,0x00027fcfe2e84576,0x000475a74a84aed3,0x00008c93722d368d}}, {{0x0005748f83e8a3b0,0x00068d2495f30dbd,0x000496e9ba579aa9,0x000cc2535996a0ae,0x00007afbfe9b7f9b}, {0x000dc6d5b7bd2931,0x000f6022323d3ac1,0x0000a3e763b592cf,0x000acbaa0deb989c,0x00008e78e9f5b197}}, {{0x000de10296c36eff,0x000192c4da77211c,0x0007836da7ee8967,0x00060ac617d270a5,0x00000cd9c328cb75}, {0x000cbf7e455fe908,0x000afe7334f301fd,0x0007de4ec3fb53cb,0x000fcff81e2ea44e,0x0000adab3ad8b384}}, {{0x000ee2f53d648293,0x00077261492b129e,0x000cb4a2c7a471e1,0x000c2db4f9adb9e4,0x0000d359f6fc7ba2}, {0x00067860aacd6975,0x000325c2f8a8346c,0x0005df44e92b444c,0x000f31779fa117d8,0x00006782372898dd}}, {{0x00090f2bbbab3b85,0x000e3b04816b60e6,0x00092e4d24851f8a,0x00036b772046ab9c,0x000018c74a1ccf31}, {0x000b50af9877d4ca,0x00000919cabbff4e,0x0005eb2b614578d9,0x0006e3e218f8c4ac,0x00003ccc547f4201}}, {{0x000f48e327f83495,0x0006a43cb641025b,0x0000f1085f3e9734,0x0000558c2bafdf50,0x000071678767f063}, {0x00014b9411925a6b,0x0007f1123de55bd9,0x0002b165d7c078d4,0x0007273e6bf83518,0x000011b5e5c6a519}}, {{0x000a76c1eea7b85f,0x0000a2d4f85ee33e,0x000e115bb2352b46,0x0005a30101d334af,0x0000abc129578917}, {0x000cdc05233f9251,0x000bd77fec557f6b,0x00069b659e0a802d,0x000d74adb47b7580,0x0000c5e12df098fb}}, {{0x00058c64b8457ee6,0x0008ef7ea9f7869c,0x00060b38fa5360f6,0x000b368576c09ff4,0x0000b70d54882b7f}, {0x00037f13bfae3154,0x00028bdff3693fd2,0x000b516f93379785,0x000d2d57df25f525,0x00006f388f2fa38a}}, {{0x000465889d8ddbbc,0x000db0f38ee8656c,0x0001212b08830b26,0x000db18320fd5cde,0x000034f30d0a4a2e}, {0x00031a356ab64b81,0x000cc99c5d26abb1,0x000981d947f77f0c,0x00076e56856a37bf,0x00009e76d09838bd}}, {{0x0008ac396238f398,0x000e2830b366e76c,0x0004eb499c0a482b,0x00086537b8eaff0b,0x0000ecd83bccbfb4}, {0x0002cb7a2f3776f8,0x000474b88adf971b,0x0001fa446b42176a,0x000bd239617df5be,0x0000b32d5094d031}}, {{0x000d47d53b618c0e,0x000b8a2279231c6b,0x00092d964c424f46,0x000bf19303ffdedd,0x0000971287951b5a}, {0x000a632f815561dd,0x000503c055d18f48,0x00025684f85f48ff,0x000cc2522a142775,0x00000d841a137360}}, {{0x000a9260b9267c6a,0x00012f07f8634245,0x0000d9e24c78913f,0x0000170a844c8e4d,0x000042ad522dd5f9}, {0x0001749a2c989d55,0x000f91f5e78ebd37,0x0001ea6da928292d,0x000528f93b383e0a,0x0000136fd8d63aee}}, {{0x00044b1f2c34a996,0x00045f5855ac860c,0x000af37be3b00aca,0x000c084bf6aaa0fa,0x00005f436828a53e}, {0x0005801a11b12e13,0x000cb20ed4751d9a,0x00041e0d578a7ab2,0x0003e9dde1067e9a,0x00000473f5f60502}}, {{0x000e09d169c7d97d,0x0003ffaef9cddd3a,0x000a448035cd5baa,0x0004dd8cd7440b65,0x0000c13966b17f36}, {0x0002be82b8357c1f,0x0004f9d57c2a077b,0x000ff363e0cb1b4c,0x0009ee8a4ceb3205,0x0000310fa4eba35a}}, {{0x000b352f97f68c6f,0x000f1b02cf58dbb7,0x0001f96d90c773b4,0x000814fa2e48213c,0x0000fb357b1dee01}, {0x00024cde0f28039c,0x000986a3fbe4b9c9,0x00046db6c0b36c95,0x000afe5faaaea45e,0x0000ae575c3d928a}}, {{0x0001302a70dab865,0x000921c58cfc7f67,0x000e0cb92fcbd12a,0x0005837bef9acfbe,0x000073da0ba48c1b}, {0x000fcfe0d41d5505,0x0002d155cffe4752,0x0005ae248e7eec0e,0x00044dbfc39fcb54,0x000022cb8d1d065f}}, {{0x000962a70cbb96cb,0x000a0cd124a9263c,0x0002ae58de034362,0x0005074120db283c,0x00009a38d4aaef6d}, {0x0002a821ff140fd2,0x000000aee7e0b1fd,0x000251949bd162f3,0x000c3d2e17a5d4cb,0x0000aebcb836f7e1}}, {{0x000b25f937b05271,0x0007db7d9997608e,0x000a53a29f42e1e4,0x000536dba699c4b8,0x0000f921c71f091b}, {0x0009e7b5b26bbd51,0x000d2b61a680cce2,0x0001f1c7e7a8ef5e,0x000ddad5ef8043ba,0x00006ea821728158}}, {{0x0008a2b599ff0f94,0x00074104fc6b0177,0x000694ff368a923d,0x000f121bfa44dfda,0x0000f7199dc37667}, {0x0008ff6e46f2a79c,0x000d29f8131dc06d,0x000b4ce7c08b5dea,0x000c3d42519a59ab,0x00004f710bd742ae}}, {{0x000b05778bde41ac,0x000ff4186b5a3d77,0x000c657416474bf7,0x000153448b3f6788,0x000064519dec3c7c}, {0x00038460edfcc4f9,0x0006b8f1aa6bdf07,0x000909f77319aa73,0x000feefb9f8a02ca,0x0000025813a0580b}}, {{0x000d3cac0c227196,0x000469ca151ed8bf,0x000a1a69cc60209e,0x000f8f1a744ab5d9,0x0000de5048b74937}, {0x00038d8e115ac04c,0x000f5c6b16d21719,0x0008e94e77df7093,0x000093e6aeb6637f,0x0000130388eea2cf}}, {{0x000be8477f54e6e0,0x000265d60fe51850,0x0009146d69f258a7,0x00030bff7ff0c06c,0x000039aaf90e63a8}, {0x0007a739460342f0,0x000c3f795f8a38f2,0x00081a97e4703148,0x0005941bb5467b96,0x00000931ba5ecaeb}}, {{0x000719d786f337c0,0x0002e704397dcdb6,0x0005c2fefd9c01cd,0x0002230f4a3f2055,0x000004525097c0af}, {0x000804784db8e765,0x000a43c8aa0654a5,0x0009194223bacf1a,0x000a3fc1ca957cf7,0x00000641053c8cda}}, {{0x00038749f7144aea,0x000ea3d4acfd7a30,0x000ddd3ef170c963,0x000ba7be14814958,0x00007bde5833e72d}, {0x000da8b6fa687508,0x0001d72e02490769,0x00019ad31fa64e53,0x0009cd7caadf9d26,0x00007882dab27b34}}, {{0x000b7316c67a7751,0x000adfc5d0b19f6e,0x000b806b2cb10471,0x000e7ea433750ce1,0x00009c5714d67b1a}, {0x0008b7bed03fd3f8,0x000eb1bc194ec0dc,0x0006320b5dd03344,0x000d93266c52a78c,0x0000bc82ce450b6f}}, {{0x0003501b35f1341b,0x000c75a43e42f8e1,0x000aeb85ce53156d,0x000eb523adf27e4d,0x000081d837a6bedd}, {0x000546e2e4358674,0x0004aba5dd601b0b,0x00010cb9d9020eb9,0x0001cef7d9116182,0x0000c596b319c91f}}, {{0x000a90f0e0b040d2,0x000225ff897fb228,0x000fa6122baf02d8,0x0005570aac79e600,0x00004828817ae36f}, {0x0001d31113ec3567,0x000da5eff1f8b952,0x000d417159e48861,0x0001b7baa1d412e0,0x00001f86203c3f13}}, {{0x000a8da3fd19408b,0x000b778d9d99f60d,0x000c51c904aa716d,0x00051b894531f7a8,0x0000560b0e9a59db}, {0x000c992fa34bdad6,0x00043cd4f8bda28f,0x000a9d0d3f024fa1,0x000b55fcf530f723,0x000015ca194428c9}}, {{0x000483d6f73c51e3,0x0002ba0dc2dd6d2a,0x000b917ffa4cb241,0x00099e20663c411e,0x0000d3a74d01ade2}, {0x000990f4a7a92024,0x000967b15c3d29b3,0x000df9208a9bccf5,0x00092926a3ccdca5,0x00008027c1483f2f}}, {{0x000377c40b557f08,0x00064d684660d385,0x000183a27e001c36,0x0003289b18ed6be2,0x000079738d8e3210}, {0x000c74bbda948826,0x00084684b299a687,0x0003b3724d1bbcc4,0x0009f84f6f111286,0x0000943d1b48c8ce}}, {{0x000a3bb098cafb4c,0x000fa0d48cafe044,0x00031b84d27ed230,0x000ed6942b56753a,0x0000bf3dd51bcddb}, {0x0001f1641b1d830b,0x000d1b0c1e272503,0x000ae75dba7ec851,0x00011ffc1c8fe0b5,0x000024c7557b8c52}}, {{0x00011dc1d4636c38,0x0005e81a993957f8,0x00081adb3f843652,0x0000d39f6bc6d99c,0x000040f8ac3db7d8}, {0x0009811f4387f1af,0x0002c5156880731a,0x000e688677c501cd,0x00011fb5ca4a07df,0x0000123d8f14fcea}}, {{0x0000e71d607039eb,0x00051d3a45461fbb,0x0003240912b70e21,0x00019a82d2f01d53,0x0000796ff08c80ab}, {0x0007a863c57c4aa3,0x000f87c49a2732d8,0x000630d982aed9ca,0x0000a36fb35eac31,0x000038e8cdf8c3e2}}, {{0x000618266cde8dbf,0x000f3d72fd3680f1,0x0006e50724e15997,0x000dc0e7b8f13b9b,0x000052139082b7b5}, {0x0001f1d8ce4396ea,0x000007ed21424d43,0x0001aaf6b37a1a68,0x000b661f375696d0,0x0000a1c0c55863aa}}, {{0x000368b4ed80940f,0x00058a6fcedd3014,0x00097579f67e6d05,0x0007f58c208c49ca,0x0000e3d7a8292359}, {0x00032027e096ae27,0x0006b4b393665e20,0x000dcdffcb1f3e1e,0x000e82b6da26f32f,0x00009422f1dd097b}}, }, {/* digit=24 [{1,2,3,..,}]*([2^168]*G) */ {{0x0002cfb9db3b3818,0x000e54df0a4b263a,0x00004e61f9c3a2de,0x000324f28d06e97d,0x0000b1adfbcc2449}, {0x000d9397e053a1bd,0x000696daf7076ec1,0x0000ac7abee2be5c,0x000173b0ba1e1481,0x0000d2ae779c530f}}, {{0x000d97a205b9d8b0,0x0004056756d40435,0x000f8210e6eb8f06,0x0009ead5e88a8bb6,0x000070ef12dec9fd}, {0x00095053bcc876ae,0x0007c7404ce34d84,0x000a1db5e12a7533,0x0005acf22b49e1b8,0x0000c1f2051f4bfa}}, {{0x000eb79b6828f364,0x0007c1bd5b9eadba,0x000844b0c9d7a025,0x000fc9ada01e0d1e,0x0000b625175c87ed}, {0x0009fdd9669b6210,0x0006f6f87b981410,0x0000df6bc88a2ca5,0x0003f9fe2eb78817,0x0000cea06f4ffa47}}, {{0x00081b5c4e83d33c,0x00089efd488b43ed,0x000eb4d0fd9f3587,0x000393564a620f9d,0x00006927bdc6c6a7}, {0x0008df79f9e0f036,0x000e9cd7e1a945c2,0x000a348f12868661,0x0008e01cf4e8d0ff,0x0000bd4c28499853}}, {{0x000a091289a8619a,0x000fc671b1732618,0x00090c632ef796e5,0x0008fac64e46e590,0x000038062d4be66f}, {0x0004a200573274eb,0x0003f92713946c74,0x000dc0e20d07b67e,0x0005a6891223b26b,0x0000e2d93f29b0a0}}, {{0x0002e533f36d1411,0x00043dfca442f23e,0x0007c023ae84bb3d,0x000c3ba804a48d6b,0x0000e16a8fa86431}, {0x00052adddd472e03,0x0006dd1ee1271b54,0x000a275997d405ee,0x000b3520fc6f1dff,0x000051ac53cef391}}, {{0x00014b84444896b8,0x000f794027fb7efa,0x00084487d64974d2,0x00089b6fdcd0e8de,0x0000c45b260ab489}, {0x000bbc2d84634875,0x0006efbc476ca8fc,0x000f443c0d1b2b3f,0x00039bd1d005b7c8,0x000018f2e6790c01}}, {{0x0006e8c06d75fc1f,0x00064249a89f5603,0x00045e7dd2dcf7bb,0x0002a691dd1d3de2,0x0000578dc4cdbd6e}, {0x0008903df2ce7a06,0x00083c39afac4c02,0x0006404abaee3628,0x0008187c847c3114,0x0000304c0d904e97}}, {{0x000dca2a91f6791e,0x000fbbaa9efcae51,0x0009c7ac12abe418,0x000739f9d2e2f455,0x000082f4b52dc9f7}, {0x00030274073e81c2,0x000cdbb596fca771,0x00084f70cc0276fa,0x0001dffd819fc9a6,0x00009b47fdde9f7b}}, {{0x000e103459b19402,0x00093b013e93358d,0x000532ad3ec881c5,0x0006de31574c9349,0x0000db1d445d37b4}, {0x0005b87df239fd84,0x0004d51d24eec644,0x0003c6259c718af7,0x0002f76ea1c4a4f4,0x00000c0e5d7b0be0}}, {{0x00090f4721b33f2e,0x000b1edf04ea6a45,0x00045efe72124f1f,0x0006d918e53cde97,0x00007e1043345f04}, {0x000a28ee4d0c7e6c,0x0009c7253b1bc3fc,0x00043e643847e339,0x000fc4db59534837,0x0000b6a0a0c0fd12}}, {{0x00036c327d02dccc,0x0001ba68bcc2fb68,0x0005e912d5ad0098,0x000cfd5b24b44c00,0x0000c83d210411fd}, {0x0007ec1666fba0ca,0x0006747546353652,0x0006da9c26994819,0x0002b25cdcb1a855,0x0000593426821a73}}, {{0x00014eda714181da,0x000ac067b341ec12,0x00045df1f609ac13,0x00076b5f4b4c97a5,0x00001240501d4d20}, {0x0000c231409ca976,0x0007c0638c436efa,0x000fb46cd254cc1a,0x000a2774e363afdc,0x00002c2adc363942}}, {{0x0009df056e464833,0x000033736356c67b,0x00051bc52a55abb2,0x00064b7b93c098c5,0x000082b49f9e15fe}, {0x00021ad4dff8d47e,0x0004637df4d69ec2,0x00045650979caf61,0x0007137f13dc64bb,0x00004c589d9f91f0}}, {{0x000a8ab3fd40e095,0x000e27313ea927b6,0x00055988be455842,0x000bfc3b51d1e21f,0x0000716dd73562bb}, {0x00011e54e8bf3de2,0x0005fb85be3b633c,0x00011cca69a0e77b,0x00090f3651072909,0x00007e764960fa65}}, {{0x0008b33070d3aab6,0x000b3a2cd5e5e4ac,0x000fc91732643672,0x00013ef2eff79b1c,0x000065ca49bf0a7c}, {0x000da59b3efb9983,0x000cd52f13415a8d,0x000f9a5308a5b922,0x0004d77e9ebbab3c,0x00005986e7c256da}}, {{0x0006b5cff3513cc7,0x0009c198f7dd3a63,0x000f16f86bb0cf8b,0x0007bf48d4052241,0x000060575d94e13a}, {0x0004e169f7aa1811,0x000fe509ed1c36f7,0x00040a491163a3ec,0x000caa5aead61f3c,0x000058c95fcefe8f}}, {{0x0001b6e13cda46f1,0x0005242faed0a399,0x0006b59707948241,0x0006dde3ba5bde66,0x0000d52e6bcc26ab}, {0x000a1e78608dd3d1,0x000ada076586768b,0x000dc1afa4930db2,0x000817c9575714e7,0x0000fc7bf7e07c58}}, {{0x000accdd9eee96cd,0x000b158cec376b47,0x00002c42a0ca277f,0x000e50413fe413e7,0x0000d1764ef947cb}, {0x0007cde7b3ed7397,0x0008ece9e1c0041e,0x00025b21250cb745,0x00081bc556851329,0x0000cff95c4701b0}}, {{0x0004cbd8088b454e,0x0006ba9e0c8a63ee,0x0002447cbdb7f32f,0x00019ad377d4186b,0x00003e982abb3702}, {0x000c1e4c2a2a5938,0x00048773f24f06cc,0x00085942372c3686,0x000c8f213b4da795,0x0000bbf1d33f5040}}, {{0x0000973da50c991b,0x000ad22d6ee2726f,0x000fd777148afcd5,0x0007a135fc718b20,0x00009e8e77ead080}, {0x0000f4499a7703de,0x000d818e36f37f5e,0x000807bbe6972930,0x000f4f4b7c77b823,0x00005b82406ab27f}}, {{0x0008be3bd3790620,0x000d2dce4a92ba8b,0x000952e37d64b7a1,0x000eca040a73c5b2,0x0000a9e252ed438a}, {0x000956bc39d3bcbd,0x000fe32b2d63dd43,0x000417a181a31c9f,0x0002c8067133b85c,0x000008e4790fef44}}, {{0x0001ae9255c09801,0x00011b4a739f98cb,0x0004a45a14bd8638,0x000b2f4a5c31e11e,0x0000e5d55feacb0d}, {0x0001b068ff5cc292,0x000eeeb8a4f47466,0x000848c24026b389,0x0002b0336b21a458,0x0000e5bf8eca1dc7}}, {{0x00087d0ad886aac2,0x000a9771b64503c1,0x0004045ab5c16878,0x000aed907dfc6fc7,0x0000c6360bf9800c}, {0x0005bb5b9c972a3d,0x000dac9a6dba2429,0x000a79aa6c9e6f88,0x000ac1c0ffbf2492,0x0000e29d50b11c26}}, {{0x000f483d309cbe6a,0x000a40bced4f9f0a,0x0008023e35b020d8,0x000932c06e986db3,0x0000d8f2c9dbabc6}, {0x0002e1de7400e938,0x0008d2be5e4d1929,0x0000680bffe3e18a,0x00006368e9771d2e,0x0000c5bec99454db}}, {{0x000662a74a55d1f0,0x000f046f66d82af9,0x000dc4794e3fbf28,0x000dd8a3a72ab4d4,0x00009779f455c7c2}, {0x000bdafc3d19d8d3,0x000427d6a6dfd893,0x0002e6255d5a7509,0x000aff5cf8fef995,0x0000da67cfc0a9a8}}, {{0x000f62a2c160dcd0,0x00038f90eaef4c23,0x000a65d5a34e6c5e,0x000a3d35865519a9,0x00007c48aae8fd38}, {0x000aeda50068527a,0x00027c90936ab7e7,0x00079324c2c09ef2,0x00093791ecfeb6e8,0x00000871f6c9b0ec}}, {{0x000fb68d84d835d2,0x0009661dc1e6b1f0,0x00094f8d7c90caf3,0x000b91f2e5b04675,0x00006897ae285012}, {0x0008a08a4d6755dd,0x000b3991fbdabcf6,0x000bf17e8403ee41,0x000d64a33e343e3b,0x00002c7980e379b3}}, {{0x0006232d2e11305f,0x000203c07a6f3305,0x00015509d966be49,0x0009a37a8878ffbb,0x0000f221101fa9b5}, {0x000564aabe30129b,0x000f836e64cf6c9f,0x0000c8022c6f2c93,0x000b865fe752628b,0x0000e0267ea1ae8d}}, {{0x00092f193bc042b7,0x00044237c45822e1,0x0002c4168f085b53,0x00071d30d192bd83,0x0000a76e9e42df62}, {0x00082fab88911b55,0x000464db0eb552a8,0x000a7c3ffc85345e,0x00046953be02a681,0x00001889c8d40ec0}}, {{0x0001369a5e829e5c,0x000b5607aa419d03,0x0001d84c1cbb4c6f,0x0000edb5ac59a624,0x0000043f2c04829e}, {0x0008f758ea5e1853,0x0009a87cbd9f82a3,0x0008fc6018bda40b,0x0000b36e65e75e2d,0x0000d515f74d3569}}, {{0x000cf4fda79e5acb,0x0009d630215f534a,0x00085756e68b83b3,0x000cb1ac748b2ed0,0x0000031725995d37}, {0x000841ac5ccc2c46,0x000add9d50696735,0x0001754bd7d7dc96,0x000dd54147e410fd,0x00005296e953399d}}, {{0x000b2d0bc8fa5bc5,0x0007000c277bf6b5,0x000a08a5d8a5ead6,0x000046d14625e6df,0x00001fdfedce59cf}, {0x000430b289fca32e,0x000ebd9bdc3f6bc9,0x000ea0edee36ff0c,0x000b3e4fe187cb58,0x0000d66af213a900}}, {{0x000968b5fa9f4d67,0x000dc7a362e700e0,0x00007e7722d4066c,0x0001d0399a9748bd,0x000010989c076a4f}, {0x000df35ce40cbd89,0x000f8743293dd5de,0x000a24e2cab55c5e,0x000cb3e66f11448a,0x00004d874f8f05fb}}, {{0x000f0e8a518001b4,0x00065d04ef0fa365,0x0008d4d25ee605eb,0x0004721a3915cdba,0x00004c0e1b8f5113}, {0x00024e88b6740dc8,0x00036e1d4f0ccbb0,0x000c4e37289087a5,0x000af2288fa05c1f,0x0000bf395cc2f8b3}}, {{0x000c9a1deb8568b6,0x000020fb3d321e71,0x000f8fb81a35daea,0x00096a88b6f2662c,0x0000d51afe8f4906}, {0x000ac6e51803a198,0x000f0621908081be,0x0006f463ce3d24b7,0x000ee7f27cfd9ddf,0x0000c6865caf2284}}, {{0x0008b7db743f4ef2,0x000bc7d11dce32c8,0x000f2ebe83793909,0x000796b398f9222f,0x0000c70ca4505e49}, {0x0009929cb1131b10,0x000825888e79df4d,0x000d8740a7826f29,0x000a8b4d3a112cf1,0x00000384cb6270af}}, {{0x000125b3ab480953,0x000632d05106cb64,0x0009558453451c25,0x000433a73d577da4,0x00009570c16ef9f4}, {0x000aad3adecf263d,0x00010c76e102d7df,0x000c6a836f1c3d8d,0x00047a8e774a5854,0x0000ad4b6730e92d}}, {{0x000990ff0d796a03,0x0008af0e8b02be7e,0x0000c00ad5fc6247,0x000a0f5aae8bf403,0x0000d2db93bc004b}, {0x0008a79d85d5ddc0,0x00076bb07f34e48c,0x0009eaed5e907caa,0x00072458db343aa3,0x0000ea6e007adaf5}}, {{0x000f169d23233f3a,0x0005d7cb637fe00d,0x000a0cf6c3e32279,0x000bdc7f897c0e1d,0x0000651f5d8d1d6b}, {0x000af191a230c767,0x00025daa5e4add61,0x000abcd7ebd52727,0x0008dc5a753636d0,0x00008bdd37ca70bd}}, {{0x00016c217cd93fe1,0x000dcadce6e2c239,0x0004e42f865b97a4,0x00080ad04ed4eb17,0x0000491ccaacb214}, {0x0008280231963324,0x0007187b479a145a,0x000dcd0ed3c3862d,0x000f1f5f4a88a301,0x0000da2b7ef7ea12}}, {{0x000ae33b126e48e4,0x0002b494e237f8e7,0x0005acadb404a0b3,0x000fd95beac474c5,0x0000ee5cf3c0bec9}, {0x00033b97df3c8c32,0x0003976808fd336b,0x00045c16abd905fe,0x000b626f436981aa,0x000055c5bfa5dd27}}, {{0x0005cbfc3dd9b4d7,0x000f8c068a877196,0x0005b029bce23edb,0x0009bd478d472574,0x000046107143efdd}, {0x000f75f1266bf52e,0x000138e49bb67116,0x0006f19e30204672,0x000b2eff43df9f3d,0x0000f1bc7d1c685c}}, {{0x00027c17078c4322,0x000c977fedb7cddb,0x000290570e1961b9,0x000885fedc2f5cc2,0x0000c3fefca39cbd}, {0x0000a36c2af389a8,0x000d3da71ceacf88,0x000aa846396c610f,0x00090a703977a932,0x0000eb776400586d}}, {{0x00024542a296e775,0x0002f2837a353f34,0x00009c731c871868,0x0006db2dc710906a,0x00004778ffba1b81}, {0x000bfecaf06defd3,0x000f5592b70b6b33,0x000da6114fe3c105,0x000ad7c937fda461,0x0000c13e6517c266}}, {{0x000a829855938e83,0x000e6de54b72e363,0x000ccfab92eeb5d9,0x000a258eb93b0e20,0x0000dffbb5f55e61}, {0x0005e431acc093d5,0x000ce964ce617f65,0x000e9b4600cb6cc3,0x00072d1ab283a1e5,0x00005d787c5f1c7e}}, {{0x000fd47deadbf02f,0x0008bc4590684d2e,0x000f311f011e8021,0x000f52910c762671,0x0000a17ef8e3ab6e}, {0x000fd2593e43bff7,0x000e9be40632af47,0x000e61da35cb5ff3,0x000d0ee46871068e,0x0000764196f208af}}, {{0x000b3edf0290a8fd,0x0005fb47c387831a,0x0004efb4fcae8196,0x00010ddad7dece18,0x0000cfc53b417491}, {0x000f23c4cb632f9e,0x0005d91f80676698,0x00084180ac42a1ad,0x00026ed116a81d62,0x0000bedf5f9c9013}}, {{0x0004c9f97e3e0442,0x000ff1d09fc9f227,0x0008e6e234201851,0x00083c36a65f17d1,0x0000ea61e2a552b6}, {0x00091bc575eaa945,0x000168ff522d27d2,0x000f04d6f9e7bc72,0x0007480f7268bfa7,0x0000868c73ffba41}}, {{0x000c2db7be0eead0,0x0002ff7191359f85,0x000ea90d7511e784,0x0006315a06b1e9c5,0x0000c19e28326fab}, {0x000f0cfe9206c550,0x00043553c06a8af8,0x0005f800489389cb,0x00091d39dbed97f6,0x0000621b037c5089}}, {{0x000e63596e78cc4c,0x00014c06b4a81c52,0x000e87d035385c8b,0x000fad184ddfdbb0,0x000049dfb67534ba}, {0x000e17059f707727,0x0003ca1db56b7071,0x0008af1903a073a8,0x0000ef934949033b,0x0000d882de443292}}, {{0x0003f0ab2cf89408,0x0007ef948f519163,0x0002653c872b0b17,0x000a04ad28dc3078,0x0000882984a5b903}, {0x0005d0c6a19d2bbd,0x000bb6f782cbb809,0x0009070644b9e7f0,0x00043baaf739882d,0x000012be0ff5b326}}, {{0x000d23d0e165dc33,0x00021e2378ce358e,0x000b8a0873d47ce6,0x0000b94e2bb0b9fe,0x0000246e8af129e1}, {0x0004ec703ce2b4df,0x000acbc077cf459f,0x0009940c1e9b4ca1,0x000eb03613b4f20e,0x0000c598bb9f47d1}}, {{0x000c62b45036099d,0x0001467c65d89744,0x000be1943a9dee74,0x0006233c511525da,0x0000a11055563c6c}, {0x000a52c651a3be27,0x000d184449a6ae00,0x00033bed1cda5111,0x0006b3963c06f4ff,0x00003baaf9a7d3d7}}, {{0x0000c9d7fc63668b,0x000c5c039cde52fb,0x000b223516886c9d,0x000c12b02bd59955,0x000000cab02e60c7}, {0x00016bc81b69442a,0x0000155c3cee8cb6,0x0009ba2784148670,0x00070fd1093281f4,0x0000d956d9d04a50}}, {{0x000f28b638a7e819,0x000ec980ddc39561,0x0006f247a54155cd,0x00010022db4a96d2,0x0000d774e4ed787d}, {0x0006e2e078637d27,0x000cee0ae06a1a9e,0x000cfa3541c363e2,0x00098d0493483ee9,0x00006843cb3ef74b}}, {{0x0006591d4b66947f,0x000714460a8cbaca,0x000768f55b452ce9,0x0002de7830d24643,0x00004197ed96dff1}, {0x000b472400dd0f70,0x000f4b1e70936521,0x0000338ae59f5ca8,0x0003c66feff11b08,0x0000ada31f6a29ca}}, {{0x0004eb694a2c2152,0x000ae5a57ab42479,0x0006f89fed83a43a,0x0007c2064a543a2a,0x0000c2a3868fd5ec}, {0x00039408439d9b28,0x00018acd1f11d337,0x000e6cc19715ea67,0x00085bc2c1d235e7,0x00001ce6e9739905}}, {{0x000dfe0d809c7bd0,0x000c8f1050ab04e5,0x000a4176fd7b2580,0x00097c6d91ad78d8,0x0000af556ee4e2e8}, {0x0008b73921de0acb,0x0001cea78400162a,0x000ce217452ac9c2,0x000f793e2a4eeaef,0x0000e61844f1d637}}, {{0x000f1bc789a283b1,0x000d780836f40491,0x000e5402d72d3ac3,0x00073d9a1c5ea388,0x0000b192421e5cc4}, {0x00099989dc84cacd,0x000ccc6e75b85c0b,0x000191ce2b0a8482,0x00092f939961d03a,0x0000a3bc8663d837}}, {{0x0000653056e6f8fb,0x0000b4d133a7ca99,0x0006abe4084861c4,0x000302db40327674,0x00007b4d51b9bf8e}, {0x0003211220a255d5,0x000bb2419e6e05b4,0x0000c2feac997152,0x000ade26ff47b663,0x00000518677781fd}}, {{0x000b8bacf902b0bb,0x000487db303b3283,0x0005011bc8d4b4eb,0x00019b1c89f42d75,0x000043d74bc8d09d}, {0x0006bc98adba3503,0x000c851c19276574,0x000ad72ec364eaf8,0x000c1fe3c7659610,0x0000004512228d40}}, {{0x00099b7ea7b979b7,0x000476fb3bcd6d2d,0x000cffbfecd78cd7,0x0004f5a1e45a9e86,0x00008a61cf4d3702}, {0x000c8723d502295f,0x0003558cb288d06b,0x0002f8586f137685,0x00009dc9db26a134,0x000033effd03beee}}, {{0x000c4cdb30cfb3a6,0x00010c9db4c8d7e0,0x000c8d9df6d09b8c,0x00066ce0ba1a4207,0x0000fd495f77c52c}, {0x000169f275264daf,0x0005f57d8362fb0e,0x000ad722280c2b74,0x000c7afdd987f749,0x0000dc229b03398e}}, }, {/* digit=25 [{1,2,3,..,}]*([2^175]*G) */ {{0x000ed8452666a58c,0x000026a9c3c2b0d1,0x0009064084bcb6e0,0x0003ff7c57411c26,0x0000fc20755d3556}, {0x0001c505294dba30,0x00068b7dd31ea08b,0x0001eca74a30ba28,0x0002b9d70ba90e99,0x000094e142ce762c}}, {{0x000783e979f39254,0x000a6f4c89a7b81d,0x0001bf7fa1efd130,0x000a9e125c2144fd,0x0000b2969045b265}, {0x0009634b9db65b69,0x000173599d8aed8e,0x0003563f335c82e3,0x0008ab4aa7a54f40,0x0000df088ad922c3}}, {{0x000b066bb3fd30a1,0x000adff0354ee5cf,0x00024e36c429169d,0x000e1d709cf85235,0x000036f4fb31155b}, {0x000af011fbba712e,0x0003706ba1a14826,0x000aea73e6ef0f0b,0x00044df9928b3177,0x00002bf6af33eaa2}}, {{0x0004f124237b64b8,0x000963ecfd078d08,0x000845dd8688ebe9,0x000324d7b8a70cf6,0x000008fc59cdda4a}, {0x0002b2ba3585862b,0x00053df29386a903,0x0001ec29bb66825d,0x000dc805a5a8db43,0x0000b143a98ea1e8}}, {{0x00094ce12ae381b9,0x000bf6ccda9035ee,0x00006eaca3a7f176,0x0004df363a657e46,0x0000ae5a380d3cd0}, {0x0008d15ed251b464,0x00008aca5e649bec,0x000f20f071f5d6d3,0x000285f47b3b359f,0x0000d65f03537e4b}}, {{0x000ba24f111661eb,0x00040105eb049e93,0x00024b578edced48,0x000068e6dc9ba1f4,0x0000f8f66b8983e9}, {0x0004df4d7ed8216f,0x00069e2cbecf872d,0x000e73754bf07f37,0x0007075281d89998,0x0000ec85fbc7aab8}}, {{0x0000deea5ba5b0b7,0x000dd2d052999a3c,0x000b02d42e6a116c,0x000cb63e9775fee9,0x00002b0520111545}, {0x0006f7d31a3b4ea6,0x00082bbd9b32bc50,0x000b12a97e589307,0x00067168bc5f37e4,0x0000b000c06aa73b}}, {{0x000bf22765fa7d04,0x000fdd6a537013b5,0x00080db9859805be,0x000ce327a5e29d42,0x0000f53916fb76b1}, {0x000f61f33ddf6269,0x000e1085d103714f,0x000809ee34206238,0x000b1c8c50d4b7e5,0x000099f450e15f8e}}, {{0x0006051e4c79e9bf,0x0002d66a9fea658a,0x000be7b231394cb7,0x0008fd37f31ed5c6,0x00004c88f374aa6f}, {0x000721f4aaa499e0,0x0005e3fb2a6b0fb0,0x00092851d68b3a7d,0x000913a788097d3a,0x000060e7f8ae96f4}}, {{0x000be731a3a93bc2,0x0005821adc1a82ee,0x000030efd42bbf46,0x0007bba10b6fa4ef,0x000047aa4c7a7b09}, {0x000c632f60c77da5,0x000a7223523e8b8d,0x0004579cf6ffbc26,0x0000f654f6ff1134,0x0000825653ce8025}}, {{0x000097ebc1aa2b92,0x000317a0333ab2dd,0x000a0db380788939,0x000612fcf55e7137,0x0000648487f992c1}, {0x00013363fcef2614,0x000cceabf129dad0,0x000276be26239c81,0x000ad34ee761de9d,0x000006a7a345eda6}}, {{0x00067ba4a493b31c,0x0001dbf7f0264bf3,0x00095914b54f20a5,0x0006abf696e06297,0x0000ddab96e4bf23}, {0x000c70aed25ea138,0x000b01cbbbe74ff2,0x0008544c5fa1d09e,0x00031708fc8c8746,0x000047a670de96b3}}, {{0x000421e64bcb626e,0x000746dee0b5f133,0x00010346caea638c,0x000ed2f6e7680bb3,0x000006f4098b5d4c}, {0x00014527512a30b9,0x000d5589a59a0996,0x000d0c180f3d867f,0x0004ab9e73254f52,0x0000063d8a3c33c7}}, {{0x000c595d314e7bc2,0x000b267899ededa6,0x0001ed5d32ee7464,0x000612fcef423c0a,0x000017e76ea89cc7}, {0x000ce1fe7cda917f,0x000a9a893f1627cc,0x000c74f6b12d8016,0x000e60ccd6de849f,0x0000a5817e3e3144}}, {{0x00041640821ee4c9,0x00037bc619921f35,0x00072879f1583eab,0x0007b1e490caf61d,0x000098ad9f4876ae}, {0x0001950a41157f70,0x0006e8da3a7e1e18,0x00026b95fa9d7e1e,0x000a10963784eb84,0x0000ee4ed6e542e2}}, {{0x0004cc5ac751e7b7,0x00028d4211bdb79d,0x000de4fc693f9647,0x0000641c72d3d2c8,0x0000b69cbf64f44f}, {0x0000ca2f4bf94e19,0x0008612894e23da9,0x00017d60b1a5325f,0x000b5c7a437f6c79,0x0000be7048726c9c}}, {{0x00080bfe1dc5c055,0x000a9ebeeb57b4d8,0x0000fe6a3d738add,0x000f5a1f0119d3df,0x0000c686e55b6eaa}, {0x0000b50dfd0b7ec5,0x000b1a497c219cb1,0x000546c96bdd0264,0x00042aac0935148c,0x00008a947fac9dbf}}, {{0x0008d4e49ccd6d74,0x000c48bd5580c0b4,0x000d473b2ff8fb02,0x000af3875235e907,0x0000fab1ac5e2188}, {0x000a3bc97576ec06,0x0007ab7e7d2f030f,0x000305600e8c946e,0x0003b3e0a5c9cc70,0x0000d8260aa28b01}}, {{0x000304f70bba85cb,0x0000f4a0d3110368,0x00015eec1ad090da,0x000a46c170e87024,0x0000fba35ff3461e}, {0x000019ac1e919380,0x00031afc415f6279,0x000ba0e0fa47638f,0x000c4836c65cbbbc,0x00002160efb034e2}}, {{0x0001073615cd9e45,0x0007a1243c06e6c5,0x0007b3d8c498ec04,0x0005f0ee5a8809b1,0x0000cd99e615cc56}, {0x00012df7851dafeb,0x0009f79061e281e3,0x0000c590ef156f5b,0x000aa0d0d62b7188,0x0000ec9746fba39f}}, {{0x000a9c1c8ed1f7a4,0x0005681d5ff21d98,0x000a0794a09e43bb,0x00083695f00f680d,0x000012050d9a61aa}, {0x0007c4e90747e405,0x000b662a3686a89f,0x0008e33536dc05eb,0x000bb98f4de84730,0x00003868fbbefb53}}, {{0x000d2c3cfdcf7dd0,0x0003723fcab42b09,0x000f57ca341a9fce,0x00055573d905f707,0x000080f9fb1ac8e1}, {0x0008e849ba7a5317,0x00067d9a147f7c08,0x00048c33607d3558,0x000e78f02846abaf,0x0000320fd327ccf0}}, {{0x0000798b18bd1ff8,0x00002fdd2905aa78,0x0004267cd52c2e30,0x000b5f727ea3d643,0x0000b96d16d95605}, {0x00010494b45706bd,0x000da43d25f87bb3,0x000f30076e7f58b8,0x000d5a19b5e45b87,0x000019448d72d053}}, {{0x0008cb9d3210a041,0x0003cafb52691ecc,0x000c3489f6bc7d46,0x000e1b2e59b10a67,0x0000769788c75641}, {0x000b82dbd6cb838c,0x0005636d5f228a53,0x00008536e7066d6e,0x00080843aa1c6169,0x0000971da0e26ae9}}, {{0x000a86bc49a2fac6,0x000fd092e77a01b3,0x0006fb5563b8420b,0x000a86a20573007d,0x0000941b2a21ff40}, {0x00063080658ff2ac,0x00027424ab36140b,0x00051e2998780436,0x000e394253bd5157,0x000075bcd77049c3}}, {{0x00040907f8f875d6,0x000df6c26bbf92eb,0x00010bbe79c9d754,0x0001e9b58cea6181,0x00002a6b802d45f9}, {0x00041aac6e7394b3,0x00037d57ef10a79c,0x000a6f40c445b6a8,0x000364dc5277eb6e,0x000019fe96bb8633}}, {{0x000c61f385f63cb6,0x0003c2bdd1270b0f,0x000e942c241250c8,0x000d5d07d153f109,0x00000920d092021a}, {0x0005746724d81a52,0x00023bba3299229f,0x000413032b7ffb89,0x00094c318c51a1de,0x0000a9bfe775c2fd}}, {{0x000e2393191f4fd2,0x0006b3d6ada1cbcd,0x00076960643093e1,0x00025bf84579f358,0x0000c94a8b3f2366}, {0x000b9c05c437d8e4,0x000398d9f3c86922,0x0007090a23d4ae42,0x0005bdb72c31c12e,0x0000ac3f5f4176a5}}, {{0x00008fc6b6af9917,0x000fab5cebbd3425,0x000440dd70d5270f,0x0002fd484740d0dd,0x000048ef841e8016}, {0x000fe0edfc6fafb1,0x0005e7300f27a8db,0x000ba4ec9eadfdf0,0x000a976d06555ffe,0x00002c56f83ae25f}}, {{0x0004203d39b8c34b,0x00058125eddb77f8,0x000e39dc5ed8b1be,0x000789abbf2441f6,0x000000f6ee71a5d6}, {0x0006ecf57d0ea992,0x0007f7e06c43ba45,0x0005b4baadcae0f5,0x0009bde1643de40f,0x0000c324341f161b}}, {{0x0007f55e126d4682,0x000f56748e098017,0x000a9bdc2ed325f1,0x0004684116004acf,0x0000d8607e65a9fb}, {0x0003e276009d660b,0x000ddd10c5a10e57,0x0009009a03a525d2,0x000448226cb45c3b,0x00006b0cdc18e9d7}}, {{0x0009976e1337c262,0x000db73d68e5949c,0x000b768d96faadeb,0x0000697e158614f1,0x00002dfa557bcc4f}, {0x000da17be93c6d61,0x00019504f5b9ccd6,0x000694da124866c6,0x0008c61121353c8d,0x0000c6ca5801140b}}, {{0x000ad8ce964021e7,0x0009932b82b3c245,0x000ef9898b83bffb,0x00048a8aa220c647,0x0000e8d3ac7082c9}, {0x0002091bc2d124af,0x000c15b15ff41faa,0x0007c6fb7bd54c3d,0x000f65486bf3abc8,0x0000b2b0564edeb6}}, {{0x000c5575b45afb42,0x0009cfb8912d4e77,0x000f6e557e9ded64,0x000f005ec9bbf542,0x0000570dfff82671}, {0x000fb7888e084bd4,0x0008b37fe5b42b3b,0x000649aeea024b23,0x0001d804e7dc0495,0x000098ca2559e7ec}}, {{0x00066eaaaa07e869,0x000b636085863bc7,0x000c259c80db6fac,0x00049f2add2549bd,0x00005af3c6e941c6}, {0x000928c02e30afbc,0x000c408a88b8b36a,0x0001d9e9d9b5356a,0x0008cd8b67a5f1cf,0x00006542e4865d8d}}, {{0x0001fe87adfb6cc6,0x0003386781417306,0x00080515acc826fd,0x000082a0e758b13c,0x0000afe3247a1485}, {0x00008b9b6ae8a751,0x000d3acf51e10fcb,0x00061b9d6b8cf388,0x000d0c244a556069,0x0000a6778b87a97f}}, {{0x000fdc1ecc4c7e38,0x000c96db68ccd840,0x000e216aade9fe47,0x0008be695f89dea3,0x00004f1a6a51594a}, {0x0007d725a7b162b9,0x00091dc817a37ddc,0x000b58d46c5cfda1,0x000f18f0a5d35078,0x00003365b1412978}}, {{0x000d22526a1fc900,0x00024d70705d2e44,0x0000c45f40d6d10d,0x000079d94b6b10d7,0x0000f201022b216c}, {0x00066c5658fde413,0x000d4e27601dcec9,0x000230be7a8d2bc7,0x000fb58fcce3e1ff,0x0000394ff6b3033f}}, {{0x000c5098132c9af4,0x000af61e7868d890,0x0002d15aaaac4b0e,0x000b7d1194ded3e8,0x0000550bd2e63ae6}, {0x000318eea5399d41,0x000a81638b803fda,0x0004aa12dd989bff,0x0009444ea124d0a1,0x0000fb1b8994667b}}, {{0x000796944c44d6a8,0x0009d7e8613795ec,0x000adac4491df144,0x000801115fd62073,0x0000f01732dd9a83}, {0x0009d253aa0a6332,0x000ca9d6d59cec57,0x000ef801006de5e7,0x000a02a132f958b1,0x00009476f97065c1}}, {{0x00077c0d34c35659,0x00018b9f1e9e336a,0x000e08002ef1105b,0x00009dd3e6d08bf9,0x0000aff2f2256138}, {0x0004f853a80e75d8,0x000debbda681b575,0x00097fd7ade71853,0x0007fa06f041df81,0x0000b332e0892781}}, {{0x0009be8b9c20cda9,0x000545cd0c9805d9,0x000b9418389f7aad,0x0007f1eef936fe5b,0x00002ca0754405cd}, {0x000db1174a1e0359,0x000783eaea929d65,0x000e4fbf202628cc,0x0008b762d9e24249,0x00004fdfd9c7384f}}, {{0x000605463428c6ba,0x0001f0b409a565f5,0x00045ae112f7205b,0x0003b25778bb78ff,0x000013045bf65ee5}, {0x00014ff03ef77fee,0x000f1fef8befe00a,0x0009ade22689cd59,0x0006a75578f0ed1e,0x000099f3ec14268b}}, {{0x0007d91ea1b3c3ec,0x0002f8823a4aa205,0x000ca451e2d1a705,0x000b5cebbb336a2c,0x0000d2466e3e218b}, {0x000f42fc8cb762d2,0x000e5690211f3ac1,0x000d074507e312aa,0x00013fcbb9bd7345,0x000007c4b8266c22}}, {{0x00025c1375913eca,0x0005c790822099d4,0x00067dbf694e45e9,0x000056208f3087cd,0x00005670fbf60887}, {0x000b64a66f5b8fca,0x0009d86fec286717,0x000ff4952d5a56ae,0x00049b08c3f55fc0,0x000077fefaee57ac}}, {{0x0002d7c98379d445,0x000b009edc8a2988,0x0006fe464d000bdf,0x000de076f95979e6,0x000004a61164a61b}, {0x000b871effea31ae,0x000d10c21a5456b3,0x0004753bf2d3de26,0x000d8541dbff3183,0x000067ecf4a49269}}, {{0x0006952151fe690f,0x00038f2adb5f7a17,0x000b62a8d0351580,0x0004e5fe794b15d1,0x0000004ceed9ae45}, {0x000ea7cf0386fac2,0x0002b1fca7510897,0x0007a04ec3b62ff1,0x0007ebf54181df1b,0x0000008e04b1b584}}, {{0x000148e41dbd7725,0x0002d2942654d147,0x000c544f72b419f7,0x000149169f30d3e9,0x00002a2c22418540}, {0x000ee14634dfb02e,0x0000147869f35da9,0x000933acc5f074ff,0x000ed094ee878da3,0x000065106522fe35}}, {{0x0009482f1012e7a7,0x000038a566aeb3eb,0x000c00d3b51013cc,0x0000e56d5e924347,0x0000fde089e046bb}, {0x00054fec731b4b3b,0x0003e9fda0620307,0x0001a35bc12a136a,0x0004eecc1064b85a,0x0000f1f5763f46c8}}, {{0x000a56da16d4b346,0x00097ca21c4fed29,0x0008de4867fba9d0,0x0005e106d7ac006d,0x00000061987d3a2a}, {0x0000f869da28ff0c,0x000783c4599c8b40,0x00028cb0d3133f70,0x00061cd911c9b8ee,0x0000d7e28754e0af}}, {{0x000f0f272ed91fcd,0x0000ccd4a3735a85,0x00025253c85214f3,0x000c75b81fe5be19,0x00008dc98e161e8b}, {0x000affe585cc3a25,0x000d235bf97a7120,0x000b34581724952e,0x00057d0581e7dc3e,0x0000cbff4f3352ee}}, {{0x0000a0e87d8cc7b9,0x000361d280d08d32,0x000eec7049beaa7f,0x000056ea0b95719b,0x0000126332eeb7f0}, {0x000c1b48ed3bd6db,0x00022945eb2401fb,0x0008ae25535bb2c1,0x000fb2b404694e9a,0x00006092eed3d6ab}}, {{0x000143fcc058865e,0x00018e2499224d76,0x00050d3537b0a5af,0x000079aaef94406a,0x000011e4bcd44f0e}, {0x000993aa14a90fa5,0x000c6a0c51d44472,0x00032672d7706e20,0x000382a403292f15,0x00002573bfa71829}}, {{0x000b6a93b5bdb831,0x000094a723186a7b,0x000eb065f08da65c,0x000685b58d22aa63,0x0000717596c2b15d}, {0x000f0d0b266d88b4,0x00071941945a112d,0x000292cacf688ae9,0x00085c087386e37c,0x00002f3b50d97d69}}, {{0x000f9986a90fc34e,0x000285ca8a8d6da4,0x00051f762c8f257d,0x0003abe2feabca69,0x00001bc81d154c32}, {0x0008f67251a2a12f,0x0006ce8a70dc1bc6,0x000f84d2e10d8658,0x000c91e648af7ff0,0x00000aa9ebd5a43a}}, {{0x000be04275968936,0x0005e5bf452b69e3,0x000c698c8b6bb02a,0x000793a875c11af4,0x0000652b5c81ece3}, {0x00055fd4f5c04999,0x000825532b387b37,0x000e96ef76ea1655,0x000f4841c69889a2,0x0000c773c3af1ed8}}, {{0x0003a409b323abc8,0x000170e1d7912b65,0x00087157ae26605e,0x000615c5d410644a,0x0000f9a78b84bbce}, {0x00044aac407eddd6,0x0008435b964fcf1e,0x00008399981ddd1d,0x000801e73e339efd,0x0000c94bddeee796}}, {{0x0004ada8545d185d,0x0009a38bb8cb5a30,0x00087e10e82ae44e,0x000fe2928a35e3df,0x00003624f3e715b9}, {0x000209b14be42542,0x000c9dbc2ea5cc44,0x000c37bbe7d0efcb,0x00052bff60336204,0x00001f363f576a58}}, {{0x0003d1ca85015501,0x0001c8ab10bba150,0x00061c51c2251e0e,0x000f68ce129c9669,0x0000f7246a491910}, {0x00044ee5f2591f26,0x000efe6271572eb7,0x000f3bd683c47d33,0x000855ed6d62c922,0x0000120a64c2b8df}}, {{0x000c6c07b5d07df4,0x00083ef397833a9a,0x0003a9b4fa92b955,0x000f05a128a134ab,0x00001c18807f1252}, {0x000d08980ba9b1c1,0x000eb532a9ddfc7e,0x000246809ac8dc6d,0x00080faf829cef55,0x000001b784f6b4ee}}, {{0x00045bbb6f116037,0x000dd1d2801ec099,0x0007534a857b09db,0x0006148ba5202fa9,0x0000fd8ae60317b9}, {0x000a66678308435e,0x000bf3868c4da50b,0x000d7aab09572f77,0x0009fe2cef7bfd2d,0x00007958e090c7c7}}, {{0x0002e42253466896,0x0000507c70048126,0x000950ee3716da29,0x0001b4d5f911eab7,0x0000fd72969861d2}, {0x000980308b640d30,0x000e887f12a15238,0x0002e93115b0026e,0x000ff720e2166074,0x0000ef6d5415ff77}}, {{0x00027f0f9c41135f,0x000878a649939691,0x00041875cf21d60c,0x000232756e5d0ce5,0x00001e0f84f91d3c}, {0x000a35906002d609,0x000b761915529bcc,0x000181ec3be2da60,0x000f18cda8bbae61,0x0000f04b823f5806}}, {{0x0004a7dd4b79bb87,0x000ae2c878c8f160,0x00047b8e8aee806f,0x000053c4144f118d,0x00002edf52c049f9}, {0x000a84e2127015a3,0x00006cb7cef3ebfc,0x0006deec89051d0c,0x000d7456e8fe5829,0x00003b2818871010}}, }, {/* digit=26 [{1,2,3,..,}]*([2^182]*G) */ {{0x0009383171b445fe,0x0002a131ad4c0107,0x0003987e89bcf21e,0x000c8eacdfe205c9,0x000063f4153a92e8}, {0x00062a930add43df,0x0002d980f05a7294,0x00006e96862ebb14,0x0006b05f3954e53b,0x0000e1d75ae142cf}}, {{0x000c6c7af8685c8b,0x000d7f8f01aa5f95,0x00074692ad4c1c8c,0x000068144bbe3225,0x0000800347984a4a}, {0x000c6e52eca3cdb7,0x000b7c04d3997c8f,0x0002bc5cfea1db16,0x0003d2405bc82e8f,0x000063d518064479}}, {{0x000c1b808bd98d05,0x00041575f2404451,0x00075d270644b1cd,0x0006bd1907eb3373,0x00006c8bebe4a228}, {0x000d2acc4632b46f,0x0009bfd60242c713,0x0005c754617da427,0x0003dd413065b7c9,0x00008239899af17a}}, {{0x000963f4c8303203,0x0000603203e3f3b7,0x000327afb842c7aa,0x0009b67f22ca0ae7,0x00008e13092c6760}, {0x000fb62757558f1a,0x000157eca8c173b8,0x0003316273cc3e83,0x00023444174474f6,0x000077989cb63c40}}, {{0x00017a144a081e00,0x000db70e296ae5fd,0x0001f719cd797fb7,0x000c522b472b3048,0x0000e632a98fe6f8}, {0x000d116c5f0c2848,0x000ead987c6289cc,0x0002de6cff51088a,0x0000f8aa2bccda4c,0x000010f9eff7679f}}, {{0x00094b97ffe4b3ed,0x000115fa5d21b0f3,0x000fbbc750b691d2,0x000affe0bd77479d,0x00002830fdbcaf78}, {0x000249c52434f573,0x000568096dabf78c,0x000f8c0b34b1f754,0x00034c43bf6f948f,0x00004aef03d754e1}}, {{0x00051f4b7ac7ec57,0x000a750da7d5f8d1,0x0003a0eb8d6ceb95,0x00086331b492b0dc,0x00005157b6a23dd2}, {0x000c74ec5413d62f,0x0006cc5fc4c7e2c4,0x000fa9ddabe329ff,0x000b86935a2aea60,0x0000117f5ae6445c}}, {{0x00017f4b0166f7a3,0x00079eec74e6ae83,0x000874bfdfbd3e3f,0x0003a3cdb516ace0,0x0000d846019f681f}, {0x000ee5c7c1620b02,0x000d0b63c5010b12,0x00068c51eba68b4d,0x000b5b8c03cd3266,0x0000a6279f76e0bc}}, {{0x00069b06ae85c104,0x0008ddfdd3a617bd,0x000078bec7294697,0x000a5299a032682c,0x00001c6a658ffd68}, {0x00010240e0239001,0x0001a10d144dcdea,0x0008ab8dcbaeec12,0x000cdd4a600e7405,0x0000333af21cb89c}}, {{0x000eae03aaba1f19,0x000dab7144cfdf25,0x000ab98bc2cada16,0x00096dd57ee27d71,0x00009088b4d0a6fc}, {0x000c0a03549dbd42,0x000fd158c3ac05d5,0x000edd68542cbdf8,0x0004d01fb6b3b087,0x00002071cf6a6f06}}, {{0x000721fff2811e50,0x0003fe7fae8cd2d6,0x000f1f7bbdb81b70,0x000b5d3cfb74efd3,0x0000cdbcd7616cde}, {0x000642a566a808ce,0x0003540064d64f39,0x00028fa6f02b7445,0x000bb61abbadca05,0x00004c3074db3fc0}}, {{0x000b8b0b796d2197,0x000ec4741dd9b32c,0x000edf6f5c3e95f4,0x000b8e1721212568,0x0000a03aee512b9c}, {0x000c376f53a89aa8,0x0001148a28dc0cd3,0x0002ab04f0d8af9b,0x00002d4f86a3f490,0x0000aacb62aff420}}, {{0x00085ebf62ffd521,0x000e4797bf101069,0x000e30aefe670b54,0x0005e93b405209c5,0x00002c97a205365b}, {0x00046ce1fe32093e,0x00055907a8c91046,0x0006e726b13cb4ff,0x000498ab9f30d1d4,0x00001985e228ba0f}}, {{0x000dea910a230cd3,0x00039d30f947c573,0x000e2010a24f46a9,0x000e4fc2623fcfab,0x0000f278cb2a3f00}, {0x000c67d50b920eb4,0x000d4e760571ed55,0x00095b709f1cb9a2,0x0003693c50d10908,0x0000207cf07590d4}}, {{0x0007e81c4127fe1a,0x000c9ae9c5663b02,0x000bfbba5a9f8b9a,0x0006f4bab10851ac,0x0000747d648f6955}, {0x0002b5c2ba97bf75,0x000d6cfa3324cc17,0x00086279d15e0f77,0x0003d35345b79776,0x0000a72348133800}}, {{0x000139f8f5fcda83,0x00048dee5bfdfd8e,0x0003f9f77f3e558c,0x000969a76cbaf4e3,0x0000a4c97a4a1771}, {0x000e84bf6dce6a73,0x0005e3e6c2d1da27,0x00059a6e9ff373d9,0x00062cc115193cd7,0x0000f9b702593d22}}, {{0x0004a31317cd0627,0x000da99f8332d976,0x000b11b0b30779d8,0x000ed86807410616,0x0000917ab9fe8aea}, {0x0009cbe28fb1d8e4,0x0002d36eda33b67a,0x00071a86c2e31356,0x0006b6c10b7069a3,0x00004d90fa2a744e}}, {{0x0000867d6b3e243a,0x000cb9048c486819,0x0007315389fe6cd9,0x00004f1900b02895,0x0000012062fd2cae}, {0x000c8bc9399d0822,0x000a21df12e28107,0x000ef3f7347e8c54,0x000f0af4ba5117b6,0x00002260beaa1362}}, {{0x000261e1a18cc20d,0x000e5321d63690ea,0x00011b6a02192999,0x0001f51f64d314e3,0x00007401e4d0b54a}, {0x00099836fbca2bae,0x0002afbffc4b1901,0x00086bf4046ad329,0x0009fbc142d3f637,0x0000b5cbc2796703}}, {{0x000ae6c252bd4796,0x0009b2b5848f9cb0,0x000c9766305e0f88,0x00025c18f6d2b2a5,0x0000f6e149c21622}, {0x000235cde601a897,0x00088373be1fe602,0x000471827d17bbe9,0x0001165af49a5ba8,0x0000e1a0a8588aaa}}, {{0x0003196270580c34,0x0009b1c98a146c83,0x00034e0a51e23383,0x00028927b2f7b4ae,0x00007ac874618ce7}, {0x000779a100dd467c,0x00068ee50d092b74,0x000608bc9274a433,0x000387a03dcf1383,0x0000d9da6c4889e8}}, {{0x000199f355116ac9,0x000926d18eed2660,0x0004bc071cc38bb5,0x00057da075f31f2f,0x0000774457fb65dc}, {0x000a9c8c6db88bb2,0x000f2ec98e0406a6,0x000ecaa8b6429d07,0x000a7b6d05e57b05,0x00000f140b19872e}}, {{0x0000f09ca4946937,0x00008252e909df8c,0x000b14b1248d3a02,0x000d1bdc5c29af57,0x0000e6fa37e2f47a}, {0x000b50649a0c938c,0x0007abe5f41f66e7,0x000359412b72c0d4,0x00047faa6242b8b2,0x0000d35c7754e859}}, {{0x0006fea87baa6279,0x0001672aa6801253,0x0001e5dc958c1fec,0x0001b8dc29b63760,0x0000e3c3c1d6e9e0}, {0x000127b2bcfe0b0f,0x00013a12f50defc8,0x00079b3973510710,0x000f207ccd6cb148,0x0000792f805e8a82}}, {{0x0004804a9b46402f,0x000cd10f0850509d,0x0006208aaedddf85,0x0002dba28410dc4b,0x00006229c4729101}, {0x000c41e7727b9b64,0x000b6a444842c5a7,0x000a947ea289e4e4,0x000ebbc49ba1d9e9,0x00004f9e47fc3c8d}}, {{0x000a1fe611f8b8ef,0x000a0518f427fa77,0x0004ebac3fd2e416,0x00097ad5fffa7011,0x0000e57c4ea4d896}, {0x00053acb1aaf6131,0x000fda585a45fdd0,0x00098503431df210,0x000130218cc10e24,0x0000a38efd16f1d6}}, {{0x000f2370b1e9e212,0x000cfdbe88aabf86,0x000c1baf9b258514,0x000691fe38a58890,0x0000936a01eddb9b}, {0x000de986dd5b20c8,0x0000f0f98ecfd576,0x0002d2fd7b586bf7,0x000d7b4ccf0f12c4,0x0000717e61d7b35b}}, {{0x000572235e6fc06c,0x000e4b3e13d58b1e,0x0008a73723477728,0x000289550c294daa,0x00000291d43fbfa5}, {0x000bc67cec5a196b,0x0003ac2e8a7cc6c8,0x0006e1c51deeb31e,0x0001560a93e244fb,0x00009f8b71bde28e}}, {{0x000a287968a2ab91,0x000936bbcb1fce65,0x000ae3f30e3c5ce6,0x00082be8c835b9e7,0x00006bbee270f72b}, {0x0002017fd42cd227,0x000088b1d2a0665e,0x0002049321e13997,0x000ee4a25cda2979,0x0000aee94a5b9c3b}}, {{0x000016089821a663,0x00085f98166968c7,0x000cc3645f7c3767,0x000dfca90829fc48,0x000046af04a070ad}, {0x000b232370bf29c0,0x000e42e650ee2057,0x00026ab90f90c73c,0x00087be03386eaa1,0x0000e266e7e975a0}}, {{0x0008eb90fca65d93,0x0009e6af45b88057,0x000c75a4e7e2989e,0x0006b84438212dca,0x00008c7ca397fef3}, {0x000c494d402676af,0x0006072c7c488650,0x0003a464e26ab5a6,0x0008405e6cb426ce,0x00008f998971b72f}}, {{0x00084911a335cc88,0x0009ea5913e48c31,0x000b32919563459b,0x0005ac9b920d61c7,0x000005ab8b720242}, {0x00012da8d006086c,0x0009fcf5c0fd2ac5,0x0002138d76ca4846,0x000442efea51d8ac,0x0000b647545f44cd}}, {{0x000ee8fbd7d90402,0x000e619b9c960429,0x000a7d744ee66a2d,0x0001bb34f9ec25de,0x0000ffea64287172}, {0x000dbd1114344eab,0x00064d0dbc8b4f19,0x000ec7f910430453,0x00014c514b50aa29,0x00005fc22ff6b060}}, {{0x00063a91ee682e0d,0x00002e85c72760d9,0x000707c2ddf48abc,0x000efe3cadba132e,0x0000e608d3b7645a}, {0x000c28bedafd8830,0x000ebd94de1f05f1,0x000593e413c362ed,0x000eaf8dd0629d13,0x0000a5e736f766d6}}, {{0x0002311f68cf9d16,0x000761797556bfa9,0x00001c209a4f9ef8,0x000360b0d75a1f56,0x000051c374c69b07}, {0x0000b5888b5cead1,0x00085fa9dbaa4995,0x00015f33a0ef0005,0x000140e51ddc264e,0x0000f8b5ca63ef46}}, {{0x000c0a3ee9523f07,0x0002275ea978343a,0x0007387f4bb75eab,0x00062dabccf33210,0x000090f925a0ab00}, {0x00063ad1e4f6a5f6,0x000402519a50f1a3,0x00065f1ee06e08b8,0x00085e0091518772,0x0000a80ca34f3ae9}}, {{0x0009768aaba4864c,0x0001cd52a7d681b2,0x000ad03f1b13cabf,0x0001bff5c363488e,0x0000932ad9641c7c}, {0x000708ecae1e27be,0x00083b0df6485452,0x000cdb8bc9dac426,0x000173433e3f0cdf,0x00006cecce0cc540}}, {{0x000845e95081181f,0x000f799355d5bd0d,0x000b375a8cc8a791,0x0000db211c0f6dc3,0x0000d95bc6ced51e}, {0x0006a266888523a0,0x0006cb01a06d4a10,0x000b9b3974d142bd,0x00091479bfd289ad,0x0000bdbfb94e9863}}, {{0x000a2291660f6a6a,0x0005b51c042d29d8,0x000c3ffe87f6abcd,0x0003fa73039deb0a,0x000001be6298c852}, {0x00041030ca1c3287,0x000d4903928e6ea3,0x0009144b0c74114b,0x000b171aa4ff4e9e,0x0000064091fef9a4}}, {{0x000f521e447f2c48,0x0009e04291f0a3f4,0x0005926de81b8da7,0x00002f5680bc467d,0x00004f21fd5b4a12}, {0x00031814e9df3d85,0x0009e9ab8d341d1e,0x00019aa4a1ca4861,0x000366309ddeec5b,0x00009f72f7e9d329}}, {{0x0003f41386d5087c,0x000c1d67d64fa2f9,0x00070215840bf739,0x000177f449420566,0x000033c65bf33b1e}, {0x000657c38ca61533,0x000aac791976cdcd,0x0006e1f3997f4519,0x0009329c7c7f29cd,0x00008de9cfbae3c3}}, {{0x000eba37b793f853,0x0009c067e914e448,0x00014ae87e9f8dbf,0x000e2a90390266f1,0x00009ed75a7fd6a8}, {0x00048487ffba390a,0x000acaf9bc09adb1,0x0007476db67f8cb8,0x0008d5922c38489c,0x0000320fecff2a53}}, {{0x0003002b2aced2bb,0x0008b16bd430e049,0x00031be70dfba180,0x00044fa31c4644c3,0x0000c04d32f40d2e}, {0x000a0d10f9f142d6,0x0004e7ee5a231805,0x00089b4e32c44a0c,0x000480d1875a4339,0x0000b1949fd6c063}}, {{0x0009e08be0f44920,0x0003e9d5e5172dfb,0x0009466a83ff0da0,0x00093203dbe9a1f7,0x0000b87bcd015ea9}, {0x000fc83ab1f58ab6,0x000a217edc8aeb64,0x0003b67e56d9598d,0x000853099cff661d,0x000045c0f29f2635}}, {{0x000dd82eabaf21cb,0x00097241659e253c,0x0009f709182b9602,0x000d9a7cae07ec2d,0x0000e4c720d3b48c}, {0x000bc036f08d6c97,0x00073f10bf406ce5,0x00010ff1236e8a99,0x00049413422d213e,0x0000b26d3ec2cc12}}, {{0x000d2d0c9469ad61,0x000d20afa05bb240,0x0006ba286c4a11b4,0x00064c3b604acedd,0x000084866004ee28}, {0x000d6ba8d9ce5be6,0x00059f4bfb0d5869,0x00000cf730d8f68c,0x000135569f210b57,0x00001f6653acd37c}}, {{0x000432b5aff5a48b,0x0008c2ba3a69ff3d,0x0001899ef0d81c4b,0x000afd3e879ae9fa,0x0000ac7e2a0dd6ac}, {0x0003f6c1c664399f,0x00006bcb135dd6d9,0x000ab7cbf4c288de,0x0005ef93031dab9d,0x0000e23feb12abbf}}, {{0x0002466cdedca850,0x00001a09538c9f1b,0x00011115d140bb71,0x00059eac8ae8515e,0x0000d63ff676f03f}, {0x00055517d234afbb,0x000dce208fc1755e,0x0008a4b5d61c2db4,0x00030efa9859cef2,0x0000dd6d4fce4af0}}, {{0x000a26d3be01cb1e,0x000b443aa07cd1c4,0x0005035029ba14ff,0x0003ab195cd3a9b2,0x0000379bc075d2a9}, {0x00018e9d4ca8d68a,0x000be0bb412a3efc,0x00045a968083558e,0x00054f3903b94096,0x0000499f0b73ba60}}, {{0x000573cb8349abe3,0x000500b4fc1c208b,0x0005249903baab3e,0x000e8057e978bacb,0x0000524194efcdf0}, {0x00017257d4bcc42b,0x000b090109ba6271,0x00023e1e0e90a3d9,0x0005988b1bdd5713,0x000078e9bd60eae1}}, {{0x000b7469e03d2781,0x0005c70e62970794,0x000c978558017860,0x000b5c071792f899,0x00001b393ef05a86}, {0x0006582d8884f278,0x000a3f19ba5f48ef,0x0002062c6bd44737,0x000c540698de4ca4,0x0000975eb80e1ce9}}, {{0x00057c7d7fe71f3b,0x00000c97ce38d50e,0x000f07b631534219,0x00087ca1bda2de4d,0x0000a12aeaed00eb}, {0x00035d2a9b4f8f67,0x00058ad6d99cabe1,0x00094937c04619d6,0x000099da6683a779,0x0000a778c8bdf94f}}, {{0x000862320a71b899,0x000c8c2291658c50,0x000f83a99241a2ae,0x000ac7a52be595aa,0x0000fbfee7fa562b}, {0x00058b95c4017e32,0x000ff5120b86eaf6,0x000034d6f1dc7f9d,0x000038b84f13dd4c,0x000083dd7380aea3}}, {{0x0002609cd85d6a2d,0x00052ae60177197f,0x00012fede6ebbc34,0x00086ae80f031b4e,0x0000e55d0c2d7a21}, {0x000e37f24dcdd5a7,0x00050ed191fb1fb3,0x000023e0d8d602da,0x0000bfa08fb05676,0x00000178c71b59c2}}, {{0x000a3863fe54cf05,0x000eb2bbb475fad5,0x0009d94d7a4a3ec4,0x000ab2caa5ec2091,0x0000d3b63b5f81e4}, {0x00033d85ad3d2aff,0x000ce1ac7a377fa7,0x000779614fbc586d,0x000429382925de40,0x0000e0ffffcd74a2}}, {{0x000e67f906151e50,0x000f55e106493f39,0x0007cf7b7cea27f5,0x00062ddca1d4e1c1,0x0000c326d122fe23}, {0x000ac337dd35df39,0x00093396dbdf05f7,0x000b7db1c0c3b763,0x0004a87912f5ac03,0x0000dea4b70ec9ed}}, {{0x0006e53aae3f639a,0x000c5c278bac475e,0x00090375ffaba0e7,0x000d0976f9e22194,0x0000ebf974745a7e}, {0x000af3ff41ad5d66,0x000c52e9922445f9,0x000cf56aa03c4623,0x000ed322c5bb5cb3,0x0000431181994567}}, {{0x000f2118be489ac8,0x000d39a1104bec57,0x00064e0072821895,0x0000fde10dc87560,0x0000e526f3fdb20d}, {0x000ca775b645aee2,0x000f600e10ff6e71,0x0009cf6de3d1dcb9,0x00035316b5116218,0x0000c5a3e308bb17}}, {{0x000cd3e2a6c6fbf0,0x000a4bf97906c186,0x0009d6901a74516f,0x0007435b4b8f4b27,0x0000c4e57b42b573}, {0x000b229b6e386b6e,0x000cb9deac2775fd,0x000712629b46793f,0x0002dd0eec47eacf,0x0000965f3c5abc3b}}, {{0x000fb83425c65590,0x00060af06fda8dd1,0x000d956df7fc00ee,0x0008a2e98c922533,0x0000f1ef3354fbdc}, {0x0005145b79b8ea2c,0x0004fdbff2882abb,0x000185db740fd294,0x000099aa814ac4d7,0x00004329d7080846}}, {{0x0007b52ed1be45d6,0x000d84cd2c74c9ba,0x0004139b1891dd20,0x00070ffa4d4a7f82,0x00006c177171873c}, {0x000c1412843c4e0c,0x0006f97eb5bf5e5b,0x0000c95c7d5ac481,0x0006c500f8af5445,0x000091b3fa0f1840}}, {{0x000340aab9d97f89,0x000700a2d611360c,0x000a6f7e5fb57bd0,0x000a0fb339ae3ca6,0x0000c1fcd2abfeb8}, {0x000cca9c7ea74322,0x000c108076f6972b,0x0005b4ca51b0b924,0x000b2960b2814a2a,0x0000f78f55b81ef3}}, {{0x000744ac18a414fe,0x000db03d0a86f838,0x000453f55c611eaa,0x000278b4dabc162a,0x00006f2e3daf4efb}, {0x00060179320dc3cc,0x000ecdf6b5a45b7a,0x00040fa90692e382,0x0003177f5e15e02d,0x000087883af243dd}}, {{0x00053e453544774f,0x000b4adba2bc5110,0x000e371f5834d0ec,0x0003bb5215d7f7ba,0x0000cfd57c05c866}, {0x000383dd6901b1d3,0x000485587dc3ded2,0x000625f623b49fbb,0x000762cd44a08d07,0x0000ee4d65bcde9b}}, }, {/* digit=27 [{1,2,3,..,}]*([2^189]*G) */ {{0x000137d0d63d1fae,0x000122a9d89f64e5,0x000436309658fc05,0x000a606889487450,0x00009ae30f9b598d}, {0x00010d1818baf918,0x00060b6a0c202ed7,0x0001a6b44e27e9e0,0x0007db9e28dcfb1c,0x000083acb6556ac5}}, {{0x000728dc2c6ff707,0x000f55dc22358735,0x000e277f979d6122,0x000cc6b3f5d00319,0x0000ee84e264ded8}, {0x000afb063cd880a6,0x0005d574af6091a8,0x000de7f423f3ea7c,0x000151acfcdc8402,0x00002d07930131aa}}, {{0x0004e438a5807cef,0x0002f4109a7e8e1b,0x000d59ddaad28389,0x000092d30cc9cbaf,0x000065f36c72d8d8}, {0x000469ea60d32b2d,0x000a6e8191c8df31,0x0005bdeb5ee93df4,0x000a27cc1017c535,0x000026231865616a}}, {{0x00083f9dec31a21e,0x00028ad9d573b02c,0x0007be365988c8b2,0x00034d73e983aea5,0x0000968734e446f8}, {0x000ea8f5da6309bd,0x0003f1f1ce169137,0x00044092110f3a62,0x0001b4a82a9ea2ca,0x0000f94739f2b46f}}, {{0x000e006cce85c9b6,0x000644c7c2d39f9b,0x000fa1e60360e70d,0x000b6cccd5beeaae,0x00004cf63c0ec3d2}, {0x0007fa3e1cf6f904,0x000695e044e6fb10,0x00034db9fb7e937c,0x000bd034e8ca78ce,0x0000f8b36c17e210}}, {{0x00065a434a35ea84,0x00070d4412f61df1,0x0008836c33418e0f,0x0009651af1f8af51,0x00002ceef4d530e1}, {0x000ca0b543a1957f,0x0004986cb1235560,0x00098ed30c33761e,0x00097c76624b1ffe,0x0000772f4c000909}}, {{0x00040bb4885d4104,0x00005ba5f8d7f4e5,0x00098dfb17287f81,0x0008a2e2d0d865de,0x00009ff51a1fcfbb}, {0x000fa536bc3012e7,0x0001a70d541db6b6,0x0000f49663d31fd7,0x000e071018724f4b,0x00009e7399ff7dbd}}, {{0x000410ef4f8b16a8,0x000e447b266a56f8,0x0009c87c197241af,0x000b1a8a406b8e6d,0x000003f3e034d42a}, {0x00009a804dbec69c,0x00067bbad05f7f03,0x0008e197fa83b85f,0x000dc106097273ad,0x0000097440f1067a}}, {{0x000afb63524ff164,0x000e423fc6ce730e,0x0003e4ac0d7f9b51,0x000216e7bd0d3244,0x00000c59ad98d66f}, {0x000136f17c387a48,0x00056b86804d6c33,0x0005a73c95043b8d,0x0009b5f497031267,0x000038fdb3271666}}, {{0x000b6dd418e7ddd1,0x0003372f19d6c507,0x00027eb4d39888d9,0x0008846eae26be0c,0x00007b53ed40babb}, {0x000021b2b01ae4fe,0x0006ef488682fc27,0x0005e2d8788462e8,0x00029adee096ec21,0x0000b2fea9bb242e}}, {{0x0005b5fb821fc28e,0x0006fc1e2ad25d98,0x00030ba6289d2e19,0x0001c575b566b890,0x00003fd41b62f41b}, {0x000ac2eb9a96d612,0x000a169443f4b738,0x00003a4407f8567c,0x0004dc6698622df8,0x0000b586236afe2f}}, {{0x00000c756b95bce4,0x0006216da680bbcc,0x0002142525ec0390,0x0002d239162ee672,0x00003132b63c6a89}, {0x0003ff22f3263bf6,0x000c3cd0a1424bdd,0x000415ccbd5b3733,0x0004e9f92eaa8244,0x000063e8924ed547}}, {{0x000a25e5236344e0,0x000dbda76ee68058,0x000cc3d2282e8df9,0x000529dcf6efd811,0x00000089cda3b4ab}, {0x000a071bd38a3db5,0x00009f72b92591d3,0x0003edf754ea97fc,0x000ed2bc9fc15bea,0x0000a6297cdf4348}}, {{0x000ab35ce7c42d4d,0x000eb2feab100d38,0x000111b459fd493e,0x0005c276056b6d82,0x0000a11dae243efc}, {0x00002785545a7fb2,0x000c20d507e6dc74,0x00066fa58bdb2601,0x000c29f21dfeeb70,0x000014369a859ae8}}, {{0x00009cb06e0956ce,0x000e210cd34b1957,0x00071a5324c9d254,0x00054d151e13f704,0x000019d6791fe730}, {0x000a628db5c7be33,0x0008824dde05f702,0x0009b2e2ec714121,0x000dbaac18233cf2,0x0000a6bd1e8b5342}}, {{0x0007fa0b311898c7,0x00045d0eac653f74,0x00014d0bce2a272e,0x000ee2dbba5851f9,0x0000a1a966134a43}, {0x00067cea1c8cde9a,0x0008d271abe3e5a3,0x0001615cd9d958ba,0x0000b053ff7eb63d,0x00002280dcf95ae2}}, {{0x000a5c1cf6401471,0x000d4e83d11856db,0x00024c511ea5a2e3,0x000213f4cd6b6dda,0x0000c0f4671f854d}, {0x000b7a9695653812,0x0000becf1f5b91a6,0x000f5d009dc96624,0x000bd4fb22d21cfc,0x0000a05f641b021d}}, {{0x000d566d4312483b,0x000cb43e216f8c0e,0x0000444935179a95,0x000a211c185fec17,0x0000306333a04991}, {0x000ecdb0081a726e,0x00056fa89bbbd801,0x00091b6b90149b0c,0x0003a2cfe9065a43,0x0000dc92787b633f}}, {{0x000c24aae6a8e13d,0x000dcf3897abe408,0x0001a071585833fd,0x000c5e73800e7ed8,0x0000e08e347844ff}, {0x000184ccdeff2e08,0x000a965eaed17094,0x0007c468a49f9387,0x000dd7e35d612977,0x0000c0dcfd1d38c2}}, {{0x000d9e37a6a308bd,0x000f7c2767d3d6d9,0x0008cbeb66237582,0x000d9db74a8bc6f3,0x000094d3f1b9cb6f}, {0x000735bba21f248e,0x00048cd1efb092a9,0x000b03284272ad0e,0x0002249437b69c05,0x00007f047034948c}}, {{0x000c04acba2ececf,0x000ff3a73e418a56,0x000e937250c18126,0x0001a87cb34e9d03,0x000077c871439652}, {0x0009183fa7f9f909,0x000bfc9707ad9456,0x000c1c9a3f2e7aa4,0x0005073ed2c9ba26,0x0000109fe96d0197}}, {{0x00068a9e9adfe1c3,0x000d014e39bb9ae8,0x000fe378f3984403,0x00062885875720f2,0x00003f901e0ea44a}, {0x00025fe3652438c6,0x00063dd1f20bea11,0x000bf7fbdae9ec4e,0x00079bbe740d9ebe,0x0000dbd3ddca2dbe}}, {{0x0002aecedd36776e,0x0008098590396208,0x0002f7065f612c47,0x000210c493b20103,0x0000bd4d8f32ff9b}, {0x000a0aaaac4cb325,0x0006c5ed40053f23,0x000a27e63ea3aadb,0x00066c5cf17ea4af,0x00006125c1b111fd}}, {{0x00044a43794f8dcb,0x0009983c5c362663,0x0009d10a0dcca923,0x000df27d6b6bbf3f,0x0000320c5cb31d9b}, {0x00028ff47b50a951,0x0001bef03371620e,0x000100153933e3b0,0x0008d6e081bf8599,0x000083be9a0d3a8c}}, {{0x000dc5ad6bbe24db,0x000fa38437954e3d,0x000ec2d4cc6c7462,0x0009b1c8193dd765,0x00008df26cd7d3c8}, {0x000e3995a483f8df,0x00068dd3313a98db,0x0000bd37572d8a95,0x000d1575087294ab,0x0000cd892496c259}}, {{0x00043d77613aa81f,0x000f95fe65848a94,0x000b10288801007f,0x000ee780fc4dbc7f,0x000058280d4d86be}, {0x000d82f7c978c385,0x0000bde44d7b14fd,0x00060252fdf1204c,0x0006a5508a1c8441,0x000091554cb11764}}, {{0x00037d6a05bd5254,0x000ac7957b3c214a,0x000109bc948d5f09,0x000ce6c247cdcbd7,0x00000f9e4bb70599}, {0x000fa03f46ad2ec6,0x000f63e3f9eec325,0x0003a457700f766c,0x000b934b556668d4,0x00008d30a619ee03}}, {{0x00081ea77b46a081,0x0007b74806997ddc,0x00033f683cf5a647,0x000c6033a8cb3466,0x0000b867e6ba2363}, {0x00011141f60558ee,0x00024f41450e4392,0x000630e8bcdbcdd6,0x000b429fc04601cc,0x0000a7c66d677038}}, {{0x000b8a504e99fd8c,0x00018785549a7259,0x0000552e198a8dd1,0x00009d4e459a7c84,0x0000dfcf4d10bb09}, {0x0006db253758da79,0x00035ac997e134a8,0x0000c5b7ee643bb8,0x000b5206400bd753,0x0000f97af88441c8}}, {{0x0008820fbeee3f97,0x000fd9091afd34fc,0x00031f35c93e5348,0x000924064b9be59a,0x00001f37864c7e3d}, {0x00034e0943aa75e5,0x00085b8ff6e402fb,0x000cf0d19a18c9c5,0x0008a6b80f31b133,0x0000c9682db58351}}, {{0x0004ca6b709c3de9,0x0001a575b8f0873d,0x0000154bb64a8426,0x0001aad275da1f02,0x00007678cab617cf}, {0x000795f951a95c33,0x000320fccc088779,0x000d8f031dd35b16,0x00085c0270962733,0x0000c5ab10a798dd}}, {{0x00085c341dca5663,0x000aa8622aa3b6c1,0x0001b6dfb7de7fed,0x00028869e84d9290,0x00000a02b0eac4ad}, {0x0001daa2fd3cf36d,0x00070f89e59fc7c8,0x000496733d131954,0x00012ae2be8184cd,0x00005f449ec63d34}}, {{0x0001b1b25fe531df,0x00017a1d56467ea4,0x000de501af979743,0x00089b96067f722b,0x000091481c0fc85e}, {0x000e465f8b05bc60,0x000f02e83cdaca8e,0x000dbe33b1844e1c,0x000de2ca82114ab4,0x0000f9f87694eabf}}, {{0x000b1c038b27fe29,0x000b1ba402df4936,0x0006bdbab63b6359,0x00039bb0c0ea2f65,0x0000c992a89f580c}, {0x0008f152a60aed16,0x000480bf49df600e,0x00042d99aeb089ca,0x0002fa3c233d7d2d,0x000048d3f95ac6bc}}, {{0x00083a8e1add3f34,0x000a0f64a348dcc3,0x00030dbdbf42c0c6,0x00015deabd176f00,0x0000de501a3bd6c2}, {0x0007c1f4b9a64bc7,0x0002b496cd594a10,0x00088dffba77f0ad,0x000d8e8b78ac6276,0x0000025a2cad7937}}, {{0x000b2d1d1a8f4e7a,0x0006d354927cfde8,0x000205735f5b3da4,0x000917448606a3d9,0x0000c477cc78177b}, {0x00073d2a883239a8,0x00064c8b8357fb1f,0x0001f4f86e12572f,0x000c6e1d355e9cfb,0x00009b795f959f3e}}, {{0x00056f1b54398dc7,0x0006cfedeed527be,0x0006d01401890efd,0x000ee3f2f77f1f9c,0x0000ef0e314c96f0}, {0x0006631cc61dab32,0x000dd4866e4f50ca,0x000363b394a39801,0x0006aa46c8d032ae,0x00002c591e54ead6}}, {{0x000a308de02a53e8,0x000f5389f357954b,0x000f40b662a6c060,0x000ce166cfcde8fb,0x0000e02fc5746340}, {0x000779573adb4ba8,0x000c27b03805e495,0x0008e6fa67b86122,0x000803e3f835120c,0x00003660ea0857d7}}, {{0x000910521ba473cd,0x000e0ed5389dbad7,0x0007c9bc0b6c50be,0x0008a71e2caf4daa,0x000097b8de55c4e9}, {0x0003e70ab3bbddbe,0x000e4597815aa9f6,0x00015b3d93898aab,0x0007839659af89ac,0x0000df7725c503ce}}, {{0x0000fabe085116b3,0x0005572853102547,0x000bfd52f04a4337,0x000c741e39187ee2,0x00006166b44ad9eb}, {0x000433cfd4b322cf,0x0006ca79ab5192ad,0x000db15eb726aa81,0x000e63096eacd8c1,0x0000af71e91f476b}}, {{0x000a640641fad989,0x000799622559dd69,0x0004199dcb799591,0x000eb373c6daa5de,0x00002cadc983d545}, {0x000238b256534e4c,0x0005c595409a1028,0x0005dc59b73e80ce,0x000e7fa90d4c66d0,0x000095f7b90581de}}, {{0x0007014d856ac253,0x000d7c524dcaf433,0x0000499f5441bd9d,0x000182340b3d855f,0x00009cf84aa05fda}, {0x000b055b2aa95a02,0x0009eddf186004e7,0x0003f6b4329e33f0,0x000b0ee82e74b542,0x000017edeb92aaa2}}, {{0x0003f3583cbea55b,0x000d0c185d7058b8,0x0005f6992c485ee4,0x000dd4d33ff03b1e,0x00005b9b9cd7f0c0}, {0x000ee8e4e9e8a506,0x000b0269dafd7caa,0x000e791c6462e907,0x0007900ed5cee9fb,0x00008ca325a4d430}}, {{0x000bdf213b5ba885,0x0009e5ef0ac42b72,0x000b99b0860294c8,0x0009aa4c3230ed19,0x000060fff17bc258}, {0x0008487d67703743,0x000d6a56f685552b,0x000f175d9a373202,0x000810a3e7f90745,0x0000c2f31600080d}}, {{0x000e9dd7b9520e80,0x00020af037b51130,0x0009c104cc078f9e,0x000e9238cd2ec71e,0x0000f684368c472f}, {0x000b5ed6247e7ef6,0x0008d96dfe21d3f1,0x0009aa2c2b32d33a,0x000e40e6f59cf44a,0x00009cd51695f0f7}}, {{0x000da0f4b3234da4,0x000574579ebe3f59,0x0002476c7cf0b023,0x000f082d1cbb256d,0x0000f0837e6ddc30}, {0x00075bb906f6e98b,0x00041761e7d19a40,0x00073af10253bb43,0x00031c2e2e645f6e,0x000089a4060bc5f1}}, {{0x00040c5b8cc037fb,0x000ac405bb47d128,0x0006348b83d093a5,0x000ca6b202c25320,0x0000f5d57fd755a3}, {0x000c90c8c3bef483,0x00032a0a960a89f6,0x0002b42ab23ac762,0x0001f6afbd3d6b55,0x0000ef2245843206}}, {{0x0009bdac97e65165,0x00007230f49ed74e,0x00074ea498877936,0x0005a256ec1de31e,0x000081dcee58fb64}, {0x00023918f483f148,0x000c5137d13bbaef,0x000743a426d2dddf,0x000e66d4cde50ed2,0x00009a34fc664d97}}, {{0x000f5b312e08ce5b,0x0007f7f0b2ca13f1,0x000982805a80540b,0x000a03d54bcf7701,0x00008653ffdd33be}, {0x000878702b0b4c9b,0x000eeacb170a8e7b,0x0000c14e52675261,0x000be9561a9d9093,0x000059b30e18ef0a}}, {{0x0009ea60200ec7db,0x00085bce132b1dc1,0x0003e27e0b6f4a3f,0x00016f08d5de90f1,0x0000aee5ef0cfade}, {0x0006aaae4c6cf389,0x0006413698156f40,0x000d550c6ab4cfe0,0x000d387dcffe87ef,0x0000d4f59c805ff7}}, {{0x00053b151deb6adc,0x0003f1877749b025,0x0006006e1812399a,0x000e770e90f71fca,0x000032363a7702b6}, {0x0004fbedc36c64d8,0x000127e1ae610228,0x00009d94a86c81e3,0x000bafa576c7e5b9,0x0000b6f7d03018b2}}, {{0x000ed0756faa38ab,0x000be305bb54eca3,0x000c73061a3790e6,0x0006142784eeda7b,0x0000d56d36a1dd50}, {0x0005949229a8aa9c,0x00068595ec28d657,0x000ab4fe6dcca8f4,0x000f15c14305c106,0x00008c39768e4f43}}, {{0x0005f36523f2b367,0x0003220d93bbe2a4,0x000f1632b995c649,0x00095488afdab790,0x00009ebbecd8c295}, {0x0003ddb79592f48f,0x000a6f88e998c7bb,0x00001193e67216a7,0x0003fbe91f098bbc,0x00007d928a6a1db8}}, {{0x0008417e991f600b,0x000d7981a93455e3,0x000b13bde2a91113,0x000f441bc9d64806,0x0000011b6acb755f}, {0x000b518045ec6135,0x000172f5930a6f4c,0x0002e65de522d2d3,0x00066f0acae1af38,0x0000764306777bc9}}, {{0x000705d1c7193f0d,0x00066be8858e5e12,0x000c6dfc7f0f32f4,0x00095ca85c3d7d96,0x000075b4a218f317}, {0x000f17b342659d41,0x000434f0378f91ac,0x00052129de596ea3,0x0005853515708fce,0x00007387e1e89f2f}}, {{0x000d2e949dee1686,0x0002de2af23972cf,0x00094066a1ae0522,0x000412a09e75be1d,0x0000cca31c798abf}, {0x000d61d9bc499082,0x000cd5e2bc1eb50b,0x0006f83ac4a9b4a8,0x000b28cb6cc5f794,0x00007da93fd0bffa}}, {{0x0004c964821c8c54,0x000d683c15f4ea31,0x000f330048de49de,0x000e103a64cf207a,0x00005f1bfec09627}, {0x000062654b9df609,0x000c195c0b33878b,0x000035d8e5e4fdc3,0x000b8c554a37cac2,0x0000087cdaa10f20}}, {{0x0001c238319ade44,0x000a9e8cfdf836f6,0x0006f3705766f287,0x0004a20882194834,0x00009a7b85356e4f}, {0x000f8a75cedadfd1,0x00057db2a815b9b3,0x000f68f958f56281,0x00008eb0b7d55401,0x00002971e27788a2}}, {{0x000b696d0ff34fce,0x00013222718cc9f8,0x00095284d20824de,0x00023f9213cf9f0c,0x00002ad741cbc158}, {0x000a6df54043ccfa,0x000b384412b30ee3,0x000c98af016ff479,0x0002fb56c74ee0df,0x000078a169ff2fcd}}, {{0x000874699c930e9d,0x000779e117a5d8ae,0x00024759f1d33e85,0x00001ca581fcb466,0x0000e5064502bedc}, {0x0005d00caf3155ed,0x000bec73e75fbeec,0x0000b01db672d66a,0x000b78b6b9d8c627,0x0000249ef8420f55}}, {{0x000d6d473978fe39,0x0001e54b00a16131,0x000dfcfe9cc4e454,0x000befbe05df0557,0x00004b29cdde1ef6}, {0x0000cff9bc7edf24,0x000d93da65f3e453,0x000eb0b488ac236f,0x000038cfaf7d5fc8,0x0000d2de14ca60eb}}, {{0x000bba760430e540,0x0006da3289abc006,0x000979c5910a2d0d,0x0009449c037a5dd7,0x00004d1f3d3a116d}, {0x00024738a0983cd2,0x0008a883cabb9ff2,0x000a5899528e25b3,0x000bdfc968dba547,0x0000c80b505974ee}}, {{0x0003b714a953beb9,0x000e8642e7f6ee76,0x000d5e722502e223,0x000315dfe4b64161,0x0000d37c5b16bef5}, {0x000ed70f8330bc73,0x000645a727890115,0x000ceccc2139850e,0x0007f5f7d7faecff,0x0000016a8607fd9f}}, {{0x000ec644cd8f64c3,0x000ff79d7b51c492,0x000c7525658a2d78,0x000016dced1fc51f,0x0000e658aedbf433}, {0x000942e05da59eb6,0x0002addc37220b61,0x0002e7f87ba3d60a,0x000b6e1c311cd174,0x0000473ffef56b01}}, }, {/* digit=28 [{1,2,3,..,}]*([2^196]*G) */ {{0x000604f692ac542f,0x0000327b91d38303,0x000aaf9bdf079ffe,0x0004fa29f63e6315,0x000099ee566e1f34}, {0x000661fd62191997,0x0006648ce41c8a1d,0x00074d9048c883bc,0x000b1aa065118f3c,0x000013889ee7faf8}}, {{0x0003f8f81a1b3bed,0x0004fe2764a0972b,0x000c4f5f74f3ce14,0x00085b12d0f1cc28,0x0000eee0c0e97f39}, {0x000adc0d39e25c35,0x00007467a0807df4,0x000cf5a584061982,0x0005fff40ebc9361,0x000027729a6922ad}}, {{0x0000937b1b76ba6f,0x00045d2026dcca6c,0x000d9ae0a1a2eab8,0x000025c1715e1519,0x00001ad919aaac4a}, {0x000dfb807ea7b0ef,0x000e4ed9eb8935b3,0x0006d08abedf5496,0x0007309932e5ff2d,0x0000314874f15bd2}}, {{0x0006a753f73f449b,0x0007dd44fc79efb2,0x000c0dc4d1d1c94f,0x0000cf99f0fbc53b,0x0000747ea0be698a}, {0x000c3fe228d291e6,0x0004e3c129d65218,0x000acc51635b804b,0x0006689ac859b8d1,0x0000c10697df5d6e}}, {{0x000438f0876fd4e6,0x000723d2f383c38e,0x0000934cb45f0c30,0x0006edc03cc2ecb1,0x0000a8f24398c9d4}, {0x000431b65ccde7b6,0x0007c7e76a6ff16b,0x0003484d741e2cd1,0x00044a59c8cf8f4e,0x00004426efde3152}}, {{0x0008e44fc94dea3f,0x000eead6a0b01c0a,0x000113cef34c8cdb,0x000ff9a19c384004,0x0000d32fba505490}, {0x00090f6795dcfb75,0x000333588baf58d1,0x0001fc1c0fef01b0,0x000ac94e6d1d63ca,0x00003173f9740a41}}, {{0x000402aba16f73bc,0x0003ccf9b9fc2b1d,0x0006ef7bf2fb3101,0x0007446d51e60e44,0x0000731021c791e1}, {0x00047244fee99d47,0x00068ac5c1ea9d3b,0x000ea9af74bca48b,0x00083a00f5f514bb,0x000051f55a6074c2}}, {{0x000251acb452fdbb,0x0004a0f306506e30,0x0003548d931ee696,0x000f5b00b3e50893,0x00008949a50a4b0e}, {0x00083263c88f3bd1,0x0000cb1d9989208b,0x000d4df03ab147c3,0x0000c5dd6515fd44,0x00007a12f75f72eb}}, {{0x000796d36cf69db9,0x0008c6670c183b59,0x000070d8e1219eee,0x00090c6e3341f77a,0x0000b70130c3327f}, {0x00024620ae18e0e8,0x0002c6c0a63836a3,0x0002eb0d42021a62,0x000292a51b5817c6,0x00007bfbcdfcc762}}, {{0x000b505cdd61d649,0x000c38c18857f78a,0x0001475158c7a53f,0x0002d51653ce6f16,0x0000c923aa67a7d5}, {0x00009cb5c18871f5,0x000823b3cc74c247,0x000d1d4c47d53bec,0x00058209264afffd,0x0000555917e740da}}, {{0x000bbda548f5a0e4,0x0009fbbfbbe1cae8,0x00077afc31910eab,0x000b5c6e57968576,0x00009ea61f1b3ff0}, {0x00054784f7c39221,0x000d10c68eef7865,0x000779ab995d337c,0x0009a858f1e1e5df,0x00004b491b0c5cf6}}, {{0x000bbe028e3fe894,0x000485aac0eb7a6c,0x0007e5140e7e1fee,0x00021f3f47eda569,0x0000f450137f4549}, {0x0005f8495cd81854,0x00018db2e583db62,0x0005e6de474be0ba,0x0007396ee4fd7cdd,0x0000251437e28101}}, {{0x00072a0ac6203668,0x000c36d59344686d,0x000eb75b94be3fb9,0x00010bee8b44e7a1,0x00004e39da411a5c}, {0x0001490b38f04092,0x00030c2ade8237cc,0x00090a2d80295194,0x0002ba7b68878311,0x00005627d1443118}}, {{0x00050aa658a6d877,0x00075f9c73256eb5,0x0008748c91405aaa,0x0000e06147142e5c,0x0000f637e4fc3ede}, {0x000277614ffad2c7,0x000d4afb6791f8ca,0x0008f93fce58fb1b,0x000654a7158c23bf,0x0000f15b3737a4a4}}, {{0x000add2d842ca726,0x0000ded9630539d4,0x00000be14a71e439,0x000cf5fbb09cbe67,0x00008d69d5538bef}, {0x000536737183bcfe,0x000a5370dff7a45f,0x00012525b7152b7b,0x0003ccef887baabf,0x00007ac7bdeb6d1e}}, {{0x0004f7881fdad909,0x00057d2cf6ab2591,0x000054de5cf638f5,0x000350290bc03fcc,0x000032811a7a8b06}, {0x000b3309bbd11ff0,0x000fb40449742f00,0x00051d26676108a6,0x0000c1801bb9e0a8,0x0000dd099bebf899}}, {{0x000aaaaabe329866,0x0009f0d59c2758c5,0x0003073050fe9dd2,0x000b7824951ff48d,0x0000c23f829e6529}, {0x00022180b136a798,0x000df7a2099650bb,0x000bb4da67e2174d,0x0008d9ef00a4b9c0,0x00009a25a186fdde}}, {{0x000a27ec11ee01d3,0x000ab5f10dfbf728,0x000ec893cf900553,0x000d76e89a83c802,0x0000ca5bdc153f66}, {0x000153797eada9f1,0x0003002562309878,0x0003c69b359c50ab,0x000449246042d932,0x0000b715a6d3c460}}, {{0x000d4766ae06e0be,0x000dbd42e25fa41d,0x000b25a20cdd7888,0x00027d2f395f7456,0x0000adfe0af6700e}, {0x00052a9699500937,0x000ac27f8d40b09d,0x000df886a3525d9c,0x000ec248235a9467,0x00007e4b0dd735fa}}, {{0x000b20a517d7061b,0x0002bc2df683115e,0x000c6fc6777fe343,0x000e82b870ddc7cd,0x00001610588bb87d}, {0x00084cad9c4ddbe2,0x000c1d754be23435,0x000e6c894b3164f1,0x00004be731ed3ac1,0x00006327dec6f6b9}}, {{0x000c6de97b5cd328,0x000e35eceecd9d49,0x000ded7fe40835da,0x000804466350edd9,0x0000aeebb5cfa678}, {0x0002fb75b8ee9ecc,0x000cce3ca11851d4,0x000f4400ed7a17bd,0x0006f380d7511a2e,0x000048990ad475a6}}, {{0x0007d2a2199e347e,0x00054a39e0518de0,0x0006e51dcbee7555,0x0009eb7691878691,0x0000b1913142a2d8}, {0x000610d37d341eda,0x0000b6d51c2b6679,0x000492dba434fbb4,0x000493454b7ee7d7,0x0000a33a79af9021}}, {{0x0005054e4bd6d3d2,0x00043ab551d049fc,0x00042d3a609540f0,0x00023b6acc908549,0x000031af02f4d283}, {0x0008cac0992c163c,0x0000c88e3bb49345,0x0008c268c1fef8e7,0x000bff67578da5be,0x0000c8be793a805e}}, {{0x0007baec61c3855c,0x000c98c1fd3b2926,0x0000b93b8ebff429,0x00095262d886c08c,0x0000a5e00b2eddb8}, {0x0000117c3fed8b79,0x0009f19c01f6cf33,0x0000fbd54d49ac6f,0x0002cedddaa6bd3c,0x000017430691049a}}, {{0x000981eaff2ef812,0x00050818ae80d67f,0x0002aa892c3654d3,0x00032861d050441b,0x0000db067bf5d099}, {0x0009e86703dcc974,0x0007a133e215e7c7,0x0009a7a5ce66f9b3,0x000b618df119a6e3,0x00007c60de3c76f1}}, {{0x0005939d860f1b25,0x000ca5ed4d4a6e40,0x000b6bcbd3e9a1db,0x000496ef23619ec9,0x0000ee790cfc34e4}, {0x00034b15bdaf9bbe,0x00066ca295f0f0a8,0x0008e378c02cedda,0x000ea36619aa2bcb,0x00005613245ac987}}, {{0x00022cc76b23a502,0x000cea6c21ce0bc0,0x000cac3f54a2793a,0x000d561832878089,0x00009176f1beba26}, {0x00061874f6f59eb5,0x00093bdc658e0629,0x000e3040286e9bca,0x0009badca9c4d357,0x0000438b216a16a0}}, {{0x000063c7672765ab,0x00035547b9bf0a6a,0x000b1a63337a3ce6,0x00096092c099c898,0x00005ab800db5ee6}, {0x0003f5911a5acd6a,0x0006a6201063f196,0x00096210abaee615,0x00038b96d9a649a5,0x0000ed04363bba71}}, {{0x0007d1ca4a82b765,0x000ea3806be9cf81,0x000dc6bb55586960,0x0007eb2ab67c8909,0x00002ace7a0614fe}, {0x0007618cbbc9b701,0x000a504ca5e1cd98,0x000bde1334f06fd5,0x00026480af14ca6d,0x0000afe4322a48a3}}, {{0x0002ca6c44b2c6c4,0x0008cef87dfea70d,0x000696377ab72679,0x00069ff10f64dc2e,0x00009b42e688c812}, {0x00044c3cea0b1760,0x0007cb2691820ea4,0x000ba9dcb53a8ddf,0x000d33f3e674ebbb,0x0000d2878a8d8669}}, {{0x00035d5d019b6a39,0x000db06f1e4604b9,0x00057c111bb5cf88,0x000d7811912d165b,0x0000803fc21a9ebf}, {0x0001c9ec07764a90,0x000eb75bd0554f23,0x000e6c9ded93286e,0x000c9083a9457d8e,0x000046959156087e}}, {{0x000dd8a58d6cd461,0x00057e6634d214c6,0x0001bc3289cb633b,0x0007e5b1305047f8,0x00002ede0e236a17}, {0x000ca62065a6f4f9,0x000cd7be487b332c,0x00047ed1cc3a47ec,0x000b13e41eb1870f,0x00009e66e5977598}}, {{0x00044ca63d0ff123,0x00048610a05f6f05,0x000ad7b47e5efc78,0x0000c0c72917b17c,0x0000ff6ea2122cac}, {0x000791bf21db8b7e,0x0000f7d93565cc23,0x0004bdaad7dac70b,0x00016c882cda1d69,0x0000b88bb8cf0235}}, {{0x00034b4dfdbeb1be,0x0001d4ee4deac4c6,0x00052482122f5ca7,0x0008b13045a368e6,0x0000d9e8a3fe52b1}, {0x0002cb1b961f49a5,0x00012b0096709b7f,0x000507a6d7fee2ec,0x000f1ce50d875422,0x000061bd7119db55}}, {{0x0009ccc320bbcaff,0x000eef1de48c4c18,0x000a8f128568434c,0x00083b7af1b00e0f,0x00000ba9d0379075}, {0x000400432ff9f60d,0x0005f25dcf33735a,0x000c74cef3dd8e4b,0x0008ad22230f1642,0x00008117623d13fa}}, {{0x0002876f51fe76eb,0x000b61d625893682,0x0002257188a6811c,0x000bcd13fc7e6546,0x00007df2ca0782fd}, {0x0004e52dd7b205bb,0x000797a2e4143b1d,0x000a91148b695947,0x00067455e4d793ef,0x000047ed447ad2e9}}, {{0x00098b904c9d9bfb,0x00006b7930481a70,0x0001ee461661e288,0x00046f01a16966b0,0x0000c521308d9547}, {0x000a0fc2477de506,0x000c1dbd51efc909,0x000294905d80bb41,0x000f97485be7ec53,0x0000d465b18e3958}}, {{0x000f330fb6840fd2,0x00041401e6c816f6,0x000b5b4f8faaeb21,0x000c4b8f83d30fcc,0x00002885739466de}, {0x000367c7bc467dfe,0x0002f842d27a51b4,0x000ea14a6926562e,0x000cd8ffcb66140f,0x0000b394dafd2734}}, {{0x000e5d211c0be981,0x0001714e81653eea,0x0002bce1cb1e6ed1,0x0004da091086bce5,0x00004b74cc6b75a0}, {0x00011868c060985e,0x000d4dbd7f7c63cf,0x0000942ca071047d,0x00061c6e433b8bce,0x0000cbac448b8fec}}, {{0x000d0e2ebf3232f7,0x000e552a2edd8f0e,0x000b55fdbfff80f9,0x000c113d9ab43375,0x00003ca7821542e0}, {0x000e0a0e6251b462,0x000c2c0d932d6dac,0x0005da19a89bc6b5,0x000dfb1438cd7709,0x0000f24a939ad48b}}, {{0x0007e46766561b79,0x00057ed0322a99b4,0x0008e1865736600e,0x000fff76a47cb163,0x000027c1c2e5b135}, {0x00023370cc5df696,0x0001a9d649a92954,0x000efdb2799b37c0,0x000c2765f0043c6a,0x0000cdd99877be95}}, {{0x0000931390420d28,0x000b8983efa46985,0x00039aead299c40a,0x000192ba05e778af,0x00004274408c3a45}, {0x0000fb991a711a0c,0x0007df52ab176bcd,0x0003c6ed6461592c,0x000066f49302b4da,0x000051fddc7f30d7}}, {{0x000beb6da50d5311,0x000d96a7b9da94ba,0x0004bdc89521b840,0x0004494305151e40,0x0000bcde201e0d07}, {0x000a78b3b76a59a8,0x000d87791a1bf427,0x00091ed1cf84841c,0x0009436bd314bebf,0x0000e61d34d3f172}}, {{0x000c4515541b8923,0x0001cc9d9e541d5d,0x000bf610db186ee4,0x000a9f6d9f345ed5,0x0000e7ba65e26acc}, {0x000787aa83694867,0x00071eb5ba539dda,0x000481bc309f9dab,0x000103eafb2033d6,0x00006f4ce311fa62}}, {{0x00000cff4f066b52,0x0003261dafc2a8fa,0x00038999889ab514,0x00090324339ed7a3,0x0000ff862f1dc214}, {0x000f985b05556e3e,0x000d5467081e2c88,0x000c637eacd96058,0x000cdb9d6a4176ed,0x00001743d0a16a5a}}, {{0x00072e27eb37726e,0x000d3481a03766fd,0x000f4aa79f7fa264,0x000e21bfbd3bde45,0x0000d1e0148567c3}, {0x000f97982e7abe2a,0x0001a5f633f87621,0x00037bf3a19eedc7,0x00094e469b155e61,0x00000ad13cee14ee}}, {{0x000d5241c0e651a2,0x0009e2ce227e93e3,0x000b27ecaab1a6e2,0x000f39c7af17974a,0x000045446dedd444}, {0x0002a2156c07613a,0x000e5427549859e2,0x000fd094643deafc,0x000ede70834ccb67,0x000075841e5e7406}}, {{0x000a6777b0ac93d1,0x000d68f5e0d7ebd6,0x000f5492ba6e37b0,0x000f3a1516c09676,0x0000e4bf888aac05}, {0x0002ce04df0ba2b4,0x000d1062341bcdb4,0x000acac20935d5cf,0x00000e4a30333382,0x000029438c49198b}}, {{0x0003bc9049d33fa6,0x000a346f67ff1d08,0x000a1d6a358b82dd,0x000ac84c3e2db867,0x00002e6bead7798a}, {0x000980fde46c58c0,0x000969c8d7befc85,0x0007b35eca7f6937,0x000c0c2355792783,0x00006a933d8e0790}}, {{0x0000e9b077ff55dc,0x0007fb26e680827c,0x0009cb54f5397779,0x0003ee995308741d,0x0000ca3f44a0aac5}, {0x0005c87a07eda0fc,0x000f3d6400c811dc,0x000e5da72c138bcc,0x00017d949680d313,0x000093eed8305406}}, {{0x000b1574d0b75c00,0x00026386075bfd3d,0x0007b2c169716eb4,0x0002010639605c81,0x00009915109f1e4f}, {0x000a9285cca6c3bc,0x00097505c90035c9,0x0000480c4b25f7d1,0x00001c2b9f7d2063,0x00003c7b8c6ea1a5}}, {{0x000183c5a1f8e24e,0x0009bdd255f03f99,0x0007f62a6fdb118f,0x000190d9b18b90c2,0x00008f732f8196ec}, {0x0002d910be786ab0,0x000f0ac5a0f5524a,0x00025f6945d32ade,0x000a899b53d4d697,0x000032a76c60510b}}, {{0x00091a3ebeb15447,0x000bced73ac38403,0x0006cb8b344b7b88,0x000b12624bae7a25,0x0000ceb151b5394c}, {0x00066d05bc1e6a8e,0x000a290f07bfbd6b,0x000937589ec70cec,0x000cfd470644ed7d,0x0000e9e1a3e3f1dc}}, {{0x0000a84745b98d25,0x0000d556ed40b0d4,0x000148cb9da429a2,0x000936a676eced85,0x0000a22d40d2ed18}, {0x000b9e570e8a4cea,0x000afeae03793bc4,0x0000bd47ebfd1445,0x000531523f2c0c1a,0x00009c0bb3281845}}, {{0x0004d600a4c3f6b0,0x00092c15ef449ddc,0x000484accbdfaad7,0x000f15ce55a2367f,0x00008653ca7055b1}, {0x0008724538873a39,0x000d1ce1c7e72efa,0x000e332ba09299e5,0x0001b677afab66ad,0x0000be1fdf722dd7}}, {{0x0005d595758b11cd,0x0002f8654f40a49b,0x0003794470b85289,0x00090be63ef6f452,0x00004957d29e05e6}, {0x0004363646559b01,0x000c39788a8e7d48,0x000ce54a9f4a8273,0x000a9bde406cb834,0x0000e1c2610086fd}}, {{0x000e228cf6a4a81c,0x00025b488772e150,0x000a9c15b1fa3b6a,0x000a465e6ff110c5,0x00006133b924ad6a}, {0x000d55c9dffa978f,0x000c6f3965f28ac5,0x00032b52fba1d1c1,0x000a070969f4e077,0x0000ceecdb695172}}, {{0x0000a5f10f2b8f5d,0x000e8c4c2f63b012,0x000f9c213c83a6cd,0x000bd47d47a491f8,0x00009e1cce6a3f1b}, {0x000bc7caba7e3721,0x0008cfd1a2db0d91,0x0004618e5fcdc74c,0x00025df5efa80037,0x0000121696925a79}}, {{0x0009823f6021c5dd,0x00041ff14423d4c8,0x000cd1396880d5e8,0x00078a9523bc5a6d,0x00001acfdfce13c9}, {0x00064e8bbb66840f,0x000d82b58459b0c1,0x00038e8ecf7f4301,0x000698d29ad4a6a6,0x00005ab896236b78}}, {{0x00079740e9547505,0x000814f9d2c69dbd,0x00085232e0121de8,0x000776de597b42d9,0x00005b6c3c5a3451}, {0x000e547519cb9fb2,0x000f6428600dbb53,0x00081791af134019,0x000c083a473176e0,0x0000f3e226355fb0}}, {{0x000301773d273b06,0x00061721ef9ab28c,0x00050dc39ccd2107,0x00045da54cc292b6,0x000062246dec1880}, {0x00052fa6b83c0d12,0x000777e9cd46904b,0x0009725e4a72df26,0x000f22686b43cd89,0x0000b651688f849f}}, {{0x0009b7902f345331,0x0003fc77c1486047,0x000537c785e354c1,0x00095fa4bb7581a8,0x000088043d7ffe14}, {0x0002f428c1d50261,0x000683d4aaab9ba1,0x00057c4502e0c8a2,0x000fefadba7b8baa,0x000040c9ad6abbda}}, {{0x000aa4225ac0f182,0x000ae4d1fbf32067,0x000b04824f7b1295,0x000e90f4829111a4,0x0000ce3f19253bd5}, {0x0001d558f2e1b72b,0x0005802aa2439c7a,0x000be9554fe93228,0x000a6d997ca7b4d4,0x00008e821b990547}}, {{0x00038be67e573e06,0x0008e084c44bfb28,0x000c1c2c505891db,0x00044b3131137396,0x0000aebfa4039584}, {0x000dce9e56e55c19,0x00029caa46d0ac9c,0x0001fe8eb7148ced,0x000f4c9e10c7efb6,0x0000fd835db8f97c}}, }, {/* digit=29 [{1,2,3,..,}]*([2^203]*G) */ {{0x000a109081e9387c,0x0006cc935828a36d,0x00040b015fb9780d,0x0006fa15940332e5,0x00009d7b51ca0f46}, {0x000cd41d6d9f6711,0x0008a1a2ac17faad,0x000201e5fba6c1e2,0x00062af66a7833ed,0x00009d9971a090f4}}, {{0x000f462060b5f619,0x0003ebd057c2f431,0x000e1bf65a56f46b,0x0001fea48dca6c47,0x0000a38783ed1bcf}, {0x00033a9da710718f,0x00063e0aeaf67a5d,0x00029d1875a77998,0x000732da87314d2d,0x0000a0edc3fb687d}}, {{0x00036216a31e09bd,0x000cf1350e359df3,0x000a0cf52de89e44,0x000537592148714c,0x0000f379672db88a}, {0x000510a2591d61b1,0x0007485b447bc92a,0x000287f7779aa87d,0x000a80e67db604e5,0x0000697c8bf6efe7}}, {{0x0004849cb198ac73,0x000cdf2646651c89,0x000200678a884a93,0x0004e5fda964ef9b,0x0000c351b8730983}, {0x000ef9fe2c4b44b8,0x0006b326790cafb2,0x00002264a580f6c4,0x0004e2384805210b,0x0000ba6f9e2c2a19}}, {{0x000975f8fb547385,0x0007d7c3ead3fc87,0x0004a085a3516078,0x000996334116d2b7,0x00003c99a73f62fe}, {0x0005be05b81c51b3,0x00088e0852b78758,0x0004d19a7925bafa,0x0006d446a4fafda8,0x00009a4598288520}}, {{0x0006ab65eb03c0ee,0x000392bc3fde499b,0x0003a80d2f19b795,0x00019ec86b5b9c6e,0x000043775094d428}, {0x0003650bb3ee8a3e,0x000bd132075fc166,0x000d834f675eb14f,0x000ffcc8ccc9067a,0x0000a6a2475c6e92}}, {{0x000fd950f8d67583,0x0001108c07dd9d72,0x000e23221cb84e10,0x00042c89114bfda5,0x000058b5fe3194e7}, {0x00077ec95f40e756,0x0000dd73f3d61c05,0x0001b9b66f015545,0x0003c73d55cd67bd,0x00003e86e790f8d6}}, {{0x00034abd3c095f18,0x000e64b76d7139d9,0x0003e698404b261b,0x000b109d2e6970e7,0x000079fb23bde5fc}, {0x0006c72dfd754907,0x0004f1bcf1c11150,0x0005e70073a97d08,0x0002a6d3201d82bf,0x0000f0ac52fe9823}}, {{0x000cbc46eb564d4c,0x000bde570e292715,0x000f5fd5d8d6c752,0x000514380247c89e,0x00003c66b47953eb}, {0x000b4010f87de563,0x000f96c603b59666,0x0004fc942ce62c06,0x000c197e7b4c607e,0x00008ac0b77963a9}}, {{0x00020ee4b049136e,0x0001556a4613cb4d,0x000e081288b63bf1,0x000b153221aef670,0x000062d8c522acb6}, {0x0004a67379e7896c,0x00020afd7fa571f6,0x00041ba6ab25237a,0x000e7e3077bd9838,0x00004ac0244fcd16}}, {{0x000a86921fea4ca8,0x000773dfdac1548b,0x000685fafd36d081,0x00059989d8d71ff4,0x0000eff66bf452c4}, {0x000aee70b57235e6,0x0000a106712b182f,0x000fcdcb0ee3c39b,0x0004b9f107331fc0,0x000069fb9dd05105}}, {{0x00001fb319d76820,0x00090a982feeb251,0x00061b344b029312,0x0001fa51c1c9b902,0x0000e008c5bbfd37}, {0x000dd1c0278ca331,0x0006d5aa53b1d866,0x00013a2cf666f76a,0x000836d5cfb77960,0x0000d3a1aadb3521}}, {{0x000253173faa4851,0x000fb0a76878cedd,0x00011667dc8ee6c4,0x00095acdbccfc92a,0x0000a418ea92c2f6}, {0x000bd9251f73971d,0x00020a2ed89fdb11,0x0003e03193e4b3c8,0x0001aeca44f3f4e7,0x00001e3de1000343}}, {{0x00004ff50f75f9cd,0x0002ae752b223c56,0x0009a11181d8eddf,0x000d7a3ef074dd3c,0x00000ffc1739cb86}, {0x000ece3037d90f29,0x0005d055856cabd1,0x0004c6dafe3f307d,0x00099fb22f93287e,0x000002aac66c3487}}, {{0x000e7bf94cdfadef,0x000c8fc6d634b6a1,0x000fb63f86c97e1e,0x000404762ad24da2,0x000081be1ba95928}, {0x00065e4d14b4206e,0x000dafa0db6586d7,0x0007fc76cbecc2e0,0x00024dc28838e0b1,0x000049a602bc37cf}}, {{0x000131a567193ec5,0x000a95f6e70b76b4,0x0001eebddaf3c305,0x0008314587bd3903,0x0000709def8c1bbe}, {0x00099830eb2b6692,0x000b675b70295705,0x00064ac164d80ce1,0x0003ab638a7da803,0x0000f431d23de1c8}}, {{0x00012a6f9294dd32,0x000f7b4b0d77e568,0x000e8305cb448d01,0x00063ed3ae606104,0x0000bead645b4d8c}, {0x000434d84fd8b072,0x000fd7a9dee50a85,0x00055bd85537b983,0x000f8bcdcc5f18ef,0x0000041af6241c6c}}, {{0x000874cb940c71e3,0x0009ab5f4b3a8e52,0x0001b1dc3211935a,0x0006206435049230,0x00003d2646d59958}, {0x000d64bef9114044,0x000a5a3c5ef416b0,0x000352c789d1f25e,0x000427e0f200eb4a,0x00003929f2c8bd0b}}, {{0x0006667c7196e295,0x00004391be48a565,0x000e0cd6e7992c2f,0x0009bf5aa97cbd9e,0x00001b0310c8dc8c}, {0x0008acfdd9f22cb0,0x0001b585d584237f,0x000416388bb1d81a,0x00074f8d5d85f58c,0x0000d6e5a5a42fe4}}, {{0x000276638235d4e4,0x0007096e3298e781,0x000175bc81c62bd6,0x000d4d4378660c3f,0x0000d04e18957afd}, {0x000160185a8068c5,0x000142b29a8532a8,0x0000d8a3bdb58e4e,0x00003b98a65b86c7,0x0000f0e6f4ee8a04}}, {{0x000968469ed23707,0x000c9871ee260812,0x0009c5b0534dc30b,0x000c86ca5ce9487c,0x0000d487b80b3a90}, {0x000ba37dd0e71799,0x0001240418114089,0x000747ba545f8019,0x0005918c3e105898,0x00008c4e13afe1ae}}, {{0x00036e6e82c9f9e4,0x000c833a1043d446,0x0008aec05711db87,0x0004aa2f431263aa,0x00003ff120d6744a}, {0x000892fae77779bc,0x0008ccdc9f82d3bd,0x000c5b1bcf0fe0cc,0x000a720a5f7fe6f1,0x0000c63a68304929}}, {{0x000ba0c09dbe19a1,0x000d5b5c73c2c7ea,0x000e50c302f3585a,0x0000ba7ab8924b0a,0x00007fcd27a738b3}, {0x0004d3410b3d5a5a,0x00018a9accf1af41,0x0006a624209c107d,0x00064175dac49f94,0x0000ec3df2b7707d}}, {{0x00092b73f894ae03,0x0005875f18ce2c24,0x00053cad0f59df3e,0x0002944cb740d28f,0x0000eb585fbf4f01}, {0x0000c8632c7f717e,0x000acf943f4c17da,0x0007c51d2eb8c795,0x0009486ee23fb5f6,0x0000f18757648889}}, {{0x000bdb20389168b6,0x00088a577d03a6b4,0x000743082c4ecd25,0x0008ccda63782b55,0x0000f678f4d272f0}, {0x00011cf65e58dd88,0x000e5402c0cd5535,0x00037c14cd53b4e3,0x0002a9b7de3e29a0,0x00006b6c51740571}}, {{0x000da3eb38dff6f0,0x0002ea636be82834,0x000dd37f8be012c5,0x0002db292d238c61,0x0000e54523f8f814}, {0x000b436036a05d8c,0x000e5e93c0ffe31e,0x000821ddf83e3cdf,0x00033a7fd2fe0f50,0x00008e19b0ebf9eb}}, {{0x000943fb569a5fec,0x000414342d75c8cc,0x000eca000ad0090d,0x0000eac2090b4bca,0x0000a39687fdbd41}, {0x0000df765959d77e,0x0007bc964999e7bb,0x00041545139d7821,0x000107f87f62e8b2,0x00005efb7759ed76}}, {{0x00011a4e822f0d08,0x0000da8704f83ea0,0x000c6820fbc647ad,0x000bec3b315b3550,0x000063dec3e37e76}, {0x0005d3af017bfc7f,0x0008a76b822901ff,0x000bd0d3b2005443,0x000d0e167fca370b,0x000063dde656f5e3}}, {{0x000efb32a4c94e9b,0x000de6f8278a22db,0x00003793dafbff0f,0x000d28d0aea0b135,0x0000223802a0f06c}, {0x0003e578ec3fecad,0x0003693e70536570,0x0006734c406c3831,0x000f1dd0b751eb7c,0x00002e8a436959f0}}, {{0x00090525e9ca895c,0x000dd72072df147d,0x000c6755c2f4dd31,0x000557e16fda8ee6,0x000066827008f196}, {0x00076a30cf43895a,0x000fe3c3097b1f1a,0x000390e0ea9d604d,0x000eff4190830966,0x000050bf75453c85}}, {{0x000bddef6a702510,0x000b3c6ab16a0696,0x000d08762548b801,0x000c4e37fcf704a4,0x000090b3defdff76}, {0x000cb8969cb91584,0x0004595ece4387e8,0x000d9fbf544a9074,0x00082db85395f40a,0x00009b0f6c58fb0c}}, {{0x000bc15adf7cccff,0x0005efa1e1b075d9,0x0009bc17e81a3e5d,0x000d429c39e44424,0x000037dccb37ea7f}, {0x0004873907fba12d,0x00097a372904da65,0x00083a6c535daa6d,0x0005be3564cfc662,0x000009fa4f71a939}}, {{0x0009ec9aeb19a362,0x000ea7bfbfb4688e,0x000c2faa6d913f1c,0x000c12597b9a3c61,0x0000f979bec8a0a9}, {0x0009d0f359679ec3,0x000cd79b0460b596,0x000fab870ebcf523,0x00039ccd6b000810,0x0000f2edcdac373a}}, {{0x000f9a76f568431c,0x000b42f8898c0d64,0x0000b5bd5f848c27,0x000ee83418ade126,0x00001f3e3242973d}, {0x000319c26c185ddb,0x0007a46f0ac446e9,0x0007f9d576d85b7d,0x000f47927965f224,0x0000519b63760035}}, {{0x00063a9ab87d59c5,0x0002e9caaa116b61,0x00077387bff9f58c,0x0007f8fac39cde31,0x0000f6557c2d73e7}, {0x000400636a830417,0x000a05ef196c6750,0x0008c79409b1c96c,0x000316834283deb0,0x0000ea096448128c}}, {{0x000b3b56aa39dff0,0x00029f8e4d8cb510,0x0004c4b9f59b43da,0x000c01a8ce31fd9e,0x0000e20be26c1303}, {0x0007182e8ee47c94,0x000b3db981011818,0x000e14ff6d9687cd,0x0005723a520e4da1,0x000029808bac836d}}, {{0x000a60d4944b6639,0x000913f91ae5a37c,0x00036e3b1f901f7a,0x00025054e3e76e9e,0x0000aa219cfb9d93}, {0x000e275056a2512b,0x00092e65d95c347f,0x0009fc3eda4d643d,0x000bbde669d39669,0x0000598dee37f8c6}}, {{0x000c1e5dda9e5c65,0x00027aa9fc95682a,0x0002bea444e0d3c7,0x0009c7c7faaade77,0x0000ef8428cfb000}, {0x000e47a460ff0166,0x000f125281cbcc4c,0x00023aad2da6d12b,0x000e27e4c6784802,0x0000e342afa96256}}, {{0x000bb0b93a37c047,0x000b6d10bd961400,0x000ac46b762b1bc9,0x000f510251adeb0d,0x0000d33b92eebe4e}, {0x000a94be61fa29a5,0x000eb642223328b2,0x0000d8d374b2be13,0x000004e6d6d06233,0x0000ef80e1f028ca}}, {{0x00046996d16768e9,0x0009d28bf217174d,0x0004e490d9fc4ff6,0x000979e7705a9415,0x0000d96dd291d2d9}, {0x000d9d8ce5d72c41,0x0004b11c714f77e2,0x000e4a03e9d06c5a,0x00028af2aa513679,0x0000386b3c2130ff}}, {{0x000e8a6fb283f61f,0x000503abc3fbfe82,0x0004d36227df203e,0x000760fec7c3513a,0x00007d17dc0cf762}, {0x0006e44522055f0a,0x000aefa748dbc395,0x0001dcc14de3012d,0x000f3a2a9fcb63bf,0x000056d9dd05e4e2}}, {{0x00086b68bcec9c2f,0x0008780b9f06b861,0x000d292817cf24df,0x000e11d46b45eac0,0x0000ff42bc5f7b10}, {0x0003c404d289427b,0x000904848ec41226,0x00040800c3d5f189,0x000b1f61f97010d0,0x00004c5f529e00fe}}, {{0x0003f8fde94fdcb0,0x0009c7c2f05ecc54,0x0002692e1e96af73,0x000ae9aa5e003688,0x00009c75b68950d4}, {0x0003df2b5932a7a7,0x000e6e0979ad62f6,0x000e696312658252,0x00066aba19343fb5,0x000018c7501c25b6}}, {{0x0002d69ea40dc3a4,0x00026ecc018f26a4,0x00070f04adc84ad2,0x0002ece5c36c7b32,0x00006ba6d4790fa7}, {0x000d1c593e58a8e2,0x0000f20c088c6c37,0x0006e86daa239473,0x000038a3be4263cb,0x0000c417d369126d}}, {{0x000f9c58b6f8efae,0x0009577185365b70,0x00039c92b671a2fa,0x0003c1f3ced3c6b5,0x000056f1bda83120}, {0x0006ec49ff3c8eb5,0x0001f3491cea8b09,0x0009437942deae43,0x000842d465c6eb17,0x0000d267e6670586}}, {{0x000116db07159d03,0x000f918962109d3d,0x000961579ae07a67,0x000dd65fc84d87bb,0x00000009e494c1f8}, {0x000af22e31328195,0x000ca23ab4ff8a8c,0x0005dd687cffa197,0x0007a208103a4420,0x00007b796c35ded6}}, {{0x0003a6ca1779ad79,0x000da57c09c50b9c,0x000b4a57ea33cfe2,0x00052d9ea293153d,0x000019596961ebeb}, {0x000b9a6e546c8792,0x00044295c8d6118d,0x000ec806b8e996df,0x000035bd99048455,0x00004f291ca365c1}}, {{0x00023bb440e22296,0x000213ef4d04cca5,0x00011ec39324673a,0x0008d34f3adf343e,0x0000136d7f23c596}, {0x0002899b053a9270,0x0001ae067ecd7a7b,0x000779cd93eaa266,0x0005ea8549b9c802,0x000061d7940c5338}}, {{0x000a883f06d18bd9,0x0003227008433e0b,0x0001a9e4d4ba6de5,0x0000ed2966b66859,0x00003f675680f4fa}, {0x000711b4347237bd,0x000f1794608e5a02,0x000f73d8cbc041e2,0x0004f685af10f570,0x00002d4d4f88b756}}, {{0x0007a89b3e93ce7b,0x0004ad3a2c1bd7d2,0x0005b218af7b5a87,0x000754029e68a025,0x0000533837f3af76}, {0x0005a73579fab2e2,0x0001ccd74385d1b0,0x0005e9115b41055a,0x00074e9236927444,0x0000972a7c515202}}, {{0x000334ef678e68a2,0x000079b057ed6c08,0x000ccb69a4e4160f,0x0007721cfe11b852,0x0000fd1823a41c8f}, {0x000072f3298f0557,0x00098ec74a6edf7f,0x000b4d0418c0566f,0x0008507549e0195b,0x0000c3930bb0208d}}, {{0x00041fcaaa2902bc,0x000924f69ad3e071,0x0003f9ffd539ad79,0x0002f6e6453f9481,0x000058d3c48f75bc}, {0x0006fad5dc64e964,0x00097240e354b332,0x000a1e7a93aafcaa,0x00089fdd1b0903ac,0x0000ceb97675211b}}, {{0x0003e49e32a858e7,0x000e3e907badeca8,0x000b9b4944c32892,0x000e1b65b42ab62e,0x0000fde3ee28eaba}, {0x000ab09caf549579,0x000e55f5d5d513b5,0x00003e2c0bfb028b,0x000843028a065020,0x00000793aacf7476}}, {{0x0002e79c81710a00,0x000627ccadd45e94,0x000cf6d0c557e4a3,0x00080c72a2bc564b,0x00009ee5f4326d7b}, {0x000dbe9d4292f19b,0x0005b3f16b186b70,0x000fbb42a56f74c2,0x000040123db0f735,0x0000606bdf71ae10}}, {{0x0005d4d044573ac0,0x0006556b0ba41eb1,0x0000df6f77dc3cf8,0x000e8c97af9a33c6,0x0000b1ef85ca716c}, {0x000f884c96958bee,0x0003556909632922,0x000a000617c32fa9,0x00065b4d7f667cea,0x0000aaf7c1815473}}, {{0x000de4687032d585,0x00030e2c79e01eb4,0x00004ef23c54f3d8,0x0001b3b7818df45d,0x00005faa9c8b73d4}, {0x0004f6f89b95355d,0x0009e7415c84ced6,0x0000ebad34860d2e,0x0005be8fdb9bd205,0x0000b53e0cd3685a}}, {{0x000c0319feb65939,0x000fdaccff17b830,0x000555c10dd87f30,0x0000649303ebab9f,0x00004603695b87e7}, {0x00011c32e83358c6,0x00048efb0178f883,0x000ba8652508dd9b,0x000be51ca237062d,0x00002aac5a36047a}}, {{0x000d2a08b1ea7b31,0x00039e8b14859a61,0x000052f99d495ab6,0x000eea28740f8487,0x000078ebe5bc2974}, {0x000bcca5b36d17fa,0x00030af86eea030b,0x000f8e9e0b5e4cce,0x000e75151a022068,0x00004348796a9eb3}}, {{0x0002309eef1a7522,0x00074f2aa1edbe59,0x000007dd25d7162d,0x000d228ebfb5ed0f,0x000055e14b2e89ed}, {0x000e0720303b6972,0x0005d05720ffba85,0x00028ebb6c5d17e2,0x000112e2b58d6e51,0x0000c80242df754e}}, {{0x000ca5fabfae1ca1,0x000c0a21459b919f,0x00066a4d2937afaa,0x0003318e0ca91c1f,0x000094cc7f333ec1}, {0x000143a8aa116906,0x000ca9b59e08ad25,0x00050860abe40ad8,0x00034bd7d60d9be7,0x0000c53b00926bf4}}, {{0x000415d1356eb809,0x00030578ded8b572,0x0008fb38bb8bf9da,0x000b2192658e365e,0x0000b70ce22eaf8c}, {0x000018a829a81803,0x0003881ed2957c00,0x0003cea8384329f9,0x0005364c343ea25f,0x00008f8655f97586}}, {{0x000a0d01d3ec517a,0x0001b12321aea661,0x000a925989874465,0x000fea684ca591ec,0x00009bb9dc9bdcb3}, {0x000435578b4c2405,0x000b110cafdc14c5,0x00038846b5ed62a3,0x000160b7512f371b,0x000071bb70b00e38}}, {{0x000b95b2da705d20,0x0006b1a08f98b556,0x000ecfbe53ef8ada,0x0005cd85302ca7dd,0x0000e53057394310}, {0x0004d5521a9255d9,0x000162f3802a6055,0x00047787563a32fa,0x000da0a5c8c5b0cd,0x00007f458eafad42}}, {{0x0007080eb6b242d6,0x0002db71e246832d,0x00031139dd30bd02,0x000e531027991bbe,0x00008797e91a62e4}, {0x000e20a6b4e185ab,0x000d92d9b707423f,0x000f7811b82f2c67,0x00095c75c817684c,0x0000d53005eb45bb}}, }, {/* digit=30 [{1,2,3,..,}]*([2^210]*G) */ {{0x00049be9d8e68fd9,0x00028b044320e5f6,0x000c33398db0f053,0x000fae66fde9b3e0,0x00002f4209bf6c8c}, {0x000afcc1a739d4b6,0x000f428ab8dee9d1,0x000c6f1d009aea75,0x000aa4b4375fb5ea,0x0000420b560d08f7}}, {{0x000499c6254dc41f,0x00038a837e7e9eae,0x0000524a77e29392,0x0005f184aec08c09,0x000082b921a7d6f5}, {0x000962e1402cec5e,0x00071a2f30e7493c,0x000b879cb9f17ca1,0x00045edcd783e8e9,0x0000a3d8c153a6f1}}, {{0x00015e75e0dee6e5,0x00028c628aa2dede,0x00061bb9374f2487,0x0002e083e9c4fe78,0x00006d4822ab187b}, {0x00017cfc59826f90,0x00092408169eb664,0x0009ef885ca26096,0x00038fedf69d06c7,0x00000031f8adc7d1}}, {{0x00046e60ebcf7262,0x00014231470e103c,0x0007c21094482b83,0x0006ef4f6dfaca48,0x0000e0ace9782e66}, {0x000a9d31f8d1f420,0x0001574944d23246,0x0007f334b1b1e83f,0x000d8113dfa63aa5,0x0000cf8daed9f025}}, {{0x0008ea800ee11c1c,0x0003f5e3dd7530d7,0x0008c43c5eb053cd,0x000662db65b13ed5,0x00003ad49be7d151}, {0x0008e41b64279905,0x000d207eae1e99fd,0x000abb71e12cf15b,0x000d0dd9ad4f1b1a,0x0000143e74d57545}}, {{0x0006336c88bdee1c,0x00059876767c3026,0x00073199625f2930,0x000950dc078571c6,0x000088690b3ad552}, {0x0002c2d852705b44,0x00040e09552d274f,0x0006575d1b0bf8d4,0x0006513628beeb98,0x000007be238bf864}}, {{0x0003049a639fc6b8,0x0009060036250e5e,0x000cc1646e75c35d,0x0007398cf35bd85d,0x0000bcaced2ec262}, {0x000cf1db55367425,0x0006ca9e068be22e,0x0007909c5013dd89,0x000505c7f411cb8a,0x0000757ac98d61dd}}, {{0x0001f0d1e935abb5,0x0003c54de37a85de,0x0009cebb5defd10b,0x0004be68d9e39236,0x00004d5ef9bc6132}, {0x00041ba74f17e266,0x000818c1dde44d63,0x000d918fdc0a0e3c,0x000a1346d7758187,0x0000687601562ca3}}, {{0x0003e9cf36658f0c,0x000bb1f8057ec731,0x0006a835ac433ef1,0x00094bc53262461b,0x00008f053993c863}, {0x0008cdfe983c4a11,0x0001f3b7b931ff39,0x000b9045bbf5e816,0x00046b83193c46b7,0x0000e4ebf5db4a6e}}, {{0x0002a6043a24fe7c,0x000e3fb3492bf994,0x0002fde0529c1191,0x00032cdf66244990,0x0000792a7ad2713c}, {0x0008ad8b737982c6,0x0009421e60e32fd8,0x00083591a7e3a031,0x000455a9b0de4473,0x0000df141eee310a}}, {{0x000a039e6d6f4714,0x000ed198d12eaec1,0x000eee5ac14b2ba0,0x0004ceabc1a1603a,0x000001f483720b96}, {0x00037964fd03f663,0x0009ad8f3f122ee4,0x000380f183fdb4e4,0x000d163ef267f629,0x0000e8e9670bda64}}, {{0x000180c207674f17,0x0006c3ae8fdbbc19,0x000aeb71e112e09a,0x0001c7296675546a,0x00009432af25101b}, {0x000558fde2ddec64,0x000f1357753fd5eb,0x000e1158a81392d1,0x00099167a76b973a,0x000016fbbff8a899}}, {{0x000fdfd0d4a9dcf2,0x0008744ddf129e65,0x0008568667bc29e4,0x000fe29c1a92d93c,0x000073c69058e98d}, {0x000e418cdfaa6b88,0x0002d061c69f69fc,0x000f75e27606bd82,0x000a1ec2d495a06a,0x0000ed3d505ed873}}, {{0x00028416ab25b6a0,0x00072b1a4523af55,0x000c99e03c6c0ffc,0x00091bab18827b21,0x000060e864890346}, {0x000f90f93c7f3988,0x000b02f8d10b5207,0x000d0f9e39f4a96c,0x0004f55d71cd793a,0x00004f435d37c3a5}}, {{0x000c55b8e33787f1,0x0005963846734b03,0x00051b9f0ef42f97,0x0007c2ef7304f750,0x00008aca1dc841c8}, {0x00020a72d4bfe80d,0x000c353e732c56f1,0x00037ca16fd823b3,0x00096a41bccfe475,0x0000f6c9c74eb5a9}}, {{0x00032c7904fc3fa4,0x000587e3636aee73,0x00091d9aa14a23f4,0x000540838659c3f0,0x0000a995e5df12d8}, {0x0003becf3a5598a7,0x000741eaa99520a5,0x00004e03c56534b1,0x0002682ed3dca4bf,0x000016c563b48d56}}, {{0x00077a41d6178e77,0x000ff8a1ff8e27ba,0x00013f63de4c80c3,0x0006f3050110990a,0x0000bf33522161d4}, {0x000218e10b365bbb,0x00035fd7ea750aff,0x000b3a9258102180,0x0004e555a3fd8aa4,0x0000829e7604b3db}}, {{0x00075a54d53e5fb8,0x0002552717e36bdc,0x000a42ec204a5dc0,0x00038206af502fe9,0x0000867e8fba630e}, {0x0005c6ebec9889bd,0x0001fb47c98dbf84,0x0000c2a1254f491f,0x00008ad3091fba79,0x00007f6fd79920f7}}, {{0x000ac30acde5e173,0x00003852b4d7a569,0x00009ae54d0f996d,0x000061b51d4bb546,0x0000fa37d173daed}, {0x000868434b8fb41f,0x000caefb64f162a8,0x00048e1f299a2acb,0x000068c75c1a5e64,0x0000a99951b32b5a}}, {{0x0006e892f3b26e7d,0x00000a8752476d95,0x00082dda3f470986,0x0002ef6ad1517924,0x000064110e3d17d8}, {0x0008d2cfad414e41,0x00081ed02b241492,0x000821bf12b155f5,0x0005da381a141bcb,0x00002e3c7705f81f}}, {{0x0005de59fff83814,0x00021bbec894e49c,0x0004d88c41105323,0x00031b60d051cc45,0x0000f6db89c5f8e5}, {0x0003fd6ca563a441,0x000548da8ab934fe,0x00074f0a17f5c221,0x000a0a7445016d94,0x00007d34d61db7d8}}, {{0x00039101c474019d,0x0009052ceefb8e9d,0x000622c2bcaff262,0x000a0529cf3e32c1,0x00004b95e3db9071}, {0x000a61f1594438c2,0x0005e4aadedffbbc,0x000e149401eb6e6a,0x000a9c653027f468,0x000021d322affabd}}, {{0x000a9f6b7cb179a6,0x000d57934dcced8e,0x00009180ddc7b764,0x0002dd9cb139405e,0x0000629a6c0147dc}, {0x0005e4e9f5a915e1,0x00075204441ebfc5,0x0000c5f53b1db9d3,0x0005b1e82d68cf93,0x00007d3a142dbb60}}, {{0x00044ea308780f21,0x00012845f5e4dd59,0x00024d7a3dc8de76,0x00011e5beaba7d76,0x0000e709afd404df}, {0x0004376021704560,0x000ac8f94b649536,0x00080ca68bf204b3,0x0005744e53af7c56,0x0000526074ae0c67}}, {{0x000cef8ecd92af61,0x000a5cd1745a95d8,0x00025c3e4e6b9fa7,0x000aae2d546d3da3,0x0000f57691daae93}, {0x000f3fe9d2e1a33d,0x000edc063d35e891,0x00013a327d430093,0x00018f1da59b1255,0x0000c2134f42536f}}, {{0x000fe2c5c2102869,0x000d8cab658caa51,0x0003572923f68aae,0x000becca23a00bf9,0x0000a626f3a0efda}, {0x0003bf3199d78e38,0x0006f1bbc345fe2b,0x00059802cb7a2af7,0x00051bbd19827a1e,0x000023bbc163487a}}, {{0x00039f299d0a4221,0x0005e456c6fb8561,0x0001f8bd69ac3df6,0x000f879ddf65c670,0x000049f321e4758d}, {0x000f714721b7ebaf,0x000741a3312ab1ec,0x000c4d581e17df09,0x0001b2eb2fd6ecd5,0x0000d0299707fcea}}, {{0x000a63e7882f14f1,0x0004f7c6cadce29f,0x00082bed0c9f6dc3,0x00052c36f22d6fb8,0x0000a45755be118e}, {0x0007c277c4608cf7,0x0001e68012c29f2c,0x000729b0e7ccbdf3,0x000dbf8cb0aedd61,0x0000ca2ca9f67d75}}, {{0x000ecb16f640f620,0x000b39f51946f58f,0x00088af44e274b92,0x0009e57f4dfc0462,0x0000a91f32aeac32}, {0x000274bd6aaba315,0x000fbf6884f943ad,0x000f91e20719a163,0x000d52185d29f6da,0x0000ec1cc3377e49}}, {{0x000de963b54a0599,0x00055fbcfdb338f4,0x000bb8da60e0015e,0x0007ac877d23d94d,0x00008724aa327a61}, {0x000885bfdb6558ef,0x0009d7899a9630f0,0x0002dc112f9f7a28,0x000458e2ae8ac887,0x0000a0642cb63c3c}}, {{0x0006981e7dfc8d6c,0x000f5fb5b94a1529,0x000ddfd3767cd444,0x000dc64ec71cf10e,0x00007e5eeb45a8ed}, {0x0008e3d81d950286,0x000210b0e35d02ac,0x000881fe30088f17,0x000faa8c041fabe1,0x00002cf71b9399e7}}, {{0x000dea7e0f222c2d,0x000ba2e651425043,0x00016cd30309d42a,0x000eebc4fe9ddd92,0x00006539c7ddf87f}, {0x000a57c432ac7d72,0x0000127fda1003c5,0x0000698de72692cf,0x0003b1cc28c85f28,0x0000331fb469ec28}}, {{0x000fa322867e6332,0x0001ea9cc815d34b,0x0005e2fa578709a8,0x000fb597fe696487,0x00005cc064fbe98b}, {0x000151c493a65c5a,0x0000b31824649eb0,0x0004618e25fb5d94,0x000ab5c9e6f130f0,0x00008ecec23989c8}}, {{0x000c88bb96209bd8,0x000b33e1c9e0cd6a,0x0008d8eac65fa8cd,0x000963247d22f54a,0x00003895ce00d33f}, {0x000ca59b56cd3d1b,0x000b2af38232a8ad,0x000080a9f10c8350,0x000b397b161fb3a5,0x0000e7f5c64eaf65}}, {{0x000403997403a113,0x0006e21b96af2c75,0x000983ec294626cf,0x000df7131de7c46a,0x0000780dd3a82cc3}, {0x0000e462baf8e3b1,0x000d41d299aee28a,0x0007a2408abe68aa,0x000981503eb8f964,0x00004c61ed66c750}}, {{0x0004414c53352e78,0x000b9337d46e88b3,0x0005f2bc85a34889,0x000a39e12c1560f9,0x0000a3f844254807}, {0x0009e975224da68d,0x0007f3eb00e9680d,0x0006bc37560cd6e8,0x0004c16875a98e9a,0x0000c80f9251fd55}}, {{0x00034156ac774075,0x000ed54206816c4b,0x00007a458a1e5ea8,0x000bf9041bfa1446,0x0000dbc7e7ae6d7f}, {0x000851b31590a478,0x000995ee6df8646a,0x000b43fc0039e85b,0x000e04519fa231d7,0x00004bc8be8a99a0}}, {{0x0002936f20df03ab,0x0001d608d4722b9d,0x00049202a2405438,0x0007b6c6b6ba0491,0x000021c3831e670e}, {0x0003059d6fdee104,0x000338488e71ddd9,0x000fcfb259da47ad,0x00095459cc1dfda0,0x00002abde10a4696}}, {{0x00015fc17eab9fe8,0x000453e7097214cc,0x00032112cd6e863e,0x0004d7a9a7765c64,0x00008660001db077}, {0x000175a2c088eaef,0x000d9230b8d43729,0x0005f437913afbca,0x0008115476815191,0x0000086431bc8d22}}, {{0x0001955c298b9743,0x0000c8711e043746,0x000969d18905fb5f,0x00094e487abf3afe,0x000092167c29f6a4}, {0x0000d2d28c511da9,0x000c266a262dfc7a,0x00063fdf0f127c7d,0x000f4669c4bb95fd,0x00000016589c913e}}, {{0x000a73c11aa600d6,0x000d3fb5ab5274d2,0x000b700682f5379b,0x0009a7849e53a47f,0x00008dd39e5a04aa}, {0x000cf572ecaa9c3c,0x000b2824826bb9b0,0x00031a3c4ba0e103,0x0006a1a0c2198b46,0x00005ff84acba896}}, {{0x000be22ac95aff87,0x000b45a46d092d6e,0x000ee4f8d1c9bb6d,0x000feed19062da53,0x0000b9042d12b97e}, {0x000f080830cf6bdb,0x0009bec8a6c60f87,0x0002f01aa4861d19,0x000bd523a0daa120,0x00000111675a25af}}, {{0x000d6cf1afb20d91,0x000030671bc56d00,0x00085ea9b1369500,0x0001ac813ab0dc24,0x0000f2bed06aeef6}, {0x00082176d799e206,0x0006d271c2de850c,0x0004f591093415f3,0x000420fafb06e96c,0x000088a52e024e9e}}, {{0x0005ba3e2a9a6db4,0x000d18f9268b3049,0x000b0f04f4601303,0x00036d7e3b0dad7e,0x0000ea4725084569}, {0x0008798d33fd3e7b,0x00093b4337088caf,0x000fd50ad1ccd8a8,0x0004deeeffe3e887,0x0000e240a571b29c}}, {{0x000fd98ca0e7ebd0,0x000ae748616eec4f,0x0007baa99f586783,0x000c9ca5b00d8fc7,0x0000acada29b4f34}, {0x000d67d0fe723ac6,0x0004d9c36c1e36da,0x0004bea411d8e53a,0x0004e084dd342d1f,0x00004fd5e364bc9e}}, {{0x0001f9057908805e,0x000c7ed480dd96f0,0x000fd2dd0b5b9ea3,0x000a26566c5dc23e,0x0000d2fe3064e9df}, {0x000e8926e9197e27,0x00093b502a5d4575,0x0001f213f11719c0,0x000456b64c7bece8,0x000041b9241c5f5c}}, {{0x0007b6849a5f4f41,0x00028fc45b7d78ac,0x000f5f355f91d70a,0x0000d929b05544b0,0x00001f06bcefef93}, {0x000d25d038d05e1c,0x0004facc1d51db84,0x0008ee00b04838ee,0x000a1edda3ce869e,0x00003412058836ed}}, {{0x000b91364d9c2f41,0x00039010a8ffae80,0x000359d417468bac,0x000acccfd2003737,0x0000a0f5ab825efe}, {0x000ad2f659d0ce0a,0x000ac785cff17c25,0x0002192c74011bcb,0x0000e7728b99127e,0x0000549d8e1b3ccb}}, {{0x00088d8c85438b17,0x000d4c25cb278055,0x0004bfdf45680332,0x0005666cd1bc961a,0x000079ff428e06f6}, {0x000e998f059987ad,0x0001fc686de78bbe,0x0003cfdb2f6ce8cf,0x000a3628ad3c4a95,0x00001d426d9f205d}}, {{0x000f13fc781a2419,0x000e475362a8b3c0,0x000a911843e89360,0x0007f43cd05863c8,0x0000bd0c9b87fa8a}, {0x0004d538a912a4b1,0x0008acf518fd97ee,0x00067e1e0de5e15f,0x0002565a055bf8c4,0x00000be4b4b2587e}}, {{0x00014f2668621c9c,0x0000eb9c92c1d90c,0x000d47b3cd5518f5,0x000174ce6a0100d6,0x0000be980de26716}, {0x0003f10ddd83683c,0x000cd9cac73c500d,0x00083d5503b6cb35,0x00098693730c8b60,0x0000f1597689f0a1}}, {{0x000cf5343ad73b3b,0x000f9f035a9484bf,0x000eeac691b528c1,0x00023f9294edf733,0x00006283e84317f3}, {0x000c9590a5f25b1e,0x00047844ee22c3fd,0x000dde4deefaf8aa,0x0003befe269ba5db,0x00003347161a5613}}, {{0x00042198d9ea9f87,0x000b83fc1ab5c118,0x000f22cda090de5d,0x000893d04c37b10b,0x0000de20ec965618}, {0x000588eecdaecabd,0x000cb8342743754c,0x000a938ec6ca4b0e,0x000ccaa6f08bddf4,0x0000182de8a61493}}, {{0x000c53ec8a4186a5,0x000b446d8e33d652,0x00037663cb3e878d,0x00048ab88453c05f,0x0000cd9daab04077}, {0x000197f586d5e720,0x0008c443ca59a1f5,0x00065242447500be,0x00067d78ef35b2e2,0x00009c5d26f6dd77}}, {{0x000a79aa74d3f7b3,0x000d9f5ea4597175,0x000d1746d0428fd8,0x000278211cb97ca5,0x0000636393a171d1}, {0x000f95510350bf49,0x0008d0aae782cf2d,0x000688809b381743,0x0000061748c0e43e,0x00008021fc067a5a}}, {{0x000a70c0e367a98a,0x00046f62b7c29076,0x000fe0343bea1bc1,0x00014e8645a68c30,0x0000caffa79099dc}, {0x0009964457bf9c43,0x000add2ead83f446,0x000c6f3eb0db6407,0x00056c38d56cadb2,0x0000b512e7423763}}, {{0x0000e1ffce104080,0x00035a5e257de43b,0x00062e5b389ddc00,0x000161b0ae0d1203,0x00007f983c7b0519}, {0x0004d155d5231e7b,0x000c5b4f9513c2e9,0x000d0b0b5cff22ae,0x000cd5002588dd6a,0x0000967d1acc1d0d}}, {{0x0006bc6cf777b6c0,0x000d4c6d19598dac,0x000f5cc850062bdb,0x00014f53da71b50e,0x00007012c7d4006f}, {0x000f962ac47800d1,0x000bb102ed754617,0x000b8c9d353365f2,0x0001c9a422efcb4a,0x000095cb26b44af3}}, {{0x0006e2905f2c4ce9,0x000b0856966c3a92,0x000527015bd2bdec,0x000230cd16ab3a85,0x0000f81609ed486c}, {0x0006b2cda350002f,0x00000a1b7d36d8b9,0x0001d79bcbd05469,0x000e4dec90ebf5e7,0x0000241b6f9f8964}}, {{0x00086432fe3cd4c0,0x000bb4bc633c7c83,0x000139f1fe0f33ac,0x000f49b4a9ecec3d,0x00005ce69cddc4a1}, {0x0001b16f5f98aaf9,0x0005df23e0efa19d,0x000cdfdd345bb71d,0x0000c9a3789fcd46,0x0000b8e29795ee04}}, {{0x000b246ae0a6828c,0x0003b078d5aa9c69,0x000b4fbdbba533d2,0x00085bba2e42c07b,0x0000fb4879b30353}, {0x000d30b3281705b5,0x000bf04fe0818c3d,0x000604edf7e361c6,0x000e472b21649c3f,0x0000dbf6a40352ff}}, {{0x0007c234b54d9bf9,0x0000a511c3d9c41b,0x000b2b7581374e68,0x000a958863bf16c1,0x00000e78507ae9e6}, {0x000f98d5d86f1749,0x0002f5e96fe4ab4b,0x000c5d344d74e0bd,0x000846fafde39fca,0x00000946dbd4d91b}}, {{0x0002358fe1a838c8,0x0004e20ac9d8f5b4,0x000ce5a0b05aae6c,0x000d720e193bd8a1,0x0000f710571cdabf}, {0x000dd48182caaac9,0x0009740745cf8d8f,0x000b93e6d8c4aeef,0x000010e3c6c30af3,0x000091241f3a6f42}}, {{0x0008eeae457a4773,0x000bbe6ddc05a015,0x000c41671d19857d,0x000d588326522418,0x0000ffdfc7e6c2c0}, {0x000525426ee7cda3,0x0009af02c3a83a3a,0x0003bbfc8341b086,0x0006917023bf4272,0x0000d15002a44452}}, }, {/* digit=31 [{1,2,3,..,}]*([2^217]*G) */ {{0x000324c85edfa308,0x000407d4f3da5ef7,0x000b50c862597655,0x00096bb52f5bc0dc,0x0000f6927b0c832a}, {0x000e1ba55f2f94c5,0x0008e44b45fad08e,0x000aa455d6a996f9,0x0001f79133cb8da8,0x0000d0721ecc58dc}}, {{0x000a92079e5fb67e,0x000a90aa725e6ba7,0x000f5d837e1331fe,0x000e207080ccf57d,0x00004cae01e5ff72}, {0x0003ee60412a77db,0x000c2f449025d924,0x000ef5a3106ff7ca,0x0007a80e75f7cd23,0x0000c957822bddef}}, {{0x000230cb0ce1c552,0x0004ebbfb6078cf7,0x00016363b5b534d0,0x000e82ce1ef1130e,0x00007e0aa7ad4999}, {0x000ac2d79362c410,0x000091bb6cb0ce1d,0x00023df2467920c9,0x000f281e648d6322,0x0000f7d9eefe32e8}}, {{0x000f39afa8338349,0x0002163285626943,0x00070fc102295172,0x000e6cf1d63dd541,0x0000f5fa5903ecc2}, {0x0008725e77d9a3b0,0x000a6384ebe0b66c,0x00045e24a11235ce,0x0003b106a8c11858,0x0000137b286ebd09}}, {{0x000e1ce44ace1509,0x0008b381e97cc589,0x000c5a4b8e0f8d3d,0x0009f8c9e99b1162,0x00000d262f88d0ec}, {0x00054c9283e13c98,0x00072edc7085fbc8,0x000dcbecb2d04fde,0x000a5e857d776547,0x0000dbdf5921a76f}}, {{0x00006950de1e5786,0x000789f72bc6d015,0x00039eca52e1463e,0x000f2f9fa684411b,0x000073c8530dc037}, {0x000a600747f91da5,0x000179cb78e9d0d6,0x000b5cef5b08d43e,0x000fd5bfc0c64427,0x0000c1d160af60a2}}, {{0x000ae5328c8e13bb,0x000402eddcd1f98c,0x000ce06ad375f10c,0x0001ef24eb8b7f5c,0x00004669f4630a2e}, {0x000f9d05bbd8699b,0x000937976d13d593,0x0007e28d35528a4c,0x0005768923e0951c,0x00009293790ef6bb}}, {{0x0007d6ac42bd6d29,0x00082b1f96aedb56,0x00043b28e6df8646,0x00023f7efe5b1a48,0x000061bbb05f379b}, {0x000f5f070a6a26b8,0x000cb28e6e39b6ca,0x0005fc8d370686c0,0x000dc900da06cf89,0x000004d88113363f}}, {{0x000877b207f16700,0x00084e615291be22,0x000a3c2bf9b0dd18,0x0006e8625ae8dc97,0x00008584ef7439b8}, {0x00090a5dcd898ffc,0x000f6058ee3dde71,0x00087b1c126286c3,0x000db47db0b2175f,0x0000c334771d02a6}}, {{0x000e9542f770fb1d,0x000f7cd7535ed99d,0x00009cefc97c1c61,0x0004f803b6c4483f,0x0000725af162a63b}, {0x000d24fc01e20ecf,0x0003aae7121f0c95,0x00077b7ecdfd3749,0x0004ad8d6ddb72ec,0x0000e079d3bf353a}}, {{0x000e70a2e6ac8d23,0x0002e06e5c053066,0x000e59b8c9c6b5a4,0x0009ae22d3c6f5ed,0x00000d6a5c42ccec}, {0x0007c224fc0a9ef0,0x000395c16cededec,0x000de0fde190ff08,0x000433be12ec8f94,0x0000d131ab8852d3}}, {{0x000e07e857012919,0x0008894061a842ac,0x000f4a48594793ed,0x000f4ca0e83ed6d7,0x0000eec726a89eef}, {0x000ba590c9d8005a,0x00077e79b9d190ac,0x000506a1e5feca45,0x000fa6efbe54271d,0x000032b2c8ec439c}}, {{0x000c17373dd0b4ea,0x0003a4a054c61671,0x0008b53f137a2821,0x000b9de1760a1b4e,0x00006c0422599f93}, {0x0004b34cf671e3ce,0x0001eda9b9941878,0x000ab384881bbecd,0x000c2c58831979b2,0x0000f54feb8d2e03}}, {{0x0007ca7fb8088fa5,0x0006fddc96c5cf19,0x0007771760142724,0x00071d52d2550a30,0x000034698989d0cf}, {0x00037b83a2aaac68,0x0002daf38d9b6ce9,0x000bf2899e9f91dc,0x000c15a598ad83c8,0x0000e706aca35536}}, {{0x0007495f688dc983,0x0006e24c4afc40dc,0x00018775c26490cd,0x000f4ab651ec841f,0x000093ea6c3e4fda}, {0x00033437f338e0d8,0x000ae053e7b51e1f,0x0009e14d539fb832,0x0006dfc6e702da61,0x000059cacd24deef}}, {{0x0009ce74462007dd,0x00047cb5f5b763b9,0x0005edde7b8ab48a,0x000fd9cec673d2f5,0x00001567f755cfae}, {0x0001b6b0887bcec5,0x000e9178f3c24638,0x0006266cb694497c,0x0004130e6525e31e,0x0000931de26b97d6}}, {{0x000df7c0e58d4939,0x000fc8b73f1287f8,0x000a0c34db1ae5ec,0x0001a03368f784de,0x0000bd0a121159a9}, {0x00088b7cc863c683,0x000e0d1f4d65b00d,0x000a855933a1cc11,0x000ee8ba38e0e70a,0x00007f13e98adc4a}}, {{0x0008667bc947badd,0x000d5a36ee2e10d3,0x00077fcac738e07c,0x00070cf93470cdc5,0x0000ee1b616f7824}, {0x0005e672e793d12f,0x000df0f186da36a2,0x000e07af7d6aa6ca,0x000cd3574d0fd980,0x00007cdc47eaa8a5}}, {{0x0006d9dab15247f0,0x0000493a537f28af,0x000a334e77c789c1,0x0002777ac9b11023,0x0000236ac0912c9c}, {0x000bd251d7a51446,0x000a913ec4eca7e5,0x000f0abca098b9c2,0x0000f8d639dacad3,0x000042da81b02396}}, {{0x0005c054f7269b13,0x0007b287c3857d2e,0x000a46f21fcf3077,0x000a35e0edc84ff2,0x000054417577f43f}, {0x0007899fd703431a,0x000576dd587af132,0x000c8352da438d7a,0x00024dc5c34c57e9,0x0000728edabfcc5a}}, {{0x0008abc42531689f,0x0007110963efaed7,0x00017d9b30a51a0e,0x00028a6776fa0ad7,0x0000356c23a6dd34}, {0x0003fff8d3a3dace,0x00095d94491f2990,0x0004a56a4409597f,0x0004616cd7a5ffbf,0x000050964756adab}}, {{0x00051265c3427b0b,0x000c2282c9bda97b,0x0002c5c456401405,0x000aec8629f8d722,0x00001c02c1798d50}, {0x000ed75d9635bc92,0x00074e24552fbea2,0x000f1d066226790c,0x000c2e1c33f2a365,0x0000a43463e8dfcc}}, {{0x000453adb4837611,0x000555d5672b8cc3,0x0003efc87e7cc608,0x000eaf177ed6cbde,0x00009f2f36879234}, {0x00043175c0b800bd,0x0008bb6da6e29aaf,0x0004ec75e1f1e7c8,0x0008c19cfb4715b9,0x0000590dd6015311}}, {{0x0009da11f17a34c7,0x0008b35a145614e4,0x00050363b5420ab3,0x000b6e476372412f,0x0000b15d62433fab}, {0x00040b1e274e49c4,0x000456b1860aa0ef,0x000afe5a45cf5074,0x000e9a96583fbf66,0x00004240511347e3}}, {{0x000434311b2d595d,0x00091ec8df579925,0x00073dd05f136749,0x0000296cb12c613e,0x0000248c0344dac1}, {0x0004f13a77739f5e,0x000a43d2af42cf15,0x000e4a1cfbf4288c,0x0008f2ca64c9b632,0x0000e8c07a9a8a20}}, {{0x00049996fe8393f2,0x000fc91f3a32e10d,0x0002f63c80f809a3,0x000d3d41096d1c80,0x000089e146277750}, {0x000167e9889feea9,0x000250993909ed06,0x000508ac6d5c9c0e,0x000e82b6fca0d856,0x00001826047df1b8}}, {{0x000877a9a4a27515,0x00027ae6fead4f2c,0x000aa194171bd007,0x000aa7e8df8dcc06,0x0000a074b4cb3bee}, {0x0005934c1cec8edc,0x000deabc03bdd6d6,0x0008a8415a6ecb49,0x0006dfeade91c2de,0x0000fb0efe029113}}, {{0x00045ee23ab3495c,0x00074b77463d11af,0x0005d06f4a132df8,0x000435c923c15c81,0x00003ceb3f5cd61a}, {0x000291de88fb1da6,0x0003bda12179af52,0x000fef720ea05797,0x00084550d7218cd2,0x0000c0899c9ee1d8}}, {{0x0007504752ddad71,0x000f91a68a979815,0x00058fb99d60bd74,0x0001e46047a3a9f6,0x0000f5d86d66f851}, {0x000bc424b5a6d88f,0x00022abefa7db8a4,0x000c9c51069eb2c3,0x000b42a5bf39e813,0x0000571960bc48aa}}, {{0x000fbcf704e23c66,0x0001c8aaa65b7e8c,0x0005e3c83c71b7d2,0x0004ff4041b2bd24,0x00009b9883532185}, {0x00027a3963bfeec0,0x000ade7da7cb89d2,0x00068a9b199947aa,0x0003681d9ee9dbee,0x0000a08f003698ec}}, {{0x000409478ef24870,0x000502cfec26e9ea,0x000dcf328c8d2d41,0x000937c52f9a6eb7,0x0000ed489e385b6a}, {0x000986bbef3366e9,0x00005dddddb89b94,0x000dddbe20de59c7,0x000a406fdb748cea,0x0000b9784bc1266e}}, {{0x00055021a93507a4,0x00074d3c06cf142b,0x000ec3f40b4cd118,0x0003c29f70e76a91,0x000084e81ad8e755}, {0x00087b5272e9d6ec,0x000506ff514a830f,0x000192a8eea1c93e,0x000359a7cc2adcc4,0x000077e27e302f45}}, {{0x000ab36d2b713c5b,0x00001f7b0cd39cdb,0x000af826b86274ea,0x000ea2c84680f309,0x0000fcc837abc72d}, {0x000fe9dd6529b73d,0x000793a88002a8bd,0x0001d45b9708aa22,0x000f559c7a9a54c9,0x0000f1a38bccd004}}, {{0x0009a26b8bad853a,0x00029723eae72e8c,0x000ca28302d52cea,0x000410654d6d8156,0x00003317d153a8dc}, {0x00062fefd4ddedab,0x000a055d792ba086,0x000c6e944ed2a153,0x000cf2c035c16abf,0x00006bc5834b0171}}, {{0x00052b383d102b6b,0x00065646b848e271,0x0006e6d37fe695a4,0x00015df5bb09d891,0x00004269d64bd170}, {0x00056a10a1d22850,0x000146d26d728d81,0x0005434a7feef6c5,0x000e319dac57c84c,0x0000282e5be59d39}}, {{0x000f181721c486d5,0x00006c58824eedff,0x000570031301baf1,0x000e683136a6aa00,0x00005aaf78c6cddd}, {0x000937159c639522,0x00046bc25baf2682,0x000e52dc33a3bd27,0x0006c8ccdf8657b7,0x0000dd8c0881d78e}}, {{0x0003274f5531461d,0x00008d95499b2055,0x00080f9d28b4a128,0x00075812c8763a1a,0x00001dbe32c1ddec}, {0x000210d30c34169a,0x0002d8baa533af12,0x00038f254ba74a95,0x000f5a9d133c6ea4,0x0000431531ac01be}}, {{0x0005e22f669d7ec1,0x0004257fb5151529,0x000a3fdb3ca374f6,0x000da87a8406ffea,0x000006ae448ef3f2}, {0x0000a9033c8e9a1f,0x000181ad58858f9b,0x0000aed14234645e,0x000d454d0832241c,0x000010a7d3f6a942}}, {{0x000deee40d5c9be3,0x000f8a84ed987c11,0x000d58dddb2bae7f,0x000fa363e97139aa,0x0000d8727966f6d1}, {0x000ca818569ff132,0x000b7a600f72483a,0x0006f2b868b89a5f,0x000c0b2cbc27c3c0,0x0000213071383ad9}}, {{0x0008b1e48ac28403,0x0004bcba9477b535,0x000946b431831129,0x000819aa58f990a6,0x0000098baf9cab41}, {0x000c1584198da522,0x000bf46bfd1b66c4,0x00036a908ab4fc17,0x0008380f0a4c3cbf,0x0000ae9e34b78cf7}}, {{0x000529e3fa11b1f7,0x0007274af2b4f411,0x00030793b21e4367,0x0000f30c20958ec2,0x000010ea88586e84}, {0x00021fcc5dc67cf9,0x0006f8405718fc0b,0x000e49eb708d5164,0x000a1f4955c21fcf,0x0000722a5d5e6dd4}}, {{0x00050e2c861baa5c,0x000cd505ac3ec9ef,0x0007c063fc0c21a5,0x0009c0ef6b9a338b,0x00006370339ef477}, {0x00099c7638167c3f,0x0005895db30c22df,0x000854989fe6ffe7,0x000aa43b822d33a4,0x0000ef031de20563}}, {{0x0009f82d57c667f8,0x000e4c0b76f116b0,0x000118aecc70312c,0x0001333f04a9e6c9,0x00002fcb419b409d}, {0x000b385ab45d44d1,0x0002517b83a31a8a,0x000e81b52fba0722,0x000affa05f50dd58,0x0000d8db55331ce5}}, {{0x000b8d4e344a8732,0x000dde36d53e3097,0x00075e7507d8d116,0x0004ea4db22f5878,0x0000dc5e37363e14}, {0x00032e6e799eb95b,0x000eb899e6ecc05f,0x000ab23d5e9e5f4d,0x0000e60dc3bd681f,0x000072b8ab823af6}}, {{0x0007ae02cecc84ab,0x0007cbdb871c8db2,0x000c46f58600016d,0x000d3892a44b13d7,0x0000891972873a77}, {0x000bbbddafd60884,0x00062bd20d39cfc6,0x000c410721a74014,0x000ea14c747abd98,0x0000c91e765fdf68}}, {{0x000e5ca08819a786,0x0009695879217c95,0x000bbcc7dcf48b72,0x000148a91c7c5fde,0x0000f28740550e05}, {0x0005ac226cd44ecc,0x00060fea250ef83b,0x00006ebc588ae32a,0x000780aac5047a1d,0x00007e550b59434f}}, {{0x0001cf25c727bd2e,0x00003cf915b061ab,0x0009d39202e4badb,0x000dfd3b4dadecf6,0x000061b1ca7d14c1}, {0x00079ccbd6bd51f4,0x00014045ec3090b4,0x000ef0e628024e40,0x000bc08ab29ca325,0x0000f2e941689e4e}}, {{0x00040ec0ccced589,0x000b7da44f9845eb,0x0001812c625cd4b9,0x000650b3e0645887,0x00009f80d55a6cef}, {0x00040c9ce6dc1532,0x0007b86655215713,0x00007014d138d511,0x000b918cdb45bc4e,0x0000f34bb38a4b60}}, {{0x0004fd22ae8921e6,0x000e292ba1e2f44a,0x000c180b2b039288,0x000c873da50174b1,0x0000b70ab667693d}, {0x000abc9e70574810,0x000f9c80dc417e9b,0x0002946824581dde,0x0006e50c890da951,0x0000b5629d33f473}}, {{0x000c79eb06f5b41e,0x000d6e2434692340,0x0005a71a9a42e84c,0x000fb619a2013504,0x0000fbfb416b27b6}, {0x000ea239d33cd6f3,0x00087a6c0af825eb,0x000ce6f969caedb8,0x00015a23dc7e9ad9,0x0000897f9fd81e0b}}, {{0x000b1f88e5d788e9,0x000851d490eef51c,0x00058cb3c1aec7ba,0x000d30965991e0cc,0x0000f306e8d2fc3a}, {0x000006e5040a0acd,0x00032b476f2e5fed,0x000ea7a23ca9d504,0x000b62d19c06e8be,0x00002865801dedab}}, {{0x000293f6967469a8,0x00090d8a8ed8db92,0x000c771222894d83,0x00026a07c9e406bb,0x0000671c6f1aea3a}, {0x000f8d6d7de9853b,0x000601f2bcc7e42d,0x0009d50cf2e3ce34,0x00098f2a601dfc89,0x0000fc913dfab1b5}}, {{0x000909fe61f7908e,0x000ebbbc7b2981c4,0x00004b338192e304,0x000d60e3ed8738c1,0x0000dbe9e48583f5}, {0x000e9be2db30660f,0x000ed0eb7d8e0c06,0x0002e096eda3e613,0x000246e8fa3e9732,0x0000ebd91e9c336e}}, {{0x000ccc4df655a499,0x000bceb202108f13,0x00056b6eaa9e00df,0x000946f4631d0fc6,0x00003a058ce68c0d}, {0x000904a67bd3448e,0x000a1394fd5c6846,0x000225f524a3d4e1,0x000e99e102c1a5db,0x00003455bbbdc4f5}}, {{0x000985b4b9ad1ce1,0x00064bb7f7936b36,0x000b1a416a981853,0x000ee75c25e1d048,0x0000381dd534c81b}, {0x0000d617a4a76209,0x0005a9b8944cd2a3,0x00097c33ac841292,0x0004e6ac1c6fbe7a,0x000041e541e23866}}, {{0x00099e84a34f239b,0x000c090402d54174,0x0003aa83215fdb83,0x000db1075f46bf43,0x000061e15b013215}, {0x00059d4a127f89a5,0x000bb7e816daaabe,0x00018b6925d541e0,0x0000265aba0659a6,0x0000532773367266}}, {{0x000a0fc95f57552b,0x000fbcacb0c9af53,0x00021be013294764,0x000145753ff58dc8,0x00000309532506f1}, {0x000bdf505c2e54da,0x000c86e8dd2259bb,0x0007e1e53158f27a,0x00050d2c5b7ffb39,0x0000e03f65c1fc1e}}, {{0x0004ebd9c95f0f98,0x0001a4640771a978,0x0005561c45ed9deb,0x0007ddb1244af703,0x00007332f3afee85}, {0x0006e9e2b9e0d888,0x0003d6a0604909e1,0x000592f4852d910f,0x000677d07ed477a9,0x00005cb917ba365d}}, {{0x0001c934c8998d19,0x0000e30ea58ff851,0x000029db02186a3f,0x000759c0189626b2,0x0000137a6d992ceb}, {0x0007f37748bc82c0,0x000180469f8c2fe1,0x000891aa287c2e93,0x000d8d850f71cdbf,0x0000ca1b89b75ec3}}, {{0x00043aa5e1cd3cd7,0x00082a887c28516c,0x000ea1f9f8939780,0x0008f69059c699dd,0x0000737d6fafe686}, {0x000746a60f1524b3,0x00058a052aa76d93,0x000923ea536985e5,0x000a1111b1d322ed,0x0000429759f55852}}, {{0x0006ec3092e9f414,0x000622256bbdbeca,0x000ad487d3a238c6,0x000d93982958ea70,0x0000ac8aaf9a5610}, {0x00001b15e4ccab05,0x00024de14bfb3fa1,0x00031899d9bf430f,0x00017d510f5cc665,0x000090005fc3a8ce}}, {{0x000912f24544cb60,0x000ad79ac2e3c437,0x00058a2129987b71,0x00060613e3d9ddc0,0x00000075aacd2de9}, {0x000508b6cac83696,0x0007954f6c8980ab,0x000c532a487842be,0x000bc847ad663d6b,0x00007813de7d8a91}}, {{0x00061cec3427239e,0x000fe56934d95dcb,0x0001915915f3c7ce,0x000da6e079e0fbe3,0x000040896be901aa}, {0x00067910492d25f2,0x0009c74082768d46,0x00087aacc8aeb30c,0x0003d4c943749592,0x00003d4708d99fe0}}, {{0x0009cf2d0c051995,0x0002aae784548cda,0x00072a182502fbc2,0x00037270bda9dff5,0x0000f9b71b8b158b}, {0x0003a592b82dd077,0x00052523032ee0f3,0x000505a327630273,0x00009f0fe1a721c4,0x0000b6e3e8367964}}, }, {/* digit=32 [{1,2,3,..,}]*([2^224]*G) */ {{0x0007bc035d0b34a2,0x000b6327c0a7e341,0x0000362d1440b386,0x0009436fb7262dac,0x0000c41114d00cdf}, {0x000cef1ad95a0b12,0x000847d543622ba5,0x000e486c9c09b37a,0x00029706d6cdd201,0x00000477abf62ff9}}, {{0x000dcb3292a92874,0x000637b092c7a004,0x0006c0605ddc15cf,0x0007afc83a846480,0x0000a68df707db99}, {0x0004e4505bf7dd0a,0x0008eccf7f8c9c13,0x000b5f8afa4e63d3,0x0001cc06e6517f41,0x0000a8b93434d7bc}}, {{0x00035b51e706ad97,0x000453a9ebdf126f,0x000608d90b99cebb,0x000858375389afbf,0x00006113c5036c89}, {0x0008eb097e2b5aa3,0x000c33b9130480de,0x000cc066c7e1022c,0x0009000bdab6056c,0x00003cbb144e2edf}}, {{0x00064717af715d2e,0x0003f0134a96c417,0x0001ec956e2f7f59,0x0003034c1873efa4,0x00004e7b4f757821}, {0x000ff9788d5374a6,0x000320823d5be5c8,0x000ee8fe22b915e6,0x0006518a6bc755b2,0x0000657624d47112}}, {{0x000f101dace5aca9,0x000181a6a267157a,0x0009c8609c4fdbcf,0x000a654addf340c4,0x00007e49f5379604}, {0x000e790937e2ad5c,0x0007726e17f19be8,0x000bbc0dc846e250,0x0006d57f38007a0b,0x0000f036040711e1}}, {{0x00000e07442f1d58,0x0000e6e0e3abd6f8,0x000c64047475607d,0x00083d02807f16b7,0x0000858e1e427498}, {0x000120b8231ee10a,0x000ac38a1ece5859,0x000aa73a41b80e7e,0x0003ac2b72525ac6,0x00007cdea3e24442}}, {{0x000c007f8ae7c38d,0x000b6d7401925ed0,0x000e36db36db07a5,0x000045ee5e9c2a5f,0x00005b9d57b46e95}, {0x00032e78eba20f2f,0x000e81b9a35254ac,0x00098a658ef11ca8,0x000666405e373eff,0x0000fe5a101723eb}}, {{0x0007b11e51732d26,0x0007c538fc0e5747,0x00039eec5dfd6eb2,0x000c56fc43b0cc3b,0x0000af127792b36c}, {0x000852d06c425aef,0x000b6c221b9b70b0,0x000826d9c6df92f8,0x0009c27c8d4f9ece,0x000059aba7ca4935}}, {{0x000d8d5da64309d0,0x000691b307045c8e,0x0009b580861a6de5,0x0008a7d6b52f6a2f,0x0000eee419498c95}, {0x0009aab771e4caa3,0x000d48bc21becddd,0x000b504f583965df,0x000290d2affce3b3,0x00000847a21861c8}}, {{0x0002cf152bfda056,0x00090197b98cd2eb,0x000a1726fe0e4c4e,0x000e3cbd35076cf8,0x0000c06085b8db11}, {0x000c4d74463ba14f,0x00021030238c15c0,0x00027536d9d292f8,0x000c1d2311ee8b37,0x0000eea86f0aeaed}}, {{0x0008cd366131e2e7,0x000f10fe2682b9d1,0x000160289f31d974,0x00079946e49e0fe4,0x0000c48ec0b78e92}, {0x00011d8d1989aa7f,0x0009fbf926f98181,0x00045474ab34fa0a,0x000755eb5fe2f5a2,0x000080a6ebc2c7ca}}, {{0x0006054afa05dd8e,0x00011caf119ea7f9,0x00064bb5926dfcf2,0x0002b8020ef2e305,0x0000f4dca5141cb0}, {0x000838a65d306723,0x0004cd657e86cda7,0x000d595c88b08d53,0x0008361c5b439546,0x00009b58725725cb}}, {{0x00010593de9abe37,0x00012cdc03be8ea6,0x000edce8c4043488,0x0004a12b261245cf,0x00008c318b53f523}, {0x000cf16fde24c99d,0x0004d2c2ff5d510b,0x000960fb42a77cb7,0x00042acc895c2b27,0x000030ce97680eda}}, {{0x00053931a62cc262,0x000630c0e052fda8,0x000c633f323c69b9,0x000d488227df15bf,0x0000ac788483bae7}, {0x00078f9187d073d8,0x0009167f807d4878,0x0006e6d8f6c2be91,0x000a42f65861d833,0x00008b8974d4e528}}, {{0x0001177ff57d0517,0x00078b6a19610952,0x000d76ad42ff3803,0x000c178c0aba74a3,0x0000c76480395a7e}, {0x000d75f48879bc89,0x000fc8ce6bc17532,0x000896c16ea7eacb,0x000fed382176b48e,0x0000a30e0b2bc750}}, {{0x0002c2e421d3aa42,0x000cc84fa840c37e,0x00054e41cf926407,0x000643f8abc03d14,0x00006605ecd5f7af}, {0x00041a6d6a5eabf5,0x0003d16b668e2423,0x0000101021edb84f,0x000d8c8836edb804,0x0000b337ce7e45e1}}, {{0x0005c77c055dc14a,0x0004e1d89cdfd207,0x000fdcbaf2a0ffa2,0x000866ece815ea6f,0x000034288799b648}, {0x00099cf884655fb3,0x0006064d3e412776,0x0001e1cb7fa5b5bd,0x000d66d1f680c644,0x0000fd61e66e70a7}}, {{0x000a2dccc78cf662,0x00044fdbff77666b,0x0008d4668b301817,0x000a2a6d4dd0db16,0x000059455d03dab3}, {0x00064c5cde3acec5,0x0004c3adb276f585,0x000303f657714192,0x000f7b027d725d8a,0x00005deb6ca36f38}}, {{0x000b657b1fa70fbf,0x000ee8073a00fd5b,0x000a02500fa07f50,0x00040d072e3aa7bc,0x000068f895e89757}, {0x00020605cae2a6aa,0x0007628748423011,0x000e47bd301bd721,0x0004f59d4238917c,0x000066663c218954}}, {{0x00005d73272d8383,0x0009ca6295c5864d,0x0002fda32e22924f,0x0005445189593f6c,0x000030d7189e184b}, {0x000a62cbde1f7140,0x0004e5cb1a6379ef,0x0001c833235771c9,0x0008542f4826b864,0x00000a894fbc8cee}}, {{0x000a39b36194d408,0x0004f7612601b4b9,0x000cf2f58e857a7c,0x00048774209dd24e,0x00002b9e66dda033}, {0x0006934e4e8b9dd4,0x000d642377d7c1e3,0x0003ae43bd2372c9,0x000f6f11dc94c70e,0x0000c57761e44474}}, {{0x000cd0a1058a3184,0x000538053a9adcda,0x000c68de2369cf3f,0x000d9f86c3de5031,0x0000653a5767c4b6}, {0x000dd5aaa4e5c975,0x000167ab3c741688,0x00065c2835be80aa,0x00009120cefe7cbc,0x00007f95f1356867}}, {{0x00014e24415503b6,0x0005ecbb17e9a391,0x000dec966c08ff7c,0x000f62beff674dd7,0x0000d4690afb3376}, {0x000e32eea74237b0,0x000ecd57508eff6f,0x000cc40fec436d17,0x000b4415aa28e1ed,0x0000d769c04581bb}}, {{0x000b6de34eaacda9,0x00079ba0f1dec240,0x000438e55d9e116e,0x0002d73be45ec779,0x00001787c9e26f75}, {0x000532bf129ac2fd,0x00078a36e22c897f,0x0009fb8f3d307b7c,0x000b27c194067574,0x000014f95d0e57fd}}, {{0x000d0296ae550430,0x000f44a87de1fe51,0x000e4fee28931e98,0x000d92e57f1cc609,0x0000d063b674e072}, {0x00098b9ed0e4316a,0x000a906aca4670a9,0x000da97c7e74a736,0x000d934cf0fbf24f,0x000040f65cbde178}}, {{0x000360416df4285e,0x000af0c56ae21625,0x000c5cfc3b0c9bab,0x00005593032b19cf,0x0000497e5c3e9752}, {0x0006bb4164bda960,0x0009a0b74da11209,0x0003826ba1ee4241,0x0006608fc3624340,0x0000c8f0069dc09e}}, {{0x000e981c27253c98,0x000b12b36a458667,0x000b7bb4605a6aef,0x00027b262c4b369c,0x0000394f37591f70}, {0x000c79c5f109d0fe,0x00057b8cc60a747b,0x000f09e68cad88a7,0x000eaba0c5a66b58,0x0000753d452d6127}}, {{0x00074a15b0ec6f5e,0x00037289b2b8c44b,0x000d6fc7347989fe,0x0000aa945f848458,0x0000c362a70d61c7}, {0x00098a7b3a8ad418,0x000ffb63db51070c,0x0004c35f473a20fb,0x000dca6d2c2173f4,0x0000a56149e1acc9}}, {{0x00078819ac6e0f4f,0x000eb413b5ed98f1,0x00000b0fd360fdea,0x0002d21625b8f4a3,0x00001f4d76b4b322}, {0x0005109587f76b89,0x000c9317fdb59d6f,0x00068b0958b4ee08,0x0009b8f8089bb78c,0x00005570e9ae808d}}, {{0x000c36f35d33ae72,0x000330bb5a94a395,0x000afe84b200ea12,0x00076a00c789bd0b,0x000043ef52d29192}, {0x000c577e23ae233d,0x000ed460d1ec3934,0x000fa76a4b93807a,0x000490e72a53b1f8,0x00008914cb193ca4}}, {{0x00084943fb42622f,0x000b600907d52e12,0x00095ec633b2700a,0x000fbd0370fb091a,0x00008f30be321b6d}, {0x000f8d269e55f156,0x00016c1323e9f2b2,0x000e5eef61fead85,0x00007e9a366010d9,0x00004d487b143161}}, {{0x0006b86d23ddc820,0x000c7e0143f04c07,0x0007af2c503fd344,0x000a4fa95362ff31,0x0000add3db7e18b7}, {0x0003e3f8260e01bc,0x000494a1cc919c67,0x000f2e433fbeb49e,0x0001ead1351bf292,0x0000755e7ed45114}}, {{0x0005139296077453,0x0000726f2b28c9a9,0x000c6f9dd0ca0742,0x000fc09b2790e74b,0x000045bbb58ddcaf}, {0x000a38cbe0f27a29,0x000bd41fcb56c65e,0x000e2c75767c24d7,0x000c489c25f0a7a9,0x00003f5cdb0a6f16}}, {{0x000a9d7c5ee30a1e,0x0004d909b7292ca5,0x000deff48d159363,0x0000c2a04ce9f3da,0x0000c464752907c3}, {0x0005ff39e49af6a5,0x000a1f3d01bc89d6,0x000ced843f2d6238,0x000fd7c095561e0b,0x00001789e1318a13}}, {{0x000f929763231dff,0x000cf7cbddefd633,0x000265da846df9f7,0x0006d111c889c0cb,0x0000ce1ad119f433}, {0x0000df6fc6a0a7e8,0x0007eda425dc8d11,0x00034aabedd431b9,0x0007fc4dc4aeab18,0x00004deb1250439b}}, {{0x000f1693c2a59987,0x00040947190d8796,0x0005970149b9247b,0x0006ede5b9d9a511,0x0000e9dd70deb156}, {0x00078f7cbcd5e64a,0x0006fbd4c03294ad,0x000c222ae0359ac1,0x0008119b11baaf7c,0x00006a6e2855a78e}}, {{0x000053f24cea1a04,0x0009f36214918392,0x000399ee9c97bce4,0x000ad13eb1db3435,0x000073f78f02ce81}, {0x0002fe0f63d3d0d4,0x00006fab62fc41d7,0x000158383e620b88,0x000f6c52096bc993,0x00001a21357cf896}}, {{0x000e2fac7dcfcabd,0x000dc546e0071b5e,0x000b02e07650acfd,0x00003cf081b749b1,0x0000a9e41a1c9eca}, {0x000a727175a54ab2,0x0000ca5d8d10013b,0x000fd96a9ca0cd19,0x00094065ea52c095,0x0000c591b9fdc5c3}}, {{0x000d4e42bad4d5f9,0x00006ef0059b6fb4,0x000122294fa4c359,0x0001d0da10218af5,0x0000a78a81b38575}, {0x0000579a98e84e7f,0x000f5997e5b504f2,0x00021e1e4fe1242b,0x00039cf77a273bca,0x0000cc8b1f084119}}, {{0x000a30292d0487a1,0x000c194b91fee20e,0x0006b0e8f1442dbe,0x0003180f7a4afebb,0x0000700ef747889c}, {0x000ffc370f1fc62b,0x0005b9c79ccaf5bb,0x000f6340d3b31d4b,0x00010a38bc2aaba7,0x00000b08ab55725e}}, {{0x0005701ae3400501,0x00060cf0c56944f0,0x000e19a51ba4b301,0x00052e4aa29f83fb,0x0000b9ed428c71d7}, {0x000e54eeb4819f5f,0x000cae18b75b1666,0x000e27b0b616cdfe,0x000e4c212ed5be3e,0x0000bf2831a34c7d}}, {{0x000ec85e0e60d843,0x000fedb7ee78d685,0x0003c4d6e68037e2,0x000a6a2b65bdcd00,0x00003e7363ac3e29}, {0x0003a6108d0756c9,0x000b9faf134b995b,0x000337823d727f85,0x0008b46ac6edf71d,0x00009b9aa509439b}}, {{0x000b104e2b4e075d,0x0004737c4926722e,0x000a9b82d4998729,0x0006f4e1e4c0e446,0x00000cb319827a00}, {0x0000f7dd7808c569,0x000ec1f89772f3de,0x000bd31aab5c54d8,0x000caac00a114aad,0x0000afaaaa6b95f6}}, {{0x0005e2104cf667af,0x000aad3935d79470,0x00009267cfc2a811,0x00053a660b02806d,0x000019ed11ae780e}, {0x0007c09067b6269c,0x00029caef599f022,0x000efeebc967b853,0x000ae5555b924368,0x0000d6d34f68497b}}, {{0x000d5d36cceb3707,0x0009378d7bf91dd8,0x000b67a622aeac57,0x000f66ed65017d70,0x00000c8e44f87c53}, {0x000095086a34d092,0x0006c7134907d1fc,0x000fdd315e0fca25,0x0009adc24fa29c80,0x0000c4acd03f8749}}, {{0x00075173b5a9ba6e,0x000532e51a51baaf,0x000154897b9cbe1f,0x000c9ff88edae35e,0x00004309c3d57b66}, {0x0005805f67f37466,0x000a436401fff555,0x000499a5385fc37b,0x00055b7f86e2cad9,0x0000270b2a44cbc9}}, {{0x00064f5974ad33b0,0x0007fe7b2df1afae,0x000b03f7304d8597,0x00040a2a3db3ff4a,0x0000b87878a87027}, {0x0003f015a0617323,0x000e732a19016d26,0x000155018c25430c,0x00078ec7ebab3ddb,0x0000a86f69393a9b}}, {{0x000e368da9f3804c,0x000de164349c349a,0x00062baa5470f07f,0x000df3152f4cc985,0x000074a9e86eb290}, {0x000aa3543471a24c,0x000df8194511d3a1,0x000dcd44d239446b,0x00082cfec2dd0081,0x0000a3d7f10842ac}}, {{0x000b085fdaf45207,0x000fd549daf21f3d,0x000ad5c42bb6d3e7,0x00051185969d8a19,0x0000052b13e4bfd1}, {0x0000d1b682b90604,0x00036c34452c1189,0x0003805b4a71d388,0x00023e6438055b78,0x000032412778725b}}, {{0x000f96e4901bbed5,0x0000a432a2bbf20c,0x000a9cd7d6419c71,0x00024907a0fbb9df,0x000089111e450daa}, {0x0009a337b60554e1,0x0007dde283a41980,0x0003bfd35ea5f888,0x000a531d71380250,0x000051bb0af685d2}}, {{0x0008f7443b30ca81,0x000ac993458340b0,0x0001110ade10b5bb,0x0006c5d8a546d6b5,0x0000dd50e6638e0b}, {0x0009d54cff2b821f,0x000c57281760292e,0x00024d6e33882555,0x000da0234838f837,0x00002c679e112ddc}}, {{0x00088156d2a57687,0x0001ac1e7e2d40ee,0x0004ff4437f227bd,0x00054ad87ba134d0,0x00006e2ff3e3614e}, {0x0008d6fa3177ec75,0x0000d328fff536b8,0x000ba158ebf731d5,0x000188258caea249,0x0000ab8ff4c52938}}, {{0x000605635edc56d2,0x00095e940d7933e1,0x000866dcb5a69d34,0x000def4c4fd00103,0x00000a38f576893c}, {0x000e790fac3a15b2,0x000e5a4f8e6bfbf3,0x0003aca866ed7ea2,0x0003f78663eb4fbc,0x00002061ea5280d5}}, {{0x000dfe6f546783f8,0x0009da0a641e2480,0x000de8965d38bc6d,0x0005cf7b093cd12e,0x00009654db52cb45}, {0x000bf9a26e1adee2,0x0004173294d4413c,0x0008083fe291f376,0x000340e079725764,0x00005f504d3408cc}}, {{0x0008e5ec3a0ee43c,0x0009a79898ff635a,0x000c63d5670aaebc,0x000cffdee9f5475d,0x0000e987967bfb34}, {0x0006b195e26310aa,0x0003982a8ca8f9f8,0x000352fe49e43548,0x000570853bcb81c2,0x00004eac8b0e474b}}, {{0x0007512c1ad8cf84,0x000e59e0b697c1b9,0x000e85df0193b4e9,0x000afd539d271601,0x0000fb265b40d44e}, {0x0007dcde51e1ae29,0x000653d8b096321e,0x0006049988e3a8ca,0x000aa6fde46cb052,0x00001099ad8c9072}}, {{0x000f91c93aa96b8d,0x000aafca2e132617,0x0003287230fc8716,0x000521d7106f5e95,0x00001c9c40bf62e6}, {0x000fe8642b7c094a,0x000c7543c021b9ba,0x000befd5d1873439,0x000aff41baa5de5c,0x0000363fc5ef21e8}}, {{0x000320df862eaacc,0x000262c647dcefe6,0x00046d42814419c6,0x000f8e4e06707c4e,0x0000b6c83500a178}, {0x0003a45d30f917c7,0x00092879afee0f99,0x000500063d4c4b04,0x00060546142a1e70,0x0000c9b41c415d9d}}, {{0x000fc2f2f8ba2c73,0x000f4c67aa28bc00,0x0007869720966eb2,0x000b9fe3f7b5165a,0x0000bfb7557ba2fb}, {0x0004f235a2b96204,0x00072faf46be131c,0x000172323bff3ed2,0x0002465b4473d17e,0x000021e8878739f6}}, {{0x000587a25a416322,0x0004835b6c930fa8,0x000ebb8dbc081412,0x00029c0b18a9f559,0x000064e335796edb}, {0x0005ccdc87c51e26,0x000af01e6214af24,0x0003882ce16b3015,0x000e045b31c5600a,0x0000961bb955ec11}}, {{0x0005b8deff7a3a0d,0x0007e1df73263b82,0x000604a1fbec3373,0x00049898ad747c99,0x0000154c9356a3bd}, {0x000506f1cc7a906c,0x0001ac560e8fac33,0x0003e394473bb539,0x000433a428fcbe26,0x000011828d5dc387}}, {{0x0004be13e4b12ff9,0x00089d88667c3cd0,0x0008120cfc3aad9f,0x000532352ddcf824,0x000085a892eba389}, {0x000b21b3bb85fa06,0x00002dfc6269fbb4,0x000e2aceaf95375e,0x000d1f9b4fb06c7e,0x0000785426e909c4}}, {{0x00017c8d8ceb147d,0x000de70a5554659b,0x0006bc6349b649ee,0x00032e9b7fa0b5ac,0x000099fe2c7ed6e7}, {0x000e7628d3abba2e,0x0006c797b79930e6,0x00096464d18fee6e,0x000e117c9d360dc6,0x00003baeb4907bfd}}, {{0x000db47f23206d55,0x000fcd2601522bf5,0x0008ff89a2f6d341,0x000457c7b876533f,0x0000157c30c878fa}, {0x000c5c52d4fb936f,0x000bf6518cdc7517,0x000847a64ef22f7a,0x000a88eeb483e6bf,0x0000508455982e0f}}, }, {/* digit=33 [{1,2,3,..,}]*([2^231]*G) */ {{0x00059d8df7304d44,0x000bbf210e8eab96,0x0003fbd60b71bcf1,0x0004de69a2438bd7,0x0000595cd1f9d11b}, {0x000329a4835859dc,0x000cbdbb6e569c0d,0x000928a4e4a0f0d2,0x00015406038e5edf,0x000094296224f5ad}}, {{0x0003462f23f2d925,0x000d10b940789121,0x0006cde206cab71b,0x0004bc1bdd0a6317,0x00004c9b20d3e4d5}, {0x000d8aa9f2ac02f8,0x0006a06eedb03cd2,0x00008643403f8e61,0x000db947f68e1693,0x000031469c612dd3}}, {{0x000df248f9813540,0x000c3588a2598521,0x000a0992c587e23e,0x000407cbedf281d7,0x00006930a5538961}, {0x0000debbe5bbe21a,0x00048491817f0932,0x000065160a7ffa5b,0x0002a946c8b4d909,0x0000c4f39939ff6d}}, {{0x000a1583ae9c1bde,0x0008037ce2407aa7,0x000ab38b4e0af6d9,0x0008ca054342d928,0x00008b75007ea1c9}, {0x00086afe02358f2b,0x00063a921228efce,0x0001c67fc31b8b85,0x000d58552a19120a,0x00004069ea593aea}}, {{0x000d6e27fa03cb3d,0x000a3fdd7d883232,0x000cbfc5ddb938e5,0x00080e34c1d2cd2c,0x00002f45c137f3a5}, {0x00020b57883e6142,0x00089e7c5f265926,0x00067e1e35fd27e6,0x000aaef39e45a915,0x0000cc71d2d64d8a}}, {{0x00090cde36d07576,0x000179a293824a90,0x000b48ddff722d7b,0x000f439b7fb04c04,0x000028ad2a84be16}, {0x000bfb520226040e,0x00007104b6c4cd3f,0x00003c1886c34ecb,0x000aaf50c0754ec9,0x0000c336b090d23c}}, {{0x00062a21e206ee56,0x00002c49a633473d,0x000f6b2c3f1e2748,0x0006ea27ab956ce9,0x00001830b48c2b60}, {0x0006846e78e815f7,0x000edc02082a67cd,0x0002ec365fe40139,0x0006aae2bbbfcb95,0x00004c11642db983}}, {{0x000439e558df0194,0x000a6c712b279f51,0x000185a24230da4b,0x000f50118919e355,0x0000dcefcddc4b78}, {0x0000fb2a47d4c5ab,0x000f030e009ea7d9,0x000eed27355ac9ab,0x000faf4d2fc35974,0x000072d824d8bea8}}, {{0x0001a744513e2cae,0x000158240b2cce72,0x000baa4500b41861,0x000c2425199968d5,0x0000b1757ee0b0e8}, {0x0003e283dfac6d55,0x000df8a237f56ebc,0x000f61499b2431e2,0x00036adacb5e2352,0x0000558a2a8306c9}}, {{0x000f923cbb13d1b0,0x00025bfb9bfed213,0x0001144a998799f4,0x0005ee1ae8ddc970,0x0000b8b3bb64c559}, {0x000ef2e3ecebb211,0x000b2671f9a70ea9,0x0006f1d1f17cb6c4,0x00027637ef464f72,0x000071b94847943a}}, {{0x000ae2d7ef0329c3,0x000261c4402a51a4,0x000d45bbc0850922,0x00085134a61d35af,0x00008f096fe6035a}, {0x0008b74a1dec0270,0x00074fc7dcbac746,0x000a06353e8cf10e,0x000d66ea35ff40f4,0x0000b4c0dfa8b77d}}, {{0x0008552de7e5c194,0x000981c0256c779b,0x000d4743dfab2860,0x00093b24f58eeeab,0x0000e8ef838bb6cc}, {0x0000d264cb1bf3d1,0x000963dedf61ee65,0x000b70ced4c1f9d0,0x000e1e9ef7c9d7bf,0x0000ec0507e2641d}}, {{0x0005cc7cde450794,0x000a116ac9e4cd7e,0x00070315cde173c9,0x0008fb117a8494c1,0x000038fd905d1d8e}, {0x000c506c7d9630b4,0x000bb47d4d755145,0x0009a80e86457a87,0x000abe931646bf0d,0x000053add2c0ef3a}}, {{0x0001109a607419d5,0x00026b6bca80c994,0x000c431f3faa71e6,0x000479e4158c1307,0x000094abebce92bc}, {0x000a691eb78399f1,0x00052f42cba46dfe,0x0007c04f048aafb3,0x00091addcd65af07,0x0000a29a366f8844}}, {{0x00040e51c21f2bf8,0x000c25057aee023a,0x000ab072ef99a513,0x000bcf23fe7e25bc,0x0000568d2e1c0e32}, {0x00094ebd3f69d9f8,0x000287affab19045,0x000e330f4181a973,0x000fc164d68d76b6,0x00007a6dafc475a7}}, {{0x000b2b5ef7d92893,0x0007e97f015a549d,0x0000493b62480d4a,0x00033131d5590bc4,0x0000a55b52e9f780}, {0x0008115309eadb09,0x000a02e5c62540eb,0x0006a3d5adea7de5,0x000d60d4d631f0cc,0x0000d5e9d7d23e8d}}, {{0x000bef5206d3ffce,0x00029d808bd4f297,0x0004cf5ba23d5e03,0x000a896a4f6912d2,0x00004d8163be9cda}, {0x000e9efd3082e8e5,0x000bb192f3600e0d,0x0008eee0a4fe1246,0x00091acf9001504b,0x0000219da8241da3}}, {{0x000a5c1f7ea25aaa,0x000f5bb07d5f7bf6,0x000e78671d165e6b,0x0002194353936189,0x00003fcac89cbac4}, {0x0006fd4f0baa8abc,0x000122c1c2e5dfab,0x000d858495a4adac,0x000180acd75e3140,0x0000e263fead9b39}}, {{0x00003d307032c722,0x000e590968c8cb68,0x000e978f07f40d5c,0x00051c86de86bddc,0x00005547c4f568f7}, {0x00085fd65fb2a9eb,0x000e6eb9179cb1e6,0x000504442ce69336,0x00006b015d1c2712,0x00007df465d6911a}}, {{0x00004a3315980cd1,0x0002ea3bebf7b8d8,0x00053c504693bc49,0x0004a22578aeee22,0x000058de498dd247}, {0x000f5c7cfda83685,0x000328d7177e1331,0x000c1e46ed2d7bbb,0x000be88f61133af3,0x0000836ce7e230e7}}, {{0x0004f1994f834cbc,0x0003829ed7828308,0x000e58243d35653d,0x00022ce542f16f59,0x00002b52f65c470a}, {0x000221b18f23d962,0x000c1f5252b4e3b6,0x000d61402cb05aba,0x0003e4aa00938b87,0x0000f186cdd61193}}, {{0x000ece59a29a5c5b,0x00068b6c8402e042,0x000d92684b19b3c0,0x000372197667c719,0x000056246239bc66}, {0x0006e653c04fa024,0x000c4eaa39aa0cb9,0x000a1633f83a7176,0x000f72e033561dea,0x00005a9d0868533d}}, {{0x0002c1d3dc090bc7,0x000f3a59c167e054,0x000e7fc4d82c996e,0x000b7973f735e80e,0x0000b179393ec35d}, {0x0009e25f8c5dbfdc,0x000d5f327b04b641,0x0008dfca84d9d7a1,0x000669d79f6f9b29,0x00007c5dff24de93}}, {{0x000588d04c82bdd5,0x0004a8319dfd1b7a,0x000eb95806800553,0x000a818e8a55b5d8,0x0000ea886dadd5bc}, {0x0000a01252a0b4d7,0x000dc5eaa0a1e853,0x000e995631bffb4f,0x000d86bad828b1d8,0x0000de96ef605f9c}}, {{0x0002d0cd77d970c2,0x0003b33ef9cb4abb,0x000211fe903cfb93,0x0001c690547c018b,0x0000fe64809c56ed}, {0x0005624c2ac98ccf,0x000f2a393e33cb7d,0x0006605212a1372b,0x0003e8d8d1ec1c29,0x00003d31b05a37ac}}, {{0x000e9df5ece6e7ce,0x000e2facfb55a29a,0x000a233a50603ac8,0x0000b7efe85b7add,0x000061891a09d75f}, {0x000a3d299bf1603d,0x00092184255af555,0x0009a3e021f43afc,0x000a390cdaf34131,0x00003b117efd3903}}, {{0x000da1365d1d131c,0x0007037ad03ee095,0x0002cd8dd86f1636,0x0000e59f37389e46,0x0000103fa05967a6}, {0x0004344f4b478f01,0x0008d117c98d57c3,0x0001fc12ece91edd,0x000ccaf01777b023,0x00001ae47f2c207b}}, {{0x000cf8d20f8a2425,0x000da22e1ad8d983,0x000c4feb37aff5b1,0x0003e118fd11d07f,0x0000d53ae9100f1c}, {0x0007905ec0418032,0x0006f440488850fb,0x000628d8f85e3c97,0x00032bee67faedac,0x0000e86515086685}}, {{0x000aaa46a67a6b02,0x0005925cec4115ac,0x000c6701ef4cdee2,0x0003d829ee565ae4,0x0000a04ca671c7d6}, {0x0005018ef0543fbf,0x0004e1b0d81deb10,0x00015d333f709a4f,0x0000aa6b906ee629,0x00004a8741386f1f}}, {{0x0002fa74d82f4c2b,0x000fb804efb3b6b8,0x000c3425e90725a5,0x00043e0c82ec46ad,0x00007b80581d7878}, {0x000d91cdd1fc74cd,0x000b1783a6c4df46,0x00004cbbadc1c62c,0x00076389d1b9f31a,0x000087f6f7365e40}}, {{0x000cfc1317f4a765,0x000b41036bce02b4,0x000e72a568d2703e,0x000b0f48206cc6a5,0x00007be9ed21f53f}, {0x0004571ef0b17acc,0x000e19181b380937,0x000935d0e74b2655,0x00093608f80ea889,0x00000d9e94351529}}, {{0x00060411e84e0e5b,0x0002fea34c931968,0x00073a732a5db84d,0x0007c049d5bb1970,0x00008d2fe571bcfd}, {0x0005f36f3eb82fab,0x000c4dff8b584577,0x00074c1108cb20cc,0x0008996659b65f83,0x00008b4a422e30c7}}, {{0x000c3ea6fe8208b7,0x0003b86e78fe75e3,0x000d93a1abd74b9e,0x000aad9be2e81bd7,0x0000ed06e284d0a5}, {0x0005a586be8b800c,0x00011846db28721f,0x000e88ed3428299d,0x000e10d5cb8e6b5b,0x00003186b23dc034}}, {{0x0002c9e8977d99b6,0x000123f531e7a631,0x000d3b1d4be94433,0x000b732232c0c218,0x000017aae8c41247}, {0x0003fc4282aec3b3,0x000fc7b8f8234015,0x00004f94cc6063d2,0x00034638f10e5833,0x00001efae751e676}}, {{0x0006c6d40a9b97c5,0x0002ff666256badb,0x00084b2e314702c6,0x000a408eb954f151,0x0000184a526e4b6c}, {0x0005337003c32ea4,0x000ce05974c7fff0,0x0000dd71a5aa374d,0x0007ec5a7638544b,0x000059cd2801eb94}}, {{0x0008161459c2b92c,0x0007b5ee8ef5a6e2,0x000b063102f020fa,0x00052ff132ec2d30,0x00003e1589a7c6a4}, {0x00053feaa3f451a6,0x000362d9acacdc5f,0x00027e58b3a3c7f2,0x00099ecec2f8926b,0x00008466ee837427}}, {{0x0004dd41fa266138,0x000b3dc29d639832,0x00012d657a2dc6da,0x000d1579675faad7,0x000013994bea1fd8}, {0x000b722fd4f75534,0x000bb3a36b205ccb,0x000559df55135ff8,0x000f3004be28af69,0x00000b65beddd41b}}, {{0x000f2a43734e5205,0x0002d09bdcbad98b,0x000945b355e3abbe,0x0004aa27c76553bc,0x0000331c09416ef1}, {0x000fe2976b60c80e,0x000a9ace16f8518f,0x0002b97842285593,0x0001b5cb1f64ccbe,0x00008f2c0da8b242}}, {{0x0007174c1df065c4,0x000b1f6578fa617d,0x0003b54a8afeeb5a,0x000ce2d6ff132926,0x00005c558090990d}, {0x000b6c0ecc8c1778,0x0004d982ecaa42ea,0x00007ef8e799ea9b,0x000c2c765da244b6,0x0000ab226ceb2a3f}}, {{0x00041e57ea973dc8,0x000fa0888f2e7457,0x000fd9cf15c00ca6,0x000871fcdce3cf45,0x0000a741ef1d507f}, {0x0001c2f196b4cec3,0x0003997ea61847c5,0x000b18a2b70d08e4,0x000514630da15c15,0x00003b6c6785f610}}, {{0x000e4f807ac97946,0x00005a06cb79c662,0x000d954e51eccf05,0x0001c2bff08623e7,0x0000ef2c5fb84cf7}, {0x00063d2679784532,0x0005fd654af8b2c0,0x000bdaa37a0cf379,0x0007e05cb242ea7e,0x000006e0b10d8674}}, {{0x000ae5fd5ecfefc4,0x000882bff8fc481d,0x00032459607084fd,0x0000364040a01aea,0x0000c64698114de4}, {0x000ab4ed65abfc39,0x000e83541ec79eb8,0x000695012e01cb91,0x0009ebff029adbfd,0x0000ae28483cc756}}, {{0x0004c9ea66d80a18,0x0003f5f5f911a561,0x000ba4fc1680a3e4,0x0001c08c07b14dce,0x000091c285c21307}, {0x0007ceb799ece3c0,0x000941e07e27cac6,0x000e4312329b910a,0x000cbe66bdb409f2,0x00006f8b1377ac9e}}, {{0x000fafd385470908,0x000f05e3415d5981,0x000e31b2719ab8b9,0x000b427c28c194c7,0x000043be0aaefbcb}, {0x000ed43a6db836ca,0x000361a45c05f3b1,0x000c1a3772a1330e,0x000e32af19f3c595,0x000085f39d0e4b5e}}, {{0x0008e6d4ae528342,0x00095423dcb03da1,0x000374aef5a403b3,0x0001119b555e0af2,0x0000ad599c43e8ca}, {0x0002fb9014b3bf81,0x0004e66d50071b3a,0x0003401027309268,0x0004ddf79f1426c4,0x0000827cf819fddf}}, {{0x00005f6f10ff9276,0x0000c3739fc6c836,0x000c1c2ccd387145,0x000ac50d163450ca,0x0000b52129702ec1}, {0x000c4f96e3cb4a55,0x0001278abff70606,0x0008e3a45e47d3f4,0x00015ff25a8d5ebe,0x00003ea9e97f6102}}, {{0x000106e39cbb688c,0x000233386d32477a,0x000b9b421532401d,0x00033ece564f64b1,0x0000a9b838941dad}, {0x0002b4e2093913eb,0x0001b9bc8112b142,0x000e7b2c7533d2f9,0x0007c58fa017beeb,0x00002767c4b7af19}}, {{0x000ff87aedbae9f1,0x000926880a54c925,0x0004d0e717daf0eb,0x000cf58284ddf59c,0x0000581cf93416f8}, {0x000a8873ac1f4527,0x00098b6aeffe3eec,0x000fb8dc3b417fce,0x00040035918046ee,0x00003d318ac72209}}, {{0x000400f728693e5f,0x000a439927ede800,0x000ea9910e87d814,0x000b68a3e94d3b57,0x0000f8a35b71245f}, {0x00053d77f200d34a,0x00076f653ce10438,0x000a06379470f1e6,0x000c28e1ac05bd59,0x000014052c2a3930}}, {{0x000fab526bc27979,0x000609f167716b72,0x0003e48d113670d1,0x000677701700521e,0x000078fe40247adf}, {0x000fb92d41c5dd45,0x000777b27da555ec,0x0003fb6065ff8e24,0x000a3c9751827201,0x0000768d7e57f547}}, {{0x000eaa360017a5ff,0x0003ac64ce9bbb24,0x0003dde076b18e6e,0x0007e9d225c65510,0x0000c3672af6592f}, {0x000ad77d06283a1a,0x000044d59d999606,0x00040e7c2542fc65,0x000f550bb57c492a,0x0000c948f1448db9}}, {{0x0009682b04465c31,0x000a5468bd156d4c,0x000318d7ee3d062f,0x000c95951729ac5f,0x0000fc87df6aeb6f}, {0x00046a80591f6528,0x0006d89621aa63d1,0x00031348ca861b8f,0x0006d9d9f5f15ace,0x0000f663391c40da}}, {{0x00078acb591ffa38,0x0004ccdfebcecfa7,0x0004ea6b3027ca9c,0x0002543e8e05a544,0x0000aab4e6a278d8}, {0x000f04fb474d6b85,0x0003b45b38552437,0x00047ecaa6597ffd,0x000bfc6b0aea4eca,0x000068aae83d5c7e}}, {{0x0006e64c73b23834,0x0007917d87620e96,0x000a05dab49eb344,0x0002369e1078218d,0x000043d8baa416b7}, {0x00063a5ea7610d6e,0x0004ee1ca979163b,0x000baa132e47e418,0x000b63ce648b6580,0x0000bf53de2ee0d5}}, {{0x000fcb4d3c8c1cab,0x0002ad04b3098d3b,0x000e7d3950d914ef,0x0000e7a5ef64153d,0x0000de1666fd6b85}, {0x000ca6ed449ab198,0x0002689a2672dbe1,0x000cb7a538902b32,0x0003ff31674b7eda,0x0000e9faf6f75252}}, {{0x00035da9a85788bc,0x000dfd0626d46ba5,0x00073dc64d21f03a,0x00097d499f8c47e8,0x0000da8564dc18ec}, {0x0007a5cde92c68ca,0x0000d3323cc43e8d,0x00080ff7c78e035a,0x000da99ef26275f8,0x00004ee3dffc73ee}}, {{0x0003507af4e18f85,0x0004b672f3285882,0x0009d3186967ec9b,0x00039c4ded19d955,0x0000e2ab3debcdce}, {0x0006e4d11c226dff,0x000297723014abad,0x000885719f9783f4,0x000dbeaa49a0cf1a,0x0000c0c1a5b80da9}}, {{0x000ec49571d92ac3,0x000e1692517f8bba,0x0004ea4af569e85f,0x0005ad5333b014a1,0x00002f2a62f42e5c}, {0x000ce3a06d89b85d,0x00095ff77a0898c2,0x000f795a2b90741a,0x0001985530defc01,0x00006e5ba0c54b3c}}, {{0x000845112e4c9366,0x000d5d0be17b7d8e,0x000262bc9ae419f7,0x0002bd4583fc8c22,0x0000b842ac7f1bfe}, {0x000f4e9440d68277,0x000e7f81fb1433ce,0x0004fbb925f69f4d,0x000158816cf6f623,0x00006ae3fc449e7e}}, {{0x000f6c2e9740b335,0x000cf962d6a14e89,0x000d10d15677bc85,0x0001cd1c6d8a7f68,0x0000f9a72245257b}, {0x000b9164ad859617,0x00077657ab4a7096,0x000461d7e5f8c47f,0x000ee26e57d7d0f7,0x0000eb6094df0ce5}}, {{0x0001dfd341905477,0x0003805dd1500b1e,0x000df44e68a394f4,0x0007189a9eb24d97,0x00008ca06bff7675}, {0x00034626ffeec228,0x0009b6cdd8fb6f0b,0x00005be479d91bce,0x0000e32c83363ca1,0x00001ba76c186971}}, {{0x00024cb28c682c67,0x00081612575b3d1b,0x000e66e9827f2522,0x0001fe4587c779e8,0x0000b0c03e9b05eb}, {0x000d03015b548e76,0x000fd8b36af7fdf0,0x000310c40a8be76d,0x000aebecdab04a4f,0x0000287223f547ec}}, {{0x00060558b399320d,0x0005f01e4646678e,0x000261a5e61fe3fa,0x000449f482866b03,0x0000fcf45b92c2f2}, {0x0009a512f684b432,0x0004a7220a668fab,0x000afa58ff796c65,0x0000ddfd90707ef5,0x0000c421d976fdbe}}, {{0x000cda3af2ebc2fd,0x000cfb4efe24c4f4,0x000cd10b1a0af843,0x000e0383b857c19c,0x0000dc9d1ec614d3}, {0x000c8bb62771deb1,0x000a81c5aa817bde,0x0002391ae829277a,0x0004ca6af18dd683,0x0000740f316d71a8}}, }, {/* digit=34 [{1,2,3,..,}]*([2^238]*G) */ {{0x000e99aeeaf8c495,0x000d1e24d7288928,0x0002b156cee7aa73,0x000a1cfc5007c2e7,0x0000fcf57c63d408}, {0x0009e39b6057604e,0x0000e2868bbf9f71,0x000103e2d7d343c0,0x000ea14cca254b7e,0x00006eb38aad131b}}, {{0x000624f8be762b49,0x0000758e3413b33e,0x000d805fa2a9ee4d,0x000fd7068e636967,0x0000848949c0db8b}, {0x000d7e5d23a84178,0x000d73e29da55308,0x000ee471f892f3b1,0x000089495c139e3d,0x0000631594e5757e}}, {{0x0002a3cde918dcce,0x000346fdcf4be0c8,0x000cb1b2d2e7b599,0x000e06a2c5024932,0x0000a613a9e5657a}, {0x0005f6cf1fdc9f70,0x0008879fe682c2eb,0x0001cbc7fb6eae8b,0x0000e6253dfee059,0x000000da7133e129}}, {{0x000e2ea1f095615b,0x000664e68c331083,0x0008818be0a28ad7,0x0000ccbbfc02523d,0x0000585113ba3585}, {0x0005f0b30df8aa1c,0x000b8ab7e3ac7d93,0x0002f00cbaddda07,0x000f6bd2c3429955,0x000033ed1dee909d}}, {{0x000195d80e877662,0x00087ddf4ac022c2,0x000e749349e99e6d,0x000240e9642e4e65,0x0000610ffa31f1ff}, {0x00047d4751c8159a,0x00050f3a93634d1d,0x000477c33697b498,0x000ff26318ca4687,0x000090cb5663441e}}, {{0x000384836f024cb1,0x00072601616858bb,0x0007e07f185be1f7,0x000f025c59587cdc,0x000091be071bf1d8}, {0x0009fa5cca5e55cb,0x000c47d04eacbf16,0x0007d05db3864ba3,0x000e5ce15e367f8d,0x000048a876e56549}}, {{0x000c656580e40a2f,0x000b828068bcef89,0x0007990c9f194ed8,0x00064884528045a4,0x000053fc7d84e1a4}, {0x000ae9b78593e7d5,0x0002f1db65d7bec5,0x000a3d39b2cac4ee,0x0003ef58c1eb2404,0x00003b7d63453f8f}}, {{0x0000d483e07113c9,0x0008ed8b63ae2dc4,0x000684c2b6e4a5d3,0x00026bc582a94b79,0x000032b33d4f22da}, {0x000f6510dbbf08dd,0x000894c23a52f534,0x0005bdc9b211d07c,0x0005573eeece0fee,0x0000f178169c7015}}, {{0x00046350a712229b,0x000759273f8cd429,0x00013bc8393cbe44,0x00078b50b095ef8f,0x0000b74197337989}, {0x00009a256dbe6e72,0x00063a5d39ec9d73,0x0001f9a31e578ec5,0x000eb41961151b85,0x0000da7715e05709}}, {{0x000301753dfabf0f,0x0007c8e39259867f,0x0005d9958728d207,0x000be06c75a0cd81,0x000084867a706603}, {0x000b13d70e35b1c7,0x0007a9b03e2cc865,0x0001f31210241446,0x000a7c746041daac,0x0000c9017addf028}}, {{0x0006de90a482873d,0x0000e77e54d4abc9,0x0007d88e74265d6b,0x000de298c38e79a5,0x0000461d7676ce82}, {0x0009ec564a7e489c,0x000ce0def5f2817a,0x0005d494ecc5675c,0x000149da00e78598,0x0000626833fdb035}}, {{0x000905a83cdd60ed,0x0004d1170184abe7,0x00023642a50602fb,0x000aff989886cdb0,0x0000568d09176e1f}, {0x00022c70259217fd,0x0008f43141e45b19,0x00095f86e93831cd,0x0008280fca35870c,0x0000ec2057b268ae}}, {{0x000a599f98a759a3,0x0002c7c23c1dc44e,0x000c4f68755a0a7a,0x000478a5ffb6e694,0x0000563cce242848}, {0x0003517e7b1fbe12,0x00092f7338e0812b,0x000d048db8a7dc97,0x0003b8011ecee952,0x0000eea4056e86ea}}, {{0x00068a7ba772b34e,0x00007f4e2541d8cb,0x000ec14dbe16ed34,0x0008bdbb32f6a60f,0x0000ee376f819169}, {0x000aa1783674c027,0x0006e843022ae9a7,0x000a4990f65832f9,0x000215b9f3a8da5b,0x00009a59c3b6b8e3}}, {{0x0004d2ebd19bb161,0x0000a3262d869cdc,0x0009c0b47c6c7cfd,0x000128c4ce14d096,0x0000fa352b723e56}, {0x00055b8973db6d32,0x0000c8e5b7bf383d,0x000bb571f7183685,0x000dd2a7714596e6,0x000059df31f4d5b2}}, {{0x0008925913cc16df,0x000cf1a26f5a568f,0x000f499ae18bc5b6,0x000e83efa413bef5,0x00008835dedb3f0a}, {0x0000bd865a40ab05,0x0008c94b377eb6e6,0x000084a696559643,0x000de06cd8562592,0x0000ce433b99f23e}}, {{0x000f04f6ad651437,0x000766e14af6e8e8,0x00095c0c71151182,0x000a15cd390a1082,0x00001e29ee4d21eb}, {0x000fc0963717b46b,0x000e306ad4a2a588,0x000c22b2202be02f,0x000848e31558c604,0x0000b4d4bd6c2f3c}}, {{0x000f49620efd6628,0x000045952d1454a4,0x0009784c292ba6d2,0x000643adb8ea1ecc,0x00001cc10cacb353}, {0x00070ad4b4d7f6ce,0x0005a4a1dcd240b5,0x00047e7975c9f1d9,0x0009f421379f8131,0x00005c6097c0bd49}}, {{0x000afa6328e5e200,0x000a5481555040dc,0x000bfc978f7b5244,0x0005b1b9a4f11847,0x0000ea0e79fd2582}, {0x00096eb646c7ecfb,0x0002946dea9da50f,0x000abcf69eb81149,0x0006e77af04677df,0x0000e3a06907713f}}, {{0x000523d42e06189e,0x00006e3aff13860d,0x000b20650bf07794,0x00000c2b616dcac1,0x000066dd6d201313}, {0x000fd67ff99abde3,0x000097aac50dd4a0,0x00046b2d7c990355,0x0002aed22ecf8b7c,0x0000333b1e86abf9}}, {{0x000113c6c491c14e,0x0007a0dd3f8811cc,0x000d932ed0597668,0x000b6d15b4d9e729,0x0000982aad982c38}, {0x00053478be0dcf0e,0x000d85ca53f26f92,0x0003ca77f700080a,0x000983f813115644,0x000092d6943cc51f}}, {{0x0008af885dfe9aef,0x00045d2a86cad2a0,0x000dff020d825d9a,0x000c3f3c53988d39,0x000038b135b330cd}, {0x0008ae062a7150b5,0x000dbc340e9b0c91,0x000bbf02ef31fd8d,0x0002395fa0e7ae4d,0x0000847fb2aaeba6}}, {{0x00047dcdccbac8b2,0x0007e6f485c86b16,0x00038ecdfb642aa7,0x0003fe673f376570,0x0000ce5e8661a49d}, {0x0003788c98c44004,0x000db1fa5279ea22,0x000becfd78104a8c,0x0004ae7cf7cc7a06,0x0000942431708f97}}, {{0x00065e784d6365d8,0x000f0f759fb8c0da,0x000e81930bcb7443,0x0008aab5c712b17a,0x00000428dffcc6e0}, {0x000afefa4faf8433,0x000dcfa9855ff19d,0x0003ac7ceced8538,0x00071df0ac409cbe,0x000058c1fb6b82da}}, {{0x000c0e5fd349961a,0x0000e421c2fcafa9,0x000a28d382b2cfa5,0x000e7d8a80db17f3,0x00008aba539fd138}, {0x0002d1d6e96eb8db,0x00001baf96225201,0x00064f56c65d8dea,0x000da1a7735447b2,0x0000eebef3fcb6c8}}, {{0x0006d98ce7852541,0x0002ab64a161fc34,0x000794addd50e8d7,0x000ef6b03567c749,0x00005a76065852c7}, {0x000a222961f23d6a,0x0007d3ecc0b059f3,0x00082fde4378e443,0x000f34274be4345a,0x0000e509af378b9c}}, {{0x000ee46577f44a13,0x000c8611deeb4a61,0x000f7b884e09b748,0x000a6b90481b2cf5,0x0000562667891acf}, {0x000c518bf8d21e6b,0x00010205a76d37f4,0x0004073c022d9653,0x00056687fb85e195,0x0000ceafe5015b3a}}, {{0x000def7be42a5821,0x000055046be6efec,0x000e8dba9d3fc608,0x0001ffb9af13c809,0x0000e6c984774149}, {0x0004925d30c31f70,0x000aac2a21223b57,0x0000859e7b7eb72b,0x000942776a0dacef,0x00006fec31421900}}, {{0x000bc10f8c22049d,0x0006b75ebf692464,0x00036326b9bfbcce,0x000cfa07a88e2a43,0x0000a05261d2bc2a}, {0x0005bdceba7efc8d,0x000955dbbf2ec29f,0x00075f127471237c,0x000325d72773f229,0x0000c744e8ed4d0b}}, {{0x000ed16a56edb730,0x00072c007e7038a7,0x00080b40064357e3,0x000be1a167d15b50,0x00007b4116423de4}, {0x0001e3274c898834,0x0000e882e7edb2d9,0x00003e4823c16282,0x0003316d6b36ba75,0x00008434e8e4ea34}}, {{0x000f24f2c7ae0b94,0x0000d939b44a79f4,0x000595eb1c46fbf8,0x0009c736fefae856,0x000017b66ac0d5f2}, {0x00032b2c5ceec209,0x000f51a1cae25f23,0x0000286e6d69661f,0x000992cede7e529b,0x0000d06252a7276b}}, {{0x00094b07e50122b3,0x000b1af07ca53247,0x0003fc97bdd744f8,0x000d9d00a12f08d6,0x00009650f1aa6626}, {0x00047f71fa38477c,0x000914dc124f101b,0x0006eb58a3d815f1,0x0008865569ae95b2,0x00003cde18955fb1}}, {{0x000f37bf9539a488,0x0005f408c1a554e9,0x000580cbbb0100e0,0x000c56021d9811ea,0x0000af52d3606e50}, {0x0009d47dbbf698b0,0x000a03dc1c73dfbd,0x0006a5df82961a1e,0x00007a203d38f8e7,0x00008a53a686def7}}, {{0x000fb481bee45d41,0x00062c68803626ee,0x0002f2469b3cee34,0x000162363c5315c4,0x00009d84d2e91378}, {0x000c3c51c4d349f6,0x0003b63d59c522d7,0x000abceae6596584,0x0009d56f198c56b8,0x0000fb1fb1bc2855}}, {{0x000fd0607bf8fe31,0x00082467734b8bbf,0x000f7f0d346259c5,0x000ff1c8953cea35,0x0000f0bece2e65b0}, {0x000b4b3f3c72914e,0x00045cb53389f7d5,0x0006b6d4629e8ea9,0x000fdd6a36562683,0x0000849f911ca174}}, {{0x0002fbbf4737f217,0x000af209f5ac7ec6,0x000f9adbed8dba5a,0x000767b4b5d7a9a5,0x000007d28f8161dc}, {0x000460bcaa999eab,0x000c6c92e4cc7711,0x000d4bf2dba7b174,0x0002788c4bab6618,0x00008f0c9819b8bd}}, {{0x000ea9a324b47379,0x0002a2a83bca024b,0x00032dcedfba9e42,0x0008b9de635643a2,0x00009619367b571c}, {0x000f35754b7032b4,0x0009e442d54ae8c9,0x00090c65af936b3b,0x000fdae263f0f082,0x000089897812e2c7}}, {{0x000d55a13d4f95eb,0x0004fd9b8500adc5,0x00073f43d737cff8,0x000475771c557b8a,0x0000ed617a5918bc}, {0x00054017dfd8ab26,0x000dda2870aa6624,0x000a7e545ae7b89a,0x000e4bbb555f5323,0x0000791e2481e057}}, {{0x00036ad324fa34d3,0x00071cbeae288601,0x000dd3299ea11144,0x000c33d23a4270be,0x0000d5c3a7ff1c35}, {0x000db678d0412d2e,0x00021cdc6b9ab0f6,0x00028a982d92625e,0x000e7db2ae5ccc4e,0x0000a251c3727a3c}}, {{0x0008932790691bf5,0x0008b6b736ae9d65,0x000d63b6eed61058,0x00088f212c2f04c0,0x0000cf06fd6163d4}, {0x0003facd9588e411,0x00021b93257e9736,0x0007acace1f9bf76,0x000ecf99d1ffc466,0x0000cf4a1aa1a061}}, {{0x0008a49dc1818d01,0x000993621ab040e4,0x0009ef6390643ff3,0x0008544768640ce3,0x0000fc099ea14d86}, {0x000b9c3eccd28fd0,0x00027eec54ab9130,0x000b475b6d743cbd,0x000d1f052b146fe5,0x000058d9a82900a7}}, {{0x000229291262b72f,0x0008cb0edf0365e0,0x00020684296f924f,0x00071f6cfa59c8fe,0x000060370054eafa}, {0x000699e18d7dd96b,0x00021bab24955f30,0x0008be949381e878,0x0008eee1669b46dd,0x000040606f5d6aae}}, {{0x000b839fc6751a47,0x00048ba800ef2812,0x0001a28751619621,0x000348d398d5ca4c,0x000020c00eed53d8}, {0x0009eb0d820007cf,0x000fb39b5825c269,0x0001f6984880ee65,0x0009998069469447,0x00007d16ea9d3dda}}, {{0x00075b2c0519a238,0x000dcf6952e328d6,0x000294a8a9ebf94f,0x0003f5728bb767a2,0x00005512b4e7e0af}, {0x0008ba899b16a0de,0x000bda7548a71895,0x0006be61595c2430,0x00074bd30d1b10a1,0x00003ebbb9865bfb}}, {{0x0003cfe18549fdb7,0x000edfcdb792a327,0x000aba56cf6e200b,0x000aa1e4a76e1883,0x00003ec66f6f9ef6}, {0x000add7d1b9a305c,0x0008f7ae1b9d8d17,0x000cc094aa959c5b,0x0009b8c86435226b,0x0000c5616c597d42}}, {{0x000da01e6a33f7ce,0x0006bd4e70ada6da,0x000c15b7cc6217a0,0x000853f619a81809,0x0000a06b329ee80c}, {0x00011cea5f5e7b9c,0x000fb87c65f41748,0x00016ab5466dfc30,0x000f6f8ea7bd6933,0x000012c4acbddcc0}}, {{0x0008d1a1e407dd9b,0x000be1afa997e430,0x00077b7a5e8a3587,0x000d523a296c12ab,0x00005ad49e5173c0}, {0x000b2b27006085ab,0x000fd7bf6ec240f9,0x0003066a6a88ff33,0x0006e1e78603b14e,0x00003f99fc365e48}}, {{0x0003f5eb2e636456,0x000724c8423207b5,0x00014d5cfbe57e54,0x000aca7779c21672,0x000017969cd629a3}, {0x00068cd8a7017a0a,0x000a1e9b7ee8d176,0x00016177677b4d19,0x000a71b8fd0e939c,0x00008c4f4f075968}}, {{0x00071cc67b3de77b,0x000db34f79052960,0x0007100c9ae3c0b8,0x000b41b7e440c28a,0x0000b8c3c1c9b4b9}, {0x000e8eac51b35836,0x000f3525e6426d71,0x000f509f37591f5a,0x000c9b973a2f7b13,0x000018487aab619a}}, {{0x000e5f79d61718a7,0x000c0592d28c3a72,0x0003c35cf00413bc,0x0006ed0d9b11d396,0x00007623bd0290a4}, {0x000273bdcdd2a50c,0x000a4601846edeef,0x000c6e9294a741f9,0x0002cc73b89e510e,0x0000b0231a04b7f2}}, {{0x000500d084bae24a,0x0006943d2693bbe1,0x000def8112f0ae8d,0x00094f0cffb5f27c,0x0000a0c030ac63fb}, {0x0000d61a0f442dea,0x000687b139d36eef,0x000d8bc28f92e181,0x00012f7ae6deb70a,0x000089e38dd60514}}, {{0x000b865d2fdca23e,0x0007ec8ef89581ee,0x0009056145a15ee0,0x00019a968fa10a01,0x0000ff5b8f0680ee}, {0x000cabbcb1c8a0ef,0x000cc8c838f9f0c0,0x0004a14c02e1ee9c,0x0008e41587d8b88a,0x00006f278971ff69}}, {{0x000ef1c89ee6256c,0x000dab353b45ed38,0x000e903b3f44ee1f,0x0001ded115c0c770,0x000078ec0a2418f3}, {0x0003324b7dccbc61,0x0003063bbc256c00,0x000edd805d96dd1f,0x0002f123aa82dd5c,0x000023aae4f8f7eb}}, {{0x000fcf5a26262cd2,0x000ce060ebd51723,0x000eaa3af1f7f4d5,0x000ccfd19c5c01b2,0x0000ccb9b14b790a}, {0x0001cad52324aa65,0x00062247df541f9c,0x000c96f826320052,0x0003840732fe42ba,0x00002fe771f51a1c}}, {{0x000a13db1001684e,0x000dc1709f75546c,0x000db8672b56b4ee,0x000cfa466545a9d5,0x0000d971c90fe8f3}, {0x0008691e3a07b296,0x000c84b696b94e7d,0x000c7e9ae7570d9e,0x0008447c5fa0677b,0x00008b44cb0282c4}}, {{0x00034b3bf44da801,0x00094ab32e66519d,0x00078a000283834f,0x0002f65e60879762,0x0000e62960e72731}, {0x000b27be6901c550,0x000824fdbc1f9b87,0x000acc27d80e7853,0x000b5abbbc09512f,0x00006394239ac143}}, {{0x0004a40376c1944a,0x0003c3da151135bb,0x000148a3b7cb6269,0x0002ee0fd29161b7,0x00006f9d9edee2ea}, {0x0002ca2880dd2123,0x0003761139a915dc,0x0000f8785903c381,0x0000fefaa7b46d6c,0x00006ce2871c01c6}}, {{0x000b028e10d9c12f,0x0001132f33d3c683,0x000a31b587573baa,0x000e1197a9b1f667,0x0000d3ed11be4ffa}, {0x000aa9a0cb2748e2,0x00083d6fdf1683dc,0x0007539418239f01,0x000b369a67b49c72,0x0000beec455e321c}}, {{0x00056063f8b84cec,0x0002cd38c86f8801,0x0008953dd7641708,0x000428454f1ca759,0x0000939e1110e8e7}, {0x000c2b35a914f2f1,0x0003d74b8f9c9b1a,0x0001b2fb039e35ed,0x000ba2c0debdb278,0x0000585638f3d997}}, {{0x000646e9e2fce99d,0x00004e80857f9c4b,0x00043b52a68a2108,0x00084236d54e4436,0x0000e8d6d63dd8eb}, {0x000156342146a0a4,0x00021eaa36227032,0x0001387878ba826f,0x000d36e27a58bd86,0x00003b6c03c50281}}, {{0x000afbbb54dde39a,0x000a3b6f2d5f6326,0x000f158e1744e5e8,0x00018ea8b2a99acf,0x000093c8fa18f879}, {0x000f956de058c5cc,0x0001d36f9e7a2182,0x000e31e67216235d,0x0003e6ece0c0dbd2,0x000096449c0b23ac}}, {{0x0002874170693bd8,0x000d245e63357e9a,0x000427344a28e14f,0x000df8d757f6b356,0x000022e45572cf8e}, {0x0006ee2e6a285cd9,0x000119df3af02b7a,0x00045b8445866f21,0x000e48b0dde2ddf8,0x000086c3726a10e5}}, {{0x0000c2af7172277b,0x000e5cccb2447368,0x000438ca757b94f0,0x0003fd0dff72672d,0x0000ad1ce127f466}, {0x000ed9dd8f71caef,0x0005a61fdaa69813,0x0006d1637f43272a,0x000977ceff0119bd,0x0000ebc4f9220361}}, {{0x0007a952f41deff1,0x000ad63b89b702b3,0x0003ff9510e44a59,0x000af4573257dc14,0x00009c02205e752b}, {0x0003069c4b7d692e,0x00031d1502ac46c2,0x0002208462e6392c,0x000b628057b1a21b,0x000051ff946ec1b5}}, }, {/* digit=35 [{1,2,3,..,}]*([2^245]*G) */ {{0x000cb51566c5c43e,0x00085597f0466e85,0x00094d94acff9c91,0x00027cb354e90c49,0x00000a3933301479}, {0x000fac10dc1eb2bf,0x00013ff319fa8427,0x00096527488cfd8c,0x000745f2d4e68401,0x0000a2e067e57aaa}}, {{0x0002a7f3e5f9f11f,0x0009e6cb3b8eb6d9,0x000f800bd9afe153,0x000e185d1a6dd7dd,0x00006c13cc1baf17}, {0x000c58e325fc3ee3,0x0000731dc3b215f6,0x000a3d3e77109540,0x000e2ce68e7c07af,0x0000f8417a1c4c7a}}, {{0x0004772813b230d7,0x000ea7344427ec23,0x0007fc56a634d0f5,0x000f76a1548ab1d7,0x0000fab17513e06a}, {0x00010a74f7c4f830,0x0004220a67d9b62c,0x0001209a0a7d2edc,0x0009f01c40417092,0x0000b9815a0face5}}, {{0x000589b319540c33,0x00097283d6f82842,0x000ae9fcb18490f5,0x000ba072731f84da,0x0000db6d960f3683}, {0x00063bb146110697,0x000e9788bf05c85c,0x0007460d2b19436a,0x000db1205459df34,0x00003f6e095511a7}}, {{0x000938eb6357f373,0x0008fbd8aa62dc7f,0x000a979fcc5d00f7,0x000a999878dcb92c,0x00007e83eda1b023}, {0x000e2731560bf3d1,0x00090d0fae616b23,0x0009414bd1086e45,0x000ea1682483169a,0x0000b956bc100ea9}}, {{0x000bb91c31b9c38e,0x000a68ef57b57b85,0x0003bab6f0c5aa90,0x000684fedeb169af,0x0000610ad740d373}, {0x00070df02ba8e15d,0x0005bca7f771f138,0x0002c036c0337edb,0x000e8114acf747b6,0x0000921d57786b94}}, {{0x00064392c422f7ac,0x00022d348898dbc8,0x0005bfcd1fb63536,0x000e10c3084668c4,0x0000357c9e3eb315}, {0x000b5405b2e5b8ce,0x00010102b9a4b173,0x0000fb1997e94693,0x00062a37c890eb7b,0x0000c225a84b61b6}}, {{0x000a3c8ee3c76cb3,0x0003a32a1f6ef306,0x00063e9563cf1162,0x000c26b6d5ab6468,0x0000b8a4cbe8c005}, {0x00029a59ce6bb278,0x000184d4b16fdcd5,0x00023798dc4afaa5,0x000fab30624a2679,0x00005e56df6eb307}}, {{0x000893c2bf296984,0x000497ce76030281,0x0009a558f91fc19a,0x000f7735a5dca3ad,0x00000ceb3fa8d50b}, {0x0006060bc9ba369d,0x0006897888c21baf,0x000a34c07927e103,0x0009800936bf1986,0x00004cf10c2934ae}}, {{0x0005334859dd614c,0x000a58d0c8ee3a3e,0x000cd51d59c475b5,0x000325a3080d1f07,0x00009c0d0a7788b4}, {0x0008691c234296f5,0x000444887fb61ac9,0x000ea9cf22a0a83a,0x0002f5065114270c,0x0000230a6e8f2480}}, {{0x000bf0f72e3d5c1e,0x00056f21439ef7a2,0x000e303343771744,0x0002f91edcbf259c,0x00000030a795ce20}, {0x0009ebf1202e9ca6,0x000c15e6e5916f2d,0x000dac4f8e79dde6,0x00004d952072aff1,0x0000c8d087f1b9b4}}, {{0x000c73dbce913af4,0x000b058a07cbad0f,0x000f00c8a909e587,0x0006abd300da84d4,0x000025cd048f5446}, {0x000b9be90e9d8bf9,0x000aae431b0eb59c,0x0001aecff991616d,0x000c3b43aa117a53,0x00001af92d3e9f4d}}, {{0x000c292e93fda293,0x0007b97d91bc9b1e,0x000ace1e676bb6c1,0x000ae34509d95faf,0x0000653fe47ee855}, {0x0000b280f680e752,0x000bceb6c26c7318,0x0006d423675eefd1,0x0001d884cdf29fb6,0x0000d70a9978b582}}, {{0x000e20720445c36d,0x0001898771747a3e,0x0009f73e971d1ac8,0x0000803fc539f794,0x000005cf3d8682e3}, {0x000e20b7b1c7129b,0x000fa69e61f28758,0x000544c2dffadcc1,0x000e53005d3a2f59,0x0000e16f5c24fff5}}, {{0x00065b8aad581350,0x0009037aa5be73cf,0x0006fd6a0622c211,0x0008cf79373b3f64,0x0000e029db50d397}, {0x000c43794fba0377,0x0006f20797a68bdf,0x00030d38eaefbd68,0x000463cfa5382bbd,0x0000627cfbfc85d7}}, {{0x0000fef4e4ca4631,0x00072566cc63b233,0x000780900bcef728,0x00027dc161d2cacf,0x000035dc5396b548}, {0x000052e27bf1bc68,0x000f87dfa06c638f,0x0003321da10a224e,0x000c8f6973586d6d,0x0000b0c5738a6152}}, {{0x0004f2a346060743,0x000870f7047a07ef,0x000a0e30680fe7fe,0x0002220d1a8152e1,0x00002cf43d8b8da5}, {0x000a95f5f02ffe6f,0x0003906ad3eabf89,0x000c8e55e3d9eb9a,0x000dab112c17bb79,0x0000dcd1a7589c81}}, {{0x000178bb95560983,0x000f501c38867043,0x00067b9124090a1d,0x0000c8459800ff9b,0x0000e5c030453262}, {0x0003c4b70dceecab,0x0004681f648e4b9d,0x00033345cbb2d3c1,0x00097a4981d8376e,0x0000626289bbcf22}}, {{0x000c6598baebdcf4,0x000935df01e5766a,0x0005876d81a28ae0,0x000800771283da37,0x0000865a96da07b9}, {0x0001bcd237936b24,0x000b2041749425dd,0x0000a2147332f4f4,0x00020390923d6837,0x000097f5dfc1c842}}, {{0x0004cbd32be5e0fc,0x000657a013759dc7,0x000d872b17475bcb,0x00063c838477c950,0x0000ec6787abfe1d}, {0x0006014d8578c70c,0x0007b8bb6b8b9b00,0x000fb3806c9ad99a,0x000ab2a799008e11,0x0000fe814368d44c}}, {{0x00015822f4fb344d,0x000f783fa6eba2ee,0x0002c7749b882344,0x00015a922d323d65,0x00008474a998eb0a}, {0x000154d5d1c00d06,0x0008ae3e7aace43c,0x00025ddf87fd581d,0x000738cb44c61925,0x00007a033ec18ae9}}, {{0x000fec19ef2d2e4a,0x000e35a0ea7f113f,0x000714c0a1bf6767,0x0009edb7fff75e03,0x000023c422eaa23e}, {0x0006b2d540f83afd,0x000d85ea46a7dd5f,0x0002a1208c2c2c27,0x000f7a1b6b424667,0x000013599f87e634}}, {{0x0004b5cd7b32c6ee,0x00000af61814cf91,0x0008a1bbb61a5a64,0x000aa4adc3df8b20,0x0000f627fd796d79}, {0x0002ffcc4c86bc81,0x000af61539fe4423,0x0008b9533e6f9231,0x0008850d04f25a95,0x000080cf93459e8c}}, {{0x00095959884aaf7a,0x000267b348a68968,0x000147c87b1959be,0x0001f7f6250e573c,0x0000e0efb3b7d0c6}, {0x000745eca8c325e7,0x00067cff3f70ed00,0x0009ad41d3c91169,0x0007ef03acbc6531,0x0000b01a02160b1c}}, {{0x000b29363a1483f9,0x0000ea248f96ea32,0x0003157e589eabe7,0x00046d0c6231d334,0x00003a375e66f3c5}, {0x00093436a2afe69a,0x00004166c88ee76e,0x000872093c4f8910,0x000a60848efd0d4f,0x0000e0eb3eb2fe0e}}, {{0x000790d9d79046e6,0x000d0cee0976af89,0x000071eca4d650f2,0x000bfe43935d9a43,0x00006fcd2c9883b0}, {0x0005eb5696605f18,0x0007254cd38d0e66,0x000d950cfe77e5d0,0x0009b510ee050a43,0x00006ddebdb532e6}}, {{0x0004a3dfddf74157,0x0008cf6e8d5a6ad9,0x000957f75f7fa130,0x00044754831d1de9,0x0000de2850245817}, {0x00070789e2aeb6b4,0x0004b67a53c26f1d,0x0009defc3ba2b9ff,0x00022bf6963767df,0x000079deed34d380}}, {{0x000b89b3a8631e8d,0x000daa213746d2ed,0x0000c5f118de855d,0x0005e3e2056cb7b0,0x0000eaefbd0fc9b8}, {0x0009a8dd150892d4,0x0005e18b798503f3,0x000375f1a37b8468,0x00098df6296dd8b7,0x000072cd4b1f78e8}}, {{0x000f651e9f05de9b,0x00087ce98ba915df,0x00038024cd404506,0x0005eed466a7ae9b,0x0000910e70195a6b}, {0x00056eab3aa8f0df,0x00068eee74a6ae1c,0x0004c4620bab2a50,0x0001f31dca11e24b,0x0000d896e2f3c47d}}, {{0x000ae53308fbd93d,0x000d32c36fdaeb45,0x000a4838546cd5a2,0x00095f9a3d4e90ba,0x0000d55e62f6dbe9}, {0x0006aa02a81ede7f,0x000409274ea7a140,0x000414f866860dd1,0x000326dfdcb0c280,0x0000f410b1112f94}}, {{0x000cc3849ad467b6,0x000baa7335f15a33,0x00053a360efb48b6,0x0009cbb4fb54a4b1,0x000004aa9d315246}, {0x000c486754e48e96,0x0004d7471e8e5e9d,0x0003b37b6693cb45,0x000f079b2fd7cd8d,0x00003345e172f09f}}, {{0x000ba6b23a5d8961,0x00056fe4364e9910,0x00033c6771fe19e3,0x000fd05e1da8c39a,0x00005b4488b39fd9}, {0x00092541a1f22bff,0x000fbb8163e81f43,0x000e5658e920a8a6,0x00039a4fd1b24907,0x00002c4f79da6ec8}}, {{0x000c3d04aa38d1b5,0x000c65d9510e1abb,0x00060dec03b0db35,0x000b32c754ac783e,0x00003272fd83a099}, {0x000494f07a8e1078,0x0006ea8191fa5fb0,0x0004ad5444a89e13,0x00097b2113b7f63c,0x00008a2e909ecb98}}, {{0x0005de3b44a3f84f,0x000327c6c69017d5,0x000232390acb2f34,0x000bf64208816810,0x00002e8a6205c733}, {0x000aab69c2d76521,0x0003dd95c5bca774,0x00081f110fb5307e,0x0008c9905c73c249,0x0000baae31cb3945}}, {{0x000185bcbea62e7d,0x000e1af630591def,0x00021851ce8ac9ea,0x000f5a398a8cfd99,0x0000959c3f20abe2}, {0x000952520e40ae55,0x0002b7a24aa1a4f1,0x00092b2bc320789e,0x00068ad59e692773,0x00008f6c66769186}}, {{0x000b2bbc55d2d8b9,0x000764f6ca56ce1d,0x00087761441d58bb,0x0009ece650b6808f,0x000005e16bb84c34}, {0x0005140f661acacd,0x000ffb2270afed41,0x000402cba3b8784e,0x0002196bc280ac8a,0x000053f7146d9379}}, {{0x0008ee5e5681e833,0x0005c6ac9e4ac03c,0x0006b1a386212610,0x000cbd6503a53f93,0x0000d45e2d4a82fe}, {0x000c43976e8ae983,0x000b8fb4b00e69a5,0x000386c89b53b2ee,0x000ce4c167471272,0x00000ca34a27268b}}, {{0x000d86c783417303,0x00088525e2487f1e,0x0004fbf388ef5beb,0x0003828bc489fdb7,0x00008a92a0ec1a0b}, {0x000ba3f22433ccf6,0x0006429f05a97a77,0x000189afcde8362d,0x00014f1f6a30ea61,0x000093b5505b9ef1}}, {{0x0006bc0cd1797a18,0x000e74b7af2d5026,0x000f9483eea17b47,0x0008c956c4025c3d,0x0000cbb9da0237b1}, {0x000fd9c4d8424cff,0x0000bb1c350691cb,0x0008206a3db7048f,0x0006cdaeaf641f02,0x0000986f3fa15bdf}}, {{0x00043b5224c08dca,0x0003e1b50c912621,0x000a8c84f2bbb09b,0x000ca8216ed709ac,0x00006210d9e52850}, {0x000f67a09cb54d69,0x000fc00919a46d8d,0x00013285791eef6d,0x00028b00f613810f,0x0000acede4888d50}}, {{0x0001b7190b771c33,0x00048a6426be844d,0x000b802ff563b71e,0x000a40fefa2e83bd,0x0000410cbabdb5b4}, {0x0002d2630da84dd0,0x0009ee1cc29a555b,0x000547792d0711ae,0x000b35cf3e8c602f,0x00003d7d5dedc678}}, {{0x0002fa8ced806b84,0x0004297f1478071a,0x000fcdbbf222e613,0x0003b89c16fd5dab,0x00004912ebf521b5}, {0x00036742496c27c5,0x000bcffc26b0ac94,0x000debf2c8ea3176,0x00083266e224ac13,0x000024cc2364372a}}, {{0x000e1d89f6f1b18b,0x000494cce35bd706,0x0008e31fc2552f00,0x000046dc8326c2a8,0x00005468b2da9552}, {0x0003e883ff90f2ba,0x000e8f0a5423ce68,0x00056e32877947bd,0x0004ac30a1b28bed,0x0000ee3525462013}}, {{0x000367d3567962f6,0x000f2188bffb7e98,0x000f130a1379ed61,0x00073413bba348fa,0x0000c1f75e1f04ed}, {0x00066423b4a79fce,0x000c74ef44931895,0x00011eca1f20bc83,0x000dcea36d425d91,0x00005b5c318e09a8}}, {{0x000b25d13221bc57,0x0001fb3eeaf73360,0x0003a95a1707baad,0x00009f67279ed874,0x0000450a876069e8}, {0x000bd53e5d0338fe,0x000e4b883bbc32b6,0x00063ecd01e77f7a,0x000e46b0da12cc10,0x00002697b59a315b}}, {{0x000a5bdda85d5347,0x000f8f980eea2771,0x0000385e753e78c1,0x000b623df1cf8490,0x0000d3b14f739387}, {0x00074b0cb8f2bd25,0x0006327fa993170e,0x000f32bab2d50b48,0x000ab87dbe8c9af6,0x00005e906b113b93}}, {{0x00022fc8fe280d19,0x000522e114ab747f,0x0000b68b0cd8e0de,0x0004b1cab7dbebe1,0x0000dc63a9d3480d}, {0x000bc3b4be1495fb,0x0007e359122d78d4,0x00009cbdc25eb3db,0x00002e8f8ac05b08,0x0000f4187bc837c7}}, {{0x000a0691416a6a5e,0x000863ef881c84ce,0x000038a5d8f860c7,0x00006661311f8a38,0x000078c2ec1dc612}, {0x0002e815ad735813,0x000029604097494d,0x000612cbab4cc9e0,0x00039ecf558aecf3,0x00005beef7ace36c}}, {{0x000c7cfdbcf41b9d,0x0009dea997c01845,0x00002f6d85703662,0x000161bb925afee4,0x00000a1b1af1dd72}, {0x000b37503c41c4b1,0x000af391d0429f47,0x0003b8b0aa023829,0x0000e54f5045c350,0x000023c2688a8c01}}, {{0x000c0cc36ba06eee,0x00045dd2cc0c324e,0x00033e91fface311,0x0002afd364f3bef3,0x0000f8aff7408e83}, {0x000ad042d05841bb,0x000e856a21e21e9b,0x000dd627e42f0e3d,0x000710f3270bcb4a,0x000009a81598322e}}, {{0x00026a10fee104a6,0x0007d703f65d86e3,0x000bc4833ad7788f,0x00093a1e76543047,0x0000cee582b8b9b8}, {0x000a167e8f55a7b8,0x000659e4190d9cd2,0x0000c2e9defbee3c,0x000547b3ee7185d4,0x000044cc9c62380b}}, {{0x0008ecd66926e04d,0x000eb110c1ba323f,0x0006a7f070001e38,0x000826bdbcac12fc,0x000065e1d58dcec0}, {0x0004141be76ca2da,0x000c4892f33ad2cd,0x0007139d27895cf5,0x0004c0f56d230d36,0x000091abd3f7012c}}, {{0x000488387eb36bff,0x0001a14b8fb434fa,0x000b9c95fc5f0710,0x000194a0f0e579ad,0x0000e6ea8cc18888}, {0x0005065edfa9284e,0x00014b8c8d657b9b,0x000e8aafd6c510bd,0x000a06f7b8ebefcb,0x0000db3af9976b1d}}, {{0x000779d6295d4269,0x0006afa3ad7b28ff,0x0008e26040c4f6ac,0x0000e15c44d0548b,0x0000b32a66e1b005}, {0x0003366f0476ce2b,0x0002f602c7b41f94,0x0004f28097554d95,0x000bea0e35aca652,0x0000688122aad4ed}}, {{0x0000c8f508efb637,0x0007fabcefc7e8cd,0x00041ab4f9eb5b5c,0x000b2285621f5fb4,0x00009e6c047276a2}, {0x000792ce37a1f698,0x000a83542b6074a4,0x000c20bd3cbd252c,0x00060bf85f65d5b3,0x0000dea6143cfabc}}, {{0x0001446de6736294,0x000e303c2d2145e2,0x000c868c757f7aa1,0x00067660e99b7f98,0x0000e42f66dcb641}, {0x00084dc910778965,0x000f72c9885b6028,0x0009a5187a0d690c,0x0007eeaeb4da333b,0x0000f789598653c8}}, {{0x000dd4752b16dba7,0x0005c524c1b12192,0x000383693deefc0e,0x000d97d65ea76ee4,0x00009401711a61b8}, {0x000ace9f21a15cb6,0x00038fee9aeba5f9,0x00077016c73d2616,0x000e066ca844b3e6,0x0000c122b07b7eae}}, {{0x000dce715f096905,0x0001ddfc0fc9b782,0x000d89fc6508b9b1,0x000b0f4015ab4b65,0x0000e79dab826d5b}, {0x00021f06c775aa2e,0x000b57c7eca164f0,0x0002fa506df09d8c,0x000ec5ba761367ef,0x0000d4ca4773b81e}}, {{0x000de3610bbb8b54,0x0002c641ada3262e,0x000831ccc0737ce8,0x0006350c94288ae9,0x000087fc1cec065e}, {0x0007ab3b8bb36591,0x000e755e4120b13d,0x000eb0244dea5df3,0x0000a3a9a1857385,0x0000a1b8ea3b7cfe}}, {{0x000711967b0867ce,0x0007bd3645203b83,0x00030f0e38d5e0d0,0x000bae72dccc1ed9,0x0000fbbcec89f20b}, {0x000fcab0263ad100,0x000dfcd18f8a99cf,0x000f10617d8199e6,0x00084864e2773fe9,0x0000079e8e108704}}, {{0x000989f8a3422839,0x000c183012e61169,0x0006a90018097799,0x0007fc5ce966cb8a,0x00003b3afef972ac}, {0x0003a2a2db3d5ba7,0x000219bf4fdce689,0x000396673263dc46,0x0002b61852dfc9e0,0x0000ac70895aaf36}}, {{0x000ce4d5c2f342bb,0x000a052d7aaebb9c,0x00061bcd0bf80907,0x00044ce7f3d3cd21,0x000025b0834b9627}, {0x0008ea56c3a1ddad,0x000a36c92317c5b1,0x0001c4afefe4ec7e,0x000019e787b890ad,0x0000ccd9a92dede8}}, {{0x000dddadb58da1f8,0x000f38cae6ee9ac6,0x0005c4a4322bbc12,0x0000c746f8bced81,0x0000105a92d79648}, {0x000dbf37a859d51f,0x00054041196b0dc3,0x0001067c9e3ec7ce,0x000dd7e9f64b250d,0x000023213222d1f8}}, {{0x000619c76497ee80,0x0006c717370e8b5c,0x000cf68e15d2b0ac,0x00079298204cb64f,0x0000bdec21162bc6}, {0x000ccefa63b10110,0x0007e0de1ac56973,0x0000e0c8bf9e3fa9,0x000cb45efb693e3d,0x000037248e9d2d4f}}, }, {/* digit=36 [{1,2,3,..,}]*([2^252]*G) */ {{0x0002dc91ec34f9e7,0x0004c38106038080,0x0000cb4f3d8772d3,0x000128cf06d66c53,0x0000be5ed0e3475c}, {0x0003c1931e82b100,0x0007c9ff6b4ccb9e,0x000a1b45ec63d285,0x000bcab92118c692,0x0000aec44147285b}}, {{0x0009ae71e29a3efb,0x000f9c93302efc18,0x000aae10ecbe906e,0x0009f820107914ce,0x00007a23f35668e1}, {0x00075c2efd2119d3,0x000eccadc9c8e9d8,0x000a1711303198c6,0x00003835591bf64d,0x0000cf0bbf86d443}}, {{0x0005bb72b7247593,0x000182d4c63aae48,0x0007d6f2c945353e,0x00010952159d07de,0x000089caef37ec5b}, {0x000bb53db65ef147,0x000e6d99de434a8e,0x000f2405f2dc2cb7,0x0008a3116fa3ed83,0x00003429bba31420}}, {{0x000d590b01e6e274,0x000da180b2dcb618,0x000aea4a9047e2cc,0x0003a491b299b504,0x000012c9e1edfa40}, {0x0008a36794075521,0x0006e332b8e388d2,0x00068de1949c5013,0x000b972a1b6fcce6,0x000078851bc85122}}, {{0x0003752fb85fa4ca,0x000d983c8ce9b1e1,0x000f74daed61257c,0x000bbb343da670d2,0x000035aa2405f846}, {0x000235d4421fc835,0x00007363473b5e74,0x0004aa158f6df8ee,0x00022de4d7f52a3c,0x00000d05aabebc6d}}, {{0x000e735a64785f45,0x000b0f29cd078c56,0x000e35067bc56637,0x00027003b2bb803e,0x00000235a102c919}, {0x000b6d8f2c4aa658,0x00010396023b191a,0x000f805bac347583,0x00080f00400ba5f0,0x0000881065bdec0f}}, {{0x000e522cc1b5e838,0x0001060b8bfbc370,0x000b256dfde2d4ad,0x0009972d364df067,0x0000f12502f60138}, {0x000a0dc7783920a0,0x000dc0bc866a503f,0x000064ba6e80014a,0x000ba53f89b744d3,0x00003511dcdcba5d}}, {{0x000d46d95a7b1a29,0x0005ac6341fb197d,0x0004c2ece9c4e7ad,0x000f89b26eca2948,0x0000211e48a6e7f4}, {0x0007f6ec78ef1f42,0x000fe65745861499,0x0003eede82b2c090,0x000017f7286a6e1c,0x00005f92e472f60e}}, {{0x000564631890a36e,0x000f77feea5b805c,0x0003c3030703ef5f,0x000738589f747caf,0x00000e5daec34dd3}, {0x000a4c3c9c9f1554,0x000675393962fe24,0x00020bf297e4bf17,0x000c3af7183de2af,0x0000a1bd7b6395a8}}, {{0x000969946191d3d6,0x000d1b87f257a83b,0x000107588281fc8d,0x000fe8518e2c1354,0x0000372def7fb2ba}, {0x000bb480d8972cae,0x000676167a3fdaf4,0x000310cf43f2dd4b,0x0000a93eace32d84,0x00003bcefb0c4270}}, {{0x000691ed785e73d3,0x0005fea604675fe5,0x000c6514aa5db5ab,0x000664d2e23d41df,0x00005e8048f103c3}, {0x000118f1adaa0f81,0x000574ce1a5a3f8b,0x0006646b828ec3b4,0x00040fd8cacc6e2c,0x0000343d185ebd0e}}, {{0x000f844caaa358cb,0x0003e924182ae5d7,0x000875d9a1a1db7e,0x000ec8264cd42d9c,0x000037b515fb42ee}, {0x000d4097b165fbe5,0x00099206eff34d4d,0x000b7e17efc322ed,0x000a002dee410259,0x00005a481c0d236c}}, {{0x0005312c23fc9759,0x000575d6297b8c88,0x0008edd391571580,0x000e521078868ef7,0x000056b31e093c45}, {0x00075d5ff7b33a68,0x00098c7e673f4702,0x0002f2598c8d5dc3,0x000974c19227b47e,0x0000b37b634cc14a}}, {{0x0007ed68b11888c9,0x000df03e25dcd066,0x00087a24a5e0e8c3,0x000322a4e5d0dcb9,0x0000f40ac3c3e920}, {0x000de9534e0f63a7,0x0001fb6328f95463,0x00064f1b7a128bf9,0x000e34d91ccd7cda,0x0000ef1ec28347bd}}, {{0x000240fa36a27378,0x0005e3621bc1a857,0x000fb689735dc136,0x00019cfa3a6453d4,0x00000f1a43a49293}, {0x000274bf8cb0ba05,0x00063078c5ebfc18,0x00001d0efb0b5376,0x00009cab0d49241e,0x00000d7c67d872ab}}, {{0x00070af3aeac968f,0x0008d4b63266b4e3,0x000ac5664e4f7fee,0x000cbec4acd4c2e3,0x00008910bd3beb38}, {0x000e50cc9c0726e3,0x0009a97b40bf1c3a,0x0005a5a1b1530956,0x0004cd40884b7ffd,0x0000890896b1f831}}, {{0x000515ca5618c937,0x000b07d942d158e1,0x000f767a8e665432,0x000110432181bfb6,0x000053794e8aa604}, {0x000eb7ce8c0dbccf,0x0002698673a309af,0x00046db0031e0261,0x000b276d98e5577d,0x0000c21fb8d8d985}}, {{0x0000116b0843e0bb,0x0007b9b04531c904,0x000d7d83053b1b3a,0x0007e82d1649f085,0x0000b3bcc887b742}, {0x0001100c93dce831,0x000191922a2a7726,0x000149ce87e79da6,0x000c83487a2b02f3,0x000047e1384ee92e}}, {{0x00083d3af077f30f,0x00031658b53a484c,0x0007aec53ea78f84,0x00077ca12076c202,0x000034714e483c81}, {0x0005d15c2376c840,0x00093d1aa78337ef,0x000852a908315b65,0x000bd43a75c484ef,0x0000ba0c58a16086}}, {{0x0008d7a529a6d482,0x000da2f192032968,0x0002e2df99c7f250,0x0001bbf23042fb68,0x0000b7587e7cd812}, {0x0000233e0182a650,0x0007e3e1128a30fc,0x000fb098fb82ecf8,0x0006a77168286193,0x000043e21ae85e9e}}, {{0x00049d666c834ea0,0x000847414287ab5b,0x0009a2a473be43e1,0x000f3cf40fb85921,0x0000e6559e9cc58d}, {0x000fe8e0c6615b48,0x000cd6459d70fe1d,0x000de038614abc8f,0x000c7bfbe0fa8e05,0x0000e63ef6969035}}, {{0x00001b453b31e91a,0x0003a436b4d81164,0x0007afd660cba7ad,0x0004c3f151f9a010,0x0000faca8d0bf0ee}, {0x0005c1d9ee9761ca,0x000b50c0588f75fe,0x00004804c3497a16,0x0000b89ee2bebd03,0x00008fb9a6162c99}}, {{0x00032fe392511143,0x000c9ac73366d14d,0x000a7495c36bf25b,0x00048b99562c66db,0x000024d301b76ad3}, {0x000620cd670407e5,0x000193733a019f46,0x000c324e00ea8d4f,0x0007cd8396d532b0,0x0000b211a0e53c31}}, {{0x0007d205ffe7b376,0x000ab747d2da090d,0x0004fc5193b7f3ef,0x00071e42cb525fb5,0x0000e220933566a9}, {0x00060dfb486d440d,0x00056fe13465ddc1,0x000e4c1517fcfec4,0x0002b4b3da7e4e76,0x00006fa48a2a8d30}}, {{0x0004f265872cd88f,0x000b378b90a1c630,0x000f0bc1c806c1d3,0x000d5b4553e725ca,0x0000f59e604ab9d8}, {0x0000f327a0b85dd7,0x000a23ecc217a455,0x000d62213dec5720,0x0009549b88b74169,0x0000212f245cb365}}, {{0x0004111b5cae787e,0x00073dfd31242076,0x00075aefb13cb7f5,0x0007744dca77da11,0x0000b75466cdfaae}, {0x0006f3bdb6cff322,0x000a41fcda9a74d7,0x00025028b7440f37,0x000f28fbb3ac92b5,0x00000fbf8f7c1975}}, {{0x00092e1df83097f7,0x000be54b08009826,0x000ce2f2f28738f6,0x0001946c703717a2,0x0000913b93cb0814}, {0x00045931fe896366,0x000f978834a60492,0x00014a5a17b98443,0x000f4bb1c6ab0151,0x00000deb3845fba5}}, {{0x00054c601a982e6c,0x00007491cd264caa,0x000bd6b051dd35e1,0x000723d73c315f7c,0x0000ab0077612494}, {0x0009b1f6565e15ae,0x0008ac8fb0260465,0x000a0de37bf30f52,0x0001141c21641ba8,0x00009c7a367da5e5}}, {{0x0009ca552f03ad8b,0x0008524e35c0db84,0x000c3c789c7e8dbe,0x000261f1a2bbaccf,0x0000f733e7e4c26f}, {0x000fbf5b8444823a,0x0007cbf8483b882f,0x000bef640b7224e8,0x0008ccb3023b8b65,0x0000abfec9274d5f}}, {{0x0001510079ea1bd1,0x000cc05d5d26a40e,0x000e68d4f1ad9add,0x00003fcb3f2eab13,0x0000cff1ae2740f8}, {0x000b749d4cee1172,0x000b2036d909e0e7,0x0004d4c388e9f275,0x0000fcae34e31d8f,0x00002b37f69f7513}}, {{0x000f1fdb40146044,0x00094941507883e0,0x000792efea8ce991,0x00015b42375b7541,0x0000f59bf5cd7d45}, {0x000324f923a277d8,0x000ce50f3406ac4f,0x00039bc51d9bc9b7,0x00008f46fa87d18a,0x00002588530dccc1}}, {{0x0003c9f82e4c6346,0x0003da4464f85ced,0x0001dca258efb831,0x00012b8706381b7a,0x0000cd15a3cba2a4}, {0x000a8fdbfcd8fb51,0x000f5e54cd229347,0x000d8932f31db2ee,0x0001afb4aeb11ef8,0x00001e7c1ed44441}}, {{0x000050cdc9a151e9,0x0007abb0a8592653,0x0005691e79edbfc0,0x00019a026c81c7fd,0x0000c1b2342ff390}, {0x0001c8b7f8474b9c,0x00064176181964a8,0x000e0375a90657c0,0x00047c790b333155,0x0000676c62776ebc}}, {{0x0003247b7d6dee80,0x0007796593135162,0x000ab35ed0948d92,0x00040899700161e9,0x00006cc32b48ddde}, {0x000d664061ef338c,0x00020202e9ed6f2f,0x0009ba99b1606fa0,0x000f6895388bc192,0x00004428c5ede81d}}, {{0x00028aef91b0b2ab,0x0003403dfd3fce20,0x000ffe8edce870a2,0x000bffb6ec2c870a,0x0000205fb46d84d0}, {0x000ffe744cefa48d,0x0007d19876d7bf5d,0x000b72863b6fc37a,0x00074eeecfa84c08,0x00007205ff5f5763}}, {{0x0000d328887de41e,0x000ba69ea5348033,0x00056ea175de0df0,0x000a7733f427533c,0x0000b1f606a252b1}, {0x0004396e30ea15cb,0x0001114941255047,0x0006bb38f575816a,0x0000f70e1ce55bfe,0x0000901a94946ae3}}, {{0x0000f08d8fc35489,0x0000473bfd08e5af,0x000fe655a5010b5d,0x0009fd093d288053,0x00009f2630bac130}, {0x0007bafb4e3b76fc,0x000bf840784bd867,0x0000092ce14e51dd,0x00020e726c750cbf,0x000083d306cb5283}}, {{0x000671577d4715c5,0x00091b703235c445,0x00069e986d30019f,0x000c27d07ccb2ed6,0x00007c824b046dbf}, {0x000532fd8f92a230,0x00049bb98fd2f0eb,0x000e6199a4a557fd,0x0001eda57acea7c1,0x0000c6638208b94b}}, {{0x000be8ff83a92661,0x0006f101bd459b42,0x000bd9cebc7741c9,0x00074485770c1107,0x0000f50250a9b2e0}, {0x000eec81477b6547,0x000da5efe59af762,0x00046a897c65b900,0x000d7c18c9614895,0x0000e8025b4330b4}}, {{0x00065ef12045cf9f,0x000eaccce8bdae40,0x000cf65256fcb2ca,0x0003112fa0ba4ef2,0x0000683125ebb72c}, {0x000a4eae312410e0,0x00076cd8e830a01d,0x000fb3f0767e2867,0x0009a5abd9575298,0x00005f11e11eef64}}, {{0x000faef9d3472c26,0x0007677d1345ba47,0x00015afee3adff69,0x000461e761fa04dd,0x00004f1f61b19e69}, {0x0001fab9bfb9093f,0x000eb1133dfefa69,0x000cc710d3df8ae8,0x000e78dd5f896758,0x0000bb88d5106c7f}}, {{0x0001b4ce88c50d10,0x0007a8771c4f8e01,0x000278ee47532e80,0x00072a64c78a48e2,0x0000b283e8338450}, {0x000f29149e692749,0x00078868b21c98a6,0x000a8908eb96e966,0x00029ca8f0adc2b1,0x00000afcff7afeb8}}, {{0x000a383210b08568,0x00025ef048899915,0x00064d509a5a8060,0x000f6f000e9af97c,0x00001382d0c38996}, {0x000ba5381927e27e,0x00016af50182490e,0x000ad62ce46c63b3,0x000735984c5fd9d3,0x00004fa1871d8ae8}}, {{0x000d0bcd7466b255,0x000a8b235c654ec9,0x0003c168884ddbe1,0x0007470e2645ee16,0x000070bd00e50eba}, {0x000b629128bfa0f9,0x000cdc1d3b68fa51,0x0006778b192fce1b,0x0002baae7361dcb6,0x0000c7d249de561d}}, {{0x00028bf0bbc6229b,0x000e2fd91497a40b,0x00083df051c83c05,0x000c9caf9f5154f0,0x0000ac38b3d9ee66}, {0x000b7e3ec0dfcfd2,0x000e6b0a8416f71d,0x00012aa66f2ecda8,0x00027232fddd8678,0x0000896ef106e6f4}}, {{0x000186a0fe9a745f,0x000c59ca70dbff27,0x0001cac4908249fc,0x000f568425a2e644,0x00004a0885bdce5f}, {0x000b7317d7ead588,0x00059898d1046e2c,0x0002c9a89f96cf7d,0x0005bc2fe67c9d4f,0x00009895a509c7bf}}, {{0x000b8e5573cecfa3,0x000ea15f03e6dc7c,0x00008442066497ea,0x0002b03bc0de693f,0x000023b9b36dcd53}, {0x000390a0115a3c12,0x000b0d65ca0ecfed,0x000530c789414c40,0x0008f2441406bd2f,0x00009369a44a3343}}, {{0x00084f5903fa2711,0x0002a9da921e9968,0x000b01e54e6da0fd,0x00014e96f2f2695d,0x0000ee3e9bd78762}, {0x000181ce27a94979,0x0003fe215e04a26e,0x0002cabca36d254e,0x000613b2f32a6c25,0x0000948148810b57}}, {{0x000fe6940d9cae17,0x000fa1a10f094c4d,0x00091b64b0586957,0x00053b5a287b5734,0x00007862d5dafd4a}, {0x000856e503491266,0x000111c5268fbf94,0x000b650a62be30bd,0x0009fcb0393f19cb,0x000039531fed78cf}}, {{0x0006a11b29353593,0x00067f8c126e0255,0x00060167fda38aa9,0x0001cd17dbe6c209,0x00007bbabb680190}, {0x00079e02c9477784,0x00053a1a1dc6b6e9,0x0009faf0cd69a517,0x0005f083ed50959d,0x0000dd9c0965d5fa}}, {{0x000304d64f16ea85,0x00062e718623a0c4,0x00067f03e8b1cac1,0x000c00bb5765467c,0x000059cf5ae1bd88}, {0x00077bb0e2af19ae,0x0000c1228c920748,0x0006e89201f717ec,0x00080390bcb80032,0x0000c6e2c5d2f312}}, {{0x000ea7d3fca4752b,0x00087211f62a426a,0x000e7b6b5f12c094,0x00027c74beecd87b,0x000077eaf4ce6d7a}, {0x0002781fda78fd37,0x000fb64eeabe154c,0x000fe2bc4848a83a,0x000c2a11287ef04f,0x0000b6d88c726b6f}}, {{0x000b947ce417d99b,0x0002db916cc4805f,0x0002733234b93dcc,0x00086dc2e65bb321,0x0000cc1bade1ea98}, {0x00030114bc5ee855,0x0004718ee1e40e22,0x000bcf1f1a561be7,0x000489262fd2d4a6,0x00000e6a5a4e5231}}, {{0x000001fa00b500bb,0x000bad7dcdf5ca96,0x000446a855c098cf,0x000c61f64e2d2e8c,0x0000ae9bcf2471f3}, {0x00026838435a2c5b,0x000b9bad46434ec2,0x000ccf4e38ceaed6,0x00021e39f8fb47cc,0x0000d4f3fa4cce3b}}, {{0x000b110a3db32927,0x000a4536c66ad79f,0x00049e6a9e28a37d,0x0008e2b79ce87b8e,0x00000ccfe8e6dcec}, {0x000e4e03ba464b2d,0x000ddca9a3982193,0x0002c12ab0f39d60,0x0000f6ad7932aff8,0x00008ff50ee61e7e}}, {{0x0001058fa28a7e00,0x00050bf5ec74ea96,0x000229666c726cf2,0x000799e74d55c8db,0x0000bd9abbfa57f5}, {0x000ef074dfc47b3a,0x00026c52f91d7479,0x000a8bde2d9c65fc,0x00027fee0283fe36,0x000032a8b5f1d4b7}}, {{0x0007c6112e832330,0x0002dcc9bf286a67,0x000780f610fbb351,0x00089c562e8ea50d,0x0000db8b22b1dc4e}, {0x000d1fb89be01445,0x00067a57113b0a6f,0x00009c91c8c77d24,0x00024bf639075dff,0x0000b47b17fa0608}}, {{0x000a2b016287b52d,0x000000cd8eb058ae,0x000d58573a134352,0x0008ad9148b4d0c5,0x0000d2b6170f91c6}, {0x00039291da3b3b75,0x0008b8c4ac10a61b,0x00017d5835f946d7,0x000e5df105d4a572,0x0000061da3d75e6d}}, {{0x000940dec1b49919,0x0000a6f485ae3113,0x0001a2ee0f12195e,0x00096e17507fb273,0x00005057a8efe9e1}, {0x000c9112e1301367,0x0005c3c60d15a3c2,0x00000ee2b97dfbb3,0x0008b85af3c581b3,0x00007f25d9164bac}}, {{0x0004f986d840cd64,0x0000a634288cdb1c,0x000c8a161471d62c,0x000ae24ec2f85ece,0x00001f37cbd3a6f4}, {0x000a20f4b7099851,0x000bdfa8985b6793,0x0008e64467a7bd33,0x0007c11c6a3fbd93,0x000090426193a8d4}}, {{0x0008667cc36975fb,0x0007ed5f1dfb1684,0x0003baa9402acf16,0x00066fb2d41ad461,0x000056fbb934f684}, {0x0000d0de9e405698,0x000eb5489fefce61,0x000f18b977b99c65,0x000eda8c88ad1b3d,0x00001b7d9bedd0e9}}, {{0x00018c0c716cc0a1,0x000075691c49d852,0x000356ac6f4b5ff9,0x000a7a94fd666bce,0x00007c728955b327}, {0x0005085da6be7de9,0x000da301d34ef93d,0x000f448e8ff71530,0x000ff9bcd96442d8,0x0000283d331bed18}}, {{0x000dd992a8498705,0x000af15763354d33,0x0009be0e5a716964,0x000632af5e3a9b17,0x0000b9d6b1bd3b13}, {0x000d7d4a52f313bc,0x000fa37a46603b8b,0x0003e218fc9dd959,0x000a3b700359620b,0x0000e1481a487b28}}, {{0x000b43a43228d831,0x00003ad63f99ab41,0x000a5122924ae1c3,0x0002b47e525f1a46,0x00004af860fdd26d}, {0x000ef613f714aa18,0x000d6b78795ed6ba,0x000a9d694f51865a,0x00052753e21fcee6,0x00002ceb1de0a37b}}, } }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPRECOMP7_P256_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ed25519/000077500000000000000000000000001470420105600274645ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ed25519/ifma_arith_ed25519.h000066400000000000000000000132301470420105600330150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ED25519_H #define IFMA_ED25519_H #include #include #if (_MBX>=_MBX_K1) /* homogeneous: (X:Y:Z) satisfying x=X/Z, y=Y/Z */ typedef struct ge52_homo_mb_t { fe52_mb X; fe52_mb Y; fe52_mb Z; } ge52_homo_mb; /* extended homogeneous: (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT */ typedef struct ge52_mb_t { fe52_mb X; fe52_mb Y; fe52_mb T; fe52_mb Z; } ge52_ext_mb; /* copmpleted: (X:Y:Z:T) satisfying x=X/Z, y=Y/T */ typedef struct ge52_p1p1_mb_t { fe52_mb X; fe52_mb Y; fe52_mb T; fe52_mb Z; } ge52_p1p1_mb; /* scalar precomputed group element: (y-x:y+x:2*t*d), t=x*y, ed25519 parameter d = -(121665/121666)*/ typedef struct ge52_precomp_t { fe52 ysubx; fe52 yaddx; fe52 t2d; } ge52_precomp; /* mb precomputed group element: (y-x:y+x:2*t*d), t=x*y, ed25519 parameter d = -(121665/121666)*/ typedef struct ge52_precomp_mb_t { fe52_mb ysubx; fe52_mb yaddx; fe52_mb t2d; } ge52_precomp_mb; /* projective falvor of the ge52_precomp_mb */ typedef struct ge52_cached_mb_t { fe52_mb YsubX; fe52_mb YaddX; fe52_mb T2d; fe52_mb Z; } ge52_cached_mb; /* bitsize of compression point */ #define GE25519_COMP_BITSIZE (P25519_BITSIZE+1) /* // conversion */ /* ext => homo */ __MBX_INLINE void ge52_ext_to_homo_mb(ge52_homo_mb*r, const ge52_ext_mb* p) { fe52_copy_mb(r->X, p->X); fe52_copy_mb(r->Y, p->Y); fe52_copy_mb(r->Z, p->Z); } /* p1p1 => homo */ __MBX_INLINE void ge52_p1p1_to_homo_mb(ge52_homo_mb *r, const ge52_p1p1_mb *p) { fe52_mul(r->X, p->X, p->T); fe52_mul(r->Y, p->Y, p->Z); fe52_mul(r->Z, p->Z, p->T); } /* p1p1 => ext */ __MBX_INLINE void ge52_p1p1_to_ext_mb(ge52_ext_mb *r, const ge52_p1p1_mb *p) { fe52_mul(r->X, p->X, p->T); fe52_mul(r->Y, p->Y, p->Z); fe52_mul(r->T, p->X, p->Y); fe52_mul(r->Z, p->Z, p->T); } /* set GE to neutral */ __MBX_INLINE void neutral_ge52_homo_mb(ge52_homo_mb* ge) { fe52_0_mb(ge->X); fe52_1_mb(ge->Y); fe52_1_mb(ge->Z); } __MBX_INLINE void neutral_ge52_ext_mb(ge52_ext_mb* ge) { fe52_0_mb(ge->X); fe52_1_mb(ge->Y); fe52_0_mb(ge->T); fe52_1_mb(ge->Z); } __MBX_INLINE void neutral_ge52_precomp_mb(ge52_precomp_mb *ge) { fe52_1_mb(ge->ysubx); fe52_1_mb(ge->yaddx); fe52_0_mb(ge->t2d); } __MBX_INLINE void neutral_ge52_cached_mb(ge52_cached_mb* ge) { fe52_1_mb(ge->YsubX); fe52_1_mb(ge->YaddX); fe52_0_mb(ge->T2d); fe52_1_mb(ge->Z); } /* move GE under mask (conditionally): r = k? a : b */ __MBX_INLINE void ge52_cmov1_precomp_mb(ge52_precomp_mb* r, const ge52_precomp_mb* b, __mb_mask k, const ge52_precomp* a) { fe52_cmov1_mb(r->ysubx, b->ysubx, k, a->ysubx); fe52_cmov1_mb(r->yaddx, b->yaddx, k, a->yaddx); fe52_cmov1_mb(r->t2d, b->t2d, k, a->t2d); } __MBX_INLINE void cmov_ge52_precomp_mb(ge52_precomp_mb* r, const ge52_precomp_mb* b, __mb_mask k, const ge52_precomp_mb* a) { fe52_cmov_mb(r->ysubx, b->ysubx, k, a->ysubx); fe52_cmov_mb(r->yaddx, b->yaddx, k, a->yaddx); fe52_cmov_mb(r->t2d, b->t2d, k, a->t2d); } __MBX_INLINE void cmov_ge52_cached_mb(ge52_cached_mb* r, const ge52_cached_mb* b, __mb_mask k, const ge52_cached_mb* a) { fe52_cmov_mb(r->YsubX, b->YsubX, k, a->YsubX); fe52_cmov_mb(r->YaddX, b->YaddX, k, a->YaddX); fe52_cmov_mb(r->T2d, b->T2d, k, a->T2d); fe52_cmov_mb(r->Z, b->Z, k, a->Z); } /* private functions */ void ifma_ed25519_mul_basepoint(ge52_ext_mb* r, const U64 scalar[]); void ifma_ed25519_mul_point(ge52_ext_mb* r, const ge52_ext_mb* p, const U64 scalar[]); void ifma_ed25519_prod_point(ge52_ext_mb* r, const ge52_ext_mb* p, const U64 scalarP[], const U64 scalarG[]); void ge52_ext_compress(fe52_mb fe, const ge52_ext_mb* p); __mb_mask ge52_ext_decompress(ge52_ext_mb* p, const fe52_mb fe); mbx_status MB_FUNC_NAME(internal_avx512_ed25519_public_key_)(ed25519_public_key* pa_public_key[8], const ed25519_private_key* const pa_private_key[8]); mbx_status MB_FUNC_NAME(internal_avx512_ed25519_sign_)(ed25519_sign_component* pa_sign_r[8], ed25519_sign_component* pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_private_key* const pa_private_key[8], const ed25519_public_key* const pa_public_key[8]); mbx_status MB_FUNC_NAME(internal_avx512_ed25519_verify_)(const ed25519_sign_component* const pa_sign_r[8], const ed25519_sign_component* const pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_public_key* const pa_public_key[8]); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ED25519_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ed25519/ifma_arith_n25519.h000066400000000000000000000025151470420105600326660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ARITH_N25519_H #define IFMA_ARITH_N25519_H #include #include #if (_MBX>=_MBX_K1) /* bitsize of base point order */ #define N25519_BITSIZE (253) #define NE_LEN52 NUMBER_OF_DIGITS(N25519_BITSIZE, DIGIT_SIZE) #define NE_LEN64 NUMBER_OF_DIGITS(N25519_BITSIZE, 64) void ifma52_ed25519n_madd(U64 r[NE_LEN52], const U64 a[NE_LEN52], const U64 b[NE_LEN52], const U64 c[NE_LEN52]); void ifma52_ed25519n_reduce(U64 r[NE_LEN52], const U64 x[NE_LEN52 * 2]); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ARITH_N25519_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ed25519/ifma_arith_p25519.h000066400000000000000000000113771470420105600326760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ARITH_P25519_H #define IFMA_ARITH_P25519_H #include #include #if (_MBX>=_MBX_K1) /* // prime25519 = 2^255-19 // in the radix 2^52 // int64u prime25519[5] = {PRIME25519_LO, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_HI} */ #define PRIME25519_LO 0x000FFFFFFFFFFFED #define PRIME25519_MID 0x000FFFFFFFFFFFFF #define PRIME25519_HI 0x00007FFFFFFFFFFF /* underlying prime bitsize */ #define P25519_BITSIZE (255) /* lengths of FF elements */ #define FE_LEN52 NUMBER_OF_DIGITS(P25519_BITSIZE, DIGIT_SIZE) #define FE_LEN64 NUMBER_OF_DIGITS(P25519_BITSIZE, 64) /* scalar field element (FE)*/ typedef int64u fe64[FE_LEN64]; typedef int64u fe52[FE_LEN52]; /* mb field element */ typedef U64 fe64_mb[FE_LEN64]; typedef U64 fe52_mb[FE_LEN52]; /* set FE to zero */ __MBX_INLINE void fe52_0_mb(fe52_mb fe) { fe[0] = fe[1] = fe[2] = fe[3] = fe[4] = get_zero64(); } /* set FE to 1 */ __MBX_INLINE void fe52_1_mb(fe52_mb fe) { fe[0] = set1(1LL); fe[1] = fe[2] = fe[3] = fe[4] = get_zero64(); } /* copy FE */ __MBX_INLINE void fe52_copy_mb(fe52_mb r, const fe52_mb a) { r[0] = a[0]; r[1] = a[1]; r[2] = a[2]; r[3] = a[3]; r[4] = a[4]; } /* convert fe52_mb => fe64_mb */ __MBX_INLINE void fe52_to_fe64_mb(fe64_mb r, const fe52_mb a) { r[0] = xor64(slli64(a[1],52), a[0]); r[1] = xor64(slli64(a[2],40), srli64(a[1],12)); r[2] = xor64(slli64(a[3],28), srli64(a[2],24)); r[3] = xor64(slli64(a[4],16), srli64(a[3],36)); } /* check if FE is zero */ __MBX_INLINE __mb_mask fe52_mb_is_zero(const fe52_mb a) { U64 t = or64(or64(a[0], a[1]), or64(or64(a[2], a[3]), a[4])); return cmpeq64_mask(t, get_zero64()); } /* check if a==b */ __MBX_INLINE __mb_mask fe52_mb_is_equ(const fe52_mb a, const fe52_mb b) { __ALIGN64 fe52_mb t; t[0] = xor64(a[0], b[0]); t[1] = xor64(a[1], b[1]); t[2] = xor64(a[2], b[2]); t[3] = xor64(a[3], b[3]); t[4] = xor64(a[4], b[4]); return fe52_mb_is_zero(t); } /* move FE under mask (conditionally): r = k? a : b */ __MBX_INLINE void fe52_cmov1_mb(fe52_mb r, const fe52_mb b, __mb_mask k, const fe52 a) { r[0] = mask_mov64(b[0], k, set1(a[0])); r[1] = mask_mov64(b[1], k, set1(a[1])); r[2] = mask_mov64(b[2], k, set1(a[2])); r[3] = mask_mov64(b[3], k, set1(a[3])); r[4] = mask_mov64(b[4], k, set1(a[4])); } OPTIMIZE_OFF_VS19 __MBX_INLINE void fe52_cmov_mb(fe52_mb r, const fe52_mb b, __mb_mask k, const fe52_mb a) { r[0] = mask_mov64(b[0], k, a[0]); r[1] = mask_mov64(b[1], k, a[1]); r[2] = mask_mov64(b[2], k, a[2]); r[3] = mask_mov64(b[3], k, a[3]); r[4] = mask_mov64(b[4], k, a[4]); } /* swap FE under mask (conditionally): r = k? a : b */ __MBX_INLINE void cswap_U64(U64* x, __mb_mask k, U64* y) { *x = _mm512_mask_xor_epi64(*x, k, *x, *y); *y = _mm512_mask_xor_epi64(*y, k, *y, *x); *x = _mm512_mask_xor_epi64(*x, k, *x, *y); } __MBX_INLINE void fe52_cswap_mb(fe52_mb a, __mb_mask k, fe52_mb b) { cswap_U64(&a[0], k, &b[0]); cswap_U64(&a[1], k, &b[1]); cswap_U64(&a[2], k, &b[2]); cswap_U64(&a[3], k, &b[3]); cswap_U64(&a[4], k, &b[4]); } void fe52_mb_add_mod25519(fe52_mb vr, const fe52_mb va, const fe52_mb vb); void fe52_mb_sub_mod25519(fe52_mb vr, const fe52_mb va, const fe52_mb vb); void fe52_mb_neg_mod25519(fe52_mb vr, const fe52_mb va); void fe52_mb_mul_mod25519(fe52_mb vr, const fe52_mb va, const fe52_mb vb); void fe52_mb_sqr_mod25519(fe52_mb vr, const fe52_mb va); void fe52_mb_inv_mod25519(fe52_mb vr, const fe52_mb va); void fe52_pow_2_252m3_mod25519(fe52_mb vr, const fe52_mb va); void fe52mb8_red_p25519(fe52_mb r, const fe52_mb a); #define fe52_add fe52_mb_add_mod25519 #define fe52_sub fe52_mb_sub_mod25519 #define fe52_neg fe52_mb_neg_mod25519 #define fe52_mul fe52_mb_mul_mod25519 #define fe52_sqr fe52_mb_sqr_mod25519 #define fe52_inv fe52_mb_inv_mod25519 #define fe52_p2n fe52_mb_sqr_mod25519_times #define fe52_p2_252m3 fe52_pow_2_252m3_mod25519 #define fe52_red fe52mb8_red_p25519 #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ARITH_P25519_H */ ifma_ed25519_precomp4.h000066400000000000000000002313371470420105600333720ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ed25519/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 IFMA_ED25519_PRECOMP_H #define IFMA_ED25519_PRECOMP_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (4) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static ge52_precomp ifma_ed25519_bp_precomp[][BP_N_ENTRY] = { { /* slot=0 [{1,2,3,..,8} * 16^(2*0)] * G) */ {{0x00003905d740913e,0x00005d140beb39d1,0x00088f8a09fd399f,0x0001267a5c184346,0x000044fd2f9298f8}, {0x000c93c6f58c3b85,0x000c6fb8c0e192fb,0x00043d42c2cf932d,0x000ba65270b48986,0x000007cf9d3a33d4}, {0x00091205877aaa68,0x00023ccaac49eabc,0x000d43598c26d9e8,0x00065a85a1b7dcbd,0x00006f117b689f0c}}, {{0x0009a56042b4d5a8,0x0000c4e60acf68a9,0x00016e37aa8f2b81,0x0002555e09e236bb,0x00006bb595a669c9}, {0x0004e7fc933c71d7,0x000967a0ff5b5922,0x0001d607029f469d,0x0002e2e5aa69a65e,0x0000590c063fa87d}, {0x000aa8b3a59b7a5f,0x000dd5d9acf7843f,0x000b3d6a3136c16b,0x0000b73500fa0840,0x0000701af5b13ea5}}, {{0x00011fe8a4fcd265,0x000fde5c1ba7d566,0x00014bd6bd3bd353,0x000da628131f31a2,0x00002ab91587555b}, {0x0005b0a84cee9730,0x00030e8864b8aaf2,0x000f016732025a84,0x000f8f4c11b50029,0x00007a164e1b9a80}, {0x000e933f0dd0d889,0x000221c35da6214a,0x000cf2db4c589423,0x000b4c6d170e5458,0x00005a2826af12b9}}, {{0x000e050a056818bf,0x000715660faa995f,0x0006a05073327e89,0x000a49ac3e8e3cd0,0x000027933f4c7445}, {0x000351b98efc099f,0x000f47dfd2538287,0x000b0a92656765c6,0x0008727ca348d3df,0x0000680e910321e5}, {0x0003fbe9c476ff09,0x000457b5cc1725a1,0x00002b44946e9e39,0x0003e2b5ddbdcf91,0x00007f9d0cbf6355}}, {{0x000182c3a447d6ba,0x000d14b2729b77f9,0x000864a087d50014,0x00055f3e33cf11cb,0x0000154a7e73eb1b}, {0x0002bc4408a5bb33,0x000c3c75eed02a21,0x000abfec448d5048,0x00006ebdd1beb0c5,0x00002945ccf146e2}, {0x000bdbf1812a8285,0x00007d0bdd1fcbcb,0x000bbda72d270e08,0x000b69ab41b670b1,0x000043aabe696b3b}}, {{0x000806b67b7d8ca4,0x0008427d22739499,0x00004553b9575be2,0x0007884bb085ce72,0x000038b64c41ae41}, {0x000ceeeb77157131,0x0008900c8af883a0,0x000a59a7369b2715,0x00038bd8065b668d,0x000051e57bb6a2cc}, {0x000c326702ea4b71,0x0000341a1bb0185a,0x00083bc144be70e0,0x00061e353e4a24b0,0x000010b8e91a9f0d}}, {{0x000f2c9aaa3221b1,0x000533bba23a7ba6,0x0002192c3a6ca021,0x00017e09dea764f9,0x00001d6edd5d2e53}, {0x000a5cd0944ea3bf,0x0003ab39dc0d26b1,0x0008542e49747035,0x000927e71b252822,0x0000461bea69283c}, {0x00036dc801b8b3a2,0x00047053ea49af18,0x000877adf3b3035f,0x00090a7529c41ba5,0x00007a9fbb1c6a0f}}, {{0x00075dedf39234d9,0x00080e1b558f9e2a,0x000e3c23fb963d76,0x00001c32c2741ac6,0x00003a9024a1320e}, {0x0007596604dd3e8f,0x00077e288702c59b,0x000ed9c3236cb303,0x000e52fb1339c665,0x00000915e76061bc}, {0x0001f5d9c9a2911a,0x000788bcca7d7e7c,0x000eb62a32b8a371,0x0004e95636412190,0x000026907c5c2ecc}}, }, { /* slot=1 [{1,2,3,..,8} * 16^(2*1)] * G) */ {{0x000b635449aa515e,0x0009f0bc6823aed5,0x000b42d1c4a865c4,0x00015b9850c1fe95,0x000030d76d6f03d3}, {0x000cdd0e632f9c1d,0x00096768931152ec,0x0008637a5851d0b6,0x000ef3952dfb76ba,0x00006dd37d49a00e}, {0x000444172106e4c7,0x00080928d7f696c4,0x00094d3f26fb53d6,0x0004bb0b4739ea46,0x000010c697112e86}}, {{0x0003c4277dbe5fde,0x000ad19ad7ea2649,0x0006304590265d4f,0x000fe090e00dfc84,0x000025e61cabed66}, {0x00062aa08358c805,0x000e37a2042470ca,0x000b11eddc6a3d4a,0x00006ef7464d3a63,0x000003bf9baf5508}, {0x0003e128cc586604,0x000ecb459747e3f1,0x000c1268f56f5873,0x000e22ca0b63dedc,0x0000566d78634586}}, {{0x0007a49f9cc10834,0x000d5a89bc451163,0x000f7fd2dbbc8e56,0x00035d91cb5ec0f7,0x000033975bca5ecc}, {0x00054285c65a2fd0,0x0002af31667c3a10,0x00031aee586c6411,0x000b22a680ae2407,0x000014fba5f34793}, {0x000746166985f7d4,0x00084c9c800573cd,0x000b61131e593e5e,0x000526c2fc3f2b67,0x000014829cea83fc}}, {{0x00037b8497dd95c2,0x00030aa4eb5a7ff4,0x000c85e88b6c744e,0x00081739e0c5d613,0x00002fd9c71e5f75}, {0x00070b2f4e71ecb8,0x000b940a477e321e,0x000e1d4f80e656dd,0x0007b7ebf6556cec,0x000005fc3bc4535d}, {0x0008b3ae52afdedd,0x0008ced3b30cf24b,0x0009be8195349563,0x0001f0433a4bc83a,0x0000373767475c65}}, {{0x000a99fd40d1add9,0x0006f96f4d0272fb,0x0005f03baeb30716,0x000f9994363f0521,0x00001fbea56c3b18}, {0x000095cb14246590,0x0004016c15535634,0x000910bc60ef1214,0x0007c8c9e38140c8,0x00006bf590573090}, {0x000778f1e1415b8a,0x000f7bac3a77e0fa,0x000aa29a5006409f,0x0005a566f52d7b89,0x000002521cf67a63}}, {{0x000fee0b0a9d5294,0x0005c0fdf5a66513,0x000fe107ce8f98e7,0x0002cedd4618688b,0x00003fa00a7e7138}, {0x00046720772f5ee4,0x000b196079aceb11,0x0000ac824ae8f894,0x0006cc44af8224d0,0x0000001753d9f7cd}, {0x0009232d963ddb34,0x000dab49738583c6,0x000091f2851dde87,0x000edb6aad7d1f9a,0x000012b5fe2fa048}}, {{0x0000fbc496fce34d,0x0006badf35bed71f,0x000f28c56173b982,0x000206fd2047261f,0x0000749b76f96fb1}, {0x000b7c26ad6f1e92,0x00023504b8913df2,0x00051c8bc34b66d3,0x000c7b88c409dc07,0x00006f7e93c20796}, {0x000af604aea6ae05,0x000f1bee49c991f5,0x000eff6b66c12351,0x000215161a808b5e,0x00000fcec10f01e0}}, {{0x000d58a649fe1e44,0x000a231ad777e644,0x00087fd0d221fcae,0x00011f302441c5a8,0x00004901aa7183c5}, {0x0002d29dc4244e45,0x0007493d8de0a3df,0x00020c214d2b020e,0x000b90a6cc8067e8,0x0000413779166fea}, {0x0001b7548c1af8f0,0x0007c246299b408b,0x000e06d939ce0f7a,0x0001213f760b0f91,0x000041bb887b726d}}, }, { /* slot=2 [{1,2,3,..,8} * 16^(2*2)] * G) */ {{0x00087d44744346be,0x000d415b52b2540e,0x00013b603e1d48da,0x000bdf77c3a8a18a,0x00004eb728c12fcd}, {0x00034c597c6691ae,0x0003d0a85b4c87e2,0x00054afae764889d,0x0009e1ddae2c90c3,0x00000a871e070c6a}, {0x0001b5994bbc8989,0x0003a5bdd4260330,0x0009d59e3c736bae,0x000d4640d61ade21,0x00003ee7300f2685}}, {{0x000255e49e7dd6b7,0x0005c610b1eacf5d,0x0002e187ca801611,0x00025c23c99975d9,0x0000138157629791}, {0x000a7947841e7518,0x00059639c46d743f,0x0003052b74e5c6fa,0x0009030a1065e1de,0x00007d47c6a2cfb8}, {0x000ad0148ef0d6e0,0x0009a91546f3c3fd,0x0006bb81579d3e74,0x000ec8071ec62102,0x0000148cf58d34c9}}, {{0x000492f67934f027,0x000bef6840aa946a,0x0009611854469984,0x000bbd45ca1bc2a8,0x00003ff2fa1ebd5d}, {0x00072f7d9ae4756d,0x000bb88f3487fe25,0x000960a88d56c345,0x000a1b99fd10b6d6,0x0000278febad4eae}, {0x000a681f8c933966,0x0009c20290c98b1a,0x00019d3c528c2194,0x000677b391152912,0x00004104dd02fe9c}}, {{0x0002bf5e1124422a,0x0003398a33ab572b,0x000a52b666a1fa0c,0x00053d594cb6101f,0x00002c863b00afaf}, {0x00014e06db096ab8,0x000c90ce44f35812,0x00009e2af521a8b6,0x000a4816524c12a4,0x00000165b5a48efc}, {0x0000a474a0846a76,0x00084cd2f7cc0f19,0x0008aa2b8f12eff9,0x000c8b8695e29065,0x0000591b67d9bffe}}, {{0x000f0d1c80b49bfa,0x0005eabf3ec8a312,0x000ef01c88597951,0x0007bcb727033c09,0x00003de02ec7ca8f}, {0x0009b3719f18b55d,0x000faa18c641e99b,0x00029f05ede465e5,0x000128b61081136c,0x0000489b4f867030}, {0x0002102d3aeb92ef,0x000b46116a861d23,0x00090baa24e16253,0x000bebf3d7eabe71,0x000049f5fbba496c}}, {{0x00049a108a5bcfd4,0x00070bc6473eb309,0x00007c0d1cdc40dd,0x0006e7492c294c13,0x00005604a86dcbfa}, {0x000d628c1e9c572e,0x000acc5884741155,0x00015763eb8a4d86,0x000515b91a352f65,0x000006a1a6c28867}, {0x0008d1d47c1764b6,0x00040e0418b51728,0x0008acf6d1725411,0x00042c69f031a601,0x000020989e89fe27}}, {{0x000777fd3a2dcc7f,0x0002ca54fd892499,0x000207e3a032857c,0x0007e29a279d864d,0x00000403ed1d0ca6}, {0x0004278b85eaec2e,0x000077acb2bdf167,0x0001cbf45a5621dc,0x00095d3640a4c166,0x0000730b9950f705}, {0x000b2d35874ec552,0x000cf98246f8dc94,0x0006c035cec5e6c8,0x0003dccf7cb46fa1,0x00005bd745430830}}, {{0x000ad19528b24cc2,0x000656335c1817f9,0x000fc072367f6b54,0x000ad8366b8b66e4,0x0000133a78007380}, {0x0004932115e7792a,0x000a2bdcdddc985c,0x000da3d762c64c89,0x000f82c9d1e3da8a,0x00005bb7db123067}, {0x0001f467c6ca62be,0x000d6211952ee096,0x000bd5477004ec21,0x000e0d2182360779,0x0000740dca6d58f0}}, }, { /* slot=3 [{1,2,3,..,8} * 16^(2*3)] * G) */ {{0x0008ee0752cfce4e,0x000f306ec08b7df4,0x00095459c4c3fffa,0x000a38d05710b2ab,0x0000161d25fa963e}, {0x000a8c570478433c,0x0000ec281439d231,0x0003d9079fb7b527,0x00003d9dbaa99eae,0x00002c03f5256c2b}, {0x000f18757b53a47d,0x00030cf0c5879790,0x00057ef7f9307b01,0x000bbaf31903d772,0x0000699468bdbd96}}, {{0x000f2f46f4dafecf,0x00014a47fd6f7bd1,0x000a47b37f7cef01,0x0005785d31ffdda4,0x0000525219a47390}, {0x000d3de66aa91948,0x000c22fc0d2ccd8d,0x0004fdea2f485064,0x0002e3a9b4824663,0x0000293e1c4e6c4a}, {0x000e134b925112e1,0x000b5dca15da0376,0x00061c3111703778,0x0002823b04589af4,0x00005b605c447f03}}, {{0x0005805920c47c89,0x0000c923b8fccb96,0x0002e2ef77e7f010,0x000b3ee000125650,0x000024a76dcea8ae}, {0x0009fec6f0e7f04c,0x0009e75e349623be,0x000e1de61a866a57,0x000bdd55542ef161,0x00002f12fef4cc5a}, {0x000522b2dfc0c740,0x0007f40c9a4070a4,0x0008cff66810d06e,0x0003790c6cf14417,0x00005e607b2518a4}}, {{0x00031d8f6cdf1818,0x0004fc36258a258b,0x0006e61d6e35cfa7,0x000d5f7e1b3ff4f6,0x00005067acab6ccd}, {0x000c431ca596cf14,0x00040aed3e400a02,0x000e0f26dbe3c42d,0x0007068d24526802,0x0000201f33139e45}, {0x00027f6b08039d51,0x00064017c0006fd5,0x000e25a4a818b149,0x0000375d5220eb02,0x0000397cba886246}}, {{0x00013093f05959b2,0x0008de9a9797630c,0x00021d5e26e23aa1,0x0006c3a222fd4917,0x00002339d320766e}, {0x0005c3fbc81379e7,0x00020dde12af1781,0x0005a8fdd5a66194,0x000c252ffa9c0f88,0x0000771b4022c1e1}, {0x000dd986513a2fa7,0x00071f9d4cf08d87,0x000ea283b3f5ac9b,0x0001a76d06bc31b1,0x0000331a18921997}}, {{0x00066f45fb4f80c6,0x000de61c775cff51,0x000041d91c9c36c7,0x000fe21e3d4e81b9,0x000031167c6b83bd}, {0x00012f3a9d7572af,0x0008868074a9e265,0x000180f7c45bcbe2,0x000a67b84edc1c11,0x00001ac9619ff649}, {0x000b3842524b1068,0x0003bee9ce987f22,0x000a6250c8506834,0x000b111fc9d71844,0x0000612436341f08}}, {{0x000d41db874e898d,0x000f16c07dc20d99,0x00000f9bbc09fea5,0x000ff40793d2c67d,0x000046ebe2309e5e}, {0x000349e31a2d2638,0x000009bd3fd358b6,0x0003a06ba49ddfb7,0x00004457f8bf1b8a,0x00001522aa3178d9}, {0x00082f5369614938,0x0009ab72d6d102c3,0x000646f227dafe40,0x000306ce8c83391b,0x000045fe70f50524}}, {{0x000875a6960c0b8c,0x00076ef0e2f20da4,0x000d0b8fd45b68d0,0x00092d407fb51cf3,0x0000428d1623a0e3}, {0x00024920c8951491,0x000c83f630ca262f,0x0005c9d4b805f007,0x00022456fbb45d2f,0x000016619f6db57a}, {0x000f4a4401a308fd,0x000c376a5caac084,0x0003d1bc7da82219,0x00038c6deb8de464,0x00001d81592d60bd}}, }, { /* slot=4 [{1,2,3,..,8} * 16^(2*4)] * G) */ {{0x00068756a60dac5f,0x0006aebabdc57613,0x000cce0f7d17e02f,0x000dcf07f193f2d4,0x000020234a7789ec}, {0x0005b69f7b85c5e8,0x0008bd168bab2876,0x000d330f9b6ff067,0x0008e7c3a70e77c1,0x00003a5f6d51b0af}, {0x00020db67178b252,0x000f9d51ed16076d,0x0003e41170071c34,0x000e366f62a4a20b,0x00007cd682353cff}}, {{0x0001a45bd887fab6,0x00032ba403b6e0be,0x00096e60002a846a,0x0000943d9921012e,0x00002838c8863bdc}, {0x0005cd6068acf4f3,0x000183cd7e3d3a66,0x00036025d942d92d,0x000d8ff5759389d3,0x00003ef0253b2b2c}, {0x000bb0cf4a465030,0x0004115c577abd16,0x0004ab419dfa496b,0x000281282cfae8af,0x000021dcb8a606a8}}, {{0x000004468c9d9fc8,0x0006ed42aa3cb5c6,0x0002ee2f9c254009,0x0001dab125b4d4c1,0x00000bc3d08194a3}, {0x000d00fabe7731ba,0x0007e629e18899a8,0x0003f3d97f820360,0x000678bb2cc02374,0x00005d840dbf6c6f}, {0x000e380d309fe18b,0x000a6b9e165c7706,0x000dae20ab6eb02d,0x00096dd57bbba997,0x00003a4276232ac1}}, {{0x0002432c8a7084fa,0x000e3dfb9e5454b4,0x000c58e45d898a19,0x000ebd1be9f00219,0x00001ff177cea16d}, {0x0008c172db447ecb,0x0001fc6282dbd3bf,0x0005aa15fe5fcfc4,0x000a9f980acffc07,0x00000770c9e824e1}, {0x0001d99a45b5b5fd,0x000e91b3a7924cf6,0x00003e3e89860984,0x0000b1ee73009193,0x000039f264fd4150}}, {{0x000d3417dbe7e29c,0x0006a2b9c139ca7a,0x0003597ba9bd9437,0x0009840a0e91b8e9,0x00001712d7346888}, {0x000b4aabfe097be1,0x000e1dfe01929d19,0x000ca6f1ffa46dfc,0x000f14ec3c908942,0x000065c621272c35}, {0x000b89f8ce3193dd,0x00056a125c0bbe72,0x000e1cfe834d1033,0x000e2720419a93d2,0x000022f9800ab19c}}, {{0x000a368a3e9ef8cb,0x00022a5504715605,0x000f24248fe3e9c0,0x00026e5553d48b05,0x000013f416cd6476}, {0x00029fdd9a6efdac,0x000be34a54941420,0x0007bdf37bb912ce,0x000cab4640f64b98,0x00004171a4d38598}, {0x000758aa99c94c8c,0x0006fb000b807fa2,0x000dda539223006f,0x000d1abfbd291dda,0x0000508214fa574b}}, {{0x000269153ed6fe4b,0x00039511d77c4c20,0x000c14af94a65a67,0x000a74bcbde26462,0x000022f960ec6fab}, {0x000a15bb53d003d6,0x00088bcf3c965461,0x000c683a5ab21028,0x000b44727c576756,0x00003a7758a4c86c}, {0x000111f693ae5076,0x000df1dfd54a6548,0x0003115e651dae21,0x000f49412248c90f,0x00005d9fd15f8de7}}, {{0x000408d36d63727f,0x000efd7c7b533031,0x000caee24b6a379a,0x000bed3a9e18fc5c,0x0000332f35914f8f}, {0x00044d2aeed7521e,0x00028432e96153f2,0x000e9c16d48e3a90,0x00098d8e164ba772,0x00003bc187fa47eb}, {0x00070115ea86c20c,0x000cb6c46d1256d4,0x000a660188998ab7,0x000ba03d77832b53,0x0000450d81ce906f}}, }, { /* slot=5 [{1,2,3,..,8} * 16^(2*5)] * G) */ {{0x000bb6a1a6205275,0x000d7413c8e836e7,0x00088f5cb2aa4f21,0x0005be16f56d155e,0x00002de25d4ba634}, {0x0004d8961cae743f,0x000f5ee1c63edd07,0x0007f4ed29f86d18,0x000b10897bdc55be,0x00004cbad279663a}, {0x00019024a0d71fcd,0x0000afb288af880d,0x000f3a6419c525c2,0x0007233b1a3974b5,0x00007d7fbcefe200}}, {{0x000f1e6a266b2801,0x000c4d5739f16fae,0x000b03762c866c68,0x0005a8df68a2fbc1,0x00005975435e87b7}, {0x000c5dc5f3c29094,0x0009a2a9105abcd7,0x00021c3058c781a2,0x000d4d780c61d364,0x00004f9cd196dcd8}, {0x000297d86a7b3768,0x000241ad17a63199,0x000c1c0c17d0d058,0x0000307ba029cad5,0x00007ccdd084387a}}, {{0x0006422c6d260417,0x00050948240bddca,0x000b68c677ae153d,0x000cf53a9c0c1b4f,0x0000428bd0ed61d0}, {0x000c84186760cc93,0x0007a1ab32a999b0,0x00020bda18cdae00,0x000ca44a88dec866,0x00003593ca848190}, {0x0003189a5e849aa7,0x0003565d8facd921,0x0003fdbbd1d4d8c3,0x00063e68c52545b5,0x000027398308da2d}}, {{0x00038d28435ed413,0x000603278ccc942c,0x0009da03efbd50f3,0x0003355bb07ab1a7,0x0000269597aebe8c}, {0x00010e4c0a702453,0x00066d57d1bdeb9a,0x000d27daf70fa258,0x00033fdffb9d9b5c,0x0000572c2945492c}, {0x000fc745d6cd30be,0x000d3e3baaefbc77,0x000a5dda0ce4dfe8,0x000ca80a22c8830a,0x00007f985498c05b}}, {{0x0009ce889f0be117,0x0001b7b54a288384,0x0003fc921c8005ad,0x000f3043da3c39f2,0x000076c2ec470a31}, {0x000615520fbf6363,0x00045cf4dfba6d35,0x00073fa0c208045a,0x00012e7eec24fbc8,0x000030f2653cd69b}, {0x0008c938aac10c85,0x00060db276bcb8a0,0x000e6fac7046179b,0x00073daa920c01e0,0x00002f1273f15964}}, {{0x0009fc7c8ae01e11,0x000904a6aab9f473,0x0007728f2efd5274,0x00069f241d98a828,0x00005d9e572ad85b}, {0x00088bd755a70bc0,0x000a4f1d442e7304,0x000c59616206d6b5,0x000f784ead1a69eb,0x000038ac1997edc5}, {0x0006b517a751b13b,0x000867e9b858c066,0x00054dde49747d06,0x000e69cacacc0114,0x000022dfcd9cbfe9}}, {{0x000bd2e0c30d0cd9,0x0005facbb43338dd,0x00022a961fad8e66,0x000c1c78f6b258c3,0x00006b2916c05448}, {0x000c59b4103be0a1,0x000ecd259f96956e,0x0003f5cd322ee3ba,0x000e472797cb2941,0x00000fe9877824cd}, {0x000b34d10aba913b,0x000822e6dac0e7ed,0x000578f8154ea3cd,0x0000a1766083dff6,0x00004c303f307ff0}}, {{0x000a3bd617b28c85,0x000b739773bead30,0x000e6a5cbfc5d377,0x000b7c4c6c6e78c1,0x00000d61b8f78b2a}, {0x000c03580dd94500,0x000a46fbbec9329f,0x0002e2a7f8ecd27a,0x000a1d5130a155fc,0x0000416b151ab706}, {0x0008d7efe9c136b0,0x000cd58e44b2056a,0x000b57e0abbd07e5,0x000e8d2afe62fda1,0x0000191a2af74277}}, }, { /* slot=6 [{1,2,3,..,8} * 16^(2*6)] * G) */ {{0x0006f74bc53c1431,0x000ce2072eddece1,0x0005b23ee72b9725,0x000c908b8b9c36fb,0x00007e2e0e450b5c}, {0x00062b434f460efb,0x000d4a63607d69fe,0x0007a0da24ded303,0x0005b93f052210eb,0x0000237e7dbe0054}, {0x000575ed6701b430,0x000e69f0bfd10013,0x0003e47f22231094,0x00055e375320f158,0x000071afa699b111}}, {{0x000e6f9b3953b61d,0x000eaafa141e665c,0x0009f759fec65839,0x000c28e0f435ffda,0x0000021142e9c2b1}, {0x00023c1c473b50d6,0x0001f3b38ef10ea4,0x0002c9be9551e87a,0x0009a1c9b84bf5fb,0x000000731fbc78f8}, {0x0000c71848f81880,0x000225ecec119e43,0x000bba15e3bf960c,0x0005808b6dae0836,0x00004c4d6f3347e1}}, {{0x0007eccfc17d1fc9,0x000a651403c1418f,0x0007ee0cdf6c75f5,0x0007a22dbde712bf,0x0000193fddaaa7e4}, {0x000cddfc988f1970,0x00027b0b9f51b2f0,0x00079176be6b9162,0x0009fa86ec7b6c47,0x000038bf9500a88f}, {0x0002c93c37e8876f,0x0005a18d1462c1fd,0x0009241276a2f61e,0x00049695080f5823,0x00006a6fb99ebf0d}}, {{0x0006c1bb560855eb,0x00038f893f09d6a4,0x000f71acc12416bb,0x00096ead71d11378,0x000075f76914a318}, {0x000122b5b6e423c6,0x00010f286ff8eeeb,0x000dcf5d8c939d70,0x000eb1090a92a831,0x0000136fda9f42c5}, {0x000cdfb1a305bdd1,0x0009d9ff82c08f94,0x0003bb588a0f364b,0x000dcba2a87d8a5c,0x0000022183510be8}}, {{0x000766385ead2d14,0x00080ca7c58304af,0x0000211e3da08ed8,0x0006c030d13a6e61,0x00006a071ce17b80}, {0x000a710143307a7f,0x0009ec47da45f9d5,0x000e927ad3b063de,0x000426c22bbfe52b,0x00001387c441fd40}, {0x0003c3d187978af8,0x0003d7f0e4413b5d,0x000b477ca0722b5a,0x000dc920d7b4848b,0x00003171b26aaf1e}}, {{0x000f319097564ca8,0x0004c2275e119a92,0x0004875150ff7bb8,0x000835a4f55fe37a,0x0000221fd4873cf0}, {0x000db7d8b28a47d1,0x000d61770a4f1a60,0x0003ddbd58a6bf14,0x00043e9d4a1f8935,0x00006c514a633442}, {0x0002204f3a156341,0x000e9ba0a032d232,0x00010f030efb73e0,0x0004aaafce0dd4c4,0x000048daa596fb92}}, {{0x000a8e665ca59cc7,0x0004b2e38aca06ec,0x00021e17cea84725,0x0004af731afc708d,0x0000676dd6fccad8}, {0x00061d5dc84c9793,0x000e3ef41820614f,0x00046277ac9941f9,0x00079a9cdf5b88f3,0x000058c837fa0e8a}, {0x0009688596fc9058,0x000f37b56a01b0cf,0x000935d66a1ddcbb,0x0007f0adcc2e77d4,0x00001c4f73f2c6a5}}, {{0x000a4fbd305fa0bb,0x000e054c663ad0e7,0x000fe33848829d4c,0x0004c42f421c3832,0x0000795ac80d1bf6}, {0x000e706efc7c3484,0x000b4c3c1cf61b36,0x00081cc7e573dfc9,0x000675ceb1d79c97,0x000070459adb7daf}, {0x0001db4991b42bb3,0x000234b02dcca1b9,0x000f8c78dc572696,0x0001fd39fdf9ee51,0x00005fe162848ce2}}, }, { /* slot=7 [{1,2,3,..,8} * 16^(2*7)] * G) */ {{0x0009214fe194961a,0x000c70d71cd4f4e5,0x000b50f22d49be7d,0x00072329300cfd23,0x00004789d446fc91}, {0x0009852d5d7cb208,0x00070687df2e7287,0x0001687891b8dedd,0x000aa35dc0bffab2,0x00002b44c043677d}, {0x000c87ab074eb78e,0x0008e99daf4671a1,0x00084f9067fac6d1,0x000a4e43eacbbcd4,0x000060c52eef2bb9}}, {{0x000d89bc3bfd8bf1,0x00037c9f3551a0b5,0x00053028f5b06b92,0x000caab0e4c16b0d,0x000010bc9c312ccf}, {0x000bc5c27cae6d11,0x0009b54a48cab702,0x000a492eb244c769,0x000676defbc4056b,0x000070d77248d9b6}, {0x000ae84b3ec2a05b,0x000f4ed1781e0aa8,0x00008e85d198699e,0x000f413794513e47,0x000063755bd3a976}}, {{0x000fa03e2ad10853,0x000909ee63569b55,0x000e69b890356f75,0x0006f849ff9f1fdb,0x00000d8cc1c48bc1}, {0x0007101897f1acb7,0x0005ec165bbd83dc,0x000fa1020f5dda7d,0x0002a56508e5b9c0,0x00002763751737c5}, {0x000402d36eb419a9,0x0007e77b460a5029,0x00043c4956f0b44e,0x00066e7cfa86230d,0x000070c2dd8a7ad1}}, {{0x000194509f6fec0e,0x000a946c6518d656,0x0007e09b5cee2e7e,0x00084959733c1f36,0x00002e0fac636394}, {0x0004967db8ed7e13,0x0000ad776817a91d,0x000d85256474252f,0x0003ce5e40982e00,0x000032b8613816a5}, {0x0007f7bee448cd64,0x00067087886d079e,0x0000e4db2e6ac83a,0x0004f41f89fd4d9a,0x00004179215c735a}}, {{0x000094e7d7dced2a,0x000c347d39c708c7,0x000906d90297fb8a,0x0009d76e13be033a,0x0000700344a30cd9}, {0x000e33b9286bcd34,0x000b6559dd6dce4a,0x0003d38e1fb7ef7e,0x000c286278b141fb,0x000031fa85662241}, {0x00026c422e3622f4,0x000879833502daf8,0x000b389123c12029,0x00024899bc1b7e12,0x000024bb2312a995}}, {{0x0008ed1732de67c3,0x00018461b4948b1a,0x0006cfbcd23cb494,0x00080088ebd43437,0x00000fee3e871e18}, {0x00080c2af5f85c6b,0x000c304fa679441f,0x0003ba1bad687284,0x0005d168945df99a,0x00000d1d2af9ffeb}, {0x000a8aa132621edf,0x000a159226579a9d,0x00079ac19330b822,0x0001d764004197ba,0x000016acd7971853}}, {{0x000f72af2d9b1d3d,0x00036a432245a72d,0x0006b3963763462a,0x00023093ecea0791,0x0000123e0ef6b930}, {0x0009c6c57887b6ad,0x000ad5f90febac95,0x000342f50494e19e,0x000170016e24e62a,0x0000164ed34b1816}, {0x000ed94c192fe69a,0x000ea3a911513487,0x0009a4de2761ae2c,0x000f3eb877bf6d3b,0x000078da0fc61073}}, {{0x00015d28e52bc66a,0x0001870f01a8e5bf,0x0006c28bdd2c47e3,0x000173a2419afbc0,0x00002d25deeb256b}, {0x000f80f1680c3a94,0x000151ae9e7e6a29,0x000801797371f77e,0x0008ddd1100f1584,0x0000054aa4b316b3}, {0x0008468d19267cb8,0x0009c66e54dafdfc,0x00066eec170b2878,0x000a7602aeb1d2a6,0x0000134610a6ab7d}}, }, { /* slot=8 [{1,2,3,..,8} * 16^(2*8)] * G) */ {{0x00038ec78df6b0fe,0x00089e575f51b511,0x00017af1b95397da,0x000d65009207a1d7,0x00002102fdba2b20}, {0x000a65e777d1f515,0x000878faa60f1cd2,0x000abc06e5548991,0x000c9fbb1b73bbcd,0x0000654878cba97c}, {0x000ee405055ce6a1,0x000681251ad29969,0x000a7da41536bca7,0x000b2ba3a1af517a,0x00000ad725db29ec}}, {{0x000267b1834e2457,0x000b570ce1bc5dc4,0x0007d15ed7b67544,0x00036501af07a0bf,0x00004aefcffb71a0}, {0x0007bc0c9b056f85,0x00068e7f5ffd7fec,0x000312aefa537d52,0x0009fd977afc6624,0x00004f675f530239}, {0x000d36360415171e,0x000118998483bc32,0x0000945110cd2bef,0x0006561870a6eadd,0x00000bccbb72a2a8}}, {{0x000e962feab1a9c8,0x0003565147dcd185,0x000b5b6df286e7e6,0x000b73eb092e031b,0x00004024f0ab59d6}, {0x000d5e4c50fe1296,0x00082fee89f7e186,0x00007031b0e0397b,0x00037c23bc7f6c55,0x00006678fd69108f}, {0x0006fa31636863c2,0x00048572d33f2158,0x00089eaefc07f68c,0x00047014f73cc9f7,0x00002d42e2108ead}}, {{0x0005131594dfd29b,0x0005d313f4c6a97f,0x0008455010615598,0x000d322eba13f070,0x0000676b2608b8d2}, {0x00017b0d0f537593,0x0000b131e064c217,0x00052ae09f914e69,0x0003c6e1bb687ae7,0x0000420bf3a79b42}, {0x0008ba651c5b2b47,0x000ec311b1b80813,0x000c3135b08671b6,0x000f1e07bff0cb1b,0x0000745d2ffa9c0c}}, {{0x00025a1e2bc9c8bd,0x0000826479d81bf5,0x000f0155dbea5b26,0x000f5d0d511c70ed,0x00001ae23ceb960c}, {0x0006df5721d34e6a,0x00027997bb3d0603,0x0008756afab1db88,0x000c839d3c209c3c,0x000006e15be54c1d}, {0x00025d871932994a,0x000b5ceb1dab05b7,0x000ab7ca0532351c,0x000c1f77dc41549d,0x000058ded861278e}}, {{0x00073793f266c55c,0x000c5cc454e49d81,0x000c26c3a8c8c976,0x000f6f95ce382f8b,0x00002ff39de85485}, {0x000b5ba8b6c2c9a8,0x0008ef52c598c2df,0x00012d157348eeef,0x0005bd833809107f,0x000008ba696b531d}, {0x000d3eeec3efc57a,0x00017d4ff481177e,0x0001a671cb04e055,0x000fe54ea3d7a3ff,0x0000120633b4947c}}, {{0x0004987891610042,0x0003cecebfae80b9,0x0004f0a4c04ee7b1,0x000918570be73959,0x000035d30a99b4d5}, {0x000d31474912100a,0x0006d7e6fbe0682b,0x0001ea79c6de237b,0x0003bdee11e76191,0x000007433be3cb39}, {0x000944c05ce997f4,0x000e4b05c51a3ff7,0x000a76847c575d3d,0x000da9f583381fd5,0x00002d873ede7af6}}, {{0x000a316443373409,0x000eef4aa81d9157,0x0005a64806fab8b7,0x000a7b6b093fee6f,0x00002e773654707f}, {0x000202e14e5df981,0x000175015e1f5aa6,0x000ae21d6ca20d59,0x000025318a275d3b,0x00000543618a0160}, {0x000abdf4974c23c1,0x000259dce46930de,0x00029aba2caa6f0a,0x000960d04202cb8a,0x00004b1443362d07}}, }, { /* slot=9 [{1,2,3,..,8} * 16^(2*9)] * G) */ {{0x0004b7c7b66e1f7a,0x00025f50c2f7eccc,0x00013eaf1c44157e,0x00063f73ef06dfc7,0x0000582f446752da}, {0x000c54e91c529ccb,0x0009264c635fb967,0x000812196530f626,0x0006f5c2747aff47,0x000017038418eaf6}, {0x00017bd320324ce4,0x000e8a4488bc4c63,0x000e5a1364a81042,0x0008dc9b21ef18b4,0x00000c2a1c4bcda2}}, {{0x000dc7d06f1f0447,0x0003edb87c059d24,0x000bb2d28fb2269e,0x0004877d15b0272f,0x00007c558bd1c6f6}, {0x0004814869bd6945,0x0007dbe1c8d22edc,0x00055cc5ab0d6d90,0x000dc83c63bd212d,0x00005a6a9b30a314}, {0x000c1524d396463d,0x0008ac35a24f0d0e,0x000cbc5fa412bb62,0x000afc3a50c3a791,0x00000404a5ca0afb}}, {{0x000f40070aa743d6,0x000cb5b265ee88c1,0x00068fd2deccbad0,0x0009633574b046b6,0x000046395bfdcadd}, {0x000c9e1b2a416fd1,0x00028e350598b62b,0x000d5d6967b5c6f7,0x000ee9804343fd83,0x000039527516e7f8}, {0x000fdb2d1a5d9a9c,0x000bcd1005c2a117,0x0004d56fea9c7745,0x000d016efd4bef15,0x000076579a29e822}}, {{0x00068e7e49c02a17,0x000a2bca9a37f45b,0x000c224c1b23cd51,0x000bdb13ed65f11e,0x000043a384dc9e05}, {0x000cb51352b434f2,0x0004993de80e1333,0x00050d35ced83228,0x00077c1b55128877,0x000002c514bb2a27}, {0x000bd5da8bf1b645,0x0007ef6b54b53684,0x0009b0d253fb8bd3,0x0008059313916d7a,0x0000116092096154}}, {{0x000d166929dacfaa,0x0004c8413598fb44,0x00053d5559da529f,0x0008e0be9ef63ca4,0x0000351e125bc569}, {0x00085616369b4dcd,0x000a7655c35637a3,0x0004f1802175c02c,0x000e0427dc21bf9d,0x00002f637d7491e6}, {0x00049b461af67bbe,0x0007ac8ab8961d4b,0x0009a699fbd60303,0x0002a9a71dee19ff,0x00007f182d06e7ce}}, {{0x000c8e64ab0168ec,0x0005515edc5437a7,0x0007cd0edacb5a4a,0x00093b0095519d34,0x000067d4ac8c343e}, {0x00054b728e217522,0x000f4d484b8d8094,0x000f46903caa58e8,0x0005217d358254d7,0x000044acc043241c}, {0x000d6bbb4f7a5777,0x000d4918313e11c7,0x00096b46848b35fe,0x00071bd4adca1c6c,0x0000556d1c8312ad}}, {{0x000f40e30c8d3982,0x0003e15a3fa3417e,0x000773646e31f707,0x0004eff4f21f3cb0,0x0000746c6c6d1d82}, {0x00006756b11be821,0x0002310a3f3dd81f,0x000a99465d0faff8,0x0007f05f8b2d0556,0x0000097abe38cc8c}, {0x0009c9877ea52da4,0x000559bdc1d430c4,0x0007ccebd24c4369,0x00084bd022c3809f,0x0000577e14a34bee}}, {{0x000268ac61a73b0a,0x000103791a5f5f0e,0x000b6d00e9f2fafa,0x0008f42c1e13e826,0x000060fa7ee96fd7}, {0x000ecebebd4dd72b,0x000da060f221194f,0x0000c8d1fff46a4f,0x0009295124a5977c,0x0000705304b8fb00}, {0x000d1d354d296ec6,0x0003e5fad31d8b63,0x0004bd42ecf3c305,0x00053fd670b958cb,0x000021398e0ca163}}, }, { /* slot=10 [{1,2,3,..,8} * 16^(2*10)] * G) */ {{0x0005058a382b33f3,0x0000bad48c0b489f,0x00053db36e5ae2ba,0x00032e68f93b503a,0x00005aa3ed9d95a2}, {0x0008aaf9b4b75601,0x000135c8dad72279,0x0001b7a0235eac72,0x0007d4ed2ceaa616,0x00001bbfb284e98f}, {0x000777e9c7d96561,0x0005472c78036656,0x0009506eeecb2b12,0x00057cc65053299d,0x00004a07e14e5e89}}, {{0x000412cb980df999,0x0006f3c6ec7714ee,0x00025c77fda315d7,0x0003402bba5edde9,0x00003f0bac391d31}, {0x000b58cdc477a49b,0x000de6447f017240,0x0007c86aadfd38da,0x000a08119928d32a,0x000050af7aed84af}, {0x000fde0115f65be5,0x00021216109b26e4,0x000badd6d9299826,0x000d006780205810,0x00001921a316baeb}}, {{0x00022f7edfb870fc,0x000eb4f76b3bd894,0x0006c24df72c296b,0x000aeb00738f1d43,0x00006458df41e273}, {0x000aad9ad9f3c18b,0x000ef60b1c19cd75,0x00055c0ed9566a0e,0x000c7f53e9a0bac2,0x00007b049deca062}, {0x000be37a35444483,0x000330fedbe93dcc,0x0002c5dd87758879,0x0000e64786004c31,0x00006093dccbc295}}, {{0x00039a8585e0706d,0x000d8b3e739331ff,0x00018f453b36d0a5,0x000a97c43b9f2e17,0x000057d1ea084827}, {0x000eeebe6084034b,0x000b6780fb8546bd,0x00062d06953199c2,0x0007d90973376abb,0x00006e3180c98b64}, {0x000ab6e7a128b071,0x0006d93a88baaee7,0x0002216130a4c159,0x000bd18f7b4de82b,0x0000363e999ddd97}}, {{0x000843c135ee1fc4,0x0005508e4c8cf96a,0x00058cd330976eb3,0x000052bb42f6801b,0x000048ee9b78693a}, {0x000848dce24baec6,0x00055babcaf602f1,0x000cefe931769b72,0x000b35590cb3c6e3,0x0000231f979bc6f9}, {0x0001de4bcc2af3c6,0x00030fe208d1f5c3,0x00014fb466b04bb0,0x0002413b78d7009c,0x0000079bfa9b0879}}, {{0x00003a51da300df4,0x000233da95ab0e39,0x000b356480843964,0x0007194ed3cf12d0,0x0000038c77f68481}, {0x0009ed80a2d54245,0x0007877f63952f3c,0x00010854750aa08b,0x000636bd76dac63d,0x00001ef4fb159470}, {0x000e5ee65b167bec,0x0004296d0cdc2854,0x000810219959590a,0x000ff5672b2df349,0x0000575ee92a4a0b}}, {{0x000080908a182fcf,0x000c299489dbdd4c,0x0002f733de30e170,0x000fd0005babd575,0x000043d4e7112cd3}, {0x0006bc450aa4d801,0x00027a533b9d85d4,0x000b8906c2c3af12,0x000581b389e3b262,0x0000200a1e7e382f}, {0x000db967eaf93ac5,0x0009b056652c0518,0x00067197f571bc98,0x0004e38fe2b85d95,0x0000050eca52651e}}, {{0x00031ade453f0c9c,0x0005eff703b9bc34,0x000d847b3de9f504,0x000f4c6fcd97ac9e,0x00004b0ee6c21c58}, {0x000c397660e668ea,0x000fe153ab49797a,0x0004eca79f9b19bb,0x000ae574cb179b53,0x00006151c09fa131}, {0x00055c0dfdf05d96,0x000e02ab4ee7a3af,0x0002171709dd262e,0x000030b11b2bb871,0x00001fef24fa800f}}, }, { /* slot=11 [{1,2,3,..,8} * 16^(2*11)] * G) */ {{0x000653fb1aa73196,0x000303fd7641837d,0x000b3a17b20f9495,0x000613ead200b09f,0x0000544d49292fc8}, {0x0002aff530976b86,0x00006c2d2460422d,0x000de5bae58d90b8,0x0000c17dca1896c4,0x000028005fe6c834}, {0x000fba9f34528688,0x0009425107da16ae,0x0006d94b365c1bff,0x0006dfaf75bbbcd6,0x000072e472930f31}}, {{0x0005208c9781084f,0x0000b23450ee1269,0x0003efde02b1502a,0x000a34cfd9daea60,0x00005a9d2e8c2733}, {0x0003f635d32a7627,0x000865f6566f007f,0x0008d044507aaa4d,0x00064383c85e7972,0x00001fee7f000fe0}, {0x000305da03dbf7e5,0x000491434cdbd765,0x00024a88eca4daf2,0x00005437b4ad5cdd,0x000000f94051ee04}}, {{0x00056b23c3d330b2,0x0009bb0471b068d3,0x000e42b83cf21c8b,0x000b10db36c316c6,0x000007d79c7e8bea}, {0x000f93bb07af9753,0x000cf3db766a7d7e,0x000e0b1ec5583ed0,0x0000452ce6998bf6,0x000047b7ffd25dd4}, {0x000bfb9cbc08dd12,0x0003ae1eec29b87f,0x000b1fc1bf8a066b,0x0004bb60d57242bd,0x00001c3520a35ea6}}, {{0x000253a6bccba34a,0x000a13838219b80d,0x000882e3963e61c3,0x000e66f90c3b6019,0x00001c3d05775d0e}, {0x00086f40216bc059,0x0001d12bcd87ecda,0x0007c709901fbb23,0x0002e55b4956a9e1,0x000038750c3b66d1}, {0x000ef1409422e51a,0x0003c2b5df671692,0x00044ce029cbc0c7,0x000487c21014fe77,0x00000621e2c7d330}}, {{0x000860cc8259838d,0x000c1c69f9adcaf9,0x0005581e3090ea48,0x000a5bc652648376,0x00000007d6097bd3}, {0x000e1796b0dbf0f3,0x000b9e17ce196b7a,0x0009aaa3b454dfaf,0x0002e9d25923071e,0x00005d8e589ca100}, {0x000f1d950842a94b,0x00063588f2e3ec0b,0x000b51e2efb2d3c3,0x000bf860a961438b,0x00001583d7783c1c}}, {{0x000ea2ef5da27ae1,0x0001455670174ece,0x000609167a597c3a,0x0008f70c9a62a126,0x0000252a5f2e81ed}, {0x00034704cc9d28c7,0x0009ef72cc58f900,0x000e5b87261d1b67,0x000580a16e12b5fb,0x00004958064e83c5}, {0x000894265066e80d,0x00085307c8c6b0d2,0x000c1112fdfcc3f7,0x000b3881b53da780,0x0000079c170bd843}}, {{0x0006ece464fa6fff,0x0001e6205e523050,0x0001b8ea42bee343,0x000fb00357942245,0x00006dec05e34ac9}, {0x0006cd50c0d5d056,0x0006dbb03573bcdd,0x0003c3ef489af768,0x0008acc3ca6723ff,0x00006768c0d7317b}, {0x000625e5f155c1b3,0x000a7997b7b9194b,0x000d6b2600417bf3,0x00052f4c22cbddc6,0x000051445e14ddcd}}, {{0x00002b4b3b144951,0x0006b444bbcb3575,0x00066385db8e67ff,0x00095c8b8bd69271,0x000013186f31e392}, {0x000147ab2bbea455,0x0004f92079129893,0x000e30f7a78c53a2,0x000d43d4b49f948b,0x000012e990086e4f}, {0x000c96b37fdfbb2e,0x0005e121ceaf9f10,0x000a5b983f9f9a93,0x00099afdf1136c43,0x000077b2e3f05d3e}}, }, { /* slot=12 [{1,2,3,..,8} * 16^(2*12)] * G) */ {{0x000fa9c59c2ec4de,0x000bf4f84f3cb296,0x0007a8f908bc8b61,0x000255d1c7706d91,0x000063b795fc7ad3}, {0x0008639c12ddb0a4,0x00030c024866bd59,0x0008fce460a5d19f,0x0005e8ad17c2f035,0x000007a195152e09}, {0x00068f02389e5fc8,0x00002cf8de43ba83,0x000541264390433b,0x0000137afa1fd5dc,0x00003e8fe83d032f}}, {{0x000b15b90570a294,0x00070670845492f8,0x0001bbfd8494f242,0x0004007de1c5ae16,0x000075ba3b797fac}, {0x00004c8de8efd13c,0x0008e33e03731087,0x000260cde3dfc51a,0x0008c86a59d5da51,0x000022d60899a625}, {0x0009dbc070cdd196,0x0008b6c7d8a9a623,0x000b40126060fe8a,0x0009e5eb38847bce,0x00000904d07b8777}}, {{0x000e1fd4ddba919c,0x0003ec74c8daab4c,0x000d86cc51cf31db,0x000de072c63cc63a,0x000043e2143fbc1d}, {0x00022d6648f940b9,0x0000cbd2d0c39f43,0x000081f93106952f,0x0002a6c167697ada,0x00006240aacebaf7}, {0x0004749c5ba295a0,0x0005bca37d25af83,0x0007c9316ad6947c,0x0000cac66f13ba7e,0x000056bdaf238db4}}, {{0x000ab9e3f53533eb,0x000d56eb93d40362,0x000d5a5572338568,0x00013189e0e14521,0x00001d24a86d8374}, {0x0000d36cc19d3bb2,0x000b7622386b9131,0x0007a14f5c062a6b,0x00057547c9b8591d,0x000003aa31507e1e}, {0x000c7648ffd4ce1f,0x000f054ac8c1cf4e,0x000d09357ce045ea,0x000485988d225821,0x000043b261dc9aeb}}, {{0x000b1e1988bb79bb,0x0007dc17a359de55,0x00003dea33a09ed0,0x0006bc2b02c2ee26,0x0000326055cf5b27}, {0x00013d8b6c951364,0x00026000bf47b195,0x00054f956794fe71,0x0000964028d10ddd,0x000002b4d5e24294}, {0x000155cb28d18df2,0x00046186ce508b4a,0x000c824389eacc46,0x0003410c49cf4936,0x000027a6c809ae5d}}, {{0x0006ebcd1f0db188,0x0003a675a5be88ba,0x0005f5585a37d3d7,0x000a17ef22edfa31,0x00002cb67174ff60}, {0x000c270ac43d6954,0x000576a66cab2cd2,0x0009d7036cdd4a3e,0x000259979fa59246,0x0000221503603d8c}, {0x000ecdf9390be1d0,0x00044728ce3f159e,0x000a94f0f4a94220,0x000f43682891c667,0x00007b1df4b73890}}, {{0x0002f2e0b3b2a224,0x000062b551160e49,0x000d7f7b0e7c6c9e,0x000599215eb8fe20,0x000061fcef2658fc}, {0x000e221807f8f58c,0x0009fd49409d45f2,0x000fb6a630e3555c,0x000e03db2aaa88d1,0x000068698245d352}, {0x00015d852a18187a,0x000d386ddacd7dbb,0x000ff6c482f3e4aa,0x00001cf44bae2810,0x000046cf4c473daf}}, {{0x000525ed9ec4e5f9,0x0000116903303426,0x000be5cadc0e5eda,0x0005f4072b1a7f2c,0x000029387bcd14eb}, {0x000c6ea7f1498140,0x000f8392b4854213,0x000629ceba7c1e7e,0x000c5bb2488c38c5,0x00001065aae50d8c}, {0x000c4525df200d57,0x000d6bfca674a1c2,0x00018340305c3b2d,0x000e7160a07e7b1e,0x000069a198e64f1c}}, }, { /* slot=13 [{1,2,3,..,8} * 16^(2*13)] * G) */ {{0x0002b2e0d91a78bc,0x0009cc8509667906,0x00005070b847c988,0x000a1bf9df54a664,0x00007369e6a92493}, {0x00014434dcc5caed,0x000963c84fb33e10,0x000d86a0e747ed5d,0x000f9e470019576e,0x000025b2697bd267}, {0x00073ffb13986864,0x000d9415dc7b89d6,0x000f273b5e3ca5fb,0x0004cd2e04ecc3bd,0x00001420683db54e}}, {{0x0008bd1e249dd197,0x000005e58c102b47,0x000cbaac5c620c35,0x000a72dfb02d32fc,0x000060b63bebf508}, {0x000ebb6fc1cc5ad0,0x000e99646ac8b34e,0x00066bde536a1b0c,0x00081c1d3b0da49a,0x000031e83b4161d0}, {0x0008c7129e062b4f,0x0004f29320ad897e,0x000f18683f49e48f,0x00003175bece14b6,0x000055cf1eb62d55}}, {{0x0009101065c23d58,0x0006d5094819c587,0x0002c55fa78b9d08,0x00091d4e2402fa91,0x0000669a65645708}, {0x0006b5e37df58c52,0x000dde799cc36307,0x000913ee20d73ab9,0x0000133bd831ce34,0x00001a56fbaa62ba}, {0x000e6b505c9dc9ec,0x000bba77c371a943,0x0001347651302557,0x0008a5c9873ae564,0x000013c4836799c5}}, {{0x000a5d465ab3e1b9,0x00087c7f13f61423,0x000cb5b9b6fc13c1,0x000b60719f83664e,0x000066f80c93a637}, {0x000cfb6a5d8bd080,0x000ec571a4842c4d,0x0008e55365deebc4,0x000b827d4b2e883b,0x000050bdc87dc8e5}, {0x000d37836edfe111,0x00015f011abd9606,0x0005b73b9632353e,0x000d5ae64b03ac32,0x00001dd56444725f}}, {{0x00047ff83362127d,0x000c471cd7c158fa,0x0009220c8bbc9f6a,0x000732e6e7145434,0x00000e645912219f}, {0x0007e60008bac89a,0x00011eae1c3e0c29,0x000fe7977c7d4cea,0x00005cdf3e38be19,0x00003a3a450f63a3}, {0x000f2f31d8394627,0x00083de94a510078,0x0007996f80389d31,0x000a87bd1e36c6d1,0x0000318c8d9393a9}}, {{0x00045d032afffe19,0x000497f24db66f27,0x000a8598ef0c9f3c,0x0005314bc98d3e3b,0x0000224c7c679a1d}, {0x00069e29ab1dd398,0x00058342d9e3b5d6,0x00035973cdfc9216,0x0000af655851dfdf,0x0000509a41c32595}, {0x00006edca6f925e9,0x000f4641b1f33bdc,0x000d833e89793ef3,0x000138982ec12809,0x000005bff02328a1}}, {{0x0002137023cae00b,0x0000ad1accf59363,0x00021a1c88544acf,0x00044a796741049d,0x0000780b8cc3fa2a}, {0x0001a0dd0dc512e4,0x000c844a5fafe688,0x000f4a52404fe70d,0x000a3ea1f748e6b8,0x0000576277cdee01}, {0x00038abc234f305f,0x000bd1405de081ef,0x0004e62a0d9a577f,0x000b7a15e82a5143,0x00005ff418726271}}, {{0x000e080c1789db9d,0x00025f3e778f5398,0x0006bd035da76020,0x00066befa98894c0,0x0000106a03dc25a9}, {0x000b47e813b69540,0x0003b432610e1e5d,0x0008781276f35d2a,0x000cb69ac1f26e93,0x000029d4db8ca0a0}, {0x000d0aaf333353d0,0x000a5acd309e5d9a,0x000888f7f038669d,0x000befa3c57658ac,0x00004ab38a51052c}}, }, { /* slot=14 [{1,2,3,..,8} * 16^(2*14)] * G) */ {{0x000c2b256768d593,0x000574422ca13da7,0x000a0ace1d98c1c0,0x000a690f1a80bd5c,0x000029cdd1adc088}, {0x000fd1ef5fddc09c,0x000fdf7575dced6c,0x00001634c2e82b3e,0x0002b9b25d56b5d2,0x00003041c6bb04ed}, {0x0002f2f9d956e148,0x000759f356b2e0ff,0x000f6c025cade797,0x0009a7b1a4698bb5,0x0000104bbd681404}}, {{0x0000fd3168f1ed67,0x000cdd86f3bc251f,0x0004d2f2de2c811d,0x000714944dc5c430,0x00005be8cc57092a}, {0x000d9a5fd67ff163,0x0009d4cc75681a95,0x000e20f257e92be6,0x0002df5b7f8024cd,0x0000204f2a20fb07}, {0x00043b3d30ebb079,0x0005abd652e30c81,0x000f6d5c31758915,0x000161f653c3c318,0x00002570fb17c279}}, {{0x000a367f2cb61575,0x000761cd6026c3ef,0x0005b52562f5f96f,0x0000acde8c7142a6,0x00003dcb65ea5303}, {0x000ea9550bb8245a,0x000a88f9050d1192,0x0008a4c935c8e6fb,0x00086687986ea2d8,0x0000241c5f91de01}, {0x0008172940de6caa,0x000f022d9733a28d,0x00035b01d18fbf2c,0x000f0e516d7fcdd2,0x000008420edd5fcd}}, {{0x000f20ab8362fa4a,0x000d4e21a3e6ecdf,0x000c39e62b57e118,0x00069fde3179617f,0x00000d9a53efbc17}, {0x0008c34e04f410ce,0x0005a276e0685035,0x000bb91521b6135b,0x000889c5d9670c7e,0x000004d654f321db}, {0x000dc116ddbdb5d5,0x000b68da5dd2d5e7,0x000334a2922954de,0x0001ad71cb608173,0x00004a7a4f261899}}, {{0x000718025fb15f95,0x000346b5c1b8ff4a,0x0000e011123df65f,0x0001848cdfcf0850,0x000011b50c4cddd3}, {0x0003b291af372a4b,0x00070718147f224c,0x0006899ef293da82,0x000ee33dd8485648,0x00004a96314223e0}, {0x0008274408a4ffd6,0x0007e9c1576d9a6e,0x000d02b3f2738e17,0x000cc51773348b63,0x00004f4bce4dce6b}}, {{0x000fce5ae2242584,0x0005692f58a9ea71,0x000cea3cf426ea72,0x00001e6d21a09d71,0x000073fcdd14b71c}, {0x0002616ec49d0b6f,0x0008fcaec231730e,0x00026b4fa6e45671,0x0005f3748eb409bf,0x00003042cee56159}, {0x000e7079449bac41,0x0006dbce2310a427,0x000f841a7c855ae3,0x000e1d64cae76215,0x0000389e740c9a9c}}, {{0x000cb3ae34dcb9ce,0x00023e348d0ad64f,0x0002c6381b975003,0x000678845b3f07d6,0x000061545379465a}, {0x000d78f6570eac28,0x0003227919ce1c9b,0x00019b91ede55b0b,0x000369065fc3eaba,0x000025c425e5d626}, {0x000e06a6f1d7de6e,0x000278e0623083f3,0x000e8a6c773ef976,0x00047598c14f6264,0x00006539a0891548}}, {{0x00021f74c3d2f773,0x0004125c46845e9d,0x0009b99e33c15054,0x000186c624e5ce8f,0x000011c5e4aac5cd}, {0x0004dbd414bb4a19,0x0003c98424f8eddc,0x0006ca716919b2bc,0x000bd9048a89fd73,0x00000f65320ef019}, {0x0006d1b1cafde0c6,0x000e3163b5181d48,0x000af2939a4f3fe6,0x000072a59a8af0df,0x00004cabc7bdec33}}, }, { /* slot=15 [{1,2,3,..,8} * 16^(2*15)] * G) */ {{0x000e9624089c0a2e,0x000c03afe4738239,0x00064fa12ac748c4,0x000858217dbed2a7,0x0000639b93f0321c}, {0x000f788f3f78d289,0x0002ca1404d9fc08,0x000f65cc9dfe30a7,0x0002021f2778bfcc,0x00007ee498165acb}, {0x000508e39111a1c3,0x000d4809074897bd,0x000e72fd192b2b90,0x00002a6e7d2aec2a,0x00000edf493c85b6}}, {{0x000c8158599b5a68,0x0000febade20eaec,0x0002b67f07ea574f,0x0004fb44fe41d742,0x0000403b92e3019d}, {0x0007c4d284764113,0x0003ff7f5f835676,0x000ae6bedea09040,0x000a3691c8fcffac,0x000004c00c54d1df}, {0x00022f818b465cf8,0x0005a1480eff84dc,0x0004c7d65771a0f3,0x00076f4aee8bfad0,0x0000355bb12ab261}}, {{0x000e64cc7493bbf4,0x000d9eca3b0c3a71,0x000a05e785e5bd84,0x000c3120a6bc50cf,0x00000f9b8132182e}, {0x0001dac75a8c7318,0x0009db3ceaa11a30,0x000bae3f2ded9003,0x000ad8e6f077cbf3,0x00007518eaf8e052}, {0x000859c41b7f6c32,0x000bcf4383298a48,0x0009b1d1d90f2d60,0x00055c41815a929c,0x000047c3871bbb17}}, {{0x0004539771ec4f48,0x0007dc98c5d6e514,0x0007c3c66bf805b1,0x00099dcf762c11a4,0x000000b89b857646}, {0x00065d50c85066b0,0x000b0b3a299b0fbe,0x00041ae8e062ecc4,0x0008d5fe53754ea4,0x000008fea02ce8d4}, {0x000ddd7668deead0,0x000204b685d23824,0x000d89d665c86445,0x000d537b514cfcd5,0x0000473829a74f75}}, {{0x0002da754679c418,0x000d8b2618df082d,0x000c47eb0ae63bd7,0x000c6b4355eef24a,0x00002078684c4833}, {0x0009533aad3902c9,0x000ceef03588f23d,0x000fe12fb464c2dd,0x000d39015257390c,0x00006c668b4d44e4}, {0x0008cf217a78820c,0x000b281273e973b4,0x000c8eed7bf76a0a,0x000433fa96c65a78,0x00007411a6054f8a}}, {{0x00059d32b99dc86d,0x00075603af1154d6,0x000cc2e488044cdc,0x00034ffb34c712cd,0x00007c136574fb81}, {0x000ae53d18b175b4,0x00059f392a102579,0x000eef35f5687131,0x000398f8455ecba1,0x00001ec9a872458c}, {0x0006a4d400a2509b,0x000020bc882b4b8e,0x00019575619b81d7,0x000646057e7cc9bf,0x00003add88a5c7cd}}, {{0x00095770b635dcf2,0x0006cf66c1fbcab8,0x000eb6d18702dfef,0x0009e7485530268b,0x0000249929fccc87}, {0x000298d459393046,0x000985ff659ec85c,0x0002f66e3a8f7e35,0x000a7201d2ca22af,0x000061ba1131a406}, {0x0000a0f116959029,0x0006cba7ebd89a3d,0x0006783307023b6b,0x000ece77bf15a3e2,0x00005620310cbbd8}}, {{0x000993434934d643,0x00006a51222f5528,0x0003f41c22b9dbf8,0x00097308f6d878fc,0x000037676a2a4d9d}, {0x0006b5f477e285d6,0x000676c8f6193664,0x000bb594dd40e8ff,0x000ec4da6ec7311a,0x00007ec846f3658c}, {0x000e8f3f1da22ec7,0x000776c01cd139b5,0x0002989fb8130f1d,0x0009dd5214c8fcfa,0x00006daaf723399b}}, }, { /* slot=16 [{1,2,3,..,8} * 16^(2*16)] * G) */ {{0x000a7562eb3dbe47,0x000548ebda0b85f3,0x0005747299f7ea38,0x000d55100c3e5314,0x00001304e9e71627}, {0x000b04bfacad8ea2,0x000e8148be884583,0x000810c5db29b743,0x000bbaa2b1e583b0,0x00002b5449e58eb3}, {0x000814d26adc9cfe,0x0003f8b48dd0b789,0x000979c60a3c1bab,0x000d693da0fe1fff,0x00004468de2d7c2d}}, {{0x000b355e9419469e,0x0004c23ddc75451b,0x00047f996233e6dc,0x000bd6393a5b6d64,0x00006cce7c6ffb44}, {0x000ad8c6f86307ce,0x00031435d0c284b9,0x00057a772c211135,0x0007352d4a866c56,0x00005da6427e6324}, {0x0004c688deac22ca,0x000f7bbae1ff81a9,0x000d59580fb9066e,0x0002ca888ad8c388,0x000058f29abfe79f}}, {{0x000ecfab8de73e68,0x0009f377e76a5e90,0x000e01598254036f,0x0001e36f0495b0bb,0x0000577629c4a7f4}, {0x000a64bf710ecdf6,0x00038462c293c4b5,0x00050b3ab9b14ce5,0x00048703643d056d,0x00006af93724185b}, {0x0000024509c6a888,0x000134b558973322,0x000c33289fd2e036,0x000c18f83e236233,0x0000701f25bb0cae}}, {{0x0008b0f8e4616ced,0x0000e9e25a87dc3a,0x0004bca59cf70066,0x0000be961e3061ff,0x00002e0c92bfbdc4}, {0x0008f6d97cbec113,0x000e674bfdbe49d1,0x000c4e60d6844a06,0x0005e5120f5b522a,0x0000720a5bc05095}, {0x000f09439b805a35,0x000376242abfc0c3,0x000c229346e84e8b,0x000f0ec691417f35,0x00000e9b9cbb144e}}, {{0x000ad48ffb5720ad,0x0006bdbf90d0efbb,0x00035543bfee8191,0x0007bd8d48131526,0x0000221104eb3f33}, {0x000e9bd55db1beee,0x000370a723fb98de,0x000c68d791c9c3ab,0x0003cde44a8f1bf1,0x0000366d44191cfd}, {0x000c1743f2bc8c14,0x000fcb5856c3b9e3,0x0008a7fb972eda26,0x0003244ccb82f0e6,0x00004167a4e6bc59}}, {{0x000b9d2876f62700,0x000400e7668eb643,0x0001fc06845d1d9d,0x000246a1b4b43032,0x00007938bb7e2255}, {0x000e2665f8ce8fee,0x00014e880d62cc2b,0x000f364eeee967ff,0x000d2f6f12e6e7e2,0x000034b33370cb7e}, {0x000591ee8681d6cc,0x0009ced85a753cdc,0x0008808883ce0210,0x00065e4ed7485c15,0x00001176fc6e2dfe}}, {{0x000f6cd05b9c619b,0x000f4b2a58480b4a,0x000be94dc42ddfc9,0x0005f343d4fa502e,0x000008fc3a4c677d}, {0x0000e28949770eb8,0x0002aacf440a3db9,0x000ed7879b98fbcc,0x00006b621354ffed,0x00001f6a3e54f269}, {0x0004c199d30734ea,0x000b631165cd660a,0x000759829540c085,0x00000d1e2333e23f,0x00004f2fad0116b9}}, {{0x000eb24194ae4e54,0x000511857ef6c44b,0x00068d04985f541c,0x000f7aba61e6b2d3,0x0000445484a4972e}, {0x000cd91db73bb638,0x000aafc129c08962,0x0003b61689e60577,0x000ee816f619b39f,0x00003451995f2944}, {0x0002fcd09fea7d7c,0x00094b0935cf6915,0x0007285c404a816c,0x00093b7258e9aaa4,0x000010b89ca60428}}, }, { /* slot=17 [{1,2,3,..,8} * 16^(2*17)] * G) */ {{0x000947499718289c,0x000c524533f263d5,0x0004c3ef1512ebf8,0x000518e0262bfcb1,0x000020b878d577b7}, {0x000941be5a45f06e,0x000ed6d9c5f65753,0x0002ff51b6d07cae,0x0004da911776b9c7,0x000017d2d1d9ef0d}, {0x0002af18073f3e6a,0x00019d752106927f,0x000ca60022fd3fe5,0x000c6a722e3b72c3,0x000072214f63cc65}}, {{0x00037f405307a693,0x000d72f336795b4e,0x0003761099aba714,0x000cbc9d6fbd0a77,0x00005fdf48c58171}, {0x000db7b9f43b29c9,0x0004a4f518f751d9,0x00012f9dc4d60582,0x00045b0f2c072bd3,0x00001f24ac855a15}, {0x000608328e9505aa,0x000d10c1420ee24d,0x0006fb25a24748c1,0x00095e6c7ffe45c0,0x000000ba739e2ae3}}, {{0x000e98de5c8790d6,0x000d345c2a2df592,0x0009b49922e5bfb7,0x00078f3115a3b60f,0x000003283a3e67ad}, {0x000426f5ea88bb26,0x000d984973bfbae4,0x0006694e50360679,0x000d2265c9f030c2,0x000072297de7d518}, {0x00041dc7be0cb939,0x0004d8b633080482,0x000228930832f19b,0x0001945d3dfc90d0,0x000005e129684627}}, {{0x0002eeb32d9c495a,0x000fcf12bb97cba8,0x0003b5d1e0ceefc8,0x0008d9bb02dabae9,0x000039c00c9c1369}, {0x000fbbc8242c4550,0x000ecd03081d9adb,0x0005c8df92bcc80c,0x000ce4c843566a6f,0x000078cf25d38258}, {0x000e6b8e31489d68,0x000ab9c2bf08715a,0x00004efa05aa851c,0x000f832c9a75a97f,0x0000006b52076b3f}}, {{0x0000cfe19d95781c,0x00018966310e229e,0x0000516b39b681df,0x000612257df39d37,0x00004d57e3443bc7}, {0x000b7e16b9ce082d,0x0004c417abc29f5c,0x000bf4a7ab3407f1,0x00075ced4b36bce2,0x00007de2e9561a9f}, {0x0000d4f4b6a55ecb,0x0007f5d85db99de7,0x0003ee9a81480152,0x00029eddbc9c440d,0x00006b2a90af1a60}}, {{0x0003f4fc9ae61e97,0x0001de03f5fd1692,0x0006edd12d573528,0x0003e4aa764ae43e,0x00005fd8f4e9d12d}, {0x000bf3245bb2d80a,0x000472fb9079b77e,0x000cee7333d8301b,0x0002109c647e6f24,0x0000465812c8276c}, {0x0003beb22a1062d9,0x000753831dc164d4,0x000e2968d77065fb,0x0006790180d4a7bd,0x000005b32c2b1cb1}}, {{0x00005eccd24da8fd,0x000ac05dfef83c8c,0x000df9cd61a1cf1a,0x0001e99dbbeeff27,0x00003b5556a37b47}, {0x000ca42c7ad58195,0x0006e4333f3ccf7f,0x00040b979d321428,0x00007e1b6c29d0d3,0x000031771a485673}, {0x0000c524e14dd482,0x000541a2ba4b632b,0x00082b5af3edb351,0x00036eba3d160482,0x00004fc079d27a73}}, {{0x000938b089bf2f7f,0x0006502dfe9a751c,0x000880e4532497bd,0x0008e92ffffc09c7,0x0000124567cecaf9}, {0x00048b440c86c50d,0x000c9cc94e651dc3,0x00043e3cb91337cb,0x000cd086422f74d6,0x0000241170c2bae3}, {0x0009ab860ac473b4,0x000ee0113e4353ff,0x000bc6c4aff0911d,0x000000d4ae75060e,0x00003f8612966c87}}, }, { /* slot=18 [{1,2,3,..,8} * 16^(2*18)] * G) */ {{0x000a0cc9782a0dde,0x000b2ea718385559,0x0001ef238c551dcd,0x000613d7f62865b3,0x0000504aa7767973}, {0x0008fcfa36048d13,0x000b373899ddd9c1,0x000f92d0aa29159d,0x00019d4dc9f350b9,0x000026f57eee878a}, {0x000b2cd55687efb1,0x00062247af17b0ca,0x000f5a24675180d1,0x000306985c15a344,0x00004041943d9dba}}, {{0x0000eeba43ebcc96,0x0009c26ea9cafc3c,0x000c77ccc68d749c,0x000340fd9fa95ee1,0x00001420a1d97684}, {0x00017743a26caadd,0x00024648ab7ce4b2,0x0003fbc9e347a6b4,0x000d019cb1d4f7a0,0x000012d931429800}, {0x00067799d337594f,0x00040b23aa47b00c,0x00035ff3955e3c51,0x000a01244182854e,0x00001b4f92314359}}, {{0x000c109d89150951,0x000912de9696a3e5,0x00075f302039cefa,0x0002dae20eae43f9,0x0000239b572a7f13}, {0x000f3030a49866b1,0x000d2215f485933c,0x0001def4f6251f73,0x00023f6ab82aa405,0x00005ff191d56f9a}, {0x000ed433ac2d9068,0x000795fc98523819,0x000593eb3d2883ab,0x00036cbef4572805,0x0000020c526a758f}}, {{0x000834f89ed8dbbc,0x000f9dc7ca46c779,0x0003e1b074c8f2aa,0x0003877a9524cdca,0x000002aacc461531}, {0x0001ef59f042cc89,0x0009d8e124bb6e93,0x000ec759972c589c,0x000c50cadc8e18aa,0x0000452cfe0a5602}, {0x0000f7a0647877df,0x000270e607c9f86a,0x0001fb11c9bbc464,0x000877bab17ea25f,0x00004cfb7d7b304b}}, {{0x00043d6cb89b75fe,0x000d99c6adc8072b,0x000ee34c9f54c694,0x0005364b8c3aa373,0x000014b4622b3907}, {0x000699c29789ef12,0x00071df57190de28,0x000cc970d02b6ecd,0x0003ac5c343c857e,0x00005b1d4cbc434d}, {0x000b2615cc0a9f26,0x0002bb88dcce5b6f,0x000369a7053a4f0e,0x0002dd11301498b3,0x00002f98f7125859}}, {{0x0004a74cb50f9e56,0x000a98e8e13200c9,0x0002300f675b1ff4,0x000aaf99a2acc218,0x00003a6ae249d806}, {0x0002ae444f54a701,0x000f0a9cbd7de2e1,0x0005835de0fcfe3e,0x0004554cebf890d7,0x00001d8062e9e761}, {0x000ada85a9907c5a,0x000b591b90f62657,0x000f34b4e91a0ea8,0x0005ff38d0e1dfbd,0x0000298b8ce8aef2}}, {{0x00027953eff70cb2,0x0002a791570762a9,0x0000a7cf6a4b89c9,0x000e4859418457a3,0x000034b8a8404d5c}, {0x000a72ea0a2165de,0x000b40bcf79f6837,0x000738ae703fab07,0x000d7dc521636c77,0x00006ba6271803a7}, {0x000eecb583693335,0x000df63b5fefdc26,0x0004b22573d5a813,0x0001c6aa293aa9aa,0x000071d62bdd465e}}, {{0x0003cc28d378df80,0x000790a0fa4b4653,0x000701da5af6db43,0x0002ba4e3645ff9f,0x000074d5f317f317}, {0x000db5dab1f75ef5,0x000cf16b065f5cd2,0x000f49f085d77f95,0x0002b3d14571fea3,0x00001c333621262b}, {0x000fe55467d9ca81,0x000752b298c37a86,0x0003ac623b398b7c,0x000d98cda6d0892e,0x00004aebcc4547e9}}, }, { /* slot=19 [{1,2,3,..,8} * 16^(2*19)] * G) */ {{0x0000071b276d01c9,0x000c586c48c7012f,0x0001d6fba9e7b8ba,0x000b7925308129b7,0x00005d88fbf95a3d}, {0x00008d9e7354b610,0x000535ba85b6e0b4,0x000a58a207806b32,0x000df2cdbe63a034,0x0000173bd9ddc9a1}, {0x00000f1efe5872df,0x0002ed43918c12b5,0x0009673ae058d658,0x000a319e6ed278ec,0x000006e1cd13b19e}}, {{0x0000ad516f166f23,0x000931fab6abe40d,0x00004d088e118e32,0x00062663fe35e14a,0x00003080603526e1}, {0x000baf629e5b0353,0x00090278d0447472,0x000643bf273baa0b,0x0007b130c785f469,0x00007f3a6a1a8d83}, {0x000644395d3d800b,0x00055c901edf6f7e,0x00092c633995a8d5,0x000307e68cd78305,0x000030d0fded2e51}}, {{0x00094d1af21233b3,0x0008ef0cc4d9ce05,0x000f499a771bdbe7,0x00098686965187f8,0x00000a9214202c09}, {0x0004971e68b84750,0x000296664bbcf9cb,0x0002fa412ba09572,0x00089d95c8de7267,0x00004615084351c5}, {0x000019c0aeb9a02e,0x0000d16034caebc9,0x00059932ec55c711,0x0005dfe0e6df5016,0x00003bca0d2895ca}}, {{0x000031bc3c5d62a4,0x0003ecff07a6040f,0x00030fb54519fc8b,0x00013cd98183da21,0x00005631deddae8f}, {0x00088eb69ecc01bf,0x000ada644896f9c6,0x000f7a9fe2f0bc83,0x0008241ca2d955f5,0x00004ea8b4038df2}, {0x000d460af1cad202,0x00005a48cee832ae,0x0009f11a5f463053,0x000a463912177454,0x000024ce0930542c}}, {{0x000890f5fd06c106,0x000355d8810f21fe,0x000e8caf3eb5c468,0x000d74b827808fe6,0x000041d4e3c28a06}, {0x000fa155fdf30b85,0x0008e36372ea43fc,0x000492f844d2f716,0x0004280b2e064de6,0x0000549928a7324f}, {0x000e32a763ee1a2e,0x000b7d25ffdeaf26,0x00017f4d69ae91e4,0x000ff6abc3bd33bd,0x0000491b66dec0dc}}, {{0x0005b13dc7ea32a7,0x000cc7e16db9898f,0x000bf8d947e3d5f8,0x000e4acac0abf52c,0x000008f338d0c85e}, {0x00004a8ed0da64a1,0x000af67e2284b75f,0x000f7b7ba4ed222c,0x0008b678234a3791,0x00004cf6b8b0b701}, {0x0003a821991a73bd,0x00001df320c7ac38,0x0004777063ab27bc,0x0008a99c13d331b8,0x0000530d4a82eb07}}, {{0x000c3630e1f94825,0x000268cab535a004,0x000c84ff8b7e2d78,0x00070b9c7482323c,0x000065ea753f1017}, {0x000973456c9abf9e,0x000fc4900a8806d6,0x0008cfb850257fb2,0x000bd5b2bacf412c,0x00000db3e7e00cbf}, {0x0006fc3ee2096363,0x0007f61b5cb6b3d6,0x0003443b1a81d62c,0x000a1db0fbe04421,0x000002a4ec1921e1}}, {{0x0006259a3b24b8a2,0x000cc45afa0b85ce,0x000ba07037b8577a,0x00009bfcccbe6e88,0x00003d143c511278}, {0x00086162f1cf795f,0x0001926ee57f2f5c,0x000c063578118c86,0x0007fcf172124851,0x000036d12b5dec06}, {0x000d279179154557,0x0005cfc783a0a126,0x000f179bacd5e48f,0x000285936bdb6e8d,0x00002ef517885ba8}}, }, { /* slot=20 [{1,2,3,..,8} * 16^(2*20)] * G) */ {{0x0007974e8c58aedc,0x000fbabf041a4463,0x000980718ab9ef22,0x000a8a6e185d956e,0x00002f1b78fab143}, {0x000ebffb305b2f51,0x000ad889596b896e,0x0006d5dd25d3f938,0x0000095f0f52dc74,0x000057968290bb3a}, {0x000ab8430a20e101,0x0008d24f0ec47f71,0x000ee2eed1f39365,0x000a3e1cf7509a86,0x00007dc43e35dc2a}}, {{0x00066665887dd9c3,0x000314bb05355859,0x000f2079b1c90f9b,0x000c12fc6e08df8e,0x00007ef72016758c}, {0x00082a5c273e9718,0x000995e4efd945a7,0x000f237d3e3576c6,0x0000a990f2ed8051,0x0000044fb81d82d5}, {0x000f18c5a907e3d9,0x0001dce4c6359c1d,0x000201bb4957b337,0x000dd2eca704534b,0x00007f79823f9c30}}, {{0x0004d239a3b513e8,0x000d4b91fa8d8833,0x000590bd33c13670,0x000d9b412b54136f,0x00000a4e0373d784}, {0x000c1ff068f587ba,0x0004e0050c8de6a9,0x000ded5be7082789,0x000d6f03cbf99557,0x000064a9b0431c06}, {0x0003d6a15b7d2919,0x000a0d53a82352eb,0x0009a45d47b0b4f6,0x000346c7156ce438,0x0000071a7d0ace18}}, {{0x00072daac887ba0b,0x00005bfa562eed30,0x0000ef768b012629,0x0007e9ccf543002c,0x00002c3bcc7146ea}, {0x000c355220e14431,0x0000709b15141cc0,0x00009d5f360d6595,0x00055d39af5621b2,0x00007c69bcf76177}, {0x0000d7eb04e8295f,0x000252f50f37d07f,0x00071798d710db18,0x000a51de951a9a31,0x00006f5a9a7322ac}}, {{0x0001000c2f41c6c5,0x000c10cfefb9b8ba,0x000cc51c9fc49f79,0x000afca4efa47703,0x0000494e21a2e147}, {0x0009d4eba3d944be,0x000408078af9ee72,0x0007869c038d9e09,0x0003b244525567a4,0x000002ab9680ee8d}, {0x00048a85dde50d9a,0x0004e0fb9a249efa,0x00091ef6d9219a22,0x000bb34fa091f1dd,0x00006b5d76cbea46}}, {{0x0007556cec0cd994,0x0006f5cd01dba885,0x000f42b4776472dc,0x0007354af0169148,0x00000ae333f68527}, {0x000941171e782522,0x00074036936d3e0f,0x0000fcc746f1e6ae,0x000313e408b3ea2d,0x000016fb869c03dd}, {0x000e199733b60962,0x000b4d8abe133288,0x000991d03e24fc72,0x000d0754811f7ed0,0x00003f81e38b8f70}}, {{0x00010fcc7ed9affe,0x000a12465874b7f9,0x000b0c4704545cb8,0x0000993a8397ed24,0x000050510fc104f5}, {0x000b7f355f17c824,0x000c3d74299a40ad,0x000bf8eaf774b923,0x000dc3dd57c3e8bc,0x00000ad3e2d34cde}, {0x000c0fc5336e249d,0x00019c331cfd96f0,0x0009eefe1c745ede,0x0001ebef2d6fd000,0x0000127c158bf0fa}}, {{0x00097c422e9879a2,0x000d452ca3647f61,0x000b4eaccba44add,0x0004f689b413fc14,0x0000354ef87d07ef}, {0x00028fc4ae51b974,0x000d3744dfe96dea,0x00073848a81d9973,0x000df956240680b8,0x00004ed82479d167}, {0x0003b52260c5d975,0x000fceb41b0b8fee,0x0009f6653c50352e,0x000236d8808ac30a,0x0000302d92d20539}}, }, { /* slot=21 [{1,2,3,..,8} * 16^(2*21)] * G) */ {{0x0003c1a2bca4283d,0x00091a1863dd9781,0x000268fa86ed62f0,0x000ae4caec7bcb8c,0x000010e5d3b76f1c}, {0x000c6fb6e4e0f177,0x00029a4bd6a932db,0x00087af6e804e1bf,0x000d0605e1966d47,0x00000edc5f5eb426}, {0x0003bfd653da8e67,0x000ec24a9f641545,0x0003578a23e9dc1e,0x000ba72bf87263b0,0x000045b46c51361c}}, {{0x00002abf314f7fa1,0x000dc8e8cf450a94,0x0003a8be84e257f1,0x000713b1dbbd54b2,0x00002177bfa36dcb}, {0x000d4ddd8a7fe3e4,0x0005676620e30ce9,0x00030e9958ab1364,0x00029df4b594f7bb,0x00005c1c0aef3212}, {0x00081bbcfa79db8f,0x0001ec25f59b3370,0x000c832487604881,0x000b5bb087a76659,0x00004ae619387d8a}}, {{0x000bf6aa5344a32e,0x000b4b41b40788dd,0x000a130d607d88ea,0x0003e035eb0eb974,0x00001a00d91b17bf}, {0x00017e44985bfb83,0x0002a71963136611,0x000425904bfce046,0x0003d6483ac3448d,0x000075685abe5ba4}, {0x00060933eb61f2b2,0x000a8c9ff49526e9,0x000af66569543d0f,0x000e6aadf7275107,0x0000135529b623b0}}, {{0x0000dbd7add1d518,0x00088cfc11f1118f,0x000114759b979f78,0x0003a018732e1f07,0x000079b5b81a65ca}, {0x000716bce22e83fe,0x00019e80985c1f5c,0x0004254aaeb42beb,0x000a613ec9da6371,0x00005972ea051590}, {0x0004ac20dc8f7811,0x00094ac4d4fa80fd,0x00033604349a9ad2,0x0003bdbc01b2d64b,0x00004f7e9c95905f}}, {{0x00074bbc5781302e,0x0003989addc0f626,0x0003fbd9c6d8520f,0x0008e4c8c2999ae5,0x000031993ad92e63}, {0x0008443d355299fe,0x0001cdbebead771c,0x0001a494668bcd3b,0x000adc88092499ef,0x00001942eec4a144}, {0x000c5319ae234992,0x000910cea3e927da,0x00053c11222c1b3d,0x000ca75553ce4942,0x00002a0a65314ef9}}, {{0x0007937ff7f927c2,0x0000617d0a6352db,0x000155af76db741f,0x0002ded5982f3a21,0x00004cf6e218647c}, {0x00061acd3c1c793a,0x000ac5a35bc3bcf3,0x0008cda6ab2f9ebc,0x0001a1360e860e9a,0x0000055dc39b6dea}, {0x0009227cc28d5bb6,0x000bc774dffabb11,0x0004a32c8907e24e,0x00024b6a83c78cee,0x0000121a307710aa}}, {{0x000b5d5e9f034a97,0x000093034bc2de4d,0x000551d3b1e153fc,0x000e52d460546919,0x0000333fc76c7a40}, {0x0009713ec77483c9,0x00077b82b96afd65,0x000097bcd388bfe0,0x0003a9b289e28231,0x0000527bb94a6ced}, {0x000d992a995b482e,0x0007c6e383801563,0x000f64d8e53405d0,0x000a9f7485035de2,0x00006b89069b20a7}}, {{0x000aa0416270220d,0x000faf9245b4e812,0x000072ef05995a89,0x000eb73ffadc4ce5,0x000023bc2103aa73}, {0x0002fa8cb5c7db77,0x000f8c734c155408,0x0006e7a57e068686,0x0009bcf29e6c8d9f,0x00000473d308a763}, {0x000e792603589e05,0x0001246dcc492cae,0x000601a94f2b4b42,0x000341a02a1ef74e,0x0000102f73bfde04}}, }, { /* slot=22 [{1,2,3,..,8} * 16^(2*22)] * G) */ {{0x0008b9ab7f5745c6,0x000ee5787c690eb1,0x000df7afa9023a8a,0x000013db72712da2,0x000036597d25ea5c}, {0x0004dae0b5511c9a,0x000292bffff06a2b,0x00055042347ac860,0x000a12d981f375df,0x00003f6bd725da4e}, {0x000d8d7b106058ac,0x0009e6fc6905f734,0x000202932dd94057,0x000d6d06466f8f99,0x00007b7ecc19da60}}, {{0x0002373c695c690d,0x000660642906e78c,0x000ae12bd2dd252e,0x0003956951d44444,0x00004235ad760174}, {0x000e4a51a77cfa9b,0x00054e7a386506da,0x000f2d82db822636,0x000caba09bbffcd8,0x000003bedc661bf5}, {0x0008cb0d078975f5,0x000549189f298625,0x0002e36ee4492942,0x00066a1a0cab423e,0x00000e7ce2b0cdf0}}, {{0x0004643ac48c85a3,0x000f43c6139adc49,0x000ae94d48fd361d,0x000674a09db17dd3,0x0000666e0a5d8fb4}, {0x0006fedfd94b70f9,0x00051c1fcba2dfea,0x000f2fab89f130c0,0x000eeb54882d47e7,0x0000615256138aec}, {0x000bf64e4870cb0d,0x000f0aa458b6b2ab,0x0005e8985dcd65bc,0x000dee49abe4eba7,0x00007f0bc810d514}}, {{0x00006ba426f4136f,0x0009e57e03035b90,0x000f463c288d6736,0x000dbf5cbc8dfd94,0x00000d1f8dbcf8ee}, {0x000c9dad737213a0,0x000ba2ef72e9883a,0x0003ec69579ff6f8,0x000ab75311e2edd4,0x00001d3a907ddec5}, {0x000693313ed081dc,0x000ad851b3480ba1,0x00030321cb29329f,0x000fde30128013c0,0x000000011b44a31b}}, {{0x000fa06c3fc66c0c,0x0008e4dd60dd23fd,0x00068e4d715d40e3,0x00057e17ae38b382,0x00003ac48d916e83}, {0x00061f696a0aa75c,0x0005c5852bd6a165,0x000a7966adc1bf72,0x000102611a8dd7f9,0x000063d988a2d285}, {0x00020753afbd232e,0x000b8fdd8f683001,0x0004e72b91e92bce,0x000a066f81669b38,0x000033fad52b2368}}, {{0x000649c6c5e41e16,0x00030333f7735540,0x000305e7460af864,0x000dca7b2acfcd2f,0x000016c0f429a256}, {0x000cc8d0c422cfe8,0x0007b05a13acb8d2,0x000cf6a56f072b4f,0x00071e2a3feb6e6e,0x00003cc355ccb90a}, {0x00069443903e9131,0x000cb7a5637cee9b,0x000aba9244b8a494,0x0007568c87cd1a4b,0x0000631eaf426bae}}, {{0x00090410da66fe9f,0x000526c16e5a6b3e,0x000ef9bf8385dd4b,0x00019b5bc3d97611,0x00005599648b1ea9}, {0x000975b9a3700de8,0x000fbe2f8055247d,0x0002e45de17280c5,0x00080b553658f273,0x0000431f2c7f665f}, {0x00026344858f7b19,0x0002fa1ea514ad60,0x000090a9d714ab35,0x0003b268900441a2,0x00007b04715f9125}}, {{0x000dbd28acf6ae43,0x0008b7d5c7ab483e,0x0007eb2c4486357c,0x000583fc0404769b,0x000059b37bf5c2f6}, {0x0006c280c4e6bac6,0x000dd6d1d9b0bb37,0x00050bf944970ed3,0x000e223b09a95584,0x000048d0acfa57cd}, {0x000f26e47dabe671,0x00097622f3a37b60,0x0009960394f1d1a1,0x0003bdb4208ce7ee,0x000016234191336d}}, }, { /* slot=23 [{1,2,3,..,8} * 16^(2*23)] * G) */ {{0x000499def6267ff6,0x0007b742c0843b9e,0x0009a4f2b17772ca,0x000500623a0153fe,0x00002cdfdfecd5d0}, {0x00099cd61ff38640,0x000c3063625a0dd4,0x000dd73dc329cd9b,0x000923151e2d8023,0x00004a25707a203b}, {0x0007668a53f6ed6a,0x000581dd170a12ab,0x000ae20161304242,0x00049fc4000144c3,0x00005721896d248e}}, {{0x000e5517fd181bae,0x0009f2bb963b40b6,0x0002064625902262,0x00013da5509bce93,0x0000578edd74f63c}, {0x000d5091a1d0da4e,0x000a7b5fe3e08285,0x00019393b34baa6f,0x00030fd63e5177ce,0x000003c935afc4b0}, {0x000276c6492b0c3d,0x000c4dfe205fc997,0x000d623a3c47ccc2,0x000c7a2dcd29b84d,0x00003ec2ab590288}}, {{0x0000d27be4d87bb9,0x000eb61391aeda1a,0x0003cb9b83a98b4d,0x000cace99a0ddd07,0x00002dd5c25a200f}, {0x00013a09ae32d1cb,0x000df40f5c2d5a72,0x00081eab290f2b87,0x000ac5e0baea4c6e,0x00000e1bf66c6adb}, {0x000bd5e9792c887e,0x00018cb926d5de2a,0x000aae5f1e1a0200,0x0008f5fbfba69cdb,0x0000730548b35ae8}}, {{0x000551a3cba8b8ee,0x0001db2115f16c43,0x000b8c385065a26f,0x000b8ca760f4f52a,0x00003043443b411d}, {0x000b094ba1d6e334,0x0007709353f19805,0x000622702bbf3ef1,0x00045dd423f06cb0,0x0000585a2277d878}, {0x000a5f8233d48962,0x000b5ec78257fa18,0x00073e41ff6698c4,0x000981fa78e6fa53,0x00007656278950ef}}, {{0x0003cf59d51fc8c0,0x000fd0506b6f238c,0x000b570e8f9bedd2,0x00046a626bf109fa,0x00003f4160a8c1b8}, {0x000073a3ea86cf9d,0x000b707155fdce17,0x0001838a8e3a8cfb,0x000f6164853e7fc3,0x000028bbf484b613}, {0x00012f5c6f136c7c,0x00007f6dd11bef26,0x0003de6f33afead1,0x000f75d527e9ad21,0x00001e79cb358188}}, {{0x000436c3eef7e3f1,0x0007ffe9e10f8013,0x000cf9defc828b6a,0x00038317ff908e5b,0x000065d7951b3a3b}, {0x000953d8f5e08181,0x00044299dded977e,0x00064525e584a50c,0x000f2f4dc6c2d0c8,0x0000478ab52d39d1}, {0x0006a4d39252d159,0x000bc871ac80766a,0x0006c1c96fe5dde1,0x0002214b82c6b40a,0x000016d87a411a21}}, {{0x000d7e5a42066215,0x000cd0c5a24c1b3b,0x0006f994b7879be3,0x0008ca657c05db1d,0x000028f87c8165f3}, {0x0004d5e2d54e0583,0x000d72ebd99fafba,0x000ee9778fe21faf,0x0006dde497ac2736,0x00001f990b577a5a}, {0x00044ead1be8f7d6,0x000ebacea798fa33,0x00020de0527d1e50,0x0006d3e77c6569e5,0x000045882fe1534d}}, {{0x0009345d757983d6,0x0001117aa11a6666,0x00085e128f62b6ed,0x000f6dd7ddd18579,0x0000688fe5b8f626}, {0x000c9929943c6fe4,0x00061a38392a2d8a,0x000ec89af3b5f9f1,0x000f0742699db13b,0x00007dcf843ce405}, {0x0000d6484a4732c0,0x000fdca5632996c9,0x00015dc6e1d52143,0x000191bb3be28c39,0x00006739687e7327}}, }, { /* slot=24 [{1,2,3,..,8} * 16^(2*24)] * G) */ {{0x00082014385675a6,0x00030aafda9e8ef7,0x000cdfa8cba2649f,0x000c0b34cd1eb505,0x000046115aba1d4d}, {0x000dcc9dc80c1ac0,0x000f41b38a436a66,0x0005dbd7c697a05c,0x0007daba7ebf3be9,0x00007da0b8f68d7e}, {0x000f1953c3b5da76,0x0007321119e9bd40,0x000eb259601dac6f,0x0004b4b03cc6021f,0x00005a5f887e8367}}, {{0x000301cf70a13d11,0x00015350dd0c48f6,0x0004bca47ecfceb8,0x0001434f70297d4a,0x00003669b656e44d}, {0x000628d3a0a643b9,0x00000e6c320649e9,0x000c2dec32b5c3cb,0x000c70c9b5302897,0x000043e37ae2d5d1}, {0x000e3f06eda6e133,0x0005199a13ac0387,0x000626381167301d,0x000e9bebd5ad8f83,0x00006a21e6cd4fd5}}, {{0x0006170a3046e65f,0x0002a00d23524f1c,0x000c82b75558712a,0x000ff5769dbbd3c8,0x0000586bf9f1a195}, {0x000129126699b2e3,0x00047708d1301ef4,0x000182b0bd71d308,0x0008b36325432d01,0x000045371b07001e}, {0x000b088d5ef8790b,0x000dc610937e5a6d,0x0001a16eb85278f0,0x0002179ac0349d26,0x00000eafb03790e5}}, {{0x000555c13748042f,0x000e6820baa11960,0x0003486d0c219a41,0x000c6611c81f7387,0x0000309acc675a02}, {0x0000805e0f75ae1d,0x000e32662cc30514,0x000a92396dec02fb,0x0005bb32cebdf1ee,0x000044ae3344c543}, {0x000289b9bba543ee,0x0009d5ac971429cf,0x000f9360aaf3760e,0x000678f1d82e5c64,0x000062d5221b7f94}}, {{0x000c299c18d0936d,0x0006c8a0c1a0c524,0x000b4a8631c86bb5,0x0004562a375052ed,0x00005c0efde4bc75}, {0x0005d4263af77a3c,0x00011fee9144d758,0x0009f7193ddfae7b,0x0002037a50670805,0x000014f29a538392}, {0x00017edc25b2d7f5,0x000db99b53040df7,0x0003ed4c6221f970,0x000093eda9234b7c,0x00005e72365c7bee}}, {{0x000bfc074571217f,0x0005d0694d95b575,0x0004191e33377967,0x000eabc9a0a37bbf,0x000077f1104c47b4}, {0x000339062f08b33e,0x000e5df9f32be7d9,0x000f9ebdfd5b9659,0x00049b7acff3dad1,0x000070b20555cb73}, {0x000113c555112c4c,0x0003a9a881fcdbe5,0x000e503b47668842,0x000404a446677855,0x00000e34398f4a06}}, {{0x000d22d93ecebde8,0x0004127822f07b67,0x00005b6d8d09b3e8,0x0002372743fa61fb,0x00005e5405368a36}, {0x00030b093e4b1928,0x0000e73f3f640189,0x0003395d6f7de3e1,0x0009c3ef43217da7,0x00006f8aded6ca37}, {0x0000123dfdb7b29a,0x000e1a21ab291e34,0x000de6949e487b97,0x000de97f9967d02f,0x0000780de72ec8d3}}, {{0x00028545089ae7bc,0x000cf1c7f4d060ae,0x000a4811b8388dde,0x0008ce438ac15510,0x00000eb28bf67192}, {0x000feaf300f42772,0x0002a2a8c41aa671,0x00073732928f72eb,0x00087a629a17fd79,0x00001defc6ad32b5}, {0x000bbe1aef5195a7,0x00077917b15edaf5,0x000ae5da2e148c12,0x00028672991f7fb7,0x0000467d201bf8dd}}, }, { /* slot=25 [{1,2,3,..,8} * 16^(2*25)] * G) */ {{0x000e919a74ef4fad,0x000ecf6a308a295f,0x0009a47b013a827b,0x000c797964e01d30,0x000071c43c4f5ba3}, {0x000ef4bd567ae7a9,0x000b2d64498bdbc1,0x000c1f4ec83f624c,0x0004001e41064d22,0x00002ef9c5a5ba38}, {0x000d6df6fa9e74cd,0x000bce4af267ab6f,0x0001ef990ef18278,0x000f2938255b3d0f,0x00005a758ca390c5}}, {{0x00072710d9462495,0x000d2d57d5003a2b,0x0000b487ca3aa8c6,0x00072ece3d400bfa,0x00002dbae244b3eb}, {0x0000918b1d61dc94,0x000469a8130668ce,0x000fe8aad38ded36,0x000d43fd4e6a829a,0x00000a738027f639}, {0x000f4a2f57ffe1cc,0x0000de1839843980,0x0009fb15fd00670d,0x000a69c105c3f4a4,0x00002698ca635126}}, {{0x0005318832b0ba78,0x000f7925cff8be76,0x0000291fcc381831,0x000eb0708a81b91a,0x00001fb43dcc49ca}, {0x000d702f5e3dd90e,0x00018e4d253862e3,0x00024da96a9e3f09,0x00033325e773ef60,0x00003c004b0c4afa}, {0x000946ac06f4b82b,0x000a5a806c4f39aa,0x0006cd47871ca284,0x000d2173ed3265fc,0x00006b43fd01cd1f}}, {{0x00075d4b4697c544,0x00048df0fffbfc7a,0x000a46785a15fdf8,0x000f7142868b9eba,0x00005a68d7105b52}, {0x000742583e760ef3,0x000b9ee0ab990b5c,0x00072b923f75dc52,0x000d9f0bf1427c20,0x000073420b2d6ff0}, {0x000cf6cb9e851e06,0x00013c62238c4af2,0x0009fbf3738f5939,0x000bc9eda8ab8969,0x00003db5632fea34}}, {{0x000eee2bf75dd9d8,0x000f6396759a5f46,0x00099e72730d17b1,0x0005f131bf2d1314,0x000004321adf49d7}, {0x000990b1829825d5,0x000873e9a89912e4,0x000c704af8edeaeb,0x0002b0eeef03d394,0x000059197ea495df}, {0x00016019e4e55aae,0x0007a7e2f92e904e,0x000f159aa4e77b43,0x0000cc0c7ce2dc16,0x000045eafdc1f4d7}}, {{0x000401858045d72b,0x000a2cf2f0651698,0x000b222dc64c22fa,0x000dade941a36656,0x00005a5eebc80362}, {0x000e4624cfccb1ed,0x00092bd5c0395b60,0x000c0481c959dbc2,0x000d94031a09d1dd,0x00003f73ceea5d56}, {0x0007bfd10a4e8dc6,0x0007e44c9b339b7a,0x000557aefabe5700,0x00018db60c1207f1,0x0000260588912662}}, {{0x000704a68360ff04,0x000de7661e6f459f,0x0002873551c3d93f,0x0005d57831b2a731,0x000054ad0c2e4e61}, {0x00018e3cc676e542,0x0009303ceccad4c8,0x0004129f085e422c,0x00043b8ec07cccab,0x00000dedfa10b244}, {0x000b67d5b82b522a,0x000469fa5c1ebee3,0x000ec19fd336f163,0x0009408a5b4d2f26,0x000062ecb2baa77a}}, {{0x000d795261152b3d,0x0007d0eddd7d1e5e,0x00096b4c71496235,0x000d8be7482c8d0b,0x00002e59f919a966}, {0x00072836afb62874,0x0008579e104a5920,0x000630a14a5fcd5e,0x0003f985aad01adc,0x000061913d507566}, {0x00062d361a3231da,0x00032942002700dc,0x000f9594cefa4758,0x0005d5c02d801513,0x00003ddbc2a131c0}}, }, { /* slot=26 [{1,2,3,..,8} * 16^(2*26)] * G) */ {{0x000c0ff9ce5ec54b,0x0006b8c2f130d9ad,0x0000f89515039c2a,0x000b36b028007c7f,0x000078968314ac04}, {0x000a57a22796bb14,0x000b79b07da21f3a,0x0001a0391c883aba,0x00005f9e54be2183,0x00005ee7fb38d832}, {0x000dfdcb41446a8e,0x000a9434937f9538,0x00063c8c78a5acfd,0x0000d0946af908d2,0x000061d0633c9bca}}, {{0x00044935ffdb2566,0x00089780b68bb637,0x00053eec03c5bd6b,0x000d7f56f1b32805,0x00006e965fd847ae}, {0x000328bcf8fc73df,0x0005da6f037fcada,0x0008c2a909ee8469,0x0007bdc637fb4db3,0x00005b23ac2df806}, {0x0002b953ee80527b,0x000aafade6d8d9ad,0x00050e82cfe88f19,0x000dedc0e7117041,0x000079b9bbb9dd95}}, {{0x000355406a3126c2,0x000a868c8c393ebb,0x0005b97a82d26383,0x00021476c0c6429e,0x00005065f158c9fd}, {0x00097dae8e9f7374,0x000f8cfbb0816d19,0x000d445f0aa032a2,0x000b834cd6cba126,0x00001ba811460acc}, {0x000169fb0c429954,0x000acd76ecf67708,0x0000e645bae14600,0x000faf22eaab98a7,0x00003981f39e58a4}}, {{0x000b8a7559230a93,0x0006960e6f45d18f,0x0004a93cb51d168f,0x000d0fd3a85a9451,0x000038dc083705ac}, {0x0005dfa56de66fde,0x000002c40483ac84,0x0007b4f632e152a5,0x0001b65e9d2e163c,0x000030f4452edcbc}, {0x000d2782c5759740,0x00069f99cbecc856,0x0000ea4e71fa1345,0x00024698844fc73c,0x0000632d9a1a593f}}, {{0x000b6b15b807cba6,0x000dfbc54f0d7f6b,0x000e29670b1823c7,0x0004a57bb1d97036,0x00000b24f48847ed}, {0x0009fd11ed0c84a7,0x000810d9f693abf0,0x0007cf877963f071,0x0004ba221908c2d5,0x00003a5a7df28af6}, {0x000ad4be511beac7,0x00075ed26ccf2dcd,0x00005f9a65a45380,0x0001f63e19cff9f0,0x000034fcf7447548}}, {{0x0007e04c789767ca,0x000cb38d9467dc19,0x0003f95fa8b8714d,0x00063f755de88828,0x00003d3bdc164dfa}, {0x000b1dab78cfaa98,0x00067190b72f2a5b,0x000a92608e5ceda2,0x00074b09309c9110,0x00000119a3042fb3}, {0x0002d89ce8c2177d,0x000f66895d0c167a,0x000282a2b0669da5,0x0000a73f56598e5b,0x000056c088f1ede2}}, {{0x000d3d1110a86e17,0x000320b75b2fa336,0x0005072988d7f388,0x0008b87f91533762,0x000009674c6b9910}, {0x000b5fac24f38f02,0x000febae30cbd581,0x000acf92f0a90be9,0x000038f9a2169028,0x0000038b7ea48359}, {0x000ef82199316ff8,0x00082eaa78d4f9f4,0x000aef31742f49d2,0x000eb650971a5ab5,0x00006e5e31025969}}, {{0x000c62f587e593fb,0x000deca5d3e71b16,0x0004cc3e6d4999ed,0x000dba8b491c1e01,0x000008f5114789a8}, {0x0004fb0e63066222,0x0008987acba3f330,0x000c1061a3fb3506,0x0008620bd1924778,0x00003058ad43d183}, {0x000c0ffde57663d0,0x00038a22ea610323,0x000c994f9a05c3df,0x000dc99bdc78abda,0x000026549fa4efe3}}, }, { /* slot=27 [{1,2,3,..,8} * 16^(2*27)] * G) */ {{0x000d5a461e6bf9d6,0x000fc7777a581741,0x000474d3d92305b3,0x000e0ffd45574a26,0x00001926e1dc6401}, {0x00068549af3f666e,0x00004f14a0ea5db4,0x0004ba0c47d77fcf,0x0003c853df23ff7a,0x00003a10dfe132ce}, {0x000f4e8aea17cea0,0x000463a1fc1fde07,0x0001f2c0f12fd515,0x0005d15175322fd3,0x00001fa1d01d861e}}, {{0x000055947d599832,0x000da37f15520cc8,0x000e0593201e4656,0x000cf3399f6f7744,0x0000773563bc6a75}, {0x000cac00d1df94ab,0x000ddd1080de938d,0x000dd5e2622e712b,0x00001e57f13e93ef,0x000073fced18ee9a}, {0x0001e90863139cb3,0x00067c5a03ecd06b,0x000d638932a493da,0x0004f448d77cec8a,0x00001f426b701b86}}, {{0x0009264c41911c01,0x000b817a22c25efc,0x00030f1447f1a3b7,0x000b0905875da6bf,0x00004e1af5271d31}, {0x000e35c891a12552,0x00053575e9c76f17,0x000d9b723eb76b81,0x000e438fa83406f0,0x00000b76bb1b3fa7}, {0x0008c1f97f92939b,0x000cbd444ab6e08b,0x0009bb8017be6771,0x000a95522e564639,0x00007b6dd61eb772}}, {{0x000dc1e850f33d92,0x0004f608cd5cfb7a,0x000dfc5bdb7998fa,0x0002f4fad962dbd8,0x0000703e9bceaf1d}, {0x0000abf9ab01d2c7,0x000dc40143b18573,0x0000cbb28116fb76,0x0006afe866cbe65a,0x000053fa9b659bff}, {0x0004c8e994885455,0x0006665aed4e56c1,0x000cd65af1843a5d,0x0001f50181bb73eb,0x0000398d93e5c4c6}}, {{0x000bd16733e248f3,0x0008715bf0a5f1c4,0x00010b0376bd9e12,0x0001b13d43f8cf0a,0x000053b09b5ddf19}, {0x00077c60d2e7e3f2,0x000a030828bb1c38,0x00039ef1383b34aa,0x0000577283e26e77,0x0000699c9c9002c3}, {0x0006a7235946f1cc,0x000b5cce5d97df30,0x0001b4e975921718,0x000d90728cdd2478,0x000051caf30c6fcd}}, {{0x000ba7427674e00a,0x00070a17a7bf3a60,0x000f3324cc630e85,0x000fdaa3758563dc,0x00005504aa292383}, {0x000af99a18ac54c7,0x000dcc51cb30f737,0x000ce10cc7903378,0x000e99a2b89bc334,0x000012ae29c189f8}, {0x000ec0cb1f0d01cf,0x000cc3a34f7aea99,0x00009c4e220dd1ef,0x000a5ea55ca7521d,0x00005fd14fe958eb}}, {{0x000c2ddf2845ab2c,0x000b10a7fe993b5d,0x000002e346069491,0x00074d14daaf3d64,0x0000093ff26e5864}, {0x0002fe5ebf93cb8e,0x0005136d4565f3c4,0x00084220e8bedfa8,0x000d128e0f0859e8,0x00007dd73f960725}, {0x000d24fe68059829,0x00072dbaf23e5b10,0x000457ac29757306,0x00070a41367253ab,0x00002f59bcbc86b4}}, {{0x00047d429917135f,0x0001f567d03d7838,0x000e77aad1ad1b91,0x000af4a7e7748d9b,0x00005458b42e2e51}, {0x0001d560b691c301,0x0003fadd7e71e704,0x000133558585201b,0x00028b116c2e1631,0x00002aa55e3d0108}, {0x000192e60c07444f,0x0002d74421d10ed5,0x000db5c86442c54e,0x0008664352b4c82f,0x000013e9004a8a76}}, }, { /* slot=28 [{1,2,3,..,8} * 16^(2*28)] * G) */ {{0x000d8845832fcedb,0x000c9ae6bf863739,0x00074ffef7fa38d6,0x000e45e32bc0dcab,0x000073937e8814bc}, {0x000e00c9193b877f,0x00090e0dc506bbb2,0x0006de649fece3a8,0x0009e1aecf3b7c03,0x00005f46040898de}, {0x00037116297bf48d,0x00022d4f06834b90,0x000696bdc6a9d13b,0x000e835e19715574,0x00002cf8a4e891d5}}, {{0x0003fd8707110f67,0x000d37c38b5496d9,0x0002736a86dd4c09,0x0002a097cb16a4cc,0x00002049bd6e5825}, {0x0005487e17d06ba2,0x0001c3950196b2cb,0x0005978a3024d238,0x000a4f6d7659c818,0x00007a6f7f2891d6}, {0x0009fd8d6a9aef49,0x000be5b3db90b7d0,0x00019ebfd4f0ee60,0x000941d4c21b52c5,0x00006011aadfc545}}, {{0x0007926dcf95f83c,0x00061712890715f6,0x00098f7a5b7c7e85,0x000f9e0d6a1e7f39,0x00006fc5cc1b0b62}, {0x000ed0c802cbf890,0x000ca0dff6aaa63d,0x0009b6ed99fbd098,0x0000b1e624d0afdb,0x000069ce18b77934}, {0x000f5528b29879cb,0x0003cd47e9092d1e,0x00089f2352dd1aae,0x00001f1127e04421,0x000015596b3ae571}}, {{0x000739d23f9179a2,0x0003197d6ddcf462,0x0003f2148aff8312,0x0004dda1307deb55,0x00000d2237687b5f}, {0x000f31167e5124ca,0x0008bd9c745df09f,0x000ef556e50be415,0x000d138292b7d227,0x00003aa4e241afb6}, {0x000138bf2a3305f5,0x0008fa2e926c32cc,0x000549d2eb48583f,0x000a36c083ab1a25,0x000032fcaa6e4687}}, {{0x00056e8dc57d9af5,0x000ed9df0bdf27bc,0x0002efe4a33e0bd2,0x0006a5caac014de2,0x00004627e9cefebd}, {0x0007a4732787ccdf,0x00008f213e3f8320,0x00060d964e17e319,0x0000be9d5b2ecd7f,0x0000746f6336c260}, {0x000af345ab6c971c,0x000729943731f3f4,0x000344186de288eb,0x000629333596a8a0,0x00007b4917007ed6}}, {{0x0005fb5cab84b064,0x000d289f3bc142d8,0x000b15ce0c497810,0x000fd7b476adc447,0x0000122ba376f844}, {0x00041b28dd53a2dd,0x0005bdf42fc3f543,0x000dd2f8f4aa1790,0x000d37d0ff592d94,0x00001d03620fe08c}, {0x000232cda2b4e554,0x00042115d187fc20,0x000dd479d99ed0fd,0x000ec4c2eabb4be7,0x000002c70bf52b68}}, {{0x0007ec4b5d0b2fbb,0x00090074882caa28,0x0001d0815c415c57,0x000f5e0e044a61ec,0x000026334f0a409e}, {0x000532bf458d72e1,0x000e07cb73cb5ace,0x000e8bbde75be768,0x0003a0356cf7d94e,0x00006b0697e3feb4}, {0x0008f04adf62a3c0,0x000ef076da45db6c,0x0009f0d2a93ef000,0x0002fae9c9cb9584,0x00001cc37f43441b}}, {{0x000f565a5cc7324f,0x000c0e506a922508,0x000c45ac19d061c4,0x000314afb18abdb5,0x00006c6809c10380}, {0x000656f1c9ceaeb9,0x000f818e5656ad76,0x00044c23341c5b15,0x000683826e728328,0x00003a346f772f19}, {0x00055112e2da6ac8,0x00031b1e851edd2d,0x000ec67262e9bd03,0x000c5d0960746dd8,0x000005911b9f6ef7}}, }, { /* slot=29 [{1,2,3,..,8} * 16^(2*29)] * G) */ {{0x00039983f5df0ebb,0x0008f512c4cacc13,0x000bb398e1c0f375,0x0000c622cf1130a0,0x00006b3cecf9aa27}, {0x0009acf3512eeaef,0x000d31cc1cb49534,0x00099a688d20c141,0x0002d1724180c07a,0x0000555ef9d1c64b}, {0x000770ba3b73bd08,0x00008a3afbf0c36a,0x00040946f2624aef,0x000749d5737ff98b,0x0000675f4de13381}}, {{0x000c52036b1782fc,0x000816cad83b40e2,0x000964073e64816c,0x000c520d0dcbdd96,0x000013d99df70164}, {0x000ff6d93bdab31d,0x0000f9d652dfea12,0x000abe94870725d8,0x0003c43019c4ff39,0x000060f450b882cd}, {0x000b5ec321e5c0ca,0x000c9d719bfa2014,0x00050023a04fcb69,0x000ac804e5f1c187,0x00001c06de9e55ed}}, {{0x000f7ad6a33ec4e2,0x00038be2ee08e990,0x00032845156608f9,0x000b60d9ca143c56,0x00004cf38a1fec2d}, {0x00052b40ff6d69aa,0x00018dc4049bbffd,0x00034d989734530b,0x000ba2d5e4a5c2fa,0x000078096f8e7d32}, {0x000aaa650dfa5ce7,0x0002a48b5478ca0a,0x000003725bf9c49e,0x0001abe4f09cc7d7,0x0000373cad3a2609}}, {{0x0004634d82c9f57c,0x000e124934536b29,0x00018cdb5a1fcbfd,0x00019fc9e9c4db34,0x00000040f3d94544}, {0x000ea8fb89ddbbad,0x000bc61aeaecbf1b,0x000f9b8d9d3bcb2c,0x000a6868f58a7bb1,0x000021547eda5112}, {0x000de939fd5986d3,0x00089510a380cdef,0x000b3119b9f4272c,0x0004df4b72ba407b,0x000063550a334a25}}, {{0x0007d6edb569cf37,0x000b00ca52ee1650,0x000b6bd65d178429,0x0008f51ea7c0090e,0x00003eea62c7daf7}, {0x000a584572547b49,0x000fae2c408e09bb,0x000734f18df305c6,0x000767a60e8fa69c,0x000039a92bafaa7d}, {0x0004c713e693274e,0x0007768dbd3759d2,0x000b8ab39a5f6385,0x000c4cd70525560e,0x000068436a0665c9}}, {{0x000235e8202f3f27,0x000e264f975b0bc0,0x00038c2416c75c00,0x00089f991a4e9d5a,0x000017b6e7f68ab7}, {0x0006d317e820107c,0x00044840ae9651e5,0x00020ffc7ac52668,0x0001472c1e0a1c63,0x00005373669c9161}, {0x000814ab9a0e5257,0x00084c9cab3fc5d2,0x000b2d1eca908f20,0x0007d11afcaf5885,0x00001cb4b5a678f8}}, {{0x0004c06b394afc6c,0x0002498da5fb1b66,0x000bcad8340c88de,0x00034a24f8d03164,0x0000330bca78de74}, {0x0004aa62a2a007e7,0x000b0f071c7b16b7,0x00000be223f311e0,0x0006eac5707e4380,0x00002dc0fd2d82ef}, {0x000eff841119744e,0x000962b074724982,0x000fc953fbf9695e,0x0001cf5c58ac14fb,0x00003c31be1b369f}}, {{0x0004864d08948aee,0x000ee91ba1c6fb0f,0x0006aca15807dc19,0x000d4bb7975cdaea,0x0000330b61134262}, {0x0008bc93f9cb4272,0x0001fc7cedb98c16,0x0004ac8d7aaeb871,0x00055bb7f0e52aa3,0x000041cec1097e7d}, {0x000619d7a26d808a,0x0009e1d9e156df79,0x000ba1df27bb1fd4,0x000777d73d7c36cd,0x000026b44cd91f28}}, }, { /* slot=30 [{1,2,3,..,8} * 16^(2*30)] * G) */ {{0x000048478f387475,0x000f49cbecb3c51f,0x00099f2055b25dbc,0x000a5d69aab1244d,0x00002c709e6c1c10}, {0x0007f29362730383,0x000ffebca8a2ce1b,0x000fd413144b5279,0x000610fdafc778ab,0x00007deb10149c72}, {0x0002af6a8766ee7a,0x000045553cd0ecb6,0x000f0be4b566cbec,0x000e2ea588001380,0x000008e68e9ff62c}}, {{0x000d500a4bc130ad,0x000493d0bd49c34a,0x00000a89be8d38db,0x0003b09a25c3d985,0x00002f1f3f87eeba}, {0x000d09d50ab8f2f9,0x0008dc55923df2f2,0x0003766cb9acb921,0x00019f54a8f34267,0x00004cb13bd738f7}, {0x00048c75e515b64a,0x000badb4a9038f78,0x000f751b50a59501,0x0002ee8c20d313f3,0x000019a1e353c0ae}}, {{0x000c7560bafa05c3,0x000a0c6e55e617d1,0x0000d66473b3e1a0,0x0003486e3529718c,0x000041546b11c20c}, {0x000172cdd596bdbd,0x0004398eefc40b42,0x00044109b593e045,0x000ae349fb15347b,0x0000736bd3990266}, {0x00032d509334b3b4,0x0004b60816573855,0x00025c837546fd11,0x000ab5ccc5f5f304,0x0000412295a2b87f}}, {{0x00099b88f57ed6e9,0x000266df8c82519c,0x00030ad2735393cb,0x0002e345cee3213b,0x000014e153ebb52d}, {0x00055261e293eac6,0x000032133acdb2e6,0x000900996b845a92,0x000dd80460975cb7,0x00000760bb8d195a}, {0x000e1a17cde6818a,0x000a9ed69a084413,0x0006caccb157156d,0x000c5f22cbf268f4,0x00006b34be9bc33a}}, {{0x000f2f643a78c0b2,0x0001ef22e027cf3d,0x0009c1b5a34c3e97,0x000dd2dec7d1c5e4,0x00002012c18f0922}, {0x000c69656571f2d3,0x00045530e737a11f,0x0004fe5035c6c9e8,0x000d30be33ae7a2d,0x000001b9c7b62e6d}, {0x000b55e55ac89d29,0x0001f45a0a763880,0x0002e76c1f148324,0x000ade83d36efdfc,0x000008af5b784e4b}}, {{0x000499dc881f2533,0x000da779323b6283,0x00073441f49d0525,0x000168d897addfb6,0x000032b79d71163a}, {0x000314d289cc2c4b,0x00011a287178de27,0x000a3364ce4be4bd,0x000826e18d528d6f,0x00006423c1d5afd9}, {0x0005f8d9edfcb36a,0x0008f3746e5f9cc8,0x0009e5d3cd22bcc2,0x0002dcce49de338f,0x0000480a5efbc13e}}, {{0x0001e70b01622071,0x000cf8b1dafc50b5,0x000f5aabcd06b505,0x000bf312c6bb061e,0x000047aa27600cb7}, {0x00014ce442ce221f,0x000cc4c053928b66,0x000c1cbe036e199d,0x0008e06663fb4a4d,0x000024b31d47691c}, {0x00041eedc015f8c3,0x0007e7c693f7c2a5,0x000ea278d611a4fe,0x000a094f0af66134,0x0000545b585d14dd}}, {{0x000f275ea0d43a0f,0x00034089beebe67b,0x000479e72eade68e,0x00054544289134cd,0x00000f62f9c332ba}, {0x0004e4d0e3b321e1,0x0007a28ff1e95620,0x000b99bd9e3baa63,0x000d0710b0ccffd5,0x00004d22dc3e64c8}, {0x00046589d63b5f39,0x0003f57cbcf61fcb,0x00053afa055cae6a,0x0001436febac2d29,0x00001c0fa01a3637}}, }, { /* slot=31 [{1,2,3,..,8} * 16^(2*31)] * G) */ {{0x000604b622943dff,0x000ce44cfb3a0d2c,0x0007808678bc8cbe,0x000a6bf5d254ff39,0x00000fa3614f3b1c}, {0x00082b0e8c936a50,0x00035c1dac5b6690,0x0004dfb634f9c9a0,0x000c1406fb73e54c,0x00004005419b1d2b}, {0x0003febdb9be82f0,0x000af3a44ac90a00,0x000954fa8e2089c1,0x000ab42f8499f911,0x00001fba218aef40}}, {{0x00049448fac8f53e,0x0009a7ba63741ab5,0x000c2b5e0181f6e8,0x0006e4274fd6c7d6,0x0000392e3acaa8c8}, {0x000e57043e7b0194,0x000ee08daaf7f4f3,0x0009dcdef1a81d3e,0x00061d5c839c6ab9,0x00006c535d13ff77}, {0x000d34e93e8a35af,0x000445887e8164cb,0x00029ab0ab2e0781,0x000c13b19319c76f,0x000025e17fe4d50a}}, {{0x00089bd71e04f676,0x00052d6420f950a2,0x0004691fab208e1c,0x000b3515186d8b03,0x0000255751442a9f}, {0x000f7ff576f121a7,0x000272fcd87e3915,0x000d1be526c34a32,0x000899bccba2fde4,0x00006bba828f8969}, {0x0001bc6690fe3901,0x00018a0997ad5e2d,0x000f8460d44cb54a,0x0007be4971d6914a,0x0000559d504f7f6b}}, {{0x00038378b3eb54d5,0x00066a5553c7ca77,0x00092800ba1d69d3,0x00032170a26cf62f,0x000001ab12d5807e}, {0x000891e7f6d266fd,0x0009b0307781b9c4,0x000061e23b0744a1,0x000d50e88388f1d6,0x0000123ea6a3354b}, {0x000d189041e32d96,0x000c2d8315848118,0x00083245d9b9ede3,0x000a1541eab4271d,0x00004a3961e2c918}}, {{0x000c3be0f8e6bba0,0x000347effe30a71d,0x00013a476ad6cef8,0x000b763a992425fe,0x00002cd6bce3fb1d}, {0x0007d644f3233f1e,0x0000e34fcf016032,0x0002dab979499a26,0x000111f83b5a716f,0x000068aceead9bd4}, {0x0004c90ef3d7c210,0x00024b7ad040c38b,0x0007e73e23308e6e,0x000f5973860d9f1b,0x0000595760d5b508}}, {{0x0009bfe104aa6397,0x00008a4a7fccb612,0x000d9094588f9600,0x00091a93f8bc0897,0x0000709fa43edcb2}, {0x000acbebfd022790,0x00005c4115760882,0x000d3473f489af33,0x0005a2b65f492e37,0x00002cb2c5df5451}, {0x000a5d8c63fd2aca,0x000662e694effeb0,0x0008cbb03ad22bc1,0x000131f2723f36ef,0x000070f029ecf0c8}}, {{0x000307b32eed3e33,0x00033a45581e7461,0x00095f0366ae042f,0x0004858c94449d31,0x00000b7d5d8a6c31}, {0x000aafaa5e10b0b9,0x00070ef041aa92a6,0x000a3ad61f78f0a3,0x000d9e1773efb77a,0x000044eca5a2a74b}, {0x000448327b95d543,0x00000a3340f1d25d,0x0000e1c52b70d383,0x000e9e4de1c531c6,0x0000272224512c7d}}, {{0x000c92af49c5342e,0x00011b2e6fad01ab,0x000cc84e29ffeed8,0x000c543efa28c8df,0x000011b5df18a44c}, {0x000bbb8a42a975fc,0x0007796ada358bf7,0x000dedaa488c5c39,0x00020a6e27fc76fc,0x000019735fd7f6bc}, {0x000b90d042c84266,0x0000f7f19547ee3a,0x0005a497b9eb848e,0x000895f2503a1d06,0x00000fef911191df}}, }, }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* #define IFMA_ED25519_PRECOMP_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/ed25519/sha512.h000066400000000000000000000167631470420105600306550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ /* // Macros and definitions that is necessary for SHA512 computation */ #ifndef SHA_512_H #define SHA_512_H #include #if (_MBX>=_MBX_K1) /* define 64-bit constant */ #if !defined(__GNUC__) #define CONST_64(x) (x) /*(x##i64)*/ #else #define CONST_64(x) (x##LL) #endif static const int64u sha512_iv[] = { CONST_64(0x6A09E667F3BCC908), CONST_64(0xBB67AE8584CAA73B), CONST_64(0x3C6EF372FE94F82B), CONST_64(0xA54FF53A5F1D36F1), CONST_64(0x510E527FADE682D1), CONST_64(0x9B05688C2B3E6C1F), CONST_64(0x1F83D9ABFB41BD6B), CONST_64(0x5BE0CD19137E2179) }; static __ALIGN64 const int64u sha512_cnt[] = { CONST_64(0x428A2F98D728AE22), CONST_64(0x7137449123EF65CD), CONST_64(0xB5C0FBCFEC4D3B2F), CONST_64(0xE9B5DBA58189DBBC), CONST_64(0x3956C25BF348B538), CONST_64(0x59F111F1B605D019), CONST_64(0x923F82A4AF194F9B), CONST_64(0xAB1C5ED5DA6D8118), CONST_64(0xD807AA98A3030242), CONST_64(0x12835B0145706FBE), CONST_64(0x243185BE4EE4B28C), CONST_64(0x550C7DC3D5FFB4E2), CONST_64(0x72BE5D74F27B896F), CONST_64(0x80DEB1FE3B1696B1), CONST_64(0x9BDC06A725C71235), CONST_64(0xC19BF174CF692694), CONST_64(0xE49B69C19EF14AD2), CONST_64(0xEFBE4786384F25E3), CONST_64(0x0FC19DC68B8CD5B5), CONST_64(0x240CA1CC77AC9C65), CONST_64(0x2DE92C6F592B0275), CONST_64(0x4A7484AA6EA6E483), CONST_64(0x5CB0A9DCBD41FBD4), CONST_64(0x76F988DA831153B5), CONST_64(0x983E5152EE66DFAB), CONST_64(0xA831C66D2DB43210), CONST_64(0xB00327C898FB213F), CONST_64(0xBF597FC7BEEF0EE4), CONST_64(0xC6E00BF33DA88FC2), CONST_64(0xD5A79147930AA725), CONST_64(0x06CA6351E003826F), CONST_64(0x142929670A0E6E70), CONST_64(0x27B70A8546D22FFC), CONST_64(0x2E1B21385C26C926), CONST_64(0x4D2C6DFC5AC42AED), CONST_64(0x53380D139D95B3DF), CONST_64(0x650A73548BAF63DE), CONST_64(0x766A0ABB3C77B2A8), CONST_64(0x81C2C92E47EDAEE6), CONST_64(0x92722C851482353B), CONST_64(0xA2BFE8A14CF10364), CONST_64(0xA81A664BBC423001), CONST_64(0xC24B8B70D0F89791), CONST_64(0xC76C51A30654BE30), CONST_64(0xD192E819D6EF5218), CONST_64(0xD69906245565A910), CONST_64(0xF40E35855771202A), CONST_64(0x106AA07032BBD1B8), CONST_64(0x19A4C116B8D2D0C8), CONST_64(0x1E376C085141AB53), CONST_64(0x2748774CDF8EEB99), CONST_64(0x34B0BCB5E19B48A8), CONST_64(0x391C0CB3C5C95A63), CONST_64(0x4ED8AA4AE3418ACB), CONST_64(0x5B9CCA4F7763E373), CONST_64(0x682E6FF3D6B2B8A3), CONST_64(0x748F82EE5DEFB2FC), CONST_64(0x78A5636F43172F60), CONST_64(0x84C87814A1F0AB72), CONST_64(0x8CC702081A6439EC), CONST_64(0x90BEFFFA23631E28), CONST_64(0xA4506CEBDE82BDE9), CONST_64(0xBEF9A3F7B2C67915), CONST_64(0xC67178F2E372532B), CONST_64(0xCA273ECEEA26619C), CONST_64(0xD186B8C721C0C207), CONST_64(0xEADA7DD6CDE0EB1E), CONST_64(0xF57D4F7FEE6ED178), CONST_64(0x06F067AA72176FBA), CONST_64(0x0A637DC5A2C898A6), CONST_64(0x113F9804BEF90DAE), CONST_64(0x1B710B35131C471B), CONST_64(0x28DB77F523047D84), CONST_64(0x32CAAB7B40C72493), CONST_64(0x3C9EBE0A15C9BEBC), CONST_64(0x431D67C49C100D4C), CONST_64(0x4CC5D4BECB3E42B6), CONST_64(0x597F299CFC657E2A), CONST_64(0x5FCB6FAB3AD6FAEC), CONST_64(0x6C44198C4A475817) }; /* SHA512 constants */ #define SHA512_DIGEST_BITSIZE 512 #define BYTESIZE (8) #define MBS_SHA512 (128) #define MLR_SHA512 (sizeof(int64u)*2) /* Logical Shifts (right and left) of WORD */ #define LSR32(x,nBits) ((x)>>(nBits)) #define LSL32(x,nBits) ((x)<<(nBits)) /* Rotate (right and left) of WORD */ #if defined(_MSC_VER) && !defined( __ICL ) # include # define ROR32(x, nBits) _lrotr((x),(nBits)) # define ROL32(x, nBits) _lrotl((x),(nBits)) #else # define ROR32(x, nBits) (LSR32((x),(nBits)) | LSL32((x),32-(nBits))) # define ROL32(x, nBits) ROR32((x),(32-(nBits))) #endif /* Logical Shifts (right and left) of DWORD */ #define LSR64(x,nBits) ((x)>>(nBits)) #define LSL64(x,nBits) ((x)<<(nBits)) /* Rotate (right and left) of DWORD */ #define ROR64(x, nBits) (LSR64((x),(nBits)) | LSL64((x),64-(nBits))) #define ROL64(x, nBits) ROR64((x),(64-(nBits))) /* WORD and DWORD manipulators */ #define LODWORD(x) ((int32u)(x)) #define HIDWORD(x) ((int32u)(((int64u)(x) >>32) & 0xFFFFFFFF)) #define MAKEDWORD(wLo,wHi) ((int64u)(((int32u)(wLo)) | ((int64u)((int32u)(wHi))) << 32)) /* Change endian */ #if defined(_MSC_VER) # define ENDIANNESS(x) _byteswap_ulong((x)) # define ENDIANNESS32(x) ENDIANNESS((x)) # define ENDIANNESS64(x) _byteswap_uint64((x)) #elif defined(__ICL) # define ENDIANNESS(x) _bswap((x)) # define ENDIANNESS32(x) ENDIANNESS((x)) # define ENDIANNESS64(x) _bswap64((x)) #else # define ENDIANNESS(x) ((ROR32((x), 24) & 0x00ff00ff) | (ROR32((x), 8) & 0xff00ff00)) # define ENDIANNESS32(x) ENDIANNESS((x)) # define ENDIANNESS64(x) MAKEDWORD(ENDIANNESS(HIDWORD((x))), ENDIANNESS(LODWORD((x)))) #endif #ifndef MIN #define MIN( a, b ) ( ((a) < (b)) ? (a) : (b) ) #endif /* // SHA512 Specific Macros // // Note: All operations act on DWORDs (64-bits) */ #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define SUM0(x) (ROR64((x),28) ^ ROR64((x),34) ^ ROR64((x),39)) #define SUM1(x) (ROR64((x),14) ^ ROR64((x),18) ^ ROR64((x),41)) #define SIG0(x) (ROR64((x), 1) ^ ROR64((x), 8) ^ LSR64((x), 7)) #define SIG1(x) (ROR64((x),19) ^ ROR64((x),61) ^ LSR64((x), 6)) #define SHA512_UPDATE(i) \ wdat[i&15] += SIG1(wdat[(i+14)&15]) + wdat[(i+9)&15] + SIG0(wdat[(i+1)&15]) #define SHA512_STEP(i,j) \ v[(7-i)&7] += (j ? SHA512_UPDATE(i) : wdat[i&15]) \ + SHA512_cnt_loc[i+j] \ + SUM1(v[(4-i)&7]) \ + CH(v[(4-i)&7], v[(5-i)&7], v[(6-i)&7]); \ v[(3-i)&7] += v[(7-i)&7]; \ v[(7-i)&7] += SUM0(v[(0-i)&7]) + MAJ(v[(0-i)&7], v[(1-i)&7], v[(2-i)&7]) /* // SHA512 structures and data types */ /* SHA512 digest */ typedef int64u DigestSHA512[8]; /* SHA512 context */ struct _cpSHA512 { int msgBuffIdx; /* buffer entry */ int64u msgLenLo; /* message length */ int64u msgLenHi; /* message length */ int8u msgBuffer[MBS_SHA512]; /* buffer */ DigestSHA512 msgHash; /* intermediate hash */ }; typedef struct _cpSHA512 SHA512State; #define HASH_LENLO(stt) ((stt)->msgLenLo) #define HASH_LENHI(stt) ((stt)->msgLenHi) #define HASH_VALUE(stt) ((stt)->msgHash) #define HASH_BUFFIDX(stt) ((stt)->msgBuffIdx) #define HASH_BUFF(stt) ((stt)->msgBuffer) /* // SHA512 internal functions */ void SHA512MsgDigest(const int8u* pMsg, int len, int8u* pMD); void SHA512Init(SHA512State* pState); void SHA512Update(const int8u* pSrc, int len, SHA512State* pState); void SHA512Final(int8u* pMD, SHA512State* pState); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* SHA_512_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/exp/000077500000000000000000000000001470420105600272625ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/exp/ifma_exp_method.h000066400000000000000000000065241470420105600325720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_EXP_METHOD_H #define IFMA_EXP_METHOD_H #include /* exponentiation processing window */ #define EXP_WIN_SIZE (5) #define EXP_WIN_MASK ((1< #ifndef BN_OPENSSL_DISABLE #include #endif #define MBX_LANES (8) #define MBX_NISTP256_DATA_BYTE_LEN (32) #define MBX_NISTP384_DATA_BYTE_LEN (48) #define MBX_NISTP521_DATA_BYTE_LEN (66) #define MBX_ED25519_DATA_BYTE_LEN (32) #define MBX_X25519_DATA_BYTE_LEN (32) #define MBX_RSA_PUB_EXP_BYTE_LEN (3) #define MBX_RSA1K_DATA_BIT_LEN (1024) #define MBX_RSA2K_DATA_BIT_LEN (2048) #define MBX_RSA3K_DATA_BIT_LEN (3072) #define MBX_RSA4K_DATA_BIT_LEN (4096) #define MBX_RSA1K_DATA_BYTE_LEN ( (MBX_RSA1K_DATA_BIT_LEN) >> 3 ) #define MBX_RSA2K_DATA_BYTE_LEN ( (MBX_RSA2K_DATA_BIT_LEN) >> 3 ) #define MBX_RSA3K_DATA_BYTE_LEN ( (MBX_RSA3K_DATA_BIT_LEN) >> 3 ) #define MBX_RSA4K_DATA_BYTE_LEN ( (MBX_RSA4K_DATA_BIT_LEN) >> 3 ) /** * \brief * * Comparison of two byte arrays. * * Compares byte arrays, returns 1 if arrays are equal, 0 otherwise. * * NOTE: This function should not be used for a secure memory comparison (i.e. constant time). * * \param[in] p1 pointer to first byte array * \param[in] p1_byte_len length of first array in bytes * \param[in] p2 pointer to second byte array * \param[in] p2_byte_len length of second array in bytes * */ int mbx_is_mem_eq(const int8u *p1, int32u p1_byte_len, const int8u *p2, int32u p2_byte_len); #endif // MBX_FIPS_CERT_COMMON_H #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/000077500000000000000000000000001470420105600272535ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/avxifma_ahmm.h000066400000000000000000000206341470420105600320660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 AVXIFMA_AHMM_H #define AVXIFMA_AHMM_H #include #include #include /* Almost Half Montgomery Multiplication (AHMM) Output: out_mb : C = A*B*(2^(-N*52)) mod M Inputs: inpA_mb : A (N*52-bit input) inpB_mb : B (N*52-bit input) inpBx_mb : K = B*(2^(-(N/2)*52)) mod M inpM_mb : M (N*52-bit modulus) k0_mb : montgomery constant = (-M^(-1) mod 2^(52)) N : size of the operation (number of 52-bit words) i.e. N=20 corresponds to 1024-bit operation AL=A[(N/2) - 1 : 0] AH=A[ N - 1 : N/2] C=0 for i from 0 to N/2-1: C=C+AL[i]*K+AH[i]*B T=C[0]*mu // discard T[1] C=C+T[0]*M // C[0] is zero C=C>>52 // at each step of the for loop, divide the result by 2^52 return C */ __MBX_INLINE void ifma_ahmm52xN_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpBx_mb, const int64u *inpM_mb, const int64u *k0_mb, const int N) { const __m256i *A = (const __m256i *)inpA_mb; const __m256i *mulb = (const __m256i *)inpB_mb; const __m256i *mulbx = (const __m256i *)inpBx_mb; const __m256i *M = (const __m256i *)inpM_mb; // Temporary Registers to hold 20 52-bit intermediate results int i; // C = 0 __m256i C[40 + 1]; assert(N <= 40); zero_mb4(C, N + 1); // Precomputed Montgomery constant (-M^(-1) mod 2^(52)) const __m256i mont_constant = _mm256_loadu_si256((const __m256i *)k0_mb); for (i = 0; i < (N / 2); i++) { //****************************************************** // The loop realizes the following operations // C=C+AL[i]*K+AH[i]*B // T=C[0]*mu // C=C+T[0]*M // C=C>>52 //****************************************************** // load AH[i] const __m256i AH = A[i + (N / 2)]; // load AL[i] const __m256i AL = A[i]; int j; // C[0] and C[1] computation is unrolled to compute T[0] and // get 8xC[] value computation loop going // C=C+AH[i]*B C[0] = _mm256_madd52lo_epu64(C[0], AH, mulb[0]); // C=C+AL[i]*K (low part) C[0] = _mm256_madd52lo_epu64(C[0], AL, mulbx[0]); // T=C[0]*mu const __m256i T = _mm256_madd52lo_epu64(_mm256_setzero_si256(), C[0], mont_constant); // C=C+T[0]*M (low part) C[0] = _mm256_madd52lo_epu64(C[0], T, M[0]); // C[1] // C=C+AH[i]*B C[1] = _mm256_madd52hi_epu64(C[1], AH, mulb[0]); C[1] = _mm256_madd52lo_epu64(C[1], AH, mulb[1]); // C=C+AL[i]*K (low part) C[1] = _mm256_madd52hi_epu64(C[1], AL, mulbx[0]); C[1] = _mm256_madd52lo_epu64(C[1], AL, mulbx[1]); // low 52 (DIGIT_SIZE) bits of C[0] are 0 // high 12 bits are accumulated to C[1] (same bit-weight) C[1] = _mm256_add_epi64(C[1], _mm256_srli_epi64(C[0], DIGIT_SIZE)); const __m256i L0 = _mm256_madd52hi_epu64(C[1], T, M[0]); C[0] = _mm256_madd52lo_epu64(L0, T, M[1]); for (j = 2; (j + 7) < N; j += 8) { // This loop works on 8 result words at the same time C[j], C[j+1], ... C[j+7]. // This is to keep 8 independent IFMA operations in flight. register __m256i r0 = C[j + 0], r1 = C[j + 1], r2 = C[j + 2], r3 = C[j + 3], r4 = C[j + 4], r5 = C[j + 5], r6 = C[j + 6], r7 = C[j + 7]; // C=C+AH[i]*B r0 = _mm256_madd52hi_epu64(r0, AH, mulb[j - 1]); r1 = _mm256_madd52hi_epu64(r1, AH, mulb[j + 0]); r2 = _mm256_madd52hi_epu64(r2, AH, mulb[j + 1]); r3 = _mm256_madd52hi_epu64(r3, AH, mulb[j + 2]); r4 = _mm256_madd52hi_epu64(r4, AH, mulb[j + 3]); r5 = _mm256_madd52hi_epu64(r5, AH, mulb[j + 4]); r6 = _mm256_madd52hi_epu64(r6, AH, mulb[j + 5]); r7 = _mm256_madd52hi_epu64(r7, AH, mulb[j + 6]); r0 = _mm256_madd52lo_epu64(r0, AH, mulb[j + 0]); r1 = _mm256_madd52lo_epu64(r1, AH, mulb[j + 1]); r2 = _mm256_madd52lo_epu64(r2, AH, mulb[j + 2]); r3 = _mm256_madd52lo_epu64(r3, AH, mulb[j + 3]); r4 = _mm256_madd52lo_epu64(r4, AH, mulb[j + 4]); r5 = _mm256_madd52lo_epu64(r5, AH, mulb[j + 5]); r6 = _mm256_madd52lo_epu64(r6, AH, mulb[j + 6]); r7 = _mm256_madd52lo_epu64(r7, AH, mulb[j + 7]); // C=C+AL[i]*K (low part) r0 = _mm256_madd52hi_epu64(r0, AL, mulbx[j - 1]); r1 = _mm256_madd52hi_epu64(r1, AL, mulbx[j + 0]); r2 = _mm256_madd52hi_epu64(r2, AL, mulbx[j + 1]); r3 = _mm256_madd52hi_epu64(r3, AL, mulbx[j + 2]); r4 = _mm256_madd52hi_epu64(r4, AL, mulbx[j + 3]); r5 = _mm256_madd52hi_epu64(r5, AL, mulbx[j + 4]); r6 = _mm256_madd52hi_epu64(r6, AL, mulbx[j + 5]); r7 = _mm256_madd52hi_epu64(r7, AL, mulbx[j + 6]); r0 = _mm256_madd52lo_epu64(r0, AL, mulbx[j + 0]); r1 = _mm256_madd52lo_epu64(r1, AL, mulbx[j + 1]); r2 = _mm256_madd52lo_epu64(r2, AL, mulbx[j + 2]); r3 = _mm256_madd52lo_epu64(r3, AL, mulbx[j + 3]); r4 = _mm256_madd52lo_epu64(r4, AL, mulbx[j + 4]); r5 = _mm256_madd52lo_epu64(r5, AL, mulbx[j + 5]); r6 = _mm256_madd52lo_epu64(r6, AL, mulbx[j + 6]); r7 = _mm256_madd52lo_epu64(r7, AL, mulbx[j + 7]); /* C[j] = C[j + 1] + LO(T x M[j + 1]) + HI(T x M[j]) */ r0 = _mm256_madd52hi_epu64(r0, T, M[j - 1]); r1 = _mm256_madd52hi_epu64(r1, T, M[j + 0]); r2 = _mm256_madd52hi_epu64(r2, T, M[j + 1]); r3 = _mm256_madd52hi_epu64(r3, T, M[j + 2]); r4 = _mm256_madd52hi_epu64(r4, T, M[j + 3]); r5 = _mm256_madd52hi_epu64(r5, T, M[j + 4]); r6 = _mm256_madd52hi_epu64(r6, T, M[j + 5]); r7 = _mm256_madd52hi_epu64(r7, T, M[j + 6]); r0 = _mm256_madd52lo_epu64(r0, T, M[j + 0]); r1 = _mm256_madd52lo_epu64(r1, T, M[j + 1]); r2 = _mm256_madd52lo_epu64(r2, T, M[j + 2]); r3 = _mm256_madd52lo_epu64(r3, T, M[j + 3]); r4 = _mm256_madd52lo_epu64(r4, T, M[j + 4]); r5 = _mm256_madd52lo_epu64(r5, T, M[j + 5]); r6 = _mm256_madd52lo_epu64(r6, T, M[j + 6]); r7 = _mm256_madd52lo_epu64(r7, T, M[j + 7]); C[j - 1] = r0; C[j + 0] = r1; C[j + 1] = r2; C[j + 2] = r3; C[j + 3] = r4; C[j + 4] = r5; C[j + 5] = r6; C[j + 6] = r7; } for (; j < N; j++) { // Finish up by computing 1 result per loop. register __m256i r0 = C[j + 0]; // C=C+AH[i]*B r0 = _mm256_madd52hi_epu64(r0, AH, mulb[j - 1]); r0 = _mm256_madd52lo_epu64(r0, AH, mulb[j + 0]); // C=C+AL[i]*K (low part) r0 = _mm256_madd52hi_epu64(r0, AL, mulbx[j - 1]); r0 = _mm256_madd52lo_epu64(r0, AL, mulbx[j + 0]); /* C[j] = C[j + 1] + LO(T x M[j + 1]) + HI(T x M[j]) */ r0 = _mm256_madd52hi_epu64(r0, T, M[j - 1]); r0 = _mm256_madd52lo_epu64(r0, T, M[j + 0]); C[j - 1] = r0; } // C[N] = HI(AH[i] x B) + HI(AL[i] x K) C[j] = _mm256_madd52hi_epu64(_mm256_setzero_si256(), AH, mulb[j - 1]); C[j] = _mm256_madd52hi_epu64(C[j], AL, mulbx[j - 1]); // C[N-1] = C[N] + HI(T x M[N - 1]) */ j = N - 1; C[j] = _mm256_madd52hi_epu64(C[j + 1], T, M[j]); //****************************************************** } /* Normalization - without clearing the top bits */ ifma_normalize_52xN_mb4(out_mb, C, N); } #endif /* AVXIFMA_AHMM_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/avxifma_ahmr.h000066400000000000000000000054221470420105600320710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 AVXIFMA_AHMR_H #define AVXIFMA_AHMR_H #include #include #include /* Almost Half Montgomery Reduction (AHMR) Output: out_mb : C = A*(2^(-10*52)) mod M Inputs: inpA_mb : A (N*52-bit input) inpM_mb : M (N*52-bit modulus) k0_mb : montgomery constant = (-M^(-1) mod 2^(52)) N : size of the operation (number of 52-bit words) i.e. N=20 corresponds to 1024-bit operation C=A for i from 0 to N/2 - 1: T=C[0]*mu // discard T[1] C=C+T[0]*M // C[0] is zero C=C>>52 // at each step of the for loop, divide the result by 2^52 return C */ __MBX_INLINE void ifma_ahmr52xN_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb, const int N) { const __m256i *inpM = (const __m256i *)inpM_mb; const __m256i *inpA = (const __m256i *)inpA_mb; __m256i C[40]; int i; const __m256i MASK52 = _mm256_set1_epi64x(DIGIT_MASK); assert(N <= 40); // C=A for (i = 0; i < N; i++) C[i] = _mm256_and_si256(inpA[i], MASK52); const __m256i mont_constant = _mm256_loadu_si256((const __m256i *)&k0_mb[0]); for (i = 0; i < (N / 2); i++) { // T=C[0]*mu const __m256i T = _mm256_madd52lo_epu64(_mm256_setzero_si256(), C[0], mont_constant); // C=C+T[0]*M (low part) C[0] = _mm256_madd52lo_epu64(C[0], T, inpM[0]); // low 52 (DIGIT_SIZE) bits of C[0] are 0 // high 12 bits are accumulated to C[1] (same bit-weight) C[1] = _mm256_add_epi64(C[1], _mm256_srli_epi64(C[0], DIGIT_SIZE)); int j; for (j = 0; j < (N - 1); j++) { /* C[j] = C[j + 1] + LO(T x M[j + 1]) + HI(T x M[j]) */ const __m256i L = _mm256_madd52lo_epu64(C[j + 1], T, inpM[j + 1]); C[j] = _mm256_madd52hi_epu64(L, T, inpM[j]); } // C[N-1] C[j] = _mm256_madd52hi_epu64(_mm256_setzero_si256(), T, inpM[j]); } // return C ifma_normalize_52xN_mb4(out_mb, C, N); } #endif /* AVXIFMA_AHMR_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/avxifma_amm.h000066400000000000000000000157301470420105600317170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 AVXIFMA_AMM_H #define AVXIFMA_AMM_H #include #include #include #include /* Almost Montgomery Multiplication Output: out_mb : C = A*B*(2^(-N*52)) mod M Inputs: inpA_mb : A (N*52-bit input) inpB_mb : B (N*52-bit input) inpM_mb : M (N*52-bit modulus) k0_mb : mu, montgomery constant = (-M^(-1) mod 2^(52)) N : size of the operation (number of 52-bit words) i.e. N=20 corresponds to 1024-bit operation C=0 for i from 0 to N - 1: C=C+A*B[i] T=C[0]*mu // discard T[1] C=C+T[0]*M // C[0] is zero C=C>>52 // at each step of the for loop, divide the result by 2^52 return C */ __MBX_INLINE void ifma_amm52xN_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb, const int N) { const __m256i *inpA = (const __m256i *)inpA_mb; const __m256i *inpB = (const __m256i *)inpB_mb; const __m256i *inpM = (const __m256i *)inpM_mb; const __m256i K0 = _mm256_load_si256((const __m256i *)&k0_mb[0]); __m256i C[79]; int i; assert(N <= 79); zero_mb4(C, N); for (i = 0; i < N; i++) { const register __m256i Bi = inpB[i]; register __m256i r0, r1, r2, r3, r4, r5, r6, r7; int j; /* calculate C[0] and prepare T */ r0 = _mm256_madd52lo_epu64(C[0], Bi, inpA[0]); const register __m256i T = _mm256_madd52lo_epu64(_mm256_setzero_si256(), r0, K0); r1 = _mm256_madd52lo_epu64(C[1], Bi, inpA[1]); r0 = _mm256_madd52lo_epu64(r0, T, inpM[0]); r1 = _mm256_madd52lo_epu64(r1, T, inpM[1]); r0 = _mm256_srli_epi64(r0, DIGIT_SIZE); r1 = _mm256_add_epi64(r1, r0); r0 = _mm256_madd52hi_epu64(r1, Bi, inpA[0]); r0 = _mm256_madd52hi_epu64(r0, T, inpM[0]); C[0] = r0; // calculate C[2, 3, ..., N-2] for (j = 2; (j + 8) < N; j += 8) { // This loop calculates 8 C[] values to keep number of independent IFMA operations running r0 = C[j + 0]; r1 = C[j + 1]; r2 = C[j + 2]; r3 = C[j + 3]; r4 = C[j + 4]; r5 = C[j + 5]; r6 = C[j + 6]; r7 = C[j + 7]; r0 = _mm256_madd52lo_epu64(r0, Bi, inpA[j + 0]); r1 = _mm256_madd52lo_epu64(r1, Bi, inpA[j + 1]); r2 = _mm256_madd52lo_epu64(r2, Bi, inpA[j + 2]); r3 = _mm256_madd52lo_epu64(r3, Bi, inpA[j + 3]); r4 = _mm256_madd52lo_epu64(r4, Bi, inpA[j + 4]); r5 = _mm256_madd52lo_epu64(r5, Bi, inpA[j + 5]); r6 = _mm256_madd52lo_epu64(r6, Bi, inpA[j + 6]); r7 = _mm256_madd52lo_epu64(r7, Bi, inpA[j + 7]); r0 = _mm256_madd52lo_epu64(r0, T, inpM[j + 0]); r1 = _mm256_madd52lo_epu64(r1, T, inpM[j + 1]); r2 = _mm256_madd52lo_epu64(r2, T, inpM[j + 2]); r3 = _mm256_madd52lo_epu64(r3, T, inpM[j + 3]); r4 = _mm256_madd52lo_epu64(r4, T, inpM[j + 4]); r5 = _mm256_madd52lo_epu64(r5, T, inpM[j + 5]); r6 = _mm256_madd52lo_epu64(r6, T, inpM[j + 6]); r7 = _mm256_madd52lo_epu64(r7, T, inpM[j + 7]); r0 = _mm256_madd52hi_epu64(r0, Bi, inpA[j + 0 - 1]); r1 = _mm256_madd52hi_epu64(r1, Bi, inpA[j + 1 - 1]); r2 = _mm256_madd52hi_epu64(r2, Bi, inpA[j + 2 - 1]); r3 = _mm256_madd52hi_epu64(r3, Bi, inpA[j + 3 - 1]); r4 = _mm256_madd52hi_epu64(r4, Bi, inpA[j + 4 - 1]); r5 = _mm256_madd52hi_epu64(r5, Bi, inpA[j + 5 - 1]); r6 = _mm256_madd52hi_epu64(r6, Bi, inpA[j + 6 - 1]); r7 = _mm256_madd52hi_epu64(r7, Bi, inpA[j + 7 - 1]); r0 = _mm256_madd52hi_epu64(r0, T, inpM[j + 0 - 1]); r1 = _mm256_madd52hi_epu64(r1, T, inpM[j + 1 - 1]); r2 = _mm256_madd52hi_epu64(r2, T, inpM[j + 2 - 1]); r3 = _mm256_madd52hi_epu64(r3, T, inpM[j + 3 - 1]); r4 = _mm256_madd52hi_epu64(r4, T, inpM[j + 4 - 1]); r5 = _mm256_madd52hi_epu64(r5, T, inpM[j + 5 - 1]); r6 = _mm256_madd52hi_epu64(r6, T, inpM[j + 6 - 1]); r7 = _mm256_madd52hi_epu64(r7, T, inpM[j + 7 - 1]); C[j + 0 - 1] = r0; C[j + 1 - 1] = r1; C[j + 2 - 1] = r2; C[j + 3 - 1] = r3; C[j + 4 - 1] = r4; C[j + 5 - 1] = r5; C[j + 6 - 1] = r6; C[j + 7 - 1] = r7; } // finish up remaining computations in 4's and 1's for (; (j + 4) < N; j += 4) { r0 = C[j + 0]; r1 = C[j + 1]; r2 = C[j + 2]; r3 = C[j + 3]; r0 = _mm256_madd52lo_epu64(r0, Bi, inpA[j + 0]); r1 = _mm256_madd52lo_epu64(r1, Bi, inpA[j + 1]); r2 = _mm256_madd52lo_epu64(r2, Bi, inpA[j + 2]); r3 = _mm256_madd52lo_epu64(r3, Bi, inpA[j + 3]); r0 = _mm256_madd52lo_epu64(r0, T, inpM[j + 0]); r1 = _mm256_madd52lo_epu64(r1, T, inpM[j + 1]); r2 = _mm256_madd52lo_epu64(r2, T, inpM[j + 2]); r3 = _mm256_madd52lo_epu64(r3, T, inpM[j + 3]); r0 = _mm256_madd52hi_epu64(r0, Bi, inpA[j + 0 - 1]); r1 = _mm256_madd52hi_epu64(r1, Bi, inpA[j + 1 - 1]); r2 = _mm256_madd52hi_epu64(r2, Bi, inpA[j + 2 - 1]); r3 = _mm256_madd52hi_epu64(r3, Bi, inpA[j + 3 - 1]); r0 = _mm256_madd52hi_epu64(r0, T, inpM[j + 0 - 1]); r1 = _mm256_madd52hi_epu64(r1, T, inpM[j + 1 - 1]); r2 = _mm256_madd52hi_epu64(r2, T, inpM[j + 2 - 1]); r3 = _mm256_madd52hi_epu64(r3, T, inpM[j + 3 - 1]); C[j + 0 - 1] = r0; C[j + 1 - 1] = r1; C[j + 2 - 1] = r2; C[j + 3 - 1] = r3; } for (; j < N; j++) { r0 = C[j]; r0 = _mm256_madd52lo_epu64(r0, Bi, inpA[j]); r0 = _mm256_madd52lo_epu64(r0, T, inpM[j]); r0 = _mm256_madd52hi_epu64(r0, Bi, inpA[j - 1]); r0 = _mm256_madd52hi_epu64(r0, T, inpM[j - 1]); C[j - 1] = r0; } /* finish up with the last element */ r0 = _mm256_madd52hi_epu64(_mm256_setzero_si256(), Bi, inpA[N - 1]); r0 = _mm256_madd52hi_epu64(r0, T, inpM[N - 1]); C[N - 1] = r0; } /* Normalization and return C */ ifma_normalize_clear_52xN_mb4(out_mb, C, N); } #endif /* AVXIFMA_AMM_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/avxifma_ams.h000066400000000000000000000216111470420105600317200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 AVXIFMA_AMS_H #define AVXIFMA_AMS_H #include #include #include #include /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ /* Montgomery reduction after squaring Output (N*52-bits): res : C = A*(2^(-10*52)) mod M Inputs: res : A (2*N*52-bit input) inpM_mb : M (N*52-bit modulus) k0_mb : montgomery constant = (-M^(-1) mod 2^(52)) N : size of the operation (number of 52-bit words) i.e. N=20 corresponds to 1024-bit operation // Note: implemented as an in-place operation (res = A, and C = res) C=A for i from 0 to N - 1: u=C[0]*mu // discard u[1] C=C+u[0]*M // C[0] is zero C=C>>52 // at each step of the for loop, divide the result by 2^52 return C */ __MBX_INLINE void ams_reduce_52xN_mb4(__m256i *res, const int64u *inpM_mb, const int64u *k0_mb, const int N) { /* Generate u_i */ const __m256i K0 = _mm256_load_si256((const __m256i *)&k0_mb[0]); const __m256i *inpM = (const __m256i *)inpM_mb; int i; for (i = 0; i < N; i++) { register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8; int j = 0; r0 = res[i]; /* res[i + j + 0] and j=0 here */ if (i != 0) r0 = _mm256_add_epi64(r0, _mm256_srli_epi64(res[i - 1], DIGIT_SIZE)); const __m256i u = _mm256_madd52lo_epu64(_mm256_setzero_si256(), r0, K0); for (; (j + 8) < N; j += 8) { // keep 8 independent IFMA operations in flight r1 = res[i + j + 1]; r2 = res[i + j + 2]; r3 = res[i + j + 3]; r4 = res[i + j + 4]; r5 = res[i + j + 5]; r6 = res[i + j + 6]; r7 = res[i + j + 7]; r8 = res[i + j + 8]; r0 = _mm256_madd52lo_epu64(r0, u, inpM[j + 0]); r1 = _mm256_madd52lo_epu64(r1, u, inpM[j + 1]); r2 = _mm256_madd52lo_epu64(r2, u, inpM[j + 2]); r3 = _mm256_madd52lo_epu64(r3, u, inpM[j + 3]); r4 = _mm256_madd52lo_epu64(r4, u, inpM[j + 4]); r5 = _mm256_madd52lo_epu64(r5, u, inpM[j + 5]); r6 = _mm256_madd52lo_epu64(r6, u, inpM[j + 6]); r7 = _mm256_madd52lo_epu64(r7, u, inpM[j + 7]); r1 = _mm256_madd52hi_epu64(r1, u, inpM[j + 0]); r2 = _mm256_madd52hi_epu64(r2, u, inpM[j + 1]); r3 = _mm256_madd52hi_epu64(r3, u, inpM[j + 2]); r4 = _mm256_madd52hi_epu64(r4, u, inpM[j + 3]); r5 = _mm256_madd52hi_epu64(r5, u, inpM[j + 4]); r6 = _mm256_madd52hi_epu64(r6, u, inpM[j + 5]); r7 = _mm256_madd52hi_epu64(r7, u, inpM[j + 6]); r8 = _mm256_madd52hi_epu64(r8, u, inpM[j + 7]); res[i + j + 0] = r0; res[i + j + 1] = r1; res[i + j + 2] = r2; res[i + j + 3] = r3; res[i + j + 4] = r4; res[i + j + 5] = r5; res[i + j + 6] = r6; res[i + j + 7] = r7; r0 = r8; } for (; (j + 4) < N; j += 4) { // keep 4 independent IFMA operations in flight r1 = res[i + j + 1]; r2 = res[i + j + 2]; r3 = res[i + j + 3]; r4 = res[i + j + 4]; r0 = _mm256_madd52lo_epu64(r0, u, inpM[j + 0]); r1 = _mm256_madd52lo_epu64(r1, u, inpM[j + 1]); r2 = _mm256_madd52lo_epu64(r2, u, inpM[j + 2]); r3 = _mm256_madd52lo_epu64(r3, u, inpM[j + 3]); r1 = _mm256_madd52hi_epu64(r1, u, inpM[j + 0]); r2 = _mm256_madd52hi_epu64(r2, u, inpM[j + 1]); r3 = _mm256_madd52hi_epu64(r3, u, inpM[j + 2]); r4 = _mm256_madd52hi_epu64(r4, u, inpM[j + 3]); res[i + j + 0] = r0; res[i + j + 1] = r1; res[i + j + 2] = r2; res[i + j + 3] = r3; r0 = r4; } // finish up computation with reduction at a time for (; j < N; j++) { r1 = res[i + j + 1]; r0 = _mm256_madd52lo_epu64(r0, u, inpM[j]); r1 = _mm256_madd52hi_epu64(r1, u, inpM[j]); res[i + j] = r0; r0 = r1; } res[i + j] = r0; } } /* Square operation Output (2*N*52-bits): res : C = A*A Inputs: inpA : A (N*52-bit input) N : size of the operation (number of 52-bit words) i.e. N=20 corresponds to 1024-bit operation C = 0 // note: assumed to be done outside this function // triangle for i from 0 to N-2: AL = A[i] for j from i+1 to N-1: C[i+j] = C[i+j] + AL*A[j] // double for i from 0 to 2*N-1: C[i] = 2*C[i] // add square diagonal for i from 0 to N-1: C[i*2] = C[i*2] + A[i]*A[i] return C */ __MBX_INLINE void ams52xN_square_diagonal_mb4(__m256i *res, const __m256i *inpA, const int N) { /* Sum */ for (int i = 0; i < (N - 1); i++) { const __m256i AL = inpA[i]; for (int j = i + 1; j < N; j++) { const __m256i AR = inpA[j]; const int iL = i + j; const int iH = iL + 1; res[iL] = _mm256_madd52lo_epu64(res[iL], AL, AR); res[iH] = _mm256_madd52hi_epu64(res[iH], AL, AR); } } /* Double */ for (int i = 0; i < (N * 2); i++) res[i] = _mm256_add_epi64(res[i], res[i]); /* Add square */ for (int i = 0; i < N; i++) { const __m256i AL = inpA[i]; const int iL = 2 * i; const int iH = iL + 1; res[iL] = _mm256_madd52lo_epu64(res[iL], AL, AL); res[iH] = _mm256_madd52hi_epu64(res[iH], AL, AL); } } /* Almost Montgomery Square NOTE: This function is just for reference. All optimized AMS code use auto-generated square functions and only leverage reduction & normalization functions from this module Output (N*52-bits): out_mb : C = (A^2)*(2^(-10*52)) mod M Inputs: inpA_mb : A (N*52-bit input) inpM_mb : M (N*52-bit modulus) k0_mb : montgomery constant = (-M^(-1) mod 2^(52)) N : size of the operation (number of 52-bit words) i.e. N=20 corresponds to 1024-bit operation // square operation expects res to be 0 // res is 2*N*52 bits in size res = 0 // square A res = A^2; // reduce res[N..2*N-1] = reduce(res[0..2*N-1]) // normalize and return normalize(res[N..2*N-1] return res[N..2*N-1] */ __MBX_INLINE void AMS52xN_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb, const int N) { __m256i res[79 * 2]; assert(N <= 79); zero_mb4(res, 2 * N); /* generic square */ ams52xN_square_diagonal_mb4(res, (const __m256i *)inpA_mb, N); /* Generate u_i and reduce */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif /* AVXIFMA_AMS_H */ avxifma_extract_multiplier.h000066400000000000000000000060731470420105600350060ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 AVXIFMA_EXTRACT_MULTIPLIER_H #define AVXIFMA_EXTRACT_MULTIPLIER_H #include /* Constant time extraction of multipliers from the lookup table for 4 independent operations Output: pOut : Inputs: pTbl : two dimensional table [2^exp_window_size][MB4 * N*52-bit] idx_target : SIMD word with 4 64-bit indexes to pTbl[] N : size of the operation (number of 52-bit data words packed in 64-bit words) i.e. N=20 corresponds to 1024-bit operation stored in 20*64-bits exp_window_size : exponantiation window size L=2^exp_window_size // assume multiplier from index 0 is required pOut[0..N-1] = pTbl[0][0..N-1] for i from 1 to L-1: K = (i == idx_target) ? 0xffffffff_ffffffff : 0 pOut[0..N-1] = (pOut[0..N-1] & (~K)) | (pTbl[i][0..L-1] & K) */ __MBX_INLINE void extract_multiplier_mb4_N(__m256i *pOut, const __m256i *pTbl, const __m256i idx_target, const int N, const int exp_window_size) { // Assume first element is what we need int i; for (i = 0; i < N; i++) pOut[i] = *pTbl++; // Find out what we actually need or just keep the original for (i = 1; i < (1 << exp_window_size); i++) { const __m256i idx_curr = _mm256_set1_epi64x(i); const __m256i k = _mm256_cmpeq_epi64(idx_curr, idx_target); for (int j = 0; j < N; j++) { const __m256i temp = *pTbl++; pOut[j] = _mm256_or_si256(_mm256_and_si256(k, temp), _mm256_andnot_si256(k, pOut[j])); } } } __MBX_INLINE void extract_1x_mb4(__m256i *mulB, const __m256i *pMulTbl, const __m256i k, const __m256i idx_target, const int N) { int i; for (i = 0; i < N; i++) { const __m256i temp = _mm256_stream_load_si256(&pMulTbl[i]); mulB[i] = _mm256_or_si256(_mm256_and_si256(k, temp), _mm256_andnot_si256(k, mulB[i])); } } __MBX_INLINE void extract_mb4(__m256i *pMulb, const __m256i *pMulTbl, const int iter, const __m256i idx_target, const int N) { int j; for (j = 0; j < 4; j++) { const int l = j + (4 * iter); const __m256i idx_curr = _mm256_set1_epi64x(l); const __m256i k = _mm256_cmpeq_epi64(idx_curr, idx_target); extract_1x_mb4(&pMulb[0], &pMulTbl[0], k, idx_target, N); pMulTbl += N; } } #endif /* AVXIFMA_EXTRACT_MULTIPLIER_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/ifma_div_104_by_52.h000066400000000000000000000053131470420105600325700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define ALIGNSPEC __ALIGN64 #define DUP2_DECL(a) a, a #define DUP4_DECL(a) DUP2_DECL(a), DUP2_DECL(a) #define DUP8_DECL(a) DUP4_DECL(a), DUP4_DECL(a) // gres: typedef unsigned __int64 UINT64; typedef int64u UINT64; #define VUINT64 __m512i #define VINT64 VUINT64 #define VDOUBLE __m512d #define VMASK_L __mmask8 #define L2D(x) _mm512_castsi512_pd(x) #define D2L(x) _mm512_castpd_si512(x) // Load int constant #define VLOAD_L(addr) _mm512_load_epi64((__m512i const *)&(addr)[0]); // Load DP constant #define VLOAD_D(addr) _mm512_load_pd((const double *)&(addr)[0]); #define VSTORE_L(addr, x) _mm512_store_epi64(((__m512i *)&(addr)[0]), (x)); #define VSHL_L(x, n) _mm512_slli_epi64((x), (n)); #define VSAR_L(x, n) _mm512_srai_epi64((x), (n)); #define VAND_L(a, b) _mm512_and_epi64((a), (b)); #define VADD_L(a, b) _mm512_add_epi64((a), (b)); #define VSUB_L(a, b) _mm512_sub_epi64((a), (b)); #define VMSUB_L(mask, a, b) _mm512_mask_sub_epi64((a), mask, (a), (b)); #define VMADD_L(mask, a, b) _mm512_mask_add_epi64((a), mask, (a), (b)); #define VCMPU_GT_L(a, b) _mm512_cmpgt_epu64_mask((a), (b)); #define VCMP_GE_L(a, b) _mm512_cmpge_epi64_mask((a), (b)); // conversion unsigned 64-bit -> double #define VCVT_L2D(x) _mm512_cvtepu64_pd(x) // conversion double -> signed 64-bit #define VCVT_D2L(x) _mm512_cvtpd_epi64(x) #define VADD_D(a, b) _mm512_add_pd(a, b) #define VMUL_D(a, b) _mm512_mul_pd(a, b) #define VMUL_RZ_D(a, b) _mm512_mul_round_pd(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC) #define VMUL_RU_D(a, b) _mm512_mul_round_pd(a, b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) #define VDIV_RZ_D(a, b) _mm512_div_round_pd(a, b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC) #define VDIV_RU_D(a, b) _mm512_div_round_pd(a, b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC) #define VROUND_RZ_D(a) _mm512_roundscale_pd(a, 3) #define VQFMR_D(a, b, c) _mm512_fnmadd_pd(a, b, c) #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/ifma_rsa_arith.h000066400000000000000000000560271470420105600324060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 IFMA_RSA_ARITH_H #define IFMA_RSA_ARITH_H #ifndef BN_OPENSSL_DISABLE #include #endif #include #include #include typedef int64u int64u_x8[8]; // alias of 8-term vector of int64u each typedef int64u (*pint64u_x8)[8]; // pointer to 8-term vector of int64u each typedef int64u int64u_x4[4]; // alias of 4-term vector of int64u each typedef int64u (*pint64u_x4)[4]; // pointer to 4-term vector of int64u each /* fixed size of RSA */ #define RSA_1K (1024) #define RSA_2K (2 * RSA_1K) #define RSA_3K (3 * RSA_1K) #define RSA_4K (4 * RSA_1K) #ifndef NUMBER_OF_DIGITS #define NUMBER_OF_DIGITS(bitsize, digsize) (((bitsize) + (digsize) - 1) / (digsize)) #endif #define MULTIPLE_OF(x, factor) ((x) + (((factor) - ((x) % (factor))) % (factor))) #define redLen2K ((RSA_1K + (DIGIT_SIZE - 1)) / DIGIT_SIZE) // 20 #define redLen3K (((RSA_3K / 2) + (DIGIT_SIZE - 1)) / DIGIT_SIZE) // 30 #define redLen4K ((RSA_2K + (DIGIT_SIZE - 1)) / DIGIT_SIZE) // 40 #if (_MBX >= _MBX_K1) // ============ Multi-Buffer required functions ============ EXTERN_C void ifma_extract_amm52x20_mb8(int64u *out_mb8, const int64u *inpA_mb8, int64u MulTbl[][redLen2K][8], const int64u Idx[8], const int64u *inpM_mb8, const int64u *k0_mb8); // Multiplication EXTERN_C void ifma_amm52x10_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void ifma_amm52x20_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void ifma_amm52x60_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void ifma_amm52x40_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void ifma_amm52x30_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void ifma_amm52x79_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); // New functions for almost half montgomery EXTERN_C void ifma_ahmm52x20_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpBx_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void ifma_ahmr52x20_mb8(int64u *out_mb, const int64u *inpA_mb, int64u *inpM_mb, const int64u *k0_mb); // Diagonal sqr EXTERN_C void AMS52x10_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS5x52x10_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS52x20_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS4x52x20_diagonal_stitched_with_extract_mb8(int64u *out_mb8, U64 *mulb, U64 *mulbx, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8, int64u MulTbl[][redLen2K][8], int64u MulTblx[][redLen2K][8], const int64u Idx[8]); EXTERN_C void AMS5x52x20_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS52x40_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS5x52x40_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS52x30_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS52x60_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); EXTERN_C void AMS52x79_diagonal_mb8(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); // clear/copy mb8 buffer EXTERN_C void zero_mb8(int64u (*redOut)[8], int len); EXTERN_C void copy_mb8(int64u out[][8], const int64u inp[][8], int len); // other 2^52 radix arith functions EXTERN_C void ifma_montFactor52_mb8(int64u k0_mb8[8], const int64u m0_mb8[8]); EXTERN_C void ifma_modsub52x10_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]); EXTERN_C void ifma_modsub52x20_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]); EXTERN_C void ifma_modsub52x30_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]); EXTERN_C void ifma_modsub52x40_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]); EXTERN_C void ifma_addmul52x10_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8]); EXTERN_C void ifma_addmul52x20_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8]); EXTERN_C void ifma_addmul52x30_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8]); EXTERN_C void ifma_addmul52x40_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8]); EXTERN_C void ifma_amred52x10_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpM[][8], const int64u k0[8]); EXTERN_C void ifma_amred52x20_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpM[][8], const int64u k0[8]); EXTERN_C void ifma_amred52x30_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpM[][8], const int64u k0[8]); EXTERN_C void ifma_amred52x40_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpM[][8], const int64u k0[8]); EXTERN_C void ifma_mreduce52x_mb8(int64u pX[][8], int nsX, int64u pM[][8], int nsM); EXTERN_C void ifma_montRR52x_mb8(int64u pRR[][8], int64u pM[][8], int convBitLen); // exponentiations EXTERN_C void EXP52x10_mb8(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); EXTERN_C void EXP52x20_mb8(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); EXTERN_C void EXP52x40_mb8(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); EXTERN_C void EXP52x60_mb8(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); EXTERN_C void EXP52x30_mb8(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); EXTERN_C void EXP52x79_mb8(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); // exponentiations (fixed short exponent ==65537) EXTERN_C void EXP52x20_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]); EXTERN_C void EXP52x40_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]); EXTERN_C void EXP52x60_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]); EXTERN_C void EXP52x79_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]); mbx_status MB_FUNC_NAME(internal_avx512_x25519_)(int8u *const pa_shared_key[8], const int8u *const pa_private_key[8], const int8u *const pa_public_key[8]); mbx_status MB_FUNC_NAME(internal_avx512_x25519_public_key_)(int8u *const pa_public_key[8], const int8u *const pa_private_key[8]); #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) // ============ Multi-Buffer required functions ============ EXTERN_C void ifma_extract_amm52x20_mb4(int64u *out_mb4, const int64u *inpA_mb4, int64u MulTbl[][redLen2K][4], const int64u Idx[4], const int64u *inpM_mb4, const int64u *k0_mb4); // Multiplication EXTERN_C void ifma_amm52x10_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_amm52x20_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_amm52x60_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_amm52x40_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_amm52x30_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_amm52x79_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); // New functions for almost half montgomery EXTERN_C void ifma_ahmm52x20_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpBx_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_ahmm52x30_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpBx_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_ahmm52x40_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpBx_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void ifma_ahmr52x20_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb); EXTERN_C void ifma_ahmr52x30_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb); EXTERN_C void ifma_ahmr52x40_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb); // Diagonal sqr EXTERN_C void AMS52x10_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS52x20_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS52x30_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS52x40_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS52x60_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS52x79_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS4x52x20_diagonal_stitched_with_extract_mb4(int64u *out_mb4, U64 *mulb, U64 *mulbx, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4, int64u MulTbl[][redLen2K][4], int64u MulTblx[][redLen2K][4], const __m256i idx); EXTERN_C void AMS4x52x30_diagonal_stitched_with_extract_mb4(int64u *out_mb4, U64 *mulb, U64 *mulbx, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4, int64u MulTbl[][redLen3K][4], int64u MulTblx[][redLen3K][4], const __m256i idx); EXTERN_C void AMS4x52x40_diagonal_stitched_with_extract_mb4(int64u *out_mb4, U64 *mulb, U64 *mulbx, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4, int64u MulTbl[][redLen4K][4], int64u MulTblx[][redLen4K][4], const __m256i idx); EXTERN_C void AMS5x52x10_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS5x52x20_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); EXTERN_C void AMS5x52x40_diagonal_mb4(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); // clear/copy mb8 buffer EXTERN_C void zero_mb4(void *redOut, int len); EXTERN_C void copy_mb4(int64u out[][4], const int64u inp[][4], int len); // other 2^52 radix arith functions EXTERN_C void ifma_montFactor52_mb4(int64u k0_mb4[4], const int64u m0_mb4[4]); EXTERN_C void ifma_modsub52x10_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]); EXTERN_C void ifma_modsub52x20_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]); EXTERN_C void ifma_modsub52x30_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]); EXTERN_C void ifma_modsub52x40_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]); EXTERN_C void ifma_addmul52x10_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4]); EXTERN_C void ifma_addmul52x20_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4]); EXTERN_C void ifma_addmul52x30_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4]); EXTERN_C void ifma_addmul52x40_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4]); EXTERN_C void ifma_amred52x10_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpM[][4], const int64u k0[4]); EXTERN_C void ifma_amred52x20_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpM[][4], const int64u k0[4]); EXTERN_C void ifma_amred52x30_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpM[][4], const int64u k0[4]); EXTERN_C void ifma_amred52x40_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpM[][4], const int64u k0[4]); EXTERN_C void ifma_mreduce52x_mb4(int64u pX[][4], int nsX, int64u pM[][4], int nsM); EXTERN_C void ifma_montRR52x_mb4(int64u pRR[][4], int64u pM[][4], int convBitLen); // exponentiations EXTERN_C void EXP52x10_mb4(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb4[4], int64u work_buffer[][4]); EXTERN_C void EXP52x20_mb4(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb4[4], int64u work_buffer[][4]); EXTERN_C void EXP52x40_mb4(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb4[4], int64u work_buffer[][4]); EXTERN_C void EXP52x60_mb4(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb4[4], int64u work_buffer[][4]); EXTERN_C void EXP52x30_mb4(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb4[4], int64u work_buffer[][4]); EXTERN_C void EXP52x79_mb4(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb4[4], int64u work_buffer[][4]); // exponentiations (fixed short exponent ==65537) EXTERN_C void EXP52x20_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]); EXTERN_C void EXP52x40_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]); EXTERN_C void EXP52x60_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]); EXTERN_C void EXP52x79_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]); mbx_status MB_FUNC_NAME(internal_avx512_x25519_)(int8u *const pa_shared_key[4], const int8u *const pa_private_key[4], const int8u *const pa_public_key[4]); mbx_status MB_FUNC_NAME(internal_avx512_x25519_public_key_)(int8u *const pa_public_key[4], const int8u *const pa_private_key[4]); EXTERN_C void ifma_normalize_52xN_mb4(void *out_mb4, const void *in_mb4, const int N); EXTERN_C void ifma_normalize_clear_52xN_mb4(void *out_mb4, const void *in_mb4, const int N); EXTERN_C void ifma_normalize_ams_52xN_mb4(void *out_mb4, const void *in_mb4, const int N); #endif /* #if (_MBX >= _MBX_K1) */ #endif /* _IFMA_INTERNAL_H_ */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/ifma_rsa_layer_cp.h000066400000000000000000000076751470420105600331020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 IFMA_CP_LAYER_H #define IFMA_CP_LAYER_H #include #include #if (_MBX >= _MBX_K1) EXTERN_C void ifma_cp_rsa_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const n_pa[8], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer); EXTERN_C void ifma_cp_rsa_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const d_pa[8], const int64u *const n_pa[8], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer); EXTERN_C void ifma_cp_rsa_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const p_pa[8], const int64u *const q_pa[8], const int64u *const dp_pa[8], const int64u *const dq_pa[8], const int64u *const iq_pa[8], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer); #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) EXTERN_C void ifma_cp_rsa_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const int64u *const n_pa[4], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer); EXTERN_C void ifma_cp_rsa_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const int64u *const d_pa[4], const int64u *const n_pa[4], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer); EXTERN_C void ifma_cp_rsa_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const int64u *const p_pa[4], const int64u *const q_pa[4], const int64u *const dp_pa[4], const int64u *const dq_pa[4], const int64u *const iq_pa[4], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer); #endif /* #if (_MBX >= _MBX_K1) */ #endif /* IFMA_CP_LAYER_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/ifma_rsa_layer_ssl.h000066400000000000000000000170441470420105600332700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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. *************************************************************************/ #if (_MBX >= _MBX_K1) #ifndef BN_OPENSSL_DISABLE #if !defined(_IFMA_INTERNAL_SSL_LAYER_H_) #define _IFMA_INTERNAL_SSL_LAYER_H_ #include #include EXTERN_C void ifma_ssl_rsa1K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa2K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa3K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa4K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa1K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa2K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa3K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa4K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]); EXTERN_C void ifma_ssl_rsa1K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]); EXTERN_C void ifma_ssl_rsa2K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]); EXTERN_C void ifma_ssl_rsa3K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]); EXTERN_C void ifma_ssl_rsa4K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]); #endif /* _IFMA_INTERNAL_SSL_LAYER_H_ */ #endif /* BN_OPENSSL_DISABLE */ #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #ifndef BN_OPENSSL_DISABLE #if !defined(_IFMA_INTERNAL_SSL_LAYER_H_) #define _IFMA_INTERNAL_SSL_LAYER_H_ #include #include EXTERN_C void ifma_ssl_rsa1K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa2K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa3K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa4K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa1K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa2K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa3K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa4K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]); EXTERN_C void ifma_ssl_rsa1K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]); EXTERN_C void ifma_ssl_rsa2K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]); EXTERN_C void ifma_ssl_rsa3K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]); EXTERN_C void ifma_ssl_rsa4K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]); #endif /* _IFMA_INTERNAL_SSL_LAYER_H_ */ #endif /* BN_OPENSSL_DISABLE */ #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/rsa/ifma_rsa_method.h000066400000000000000000000127361470420105600325560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 IFMA_RSA_METHOD_H #define IFMA_RSA_METHOD_H #include /* RSA operation */ typedef enum { RSA_PUB_KEY = (0x01 << 16), RSA_PRV2_KEY = (0x20 << 16), RSA_PRV5_KEY = (0x50 << 16), } RSA_OP_ID; /* RSA size */ typedef enum { RSA1024 = 1024, RSA2048 = 2048, RSA3072 = 3072, RSA4096 = 4096, } RSA_BITSIZE_ID; /* RSA ID */ #define RSA_ID(OP, BITSIZE) ((OP) | (BITSIZE)) #define OP_RSA_ID(ID) ((ID) & (0xFF << 16)) #define BISIZE_RSA_ID(ID) ((ID) & 0xFFFF) #if (_MBX >= _MBX_K1) /* exponentiations */ typedef void (*EXP52x_65537_mb8)(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]); typedef void (*EXP52x_mb8)(int64u out[][8], const int64u base[][8], const int64u exponent[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0_mb8[8], int64u work_buffer[][8]); /* // auxiliary mb8 arithmetic */ /* Mont reduction */ typedef void (*amred52x_mb8)(int64u res[][8], const int64u inpA[][8], const int64u inpM[][8], const int64u k0[8]); /* Mont multiplication */ typedef void (*ammul52x_mb8)(int64u *out_mb8, const int64u *inpA_mb8, const int64u *inpB_mb8, const int64u *inpM_mb8, const int64u *k0_mb8); /* modular subtraction */ typedef void (*modsub52x_mb8)(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]); /* multiply and add */ typedef void (*addmul52x_mb8)(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8]); struct _ifma_rsa_method { int id; /* exponentiation's id (=1/2/5 -- public(fixed)/private/private_crt */ int rsaBitsize; /* size of rsa modulus (bits) */ int buffSize; /* size of scratch buffer */ // cvt52BN_to_mb8 cvt52; /* convert non-contiguous BN to radix 2^52 and store in mb8 forman */ // tcopyBN_to_mb8 tcopy; /* copy non-contiguos BN into mb8 format */ EXP52x_65537_mb8 expfunc65537; /* "exp52x_fix_mb8" fixed exponentiation */ EXP52x_mb8 expfun; /* "exp52x_arb_mb8" exponentiation */ amred52x_mb8 amred52x; /* reduction */ ammul52x_mb8 ammul52x; /* multiplication */ modsub52x_mb8 modsub52x; /* subtraction */ addmul52x_mb8 mla52x; /* multiply & add */ }; #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) /* exponentiations */ typedef void (*EXP52x_65537_mb4)(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]); typedef void (*EXP52x_mb4)(int64u out[][4], const int64u base[][4], const int64u exponent[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0_mb8[4], int64u work_buffer[][4]); /* // auxiliary mb8 arithmetic */ /* Mont reduction */ typedef void (*amred52x_mb4)(int64u res[][4], const int64u inpA[][4], const int64u inpM[][4], const int64u k0[4]); /* Mont multiplication */ typedef void (*ammul52x_mb4)(int64u *out_mb4, const int64u *inpA_mb4, const int64u *inpB_mb4, const int64u *inpM_mb4, const int64u *k0_mb4); /* modular subtraction */ typedef void (*modsub52x_mb4)(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]); /* multiply and add */ typedef void (*addmul52x_mb4)(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4]); struct _ifma_rsa_method { int id; /* exponentiation's id (=1/2/5 -- public(fixed)/private/private_crt */ int rsaBitsize; /* size of rsa modulus (bits) */ int buffSize; /* size of scratch buffer */ // cvt52BN_to_mb4 cvt52; /* convert non-contiguous BN to radix 2^52 and store in mb4 forman */ // tcopyBN_to_mb4 tcopy; /* copy non-contiguos BN into mb4 format */ EXP52x_65537_mb4 expfunc65537; /* "exp52x_fix_mb4" fixed exponentiation */ EXP52x_mb4 expfun; /* "exp52x_arb_mb4" exponentiation */ amred52x_mb4 amred52x; /* reduction */ ammul52x_mb4 ammul52x; /* multiplication */ modsub52x_mb4 modsub52x; /* subtraction */ addmul52x_mb4 mla52x; /* multiply & add */ }; #endif /* #if (_MBX >= _MBX_K1) */ #endif /* IFMA_RSA_METHOD_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm2/000077500000000000000000000000001470420105600271675ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm2/ifma_arith_sm2.h000066400000000000000000000120651470420105600322300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ARITH_SM2_H #define IFMA_ARITH_SM2_H #include #include #include #if (_MBX>=_MBX_K1) /* underlying prime's size */ #define PSM2_BITSIZE (256) #define PSM2_LEN52 NUMBER_OF_DIGITS(PSM2_BITSIZE,DIGIT_SIZE) #define PSM2_LEN64 NUMBER_OF_DIGITS(PSM2_BITSIZE,64) #define PSM2_LEN8 NUMBER_OF_DIGITS(PSM2_BITSIZE,8) /* set FE to zero */ __MBX_INLINE void MB_FUNC_NAME(zero_FESM2_)(U64 T[]) { T[0] = T[1] = T[2] = T[3] = T[4] = get_zero64(); } /* check if FE is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_FESM2_)(const U64 T[]) { U64 Z = or64(or64(T[0], T[1]), or64(or64(T[2], T[3]), T[4])); return cmpeq64_mask(Z, get_zero64()); } /* move field element */ __MBX_INLINE void MB_FUNC_NAME(mov_FESM2_)(U64 r[], const U64 a[]) { r[0] = a[0]; r[1] = a[1]; r[2] = a[2]; r[3] = a[3]; r[4] = a[4]; } /* move coordinate using mask: R = k? A : B */ __MBX_INLINE void MB_FUNC_NAME(mask_mov_FESM2_)(U64 R[], const U64 B[], __mb_mask k, const U64 A[]) { R[0] = mask_mov64(B[0], k, A[0]); R[1] = mask_mov64(B[1], k, A[1]); R[2] = mask_mov64(B[2], k, A[2]); R[3] = mask_mov64(B[3], k, A[3]); R[4] = mask_mov64(B[4], k, A[4]); } __MBX_INLINE void MB_FUNC_NAME(secure_mask_mov_FESM2_)(U64 R[], U64 B[], __mb_mask k, const U64 A[]) { R[0] = select64(k, B[0], (U64*)(&A[0])); R[1] = select64(k, B[1], (U64*)(&A[1])); R[2] = select64(k, B[2], (U64*)(&A[2])); R[3] = select64(k, B[3], (U64*)(&A[3])); R[4] = select64(k, B[4], (U64*)(&A[4])); } /* compare two FE */ __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_lt_FESM2_)(const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); /* normalize r0 – r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) /* return mask LT */ return cmp64_mask(r4, get_zero64(), _MM_CMPINT_LT); } __MBX_INLINE __mb_mask MB_FUNC_NAME(cmp_eq_FESM2_)(const U64 A[], const U64 B[]) { __ALIGN64 U64 msg[PSM2_LEN52]; msg[0] = xor64(A[0], B[0]); msg[1] = xor64(A[1], B[1]); msg[2] = xor64(A[2], B[2]); msg[3] = xor64(A[3], B[3]); msg[4] = xor64(A[4], B[4]); return MB_FUNC_NAME(is_zero_FESM2_)(msg); } /* Specialized operations over EC SM2 prime */ EXTERN_C void MB_FUNC_NAME(ifma_tomont52_psm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_psm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_psm2_)(U64 r[], const U64 va[], const U64 vb[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_psm2_)(U64 r[], const U64 va[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_psm2_)(U64 r[], const U64 z[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_psm2_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_psm2_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_psm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_double52_psm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_tripple52_psm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_half52_psm2_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_psm2_)(const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_psm2_)(const U64 a[]); /* Specialized operations over EC SM2 order */ EXTERN_C U64* MB_FUNC_NAME(ifma_nsm2_)(void); EXTERN_C void MB_FUNC_NAME(ifma_tomont52_nsm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_frommont52_nsm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_ams52_nsm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_amm52_nsm2_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_aminv52_nsm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_add52_nsm2_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_sub52_nsm2_)(U64 r[], const U64 a[], const U64 b[]); EXTERN_C void MB_FUNC_NAME(ifma_neg52_nsm2_)(U64 r[], const U64 a[]); EXTERN_C void MB_FUNC_NAME(ifma_fastred52_pnsm2_)(U64 r[], const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_cmp_lt_nsm2_)(const U64 a[]); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_check_range_nsm2_)(const U64 a[]); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ARITH_SM2_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm2/ifma_ecpoint_sm2.h000066400000000000000000000214271470420105600325640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ECPOINT_SM2_H #define IFMA_ECPOINT_SM2_H #include #include #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* BN_OPENSSL_DISABLE */ #if (_MBX>=_MBX_K1) typedef struct { U64 X[PSM2_LEN52]; U64 Y[PSM2_LEN52]; U64 Z[PSM2_LEN52]; } SM2_POINT; typedef struct { U64 x[PSM2_LEN52]; U64 y[PSM2_LEN52]; } SM2_POINT_AFFINE; typedef struct { int64u x[PSM2_LEN52]; int64u y[PSM2_LEN52]; } SINGLE_SM2_POINT_AFFINE; /* check if coordinate is zero */ __MBX_INLINE __mb_mask MB_FUNC_NAME(is_zero_point_cordinate_)(const U64 T[]) { return MB_FUNC_NAME(is_zero_FESM2_)(T); } /* set point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_to_infinity_)(SM2_POINT* r) { r->X[0] = r->X[1] = r->X[2] = r->X[3] = r->X[4] = get_zero64(); r->Y[0] = r->Y[1] = r->Y[2] = r->Y[3] = r->Y[4] = get_zero64(); r->Z[0] = r->Z[1] = r->Z[2] = r->Z[3] = r->Z[4] = get_zero64(); } /* set point to infinity by mask */ __MBX_INLINE void MB_FUNC_NAME(mask_set_point_to_infinity_)(SM2_POINT* r, __mb_mask mask) { U64 zeros = get_zero64(); r->X[0] = mask_mov64(r->X[0], mask, zeros); r->X[1] = mask_mov64(r->X[1], mask, zeros); r->X[2] = mask_mov64(r->X[2], mask, zeros); r->X[3] = mask_mov64(r->X[3], mask, zeros); r->X[4] = mask_mov64(r->X[4], mask, zeros); r->Y[0] = mask_mov64(r->Y[0], mask, zeros); r->Y[1] = mask_mov64(r->Y[1], mask, zeros); r->Y[2] = mask_mov64(r->Y[2], mask, zeros); r->Y[3] = mask_mov64(r->Y[3], mask, zeros); r->Y[4] = mask_mov64(r->Y[4], mask, zeros); r->Z[0] = mask_mov64(r->Z[0], mask, zeros); r->Z[1] = mask_mov64(r->Z[1], mask, zeros); r->Z[2] = mask_mov64(r->Z[2], mask, zeros); r->Z[3] = mask_mov64(r->Z[3], mask, zeros); r->Z[4] = mask_mov64(r->Z[4], mask, zeros); } /* set affine point to infinity */ __MBX_INLINE void MB_FUNC_NAME(set_point_affine_to_infinity_)(SM2_POINT_AFFINE* r) { r->x[0] = r->x[1] = r->x[2] = r->x[3] = r->x[4] = get_zero64(); r->y[0] = r->y[1] = r->y[2] = r->y[3] = r->y[4] = get_zero64(); } EXTERN_C void MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(SM2_POINT* r, const SM2_POINT* p); EXTERN_C void MB_FUNC_NAME(ifma_ec_sm2_add_point_)(SM2_POINT* r, const SM2_POINT* p, const SM2_POINT* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_sm2_add_point_affine_)(SM2_POINT* r, const SM2_POINT* p, const SM2_POINT_AFFINE* q); EXTERN_C void MB_FUNC_NAME(ifma_ec_sm2_mul_point_)(SM2_POINT* r, const SM2_POINT* p, const U64* scalar); EXTERN_C void MB_FUNC_NAME(ifma_ec_sm2_mul_pointbase_)(SM2_POINT* r, const U64* scalar); EXTERN_C void MB_FUNC_NAME(get_sm2_ec_affine_coords_)(U64 x[], U64 y[], const SM2_POINT* P); EXTERN_C const U64* MB_FUNC_NAME(ifma_ec_sm2_coord_one_)(void); EXTERN_C __mb_mask MB_FUNC_NAME(ifma_is_on_curve_psm2_)(const SM2_POINT* p, int use_jproj_coords); #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_sm2_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_sm2_ecdsa_sign_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked); mbx_status internal_avx512_sm2_ecdsa_verify_ssl_mb8(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked); mbx_status internal_avx512_sm2_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* BN_OPENSSL_DISABLE */ mbx_status internal_avx512_sm2_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords); mbx_status internal_avx512_sm2_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked); mbx_status internal_avx512_sm2_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked); mbx_status internal_avx512_sm2_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPOINT_PSM2_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm2/ifma_ecprecomp4_psm2.h000066400000000000000000003242251470420105600333460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ECPRECOMP4_PSM2_H #define IFMA_ECPRECOMP4_PSM2_H #include #if (_MBX>=_MBX_K1) #define MUL_BASEPOINT_WIN_SIZE (4) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE #define BP_N_SLOTS NUMBER_OF_DIGITS(PSM2_BITSIZE+1,BP_WIN_SIZE) #define BP_N_ENTRY (1<<(BP_WIN_SIZE-1)) __ALIGN64 static SINGLE_SM2_POINT_AFFINE ifma_ec_sm2_bp_precomp[][BP_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x0008990f418029e9,0x000e6ca6c04fd132,0x00024c3c33e7981e,0x000b05d6a1ed99ac,0x00001167a5f71c13}, {0x0004e593c2d0ddd6,0x0008ed3295fa6135,0x0002a48f8c1f5e57,0x0005bd8d4cfb066e,0x00003cd65d4e1d73}}, {{0x00037bfbc3be46a0,0x000a2d8fa9380af0,0x00088cd2483bdc9b,0x00036a5349d94b57,0x0000d7e9c18caa57}, {0x0001a1d69db9ac19,0x000854a8e82ada7e,0x0007157acccbd8d3,0x000df5c7b145169b,0x000047e7465fc21b}}, {{0x00054fdab589e4a3,0x000a0b4f0a0cecda,0x000eb4a0a2676528,0x000c640a265a308c,0x0000019fd6c2e887}, {0x000fbe94b2fc1902,0x000ba7cbce5fea10,0x000c13c97f40aa52,0x000bb4cc496bfa6d,0x00008ad34787bb3f}}, {{0x0007c5a986150605,0x000039016208e93f,0x0009f9020487ea28,0x000be18a86bcb4a0,0x00000dc8e3b1899d}, {0x0009043fd6199986,0x000adc7383bd9c09,0x000cf70ed1de135e,0x0009e34d0bd55632,0x0000ffc31c585bce}}, {{0x00056336a9c81620,0x000221dfcc539a57,0x000f5f4c515aa58f,0x0005b97ad354bf1e,0x0000f443ef363f87}, {0x000d68fd34501337,0x000e53607d17be81,0x0002258efb30f4bb,0x000768b1826a4c36,0x0000b415276842a6}}, {{0x0009c4c0acd72ba8,0x0005de7ec73b936a,0x000e34db6b1274a2,0x000047f15a876e5d,0x00005e74ca10cba8}, {0x0004cddb469eb37b,0x0000799754f75845,0x00030e9848fbf6d2,0x00098a1060e7f8ec,0x0000568bc97fb8c5}}, {{0x00031c781f06784b,0x0003b713251ffa35,0x000fe18c50b89419,0x000c2884ee5b69ac,0x0000bf492e189fbe}, {0x00035c1e5f6186d2,0x000e957a01b8113a,0x000d99baf0e449a2,0x00077796c9b9922b,0x0000ba05a8f5b84d}}, {{0x0003a1c091226701,0x000a32cc810cce52,0x00087df9e90be6f2,0x000134086e634143,0x000015c2fc0e9c44}, {0x000430d8799302ae,0x0001c27b7ea3b334,0x0008f3382693b350,0x000247cbe1136f9a,0x000077fd5f395778}}, }, {/* digit=1 [{1,2,3,..,}]*([2^4]*G) */ {{0x00060c939e8a120c,0x00093273b59a3715,0x000f4639d7121d6b,0x000d58649535ce8e,0x0000d01076ed4cc6}, {0x000729a96e74f8a6,0x0000b533037dc705,0x0003c5c62b07e323,0x000ac10846dcc166,0x0000a4759c170fc3}}, {{0x0001369adbb3c8b5,0x000b9c8ec37856c1,0x000f0a982d78af40,0x00050affb3a80d03,0x000050e3e71f83be}, {0x0000fb2418ee45bb,0x0003b791b963d45c,0x00047e33b5297cf4,0x0005b2676b638ccc,0x00001c52fadaecf8}}, {{0x000f511b36362ecf,0x0007240859590a8f,0x00070c62b11c5a9f,0x000827272b86f297,0x000006262266c7e8}, {0x00068bfea1e13ebf,0x0002be59b0f4a291,0x000826f34db89297,0x000cec6769e31d4f,0x0000a1dd934fa955}}, {{0x000a5ae0d038ad4f,0x000426256c8e90ff,0x000978dcef44d3df,0x0003170a3077c8bc,0x00003d9b4b1645b8}, {0x0004484b6b1852c5,0x00045e78ff073bbf,0x000c242380cd02ed,0x000b5591cb827e49,0x00008adaee62aa3c}}, {{0x0001687af48d3524,0x0000068c04010e5a,0x0003b2e10fa700b7,0x0001f5c06c84139f,0x00007cd5ff4bcf2f}, {0x000c6996a3ebd39b,0x00085f9371d6b52d,0x000c57dadb8d9103,0x000b8bee3f1d85f2,0x0000c987637ef0d8}}, {{0x00091da5f6fbf645,0x000364de051b9b7a,0x0005a1ac8ad5bf46,0x0002fa13e4455d48,0x0000d09b6e064f3a}, {0x000ffc804bf14165,0x000c1e88e44737c3,0x0003777ca4b5beda,0x0001181fc4f3fd98,0x00005e4509f06d4b}}, {{0x0007754a47073753,0x00053923a9dc5b93,0x000ab2dd726607db,0x0000a7690f12ae67,0x0000a39fc8c30a65}, {0x00095fd0ae53d66e,0x000319b1c44980fe,0x000eb8e6eefebcba,0x000c8cf8b3ca72f1,0x0000586e40734f5c}}, {{0x000ce4d033fc12ae,0x00022886f31527e6,0x0006f3f11ba4f98a,0x000de3b24b38f3e6,0x00003f6205b3ea4b}, {0x0005387a77b998f4,0x0007d549f3b0c070,0x0003a61d62c9b445,0x00081adef6625b53,0x0000eda7e2abe4f7}}, }, {/* digit=2 [{1,2,3,..,}]*([2^8]*G) */ {{0x0000aaafd1201340,0x0009c057309ce973,0x000726ce7b22b908,0x00058498e7956584,0x0000e1431a0d635a}, {0x0007023e834ffa6a,0x000fa36ab1ae1d38,0x00024b68464198dd,0x000c6d46e5ebb191,0x0000316fa44c33b3}}, {{0x0000210a1371aa41,0x000064b5424eac97,0x00064269baff481a,0x0007cfbcdf91fd0e,0x00008bb37bbc02fc}, {0x000dd796f69d4390,0x000f169514b2d99e,0x000e19ae44e27a58,0x00096d80eca1ca66,0x0000470e96507886}}, {{0x0008bfc3dfdc228b,0x000e69648a35b377,0x0005a99b5c0bae0a,0x00058ada8cb8ab01,0x0000045cccc3366b}, {0x0008ef44164cebd7,0x000935e00e5f04ef,0x00079468e41e71fc,0x00072d753cf90644,0x00008b5223fa32ea}}, {{0x0009e2f5876d6e8b,0x000682b622d6a28a,0x0005411d793c48f8,0x000e9188d9eac83e,0x00007e4a6bab0a70}, {0x000e5baf1c43b2ea,0x000f42f347de0f18,0x00009638f46578c7,0x000d2919ca736df0,0x00006563f1f5d1ac}}, {{0x00054b5577dae353,0x0006dac3a655cefc,0x000c31d009d2f054,0x00063db96bd298fa,0x0000328a51d1e695}, {0x000098e43195f4e8,0x00062998010ade19,0x00047ccb6657f4ba,0x000da645f29a8440,0x000033a5443ee423}}, {{0x000f29899229a90d,0x0008ed71d5319e6c,0x000e3a8b7a6840bc,0x000a0e803e540771,0x00005611ee53afd9}, {0x000ca0ebbbefa73b,0x000c75ec48b72739,0x000dea0ec6082dba,0x000e03a0ab10dfbb,0x00001b7ebe5a1633}}, {{0x0004475ad1cac223,0x000ef7e1139532e6,0x000479c4a2008653,0x0000d1a875ad01d9,0x0000e6cf633b04b3}, {0x000ef6eb6b06e46b,0x000fa7b8410aa8b3,0x00078458d74c45db,0x000bd102675759c2,0x00002ef49575cd30}}, {{0x00012dd12ee579d7,0x000b76dd62d6170b,0x0001d75822a9a12a,0x000457bcd5259907,0x0000a36193b1869c}, {0x0006592e976ae5bf,0x00039dfecd57e29e,0x00014686de82c871,0x0003babc83a440f7,0x0000e19344afc21e}}, }, {/* digit=3 [{1,2,3,..,}]*([2^12]*G) */ {{0x000010b2c4391719,0x0007781393878f41,0x0000776333ff85ee,0x0000234ada4c7d8f,0x0000976011b124e6}, {0x0001197eaf49f638,0x0000560b0c4c2250,0x000b3df90dff2123,0x000d5f1a6a3abbba,0x000054bbcc7366ff}}, {{0x000c28718d13bd32,0x000443c6dd1a9b45,0x000b9cf87bbf3a89,0x00048dc8171c5e13,0x0000dfc779254f53}, {0x000662d985cabd47,0x000cbd971de02b9a,0x0004cba64588a6eb,0x000e67da9fd89457,0x0000e0f0ccad51e6}}, {{0x000572f9f177d653,0x00055c2394c3f74c,0x000307ad6c39e9e1,0x0009c8c9e7b18c1e,0x00003da596c7c22d}, {0x0000e12b74b9c00c,0x000e19f5d1339c30,0x0009e84425f434a9,0x0001c35b87294371,0x00000164ba54acd1}}, {{0x000276c4b8bceb84,0x0001b52d110648ca,0x00034dcbf6d4ec10,0x0009d02ad98063f8,0x0000da81d1a1fff1}, {0x0007cd23a9828ffc,0x0000ee64b3318ccc,0x00008b81cf1e389b,0x000ac6e2fb6a6c73,0x00006df66b31bcc0}}, {{0x00029d74220fbbff,0x0004f09ba10d52f0,0x000858df9405e1d8,0x000b23e53bd89048,0x0000d7bc7aa35dab}, {0x000f3807f06c21c7,0x0000b324828efe76,0x00017d5a3616f89c,0x00060fe30abf04a5,0x0000714fd2e0d0db}}, {{0x00013306dccac081,0x00050610b07430a3,0x000edd616b67ab62,0x0006666fd86597e7,0x000029abb54bf0c4}, {0x000f5f3c3ca87bd2,0x0002fde60e830fef,0x00077b8c7bee8fe9,0x00030251c192c984,0x0000b0bc40c43995}}, {{0x000e53d299f5d074,0x00060132e675167f,0x0007ce589b1afc7c,0x0006d18ac9a60464,0x000054e627504184}, {0x000160130ed07dbb,0x000342bd885fb63b,0x00069a710648bea2,0x000c83def2b055c5,0x0000a36e625f096b}}, {{0x0008c75e1c58c801,0x000493fcc95a4ccb,0x000ccbcf92ba9de0,0x0003adccdeb0eedf,0x0000d667d4f80f3d}, {0x00014a536269820c,0x000bcfe8794006aa,0x000e5cfb2329a308,0x000b2c39869970ed,0x000033c3069b601b}}, }, {/* digit=4 [{1,2,3,..,}]*([2^16]*G) */ {{0x000045511c092897,0x0007864079c97c25,0x0003879a283042ba,0x0002ee4881640c6e,0x00007c5babcf0245}, {0x00059a67088f360a,0x000d574be7e8da77,0x00033828902da352,0x0008c615800cdbe0,0x0000d69f7c9f0168}}, {{0x000c67faee039995,0x0003c9ff7f90c64a,0x0008da6ea4de174d,0x000df7063e494354,0x0000264880c2b7cc}, {0x000f34b49b992ccc,0x000dd406586f8a18,0x000db0e21e16b6f4,0x0009f8d32479ac4c,0x0000e8151f6d62bc}}, {{0x0002a1cc216cf37f,0x0006673828be9ae8,0x00051a85bac437f4,0x0005788c12ff189d,0x0000eb563bf24c16}, {0x00053b6c67069662,0x000a2cda87337d93,0x0004953dbcdc6eb5,0x000f7c033c186e3e,0x0000ba46a66d2e37}}, {{0x000f516da0abf3eb,0x000511b3381eceb7,0x0004188703c92ac9,0x000066bad7320ed3,0x0000ab7a126b7dbe}, {0x00059be2def303f7,0x00079d1e0c9f77ce,0x000f418dc0bf1f23,0x00067612c18d1e38,0x0000fcc5e3f285bb}}, {{0x000e7047e1754b8b,0x000261c0027aeefe,0x000af4e6d5408547,0x000569c5e7a6fa45,0x00004d3cd58e0048}, {0x0000014f3ae8e79e,0x0004649f3f22f2c2,0x000982a8cd0b6af1,0x000f903a1db91517,0x0000a3c809ad9ffc}}, {{0x000c9530fa12b5b4,0x0003b7d159b4d8ea,0x000844a0d45ccf07,0x000c18a74804446e,0x0000404e6c7177d1}, {0x00043a6ce1af18fa,0x0001b7fdffcb603e,0x000bf3d178a82808,0x00028691b63c11ca,0x00004dedc224d26f}}, {{0x000853b60aa5c141,0x00044850cc05c202,0x000abccfd1dc35d3,0x00025a8014357e0c,0x0000aa44ce9d5a52}, {0x000f9203a8444b4b,0x0004795384b0f3ce,0x000e5da54cf3f91b,0x00046a1d625ba1c9,0x0000f1fba3861d0f}}, {{0x0005caee30ae90b2,0x0000eaabea0d0cda,0x000e678562cc3429,0x0008b7564afcd941,0x000010c7a09ef6ef}, {0x000d352f82a591d2,0x000dcb43d2a1a316,0x0004e94705fe8cc4,0x000a07d8ebce978b,0x00006c78f44da321}}, }, {/* digit=5 [{1,2,3,..,}]*([2^20]*G) */ {{0x00038c7656047260,0x0003247a421e681a,0x00094956e4f8c6ae,0x0003241a51eaa012,0x0000984b1ef47c9b}, {0x000bd0d597b76968,0x000888e57ee6b749,0x000a112d29d432b7,0x0007f53092afe12b,0x00009ccee4996c5a}}, {{0x0009d7b54089685c,0x000000818348755e,0x00061b80f9f0ec69,0x000a144cf4d8cd38,0x0000ce669fe81f5f}, {0x00025091788f9dae,0x0004d3ccf2390a21,0x000027f3b3295361,0x000bcb1048d09250,0x0000807b39e2270f}}, {{0x000c73cdf18eddfb,0x000a92465ee8a660,0x000f950c877edb4b,0x00068baf24eff83a,0x0000822c6b31f6cb}, {0x00052f6149d2bb2d,0x000bc4a66ae65503,0x0007e1c68926809d,0x00029b9964c2803f,0x0000253298b86681}}, {{0x000dc5595e388c34,0x00062a44e3ea1099,0x000b41f7bd0670ff,0x000305d212c99361,0x0000f594afa3af13}, {0x0008bf205c01232b,0x0006e9ff08a50c50,0x00037741a7683353,0x000d2aa1cf70bdb8,0x0000a8e66175af7b}}, {{0x00068da909bf8c66,0x000bef4bad4a4b7b,0x000e39585b5bd7c8,0x0002d9a0ebb027fa,0x00008932a372676d}, {0x000954b730901cb5,0x000774fa3192062f,0x00047b351108194a,0x000765e32829e6a5,0x0000ca08b2eab343}}, {{0x000c343def27938c,0x000208cee32a1e04,0x000d142da3f15ca9,0x0009bccb61573b9d,0x0000094eefdd26dd}, {0x000f1a5136bb4da9,0x00036b2f3448cd42,0x00016795e7569395,0x0007db98017cd65c,0x0000e401530bafb6}}, {{0x000608550643d18f,0x00046902eb90a0cd,0x0007964ba821f27f,0x000ad5766f7c645d,0x000056feaa57c7bd}, {0x00029281bfda5eca,0x000e6624a7de56aa,0x000f7f3b15c09581,0x000e4b33d1a64a6f,0x000019a86e60c36d}}, {{0x000749f9b7c6c75e,0x000d8cbca35c8376,0x000145b32680eacd,0x0006afe87fd5b55e,0x0000b20d1bb16b88}, {0x0009055779b12bbf,0x0002fbe39fb6da49,0x000a128ce6f290ff,0x000a8133ad6fe0f4,0x000009e2a418b31d}}, }, {/* digit=6 [{1,2,3,..,}]*([2^24]*G) */ {{0x0004783f357999bb,0x000cd6bfacb340c2,0x000ddb9452c21474,0x0005eae3abed6ad3,0x0000b21b7651031a}, {0x000b68b8afc2a09a,0x000921306b70cdb3,0x0002eb6f51aac2f0,0x000b6f882c337185,0x0000dfe0c1b798e9}}, {{0x000f0633fd5a1de4,0x0001e75b5b8bde0b,0x0003c617a5d05e90,0x000706bbbdb1abcb,0x00004954a8c5aef4}, {0x000eea3ff6a6e47c,0x0001cded1274fc3c,0x000abe95f6140f42,0x000813bb4b4c044d,0x000055e87db3135e}}, {{0x000fda84e1d5d9a1,0x0005445ccdef5a65,0x000d72c0a0c0fe38,0x00013119ff360fd6,0x0000be1e8d80b016}, {0x0007e91025b45e13,0x000635259bf1b2f2,0x0001cc67e25bec26,0x00020ed7b8b4e7e5,0x0000a839aa5db80a}}, {{0x000de9738f4194d9,0x000acb996b636fa1,0x0002053a733d2726,0x000c0c787c0ec30d,0x0000447e9cc7ecd5}, {0x000121c284773c09,0x0005115829a0777f,0x000def08b496427e,0x0007784b11978694,0x0000e7b29e72c15a}}, {{0x0009c5550b66feca,0x0001ac065cfa1f7e,0x000d459ea5db7dd7,0x00041a3525e31050,0x0000d7abe5b21229}, {0x000ba80122d92fa4,0x00062fcc1c2487ae,0x000fd71b1066c376,0x000dbca6d767ca8f,0x0000a75fab5dcc16}}, {{0x00018af2988abcdf,0x00007e7da51801b3,0x000836b57f887559,0x000cf3b8b9939c97,0x0000793e3b6b0a74}, {0x000008a376841700,0x000b05cb453ce191,0x0001beb2c7708823,0x0008f4ec221d4036,0x0000e5a6cceeb1b6}}, {{0x000a0068ae66f002,0x000e98d648f0a6f0,0x000d2880f2620157,0x000017fc71776240,0x0000e0e293cde105}, {0x000f214854116f41,0x00003d5cd4eca320,0x000fc1c555e4fa70,0x000a1583fa0a23df,0x00008fcb8d2d9a9c}}, {{0x000995e2a8ed3d7c,0x0008ef319e47285f,0x0006d98a29dc712e,0x000e35c4402eff53,0x0000a61e310f7521}, {0x0009621c3196672f,0x0000ef17e8a70ed3,0x0002a7c4929e7744,0x0006da47eca48841,0x0000011451423a2a}}, }, {/* digit=7 [{1,2,3,..,}]*([2^28]*G) */ {{0x000a12ae6880b5f3,0x000d12606d252675,0x0003b21259ba1e92,0x000099b012facbeb,0x0000c50fdfbf37b0}, {0x000461c9ce223e96,0x00074efbd8ac69ce,0x00031ea8ecb90bdd,0x000ff6f657e5a4c6,0x0000584520b98a83}}, {{0x000f317635abcf02,0x000fb9e17618b959,0x0003bd99ba516a43,0x000290ed90ccf2ce,0x0000fc6d460c9fb3}, {0x000be090cde43021,0x00000908003ba61e,0x0000f57875a3b062,0x000c2ff51bb736f6,0x0000717f6e9157ef}}, {{0x000cf931ca260efd,0x000ec1811d22865a,0x0003e42c87d6e797,0x000158e63c692078,0x0000c9dbce95dcb5}, {0x000dc7ac8e39022b,0x0004e0ebfe466426,0x0007d6395f3037f3,0x00053975aa6845f8,0x0000f792fd611f53}}, {{0x00021726ddc3d836,0x000f388207bb48bf,0x00003bd7ef68deb6,0x0009a4a8eae2ebcd,0x00004c7f57ef51f5}, {0x000b223a1786d576,0x0000d11827902bad,0x0005a94572e7fda6,0x000e079dc90e369a,0x0000eca838c54b07}}, {{0x000235b032648719,0x000448b933de1d2e,0x000354c8eb4c5624,0x000c76d9c2bdda91,0x00007d743fffa73f}, {0x000109dce88013e3,0x000623b3bf4f8ed4,0x0001e761ca242827,0x0006c2900d356001,0x00004925d7e124fd}}, {{0x00066caa81982353,0x000d1d2d7649d8b9,0x000d63f3a355d098,0x000140fac27f7ca3,0x0000e553f6d03edc}, {0x0002c7f11ff4334c,0x000c7c62cb56a4d7,0x000a2108248735aa,0x0006fdcf064294eb,0x00001f9e4577b8d9}}, {{0x000bdbc293cd9450,0x000bea254e361d24,0x0006fb48576985bc,0x00073d3df2cb6a87,0x0000176969fcd1f6}, {0x000cacb642133a78,0x0008b73880e20b41,0x000b1463f31ea88f,0x000a27ccf1ff85b3,0x00008fffa162ca74}}, {{0x0009b92167cdd1ff,0x0001e879b893aa4b,0x0005479f5a9118fc,0x000292f6e73387c5,0x0000adf82eeb626d}, {0x000b76156e80e6a2,0x000a127555d1803b,0x000087e4359a783f,0x000ded027d63b63d,0x00009f9ff3222fde}}, }, {/* digit=8 [{1,2,3,..,}]*([2^32]*G) */ {{0x000f92d0cf4efe5d,0x0005660e2d221cb8,0x00059f07988c4721,0x000a7cca9549ef60,0x00000a3774b4016d}, {0x00095f61d001cabb,0x000053feeec1251c,0x000fedf2b2d744df,0x0004a5b7c20cc20a,0x0000f16c5f221d14}}, {{0x0005450677b7a8f8,0x000f669273d20112,0x0002c5990ba889fc,0x0004c34a40a85958,0x000036638b474893}, {0x000e189f3596ba60,0x000ede8b0754e964,0x000f93f1b2f417c0,0x000389d883169fd5,0x0000318fe4ed45bb}}, {{0x000e34d674d10cf3,0x0009cf962ec58559,0x0002af42d6955bb6,0x0002568bf1ab6c54,0x0000f2f33fb0fa61}, {0x000019573d1049ed,0x0009afd7f39a6214,0x000237be0f508927,0x000e57b42eb51cb4,0x0000f747f45574d0}}, {{0x000537af0c1bb4f5,0x0000206b90f4d6bc,0x0007c89cf37f3770,0x0000034d48d994be,0x000011c2158dd572}, {0x000bac1088dda1ee,0x000a5ad4934be26f,0x000dcaf7cc3d5518,0x00073d5233c17685,0x0000c3a8a2a888b4}}, {{0x0000fbb573c9aaf3,0x000a13cc6c7870a3,0x000cc5c2f0e71124,0x00003e3b57c921a1,0x00005b1badbfd70c}, {0x000286a9384dc1ec,0x000903a5febac82b,0x00046e3c694e98c4,0x000b10f2872b3abb,0x00008258ff96fa45}}, {{0x000a3a880b5f763f,0x000a54ed2fd06e09,0x00069d361c365267,0x000a6292b39fb7bd,0x0000801859aa1386}, {0x0002d562056479b9,0x0004e837087f6f64,0x000a2e3c3ace29a1,0x00010ad5dac94ce8,0x0000f0d3dce1bbf8}}, {{0x00001c95b2614292,0x0003bf1c4c90e560,0x000708120f1566d6,0x000a442e30662c3c,0x0000130cfa81a306}, {0x0001a8e4f57f7720,0x00069cca3398686c,0x000fde0e6d53c9e6,0x000b53a355d4890b,0x0000daf31990e2ee}}, {{0x000667ab1f0c1753,0x00015ab99e7dcd96,0x000e43f9da256a61,0x000cd6ff07c1ea05,0x000005700bcae1c9}, {0x00025462b2887a31,0x0009d772fd142f1e,0x000584057dd782f4,0x000cf99125f99638,0x00009fd039626a02}}, }, {/* digit=9 [{1,2,3,..,}]*([2^36]*G) */ {{0x0002bd34c58174d5,0x0003f900551f58d6,0x0002802c3872251d,0x00055506f5862df1,0x0000d93c48b2d925}, {0x00067d5bd6006f82,0x000c196ccc67a39b,0x0003014dbea6f756,0x0002c0140e853e54,0x0000bdc567509de4}}, {{0x00058faeda49f746,0x00076e4545a39a1a,0x0004c07e4ddb8995,0x000008d3576489c7,0x00004e4b39f159b1}, {0x0000340f66b546c5,0x00041deb912eeb09,0x000e55cca0e0f401,0x000768bb00b46c01,0x00005b61b34e9ad0}}, {{0x0002337e989963ee,0x000fb3778d59e0d2,0x0008c41782c4831c,0x000894d775c6a5ee,0x000023916557d0c2}, {0x000fe865d0eb314c,0x00004b2290d337d4,0x000cefa7842801b9,0x000fea73e9b332cd,0x00000d169d9fe877}}, {{0x0002370734a13273,0x000c4951afa89ab0,0x000638b8aa1df7af,0x000aa6581cfbaf42,0x00009db6d2b5130e}, {0x000805bda2f91a5a,0x000f8569add7abbc,0x00021fa7d3dcb0a7,0x000008724ab65ad7,0x00005152b96988f8}}, {{0x0008dc441177a460,0x000b7f039a7bedf3,0x0008ae7c2d9a955b,0x0008194f1525814d,0x000063c9f834f848}, {0x0004526841e87839,0x000a3a5f2b31c4ea,0x000846dcfe86a411,0x000d70b7529a3b19,0x00001356a07c5689}}, {{0x0004dea8910763ed,0x0008d76a0f7f958f,0x00065f9b96e5fcb4,0x0000c56a5447a4ab,0x00007d863d5775bb}, {0x00034a7e87e79168,0x000a4d961e88006c,0x000fe6aeb0539155,0x000ca15def2d8874,0x0000ac350b379226}}, {{0x00035d081443d166,0x000b06cc364b9f96,0x000bf84382342cbf,0x00029863b0a03225,0x0000ccd3ce60078d}, {0x000d10891292fd30,0x000b14073286f93b,0x00062cd16c887a31,0x000b46eb1275bf9f,0x0000335bae361578}}, {{0x000aca7614d9ff3c,0x000cf58f2459fee2,0x0006f62abd1f13b2,0x0003749e92d83fc4,0x00001dd32de427d7}, {0x000d593c3e566e7a,0x0007a4ccb02a7636,0x00035b65281c2f4e,0x000d42b57782c6cd,0x0000d88787f28210}}, }, {/* digit=10 [{1,2,3,..,}]*([2^40]*G) */ {{0x00083c6150b0fcd3,0x00011d9b0f4c85b3,0x000d05413f948da8,0x000e64cf075225cc,0x0000f31b12c7f62b}, {0x0001fc8368c17f6e,0x000a200bc68f43b2,0x000ac140e423d536,0x000d615335dd1ede,0x0000631c24a7493a}}, {{0x000262021afa86f1,0x000396b11457a23d,0x000148d30ea757f0,0x0001700bc4d2d1b0,0x000019b553598ce4}, {0x000bb670aa9c8f62,0x000ca8e05de28ab5,0x000f1e9c3dfc9693,0x000b9c6cae7e57e3,0x0000b1ceb548f6c3}}, {{0x0009fcb03cdcc63a,0x00026fc3afa8c753,0x00099aa9772fdb55,0x000651573534e102,0x0000ffe7179c664d}, {0x000fa10f5ecccf0c,0x0000003d6c622660,0x0007f57868df4395,0x000d741bec4f0f31,0x0000019916d7a461}}, {{0x00035ca876361830,0x000a719d1ca312e3,0x0004161d81461a65,0x0001128150080ab1,0x00008da4ebfc612e}, {0x000fb6ba8498a9af,0x000eaa0f8db9d95d,0x000b4f497099cf91,0x00030612d2ae144f,0x0000a3a28b123cb7}}, {{0x000577b9ec7f1ff9,0x0007936c299fce38,0x000f0939b9deaab6,0x0005c0624127222c,0x00008c2a3492b510}, {0x000a08656706b8d6,0x000bd14add6ad069,0x000d85a98a2296ff,0x000bd6537a875bde,0x0000705fef2603de}}, {{0x00079bdc3141d130,0x0002918736859cd7,0x0004305b9e4acdef,0x000d6de804c2cc4e,0x00003c2e8392d86b}, {0x0003c44aee7c9a30,0x000a9f8d49b095d5,0x000c57bc9b303ea1,0x0006a65c3579b5c2,0x00009ac7359ad03f}}, {{0x000cfc3afb8cec58,0x000eb630ab5869b3,0x000322634533076a,0x000a3dd50dcfb8f0,0x000053af6f4fb737}, {0x00062cefa4582dca,0x000b14554a478703,0x0004c8a663019bfd,0x00010e61487a210f,0x00005b5f361c1306}}, {{0x000c5d00f01c7cee,0x000e5283bdefe89f,0x0001519236fc45ff,0x000cc971dece8181,0x0000d1cb14da433f}, {0x000612bd3959bcfe,0x000c15b5732e6279,0x000d0a1cae163880,0x0007f335414ca771,0x00008b9e6520c1e4}}, }, {/* digit=11 [{1,2,3,..,}]*([2^44]*G) */ {{0x000a78a08b213629,0x000069fe0b35cce8,0x00087837cf37f5e8,0x000993dca66c7f2c,0x00002524b949bf2e}, {0x000020c71745788b,0x0006ecbfbf4c4c0f,0x0003de1c86018de4,0x000e41a8446691ac,0x0000194d41a0de5a}}, {{0x000a4a89ce76a94e,0x0002a0725c9649aa,0x000e16665847cd08,0x000fc40c099e9097,0x0000409ffca6f7b1}, {0x0005b80690941ed6,0x000af2c0ee9d6057,0x00075837d8e25100,0x00022b71662d279b,0x0000eeb9e98456bb}}, {{0x0000d52390e35da2,0x000347a9947be434,0x000cc7a3fc098e3d,0x000df6e6d781989e,0x0000c39102e43aa6}, {0x000ed0d300f3cb15,0x00072cfbe054683f,0x000cf45a8c0b1e35,0x000eda3da2224c20,0x0000be55df77f30d}}, {{0x0006e66528960b13,0x0004084aecb383e7,0x00012ad64445dc39,0x000e371361843616,0x0000ccbecccbc831}, {0x000bd416121383c2,0x0003a0d895a2efb0,0x0003f2f1e316164a,0x000225c3d3415323,0x0000905907000d92}}, {{0x000f0d3a3d89e152,0x00092d07f5eb1d0e,0x000e4887a4d5a30c,0x000349c359e31073,0x0000f4c6b7efbdec}, {0x000d3e9ba1426435,0x000e61c794b675a1,0x00010c63d8f4fd58,0x00076ccad091d118,0x0000b61623a40bfa}}, {{0x000afb7b790881c4,0x00047663e76c567d,0x000e824902002b8e,0x00047a3bd28edef8,0x00004dd2e818bb2a}, {0x0000dfedbc3f2f8d,0x00033e2eec700e75,0x0004c4d2fd9b6e91,0x000be2e8400e2f1e,0x00003325697f3217}}, {{0x0008e40347dfaefc,0x000e24464bf2717c,0x00064ec20795b0f7,0x000d3f15dc99d613,0x000007fce2951600}, {0x000338bc8bebbdac,0x000768547c02d825,0x000040b845e5e89f,0x00033d3c50032f1a,0x0000ea7544feb3a5}}, {{0x00087934d217a2e3,0x00064fa4702d663d,0x000431f1b099e8c5,0x0003996d91bc47e6,0x0000fd21287d5f61}, {0x0000bae682fa08b0,0x0005c1ca371c2fc9,0x0001c428f51699c8,0x00050416f29d7483,0x0000ecefb669fa2b}}, }, {/* digit=12 [{1,2,3,..,}]*([2^48]*G) */ {{0x000eb9068755cf37,0x000eefe125411487,0x000af8ca81887394,0x0009dc2e4c65d446,0x00002aae64629e11}, {0x00000941ec6ad734,0x0004cce4573e558e,0x000254b9684a7eec,0x0007323d6d00d4f9,0x0000ef44f58ce421}}, {{0x000e0f87d3ad2ac1,0x0001d0f92c5ce59d,0x00000b6a5d2670cb,0x0008eb8f05944ac9,0x00001aeed239d966}, {0x00038e47c488ea6d,0x000848083d7451b0,0x000d31fe2406ea3f,0x000f9ad22197b43b,0x0000c8f8ccbf8a6e}}, {{0x000cfbffc9188216,0x000c7e0fbf5fd2b3,0x00062452f51cb7e5,0x0009f0a73f6716bf,0x00002b74252c05f2}, {0x0009d259e88b0f1b,0x000175841f6142f1,0x000378ac867525d1,0x0002d6e54c3b5661,0x00009fade95d9a45}}, {{0x000648302887281a,0x000c1f9de66ec79a,0x000a7dee213f3d39,0x0008b8289c3c50f1,0x0000510a53ce0b69}, {0x000c3fb06f799adb,0x000a653746501566,0x000c947b2cc95a87,0x00051bbd7343c061,0x0000bbff69e4543e}}, {{0x00041aa7a0a745a0,0x000243371bd1327a,0x000b5f82492d43e3,0x000478cde41b9031,0x0000f5e1e18cda04}, {0x000c186247853141,0x00025ef5518b5db2,0x000b7c8ee0c4cfdb,0x0009d7acc9f6ec1f,0x0000efb06595d6c0}}, {{0x00038dcba75aba90,0x0006d150f881b80d,0x0007b47c5e9b61ac,0x0001289f56af52ca,0x000040300d977fb3}, {0x0007184c01fd0c1e,0x00056b6e134a5687,0x000d7165340112a0,0x00062e56daed90cc,0x0000c553aa7974bd}}, {{0x000472aab109ef7c,0x000d759b268a33d8,0x000314e79dbdfe41,0x00077c147dd06eeb,0x0000ae5583823c5b}, {0x000d83c8b1c89525,0x0008f1ba0321bc8b,0x00098beeecf4b71c,0x00034268f32934ea,0x0000580dbb671a4b}}, {{0x000381d11476ddee,0x000dfea0923e2398,0x0007745bd4959204,0x000467d67427ad01,0x0000f022a754935e}, {0x00099f524e0380a0,0x000fb5f1a73057e7,0x0001771d86ee2b64,0x00013c9aeaac4852,0x00002c8521c0992a}}, }, {/* digit=13 [{1,2,3,..,}]*([2^52]*G) */ {{0x000c43b153adbf74,0x000fc0351fec7fe5,0x000109e6007a66ed,0x0001623d8042353b,0x0000dc97176e832c}, {0x000c75fb1db1e5c9,0x0007315b98ff73fe,0x000aa1cff6aa02da,0x000a265f9e808f4f,0x00000aa28be36412}}, {{0x000f1c99ce0fcd68,0x000eb232a8468dba,0x00075d822732ea65,0x0003cadb2ce2186a,0x00008ffd479bd227}, {0x0002ad2f2f26b61a,0x000e086706aae909,0x00023597cfb7041b,0x000c84e3d5fa755e,0x00002035bf8f995f}}, {{0x0006c1ab9ac4754c,0x000a0d3f305a1b45,0x000a62dc0f497e6e,0x00094f84d27e3a3f,0x000018c3569e524b}, {0x0008954e380f5cb8,0x000ca72ea4581219,0x00032849181d8221,0x000ccf6fa082f65f,0x000010ca5b00e304}}, {{0x000b892313de667f,0x000856a478a7c5de,0x00099242875c872d,0x000e09b67b5513c4,0x000097e010fe70fd}, {0x000f05360ee268c1,0x0002067cd32139b0,0x000bc187c981b514,0x000da8b5a1ac8d4f,0x000062417e2d12e6}}, {{0x000e262502e26d19,0x000cc294e23f905e,0x000a7733db961ef9,0x000f737178f1fb6d,0x000089b69fbb32ec}, {0x0008a359a9bccae8,0x000bc00a01f33727,0x000b213bab1c81a0,0x00017e0781855aa6,0x0000acc1b78b4298}}, {{0x000d3a83016e5135,0x00004b0f7bfadbde,0x0002be716a3c508b,0x000b9fa6a490deaa,0x0000a04d9e644485}, {0x00099d16ad25b5d0,0x000965a72cb4d07b,0x000c45a95a184010,0x000cffc8e2b32d14,0x0000fae6e86e4f2e}}, {{0x000115e55a0c9314,0x0009e5c920a3d764,0x00090371034ea18b,0x000c7a6a099ddcaf,0x0000b937dc2249f2}, {0x0004a1a430f0a7e5,0x0008921dbe965cfc,0x00011d3fe8f106a5,0x0003c548ac702618,0x0000484226b080f1}}, {{0x00050f8849e6d32e,0x0005de16485df445,0x000343924e7bc29d,0x0005ce29bbfec62f,0x0000eb802f320f2b}, {0x0007542bbb64f333,0x0006cf9bdb3bfb33,0x000a1cb884c1d3a3,0x000b6e1067cf3bc7,0x0000f12a31d7601f}}, }, {/* digit=14 [{1,2,3,..,}]*([2^56]*G) */ {{0x000a78f1f8a4a913,0x0001a53dbe738720,0x000d0991a59e2221,0x00026f9f5ad99cad,0x0000a0db802a3807}, {0x000761c7dfb4f1c5,0x000aaac819cce7f0,0x000ffe34868e7098,0x0001409683d61037,0x0000bf205e57b7b5}}, {{0x000b5f661a972624,0x000bd74a82f75846,0x000439654edf2cac,0x000e093dfab85faf,0x00003fb0efa0724e}, {0x000016f53b0119a0,0x00035bc8fc81d0d5,0x00065d2986844536,0x00064f6d10b6491f,0x0000f3c88c621a4e}}, {{0x00072a17f34c5177,0x00069378bc26c203,0x000aae0245602bd1,0x000daa666a592d91,0x000016886aba17bb}, {0x000fe68e30451039,0x00030de1d7013e55,0x000724cb6f2c4b0b,0x0003148da358857d,0x0000aac623d2ec47}}, {{0x000ff46b8529a018,0x0002c856b95c024c,0x0005af7f76e4d82a,0x000e5358c6b833c6,0x0000a6c41262e110}, {0x0007c304f0833403,0x000b476cdb310820,0x000882de171aa384,0x000e4a1ada294142,0x00008b1ad2ef16a2}}, {{0x0002720142bcb30d,0x0004caf604d0edda,0x0007963145617526,0x000d19086189c1e6,0x0000ab01c692b04d}, {0x000e4b0ba8ed3c18,0x000c6281acfb4e54,0x0000a6319f616513,0x00087baf1796295e,0x00005e79ac9b28b5}}, {{0x0004588c9fd7da08,0x00009238d0c391d8,0x0009d6475a78682d,0x000e18333ddde082,0x00000c88440e9de9}, {0x000f21ac6d8176ff,0x00059509d46f6d15,0x000bbfcd5daff943,0x0006880191bb0a8b,0x0000f7732b8f8fc2}}, {{0x000772d5ab3d89e9,0x000a2a786c9072fe,0x000323866f1580ec,0x00096f8fd834175a,0x00003711d4a4adec}, {0x000c34a6b9b4a308,0x000138b0de23a020,0x000de3ce5bf10e00,0x000c632a5f298d28,0x000007a398f7e1a1}}, {{0x00040cd73f7c45c6,0x000d6afe059c3fb6,0x000b168d4eb1f87a,0x00003fa3c3979a52,0x0000eef460cdb1e4}, {0x0003e502724bb3f3,0x000c29d922d13d94,0x000538b4a53f3f1b,0x00045f547e7a03cd,0x00007631e2102c41}}, }, {/* digit=15 [{1,2,3,..,}]*([2^60]*G) */ {{0x000bf06970e164d1,0x0008cd3d3087a7c9,0x000e7c899c27a88d,0x0003718a37c9cdf4,0x00008494d5abb411}, {0x0002375d9d8b29c0,0x000c915a2f740653,0x0005acb02b92dd45,0x000a898a23f6bf51,0x0000e69248c435bf}}, {{0x00054fd6113a9f82,0x0004070e67e63614,0x0003f2feb78ebe73,0x000f368764360b90,0x0000ba3b3d8b7902}, {0x0008cef87490b8a1,0x0005005f31b31880,0x0009b4f4db117595,0x000e60bd5d60056c,0x00002b13fcaed254}}, {{0x00074449a7a4edea,0x000695cfd20f1f84,0x000b33b64b26b1f1,0x0008c9f380ed7d83,0x000021f9564dd199}, {0x000c7d3a720e347f,0x00057bdf09d4e985,0x0009476929807897,0x000385a1f34ce2ce,0x000069e6145e419c}}, {{0x00071ef16f55d400,0x00089bb45ea57fc0,0x0005543ca7019543,0x000c1983cf09f2a3,0x00007e91a8420554}, {0x000d70162a9d06ef,0x00031044a66261ec,0x000423dd900e14c6,0x000b4cb1317c1300,0x000049431bd946ea}}, {{0x000548a60bffa601,0x000b7e0c4e341ed5,0x000db5bad903708b,0x0008a5cbc42d78a1,0x000052ad7377be14}, {0x000cda3ef8265d6d,0x0004490c675cbb3f,0x00033d235cfcb34f,0x0003cb0c2954b5d3,0x00004a7d16a1a320}}, {{0x000dffbcdc0e5cfb,0x00040f611432a75b,0x000c16d43eeb8cc1,0x000997e3b489f974,0x00005c174e0722ed}, {0x000a9b6afb9c1d83,0x000295cb574a38ce,0x00015c4a8da546da,0x000307688d2edc0e,0x0000ffc898fef45b}}, {{0x0005f1be45b69cf1,0x00077a5a8c531e35,0x0007d0264570bb79,0x000a61a0a43c059f,0x0000cd74a04320e4}, {0x0002e876cf3ac0a3,0x0002b212cb77fc35,0x0006c032db7672e6,0x000bc2045a0ba3fc,0x00003e7bc4433ad9}}, {{0x0008434d0614aa12,0x0009f14184341511,0x000c15b898bae977,0x0002ebf5641d82b8,0x0000383af5661643}, {0x000d3f02c73f990c,0x000f66bbdc7ce552,0x0005ec6348df82e9,0x00053f0f336aa8d7,0x000042e3b2dd603e}}, }, {/* digit=16 [{1,2,3,..,}]*([2^64]*G) */ {{0x000e020bad830d23,0x000e890dffb31b33,0x00080ecb05c101f9,0x00093ecd0e0498bc,0x000002787f882aa2}, {0x0004ced220f8fc84,0x0000fe0ee3777fd6,0x00013b128cf5cebe,0x000279dc03a03889,0x0000b0969723de23}}, {{0x00089aff727ef3ad,0x000603db88fa9c53,0x000ae077795ffeb9,0x000f0227cb70429d,0x000020afe82316db}, {0x0008e18914bf7060,0x00030517cd090fab,0x000e406443b1e66f,0x0008fa24b46dce12,0x0000ff1016808f2d}}, {{0x00034c883dc54470,0x000b04e4e9a0e55f,0x0009166a2be76243,0x00080a78fb4cbc81,0x0000bdfb703ae37f}, {0x000288ec217cda8e,0x000242af41561869,0x000ae9d302662bb7,0x0003c9ce64f29150,0x0000e0d4441bc035}}, {{0x000aaddca9a95262,0x000a89a303e9913c,0x000a50f3c701c63f,0x00057fb97d667ab0,0x00007c03d7c88e65}, {0x000e712eb1056070,0x000d8dd86ccbab24,0x000986d684936aed,0x000a6532196f8a0a,0x0000307b826248f5}}, {{0x00058b5ebbe949f8,0x0006e982215ad88f,0x000f863c0b776229,0x000f513cc83dd6cf,0x00001ec094d81098}, {0x00069aabe0432d02,0x000c8455957d014d,0x000dc1eabe4e52a9,0x00016f94743ba8fa,0x0000c395d97a1763}}, {{0x000ab7799458b24a,0x0005ceba3064364b,0x000068f036fe19e2,0x0006559aabd83d74,0x0000ef812190fdf8}, {0x000d27b65593fefe,0x000edaa457b21506,0x00003dff40a1ad85,0x0006e3266d0f06a3,0x00008114f4f8bb41}}, {{0x000e2d38fc2ed938,0x0005f8f0f8582acf,0x000a35ec48344664,0x0009b158de6f09dd,0x000091e5ece778c6}, {0x0004ba991c13d675,0x000d987d5575af4a,0x000303a7e6e78063,0x0007ed226b621e8d,0x0000c9bc10419598}}, {{0x000581a88a45b65d,0x000138e58c1b905f,0x0005bfe1ccb78920,0x0001d714cbed65bc,0x00001af7dc8c02b1}, {0x0001bc0cd3a7cc82,0x0008c01a77b79834,0x000e2a4028e9aefe,0x0008598eeafe875a,0x00007a0698fe11f3}}, }, {/* digit=17 [{1,2,3,..,}]*([2^68]*G) */ {{0x0005759c85448853,0x000aabfcad786b80,0x0008fe78ebe9b99c,0x000bcfd1db36e12b,0x00007255a2e05387}, {0x0003a3ea150ad323,0x00039671ae58d44b,0x00052384bc65bc2a,0x00030041ce078e1d,0x0000115f1b1ce72c}}, {{0x000517480eed542e,0x00021362ef7e34a4,0x000dd0396add6456,0x00038b39228bfcc5,0x00009fdf904ca0c5}, {0x00091ec74d235de0,0x000824aa0a476bfd,0x0008d616896ec237,0x00060bf5699241af,0x0000a7b9be3c548a}}, {{0x0002854f2b4c5818,0x0009ca26223a3e67,0x000aa188c6df8d84,0x0004ebd1debdf2e3,0x00000bfdc0a33d8c}, {0x00049164502ad485,0x00013c4eec044436,0x000526b7ad1ce82b,0x000ec1b7c386c272,0x0000a6cc4f4bb8de}}, {{0x0005c302ade9556b,0x000c25ba2e9b3525,0x000ce9e47e328af1,0x000cc99d3391ef41,0x000074cd669ab0ff}, {0x00003e4e3226acf3,0x000d02959e429671,0x000d490fca65ad22,0x0003563aaa840699,0x0000e26a1c2cecc6}}, {{0x000c3180561c002a,0x000500356bad1178,0x0006c78568e636d7,0x00001af8d07145e3,0x00007730567cae79}, {0x0005ddcb77d9db90,0x000989d16e89691f,0x0005142a2f824b7f,0x000bfaafb5c9b7eb,0x00009b34446f6015}}, {{0x0000be45824c88aa,0x0001e847b35a949b,0x000027aa0e3a35e8,0x00082301594fd284,0x0000aff184b8e873}, {0x000e135810fa4740,0x000a8f7398d7d5fc,0x00096a1f3aba6165,0x000924e3aaa99a8a,0x00006ff0fd3b6295}}, {{0x0008b7dfddda1bc2,0x0009d5f713ecc26b,0x00012edcbc93512b,0x000095029ffeb33b,0x0000ea0649923564}, {0x000b5a0fcd32167d,0x000a0c2eb30bde37,0x0006cd0182008416,0x000502b2663d607c,0x0000810c96305b2b}}, {{0x00075de4e92defc4,0x00041008988331c9,0x000c0919081aeb17,0x000d648a30ce4a2e,0x000026e7838a9a36}, {0x000a0b6309bd2d7d,0x00000cc1a4ae8899,0x0005163b33b1c24b,0x00086db2aa814234,0x00002ad9a69fc78c}}, }, {/* digit=18 [{1,2,3,..,}]*([2^72]*G) */ {{0x00033c6ba4e4651b,0x0000b714d4ac4672,0x000f1f8da8cf9566,0x00070ed70decc371,0x0000674732b20783}, {0x000416d4ccc773bd,0x0006ae87951d7270,0x0003dfb56c848ff3,0x000110a61506a849,0x00008371eaa467eb}}, {{0x000ee2fda3adfe0b,0x000cbc964e7d1066,0x000859476ce6a9bd,0x00099c04a0115b0c,0x00005e02dca4c956}, {0x0001f6211377eb91,0x0002272bca2ee830,0x00047cf1f57b245a,0x0001c1a7d9b4707b,0x0000b469bab2774b}}, {{0x000fa67dfd6586eb,0x0005cba23faa1dfc,0x000ec5d6f358953e,0x000b2a0f467275ae,0x0000815967b0b0e6}, {0x000f133012b89b41,0x000c7839cc04a01b,0x0000dfd73dd924bb,0x000098a5cd218012,0x0000abb11ef29bf8}}, {{0x0007889f1ef22320,0x00019c7409a50397,0x000004e03be2c82f,0x0003a335ac44f932,0x000048bb35985682}, {0x0008d6cec1cf253f,0x0008603eb1d13e10,0x0000ac34de98e74d,0x0007facaf64f6057,0x0000f814e7e3d779}}, {{0x000b2eb0d1b96aa9,0x0003ce52ccf0cdee,0x000d534ef25783ce,0x000dade4e251f429,0x0000fe9693de5797}, {0x0003d69c6ab9935e,0x00095721ca8d8a17,0x00093eb262399131,0x000a9e38cbcd30c3,0x00003627aba51d95}}, {{0x0000e575ef764b4a,0x000d5e73c69849b6,0x0002be1ee61ad29f,0x000a7118489017dd,0x0000c95e3b71febd}, {0x00053465ac960924,0x0003ffc835666698,0x00072fa4a906265c,0x0005401692c81259,0x0000e76f87940773}}, {{0x0005c3ea7b82f5c5,0x000f3a98adfad6a4,0x0004b182c494694d,0x000b4144a06ec313,0x0000570befac5b82}, {0x0006808129f952e9,0x0000214f87c3f19f,0x0007be905a6fad26,0x0005c2831e56687c,0x00003107f397623a}}, {{0x0001bcc89e35108a,0x000433f1cbaf57cd,0x0005b13ac924efa4,0x000a1de3716559f3,0x00000a88e8800370}, {0x000be0a8c286ea33,0x00069ebd50c6e203,0x000284d0897fc5ab,0x0000e02b5b360274,0x0000055716f994a2}}, }, {/* digit=19 [{1,2,3,..,}]*([2^76]*G) */ {{0x000a63d5b99708d3,0x00077b80189a4d67,0x0001c402efb29bef,0x0007673cb7eeaa24,0x000028cb6de5c5c2}, {0x000a7b49cec231d2,0x000c2e2e6a7eed24,0x000f17b13725955f,0x0001cfa2040cfab7,0x000015eff8dc25c7}}, {{0x000cab1c0d41a942,0x000abe60f7d4c4d9,0x00036116cc38b202,0x000f132bbf6b1793,0x0000f9aa8774e068}, {0x0000627a4bac9fd4,0x000eca593cb4b882,0x0004179312209cb9,0x000fbfaa78ec63c7,0x00002d21251bcfcc}}, {{0x000fb305334d7b56,0x0005a11f7073b233,0x00097794e41b5755,0x0000dd099a53713c,0x000056ead5a9a5f0}, {0x000696f1e3511dc7,0x00070e5e30fd2ece,0x0004ace651828a64,0x00061ce007b8ff60,0x00003da66390b892}}, {{0x000e5ae3e6119407,0x00097aa090ebd0ce,0x000926e424e2d9ea,0x0002a373d167ef1b,0x0000fff36dfcd511}, {0x0007745caffa3fbe,0x000fa5a835034558,0x00047bf2a224f7f4,0x0005c65ceff0183b,0x0000d9bfa74ccfab}}, {{0x000c13c73f076b32,0x000eaa3baf1a5581,0x00086b1ccf225af7,0x0005b36fa0d82d4e,0x000009f416823464}, {0x000cfcb2fbe643e7,0x000163c46a73f613,0x00019477d806abcd,0x000c02d04bc1028a,0x000068888cb668be}}, {{0x00070b8d9b429c9a,0x000765ad81cb53d5,0x0006825bd6946011,0x00036a30833a082f,0x0000297122b1c99f}, {0x000b84805c3abdf7,0x0008cf2e24b1ffc9,0x00015d922efe9529,0x000726f045275a89,0x00009146aab998a9}}, {{0x00051d89cdbd4b33,0x0000e1195d208087,0x000c6618eae8de7a,0x000cfbdb08e2fc12,0x000097fc24f3fc4a}, {0x0002071844eeaa70,0x000b2c004c259869,0x00035fcca2b3e1e6,0x000be4a1211da1e8,0x0000c881208c73ff}}, {{0x00059054f831d0b7,0x000c9d47d4fd9c7d,0x000042e12faaaa26,0x00077d5ac2859985,0x0000eda370be7969}, {0x000d71d95c0be637,0x000cfe8210052f0b,0x0002ffae97c4601b,0x000173f1ecbc604c,0x0000e3efc580b688}}, }, {/* digit=20 [{1,2,3,..,}]*([2^80]*G) */ {{0x000ca15587feffa0,0x00007d69e4ad8348,0x0005a0745585d074,0x0004dd6fbe561988,0x00004ee9ebab10b2}, {0x000075c0f4c12d76,0x000c9c51c604fc27,0x000e336d0acf4acd,0x0001d2782fa52bfc,0x0000e1d078fa8362}}, {{0x0007a1bb2b806a85,0x00010ad5d0f42438,0x000a0e9e414efa30,0x000decee7e442123,0x000004ae4288b6ab}, {0x0006fcb927b1aac6,0x000c923b71d358c0,0x000d6dae155e1c85,0x0000b8f47e180f48,0x0000d80dd64084cb}}, {{0x000c3819ec64698b,0x0001cef36dd1f0db,0x00056bdfd770e4d1,0x00094701d179158d,0x000048153ce25eb9}, {0x0007a54fde983909,0x00079fe2d6fc31d1,0x000a704f10817eaf,0x00018244a63591a6,0x000042346600f554}}, {{0x00086430d7fff59a,0x000407bfe742e8a6,0x000ce06f982b9219,0x0001341a8b86cfc2,0x000038414a199ad6}, {0x000261028e2c39f1,0x0000580856a06f10,0x000c3034d34805c2,0x000c9d1b3f930218,0x0000713f457674c0}}, {{0x000c8821b96672b1,0x000b479d1f5709cf,0x00069a5142759c76,0x000413a6cc7a9822,0x0000bc2015b783b1}, {0x00011781bf4be622,0x00059bf2b0bea43b,0x000591cfdd294197,0x0004951eac3587c4,0x000083169e62e66d}}, {{0x0004800da0723bca,0x000093c8381d3859,0x0008ca980524452e,0x000e56846dfa0213,0x0000a77a80d82d32}, {0x0003fbc419c86b5a,0x0008570216c28757,0x0002036e6e748680,0x0003d88b7a685ac7,0x00001764627b5fae}}, {{0x000d0556b1fb1041,0x000441fe146f9ea8,0x00063c4132ff339a,0x00097b3d7ef85bcf,0x0000f0f57c5389a0}, {0x000f83b5bda1160f,0x000e5fea66e792f2,0x000e11651433eea4,0x00043b1f3fff4fca,0x0000a71c3fe5b1c2}}, {{0x000edc2023cb0df4,0x000e15a245918b52,0x0002a907208773a4,0x00086e0d9a6aaae1,0x0000261f56f9bf55}, {0x000040260a081069,0x0004409cfa60884b,0x000dae4831b39805,0x000cdedf7f55b1d5,0x0000554210f16ef2}}, }, {/* digit=21 [{1,2,3,..,}]*([2^84]*G) */ {{0x0006e859204db305,0x00087aa84cdf064d,0x000476456139bb92,0x000a669413d7ea88,0x0000c554483aa1ff}, {0x00030892ed180808,0x0001514e5daefb86,0x0005f81ca589aaf2,0x000415eee4f96f7b,0x00008d470079bb0b}}, {{0x00000d355c9bd11b,0x000cb6fc28506bb4,0x000063b3e8402465,0x0000c6a81ba22d65,0x0000ab2dcbd1e1aa}, {0x0003f1abe645e253,0x00037df84be1b5f4,0x000a2eaf46232053,0x00026f14ac708021,0x0000f94646488beb}}, {{0x0003e9a7a82d20f0,0x000c191011f25f2a,0x0006ac8e6399e015,0x000f96fbec312a88,0x0000dd5140aeda47}, {0x000f31326b47318d,0x0009b6685ec73d4d,0x0008442cde2c9ec7,0x0001cf4df119aecd,0x0000b1ca9564b32a}}, {{0x0005852126506ccb,0x0007b8b3567cce2c,0x0005a3f24ba94aac,0x0008b36905cdf4c0,0x0000f5f559be547f}, {0x0004e62aade7a1df,0x00070fda3087ae4b,0x00043d89f56b8b9d,0x000047ea3eb4c64c,0x0000b7e537d8c69e}}, {{0x0009491dfe5f6ab4,0x000e01a9c0af823d,0x0007d2b3542fc362,0x000aeb04170b0112,0x0000f0f17bc44116}, {0x00001dfc9184cf6f,0x0008795ceae6816c,0x0000bff2e914dc87,0x0005db696b2ae839,0x00006ccd629e88af}}, {{0x0009bb90f88095a6,0x000ff19ce3057ada,0x00078b2667155c28,0x0004f832a01e476d,0x0000da9445a1652c}, {0x00083a6827ea8efa,0x00075db1af2b0317,0x00031dab94d69b7c,0x000ace2874eb38af,0x00000ed99114fd9b}}, {{0x0002e3a4037f17e3,0x00018f91a4fa4d89,0x0001cf02f81fa984,0x000c7517c7292d96,0x00005af0c0e688bc}, {0x000ec90127a29b07,0x0004ad087444c40b,0x00087c273955714a,0x000da2fd430880a5,0x000015ecd51424df}}, {{0x000066daafd6cefe,0x000fd8c1decb6ade,0x000b96ecece59c8d,0x00010c3e12a24a77,0x0000e7c32fd24cc7}, {0x0000e4f240e9bb7c,0x00052a63b06db070,0x0009644ee837ada5,0x00051ca58ce980d1,0x0000aa5d14de7e74}}, }, {/* digit=22 [{1,2,3,..,}]*([2^88]*G) */ {{0x000d50cf1edd62f5,0x0000229f48d97a0e,0x00072ae88c3c7ae7,0x000666ff47bf288a,0x000084ddfe5848c6}, {0x00037e936731fdf9,0x000c18d98bc79711,0x000a6be30714bc7d,0x0006a5cea912c10d,0x00001cb844e4e62d}}, {{0x00093634626e343e,0x0009d4e4c8f9696c,0x000648a06f699957,0x0006e5ce7306f6b8,0x00002775c8d8e799}, {0x000e678bf09d221c,0x000f115c2acdbb47,0x000b48b41f5251e1,0x00074b087f912177,0x000040e7726ab38d}}, {{0x0008aaae4fdd396c,0x000f9371c3f3cdc1,0x000dfefdef6e8a9e,0x000577c6b58042a5,0x0000cc3bbb7bc4f3}, {0x0003e4adedfdd556,0x0004148c5fb23f58,0x0002d61e09ea4513,0x000b38ca2b322923,0x000042101a910b5c}}, {{0x000ab3cc064f530b,0x000f8e1758919b7f,0x0004c4e60731153a,0x00013a335e65033d,0x00000876a8b276ce}, {0x00066ee22241ecd1,0x000e111e861c98a5,0x0007dd490b7456b3,0x000c40a9aff4eb17,0x000089b1ed9d8f77}}, {{0x0006f5a394d7786d,0x000dd7ff0605880d,0x000dbaf4d3e66b3f,0x000f09abeb798da3,0x000055a81a432168}, {0x000e4853cae87841,0x00051aa0e48c3e00,0x000e17bcbf4bf671,0x0005a084ce2b4df4,0x000010852e0a41f1}}, {{0x000666f50956c896,0x000bf47304e9abf6,0x0001770f44938548,0x000bb75c17622116,0x00005f7c0b74c493}, {0x000e3303459a009a,0x0002d40ab80bc6fb,0x000f5d3096dbed19,0x000e7a5fc682575b,0x0000ba698d48d53c}}, {{0x000db6a830ae3327,0x0006ec5c4f57bc5b,0x000a40ac4ef38847,0x000d07b5329ba2d7,0x00004b55633b22e2}, {0x000719d1f38f3c87,0x0006dba25c7f63e8,0x000c8bb16e712c08,0x000bbc9fb85a3b64,0x00004ee16f039ef0}}, {{0x000e6872857a1fc7,0x000c9ff8f504f24d,0x00081bc9abd0a0d9,0x00041beecb4fadc3,0x000023862936a94e}, {0x0003f83e75fc753c,0x000467a5a6be754d,0x000f568dc06afc75,0x0006471ce792eeb2,0x00005faaee47d2f9}}, }, {/* digit=23 [{1,2,3,..,}]*([2^92]*G) */ {{0x000beb0f912b74fe,0x00024e0ceedc375f,0x000233ee745fbe8e,0x00026ef0e1aa68d9,0x000055fc1cf206a6}, {0x000a1b9e08712e7a,0x00065cfd635f80ef,0x000c1edac5fd108b,0x0003f1ea431df6ee,0x0000e1c052234080}}, {{0x0007fb664bc0f09b,0x00027953cd07f8e9,0x000c3bf000b91399,0x000d8f8385a1b37f,0x00006e74ded609cc}, {0x000f026ec473ea77,0x000ec30766bcfe1d,0x00092052bf2f7fbb,0x00066af18cb47a32,0x0000f8d459301148}}, {{0x000d957b3086691a,0x000bc6640915a8d6,0x000db59a99946a29,0x0001ba932ca93c43,0x0000a61a0c684fe9}, {0x000e112815bf0033,0x0008f86ba8d36e22,0x00069f434a9ed1b1,0x0007541b5d3c1410,0x0000cd2ebd04cc01}}, {{0x00007cb8e419e083,0x0007df855eebfb75,0x0008683a5785328d,0x0007e9875db0c77b,0x0000d1bc968c0a59}, {0x000fa1047eeeab4d,0x0004a680ca70ad4a,0x0003650232668dd4,0x0001ccc3210d1f17,0x00005bb2ee4e7fb3}}, {{0x000156fb22c5f89f,0x000baf786759c0c3,0x000b8ad9fd10ece4,0x000420e270e31780,0x0000e7a6211a0c2b}, {0x000d738125ef6358,0x000741a6f2027091,0x00087d9bbf1f277d,0x00084be2727e7b35,0x00003b209aa33e2b}}, {{0x000bab750f2b65b6,0x000bbe5d53e3b5b9,0x000529212a7403d4,0x0007672e23e37628,0x0000fe903a2ce050}, {0x00091a16cf570fb7,0x0007ea30b325dc52,0x000c572a94bfb860,0x000c31ec4905f827,0x00002eeb8c97f381}}, {{0x000502e9c14b6997,0x00067948a290b6b8,0x000efd415f1bcdca,0x000fb573e43a322a,0x0000f52335841e2c}, {0x00051c097d3fa948,0x0008f21296302601,0x00054acf5820c0d5,0x000ac3b8f2e1ed58,0x00006d6646cbc656}}, {{0x000f6acf96ec2b85,0x0003f961cc16524c,0x00017f0a2d06747c,0x0002d657c7001cbd,0x0000f298db084afe}, {0x0001ef2df12f671a,0x0006fce712fdb1b0,0x000a74776c01c506,0x0006bdac0f403492,0x00003e9934fa8d69}}, }, {/* digit=24 [{1,2,3,..,}]*([2^96]*G) */ {{0x000b8941abd31f02,0x000dba1da7d32599,0x000f0217ddb34198,0x00084ea8b89523a0,0x0000014cc44056b8}, {0x0004f8849efd4ee8,0x0000a87f4adfefb9,0x000fd2debf1b8171,0x000a5389d38a9a99,0x0000179277af2b67}}, {{0x000ee9e2d3a6e28e,0x0005486d8ca2fd5f,0x0000834918eed56d,0x00045736889a2778,0x0000a1a65569ef20}, {0x000b609a501e2a36,0x000a5b23de2f87e6,0x0002c9a6b1ea0ae2,0x0009615f537d0763,0x00001770d1ffa3db}}, {{0x000d1fa9047d3c68,0x00041e2d51ce4e21,0x000b10c9c847d157,0x00062380167a634e,0x00008966868f8c07}, {0x0008f2cdc401ce66,0x000ac97d1c838e87,0x00062b7c27f46062,0x00036e04a047da68,0x00008a2cacd5afd6}}, {{0x00060db7497e8a5a,0x00092c6949a8925c,0x000bd589805d8eab,0x000e3f3169e466c7,0x0000dc06264b92d8}, {0x00068f4d55959fe4,0x0000602dba18dff4,0x000cf84bb97b33ee,0x000176aa0c3fe221,0x00008cdc0af44a8d}}, {{0x000730ec599b822b,0x000e71db1fe734f3,0x0008091cd821b583,0x000cffa5b97c09f6,0x0000eb36d9557afb}, {0x000e9729ef451b2e,0x000cc72474ce4e71,0x00075c396c20a694,0x000fa4d30f6220dd,0x00000b129e07fa41}}, {{0x0007a8b81ba9b34a,0x0005d196b5125a9f,0x00076f535e32ba94,0x00063f93a571c824,0x0000fdf2923b8108}, {0x0009a3c16169f605,0x0002eb5c7c3503bc,0x000d93e032a0397f,0x000ef4f1059d5016,0x0000e6e9109888f5}}, {{0x000a9ddaaa05d08c,0x000b651b5a2480ce,0x0005d54b4d0caffa,0x000009d63010c858,0x0000852d0347e35b}, {0x000e50ef3df425c4,0x00023f86f10c9508,0x0001059ff9e45970,0x000ff4e36cccc208,0x00008d3f15023989}}, {{0x000c4489c0d40099,0x0007be24dba9c3d8,0x00062e5f1d371461,0x000c8add92e7309b,0x00007b344d82922c}, {0x000009b0bfe3e8fb,0x0005a3c82268916b,0x0006235555687383,0x000e54f82a980fe6,0x0000027ecab0ce68}}, }, {/* digit=25 [{1,2,3,..,}]*([2^100]*G) */ {{0x0002c86fbd613c3f,0x0006b366f179f698,0x0005c2343f4af69d,0x0001168683eed6b8,0x00005bb244b14bc2}, {0x00074bcc9fc77d46,0x0001cf44b54b397a,0x000997e76e202eb9,0x00037e77886412a6,0x0000996c8fb62c88}}, {{0x000371c902c343de,0x0009ba4fdba0d2e9,0x0007703a1f57b2de,0x00020343f9afa4b6,0x0000afafb42d79fe}, {0x0009dc9f649a4940,0x0009fe378232fec9,0x00084e31e14799ef,0x00087fba3f811471,0x0000abbb815dc0e9}}, {{0x0009ad6e069de1c1,0x000a8ee09300c258,0x0008ae49b3fe8e67,0x000a905b8818602f,0x000086a1482363a6}, {0x0009b399b35b33a4,0x000993d3411d8607,0x0000b2f996c38d78,0x000d08743c446272,0x0000d903dd769e14}}, {{0x0005efcb4e31aa48,0x000098b26adf5408,0x000a7400dc760aec,0x00012814c1f78e76,0x00007b8acedb17fe}, {0x000582ecbd85bb42,0x0006a6adc0412433,0x0000d578158f0142,0x00082f3596dd508f,0x0000e7f3b803a31a}}, {{0x000bd80d6d7878c9,0x000ec4ff7c7505c9,0x000ccd599e1ef20e,0x0004f93fab197ad2,0x0000e480594252ef}, {0x0007fd206ea34109,0x000504fa7dd4d977,0x0003bb5fcb028045,0x0008a8641b6860c4,0x0000f359d5c7cd7b}}, {{0x0002c379ce084523,0x0009d3a870244ff1,0x00049dcb63dd8dd0,0x0006de61ff0d39b8,0x0000f5eab872efad}, {0x0006886251523f97,0x0002cbe2135b4614,0x000d2c5d445ac1d5,0x000e726350799541,0x0000f19f79a23064}}, {{0x000044ae1118539e,0x000d3192a0069335,0x0003a2bd4ed6d43f,0x0003a51a8bf622a4,0x0000fec3fb7cfa9f}, {0x0004bbc6d834bde9,0x000940fbc743dd22,0x000ea1652aaebfcb,0x000816383b2bfcc4,0x0000cd26d91051ae}}, {{0x0002a29161f6475b,0x0009ac8797ea7d83,0x0001b609c435b8d7,0x00000466bc156dd7,0x00003dca799ae0c2}, {0x00047bf02fd92d7b,0x000978b03082945d,0x0009a7c511d1c979,0x00089aca46d98d07,0x000093f286ccafeb}}, }, {/* digit=26 [{1,2,3,..,}]*([2^104]*G) */ {{0x0002d2d4919affec,0x00046009bd158037,0x000a62eb12d4a2ea,0x00012448f1e7f8c1,0x0000e083726187a1}, {0x000261be7ebadd32,0x0006257b93e9c874,0x00039e6ff7ca5c15,0x0005c3e8b381e5fe,0x0000d16b32ff3081}}, {{0x0000b28ad2e996a9,0x000d2df0fc374fd3,0x000c3976364d4eee,0x000e8e8e049e3ddd,0x0000f55e0cec7ea2}, {0x000ba4e4bf019842,0x000dbd55bc4bd3fc,0x000da895f764d5c3,0x000a6998cb92a1cf,0x00007dfe7957c7bc}}, {{0x000d127df32d462e,0x00069353d1362a82,0x0001a23472b2d2a5,0x000b450ec57e5916,0x0000f4ff6eae5ff8}, {0x000400ac40a9d454,0x00004596718f82b0,0x0007a0dba9ecfec5,0x000cc066c183470f,0x0000f1aef698d4ca}}, {{0x000decf23a86e2cd,0x000c0387f711b6df,0x0003509d102ac466,0x000bd1c30a1ac2d6,0x0000391342333aeb}, {0x000789f068ae34fd,0x0002187dcd100c7b,0x000e8a4b4499f2d0,0x00026c68e2a3bca3,0x0000f87ba71e4d2a}}, {{0x00026848490bfdd6,0x000e35430226bf58,0x0007ae001b81059a,0x000449d5557551b1,0x00009a0e4f06a9c0}, {0x000ffb5aa7f70c1b,0x0000de46ce99fb72,0x000a020f9ac4e4ba,0x000477e56ecf595b,0x000074c5d6609374}}, {{0x000b99934479e7b9,0x00044026e7800e3a,0x0001bd4299d5f2dc,0x00079a131374fd4f,0x00002e2e7392be13}, {0x0002f80d13bc1116,0x0000e6f81c920cc3,0x00063913a6fbfc35,0x00075c12ca1b3092,0x0000f7da200406ab}}, {{0x000ea765fe235a8e,0x00004de31523f94b,0x0000ebfbb64be92a,0x0007ec6ed505fa08,0x000003434e32a6db}, {0x0006ebad02efcc64,0x0000d651266ce100,0x00052a6a6f23ba6a,0x0009c596fc0cc05d,0x00008d95322f6ce0}}, {{0x000f12a19301b163,0x0001ec368a201780,0x000adb344233bc23,0x0005a1d9650892cb,0x00008a0d964dd942}, {0x000bcf24a8d4d7e5,0x00020806ce9dd77a,0x00070d4734ccd16b,0x00078082ff40f075,0x000074914152f130}}, }, {/* digit=27 [{1,2,3,..,}]*([2^108]*G) */ {{0x00041205d8f6fabf,0x000a9bed09c79d8d,0x000acbb1e5e42083,0x0009965120e0794a,0x00007e840f9dc1bc}, {0x000d63b9707c3bb7,0x00091e891a716921,0x000bb22783ab4b8b,0x00091cbe46575673,0x000076ce040c53ee}}, {{0x000b010fdc7945f2,0x000023750a4bcbad,0x000c85b9d62c9cff,0x000bf975192383a0,0x0000aba7b5336eb0}, {0x000adaaa4c06f9ad,0x00032f8e482bc3d4,0x00091a79f573a86a,0x000ec2109c6fdce7,0x00009ed02cf837ee}}, {{0x00019d38fc7ea72c,0x00063211ef447211,0x000eda1a2390b4ef,0x000596289f39451f,0x0000ee9cb34205c8}, {0x0009e96971b6897f,0x000409701ea6a110,0x0002c6b2bdf70c17,0x000766a07d0ecda9,0x00008eb97ff99eab}}, {{0x0008c448b63b669b,0x00071972d2d0d6f1,0x000ff59bc53c6eba,0x000ce52a522d8c8c,0x0000c181d161ed25}, {0x000173d5feb0eca8,0x000e2207bd71113f,0x0001715ae34273f8,0x0004ae41b7572efa,0x0000a8ffea2ff16f}}, {{0x0005e681e13eaee1,0x000419dafdb94ed7,0x000941fc4bebd474,0x000bc08b46621f69,0x0000fd3c13fa1129}, {0x00048d0b7b9da22f,0x000bc87a47414714,0x0001c38b9d452cce,0x000bfee2f04778f9,0x0000b443a5ead516}}, {{0x000b4797e8215d87,0x0007023b4b27721a,0x0003d21ef8438468,0x000e1ca93c08fe6a,0x0000bd962489fa6d}, {0x000ecd7ca6de3e08,0x0008c7c9fced3858,0x00008239e466a48c,0x00083323ca9b75c7,0x000060d553e35bbe}}, {{0x000e02a5022112c4,0x00015461b1c6a66c,0x000247c388415df8,0x0004d6c2546e6aad,0x0000b9788e6da9c7}, {0x000b2e0a22be3e86,0x000c895f76ad3d0c,0x00033767015db086,0x000f549758f99ba2,0x00001ae09bbfab57}}, {{0x000917a2f8ebcf55,0x000be53f056ca356,0x00084bb486f2c400,0x0008e309d9ac41dd,0x00000dc7a8ef61e9}, {0x000a9d33d3a67762,0x000736de8b3df179,0x0006e2beadda312e,0x000ca062a8b7c3ce,0x0000b00036c845e4}}, }, {/* digit=28 [{1,2,3,..,}]*([2^112]*G) */ {{0x000cbd7ab6cf0b48,0x0005713d1ddf1ad2,0x0006003ba7a1e67f,0x000fcca58f0c7374,0x0000263e889264a8}, {0x000be37be2452f79,0x0006fae81a75c35c,0x0005537019312576,0x000d787d2ed0ab3a,0x00003d7e7e040717}}, {{0x000013cf9cf03baa,0x00099eee3a77c1bc,0x0007e4c9536223b8,0x0005e486efc9233d,0x0000f3801bf36562}, {0x000a1413f32fd9d0,0x000c4e564acba7bb,0x000edcac170724de,0x00098552587f32b7,0x0000b1cd94cb3969}}, {{0x000407a661fbdabc,0x000718e52150df08,0x000dfe954c4d7c53,0x000dd1a3765bce63,0x00006829bfc6c2dd}, {0x0003f65dc6e44874,0x0002ff04c9305739,0x000838c0a9ba2942,0x0005cd493c691418,0x00001b137ff8b2f3}}, {{0x000aa244e1c5e60d,0x0009e3253d50f9e4,0x000babe5354bb528,0x000a64f4a86ab39b,0x0000561feaf3ac0a}, {0x00096ab1911bad71,0x00087433730317a8,0x0001f69289cb22b9,0x000c9ff14262fb16,0x0000661885c69ba6}}, {{0x000ebd3b82574dbc,0x00034d8af3f58666,0x0009319bfc5e8667,0x0001a8cc64520520,0x0000183c12ef834d}, {0x00073da49eb0f402,0x000c8aca649e333d,0x0009e83613bcab0b,0x000c85a02f4c41e3,0x0000391e7aec89bd}}, {{0x0007c5e608cbe2f2,0x0007116c22f26806,0x000faf9dccdec82f,0x00085c80aa719af1,0x000061fe95143401}, {0x00013669713e72e6,0x000ecd8a2a466b41,0x000106ce0db1e405,0x000e69ed17475711,0x0000d70cf6f571c0}}, {{0x0000322cf707c76a,0x000fe0b4b7d71531,0x000a2d26d3a1eb2f,0x0000c0b83259fbb1,0x000083ffb1019972}, {0x00019280bedb326e,0x0001c92717150ecb,0x0002d71a94473e82,0x00056d506e6d202f,0x00007b253b223197}}, {{0x0009335f576cb3cb,0x00048fb3b78e77e1,0x000da0001e16e457,0x000c5eaf96d78563,0x000038deafea7444}, {0x000b38cc0eb0e287,0x0001efe41b983ca6,0x000965b31a6ca354,0x000bc6feb37b4718,0x000039cc322c97d5}}, }, {/* digit=29 [{1,2,3,..,}]*([2^116]*G) */ {{0x000ac99a211ffd3e,0x00051f1f6bca019f,0x000648244408f942,0x000d671f5b76d1a5,0x0000f3942e975b2b}, {0x000ee7fb538f1d7c,0x0001044b8f845b9d,0x0008ea6a31cb7862,0x00071f9f8ecd63cb,0x0000a111b2f79d3b}}, {{0x0000e21091e1c4cc,0x0005467ccc747cc0,0x000ebbbe4d500db4,0x000ac0a8e2e84bf5,0x0000326688284279}, {0x000b4de7a1706589,0x0001e1da4a2d9e8f,0x000acee19219c5ec,0x000243da69a3fdee,0x0000d4c6fbdc0462}}, {{0x0001d166087c5e5f,0x000fb53a8bc4e962,0x000d314cdae49c2c,0x000f18d7868882ca,0x0000de10dc89a57a}, {0x000a60d3800f3973,0x000b688b333c0fa8,0x000fa8129cec8ae7,0x000c32efd8d69285,0x00003d5685bc0776}}, {{0x000f768680dcbf99,0x0005df0a51df60ac,0x0008df9c55072b82,0x0003323a74751cd8,0x0000d20f989acc1a}, {0x000042b6926c34ad,0x000ed076687f7e90,0x0006e9dcb5c728b1,0x0005aef2e3bfe8f7,0x00009822f0ae5a12}}, {{0x000eafec58b6d022,0x000373443629441a,0x000823652750cd60,0x000d5ea68af789e4,0x000084d1e24e8d6a}, {0x0003ee3c4d56ddf6,0x00000c18e36243f9,0x000a2fe798365005,0x000df90e409c5b85,0x0000127bfe085cfd}}, {{0x000ff1d35689ad9f,0x0003932addf1ec56,0x000fdde42e0f2114,0x000f5f4d52297877,0x0000402832dcd838}, {0x000267d915ac8813,0x00003c9963a5fa13,0x0002a42bdcf224e2,0x000c500d44419ac5,0x0000ed2898d4cc0a}}, {{0x00005799f67b96be,0x000b3f509e955e73,0x00016dc34c6d265e,0x000493e985dceed4,0x0000308208028803}, {0x0004271dc7a39d4f,0x00032b9f5dc3afcb,0x000d33ea6839afda,0x00065a1c08ba2fc7,0x00003ae1c287c591}}, {{0x000db58f51b14b08,0x0006239a79f03f84,0x0005a1f11df73ccf,0x0004000ce1e5842b,0x000041fa6a3985fc}, {0x0009c682455c32a3,0x000eefa71cc364b0,0x000797929383c9bd,0x000a5db63814861e,0x00003036faf923d0}}, }, {/* digit=30 [{1,2,3,..,}]*([2^120]*G) */ {{0x000cf7c90f17cbaf,0x000520c7c5f351b6,0x000cc7f385d655ff,0x00079ec64f29d54c,0x000028e85325124a}, {0x0008d5167bf1e98c,0x00001d7a33af5efa,0x0009a40a48610028,0x000a0b35fe2bb2cb,0x00005cc1bf203d50}}, {{0x0002bbfa32106c2a,0x000ade91774fc0ae,0x000853a30ef155b2,0x00005b5567c3c713,0x00006be82918ddb3}, {0x0008c21ade26eecb,0x000cb03c17ec7db5,0x00093f8a2fa3c895,0x0000c696ab0de162,0x0000d2365ed5c371}}, {{0x0003e73e194c6423,0x0006a89e3c856ab0,0x000dacd55607b710,0x000084952aab024b,0x00001ca3ee251cc6}, {0x0009b2b1c6b93f9e,0x000ccad930f7f314,0x000872630cbc5ef3,0x000fe2ed04984f22,0x0000f5d052e4c4b6}}, {{0x0008d05570286777,0x000c3e9aabdf6202,0x000d4e5d090eebee,0x000873ab977aee06,0x0000a98c52869361}, {0x0001251b7c2474df,0x00074f3e7b01f49b,0x000e54af1cdaf2a3,0x0006b7638bcaf46f,0x0000ec426250dac0}}, {{0x0008cf51eafe37b0,0x000430dd7c2bda73,0x000dd77af503eac2,0x000e7cf9b7b7a511,0x0000ade03afe9dcf}, {0x000d34af479e3b5a,0x0003a30a33f2a89b,0x000b64068993ab40,0x000110aef322bf9f,0x000047cc71bae27f}}, {{0x000f8f8c63b9e759,0x000c9d7d130a519f,0x0008490b743f6b4f,0x00014adba3385d7c,0x00007889df79252c}, {0x000ca86b2f18b9f0,0x000ec3a87422fccf,0x000474838f092ff9,0x000e9ff96dd67567,0x000039e82875bad2}}, {{0x00009112da32c0af,0x0003a2676ca256a6,0x000614dc6b2e1ac3,0x000965fb74093f17,0x000044939e52f27f}, {0x000a402c922422bc,0x000afff5c56e8656,0x0009aa62ed60a55b,0x000cd20d061b41ab,0x00009ceacff6ca3a}}, {{0x0001d47515f954cf,0x000c6f470a3f5f58,0x0006feaaf145f925,0x00043bfee6b6b073,0x000090744b01ea57}, {0x0008ceaa2f36f565,0x000f33ed4006fd8e,0x00015e6db4239a6c,0x0003d10906b5bdd5,0x00003622990dac97}}, }, {/* digit=31 [{1,2,3,..,}]*([2^124]*G) */ {{0x000667432efbbce1,0x0003f9639719548d,0x000662e7d64a6c2b,0x00018438c0465730,0x00005d1d7ca452c9}, {0x000630ccc3020cc4,0x000cf09f038f30e8,0x00076a744e4b56c9,0x000988db9cb5edfe,0x0000c85f020a947b}}, {{0x0004873ec83c9534,0x00037a21ef09f49e,0x000f7d93eb4f59fb,0x000c823872d31440,0x000079e1d0302568}, {0x000dc9a65d43d228,0x00026775efa857e4,0x0006defa6cc068e8,0x000956b78ccae932,0x0000f92b296ada64}}, {{0x000aaa9c8a3e3ac8,0x000f43979374b572,0x000f271ebf9bc4e1,0x0008468117501ecc,0x0000c636f82980b7}, {0x000ef401522bb338,0x000b1a451df84842,0x000adce528726480,0x000bb68955aa02ed,0x0000e83cf34e78d0}}, {{0x000f8d5dea227eee,0x000d1dda8b9fd721,0x0003e3520f48c766,0x0008b60583d94be4,0x0000bda36cac1d89}, {0x000286a6627adaac,0x00015938368d5808,0x00050949f19c4c62,0x0006d9e0dbd707f7,0x0000adf4beaccf35}}, {{0x000cce23329e671b,0x000133ba85f9fa3d,0x000d2f0acbfe89cd,0x000dd5a661b1f182,0x0000ec370f3d49b0}, {0x0004271be20fb25c,0x0003f8f79665eacb,0x0008e416948ffff8,0x000ba1df8d3d2cbf,0x00007a6d9edd03f5}}, {{0x00053eeb5763ed71,0x00076458542565c0,0x000cd718c4a553fb,0x0004bb3b2736a46c,0x0000c4f9cded6489}, {0x00001a0f71211b78,0x0003f2974258adf0,0x000ff25912c5325f,0x00020be8e172f449,0x00002e960cb21a37}}, {{0x000c4a93631bfbda,0x000ad77461c62943,0x000958036ce38afd,0x000c48f0ad59d5c1,0x0000e284bfe02556}, {0x0003006d8b01967d,0x000c55a31d662fba,0x000c592b66b2f4ad,0x000018fe6af925e2,0x000030c029c1eb3e}}, {{0x00021262dc890a77,0x000605aa75a385de,0x000070b3276b7b67,0x00068f475fc1432a,0x0000429a646fe31d}, {0x0009aaa09be3dcab,0x000a5f780ed73c3a,0x000fd96c407e119a,0x0005776212562564,0x0000571495098e80}}, }, {/* digit=32 [{1,2,3,..,}]*([2^128]*G) */ {{0x000561a8a914b50c,0x000f5154d376bb9f,0x0009b4c352bf7130,0x000c566800f69651,0x00009e65041168b4}, {0x0006e006d98a3316,0x00074211ce1dd070,0x000562e5f781a12f,0x0007471fff9e3d40,0x0000356cf46ec166}}, {{0x0008d63003b40dd2,0x00025951b7ae5a74,0x0004a91b08a68240,0x0003ea41e92dd970,0x0000dfb3eb9a58cd}, {0x000af35f5094667d,0x000d4435aa2cf3c2,0x00062714fffa287d,0x000b0ed03f397974,0x0000b550f67f03e5}}, {{0x000549dd3341d809,0x0007c1a2a0a44759,0x000164f75079e9fa,0x00018275da56c72a,0x0000313ef5b4eefc}, {0x00065b6bde130ad1,0x0007a841117ffaa3,0x00026466a4426597,0x000404a65373f7aa,0x0000a43bee63e2cf}}, {{0x000e1b8207eecd99,0x00047c07b47c29da,0x0004292dad3f50d6,0x00075b02b4d90936,0x000019a6df48c359}, {0x000d4aab616452e4,0x000d9cfc6abb741e,0x00089b025e58689c,0x000de5eac325d9f3,0x00005ceb1e6cf255}}, {{0x0005a9858bf21d97,0x00074beab706075d,0x00032d47700eb684,0x0001c29d714c9f82,0x0000cde2c3f270f9}, {0x000a8cee9871f0c4,0x000b59e8444aa6d0,0x0000cd43a902bc60,0x0002228651ed57ff,0x0000418cc081480d}}, {{0x000188534a70bfed,0x0008736345c44b2b,0x000322ae9cfa421f,0x0007a02f33f4cc6f,0x0000ac0bb761dabb}, {0x0005536923cea0a8,0x0005ed9cb50c7ba3,0x000812c96c16f73e,0x00042423216dc625,0x00002945e67bd7ab}}, {{0x000bb350b6da2b61,0x00068b65ee5504ae,0x0000a004d91fef33,0x0001f7db77b57b1a,0x0000c59b62833aef}, {0x0008c893ec88d182,0x000a6fde31f1879c,0x0004e30b652cca38,0x000cbbe2f64a94cf,0x0000b4cdbd757ff1}}, {{0x000b7fc506f7dcd8,0x0006dd037d68f4e7,0x000c8d374985e854,0x000180ff00a4da1e,0x0000c339ae3d05b4}, {0x000d4f23a5f71c42,0x000f87ac3e9f58bc,0x00065dad12fb4d99,0x0004dc7dd25aa6ee,0x0000fd63fc2d62c3}}, }, {/* digit=33 [{1,2,3,..,}]*([2^132]*G) */ {{0x000671fe43332ef5,0x000b941c2217f3e0,0x00022ba1871c5dd5,0x000b674c1d2c1fe9,0x000058e9c302619c}, {0x000cde01ec51255b,0x00015f824507204a,0x0004c6afe824b374,0x0002e362d1b9de74,0x000099616dc5b0d5}}, {{0x000c0847f6a1cda6,0x0004e23d634ffec9,0x000bad00768839c1,0x00054ecbbb678b03,0x0000a727255a7888}, {0x000fea2ef5c72941,0x00085875e775b747,0x00061a8937485277,0x0008b1ad7b8e8baa,0x00008ff333550da9}}, {{0x0006ca48d15f612f,0x000661a8a9100439,0x000e4801edc27609,0x000765b388a29a0d,0x00001786469e2330}, {0x000153bbefdde3b2,0x000c66b8ce1ac63e,0x000313e17ecffc16,0x000fc5ab70c46999,0x000063b28a2fa50f}}, {{0x0009f4f5529ec802,0x000a8fd146d1851e,0x000300c2c0420274,0x000feabbf1ab668e,0x0000d0b3a9d61653}, {0x000180f23a495b9a,0x0004f415d73a8be2,0x0007ae4fc6ef3c37,0x000f5f1d3e1ec8c6,0x00005839e9d38d31}}, {{0x000c8b9c3fb67790,0x000ca57ee680c4c8,0x000673efc54fc9c6,0x00079e99003261b7,0x000067670079b117}, {0x0001da6250891c34,0x000b9d785ab3fb15,0x0006759c64720dec,0x00008e872b351ffa,0x0000c7ad29ae4f10}}, {{0x00014d637d77c019,0x000bd1023c876541,0x0006e1221c2e18a4,0x0008f96fa6c3d39e,0x0000a6cf4e2d10e4}, {0x0001140b181828fb,0x000a28cb78333088,0x000cd236717c6df2,0x000922c1eb8df1a7,0x000078f1c8e7a89f}}, {{0x000bcacbd862cefb,0x000dbf8f23c2598b,0x00045228f58f4234,0x0003688bce359f81,0x0000605d0f84812c}, {0x000dddfe4018fcda,0x000f9f797960b8b4,0x0005d8257b8139dd,0x0009bf631ee83dd5,0x0000c8b3932c4571}}, {{0x0004777d0d428874,0x00086b7a2707b25d,0x0003966fe4b48921,0x000bec1b4dbf9b2d,0x0000bac5f4881ae2}, {0x00027331733964e6,0x000fca814a6908db,0x000898348a10c5df,0x0003f484ebdaf0a9,0x00000e46824074da}}, }, {/* digit=34 [{1,2,3,..,}]*([2^136]*G) */ {{0x0002d18f9066d734,0x0003e098b3bfa064,0x000b4954cbe1d2ec,0x0009bbefee860c21,0x0000d7c4e6d67b62}, {0x0001e038e8b81b09,0x000f0fe77eb03d8f,0x000247c734a80168,0x0003564d977591ce,0x0000b30c9f3157e0}}, {{0x000ead488c06b1c4,0x000089d9d4e8273a,0x0009e86bfea8af42,0x000a56a7b4409acb,0x00009f76f719414a}, {0x000c8018c13857a2,0x0002ee7423844603,0x0006657197c26f1c,0x0000c6042fb2242a,0x0000619f2550175b}}, {{0x000699444bb5a795,0x000cebd1fdbfb12c,0x000e49191f5928e0,0x000dd3d30b8a973c,0x00002792b8633a05}, {0x00089161d3d69c3b,0x00099d59a28c5da0,0x000a05485931759e,0x000964412148d96c,0x00001517aa0ed6e9}}, {{0x000bcc7d9b45206a,0x000e8abc463fed6f,0x0000e37d100ab735,0x000718428c701781,0x00004365872c7af5}, {0x00058230a910146d,0x0007dff76703bf19,0x000d6f1c8c13ccdd,0x0001b459d34ad644,0x00003dfa6b3495b6}}, {{0x0005d0a1685e4603,0x0007455d00b5d0e1,0x0005614566fae8b3,0x000c63277126d8dc,0x000031c02e59bf70}, {0x000da4e515f39b7c,0x0006566c206009b7,0x00001f926b7e0d13,0x00037e9a801457c4,0x0000c560826bfb01}}, {{0x000ffb56487a5d42,0x00054f53e25f6874,0x0006ba8fcc02a12b,0x0005d638654a5741,0x000026356f22c0b2}, {0x000eaa66030f2ac9,0x00022cea9175a4f2,0x000912104b788baa,0x000e3d66fbe9f74e,0x000082ef71dc9a69}}, {{0x00090f62369ce91c,0x000a1754d218b653,0x000018afb2dc3763,0x000b66bc5523697c,0x0000a835077f5bf6}, {0x0003e4361d4b0a62,0x000747cf66c541b8,0x00057cbf28f87f59,0x000fb7ace5784093,0x00004834481cbe47}}, {{0x000c2c96fd8b3094,0x000ae055809f298e,0x00022943c512ea17,0x0003e628cb44e788,0x000034dc70a1eb7d}, {0x00024d11be76434d,0x0004082ff0b0e8b3,0x00005e7267cf24ed,0x000abcda8265fe29,0x000057b3916be6c3}}, }, {/* digit=35 [{1,2,3,..,}]*([2^140]*G) */ {{0x0000095d2a819b58,0x0009c8f2f6537901,0x000afe3665291aaf,0x000e27fa533907f0,0x00008a58ed00e279}, {0x0007127fae130bc9,0x000b88a54c747f07,0x000d82b6aee9ccf1,0x00052438a6783ebe,0x0000a1acb3e7d414}}, {{0x0003ceed9c12e2aa,0x00021fc1308f44e5,0x0002c2d0f11983fc,0x0007233eb4d84d89,0x00000bfc1cb14499}, {0x00044d90145176bf,0x00015f12e75a8083,0x000a67545bb2988e,0x000989df73ceadad,0x000037069d21bb8f}}, {{0x00035e69cc17f65b,0x000b39d9abdff24a,0x000c09ae3c49b3e9,0x00058782f403032f,0x0000ffe7d4db02cc}, {0x000f4e6424ef7136,0x00050658f65ff511,0x0008baea2b86bf65,0x000759623388d91c,0x00000664a7193656}}, {{0x0006198d8447e168,0x0006e62171dc9899,0x00048b8e617195d7,0x00092328cfe6a1f4,0x0000a3c28238658c}, {0x0008d899c35e852f,0x00001b3781561c54,0x0000113b6adf1cd3,0x00096f999e41aff3,0x000087515a68cf46}}, {{0x0002c559778aa8ee,0x000bb1b8d8b18c33,0x000533883290ae3e,0x000ee23e2bfa0bbf,0x000048e3747fa523}, {0x000f1d550fde3eda,0x000be8710432ad40,0x000241f3fb57e695,0x000abca41012581b,0x00000cabf7bd042c}}, {{0x00019c7edfea5220,0x0008a400db7b68eb,0x000f03a0868e028b,0x000e366cd97bf7a8,0x00009f4d266f442f}, {0x0007f915d713a1ff,0x00061f58ccb42ac7,0x000ddc47d356e3a3,0x00011531d657f1f8,0x0000ea7aedf80092}}, {{0x000a1d24ad49f66a,0x000e3d40861a8aeb,0x000a225f516ff2ba,0x000f0b25464f377d,0x00002fe66ccbffc3}, {0x0004d7fac757f415,0x00021d0a2c202407,0x00074b2665c85d3d,0x00004fccda2a05c9,0x0000c2e25121c10a}}, {{0x0002535510d515f7,0x000cb89e785591ea,0x0000d17bcc861c54,0x000c869bc8485b68,0x00001472c11f19cc}, {0x00094850e9b5d8b0,0x0008d029720da7ef,0x000f50161698c9fe,0x000bf66ce987d161,0x000035f6f329d240}}, }, {/* digit=36 [{1,2,3,..,}]*([2^144]*G) */ {{0x00015879c34971bf,0x0008d76545cefe03,0x000a81bb95829eb0,0x000710b7a3a6ae33,0x0000f42db0039c9f}, {0x000ae85bffb951b7,0x00033e70f324194e,0x0008b1f12815fe3e,0x0000bd636564cb42,0x000022e00511029b}}, {{0x000578b41aeb39f1,0x000e8dd55c1fcfc9,0x000814075eeda86f,0x00017cd4b8fc54fb,0x00002e32a7843a13}, {0x000cd2b2fd217d16,0x00013bd076388b79,0x000dc7d8b5f5f20c,0x0000e2fc57643a53,0x0000512601550835}}, {{0x0007479d0058ffac,0x000fd80b0de5705b,0x000a0585fe459ecf,0x000fa0fbe00c088c,0x0000169e23b83dd4}, {0x000009a44026f6ee,0x0003fd96fe5785d9,0x0008ed1e0bbc258c,0x000884d7ed379c32,0x00008b4574503970}}, {{0x00091e139bb481ab,0x000b49984155263e,0x000d8e622dcdc072,0x0000349fce6e38d2,0x0000f6978b73e8c8}, {0x000e8748c37990a9,0x00089e749b861a1a,0x000dc7c12d1f0e06,0x0002115aa303b1cb,0x0000a78bab059130}}, {{0x0000e8c48790aacf,0x0009154ad24e5601,0x0002090b8ac7a52d,0x0007dfbca462bd2d,0x0000cd84ef5a2f8d}, {0x00055b07ec8e0744,0x0003ba9b88dbf017,0x0007e09a00e4205e,0x0009130170f7d14d,0x00007f7d48d0e9d8}}, {{0x0000b8acc130e8b6,0x00003c6f0871db27,0x0000d3f3417f5f79,0x0000319683bd22e5,0x0000d5852afc2699}, {0x00054cd8f15058ac,0x000b74cfe9dcc3d5,0x0009479d624038de,0x00059bb19336ecc8,0x0000aa9ed55b03eb}}, {{0x000c5c0e0b77ebf3,0x0006d45a471d41ab,0x000e535e9dc41d92,0x000a8528f162333c,0x00005db2f52ebbd0}, {0x0005bf4eaec8559f,0x000702b31f5e4c0e,0x000d337b87be9434,0x000280c2b24a8e89,0x0000564495937b34}}, {{0x000a910b3e2087b0,0x000344a61a335eeb,0x000cd5c0fbd016dd,0x000e94ffd1f08148,0x000041c6aa02e6a8}, {0x00035c5c4ac3d913,0x0005934767a4b09c,0x00040c2b55829810,0x00089f6120e7cb10,0x00002a661efd7135}}, }, {/* digit=37 [{1,2,3,..,}]*([2^148]*G) */ {{0x0006a90bd74c70ea,0x000e2af672f2ba05,0x0004e9a4844f7d00,0x000069dc25ab68ef,0x0000dd15cc49dfb1}, {0x000fd289f3033bf4,0x000c2bb8b8a771f4,0x000d2861c088a49b,0x000fb5ea485869a8,0x00006dbfdafab977}}, {{0x000ef4002d0aaff9,0x000dfe679fe21264,0x00088bdcea678c07,0x000db8cff13be7fd,0x0000a8efe8df17ba}, {0x000a815ad5a22f46,0x00015ec398b2b388,0x0004fc2da8f82140,0x0004f385a6a565ff,0x000081f0181e58dd}}, {{0x000b637f8ec1151c,0x000c6adc8544ee61,0x000d0985a415dd36,0x000f50ed21d17669,0x00004d062b057893}, {0x000ba1a337b81f9d,0x000f87c163a17d93,0x00016e4edb995fe9,0x0008e7447eff3b54,0x00007660300dbf4a}}, {{0x0008fbc4e933b192,0x000d054ea9692416,0x000acbb56af2db74,0x000d1d36fade13ae,0x00009708665a4e6c}, {0x000f1e1b692df97b,0x00031ae66306bf7f,0x000685f205a68c1a,0x000eec85bc544ce7,0x00003f42e6dbf65e}}, {{0x000bbad2a08a1dcc,0x000b3f2dba7953f6,0x00064f5a3a7131e4,0x000109751dce4878,0x00005af1b45c8135}, {0x00075f74f08636e0,0x00052e251e483c4d,0x000d988539949b2f,0x000e84d04979779b,0x00009d8e627909b0}}, {{0x000078177ef7f672,0x00074b6340c9166d,0x0007acf63fefec94,0x000dec7ce3a05609,0x00006538c7ccf306}, {0x000b55e287dc8d19,0x000bd48823adfa8b,0x00070fc519431095,0x0009ac8358087a79,0x00005299959d1350}}, {{0x000ef0bfb48bd3a8,0x000f4508309e0814,0x000709c101bbbe13,0x0006557ddaf06167,0x00002b67847e436f}, {0x00001c603712e641,0x00024e3f9b2e1a56,0x000184b5dac1f036,0x000149cc7e6a0909,0x0000258b265c4625}}, {{0x000033a675b47a06,0x0004c542378f9bf7,0x0005ec248cb3669c,0x00034696abb0f712,0x0000d5d2047d95fc}, {0x000c9e88f5cffb67,0x00082ea5ee0936c6,0x0004ffd6fb968f2c,0x000ac82f2ce73584,0x0000931b87797e40}}, }, {/* digit=38 [{1,2,3,..,}]*([2^152]*G) */ {{0x00015ecfe73e6993,0x000c7752648968bb,0x0001dcc6d7533abd,0x0003634b26960749,0x000025ec2a0a7187}, {0x000aa197e9ab8653,0x000af25a9448466f,0x00031b5ba1c105b4,0x0005790b6b896305,0x00002691f115db1a}}, {{0x0005f7341690d1cd,0x0009c0edac8bdbdf,0x00038cfb00e857a7,0x0001d259f40fcf82,0x0000cb54f68211d4}, {0x0006ac80e6451179,0x000f0af5fdcbaf03,0x0007bab2cdc4e833,0x0002bd67d859b23d,0x00002489b23ef8b3}}, {{0x00034b4c22eb7ffd,0x000bad66596a89ef,0x000b3f3e1fc26171,0x000de06ce57d2c0e,0x0000e4177dcd587b}, {0x000f7eb6ebf95ffe,0x0004ff55b87342f0,0x0000cbc46efde869,0x000190b699bdb308,0x000032804f430cd4}}, {{0x000aaf7b9e2f9f82,0x000a2ff419acc412,0x0007bcb900484c1a,0x0008ca9d94498941,0x0000b73dbe41e731}, {0x00071e552dd7b0ad,0x000b0954afeae91b,0x0007e3958d61f8ee,0x000f49aaeab13ca0,0x0000e442032d2a1f}}, {{0x000f06ac55c0828f,0x0001667e2247abc6,0x000c49d4d62a7430,0x000b34e42b4c8984,0x00007a8dd4742091}, {0x000b96540a8295bd,0x000c39e900eb5ffb,0x00042ae0a36db01c,0x0009ebd9b90987de,0x000051f12e4efc53}}, {{0x000fbd4a3b4ab0fb,0x0004907bdb60d581,0x000ae79b355d3bb1,0x00024ee65507f786,0x000085fa584e36d8}, {0x0004492bc0d8c261,0x0003a9b3e8d4611d,0x0004029cfbbdbeb6,0x000bf2f201f709e4,0x00008a99397c6748}}, {{0x00020b3838c4ab94,0x000cb736cae32a95,0x00039f308526b695,0x00017f0f8eab84d2,0x000009b53e4d08c5}, {0x0001bcad169e4b4c,0x000767a467b7d378,0x000cc9436a91f107,0x000ec70e885579f3,0x00000d1f792fe123}}, {{0x000d96d0b054a0fb,0x000924b90779d292,0x000f1d49fa978af8,0x000ab170bd185bff,0x0000e6d0844b279e}, {0x000fe45b8ed07e9d,0x00029b920e54d8ff,0x0001bb143714824a,0x000bb7cd5c628aaf,0x0000151afce4637d}}, }, {/* digit=39 [{1,2,3,..,}]*([2^156]*G) */ {{0x000bd2e5a26a1d4d,0x000ea1c2d78bd433,0x0001025151148bb1,0x0003844aae419e64,0x000003b993a36489}, {0x00058b1d61a99194,0x00068a0ef3d4a21d,0x000e8c0dd17618c3,0x000a752519020d6f,0x00008d837d640b87}}, {{0x0003a693f11fc001,0x00019bc8eade4cfd,0x000b9f7ae1f2b5d0,0x0004635160359ba6,0x0000e2601dd0a696}, {0x000c6d2915f60844,0x0009a79176d53f5a,0x00026abee6e38778,0x000d227fb99f4bae,0x0000798a2fcea409}}, {{0x000342d86b383b5e,0x0000506b01d4e192,0x000cdcb89e85f304,0x000e2a19e1921388,0x000088f19440ce0d}, {0x000f8cfe453aecce,0x00097a67b49f16fc,0x000ece9610dcd10b,0x000b53b93d5b4daf,0x0000232f34ba39d0}}, {{0x000cd7c64ca2efc0,0x000b4e0bcb6c799a,0x00058a26c3397a15,0x000faab9b10ced03,0x0000a30dbbe4b8dd}, {0x0009712e20f6facb,0x0003811451aff70e,0x000eece8f87c7f73,0x000e2df0c967b1d5,0x0000c62882b5b370}}, {{0x000ba8516a010bce,0x000bca4f3e8e09c0,0x00070a1e52fd90fb,0x0000048af1837145,0x0000869e8f85cca9}, {0x000afb72dd830199,0x000e8d99b38652c8,0x000adab87b877995,0x00091a1e3efc16f5,0x00003105fe53a3b1}}, {{0x00065d10a020be77,0x0002666eaf8ac051,0x000d2380e4856041,0x000b115ff898ddff,0x0000da35f08e84b4}, {0x0003e2c38fd05c77,0x0002b7ada3a4e0f5,0x0008995de64b3ee8,0x000605672ae31667,0x000047074614fe96}}, {{0x000ce8b62a0b0ed7,0x00037abbc9be00cb,0x00069c2d692f5dc3,0x0003e1bb92b7d3f3,0x00000dd90c8e9ef8}, {0x00031537937ab45e,0x0005a054af6d00b3,0x0005ebfc43a8d1f7,0x000d0c35cf7380b0,0x0000fb8dac338c2c}}, {{0x000cb400c11e65a4,0x0002a8ff2be53722,0x0009f9352c94a7f5,0x000544420085cc8d,0x0000addb9870a4b2}, {0x000eac006264a479,0x000472b48ccbac6c,0x00094fef2ebc01a0,0x000a8ac430e7abea,0x000073bb6f14d94a}}, }, {/* digit=40 [{1,2,3,..,}]*([2^160]*G) */ {{0x0004c2e24424a48f,0x000f27d4471b21cf,0x0007a488b843c73e,0x00061cb3047fc561,0x00002a9170ad3cf8}, {0x00044211c3a60f77,0x0006966791481444,0x000d9404b74787a3,0x000ef0115fbd0653,0x00000fd3365d244c}}, {{0x0005c9b2b574b7f9,0x00065369b6bde669,0x000108dedcca8040,0x000fce1f4bae99e3,0x0000e715ce37a133}, {0x000205554c2ee1ce,0x0001f680742d80d5,0x000e438b956bab30,0x0007cea409b5f63f,0x00003a8e4d16036f}}, {{0x000fbfea62e08420,0x000360d426c06d25,0x0003a816cf07a613,0x00059db28fe4774c,0x00007987198b8d12}, {0x00021b150044888d,0x000211a2ad57348c,0x000ba884ad0b1f74,0x000a0385be8dae4d,0x000096bc030d9802}}, {{0x000ec0f247fdfdf5,0x00079a23d1dc91d7,0x0000fdc41fb9d90e,0x00048c7012eb2c19,0x0000c2bbff72dced}, {0x000426a68cd7febc,0x00032b4854e0ca93,0x00072bbd8b596396,0x00040a8ac72b8ee7,0x000010d24d366b30}}, {{0x0004b14e735cafe0,0x00044e80373d66ab,0x00095617fb275399,0x000da6bc5bba23f5,0x0000802dcbf70cce}, {0x000ba1cc60401601,0x0004eb5524732bf5,0x000b1a5907e18137,0x0003b1abdeb3cad1,0x00004f0c02531750}}, {{0x000ef1694d5f3478,0x0000ab04af0a0fdf,0x0002ca633f318949,0x00014a30e3da7a6d,0x0000d002aeac8038}, {0x000311f95a0bfe97,0x000ebb4cc50c515e,0x00034df252891ec7,0x0002890936fed888,0x0000e5d7dbfe8e00}}, {{0x000b4ae1863c1b58,0x000c296f5659ba49,0x000c2f3cb84af9fb,0x000bbdb45c071ded,0x0000db1c01e276f7}, {0x0009a9ea84ee50fc,0x000b09145b546f3e,0x000692134508e794,0x000adc6acff4f7e9,0x00007c5a5c9155cd}}, {{0x0002d78fbfcf1b56,0x000c48427d7459a9,0x00066e74e17ce4fa,0x0005e5bae98ffdac,0x0000d548304745bb}, {0x000c6030992abe13,0x000aeefdc5c58f3d,0x000f8efb8318cfbd,0x000ef8bb5fa37d59,0x000047874a07ef5b}}, }, {/* digit=41 [{1,2,3,..,}]*([2^164]*G) */ {{0x000cb614b4558fbf,0x000c0f2545a97f5f,0x000e5e4699602597,0x0006bcfd89ab3fab,0x00001daeea3eb2e1}, {0x000acd73a12940f8,0x000ccd7c73116699,0x0006c8ec624980f6,0x0003dc4a5cf97533,0x0000e180e330c27d}}, {{0x000ece400e25a956,0x0002dac1732def02,0x000149260ef94740,0x000d51ecdb65ac51,0x0000043aa2a09180}, {0x00092bd852deca02,0x000735237c8ce7fc,0x0004b3f38f333829,0x000f17ecfb0e76e8,0x00001f2f5c58b89a}}, {{0x0007134ca9bf60f5,0x00000c7da3a4dc68,0x0005fb57e2473ea9,0x000adbf54ef685b4,0x000094e84458383c}, {0x000d3fb4a7df4bbd,0x0008917c2c9211ed,0x0008fcba8a783d98,0x000e4c0d498637cf,0x0000ebd801e0acd6}}, {{0x000aa5c7fd181e78,0x00004a3ad1eb08ab,0x00094aab5136a0ca,0x0004a5e6e5e6c2f3,0x00004d697d51349e}, {0x000578bf76f4b3be,0x0006f2feeb5ea215,0x000876bc381a1cec,0x0002ca5d336eb73e,0x00008afdcb5e7189}}, {{0x000bc8cc051e9f61,0x000f5be2d9ca608a,0x000ab534875194e9,0x000490031d69c1d6,0x0000785990e88b0e}, {0x000f125f6c41f8ea,0x000aafbf2fe63825,0x00087161e429924e,0x00015353c044befb,0x00003bbdf1ba651d}}, {{0x0002085894f7f160,0x0002b5c353fb791b,0x0008db0d442eb80f,0x000ef2377777f7df,0x000023c096334c42}, {0x000eb5ea34cb6d01,0x000e65cd1242aa05,0x000cd9f24ffb8b01,0x0009fceab6ff7d87,0x000075e94c9bb3c0}}, {{0x00067251454f76ed,0x0005125c87a8a389,0x000efb7d652772de,0x000c11e59e4516c6,0x0000ddb8bf4a76bb}, {0x000ebd9c6fd2066d,0x0005ed7082e94acb,0x00069cea388c3b52,0x0004056a3b3d626d,0x0000bf73dfb5d065}}, {{0x0002f06978f92cc2,0x0003431967527579,0x000cfcac1b11574d,0x000f67c3249711b8,0x0000061c767ef93a}, {0x0009a1b2f63dbe7c,0x000708091edd2ff0,0x000bba5a9527776b,0x000221f0fa985e19,0x000054f89f426ae3}}, }, {/* digit=42 [{1,2,3,..,}]*([2^168]*G) */ {{0x00062846a436476c,0x0003f5dbb9cafc5a,0x00012ffbf6fcc231,0x000d14a77d2d9f50,0x0000c25e9f50ae4b}, {0x000cfc41a5e40c6e,0x0000df085321f17f,0x0003077c47d716a6,0x000e619dcbc50bee,0x0000bfe953dbb4a6}}, {{0x0006f2fd3d777d71,0x0004df1a6b09d7e6,0x000f88dcf3519dc6,0x0001050df07bebdb,0x00007b09654bcd4e}, {0x000acd04e70c7833,0x0007c6b9d5779bd7,0x000e52f8ada66e74,0x000c1b6d0488a1e3,0x0000ec0fd119ff71}}, {{0x0004cb6be4f27824,0x000b81c2c0cd3547,0x00065e29c10ef5e6,0x000608592c6b066a,0x0000d424663112d0}, {0x0000949b1a714fe2,0x000c3199f802d528,0x000a4ff3a52697bc,0x0009cec68ba4f8e6,0x00005a5380f55184}}, {{0x0007f69573ec6f50,0x000e67bd2e8b3320,0x000fe24207ecc4bb,0x000cdda07acd348f,0x0000a957eb8a13f9}, {0x000f95b9ec9c0c55,0x000cba8578ccbbc7,0x00061923cd82147c,0x000f2507a2e7c59e,0x000091eb06682e83}}, {{0x0001588957c94fa4,0x0007764911fb6aa6,0x000907b196a2bc70,0x000cc409771450c4,0x0000cc48773d694c}, {0x000216e50c878ace,0x000d4f3031f0bdb6,0x000d0d41e6e89210,0x000751b711dcbfce,0x000039bfe3eefbf9}}, {{0x0007a45764636b5e,0x0007975d48f238fd,0x000a80177e437ee8,0x0000eae323bb1860,0x0000dc3c8f49c94c}, {0x0001164ec8cb0cf4,0x00096472936d9835,0x000059756ccdd882,0x00084aa8db1b8558,0x0000eda8cf9155c1}}, {{0x000727d2923b8cb6,0x000d46773d5e7fb5,0x0006411656e793e5,0x0000958ecc901ba0,0x0000077ab2736da5}, {0x0009b0c6b127d9d4,0x0001163e2e1ec066,0x00041b6a28140e4e,0x0007b01ad5b03c96,0x00004299f88dbaed}}, {{0x000296d1ea4a0569,0x000d677811b98736,0x0002dd74b6f74702,0x0004ab5c92754843,0x0000cc7327277a19}, {0x0005eded6328dca6,0x000988db755daf03,0x000192a4a5292aa3,0x00095cb5488385a0,0x0000e7d2fa93fc68}}, }, {/* digit=43 [{1,2,3,..,}]*([2^172]*G) */ {{0x0002e2a0133903ba,0x00038495ee31871b,0x000991f285b3686f,0x000b8a89bcc9740c,0x0000dd20cced4f93}, {0x0001768680b65b66,0x00090ad41c3fff5a,0x000fb42690c453ab,0x000929d479630fa7,0x00000039d01b2c4e}}, {{0x0008134bce59c0f4,0x000d159f7f86ae6e,0x0002834573d068b4,0x000bf0afa2753c96,0x000053fe33c5aedc}, {0x00094c8483c0b1ac,0x00041c2ad1edb812,0x000383e0b9e6f513,0x0001422a77b6ce69,0x0000b5a83acba9f0}}, {{0x0003a2c72aa1c89b,0x000eda4d513df328,0x000d5ea181969613,0x0005fe0d4c0347dd,0x0000bad9ce4f3cee}, {0x00050a857313b49f,0x000def09bf30f8c0,0x0000395cb3b91c3c,0x000befe6e5ab6d61,0x0000c36cde1ceb31}}, {{0x0005b26c3d8ed981,0x000aaa66a6e50991,0x000dab6a3f451e57,0x000ebb2984360730,0x0000710267c4d1a1}, {0x000cfd4e11d88c05,0x000761ce026a7e4e,0x0001227de12fc278,0x000dae9801cecd69,0x000017a92f3c6ce6}}, {{0x000cdebb47b16903,0x00003a3866812439,0x00031334f0593b0e,0x000b1e46074e6e4b,0x0000e26a9771cf7c}, {0x000122b7e2ad0ee3,0x000b8e1b1a8ab475,0x0004832eadccc365,0x0004afe9dfaa7c6c,0x000071d9e4ff6790}}, {{0x000c219e2b4f275e,0x000726d34c98a0c0,0x000d9305c8f7b63c,0x000ad6bdc5d00f11,0x0000fd56e73fd1d4}, {0x0003f94904a1f2ca,0x000a28430c3b8940,0x0000badcc559b8f5,0x000d737be89d20c3,0x0000c788b568b970}}, {{0x000b800d37be97f4,0x000ccd54501eddee,0x0001ba27f575aed8,0x0006ea907f9efe29,0x0000430900142b1e}, {0x000e3526fcec9dcf,0x0004f01459aea95f,0x00067f611a37d324,0x00039d4ec59125d7,0x0000df685f85fe02}}, {{0x0000fdf648c48e5b,0x00074f45a432d21b,0x000572855689e6d5,0x000547a5a9dca82e,0x00000f07eb83adfb}, {0x000b166552c8d550,0x0008ce85417148ec,0x000ee9bc0fe3fc26,0x000c80323af5ebee,0x0000666a2a341ae1}}, }, {/* digit=44 [{1,2,3,..,}]*([2^176]*G) */ {{0x00020bc9ff262fb8,0x000e5075868b206d,0x0003fd973cba032f,0x000e027037602694,0x00001c57cbb635c5}, {0x000e700ba871f1bd,0x00053b265f564964,0x000950259f03a8c0,0x000a8bc8ebc9120b,0x00002b0ee317d32c}}, {{0x000f1ffdeec441ea,0x000c701b21568c88,0x00045cf5cab52096,0x000caa37eee2756c,0x0000070d24ea520e}, {0x0005bd1546b9fd3e,0x00050c96db1b81d1,0x0005b29b73276fb7,0x000254c5c1b041b9,0x000018008dc9d7d3}}, {{0x000a71dd360d017e,0x000609b0ed7245f5,0x00025a0184c0779b,0x000dd0c662fedc98,0x0000ee8912641d4a}, {0x000814d92163d14f,0x000017370d3b2543,0x000e1af7a79f2377,0x0001f7f80c6963cb,0x00002d521bddb9e4}}, {{0x0000bf0ae309a0a5,0x0008875b8fbc68eb,0x0004993b7a9f52f5,0x000292b8e4f9481a,0x00000ce578edf73c}, {0x000a4a602e503d65,0x000134c68ea2d437,0x00016f34820cdfc5,0x0000dffec5993b36,0x0000d96b4c610c42}}, {{0x000e136d3399e1e7,0x00016e2f8b74ee5d,0x00077db29e38bab0,0x00021e736126de3a,0x0000b0d186662aa1}, {0x000e45edecf9cde0,0x000e2318be705545,0x00055b0e59608ebc,0x000ca0e6596006fa,0x0000c8c2f41bc4b6}}, {{0x000a7d03b64dcd73,0x000c858c9d559fb0,0x000fbc656f4c2f1f,0x000bea110c2db2a0,0x0000cad85cb1f5b6}, {0x000dd0e4e0b12301,0x0007198a2fcd6099,0x0001e7407c769b93,0x000b479209f5501e,0x0000b47255d2ba7c}}, {{0x0005aa5d562b5f1e,0x000b15dac657dc80,0x000c28e5a7101b9d,0x000d0a5b7f211ddd,0x0000a89f24db3d1c}, {0x0009ef57567c80db,0x000e4a60c5ee0aaa,0x00036cd64e0d1f26,0x000de6c88a044cab,0x00008e03d02cb125}}, {{0x000699827c7e6ebc,0x00032625bc7e8926,0x000c9cb1584ffa37,0x00084eedec924705,0x0000fad0b914075b}, {0x000d316bc0898d3a,0x000cb1f92524f4be,0x0007e59d702481ee,0x00012919896e1b0d,0x000006adb6d92bb3}}, }, {/* digit=45 [{1,2,3,..,}]*([2^180]*G) */ {{0x0006950fe94629d0,0x00059f860b15c35f,0x0004f8f151cbaa93,0x00045829b4bcd3f2,0x0000ae5b06ad29c8}, {0x000c31d1b6c2df19,0x00016804facc1645,0x0002b33e6640b099,0x0008287a4a7f5912,0x00004bb0b2c0479b}}, {{0x000aed34397ee7ca,0x000cd6fbc7fe5460,0x000b03dfef249e4c,0x0009f3c42d9da8aa,0x00003d73ce3e35ab}, {0x000dbc33813a3f3c,0x000b779c32a2c6dd,0x0008a2c3f86d5779,0x0002bf7c3d9aff02,0x0000687e71c71add}}, {{0x000b3d6ce2a7da5c,0x000c86d365094a23,0x0009d79cd7efbfc9,0x000529dddc5f43e4,0x0000642b12101334}, {0x00052b60eb07da3b,0x00084623cceb073d,0x000ccb9c3e0c9a6e,0x00040e65e4f274a8,0x0000c6dacba8214d}}, {{0x000a56209b3fed36,0x000a95799669e612,0x000960971f296c17,0x000a05a124a36f07,0x0000d03b214980c4}, {0x00046e270f1f268a,0x00003341aea42b07,0x0002f59cccc9b480,0x00015d1b3662d56d,0x00006c65b2e74b1a}}, {{0x0006d5faba617ca5,0x000b0788f1e74ce6,0x000bd2024f5bb17d,0x000aae03ea09fdff,0x000053dd7097abd4}, {0x000458bc19c4561c,0x000dcb2676dc42c1,0x00074f7de4ecc53b,0x00051b1614610252,0x0000f5fa738c9ebc}}, {{0x0000f5608a104d47,0x000f2317079a22df,0x00031eaa8fa16cf8,0x000c540425bed530,0x0000f7c45cba44f3}, {0x0004e5f9db182a9f,0x000f49f23a6d6157,0x000b6efa6cae923f,0x0005174b19b78d03,0x0000fa74d30af8c3}}, {{0x0000568ac0e00ce2,0x000821c05e349afb,0x000a524f0ff4bc59,0x000539a94e0be1f6,0x0000995e87848303}, {0x000f99cde02dc40a,0x00037e00fcad06cb,0x00030a510be18069,0x0007327a71994d91,0x000072b5007a9e07}}, {{0x000113acccb0a4b8,0x000ab615f016796c,0x000ad2f5b24c26bb,0x000abb52fe115aee,0x00005623d268d7aa}, {0x0001fd031a2564fc,0x000e8d0d59a39079,0x0008b74663659974,0x0007b02cffdb747a,0x0000f6b36e611478}}, }, {/* digit=46 [{1,2,3,..,}]*([2^184]*G) */ {{0x000aa41b6223f04a,0x000f241c3faaed9d,0x0000b42cf803c9c0,0x00019360eee3f9c5,0x0000f4a7a5b17298}, {0x000c2e1bf809ad69,0x0002867c0ff24379,0x000f8e637903ab4b,0x000363c779d7ed90,0x000068b0cc0bcf3d}}, {{0x000871cb79f82af7,0x00029dab52f5f4ca,0x0008239a731304b0,0x0007361825ab5492,0x000040413b2fe4ad}, {0x000d3fa44071d191,0x00014f0b2da8b5c5,0x0000a198183e438f,0x000ae3fd759448c7,0x00003e0c7ee665eb}}, {{0x000eaba5568f2420,0x000b029afc1f58f4,0x0004d7dfc83b0c37,0x00053293de2d2799,0x0000d9a6edbb1679}, {0x000427995f085b0f,0x00099299355e4b83,0x0004427f846ebac9,0x000d0e0212e48904,0x00009e4ce3592f37}}, {{0x000d314ef7750f08,0x0005a2da84d6834d,0x0000d647b2ceaa70,0x0001574561a254fc,0x00001cf09163be01}, {0x0003d4e34b798ebd,0x00065b1c7543847a,0x000194168bb5dd62,0x00010b94fee01bc8,0x0000b4c2600caeb0}}, {{0x0006baf530c98b7b,0x000c0acf023af1b3,0x000de150304503d7,0x00089f96bc444921,0x0000b8a123082a9c}, {0x00099dfd5d4b133f,0x000cb97d3e5176df,0x000b318d61bb4a13,0x00052edab370f379,0x0000a6c823f8f185}}, {{0x000b22514fb96241,0x0008da4229d70f09,0x000dc8c192eba4ff,0x00053e5b159dd121,0x0000e1f968fc1aa5}, {0x0005976c7674d527,0x000ceb283500fea2,0x0009468c298e73ad,0x000a627cfce0e1d3,0x0000aad0af978438}}, {{0x00009f62eb1db212,0x0005b2c3e3e183cd,0x000a43da5be37048,0x00025eeb51fa296a,0x0000c7fa809f7266}, {0x000786ff0ec0e998,0x000388135cbf10c6,0x00004751bd315af3,0x00081ac1b6017215,0x00008674e2d8e287}}, {{0x0000f771e33b2a39,0x00002f78986f8fee,0x000f05b7ed4bed82,0x00062a6396feea6e,0x0000c5d6a01b640b}, {0x000fec96834bea4e,0x0009c131fec9370c,0x000affb4d68d1672,0x0002564be9c5d600,0x000034a423d79a6f}}, }, {/* digit=47 [{1,2,3,..,}]*([2^188]*G) */ {{0x0002874d8247f131,0x0001f3c11f564dfc,0x000503b97c211a7a,0x000c827512563fa2,0x000024cd9846c007}, {0x000b682491cd2498,0x00042683359ccf6e,0x000302b62af4f70a,0x000f562f1dfe71cc,0x00003c474bc657fb}}, {{0x0007ab7916a8016d,0x0000232bfb9b73af,0x000174971f93d488,0x0004d4a5f9af3ce2,0x00001b9cf1ffd59b}, {0x000941844f4eb91b,0x000d7226edc49a77,0x000d4bb336a131fa,0x0001fe472ab89780,0x000069687a5df6ca}}, {{0x000cc72520cd267f,0x000403d37ceb7c99,0x000c45cd39b83c2d,0x0001efc2b56ed68c,0x000061a49ae9d3ff}, {0x0006205a05677aaa,0x0009311b22bc4589,0x000beaef3c87845d,0x00092199ef1336bf,0x0000542906a3b1a9}}, {{0x0003ca2fabd066a0,0x0008f9c78bfdffa7,0x00055cfef494e03a,0x000784e585a878ff,0x00000770b1fd7053}, {0x000da4a056fe70b0,0x000857bd444fdec4,0x0005df668e37395d,0x000583666250d468,0x0000549569ebe6cc}}, {{0x000aac0ba9b5ca4d,0x000c4512a151524a,0x0000680f2f556fea,0x00041a6cff93f359,0x000033c25c629212}, {0x0007a1300ee2808d,0x0001896afc72b53f,0x000f030ead83e2c6,0x000f23a0abf470ea,0x00006c675098a456}}, {{0x0009830ab11639e9,0x000b34488d52f762,0x000f06eb6869dd3b,0x000c3710fe1c0bba,0x00009034839a687a}, {0x00083777f1ffe7b3,0x000c55bd7c570841,0x00008ba673334a74,0x00012dc57cb7ed70,0x000084c12d0f1e4e}}, {{0x0008690fb57459b5,0x00067b878006d66e,0x0007ea63d14bee76,0x0002bc9b5267dd2c,0x0000e8f2a4c53e01}, {0x000c64aca5e07275,0x00053875bdcccc3f,0x0006194383dd2f10,0x000d012a09337b76,0x00005415071fe1e9}}, {{0x000dca6db4bdb35e,0x000d54d913a7148c,0x000ed94d56bc23ae,0x0009e78f0ccd9d12,0x00004aabd1366db0}, {0x000f31a1e9483261,0x000c27a479a1fcbf,0x0007686f1cf68c47,0x0006693cced8e2ca,0x00005ed1e995eb62}}, }, {/* digit=48 [{1,2,3,..,}]*([2^192]*G) */ {{0x00092a4202bde39d,0x00050d6bab982b39,0x0007125122549f56,0x000e500b56464287,0x000052442b54fde7}, {0x000fd08a3d3e16e7,0x000b383b29bd36ce,0x0006dec8c5b194f0,0x000c1e6db0edd890,0x0000a09095972570}}, {{0x00095d0eb10175e2,0x000aed236aa11106,0x000dfff4079aaa6e,0x000063f78539ff3e,0x0000369c51722cd6}, {0x0003ae55c8631ff6,0x0002816a60bd21e4,0x00061a5f9065e821,0x0006fa225cb473e7,0x000095ef8610b6de}}, {{0x000e6c9f60ee3e5a,0x00004236377f06b9,0x000a4af71b397af8,0x0009fbb7a318ac7d,0x0000e64b613aa9d3}, {0x0006c74902b34119,0x0000ea199e52d6ce,0x0000fb76fea256a7,0x000f9c8dcddd8955,0x0000443b47793e70}}, {{0x000fe2d952980037,0x00011d8412fbc96c,0x000997dd3caa6655,0x000587f41d021583,0x0000066e356b5534}, {0x0005c3e5b6de0d7f,0x0001becd5f251d5b,0x00052ae508ead45d,0x0000bfe2f24e2cd2,0x000071e5d5071515}}, {{0x0004735e1d88c25d,0x00026bd66b66d27a,0x000af9942339905e,0x00083ca9bfa0ed62,0x000094dd9e0fe2cb}, {0x0008fdaab28e268b,0x000c01a97517779d,0x00091f33ef28ab69,0x000d64ce9bd2ea96,0x00009e8b2ff24be3}}, {{0x000c0908b9f8e8c0,0x000024e94ce19274,0x0000f3ec1a375761,0x00026f8f2b1f2c4f,0x00002e53bb23938d}, {0x000da2c701e5ae8c,0x000b6271dcc9d0a3,0x000fb237260c2eac,0x00008ac9c08e3931,0x0000aa3245f78389}}, {{0x000f3382b02578ba,0x000f04b2c6071100,0x0001611794716339,0x0002a092c923ae5b,0x0000da2e4daadf44}, {0x00090c547f854740,0x0009824e31954d4b,0x00078a0d4a378bf7,0x0009e24469339d24,0x0000972e7880c1e6}}, {{0x000585b36a1f3a8d,0x0000613ba5f1a9d0,0x0005acf11a3d8f18,0x000e791eaee5d622,0x00004dfd0a2dd32d}, {0x000324b6b3ceff30,0x000cab4478700cec,0x000c759ac3acc6de,0x000938abbf7e6db9,0x0000d5c1f47a5196}}, }, {/* digit=49 [{1,2,3,..,}]*([2^196]*G) */ {{0x000215745e7ea912,0x000dccadfc40581a,0x0002cd3934da3f86,0x0000fcc81d6c7d16,0x0000c38a2a1cd6e6}, {0x00025d6f753479d6,0x000f1dec6024f75b,0x0002d5547c914e08,0x000969f81cea3449,0x0000bbb8bb25b1b6}}, {{0x000082c1279504c1,0x00023c92ffb70ee8,0x00081c7e2a466abb,0x00033a4118b26a3e,0x0000a76cc510c60e}, {0x0008bc25736d7aeb,0x00096d1ef9928499,0x000bf252520b3955,0x000626d669e2ae5f,0x0000f956ec6b1cc7}}, {{0x0007029b0ccbaa5e,0x0003079b78a5ee81,0x000f45d8957ef5bd,0x000fd3c92837474d,0x000086b91a90ec4b}, {0x0004c6dfe5659152,0x00069c58a042c5ab,0x00001c4bce657471,0x00013ae141deda63,0x0000f95d561a0845}}, {{0x0004508eecede3d7,0x0005a86440d06c42,0x000de0d7711889b3,0x0004477b229f9398,0x00003fced8aa00a7}, {0x0001c79e31c8f881,0x000dcb277e4fe75e,0x00087c02c8db20bd,0x000c1a8ded0a702b,0x000066281b55d164}}, {{0x00056cfeedd8e0c9,0x0000744c012af873,0x000aa3eb68afab38,0x000a570795935fe4,0x0000b9efc0d6a6df}, {0x000f8aaa8ab0840e,0x0004a85616042ff0,0x000db93150f3a4b6,0x0009f82ca911efd5,0x0000f70e5bba8ded}}, {{0x0009209a6aae58bb,0x0008d74edda2943d,0x000be3c9a3d0798e,0x0002dc5c2d462cc2,0x00005488239f3988}, {0x000bb41977d4de44,0x00005e8245c42391,0x000093dc27fd9104,0x000e121a6d3c713b,0x000023a4e3abb22f}}, {{0x0006f403a9a04a3f,0x0006197d9afef315,0x000a898509b32c4e,0x0000827e0b401e62,0x0000fbf542f984ef}, {0x000c0e0f990caf53,0x00041c88ea9b077c,0x000f96a510270434,0x000c47846fd46c63,0x00007f5cec019855}}, {{0x0000bd8e6ad29dc4,0x0000aa04da287d14,0x000e05b337dca4b1,0x000acfa84feafcad,0x00004d031f8b630a}, {0x0002fa6cdee269c2,0x000ba697a40af8af,0x000e5f8261e40571,0x000fe6f71d44adf0,0x0000a47ddf9c434c}}, }, {/* digit=50 [{1,2,3,..,}]*([2^200]*G) */ {{0x00092d346410cb1f,0x0002f3a5a1354b38,0x000de068d72097f2,0x000890db3a1b8098,0x0000b7438e53b1a3}, {0x000d5ea3839d3d99,0x000e84bd8125fa10,0x000800261d9ad034,0x000c5207d108efd4,0x000078d98bb2c5d6}}, {{0x0002d017375f2deb,0x00093aa152399f94,0x0007e5c4c968a760,0x00040e55dc7da637,0x000075fff53d82b5}, {0x0005c15fd4b69512,0x0007104ddfaedee3,0x0007c87146d1d64f,0x0006fd320f1769af,0x0000b5f86a4682ba}}, {{0x0001f3bdd857b31a,0x000b69513734201e,0x0009327b892c2263,0x000164562652d558,0x00008edd06636a1c}, {0x0008f9879f8df8df,0x000230847ddd3cbf,0x0007c06223d5cf77,0x000f2a69b08ee459,0x0000ff18c4e7a868}}, {{0x000d7a99107901be,0x000f8211d1153c6f,0x0001b78a85dc4a41,0x000b6a597e94e7af,0x000072da34e33afc}, {0x0004db774512c248,0x000a32811e913c36,0x0000469b1c26a8fb,0x000535fdd39d7f29,0x00004515392a0612}}, {{0x000606a4a98f93dc,0x000eb3475d7197ef,0x000e3f8cf41b9190,0x000a4f7ec792db91,0x0000a37ec10e2396}, {0x000c219d0879e176,0x00044ac57d3f90b9,0x000037ea761303af,0x0001ec13293c3be1,0x00001557e050058f}}, {{0x0007cd15c5d384fe,0x0000d74de832cb99,0x000fb7ce336884af,0x000ef76be21274d8,0x00000bb298f86608}, {0x0001a0cd53bd4269,0x0000feb3293b527c,0x0006fc1ac78035a2,0x000fed0d7689eb2a,0x0000a38274adf2c4}}, {{0x0001c4eccf60d0bb,0x0004bcab95d81e7f,0x00025a060c7918e1,0x000f357af4761e14,0x0000fa0bf6fa8e80}, {0x000629801e11b3e0,0x0008d92d8a4f88e7,0x0004a9e6f4b7ca48,0x000b1f247db98bcf,0x00008745cd1c9705}}, {{0x00096a01539cf31c,0x000acded7c6dbfe9,0x00016f6144a3f729,0x00016386f1f29930,0x00003d44e1946cb9}, {0x0004531558fa36c2,0x0005569c89d67698,0x000ee923f58e8bf0,0x000fbc287da114f9,0x0000032e9850c271}}, }, {/* digit=51 [{1,2,3,..,}]*([2^204]*G) */ {{0x000579dd39207ad8,0x00058b1fe91611b8,0x0009e01bf6f62c72,0x0008430f1599acd8,0x0000d9bb86dcd1e5}, {0x00090d4726e38d1e,0x000b32a8c6b8548b,0x000d2f6f4b824a1c,0x00012e984d9309b1,0x0000fa485b8231ec}}, {{0x000560776ac19252,0x000b5442fc587972,0x000311e74086449d,0x0005618dbab9202e,0x00009dee69b9ea25}, {0x000b6ee19a7cd6c0,0x000c0d0dd5a05a62,0x0006d0ff1ba38cc4,0x000dae779279e516,0x0000eef53ccf48b3}}, {{0x00078408c7c6d897,0x0008b2c2555f255b,0x0009c3165bfa78bc,0x0001bc8c56ae3da6,0x00002b20e73533bb}, {0x00070b4d1aa6416e,0x000c5db03cdc8868,0x000a0fd40f000040,0x000f1fd25b16a9b0,0x0000b89e93316815}}, {{0x000393579f34a8a7,0x000fa0046434c9b4,0x00005fdb161acf55,0x0007fff0a23fe63f,0x0000d6baee17c4fa}, {0x00062b6e2daf735f,0x00091948637a353f,0x0004e6206e370ead,0x000ad3da57c16ad8,0x000019ffe09fdd22}}, {{0x000ed1e4263a5660,0x00041d5e8f55fe64,0x00094342c735bbee,0x0009359ac6191582,0x0000f522e5ad4904}, {0x00083b57c1e11f47,0x000060c237f3bee8,0x0009550860a2ce31,0x0002dbf4a7157b8d,0x0000ec0462e722dc}}, {{0x000a5c739620daa9,0x000fff7c078f1e65,0x000177db88ef6f93,0x000535b06d52bcb0,0x000015cdd08f8fdf}, {0x000d150c51832222,0x000d9817a2ade070,0x000194f0b2b6495c,0x000dfb3ce476140b,0x0000eec6acf713bf}}, {{0x000814fd7daf836b,0x0007bd6169217cd2,0x000066012877b72b,0x00059dea73ca1bdb,0x0000e336c7c60d41}, {0x000b07f0f8fcd765,0x000ada5935626993,0x00091ec195fdceab,0x0003c0716595fbf6,0x00001a77f61de68e}}, {{0x00045a51d63aa7f7,0x000623b32da2680f,0x0007088588d5eba7,0x000c610ef233dfa4,0x00004c3f4f7c2161}, {0x000fe6be6420de40,0x000197dd86d5fa9b,0x000ce233b96c0c50,0x000d6328e6827bcf,0x000035cc9a958e74}}, }, {/* digit=52 [{1,2,3,..,}]*([2^208]*G) */ {{0x000997917a86e187,0x00022e029110b2de,0x000cc5a17e2ac232,0x0003cfbfd3439735,0x0000a93461fc25e1}, {0x000542c5122d6f14,0x000ec33982c79433,0x000c24d2741d2d9d,0x000d58e9f1f29a8e,0x0000ae251f433b99}}, {{0x000a46047920742a,0x0000545f94cba02d,0x000608dd4b142d6f,0x0004b5c2d613e876,0x00002c06cddfd75d}, {0x0001bc53c564ff4a,0x000c4d1d5ecd0195,0x0002135ade60f126,0x000695a634e76570,0x00005a56a6f2df44}}, {{0x000482697e839b67,0x000b3f49adaf9986,0x000795531cfdae67,0x000aa4f713da0fb3,0x0000b2f6f6d8d391}, {0x000b8c351b5e7aa9,0x000244f29191734a,0x000692f40fc4a912,0x0008ba8f8e2cdc12,0x0000b0bee740f405}}, {{0x0008c7a9e2207b45,0x000147ee9f61d34b,0x0008e21b61f724f3,0x0006aefa908ca2c5,0x00005587744f7429}, {0x000913002911ae14,0x0003dd3af02e3dbe,0x0003955a1c207543,0x000d66505b724b0f,0x000080e1a930aece}}, {{0x000246ba01d1d691,0x00061c28f15519cf,0x000dcd8cb66c23cf,0x0000f0441e71089f,0x0000c22323a9398c}, {0x000ea418a3f400f7,0x00008b3a0959e3ad,0x0003b53b4787d2e1,0x000436e7464f0fbf,0x0000e7cda2bec46e}}, {{0x000f0871be603736,0x00064f9180e995fe,0x00060416e4dd25ba,0x0005530d3996f9ef,0x00002be886c4b749}, {0x000c5fbb48089d39,0x000e6a2b6d24c533,0x000c20f7f06c8690,0x000dbfdf149e4e00,0x00000f3d7e0794a9}}, {{0x00015dcfc8176c4d,0x000d68bad0d95505,0x000ec582805f29f5,0x00027312d25fc5ef,0x00002f5fa1bfdd52}, {0x00071e3717366b82,0x0002d2d99b2a09d8,0x0005ed437bda0f49,0x0001592abda54f23,0x0000449feb33935c}}, {{0x0006128446d9f664,0x00050354b5a1720f,0x000558aacd6e06b1,0x0008fda72d287d63,0x0000819be29ee68a}, {0x000c324205fbdf26,0x0007810927f95024,0x000658f802fca94e,0x00004674798be7be,0x000018e07f24f07c}}, }, {/* digit=53 [{1,2,3,..,}]*([2^212]*G) */ {{0x000a94654b01bbca,0x000da55d4820b47b,0x000575f207c56c36,0x000cf48e93362005,0x0000ec65be9da621}, {0x00096df462879372,0x0003933c67e7620b,0x000cf3e0535cea88,0x00077330366a3a58,0x0000580d5654da39}}, {{0x00061815832cd6cf,0x0008885e90b9553b,0x00014f686c002e33,0x000d454b33afde64,0x00009ab29ea7511f}, {0x00009726fb9a688c,0x000d3202a1b2467f,0x000a881ab7db6e14,0x0006600c15b6e973,0x00008c324e1bad10}}, {{0x000d412c9489dcb4,0x0005512d084ba43e,0x0004c7cd2cec053a,0x0007f70fd4fe4266,0x00008ee06f4c2a91}, {0x000197083cd65f5f,0x00094569c42ed5de,0x0008761103a17657,0x000bc4f24508f34f,0x0000350374bfa415}}, {{0x000108255ade88b5,0x00019b212e84bc89,0x0001362fa0525b50,0x000cac9ede010bb6,0x00002f3d088d81ee}, {0x0007b6ebc6f0ae45,0x00036659701cf995,0x000b76f4525fe726,0x000d4241e9b7f507,0x0000f2ad6650da77}}, {{0x000518c9bb777fc6,0x0001e24151875571,0x00020284bf369c39,0x0001cc2d7c5dd927,0x0000feab634aeec4}, {0x000d5db24ecd0bef,0x0007f03387353522,0x0001452791fca0d9,0x0009257441610520,0x00004492e1ef496e}}, {{0x000dac0d193a5260,0x0009e2b2d54f3c44,0x000c67d11d071709,0x000ad865624fb4c4,0x00004aa7033bcced}, {0x0002fac31470c527,0x000aa3b05d539c52,0x000565e5708eb33c,0x000370940e0693b4,0x0000e2fd553ebe56}}, {{0x000f5d0be4d36ec2,0x000348e952fe8568,0x000ad6b241e9e539,0x000de9768113f9ea,0x0000bc798fcc8fbe}, {0x0007f9baaa9010de,0x000b561834c94c78,0x0002c25d832cbc77,0x0006dd449e55f703,0x0000824a5c0aa621}}, {{0x000065a848bdc535,0x0004578554dcb366,0x000ff3b4dba2af07,0x000cbb3c755fba19,0x0000ea9337285a22}, {0x000fe021eb3e23bb,0x000b265dede35e55,0x000f445da2626ecc,0x000578187bf09481,0x0000a0110184df30}}, }, {/* digit=54 [{1,2,3,..,}]*([2^216]*G) */ {{0x000ee9a1baea5745,0x000853ae5167cae4,0x0006911240d922f2,0x0007c407df28fdca,0x0000aad2f31ddd45}, {0x000f443137384cac,0x000b2620ea8c20d4,0x00067797ad93d424,0x0005bc21d544d350,0x00008a8cc9a5d8a1}}, {{0x0000e26941d80a3b,0x000a5d36514db10f,0x000f226013092787,0x0000f6aa2dfd4898,0x0000c5b31b838c8b}, {0x0001f376c841cc81,0x00096a412b84a128,0x0008f210ddae1671,0x0009019ec1f6c882,0x0000935d576f8d92}}, {{0x0009be8f731e66e3,0x000ff7c9ac6742c8,0x0007788475c65a3b,0x0005a7621746f622,0x0000e38982159449}, {0x0004aab948c94967,0x0008741e79476b0c,0x0005283abdfdec51,0x000bc091420e3a60,0x000099ec46fa4c7d}}, {{0x0007921af3840f27,0x00034f3fcdfbd724,0x0003961bd348325d,0x000c29ef578508c4,0x0000d5e8ccd8bd98}, {0x000ba10f8a30164d,0x00004cb8c65289cd,0x000056ef40757409,0x000d1bcd7ed73fc3,0x000028e7cc2cb99c}}, {{0x000c0f95182958d0,0x00075749c24bf1b7,0x000638c77ee0c407,0x000cee32f35fcff3,0x0000a46c52952773}, {0x000d4f7e2fb9042e,0x000a32ce916d9ae3,0x000bf7ae89855249,0x0002b7e48a640b04,0x00003eb60417c9cb}}, {{0x00074946bb62286f,0x0007d7d87466b8a6,0x00073b6d58d6ef81,0x00001b3529f938f6,0x00005c0ee777bbf1}, {0x000ed6149fdc9493,0x000eff405ee00768,0x00018e51a53b6999,0x000bd7bf0108a017,0x00008e609ec8181e}}, {{0x00079083a6a2a006,0x0007ee549a6dc288,0x0005facfa82df7fb,0x000de38f1d62b44e,0x00005566a01600ca}, {0x000bcf5b76201357,0x000ddb75df8e1672,0x0002fd615cf00849,0x000a8a8f5d3e0fe1,0x0000fb3f7894f727}}, {{0x0001640d85951597,0x0006c79a38761205,0x00098a67c30e1c70,0x000d27091154c602,0x00006d9a9c9c1132}, {0x000e8b75c661a4d6,0x00068a6dcbaf841d,0x00014e045f24b5e9,0x000c701ed4cb0cd7,0x000005926a46c187}}, }, {/* digit=55 [{1,2,3,..,}]*([2^220]*G) */ {{0x000e0f2aa1ff4af5,0x0007890503a3c558,0x0004f76f161f4348,0x00032e661647323c,0x00000d0706eee134}, {0x00087caf5eba0fb7,0x000ff0bda2c4ef1a,0x000ae646228a95c0,0x000ba610d693e012,0x00009871341645e6}}, {{0x000b01264b496679,0x0007ae05f7601dc4,0x00085d27aa4bdafa,0x000747171b28b3f1,0x000087e5163c3425}, {0x000ac4ec3864a656,0x00091f449c121c42,0x0009658322dae1bb,0x0009f4680d974306,0x0000ac1ef01de31d}}, {{0x00068563958e0555,0x0000adf44aeea780,0x000c18b8dac35ee4,0x0006cd2b47891397,0x0000396824f4a258}, {0x0007b251b23f8c4a,0x000f6decdef982b3,0x000fc39c0f9ced36,0x00032b28c3bee5c2,0x00001731faf0d9db}}, {{0x0004f74ea3d44467,0x0008b0ad1c7f045d,0x000374e92a439f17,0x000008c95d951051,0x00005870ea000229}, {0x00098c2c54e7e812,0x0009b4b3860b1fec,0x000bfc8f6ef537ee,0x000403139dd83440,0x00000b513642f114}}, {{0x0006ab6dd13b3c94,0x00072371f872f32f,0x0005712ab70e052f,0x0001000574074212,0x0000239152df3512}, {0x0005eaa80b229154,0x000cf896f6fa5835,0x0002b4c8fd0e263e,0x0005bb9378a8a644,0x00000c2b54736579}}, {{0x000fe8c284745301,0x0003eb7fec008f80,0x000cb05ca5649a17,0x000c41deed5bf4d9,0x00004b1a3a9e7077}, {0x000d239096883ec3,0x000e74ae671d1c2e,0x000b7362ad550edf,0x0004f2b233e5dcf7,0x00002c158207fd46}}, {{0x0006a81c61ae9676,0x000cd2a2e1e5c52e,0x000211ef8af11042,0x0005fcb353902a1a,0x000044d16e1299a2}, {0x000d6065b67e48ad,0x000421a0b664937f,0x000e072b8fa57096,0x000727aa661c737e,0x0000e1eb4ffc2e0a}}, {{0x000bc2afda6a4a95,0x000a5106ae0dbdd9,0x00069a4bbdba0178,0x0007153820c9f549,0x0000031e9fde9fbc}, {0x000030ac193d9428,0x0007c54cbb38e42a,0x0008fa77cdc3d6ab,0x000a95507c17b91c,0x0000465bcc963642}}, }, {/* digit=56 [{1,2,3,..,}]*([2^224]*G) */ {{0x000265bc25dfad35,0x0009993f44b6974e,0x000d6d473d03630b,0x000992b3270892bf,0x0000b2d95436c5ee}, {0x0004537a36f7c5f4,0x000dcab0b81daeb9,0x0008b45e59befc01,0x00048b483cdb0818,0x00004c753b741e46}}, {{0x000bc87b24116186,0x0003507924c48e43,0x000c9255708754bd,0x0007f4ef2050334a,0x0000e7e4fe74e038}, {0x000e2e276961d0e3,0x000767eac10f21f3,0x000757a882b69d41,0x000d3536d0f45f73,0x00008b967e55b0c7}}, {{0x0008fc4b31fa7794,0x00054f13036e54ba,0x000d754b78024dc8,0x0009aefda2af6382,0x0000a784242ee9ea}, {0x00014abf9887947d,0x00059d555a0997dd,0x0003a46aa7f2ecfc,0x0004b5b37c4244f6,0x0000032cfc2cf71b}}, {{0x00084c16b8a6a975,0x000e5b2bca35baef,0x000174d43d2e7f3d,0x000c5b721c6c095b,0x0000719cf32252cc}, {0x00061f03adf95177,0x000a1be20ff4fc73,0x000eacc0e1e26416,0x0005d201f9d99769,0x000021eba6432e63}}, {{0x000e9c825df8bb5c,0x000f75752d7d8225,0x0003b281d931f721,0x0008be3c4ed4750a,0x0000f9276830a466}, {0x000358e75b7e90c9,0x000e47a29b998b7f,0x00067f2c806e5c24,0x0002d30058967aa1,0x0000f1a6fba34ee6}}, {{0x0009c4f278291f13,0x000524e64c1d9a89,0x00062916e69a9032,0x0007cc46cc5d428d,0x0000c802e661c100}, {0x000f2aa6219cfbbf,0x000dc10258b1eadc,0x000e142af942870d,0x0007a377264e68a5,0x000025675e2f89cc}}, {{0x0008a3b7336aa166,0x000e1c5c622bb77e,0x00089e0295a92cc2,0x00057333a35a2c17,0x0000f91306eae4d5}, {0x000a581da0a46f52,0x000d62640bbac5a2,0x0007b3ae4fb532be,0x000a7188ff0f114a,0x0000223e7b6d8ff7}}, {{0x00031335d21d261c,0x000b8abb1fbcb593,0x0001b3b61a336289,0x000511797db2f363,0x00002cedb2697e6a}, {0x0006f34103553328,0x000add0ae37f3880,0x00017c5c7e5f1fb4,0x000ec357cf26a55d,0x00002e8df47e8c43}}, }, {/* digit=57 [{1,2,3,..,}]*([2^228]*G) */ {{0x0001128ffb5e7ce8,0x00032ecb96c1e0d4,0x0005ca788dbd8b54,0x00038c029ab3dd0b,0x0000b1148a2990eb}, {0x0008db869fb19245,0x0001018391a80904,0x000d311b9cd2149f,0x0009b96bece5b6fe,0x0000edbe9b9effd2}}, {{0x00093e7532e8d6a4,0x0005302a1ee4ab55,0x0000496c09409290,0x0007c8379b32e820,0x00006fb6e9e760a2}, {0x00077ba620051584,0x00014de3f1914a33,0x0004d21271a3266c,0x0002f3e60fad96c9,0x00001553dd1a4630}}, {{0x00031a2a6ec0fe46,0x0002959645720704,0x000da5c3949da0b4,0x000e51bb12d1b09d,0x00004170fe1d2d3d}, {0x0002b16a4a2f5d9b,0x00059590be923a8b,0x000b9b0b5de1bad6,0x00067eb7f93581f0,0x0000007f4de9115d}}, {{0x000d36fe12a94abc,0x000a75ad7c477b0c,0x000768469f364b3b,0x000cc596a7a2a78e,0x0000cc31c7edbbc7}, {0x000d5d0080dbb92c,0x000316fb0f1f270a,0x000d99f57fb201e9,0x000da5dfce7a1e29,0x000012a02b0c6457}}, {{0x0005482a048530b6,0x00040467f15d9468,0x0001b7d84b4a3120,0x00095db5f8a2605b,0x00001ceef97bf452}, {0x000832a07e7578a7,0x0003d915eb7cc48b,0x000cc58340724963,0x00028995bbad2d0f,0x0000fdeed650da95}}, {{0x000b56d84457fa16,0x00061e11055dfd9f,0x000d8d3cf1cddb6c,0x000b08d4173a6b13,0x0000e1b2d83761d2}, {0x000efe79a7aed4b6,0x0009fc67b13ce887,0x000a8d47351b67cc,0x000cf5ffd958d4f0,0x00002c566abb452e}}, {{0x0002367962f3f098,0x000b1784e6f456a0,0x000fc496b5d1b73a,0x000d88b82f0e3c6e,0x00005b2fe37d1f96}, {0x000de1a58c6ee495,0x0003ae7abc0c0aeb,0x000075de7d3903b0,0x00051633f3381ecc,0x00009c9d48206fa7}}, {{0x0002ba62a80f39c6,0x0001c8cbe0887ea7,0x000bd1cc1cb2174b,0x000ce69c73ec69d6,0x0000a2dbe21520dc}, {0x000150beeaae9da5,0x000dedf630d9d0a5,0x000634cd8c935e85,0x000f022147144fa1,0x0000eccb56c94f3a}}, }, {/* digit=58 [{1,2,3,..,}]*([2^232]*G) */ {{0x00079cfc0e2b70a5,0x000d3e8cbae7a77a,0x000db18fc2569c8b,0x0000ff392a5dbefa,0x00009bc96b48ce6a}, {0x00004f48b5510059,0x0006344b2bd7987f,0x000c447d77efe3aa,0x000dd00e9cb8ed6a,0x0000b4eb10b0783b}}, {{0x0002acc711923485,0x000f8f17ef5fecc3,0x000e25b0e545401b,0x000ab9e209a493cd,0x0000c11886bb63ab}, {0x00081b128ec7c90b,0x000725b57f5c361a,0x000d9169618b125a,0x0007ff86d1b45afa,0x000031a786e54c3f}}, {{0x000189659471f1f2,0x000d1630357339d2,0x000bf5a4b2e613de,0x000be5a799579478,0x00000adf6b5df19f}, {0x000c95f1574d34dd,0x0009d9323cea6a48,0x0002df9cf95488f0,0x000500450aee7f55,0x0000f016f7b23557}}, {{0x0004c6f8d9fceb6f,0x00099b528f3748cf,0x000303b2b11e85f7,0x000605e2896d2552,0x0000929675bdd68c}, {0x000237410c708a9a,0x0007e0d7e5a75bd2,0x00041047f4682ca1,0x0008404242b5c590,0x0000f571053af9c6}}, {{0x00066978e93edd55,0x000207ea4f453969,0x000d33d8735cdb8e,0x0002d636f8305dfe,0x00007623440b2564}, {0x000b580945dd7d69,0x0006031739bc4fd9,0x0007bf127965ffcb,0x0001c734588e1f63,0x000036c0ba0e39d2}}, {{0x0006a599a93a5c94,0x000ce8d12f613d87,0x000b2aa43026be75,0x000dade49900ede9,0x00004d6dc80f3a68}, {0x000116b7d23e11bc,0x000376814209396b,0x000c659561279121,0x000fae3e2807cf6c,0x0000c606ca8b405f}}, {{0x000017dc145a6c70,0x0002968798dab36c,0x0000eff5dcca6438,0x000681d13b63768d,0x00006e39e2d2206e}, {0x000ffa43add517af,0x000900d95fee2d9d,0x000c7c7a8e670e6c,0x0003050ecb51abf1,0x000017dff5264945}}, {{0x00068f9e5137d20c,0x000acf7e70ac618e,0x000b86b0a79588cb,0x0001feb6d37f5258,0x0000b281c993cc59}, {0x0003fed8fe40e06c,0x0006ad9ca79270e0,0x000d3a3da394ded9,0x000130f1d22cddbc,0x0000b88cb27cc591}}, }, {/* digit=59 [{1,2,3,..,}]*([2^236]*G) */ {{0x000eb34649966a56,0x000f86639e18c8c7,0x000ce0f3897587f4,0x00080a0724cc000b,0x00003578addaae62}, {0x000aa57c7fd6a1af,0x00046b017e3501be,0x000df2ed183b1a53,0x00085201c027e3ef,0x0000373d4ebc2d31}}, {{0x000546827502203e,0x000538ade3161e8d,0x000687415985039d,0x000774efd373f10a,0x0000fccb79223526}, {0x000d46e0f4497d9a,0x0001b601ab9a4ef8,0x0007b2ad14152df7,0x0001804250cd2fe4,0x00002b63fa69b048}}, {{0x0004ab81e6799c95,0x00006d148443a72e,0x000a73a1b4c0452b,0x0003dc4f3d6068b1,0x00003d967d92a918}, {0x0006305308773b32,0x000dd107d1c4a6ba,0x0002936f7c5535c5,0x000e7282492b6d5d,0x0000207d5e4da0f0}}, {{0x000cb6f787d1f1c8,0x0004bd219a6658a6,0x0003146b0427bac9,0x00078151d7d49f38,0x0000164b77ff863d}, {0x000b0842f9631b8b,0x0009349388de6646,0x0008cd383ef5b3aa,0x0003a060536422e5,0x0000079d912a43ea}}, {{0x000234ea69b16e89,0x000bc1d5e5a6f2c1,0x000b57835cef457b,0x000ddf906b1d3021,0x00008fccf893f260}, {0x000af0d389fa01e6,0x0009e0e60cc9a47b,0x000e5dd23920c8f4,0x0001cdf9674c7ce3,0x00003ba7e5f5ab84}}, {{0x0003293983884693,0x0006f55208130d55,0x000c8b1b292a9779,0x0008e2c2bb329ebf,0x0000c6f15324e83e}, {0x000d963e4290a26e,0x00017cf40c04de61,0x000e829f7d35af4d,0x000a8efac154d763,0x00001d9debc16dc9}}, {{0x00063e677bca7881,0x000e37d394580513,0x00024e144be8d0ae,0x00028e4dbde8185b,0x000023188f4e65e5}, {0x0008b9cefe44eb7f,0x00022e76be281a4f,0x00062f74431f9f1a,0x00073701910bc8e4,0x00002e6f9dbd037a}}, {{0x000c041cb73887ee,0x0009a3ce3a32704a,0x000393e75f878b61,0x00008c57ef73d556,0x00004372d2fb276c}, {0x000c8940924cf58a,0x000c4aa317e25d9b,0x000608da5fa2a4de,0x000960e51edccc79,0x0000dcc68fb2cd4b}}, }, {/* digit=60 [{1,2,3,..,}]*([2^240]*G) */ {{0x0004f09a9e0eeaed,0x000f7b05a6569f15,0x00045b85d2246e6f,0x0004324d7c1c8110,0x0000e99ea38a3bb7}, {0x000818763184ff43,0x00020134bfc2d58f,0x0001203202a22342,0x000e9c1560dbed23,0x00007243c95a6a3d}}, {{0x0006c8fe256b02b0,0x0003fa5946e09f11,0x00035452a7149569,0x00062eeb9696ffc3,0x00001ca592949711}, {0x0001f50c0f28e720,0x000c70d8df1aee0a,0x0009110f82baac62,0x00016acf65d297f4,0x000041dbb019a45e}}, {{0x0009223d39e1ee45,0x000c9e3e6c2bd0b1,0x000a45c34c8832a2,0x00091b64a8f43da3,0x00002a05eef71fb2}, {0x000e24ae4b68e385,0x000b3e2d8a3fc0d3,0x0005b7da85289120,0x0004e133836b9842,0x0000bd418f4000c6}}, {{0x0002241cedc2c975,0x000b7b632640e1a0,0x000fb588ff0f5489,0x0008e7b09091ddcb,0x0000ffd0f38ad947}, {0x00041a1dae35eda9,0x0006f2f0b26b83f1,0x0009dde18d25563a,0x000b3680014b171b,0x0000fcf8f820da49}}, {{0x000380540096f25a,0x000e8c8201311e99,0x000993f9c900d4bd,0x0000072170cfd32a,0x00000e3d894cdfe1}, {0x0000b5a0e7df1098,0x000ac7fde3dce00d,0x00089816ac904985,0x000b9e15597a84cb,0x0000ac8b02839dfe}}, {{0x000a4fdf7a2df835,0x000bb4524d444e3e,0x0006aee218b68b26,0x000e1c74caeeab12,0x000090a00a5e15d9}, {0x000a6ab49b90eff5,0x000e7df4fe510ae2,0x000fcb6ed74b4cb1,0x000b300306ed1107,0x000064ebe2ea02f5}}, {{0x000a0c3c0a9d128d,0x00047ed0d3bce0f7,0x000e778e62adc34d,0x0006ba4ebf577813,0x00003b89bd18b847}, {0x000b52837413953c,0x000d98ba3471209e,0x000a79c09952b705,0x000b2acaa81ade86,0x000008eed3e3e0e7}}, {{0x000c2bc9a8f42ff5,0x00009a1c0299dea0,0x0004dd41b6297424,0x0002495ee5f5f69e,0x0000b1bba807e110}, {0x000eadb78da80167,0x00008809f79eeac4,0x000f8c0dec297878,0x000ba939d2dbcee3,0x0000fb4b5fc764d3}}, }, {/* digit=61 [{1,2,3,..,}]*([2^244]*G) */ {{0x000179c7f034ff4c,0x0009f781eac1a607,0x000022138efb8fcd,0x000039fa57f8a97b,0x00005bb9f1e16ab6}, {0x0007e24e4d2ab7f7,0x0001e7a9e3648902,0x0007f487d3d67ad7,0x000bd0c579e70c1f,0x0000fefc8949a7e6}}, {{0x0001662a45cfd31b,0x0003c6f65cfd7cb9,0x000f3de5109dd56d,0x0004fc983e005d14,0x00009dc05b0d10f6}, {0x0000afd885eafe56,0x0003d444bdebc279,0x00087300abd5213d,0x000b76289dca9289,0x00009fb2ac313960}}, {{0x0008bb43e4e99c48,0x0006f1f5ac02913a,0x00083f958b0c5fed,0x000eb65c5ccabdd7,0x0000d10225585a25}, {0x00075bc2701b5ef5,0x000f34ead28ab53b,0x000d37ba17cdfbb9,0x0007b8a111be6984,0x0000324f41a75991}}, {{0x00048869ae7540fb,0x00021131e9213327,0x000a360c8d738663,0x0001e02e3d4fd8f2,0x000020a59b6ed9d4}, {0x0007eae99082a34c,0x000e1181946fb2b6,0x000d1d007fad6aa7,0x000ed07c299b9aa2,0x00001f841e14100b}}, {{0x0008bf21619db767,0x000be5dbcdc6ba04,0x00053cfdca928899,0x00089daaf1e8f8a0,0x0000e49dcc581266}, {0x000001ccbf14e0ef,0x0002592029f13992,0x0002972a8aefbe02,0x000c66a3c0cc8691,0x00008495b3926f9a}}, {{0x0007d4c43e90ebdf,0x00080fc72b063c1f,0x00094f40258b7810,0x0004b0da8503e1af,0x0000bb724b849f24}, {0x0002186fcd8755a4,0x000ec68482b6efcd,0x0009be3d57407cde,0x00002c4d62f57834,0x0000a0125451cc62}}, {{0x00018c779f099ea8,0x0009290f6a520a5a,0x00025d678dfefc64,0x000de97c3b4cc277,0x0000d87ef5ce132b}, {0x000ee07a7023e899,0x000f309c8784c042,0x000c1268d9681a7d,0x0002c2fa00007a86,0x0000f76f114b2bf8}}, {{0x00014d2151ffc085,0x0000c40d6b5568a4,0x000f472abaa79acf,0x000f1deeab0104cd,0x0000014a8c1f3aa5}, {0x000340533f134256,0x0009b7eb54d42c74,0x0008a723b2b776b4,0x00063a3a0cc4ac54,0x00005aae6f4279fe}}, }, {/* digit=62 [{1,2,3,..,}]*([2^248]*G) */ {{0x0007ef9dfa782a41,0x000184cd95006944,0x00038f7626dadc8e,0x000a140574020edc,0x00007596d7ef2ee7}, {0x0005af79e1f8adc5,0x0006f4791da04ef7,0x0007b5d805ac5f21,0x0006cc1583226b7b,0x00009f3f053f21c2}}, {{0x000abd049c879a59,0x0008347ac42e5e16,0x0009c2326844874a,0x00033bee3f8a203c,0x00009a120556eaed}, {0x000a15b63b333ae3,0x0005cd923fa01814,0x000b1b1efee9f28a,0x0009285b0cd25033,0x0000ccc39b9b346d}}, {{0x0005e1d161e13e79,0x0001207e7068bb79,0x000522fe70f9abc2,0x00034efb3be61854,0x0000e2d0f37a9381}, {0x0007c36d292c6b0e,0x000da1e77894d8dc,0x0006c55f3bafbf59,0x0000877d0132cd1b,0x0000fa02edad609f}}, {{0x0009359d93f6e1a6,0x00049d41c11898ea,0x000b641af729005d,0x000e784c2934107c,0x0000b2b4671e95e8}, {0x00051d05958fad35,0x000ec8619fe3da12,0x00011d318b69bc2b,0x000704d74df34cd9,0x0000def837865102}}, {{0x00058678c673c89c,0x0006c99c7bae39ff,0x000b1e1b64925a04,0x00084f0b3bf59adb,0x00007e9d9f2f0ae0}, {0x00023960fa1776f5,0x000fb24c897b2098,0x0003534d5b2e1b98,0x000f63a9a6407d6c,0x0000e22319bf4dc3}}, {{0x0006a2e916ef5271,0x0000393dc0853d90,0x00091da3eadeb94d,0x0002eb03a0780114,0x000077dceae1b84d}, {0x000a3c17b691e0c9,0x00086172cea2d1e5,0x000a76bce47d40bd,0x00035f7d0646ad8c,0x00000b030aa564d6}}, {{0x00037b31f6e396ce,0x000f29a782f2d083,0x000c9b9746166b21,0x000d3d1ac6198b8e,0x0000e2e3446ebb44}, {0x000374035039dd98,0x0005a9f5c6925b28,0x000ddb4667c708f9,0x0003cf8914cce098,0x0000bb1b9f25446f}}, {{0x00075c2a2c539e41,0x000db756daf9d315,0x000f55a120bac5dc,0x000299e917cecf91,0x0000e96433bf96f6}, {0x000c71c3700d8fb3,0x00060c9b4444bec7,0x00074f19c9a1d296,0x000d6b3d2c6970cf,0x0000b444c48dc5e0}}, }, {/* digit=63 [{1,2,3,..,}]*([2^252]*G) */ {{0x000cefd8ccb854c3,0x000b95b0c45ab563,0x00037f743f5452cd,0x0004abb3c787699c,0x00004e9d192c5d44}, {0x000794652ff26b7c,0x000b5b94d6416934,0x000affb8f70d6ecf,0x000c717d201858fd,0x0000288719e05dcd}}, {{0x000469d0728a2eb7,0x000f3433d11c5695,0x00006c08e7b46244,0x0000834a8b99baf1,0x0000989794fd3422}, {0x0008867d4fc5696b,0x0008ec79cdb7d221,0x0006d50496b021f2,0x0006285ff7bbeab2,0x000078611cb57261}}, {{0x000f961531313d77,0x000bd6dcdc9dea75,0x00060e99185a1f4d,0x0007ccae3026b964,0x0000d467bef87ecf}, {0x000bf6705118708a,0x000993b2f1c8ea0d,0x000c0e4e054bfa36,0x00011ba9fc9d5cf2,0x00008c2ad11fe936}}, {{0x000faf0aa1256bd2,0x0005be4631de1ef1,0x0009c26760f22454,0x000b2469cb9800de,0x00006019816b5782}, {0x000172ca66c0ccdc,0x000674407199d45c,0x0009f681a6c25f63,0x000df4917d5dbaa4,0x00000cad04872dc5}}, {{0x000cf4c5960ef1c9,0x000e1c6979d5445b,0x0009090d6babcb16,0x0007288e3be750ae,0x0000481d2623c0eb}, {0x00036cd0d6a7d46e,0x0003ff97650066b4,0x000e1064f6eb1a6a,0x000c205984ffa2db,0x00006575fb2d809d}}, {{0x0006d804d974a81a,0x000037a74be65042,0x00048653161304f1,0x00081a2346ff98a9,0x00001242ccb953d7}, {0x00003df97355f15a,0x00045d6058cea82f,0x000aefe28c607ed3,0x0007e403bc8cd468,0x00006e7de5b25130}}, {{0x000df0fc6af7d445,0x0000015a9187dc07,0x000e15c2f310b252,0x000313d42661ced3,0x0000198fd906b4d8}, {0x00062cdda8368a13,0x00018e9c25424a60,0x000e37cee1a905d1,0x0004ca1d752b70da,0x0000ed8c1a546bf8}}, {{0x000fb0feecc2f22b,0x0004198d8e5fa190,0x000f3ce723df210f,0x000fc6cce57d3af5,0x00002fb6223e12b8}, {0x000700571867c84a,0x000d5e139ebdd994,0x000e7944e141cd92,0x000058415efc9e5d,0x0000e9ee919e5821}}, }, {/* digit=64 [{1,2,3,..,}]*([2^256]*G) */ {{0x0001a6a32f9eaf5b,0x00055cfc13dbbf7b,0x000b18adf2c440f9,0x00033f2cf39bc566,0x00009939fe94f015}, {0x0004553383a64506,0x000450102086a31c,0x0001f136016d96ad,0x000c08cbd6fa9550,0x000067d3ea0c5f96}}, {{0x000c13ba12fdf41d,0x000c5224f5d1fa1f,0x000d5872bd798c04,0x000da822f4594e1d,0x0000ee12df5ebddf}, {0x0003ff0ed83420ad,0x00085daa27f3c647,0x000cefd8af41cf1c,0x00047f2772cd56ae,0x00005ddaf191902b}}, {{0x0005abf53e86ae11,0x00004850830d88e0,0x0006bc33cc1dc4d9,0x00086fbd7fd806e0,0x0000ac330d6bcf12}, {0x0002303e1588c1e5,0x000b6b7e9c18d8ce,0x0007149f2dc25e54,0x000a2511e51e494b,0x000051b839205c7f}}, {{0x0005ddf1510a406a,0x000569f0e98c83fc,0x0002843a0475a78f,0x0005a6b6d681c4e7,0x000090af2a4ea00c}, {0x0006d45a34f44127,0x000357f5d70325fc,0x00011092560f9c0e,0x0004d52bc0642bad,0x00009abfc112e24a}}, {{0x000ee0691cf6cf09,0x0001b6b6bb14f844,0x000f77954e05b5ed,0x000619049c4bbcb7,0x0000d0f82198d94a}, {0x000e53617b8a0fde,0x000a78a163c77369,0x0004efcc52f1c014,0x000f9ea95975cd72,0x0000be1ab00c9aa9}}, {{0x0000621245e20bef,0x0009134bbfc574fd,0x0007b3b6835a502d,0x0005cd40b56e370b,0x0000ca24ac75641f}, {0x00049d7102ae1815,0x00001fe146bde29a,0x0005146a8d2205d3,0x0009632a432de4b8,0x0000f90d9d766c61}}, {{0x0004e18f143aa0fa,0x000641cf03d329bd,0x000345f4cf3894c5,0x00089dd25d055813,0x0000da5c0a11d580}, {0x000b9b65ddf3b293,0x0005e8afdfa60988,0x0006ebe1439c3438,0x000d381e3c991790,0x0000c9efd259ca95}}, {{0x0009ce39b3d6844b,0x00093320f9bee042,0x0007dc2d2af562e9,0x0005ea5fbc2c5d71,0x00006fa79ff0722f}, {0x00070a079eea8d96,0x00019377e5ee65aa,0x000ad14cb624a2b9,0x000ac930ec06eaf7,0x00008d07bdd35640}}, }, }; #endif /* #if (_MBX>=_MBX_K1) */ #endif /* IFMA_ECPRECOMP4_PSM2_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm3/000077500000000000000000000000001470420105600271705ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm3/sm3_common.h000066400000000000000000000220271470420105600314160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_SM3_COMMON_H) #define _SM3_COMMON_H #include #include #include #include #if (_MBX>=_MBX_K1) #define SM3_MSG_LEN_REPR (sizeof(int64u)) /* size of processed message length representation (bytes) */ #ifndef MIN #define MIN(a, b) ( ((a) < (b)) ? a : b ) #endif /* // accessors to context's fields */ #define MSG_LEN(ctx) ((ctx)->msg_len) #define HASH_VALUE(ctx) ((ctx)->msg_hash) #define HASH_BUFFIDX(ctx) ((ctx)->msg_buff_idx) #define HASH_BUFF(ctx) ((ctx)->msg_buffer) /* // constants */ static const int32u sm3_iv[] = { 0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600, 0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E }; __ALIGN64 static const int8u swapBytes[] = { 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8 }; __ALIGN64 static const int32u tj_calculated[] = { 0x79CC4519,0xF3988A32,0xE7311465,0xCE6228CB,0x9CC45197,0x3988A32F,0x7311465E,0xE6228CBC, 0xCC451979,0x988A32F3,0x311465E7,0x6228CBCE,0xC451979C,0x88A32F39,0x11465E73,0x228CBCE6, 0x9D8A7A87,0x3B14F50F,0x7629EA1E,0xEC53D43C,0xD8A7A879,0xB14F50F3,0x629EA1E7,0xC53D43CE, 0x8A7A879D,0x14F50F3B,0x29EA1E76,0x53D43CEC,0xA7A879D8,0x4F50F3B1,0x9EA1E762,0x3D43CEC5, 0x7A879D8A,0xF50F3B14,0xEA1E7629,0xD43CEC53,0xA879D8A7,0x50F3B14F,0xA1E7629E,0x43CEC53D, 0x879D8A7A,0x0F3B14F5,0x1E7629EA,0x3CEC53D4,0x79D8A7A8,0xF3B14F50,0xE7629EA1,0xCEC53D43 }; /* // internal functions */ __MBX_INLINE void pad_block(int8u padding_byte, void* dst_p, int num_bytes) { int8u* d = (int8u*)dst_p; int k; for(k = 0; k < num_bytes; k++ ) d[k] = padding_byte; } __MBX_INLINE void TRANSPOSE_8X8_I32(__m256i *v0, __m256i *v1, __m256i *v2, __m256i *v3, __m256i *v4, __m256i *v5, __m256i *v6, __m256i *v7) { __m256i w0, w1, w2, w3, w4, w5, w6, w7; __m256i x0, x1, x2, x3, x4, x5, x6, x7; __m256i t1, t2; x0 = _mm256_permute4x64_epi64(*v0, 0b11011000); x1 = _mm256_permute4x64_epi64(*v1, 0b11011000); w0 = _mm256_unpacklo_epi32(x0, x1); w1 = _mm256_unpackhi_epi32(x0, x1); x2 = _mm256_permute4x64_epi64(*v2, 0b11011000); x3 = _mm256_permute4x64_epi64(*v3, 0b11011000); w2 = _mm256_unpacklo_epi32(x2, x3); w3 = _mm256_unpackhi_epi32(x2, x3); x4 = _mm256_permute4x64_epi64(*v4, 0b11011000); x5 = _mm256_permute4x64_epi64(*v5, 0b11011000); w4 = _mm256_unpacklo_epi32(x4, x5); w5 = _mm256_unpackhi_epi32(x4, x5); x6 = _mm256_permute4x64_epi64(*v6, 0b11011000); x7 = _mm256_permute4x64_epi64(*v7, 0b11011000); w6 = _mm256_unpacklo_epi32(x6, x7); w7 = _mm256_unpackhi_epi32(x6, x7); t1 = _mm256_permute4x64_epi64(w0, 0b11011000); t2 = _mm256_permute4x64_epi64(w2, 0b11011000); x0 = _mm256_unpacklo_epi64(t1, t2); x1 = _mm256_unpackhi_epi64(t1, t2); t1 = _mm256_permute4x64_epi64(w1, 0b11011000); t2 = _mm256_permute4x64_epi64(w3, 0b11011000); x2 = _mm256_unpacklo_epi64(t1, t2); x3 = _mm256_unpackhi_epi64(t1, t2); t1 = _mm256_permute4x64_epi64(w4, 0b11011000); t2 = _mm256_permute4x64_epi64(w6, 0b11011000); x4 = _mm256_unpacklo_epi64(t1, t2); x5 = _mm256_unpackhi_epi64(t1, t2); t1 = _mm256_permute4x64_epi64(w5, 0b11011000); t2 = _mm256_permute4x64_epi64(w7, 0b11011000); x6 = _mm256_unpacklo_epi64(t1, t2); x7 = _mm256_unpackhi_epi64(t1, t2); *v0 = _mm256_permute2x128_si256(x0, x4, 0b100000); *v1 = _mm256_permute2x128_si256(x0, x4, 0b110001); *v2 = _mm256_permute2x128_si256(x1, x5, 0b100000); *v3 = _mm256_permute2x128_si256(x1, x5, 0b110001); *v4 = _mm256_permute2x128_si256(x2, x6, 0b100000); *v5 = _mm256_permute2x128_si256(x2, x6, 0b110001); *v6 = _mm256_permute2x128_si256(x3, x7, 0b100000); *v7 = _mm256_permute2x128_si256(x3, x7, 0b110001); } __MBX_INLINE void MASK_TRANSPOSE_8X8_I32(int32u* out[8], const int32u* const inp[8], __mmask16 mb_mask) { __m256i v0 = _mm256_loadu_si256((__m256i*)inp[0]); __m256i v1 = _mm256_loadu_si256((__m256i*)inp[1]); __m256i v2 = _mm256_loadu_si256((__m256i*)inp[2]); __m256i v3 = _mm256_loadu_si256((__m256i*)inp[3]); __m256i v4 = _mm256_loadu_si256((__m256i*)inp[4]); __m256i v5 = _mm256_loadu_si256((__m256i*)inp[5]); __m256i v6 = _mm256_loadu_si256((__m256i*)inp[6]); __m256i v7 = _mm256_loadu_si256((__m256i*)inp[7]); TRANSPOSE_8X8_I32(&v0, &v1, &v2, &v3, &v4, &v5, &v6, &v7); /* mask store hashes to the first 8 buffers */ _mm256_mask_storeu_epi32((void*)out[0], (__mmask8)(((mb_mask >> 0) & 1)) * 0xFF, v0); _mm256_mask_storeu_epi32((void*)out[1], (__mmask8)(((mb_mask >> 1) & 1)) * 0xFF, v1); _mm256_mask_storeu_epi32((void*)out[2], (__mmask8)(((mb_mask >> 2) & 1)) * 0xFF, v2); _mm256_mask_storeu_epi32((void*)out[3], (__mmask8)(((mb_mask >> 3) & 1)) * 0xFF, v3); _mm256_mask_storeu_epi32((void*)out[4], (__mmask8)(((mb_mask >> 4) & 1)) * 0xFF, v4); _mm256_mask_storeu_epi32((void*)out[5], (__mmask8)(((mb_mask >> 5) & 1)) * 0xFF, v5); _mm256_mask_storeu_epi32((void*)out[6], (__mmask8)(((mb_mask >> 6) & 1)) * 0xFF, v6); _mm256_mask_storeu_epi32((void*)out[7], (__mmask8)(((mb_mask >> 7) & 1)) * 0xFF, v7); } __MBX_INLINE void TRANSPOSE_8X16_I32(int32u* out[16], const int32u* const inp[8], __mmask16 mb_mask) { __m256i v0 = _mm256_loadu_si256((__m256i*)inp[0]); __m256i v1 = _mm256_loadu_si256((__m256i*)inp[1]); __m256i v2 = _mm256_loadu_si256((__m256i*)inp[2]); __m256i v3 = _mm256_loadu_si256((__m256i*)inp[3]); __m256i v4 = _mm256_loadu_si256((__m256i*)inp[4]); __m256i v5 = _mm256_loadu_si256((__m256i*)inp[5]); __m256i v6 = _mm256_loadu_si256((__m256i*)inp[6]); __m256i v7 = _mm256_loadu_si256((__m256i*)inp[7]); TRANSPOSE_8X8_I32(&v0, &v1, &v2, &v3, &v4, &v5, &v6, &v7); /* mask store hashes to the first 8 buffers */ _mm256_mask_storeu_epi32((void*)out[0], (__mmask8)(((mb_mask >> 0) & 1)) * 0xFF, v0); _mm256_mask_storeu_epi32((void*)out[1], (__mmask8)(((mb_mask >> 1) & 1)) * 0xFF, v1); _mm256_mask_storeu_epi32((void*)out[2], (__mmask8)(((mb_mask >> 2) & 1)) * 0xFF, v2); _mm256_mask_storeu_epi32((void*)out[3], (__mmask8)(((mb_mask >> 3) & 1)) * 0xFF, v3); _mm256_mask_storeu_epi32((void*)out[4], (__mmask8)(((mb_mask >> 4) & 1)) * 0xFF, v4); _mm256_mask_storeu_epi32((void*)out[5], (__mmask8)(((mb_mask >> 5) & 1)) * 0xFF, v5); _mm256_mask_storeu_epi32((void*)out[6], (__mmask8)(((mb_mask >> 6) & 1)) * 0xFF, v6); _mm256_mask_storeu_epi32((void*)out[7], (__mmask8)(((mb_mask >> 7) & 1)) * 0xFF, v7); v0 = _mm256_loadu_si256((__m256i*)inp[0] + 1); v1 = _mm256_loadu_si256((__m256i*)inp[1] + 1); v2 = _mm256_loadu_si256((__m256i*)inp[2] + 1); v3 = _mm256_loadu_si256((__m256i*)inp[3] + 1); v4 = _mm256_loadu_si256((__m256i*)inp[4] + 1); v5 = _mm256_loadu_si256((__m256i*)inp[5] + 1); v6 = _mm256_loadu_si256((__m256i*)inp[6] + 1); v7 = _mm256_loadu_si256((__m256i*)inp[7] + 1); TRANSPOSE_8X8_I32(&v0, &v1, &v2, &v3, &v4, &v5, &v6, &v7); /* mask store hashes to the last 8 buffers */ _mm256_mask_storeu_epi32((void*)out[8], (__mmask8)(((mb_mask >> 8) & 1)) * 0xFF, v0); _mm256_mask_storeu_epi32((void*)out[9], (__mmask8)(((mb_mask >> 9) & 1)) * 0xFF, v1); _mm256_mask_storeu_epi32((void*)out[10], (__mmask8)(((mb_mask >> 10) & 1)) * 0xFF, v2); _mm256_mask_storeu_epi32((void*)out[11], (__mmask8)(((mb_mask >> 11) & 1)) * 0xFF, v3); _mm256_mask_storeu_epi32((void*)out[12], (__mmask8)(((mb_mask >> 12) & 1)) * 0xFF, v4); _mm256_mask_storeu_epi32((void*)out[13], (__mmask8)(((mb_mask >> 13) & 1)) * 0xFF, v5); _mm256_mask_storeu_epi32((void*)out[14], (__mmask8)(((mb_mask >> 14) & 1)) * 0xFF, v6); _mm256_mask_storeu_epi32((void*)out[15], (__mmask8)(((mb_mask >> 15) & 1)) * 0xFF, v7); } #endif /* #if (_MBX>=_MBX_K1) */ #endif /* _SM3_COMMON_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm3/sm3_mb16.h000066400000000000000000000040171470420105600306720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ #if !defined(_SM3_MB16_H) #define _SM3_MB16_H #include #include #include #include #if (_MBX>=_MBX_K1) /* // change endian */ static __ALIGN64 const int8u swapBytesCtx[] = { 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 }; #define SIMD_ENDIANNESS32(x) _mm512_shuffle_epi8((x), _mm512_loadu_si512(swapBytesCtx)); /* // internal functions */ #define sm3_avx512_mb16 OWNAPI(sm3_avx512_mb16) void sm3_avx512_mb16(int32u hash_pa[][16], const int8u* const msg_pa[16], int len[16]); mbx_status16 internal_avx512_sm3_mask_init_mb16(SM3_CTX_mb16* p_state, unsigned short mb_mask); mbx_status16 internal_avx512_sm3_final_mb16(int8u* hash_pa[16], SM3_CTX_mb16* p_state); mbx_status16 internal_avx512_sm3_msg_digest_mb16(const int8u* const msg_pa[16], int len[16], int8u* hash_pa[16]); mbx_status16 internal_avx512_sm3_update_mb16(const int8u* const msg_pa[16], int len[16], SM3_CTX_mb16* p_state); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* _SM3_MB16_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm3/sm3_mb8.h000066400000000000000000000051061470420105600306130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_SM3_MB8_H) #define _SM3_MB8_H #include #include #include #if (_MBX>=_MBX_K1) /* // change endian */ static __ALIGN64 const int8u swapBytesCtx[] = { 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 }; #define SIMD_ENDIANNESS32(x) _mm256_shuffle_epi8((x), _mm256_loadu_si256((__m256i*)swapBytesCtx)); #define SM3_NUM_BUFFERS8 (8) /* max number of buffers in sm3 multi-buffer 8 */ typedef int32u sm3_hash_mb8[SM3_SIZE_IN_WORDS][SM3_NUM_BUFFERS8]; /* sm3 hash value in multi-buffer 8 format */ struct _sm3_context_mb8 { int msg_buff_idx[SM3_NUM_BUFFERS8]; /* buffer entry */ int64u msg_len[SM3_NUM_BUFFERS8]; /* message length */ int8u msg_buffer[SM3_NUM_BUFFERS8][SM3_MSG_BLOCK_SIZE]; /* buffer */ __ALIGN64 sm3_hash_mb8 msg_hash; /* intermediate hash */ }; typedef struct _sm3_context_mb8 SM3_CTX_mb8; /* // internal functions */ EXTERN_C mbx_status sm3_init_mb8(SM3_CTX_mb8* p_state); EXTERN_C mbx_status sm3_update_mb8(const int8u* const msg_pa[8], int len[8], SM3_CTX_mb8* p_state); EXTERN_C mbx_status sm3_final_mb8(int8u* hash_pa[8], SM3_CTX_mb8* p_state); EXTERN_C mbx_status sm3_msg_digest_mb8(const int8u* const msg_pa[8], int len[8], int8u* hash_pa[8]); EXTERN_C void sm3_avx512_mb8(int32u hash_pa[][8], const int8u* const msg_pa[8], int len[8]); EXTERN_C void sm3_mask_init_mb8(SM3_CTX_mb8 * p_state, __mmask8 mb_mask); #endif /* #if (_MBX>=_MBX_K1) */ #endif /* _SM3_MB8_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm4/000077500000000000000000000000001470420105600271715ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm4/sm4_ccm_mb.h000066400000000000000000000133031470420105600313450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #ifndef SM4_CCM_MB_H #define SM4_CCM_MB_H ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* // Internal functions */ #if (_MBX>=_MBX_K1) /* * Set IV for 16 buffers in SM4-CCM context * * @param[in] pa_iv Array of IVs * @param[in] iv_len Array of IV lengths * @param[in] mb_mask Bitmask selecting which lines to update * @param[in/out] p_context SM4-CCM context * */ EXTERN_C void sm4_ccm_update_iv_mb16(const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); /* * Set message lengths for 16 buffers in SM4-CCM context * * @param[in] msg_len Array of total message lengths * @param[in] mb_mask Bitmask selecting which lines to update * @param[in/out] p_context SM4-CCM context * */ EXTERN_C void sm4_ccm_set_msg_len_mb16(const int64u msg_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); /* * Set authentication tag lengths for 16 buffers in SM4-CCM context * * @param[in] tag_len Array of authentication tag lengths * @param[in] mb_mask Bitmask selecting which lines to update * @param[in/out] p_context SM4-CCM context * */ EXTERN_C void sm4_ccm_set_tag_len_mb16(const int tag_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); EXTERN_C mbx_status16 sm4_ccm_update_aad_mb16(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); EXTERN_C mbx_status16 sm4_ccm_encrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); EXTERN_C mbx_status16 sm4_ccm_decrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); EXTERN_C mbx_status16 sm4_ccm_get_tag_mb16(int8u *pa_out[SM4_LINES], const int tag_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context); mbx_status16 internal_avx512_sm4_ccm_init_mb16(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], const int tag_len[SM4_LINES], const int64u msg_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context, __mmask16 mb_mask); #endif /* #if (_MBX>=_MBX_K1) */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* Context accessors */ #define SM4_CCM_CONTEXT_MSG_LEN(context) ((context)->msg_len) #define SM4_CCM_CONTEXT_PROCESSED_LEN(context) ((context)->total_processed_len) #define SM4_CCM_CONTEXT_TAG_LEN(context) ((context)->tag_len) #define SM4_CCM_CONTEXT_IV_LEN(context) ((context)->iv_len) #define SM4_CCM_CONTEXT_CTR0(context) ((context)->ctr0) #define SM4_CCM_CONTEXT_CTR(context) ((context)->ctr) #define SM4_CCM_CONTEXT_HASH(context) ((context)->hash) #define SM4_CCM_CONTEXT_KEY(context) (&((context)->key_sched)) #define SM4_CCM_CONTEXT_STATE(context) ((context)->state) /* Calculate offsets for accessing blocks in buffers */ #define REG_SIZE_BITS (512) #define REG_SIZE_BYTES (REG_SIZE_BITS / 8) /* Register size in bytes */ #define SLOTS_PER_BLOCK (SM4_BLOCK_SIZE / SM4_CCM_CONTEXT_BUFFER_SLOT_SIZE_BYTES) #define BLOCKS_PER_REG (REG_SIZE_BYTES / SM4_BLOCK_SIZE) #define BUFFER_BLOCK_NUM(buffer, n) (buffer + SLOTS_PER_BLOCK * n) #define BUFFER_REG_NUM(buffer, n) (buffer + SLOTS_PER_BLOCK * BLOCKS_PER_REG * n) /* Internal macros */ #define sm4_ccm_clear_buffer(p_buffer) storeu((void *)(p_buffer), setzero()); #define SM4_CCM_CLEAR_BUFFER(p_buffer) \ { \ sm4_ccm_clear_buffer(BUFFER_REG_NUM(p_buffer, 0)); \ sm4_ccm_clear_buffer(BUFFER_REG_NUM(p_buffer, 1)); \ sm4_ccm_clear_buffer(BUFFER_REG_NUM(p_buffer, 2)); \ sm4_ccm_clear_buffer(BUFFER_REG_NUM(p_buffer, 3)); \ } #define SM4_CCM_CLEAR_LEN(p_len) \ { \ sm4_ccm_clear_buffer(p_len); \ } #endif // SM4_CCM_MB_H cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm4/sm4_gcm_mb.h000066400000000000000000000206471470420105600313620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #ifndef SM4_GCM_MB_H #define SM4_GCM_MB_H ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* // Constant from NIST Special Publication 800-38D // (Recommendation for GCMmode, p.5.2.1.1 Input Data) // len(P) <= 2^39-256 bits */ static const int64u MAX_TXT_LEN = ((int64u)1 << 36) - 32; // length in bytes /* // Internal functions */ #if (_MBX>=_MBX_K1) EXTERN_C void sm4_gcm_ghash_mul_single_block_mb16(__m512i *data_blocks[], __m512i *hashkeys[]); EXTERN_C void sm4_gcm_update_ghash_full_blocks_mb16(__m128i ghash[SM4_LINES], const int8u *const pa_input[SM4_LINES], __m512i *input_len, __m128i hashkey[SM4_GCM_HASHKEY_PWR_NUM][SM4_LINES], __mmask16 mb_mask); EXTERN_C void sm4_gcm_update_ghash_partial_blocks_mb16(__m128i ghash[SM4_LINES], const int8u *const pa_input[SM4_LINES], __m512i *input_len, __m128i hashkey[SM4_LINES], __mmask16 mb_mask); EXTERN_C void sm4_gcm_precompute_hashkey_mb16(const mbx_sm4_key_schedule *key_sched, SM4_GCM_CTX_mb16 *p_context); EXTERN_C __mmask16 sm4_gcm_update_iv_mb16(const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); EXTERN_C void sm4_gcm_finalize_iv_mb16(const int8u *const pa_iv[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); EXTERN_C __mmask16 sm4_gcm_update_aad_mb16(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); EXTERN_C void sm4_encrypt_j0_mb16(SM4_GCM_CTX_mb16 *p_context); EXTERN_C void sm4_gctr_kernel_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u *key_sched[SM4_ROUNDS], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); EXTERN_C __mmask16 sm4_gcm_encrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); EXTERN_C __mmask16 sm4_gcm_decrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); EXTERN_C mbx_status16 sm4_gcm_get_tag_mb16(int8u *pa_out[SM4_LINES], const int tag_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context); mbx_status16 internal_avx512_sm4_gcm_init_mb16(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context, __mmask16 mb_mask_rearranged, __mmask16 mb_mask); __MBX_INLINE __m512i inc_block32(__m512i x, const int8u *increment) { return mask_add_epi32(x, 0x1111, x, M512(increment)); } static __ALIGN64 const int8u initialInc[] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #endif /* #if (_MBX>=_MBX_K1) */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* Context accessors */ #define SM4_GCM_CONTEXT_HASHKEY(context) ((p_context)->hashkey) #define SM4_GCM_CONTEXT_J0(context) ((p_context)->j0) #define SM4_GCM_CONTEXT_GHASH(context) ((p_context)->ghash) #define SM4_GCM_CONTEXT_CTR(context) ((p_context)->ctr) #define SM4_GCM_CONTEXT_LEN(context) ((p_context)->len) #define SM4_GCM_CONTEXT_KEY(context) (&((p_context)->key_sched)) #define SM4_GCM_CONTEXT_STATE(context) ((p_context)->state) /* Calculate offsets for accessing blocks in buffers */ #define REG_SIZE_BITS (512) #define REG_SIZE_BYTES (REG_SIZE_BITS / 8) /* Register size in bytes */ #define SLOTS_PER_BLOCK (SM4_BLOCK_SIZE / SM4_GCM_CONTEXT_BUFFER_SLOT_SIZE_BYTES) #define BLOCKS_PER_REG (REG_SIZE_BYTES / SM4_BLOCK_SIZE) #define BUFFER_BLOCK_NUM(buffer, n) (buffer + SLOTS_PER_BLOCK * n) #define BUFFER_REG_NUM(buffer, n) (buffer + SLOTS_PER_BLOCK * BLOCKS_PER_REG * n) /* Internal macros */ #define sm4_gcm_clear_buffer(p_buffer) storeu((void *)(p_buffer), setzero()); #define SM4_GCM_CLEAR_BUFFER(p_buffer) \ { \ sm4_gcm_clear_buffer(BUFFER_REG_NUM(p_buffer, 0)); \ sm4_gcm_clear_buffer(BUFFER_REG_NUM(p_buffer, 1)); \ sm4_gcm_clear_buffer(BUFFER_REG_NUM(p_buffer, 2)); \ sm4_gcm_clear_buffer(BUFFER_REG_NUM(p_buffer, 3)); \ } #define SM4_GCM_CLEAR_LEN(p_len) \ { \ sm4_gcm_clear_buffer(p_len); \ } /* Constants */ /* GCM polynomials for reduction */ static __ALIGN64 const int64u gcm_poly[] = { 0x0000000000000001, 0xC200000000000000, 0x0000000000000001, 0xC200000000000000, 0x0000000000000001, 0xC200000000000000, 0x0000000000000001, 0xC200000000000000 }; static __ALIGN64 const int64u gcm_poly2[] = { 0x00000001C2000000, 0xC200000000000000, 0x00000001C2000000, 0xC200000000000000, 0x00000001C2000000, 0xC200000000000000, 0x00000001C2000000, 0xC200000000000000 }; /* */ static __ALIGN64 const int64u two_one[] = { 0x0000000000000001, 0x0000000100000000, 0x0000000000000001, 0x0000000100000000, 0x0000000000000001, 0x0000000100000000, 0x0000000000000001, 0x0000000100000000 }; /* Constant for IV of 12 bytes size finalization */ static __ALIGN64 const int64u one_f[] = { 0x0000000000000000, 0x0100000000000000, 0x0000000000000000, 0x0100000000000000, 0x0000000000000000, 0x0100000000000000, 0x0000000000000000, 0x0100000000000000 }; static __ALIGN64 const int64u bytes_to_bits_shift[] = { 0x0000000000000003, 0x0000000000000000 }; static const int rearrangeOrder[] = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; /* Need to rearrange input pointers and lengths to keep it in the same layout with hashkeys */ #define rearrange(to, from) \ to[0] = from[0]; \ to[1] = from[4]; \ to[2] = from[8]; \ to[3] = from[12]; \ to[4] = from[1]; \ to[5] = from[5]; \ to[6] = from[9]; \ to[7] = from[13]; \ to[8] = from[2]; \ to[9] = from[6]; \ to[10] = from[10]; \ to[11] = from[14]; \ to[12] = from[3]; \ to[13] = from[7]; \ to[14] = from[11]; \ to[15] = from[15]; #endif // SM4_GCM_MB_H cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/include/internal/sm4/sm4_mb.h000066400000000000000000001216571470420105600305370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_SM4_GFNI_MB_H) #define _SM4_GFNI_MB_H #include #include #include #include #if (_MBX>=_MBX_K1) #ifndef M128 #define M128(mem) (*((__m128i*)(mem))) #endif #ifndef M256 #define M256(mem) (*((__m256i*)(mem))) #endif #ifndef M512 #define M512(mem) (*((__m512i*)(mem))) #endif #define loadu _mm512_loadu_si512 #define storeu _mm512_storeu_si512 #define mask_storeu_epi64 _mm512_mask_storeu_epi64 #define maskz_expandloadu_epi32 _mm512_maskz_expandloadu_epi32 #define mask_storeu_epi8 _mm512_mask_storeu_epi8 #define maskz_loadu_epi8 _mm512_maskz_loadu_epi8 #define srli_epi64 _mm512_srli_epi64 #define slli_epi64 _mm512_slli_epi64 #define bsrli_epi128 _mm512_bsrli_epi128 #define bslli_epi128 _mm512_bslli_epi128 #define shuffle_epi8 _mm512_shuffle_epi8 #define shuffle_epi32 _mm512_shuffle_epi32 #define set1_epi32 _mm512_set1_epi32 #define set1_epi64 _mm512_set1_epi64 #define setzero _mm512_setzero_si512 #define cmpeq_epi32_mask _mm512_cmpeq_epi32_mask #define cmp_epi32_mask _mm512_cmp_epi32_mask #define cmp_epi64_mask _mm512_cmp_epi64_mask #define mask_set1_epi32 _mm512_mask_set1_epi32 #define mask_sub_epi32 _mm512_mask_sub_epi32 #define mask_add_epi32 _mm512_mask_add_epi32 #define mask_add_epi64 _mm512_mask_add_epi64 #define add_epi32 _mm512_add_epi32 #define sub_epi32 _mm512_sub_epi32 #define add_epi64 _mm512_add_epi64 #define or _mm512_or_si512 #define and _mm512_and_si512 #define xor _mm512_xor_si512 #define clmul _mm512_clmulepi64_epi128 #define unpacklo_epi32 _mm512_unpacklo_epi32 #define unpackhi_epi32 _mm512_unpackhi_epi32 #define unpacklo_epi64 _mm512_unpacklo_epi64 #define unpackhi_epi64 _mm512_unpackhi_epi64 #define insert32x4 _mm512_inserti32x4 #define sll_epi32 _mm512_sll_epi32 #define srli_epi32 _mm512_srli_epi32 #define mask_cmp_epi32_mask _mm512_mask_cmp_epi32_mask #define broadcast_i64x2 _mm512_broadcast_i64x2 /* // Constants */ static __ALIGN64 const int8u permMask_in[] = { 0,0x00,0x00,0x00, 4,0x00,0x00,0x00, 8,0x00,0x00,0x00, 12,0x00,0x00,0x00, 1,0x00,0x00,0x00, 5,0x00,0x00,0x00, 9,0x00,0x00,0x00, 13,0x00,0x00,0x00, 2,0x00,0x00,0x00, 6,0x00,0x00,0x00, 10,0x00,0x00,0x00, 14,0x00,0x00,0x00, 3,0x00,0x00,0x00, 7,0x00,0x00,0x00, 11,0x00,0x00,0x00, 15,0x00,0x00,0x00 }; static __ALIGN64 const int8u permMask_out[] = { 12,0x00,0x00,0x00, 8,0x00,0x00,0x00, 4,0x00,0x00,0x00, 0,0x00,0x00,0x00, 13,0x00,0x00,0x00, 9,0x00,0x00,0x00, 5,0x00,0x00,0x00, 1,0x00,0x00,0x00, 14,0x00,0x00,0x00, 10,0x00,0x00,0x00, 6,0x00,0x00,0x00, 2,0x00,0x00,0x00, 15,0x00,0x00,0x00, 11,0x00,0x00,0x00, 7,0x00,0x00,0x00, 3,0x00,0x00,0x00 }; static __ALIGN64 const int8u affineIn[] = { 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34 }; static __ALIGN64 const int8u affineOut[] = { 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7 }; // Constant for swapping the bytes inside the words static __ALIGN64 const int8u swapBytes[] = { 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 }; // Constant for swapping the endianness static __ALIGN64 const int8u swapEndianness[] = { 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0 }; // Constant for swapping the order of words static __ALIGN64 const int8u swapWordsOrder[] = { 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3 }; static __ALIGN64 const int64u idx_0_3[] = { 0x0000000000000000, 0x0000000000000000, 0x0000000100000001, 0x0000000100000001, 0x0000000200000002, 0x0000000200000002, 0x0000000300000003, 0x0000000300000003 }; static __ALIGN64 const int64u idx_4_7[] = { 0x0000000400000004, 0x0000000400000004, 0x0000000500000005, 0x0000000500000005, 0x0000000600000006, 0x0000000600000006, 0x0000000700000007, 0x0000000700000007 }; static __ALIGN64 const int64u idx_8_b[] = { 0x0000000800000008, 0x0000000800000008, 0x0000000900000009, 0x0000000900000009, 0x0000000a0000000a, 0x0000000a0000000a, 0x0000000b0000000b, 0x0000000b0000000b }; static __ALIGN64 const int64u idx_c_f[] = { 0x0000000c0000000c, 0x0000000c0000000c, 0x0000000d0000000d, 0x0000000d0000000d, 0x0000000e0000000e, 0x0000000e0000000e, 0x0000000f0000000f, 0x0000000f0000000f }; static __ALIGN64 const int8u firstInc[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; static __ALIGN64 const int8u nextInc[] = { 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; static __ALIGN64 const int8u shuf8[] = { 0x01, 0x02, 0x03, 0x00, 0x05, 0x06, 0x07, 0x04, 0x09, 0x0A, 0x0B, 0x08, 0x0D, 0x0E, 0x0F, 0x0C, 0x01, 0x02, 0x03, 0x00, 0x05, 0x06, 0x07, 0x04, 0x09, 0x0A, 0x0B, 0x08, 0x0D, 0x0E, 0x0F, 0x0C, 0x01, 0x02, 0x03, 0x00, 0x05, 0x06, 0x07, 0x04, 0x09, 0x0A, 0x0B, 0x08, 0x0D, 0x0E, 0x0F, 0x0C, 0x01, 0x02, 0x03, 0x00, 0x05, 0x06, 0x07, 0x04, 0x09, 0x0A, 0x0B, 0x08, 0x0D, 0x0E, 0x0F, 0x0C, }; /* For SM4-XTS */ static __ALIGN64 const int64u xts_poly[] = { 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87 }; static __ALIGN64 const int8u xts_shuf_mask[] = { 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static __ALIGN64 const int64u xts_const_dq3210[] = { 0, 0, 1, 1, 2, 2, 3, 3 }; static __ALIGN64 const int64u xts_const_dq5678[] = { 8, 8, 7, 7, 6, 6, 5, 5 }; static __ALIGN64 const int32u xts_full_block_mask[] = { 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0, 0xfffffff0 }; static __ALIGN64 const int32u xts_partial_block_mask[] = { 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f }; static __ALIGN64 const int32u xts_dw0_7_to_qw_idx[] = { 0, 0xFF, 1, 0xFF, 2, 0xFF, 3, 0xFF, 4, 0xFF, 5, 0xFF, 6, 0xFF, 7, 0xFF }; static __ALIGN64 const int32u xts_dw8_15_to_qw_idx[] = { 8, 0xFF, 9, 0xFF, 10, 0xFF, 11, 0xFF, 12, 0xFF, 13, 0xFF, 14, 0xFF, 15, 0xFF }; static __ALIGN64 const int64u xts_tweak_permq[] = { 2, 3, 0, 1, 0xFF, 0xFF, 0xFF, 0xFF, 0, 1, 4, 5, 2, 3, 0xFF, 0xFF, 0, 1, 2, 3, 6, 7, 4, 5, 0, 1, 2, 3, 4, 5, 10, 11 /* for vpermi2q */ }; static __ALIGN64 const int64u xts_next_tweak_permq[] = { 0, 1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 2, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 4, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 14, 15, 0, 1, 0xFF, 0xFF, 0xFF, 0xFF /* for vpermi2q */ }; static __ALIGN64 const int64u xts_next_tweak_permq_enc[] = { 2, 3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 4, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 6, 7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, }; #define SM4_ONE_ROUND(X0, X1, X2, X3, TMP, RK) { \ /* (Xi+1 ^ Xi+2 ^ Xi+3 ^ rki) */ \ TMP = _mm512_ternarylogic_epi32 (X1, X2, X3, 0x96); \ TMP = _mm512_xor_epi32(TMP, _mm512_loadu_si512(RK)); \ /* T(Xi+1 ^ Xi+2 ^ Xi+3 ^ rki) */ \ TMP = sBox512(TMP); \ X0 = _mm512_ternarylogic_epi64 (X0, TMP, Lblock512(TMP), 0x96); \ } #define SM4_FOUR_ROUNDS(X0, X1, X2, X3, TMP, RK, sign) { \ SM4_ONE_ROUND(X0, X1, X2, X3, TMP, RK); \ SM4_ONE_ROUND(X1, X2, X3, X0, TMP, (RK + sign * 1)); \ SM4_ONE_ROUND(X2, X3, X0, X1, TMP, (RK + sign * 2)); \ SM4_ONE_ROUND(X3, X0, X1, X2, TMP, (RK + sign * 3)); \ } #define SM4_ONE_ROUND_MASKED(X0, X1, X2, X3, TMP, MASK, RK) { \ /* (Xi+1 ^ Xi+2 ^ Xi+3 ^ rki) */ \ TMP = _mm512_xor_epi32(_mm512_xor_epi32(_mm512_xor_epi32(X1, X2), X3), _mm512_loadu_si512(RK)); \ /* T(Xi+1 ^ Xi+2 ^ Xi+3 ^ rki) */ \ TMP = sBox512(TMP); \ TMP = _mm512_xor_epi32(TMP, Lblock512(TMP)); \ /* Xi+4 = Xi ^ T(Xi+1 ^ Xi+2 ^ Xi+3 ^ rki) */ \ X0 = _mm512_mask_xor_epi32(X0, MASK, X0, TMP); \ } #define SM4_FOUR_ROUNDS_MASKED(X0, X1, X2, X3, TMP, MASK, RK, sign) { \ SM4_ONE_ROUND_MASKED(X0, X1, X2, X3, TMP, MASK, RK); \ SM4_ONE_ROUND_MASKED(X1, X2, X3, X0, TMP, MASK, (RK + sign * 1)); \ SM4_ONE_ROUND_MASKED(X2, X3, X0, X1, TMP, MASK, (RK + sign * 2)); \ SM4_ONE_ROUND_MASKED(X3, X0, X1, X2, TMP, MASK, (RK + sign * 3)); \ } #define EXPAND_ONE_RKEY(X, p_rk) { \ X[0] = _mm512_permutexvar_epi32(M512(idx_0_3), _mm512_loadu_si512(p_rk)); \ X[1] = _mm512_permutexvar_epi32(M512(idx_4_7), _mm512_loadu_si512(p_rk)); \ X[2] = _mm512_permutexvar_epi32(M512(idx_8_b), _mm512_loadu_si512(p_rk)); \ X[3] = _mm512_permutexvar_epi32(M512(idx_c_f), _mm512_loadu_si512(p_rk)); \ } #define ENDIANNESS_16x32(x) _mm512_shuffle_epi8((x), M512(swapBytes)); #define CHANGE_ORDER_BLOCKS(x) _mm512_shuffle_epi8((x), M512(swapEndianness)); /* Workaround for gcc91, got the error: implicit declaration of function ‘_mm512_div_epi32’ */ #if defined(__GNUC__) && !defined(__INTEL_COMPILER) #define GET_NUM_BLOCKS(OUT, LEN, BLOCK_SIZE) \ { \ int32u blocks[SM4_LINES]; \ for (int i = 0; i < SM4_LINES; i++) \ blocks[i] = (LEN)[i] / (BLOCK_SIZE); \ (OUT) = _mm512_loadu_si512(blocks); \ } #else #define GET_NUM_BLOCKS(OUT, LEN, BLOCK_SIZE) (OUT) = _mm512_div_epi32(_mm512_loadu_si512(LEN), _mm512_set1_epi32(BLOCK_SIZE)) #endif #define UPDATE_STREAM_MASK_16(MASK, p_len) \ MASK = *p_len < (16) ? (*p_len <= 0 ? 0 : ((int64u)1 << *p_len) - 1) : (__mmask64)(0xFFFF); p_len++; #define UPDATE_STREAM_MASK_64(MASK, p_len) MASK = *p_len < (4 * 16) ? (*p_len <= 0 ? 0 : ((int64u)1 << *p_len) - 1) : (__mmask64)(-1); p_len++; #define SM4_ENC (1) #define SM4_DEC (-1) #ifdef __cplusplus extern "C" { #endif /* // Internal functions */ #define sm4_ecb_kernel_mb16 OWNAPI(sm4_ecb_kernel_mb16) mbx_status16 sm4_ecb_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, int operation); #define sm4_cbc_enc_kernel_mb16 OWNAPI(sm4_cbc_enc_kernel_mb16) mbx_status16 sm4_cbc_enc_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, const int8u* pa_iv[SM4_LINES]); #define sm4_cbc_dec_kernel_mb16 OWNAPI(sm4_cbc_dec_kernel_mb16) mbx_status16 sm4_cbc_dec_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, const int8u* pa_iv[SM4_LINES]); #define sm4_cbc_mac_kernel_mb16 OWNAPI(sm4_cbc_mac_kernel_mb16) void sm4_cbc_mac_kernel_mb16(__m128i pa_out[SM4_LINES], const int8u *const pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, const int8u* pa_iv[SM4_LINES]); #define sm4_ctr128_kernel_mb16 OWNAPI(sm4_ctr128_kernel_mb16) mbx_status16 sm4_ctr128_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, int8u* pa_ctr[SM4_LINES]); #define sm4_ofb_kernel_mb16 OWNAPI(sm4_ofb_kernel_mb16) mbx_status16 sm4_ofb_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, int8u* pa_iv[SM4_LINES]); #define sm4_cfb128_enc_kernel_mb16 OWNAPI(sm4_cfb128_enc_kernel_mb16) mbx_status16 sm4_cfb128_enc_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], const int8u* pa_iv[SM4_LINES], __mmask16 mb_mask); #define sm4_cfb128_dec_kernel_mb16 OWNAPI(sm4_cfb128_dec_kernel_mb16) mbx_status16 sm4_cfb128_dec_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], const int8u* pa_iv[SM4_LINES], __mmask16 mb_mask); #define sm4_xts_kernel_mb16 OWNAPI(sm4_xts_kernel_mb16) mbx_status16 sm4_xts_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], \ const int32u* key_sched1[SM4_ROUNDS], const int32u* key_sched2[SM4_ROUNDS], \ const int8u* pa_tweak[SM4_LINES], __mmask16 mb_mask, const int dir); mbx_status16 internal_avx512_sm4_set_round_keys_mb16(int32u* key_sched[SM4_ROUNDS], const int8u* pa_inp_key[SM4_LINES], __mmask16 mb_mask); mbx_status16 internal_avx512_sm4_xts_set_keys_mb16(mbx_sm4_key_schedule* key_sched1, mbx_sm4_key_schedule* key_sched2, const sm4_xts_key* pa_key[SM4_LINES], __mmask16 mb_mask); #ifdef __cplusplus } #endif // The transformation based on SM4 sbox algebraic structure, parameters were computed manually __MBX_INLINE __m512i sBox512(__m512i block) { block = _mm512_gf2p8affine_epi64_epi8(block, M512(affineIn), 0x65); block = _mm512_gf2p8affineinv_epi64_epi8(block, M512(affineOut), 0xd3); return block; } __MBX_INLINE __m512i Lblock512(__m512i x) { return _mm512_ternarylogic_epi32(_mm512_xor_si512(_mm512_rol_epi32(x, 2), _mm512_rol_epi32(x, 10)), _mm512_rol_epi32(x, 18), _mm512_shuffle_epi8 (x, _mm512_loadu_si512(shuf8)), 0x96); } __MBX_INLINE __m512i Lkey512(__m512i x) { return _mm512_xor_epi32(_mm512_rol_epi32(x, 13), _mm512_rol_epi32(x, 23)); } __MBX_INLINE __m512i IncBlock512(__m512i x, const int8u* increment) { __m512i t = _mm512_add_epi64(x, M512(increment)); __mmask8 carryMask = _mm512_cmplt_epu64_mask(t, x); carryMask = (__mmask8)(carryMask << 1); t = _mm512_add_epi64(t, _mm512_mask_set1_epi64(_mm512_setzero_si512(), carryMask, 1)); return t; } #define SM4_KERNEL(TMP, p_rk, iterator) \ for (int itr = 0, j = 0; itr < 8; itr++, j++) { \ /* initial xors */ \ EXPAND_ONE_RKEY(TMP, p_rk); p_rk+=iterator; \ TMP[0] = _mm512_ternarylogic_epi32 (TMP[0], TMP[5], TMP[6], 0x96); \ TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); \ TMP[1] = _mm512_ternarylogic_epi32 (TMP[1], TMP[9], TMP[10], 0x96); \ TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); \ TMP[2] = _mm512_ternarylogic_epi32 (TMP[2], TMP[13], TMP[14], 0x96); \ TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); \ TMP[3] = _mm512_ternarylogic_epi32 (TMP[3], TMP[17], TMP[18], 0x96); \ TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); \ /* Sbox */ \ TMP[0] = sBox512(TMP[0]); \ TMP[1] = sBox512(TMP[1]); \ TMP[2] = sBox512(TMP[2]); \ TMP[3] = sBox512(TMP[3]); \ /* Sbox done, now L */ \ TMP[4] = _mm512_ternarylogic_epi32(TMP[4], TMP[0], Lblock512(TMP[0]), 0x96); \ TMP[8] = _mm512_ternarylogic_epi32(TMP[8], TMP[1], Lblock512(TMP[1]), 0x96); \ TMP[12] = _mm512_ternarylogic_epi32(TMP[12], TMP[2], Lblock512(TMP[2]), 0x96); \ TMP[16] = _mm512_ternarylogic_epi32(TMP[16], TMP[3], Lblock512(TMP[3]), 0x96); \ /* initial xors */ \ EXPAND_ONE_RKEY(TMP, p_rk); p_rk+=iterator; \ TMP[0] = _mm512_ternarylogic_epi32 (TMP[0], TMP[6], TMP[7], 0x96); \ TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); \ TMP[1] = _mm512_ternarylogic_epi32 (TMP[1], TMP[10], TMP[11], 0x96); \ TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); \ TMP[2] = _mm512_ternarylogic_epi32 (TMP[2], TMP[14], TMP[15], 0x96); \ TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); \ TMP[3] = _mm512_ternarylogic_epi32 (TMP[3], TMP[18], TMP[19], 0x96); \ TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); \ /* Sbox */ \ TMP[0] = sBox512(TMP[0]); \ TMP[1] = sBox512(TMP[1]); \ TMP[2] = sBox512(TMP[2]); \ TMP[3] = sBox512(TMP[3]); \ /* Sbox done, now L */ \ TMP[5] = _mm512_ternarylogic_epi32(TMP[5], TMP[0], Lblock512(TMP[0]), 0x96); \ TMP[9] = _mm512_ternarylogic_epi32(TMP[9], TMP[1], Lblock512(TMP[1]), 0x96); \ TMP[13] = _mm512_ternarylogic_epi32(TMP[13], TMP[2], Lblock512(TMP[2]), 0x96); \ TMP[17] = _mm512_ternarylogic_epi32(TMP[17], TMP[3], Lblock512(TMP[3]), 0x96); \ \ /* initial xors */ \ EXPAND_ONE_RKEY(TMP, p_rk); p_rk+=iterator; \ TMP[0] = _mm512_ternarylogic_epi32 (TMP[0], TMP[7], TMP[4], 0x96); \ TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); \ TMP[1] = _mm512_ternarylogic_epi32 (TMP[1], TMP[11], TMP[8], 0x96); \ TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); \ TMP[2] = _mm512_ternarylogic_epi32 (TMP[2], TMP[15], TMP[12], 0x96); \ TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); \ TMP[3] = _mm512_ternarylogic_epi32 (TMP[3], TMP[19], TMP[16], 0x96); \ TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); \ /* Sbox */ \ TMP[0] = sBox512(TMP[0]); \ TMP[1] = sBox512(TMP[1]); \ TMP[2] = sBox512(TMP[2]); \ TMP[3] = sBox512(TMP[3]); \ /* Sbox done, now L */ \ TMP[6] = _mm512_ternarylogic_epi32(TMP[6], TMP[0], Lblock512(TMP[0]), 0x96); \ TMP[10] = _mm512_ternarylogic_epi32(TMP[10], TMP[1], Lblock512(TMP[1]), 0x96); \ TMP[14] = _mm512_ternarylogic_epi32(TMP[14], TMP[2], Lblock512(TMP[2]), 0x96); \ TMP[18] = _mm512_ternarylogic_epi32(TMP[18], TMP[3], Lblock512(TMP[3]), 0x96); \ \ /* initial xors */ \ EXPAND_ONE_RKEY(TMP, p_rk); p_rk+=iterator; \ TMP[0] = _mm512_ternarylogic_epi32 (TMP[0], TMP[4], TMP[5], 0x96); \ TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); \ TMP[1] = _mm512_ternarylogic_epi32 (TMP[1], TMP[8], TMP[9], 0x96); \ TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); \ TMP[2] = _mm512_ternarylogic_epi32 (TMP[2], TMP[12], TMP[13], 0x96); \ TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); \ TMP[3] = _mm512_ternarylogic_epi32 (TMP[3], TMP[16], TMP[17], 0x96); \ TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); \ /* Sbox */ \ TMP[0] = sBox512(TMP[0]); \ TMP[1] = sBox512(TMP[1]); \ TMP[2] = sBox512(TMP[2]); \ TMP[3] = sBox512(TMP[3]); \ /* Sbox done, now L */ \ TMP[7] = _mm512_ternarylogic_epi32(TMP[7], TMP[0], Lblock512(TMP[0]), 0x96); \ TMP[11] = _mm512_ternarylogic_epi32(TMP[11], TMP[1], Lblock512(TMP[1]), 0x96); \ TMP[15] = _mm512_ternarylogic_epi32(TMP[15], TMP[2], Lblock512(TMP[2]), 0x96); \ TMP[19] = _mm512_ternarylogic_epi32(TMP[19], TMP[3], Lblock512(TMP[3]), 0x96); \ } /* // Transpose functions */ #define TRANSPOSE_INP_512(K0,K1,K2,K3, T0,T1,T2,T3) \ K0 = _mm512_unpacklo_epi32(T0, T1); \ K1 = _mm512_unpacklo_epi32(T2, T3); \ K2 = _mm512_unpackhi_epi32(T0, T1); \ K3 = _mm512_unpackhi_epi32(T2, T3); \ \ T0 = _mm512_unpacklo_epi64(K0, K1); \ T1 = _mm512_unpacklo_epi64(K2, K3); \ T2 = _mm512_unpackhi_epi64(K0, K1); \ T3 = _mm512_unpackhi_epi64(K2, K3); \ \ K2 = _mm512_permutexvar_epi32(M512(permMask_in), T1); \ K1 = _mm512_permutexvar_epi32(M512(permMask_in), T2); \ K3 = _mm512_permutexvar_epi32(M512(permMask_in), T3); \ K0 = _mm512_permutexvar_epi32(M512(permMask_in), T0) #define TRANSPOSE_OUT_512(T0,T1,T2,T3, K0,K1,K2,K3) \ T0 = _mm512_shuffle_i32x4(K0, K1, 0x44); \ T1 = _mm512_shuffle_i32x4(K0, K1, 0xee); \ T2 = _mm512_shuffle_i32x4(K2, K3, 0x44); \ T3 = _mm512_shuffle_i32x4(K2, K3, 0xee); \ \ K0 = _mm512_shuffle_i32x4(T0, T2, 0x88); \ K1 = _mm512_shuffle_i32x4(T0, T2, 0xdd); \ K2 = _mm512_shuffle_i32x4(T1, T3, 0x88); \ K3 = _mm512_shuffle_i32x4(T1, T3, 0xdd); \ \ K0 = _mm512_permutexvar_epi32(M512(permMask_out), K0);\ K1 = _mm512_permutexvar_epi32(M512(permMask_out), K1);\ K2 = _mm512_permutexvar_epi32(M512(permMask_out), K2);\ K3 = _mm512_permutexvar_epi32(M512(permMask_out), K3);\ \ T0=K0,T1=K1,T2=K2,T3=K3 __MBX_INLINE void TRANSPOSE_16x4_I32_EPI32(__m512i* t0, __m512i* t1, __m512i* t2, __m512i* t3, const int8u* p_inp[16], __mmask16 mb_mask) { __mmask16 loc_mb_mask = mb_mask; // L0 - L3 __m512i z0 = _mm512_maskz_loadu_epi32(0x000F * (0x1&loc_mb_mask), p_inp[0]); loc_mb_mask >>= 1; __m512i z1 = _mm512_maskz_loadu_epi32(0x000F * (0x1&loc_mb_mask), p_inp[1]); loc_mb_mask >>= 1; __m512i z2 = _mm512_maskz_loadu_epi32(0x000F * (0x1&loc_mb_mask), p_inp[2]); loc_mb_mask >>= 1; __m512i z3 = _mm512_maskz_loadu_epi32(0x000F * (0x1&loc_mb_mask), p_inp[3]); loc_mb_mask >>= 1; // L4 - L7 z0 = _mm512_mask_loadu_epi32(z0, 0x00F0 * (0x1&loc_mb_mask), (__m128i*)p_inp[4] - 1); loc_mb_mask >>= 1; z1 = _mm512_mask_loadu_epi32(z1, 0x00F0 * (0x1&loc_mb_mask), (__m128i*)p_inp[5] - 1); loc_mb_mask >>= 1; z2 = _mm512_mask_loadu_epi32(z2, 0x00F0 * (0x1&loc_mb_mask), (__m128i*)p_inp[6] - 1); loc_mb_mask >>= 1; z3 = _mm512_mask_loadu_epi32(z3, 0x00F0 * (0x1&loc_mb_mask), (__m128i*)p_inp[7] - 1); loc_mb_mask >>= 1; // L8 - Lb z0 = _mm512_mask_loadu_epi32(z0, 0x0F00 * (0x1&loc_mb_mask), (__m128i*)p_inp[8] - 2); loc_mb_mask >>= 1; z1 = _mm512_mask_loadu_epi32(z1, 0x0F00 * (0x1&loc_mb_mask), (__m128i*)p_inp[9] - 2); loc_mb_mask >>= 1; z2 = _mm512_mask_loadu_epi32(z2, 0x0F00 * (0x1&loc_mb_mask), (__m128i*)p_inp[10] - 2); loc_mb_mask >>= 1; z3 = _mm512_mask_loadu_epi32(z3, 0x0F00 * (0x1&loc_mb_mask), (__m128i*)p_inp[11] - 2); loc_mb_mask >>= 1; // Lc - Lf *t0 = ENDIANNESS_16x32(_mm512_mask_loadu_epi32(z0, 0xF000 * (0x1&loc_mb_mask), (__m128i*)p_inp[12] - 3)); loc_mb_mask >>= 1; *t1 = ENDIANNESS_16x32(_mm512_mask_loadu_epi32(z1, 0xF000 * (0x1&loc_mb_mask), (__m128i*)p_inp[13] - 3)); loc_mb_mask >>= 1; *t2 = ENDIANNESS_16x32(_mm512_mask_loadu_epi32(z2, 0xF000 * (0x1&loc_mb_mask), (__m128i*)p_inp[14] - 3)); loc_mb_mask >>= 1; *t3 = ENDIANNESS_16x32(_mm512_mask_loadu_epi32(z3, 0xF000 * (0x1&loc_mb_mask), (__m128i*)p_inp[15] - 3)); loc_mb_mask >>= 1; z0 = _mm512_unpacklo_epi32(*t0, *t1); z1 = _mm512_unpackhi_epi32(*t0, *t1); z2 = _mm512_unpacklo_epi32(*t2, *t3); z3 = _mm512_unpackhi_epi32(*t2, *t3); *t0 = _mm512_unpacklo_epi64(z0, z2); *t1 = _mm512_unpackhi_epi64(z0, z2); *t2 = _mm512_unpacklo_epi64(z1, z3); *t3 = _mm512_unpackhi_epi64(z1, z3); } __MBX_INLINE void TRANSPOSE_16x4_I32_XMM_EPI32(__m512i* t0, __m512i* t1, __m512i* t2, __m512i* t3, const __m128i in[16]) { // L0 - L3 __m512i z0 = _mm512_castsi128_si512(in[0]); __m512i z1 = _mm512_castsi128_si512(in[1]); __m512i z2 = _mm512_castsi128_si512(in[2]); __m512i z3 = _mm512_castsi128_si512(in[3]); // L4 - L7 z0 = _mm512_inserti64x2(z0, in[4], 1); z1 = _mm512_inserti64x2(z1, in[5], 1); z2 = _mm512_inserti64x2(z2, in[6], 1); z3 = _mm512_inserti64x2(z3, in[7], 1); // L8 - Lb z0 = _mm512_inserti64x2(z0, in[8], 2); z1 = _mm512_inserti64x2(z1, in[9], 2); z2 = _mm512_inserti64x2(z2, in[10], 2); z3 = _mm512_inserti64x2(z3, in[11], 2); // Lc - Lf *t0 = ENDIANNESS_16x32(_mm512_inserti64x2(z0, in[12], 3)); *t1 = ENDIANNESS_16x32(_mm512_inserti64x2(z1, in[13], 3)); *t2 = ENDIANNESS_16x32(_mm512_inserti64x2(z2, in[14], 3)); *t3 = ENDIANNESS_16x32(_mm512_inserti64x2(z3, in[15], 3)); z0 = _mm512_unpacklo_epi32(*t0, *t1); z1 = _mm512_unpackhi_epi32(*t0, *t1); z2 = _mm512_unpacklo_epi32(*t2, *t3); z3 = _mm512_unpackhi_epi32(*t2, *t3); *t0 = _mm512_unpacklo_epi64(z0, z2); *t1 = _mm512_unpackhi_epi64(z0, z2); *t2 = _mm512_unpacklo_epi64(z1, z3); *t3 = _mm512_unpackhi_epi64(z1, z3); } __MBX_INLINE void TRANSPOSE_4x16_I32_EPI32(__m512i* t0, __m512i* t1, __m512i* t2, __m512i* t3, int8u* p_out[16], __mmask16 mb_mask) { #define STORE_RESULT(OUT, store_mask, loc_mb_mask, Ti) \ _mm512_mask_storeu_epi32(OUT, store_mask * (0x1&loc_mb_mask), Ti); \ loc_mb_mask >>= 1; __mmask16 loc_mb_mask = mb_mask; __m512i z0 = _mm512_unpacklo_epi32(*t0, *t1); __m512i z1 = _mm512_unpackhi_epi32(*t0, *t1); __m512i z2 = _mm512_unpacklo_epi32(*t2, *t3); __m512i z3 = _mm512_unpackhi_epi32(*t2, *t3); /* Get the right endianness and do (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) */ *t0 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z0, z2)); *t1 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z0, z2)); *t2 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z1, z3)); *t3 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z1, z3)); // L0 - L3 STORE_RESULT(p_out[0], 0x000F, loc_mb_mask, *t0); STORE_RESULT(p_out[1], 0x000F, loc_mb_mask, *t1); STORE_RESULT(p_out[2], 0x000F, loc_mb_mask, *t2); STORE_RESULT(p_out[3], 0x000F, loc_mb_mask, *t3); // L4 - L7 STORE_RESULT((__m128i*)p_out[4] - 1, 0x00F0, loc_mb_mask, *t0); STORE_RESULT((__m128i*)p_out[5] - 1, 0x00F0, loc_mb_mask, *t1); STORE_RESULT((__m128i*)p_out[6] - 1, 0x00F0, loc_mb_mask, *t2); STORE_RESULT((__m128i*)p_out[7] - 1, 0x00F0, loc_mb_mask, *t3); // L8 - Lb STORE_RESULT((__m128i*)p_out[8] - 2, 0x0F00, loc_mb_mask, *t0); STORE_RESULT((__m128i*)p_out[9] - 2, 0x0F00, loc_mb_mask, *t1); STORE_RESULT((__m128i*)p_out[10] - 2, 0x0F00, loc_mb_mask, *t2); STORE_RESULT((__m128i*)p_out[11] - 2, 0x0F00, loc_mb_mask, *t3); // Lc - Lf STORE_RESULT((__m128i*)p_out[12] - 3, 0xF000, loc_mb_mask, *t0); STORE_RESULT((__m128i*)p_out[13] - 3, 0xF000, loc_mb_mask, *t1); STORE_RESULT((__m128i*)p_out[14] - 3, 0xF000, loc_mb_mask, *t2); STORE_RESULT((__m128i*)p_out[15] - 3, 0xF000, loc_mb_mask, *t3); } __MBX_INLINE void TRANSPOSE_4x16_I32_XMM_EPI32(__m512i* t0, __m512i* t1, __m512i* t2, __m512i* t3, __m128i out[16]) { __m512i z0 = _mm512_unpacklo_epi32(*t0, *t1); __m512i z1 = _mm512_unpackhi_epi32(*t0, *t1); __m512i z2 = _mm512_unpacklo_epi32(*t2, *t3); __m512i z3 = _mm512_unpackhi_epi32(*t2, *t3); /* Get the right endianness and do (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) */ *t0 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z0, z2)); *t1 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z0, z2)); *t2 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z1, z3)); *t3 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z1, z3)); // L0 - L3 out[0] = _mm512_extracti64x2_epi64(*t0, 0); out[1] = _mm512_extracti64x2_epi64(*t1, 0); out[2] = _mm512_extracti64x2_epi64(*t2, 0); out[3] = _mm512_extracti64x2_epi64(*t3, 0); // L4 - L7 out[4] = _mm512_extracti64x2_epi64(*t0, 1); out[5] = _mm512_extracti64x2_epi64(*t1, 1); out[6] = _mm512_extracti64x2_epi64(*t2, 1); out[7] = _mm512_extracti64x2_epi64(*t3, 1); // L8 - Lb out[8] = _mm512_extracti64x2_epi64(*t0, 2); out[9] = _mm512_extracti64x2_epi64(*t1, 2); out[10] = _mm512_extracti64x2_epi64(*t2, 2); out[11] = _mm512_extracti64x2_epi64(*t3, 2); // Lc - Lf out[12] = _mm512_extracti64x2_epi64(*t0, 3); out[13] = _mm512_extracti64x2_epi64(*t1, 3); out[14] = _mm512_extracti64x2_epi64(*t2, 3); out[15] = _mm512_extracti64x2_epi64(*t3, 3); } __MBX_INLINE void TRANSPOSE_4x16_I32_O128_EPI32(__m512i* t0, __m512i* t1, __m512i* t2, __m512i* t3, __m128i p_out[16], __mmask16 mb_mask) { #define STORE_RESULT(OUT, store_mask, loc_mb_mask, Ti) \ _mm512_mask_storeu_epi32(OUT, store_mask * (0x1&loc_mb_mask), Ti); \ loc_mb_mask >>= 1; __mmask16 loc_mb_mask = mb_mask; __m512i z0 = _mm512_unpacklo_epi32(*t0, *t1); __m512i z1 = _mm512_unpackhi_epi32(*t0, *t1); __m512i z2 = _mm512_unpacklo_epi32(*t2, *t3); __m512i z3 = _mm512_unpackhi_epi32(*t2, *t3); /* Get the right endianness and do (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) */ *t0 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z0, z2)); *t1 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z0, z2)); *t2 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z1, z3)); *t3 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z1, z3)); // L0 - L3 STORE_RESULT(&p_out[0], 0x000F, loc_mb_mask, *t0); STORE_RESULT(&p_out[1], 0x000F, loc_mb_mask, *t1); STORE_RESULT(&p_out[2], 0x000F, loc_mb_mask, *t2); STORE_RESULT(&p_out[3], 0x000F, loc_mb_mask, *t3); // L4 - L7 STORE_RESULT(&p_out[4] - 1, 0x00F0, loc_mb_mask, *t0); STORE_RESULT(&p_out[5] - 1, 0x00F0, loc_mb_mask, *t1); STORE_RESULT(&p_out[6] - 1, 0x00F0, loc_mb_mask, *t2); STORE_RESULT(&p_out[7] - 1, 0x00F0, loc_mb_mask, *t3); // L8 - Lb STORE_RESULT(&p_out[8] - 2, 0x0F00, loc_mb_mask, *t0); STORE_RESULT(&p_out[9] - 2, 0x0F00, loc_mb_mask, *t1); STORE_RESULT(&p_out[10] - 2, 0x0F00, loc_mb_mask, *t2); STORE_RESULT(&p_out[11] - 2, 0x0F00, loc_mb_mask, *t3); // Lc - Lf STORE_RESULT(&p_out[12] - 3, 0xF000, loc_mb_mask, *t0); STORE_RESULT(&p_out[13] - 3, 0xF000, loc_mb_mask, *t1); STORE_RESULT(&p_out[14] - 3, 0xF000, loc_mb_mask, *t2); STORE_RESULT(&p_out[15] - 3, 0xF000, loc_mb_mask, *t3); } __MBX_INLINE void TRANSPOSE_4x16_I32_EPI8(__m512i t0, __m512i t1, __m512i t2, __m512i t3, int8u* p_out[16], int* p_loc_len, __mmask16 mb_mask) { #define STORE_RESULT_EPI8(OUT, store_mask, loc_mb_mask, Ti) \ _mm512_mask_storeu_epi8(OUT, store_mask * (0x1&loc_mb_mask), Ti); \ loc_mb_mask >>= 1; __mmask16 loc_mb_mask = mb_mask; /* Mask for data loading */ __mmask64 stream_mask; __m512i z0 = _mm512_unpacklo_epi32(t0, t1); __m512i z1 = _mm512_unpackhi_epi32(t0, t1); __m512i z2 = _mm512_unpacklo_epi32(t2, t3); __m512i z3 = _mm512_unpackhi_epi32(t2, t3); /* Get the right endianness */ t0 = ENDIANNESS_16x32(_mm512_unpacklo_epi64(z0, z2)); t1 = ENDIANNESS_16x32(_mm512_unpackhi_epi64(z0, z2)); t2 = ENDIANNESS_16x32(_mm512_unpacklo_epi64(z1, z3)); t3 = ENDIANNESS_16x32(_mm512_unpackhi_epi64(z1, z3)); // L0 - L3 UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8(p_out[0], stream_mask, loc_mb_mask, t0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8(p_out[1], stream_mask, loc_mb_mask, t1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8(p_out[2], stream_mask, loc_mb_mask, t2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8(p_out[3], stream_mask, loc_mb_mask, t3); // L4 - L7 UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[4] - 1, stream_mask << 16, loc_mb_mask, t0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[5] - 1, stream_mask << 16, loc_mb_mask, t1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[6] - 1, stream_mask << 16, loc_mb_mask, t2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[7] - 1, stream_mask << 16, loc_mb_mask, t3); // L8 - Lb UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[8] - 2, stream_mask << 32, loc_mb_mask, t0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[9] - 2, stream_mask << 32, loc_mb_mask, t1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[10] - 2, stream_mask << 32, loc_mb_mask, t2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[11] - 2, stream_mask << 32, loc_mb_mask, t3); // Lc - Lf UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[12] - 3, stream_mask << 48, loc_mb_mask, t0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[13] - 3, stream_mask << 48, loc_mb_mask, t1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[14] - 3, stream_mask << 48, loc_mb_mask, t2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) STORE_RESULT_EPI8((__m128i*)p_out[15] - 3, stream_mask << 48, loc_mb_mask, t3); } __MBX_INLINE void TRANSPOSE_AND_XOR_4x16_I32_EPI32(__m512i* t0, __m512i* t1, __m512i* t2, __m512i* t3, int8u* p_out[16], const int8u* p_iv[16], __mmask16 mb_mask) { #define XOR_AND_STORE_RESULT(OUT, store_mask, loc_mb_mask, Ti, IV, TMP) \ TMP = _mm512_maskz_loadu_epi32(store_mask * (0x1&loc_mb_mask), IV); \ _mm512_mask_storeu_epi32(OUT, store_mask * (0x1&loc_mb_mask), _mm512_xor_epi32(Ti, TMP)); \ loc_mb_mask >>= 1; __m512i z0 = _mm512_setzero_si512(); __m512i z1 = _mm512_setzero_si512(); __m512i z2 = _mm512_setzero_si512(); __m512i z3 = _mm512_setzero_si512(); __mmask16 loc_mb_mask = mb_mask; z0 = _mm512_unpacklo_epi32(*t0, *t1); z1 = _mm512_unpackhi_epi32(*t0, *t1); z2 = _mm512_unpacklo_epi32(*t2, *t3); z3 = _mm512_unpackhi_epi32(*t2, *t3); /* Get the right endianness and do (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) */ *t0 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z0, z2)); *t1 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z0, z2)); *t2 = CHANGE_ORDER_BLOCKS(_mm512_unpacklo_epi64(z1, z3)); *t3 = CHANGE_ORDER_BLOCKS(_mm512_unpackhi_epi64(z1, z3)); // L0 - L3 XOR_AND_STORE_RESULT(p_out[0], 0x000F, loc_mb_mask, *t0, p_iv[0], z0); XOR_AND_STORE_RESULT(p_out[1], 0x000F, loc_mb_mask, *t1, p_iv[1], z1); XOR_AND_STORE_RESULT(p_out[2], 0x000F, loc_mb_mask, *t2, p_iv[2], z2); XOR_AND_STORE_RESULT(p_out[3], 0x000F, loc_mb_mask, *t3, p_iv[3], z3); // L4 - L7 XOR_AND_STORE_RESULT((__m128i*)p_out[4] - 1, 0x00F0, loc_mb_mask, *t0, (__m128i*)p_iv[4] - 1, z0); XOR_AND_STORE_RESULT((__m128i*)p_out[5] - 1, 0x00F0, loc_mb_mask, *t1, (__m128i*)p_iv[5] - 1, z1); XOR_AND_STORE_RESULT((__m128i*)p_out[6] - 1, 0x00F0, loc_mb_mask, *t2, (__m128i*)p_iv[6] - 1, z2); XOR_AND_STORE_RESULT((__m128i*)p_out[7] - 1, 0x00F0, loc_mb_mask, *t3, (__m128i*)p_iv[7] - 1, z3); // L8 - Lb XOR_AND_STORE_RESULT((__m128i*)p_out[8] - 2, 0x0F00, loc_mb_mask, *t0, (__m128i*)p_iv[8] - 2, z0); XOR_AND_STORE_RESULT((__m128i*)p_out[9] - 2, 0x0F00, loc_mb_mask, *t1, (__m128i*)p_iv[9] - 2, z1); XOR_AND_STORE_RESULT((__m128i*)p_out[10] - 2, 0x0F00, loc_mb_mask, *t2, (__m128i*)p_iv[10] - 2, z2); XOR_AND_STORE_RESULT((__m128i*)p_out[11] - 2, 0x0F00, loc_mb_mask, *t3, (__m128i*)p_iv[11] - 2, z3); // Lc - Lf XOR_AND_STORE_RESULT((__m128i*)p_out[12] - 3, 0xF000, loc_mb_mask, *t0, (__m128i*)p_iv[12] - 3, z0); XOR_AND_STORE_RESULT((__m128i*)p_out[13] - 3, 0xF000, loc_mb_mask, *t1, (__m128i*)p_iv[13] - 3, z1); XOR_AND_STORE_RESULT((__m128i*)p_out[14] - 3, 0xF000, loc_mb_mask, *t2, (__m128i*)p_iv[14] - 3, z2); XOR_AND_STORE_RESULT((__m128i*)p_out[15] - 3, 0xF000, loc_mb_mask, *t3, (__m128i*)p_iv[15] - 3, z3); } __MBX_INLINE void TRANSPOSE_AND_XOR_4x16_I32_EPI8(__m512i t0, __m512i t1, __m512i t2, __m512i t3, int8u* p_out[16], const int8u* p_iv[16], int* p_loc_len, __mmask16 mb_mask) { #define XOR_AND_STORE_RESULT_EPI8(OUT, store_mask, loc_mb_mask, Ti, IV, TMP) \ TMP = _mm512_maskz_loadu_epi8(store_mask * (0x1&loc_mb_mask), IV); \ _mm512_mask_storeu_epi8(OUT, store_mask * (0x1&loc_mb_mask), _mm512_xor_epi32(Ti, TMP)); \ loc_mb_mask >>= 1; __m512i z0 = _mm512_setzero_si512(); __m512i z1 = _mm512_setzero_si512(); __m512i z2 = _mm512_setzero_si512(); __m512i z3 = _mm512_setzero_si512(); __mmask16 loc_mb_mask = mb_mask; /* Mask for data loading */ __mmask64 stream_mask; z0 = _mm512_unpacklo_epi32(t0, t1); z1 = _mm512_unpackhi_epi32(t0, t1); z2 = _mm512_unpacklo_epi32(t2, t3); z3 = _mm512_unpackhi_epi32(t2, t3); /* Get the right endianness */ t0 = ENDIANNESS_16x32(_mm512_unpacklo_epi64(z0, z2)); t1 = ENDIANNESS_16x32(_mm512_unpackhi_epi64(z0, z2)); t2 = ENDIANNESS_16x32(_mm512_unpacklo_epi64(z1, z3)); t3 = ENDIANNESS_16x32(_mm512_unpackhi_epi64(z1, z3)); // L0 - L3 UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8(p_out[0], stream_mask, loc_mb_mask, t0, p_iv[0], z0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8(p_out[1], stream_mask, loc_mb_mask, t1, p_iv[1], z1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8(p_out[2], stream_mask, loc_mb_mask, t2, p_iv[2], z2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8(p_out[3], stream_mask, loc_mb_mask, t3, p_iv[3], z3); // L4 - L7 UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[4] - 1, stream_mask << 16, loc_mb_mask, t0, (__m128i*)p_iv[4] - 1, z0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[5] - 1, stream_mask << 16, loc_mb_mask, t1, (__m128i*)p_iv[5] - 1, z1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[6] - 1, stream_mask << 16, loc_mb_mask, t2, (__m128i*)p_iv[6] - 1, z2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[7] - 1, stream_mask << 16, loc_mb_mask, t3, (__m128i*)p_iv[7] - 1, z3); // L8 - Lb UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[8] - 2, stream_mask << 32, loc_mb_mask, t0, (__m128i*)p_iv[8] - 2, z0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[9] - 2, stream_mask << 32, loc_mb_mask, t1, (__m128i*)p_iv[9] - 2, z1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[10] - 2, stream_mask << 32, loc_mb_mask, t2, (__m128i*)p_iv[10] - 2, z2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[11] - 2, stream_mask << 32, loc_mb_mask, t3, (__m128i*)p_iv[11] - 2, z3); // Lc - Lf UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[12] - 3, stream_mask << 48, loc_mb_mask, t0, (__m128i*)p_iv[12] - 3, z0); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[13] - 3, stream_mask << 48, loc_mb_mask, t1, (__m128i*)p_iv[13] - 3, z1); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[14] - 3, stream_mask << 48, loc_mb_mask, t2, (__m128i*)p_iv[14] - 3, z2); UPDATE_STREAM_MASK_16(stream_mask, p_loc_len) XOR_AND_STORE_RESULT_EPI8((__m128i*)p_out[15] - 3, stream_mask << 48, loc_mb_mask, t3, (__m128i*)p_iv[15] - 3, z3); } #endif /* #if (_MBX>=_MBX_K1) */ #endif /* _SM4_GFNI_MB_H */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/000077500000000000000000000000001470420105600240165ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/CMakeLists.txt000066400000000000000000000277451470420105600265750ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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 defaults for every supported compiler set(DEFAULT_GNU_COMPILER_VER 8.2.0) set(DEFAULT_CLANG_COMPILER_VER 9.0.0) set(DEFAULT_Intel_COMPILER_VER 19.0.0) # Check min compiler version if(("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_GNU_COMPILER_VER)) message(FATAL_ERROR "GNU C Compiler version must be 8.2 or higher") endif() if(("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_CLANG_COMPILER_VER)) message(FATAL_ERROR "Clang C Compiler version must be 9.0 or higher") endif() if(("${CMAKE_C_COMPILER_ID}" STREQUAL "Intel") AND (CMAKE_C_COMPILER_VERSION VERSION_LESS DEFAULT_Intel_COMPILER_VER)) message(FATAL_ERROR "Compiler version must be 19.0 or higher") endif() include("${CRYPTO_MB_SOURCES_DIR}/cmake/common.cmake") include(${COMPILER_OPTIONS_FILE}) # Get ${CMAKE_C_FLAGS}, ${CMAKE_CXX_FLAGS} and ${AVX512_CFLAGS} # Sources file(GLOB RSA_SOURCES "${CRYPTO_MB_SOURCES_DIR}/rsa/*.c" "${CRYPTO_MB_SOURCES_DIR}/rsa/internal_avx2/*.c" "${CRYPTO_MB_SOURCES_DIR}/rsa/internal_avx512/*.c") file(GLOB COMMON_SOURCES "${CRYPTO_MB_SOURCES_DIR}/common/*.c") file(GLOB X25519_SOURCES "${CRYPTO_MB_SOURCES_DIR}/x25519/*.c" "${CRYPTO_MB_SOURCES_DIR}/x25519/internal_avx512/*.c") file(GLOB ECNIST_SOURCES "${CRYPTO_MB_SOURCES_DIR}/ecnist/*.c" "${CRYPTO_MB_SOURCES_DIR}/ecnist/internal_avx512/*.c") file(GLOB SM2_SOURCES "${CRYPTO_MB_SOURCES_DIR}/sm2/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm2/internal_avx512/*.c") file(GLOB SM3_SOURCES "${CRYPTO_MB_SOURCES_DIR}/sm3/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm3/internal_avx512/*.c") # SM4 Sources file(GLOB SM4_SOURCES "${CRYPTO_MB_SOURCES_DIR}/sm4/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm4/internal_avx512/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm4/gcm/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm4/gcm/internal_avx512/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm4/ccm/*.c" "${CRYPTO_MB_SOURCES_DIR}/sm4/ccm/internal_avx512/*.c") file(GLOB ED25519_SOURCES "${CRYPTO_MB_SOURCES_DIR}/ed25519/*.c" "${CRYPTO_MB_SOURCES_DIR}/ed25519/internal_avx512/*.c") file(GLOB EXP_SOURCES "${CRYPTO_MB_SOURCES_DIR}/exp/*.c") file(GLOB FIPS_CERT_SOURCES "${CRYPTO_MB_SOURCES_DIR}/fips_cert/*.c") # Headers file(GLOB MB_PRIVATE_HEADERS "${CRYPTO_MB_INCLUDE_DIR}/internal/common/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/ecnist/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/rsa/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/sm2/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/sm3/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/sm4/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/ed25519/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/exp/*.h" "${CRYPTO_MB_INCLUDE_DIR}/internal/fips_cert/*.h") file(GLOB OPENSSL_HEADERS "${OPENSSL_INCLUDE_DIR}/openssl/*.h") set(CRYPTO_MB_SOURCES_ORIGINAL ${RSA_SOURCES} ${COMMON_SOURCES} ${X25519_SOURCES} ${ECNIST_SOURCES} ${SM2_SOURCES} ${SM3_SOURCES} ${SM4_SOURCES} ${ED25519_SOURCES} ${EXP_SOURCES}) set(CRYPTO_MB_HEADERS ${MB_PUBLIC_HEADERS} ${MB_PRIVATE_HEADERS} ${OPENSSL_HEADERS}) set(WIN_RESOURCE_FILE ${CRYPTO_MB_SOURCES_DIR}/common/crypto_mb_ver.rc) set(CPU_FEATURES_FILE ${CRYPTO_MB_SOURCES_DIR}/common/cpu_features.c) set(MBX_VERSION_FILE ${CRYPTO_MB_SOURCES_DIR}/common/ifma_version.c) # Disable compiler optimizations for this file, as compiler adds some ISA specific code # which is unwanted for functions that are aimed to work on any CPU list(REMOVE_ITEM CRYPTO_MB_SOURCES_ORIGINAL ${CPU_FEATURES_FILE}) if("${OS_STRING}" STREQUAL "windows") set_source_files_properties(${CPU_FEATURES_FILE} PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_SECURITY} /Od") else() set_source_files_properties(${CPU_FEATURES_FILE} PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_SECURITY} -O0") endif() if(BN_OPENSSL_PATCH) # Off by default list(APPEND AVX512_LIBRARY_DEFINES "BN_OPENSSL_PATCH") endif() set(CRYPTO_MB_API ${MB_PUBLIC_HEADERS}) list(REMOVE_ITEM CRYPTO_MB_API ${CRYPTO_MB_INCLUDE_DIR}/crypto_mb/cpu_features.h ${CRYPTO_MB_INCLUDE_DIR}/crypto_mb/defs.h ${CRYPTO_MB_INCLUDE_DIR}/crypto_mb/status.h) # Generate single-CPU headers set(MBX_ONE_CPU_FOLDER ${INTERNAL_INCLUDE_DIR}/single_cpu/crypto_mb) set(MBX_ONE_CPU_GENERATOR ${MBX_DIR}/gen_cpu_spc_header/gen_cpu_spc_1cpu_header_crypto_mb.py) set(MBX_INTERNAL_GENERATOR ${MBX_DIR}/gen_cpu_spc_header/gen_cpu_spc_header_crypto_mb.py) foreach( header ${CRYPTO_MB_API}) execute_process(COMMAND ${Python_EXECUTABLE} ${MBX_ONE_CPU_GENERATOR} ${header} ${MBX_ONE_CPU_FOLDER}) execute_process(COMMAND ${Python_EXECUTABLE} ${MBX_INTERNAL_GENERATOR} ${header} ${INTERNAL_INCLUDE_DIR}) endforeach() file(GLOB MBX_ONE_CPU_HEADERS "${MBX_ONE_CPU_FOLDER}/*.h") file(GLOB MBX_CPU_SPC_HEADERS "${INTERNAL_INCLUDE_DIR}/*.h") # Copy headers to the output directory foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES}) string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG ) file(COPY ${MBX_ONE_CPU_FOLDER} DESTINATION "${CMAKE_OUTPUT_DIR}/${OUTPUTCONFIG}/include/single_cpu") endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) if(MBX_CC_AVXIFMA_SUPPORT) set(MBX_AVXIFMA_SUPPORT_DEFINE "_MBX_AVX_IFMA_SUPPORTED") endif() foreach(opt ${MBX_PLATFORM_LIST}) # Populate C source files in to corresponding folders per library 'letter' set(mbx_c_cache_dir "${CMAKE_BINARY_DIR}/c_sources/crypto_mb/${opt}/c_${ARCH}") file(MAKE_DIRECTORY ${mbx_c_cache_dir}) # Add a prefix to the source files, so that corresponding object files in the merged library are unique named foreach (file ${CRYPTO_MB_SOURCES_ORIGINAL}) get_filename_component(basename ${file} NAME) configure_file(${file} ${mbx_c_cache_dir}/${opt}_${basename} COPYONLY) endforeach() file (GLOB MBX_C_SOURCES_${opt} ${mbx_c_cache_dir}/*.c ) set(OPT_FLAGS_${opt} ${${opt}_opt}) # Put a specific define into the library if Intel® AVX-IFMA instructions are supported by the compiler set(MBX_LIBRARY_DEFINES "${MBX_AVXIFMA_SUPPORT_DEFINE}" "${${opt}_def}") set_source_files_properties(${MBX_C_SOURCES_${opt}} PROPERTIES COMPILE_DEFINITIONS "${MBX_LIBRARY_DEFINES}" COMPILE_FLAGS "${OPT_FLAGS_${opt}} ${CMAKE_C_FLAGS_SECURITY}") endforeach() # build object libraries set(MBX_TARGET_NAME ${MB_STATIC_LIB_TARGET}) foreach(opt ${MBX_PLATFORM_LIST}) set(MBX_ST_ITER ${MBX_TARGET_NAME}_${opt}) add_library(${MBX_ST_ITER} OBJECT ${CRYPTO_MB_HEADERS} ${MBX_C_SOURCES_${opt}}) set(MBX_MERGED_DEPENDENCY ${MBX_MERGED_DEPENDENCY} $) list(APPEND MBX_LIB_STATIC ${MBX_ST_ITER}) endforeach() set(DISPATCHER ${CMAKE_BINARY_DIR}/dispatcher/crypto_mb) file(MAKE_DIRECTORY ${DISPATCHER}) set(DISPATCHER_GENERATOR ${CRYPTO_MB_DISPATCHER_DIR}/gen_disp_crypto_mb.py) foreach(incl ${CRYPTO_MB_API}) execute_process(COMMAND ${Python_EXECUTABLE} ${DISPATCHER_GENERATOR} -i ${incl} -o ${DISPATCHER} -l "${MBX_PLATFORM_LIST}" -c ${CMAKE_C_COMPILER_ID} RESULT_VARIABLE result ) endforeach() file(GLOB DISPATCHER_HEADERS ${CMAKE_BINARY_DIR}/dispatcher/crypto_mb/*.h ) file(GLOB DISPATCHER_C_SOURCES ${CMAKE_BINARY_DIR}/dispatcher/crypto_mb/*.c ) if(MBX_FIPS_MODE) set_source_files_properties(${FIPS_CERT_SOURCES} PROPERTIES COMPILE_DEFINITIONS "MBX_FIPS_MODE") set(DISPATCHER_C_SOURCES ${DISPATCHER_C_SOURCES} ${FIPS_CERT_SOURCES}) endif() set(MB_LIB_TARGET ${MB_DYN_LIB_TARGET}) set_source_files_properties(${DISPATCHER_C_SOURCES} PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_SECURITY}") # Static library if(WIN32) add_library(${MB_STATIC_LIB_TARGET} STATIC ${DISPATCHER_HEADERS} ${DISPATCHER_C_SOURCES} ${MBX_MERGED_DEPENDENCY} ${CPU_FEATURES_FILE} ${WIN_RESOURCE_FILE}) else() add_library(${MB_STATIC_LIB_TARGET} STATIC ${DISPATCHER_HEADERS} ${DISPATCHER_C_SOURCES} ${MBX_MERGED_DEPENDENCY} ${CPU_FEATURES_FILE}) endif() set_target_properties(${MB_STATIC_LIB_TARGET} PROPERTIES C_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON PUBLIC_HEADER "${MB_PUBLIC_HEADERS}" PRIVATE_HEADER "${MBX_ONE_CPU_HEADERS}") if(WIN32) set_target_properties(${MB_STATIC_LIB_TARGET} PROPERTIES OUTPUT_NAME "${MB_LIB_TARGET}mt") else() set_target_properties(${MB_STATIC_LIB_TARGET} PROPERTIES OUTPUT_NAME "${MB_LIB_TARGET}") endif() target_link_libraries(${MB_STATIC_LIB_TARGET} OpenSSL::Crypto) # Static lib installation if(MB_STANDALONE) install(TARGETS ${MB_STATIC_LIB_TARGET} ARCHIVE DESTINATION "lib" PUBLIC_HEADER DESTINATION "include/crypto_mb" PRIVATE_HEADER DESTINATION "tools/staticlib/crypto_mb") else() install(TARGETS ${MB_STATIC_LIB_TARGET} ARCHIVE DESTINATION "lib/intel64" PUBLIC_HEADER DESTINATION "include/crypto_mb" PRIVATE_HEADER DESTINATION "tools/intel64/staticlib/crypto_mb") endif() # Create shared library if(DYNAMIC_LIB OR MB_STANDALONE) add_library(${MB_DYN_LIB_TARGET} SHARED common/emptyfile.c common/crypto_mb_ver.rc) # emptyfile.c to suppress the cmake warning set_target_properties(${MB_DYN_LIB_TARGET} PROPERTIES C_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON LINK_FLAGS "${LINK_FLAGS_DYNAMIC} ${LINK_FLAG_SECURITY}" PUBLIC_HEADER "${MB_PUBLIC_HEADERS}" PRIVATE_HEADER "${MBX_ONE_CPU_HEADERS}" ) if(UNIX) set_target_properties(${MB_DYN_LIB_TARGET} PROPERTIES VERSION ${MBX_INTERFACE_VERSION} SOVERSION ${MBX_INTERFACE_VERSION_MAJOR}) endif() target_link_libraries(${MB_DYN_LIB_TARGET} ${MB_STATIC_LIB_TARGET}) # link to the static merged endif(DYNAMIC_LIB OR MB_STANDALONE) # Installation of the shared library if (MB_STANDALONE) # standalone crypto_mb's cmake run install(TARGETS ${MB_DYN_LIB_TARGET} LIBRARY DESTINATION "lib" RUNTIME DESTINATION "lib" PUBLIC_HEADER DESTINATION "include/crypto_mb" PRIVATE_HEADER DESTINATION "tools/staticlib/crypto_mb") elseif (DYNAMIC_LIB) # build from ippcp's cmake install(TARGETS ${MB_DYN_LIB_TARGET} LIBRARY DESTINATION "lib/intel64" RUNTIME DESTINATION "lib/intel64" PUBLIC_HEADER DESTINATION "include/crypto_mb" PRIVATE_HEADER DESTINATION "tools/intel64/staticlib/crypto_mb") endif() cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/000077500000000000000000000000001470420105600250765ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/common.cmake000066400000000000000000000027171470420105600273770ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= if(UNIX) if(APPLE) set(OS_STRING "macosx") set(OS_DEFAULT_COMPILER Intel) else() set(OS_STRING "linux") set(OS_DEFAULT_COMPILER GNU) endif() else() set(OS_STRING "windows") set(OS_DEFAULT_COMPILER Intel) endif() # Find appropriate compiler options file set(COMPILER_OPTIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/${OS_STRING}") if(EXISTS "${COMPILER_OPTIONS_DIR}/${CMAKE_C_COMPILER_ID}.cmake") set(COMPILER_OPTIONS_FILE "${COMPILER_OPTIONS_DIR}/${CMAKE_C_COMPILER_ID}.cmake") else() set(COMPILER_OPTIONS_FILE "${COMPILER_OPTIONS_DIR}/${OS_DEFAULT_COMPILER}.cmake") message(WARNING "Unknown compiler, using options from the OS default one: ${OS_DEFAULT_COMPILER}") endif()cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/crypto_mb-utils.cmake000066400000000000000000000041721470420105600312400ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= macro(mbx_getlibversion VERSION_FILE) unset(MBX_VER_MAJOR) unset(MBX_VER_MINOR) unset(MBX_VER_PATCH) unset(MBX_VER_FULL) file(STRINGS "${VERSION_FILE}" FILE_CONTENTS) foreach(LINE ${FILE_CONTENTS}) if ("${LINE}" MATCHES "#define +MBX_VER_MAJOR") string(REGEX REPLACE "^#define +MBX_VER_MAJOR +\([0-9]+\).*$" "\\1" MBX_VER_MAJOR ${LINE}) endif() if ("${LINE}" MATCHES "#define +MBX_VER_MINOR") string(REGEX REPLACE "^#define +MBX_VER_MINOR +\([0-9]+\).*$" "\\1" MBX_VER_MINOR ${LINE}) endif() if ("${LINE}" MATCHES "#define +MBX_VER_PATCH") string(REGEX REPLACE "^#define +MBX_VER_PATCH +\([0-9]+\).*$" "\\1" MBX_VER_PATCH ${LINE}) endif() if ("${LINE}" MATCHES "#define MBX_INTERFACE_VERSION_MAJOR") string(REGEX REPLACE "^#define +MBX_INTERFACE_VERSION_MAJOR +\([0-9]+\).*$" "\\1" MBX_INTERFACE_VERSION_MAJOR ${LINE}) endif() if ("${LINE}" MATCHES "#define MBX_INTERFACE_VERSION_MINOR") string(REGEX REPLACE "^#define +MBX_INTERFACE_VERSION_MINOR +\([0-9]+\).*$" "\\1" MBX_INTERFACE_VERSION_MINOR ${LINE}) endif() endforeach() set(MBX_VER_FULL "${MBX_VER_MAJOR}.${MBX_VER_MINOR}.${MBX_VER_PATCH}") set(MBX_INTERFACE_VERSION "${MBX_INTERFACE_VERSION_MAJOR}.${MBX_INTERFACE_VERSION_MINOR}") unset(FILE_CONTENTS) endmacro(mbx_getlibversion) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_export/000077500000000000000000000000001470420105600272525ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_export/crypto_mb.defs000066400000000000000000000056241470420105600321220ustar00rootroot00000000000000EXPORTS mbx_getversion mbx_get_cpu_features mbx_set_cpu_features mbx_is_crypto_mb_applicable mbx_get_algo_info mbx_rsa_public_mb8 mbx_rsa_private_mb8 mbx_rsa_private_crt_mb8 mbx_rsa_public_ssl_mb8 mbx_rsa_private_ssl_mb8 mbx_rsa_private_crt_ssl_mb8 mbx_x25519_public_key_mb8 mbx_x25519_mb8 mbx_ed25519_public_key_mb8 mbx_ed25519_sign_mb8 mbx_ed25519_verify_mb8 mbx_exp_BufferSize mbx_exp1024_mb8 mbx_exp2048_mb8 mbx_exp3072_mb8 mbx_exp4096_mb8 mbx_exp_mb8 mbx_nistp256_ecdh_mb8 mbx_nistp256_ecdsa_sign_setup_mb8 mbx_nistp256_ecdsa_sign_complete_mb8 mbx_nistp256_ecdsa_sign_mb8 mbx_nistp256_ecdsa_verify_mb8 mbx_nistp256_ecpublic_key_mb8 mbx_nistp256_ecdh_ssl_mb8 mbx_nistp256_ecdsa_sign_setup_ssl_mb8 mbx_nistp256_ecdsa_sign_complete_ssl_mb8 mbx_nistp256_ecdsa_sign_ssl_mb8 mbx_nistp256_ecdsa_verify_ssl_mb8 mbx_nistp256_ecpublic_key_ssl_mb8 mbx_nistp384_ecdh_mb8 mbx_nistp384_ecdsa_sign_setup_mb8 mbx_nistp384_ecdsa_sign_complete_mb8 mbx_nistp384_ecdsa_sign_mb8 mbx_nistp384_ecdsa_verify_mb8 mbx_nistp384_ecpublic_key_mb8 mbx_nistp384_ecdh_ssl_mb8 mbx_nistp384_ecdsa_sign_setup_ssl_mb8 mbx_nistp384_ecdsa_sign_complete_ssl_mb8 mbx_nistp384_ecdsa_sign_ssl_mb8 mbx_nistp384_ecdsa_verify_ssl_mb8 mbx_nistp384_ecpublic_key_ssl_mb8 mbx_nistp521_ecdh_mb8 mbx_nistp521_ecdsa_sign_setup_mb8 mbx_nistp521_ecdsa_sign_complete_mb8 mbx_nistp521_ecdsa_sign_mb8 mbx_nistp521_ecdsa_verify_mb8 mbx_nistp521_ecpublic_key_mb8 mbx_nistp521_ecdh_ssl_mb8 mbx_nistp521_ecdsa_sign_setup_ssl_mb8 mbx_nistp521_ecdsa_sign_complete_ssl_mb8 mbx_nistp521_ecdsa_sign_ssl_mb8 mbx_nistp521_ecdsa_verify_ssl_mb8 mbx_nistp521_ecpublic_key_ssl_mb8 mbx_sm2_ecdh_mb8 mbx_sm2_ecdsa_sign_mb8 mbx_sm2_ecdsa_verify_mb8 mbx_sm2_ecpublic_key_mb8 mbx_sm2_ecdh_ssl_mb8 mbx_sm2_ecdsa_sign_ssl_mb8 mbx_sm2_ecdsa_verify_ssl_mb8 mbx_sm2_ecpublic_key_ssl_mb8 mbx_RSA1K_pub65537_Method mbx_RSA2K_pub65537_Method mbx_RSA3K_pub65537_Method mbx_RSA4K_pub65537_Method mbx_RSA_pub65537_Method mbx_RSA1K_private_Method mbx_RSA2K_private_Method mbx_RSA3K_private_Method mbx_RSA4K_private_Method mbx_RSA_private_Method mbx_RSA1K_private_crt_Method mbx_RSA2K_private_crt_Method mbx_RSA3K_private_crt_Method mbx_RSA4K_private_crt_Method mbx_RSA_private_crt_Method mbx_RSA_Method_BufSize mbx_sm3_init_mb16 mbx_sm3_update_mb16 mbx_sm3_final_mb16 mbx_sm3_msg_digest_mb16 mbx_sm4_set_key_mb16 mbx_sm4_encrypt_ecb_mb16 mbx_sm4_decrypt_ecb_mb16 mbx_sm4_encrypt_cbc_mb16 mbx_sm4_decrypt_cbc_mb16 mbx_sm4_encrypt_ctr128_mb16 mbx_sm4_decrypt_ctr128_mb16 mbx_sm4_encrypt_ofb_mb16 mbx_sm4_decrypt_ofb_mb16 mbx_sm4_encrypt_cfb128_mb16 mbx_sm4_decrypt_cfb128_mb16 mbx_sm4_gcm_init_mb16 mbx_sm4_gcm_update_iv_mb16 mbx_sm4_gcm_update_aad_mb16 mbx_sm4_gcm_encrypt_mb16 mbx_sm4_gcm_decrypt_mb16 mbx_sm4_gcm_get_tag_mb16 mbx_sm4_ccm_init_mb16 mbx_sm4_ccm_update_aad_mb16 mbx_sm4_ccm_encrypt_mb16 mbx_sm4_ccm_decrypt_mb16 mbx_sm4_ccm_get_tag_mb16 mbx_sm4_xts_set_keys_mb16 mbx_sm4_xts_encrypt_mb16 mbx_sm4_xts_decrypt_mb16 crypto_mb.linux.lib-export000066400000000000000000000075621470420105600343500ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_exportEXTERN (mbx_getversion) EXTERN (mbx_get_cpu_features) EXTERN (mbx_set_cpu_features) EXTERN (mbx_is_crypto_mb_applicable) EXTERN (mbx_get_algo_info) EXTERN (mbx_rsa_public_mb8) EXTERN (mbx_rsa_private_mb8) EXTERN (mbx_rsa_private_crt_mb8) EXTERN (mbx_rsa_public_ssl_mb8) EXTERN (mbx_rsa_private_ssl_mb8) EXTERN (mbx_rsa_private_crt_ssl_mb8) EXTERN (mbx_x25519_public_key_mb8) EXTERN (mbx_x25519_mb8) EXTERN (mbx_ed25519_public_key_mb8) EXTERN (mbx_ed25519_sign_mb8) EXTERN (mbx_ed25519_verify_mb8) EXTERN (mbx_exp_BufferSize) EXTERN (mbx_exp1024_mb8) EXTERN (mbx_exp2048_mb8) EXTERN (mbx_exp3072_mb8) EXTERN (mbx_exp4096_mb8) EXTERN (mbx_exp_mb8) EXTERN (mbx_nistp256_ecdh_mb8) EXTERN (mbx_nistp256_ecdsa_sign_setup_mb8) EXTERN (mbx_nistp256_ecdsa_sign_complete_mb8) EXTERN (mbx_nistp256_ecdsa_sign_mb8) EXTERN (mbx_nistp256_ecdsa_verify_mb8) EXTERN (mbx_nistp256_ecpublic_key_mb8) EXTERN (mbx_nistp256_ecdh_ssl_mb8) EXTERN (mbx_nistp256_ecdsa_sign_setup_ssl_mb8) EXTERN (mbx_nistp256_ecdsa_sign_complete_ssl_mb8) EXTERN (mbx_nistp256_ecdsa_sign_ssl_mb8) EXTERN (mbx_nistp256_ecdsa_verify_ssl_mb8) EXTERN (mbx_nistp256_ecpublic_key_ssl_mb8) EXTERN (mbx_nistp384_ecdh_mb8) EXTERN (mbx_nistp384_ecdsa_sign_setup_mb8) EXTERN (mbx_nistp384_ecdsa_sign_complete_mb8) EXTERN (mbx_nistp384_ecdsa_sign_mb8) EXTERN (mbx_nistp384_ecdsa_verify_mb8) EXTERN (mbx_nistp384_ecpublic_key_mb8) EXTERN (mbx_nistp384_ecdh_ssl_mb8) EXTERN (mbx_nistp384_ecdsa_sign_setup_ssl_mb8) EXTERN (mbx_nistp384_ecdsa_sign_complete_ssl_mb8) EXTERN (mbx_nistp384_ecdsa_sign_ssl_mb8) EXTERN (mbx_nistp384_ecdsa_verify_ssl_mb8) EXTERN (mbx_nistp384_ecpublic_key_ssl_mb8) EXTERN (mbx_nistp521_ecdh_mb8) EXTERN (mbx_nistp521_ecdsa_sign_setup_mb8) EXTERN (mbx_nistp521_ecdsa_sign_complete_mb8) EXTERN (mbx_nistp521_ecdsa_sign_mb8) EXTERN (mbx_nistp521_ecdsa_verify_mb8) EXTERN (mbx_nistp521_ecpublic_key_mb8) EXTERN (mbx_nistp521_ecdh_ssl_mb8) EXTERN (mbx_nistp521_ecdsa_sign_setup_ssl_mb8) EXTERN (mbx_nistp521_ecdsa_sign_complete_ssl_mb8) EXTERN (mbx_nistp521_ecdsa_sign_ssl_mb8) EXTERN (mbx_nistp521_ecdsa_verify_ssl_mb8) EXTERN (mbx_nistp521_ecpublic_key_ssl_mb8) EXTERN (mbx_sm2_ecdh_mb8) EXTERN (mbx_sm2_ecdsa_sign_mb8) EXTERN (mbx_sm2_ecdsa_verify_mb8) EXTERN (mbx_sm2_ecpublic_key_mb8) EXTERN (mbx_sm2_ecdh_ssl_mb8) EXTERN (mbx_sm2_ecdsa_sign_ssl_mb8) EXTERN (mbx_sm2_ecdsa_verify_ssl_mb8) EXTERN (mbx_sm2_ecpublic_key_ssl_mb8) EXTERN (mbx_RSA1K_pub65537_Method) EXTERN (mbx_RSA2K_pub65537_Method) EXTERN (mbx_RSA3K_pub65537_Method) EXTERN (mbx_RSA4K_pub65537_Method) EXTERN (mbx_RSA_pub65537_Method) EXTERN (mbx_RSA1K_private_Method) EXTERN (mbx_RSA2K_private_Method) EXTERN (mbx_RSA3K_private_Method) EXTERN (mbx_RSA4K_private_Method) EXTERN (mbx_RSA_private_Method) EXTERN (mbx_RSA1K_private_crt_Method) EXTERN (mbx_RSA2K_private_crt_Method) EXTERN (mbx_RSA3K_private_crt_Method) EXTERN (mbx_RSA4K_private_crt_Method) EXTERN (mbx_RSA_private_crt_Method) EXTERN (mbx_RSA_Method_BufSize) EXTERN (mbx_sm3_init_mb16) EXTERN (mbx_sm3_update_mb16) EXTERN (mbx_sm3_final_mb16) EXTERN (mbx_sm3_msg_digest_mb16) EXTERN (mbx_sm4_set_key_mb16) EXTERN (mbx_sm4_encrypt_ecb_mb16) EXTERN (mbx_sm4_decrypt_ecb_mb16) EXTERN (mbx_sm4_encrypt_cbc_mb16) EXTERN (mbx_sm4_decrypt_cbc_mb16) EXTERN (mbx_sm4_encrypt_ctr128_mb16) EXTERN (mbx_sm4_decrypt_ctr128_mb16) EXTERN (mbx_sm4_encrypt_ofb_mb16) EXTERN (mbx_sm4_decrypt_ofb_mb16) EXTERN (mbx_sm4_encrypt_cfb128_mb16) EXTERN (mbx_sm4_decrypt_cfb128_mb16) EXTERN (mbx_sm4_gcm_init_mb16) EXTERN (mbx_sm4_gcm_update_iv_mb16) EXTERN (mbx_sm4_gcm_update_aad_mb16) EXTERN (mbx_sm4_gcm_encrypt_mb16) EXTERN (mbx_sm4_gcm_decrypt_mb16) EXTERN (mbx_sm4_gcm_get_tag_mb16) EXTERN (mbx_sm4_ccm_init_mb16) EXTERN (mbx_sm4_ccm_update_aad_mb16) EXTERN (mbx_sm4_ccm_encrypt_mb16) EXTERN (mbx_sm4_ccm_decrypt_mb16) EXTERN (mbx_sm4_ccm_get_tag_mb16) EXTERN (mbx_sm4_xts_set_keys_mb16) EXTERN (mbx_sm4_xts_encrypt_mb16) EXTERN (mbx_sm4_xts_decrypt_mb16) crypto_mb.macosx.lib-export000066400000000000000000000057721470420105600345040ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_export_mbx_getversion _mbx_get_cpu_features _mbx_set_cpu_features _mbx_is_crypto_mb_applicable _mbx_get_algo_info _mbx_rsa_public_mb8 _mbx_rsa_private_mb8 _mbx_rsa_private_crt_mb8 _mbx_rsa_public_ssl_mb8 _mbx_rsa_private_ssl_mb8 _mbx_rsa_private_crt_ssl_mb8 _mbx_x25519_public_key_mb8 _mbx_x25519_mb8 _mbx_ed25519_public_key_mb8 _mbx_ed25519_sign_mb8 _mbx_ed25519_verify_mb8 _mbx_exp_BufferSize _mbx_exp1024_mb8 _mbx_exp2048_mb8 _mbx_exp3072_mb8 _mbx_exp4096_mb8 _mbx_exp_mb8 _mbx_nistp256_ecdh_mb8 _mbx_nistp256_ecdsa_sign_setup_mb8 _mbx_nistp256_ecdsa_sign_complete_mb8 _mbx_nistp256_ecdsa_sign_mb8 _mbx_nistp256_ecdsa_verify_mb8 _mbx_nistp256_ecpublic_key_mb8 _mbx_nistp256_ecdh_ssl_mb8 _mbx_nistp256_ecdsa_sign_setup_ssl_mb8 _mbx_nistp256_ecdsa_sign_complete_ssl_mb8 _mbx_nistp256_ecdsa_sign_ssl_mb8 _mbx_nistp256_ecdsa_verify_ssl_mb8 _mbx_nistp256_ecpublic_key_ssl_mb8 _mbx_nistp384_ecdh_mb8 _mbx_nistp384_ecdsa_sign_setup_mb8 _mbx_nistp384_ecdsa_sign_complete_mb8 _mbx_nistp384_ecdsa_sign_mb8 _mbx_nistp384_ecdsa_verify_mb8 _mbx_nistp384_ecpublic_key_mb8 _mbx_nistp384_ecdh_ssl_mb8 _mbx_nistp384_ecdsa_sign_setup_ssl_mb8 _mbx_nistp384_ecdsa_sign_complete_ssl_mb8 _mbx_nistp384_ecdsa_sign_ssl_mb8 _mbx_nistp384_ecdsa_verify_ssl_mb8 _mbx_nistp384_ecpublic_key_ssl_mb8 _mbx_nistp521_ecdh_mb8 _mbx_nistp521_ecdsa_sign_setup_mb8 _mbx_nistp521_ecdsa_sign_complete_mb8 _mbx_nistp521_ecdsa_sign_mb8 _mbx_nistp521_ecdsa_verify_mb8 _mbx_nistp521_ecpublic_key_mb8 _mbx_nistp521_ecdh_ssl_mb8 _mbx_nistp521_ecdsa_sign_setup_ssl_mb8 _mbx_nistp521_ecdsa_sign_complete_ssl_mb8 _mbx_nistp521_ecdsa_sign_ssl_mb8 _mbx_nistp521_ecdsa_verify_ssl_mb8 _mbx_nistp521_ecpublic_key_ssl_mb8 _mbx_sm2_ecdh_mb8 _mbx_sm2_ecdsa_sign_mb8 _mbx_sm2_ecdsa_verify_mb8 _mbx_sm2_ecpublic_key_mb8 _mbx_sm2_ecdh_ssl_mb8 _mbx_sm2_ecdsa_sign_ssl_mb8 _mbx_sm2_ecdsa_verify_ssl_mb8 _mbx_sm2_ecpublic_key_ssl_mb8 _mbx_RSA1K_pub65537_Method _mbx_RSA2K_pub65537_Method _mbx_RSA3K_pub65537_Method _mbx_RSA4K_pub65537_Method _mbx_RSA_pub65537_Method _mbx_RSA1K_private_Method _mbx_RSA2K_private_Method _mbx_RSA3K_private_Method _mbx_RSA4K_private_Method _mbx_RSA_private_Method _mbx_RSA1K_private_crt_Method _mbx_RSA2K_private_crt_Method _mbx_RSA3K_private_crt_Method _mbx_RSA4K_private_crt_Method _mbx_RSA_private_crt_Method _mbx_RSA_Method_BufSize _mbx_sm3_init_mb16 _mbx_sm3_update_mb16 _mbx_sm3_final_mb16 _mbx_sm3_msg_digest_mb16 _mbx_sm4_set_key_mb16 _mbx_sm4_encrypt_ecb_mb16 _mbx_sm4_decrypt_ecb_mb16 _mbx_sm4_encrypt_cbc_mb16 _mbx_sm4_decrypt_cbc_mb16 _mbx_sm4_encrypt_ctr128_mb16 _mbx_sm4_decrypt_ctr128_mb16 _mbx_sm4_encrypt_ofb_mb16 _mbx_sm4_decrypt_ofb_mb16 _mbx_sm4_encrypt_cfb128_mb16 _mbx_sm4_decrypt_cfb128_mb16 _mbx_sm4_gcm_init_mb16 _mbx_sm4_gcm_update_iv_mb16 _mbx_sm4_gcm_update_aad_mb16 _mbx_sm4_gcm_encrypt_mb16 _mbx_sm4_gcm_decrypt_mb16 _mbx_sm4_gcm_get_tag_mb16 _mbx_sm4_ccm_init_mb16 _mbx_sm4_ccm_update_aad_mb16 _mbx_sm4_ccm_encrypt_mb16 _mbx_sm4_ccm_decrypt_mb16 _mbx_sm4_ccm_get_tag_mb16 _mbx_sm4_xts_set_keys_mb16 _mbx_sm4_xts_encrypt_mb16 _mbx_sm4_xts_decrypt_mb16 crypto_mb.macosx.selftests-export000066400000000000000000000043501470420105600357410ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_export_fips_selftest_mbx_nistp256_ecpublic_key_mb8 _fips_selftest_mbx_nistp384_ecpublic_key_mb8 _fips_selftest_mbx_nistp521_ecpublic_key_mb8 _fips_selftest_mbx_nistp256_ecdh_mb8 _fips_selftest_mbx_nistp384_ecdh_mb8 _fips_selftest_mbx_nistp521_ecdh_mb8 _fips_selftest_mbx_nistp256_ecdsa_sign_mb8 _fips_selftest_mbx_nistp384_ecdsa_sign_mb8 _fips_selftest_mbx_nistp521_ecdsa_sign_mb8 _fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8 _fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8 _fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8 _fips_selftest_mbx_nistp256_ecdsa_verify_mb8 _fips_selftest_mbx_nistp384_ecdsa_verify_mb8 _fips_selftest_mbx_nistp521_ecdsa_verify_mb8 _fips_selftest_mbx_ed25519_public_key_mb8 _fips_selftest_mbx_ed25519_sign_mb8 _fips_selftest_mbx_ed25519_verify_mb8 _fips_selftest_mbx_rsa2k_public_mb8 _fips_selftest_mbx_rsa3k_public_mb8 _fips_selftest_mbx_rsa4k_public_mb8 _fips_selftest_mbx_rsa2k_private_mb8 _fips_selftest_mbx_rsa3k_private_mb8 _fips_selftest_mbx_rsa4k_private_mb8 _fips_selftest_mbx_rsa2k_private_crt_mb8 _fips_selftest_mbx_rsa3k_private_crt_mb8 _fips_selftest_mbx_rsa4k_private_crt_mb8 _fips_selftest_mbx_nistp256_ecdsa_sign_ssl_mb8 _fips_selftest_mbx_nistp384_ecdsa_sign_ssl_mb8 _fips_selftest_mbx_nistp521_ecdsa_sign_ssl_mb8 _fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_ssl_mb8 _fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_ssl_mb8 _fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_ssl_mb8 _fips_selftest_mbx_nistp256_ecdsa_verify_ssl_mb8 _fips_selftest_mbx_nistp384_ecdsa_verify_ssl_mb8 _fips_selftest_mbx_nistp521_ecdsa_verify_ssl_mb8 _fips_selftest_mbx_nistp256_ecpublic_key_ssl_mb8 _fips_selftest_mbx_nistp384_ecpublic_key_ssl_mb8 _fips_selftest_mbx_nistp521_ecpublic_key_ssl_mb8 _fips_selftest_mbx_nistp256_ecdh_ssl_mb8 _fips_selftest_mbx_nistp384_ecdh_ssl_mb8 _fips_selftest_mbx_nistp521_ecdh_ssl_mb8 _fips_selftest_mbx_rsa2k_public_ssl_mb8 _fips_selftest_mbx_rsa3k_public_ssl_mb8 _fips_selftest_mbx_rsa4k_public_ssl_mb8 _fips_selftest_mbx_rsa2k_private_ssl_mb8 _fips_selftest_mbx_rsa3k_private_ssl_mb8 _fips_selftest_mbx_rsa4k_private_ssl_mb8 _fips_selftest_mbx_rsa2k_private_crt_ssl_mb8 _fips_selftest_mbx_rsa3k_private_crt_ssl_mb8 _fips_selftest_mbx_rsa4k_private_crt_ssl_mb8 crypto_mb_fips_selftests.defs000066400000000000000000000121121470420105600351460ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_exportEXPORTS mbx_getversion mbx_get_cpu_features mbx_set_cpu_features mbx_is_crypto_mb_applicable mbx_get_algo_info mbx_rsa_public_mb8 mbx_rsa_private_mb8 mbx_rsa_private_crt_mb8 mbx_rsa_public_ssl_mb8 mbx_rsa_private_ssl_mb8 mbx_rsa_private_crt_ssl_mb8 mbx_x25519_public_key_mb8 mbx_x25519_mb8 mbx_ed25519_public_key_mb8 mbx_ed25519_sign_mb8 mbx_ed25519_verify_mb8 mbx_exp_BufferSize mbx_exp1024_mb8 mbx_exp2048_mb8 mbx_exp3072_mb8 mbx_exp4096_mb8 mbx_exp_mb8 mbx_nistp256_ecdh_mb8 mbx_nistp256_ecdsa_sign_setup_mb8 mbx_nistp256_ecdsa_sign_complete_mb8 mbx_nistp256_ecdsa_sign_mb8 mbx_nistp256_ecdsa_verify_mb8 mbx_nistp256_ecpublic_key_mb8 mbx_nistp256_ecdh_ssl_mb8 mbx_nistp256_ecdsa_sign_setup_ssl_mb8 mbx_nistp256_ecdsa_sign_complete_ssl_mb8 mbx_nistp256_ecdsa_sign_ssl_mb8 mbx_nistp256_ecdsa_verify_ssl_mb8 mbx_nistp256_ecpublic_key_ssl_mb8 mbx_nistp384_ecdh_mb8 mbx_nistp384_ecdsa_sign_setup_mb8 mbx_nistp384_ecdsa_sign_complete_mb8 mbx_nistp384_ecdsa_sign_mb8 mbx_nistp384_ecdsa_verify_mb8 mbx_nistp384_ecpublic_key_mb8 mbx_nistp384_ecdh_ssl_mb8 mbx_nistp384_ecdsa_sign_setup_ssl_mb8 mbx_nistp384_ecdsa_sign_complete_ssl_mb8 mbx_nistp384_ecdsa_sign_ssl_mb8 mbx_nistp384_ecdsa_verify_ssl_mb8 mbx_nistp384_ecpublic_key_ssl_mb8 mbx_nistp521_ecdh_mb8 mbx_nistp521_ecdsa_sign_setup_mb8 mbx_nistp521_ecdsa_sign_complete_mb8 mbx_nistp521_ecdsa_sign_mb8 mbx_nistp521_ecdsa_verify_mb8 mbx_nistp521_ecpublic_key_mb8 mbx_nistp521_ecdh_ssl_mb8 mbx_nistp521_ecdsa_sign_setup_ssl_mb8 mbx_nistp521_ecdsa_sign_complete_ssl_mb8 mbx_nistp521_ecdsa_sign_ssl_mb8 mbx_nistp521_ecdsa_verify_ssl_mb8 mbx_nistp521_ecpublic_key_ssl_mb8 mbx_sm2_ecdh_mb8 mbx_sm2_ecdsa_sign_mb8 mbx_sm2_ecdsa_verify_mb8 mbx_sm2_ecpublic_key_mb8 mbx_sm2_ecdh_ssl_mb8 mbx_sm2_ecdsa_sign_ssl_mb8 mbx_sm2_ecdsa_verify_ssl_mb8 mbx_sm2_ecpublic_key_ssl_mb8 mbx_RSA1K_pub65537_Method mbx_RSA2K_pub65537_Method mbx_RSA3K_pub65537_Method mbx_RSA4K_pub65537_Method mbx_RSA_pub65537_Method mbx_RSA1K_private_Method mbx_RSA2K_private_Method mbx_RSA3K_private_Method mbx_RSA4K_private_Method mbx_RSA_private_Method mbx_RSA1K_private_crt_Method mbx_RSA2K_private_crt_Method mbx_RSA3K_private_crt_Method mbx_RSA4K_private_crt_Method mbx_RSA_private_crt_Method mbx_RSA_Method_BufSize mbx_sm3_init_mb16 mbx_sm3_update_mb16 mbx_sm3_final_mb16 mbx_sm3_msg_digest_mb16 mbx_sm4_set_key_mb16 mbx_sm4_encrypt_ecb_mb16 mbx_sm4_decrypt_ecb_mb16 mbx_sm4_encrypt_cbc_mb16 mbx_sm4_decrypt_cbc_mb16 mbx_sm4_encrypt_ctr128_mb16 mbx_sm4_decrypt_ctr128_mb16 mbx_sm4_encrypt_ofb_mb16 mbx_sm4_decrypt_ofb_mb16 mbx_sm4_encrypt_cfb128_mb16 mbx_sm4_decrypt_cfb128_mb16 mbx_sm4_gcm_init_mb16 mbx_sm4_gcm_update_iv_mb16 mbx_sm4_gcm_update_aad_mb16 mbx_sm4_gcm_encrypt_mb16 mbx_sm4_gcm_decrypt_mb16 mbx_sm4_gcm_get_tag_mb16 mbx_sm4_ccm_init_mb16 mbx_sm4_ccm_update_aad_mb16 mbx_sm4_ccm_encrypt_mb16 mbx_sm4_ccm_decrypt_mb16 mbx_sm4_ccm_get_tag_mb16 mbx_sm4_xts_set_keys_mb16 mbx_sm4_xts_encrypt_mb16 mbx_sm4_xts_decrypt_mb16 fips_selftest_mbx_nistp256_ecpublic_key_mb8 fips_selftest_mbx_nistp384_ecpublic_key_mb8 fips_selftest_mbx_nistp521_ecpublic_key_mb8 fips_selftest_mbx_nistp256_ecdh_mb8 fips_selftest_mbx_nistp384_ecdh_mb8 fips_selftest_mbx_nistp521_ecdh_mb8 fips_selftest_mbx_nistp256_ecdsa_sign_mb8 fips_selftest_mbx_nistp384_ecdsa_sign_mb8 fips_selftest_mbx_nistp521_ecdsa_sign_mb8 fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8 fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8 fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8 fips_selftest_mbx_nistp256_ecdsa_verify_mb8 fips_selftest_mbx_nistp384_ecdsa_verify_mb8 fips_selftest_mbx_nistp521_ecdsa_verify_mb8 fips_selftest_mbx_ed25519_public_key_mb8 fips_selftest_mbx_ed25519_sign_mb8 fips_selftest_mbx_ed25519_verify_mb8 fips_selftest_mbx_rsa2k_public_mb8 fips_selftest_mbx_rsa3k_public_mb8 fips_selftest_mbx_rsa4k_public_mb8 fips_selftest_mbx_rsa2k_private_mb8 fips_selftest_mbx_rsa3k_private_mb8 fips_selftest_mbx_rsa4k_private_mb8 fips_selftest_mbx_rsa2k_private_crt_mb8 fips_selftest_mbx_rsa3k_private_crt_mb8 fips_selftest_mbx_rsa4k_private_crt_mb8 fips_selftest_mbx_nistp256_ecdsa_sign_ssl_mb8 fips_selftest_mbx_nistp384_ecdsa_sign_ssl_mb8 fips_selftest_mbx_nistp521_ecdsa_sign_ssl_mb8 fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_ssl_mb8 fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_ssl_mb8 fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_ssl_mb8 fips_selftest_mbx_nistp256_ecdsa_verify_ssl_mb8 fips_selftest_mbx_nistp384_ecdsa_verify_ssl_mb8 fips_selftest_mbx_nistp521_ecdsa_verify_ssl_mb8 fips_selftest_mbx_nistp256_ecpublic_key_ssl_mb8 fips_selftest_mbx_nistp384_ecpublic_key_ssl_mb8 fips_selftest_mbx_nistp521_ecpublic_key_ssl_mb8 fips_selftest_mbx_nistp256_ecdh_ssl_mb8 fips_selftest_mbx_nistp384_ecdh_ssl_mb8 fips_selftest_mbx_nistp521_ecdh_ssl_mb8 fips_selftest_mbx_rsa2k_public_ssl_mb8 fips_selftest_mbx_rsa3k_public_ssl_mb8 fips_selftest_mbx_rsa4k_public_ssl_mb8 fips_selftest_mbx_rsa2k_private_ssl_mb8 fips_selftest_mbx_rsa3k_private_ssl_mb8 fips_selftest_mbx_rsa4k_private_ssl_mb8 fips_selftest_mbx_rsa2k_private_crt_ssl_mb8 fips_selftest_mbx_rsa3k_private_crt_ssl_mb8 fips_selftest_mbx_rsa4k_private_crt_ssl_mb8 fips_selftests.linux.lib-export000066400000000000000000000052001470420105600353720ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/dll_exportEXTERN (fips_selftest_mbx_nistp256_ecpublic_key_mb8) EXTERN (fips_selftest_mbx_nistp384_ecpublic_key_mb8) EXTERN (fips_selftest_mbx_nistp521_ecpublic_key_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdh_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdh_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdh_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdsa_sign_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdsa_sign_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdsa_sign_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdsa_verify_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdsa_verify_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdsa_verify_mb8) EXTERN (fips_selftest_mbx_ed25519_public_key_mb8) EXTERN (fips_selftest_mbx_ed25519_sign_mb8) EXTERN (fips_selftest_mbx_ed25519_verify_mb8) EXTERN (fips_selftest_mbx_rsa2k_public_mb8) EXTERN (fips_selftest_mbx_rsa3k_public_mb8) EXTERN (fips_selftest_mbx_rsa4k_public_mb8) EXTERN (fips_selftest_mbx_rsa2k_private_mb8) EXTERN (fips_selftest_mbx_rsa3k_private_mb8) EXTERN (fips_selftest_mbx_rsa4k_private_mb8) EXTERN (fips_selftest_mbx_rsa2k_private_crt_mb8) EXTERN (fips_selftest_mbx_rsa3k_private_crt_mb8) EXTERN (fips_selftest_mbx_rsa4k_private_crt_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdsa_sign_ssl_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdsa_sign_ssl_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdsa_sign_ssl_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_ssl_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_ssl_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_ssl_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdsa_verify_ssl_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdsa_verify_ssl_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdsa_verify_ssl_mb8) EXTERN (fips_selftest_mbx_nistp256_ecpublic_key_ssl_mb8) EXTERN (fips_selftest_mbx_nistp384_ecpublic_key_ssl_mb8) EXTERN (fips_selftest_mbx_nistp521_ecpublic_key_ssl_mb8) EXTERN (fips_selftest_mbx_nistp256_ecdh_ssl_mb8) EXTERN (fips_selftest_mbx_nistp384_ecdh_ssl_mb8) EXTERN (fips_selftest_mbx_nistp521_ecdh_ssl_mb8) EXTERN (fips_selftest_mbx_rsa2k_public_ssl_mb8) EXTERN (fips_selftest_mbx_rsa3k_public_ssl_mb8) EXTERN (fips_selftest_mbx_rsa4k_public_ssl_mb8) EXTERN (fips_selftest_mbx_rsa2k_private_ssl_mb8) EXTERN (fips_selftest_mbx_rsa3k_private_ssl_mb8) EXTERN (fips_selftest_mbx_rsa4k_private_ssl_mb8) EXTERN (fips_selftest_mbx_rsa2k_private_crt_ssl_mb8) EXTERN (fips_selftest_mbx_rsa3k_private_crt_ssl_mb8) EXTERN (fips_selftest_mbx_rsa4k_private_crt_ssl_mb8) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/linux/000077500000000000000000000000001470420105600262355ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/linux/Clang.cmake000066400000000000000000000101261470420105600302630ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Format string vulnerabilities set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wformat -Wformat-security -Werror=format-security") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fcf-protection=full") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-protector") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fpic -fPIC") # Enables important warning and error messages relevant to security during compilation set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall") # Warnings=errors set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Werror") # Linker flags # Create shared library set(LINK_FLAGS_DYNAMIC " -Wl,-shared") # Add export files set(DLL_EXPORT_DIR "${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/") set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/crypto_mb.linux.lib-export") if (MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/fips_selftests.linux.lib-export") endif() # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS " -falign-functions=32") # -ffreestanding flag removed for clang because it causes compilation error in combination with -D_FORTIFY_SOURCE=2 # and limits.h and stdlib.h headers because of wrong value of MB_LEN_MAX defined in limits.h and checked in stdlib.h # This issue is reprodusable with clang9. Flag is not removed for other compilers to prevent other possible issues. set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") # Suppress warnings from casts from a pointer to an integer type of a different size set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast") # Optimization level = 3, no-debug definition (turns off asserts) set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG") if(NOT DEFINED NO_FORTIFY_SOURCE) # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Optimisation dependent flags # Add Intel® AVX-IFMA specific compiler options only for compilers that support them if(MBX_CC_AVXIFMA_SUPPORT) set(l9_opt "-march=sierraforest -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni -mavxifma") else() set(l9_opt "-mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni") endif() set(k1_opt "-march=icelake-server -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") # Build with sanitizers # FIXME: so far it can be enabled from the IPPCP build only. Change it once crypto_mb build is separated. if(SANITIZERS) include(${CMAKE_SOURCE_DIR}/sources/cmake/linux/SanitizersSettings.cmake) set_sanitizers_flags("C") set_sanitizers_flags("CXX") endif(SANITIZERS) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/linux/GNU.cmake000066400000000000000000000073201470420105600276720ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Format string vulnerabilities set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wformat -Wformat-security -Werror=format-security") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-protector") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-clash-protection") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fpic -fPIC") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fcf-protection=full") # Enables important warning and error messages relevant to security during compilation set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall") # Warnings=errors set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Werror") # Linker flags # Create shared library set(LINK_FLAGS_DYNAMIC " -Wl,-shared") # Add export files set(DLL_EXPORT_DIR "${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/") set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/crypto_mb.linux.lib-export") if (MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/fips_selftests.linux.lib-export") endif() # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS " -falign-functions=32 -falign-loops=32") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") # Suppress warnings from casts from a pointer to an integer type of a different size set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast") # Optimization level = 3, no-debug definition (turns off asserts) set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG") if(NOT DEFINED NO_FORTIFY_SOURCE) # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Optimisation dependent flags # Add Intel® AVX-IFMA specific compiler options only for compilers that support them if(MBX_CC_AVXIFMA_SUPPORT) set(l9_opt "-march=sierraforest -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni -mavxifma") else() set(l9_opt "-mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni") endif() set(k1_opt "-march=icelake-server -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/linux/Intel.cmake000066400000000000000000000063711470420105600303210ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Format string vulnerabilities set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wformat -Wformat-security -Werror=format-security") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-protector") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fpic -fPIC") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fcf-protection=full") # Enables important warning and error messages relevant to security during compilation set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall") # Warnings=errors set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Werror") # Linker flags # Create shared library set(LINK_FLAGS_DYNAMIC " -Wl,-shared") # Add export files set(DLL_EXPORT_DIR "${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/") set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/crypto_mb.linux.lib-export") if (MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/fips_selftests.linux.lib-export") endif() # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS " -falign-functions=32 -falign-loops=32") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -prof-gen:srcpos -prof-dir $ENV{PROF_DATA_DIR}") endif() set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") # Suppress warnings from casts from a pointer to an integer type of a different size set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast") # Optimization level = 3, no-debug definition (turns off asserts) set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG") if(NOT DEFINED NO_FORTIFY_SOURCE) # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Optimisation dependent flags set(l9_opt "-xCORE-AVX2") set(k1_opt "-xCORE-AVX512 -qopt-zmm-usage:high") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/linux/IntelLLVM.cmake000066400000000000000000000073161470420105600310140ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Format string vulnerabilities set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wformat -Wformat-security -Werror=format-security") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-protector") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fpic -fPIC") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fcf-protection=full") # Enables important warning and error messages relevant to security during compilation set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall") # Warnings=errors set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Werror") # Linker flags # Create shared library set(LINK_FLAGS_DYNAMIC " -Wl,-shared") # Add export files set(DLL_EXPORT_DIR "${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/") set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/crypto_mb.linux.lib-export") if (MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} ${DLL_EXPORT_DIR}/fips_selftests.linux.lib-export") endif() # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS " -falign-functions=32") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -prof-gen:srcpos -prof-dir $ENV{PROF_DATA_DIR}") endif() set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") # Suppress warnings from casts from a pointer to an integer type of a different size set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast") # Optimization level = 3, no-debug definition (turns off asserts) set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG") if(NOT DEFINED NO_FORTIFY_SOURCE) # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Optimisation dependent flags # Add Intel® AVX-IFMA specific compiler options only for compilers that support them if(MBX_CC_AVXIFMA_SUPPORT) set(l9_opt "-march=sierraforest -mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni -mavxifma") else() set(l9_opt "-mavx2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni") endif() set(k1_opt "-march=icelake-server -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2 -mprefer-vector-width=512") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/macosx/000077500000000000000000000000001470420105600263705ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/macosx/AppleClang.cmake000066400000000000000000000061251470420105600314040ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Data relocation and protection (RELRO) set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,relro -Wl,-z,now") # Stack execution protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} -Wl,-z,noexecstack") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Format string vulnerabilities set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wformat -Wformat-security -Werror=format-security") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-protector") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fpic -fPIC") # Enables important warning and error messages relevant to security during compilation set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall") # Warnings=errors set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Werror") # Linker flags # Add export files set(DLL_EXPORT_DIR "${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/") set(LINK_FLAGS_DYNAMIC "-exported_symbols_list ${DLL_EXPORT_DIR}/crypto_mb.macosx.lib-export") if(MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} -exported_symbols_list ${DLL_EXPORT_DIR}/crypto_mb.macosx.selftests-export") endif() # Add mininmum version support macOS set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} -mmacosx-version-min=12.0") # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS " -falign-functions=32") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") # Suppress warnings from casts from a pointer to an integer type of a different size set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast") # Optimization level = 3, no-debug definition (turns off asserts) set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG") if(NOT DEFINED NO_FORTIFY_SOURCE) # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Optimisation dependent flags set(AVX512_CFLAGS " -march=icelake-server -mavx512dq -mavx512ifma -mavx512f -mavx512vbmi2 -mavx512cd -mavx512bw -mbmi2") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/macosx/Intel.cmake000066400000000000000000000063441470420105600304540ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") set(LINK_FLAG_SECURITY " -Wl,-dynamic") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Format string vulnerabilities set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wformat -Wformat-security -Werror=format-security") # Stack-based Buffer Overrun Detection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fstack-protector") # Position Independent Execution (PIE) set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fpic -fPIC") # Enables important warning and error messages relevant to security during compilation set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall") # Warnings=errors set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Werror") # Linker flags # Add export files set(DLL_EXPORT_DIR "${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/") set(LINK_FLAGS_DYNAMIC "-exported_symbols_list ${DLL_EXPORT_DIR}/crypto_mb.macosx.lib-export") if(MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} -exported_symbols_list ${DLL_EXPORT_DIR}/crypto_mb.macosx.selftests-export") endif() # Add mininmum version support macOS set(LINK_FLAGS_DYNAMIC "${LINK_FLAGS_DYNAMIC} -mmacosx-version-min=12.0") # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS " -falign-functions=32 -falign-loops=32") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -prof-gen:srcpos -prof-dir ${PROF_DATA_DIR}") endif() # Architectural flags for assembler. The old XCode tools require an explicit enumeration of architectural flags be given to assembler. set(CMAKE_ASM_FLAGS "-Wa,-mavx512dq,-mavx512ifma,-mavx512f,-mavx512cd,-mavx512vbmi,-mavx512bw,-mavx512vl,-mbmi") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") # Suppress warnings from casts from a pointer to an integer type of a different size set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast") # Optimization level = 3, no-debug definition (turns off asserts) set(CMAKE_C_FLAGS_RELEASE " -O3 -DNDEBUG") if(NOT DEFINED NO_FORTIFY_SOURCE) # Security flag that adds compile-time and run-time checks set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Optimisation dependent flags set(AVX512_CFLAGS " -xCORE-AVX512 -qopt-zmm-usage:high") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/windows/000077500000000000000000000000001470420105600265705ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/windows/Intel.cmake000066400000000000000000000100141470420105600306410ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Specifies whether to generate an executable image that can be randomly rebased at load time. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /DYNAMICBASE") # This option modifies the header of an executable image, a .dll file or .exe file, to indicate whether ASLR with 64-bit addresses is supported. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /HIGHENTROPYVA") # The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /LARGEADDRESSAWARE") # Indicates that an executable is compatible with the Windows Data Execution Prevention (DEP) feature set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /NXCOMPAT") # Linker option to mitigate DLL hijacking vulnerability - removes CWD from the DLL search order set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /DEPENDENTLOADFLAG:0x2000") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Detect some buffer overruns. set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /GS") # Warning level = 3 set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /W3") # Changes all warnings to errors. set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /WX") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /Qcf-protection:full") # Changes all warnings to errors. set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /WX") # Linker flags # Add export files if(MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "/DEF:${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/crypto_mb_fips_selftests.defs") else() set(LINK_FLAGS_DYNAMIC "/DEF:${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/crypto_mb.defs") endif() # Compiler flags # Tells the compiler to align functions and loops set(CMAKE_C_FLAGS "/Qfnalign:32 /Qalign-loops:32") # Suppress warning #10120: overriding '/O2' with '/O3' set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -wd10120") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qfreestanding") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qrof-gen:srcpos /Qprof-dir:${PROF_DATA_DIR}") endif() set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qstd=c99") # Causes the application to use the multithread, static version of the run-time library set(CMAKE_C_FLAGS_RELEASE "/MT") # Optimization level = 3 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O3") # No-debug macro set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Causes the application to use the multithread, static version of the run-time library (debug version). set(CMAKE_C_FLAGS_DEBUG "/MTd") # The /Zi option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi") # Turns off all optimizations. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od") # Debug macro set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /D_DEBUG") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") # Optimisation dependent flags set(l9_opt "-QxCORE-AVX2") set(k1_opt "-QxCORE-AVX512 -Qopt-zmm-usage:high") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/windows/IntelLLVM.cmake000066400000000000000000000112321470420105600313370ustar00rootroot00000000000000#=============================================================================== # Copyright (C) 2024 Intel Corporation # # 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. # #=============================================================================== # Security Linker flags set(LINK_FLAG_SECURITY "") # Specifies whether to generate an executable image that can be randomly rebased at load time. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /DYNAMICBASE") # This option modifies the header of an executable image, a .dll file or .exe file, to indicate whether ASLR with 64-bit addresses is supported. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /HIGHENTROPYVA") # The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /LARGEADDRESSAWARE") # Indicates that an executable is compatible with the Windows Data Execution Prevention (DEP) feature set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /NXCOMPAT") # Linker option to mitigate DLL hijacking vulnerability - removes CWD from the DLL search order set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /DEPENDENTLOADFLAG:0x2000") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Detect some buffer overruns. set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /GS") # Warning level = 3 set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /W4") # Changes all warnings to errors. set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /WX") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -fcf-protection:full") # Recommended security flags set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} -Wall -Wformat -Wformat-security -Werror=format-security") # Linker flags # Add export files if(MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "/DEF:${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/crypto_mb_fips_selftests.defs") else() set(LINK_FLAGS_DYNAMIC "/DEF:${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/crypto_mb.defs") endif() # Compiler flags # Tells the compiler to align functions and loops # set(CMAKE_C_FLAGS "/Qfnalign:32 /Qalign-loops:32") # Suppress warning #10120: overriding '/O2' with '/O3' set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -wd10120 -Wno-unused-command-line-argument -Wno-unused-parameter -Wno-pointer-sign -Wno-sign-compare -Wno-static-in-inline /Qno-intel-lib") # Ensures that compilation takes place in a freestanding environment set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qfreestanding") if(CODE_COVERAGE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qrof-gen:srcpos /Qprof-dir:${PROF_DATA_DIR}") endif() set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") # Tells the compiler to conform to a specific language standard. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Qstd=c99") # Causes the application to use the multithread, static version of the run-time library set(CMAKE_C_FLAGS_RELEASE "/MT") # Optimization level = 3 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O3") # No-debug macro set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Causes the application to use the multithread, static version of the run-time library (debug version). set(CMAKE_C_FLAGS_DEBUG "/MTd") # The /Zi option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi") # Turns off all optimizations. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od") # Debug macro set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /D_DEBUG") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") # Optimisation dependent flags # Add Intel® AVX-IFMA specific compiler options only for compilers that support them if(MBX_CC_AVXIFMA_SUPPORT) set(l9_opt "/arch:CORE-AVX2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni -mavxifma") else() set(l9_opt "/arch:CORE-AVX2 -maes -mvaes -mpclmul -mvpclmulqdq -msha -mrdrnd -mrdseed -mgfni") endif() set(k1_opt "/arch:ICELAKE-SERVER -maes -mavx512f -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mpclmul -msha -mrdrnd -mrdseed -madx -mgfni -mvaes -mvpclmulqdq -mavx512vbmi -mavx512vbmi2 -mprefer-vector-width=512") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/cmake/windows/MSVC.cmake000066400000000000000000000064401470420105600303460ustar00rootroot00000000000000#========================================================================= # Copyright (C) 2019 Intel Corporation # # 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. #========================================================================= # Security Linker flags set(LINK_FLAG_SECURITY "") # Specifies whether to generate an executable image that can be randomly rebased at load time. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /DYNAMICBASE") # This option modifies the header of an executable image, a .dll file or .exe file, to indicate whether ASLR with 64-bit addresses is supported. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /HIGHENTROPYVA") # The /LARGEADDRESSAWARE option tells the linker that the application can handle addresses larger than 2 gigabytes. set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /LARGEADDRESSAWARE") # Indicates that an executable is compatible with the Windows Data Execution Prevention (DEP) feature set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /NXCOMPAT") # Enable Intel® Control-Flow Enforcement Technology (Intel® CET) protection set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /CETCOMPAT") # Linker option to mitigate DLL hijacking vulnerability - removes CWD from the DLL search order set(LINK_FLAG_SECURITY "${LINK_FLAG_SECURITY} /DEPENDENTLOADFLAG:0x2000") # Security Compiler flags set(CMAKE_C_FLAGS_SECURITY "") # Detect some buffer overruns. set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /GS") # Warning level = 3 set(CMAKE_C_FLAGS_SECURITY "${CMAKE_C_FLAGS_SECURITY} /W3") # Changes all warnings to errors. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") # Linker flags # Add export files if(MBX_FIPS_MODE) set(LINK_FLAGS_DYNAMIC "/DEF:${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/crypto_mb_fips_selftests.defs") else() set(LINK_FLAGS_DYNAMIC "/DEF:${CRYPTO_MB_SOURCES_DIR}/cmake/dll_export/crypto_mb.defs") endif() # Compiler flags # Causes the application to use the multithread, static version of the run-time library set(CMAKE_C_FLAGS_RELEASE "/MT") # Optimization level = 2 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /O2") # No-debug macro set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Causes the application to use the multithread, static version of the run-time library (debug version). set(CMAKE_C_FLAGS_DEBUG "/MTd") # The /Zi option produces a separate PDB file that contains all the symbolic debugging information for use with the debugger. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi") # Turns off all optimizations. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Od") # Debug macro set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /D_DEBUG") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") # Optimisation dependent flags set(l9_opt "/arch:AVX2") set(k1_opt "/arch:AVX512") cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/000077500000000000000000000000001470420105600253065ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/cpu_features.c000066400000000000000000000260041470420105600301410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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. *************************************************************************/ #if defined( _WIN32 ) || defined( _WIN64 ) #include #endif #include #include /* masks of bits */ #define BIT00 0x00000001 #define BIT01 0x00000002 #define BIT02 0x00000004 #define BIT03 0x00000008 #define BIT04 0x00000010 #define BIT05 0x00000020 #define BIT06 0x00000040 #define BIT07 0x00000080 #define BIT08 0x00000100 #define BIT09 0x00000200 #define BIT10 0x00000400 #define BIT11 0x00000800 #define BIT12 0x00001000 #define BIT13 0x00002000 #define BIT14 0x00004000 #define BIT15 0x00008000 #define BIT16 0x00010000 #define BIT17 0x00020000 #define BIT18 0x00040000 #define BIT19 0x00080000 #define BIT20 0x00100000 #define BIT21 0x00200000 #define BIT22 0x00400000 #define BIT23 0x00800000 #define BIT24 0x01000000 #define BIT25 0x02000000 #define BIT26 0x04000000 #define BIT27 0x08000000 #define BIT28 0x10000000 #define BIT29 0x20000000 #define BIT30 0x40000000 #define BIT31 0x80000000 /* index inside cpu_info[4] */ #define eax_ (0) #define ebx_ (1) #define ecx_ (2) #define edx_ (3) __MBX_INLINE void _mbcp_cpuid(int32u buf[4], int32u leaf, int32u subleaf) { #ifdef __GNUC__ __asm__ ("cpuid" : "=a" (buf[0]), "=b" (buf[1]), "=c" (buf[2]), "=d" (buf[3]) : "a" (leaf), "c" (subleaf)); #else __cpuidex(buf,leaf, subleaf); #endif } static int32u _mbcp_max_cpuid_main_leaf_number(void) { int32u buf[4]; _mbcp_cpuid(buf, 0, 0); return buf[0]; } #if 0 static int32u _mbcp_max_cpuid_extd_leaf_number(void) { int32u buf[4]; _mbcp_cpuid(buf, 0x80000000, 0); return buf[0]; } #endif #define XSAVE_OSXSAVE (BIT26|BIT27) static int32u _mbcp_xsave_support(int32u bits) { int32u buf[4]; _mbcp_cpuid(buf, 1, 0); if(XSAVE_OSXSAVE != (buf[ecx_] & XSAVE_OSXSAVE)) return 0; int32u xcr0; #ifdef __GNUC__ //asm volatile("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx"); __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx"); #else xcr0 = (int32u)_xgetbv(0); #endif return (xcr0 & bits) == bits; } typedef struct { int32u info_idx; int32u info_idx_bit; int64u cpu_feature; } cpu_feature_map; /* // Intel(r) Architecture Instruction Set Extension and Future Features. // Programming Reference. 319433-038, March 2020 // see Table 1-5, Table 1-6 */ static const cpu_feature_map cpu_feature_detector_1_0[] = { {ecx_, BIT00, mbcpCPUID_SSE3}, {ecx_, BIT01, mbcpCPUID_CLMUL}, {ecx_, BIT09, mbcpCPUID_SSSE3}, //{ecx_, BIT12, mbcpCPUID_FMA}, /* supported FMA extensions using YMM*/ //{ecx_, BIT13, mbcpCPUID_CMPXCHG16B}, {ecx_, BIT19, mbcpCPUID_SSE41}, {ecx_, BIT20, mbcpCPUID_SSE42}, {ecx_, BIT22, mbcpCPUID_MOVBE}, //{ecx_, BIT23, mbcpCPUID_POPCNT}, {ecx_, BIT25, mbcpCPUID_AES}, {ecx_, BIT28, mbcpCPUID_AVX}, {ecx_, BIT29, mbcpCPUID_F16C}, {ecx_, BIT30, mbcpCPUID_RDRAND}, {edx_, BIT23, mbcpCPUID_MMX}, {edx_, BIT25, mbcpCPUID_SSE}, {edx_, BIT26, mbcpCPUID_SSE2}, }; static const cpu_feature_map cpu_feature_detector_7_0[] = { {ebx_, BIT03, mbcpCPUID_BMI1}, {ebx_, BIT05, mbcpCPUID_AVX2}, {ebx_, BIT08, mbcpCPUID_BMI2}, {ebx_, BIT14, mbcpCPUID_MPX}, {ebx_, BIT16, mbcpCPUID_AVX512F}, {ebx_, BIT17, mbcpCPUID_AVX512DQ}, {ebx_, BIT18, mbcpCPUID_RDSEED}, {ebx_, BIT19, mbcpCPUID_ADX}, {ebx_, BIT21, mbcpCPUID_AVX512IFMA}, {ebx_, BIT26, mbcpCPUID_AVX512PF}, {ebx_, BIT27, mbcpCPUID_AVX512ER}, {ebx_, BIT28, mbcpCPUID_AVX512CD}, {ebx_, BIT29, mbcpCPUID_SHA}, {ebx_, BIT30, mbcpCPUID_AVX512BW}, {ebx_, BIT31, mbcpCPUID_AVX512VL}, {ecx_, BIT01, mbcpCPUID_AVX512VBMI}, {ecx_, BIT06, mbcpCPUID_AVX512VBMI2}, {ecx_, BIT08, mbcpCPUID_AVX512GFNI}, {ecx_, BIT09, mbcpCPUID_AVX512VAES}, {ecx_, BIT10, mbcpCPUID_AVX512VCLMUL}, //{ecx_, BIT11, mbcpCPUID_AVX512VNNI}, //{ecx_, BIT12, mbcpCPUID_AVX512BITALG}, {edx_, BIT02, mbcpCPUID_AVX512_4VNNIW}, {edx_, BIT03, mbcpCPUID_AVX512_4FMADDPS}, }; static const cpu_feature_map cpu_feature_detector_7_1[] = { {eax_, BIT23, mbcpCPUID_AVXIFMA}, }; #undef eax_ #undef ebx_ #undef ecx_ #undef edx_ static int64u _mbcp_cpu_feature_detector(const int32u cpuinfo[4], const cpu_feature_map* tbl, int32u tbl_len) { int64u features = 0; int32u n; for(n=0; n=7) { /* cpuid info: cpuid_7_0 */ _mbcp_cpuid(cpu_info, 7, 0); features |= _mbcp_cpu_feature_detector(cpu_info, cpu_feature_detector_7_0, sizeof(cpu_feature_detector_7_0)/sizeof(cpu_feature_map)); if((features & mbcpCPUID_AVX512F) && _mbcp_xsave_support(XSAVE_AVX512_SUPPORT)) features |= mbcpAVX512_ENABLEDBYOS; /* cpuid info: cpuid_7_1 */ _mbcp_cpuid(cpu_info, 7, 1); features |= _mbcp_cpu_feature_detector(cpu_info, cpu_feature_detector_7_1, sizeof(cpu_feature_detector_7_1)/sizeof(cpu_feature_map)); } } return features; } // based on c-flags: -mavx512dq -mavx512ifma -mavx512f -mavx512vbmi2 -mavx512cd -mavx512bw -mbmi2 #define CRYPTO_MB_REQUIRED_CPU_FEATURES_K1 ( \ mbcpCPUID_BMI2 \ | mbcpCPUID_AVX512F \ | mbcpCPUID_AVX512DQ \ | mbcpCPUID_AVX512BW \ | mbcpCPUID_AVX512IFMA \ | mbcpCPUID_AVX512VBMI2 \ | mbcpAVX512_ENABLEDBYOS) #define CRYPTO_MB_REQUIRED_CPU_FEATURES_L9 ( \ mbcpCPUID_MOVBE \ | mbcpCPUID_AVX2 \ | mbcpCPUID_RDSEED \ | mbcpCPUID_AVXIFMA \ | mbcpAVX_ENABLEDBYOS) int internal_is_k1_applicable(int64u cpu_features) { int64u features = cpu_features; if(0 == features) features = mbx_get_cpu_features(); return (CRYPTO_MB_REQUIRED_CPU_FEATURES_K1 == (features & CRYPTO_MB_REQUIRED_CPU_FEATURES_K1)); } int internal_is_l9_applicable(int64u cpu_features) { int64u features = cpu_features; if(0 == features) features = mbx_get_cpu_features(); return (CRYPTO_MB_REQUIRED_CPU_FEATURES_L9 == (features & CRYPTO_MB_REQUIRED_CPU_FEATURES_L9)); } DLL_PUBLIC int mbx_is_crypto_mb_applicable(int64u cpu_features) { return (internal_is_k1_applicable(cpu_features) || internal_is_l9_applicable(cpu_features)); } static int mbx_own_lib_index = -1; /* choosing the code path */ extern int* _mbx_own_get_index() { if (0 > mbx_own_lib_index) { if (internal_is_k1_applicable(mbx_get_cpu_features())) mbx_own_lib_index = 0; // K1 code path else mbx_own_lib_index = 1; // L9 code path } return &mbx_own_lib_index; } /* structure for determining the number of buffers(WIDTH) for the algorithm */ typedef struct { enum MBX_ALGO algo; enum MBX_WIDTH width; } algo_width_map; /* clang-config off */ static const algo_width_map arr_algo_width_k1[] = { { MBX_ALGO_RSA_1K, MBX_WIDTH_MB8 }, { MBX_ALGO_RSA_2K, MBX_WIDTH_MB8 }, { MBX_ALGO_RSA_3K, MBX_WIDTH_MB8 }, { MBX_ALGO_RSA_4K, MBX_WIDTH_MB8 }, { MBX_ALGO_X25519, MBX_WIDTH_MB8 }, { MBX_ALGO_EC_NIST_P256, MBX_WIDTH_MB8 }, { MBX_ALGO_EC_NIST_P384, MBX_WIDTH_MB8 }, { MBX_ALGO_EC_NIST_P521, MBX_WIDTH_MB8 }, { MBX_ALGO_EC_SM2, MBX_WIDTH_MB8 }, { MBX_ALGO_SM3, MBX_WIDTH_MB16 }, { MBX_ALGO_SM4, MBX_WIDTH_MB16 } }; static const algo_width_map arr_algo_width_l9[] = { { MBX_ALGO_RSA_1K, MBX_WIDTH_MB8 }, { MBX_ALGO_RSA_2K, MBX_WIDTH_MB8 }, { MBX_ALGO_RSA_3K, MBX_WIDTH_MB8 }, { MBX_ALGO_RSA_4K, MBX_WIDTH_MB8 }, { MBX_ALGO_X25519, 0 }, { MBX_ALGO_EC_NIST_P256, 0 }, { MBX_ALGO_EC_NIST_P384, 0 }, { MBX_ALGO_EC_NIST_P521, 0 }, { MBX_ALGO_EC_SM2, 0 }, { MBX_ALGO_SM3, 0 }, { MBX_ALGO_SM4, 0 } }; /* clang-config on */ DLL_PUBLIC MBX_ALGO_INFO mbx_get_algo_info(enum MBX_ALGO algo) { const int k1_applicable = internal_is_k1_applicable(0); const int l9_applicable = internal_is_l9_applicable(0); const struct { const algo_width_map *arr_algo_width; unsigned num_tbl; } map_tbl[] = { {arr_algo_width_k1, (unsigned) sizeof(arr_algo_width_k1) / sizeof(algo_width_map) }, // K1 = index 0 {arr_algo_width_l9, (unsigned) sizeof(arr_algo_width_l9) / sizeof(algo_width_map) }, // L9 = index 1 }; int num_width = 0; /* check CPU feature */ if (0 == k1_applicable && 0 == l9_applicable) return num_width; /* get selected architecture */ const int map_idx = *_mbx_own_get_index(); if (map_idx < 0 || map_idx >= (int) (sizeof(map_tbl) / sizeof(map_tbl[0]))) return num_width; const unsigned num_tbl = map_tbl[map_idx].num_tbl; const algo_width_map *tbl = map_tbl[map_idx].arr_algo_width; /* loop determining the number of buffers to process */ for (unsigned i = 0; i < num_tbl; ++i) { if (algo != tbl[i].algo) continue; num_width = tbl[i].width; break; } return num_width; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/crypto_mb_res.gen000066400000000000000000000037351470420105600306600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 1999 Intel Corporation * * 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 "winres.h" #define STR2(x) #x #define STR(x) STR2(x) VS_VERSION_INFO VERSIONINFO FILEVERSION MBX_VERSION() PRODUCTVERSION MBX_VERSION() FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Intel Corporation.\0" VALUE "FileVersion", STR_FILE_MBX_VERSION() "\0" VALUE "ProductName", MBX_LIB_SHORTNAME() ". Intel(R) Cryptography Primitives Library. " MBX_LIB_LONGNAME() ".\0" VALUE "ProductVersion", CRYPTO_MB_STR_VERSION() "\0" VALUE "LegalCopyright", "Copyright (C) 1999-2021, Intel Corporation. All rights reserved.\0" VALUE "Comments", "Intel(R) Cryptography Primitives Library. " MBX_LIB_LONGNAME() ".\0" VALUE "FileDescription", MBX_LIB_SHORTNAME() ".dll is the intel64 " MBX_LIB_SHORTNAME() " dynamic library\0" VALUE "InternalName", MBX_LIB_SHORTNAME() ".dll\0" VALUE "OriginalFilename", MBX_LIB_SHORTNAME() ".dll\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/crypto_mb_ver.rc000066400000000000000000000016121470420105600305060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "crypto_mb_res.gen" /* ////////////////////////////// End of file /////////////////////////////// */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/emptyfile.c000066400000000000000000000016361470420105600274560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ typedef int to_avoid_translation_unit_is_empty_warning; /* The empty file to build a dynamic library in Visual Studio. The IDE does not produce a dll without source files */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/ifma52_mb8_template.cxx000066400000000000000000000016021470420105600315550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "ifma_math.h" #include "ifma_internal.h" {typedef} {functions} void {function_name} ({parameters}) { // Main code goes here {code} } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/ifma_cvt52.c000066400000000000000000001311211470420105600274100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 PROC_LEN (52) #define BYTES_REV (1) #define RADIX_CVT (2) #define MIN(a, b) ( ((a) < (b)) ? a : b ) #if (_MBX >= _MBX_K1) #if defined(_MSC_VER) && (_MSC_VER < 1920) // Disable optimization for VS2017 due to AVX512 masking bug #define DISABLE_OPTIMIZATION __pragma(optimize( "", off )) #else #define DISABLE_OPTIMIZATION #endif __MBX_INLINE __mmask8 MB_MASK(int L) { return (L > 0) ? (__mmask8)0xFF : (__mmask8)0; } __MBX_INLINE __mmask64 SB_MASK1(int L, int REV) { if (L <= 0) return (__mmask64)0x0; if (L > PROC_LEN) L = PROC_LEN; if (REV) return (__mmask64)(0xFFFFFFFFFFFFFFFFULL << ((int)sizeof(__m512i) - L)); return (__mmask64)(0xFFFFFFFFFFFFFFFFULL >> ((int)sizeof(__m512i) - L)); } #ifndef BN_OPENSSL_DISABLE #include #if BN_OPENSSL_PATCH extern BN_ULONG* bn_get_words(const BIGNUM* bn); #endif #endif /* BN_OPENSSL_DISABLE */ /* // transpose 8 SB into MB including (reverse bytes and) radix 2^64 => 2^52 conversion // // covers: // - 8 BIGNUM -> mb8 // - 8 BNU -> mb8 // - 8 hex strings -> mb8 */ DISABLE_OPTIMIZATION __MBX_INLINE void transform_8sb_to_mb8(U64 out_mb8[], int bitLen, int8u *inp[8], int inpLen[8], int flag) { // inverse bytes (reverse=1) const __m512i bswap_mask = _mm512_set_epi64( 0x0001020304050607, 0x08090a0b0c0d0e0f, 0x1011121314151617, 0x18191a1b1c1d1e1f, 0x2021222324252627, 0x28292a2b2c2d2e2f, 0x3031323334353637, 0x38393a3b3c3d3e3f); // repeat words const __m512i idx16 = _mm512_set_epi64( 0x0019001800170016, 0x0016001500140013, 0x0013001200110010, 0x0010000f000e000d, 0x000c000b000a0009, 0x0009000800070006, 0x0006000500040003, 0x0003000200010000); // shift right const __m512i shiftR = _mm512_set_epi64( 12, 8, 4, 0, 12, 8, 4, 0); // radix 2^52 mask of digits __m512i digMask = _mm512_set1_epi64(DIGIT_MASK); int bytesRev = flag & BYTES_REV; /* reverse flag */ int radixCvt = flag & RADIX_CVT; /* radix (64->52) conversion assumed*/ int inpBytes = NUMBER_OF_DIGITS(bitLen, 8); /* bytes */ int outDigits = NUMBER_OF_DIGITS(bitLen, DIGIT_SIZE); /* digits */ int i; for (i = 0; inpBytes > 0; i += PROC_LEN, inpBytes -= PROC_LEN, out_mb8 += 8) { int sbidx = bytesRev ? inpBytes - (int)sizeof(__m512i) : i; __m512i X0 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[0] - i, bytesRev), (__m512i*)&inp[0][sbidx]); __m512i X1 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[1] - i, bytesRev), (__m512i*)&inp[1][sbidx]); __m512i X2 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[2] - i, bytesRev), (__m512i*)&inp[2][sbidx]); __m512i X3 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[3] - i, bytesRev), (__m512i*)&inp[3][sbidx]); __m512i X4 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[4] - i, bytesRev), (__m512i*)&inp[4][sbidx]); __m512i X5 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[5] - i, bytesRev), (__m512i*)&inp[5][sbidx]); __m512i X6 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[6] - i, bytesRev), (__m512i*)&inp[6][sbidx]); __m512i X7 = _mm512_maskz_loadu_epi8(SB_MASK1(inpLen[7] - i, bytesRev), (__m512i*)&inp[7][sbidx]); if (bytesRev) { X0 = _mm512_permutexvar_epi8(bswap_mask, X0); X1 = _mm512_permutexvar_epi8(bswap_mask, X1); X2 = _mm512_permutexvar_epi8(bswap_mask, X2); X3 = _mm512_permutexvar_epi8(bswap_mask, X3); X4 = _mm512_permutexvar_epi8(bswap_mask, X4); X5 = _mm512_permutexvar_epi8(bswap_mask, X5); X6 = _mm512_permutexvar_epi8(bswap_mask, X6); X7 = _mm512_permutexvar_epi8(bswap_mask, X7); } if (radixCvt) { X0 = _mm512_permutexvar_epi16(idx16, X0); X0 = _mm512_srlv_epi64(X0, shiftR); X0 = _mm512_and_si512(X0, digMask); /* probably exceeded instruction */ X1 = _mm512_permutexvar_epi16(idx16, X1); X1 = _mm512_srlv_epi64(X1, shiftR); X1 = _mm512_and_si512(X1, digMask); X2 = _mm512_permutexvar_epi16(idx16, X2); X2 = _mm512_srlv_epi64(X2, shiftR); X2 = _mm512_and_si512(X2, digMask); X3 = _mm512_permutexvar_epi16(idx16, X3); X3 = _mm512_srlv_epi64(X3, shiftR); X3 = _mm512_and_si512(X3, digMask); X4 = _mm512_permutexvar_epi16(idx16, X4); X4 = _mm512_srlv_epi64(X4, shiftR); X4 = _mm512_and_si512(X4, digMask); X5 = _mm512_permutexvar_epi16(idx16, X5); X5 = _mm512_srlv_epi64(X5, shiftR); X5 = _mm512_and_si512(X5, digMask); X6 = _mm512_permutexvar_epi16(idx16, X6); X6 = _mm512_srlv_epi64(X6, shiftR); X6 = _mm512_and_si512(X6, digMask); X7 = _mm512_permutexvar_epi16(idx16, X7); X7 = _mm512_srlv_epi64(X7, shiftR); X7 = _mm512_and_si512(X7, digMask); } // transpose 8 digits at a time TRANSPOSE_8xI64x8(X0, X1, X2, X3, X4, X5, X6, X7); // store transposed digits _mm512_mask_storeu_epi64(&out_mb8[0], MB_MASK(outDigits--), X0); _mm512_mask_storeu_epi64(&out_mb8[1], MB_MASK(outDigits--), X1); _mm512_mask_storeu_epi64(&out_mb8[2], MB_MASK(outDigits--), X2); _mm512_mask_storeu_epi64(&out_mb8[3], MB_MASK(outDigits--), X3); _mm512_mask_storeu_epi64(&out_mb8[4], MB_MASK(outDigits--), X4); _mm512_mask_storeu_epi64(&out_mb8[5], MB_MASK(outDigits--), X5); _mm512_mask_storeu_epi64(&out_mb8[6], MB_MASK(outDigits--), X6); _mm512_mask_storeu_epi64(&out_mb8[7], MB_MASK(outDigits--), X7); } } #ifndef BN_OPENSSL_DISABLE // Convert BIGNUM into MB8(Radix=2^52) format // Returns bitmask of successfully converted values // Accepts NULLs as BIGNUM inputs // Null or wrong length int8u ifma_BN_to_mb8(int64u out_mb8[][8], const BIGNUM* const bn[8], int bitLen) { // check input input length assert((0 0); int byteLens[8]; int byteLen = NUMBER_OF_DIGITS(bitLen, 8); int i; for (i = 0; i < 8; ++i) byteLens[i] = (NULL != bn[i]) ? byteLen : 0; transform_8sb_to_mb8((U64*)out_mb8, bitLen, (int8u**)bn, byteLens, RADIX_CVT); return _mm512_cmpneq_epi64_mask(_mm512_loadu_si512((__m512i*)bn), _mm512_setzero_si512()); } int8u ifma_HexStr8_to_mb8(int64u out_mb8[][8], const int8u* const pStr[8], int bitLen) { // check input parameters assert(bitLen > 0); int byteLens[8]; int byteLen = NUMBER_OF_DIGITS(bitLen, 8); int i; for (i = 0; i < 8; i++) byteLens[i] = (NULL != pStr[i]) ? byteLen : 0; transform_8sb_to_mb8((U64*)out_mb8, bitLen, (int8u**)pStr, byteLens, RADIX_CVT | BYTES_REV); return _mm512_cmpneq_epi64_mask(_mm512_loadu_si512((__m512i*)pStr), _mm512_setzero_si512()); } //////////////////////////////////////////////////////////////////////////////////////////////////// /* // transpose MB into 8 SB including (reverse bytes and) radix 2^52 => 2^64 conversion // // covers: // - mb8 -> 8 BNU // - mb8 -> 8 hex strings */ DISABLE_OPTIMIZATION __MBX_INLINE void transform_mb8_to_8sb(int8u* out[8], int outLen[8], const U64 inp_mb8[], int bitLen, int flag) { // inverse bytes (reverse=1) const __m512i bswap_mask = _mm512_set_epi64( 0x0001020304050607, 0x08090a0b0c0d0e0f, 0x1011121314151617, 0x18191a1b1c1d1e1f, 0x2021222324252627, 0x28292a2b2c2d2e2f, 0x3031323334353637, 0x38393a3b3c3d3e3f); const __m512i shiftL = _mm512_set_epi64(4, 0, 4, 0, 4, 0, 4, 0); const __m512i permutation1 = _mm512_set_epi64(0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3e3d3c3b, // {63,63,63,63,62,61,60,59} 0x3737363534333231, // {55,55,54,53,52,51,50,49} 0x302e2d2c2b2a2928, // {48,46,45,44,43,42,41,40} 0x1f1f1f1f1f1f1e1d, // {31,31,31,31,31,31,30,29} 0x1717171716151413, // {23,23,23,23,22,21,20,19} 0x0f0f0f0e0d0c0b0a, // {15,15,15,14,13,12,11,10} 0x0706050403020100); // { 7, 6, 5, 4, 3, 2, 1, 0} const __m512i permutation2 = _mm512_set_epi64(0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3a39383737373737, // {58,57,56,55,55,55,55,55} 0x2727272727272726, // {39,39,39,39,39,39,39,38} 0x2524232221201f1f, // {37,36,35,34,33,32,31,31} 0x1c1b1a1918171717, // {28,27,26,25,24,23,23,23} 0x1211100f0f0f0f0f, // {18,17,16,15,15,15,15,15} 0x0908070707070707); // { 9, 8, 7, 7, 7, 7, 7, 7} int bytesRev = flag & BYTES_REV; /* reverse flag */ int radixCvt = flag & RADIX_CVT; /* radix (52->64) conversion assumed */ int inpDigits = NUMBER_OF_DIGITS(bitLen, DIGIT_SIZE); /* digits */ int outBytes = NUMBER_OF_DIGITS(bitLen, 8); /* bytes */ int i; for (i = 0; outBytes > 0; i += PROC_LEN, outBytes -= PROC_LEN, inp_mb8 += 8) { int sbidx = bytesRev ? outBytes - (int)sizeof(__m512i) : i; __m512i X0 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[0]); __m512i X1 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[1]); __m512i X2 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[2]); __m512i X3 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[3]); __m512i X4 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[4]); __m512i X5 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[5]); __m512i X6 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[6]); __m512i X7 = _mm512_maskz_loadu_epi64(MB_MASK(inpDigits--), &inp_mb8[7]); // transpose 8 digits at a time TRANSPOSE_8xI64x8(X0, X1, X2, X3, X4, X5, X6, X7); if (radixCvt) { __m512i T; X0 = _mm512_sllv_epi64(X0, shiftL); T = _mm512_permutexvar_epi8(permutation1, X0); X0 = _mm512_permutexvar_epi8(permutation2, X0); X0 = _mm512_or_si512(X0, T); X1 = _mm512_sllv_epi64(X1, shiftL); T = _mm512_permutexvar_epi8(permutation1, X1); X1 = _mm512_permutexvar_epi8(permutation2, X1); X1 = _mm512_or_si512(X1, T); X2 = _mm512_sllv_epi64(X2, shiftL); T = _mm512_permutexvar_epi8(permutation1, X2); X2 = _mm512_permutexvar_epi8(permutation2, X2); X2 = _mm512_or_si512(X2, T); X3 = _mm512_sllv_epi64(X3, shiftL); T = _mm512_permutexvar_epi8(permutation1, X3); X3 = _mm512_permutexvar_epi8(permutation2, X3); X3 = _mm512_or_si512(X3, T); X4 = _mm512_sllv_epi64(X4, shiftL); T = _mm512_permutexvar_epi8(permutation1, X4); X4 = _mm512_permutexvar_epi8(permutation2, X4); X4 = _mm512_or_si512(X4, T); X5 = _mm512_sllv_epi64(X5, shiftL); T = _mm512_permutexvar_epi8(permutation1, X5); X5 = _mm512_permutexvar_epi8(permutation2, X5); X5 = _mm512_or_si512(X5, T); X6 = _mm512_sllv_epi64(X6, shiftL); T = _mm512_permutexvar_epi8(permutation1, X6); X6 = _mm512_permutexvar_epi8(permutation2, X6); X6 = _mm512_or_si512(X6, T); X7 = _mm512_sllv_epi64(X7, shiftL); T = _mm512_permutexvar_epi8(permutation1, X7); X7 = _mm512_permutexvar_epi8(permutation2, X7); X7 = _mm512_or_si512(X7, T); } if (bytesRev) { X0 = _mm512_permutexvar_epi8(bswap_mask, X0); X1 = _mm512_permutexvar_epi8(bswap_mask, X1); X2 = _mm512_permutexvar_epi8(bswap_mask, X2); X3 = _mm512_permutexvar_epi8(bswap_mask, X3); X4 = _mm512_permutexvar_epi8(bswap_mask, X4); X5 = _mm512_permutexvar_epi8(bswap_mask, X5); X6 = _mm512_permutexvar_epi8(bswap_mask, X6); X7 = _mm512_permutexvar_epi8(bswap_mask, X7); } // store transposed digits _mm512_mask_storeu_epi8(out[0] + sbidx, SB_MASK1(outLen[0] - i, bytesRev), X0); _mm512_mask_storeu_epi8(out[1] + sbidx, SB_MASK1(outLen[1] - i, bytesRev), X1); _mm512_mask_storeu_epi8(out[2] + sbidx, SB_MASK1(outLen[2] - i, bytesRev), X2); _mm512_mask_storeu_epi8(out[3] + sbidx, SB_MASK1(outLen[3] - i, bytesRev), X3); _mm512_mask_storeu_epi8(out[4] + sbidx, SB_MASK1(outLen[4] - i, bytesRev), X4); _mm512_mask_storeu_epi8(out[5] + sbidx, SB_MASK1(outLen[5] - i, bytesRev), X5); _mm512_mask_storeu_epi8(out[6] + sbidx, SB_MASK1(outLen[6] - i, bytesRev), X6); _mm512_mask_storeu_epi8(out[7] + sbidx, SB_MASK1(outLen[7] - i, bytesRev), X7); } } int8u ifma_mb8_to_BNU(int64u* const out_bn[8], const int64u inp_mb8[][8], const int bitLen) { // Check input parameters assert(bitLen > 0); int bnu_bitlen = NUMBER_OF_DIGITS(bitLen, 64) * 64; // gres: output length is multiple 64 int byteLens[8]; int i; for (i = 0; i < 8; ++i) //gres: byteLens[i] = (NULL != out_bn[i]) ? NUMBER_OF_DIGITS(bitLen, 8) : 0; byteLens[i] = (NULL != out_bn[i]) ? NUMBER_OF_DIGITS(bnu_bitlen, 8) : 0; transform_mb8_to_8sb((int8u**)out_bn, byteLens, (U64*)inp_mb8, bitLen, RADIX_CVT); return _mm512_cmpneq_epi64_mask(_mm512_loadu_si512((__m512i*)out_bn), _mm512_setzero_si512()); } int8u ifma_mb8_to_HexStr8(int8u* const pStr[8], const int64u inp_mb8[][8], int bitLen) { // check input parameters assert(bitLen > 0); int byteLens[8]; int byteLen = NUMBER_OF_DIGITS(bitLen, 8); int i; for (i = 0; i < 8; i++) byteLens[i] = (NULL != pStr[i]) ? byteLen : 0; transform_mb8_to_8sb((int8u**)pStr, byteLens, (U64*)inp_mb8, bitLen, RADIX_CVT | BYTES_REV); return _mm512_cmpneq_epi64_mask(_mm512_loadu_si512((__m512i*)pStr), _mm512_setzero_si512()); } //////////////////////////////////////////////////////////////////////////////////////////////////// /* // transpose 8 SB into MB without radix conversion // // covers: // - mb8 -> 8 BNU // - mb8 -> 8 hex strings */ DISABLE_OPTIMIZATION int8u ifma_BNU_transpose_copy(int64u out_mb8[][8], const int64u* const bn[8], int bitLen) { // Check input parameters assert(bitLen > 0); __mmask8 kbn[8]; int i; for (i = 0; i < 8; ++i) kbn[i] = (NULL == bn[i]) ? (__mmask8)0 : (__mmask8)0xFF; int len = NUMBER_OF_DIGITS(bitLen, 64); int n; for (n = 0; len > 0; n += 8, out_mb8 += 8) { __mmask8 kread = (len >= 8) ? 0xFF : (__mmask8)((1 << len) - 1); __m512i X0 = _mm512_maskz_loadu_epi64(kread & kbn[0], bn[0] + n); __m512i X1 = _mm512_maskz_loadu_epi64(kread & kbn[1], bn[1] + n); __m512i X2 = _mm512_maskz_loadu_epi64(kread & kbn[2], bn[2] + n); __m512i X3 = _mm512_maskz_loadu_epi64(kread & kbn[3], bn[3] + n); __m512i X4 = _mm512_maskz_loadu_epi64(kread & kbn[4], bn[4] + n); __m512i X5 = _mm512_maskz_loadu_epi64(kread & kbn[5], bn[5] + n); __m512i X6 = _mm512_maskz_loadu_epi64(kread & kbn[6], bn[6] + n); __m512i X7 = _mm512_maskz_loadu_epi64(kread & kbn[7], bn[7] + n); TRANSPOSE_8xI64x8(X0, X1, X2, X3, X4, X5, X6, X7); _mm512_mask_storeu_epi64(&out_mb8[0], MB_MASK(len--), X0); _mm512_mask_storeu_epi64(&out_mb8[1], MB_MASK(len--), X1); _mm512_mask_storeu_epi64(&out_mb8[2], MB_MASK(len--), X2); _mm512_mask_storeu_epi64(&out_mb8[3], MB_MASK(len--), X3); _mm512_mask_storeu_epi64(&out_mb8[4], MB_MASK(len--), X4); _mm512_mask_storeu_epi64(&out_mb8[5], MB_MASK(len--), X5); _mm512_mask_storeu_epi64(&out_mb8[6], MB_MASK(len--), X6); _mm512_mask_storeu_epi64(&out_mb8[7], MB_MASK(len--), X7); } return _mm512_cmpneq_epi64_mask(_mm512_loadu_si512((__m512i*)bn), _mm512_setzero_si512()); } #ifndef BN_OPENSSL_DISABLE DISABLE_OPTIMIZATION int8u ifma_BN_transpose_copy(int64u out_mb8[][8], const BIGNUM* const bn[8], int bitLen) { // check input length assert((0 0; n += 8, out_mb8 += 8) { __mmask8 k = (len >= 8) ? 0xFF : (1 << len) - 1; __m512i X0 = _mm512_maskz_loadu_epi64(k & kbn[0], inp[0]+n); __m512i X1 = _mm512_maskz_loadu_epi64(k & kbn[1], inp[1]+n); __m512i X2 = _mm512_maskz_loadu_epi64(k & kbn[2], inp[2]+n); __m512i X3 = _mm512_maskz_loadu_epi64(k & kbn[3], inp[3]+n); __m512i X4 = _mm512_maskz_loadu_epi64(k & kbn[4], inp[4]+n); __m512i X5 = _mm512_maskz_loadu_epi64(k & kbn[5], inp[5]+n); __m512i X6 = _mm512_maskz_loadu_epi64(k & kbn[6], inp[6]+n); __m512i X7 = _mm512_maskz_loadu_epi64(k & kbn[7], inp[7]+n); TRANSPOSE_8xI64x8(X0, X1, X2, X3, X4, X5, X6, X7); _mm512_mask_storeu_epi64(&out_mb8[0], MB_MASK(len--), X0); _mm512_mask_storeu_epi64(&out_mb8[1], MB_MASK(len--), X1); _mm512_mask_storeu_epi64(&out_mb8[2], MB_MASK(len--), X2); _mm512_mask_storeu_epi64(&out_mb8[3], MB_MASK(len--), X3); _mm512_mask_storeu_epi64(&out_mb8[4], MB_MASK(len--), X4); _mm512_mask_storeu_epi64(&out_mb8[5], MB_MASK(len--), X5); _mm512_mask_storeu_epi64(&out_mb8[6], MB_MASK(len--), X6); _mm512_mask_storeu_epi64(&out_mb8[7], MB_MASK(len--), X7); } return _mm512_cmpneq_epi64_mask(_mm512_loadu_si512((__m512i*)bn), _mm512_setzero_si512()); } #endif /* BN_OPENSSL_DISABLE */ #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #define PROC_LEN2 (PROC_LEN / 2) #ifndef BN_OPENSSL_DISABLE #include #if BN_OPENSSL_PATCH extern BN_ULONG* bn_get_words(const BIGNUM* bn); #endif #endif /* BN_OPENSSL_DISABLE */ __MBX_INLINE void transpose_4x64bx4(__m256i *w0, __m256i *w1, __m256i *w2, __m256i *w3) { const __m256i r0 = _mm256_permute2x128_si256(*w0, *w2, 0x20); const __m256i r1 = _mm256_permute2x128_si256(*w1, *w3, 0x20); const __m256i r2 = _mm256_permute2x128_si256(*w0, *w2, 0x31); const __m256i r3 = _mm256_permute2x128_si256(*w1, *w3, 0x31); /* * Structure at this point: * r0 = {c1 c0 a1 a0} * r1 = {d1 d0 b1 b0} * r2 = {c3 c2 a3 a2} * r3 = {d3 d2 b3 b2} */ *w0 = _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(r0), _mm256_castsi256_ps(r1), 0x44)); *w1 = _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(r0), _mm256_castsi256_ps(r1), 0xee)); *w2 = _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(r2), _mm256_castsi256_ps(r3), 0x44)); *w3 = _mm256_castps_si256(_mm256_shuffle_ps(_mm256_castsi256_ps(r2), _mm256_castsi256_ps(r3), 0xee)); /* * Output structure: * w0 = {d0 c0 b0 a0} * w1 = {d1 c1 b1 a1} * w2 = {d2 c2 b2 a2} * w3 = {d3 c3 b3 a3} */ } #if defined(_MSC_VER) && !defined(__clang__) #pragma optimize( "", off ) #endif MBX_ZEROING_FUNC_ATTRIBUTES void zero_u256(int8u *buffer) { #if defined(__GNUC__) // Avoid dead code elimination for GNU compilers ASM(""); #endif _mm256_storeu_si256((__m256i *)buffer, _mm256_setzero_si256()); } #if defined(_MSC_VER) && !defined(__clang__) #pragma optimize( "", on ) #endif /* // transpose 4 SB into MB including (reverse bytes and) radix 2^64 => 2^52 conversion // // covers: // - 4 BIGNUM -> mb4 // - 4 BNU -> mb4 // - 4 hex strings -> mb4 */ __MBX_INLINE void transform_4sb_to_mb4(U64 out_mb4[], const int bitLen, const int8u *inp[4], int inpLen[4], const int flag) { const int bytesRev = flag & BYTES_REV; /* reverse flag */ const int radixCvt = flag & RADIX_CVT; /* radix (64->52) conversion assumed*/ int inpBytes = NUMBER_OF_DIGITS(bitLen, 8); /* bytes */ int outDigits = NUMBER_OF_DIGITS(bitLen, DIGIT_SIZE); /* digits */ __m256i *out_mb4_simd = (__m256i *) out_mb4; for (int i = 0; inpBytes > 0; i += PROC_LEN2, inpBytes -= PROC_LEN2, out_mb4_simd += 4) { __m256i X[4]; if (bytesRev) { // inverse bytes (reverse=1) const int sbidx = inpBytes; #define BUFFER_LEN ((PROC_LEN2 + 31) & (~31)) int8u buffer[BUFFER_LEN]; for (int k = 0; k < 4; k++) { if (i >= inpLen[k]) { X[k] = _mm256_setzero_si256(); continue; } const int L1 = inpLen[k] - i; const int L2 = L1 > PROC_LEN2 ? PROC_LEN2 : L1; const int8u *ptr = &inp[k][sbidx - L2]; const __m128i swap_mask = _mm_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f); /* * load [ 0..15 | xx xx xx xx xx xx A6 A7 A8 A9 AA AB AC AD AE AF] * [16..31 | B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF] */ if (L2 != PROC_LEN2) { PadBlock(0, buffer, PROC_LEN2 - L2); CopyBlock(ptr, &buffer[PROC_LEN2 - L2], L2); ptr = buffer; } __m128i t128a = _mm_loadu_si128((const __m128i *) &ptr[0]); __m128i t128b = _mm_loadu_si128((const __m128i *) &ptr[10]); t128a = _mm_bslli_si128(t128a, 6); t128a = _mm_shuffle_epi8(t128a, swap_mask); t128b = _mm_shuffle_epi8(t128b, swap_mask); /* * store [ 0..15 | BF BE BD BC BB BA B9 B8 B7 B6 B5 B4 B3 B2 B1 B0] * [16..31 | AF AE AD AC AB AA A9 A8 A7 A6 xx xx xx xx xx xx] */ X[k] = _mm256_inserti128_si256(_mm256_castsi128_si256(t128b), t128a, 1); } zero_u256(buffer); } else { const int sbidx = i; for (int k = 0; k < 4; k++) { if (i >= inpLen[k]) { X[k] = _mm256_setzero_si256(); continue; } const int L1 = inpLen[k] - i; const int L2 = L1 > PROC_LEN2 ? PROC_LEN2 : L1; if (L2 == PROC_LEN2) { const int8u *ptr = &inp[k][sbidx]; const __m128i t128a = _mm_loadu_si128((const __m128i *) &ptr[0]); __m128i t128b = _mm_loadu_si128((const __m128i *) &ptr[10]); t128b = _mm_bsrli_si128(t128b, 6); X[k] = _mm256_inserti128_si256(_mm256_castsi128_si256(t128a), t128b, 1); } else { __m256i buffer = _mm256_setzero_si256(); CopyBlock(&inp[k][sbidx], &buffer, L2); X[k] = buffer; } } } if (radixCvt) { // convert consecutive 26 bytes spread across X[i] into // 4 x 64 bit words, each word consisting of: // bits 63:52 - zero // bits 51:0 - message // shift right const __m256i shiftRight = _mm256_set_epi64x(4, 0, 4, 0); // radix 2^52 mask of digits const __m256i mask52b = _mm256_set1_epi64x(DIGIT_MASK); // repeat one byte const __m128i cvt104b_2x52b = _mm_set_epi8(0xff, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0xff, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00); for (int k = 0; k < 4; k++) { // split 32 bytes into 2 x 16 bytes const __m128i l0 = _mm256_castsi256_si128(X[k]); const __m128i l1 = _mm256_extracti128_si256(X[k], 1); // use alignr to create 4 x (2 x 52 bits) data chunks const __m128i l0_13b = _mm_shuffle_epi8(l0, cvt104b_2x52b); const __m128i l1_13b = _mm_shuffle_epi8(_mm_alignr_epi8(l1, l0, 1*13), cvt104b_2x52b); // put back the chunks into 32 byte chunks const __m256i l01_26b = _mm256_inserti128_si256(_mm256_castsi128_si256(l0_13b), l1_13b, 1); // do the final shift right and & before storing into the buffer X[k] = _mm256_and_si256(_mm256_srlv_epi64(l01_26b, shiftRight), mask52b); } } /* * X[0] = A0 A1 A2 A3 * X[1] = B0 B1 B2 B3 * X[2] = C0 C1 C2 C3 * X[3] = D0 D1 D2 D3 */ transpose_4x64bx4(&X[0], &X[1], &X[2], &X[3]); /* * X[0] = A0 B0 C0 D0 * X[1] = A1 B1 C1 D1 * X[2] = A2 B2 C2 D2 * X[3] = A3 B3 C3 D3 */ // store transposed digits for (int k = 0; (k < 4) && (outDigits > 0); k++, outDigits--) _mm256_storeu_si256((__m256i *) &out_mb4_simd[k], X[k]); } } #ifndef BN_OPENSSL_DISABLE // Convert BIGNUM into MB4(Radix=2^52) format // Returns bitmask of successfully converted values // Accepts NULLs as BIGNUM inputs // Null or wrong length int8u ifma_BN_to_mb4(int64u out_mb4[][4], const BIGNUM* const bn[4], int bitLen) { // check input input length assert((0 0); int byteLens[4]; int byteLen = NUMBER_OF_DIGITS(bitLen, 8); int8u retVal = 0; int i; for (i = 0; i < 4; ++i) { if (NULL != bn[i]) { byteLens[i] = byteLen; retVal |= (1 << i); } else { byteLens[i] = 0; } } transform_4sb_to_mb4((U64*)out_mb4, bitLen, (const int8u**)bn, byteLens, RADIX_CVT); return retVal; } int8u ifma_HexStr4_to_mb4(int64u out_mb4[][4], const int8u* const pStr[4], int bitLen) { // check input parameters assert(bitLen > 0); int byteLens[4]; int byteLen = NUMBER_OF_DIGITS(bitLen, 8); int i; int8u retVal = 0; for (i = 0; i < 4; i++) { if (NULL != pStr[i]) { byteLens[i] = byteLen; retVal |= (1 << i); } else { byteLens[i] = 0; } } transform_4sb_to_mb4((U64*)out_mb4, bitLen, (const int8u**)pStr, byteLens, RADIX_CVT | BYTES_REV); return retVal; } //////////////////////////////////////////////////////////////////////////////////////////////////// /* // transpose MB into 4 SB including (reverse bytes and) radix 2^52 => 2^64 conversion // // covers: // - mb4 -> 4 BNU // - mb4 -> 4 hex strings */ __MBX_INLINE void transform_mb4_to_4sb(int8u* out[4], int outLen[4], const U64 inp_mb4[], const int bitLen, const int flag) { const int bytesRev = flag & BYTES_REV; /* reverse flag */ const int radixCvt = flag & RADIX_CVT; /* radix (52->64) conversion assumed */ int inpDigits = NUMBER_OF_DIGITS(bitLen, DIGIT_SIZE); /* digits */ int outBytes = NUMBER_OF_DIGITS(bitLen, 8); /* bytes */ const __m256i *inp_mb4_simd = (const __m256i *) inp_mb4; for (int i = 0; outBytes > 0; i += PROC_LEN2, outBytes -= PROC_LEN2, inp_mb4_simd += 4) { __m256i X[4] = {}; /* * Load & transpose. Initial layout: * * A0 B0 C0 D0 * A1 B1 C1 D1 * A2 B2 C2 D2 * A3 B3 C3 D3 */ for (int n = 0; (n < 4) && (inpDigits > 0); n++, inpDigits--) X[n] = _mm256_loadu_si256((const __m256i *) &inp_mb4_simd[n]); /* * X[0] = A0 B0 C0 D0 * X[1] = A1 B1 C1 D1 * X[2] = A2 B2 C2 D2 * X[3] = A3 B3 C3 D3 */ transpose_4x64bx4(&X[0], &X[1], &X[2], &X[3]); /* * X[0] = A0 A1 A2 A3 * X[1] = B0 B1 B2 B3 * X[2] = C0 C1 C2 C3 * X[3] = D0 D1 D2 D3 */ if (radixCvt) { // convert 4 x 64 bit words spread across X[i] into // consecutive 4 x 52 bit words: // shift left const __m256i shiftLeft = _mm256_set_epi64x(4, 0, 4, 0); // radix 2^52 mask of digits const __m256i mask52b = _mm256_set_epi64x(0, DIGIT_MASK, 0, DIGIT_MASK); // repeat one byte const __m256i shift_2nd_52b = _mm256_set_epi8(0xff, 0xff, 0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff); for (int n = 0; n < 4; n++) { const __m256i a0 = _mm256_sllv_epi64(X[n], shiftLeft); const __m256i b0 = _mm256_shuffle_epi8(a0, shift_2nd_52b); const __m256i c0 = _mm256_and_si256(a0, mask52b); const __m256i d0 = _mm256_or_si256(b0, c0); const __m128i l0 = _mm256_castsi256_si128(d0); const __m128i l1 = _mm256_extracti128_si256(d0, 1); /* m0 = l1[2..0] | l0 */ const __m128i m0 = _mm_alignr_epi8(l1, _mm_bslli_si128(l0, 3), 3); /* m1 = ZERO | l1[12..3] */ const __m128i m1 = _mm_alignr_epi8(_mm_setzero_si128(), _mm_bslli_si128(l1, 3), 6); X[n] = _mm256_inserti128_si256(_mm256_castsi128_si256(m0), m1, 1); } } // store transposed digits if (bytesRev) { for (int n = 0; n < 4; n++) { const int L1 = outLen[n] - i; if (L1 <= 0) continue; const int L2 = (L1 > PROC_LEN2) ? PROC_LEN2 : L1; const int sbidx = outBytes - L2; int8u *ptr = out[n] + sbidx; // inverse bytes (reverse=1) const __m256i swap_mask = _mm256_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f); const __m256i t256ab = _mm256_shuffle_epi8(X[n], swap_mask); const __m256i t256ba = _mm256_permute4x64_epi64(t256ab, 0x4e); X[n] = t256ba; if (L2 == PROC_LEN) { _mm_storeu_si128((__m128i *) &ptr[0],_mm256_castsi256_si128(X[n])); *((int64u *) &ptr[16]) = _mm256_extract_epi64(X[n], 2); *((int16u *) &ptr[24]) = _mm256_extract_epi16(X[n], 12); } else { union { int8u buffer[32]; __m256i x256; } u; u.x256 = X[n]; CopyBlock(&u.buffer[32 - L2], ptr, L2); } } } else { const int sbidx = i; for (int n = 0; n < 4; n++) { const int L1 = outLen[n] - i; if (L1 <= 0) continue; const int L2 = L1 > PROC_LEN2 ? PROC_LEN2 : L1; int8u *ptr = out[n] + sbidx; if (L2 == PROC_LEN2) { _mm_storeu_si128((__m128i *) &ptr[0],_mm256_castsi256_si128(X[n])); *((int64u *) &ptr[16]) = _mm256_extract_epi64(X[n], 2); *((int16u *) &ptr[24]) = _mm256_extract_epi16(X[n], 12); } else { union { int8u buffer[32]; __m256i x256; } u; u.x256 = X[n]; CopyBlock(&u.buffer[0], ptr, L2); } } } // bytesRev } } int8u ifma_mb4_to_BNU(int64u* const out_bn[4], const int64u inp_mb4[][4], const int bitLen) { // Check input parameters assert(bitLen > 0); const int bnu_bitlen = NUMBER_OF_DIGITS(bitLen, 64) * 64; // gres: output length is multiple 64 int byteLens[4]; int8u retVal = 0; int i; for (i = 0; i < 4; ++i) { if (NULL != out_bn[i]) { byteLens[i] = NUMBER_OF_DIGITS(bnu_bitlen, 8); retVal |= (1 << i); } else { byteLens[i] = 0; } } transform_mb4_to_4sb((int8u**)out_bn, byteLens, (U64*)inp_mb4, bitLen, RADIX_CVT); return retVal; } int8u ifma_mb4_to_HexStr4(int8u* const pStr[4], const int64u inp_mb4[][4], int bitLen) { // check input parameters assert(bitLen > 0); int byteLens[4]; const int byteLen = NUMBER_OF_DIGITS(bitLen, 8); int8u retVal = 0; int i; for (i = 0; i < 4; i++) { if (NULL != pStr[i]) { byteLens[i] = byteLen; retVal |= (1 << i); } else { byteLens[i] = 0; } } transform_mb4_to_4sb((int8u**)pStr, byteLens, (U64*)inp_mb4, bitLen, RADIX_CVT | BYTES_REV); return retVal; } //////////////////////////////////////////////////////////////////////////////////////////////////// /* // transpose 4 SB into MB without radix conversion // // covers: // - mb4 -> 8 BNU // - mb4 -> 8 hex strings */ int8u ifma_BNU_transpose_copy_mb4(int64u out_mb4[][4], const int64u* const bn[4], const int bitLen) { // Check input parameters assert(bitLen > 0); int8u ret = 0; for (int i = 0; i < 4; ++i) if (NULL != bn[i]) ret |= (1 << i); int len = NUMBER_OF_DIGITS(bitLen, 64); for (int n = 0; len > 0; n += 4, out_mb4 += 4) { __m256i X[4]; const int L1 = (len > 4) ? 4 : len; for (int k = 0; k < 4; k++) { if (bn[k] == NULL) { X[k] = _mm256_setzero_si256(); continue; } if (L1 == 4) { X[k] = _mm256_loadu_si256((const __m256i *) &bn[k][n]); continue; } const int64u mask[2 * 8] = { 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL }; const __m256i m1 = _mm256_loadu_si256((const __m256i *) &mask[8 - L1]); X[k] = _mm256_maskload_epi64((const void *) &bn[k][n], m1); } /* * X[0] = A0 A1 A2 A3 * X[1] = B0 B1 B2 B3 * X[2] = C0 C1 C2 C3 * X[3] = D0 D1 D2 D3 */ transpose_4x64bx4(&X[0], &X[1], &X[2], &X[3]); /* * X[0] = A0 B0 C0 D0 * X[1] = A1 B1 C1 D1 * X[2] = A2 B2 C2 D2 * X[3] = A3 B3 C3 D4 */ // store transposed digits for (int k = 0; (k < 4) && (len > 0); k++, len--) _mm256_storeu_si256((__m256i *) &out_mb4[k], X[k]); } return ret; } #ifndef BN_OPENSSL_DISABLE int8u ifma_BN_transpose_copy_mb4(int64u out_mb4[][4], const BIGNUM* const bn[4], const int bitLen) { // check input length assert((0 0; n += 4, out_mb4 += 4) { __m256i X[4]; const int L1 = (len > 4) ? 4 : len; for (int k = 0; k < 4; k++) { if (inp[k] == NULL) { X[k] = _mm256_setzero_si256(); continue; } if (L1 == 4) { X[k] = _mm256_loadu_si256((const __m256i *) &inp[k][n]); continue; } const int64u mask[2 * 8] = { 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 1ULL << 63, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL, 0ULL }; const __m256i m1 = _mm256_loadu_si256((const __m256i *) &mask[8 - L1]); X[k] = _mm256_maskload_epi64((const void *) &inp[k][n], m1); } /* * X[0] = A0 A1 A2 A3 * X[1] = B0 B1 B2 B3 * X[2] = C0 C1 C2 C3 * X[3] = D0 D1 D2 D3 */ transpose_4x64bx4(&X[0], &X[1], &X[2], &X[3]); /* * X[0] = A0 B0 C0 D0 * X[1] = A1 B1 C1 D1 * X[2] = A2 B2 C2 D2 * X[3] = A3 B3 C3 D4 */ // store transposed digits for (int k = 0; (k < 4) && (len > 0); k++, len--) _mm256_storeu_si256((__m256i *) &out_mb4[k], X[k]); } return ret; } #endif /* BN_OPENSSL_DISABLE */ #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/common/ifma_version.c000066400000000000000000000041661470420105600301420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 #define MBX_LIB_VERSION() MBX_VER_MAJOR,MBX_VER_MINOR,MBX_VER_PATCH #define MBX_LIB_BUILD() __DATE__ #define STR2(x) #x #define STR(x) STR2(x) #if ( _MBX >= _MBX_K1 ) /* Intel® Advanced Vector Extensions 512 (Intel® AVX-512) (formerly Icelake) - intel64 */ #define MBX_LIB_CPU_TYPE() "k1" #else /* Intel® Advanced Vector Extensions 2 (Intel® AVX2) - intel64 */ #define MBX_LIB_CPU_TYPE() "l9" #endif #define MBX_STR_VERSION() MBX_LIB_NAME() " (" MBX_LIB_CPU_TYPE() ")" \ " (ver: " STR(MBX_VER_MAJOR) "." STR(MBX_VER_MINOR) "." STR(MBX_VER_PATCH) " (" \ STR(MBX_INTERFACE_VERSION_MAJOR)"."STR(MBX_INTERFACE_VERSION_MINOR)")" \ " build: " MBX_LIB_BUILD()")" /* version info */ static const mbxVersion mbxLibVer = { MBX_LIB_VERSION(), /* major, minor, patch */ MBX_LIB_CPU_TYPE(), /* target CPU */ MBX_LIB_NAME() " (" MBX_LIB_CPU_TYPE() ")", /* lib name */ MBX_LIB_BUILD(), /* build date */ MBX_STR_VERSION() /* version str */ }; DLL_PUBLIC const mbxVersion* OWNAPI(mbx_getversion)(void) { return &mbxLibVer; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/000077500000000000000000000000001470420105600253035ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_m256.c000066400000000000000000000260771470420105600303370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /*===================================================================== General 256-bit operations - sqr & mul =====================================================================*/ void MB_FUNC_NAME(ifma_amm52x5_)(U64 R[], const U64 inpA[], const U64 inpB[], const U64 inpM[], const int64u* k0_mb) { U64 res00, res01, res02, res03, res04; U64 K = loadu64(k0_mb); /* k0[] */ int itr; res00 = res01 = res02 = res03 = res04 = get_zero64(); for (itr = 0; itr < P256_LEN52; itr++) { U64 Yi; U64 Bi = loadu64(inpB); inpB++; res00 = fma52lo(res00, Bi, inpA[0]); res01 = fma52lo(res01, Bi, inpA[1]); res02 = fma52lo(res02, Bi, inpA[2]); res03 = fma52lo(res03, Bi, inpA[3]); res04 = fma52lo(res04, Bi, inpA[4]); Yi = fma52lo(get_zero64(), res00, K); res00 = fma52lo(res00, Yi, inpM[0]); res01 = fma52lo(res01, Yi, inpM[1]); res02 = fma52lo(res02, Yi, inpM[2]); res03 = fma52lo(res03, Yi, inpM[3]); res04 = fma52lo(res04, Yi, inpM[4]); res00 = srli64(res00, DIGIT_SIZE); res01 = add64 (res01, res00); res00 = fma52hi(res01, Bi, inpA[0]); res01 = fma52hi(res02, Bi, inpA[1]); res02 = fma52hi(res03, Bi, inpA[2]); res03 = fma52hi(res04, Bi, inpA[3]); res04 = fma52hi(get_zero64(), Bi, inpA[4]); res00 = fma52hi(res00, Yi, inpM[0]); res01 = fma52hi(res01, Yi, inpM[1]); res02 = fma52hi(res02, Yi, inpM[2]); res03 = fma52hi(res03, Yi, inpM[3]); res04 = fma52hi(res04, Yi, inpM[4]); } // normalization NORM_LSHIFTR(res0, 0, 1) NORM_LSHIFTR(res0, 1, 2) NORM_LSHIFTR(res0, 2, 3) NORM_LSHIFTR(res0, 3, 4) #if 0 // t = res -modulus and normalize U64 t0 = sub64(res00, inpM[0]); U64 t1 = sub64(res01, inpM[1]); U64 t2 = sub64(res02, inpM[2]); U64 t3 = sub64(res03, inpM[3]); U64 t4 = sub64(res04, inpM[4]); NORM_ASHIFTR(t, 0,1) NORM_ASHIFTR(t, 1,2) NORM_ASHIFTR(t, 2,3) NORM_ASHIFTR(t, 3,4) /* condition mov R[] = (t4>=0)? t : res */ __mb_mask cmask = cmp64_mask(t4, get_zero64(), _MM_CMPINT_GE); R[0] = cmov_U64(res00, t0, cmask); R[1] = cmov_U64(res01, t1, cmask); R[2] = cmov_U64(res02, t2, cmask); R[3] = cmov_U64(res03, t3, cmask); R[4] = cmov_U64(res04, t4, cmask); #endif R[0] = res00; R[1] = res01; R[2] = res02; R[3] = res03; R[4] = res04; } void MB_FUNC_NAME(ifma_ams52x5_)(U64 r[], const U64 a[], const U64 m[], const int64u* k0_mb) { U64 k = loadu64((U64*)k0_mb); U64 res0, res1, res2, res3, res4, res5, res6, res7, res8, res9; res0 = res1 = res2 = res3 = res4 = res5 = res6 = res7 = res8 = res9 = get_zero64(); // Calculate full square res1 = fma52lo(res1, a[0], a[1]); // Sum(1) res2 = fma52hi(res2, a[0], a[1]); // Sum(1) res2 = fma52lo(res2, a[0], a[2]); // Sum(2) res3 = fma52hi(res3, a[0], a[2]); // Sum(2) res3 = fma52lo(res3, a[1], a[2]); // Sum(3) res4 = fma52hi(res4, a[1], a[2]); // Sum(3) res3 = fma52lo(res3, a[0], a[3]); // Sum(3) res4 = fma52hi(res4, a[0], a[3]); // Sum(3) res4 = fma52lo(res4, a[1], a[3]); // Sum(4) res5 = fma52hi(res5, a[1], a[3]); // Sum(4) res5 = fma52lo(res5, a[2], a[3]); // Sum(5) res6 = fma52hi(res6, a[2], a[3]); // Sum(5) res4 = fma52lo(res4, a[0], a[4]); // Sum(4) res5 = fma52hi(res5, a[0], a[4]); // Sum(4) res5 = fma52lo(res5, a[1], a[4]); // Sum(5) res6 = fma52hi(res6, a[1], a[4]); // Sum(5) res6 = fma52lo(res6, a[2], a[4]); // Sum(6) res7 = fma52hi(res7, a[2], a[4]); // Sum(6) res7 = fma52lo(res7, a[3], a[4]); // Sum(7) res8 = fma52hi(res8, a[3], a[4]); // Sum(7) { res0 = add64(res0, res0); // Double(0) res1 = add64(res1, res1); // Double(1) res2 = add64(res2, res2); // Double(2) res3 = add64(res3, res3); // Double(3) res4 = add64(res4, res4); // Double(4) res5 = add64(res5, res5); // Double(5) res6 = add64(res6, res6); // Double(6) res7 = add64(res7, res7); // Double(7) res8 = add64(res8, res8); // Double(8) { res0 = fma52lo(res0, a[0], a[0]); // Add sqr(0) res1 = fma52hi(res1, a[0], a[0]); // Add sqr(0) res2 = fma52lo(res2, a[1], a[1]); // Add sqr(2) res3 = fma52hi(res3, a[1], a[1]); // Add sqr(2) res4 = fma52lo(res4, a[2], a[2]); // Add sqr(4) res5 = fma52hi(res5, a[2], a[2]); // Add sqr(4) res6 = fma52lo(res6, a[3], a[3]); // Add sqr(6) res7 = fma52hi(res7, a[3], a[3]); // Add sqr(6) res8 = fma52lo(res8, a[4], a[4]); // Add sqr(8) res9 = fma52hi(res9, a[4], a[4]); // Add sqr(8) } } // Reduction U64 u0 = mul52lo(res0,k); // Create u0 res0 = fma52lo(res0, u0, m[0]); res1 = fma52hi(res1, u0, m[0]); res1 = fma52lo(res1, u0, m[1]); res2 = fma52hi(res2, u0, m[1]); res1 = add64(res1, srli64(res0, DIGIT_SIZE)); U64 u1 = mul52lo(res1,k); res2 = fma52lo(res2, u0, m[2]); res3 = fma52hi(res3, u0, m[2]); res3 = fma52lo(res3, u0, m[3]); res4 = fma52hi(res4, u0, m[3]); res4 = fma52lo(res4, u0, m[4]); res5 = fma52hi(res5, u0, m[4]); // Create u1 res1 = fma52lo(res1, u1, m[0]); res2 = fma52hi(res2, u1, m[0]); res2 = fma52lo(res2, u1, m[1]); res3 = fma52hi(res3, u1, m[1]); res2 = add64(res2, srli64(res1, DIGIT_SIZE)); U64 u2 = mul52lo(res2,k); res3 = fma52lo(res3, u1, m[2]); res4 = fma52hi(res4, u1, m[2]); res4 = fma52lo(res4, u1, m[3]); res5 = fma52hi(res5, u1, m[3]); res5 = fma52lo(res5, u1, m[4]); res6 = fma52hi(res6, u1, m[4]); // Create u2 res2 = fma52lo(res2, u2, m[0]); res3 = fma52hi(res3, u2, m[0]); res3 = fma52lo(res3, u2, m[1]); res4 = fma52hi(res4, u2, m[1]); res3 = add64(res3, srli64(res2, DIGIT_SIZE)); U64 u3 = mul52lo(res3,k); res4 = fma52lo(res4, u2, m[2]); res5 = fma52hi(res5, u2, m[2]); res5 = fma52lo(res5, u2, m[3]); res6 = fma52hi(res6, u2, m[3]); res6 = fma52lo(res6, u2, m[4]); res7 = fma52hi(res7, u2, m[4]); // Create u3 res3 = fma52lo(res3, u3, m[0]); res4 = fma52hi(res4, u3, m[0]); res4 = fma52lo(res4, u3, m[1]); res5 = fma52hi(res5, u3, m[1]); res4 = add64(res4, srli64(res3, DIGIT_SIZE)); U64 u4 = mul52lo(res4,k); res5 = fma52lo(res5, u3, m[2]); res6 = fma52hi(res6, u3, m[2]); res6 = fma52lo(res6, u3, m[3]); res7 = fma52hi(res7, u3, m[3]); res7 = fma52lo(res7, u3, m[4]); res8 = fma52hi(res8, u3, m[4]); // Create u4 res4 = fma52lo(res4, u4, m[0]); res5 = fma52hi(res5, u4, m[0]); res5 = fma52lo(res5, u4, m[1]); res6 = fma52hi(res6, u4, m[1]); res5 = add64(res5, srli64(res4, DIGIT_SIZE)); res6 = fma52lo(res6, u4, m[2]); res7 = fma52hi(res7, u4, m[2]); res7 = fma52lo(res7, u4, m[3]); res8 = fma52hi(res8, u4, m[3]); res8 = fma52lo(res8, u4, m[4]); res9 = fma52hi(res9, u4, m[4]); // normalization NORM_LSHIFTR(res, 5, 6) NORM_LSHIFTR(res, 6, 7) NORM_LSHIFTR(res, 7, 8) NORM_LSHIFTR(res, 8, 9) #if 0 // {res0-4) = (res5-9) -modulus and normalize res0 = sub64(res5, m[0]); res1 = sub64(res6, m[1]); res2 = sub64(res7, m[2]); res3 = sub64(res8, m[3]); res4 = sub64(res9, m[4]); NORM_ASHIFTR(res, 0,1) NORM_ASHIFTR(res, 1,2) NORM_ASHIFTR(res, 2,3) NORM_ASHIFTR(res, 3,4) /* condition mov r[] = (res4>=0)? res(5 - 9) : res(0 - 4) */ __mb_mask cmask = cmp64_mask(res4, get_zero64(), _MM_CMPINT_GE); r[0] = cmov_U64(res5, res0, cmask); r[1] = cmov_U64(res6, res1, cmask); r[2] = cmov_U64(res7, res2, cmask); r[3] = cmov_U64(res8, res3, cmask); r[4] = cmov_U64(res9, res4, cmask); #endif r[0] = res5; r[1] = res6; r[2] = res7; r[3] = res8; r[4] = res9; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* R = (A+B) mod M */ void MB_FUNC_NAME(ifma_add52x5_)(U64 R[], const U64 A[], const U64 B[], const U64 M[]) { /* r = a + b */ U64 r0 = add64(A[0], B[0]); U64 r1 = add64(A[1], B[1]); U64 r2 = add64(A[2], B[2]); U64 r3 = add64(A[3], B[3]); U64 r4 = add64(A[4], B[4]); /* t = r - M */ U64 t0 = sub64(r0, M[0]); U64 t1 = sub64(r1, M[1]); U64 t2 = sub64(r2, M[2]); U64 t3 = sub64(r3, M[3]); U64 t4 = sub64(r4, M[4]); /* normalize r0, r1, r2, r3, r4 */ NORM_LSHIFTR(r, 0,1) NORM_LSHIFTR(r, 1,2) NORM_LSHIFTR(r, 2,3) NORM_LSHIFTR(r, 3,4) /* normalize t0, t1, t2, t3, t4 */ NORM_ASHIFTR(t, 0,1) NORM_ASHIFTR(t, 1,2) NORM_ASHIFTR(t, 2,3) NORM_ASHIFTR(t, 3,4) /* condition mask t4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(t4, get_zero64(), _MM_CMPINT_LT); R[0] = cmov_U64(t0, r0, cmask); R[1] = cmov_U64(t1, r1, cmask); R[2] = cmov_U64(t2, r2, cmask); R[3] = cmov_U64(t3, r3, cmask); R[4] = cmov_U64(t4, r4, cmask); } /* R = (A-B) mod M */ void MB_FUNC_NAME(ifma_sub52x5_)(U64 R[], const U64 A[], const U64 B[], const U64 M[]) { /* r = a-b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); /* t = r + M */ U64 t0 = add64(r0, M[0]); U64 t1 = add64(r1, M[1]); U64 t2 = add64(r2, M[2]); U64 t3 = add64(r3, M[3]); U64 t4 = add64(r4, M[4]); /* normalize r0, r1, r2, r3, r4 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) /* normalize t0, t1, t2, t3, t4 */ NORM_ASHIFTR(t, 0,1) NORM_ASHIFTR(t, 1,2) NORM_ASHIFTR(t, 2,3) NORM_ASHIFTR(t, 3,4) /* condition mask t4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(r4, get_zero64(), _MM_CMPINT_LT); R[0] = cmov_U64(r0, t0, cmask); R[1] = cmov_U64(r1, t1, cmask); R[2] = cmov_U64(r2, t2, cmask); R[3] = cmov_U64(r3, t3, cmask); R[4] = cmov_U64(r4, t4, cmask); } /* R = (-A) mod M */ void MB_FUNC_NAME(ifma_neg52x5_)(U64 R[], const U64 A[], const U64 M[]) { /* mask = a[]!=0? 1 : 0 */ U64 t = _mm512_or_epi64(A[0], A[1]); t = _mm512_or_epi64(t, A[2]); t = _mm512_or_epi64(t, A[3]); t = _mm512_or_epi64(t, A[4]); __mb_mask mask = cmp64_mask(t, get_zero64(), _MM_CMPINT_NE); /* r = M - A */ U64 r0 = _mm512_maskz_sub_epi64(mask, M[0], A[0]); U64 r1 = _mm512_maskz_sub_epi64(mask, M[1], A[1]); U64 r2 = _mm512_maskz_sub_epi64(mask, M[2], A[2]); U64 r3 = _mm512_maskz_sub_epi64(mask, M[3], A[3]); U64 r4 = _mm512_maskz_sub_epi64(mask, M[4], A[4]); /* normalize r0, r1, r2, r3, r4 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_n256.c000066400000000000000000000175751470420105600303430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ #define LEN52 NUMBER_OF_DIGITS(256,DIGIT_SIZE) /* // EC NIST-P256 prime base point order // in 2^52 radix */ __ALIGN64 static const int64u n256_mb[LEN52][8] = { {0x9cac2fc632551, 0x9cac2fc632551, 0x9cac2fc632551, 0x9cac2fc632551, 0x9cac2fc632551, 0x9cac2fc632551, 0x9cac2fc632551, 0x9cac2fc632551}, {0xada7179e84f3b, 0xada7179e84f3b, 0xada7179e84f3b, 0xada7179e84f3b, 0xada7179e84f3b, 0xada7179e84f3b, 0xada7179e84f3b, 0xada7179e84f3b}, {0xfffffffbce6fa, 0xfffffffbce6fa, 0xfffffffbce6fa, 0xfffffffbce6fa, 0xfffffffbce6fa, 0xfffffffbce6fa, 0xfffffffbce6fa, 0xfffffffbce6fa}, {0x0000fffffffff, 0x0000fffffffff, 0x0000fffffffff, 0x0000fffffffff, 0x0000fffffffff, 0x0000fffffffff, 0x0000fffffffff, 0x0000fffffffff}, {0x0ffffffff0000, 0x0ffffffff0000, 0x0ffffffff0000, 0x0ffffffff0000, 0x0ffffffff0000, 0x0ffffffff0000, 0x0ffffffff0000, 0x0ffffffff0000} }; __ALIGN64 static const int64u n256x2_mb[LEN52][8] = { {0x39585f8c64aa2, 0x39585f8c64aa2, 0x39585f8c64aa2, 0x39585f8c64aa2, 0x39585f8c64aa2, 0x39585f8c64aa2, 0x39585f8c64aa2, 0x39585f8c64aa2}, {0x5b4e2f3d09e77, 0x5b4e2f3d09e77, 0x5b4e2f3d09e77, 0x5b4e2f3d09e77, 0x5b4e2f3d09e77, 0x5b4e2f3d09e77, 0x5b4e2f3d09e77, 0x5b4e2f3d09e77}, {0xfffffff79cdf5, 0xfffffff79cdf5, 0xfffffff79cdf5, 0xfffffff79cdf5, 0xfffffff79cdf5, 0xfffffff79cdf5, 0xfffffff79cdf5, 0xfffffff79cdf5}, {0x0001fffffffff, 0x0001fffffffff, 0x0001fffffffff, 0x0001fffffffff, 0x0001fffffffff, 0x0001fffffffff, 0x0001fffffffff, 0x0001fffffffff}, {0x1fffffffe0000, 0x1fffffffe0000, 0x1fffffffe0000, 0x1fffffffe0000, 0x1fffffffe0000, 0x1fffffffe0000, 0x1fffffffe0000, 0x1fffffffe0000} }; /* k0 = -( (1/n256 mod 2^DIGIT_SIZE) ) mod 2^DIGIT_SIZE */ __ALIGN64 static const int64u n256_k0_mb[8] = { 0x1c8aaee00bc4f, 0x1c8aaee00bc4f, 0x1c8aaee00bc4f, 0x1c8aaee00bc4f, 0x1c8aaee00bc4f, 0x1c8aaee00bc4f, 0x1c8aaee00bc4f, 0x1c8aaee00bc4f }; /* to Montgomery conversion constant // rr = 2^((LEN52*DIGIT_SIZE)*2) mod n256 */ __ALIGN64 static const int64u n256_rr_mb[LEN52][8] = { {0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba,0x0005cc0dea6dc3ba}, {0x000192a067d8a084,0x000192a067d8a084,0x000192a067d8a084,0x000192a067d8a084,0x000192a067d8a084,0x000192a067d8a084,0x000192a067d8a084,0x000192a067d8a084}, {0x000bec59615571bb,0x000bec59615571bb,0x000bec59615571bb,0x000bec59615571bb,0x000bec59615571bb,0x000bec59615571bb,0x000bec59615571bb,0x000bec59615571bb}, {0x0001fc245b2392b6,0x0001fc245b2392b6,0x0001fc245b2392b6,0x0001fc245b2392b6,0x0001fc245b2392b6,0x0001fc245b2392b6,0x0001fc245b2392b6,0x0001fc245b2392b6}, {0x0000e12d9559d956,0x0000e12d9559d956,0x0000e12d9559d956,0x0000e12d9559d956,0x0000e12d9559d956,0x0000e12d9559d956,0x0000e12d9559d956,0x0000e12d9559d956} }; /*===================================================================== Specialized single operations in n256 - sqr & mul =====================================================================*/ EXTERN_C U64* MB_FUNC_NAME(ifma_n256_)(void) { return (U64*)n256_mb; } void MB_FUNC_NAME(ifma_ams52_n256_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_ams52x5_)(r, a, (U64*)n256_mb, n256_k0_mb); } void MB_FUNC_NAME(ifma_amm52_n256_)(U64 r[], const U64 a[], const U64 b[]) { MB_FUNC_NAME(ifma_amm52x5_)(r, a, b, (U64*)n256_mb, n256_k0_mb); } void MB_FUNC_NAME(ifma_tomont52_n256_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52x5_)(r, a, (U64*)n256_rr_mb, (U64*)n256_mb, n256_k0_mb); } void MB_FUNC_NAME(ifma_frommont52_n256_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52_n256_)(r, a, (U64*)ones); } /* // computes r = 1/z = z^(n256-2) mod n256 // // note: z in in Montgomery domain (as soon mul() and sqr() below are amm-functions // r in Montgomery domain too */ #define sqr_n256 MB_FUNC_NAME(ifma_ams52_n256_) #define mul_n256 MB_FUNC_NAME(ifma_amm52_n256_) void MB_FUNC_NAME(ifma_aminv52_n256_)(U64 r[], const U64 z[]) { int i; // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 U64 pwr_z_Tbl[16][LEN52]; MB_FUNC_NAME(ifma_tomont52_n256_)(pwr_z_Tbl[0], (U64*)ones); MB_FUNC_NAME(mov_FE256_)(pwr_z_Tbl[1], z); for(i=2; i<16; i+=2) { sqr_n256(pwr_z_Tbl[i], pwr_z_Tbl[i/2]); mul_n256(pwr_z_Tbl[i+1], pwr_z_Tbl[i], z); } // pwr = (n256-2) in big endian int8u pwr[] = "\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84" "\xF3\xB9\xCA\xC2\xFC\x63\x25\x4F"; // init r = 1 MB_FUNC_NAME(mov_FE256_)(r, pwr_z_Tbl[0]); for(i=0; i<32; i++) { int v = pwr[i]; int hi = (v>>4) &0xF; int lo = v & 0xF; sqr_n256(r, r); sqr_n256(r, r); sqr_n256(r, r); sqr_n256(r, r); if(hi) mul_n256(r, r, pwr_z_Tbl[hi]); sqr_n256(r, r); sqr_n256(r, r); sqr_n256(r, r); sqr_n256(r, r); if(lo) mul_n256(r, r, pwr_z_Tbl[lo]); } } /*===================================================================== Specialized single operations in n256 - add, sub & neg =====================================================================*/ void MB_FUNC_NAME(ifma_add52_n256_)(U64 r[], const U64 a[], const U64 b[]) { MB_FUNC_NAME(ifma_add52x5_)(r, a, b, (U64*)n256x2_mb); } void MB_FUNC_NAME(ifma_sub52_n256_)(U64 r[], const U64 a[], const U64 b[]) { MB_FUNC_NAME(ifma_sub52x5_)(r, a, b, (U64*)n256x2_mb); } void MB_FUNC_NAME(ifma_neg52_n256_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_neg52x5_)(r, a, (U64*)n256x2_mb); } __mb_mask MB_FUNC_NAME(lt_mbx_digit_)(const U64 a, const U64 b, const __mb_mask lt_mask) { U64 d = mask_sub64(sub64(a, b), lt_mask, sub64(a, b), set1(1)); return cmp64_mask(d, get_zero64(), _MM_CMPINT_LT); } /* r = (a>=n256)? a-n256 : a */ void MB_FUNC_NAME(ifma_fastred52_pn256_)(U64 R[], const U64 A[]) { /* r = a - b */ U64 r0 = sub64(A[0], ((U64*)(n256_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(n256_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(n256_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(n256_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(n256_mb))[4]); /* lt = {r0 - r4} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); r0 = mask_mov64(A[0], ~lt, r0); r1 = mask_mov64(A[1], ~lt, r1); r2 = mask_mov64(A[2], ~lt, r2); r3 = mask_mov64(A[3], ~lt, r3); r4 = mask_mov64(A[4], ~lt, r4); /* normalize r0 - r4 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_n256_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FE256_)(a,(const U64 (*))n256_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_n256_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FE256_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_n256_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_n384.c000066400000000000000000000472421470420105600303370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ /* // EC NIST-P384 prime base point order // in 2^52 radix */ __ALIGN64 static const int64u n384_mb[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000c196accc52973) }, { REP8_DECL(0x000b248b0a77aece) }, { REP8_DECL(0x0004372ddf581a0d) }, { REP8_DECL(0x000ffffc7634d81f) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x00000000000fffff) } }; /* 2*n384 */ __ALIGN64 static const int64u n384_x2[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000832d5998a52e6) }, { REP8_DECL(0x0006491614ef5d9d) }, { REP8_DECL(0x00086e5bbeb0341b) }, { REP8_DECL(0x000ffff8ec69b03e) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x00000000001fffff) } }; /* k0 = -( (1/n384 mod 2^DIGIT_SIZE) ) mod 2^DIGIT_SIZE */ __ALIGN64 static const int64u n384_k0_mb[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(0x00046089e88fdc45) }; /* to Montgomery conversion constant // rr = 2^((P384_LEN52*DIGIT_SIZE)*2) mod n384 */ __ALIGN64 static const int64u n384_rr_mb[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x00034124f50ddb2d) }, { REP8_DECL(0x000c974971bd0d8d) }, { REP8_DECL(0x0002118942bfd3cc) }, { REP8_DECL(0x0009f43be8072178) }, { REP8_DECL(0x0005bf030606de60) }, { REP8_DECL(0x0000d49174aab1cc) }, { REP8_DECL(0x000b7a28266895d4) }, { REP8_DECL(0x000000000003fb05) } }; /* ifma_tomont52_n384_(1) */ __ALIGN64 static const int64u n384_r_mb[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000ad68d00000000) }, { REP8_DECL(0x000851313e695333) }, { REP8_DECL(0x0007e5f24db74f58) }, { REP8_DECL(0x000b27e0bc8d220a) }, { REP8_DECL(0x000000000000389c) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) } }; /*===================================================================== Specialized single operations over n384: sqr & mul =====================================================================*/ void MB_FUNC_NAME(ifma_amm52_n384_)(U64 r[], const U64 va[], const U64 vb[]) { U64 K = loadu64(n384_k0_mb); U64 r0, r1, r2, r3, r4, r5, r6, r7; int itr; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = get_zero64(); for(itr=0; itr < P384_LEN52; itr++) { U64 Yi, T, LO, HI; U64 Bi = loadu64(vb); vb++; fma52lo_mem(r0, r0, Bi, va, SIMD_BYTES * 0); Yi = fma52lo(get_zero64(), r0, K); T = sub64(get_zero64(), Yi); LO = and64(T, loadu64(VMASK52)); HI = add64(Yi, srai64(T,63)); fma52lo_mem(r1, r1, Bi, va, SIMD_BYTES * 1); fma52lo_mem(r2, r2, Bi, va, SIMD_BYTES * 2); fma52lo_mem(r3, r3, Bi, va, SIMD_BYTES * 3); fma52lo_mem(r4, r4, Bi, va, SIMD_BYTES * 4); fma52lo_mem(r5, r5, Bi, va, SIMD_BYTES * 5); fma52lo_mem(r6, r6, Bi, va, SIMD_BYTES * 6); fma52lo_mem(r7, r7, Bi, va, SIMD_BYTES * 7); fma52lo_mem(r0, r0, Yi, n384_mb, SIMD_BYTES * 0); fma52lo_mem(r1, r1, Yi, n384_mb, SIMD_BYTES * 1); fma52lo_mem(r2, r2, Yi, n384_mb, SIMD_BYTES * 2); fma52lo_mem(r3, r3, Yi, n384_mb, SIMD_BYTES * 3); r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ r4 = add64(r4, LO); /* fma52lo_mem(r4, r4, Yi, n384_mb, SIMD_BYTES * 4); */ r5 = add64(r5, LO); /* fma52lo_mem(r5, r5, Yi, n384_mb, SIMD_BYTES * 5); */ r6 = add64(r6, LO); /* fma52lo_mem(r6, r6, Yi, n384_mb, SIMD_BYTES * 6); */ fma52lo_mem(r7, r7, Yi, n384_mb, SIMD_BYTES * 7); fma52hi_mem(r0, r1, Bi, va, SIMD_BYTES * 0); fma52hi_mem(r1, r2, Bi, va, SIMD_BYTES * 1); fma52hi_mem(r2, r3, Bi, va, SIMD_BYTES * 2); fma52hi_mem(r3, r4, Bi, va, SIMD_BYTES * 3); fma52hi_mem(r4, r5, Bi, va, SIMD_BYTES * 4); fma52hi_mem(r5, r6, Bi, va, SIMD_BYTES * 5); fma52hi_mem(r6, r7, Bi, va, SIMD_BYTES * 6); fma52hi_mem(r7, get_zero64(), Bi, va, SIMD_BYTES * 7); fma52hi_mem(r0, r0, Yi, n384_mb, SIMD_BYTES * 0); fma52hi_mem(r1, r1, Yi, n384_mb, SIMD_BYTES * 1); fma52hi_mem(r2, r2, Yi, n384_mb, SIMD_BYTES * 2); fma52hi_mem(r3, r3, Yi, n384_mb, SIMD_BYTES * 3); r4 = add64(r4, HI); /* fma52hi_mem(r4, r4, Yi, n384_mb, SIMD_BYTES * 4); */ r5 = add64(r5, HI); /* fma52hi_mem(r5, r5, Yi, n384_mb, SIMD_BYTES * 5); */ r6 = add64(r6, HI); /* fma52hi_mem(r6, r6, Yi, n384_mb, SIMD_BYTES * 6); */ fma52hi_mem(r7, r7, Yi, n384_mb, SIMD_BYTES * 7); } // normalization NORM_LSHIFTR(r, 0, 1) NORM_LSHIFTR(r, 1, 2) NORM_LSHIFTR(r, 2, 3) NORM_LSHIFTR(r, 3, 4) NORM_LSHIFTR(r, 4, 5) NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) r[0] = r0; r[1] = r1; r[2] = r2; r[3] = r3; r[4] = r4; r[5] = r5; r[6] = r6; r[7] = r7; } #define ROUND_MUL(I, J, R_LO, R_HI) \ R_LO = fma52lo(R_LO, va[I], vb[J]); \ R_HI = fma52hi(R_HI, va[I], vb[J]); #define N384_REDUCTION_ROUND(u, r0, r1, r2, r3, r4, r5, r6, r7, r8, modulus, k) \ { \ U64 t = sub64(get_zero64(), u); \ U64 lo = and64(t, loadu64(VMASK52)); \ U64 hi = add64(u, srai64(t,63)); \ \ r0 = fma52lo(r0, u, modulus[0]); \ r1 = fma52lo(r1, u, modulus[1]); \ r2 = fma52lo(r2, u, modulus[2]); \ r3 = fma52lo(r3, u, modulus[3]); \ r7 = fma52lo(r7, u, modulus[7]); \ r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ \ r4 = add64(r4, lo); /*r4 = fma52lo(r4, u, modulus[4]); */ \ r5 = add64(r5, lo); /*r5 = fma52lo(r5, u, modulus[5]); */ \ r6 = add64(r6, lo); /*r6 = fma52lo(r6, u, modulus[6]); */ \ \ r1 = fma52hi(r1, u, modulus[0]); \ r2 = fma52hi(r2, u, modulus[1]); \ r3 = fma52hi(r3, u, modulus[2]); \ r4 = fma52hi(r4, u, modulus[3]); \ r8 = fma52hi(r8, u, modulus[7]); \ u = fma52lo(get_zero64(), r1, k); /* update u = r1*k */ \ r5 = add64(r5, hi); /*r5 = fma52hi(r5, u, modulus[4]); */ \ r6 = add64(r6, hi); /*r6 = fma52hi(r6, u, modulus[5]); */ \ r7 = add64(r7, hi); /*r7 = fma52hi(r7, u, modulus[6]); */ \ } void MB_FUNC_NAME(ifma_ams52_n384_)(U64 r[], const U64 va[]) { U64 K = loadu64(n384_k0_mb); const U64* vb = va; U64* modulus = (U64*)n384_mb; U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15; U64 u; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = get_zero64(); // full square ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(0, 5, r5, r6) ROUND_MUL(0, 6, r6, r7) ROUND_MUL(0, 7, r7, r8) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(1, 5, r6, r7) ROUND_MUL(1, 6, r7, r8) ROUND_MUL(1, 7, r8, r9) ROUND_MUL(2, 3, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(2, 5, r7, r8) ROUND_MUL(2, 6, r8, r9) ROUND_MUL(2, 7, r9, r10) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(3, 5, r8, r9) ROUND_MUL(3, 6, r9, r10) ROUND_MUL(3, 7, r10,r11) ROUND_MUL(4, 5, r9, r10) ROUND_MUL(4, 6, r10,r11) ROUND_MUL(4, 7, r11,r12) ROUND_MUL(5, 6, r11,r12) ROUND_MUL(5, 7, r12,r13) ROUND_MUL(6, 7, r13,r14) r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); r9 = add64(r9, r9); r10 = add64(r10, r10); r11 = add64(r11, r11); r12 = add64(r12, r12); r13 = add64(r13, r13); r14 = add64(r14, r14); ROUND_MUL(0, 0, r0, r1) u = fma52lo(get_zero64(), r0, K); ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 4, r8, r9) ROUND_MUL(5, 5, r10, r11) ROUND_MUL(6, 6, r12, r13) ROUND_MUL(7, 7, r14, r15) // reduction N384_REDUCTION_ROUND(u, r0, r1, r2, r3, r4, r5, r6, r7, r8, modulus, K); N384_REDUCTION_ROUND(u, r1, r2, r3, r4, r5, r6, r7, r8, r9, modulus, K); N384_REDUCTION_ROUND(u, r2, r3, r4, r5, r6, r7, r8, r9, r10, modulus, K); N384_REDUCTION_ROUND(u, r3, r4, r5, r6, r7, r8, r9, r10,r11, modulus, K); N384_REDUCTION_ROUND(u, r4, r5, r6, r7, r8, r9, r10,r11,r12, modulus, K); N384_REDUCTION_ROUND(u, r5, r6, r7, r8, r9, r10,r11,r12,r13, modulus, K); N384_REDUCTION_ROUND(u, r6, r7, r8, r9, r10,r11,r12,r13,r14, modulus, K); N384_REDUCTION_ROUND(u, r7, r8, r9, r10,r11,r12,r13,r14,r15, modulus, K); // normalization NORM_LSHIFTR(r, 8, 9) NORM_LSHIFTR(r, 9, 10) NORM_LSHIFTR(r, 10, 11) NORM_LSHIFTR(r, 11, 12) NORM_LSHIFTR(r, 12, 13) NORM_LSHIFTR(r, 13, 14) NORM_LSHIFTR(r, 14, 15) r[0] = r8; r[1] = r9; r[2] = r10; r[3] = r11; r[4] = r12; r[5] = r13; r[6] = r14; r[7] = r15; } void MB_FUNC_NAME(ifma_tomont52_n384_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52_n384_)(r, a, (U64*)n384_rr_mb); } void MB_FUNC_NAME(ifma_frommont52_n384_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52_n384_)(r, a, (U64*)ones); } /* // computes r = 1/z = z^(n384-2) mod n384 // // note: z in in Montgomery domain (as soon mul() and sqr() below are amm-functions // r in Montgomery domain too */ #define fe52_sqr MB_FUNC_NAME(ifma_ams52_n384_) #define fe52_mul MB_FUNC_NAME(ifma_amm52_n384_) /* r = base^(2^n) */ __MBX_INLINE void fe52_sqr_pwr(U64 r[], const U64 base[], int n) { if(r!=base) { fe52_sqr(r,base); n--; } for(; n>0; n--) fe52_sqr(r,r); } void MB_FUNC_NAME(ifma_aminv52_n384_)(U64 r[], const U64 z[]) { int i; // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 U64 pwr_z_Tbl[16][P384_LEN52]; __ALIGN64 U64 lexp[P384_LEN52]; MB_FUNC_NAME(mov_FE384_)(pwr_z_Tbl[0], (U64*)n384_r_mb); MB_FUNC_NAME(mov_FE384_)(pwr_z_Tbl[1], z); for(i=2; i<16; i+=2) { fe52_sqr(pwr_z_Tbl[i], pwr_z_Tbl[i/2]); fe52_mul(pwr_z_Tbl[i+1], pwr_z_Tbl[i], z); } // pwr = (n384-2) in big endian int8u pwr[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xC7\x63\x4D\x81\xF4\x37\x2D\xDF" "\x58\x1A\x0D\xB2\x48\xB0\xA7\x7A" "\xEC\xEC\x19\x6A\xCC\xC5\x29\x71"; /* // process low part of the exponent: "0xc7634d81f4372ddf 0x581a0db248b0a77a 0xecec196accc52973" */ /* init result */ MB_FUNC_NAME(mov_FE384_)(lexp, (U64*)n384_r_mb); for(i=24; i>4) &0xF; int lo = v & 0xF; fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); if(hi) fe52_mul(lexp, lexp, pwr_z_Tbl[hi]); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); if(lo) fe52_mul(lexp, lexp, pwr_z_Tbl[lo]); } /* // process high part of the exponent: "0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff" */ __ALIGN64 U64 u[P384_LEN52]; __ALIGN64 U64 v[P384_LEN52]; fe52_sqr(v, z); /* v = z^2 */ fe52_mul(u, v, z); /* u = z^2 * z = z^3 */ fe52_sqr_pwr(v, u, 2); /* v= (z^3)^(2^2) = z^12 */ fe52_mul(u, v, u); /* u = z^12 * z^3 = z^15 = z^(0xF) */ fe52_sqr_pwr(v, u, 4); /* v= (z^0xF)^(2^4) = z^(0xF0) */ fe52_mul(u, v, u); /* u = z^0xF0 * z^(0xF) = z^(0xFF) */ fe52_sqr_pwr(v, u, 8); /* v= (z^0xFF)^(2^8) = z^(0xFF00) */ fe52_mul(u, v, u); /* u = z^0xFF00 * z^(0xFF) = z^(0xFFFF) */ fe52_sqr_pwr(v, u, 16); /* v= (z^0xFFFF)^(2^16) = z^(0xFFFF0000) */ fe52_mul(u, v, u); /* u = z^0xFFFF0000 * z^(0xFFFF) = z^(0xFFFFFFFF) */ fe52_sqr_pwr(v, u, 32); /* v= (z^0xFFFFFFFF)^(2^32) = z^(0xFFFFFFFF00000000) */ fe52_mul(u, v, u); /* u = z^0xFFFFFFFF00000000 * z^(0xFFFFFFFF) = z^(0xFFFFFFFFFFFFFFFF) */ fe52_sqr_pwr(v, u, 64); fe52_mul(v, v, u); /* v = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, u); /* v = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /* combine low and high results */ fe52_sqr_pwr(v, v, 64*3); /* u = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000.0000000000000000.0000000000000000) */ fe52_mul(r, v, lexp); /* r = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.c7634d81f4372ddf.581a0db248b0a77a.ecec196accc52973) */ } /*===================================================================== Specialized single operations over n384 add, sub, neg =====================================================================*/ static __mb_mask MB_FUNC_NAME(lt_mbx_digit_)(const U64 a, const U64 b, const __mb_mask lt_mask) { U64 d = mask_sub64(sub64(a, b), lt_mask, sub64(a, b), set1(1)); return cmp64_mask(d, get_zero64(), _MM_CMPINT_LT); } void MB_FUNC_NAME(ifma_add52_n384_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a + b */ U64 r0 = add64(A[0], B[0]); U64 r1 = add64(A[1], B[1]); U64 r2 = add64(A[2], B[2]); U64 r3 = add64(A[3], B[3]); U64 r4 = add64(A[4], B[4]); U64 r5 = add64(A[5], B[5]); U64 r6 = add64(A[6], B[6]); U64 r7 = add64(A[7], B[7]); /* lt = {r0 - r7} < 2*n */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)( r0, ((U64*)(n384_x2))[0], 0); lt = MB_FUNC_NAME(lt_mbx_digit_)( r1, ((U64*)(n384_x2))[1], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r2, ((U64*)(n384_x2))[2], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r3, ((U64*)(n384_x2))[3], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r4, ((U64*)(n384_x2))[4], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r5, ((U64*)(n384_x2))[5], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r6, ((U64*)(n384_x2))[6], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r7, ((U64*)(n384_x2))[7], lt); /* {r0 - r7} -= 2*n */ r0 = mask_sub64(r0, ~lt, r0, ((U64*)(n384_x2))[0]); r1 = mask_sub64(r1, ~lt, r1, ((U64*)(n384_x2))[1]); r2 = mask_sub64(r2, ~lt, r2, ((U64*)(n384_x2))[2]); r3 = mask_sub64(r3, ~lt, r3, ((U64*)(n384_x2))[3]); r4 = mask_sub64(r4, ~lt, r4, ((U64*)(n384_x2))[4]); r5 = mask_sub64(r5, ~lt, r5, ((U64*)(n384_x2))[5]); r6 = mask_sub64(r6, ~lt, r6, ((U64*)(n384_x2))[6]); r7 = mask_sub64(r7, ~lt, r7, ((U64*)(n384_x2))[7]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } void MB_FUNC_NAME(ifma_sub52_n384_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); U64 r5 = sub64(A[5], B[5]); U64 r6 = sub64(A[6], B[6]); U64 r7 = sub64(A[7], B[7]); /* lt = {r0 - r7} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r5, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r6, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r7, get_zero64(), lt); r0 = mask_add64(r0, lt, r0, ((U64*)(n384_x2))[0]); r1 = mask_add64(r1, lt, r1, ((U64*)(n384_x2))[1]); r2 = mask_add64(r2, lt, r2, ((U64*)(n384_x2))[2]); r3 = mask_add64(r3, lt, r3, ((U64*)(n384_x2))[3]); r4 = mask_add64(r4, lt, r4, ((U64*)(n384_x2))[4]); r5 = mask_add64(r5, lt, r5, ((U64*)(n384_x2))[5]); r6 = mask_add64(r6, lt, r6, ((U64*)(n384_x2))[6]); r7 = mask_add64(r7, lt, r7, ((U64*)(n384_x2))[7]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } void MB_FUNC_NAME(ifma_neg52_n384_)(U64 R[], const U64 A[]) { __mb_mask nz_mask = ~MB_FUNC_NAME(is_zero_FE384_)(A); /* {r0 - r7} = 2*n - A */ U64 r0 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[0], A[0] ); U64 r1 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[1], A[1] ); U64 r2 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[2], A[2] ); U64 r3 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[3], A[3] ); U64 r4 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[4], A[4] ); U64 r5 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[5], A[5] ); U64 r6 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[6], A[6] ); U64 r7 = mask_sub64( A[0], nz_mask, ((U64*)(n384_x2))[7], A[7] ); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } /* r = (a>=n384)? a-n384 : a */ void MB_FUNC_NAME(ifma_fastred52_pn384_)(U64 R[], const U64 A[]) { /* r = a - b */ U64 r0 = sub64(A[0], ((U64*)(n384_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(n384_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(n384_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(n384_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(n384_mb))[4]); U64 r5 = sub64(A[5], ((U64*)(n384_mb))[5]); U64 r6 = sub64(A[6], ((U64*)(n384_mb))[6]); U64 r7 = sub64(A[7], ((U64*)(n384_mb))[7]); /* lt = {r0 - r7} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r5, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r6, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r7, get_zero64(), lt); r0 = mask_mov64(A[0], ~lt, r0); r1 = mask_mov64(A[1], ~lt, r1); r2 = mask_mov64(A[2], ~lt, r2); r3 = mask_mov64(A[3], ~lt, r3); r4 = mask_mov64(A[4], ~lt, r4); r5 = mask_mov64(A[5], ~lt, r5); r6 = mask_mov64(A[6], ~lt, r6); r7 = mask_mov64(A[7], ~lt, r7); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_n384_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FE384_)(a,(const U64 (*))n384_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_n384_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FE384_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_n384_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_n521.c000066400000000000000000000622351470420105600303270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ /* // EC NIST-P521 prime base point order // in 2^52 radix */ __ALIGN64 static const int64u n521_mb[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000fb71e91386409) }, { REP8_DECL(0x000b8899c47aebb6) }, { REP8_DECL(0x000709a5d03bb5c9) }, { REP8_DECL(0x000966b7fcc0148f) }, { REP8_DECL(0x000a51868783bf2f) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000000000000001) } }; /* 2*n521 */ __ALIGN64 static const int64u n521_x2[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000f6e3d2270c812) }, { REP8_DECL(0x0007113388f5d76d) }, { REP8_DECL(0x000e134ba0776b93) }, { REP8_DECL(0x0002cd6ff980291e) }, { REP8_DECL(0x0004a30d0f077e5f) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000000000000003) } }; /* k0 = -( (1/n521 mod 2^DIGIT_SIZE) ) mod 2^DIGIT_SIZE */ __ALIGN64 static const int64u n521_k0_mb[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(0x000f5ccd79a995c7) }; /* to Montgomery conversion constant // rr = 2^((P521_LEN52*DIGIT_SIZE)*2) mod n521 */ __ALIGN64 static const int64u n521_rr_mb[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0003b4d7a5b140ce) }, { REP8_DECL(0x000cb0bf26c55bf9) }, { REP8_DECL(0x00037e5396c67ee9) }, { REP8_DECL(0x0002bd1c80cf7b13) }, { REP8_DECL(0x00073cbe28f15e41) }, { REP8_DECL(0x000dd6e23d82e49c) }, { REP8_DECL(0x0003d142b7756e3e) }, { REP8_DECL(0x00061a8e567bccff) }, { REP8_DECL(0x00092d0d455bcc6d) }, { REP8_DECL(0x000383d2d8e03d14) }, { REP8_DECL(0x0000000000000000) } }; /* ifma_tomont52_n521_(1) */ __ALIGN64 static const int64u n521_r_mb[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0008000000000000) }, { REP8_DECL(0x00082470b763cdfb) }, { REP8_DECL(0x00023bb31dc28a24) }, { REP8_DECL(0x00047b2d17e2251b) }, { REP8_DECL(0x00034ca4019ff5b8) }, { REP8_DECL(0x0002d73cbc3e2068) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) } }; /*===================================================================== Specialized single operations over n384: sqr & mul =====================================================================*/ void MB_FUNC_NAME(ifma_amm52_n521_)(U64 r[], const U64 va[], const U64 vb[]) { U64 K = loadu64(n521_k0_mb); U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10; int itr; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = get_zero64(); for(itr=0; itr < P521_LEN52; itr++) { U64 Yi, T, LO, HI; U64 Bi = loadu64(vb); vb++; fma52lo_mem(r0, r0, Bi, va, SIMD_BYTES * 0); fma52lo_mem(r1, r1, Bi, va, SIMD_BYTES * 1); fma52lo_mem(r2, r2, Bi, va, SIMD_BYTES * 2); fma52lo_mem(r3, r3, Bi, va, SIMD_BYTES * 3); fma52lo_mem(r4, r4, Bi, va, SIMD_BYTES * 4); fma52lo_mem(r5, r5, Bi, va, SIMD_BYTES * 5); fma52lo_mem(r6, r6, Bi, va, SIMD_BYTES * 6); fma52lo_mem(r7, r7, Bi, va, SIMD_BYTES * 7); fma52lo_mem(r8, r8, Bi, va, SIMD_BYTES * 8); fma52lo_mem(r9, r9, Bi, va, SIMD_BYTES * 9); fma52lo_mem(r10,r10,Bi, va, SIMD_BYTES * 10); Yi = fma52lo(get_zero64(), r0, K); T = sub64(get_zero64(), Yi); LO = and64(T, loadu64(VMASK52)); HI = add64(Yi, srai64(T,63)); fma52lo_mem(r0, r0, Yi, n521_mb, SIMD_BYTES * 0); fma52lo_mem(r1, r1, Yi, n521_mb, SIMD_BYTES * 1); fma52lo_mem(r2, r2, Yi, n521_mb, SIMD_BYTES * 2); fma52lo_mem(r3, r3, Yi, n521_mb, SIMD_BYTES * 3); fma52lo_mem(r4, r4, Yi, n521_mb, SIMD_BYTES * 4); r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ r5 = add64(r5, LO); /* fma52lo_mem(r5, r5, Yi, n521_mb, SIMD_BYTES * 5); */ r6 = add64(r6, LO); /* fma52lo_mem(r6, r6, Yi, n521_mb, SIMD_BYTES * 6); */ r7 = add64(r7, LO); /* fma52lo_mem(r7, r7, Yi, n521_mb, SIMD_BYTES * 7); */ r8 = add64(r8, LO); /* fma52lo_mem(r8, r8, Yi, n521_mb, SIMD_BYTES * 8); */ r9 = add64(r9, LO); /* fma52lo_mem(r9, r9, Yi, n521_mb, SIMD_BYTES * 9); */ r10= add64(r10,Yi); /* fma52lo_mem(r10,r10,Yi, n521_mb, SIMD_BYTES * 10); */ fma52hi_mem(r0, r1, Bi, va, SIMD_BYTES * 0); fma52hi_mem(r1, r2, Bi, va, SIMD_BYTES * 1); fma52hi_mem(r2, r3, Bi, va, SIMD_BYTES * 2); fma52hi_mem(r3, r4, Bi, va, SIMD_BYTES * 3); fma52hi_mem(r4, r5, Bi, va, SIMD_BYTES * 4); fma52hi_mem(r5, r6, Bi, va, SIMD_BYTES * 5); fma52hi_mem(r6, r7, Bi, va, SIMD_BYTES * 6); fma52hi_mem(r7, r8, Bi, va, SIMD_BYTES * 7); fma52hi_mem(r8, r9, Bi, va, SIMD_BYTES * 8); fma52hi_mem(r9, r10,Bi, va, SIMD_BYTES * 9); fma52hi_mem(r10,get_zero64(), Bi, va, SIMD_BYTES * 10); fma52hi_mem(r0, r0, Yi, n521_mb, SIMD_BYTES * 0); fma52hi_mem(r1, r1, Yi, n521_mb, SIMD_BYTES * 1); fma52hi_mem(r2, r2, Yi, n521_mb, SIMD_BYTES * 2); fma52hi_mem(r3, r3, Yi, n521_mb, SIMD_BYTES * 3); fma52hi_mem(r4, r4, Yi, n521_mb, SIMD_BYTES * 4); r5 = add64(r5, HI); /* fma52hi_mem(r5, r5, Yi, n521_mb, SIMD_BYTES * 5); */ r6 = add64(r6, HI); /* fma52hi_mem(r6, r6, Yi, n521_mb, SIMD_BYTES * 6); */ r7 = add64(r7, HI); /* fma52hi_mem(r7, r7, Yi, n521_mb, SIMD_BYTES * 7); */ r8 = add64(r8, HI); /* fma52hi_mem(r8, r8, Yi, n521_mb, SIMD_BYTES * 8); */ r9 = add64(r9, HI); /* fma52hi_mem(r9, r9, Yi, n521_mb, SIMD_BYTES * 9); */ /* 0 == hi(Yi, n521_mb[10] */; } // normalization NORM_LSHIFTR(r, 0, 1) NORM_LSHIFTR(r, 1, 2) NORM_LSHIFTR(r, 2, 3) NORM_LSHIFTR(r, 3, 4) NORM_LSHIFTR(r, 4, 5) NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) NORM_LSHIFTR(r, 7, 8) NORM_LSHIFTR(r, 8, 9) NORM_LSHIFTR(r, 9, 10) r[0] = r0; r[1] = r1; r[2] = r2; r[3] = r3; r[4] = r4; r[5] = r5; r[6] = r6; r[7] = r7; r[8] = r8; r[9] = r9; r[10]= r10; } #define ROUND_MUL(I, J, R_LO, R_HI) \ R_LO = fma52lo(R_LO, va[I], vb[J]); \ R_HI = fma52hi(R_HI, va[I], vb[J]); #define N521_REDUCTION_ROUND(u, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, modulus, k) \ { \ U64 t = sub64(get_zero64(), u); \ U64 lo = and64(t, loadu64(VMASK52)); \ U64 hi = add64(u, srai64(t,63)); \ \ r0 = fma52lo(r0, u, modulus[0]); \ r1 = fma52lo(r1, u, modulus[1]); \ r2 = fma52lo(r2, u, modulus[2]); \ r3 = fma52lo(r3, u, modulus[3]); \ r4 = fma52lo(r4, u, modulus[4]); \ r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ \ r5 = add64(r5, lo); \ r6 = add64(r6, lo); \ r7 = add64(r7, lo); \ r8 = add64(r8, lo); \ r9 = add64(r9, lo); \ r10 = add64(r10, u); \ \ \ r1 = fma52hi(r1, u, modulus[0]); \ r2 = fma52hi(r2, u, modulus[1]); \ r3 = fma52hi(r3, u, modulus[2]); \ r4 = fma52hi(r4, u, modulus[3]); \ r5 = fma52hi(r5, u, modulus[4]); \ u = fma52lo(get_zero64(), r1, k); /* update u = r1*k */ \ r6 = add64(r6, hi); \ r7 = add64(r7, hi); \ r8 = add64(r8, hi); \ r9 = add64(r9, hi); \ r10= add64(r10,hi); \ } void MB_FUNC_NAME(ifma_ams52_n521_)(U64 r[], const U64 va[]) { U64 K = loadu64(n521_k0_mb); const U64* vb = va; U64* modulus = (U64*)n521_mb; U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; U64 r20, r21; U64 u; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = r20 = r21 = get_zero64(); // full square ROUND_MUL(0, 1, r1, r2); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(0, 5, r5, r6); ROUND_MUL(0, 6, r6, r7); ROUND_MUL(0, 7, r7, r8); ROUND_MUL(0, 8, r8, r9); ROUND_MUL(0, 9, r9, r10); ROUND_MUL(0, 10,r10,r11); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(1, 5, r6, r7); ROUND_MUL(1, 6, r7, r8); ROUND_MUL(1, 7, r8, r9); ROUND_MUL(1, 8, r9, r10); ROUND_MUL(1, 9, r10,r11); ROUND_MUL(1, 10,r11,r12); ROUND_MUL(2, 3, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(2, 5, r7, r8); ROUND_MUL(2, 6, r8, r9); ROUND_MUL(2, 7, r9, r10); ROUND_MUL(2, 8, r10,r11); ROUND_MUL(2, 9, r11,r12); ROUND_MUL(2, 10,r12,r13); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(3, 5, r8, r9); ROUND_MUL(3, 6, r9, r10); ROUND_MUL(3, 7, r10,r11); ROUND_MUL(3, 8, r11,r12); ROUND_MUL(3, 9, r12,r13); ROUND_MUL(3, 10,r13,r14); ROUND_MUL(4, 5, r9, r10); ROUND_MUL(4, 6, r10,r11); ROUND_MUL(4, 7, r11,r12); ROUND_MUL(4, 8, r12,r13); ROUND_MUL(4, 9, r13,r14); ROUND_MUL(4, 10,r14,r15); ROUND_MUL(5, 6, r11,r12); ROUND_MUL(5, 7, r12,r13); ROUND_MUL(5, 8, r13,r14); ROUND_MUL(5, 9, r14,r15); ROUND_MUL(5, 10,r15,r16); ROUND_MUL(6, 7, r13,r14); ROUND_MUL(6, 8, r14,r15); ROUND_MUL(6, 9, r15,r16); ROUND_MUL(6, 10,r16,r17); ROUND_MUL(7, 8, r15,r16); ROUND_MUL(7, 9, r16,r17); ROUND_MUL(7, 10,r17,r18); ROUND_MUL(8, 9, r17,r18); ROUND_MUL(8, 10,r18,r19); ROUND_MUL(9, 10,r19,r20); r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); r9 = add64(r9, r9); r10 = add64(r10, r10); r11 = add64(r11, r11); r12 = add64(r12, r12); r13 = add64(r13, r13); r14 = add64(r14, r14); r15 = add64(r15, r15); r16 = add64(r16, r16); r17 = add64(r17, r17); r18 = add64(r18, r18); r19 = add64(r19, r19); r20 = add64(r20, r20); ROUND_MUL(0, 0, r0, r1); u = fma52lo(get_zero64(), r0, K); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 4, r8, r9); ROUND_MUL(5, 5, r10, r11); ROUND_MUL(6, 6, r12, r13); ROUND_MUL(7, 7, r14, r15); ROUND_MUL(8, 8, r16, r17); ROUND_MUL(9, 9, r18, r19); ROUND_MUL(10,10,r20, r21); // reduction n521 N521_REDUCTION_ROUND(u, r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, modulus, K); N521_REDUCTION_ROUND(u, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, modulus, K); N521_REDUCTION_ROUND(u, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, modulus, K); N521_REDUCTION_ROUND(u, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, modulus, K); N521_REDUCTION_ROUND(u, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, modulus, K); N521_REDUCTION_ROUND(u, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, modulus, K); N521_REDUCTION_ROUND(u, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, modulus, K); N521_REDUCTION_ROUND(u, r7, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, modulus, K); N521_REDUCTION_ROUND(u, r8, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, modulus, K); N521_REDUCTION_ROUND(u, r9, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, modulus, K); N521_REDUCTION_ROUND(u, r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, r20, modulus, K); // normalization NORM_LSHIFTR(r, 11, 12) NORM_LSHIFTR(r, 12, 13) NORM_LSHIFTR(r, 13, 14) NORM_LSHIFTR(r, 14, 15) NORM_LSHIFTR(r, 15, 16) NORM_LSHIFTR(r, 16, 17) NORM_LSHIFTR(r, 17, 18) NORM_LSHIFTR(r, 18, 19) NORM_LSHIFTR(r, 19, 20) NORM_LSHIFTR(r, 20, 21) r[0] = r11; r[1] = r12; r[2] = r13; r[3] = r14; r[4] = r15; r[5] = r16; r[6] = r17; r[7] = r18; r[8] = r19; r[9] = r20; r[10]= r21; } void MB_FUNC_NAME(ifma_tomont52_n521_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52_n521_)(r, a, (U64*)n521_rr_mb); } void MB_FUNC_NAME(ifma_frommont52_n521_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52_n521_)(r, a, (U64*)ones); } /* // computes r = 1/z = z^(n384-2) mod n384 // // note: z in in Montgomery domain (as soon mul() and sqr() below are amm-functions // r in Montgomery domain too */ #define fe52_sqr MB_FUNC_NAME(ifma_ams52_n521_) #define fe52_mul MB_FUNC_NAME(ifma_amm52_n521_) /* r = base^(2^n) */ __MBX_INLINE void fe52_sqr_pwr(U64 r[], const U64 base[], int n) { if(r!=base) { fe52_sqr(r,base); n--; } for(; n>0; n--) fe52_sqr(r,r); } void MB_FUNC_NAME(ifma_aminv52_n521_)(U64 r[], const U64 z[]) { int i; // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 U64 pwr_z_Tbl[16][P521_LEN52]; __ALIGN64 U64 lexp[P521_LEN52]; MB_FUNC_NAME(mov_FE521_)(pwr_z_Tbl[0], (U64*)n521_r_mb); MB_FUNC_NAME(mov_FE521_)(pwr_z_Tbl[1], z); for(i=2; i<16; i+=2) { fe52_sqr(pwr_z_Tbl[i], pwr_z_Tbl[i/2]); fe52_mul(pwr_z_Tbl[i+1], pwr_z_Tbl[i], z); } // pwr = (n521-2) in big endian int8u pwr[] = "\x1\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFA" "\x51\x86\x87\x83\xBF\x2F\x96\x6B" "\x7F\xCC\x01\x48\xF7\x09\xA5\xD0" "\x3B\xB5\xC9\xB8\x89\x9C\x47\xAE" "\xBB\x6F\xB7\x1E\x91\x38\x64\x07"; /* // process 25 low bytes of the exponent: :FA 51 86 ... 64 07" */ /* init result */ MB_FUNC_NAME(mov_FE521_)(lexp, (U64*)n521_r_mb); for(i=33; i>4) &0xF; int lo = v & 0xF; fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); if(hi) fe52_mul(lexp, lexp, pwr_z_Tbl[hi]); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); fe52_sqr(lexp, lexp); if(lo) fe52_mul(lexp, lexp, pwr_z_Tbl[lo]); } /* // process high part of the exponent: "0x1 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff" */ __ALIGN64 U64 u[P521_LEN52]; __ALIGN64 U64 v[P521_LEN52]; MB_FUNC_NAME(mov_FE521_)(u, pwr_z_Tbl[15]); /* u = z^0xF */ fe52_sqr_pwr(v, u, 4); /* v= (z^0xF)^(2^4) = z^(0xF0) */ fe52_mul(u, v, u); /* u = z^0xF0 * z^(0xF) = z^(0xFF) */ fe52_sqr_pwr(v, u, 8); /* v= (z^0xFF)^(2^8) = z^(0xFF00) */ fe52_mul(u, v, u); /* u = z^0xFF00 * z^(0xFF) = z^(0xFFFF) */ fe52_sqr_pwr(v, u, 16); /* v= (z^0xFFFF)^(2^16) = z^(0xFFFF0000) */ fe52_mul(u, v, u); /* u = z^0xFFFF0000 * z^(0xFFFF) = z^(0xFFFFFFFF) */ fe52_sqr_pwr(v, u, 32); /* v= (z^0xFFFFFFFF)^(2^32) = z^(0xFFFFFFFF00000000) */ fe52_mul(u, v, u); /* u = z^0xFFFFFFFF00000000 * z^(0xFFFFFFFF) = z^(0xFFFFFFFFFFFFFFFF) */ fe52_sqr_pwr(v, z, 64); fe52_mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF) */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /* combine low and high results */ fe52_sqr_pwr(v, v, 64*4+8);/* u = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.00.0000000000000000.0000000000000000.0000000000000000.0000000000000000) */ fe52_mul(r, v, lexp); /* r = z^(0x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFA.51868783BF2F966B.7FCC0148F709A5D0.3BB5C9B8899C47AE.BB6FB71E91386407) */ } /*===================================================================== Specialized single operations over n521 add, sub, neg =====================================================================*/ __MBX_INLINE __mb_mask MB_FUNC_NAME(lt_mbx_digit_)(const U64 a, const U64 b, const __mb_mask lt_mask) { U64 d = mask_sub64(sub64(a, b), lt_mask, sub64(a, b), set1(1)); return cmp64_mask(d, get_zero64(), _MM_CMPINT_LT); } void MB_FUNC_NAME(ifma_add52_n521_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a + b */ U64 r0 = add64(A[0], B[0]); U64 r1 = add64(A[1], B[1]); U64 r2 = add64(A[2], B[2]); U64 r3 = add64(A[3], B[3]); U64 r4 = add64(A[4], B[4]); U64 r5 = add64(A[5], B[5]); U64 r6 = add64(A[6], B[6]); U64 r7 = add64(A[7], B[7]); U64 r8 = add64(A[8], B[8]); U64 r9 = add64(A[9], B[9]); U64 r10= add64(A[10],B[10]); /* lt = {r0 - r10} < 2*n */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)( r0, ((U64*)(n521_x2))[0], 0); lt = MB_FUNC_NAME(lt_mbx_digit_)( r1, ((U64*)(n521_x2))[1], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r2, ((U64*)(n521_x2))[2], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r3, ((U64*)(n521_x2))[3], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r4, ((U64*)(n521_x2))[4], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r5, ((U64*)(n521_x2))[5], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r6, ((U64*)(n521_x2))[6], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r7, ((U64*)(n521_x2))[7], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r8, ((U64*)(n521_x2))[8], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r9, ((U64*)(n521_x2))[9], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r10,((U64*)(n521_x2))[10],lt); /* {r0 - r10} -= 2*p */ r0 = mask_sub64(r0, ~lt, r0, ((U64*)(n521_x2))[0]); r1 = mask_sub64(r1, ~lt, r1, ((U64*)(n521_x2))[1]); r2 = mask_sub64(r2, ~lt, r2, ((U64*)(n521_x2))[2]); r3 = mask_sub64(r3, ~lt, r3, ((U64*)(n521_x2))[3]); r4 = mask_sub64(r4, ~lt, r4, ((U64*)(n521_x2))[4]); r5 = mask_sub64(r5, ~lt, r5, ((U64*)(n521_x2))[5]); r6 = mask_sub64(r6, ~lt, r6, ((U64*)(n521_x2))[6]); r7 = mask_sub64(r7, ~lt, r7, ((U64*)(n521_x2))[7]); r8 = mask_sub64(r8, ~lt, r8, ((U64*)(n521_x2))[8]); r9 = mask_sub64(r9, ~lt, r9, ((U64*)(n521_x2))[9]); r10= mask_sub64(r10,~lt, r10,((U64*)(n521_x2))[10]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9,10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } void MB_FUNC_NAME(ifma_sub52_n521_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); U64 r5 = sub64(A[5], B[5]); U64 r6 = sub64(A[6], B[6]); U64 r7 = sub64(A[7], B[7]); U64 r8 = sub64(A[8], B[8]); U64 r9 = sub64(A[9], B[9]); U64 r10= sub64(A[10],B[10]); /* lt = {r0 - r10} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r5, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r6, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r7, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r8, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r9, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r10,get_zero64(), lt); r0 = mask_add64(r0, lt, r0, ((U64*)(n521_x2))[0]); r1 = mask_add64(r1, lt, r1, ((U64*)(n521_x2))[1]); r2 = mask_add64(r2, lt, r2, ((U64*)(n521_x2))[2]); r3 = mask_add64(r3, lt, r3, ((U64*)(n521_x2))[3]); r4 = mask_add64(r4, lt, r4, ((U64*)(n521_x2))[4]); r5 = mask_add64(r5, lt, r5, ((U64*)(n521_x2))[5]); r6 = mask_add64(r6, lt, r6, ((U64*)(n521_x2))[6]); r7 = mask_add64(r7, lt, r7, ((U64*)(n521_x2))[7]); r8 = mask_add64(r8, lt, r8, ((U64*)(n521_x2))[8]); r9 = mask_add64(r9, lt, r9, ((U64*)(n521_x2))[9]); r10= mask_add64(r10,lt, r10,((U64*)(n521_x2))[10]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9, 10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } void MB_FUNC_NAME(ifma_neg52_n521_)(U64 R[], const U64 A[]) { __mb_mask nz_mask = ~MB_FUNC_NAME(is_zero_FE521_)(A); /* {r0 - r10} = 2*p - A */ U64 r0 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[0], A[0] ); U64 r1 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[1], A[1] ); U64 r2 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[2], A[2] ); U64 r3 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[3], A[3] ); U64 r4 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[4], A[4] ); U64 r5 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[5], A[5] ); U64 r6 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[6], A[6] ); U64 r7 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[7], A[7] ); U64 r8 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[8], A[8] ); U64 r9 = mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[9], A[9] ); U64 r10= mask_sub64( A[0], nz_mask, ((U64*)(n521_x2))[10],A[10]); /* normalize r0 - r10 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9, 10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } // Disable optimization for VS17 #if defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__INTEL_COMPILER) #pragma optimize( "", off ) #endif /* r = (a>=n521)? a-n521 : a */ void MB_FUNC_NAME(ifma_fastred52_pn521_)(U64 R[], const U64 A[]) { /* r = a - b */ U64 r0 = sub64(A[0], ((U64*)(n521_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(n521_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(n521_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(n521_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(n521_mb))[4]); U64 r5 = sub64(A[5], ((U64*)(n521_mb))[5]); U64 r6 = sub64(A[6], ((U64*)(n521_mb))[6]); U64 r7 = sub64(A[7], ((U64*)(n521_mb))[7]); U64 r8 = sub64(A[8], ((U64*)(n521_mb))[8]); U64 r9 = sub64(A[9], ((U64*)(n521_mb))[9]); U64 r10= sub64(A[10],((U64*)(n521_mb))[10]); /* lt = {r0 - r10} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r5, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r6, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r7, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r8, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r9, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r10,get_zero64(), lt); r0 = mask_mov64(A[0], ~lt, r0); r1 = mask_mov64(A[1], ~lt, r1); r2 = mask_mov64(A[2], ~lt, r2); r3 = mask_mov64(A[3], ~lt, r3); r4 = mask_mov64(A[4], ~lt, r4); r5 = mask_mov64(A[5], ~lt, r5); r6 = mask_mov64(A[6], ~lt, r6); r7 = mask_mov64(A[7], ~lt, r7); r8 = mask_mov64(A[8], ~lt, r8); r9 = mask_mov64(A[9], ~lt, r9); r10= mask_mov64(A[10],~lt, r10); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9,10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } #if defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__INTEL_COMPILER) #pragma optimize( "", on ) #endif __mb_mask MB_FUNC_NAME(ifma_cmp_lt_n521_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FE521_)(a,(const U64 (*))n521_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_n521_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FE521_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_n521_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_p256.c000066400000000000000000000501201470420105600303240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ #define LEN52 NUMBER_OF_DIGITS(256,DIGIT_SIZE) /* // prime256 = 2^256 - 2^224 + 2^192 + 2^96 -1 // in 2^52 radix */ __ALIGN64 static const int64u p256_mb[LEN52][8] = { { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x00000fffffffffff) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000001000000000) }, { REP8_DECL(0x0000ffffffff0000) } }; __ALIGN64 static const int64u p256x2_mb[LEN52][8] = { { REP8_DECL(0x000ffffffffffffe) }, { REP8_DECL(0x00001fffffffffff) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000002000000000) }, { REP8_DECL(0x0001fffffffe0000) } }; /* // Note that // k0 = -(1/p256 mod 2^DIGIT_SIZE) equals 1 // The implementation takes this fact into account */ /* to Montgomery conversion constant // rr = 2^((5*DIGIT_SIZE)*2) mod p256 */ __ALIGN64 static const int64u p256_rr_mb[5][8] = { { REP8_DECL(0x0000000000000300) }, { REP8_DECL(0x000ffffffff00000) }, { REP8_DECL(0x000ffffefffffffb) }, { REP8_DECL(0x000fdfffffffffff) }, { REP8_DECL(0x0000000004ffffff) } }; /* other constants */ __ALIGN64 static const int64u VDIGIT_MASK_[8] = {DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK}; #define VDIGIT_MASK loadu64(VDIGIT_MASK_) #define P256_PRIME_TOP_ 0xFFFFFFFF0000LL __ALIGN64 static const int64u VP256_PRIME_TOP_[8] = {P256_PRIME_TOP_, P256_PRIME_TOP_, P256_PRIME_TOP_, P256_PRIME_TOP_, P256_PRIME_TOP_, P256_PRIME_TOP_, P256_PRIME_TOP_, P256_PRIME_TOP_}; #define VP256_PRIME_TOP loadu64(VP256_PRIME_TOP_) /* Round operations */ #define ROUND_MUL_SRC(I, J, S_LO, R_LO, S_HI, R_HI) \ R_LO = fma52lo(S_LO, va[I], vb[J]); \ R_HI = fma52hi(S_HI, va[I], vb[J]); #define ROUND_MUL(I, J, M0, M1) \ ROUND_MUL_SRC(I, J, M0, M0, M1, M1) /* Reduction round for p256 prime */ // Note that k == 1 for p256 curve #ifdef IFMA_RED #define MUL_ADD_P256(u, res0, res1, res2, res3, res4, res5) \ { \ U64 u = and64_const(res0, DIGIT_MASK); /* k == 1 */ \ res0 = fma52lo(res0, u, set64((1ULL<<52) - 1)); \ res1 = fma52hi(res1, u, set64((1ULL<<52) - 1)); \ res1 = add64(res1, srli64(res0, 52)); \ res1 = fma52lo(res1, u, set64((1ULL<<44) - 1)); \ res2 = fma52hi(res2, u, set64((1ULL<<44) - 1)); \ res3 = fma52lo(res3, u, set64(1ULL<<36)); \ res4 = fma52hi(res4, u, set64(1ULL<<36)); \ res4 = fma52lo(res4, u, set64(0xFFFFFFFF0000LL)); \ res5 = fma52hi(res5, u, set64(0xFFFFFFFF0000LL)); \ } #else // IFMA_RED #define MUL_ADD_P256(u, res0, res1, res2, res3, res4, res5) \ { \ /* a * ( 2^96 - 1 ) = -a + a * 2^96 = -a + a * 2^{52+44} */ \ U64 u = and64(res0, VDIGIT_MASK); /* k == 1 */ \ /*res0 = sub64(res0, u);*/ /* Zero out low 52 bits */ \ res1 = add64(res1, srli64(res0, DIGIT_SIZE)); /* Carry propagation */ \ res1 = add64(res1, and64(slli64(u, 44), VDIGIT_MASK)); \ res2 = add64(res2, srli64(u, DIGIT_SIZE - 44)); \ /* ( a * 2^{36} ) * 2^{52*3} */ \ res3 = add64(res3, and64(slli64(u, 36), VDIGIT_MASK)); \ res4 = add64(res4, srli64(u, DIGIT_SIZE - 36)); \ /* ( a * (2^{48} - 1) - a * (2^{16} - 1) ) * 2^{52*4} = */ \ /* ( a * 2^{48} - a * 2^{16} ) * 2^{52*4} */ \ res4 = fma52lo(res4, u, VP256_PRIME_TOP); \ res5 = fma52hi(res5, u, VP256_PRIME_TOP); \ } #endif // IFMA_RED /*===================================================================== Specialized single and dual operations in p256 - sqr & mul =====================================================================*/ void MB_FUNC_NAME(ifma_ams52_p256_)(U64 r[], const U64 va[]) { const U64* vb = va; U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // Calculate full square ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(2, 3, r5, r6) r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); ROUND_MUL(0, 0, r0, r1) ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 4, r8, r9) // Reduction MUL_ADD_P256(u0, r0, r1, r2, r3, r4, r5); MUL_ADD_P256(u1, r1, r2, r3, r4, r5, r6); MUL_ADD_P256(u2, r2, r3, r4, r5, r6, r7); MUL_ADD_P256(u3, r3, r4, r5, r6, r7, r8); MUL_ADD_P256(u4, r4, r5, r6, r7, r8, r9); // normalization NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) NORM_LSHIFTR(r, 7, 8) NORM_LSHIFTR(r, 8, 9) r[0] = r5; r[1] = r6; r[2] = r7; r[3] = r8; r[4] = r9; } void MB_FUNC_NAME(ifma_amm52_p256_)(U64 r[], const U64 va[], const U64 vb[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); ROUND_MUL(4, 4, r8, r9) ROUND_MUL(3, 0, r3, r4) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(2, 1, r3, r4) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(3, 1, r4, r5) ROUND_MUL(4, 0, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(2, 3, r5, r6) ROUND_MUL(3, 2, r5, r6) ROUND_MUL(4, 1, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 2, r6, r7) ROUND_MUL(0, 0, r0, r1) ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(1, 0, r1, r2) ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 0, r2, r3) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(4, 3, r7, r8) // Reduction MUL_ADD_P256(u0, r0, r1, r2, r3, r4, r5); MUL_ADD_P256(u1, r1, r2, r3, r4, r5, r6); MUL_ADD_P256(u2, r2, r3, r4, r5, r6, r7); MUL_ADD_P256(u3, r3, r4, r5, r6, r7, r8); MUL_ADD_P256(u4, r4, r5, r6, r7, r8, r9); // normalization NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) NORM_LSHIFTR(r, 7, 8) NORM_LSHIFTR(r, 8, 9) r[0] = r5; r[1] = r6; r[2] = r7; r[3] = r8; r[4] = r9; } void MB_FUNC_NAME(ifma_ams52_p256_dual_)(U64 r0[], U64 r1[], const U64 inp0[], const U64 inp1[]) { U64 *va; // = (U64 *)inp0; U64 *vb; // = (U64 *)inp0; U64 r00, r01, r02, r03, r04, r05, r06, r07, r08, r09; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; r00 = r01 = r02 = r03 = r04 = r05 = r06 = r07 = r08 = r09 = get_zero64(); r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = get_zero64(); /// Calculate full square va = vb = (U64 *)inp0; // Multiplication ROUND_MUL(0, 1, r01, r02) ROUND_MUL(0, 2, r02, r03) ROUND_MUL(0, 3, r03, r04) ROUND_MUL(0, 4, r04, r05) ROUND_MUL(1, 4, r05, r06) ROUND_MUL(2, 4, r06, r07) ROUND_MUL(3, 4, r07, r08) ROUND_MUL(1, 2, r03, r04) ROUND_MUL(1, 3, r04, r05) ROUND_MUL(2, 3, r05, r06) // Doubling r01 = add64(r01, r01); r02 = add64(r02, r02); r03 = add64(r03, r03); r04 = add64(r04, r04); r05 = add64(r05, r05); r06 = add64(r06, r06); r07 = add64(r07, r07); r08 = add64(r08, r08); // Adding square ROUND_MUL(0, 0, r00, r01) ROUND_MUL(1, 1, r02, r03) ROUND_MUL(2, 2, r04, r05) ROUND_MUL(3, 3, r06, r07) ROUND_MUL(4, 4, r08, r09) /// Calculate full square va = vb = (U64 *)inp1; // Multiplication ROUND_MUL(0, 1, r11, r12) ROUND_MUL(0, 2, r12, r13) ROUND_MUL(0, 3, r13, r14) ROUND_MUL(0, 4, r14, r15) ROUND_MUL(1, 4, r15, r16) ROUND_MUL(2, 4, r16, r17) ROUND_MUL(3, 4, r17, r18) ROUND_MUL(1, 2, r13, r14) ROUND_MUL(1, 3, r14, r15) ROUND_MUL(2, 3, r15, r16) // Doubling r11 = add64(r11, r11); r12 = add64(r12, r12); r13 = add64(r13, r13); r14 = add64(r14, r14); r15 = add64(r15, r15); r16 = add64(r16, r16); r17 = add64(r17, r17); r18 = add64(r18, r18); // Adding square ROUND_MUL(0, 0, r10, r11) ROUND_MUL(1, 1, r12, r13) ROUND_MUL(2, 2, r14, r15) ROUND_MUL(3, 3, r16, r17) ROUND_MUL(4, 4, r18, r19) // Reduction res0 MUL_ADD_P256(u0, r00, r01, r02, r03, r04, r05); MUL_ADD_P256(u1, r01, r02, r03, r04, r05, r06); MUL_ADD_P256(u2, r02, r03, r04, r05, r06, r07); MUL_ADD_P256(u3, r03, r04, r05, r06, r07, r08); MUL_ADD_P256(u4, r04, r05, r06, r07, r08, r09); // Reduction res1 MUL_ADD_P256(u0, r10, r11, r12, r13, r14, r15); MUL_ADD_P256(u1, r11, r12, r13, r14, r15, r16); MUL_ADD_P256(u2, r12, r13, r14, r15, r16, r17); MUL_ADD_P256(u3, r13, r14, r15, r16, r17, r18); MUL_ADD_P256(u4, r14, r15, r16, r17, r18, r19); // normalization res0 NORM_LSHIFTR(r0, 5, 6) NORM_LSHIFTR(r0, 6, 7) NORM_LSHIFTR(r0, 7, 8) NORM_LSHIFTR(r0, 8, 9) r0[0] = r05; r0[1] = r06; r0[2] = r07; r0[3] = r08; r0[4] = r09; // normalization res1 NORM_LSHIFTR(r1, 5, 6) NORM_LSHIFTR(r1, 6, 7) NORM_LSHIFTR(r1, 7, 8) NORM_LSHIFTR(r1, 8, 9) r1[0] = r15; r1[1] = r16; r1[2] = r17; r1[3] = r18; r1[4] = r19; } void MB_FUNC_NAME(ifma_amm52_p256_dual_)(U64 r0[], U64 r1[], const U64 inp0A[], const U64 inp0B[], const U64 inp1A[], const U64 inp1B[]) { U64 *va, *vb; U64 r00, r01, r02, r03, r04, r05, r06, r07, r08, r09; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; r00 = r01 = r02 = r03 = r04 = r05 = r06 = r07 = r08 = r09 = get_zero64(); r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = get_zero64(); // 5x5 multiplication va = (U64 *)inp0A; vb = (U64 *)inp0B; ROUND_MUL(4, 4, r08, r09) ROUND_MUL(3, 0, r03, r04) ROUND_MUL(1, 2, r03, r04) ROUND_MUL(0, 3, r03, r04) ROUND_MUL(2, 1, r03, r04) ROUND_MUL(2, 2, r04, r05) ROUND_MUL(0, 4, r04, r05) ROUND_MUL(1, 3, r04, r05) ROUND_MUL(3, 1, r04, r05) ROUND_MUL(4, 0, r04, r05) ROUND_MUL(1, 4, r05, r06) ROUND_MUL(2, 3, r05, r06) ROUND_MUL(3, 2, r05, r06) ROUND_MUL(4, 1, r05, r06) ROUND_MUL(2, 4, r06, r07) ROUND_MUL(3, 3, r06, r07) ROUND_MUL(4, 2, r06, r07) ROUND_MUL(0, 0, r00, r01) ROUND_MUL(0, 1, r01, r02) ROUND_MUL(0, 2, r02, r03) ROUND_MUL(1, 0, r01, r02) ROUND_MUL(1, 1, r02, r03) ROUND_MUL(2, 0, r02, r03) ROUND_MUL(3, 4, r07, r08) ROUND_MUL(4, 3, r07, r08) // 5x5 multiplication va = (U64 *)inp1A; vb = (U64 *)inp1B; ROUND_MUL(4, 4, r18, r19) ROUND_MUL(3, 0, r13, r14) ROUND_MUL(1, 2, r13, r14) ROUND_MUL(0, 3, r13, r14) ROUND_MUL(2, 1, r13, r14) ROUND_MUL(2, 2, r14, r15) ROUND_MUL(0, 4, r14, r15) ROUND_MUL(1, 3, r14, r15) ROUND_MUL(3, 1, r14, r15) ROUND_MUL(4, 0, r14, r15) ROUND_MUL(1, 4, r15, r16) ROUND_MUL(2, 3, r15, r16) ROUND_MUL(3, 2, r15, r16) ROUND_MUL(4, 1, r15, r16) ROUND_MUL(2, 4, r16, r17) ROUND_MUL(3, 3, r16, r17) ROUND_MUL(4, 2, r16, r17) ROUND_MUL(0, 0, r10, r11) ROUND_MUL(0, 1, r11, r12) ROUND_MUL(0, 2, r12, r13) ROUND_MUL(1, 0, r11, r12) ROUND_MUL(1, 1, r12, r13) ROUND_MUL(2, 0, r12, r13) ROUND_MUL(3, 4, r17, r18) ROUND_MUL(4, 3, r17, r18) // Reduction for input 0 MUL_ADD_P256(u0, r00, r01, r02, r03, r04, r05) MUL_ADD_P256(u1, r01, r02, r03, r04, r05, r06) MUL_ADD_P256(u2, r02, r03, r04, r05, r06, r07) MUL_ADD_P256(u3, r03, r04, r05, r06, r07, r08) MUL_ADD_P256(u4, r04, r05, r06, r07, r08, r09) // Reduction for input 1 MUL_ADD_P256(u0, r10, r11, r12, r13, r14, r15) MUL_ADD_P256(u1, r11, r12, r13, r14, r15, r16) MUL_ADD_P256(u2, r12, r13, r14, r15, r16, r17) MUL_ADD_P256(u3, r13, r14, r15, r16, r17, r18) MUL_ADD_P256(u4, r14, r15, r16, r17, r18, r19) // normalization res0 NORM_LSHIFTR(r0, 5, 6) NORM_LSHIFTR(r0, 6, 7) NORM_LSHIFTR(r0, 7, 8) NORM_LSHIFTR(r0, 8, 9) r0[0] = r05; r0[1] = r06; r0[2] = r07; r0[3] = r08; r0[4] = r09; // normalization res1 NORM_LSHIFTR(r1, 5, 6) NORM_LSHIFTR(r1, 6, 7) NORM_LSHIFTR(r1, 7, 8) NORM_LSHIFTR(r1, 8, 9) r1[0] = r15; r1[1] = r16; r1[2] = r17; r1[3] = r18; r1[4] = r19; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define LEN52 NUMBER_OF_DIGITS(256,DIGIT_SIZE) void MB_FUNC_NAME(ifma_reduce52_p256_)(U64 R[], const U64 A[]) { /* r = a - p256_mb */ U64 r0 = sub64(A[0], ((U64*)(p256_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(p256_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(p256_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(p256_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(p256_mb))[4]); /* normalize r0 - r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) /* r = a> 1 */ mask = sub64(get_zero64(), and64(t1, one)); t0 = add64(t0, and64(base, mask)); t0 = srli64(t0, 1); mask = sub64(get_zero64(), and64(t2, one)); t1 = add64(t1, and64(base, mask)); t1 = srli64(t1, 1); mask = sub64(get_zero64(), and64(t3, one)); t2 = add64(t2, and64(base, mask)); t2 = srli64(t2, 1); mask = sub64(get_zero64(), and64(t4, one)); t3 = add64(t3, and64(base, mask)); t3 = srli64(t3, 1); t4 = srli64(t4, 1); /* normalize t0, t1, t2, t3, t4 */ NORM_LSHIFTR(t, 0,1) NORM_LSHIFTR(t, 1,2) NORM_LSHIFTR(t, 2,3) NORM_LSHIFTR(t, 3,4) r[0] = t0; r[1] = t1; r[2] = t2; r[3] = t3; r[4] = t4; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_p256_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FE256_)(a,(const U64 (*))p256_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_p256_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FE256_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_p256_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_p384.c000066400000000000000000000516261470420105600303420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ /* // p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1 // in 2^52 radix */ __ALIGN64 static const int64u p384_mb[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x00000000ffffffff) }, { REP8_DECL(0x000ff00000000000) }, { REP8_DECL(0x000ffffffeffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x00000000000fffff) } }; /* 2*p384 */ __ALIGN64 static const int64u p384_x2[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x00000001fffffffe) }, { REP8_DECL(0x000fe00000000000) }, { REP8_DECL(0x000ffffffdffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x00000000001fffff) } }; /* // Note that // k0 = -(1/p384 mod 2^DIGIT_SIZE) equals 1 // The implementation takes this fact into account */ /* to Montgomery conversion constant // rr = 2^((P384_LEN52*DIGIT_SIZE)*2) mod p384 */ __ALIGN64 static const int64u p384_rr_mb[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x000fe00000001000) }, { REP8_DECL(0x0000000000ffffff) }, { REP8_DECL(0x0000000000000020) }, { REP8_DECL(0x0000fffffffe0000) }, { REP8_DECL(0x0000000020000000) }, { REP8_DECL(0x0000000000000100) }, { REP8_DECL(0x0000000000000000) } }; /*===================================================================== Specialized operations over p384: sqr & mul =====================================================================*/ #define ROUND_MUL(I, J, R_LO, R_HI) \ R_LO = fma52lo(R_LO, va[I], vb[J]); \ R_HI = fma52hi(R_HI, va[I], vb[J]); #define P384_REDUCTION_ROUND(u, r0, r1, r2, r3, r4, r5, r6, r7, r8, modulus) \ { \ U64 t = sub64(get_zero64(), u); \ U64 lo = and64(t, loadu64(VMASK52)); \ U64 hi = add64(u, srai64(t,63)); \ \ r0 = fma52lo(r0, u, modulus[0]); \ r1 = fma52lo(r1, u, modulus[1]); \ r2 = fma52lo(r2, u, modulus[2]); \ r3 = add64(r3, lo); /*r3 = fma52lo(r3, u, modulus[3]); */ \ r4 = add64(r4, lo); /*r4 = fma52lo(r4, u, modulus[4]); */ \ r5 = add64(r5, lo); /*r5 = fma52lo(r5, u, modulus[5]); */ \ r6 = add64(r6, lo); /*r6 = fma52lo(r6, u, modulus[6]); */ \ r7 = fma52lo(r7, u, modulus[7]); \ \ r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ \ \ r1 = fma52hi(r1, u, modulus[0]); \ r2 = fma52hi(r2, u, modulus[1]); \ r3 = fma52hi(r3, u, modulus[2]); \ r8 = fma52hi(r8, u, modulus[7]); \ u = and64(add64(r1, slli64(r1, 32)), loadu64(VMASK52)); /* update u = r1*k, k = (2^32 +1) */ \ r4 = add64(r4, hi); /*r4 = fma52hi(r4, u, modulus[3]); */ \ r5 = add64(r5, hi); /*r5 = fma52hi(r5, u, modulus[4]); */ \ r6 = add64(r6, hi); /*r6 = fma52hi(r6, u, modulus[5]); */ \ r7 = add64(r7, hi); /*r7 = fma52hi(r7, u, modulus[6]); */ \ } void MB_FUNC_NAME(ifma_amm52_p384_)(U64 r[], const U64 va[], const U64 vb[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7; int itr; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = get_zero64(); for(itr=0; itr < P384_LEN52; itr++) { U64 Yi, T, LO, HI; U64 Bi = loadu64(vb); vb++; fma52lo_mem(r0, r0, Bi, va, SIMD_BYTES * 0); Yi = and64(add64(r0, slli64(r0, 32)), loadu64(VMASK52)); /* k = (2^32 +1) */ T = sub64(get_zero64(), Yi); LO = and64(T, loadu64(VMASK52)); HI = add64(Yi, srai64(T,63)); fma52lo_mem(r1, r1, Bi, va, SIMD_BYTES * 1); fma52lo_mem(r2, r2, Bi, va, SIMD_BYTES * 2); fma52lo_mem(r3, r3, Bi, va, SIMD_BYTES * 3); fma52lo_mem(r4, r4, Bi, va, SIMD_BYTES * 4); fma52lo_mem(r5, r5, Bi, va, SIMD_BYTES * 5); fma52lo_mem(r6, r6, Bi, va, SIMD_BYTES * 6); fma52lo_mem(r7, r7, Bi, va, SIMD_BYTES * 7); fma52lo_mem(r0, r0, Yi, p384_mb, SIMD_BYTES * 0); fma52lo_mem(r1, r1, Yi, p384_mb, SIMD_BYTES * 1); r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ fma52lo_mem(r2, r2, Yi, p384_mb, SIMD_BYTES * 2); r3 = add64(r3, LO); /* fma52lo_mem(r3, r3, Yi, p384_mb, SIMD_BYTES * 3); */ r4 = add64(r4, LO); /* fma52lo_mem(r4, r4, Yi, p384_mb, SIMD_BYTES * 4); */ r5 = add64(r5, LO); /* fma52lo_mem(r5, r5, Yi, p384_mb, SIMD_BYTES * 5); */ r6 = add64(r6, LO); /* fma52lo_mem(r6, r6, Yi, p384_mb, SIMD_BYTES * 6); */ fma52lo_mem(r7, r7, Yi, p384_mb, SIMD_BYTES * 7); fma52hi_mem(r0, r1, Bi, va, SIMD_BYTES * 0); fma52hi_mem(r1, r2, Bi, va, SIMD_BYTES * 1); fma52hi_mem(r2, r3, Bi, va, SIMD_BYTES * 2); fma52hi_mem(r3, r4, Bi, va, SIMD_BYTES * 3); fma52hi_mem(r4, r5, Bi, va, SIMD_BYTES * 4); fma52hi_mem(r5, r6, Bi, va, SIMD_BYTES * 5); fma52hi_mem(r6, r7, Bi, va, SIMD_BYTES * 6); fma52hi_mem(r7, get_zero64(), Bi, va, SIMD_BYTES * 7); fma52hi_mem(r0, r0, Yi, p384_mb, SIMD_BYTES * 0); fma52hi_mem(r1, r1, Yi, p384_mb, SIMD_BYTES * 1); fma52hi_mem(r2, r2, Yi, p384_mb, SIMD_BYTES * 2); r3 = add64(r3, HI); /* fma52hi_mem(r3, r3, Yi, p384_mb, SIMD_BYTES * 3); */ r4 = add64(r4, HI); /* fma52hi_mem(r4, r4, Yi, p384_mb, SIMD_BYTES * 4); */ r5 = add64(r5, HI); /* fma52hi_mem(r5, r5, Yi, p384_mb, SIMD_BYTES * 5); */ r6 = add64(r6, HI); /* fma52hi_mem(r6, r6, Yi, p384_mb, SIMD_BYTES * 6); */ fma52hi_mem(r7, r7, Yi, p384_mb, SIMD_BYTES * 7); } // normalization NORM_LSHIFTR(r, 0, 1) NORM_LSHIFTR(r, 1, 2) NORM_LSHIFTR(r, 2, 3) NORM_LSHIFTR(r, 3, 4) NORM_LSHIFTR(r, 4, 5) NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) r[0] = r0; r[1] = r1; r[2] = r2; r[3] = r3; r[4] = r4; r[5] = r5; r[6] = r6; r[7] = r7; } void MB_FUNC_NAME(ifma_ams52_p384_)(U64 r[], const U64 va[]) { const U64* vb = va; U64* modulus = (U64*)p384_mb; U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = get_zero64(); // full square ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(0, 5, r5, r6) ROUND_MUL(0, 6, r6, r7) ROUND_MUL(0, 7, r7, r8) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(1, 5, r6, r7) ROUND_MUL(1, 6, r7, r8) ROUND_MUL(1, 7, r8, r9) ROUND_MUL(2, 3, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(2, 5, r7, r8) ROUND_MUL(2, 6, r8, r9) ROUND_MUL(2, 7, r9, r10) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(3, 5, r8, r9) ROUND_MUL(3, 6, r9, r10) ROUND_MUL(3, 7, r10,r11) ROUND_MUL(4, 5, r9, r10) ROUND_MUL(4, 6, r10,r11) ROUND_MUL(4, 7, r11,r12) ROUND_MUL(5, 6, r11,r12) ROUND_MUL(5, 7, r12,r13) ROUND_MUL(6, 7, r13,r14) r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); r9 = add64(r9, r9); r10 = add64(r10, r10); r11 = add64(r11, r11); r12 = add64(r12, r12); r13 = add64(r13, r13); r14 = add64(r14, r14); U64 u; ROUND_MUL(0, 0, r0, r1) u = and64(add64(r0, slli64(r0, 32)), loadu64(VMASK52)); ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 4, r8, r9) ROUND_MUL(5, 5, r10, r11) ROUND_MUL(6, 6, r12, r13) ROUND_MUL(7, 7, r14, r15) // reduction P384_REDUCTION_ROUND(u, r0, r1, r2, r3, r4, r5, r6, r7, r8, modulus); P384_REDUCTION_ROUND(u, r1, r2, r3, r4, r5, r6, r7, r8, r9, modulus); P384_REDUCTION_ROUND(u, r2, r3, r4, r5, r6, r7, r8, r9, r10, modulus); P384_REDUCTION_ROUND(u, r3, r4, r5, r6, r7, r8, r9, r10,r11, modulus); P384_REDUCTION_ROUND(u, r4, r5, r6, r7, r8, r9, r10,r11,r12, modulus); P384_REDUCTION_ROUND(u, r5, r6, r7, r8, r9, r10,r11,r12,r13, modulus); P384_REDUCTION_ROUND(u, r6, r7, r8, r9, r10,r11,r12,r13,r14, modulus); P384_REDUCTION_ROUND(u, r7, r8, r9, r10,r11,r12,r13,r14,r15, modulus); // normalization NORM_LSHIFTR(r, 8, 9) NORM_LSHIFTR(r, 9, 10) NORM_LSHIFTR(r, 10, 11) NORM_LSHIFTR(r, 11, 12) NORM_LSHIFTR(r, 12, 13) NORM_LSHIFTR(r, 13, 14) NORM_LSHIFTR(r, 14, 15) r[0] = r8; r[1] = r9; r[2] = r10; r[3] = r11; r[4] = r12; r[5] = r13; r[6] = r14; r[7] = r15; } void MB_FUNC_NAME(ifma_reduce52_p384_)(U64 R[], const U64 A[]) { /* r = a - p384_mb */ U64 r0 = sub64(A[0], ((U64*)(p384_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(p384_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(p384_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(p384_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(p384_mb))[4]); U64 r5 = sub64(A[5], ((U64*)(p384_mb))[5]); U64 r6 = sub64(A[6], ((U64*)(p384_mb))[6]); U64 r7 = sub64(A[7], ((U64*)(p384_mb))[7]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) /* r = a r = z^(0xFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFE FFFFFFFF00000000 00000000FFFFFFFD) // // note: z in in Montgomery domain (as soon mul() and sqr() below are amm-functions // r in Montgomery domain too */ #define fe52_sqr MB_FUNC_NAME(ifma_ams52_p384_) #define fe52_mul MB_FUNC_NAME(ifma_amm52_p384_) /* r = base^(2^n) */ __MBX_INLINE void fe52_sqr_pwr(U64 r[], const U64 base[], int n) { if(r!=base) MB_FUNC_NAME(mov_FE384_)(r, base); for(; n>0; n--) fe52_sqr(r,r); } void MB_FUNC_NAME(ifma_aminv52_p384_)(U64 r[], const U64 z[]) { __ALIGN64 U64 u[P384_LEN52]; __ALIGN64 U64 v[P384_LEN52]; __ALIGN64 U64 zD[P384_LEN52]; __ALIGN64 U64 zE[P384_LEN52]; __ALIGN64 U64 zF[P384_LEN52]; fe52_sqr(u, z); /* u = z^2 */ fe52_mul(v, u, z); /* v = z^2 * z = z^3 */ fe52_sqr_pwr(zF, v, 2); /* zF= (z^3)^(2^2) = z^12 */ fe52_mul(zD, zF, z); /* zD = z^12 * z = z^xD */ fe52_mul(zE, zF, u); /* zE = z^12 * z^2 = z^xE */ fe52_mul(zF, zF, v); /* zF = z^12 * z^3 = z^xF */ fe52_sqr_pwr(u, zF, 4); /* u = (z^xF)^(2^4) = z^xF0 */ fe52_mul(zD, u, zD); /* zD = z^xF0 * z^xD = z^xFD */ fe52_mul(zE, u, zE); /* zE = z^xF0 * z^xE = z^xFE */ fe52_mul(zF, u, zF); /* zF = z^xF0 * z^xF = z^xFF */ fe52_sqr_pwr(u, zF, 8); /* u = (z^xFF)^(2^8) = z^xFF00 */ fe52_mul(zD, u, zD); /* zD = z^xFF00 * z^xFD = z^xFFFD */ fe52_mul(zE, u, zE); /* zE = z^xFF00 * z^xFE = z^xFFFE */ fe52_mul(zF, u, zF); /* zF = z^xFF00 * z^xFF = z^xFFFF */ fe52_sqr_pwr(u, zF, 16); /* u = (z^xFFFF)^(2^16) = z^xFFFF0000 */ fe52_mul(zD, u, zD); /* zD = z^xFFFF0000 * z^xFFFD = z^xFFFFFFFD */ fe52_mul(zE, u, zE); /* zE = z^xFFFF0000 * z^xFFFE = z^xFFFFFFFE */ fe52_mul(zF, u, zF); /* zF = z^xFFFF0000 * z^xFFFF = z^xFFFFFFFF */ fe52_sqr_pwr(u, zF, 32); /* u = (z^xFFFFFFFF)^(2^32) = z^xFFFFFFFF00000000 */ fe52_mul(zE, u, zE); /* zE = z^xFFFFFFFF00000000 * z^xFFFFFFFE = z^xFFFFFFFFFFFFFFFE */ fe52_mul(zF, u, zF); /* zF = z^xFFFFFFFF00000000 * z^xFFFFFFFF = z^xFFFFFFFFFFFFFFFF */ /* v = z^xFFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, zF, 64); fe52_mul(v, v, zF); /* v = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFE = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zE); /* v = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.0000000000000000 * z^xFFFFFFFF00000000 = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFF00000000 */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, u); /* r = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFF00000000.0000000000000000 * z^xFFFFFFFD = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFF00000000.00000000FFFFFFFD */ fe52_sqr_pwr(v, v, 64); fe52_mul(r, v, zD); } /*===================================================================== Specialized single operations over p384: add, sub, neg =====================================================================*/ __MBX_INLINE __mb_mask MB_FUNC_NAME(lt_mbx_digit_)(const U64 a, const U64 b, const __mb_mask lt_mask) { U64 d = mask_sub64(sub64(a, b), lt_mask, sub64(a, b), set1(1)); return cmp64_mask(d, get_zero64(), _MM_CMPINT_LT); } void MB_FUNC_NAME(ifma_add52_p384_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a + b */ U64 r0 = add64(A[0], B[0]); U64 r1 = add64(A[1], B[1]); U64 r2 = add64(A[2], B[2]); U64 r3 = add64(A[3], B[3]); U64 r4 = add64(A[4], B[4]); U64 r5 = add64(A[5], B[5]); U64 r6 = add64(A[6], B[6]); U64 r7 = add64(A[7], B[7]); /* lt = {r0 - r7} < 2*p */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)( r0, ((U64*)(p384_x2))[0], 0); lt = MB_FUNC_NAME(lt_mbx_digit_)( r1, ((U64*)(p384_x2))[1], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r2, ((U64*)(p384_x2))[2], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r3, ((U64*)(p384_x2))[3], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r4, ((U64*)(p384_x2))[4], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r5, ((U64*)(p384_x2))[5], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r6, ((U64*)(p384_x2))[6], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r7, ((U64*)(p384_x2))[7], lt); /* {r0 - r7} -= 2*p */ r0 = mask_sub64(r0, ~lt, r0, ((U64*)(p384_x2))[0]); r1 = mask_sub64(r1, ~lt, r1, ((U64*)(p384_x2))[1]); r2 = mask_sub64(r2, ~lt, r2, ((U64*)(p384_x2))[2]); r3 = mask_sub64(r3, ~lt, r3, ((U64*)(p384_x2))[3]); r4 = mask_sub64(r4, ~lt, r4, ((U64*)(p384_x2))[4]); r5 = mask_sub64(r5, ~lt, r5, ((U64*)(p384_x2))[5]); r6 = mask_sub64(r6, ~lt, r6, ((U64*)(p384_x2))[6]); r7 = mask_sub64(r7, ~lt, r7, ((U64*)(p384_x2))[7]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } void MB_FUNC_NAME(ifma_sub52_p384_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); U64 r5 = sub64(A[5], B[5]); U64 r6 = sub64(A[6], B[6]); U64 r7 = sub64(A[7], B[7]); /* lt = {r0 - r7} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r5, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r6, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r7, get_zero64(), lt); r0 = mask_add64(r0, lt, r0, ((U64*)(p384_x2))[0]); r1 = mask_add64(r1, lt, r1, ((U64*)(p384_x2))[1]); r2 = mask_add64(r2, lt, r2, ((U64*)(p384_x2))[2]); r3 = mask_add64(r3, lt, r3, ((U64*)(p384_x2))[3]); r4 = mask_add64(r4, lt, r4, ((U64*)(p384_x2))[4]); r5 = mask_add64(r5, lt, r5, ((U64*)(p384_x2))[5]); r6 = mask_add64(r6, lt, r6, ((U64*)(p384_x2))[6]); r7 = mask_add64(r7, lt, r7, ((U64*)(p384_x2))[7]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } void MB_FUNC_NAME(ifma_neg52_p384_)(U64 R[], const U64 A[]) { __mb_mask nz_mask = ~MB_FUNC_NAME(is_zero_FE384_)(A); /* {r0 - r7} = 2*p - A */ U64 r0 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[0], A[0] ); U64 r1 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[1], A[1] ); U64 r2 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[2], A[2] ); U64 r3 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[3], A[3] ); U64 r4 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[4], A[4] ); U64 r5 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[5], A[5] ); U64 r6 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[6], A[6] ); U64 r7 = mask_sub64( A[0], nz_mask, ((U64*)(p384_x2))[7], A[7] ); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) NORM_ASHIFTR(r, 4,5) NORM_ASHIFTR(r, 5,6) NORM_ASHIFTR(r, 6,7) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; } void MB_FUNC_NAME(ifma_double52_p384_)(U64 R[], const U64 A[]) { MB_FUNC_NAME(ifma_add52_p384_)(R, A, A); } void MB_FUNC_NAME(ifma_tripple52_p384_)(U64 R[], const U64 A[]) { U64 T[P384_LEN52]; MB_FUNC_NAME(ifma_add52_p384_)(T, A, A); MB_FUNC_NAME(ifma_add52_p384_)(R, T, A); } void MB_FUNC_NAME(ifma_half52_p384_)(U64 R[], const U64 A[]) { U64 one = set1(1); U64 base = set1(DIGIT_BASE); /* res = a + is_odd(a)? p384 : 0 */ U64 mask = sub64(get_zero64(), and64(A[0], one)); U64 t0 = add64(A[0], and64(((U64*)p384_mb)[0], mask)); U64 t1 = add64(A[1], and64(((U64*)p384_mb)[1], mask)); U64 t2 = add64(A[2], and64(((U64*)p384_mb)[2], mask)); U64 t3 = add64(A[3], and64(((U64*)p384_mb)[3], mask)); U64 t4 = add64(A[4], and64(((U64*)p384_mb)[4], mask)); U64 t5 = add64(A[5], and64(((U64*)p384_mb)[5], mask)); U64 t6 = add64(A[6], and64(((U64*)p384_mb)[6], mask)); U64 t7 = add64(A[7], and64(((U64*)p384_mb)[7], mask)); /* t =>> 1 */ mask = sub64(get_zero64(), and64(t1, one)); t0 = add64(t0, and64(base, mask)); t0 = srli64(t0, 1); mask = sub64(get_zero64(), and64(t2, one)); t1 = add64(t1, and64(base, mask)); t1 = srli64(t1, 1); mask = sub64(get_zero64(), and64(t3, one)); t2 = add64(t2, and64(base, mask)); t2 = srli64(t2, 1); mask = sub64(get_zero64(), and64(t4, one)); t3 = add64(t3, and64(base, mask)); t3 = srli64(t3, 1); mask = sub64(get_zero64(), and64(t5, one)); t4 = add64(t4, and64(base, mask)); t4 = srli64(t4, 1); mask = sub64(get_zero64(), and64(t6, one)); t5 = add64(t5, and64(base, mask)); t5 = srli64(t5, 1); mask = sub64(get_zero64(), and64(t7, one)); t6 = add64(t6, and64(base, mask)); t6 = srli64(t6, 1); t7 = srli64(t7, 1); /* normalize t0, t1, t2, t3, t4 */ NORM_LSHIFTR(t, 0,1) NORM_LSHIFTR(t, 1,2) NORM_LSHIFTR(t, 2,3) NORM_LSHIFTR(t, 3,4) NORM_LSHIFTR(t, 4,5) NORM_LSHIFTR(t, 5,6) NORM_LSHIFTR(t, 6,7) R[0] = t0; R[1] = t1; R[2] = t2; R[3] = t3; R[4] = t4; R[5] = t5; R[6] = t6; R[7] = t7; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_p384_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FE384_)(a,(const U64 (*))p384_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_p384_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FE384_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_p384_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_arith_p521.c000066400000000000000000000644141470420105600303320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ /* // p521 = 2^521 - 1 // in 2^52 radix */ __ALIGN64 static const int64u p521_mb[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000000000000001) } }; /* 2*p521 */ __ALIGN64 static const int64u p521_x2[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000ffffffffffffe) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000000000000003) } }; /* // Note that // k0 = -(1/p521 mod 2^DIGIT_SIZE) equals 1 // The implementation takes this fact into account */ /* to Montgomery conversion constant // rr = 2^((P521_LEN52*DIGIT_SIZE)*2) mod p521 */ __ALIGN64 static const int64u p521_rr_mb[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0004000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) } }; /*===================================================================== Specialized operations over p521: sqr & mul =====================================================================*/ #define ROUND_MUL(I, J, LO, HI) \ LO = fma52lo(LO, va[I], vb[J]); \ HI = fma52hi(HI, va[I], vb[J]) #define RED_P521_STEP(u, r0,r1, r10) { \ U64 u = and64(r0, loadu64(VMASK52)); /* u = r0*k, k == 1 */ \ r1 = add64(r1, srli64(r0, DIGIT_SIZE)); /* carry propagation */ \ /* reduction */ \ u = add64(u, u); \ r10 = add64(r10, u); \ } void MB_FUNC_NAME(ifma_amm52_p521_)(U64 r[], const U64 va[], const U64 vb[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; U64 r20, r21; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19= r20 = r21 = get_zero64(); // full multiplication ROUND_MUL(0, 0, r0, r1); ROUND_MUL(1, 0, r1, r2); ROUND_MUL(2, 0, r2, r3); ROUND_MUL(3, 0, r3, r4); ROUND_MUL(4, 0, r4, r5); ROUND_MUL(5, 0, r5, r6); ROUND_MUL(6, 0, r6, r7); ROUND_MUL(7, 0, r7, r8); ROUND_MUL(8, 0, r8, r9); ROUND_MUL(9, 0, r9, r10); ROUND_MUL(10,0, r10,r11); ROUND_MUL(0, 1, r1, r2); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 1, r3, r4); ROUND_MUL(3, 1, r4, r5); ROUND_MUL(4, 1, r5, r6); ROUND_MUL(5, 1, r6, r7); ROUND_MUL(6, 1, r7, r8); ROUND_MUL(7, 1, r8, r9); ROUND_MUL(8, 1, r9, r10); ROUND_MUL(9, 1, r10,r11); ROUND_MUL(10,1, r11,r12); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(3, 2, r5, r6); ROUND_MUL(4, 2, r6, r7); ROUND_MUL(5, 2, r7, r8); ROUND_MUL(6, 2, r8, r9); ROUND_MUL(7, 2, r9, r10); ROUND_MUL(8, 2, r10,r11); ROUND_MUL(9, 2, r11,r12); ROUND_MUL(10,2, r12,r13); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(2, 3, r5, r6); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 3, r7, r8); ROUND_MUL(5, 3, r8, r9); ROUND_MUL(6, 3, r9, r10); ROUND_MUL(7, 3, r10,r11); ROUND_MUL(8, 3, r11,r12); ROUND_MUL(9, 3, r12,r13); ROUND_MUL(10,3, r13,r14); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(4, 4, r8, r9); ROUND_MUL(5, 4, r9, r10); ROUND_MUL(6, 4, r10,r11); ROUND_MUL(7, 4, r11,r12); ROUND_MUL(8, 4, r12,r13); ROUND_MUL(9, 4, r13,r14); ROUND_MUL(10,4, r14,r15); ROUND_MUL(0, 5, r5, r6); ROUND_MUL(1, 5, r6, r7); ROUND_MUL(2, 5, r7, r8); ROUND_MUL(3, 5, r8, r9); ROUND_MUL(4, 5, r9, r10); ROUND_MUL(5, 5, r10,r11); ROUND_MUL(6, 5, r11,r12); ROUND_MUL(7, 5, r12,r13); ROUND_MUL(8, 5, r13,r14); ROUND_MUL(9, 5, r14,r15); ROUND_MUL(10,5, r15,r16); ROUND_MUL(0, 6, r6, r7); ROUND_MUL(1, 6, r7, r8); ROUND_MUL(2, 6, r8, r9); ROUND_MUL(3, 6, r9, r10); ROUND_MUL(4, 6, r10,r11); ROUND_MUL(5, 6, r11,r12); ROUND_MUL(6, 6, r12,r13); ROUND_MUL(7, 6, r13,r14); ROUND_MUL(8, 6, r14,r15); ROUND_MUL(9, 6, r15,r16); ROUND_MUL(10,6, r16,r17); ROUND_MUL(0, 7, r7, r8); ROUND_MUL(1, 7, r8, r9); ROUND_MUL(2, 7, r9, r10); ROUND_MUL(3, 7, r10,r11); ROUND_MUL(4, 7, r11,r12); ROUND_MUL(5, 7, r12,r13); ROUND_MUL(6, 7, r13,r14); ROUND_MUL(7, 7, r14,r15); ROUND_MUL(8, 7, r15,r16); ROUND_MUL(9, 7, r16,r17); ROUND_MUL(10,7, r17,r18); ROUND_MUL(0, 8, r8, r9); ROUND_MUL(1, 8, r9, r10); ROUND_MUL(2, 8, r10,r11); ROUND_MUL(3, 8, r11,r12); ROUND_MUL(4, 8, r12,r13); ROUND_MUL(5, 8, r13,r14); ROUND_MUL(6, 8, r14,r15); ROUND_MUL(7, 8, r15,r16); ROUND_MUL(8, 8, r16,r17); ROUND_MUL(9, 8, r17,r18); ROUND_MUL(10,8, r18,r19); ROUND_MUL(0, 9, r9, r10); ROUND_MUL(1, 9, r10,r11); ROUND_MUL(2, 9, r11,r12); ROUND_MUL(3, 9, r12,r13); ROUND_MUL(4, 9, r13,r14); ROUND_MUL(5, 9, r14,r15); ROUND_MUL(6, 9, r15,r16); ROUND_MUL(7, 9, r16,r17); ROUND_MUL(8, 9, r17,r18); ROUND_MUL(9, 9, r18,r19); ROUND_MUL(10,9, r19,r20); ROUND_MUL(0, 10, r10,r11); ROUND_MUL(1, 10, r11,r12); ROUND_MUL(2, 10, r12,r13); ROUND_MUL(3, 10, r13,r14); ROUND_MUL(4, 10, r14,r15); ROUND_MUL(5, 10, r15,r16); ROUND_MUL(6, 10, r16,r17); ROUND_MUL(7, 10, r17,r18); ROUND_MUL(8, 10, r18,r19); ROUND_MUL(9, 10, r19,r20); ROUND_MUL(10,10, r20,r21); // reduction p = 2^521 -1 RED_P521_STEP(u0, r0, r1, r10); RED_P521_STEP(u1, r1, r2, r11); RED_P521_STEP(u2, r2, r3, r12); RED_P521_STEP(u3, r3, r4, r13); RED_P521_STEP(u4, r4, r5, r14); RED_P521_STEP(u5, r5, r6, r15); RED_P521_STEP(u6, r6, r7, r16); RED_P521_STEP(u7, r7, r8, r17); RED_P521_STEP(u8, r8, r9, r18); RED_P521_STEP(u9, r9, r10,r19); RED_P521_STEP(u10,r10,r11,r20); // normalization NORM_LSHIFTR(r, 11, 12) NORM_LSHIFTR(r, 12, 13) NORM_LSHIFTR(r, 13, 14) NORM_LSHIFTR(r, 14, 15) NORM_LSHIFTR(r, 15, 16) NORM_LSHIFTR(r, 16, 17) NORM_LSHIFTR(r, 17, 18) NORM_LSHIFTR(r, 18, 19) NORM_LSHIFTR(r, 19, 20) NORM_LSHIFTR(r, 20, 21) r[0] = r11; r[1] = r12; r[2] = r13; r[3] = r14; r[4] = r15; r[5] = r16; r[6] = r17; r[7] = r18; r[8] = r19; r[9] = r20; r[10]= r21; } void MB_FUNC_NAME(ifma_ams52_p521_)(U64 r[], const U64 va[]) { const U64* vb = va; U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; U64 r20, r21; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = r20 = r21 = get_zero64(); // full square ROUND_MUL(0, 1, r1, r2); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(0, 5, r5, r6); ROUND_MUL(0, 6, r6, r7); ROUND_MUL(0, 7, r7, r8); ROUND_MUL(0, 8, r8, r9); ROUND_MUL(0, 9, r9, r10); ROUND_MUL(0, 10,r10,r11); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(1, 5, r6, r7); ROUND_MUL(1, 6, r7, r8); ROUND_MUL(1, 7, r8, r9); ROUND_MUL(1, 8, r9, r10); ROUND_MUL(1, 9, r10,r11); ROUND_MUL(1, 10,r11,r12); ROUND_MUL(2, 3, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(2, 5, r7, r8); ROUND_MUL(2, 6, r8, r9); ROUND_MUL(2, 7, r9, r10); ROUND_MUL(2, 8, r10,r11); ROUND_MUL(2, 9, r11,r12); ROUND_MUL(2, 10,r12,r13); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(3, 5, r8, r9); ROUND_MUL(3, 6, r9, r10); ROUND_MUL(3, 7, r10,r11); ROUND_MUL(3, 8, r11,r12); ROUND_MUL(3, 9, r12,r13); ROUND_MUL(3, 10,r13,r14); ROUND_MUL(4, 5, r9, r10); ROUND_MUL(4, 6, r10,r11); ROUND_MUL(4, 7, r11,r12); ROUND_MUL(4, 8, r12,r13); ROUND_MUL(4, 9, r13,r14); ROUND_MUL(4, 10,r14,r15); ROUND_MUL(5, 6, r11,r12); ROUND_MUL(5, 7, r12,r13); ROUND_MUL(5, 8, r13,r14); ROUND_MUL(5, 9, r14,r15); ROUND_MUL(5, 10,r15,r16); ROUND_MUL(6, 7, r13,r14); ROUND_MUL(6, 8, r14,r15); ROUND_MUL(6, 9, r15,r16); ROUND_MUL(6, 10,r16,r17); ROUND_MUL(7, 8, r15,r16); ROUND_MUL(7, 9, r16,r17); ROUND_MUL(7, 10,r17,r18); ROUND_MUL(8, 9, r17,r18); ROUND_MUL(8, 10,r18,r19); ROUND_MUL(9, 10,r19,r20); r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); r9 = add64(r9, r9); r10 = add64(r10, r10); r11 = add64(r11, r11); r12 = add64(r12, r12); r13 = add64(r13, r13); r14 = add64(r14, r14); r15 = add64(r15, r15); r16 = add64(r16, r16); r17 = add64(r17, r17); r18 = add64(r18, r18); r19 = add64(r19, r19); r20 = add64(r20, r20); ROUND_MUL(0, 0, r0, r1); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 4, r8, r9); ROUND_MUL(5, 5, r10, r11); ROUND_MUL(6, 6, r12, r13); ROUND_MUL(7, 7, r14, r15); ROUND_MUL(8, 8, r16, r17); ROUND_MUL(9, 9, r18, r19); ROUND_MUL(10,10,r20, r21); // reduction p = 2^521 -1 RED_P521_STEP(u0, r0, r1, r10); RED_P521_STEP(u1, r1, r2, r11); RED_P521_STEP(u2, r2, r3, r12); RED_P521_STEP(u3, r3, r4, r13); RED_P521_STEP(u4, r4, r5, r14); RED_P521_STEP(u5, r5, r6, r15); RED_P521_STEP(u6, r6, r7, r16); RED_P521_STEP(u7, r7, r8, r17); RED_P521_STEP(u8, r8, r9, r18); RED_P521_STEP(u9, r9, r10,r19); RED_P521_STEP(u10,r10,r11,r20); // normalization NORM_LSHIFTR(r, 11, 12) NORM_LSHIFTR(r, 12, 13) NORM_LSHIFTR(r, 13, 14) NORM_LSHIFTR(r, 14, 15) NORM_LSHIFTR(r, 15, 16) NORM_LSHIFTR(r, 16, 17) NORM_LSHIFTR(r, 17, 18) NORM_LSHIFTR(r, 18, 19) NORM_LSHIFTR(r, 19, 20) NORM_LSHIFTR(r, 20, 21) r[0] = r11; r[1] = r12; r[2] = r13; r[3] = r14; r[4] = r15; r[5] = r16; r[6] = r17; r[7] = r18; r[8] = r19; r[9] = r20; r[10]= r21; } void MB_FUNC_NAME(ifma_reduce52_p521_)(U64 R[], const U64 A[]) { /* r = a - p521_mb */ U64 r0 = sub64(A[0], ((U64*)(p521_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(p521_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(p521_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(p521_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(p521_mb))[4]); U64 r5 = sub64(A[5], ((U64*)(p521_mb))[5]); U64 r6 = sub64(A[6], ((U64*)(p521_mb))[6]); U64 r7 = sub64(A[7], ((U64*)(p521_mb))[7]); U64 r8 = sub64(A[8], ((U64*)(p521_mb))[8]); U64 r9 = sub64(A[9], ((U64*)(p521_mb))[9]); U64 r10= sub64(A[10],((U64*)(p521_mb))[10]); /* normalize r0 - r10 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9, 10) /* r = a r = z^(0x1FF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFD) // // note: z in in Montgomery domain (as soon mul() and sqr() below are amm-functions // r in Montgomery domain too */ #define fe52_sqr MB_FUNC_NAME(ifma_ams52_p521_) #define fe52_mul MB_FUNC_NAME(ifma_amm52_p521_) /* r = base^(2^n) */ __MBX_INLINE void fe52_sqr_pwr(U64 r[], const U64 base[], int n) { if(r!=base) MB_FUNC_NAME(mov_FE521_)(r, base); for(; n>0; n--) fe52_sqr(r,r); } void MB_FUNC_NAME(ifma_aminv52_p521_)(U64 r[], const U64 z[]) { __ALIGN64 U64 u[P521_LEN52]; __ALIGN64 U64 v[P521_LEN52]; __ALIGN64 U64 zD[P521_LEN52]; __ALIGN64 U64 zF[P521_LEN52]; __ALIGN64 U64 z1FF[P521_LEN52]; fe52_sqr(u, z); /* u = z^2 */ fe52_mul(v, u, z); /* v = z^2 * z = z^3 */ fe52_sqr_pwr(zF, v, 2); /* zF= (z^3)^(2^2) = z^12 */ fe52_mul(zD, zF, z); /* zD = z^12 * z = z^xD */ fe52_mul(zF, zF, v); /* zF = z^12 * z^3 = z^xF */ fe52_sqr_pwr(u, zF, 4); /* u = (z^xF)^(2^4) = z^xF0 */ fe52_mul(zD, u, zD); /* zD = z^xF0 * z^xD = z^xFD */ fe52_mul(zF, u, zF); /* zF = z^xF0 * z^xF = z^xFF */ fe52_sqr(z1FF, zF); /* z1FF= (zF^2) = z^x1FE */ fe52_mul(z1FF, z1FF, z); /* z1FF *= z = z^x1FF */ fe52_sqr_pwr(u, zF, 8); /* u = (z^xFF)^(2^8) = z^xFF00 */ fe52_mul(zD, u, zD); /* zD = z^xFF00 * z^xFD = z^xFFFD */ fe52_mul(zF, u, zF); /* zF = z^xFF00 * z^xFF = z^xFFFF */ fe52_sqr_pwr(u, zF, 16); /* u = (z^xFFFF)^(2^16) = z^xFFFF0000 */ fe52_mul(zD, u, zD); /* zD = z^xFFFF0000 * z^xFFFD = z^xFFFFFFFD */ fe52_mul(zF, u, zF); /* zF = z^xFFFF0000 * z^xFFFF = z^xFFFFFFFF */ fe52_sqr_pwr(u, zF, 32); /* u = (z^xFFFFFFFF)^(2^32) = z^xFFFFFFFF00000000 */ fe52_mul(zD, u, zD); /* zD = z^xFFFFFFFF00000000 * z^xFFFFFFFD = z^xFFFFFFFFFFFFFFFD */ fe52_mul(zF, u, zF); /* zF = z^xFFFFFFFF00000000 * z^xFFFFFFFF = z^xFFFFFFFFFFFFFFFF */ /* v = z^x1FF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, z1FF, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ fe52_sqr_pwr(v, v, 64); fe52_mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFD = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFD */ fe52_sqr_pwr(v, v, 64); fe52_mul(r, v, zD); } /*===================================================================== Specialized single operations over p521: add, sub, neg =====================================================================*/ __MBX_INLINE __mb_mask MB_FUNC_NAME(lt_mbx_digit_)(const U64 a, const U64 b, const __mb_mask lt_mask) { U64 d = mask_sub64(sub64(a, b), lt_mask, sub64(a, b), set1(1)); return cmp64_mask(d, get_zero64(), _MM_CMPINT_LT); } void MB_FUNC_NAME(ifma_add52_p521_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a + b */ U64 r0 = add64(A[0], B[0]); U64 r1 = add64(A[1], B[1]); U64 r2 = add64(A[2], B[2]); U64 r3 = add64(A[3], B[3]); U64 r4 = add64(A[4], B[4]); U64 r5 = add64(A[5], B[5]); U64 r6 = add64(A[6], B[6]); U64 r7 = add64(A[7], B[7]); U64 r8 = add64(A[8], B[8]); U64 r9 = add64(A[9], B[9]); U64 r10= add64(A[10],B[10]); /* lt = {r0 - r10} < 2*p */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)( r0, ((U64*)(p521_x2))[0], 0); lt = MB_FUNC_NAME(lt_mbx_digit_)( r1, ((U64*)(p521_x2))[1], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r2, ((U64*)(p521_x2))[2], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r3, ((U64*)(p521_x2))[3], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r4, ((U64*)(p521_x2))[4], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r5, ((U64*)(p521_x2))[5], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r6, ((U64*)(p521_x2))[6], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r7, ((U64*)(p521_x2))[7], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r8, ((U64*)(p521_x2))[8], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r9, ((U64*)(p521_x2))[9], lt); lt = MB_FUNC_NAME(lt_mbx_digit_)( r10,((U64*)(p521_x2))[10],lt); /* {r0 - r10} -= 2*p */ r0 = mask_sub64(r0, ~lt, r0, ((U64*)(p521_x2))[0]); r1 = mask_sub64(r1, ~lt, r1, ((U64*)(p521_x2))[1]); r2 = mask_sub64(r2, ~lt, r2, ((U64*)(p521_x2))[2]); r3 = mask_sub64(r3, ~lt, r3, ((U64*)(p521_x2))[3]); r4 = mask_sub64(r4, ~lt, r4, ((U64*)(p521_x2))[4]); r5 = mask_sub64(r5, ~lt, r5, ((U64*)(p521_x2))[5]); r6 = mask_sub64(r6, ~lt, r6, ((U64*)(p521_x2))[6]); r7 = mask_sub64(r7, ~lt, r7, ((U64*)(p521_x2))[7]); r8 = mask_sub64(r8, ~lt, r8, ((U64*)(p521_x2))[8]); r9 = mask_sub64(r9, ~lt, r9, ((U64*)(p521_x2))[9]); r10= mask_sub64(r10,~lt, r10,((U64*)(p521_x2))[10]); /* normalize r0 - r10 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9,10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } void MB_FUNC_NAME(ifma_sub52_p521_)(U64 R[], const U64 A[], const U64 B[]) { /* r = a - b */ U64 r0 = sub64(A[0], B[0]); U64 r1 = sub64(A[1], B[1]); U64 r2 = sub64(A[2], B[2]); U64 r3 = sub64(A[3], B[3]); U64 r4 = sub64(A[4], B[4]); U64 r5 = sub64(A[5], B[5]); U64 r6 = sub64(A[6], B[6]); U64 r7 = sub64(A[7], B[7]); U64 r8 = sub64(A[8], B[8]); U64 r9 = sub64(A[9], B[9]); U64 r10= sub64(A[10],B[10]); /* lt = {r0 - r10} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r5, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r6, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r7, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r8, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r9, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r10,get_zero64(), lt); r0 = mask_add64(r0, lt, r0, ((U64*)(p521_x2))[0]); r1 = mask_add64(r1, lt, r1, ((U64*)(p521_x2))[1]); r2 = mask_add64(r2, lt, r2, ((U64*)(p521_x2))[2]); r3 = mask_add64(r3, lt, r3, ((U64*)(p521_x2))[3]); r4 = mask_add64(r4, lt, r4, ((U64*)(p521_x2))[4]); r5 = mask_add64(r5, lt, r5, ((U64*)(p521_x2))[5]); r6 = mask_add64(r6, lt, r6, ((U64*)(p521_x2))[6]); r7 = mask_add64(r7, lt, r7, ((U64*)(p521_x2))[7]); r8 = mask_add64(r8, lt, r8, ((U64*)(p521_x2))[8]); r9 = mask_add64(r9, lt, r9, ((U64*)(p521_x2))[9]); r10= mask_add64(r10,lt, r10,((U64*)(p521_x2))[10]); /* normalize r0 - r7 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9, 10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } void MB_FUNC_NAME(ifma_neg52_p521_)(U64 R[], const U64 A[]) { __mb_mask nz_mask = ~MB_FUNC_NAME(is_zero_FE521_)(A); /* {r0 - r10} = 2*p - A */ U64 r0 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[0], A[0] ); U64 r1 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[1], A[1] ); U64 r2 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[2], A[2] ); U64 r3 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[3], A[3] ); U64 r4 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[4], A[4] ); U64 r5 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[5], A[5] ); U64 r6 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[6], A[6] ); U64 r7 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[7], A[7] ); U64 r8 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[8], A[8] ); U64 r9 = mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[9], A[9] ); U64 r10= mask_sub64( A[0], nz_mask, ((U64*)(p521_x2))[10],A[10]); /* normalize r0 - r10 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) NORM_ASHIFTR(r, 4, 5) NORM_ASHIFTR(r, 5, 6) NORM_ASHIFTR(r, 6, 7) NORM_ASHIFTR(r, 7, 8) NORM_ASHIFTR(r, 8, 9) NORM_ASHIFTR(r, 9, 10) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; R[5] = r5; R[6] = r6; R[7] = r7; R[8] = r8; R[9] = r9; R[10]= r10; } void MB_FUNC_NAME(ifma_double52_p521_)(U64 R[], const U64 A[]) { MB_FUNC_NAME(ifma_add52_p521_)(R, A, A); } void MB_FUNC_NAME(ifma_tripple52_p521_)(U64 R[], const U64 A[]) { U64 T[P521_LEN52]; MB_FUNC_NAME(ifma_add52_p521_)(T, A, A); MB_FUNC_NAME(ifma_add52_p521_)(R, T, A); } void MB_FUNC_NAME(ifma_half52_p521_)(U64 R[], const U64 A[]) { U64 one = set1(1); U64 base = set1(DIGIT_BASE); /* res = a + is_odd(a)? p521 : 0 */ U64 mask = sub64(get_zero64(), and64(A[0], one)); U64 t0 = add64(A[0], and64(((U64*)p521_mb)[0], mask)); U64 t1 = add64(A[1], and64(((U64*)p521_mb)[1], mask)); U64 t2 = add64(A[2], and64(((U64*)p521_mb)[2], mask)); U64 t3 = add64(A[3], and64(((U64*)p521_mb)[3], mask)); U64 t4 = add64(A[4], and64(((U64*)p521_mb)[4], mask)); U64 t5 = add64(A[5], and64(((U64*)p521_mb)[5], mask)); U64 t6 = add64(A[6], and64(((U64*)p521_mb)[6], mask)); U64 t7 = add64(A[7], and64(((U64*)p521_mb)[7], mask)); U64 t8 = add64(A[8], and64(((U64*)p521_mb)[8], mask)); U64 t9 = add64(A[9], and64(((U64*)p521_mb)[9], mask)); U64 t10= add64(A[10],and64(((U64*)p521_mb)[10],mask)); /* t =>> 1 */ mask = sub64(get_zero64(), and64(t1, one)); t0 = add64(t0, and64(base, mask)); t0 = srli64(t0, 1); mask = sub64(get_zero64(), and64(t2, one)); t1 = add64(t1, and64(base, mask)); t1 = srli64(t1, 1); mask = sub64(get_zero64(), and64(t3, one)); t2 = add64(t2, and64(base, mask)); t2 = srli64(t2, 1); mask = sub64(get_zero64(), and64(t4, one)); t3 = add64(t3, and64(base, mask)); t3 = srli64(t3, 1); mask = sub64(get_zero64(), and64(t5, one)); t4 = add64(t4, and64(base, mask)); t4 = srli64(t4, 1); mask = sub64(get_zero64(), and64(t6, one)); t5 = add64(t5, and64(base, mask)); t5 = srli64(t5, 1); mask = sub64(get_zero64(), and64(t7, one)); t6 = add64(t6, and64(base, mask)); t6 = srli64(t6, 1); mask = sub64(get_zero64(), and64(t8, one)); t7 = add64(t7, and64(base, mask)); t7 = srli64(t7, 1); mask = sub64(get_zero64(), and64(t9, one)); t8 = add64(t8, and64(base, mask)); t8 = srli64(t8, 1); mask = sub64(get_zero64(), and64(t10, one)); t9 = add64(t9, and64(base, mask)); t9 = srli64(t9, 1); t10 = srli64(t10, 1); /* normalize t0, t1, t2, t3, t4 */ NORM_LSHIFTR(t, 0, 1) NORM_LSHIFTR(t, 1, 2) NORM_LSHIFTR(t, 2, 3) NORM_LSHIFTR(t, 3, 4) NORM_LSHIFTR(t, 4, 5) NORM_LSHIFTR(t, 5, 6) NORM_LSHIFTR(t, 6, 7) NORM_LSHIFTR(t, 7, 8) NORM_LSHIFTR(t, 8, 9) NORM_LSHIFTR(t, 9,10) R[0] = t0; R[1] = t1; R[2] = t2; R[3] = t3; R[4] = t4; R[5] = t5; R[6] = t6; R[7] = t7; R[8] = t8; R[9] = t9; R[10]= t10; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_p521_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FE521_)(a,(const U64 (*))p521_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_p521_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FE521_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_p521_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecdh_p256.c000066400000000000000000000115351470420105600301270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer // // Note: // input party's public key depends on is pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates // or // - in (x:y) affine coordinate */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdh_ssl_mb8)(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const BIGNUM* skey = pa_skey[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey|| NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_mbx_nistp256_ecdh_ssl_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdh_mb8)(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const int64u* skey = pa_skey[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdh_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecdh_p384.c000066400000000000000000000115321470420105600301260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer // // Note: // input party's public key depends on is pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates // or // - in (x:y) affine coordinate */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdh_ssl_mb8)(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const BIGNUM* skey = pa_skey[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdh_ssl_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdh_mb8)(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const int64u* skey = pa_skey[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey || NULL==pubx || NULL== puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdh_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecdh_p521.c000066400000000000000000000115321470420105600301170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer // // Note: // input party's public key depends on is pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates // or // - in (x:y) affine coordinate */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdh_ssl_mb8)(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const BIGNUM* skey = pa_skey[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdh_ssl_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdh_mb8)(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const int64u* skey = pa_skey[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey || NULL==pubx || NULL== puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdh_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecdsa_p256.c000066400000000000000000000367721470420105600303150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 "crypto_mb/status.h" #include #include #include #include #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* // ECDSA kernels */ /* // pre-computation of ECDSA signature // // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_sign_rp[] array of pointers to the r-components of the signatures // pa_eph_skey[] array of pointers to the ephemeral (nonce) signer's ephemeral private keys // pBuffer pointer to the scratch buffer // // function computes two values that does not depend on the message to be signed // - inversion of signer's ephemeral (nonce) keys // - r-component of the signature // and are later used during the signing process */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_sign_setup_mb8)(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_inv_eph_skey || NULL==pa_sign_rp || NULL==pa_eph_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int64u* pinv_key = pa_inv_eph_skey[buf_no]; int64u* psign_rp = pa_sign_rp[buf_no]; const int64u* pkey = pa_eph_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pinv_key || NULL==psign_rp || NULL==pkey) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_sign_setup_mb8(pa_inv_eph_skey, pa_sign_rp, pa_eph_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // computes ECDSA signature // // pa_sign_r[] array of pointers to the r-components of the signatures // pa_sign_s[] array of pointers to the s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_sign_rp[] array of pointers to the pre-computed r-components of the signatures // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_reg_skey[] array of pointers to the regular signer's ephemeral (nonce) private keys // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_sign_complete_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_sign_rp || NULL==pa_inv_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* psign_pr = pa_sign_rp[buf_no]; const int64u* pinv_eph_key = pa_inv_eph_skey[buf_no]; const int64u* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==psign_pr || NULL==pinv_eph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_sign_complete_mb8(pa_sign_r, pa_sign_s,pa_msg, pa_sign_rp, pa_inv_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // Computes ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_eph_skey[] array of pointers to the signer's ephemeral (nonce) private keys // pa_reg_skey[] array of pointers to the signer's regular (long term) private keys // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_sign_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* peph_key = pa_eph_skey[buf_no]; const int64u* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==peph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // Verifies ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates // pBuffer pointer to the scratch buffer*/ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_verify_mb8)(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_msg || NULL==pa_sign_r || NULL==pa_sign_s) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; const int8u* msg = pa_msg[buf_no]; const int8u* r = pa_sign_r[buf_no]; const int8u* s = pa_sign_s[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pubx || NULL==puby || NULL==msg || NULL== r || NULL==s || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* if all pointers NULL exit */ if(!MBX_IS_ANY_OK_STS(status)) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_sign_setup_ssl_mb8)(BIGNUM* pa_inv_skey[8], BIGNUM* pa_sign_rp[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_inv_skey || NULL==pa_sign_rp || NULL==pa_eph_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { const BIGNUM* pinv_key = pa_inv_skey[buf_no]; const BIGNUM* psign_rp = pa_sign_rp[buf_no]; const BIGNUM* pkey = pa_eph_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pinv_key || NULL==psign_rp || NULL==pkey) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_sign_setup_ssl_mb8(pa_inv_skey, pa_sign_rp, pa_eph_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_sign_complete_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sign_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_sign_rp || NULL==pa_inv_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* psign_pr = pa_sign_rp[buf_no]; const BIGNUM* pinv_eph_key = pa_inv_eph_skey[buf_no]; const BIGNUM* preg_key = pa_reg_skey[buf_no]; if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==psign_pr || NULL==pinv_eph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_sign_complete_ssl_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_sign_rp, pa_inv_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_sign_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* peph_key = pa_eph_skey[buf_no]; const BIGNUM* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==peph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecdsa_verify_ssl_mb8)(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_msg || NULL==pa_sig) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; const int8u* msg = pa_msg[buf_no]; const ECDSA_SIG* sig = pa_sig[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pubx || NULL==puby || NULL==msg || NULL==sig || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* if all pointers NULL exit */ if(!MBX_IS_ANY_OK_STS(status)) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecdsa_verify_ssl_mb8(pa_sig, pa_msg, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecdsa_p384.c000066400000000000000000000374231470420105600303110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 "crypto_mb/status.h" #include #include #include #include #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* // ECDSA kernels */ /* // pre-computation of ECDSA signature // // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_sign_rp[] array of pointers to the r-components of the signatures // pa_eph_skey[] array of pointers to the ephemeral (nonce) signer's ephemeral private keys // pBuffer pointer to the scratch buffer // // function computes two values that does not depend on the message to be signed // - inversion of signer's ephemeral (nonce) keys // - r-component of the signature // and are later used during the signing process */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_sign_setup_mb8)(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_inv_eph_skey || NULL==pa_sign_rp || NULL==pa_eph_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int64u* pinv_key = pa_inv_eph_skey[buf_no]; int64u* psign_rp = pa_sign_rp[buf_no]; const int64u* pkey = pa_eph_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pinv_key || NULL==psign_rp || NULL==pkey) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_sign_setup_mb8(pa_inv_eph_skey, pa_sign_rp, pa_eph_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // computes ECDSA signature // // pa_sign_r[] array of pointers to the r-components of the signatures // pa_sign_s[] array of pointers to the s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_sign_rp[] array of pointers to the pre-computed r-components of the signatures // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_reg_skey[] array of pointers to the regular signer's ephemeral (nonce) private keys // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_sign_complete_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_sign_rp || NULL==pa_inv_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* psign_pr = pa_sign_rp[buf_no]; const int64u* pinv_eph_key = pa_inv_eph_skey[buf_no]; const int64u* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==psign_pr || NULL==pinv_eph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_sign_complete_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_sign_rp, pa_inv_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // Computes ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_eph_skey[] array of pointers to the signer's ephemeral (nonce) private keys // pa_reg_skey[] array of pointers to the signer's regular (long term) private keys // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_sign_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* peph_key = pa_eph_skey[buf_no]; const int64u* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==peph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // ECDSA signature verification // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the message representatives that have been signed // pa_pubx[] array of pointers to the signer's public keys X-coordinates // pa_puby[] array of pointers to the signer's public keys Y-coordinates // pa_pubz[] array of pointers to the signer's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_verify_mb8)(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; int use_jproj_coords = NULL != pa_pubz; /* test input pointers */ if (NULL == pa_sign_r || NULL == pa_sign_s || NULL == pa_msg || NULL == pa_pubx || NULL == pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u* psign_r = pa_sign_r[buf_no]; const int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords ? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if (NULL == psign_r || NULL == psign_s || NULL == pmsg || NULL == pubx || NULL == puby || (use_jproj_coords && NULL == pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* if all pointers NULL exit */ if (!MBX_IS_ANY_OK_STS(status)) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // OpenSSL's specific implementations */ #ifndef BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_sign_setup_ssl_mb8)(BIGNUM* pa_inv_skey[8], BIGNUM* pa_sign_rp[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_inv_skey || NULL==pa_sign_rp || NULL==pa_eph_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { const BIGNUM* pinv_key = pa_inv_skey[buf_no]; const BIGNUM* psign_rp = pa_sign_rp[buf_no]; const BIGNUM* pkey = pa_eph_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pinv_key || NULL==psign_rp || NULL==pkey) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_sign_setup_ssl_mb8(pa_inv_skey, pa_sign_rp, pa_eph_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_sign_complete_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sign_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_sign_rp || NULL==pa_inv_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* psign_pr = pa_sign_rp[buf_no]; const BIGNUM* pinv_eph_key = pa_inv_eph_skey[buf_no]; const BIGNUM* preg_key = pa_reg_skey[buf_no]; if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==psign_pr || NULL==pinv_eph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_sign_complete_ssl_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_sign_rp, pa_inv_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_sign_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* peph_key = pa_eph_skey[buf_no]; const BIGNUM* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==peph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecdsa_verify_ssl_mb8)(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; int use_jproj_coords = NULL != pa_pubz; /* test input pointers */ if (NULL == pa_msg || NULL == pa_sig || NULL == pa_pubx || NULL == pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const ECDSA_SIG* sig = pa_sig[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords ? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if (NULL == sig || NULL == pmsg || NULL == pubx || NULL == puby || (use_jproj_coords && NULL == pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* if all pointers NULL exit */ if (!MBX_IS_ANY_OK_STS(status)) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecdsa_verify_ssl_mb8(pa_sig, pa_msg, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecdsa_p521.c000066400000000000000000000372151470420105600303010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* // ECDSA kernels */ /* // pre-computation of ECDSA signature // // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_sign_rp[] array of pointers to the r-components of the signatures // pa_eph_skey[] array of pointers to the ephemeral (nonce) signer's ephemeral private keys // pBuffer pointer to the scratch buffer // // function computes two values that does not depend on the message to be signed // - inversion of signer's ephemeral (nonce) keys // - r-component of the signature // and are later used during the signing process */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_sign_setup_mb8)(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_inv_eph_skey || NULL==pa_sign_rp || NULL==pa_eph_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int64u* pinv_key = pa_inv_eph_skey[buf_no]; int64u* psign_rp = pa_sign_rp[buf_no]; const int64u* pkey = pa_eph_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pinv_key || NULL==psign_rp || NULL==pkey) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_sign_setup_mb8(pa_inv_eph_skey, pa_sign_rp, pa_eph_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // computes ECDSA signature // // pa_sign_r[] array of pointers to the r-components of the signatures // pa_sign_s[] array of pointers to the s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_sign_rp[] array of pointers to the pre-computed r-components of the signatures // pa_inv_eph_skey[] array of pointers to the inversion of signer's ephemeral private keys // pa_reg_skey[] array of pointers to the regular signer's ephemeral (nonce) private keys // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_sign_complete_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_sign_rp || NULL==pa_inv_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* psign_pr = pa_sign_rp[buf_no]; const int64u* pinv_eph_key = pa_inv_eph_skey[buf_no]; const int64u* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==psign_pr || NULL==pinv_eph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_sign_complete_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_sign_rp, pa_inv_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // Computes ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_eph_skey[] array of pointers to the signer's ephemeral (nonce) private keys // pa_reg_skey[] array of pointers to the signer's regular (long term) private keys // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_sign_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const int64u* peph_key = pa_eph_skey[buf_no]; const int64u* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==peph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // Verifies ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_verify_mb8)(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_msg || NULL==pa_sign_r || NULL==pa_sign_s) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; const int8u* msg = pa_msg[buf_no]; const int8u* r = pa_sign_r[buf_no]; const int8u* s = pa_sign_s[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pubx || NULL==puby || NULL==msg || NULL== r || NULL==s || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* if all pointers NULL exit */ if(!MBX_IS_ANY_OK_STS(status)) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // OpenSSL's specific implementations */ #ifndef BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_sign_setup_ssl_mb8)(BIGNUM* pa_inv_skey[8], BIGNUM* pa_sign_rp[8], const BIGNUM* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_inv_skey || NULL==pa_sign_rp || NULL==pa_eph_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { const BIGNUM* pinv_key = pa_inv_skey[buf_no]; const BIGNUM* psign_rp = pa_sign_rp[buf_no]; const BIGNUM* pkey = pa_eph_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pinv_key || NULL==psign_rp || NULL==pkey) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_sign_setup_ssl_mb8(pa_inv_skey, pa_sign_rp, pa_eph_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_sign_complete_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_sign_rp[8], const BIGNUM* const pa_inv_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_sign_rp || NULL==pa_inv_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* psign_pr = pa_sign_rp[buf_no]; const BIGNUM* pinv_eph_key = pa_inv_eph_skey[buf_no]; const BIGNUM* preg_key = pa_reg_skey[buf_no]; if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==psign_pr || NULL==pinv_eph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_sign_complete_ssl_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_sign_rp, pa_inv_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_sign_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_msg || NULL==pa_eph_skey || NULL==pa_reg_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check data pointers */ for(buf_no=0; buf_no<8; buf_no++) { int8u* psign_r = pa_sign_r[buf_no]; int8u* psign_s = pa_sign_s[buf_no]; const int8u* pmsg = pa_msg[buf_no]; const BIGNUM* peph_key = pa_eph_skey[buf_no]; const BIGNUM* preg_key = pa_reg_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==psign_r || NULL==psign_s || NULL==pmsg || NULL==peph_key || NULL==preg_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_eph_skey, pa_reg_skey, pBuffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecdsa_verify_ssl_mb8)(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_msg[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_msg || NULL==pa_sig) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; const int8u* msg = pa_msg[buf_no]; const ECDSA_SIG* sig = pa_sig[buf_no]; /* if any of pointer NULL set error status */ if(NULL==pubx || NULL==puby || NULL==msg || NULL==sig || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* if all pointers NULL exit */ if(!MBX_IS_ANY_OK_STS(status)) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecdsa_verify_ssl_mb8(pa_sig, pa_msg, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecpoint_p256.c000066400000000000000000000533141470420105600306660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* simplify naming */ #define sqr MB_FUNC_NAME(ifma_ams52_p256_) #define mul MB_FUNC_NAME(ifma_amm52_p256_) #define add MB_FUNC_NAME(ifma_add52_p256_) #define sub MB_FUNC_NAME(ifma_sub52_p256_) #define mul2 MB_FUNC_NAME(ifma_double52_p256_) #define mul3 MB_FUNC_NAME(ifma_tripple52_p256_) #define div2 MB_FUNC_NAME(ifma_half52_p256_) /* // Presentation of point at infinity: // - projective (X : Y : 0) // - affine (0 : 0) */ /* // R(X3:Y3:Z3) = [2]P(X1:Y1:Z1) // // formulas: // A = 4*X1*Y1^2 // B = 3*(X1^2-Z1^4) // X3= B^2 -2*A // Y3= B*(A-X3) -8*Y1^4 // Z3= 2*Y1*Z1 // // cost: 4S+4M+9A // */ void MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(P256_POINT* r, const P256_POINT* p) { __ALIGN64 U64 T[P256_LEN52]; __ALIGN64 U64 U[P256_LEN52]; __ALIGN64 U64 V[P256_LEN52]; __ALIGN64 U64 A[P256_LEN52]; __ALIGN64 U64 B[P256_LEN52]; const U64* X1 = p->X; /* input point */ const U64* Y1 = p->Y; const U64* Z1 = p->Z; U64* X3 = r->X; /* output point */ U64* Y3 = r->Y; U64* Z3 = r->Z; mul2(T, Y1); /* T = 2*Y1 */ sqr(V, T); /* V = 4*Y1^2 */ /* sqr_dual */ sqr(U, Z1); /* U = Z1^2 */ sub(B, X1, U); /* B = X1-Z1^2 */ add(U, X1, U); /* U = X1+Z1^2 */ mul(A, V, X1); /* A = 4*X*Y1^2 */ /* mul_dual */ mul(B, B, U); /* B = (X1^2-Z1^4) */ mul2(X3, A); /* X3 = 2*A */ mul3(B, B); /* B = 3*(X1^2-Z1^4) */ sqr(U, B); /* U = B^2 */ /* sqr_dual */ sqr(Y3, V); /* Y3= V^2 = 16*Y1^4 */ sub(X3, U, X3); /* X3=B^2 - 2*A */ div2(Y3,Y3); /* Y3=Y3/2 = 8*Y1^4 */ sub(U, A, X3); /* U = A-X3 */ mul(Z3, T, Z1); /* Z3= 2*Y1*Z1 */ /* mul_dual */ mul(U, U, B); /* U = B*(A-X3) */ sub(Y3, U, Y3); /* Y3 = B*(A-X3) -8*Y1^4 */ } /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // cost: 4S+12M+7A // */ void MB_FUNC_NAME(ifma_ec_nistp256_add_point_)(P256_POINT* r, const P256_POINT* p, const P256_POINT* q) { /* coordinates of p */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q */ const U64* X2 = q->X; const U64* Y2 = q->Y; const U64* Z2 = q->Z; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->Z); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[P256_LEN52]; __ALIGN64 U64 Y3[P256_LEN52]; __ALIGN64 U64 Z3[P256_LEN52]; /* temporary */ __ALIGN64 U64 U1[P256_LEN52]; __ALIGN64 U64 U2[P256_LEN52]; __ALIGN64 U64 S1[P256_LEN52]; __ALIGN64 U64 S2[P256_LEN52]; __ALIGN64 U64 H[P256_LEN52]; __ALIGN64 U64 R[P256_LEN52]; mul(S1, Y1, Z2); /* S1 = Y1*Z2 */ sqr(U1, Z2); /* U1 = Z2^2 */ mul(S2, Y2, Z1); /* S2 = Y2*Z1 */ sqr(U2, Z1); /* U2 = Z1^2 */ mul(S1, S1, U1); /* S1 = Y1*Z2^3 */ mul(S2, S2, U2); /* S2 = Y2*Z1^3 */ mul(U1, X1, U1); /* U1 = X1*Z2^2 */ mul(U2, X2, U2); /* U2 = X2*Z1^2 */ sub(R, S2, S1); /* R = S2-S1 */ sub(H, U2, U1); /* H = U2-U1 */ /* check if affine (p.x:p.y) == (q.x:q.y) and and do doubling if this happens */ __mb_mask x_are_equal = MB_FUNC_NAME(is_zero_FE256_)(H); __mb_mask y_are_equal = MB_FUNC_NAME(is_zero_FE256_)(R); __mb_mask points_are_equal = (x_are_equal & y_are_equal & (~p_at_infinity) & (~q_at_infinity)); P256_POINT P2; MB_FUNC_NAME(set_point_to_infinity_)(&P2); if (points_are_equal) { MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&P2, p); } mul(Z3, Z1, Z2); /* Z3 = Z1*Z2 */ sqr(U2, H); /* U2 = H^2 */ mul(Z3, Z3, H); /* Z3 = (Z1*Z2)*H */ sqr(S2, R); /* S2 = R^2 */ mul(H, H, U2); /* H = H^3 */ mul(U1, U1, U2); /* U1 = U1*H^2 */ sub(X3, S2, H); /* X3 = R^2 - H^3 */ mul2(U2, U1); /* U2 = 2*U1*H^2 */ mul(S1, S1, H); /* S1 = S1*H^3 */ sub(X3, X3, U2); /* X3 = (R^2 - H^3) -2*U1*H^2 */ sub(Y3, U1, X3); /* Y3 = R*(U1*H^2 - X3) -S1*H^3 */ mul(Y3, Y3, R); sub(Y3, Y3, S1); /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FE256_)(X3, X3, p_at_infinity, q->X); MB_FUNC_NAME(mask_mov_FE256_)(Y3, Y3, p_at_infinity, q->Y); MB_FUNC_NAME(mask_mov_FE256_)(Z3, Z3, p_at_infinity, q->Z); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FE256_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FE256_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FE256_)(Z3, Z3, q_at_infinity, p->Z); /* r = points_are_equal? P2 : T */ MB_FUNC_NAME(mask_mov_FE256_)(r->X, X3, points_are_equal, P2.X); MB_FUNC_NAME(mask_mov_FE256_)(r->Y, Y3, points_are_equal, P2.Y); MB_FUNC_NAME(mask_mov_FE256_)(r->Z, Z3, points_are_equal, P2.Z); } /* to Montgomery conversion constant // r = 2^(P256_LEN52*DIGIT_SIZE) mod p256 */ __ALIGN64 static const int64u p256_r_mb[P256_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0000000000000010) }, { REP8_DECL(0x000f000000000000) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000ffeffffffffff) }, { REP8_DECL(0x00000000000fffff) } }; const U64* MB_FUNC_NAME(ifma_ec_nistp256_coord_one_)(void) { return (U64*)p256_r_mb; } /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2=1) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // if Z2=1, then // A = X1 B = X2*Z1^2 C = Y1 D = Y2*Z1^3 // E = B-X1 F = D-Y1 // X3= -E^3 -2*X1*E^2 + F^2 // Y3= -Y1*E^3 + F*(X1*E^2 -X3) // Z3= Z1*E // // cost: 3S+8M+7A */ void MB_FUNC_NAME(ifma_ec_nistp256_add_point_affine_)(P256_POINT* r, const P256_POINT* p, const P256_POINT_AFFINE* q) { /* coordinates of p (projective) */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q (affine) */ const U64* X2 = q->x; const U64* Y2 = q->y; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->x) & MB_FUNC_NAME(is_zero_point_cordinate_)(q->y); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[P256_LEN52]; __ALIGN64 U64 Y3[P256_LEN52]; __ALIGN64 U64 Z3[P256_LEN52]; __ALIGN64 U64 U2[P256_LEN52]; __ALIGN64 U64 S2[P256_LEN52]; __ALIGN64 U64 H[P256_LEN52]; __ALIGN64 U64 R[P256_LEN52]; sqr(R, Z1); // R = Z1^2 mul(S2, Y2, Z1); // S2 = Y2*Z1 mul(U2, X2, R); // U2 = X2*Z1^2 mul(S2, S2, R); // S2 = Y2*Z1^3 sub(H, U2, X1); // H = U2-X1 sub(R, S2, Y1); // R = S2-Y1 mul(Z3, H, Z1); // Z3 = H*Z1 sqr(U2, H); // U2 = H^2 sqr(S2, R); // S2 = R^2 mul(H, H, U2); // H = H^3 mul(U2, U2, X1); // U2 = X1*H^2 mul(Y3, H, Y1); // T = Y1*H^3 mul2(X3, U2); // X3 = 2*X1*H^2 sub(X3, S2, X3); // X3 = R^2 - 2*X1*H^2 sub(X3, X3, H); // X3 = R^2 - 2*X1*H^2 -H^3 sub(U2, U2, X3); // U2 = X1*H^2 - X3 mul(U2, U2, R); // U2 = R*(X1*H^2 - X3) sub(Y3, U2, Y3); // Y3 = -Y1*H^3 + R*(X1*H^2 - X3) /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FE256_)(X3, X3, p_at_infinity, q->x); MB_FUNC_NAME(mask_mov_FE256_)(Y3, Y3, p_at_infinity, q->y); MB_FUNC_NAME(mask_mov_FE256_)(Z3, Z3, p_at_infinity, (U64*)p256_r_mb); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FE256_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FE256_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FE256_)(Z3, Z3, q_at_infinity, p->Z); /* r = T */ MB_FUNC_NAME(mov_FE256_)(r->X, X3); MB_FUNC_NAME(mov_FE256_)(r->Y, Y3); MB_FUNC_NAME(mov_FE256_)(r->Z, Z3); } void MB_FUNC_NAME(get_nistp256_ec_affine_coords_)(U64 x[], U64 y[], const P256_POINT* P) { __ALIGN64 U64 invZ1[P256_LEN52]; __ALIGN64 U64 invZn[P256_LEN52]; /* 1/Z and 1/Z^2 */ MB_FUNC_NAME(ifma_aminv52_p256_)(invZ1, P->Z); MB_FUNC_NAME(ifma_ams52_p256_)(invZn, invZ1); /* if affine P.x requested */ if(x) MB_FUNC_NAME(ifma_amm52_p256_)(x, P->X, invZn); /* if affine P.y requested */ if(y) { MB_FUNC_NAME(ifma_amm52_p256_)(invZn, invZn, invZ1); MB_FUNC_NAME(ifma_amm52_p256_)(y, P->Y, invZn); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static __NOINLINE void clear_secret_context(U64* wval, U64* dval, __mb_mask* dsign) { *wval = get_zero64(); *dval = get_zero64(); *dsign = 0; return; } #define WIN_SIZE (4) /* s = (Ipp8u)(~((wvalue >> ws) - 1)); //sign d = (1 << (ws+1)) - wvalue - 1; // digit, win size "ws" d = (d & s) | (wvaluen & ~s); d = (d >> 1) + (d & 1); *sign = s & 1; *digit = (Ipp8u)d; */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract point */ static void MB_FUNC_NAME(extract_point_)(P256_POINT* r, const P256_POINT tbl[], U64 idx) { /* decrenent index (the table does not contain [0]*P */ U64 idx_target = sub64(idx, set1(1)); /* assume the point at infinity is what need */ P256_POINT R; MB_FUNC_NAME(set_point_to_infinity_)(&R); /* find out what we actually need or just keep original infinity */ int32u n; for(n=0; n<(1<<(WIN_SIZE-1)); n++) { U64 idx_curr = set1(n); __mb_mask k = cmp64_mask(idx_curr, idx_target, _MM_CMPINT_EQ); /* R = k? tbl[] : R */ MB_FUNC_NAME(secure_mask_mov_FE256_)(R.X, R.X, k, tbl[n].X); MB_FUNC_NAME(secure_mask_mov_FE256_)(R.Y, R.Y, k, tbl[n].Y); MB_FUNC_NAME(secure_mask_mov_FE256_)(R.Z, R.Z, k, tbl[n].Z); } MB_FUNC_NAME(mov_FE256_)(r->X, R.X); MB_FUNC_NAME(mov_FE256_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE256_)(r->Z, R.Z); } void MB_FUNC_NAME(ifma_ec_nistp256_mul_point_)(P256_POINT* r, const P256_POINT* p, const U64 scalar[]) { /* pre-computed table */ __ALIGN64 P256_POINT tbl[1<<(WIN_SIZE-1)]; /* // compute tbl[] = [n]P, n=1,..,2^(WIN_SIZE-1): // // tbl[2*n] = tbl[2*n-1]+p // tbl[2*n+1] = [2]*tbl[n] */ /* tbl[0] = p */ MB_FUNC_NAME(mov_FE256_)(tbl[0].X, p->X); MB_FUNC_NAME(mov_FE256_)(tbl[0].Y, p->Y); MB_FUNC_NAME(mov_FE256_)(tbl[0].Z, p->Z); /* tbl[1] = [2]*p */ MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&tbl[1], p); int n; for(n=1; n < (1<<(WIN_SIZE-1))/2; n++) { MB_FUNC_NAME(ifma_ec_nistp256_add_point_)(&tbl[2*n], &tbl[2*n-1], p); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&tbl[2*n+1], &tbl[n]); } P256_POINT R; P256_POINT T; U64 Ty[P256_LEN52]; /* // point (LR) multiplication */ U64 idx_mask = set1( (1<<(WIN_SIZE+1))-1 ); int bit = P256_BITSIZE-(P256_BITSIZE % WIN_SIZE); int chunk_no = (bit-1)/64; int chunk_shift = (bit-1)%64; /* first window */ U64 wvalue = loadu64(&scalar[chunk_no]); wvalue = and64( srli64(wvalue, chunk_shift), idx_mask); U64 dvalue; __mb_mask dsign; MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&R, tbl, dvalue); for(bit-=WIN_SIZE; bit>=WIN_SIZE; bit-=WIN_SIZE) { /* doubling */ MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); #endif /* extract precomputed []P */ chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); /* T = dsign? -T : T */ MB_FUNC_NAME(ifma_neg52_p256_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FE256_)(T.Y, T.Y, dsign, Ty); /* accumulate T */ MB_FUNC_NAME(ifma_ec_nistp256_add_point_)(&R, &R, &T); } /* last window */ MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_nistp256_dbl_point_)(&R, &R); #endif wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); MB_FUNC_NAME(ifma_neg52_p256_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FE256_)(T.Y, T.Y, dsign, Ty); MB_FUNC_NAME(ifma_ec_nistp256_add_point_)(&R, &R, &T); /* r = R */ MB_FUNC_NAME(mov_FE256_)(r->X, R.X); MB_FUNC_NAME(mov_FE256_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE256_)(r->Z, R.Z); /* clear r (to fix potential secutity flaw in case of ecdh */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef WIN_SIZE ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// #include #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE /* defined in the header above */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_bp_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, BP_WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(BP_WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract affine affine point */ __MBX_INLINE void MB_FUNC_NAME(extract_point_affine_)(P256_POINT_AFFINE* r, const SINGLE_P256_POINT_AFFINE* tbl, U64 idx) { /* decrement index (the table does not contain [0]*P */ U64 targIdx = sub64(idx, set1(1)); U64 ax0, ax1, ax2, ax3, ax4, ay0, ay1, ay2, ay3, ay4; /* assume the point at infinity is what need */ ax0 = ax1 = ax2 = ax3 = ax4 = ay0 = ay1 = ay2 = ay3 = ay4 = get_zero64(); /* find out what we actually need or just keep original infinity */ int n; U64 currIdx = get_zero64(); for(n=0; n<(1<<(BP_WIN_SIZE-1)); n++, tbl++, currIdx = add64(currIdx, set1(1))) { __mb_mask k = cmp64_mask(currIdx, targIdx, _MM_CMPINT_EQ); /* R = k? set1( tbl[] ) : R */ ax0 = mask_add64(ax0, k, ax0, set1( tbl->x[0] )); ax1 = mask_add64(ax1, k, ax1, set1( tbl->x[1] )); ax2 = mask_add64(ax2, k, ax2, set1( tbl->x[2] )); ax3 = mask_add64(ax3, k, ax3, set1( tbl->x[3] )); ax4 = mask_add64(ax4, k, ax4, set1( tbl->x[4] )); ay0 = mask_add64(ay0, k, ay0, set1( tbl->y[0] )); ay1 = mask_add64(ay1, k, ay1, set1( tbl->y[1] )); ay2 = mask_add64(ay2, k, ay2, set1( tbl->y[2] )); ay3 = mask_add64(ay3, k, ay3, set1( tbl->y[3] )); ay4 = mask_add64(ay4, k, ay4, set1( tbl->y[4] )); } r->x[0] = ax0; r->x[1] = ax1; r->x[2] = ax2; r->x[3] = ax3; r->x[4] = ax4; r->y[0] = ay0; r->y[1] = ay1; r->y[2] = ay2; r->y[3] = ay3; r->y[4] = ay4; } void MB_FUNC_NAME(ifma_ec_nistp256_mul_pointbase_)(P256_POINT* r, const U64 scalar[]) { /* pre-computed table of base powers */ SINGLE_P256_POINT_AFFINE* tbl = &ifma_ec_nistp256_bp_precomp[0][0]; P256_POINT R; P256_POINT_AFFINE A; U64 Ty[P256_LEN52]; /* R = O */ MB_FUNC_NAME(set_point_to_infinity_)(&R); /* // base point (RL) multiplication */ U64 wvalue, dvalue; __mb_mask dsign; U64 idx_mask = set1( (1<<(BP_WIN_SIZE+1))-1 ); int bit = 0; /* first window - window[0] */ wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_p256_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FE256_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_nistp256_add_point_affine_)(&R, &R, &A); int chunk_no; int chunk_shift; for(bit+=BP_WIN_SIZE; bit<=P256_BITSIZE; bit+=BP_WIN_SIZE) { chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_p256_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FE256_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_nistp256_add_point_affine_)(&R, &R, &A); } /* r = R */ MB_FUNC_NAME(mov_FE256_)(r->X, R.X); MB_FUNC_NAME(mov_FE256_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE256_)(r->Z, R.Z); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef BP_WIN_SIZE /* P256 parameters: mont(a), mont(b) */ __ALIGN64 static const int64u mont_a_p256_mb[P256_LEN52][8] = { { REP8_DECL(0x000fffffffffffcf) }, { REP8_DECL(0x00030fffffffffff) }, { REP8_DECL(0x000000000000000) }, { REP8_DECL(0x0000031000000000) }, { REP8_DECL(0x0000ffffffcf0000) } }; __ALIGN64 static const int64u mont_b_p256_mb[P256_LEN52][8] = { { REP8_DECL(0x000df6229c4bddfd) }, { REP8_DECL(0x000ca8843090d89c) }, { REP8_DECL(0x000212ed6acf005c) }, { REP8_DECL(0x00083415a220abf7) }, { REP8_DECL(0x0000c30061dd4874) } }; /* // We have a curve defined by a Weierstrass equation: y^2 = x^3 + a*x + b. // // The points are considered in Jacobian projective coordinates // where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). // Substituting this and multiplying by Z^6 transforms the above equation into // Y^2 = X^3 + a*X*Z^4 + b*Z^6 // To test this, we add up the right-hand side in 'rh'. */ __mb_mask MB_FUNC_NAME(ifma_is_on_curve_p256_)(const P256_POINT* p, int use_jproj_coords) { U64 rh[P256_LEN52]; U64 Z4[P256_LEN52], Z6[P256_LEN52], tmp[P256_LEN52]; /* rh := X^2 */ MB_FUNC_NAME(ifma_ams52_p256_)(rh, p->X); /* if Z!=1, then rh = X^3 + a*X*Z^4 + b*Z^6 = X*(X^2 + a*X*Z^4) + b*Z^6 */ if(use_jproj_coords) { MB_FUNC_NAME(ifma_ams52_p256_)(tmp, p->Z); /* tmp = Z^2 */ MB_FUNC_NAME(ifma_ams52_p256_)(Z4, tmp); /* Z4 = Z^4 */ MB_FUNC_NAME(ifma_amm52_p256_)(Z6, Z4, tmp); /* Z6 = Z^6 */ MB_FUNC_NAME(ifma_add52_p256_)(tmp, Z4, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_add52_p256_)(tmp, tmp, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_sub52_p256_)(rh, rh, tmp); /* rh = X^2 + a*Z^4 */ MB_FUNC_NAME(ifma_amm52_p256_)(rh, rh, p->X); /* rh = (X^2 + a*Z^4)*X */ MB_FUNC_NAME(ifma_amm52_p256_)(tmp, Z6, (U64*)mont_b_p256_mb); MB_FUNC_NAME(ifma_add52_p256_)(rh, rh, tmp); /* rh = (X^2 + a*Z^4)*X + b*Z^6 */ } /* if Z==1, then rh = X^3 + a*X + b = X*(X^2 +a) b */ else { MB_FUNC_NAME(ifma_add52_p256_)(rh, rh, (U64*)mont_a_p256_mb); /* rh = X^2+a */ MB_FUNC_NAME(ifma_amm52_p256_)(rh, rh, p->X); /* rh = (X^2+a)*X */ MB_FUNC_NAME(ifma_add52_p256_)(rh, rh, (U64*)mont_b_p256_mb); /* rh = (X^2+a)*X + b */ } MB_FUNC_NAME(ifma_frommont52_p256_)(rh, rh); /* rl = tmp = Y^2 */ MB_FUNC_NAME(ifma_ams52_p256_)(tmp, p->Y); MB_FUNC_NAME(ifma_frommont52_p256_)(tmp, tmp); /* mask = rl==rh */ __mb_mask is_on_curve_mask = MB_FUNC_NAME(cmp_eq_FE256_)(tmp, rh); return is_on_curve_mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecpoint_p384.c000066400000000000000000000546611470420105600306760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* simplify naming */ #define sqr MB_FUNC_NAME(ifma_ams52_p384_) #define mul MB_FUNC_NAME(ifma_amm52_p384_) #define add MB_FUNC_NAME(ifma_add52_p384_) #define sub MB_FUNC_NAME(ifma_sub52_p384_) #define mul2 MB_FUNC_NAME(ifma_double52_p384_) #define mul3 MB_FUNC_NAME(ifma_tripple52_p384_) #define div2 MB_FUNC_NAME(ifma_half52_p384_) /* // Presentation of point at infinity: // - projective (X : Y : 0) // - affine (0 : 0) */ /* // R(X3:Y3:Z3) = [2]P(X1:Y1:Z1) // // formulas: // A = 4*X1*Y1^2 // B = 3*(X1^2-Z1^4) // X3= B^2 -2*A // Y3= B*(A-X3) -8*Y1^4 // Z3= 2*Y1*Z1 // // cost: 4S+4M+9A // */ void MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(P384_POINT* r, const P384_POINT* p) { __ALIGN64 U64 T[P384_LEN52]; __ALIGN64 U64 U[P384_LEN52]; __ALIGN64 U64 V[P384_LEN52]; __ALIGN64 U64 A[P384_LEN52]; __ALIGN64 U64 B[P384_LEN52]; const U64* X1 = p->X; /* input point */ const U64* Y1 = p->Y; const U64* Z1 = p->Z; U64* X3 = r->X; /* output point */ U64* Y3 = r->Y; U64* Z3 = r->Z; mul2(T, Y1); /* T = 2*Y1 */ sqr(V, T); /* V = 4*Y1^2 */ /* sqr_dual */ sqr(U, Z1); /* U = Z1^2 */ sub(B, X1, U); /* B = X1-Z1^2 */ add(U, X1, U); /* U = X1+Z1^2 */ mul(A, V, X1); /* A = 4*X*Y1^2 */ /* mul_dual */ mul(B, B, U); /* B = (X1^2-Z1^4) */ mul2(X3, A); /* X3 = 2*A */ mul3(B, B); /* B = 3*(X1^2-Z1^4) */ sqr(U, B); /* U = B^2 */ /* sqr_dual */ sqr(Y3, V); /* Y3= V^2 = 16*Y1^4 */ sub(X3, U, X3); /* X3=B^2 - 2*A */ div2(Y3,Y3); /* Y3=Y3/2 = 8*Y1^4 */ sub(U, A, X3); /* U = A-X3 */ mul(Z3, T, Z1); /* Z3= 2*Y1*Z1 */ /* mul_dual */ mul(U, U, B); /* U = B*(A-X3) */ sub(Y3, U, Y3); /* Y3 = B*(A-X3) -8*Y1^4 */ } /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // cost: 4S+12M+7A // */ void MB_FUNC_NAME(ifma_ec_nistp384_add_point_)(P384_POINT* r, const P384_POINT* p, const P384_POINT* q) { /* coordinates of p */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q */ const U64* X2 = q->X; const U64* Y2 = q->Y; const U64* Z2 = q->Z; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->Z); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[P384_LEN52]; __ALIGN64 U64 Y3[P384_LEN52]; __ALIGN64 U64 Z3[P384_LEN52]; /* temporary */ __ALIGN64 U64 U1[P384_LEN52]; __ALIGN64 U64 U2[P384_LEN52]; __ALIGN64 U64 S1[P384_LEN52]; __ALIGN64 U64 S2[P384_LEN52]; __ALIGN64 U64 H[P384_LEN52]; __ALIGN64 U64 R[P384_LEN52]; mul(S1, Y1, Z2); /* S1 = Y1*Z2 */ sqr(U1, Z2); /* U1 = Z2^2 */ mul(S2, Y2, Z1); /* S2 = Y2*Z1 */ sqr(U2, Z1); /* U2 = Z1^2 */ mul(S1, S1, U1); /* S1 = Y1*Z2^3 */ mul(S2, S2, U2); /* S2 = Y2*Z1^3 */ mul(U1, X1, U1); /* U1 = X1*Z2^2 */ mul(U2, X2, U2); /* U2 = X2*Z1^2 */ sub(R, S2, S1); /* R = S2-S1 */ sub(H, U2, U1); /* H = U2-U1 */ /* check if affine (p.x:p.y) == (q.x:q.y) and and do doubling if this happens */ __mb_mask x_are_equal = MB_FUNC_NAME(is_zero_FE384_)(H); __mb_mask y_are_equal = MB_FUNC_NAME(is_zero_FE384_)(R); __mb_mask points_are_equal = (x_are_equal & y_are_equal & (~p_at_infinity) & (~q_at_infinity)); P384_POINT P2; MB_FUNC_NAME(set_point_to_infinity_)(&P2); if (points_are_equal) { MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&P2, p); } mul(Z3, Z1, Z2); /* Z3 = Z1*Z2 */ sqr(U2, H); /* U2 = H^2 */ mul(Z3, Z3, H); /* Z3 = (Z1*Z2)*H */ sqr(S2, R); /* S2 = R^2 */ mul(H, H, U2); /* H = H^3 */ mul(U1, U1, U2); /* U1 = U1*H^2 */ sub(X3, S2, H); /* X3 = R^2 - H^3 */ mul2(U2, U1); /* U2 = 2*U1*H^2 */ mul(S1, S1, H); /* S1 = S1*H^3 */ sub(X3, X3, U2); /* X3 = (R^2 - H^3) -2*U1*H^2 */ sub(Y3, U1, X3); /* Y3 = R*(U1*H^2 - X3) -S1*H^3 */ mul(Y3, Y3, R); sub(Y3, Y3, S1); /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FE384_)(X3, X3, p_at_infinity, q->X); MB_FUNC_NAME(mask_mov_FE384_)(Y3, Y3, p_at_infinity, q->Y); MB_FUNC_NAME(mask_mov_FE384_)(Z3, Z3, p_at_infinity, q->Z); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FE384_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FE384_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FE384_)(Z3, Z3, q_at_infinity, p->Z); /* r = points_are_equal? P2 : T */ MB_FUNC_NAME(mask_mov_FE384_)(r->X, X3, points_are_equal, P2.X); MB_FUNC_NAME(mask_mov_FE384_)(r->Y, Y3, points_are_equal, P2.Y); MB_FUNC_NAME(mask_mov_FE384_)(r->Z, Z3, points_are_equal, P2.Z); } /* Montgomery(1) // r = 2^(P384_LEN52*DIGIT_SIZE) mod p384 */ __ALIGN64 static const int64u p384_r_mb[P384_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0000000100000000) }, { REP8_DECL(0x000ffffffffff000) }, { REP8_DECL(0x0000000000ffffff) }, { REP8_DECL(0x0000000000000010) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) } }; /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2=1) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // if Z2=1, then // A = X1 B = X2*Z1^2 C = Y1 D = Y2*Z1^3 // E = B-X1 F = D-Y1 // X3= -E^3 -2*X1*E^2 + F^2 // Y3= -Y1*E^3 + F*(X1*E^2 -X3) // Z3= Z1*E // // cost: 3S+8M+7A */ void MB_FUNC_NAME(ifma_ec_nistp384_add_point_affine_)(P384_POINT* r, const P384_POINT* p, const P384_POINT_AFFINE* q) { /* coordinates of p (projective) */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q (affine) */ const U64* X2 = q->x; const U64* Y2 = q->y; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->x) & MB_FUNC_NAME(is_zero_point_cordinate_)(q->y); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[P384_LEN52]; __ALIGN64 U64 Y3[P384_LEN52]; __ALIGN64 U64 Z3[P384_LEN52]; __ALIGN64 U64 U2[P384_LEN52]; __ALIGN64 U64 S2[P384_LEN52]; __ALIGN64 U64 H[P384_LEN52]; __ALIGN64 U64 R[P384_LEN52]; sqr(R, Z1); // R = Z1^2 mul(S2, Y2, Z1); // S2 = Y2*Z1 mul(U2, X2, R); // U2 = X2*Z1^2 mul(S2, S2, R); // S2 = Y2*Z1^3 sub(H, U2, X1); // H = U2-X1 sub(R, S2, Y1); // R = S2-Y1 mul(Z3, H, Z1); // Z3 = H*Z1 sqr(U2, H); // U2 = H^2 sqr(S2, R); // S2 = R^2 mul(H, H, U2); // H = H^3 mul(U2, U2, X1); // U2 = X1*H^2 mul(Y3, H, Y1); // T = Y1*H^3 mul2(X3, U2); // X3 = 2*X1*H^2 sub(X3, S2, X3); // X3 = R^2 - 2*X1*H^2 sub(X3, X3, H); // X3 = R^2 - 2*X1*H^2 -H^3 sub(U2, U2, X3); // U2 = X1*H^2 - X3 mul(U2, U2, R); // U2 = R*(X1*H^2 - X3) sub(Y3, U2, Y3); // Y3 = -Y1*H^3 + R*(X1*H^2 - X3) /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FE384_)(X3, X3, p_at_infinity, q->x); MB_FUNC_NAME(mask_mov_FE384_)(Y3, Y3, p_at_infinity, q->y); MB_FUNC_NAME(mask_mov_FE384_)(Z3, Z3, p_at_infinity, (U64*)p384_r_mb); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FE384_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FE384_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FE384_)(Z3, Z3, q_at_infinity, p->Z); /* r = T */ MB_FUNC_NAME(mov_FE384_)(r->X, X3); MB_FUNC_NAME(mov_FE384_)(r->Y, Y3); MB_FUNC_NAME(mov_FE384_)(r->Z, Z3); } void MB_FUNC_NAME(get_nistp384_ec_affine_coords_)(U64 x[], U64 y[], const P384_POINT* P) { __ALIGN64 U64 invZ1[P384_LEN52]; __ALIGN64 U64 invZn[P384_LEN52]; /* 1/Z and 1/Z^2 */ MB_FUNC_NAME(ifma_aminv52_p384_)(invZ1, P->Z); MB_FUNC_NAME(ifma_ams52_p384_)(invZn, invZ1); /* if affine P.x requested */ if(x) MB_FUNC_NAME(ifma_amm52_p384_)(x, P->X, invZn); /* if affine P.y requested */ if(y) { MB_FUNC_NAME(ifma_amm52_p384_)(invZn, invZn, invZ1); MB_FUNC_NAME(ifma_amm52_p384_)(y, P->Y, invZn); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static __NOINLINE void clear_secret_context(U64* wval, U64* dval, __mb_mask* dsign) { *wval = get_zero64(); *dval = get_zero64(); *dsign = 0; return; } #define WIN_SIZE (4) /* s = (Ipp8u)(~((wvalue >> ws) - 1)); //sign d = (1 << (ws+1)) - wvalue - 1; // digit, win size "ws" d = (d & s) | (wvaluen & ~s); d = (d >> 1) + (d & 1); *sign = s & 1; *digit = (Ipp8u)d; */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract point */ static void MB_FUNC_NAME(extract_point_)(P384_POINT* r, const P384_POINT tbl[], U64 idx) { /* decrenent index (the table does not contain [0]*P */ U64 idx_target = sub64(idx, set1(1)); /* assume the point at infinity is what need */ P384_POINT R; MB_FUNC_NAME(set_point_to_infinity_)(&R); /* find out what we actually need or just keep original infinity */ int32u n; for(n=0; n<(1<<(WIN_SIZE-1)); n++) { U64 idx_curr = set1(n); __mb_mask k = cmp64_mask(idx_curr, idx_target, _MM_CMPINT_EQ); /* R = k? tbl[] : R */ MB_FUNC_NAME(secure_mask_mov_FE384_)(R.X, R.X, k, tbl[n].X); MB_FUNC_NAME(secure_mask_mov_FE384_)(R.Y, R.Y, k, tbl[n].Y); MB_FUNC_NAME(secure_mask_mov_FE384_)(R.Z, R.Z, k, tbl[n].Z); } MB_FUNC_NAME(mov_FE384_)(r->X, R.X); MB_FUNC_NAME(mov_FE384_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE384_)(r->Z, R.Z); } void MB_FUNC_NAME(ifma_ec_nistp384_mul_point_)(P384_POINT* r, const P384_POINT* p, const U64 scalar[]) { /* pre-computed table */ __ALIGN64 P384_POINT tbl[1<<(WIN_SIZE-1)]; /* // compute tbl[] = [n]P, n=1,..,2^(WIN_SIZE-1): // // tbl[2*n] = tbl[2*n-1]+p // tbl[2*n+1] = [2]*tbl[n] */ /* tbl[0] = p */ MB_FUNC_NAME(mov_FE384_)(tbl[0].X, p->X); MB_FUNC_NAME(mov_FE384_)(tbl[0].Y, p->Y); MB_FUNC_NAME(mov_FE384_)(tbl[0].Z, p->Z); /* tbl[1] = [2]*p */ MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&tbl[1], p); int n; for(n=1; n < (1<<(WIN_SIZE-1))/2; n++) { MB_FUNC_NAME(ifma_ec_nistp384_add_point_)(&tbl[2*n], &tbl[2*n-1], p); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&tbl[2*n+1], &tbl[n]); } P384_POINT R; P384_POINT T; U64 Ty[P384_LEN52]; /* // point (LR) multiplication */ U64 idx_mask = set1( (1<<(WIN_SIZE+1))-1 ); int bit = P384_BITSIZE-(P384_BITSIZE % WIN_SIZE); int chunk_no = (bit-1)/64; int chunk_shift = (bit-1)%64; /* first window */ U64 wvalue = loadu64(&scalar[chunk_no]); wvalue = and64( srli64(wvalue, chunk_shift), idx_mask); U64 dvalue; __mb_mask dsign; MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&R, tbl, dvalue); for(bit-=WIN_SIZE; bit>=WIN_SIZE; bit-=WIN_SIZE) { /* doubling */ MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); #endif /* extract precomputed []P */ chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); /* T = dsign? -T : T */ MB_FUNC_NAME(ifma_neg52_p384_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FE384_)(T.Y, T.Y, dsign, Ty); /* accumulate T */ MB_FUNC_NAME(ifma_ec_nistp384_add_point_)(&R, &R, &T); } /* last window */ MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_nistp384_dbl_point_)(&R, &R); #endif wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); MB_FUNC_NAME(ifma_neg52_p384_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FE384_)(T.Y, T.Y, dsign, Ty); MB_FUNC_NAME(ifma_ec_nistp384_add_point_)(&R, &R, &T); /* r = R */ MB_FUNC_NAME(mov_FE384_)(r->X, R.X); MB_FUNC_NAME(mov_FE384_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE384_)(r->Z, R.Z); /* clear r (to fix potential secutity flaw in case of ecdh */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef WIN_SIZE ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// #include #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE /* defined in the header above */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_bp_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, BP_WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(BP_WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract affine affine point */ __MBX_INLINE void MB_FUNC_NAME(extract_point_affine_)(P384_POINT_AFFINE* r, const SINGLE_P384_POINT_AFFINE* tbl, U64 idx) { /* decrement index (the table does not contain [0]*P */ U64 targIdx = sub64(idx, set1(1)); U64 ax0, ax1, ax2, ax3, ax4, ax5, ax6, ax7; U64 ay0, ay1, ay2, ay3, ay4, ay5, ay6, ay7; /* assume the point at infinity is what need */ ax0 = ax1 = ax2 = ax3 = ax4 = ax5 = ax6 = ax7= ay0 = ay1 = ay2 = ay3 = ay4 = ay5 = ay6 = ay7 = get_zero64(); /* find out what we actually need or just keep original infinity */ int n; U64 currIdx = get_zero64(); for(n=0; n<(1<<(BP_WIN_SIZE-1)); n++, tbl++, currIdx = add64(currIdx, set1(1))) { __mb_mask k = cmp64_mask(currIdx, targIdx, _MM_CMPINT_EQ); /* R = k? set1( tbl[] ) : R */ ax0 = mask_add64(ax0, k, ax0, set1( tbl->x[0] )); ax1 = mask_add64(ax1, k, ax1, set1( tbl->x[1] )); ax2 = mask_add64(ax2, k, ax2, set1( tbl->x[2] )); ax3 = mask_add64(ax3, k, ax3, set1( tbl->x[3] )); ax4 = mask_add64(ax4, k, ax4, set1( tbl->x[4] )); ax5 = mask_add64(ax5, k, ax5, set1( tbl->x[5] )); ax6 = mask_add64(ax6, k, ax6, set1( tbl->x[6] )); ax7 = mask_add64(ax7, k, ax7, set1( tbl->x[7] )); ay0 = mask_add64(ay0, k, ay0, set1( tbl->y[0] )); ay1 = mask_add64(ay1, k, ay1, set1( tbl->y[1] )); ay2 = mask_add64(ay2, k, ay2, set1( tbl->y[2] )); ay3 = mask_add64(ay3, k, ay3, set1( tbl->y[3] )); ay4 = mask_add64(ay4, k, ay4, set1( tbl->y[4] )); ay5 = mask_add64(ay5, k, ay5, set1( tbl->y[5] )); ay6 = mask_add64(ay6, k, ay6, set1( tbl->y[6] )); ay7 = mask_add64(ay7, k, ay7, set1( tbl->y[7] )); } r->x[0] = ax0; r->x[1] = ax1; r->x[2] = ax2; r->x[3] = ax3; r->x[4] = ax4; r->x[5] = ax5; r->x[6] = ax6; r->x[7] = ax7; r->y[0] = ay0; r->y[1] = ay1; r->y[2] = ay2; r->y[3] = ay3; r->y[4] = ay4; r->y[5] = ay5; r->y[6] = ay6; r->y[7] = ay7; } void MB_FUNC_NAME(ifma_ec_nistp384_mul_pointbase_)(P384_POINT* r, const U64 scalar[]) { /* pre-computed table of base powers */ SINGLE_P384_POINT_AFFINE* tbl = &ifma_ec_nistp384_bp_precomp[0][0]; P384_POINT R; P384_POINT_AFFINE A; U64 Ty[P384_LEN52]; /* R = O */ MB_FUNC_NAME(set_point_to_infinity_)(&R); /* // base point (RL) multiplication */ U64 wvalue, dvalue; __mb_mask dsign; U64 idx_mask = set1( (1<<(BP_WIN_SIZE+1))-1 ); int bit = 0; /* first window - window[0] */ wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_p384_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FE384_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_nistp384_add_point_affine_)(&R, &R, &A); int chunk_no; int chunk_shift; for(bit+=BP_WIN_SIZE; bit<=P384_BITSIZE; bit+=BP_WIN_SIZE) { chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_p384_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FE384_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_nistp384_add_point_affine_)(&R, &R, &A); } /* r = R */ MB_FUNC_NAME(mov_FE384_)(r->X, R.X); MB_FUNC_NAME(mov_FE384_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE384_)(r->Z, R.Z); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef BP_WIN_SIZE /* P384 parameters: mont(a), mont(b) */ __ALIGN64 int64u mont_a_p384_mb[P384_LEN52][8] = { //!!! { REP8_DECL(0x000ffffdffffffff) }, { REP8_DECL(0x000ff00000002fff) }, { REP8_DECL(0x000ffffffbffffff) }, { REP8_DECL(0x000fffffffffffcf) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x00000000000fffff) } }; __ALIGN64 int64u mont_b_p384_mb[P384_LEN52][8] = { //!!!!! { REP8_DECL(0x00091c81cd08114b) }, { REP8_DECL(0x0003708118870d03) }, { REP8_DECL(0x000431bf24475444) }, { REP8_DECL(0x000209b1920022fc) }, { REP8_DECL(0x000e94938ae277f2) }, { REP8_DECL(0x000022094e3374be) }, { REP8_DECL(0x000ff9b62b21f41f) }, { REP8_DECL(0x00000000000604fb) }, }; /* // We have a curve defined by a Weierstrass equation: y^2 = x^3 + a*x + b. // // The points are considered in Jacobian projective coordinates // where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). // Substituting this and multiplying by Z^6 transforms the above equation into // Y^2 = X^3 + a*X*Z^4 + b*Z^6 // To test this, we add up the right-hand side in 'rh'. */ __mb_mask MB_FUNC_NAME(ifma_is_on_curve_p384_)(const P384_POINT* p, int use_jproj_coords) { U64 rh[P384_LEN52]; U64 Z4[P384_LEN52], Z6[P384_LEN52], tmp[P384_LEN52]; /* rh := X^2 */ MB_FUNC_NAME(ifma_ams52_p384_)(rh, p->X); /* if Z!=1, then rh = X^3 + a*X*Z^4 + b*Z^6 = X*(X^2 + a*X*Z^4) + b*Z^6 */ if(use_jproj_coords) { MB_FUNC_NAME(ifma_ams52_p384_)(tmp, p->Z); /* tmp = Z^2 */ MB_FUNC_NAME(ifma_ams52_p384_)(Z4, tmp); /* Z4 = Z^4 */ MB_FUNC_NAME(ifma_amm52_p384_)(Z6, Z4, tmp); /* Z6 = Z^6 */ MB_FUNC_NAME(ifma_add52_p384_)(tmp, Z4, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_add52_p384_)(tmp, tmp, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_sub52_p384_)(rh, rh, tmp); /* rh = X^2 + a*Z^4 */ MB_FUNC_NAME(ifma_amm52_p384_)(rh, rh, p->X); /* rh = (X^2 + a*Z^4)*X */ MB_FUNC_NAME(ifma_amm52_p384_)(tmp, Z6, (U64*)mont_b_p384_mb); MB_FUNC_NAME(ifma_add52_p384_)(rh, rh, tmp); /* rh = (X^2 + a*Z^4)*X + b*Z^6 */ } /* if Z==1, then rh = X^3 + a*X + b = X*(X^2 +a) b */ else { MB_FUNC_NAME(ifma_add52_p384_)(rh, rh, (U64*)mont_a_p384_mb); /* rh = X^2+a */ MB_FUNC_NAME(ifma_amm52_p384_)(rh, rh, p->X); /* rh = (X^2+a)*X */ MB_FUNC_NAME(ifma_add52_p384_)(rh, rh, (U64*)mont_b_p384_mb); /* rh = (X^2+a)*X + b */ } MB_FUNC_NAME(ifma_frommont52_p384_)(rh, rh); /* rl = tmp = Y^2 */ MB_FUNC_NAME(ifma_ams52_p384_)(tmp, p->Y); MB_FUNC_NAME(ifma_frommont52_p384_)(tmp, tmp); /* mask = rl==rh */ __mb_mask is_on_curve_mask = MB_FUNC_NAME(cmp_eq_FE384_)(tmp, rh); return is_on_curve_mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecpoint_p521.c000066400000000000000000000564141470420105600306650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* simplify naming */ #define sqr MB_FUNC_NAME(ifma_ams52_p521_) #define mul MB_FUNC_NAME(ifma_amm52_p521_) #define add MB_FUNC_NAME(ifma_add52_p521_) #define sub MB_FUNC_NAME(ifma_sub52_p521_) #define mul2 MB_FUNC_NAME(ifma_double52_p521_) #define mul3 MB_FUNC_NAME(ifma_tripple52_p521_) #define div2 MB_FUNC_NAME(ifma_half52_p521_) /* // Presentation of point at infinity: // - projective (X : Y : 0) // - affine (0 : 0) */ /* // R(X3:Y3:Z3) = [2]P(X1:Y1:Z1) // // formulas: // A = 4*X1*Y1^2 // B = 3*(X1^2-Z1^4) // X3= B^2 -2*A // Y3= B*(A-X3) -8*Y1^4 // Z3= 2*Y1*Z1 // // cost: 4S+4M+9A // */ void MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(P521_POINT* r, const P521_POINT* p) { __ALIGN64 U64 T[P521_LEN52]; __ALIGN64 U64 U[P521_LEN52]; __ALIGN64 U64 V[P521_LEN52]; __ALIGN64 U64 A[P521_LEN52]; __ALIGN64 U64 B[P521_LEN52]; const U64* X1 = p->X; /* input point */ const U64* Y1 = p->Y; const U64* Z1 = p->Z; U64* X3 = r->X; /* output point */ U64* Y3 = r->Y; U64* Z3 = r->Z; mul2(T, Y1); /* T = 2*Y1 */ sqr(V, T); /* V = 4*Y1^2 */ /* sqr_dual */ sqr(U, Z1); /* U = Z1^2 */ sub(B, X1, U); /* B = X1-Z1^2 */ add(U, X1, U); /* U = X1+Z1^2 */ mul(A, V, X1); /* A = 4*X*Y1^2 */ /* mul_dual */ mul(B, B, U); /* B = (X1^2-Z1^4) */ mul2(X3, A); /* X3 = 2*A */ mul3(B, B); /* B = 3*(X1^2-Z1^4) */ sqr(U, B); /* U = B^2 */ /* sqr_dual */ sqr(Y3, V); /* Y3= V^2 = 16*Y1^4 */ sub(X3, U, X3); /* X3=B^2 - 2*A */ div2(Y3,Y3); /* Y3=Y3/2 = 8*Y1^4 */ sub(U, A, X3); /* U = A-X3 */ mul(Z3, T, Z1); /* Z3= 2*Y1*Z1 */ /* mul_dual */ mul(U, U, B); /* U = B*(A-X3) */ sub(Y3, U, Y3); /* Y3 = B*(A-X3) -8*Y1^4 */ } /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // cost: 4S+12M+7A // */ void MB_FUNC_NAME(ifma_ec_nistp521_add_point_)(P521_POINT* r, const P521_POINT* p, const P521_POINT* q) { /* coordinates of p */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q */ const U64* X2 = q->X; const U64* Y2 = q->Y; const U64* Z2 = q->Z; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->Z); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[P521_LEN52]; __ALIGN64 U64 Y3[P521_LEN52]; __ALIGN64 U64 Z3[P521_LEN52]; /* temporary */ __ALIGN64 U64 U1[P521_LEN52]; __ALIGN64 U64 U2[P521_LEN52]; __ALIGN64 U64 S1[P521_LEN52]; __ALIGN64 U64 S2[P521_LEN52]; __ALIGN64 U64 H[P521_LEN52]; __ALIGN64 U64 R[P521_LEN52]; mul(S1, Y1, Z2); /* S1 = Y1*Z2 */ sqr(U1, Z2); /* U1 = Z2^2 */ mul(S2, Y2, Z1); /* S2 = Y2*Z1 */ sqr(U2, Z1); /* U2 = Z1^2 */ mul(S1, S1, U1); /* S1 = Y1*Z2^3 */ mul(S2, S2, U2); /* S2 = Y2*Z1^3 */ mul(U1, X1, U1); /* U1 = X1*Z2^2 */ mul(U2, X2, U2); /* U2 = X2*Z1^2 */ sub(R, S2, S1); /* R = S2-S1 */ sub(H, U2, U1); /* H = U2-U1 */ /* check if affine (p.x:p.y) == (q.x:q.y) and and do doubling if this happens */ __mb_mask x_are_equal = MB_FUNC_NAME(is_zero_FE521_)(H); __mb_mask y_are_equal = MB_FUNC_NAME(is_zero_FE521_)(R); __mb_mask points_are_equal = (x_are_equal & y_are_equal & (~p_at_infinity) & (~q_at_infinity)); P521_POINT P2; MB_FUNC_NAME(set_point_to_infinity_)(&P2); if (points_are_equal) { MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&P2, p); } mul(Z3, Z1, Z2); /* Z3 = Z1*Z2 */ sqr(U2, H); /* U2 = H^2 */ mul(Z3, Z3, H); /* Z3 = (Z1*Z2)*H */ sqr(S2, R); /* S2 = R^2 */ mul(H, H, U2); /* H = H^3 */ mul(U1, U1, U2); /* U1 = U1*H^2 */ sub(X3, S2, H); /* X3 = R^2 - H^3 */ mul2(U2, U1); /* U2 = 2*U1*H^2 */ mul(S1, S1, H); /* S1 = S1*H^3 */ sub(X3, X3, U2); /* X3 = (R^2 - H^3) -2*U1*H^2 */ sub(Y3, U1, X3); /* Y3 = R*(U1*H^2 - X3) -S1*H^3 */ mul(Y3, Y3, R); sub(Y3, Y3, S1); /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FE521_)(X3, X3, p_at_infinity, q->X); MB_FUNC_NAME(mask_mov_FE521_)(Y3, Y3, p_at_infinity, q->Y); MB_FUNC_NAME(mask_mov_FE521_)(Z3, Z3, p_at_infinity, q->Z); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FE521_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FE521_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FE521_)(Z3, Z3, q_at_infinity, p->Z); /* r = T */ /* r = points_are_equal? P2 : T */ MB_FUNC_NAME(mask_mov_FE521_)(r->X, X3, points_are_equal, P2.X); MB_FUNC_NAME(mask_mov_FE521_)(r->Y, Y3, points_are_equal, P2.Y); MB_FUNC_NAME(mask_mov_FE521_)(r->Z, Z3, points_are_equal, P2.Z); } /* Montgomery(1) // r = 2^(P521_LEN52*DIGIT_SIZE) mod p521 */ __ALIGN64 static const int64u p521_r_mb[P521_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0008000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) } }; /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2=1) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // if Z2=1, then // A = X1 B = X2*Z1^2 C = Y1 D = Y2*Z1^3 // E = B-X1 F = D-Y1 // X3= -E^3 -2*X1*E^2 + F^2 // Y3= -Y1*E^3 + F*(X1*E^2 -X3) // Z3= Z1*E // // cost: 3S+8M+7A */ void MB_FUNC_NAME(ifma_ec_nistp521_add_point_affine_)(P521_POINT* r, const P521_POINT* p, const P521_POINT_AFFINE* q) { /* coordinates of p (projective) */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q (affine) */ const U64* X2 = q->x; const U64* Y2 = q->y; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->x) & MB_FUNC_NAME(is_zero_point_cordinate_)(q->y); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[P521_LEN52]; __ALIGN64 U64 Y3[P521_LEN52]; __ALIGN64 U64 Z3[P521_LEN52]; __ALIGN64 U64 U2[P521_LEN52]; __ALIGN64 U64 S2[P521_LEN52]; __ALIGN64 U64 H[P521_LEN52]; __ALIGN64 U64 R[P521_LEN52]; sqr(R, Z1); // R = Z1^2 mul(S2, Y2, Z1); // S2 = Y2*Z1 mul(U2, X2, R); // U2 = X2*Z1^2 mul(S2, S2, R); // S2 = Y2*Z1^3 sub(H, U2, X1); // H = U2-X1 sub(R, S2, Y1); // R = S2-Y1 mul(Z3, H, Z1); // Z3 = H*Z1 sqr(U2, H); // U2 = H^2 sqr(S2, R); // S2 = R^2 mul(H, H, U2); // H = H^3 mul(U2, U2, X1); // U2 = X1*H^2 mul(Y3, H, Y1); // T = Y1*H^3 mul2(X3, U2); // X3 = 2*X1*H^2 sub(X3, S2, X3); // X3 = R^2 - 2*X1*H^2 sub(X3, X3, H); // X3 = R^2 - 2*X1*H^2 -H^3 sub(U2, U2, X3); // U2 = X1*H^2 - X3 mul(U2, U2, R); // U2 = R*(X1*H^2 - X3) sub(Y3, U2, Y3); // Y3 = -Y1*H^3 + R*(X1*H^2 - X3) /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FE521_)(X3, X3, p_at_infinity, q->x); MB_FUNC_NAME(mask_mov_FE521_)(Y3, Y3, p_at_infinity, q->y); MB_FUNC_NAME(mask_mov_FE521_)(Z3, Z3, p_at_infinity, (U64*)p521_r_mb); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FE521_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FE521_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FE521_)(Z3, Z3, q_at_infinity, p->Z); /* r = T */ MB_FUNC_NAME(mov_FE521_)(r->X, X3); MB_FUNC_NAME(mov_FE521_)(r->Y, Y3); MB_FUNC_NAME(mov_FE521_)(r->Z, Z3); } void MB_FUNC_NAME(get_nistp521_ec_affine_coords_)(U64 x[], U64 y[], const P521_POINT* P) { __ALIGN64 U64 invZ1[P521_LEN52]; __ALIGN64 U64 invZn[P521_LEN52]; /* 1/Z and 1/Z^2 */ MB_FUNC_NAME(ifma_aminv52_p521_)(invZ1, P->Z); MB_FUNC_NAME(ifma_ams52_p521_)(invZn, invZ1); /* if affine P.x requested */ if(x) MB_FUNC_NAME(ifma_amm52_p521_)(x, P->X, invZn); /* if affine P.y requested */ if(y) { MB_FUNC_NAME(ifma_amm52_p521_)(invZn, invZn, invZ1); MB_FUNC_NAME(ifma_amm52_p521_)(y, P->Y, invZn); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static __NOINLINE void clear_secret_context(U64* wval, U64* dval, __mb_mask* dsign) { *wval = get_zero64(); *dval = get_zero64(); *dsign = 0; return; } #define WIN_SIZE (4) /* s = (Ipp8u)(~((wvalue >> ws) - 1)); //sign d = (1 << (ws+1)) - wvalue - 1; // digit, win size "ws" d = (d & s) | (wvaluen & ~s); d = (d >> 1) + (d & 1); *sign = s & 1; *digit = (Ipp8u)d; */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract point */ static void MB_FUNC_NAME(extract_point_)(P521_POINT* r, const P521_POINT tbl[], U64 idx) { /* decrenent index (the table does not contain [0]*P */ U64 idx_target = sub64(idx, set1(1)); /* assume the point at infinity is what need */ P521_POINT R; MB_FUNC_NAME(set_point_to_infinity_)(&R); /* find out what we actually need or just keep original infinity */ int32u n; for(n=0; n<(1<<(WIN_SIZE-1)); n++) { U64 idx_curr = set1(n); __mb_mask k = cmp64_mask(idx_curr, idx_target, _MM_CMPINT_EQ); /* R = k? tbl[] : R */ MB_FUNC_NAME(secure_mask_mov_FE521_)(R.X, R.X, k, tbl[n].X); MB_FUNC_NAME(secure_mask_mov_FE521_)(R.Y, R.Y, k, tbl[n].Y); MB_FUNC_NAME(secure_mask_mov_FE521_)(R.Z, R.Z, k, tbl[n].Z); } MB_FUNC_NAME(mov_FE521_)(r->X, R.X); MB_FUNC_NAME(mov_FE521_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE521_)(r->Z, R.Z); } void MB_FUNC_NAME(ifma_ec_nistp521_mul_point_)(P521_POINT* r, const P521_POINT* p, const U64 scalar[]) { /* pre-computed table */ __ALIGN64 P521_POINT tbl[1<<(WIN_SIZE-1)]; /* // compute tbl[] = [n]P, n=1,..,2^(WIN_SIZE-1): // // tbl[2*n] = tbl[2*n-1]+p // tbl[2*n+1] = [2]*tbl[n] */ /* tbl[0] = p */ MB_FUNC_NAME(mov_FE521_)(tbl[0].X, p->X); MB_FUNC_NAME(mov_FE521_)(tbl[0].Y, p->Y); MB_FUNC_NAME(mov_FE521_)(tbl[0].Z, p->Z); /* tbl[1] = [2]*p */ MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&tbl[1], p); int n; for(n=1; n < (1<<(WIN_SIZE-1))/2; n++) { MB_FUNC_NAME(ifma_ec_nistp521_add_point_)(&tbl[2*n], &tbl[2*n-1], p); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&tbl[2*n+1], &tbl[n]); } P521_POINT R; P521_POINT T; U64 Ty[P521_LEN52]; /* // point (LR) multiplication */ U64 idx_mask = set1( (1<<(WIN_SIZE+1))-1 ); int bit = P521_BITSIZE-(P521_BITSIZE % WIN_SIZE); int chunk_no = (bit-1)/64; int chunk_shift = (bit-1)%64; /* first window */ U64 wvalue = loadu64(&scalar[chunk_no]); wvalue = and64( srli64(wvalue, chunk_shift), idx_mask); U64 dvalue; __mb_mask dsign; MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&R, tbl, dvalue); for(bit-=WIN_SIZE; bit>=WIN_SIZE; bit-=WIN_SIZE) { /* doubling */ MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); #endif /* extract precomputed []P */ chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); /* T = dsign? -T : T */ MB_FUNC_NAME(ifma_neg52_p521_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FE521_)(T.Y, T.Y, dsign, Ty); /* accumulate T */ MB_FUNC_NAME(ifma_ec_nistp521_add_point_)(&R, &R, &T); } /* last window */ MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_nistp521_dbl_point_)(&R, &R); #endif wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); MB_FUNC_NAME(ifma_neg52_p521_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FE521_)(T.Y, T.Y, dsign, Ty); MB_FUNC_NAME(ifma_ec_nistp521_add_point_)(&R, &R, &T); /* r = R */ MB_FUNC_NAME(mov_FE521_)(r->X, R.X); MB_FUNC_NAME(mov_FE521_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE521_)(r->Z, R.Z); /* clear r (to fix potential secutity flaw in case of ecdh */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef WIN_SIZE ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// #include #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE /* defined in the header above */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_bp_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, BP_WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(BP_WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract affine affine point */ __MBX_INLINE void MB_FUNC_NAME(extract_point_affine_)(P521_POINT_AFFINE* r, const SINGLE_P521_POINT_AFFINE* tbl, U64 idx) { /* decrement index (the table does not contain [0]*P */ U64 targIdx = sub64(idx, set1(1)); U64 ax0, ax1, ax2, ax3, ax4, ax5, ax6, ax7, ax8, ax9, ax10; U64 ay0, ay1, ay2, ay3, ay4, ay5, ay6, ay7, ay8, ay9, ay10; /* assume the point at infinity is what need */ ax0 = ax1 = ax2 = ax3 = ax4 = ax5 = ax6 = ax7 = ax8 = ax9 = ax10 = ay0 = ay1 = ay2 = ay3 = ay4 = ay5 = ay6 = ay7 = ay8 = ay9 = ay10 = get_zero64(); /* find out what we actually need or just keep original infinity */ int n; U64 currIdx = get_zero64(); for(n=0; n<(1<<(BP_WIN_SIZE-1)); n++, tbl++, currIdx = add64(currIdx, set1(1))) { __mb_mask k = cmp64_mask(currIdx, targIdx, _MM_CMPINT_EQ); /* R = k? set1( tbl[] ) : R */ ax0 = mask_add64(ax0, k, ax0, set1( tbl->x[0] )); ax1 = mask_add64(ax1, k, ax1, set1( tbl->x[1] )); ax2 = mask_add64(ax2, k, ax2, set1( tbl->x[2] )); ax3 = mask_add64(ax3, k, ax3, set1( tbl->x[3] )); ax4 = mask_add64(ax4, k, ax4, set1( tbl->x[4] )); ax5 = mask_add64(ax5, k, ax5, set1( tbl->x[5] )); ax6 = mask_add64(ax6, k, ax6, set1( tbl->x[6] )); ax7 = mask_add64(ax7, k, ax7, set1( tbl->x[7] )); ax8 = mask_add64(ax8, k, ax8, set1( tbl->x[8] )); ax9 = mask_add64(ax9, k, ax9, set1( tbl->x[9] )); ax10= mask_add64(ax10,k, ax10,set1( tbl->x[10])); ay0 = mask_add64(ay0, k, ay0, set1( tbl->y[0] )); ay1 = mask_add64(ay1, k, ay1, set1( tbl->y[1] )); ay2 = mask_add64(ay2, k, ay2, set1( tbl->y[2] )); ay3 = mask_add64(ay3, k, ay3, set1( tbl->y[3] )); ay4 = mask_add64(ay4, k, ay4, set1( tbl->y[4] )); ay5 = mask_add64(ay5, k, ay5, set1( tbl->y[5] )); ay6 = mask_add64(ay6, k, ay6, set1( tbl->y[6] )); ay7 = mask_add64(ay7, k, ay7, set1( tbl->y[7] )); ay8 = mask_add64(ay8, k, ay8, set1( tbl->y[8] )); ay9 = mask_add64(ay9, k, ay9, set1( tbl->y[9] )); ay10= mask_add64(ay10,k, ay10,set1( tbl->y[10])); } r->x[0] = ax0; r->x[1] = ax1; r->x[2] = ax2; r->x[3] = ax3; r->x[4] = ax4; r->x[5] = ax5; r->x[6] = ax6; r->x[7] = ax7; r->x[8] = ax8; r->x[9] = ax9; r->x[10]= ax10; r->y[0] = ay0; r->y[1] = ay1; r->y[2] = ay2; r->y[3] = ay3; r->y[4] = ay4; r->y[5] = ay5; r->y[6] = ay6; r->y[7] = ay7; r->y[8] = ay8; r->y[9] = ay9; r->y[10]= ay10; } void MB_FUNC_NAME(ifma_ec_nistp521_mul_pointbase_)(P521_POINT* r, const U64 scalar[]) { /* pre-computed table of base powers */ SINGLE_P521_POINT_AFFINE* tbl = &ifma_ec_nistp521_bp_precomp[0][0]; P521_POINT R; P521_POINT_AFFINE A; U64 Ty[P521_LEN52]; /* R = O */ MB_FUNC_NAME(set_point_to_infinity_)(&R); /* // base point (RL) multiplication */ U64 wvalue, dvalue; __mb_mask dsign; U64 idx_mask = set1( (1<<(BP_WIN_SIZE+1))-1 ); int bit = 0; /* first window - window[0] */ wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_p521_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FE521_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_nistp521_add_point_affine_)(&R, &R, &A); int chunk_no; int chunk_shift; for(bit+=BP_WIN_SIZE; bit<=P521_BITSIZE; bit+=BP_WIN_SIZE) { chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_p521_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FE521_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_nistp521_add_point_affine_)(&R, &R, &A); } /* r = R */ MB_FUNC_NAME(mov_FE521_)(r->X, R.X); MB_FUNC_NAME(mov_FE521_)(r->Y, R.Y); MB_FUNC_NAME(mov_FE521_)(r->Z, R.Z); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef BP_WIN_SIZE /* P521 parameters: mont(a), mont(b) */ __ALIGN64 int64u mont_a_p521_mb[P521_LEN52][8] = { { REP8_DECL(0x0007ffffffffffff) }, { REP8_DECL(0x000ffffffffffffe) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000000000000001) } }; __ALIGN64 int64u mont_b_p521_mb[P521_LEN52][8] = { { REP8_DECL(0x00014654fae58638) }, { REP8_DECL(0x00028fea35a81f80) }, { REP8_DECL(0x000c41e961a78f7a) }, { REP8_DECL(0x000dd8df839ab9ef) }, { REP8_DECL(0x00049bd8b29605e9) }, { REP8_DECL(0x0000ab0c9ca8f63f) }, { REP8_DECL(0x0005a44c8c77884f) }, { REP8_DECL(0x00092dccd98af9dc) }, { REP8_DECL(0x0005b42a077516d3) }, { REP8_DECL(0x000e4d0fc94d10d0) }, { REP8_DECL(0x0000000000000000) } }; /* // We have a curve defined by a Weierstrass equation: y^2 = x^3 + a*x + b. // // The points are considered in Jacobian projective coordinates // where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). // Substituting this and multiplying by Z^6 transforms the above equation into // Y^2 = X^3 + a*X*Z^4 + b*Z^6 // To test this, we add up the right-hand side in 'rh'. */ __mb_mask MB_FUNC_NAME(ifma_is_on_curve_p521_)(const P521_POINT* p, int use_jproj_coords) { U64 rh[P521_LEN52]; U64 Z4[P521_LEN52], Z6[P521_LEN52], tmp[P521_LEN52]; /* rh := X^2 */ MB_FUNC_NAME(ifma_ams52_p521_)(rh, p->X); /* if Z!=1, then rh = X^3 + a*X*Z^4 + b*Z^6 = X*(X^2 + a*X*Z^4) + b*Z^6 */ if(use_jproj_coords) { MB_FUNC_NAME(ifma_ams52_p521_)(tmp, p->Z); /* tmp = Z^2 */ MB_FUNC_NAME(ifma_ams52_p521_)(Z4, tmp); /* Z4 = Z^4 */ MB_FUNC_NAME(ifma_amm52_p521_)(Z6, Z4, tmp); /* Z6 = Z^6 */ MB_FUNC_NAME(ifma_add52_p521_)(tmp, Z4, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_add52_p521_)(tmp, tmp, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_sub52_p521_)(rh, rh, tmp); /* rh = X^2 + a*Z^4 */ MB_FUNC_NAME(ifma_amm52_p521_)(rh, rh, p->X); /* rh = (X^2 + a*Z^4)*X */ MB_FUNC_NAME(ifma_amm52_p521_)(tmp, Z6, (U64*)mont_b_p521_mb); MB_FUNC_NAME(ifma_add52_p521_)(rh, rh, tmp); /* rh = (X^2 + a*Z^4)*X + b*Z^6 */ } /* if Z==1, then rh = X^3 + a*X + b = X*(X^2 +a) b */ else { MB_FUNC_NAME(ifma_add52_p521_)(rh, rh, (U64*)mont_a_p521_mb); /* rh = X^2+a */ MB_FUNC_NAME(ifma_amm52_p521_)(rh, rh, p->X); /* rh = (X^2+a)*X */ MB_FUNC_NAME(ifma_add52_p521_)(rh, rh, (U64*)mont_b_p521_mb); /* rh = (X^2+a)*X + b */ } MB_FUNC_NAME(ifma_frommont52_p521_)(rh, rh); /* rl = tmp = Y^2 */ MB_FUNC_NAME(ifma_ams52_p521_)(tmp, p->Y); MB_FUNC_NAME(ifma_frommont52_p521_)(tmp, tmp); /* mask = rl==rh */ __mb_mask is_on_curve_mask = MB_FUNC_NAME(cmp_eq_FE521_)(tmp, rh); return is_on_curve_mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecpubkey_p256.c000066400000000000000000000111401470420105600310230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates (or NULL, if affine coordinate requested) // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key depends on pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates if pa_pubz[] != NULL // or // - in (x:y) affine coordinate if pa_pubz[] == NULL */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecpublic_key_ssl_mb8)(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { BIGNUM* out_x = pa_pubx[buf_no]; BIGNUM* out_y = pa_puby[buf_no]; BIGNUM* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const BIGNUM* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecpublic_key_ssl_mb8(pa_pubx,pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp256_ecpublic_key_mb8)(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int64u* out_x = pa_pubx[buf_no]; int64u* out_y = pa_puby[buf_no]; int64u* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const int64u* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp256_ecpublic_key_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecpubkey_p384.c000066400000000000000000000111421470420105600310270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates (or NULL, if affine coordinate requested) // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key depends on pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates if pa_pubz[] != NULL // or // - in (x:y) affine coordinate if pa_pubz[] == NULL */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecpublic_key_ssl_mb8)(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { BIGNUM* out_x = pa_pubx[buf_no]; BIGNUM* out_y = pa_puby[buf_no]; BIGNUM* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const BIGNUM* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecpublic_key_ssl_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp384_ecpublic_key_mb8)(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int64u* out_x = pa_pubx[buf_no]; int64u* out_y = pa_puby[buf_no]; int64u* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const int64u* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp384_ecpublic_key_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/ifma_ecpubkey_p521.c000066400000000000000000000111411470420105600310170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates (or NULL, if affine coordinate requested) // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key depends on pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates if pa_pubz[] != NULL // or // - in (x:y) affine coordinate if pa_pubz[] == NULL */ DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecpublic_key_ssl_mb8)(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { BIGNUM* out_x = pa_pubx[buf_no]; BIGNUM* out_y = pa_puby[buf_no]; BIGNUM* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const BIGNUM* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecpublic_key_ssl_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_nistp521_ecpublic_key_mb8)(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int64u* out_x = pa_pubx[buf_no]; int64u* out_y = pa_puby[buf_no]; int64u* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const int64u* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_nistp521_ecpublic_key_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/000077500000000000000000000000001470420105600302255ustar00rootroot00000000000000internal_ecdsa_p256.c000066400000000000000000000652341470420105600340530ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // common functions */ /* // compute secret key inversion // // inv_skey 1/skey mod n256 // // note: pay attention on skey[] presenttaion // it should be FE element of N256 basef GF */ static void nistp256_ecdsa_inv_keys_mb8(U64 inv_skey[], const U64 skey[], int8u pBuffer[]) { /* compute inversion ober n256 of secret keys */ MB_FUNC_NAME(ifma_tomont52_n256_)(inv_skey, skey); ifma_aminv52_n256_mb8(inv_skey, inv_skey); /* 1/skeys mod n256 */ MB_FUNC_NAME(ifma_frommont52_n256_)(inv_skey, inv_skey); } /* // compute r-component of the ECDSA signature // // r = ([skey]*G).x mod n256 // // note: pay attention on skey[] presenttaion // it should be transposed and zero expanded */ static __mb_mask nistp256_ecdsa_sign_r_mb8(U64 sign_r[], const U64 skey[], int8u pBuffer[]) { /* compute ephemeral public keys */ P256_POINT P; MB_FUNC_NAME(ifma_ec_nistp256_mul_pointbase_)(&P, skey); /* extract affine P.x */ MB_FUNC_NAME(ifma_aminv52_p256_)(P.Z, P.Z); /* 1/Z */ MB_FUNC_NAME(ifma_ams52_p256_)(P.Z, P.Z); /* 1/Z^2 */ MB_FUNC_NAME(ifma_amm52_p256_)(P.X, P.X, P.Z); /* x = (X) * (1/Z^2) */ /* convert x-coordinate to regular and then tp Montgomery n256 */ MB_FUNC_NAME(ifma_frommont52_p256_)(P.X, P.X); MB_FUNC_NAME(ifma_fastred52_pn256_)(sign_r, P.X); /* fast reduction p => n */ return MB_FUNC_NAME(is_zero_FE256_)(sign_r); } /* // compute s-component of the ECDSA signature // // s = (inv_eph) * (msg + prv_skey*sign_r) mod n256 */ static __mb_mask nistp256_ecdsa_sign_s_mb8(U64 sign_s[], U64 msg[], const U64 sign_r[], U64 inv_eph_skey[], U64 reg_skey[], int8u pBuffer[]) { __ALIGN64 U64 tmp[P256_LEN52]; /* convert to Montgomery over n256 domain */ MB_FUNC_NAME(ifma_tomont52_n256_)(inv_eph_skey, inv_eph_skey); MB_FUNC_NAME(ifma_tomont52_n256_)(tmp, sign_r); MB_FUNC_NAME(ifma_tomont52_n256_)(msg, msg); MB_FUNC_NAME(ifma_tomont52_n256_)(reg_skey, reg_skey); /* s = (inv_eph) * (msg + prv_skey*sign_r) mod n256 */ MB_FUNC_NAME(ifma_amm52_n256_)(sign_s, reg_skey, tmp); MB_FUNC_NAME(ifma_add52_n256_)(sign_s, sign_s, msg); MB_FUNC_NAME(ifma_amm52_n256_)(sign_s, sign_s, inv_eph_skey); MB_FUNC_NAME(ifma_frommont52_n256_)(sign_s, sign_s); return MB_FUNC_NAME(is_zero_FE256_)(sign_s); } /* // ECDSA signature verification algorithm */ static __mb_mask nistp256_ecdsa_verify_mb8(U64 sign_r[], U64 sign_s[], U64 msg[], P256_POINT* W) { /* convert public key coords to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p256_)(W->X, W->X); MB_FUNC_NAME(ifma_tomont52_p256_)(W->Y, W->Y); MB_FUNC_NAME(ifma_tomont52_p256_)(W->Z, W->Z); __ALIGN64 U64 h1[P256_LEN52]; __ALIGN64 U64 h2[P256_LEN52]; /* h = (sign_s)^(-1) */ MB_FUNC_NAME(ifma_tomont52_n256_)(sign_s, sign_s); MB_FUNC_NAME(ifma_aminv52_n256_)(sign_s, sign_s); /* h1 = msg * h */ MB_FUNC_NAME(ifma_tomont52_n256_)(h1, msg); MB_FUNC_NAME(ifma_amm52_n256_)(h1, h1, sign_s); MB_FUNC_NAME(ifma_frommont52_n256_)(h1, h1); /* h2 = sign_r * h */ MB_FUNC_NAME(ifma_tomont52_n256_)(h2, sign_r); MB_FUNC_NAME(ifma_amm52_n256_)(h2, h2, sign_s); MB_FUNC_NAME(ifma_frommont52_n256_)(h2, h2); int64u tmp[8][P256_LEN64]; int64u* pa_tmp[8] = { tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7] }; ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])h1, P256_BITSIZE); ifma_BNU_transpose_copy((int64u(*)[8])h1, (const int64u(**))pa_tmp, P256_BITSIZE); ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])h2, P256_BITSIZE); ifma_BNU_transpose_copy((int64u(*)[8])h2, (const int64u(**))pa_tmp, P256_BITSIZE); h1[P256_LEN64] = get_zero64(); h2[P256_LEN64] = get_zero64(); P256_POINT P; // P = h1*G + h2*W MB_FUNC_NAME(ifma_ec_nistp256_mul_point_)(W, W, h2); MB_FUNC_NAME(ifma_ec_nistp256_mul_pointbase_)(&P, h1); MB_FUNC_NAME(ifma_ec_nistp256_add_point_)(&P, &P, W); // P != 0 __mb_mask signature_err_mask = MB_FUNC_NAME(is_zero_point_cordinate_)(P.Z); /* sign_r_restored = P.X mod n */ __ALIGN64 U64 sign_r_restored[P256_LEN52]; MB_FUNC_NAME(get_nistp256_ec_affine_coords_)(sign_r_restored, NULL, &P); MB_FUNC_NAME(ifma_frommont52_p256_)(sign_r_restored, sign_r_restored); MB_FUNC_NAME(ifma_fastred52_pn256_)(sign_r_restored, sign_r_restored); /* sign_r_restored != sign_r */ signature_err_mask |= ~(MB_FUNC_NAME(cmp_eq_FE256_)(sign_r_restored, sign_r)); return signature_err_mask; } mbx_status internal_avx512_nistp256_ecdsa_sign_setup_mb8(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; /* convert keys into FE and compute inversion */ U64 T[P256_LEN52]; ifma_BNU_to_mb8((int64u (*)[8])T, pa_eph_skey, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE256_)(T), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear key's inversion */ MB_FUNC_NAME(zero_)((int64u (*)[8])T, sizeof(T)/sizeof(U64)); return status; } nistp256_ecdsa_inv_keys_mb8(T, T, 0); /* return results in suitable format */ ifma_mb8_to_BNU(pa_inv_eph_skey, (const int64u(*)[8])T, P256_BITSIZE); /* clear key's inversion */ MB_FUNC_NAME(zero_)((int64u (*)[8])T, sizeof(T)/sizeof(U64)); /* convert keys into scalars */ U64 scalarz[P256_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_eph_skey, P256_BITSIZE); scalarz[P256_LEN64] = get_zero64(); /* compute r-component of the DSA signature */ int8u stt_mask = nistp256_ecdsa_sign_r_mb8(T, scalarz, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); /* return results in suitable format */ ifma_mb8_to_BNU(pa_sign_rp, (const int64u(*)[8])T, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp256_ecdsa_sign_complete_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; __ALIGN64 U64 inv_eph[P256_LEN52]; __ALIGN64 U64 reg_skey[P256_LEN52]; __ALIGN64 U64 sign_r[P256_LEN52]; __ALIGN64 U64 sign_s[P256_LEN52]; __ALIGN64 U64 msg[P256_LEN52]; /* convert inv_eph, reg_skey, sign_r and message to mb format */ ifma_BNU_to_mb8((int64u (*)[8])inv_eph, pa_inv_eph_skey, P256_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])reg_skey, pa_reg_skey, P256_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])sign_r, pa_sign_rp, P256_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE256_)(inv_eph), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE256_)(reg_skey), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE256_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n256_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph, sizeof(inv_eph)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); return status; } /* compute s- signature component: s = (inv_eph) * (msg + prv_skey*sign_r) mod n256 */ nistp256_ecdsa_sign_s_mb8(sign_s, msg, sign_r, inv_eph, reg_skey, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph, sizeof(inv_eph)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); /* check if sign_r!=0 and sign_s!=0 */ int8u stt_mask_r = MB_FUNC_NAME(is_zero_FE256_)(sign_r); int8u stt_mask_s = MB_FUNC_NAME(is_zero_FE256_)(sign_s); /* convert sign_r and sing_s to strings */ ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, P256_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask_r, MBX_STATUS_SIGNATURE_ERR); status |= MBX_SET_STS_BY_MASK(status, stt_mask_s, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp256_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; __ALIGN64 U64 inv_eph_key[P256_LEN52]; __ALIGN64 U64 reg_key[P256_LEN52]; __ALIGN64 U64 sign_r[P256_LEN52]; __ALIGN64 U64 sign_s[P256_LEN52]; __ALIGN64 U64 scalar[P256_LEN64+1]; __ALIGN64 U64 msg[P256_LEN52]; /* convert ephemeral keys into FE */ ifma_BNU_to_mb8((int64u (*)[8])inv_eph_key, pa_eph_skey, P256_BITSIZE); /* convert epphemeral keys into scalar */ ifma_BNU_transpose_copy((int64u (*)[8])scalar, pa_eph_skey, P256_BITSIZE); scalar[P256_LEN64] = get_zero64(); /* convert reg_skey */ ifma_BNU_to_mb8((int64u (*)[8])reg_key, pa_reg_skey, P256_BITSIZE); /* convert message */ ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE256_)(inv_eph_key), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE256_)(reg_key), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n256_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph_key, sizeof(inv_eph_key)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])scalar, sizeof(scalar)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_key, sizeof(reg_key)/sizeof(U64)); return status; } /* compute inversion */ nistp256_ecdsa_inv_keys_mb8(inv_eph_key, inv_eph_key, pBuffer); /* compute r-component */ nistp256_ecdsa_sign_r_mb8(sign_r, scalar, pBuffer); /* compute s-component */ nistp256_ecdsa_sign_s_mb8(sign_s, msg, sign_r, inv_eph_key, reg_key, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph_key, sizeof(inv_eph_key)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])scalar, sizeof(scalar)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_key, sizeof(reg_key)/sizeof(U64)); /* check if sign_r!=0 and sign_s!=0 */ int8u stt_mask_r = MB_FUNC_NAME(is_zero_FE256_)(sign_r); int8u stt_mask_s = MB_FUNC_NAME(is_zero_FE256_)(sign_s); /* convert signature components to strings */ ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, P256_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask_r, MBX_STATUS_SIGNATURE_ERR); status |= MBX_SET_STS_BY_MASK(status, stt_mask_s, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp256_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; __ALIGN64 U64 msg[P256_LEN52]; __ALIGN64 U64 sign_r[P256_LEN52]; __ALIGN64 U64 sign_s[P256_LEN52]; /* convert input params */ ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P256_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])sign_r, pa_sign_r, P256_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])sign_s, pa_sign_s, P256_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n256_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n256_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n256_)(sign_s), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) return status; P256_POINT W; ifma_BNU_to_mb8((int64u (*)[8])W.X, (const int64u* (*))pa_pubx, P256_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])W.Y, (const int64u* (*))pa_puby, P256_BITSIZE); if(use_jproj_coords) ifma_BNU_to_mb8((int64u (*)[8])W.Z, (const int64u* (*))pa_pubz, P256_BITSIZE); else MB_FUNC_NAME(mov_FE256_)(W.Z, (U64*)ones); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p256_)(W.X), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p256_)(W.Y), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p256_)(W.Z), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) return status; __mb_mask signature_err_mask = nistp256_ecdsa_verify_mb8(sign_r,sign_s,msg, &W); status |= MBX_SET_STS_BY_MASK(status, signature_err_mask, MBX_STATUS_SIGNATURE_ERR); return status; } /* // OpenSSL's specific implementations */ #ifndef BN_OPENSSL_DISABLE static void reverse_inplace(int8u* inpout, int len) { int mudpoint = len/2; for(int n=0; n=_MBX_K1) */ internal_ecdsa_p384.c000066400000000000000000000651551470420105600340570ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // common functions */ /* // compute secret key inversion // // inv_skey 1/skey mod n384 // // note: pay attention on skey[] presenttaion // it should be FE element of N384 basef GF */ static void nistp384_ecdsa_inv_keys_mb8(U64 inv_skey[], const U64 skey[], int8u pBuffer[]) { /* compute inversion ober n384 of secret keys */ MB_FUNC_NAME(ifma_tomont52_n384_)(inv_skey, skey); ifma_aminv52_n384_mb8(inv_skey, inv_skey); /* 1/skeys mod n384 */ MB_FUNC_NAME(ifma_frommont52_n384_)(inv_skey, inv_skey); } /* // compute r-component of the ECDSA signature // // r = ([skey]*G).x mod n384 // // note: pay attention on skey[] presenttaion // it should be transposed and zero expanded */ static __mb_mask nistp384_ecdsa_sign_r_mb8(U64 sign_r[], const U64 skey[], int8u pBuffer[]) { /* compute ephemeral public keys */ P384_POINT P; MB_FUNC_NAME(ifma_ec_nistp384_mul_pointbase_)(&P, skey); /* extract affine P.x */ MB_FUNC_NAME(ifma_aminv52_p384_)(P.Z, P.Z); /* 1/Z */ MB_FUNC_NAME(ifma_ams52_p384_)(P.Z, P.Z); /* 1/Z^2 */ MB_FUNC_NAME(ifma_amm52_p384_)(P.X, P.X, P.Z); /* x = (X) * (1/Z^2) */ /* convert x-coordinate to regular and then tp Montgomery n384 */ MB_FUNC_NAME(ifma_frommont52_p384_)(P.X, P.X); MB_FUNC_NAME(ifma_fastred52_pn384_)(sign_r, P.X); /* fast reduction p => n */ return MB_FUNC_NAME(is_zero_FE384_)(sign_r); } /* // compute s-component of the ECDSA signature // // s = (inv_eph) * (msg + prv_skey*sign_r) mod n384 */ static __mb_mask nistp384_ecdsa_sign_s_mb8(U64 sign_s[], U64 msg[], const U64 sign_r[], U64 inv_eph_skey[], U64 reg_skey[], int8u pBuffer[]) { __ALIGN64 U64 tmp[P384_LEN52]; /* convert to Montgomery over n384 domain */ MB_FUNC_NAME(ifma_tomont52_n384_)(inv_eph_skey, inv_eph_skey); MB_FUNC_NAME(ifma_tomont52_n384_)(tmp, sign_r); MB_FUNC_NAME(ifma_tomont52_n384_)(msg, msg); MB_FUNC_NAME(ifma_tomont52_n384_)(reg_skey, reg_skey); /* s = (inv_eph) * (msg + prv_skey*sign_r) mod n384 */ MB_FUNC_NAME(ifma_amm52_n384_)(sign_s, reg_skey, tmp); MB_FUNC_NAME(ifma_add52_n384_)(sign_s, sign_s, msg); MB_FUNC_NAME(ifma_amm52_n384_)(sign_s, sign_s, inv_eph_skey); MB_FUNC_NAME(ifma_frommont52_n384_)(sign_s, sign_s); return MB_FUNC_NAME(is_zero_FE384_)(sign_s); } /* // ECDSA signature verification algorithm */ static __mb_mask nistp384_ecdsa_verify_mb8(U64 sign_r[], U64 sign_s[], U64 msg[], P384_POINT* W) { /* convert public key coords to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p384_)(W->X, W->X); MB_FUNC_NAME(ifma_tomont52_p384_)(W->Y, W->Y); MB_FUNC_NAME(ifma_tomont52_p384_)(W->Z, W->Z); __ALIGN64 U64 h1[P384_LEN52]; __ALIGN64 U64 h2[P384_LEN52]; /* h = (sign_s)^(-1) */ MB_FUNC_NAME(ifma_tomont52_n384_)(sign_s, sign_s); MB_FUNC_NAME(ifma_aminv52_n384_)(sign_s, sign_s); /* h1 = msg * h */ MB_FUNC_NAME(ifma_tomont52_n384_)(h1, msg); MB_FUNC_NAME(ifma_amm52_n384_)(h1, h1, sign_s); MB_FUNC_NAME(ifma_frommont52_n384_)(h1, h1); /* h2 = sign_r * h */ MB_FUNC_NAME(ifma_tomont52_n384_)(h2, sign_r); MB_FUNC_NAME(ifma_amm52_n384_)(h2, h2, sign_s); MB_FUNC_NAME(ifma_frommont52_n384_)(h2, h2); int64u tmp[8][P384_LEN64]; int64u* pa_tmp[8] = { tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7] }; ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])h1, P384_BITSIZE); ifma_BNU_transpose_copy((int64u(*)[8])h1, (const int64u(**))pa_tmp, P384_BITSIZE); ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])h2, P384_BITSIZE); ifma_BNU_transpose_copy((int64u(*)[8])h2, (const int64u(**))pa_tmp, P384_BITSIZE); h1[P384_LEN64] = get_zero64(); h2[P384_LEN64] = get_zero64(); P384_POINT P; // P = h1*G + h2*W MB_FUNC_NAME(ifma_ec_nistp384_mul_point_)(W, W, h2); MB_FUNC_NAME(ifma_ec_nistp384_mul_pointbase_)(&P, h1); MB_FUNC_NAME(ifma_ec_nistp384_add_point_)(&P, &P, W); // P != 0 __mb_mask signature_err_mask = MB_FUNC_NAME(is_zero_point_cordinate_)(P.Z); /* sign_r_restored = P.X mod n */ __ALIGN64 U64 sign_r_restored[P384_LEN52]; MB_FUNC_NAME(get_nistp384_ec_affine_coords_)(sign_r_restored, NULL, &P); MB_FUNC_NAME(ifma_frommont52_p384_)(sign_r_restored, sign_r_restored); MB_FUNC_NAME(ifma_fastred52_pn384_)(sign_r_restored, sign_r_restored); /* sign_r_restored != sign_r */ signature_err_mask |= ~(MB_FUNC_NAME(cmp_eq_FE384_)(sign_r_restored, sign_r)); return signature_err_mask; } mbx_status internal_avx512_nistp384_ecdsa_sign_setup_mb8(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; /* convert keys into FE and compute inversion */ U64 T[P384_LEN52]; ifma_BNU_to_mb8((int64u (*)[8])T, pa_eph_skey, P384_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE384_)(T), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear key's inversion */ MB_FUNC_NAME(zero_)((int64u (*)[8])T, sizeof(T)/sizeof(U64)); return status; } nistp384_ecdsa_inv_keys_mb8(T, T, 0); /* return results in suitable format */ ifma_mb8_to_BNU(pa_inv_eph_skey, (const int64u(*)[8])T, P384_BITSIZE); /* clear key's inversion */ MB_FUNC_NAME(zero_)((int64u (*)[8])T, sizeof(T)/sizeof(U64)); /* convert keys into scalars */ U64 scalarz[P384_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_eph_skey, P384_BITSIZE); scalarz[P384_LEN64] = get_zero64(); /* compute r-component of the DSA signature */ int8u stt_mask = nistp384_ecdsa_sign_r_mb8(T, scalarz, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); /* return results in suitable format */ ifma_mb8_to_BNU(pa_sign_rp, (const int64u(*)[8])T, P384_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp384_ecdsa_sign_complete_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; __ALIGN64 U64 inv_eph[P384_LEN52]; __ALIGN64 U64 reg_skey[P384_LEN52]; __ALIGN64 U64 sign_r[P384_LEN52]; __ALIGN64 U64 sign_s[P384_LEN52]; __ALIGN64 U64 msg[P384_LEN52]; /* convert inv_eph, reg_skey, sign_r and message to mb format */ ifma_BNU_to_mb8((int64u (*)[8])inv_eph, pa_inv_eph_skey, P384_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])reg_skey, pa_reg_skey, P384_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])sign_r, pa_sign_rp, P384_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P384_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE384_)(inv_eph), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE384_)(reg_skey), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE384_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n384_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph, sizeof(inv_eph)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); return status; } /* compute s- signature component: s = (inv_eph) * (msg + prv_skey*sign_r) mod n384 */ nistp384_ecdsa_sign_s_mb8(sign_s, msg, sign_r, inv_eph, reg_skey, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph, sizeof(inv_eph)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); /* check if sign_r!=0 and sign_s!=0 */ int8u stt_mask_r = MB_FUNC_NAME(is_zero_FE384_)(sign_r); int8u stt_mask_s = MB_FUNC_NAME(is_zero_FE384_)(sign_s); /* convert sign_r and sing_s to strings */ ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, P384_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, P384_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask_r, MBX_STATUS_SIGNATURE_ERR); status |= MBX_SET_STS_BY_MASK(status, stt_mask_s, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp384_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; __ALIGN64 U64 inv_eph_key[P384_LEN52]; __ALIGN64 U64 reg_key[P384_LEN52]; __ALIGN64 U64 sign_r[P384_LEN52]; __ALIGN64 U64 sign_s[P384_LEN52]; __ALIGN64 U64 scalar[P384_LEN64+1]; __ALIGN64 U64 msg[P384_LEN52]; /* convert ephemeral keys into FE */ ifma_BNU_to_mb8((int64u (*)[8])inv_eph_key, pa_eph_skey, P384_BITSIZE); /* convert epphemeral keys into scalar */ ifma_BNU_transpose_copy((int64u (*)[8])scalar, pa_eph_skey, P384_BITSIZE); scalar[P384_LEN64] = get_zero64(); /* convert reg_skey*/ ifma_BNU_to_mb8((int64u (*)[8])reg_key, pa_reg_skey, P384_BITSIZE); /* convert message */ ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P384_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE384_)(inv_eph_key), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE384_)(reg_key), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n384_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph_key, sizeof(inv_eph_key)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])scalar, sizeof(scalar)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_key, sizeof(reg_key)/sizeof(U64)); return status; } /* compute inversion */ nistp384_ecdsa_inv_keys_mb8(inv_eph_key, inv_eph_key, pBuffer); /* compute r-component */ nistp384_ecdsa_sign_r_mb8(sign_r, scalar, pBuffer); /* compute s-component */ nistp384_ecdsa_sign_s_mb8(sign_s, msg, sign_r, inv_eph_key, reg_key, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph_key, sizeof(inv_eph_key)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])scalar, sizeof(scalar)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_key, sizeof(reg_key)/sizeof(U64)); /* check if sign_r!=0 and sign_s!=0 */ int8u stt_mask_r = MB_FUNC_NAME(is_zero_FE384_)(sign_r); int8u stt_mask_s = MB_FUNC_NAME(is_zero_FE384_)(sign_s); /* convert signature components to strings */ ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, P384_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, P384_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask_r, MBX_STATUS_SIGNATURE_ERR); status |= MBX_SET_STS_BY_MASK(status, stt_mask_s, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp384_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; __ALIGN64 U64 msg[P384_LEN52]; __ALIGN64 U64 sign_r[P384_LEN52]; __ALIGN64 U64 sign_s[P384_LEN52]; /* convert input params */ ifma_HexStr8_to_mb8((int64u(*)[8])msg, pa_msg, P384_BITSIZE); ifma_HexStr8_to_mb8((int64u(*)[8])sign_r, pa_sign_r, P384_BITSIZE); ifma_HexStr8_to_mb8((int64u(*)[8])sign_s, pa_sign_s, P384_BITSIZE); /* // check, that sign_r and sign_s is in [1, n – 1] // it's equivalent to sign_ != 0 (because it is unsigned value) and sign_ < n */ status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n384_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n384_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n384_)(sign_s), MBX_STATUS_MISMATCH_PARAM_ERR); if (!MBX_IS_ANY_OK_STS(status)) return status; P384_POINT W; ifma_BNU_to_mb8((int64u(*)[8])W.X, (const int64u* (*))pa_pubx, P384_BITSIZE); ifma_BNU_to_mb8((int64u(*)[8])W.Y, (const int64u* (*))pa_puby, P384_BITSIZE); if (use_jproj_coords) ifma_BNU_to_mb8((int64u(*)[8])W.Z, (const int64u* (*))pa_pubz, P384_BITSIZE); else MB_FUNC_NAME(mov_FE384_)(W.Z, (U64*)ones); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p384_)(W.X), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p384_)(W.Y), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p384_)(W.Z), MBX_STATUS_MISMATCH_PARAM_ERR); if (!MBX_IS_ANY_OK_STS(status)) return status; __mb_mask signature_err_mask = nistp384_ecdsa_verify_mb8(sign_r, sign_s, msg, &W); status |= MBX_SET_STS_BY_MASK(status, signature_err_mask, MBX_STATUS_SIGNATURE_ERR); return status; } /* // OpenSSL's specific implementations */ #ifndef BN_OPENSSL_DISABLE static void reverse_inplace(int8u* inpout, int len) { int mudpoint = len/2; for(int n=0; n=_MBX_K1) */ internal_ecdsa_p521.c000066400000000000000000000653421470420105600340460ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // common functions */ /* // compute secret key inversion // // inv_skey 1/skey mod n521 // // note: pay attention on skey[] presenttaion // it should be FE element of N521 basef GF */ static void nistp521_ecdsa_inv_keys_mb8(U64 inv_skey[], const U64 skey[], int8u pBuffer[]) { /* compute inversion ober n521 of secret keys */ MB_FUNC_NAME(ifma_tomont52_n521_)(inv_skey, skey); ifma_aminv52_n521_mb8(inv_skey, inv_skey); /* 1/skeys mod n521 */ MB_FUNC_NAME(ifma_frommont52_n521_)(inv_skey, inv_skey); } /* // compute r-component of the ECDSA signature // // r = ([skey]*G).x mod n521 // // note: pay attention on skey[] presenttaion // it should be transposed and zero expanded */ static __mb_mask nistp521_ecdsa_sign_r_mb8(U64 sign_r[], const U64 skey[], int8u pBuffer[]) { /* compute ephemeral public keys */ P521_POINT P; MB_FUNC_NAME(ifma_ec_nistp521_mul_pointbase_)(&P, skey); /* extract affine P.x */ MB_FUNC_NAME(ifma_aminv52_p521_)(P.Z, P.Z); /* 1/Z */ MB_FUNC_NAME(ifma_ams52_p521_)(P.Z, P.Z); /* 1/Z^2 */ MB_FUNC_NAME(ifma_amm52_p521_)(P.X, P.X, P.Z); /* x = (X) * (1/Z^2) */ /* convert x-coordinate to regular and then tp Montgomery n521 */ MB_FUNC_NAME(ifma_frommont52_p521_)(P.X, P.X); MB_FUNC_NAME(ifma_fastred52_pn521_)(sign_r, P.X); /* fast reduction p => n */ return MB_FUNC_NAME(is_zero_FE521_)(sign_r); } /* // compute s-component of the ECDSA signature // // s = (inv_eph) * (msg + prv_skey*sign_r) mod n521 */ static __mb_mask nistp521_ecdsa_sign_s_mb8(U64 sign_s[], U64 msg[], const U64 sign_r[], U64 inv_eph_skey[], U64 reg_skey[], int8u pBuffer[]) { __ALIGN64 U64 tmp[P521_LEN52]; /* convert to Montgomery over n521 domain */ MB_FUNC_NAME(ifma_tomont52_n521_)(inv_eph_skey, inv_eph_skey); MB_FUNC_NAME(ifma_tomont52_n521_)(tmp, sign_r); MB_FUNC_NAME(ifma_tomont52_n521_)(msg, msg); MB_FUNC_NAME(ifma_tomont52_n521_)(reg_skey, reg_skey); /* s = (inv_eph) * (msg + prv_skey*sign_r) mod n521 */ MB_FUNC_NAME(ifma_amm52_n521_)(sign_s, reg_skey, tmp); MB_FUNC_NAME(ifma_add52_n521_)(sign_s, sign_s, msg); MB_FUNC_NAME(ifma_amm52_n521_)(sign_s, sign_s, inv_eph_skey); MB_FUNC_NAME(ifma_frommont52_n521_)(sign_s, sign_s); return MB_FUNC_NAME(is_zero_FE521_)(sign_s); } /* // ECDSA signature verification algorithm */ static __mb_mask nistp521_ecdsa_verify_mb8(U64 sign_r[], U64 sign_s[], U64 msg[], P521_POINT* W) { /* convert public key coords to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p521_)(W->X, W->X); MB_FUNC_NAME(ifma_tomont52_p521_)(W->Y, W->Y); MB_FUNC_NAME(ifma_tomont52_p521_)(W->Z, W->Z); __ALIGN64 U64 h1[P521_LEN52]; __ALIGN64 U64 h2[P521_LEN52]; /* h = (sign_s)^(-1) */ MB_FUNC_NAME(ifma_tomont52_n521_)(sign_s, sign_s); MB_FUNC_NAME(ifma_aminv52_n521_)(sign_s, sign_s); /* h1 = msg * h */ MB_FUNC_NAME(ifma_tomont52_n521_)(h1, msg); MB_FUNC_NAME(ifma_amm52_n521_)(h1, h1, sign_s); MB_FUNC_NAME(ifma_frommont52_n521_)(h1,h1); /* h2 = sign_r * h */ MB_FUNC_NAME(ifma_tomont52_n521_)(h2, sign_r); MB_FUNC_NAME(ifma_amm52_n521_)(h2, h2, sign_s); MB_FUNC_NAME(ifma_frommont52_n521_)(h2,h2); int64u tmp[8][P521_LEN64]; int64u* pa_tmp[8] = {tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]}; ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])h1, P521_BITSIZE); ifma_BNU_transpose_copy((int64u (*)[8])h1, (const int64u(**))pa_tmp, P521_BITSIZE); ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])h2, P521_BITSIZE); ifma_BNU_transpose_copy((int64u (*)[8])h2, (const int64u(**))pa_tmp, P521_BITSIZE); h1[P521_LEN64] = get_zero64(); h2[P521_LEN64] = get_zero64(); P521_POINT P; // P = h1*G + h2*W MB_FUNC_NAME(ifma_ec_nistp521_mul_point_)(W, W, h2); MB_FUNC_NAME(ifma_ec_nistp521_mul_pointbase_)(&P, h1); MB_FUNC_NAME(ifma_ec_nistp521_add_point_)(&P, &P, W); // P != 0 __mb_mask signature_err_mask = MB_FUNC_NAME(is_zero_point_cordinate_)(P.Z); /* sign_r_restored = P.X mod n */ __ALIGN64 U64 sign_r_restored[P521_LEN52]; MB_FUNC_NAME(get_nistp521_ec_affine_coords_)(sign_r_restored, NULL, &P); MB_FUNC_NAME(ifma_frommont52_p521_)(sign_r_restored, sign_r_restored); MB_FUNC_NAME(ifma_fastred52_pn521_)(sign_r_restored, sign_r_restored); /* sign_r_restored != sign_r */ signature_err_mask |= ~(MB_FUNC_NAME(cmp_eq_FE521_)(sign_r_restored, sign_r)); return signature_err_mask; } mbx_status internal_avx512_nistp521_ecdsa_sign_setup_mb8(int64u* pa_inv_eph_skey[8], int64u* pa_sign_rp[8], const int64u* const pa_eph_skey[8], int8u* pBuffer) { mbx_status status = 0; /* convert keys into FE and compute inversion */ U64 T[P521_LEN52]; ifma_BNU_to_mb8((int64u (*)[8])T, pa_eph_skey, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE521_)(T), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear key's inversion */ MB_FUNC_NAME(zero_)((int64u (*)[8])T, sizeof(T)/sizeof(U64)); return status; } nistp521_ecdsa_inv_keys_mb8(T, T, 0); /* return results in suitable format */ ifma_mb8_to_BNU(pa_inv_eph_skey, (const int64u(*)[8])T, P521_BITSIZE); /* clear key's inversion */ MB_FUNC_NAME(zero_)((int64u (*)[8])T, sizeof(T)/sizeof(U64)); /* convert keys into scalars */ U64 scalarz[P521_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_eph_skey, P521_BITSIZE); scalarz[P521_LEN64] = get_zero64(); /* compute r-component of the DSA signature */ int8u stt_mask = nistp521_ecdsa_sign_r_mb8(T, scalarz, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); /* return results in suitable format */ ifma_mb8_to_BNU(pa_sign_rp, (const int64u(*)[8])T, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp521_ecdsa_sign_complete_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_sign_rp[8], const int64u* const pa_inv_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; __ALIGN64 U64 inv_eph[P521_LEN52]; __ALIGN64 U64 reg_skey[P521_LEN52]; __ALIGN64 U64 sign_r[P521_LEN52]; __ALIGN64 U64 sign_s[P521_LEN52]; __ALIGN64 U64 msg[P521_LEN52]; /* convert inv_eph, reg_skey, sign_r and message to mb format */ ifma_BNU_to_mb8((int64u (*)[8])inv_eph, pa_inv_eph_skey, P521_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])reg_skey, pa_reg_skey, P521_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])sign_r, pa_sign_rp, P521_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE521_)(inv_eph), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE521_)(reg_skey), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE521_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n521_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph, sizeof(inv_eph)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); return status; } /* compute s- signature component: s = (inv_eph) * (msg + prv_skey*sign_r) mod n521 */ nistp521_ecdsa_sign_s_mb8(sign_s, msg, sign_r, inv_eph, reg_skey, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph, sizeof(inv_eph)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); /* check if sign_r!=0 and sign_s!=0 */ int8u stt_mask_r = MB_FUNC_NAME(is_zero_FE521_)(sign_r); int8u stt_mask_s = MB_FUNC_NAME(is_zero_FE521_)(sign_s); /* convert sign_r and sing_s to strings */ ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, P521_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask_r, MBX_STATUS_SIGNATURE_ERR); status |= MBX_SET_STS_BY_MASK(status, stt_mask_s, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp521_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], int8u* pBuffer) { mbx_status status = 0; __ALIGN64 U64 inv_eph_key[P521_LEN52]; __ALIGN64 U64 reg_key[P521_LEN52]; __ALIGN64 U64 sign_r[P521_LEN52]; __ALIGN64 U64 sign_s[P521_LEN52]; __ALIGN64 U64 scalar[P521_LEN64+1]; __ALIGN64 U64 msg[P521_LEN52]; /* convert ephemeral keys into FE */ ifma_BNU_to_mb8((int64u (*)[8])inv_eph_key, pa_eph_skey, P521_BITSIZE); /* convert epphemeral keys into scalar */ ifma_BNU_transpose_copy((int64u (*)[8])scalar, pa_eph_skey, P521_BITSIZE); scalar[P521_LEN64] = get_zero64(); /* convert reg_skey*/ ifma_BNU_to_mb8((int64u (*)[8])reg_key, pa_reg_skey, P521_BITSIZE); /* convert message */ ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE521_)(inv_eph_key), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FE521_)(reg_key), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n521_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph_key, sizeof(inv_eph_key)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])scalar, sizeof(scalar)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_key, sizeof(reg_key)/sizeof(U64)); return status; } /* compute inversion */ nistp521_ecdsa_inv_keys_mb8(inv_eph_key, inv_eph_key, pBuffer); /* compute r-component */ nistp521_ecdsa_sign_r_mb8(sign_r, scalar, pBuffer); /* compute s-component */ nistp521_ecdsa_sign_s_mb8(sign_s, msg, sign_r, inv_eph_key, reg_key, pBuffer); /* clear copy of the ephemeral secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])inv_eph_key, sizeof(inv_eph_key)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])scalar, sizeof(scalar)/sizeof(U64)); /* clear copy of the regular secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_key, sizeof(reg_key)/sizeof(U64)); /* check if sign_r!=0 and sign_s!=0 */ int8u stt_mask_r = MB_FUNC_NAME(is_zero_FE521_)(sign_r); int8u stt_mask_s = MB_FUNC_NAME(is_zero_FE521_)(sign_s); /* convert signature components to strings */ ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, P521_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, stt_mask_r, MBX_STATUS_SIGNATURE_ERR); status |= MBX_SET_STS_BY_MASK(status, stt_mask_s, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_nistp521_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_msg[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; __ALIGN64 U64 msg[P521_LEN52]; __ALIGN64 U64 sign_r[P521_LEN52]; __ALIGN64 U64 sign_s[P521_LEN52]; /* convert input params */ ifma_HexStr8_to_mb8((int64u (*)[8])msg, pa_msg, P521_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])sign_r, pa_sign_r, P521_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])sign_s, pa_sign_s, P521_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n521_)(msg), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n521_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_n521_)(sign_s), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) return status; P521_POINT W; ifma_BNU_to_mb8((int64u (*)[8])W.X, (const int64u* (*))pa_pubx, P521_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])W.Y, (const int64u* (*))pa_puby, P521_BITSIZE); if(use_jproj_coords) ifma_BNU_to_mb8((int64u (*)[8])W.Z, (const int64u* (*))pa_pubz, P521_BITSIZE); else MB_FUNC_NAME(mov_FE521_)(W.Z, (U64*)ones); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p521_)(W.X), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p521_)(W.Y), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_p521_)(W.Z), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) return status; __mb_mask signature_err_mask = nistp521_ecdsa_verify_mb8(sign_r,sign_s,msg, &W); status |= MBX_SET_STS_BY_MASK(status, signature_err_mask, MBX_STATUS_SIGNATURE_ERR); return status; } /* // OpenSSL's specific implementations */ #ifndef BN_OPENSSL_DISABLE static void reverse_inplace(int8u* inpout, int len) { int mudpoint = len/2; for(int n=0; n=_MBX_K1) */internal_ecpubkey_p256.c000066400000000000000000000121261470420105600345730ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp256_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; int buf_no = 0; /* zero padded keys */ U64 scalarz[P256_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])scalarz, pa_skey, P256_BITSIZE); scalarz[P256_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, P256_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ P256_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_nistp256_mul_pointbase_)(&P, scalarz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_nistp256_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_p256_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_p256_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_p256_)(P.Z, P.Z); /* convert public key and store BIGNUM result */ int8u tmp[8][NUMBER_OF_DIGITS(P256_BITSIZE,8)]; int8u* const pa_tmp[8] = {tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],tmp[7]}; /* X */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.X, P256_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P256_BITSIZE,8), pa_pubx[buf_no]); } /* Y */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Y, P256_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P256_BITSIZE,8), pa_puby[buf_no]); } /* Z */ if(use_jproj_coords) { ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Z, P256_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P256_BITSIZE,8), pa_pubz[buf_no]); } } return status; } #endif // BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp256_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded keys */ U64 scalarz[P256_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_skey, P256_BITSIZE); scalarz[P256_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, P256_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ P256_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_nistp256_mul_pointbase_)(&P, scalarz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_nistp256_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_p256_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_p256_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_p256_)(P.Z, P.Z); /* store result */ ifma_mb8_to_BNU(pa_pubx, (const int64u (*)[8])P.X, P256_BITSIZE); ifma_mb8_to_BNU(pa_puby, (const int64u (*)[8])P.Y, P256_BITSIZE); if(use_jproj_coords) ifma_mb8_to_BNU(pa_pubz, (const int64u (*)[8])P.Z, P256_BITSIZE); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_ecpubkey_p384.c000066400000000000000000000121051470420105600345720ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp384_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; int buf_no = 0; /* zero padded keys */ U64 scalarz[P384_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])scalarz, pa_skey, P384_BITSIZE); scalarz[P384_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, P384_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ P384_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_nistp384_mul_pointbase_)(&P, scalarz); /* clear copy of secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_nistp384_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_p384_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_p384_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_p384_)(P.Z, P.Z); /* convert public key and store BIGNUM result */ int8u tmp[8][NUMBER_OF_DIGITS(P384_BITSIZE,8)]; int8u* const pa_tmp[8] = {tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],tmp[7]}; /* X */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.X, P384_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P384_BITSIZE,8), pa_pubx[buf_no]); } /* Y */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Y, P384_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P384_BITSIZE,8), pa_puby[buf_no]); } /* Z */ if(use_jproj_coords) { ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Z, P384_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P384_BITSIZE,8), pa_pubz[buf_no]); } } return status; } #endif // BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp384_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded keys */ U64 scalarz[P384_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_skey, P384_BITSIZE); scalarz[P384_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, P384_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ P384_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_nistp384_mul_pointbase_)(&P, scalarz); /* clear copy of secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_nistp384_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_p384_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_p384_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_p384_)(P.Z, P.Z); /* store result */ ifma_mb8_to_BNU(pa_pubx, (const int64u (*)[8])P.X, P384_BITSIZE); ifma_mb8_to_BNU(pa_puby, (const int64u (*)[8])P.Y, P384_BITSIZE); if(use_jproj_coords) ifma_mb8_to_BNU(pa_pubz, (const int64u (*)[8])P.Z, P384_BITSIZE); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_ecpubkey_p521.c000066400000000000000000000120221470420105600345610ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp521_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; int buf_no = 0; /* zero padded keys */ U64 scalarz[P521_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])scalarz, pa_skey, P521_BITSIZE); scalarz[P521_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, P521_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ P521_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_nistp521_mul_pointbase_)(&P, scalarz); /* clear copy of secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_nistp521_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_p521_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_p521_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_p521_)(P.Z, P.Z); /* convert public key and store BIGNUM result */ int8u tmp[8][NUMBER_OF_DIGITS(P521_BITSIZE,8)]; int8u* const pa_tmp[8] = {tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],tmp[7]}; /* X */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.X, P521_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P521_BITSIZE,8), pa_pubx[buf_no]); } /* Y */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Y, P521_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P521_BITSIZE,8), pa_puby[buf_no]); } /* Z */ if(use_jproj_coords) { ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Z, P521_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], NUMBER_OF_DIGITS(P521_BITSIZE,8), pa_pubz[buf_no]); } } return status; } #endif // BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp521_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded keys */ U64 scalarz[P521_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_skey, P521_BITSIZE); scalarz[P521_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, P521_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ P521_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_nistp521_mul_pointbase_)(&P, scalarz); /* clear copy of secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_nistp521_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_p521_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_p521_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_p521_)(P.Z, P.Z); /* store result */ ifma_mb8_to_BNU(pa_pubx, (const int64u (*)[8])P.X, P521_BITSIZE); ifma_mb8_to_BNU(pa_puby, (const int64u (*)[8])P.Y, P521_BITSIZE); if(use_jproj_coords) ifma_mb8_to_BNU(pa_pubz, (const int64u (*)[8])P.Z, P521_BITSIZE); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_ifma_ecdh_p256.c000066400000000000000000000151741470420105600346710ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE #include mbx_status internal_avx512_mbx_nistp256_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[P256_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])secretz, (const BIGNUM**)pa_skey, P256_BITSIZE); secretz[P256_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, P256_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P256_POINT P; /* set party's public */ ifma_BN_to_mb8((int64u (*)[8])P.X, (const BIGNUM* (*))pa_pubx, P256_BITSIZE); /* P-> radix 2^52 */ ifma_BN_to_mb8((int64u (*)[8])P.Y, (const BIGNUM* (*))pa_puby, P256_BITSIZE); if(use_jproj_coords) ifma_BN_to_mb8((int64u (*)[8])P.Z, (const BIGNUM* (*))pa_pubz, P256_BITSIZE); else MB_FUNC_NAME(mov_FE256_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p256_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_p256_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_p256_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_p256_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P256_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_nistp256_mul_point_)(&R, &P, secretz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[P256_LEN52]; ifma_aminv52_p256_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_p256_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_p256_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_p256_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, P256_BITSIZE); /* clear computed shared keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif // BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp256_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[P256_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])secretz, (const int64u**)pa_skey, P256_BITSIZE); secretz[P256_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, P256_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P256_POINT P; /* set party's public */ ifma_BNU_to_mb8((int64u (*)[8])P.X, (const int64u* (*))pa_pubx, P256_BITSIZE); // P-> crypto_mb radix 2^52 ifma_BNU_to_mb8((int64u (*)[8])P.Y, (const int64u* (*))pa_puby, P256_BITSIZE); if(use_jproj_coords) ifma_BNU_to_mb8((int64u (*)[8])P.Z, (const int64u* (*))pa_pubz, P256_BITSIZE); else MB_FUNC_NAME(mov_FE256_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p256_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_p256_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_p256_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_p256_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P256_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_nistp256_mul_point_)(&R, &P, secretz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[P256_LEN52]; ifma_aminv52_p256_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_p256_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_p256_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_p256_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, P256_BITSIZE); /* clear computed shared keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_ifma_ecdh_p384.c000066400000000000000000000150551470420105600346710ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp384_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[P384_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])secretz, (const BIGNUM**)pa_skey, P384_BITSIZE); secretz[P384_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, P384_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P384_POINT P; /* set party's public */ ifma_BN_to_mb8((int64u (*)[8])P.X, (const BIGNUM* (*))pa_pubx, P384_BITSIZE); /* P-> radix 2^52 */ ifma_BN_to_mb8((int64u (*)[8])P.Y, (const BIGNUM* (*))pa_puby, P384_BITSIZE); if(use_jproj_coords) ifma_BN_to_mb8((int64u (*)[8])P.Z, (const BIGNUM* (*))pa_pubz, P384_BITSIZE); else MB_FUNC_NAME(mov_FE384_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p384_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_p384_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_p384_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_p384_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P384_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_nistp384_mul_point_)(&R, &P, secretz); /* clear ephemeral secret copy */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[P384_LEN52]; ifma_aminv52_p384_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_p384_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_p384_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_p384_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, P384_BITSIZE); /* clear shared secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif /* BN_OPENSSL_DISABLE */ mbx_status internal_avx512_nistp384_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[P384_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])secretz, (const int64u**)pa_skey, P384_BITSIZE); secretz[P384_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, P384_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P384_POINT P; /* set party's public */ ifma_BNU_to_mb8((int64u (*)[8])P.X, (const int64u* (*))pa_pubx, P384_BITSIZE); // P-> crypto_mb radix 2^52 ifma_BNU_to_mb8((int64u (*)[8])P.Y, (const int64u* (*))pa_puby, P384_BITSIZE); if(use_jproj_coords) ifma_BNU_to_mb8((int64u (*)[8])P.Z, (const int64u* (*))pa_pubz, P384_BITSIZE); else MB_FUNC_NAME(mov_FE384_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p384_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_p384_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_p384_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_p384_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P384_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_nistp384_mul_point_)(&R, &P, secretz); /* clear ephemeral secret copy */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[P384_LEN52]; ifma_aminv52_p384_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_p384_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_p384_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_p384_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, P384_BITSIZE); /* clear shared secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif /* #if (_MBX>=_MBX_K1) */internal_ifma_ecdh_p521.c000066400000000000000000000147571470420105600346720ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ecnist/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_nistp521_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[P521_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])secretz, (const BIGNUM**)pa_skey, P521_BITSIZE); secretz[P521_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, P521_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P521_POINT P; /* set party's public */ ifma_BN_to_mb8((int64u (*)[8])P.X, (const BIGNUM* (*))pa_pubx, P521_BITSIZE); /* P-> radix 2^52 */ ifma_BN_to_mb8((int64u (*)[8])P.Y, (const BIGNUM* (*))pa_puby, P521_BITSIZE); if(use_jproj_coords) ifma_BN_to_mb8((int64u (*)[8])P.Z, (const BIGNUM* (*))pa_pubz, P521_BITSIZE); else MB_FUNC_NAME(mov_FE521_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p521_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_p521_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_p521_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_p521_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P521_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_nistp521_mul_point_)(&R, &P, secretz); /* clear ephemeral secret copy */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[P521_LEN52]; ifma_aminv52_p521_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_p521_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_p521_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_p521_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, P521_BITSIZE); /* clear shared secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif /* BN_OPENSSL_DISABLE */ mbx_status internal_avx512_nistp521_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[P521_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])secretz, (const int64u**)pa_skey, P521_BITSIZE); secretz[P521_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, P521_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P521_POINT P; /* set party's public */ ifma_BNU_to_mb8((int64u (*)[8])P.X, (const int64u* (*))pa_pubx, P521_BITSIZE); // P-> crypto_mb radix 2^52 ifma_BNU_to_mb8((int64u (*)[8])P.Y, (const int64u* (*))pa_puby, P521_BITSIZE); if(use_jproj_coords) ifma_BNU_to_mb8((int64u (*)[8])P.Z, (const int64u* (*))pa_pubz, P521_BITSIZE); else MB_FUNC_NAME(mov_FE521_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_p521_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_p521_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_p521_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_p521_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } P521_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_nistp521_mul_point_)(&R, &P, secretz); /* clear ephemeral secret copy */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[P521_LEN52]; ifma_aminv52_p521_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_p521_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_p521_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_p521_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, P521_BITSIZE); /* clear shared secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/000077500000000000000000000000001470420105600250145ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/ifma_arith_ed25519.c000066400000000000000000000411311470420105600303410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE /* defined in the header above */ /* // Twisted Edwards Curve parameters */ /* d = -(121665/121666) */ __ALIGN64 static const int64u ed25519_d[FE_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x000b4dca135978a3) }, { REP8_DECL(0x0004d4141d8ab75e) }, { REP8_DECL(0x000779e89800700a) }, { REP8_DECL(0x000fe738cc740797) }, { REP8_DECL(0x000052036cee2b6f) } }; /* (2*d) */ __ALIGN64 static const int64u ed25519_d2[FE_LEN52][sizeof(U64) / sizeof(int64u)] = { { REP8_DECL(0x00069b9426b2f159) }, { REP8_DECL(0x0009a8283b156ebd) }, { REP8_DECL(0x000ef3d13000e014) }, { REP8_DECL(0x000fce7198e80f2e) }, { REP8_DECL(0x00002406d9dc56df) } }; /* 2^((p-1)/4) = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0 */ __ALIGN64 static const int64u ed25519_2_pm1_4[FE_LEN52][sizeof(U64) / sizeof(int64u)] = { { REP8_DECL(0x000e1b274a0ea0b0) }, { REP8_DECL(0x00006ad2fe478c4e) }, { REP8_DECL(0x000dfbd7a72f4318) }, { REP8_DECL(0x000df0b2b4d00993) }, { REP8_DECL(0x00002b8324804fc1) } }; /* ext => cached */ __MBX_INLINE void ge_ext_to_cached_mb(ge52_cached_mb *r, const ge52_ext_mb* p) { fe52_add(r->YaddX, p->Y, p->X); fe52_sub(r->YsubX, p->Y, p->X); fe52_copy_mb(r->Z, p->Z); fe52_mul(r->T2d, p->T, (U64*)ed25519_d2); } /* // r = p + q */ static void ge52_add_precomp(ge52_p1p1_mb *r, const ge52_ext_mb *p, const ge52_precomp_mb *q) { fe52_mb t0; fe52_add(r->X, p->Y, p->X); // X3 = Y1+X1 fe52_sub(r->Y, p->Y, p->X); // Y3 = Y1-X1 fe52_mul(r->Z, r->X, q->yaddx); // Z3 = X3*yplusx2 fe52_mul(r->Y, r->Y, q->ysubx); // Y3 = Y3*yminisx2 fe52_mul(r->T, q->t2d, p->T); // T3 = T1*xy2d2 fe52_add(t0, p->Z, p->Z); // t0 = Z1+Z1 fe52_sub(r->X, r->Z, r->Y); // X3 = Z3-Y3 = X3*yplusx2 - Y3*yminisx2 = (Y1+X1)*yplusx2 - (Y1-X1)*yminisx2 fe52_add(r->Y, r->Z, r->Y); // Y3 = Z3+Y3 = X3*yplusx2 + Y3*yminisx2 = (Y1+X1)*yplusx2 + (Y1-X1)*yminisx2 fe52_add(r->Z, t0, r->T); // Z3 = 2*Z1 + T1*xy2d2 fe52_sub(r->T, t0, r->T); // T3 = 2*Z1 - T1*xy2d2 } static void ge_add(ge52_p1p1_mb* r, const ge52_ext_mb* p, const ge52_cached_mb* q) { fe52_mb t0; fe52_add(r->X, p->Y, p->X); fe52_sub(r->Y, p->Y, p->X); fe52_mul(r->Z, r->X, q->YaddX); fe52_mul(r->Y, r->Y, q->YsubX); fe52_mul(r->T, q->T2d, p->T); fe52_mul(r->X, p->Z, q->Z); fe52_add(t0, r->X, r->X); fe52_sub(r->X, r->Z, r->Y); fe52_add(r->Y, r->Z, r->Y); fe52_add(r->Z, t0, r->T); fe52_sub(r->T, t0, r->T); } /* r = 2 * p */ static void ge_dbl(ge52_p1p1_mb *r, const ge52_homo_mb* p) { fe52_mb t0; fe52_sqr(r->X, p->X); fe52_sqr(r->Z, p->Y); fe52_sqr(r->T, p->Z); fe52_add(r->T, r->T, r->T); fe52_add(r->Y, p->X, p->Y); fe52_sqr(t0, r->Y); fe52_add(r->Y, r->Z, r->X); fe52_sub(r->Z, r->Z, r->X); fe52_sub(r->X, t0, r->Y); fe52_sub(r->T, r->T, r->Z); } #define PARITY_SLOT ((GE25519_COMP_BITSIZE-1)/DIGIT_SIZE) #define PARITY_BIT (1LL << ((GE25519_COMP_BITSIZE - 1) % DIGIT_SIZE)) #define SIGN_FE52(fe) srli64((fe)[PARITY_SLOT], ((GE25519_COMP_BITSIZE - 1) % DIGIT_SIZE)) #define PARITY_FE52(fe) and64_const((fe)[0], 1) /* compress point */ void ge52_ext_compress(fe52_mb r, const ge52_ext_mb* p) { fe52_mb recip; fe52_mb x; fe52_mb y; fe52_inv(recip, p->Z); fe52_mul(x, p->X, recip); fe52_mul(y, p->Y, recip); fe52_red(x, x); fe52_red(y, y); __mb_mask is_negative = cmp64_mask(and64_const(x[0], 1), set1(1), _MM_CMPINT_EQ); y[(GE25519_COMP_BITSIZE-1)/DIGIT_SIZE] = _mm512_mask_or_epi64(y[(GE25519_COMP_BITSIZE-1)/DIGIT_SIZE], is_negative, y[(GE25519_COMP_BITSIZE - 1) / DIGIT_SIZE], set1(1LL << (GE25519_COMP_BITSIZE-1)%DIGIT_SIZE)); fe52_copy_mb(r, y); } /* decompress point */ __mb_mask ge52_ext_decompress(ge52_ext_mb* r, const fe52_mb compressed_point) { fe52_mb x; fe52_mb y; fe52_mb u; fe52_mb v; fe52_mb v3; fe52_mb vxx; /* initial values are neutral */ neutral_ge52_ext_mb(r); /* y = fe and clear "x-sign" bit */ fe52_copy_mb(y, compressed_point); y[FE_LEN52-1] = and64_const(y[FE_LEN52-1], PRIME25519_HI); /* x^2 = (y^2 -1) / (d y^2 +1) = u/v. compute numerator (u) and denumerator (v) */ fe52_sqr(u, y); fe52_mul(v, u, (U64*)ed25519_d); fe52_sub(u, u, r->Z); /* u = y^2-1 */ fe52_add(v, v, r->Z); /* v = dy^2+1 */ /* // compute candidate x = sqrt(u/v) = uv^3(uv^7)^((p-5)/8) */ fe52_sqr(v3, v); fe52_mul(v3, v3, v); /* v3 = v^3 */ fe52_sqr(x, v3); fe52_mul(x, x, v); fe52_mul(x, x, u); /* x = uv^7 */ fe52_p2_252m3(x, x); /* x = (uv^7)^((p-5)/8) */ fe52_mul(x, x, v3); fe52_mul(x, x, u); /* x = uv^3(uv^7)^((p-5)/8) */ fe52_sqr(vxx, x); fe52_mul(vxx, vxx, v); /* vxx = v*x^2 */ /* case 1: check if v*x^2 == u */ fe52_sub(v3, vxx, u); /* v*x^2-u */ __mb_mask k1 = fe52_mb_is_zero(v3); fe52_cmov_mb(r->X, r->X, k1, x); /* case 2: check if v*x^2 == -u */ fe52_add(v3, vxx, u); __mb_mask k2 = fe52_mb_is_zero(v3); fe52_mul(x, x, (U64*)ed25519_2_pm1_4); fe52_cmov_mb(r->X, r->X, k2, x); /* copy y coordinate*/ __mb_mask k = k1|k2; fe52_cmov_mb(r->Y, r->Y, k, y); /* set x to (-x) if x.parity different with compressed_point.sign */ k1 = cmp64_mask(SIGN_FE52(compressed_point), PARITY_FE52(r->X), _MM_CMPINT_NE); fe52_neg(v3, r->X); fe52_cmov_mb(r->X, r->X, k1, v3); /* update T compomemt */ fe52_mul(r->T, r->X, r->Y); return k; } /* select from the pre-computed table */ static void extract_precomputed_basepoint_dual(ge52_precomp_mb* p0, ge52_precomp_mb* p1, const ge52_precomp* tbl, U64 idx0, U64 idx1) { /* set h0, h1 to neutral point */ neutral_ge52_precomp_mb(p0); neutral_ge52_precomp_mb(p1); /* indexes are considered as signed values */ __mb_mask is_neg_idx0 = cmp64_mask(idx0, get_zero64(), _MM_CMPINT_LT); __mb_mask is_neg_idx1 = cmp64_mask(idx1, get_zero64(), _MM_CMPINT_LT); idx0 = mask_sub64(idx0, is_neg_idx0, get_zero64(), idx0); idx1 = mask_sub64(idx1, is_neg_idx1, get_zero64(), idx1); /* select p0, p1 wrt idx0, idx1 indexes */ ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(1), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(1), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(2), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(2), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(3), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(3), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(4), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(4), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(5), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(5), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(6), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(6), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(7), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(7), _MM_CMPINT_EQ), tbl); tbl++; ge52_cmov1_precomp_mb(p0, p0, cmp64_mask(idx0, set1(8), _MM_CMPINT_EQ), tbl); ge52_cmov1_precomp_mb(p1, p1, cmp64_mask(idx1, set1(8), _MM_CMPINT_EQ), tbl); /* adjust for sign */ fe52_mb neg; fe52_neg(neg, p0->t2d); fe52_cswap_mb(p0->ysubx, is_neg_idx0, p0->yaddx); fe52_cmov_mb(p0->t2d, p0->t2d, is_neg_idx0, neg); fe52_neg(neg, p1->t2d); fe52_cswap_mb(p1->ysubx, is_neg_idx1, p1->yaddx); fe52_cmov_mb(p1->t2d, p1->t2d, is_neg_idx1, neg); } /* // r = [s]*G // // where s = s[0] + 256*s[1] +...+ 256^31*s[31] // G is the Ed25519 base point (x,4/5) with x positive. // // Preconditions: // s[31] <= 127 */ /* if msb set */ __MBX_INLINE int32u isMsb_ct(int32u a) { return (int32u)0 - (a >> (sizeof(a) * 8 - 1)); } /* tests if a==0 */ __MBX_INLINE int32u isZero(int32u a) { return isMsb_ct(~a & (a - 1)); } /* tests if a==b */ __MBX_INLINE int32u isEqu(int32u a, int32u b) { return isZero(a ^ b); } void ifma_ed25519_mul_basepoint(ge52_ext_mb* r, const U64 scalar[]) { /* implementation uses scalar representation over base b=16, q[i] are half-bytes */ __ALIGN64 ge52_ext_mb r0; /* q[0]*16^0 + q[2]*16^2 + q[4]*16^4 + ...+ q[30]*16^30 */ __ALIGN64 ge52_ext_mb r1; /* q[1]*16^1 + q[3]*16^3 + q[5]*16^5 + ...+ q[31]*16^31 */ /* point extracted from the pre-computed table */ __ALIGN64 ge52_precomp_mb h0; __ALIGN64 ge52_precomp_mb h1; /* temporary */ __ALIGN64 ge52_p1p1_mb t; __ALIGN64 ge52_homo_mb s; /* initial values are neutral */ neutral_ge52_ext_mb(&r0); neutral_ge52_ext_mb(&r1); /* pre-computed basepoint table */ ge52_precomp* tbl = &ifma_ed25519_bp_precomp[0][0]; __mb_mask carry = 0; /* used in conversion to signed value */ for(int n=0; n< FE_LEN64; n++) { /* scalar value*/ U64 scalarV = loadu64(&scalar[n]); for(int m=0; m> ws) - 1)); //sign d = (1 << (ws+1)) - wvalue - 1; // digit, win size "ws" d = (d & s) | (wvaluen & ~s); d = (d >> 1) + (d & 1); *sign = s & 1; *digit = (Ipp8u)d; */ __MBX_INLINE void booth_recode(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64(sub64(set1(1 << (WIN_SIZE + 1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64(srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract point */ static void extract_cached_point(ge52_cached_mb* r, const ge52_cached_mb tbl[], U64 idx, __mb_mask sign) { /* decrement index (the table does not contain neutral element) */ U64 idx_target = sub64(idx, set1(1)); neutral_ge52_cached_mb(r); /* find out what we actually need or just keep neutral */ int32u n; for(n=0; n<(1<<(WIN_SIZE-1)); n++) { U64 idx_curr = set1(n); __mb_mask k = cmp64_mask(idx_curr, idx_target, _MM_CMPINT_EQ); /* r = k? tbl[] : r */ cmov_ge52_cached_mb(r, r, k, &tbl[n]); } /* adjust for sign */ fe52_mb neg; fe52_neg(neg, r->T2d); fe52_cswap_mb(r->YsubX, sign, r->YaddX); fe52_cmov_mb(r->T2d, r->T2d, sign, neg); } /* // r = [s]*P // // where s = s[0] + 256*s[1] +...+ 256^31*s[31] // P is an arbitrary Ed25519 point. */ void ifma_ed25519_mul_point(ge52_ext_mb* r, const ge52_ext_mb* p, const U64 scalar[]) { __ALIGN64 ge52_p1p1_mb p1p1; __ALIGN64 ge52_homo_mb homo; __ALIGN64 ge52_cached_mb cached; __ALIGN64 ge52_ext_mb ext; /* generate the table tbl[] = {p, [2]p, [3]p, [4]p, [5]p, [6]p, [7]p, [8]p} */ __ALIGN64 ge52_cached_mb tbl[1 << (WIN_SIZE-1)]; int n; ge_ext_to_cached_mb(&tbl[0], p); /* tbl[0] = p */ for(n=1; n<(1 << (WIN_SIZE-1)); n++) { ge_add(&p1p1, p, &tbl[n-1]); /* tbl[n] = p + tbl[n-1] */ ge52_p1p1_to_ext_mb(&ext, &p1p1); ge_ext_to_cached_mb(&tbl[n], &ext); } /* ext = neutral */ neutral_ge52_ext_mb(&ext); /* // point (LR) multiplication, 256-bit scalar */ U64 idx_mask = set1((1 << (WIN_SIZE + 1)) - 1); int bit = SCALAR_BITSIZE - (SCALAR_BITSIZE% WIN_SIZE); int chunk_no = (bit - 1) / 64; int chunk_shift = (bit - 1) % 64; U64 dvalue; /* digit value */ __mb_mask dsign; /* digit sign */ /* // first window */ U64 wvalue = loadu64(&scalar[chunk_no]); wvalue = and64(srli64(wvalue, chunk_shift), idx_mask); booth_recode(&dsign, &dvalue, wvalue); extract_cached_point(&cached, tbl, dvalue, dsign); /* ext = cached */ ge_add(&p1p1, &ext, &cached); ge52_p1p1_to_ext_mb(&ext, &p1p1); /* // other windows */ for(bit-=WIN_SIZE; bit>=WIN_SIZE; bit-=WIN_SIZE) { /* 4-x doubling: ext = [16]ext */ ge52_ext_to_homo_mb(&homo, &ext); ge_dbl(&p1p1, &homo); ge52_p1p1_to_homo_mb(&homo, &p1p1); ge_dbl(&p1p1, &homo); ge52_p1p1_to_homo_mb(&homo, &p1p1); ge_dbl(&p1p1, &homo); ge52_p1p1_to_homo_mb(&homo, &p1p1); ge_dbl(&p1p1, &homo); ge52_p1p1_to_ext_mb(&ext, &p1p1); /* extract precomputed []P */ chunk_no = (bit - 1) / 64; chunk_shift = (bit - 1) % 64; wvalue = loadu64(&scalar[chunk_no]); wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no + 1]), set1((int32u)chunk_shift)); wvalue = and64(wvalue, idx_mask); booth_recode(&dsign, &dvalue, wvalue); extract_cached_point(&cached, tbl, dvalue, dsign); /* accumulate ext += cached */ ge_add(&p1p1, &ext, &cached); ge52_p1p1_to_ext_mb(&ext, &p1p1); } /* // last window */ ge52_ext_to_homo_mb(&homo, &ext); ge_dbl(&p1p1, &homo); ge52_p1p1_to_homo_mb(&homo, &p1p1); ge_dbl(&p1p1, &homo); ge52_p1p1_to_homo_mb(&homo, &p1p1); ge_dbl(&p1p1, &homo); ge52_p1p1_to_homo_mb(&homo, &p1p1); ge_dbl(&p1p1, &homo); ge52_p1p1_to_ext_mb(&ext, &p1p1); /* extract precomputed []P */ wvalue = loadu64(&scalar[0]); wvalue = and64(slli64(wvalue, 1), idx_mask); booth_recode(&dsign, &dvalue, wvalue); extract_cached_point(&cached, tbl, dvalue, dsign); /* accumulate ext += cached */ ge_add(&p1p1, &ext, &cached); ge52_p1p1_to_ext_mb(r, &p1p1); } #undef SCALAR_BITSIZE #undef WIN_SIZE /* R = [p]P + [g]G */ void ifma_ed25519_prod_point(ge52_ext_mb* r, const ge52_ext_mb* p, const U64 scalarP[], const U64 scalarG[]) { __ALIGN64 ge52_ext_mb T_mb; ifma_ed25519_mul_point(r, p, scalarP); ifma_ed25519_mul_basepoint(&T_mb, scalarG); __ALIGN64 ge52_cached_mb c; __ALIGN64 ge52_p1p1_mb t; ge_ext_to_cached_mb(&c, &T_mb); ge_add(&t, r, &c); ge52_p1p1_to_ext_mb(r, &t); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/ifma_arith_n25519.c000066400000000000000000000311431470420105600302100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // ED25519 prime base point order // n = 2^252+27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED // in 2^52 radix */ __ALIGN64 static const int64u ed25519n_mb[NE_LEN52][sizeof(U64) / sizeof(int64u)] = { { REP8_DECL(0x0002631A5CF5D3ED) }, { REP8_DECL(0x000DEA2F79CD6581) }, { REP8_DECL(0x000000000014DEF9) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000100000000000) } }; /* mu = floor( 2^2*DIGIT_SIZE/n) = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB2106215D086329A7ED9CE5A30A2C131B39 */ __ALIGN64 static const int64u ed25519mu_mb[NE_LEN52+1][sizeof(U64) / sizeof(int64u)] = { { REP8_DECL(0x0005A30A2C131B39) }, { REP8_DECL(0x000086329A7ED9CE) }, { REP8_DECL(0x000FFFEB2106215D) }, { REP8_DECL(0x000FFFFFFFFFFFFF) }, { REP8_DECL(0x000FFFFFFFFFFFFF) }, { REP8_DECL(0x00000000000000FF) } }; #define ROUND_MUL(R_LO, R_HI, A_I, B_J) \ (R_LO) = fma52lo((R_LO), (A_I), (B_J)); \ (R_HI) = fma52hi((R_HI), (A_I), (B_J)); __ALIGN64 static const int64u VBASE52[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(DIGIT_BASE) }; __ALIGN64 static const int64u VMASK52[sizeof(U64)/sizeof(int64u)] = { REP8_DECL(DIGIT_MASK) }; #define NORM_LSHIFTR(LO, HI) \ (HI) = add64((HI), srli64((LO), DIGIT_SIZE)); \ (LO) = and64((LO), loadu64(VMASK52)); void ifma52_sub_with_borrow(U64 r[], const U64 x[], const U64 y[]) { U64 base = loadu64(VBASE52); U64 one = set1(1LL); U64 subtrahend = get_zero64(); __mmask8 lt = 0; subtrahend = _mm512_mask_add_epi64(y[0], lt, y[0], one); lt = _mm512_cmp_epu64_mask(x[0], subtrahend, _MM_CMPINT_LT); r[0] = _mm512_sub_epi64(x[0], subtrahend); r[0] = _mm512_mask_add_epi64(r[0], lt, r[0], base); subtrahend = _mm512_mask_add_epi64(y[1], lt, y[1], one); lt = _mm512_cmp_epu64_mask(x[1], subtrahend, _MM_CMPINT_LT); r[1] = _mm512_sub_epi64(x[1], subtrahend); r[1] = _mm512_mask_add_epi64(r[1], lt, r[1], base); subtrahend = _mm512_mask_add_epi64(y[2], lt, y[2], one); lt = _mm512_cmp_epu64_mask(x[2], subtrahend, _MM_CMPINT_LT); r[2] = _mm512_sub_epi64(x[2], subtrahend); r[2] = _mm512_mask_add_epi64(r[2], lt, r[2], base); subtrahend = _mm512_mask_add_epi64(y[3], lt, y[3], one); lt = _mm512_cmp_epu64_mask(x[3], subtrahend, _MM_CMPINT_LT); r[3] = _mm512_sub_epi64(x[3], subtrahend); r[3] = _mm512_mask_add_epi64(r[3], lt, r[3], base); subtrahend = _mm512_mask_add_epi64(y[4], lt, y[4], one); lt = _mm512_cmp_epu64_mask(x[4], subtrahend, _MM_CMPINT_LT); r[4] = _mm512_sub_epi64(x[4], subtrahend); r[4] = _mm512_mask_add_epi64(r[4], lt, r[4], base); /* the latest step is not necessary, because Barett algorithms guarantee that // 0<= (r = r1-r2) <3*modulus // r[0..4] is enough to keep 3*modulus */ #if 0 subtrahend = _mm512_mask_add_epi64(y[5], lt, y[5], one); lt = _mm512_cmp_epu64_mask(x[5], subtrahend, _MM_CMPINT_LT); r[5] = _mm512_sub_epi64(x[5], subtrahend); r[5] = _mm512_mask_add_epi64(r[5], lt, r[4], base); #endif } // r = x>DITIT_SIZE*(K+1) // // 4. r1 = x mod b^(k+1) // 5. r2 = q3*n mod b^(k+1) // 6. r = r1-r2, if r<0 then r+=b^(k+1) // 7. if r>n then r -=n -- at most 2 final reductions // r>n then r -=n */ void ifma52_ed25519n_reduce(U64 r[NE_LEN52], const U64 x[NE_LEN52*2]) { /* 1. q1 = x/b^(k-1) -- just (k+1) most significant digits, len(q1) = 2*k - (k-1) = k+1 */ const U64* q1 = x + (NE_LEN52-1); /* // 2. q2 = q1*mu, len(q2) = (k+1) + (k+1) = 2*k+2 // 3. q3 = floor(q2 / b^(k+1)), len(q3) = 2*k+2 - (k+1) = k+1 // => no necessary do compute whole (q1*mu) product, (k+1) most significant digits are enough // // code below represents full multiplication // from which discarded (commented out) computation of the least significant digits */ U64* mu = (U64*)ed25519mu_mb; U64 /*q3_0, q3_1, q3_2, q3_3, q3_4, */ q3_5, q3_6, q3_7, q3_8, q3_9, q3_10, q3_11; /*q3_0= q3_1= q3_2= q3_3= q3_4= */ q3_5 = q3_6 = q3_7 = q3_8 = q3_9 = q3_10 = q3_11 = get_zero64(); //ROUND_MUL(q3_0, q3_1, q1[0], mu[0]); //ROUND_MUL(q3_1, q3_2, q1[0], mu[1]); //ROUND_MUL(q3_1, q3_2, q1[1], mu[0]); //ROUND_MUL(q3_2, q3_3, q1[0], mu[2]); //ROUND_MUL(q3_2, q3_3, q1[1], mu[1]); //ROUND_MUL(q3_2, q3_3, q1[2], mu[0]); //ROUND_MUL(q3_3, q3_4, q1[0], mu[3]); //ROUND_MUL(q3_3, q3_4, q1[1], mu[2]); //ROUND_MUL(q3_3, q3_4, q1[2], mu[1]); //ROUND_MUL(q3_3, q3_4, q1[3], mu[0]); //ROUND_MUL(q3_4, q3_5, q1[0], mu[4]); //ROUND_MUL(q3_4, q3_5, q1[1], mu[3]); //ROUND_MUL(q3_4, q3_5, q1[2], mu[2]); //ROUND_MUL(q3_4, q3_5, q1[3], mu[1]); //ROUND_MUL(q3_4, q3_5, q1[4], mu[0]); q3_5 = fma52hi(q3_5, q1[0], mu[4]); q3_5 = fma52hi(q3_5, q1[1], mu[3]); q3_5 = fma52hi(q3_5, q1[2], mu[2]); q3_5 = fma52hi(q3_5, q1[3], mu[1]); q3_5 = fma52hi(q3_5, q1[4], mu[0]); ROUND_MUL(q3_5, q3_6, q1[0], mu[5]); ROUND_MUL(q3_5, q3_6, q1[1], mu[4]); ROUND_MUL(q3_5, q3_6, q1[2], mu[3]); ROUND_MUL(q3_5, q3_6, q1[3], mu[2]); ROUND_MUL(q3_5, q3_6, q1[4], mu[1]); ROUND_MUL(q3_5, q3_6, q1[5], mu[0]); ROUND_MUL(q3_6, q3_7, q1[1], mu[5]); ROUND_MUL(q3_6, q3_7, q1[2], mu[4]); ROUND_MUL(q3_6, q3_7, q1[3], mu[3]); ROUND_MUL(q3_6, q3_7, q1[4], mu[2]); ROUND_MUL(q3_6, q3_7, q1[5], mu[1]); ROUND_MUL(q3_7, q3_8, q1[2], mu[5]); ROUND_MUL(q3_7, q3_8, q1[3], mu[4]); ROUND_MUL(q3_7, q3_8, q1[4], mu[3]); ROUND_MUL(q3_7, q3_8, q1[5], mu[2]); ROUND_MUL(q3_8, q3_9, q1[3], mu[5]); ROUND_MUL(q3_8, q3_9, q1[4], mu[4]); ROUND_MUL(q3_8, q3_9, q1[5], mu[3]); ROUND_MUL(q3_9, q3_10, q1[4], mu[5]); ROUND_MUL(q3_9, q3_10, q1[5], mu[4]); /* note, that the latest (2*k+2) digit will always be 0 (count bits presentation of x and mu) */ ROUND_MUL(q3_10, q3_11, q1[5], mu[5]); /* normalization, q3 = {q3_11, q3_10, q3_9, q3_8, q3_7, q3_6}, note q3_11 is zero */ NORM_LSHIFTR(q3_5, q3_6); NORM_LSHIFTR(q3_6, q3_7); NORM_LSHIFTR(q3_7, q3_8); NORM_LSHIFTR(q3_8, q3_9); NORM_LSHIFTR(q3_9, q3_10); NORM_LSHIFTR(q3_10, q3_11); /* 4. r1 = x mod b^(k+1) is just (k+1) least significant digits of x */ const U64* r1 = x; /* 5. r2 = (q3*n) mod b^(k+1) // => no necessary do compute whole (q3*n) product, (k+1) least significant digits are enough // // code below represents full multiplication // from which discarded (commented out) computation of the most significant digits */ U64* n = (U64*)ed25519n_mb; U64 r2_0, r2_1, r2_2, r2_3, r2_4, r2_5; r2_0 = r2_1 = r2_2 = r2_3 = r2_4 = r2_5 = q3_11 = get_zero64(); ROUND_MUL(r2_0, r2_1, q3_6, n[0]); ROUND_MUL(r2_1, r2_2, q3_6, n[1]); ROUND_MUL(r2_1, r2_2, q3_7, n[0]); ROUND_MUL(r2_2, r2_3, q3_6, n[2]); ROUND_MUL(r2_2, r2_3, q3_7, n[1]); ROUND_MUL(r2_2, r2_3, q3_8, n[0]); ROUND_MUL(r2_3, r2_4, q3_6, n[3]); ROUND_MUL(r2_3, r2_4, q3_7, n[2]); ROUND_MUL(r2_3, r2_4, q3_8, n[1]); ROUND_MUL(r2_3, r2_4, q3_9, n[0]); ROUND_MUL(r2_4, r2_5, q3_6, n[4]); ROUND_MUL(r2_4, r2_5, q3_7, n[3]); ROUND_MUL(r2_4, r2_5, q3_8, n[2]); ROUND_MUL(r2_4, r2_5, q3_9, n[1]); ROUND_MUL(r2_4, r2_5,q3_10, n[0]); r2_5 = fma52lo(r2_5, q3_7, n[4]); r2_5 = fma52lo(r2_5, q3_8, n[3]); r2_5 = fma52lo(r2_5, q3_9, n[2]); r2_5 = fma52lo(r2_5,q3_10, n[1]); r2_5 = fma52lo(r2_5,q3_11, n[0]); /* r2[6], r2[7], ... amd other most significal digits of full multiplication are discarded */ //r2[6] = fma52hi(r2[5], q3_7, n[4]); //r2[6] = fma52hi(r2[5], q3_8, n[3]); //r2[6] = fma52hi(r2[5], q3_9, n[2]); //r2[6] = fma52hi(r2[5],q3_10, n[1]); //r2[6] = fma52hi(r2[5],q3_11, n[0]); /* normalization */ NORM_LSHIFTR(r2_0, r2_1); NORM_LSHIFTR(r2_1, r2_2); NORM_LSHIFTR(r2_2, r2_3); NORM_LSHIFTR(r2_3, r2_4); NORM_LSHIFTR(r2_4, r2_5); NORM_LSHIFTR(r2_5, q3_11); /* note q3_11 is out of mod b^(k+1) */ U64 r2[NE_LEN52+1]; r2[0] = r2_0; r2[1] = r2_1; r2[2] = r2_2; r2[3] = r2_3; r2[4] = r2_4; r2[5] = r2_5; /* 6. r = r1-r2 */ ifma52_sub_with_borrow(r, r1, r2); /* 7. reduce modulo twice */ ifma52_sub_ed25519n(r, r); ifma52_sub_ed25519n(r, r); } // r = a*b+c %n void ifma52_ed25519n_madd(U64 r[NE_LEN52], const U64 a[NE_LEN52], const U64 b[NE_LEN52], const U64 c[NE_LEN52]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); /* (a*b) */ ROUND_MUL(r0, r1, a[0], b[0]); ROUND_MUL(r1, r2, a[1], b[0]); ROUND_MUL(r2, r3, a[2], b[0]); ROUND_MUL(r3, r4, a[3], b[0]); ROUND_MUL(r4, r5, a[4], b[0]); ROUND_MUL(r1, r2, a[0], b[1]); ROUND_MUL(r2, r3, a[1], b[1]); ROUND_MUL(r3, r4, a[2], b[1]); ROUND_MUL(r4, r5, a[3], b[1]); ROUND_MUL(r5, r6, a[4], b[1]); ROUND_MUL(r2, r3, a[0], b[2]); ROUND_MUL(r3, r4, a[1], b[2]); ROUND_MUL(r4, r5, a[2], b[2]); ROUND_MUL(r5, r6, a[3], b[2]); ROUND_MUL(r6, r7, a[4], b[2]); ROUND_MUL(r3, r4, a[0], b[3]); ROUND_MUL(r4, r5, a[1], b[3]); ROUND_MUL(r5, r6, a[2], b[3]); ROUND_MUL(r6, r7, a[3], b[3]); ROUND_MUL(r7, r8, a[4], b[3]); ROUND_MUL(r4, r5, a[0], b[4]); ROUND_MUL(r5, r6, a[1], b[4]); ROUND_MUL(r6, r7, a[2], b[4]); ROUND_MUL(r7, r8, a[3], b[4]); ROUND_MUL(r8, r9, a[4], b[4]); /* (a*b) + c */ r0 = add64(r0, c[0]); r1 = add64(r1, c[1]); r2 = add64(r2, c[2]); r3 = add64(r3, c[3]); r4 = add64(r4, c[4]); /* normalize result */ NORM_LSHIFTR(r0, r1); NORM_LSHIFTR(r1, r2); NORM_LSHIFTR(r2, r3); NORM_LSHIFTR(r3, r4); NORM_LSHIFTR(r4, r5); NORM_LSHIFTR(r5, r6); NORM_LSHIFTR(r6, r7); NORM_LSHIFTR(r7, r8); NORM_LSHIFTR(r8, r9); U64 t[NE_LEN52*2]; t[0] = r0; t[1] = r1; t[2] = r2; t[3] = r3; t[4] = r4; t[5] = r5; t[6] = r6; t[7] = r7; t[8] = r8; t[9] = r9; ifma52_ed25519n_reduce(r, t); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/ifma_arith_p25519.c000066400000000000000000000343221470420105600302140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) __ALIGN64 static const int64u VPRIME25519_LO[sizeof(U64) / sizeof(int64u)] = { REP8_DECL(PRIME25519_LO) }; __ALIGN64 static const int64u VPRIME25519_MID[sizeof(U64) / sizeof(int64u)] = { REP8_DECL(PRIME25519_MID) }; __ALIGN64 static const int64u VPRIME25519_HI[sizeof(U64) / sizeof(int64u)] = { REP8_DECL(PRIME25519_HI) }; /* normalization macros */ #define NORM_LSHIFTR(R, I, J) \ R##J = add64(R##J, srli64(R##I, DIGIT_SIZE)); \ R##I = and64_const(R##I, DIGIT_MASK); #define NORM_ASHIFTR(R, I, J) \ R##J = add64(R##J, srai64(R##I, DIGIT_SIZE)); \ R##I = and64_const(R##I, DIGIT_MASK); //__MBX_INLINE void fe52_mb_add_mod25519(fe52_mb vr, const fe52_mb va, const fe52_mb vb) { /* r = a+b */ U64 r0 = add64(va[0], vb[0]); U64 r1 = add64(va[1], vb[1]); U64 r2 = add64(va[2], vb[2]); U64 r3 = add64(va[3], vb[3]); U64 r4 = add64(va[4], vb[4]); /* t = r-modulus (2^255-19) */ U64 t0 = sub64(r0, loadu64(VPRIME25519_LO)); U64 t1 = sub64(r1, loadu64(VPRIME25519_MID)); U64 t2 = sub64(r2, loadu64(VPRIME25519_MID)); U64 t3 = sub64(r3, loadu64(VPRIME25519_MID)); U64 t4 = sub64(r4, loadu64(VPRIME25519_HI)); /* normalize r0, r1, r2, r3, r4 */ NORM_LSHIFTR(r, 0, 1) NORM_LSHIFTR(r, 1, 2) NORM_LSHIFTR(r, 2, 3) NORM_LSHIFTR(r, 3, 4) /* normalize t0, t1, t2, t3, t4 */ NORM_ASHIFTR(t, 0, 1) NORM_ASHIFTR(t, 1, 2) NORM_ASHIFTR(t, 2, 3) NORM_ASHIFTR(t, 3, 4) /* condition mask t4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(t4, get_zero64(), _MM_CMPINT_LT); vr[0] = mask_mov64(t0, cmask, r0); vr[1] = mask_mov64(t1, cmask, r1); vr[2] = mask_mov64(t2, cmask, r2); vr[3] = mask_mov64(t3, cmask, r3); vr[4] = mask_mov64(t4, cmask, r4); } //__MBX_INLINE void fe52_mb_sub_mod25519(fe52_mb vr, const fe52_mb va, const fe52_mb vb) { /* r = a-b */ U64 r0 = sub64(va[0], vb[0]); U64 r1 = sub64(va[1], vb[1]); U64 r2 = sub64(va[2], vb[2]); U64 r3 = sub64(va[3], vb[3]); U64 r4 = sub64(va[4], vb[4]); /* t = r+modulus (2^255-19) */ U64 t0 = add64(r0, loadu64(VPRIME25519_LO)); U64 t1 = add64(r1, loadu64(VPRIME25519_MID)); U64 t2 = add64(r2, loadu64(VPRIME25519_MID)); U64 t3 = add64(r3, loadu64(VPRIME25519_MID)); U64 t4 = add64(r4, loadu64(VPRIME25519_HI)); /* normalize r0, r1, r2, r3, r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) /* normalize t0, t1, t2, t3, t4 */ NORM_ASHIFTR(t, 0, 1) NORM_ASHIFTR(t, 1, 2) NORM_ASHIFTR(t, 2, 3) NORM_ASHIFTR(t, 3, 4) /* condition mask r4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(r4, get_zero64(), _MM_CMPINT_LT); vr[0] = mask_mov64(r0, cmask, t0); vr[1] = mask_mov64(r1, cmask, t1); vr[2] = mask_mov64(r2, cmask, t2); vr[3] = mask_mov64(r3, cmask, t3); vr[4] = mask_mov64(r4, cmask, t4); } //__MBX_INLINE void fe52_mb_neg_mod25519(fe52_mb vr, const fe52_mb va) { __mb_mask non_zero = ~fe52_mb_is_zero(va); /* r = is_zero? a : p-a */ U64 r0 = mask_sub64(va[0], non_zero, loadu64(VPRIME25519_LO), va[0]); U64 r1 = mask_sub64(va[1], non_zero, loadu64(VPRIME25519_MID), va[1]); U64 r2 = mask_sub64(va[2], non_zero, loadu64(VPRIME25519_MID), va[2]); U64 r3 = mask_sub64(va[3], non_zero, loadu64(VPRIME25519_MID), va[3]); U64 r4 = mask_sub64(va[4], non_zero, loadu64(VPRIME25519_HI), va[4]); /* normalize r0, r1, r2, r3, r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) vr[0] = r0; vr[1] = r1; vr[2] = r2; vr[3] = r3; vr[4] = r4; } /* // multiplicative operations */ /* full multiplication macros */ #define ROUND_MUL_SRC(I, J, S_LO, R_LO, S_HI, R_HI) \ R_LO = fma52lo(S_LO, va[I], vb[J]); \ R_HI = fma52hi(S_HI, va[I], vb[J]); #define ROUND_MUL(I, J, M0, M1) \ ROUND_MUL_SRC(I, J, M0, M0, M1, M1) /* reduction constants and macros */ #define MASK47 ((1ULL << (255 - 52 * 4)) - 1) __ALIGN64 static const int64u MASK47_[sizeof(U64) / sizeof(int64u)] = { REP8_DECL(MASK47) }; __ALIGN64 static const int64u MOD_2_255_[sizeof(U64) / sizeof(int64u)] = { REP8_DECL(19) }; __ALIGN64 static const int64u MOD_2_260_[sizeof(U64) / sizeof(int64u)] = { REP8_DECL(19*32) }; #define MASK_47 loadu64(MASK47_) #define MOD_2_255 loadu64(MOD_2_255_) #define MOD_2_260 loadu64(MOD_2_260_) #define REDUCE_ROUND(R0, R1, R5) \ r##R0 = fma52lo(r##R0, r##R5, MOD_2_260); \ r##R1 = fma52lo( fma52hi(r##R1, r##R5, MOD_2_260), \ srli64(r##R5, 52), MOD_2_260); //__MBX_INLINE void fe52_mb_mul_mod25519(fe52_mb vr, const fe52_mb va, const fe52_mb vb) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); /* full multiplication */ ROUND_MUL(4, 4, r8, r9); ROUND_MUL(3, 0, r3, r4); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(2, 1, r3, r4); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(3, 1, r4, r5); ROUND_MUL(4, 0, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(2, 3, r5, r6); ROUND_MUL(3, 2, r5, r6); ROUND_MUL(4, 1, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 2, r6, r7); ROUND_MUL(0, 0, r0, r1); ROUND_MUL(0, 1, r1, r2); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(1, 0, r1, r2); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 0, r2, r3); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(4, 3, r7, r8); /* reduce r4 upper bits */ r4 = fma52lo(r4, r9, MOD_2_260); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); r4 = and64(r4, MASK_47); /* rest of reduction */ REDUCE_ROUND(0, 1, 5); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(3, 4, 8); /* normalize result */ NORM_LSHIFTR(r, 0, 1); NORM_LSHIFTR(r, 1, 2); NORM_LSHIFTR(r, 2, 3); NORM_LSHIFTR(r, 3, 4); vr[0] = r0; vr[1] = r1; vr[2] = r2; vr[3] = r3; vr[4] = r4; } /* SQR c=0 (0,0) c=1 (0,1) c=2 (0,2) (1,1) c=3 (0,3) (1,2) c=4 (0,4) (1,3) (2,2) c=5 (1,4) (2,3) c=6 (2,4) (3,3) c=7 (3,4) c=8 (4,4) */ //__MBX_INLINE void fe52_mb_sqr_mod25519(fe52_mb vr, const fe52_mb va) { U64 *vb = (U64*)va; U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // Square ROUND_MUL(0, 1, r1, r2); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(2, 3, r5, r6); r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); ROUND_MUL(0, 0, r0, r1); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 4, r8, r9); /* reduce r4 upper bits */ r4 = fma52lo(r4, r9, MOD_2_260); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); r4 = and64(r4, MASK_47); /* rest of reduction */ REDUCE_ROUND(0, 1, 5); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(3, 4, 8); /* normalize result */ NORM_LSHIFTR(r, 0, 1); NORM_LSHIFTR(r, 1, 2); NORM_LSHIFTR(r, 2, 3); NORM_LSHIFTR(r, 3, 4); vr[0] = r0; vr[1] = r1; vr[2] = r2; vr[3] = r3; vr[4] = r4; } /* variant of ROUND_MUL_SRC() and ROUND_MUL() macros */ #define ROUND_MUL_SRC_A(I, J, S_LO, R_LO, S_HI, R_HI) \ R_LO = fma52lo(S_LO, a##I, a##J); \ R_HI = fma52hi(S_HI, a##I, a##J); #define ROUND_MUL_A(I, J, M0, M1) \ ROUND_MUL_SRC_A(I, J, M0, M0, M1, M1) void fe52_mb_sqr_mod25519_times(fe52_mb vr, const fe52_mb va, int count) { U64 a0 = va[0]; U64 a1 = va[1]; U64 a2 = va[2]; U64 a3 = va[3]; U64 a4 = va[4]; U64 r0, r1, r2, r3, r4_1, r4, r5, r6, r7, r8, r9; for(int i=0; i=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/ifma_ed25519.c000066400000000000000000000125611470420105600271570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 /* // Computes public key // pa_public_key[] array of pointers to the public keys X-coordinates // pa_secret_key[] array of pointers to the public keys Y-coordinates */ DLL_PUBLIC mbx_status OWNAPI(mbx_ed25519_public_key_mb8)(ed25519_public_key* pa_public_key[8], const ed25519_private_key* const pa_private_key[8]) { mbx_status status = MBX_STATUS_OK; /* test input pointers */ if (NULL == pa_private_key || NULL == pa_public_key) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ int buf_no; for (buf_no = 0; buf_no < 8; buf_no++) { const ed25519_private_key* private_key = pa_private_key[buf_no]; ed25519_public_key* public_key = pa_public_key[buf_no]; /* if any of pointer NULL set error status */ if (NULL == private_key || NULL == public_key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } #if (_MBX>=_MBX_K1) status |= internal_avx512_ed25519_public_key_mb8(pa_public_key, pa_private_key); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_ed25519_sign_mb8)(ed25519_sign_component* pa_sign_r[8], ed25519_sign_component* pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_private_key* const pa_private_key[8], const ed25519_public_key* const pa_public_key[8]) { mbx_status status = MBX_STATUS_OK; /* test input pointers */ if(NULL == pa_sign_r || NULL == pa_sign_s || NULL == pa_msg || NULL == msgLen || NULL == pa_private_key || NULL== pa_public_key) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ int buf_no; for (buf_no = 0; buf_no < 8; buf_no++) { ed25519_sign_component* sign_r = pa_sign_r[buf_no]; ed25519_sign_component* sign_s = pa_sign_s[buf_no]; const int8u* msg = pa_msg[buf_no]; const ed25519_private_key* secret = pa_private_key[buf_no]; const ed25519_public_key* public = pa_public_key[buf_no]; /* if any of pointer NULL set error status */ if(NULL == sign_r || NULL == sign_s || NULL== msg || NULL == secret || NULL == public) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } #if (_MBX>=_MBX_K1) status |= internal_avx512_ed25519_sign_mb8(pa_sign_r, pa_sign_s, pa_msg, msgLen, pa_private_key, pa_public_key); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_ed25519_verify_mb8)(const ed25519_sign_component* const pa_sign_r[8], const ed25519_sign_component* const pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_public_key* const pa_public_key[8]) { mbx_status status = MBX_STATUS_OK; /* test input pointers */ if (NULL == pa_sign_r || NULL == pa_sign_s || NULL == pa_msg || NULL == msgLen || NULL == pa_public_key) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ int buf_no; for (buf_no = 0; buf_no < 8; buf_no++) { const ed25519_sign_component* sign_r = pa_sign_r[buf_no]; const ed25519_sign_component* sign_s = pa_sign_s[buf_no]; const int8u* msg = pa_msg[buf_no]; const ed25519_public_key* public = pa_public_key[buf_no]; /* if any of pointer NULL set error status */ if (NULL == sign_r || NULL == sign_s || NULL == msg || NULL == public) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } #if (_MBX>=_MBX_K1) status |= internal_avx512_ed25519_verify_mb8(pa_sign_r, pa_sign_s, pa_msg, msgLen, pa_public_key); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/internal_avx512/000077500000000000000000000000001470420105600277365ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/internal_avx512/internal_ed25519.c000066400000000000000000000303311470420105600327740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* length of SHA512 hash in bits and bytes */ #define SHA512_HASH_BITLENGTH (512) #define HASH_LENGTH NUMBER_OF_DIGITS(SHA512_HASH_BITLENGTH, 8) void ed25519_expand_key(int8u* pa_secret_expand[8], const ed25519_private_key* const pa_secret_key[8]) { /* do hash of secret keys in sequence */ for (int n = 0; n < 8; n++) { const ed25519_private_key* psecret = pa_secret_key[n]; if (psecret) { SHA512MsgDigest(*psecret, sizeof(ed25519_private_key), pa_secret_expand[n]); /* prune the buffer according to RFC8032 */ pa_secret_expand[n][0] &= 0xf8; pa_secret_expand[n][31] &= 0x7f; pa_secret_expand[n][31] |= 0x40; } } } mbx_status internal_avx512_ed25519_public_key_mb8(ed25519_public_key* pa_public_key[8], const ed25519_private_key* const pa_private_key[8]) { mbx_status status = 0; /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { int8u sha512_digest[8][HASH_LENGTH] = { 0 }; int64u* pa_sha512_digest[] = { (int64u*)sha512_digest[0], (int64u*)sha512_digest[1], (int64u*)sha512_digest[2], (int64u*)sha512_digest[3], (int64u*)sha512_digest[4], (int64u*)sha512_digest[5], (int64u*)sha512_digest[6], (int64u*)sha512_digest[7] }; /* expand secret keys */ ed25519_expand_key((int8u**)pa_sha512_digest, pa_private_key); /* convert into mb format */ U64 scalar[FE_LEN64]; ifma_BNU_transpose_copy((int64u(*)[8])scalar, (const int64u**)pa_sha512_digest, SHA512_HASH_BITLENGTH/2); /* r = [scalar]*G */ ge52_ext_mb r; ifma_ed25519_mul_basepoint(&r, scalar); /* compress point to public */ fe52_mb packed_point; ge52_ext_compress(packed_point, &r); /* return result */ ifma_mb8_to_BNU((int64u * const*)pa_public_key, (const int64u(*)[8])packed_point, GE25519_COMP_BITSIZE); /* clear memory containing potentially secret data */ MB_FUNC_NAME(zero_)((int64u(*)[8])scalar, sizeof(scalar)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u(*)[8])sha512_digest, sizeof(sha512_digest)/sizeof(U64)); } return status; } /* // Computes ED2519 signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages are being signed // msgLen[] array of messages lengths (in bytes) // pa_private_key[] array of pointers to the signer's private keys // pa_public_key[] array of pointers to the signer's public keys */ static void ed25519_nonce(int8u* pa_nonce[8], int8u* pa_az[8], const int8u* const pa_msg[8], const int32u msgLen[8]) { SHA512State pState; for(int n=0; n<8; n++) { int8u* az = pa_az[n] + HASH_LENGTH/2; const int8u* msg = pa_msg[n]; int32u mlen = msgLen[n]; SHA512Init(&pState); SHA512Update(az, 32, &pState); if (msg) SHA512Update(msg, mlen, &pState); SHA512Final(pa_nonce[n], &pState); } } static void ed25519_hash_r_pub_msg(int8u* pa_hram[8], const ed25519_sign_component* const pa_sign_r[], const ed25519_public_key* const pa_public_key[8], const int8u* const pa_msg[8], const int32u msgLen[8]) { SHA512State pState; for (int n = 0; n < 8; n++) { const ed25519_sign_component* sign_r = pa_sign_r[n]; const ed25519_public_key* public = pa_public_key[n]; const int8u* msg = pa_msg[n]; int32u mlen = msgLen[n]; SHA512Init(&pState); if(sign_r) SHA512Update((const int8u*)sign_r, NUMBER_OF_DIGITS(GE25519_COMP_BITSIZE, 8), &pState); if(public) SHA512Update((const int8u*)public, sizeof(ed25519_public_key), &pState); if(msg) SHA512Update(msg, mlen, &pState); SHA512Final(pa_hram[n], &pState); } } mbx_status MB_FUNC_NAME(internal_avx512_ed25519_sign_)(ed25519_sign_component* pa_sign_r[8], ed25519_sign_component* pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_private_key* const pa_private_key[8], const ed25519_public_key* const pa_public_key[8]) { mbx_status status = 0; /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { //#define HASH_LENGTH NUMBER_OF_DIGITS(SHA512_DIGEST_BITLENGTH, 8) /* expanded secret keys */ int8u az[8][HASH_LENGTH] = { 0 }; int64u* pa_az[8] = { (int64u*)az[0], (int64u*)az[1], (int64u*)az[2], (int64u*)az[3], (int64u*)az[4], (int64u*)az[5], (int64u*)az[6], (int64u*)az[7] }; /* nonce */ int8u nonce[8][HASH_LENGTH] = { 0 }; int64u* pa_nonce[8] = { (int64u*)nonce[0], (int64u*)nonce[1], (int64u*)nonce[2], (int64u*)nonce[3], (int64u*)nonce[4], (int64u*)nonce[5], (int64u*)nonce[6], (int64u*)nonce[7] }; /* hram */ int8u hram[8][HASH_LENGTH] = { 0 }; int64u* pa_hram[8] = { (int64u*)hram[0], (int64u*)hram[1], (int64u*)hram[2], (int64u*)hram[3], (int64u*)hram[4], (int64u*)hram[5], (int64u*)hram[6], (int64u*)hram[7] }; /* expands secret key, az = H(private_key) */ ed25519_expand_key((int8u**)pa_az, pa_private_key); U64 mb_az[FE_LEN52]; ifma_BNU_to_mb8((int64u(*)[8])mb_az, (const int64u**)pa_az, SHA512_HASH_BITLENGTH/2); /* computes nonce, nonce = H(az+32, msg) */ /* Note: only a second half of each pa_az[n] item is used in the ed25519_nonce() function */ ed25519_nonce((int8u**)pa_nonce, (int8u**)pa_az, pa_msg, msgLen); /* reduce nonce wrt n */ U64 mb_nonce[NUMBER_OF_DIGITS(SHA512_HASH_BITLENGTH, DIGIT_SIZE)]; ifma_BNU_to_mb8((int64u(*)[8])mb_nonce, (const int64u**)pa_nonce, SHA512_HASH_BITLENGTH); ifma52_ed25519n_reduce(mb_nonce, mb_nonce); /* computes r-component of the signature */ ifma_mb8_to_BNU(pa_nonce, (const int64u(*)[8])mb_nonce, N25519_BITSIZE); fe52_mb mb_scalar; ifma_BNU_transpose_copy((int64u(*)[8])mb_scalar, (const int64u**)pa_nonce, N25519_BITSIZE); ge52_ext_mb R; ifma_ed25519_mul_basepoint(&R, mb_scalar); /* R = [scalar]*G */ fe52_mb mb_sign_r; ge52_ext_compress(mb_sign_r, &R); /* compress point to r-component */ /* store r-component of the signature */ ifma_mb8_to_BNU((int64u * const*)pa_sign_r, (const int64u(*)[8])mb_sign_r, GE25519_COMP_BITSIZE); /* computes hram, hram = H(r_sign, public_key, msg) */ ed25519_hash_r_pub_msg((int8u**)pa_hram, (const ed25519_sign_component**)pa_sign_r, pa_public_key, pa_msg, msgLen); U64 mb_hram[NUMBER_OF_DIGITS(SHA512_HASH_BITLENGTH, DIGIT_SIZE)]; ifma_BNU_to_mb8((int64u(*)[8])mb_hram, (const int64u**)pa_hram, SHA512_HASH_BITLENGTH); ifma52_ed25519n_reduce(mb_hram, mb_hram); /* s = hram*az + nonce */ fe52_mb mb_sign_s; ifma52_ed25519n_madd(mb_sign_s, mb_hram, mb_az, mb_nonce); /* store s-component of the signature */ ifma_mb8_to_BNU((int64u * const*)pa_sign_s, (const int64u(*)[8])mb_sign_s, N25519_BITSIZE); /* clear memory containing potentially secret data */ MB_FUNC_NAME(zero_)((int64u(*)[8])az, sizeof(az)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u(*)[8])nonce, sizeof(nonce)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u(*)[8])mb_scalar, sizeof(mb_scalar)/sizeof(U64)); } return status; } /* // ED25519 prime base point order // n = 2^252+27742317777372353535851937790883648493 = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED // in 2^64 radix */ __ALIGN64 static int64u ed25519n_mb64[NE_LEN64][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x5812631A5CF5D3ED) }, { REP8_DECL(0x14DEF9DEA2F79CD6) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x1000000000000000) } }; mbx_status MB_FUNC_NAME(internal_avx512_ed25519_verify_)(const ed25519_sign_component* const pa_sign_r[8], const ed25519_sign_component* const pa_sign_s[8], const int8u* const pa_msg[8], const int32u msgLen[8], const ed25519_public_key* const pa_public_key[8]) { mbx_status status = 0; /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { /* h = SHA512(sign_r || public_key || msg) */ __ALIGN64 int8u h[8][HASH_LENGTH] = { 0 }; int64u* pa_h[8] = { (int64u*)h[0], (int64u*)h[1], (int64u*)h[2], (int64u*)h[3], (int64u*)h[4], (int64u*)h[5], (int64u*)h[6], (int64u*)h[7] }; ed25519_hash_r_pub_msg((int8u**)pa_h, pa_sign_r, pa_public_key, pa_msg, msgLen); /* reduce h %= n */ __ALIGN64 U64 h_mb[NUMBER_OF_DIGITS(SHA512_HASH_BITLENGTH, DIGIT_SIZE)]; ifma_BNU_to_mb8((int64u(*)[8])h_mb, (const int64u**)pa_h, SHA512_HASH_BITLENGTH); ifma52_ed25519n_reduce(h_mb, h_mb); /* convert h_mb: fe52 => fe64 */ __ALIGN64 U64 h64_mb[FE_LEN64+1]; fe52_to_fe64_mb(h64_mb, h_mb); h64_mb[FE_LEN64] = get_zero64(); /* input r-components to mb */ __ALIGN64 fe52_mb inputR_mb; ifma_BNU_to_mb8((int64u(*)[8])inputR_mb, (const int64u**)pa_sign_r, GE25519_COMP_BITSIZE); /* input s-components to mb */ __ALIGN64 U64 s_mb[NE_LEN64 + 1]; ifma_BNU_transpose_copy((int64u(*)[8])s_mb, (const int64u**)pa_sign_s, 256); s_mb[NE_LEN64] = get_zero64(); /* (comppressed) publickey to mb */ __ALIGN64 fe52_mb pubfe_mb; ifma_BNU_to_mb8((int64u(*)[8])pubfe_mb, (const int64u**)pa_public_key, P25519_BITSIZE + 1); /* check that s0; n--) { k |= cmp64_mask(n_mb[n - 1], s_mb[n - 1], _MM_CMPINT_NLE); } status |= MBX_SET_STS_BY_MASK(status, ~k, MBX_STATUS_MISMATCH_PARAM_ERR); /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { /* decompress public to ext point A */ __ALIGN64 ge52_ext_mb pubA_mb; k = ge52_ext_decompress(&pubA_mb, pubfe_mb); fe52_neg(pubA_mb.X, pubA_mb.X); fe52_neg(pubA_mb.T, pubA_mb.T); status |= MBX_SET_STS_BY_MASK(status, ~k, MBX_STATUS_SIGNATURE_ERR); if (MBX_IS_ANY_OK_STS(status)) { /* R = [h]A + [s]G */ __ALIGN64 ge52_ext_mb R_mb; ifma_ed25519_prod_point(&R_mb, &pubA_mb, h64_mb, s_mb); /* recovered r-components */ __ALIGN64 fe52_mb checkR_mb; ge52_ext_compress(checkR_mb, &R_mb); /* check that recovered r- and input r- components are equal each other */ k = fe52_mb_is_equ(checkR_mb, inputR_mb); status |= MBX_SET_STS_BY_MASK(status, ~k, MBX_STATUS_SIGNATURE_ERR); } } } return status; } #endif /* #if (_MBX>=_MBX_K1) */cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/ed25519/sha512.c000066400000000000000000000155011470420105600261650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* setup init hash value */ static void sha512_init(int64u* pHash) { pHash[0] = sha512_iv[0]; pHash[1] = sha512_iv[1]; pHash[2] = sha512_iv[2]; pHash[3] = sha512_iv[3]; pHash[4] = sha512_iv[4]; pHash[5] = sha512_iv[5]; pHash[6] = sha512_iv[6]; pHash[7] = sha512_iv[7]; } static void sha512_update(void* uniHash, const int8u* mblk, int mlen) { int32u* data = (int32u*)mblk; int64u* digest = (int64u*)uniHash; int64u* SHA512_cnt_loc = (int64u*)sha512_cnt; for (; mlen >= MBS_SHA512; data += MBS_SHA512 / sizeof(int32u), mlen -= MBS_SHA512) { int64u wdat[16]; int j; int64u v[8]; /* initialize the first 16 words in the array W (remember about endian) */ for (j = 0; j < 16; j++) { int32u hiX = data[2 * j]; int32u loX = data[2 * j + 1]; wdat[j] = MAKEDWORD(ENDIANNESS(loX), ENDIANNESS(hiX)); } /* copy digest */ CopyBlock(digest, v, SHA512_DIGEST_BITSIZE / BYTESIZE); for (j = 0; j < 80; j += 16) { SHA512_STEP(0, j); SHA512_STEP(1, j); SHA512_STEP(2, j); SHA512_STEP(3, j); SHA512_STEP(4, j); SHA512_STEP(5, j); SHA512_STEP(6, j); SHA512_STEP(7, j); SHA512_STEP(8, j); SHA512_STEP(9, j); SHA512_STEP(10, j); SHA512_STEP(11, j); SHA512_STEP(12, j); SHA512_STEP(13, j); SHA512_STEP(14, j); SHA512_STEP(15, j); } /* update digest */ digest[0] += v[0]; digest[1] += v[1]; digest[2] += v[2]; digest[3] += v[3]; digest[4] += v[4]; digest[5] += v[5]; digest[6] += v[6]; digest[7] += v[7]; } } static void sha512_final(DigestSHA512 pHash, const int8u* inpBuffer, int inpLen, const int64u lenLo, const int64u lenHi) { /* local buffer and its length */ int8u buffer[MBS_SHA512 * 2]; int bufferLen = inpLen < (MBS_SHA512 - (int)MLR_SHA512) ? MBS_SHA512 : MBS_SHA512 * 2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer + inpLen, (int)(bufferLen - inpLen - (int)MLR_SHA512)); /* message length representation */ const int64u beLenHi = ENDIANNESS64(LSL64(lenHi, 3) | LSR64(lenLo, 63 - 3)); const int64u beLenLo = ENDIANNESS64(LSL64(lenLo, 3)); CopyBlock(&beLenHi, &buffer[bufferLen - 2 * sizeof(int64u)], sizeof(int64u)); CopyBlock(&beLenLo, &buffer[bufferLen - 1 * sizeof(int64u)], sizeof(int64u)); /* complete hash computation */ sha512_update(pHash, buffer, bufferLen); } void SHA512Init(SHA512State* pState) { /* zeros message length */ HASH_LENLO(pState) = 0; HASH_LENHI(pState) = 0; /* message buffer is free */ HASH_BUFFIDX(pState) = 0; /* clear ctx buffer */ PadBlock(0, HASH_BUFF(pState), MBS_SHA512); /* setup initial digest */ sha512_init(HASH_VALUE(pState)); } void SHA512Update(const int8u* pSrc, int len, SHA512State* pState) { /* // handle non empty message */ if (len) { int procLen; int idx = HASH_BUFFIDX(pState); int8u* pBuffer = HASH_BUFF(pState); int64u lenLo = HASH_LENLO(pState) + (int64u)len; int64u lenHi = HASH_LENHI(pState); if (lenLo < HASH_LENLO(pState)) lenHi++; /* if non empty internal buffer filling */ if (idx) { /* copy from input stream to the internal buffer as match as possible */ procLen = MIN(len, (MBS_SHA512 - idx)); CopyBlock(pSrc, pBuffer + idx, procLen); /* update message pointer and length */ pSrc += procLen; len -= procLen; idx += procLen; /* update digest if buffer full */ if (MBS_SHA512 == idx) { sha512_update(HASH_VALUE(pState), pBuffer, MBS_SHA512); idx = 0; } } /* main message part processing */ procLen = len & ~(MBS_SHA512 - 1); if (procLen) { sha512_update(HASH_VALUE(pState), pSrc, procLen); pSrc += procLen; len -= procLen; } /* store rest of message into the internal buffer */ if (len) { CopyBlock(pSrc, pBuffer, len); idx += len; } /* update length of processed message */ HASH_LENLO(pState) = lenLo; HASH_LENHI(pState) = lenHi; HASH_BUFFIDX(pState) = idx; } } void SHA512Final(int8u* pMD, SHA512State* pState) { sha512_final(HASH_VALUE(pState), HASH_BUFF(pState), HASH_BUFFIDX(pState), HASH_LENLO(pState), HASH_LENHI(pState)); /* convert hash into big endian */ ((int64u*)pMD)[0] = ENDIANNESS64(HASH_VALUE(pState)[0]); ((int64u*)pMD)[1] = ENDIANNESS64(HASH_VALUE(pState)[1]); ((int64u*)pMD)[2] = ENDIANNESS64(HASH_VALUE(pState)[2]); ((int64u*)pMD)[3] = ENDIANNESS64(HASH_VALUE(pState)[3]); ((int64u*)pMD)[4] = ENDIANNESS64(HASH_VALUE(pState)[4]); ((int64u*)pMD)[5] = ENDIANNESS64(HASH_VALUE(pState)[5]); ((int64u*)pMD)[6] = ENDIANNESS64(HASH_VALUE(pState)[6]); ((int64u*)pMD)[7] = ENDIANNESS64(HASH_VALUE(pState)[7]); /* re-init hash value */ SHA512Init(pState); } void SHA512MsgDigest(const int8u* pMsg, int len, int8u* pMD) { /* message length in the multiple MBS and the rest */ int msgLenBlks = len & (-MBS_SHA512); int msgLenRest = len - msgLenBlks; DigestSHA512 hash; /* init hash */ sha512_init(hash); /* process main part of the message */ if (msgLenBlks) { sha512_update(hash, pMsg, msgLenBlks); pMsg += msgLenBlks; } sha512_final(hash, pMsg, msgLenRest, (int64u)len, 0); hash[0] = ENDIANNESS64(hash[0]); hash[1] = ENDIANNESS64(hash[1]); hash[2] = ENDIANNESS64(hash[2]); hash[3] = ENDIANNESS64(hash[3]); hash[4] = ENDIANNESS64(hash[4]); hash[5] = ENDIANNESS64(hash[5]); hash[6] = ENDIANNESS64(hash[6]); hash[7] = ENDIANNESS64(hash[7]); CopyBlock(hash, pMD, SHA512_DIGEST_BITSIZE / BYTESIZE); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/000077500000000000000000000000001470420105600246125ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/ifma_exp1k_mb.c000066400000000000000000000231731470420105600274660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x20_mb8(out, Y, mod, k0) \ AMS52x20_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x20_mb8(out, Y, mod, k0) \ AMS5x52x20_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); #else #define SQUARE_5x52x20_mb8(out, Y, mod, k0) \ AMS52x20_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ AMS52x20_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x20_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x20_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x20_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #endif #else #define SQUARE_52x20_mb8(out, Y, mod, k0) \ ifma_amm52x20_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); #define SQUARE_5x52x20_mb8(out, Y, mod, k0) \ ifma_amm52x20_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ ifma_amm52x20_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x20_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x20_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x20_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #endif #define BITSIZE_MODULUS (1024) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,DIGIT_SIZE)) //20 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) //16 typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u* extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10= _mm512_load_si512(tbl[0][10]); __m512i X11= _mm512_load_si512(tbl[0][11]); __m512i X12= _mm512_load_si512(tbl[0][12]); __m512i X13= _mm512_load_si512(tbl[0][13]); __m512i X14= _mm512_load_si512(tbl[0][14]); __m512i X15= _mm512_load_si512(tbl[0][15]); __m512i X16= _mm512_load_si512(tbl[0][16]); __m512i X17= _mm512_load_si512(tbl[0][17]); __m512i X18= _mm512_load_si512(tbl[0][18]); __m512i X19= _mm512_load_si512(tbl[0][19]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for(n=1; n<(1<=0; exp_bit_no-=EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE==5 SQUARE_5x52x20_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #else SQUARE_52x20_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x20_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x20_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x20_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #endif /* extract pre-computed multiplier from the table */ { exp_chunk_no = exp_bit_no/64; exp_chunk_shift = exp_bit_no%64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no+1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64-exp_chunk_shift)); red_table_idx = _mm512_and_si512( _mm512_xor_si512(red_table_idx, T), table_idx_mask); ifma_extract_amm52x20_mb8 ((int64u*)red_Y, (int64u*)red_Y, red_table, (int64u*)(&red_table_idx), (int64u*)modulus, (int64u*)k0); } } } /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x20_mb8((int64u*)out, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); zero_mb8(red_Y, LEN52); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/ifma_exp2k_mb.c000066400000000000000000000303761470420105600274720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x40_mb8(out, Y, mod, k0) \ AMS52x40_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ AMS5x52x40_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); #else #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ AMS52x40_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ AMS52x40_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x40_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x40_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x40_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #endif #else #define SQUARE_52x40_mb8(out, Y, mod, k0) \ ifma_amm52x40_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ ifma_amm52x40_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ ifma_amm52x40_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x40_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x40_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x40_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #endif #define BITSIZE_MODULUS (2048) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,DIGIT_SIZE)) //40 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) //32 typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u* extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10= _mm512_load_si512(tbl[0][10]); __m512i X11= _mm512_load_si512(tbl[0][11]); __m512i X12= _mm512_load_si512(tbl[0][12]); __m512i X13= _mm512_load_si512(tbl[0][13]); __m512i X14= _mm512_load_si512(tbl[0][14]); __m512i X15= _mm512_load_si512(tbl[0][15]); __m512i X16= _mm512_load_si512(tbl[0][16]); __m512i X17= _mm512_load_si512(tbl[0][17]); __m512i X18= _mm512_load_si512(tbl[0][18]); __m512i X19= _mm512_load_si512(tbl[0][19]); __m512i X20= _mm512_load_si512(tbl[0][20]); __m512i X21= _mm512_load_si512(tbl[0][21]); __m512i X22= _mm512_load_si512(tbl[0][22]); __m512i X23= _mm512_load_si512(tbl[0][23]); __m512i X24= _mm512_load_si512(tbl[0][24]); __m512i X25= _mm512_load_si512(tbl[0][25]); __m512i X26= _mm512_load_si512(tbl[0][26]); __m512i X27= _mm512_load_si512(tbl[0][27]); __m512i X28= _mm512_load_si512(tbl[0][28]); __m512i X29= _mm512_load_si512(tbl[0][29]); __m512i X30= _mm512_load_si512(tbl[0][30]); __m512i X31= _mm512_load_si512(tbl[0][31]); __m512i X32= _mm512_load_si512(tbl[0][32]); __m512i X33= _mm512_load_si512(tbl[0][33]); __m512i X34= _mm512_load_si512(tbl[0][34]); __m512i X35= _mm512_load_si512(tbl[0][35]); __m512i X36= _mm512_load_si512(tbl[0][36]); __m512i X37= _mm512_load_si512(tbl[0][37]); __m512i X38= _mm512_load_si512(tbl[0][38]); __m512i X39= _mm512_load_si512(tbl[0][39]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for(n=1; n<(1<=0; exp_bit_no-=EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE==5 SQUARE_5x52x40_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #else SQUARE_52x40_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x40_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x40_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x40_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #endif /* extract pre-computed multiplier from the table */ { exp_chunk_no = exp_bit_no/64; exp_chunk_shift = exp_bit_no%64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no+1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64-exp_chunk_shift)); red_table_idx = _mm512_and_si512( _mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u*)(&red_table_idx)); } /* and multiply */ ifma_amm52x40_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); } } /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x40_mb8((int64u*)out, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); zero_mb8(red_Y, LEN52); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/ifma_exp3k_mb.c000066400000000000000000000352321470420105600274670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x60_mb8(out, Y, mod, k0) \ AMS52x60_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); #define SQUARE_5x52x60_mb8(out, Y, mod, k0) \ AMS52x60_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ AMS52x60_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x60_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x60_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x60_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #else #define SQUARE_52x60_mb8(out, Y, mod, k0) \ ifma_amm52x60_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); #define SQUARE_5x52x60_mb8(out, Y, mod, k0) \ ifma_amm52x60_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ ifma_amm52x60_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x60_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x60_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x60_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #endif #define BITSIZE_MODULUS (3072) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,DIGIT_SIZE)) //60 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) //48 typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u* extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10= _mm512_load_si512(tbl[0][10]); __m512i X11= _mm512_load_si512(tbl[0][11]); __m512i X12= _mm512_load_si512(tbl[0][12]); __m512i X13= _mm512_load_si512(tbl[0][13]); __m512i X14= _mm512_load_si512(tbl[0][14]); __m512i X15= _mm512_load_si512(tbl[0][15]); __m512i X16= _mm512_load_si512(tbl[0][16]); __m512i X17= _mm512_load_si512(tbl[0][17]); __m512i X18= _mm512_load_si512(tbl[0][18]); __m512i X19= _mm512_load_si512(tbl[0][19]); __m512i X20= _mm512_load_si512(tbl[0][20]); __m512i X21= _mm512_load_si512(tbl[0][21]); __m512i X22= _mm512_load_si512(tbl[0][22]); __m512i X23= _mm512_load_si512(tbl[0][23]); __m512i X24= _mm512_load_si512(tbl[0][24]); __m512i X25= _mm512_load_si512(tbl[0][25]); __m512i X26= _mm512_load_si512(tbl[0][26]); __m512i X27= _mm512_load_si512(tbl[0][27]); __m512i X28= _mm512_load_si512(tbl[0][28]); __m512i X29= _mm512_load_si512(tbl[0][29]); __m512i X30= _mm512_load_si512(tbl[0][30]); __m512i X31= _mm512_load_si512(tbl[0][31]); __m512i X32= _mm512_load_si512(tbl[0][32]); __m512i X33= _mm512_load_si512(tbl[0][33]); __m512i X34= _mm512_load_si512(tbl[0][34]); __m512i X35= _mm512_load_si512(tbl[0][35]); __m512i X36= _mm512_load_si512(tbl[0][36]); __m512i X37= _mm512_load_si512(tbl[0][37]); __m512i X38= _mm512_load_si512(tbl[0][38]); __m512i X39= _mm512_load_si512(tbl[0][39]); __m512i X40= _mm512_load_si512(tbl[0][40]); __m512i X41= _mm512_load_si512(tbl[0][41]); __m512i X42= _mm512_load_si512(tbl[0][42]); __m512i X43= _mm512_load_si512(tbl[0][43]); __m512i X44= _mm512_load_si512(tbl[0][44]); __m512i X45= _mm512_load_si512(tbl[0][45]); __m512i X46= _mm512_load_si512(tbl[0][46]); __m512i X47= _mm512_load_si512(tbl[0][47]); __m512i X48= _mm512_load_si512(tbl[0][48]); __m512i X49= _mm512_load_si512(tbl[0][49]); __m512i X50= _mm512_load_si512(tbl[0][50]); __m512i X51= _mm512_load_si512(tbl[0][51]); __m512i X52= _mm512_load_si512(tbl[0][52]); __m512i X53= _mm512_load_si512(tbl[0][53]); __m512i X54= _mm512_load_si512(tbl[0][54]); __m512i X55= _mm512_load_si512(tbl[0][55]); __m512i X56= _mm512_load_si512(tbl[0][56]); __m512i X57= _mm512_load_si512(tbl[0][57]); __m512i X58= _mm512_load_si512(tbl[0][58]); __m512i X59= _mm512_load_si512(tbl[0][59]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for(n=1; n<(1<=0; exp_bit_no-=EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE==5 SQUARE_5x52x60_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #else SQUARE_52x60_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x60_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x60_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x60_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #endif /* extract pre-computed multiplier from the table */ { exp_chunk_no = exp_bit_no/64; exp_chunk_shift = exp_bit_no%64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no+1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64-exp_chunk_shift)); red_table_idx = _mm512_and_si512( _mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u*)(&red_table_idx)); } /* and multiply */ ifma_amm52x60_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); } } /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x60_mb8((int64u*)out, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); zero_mb8(red_Y, LEN52); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/ifma_exp4k_mb.c000066400000000000000000000421571470420105600274740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x79_mb8(out, Y, mod, k0) \ AMS52x79_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); #define SQUARE_5x52x79_mb8(out, Y, mod, k0) \ AMS52x79_diagonal_mb8((int64u*)out, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ AMS52x79_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x79_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x79_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ AMS52x79_diagonal_mb8((int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #else #define SQUARE_52x79_mb8(out, Y, mod, k0) \ ifma_amm52x79_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); #define SQUARE_5x52x79_mb8(out, Y, mod, k0) \ ifma_amm52x79_mb8((int64u*)out, (int64u*)Y, (int64u*)Y, (int64u*)mod, (int64u*)k0); \ ifma_amm52x79_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x79_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x79_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); \ ifma_amm52x79_mb8((int64u*)out, (int64u*)out, (int64u*)out, (int64u*)mod, (int64u*)k0); #endif #define BITSIZE_MODULUS (4096) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,DIGIT_SIZE)) //79 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) //64 typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u* extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10= _mm512_load_si512(tbl[0][10]); __m512i X11= _mm512_load_si512(tbl[0][11]); __m512i X12= _mm512_load_si512(tbl[0][12]); __m512i X13= _mm512_load_si512(tbl[0][13]); __m512i X14= _mm512_load_si512(tbl[0][14]); __m512i X15= _mm512_load_si512(tbl[0][15]); __m512i X16= _mm512_load_si512(tbl[0][16]); __m512i X17= _mm512_load_si512(tbl[0][17]); __m512i X18= _mm512_load_si512(tbl[0][18]); __m512i X19= _mm512_load_si512(tbl[0][19]); __m512i X20= _mm512_load_si512(tbl[0][20]); __m512i X21= _mm512_load_si512(tbl[0][21]); __m512i X22= _mm512_load_si512(tbl[0][22]); __m512i X23= _mm512_load_si512(tbl[0][23]); __m512i X24= _mm512_load_si512(tbl[0][24]); __m512i X25= _mm512_load_si512(tbl[0][25]); __m512i X26= _mm512_load_si512(tbl[0][26]); __m512i X27= _mm512_load_si512(tbl[0][27]); __m512i X28= _mm512_load_si512(tbl[0][28]); __m512i X29= _mm512_load_si512(tbl[0][29]); __m512i X30= _mm512_load_si512(tbl[0][30]); __m512i X31= _mm512_load_si512(tbl[0][31]); __m512i X32= _mm512_load_si512(tbl[0][32]); __m512i X33= _mm512_load_si512(tbl[0][33]); __m512i X34= _mm512_load_si512(tbl[0][34]); __m512i X35= _mm512_load_si512(tbl[0][35]); __m512i X36= _mm512_load_si512(tbl[0][36]); __m512i X37= _mm512_load_si512(tbl[0][37]); __m512i X38= _mm512_load_si512(tbl[0][38]); __m512i X39= _mm512_load_si512(tbl[0][39]); __m512i X40= _mm512_load_si512(tbl[0][40]); __m512i X41= _mm512_load_si512(tbl[0][41]); __m512i X42= _mm512_load_si512(tbl[0][42]); __m512i X43= _mm512_load_si512(tbl[0][43]); __m512i X44= _mm512_load_si512(tbl[0][44]); __m512i X45= _mm512_load_si512(tbl[0][45]); __m512i X46= _mm512_load_si512(tbl[0][46]); __m512i X47= _mm512_load_si512(tbl[0][47]); __m512i X48= _mm512_load_si512(tbl[0][48]); __m512i X49= _mm512_load_si512(tbl[0][49]); __m512i X50= _mm512_load_si512(tbl[0][50]); __m512i X51= _mm512_load_si512(tbl[0][51]); __m512i X52= _mm512_load_si512(tbl[0][52]); __m512i X53= _mm512_load_si512(tbl[0][53]); __m512i X54= _mm512_load_si512(tbl[0][54]); __m512i X55= _mm512_load_si512(tbl[0][55]); __m512i X56= _mm512_load_si512(tbl[0][56]); __m512i X57= _mm512_load_si512(tbl[0][57]); __m512i X58= _mm512_load_si512(tbl[0][58]); __m512i X59= _mm512_load_si512(tbl[0][59]); __m512i X60= _mm512_load_si512(tbl[0][60]); __m512i X61= _mm512_load_si512(tbl[0][61]); __m512i X62= _mm512_load_si512(tbl[0][62]); __m512i X63= _mm512_load_si512(tbl[0][63]); __m512i X64= _mm512_load_si512(tbl[0][64]); __m512i X65= _mm512_load_si512(tbl[0][65]); __m512i X66= _mm512_load_si512(tbl[0][66]); __m512i X67= _mm512_load_si512(tbl[0][67]); __m512i X68= _mm512_load_si512(tbl[0][68]); __m512i X69= _mm512_load_si512(tbl[0][69]); __m512i X70= _mm512_load_si512(tbl[0][70]); __m512i X71= _mm512_load_si512(tbl[0][71]); __m512i X72= _mm512_load_si512(tbl[0][72]); __m512i X73= _mm512_load_si512(tbl[0][73]); __m512i X74= _mm512_load_si512(tbl[0][74]); __m512i X75= _mm512_load_si512(tbl[0][75]); __m512i X76= _mm512_load_si512(tbl[0][76]); __m512i X77= _mm512_load_si512(tbl[0][77]); __m512i X78= _mm512_load_si512(tbl[0][78]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for(n=1; n<(1<=0; exp_bit_no-=EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE==5 SQUARE_5x52x79_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #else SQUARE_52x79_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x79_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x79_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); SQUARE_52x79_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)modulus, (int64u*)k0); #endif /* extract pre-computed multiplier from the table */ { exp_chunk_no = exp_bit_no/64; exp_chunk_shift = exp_bit_no%64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no+1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64-exp_chunk_shift)); red_table_idx = _mm512_and_si512( _mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u*)(&red_table_idx)); } /* and multiply */ ifma_amm52x79_mb8((int64u*)red_Y, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); } } /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x79_mb8((int64u*)out, (int64u*)red_Y, (int64u*)red_X, (int64u*)modulus, (int64u*)k0); zero_mb8(red_Y, LEN52); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/ifma_exp_mb.c000066400000000000000000000215751470420105600272360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status ifma_exp_mb(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, exp_mb8 expfunc, int8u* pBuffer, int bufferLen) { mbx_status status = MBX_STATUS_OK; /* test input pointers */ if (NULL==out_pa || NULL==base_pa || NULL==exp_pa || NULL==mod_pa || NULL==expfunc || NULL== pBuffer) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test exp length */ if (exp_bits > mod_bits) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* test length of buffer */ int bufferMinLen = mbx_exp_BufferSize(mod_bits); if (bufferLen < bufferMinLen) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ int buf_no; for (buf_no = 0; buf_no < 8; buf_no++) { int64u* out = out_pa[buf_no]; const int64u* base = base_pa[buf_no]; const int64u* exp = exp_pa[buf_no]; const int64u* mod = mod_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == out || NULL == base || NULL == exp || NULL == mod) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } /* // processing */ if (MBX_IS_ANY_OK_STS(status)) { int len52 = NUMBER_OF_DIGITS(mod_bits, DIGIT_SIZE); int len64 = NUMBER_OF_DIGITS(mod_bits, 64); /* 64-byte aligned buffer of int64[8] */ pint64u_x8 pBuffer_x8 = (pint64u_x8)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb8 buffers */ pint64u_x8 k0_mb8 = pBuffer_x8; pint64u_x8 expz_mb8 = k0_mb8 + 1; pint64u_x8 rr_mb8 = expz_mb8 + (len64+1); pint64u_x8 inout_mb8 = rr_mb8 + len52; pint64u_x8 mod_mb8 = inout_mb8 + len52; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ pint64u_x8 work_buffer = mod_mb8 + MULTIPLE_OF(len52, 10); /* convert modulus to ifma fmt */ zero_mb8(mod_mb8, MULTIPLE_OF(len52, 10)); ifma_BNU_to_mb8(mod_mb8, mod_pa, mod_bits); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8[0], mod_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, mod_mb8, mod_bits); /* convert input to ifma fmt */ ifma_BNU_to_mb8(inout_mb8, base_pa, mod_bits); /* re-arrange exps to ifma */ zero_mb8(expz_mb8, len64+1); ifma_BNU_transpose_copy(expz_mb8, exp_pa, exp_bits); /* exponentiation */ expfunc(inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])expz_mb8, exp_bits, (const int64u(*)[8])mod_mb8, (const int64u(*)[8])rr_mb8, k0_mb8[0], (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_BNU(out_pa, (const int64u(*)[8])inout_mb8, mod_bits); /* clear exponents */ zero_mb8(expz_mb8, len64); } return status; } #endif /* #if (_MBX>=_MBX_K1) */ DLL_PUBLIC mbx_status OWNAPI(mbx_exp1024_mb8)(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen) { mbx_status status = MBX_STATUS_OK; /* test exp modulus range */ if(EXP_MODULUS_1024 != bits_range(mod_bits)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) /* 1k exponentiation */ status |= ifma_exp_mb(out_pa, base_pa, exp_pa, exp_bits, mod_pa, mod_bits, ifma_modexp1024_mb, pBuffer, bufferLen); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_exp2048_mb8)(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen) { mbx_status status = MBX_STATUS_OK; /* test exp modulus range */ if(EXP_MODULUS_2048 != bits_range(mod_bits)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) /* 2k exponentiation */ status |= ifma_exp_mb(out_pa, base_pa, exp_pa, exp_bits, mod_pa, mod_bits, ifma_modexp2048_mb, pBuffer, bufferLen); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_exp3072_mb8)(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen) { mbx_status status = MBX_STATUS_OK; /* test exp modulus range */ if(EXP_MODULUS_3072 != bits_range(mod_bits)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) /* 3k exponentiation */ status |= ifma_exp_mb(out_pa, base_pa, exp_pa, exp_bits, mod_pa, mod_bits, ifma_modexp3072_mb, pBuffer, bufferLen); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_exp4096_mb8)(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen) { mbx_status status = MBX_STATUS_OK; /* test exp modulus range */ if(EXP_MODULUS_4096 != bits_range(mod_bits)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) /* 4k exponentiation */ status |= ifma_exp_mb(out_pa, base_pa, exp_pa, exp_bits, mod_pa, mod_bits, ifma_modexp4096_mb, pBuffer, bufferLen); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_exp_mb8)(int64u* const out_pa[8], const int64u* const base_pa[8], const int64u* const exp_pa[8], int exp_bits, const int64u* const mod_pa[8], int mod_bits, int8u* pBuffer, int bufferLen) { mbx_status status = MBX_STATUS_OK; /* test exp modulus range */ int modulus_range = bits_range(mod_bits); if(0 == modulus_range) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } // // processing // #if (_MBX>=_MBX_K1) exp_mb8 expfunc = NULL; switch (modulus_range) { case EXP_MODULUS_1024: expfunc = ifma_modexp1024_mb; break; case EXP_MODULUS_2048: expfunc = ifma_modexp2048_mb; break; case EXP_MODULUS_3072: expfunc = ifma_modexp3072_mb; break; case EXP_MODULUS_4096: expfunc = ifma_modexp4096_mb; break; default: break; } status |= ifma_exp_mb(out_pa, base_pa, exp_pa, exp_bits, mod_pa, mod_bits, expfunc, pBuffer, bufferLen); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/exp/ifma_exp_method.c000066400000000000000000000052551470420105600301150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 /* map exp modulus bit size to exp modulus range */ int bits_range(int modulusBits) { int modulusLen = (NUMBER_OF_DIGITS(modulusBits, DIGIT_SIZE)); int modulusLen_top = (NUMBER_OF_DIGITS(modulusBits+2, DIGIT_SIZE)); if(modulusLen != modulusLen_top) return EXP_MODULUS_UNSUPPORT; switch (modulusLen) { case NUMBER_OF_DIGITS(EXP_MODULUS_1024, DIGIT_SIZE): return EXP_MODULUS_1024; case NUMBER_OF_DIGITS(EXP_MODULUS_2048, DIGIT_SIZE): return EXP_MODULUS_2048; case NUMBER_OF_DIGITS(EXP_MODULUS_3072, DIGIT_SIZE): return EXP_MODULUS_3072; case NUMBER_OF_DIGITS(EXP_MODULUS_4096, DIGIT_SIZE): return EXP_MODULUS_4096; default: return EXP_MODULUS_UNSUPPORT; } } /* size of scratch buffer */ DLL_PUBLIC int OWNAPI(mbx_exp_BufferSize)(int modulusBits) { #if (_MBX>=_MBX_K1) int modulusRange = bits_range(modulusBits); if(modulusRange) { int len52 = NUMBER_OF_DIGITS(modulusRange, DIGIT_SIZE); int len64 = NUMBER_OF_DIGITS(modulusRange, 64); int bufferSize = (8 /* alignment*/ /* ifma_mont_exp_mb */ +1*8 /* k0 */ +(len64+1+1)*8 /* expz */ +len52*8 /* rr */ +len52*8 /* inp_out */ + MULTIPLE_OF(len52, 10)*8 /* modulus */ /* ifma_exp1/2/3/4k_mb */ +len52*8 /* Y */ +len52*8 /* X */ +(1 << EXP_WIN_SIZE) * len52*8 /* pre-computed table*/ ) * sizeof(int64u); return bufferSize; } else return 0; #else return 0; #endif /* #if (_MBX>=_MBX_K1) */ } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/000077500000000000000000000000001470420105600257745ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/common.c000066400000000000000000000021731470420105600274330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include int mbx_is_mem_eq(const int8u *p1, int32u p1_byte_len, const int8u *p2, int32u p2_byte_len) { if ((p1_byte_len != p2_byte_len) || (p1 == NULL) || (p2 == NULL)) { return 0; } while (p1_byte_len) { if (*p1 != *p2) { return 0; } ++p1; ++p2; --p1_byte_len; } return 1; } #endif // MBX_FIPS_MODE selftest_mbx_ed25519_public_key_mb8.c000066400000000000000000000121661470420105600346200ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* Pairwise Consistency Test for ED25519 keypair */ /* KAT data taken from wycheproof testing */ /* msg len */ #define MSG_LEN (16) /* msg */ static const int8u msg[MSG_LEN] = {0}; /* output public key */ static ed25519_public_key out_pub_key[MBX_LANES]; /* output signature */ static ed25519_sign_component out_r[MBX_LANES]; static ed25519_sign_component out_s[MBX_LANES]; /* private key */ static const ed25519_private_key prv_key = {0xad,0xd4,0xbb,0x81,0x03,0x78,0x5b,0xaf, 0x9a,0xc5,0x34,0x25,0x8e,0x8a,0xaf,0x65, 0xf5,0xf1,0xad,0xb5,0xef,0x5f,0x3d,0xf1, 0x9b,0xb8,0x0a,0xb9,0x89,0xc4,0xd6,0x4b}; DLL_PUBLIC fips_test_status fips_selftest_mbx_ed25519_public_key_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* functions input parameters */ // msg const int8u *const pa_msg[MBX_LANES] = { msg, msg, msg, msg, msg, msg, msg, msg}; // msg len const int32u pa_msg_len[MBX_LANES] = { MSG_LEN, MSG_LEN, MSG_LEN, MSG_LEN, MSG_LEN, MSG_LEN, MSG_LEN, MSG_LEN}; // private key const ed25519_private_key *const pa_prv_key[MBX_LANES] = { (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key}; /* functions output parameters */ // output public key ed25519_public_key *pa_out_pub_key[MBX_LANES] = { (ed25519_public_key *)out_pub_key[0], (ed25519_public_key *)out_pub_key[1], (ed25519_public_key *)out_pub_key[2], (ed25519_public_key *)out_pub_key[3], (ed25519_public_key *)out_pub_key[4], (ed25519_public_key *)out_pub_key[5], (ed25519_public_key *)out_pub_key[6], (ed25519_public_key *)out_pub_key[7]}; // output signature components ed25519_sign_component *pa_sign_r[MBX_LANES] = { (ed25519_sign_component *)out_r[0], (ed25519_sign_component *)out_r[1], (ed25519_sign_component *)out_r[2], (ed25519_sign_component *)out_r[3], (ed25519_sign_component *)out_r[4], (ed25519_sign_component *)out_r[5], (ed25519_sign_component *)out_r[6], (ed25519_sign_component *)out_r[7]}; ed25519_sign_component *pa_sign_s[MBX_LANES] = { (ed25519_sign_component *)out_s[0], (ed25519_sign_component *)out_s[1], (ed25519_sign_component *)out_s[2], (ed25519_sign_component *)out_s[3], (ed25519_sign_component *)out_s[4], (ed25519_sign_component *)out_s[5], (ed25519_sign_component *)out_s[6], (ed25519_sign_component *)out_s[7]}; /* test functions */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; // generate public key sts = mbx_ed25519_public_key_mb8(pa_out_pub_key, pa_prv_key); if (sts != expected_status_mb8) { if(sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; return test_result; } test_result = MBX_ALGO_SELFTEST_KAT_ERR; return test_result; } // sign and verify with the generated keypair sts = mbx_ed25519_sign_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_msg_len, pa_prv_key, (const ed25519_public_key* const*)pa_out_pub_key); if (sts != expected_status_mb8) { if(sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; return test_result; } test_result = MBX_ALGO_SELFTEST_KAT_ERR; return test_result; } sts = mbx_ed25519_verify_mb8((const ed25519_sign_component* const*)pa_sign_r, (const ed25519_sign_component* const*)pa_sign_s, pa_msg, pa_msg_len, (const ed25519_public_key* const*)pa_out_pub_key); // check the result of verification if (sts != expected_status_mb8) { if(sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; return test_result; } test_result = MBX_ALGO_SELFTEST_KAT_ERR; return test_result; } return test_result; } #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_ed25519_sign_mb8.c000066400000000000000000000131221470420105600335020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from wycheproof testing) */ /* msg len */ static const int32u msg_len = 0; /* msg */ static const int8u msg[] = {0}; /* public key */ static const ed25519_public_key pub_key = {0x7d,0x4d,0x0e,0x7f,0x61,0x53,0xa6,0x9b, 0x62,0x42,0xb5,0x22,0xab,0xbe,0xe6,0x85, 0xfd,0xa4,0x42,0x0f,0x88,0x34,0xb1,0x08, 0xc3,0xbd,0xae,0x36,0x9e,0xf5,0x49,0xfa}; /* private key */ static const ed25519_private_key prv_key = {0xad,0xd4,0xbb,0x81,0x03,0x78,0x5b,0xaf, 0x9a,0xc5,0x34,0x25,0x8e,0x8a,0xaf,0x65, 0xf5,0xf1,0xad,0xb5,0xef,0x5f,0x3d,0xf1, 0x9b,0xb8,0x0a,0xb9,0x89,0xc4,0xd6,0x4b}; /* signature */ static const ed25519_sign_component r = {0xd4,0xfb,0xdb,0x52,0xbf,0xa7,0x26,0xb4, 0x4d,0x17,0x86,0xa8,0xc0,0xd1,0x71,0xc3, 0xe6,0x2c,0xa8,0x3c,0x9e,0x5b,0xbe,0x63, 0xde,0x0b,0xb2,0x48,0x3f,0x8f,0xd6,0xcc}; static const ed25519_sign_component s = {0x14,0x29,0xab,0x72,0xca,0xfc,0x41,0xab, 0x56,0xaf,0x02,0xff,0x8f,0xcc,0x43,0xb9, 0x9b,0xfe,0x4c,0x7a,0xe9,0x40,0xf6,0x0f, 0x38,0xeb,0xaa,0x9d,0x31,0x1c,0x40,0x07}; DLL_PUBLIC fips_test_status fips_selftest_mbx_ed25519_sign_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output signature */ ed25519_sign_component out_r[MBX_LANES]; ed25519_sign_component out_s[MBX_LANES]; /* function input parameters */ // msg const int8u *const pa_msg[MBX_LANES] = { msg, msg, msg, msg, msg, msg, msg, msg}; // msg len const int32u pa_msg_len[MBX_LANES] = { msg_len, msg_len, msg_len, msg_len, msg_len, msg_len, msg_len, msg_len}; // public key const ed25519_public_key *const pa_pub_key[MBX_LANES] = { (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key}; // private key const ed25519_private_key *const pa_prv_key[MBX_LANES] = { (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key, (const ed25519_private_key *const)prv_key}; // output signature ed25519_sign_component *pa_sign_r[MBX_LANES] = { (ed25519_sign_component *)out_r[0], (ed25519_sign_component *)out_r[1], (ed25519_sign_component *)out_r[2], (ed25519_sign_component *)out_r[3], (ed25519_sign_component *)out_r[4], (ed25519_sign_component *)out_r[5], (ed25519_sign_component *)out_r[6], (ed25519_sign_component *)out_r[7]}; ed25519_sign_component *pa_sign_s[MBX_LANES] = { (ed25519_sign_component *)out_s[0], (ed25519_sign_component *)out_s[1], (ed25519_sign_component *)out_s[2], (ed25519_sign_component *)out_s[3], (ed25519_sign_component *)out_s[4], (ed25519_sign_component *)out_s[5], (ed25519_sign_component *)out_s[6], (ed25519_sign_component *)out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_ed25519_sign_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_msg_len, pa_prv_key, pa_pub_key); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer int r_output_status; int s_output_status; for (int j = 0; (j < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++j) { r_output_status = mbx_is_mem_eq((const int8u *)pa_sign_r[j], MBX_ED25519_DATA_BYTE_LEN, (const int8u *) r, MBX_ED25519_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq((const int8u *)pa_sign_s[j], MBX_ED25519_DATA_BYTE_LEN, (const int8u *) s, MBX_ED25519_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #endif // MBX_FIPS_MODE selftest_mbx_ed25519_verify_mb8.c000066400000000000000000000101641470420105600337720ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from wycheproof testing) */ /* msg len */ static const int32u msg_len = 0; /* msg */ static const int8u msg[] = {0}; /* public key */ static const ed25519_public_key pub_key = {0x7d,0x4d,0x0e,0x7f,0x61,0x53,0xa6,0x9b, 0x62,0x42,0xb5,0x22,0xab,0xbe,0xe6,0x85, 0xfd,0xa4,0x42,0x0f,0x88,0x34,0xb1,0x08, 0xc3,0xbd,0xae,0x36,0x9e,0xf5,0x49,0xfa}; /* signature */ static const ed25519_sign_component r = {0xd4,0xfb,0xdb,0x52,0xbf,0xa7,0x26,0xb4, 0x4d,0x17,0x86,0xa8,0xc0,0xd1,0x71,0xc3, 0xe6,0x2c,0xa8,0x3c,0x9e,0x5b,0xbe,0x63, 0xde,0x0b,0xb2,0x48,0x3f,0x8f,0xd6,0xcc}; static const ed25519_sign_component s = {0x14,0x29,0xab,0x72,0xca,0xfc,0x41,0xab, 0x56,0xaf,0x02,0xff,0x8f,0xcc,0x43,0xb9, 0x9b,0xfe,0x4c,0x7a,0xe9,0x40,0xf6,0x0f, 0x38,0xeb,0xaa,0x9d,0x31,0x1c,0x40,0x07}; DLL_PUBLIC fips_test_status fips_selftest_mbx_ed25519_verify_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // msg const int8u *const pa_msg[MBX_LANES] = { msg, msg, msg, msg, msg, msg, msg, msg}; // msg len const int32u pa_msg_len[MBX_LANES] = { msg_len, msg_len, msg_len, msg_len, msg_len, msg_len, msg_len, msg_len}; // public key const ed25519_public_key *const pa_pub_key[MBX_LANES] = { (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key, (const ed25519_public_key *const)pub_key}; // output signature const ed25519_sign_component *const pa_sign_r[MBX_LANES] = { (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r, (const ed25519_sign_component *const)r}; const ed25519_sign_component *const pa_sign_s[MBX_LANES] = { (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s, (const ed25519_sign_component *const)s}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_ed25519_verify_mb8(pa_sign_r, pa_sign_s, pa_msg, pa_msg_len, pa_pub_key); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; return test_result; } test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_nistp256_ecdh_mb8.c000066400000000000000000000157011470420105600340460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from wycheproof testing) */ /* public */ static const int8u pub_x[MBX_NISTP256_DATA_BYTE_LEN] = {0x26,0x4f,0xe4,0xaf,0x31,0xd7,0x61,0xfa, 0xfd,0x0b,0x8b,0x86,0x46,0x70,0xe0,0x28, 0x24,0x50,0x0f,0x5d,0x71,0x40,0xa0,0x85, 0xfe,0x75,0xaf,0x72,0x33,0xbd,0xd5,0x62}; static const int8u pub_y[MBX_NISTP256_DATA_BYTE_LEN] = {0xcf,0x30,0x4e,0x01,0x5a,0x27,0x7d,0xa0, 0xb4,0x72,0x88,0xc3,0xc8,0x41,0xb7,0x0e, 0x99,0x13,0x8d,0xbf,0xb5,0x95,0x5a,0xcd, 0x81,0x0a,0xe7,0xa9,0x93,0x3a,0x33,0xac}; /* private */ static const int8u prv_key[MBX_NISTP256_DATA_BYTE_LEN] = {0x46,0xc3,0x10,0x2c,0xe0,0x52,0x53,0x7b, 0x64,0x38,0x41,0xf8,0xae,0x53,0xbb,0xfe, 0xd3,0xbf,0xce,0x6b,0x0a,0x5b,0x85,0x17, 0xab,0x23,0xa0,0x89,0x5c,0x46,0x12,0x06}; /* shared key */ static const int8u sh_key[MBX_NISTP256_DATA_BYTE_LEN] = {0x53,0x02,0x0d,0x90,0x8b,0x02,0x19,0x32, 0x8b,0x65,0x8b,0x52,0x5f,0x26,0x78,0x0e, 0x3a,0xe1,0x2b,0xcd,0x95,0x2b,0xb2,0x5a, 0x93,0xbc,0x08,0x95,0xe1,0x71,0x42,0x85}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdh_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* function input parameters */ // shared int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; // private const int64u *pa_prv_key[MBX_LANES] = { (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key}; // public const int64u *pa_pub_x[MBX_LANES] = { (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x}; const int64u *pa_pub_y[MBX_LANES] = { (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp256_ecdh_mb8(pa_shared_key, pa_prv_key, pa_pub_x, pa_pub_y, NULL, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output shared key to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_shared_key[i], MBX_NISTP256_DATA_BYTE_LEN, sh_key, MBX_NISTP256_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdh_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* ssl public key */ BIGNUM *BN_pub_x = BN_new(); BIGNUM *BN_pub_y = BN_new(); /* ssl private key */ BIGNUM *BN_prv_key = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_pub_x || NULL == BN_pub_y || NULL == BN_prv_key) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_pub_x, BN_pub_y, BN_prv_key) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; // set ssl keys BN_lebin2bn(pub_x, MBX_NISTP256_DATA_BYTE_LEN, BN_pub_x); BN_lebin2bn(pub_y, MBX_NISTP256_DATA_BYTE_LEN, BN_pub_y); BN_lebin2bn(prv_key, MBX_NISTP256_DATA_BYTE_LEN, BN_prv_key); /* function input parameters */ // output shared key int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; // private const BIGNUM *pa_prv_key[MBX_LANES] = { BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key}; // public const BIGNUM *pa_pub_x[MBX_LANES] = { BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x}; const BIGNUM *pa_pub_y[MBX_LANES] = { BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y}; /* test function */ sts = mbx_nistp256_ecdh_ssl_mb8(pa_shared_key, pa_prv_key, pa_pub_x, pa_pub_y, NULL, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output shared key to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_shared_key[i], MBX_NISTP256_DATA_BYTE_LEN, sh_key, MBX_NISTP256_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_pub_x, BN_pub_y, BN_prv_key) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp256_ecdsa_sign_mb8.c000066400000000000000000000177221470420105600351700ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf" // "416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5" // "473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17c" // "c934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8" /* msgDigest == SHA-256(msg) */ static const int8u msg_digest[MBX_NISTP256_DATA_BYTE_LEN] = {0x44,0xac,0xf6,0xb7,0xe3,0x6c,0x13,0x42, 0xc2,0xc5,0x89,0x72,0x04,0xfe,0x09,0x50, 0x4e,0x1e,0x2e,0xfb,0x1a,0x90,0x03,0x77, 0xdb,0xc4,0xe7,0xa6,0xa1,0x33,0xec,0x56}; /* key pair */ static const int8u d[MBX_NISTP256_DATA_BYTE_LEN] = {0x64,0xb4,0x72,0xda,0x6d,0xa5,0x54,0xca, 0xac,0x3e,0x4e,0x0b,0x13,0xc8,0x44,0x5b, 0x1a,0x77,0xf4,0x59,0xee,0xa8,0x4f,0x1f, 0x58,0x8b,0x5f,0x71,0x3d,0x42,0x9b,0x51}; static const int8u k[MBX_NISTP256_DATA_BYTE_LEN] = {0xde,0x68,0x2a,0x64,0x87,0x07,0x67,0xb9, 0x33,0x5d,0x4f,0x82,0x47,0x62,0x4a,0x3b, 0x7f,0x3c,0xe9,0xf9,0x45,0xf2,0x80,0xa2, 0x61,0x6a,0x90,0x4b,0xb1,0xbb,0xa1,0x94}; /* signature */ static const int8u r[MBX_NISTP256_DATA_BYTE_LEN] = {0xf3,0xac,0x80,0x61,0xb5,0x14,0x79,0x5b, 0x88,0x43,0xe3,0xd6,0x62,0x95,0x27,0xed, 0x2a,0xfd,0x6b,0x1f,0x6a,0x55,0x5a,0x7a, 0xca,0xbb,0x5e,0x6f,0x79,0xc8,0xc2,0xac}; static const int8u s[MBX_NISTP256_DATA_BYTE_LEN] = {0x8b,0xf7,0x78,0x19,0xca,0x05,0xa6,0xb2, 0x78,0x6c,0x76,0x26,0x2b,0xf7,0x37,0x1c, 0xef,0x97,0xb2,0x18,0xe9,0x6f,0x17,0x5a, 0x3c,0xcd,0xda,0x2a,0xcc,0x05,0x89,0x03}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp256_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (expected_status_mb8 != sts) { if(sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer int r_output_status; int s_output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP256_DATA_BYTE_LEN, r, MBX_NISTP256_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP256_DATA_BYTE_LEN, s, MBX_NISTP256_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl key pair */ BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_k) return test_result; } /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity statuses */ int r_output_status; int s_output_status; // set ssl key pair BN_lebin2bn(d, MBX_NISTP256_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP256_DATA_BYTE_LEN, BN_k); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const BIGNUM *pa_prv_d[MBX_LANES] = {BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d}; const BIGNUM *pa_prv_k[MBX_LANES] = {BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ sts = mbx_nistp256_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (expected_status_mb8 != sts) { if(sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP256_DATA_BYTE_LEN, r, MBX_NISTP256_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP256_DATA_BYTE_LEN, s, MBX_NISTP256_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8.c000066400000000000000000000253121470420105600402720ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf" // "416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5" // "473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17c" // "c934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8" /* msgDigest == SHA-256(msg) */ static const int8u msg_digest[MBX_NISTP256_DATA_BYTE_LEN] = {0x44,0xac,0xf6,0xb7,0xe3,0x6c,0x13,0x42, 0xc2,0xc5,0x89,0x72,0x04,0xfe,0x09,0x50, 0x4e,0x1e,0x2e,0xfb,0x1a,0x90,0x03,0x77, 0xdb,0xc4,0xe7,0xa6,0xa1,0x33,0xec,0x56}; /* key pair */ static const int8u d[MBX_NISTP256_DATA_BYTE_LEN] = {0x64,0xb4,0x72,0xda,0x6d,0xa5,0x54,0xca, 0xac,0x3e,0x4e,0x0b,0x13,0xc8,0x44,0x5b, 0x1a,0x77,0xf4,0x59,0xee,0xa8,0x4f,0x1f, 0x58,0x8b,0x5f,0x71,0x3d,0x42,0x9b,0x51}; static const int8u k[MBX_NISTP256_DATA_BYTE_LEN] = {0xde,0x68,0x2a,0x64,0x87,0x07,0x67,0xb9, 0x33,0x5d,0x4f,0x82,0x47,0x62,0x4a,0x3b, 0x7f,0x3c,0xe9,0xf9,0x45,0xf2,0x80,0xa2, 0x61,0x6a,0x90,0x4b,0xb1,0xbb,0xa1,0x94}; /* signature */ static const int8u r[MBX_NISTP256_DATA_BYTE_LEN] = {0xf3,0xac,0x80,0x61,0xb5,0x14,0x79,0x5b, 0x88,0x43,0xe3,0xd6,0x62,0x95,0x27,0xed, 0x2a,0xfd,0x6b,0x1f,0x6a,0x55,0x5a,0x7a, 0xca,0xbb,0x5e,0x6f,0x79,0xc8,0xc2,0xac}; static const int8u s[MBX_NISTP256_DATA_BYTE_LEN] = {0x8b,0xf7,0x78,0x19,0xca,0x05,0xa6,0xb2, 0x78,0x6c,0x76,0x26,0x2b,0xf7,0x37,0x1c, 0xef,0x97,0xb2,0x18,0xe9,0x6f,0x17,0x5a, 0x3c,0xcd,0xda,0x2a,0xcc,0x05,0x89,0x03}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* k key inversion */ int8u inv_k[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* precomputed r signature component */ int8u precomp_r[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // k key inversion int64u *pa_inv_k[MBX_LANES] = {(int64u *)inv_k[0], (int64u *)inv_k[1], (int64u *)inv_k[2], (int64u *)inv_k[3], (int64u *)inv_k[4], (int64u *)inv_k[5], (int64u *)inv_k[6], (int64u *)inv_k[7]}; // precomputed r signature component int64u *pa_precomp_r[MBX_LANES] = { (int64u *)precomp_r[0], (int64u *)precomp_r[1], (int64u *)precomp_r[2], (int64u *)precomp_r[3], (int64u *)precomp_r[4], (int64u *)precomp_r[5], (int64u *)precomp_r[6], (int64u *)precomp_r[7]}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; // sign setup sts = mbx_nistp256_ecdsa_sign_setup_mb8(pa_inv_k, pa_precomp_r, pa_prv_k, NULL); if(sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; return test_result; } test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; return test_result; } // sign complete sts = mbx_nistp256_ecdsa_sign_complete_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, (const int64u *const *)pa_precomp_r, (const int64u *const *)pa_inv_k, pa_prv_d, NULL); if(sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; return test_result; } test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; return test_result; } // compare output signature to known answer int r_output_status; int s_output_status; for (int i = 0; i < MBX_LANES; ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP256_DATA_BYTE_LEN, r, MBX_NISTP256_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP256_DATA_BYTE_LEN, s, MBX_NISTP256_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; break; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR_ARR1, BN_PTR_ARR2, BN_PTR3, BN_PTR4) { \ for (int i = 0; i < MBX_LANES; ++i) { \ BN_free(BN_PTR_ARR1[i]); \ BN_free(BN_PTR_ARR2[i]); \ } \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdsa_sign_setup_complete_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl key pair */ BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); /* k key inversion */ BIGNUM *pa_inv_k[MBX_LANES] = {BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; /* precomputed r signature component */ BIGNUM *pa_precomp_r[MBX_LANES] = {BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i ) { if(NULL == pa_inv_k[i] || NULL == pa_precomp_r[i]) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } if(MBX_ALGO_SELFTEST_OK != test_result) { MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity statuses */ int r_output_status; int s_output_status; // set ssl key pair BN_lebin2bn(d, MBX_NISTP256_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP256_DATA_BYTE_LEN, BN_k); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const BIGNUM *pa_prv_d[MBX_LANES] = {BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d}; const BIGNUM *pa_prv_k[MBX_LANES] = {BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ // sign setup sts = mbx_nistp256_ecdsa_sign_setup_ssl_mb8(pa_inv_k, pa_precomp_r, pa_prv_k, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } // sign complete sts = mbx_nistp256_ecdsa_sign_complete_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, (const BIGNUM *const *)pa_precomp_r, (const BIGNUM *const *)pa_inv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } // compare output signature to known answer for (int i = 0; i < MBX_LANES; ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP256_DATA_BYTE_LEN, r, MBX_NISTP256_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP256_DATA_BYTE_LEN, s, MBX_NISTP256_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; break; } } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp256_ecdsa_verify_mb8.c000066400000000000000000000162401470420105600355260ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #ifndef BN_OPENSSL_DISABLE #include #endif /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "e1130af6a38ccb412a9c8d13e15dbfc9e69a16385af3c3f1e5da954fd5e7c45f" // "d75e2b8c36699228e92840c0562fbf3772f07e17f1add56588dd45f7450e1217" // "ad239922dd9c32695dc71ff2424ca0dec1321aa47064a044b7fe3c2b97d03ce4" // "70a592304c5ef21eed9f93da56bb232d1eeb0035f9bf0dfafdcc4606272b20a3" /* msgDigest == SHA-256(msg) */ static const int8u msg_digest[MBX_NISTP256_DATA_BYTE_LEN] = {0xd1,0xb8,0xef,0x21,0xeb,0x41,0x82,0xee, 0x27,0x06,0x38,0x06,0x10,0x63,0xa3,0xf3, 0xc1,0x6c,0x11,0x4e,0x33,0x93,0x7f,0x69, 0xfb,0x23,0x2c,0xc8,0x33,0x96,0x5a,0x94}; /* public key */ static const int8u Qx[MBX_NISTP256_DATA_BYTE_LEN] = {0x3c,0xbf,0x9a,0xf4,0x12,0x6e,0x2e,0xf8, 0x74,0xc0,0x67,0x7a,0x6f,0xe1,0x34,0x51, 0x0c,0x7a,0x95,0xf8,0xa7,0x44,0x43,0xef, 0xb7,0x3c,0xbb,0xd4,0x61,0xdc,0x24,0xe4}; static const int8u Qy[MBX_NISTP256_DATA_BYTE_LEN] = {0x27,0xe9,0xae,0xdf,0xe7,0x60,0x6f,0x3d, 0x24,0xd1,0x85,0xac,0x65,0x59,0x7e,0x12, 0xf0,0xda,0xdd,0xe1,0x9d,0x94,0x45,0x15, 0x65,0x48,0xbc,0xa2,0x7a,0xed,0x0e,0x97}; /* signature */ static const int8u r[MBX_NISTP256_DATA_BYTE_LEN] = {0xbf,0x96,0xb9,0x9a,0xa4,0x9c,0x70,0x5c, 0x91,0x0b,0xe3,0x31,0x42,0x01,0x7c,0x64, 0x2f,0xf5,0x40,0xc7,0x63,0x49,0xb9,0xda, 0xb7,0x2f,0x98,0x1f,0xd9,0x34,0x7f,0x4f}; static const int8u s[MBX_NISTP256_DATA_BYTE_LEN] = {0x17,0xc5,0x50,0x95,0x81,0x90,0x89,0xc2, 0xe0,0x3b,0x9c,0xd4,0x15,0xab,0xdf,0x12, 0x44,0x4e,0x32,0x30,0x75,0xd9,0x8f,0x31, 0x92,0x0b,0x9e,0x0f,0x57,0xec,0x87,0x1c}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdsa_verify_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // public key const int64u *const pa_pub_Qx[MBX_LANES] = { (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx}; const int64u *const pa_pub_Qy[MBX_LANES] = { (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy}; // KAT signature const int8u *const pa_sign_r[MBX_LANES] = {r, r, r, r, r, r, r, r}; const int8u *const pa_sign_s[MBX_LANES] = {s, s, s, s, s, s, s, s}; /* test function */ mbx_status expected_sts_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp256_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_pub_Qx, pa_pub_Qy, NULL, NULL); if (expected_sts_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2, SIG_PTR1) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ ECDSA_SIG_free(SIG_PTR1); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecdsa_verify_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl public key */ BIGNUM *BN_Qx = BN_new(); BIGNUM *BN_Qy = BN_new(); // ssl signature BIGNUM *BN_r = BN_new(); BIGNUM *BN_s = BN_new(); ECDSA_SIG *sig = ECDSA_SIG_new(); /* check if allocated memory is valid */ if(NULL == BN_Qx || NULL == BN_Qy || NULL == BN_r || NULL == BN_s || NULL == sig) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_Qx, BN_Qy, sig) // Handled separately, since memory management of // these variables is transferred to sig below BN_free(BN_r); BN_free(BN_s); return test_result; } // set ssl public key and signature BN_lebin2bn(Qx, MBX_NISTP256_DATA_BYTE_LEN, BN_Qx); BN_lebin2bn(Qy, MBX_NISTP256_DATA_BYTE_LEN, BN_Qy); BN_bin2bn(r, MBX_NISTP256_DATA_BYTE_LEN, BN_r); BN_bin2bn(s, MBX_NISTP256_DATA_BYTE_LEN, BN_s); ECDSA_SIG_set0(sig, BN_r, BN_s); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // public key const BIGNUM *const pa_pub_Qx[MBX_LANES] = {BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx}; const BIGNUM *const pa_pub_Qy[MBX_LANES] = {BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy}; // signature const ECDSA_SIG *const pa_sig[MBX_LANES] = {sig, sig, sig, sig, sig, sig, sig, sig}; /* test function */ mbx_status expected_sts_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp256_ecdsa_verify_ssl_mb8(pa_sig, pa_pub_msg_digest, pa_pub_Qx, pa_pub_Qy, NULL, NULL); if (expected_sts_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_Qx, BN_Qy, sig) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp256_ecpublic_key_mb8.c000066400000000000000000000254401470420105600355230ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #ifndef BN_OPENSSL_DISABLE #include #endif /* Pairwise Consistency Test for EC p256 keypair */ /* KAT data taken from FIPS 186-4 examples */ // msg == // "5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf" // "416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5" // "473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17c" // "c934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8" /* msgDigest == SHA-256(msg) */ static const int8u msg_digest[MBX_NISTP256_DATA_BYTE_LEN] = { 0x44,0xac,0xf6,0xb7,0xe3,0x6c,0x13,0x42,0xc2,0xc5,0x89,0x72,0x04,0xfe,0x09,0x50, 0x4e,0x1e,0x2e,0xfb,0x1a,0x90,0x03,0x77,0xdb,0xc4,0xe7,0xa6,0xa1,0x33,0xec,0x56}; /* private key */ static const int8u d[MBX_NISTP256_DATA_BYTE_LEN] = { 0x64,0xb4,0x72,0xda,0x6d,0xa5,0x54,0xca,0xac,0x3e,0x4e,0x0b,0x13,0xc8,0x44,0x5b, 0x1a,0x77,0xf4,0x59,0xee,0xa8,0x4f,0x1f,0x58,0x8b,0x5f,0x71,0x3d,0x42,0x9b,0x51}; static const int8u k[MBX_NISTP256_DATA_BYTE_LEN] = { 0xde,0x68,0x2a,0x64,0x87,0x07,0x67,0xb9,0x33,0x5d,0x4f,0x82,0x47,0x62,0x4a,0x3b, 0x7f,0x3c,0xe9,0xf9,0x45,0xf2,0x80,0xa2,0x61,0x6a,0x90,0x4b,0xb1,0xbb,0xa1,0x94}; /* output signature buffers */ static int8u out_r[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; static int8u out_s[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecpublic_key_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // private key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; /* function output parameters */ // output public key int8u out_Qx[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; int8u out_Qy[MBX_LANES][MBX_NISTP256_DATA_BYTE_LEN]; // public key int64u *pa_pub_Qx[MBX_LANES] = { (int64u *)out_Qx[0], (int64u *)out_Qx[1], (int64u *)out_Qx[2], (int64u *)out_Qx[3], (int64u *)out_Qx[4], (int64u *)out_Qx[5], (int64u *)out_Qx[6], (int64u *)out_Qx[7]}; int64u *pa_pub_Qy[MBX_LANES] = { (int64u *)out_Qy[0], (int64u *)out_Qy[1], (int64u *)out_Qy[2], (int64u *)out_Qy[3], (int64u *)out_Qy[4], (int64u *)out_Qy[5], (int64u *)out_Qy[6], (int64u *)out_Qy[7]}; // output signature int8u *pa_sign_r[MBX_LANES] = { out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = { out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp256_ecpublic_key_mb8(pa_pub_Qx, pa_pub_Qy, NULL, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // Add const qualifiers to arrays const int64u* const * _pa_pub_Qx = (const int64u* const *)pa_pub_Qx; const int64u* const * _pa_pub_Qy = (const int64u* const *)pa_pub_Qy; // sign and verify with the generated keypair sts = mbx_nistp256_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // Add const qualifiers to arrays const int8u* const * _pa_sign_r = (const int8u* const *)pa_sign_r; const int8u* const * _pa_sign_s = (const int8u* const *)pa_sign_s; sts = mbx_nistp256_ecdsa_verify_mb8(_pa_sign_r, _pa_sign_s, pa_pub_msg_digest, _pa_pub_Qx, _pa_pub_Qy, NULL, NULL); // check the result of verification if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR_ARR1, BN_PTR_ARR2, SIG_PTR_ARR3, BN_PTR4, BN_PTR5) { \ for (int i = 0; i < MBX_LANES; ++i) { \ BN_free(BN_PTR_ARR1[i]); \ BN_free(BN_PTR_ARR2[i]); \ ECDSA_SIG_free(SIG_PTR_ARR3[i]); \ } \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp256_ecpublic_key_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* functions input parameters */ // ssl private key BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); // public key BIGNUM *pa_pub_Qx[MBX_LANES] = { BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; BIGNUM *pa_pub_Qy[MBX_LANES] = { BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; // signature for verify API ECDSA_SIG *const pa_sig[MBX_LANES] = { ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new() }; /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { if(NULL == pa_pub_Qx[i] || NULL == pa_pub_Qy[i] || NULL == pa_sig[i]) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } if(MBX_ALGO_SELFTEST_OK != test_result) { MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // set ssl private key BN_lebin2bn(d, MBX_NISTP256_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP256_DATA_BYTE_LEN, BN_k); // private key const BIGNUM *const pa_prv_d[MBX_LANES] = { (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d}; const BIGNUM *const pa_prv_k[MBX_LANES] = { (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k}; // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; /* functions output parameters */ // output signature for sign API int8u *pa_sign_r[MBX_LANES] = { out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = { out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ sts = mbx_nistp256_ecpublic_key_ssl_mb8(pa_pub_Qx, pa_pub_Qy, NULL, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // Add const qualifiers to arrays const BIGNUM* const * _pa_pub_Qx = (const BIGNUM* const *)pa_pub_Qx; const BIGNUM* const * _pa_pub_Qy = (const BIGNUM* const *)pa_pub_Qy; // sign and verify with the generated keypair sts = mbx_nistp256_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // fill ECDSA_SIG structure with the generated signature for verification for (int i = 0; i < MBX_LANES; ++i){ BIGNUM *BN_r = BN_new(); BIGNUM *BN_s = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_r || NULL == BN_s) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) // Handled separately, since memory management of // these variables is transferred to sig below BN_free(BN_r); BN_free(BN_s); return test_result; } BN_bin2bn(out_r[i], MBX_NISTP256_DATA_BYTE_LEN, BN_r); BN_bin2bn(out_s[i], MBX_NISTP256_DATA_BYTE_LEN, BN_s); ECDSA_SIG_set0(pa_sig[i], BN_r, BN_s); } sts = mbx_nistp256_ecdsa_verify_ssl_mb8((const ECDSA_SIG *const *)pa_sig, pa_pub_msg_digest, _pa_pub_Qx, _pa_pub_Qy, NULL, NULL); // check the result of verification if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_nistp384_ecdh_mb8.c000066400000000000000000000173701470420105600340540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from wycheproof testing) */ /* public */ static const int8u pub_x[MBX_NISTP384_DATA_BYTE_LEN] = {0x96,0x87,0x5d,0x18,0xd9,0x2d,0x01,0xfa, 0x9f,0x96,0x15,0xbe,0xa6,0x64,0x1b,0x79, 0x4f,0xb8,0x7a,0x67,0xbf,0xe8,0x7e,0xf1, 0xa2,0x43,0xfc,0x43,0x16,0x79,0x29,0x5d, 0x13,0x09,0x78,0x4a,0x3d,0x18,0x63,0x01, 0x94,0xa5,0xf9,0x9e,0x05,0x6e,0x0a,0x79}; static const int8u pub_y[MBX_NISTP384_DATA_BYTE_LEN] = {0xaa,0x3c,0x16,0xcb,0xbf,0xe5,0xb5,0xa0, 0x98,0x1c,0x5f,0x02,0x05,0x67,0x9a,0x32, 0x0d,0x68,0x1c,0xcc,0x1f,0x8a,0x30,0xeb, 0x1a,0x4b,0x6b,0xb2,0xc3,0x68,0xf6,0xb0, 0xf6,0xdf,0xea,0x56,0x3b,0x1b,0x71,0xdf, 0x82,0x5e,0xa7,0xa8,0xba,0x54,0xb9,0xd9}; /* private */ static const int8u prv_key[MBX_NISTP384_DATA_BYTE_LEN] = {0x81,0xfd,0x5d,0xb7,0x88,0xc5,0x21,0x9f, 0x6b,0x35,0x64,0xdd,0x4e,0xee,0x1d,0xfb, 0xd1,0x9f,0xc4,0x48,0xa9,0x0d,0xf2,0x5b, 0x16,0x85,0xc7,0x92,0x73,0x3b,0x60,0xf8, 0xa6,0x93,0x4b,0x56,0xc3,0x9f,0xc0,0x46, 0xf8,0xa9,0x2d,0x5b,0x42,0x61,0x6e,0x76}; /* shared key */ static const int8u sh_key[MBX_NISTP384_DATA_BYTE_LEN] = {0x64,0x61,0xde,0xfb,0x95,0xd9,0x96,0xb2, 0x42,0x96,0xf5,0xa1,0x83,0x2b,0x34,0xdb, 0x05,0xed,0x03,0x11,0x14,0xfb,0xe7,0xd9, 0x8d,0x09,0x8f,0x93,0x85,0x98,0x66,0xe4, 0xde,0x1e,0x22,0x9d,0xa7,0x1f,0xef,0x0c, 0x77,0xfe,0x49,0xb2,0x49,0x19,0x01,0x35}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdh_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* function input parameters */ // shared int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; // private const int64u *pa_prv_key[MBX_LANES] = { (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key}; // public const int64u *pa_pub_x[MBX_LANES] = { (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x}; const int64u *pa_pub_y[MBX_LANES] = { (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp384_ecdh_mb8(pa_shared_key, pa_prv_key, pa_pub_x, pa_pub_y, NULL, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output shared key to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_shared_key[i], MBX_NISTP384_DATA_BYTE_LEN, sh_key, MBX_NISTP384_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdh_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* ssl public key */ BIGNUM *BN_pub_x = BN_new(); BIGNUM *BN_pub_y = BN_new(); /* ssl private key */ BIGNUM *BN_prv_key = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_pub_x || NULL == BN_pub_y || NULL == BN_prv_key) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_pub_x, BN_pub_y, BN_prv_key) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl keys */ BN_lebin2bn(pub_x, MBX_NISTP384_DATA_BYTE_LEN, BN_pub_x); BN_lebin2bn(pub_y, MBX_NISTP384_DATA_BYTE_LEN, BN_pub_y); BN_lebin2bn(prv_key, MBX_NISTP384_DATA_BYTE_LEN, BN_prv_key); /* function input parameters */ // shared int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; // private const BIGNUM *pa_prv_key[MBX_LANES] = { BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key}; // public const BIGNUM *pa_pub_x[MBX_LANES] = { BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x}; const BIGNUM *pa_pub_y[MBX_LANES] = { BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y}; /* test function */ sts = mbx_nistp384_ecdh_ssl_mb8(pa_shared_key, pa_prv_key, pa_pub_x, pa_pub_y, NULL, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output shared key to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_shared_key[i], MBX_NISTP384_DATA_BYTE_LEN, sh_key, MBX_NISTP384_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_pub_x, BN_pub_y, BN_prv_key) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp384_ecdsa_sign_mb8.c000066400000000000000000000216541470420105600351710ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "6b45d88037392e1371d9fd1cd174e9c1838d11c3d6133dc17e65fa0c485dcca9" // "f52d41b60161246039e42ec784d49400bffdb51459f5de654091301a09378f93" // "464d52118b48d44b30d781eb1dbed09da11fb4c818dbd442d161aba4b9edc79f" // "05e4b7e401651395b53bd8b5bd3f2aaa6a00877fa9b45cadb8e648550b4c6cbe" /* msgDigest == SHA-384(msg) */ static const int8u msg_digest[MBX_NISTP384_DATA_BYTE_LEN] = {0x31,0xa4,0x52,0xd6,0x16,0x4d,0x90,0x4b, 0xb5,0x72,0x4c,0x87,0x82,0x80,0x23,0x1e, 0xae,0x70,0x5c,0x29,0xce,0x9d,0x4b,0xc7, 0xd5,0x8e,0x02,0x0e,0x10,0x85,0xf1,0x7e, 0xeb,0xcc,0x1a,0x38,0xf0,0xed,0x0b,0xf2, 0xb3,0x44,0xd8,0x1f,0xbd,0x89,0x68,0x25}; /* key pair */ static const int8u d[MBX_NISTP384_DATA_BYTE_LEN] = {0x97,0xac,0x80,0xb0,0x4f,0x9f,0x44,0x29, 0xbc,0xe3,0xbc,0xcc,0xb7,0x5d,0x2f,0x95, 0xc2,0x5e,0xf4,0xbd,0x6c,0x1e,0xa4,0x0d, 0x37,0x2e,0xd5,0x82,0x44,0x28,0xa8,0x46, 0x3f,0x4b,0x3e,0xdb,0x61,0x62,0x2d,0x18, 0x24,0x43,0xf1,0x8d,0x2d,0x43,0x1b,0x20}; static const int8u k[MBX_NISTP384_DATA_BYTE_LEN] = {0x71,0xc7,0xc9,0x25,0x1f,0x1e,0xc8,0x17, 0xf9,0x97,0xbf,0xe5,0x6c,0xe1,0x85,0x88, 0xdb,0x83,0x52,0xa2,0x58,0x0f,0xa0,0x76, 0x66,0x8c,0xe2,0x5c,0x6e,0xed,0x9d,0xdf, 0x34,0xfa,0x46,0x66,0xe1,0xc6,0x33,0xf7, 0x90,0xe0,0x78,0x59,0xf8,0xab,0xed,0xdc}; /* signature */ static const int8u r[MBX_NISTP384_DATA_BYTE_LEN] = {0x50,0x83,0x5a,0x92,0x51,0xba,0xd0,0x08, 0x10,0x61,0x77,0xef,0x00,0x4b,0x09,0x1a, 0x1e,0x42,0x35,0xcd,0x0d,0xa8,0x4f,0xff, 0x54,0x54,0x2b,0x0e,0xd7,0x55,0xc1,0xd6, 0xf2,0x51,0x60,0x9d,0x14,0xec,0xf1,0x8f, 0x9e,0x1d,0xdf,0xe6,0x9b,0x94,0x6e,0x32}; static const int8u s[MBX_NISTP384_DATA_BYTE_LEN] = {0x04,0x75,0xf3,0xd3,0x0c,0x64,0x63,0xb6, 0x46,0xe8,0xd3,0xbf,0x24,0x55,0x83,0x03, 0x14,0x61,0x1c,0xbd,0xe4,0x04,0xbe,0x51, 0x8b,0x14,0x46,0x4f,0xdb,0x19,0x5f,0xdc, 0xc9,0x2e,0xb2,0x22,0xe6,0x1f,0x42,0x6a, 0x4a,0x59,0x2c,0x00,0xa6,0xa8,0x97,0x21}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp384_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer int r_output_status; int s_output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP384_DATA_BYTE_LEN, r, MBX_NISTP384_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP384_DATA_BYTE_LEN, s, MBX_NISTP384_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl key pair */ BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_k) return test_result; } /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity statuses */ int r_output_status; int s_output_status; /* set ssl key pair */ BN_lebin2bn(d, MBX_NISTP384_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP384_DATA_BYTE_LEN, BN_k); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const BIGNUM *pa_prv_d[MBX_LANES] = {BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d}; const BIGNUM *pa_prv_k[MBX_LANES] = {BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ sts = mbx_nistp384_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP384_DATA_BYTE_LEN, r, MBX_NISTP384_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP384_DATA_BYTE_LEN, s, MBX_NISTP384_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8.c000066400000000000000000000272071470420105600403010ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "6b45d88037392e1371d9fd1cd174e9c1838d11c3d6133dc17e65fa0c485dcca9" // "f52d41b60161246039e42ec784d49400bffdb51459f5de654091301a09378f93" // "464d52118b48d44b30d781eb1dbed09da11fb4c818dbd442d161aba4b9edc79f" // "05e4b7e401651395b53bd8b5bd3f2aaa6a00877fa9b45cadb8e648550b4c6cbe" /* msgDigest == SHA-384(msg) */ static const int8u msg_digest[MBX_NISTP384_DATA_BYTE_LEN] = {0x31,0xa4,0x52,0xd6,0x16,0x4d,0x90,0x4b, 0xb5,0x72,0x4c,0x87,0x82,0x80,0x23,0x1e, 0xae,0x70,0x5c,0x29,0xce,0x9d,0x4b,0xc7, 0xd5,0x8e,0x02,0x0e,0x10,0x85,0xf1,0x7e, 0xeb,0xcc,0x1a,0x38,0xf0,0xed,0x0b,0xf2, 0xb3,0x44,0xd8,0x1f,0xbd,0x89,0x68,0x25}; /* key pair */ static const int8u d[MBX_NISTP384_DATA_BYTE_LEN] = {0x97,0xac,0x80,0xb0,0x4f,0x9f,0x44,0x29, 0xbc,0xe3,0xbc,0xcc,0xb7,0x5d,0x2f,0x95, 0xc2,0x5e,0xf4,0xbd,0x6c,0x1e,0xa4,0x0d, 0x37,0x2e,0xd5,0x82,0x44,0x28,0xa8,0x46, 0x3f,0x4b,0x3e,0xdb,0x61,0x62,0x2d,0x18, 0x24,0x43,0xf1,0x8d,0x2d,0x43,0x1b,0x20}; static const int8u k[MBX_NISTP384_DATA_BYTE_LEN] = {0x71,0xc7,0xc9,0x25,0x1f,0x1e,0xc8,0x17, 0xf9,0x97,0xbf,0xe5,0x6c,0xe1,0x85,0x88, 0xdb,0x83,0x52,0xa2,0x58,0x0f,0xa0,0x76, 0x66,0x8c,0xe2,0x5c,0x6e,0xed,0x9d,0xdf, 0x34,0xfa,0x46,0x66,0xe1,0xc6,0x33,0xf7, 0x90,0xe0,0x78,0x59,0xf8,0xab,0xed,0xdc}; /* signature */ static const int8u r[MBX_NISTP384_DATA_BYTE_LEN] = {0x50,0x83,0x5a,0x92,0x51,0xba,0xd0,0x08, 0x10,0x61,0x77,0xef,0x00,0x4b,0x09,0x1a, 0x1e,0x42,0x35,0xcd,0x0d,0xa8,0x4f,0xff, 0x54,0x54,0x2b,0x0e,0xd7,0x55,0xc1,0xd6, 0xf2,0x51,0x60,0x9d,0x14,0xec,0xf1,0x8f, 0x9e,0x1d,0xdf,0xe6,0x9b,0x94,0x6e,0x32}; static const int8u s[MBX_NISTP384_DATA_BYTE_LEN] = {0x04,0x75,0xf3,0xd3,0x0c,0x64,0x63,0xb6, 0x46,0xe8,0xd3,0xbf,0x24,0x55,0x83,0x03, 0x14,0x61,0x1c,0xbd,0xe4,0x04,0xbe,0x51, 0x8b,0x14,0x46,0x4f,0xdb,0x19,0x5f,0xdc, 0xc9,0x2e,0xb2,0x22,0xe6,0x1f,0x42,0x6a, 0x4a,0x59,0x2c,0x00,0xa6,0xa8,0x97,0x21}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* k key inversion */ int8u inv_k[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* precomputed r signature component */ int8u precomp_r[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // k key inversion int64u *pa_inv_k[MBX_LANES] = {(int64u *)inv_k[0], (int64u *)inv_k[1], (int64u *)inv_k[2], (int64u *)inv_k[3], (int64u *)inv_k[4], (int64u *)inv_k[5], (int64u *)inv_k[6], (int64u *)inv_k[7]}; // precomputed r signature component int64u *pa_precomp_r[MBX_LANES] = { (int64u *)precomp_r[0], (int64u *)precomp_r[1], (int64u *)precomp_r[2], (int64u *)precomp_r[3], (int64u *)precomp_r[4], (int64u *)precomp_r[5], (int64u *)precomp_r[6], (int64u *)precomp_r[7]}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test functions*/ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; // sign setup sts = mbx_nistp384_ecdsa_sign_setup_mb8(pa_inv_k, pa_precomp_r, pa_prv_k, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // sign complete sts = mbx_nistp384_ecdsa_sign_complete_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, (const int64u *const *)pa_precomp_r, (const int64u *const *)pa_inv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // compare output signature to known answer int r_output_status; int s_output_status; for (int i = 0; i < MBX_LANES; ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP384_DATA_BYTE_LEN, r, MBX_NISTP384_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP384_DATA_BYTE_LEN, s, MBX_NISTP384_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; break; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR_ARR1, BN_PTR_ARR2, BN_PTR3, BN_PTR4) { \ for (int i = 0; i < MBX_LANES; ++i) { \ BN_free(BN_PTR_ARR1[i]); \ BN_free(BN_PTR_ARR2[i]); \ } \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdsa_sign_setup_complete_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl key pair */ BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); /* k key inversion */ BIGNUM *pa_inv_k[MBX_LANES] = {BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; /* precomputed r signature component */ BIGNUM *pa_precomp_r[MBX_LANES] = {BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { if(NULL == pa_inv_k[i] || NULL == pa_precomp_r[i]) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } if(MBX_ALGO_SELFTEST_OK != test_result) { MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity statuses */ int r_output_status; int s_output_status; // set ssl key pair BN_lebin2bn(d, MBX_NISTP384_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP384_DATA_BYTE_LEN, BN_k); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const BIGNUM *pa_prv_d[MBX_LANES] = {BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d}; const BIGNUM *pa_prv_k[MBX_LANES] = {BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test functions */ // sign setup sts = mbx_nistp384_ecdsa_sign_setup_ssl_mb8(pa_inv_k, pa_precomp_r, pa_prv_k, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } // sign complete sts = mbx_nistp384_ecdsa_sign_complete_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, (const BIGNUM *const *)pa_precomp_r, (const BIGNUM *const *)pa_inv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } // compare output signature to known answer for (int i = 0; i < MBX_LANES; ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP384_DATA_BYTE_LEN, r, MBX_NISTP384_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP384_DATA_BYTE_LEN, s, MBX_NISTP384_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; break; } } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp384_ecdsa_verify_mb8.c000066400000000000000000000201721470420105600355270ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #ifndef BN_OPENSSL_DISABLE #include #endif /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "9dd789ea25c04745d57a381f22de01fb0abd3c72dbdefd44e43213c189583eef" // "85ba662044da3de2dd8670e6325154480155bbeebb702c75781ac32e13941860" // "cb576fe37a05b757da5b5b418f6dd7c30b042e40f4395a342ae4dce05634c336" // "25e2bc524345481f7e253d9551266823771b251705b4a85166022a37ac28f1bd" /* msgDigest == SHA-384(msg) */ static const int8u msg_digest[MBX_NISTP384_DATA_BYTE_LEN] = {0x96,0x5b,0x83,0xf5,0xd3,0x4f,0x74,0x43, 0xeb,0x88,0xe7,0x8f,0xcc,0x23,0x47,0x91, 0x56,0xc9,0xcb,0x00,0x80,0xdd,0x68,0x33, 0x4d,0xac,0x0a,0xd3,0x3b,0xa8,0xc7,0x74, 0x10,0x0e,0x44,0x00,0x63,0xdb,0x28,0xb4, 0x0b,0x51,0xac,0x37,0x70,0x5d,0x4d,0x70}; /* public key */ static const int8u Qx[MBX_NISTP384_DATA_BYTE_LEN] = {0x44,0xf1,0x9a,0xfd,0x64,0xd0,0xd7,0x37, 0xef,0x0f,0xe0,0x23,0xfb,0x78,0xbd,0x75, 0x1d,0x95,0xd1,0x95,0x51,0x76,0xb3,0xe2, 0x35,0x50,0x0c,0xe2,0xec,0x4f,0x15,0xcb, 0x33,0x9b,0x57,0x83,0x43,0xe1,0xe1,0x8e, 0x7b,0xa5,0x16,0xd5,0x1f,0x8b,0x90,0xcb}; static const int8u Qy[MBX_NISTP384_DATA_BYTE_LEN] = {0xbb,0x74,0xc3,0xf7,0xfd,0xbd,0x83,0x95, 0xa0,0xca,0xdb,0x2a,0xe3,0xfb,0x9b,0xf7, 0x60,0xc3,0xb2,0x59,0x6f,0x1f,0x55,0x8c, 0xed,0x1b,0x01,0x9a,0xad,0xcb,0xf1,0xfa, 0x21,0x21,0x82,0xcf,0xf7,0x2c,0xff,0xdc, 0x1d,0x40,0x57,0x58,0x6b,0xc4,0x99,0xcd}; /* signature */ static const int8u r[MBX_NISTP384_DATA_BYTE_LEN] = {0x33,0xf6,0x4f,0xb6,0x5c,0xd6,0xa8,0x91, 0x85,0x23,0xf2,0x3a,0xea,0x0b,0xbc,0xf5, 0x6b,0xba,0x1d,0xac,0xa7,0xaf,0xf8,0x17, 0xc8,0x79,0x1d,0xc9,0x24,0x28,0xd6,0x05, 0xac,0x62,0x9d,0xe2,0xe8,0x47,0xd4,0x3c, 0xee,0x55,0xba,0x9e,0x4a,0x0e,0x83,0xba}; static const int8u s[MBX_NISTP384_DATA_BYTE_LEN] = {0x44,0x28,0xbb,0x47,0x8a,0x43,0xac,0x73, 0xec,0xd6,0xde,0x51,0xdd,0xf7,0xc2,0x8f, 0xf3,0xc2,0x44,0x16,0x25,0xa0,0x81,0x71, 0x43,0x37,0xdd,0x44,0xfe,0xa8,0x01,0x1b, 0xae,0x71,0x95,0x9a,0x10,0x94,0x7b,0x6e, 0xa3,0x3f,0x77,0xe1,0x28,0xd3,0xc6,0xae}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdsa_verify_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // public key const int64u *const pa_pub_Qx[MBX_LANES] = { (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx}; const int64u *const pa_pub_Qy[MBX_LANES] = { (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy}; // signature const int8u *const pa_sign_r[MBX_LANES] = {r, r, r, r, r, r, r, r}; const int8u *const pa_sign_s[MBX_LANES] = {s, s, s, s, s, s, s, s}; /* test function */ mbx_status expected_sts_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp384_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_pub_Qx, pa_pub_Qy, NULL, NULL); if (expected_sts_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2, SIG_PTR1) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ ECDSA_SIG_free(SIG_PTR1); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecdsa_verify_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl public key */ BIGNUM *BN_Qx = BN_new(); BIGNUM *BN_Qy = BN_new(); // ssl signature BIGNUM *BN_r = BN_new(); BIGNUM *BN_s = BN_new(); ECDSA_SIG *sig = ECDSA_SIG_new(); /* check if allocated memory is valid */ if(NULL == BN_Qx || NULL == BN_Qy || NULL == BN_r || NULL == BN_s || NULL == sig) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_Qx, BN_Qy, sig) // Handled separately, since memory management of // these variables is transferred to sig below BN_free(BN_r); BN_free(BN_s); return test_result; } // set ssl public key BN_lebin2bn(Qx, MBX_NISTP384_DATA_BYTE_LEN, BN_Qx); BN_lebin2bn(Qy, MBX_NISTP384_DATA_BYTE_LEN, BN_Qy); // set ssl signature BN_bin2bn(r, MBX_NISTP384_DATA_BYTE_LEN, BN_r); BN_bin2bn(s, MBX_NISTP384_DATA_BYTE_LEN, BN_s); ECDSA_SIG_set0(sig, BN_r, BN_s); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // public key const BIGNUM *const pa_pub_Qx[MBX_LANES] = {BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx}; const BIGNUM *const pa_pub_Qy[MBX_LANES] = {BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy}; // signature const ECDSA_SIG *const pa_sig[MBX_LANES] = {sig, sig, sig, sig, sig, sig, sig, sig}; /* test function */ mbx_status expected_sts_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp384_ecdsa_verify_ssl_mb8(pa_sig, pa_pub_msg_digest, pa_pub_Qx, pa_pub_Qy, NULL, NULL); if (expected_sts_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_Qx, BN_Qy, sig) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp384_ecpublic_key_mb8.c000066400000000000000000000254071470420105600355300ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #ifndef BN_OPENSSL_DISABLE #include #endif /* Pairwise Consistency Test for EC p384 keypair */ /* KAT data taken from FIPS 186-4 examples */ // msg == // "9dd789ea25c04745d57a381f22de01fb0abd3c72dbdefd44e43213c189583eef" // "85ba662044da3de2dd8670e6325154480155bbeebb702c75781ac32e13941860" // "cb576fe37a05b757da5b5b418f6dd7c30b042e40f4395a342ae4dce05634c336" // "25e2bc524345481f7e253d9551266823771b251705b4a85166022a37ac28f1bd" /* msgDigest == SHA-384(msg) */ static const int8u msg_digest[MBX_NISTP384_DATA_BYTE_LEN] = { 0x96,0x5b,0x83,0xf5,0xd3,0x4f,0x74,0x43,0xeb,0x88,0xe7,0x8f,0xcc,0x23,0x47,0x91, 0x56,0xc9,0xcb,0x00,0x80,0xdd,0x68,0x33,0x4d,0xac,0x0a,0xd3,0x3b,0xa8,0xc7,0x74, 0x10,0x0e,0x44,0x00,0x63,0xdb,0x28,0xb4,0x0b,0x51,0xac,0x37,0x70,0x5d,0x4d,0x70}; /* private key pair */ static const int8u d[MBX_NISTP384_DATA_BYTE_LEN] = { 0x97,0xac,0x80,0xb0,0x4f,0x9f,0x44,0x29,0xbc,0xe3,0xbc,0xcc,0xb7,0x5d,0x2f,0x95, 0xc2,0x5e,0xf4,0xbd,0x6c,0x1e,0xa4,0x0d,0x37,0x2e,0xd5,0x82,0x44,0x28,0xa8,0x46, 0x3f,0x4b,0x3e,0xdb,0x61,0x62,0x2d,0x18,0x24,0x43,0xf1,0x8d,0x2d,0x43,0x1b,0x20}; static const int8u k[MBX_NISTP384_DATA_BYTE_LEN] = { 0x71,0xc7,0xc9,0x25,0x1f,0x1e,0xc8,0x17,0xf9,0x97,0xbf,0xe5,0x6c,0xe1,0x85,0x88, 0xdb,0x83,0x52,0xa2,0x58,0x0f,0xa0,0x76,0x66,0x8c,0xe2,0x5c,0x6e,0xed,0x9d,0xdf, 0x34,0xfa,0x46,0x66,0xe1,0xc6,0x33,0xf7,0x90,0xe0,0x78,0x59,0xf8,0xab,0xed,0xdc}; /* output signature buffers */ static int8u out_r[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; static int8u out_s[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecpublic_key_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // private key const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; /* function output parameters */ /* output public key */ int8u out_Qx[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; int8u out_Qy[MBX_LANES][MBX_NISTP384_DATA_BYTE_LEN]; // public key int64u *pa_pub_Qx[MBX_LANES] = { (int64u *)out_Qx[0], (int64u *)out_Qx[1], (int64u *)out_Qx[2], (int64u *)out_Qx[3], (int64u *)out_Qx[4], (int64u *)out_Qx[5], (int64u *)out_Qx[6], (int64u *)out_Qx[7]}; int64u *pa_pub_Qy[MBX_LANES] = { (int64u *)out_Qy[0], (int64u *)out_Qy[1], (int64u *)out_Qy[2], (int64u *)out_Qy[3], (int64u *)out_Qy[4], (int64u *)out_Qy[5], (int64u *)out_Qy[6], (int64u *)out_Qy[7]}; // output signature int8u *pa_sign_r[MBX_LANES] = { out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = { out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp384_ecpublic_key_mb8(pa_pub_Qx, pa_pub_Qy, NULL, pa_prv_d, NULL); if (sts != expected_status_mb8){ if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // Add const qualifiers to arrays const int64u* const * _pa_pub_Qx = (const int64u* const *)pa_pub_Qx; const int64u* const * _pa_pub_Qy = (const int64u* const *)pa_pub_Qy; // sign and verify with the generated keypair sts = mbx_nistp384_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // Add const qualifiers to arrays const int8u* const * _pa_sign_r = (const int8u* const *)pa_sign_r; const int8u* const * _pa_sign_s = (const int8u* const *)pa_sign_s; sts = mbx_nistp384_ecdsa_verify_mb8(_pa_sign_r, _pa_sign_s, pa_pub_msg_digest, _pa_pub_Qx, _pa_pub_Qy, NULL, NULL); // check the result of verification if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR_ARR1, BN_PTR_ARR2, SIG_PTR_ARR3, BN_PTR4, BN_PTR5) { \ for (int i = 0; i < MBX_LANES; ++i) { \ BN_free(BN_PTR_ARR1[i]); \ BN_free(BN_PTR_ARR2[i]); \ ECDSA_SIG_free(SIG_PTR_ARR3[i]); \ } \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp384_ecpublic_key_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* functions input parameters */ // ssl private key BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); // public key BIGNUM *pa_pub_Qx[MBX_LANES] = { BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; BIGNUM *pa_pub_Qy[MBX_LANES] = { BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; // signature for verify API ECDSA_SIG *const pa_sig[MBX_LANES] = { ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new()}; /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { if(NULL == pa_pub_Qx[i] || NULL == pa_pub_Qy[i] || NULL == pa_sig[i]) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } if(MBX_ALGO_SELFTEST_OK != test_result) { MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } BN_lebin2bn(d, MBX_NISTP384_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP384_DATA_BYTE_LEN, BN_k); // private key const BIGNUM *const pa_prv_d[MBX_LANES] = { (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d}; const BIGNUM *const pa_prv_k[MBX_LANES] = { (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k}; // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; /* functions output parameters */ // output signature for sign API int8u *pa_sign_r[MBX_LANES] = { out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = { out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ sts = mbx_nistp384_ecpublic_key_ssl_mb8(pa_pub_Qx, pa_pub_Qy, NULL, pa_prv_d, NULL); if (sts != expected_status_mb8){ if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // Add const qualifiers to arrays const BIGNUM* const * _pa_pub_Qx = (const BIGNUM* const *)pa_pub_Qx; const BIGNUM* const * _pa_pub_Qy = (const BIGNUM* const *)pa_pub_Qy; // sign and verify with the generated keypair sts = mbx_nistp384_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (sts != expected_status_mb8){ if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // fill ECDSA_SIG structure with the generated signature for verification for (int i = 0; i < MBX_LANES; ++i){ BIGNUM *BN_r = BN_new(); BIGNUM *BN_s = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_r || NULL == BN_s) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) // Handled separately, since memory management of // these variables is transferred to sig below BN_free(BN_r); BN_free(BN_s); return test_result; } BN_bin2bn(out_r[i], MBX_NISTP384_DATA_BYTE_LEN, BN_r); BN_bin2bn(out_s[i], MBX_NISTP384_DATA_BYTE_LEN, BN_s); ECDSA_SIG_set0(pa_sig[i], BN_r, BN_s); } sts = mbx_nistp384_ecdsa_verify_ssl_mb8((const ECDSA_SIG *const *)pa_sig, pa_pub_msg_digest, _pa_pub_Qx, _pa_pub_Qy, NULL, NULL); // check the result of verification if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_nistp521_ecdh_mb8.c000066400000000000000000000214311470420105600340360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from wycheproof testing) */ /* public */ static const int8u pub_x[MBX_NISTP521_DATA_BYTE_LEN] = {0xce,0xb5,0x99,0x79,0x07,0xf3,0x3c,0x61, 0xf1,0xad,0x51,0x72,0x33,0x92,0xf4,0xe7, 0x52,0xa6,0x91,0x48,0x44,0x6d,0x92,0x42, 0x26,0x97,0x4c,0x2d,0xdf,0x2b,0xca,0x69, 0x97,0xd7,0xd9,0x75,0x85,0xd3,0xfb,0x77, 0x83,0x19,0x9a,0x52,0xa6,0x1d,0x4a,0xc5, 0x31,0x5a,0x26,0xb2,0x5c,0x8a,0x0d,0x4a, 0xa7,0x36,0xb5,0x3d,0x73,0x94,0x3e,0xda, 0x64,0x00}; static const int8u pub_y[MBX_NISTP521_DATA_BYTE_LEN] = {0xf7,0x98,0xa0,0xab,0xc5,0x70,0x0a,0xa9, 0x63,0xbb,0x46,0x33,0x16,0x50,0x59,0xfc, 0xdb,0xb6,0x5b,0xb8,0x38,0xf3,0xdd,0x09, 0x14,0xdb,0x54,0xfb,0x5a,0x37,0xed,0x3c, 0x18,0x79,0x4f,0x4a,0xae,0x52,0x21,0x42, 0x92,0xfa,0x0d,0x94,0x88,0x52,0xbc,0x7e, 0x0e,0x3c,0x0c,0xf7,0x69,0xc0,0x24,0xc8, 0xb0,0x22,0x47,0xfd,0xf9,0x9c,0xd1,0x4a, 0xe0,0x00}; /* private */ static const int8u prv_key[MBX_NISTP521_DATA_BYTE_LEN] = {0xcd,0x7d,0x1c,0x61,0x1f,0x37,0xa7,0x40, 0x44,0x57,0x58,0xd4,0x41,0x13,0x4a,0xe3, 0x2a,0x99,0x43,0xdf,0xc6,0x6d,0x56,0x64, 0x5b,0x79,0x8f,0x59,0x0d,0xc9,0x40,0x16, 0xc6,0xe7,0x22,0xbb,0xc9,0xef,0x06,0xd5, 0x19,0xf6,0xb8,0x87,0x4f,0xeb,0x49,0xa8, 0x21,0x2c,0xe9,0x03,0xfd,0x6e,0xbc,0x94, 0x7a,0xe7,0x6c,0x59,0x29,0xb5,0x82,0x99, 0x93,0x01}; /* shared key */ static const int8u sh_key[MBX_NISTP521_DATA_BYTE_LEN] = {0x01,0xf1,0xe4,0x10,0xf2,0xc6,0x26,0x2b, 0xce,0x68,0x79,0xa3,0xf4,0x6d,0xfb,0x7d, 0xd1,0x1d,0x30,0xee,0xee,0x9a,0xb4,0x98, 0x52,0x10,0x2e,0x18,0x92,0x20,0x1d,0xd1, 0x0f,0x27,0x26,0x6c,0x2c,0xf7,0xcb,0xcc, 0xc7,0xf6,0x88,0x50,0x99,0x04,0x3d,0xad, 0x80,0xff,0x57,0xf0,0xdf,0x96,0xac,0xf2, 0x83,0xfb,0x09,0x0d,0xe5,0x3d,0xf9,0x5f, 0x7d,0x87}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdh_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; /* function input parameters */ // shared int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; // private const int64u *pa_prv_key[MBX_LANES] = { (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key, (int64u *)prv_key}; // public const int64u *pa_pub_x[MBX_LANES] = { (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x, (int64u *)pub_x}; const int64u *pa_pub_y[MBX_LANES] = { (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y, (int64u *)pub_y}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp521_ecdh_mb8(pa_shared_key, pa_prv_key, pa_pub_x, pa_pub_y, NULL, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output shared key to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_shared_key[i], MBX_NISTP521_DATA_BYTE_LEN, sh_key, MBX_NISTP521_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdh_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; /* ssl public key */ BIGNUM *BN_pub_x = BN_new(); BIGNUM *BN_pub_y = BN_new(); /* ssl private key */ BIGNUM *BN_prv_key = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_pub_x || NULL == BN_pub_y || NULL == BN_prv_key) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_pub_x, BN_pub_y, BN_prv_key) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl keys */ BN_lebin2bn(pub_x, MBX_NISTP521_DATA_BYTE_LEN, BN_pub_x); BN_lebin2bn(pub_y, MBX_NISTP521_DATA_BYTE_LEN, BN_pub_y); BN_lebin2bn(prv_key, MBX_NISTP521_DATA_BYTE_LEN, BN_prv_key); /* function input parameters */ // shared int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; // private const BIGNUM *pa_prv_key[MBX_LANES] = { BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key, BN_prv_key}; // public const BIGNUM *pa_pub_x[MBX_LANES] = { BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x, BN_pub_x}; const BIGNUM *pa_pub_y[MBX_LANES] = { BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y, BN_pub_y}; /* test function */ sts = mbx_nistp521_ecdh_ssl_mb8(pa_shared_key, pa_prv_key, pa_pub_x, pa_pub_y, NULL, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output shared key to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_shared_key[i], MBX_NISTP521_DATA_BYTE_LEN, sh_key, MBX_NISTP521_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_pub_x, BN_pub_y, BN_prv_key) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp521_ecdsa_sign_mb8.c000066400000000000000000000243171470420105600351610ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from FIPS 186-4 examples)*/ // msg == // "9ecd500c60e701404922e58ab20cc002651fdee7cbc9336adda33e4c1088fab1" // "964ecb7904dc6856865d6c8e15041ccf2d5ac302e99d346ff2f686531d255216" // "78d4fd3f76bbf2c893d246cb4d7693792fe18172108146853103a51f824acc62" // "1cb7311d2463c3361ea707254f2b052bc22cb8012873dcbb95bf1a5cc53ab89f" /* msgDigest == SHA-521(msg) */ static const int8u msg_digest[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x00,0x65,0xf8,0x34,0x08,0x09,0x22, 0x61,0xbd,0xa5,0x99,0x38,0x9d,0xf0,0x33, 0x82,0xc5,0xbe,0x01,0xa8,0x1f,0xe0,0x0a, 0x36,0xf3,0xf4,0xbb,0x65,0x41,0x26,0x3f, 0x80,0x16,0x27,0xc4,0x40,0xe5,0x08,0x09, 0x71,0x2b,0x0c,0xac,0xe7,0xc2,0x17,0xe6, 0xe5,0x05,0x1a,0xf8,0x1d,0xe9,0xbf,0xec, 0x32,0x04,0xdc,0xd6,0x3c,0x4f,0x9a,0x74, 0x10,0x47}; /* key pair */ static const int8u d[MBX_NISTP521_DATA_BYTE_LEN] = {0x26,0xb9,0x4c,0xa1,0x7a,0x56,0x5e,0x6c, 0xee,0x9f,0xcf,0xcc,0xc0,0x55,0x86,0x8c, 0x21,0x0f,0x9a,0xc2,0xcc,0x74,0xf5,0x72, 0x9b,0x35,0xa2,0xdc,0x80,0x00,0xab,0x2f, 0xf0,0xfa,0x7f,0x26,0x86,0xb8,0x7d,0xed, 0x15,0xe5,0x78,0x26,0x8d,0xf0,0x67,0xba, 0x4f,0x8f,0x3d,0x10,0xcf,0x0a,0xef,0x2c, 0xa8,0x3c,0x53,0xbc,0x04,0x27,0xd3,0x49, 0xf7,0x00}; static const int8u k[MBX_NISTP521_DATA_BYTE_LEN] = {0xf1,0x6d,0x4c,0x86,0x3e,0x59,0xc7,0x83, 0xbb,0xec,0xd4,0x33,0xa7,0x0a,0x3f,0xec, 0xfc,0x81,0xf8,0xdc,0xc9,0x9a,0xdb,0xf3, 0xe1,0xcf,0x46,0xcf,0xfe,0x12,0x2d,0x81, 0x60,0xac,0xde,0xdd,0x3c,0x05,0xe3,0x9b, 0x76,0x0c,0xc6,0xb5,0x52,0xcd,0xff,0x17, 0x6a,0xb1,0xc3,0x83,0xaa,0xb9,0xba,0xa5, 0x86,0xde,0xa6,0x29,0xaa,0x6c,0xab,0xf5, 0x3a,0x00}; /* signature */ static const int8u r[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x4d,0xe8,0x26,0xea,0x70,0x4a,0xd1, 0x0b,0xc0,0xf7,0x53,0x8a,0xf8,0xa3,0x84, 0x3f,0x28,0x4f,0x55,0xc8,0xb9,0x46,0xaf, 0x92,0x35,0xaf,0x5a,0xf7,0x4f,0x2b,0x76, 0xe0,0x99,0xe4,0xbc,0x72,0xfd,0x79,0xd2, 0x8a,0x38,0x0f,0x8d,0x4b,0x4c,0x91,0x9a, 0xc2,0x90,0xd2,0x48,0xc3,0x79,0x83,0xba, 0x05,0xae,0xa4,0x2e,0x2d,0xd7,0x9f,0xdd, 0x33,0xe8}; static const int8u s[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x87,0x48,0x8c,0x85,0x9a,0x96,0xfe, 0xa2,0x66,0xea,0x13,0xbf,0x6d,0x11,0x4c, 0x42,0x9b,0x16,0x3b,0xe9,0x7a,0x57,0x55, 0x90,0x86,0xed,0xb6,0x4a,0xed,0x4a,0x18, 0x59,0x4b,0x46,0xfb,0x9e,0xfc,0x7f,0xd2, 0x5d,0x8b,0x2d,0xe8,0xf0,0x9c,0xa0,0x58, 0x7f,0x54,0xbd,0x28,0x72,0x99,0xf4,0x7b, 0x2f,0xf1,0x24,0xaa,0xc5,0x66,0xe8,0xee, 0x3b,0x43}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp521_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer int r_output_status; int s_output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP521_DATA_BYTE_LEN, r, MBX_NISTP521_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP521_DATA_BYTE_LEN, s, MBX_NISTP521_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl key pair */ BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_k) return test_result; } /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity statuses */ int r_output_status; int s_output_status; // set ssl key pair BN_lebin2bn(d, MBX_NISTP521_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP521_DATA_BYTE_LEN, BN_k); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const BIGNUM *pa_prv_d[MBX_LANES] = {BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d}; const BIGNUM *pa_prv_k[MBX_LANES] = {BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ sts = mbx_nistp521_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP521_DATA_BYTE_LEN, r, MBX_NISTP521_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP521_DATA_BYTE_LEN, s, MBX_NISTP521_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8.c000066400000000000000000000320071470420105600402640ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #define NISTP521_MAX_DATA_BYTE_LEN ((((MBX_NISTP521_DATA_BYTE_LEN - 1) / 8) + 1) * 8) /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "9ecd500c60e701404922e58ab20cc002651fdee7cbc9336adda33e4c1088fab1" // "964ecb7904dc6856865d6c8e15041ccf2d5ac302e99d346ff2f686531d255216" // "78d4fd3f76bbf2c893d246cb4d7693792fe18172108146853103a51f824acc62" // "1cb7311d2463c3361ea707254f2b052bc22cb8012873dcbb95bf1a5cc53ab89f" /* msgDigest == SHA-521(msg) */ static const int8u msg_digest[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x00,0x65,0xf8,0x34,0x08,0x09,0x22, 0x61,0xbd,0xa5,0x99,0x38,0x9d,0xf0,0x33, 0x82,0xc5,0xbe,0x01,0xa8,0x1f,0xe0,0x0a, 0x36,0xf3,0xf4,0xbb,0x65,0x41,0x26,0x3f, 0x80,0x16,0x27,0xc4,0x40,0xe5,0x08,0x09, 0x71,0x2b,0x0c,0xac,0xe7,0xc2,0x17,0xe6, 0xe5,0x05,0x1a,0xf8,0x1d,0xe9,0xbf,0xec, 0x32,0x04,0xdc,0xd6,0x3c,0x4f,0x9a,0x74, 0x10,0x47}; /* key pair */ static const int8u d[MBX_NISTP521_DATA_BYTE_LEN] = {0x26,0xb9,0x4c,0xa1,0x7a,0x56,0x5e,0x6c, 0xee,0x9f,0xcf,0xcc,0xc0,0x55,0x86,0x8c, 0x21,0x0f,0x9a,0xc2,0xcc,0x74,0xf5,0x72, 0x9b,0x35,0xa2,0xdc,0x80,0x00,0xab,0x2f, 0xf0,0xfa,0x7f,0x26,0x86,0xb8,0x7d,0xed, 0x15,0xe5,0x78,0x26,0x8d,0xf0,0x67,0xba, 0x4f,0x8f,0x3d,0x10,0xcf,0x0a,0xef,0x2c, 0xa8,0x3c,0x53,0xbc,0x04,0x27,0xd3,0x49, 0xf7,0x00}; static const int8u k[MBX_NISTP521_DATA_BYTE_LEN] = {0xf1,0x6d,0x4c,0x86,0x3e,0x59,0xc7,0x83, 0xbb,0xec,0xd4,0x33,0xa7,0x0a,0x3f,0xec, 0xfc,0x81,0xf8,0xdc,0xc9,0x9a,0xdb,0xf3, 0xe1,0xcf,0x46,0xcf,0xfe,0x12,0x2d,0x81, 0x60,0xac,0xde,0xdd,0x3c,0x05,0xe3,0x9b, 0x76,0x0c,0xc6,0xb5,0x52,0xcd,0xff,0x17, 0x6a,0xb1,0xc3,0x83,0xaa,0xb9,0xba,0xa5, 0x86,0xde,0xa6,0x29,0xaa,0x6c,0xab,0xf5, 0x3a,0x00}; /* signature */ static const int8u r[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x4d,0xe8,0x26,0xea,0x70,0x4a,0xd1, 0x0b,0xc0,0xf7,0x53,0x8a,0xf8,0xa3,0x84, 0x3f,0x28,0x4f,0x55,0xc8,0xb9,0x46,0xaf, 0x92,0x35,0xaf,0x5a,0xf7,0x4f,0x2b,0x76, 0xe0,0x99,0xe4,0xbc,0x72,0xfd,0x79,0xd2, 0x8a,0x38,0x0f,0x8d,0x4b,0x4c,0x91,0x9a, 0xc2,0x90,0xd2,0x48,0xc3,0x79,0x83,0xba, 0x05,0xae,0xa4,0x2e,0x2d,0xd7,0x9f,0xdd, 0x33,0xe8}; static const int8u s[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x87,0x48,0x8c,0x85,0x9a,0x96,0xfe, 0xa2,0x66,0xea,0x13,0xbf,0x6d,0x11,0x4c, 0x42,0x9b,0x16,0x3b,0xe9,0x7a,0x57,0x55, 0x90,0x86,0xed,0xb6,0x4a,0xed,0x4a,0x18, 0x59,0x4b,0x46,0xfb,0x9e,0xfc,0x7f,0xd2, 0x5d,0x8b,0x2d,0xe8,0xf0,0x9c,0xa0,0x58, 0x7f,0x54,0xbd,0x28,0x72,0x99,0xf4,0x7b, 0x2f,0xf1,0x24,0xaa,0xc5,0x66,0xe8,0xee, 0x3b,0x43}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* k key inversion */ int8u inv_k[MBX_LANES][NISTP521_MAX_DATA_BYTE_LEN]; /* precomputed r signature component */ int8u precomp_r[MBX_LANES][NISTP521_MAX_DATA_BYTE_LEN]; /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // k key inversion int64u *pa_inv_k[MBX_LANES] = {(int64u *)inv_k[0], (int64u *)inv_k[1], (int64u *)inv_k[2], (int64u *)inv_k[3], (int64u *)inv_k[4], (int64u *)inv_k[5], (int64u *)inv_k[6], (int64u *)inv_k[7]}; // precomputed r signature component int64u *pa_precomp_r[MBX_LANES] = { (int64u *)precomp_r[0], (int64u *)precomp_r[1], (int64u *)precomp_r[2], (int64u *)precomp_r[3], (int64u *)precomp_r[4], (int64u *)precomp_r[5], (int64u *)precomp_r[6], (int64u *)precomp_r[7]}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test functions*/ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; // sign setup sts = mbx_nistp521_ecdsa_sign_setup_mb8(pa_inv_k, pa_precomp_r, pa_prv_k, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // sign complete sts = mbx_nistp521_ecdsa_sign_complete_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, (const int64u *const *)pa_precomp_r, (const int64u *const *)pa_inv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // compare output signature to known answer int r_output_status; int s_output_status; for (int i = 0; i < MBX_LANES; ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP521_DATA_BYTE_LEN, r, MBX_NISTP521_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP521_DATA_BYTE_LEN, s, MBX_NISTP521_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; break; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR_ARR1, BN_PTR_ARR2, BN_PTR3, BN_PTR4) { \ for (int i = 0; i < MBX_LANES; ++i) { \ BN_free(BN_PTR_ARR1[i]); \ BN_free(BN_PTR_ARR2[i]); \ } \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdsa_sign_setup_complete_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl key pair */ BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); /* k key inversion */ BIGNUM *pa_inv_k[MBX_LANES] = {BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; /* precomputed r signature component */ BIGNUM *pa_precomp_r[MBX_LANES] = {BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { if(NULL == pa_inv_k[i] || NULL == pa_precomp_r[i]) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } if(MBX_ALGO_SELFTEST_OK != test_result) { MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } /* output signature */ int8u out_r[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; int8u out_s[MBX_LANES][MBX_NISTP521_DATA_BYTE_LEN]; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity statuses */ int r_output_status; int s_output_status; // set ssl key pair BN_lebin2bn(d, MBX_NISTP521_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP521_DATA_BYTE_LEN, BN_k); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // key pair const BIGNUM *pa_prv_d[MBX_LANES] = {BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d, BN_d}; const BIGNUM *pa_prv_k[MBX_LANES] = {BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k, BN_k}; // output signature int8u *pa_sign_r[MBX_LANES] = {out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = {out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test functions */ // sign setup sts = mbx_nistp521_ecdsa_sign_setup_ssl_mb8(pa_inv_k, pa_precomp_r, pa_prv_k, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } // sign complete sts = mbx_nistp521_ecdsa_sign_complete_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, (const BIGNUM *const *)pa_precomp_r, (const BIGNUM *const *)pa_inv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } // compare output signature to known answer for (int i = 0; i < MBX_LANES; ++i) { r_output_status = mbx_is_mem_eq(pa_sign_r[i], MBX_NISTP521_DATA_BYTE_LEN, r, MBX_NISTP521_DATA_BYTE_LEN); s_output_status = mbx_is_mem_eq(pa_sign_s[i], MBX_NISTP521_DATA_BYTE_LEN, s, MBX_NISTP521_DATA_BYTE_LEN); if (!r_output_status || !s_output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; break; } } MEM_FREE(pa_inv_k, pa_precomp_r, BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp521_ecdsa_verify_mb8.c000066400000000000000000000226551470420105600355300ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #ifndef BN_OPENSSL_DISABLE #include #endif /* KAT TEST (taken from FIPS 186-4 examples) */ // msg == // "f69417bead3b1e208c4c99236bf84474a00de7f0b9dd23f991b6b60ef0fb3c62" // "073a5a7abb1ef69dbbd8cf61e64200ca086dfd645b641e8d02397782da92d354" // "2fbddf6349ac0b48b1b1d69fe462d1bb492f34dd40d137163843ac11bd099df7" // "19212c160cbebcb2ab6f3525e64846c887e1b52b52eced9447a3d31938593a87" /* msgDigest == SHA-521(msg) */ static const int8u msg_digest[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0x00,0x97,0xff,0x5a,0x81,0xfc,0x88, 0xf7,0xdd,0xd3,0xbc,0x58,0x15,0x4f,0xfd, 0x26,0x95,0x91,0x2f,0xe5,0x0c,0xe7,0xc6, 0x3b,0x62,0xbd,0x79,0x8f,0xb6,0x73,0xc6, 0xaa,0x49,0xf5,0x4b,0xc7,0x30,0x1f,0xb7, 0xbd,0xdc,0x6e,0xdc,0x51,0xb7,0xe0,0xd0, 0xb4,0xde,0xc9,0xf8,0x08,0x51,0xff,0xf0, 0x2a,0x33,0x67,0x1a,0xd9,0xa4,0x06,0xbb, 0xab,0xe5}; /* public key */ static const int8u Qx[MBX_NISTP521_DATA_BYTE_LEN] = {0x67,0x48,0x03,0x48,0xc4,0xb9,0xcf,0xc7, 0x28,0xc7,0xcd,0x00,0x8e,0xa6,0x1f,0x7a, 0x5c,0xf1,0xa5,0x44,0x15,0x87,0x09,0xcd, 0x6b,0x65,0x06,0x6a,0x94,0xdc,0x80,0x88, 0x0d,0x4a,0x39,0x26,0xee,0x3e,0x69,0x4b, 0xc1,0x9c,0xbc,0xf0,0x19,0xbf,0x7c,0x92, 0x3b,0x84,0xc2,0xef,0x13,0xb4,0x41,0xfb, 0xef,0xc1,0xe5,0x38,0x54,0xe0,0x2b,0xeb, 0x53,0x01}; static const int8u Qy[MBX_NISTP521_DATA_BYTE_LEN] = {0xc1,0x9b,0xef,0x3e,0x23,0x89,0xbb,0x49, 0xc0,0x2d,0x87,0xc0,0xf0,0x3e,0x03,0x47, 0xfa,0xa4,0x2f,0x1f,0xd8,0x22,0x05,0xec, 0xd0,0xdd,0x38,0xf3,0x29,0x79,0x4e,0x37, 0xe3,0xec,0xd5,0x9e,0x51,0xb7,0x11,0x73, 0x31,0x09,0x8c,0x87,0x1d,0x7c,0xc1,0x32, 0xeb,0x9c,0x0a,0x97,0xb2,0x59,0x61,0x6e, 0xb1,0xf6,0xfc,0xe8,0xbc,0xec,0x8e,0xae, 0x43,0x01}; /* signature */ static const int8u r[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0xdd,0x63,0x39,0x47,0x44,0x6d,0x0d, 0x51,0xa9,0x6a,0x01,0x73,0xc0,0x11,0x25, 0x85,0x8a,0xbb,0x2b,0xec,0xe6,0x70,0xaf, 0x92,0x2a,0x92,0xde,0xdc,0xec,0x06,0x71, 0x36,0xc1,0xfa,0x92,0xe5,0xfa,0x73,0xd7, 0x11,0x6a,0xc9,0xc1,0xa4,0x2b,0x9c,0xb6, 0x42,0xe4,0xac,0x19,0x31,0x0b,0x04,0x9e, 0x48,0xc5,0x30,0x11,0xff,0xc6,0xe7,0x46, 0x1c,0x36}; static const int8u s[MBX_NISTP521_DATA_BYTE_LEN] = {0x00,0xef,0xbd,0xc6,0xa4,0x14,0xbb,0x8d, 0x66,0x3b,0xb5,0xcd,0xb7,0xc5,0x86,0xbc, 0xcf,0xe7,0x58,0x90,0x49,0x07,0x6f,0x98, 0xce,0xe8,0x2c,0xdb,0x5d,0x20,0x3f,0xdd, 0xb2,0xe0,0xff,0xb7,0x79,0x54,0x95,0x9d, 0xfa,0x5e,0xd0,0xde,0x85,0x0e,0x42,0xa8, 0x6f,0x5a,0x63,0xc5,0xa6,0x59,0x2e,0x9b, 0x9b,0x8b,0xd1,0xb4,0x05,0x57,0xb9,0xcd, 0x0c,0xc0}; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdsa_verify_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // public key const int64u *const pa_pub_Qx[MBX_LANES] = { (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx, (const int64u *const)Qx}; const int64u *const pa_pub_Qy[MBX_LANES] = { (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy, (const int64u *const)Qy}; // signature const int8u *const pa_sign_r[MBX_LANES] = {r, r, r, r, r, r, r, r}; const int8u *const pa_sign_s[MBX_LANES] = {s, s, s, s, s, s, s, s}; /* test function */ mbx_status expected_sts_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp521_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_pub_Qx, pa_pub_Qy, NULL, NULL); if (expected_sts_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE #define MEM_FREE(BN_PTR1, BN_PTR2, SIG_PTR1) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ ECDSA_SIG_free(SIG_PTR1); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecdsa_verify_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* ssl public key */ BIGNUM *BN_Qx = BN_new(); BIGNUM *BN_Qy = BN_new(); // set ssl public key BN_lebin2bn(Qx, MBX_NISTP521_DATA_BYTE_LEN, BN_Qx); BN_lebin2bn(Qy, MBX_NISTP521_DATA_BYTE_LEN, BN_Qy); // set ssl signature BIGNUM *BN_r = BN_new(); BIGNUM *BN_s = BN_new(); ECDSA_SIG *sig = ECDSA_SIG_new(); /* check if allocated memory is valid */ if(NULL == BN_Qx || NULL == BN_Qy || NULL == BN_r || NULL == BN_s || NULL == sig) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_Qx, BN_Qy, sig) // Handled separately, since memory management of // these variables is transferred to sig below BN_free(BN_r); BN_free(BN_s); return test_result; } BN_bin2bn(r, MBX_NISTP521_DATA_BYTE_LEN, BN_r); BN_bin2bn(s, MBX_NISTP521_DATA_BYTE_LEN, BN_s); ECDSA_SIG_set0(sig, BN_r, BN_s); /* function input parameters */ // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; // public key const BIGNUM *const pa_pub_Qx[MBX_LANES] = {BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx, BN_Qx}; const BIGNUM *const pa_pub_Qy[MBX_LANES] = {BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy, BN_Qy}; // signature const ECDSA_SIG *const pa_sig[MBX_LANES] = {sig, sig, sig, sig, sig, sig, sig, sig}; /* test function */ mbx_status expected_sts_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp521_ecdsa_verify_ssl_mb8(pa_sig, pa_pub_msg_digest, pa_pub_Qx, pa_pub_Qy, NULL, NULL); if (expected_sts_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free BN_free(BN_Qx); BN_free(BN_Qy); ECDSA_SIG_free(sig); return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_nistp521_ecpublic_key_mb8.c000066400000000000000000000265021470420105600355160ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #ifndef BN_OPENSSL_DISABLE #include #endif #define NISTP521_MAX_DATA_BYTE_LEN ((((MBX_NISTP521_DATA_BYTE_LEN - 1) / 8) + 1) * 8) /* Pairwise Consistency Test for EC p521 keypair */ /* KAT data taken from FIPS 186-4 examples */ // msg == // "9ecd500c60e701404922e58ab20cc002651fdee7cbc9336adda33e4c1088fab1" // "964ecb7904dc6856865d6c8e15041ccf2d5ac302e99d346ff2f686531d255216" // "78d4fd3f76bbf2c893d246cb4d7693792fe18172108146853103a51f824acc62" // "1cb7311d2463c3361ea707254f2b052bc22cb8012873dcbb95bf1a5cc53ab89f" /* msgDigest == SHA-521(msg) */ static const int8u msg_digest[MBX_NISTP521_DATA_BYTE_LEN] = { 0x00,0x00,0x65,0xf8,0x34,0x08,0x09,0x22,0x61,0xbd,0xa5,0x99,0x38,0x9d,0xf0,0x33, 0x82,0xc5,0xbe,0x01,0xa8,0x1f,0xe0,0x0a,0x36,0xf3,0xf4,0xbb,0x65,0x41,0x26,0x3f, 0x80,0x16,0x27,0xc4,0x40,0xe5,0x08,0x09,0x71,0x2b,0x0c,0xac,0xe7,0xc2,0x17,0xe6, 0xe5,0x05,0x1a,0xf8,0x1d,0xe9,0xbf,0xec,0x32,0x04,0xdc,0xd6,0x3c,0x4f,0x9a,0x74, 0x10,0x47}; /* private key */ static const int8u d[MBX_NISTP521_DATA_BYTE_LEN] = { 0x26,0xb9,0x4c,0xa1,0x7a,0x56,0x5e,0x6c,0xee,0x9f,0xcf,0xcc,0xc0,0x55,0x86,0x8c, 0x21,0x0f,0x9a,0xc2,0xcc,0x74,0xf5,0x72,0x9b,0x35,0xa2,0xdc,0x80,0x00,0xab,0x2f, 0xf0,0xfa,0x7f,0x26,0x86,0xb8,0x7d,0xed,0x15,0xe5,0x78,0x26,0x8d,0xf0,0x67,0xba, 0x4f,0x8f,0x3d,0x10,0xcf,0x0a,0xef,0x2c,0xa8,0x3c,0x53,0xbc,0x04,0x27,0xd3,0x49, 0xf7,0x00}; static const int8u k[MBX_NISTP521_DATA_BYTE_LEN] = { 0xf1,0x6d,0x4c,0x86,0x3e,0x59,0xc7,0x83,0xbb,0xec,0xd4,0x33,0xa7,0x0a,0x3f,0xec, 0xfc,0x81,0xf8,0xdc,0xc9,0x9a,0xdb,0xf3,0xe1,0xcf,0x46,0xcf,0xfe,0x12,0x2d,0x81, 0x60,0xac,0xde,0xdd,0x3c,0x05,0xe3,0x9b,0x76,0x0c,0xc6,0xb5,0x52,0xcd,0xff,0x17, 0x6a,0xb1,0xc3,0x83,0xaa,0xb9,0xba,0xa5,0x86,0xde,0xa6,0x29,0xaa,0x6c,0xab,0xf5, 0x3a,0x00}; /* output signature buffers */ static int8u out_r[MBX_LANES][NISTP521_MAX_DATA_BYTE_LEN]; static int8u out_s[MBX_LANES][NISTP521_MAX_DATA_BYTE_LEN]; DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecpublic_key_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function input parameters */ // private key const int64u *const pa_prv_d[MBX_LANES] = { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; const int64u *const pa_prv_k[MBX_LANES] = { (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k, (int64u *)k}; // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; /* function output parameters */ // output public key int8u out_Qx[MBX_LANES][NISTP521_MAX_DATA_BYTE_LEN]; int8u out_Qy[MBX_LANES][NISTP521_MAX_DATA_BYTE_LEN]; // public key int64u *pa_pub_Qx[MBX_LANES] = { (int64u *)out_Qx[0], (int64u *)out_Qx[1], (int64u *)out_Qx[2], (int64u *)out_Qx[3], (int64u *)out_Qx[4], (int64u *)out_Qx[5], (int64u *)out_Qx[6], (int64u *)out_Qx[7]}; int64u *pa_pub_Qy[MBX_LANES] = { (int64u *)out_Qy[0], (int64u *)out_Qy[1], (int64u *)out_Qy[2], (int64u *)out_Qy[3], (int64u *)out_Qy[4], (int64u *)out_Qy[5], (int64u *)out_Qy[6], (int64u *)out_Qy[7]}; // output signature int8u *pa_sign_r[MBX_LANES] = { out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = { out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_nistp521_ecpublic_key_mb8(pa_pub_Qx, pa_pub_Qy, NULL, pa_prv_d, NULL); if (sts != expected_status_mb8){ if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // Add const qualifiers to arrays const int64u* const * _pa_pub_Qx = (const int64u* const *)pa_pub_Qx; const int64u* const * _pa_pub_Qy = (const int64u* const *)pa_pub_Qy; // sign and verify with the generated keypair sts = mbx_nistp521_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (sts != expected_status_mb8) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } return test_result; } // Add const qualifiers to arrays const int8u* const * _pa_sign_r = (const int8u* const *)pa_sign_r; const int8u* const * _pa_sign_s = (const int8u* const *)pa_sign_s; sts = mbx_nistp521_ecdsa_verify_mb8(_pa_sign_r, _pa_sign_s, pa_pub_msg_digest, _pa_pub_Qx, _pa_pub_Qy, NULL, NULL); // check the result of verification if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR_ARR1, BN_PTR_ARR2, SIG_PTR_ARR3, BN_PTR4, BN_PTR5) { \ for (int i = 0; i < MBX_LANES; ++i) { \ BN_free(BN_PTR_ARR1[i]); \ BN_free(BN_PTR_ARR2[i]); \ ECDSA_SIG_free(SIG_PTR_ARR3[i]); \ } \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_nistp521_ecpublic_key_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* functions input parameters */ // ssl private key BIGNUM *BN_d = BN_new(); BIGNUM *BN_k = BN_new(); // public key BIGNUM *pa_pub_Qx[MBX_LANES] = { BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; BIGNUM *pa_pub_Qy[MBX_LANES] = { BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new(), BN_new()}; // signature for verify API ECDSA_SIG *const pa_sig[MBX_LANES] = { ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new(), ECDSA_SIG_new()}; /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_k) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } for(int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { if(NULL == pa_pub_Qx[i] || NULL == pa_pub_Qy[i] || NULL == pa_sig[i]) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } if(MBX_ALGO_SELFTEST_OK != test_result) { MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // set ssl private key BN_lebin2bn(d, MBX_NISTP521_DATA_BYTE_LEN, BN_d); BN_lebin2bn(k, MBX_NISTP521_DATA_BYTE_LEN, BN_k); // private key const BIGNUM *const pa_prv_d[MBX_LANES] = { (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d, (const BIGNUM *const)BN_d}; const BIGNUM *const pa_prv_k[MBX_LANES] = { (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k, (const BIGNUM *const)BN_k}; // msg digest const int8u *const pa_pub_msg_digest[MBX_LANES] = { msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest, msg_digest}; /* functions output parameters */ // output signature for sign API int8u *pa_sign_r[MBX_LANES] = { out_r[0], out_r[1], out_r[2], out_r[3], out_r[4], out_r[5], out_r[6], out_r[7]}; int8u *pa_sign_s[MBX_LANES] = { out_s[0], out_s[1], out_s[2], out_s[3], out_s[4], out_s[5], out_s[6], out_s[7]}; /* test function */ sts = mbx_nistp521_ecpublic_key_ssl_mb8(pa_pub_Qx, pa_pub_Qy, NULL, pa_prv_d, NULL); if (sts != expected_status_mb8){ if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // Add const qualifiers to arrays const BIGNUM* const * _pa_pub_Qx = (const BIGNUM* const *)pa_pub_Qx; const BIGNUM* const * _pa_pub_Qy = (const BIGNUM* const *)pa_pub_Qy; // sign and verify with the generated keypair sts = mbx_nistp521_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_pub_msg_digest, pa_prv_k, pa_prv_d, NULL); if (sts != expected_status_mb8){ if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } // fill ECDSA_SIG structure with the generated signature for verification for (int i = 0; i < MBX_LANES; ++i){ BIGNUM *BN_r = BN_new(); BIGNUM *BN_s = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_r || NULL == BN_s) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) // Handled separately, since memory management of // these variables is transferred to sig below BN_free(BN_r); BN_free(BN_s); return test_result; } BN_bin2bn(out_r[i], MBX_NISTP521_DATA_BYTE_LEN, BN_r); BN_bin2bn(out_s[i], MBX_NISTP521_DATA_BYTE_LEN, BN_s); ECDSA_SIG_set0(pa_sig[i], BN_r, BN_s); } sts = mbx_nistp521_ecdsa_verify_ssl_mb8((const ECDSA_SIG *const *)pa_sig, pa_pub_msg_digest, _pa_pub_Qx, _pa_pub_Qy, NULL, NULL); // check the result of verification if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } MEM_FREE(pa_pub_Qx, pa_pub_Qy, pa_sig, BN_d, BN_k) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_rsa1k_private_crt_mb8.c000066400000000000000000000253371470420105600350430ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif /* Selftests are disabled for now, since rsa 1k scheme is not FIPS-approved */ #if 0 #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* plaintext */ static const int8u plaintext[MBX_RSA1K_DATA_BYTE_LEN] = { 0xc5,0x87,0x62,0x86,0x7f,0x60,0xa1,0x20,0xd1,0x8c,0x60,0xf6,0x9a,0xd5,0x5b,0x43, 0x19,0x53,0xb9,0xb0,0x67,0xe6,0xb3,0x3b,0xd1,0x03,0x73,0x13,0x3e,0x25,0x20,0x47, 0x44,0x9f,0xaa,0x6c,0xca,0x57,0xfd,0xcf,0xfd,0x2b,0x33,0x9b,0xb5,0x4f,0x4c,0xde, 0x59,0x0a,0x7d,0xcb,0x80,0x47,0x6d,0x54,0x59,0x0e,0x2b,0x8b,0x43,0x19,0x43,0x7d, 0x05,0x2d,0xd6,0x55,0xfe,0x08,0xe2,0x4f,0xda,0xae,0xf4,0xc1,0x3f,0x6e,0x61,0x30, 0xc4,0xe6,0x02,0x36,0xfc,0xa7,0xbe,0xc5,0xff,0xdc,0xd0,0xe4,0x5e,0x27,0x32,0xa5, 0xa9,0xde,0xca,0xd3,0x2d,0xaa,0x3f,0x7a,0x61,0x3f,0x6e,0xf7,0xf1,0x27,0xda,0x3a, 0xd5,0x71,0x4f,0xf1,0xbf,0x2f,0xbb,0xa8,0x89,0xa1,0x06,0xad,0x73,0xd4,0x63,0x7d}; /* ciphertext */ static const int8u ciphertext[MBX_RSA1K_DATA_BYTE_LEN] = { 0x91,0x43,0x4f,0x37,0xcb,0xf8,0x26,0xa6,0x74,0x2c,0xb9,0x9c,0x8b,0x09,0xfe,0x01, 0x1f,0x3a,0x01,0xc5,0x1f,0xeb,0xd9,0xea,0xc7,0x8f,0xcb,0x4d,0xf3,0xfb,0xef,0xf3, 0x73,0xe9,0xcf,0x16,0x8d,0xaf,0x05,0x60,0xd2,0x72,0x45,0xb1,0xc9,0xcd,0xb3,0x07, 0xdc,0x3f,0x81,0x2e,0x96,0x63,0xe7,0xf2,0xc4,0x92,0x6e,0x96,0xfd,0x62,0x5d,0x6f, 0xac,0xa5,0x2c,0x2e,0x21,0x91,0xe2,0xe1,0xb5,0x9a,0xb3,0xf7,0xc3,0x0c,0x1c,0x2f, 0x84,0xea,0x1d,0xe8,0xc7,0xc3,0x5b,0xb6,0x1a,0x3c,0x0d,0x22,0xc0,0x23,0x2b,0xa2, 0xb0,0x0a,0x7e,0x36,0x35,0x99,0xce,0x0d,0x0a,0xdf,0x34,0x9f,0xae,0x44,0x49,0xdb, 0x4e,0x8d,0x8a,0x7a,0x57,0xda,0xf0,0x9b,0x53,0x94,0x29,0xf0,0x3a,0x62,0x01,0x6f}; /* p, q primes */ static const int8u p[MBX_RSA1K_DATA_BYTE_LEN / 2] = { 0xb9,0x09,0x65,0xa8,0xc9,0xa3,0xa4,0x03,0x57,0xec,0x9f,0x1b,0xc1,0x6d,0xee,0xb8, 0x49,0xf0,0xf7,0x81,0xbc,0x75,0x43,0x34,0xdf,0x66,0xa3,0xeb,0xb7,0xab,0x83,0x57, 0x66,0x73,0xee,0x2f,0x82,0x95,0x18,0x10,0xaa,0xe9,0x9e,0x65,0xf7,0xca,0xe4,0x9a, 0x9d,0xc3,0xbd,0xe7,0xb5,0xd4,0xf0,0xf2,0x78,0xae,0x7f,0x0f,0xa4,0xea,0x9a,0xef}; static const int8u q[MBX_RSA1K_DATA_BYTE_LEN / 2] = { 0x53,0xc9,0x40,0x13,0x28,0x8a,0xf4,0x5c,0xf1,0xfa,0x6e,0xba,0xf0,0x5a,0x77,0x2c, 0x8c,0xa5,0x89,0xea,0xa4,0xd7,0x15,0x6d,0x75,0x63,0xaf,0xd3,0x5b,0x47,0x81,0x42, 0xff,0x0c,0x79,0x34,0x28,0x50,0xa1,0xf5,0x54,0x7e,0x78,0xcc,0x82,0x4f,0xb3,0x45, 0x43,0x82,0x94,0x98,0xb0,0xe7,0x8b,0x0f,0x4a,0xb4,0x35,0x15,0xdb,0xce,0x51,0xdc}; /* p's, q's CRT private exponent */ static const int8u dp[MBX_RSA1K_DATA_BYTE_LEN / 2] = { 0xd1,0x4f,0x50,0x2e,0x22,0xdb,0xbb,0x19,0xe1,0x1f,0x4b,0x28,0xee,0xf6,0xfb,0xc2, 0x90,0x46,0x4c,0x02,0xd6,0x27,0x75,0xc3,0x5d,0x5a,0x66,0x8f,0x47,0x1c,0x49,0xf1, 0x51,0x47,0x11,0xf1,0x94,0xc3,0xf0,0x16,0xec,0x6d,0x4b,0xe9,0xb2,0xf7,0xb5,0x0b, 0x42,0xd6,0xb9,0x9e,0x31,0xba,0xf7,0x62,0xd5,0xe5,0x91,0xce,0xcd,0xca,0xd7,0xbd}; static const int8u dq[MBX_RSA1K_DATA_BYTE_LEN / 2] = { 0x8b,0xd9,0x78,0x8c,0xa0,0xd7,0x4a,0x19,0xb0,0xbc,0x0f,0xea,0x5b,0xa5,0x12,0x28, 0xd6,0xea,0x95,0x7f,0x23,0x5c,0x87,0x4b,0xbb,0xa7,0x10,0xbc,0x57,0x78,0xd3,0xed, 0x36,0x7e,0x33,0x9e,0xc7,0xfb,0x19,0x2b,0x31,0x03,0x60,0x2f,0x1d,0x2c,0xe7,0x4f, 0x19,0xa0,0x12,0xd4,0x10,0x9d,0x86,0xa7,0xcb,0xce,0x1b,0x70,0x9b,0xa0,0x45,0x34}; /* CRT coefficient */ static const int8u inv_q[MBX_RSA1K_DATA_BYTE_LEN / 2] = { 0x33,0x50,0x88,0x58,0x0f,0x2d,0x9a,0x01,0x7d,0xd5,0x10,0xcb,0x1d,0x76,0xd4,0x67, 0xd1,0xac,0x69,0x9a,0x56,0xea,0x6e,0xbf,0x90,0x1e,0x9a,0x4e,0xcd,0x2a,0x20,0x28, 0xec,0xa0,0x8b,0xaf,0x43,0xba,0xd0,0x73,0x8f,0xf3,0xbb,0xc3,0x6c,0xe0,0xa3,0x82, 0x5f,0x46,0x50,0xba,0xc9,0x01,0x6c,0x97,0xfe,0x78,0x68,0x33,0xad,0x90,0xad,0x11}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa1k_private_crt_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA1K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA1K_private_crt_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const int64u *pa_p[MBX_LANES]= { (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p}; const int64u *pa_q[MBX_LANES]= { (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q}; /* p's, q's CRT private exponent */ const int64u *pa_dp[MBX_LANES]= { (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp}; const int64u *pa_dq[MBX_LANES]= { (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq}; /* CRT coefficient */ const int64u *pa_inv_q[MBX_LANES]= { (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_crt_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA1K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA1K_DATA_BYTE_LEN, plaintext, MBX_RSA1K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3, BN_PTR4, BN_PTR5) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa1k_private_crt_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA1K_DATA_BYTE_LEN]; /* ssl parameters */ // p, q primes BIGNUM* BN_p = BN_new(); BIGNUM* BN_q = BN_new(); // p's, q's CRT private exponent BIGNUM* BN_dp = BN_new(); BIGNUM* BN_dq = BN_new(); // CRT coefficient BIGNUM* BN_inv_q = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_p || NULL == BN_q || NULL == BN_dp || NULL == BN_dq || NULL == BN_inv_q) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(p, MBX_RSA1K_DATA_BYTE_LEN / 2, BN_p); BN_lebin2bn(q, MBX_RSA1K_DATA_BYTE_LEN / 2, BN_q); BN_lebin2bn(dp, MBX_RSA1K_DATA_BYTE_LEN / 2, BN_dp); BN_lebin2bn(dq, MBX_RSA1K_DATA_BYTE_LEN / 2, BN_dq); BN_lebin2bn(inv_q, MBX_RSA1K_DATA_BYTE_LEN / 2, BN_inv_q); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const BIGNUM *pa_p[MBX_LANES] = { (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p}; const BIGNUM *pa_q[MBX_LANES] = { (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q}; // p's, q's CRT private exponent const BIGNUM *pa_dp[MBX_LANES] = { (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp}; const BIGNUM *pa_dq[MBX_LANES] = { (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq}; // CRT coefficient const BIGNUM *pa_inv_q[MBX_LANES] = { (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q}; /* test function */ sts = mbx_rsa_private_crt_ssl_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA1K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA1K_DATA_BYTE_LEN, plaintext, MBX_RSA1K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE #endif // #if 0cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa1k_private_mb8.c000066400000000000000000000205021470420105600342370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif /* Selftests are disabled for now, since rsa 1k scheme is not FIPS-approved */ #if 0 #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA1K_DATA_BYTE_LEN] = { 0xfb,0x67,0xa4,0x16,0x7c,0x47,0x3f,0xe4,0xa0,0x00,0x48,0xc1,0x5e,0x7f,0x84,0xcd, 0x90,0x10,0x23,0x59,0xeb,0x0b,0x60,0x8b,0x70,0x8f,0xe7,0x6e,0x51,0xf2,0xcc,0xff, 0x95,0x9f,0xdc,0xeb,0x6f,0xf6,0x85,0xa4,0x21,0xfe,0x3d,0x76,0x55,0xe6,0xed,0x58, 0x3c,0x80,0xa3,0xd7,0x1a,0xf5,0xcf,0x74,0x82,0xc0,0x02,0x3e,0xdd,0xa4,0xc5,0xf6, 0x06,0xd3,0xcd,0x23,0x45,0xa4,0x0e,0x51,0x16,0x49,0xc4,0xd1,0x71,0xed,0xe2,0x32, 0xe7,0x77,0x31,0x7e,0xbb,0x09,0x18,0x54,0xd1,0xe4,0x86,0xfe,0x1b,0x5a,0xdd,0x94, 0x96,0xa5,0x97,0xa8,0x95,0x40,0xa6,0x10,0x70,0xbc,0xc6,0xdb,0xef,0xe8,0xad,0x2f, 0x75,0x81,0x7a,0xa3,0xbd,0x4c,0x38,0x6d,0x38,0x59,0x6b,0xf1,0x44,0xb3,0x35,0xce}; /* private exponent */ static const int8u d[MBX_RSA1K_DATA_BYTE_LEN] = { 0xe1,0x47,0xd2,0x67,0x25,0xe6,0x18,0x4d,0xaf,0xf5,0x06,0x57,0x18,0x8e,0x5c,0xe9, 0xbe,0xf4,0x37,0xe3,0xa6,0x35,0xd5,0xc4,0xb1,0x42,0x80,0xe6,0x12,0x59,0x46,0x6b, 0xc7,0x55,0x8c,0x98,0xc8,0x2f,0x09,0x4c,0x39,0x61,0x20,0x86,0x29,0x38,0x91,0xe4, 0x6c,0x95,0xc6,0xdb,0xbb,0x64,0x44,0x32,0x50,0x19,0x54,0x05,0x49,0xb4,0xb8,0xfe, 0x03,0x7c,0xab,0x28,0x95,0x1a,0x90,0xc7,0x32,0x34,0x6d,0xdc,0xaf,0xaf,0x3b,0xe5, 0xc8,0x0d,0x82,0x9e,0xe2,0x67,0x0b,0x86,0x68,0xbd,0xdc,0x00,0x71,0xd6,0x4c,0x30, 0x91,0x27,0x25,0xe3,0x25,0xc8,0x18,0x30,0x78,0x5b,0xec,0xb9,0xbe,0xab,0xdd,0x92, 0x1b,0x94,0x92,0x96,0x97,0xf0,0x77,0x66,0xbe,0x51,0x9b,0xef,0x72,0x43,0x1a,0x3a}; /* plaintext */ static const int8u plaintext[MBX_RSA1K_DATA_BYTE_LEN] = { 0xc5,0x87,0x62,0x86,0x7f,0x60,0xa1,0x20,0xd1,0x8c,0x60,0xf6,0x9a,0xd5,0x5b,0x43, 0x19,0x53,0xb9,0xb0,0x67,0xe6,0xb3,0x3b,0xd1,0x03,0x73,0x13,0x3e,0x25,0x20,0x47, 0x44,0x9f,0xaa,0x6c,0xca,0x57,0xfd,0xcf,0xfd,0x2b,0x33,0x9b,0xb5,0x4f,0x4c,0xde, 0x59,0x0a,0x7d,0xcb,0x80,0x47,0x6d,0x54,0x59,0x0e,0x2b,0x8b,0x43,0x19,0x43,0x7d, 0x05,0x2d,0xd6,0x55,0xfe,0x08,0xe2,0x4f,0xda,0xae,0xf4,0xc1,0x3f,0x6e,0x61,0x30, 0xc4,0xe6,0x02,0x36,0xfc,0xa7,0xbe,0xc5,0xff,0xdc,0xd0,0xe4,0x5e,0x27,0x32,0xa5, 0xa9,0xde,0xca,0xd3,0x2d,0xaa,0x3f,0x7a,0x61,0x3f,0x6e,0xf7,0xf1,0x27,0xda,0x3a, 0xd5,0x71,0x4f,0xf1,0xbf,0x2f,0xbb,0xa8,0x89,0xa1,0x06,0xad,0x73,0xd4,0x63,0x7d}; /* ciphertext */ static const int8u ciphertext[MBX_RSA1K_DATA_BYTE_LEN] = { 0x91,0x43,0x4f,0x37,0xcb,0xf8,0x26,0xa6,0x74,0x2c,0xb9,0x9c,0x8b,0x09,0xfe,0x01, 0x1f,0x3a,0x01,0xc5,0x1f,0xeb,0xd9,0xea,0xc7,0x8f,0xcb,0x4d,0xf3,0xfb,0xef,0xf3, 0x73,0xe9,0xcf,0x16,0x8d,0xaf,0x05,0x60,0xd2,0x72,0x45,0xb1,0xc9,0xcd,0xb3,0x07, 0xdc,0x3f,0x81,0x2e,0x96,0x63,0xe7,0xf2,0xc4,0x92,0x6e,0x96,0xfd,0x62,0x5d,0x6f, 0xac,0xa5,0x2c,0x2e,0x21,0x91,0xe2,0xe1,0xb5,0x9a,0xb3,0xf7,0xc3,0x0c,0x1c,0x2f, 0x84,0xea,0x1d,0xe8,0xc7,0xc3,0x5b,0xb6,0x1a,0x3c,0x0d,0x22,0xc0,0x23,0x2b,0xa2, 0xb0,0x0a,0x7e,0x36,0x35,0x99,0xce,0x0d,0x0a,0xdf,0x34,0x9f,0xae,0x44,0x49,0xdb, 0x4e,0x8d,0x8a,0x7a,0x57,0xda,0xf0,0x9b,0x53,0x94,0x29,0xf0,0x3a,0x62,0x01,0x6f}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa1k_private_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA1K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA1K_private_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // private exponent const int64u *pa_d[MBX_LANES]= { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA1K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA1K_DATA_BYTE_LEN, plaintext, MBX_RSA1K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa1k_private_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA1K_DATA_BYTE_LEN]; /* ssl private exponent */ BIGNUM* BN_d = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(d, MBX_RSA1K_DATA_BYTE_LEN, BN_d); BN_lebin2bn(moduli, MBX_RSA1K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; // private exponent const BIGNUM *pa_d[MBX_LANES] = { (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d}; /* test function */ sts = mbx_rsa_private_ssl_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA1K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA1K_DATA_BYTE_LEN, plaintext, MBX_RSA1K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE #endif // #if 0 cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa1k_public_mb8.c000066400000000000000000000170371470420105600340540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif /* Selftests are disabled for now, since rsa 1k scheme is not FIPS-approved */ #if 0 #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA1K_DATA_BYTE_LEN] = { 0xf1,0x56,0x41,0xee,0x2e,0x6e,0x39,0x07,0x26,0x03,0x6a,0x49,0xcf,0x13,0x38,0xef, 0xd7,0x57,0xed,0x82,0xa7,0x9a,0xd5,0x85,0xc5,0xc0,0x16,0x86,0x05,0x84,0xa3,0xa4, 0x6b,0x3d,0x7f,0xa7,0xe1,0x6a,0x92,0x26,0x1c,0xb4,0x30,0x4b,0xaa,0xfb,0xf2,0x17, 0xcd,0x43,0x2e,0x4c,0x52,0x1a,0x7c,0xa3,0x43,0x46,0x0f,0xd1,0xa8,0x7f,0x18,0x2a, 0x34,0x19,0x0f,0x7f,0xc5,0xd5,0x6f,0x3a,0x23,0xb9,0xac,0xf0,0xb7,0x14,0x89,0x35, 0xe8,0xa3,0xd6,0x50,0x81,0x58,0xd4,0xe4,0xd9,0x64,0xbb,0xea,0x8c,0xd4,0x5d,0xe0, 0x2a,0x36,0xad,0x83,0xe1,0x92,0xa9,0xe3,0xf2,0xcb,0x56,0xc8,0x36,0xad,0x28,0x2e, 0x8f,0x04,0xaa,0x26,0xc6,0x62,0x78,0x62,0xe5,0xab,0x93,0x8a,0x80,0xd6,0xc5,0xc3}; /* plaintext */ static const int8u plaintext[MBX_RSA1K_DATA_BYTE_LEN] = { 0x27,0x7e,0x53,0x66,0x1e,0x56,0x7a,0x12,0xdf,0xef,0x04,0x8e,0x7d,0x2d,0xf6,0x4a, 0x68,0x1b,0xcd,0x5a,0x1c,0x79,0xbd,0x7f,0xdc,0x77,0xc6,0x7b,0xea,0xbe,0x26,0x8f, 0x8e,0x4d,0x7b,0xc5,0x07,0xcc,0xe1,0x7b,0x4b,0x1e,0xc2,0x45,0xfd,0x8b,0xf5,0x56, 0x16,0x45,0xa2,0x76,0x29,0xaf,0xe8,0x2d,0x1a,0x0f,0x69,0x1b,0x4f,0xe6,0xa9,0x5c, 0xd6,0x27,0xd1,0xbe,0x49,0xe1,0x87,0x75,0x13,0xe4,0xf4,0x2c,0xde,0xa4,0x03,0x5b, 0x9b,0xe9,0x11,0x29,0x7f,0x82,0xd7,0x74,0x2a,0xda,0xe3,0x7a,0xcb,0x23,0xab,0x1a, 0x78,0xc2,0x9d,0xef,0x2f,0xd5,0x95,0xcf,0x81,0x8e,0x89,0x38,0x2f,0x46,0x16,0xb1, 0x0e,0xab,0x91,0x75,0x2a,0x3c,0xbd,0xc8,0x00,0x61,0xc7,0x84,0x69,0xb6,0x5d,0xe2}; /* ciphertext */ static const int8u ciphertext[MBX_RSA1K_DATA_BYTE_LEN] = { 0x18,0x4d,0x50,0xc3,0xb8,0xa4,0xa8,0xc7,0x76,0x5e,0x4b,0x47,0xe0,0x50,0xe9,0xa6, 0xc5,0xe6,0x11,0xdf,0xf7,0x33,0x61,0x3c,0x89,0x70,0xc5,0xf9,0x8a,0x38,0x08,0xe6, 0x03,0x24,0xf1,0x1a,0xe1,0x7d,0x66,0xf6,0xc9,0xc8,0xd2,0x7c,0x7e,0x97,0xc4,0x3a, 0x62,0xa3,0x60,0x11,0xff,0x5c,0x80,0x27,0xba,0xc5,0x25,0x37,0xa7,0x75,0xb5,0x50, 0xb3,0xa6,0x61,0xd3,0x16,0xa4,0x9d,0x64,0x4f,0x9e,0xdb,0x43,0x5c,0xea,0xb4,0xfb, 0x68,0xa2,0xe7,0xb5,0x70,0x3d,0xc4,0xbe,0x1d,0xf4,0x9b,0xcb,0x3b,0xdc,0xa5,0xdb, 0xc2,0x7d,0xe4,0x44,0x65,0x92,0x88,0x32,0xd7,0x3f,0x87,0xd7,0x1e,0x71,0xb1,0x41, 0xe5,0xc1,0x8b,0xa1,0xd5,0x28,0x09,0x94,0x06,0x53,0x2c,0x4c,0x99,0x28,0x6d,0x8d}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa1k_public_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA1K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA1K_pub65537_Method(); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_public_mb8(pa_plaintext, pa_ciphertext, pa_moduli, MBX_RSA1K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output ciphertext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA1K_DATA_BYTE_LEN, ciphertext, MBX_RSA1K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE /* exponent (for ssl function only) */ static const int8u exponent[MBX_RSA_PUB_EXP_BYTE_LEN] = {0x01,0x00,0x01}; // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa1k_public_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA1K_DATA_BYTE_LEN]; /* ssl exponent */ BIGNUM* BN_e = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_e || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_e, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(exponent, MBX_RSA_PUB_EXP_BYTE_LEN, BN_e); BN_lebin2bn(moduli, MBX_RSA1K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; // exponent const BIGNUM *pa_e[MBX_LANES] = { (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e}; /* test function */ sts = mbx_rsa_public_ssl_mb8(pa_plaintext, pa_ciphertext, pa_e, pa_moduli, MBX_RSA1K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA1K_DATA_BYTE_LEN, ciphertext, MBX_RSA1K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_e, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE #endif // #if 0 selftest_mbx_rsa2k_private_crt_mb8.c000066400000000000000000000333061470420105600350370ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* plaintext */ static const int8u plaintext[MBX_RSA2K_DATA_BYTE_LEN] = { 0x7c,0x79,0x2d,0xc8,0xfb,0x14,0x69,0x62,0x7c,0xcc,0xfd,0xc3,0xde,0x0b,0xc1,0x16, 0x8e,0xca,0xe8,0x6f,0x93,0x3f,0xbc,0x7c,0x0a,0xd4,0x46,0xd8,0x15,0xbd,0x9e,0xe1, 0x06,0x28,0x35,0x49,0x63,0xac,0x38,0x76,0xf1,0x3c,0x68,0xfb,0x42,0x1e,0x33,0xf9, 0x9f,0x53,0xe6,0xd6,0x33,0x90,0x55,0xbe,0xc7,0x05,0xc8,0xed,0xa5,0x4b,0xa3,0x83, 0xb9,0x78,0x19,0x55,0xd0,0x03,0x0a,0xad,0x3c,0xc3,0x44,0x03,0xf0,0x27,0x25,0xe4, 0xb8,0xe0,0x59,0xf9,0xda,0xb5,0xeb,0x9f,0x5d,0x63,0xb6,0x21,0xfc,0x29,0xe2,0xa9, 0xf3,0x8e,0x7b,0xb1,0x36,0xf8,0xb9,0x67,0x91,0x14,0xef,0x75,0xeb,0x95,0x37,0xd3, 0x03,0x5f,0x94,0x61,0xc6,0x42,0xe1,0x8a,0x36,0x36,0xb3,0xe4,0x3f,0x99,0x97,0x68, 0x75,0x85,0x9a,0xb9,0xd8,0x3c,0xa4,0x80,0xa4,0xdf,0xe5,0x16,0xfb,0x00,0x2c,0x18, 0x6b,0xa4,0x91,0x7d,0x6e,0x32,0xca,0xdb,0xd1,0xb5,0xae,0x78,0x1d,0x46,0x87,0xaf, 0xb9,0x10,0x8c,0x8a,0x3b,0x09,0x59,0x43,0x92,0x39,0xec,0x01,0xe0,0xb8,0x9e,0xad, 0x30,0x5b,0x0e,0x0d,0x62,0x1a,0xdb,0xdb,0xdf,0xcd,0x05,0x19,0x41,0x77,0xc7,0xf8, 0xd8,0x0c,0x41,0x57,0x67,0xa2,0x0a,0x56,0x67,0x77,0x04,0x5f,0xfd,0xc4,0x7b,0x0d, 0x41,0x22,0xdc,0x50,0x11,0x3b,0x0e,0xe1,0x6a,0x91,0x1e,0x5f,0x4c,0x01,0xf1,0xec, 0x8a,0x66,0x1b,0xf6,0xd3,0xbe,0xc9,0x98,0xad,0xa8,0x36,0x62,0xca,0x00,0xcb,0x76, 0xa4,0xb8,0xb4,0x94,0x3c,0x60,0xc8,0xdf,0xc9,0x6a,0xcd,0x9b,0x7d,0xb7,0x55,0x73}; /* ciphertext */ static const int8u ciphertext[MBX_RSA2K_DATA_BYTE_LEN] = { 0x8a,0x9b,0xf5,0xc2,0x9f,0xda,0x1b,0x63,0xd9,0x01,0xae,0x44,0xf5,0x7e,0x2c,0xec, 0xf4,0x5e,0x3a,0x02,0x20,0x43,0x39,0xd4,0x87,0xed,0x46,0x8e,0xc0,0x02,0x74,0x77, 0x5e,0x5e,0xaf,0xcd,0xe4,0x3a,0x70,0xd4,0xc7,0x47,0x9b,0xc3,0x9d,0x23,0x72,0xc7, 0x7c,0x0a,0x00,0xc9,0xa8,0xc8,0xe4,0x4c,0xd2,0x0f,0x26,0xd3,0x3f,0x03,0x87,0xbc, 0x8b,0xf8,0xe6,0x6c,0x9e,0xe8,0x18,0x88,0xfc,0xd2,0x1f,0x31,0xda,0xd6,0x09,0x63, 0x02,0xa9,0xf2,0x8c,0x3b,0x77,0x3f,0x2c,0xdc,0x1a,0x29,0xb1,0x06,0xb8,0xbf,0x98, 0x25,0xcd,0x70,0xd9,0x9d,0xf1,0xc2,0x19,0x8b,0x65,0x3e,0xce,0x49,0x25,0x4e,0x9f, 0x23,0x41,0x28,0x8e,0x90,0x46,0x91,0x2a,0xae,0xe2,0xd2,0x5c,0x46,0x28,0x87,0x94, 0x56,0xca,0x13,0x55,0x92,0xb4,0x7e,0x3a,0x0e,0xe4,0x28,0xf8,0xd4,0xa8,0x86,0x47, 0x29,0xc0,0xdc,0xdc,0xc6,0x98,0xb4,0x29,0x3e,0x9b,0x51,0x97,0x13,0x11,0xac,0x4d, 0x21,0x50,0x30,0xe8,0x44,0xcf,0xef,0x87,0x91,0xba,0x93,0x2e,0x2d,0xde,0xb5,0x87, 0x42,0x76,0x8f,0x66,0x74,0xf0,0xa8,0x0f,0x6b,0x37,0x74,0x91,0x82,0x78,0x8a,0x41, 0x31,0x29,0x5d,0x0d,0x4f,0x31,0x9f,0x04,0x3f,0xfa,0x6f,0x70,0x25,0xc3,0x21,0x7d, 0xb6,0x29,0x5f,0x84,0x8e,0xc3,0x12,0x7c,0xe6,0x8b,0xbd,0xf7,0x85,0x82,0x26,0xd8, 0x46,0x89,0xdb,0xa7,0x5e,0xd8,0x1d,0x8a,0xd8,0x17,0xcd,0x9c,0x62,0xf5,0x0c,0x1b, 0xa0,0x49,0xe9,0x19,0x81,0xaf,0x8c,0x80,0xaf,0x8f,0x8f,0x57,0x7f,0x4e,0xc9,0xb7}; /* p, q primes */ static const int8u p[MBX_RSA2K_DATA_BYTE_LEN / 2] = { 0x85,0x4f,0x39,0xb5,0x46,0x67,0x8b,0xb4,0x23,0x90,0xfb,0x9a,0x83,0x3b,0x17,0xe1, 0x37,0xbf,0xf7,0x8f,0x58,0x78,0x18,0xaf,0xa5,0x50,0xff,0x92,0xfb,0xbe,0xc3,0x55, 0x6f,0x68,0xa3,0xb4,0xd0,0x2f,0x05,0x10,0x06,0x16,0x53,0x28,0xe6,0x08,0x39,0x2b, 0x7d,0x92,0xbe,0xc2,0x9a,0x36,0x74,0x37,0x12,0x19,0x50,0x79,0x82,0x31,0xa8,0x88, 0xed,0xe7,0x7f,0x6e,0xe9,0xcc,0x80,0xf1,0x12,0xc8,0xbc,0xbd,0xaa,0x2e,0xad,0xe9, 0x7b,0x1e,0x16,0xb4,0x60,0xa3,0xd0,0x40,0x1f,0x1f,0x62,0x7c,0x60,0x34,0xc2,0xda, 0x9f,0x63,0x7a,0x41,0x62,0xd9,0x4c,0x04,0xad,0x93,0xb4,0xb4,0xbd,0x9b,0xf8,0x78, 0x74,0x5a,0x04,0x24,0x41,0xef,0x7d,0x28,0x93,0x6d,0xc6,0x06,0xb1,0xd4,0x59,0xcb}; static const int8u q[MBX_RSA2K_DATA_BYTE_LEN / 2] = { 0xd9,0x39,0x2b,0x02,0xcb,0xc5,0xf9,0x05,0x17,0x4e,0xa7,0x82,0x02,0x15,0x84,0xc1, 0xd0,0x9c,0xfb,0x63,0x1d,0x79,0x55,0x14,0x7e,0x09,0x95,0xf1,0x54,0xaf,0xc8,0x53, 0xa6,0xd6,0xd2,0xb8,0x28,0x84,0xcb,0x11,0x5c,0x6b,0xee,0x86,0x89,0x63,0x3a,0x52, 0x0a,0x9c,0xd2,0xf7,0x12,0x48,0x13,0xd3,0xd1,0x35,0x05,0xfa,0xaf,0xa6,0x1d,0x58, 0x0d,0xf5,0x9d,0x94,0xa6,0x0a,0xe1,0x2d,0x1f,0x2e,0x37,0xca,0xaf,0xca,0x53,0x72, 0x1b,0x5c,0x86,0x7b,0x35,0x96,0x5c,0x86,0x74,0xa8,0xb2,0x41,0x9b,0xce,0x08,0xbe, 0xf4,0x76,0xfd,0x92,0x9f,0x12,0xba,0xae,0xe9,0xee,0x71,0x6c,0x81,0x1c,0x96,0x93, 0x95,0xb0,0xa3,0xbc,0xaf,0xc0,0x04,0x0e,0x04,0x36,0xa7,0xfe,0xe9,0xc4,0x7f,0xca}; /* p's, q's CRT private exponent */ static const int8u dp[MBX_RSA2K_DATA_BYTE_LEN / 2] = { 0xcd,0x46,0xe8,0x8b,0x54,0xbf,0xb2,0xb8,0xe0,0x52,0x4e,0xc3,0xfd,0xfd,0x4f,0xe4, 0xef,0x89,0x60,0x5f,0xb1,0xdc,0x67,0x6d,0x4e,0x17,0x34,0xc1,0x3f,0x01,0x2f,0xb6, 0x1e,0x7a,0xcc,0x3f,0xa0,0xdd,0x3d,0xcf,0xb5,0x64,0x85,0x63,0x57,0xd9,0xb9,0xb4, 0x9d,0xe6,0x42,0x6b,0x7b,0x24,0x43,0xde,0x49,0xb3,0x01,0xd0,0x0c,0x18,0x13,0xd1, 0x5d,0xaa,0xde,0x86,0xd0,0x90,0xf4,0x6e,0x17,0x31,0xad,0x96,0xc8,0xe1,0x71,0xb2, 0xa8,0x2e,0xd7,0x41,0x38,0xef,0x94,0x6f,0xd0,0xcd,0x62,0xa0,0x6f,0x4e,0xe3,0x22, 0x7c,0x3e,0xf0,0x16,0x7e,0x41,0x97,0x44,0xa7,0xe9,0x97,0x6d,0x6d,0xea,0x9f,0x5e, 0x5c,0x43,0x71,0xd1,0xc4,0x0b,0x02,0xc4,0xb5,0x29,0x4a,0xf1,0x7b,0x70,0x1f,0x13}; static const int8u dq[MBX_RSA2K_DATA_BYTE_LEN / 2] = { 0x01,0xa0,0x8d,0x81,0xf4,0x12,0x67,0x77,0xff,0xed,0x4d,0x48,0x51,0x4e,0x9b,0xa6, 0xbf,0x46,0x01,0xb2,0x6d,0x31,0xf5,0xd6,0xce,0xb5,0x6a,0x38,0x34,0xb0,0xe3,0x58, 0xbf,0xa2,0x8f,0xc7,0xc1,0xc3,0x37,0xef,0xf3,0xa4,0x35,0x3c,0x6a,0xff,0xe9,0xaf, 0x5b,0xbb,0x36,0xa1,0xde,0xd0,0x05,0xb4,0x72,0x79,0x2a,0xbf,0x6e,0x7f,0xa2,0x73, 0x04,0xad,0x6a,0x58,0x6a,0xb2,0x14,0x0c,0xac,0x42,0x23,0xac,0x41,0x87,0x3f,0x1c, 0x8c,0x52,0x0a,0x2b,0xe9,0x5d,0x4b,0x55,0x32,0xfa,0x48,0xe5,0x1c,0x7e,0x4f,0x92, 0x3a,0xca,0xa6,0x9d,0xcc,0xc8,0x90,0xd3,0x62,0xf1,0x9b,0xc2,0xce,0x92,0xdf,0x9b, 0xb7,0x72,0xab,0xea,0x8a,0x45,0x9e,0xd7,0xaa,0x1b,0xfe,0x14,0xb1,0xc2,0x75,0x2f}; /* CRT coefficient */ static const int8u inv_q[MBX_RSA2K_DATA_BYTE_LEN / 2] = { 0x59,0x3e,0x24,0x2f,0xb3,0xc6,0x03,0xbf,0x1e,0xb5,0x5b,0xea,0xbf,0x33,0x00,0x66, 0x2f,0x9b,0x6c,0x65,0x9e,0x76,0x8e,0x92,0xb3,0x52,0xc3,0x05,0x85,0x87,0x41,0x44, 0x51,0x10,0x49,0xba,0x2b,0x37,0x4a,0x9a,0x40,0x88,0xf5,0x2f,0x44,0xed,0x96,0xfc, 0xa0,0xa5,0x25,0x58,0x25,0xc4,0xce,0xce,0x7f,0x75,0xc3,0x1e,0xb9,0x12,0xc8,0x65, 0x5f,0xc2,0xaf,0xfe,0x8d,0xde,0xb6,0x70,0x81,0x09,0x04,0xd2,0xf2,0x95,0x11,0x9c, 0x3b,0x56,0xd3,0xca,0x67,0x73,0xc9,0x19,0x3d,0x24,0x33,0x07,0x5f,0x32,0x94,0x36, 0x64,0x7d,0xdc,0x12,0xcf,0xd7,0x17,0x58,0xa5,0x68,0x94,0x93,0x6c,0x16,0xd2,0xec, 0x98,0xd5,0xdc,0xde,0xa2,0xe1,0x93,0x7a,0xb2,0xff,0xc9,0xd1,0xc5,0x57,0x66,0x92}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa2k_private_crt_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA2K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA2K_private_crt_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const int64u *pa_p[MBX_LANES]= { (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p}; const int64u *pa_q[MBX_LANES]= { (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q}; /* p's, q's CRT private exponent */ const int64u *pa_dp[MBX_LANES]= { (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp}; const int64u *pa_dq[MBX_LANES]= { (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq}; /* CRT coefficient */ const int64u *pa_inv_q[MBX_LANES]= { (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_crt_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA2K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA2K_DATA_BYTE_LEN, plaintext, MBX_RSA2K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3, BN_PTR4, BN_PTR5) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa2k_private_crt_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA2K_DATA_BYTE_LEN]; /* ssl parameters */ // p, q primes BIGNUM* BN_p = BN_new(); BIGNUM* BN_q = BN_new(); // p's, q's CRT private exponent BIGNUM* BN_dp = BN_new(); BIGNUM* BN_dq = BN_new(); // CRT coefficient BIGNUM* BN_inv_q = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_p || NULL == BN_q || NULL == BN_dp || NULL == BN_dq || NULL == BN_inv_q) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(p, MBX_RSA2K_DATA_BYTE_LEN / 2, BN_p); BN_lebin2bn(q, MBX_RSA2K_DATA_BYTE_LEN / 2, BN_q); BN_lebin2bn(dp, MBX_RSA2K_DATA_BYTE_LEN / 2, BN_dp); BN_lebin2bn(dq, MBX_RSA2K_DATA_BYTE_LEN / 2, BN_dq); BN_lebin2bn(inv_q, MBX_RSA2K_DATA_BYTE_LEN / 2, BN_inv_q); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const BIGNUM *pa_p[MBX_LANES] = { (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p}; const BIGNUM *pa_q[MBX_LANES] = { (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q}; // p's, q's CRT private exponent const BIGNUM *pa_dp[MBX_LANES] = { (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp}; const BIGNUM *pa_dq[MBX_LANES] = { (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq}; // CRT coefficient const BIGNUM *pa_inv_q[MBX_LANES] = { (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q}; /* test function */ sts = mbx_rsa_private_crt_ssl_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA2K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA2K_DATA_BYTE_LEN, plaintext, MBX_RSA2K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa2k_private_mb8.c000066400000000000000000000257331470420105600342530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA2K_DATA_BYTE_LEN] = { 0xbd,0x04,0xa0,0xc5,0xff,0x93,0x74,0xba,0x75,0xe8,0x35,0x4e,0xad,0x87,0x9c,0xbc, 0x8e,0xf4,0x8a,0x48,0x96,0x20,0xd3,0x5d,0x52,0x5b,0x4b,0x11,0x96,0x97,0x98,0x9a, 0x8d,0xa4,0x97,0xc0,0x7b,0xd3,0x40,0x23,0xe1,0x7b,0x21,0x11,0xc9,0x0c,0x56,0x53, 0xca,0x1c,0x3d,0xd3,0x34,0x4d,0xbd,0x18,0xe4,0x19,0xdf,0xeb,0x3b,0x70,0x2a,0x83, 0xbc,0x07,0xb5,0xd9,0xe5,0xa9,0x34,0x4a,0xab,0x12,0x4e,0xaf,0x70,0xdc,0x2a,0xe8, 0x7c,0xbf,0xe9,0xae,0x5c,0x18,0x57,0xa5,0xf4,0x10,0x5d,0xb7,0x5b,0x2d,0x30,0x8a, 0xf6,0xa5,0x02,0x43,0xb0,0xcc,0x88,0x66,0xa1,0x1b,0x32,0x52,0x05,0x32,0x54,0x6f, 0xb4,0x70,0x77,0x87,0xa6,0x8a,0xe0,0x11,0x55,0x92,0x19,0x79,0x12,0x35,0x47,0x0a, 0x70,0x7f,0x40,0x7b,0xa1,0x00,0x69,0x9b,0x87,0x4b,0xcb,0x82,0x8c,0xa0,0x26,0x9e, 0xb1,0xe3,0xce,0x53,0xd4,0xf1,0xb7,0x17,0x4c,0x30,0x85,0x7e,0xbb,0x0a,0xca,0xe0, 0x35,0xb2,0x48,0x6a,0x0b,0x64,0xd7,0x1d,0xa5,0xaa,0x16,0x43,0xc8,0xe1,0x6a,0xa8, 0x2f,0x29,0x96,0x7e,0x5f,0x8d,0x50,0x3e,0x25,0xf9,0x83,0xee,0x81,0xd8,0xd2,0xf2, 0xe8,0xa6,0x38,0xa5,0x12,0xc2,0xfc,0xa4,0x99,0x67,0x35,0x36,0x20,0x92,0xca,0x4d, 0x54,0xf4,0x49,0xe7,0x51,0x83,0xd8,0xbc,0x3a,0xf8,0xca,0x39,0xd0,0x18,0xb7,0x44, 0x0d,0x7f,0xef,0xdf,0x0f,0x10,0x21,0x2d,0x63,0xf5,0x6d,0xfc,0xfb,0x1f,0xe4,0x02, 0xa0,0x2b,0xd4,0xc9,0xa6,0x81,0x0e,0x20,0xbf,0x00,0x0d,0xd9,0xce,0x5f,0xda,0xa0}; /* private exponent */ static const int8u d[MBX_RSA2K_DATA_BYTE_LEN] = { 0xe1,0xe4,0x56,0xf8,0x27,0x35,0x72,0x59,0x8b,0xa9,0x05,0xee,0xbf,0xd0,0x45,0xa2, 0xe3,0xa0,0x35,0xc2,0x8a,0xed,0x5d,0xe5,0x1e,0x43,0x80,0x16,0x07,0xe8,0x2f,0x58, 0xa6,0xfd,0x58,0x81,0xbc,0x9e,0x60,0xd0,0x4b,0x93,0xf2,0x5e,0x19,0x9b,0xca,0x9c, 0x6e,0xcf,0x55,0x79,0xb6,0x28,0xf2,0x79,0x23,0x65,0xa7,0x57,0xb9,0x03,0x3a,0xa1, 0x8e,0x9a,0x17,0x54,0xc7,0xdb,0x3c,0x27,0x1d,0xd4,0x17,0x93,0x79,0x56,0x25,0xba, 0x31,0xb2,0xa1,0x1e,0x69,0xe5,0xc1,0x02,0x83,0x26,0xa4,0x76,0x69,0x35,0xcb,0xad, 0x0f,0xe2,0x97,0xfa,0x71,0xa2,0x86,0xa0,0x0b,0x13,0x1d,0x1b,0x68,0xa3,0xd8,0xdf, 0xea,0x28,0x57,0xd3,0x38,0x07,0x26,0x85,0x78,0xe4,0x91,0x0b,0xf0,0xd0,0xc3,0x4e, 0x5f,0x63,0x60,0x95,0x83,0x49,0x85,0x5a,0xe8,0x22,0xe7,0x4f,0xbe,0xc0,0x16,0x0f, 0xf8,0x4c,0x58,0xe6,0xf9,0x3a,0x8e,0x3e,0xec,0xfb,0x46,0x00,0x3b,0x1d,0x12,0x35, 0xfa,0x2b,0xd1,0x81,0xbd,0x70,0xc0,0xca,0x92,0xb7,0xb0,0x5c,0x62,0x97,0x63,0x7f, 0xb8,0x0a,0x64,0x99,0xdb,0x9b,0x22,0x2e,0x2a,0x7f,0x03,0xfc,0xd3,0x27,0xb3,0xc6, 0xfa,0xbe,0x12,0xd5,0x86,0xd0,0x4e,0xb0,0x2b,0x1c,0xee,0x13,0x89,0x59,0xcb,0x86, 0x9a,0xb3,0x73,0x42,0x57,0xc5,0x96,0x94,0x3b,0xae,0x2f,0x88,0xc1,0x66,0x4f,0x98, 0x29,0xcf,0x29,0x2d,0xe8,0x2a,0x80,0xa5,0xfb,0xaf,0xe0,0x4a,0x83,0x0c,0xa3,0x06, 0x22,0xb9,0x53,0x89,0x7d,0x7f,0x4b,0x61,0x0c,0x5b,0xc1,0xe7,0x80,0x01,0x83,0x5b}; /* plaintext */ static const int8u plaintext[MBX_RSA2K_DATA_BYTE_LEN] = { 0x7c,0x79,0x2d,0xc8,0xfb,0x14,0x69,0x62,0x7c,0xcc,0xfd,0xc3,0xde,0x0b,0xc1,0x16, 0x8e,0xca,0xe8,0x6f,0x93,0x3f,0xbc,0x7c,0x0a,0xd4,0x46,0xd8,0x15,0xbd,0x9e,0xe1, 0x06,0x28,0x35,0x49,0x63,0xac,0x38,0x76,0xf1,0x3c,0x68,0xfb,0x42,0x1e,0x33,0xf9, 0x9f,0x53,0xe6,0xd6,0x33,0x90,0x55,0xbe,0xc7,0x05,0xc8,0xed,0xa5,0x4b,0xa3,0x83, 0xb9,0x78,0x19,0x55,0xd0,0x03,0x0a,0xad,0x3c,0xc3,0x44,0x03,0xf0,0x27,0x25,0xe4, 0xb8,0xe0,0x59,0xf9,0xda,0xb5,0xeb,0x9f,0x5d,0x63,0xb6,0x21,0xfc,0x29,0xe2,0xa9, 0xf3,0x8e,0x7b,0xb1,0x36,0xf8,0xb9,0x67,0x91,0x14,0xef,0x75,0xeb,0x95,0x37,0xd3, 0x03,0x5f,0x94,0x61,0xc6,0x42,0xe1,0x8a,0x36,0x36,0xb3,0xe4,0x3f,0x99,0x97,0x68, 0x75,0x85,0x9a,0xb9,0xd8,0x3c,0xa4,0x80,0xa4,0xdf,0xe5,0x16,0xfb,0x00,0x2c,0x18, 0x6b,0xa4,0x91,0x7d,0x6e,0x32,0xca,0xdb,0xd1,0xb5,0xae,0x78,0x1d,0x46,0x87,0xaf, 0xb9,0x10,0x8c,0x8a,0x3b,0x09,0x59,0x43,0x92,0x39,0xec,0x01,0xe0,0xb8,0x9e,0xad, 0x30,0x5b,0x0e,0x0d,0x62,0x1a,0xdb,0xdb,0xdf,0xcd,0x05,0x19,0x41,0x77,0xc7,0xf8, 0xd8,0x0c,0x41,0x57,0x67,0xa2,0x0a,0x56,0x67,0x77,0x04,0x5f,0xfd,0xc4,0x7b,0x0d, 0x41,0x22,0xdc,0x50,0x11,0x3b,0x0e,0xe1,0x6a,0x91,0x1e,0x5f,0x4c,0x01,0xf1,0xec, 0x8a,0x66,0x1b,0xf6,0xd3,0xbe,0xc9,0x98,0xad,0xa8,0x36,0x62,0xca,0x00,0xcb,0x76, 0xa4,0xb8,0xb4,0x94,0x3c,0x60,0xc8,0xdf,0xc9,0x6a,0xcd,0x9b,0x7d,0xb7,0x55,0x73}; /* ciphertext */ static const int8u ciphertext[MBX_RSA2K_DATA_BYTE_LEN] = { 0x8a,0x9b,0xf5,0xc2,0x9f,0xda,0x1b,0x63,0xd9,0x01,0xae,0x44,0xf5,0x7e,0x2c,0xec, 0xf4,0x5e,0x3a,0x02,0x20,0x43,0x39,0xd4,0x87,0xed,0x46,0x8e,0xc0,0x02,0x74,0x77, 0x5e,0x5e,0xaf,0xcd,0xe4,0x3a,0x70,0xd4,0xc7,0x47,0x9b,0xc3,0x9d,0x23,0x72,0xc7, 0x7c,0x0a,0x00,0xc9,0xa8,0xc8,0xe4,0x4c,0xd2,0x0f,0x26,0xd3,0x3f,0x03,0x87,0xbc, 0x8b,0xf8,0xe6,0x6c,0x9e,0xe8,0x18,0x88,0xfc,0xd2,0x1f,0x31,0xda,0xd6,0x09,0x63, 0x02,0xa9,0xf2,0x8c,0x3b,0x77,0x3f,0x2c,0xdc,0x1a,0x29,0xb1,0x06,0xb8,0xbf,0x98, 0x25,0xcd,0x70,0xd9,0x9d,0xf1,0xc2,0x19,0x8b,0x65,0x3e,0xce,0x49,0x25,0x4e,0x9f, 0x23,0x41,0x28,0x8e,0x90,0x46,0x91,0x2a,0xae,0xe2,0xd2,0x5c,0x46,0x28,0x87,0x94, 0x56,0xca,0x13,0x55,0x92,0xb4,0x7e,0x3a,0x0e,0xe4,0x28,0xf8,0xd4,0xa8,0x86,0x47, 0x29,0xc0,0xdc,0xdc,0xc6,0x98,0xb4,0x29,0x3e,0x9b,0x51,0x97,0x13,0x11,0xac,0x4d, 0x21,0x50,0x30,0xe8,0x44,0xcf,0xef,0x87,0x91,0xba,0x93,0x2e,0x2d,0xde,0xb5,0x87, 0x42,0x76,0x8f,0x66,0x74,0xf0,0xa8,0x0f,0x6b,0x37,0x74,0x91,0x82,0x78,0x8a,0x41, 0x31,0x29,0x5d,0x0d,0x4f,0x31,0x9f,0x04,0x3f,0xfa,0x6f,0x70,0x25,0xc3,0x21,0x7d, 0xb6,0x29,0x5f,0x84,0x8e,0xc3,0x12,0x7c,0xe6,0x8b,0xbd,0xf7,0x85,0x82,0x26,0xd8, 0x46,0x89,0xdb,0xa7,0x5e,0xd8,0x1d,0x8a,0xd8,0x17,0xcd,0x9c,0x62,0xf5,0x0c,0x1b, 0xa0,0x49,0xe9,0x19,0x81,0xaf,0x8c,0x80,0xaf,0x8f,0x8f,0x57,0x7f,0x4e,0xc9,0xb7}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa2k_private_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA2K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA2K_private_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // private exponent const int64u *pa_d[MBX_LANES]= { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA2K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA2K_DATA_BYTE_LEN, plaintext, MBX_RSA2K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa2k_private_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA2K_DATA_BYTE_LEN]; /* ssl private exponent */ BIGNUM* BN_d = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(d, MBX_RSA2K_DATA_BYTE_LEN, BN_d); BN_lebin2bn(moduli, MBX_RSA2K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; // private exponent const BIGNUM *pa_d[MBX_LANES] = { (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d}; /* test function */ sts = mbx_rsa_private_ssl_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA2K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA2K_DATA_BYTE_LEN, plaintext, MBX_RSA2K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa2k_public_mb8.c000066400000000000000000000230221470420105600340440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA2K_DATA_BYTE_LEN] = { 0x17,0xdd,0x3c,0x74,0x0f,0x12,0x7f,0x99,0xd8,0x9e,0xd3,0xe7,0x60,0x16,0x15,0x7e, 0xe4,0x7c,0xa9,0x58,0x26,0x9b,0x98,0x6e,0x4e,0x9f,0x17,0x1a,0xfa,0x46,0x03,0x3a, 0xf0,0xdf,0xcc,0xc9,0x39,0x16,0x5e,0x02,0xbd,0x4c,0x73,0x5d,0xa2,0x56,0x8d,0x9c, 0x1a,0xb1,0x2c,0xca,0x7e,0xbd,0x9b,0xad,0xa7,0x8e,0xe0,0xae,0xb3,0xb8,0x8a,0x93, 0x91,0x85,0x83,0x9a,0x76,0x08,0xa6,0x4e,0xf7,0xde,0xff,0xe3,0x09,0xed,0x60,0x98, 0x17,0x8f,0xaf,0x6a,0x58,0x81,0x12,0x0d,0xfb,0xff,0x56,0xc7,0x3f,0xa0,0x72,0x93, 0x0c,0x96,0xfa,0xa7,0xfc,0x16,0x95,0xfd,0x85,0x7a,0xaa,0xab,0x9c,0xf9,0x60,0x91, 0x1b,0xf0,0xb1,0xdf,0x28,0x39,0xf3,0xb9,0x7b,0x56,0x87,0x66,0x73,0xe6,0x90,0xc9, 0x54,0x87,0x5d,0xab,0x41,0x2a,0x31,0x91,0x5c,0x87,0x7c,0x5c,0x55,0xb2,0x65,0x77, 0x5d,0x94,0x6a,0x2f,0x72,0xec,0xc8,0x9e,0x60,0x9f,0x32,0x49,0x24,0x99,0x81,0x41, 0xfa,0x8c,0x04,0x2d,0x6c,0xeb,0x43,0x1b,0x0f,0xbe,0x85,0xbb,0xb5,0x53,0x5c,0xa6, 0x86,0x6a,0x78,0x54,0x2e,0x82,0x34,0xdf,0x7f,0x57,0x0b,0x27,0x87,0x83,0x5e,0xfb, 0x0d,0x4f,0xa2,0x5d,0xfa,0x89,0x74,0x75,0xad,0x9f,0x26,0x3f,0x12,0x38,0xc5,0xc3, 0x91,0xf0,0x8a,0xe7,0xde,0x10,0xce,0xf3,0xf8,0x89,0x1a,0xf0,0xee,0x3c,0xa2,0x2c, 0x98,0xbd,0xf7,0x03,0xe1,0x46,0xc1,0x4d,0xdf,0xbb,0xae,0x6a,0x61,0xf7,0xc8,0x56, 0x31,0xd5,0xf5,0xbb,0x08,0x8d,0xfd,0x51,0x28,0x3c,0x82,0xe0,0x0d,0x7d,0xc1,0xf0}; /* plaintext */ static const int8u plaintext[MBX_RSA2K_DATA_BYTE_LEN] = { 0x5c,0x14,0x01,0xf4,0x3f,0x46,0x71,0xd5,0x3e,0xc3,0xe1,0x9a,0xec,0xb7,0x44,0x97, 0x73,0x59,0x1e,0x00,0xa5,0x5d,0xe7,0x9a,0xf4,0x0a,0xac,0x21,0x7c,0x70,0x5a,0x54, 0x23,0x61,0xaa,0x4c,0x02,0x4f,0x80,0xed,0x30,0x2c,0x4f,0xe9,0x8b,0x92,0x53,0x93, 0xa3,0xdc,0xe7,0x66,0xc4,0x90,0xa1,0x2b,0x60,0xea,0x5e,0x5f,0x58,0x63,0x47,0x75, 0x2c,0xd1,0x2b,0x6c,0x06,0x3e,0x52,0x4f,0x7c,0x54,0x90,0x9c,0xbc,0xf5,0x73,0xa2, 0xcb,0xb3,0x3c,0x24,0xb3,0x0a,0xfd,0xa7,0x30,0xeb,0x3c,0x29,0x1c,0x51,0x38,0x9c, 0x6f,0xf6,0xa6,0xc9,0xb7,0xf3,0x75,0xb0,0x30,0x74,0x5b,0x3c,0x44,0x23,0x10,0xa0, 0xbd,0x65,0xf9,0x11,0x09,0xf3,0x9f,0x63,0x03,0xf3,0x56,0xa8,0x76,0xce,0xac,0x70, 0x9c,0x21,0x55,0x62,0xb9,0xc6,0x91,0xe8,0xb6,0x82,0x4d,0x4f,0x08,0xe7,0xa5,0x72, 0x50,0xce,0x8d,0x94,0x7d,0xdc,0xe3,0x20,0x05,0x0d,0x53,0xe4,0x74,0xf7,0x85,0xb8, 0x98,0x09,0xa6,0xa0,0xc3,0xd5,0xe9,0x8c,0x23,0x17,0xd5,0x26,0x72,0x15,0x1e,0xf7, 0x28,0xa1,0x2b,0x24,0x1d,0xbe,0x45,0x38,0xe2,0xd1,0xf6,0xb1,0x0f,0x58,0xf7,0x67, 0x2b,0x2c,0x39,0x81,0x5c,0x89,0xf2,0x9d,0x07,0x21,0xd3,0xde,0x48,0x8a,0x3a,0xca, 0x15,0x0c,0x21,0x32,0xd4,0x04,0x88,0x23,0xb4,0x66,0x3f,0xe8,0x24,0xae,0x4b,0x57, 0x7b,0x32,0x87,0x47,0x0d,0x2a,0x63,0x5d,0x6d,0xa2,0x38,0xc6,0x2b,0xbe,0x65,0xf2, 0x27,0xdd,0xe6,0x0b,0x4b,0xdd,0x39,0xa6,0x5a,0x38,0x96,0x3e,0x81,0x57,0xcf,0xf1}; /* ciphertext */ static const int8u ciphertext[MBX_RSA2K_DATA_BYTE_LEN] = { 0x71,0x4b,0x43,0x7d,0x01,0x36,0xab,0x29,0xcd,0x95,0xa6,0x7c,0x30,0x70,0x51,0xd4, 0xc1,0x06,0x94,0x9f,0xff,0x50,0x84,0x87,0x84,0x91,0x39,0x65,0x40,0x2c,0x30,0x6f, 0x02,0x7c,0x0e,0xc7,0xf0,0x7d,0x1c,0xb4,0xe3,0xef,0x01,0xb0,0xde,0x3c,0xb3,0x5a, 0xce,0xbb,0xe0,0xf8,0xcd,0x3a,0x03,0xff,0x96,0x16,0xe6,0x79,0x32,0x0d,0x23,0xcb, 0xd2,0xe1,0x55,0xcc,0xa2,0x49,0x2a,0x52,0x64,0x5f,0xe6,0x1f,0xcc,0xe8,0x7b,0x7d, 0xd3,0x14,0x4e,0x6d,0x74,0x0f,0x94,0x3d,0x77,0x91,0x65,0x54,0xa6,0x24,0x60,0x1f, 0x33,0xda,0xa7,0xc7,0xf0,0x29,0xb3,0xb5,0x07,0xb0,0xed,0x5c,0x27,0x65,0x5f,0x6f, 0x0a,0x8f,0x12,0x0c,0x25,0x41,0xce,0x9e,0x16,0x7b,0x2e,0x03,0x9b,0x59,0xe0,0x72, 0x7d,0xe2,0x1a,0x82,0x57,0x2f,0x75,0x6c,0x68,0xd8,0xf8,0x3b,0x87,0xcf,0x32,0x04, 0xe0,0xfc,0x23,0x35,0x71,0xb0,0x32,0x17,0xe4,0xfd,0x7b,0x6a,0xd0,0x6c,0x35,0xdf, 0x3e,0x93,0x59,0xc1,0x42,0x71,0x7c,0x11,0x3c,0xb2,0xe6,0x6f,0xdc,0xfe,0xd5,0x79, 0x3e,0x47,0x89,0xf4,0x08,0x0b,0x6c,0x58,0xdc,0x0a,0x1f,0x72,0x3f,0x92,0x55,0x17, 0x27,0xde,0xa3,0xa2,0x1f,0xe4,0xd5,0xfa,0x8f,0xf1,0x8c,0xe3,0x28,0x7c,0xcd,0xa2, 0xe7,0xbf,0x95,0xd9,0xf1,0xf7,0x83,0xf1,0x94,0x7d,0xbc,0x14,0xf1,0x2b,0x94,0xd6, 0x84,0x03,0x84,0x99,0x97,0x02,0x7e,0x90,0x3d,0x5e,0x05,0x43,0xfd,0x12,0x0d,0x75, 0x8e,0xec,0x56,0x6d,0xde,0x8c,0x10,0x9c,0xd9,0xbe,0xa5,0x15,0xa6,0x1f,0x3a,0xf6}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa2k_public_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA2K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA2K_pub65537_Method(); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_public_mb8(pa_plaintext, pa_ciphertext, pa_moduli, MBX_RSA2K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output ciphertext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA2K_DATA_BYTE_LEN, ciphertext, MBX_RSA2K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE /* exponent (for ssl function only) */ static const int8u exponent[MBX_RSA_PUB_EXP_BYTE_LEN] = {0x01,0x00,0x01}; // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa2k_public_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA2K_DATA_BYTE_LEN]; /* ssl exponent */ BIGNUM* BN_e = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_e || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_e, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(exponent, MBX_RSA_PUB_EXP_BYTE_LEN, BN_e); BN_lebin2bn(moduli, MBX_RSA2K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; const BIGNUM *pa_e[MBX_LANES] = { (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e}; /* test function */ sts = mbx_rsa_public_ssl_mb8(pa_plaintext, pa_ciphertext, pa_e, pa_moduli, MBX_RSA2K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA2K_DATA_BYTE_LEN, ciphertext, MBX_RSA2K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_e, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_rsa3k_private_crt_mb8.c000066400000000000000000000411521470420105600350360ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* plaintext */ static const int8u plaintext[MBX_RSA3K_DATA_BYTE_LEN] = { 0x43,0x9a,0x10,0x7a,0xf5,0x23,0x48,0x2a,0xb9,0xf7,0x67,0xe7,0x57,0x65,0xbe,0x90, 0xb9,0x50,0x8a,0xc1,0xb0,0x97,0xf5,0x64,0x93,0x8a,0xb0,0xe6,0xdf,0xd9,0x44,0x17, 0xd0,0x29,0x84,0xad,0xf8,0xb0,0xad,0xe2,0xd3,0xda,0xb7,0xf5,0x12,0x47,0x6c,0x25, 0xb2,0x9f,0x7f,0xac,0x04,0x33,0x90,0x9f,0x2c,0x96,0xe9,0x1c,0xae,0x02,0x96,0x12, 0x6c,0x6a,0x88,0x10,0x06,0x9b,0x54,0xc7,0x9d,0x1b,0xd0,0xfd,0x5c,0x46,0xb4,0xe1, 0x13,0x09,0x12,0xfc,0xfb,0xc2,0x2a,0xe8,0x74,0x95,0xda,0xfa,0xd3,0x69,0x2f,0xc7, 0x8a,0xbe,0xea,0x0b,0xd7,0x8e,0xd1,0x39,0x58,0xe6,0x0d,0xa9,0xad,0x22,0x64,0x27, 0x13,0x37,0x12,0x16,0xd6,0xb7,0x8f,0x47,0x86,0x18,0xbb,0x6e,0x79,0xc2,0x92,0xfc, 0x68,0xbc,0x8a,0xc5,0x14,0xe2,0xa0,0x2f,0xd8,0xa1,0x4c,0xf9,0x39,0xb5,0xe5,0x3e, 0xcb,0x55,0x11,0x22,0xd7,0x19,0xc4,0x02,0x33,0xea,0x34,0x6e,0x23,0xde,0x1d,0x6e, 0x3c,0x6f,0x13,0x20,0xb3,0x19,0x97,0xd7,0x14,0xc3,0x3b,0x18,0x13,0xd9,0x1f,0x13, 0x22,0x34,0xc0,0x17,0xa3,0x54,0x2f,0x37,0x35,0xcc,0x53,0xa9,0xc9,0x6f,0x5a,0xaf, 0x52,0x4c,0xe0,0x5e,0x77,0xa6,0x2f,0xba,0xf9,0x15,0x3e,0x37,0x65,0x28,0x2d,0x69, 0x2f,0xcc,0x6e,0xb3,0x68,0x8b,0xe5,0xfb,0xd4,0xb1,0xb0,0x41,0xc8,0xb7,0x8a,0xd5, 0xc5,0x83,0x49,0x8c,0xfc,0x96,0x21,0xab,0x94,0xd8,0x4c,0x82,0x67,0x2a,0x6f,0x95, 0x42,0x83,0xe0,0xb1,0xc2,0xa0,0x10,0xed,0x31,0x26,0xbd,0xe2,0x73,0xb3,0x92,0x91, 0x06,0x70,0xf8,0x10,0xb8,0x01,0xc9,0x34,0x3d,0xd7,0x8e,0x61,0x4e,0x37,0x9e,0x1c, 0xd4,0x62,0x76,0xb2,0x15,0x15,0xd8,0x44,0x46,0xe5,0xc3,0x5d,0xf0,0xb1,0xe5,0xa0, 0xbd,0x70,0x17,0x6f,0x84,0x81,0xa7,0xd4,0x64,0xda,0x0a,0xe0,0xf0,0xd7,0x85,0xe9, 0x86,0x6f,0xe6,0x09,0xed,0x41,0xe3,0x3f,0xfc,0xa6,0xa1,0x30,0x5b,0x36,0x77,0x4d, 0x96,0xf1,0x58,0x99,0x00,0x27,0x4d,0xdf,0xf2,0x9e,0x94,0x0c,0xe3,0xf3,0xe0,0xeb, 0x2b,0xa2,0x02,0x6b,0x88,0xa8,0x10,0xb9,0x36,0xcf,0x41,0xb5,0x8c,0xca,0x33,0x69, 0xeb,0x22,0x6d,0x7d,0xf0,0x66,0x29,0x08,0x79,0x21,0x30,0x47,0x93,0x9d,0x7b,0xbb, 0xa3,0x05,0x8c,0xc6,0x80,0x04,0x78,0x2c,0x27,0xc5,0xfc,0xfd,0xd6,0x12,0x82,0x2c}; /* ciphertext */ static const int8u ciphertext[MBX_RSA3K_DATA_BYTE_LEN] = { 0x14,0x65,0xbe,0x8a,0x00,0xef,0x3e,0xc3,0x36,0xfd,0xa0,0x30,0x4d,0x34,0x22,0xd2, 0x12,0xde,0x7c,0xfa,0x47,0x0c,0x66,0x6b,0x1c,0x2a,0xd2,0x48,0xee,0xf6,0x7d,0x0e, 0x75,0x68,0xf4,0x50,0xa6,0x14,0x5b,0xec,0xc2,0xd4,0xc0,0xfd,0x01,0xdc,0x9d,0xa6, 0x79,0x5d,0x3c,0xc2,0xf7,0x8e,0xb9,0xdc,0x5b,0xd6,0xc9,0xe3,0xb3,0xe5,0xad,0xb6, 0xfc,0x77,0x22,0x48,0xf9,0x5d,0x7d,0xfe,0x71,0x5a,0xb5,0x1e,0x9f,0x48,0x13,0xd0, 0xa6,0x3c,0xf4,0xed,0x7e,0x45,0x21,0x46,0x08,0x99,0x04,0x94,0xc5,0x35,0x9a,0xe7, 0x2f,0x13,0xc4,0x24,0xf9,0xb4,0x79,0x03,0xd5,0x68,0x13,0x89,0x6b,0x31,0x78,0x5a, 0x84,0x11,0x50,0x18,0x2d,0x3b,0x02,0x48,0x44,0xbc,0xaf,0x48,0xe0,0xe9,0x56,0xef, 0xfa,0xaf,0xef,0xb7,0x05,0xac,0xdb,0xf7,0x42,0x0f,0x9b,0xc0,0xaa,0xc7,0x50,0x79, 0x25,0x86,0x60,0x53,0x12,0x37,0x58,0xcd,0xbc,0x29,0x19,0x0f,0xb3,0x66,0xdb,0x36, 0x31,0x55,0x69,0xf5,0xb8,0x8f,0x4f,0x7d,0xdf,0x3a,0xda,0xe0,0xc2,0xe4,0xcb,0x28, 0x70,0x72,0xf5,0x32,0x3a,0xb8,0xbb,0x78,0x7e,0x3a,0xfa,0x1f,0xe7,0x14,0xb4,0x4e, 0x77,0xf1,0xbe,0x80,0x19,0x10,0x75,0xaa,0x1f,0xd0,0x80,0x78,0xcf,0xce,0x9c,0x8e, 0x70,0xd9,0x24,0xa2,0xbb,0x6b,0xd6,0x5c,0xdb,0xe4,0xc5,0x51,0x49,0x1a,0xba,0xaf, 0x94,0x37,0xc2,0xb7,0xfe,0x85,0xcc,0xff,0xcb,0x81,0xb4,0x47,0x5a,0x46,0xd8,0xff, 0x36,0xc9,0x14,0x19,0x25,0x9e,0x6b,0x41,0x0c,0x73,0xe9,0xc6,0xd8,0xcf,0x61,0xdd, 0x82,0xd4,0xc5,0xae,0x53,0x89,0x83,0xc5,0x39,0x47,0x56,0x0d,0x77,0xf0,0xa8,0x76, 0x04,0x07,0xe8,0x34,0xbf,0x54,0x02,0x84,0xf8,0x00,0x36,0xe0,0x46,0x01,0x96,0xca, 0x0a,0xdb,0x99,0x61,0x3f,0x1b,0x86,0x36,0xea,0x6b,0xdb,0xe4,0x1b,0xcf,0x3c,0xe6, 0x16,0x6d,0x48,0x20,0xd7,0xfa,0x4f,0xf3,0xdc,0xd8,0x5c,0x68,0x28,0xe6,0x8a,0x6d, 0x96,0x9f,0xa5,0x71,0x86,0x90,0xc4,0x97,0x4c,0xe5,0x66,0x25,0xed,0xf7,0x07,0xd6, 0xbd,0xbb,0xb7,0xef,0x43,0xc2,0xba,0x6e,0xcc,0x00,0xca,0xb2,0x57,0x3f,0xef,0xdb, 0x08,0x24,0x65,0x7d,0x09,0xd1,0x2f,0x1c,0x1a,0xed,0x35,0x63,0xf6,0xea,0xec,0xea, 0xc3,0x2a,0xe8,0xb0,0xf0,0xa5,0x8f,0xb6,0x21,0xfb,0xf0,0x91,0x72,0x35,0x7e,0xb2}; /* p, q primes */ static const int8u p[MBX_RSA3K_DATA_BYTE_LEN / 2] = { 0x71,0xa4,0x32,0xb5,0x2f,0xde,0x65,0x86,0x93,0x47,0xf7,0x27,0x0c,0x6a,0x58,0x89, 0x94,0xf7,0xa2,0xdf,0xcf,0x7e,0xae,0xa2,0x11,0x60,0x84,0xea,0x40,0x53,0xc3,0x66, 0xc9,0x5e,0x0b,0xf6,0x0e,0x73,0x7c,0xa2,0x0b,0xbe,0x6b,0x8e,0x9a,0x7e,0x2c,0x66, 0xad,0x6c,0x7e,0x85,0x4a,0x83,0x10,0x38,0xcc,0x8e,0xf1,0xe3,0xc2,0xa5,0x34,0x90, 0x7d,0xe8,0x85,0x67,0x21,0x57,0xc0,0x2b,0xd9,0xd1,0xd3,0x59,0x83,0x20,0xac,0x8c, 0x8a,0x59,0xe0,0x7e,0x85,0xad,0x5f,0xd8,0xbb,0xeb,0x6b,0xf8,0xbd,0x86,0xd7,0xfa, 0x2f,0x34,0xb0,0x31,0xbb,0x2f,0xcb,0x00,0x89,0x35,0x2e,0x2a,0xea,0x0f,0xf9,0xb3, 0xe7,0x9c,0x98,0x61,0x86,0xb2,0xc2,0x37,0x15,0x59,0x72,0x06,0x2d,0xbc,0xe4,0x2f, 0xb9,0x50,0xd4,0x29,0x16,0xbb,0x65,0x36,0x1d,0xf4,0xbb,0x8f,0x9b,0xe2,0x87,0xe6, 0xdf,0x7c,0xdd,0xad,0x4f,0x2a,0xe6,0xbe,0xe0,0x94,0x64,0xd8,0xee,0x68,0xb0,0x5a, 0x54,0xf7,0x61,0xad,0x52,0xbe,0x66,0x8b,0x4c,0x19,0x6e,0x97,0xc1,0xde,0xaa,0xa2, 0x49,0xe6,0xc9,0xf3,0x04,0x03,0x91,0x7e,0xd7,0xaf,0xc4,0x31,0x16,0xf5,0xc5,0xea}; static const int8u q[MBX_RSA3K_DATA_BYTE_LEN / 2] = { 0xd5,0xa9,0x2d,0xdb,0x06,0xda,0x5d,0xb7,0xb4,0x29,0x2f,0x5e,0xa9,0xfd,0x60,0xf9, 0x73,0x70,0x26,0x6b,0xbe,0x91,0x4a,0xe9,0x7f,0xfc,0x0e,0xf0,0x55,0x2a,0x95,0x27, 0x39,0x67,0xec,0x49,0x7e,0x38,0x29,0x13,0x27,0x69,0xef,0xee,0x82,0xcf,0x3d,0xa7, 0xee,0x42,0x68,0xe1,0xf6,0x0f,0x4a,0x7a,0xae,0x3c,0xd2,0xbe,0xbd,0x8b,0x9b,0xa0, 0xee,0x33,0x02,0x15,0x77,0x49,0x38,0x6e,0xd1,0x4c,0xb0,0x24,0xb0,0xa9,0x8b,0x72, 0x29,0x7d,0x44,0x4d,0x20,0xf9,0x78,0x9f,0xe5,0x8a,0x68,0x91,0x27,0x78,0x90,0xd6, 0xf8,0x80,0x4c,0xf6,0x87,0x34,0xa4,0xcb,0xe8,0xce,0xda,0x8f,0x40,0xcd,0x17,0x2d, 0x9b,0x16,0x9b,0x41,0xce,0xba,0x18,0x94,0xe8,0x89,0x39,0x33,0x10,0x4e,0x01,0xd6, 0x58,0xfb,0xb3,0xa0,0x6f,0xa1,0xad,0x28,0x39,0x86,0xc0,0xda,0x13,0x73,0xbd,0x2e, 0x28,0x16,0xf1,0xc6,0x30,0x30,0x11,0x58,0x37,0x90,0x0c,0x6e,0x27,0x72,0xe3,0xd8, 0xb9,0x69,0x69,0x33,0xd8,0x39,0x6d,0x37,0xe4,0xe8,0x69,0xd8,0xbf,0x7c,0x9a,0xd0, 0x74,0xc5,0x44,0xc7,0xec,0xbd,0x06,0x61,0xc3,0xe9,0x47,0x9c,0x90,0x71,0x3b,0xcf}; /* p's, q's CRT private exponent */ static const int8u dp[MBX_RSA3K_DATA_BYTE_LEN / 2] = { 0xe1,0xaa,0x76,0x5d,0x3d,0x1c,0x9d,0x05,0x6c,0xc2,0x60,0x58,0x15,0x7e,0xef,0x40, 0xbe,0x81,0x20,0xaf,0x2b,0xb1,0x2b,0x88,0xfd,0xbf,0xe9,0xe1,0xa3,0x28,0x3a,0x89, 0x96,0xb9,0xba,0x3c,0x91,0x38,0x9d,0x1d,0x22,0x91,0xd2,0x22,0x2f,0x66,0x44,0x38, 0x7a,0xad,0xa8,0x3c,0x64,0xea,0x23,0x62,0x6f,0xef,0x99,0xb8,0xca,0x54,0x1b,0x3c, 0x5d,0x90,0xe4,0x55,0x10,0x6b,0x78,0x68,0x3a,0xcb,0x5d,0x46,0xed,0x6a,0x55,0xf8, 0x80,0x57,0xb8,0xdf,0x76,0x93,0x07,0x40,0x46,0x64,0xf7,0xfe,0x3d,0xc0,0x07,0xaa, 0x43,0xe5,0x46,0x97,0x7b,0xb1,0x3b,0xa6,0x2f,0xf5,0x64,0xb7,0x5f,0x5e,0xf3,0x64, 0x75,0xb2,0x6e,0x13,0x26,0x51,0xbb,0x82,0x1b,0xbb,0xbb,0xda,0xd7,0x00,0xd1,0x16, 0x1b,0x21,0x42,0xdc,0x24,0x76,0xbf,0xf6,0x56,0xe3,0x87,0x99,0x24,0xd1,0x5d,0x61, 0x2c,0xcd,0x80,0x32,0x12,0x77,0x3e,0xb9,0x82,0x26,0xae,0x9a,0xa8,0xd8,0x61,0xf5, 0xee,0x78,0x67,0xc2,0x87,0x59,0x2d,0xb8,0x2a,0x10,0x0d,0xfe,0xc3,0x9a,0x57,0x74, 0x3f,0x91,0xb9,0x87,0x65,0x13,0x6a,0xc2,0xf9,0x6c,0x11,0x4b,0x13,0x40,0x34,0x8c}; static const int8u dq[MBX_RSA3K_DATA_BYTE_LEN / 2] = { 0xb5,0xbf,0x91,0x58,0x9c,0x87,0xa0,0x50,0x5d,0x71,0xb5,0x2a,0x0a,0x0c,0x07,0xcd, 0xe7,0xa2,0x6f,0xa2,0x6d,0x2f,0x8e,0xd4,0x70,0x01,0xac,0xa4,0xbc,0x7b,0xcf,0x5e, 0x82,0xc2,0xa5,0x7f,0xe4,0xdf,0xa4,0x11,0x47,0x86,0x3e,0xcc,0x24,0x9b,0x66,0x91, 0x1d,0x57,0x94,0x16,0x1d,0x0b,0x1f,0x38,0x84,0xcf,0x6f,0x0d,0x02,0xa2,0x7e,0xbc, 0x9d,0x2f,0xe5,0x28,0x58,0x80,0xfc,0x1a,0xbc,0xf7,0x0b,0x34,0x09,0x54,0x4e,0x9b, 0x88,0xdf,0x17,0xf4,0xfd,0x2e,0xb9,0x6a,0x15,0x2a,0x40,0xae,0x8a,0x47,0x6d,0x56, 0xa0,0xec,0xe2,0x6f,0x7d,0x6d,0x54,0xb2,0x42,0x1c,0xa0,0xa5,0xd7,0x7a,0x26,0xcf, 0x3a,0xc8,0xd3,0x6f,0xbf,0xca,0xcf,0xcf,0x84,0x94,0xeb,0xc8,0x61,0x08,0xd3,0xed, 0x25,0x78,0xa3,0xcf,0xa5,0x5e,0x4a,0x04,0xec,0xa4,0x32,0x85,0x67,0x63,0x52,0x79, 0xab,0x6a,0x6b,0x5d,0x5f,0x11,0x0e,0x88,0x93,0xa0,0x1b,0x5a,0xdf,0xe8,0xcf,0x83, 0x7b,0xac,0x6b,0xb3,0x90,0x88,0xb6,0x56,0xb7,0x46,0xce,0x1d,0xb0,0x50,0x00,0xe1, 0x4d,0x0b,0x3b,0xed,0x2f,0xf7,0x27,0x80,0x72,0xf4,0x76,0xe0,0xf0,0x7d,0xdb,0xa8}; /* CRT coefficient */ static const int8u inv_q[MBX_RSA3K_DATA_BYTE_LEN / 2] = { 0xc4,0xd1,0x5e,0xb9,0x75,0x8d,0x12,0x3c,0xf1,0x3b,0x74,0xf5,0xc6,0xff,0x1f,0xca, 0xa3,0xc1,0xed,0x4f,0xe1,0x88,0xef,0xd2,0x7f,0x81,0x26,0x7e,0x34,0x17,0x3d,0x2b, 0x44,0x4d,0xee,0x91,0x32,0x2e,0x1f,0x14,0xa5,0x6f,0x89,0x4f,0x2a,0x5d,0xbb,0xc0, 0xf6,0xf2,0xf7,0xfb,0x68,0xdb,0xc7,0xb6,0xe9,0x14,0x96,0xd7,0x3b,0xcb,0x05,0xbe, 0x9d,0xa2,0xb3,0xd7,0x03,0x8a,0x84,0x72,0x03,0x50,0x3d,0x24,0xac,0x8d,0x08,0x21, 0x2e,0xfd,0x0a,0xec,0x8d,0x8e,0xbd,0xb4,0x54,0x7f,0xaf,0x7b,0xab,0xf1,0x23,0xec, 0x76,0x35,0xe9,0xd0,0xd5,0x72,0x9e,0xab,0xe0,0x6c,0xbc,0xfd,0x77,0x93,0x76,0x60, 0x64,0x89,0xbc,0x60,0x0a,0x89,0xf1,0x41,0xa4,0x36,0xad,0x97,0x54,0x96,0x85,0xc0, 0x84,0x1e,0x69,0x71,0x3f,0xe6,0x55,0x1e,0xde,0x3d,0x9b,0xf1,0xa1,0xe8,0x8c,0x24, 0x77,0x75,0x12,0x5f,0x70,0xb0,0x5d,0xdc,0x43,0xff,0xa8,0x63,0xf1,0x9b,0x61,0x2c, 0x5c,0xc1,0xef,0x95,0x37,0xdd,0xf5,0x51,0x54,0x3e,0xbc,0xa5,0x2f,0xd8,0x76,0x1c, 0xc3,0x05,0x16,0x1c,0x96,0x8c,0xa7,0x52,0xc0,0xca,0x97,0x96,0x84,0xf2,0x27,0x5b}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa3k_private_crt_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA3K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA3K_private_crt_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const int64u *pa_p[MBX_LANES]= { (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p}; const int64u *pa_q[MBX_LANES]= { (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q}; // p's, q's CRT private exponent const int64u *pa_dp[MBX_LANES]= { (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp}; const int64u *pa_dq[MBX_LANES]= { (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq}; // CRT coefficient const int64u *pa_inv_q[MBX_LANES]= { (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_crt_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA3K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA3K_DATA_BYTE_LEN, plaintext, MBX_RSA3K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3, BN_PTR4, BN_PTR5) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa3k_private_crt_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA3K_DATA_BYTE_LEN]; /* ssl parameters */ // p, q primes BIGNUM* BN_p = BN_new(); BIGNUM* BN_q = BN_new(); // p's, q's CRT private exponent BIGNUM* BN_dp = BN_new(); BIGNUM* BN_dq = BN_new(); // CRT coefficient BIGNUM* BN_inv_q = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_p || NULL == BN_q || NULL == BN_dp || NULL == BN_dq || NULL == BN_inv_q) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(p, MBX_RSA3K_DATA_BYTE_LEN / 2, BN_p); BN_lebin2bn(q, MBX_RSA3K_DATA_BYTE_LEN / 2, BN_q); BN_lebin2bn(dp, MBX_RSA3K_DATA_BYTE_LEN / 2, BN_dp); BN_lebin2bn(dq, MBX_RSA3K_DATA_BYTE_LEN / 2, BN_dq); BN_lebin2bn(inv_q, MBX_RSA3K_DATA_BYTE_LEN / 2, BN_inv_q); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const BIGNUM *pa_p[MBX_LANES] = { (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p}; const BIGNUM *pa_q[MBX_LANES] = { (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q}; // p's, q's CRT private exponent const BIGNUM *pa_dp[MBX_LANES] = { (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp}; const BIGNUM *pa_dq[MBX_LANES] = { (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq}; // CRT coefficient const BIGNUM *pa_inv_q[MBX_LANES] = { (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q}; /* test function */ sts = mbx_rsa_private_crt_ssl_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA3K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA3K_DATA_BYTE_LEN, plaintext, MBX_RSA3K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa3k_private_mb8.c000066400000000000000000000330741470420105600342510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA3K_DATA_BYTE_LEN] = { 0x05,0x6b,0x8e,0xc4,0x89,0x9d,0x19,0xd4,0x44,0x4b,0x0b,0x32,0xc7,0xbb,0x22,0x05, 0xa4,0x53,0x33,0x4c,0x60,0xd3,0xcd,0xfb,0xa9,0xae,0xa3,0xba,0x83,0xfe,0xe8,0x67, 0x56,0x10,0x7c,0x9d,0x89,0xd3,0xb7,0x8b,0x03,0xa7,0x07,0xcb,0x4c,0x4b,0x62,0xa3, 0x33,0x02,0x5d,0x32,0xd0,0xb3,0xff,0xef,0xa0,0x1a,0x7c,0x48,0xb1,0x4b,0x70,0xe7, 0xc7,0xdf,0x7c,0xd3,0xad,0x7d,0xf6,0x2f,0xef,0x9b,0xfa,0x63,0x22,0x33,0x2e,0x84, 0xab,0x93,0x8c,0x11,0x56,0x2a,0xe9,0xb0,0xba,0xcc,0x53,0xbc,0x30,0xd2,0xf2,0xb5, 0x70,0xc0,0xca,0x5d,0xb7,0xd5,0x9a,0x7d,0xad,0x63,0xfc,0x81,0xc1,0x8e,0x3d,0x7f, 0x66,0xa0,0x80,0xd5,0x73,0x65,0x15,0x68,0x71,0x3b,0xe3,0xb2,0xa9,0x85,0x82,0x40, 0x5e,0x90,0x62,0x72,0xa9,0xdc,0x6a,0x94,0x7c,0x85,0x04,0x30,0x9b,0xed,0xb9,0x41, 0x00,0x66,0xf4,0x59,0x45,0xfd,0x33,0x65,0x15,0x8c,0x18,0x03,0xb9,0x3c,0x8d,0x9a, 0x89,0x73,0xea,0x99,0x02,0x3a,0xcc,0xde,0x20,0xf6,0x6f,0xfa,0x34,0x75,0x0e,0x40, 0x07,0x6f,0xc0,0x13,0xd4,0x0c,0x7f,0x29,0xf1,0xd2,0x92,0xec,0xb4,0x35,0x74,0x90, 0x81,0x3e,0xc9,0x93,0x4e,0xbc,0x10,0x81,0x90,0x9d,0x21,0xe7,0x1d,0x04,0x90,0x55, 0xc8,0xc1,0x11,0x10,0x73,0xee,0x0d,0x9e,0xeb,0xbb,0x54,0xc8,0x2d,0xe4,0x8a,0x68, 0x11,0x08,0xc9,0x03,0x0e,0xdf,0x71,0x09,0xdc,0x5a,0x94,0xcf,0xfe,0xdf,0xc5,0x36, 0xf4,0x4c,0x72,0xe7,0xe4,0xce,0xb6,0x3d,0xf0,0x46,0xcf,0x1d,0x33,0x43,0xdc,0x16, 0xc7,0x3b,0x03,0x77,0x5d,0x43,0xcc,0x76,0xed,0xd7,0xb8,0xc4,0x2a,0xec,0x47,0x63, 0x5c,0xe1,0xfc,0xe1,0x0c,0xae,0x5b,0x49,0xc0,0x23,0x89,0xe8,0x71,0x32,0x48,0xcf, 0x61,0xba,0xcf,0x97,0x55,0x16,0x34,0x5f,0xfa,0x85,0x9c,0xdb,0x5b,0xeb,0xeb,0xfd, 0xf5,0xf7,0x1a,0x97,0xd1,0xde,0xd6,0xe5,0xce,0x62,0xc2,0xe4,0x49,0xff,0xa2,0x13, 0xa7,0x0e,0x1f,0x7d,0x06,0x22,0xb8,0xb2,0xf9,0x99,0x1a,0x15,0xf7,0xa1,0xc4,0xc4, 0x51,0xb0,0x9b,0x52,0x20,0x5c,0xa8,0x50,0xea,0xa1,0xfb,0xb9,0x5a,0x2b,0xb4,0x4f, 0x16,0x55,0x07,0x20,0xf2,0x47,0x6a,0x95,0xb6,0x5d,0x92,0x1a,0x43,0x06,0x33,0xcb, 0x28,0xd6,0x7b,0x5c,0x88,0x31,0x94,0x6f,0x99,0xbf,0x36,0x6e,0xf2,0x94,0x0c,0xbe}; /* private exponent */ static const int8u d[MBX_RSA3K_DATA_BYTE_LEN] = { 0xc1,0x3c,0x85,0x92,0xe2,0x9c,0x5f,0x15,0x50,0x18,0x72,0x44,0x64,0xb9,0xbb,0x6b, 0x4e,0x3c,0x1c,0x32,0x67,0x84,0xef,0xb8,0xfb,0x93,0x53,0x4c,0x71,0x54,0x53,0xdc, 0x28,0x89,0xcb,0x2e,0x09,0x31,0xa3,0x8b,0x1f,0xd5,0x35,0x89,0x8d,0x24,0x09,0x84, 0x93,0x1e,0x60,0x2e,0xed,0xf2,0x2d,0xbe,0x30,0xd0,0x54,0xb0,0x19,0x43,0x5d,0xf0, 0x05,0x49,0xb4,0x0b,0x82,0xc7,0x5d,0xc2,0x6e,0xda,0x70,0xa1,0xfb,0xe4,0x6b,0x6c, 0x3a,0xa8,0x50,0xf8,0x65,0x75,0x39,0x5c,0x59,0x57,0xdb,0x47,0xb1,0xe8,0x6e,0x0a, 0x63,0xbf,0xf2,0xf8,0xe1,0xf0,0x67,0x8c,0x2e,0x96,0xf4,0x00,0xa8,0x1b,0x94,0x6b, 0x5a,0x17,0x14,0xd1,0x33,0x72,0x29,0x95,0x60,0x70,0xb3,0xaa,0x25,0x7e,0xf8,0x72, 0x0f,0x30,0x46,0xf8,0xa6,0x02,0x02,0x98,0x4a,0xae,0xb4,0x48,0x8d,0x64,0x61,0xf0, 0x61,0x8c,0xb0,0x63,0x6a,0xc5,0x9d,0x42,0x3a,0x52,0x6a,0x7b,0xb4,0x2d,0xa2,0x7a, 0xd4,0x16,0xda,0x5d,0x3e,0x25,0x01,0x2b,0xa5,0xfe,0x08,0x0a,0x1c,0x94,0xc6,0xce, 0xe6,0x24,0x07,0x59,0x56,0x69,0x44,0xc4,0x4c,0x42,0x55,0xa9,0xaf,0x91,0x44,0x8d, 0xdc,0x5c,0x10,0x5f,0xb1,0xe2,0xaf,0x52,0x26,0xa2,0xb9,0x3f,0x33,0x6d,0x61,0x02, 0x59,0x75,0x38,0x4f,0x9b,0x07,0xd8,0x6a,0x0f,0x53,0x65,0xff,0x7d,0x56,0xe9,0x28, 0xe8,0x67,0x55,0xa9,0x93,0x94,0xb7,0xc7,0xc5,0x71,0x59,0x98,0x68,0xb2,0xac,0x85, 0x21,0x80,0x0a,0xf0,0x50,0x16,0xd3,0x45,0x5e,0xc7,0xb7,0x73,0x98,0x5e,0x35,0xb3, 0x46,0xa2,0x8a,0xea,0xaa,0xaa,0x27,0xef,0x82,0xd2,0x10,0x90,0x8a,0x53,0x04,0xd2, 0x03,0xda,0x73,0x80,0x62,0x7e,0xcc,0x3c,0xea,0xaa,0xa5,0x78,0x4b,0x91,0xb7,0x22, 0xc8,0x8a,0xe6,0x62,0x5b,0xa9,0xcb,0xbe,0xda,0x04,0x70,0x12,0x15,0x61,0xb8,0xc4, 0x38,0x4b,0x71,0x04,0xf4,0x99,0x1e,0x22,0x5d,0xae,0xd5,0x81,0x19,0x37,0xb0,0x44, 0x17,0xb2,0xb6,0x84,0xa6,0xcb,0xbf,0x2b,0x57,0x57,0x3f,0x48,0x90,0xfa,0x9a,0x2f, 0xad,0x96,0xde,0x0e,0xc1,0x25,0x11,0xb4,0x63,0x4c,0x78,0x49,0x0f,0xdc,0xe5,0x46, 0x43,0x7e,0xfa,0x39,0xab,0x40,0x04,0xef,0xf1,0x70,0x91,0x6a,0x38,0x81,0x8c,0xcd, 0x39,0x08,0xbf,0x09,0x20,0x81,0xbc,0x14,0x10,0x63,0x14,0xe2,0xe5,0x8b,0x2b,0x5d}; /* plaintext */ static const int8u plaintext[MBX_RSA3K_DATA_BYTE_LEN] = { 0x43,0x9a,0x10,0x7a,0xf5,0x23,0x48,0x2a,0xb9,0xf7,0x67,0xe7,0x57,0x65,0xbe,0x90, 0xb9,0x50,0x8a,0xc1,0xb0,0x97,0xf5,0x64,0x93,0x8a,0xb0,0xe6,0xdf,0xd9,0x44,0x17, 0xd0,0x29,0x84,0xad,0xf8,0xb0,0xad,0xe2,0xd3,0xda,0xb7,0xf5,0x12,0x47,0x6c,0x25, 0xb2,0x9f,0x7f,0xac,0x04,0x33,0x90,0x9f,0x2c,0x96,0xe9,0x1c,0xae,0x02,0x96,0x12, 0x6c,0x6a,0x88,0x10,0x06,0x9b,0x54,0xc7,0x9d,0x1b,0xd0,0xfd,0x5c,0x46,0xb4,0xe1, 0x13,0x09,0x12,0xfc,0xfb,0xc2,0x2a,0xe8,0x74,0x95,0xda,0xfa,0xd3,0x69,0x2f,0xc7, 0x8a,0xbe,0xea,0x0b,0xd7,0x8e,0xd1,0x39,0x58,0xe6,0x0d,0xa9,0xad,0x22,0x64,0x27, 0x13,0x37,0x12,0x16,0xd6,0xb7,0x8f,0x47,0x86,0x18,0xbb,0x6e,0x79,0xc2,0x92,0xfc, 0x68,0xbc,0x8a,0xc5,0x14,0xe2,0xa0,0x2f,0xd8,0xa1,0x4c,0xf9,0x39,0xb5,0xe5,0x3e, 0xcb,0x55,0x11,0x22,0xd7,0x19,0xc4,0x02,0x33,0xea,0x34,0x6e,0x23,0xde,0x1d,0x6e, 0x3c,0x6f,0x13,0x20,0xb3,0x19,0x97,0xd7,0x14,0xc3,0x3b,0x18,0x13,0xd9,0x1f,0x13, 0x22,0x34,0xc0,0x17,0xa3,0x54,0x2f,0x37,0x35,0xcc,0x53,0xa9,0xc9,0x6f,0x5a,0xaf, 0x52,0x4c,0xe0,0x5e,0x77,0xa6,0x2f,0xba,0xf9,0x15,0x3e,0x37,0x65,0x28,0x2d,0x69, 0x2f,0xcc,0x6e,0xb3,0x68,0x8b,0xe5,0xfb,0xd4,0xb1,0xb0,0x41,0xc8,0xb7,0x8a,0xd5, 0xc5,0x83,0x49,0x8c,0xfc,0x96,0x21,0xab,0x94,0xd8,0x4c,0x82,0x67,0x2a,0x6f,0x95, 0x42,0x83,0xe0,0xb1,0xc2,0xa0,0x10,0xed,0x31,0x26,0xbd,0xe2,0x73,0xb3,0x92,0x91, 0x06,0x70,0xf8,0x10,0xb8,0x01,0xc9,0x34,0x3d,0xd7,0x8e,0x61,0x4e,0x37,0x9e,0x1c, 0xd4,0x62,0x76,0xb2,0x15,0x15,0xd8,0x44,0x46,0xe5,0xc3,0x5d,0xf0,0xb1,0xe5,0xa0, 0xbd,0x70,0x17,0x6f,0x84,0x81,0xa7,0xd4,0x64,0xda,0x0a,0xe0,0xf0,0xd7,0x85,0xe9, 0x86,0x6f,0xe6,0x09,0xed,0x41,0xe3,0x3f,0xfc,0xa6,0xa1,0x30,0x5b,0x36,0x77,0x4d, 0x96,0xf1,0x58,0x99,0x00,0x27,0x4d,0xdf,0xf2,0x9e,0x94,0x0c,0xe3,0xf3,0xe0,0xeb, 0x2b,0xa2,0x02,0x6b,0x88,0xa8,0x10,0xb9,0x36,0xcf,0x41,0xb5,0x8c,0xca,0x33,0x69, 0xeb,0x22,0x6d,0x7d,0xf0,0x66,0x29,0x08,0x79,0x21,0x30,0x47,0x93,0x9d,0x7b,0xbb, 0xa3,0x05,0x8c,0xc6,0x80,0x04,0x78,0x2c,0x27,0xc5,0xfc,0xfd,0xd6,0x12,0x82,0x2c}; /* ciphertext */ static const int8u ciphertext[MBX_RSA3K_DATA_BYTE_LEN] = { 0x14,0x65,0xbe,0x8a,0x00,0xef,0x3e,0xc3,0x36,0xfd,0xa0,0x30,0x4d,0x34,0x22,0xd2, 0x12,0xde,0x7c,0xfa,0x47,0x0c,0x66,0x6b,0x1c,0x2a,0xd2,0x48,0xee,0xf6,0x7d,0x0e, 0x75,0x68,0xf4,0x50,0xa6,0x14,0x5b,0xec,0xc2,0xd4,0xc0,0xfd,0x01,0xdc,0x9d,0xa6, 0x79,0x5d,0x3c,0xc2,0xf7,0x8e,0xb9,0xdc,0x5b,0xd6,0xc9,0xe3,0xb3,0xe5,0xad,0xb6, 0xfc,0x77,0x22,0x48,0xf9,0x5d,0x7d,0xfe,0x71,0x5a,0xb5,0x1e,0x9f,0x48,0x13,0xd0, 0xa6,0x3c,0xf4,0xed,0x7e,0x45,0x21,0x46,0x08,0x99,0x04,0x94,0xc5,0x35,0x9a,0xe7, 0x2f,0x13,0xc4,0x24,0xf9,0xb4,0x79,0x03,0xd5,0x68,0x13,0x89,0x6b,0x31,0x78,0x5a, 0x84,0x11,0x50,0x18,0x2d,0x3b,0x02,0x48,0x44,0xbc,0xaf,0x48,0xe0,0xe9,0x56,0xef, 0xfa,0xaf,0xef,0xb7,0x05,0xac,0xdb,0xf7,0x42,0x0f,0x9b,0xc0,0xaa,0xc7,0x50,0x79, 0x25,0x86,0x60,0x53,0x12,0x37,0x58,0xcd,0xbc,0x29,0x19,0x0f,0xb3,0x66,0xdb,0x36, 0x31,0x55,0x69,0xf5,0xb8,0x8f,0x4f,0x7d,0xdf,0x3a,0xda,0xe0,0xc2,0xe4,0xcb,0x28, 0x70,0x72,0xf5,0x32,0x3a,0xb8,0xbb,0x78,0x7e,0x3a,0xfa,0x1f,0xe7,0x14,0xb4,0x4e, 0x77,0xf1,0xbe,0x80,0x19,0x10,0x75,0xaa,0x1f,0xd0,0x80,0x78,0xcf,0xce,0x9c,0x8e, 0x70,0xd9,0x24,0xa2,0xbb,0x6b,0xd6,0x5c,0xdb,0xe4,0xc5,0x51,0x49,0x1a,0xba,0xaf, 0x94,0x37,0xc2,0xb7,0xfe,0x85,0xcc,0xff,0xcb,0x81,0xb4,0x47,0x5a,0x46,0xd8,0xff, 0x36,0xc9,0x14,0x19,0x25,0x9e,0x6b,0x41,0x0c,0x73,0xe9,0xc6,0xd8,0xcf,0x61,0xdd, 0x82,0xd4,0xc5,0xae,0x53,0x89,0x83,0xc5,0x39,0x47,0x56,0x0d,0x77,0xf0,0xa8,0x76, 0x04,0x07,0xe8,0x34,0xbf,0x54,0x02,0x84,0xf8,0x00,0x36,0xe0,0x46,0x01,0x96,0xca, 0x0a,0xdb,0x99,0x61,0x3f,0x1b,0x86,0x36,0xea,0x6b,0xdb,0xe4,0x1b,0xcf,0x3c,0xe6, 0x16,0x6d,0x48,0x20,0xd7,0xfa,0x4f,0xf3,0xdc,0xd8,0x5c,0x68,0x28,0xe6,0x8a,0x6d, 0x96,0x9f,0xa5,0x71,0x86,0x90,0xc4,0x97,0x4c,0xe5,0x66,0x25,0xed,0xf7,0x07,0xd6, 0xbd,0xbb,0xb7,0xef,0x43,0xc2,0xba,0x6e,0xcc,0x00,0xca,0xb2,0x57,0x3f,0xef,0xdb, 0x08,0x24,0x65,0x7d,0x09,0xd1,0x2f,0x1c,0x1a,0xed,0x35,0x63,0xf6,0xea,0xec,0xea, 0xc3,0x2a,0xe8,0xb0,0xf0,0xa5,0x8f,0xb6,0x21,0xfb,0xf0,0x91,0x72,0x35,0x7e,0xb2}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa3k_private_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA3K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA3K_private_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // private exponent const int64u *pa_d[MBX_LANES]= { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA3K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA3K_DATA_BYTE_LEN, plaintext, MBX_RSA3K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa3k_private_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA3K_DATA_BYTE_LEN]; /* ssl private exponent */ BIGNUM* BN_d = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(d, MBX_RSA3K_DATA_BYTE_LEN, BN_d); BN_lebin2bn(moduli, MBX_RSA3K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; // private exponent const BIGNUM *pa_d[MBX_LANES] = { (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d}; /* test function */ sts = mbx_rsa_private_ssl_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA3K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA3K_DATA_BYTE_LEN, plaintext, MBX_RSA3K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa3k_public_mb8.c000066400000000000000000000267331470420105600340610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA3K_DATA_BYTE_LEN] = { 0x2d,0xdd,0xba,0xb9,0x81,0x55,0xf3,0x2e,0x4f,0x5b,0xd8,0x6a,0x9c,0xa0,0x9c,0x37, 0x7d,0x25,0x6b,0x92,0xc5,0xe2,0x80,0xa9,0xe1,0x72,0xcb,0xbd,0xf8,0xf0,0xde,0x52, 0x04,0xc4,0xde,0x04,0x9d,0x74,0xa1,0xf0,0xc6,0x89,0x89,0x5e,0xf4,0xf7,0x38,0x03, 0x9d,0xbd,0xa8,0xaa,0x6e,0x3f,0x68,0x2d,0x80,0x35,0x95,0xf0,0xa4,0xb4,0x23,0xe0, 0x12,0x33,0x1d,0x73,0xa5,0xea,0xf0,0xa8,0x95,0xd0,0x09,0x34,0x32,0x1a,0xc4,0x35, 0x16,0xe9,0xf4,0xf9,0x30,0x97,0x1d,0xb5,0xb4,0x39,0x7e,0x00,0xf9,0x16,0x22,0x1b, 0x69,0x18,0x9a,0x43,0xc0,0xab,0x21,0x34,0x7b,0x66,0xd6,0xee,0x88,0xfd,0x7b,0x77, 0x22,0x3e,0x58,0xe8,0x39,0x57,0x92,0x54,0xb9,0x21,0x02,0x28,0xdb,0x56,0xcf,0xe1, 0xe1,0xf6,0xa0,0x79,0x69,0x2f,0x20,0x0f,0xe3,0x18,0x0d,0x72,0xda,0x09,0x79,0x7c, 0x48,0x23,0x6d,0x7f,0xf3,0x8e,0xb7,0xce,0xad,0xf1,0xba,0xb2,0x76,0x59,0x22,0xd0, 0xad,0xb1,0x7c,0xae,0x9e,0x86,0xcd,0xb8,0x0d,0x8f,0x4c,0x53,0x8c,0x08,0x07,0xf5, 0x90,0xa4,0xe8,0x25,0x4d,0x30,0x24,0x0f,0x6f,0x50,0x9b,0x83,0xd1,0x92,0x5d,0xc5, 0xd5,0xfd,0xec,0x0b,0x88,0x1f,0xfc,0x5a,0x16,0x2a,0x87,0x9d,0x93,0x3f,0xfe,0x3a, 0x08,0x05,0xd8,0x6d,0x16,0xe1,0x3c,0x86,0x3b,0x65,0x23,0xbc,0xda,0x35,0xb3,0x2b, 0x43,0x28,0x1e,0x1c,0x3e,0xc8,0xaa,0x37,0x46,0x31,0xa4,0x9c,0x0b,0xc4,0x4c,0x50, 0xf4,0x0c,0xac,0x2d,0x4d,0xa3,0x43,0x40,0x5a,0xb2,0xb0,0x38,0x22,0xbe,0x42,0x85, 0x17,0xd9,0xaa,0xc5,0x2f,0xca,0x2d,0xa9,0x1d,0x71,0xc7,0x8f,0x53,0xc4,0xb3,0x73, 0x03,0xa4,0xbc,0xf3,0x24,0xe7,0x57,0x8f,0x5f,0x08,0x5e,0xe9,0xe8,0xcd,0xfd,0xf9, 0xc0,0x2f,0x57,0xae,0x46,0xea,0xbb,0xa7,0xc1,0xa5,0xd9,0x5d,0x86,0x1d,0x45,0x39, 0x92,0x30,0x94,0x11,0xc5,0x48,0x3e,0xde,0x04,0x1a,0xfa,0x4f,0x87,0x7d,0x17,0x96, 0x89,0x25,0x24,0x3d,0xa7,0x64,0xff,0xc3,0xd1,0x17,0x2f,0xef,0xf2,0x60,0x2f,0xcd, 0x4c,0xae,0xd9,0x5c,0xb9,0xeb,0x14,0x93,0xe4,0x86,0xa5,0xde,0x1a,0xf6,0xef,0xf6, 0x66,0x49,0xab,0xae,0xb2,0x01,0x61,0xe9,0x1a,0x76,0xcf,0x75,0xbc,0xcf,0x00,0x30, 0xff,0x36,0x42,0x28,0xfa,0xdb,0x24,0x67,0x56,0x5c,0x85,0x40,0x0e,0xac,0x7e,0xe7}; /* plaintext */ static const int8u plaintext[MBX_RSA3K_DATA_BYTE_LEN] = { 0xab,0x58,0x51,0x58,0x18,0x3d,0xff,0x97,0x5c,0x1e,0x73,0x8d,0xce,0x25,0xa4,0x60, 0x24,0x77,0xdd,0xe4,0x90,0x0b,0x18,0x5b,0x0f,0x93,0xb4,0xfc,0x5e,0x6a,0x07,0xa5, 0xdd,0x0b,0x2c,0x95,0x5e,0xb3,0xe4,0x10,0xc7,0xe6,0x70,0x78,0x29,0xda,0xe1,0x36, 0xcc,0xa2,0xa2,0xf7,0xa9,0xcd,0xc6,0x5f,0xfa,0x48,0x4f,0xe6,0x49,0x0d,0xab,0xd6, 0x2f,0x98,0xda,0xb4,0x83,0x7c,0x1e,0xa8,0xd5,0xd1,0xa3,0x3c,0x25,0x24,0xad,0x17, 0x1e,0xc1,0x90,0xd3,0xe9,0x43,0x97,0x90,0x98,0xae,0xb6,0x89,0xec,0x43,0x9e,0x0d, 0x3c,0x34,0xf1,0x47,0x92,0x47,0xbc,0x2d,0xd6,0xa0,0xc2,0xb8,0xf7,0x23,0xdb,0xb9, 0xa8,0xc5,0xe5,0x68,0xcd,0xcf,0x1d,0xae,0x28,0x65,0xea,0x23,0xdc,0xd9,0xcd,0x91, 0x62,0x81,0x32,0x52,0x65,0x67,0x53,0xef,0xcb,0x98,0x81,0x80,0xca,0xbf,0x3f,0xad, 0x36,0xd0,0x44,0xe2,0x99,0x87,0x95,0xd2,0xf3,0xd1,0xa1,0xa5,0x7a,0x22,0x85,0xf9, 0xf6,0x5e,0x33,0x8c,0x70,0x26,0x3a,0xb9,0x39,0x0b,0x22,0x03,0x35,0xbb,0x8d,0xbb, 0x5e,0x93,0x90,0xd5,0xd4,0x13,0x6c,0x41,0x91,0xc9,0xce,0x7c,0x22,0x5b,0x97,0xc6, 0x59,0x9e,0xfc,0xde,0x83,0xb6,0x35,0x8c,0xe1,0xc3,0x17,0x93,0x66,0xf7,0xa3,0x24, 0xa1,0x34,0x3d,0x13,0x03,0x0f,0xd0,0x27,0x89,0xc4,0xdc,0x39,0x3e,0x67,0xe9,0x8b, 0x89,0x5f,0x78,0x6c,0x0a,0xaa,0xc0,0x43,0x9e,0x3a,0xb3,0x28,0xe6,0xad,0x93,0xae, 0xac,0x3a,0x31,0x77,0xf3,0x63,0xa6,0xab,0x65,0xbb,0x1e,0x4b,0x9f,0xa7,0xb8,0xce, 0x5f,0xc5,0xc9,0xb6,0x0c,0xc6,0xe7,0xec,0xd8,0x00,0x9d,0x4f,0x0b,0x03,0x95,0x0c, 0x7e,0x0c,0x95,0xc1,0x1d,0x21,0x48,0xf0,0x29,0x0d,0x09,0x8a,0x4d,0xa6,0x3e,0x28, 0x1e,0x7a,0x6d,0xb3,0x61,0xab,0xff,0x48,0xa5,0x9d,0x9f,0xcf,0xe9,0xc7,0xed,0xb9, 0xa6,0xcd,0xb6,0xe2,0xb1,0x04,0xfd,0x34,0xd9,0x80,0x9a,0x51,0x9b,0x01,0x12,0x4f, 0x0c,0xd0,0xe9,0x70,0x54,0x83,0xd4,0xe5,0xc4,0x32,0x4e,0x99,0xd9,0x80,0xd5,0xd7, 0x3b,0x91,0xc6,0x06,0xf9,0x91,0xc3,0x9b,0xe6,0x89,0x15,0x50,0x42,0x73,0x5d,0xb5, 0x5f,0xaa,0x10,0x7e,0x74,0xf9,0x9d,0xf7,0x2f,0xd1,0x23,0xf6,0x55,0x9f,0x67,0xe0, 0x75,0xdc,0xf0,0xfc,0x31,0x63,0x6e,0x97,0x45,0x4c,0x4b,0xc0,0x1a,0x85,0xab,0x67}; /* ciphertext */ static const int8u ciphertext[MBX_RSA3K_DATA_BYTE_LEN] = { 0x5f,0x90,0x79,0xdb,0x8c,0x83,0xae,0x9d,0x81,0x00,0x79,0x97,0x34,0x9d,0x0e,0x10, 0x36,0xef,0x23,0xf9,0x8e,0x89,0xc8,0xdc,0x32,0x7c,0xb7,0x75,0x8e,0x6e,0xb6,0x58, 0xc3,0x3a,0x79,0x52,0x5b,0x0b,0x0d,0x80,0xac,0x34,0x9c,0xa6,0xe0,0x26,0x12,0xf3, 0xd2,0x3b,0xbd,0xce,0x44,0x2f,0x4c,0xd4,0x9d,0x58,0xdd,0xc0,0xdc,0xaa,0x03,0xe7, 0x78,0x9b,0x31,0x92,0x1d,0xe6,0xc2,0x39,0xd1,0x9a,0xdf,0x62,0x31,0x5c,0xfd,0xcc, 0x15,0x90,0x49,0xe6,0xbe,0x77,0x61,0x73,0x08,0x67,0xac,0x2b,0x88,0x1c,0x2e,0x25, 0xbe,0x30,0x4a,0x29,0x60,0x42,0x84,0xc0,0x62,0xb8,0x21,0xe0,0x03,0x79,0xfc,0x9d, 0xe8,0x3e,0x72,0xaf,0x3c,0xf1,0xd5,0x0d,0x2f,0x3c,0xe0,0x13,0x75,0xca,0x81,0x73, 0xf2,0xcd,0xd0,0xf1,0xd3,0x77,0xbb,0x83,0x01,0xc4,0x3f,0x47,0x06,0x4f,0x34,0x20, 0xd3,0x64,0x69,0xc0,0x80,0xb9,0xf5,0x79,0x2c,0x01,0x40,0xf0,0xd9,0xb8,0x92,0x5b, 0xbb,0xbf,0x9a,0xf9,0x50,0x48,0x01,0xaf,0xae,0x0a,0x06,0x88,0xbc,0xf0,0xce,0x55, 0x6d,0x83,0x8c,0x70,0x83,0x74,0xe6,0x0c,0x42,0xdb,0xc0,0x78,0x43,0xa7,0x36,0x6a, 0xc7,0x74,0xa0,0x76,0x02,0x5e,0xfa,0x7b,0xf5,0xf4,0x6a,0xf2,0xea,0x43,0x58,0xba, 0x75,0x24,0x9b,0xc8,0xbc,0x06,0xd8,0x16,0x26,0x1a,0xeb,0xad,0x3e,0xc0,0x0d,0xc9, 0xc3,0xd4,0x7d,0xd1,0xee,0xf0,0x8a,0x1c,0x6a,0x3f,0x94,0x8d,0x9f,0x6e,0xc1,0x0f, 0xb8,0xd9,0xed,0xe9,0x38,0xfa,0x67,0x28,0x30,0x5a,0xad,0x9c,0x33,0x02,0x64,0xa7, 0x76,0xb4,0xad,0x56,0xf8,0x0f,0x04,0x9e,0x7b,0x68,0x88,0xeb,0xeb,0x5f,0x12,0x87, 0xfb,0xe9,0x7a,0x12,0x8f,0x45,0xd3,0x10,0x84,0x59,0x63,0x42,0x69,0x05,0x03,0x9e, 0xe3,0x30,0x31,0xb2,0x85,0x58,0xf0,0xd3,0x94,0x97,0xc1,0x83,0x14,0xc3,0x95,0x1d, 0x12,0xfe,0x47,0x26,0x23,0x50,0x0e,0x69,0xcd,0xf3,0xc5,0x63,0x05,0x65,0xda,0xc9, 0x4d,0x93,0x57,0x44,0x92,0xd3,0xeb,0x4e,0x24,0x05,0x61,0x84,0xec,0x6f,0x2d,0xb6, 0xd5,0xcc,0xf4,0xa1,0x3e,0x5b,0x2e,0xbc,0x9c,0xdc,0xf9,0xf0,0x36,0xc9,0x2f,0x6c, 0xaf,0x72,0x44,0x2b,0xa8,0x35,0x18,0x27,0x08,0xa0,0x15,0x69,0x1b,0xef,0xcd,0x87, 0x31,0xe0,0xe6,0x52,0x05,0xb1,0x50,0x61,0x8b,0xa1,0x34,0x17,0x9e,0x00,0x71,0xd0}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa3k_public_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA3K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA3K_pub65537_Method(); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_public_mb8(pa_plaintext, pa_ciphertext, pa_moduli, MBX_RSA3K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output ciphertext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA3K_DATA_BYTE_LEN, ciphertext, MBX_RSA3K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE /* exponent (for ssl function only) */ static const int8u exponent[MBX_RSA_PUB_EXP_BYTE_LEN] = {0x01,0x00,0x01}; // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa3k_public_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA3K_DATA_BYTE_LEN]; /* ssl exponent */ BIGNUM* BN_e = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_e || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_e, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(exponent, MBX_RSA_PUB_EXP_BYTE_LEN, BN_e); BN_lebin2bn(moduli, MBX_RSA3K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; const BIGNUM *pa_e[MBX_LANES] = { (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e}; /* test function */ sts = mbx_rsa_public_ssl_mb8(pa_plaintext, pa_ciphertext, pa_e, pa_moduli, MBX_RSA3K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA3K_DATA_BYTE_LEN, ciphertext, MBX_RSA3K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_e, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE selftest_mbx_rsa4k_private_crt_mb8.c000066400000000000000000000470271470420105600350460ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* plaintext */ static const int8u plaintext[MBX_RSA4K_DATA_BYTE_LEN] = { 0x54,0xaa,0x9a,0x6c,0xc8,0x5e,0xea,0xde,0xc2,0xe7,0xcc,0x9a,0x0f,0xe1,0x55,0xe4, 0x3e,0xd8,0x1b,0x11,0x67,0xa5,0x52,0x1b,0x21,0x0e,0x29,0x42,0x9c,0xfd,0x66,0x66, 0x03,0x82,0x80,0x66,0x10,0x6a,0x4a,0x98,0x85,0xf9,0x09,0x91,0x7b,0x8a,0xdb,0xc3, 0x8a,0xf0,0x42,0x96,0x0a,0x9c,0x4e,0xa7,0xa0,0x10,0xe0,0xae,0x6e,0x71,0xe8,0x69, 0x8f,0xb1,0x34,0x4e,0x3e,0xbf,0xde,0xd4,0x08,0x9d,0xeb,0x4a,0x0e,0xf1,0x56,0xec, 0x38,0x54,0x27,0x94,0xbc,0xe0,0x76,0xc7,0xe9,0x22,0xff,0x6f,0xa6,0xd9,0xdb,0x2e, 0x83,0xda,0x62,0xc2,0xfb,0x8b,0x63,0xbe,0xe4,0x19,0x5e,0x17,0x21,0x18,0x7d,0x5f, 0x0d,0x51,0xca,0x03,0x39,0xbf,0x64,0x03,0xb3,0x90,0x08,0x67,0x31,0x1b,0xb4,0x7d, 0xab,0x8f,0x87,0x77,0x1a,0x3d,0x97,0x58,0x24,0xa4,0x1e,0x83,0x2f,0x91,0xe1,0x8d, 0x57,0xb7,0xd8,0xfc,0xfc,0x3c,0xd3,0x84,0xbb,0x15,0xd6,0xc1,0x70,0x6a,0xf3,0x26, 0xe7,0x8b,0x33,0xfc,0x66,0x18,0x2d,0x89,0xed,0xae,0xbc,0x72,0xff,0x83,0xaf,0x33, 0x03,0xf9,0xd8,0xa3,0xf4,0x1e,0xa4,0x2f,0xdc,0x21,0x27,0x0a,0x7c,0x9b,0x7c,0xf4, 0xc5,0xe1,0xa1,0xc3,0x43,0x2f,0xcd,0xb4,0xb2,0xf5,0x5b,0x30,0x5f,0x00,0x59,0x5e, 0x0d,0x9e,0x46,0x32,0x0f,0x0a,0x93,0x5c,0x03,0xb4,0x75,0x24,0x7e,0x74,0x7e,0x10, 0x15,0x76,0x71,0x28,0x77,0x5b,0x13,0x3d,0xd9,0x3f,0xa5,0x06,0x1a,0xe5,0xe5,0x5e, 0x82,0x58,0x6f,0x1d,0xc0,0xe1,0x5b,0xf3,0xe3,0x27,0xa4,0x99,0x74,0x84,0x61,0x1c, 0xd3,0x77,0xff,0x08,0xf3,0xcd,0x84,0x28,0xa7,0x4f,0x95,0x15,0xeb,0xcc,0xa9,0xce, 0xfb,0x77,0x34,0xcf,0xe7,0x82,0x21,0xcc,0xfb,0xda,0xdc,0x10,0xa1,0x41,0xc6,0x43, 0x6d,0xa4,0xa8,0x16,0xe8,0x2f,0x13,0x79,0x5d,0x11,0xf7,0x27,0xba,0x0d,0x71,0xd6, 0xde,0x8d,0x32,0xae,0x5d,0x48,0x38,0x46,0xdf,0x88,0xe6,0xa7,0x1d,0x08,0x01,0xb0, 0xd3,0xc7,0x47,0x5f,0x94,0xde,0x06,0x04,0xf9,0x33,0xff,0x94,0x5c,0xbd,0xfa,0xa5, 0x57,0x7b,0xde,0xc8,0xfb,0x94,0xda,0x78,0x61,0x18,0x35,0x50,0xf2,0xf3,0xf4,0x18, 0x21,0xe0,0xf1,0xf5,0xe6,0x55,0x05,0xe2,0x8f,0xce,0xd4,0x91,0xd0,0x8a,0x80,0xd0, 0xa0,0x74,0x42,0xf0,0x46,0x64,0x57,0x16,0x58,0x02,0xc4,0x78,0xcf,0xfe,0x4d,0xca, 0xf1,0x80,0x9f,0x10,0xd9,0x12,0xe3,0x0e,0xe2,0x36,0xe6,0x55,0xfe,0x9f,0xee,0x2a, 0xa3,0x85,0x47,0xa9,0x12,0xc6,0xb0,0x07,0x25,0xbf,0xd7,0xc3,0xca,0x5b,0xf1,0x2f, 0x67,0xd7,0x97,0x25,0x60,0x9a,0x75,0x90,0xb2,0x5c,0x8a,0x72,0xc5,0xe0,0x6a,0xcc, 0x98,0x1d,0x45,0xa3,0x17,0x22,0xce,0x8f,0x01,0xc4,0x37,0x79,0x90,0x7d,0x6f,0xce, 0x00,0xaa,0x32,0x1d,0x2c,0xc7,0x88,0xfd,0xe8,0xbe,0x10,0x33,0x78,0x4d,0xa2,0xe8, 0x40,0x6c,0xcc,0x42,0xec,0x4b,0xac,0x5e,0x30,0xd9,0x3e,0xfc,0x29,0x87,0x3c,0x49, 0x19,0xb8,0xc7,0x9e,0xe5,0xea,0xeb,0x63,0x16,0xdb,0x3c,0x32,0x03,0xdb,0x13,0x45, 0x3c,0xfa,0xbb,0xaf,0x9f,0x1b,0xa1,0xc0,0xd1,0x19,0x80,0x89,0xca,0xb6,0xc9,0x67}; /* ciphertext */ static const int8u ciphertext[MBX_RSA4K_DATA_BYTE_LEN] = { 0x71,0x49,0x42,0x84,0x78,0xd2,0x44,0x99,0xf0,0xb8,0x64,0x01,0x3a,0x1b,0x0c,0x68, 0xd4,0x4f,0xc2,0x0f,0x73,0xf8,0x64,0xcb,0x0f,0xbf,0x7e,0x5d,0x31,0x62,0x33,0x77, 0x8c,0xe4,0x61,0x4d,0xa1,0x35,0x47,0xb9,0xce,0x9b,0xf6,0x5e,0xd3,0x46,0x87,0x15, 0x03,0xda,0xb4,0xc8,0x7f,0x75,0x22,0x30,0x80,0x97,0xed,0x6f,0x8f,0x5f,0xe9,0x05, 0x95,0x07,0x3f,0xef,0x3a,0x79,0x73,0x75,0xb6,0x77,0xd5,0x6b,0xfc,0xc7,0x27,0x25, 0xb1,0xb5,0xf6,0x43,0x21,0xcf,0x9d,0xf1,0xee,0xb0,0x1b,0x59,0x59,0xca,0xd6,0x16, 0x97,0x38,0x8f,0x5a,0x43,0xc8,0xff,0xd2,0x11,0x3f,0x90,0x34,0xb2,0xcd,0x83,0x33, 0x5a,0xde,0xe6,0x34,0x3b,0x34,0xc5,0x2b,0x3a,0xa0,0x19,0x89,0x13,0x6d,0xd0,0x62, 0x28,0x2f,0x82,0x5e,0xa5,0x87,0x9c,0x3d,0x6e,0x0b,0xc6,0xa9,0xc4,0xf2,0xab,0x25, 0xcf,0x6e,0x50,0xa3,0x14,0x21,0xec,0x4c,0x65,0x42,0x59,0xe7,0x05,0x47,0x70,0x19, 0x00,0x16,0x0d,0xac,0x49,0x33,0x38,0x17,0xf0,0x11,0x88,0x6b,0xe6,0x0a,0xfa,0xd7, 0x28,0x37,0x42,0x65,0xb9,0xfe,0x1e,0x9b,0x37,0x29,0xf4,0xa8,0x65,0xc1,0x16,0x5d, 0x51,0x09,0xe9,0xab,0x0a,0x5b,0x3c,0x43,0x4f,0x14,0xc0,0xfb,0x41,0x6b,0x7d,0x31, 0xbb,0x58,0x28,0x8e,0x2e,0xfb,0x89,0x1c,0x60,0xa1,0x76,0x28,0x14,0x27,0x29,0x92, 0x6e,0xa7,0x96,0x9d,0x61,0x08,0xc6,0x8d,0x3d,0xb2,0x67,0x05,0x99,0x31,0xcd,0x08, 0x83,0xc7,0xfd,0x73,0x8d,0x69,0x9b,0xc9,0x6d,0x88,0x59,0x47,0x2e,0x19,0x4d,0x62, 0xe8,0x14,0x35,0x15,0x75,0x49,0x3e,0x2b,0x83,0x18,0xc4,0x16,0xda,0xd1,0x3d,0x06, 0xaf,0x3b,0x3e,0x25,0x1e,0x1d,0xc3,0xfd,0xc0,0x26,0xf0,0x2a,0xe1,0x42,0xf3,0x24, 0x1e,0x6a,0x63,0x8e,0xb7,0x25,0xe8,0x5c,0x01,0x12,0xda,0xa7,0x52,0xde,0x6a,0x65, 0x7c,0x30,0xd3,0x93,0xa8,0x57,0x40,0x92,0x14,0xe5,0xda,0x4e,0xf0,0xbb,0x4b,0x11, 0x03,0x12,0x29,0xb2,0x8b,0x3b,0x2d,0x7e,0x3d,0xad,0xbc,0x16,0x1b,0x22,0xd8,0x3a, 0x91,0xba,0xef,0x71,0x2e,0x0e,0xda,0xb0,0x8c,0xc7,0xbd,0xc5,0x69,0x10,0x41,0x86, 0x79,0x63,0xb3,0x65,0xa4,0x11,0x81,0x63,0x77,0xdb,0xa6,0xdb,0xfc,0x5a,0x7f,0x55, 0x34,0xec,0x4b,0x79,0x8d,0x2f,0xf2,0x1f,0xfe,0x41,0x46,0xd0,0x70,0xc4,0xfe,0x1c, 0x8d,0x2e,0x32,0x16,0x78,0xab,0x83,0xf2,0x87,0xef,0x6a,0x70,0x62,0xc0,0x07,0x7f, 0x6d,0xe7,0x43,0xc6,0x56,0x0f,0x19,0xc1,0x7a,0x75,0xb6,0xd7,0xbb,0xe0,0x4f,0x14, 0xc8,0x63,0xd2,0xab,0xa5,0xf3,0xdb,0x44,0x3c,0x0b,0x4f,0x9d,0xc9,0x49,0x74,0xaf, 0x6e,0x9d,0x35,0xc9,0xef,0xa6,0x0d,0xb6,0x8a,0xef,0xfa,0xa0,0x80,0xa4,0x90,0xdc, 0xef,0x91,0x4a,0x06,0x7b,0x8b,0xe1,0xd8,0xae,0x40,0xa6,0x42,0x78,0x30,0x58,0x40, 0xbd,0xfe,0x03,0xe9,0x31,0x26,0x11,0x4c,0xa2,0x05,0xb8,0xb5,0xad,0x00,0x94,0x50, 0x8f,0xad,0xd2,0x7b,0x8e,0xd8,0x88,0x51,0x1a,0x40,0x7a,0xc2,0x20,0x84,0x3a,0x97, 0x19,0x14,0x10,0x84,0x20,0xfa,0xd4,0x46,0x91,0xbb,0x72,0xe2,0x8d,0x7c,0xc4,0xa9}; /* p, q primes */ static const int8u p[MBX_RSA4K_DATA_BYTE_LEN / 2] = { 0x95,0xef,0x9e,0x93,0xea,0x9c,0x13,0x41,0x6c,0xba,0xd0,0x91,0x72,0x4f,0xeb,0x18, 0xcd,0x34,0xcf,0x6a,0x1e,0x55,0xed,0xec,0x12,0x41,0x5e,0x5e,0x2f,0xb8,0x16,0xb2, 0x97,0x69,0x2a,0x51,0x11,0x94,0x20,0xb0,0x2e,0x0e,0x89,0x79,0xfa,0x2e,0xd1,0xb7, 0x30,0x7c,0xab,0x77,0xd7,0xb9,0xc7,0x65,0x06,0xa0,0x23,0xb6,0x50,0x89,0xa1,0x06, 0x75,0x0d,0x75,0x0e,0x5e,0x97,0x10,0xe0,0x37,0x0a,0x5a,0x0a,0x1f,0x5f,0x83,0x6d, 0x24,0x8d,0x52,0x39,0x7d,0xbb,0x33,0x9d,0x6d,0xee,0x31,0x7f,0x4f,0x2f,0x8d,0x62, 0x20,0xd6,0x8b,0x2a,0xd9,0x23,0x35,0x59,0x0a,0x54,0xe9,0x14,0x02,0x3f,0xad,0x0d, 0xff,0x85,0xa1,0x11,0x92,0x8d,0xb9,0x82,0x23,0x54,0xb3,0x71,0x73,0x23,0x21,0x4e, 0xa0,0x05,0x16,0x1e,0xe1,0x21,0xe2,0xd3,0xab,0xd9,0xc1,0x7b,0x90,0xf6,0xf5,0xa0, 0xb3,0x8c,0xe9,0x30,0x38,0x8c,0x50,0x18,0x51,0xb1,0x53,0x2e,0xa9,0x59,0xaa,0x54, 0x51,0xa9,0x4d,0x40,0x84,0x42,0xf3,0x76,0x0f,0x71,0xbd,0x7d,0xc9,0xd5,0x17,0x0f, 0x05,0x3a,0x99,0x00,0x3e,0xec,0x7c,0x94,0x3f,0xad,0xdd,0x53,0x6a,0x0e,0xf4,0xa2, 0x40,0x44,0xb9,0xaa,0xc7,0x95,0x7d,0x71,0x3e,0xcc,0x46,0xb5,0x36,0x91,0x09,0xce, 0xdc,0x62,0x83,0xc2,0x8c,0x61,0x5d,0xa6,0x98,0xf3,0xbf,0x7e,0xfe,0x03,0x37,0xdf, 0x30,0x8f,0xc8,0xb1,0xa5,0x75,0x9a,0xdf,0xb3,0x94,0x67,0x2f,0x16,0x93,0x75,0xd0, 0x9f,0x80,0x85,0x06,0x7b,0x75,0x92,0xf7,0xe0,0x96,0x9b,0x74,0xf3,0x14,0xbf,0xe7}; static const int8u q[MBX_RSA4K_DATA_BYTE_LEN / 2] = { 0xd5,0x16,0x05,0x04,0x67,0xd4,0x03,0x14,0x83,0x1e,0xb7,0xb2,0x92,0xb7,0xb4,0x11, 0x17,0xc3,0xe1,0xa9,0x57,0xe5,0x77,0x1f,0x40,0x06,0xad,0x2e,0xa6,0x7f,0xf6,0x4b, 0x92,0xd9,0xea,0x81,0xee,0xa3,0xd8,0x8b,0x11,0xbb,0x5a,0x7e,0xff,0xe0,0x16,0x8f, 0xba,0x37,0x65,0xb7,0xf8,0xa6,0x00,0xc1,0xed,0x1f,0xaf,0x02,0xa3,0x5f,0xa5,0x63, 0xfe,0x23,0x2a,0x2b,0x57,0x2c,0x31,0xfe,0x63,0xa9,0x0d,0x85,0xc5,0xd9,0x74,0x11, 0xbb,0x76,0x0c,0x1e,0x13,0x2f,0xbe,0xf3,0xd2,0x2c,0xca,0x9f,0x21,0xc3,0x83,0x84, 0xb6,0x25,0x62,0xa6,0xda,0xc0,0xff,0x5d,0xc2,0xe5,0x27,0x7c,0x26,0xa2,0x0f,0xf4, 0xef,0x0f,0x28,0x34,0x2e,0x5a,0xbd,0x1a,0xd3,0x79,0x3a,0xac,0xaa,0x90,0x45,0x9b, 0xb2,0xb2,0x6e,0xa8,0xb6,0x00,0x73,0x84,0xc5,0x06,0x25,0x95,0x2c,0x62,0x01,0x41, 0x0e,0xc9,0xad,0xf4,0xff,0x31,0x0f,0x5c,0x19,0x6b,0xa7,0xc4,0x00,0xf1,0xce,0x1e, 0xfa,0x76,0x72,0xf8,0x3c,0x78,0xc7,0x1c,0x27,0x4b,0x42,0xe0,0x19,0xbc,0xdd,0x78, 0x9c,0x95,0x98,0xec,0x38,0xa8,0xf8,0x23,0xb0,0x8f,0x3b,0xc7,0xcf,0xbf,0x14,0xdc, 0x39,0xef,0x35,0x83,0x85,0x78,0x9f,0xa6,0x88,0x49,0x2a,0x4b,0x9d,0xe2,0x31,0x87, 0x69,0x7c,0x68,0xcf,0xdf,0x89,0x51,0xaf,0x81,0xbf,0xed,0x12,0x2f,0x67,0xf2,0x27, 0xe7,0x7e,0xe9,0xdc,0x6f,0x9f,0x01,0x56,0x3d,0xa8,0x0f,0xcd,0xd4,0x3d,0x73,0x45, 0x5e,0x83,0xb1,0xd3,0x76,0x44,0x02,0xc9,0xc7,0xe9,0xfb,0xe7,0xa4,0xd1,0x25,0xc5}; /* p's, q's CRT private exponent */ static const int8u dp[MBX_RSA4K_DATA_BYTE_LEN / 2] = { 0x81,0xc8,0x46,0x8f,0x46,0x92,0x80,0x8a,0x34,0xff,0xf3,0x06,0x18,0x67,0x02,0x6f, 0x16,0x73,0x0f,0xc6,0x92,0xdc,0x5d,0x0a,0x2c,0xe1,0xc8,0x3d,0xfe,0x02,0x4a,0x98, 0xe9,0x78,0xe1,0x04,0x74,0x53,0xf9,0xc9,0x0d,0x06,0x8a,0xf2,0xb6,0xe1,0x0d,0x05, 0x60,0x1c,0x3f,0x3e,0x9c,0xaa,0xc2,0x56,0x77,0x73,0x2e,0x44,0xc7,0xf0,0x43,0x01, 0xb7,0xdc,0x2c,0xa3,0x9e,0x0d,0xbb,0x96,0x55,0x4b,0xc6,0x25,0x7f,0xe9,0xfd,0xf7, 0x25,0x59,0x97,0x5f,0x92,0x89,0xc2,0x0f,0x59,0x5b,0xfc,0xfc,0xf9,0xa0,0x62,0x1f, 0x30,0xb0,0x98,0xaf,0xee,0xf2,0x38,0x8b,0xfc,0xd9,0x26,0xee,0xf2,0x06,0xce,0x91, 0x65,0xea,0xb7,0xe6,0x76,0x17,0xc5,0x12,0xae,0x5c,0xbc,0x6f,0xf3,0xbc,0x97,0x48, 0x44,0xb1,0x0e,0x38,0xfc,0x63,0xbe,0xc0,0x69,0xf2,0x1c,0x2a,0x83,0x02,0x99,0xce, 0x4f,0xf3,0xad,0x64,0x01,0xd4,0x39,0xb5,0x33,0x9b,0x48,0x8f,0x4d,0x66,0x08,0xc3, 0x47,0x9e,0x37,0x1c,0x46,0x24,0x36,0xab,0x71,0x48,0x50,0xd8,0x7d,0xa7,0xb2,0x63, 0xa6,0x46,0x35,0x98,0xb5,0x40,0xe3,0x32,0x08,0xb7,0x90,0x2e,0x26,0x51,0x62,0x37, 0x35,0x5e,0x83,0xb7,0xa0,0x45,0x67,0x7d,0x19,0x7b,0xcb,0x73,0xac,0x7a,0x94,0xf2, 0x90,0x14,0xf8,0xed,0xf3,0x13,0x77,0xcc,0x14,0xc9,0x72,0xab,0xc3,0x68,0xba,0x5b, 0xb9,0xb0,0x56,0x0c,0x87,0x6f,0xa3,0x27,0xcc,0xab,0x2e,0xaf,0xd4,0x65,0x72,0x7f, 0x40,0x37,0xdc,0xe2,0xd6,0xa8,0x47,0xb1,0xfc,0xff,0x19,0x08,0x66,0x95,0xd6,0x40}; static const int8u dq[MBX_RSA4K_DATA_BYTE_LEN / 2] = { 0x21,0x2b,0xb5,0x06,0x56,0xa1,0x68,0xec,0xcc,0x6f,0xb5,0xdf,0x1b,0xa4,0x90,0xbe, 0x82,0xce,0xfb,0x5e,0x20,0xb9,0xa3,0x0a,0xe2,0x12,0x59,0x7b,0xd0,0x76,0xe9,0x58, 0x67,0x6f,0x83,0x82,0x37,0x28,0xe2,0x4f,0xed,0x5e,0x13,0x79,0x69,0x20,0x36,0x47, 0xde,0xb2,0xa6,0xb9,0xa0,0x0d,0x10,0xad,0x12,0x48,0x58,0xa2,0xec,0xf4,0x0f,0x86, 0xc7,0xeb,0xcf,0x03,0x1d,0x9e,0x01,0x93,0x6a,0x86,0x13,0x49,0x19,0x3b,0x67,0x01, 0x45,0x5f,0xe5,0xb5,0xef,0x45,0x05,0x7c,0x13,0x01,0x81,0xf8,0x09,0xc3,0xc5,0x9c, 0x7f,0x19,0x09,0xd3,0xa6,0xa6,0x47,0x02,0x8e,0x07,0xc2,0xcf,0x13,0xcf,0xea,0x10, 0x3f,0xa3,0xc9,0xf8,0x3c,0x43,0xe3,0xfe,0x92,0x0a,0x20,0x61,0xb7,0x39,0xc2,0x47, 0x6f,0x86,0xc1,0x1d,0x89,0x54,0x03,0x2b,0x18,0xe1,0xf1,0x0b,0xa0,0x41,0x05,0x8e, 0x71,0xf2,0x97,0xa1,0x23,0x2d,0x4d,0xe6,0x68,0x28,0x2c,0x35,0xd7,0x08,0x53,0xd1, 0x2f,0x9e,0xf1,0xf1,0x3d,0xa1,0xcf,0x12,0x01,0x86,0xb8,0xe5,0xc9,0x5f,0x4c,0x32, 0x9b,0x19,0xe4,0xda,0x57,0xc4,0x3c,0x09,0x4a,0x86,0x83,0xbc,0xa1,0xdd,0xf6,0xd4, 0x13,0x7d,0x7b,0x84,0x7c,0x2d,0x59,0x9c,0x8d,0x97,0x3d,0x5c,0x34,0x8f,0x51,0x9e, 0xb8,0x91,0x74,0xf8,0x1a,0xfd,0x7b,0xfb,0xcb,0xe0,0x2b,0x8c,0xca,0x50,0x92,0x69, 0x7e,0x26,0x9e,0x5c,0xf4,0x80,0x8c,0x1d,0x1c,0x00,0x91,0x48,0x83,0x91,0xe0,0x9c, 0x95,0xe8,0x46,0x6e,0xdb,0x7e,0x1e,0xaa,0xf9,0x9a,0xe9,0x2f,0xae,0x6d,0x11,0x16}; /* CRT coefficient */ static const int8u inv_q[MBX_RSA4K_DATA_BYTE_LEN / 2] = { 0xbb,0xc0,0x69,0x44,0x4a,0xc2,0xbf,0x33,0x40,0xe0,0x7e,0x1a,0x86,0xf1,0xd6,0xa6, 0xfc,0x71,0x40,0x19,0x83,0xd8,0x9d,0xd0,0xec,0x72,0x16,0xbc,0x8e,0x78,0xc6,0x39, 0x29,0x0b,0xf1,0x24,0x8f,0xfb,0xec,0x51,0xc2,0x98,0xb5,0x99,0x40,0x3d,0x3f,0x2b, 0xbb,0xd8,0x80,0x10,0x87,0x6e,0x26,0x82,0x72,0x36,0x2f,0xf6,0x2a,0x05,0x08,0x5c, 0x48,0xe0,0x08,0x7e,0xce,0xe9,0xdc,0x34,0x15,0xef,0x95,0x34,0xc1,0xb3,0x58,0xbd, 0x5c,0x35,0x0e,0xaf,0x0e,0xbd,0xb9,0x87,0xe2,0xea,0xec,0x12,0xde,0xf4,0xd5,0xd2, 0x2b,0x5e,0x69,0xb8,0x1e,0x8c,0x80,0xc2,0xbc,0x11,0x06,0x5a,0xf0,0xed,0x4f,0x18, 0x19,0x2b,0xcc,0xf4,0x1d,0x03,0x34,0x49,0x6f,0x9a,0x30,0x42,0x05,0xb2,0x48,0xe8, 0xca,0xa3,0x6e,0xbd,0x95,0x51,0x60,0xc3,0xf5,0x3f,0x58,0xa5,0xcc,0x6a,0xe0,0xaa, 0x47,0x9e,0xfd,0x61,0x86,0x06,0x54,0x00,0x63,0xa6,0x69,0x57,0x94,0xef,0x9a,0xaa, 0x7a,0x85,0x6f,0x71,0x61,0x7a,0x2e,0xd6,0x0d,0x12,0xba,0x5f,0xb9,0x18,0xce,0x6b, 0x79,0x4c,0x52,0x9e,0x6a,0x71,0xf8,0xb0,0x86,0xea,0xed,0x16,0xc1,0xe3,0x47,0x0e, 0x3b,0x67,0x13,0xfa,0xdc,0xe2,0xb8,0xbb,0xd1,0x1a,0x55,0xf1,0xde,0xad,0xb5,0x1c, 0xa6,0x61,0x03,0xac,0x49,0xb7,0x3d,0xd4,0x99,0x23,0x48,0x2d,0xe2,0xc5,0x64,0x75, 0x7f,0x66,0x04,0xf5,0xe5,0x91,0xfe,0x14,0x85,0x12,0x8a,0x49,0x2b,0x69,0xc6,0xb2, 0x0e,0xac,0xa4,0x94,0x2c,0x10,0xc1,0xfc,0x08,0x98,0xa7,0x56,0x0c,0x27,0xf0,0x66}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa4k_private_crt_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA4K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA4K_private_crt_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const int64u *pa_p[MBX_LANES]= { (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p, (int64u *)p}; const int64u *pa_q[MBX_LANES]= { (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q, (int64u *)q}; // p's, q's CRT private exponent const int64u *pa_dp[MBX_LANES]= { (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp, (int64u *)dp}; const int64u *pa_dq[MBX_LANES]= { (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq, (int64u *)dq}; // CRT coefficient const int64u *pa_inv_q[MBX_LANES]= { (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q, (int64u *)inv_q}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_crt_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA4K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA4K_DATA_BYTE_LEN, plaintext, MBX_RSA4K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2, BN_PTR3, BN_PTR4, BN_PTR5) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); \ BN_free(BN_PTR3); \ BN_free(BN_PTR4); \ BN_free(BN_PTR5); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa4k_private_crt_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA4K_DATA_BYTE_LEN]; /* ssl parameters */ // p, q primes BIGNUM* BN_p = BN_new(); BIGNUM* BN_q = BN_new(); // p's, q's CRT private exponent BIGNUM* BN_dp = BN_new(); BIGNUM* BN_dq = BN_new(); // CRT coefficient BIGNUM* BN_inv_q = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_p || NULL == BN_q || NULL == BN_dp || NULL == BN_dq || NULL == BN_inv_q) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(p, MBX_RSA4K_DATA_BYTE_LEN / 2, BN_p); BN_lebin2bn(q, MBX_RSA4K_DATA_BYTE_LEN / 2, BN_q); BN_lebin2bn(dp, MBX_RSA4K_DATA_BYTE_LEN / 2, BN_dp); BN_lebin2bn(dq, MBX_RSA4K_DATA_BYTE_LEN / 2, BN_dq); BN_lebin2bn(inv_q, MBX_RSA4K_DATA_BYTE_LEN / 2, BN_inv_q); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // p, q primes const BIGNUM *pa_p[MBX_LANES] = { (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p, (const BIGNUM *)BN_p}; const BIGNUM *pa_q[MBX_LANES] = { (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q, (const BIGNUM *)BN_q}; // p's, q's CRT private exponent const BIGNUM *pa_dp[MBX_LANES] = { (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp, (const BIGNUM *)BN_dp}; const BIGNUM *pa_dq[MBX_LANES] = { (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq, (const BIGNUM *)BN_dq}; // CRT coefficient const BIGNUM *pa_inv_q[MBX_LANES] = { (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q, (const BIGNUM *)BN_inv_q}; /* test function */ sts = mbx_rsa_private_crt_ssl_mb8(pa_ciphertext, pa_plaintext, pa_p, pa_q, pa_dp, pa_dq, pa_inv_q, MBX_RSA4K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA4K_DATA_BYTE_LEN, plaintext, MBX_RSA4K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_p, BN_q, BN_dp, BN_dq, BN_inv_q) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa4k_private_mb8.c000066400000000000000000000402411470420105600342440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA4K_DATA_BYTE_LEN] = { 0xf9,0x24,0xbd,0x7d,0xa8,0xde,0xc9,0x05,0xf4,0x96,0xdb,0x36,0x4b,0xfa,0x44,0x7d, 0xfd,0x5d,0xa7,0x99,0x80,0xe3,0xbd,0x99,0x64,0xd4,0x01,0x54,0x3d,0xb8,0x1f,0xe6, 0x57,0x75,0x8e,0xcc,0x0c,0x15,0x4f,0xce,0x4f,0x78,0x93,0xf2,0xe6,0x64,0x0e,0x87, 0x6e,0x50,0xec,0xf6,0x99,0x57,0x14,0x7d,0x47,0xca,0xed,0x63,0x86,0x74,0x1f,0xdf, 0xad,0x2e,0xbc,0x3f,0xe2,0x97,0xe5,0x3f,0x12,0xd2,0x19,0x01,0x58,0x22,0xa9,0x14, 0xd1,0x51,0xff,0x74,0x12,0x8c,0x7d,0x60,0xb1,0xc2,0xc4,0x4a,0xcc,0x9c,0x87,0x17, 0xab,0x5e,0xc9,0x2e,0x71,0x7e,0x77,0xd8,0x56,0xdf,0x2f,0x22,0x5a,0x0d,0xf2,0xe5, 0xe7,0x51,0xaa,0x89,0xf4,0xd3,0xfe,0x46,0x26,0xfe,0x90,0xf4,0x07,0x0a,0x14,0xc6, 0x53,0x9d,0x94,0x97,0xa5,0x82,0x1d,0x8e,0xb4,0x0d,0x97,0xd4,0x3c,0x87,0x8b,0x58, 0x78,0x42,0x3d,0x14,0xb6,0x7e,0x30,0x95,0xa8,0x63,0x5c,0x9a,0x49,0x4e,0xda,0x4a, 0x49,0xae,0x5c,0x1c,0xd7,0x10,0x9b,0x37,0xf2,0x3c,0x4b,0xf6,0x8c,0x10,0xa0,0xd6, 0x08,0xa8,0x98,0xb6,0x7c,0xd5,0x0f,0xce,0xbb,0x24,0x1e,0x22,0xeb,0x3a,0xe8,0xf0, 0x3f,0xd4,0xbc,0xe1,0x4e,0x74,0x35,0xf2,0x3a,0x6d,0x79,0x35,0xb5,0x99,0xdd,0x22, 0xb3,0xb9,0x4d,0xee,0xd5,0x10,0x0d,0x69,0x99,0xfb,0xee,0x78,0x8c,0x48,0xfe,0x1f, 0x4e,0x5a,0x3a,0xd0,0xbe,0x69,0xda,0xdd,0xa0,0x61,0xbd,0x4e,0x38,0x3b,0xa5,0x29, 0x39,0x56,0xd4,0x36,0x1d,0x0c,0x8d,0x11,0xb0,0xc1,0xa9,0x3c,0xb6,0x17,0xc9,0x84, 0x15,0x43,0x9b,0x27,0x10,0x7a,0x02,0x49,0x46,0xa5,0x1b,0xe1,0x3d,0x6b,0x2c,0x92, 0x40,0x91,0x03,0xe8,0xa1,0x4f,0xd2,0x05,0x0c,0x55,0x55,0x24,0x94,0xd7,0x3e,0xbc, 0x5b,0x26,0xb7,0x38,0x99,0xbd,0x9e,0x79,0x85,0x82,0x5a,0xad,0xc8,0x5b,0xbd,0x1a, 0xeb,0xe2,0x57,0x0c,0xe9,0x4f,0x94,0x7c,0x8b,0x4a,0x26,0xab,0xe1,0x4b,0x56,0x60, 0x67,0x25,0xe4,0x9f,0xf6,0x08,0x64,0x2c,0x28,0x99,0xcb,0x58,0x17,0xab,0x51,0xfc, 0x35,0x7a,0x79,0xe0,0xda,0x5d,0xbe,0x8f,0x8c,0x9c,0x2a,0x72,0x31,0x6e,0x34,0xad, 0x5c,0x49,0xf9,0x64,0xb9,0x96,0xe6,0xf7,0xd8,0xc7,0x8a,0x44,0x1d,0xd3,0x4a,0x5a, 0x6f,0xf1,0x28,0x97,0x4b,0xd4,0x8a,0x50,0x96,0x13,0xdf,0x95,0xfc,0x14,0x3b,0x78, 0xa9,0x9f,0xe3,0x4f,0xdb,0x5b,0x58,0x71,0xe7,0x30,0x58,0x6d,0x64,0x28,0xa5,0x63, 0x22,0x57,0x29,0x6d,0x9a,0x2d,0x46,0x42,0xc9,0x73,0x7d,0x5c,0xc1,0xf1,0x61,0x3c, 0xd7,0xb6,0x64,0x9d,0x33,0xdb,0x1e,0x52,0x48,0x9e,0x26,0x1d,0x5f,0x18,0x14,0x68, 0x82,0xfc,0xe3,0xdc,0x4c,0xf3,0x50,0xdf,0x71,0x5f,0xcc,0x27,0xcf,0x44,0x18,0x5e, 0xaf,0x83,0x7c,0x6b,0x44,0xe4,0xd6,0x93,0x17,0xea,0x6d,0x8c,0x10,0x04,0x89,0x7f, 0xad,0xa8,0xf3,0xfa,0x3a,0x00,0x4a,0x62,0xb7,0x2e,0x0b,0x79,0x51,0x02,0xd3,0x2a, 0x8d,0x84,0x59,0xe2,0x60,0x2b,0xf1,0xb7,0x5d,0xcc,0x1e,0xab,0x92,0xd3,0x74,0xd8, 0x66,0xe5,0x82,0xa5,0xce,0x7b,0x5f,0xa5,0xa4,0x3b,0x71,0xa8,0x85,0x47,0x78,0xb2}; /* private exponent */ static const int8u d[MBX_RSA4K_DATA_BYTE_LEN] = { 0xd1,0x88,0xca,0x34,0x3f,0xc1,0xe5,0xc9,0x5f,0x65,0x77,0x7f,0xb0,0x23,0xd2,0x75, 0x41,0xe3,0x65,0xa5,0xec,0x33,0xf3,0x4f,0xee,0xb2,0x46,0x34,0xac,0x07,0x67,0x42, 0xe0,0xed,0xf3,0xda,0xdb,0x4d,0x63,0xd5,0x15,0xcc,0xa9,0xbe,0x29,0xe2,0x5e,0x95, 0x05,0xb0,0xcd,0x06,0x88,0x33,0x18,0x8b,0x0a,0x9b,0xee,0xfe,0x29,0x13,0xab,0x66, 0x17,0x5f,0x03,0x09,0x17,0xda,0xff,0x72,0xcd,0x92,0xbd,0x93,0x78,0xdc,0x17,0x5b, 0x90,0x90,0xab,0x8c,0x7e,0x38,0x67,0x77,0x3f,0x4b,0xf8,0x5f,0xe6,0x07,0x41,0x7e, 0x72,0x55,0xf4,0x30,0x3d,0xac,0x22,0x19,0x1a,0xfa,0xca,0x04,0xb4,0xfb,0xa3,0x83, 0x90,0x68,0xf3,0x6d,0xdd,0xbe,0x59,0x3e,0xfb,0xd4,0x9d,0x6a,0x23,0x93,0x8d,0x24, 0xd6,0xc8,0x3c,0xae,0x47,0x7b,0x49,0x3c,0x63,0x17,0xec,0xa2,0xc4,0xa5,0xa5,0xcf, 0x72,0x08,0x9f,0x20,0xb0,0x0a,0xe6,0xae,0x9e,0x78,0xd9,0x18,0x89,0x2a,0x45,0x33, 0x44,0x6f,0xab,0x91,0xc9,0xa7,0xfd,0xd8,0x17,0x9e,0x44,0x2c,0x5b,0xbc,0xc4,0xb5, 0xbb,0xfe,0x64,0x2c,0xed,0x25,0x60,0x9e,0x00,0x88,0x54,0x31,0xd4,0x48,0xda,0xc2, 0x0d,0x80,0xbe,0x72,0x1b,0x71,0x29,0xaf,0x1c,0x1e,0x2b,0x51,0x32,0x2f,0xf2,0x56, 0x9e,0x4d,0x7a,0x1a,0x4c,0x30,0x45,0xd6,0x6c,0x97,0x14,0x5a,0xb9,0x04,0x2c,0xb8, 0xfa,0x4b,0xdf,0xdb,0xfd,0x0c,0xdf,0x1a,0x48,0x3e,0x6f,0x5a,0x76,0x7f,0x46,0x3f, 0x49,0x83,0x26,0x42,0x89,0x36,0xa5,0x51,0x32,0xcf,0x73,0x31,0x4b,0x85,0x10,0x08, 0x2c,0xbe,0x3b,0xe8,0xf7,0xfe,0x72,0xbc,0x6c,0x8e,0x45,0x6b,0xa5,0x4e,0xc6,0xf8, 0x91,0xea,0x18,0x7f,0x6a,0x70,0xaf,0x94,0x9e,0x6b,0xe5,0x49,0x28,0x0b,0xc1,0xc5, 0x4e,0x5a,0x7f,0x56,0x67,0x2a,0xae,0xeb,0x0f,0x04,0x89,0x19,0xcd,0x84,0x4c,0xdc, 0x64,0x8d,0xfc,0x08,0x13,0x6c,0xf6,0x38,0x75,0xca,0x99,0xbe,0x0f,0xbe,0xa3,0xa5, 0x2e,0x99,0xff,0xd5,0x22,0x65,0x8b,0x39,0xa6,0xf3,0x17,0x26,0x30,0x81,0xa1,0x7d, 0x7b,0x5d,0x56,0x14,0x50,0x2d,0xe6,0x04,0xa6,0x29,0xbd,0x89,0x6e,0xb0,0xb3,0x57, 0x72,0xf6,0x1b,0x78,0xc2,0x3d,0x3a,0x33,0xbd,0x1e,0x5c,0x67,0x5b,0x27,0x6f,0x11, 0x5b,0x5e,0xc3,0x2c,0x6d,0xd5,0x3c,0xf3,0x2b,0xb3,0x83,0xdd,0x73,0xbe,0xc4,0xc2, 0xf1,0xb9,0xb2,0xde,0xb6,0x93,0x73,0x3b,0xd7,0xc5,0xab,0xde,0xf3,0xe0,0x92,0x29, 0xa5,0xac,0x1c,0x42,0x78,0x11,0xf3,0x3b,0xee,0x28,0x94,0xcd,0xf8,0xe2,0x6d,0xf1, 0x9d,0x21,0xc5,0x0d,0x3d,0x72,0xf5,0x6d,0xc2,0xcc,0x76,0x22,0xc4,0x7f,0x7a,0x21, 0xf4,0x91,0xa8,0xf8,0x53,0x50,0x8e,0xbc,0x6e,0x2d,0xe4,0x5f,0x24,0x36,0x9e,0x6c, 0x6d,0xa0,0x72,0x22,0x92,0x67,0x00,0xce,0x6b,0x33,0x2c,0x81,0x34,0x4d,0x9d,0x71, 0x07,0x58,0xae,0x0c,0xcf,0x0e,0xc2,0xe2,0xa7,0xbb,0x32,0x87,0x39,0x7b,0x1e,0xa1, 0x38,0x67,0x6d,0x39,0xd4,0xb6,0xc1,0x0e,0x13,0x5b,0x4c,0x3a,0xce,0x3f,0x0c,0x96, 0x1b,0x21,0x6c,0x21,0xe5,0x42,0x42,0x52,0x2a,0xab,0x7f,0x55,0xf0,0x8b,0x20,0x5e}; /* plaintext */ static const int8u plaintext[MBX_RSA4K_DATA_BYTE_LEN] = { 0x54,0xaa,0x9a,0x6c,0xc8,0x5e,0xea,0xde,0xc2,0xe7,0xcc,0x9a,0x0f,0xe1,0x55,0xe4, 0x3e,0xd8,0x1b,0x11,0x67,0xa5,0x52,0x1b,0x21,0x0e,0x29,0x42,0x9c,0xfd,0x66,0x66, 0x03,0x82,0x80,0x66,0x10,0x6a,0x4a,0x98,0x85,0xf9,0x09,0x91,0x7b,0x8a,0xdb,0xc3, 0x8a,0xf0,0x42,0x96,0x0a,0x9c,0x4e,0xa7,0xa0,0x10,0xe0,0xae,0x6e,0x71,0xe8,0x69, 0x8f,0xb1,0x34,0x4e,0x3e,0xbf,0xde,0xd4,0x08,0x9d,0xeb,0x4a,0x0e,0xf1,0x56,0xec, 0x38,0x54,0x27,0x94,0xbc,0xe0,0x76,0xc7,0xe9,0x22,0xff,0x6f,0xa6,0xd9,0xdb,0x2e, 0x83,0xda,0x62,0xc2,0xfb,0x8b,0x63,0xbe,0xe4,0x19,0x5e,0x17,0x21,0x18,0x7d,0x5f, 0x0d,0x51,0xca,0x03,0x39,0xbf,0x64,0x03,0xb3,0x90,0x08,0x67,0x31,0x1b,0xb4,0x7d, 0xab,0x8f,0x87,0x77,0x1a,0x3d,0x97,0x58,0x24,0xa4,0x1e,0x83,0x2f,0x91,0xe1,0x8d, 0x57,0xb7,0xd8,0xfc,0xfc,0x3c,0xd3,0x84,0xbb,0x15,0xd6,0xc1,0x70,0x6a,0xf3,0x26, 0xe7,0x8b,0x33,0xfc,0x66,0x18,0x2d,0x89,0xed,0xae,0xbc,0x72,0xff,0x83,0xaf,0x33, 0x03,0xf9,0xd8,0xa3,0xf4,0x1e,0xa4,0x2f,0xdc,0x21,0x27,0x0a,0x7c,0x9b,0x7c,0xf4, 0xc5,0xe1,0xa1,0xc3,0x43,0x2f,0xcd,0xb4,0xb2,0xf5,0x5b,0x30,0x5f,0x00,0x59,0x5e, 0x0d,0x9e,0x46,0x32,0x0f,0x0a,0x93,0x5c,0x03,0xb4,0x75,0x24,0x7e,0x74,0x7e,0x10, 0x15,0x76,0x71,0x28,0x77,0x5b,0x13,0x3d,0xd9,0x3f,0xa5,0x06,0x1a,0xe5,0xe5,0x5e, 0x82,0x58,0x6f,0x1d,0xc0,0xe1,0x5b,0xf3,0xe3,0x27,0xa4,0x99,0x74,0x84,0x61,0x1c, 0xd3,0x77,0xff,0x08,0xf3,0xcd,0x84,0x28,0xa7,0x4f,0x95,0x15,0xeb,0xcc,0xa9,0xce, 0xfb,0x77,0x34,0xcf,0xe7,0x82,0x21,0xcc,0xfb,0xda,0xdc,0x10,0xa1,0x41,0xc6,0x43, 0x6d,0xa4,0xa8,0x16,0xe8,0x2f,0x13,0x79,0x5d,0x11,0xf7,0x27,0xba,0x0d,0x71,0xd6, 0xde,0x8d,0x32,0xae,0x5d,0x48,0x38,0x46,0xdf,0x88,0xe6,0xa7,0x1d,0x08,0x01,0xb0, 0xd3,0xc7,0x47,0x5f,0x94,0xde,0x06,0x04,0xf9,0x33,0xff,0x94,0x5c,0xbd,0xfa,0xa5, 0x57,0x7b,0xde,0xc8,0xfb,0x94,0xda,0x78,0x61,0x18,0x35,0x50,0xf2,0xf3,0xf4,0x18, 0x21,0xe0,0xf1,0xf5,0xe6,0x55,0x05,0xe2,0x8f,0xce,0xd4,0x91,0xd0,0x8a,0x80,0xd0, 0xa0,0x74,0x42,0xf0,0x46,0x64,0x57,0x16,0x58,0x02,0xc4,0x78,0xcf,0xfe,0x4d,0xca, 0xf1,0x80,0x9f,0x10,0xd9,0x12,0xe3,0x0e,0xe2,0x36,0xe6,0x55,0xfe,0x9f,0xee,0x2a, 0xa3,0x85,0x47,0xa9,0x12,0xc6,0xb0,0x07,0x25,0xbf,0xd7,0xc3,0xca,0x5b,0xf1,0x2f, 0x67,0xd7,0x97,0x25,0x60,0x9a,0x75,0x90,0xb2,0x5c,0x8a,0x72,0xc5,0xe0,0x6a,0xcc, 0x98,0x1d,0x45,0xa3,0x17,0x22,0xce,0x8f,0x01,0xc4,0x37,0x79,0x90,0x7d,0x6f,0xce, 0x00,0xaa,0x32,0x1d,0x2c,0xc7,0x88,0xfd,0xe8,0xbe,0x10,0x33,0x78,0x4d,0xa2,0xe8, 0x40,0x6c,0xcc,0x42,0xec,0x4b,0xac,0x5e,0x30,0xd9,0x3e,0xfc,0x29,0x87,0x3c,0x49, 0x19,0xb8,0xc7,0x9e,0xe5,0xea,0xeb,0x63,0x16,0xdb,0x3c,0x32,0x03,0xdb,0x13,0x45, 0x3c,0xfa,0xbb,0xaf,0x9f,0x1b,0xa1,0xc0,0xd1,0x19,0x80,0x89,0xca,0xb6,0xc9,0x67}; /* ciphertext */ static const int8u ciphertext[MBX_RSA4K_DATA_BYTE_LEN] = { 0x71,0x49,0x42,0x84,0x78,0xd2,0x44,0x99,0xf0,0xb8,0x64,0x01,0x3a,0x1b,0x0c,0x68, 0xd4,0x4f,0xc2,0x0f,0x73,0xf8,0x64,0xcb,0x0f,0xbf,0x7e,0x5d,0x31,0x62,0x33,0x77, 0x8c,0xe4,0x61,0x4d,0xa1,0x35,0x47,0xb9,0xce,0x9b,0xf6,0x5e,0xd3,0x46,0x87,0x15, 0x03,0xda,0xb4,0xc8,0x7f,0x75,0x22,0x30,0x80,0x97,0xed,0x6f,0x8f,0x5f,0xe9,0x05, 0x95,0x07,0x3f,0xef,0x3a,0x79,0x73,0x75,0xb6,0x77,0xd5,0x6b,0xfc,0xc7,0x27,0x25, 0xb1,0xb5,0xf6,0x43,0x21,0xcf,0x9d,0xf1,0xee,0xb0,0x1b,0x59,0x59,0xca,0xd6,0x16, 0x97,0x38,0x8f,0x5a,0x43,0xc8,0xff,0xd2,0x11,0x3f,0x90,0x34,0xb2,0xcd,0x83,0x33, 0x5a,0xde,0xe6,0x34,0x3b,0x34,0xc5,0x2b,0x3a,0xa0,0x19,0x89,0x13,0x6d,0xd0,0x62, 0x28,0x2f,0x82,0x5e,0xa5,0x87,0x9c,0x3d,0x6e,0x0b,0xc6,0xa9,0xc4,0xf2,0xab,0x25, 0xcf,0x6e,0x50,0xa3,0x14,0x21,0xec,0x4c,0x65,0x42,0x59,0xe7,0x05,0x47,0x70,0x19, 0x00,0x16,0x0d,0xac,0x49,0x33,0x38,0x17,0xf0,0x11,0x88,0x6b,0xe6,0x0a,0xfa,0xd7, 0x28,0x37,0x42,0x65,0xb9,0xfe,0x1e,0x9b,0x37,0x29,0xf4,0xa8,0x65,0xc1,0x16,0x5d, 0x51,0x09,0xe9,0xab,0x0a,0x5b,0x3c,0x43,0x4f,0x14,0xc0,0xfb,0x41,0x6b,0x7d,0x31, 0xbb,0x58,0x28,0x8e,0x2e,0xfb,0x89,0x1c,0x60,0xa1,0x76,0x28,0x14,0x27,0x29,0x92, 0x6e,0xa7,0x96,0x9d,0x61,0x08,0xc6,0x8d,0x3d,0xb2,0x67,0x05,0x99,0x31,0xcd,0x08, 0x83,0xc7,0xfd,0x73,0x8d,0x69,0x9b,0xc9,0x6d,0x88,0x59,0x47,0x2e,0x19,0x4d,0x62, 0xe8,0x14,0x35,0x15,0x75,0x49,0x3e,0x2b,0x83,0x18,0xc4,0x16,0xda,0xd1,0x3d,0x06, 0xaf,0x3b,0x3e,0x25,0x1e,0x1d,0xc3,0xfd,0xc0,0x26,0xf0,0x2a,0xe1,0x42,0xf3,0x24, 0x1e,0x6a,0x63,0x8e,0xb7,0x25,0xe8,0x5c,0x01,0x12,0xda,0xa7,0x52,0xde,0x6a,0x65, 0x7c,0x30,0xd3,0x93,0xa8,0x57,0x40,0x92,0x14,0xe5,0xda,0x4e,0xf0,0xbb,0x4b,0x11, 0x03,0x12,0x29,0xb2,0x8b,0x3b,0x2d,0x7e,0x3d,0xad,0xbc,0x16,0x1b,0x22,0xd8,0x3a, 0x91,0xba,0xef,0x71,0x2e,0x0e,0xda,0xb0,0x8c,0xc7,0xbd,0xc5,0x69,0x10,0x41,0x86, 0x79,0x63,0xb3,0x65,0xa4,0x11,0x81,0x63,0x77,0xdb,0xa6,0xdb,0xfc,0x5a,0x7f,0x55, 0x34,0xec,0x4b,0x79,0x8d,0x2f,0xf2,0x1f,0xfe,0x41,0x46,0xd0,0x70,0xc4,0xfe,0x1c, 0x8d,0x2e,0x32,0x16,0x78,0xab,0x83,0xf2,0x87,0xef,0x6a,0x70,0x62,0xc0,0x07,0x7f, 0x6d,0xe7,0x43,0xc6,0x56,0x0f,0x19,0xc1,0x7a,0x75,0xb6,0xd7,0xbb,0xe0,0x4f,0x14, 0xc8,0x63,0xd2,0xab,0xa5,0xf3,0xdb,0x44,0x3c,0x0b,0x4f,0x9d,0xc9,0x49,0x74,0xaf, 0x6e,0x9d,0x35,0xc9,0xef,0xa6,0x0d,0xb6,0x8a,0xef,0xfa,0xa0,0x80,0xa4,0x90,0xdc, 0xef,0x91,0x4a,0x06,0x7b,0x8b,0xe1,0xd8,0xae,0x40,0xa6,0x42,0x78,0x30,0x58,0x40, 0xbd,0xfe,0x03,0xe9,0x31,0x26,0x11,0x4c,0xa2,0x05,0xb8,0xb5,0xad,0x00,0x94,0x50, 0x8f,0xad,0xd2,0x7b,0x8e,0xd8,0x88,0x51,0x1a,0x40,0x7a,0xc2,0x20,0x84,0x3a,0x97, 0x19,0x14,0x10,0x84,0x20,0xfa,0xd4,0x46,0x91,0xbb,0x72,0xe2,0x8d,0x7c,0xc4,0xa9}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa4k_private_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA4K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA4K_private_Method(); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // private exponent const int64u *pa_d[MBX_LANES]= { (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d, (int64u *)d}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_private_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA4K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output plaintext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA4K_DATA_BYTE_LEN, plaintext, MBX_RSA4K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa4k_private_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output plaintext */ int8u out_plaintext[MBX_LANES][MBX_RSA4K_DATA_BYTE_LEN]; /* ssl private exponent */ BIGNUM* BN_d = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_d || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_d, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(d, MBX_RSA4K_DATA_BYTE_LEN, BN_d); BN_lebin2bn(moduli, MBX_RSA4K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // ciphertext const int8u *pa_ciphertext[MBX_LANES] = { ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext, ciphertext}; // plaintext int8u *pa_plaintext[MBX_LANES] = { out_plaintext[0], out_plaintext[1], out_plaintext[2], out_plaintext[3], out_plaintext[4], out_plaintext[5], out_plaintext[6], out_plaintext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; // private exponent const BIGNUM *pa_d[MBX_LANES] = { (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d, (const BIGNUM *)BN_d}; /* test function */ sts = mbx_rsa_private_ssl_mb8(pa_ciphertext, pa_plaintext, pa_d, pa_moduli, MBX_RSA4K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_plaintext[i], MBX_RSA4K_DATA_BYTE_LEN, plaintext, MBX_RSA4K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_d, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_rsa4k_public_mb8.c000066400000000000000000000326431470420105600340570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef MBX_FIPS_MODE #include #include #include #include /* KAT TEST (generated via internal tests) */ /* moduli */ static const int8u moduli[MBX_RSA4K_DATA_BYTE_LEN] = { 0x6b,0x7c,0x69,0xa3,0x81,0x3e,0x78,0x45,0x97,0xf3,0xe6,0x64,0xf7,0x65,0xc4,0xf2, 0xa4,0x25,0x58,0x5d,0x2e,0xaf,0x09,0xaf,0x7a,0x96,0x04,0xb0,0x6f,0xf2,0xfb,0xc0, 0xf7,0x5d,0x0a,0x1b,0x76,0x3c,0xf2,0xb4,0xa0,0x45,0xce,0xc1,0x6c,0x56,0xb0,0x98, 0x88,0x51,0x27,0x57,0x7e,0xe4,0x6e,0x45,0x73,0x4a,0x2b,0x39,0x6a,0x35,0x05,0xd9, 0xc6,0x15,0xee,0x26,0xac,0xb2,0x3f,0xa6,0xef,0x21,0x91,0x36,0xbd,0x24,0x60,0xa9, 0x55,0xb2,0x6f,0xa8,0x1a,0xca,0x44,0xe8,0xaa,0xf7,0x80,0xb2,0x31,0x1a,0x8c,0x52, 0x97,0xe7,0x8c,0xb7,0x28,0xdb,0x6c,0x79,0x99,0x4e,0xfc,0x1c,0xa9,0x7b,0xa9,0x06, 0x03,0xfe,0x0c,0xc5,0x75,0x19,0xc5,0xc5,0xf1,0xd0,0x3f,0xea,0xb8,0x59,0x79,0x26, 0x86,0xc8,0xe9,0xa0,0x99,0xc1,0x24,0x72,0xed,0x82,0xc4,0x7a,0x8a,0x07,0x57,0x40, 0xc3,0xcb,0xb3,0x71,0x34,0x5d,0x39,0x30,0xb2,0xbc,0x5b,0x95,0xc8,0x44,0x07,0xb4, 0x3a,0xfe,0xf4,0xd8,0xb3,0xd5,0xe8,0x2a,0x23,0xc0,0x35,0xc5,0xeb,0x46,0x79,0x29, 0xab,0xe8,0xf8,0x15,0x2c,0xf9,0x36,0xa6,0xa7,0xdb,0x60,0xd1,0x05,0xd2,0x4a,0xbd, 0x48,0xc4,0x6d,0xe3,0x50,0x56,0x7d,0x7e,0xf2,0x57,0xb1,0x0d,0xfd,0x22,0x2d,0x0f, 0x4d,0x39,0xc6,0x23,0x70,0x68,0x01,0xb8,0xd0,0xee,0xfa,0xa3,0x5e,0x7a,0xe5,0x0a, 0x11,0x28,0xb8,0x99,0x59,0xcd,0x0e,0x3f,0x79,0x95,0x98,0xa8,0x60,0x36,0x62,0x34, 0x97,0xd0,0x51,0x5c,0x46,0x65,0x15,0xd6,0x81,0x4d,0xf8,0x70,0xb2,0x49,0xad,0xd1, 0x50,0xd8,0xc9,0x9d,0x22,0xf2,0xe7,0xef,0x6b,0x59,0xc7,0x9d,0xc8,0x54,0x86,0xbc, 0x10,0x6e,0x7d,0x20,0xad,0xf4,0xab,0x9c,0xd8,0x48,0xa4,0x01,0xa4,0x75,0x1f,0xd7, 0x18,0x0d,0x4f,0x87,0x3d,0xc5,0x86,0xbe,0x50,0xd2,0x22,0xc8,0x55,0xc6,0xa3,0xff, 0x1c,0x7f,0x9c,0x4d,0xeb,0x29,0x4e,0xbb,0xd2,0xbd,0x7d,0x3d,0x8b,0xc5,0xef,0x6d, 0x1d,0x2f,0x27,0x46,0x57,0xb7,0xf8,0xe0,0x0c,0x2e,0xe4,0x17,0x4e,0x87,0x83,0xe5, 0x2a,0x0b,0x0c,0x3f,0x6f,0xce,0x16,0x64,0x2b,0xff,0x8a,0xaa,0xdd,0xdc,0x3e,0x12, 0xba,0x2d,0xa1,0x71,0xcc,0x70,0xc2,0x05,0x86,0x3a,0x4a,0x4b,0x7c,0x07,0x96,0xb2, 0x5c,0x2d,0xe7,0x56,0x8e,0xdf,0x5e,0x80,0x6e,0x6f,0xde,0x0c,0x4c,0x5e,0x5a,0x61, 0x5c,0x77,0xef,0x3f,0x8d,0x14,0x89,0xe2,0x4e,0x36,0xa6,0x6a,0x0c,0x3c,0x6b,0x79, 0x4b,0xe0,0x62,0x78,0xcb,0x10,0x18,0x96,0x6c,0xdd,0x6c,0x90,0xc0,0xc5,0xc3,0xbb, 0x67,0x56,0x5c,0xf2,0xec,0x68,0x4e,0xae,0x29,0xbc,0x06,0x08,0x1f,0x0b,0x5a,0x49, 0xb8,0x02,0xf8,0x6e,0x4b,0xa0,0xe1,0xdd,0xc1,0xb0,0xaa,0xd0,0x8c,0x71,0x72,0x69, 0xa3,0xf6,0x3b,0xc8,0x45,0x38,0xef,0xbf,0xc8,0x75,0x3c,0xc8,0xe5,0xd1,0xac,0x9c, 0xda,0xb3,0xe9,0x7c,0xde,0x38,0x96,0xc4,0x1d,0x29,0xf6,0x80,0x4d,0x4b,0x0e,0xf2, 0x46,0x5f,0x2d,0x3d,0x1b,0xc2,0x7a,0xc6,0xa9,0xa5,0xb9,0x90,0x2a,0x68,0x7d,0x66, 0x56,0x47,0x50,0xe3,0x69,0x8f,0xd5,0x7c,0xd3,0x1a,0x5d,0xc8,0x39,0x0c,0x5b,0xee}; /* plaintext */ static const int8u plaintext[MBX_RSA4K_DATA_BYTE_LEN] = { 0x42,0x4d,0xbf,0x13,0xf4,0x9f,0xa6,0x91,0x16,0x82,0xa6,0x65,0x4d,0xfd,0x7b,0x4d, 0x5e,0xde,0x1e,0x58,0xa2,0x20,0x2a,0x4b,0xbb,0xb6,0xd3,0xe5,0x7c,0x4b,0x0c,0x00, 0xa7,0x7a,0x57,0xf5,0xfb,0x6c,0x99,0x77,0xb1,0xd5,0xa3,0x3f,0x5e,0x86,0xad,0xff, 0x29,0xdf,0x9a,0x19,0xcf,0xf6,0xd9,0x33,0xf7,0x83,0x79,0x3f,0xd3,0x50,0x70,0x91, 0xc5,0x98,0xb5,0x10,0x2a,0x6d,0x91,0x3d,0x86,0x24,0x9a,0x07,0x9a,0x4c,0x5e,0x34, 0xb4,0x4e,0x47,0x63,0xf8,0xb6,0x22,0x53,0xee,0x1a,0xbb,0x97,0x63,0xa3,0x52,0x5b, 0x8d,0x87,0xbb,0x30,0x28,0xa1,0xc4,0x83,0x62,0x34,0x57,0xb2,0x88,0x0e,0xc9,0x5e, 0xa4,0x23,0x0d,0x37,0x86,0x1e,0x69,0x2b,0x27,0xbc,0xe2,0x73,0x10,0x20,0x03,0x3a, 0x3d,0xfe,0x35,0x9a,0xf4,0x9f,0x4b,0xa1,0x01,0x4c,0x4c,0x72,0xf7,0x83,0x06,0xf5, 0x27,0x10,0xda,0xf5,0x13,0x4e,0xd2,0x61,0x95,0x94,0x67,0x7d,0x34,0x96,0x43,0x94, 0x98,0x48,0xa3,0xb8,0x5c,0xa8,0xb7,0x55,0x02,0x35,0xc5,0x72,0x52,0xc7,0xf8,0xb4, 0x4d,0xba,0xe4,0xe0,0x41,0xf6,0xec,0x6b,0xae,0xdc,0x09,0xdb,0x27,0x63,0x85,0xba, 0xec,0xf9,0xc6,0x2c,0xbe,0xcd,0x67,0x10,0xb4,0x10,0x8a,0xba,0x9c,0xae,0x3e,0x01, 0x3a,0x44,0x1a,0x64,0x63,0xd0,0xe5,0x4b,0x1c,0xdb,0x0b,0xdf,0xf9,0xad,0xba,0x7b, 0x57,0xbe,0x68,0x70,0x97,0x82,0xe1,0x67,0x71,0xce,0x29,0x29,0x8c,0xde,0x3c,0xb8, 0x45,0x54,0x7b,0x00,0x0b,0x93,0xf1,0x33,0x66,0x23,0x63,0xbb,0x52,0xcf,0x0d,0xe7, 0x3f,0xbf,0x67,0xef,0x4d,0x54,0x8c,0x97,0x83,0x03,0xe0,0xec,0x9c,0xfd,0x0b,0x4e, 0xae,0x37,0xa7,0xe2,0x52,0x44,0x21,0x97,0x3c,0xf4,0x13,0xed,0x39,0xa4,0x2f,0x40, 0x48,0x3e,0x9e,0x15,0xee,0xb6,0x34,0x65,0xc9,0xf0,0xf9,0x7a,0x83,0x29,0x94,0x14, 0xc7,0xe4,0x8e,0x5a,0xbd,0x24,0x11,0xb1,0x59,0xb4,0xd4,0x7e,0xf0,0xc4,0x11,0x16, 0x59,0xb1,0x96,0xcf,0x88,0x72,0x25,0xdc,0x37,0x0a,0x0b,0x0c,0xa0,0xe7,0xc7,0x8a, 0x58,0x29,0x19,0xdb,0xe8,0xba,0x80,0x86,0x80,0x7d,0xc5,0x4f,0x8e,0x65,0x10,0xc2, 0x4b,0x19,0xc5,0x54,0xdf,0x1d,0x17,0x45,0x9f,0x48,0xb0,0xeb,0xf8,0x46,0xee,0x10, 0x26,0xc1,0x3e,0xd6,0x6f,0x1c,0x55,0x76,0x9e,0x3d,0x6a,0xfb,0xee,0xa5,0x2f,0x83, 0x7f,0xa7,0x83,0xee,0xb0,0x35,0x16,0xa6,0x8b,0x6b,0x48,0xa7,0x74,0x9f,0x04,0x16, 0x9c,0xf0,0xb2,0x26,0x1a,0xb9,0x42,0x7e,0x57,0x14,0x8a,0xae,0x07,0xa3,0x61,0xc4, 0x07,0xae,0xd5,0x02,0x7a,0xcd,0x51,0x4b,0xa6,0xd2,0x66,0x98,0x68,0x75,0xc4,0x91, 0xcc,0x1a,0x70,0x45,0x1a,0x24,0x76,0x85,0x9d,0x18,0xea,0x22,0xd3,0xa7,0x2b,0x5f, 0x1e,0xae,0x59,0x40,0xc9,0x18,0x01,0x84,0xe2,0xbc,0xf0,0x7b,0x69,0xd2,0x6e,0xfd, 0xf9,0xc6,0x28,0x0f,0x2d,0x0a,0x65,0x04,0x0b,0xc4,0x1e,0x96,0x2a,0x23,0x4e,0xdc, 0xd4,0x4e,0x01,0x9d,0x70,0xcf,0x7e,0x01,0x8a,0x11,0x96,0x2e,0x46,0x0b,0xa5,0x72, 0x74,0xf0,0x73,0x4d,0x76,0x2a,0x67,0x40,0xa7,0xfe,0xe8,0x68,0x28,0x7c,0xa0,0x41}; /* ciphertext */ static const int8u ciphertext[MBX_RSA4K_DATA_BYTE_LEN] = { 0x61,0x05,0xb5,0xe6,0x95,0xd0,0xc7,0x8e,0x32,0x0a,0x42,0xe5,0xd5,0x26,0x49,0xaa, 0xd4,0x22,0x5b,0x43,0x1d,0x37,0x6d,0xcf,0xac,0x38,0x33,0x61,0xd7,0x84,0xe5,0x33, 0xb7,0x51,0x67,0xce,0x17,0xb3,0x96,0x0a,0x41,0xca,0x6c,0x38,0x16,0xd7,0xf9,0xe5, 0x29,0xd7,0x42,0x40,0x06,0xdc,0x88,0x84,0x9f,0xff,0x6c,0x6d,0xb2,0x81,0xdc,0xe9, 0x32,0xf0,0xa4,0xf9,0x04,0xe7,0xa3,0x2c,0x18,0x4f,0x72,0x8f,0xd4,0x1e,0x22,0x25, 0xc8,0xee,0xb9,0xd0,0x22,0xeb,0x60,0x84,0x09,0xfe,0xca,0xdb,0x09,0xbe,0x9e,0xf6, 0x46,0xfb,0x67,0x0a,0x4f,0xe1,0xb9,0xec,0xac,0xdb,0xcf,0x72,0x4d,0xe9,0xd3,0x0d, 0x2d,0xe7,0x5a,0x8f,0xa6,0xc3,0x44,0x41,0x38,0x2a,0x0d,0x42,0xa7,0x81,0x98,0xf8, 0x4e,0x3b,0x57,0x0e,0xa7,0xfd,0xf4,0xbd,0xed,0xde,0x44,0x77,0x0d,0x67,0xc6,0xbf, 0x1e,0x94,0x0f,0x55,0xa5,0xb5,0xc8,0x0b,0x09,0x35,0xc5,0xec,0x17,0x8b,0x6d,0x85, 0x45,0x88,0x58,0x85,0x90,0xf2,0xcf,0xff,0x55,0x58,0x18,0x50,0x98,0x50,0xfd,0xf1, 0x5c,0xa3,0x6a,0x91,0xf1,0x13,0xd2,0x9d,0xee,0x85,0xd8,0x4d,0xf2,0xa8,0x63,0x4e, 0x51,0x66,0xa3,0xbd,0x71,0xce,0x0c,0x46,0x66,0xfd,0xb1,0x50,0x19,0x53,0x13,0x7c, 0x74,0x65,0x14,0x9c,0xbc,0x49,0x08,0x85,0x75,0x73,0x60,0x23,0x37,0xa5,0x9f,0xe8, 0xd7,0xfa,0x73,0x0d,0x3c,0x99,0xcb,0xfc,0x22,0x0e,0x1f,0xb9,0xa6,0xc5,0xa3,0x21, 0x00,0xed,0x33,0xbf,0x1f,0xfa,0x0a,0xe7,0x45,0x0a,0x40,0x90,0x68,0xd6,0x6e,0xbf, 0x12,0xfc,0x23,0x89,0xa8,0xba,0x1c,0x32,0x45,0x41,0x11,0xae,0x4e,0xa2,0x1e,0xeb, 0x12,0xf5,0x08,0x6a,0x6e,0x68,0x71,0x13,0x59,0xbd,0xc4,0xe2,0x1c,0xef,0x4a,0xf0, 0x20,0xc4,0x8d,0x31,0x90,0xea,0x40,0xfc,0xbc,0x6b,0x5f,0xee,0x76,0x82,0x60,0x0a, 0x42,0xb9,0xb2,0x10,0x45,0xba,0x0d,0x99,0x7f,0x62,0x82,0x1e,0xd3,0x70,0x6d,0xb5, 0x22,0x7b,0x62,0x1e,0xc8,0x9c,0x2f,0xf8,0xbf,0x54,0x31,0x54,0xf8,0x1b,0xfe,0xc6, 0x2e,0x9f,0x60,0xf7,0x02,0xd5,0x3d,0x45,0x2f,0x46,0x73,0x12,0x49,0xa6,0xeb,0x2c, 0x29,0x82,0x05,0x96,0x7f,0xc9,0xeb,0xa4,0x4e,0x15,0x43,0x25,0xbf,0xcd,0x95,0xe0, 0x1b,0x27,0x7f,0x13,0xcf,0xd3,0xea,0xab,0x68,0x19,0x51,0x6f,0xeb,0xf1,0xfc,0x83, 0x2f,0x83,0x3f,0xbc,0x86,0xa6,0xec,0xa8,0x55,0x7f,0xd8,0x67,0xd3,0x50,0x06,0xf2, 0xe6,0x4a,0x89,0xfe,0x00,0x21,0x81,0x92,0xfd,0xd7,0x04,0x98,0xef,0xe4,0x89,0xf2, 0x48,0x90,0xa5,0xe3,0xd7,0x2e,0x29,0x12,0x78,0x85,0x53,0x58,0x03,0x60,0x1a,0x1b, 0xc2,0x46,0x44,0xc1,0xe7,0x8b,0x42,0x6a,0x90,0x4b,0x0c,0x5e,0x78,0x4f,0x7f,0x15, 0xda,0x58,0xd5,0x26,0xb6,0x7e,0xd2,0x5c,0xb0,0xd1,0x43,0x1f,0xf5,0x26,0xde,0x89, 0x07,0x48,0x31,0xc3,0x0c,0x73,0xd9,0xdb,0x6b,0x3f,0xf0,0x9c,0x05,0x7e,0x9b,0x07, 0xac,0xbb,0x6a,0xe7,0x99,0xd6,0x95,0xec,0xcc,0xe5,0x25,0x4a,0x35,0x50,0xb6,0xc6, 0x69,0xd8,0x43,0x59,0x3f,0x0c,0xde,0xf7,0xea,0x9c,0xe6,0xb8,0xf5,0x10,0x69,0xd8}; DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa4k_public_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA4K_DATA_BYTE_LEN]; /* key operation */ const mbx_RSA_Method* method = mbx_RSA4K_pub65537_Method(); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const int64u *pa_moduli[MBX_LANES] = { (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli, (int64u *)moduli}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_rsa_public_mb8(pa_plaintext, pa_ciphertext, pa_moduli, MBX_RSA4K_DATA_BIT_LEN, method, NULL); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output ciphertext to known answer int output_status; for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA4K_DATA_BYTE_LEN, ciphertext, MBX_RSA4K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #ifndef BN_OPENSSL_DISABLE /* exponent (for ssl function only) */ static const int8u exponent[MBX_RSA_PUB_EXP_BYTE_LEN] = {0x01,0x00,0x01}; // memory free macro #define MEM_FREE(BN_PTR1, BN_PTR2) { \ BN_free(BN_PTR1); \ BN_free(BN_PTR2); } DLL_PUBLIC fips_test_status fips_selftest_mbx_rsa4k_public_ssl_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output ciphertext */ int8u out_ciphertext[MBX_LANES][MBX_RSA4K_DATA_BYTE_LEN]; /* ssl exponent */ BIGNUM* BN_e = BN_new(); /* ssl moduli */ BIGNUM* BN_moduli = BN_new(); /* check if allocated memory is valid */ if(NULL == BN_e || NULL == BN_moduli) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; MEM_FREE(BN_e, BN_moduli) return test_result; } /* function status and expected status */ mbx_status sts; mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); /* output validity status */ int output_status; /* set ssl parameters */ BN_lebin2bn(exponent, MBX_RSA_PUB_EXP_BYTE_LEN, BN_e); BN_lebin2bn(moduli, MBX_RSA4K_DATA_BYTE_LEN, BN_moduli); /* function input parameters */ // plaintext const int8u *pa_plaintext[MBX_LANES] = { plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext, plaintext}; // ciphertext int8u *pa_ciphertext[MBX_LANES] = { out_ciphertext[0], out_ciphertext[1], out_ciphertext[2], out_ciphertext[3], out_ciphertext[4], out_ciphertext[5], out_ciphertext[6], out_ciphertext[7]}; // moduli const BIGNUM *pa_moduli[MBX_LANES] = { (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli, (const BIGNUM *)BN_moduli}; const BIGNUM *pa_e[MBX_LANES] = { (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e, (const BIGNUM *)BN_e}; /* test function */ sts = mbx_rsa_public_ssl_mb8(pa_plaintext, pa_ciphertext, pa_e, pa_moduli, MBX_RSA4K_DATA_BIT_LEN); if (expected_status_mb8 != sts) { if (sts == MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR)) { test_result = MBX_ALGO_SELFTEST_UNSUPPORTED_ISA_ERR; } else { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // compare output signature to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { output_status = mbx_is_mem_eq(pa_ciphertext[i], MBX_RSA4K_DATA_BYTE_LEN, ciphertext, MBX_RSA4K_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } // memory free MEM_FREE(BN_e, BN_moduli) return test_result; } #endif // BN_OPENSSL_DISABLE #endif // MBX_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/selftest_mbx_x25519_mb8.c000066400000000000000000000074051470420105600323500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif /* Selftests are disabled for now, since x25519 scheme is not FIPS-approved yet */ #if 0 #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from wycheproof test) */ /* public key */ static const int8u pub_key[MBX_X25519_DATA_BYTE_LEN] = {0x50,0x4a,0x36,0x99,0x9f,0x48,0x9c,0xd2, 0xfd,0xbc,0x08,0xba,0xff,0x3d,0x88,0xfa, 0x00,0x56,0x9b,0xa9,0x86,0xcb,0xa2,0x25, 0x48,0xff,0xde,0x80,0xf9,0x80,0x68,0x29}; /* private key */ static const int8u prv_key[MBX_X25519_DATA_BYTE_LEN] = {0xc8,0xa9,0xd5,0xa9,0x10,0x91,0xad,0x85, 0x1c,0x66,0x8b,0x07,0x36,0xc1,0xc9,0xa0, 0x29,0x36,0xc0,0xd3,0xad,0x62,0x67,0x08, 0x58,0x08,0x80,0x47,0xba,0x05,0x74,0x75}; /* shared key */ static const int8u shared_key[MBX_X25519_DATA_BYTE_LEN] = {0x43,0x6a,0x2c,0x04,0x0c,0xf4,0x5f,0xea, 0x9b,0x29,0xa0,0xcb,0x81,0xb1,0xf4,0x14, 0x58,0xf8,0x63,0xd0,0xd6,0x1b,0x45,0x3d, 0x0a,0x98,0x27,0x20,0xd6,0xd6,0x13,0x20}; DLL_PUBLIC fips_test_status fips_selftest_mbx_x25519_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output shared key */ int8u out_shared_key[MBX_LANES][MBX_X25519_DATA_BYTE_LEN]; /* function input parameters */ // public key const int8u *const pa_pub_key[MBX_LANES] = { pub_key, pub_key, pub_key, pub_key, pub_key, pub_key, pub_key, pub_key}; // private key const int8u *const pa_prv_key[MBX_LANES] = { prv_key, prv_key, prv_key, prv_key, prv_key, prv_key, prv_key, prv_key}; // output shared key int8u *pa_shared_key[MBX_LANES] = { out_shared_key[0], out_shared_key[1], out_shared_key[2], out_shared_key[3], out_shared_key[4], out_shared_key[5], out_shared_key[6], out_shared_key[7]}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_x25519_mb8(pa_shared_key, pa_prv_key, pa_pub_key); if (expected_status_mb8 != sts) { test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare computed shared key to known answer int output_status; for (int j = 0; (j < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++j) { output_status = mbx_is_mem_eq(pa_shared_key[j], MBX_X25519_DATA_BYTE_LEN, shared_key, MBX_X25519_DATA_BYTE_LEN); if (!output_status) { // wrong output test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #endif // MBX_FIPS_MODE #endif selftest_mbx_x25519_public_key_mb8.c000066400000000000000000000053661470420105600345030ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/fips_cert/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif /* Selftests are disabled for now, since x25519 scheme is not FIPS-approved yet */ #if 0 #ifdef MBX_FIPS_MODE #include #include #include /* KAT TEST (taken from internal tests) */ /* private key */ static const int8u prv_key[MBX_X25519_DATA_BYTE_LEN] = { 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}; /* public key */ static const int8u pub_key[MBX_X25519_DATA_BYTE_LEN] = { 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}; DLL_PUBLIC fips_test_status fips_selftest_mbx_x25519_public_key_mb8(void) { fips_test_status test_result = MBX_ALGO_SELFTEST_OK; /* output public key */ int8u out_pub_key[MBX_LANES][MBX_X25519_DATA_BYTE_LEN]; /* function input parameters */ // output public key int8u *const pa_pub_key[MBX_LANES] = { out_pub_key[0], out_pub_key[1], out_pub_key[2], out_pub_key[3], out_pub_key[4], out_pub_key[5], out_pub_key[6], out_pub_key[7]}; // private key const int8u *const pa_prv_key[MBX_LANES] = { prv_key, prv_key, prv_key, prv_key, prv_key, prv_key, prv_key, prv_key}; /* test function */ mbx_status expected_status_mb8 = MBX_SET_STS_ALL(MBX_STATUS_OK); mbx_status sts; sts = mbx_x25519_public_key_mb8(pa_pub_key, pa_prv_key); if (sts != expected_status_mb8){ test_result = MBX_ALGO_SELFTEST_BAD_ARGS_ERR; } // compare output to known answer for (int i = 0; (i < MBX_LANES) && (MBX_ALGO_SELFTEST_OK == test_result); ++i) { if(!mbx_is_mem_eq(pub_key, MBX_X25519_DATA_BYTE_LEN, pa_pub_key[i], MBX_X25519_DATA_BYTE_LEN)) { test_result = MBX_ALGO_SELFTEST_KAT_ERR; } } return test_result; } #endif // MBX_FIPS_MODE #endif cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/000077500000000000000000000000001470420105600246035ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_div_104_by_52.c000066400000000000000000000100231470420105600301050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) static ALIGNSPEC const UINT64 __mask52[] = { DUP8_DECL(0x00ffffffffffffffull) }; static ALIGNSPEC const UINT64 __one[] = { DUP8_DECL(0x3ff0000000000000ull) }; static ALIGNSPEC const UINT64 __two52[] = { DUP8_DECL(0x4330000000000000ull) }; // static ALIGNSPEC const UINT64 __zero[] = { DUP8_DECL(0x0000000000000000ull) }; static ALIGNSPEC const UINT64 __one_l[] = { DUP8_DECL(0x0000000000000001ull) }; // each 64-bit SIMD element should be in the [0, 2^52) range // perform division of (Ah[k]*2^52 + Al[k])/B[k], k=0..7 // Return quotients (as well as remainders via pointer) // Note: There is no checking for B==0 VUINT64 __div_104_by_52(VUINT64 Ah, VUINT64 Al, VUINT64 B, VUINT64 *prem) { VUINT64 msk52, Rem, one; VUINT64 sgn_mask, B_corr, Qh, Ql; VDOUBLE db, dah, dal, dbr, d_one; VDOUBLE dqh, dql, two52, dqh2; VMASK_L corr_gt_mask; // limit range of Ah, Al, B inputs to 52 bits (optional?) msk52 = VLOAD_L(__mask52); B = VAND_L(B, msk52); Ah = VAND_L(Ah, msk52); Al = VAND_L(Al, msk52); // convert inputs to double precision // conversion will be exact db = VCVT_L2D(B); dah = VCVT_L2D(Ah); dal = VCVT_L2D(Al); d_one = VLOAD_D(__one); // get reciprocal of B, RZ mode dbr = VDIV_RU_D(d_one, db); // estimate quotient Qh = (dah*dbr)_RZ ~ Ah/B dqh = VMUL_RZ_D(dah, dbr); // truncate dqh to integral dqh = VROUND_RZ_D(dqh); // get remainder term: dah_new -= dqh*dbh // 0 <= dah_new <= B (due to rounding direction and rounding error magnitude in dbr, dqh) dah = VQFMR_D(db, dqh, dah); // estimate quotient Ql = (dal*dbr)_RZ ~ Al/B dql = VMUL_RZ_D(dal, dbr); // truncate dqh to integral dql = VROUND_RZ_D(dql); // get remainder term: dal_new -= dql*dbh // 0 <= dal_new <= B (similar to above) dal = VQFMR_D(db, dql, dal); // convert remainder term back to (signed) 64-bit integer Al = VCVT_D2L(dal); // scale dah by 2^52 two52 = VLOAD_D(__two52); dah = VMUL_D(dah, two52); // estimate quotient Qh2 = ((2^52)*dah)_RU/db dqh2 = VMUL_RZ_D(dah, dbr); // truncate dqh2 to integral dqh2 = VROUND_RZ_D(dqh2); // remainder term: dah_new2 = dah - db*dqh2 // dah_new2 in (-B, 2B) dah = VQFMR_D(db, dqh2, dah); // convert remainder term back to (signed) 64-bit integer Ah = VCVT_D2L(dah); // add and convert low quotients: Qh2+Ql dql = VADD_D(dql, dqh2); Ql = VCVT_D2L(dql); // convert high quotient Qh = VCVT_D2L(dqh); // remainder term in (-B, 3B) Rem = VADD_L(Ah, Al); // Rem < 0? sgn_mask = VSAR_L(Rem, 63); // Rem > B? corr_gt_mask = VCMP_GE_L(Rem, B); B_corr = VAND_L(B, sgn_mask); // apply correction if B<0 Rem = VADD_L(Rem, B_corr); Ql = VADD_L(Ql, sgn_mask); // if Rem> B, apply correction Rem = VMSUB_L(corr_gt_mask, Rem, B); one = VLOAD_L(__one_l); Ql = VMADD_L(corr_gt_mask, Ql, one); // Rem > B? corr_gt_mask = VCMP_GE_L(Rem, B); // if Rem> B, apply correction // this is the final remainder *prem = VMSUB_L(corr_gt_mask, Rem, B); Ql = VMADD_L(corr_gt_mask, Ql, one); // now add the high part of the quotient Qh = VSHL_L(Qh, 52); Ql = VADD_L(Ql, Qh); return Ql; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x10_mb8.c000066400000000000000000000345751470420105600300230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x10_mb8(out, Y, mod, k0) AMS52x10_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x10_mb8(out, Y, mod, k0) AMS5x52x10_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x10_mb8(out, Y, mod, k0) \ AMS52x10_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x10_mb8(out, Y, mod, k0) ifma_amm52x10_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x10_mb8(out, Y, mod, k0) \ ifma_amm52x10_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (512) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 10 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 8 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u *extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for (n = 1; n < (1 << EXP_WIN_SIZE); n++) { __m512i idx_curr = _mm512_set1_epi64(n); __mmask8 k = _mm512_cmpeq_epu64_mask(idx_curr, idx_target); X0 = select64(k, X0, (U64 *)tbl[n][0]); X1 = select64(k, X1, (U64 *)tbl[n][1]); X2 = select64(k, X2, (U64 *)tbl[n][2]); X3 = select64(k, X3, (U64 *)tbl[n][3]); X4 = select64(k, X4, (U64 *)tbl[n][4]); X5 = select64(k, X5, (U64 *)tbl[n][5]); X6 = select64(k, X6, (U64 *)tbl[n][6]); X7 = select64(k, X7, (U64 *)tbl[n][7]); X8 = select64(k, X8, (U64 *)tbl[n][8]); X9 = select64(k, X9, (U64 *)tbl[n][9]); } _mm512_store_si512(out + 0, X0); _mm512_store_si512(out + 1, X1); _mm512_store_si512(out + 2, X2); _mm512_store_si512(out + 3, X3); _mm512_store_si512(out + 4, X4); _mm512_store_si512(out + 5, X5); _mm512_store_si512(out + 6, X6); _mm512_store_si512(out + 7, X7); _mm512_store_si512(out + 8, X8); _mm512_store_si512(out + 9, X9); return (int64u *)out; } void EXP52x10_mb8(int64u out[][8], const int64u base[][8], const int64u exp[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* allocate exponent X */ pint64u_x8 expz = (pint64u_x8)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x8 red_table = (arr_pint64u_x8)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ zero_mb8(red_X, LEN52); /* table[0] = mont(x^0) = mont(1) */ _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x10_mb8((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x10_mb8((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x10_mb8((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x10_mb8((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb8(expz, exp, LEN64); _mm512_store_si512(expz[LEN64], _mm512_setzero_si512()); /* exponentition */ { int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; int delta = rem ? rem : EXP_WIN_SIZE; __m512i table_idx_mask = _mm512_set1_epi64(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; int exp_chunk_no = exp_bit_no / 64; int exp_chunk_shift = exp_bit_no % 64; /* process 1-st exp window - just init result */ __m512i red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); red_table_idx = _mm512_srli_epi64(red_table_idx, exp_chunk_shift); extract_multiplier_mb8(red_Y, red_table, (int64u *)(&red_table_idx)); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x10_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x10_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x10_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x10_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x10_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ { __m512i T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no + 1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64 - exp_chunk_shift)); red_table_idx = _mm512_and_si512(_mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u *)(&red_table_idx)); } /* and multiply */ ifma_amm52x10_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } } /* clear exponents */ zero_mb8(expz, LEN64); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x10_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #define USE_AMS #ifdef USE_AMS #define SQUARE_52x10_mb4(out, Y, mod, k0) AMS52x10_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x10_mb4(out, Y, mod, k0) AMS5x52x10_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x10_mb4(out, Y, mod, k0) \ AMS52x10_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x10_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x10_mb4(out, Y, mod, k0) ifma_amm52x10_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x10_mb4(out, Y, mod, k0) \ ifma_amm52x10_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x10_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (512) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 10 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 8 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x4)[LEN52][4]; // pointer to pre-computed table of base powers static void extract_multiplier_mb4(int64u out[LEN52][4], int64u tbl[][LEN52][4], const __m256i idx_target) { extract_multiplier_mb4_N((__m256i *)out, (const __m256i *)tbl, idx_target, LEN52, EXP_WIN_SIZE); } void EXP52x10_mb4(int64u out[][4], const int64u base[][4], const int64u exp[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* allocate exponent X */ pint64u_x4 expz = (pint64u_x4)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x4 red_table = (arr_pint64u_x4)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); /* table[0] = mont(x^0) = mont(1) */ ifma_amm52x10_mb4((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x10_mb4((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x10_mb4((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x10_mb4((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb4(expz, exp, LEN64); _mm256_store_si256((__m256i *)&expz[LEN64], _mm256_setzero_si256()); /* BEGIN: exponentition */ const int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; const int delta = rem ? rem : EXP_WIN_SIZE; const __m256i table_idx_mask = _mm256_set1_epi64x(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; /* process 1-st exp window - just init result */ __m256i red_table_idx = _mm256_loadu_si256((const __m256i *)&expz[exp_bit_no / 64]); red_table_idx = _mm256_srli_epi64(red_table_idx, exp_bit_no % 64); extract_multiplier_mb4(red_Y, red_table, red_table_idx); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x10_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x10_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x10_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x10_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x10_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ const int exp_chunk_no = exp_bit_no / 64; const int exp_chunk_shift = exp_bit_no % 64; const __m128i shift_right_n = _mm_set1_epi64x(exp_chunk_shift); const __m128i shift_left_n = _mm_set1_epi64x(64 - (exp_chunk_shift)); red_table_idx = _mm256_loadu_si256((const __m256i *)&expz[exp_chunk_no]); red_table_idx = _mm256_srl_epi64(red_table_idx, shift_right_n); const __m256i T1 = _mm256_loadu_si256((const __m256i *)&expz[exp_chunk_no + 1]); const __m256i T0 = _mm256_sll_epi64(T1, shift_left_n); red_table_idx = _mm256_and_si256(_mm256_xor_si256(red_table_idx, T0), table_idx_mask); extract_multiplier_mb4(red_X, red_table, red_table_idx); /* and multiply */ ifma_amm52x10_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb4(expz, LEN64); /* convert result back in regular 2^52 domain */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); ifma_amm52x10_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x20_65537_mb8.c000066400000000000000000000156371470420105600305730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #define BITSIZE_MODULUS (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 20 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x20_mb8(out, Y, mod, k0) AMS52x20_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x20_mb8(out, Y, mod, k0) AMS5x52x20_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x20_mb8(out, Y, mod, k0) \ AMS52x20_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x20_mb8(out, Y, mod, k0) ifma_amm52x20_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x20_mb8(out, Y, mod, k0) \ ifma_amm52x20_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x20_pub65537_mb8(int64u out[][8], const int64u base[][8], // already in ifma fmt const int64u modulus[][8], // already in ifma fmt const int64u toMont[][8], // already in ifma fmt const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* convert base into redundant Montgomery domain */ ifma_amm52x20_mb8((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x20_mb8((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x20_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x20_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x20_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x20_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x20_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x20_mb4(out, Y, mod, k0) AMS52x20_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x20_mb8(out, Y, mod, k0) AMS5x52x20_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x20_mb4(out, Y, mod, k0) \ AMS52x20_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x20_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x20_mb4(out, Y, mod, k0) ifma_amm52x20_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x20_mb4(out, Y, mod, k0) \ ifma_amm52x20_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x20_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x20_pub65537_mb4(int64u out[][4], const int64u base[][4], // already in ifma fmt const int64u modulus[][4], // already in ifma fmt const int64u toMont[][4], // already in ifma fmt const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* convert base into redundant Montgomery domain */ ifma_amm52x20_mb4((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x20_mb4((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x20_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x20_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x20_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x20_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb4(red_X, LEN52); _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); ifma_amm52x20_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x20_mb8.c000066400000000000000000000416311470420105600300130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x20_mb8(out, Y, mod, k0) AMS52x20_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x20_mb8(out, Y, mod, k0) ifma_amm52x20_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (1024) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 20 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 16 // only valid value is 4 // not removed to make code more readable #define EXP_WIN_SIZE (4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u *extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what's needed __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10 = _mm512_load_si512(tbl[0][10]); __m512i X11 = _mm512_load_si512(tbl[0][11]); __m512i X12 = _mm512_load_si512(tbl[0][12]); __m512i X13 = _mm512_load_si512(tbl[0][13]); __m512i X14 = _mm512_load_si512(tbl[0][14]); __m512i X15 = _mm512_load_si512(tbl[0][15]); __m512i X16 = _mm512_load_si512(tbl[0][16]); __m512i X17 = _mm512_load_si512(tbl[0][17]); __m512i X18 = _mm512_load_si512(tbl[0][18]); __m512i X19 = _mm512_load_si512(tbl[0][19]); __m512i idx_target = _mm512_load_si512(idx_mb8); // Find out what we actually need or just keep original for (int n = 1; n < (1 << EXP_WIN_SIZE); n++) { __m512i idx_curr = _mm512_set1_epi64(n); __mmask8 extract_sel_mask = _mm512_cmpeq_epu64_mask(idx_curr, idx_target); X0 = select64(extract_sel_mask, X0, (U64 *)tbl[n][0]); X1 = select64(extract_sel_mask, X1, (U64 *)tbl[n][1]); X2 = select64(extract_sel_mask, X2, (U64 *)tbl[n][2]); X3 = select64(extract_sel_mask, X3, (U64 *)tbl[n][3]); X4 = select64(extract_sel_mask, X4, (U64 *)tbl[n][4]); X5 = select64(extract_sel_mask, X5, (U64 *)tbl[n][5]); X6 = select64(extract_sel_mask, X6, (U64 *)tbl[n][6]); X7 = select64(extract_sel_mask, X7, (U64 *)tbl[n][7]); X8 = select64(extract_sel_mask, X8, (U64 *)tbl[n][8]); X9 = select64(extract_sel_mask, X9, (U64 *)tbl[n][9]); X10 = select64(extract_sel_mask, X10, (U64 *)tbl[n][10]); X11 = select64(extract_sel_mask, X11, (U64 *)tbl[n][11]); X12 = select64(extract_sel_mask, X12, (U64 *)tbl[n][12]); X13 = select64(extract_sel_mask, X13, (U64 *)tbl[n][13]); X14 = select64(extract_sel_mask, X14, (U64 *)tbl[n][14]); X15 = select64(extract_sel_mask, X15, (U64 *)tbl[n][15]); X16 = select64(extract_sel_mask, X16, (U64 *)tbl[n][16]); X17 = select64(extract_sel_mask, X17, (U64 *)tbl[n][17]); X18 = select64(extract_sel_mask, X18, (U64 *)tbl[n][18]); X19 = select64(extract_sel_mask, X19, (U64 *)tbl[n][19]); } _mm512_store_si512(out + 0, X0); _mm512_store_si512(out + 1, X1); _mm512_store_si512(out + 2, X2); _mm512_store_si512(out + 3, X3); _mm512_store_si512(out + 4, X4); _mm512_store_si512(out + 5, X5); _mm512_store_si512(out + 6, X6); _mm512_store_si512(out + 7, X7); _mm512_store_si512(out + 8, X8); _mm512_store_si512(out + 9, X9); _mm512_store_si512(out + 10, X10); _mm512_store_si512(out + 11, X11); _mm512_store_si512(out + 12, X12); _mm512_store_si512(out + 13, X13); _mm512_store_si512(out + 14, X14); _mm512_store_si512(out + 15, X15); _mm512_store_si512(out + 16, X16); _mm512_store_si512(out + 17, X17); _mm512_store_si512(out + 18, X18); _mm512_store_si512(out + 19, X19); return (int64u *)out; } void EXP52x20_mb8(int64u out[][8], const int64u base[][8], const int64u exp[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* allocate expanded exponent*/ pint64u_x8 expz = (pint64u_x8)(red_X + LEN52); /* pre-computed table of base powers red_table[i] = (base^i)*(2^(LEN52*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 redx_table[i] = (base^i)*(2^((LEN52/2)*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 */ arr_pint64u_x8 red_table = (arr_pint64u_x8)(expz + LEN64 + 1); // total of LEN52<= 0; exp_bit_no -= EXP_WIN_SIZE) { __m512i T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no + 1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64 - exp_chunk_shift)); red_table_idx = _mm512_and_si512(_mm512_xor_si512(red_table_idx, T), table_idx_mask); /* 4 squarings stitched with extracting pre-computed multiplier from the table */ AMS4x52x20_diagonal_stitched_with_extract_mb8((int64u *)red_Y, (U64 *)mulb, (U64 *)mulbx, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0, red_table, redx_table, (int64u *)(&red_table_idx)); ifma_ahmm52x20_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)mulb, (int64u *)mulbx, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb8(expz, LEN64); /* convert result back in regular 2^DIGIT_SIZE domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x20_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #include #define USE_AMS #ifdef USE_AMS #define SQUARE_52x20_mb4(out, Y, mod, k0) AMS52x20_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x20_mb4(out, Y, mod, k0) ifma_amm52x20_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (1024) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 20 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 16 // only valid value is 4 // not removed to make code more readable #define EXP_WIN_SIZE (4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x4)[LEN52][4]; // pointer to pre-computed table of base powers static void extract_multiplier_mb4(int64u out[LEN52][4], int64u tbl[][LEN52][4], const __m256i idx_target) { extract_multiplier_mb4_N((__m256i *)out, (const __m256i *)tbl, idx_target, LEN52, EXP_WIN_SIZE); } void EXP52x20_mb4(int64u out[][4], const int64u base[][4], const int64u exp[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* other window sizes are not supported at the moment */ assert(EXP_WIN_SIZE == 4); /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* allocate expanded exponent*/ pint64u_x4 expz = (pint64u_x4)(red_X + LEN52); /* * pre-computed table of base powers * red_table[i] = (base^i)*(2^(LEN52*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 * redx_table[i] = (base^i)*(2^((LEN52/2)*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 */ arr_pint64u_x4 red_table = (arr_pint64u_x4)(expz + LEN64 + 1); // total of LEN52<= 0; exp_bit_no -= EXP_WIN_SIZE) { const int exp_chunk_no = exp_bit_no / 64; const int exp_chunk_shift = exp_bit_no % 64; const __m128i shift_right_n = _mm_set1_epi64x(exp_chunk_shift); const __m128i shift_left_n = _mm_set1_epi64x(64 - (exp_chunk_shift)); red_table_idx0 = ((const __m256i *)expz[exp_chunk_no])[0]; red_table_idx0 = _mm256_srl_epi64(red_table_idx0, shift_right_n); const __m256i T0 = _mm256_sll_epi64(((const __m256i *)expz[exp_chunk_no + 1])[0], shift_left_n); red_table_idx0 = _mm256_and_si256(_mm256_xor_si256(red_table_idx0, T0), table_idx_mask); /* 4 squarings stitched with extracting pre-computed multiplier from the table */ AMS4x52x20_diagonal_stitched_with_extract_mb4( (int64u *)red_Y, (U64 *)mulb, (U64 *)mulbx, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0, red_table, redx_table, red_table_idx0); ifma_ahmm52x20_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)mulb, (int64u *)mulbx, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb4(expz, LEN64); /* convert result back in regular 2^DIGIT_SIZE domain */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); ifma_amm52x20_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x30_mb8.c000066400000000000000000000427341470420105600300210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x30_mb8(out, Y, mod, k0) AMS52x30_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x30_mb8(out, Y, mod, k0) \ ifma_amm52x30_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x30_mb8(out, Y, mod, k0) ifma_amm52x30_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x30_mb8(out, Y, mod, k0) \ ifma_amm52x30_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x30_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (1536) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 30 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 24 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u *extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10 = _mm512_load_si512(tbl[0][10]); __m512i X11 = _mm512_load_si512(tbl[0][11]); __m512i X12 = _mm512_load_si512(tbl[0][12]); __m512i X13 = _mm512_load_si512(tbl[0][13]); __m512i X14 = _mm512_load_si512(tbl[0][14]); __m512i X15 = _mm512_load_si512(tbl[0][15]); __m512i X16 = _mm512_load_si512(tbl[0][16]); __m512i X17 = _mm512_load_si512(tbl[0][17]); __m512i X18 = _mm512_load_si512(tbl[0][18]); __m512i X19 = _mm512_load_si512(tbl[0][19]); __m512i X20 = _mm512_load_si512(tbl[0][20]); __m512i X21 = _mm512_load_si512(tbl[0][21]); __m512i X22 = _mm512_load_si512(tbl[0][22]); __m512i X23 = _mm512_load_si512(tbl[0][23]); __m512i X24 = _mm512_load_si512(tbl[0][24]); __m512i X25 = _mm512_load_si512(tbl[0][25]); __m512i X26 = _mm512_load_si512(tbl[0][26]); __m512i X27 = _mm512_load_si512(tbl[0][27]); __m512i X28 = _mm512_load_si512(tbl[0][28]); __m512i X29 = _mm512_load_si512(tbl[0][29]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for (n = 1; n < (1 << EXP_WIN_SIZE); n++) { __m512i idx_curr = _mm512_set1_epi64(n); __mmask8 k = _mm512_cmpeq_epu64_mask(idx_curr, idx_target); X0 = select64(k, X0, (U64 *)tbl[n][0]); X1 = select64(k, X1, (U64 *)tbl[n][1]); X2 = select64(k, X2, (U64 *)tbl[n][2]); X3 = select64(k, X3, (U64 *)tbl[n][3]); X4 = select64(k, X4, (U64 *)tbl[n][4]); X5 = select64(k, X5, (U64 *)tbl[n][5]); X6 = select64(k, X6, (U64 *)tbl[n][6]); X7 = select64(k, X7, (U64 *)tbl[n][7]); X8 = select64(k, X8, (U64 *)tbl[n][8]); X9 = select64(k, X9, (U64 *)tbl[n][9]); X10 = select64(k, X10, (U64 *)tbl[n][10]); X11 = select64(k, X11, (U64 *)tbl[n][11]); X12 = select64(k, X12, (U64 *)tbl[n][12]); X13 = select64(k, X13, (U64 *)tbl[n][13]); X14 = select64(k, X14, (U64 *)tbl[n][14]); X15 = select64(k, X15, (U64 *)tbl[n][15]); X16 = select64(k, X16, (U64 *)tbl[n][16]); X17 = select64(k, X17, (U64 *)tbl[n][17]); X18 = select64(k, X18, (U64 *)tbl[n][18]); X19 = select64(k, X19, (U64 *)tbl[n][19]); X20 = select64(k, X20, (U64 *)tbl[n][20]); X21 = select64(k, X21, (U64 *)tbl[n][21]); X22 = select64(k, X22, (U64 *)tbl[n][22]); X23 = select64(k, X23, (U64 *)tbl[n][23]); X24 = select64(k, X24, (U64 *)tbl[n][24]); X25 = select64(k, X25, (U64 *)tbl[n][25]); X26 = select64(k, X26, (U64 *)tbl[n][26]); X27 = select64(k, X27, (U64 *)tbl[n][27]); X28 = select64(k, X28, (U64 *)tbl[n][28]); X29 = select64(k, X29, (U64 *)tbl[n][29]); } _mm512_store_si512(out + 0, X0); _mm512_store_si512(out + 1, X1); _mm512_store_si512(out + 2, X2); _mm512_store_si512(out + 3, X3); _mm512_store_si512(out + 4, X4); _mm512_store_si512(out + 5, X5); _mm512_store_si512(out + 6, X6); _mm512_store_si512(out + 7, X7); _mm512_store_si512(out + 8, X8); _mm512_store_si512(out + 9, X9); _mm512_store_si512(out + 10, X10); _mm512_store_si512(out + 11, X11); _mm512_store_si512(out + 12, X12); _mm512_store_si512(out + 13, X13); _mm512_store_si512(out + 14, X14); _mm512_store_si512(out + 15, X15); _mm512_store_si512(out + 16, X16); _mm512_store_si512(out + 17, X17); _mm512_store_si512(out + 18, X18); _mm512_store_si512(out + 19, X19); _mm512_store_si512(out + 20, X20); _mm512_store_si512(out + 21, X21); _mm512_store_si512(out + 22, X22); _mm512_store_si512(out + 23, X23); _mm512_store_si512(out + 24, X24); _mm512_store_si512(out + 25, X25); _mm512_store_si512(out + 26, X26); _mm512_store_si512(out + 27, X27); _mm512_store_si512(out + 28, X28); _mm512_store_si512(out + 29, X29); return (int64u *)out; } void EXP52x30_mb8(int64u out[][8], const int64u base[][8], const int64u exp[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* allocate exponent X */ pint64u_x8 expz = (pint64u_x8)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x8 red_table = (arr_pint64u_x8)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ zero_mb8(red_X, LEN52); /* table[0] = mont(x^0) = mont(1) */ _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x30_mb8((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x30_mb8((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x30_mb8((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x30_mb8((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb8(expz, exp, LEN64); _mm512_store_si512(expz[LEN64], _mm512_setzero_si512()); /* exponentition */ { int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; int delta = rem ? rem : EXP_WIN_SIZE; __m512i table_idx_mask = _mm512_set1_epi64(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; int exp_chunk_no = exp_bit_no / 64; int exp_chunk_shift = exp_bit_no % 64; /* process 1-st exp window - just init result */ __m512i red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); red_table_idx = _mm512_srli_epi64(red_table_idx, exp_chunk_shift); extract_multiplier_mb8(red_Y, red_table, (int64u *)(&red_table_idx)); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x30_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x30_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x30_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x30_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x30_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ { __m512i T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no + 1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64 - exp_chunk_shift)); red_table_idx = _mm512_and_si512(_mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u *)(&red_table_idx)); } /* and multiply */ ifma_amm52x30_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } } /* clear exponents */ zero_mb8(expz, LEN64); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x30_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #include #define USE_AMS #ifdef USE_AMS #define SQUARE_52x30_mb4(out, Y, mod, k0) AMS52x30_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x30_mb4(out, Y, mod, k0) ifma_amm52x30_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (1536) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 30 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 24 // only valid value is 4 // not removed to make code more readable #define EXP_WIN_SIZE (4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x4)[LEN52][4]; // pointer to pre-computed table of base powers static void extract_multiplier_mb4(int64u out[LEN52][4], int64u tbl[][LEN52][4], const __m256i idx_target) { extract_multiplier_mb4_N((__m256i *)out, (const __m256i *)tbl, idx_target, LEN52, EXP_WIN_SIZE); } void EXP52x30_mb4(int64u out[][4], const int64u base[][4], const int64u exp[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* other window sizes are not supported at the moment */ assert(EXP_WIN_SIZE == 4); /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* allocate expanded exponent*/ pint64u_x4 expz = (pint64u_x4)(red_X + LEN52); /* * pre-computed table of base powers * red_table[i] = (base^i)*(2^(LEN52*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 * redx_table[i] = (base^i)*(2^((LEN52/2)*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 */ arr_pint64u_x4 red_table = (arr_pint64u_x4)(expz + LEN64 + 1); // total of LEN52<= 0; exp_bit_no -= EXP_WIN_SIZE) { const int exp_chunk_no = exp_bit_no / 64; const int exp_chunk_shift = exp_bit_no % 64; const __m128i shift_right_n = _mm_set1_epi64x(exp_chunk_shift); const __m128i shift_left_n = _mm_set1_epi64x(64 - (exp_chunk_shift)); red_table_idx0 = ((const __m256i *)expz[exp_chunk_no])[0]; red_table_idx0 = _mm256_srl_epi64(red_table_idx0, shift_right_n); const __m256i T0 = _mm256_sll_epi64(((const __m256i *)expz[exp_chunk_no + 1])[0], shift_left_n); red_table_idx0 = _mm256_and_si256(_mm256_xor_si256(red_table_idx0, T0), table_idx_mask); /* 4 squarings stitched with extracting pre-computed multiplier from the table */ AMS4x52x30_diagonal_stitched_with_extract_mb4( (int64u *)red_Y, (U64 *)mulb, (U64 *)mulbx, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0, red_table, redx_table, red_table_idx0); ifma_ahmm52x30_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)mulb, (int64u *)mulbx, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb4(expz, LEN64); /* convert result back in regular 2^DIGIT_SIZE domain */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); ifma_amm52x30_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x40_65537_mb8.c000066400000000000000000000154041470420105600305650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #define BITSIZE_MODULUS (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 40 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x40_mb8(out, Y, mod, k0) AMS52x40_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x40_mb8(out, Y, mod, k0) AMS5x52x40_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x40_mb8(out, Y, mod, k0) ifma_amm52x40_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ ifma_amm52x40_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x40_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(work_buffer + LEN52); /* convert base into redundant domain */ ifma_amm52x40_mb8((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x40_mb8((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x40_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x40_mb4(out, Y, mod, k0) AMS52x40_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x40_mb4(out, Y, mod, k0) AMS5x52x40_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x40_mb4(out, Y, mod, k0) \ AMS52x40_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x40_mb4(out, Y, mod, k0) ifma_amm52x40_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x40_mb4(out, Y, mod, k0) \ ifma_amm52x40_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x40_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(work_buffer + LEN52); /* convert base into redundant domain */ ifma_amm52x40_mb4((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x40_mb4((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x40_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x40_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x40_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x40_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb4(red_X, LEN52); _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); ifma_amm52x40_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x40_mb8.c000066400000000000000000000447661470420105600300310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x40_mb8(out, Y, mod, k0) AMS52x40_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x40_mb8(out, Y, mod, k0) AMS5x52x40_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x40_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x40_mb8(out, Y, mod, k0) ifma_amm52x40_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x40_mb8(out, Y, mod, k0) \ ifma_amm52x40_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x40_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (2048) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 40 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 32 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u *extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10 = _mm512_load_si512(tbl[0][10]); __m512i X11 = _mm512_load_si512(tbl[0][11]); __m512i X12 = _mm512_load_si512(tbl[0][12]); __m512i X13 = _mm512_load_si512(tbl[0][13]); __m512i X14 = _mm512_load_si512(tbl[0][14]); __m512i X15 = _mm512_load_si512(tbl[0][15]); __m512i X16 = _mm512_load_si512(tbl[0][16]); __m512i X17 = _mm512_load_si512(tbl[0][17]); __m512i X18 = _mm512_load_si512(tbl[0][18]); __m512i X19 = _mm512_load_si512(tbl[0][19]); __m512i X20 = _mm512_load_si512(tbl[0][20]); __m512i X21 = _mm512_load_si512(tbl[0][21]); __m512i X22 = _mm512_load_si512(tbl[0][22]); __m512i X23 = _mm512_load_si512(tbl[0][23]); __m512i X24 = _mm512_load_si512(tbl[0][24]); __m512i X25 = _mm512_load_si512(tbl[0][25]); __m512i X26 = _mm512_load_si512(tbl[0][26]); __m512i X27 = _mm512_load_si512(tbl[0][27]); __m512i X28 = _mm512_load_si512(tbl[0][28]); __m512i X29 = _mm512_load_si512(tbl[0][29]); __m512i X30 = _mm512_load_si512(tbl[0][30]); __m512i X31 = _mm512_load_si512(tbl[0][31]); __m512i X32 = _mm512_load_si512(tbl[0][32]); __m512i X33 = _mm512_load_si512(tbl[0][33]); __m512i X34 = _mm512_load_si512(tbl[0][34]); __m512i X35 = _mm512_load_si512(tbl[0][35]); __m512i X36 = _mm512_load_si512(tbl[0][36]); __m512i X37 = _mm512_load_si512(tbl[0][37]); __m512i X38 = _mm512_load_si512(tbl[0][38]); __m512i X39 = _mm512_load_si512(tbl[0][39]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for (n = 1; n < (1 << EXP_WIN_SIZE); n++) { __m512i idx_curr = _mm512_set1_epi64(n); __mmask8 k = _mm512_cmpeq_epu64_mask(idx_curr, idx_target); X0 = select64(k, X0, (U64 *)tbl[n][0]); X1 = select64(k, X1, (U64 *)tbl[n][1]); X2 = select64(k, X2, (U64 *)tbl[n][2]); X3 = select64(k, X3, (U64 *)tbl[n][3]); X4 = select64(k, X4, (U64 *)tbl[n][4]); X5 = select64(k, X5, (U64 *)tbl[n][5]); X6 = select64(k, X6, (U64 *)tbl[n][6]); X7 = select64(k, X7, (U64 *)tbl[n][7]); X8 = select64(k, X8, (U64 *)tbl[n][8]); X9 = select64(k, X9, (U64 *)tbl[n][9]); X10 = select64(k, X10, (U64 *)tbl[n][10]); X11 = select64(k, X11, (U64 *)tbl[n][11]); X12 = select64(k, X12, (U64 *)tbl[n][12]); X13 = select64(k, X13, (U64 *)tbl[n][13]); X14 = select64(k, X14, (U64 *)tbl[n][14]); X15 = select64(k, X15, (U64 *)tbl[n][15]); X16 = select64(k, X16, (U64 *)tbl[n][16]); X17 = select64(k, X17, (U64 *)tbl[n][17]); X18 = select64(k, X18, (U64 *)tbl[n][18]); X19 = select64(k, X19, (U64 *)tbl[n][19]); X20 = select64(k, X20, (U64 *)tbl[n][20]); X21 = select64(k, X21, (U64 *)tbl[n][21]); X22 = select64(k, X22, (U64 *)tbl[n][22]); X23 = select64(k, X23, (U64 *)tbl[n][23]); X24 = select64(k, X24, (U64 *)tbl[n][24]); X25 = select64(k, X25, (U64 *)tbl[n][25]); X26 = select64(k, X26, (U64 *)tbl[n][26]); X27 = select64(k, X27, (U64 *)tbl[n][27]); X28 = select64(k, X28, (U64 *)tbl[n][28]); X29 = select64(k, X29, (U64 *)tbl[n][29]); X30 = select64(k, X30, (U64 *)tbl[n][30]); X31 = select64(k, X31, (U64 *)tbl[n][31]); X32 = select64(k, X32, (U64 *)tbl[n][32]); X33 = select64(k, X33, (U64 *)tbl[n][33]); X34 = select64(k, X34, (U64 *)tbl[n][34]); X35 = select64(k, X35, (U64 *)tbl[n][35]); X36 = select64(k, X36, (U64 *)tbl[n][36]); X37 = select64(k, X37, (U64 *)tbl[n][37]); X38 = select64(k, X38, (U64 *)tbl[n][38]); X39 = select64(k, X39, (U64 *)tbl[n][39]); } _mm512_store_si512(out + 0, X0); _mm512_store_si512(out + 1, X1); _mm512_store_si512(out + 2, X2); _mm512_store_si512(out + 3, X3); _mm512_store_si512(out + 4, X4); _mm512_store_si512(out + 5, X5); _mm512_store_si512(out + 6, X6); _mm512_store_si512(out + 7, X7); _mm512_store_si512(out + 8, X8); _mm512_store_si512(out + 9, X9); _mm512_store_si512(out + 10, X10); _mm512_store_si512(out + 11, X11); _mm512_store_si512(out + 12, X12); _mm512_store_si512(out + 13, X13); _mm512_store_si512(out + 14, X14); _mm512_store_si512(out + 15, X15); _mm512_store_si512(out + 16, X16); _mm512_store_si512(out + 17, X17); _mm512_store_si512(out + 18, X18); _mm512_store_si512(out + 19, X19); _mm512_store_si512(out + 20, X20); _mm512_store_si512(out + 21, X21); _mm512_store_si512(out + 22, X22); _mm512_store_si512(out + 23, X23); _mm512_store_si512(out + 24, X24); _mm512_store_si512(out + 25, X25); _mm512_store_si512(out + 26, X26); _mm512_store_si512(out + 27, X27); _mm512_store_si512(out + 28, X28); _mm512_store_si512(out + 29, X29); _mm512_store_si512(out + 30, X30); _mm512_store_si512(out + 31, X31); _mm512_store_si512(out + 32, X32); _mm512_store_si512(out + 33, X33); _mm512_store_si512(out + 34, X34); _mm512_store_si512(out + 35, X35); _mm512_store_si512(out + 36, X36); _mm512_store_si512(out + 37, X37); _mm512_store_si512(out + 38, X38); _mm512_store_si512(out + 39, X39); return (int64u *)out; } void EXP52x40_mb8(int64u out[][8], const int64u base[][8], const int64u exp[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* allocate exponent X */ pint64u_x8 expz = (pint64u_x8)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x8 red_table = (arr_pint64u_x8)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ zero_mb8(red_X, LEN52); /* table[0] = mont(x^0) = mont(1) */ _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x40_mb8((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x40_mb8((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x40_mb8((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x40_mb8((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb8(expz, exp, LEN64); _mm512_store_si512(expz[LEN64], _mm512_setzero_si512()); /* exponentition */ { int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; int delta = rem ? rem : EXP_WIN_SIZE; __m512i table_idx_mask = _mm512_set1_epi64(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; int exp_chunk_no = exp_bit_no / 64; int exp_chunk_shift = exp_bit_no % 64; /* process 1-st exp window - just init result */ __m512i red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); red_table_idx = _mm512_srli_epi64(red_table_idx, exp_chunk_shift); extract_multiplier_mb8(red_Y, red_table, (int64u *)(&red_table_idx)); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ { __m512i T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no + 1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64 - exp_chunk_shift)); red_table_idx = _mm512_and_si512(_mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u *)(&red_table_idx)); } /* and multiply */ ifma_amm52x40_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } } /* clear exponents */ zero_mb8(expz, LEN64); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x40_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #include #define USE_AMS #ifdef USE_AMS #define SQUARE_52x40_mb4(out, Y, mod, k0) AMS52x40_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x40_mb4(out, Y, mod, k0) ifma_amm52x40_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (2048) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 40 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 32 // only valid value is 4 // not removed to make code more readable #define EXP_WIN_SIZE (4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x4)[LEN52][4]; // pointer to pre-computed table of base powers static void extract_multiplier_mb4(int64u out[LEN52][4], int64u tbl[][LEN52][4], const __m256i idx_target) { extract_multiplier_mb4_N((__m256i *)out, (const __m256i *)tbl, idx_target, LEN52, EXP_WIN_SIZE); } void EXP52x40_mb4(int64u out[][4], const int64u base[][4], const int64u exp[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* other window sizes are not supported at the moment */ assert(EXP_WIN_SIZE == 4); /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* allocate expanded exponent*/ pint64u_x4 expz = (pint64u_x4)(red_X + LEN52); /* * pre-computed table of base powers * red_table[i] = (base^i)*(2^(LEN52*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 * redx_table[i] = (base^i)*(2^((LEN52/2)*DIGIT_SIZE)) mod modulus, for i=0, 1, ... , (2^EXP_WIN_SIZE)-1 */ arr_pint64u_x4 red_table = (arr_pint64u_x4)(expz + LEN64 + 1); // total of LEN52<= 0; exp_bit_no -= EXP_WIN_SIZE) { const int exp_chunk_no = exp_bit_no / 64; const int exp_chunk_shift = exp_bit_no % 64; const __m128i shift_right_n = _mm_set1_epi64x(exp_chunk_shift); const __m128i shift_left_n = _mm_set1_epi64x(64 - (exp_chunk_shift)); red_table_idx0 = ((const __m256i *)expz[exp_chunk_no])[0]; red_table_idx0 = _mm256_srl_epi64(red_table_idx0, shift_right_n); const __m256i T0 = _mm256_sll_epi64(((const __m256i *)expz[exp_chunk_no + 1])[0], shift_left_n); red_table_idx0 = _mm256_and_si256(_mm256_xor_si256(red_table_idx0, T0), table_idx_mask); /* 4 squarings stitched with extracting pre-computed multiplier from the table */ AMS4x52x40_diagonal_stitched_with_extract_mb4( (int64u *)red_Y, (U64 *)mulb, (U64 *)mulbx, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0, red_table, redx_table, red_table_idx0); ifma_ahmm52x40_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)mulb, (int64u *)mulbx, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb4(expz, LEN64); /* convert result back in regular 2^DIGIT_SIZE domain */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); ifma_amm52x40_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x60_65537_mb8.c000066400000000000000000000147111470420105600305670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #define BITSIZE_MODULUS (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 60 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x60_mb8(out, Y, mod, k0) AMS52x60_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb8(out, Y, mod, k0) \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x60_mb8(out, Y, mod, k0) ifma_amm52x60_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb8(out, Y, mod, k0) \ ifma_amm52x60_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x60_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(work_buffer + LEN52); /* convert base into redundant domain */ ifma_amm52x60_mb8((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x60_mb8((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x60_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x60_mb4(out, Y, mod, k0) AMS52x60_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb4(out, Y, mod, k0) \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x60_mb4(out, Y, mod, k0) ifma_amm52x60_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb4(out, Y, mod, k0) \ ifma_amm52x60_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x60_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(work_buffer + LEN52); /* convert base into redundant domain */ ifma_amm52x60_mb4((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x60_mb4((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb4(red_X, LEN52); _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); ifma_amm52x60_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x60_mb8.c000066400000000000000000000515251470420105600300220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x60_mb8(out, Y, mod, k0) AMS52x60_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb8(out, Y, mod, k0) \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x60_mb8(out, Y, mod, k0) ifma_amm52x60_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb8(out, Y, mod, k0) \ ifma_amm52x60_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (3072) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 60 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 48 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u *extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10 = _mm512_load_si512(tbl[0][10]); __m512i X11 = _mm512_load_si512(tbl[0][11]); __m512i X12 = _mm512_load_si512(tbl[0][12]); __m512i X13 = _mm512_load_si512(tbl[0][13]); __m512i X14 = _mm512_load_si512(tbl[0][14]); __m512i X15 = _mm512_load_si512(tbl[0][15]); __m512i X16 = _mm512_load_si512(tbl[0][16]); __m512i X17 = _mm512_load_si512(tbl[0][17]); __m512i X18 = _mm512_load_si512(tbl[0][18]); __m512i X19 = _mm512_load_si512(tbl[0][19]); __m512i X20 = _mm512_load_si512(tbl[0][20]); __m512i X21 = _mm512_load_si512(tbl[0][21]); __m512i X22 = _mm512_load_si512(tbl[0][22]); __m512i X23 = _mm512_load_si512(tbl[0][23]); __m512i X24 = _mm512_load_si512(tbl[0][24]); __m512i X25 = _mm512_load_si512(tbl[0][25]); __m512i X26 = _mm512_load_si512(tbl[0][26]); __m512i X27 = _mm512_load_si512(tbl[0][27]); __m512i X28 = _mm512_load_si512(tbl[0][28]); __m512i X29 = _mm512_load_si512(tbl[0][29]); __m512i X30 = _mm512_load_si512(tbl[0][30]); __m512i X31 = _mm512_load_si512(tbl[0][31]); __m512i X32 = _mm512_load_si512(tbl[0][32]); __m512i X33 = _mm512_load_si512(tbl[0][33]); __m512i X34 = _mm512_load_si512(tbl[0][34]); __m512i X35 = _mm512_load_si512(tbl[0][35]); __m512i X36 = _mm512_load_si512(tbl[0][36]); __m512i X37 = _mm512_load_si512(tbl[0][37]); __m512i X38 = _mm512_load_si512(tbl[0][38]); __m512i X39 = _mm512_load_si512(tbl[0][39]); __m512i X40 = _mm512_load_si512(tbl[0][40]); __m512i X41 = _mm512_load_si512(tbl[0][41]); __m512i X42 = _mm512_load_si512(tbl[0][42]); __m512i X43 = _mm512_load_si512(tbl[0][43]); __m512i X44 = _mm512_load_si512(tbl[0][44]); __m512i X45 = _mm512_load_si512(tbl[0][45]); __m512i X46 = _mm512_load_si512(tbl[0][46]); __m512i X47 = _mm512_load_si512(tbl[0][47]); __m512i X48 = _mm512_load_si512(tbl[0][48]); __m512i X49 = _mm512_load_si512(tbl[0][49]); __m512i X50 = _mm512_load_si512(tbl[0][50]); __m512i X51 = _mm512_load_si512(tbl[0][51]); __m512i X52 = _mm512_load_si512(tbl[0][52]); __m512i X53 = _mm512_load_si512(tbl[0][53]); __m512i X54 = _mm512_load_si512(tbl[0][54]); __m512i X55 = _mm512_load_si512(tbl[0][55]); __m512i X56 = _mm512_load_si512(tbl[0][56]); __m512i X57 = _mm512_load_si512(tbl[0][57]); __m512i X58 = _mm512_load_si512(tbl[0][58]); __m512i X59 = _mm512_load_si512(tbl[0][59]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for (n = 1; n < (1 << EXP_WIN_SIZE); n++) { __m512i idx_curr = _mm512_set1_epi64(n); __mmask8 k = _mm512_cmpeq_epu64_mask(idx_curr, idx_target); X0 = select64(k, X0, (U64 *)tbl[n][0]); X1 = select64(k, X1, (U64 *)tbl[n][1]); X2 = select64(k, X2, (U64 *)tbl[n][2]); X3 = select64(k, X3, (U64 *)tbl[n][3]); X4 = select64(k, X4, (U64 *)tbl[n][4]); X5 = select64(k, X5, (U64 *)tbl[n][5]); X6 = select64(k, X6, (U64 *)tbl[n][6]); X7 = select64(k, X7, (U64 *)tbl[n][7]); X8 = select64(k, X8, (U64 *)tbl[n][8]); X9 = select64(k, X9, (U64 *)tbl[n][9]); X10 = select64(k, X10, (U64 *)tbl[n][10]); X11 = select64(k, X11, (U64 *)tbl[n][11]); X12 = select64(k, X12, (U64 *)tbl[n][12]); X13 = select64(k, X13, (U64 *)tbl[n][13]); X14 = select64(k, X14, (U64 *)tbl[n][14]); X15 = select64(k, X15, (U64 *)tbl[n][15]); X16 = select64(k, X16, (U64 *)tbl[n][16]); X17 = select64(k, X17, (U64 *)tbl[n][17]); X18 = select64(k, X18, (U64 *)tbl[n][18]); X19 = select64(k, X19, (U64 *)tbl[n][19]); X20 = select64(k, X20, (U64 *)tbl[n][20]); X21 = select64(k, X21, (U64 *)tbl[n][21]); X22 = select64(k, X22, (U64 *)tbl[n][22]); X23 = select64(k, X23, (U64 *)tbl[n][23]); X24 = select64(k, X24, (U64 *)tbl[n][24]); X25 = select64(k, X25, (U64 *)tbl[n][25]); X26 = select64(k, X26, (U64 *)tbl[n][26]); X27 = select64(k, X27, (U64 *)tbl[n][27]); X28 = select64(k, X28, (U64 *)tbl[n][28]); X29 = select64(k, X29, (U64 *)tbl[n][29]); X30 = select64(k, X30, (U64 *)tbl[n][30]); X31 = select64(k, X31, (U64 *)tbl[n][31]); X32 = select64(k, X32, (U64 *)tbl[n][32]); X33 = select64(k, X33, (U64 *)tbl[n][33]); X34 = select64(k, X34, (U64 *)tbl[n][34]); X35 = select64(k, X35, (U64 *)tbl[n][35]); X36 = select64(k, X36, (U64 *)tbl[n][36]); X37 = select64(k, X37, (U64 *)tbl[n][37]); X38 = select64(k, X38, (U64 *)tbl[n][38]); X39 = select64(k, X39, (U64 *)tbl[n][39]); X40 = select64(k, X40, (U64 *)tbl[n][40]); X41 = select64(k, X41, (U64 *)tbl[n][41]); X42 = select64(k, X42, (U64 *)tbl[n][42]); X43 = select64(k, X43, (U64 *)tbl[n][43]); X44 = select64(k, X44, (U64 *)tbl[n][44]); X45 = select64(k, X45, (U64 *)tbl[n][45]); X46 = select64(k, X46, (U64 *)tbl[n][46]); X47 = select64(k, X47, (U64 *)tbl[n][47]); X48 = select64(k, X48, (U64 *)tbl[n][48]); X49 = select64(k, X49, (U64 *)tbl[n][49]); X50 = select64(k, X50, (U64 *)tbl[n][50]); X51 = select64(k, X51, (U64 *)tbl[n][51]); X52 = select64(k, X52, (U64 *)tbl[n][52]); X53 = select64(k, X53, (U64 *)tbl[n][53]); X54 = select64(k, X54, (U64 *)tbl[n][54]); X55 = select64(k, X55, (U64 *)tbl[n][55]); X56 = select64(k, X56, (U64 *)tbl[n][56]); X57 = select64(k, X57, (U64 *)tbl[n][57]); X58 = select64(k, X58, (U64 *)tbl[n][58]); X59 = select64(k, X59, (U64 *)tbl[n][59]); } _mm512_store_si512(out + 0, X0); _mm512_store_si512(out + 1, X1); _mm512_store_si512(out + 2, X2); _mm512_store_si512(out + 3, X3); _mm512_store_si512(out + 4, X4); _mm512_store_si512(out + 5, X5); _mm512_store_si512(out + 6, X6); _mm512_store_si512(out + 7, X7); _mm512_store_si512(out + 8, X8); _mm512_store_si512(out + 9, X9); _mm512_store_si512(out + 10, X10); _mm512_store_si512(out + 11, X11); _mm512_store_si512(out + 12, X12); _mm512_store_si512(out + 13, X13); _mm512_store_si512(out + 14, X14); _mm512_store_si512(out + 15, X15); _mm512_store_si512(out + 16, X16); _mm512_store_si512(out + 17, X17); _mm512_store_si512(out + 18, X18); _mm512_store_si512(out + 19, X19); _mm512_store_si512(out + 20, X20); _mm512_store_si512(out + 21, X21); _mm512_store_si512(out + 22, X22); _mm512_store_si512(out + 23, X23); _mm512_store_si512(out + 24, X24); _mm512_store_si512(out + 25, X25); _mm512_store_si512(out + 26, X26); _mm512_store_si512(out + 27, X27); _mm512_store_si512(out + 28, X28); _mm512_store_si512(out + 29, X29); _mm512_store_si512(out + 30, X30); _mm512_store_si512(out + 31, X31); _mm512_store_si512(out + 32, X32); _mm512_store_si512(out + 33, X33); _mm512_store_si512(out + 34, X34); _mm512_store_si512(out + 35, X35); _mm512_store_si512(out + 36, X36); _mm512_store_si512(out + 37, X37); _mm512_store_si512(out + 38, X38); _mm512_store_si512(out + 39, X39); _mm512_store_si512(out + 40, X40); _mm512_store_si512(out + 41, X41); _mm512_store_si512(out + 42, X42); _mm512_store_si512(out + 43, X43); _mm512_store_si512(out + 44, X44); _mm512_store_si512(out + 45, X45); _mm512_store_si512(out + 46, X46); _mm512_store_si512(out + 47, X47); _mm512_store_si512(out + 48, X48); _mm512_store_si512(out + 49, X49); _mm512_store_si512(out + 50, X50); _mm512_store_si512(out + 51, X51); _mm512_store_si512(out + 52, X52); _mm512_store_si512(out + 53, X53); _mm512_store_si512(out + 54, X54); _mm512_store_si512(out + 55, X55); _mm512_store_si512(out + 56, X56); _mm512_store_si512(out + 57, X57); _mm512_store_si512(out + 58, X58); _mm512_store_si512(out + 59, X59); return (int64u *)out; } void EXP52x60_mb8(int64u out[][8], const int64u base[][8], const int64u exp[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)work_buffer; pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* allocate exponent X */ pint64u_x8 expz = (pint64u_x8)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x8 red_table = (arr_pint64u_x8)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ zero_mb8(red_X, LEN52); /* table[0] = mont(x^0) = mont(1) */ _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x60_mb8((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x60_mb8((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x60_mb8((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x60_mb8((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb8(expz, exp, LEN64); _mm512_store_si512(expz[LEN64], _mm512_setzero_si512()); /* exponentition */ { int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; int delta = rem ? rem : EXP_WIN_SIZE; __m512i table_idx_mask = _mm512_set1_epi64(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; int exp_chunk_no = exp_bit_no / 64; int exp_chunk_shift = exp_bit_no % 64; /* process 1-st exp window - just init result */ __m512i red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); red_table_idx = _mm512_srli_epi64(red_table_idx, exp_chunk_shift); extract_multiplier_mb8(red_Y, red_table, (int64u *)(&red_table_idx)); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ { __m512i T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no + 1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64 - exp_chunk_shift)); red_table_idx = _mm512_and_si512(_mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u *)(&red_table_idx)); } /* and multiply */ ifma_amm52x60_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } } /* clear exponents */ zero_mb8(expz, LEN64); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x60_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #define USE_AMS #ifdef USE_AMS #define SQUARE_52x60_mb4(out, Y, mod, k0) AMS52x60_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x60_mb4(out, Y, mod, k0) AMS5x52x60_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x60_mb4(out, Y, mod, k0) \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x60_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x60_mb4(out, Y, mod, k0) ifma_amm52x60_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x60_mb4(out, Y, mod, k0) \ ifma_amm52x60_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x60_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (3072) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 60 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 48 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x4)[LEN52][4]; // pointer to pre-computed table of base powers static void extract_multiplier_mb4(int64u out[LEN52][4], int64u tbl[][LEN52][4], const __m256i idx_target) { extract_multiplier_mb4_N((__m256i *)out, (const __m256i *)tbl, idx_target, LEN52, EXP_WIN_SIZE); } void EXP52x60_mb4(int64u out[][4], const int64u base[][4], const int64u exp[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* allocate exponent X */ pint64u_x4 expz = (pint64u_x4)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x4 red_table = (arr_pint64u_x4)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); /* table[0] = mont(x^0) = mont(1) */ ifma_amm52x60_mb4((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x60_mb4((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x60_mb4((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x60_mb4((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb4(expz, exp, LEN64); _mm256_store_si256((__m256i *)&expz[LEN64], _mm256_setzero_si256()); /* BEGIN: exponentition */ const int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; const int delta = rem ? rem : EXP_WIN_SIZE; const __m256i table_idx_mask = _mm256_set1_epi64x(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; /* process 1-st exp window - just init result */ __m256i red_table_idx = _mm256_loadu_si256((const __m256i *)&expz[exp_bit_no / 64]); red_table_idx = _mm256_srli_epi64(red_table_idx, exp_bit_no % 64); extract_multiplier_mb4(red_Y, red_table, red_table_idx); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ const int exp_chunk_no = exp_bit_no / 64; const int exp_chunk_shift = exp_bit_no % 64; const __m128i shift_right_n = _mm_set1_epi64x(exp_chunk_shift); const __m128i shift_left_n = _mm_set1_epi64x(64 - (exp_chunk_shift)); red_table_idx = _mm256_loadu_si256((const __m256i *)&expz[exp_chunk_no]); red_table_idx = _mm256_srl_epi64(red_table_idx, shift_right_n); const __m256i T1 = _mm256_loadu_si256((const __m256i *)&expz[exp_chunk_no + 1]); const __m256i T0 = _mm256_sll_epi64(T1, shift_left_n); red_table_idx = _mm256_and_si256(_mm256_xor_si256(red_table_idx, T0), table_idx_mask); extract_multiplier_mb4(red_X, red_table, red_table_idx); /* and multiply */ ifma_amm52x60_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb4(expz, LEN64); /* convert result back in regular 2^52 domain */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); ifma_amm52x60_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x79_65537_mb8.c000066400000000000000000000147771470420105600306150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #define BITSIZE_MODULUS (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 79 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x79_mb8(out, Y, mod, k0) AMS52x79_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb8(out, Y, mod, k0) \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x79_mb8(out, Y, mod, k0) ifma_amm52x79_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb8(out, Y, mod, k0) \ ifma_amm52x79_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x79_pub65537_mb8(int64u out[][8], const int64u base[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)(work_buffer + 1); pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* convert base into redundant domain */ zero_mb8(red_X, LEN52); ifma_amm52x79_mb8((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x79_mb8((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x79_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x79_mb4(out, Y, mod, k0) AMS52x79_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb4(out, Y, mod, k0) \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x79_mb4(out, Y, mod, k0) ifma_amm52x79_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb4(out, Y, mod, k0) \ ifma_amm52x79_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif void EXP52x79_pub65537_mb4(int64u out[][4], const int64u base[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)(work_buffer + 1); pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* convert base into redundant domain */ zero_mb4(red_X, LEN52); ifma_amm52x79_mb4((int64u *)red_X, (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); /* exponentition 65537 = 0x10001 */ SQUARE_52x79_mb4((int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_5x52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); ifma_amm52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); /* convert result back in regular 2^52 domain */ zero_mb4(red_X, LEN52); _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); ifma_amm52x79_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_exp52x79_mb8.c000066400000000000000000000605421470420105600300330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define USE_AMS #ifdef USE_AMS #define SQUARE_52x79_mb8(out, Y, mod, k0) AMS52x79_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb8(out, Y, mod, k0) \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb8((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #else #define SQUARE_52x79_mb8(out, Y, mod, k0) ifma_amm52x79_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb8(out, Y, mod, k0) \ ifma_amm52x79_mb8((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb8((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (4096) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 79 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 64 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x8)[LEN52][8]; // pointer to pre-computed table of base powers static int64u *extract_multiplier_mb8(int64u out[LEN52][8], int64u tbl[][LEN52][8], const int64u idx_mb8[8]) { // Assume first element is what need __m512i X0 = _mm512_load_si512(tbl[0][0]); __m512i X1 = _mm512_load_si512(tbl[0][1]); __m512i X2 = _mm512_load_si512(tbl[0][2]); __m512i X3 = _mm512_load_si512(tbl[0][3]); __m512i X4 = _mm512_load_si512(tbl[0][4]); __m512i X5 = _mm512_load_si512(tbl[0][5]); __m512i X6 = _mm512_load_si512(tbl[0][6]); __m512i X7 = _mm512_load_si512(tbl[0][7]); __m512i X8 = _mm512_load_si512(tbl[0][8]); __m512i X9 = _mm512_load_si512(tbl[0][9]); __m512i X10 = _mm512_load_si512(tbl[0][10]); __m512i X11 = _mm512_load_si512(tbl[0][11]); __m512i X12 = _mm512_load_si512(tbl[0][12]); __m512i X13 = _mm512_load_si512(tbl[0][13]); __m512i X14 = _mm512_load_si512(tbl[0][14]); __m512i X15 = _mm512_load_si512(tbl[0][15]); __m512i X16 = _mm512_load_si512(tbl[0][16]); __m512i X17 = _mm512_load_si512(tbl[0][17]); __m512i X18 = _mm512_load_si512(tbl[0][18]); __m512i X19 = _mm512_load_si512(tbl[0][19]); __m512i X20 = _mm512_load_si512(tbl[0][20]); __m512i X21 = _mm512_load_si512(tbl[0][21]); __m512i X22 = _mm512_load_si512(tbl[0][22]); __m512i X23 = _mm512_load_si512(tbl[0][23]); __m512i X24 = _mm512_load_si512(tbl[0][24]); __m512i X25 = _mm512_load_si512(tbl[0][25]); __m512i X26 = _mm512_load_si512(tbl[0][26]); __m512i X27 = _mm512_load_si512(tbl[0][27]); __m512i X28 = _mm512_load_si512(tbl[0][28]); __m512i X29 = _mm512_load_si512(tbl[0][29]); __m512i X30 = _mm512_load_si512(tbl[0][30]); __m512i X31 = _mm512_load_si512(tbl[0][31]); __m512i X32 = _mm512_load_si512(tbl[0][32]); __m512i X33 = _mm512_load_si512(tbl[0][33]); __m512i X34 = _mm512_load_si512(tbl[0][34]); __m512i X35 = _mm512_load_si512(tbl[0][35]); __m512i X36 = _mm512_load_si512(tbl[0][36]); __m512i X37 = _mm512_load_si512(tbl[0][37]); __m512i X38 = _mm512_load_si512(tbl[0][38]); __m512i X39 = _mm512_load_si512(tbl[0][39]); __m512i X40 = _mm512_load_si512(tbl[0][40]); __m512i X41 = _mm512_load_si512(tbl[0][41]); __m512i X42 = _mm512_load_si512(tbl[0][42]); __m512i X43 = _mm512_load_si512(tbl[0][43]); __m512i X44 = _mm512_load_si512(tbl[0][44]); __m512i X45 = _mm512_load_si512(tbl[0][45]); __m512i X46 = _mm512_load_si512(tbl[0][46]); __m512i X47 = _mm512_load_si512(tbl[0][47]); __m512i X48 = _mm512_load_si512(tbl[0][48]); __m512i X49 = _mm512_load_si512(tbl[0][49]); __m512i X50 = _mm512_load_si512(tbl[0][50]); __m512i X51 = _mm512_load_si512(tbl[0][51]); __m512i X52 = _mm512_load_si512(tbl[0][52]); __m512i X53 = _mm512_load_si512(tbl[0][53]); __m512i X54 = _mm512_load_si512(tbl[0][54]); __m512i X55 = _mm512_load_si512(tbl[0][55]); __m512i X56 = _mm512_load_si512(tbl[0][56]); __m512i X57 = _mm512_load_si512(tbl[0][57]); __m512i X58 = _mm512_load_si512(tbl[0][58]); __m512i X59 = _mm512_load_si512(tbl[0][59]); __m512i X60 = _mm512_load_si512(tbl[0][60]); __m512i X61 = _mm512_load_si512(tbl[0][61]); __m512i X62 = _mm512_load_si512(tbl[0][62]); __m512i X63 = _mm512_load_si512(tbl[0][63]); __m512i X64 = _mm512_load_si512(tbl[0][64]); __m512i X65 = _mm512_load_si512(tbl[0][65]); __m512i X66 = _mm512_load_si512(tbl[0][66]); __m512i X67 = _mm512_load_si512(tbl[0][67]); __m512i X68 = _mm512_load_si512(tbl[0][68]); __m512i X69 = _mm512_load_si512(tbl[0][69]); __m512i X70 = _mm512_load_si512(tbl[0][70]); __m512i X71 = _mm512_load_si512(tbl[0][71]); __m512i X72 = _mm512_load_si512(tbl[0][72]); __m512i X73 = _mm512_load_si512(tbl[0][73]); __m512i X74 = _mm512_load_si512(tbl[0][74]); __m512i X75 = _mm512_load_si512(tbl[0][75]); __m512i X76 = _mm512_load_si512(tbl[0][76]); __m512i X77 = _mm512_load_si512(tbl[0][77]); __m512i X78 = _mm512_load_si512(tbl[0][78]); __m512i idx_target = _mm512_load_si512(idx_mb8); int n; // Find out what we actually need or just keep original for (n = 1; n < (1 << EXP_WIN_SIZE); n++) { __m512i idx_curr = _mm512_set1_epi64(n); __mmask8 k = _mm512_cmpeq_epu64_mask(idx_curr, idx_target); X0 = select64(k, X0, (U64 *)tbl[n][0]); X1 = select64(k, X1, (U64 *)tbl[n][1]); X2 = select64(k, X2, (U64 *)tbl[n][2]); X3 = select64(k, X3, (U64 *)tbl[n][3]); X4 = select64(k, X4, (U64 *)tbl[n][4]); X5 = select64(k, X5, (U64 *)tbl[n][5]); X6 = select64(k, X6, (U64 *)tbl[n][6]); X7 = select64(k, X7, (U64 *)tbl[n][7]); X8 = select64(k, X8, (U64 *)tbl[n][8]); X9 = select64(k, X9, (U64 *)tbl[n][9]); X10 = select64(k, X10, (U64 *)tbl[n][10]); X11 = select64(k, X11, (U64 *)tbl[n][11]); X12 = select64(k, X12, (U64 *)tbl[n][12]); X13 = select64(k, X13, (U64 *)tbl[n][13]); X14 = select64(k, X14, (U64 *)tbl[n][14]); X15 = select64(k, X15, (U64 *)tbl[n][15]); X16 = select64(k, X16, (U64 *)tbl[n][16]); X17 = select64(k, X17, (U64 *)tbl[n][17]); X18 = select64(k, X18, (U64 *)tbl[n][18]); X19 = select64(k, X19, (U64 *)tbl[n][19]); X20 = select64(k, X20, (U64 *)tbl[n][20]); X21 = select64(k, X21, (U64 *)tbl[n][21]); X22 = select64(k, X22, (U64 *)tbl[n][22]); X23 = select64(k, X23, (U64 *)tbl[n][23]); X24 = select64(k, X24, (U64 *)tbl[n][24]); X25 = select64(k, X25, (U64 *)tbl[n][25]); X26 = select64(k, X26, (U64 *)tbl[n][26]); X27 = select64(k, X27, (U64 *)tbl[n][27]); X28 = select64(k, X28, (U64 *)tbl[n][28]); X29 = select64(k, X29, (U64 *)tbl[n][29]); X30 = select64(k, X30, (U64 *)tbl[n][30]); X31 = select64(k, X31, (U64 *)tbl[n][31]); X32 = select64(k, X32, (U64 *)tbl[n][32]); X33 = select64(k, X33, (U64 *)tbl[n][33]); X34 = select64(k, X34, (U64 *)tbl[n][34]); X35 = select64(k, X35, (U64 *)tbl[n][35]); X36 = select64(k, X36, (U64 *)tbl[n][36]); X37 = select64(k, X37, (U64 *)tbl[n][37]); X38 = select64(k, X38, (U64 *)tbl[n][38]); X39 = select64(k, X39, (U64 *)tbl[n][39]); X40 = select64(k, X40, (U64 *)tbl[n][40]); X41 = select64(k, X41, (U64 *)tbl[n][41]); X42 = select64(k, X42, (U64 *)tbl[n][42]); X43 = select64(k, X43, (U64 *)tbl[n][43]); X44 = select64(k, X44, (U64 *)tbl[n][44]); X45 = select64(k, X45, (U64 *)tbl[n][45]); X46 = select64(k, X46, (U64 *)tbl[n][46]); X47 = select64(k, X47, (U64 *)tbl[n][47]); X48 = select64(k, X48, (U64 *)tbl[n][48]); X49 = select64(k, X49, (U64 *)tbl[n][49]); X50 = select64(k, X50, (U64 *)tbl[n][50]); X51 = select64(k, X51, (U64 *)tbl[n][51]); X52 = select64(k, X52, (U64 *)tbl[n][52]); X53 = select64(k, X53, (U64 *)tbl[n][53]); X54 = select64(k, X54, (U64 *)tbl[n][54]); X55 = select64(k, X55, (U64 *)tbl[n][55]); X56 = select64(k, X56, (U64 *)tbl[n][56]); X57 = select64(k, X57, (U64 *)tbl[n][57]); X58 = select64(k, X58, (U64 *)tbl[n][58]); X59 = select64(k, X59, (U64 *)tbl[n][59]); X60 = select64(k, X60, (U64 *)tbl[n][60]); X61 = select64(k, X61, (U64 *)tbl[n][61]); X62 = select64(k, X62, (U64 *)tbl[n][62]); X63 = select64(k, X63, (U64 *)tbl[n][63]); X64 = select64(k, X64, (U64 *)tbl[n][64]); X65 = select64(k, X65, (U64 *)tbl[n][65]); X66 = select64(k, X66, (U64 *)tbl[n][66]); X67 = select64(k, X67, (U64 *)tbl[n][67]); X68 = select64(k, X68, (U64 *)tbl[n][68]); X69 = select64(k, X69, (U64 *)tbl[n][69]); X70 = select64(k, X70, (U64 *)tbl[n][70]); X71 = select64(k, X71, (U64 *)tbl[n][71]); X72 = select64(k, X72, (U64 *)tbl[n][72]); X73 = select64(k, X73, (U64 *)tbl[n][73]); X74 = select64(k, X74, (U64 *)tbl[n][74]); X75 = select64(k, X75, (U64 *)tbl[n][75]); X76 = select64(k, X76, (U64 *)tbl[n][76]); X77 = select64(k, X77, (U64 *)tbl[n][77]); X78 = select64(k, X78, (U64 *)tbl[n][78]); } _mm512_store_si512(out + 0, X0); _mm512_store_si512(out + 1, X1); _mm512_store_si512(out + 2, X2); _mm512_store_si512(out + 3, X3); _mm512_store_si512(out + 4, X4); _mm512_store_si512(out + 5, X5); _mm512_store_si512(out + 6, X6); _mm512_store_si512(out + 7, X7); _mm512_store_si512(out + 8, X8); _mm512_store_si512(out + 9, X9); _mm512_store_si512(out + 10, X10); _mm512_store_si512(out + 11, X11); _mm512_store_si512(out + 12, X12); _mm512_store_si512(out + 13, X13); _mm512_store_si512(out + 14, X14); _mm512_store_si512(out + 15, X15); _mm512_store_si512(out + 16, X16); _mm512_store_si512(out + 17, X17); _mm512_store_si512(out + 18, X18); _mm512_store_si512(out + 19, X19); _mm512_store_si512(out + 20, X20); _mm512_store_si512(out + 21, X21); _mm512_store_si512(out + 22, X22); _mm512_store_si512(out + 23, X23); _mm512_store_si512(out + 24, X24); _mm512_store_si512(out + 25, X25); _mm512_store_si512(out + 26, X26); _mm512_store_si512(out + 27, X27); _mm512_store_si512(out + 28, X28); _mm512_store_si512(out + 29, X29); _mm512_store_si512(out + 30, X30); _mm512_store_si512(out + 31, X31); _mm512_store_si512(out + 32, X32); _mm512_store_si512(out + 33, X33); _mm512_store_si512(out + 34, X34); _mm512_store_si512(out + 35, X35); _mm512_store_si512(out + 36, X36); _mm512_store_si512(out + 37, X37); _mm512_store_si512(out + 38, X38); _mm512_store_si512(out + 39, X39); _mm512_store_si512(out + 40, X40); _mm512_store_si512(out + 41, X41); _mm512_store_si512(out + 42, X42); _mm512_store_si512(out + 43, X43); _mm512_store_si512(out + 44, X44); _mm512_store_si512(out + 45, X45); _mm512_store_si512(out + 46, X46); _mm512_store_si512(out + 47, X47); _mm512_store_si512(out + 48, X48); _mm512_store_si512(out + 49, X49); _mm512_store_si512(out + 50, X50); _mm512_store_si512(out + 51, X51); _mm512_store_si512(out + 52, X52); _mm512_store_si512(out + 53, X53); _mm512_store_si512(out + 54, X54); _mm512_store_si512(out + 55, X55); _mm512_store_si512(out + 56, X56); _mm512_store_si512(out + 57, X57); _mm512_store_si512(out + 58, X58); _mm512_store_si512(out + 59, X59); _mm512_store_si512(out + 60, X60); _mm512_store_si512(out + 61, X61); _mm512_store_si512(out + 62, X62); _mm512_store_si512(out + 63, X63); _mm512_store_si512(out + 64, X64); _mm512_store_si512(out + 65, X65); _mm512_store_si512(out + 66, X66); _mm512_store_si512(out + 67, X67); _mm512_store_si512(out + 68, X68); _mm512_store_si512(out + 69, X69); _mm512_store_si512(out + 70, X70); _mm512_store_si512(out + 71, X71); _mm512_store_si512(out + 72, X72); _mm512_store_si512(out + 73, X73); _mm512_store_si512(out + 74, X74); _mm512_store_si512(out + 75, X75); _mm512_store_si512(out + 76, X76); _mm512_store_si512(out + 77, X77); _mm512_store_si512(out + 78, X78); return (int64u *)out; } void EXP52x79_mb8(int64u out[][8], const int64u base[][8], const int64u exp[][8], const int64u modulus[][8], const int64u toMont[][8], const int64u k0[8], int64u work_buffer[][8]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x8 red_Y = (pint64u_x8)(work_buffer + 1); pint64u_x8 red_X = (pint64u_x8)(red_Y + LEN52); /* allocate exponent X */ pint64u_x8 expz = (pint64u_x8)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x8 red_table = (arr_pint64u_x8)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ zero_mb8(red_X, LEN52); /* table[0] = mont(x^0) = mont(1) */ _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x79_mb8((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x79_mb8((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x79_mb8((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x79_mb8((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb8(expz, exp, LEN64); _mm512_store_si512(expz[LEN64], _mm512_setzero_si512()); /* exponentition */ { int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; int delta = rem ? rem : EXP_WIN_SIZE; __m512i table_idx_mask = _mm512_set1_epi64(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; int exp_chunk_no = exp_bit_no / 64; int exp_chunk_shift = exp_bit_no % 64; /* process 1-st exp window - just init result */ __m512i red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); red_table_idx = _mm512_srli_epi64(red_table_idx, exp_chunk_shift); extract_multiplier_mb8(red_Y, red_table, (int64u *)(&red_table_idx)); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ { __m512i T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = _mm512_load_si512(expz[exp_chunk_no]); T = _mm512_load_si512(expz[exp_chunk_no + 1]); red_table_idx = _mm512_srl_epi64(red_table_idx, _mm_set1_epi64x(exp_chunk_shift)); T = _mm512_sll_epi64(T, _mm_set1_epi64x(64 - exp_chunk_shift)); red_table_idx = _mm512_and_si512(_mm512_xor_si512(red_table_idx, T), table_idx_mask); extract_multiplier_mb8(red_X, red_table, (int64u *)(&red_table_idx)); } /* and multiply */ ifma_amm52x79_mb8((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } } /* clear exponents */ zero_mb8(expz, LEN64); /* convert result back in regular 2^52 domain */ zero_mb8(red_X, LEN52); _mm512_store_si512(red_X, _mm512_set1_epi64(1)); ifma_amm52x79_mb8((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include #define USE_AMS #ifdef USE_AMS #define SQUARE_52x79_mb4(out, Y, mod, k0) AMS52x79_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #ifdef USE_AMS_5x #define SQUARE_5x52x79_mb4(out, Y, mod, k0) AMS5x52x79_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); #else #define SQUARE_5x52x79_mb4(out, Y, mod, k0) \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ AMS52x79_diagonal_mb4((int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #else #define SQUARE_52x79_mb4(out, Y, mod, k0) ifma_amm52x79_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); #define SQUARE_5x52x79_mb4(out, Y, mod, k0) \ ifma_amm52x79_mb4((int64u *)out, (int64u *)Y, (int64u *)Y, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); \ ifma_amm52x79_mb4((int64u *)out, (int64u *)out, (int64u *)out, (int64u *)mod, (int64u *)k0); #endif #define BITSIZE_MODULUS (4096) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, DIGIT_SIZE)) // 79 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS, 64)) // 64 #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) typedef int64u (*arr_pint64u_x4)[LEN52][4]; // pointer to pre-computed table of base powers static void extract_multiplier_mb4(int64u out[LEN52][4], int64u tbl[][LEN52][4], const __m256i idx_target) { extract_multiplier_mb4_N((__m256i *)out, (const __m256i *)tbl, idx_target, LEN52, EXP_WIN_SIZE); } void EXP52x79_mb4(int64u out[][4], const int64u base[][4], const int64u exp[][4], const int64u modulus[][4], const int64u toMont[][4], const int64u k0[4], int64u work_buffer[][4]) { /* allocate red(undant) result Y and multiplier X */ pint64u_x4 red_Y = (pint64u_x4)work_buffer; pint64u_x4 red_X = (pint64u_x4)(red_Y + LEN52); /* allocate exponent X */ pint64u_x4 expz = (pint64u_x4)(red_X + LEN52); /* pre-computed table of base powers */ arr_pint64u_x4 red_table = (arr_pint64u_x4)(expz + LEN64 + 1); int idx; /* // compute table of powers base^i, i=0, ..., (2^EXP_WIN_SIZE) -1 */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); /* table[0] = mont(x^0) = mont(1) */ ifma_amm52x79_mb4((int64u *)red_table[0], (int64u *)red_X, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); ifma_amm52x79_mb4((int64u *)red_table[1], (int64u *)base, (int64u *)toMont, (int64u *)modulus, (int64u *)k0); for (idx = 1; idx < (1 << EXP_WIN_SIZE) / 2; idx++) { SQUARE_52x79_mb4((int64u *)red_table[2 * idx], (int64u *)red_table[idx], (int64u *)modulus, (int64u *)k0); ifma_amm52x79_mb4((int64u *)red_table[2 * idx + 1], (int64u *)red_table[2 * idx], (int64u *)red_table[1], (int64u *)modulus, (int64u *)k0); } /* copy and expand exponents */ copy_mb4(expz, exp, LEN64); _mm256_store_si256((__m256i *)&expz[LEN64], _mm256_setzero_si256()); /* BEGIN: exponentition */ const int rem = BITSIZE_MODULUS % EXP_WIN_SIZE; const int delta = rem ? rem : EXP_WIN_SIZE; const __m256i table_idx_mask = _mm256_set1_epi64x(EXP_WIN_MASK); int exp_bit_no = BITSIZE_MODULUS - delta; /* process 1-st exp window - just init result */ __m256i red_table_idx = _mm256_loadu_si256((const __m256i *)&expz[exp_bit_no / 64]); red_table_idx = _mm256_srli_epi64(red_table_idx, exp_bit_no % 64); extract_multiplier_mb4(red_Y, red_table, red_table_idx); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ #if EXP_WIN_SIZE == 5 SQUARE_5x52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #else SQUARE_52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); SQUARE_52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)modulus, (int64u *)k0); #endif /* extract pre-computed multiplier from the table */ const int exp_chunk_no = exp_bit_no / 64; const int exp_chunk_shift = exp_bit_no % 64; const __m128i shift_right_n = _mm_set1_epi64x(exp_chunk_shift); const __m128i shift_left_n = _mm_set1_epi64x(64 - (exp_chunk_shift)); red_table_idx = _mm256_loadu_si256((const __m256i *)&expz[exp_chunk_no]); red_table_idx = _mm256_srl_epi64(red_table_idx, shift_right_n); const __m256i T1 = _mm256_loadu_si256((const __m256i *)&expz[exp_chunk_no + 1]); const __m256i T0 = _mm256_sll_epi64(T1, shift_left_n); red_table_idx = _mm256_and_si256(_mm256_xor_si256(red_table_idx, T0), table_idx_mask); extract_multiplier_mb4(red_X, red_table, red_table_idx); /* and multiply */ ifma_amm52x79_mb4((int64u *)red_Y, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } /* clear exponents */ zero_mb4(expz, LEN64); /* convert result back in regular 2^52 domain */ _mm256_store_si256((__m256i *)red_X, _mm256_set1_epi64x(1)); zero_mb4(&red_X[1], LEN52 - 1); ifma_amm52x79_mb4((int64u *)out, (int64u *)red_Y, (int64u *)red_X, (int64u *)modulus, (int64u *)k0); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_method.c000066400000000000000000000613251470420105600272320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 EXP_WIN_SIZE (5) //(4) /* // rsa public key methods */ DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA1K_pub65537_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, EXP52x20_pub65537_mb8, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb4, // NULL, EXP52x20_pub65537_mb4, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA2K_pub65537_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, EXP52x40_pub65537_mb8, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb4, // NULL, EXP52x40_pub65537_mb4, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA3K_pub65537_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, EXP52x60_pub65537_mb8, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb4, // NULL, EXP52x60_pub65537_mb4, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA4K_pub65537_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2 + 1) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, EXP52x79_pub65537_mb8, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) static mbx_RSA_Method m = { RSA_ID(RSA_PUB_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2 + 1) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb4, // NULL, EXP52x79_pub65537_mb4, NULL, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA_pub65537_Method)(int rsaBitsize) { switch (rsaBitsize) { case RSA_1K: return mbx_RSA1K_pub65537_Method(); case RSA_2K: return mbx_RSA2K_pub65537_Method(); case RSA_3K: return mbx_RSA3K_pub65537_Method(); case RSA_4K: return mbx_RSA4K_pub65537_Method(); default: return NULL; } } /* // rsa private key methods */ DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA1K_private_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x20_mb8, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x20_mb4, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA2K_private_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x40_mb8, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x40_mb4, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA3K_private_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x60_mb8, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x60_mb4, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA4K_private_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + MULTIPLE_OF(LEN52, 10) * 8 + (LEN52 * 8) * 2 + 1 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x79_mb8, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV2_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + MULTIPLE_OF(LEN52, 10) * 4 + (LEN52 * 4) * 2 + 1 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x79_mb4, NULL, NULL, NULL, NULL }; return &m; #undef RSA_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA_private_Method)(int rsaBitsize) { switch (rsaBitsize) { case RSA_1K: return mbx_RSA1K_private_Method(); case RSA_2K: return mbx_RSA2K_private_Method(); case RSA_3K: return mbx_RSA3K_private_Method(); case RSA_4K: return mbx_RSA4K_private_Method(); default: return NULL; } } /* // rsa private key methods (crt) */ DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA1K_private_crt_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_1K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + LEN52 * 8 + 2 * LEN52 * 8 + (LEN52 * 8) * 2 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x10_mb8, ifma_amred52x10_mb8, ifma_amm52x10_mb8, ifma_modsub52x10_mb8, ifma_addmul52x10_mb8 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_1K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + LEN52 * 4 + 2 * LEN52 * 4 + (LEN52 * 4) * 2 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x10_mb4, ifma_amred52x10_mb4, ifma_amm52x10_mb4, ifma_modsub52x10_mb4, ifma_addmul52x10_mb4 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA2K_private_crt_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_2K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + LEN52 * 8 + 2 * LEN52 * 8 + (LEN52 * 8) * 2 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x20_mb8, ifma_amred52x20_mb8, ifma_amm52x20_mb8, ifma_modsub52x20_mb8, ifma_addmul52x20_mb8 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_2K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + LEN52 * 4 + 2 * LEN52 * 4 + (LEN52 * 4) * 2 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x20_mb4, ifma_amred52x20_mb4, ifma_amm52x20_mb4, ifma_modsub52x20_mb4, ifma_addmul52x20_mb4 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA3K_private_crt_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_3K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + LEN52 * 8 + 2 * LEN52 * 8 + (LEN52 * 8) * 2 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x30_mb8, ifma_amred52x30_mb8, ifma_amm52x30_mb8, ifma_modsub52x30_mb8, ifma_addmul52x30_mb8 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_3K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + LEN52 * 4 + 2 * LEN52 * 4 + (LEN52 * 4) * 2 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x30_mb4, ifma_amred52x30_mb4, ifma_amm52x30_mb4, ifma_modsub52x30_mb4, ifma_addmul52x30_mb4 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA4K_private_crt_Method)(void) { #if (_MBX >= _MBX_K1) #define RSA_BITLEN (RSA_4K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (8 + LEN52 * 8 + LEN52 * 8 + LEN64 * 8 + LEN52 * 8 + LEN52 * 8 + LEN52 * 8 + 2 * LEN52 * 8 + (LEN52 * 8) * 2 + 1 + (LEN64 + 1) * 8 + (1 << EXP_WIN_SIZE) * LEN52 * 8) * sizeof(int64u), /* buffer */ // ifma_BNU_to_mb8, // NULL, NULL, EXP52x40_mb8, ifma_amred52x40_mb8, ifma_amm52x40_mb8, ifma_modsub52x40_mb8, ifma_addmul52x40_mb8 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define RSA_BITLEN (RSA_4K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) static mbx_RSA_Method m = { RSA_ID(RSA_PRV5_KEY, RSA_BITLEN), RSA_BITLEN, 64 + (4 + LEN52 * 4 + LEN52 * 4 + LEN64 * 4 + LEN52 * 4 + LEN52 * 4 + LEN52 * 4 + 2 * LEN52 * 4 + (LEN52 * 4) * 2 + 1 + (LEN64 + 1) * 4 + (1 << EXP_WIN_SIZE) * LEN52 * 4) * sizeof(int64u), /* buffer */ NULL, EXP52x40_mb4, ifma_amred52x40_mb4, ifma_amm52x40_mb4, ifma_modsub52x40_mb4, ifma_addmul52x40_mb4 }; return &m; #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 #else return NULL; #endif /* #if (_MBX>=_MBX_K1) */ } DLL_PUBLIC const mbx_RSA_Method *OWNAPI(mbx_RSA_private_crt_Method)(int rsaBitsize) { switch (rsaBitsize) { case RSA_1K: return mbx_RSA1K_private_crt_Method(); case RSA_2K: return mbx_RSA2K_private_crt_Method(); case RSA_3K: return mbx_RSA3K_private_crt_Method(); case RSA_4K: return mbx_RSA4K_private_crt_Method(); default: return NULL; } } /* size of scratch buffer */ DLL_PUBLIC int mbx_RSA_Method_BufSize(const mbx_RSA_Method *m) { #if ((_MBX <= _MBX_L9) && !(_MBX_AVX_IFMA_SUPPORTED)) return 0; #else return m ? m->buffSize : 0; #endif } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_other52x_mb8.c000066400000000000000000003442711470420105600302040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 BITSIZE_512 (512) #define BITSIZE_1024 (1024) #define BITSIZE_1536 (1536) #define BITSIZE_2048 (2048) #if (_MBX >= _MBX_K1) __NOINLINE void zero_mb8(int64u (*out)[8], int len) { #if defined(__GNUC__) // Avoid dead code elimination for GNU compilers ASM(""); #endif __m512i T = _mm512_setzero_si512(); int i; for (i = 0; i < len; i++) _mm512_storeu_si512(out[i], T); } void copy_mb8(int64u out[][8], const int64u inp[][8], int len) { int i; for (i = 0; i < len; i++) _mm512_store_si512(out[i], _mm512_load_si512(inp[i])); } /* k0 = - ( m0 ^(-1) mod 2^52 ) */ void ifma_montFactor52_mb8(int64u k0_mb8[8], const int64u m0_mb8[8]) { __m512i m0 = _mm512_loadu_si512(m0_mb8); __m512i y = _mm512_set1_epi64(1); /* 1 */ __m512i x = _mm512_set1_epi64(2); /* 2 */ __m512i nx = _mm512_add_epi64(x, x); __m512i mask = _mm512_sub_epi64(nx, y); /* 2*x-1 */ int n; for (n = 2; n <= DIGIT_SIZE; n++ /*, x=nx , nx=_mm512_add_epi64(nx,nx)*/) { __m512i rL = _mm512_madd52lo_epu64(_mm512_setzero_si512(), m0, y); /* rL = m0*y; */ __mmask8 k = _mm512_cmplt_epu64_mask(x, _mm512_and_si512(rL, mask)); /* if( x < (rL & mask) ) < == > x < ((m0*y) mod (2*x)) */ y = _mm512_mask_add_epi64(y, k, y, x); /* y+=x */ /* mask = 2*x-1 */ x = nx; nx = _mm512_add_epi64(nx, nx); mask = _mm512_sub_epi64(nx, _mm512_set1_epi64(1)); } y = _mm512_sub_epi64(_mm512_setzero_si512(), y); /* return (0-y) */ y = _mm512_and_si512(y, _mm512_set1_epi64(DIGIT_MASK)); _mm512_storeu_si512(k0_mb8, y); } /* r = (a-b) mod m */ void ifma_modsub52x10_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]) { #define BITSIZE (512) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(BITSIZE, 52)) __m512i *pr = (__m512i *)res; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i *pm = (__m512i *)inpM; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MSD_MASK = _mm512_set1_epi64(MSD_MSK); __m512i T[LEN52]; __m512i R, CARRY, BORROW; int n; /* T[] = a[] - b[] */ BORROW = _mm512_setzero_si512(); for (n = 0; n < LEN52; n++) { R = _mm512_sub_epi64(pa[n], pb[n]); R = _mm512_sub_epi64(R, BORROW); BORROW = _mm512_srli_epi64(R, (64 - 1)); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(T + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(T + LEN52 - 1, R); /* masked modulus add: r[] = T[] + BORROW? m[] : 0 */ CARRY = _mm512_setzero_si512(); BORROW = _mm512_sub_epi64(CARRY, BORROW); /* RORROW -> mask */ for (n = 0; n < LEN52; n++) { R = _mm512_and_epi64(BORROW, pm[n]); R = _mm512_add_epi64(R, T[n]); R = _mm512_add_epi64(R, CARRY); CARRY = _mm512_srli_epi64(R, DIGIT_SIZE); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(pr + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(pr + LEN52 - 1, R); #undef BITSIZE #undef LEN52 #undef MSD_MSK } void ifma_modsub52x20_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]) { #define BITSIZE (1024) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(BITSIZE, 52)) __m512i *pr = (__m512i *)res; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i *pm = (__m512i *)inpM; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MSD_MASK = _mm512_set1_epi64(MSD_MSK); __m512i T[LEN52]; __m512i R, CARRY, BORROW; int n; /* T[] = a[] - b[] */ BORROW = _mm512_setzero_si512(); for (n = 0; n < LEN52; n++) { R = _mm512_sub_epi64(pa[n], pb[n]); R = _mm512_sub_epi64(R, BORROW); BORROW = _mm512_srli_epi64(R, (64 - 1)); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(T + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(T + LEN52 - 1, R); /* masked modulus add: r[] = T[] + BORROW? m[] : 0 */ CARRY = _mm512_setzero_si512(); BORROW = _mm512_sub_epi64(CARRY, BORROW); /* RORROW -> mask */ for (n = 0; n < LEN52; n++) { R = _mm512_and_epi64(BORROW, pm[n]); R = _mm512_add_epi64(R, T[n]); R = _mm512_add_epi64(R, CARRY); CARRY = _mm512_srli_epi64(R, DIGIT_SIZE); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(pr + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(pr + LEN52 - 1, R); #undef BITSIZE #undef LEN52 #undef MSD_MSK } void ifma_modsub52x30_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]) { #define BITSIZE (1536) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(BITSIZE, 52)) __m512i *pr = (__m512i *)res; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i *pm = (__m512i *)inpM; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MSD_MASK = _mm512_set1_epi64(MSD_MSK); __m512i T[LEN52]; __m512i R, CARRY, BORROW; int n; /* T[] = a[] - b[] */ BORROW = _mm512_setzero_si512(); for (n = 0; n < LEN52; n++) { R = _mm512_sub_epi64(pa[n], pb[n]); R = _mm512_sub_epi64(R, BORROW); BORROW = _mm512_srli_epi64(R, (64 - 1)); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(T + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(T + LEN52 - 1, R); /* masked modulus add: r[] = T[] + BORROW? m[] : 0 */ CARRY = _mm512_setzero_si512(); BORROW = _mm512_sub_epi64(CARRY, BORROW); /* RORROW -> mask */ for (n = 0; n < LEN52; n++) { R = _mm512_and_epi64(BORROW, pm[n]); R = _mm512_add_epi64(R, T[n]); R = _mm512_add_epi64(R, CARRY); CARRY = _mm512_srli_epi64(R, DIGIT_SIZE); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(pr + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(pr + LEN52 - 1, R); #undef BITSIZE #undef LEN52 #undef MSD_MSK } void ifma_modsub52x40_mb8(int64u res[][8], const int64u inpA[][8], const int64u inpB[][8], const int64u inpM[][8]) { #define BITSIZE (2048) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(BITSIZE, 52)) __m512i *pr = (__m512i *)res; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i *pm = (__m512i *)inpM; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MSD_MASK = _mm512_set1_epi64(MSD_MSK); __m512i T[LEN52]; __m512i R, CARRY, BORROW; int n; /* T[] = a[] - b[] */ BORROW = _mm512_setzero_si512(); for (n = 0; n < LEN52; n++) { R = _mm512_sub_epi64(pa[n], pb[n]); R = _mm512_sub_epi64(R, BORROW); BORROW = _mm512_srli_epi64(R, (64 - 1)); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(T + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(T + LEN52 - 1, R); /* masked modulus add: r[] = T[] + BORROW? m[] : 0 */ CARRY = _mm512_setzero_si512(); BORROW = _mm512_sub_epi64(CARRY, BORROW); /* RORROW -> mask */ for (n = 0; n < LEN52; n++) { R = _mm512_and_epi64(BORROW, pm[n]); R = _mm512_add_epi64(R, T[n]); R = _mm512_add_epi64(R, CARRY); CARRY = _mm512_srli_epi64(R, DIGIT_SIZE); R = _mm512_and_epi64(R, DIG_MASK); _mm512_store_si512(pr + n, R); } /* correct last digit */ R = _mm512_and_epi64(R, MSD_MASK); _mm512_store_si512(pr + LEN52 - 1, R); #undef BITSIZE #undef LEN52 #undef MSD_MSK } /* r += a*b */ void ifma_addmul52x10_mb8(int64u pRes[][8], const int64u inpA[][8], const int64u inpB[][8]) { #define BITSIZE (RSA_1K / 2) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(RSA_2K, 52)) __m512i *pr = (__m512i *)pRes; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i R00 = _mm512_load_si512(pr + 0); /* load pr[nsM-1],...,R[0] */ __m512i R01 = _mm512_load_si512(pr + 1); __m512i R02 = _mm512_load_si512(pr + 2); __m512i R03 = _mm512_load_si512(pr + 3); __m512i R04 = _mm512_load_si512(pr + 4); __m512i R05 = _mm512_load_si512(pr + 5); __m512i R06 = _mm512_load_si512(pr + 6); __m512i R07 = _mm512_load_si512(pr + 7); __m512i R08 = _mm512_load_si512(pr + 8); __m512i R09 = _mm512_load_si512(pr + 9); int itr; for (itr = 0; itr < LEN52; itr++) { __m512i Bi = _mm512_load_si512(pb); __m512i nxtR = _mm512_load_si512(pr + LEN52); pb++; _mm512_madd52lo_epu64_(R00, R00, Bi, pa, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Bi, pa, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Bi, pa, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Bi, pa, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Bi, pa, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Bi, pa, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Bi, pa, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Bi, pa, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Bi, pa, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Bi, pa, 64 * 9); _mm512_store_si512(pr, _mm512_and_epi64(R00, DIG_MASK)); /* store normalized result */ pr++; R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Bi, pa, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Bi, pa, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Bi, pa, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Bi, pa, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Bi, pa, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Bi, pa, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Bi, pa, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Bi, pa, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Bi, pa, 64 * 8); _mm512_madd52hi_epu64_(R09, nxtR, Bi, pa, 64 * 9); } /* normalization */ { __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, DIG_MASK); _mm512_store_si512(pr + 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, DIG_MASK); _mm512_store_si512(pr + 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, DIG_MASK); _mm512_store_si512(pr + 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, DIG_MASK); _mm512_store_si512(pr + 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, DIG_MASK); _mm512_store_si512(pr + 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, DIG_MASK); _mm512_store_si512(pr + 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, DIG_MASK); _mm512_store_si512(pr + 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, DIG_MASK); _mm512_store_si512(pr + 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, DIG_MASK); _mm512_store_si512(pr + 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, DIG_MASK); _mm512_store_si512(pr + 9, R09); } #undef BITSIZE #undef LEN52 #undef MSD_MSK } void ifma_addmul52x20_mb8(int64u pRes[][8], const int64u inpA[][8], const int64u inpB[][8]) { #define BITSIZE (RSA_2K / 2) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(RSA_2K, 52)) __m512i *pr = (__m512i *)pRes; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MS_DIG_MASK = _mm512_set1_epi64(MSD_MSK); __m512i R00 = _mm512_load_si512(pr + 0); /* load pr[nsM-1],...,R[0] */ __m512i R01 = _mm512_load_si512(pr + 1); __m512i R02 = _mm512_load_si512(pr + 2); __m512i R03 = _mm512_load_si512(pr + 3); __m512i R04 = _mm512_load_si512(pr + 4); __m512i R05 = _mm512_load_si512(pr + 5); __m512i R06 = _mm512_load_si512(pr + 6); __m512i R07 = _mm512_load_si512(pr + 7); __m512i R08 = _mm512_load_si512(pr + 8); __m512i R09 = _mm512_load_si512(pr + 9); __m512i R10 = _mm512_load_si512(pr + 10); __m512i R11 = _mm512_load_si512(pr + 11); __m512i R12 = _mm512_load_si512(pr + 12); __m512i R13 = _mm512_load_si512(pr + 13); __m512i R14 = _mm512_load_si512(pr + 14); __m512i R15 = _mm512_load_si512(pr + 15); __m512i R16 = _mm512_load_si512(pr + 16); __m512i R17 = _mm512_load_si512(pr + 17); __m512i R18 = _mm512_load_si512(pr + 18); __m512i R19 = _mm512_load_si512(pr + 19); int itr; for (itr = 0; itr < LEN52; itr++) { __m512i Bi = _mm512_load_si512(pb); __m512i nxtR = _mm512_load_si512(pr + LEN52); pb++; _mm512_madd52lo_epu64_(R00, R00, Bi, pa, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Bi, pa, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Bi, pa, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Bi, pa, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Bi, pa, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Bi, pa, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Bi, pa, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Bi, pa, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Bi, pa, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Bi, pa, 64 * 9); _mm512_madd52lo_epu64_(R10, R10, Bi, pa, 64 * 10); _mm512_madd52lo_epu64_(R11, R11, Bi, pa, 64 * 11); _mm512_madd52lo_epu64_(R12, R12, Bi, pa, 64 * 12); _mm512_madd52lo_epu64_(R13, R13, Bi, pa, 64 * 13); _mm512_madd52lo_epu64_(R14, R14, Bi, pa, 64 * 14); _mm512_madd52lo_epu64_(R15, R15, Bi, pa, 64 * 15); _mm512_madd52lo_epu64_(R16, R16, Bi, pa, 64 * 16); _mm512_madd52lo_epu64_(R17, R17, Bi, pa, 64 * 17); _mm512_madd52lo_epu64_(R18, R18, Bi, pa, 64 * 18); _mm512_madd52lo_epu64_(R19, R19, Bi, pa, 64 * 19); _mm512_store_si512(pr, _mm512_and_epi64(R00, DIG_MASK)); /* store normalized result */ pr++; R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Bi, pa, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Bi, pa, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Bi, pa, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Bi, pa, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Bi, pa, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Bi, pa, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Bi, pa, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Bi, pa, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Bi, pa, 64 * 8); _mm512_madd52hi_epu64_(R09, R10, Bi, pa, 64 * 9); _mm512_madd52hi_epu64_(R10, R11, Bi, pa, 64 * 10); _mm512_madd52hi_epu64_(R11, R12, Bi, pa, 64 * 11); _mm512_madd52hi_epu64_(R12, R13, Bi, pa, 64 * 12); _mm512_madd52hi_epu64_(R13, R14, Bi, pa, 64 * 13); _mm512_madd52hi_epu64_(R14, R15, Bi, pa, 64 * 14); _mm512_madd52hi_epu64_(R15, R16, Bi, pa, 64 * 15); _mm512_madd52hi_epu64_(R16, R17, Bi, pa, 64 * 16); _mm512_madd52hi_epu64_(R17, R18, Bi, pa, 64 * 17); _mm512_madd52hi_epu64_(R18, R19, Bi, pa, 64 * 18); _mm512_madd52hi_epu64_(R19, nxtR, Bi, pa, 64 * 19); } /* normalization */ { __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, DIG_MASK); _mm512_store_si512(pr + 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, DIG_MASK); _mm512_store_si512(pr + 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, DIG_MASK); _mm512_store_si512(pr + 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, DIG_MASK); _mm512_store_si512(pr + 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, DIG_MASK); _mm512_store_si512(pr + 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, DIG_MASK); _mm512_store_si512(pr + 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, DIG_MASK); _mm512_store_si512(pr + 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, DIG_MASK); _mm512_store_si512(pr + 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, DIG_MASK); _mm512_store_si512(pr + 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, DIG_MASK); _mm512_store_si512(pr + 9, R09); R10 = _mm512_add_epi64(R10, T); T = _mm512_srli_epi64(R10, DIGIT_SIZE); R10 = _mm512_and_epi64(R10, DIG_MASK); _mm512_store_si512(pr + 10, R10); R11 = _mm512_add_epi64(R11, T); T = _mm512_srli_epi64(R11, DIGIT_SIZE); R11 = _mm512_and_epi64(R11, DIG_MASK); _mm512_store_si512(pr + 11, R11); R12 = _mm512_add_epi64(R12, T); T = _mm512_srli_epi64(R12, DIGIT_SIZE); R12 = _mm512_and_epi64(R12, DIG_MASK); _mm512_store_si512(pr + 12, R12); R13 = _mm512_add_epi64(R13, T); T = _mm512_srli_epi64(R13, DIGIT_SIZE); R13 = _mm512_and_epi64(R13, DIG_MASK); _mm512_store_si512(pr + 13, R13); R14 = _mm512_add_epi64(R14, T); T = _mm512_srli_epi64(R14, DIGIT_SIZE); R14 = _mm512_and_epi64(R14, DIG_MASK); _mm512_store_si512(pr + 14, R14); R15 = _mm512_add_epi64(R15, T); T = _mm512_srli_epi64(R15, DIGIT_SIZE); R15 = _mm512_and_epi64(R15, DIG_MASK); _mm512_store_si512(pr + 15, R15); R16 = _mm512_add_epi64(R16, T); T = _mm512_srli_epi64(R16, DIGIT_SIZE); R16 = _mm512_and_epi64(R16, DIG_MASK); _mm512_store_si512(pr + 16, R16); R17 = _mm512_add_epi64(R17, T); T = _mm512_srli_epi64(R17, DIGIT_SIZE); R17 = _mm512_and_epi64(R17, DIG_MASK); _mm512_store_si512(pr + 17, R17); R18 = _mm512_add_epi64(R18, T); T = _mm512_srli_epi64(R18, DIGIT_SIZE); R18 = _mm512_and_epi64(R18, DIG_MASK); _mm512_store_si512(pr + 18, R18); R19 = _mm512_add_epi64(R19, T); T = _mm512_srli_epi64(R19, DIGIT_SIZE); R19 = _mm512_and_epi64(R19, MS_DIG_MASK); _mm512_store_si512(pr + 19, R19); } #undef BITSIZE #undef LEN52 #undef MSD_MSK } void ifma_addmul52x30_mb8(int64u pRes[][8], const int64u inpA[][8], const int64u inpB[][8]) { #define BITSIZE (RSA_3K / 2) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(RSA_3K, 52)) __m512i *pr = (__m512i *)pRes; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MS_DIG_MASK = _mm512_set1_epi64(MSD_MSK); __m512i R00 = _mm512_load_si512(pr + 0); /* load pr[nsM-1],...,R[0] */ __m512i R01 = _mm512_load_si512(pr + 1); __m512i R02 = _mm512_load_si512(pr + 2); __m512i R03 = _mm512_load_si512(pr + 3); __m512i R04 = _mm512_load_si512(pr + 4); __m512i R05 = _mm512_load_si512(pr + 5); __m512i R06 = _mm512_load_si512(pr + 6); __m512i R07 = _mm512_load_si512(pr + 7); __m512i R08 = _mm512_load_si512(pr + 8); __m512i R09 = _mm512_load_si512(pr + 9); __m512i R10 = _mm512_load_si512(pr + 10); __m512i R11 = _mm512_load_si512(pr + 11); __m512i R12 = _mm512_load_si512(pr + 12); __m512i R13 = _mm512_load_si512(pr + 13); __m512i R14 = _mm512_load_si512(pr + 14); __m512i R15 = _mm512_load_si512(pr + 15); __m512i R16 = _mm512_load_si512(pr + 16); __m512i R17 = _mm512_load_si512(pr + 17); __m512i R18 = _mm512_load_si512(pr + 18); __m512i R19 = _mm512_load_si512(pr + 19); __m512i R20 = _mm512_load_si512(pr + 20); __m512i R21 = _mm512_load_si512(pr + 21); __m512i R22 = _mm512_load_si512(pr + 22); __m512i R23 = _mm512_load_si512(pr + 23); __m512i R24 = _mm512_load_si512(pr + 24); __m512i R25 = _mm512_load_si512(pr + 25); __m512i R26 = _mm512_load_si512(pr + 26); __m512i R27 = _mm512_load_si512(pr + 27); __m512i R28 = _mm512_load_si512(pr + 28); __m512i R29 = _mm512_load_si512(pr + 29); int itr; for (itr = 0; itr < LEN52; itr++) { __m512i Bi = _mm512_load_si512(pb); __m512i nxtR = _mm512_load_si512(pr + LEN52); pb++; _mm512_madd52lo_epu64_(R00, R00, Bi, pa, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Bi, pa, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Bi, pa, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Bi, pa, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Bi, pa, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Bi, pa, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Bi, pa, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Bi, pa, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Bi, pa, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Bi, pa, 64 * 9); _mm512_madd52lo_epu64_(R10, R10, Bi, pa, 64 * 10); _mm512_madd52lo_epu64_(R11, R11, Bi, pa, 64 * 11); _mm512_madd52lo_epu64_(R12, R12, Bi, pa, 64 * 12); _mm512_madd52lo_epu64_(R13, R13, Bi, pa, 64 * 13); _mm512_madd52lo_epu64_(R14, R14, Bi, pa, 64 * 14); _mm512_madd52lo_epu64_(R15, R15, Bi, pa, 64 * 15); _mm512_madd52lo_epu64_(R16, R16, Bi, pa, 64 * 16); _mm512_madd52lo_epu64_(R17, R17, Bi, pa, 64 * 17); _mm512_madd52lo_epu64_(R18, R18, Bi, pa, 64 * 18); _mm512_madd52lo_epu64_(R19, R19, Bi, pa, 64 * 19); _mm512_madd52lo_epu64_(R20, R20, Bi, pa, 64 * 20); _mm512_madd52lo_epu64_(R21, R21, Bi, pa, 64 * 21); _mm512_madd52lo_epu64_(R22, R22, Bi, pa, 64 * 22); _mm512_madd52lo_epu64_(R23, R23, Bi, pa, 64 * 23); _mm512_madd52lo_epu64_(R24, R24, Bi, pa, 64 * 24); _mm512_madd52lo_epu64_(R25, R25, Bi, pa, 64 * 25); _mm512_madd52lo_epu64_(R26, R26, Bi, pa, 64 * 26); _mm512_madd52lo_epu64_(R27, R27, Bi, pa, 64 * 27); _mm512_madd52lo_epu64_(R28, R28, Bi, pa, 64 * 28); _mm512_madd52lo_epu64_(R29, R29, Bi, pa, 64 * 29); _mm512_store_si512(pr, _mm512_and_epi64(R00, DIG_MASK)); /* store normalized result */ pr++; R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Bi, pa, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Bi, pa, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Bi, pa, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Bi, pa, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Bi, pa, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Bi, pa, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Bi, pa, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Bi, pa, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Bi, pa, 64 * 8); _mm512_madd52hi_epu64_(R09, R10, Bi, pa, 64 * 9); _mm512_madd52hi_epu64_(R10, R11, Bi, pa, 64 * 10); _mm512_madd52hi_epu64_(R11, R12, Bi, pa, 64 * 11); _mm512_madd52hi_epu64_(R12, R13, Bi, pa, 64 * 12); _mm512_madd52hi_epu64_(R13, R14, Bi, pa, 64 * 13); _mm512_madd52hi_epu64_(R14, R15, Bi, pa, 64 * 14); _mm512_madd52hi_epu64_(R15, R16, Bi, pa, 64 * 15); _mm512_madd52hi_epu64_(R16, R17, Bi, pa, 64 * 16); _mm512_madd52hi_epu64_(R17, R18, Bi, pa, 64 * 17); _mm512_madd52hi_epu64_(R18, R19, Bi, pa, 64 * 18); _mm512_madd52hi_epu64_(R19, R20, Bi, pa, 64 * 19); _mm512_madd52hi_epu64_(R20, R21, Bi, pa, 64 * 20); _mm512_madd52hi_epu64_(R21, R22, Bi, pa, 64 * 21); _mm512_madd52hi_epu64_(R22, R23, Bi, pa, 64 * 22); _mm512_madd52hi_epu64_(R23, R24, Bi, pa, 64 * 23); _mm512_madd52hi_epu64_(R24, R25, Bi, pa, 64 * 24); _mm512_madd52hi_epu64_(R25, R26, Bi, pa, 64 * 25); _mm512_madd52hi_epu64_(R26, R27, Bi, pa, 64 * 26); _mm512_madd52hi_epu64_(R27, R28, Bi, pa, 64 * 27); _mm512_madd52hi_epu64_(R28, R29, Bi, pa, 64 * 28); _mm512_madd52hi_epu64_(R29, nxtR, Bi, pa, 64 * 29); } /* normalization */ { __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, DIG_MASK); _mm512_store_si512(pr + 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, DIG_MASK); _mm512_store_si512(pr + 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, DIG_MASK); _mm512_store_si512(pr + 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, DIG_MASK); _mm512_store_si512(pr + 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, DIG_MASK); _mm512_store_si512(pr + 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, DIG_MASK); _mm512_store_si512(pr + 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, DIG_MASK); _mm512_store_si512(pr + 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, DIG_MASK); _mm512_store_si512(pr + 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, DIG_MASK); _mm512_store_si512(pr + 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, DIG_MASK); _mm512_store_si512(pr + 9, R09); R10 = _mm512_add_epi64(R10, T); T = _mm512_srli_epi64(R10, DIGIT_SIZE); R10 = _mm512_and_epi64(R10, DIG_MASK); _mm512_store_si512(pr + 10, R10); R11 = _mm512_add_epi64(R11, T); T = _mm512_srli_epi64(R11, DIGIT_SIZE); R11 = _mm512_and_epi64(R11, DIG_MASK); _mm512_store_si512(pr + 11, R11); R12 = _mm512_add_epi64(R12, T); T = _mm512_srli_epi64(R12, DIGIT_SIZE); R12 = _mm512_and_epi64(R12, DIG_MASK); _mm512_store_si512(pr + 12, R12); R13 = _mm512_add_epi64(R13, T); T = _mm512_srli_epi64(R13, DIGIT_SIZE); R13 = _mm512_and_epi64(R13, DIG_MASK); _mm512_store_si512(pr + 13, R13); R14 = _mm512_add_epi64(R14, T); T = _mm512_srli_epi64(R14, DIGIT_SIZE); R14 = _mm512_and_epi64(R14, DIG_MASK); _mm512_store_si512(pr + 14, R14); R15 = _mm512_add_epi64(R15, T); T = _mm512_srli_epi64(R15, DIGIT_SIZE); R15 = _mm512_and_epi64(R15, DIG_MASK); _mm512_store_si512(pr + 15, R15); R16 = _mm512_add_epi64(R16, T); T = _mm512_srli_epi64(R16, DIGIT_SIZE); R16 = _mm512_and_epi64(R16, DIG_MASK); _mm512_store_si512(pr + 16, R16); R17 = _mm512_add_epi64(R17, T); T = _mm512_srli_epi64(R17, DIGIT_SIZE); R17 = _mm512_and_epi64(R17, DIG_MASK); _mm512_store_si512(pr + 17, R17); R18 = _mm512_add_epi64(R18, T); T = _mm512_srli_epi64(R18, DIGIT_SIZE); R18 = _mm512_and_epi64(R18, DIG_MASK); _mm512_store_si512(pr + 18, R18); R19 = _mm512_add_epi64(R19, T); T = _mm512_srli_epi64(R19, DIGIT_SIZE); R19 = _mm512_and_epi64(R19, DIG_MASK); _mm512_store_si512(pr + 19, R19); R20 = _mm512_add_epi64(R20, T); T = _mm512_srli_epi64(R20, DIGIT_SIZE); R20 = _mm512_and_epi64(R20, DIG_MASK); _mm512_store_si512(pr + 20, R20); R21 = _mm512_add_epi64(R21, T); T = _mm512_srli_epi64(R21, DIGIT_SIZE); R21 = _mm512_and_epi64(R21, DIG_MASK); _mm512_store_si512(pr + 21, R21); R22 = _mm512_add_epi64(R22, T); T = _mm512_srli_epi64(R22, DIGIT_SIZE); R22 = _mm512_and_epi64(R22, DIG_MASK); _mm512_store_si512(pr + 22, R22); R23 = _mm512_add_epi64(R23, T); T = _mm512_srli_epi64(R23, DIGIT_SIZE); R23 = _mm512_and_epi64(R23, DIG_MASK); _mm512_store_si512(pr + 23, R23); R24 = _mm512_add_epi64(R24, T); T = _mm512_srli_epi64(R24, DIGIT_SIZE); R24 = _mm512_and_epi64(R24, DIG_MASK); _mm512_store_si512(pr + 24, R24); R25 = _mm512_add_epi64(R25, T); T = _mm512_srli_epi64(R25, DIGIT_SIZE); R25 = _mm512_and_epi64(R25, DIG_MASK); _mm512_store_si512(pr + 25, R25); R26 = _mm512_add_epi64(R26, T); T = _mm512_srli_epi64(R26, DIGIT_SIZE); R26 = _mm512_and_epi64(R26, DIG_MASK); _mm512_store_si512(pr + 26, R26); R27 = _mm512_add_epi64(R27, T); T = _mm512_srli_epi64(R27, DIGIT_SIZE); R27 = _mm512_and_epi64(R27, DIG_MASK); _mm512_store_si512(pr + 27, R27); R28 = _mm512_add_epi64(R28, T); T = _mm512_srli_epi64(R28, DIGIT_SIZE); R28 = _mm512_and_epi64(R28, DIG_MASK); _mm512_store_si512(pr + 28, R28); R29 = _mm512_add_epi64(R29, T); T = _mm512_srli_epi64(R29, DIGIT_SIZE); R29 = _mm512_and_epi64(R29, MS_DIG_MASK); _mm512_store_si512(pr + 29, R29); } #undef BITSIZE #undef LEN52 #undef MSD_MSK } void ifma_addmul52x40_mb8(int64u pRes[][8], const int64u inpA[][8], const int64u inpB[][8]) { #define BITSIZE (RSA_4K / 2) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE, 52)) #define MSD_MSK (MS_DIGIT_MASK(RSA_4K, 52)) __m512i *pr = (__m512i *)pRes; __m512i *pa = (__m512i *)inpA; __m512i *pb = (__m512i *)inpB; __m512i DIG_MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i MS_DIG_MASK = _mm512_set1_epi64(MSD_MSK); __m512i R00 = _mm512_load_si512(pr + 0); /* load pr[nsM-1],...,R[0] */ __m512i R01 = _mm512_load_si512(pr + 1); __m512i R02 = _mm512_load_si512(pr + 2); __m512i R03 = _mm512_load_si512(pr + 3); __m512i R04 = _mm512_load_si512(pr + 4); __m512i R05 = _mm512_load_si512(pr + 5); __m512i R06 = _mm512_load_si512(pr + 6); __m512i R07 = _mm512_load_si512(pr + 7); __m512i R08 = _mm512_load_si512(pr + 8); __m512i R09 = _mm512_load_si512(pr + 9); __m512i R10 = _mm512_load_si512(pr + 10); __m512i R11 = _mm512_load_si512(pr + 11); __m512i R12 = _mm512_load_si512(pr + 12); __m512i R13 = _mm512_load_si512(pr + 13); __m512i R14 = _mm512_load_si512(pr + 14); __m512i R15 = _mm512_load_si512(pr + 15); __m512i R16 = _mm512_load_si512(pr + 16); __m512i R17 = _mm512_load_si512(pr + 17); __m512i R18 = _mm512_load_si512(pr + 18); __m512i R19 = _mm512_load_si512(pr + 19); __m512i R20 = _mm512_load_si512(pr + 20); __m512i R21 = _mm512_load_si512(pr + 21); __m512i R22 = _mm512_load_si512(pr + 22); __m512i R23 = _mm512_load_si512(pr + 23); __m512i R24 = _mm512_load_si512(pr + 24); __m512i R25 = _mm512_load_si512(pr + 25); __m512i R26 = _mm512_load_si512(pr + 26); __m512i R27 = _mm512_load_si512(pr + 27); __m512i R28 = _mm512_load_si512(pr + 28); __m512i R29 = _mm512_load_si512(pr + 29); __m512i R30 = _mm512_load_si512(pr + 30); __m512i R31 = _mm512_load_si512(pr + 31); __m512i R32 = _mm512_load_si512(pr + 32); __m512i R33 = _mm512_load_si512(pr + 33); __m512i R34 = _mm512_load_si512(pr + 34); __m512i R35 = _mm512_load_si512(pr + 35); __m512i R36 = _mm512_load_si512(pr + 36); __m512i R37 = _mm512_load_si512(pr + 37); __m512i R38 = _mm512_load_si512(pr + 38); __m512i R39 = _mm512_load_si512(pr + 39); int itr; for (itr = 0; itr < LEN52; itr++) { __m512i Bi = _mm512_load_si512(pb); __m512i nxtR = _mm512_load_si512(pr + LEN52); pb++; _mm512_madd52lo_epu64_(R00, R00, Bi, pa, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Bi, pa, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Bi, pa, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Bi, pa, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Bi, pa, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Bi, pa, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Bi, pa, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Bi, pa, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Bi, pa, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Bi, pa, 64 * 9); _mm512_madd52lo_epu64_(R10, R10, Bi, pa, 64 * 10); _mm512_madd52lo_epu64_(R11, R11, Bi, pa, 64 * 11); _mm512_madd52lo_epu64_(R12, R12, Bi, pa, 64 * 12); _mm512_madd52lo_epu64_(R13, R13, Bi, pa, 64 * 13); _mm512_madd52lo_epu64_(R14, R14, Bi, pa, 64 * 14); _mm512_madd52lo_epu64_(R15, R15, Bi, pa, 64 * 15); _mm512_madd52lo_epu64_(R16, R16, Bi, pa, 64 * 16); _mm512_madd52lo_epu64_(R17, R17, Bi, pa, 64 * 17); _mm512_madd52lo_epu64_(R18, R18, Bi, pa, 64 * 18); _mm512_madd52lo_epu64_(R19, R19, Bi, pa, 64 * 19); _mm512_madd52lo_epu64_(R20, R20, Bi, pa, 64 * 20); _mm512_madd52lo_epu64_(R21, R21, Bi, pa, 64 * 21); _mm512_madd52lo_epu64_(R22, R22, Bi, pa, 64 * 22); _mm512_madd52lo_epu64_(R23, R23, Bi, pa, 64 * 23); _mm512_madd52lo_epu64_(R24, R24, Bi, pa, 64 * 24); _mm512_madd52lo_epu64_(R25, R25, Bi, pa, 64 * 25); _mm512_madd52lo_epu64_(R26, R26, Bi, pa, 64 * 26); _mm512_madd52lo_epu64_(R27, R27, Bi, pa, 64 * 27); _mm512_madd52lo_epu64_(R28, R28, Bi, pa, 64 * 28); _mm512_madd52lo_epu64_(R29, R29, Bi, pa, 64 * 29); _mm512_madd52lo_epu64_(R30, R30, Bi, pa, 64 * 30); _mm512_madd52lo_epu64_(R31, R31, Bi, pa, 64 * 31); _mm512_madd52lo_epu64_(R32, R32, Bi, pa, 64 * 32); _mm512_madd52lo_epu64_(R33, R33, Bi, pa, 64 * 33); _mm512_madd52lo_epu64_(R34, R34, Bi, pa, 64 * 34); _mm512_madd52lo_epu64_(R35, R35, Bi, pa, 64 * 35); _mm512_madd52lo_epu64_(R36, R36, Bi, pa, 64 * 36); _mm512_madd52lo_epu64_(R37, R37, Bi, pa, 64 * 37); _mm512_madd52lo_epu64_(R38, R38, Bi, pa, 64 * 38); _mm512_madd52lo_epu64_(R39, R39, Bi, pa, 64 * 39); _mm512_store_si512(pr, _mm512_and_epi64(R00, DIG_MASK)); /* store normalized result */ pr++; R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Bi, pa, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Bi, pa, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Bi, pa, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Bi, pa, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Bi, pa, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Bi, pa, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Bi, pa, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Bi, pa, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Bi, pa, 64 * 8); _mm512_madd52hi_epu64_(R09, R10, Bi, pa, 64 * 9); _mm512_madd52hi_epu64_(R10, R11, Bi, pa, 64 * 10); _mm512_madd52hi_epu64_(R11, R12, Bi, pa, 64 * 11); _mm512_madd52hi_epu64_(R12, R13, Bi, pa, 64 * 12); _mm512_madd52hi_epu64_(R13, R14, Bi, pa, 64 * 13); _mm512_madd52hi_epu64_(R14, R15, Bi, pa, 64 * 14); _mm512_madd52hi_epu64_(R15, R16, Bi, pa, 64 * 15); _mm512_madd52hi_epu64_(R16, R17, Bi, pa, 64 * 16); _mm512_madd52hi_epu64_(R17, R18, Bi, pa, 64 * 17); _mm512_madd52hi_epu64_(R18, R19, Bi, pa, 64 * 18); _mm512_madd52hi_epu64_(R19, R20, Bi, pa, 64 * 19); _mm512_madd52hi_epu64_(R20, R21, Bi, pa, 64 * 20); _mm512_madd52hi_epu64_(R21, R22, Bi, pa, 64 * 21); _mm512_madd52hi_epu64_(R22, R23, Bi, pa, 64 * 22); _mm512_madd52hi_epu64_(R23, R24, Bi, pa, 64 * 23); _mm512_madd52hi_epu64_(R24, R25, Bi, pa, 64 * 24); _mm512_madd52hi_epu64_(R25, R26, Bi, pa, 64 * 25); _mm512_madd52hi_epu64_(R26, R27, Bi, pa, 64 * 26); _mm512_madd52hi_epu64_(R27, R28, Bi, pa, 64 * 27); _mm512_madd52hi_epu64_(R28, R29, Bi, pa, 64 * 28); _mm512_madd52hi_epu64_(R29, R30, Bi, pa, 64 * 29); _mm512_madd52hi_epu64_(R30, R31, Bi, pa, 64 * 30); _mm512_madd52hi_epu64_(R31, R32, Bi, pa, 64 * 31); _mm512_madd52hi_epu64_(R32, R33, Bi, pa, 64 * 32); _mm512_madd52hi_epu64_(R33, R34, Bi, pa, 64 * 33); _mm512_madd52hi_epu64_(R34, R35, Bi, pa, 64 * 34); _mm512_madd52hi_epu64_(R35, R36, Bi, pa, 64 * 35); _mm512_madd52hi_epu64_(R36, R37, Bi, pa, 64 * 36); _mm512_madd52hi_epu64_(R37, R38, Bi, pa, 64 * 37); _mm512_madd52hi_epu64_(R38, R39, Bi, pa, 64 * 38); _mm512_madd52hi_epu64_(R39, nxtR, Bi, pa, 64 * 39); } /* normalization */ { __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, DIG_MASK); _mm512_store_si512(pr + 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, DIG_MASK); _mm512_store_si512(pr + 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, DIG_MASK); _mm512_store_si512(pr + 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, DIG_MASK); _mm512_store_si512(pr + 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, DIG_MASK); _mm512_store_si512(pr + 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, DIG_MASK); _mm512_store_si512(pr + 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, DIG_MASK); _mm512_store_si512(pr + 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, DIG_MASK); _mm512_store_si512(pr + 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, DIG_MASK); _mm512_store_si512(pr + 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, DIG_MASK); _mm512_store_si512(pr + 9, R09); R10 = _mm512_add_epi64(R10, T); T = _mm512_srli_epi64(R10, DIGIT_SIZE); R10 = _mm512_and_epi64(R10, DIG_MASK); _mm512_store_si512(pr + 10, R10); R11 = _mm512_add_epi64(R11, T); T = _mm512_srli_epi64(R11, DIGIT_SIZE); R11 = _mm512_and_epi64(R11, DIG_MASK); _mm512_store_si512(pr + 11, R11); R12 = _mm512_add_epi64(R12, T); T = _mm512_srli_epi64(R12, DIGIT_SIZE); R12 = _mm512_and_epi64(R12, DIG_MASK); _mm512_store_si512(pr + 12, R12); R13 = _mm512_add_epi64(R13, T); T = _mm512_srli_epi64(R13, DIGIT_SIZE); R13 = _mm512_and_epi64(R13, DIG_MASK); _mm512_store_si512(pr + 13, R13); R14 = _mm512_add_epi64(R14, T); T = _mm512_srli_epi64(R14, DIGIT_SIZE); R14 = _mm512_and_epi64(R14, DIG_MASK); _mm512_store_si512(pr + 14, R14); R15 = _mm512_add_epi64(R15, T); T = _mm512_srli_epi64(R15, DIGIT_SIZE); R15 = _mm512_and_epi64(R15, DIG_MASK); _mm512_store_si512(pr + 15, R15); R16 = _mm512_add_epi64(R16, T); T = _mm512_srli_epi64(R16, DIGIT_SIZE); R16 = _mm512_and_epi64(R16, DIG_MASK); _mm512_store_si512(pr + 16, R16); R17 = _mm512_add_epi64(R17, T); T = _mm512_srli_epi64(R17, DIGIT_SIZE); R17 = _mm512_and_epi64(R17, DIG_MASK); _mm512_store_si512(pr + 17, R17); R18 = _mm512_add_epi64(R18, T); T = _mm512_srli_epi64(R18, DIGIT_SIZE); R18 = _mm512_and_epi64(R18, DIG_MASK); _mm512_store_si512(pr + 18, R18); R19 = _mm512_add_epi64(R19, T); T = _mm512_srli_epi64(R19, DIGIT_SIZE); R19 = _mm512_and_epi64(R19, DIG_MASK); _mm512_store_si512(pr + 19, R19); R20 = _mm512_add_epi64(R20, T); T = _mm512_srli_epi64(R20, DIGIT_SIZE); R20 = _mm512_and_epi64(R20, DIG_MASK); _mm512_store_si512(pr + 20, R20); R21 = _mm512_add_epi64(R21, T); T = _mm512_srli_epi64(R21, DIGIT_SIZE); R21 = _mm512_and_epi64(R21, DIG_MASK); _mm512_store_si512(pr + 21, R21); R22 = _mm512_add_epi64(R22, T); T = _mm512_srli_epi64(R22, DIGIT_SIZE); R22 = _mm512_and_epi64(R22, DIG_MASK); _mm512_store_si512(pr + 22, R22); R23 = _mm512_add_epi64(R23, T); T = _mm512_srli_epi64(R23, DIGIT_SIZE); R23 = _mm512_and_epi64(R23, DIG_MASK); _mm512_store_si512(pr + 23, R23); R24 = _mm512_add_epi64(R24, T); T = _mm512_srli_epi64(R24, DIGIT_SIZE); R24 = _mm512_and_epi64(R24, DIG_MASK); _mm512_store_si512(pr + 24, R24); R25 = _mm512_add_epi64(R25, T); T = _mm512_srli_epi64(R25, DIGIT_SIZE); R25 = _mm512_and_epi64(R25, DIG_MASK); _mm512_store_si512(pr + 25, R25); R26 = _mm512_add_epi64(R26, T); T = _mm512_srli_epi64(R26, DIGIT_SIZE); R26 = _mm512_and_epi64(R26, DIG_MASK); _mm512_store_si512(pr + 26, R26); R27 = _mm512_add_epi64(R27, T); T = _mm512_srli_epi64(R27, DIGIT_SIZE); R27 = _mm512_and_epi64(R27, DIG_MASK); _mm512_store_si512(pr + 27, R27); R28 = _mm512_add_epi64(R28, T); T = _mm512_srli_epi64(R28, DIGIT_SIZE); R28 = _mm512_and_epi64(R28, DIG_MASK); _mm512_store_si512(pr + 28, R28); R29 = _mm512_add_epi64(R29, T); T = _mm512_srli_epi64(R29, DIGIT_SIZE); R29 = _mm512_and_epi64(R29, DIG_MASK); _mm512_store_si512(pr + 29, R29); R30 = _mm512_add_epi64(R30, T); T = _mm512_srli_epi64(R30, DIGIT_SIZE); R30 = _mm512_and_epi64(R30, DIG_MASK); _mm512_store_si512(pr + 30, R30); R31 = _mm512_add_epi64(R31, T); T = _mm512_srli_epi64(R31, DIGIT_SIZE); R31 = _mm512_and_epi64(R31, DIG_MASK); _mm512_store_si512(pr + 31, R31); R32 = _mm512_add_epi64(R32, T); T = _mm512_srli_epi64(R32, DIGIT_SIZE); R32 = _mm512_and_epi64(R32, DIG_MASK); _mm512_store_si512(pr + 32, R32); R33 = _mm512_add_epi64(R33, T); T = _mm512_srli_epi64(R33, DIGIT_SIZE); R33 = _mm512_and_epi64(R33, DIG_MASK); _mm512_store_si512(pr + 33, R33); R34 = _mm512_add_epi64(R34, T); T = _mm512_srli_epi64(R34, DIGIT_SIZE); R34 = _mm512_and_epi64(R34, DIG_MASK); _mm512_store_si512(pr + 34, R34); R35 = _mm512_add_epi64(R35, T); T = _mm512_srli_epi64(R35, DIGIT_SIZE); R35 = _mm512_and_epi64(R35, DIG_MASK); _mm512_store_si512(pr + 35, R35); R36 = _mm512_add_epi64(R36, T); T = _mm512_srli_epi64(R36, DIGIT_SIZE); R36 = _mm512_and_epi64(R36, DIG_MASK); _mm512_store_si512(pr + 36, R36); R37 = _mm512_add_epi64(R37, T); T = _mm512_srli_epi64(R37, DIGIT_SIZE); R37 = _mm512_and_epi64(R37, DIG_MASK); _mm512_store_si512(pr + 37, R37); R38 = _mm512_add_epi64(R38, T); T = _mm512_srli_epi64(R38, DIGIT_SIZE); R38 = _mm512_and_epi64(R38, MS_DIG_MASK); _mm512_store_si512(pr + 38, R38); } #undef BITSIZE #undef LEN52 #undef MSD_MSK } /* r = x * (R^-1) mod q */ void ifma_amred52x10_mb8(int64u res[][8], const int64u inpA[][8], /* int nsA == 2*nsM */ const int64u inpM[][8], /* int nsM ==10 */ const int64u k0[8]) { int64u *pA = (int64u *)inpA; int64u *pM = (int64u *)inpM; int64u *pR = (int64u *)res; __m512i K = _mm512_load_si512(k0); /* k0[] */ __m512i R00 = _mm512_load_si512(pA + 8 * 0); /* load A[nsM-1],...,A[0] */ __m512i R01 = _mm512_load_si512(pA + 8 * 1); __m512i R02 = _mm512_load_si512(pA + 8 * 2); __m512i R03 = _mm512_load_si512(pA + 8 * 3); __m512i R04 = _mm512_load_si512(pA + 8 * 4); __m512i R05 = _mm512_load_si512(pA + 8 * 5); __m512i R06 = _mm512_load_si512(pA + 8 * 6); __m512i R07 = _mm512_load_si512(pA + 8 * 7); __m512i R08 = _mm512_load_si512(pA + 8 * 8); __m512i R09 = _mm512_load_si512(pA + 8 * 9); int itr; for (itr = 0, pA += 8 * 10; itr < 10; itr++, pA += 8) { __m512i Yi = _mm512_madd52lo_epu64(_mm512_setzero_si512(), R00, K); __m512i nxtA = _mm512_load_si512(pA); _mm512_madd52lo_epu64_(R00, R00, Yi, pM, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Yi, pM, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Yi, pM, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Yi, pM, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Yi, pM, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Yi, pM, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Yi, pM, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Yi, pM, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Yi, pM, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Yi, pM, 64 * 9); R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Yi, pM, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Yi, pM, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Yi, pM, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Yi, pM, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Yi, pM, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Yi, pM, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Yi, pM, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Yi, pM, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Yi, pM, 64 * 8); _mm512_madd52hi_epu64_(R09, nxtA, Yi, pM, 64 * 9); } /* normalization */ { __m512i MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, MASK); _mm512_store_si512(pR + 8 * 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, MASK); _mm512_store_si512(pR + 8 * 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, MASK); _mm512_store_si512(pR + 8 * 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, MASK); _mm512_store_si512(pR + 8 * 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, MASK); _mm512_store_si512(pR + 8 * 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, MASK); _mm512_store_si512(pR + 8 * 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, MASK); _mm512_store_si512(pR + 8 * 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, MASK); _mm512_store_si512(pR + 8 * 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, MASK); _mm512_store_si512(pR + 8 * 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, MASK); _mm512_store_si512(pR + 8 * 9, R09); } } void ifma_amred52x20_mb8(int64u res[][8], const int64u inpA[][8], /* int nsA == 2*nsM */ const int64u inpM[][8], /* int nsM ==20 */ const int64u k0[8]) { int64u *pA = (int64u *)inpA; int64u *pM = (int64u *)inpM; int64u *pR = (int64u *)res; __m512i K = _mm512_load_si512(k0); /* k0[] */ __m512i R00 = _mm512_load_si512(pA + 8 * 0); /* load A[nsM-1],...,A[0] */ __m512i R01 = _mm512_load_si512(pA + 8 * 1); __m512i R02 = _mm512_load_si512(pA + 8 * 2); __m512i R03 = _mm512_load_si512(pA + 8 * 3); __m512i R04 = _mm512_load_si512(pA + 8 * 4); __m512i R05 = _mm512_load_si512(pA + 8 * 5); __m512i R06 = _mm512_load_si512(pA + 8 * 6); __m512i R07 = _mm512_load_si512(pA + 8 * 7); __m512i R08 = _mm512_load_si512(pA + 8 * 8); __m512i R09 = _mm512_load_si512(pA + 8 * 9); __m512i R10 = _mm512_load_si512(pA + 8 * 10); __m512i R11 = _mm512_load_si512(pA + 8 * 11); __m512i R12 = _mm512_load_si512(pA + 8 * 12); __m512i R13 = _mm512_load_si512(pA + 8 * 13); __m512i R14 = _mm512_load_si512(pA + 8 * 14); __m512i R15 = _mm512_load_si512(pA + 8 * 15); __m512i R16 = _mm512_load_si512(pA + 8 * 16); __m512i R17 = _mm512_load_si512(pA + 8 * 17); __m512i R18 = _mm512_load_si512(pA + 8 * 18); __m512i R19 = _mm512_load_si512(pA + 8 * 19); int itr; for (itr = 0, pA += 8 * 20; itr < 20; itr++, pA += 8) { __m512i Yi = _mm512_madd52lo_epu64(_mm512_setzero_si512(), R00, K); __m512i nxtA = _mm512_load_si512(pA); _mm512_madd52lo_epu64_(R00, R00, Yi, pM, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Yi, pM, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Yi, pM, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Yi, pM, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Yi, pM, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Yi, pM, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Yi, pM, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Yi, pM, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Yi, pM, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Yi, pM, 64 * 9); _mm512_madd52lo_epu64_(R10, R10, Yi, pM, 64 * 10); _mm512_madd52lo_epu64_(R11, R11, Yi, pM, 64 * 11); _mm512_madd52lo_epu64_(R12, R12, Yi, pM, 64 * 12); _mm512_madd52lo_epu64_(R13, R13, Yi, pM, 64 * 13); _mm512_madd52lo_epu64_(R14, R14, Yi, pM, 64 * 14); _mm512_madd52lo_epu64_(R15, R15, Yi, pM, 64 * 15); _mm512_madd52lo_epu64_(R16, R16, Yi, pM, 64 * 16); _mm512_madd52lo_epu64_(R17, R17, Yi, pM, 64 * 17); _mm512_madd52lo_epu64_(R18, R18, Yi, pM, 64 * 18); _mm512_madd52lo_epu64_(R19, R19, Yi, pM, 64 * 19); R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Yi, pM, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Yi, pM, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Yi, pM, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Yi, pM, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Yi, pM, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Yi, pM, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Yi, pM, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Yi, pM, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Yi, pM, 64 * 8); _mm512_madd52hi_epu64_(R09, R10, Yi, pM, 64 * 9); _mm512_madd52hi_epu64_(R10, R11, Yi, pM, 64 * 10); _mm512_madd52hi_epu64_(R11, R12, Yi, pM, 64 * 11); _mm512_madd52hi_epu64_(R12, R13, Yi, pM, 64 * 12); _mm512_madd52hi_epu64_(R13, R14, Yi, pM, 64 * 13); _mm512_madd52hi_epu64_(R14, R15, Yi, pM, 64 * 14); _mm512_madd52hi_epu64_(R15, R16, Yi, pM, 64 * 15); _mm512_madd52hi_epu64_(R16, R17, Yi, pM, 64 * 16); _mm512_madd52hi_epu64_(R17, R18, Yi, pM, 64 * 17); _mm512_madd52hi_epu64_(R18, R19, Yi, pM, 64 * 18); _mm512_madd52hi_epu64_(R19, nxtA, Yi, pM, 64 * 19); } /* normalization */ { __m512i MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, MASK); _mm512_store_si512(pR + 8 * 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, MASK); _mm512_store_si512(pR + 8 * 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, MASK); _mm512_store_si512(pR + 8 * 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, MASK); _mm512_store_si512(pR + 8 * 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, MASK); _mm512_store_si512(pR + 8 * 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, MASK); _mm512_store_si512(pR + 8 * 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, MASK); _mm512_store_si512(pR + 8 * 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, MASK); _mm512_store_si512(pR + 8 * 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, MASK); _mm512_store_si512(pR + 8 * 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, MASK); _mm512_store_si512(pR + 8 * 9, R09); R10 = _mm512_add_epi64(R10, T); T = _mm512_srli_epi64(R10, DIGIT_SIZE); R10 = _mm512_and_epi64(R10, MASK); _mm512_store_si512(pR + 8 * 10, R10); R11 = _mm512_add_epi64(R11, T); T = _mm512_srli_epi64(R11, DIGIT_SIZE); R11 = _mm512_and_epi64(R11, MASK); _mm512_store_si512(pR + 8 * 11, R11); R12 = _mm512_add_epi64(R12, T); T = _mm512_srli_epi64(R12, DIGIT_SIZE); R12 = _mm512_and_epi64(R12, MASK); _mm512_store_si512(pR + 8 * 12, R12); R13 = _mm512_add_epi64(R13, T); T = _mm512_srli_epi64(R13, DIGIT_SIZE); R13 = _mm512_and_epi64(R13, MASK); _mm512_store_si512(pR + 8 * 13, R13); R14 = _mm512_add_epi64(R14, T); T = _mm512_srli_epi64(R14, DIGIT_SIZE); R14 = _mm512_and_epi64(R14, MASK); _mm512_store_si512(pR + 8 * 14, R14); R15 = _mm512_add_epi64(R15, T); T = _mm512_srli_epi64(R15, DIGIT_SIZE); R15 = _mm512_and_epi64(R15, MASK); _mm512_store_si512(pR + 8 * 15, R15); R16 = _mm512_add_epi64(R16, T); T = _mm512_srli_epi64(R16, DIGIT_SIZE); R16 = _mm512_and_epi64(R16, MASK); _mm512_store_si512(pR + 8 * 16, R16); R17 = _mm512_add_epi64(R17, T); T = _mm512_srli_epi64(R17, DIGIT_SIZE); R17 = _mm512_and_epi64(R17, MASK); _mm512_store_si512(pR + 8 * 17, R17); R18 = _mm512_add_epi64(R18, T); T = _mm512_srli_epi64(R18, DIGIT_SIZE); R18 = _mm512_and_epi64(R18, MASK); _mm512_store_si512(pR + 8 * 18, R18); R19 = _mm512_add_epi64(R19, T); T = _mm512_srli_epi64(R19, DIGIT_SIZE); R19 = _mm512_and_epi64(R19, MASK); _mm512_store_si512(pR + 8 * 19, R19); } } void ifma_amred52x30_mb8(int64u res[][8], const int64u inpA[][8], /* int nsA == 2*nsM */ const int64u inpM[][8], /* int nsM ==20 */ const int64u k0[8]) { int64u *pA = (int64u *)inpA; int64u *pM = (int64u *)inpM; int64u *pR = (int64u *)res; __m512i K = _mm512_load_si512(k0); /* k0[] */ __m512i R00 = _mm512_load_si512(pA + 8 * 0); /* load A[nsM-1],...,A[0] */ __m512i R01 = _mm512_load_si512(pA + 8 * 1); __m512i R02 = _mm512_load_si512(pA + 8 * 2); __m512i R03 = _mm512_load_si512(pA + 8 * 3); __m512i R04 = _mm512_load_si512(pA + 8 * 4); __m512i R05 = _mm512_load_si512(pA + 8 * 5); __m512i R06 = _mm512_load_si512(pA + 8 * 6); __m512i R07 = _mm512_load_si512(pA + 8 * 7); __m512i R08 = _mm512_load_si512(pA + 8 * 8); __m512i R09 = _mm512_load_si512(pA + 8 * 9); __m512i R10 = _mm512_load_si512(pA + 8 * 10); __m512i R11 = _mm512_load_si512(pA + 8 * 11); __m512i R12 = _mm512_load_si512(pA + 8 * 12); __m512i R13 = _mm512_load_si512(pA + 8 * 13); __m512i R14 = _mm512_load_si512(pA + 8 * 14); __m512i R15 = _mm512_load_si512(pA + 8 * 15); __m512i R16 = _mm512_load_si512(pA + 8 * 16); __m512i R17 = _mm512_load_si512(pA + 8 * 17); __m512i R18 = _mm512_load_si512(pA + 8 * 18); __m512i R19 = _mm512_load_si512(pA + 8 * 19); __m512i R20 = _mm512_load_si512(pA + 8 * 20); __m512i R21 = _mm512_load_si512(pA + 8 * 21); __m512i R22 = _mm512_load_si512(pA + 8 * 22); __m512i R23 = _mm512_load_si512(pA + 8 * 23); __m512i R24 = _mm512_load_si512(pA + 8 * 24); __m512i R25 = _mm512_load_si512(pA + 8 * 25); __m512i R26 = _mm512_load_si512(pA + 8 * 26); __m512i R27 = _mm512_load_si512(pA + 8 * 27); __m512i R28 = _mm512_load_si512(pA + 8 * 28); __m512i R29 = _mm512_load_si512(pA + 8 * 29); int itr; for (itr = 0, pA += 8 * 30; itr < 30; itr++, pA += 8) { __m512i Yi = _mm512_madd52lo_epu64(_mm512_setzero_si512(), R00, K); __m512i nxtA = _mm512_load_si512(pA); _mm512_madd52lo_epu64_(R00, R00, Yi, pM, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Yi, pM, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Yi, pM, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Yi, pM, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Yi, pM, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Yi, pM, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Yi, pM, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Yi, pM, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Yi, pM, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Yi, pM, 64 * 9); _mm512_madd52lo_epu64_(R10, R10, Yi, pM, 64 * 10); _mm512_madd52lo_epu64_(R11, R11, Yi, pM, 64 * 11); _mm512_madd52lo_epu64_(R12, R12, Yi, pM, 64 * 12); _mm512_madd52lo_epu64_(R13, R13, Yi, pM, 64 * 13); _mm512_madd52lo_epu64_(R14, R14, Yi, pM, 64 * 14); _mm512_madd52lo_epu64_(R15, R15, Yi, pM, 64 * 15); _mm512_madd52lo_epu64_(R16, R16, Yi, pM, 64 * 16); _mm512_madd52lo_epu64_(R17, R17, Yi, pM, 64 * 17); _mm512_madd52lo_epu64_(R18, R18, Yi, pM, 64 * 18); _mm512_madd52lo_epu64_(R19, R19, Yi, pM, 64 * 19); _mm512_madd52lo_epu64_(R20, R20, Yi, pM, 64 * 20); _mm512_madd52lo_epu64_(R21, R21, Yi, pM, 64 * 21); _mm512_madd52lo_epu64_(R22, R22, Yi, pM, 64 * 22); _mm512_madd52lo_epu64_(R23, R23, Yi, pM, 64 * 23); _mm512_madd52lo_epu64_(R24, R24, Yi, pM, 64 * 24); _mm512_madd52lo_epu64_(R25, R25, Yi, pM, 64 * 25); _mm512_madd52lo_epu64_(R26, R26, Yi, pM, 64 * 26); _mm512_madd52lo_epu64_(R27, R27, Yi, pM, 64 * 27); _mm512_madd52lo_epu64_(R28, R28, Yi, pM, 64 * 28); _mm512_madd52lo_epu64_(R29, R29, Yi, pM, 64 * 29); R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Yi, pM, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Yi, pM, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Yi, pM, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Yi, pM, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Yi, pM, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Yi, pM, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Yi, pM, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Yi, pM, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Yi, pM, 64 * 8); _mm512_madd52hi_epu64_(R09, R10, Yi, pM, 64 * 9); _mm512_madd52hi_epu64_(R10, R11, Yi, pM, 64 * 10); _mm512_madd52hi_epu64_(R11, R12, Yi, pM, 64 * 11); _mm512_madd52hi_epu64_(R12, R13, Yi, pM, 64 * 12); _mm512_madd52hi_epu64_(R13, R14, Yi, pM, 64 * 13); _mm512_madd52hi_epu64_(R14, R15, Yi, pM, 64 * 14); _mm512_madd52hi_epu64_(R15, R16, Yi, pM, 64 * 15); _mm512_madd52hi_epu64_(R16, R17, Yi, pM, 64 * 16); _mm512_madd52hi_epu64_(R17, R18, Yi, pM, 64 * 17); _mm512_madd52hi_epu64_(R18, R19, Yi, pM, 64 * 18); _mm512_madd52hi_epu64_(R19, R20, Yi, pM, 64 * 19); _mm512_madd52hi_epu64_(R20, R21, Yi, pM, 64 * 20); _mm512_madd52hi_epu64_(R21, R22, Yi, pM, 64 * 21); _mm512_madd52hi_epu64_(R22, R23, Yi, pM, 64 * 22); _mm512_madd52hi_epu64_(R23, R24, Yi, pM, 64 * 23); _mm512_madd52hi_epu64_(R24, R25, Yi, pM, 64 * 24); _mm512_madd52hi_epu64_(R25, R26, Yi, pM, 64 * 25); _mm512_madd52hi_epu64_(R26, R27, Yi, pM, 64 * 26); _mm512_madd52hi_epu64_(R27, R28, Yi, pM, 64 * 27); _mm512_madd52hi_epu64_(R28, R29, Yi, pM, 64 * 28); _mm512_madd52hi_epu64_(R29, nxtA, Yi, pM, 64 * 29); } /* normalization */ { __m512i MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, MASK); _mm512_store_si512(pR + 8 * 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, MASK); _mm512_store_si512(pR + 8 * 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, MASK); _mm512_store_si512(pR + 8 * 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, MASK); _mm512_store_si512(pR + 8 * 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, MASK); _mm512_store_si512(pR + 8 * 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, MASK); _mm512_store_si512(pR + 8 * 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, MASK); _mm512_store_si512(pR + 8 * 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, MASK); _mm512_store_si512(pR + 8 * 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, MASK); _mm512_store_si512(pR + 8 * 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, MASK); _mm512_store_si512(pR + 8 * 9, R09); R10 = _mm512_add_epi64(R10, T); T = _mm512_srli_epi64(R10, DIGIT_SIZE); R10 = _mm512_and_epi64(R10, MASK); _mm512_store_si512(pR + 8 * 10, R10); R11 = _mm512_add_epi64(R11, T); T = _mm512_srli_epi64(R11, DIGIT_SIZE); R11 = _mm512_and_epi64(R11, MASK); _mm512_store_si512(pR + 8 * 11, R11); R12 = _mm512_add_epi64(R12, T); T = _mm512_srli_epi64(R12, DIGIT_SIZE); R12 = _mm512_and_epi64(R12, MASK); _mm512_store_si512(pR + 8 * 12, R12); R13 = _mm512_add_epi64(R13, T); T = _mm512_srli_epi64(R13, DIGIT_SIZE); R13 = _mm512_and_epi64(R13, MASK); _mm512_store_si512(pR + 8 * 13, R13); R14 = _mm512_add_epi64(R14, T); T = _mm512_srli_epi64(R14, DIGIT_SIZE); R14 = _mm512_and_epi64(R14, MASK); _mm512_store_si512(pR + 8 * 14, R14); R15 = _mm512_add_epi64(R15, T); T = _mm512_srli_epi64(R15, DIGIT_SIZE); R15 = _mm512_and_epi64(R15, MASK); _mm512_store_si512(pR + 8 * 15, R15); R16 = _mm512_add_epi64(R16, T); T = _mm512_srli_epi64(R16, DIGIT_SIZE); R16 = _mm512_and_epi64(R16, MASK); _mm512_store_si512(pR + 8 * 16, R16); R17 = _mm512_add_epi64(R17, T); T = _mm512_srli_epi64(R17, DIGIT_SIZE); R17 = _mm512_and_epi64(R17, MASK); _mm512_store_si512(pR + 8 * 17, R17); R18 = _mm512_add_epi64(R18, T); T = _mm512_srli_epi64(R18, DIGIT_SIZE); R18 = _mm512_and_epi64(R18, MASK); _mm512_store_si512(pR + 8 * 18, R18); R19 = _mm512_add_epi64(R19, T); T = _mm512_srli_epi64(R19, DIGIT_SIZE); R19 = _mm512_and_epi64(R19, MASK); _mm512_store_si512(pR + 8 * 19, R19); R20 = _mm512_add_epi64(R20, T); T = _mm512_srli_epi64(R20, DIGIT_SIZE); R20 = _mm512_and_epi64(R20, MASK); _mm512_store_si512(pR + 8 * 20, R20); R21 = _mm512_add_epi64(R21, T); T = _mm512_srli_epi64(R21, DIGIT_SIZE); R21 = _mm512_and_epi64(R21, MASK); _mm512_store_si512(pR + 8 * 21, R21); R22 = _mm512_add_epi64(R22, T); T = _mm512_srli_epi64(R22, DIGIT_SIZE); R22 = _mm512_and_epi64(R22, MASK); _mm512_store_si512(pR + 8 * 22, R22); R23 = _mm512_add_epi64(R23, T); T = _mm512_srli_epi64(R23, DIGIT_SIZE); R23 = _mm512_and_epi64(R23, MASK); _mm512_store_si512(pR + 8 * 23, R23); R24 = _mm512_add_epi64(R24, T); T = _mm512_srli_epi64(R24, DIGIT_SIZE); R24 = _mm512_and_epi64(R24, MASK); _mm512_store_si512(pR + 8 * 24, R24); R25 = _mm512_add_epi64(R25, T); T = _mm512_srli_epi64(R25, DIGIT_SIZE); R25 = _mm512_and_epi64(R25, MASK); _mm512_store_si512(pR + 8 * 25, R25); R26 = _mm512_add_epi64(R26, T); T = _mm512_srli_epi64(R26, DIGIT_SIZE); R26 = _mm512_and_epi64(R26, MASK); _mm512_store_si512(pR + 8 * 26, R26); R27 = _mm512_add_epi64(R27, T); T = _mm512_srli_epi64(R27, DIGIT_SIZE); R27 = _mm512_and_epi64(R27, MASK); _mm512_store_si512(pR + 8 * 27, R27); R28 = _mm512_add_epi64(R28, T); T = _mm512_srli_epi64(R28, DIGIT_SIZE); R28 = _mm512_and_epi64(R28, MASK); _mm512_store_si512(pR + 8 * 28, R28); R29 = _mm512_add_epi64(R29, T); T = _mm512_srli_epi64(R29, DIGIT_SIZE); R29 = _mm512_and_epi64(R29, MASK); _mm512_store_si512(pR + 8 * 29, R29); } } void ifma_amred52x40_mb8(int64u res[][8], const int64u inpA[][8], /* int nsA == 2*nsM */ const int64u inpM[][8], /* int nsM ==20 */ const int64u k0[8]) { int64u *pA = (int64u *)inpA; int64u *pM = (int64u *)inpM; int64u *pR = (int64u *)res; __m512i K = _mm512_load_si512(k0); /* k0[] */ __m512i R00 = _mm512_load_si512(pA + 8 * 0); /* load A[nsM-1],...,A[0] */ __m512i R01 = _mm512_load_si512(pA + 8 * 1); __m512i R02 = _mm512_load_si512(pA + 8 * 2); __m512i R03 = _mm512_load_si512(pA + 8 * 3); __m512i R04 = _mm512_load_si512(pA + 8 * 4); __m512i R05 = _mm512_load_si512(pA + 8 * 5); __m512i R06 = _mm512_load_si512(pA + 8 * 6); __m512i R07 = _mm512_load_si512(pA + 8 * 7); __m512i R08 = _mm512_load_si512(pA + 8 * 8); __m512i R09 = _mm512_load_si512(pA + 8 * 9); __m512i R10 = _mm512_load_si512(pA + 8 * 10); __m512i R11 = _mm512_load_si512(pA + 8 * 11); __m512i R12 = _mm512_load_si512(pA + 8 * 12); __m512i R13 = _mm512_load_si512(pA + 8 * 13); __m512i R14 = _mm512_load_si512(pA + 8 * 14); __m512i R15 = _mm512_load_si512(pA + 8 * 15); __m512i R16 = _mm512_load_si512(pA + 8 * 16); __m512i R17 = _mm512_load_si512(pA + 8 * 17); __m512i R18 = _mm512_load_si512(pA + 8 * 18); __m512i R19 = _mm512_load_si512(pA + 8 * 19); __m512i R20 = _mm512_load_si512(pA + 8 * 20); __m512i R21 = _mm512_load_si512(pA + 8 * 21); __m512i R22 = _mm512_load_si512(pA + 8 * 22); __m512i R23 = _mm512_load_si512(pA + 8 * 23); __m512i R24 = _mm512_load_si512(pA + 8 * 24); __m512i R25 = _mm512_load_si512(pA + 8 * 25); __m512i R26 = _mm512_load_si512(pA + 8 * 26); __m512i R27 = _mm512_load_si512(pA + 8 * 27); __m512i R28 = _mm512_load_si512(pA + 8 * 28); __m512i R29 = _mm512_load_si512(pA + 8 * 29); __m512i R30 = _mm512_load_si512(pA + 8 * 30); __m512i R31 = _mm512_load_si512(pA + 8 * 31); __m512i R32 = _mm512_load_si512(pA + 8 * 32); __m512i R33 = _mm512_load_si512(pA + 8 * 33); __m512i R34 = _mm512_load_si512(pA + 8 * 34); __m512i R35 = _mm512_load_si512(pA + 8 * 35); __m512i R36 = _mm512_load_si512(pA + 8 * 36); __m512i R37 = _mm512_load_si512(pA + 8 * 37); __m512i R38 = _mm512_load_si512(pA + 8 * 38); __m512i R39 = _mm512_load_si512(pA + 8 * 39); int itr; for (itr = 0, pA += 8 * 40; itr < 40; itr++, pA += 8) { __m512i Yi = _mm512_madd52lo_epu64(_mm512_setzero_si512(), R00, K); __m512i nxtA = _mm512_load_si512(pA); _mm512_madd52lo_epu64_(R00, R00, Yi, pM, 64 * 0); _mm512_madd52lo_epu64_(R01, R01, Yi, pM, 64 * 1); _mm512_madd52lo_epu64_(R02, R02, Yi, pM, 64 * 2); _mm512_madd52lo_epu64_(R03, R03, Yi, pM, 64 * 3); _mm512_madd52lo_epu64_(R04, R04, Yi, pM, 64 * 4); _mm512_madd52lo_epu64_(R05, R05, Yi, pM, 64 * 5); _mm512_madd52lo_epu64_(R06, R06, Yi, pM, 64 * 6); _mm512_madd52lo_epu64_(R07, R07, Yi, pM, 64 * 7); _mm512_madd52lo_epu64_(R08, R08, Yi, pM, 64 * 8); _mm512_madd52lo_epu64_(R09, R09, Yi, pM, 64 * 9); _mm512_madd52lo_epu64_(R10, R10, Yi, pM, 64 * 10); _mm512_madd52lo_epu64_(R11, R11, Yi, pM, 64 * 11); _mm512_madd52lo_epu64_(R12, R12, Yi, pM, 64 * 12); _mm512_madd52lo_epu64_(R13, R13, Yi, pM, 64 * 13); _mm512_madd52lo_epu64_(R14, R14, Yi, pM, 64 * 14); _mm512_madd52lo_epu64_(R15, R15, Yi, pM, 64 * 15); _mm512_madd52lo_epu64_(R16, R16, Yi, pM, 64 * 16); _mm512_madd52lo_epu64_(R17, R17, Yi, pM, 64 * 17); _mm512_madd52lo_epu64_(R18, R18, Yi, pM, 64 * 18); _mm512_madd52lo_epu64_(R19, R19, Yi, pM, 64 * 19); _mm512_madd52lo_epu64_(R20, R20, Yi, pM, 64 * 20); _mm512_madd52lo_epu64_(R21, R21, Yi, pM, 64 * 21); _mm512_madd52lo_epu64_(R22, R22, Yi, pM, 64 * 22); _mm512_madd52lo_epu64_(R23, R23, Yi, pM, 64 * 23); _mm512_madd52lo_epu64_(R24, R24, Yi, pM, 64 * 24); _mm512_madd52lo_epu64_(R25, R25, Yi, pM, 64 * 25); _mm512_madd52lo_epu64_(R26, R26, Yi, pM, 64 * 26); _mm512_madd52lo_epu64_(R27, R27, Yi, pM, 64 * 27); _mm512_madd52lo_epu64_(R28, R28, Yi, pM, 64 * 28); _mm512_madd52lo_epu64_(R29, R29, Yi, pM, 64 * 29); _mm512_madd52lo_epu64_(R30, R30, Yi, pM, 64 * 30); _mm512_madd52lo_epu64_(R31, R31, Yi, pM, 64 * 31); _mm512_madd52lo_epu64_(R32, R32, Yi, pM, 64 * 32); _mm512_madd52lo_epu64_(R33, R33, Yi, pM, 64 * 33); _mm512_madd52lo_epu64_(R34, R34, Yi, pM, 64 * 34); _mm512_madd52lo_epu64_(R35, R35, Yi, pM, 64 * 35); _mm512_madd52lo_epu64_(R36, R36, Yi, pM, 64 * 36); _mm512_madd52lo_epu64_(R37, R37, Yi, pM, 64 * 37); _mm512_madd52lo_epu64_(R38, R38, Yi, pM, 64 * 38); _mm512_madd52lo_epu64_(R39, R39, Yi, pM, 64 * 39); R00 = _mm512_srli_epi64(R00, DIGIT_SIZE); R01 = _mm512_add_epi64(R01, R00); _mm512_madd52hi_epu64_(R00, R01, Yi, pM, 64 * 0); _mm512_madd52hi_epu64_(R01, R02, Yi, pM, 64 * 1); _mm512_madd52hi_epu64_(R02, R03, Yi, pM, 64 * 2); _mm512_madd52hi_epu64_(R03, R04, Yi, pM, 64 * 3); _mm512_madd52hi_epu64_(R04, R05, Yi, pM, 64 * 4); _mm512_madd52hi_epu64_(R05, R06, Yi, pM, 64 * 5); _mm512_madd52hi_epu64_(R06, R07, Yi, pM, 64 * 6); _mm512_madd52hi_epu64_(R07, R08, Yi, pM, 64 * 7); _mm512_madd52hi_epu64_(R08, R09, Yi, pM, 64 * 8); _mm512_madd52hi_epu64_(R09, R10, Yi, pM, 64 * 9); _mm512_madd52hi_epu64_(R10, R11, Yi, pM, 64 * 10); _mm512_madd52hi_epu64_(R11, R12, Yi, pM, 64 * 11); _mm512_madd52hi_epu64_(R12, R13, Yi, pM, 64 * 12); _mm512_madd52hi_epu64_(R13, R14, Yi, pM, 64 * 13); _mm512_madd52hi_epu64_(R14, R15, Yi, pM, 64 * 14); _mm512_madd52hi_epu64_(R15, R16, Yi, pM, 64 * 15); _mm512_madd52hi_epu64_(R16, R17, Yi, pM, 64 * 16); _mm512_madd52hi_epu64_(R17, R18, Yi, pM, 64 * 17); _mm512_madd52hi_epu64_(R18, R19, Yi, pM, 64 * 18); _mm512_madd52hi_epu64_(R19, R20, Yi, pM, 64 * 19); _mm512_madd52hi_epu64_(R20, R21, Yi, pM, 64 * 20); _mm512_madd52hi_epu64_(R21, R22, Yi, pM, 64 * 21); _mm512_madd52hi_epu64_(R22, R23, Yi, pM, 64 * 22); _mm512_madd52hi_epu64_(R23, R24, Yi, pM, 64 * 23); _mm512_madd52hi_epu64_(R24, R25, Yi, pM, 64 * 24); _mm512_madd52hi_epu64_(R25, R26, Yi, pM, 64 * 25); _mm512_madd52hi_epu64_(R26, R27, Yi, pM, 64 * 26); _mm512_madd52hi_epu64_(R27, R28, Yi, pM, 64 * 27); _mm512_madd52hi_epu64_(R28, R29, Yi, pM, 64 * 28); _mm512_madd52hi_epu64_(R29, R30, Yi, pM, 64 * 29); _mm512_madd52hi_epu64_(R30, R31, Yi, pM, 64 * 30); _mm512_madd52hi_epu64_(R31, R32, Yi, pM, 64 * 31); _mm512_madd52hi_epu64_(R32, R33, Yi, pM, 64 * 32); _mm512_madd52hi_epu64_(R33, R34, Yi, pM, 64 * 33); _mm512_madd52hi_epu64_(R34, R35, Yi, pM, 64 * 34); _mm512_madd52hi_epu64_(R35, R36, Yi, pM, 64 * 35); _mm512_madd52hi_epu64_(R36, R37, Yi, pM, 64 * 36); _mm512_madd52hi_epu64_(R37, R38, Yi, pM, 64 * 37); _mm512_madd52hi_epu64_(R38, R39, Yi, pM, 64 * 38); _mm512_madd52hi_epu64_(R39, nxtA, Yi, pM, 64 * 39); } /* normalization */ { __m512i MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i T = _mm512_srli_epi64(R00, DIGIT_SIZE); R00 = _mm512_and_epi64(R00, MASK); _mm512_store_si512(pR + 8 * 0, R00); R01 = _mm512_add_epi64(R01, T); T = _mm512_srli_epi64(R01, DIGIT_SIZE); R01 = _mm512_and_epi64(R01, MASK); _mm512_store_si512(pR + 8 * 1, R01); R02 = _mm512_add_epi64(R02, T); T = _mm512_srli_epi64(R02, DIGIT_SIZE); R02 = _mm512_and_epi64(R02, MASK); _mm512_store_si512(pR + 8 * 2, R02); R03 = _mm512_add_epi64(R03, T); T = _mm512_srli_epi64(R03, DIGIT_SIZE); R03 = _mm512_and_epi64(R03, MASK); _mm512_store_si512(pR + 8 * 3, R03); R04 = _mm512_add_epi64(R04, T); T = _mm512_srli_epi64(R04, DIGIT_SIZE); R04 = _mm512_and_epi64(R04, MASK); _mm512_store_si512(pR + 8 * 4, R04); R05 = _mm512_add_epi64(R05, T); T = _mm512_srli_epi64(R05, DIGIT_SIZE); R05 = _mm512_and_epi64(R05, MASK); _mm512_store_si512(pR + 8 * 5, R05); R06 = _mm512_add_epi64(R06, T); T = _mm512_srli_epi64(R06, DIGIT_SIZE); R06 = _mm512_and_epi64(R06, MASK); _mm512_store_si512(pR + 8 * 6, R06); R07 = _mm512_add_epi64(R07, T); T = _mm512_srli_epi64(R07, DIGIT_SIZE); R07 = _mm512_and_epi64(R07, MASK); _mm512_store_si512(pR + 8 * 7, R07); R08 = _mm512_add_epi64(R08, T); T = _mm512_srli_epi64(R08, DIGIT_SIZE); R08 = _mm512_and_epi64(R08, MASK); _mm512_store_si512(pR + 8 * 8, R08); R09 = _mm512_add_epi64(R09, T); T = _mm512_srli_epi64(R09, DIGIT_SIZE); R09 = _mm512_and_epi64(R09, MASK); _mm512_store_si512(pR + 8 * 9, R09); R10 = _mm512_add_epi64(R10, T); T = _mm512_srli_epi64(R10, DIGIT_SIZE); R10 = _mm512_and_epi64(R10, MASK); _mm512_store_si512(pR + 8 * 10, R10); R11 = _mm512_add_epi64(R11, T); T = _mm512_srli_epi64(R11, DIGIT_SIZE); R11 = _mm512_and_epi64(R11, MASK); _mm512_store_si512(pR + 8 * 11, R11); R12 = _mm512_add_epi64(R12, T); T = _mm512_srli_epi64(R12, DIGIT_SIZE); R12 = _mm512_and_epi64(R12, MASK); _mm512_store_si512(pR + 8 * 12, R12); R13 = _mm512_add_epi64(R13, T); T = _mm512_srli_epi64(R13, DIGIT_SIZE); R13 = _mm512_and_epi64(R13, MASK); _mm512_store_si512(pR + 8 * 13, R13); R14 = _mm512_add_epi64(R14, T); T = _mm512_srli_epi64(R14, DIGIT_SIZE); R14 = _mm512_and_epi64(R14, MASK); _mm512_store_si512(pR + 8 * 14, R14); R15 = _mm512_add_epi64(R15, T); T = _mm512_srli_epi64(R15, DIGIT_SIZE); R15 = _mm512_and_epi64(R15, MASK); _mm512_store_si512(pR + 8 * 15, R15); R16 = _mm512_add_epi64(R16, T); T = _mm512_srli_epi64(R16, DIGIT_SIZE); R16 = _mm512_and_epi64(R16, MASK); _mm512_store_si512(pR + 8 * 16, R16); R17 = _mm512_add_epi64(R17, T); T = _mm512_srli_epi64(R17, DIGIT_SIZE); R17 = _mm512_and_epi64(R17, MASK); _mm512_store_si512(pR + 8 * 17, R17); R18 = _mm512_add_epi64(R18, T); T = _mm512_srli_epi64(R18, DIGIT_SIZE); R18 = _mm512_and_epi64(R18, MASK); _mm512_store_si512(pR + 8 * 18, R18); R19 = _mm512_add_epi64(R19, T); T = _mm512_srli_epi64(R19, DIGIT_SIZE); R19 = _mm512_and_epi64(R19, MASK); _mm512_store_si512(pR + 8 * 19, R19); R20 = _mm512_add_epi64(R20, T); T = _mm512_srli_epi64(R20, DIGIT_SIZE); R20 = _mm512_and_epi64(R20, MASK); _mm512_store_si512(pR + 8 * 20, R20); R21 = _mm512_add_epi64(R21, T); T = _mm512_srli_epi64(R21, DIGIT_SIZE); R21 = _mm512_and_epi64(R21, MASK); _mm512_store_si512(pR + 8 * 21, R21); R22 = _mm512_add_epi64(R22, T); T = _mm512_srli_epi64(R22, DIGIT_SIZE); R22 = _mm512_and_epi64(R22, MASK); _mm512_store_si512(pR + 8 * 22, R22); R23 = _mm512_add_epi64(R23, T); T = _mm512_srli_epi64(R23, DIGIT_SIZE); R23 = _mm512_and_epi64(R23, MASK); _mm512_store_si512(pR + 8 * 23, R23); R24 = _mm512_add_epi64(R24, T); T = _mm512_srli_epi64(R24, DIGIT_SIZE); R24 = _mm512_and_epi64(R24, MASK); _mm512_store_si512(pR + 8 * 24, R24); R25 = _mm512_add_epi64(R25, T); T = _mm512_srli_epi64(R25, DIGIT_SIZE); R25 = _mm512_and_epi64(R25, MASK); _mm512_store_si512(pR + 8 * 25, R25); R26 = _mm512_add_epi64(R26, T); T = _mm512_srli_epi64(R26, DIGIT_SIZE); R26 = _mm512_and_epi64(R26, MASK); _mm512_store_si512(pR + 8 * 26, R26); R27 = _mm512_add_epi64(R27, T); T = _mm512_srli_epi64(R27, DIGIT_SIZE); R27 = _mm512_and_epi64(R27, MASK); _mm512_store_si512(pR + 8 * 27, R27); R28 = _mm512_add_epi64(R28, T); T = _mm512_srli_epi64(R28, DIGIT_SIZE); R28 = _mm512_and_epi64(R28, MASK); _mm512_store_si512(pR + 8 * 28, R28); R29 = _mm512_add_epi64(R29, T); T = _mm512_srli_epi64(R29, DIGIT_SIZE); R29 = _mm512_and_epi64(R29, MASK); _mm512_store_si512(pR + 8 * 29, R29); R30 = _mm512_add_epi64(R30, T); T = _mm512_srli_epi64(R30, DIGIT_SIZE); R30 = _mm512_and_epi64(R30, MASK); _mm512_store_si512(pR + 8 * 30, R30); R31 = _mm512_add_epi64(R31, T); T = _mm512_srli_epi64(R31, DIGIT_SIZE); R31 = _mm512_and_epi64(R31, MASK); _mm512_store_si512(pR + 8 * 31, R31); R32 = _mm512_add_epi64(R32, T); T = _mm512_srli_epi64(R32, DIGIT_SIZE); R32 = _mm512_and_epi64(R32, MASK); _mm512_store_si512(pR + 8 * 32, R32); R33 = _mm512_add_epi64(R33, T); T = _mm512_srli_epi64(R33, DIGIT_SIZE); R33 = _mm512_and_epi64(R33, MASK); _mm512_store_si512(pR + 8 * 33, R33); R34 = _mm512_add_epi64(R34, T); T = _mm512_srli_epi64(R34, DIGIT_SIZE); R34 = _mm512_and_epi64(R34, MASK); _mm512_store_si512(pR + 8 * 34, R34); R35 = _mm512_add_epi64(R35, T); T = _mm512_srli_epi64(R35, DIGIT_SIZE); R35 = _mm512_and_epi64(R35, MASK); _mm512_store_si512(pR + 8 * 35, R35); R36 = _mm512_add_epi64(R36, T); T = _mm512_srli_epi64(R36, DIGIT_SIZE); R36 = _mm512_and_epi64(R36, MASK); _mm512_store_si512(pR + 8 * 36, R36); R37 = _mm512_add_epi64(R37, T); T = _mm512_srli_epi64(R37, DIGIT_SIZE); R37 = _mm512_and_epi64(R37, MASK); _mm512_store_si512(pR + 8 * 37, R37); R38 = _mm512_add_epi64(R38, T); T = _mm512_srli_epi64(R38, DIGIT_SIZE); R38 = _mm512_and_epi64(R38, MASK); _mm512_store_si512(pR + 8 * 38, R38); R39 = _mm512_add_epi64(R39, T); T = _mm512_srli_epi64(R39, DIGIT_SIZE); R39 = _mm512_and_epi64(R39, MASK); _mm512_store_si512(pR + 8 * 39, R39); } } ////////////////////////////////////////////////////////////////////// /* // out[] = inp[] <>nbit */ static void rshift52x_mb8(int64u pOut[][8], int64u pInp[][8], int ns, __m512i sbiR) { __m512i sbiL = _mm512_sub_epi64(_mm512_set1_epi64(DIGIT_SIZE), sbiR); __m512i digMask = _mm512_set1_epi64(DIGIT_MASK); __m512i shiftedL = _mm512_setzero_si512(); int n; for (n = ns; n > 0; n--) { __m512i inp = _mm512_load_si512(pInp[n - 1]); __m512i out = _mm512_and_si512(_mm512_or_si512(shiftedL, _mm512_srlv_epi64(inp, sbiR)), digMask); _mm512_store_si512(pOut[n - 1], out); shiftedL = _mm512_sllv_epi64(inp, sbiL); } } /* // believe the following works: // // right = {r1:r0} - high and low // left = {l1:l0} - high and low // // if(r1!=l1) // return r1>l1; // else // return r0>l0; */ static __mmask8 left_gt_right_mb8(__m512i left_hi, __m512i left_lo, __m512i right_hi, __m512i right_lo) { __mmask8 k0 = _mm512_cmpneq_epi64_mask(left_hi, right_hi); __mmask8 k1 = (k0 & _mm512_cmpgt_epu64_mask(left_hi, right_hi)) | (~k0 & _mm512_cmpgt_epu64_mask(left_lo, right_lo)); return k1; } __m512i tz; /* sub multiplied_by_digit // maskk8 reports whether addition performed inside */ static __mmask8 ifma_sub_muldig52x_mb8(__m512i *pRes, const __m512i *pM, int nsM, __m512i dig) { __m512i MASK = _mm512_set1_epi64(DIGIT_MASK); __m512i prodLO = _mm512_setzero_si512(); __m512i prodHI = _mm512_setzero_si512(); __m512i cf = _mm512_setzero_si512(); __m512i T; __mmask8 k1; int n; /* multiply dig*pM[] and sub from pRes[] */ for (n = 0; n < nsM; n++) { prodLO = _mm512_madd52lo_epu64(prodHI, dig, pM[n]); // Nasty performance hack for 2 FMA SKUs prodLO = _mm512_add_epi64(prodLO, tz); prodHI = _mm512_madd52hi_epu64(_mm512_setzero_si512(), dig, pM[n]); T = _mm512_sub_epi64(pRes[n], prodLO); T = _mm512_add_epi64(T, cf); cf = _mm512_srai_epi64(T, DIGIT_SIZE); T = _mm512_and_epi64(T, MASK); _mm512_storeu_si512(pRes + n, T); } T = _mm512_sub_epi64(pRes[n], prodHI); T = _mm512_add_epi64(T, cf); cf = _mm512_srai_epi64(T, DIGIT_SIZE); T = _mm512_and_epi64(T, MASK); _mm512_storeu_si512(pRes + n, T); /* set mask if borrow */ k1 = _mm512_cmpneq_epu64_mask(cf, _mm512_setzero_si512()); /* masked add pM[] */ cf = _mm512_setzero_si512(); for (n = 0; n < nsM; n++) { T = _mm512_mask_add_epi64(pRes[n], k1, pRes[n], pM[n]); T = _mm512_add_epi64(T, cf); cf = _mm512_srli_epi64(T, DIGIT_SIZE); T = _mm512_and_epi64(T, MASK); _mm512_storeu_si512(pRes + n, T); } T = _mm512_add_epi64(cf, pRes[n]); _mm512_storeu_si512(pRes + n, T); return k1; } // EXTERN_C void div128_64_asm_mb8(int64u q[8], int64u r[8], const int64u aH[8], const int64u aL[8], const int64u d[8]); // from Cristina EXTERN_C __m512i __div_104_by_52(__m512i Ah, __m512i Al, __m512i B, __m512i *prem); /* compute estimation of quotient digit (exactq): q-1 <= exactq <= q */ static __m512i estimateq_mb8(const __m512i *ptopX, const __m512i *ptopY) { __m512i base52 = _mm512_set1_epi64(DIGIT_BASE); __m512i one = _mm512_set1_epi64(1); __m512i y0 = _mm512_load_si512(ptopY); /* high divisor's digit (B=base52) */ __m512i y1 = _mm512_load_si512(ptopY - 1); //__m512i x0 = _mm512_load_si512(ptopX); /* 3 high divident's digits (B=base52) */ //__m512i x1 = _mm512_load_si512(ptopX-1); __m512i x2 = _mm512_load_si512(ptopX - 2); __m512i quo, rem; __m512i left_lo = _mm512_setzero_si512(); __m512i left_hi = _mm512_setzero_si512(); __mmask8 k1, k0; #if 0 // replaced by Cristina's code /* get estimation for (qhat,rhat) = (x0*B + x1)/y0 */ div128_64_asm_mb8((int64u*)&quo, (int64u*)&rem, (int64u*)(ptopX), (int64u*)(ptopX-1), (int64u*)(ptopY)); // Avoid store-to-load forwarding block quo = _mm512_i32gather_epi64(_mm256_setr_epi32(0,1,2,3,4,5,6,7), &quo, 8); rem = _mm512_i32gather_epi64(_mm256_setr_epi32(0,1,2,3,4,5,6,7), &rem, 8); #endif quo = __div_104_by_52(ptopX[0], ptopX[-1], ptopY[0], &rem); /* compare {y0:y1}*quo and {x0:x1:x2} left = quo*y1 right = rem*B + x2 */ left_lo = _mm512_madd52lo_epu64(left_lo, y1, quo); // left = y1*quo left_hi = _mm512_madd52hi_epu64(left_hi, y1, quo); // right = rem*B + x2 => pair of digits {r:x2} // k1 = left>right k1 = left_gt_right_mb8(left_hi, left_lo, rem, x2); // if(left>right) quo = _mm512_mask_sub_epi64(quo, k1, quo, one); // quo -= 1 rem = _mm512_mask_add_epi64(rem, k1, rem, y0); // rem += y0 , note "right" increased at the same time k0 = _mm512_mask_cmpgt_epu64_mask(k1, y1, left_lo); // k0 = left_lo < y1 left_lo = _mm512_mask_sub_epi64(left_lo, k1, left_lo, y1); // left -= y1 left_hi = _mm512_mask_sub_epi64(left_hi, (k1 & k0), left_hi, one); // k0 = rem < B k0 = _mm512_cmplt_epu64_mask(rem, base52); // k1 = left>right k1 = k0 & left_gt_right_mb8(left_hi, left_lo, rem, x2); quo = _mm512_mask_sub_epi64(quo, k1, quo, one); // quo -= 1 return quo; } /* x = x % m */ void ifma_mreduce52x_mb8(int64u pX[][8], int nsX, int64u pM[][8], int nsM) { /* usually divider have to be normilized */ __m512i *pMtop = (__m512i *)(pM[nsM - 1]); /* top of M */ __m512i normBits = _mm512_sub_epi64(_mm512_lzcnt_epi64(pMtop[0]), _mm512_set1_epi64(64 - DIGIT_SIZE)); tz = _mm512_setzero_si512(); /* normalize both divisor and shift dividentr */ lshift52x_mb8(pM, pM, nsM, normBits); /* expand and shift X */ _mm512_store_si512(pX[nsX], _mm512_setzero_si512()); lshift52x_mb8(pX, pX, nsX + 1, normBits); // division { __m512i *pXtop = (__m512i *)(pX[nsX]); /* top of X (zero value) -- &X[nsX] */ __m512i *pXbot = (__m512i *)(pX[nsX - nsM]); /* bot of X -- &X[nsQ-1] */ while (pXbot >= (__m512i *)pX) { /* compute estimation of quotient digit q */ __m512i q = estimateq_mb8(pXtop, pMtop); /* multiply and sub */ ifma_sub_muldig52x_mb8(pXbot, (__m512i *)pM, nsM, q); pXtop--; pXbot--; } } rshift52x_mb8(pX, pX, nsM, normBits); rshift52x_mb8(pM, pM, nsM, normBits); } /* bitsize of 2^64 representation => bitsize of 2^52 representation */ #define BASE52_BITSIZE(b64bitsize) ((b64bitsize) + ((DIGIT_SIZE - ((b64bitsize) % DIGIT_SIZE)) % DIGIT_SIZE)) /* rr = 2^(2*ifmaBitLen) mod m */ void ifma_montRR52x_mb8(int64u pRR[][8], int64u pM[][8], int convBitLen) { #define MAX_IFMA_MODULUS_BITLEN BASE52_BITSIZE(RSA_4K) /* buffer to hold 2^(2*MAX_IFMA_MODULUS_BITLEN) */ __ALIGN64 int64u pwr2_mb8[(NUMBER_OF_DIGITS(2 * MAX_IFMA_MODULUS_BITLEN + 1, DIGIT_SIZE)) + 1] [8]; /* +1 is necessary extension for ifma_mreduce52x_mb8() purpose */ int ifmaBitLen = BASE52_BITSIZE(convBitLen); int ifmaLen = NUMBER_OF_DIGITS(ifmaBitLen, DIGIT_SIZE); int pwr = 2 * ifmaBitLen; int s = pwr - ((pwr / DIGIT_SIZE) * DIGIT_SIZE); int pwrLen = NUMBER_OF_DIGITS(pwr + 1, DIGIT_SIZE); /* set 2^(ifmaBitLen*2) */ zero_mb8(pwr2_mb8, pwrLen); _mm512_store_si512(pwr2_mb8[pwrLen - 1], _mm512_slli_epi64(_mm512_set1_epi64(1), s)); /* 2^(ifmaBitLen*2) mod M */ ifma_mreduce52x_mb8(pwr2_mb8, pwrLen, pM, ifmaLen); /* copy result */ for (s = 0; s < ifmaLen; s++) _mm512_store_si512(pRR[s], _mm512_load_si512(pwr2_mb8[s])); #undef MAX_IFMA_MODULUS_BITLEN } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) __MBX_INLINE __m256i _mm256_srai_epi64_wrapper(__m256i A, const int imm) { const __m256i sign_bit_mask = _mm256_and_si256(A, _mm256_set1_epi64x(1ULL << 63)); const __m256i is_not_sign_mask = _mm256_cmpeq_epi64(sign_bit_mask, _mm256_setzero_si256()); const __m256i shifted_in_bits = _mm256_set1_epi64x(0xFFFFFFFFFFFFFFFFULL << (64 - imm)); const __m256i or_mask = _mm256_andnot_si256(is_not_sign_mask, shifted_in_bits); /* logical shift right */ A = _mm256_srli_epi64(A, imm); /* put sign bits into the most significant imm number of bits */ A = _mm256_or_si256(A, or_mask); return A; } __MBX_INLINE __m256i _mm256_cvtpd_epi64_wrapper(__m256d A) { const __m128d lo = _mm256_castpd256_pd128(A); const __m128d hi = _mm256_extractf128_pd(A, 1); const int64u lo0 = _mm_cvtsd_si64(lo); const int64u lo1 = _mm_cvtsd_si64(_mm_shuffle_pd(lo, lo, 1)); const int64u hi0 = _mm_cvtsd_si64(hi); const int64u hi1 = _mm_cvtsd_si64(_mm_shuffle_pd(hi, hi, 1)); const __m128i l = _mm_insert_epi64(_mm_cvtsi64_si128(lo0), lo1, 1); const __m128i h = _mm_insert_epi64(_mm_cvtsi64_si128(hi0), hi1, 1); return _mm256_inserti128_si256(_mm256_castsi128_si256(l), h, 1); } __MBX_INLINE __m256d _mm256_cvtepu64_pd_wrapper(__m256i A) { const __m128i lo = _mm256_castsi256_si128(A); const __m128i hi = _mm256_extracti128_si256(A, 1); const __m128d lo0 = _mm_cvtsi64_sd(_mm_setzero_pd(), _mm_cvtsi128_si64(lo)); const __m128d lo1 = _mm_cvtsi64_sd(_mm_setzero_pd(), _mm_extract_epi64(lo, 1)); const __m128d hi0 = _mm_cvtsi64_sd(_mm_setzero_pd(), _mm_cvtsi128_si64(hi)); const __m128d hi1 = _mm_cvtsi64_sd(_mm_setzero_pd(), _mm_extract_epi64(hi, 1)); const __m128d l = _mm_unpacklo_pd(lo0, lo1); const __m128d h = _mm_unpacklo_pd(hi0, hi1); return _mm256_insertf128_pd(_mm256_castpd128_pd256(l), h, 1); } __NOINLINE void zero_mb4(void *out, int len) { #if defined(__GNUC__) // Avoid dead code elimination for GNU compilers ASM(""); #endif const __m256i T = _mm256_setzero_si256(); __m256i *p_out = (__m256i *)out; int i; for (i = 0; i < len; i++) _mm256_storeu_si256(p_out++, T); } void copy_mb4(int64u out[][4], const int64u inp[][4], int len) { __m256i *p_out = (__m256i *)out; const __m256i *p_in = (const __m256i *)inp; int i; for (i = 0; i < len; i++) _mm256_store_si256(p_out++, _mm256_load_si256(p_in++)); } /* k0 = - ( m0 ^(-1) mod 2^52 ) */ void ifma_montFactor52_mb4(int64u k0_mb4[4], const int64u m0_mb4[4]) { const __m256i m0 = _mm256_loadu_si256((const __m256i *)&m0_mb4[0]); __m256i y = _mm256_set1_epi64x(1); /* 1 */ __m256i x = _mm256_set1_epi64x(2); /* 2 */ __m256i nx = _mm256_add_epi64(x, x); __m256i mask = _mm256_sub_epi64(nx, y); /* 2*x-1 */ int n; for (n = 2; n <= DIGIT_SIZE; n++ /*, x = nx , nx = nx + nx */) { /* rL = (m0*y) & mask; */ const __m256i rL = _mm256_and_si256(_mm256_madd52lo_epu64(_mm256_setzero_si256(), m0, y), mask); const __m256i mask_ge = _mm256_or_si256(_mm256_cmpeq_epi64(x, rL), _mm256_cmpgt_epi64(x, rL)); /* if( x < (rL & mask) ) < == > x < ((m0*y) mod (2*x)) */ /* y+=x */ /* Note: !GE <==> LT */ y = _mm256_add_epi64(y, _mm256_andnot_si256(mask_ge, x)); /* mask = 2*x-1 */ x = nx; /* x = nx */ nx = _mm256_add_epi64(nx, nx); mask = _mm256_sub_epi64(nx, _mm256_set1_epi64x(1)); } /* return (0-y) */ y = _mm256_sub_epi64(_mm256_setzero_si256(), y); /* trim to 52-bits */ y = _mm256_and_si256(y, _mm256_set1_epi64x(DIGIT_MASK)); _mm256_storeu_si256((__m256i *)k0_mb4, y); } /* r = (a-b) mod m */ __MBX_INLINE void ifma_modsub52xN_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4], const int64u msd_mask, const int len52) { __m256i *pr = (__m256i *)res; const __m256i DIG_MASK = _mm256_set1_epi64x(DIGIT_MASK); const __m256i MSD_MASK = _mm256_set1_epi64x(msd_mask); __m256i T[40]; __m256i R, CARRY, BORROW; int n; assert(len52 <= 40); /* T[] = a[] - b[] */ BORROW = _mm256_setzero_si256(); for (n = 0; n < len52; n++) { const __m256i pa = _mm256_loadu_si256((const __m256i *)&inpA[n][0]); const __m256i pb = _mm256_loadu_si256((const __m256i *)&inpB[n][0]); R = _mm256_sub_epi64(pa, pb); R = _mm256_sub_epi64(R, BORROW); BORROW = _mm256_srli_epi64(R, (64 - 1)); R = _mm256_and_si256(R, DIG_MASK); T[n] = R; } /* correct last digit */ T[len52 - 1] = _mm256_and_si256(R, MSD_MASK); /* masked modulus add: r[] = T[] + BORROW? m[] : 0 */ CARRY = _mm256_setzero_si256(); BORROW = _mm256_sub_epi64(CARRY, BORROW); /* BORROW -> mask */ for (n = 0; n < len52; n++) { const __m256i pm = _mm256_loadu_si256((const __m256i *)&inpM[n][0]); R = _mm256_and_si256(BORROW, pm); R = _mm256_add_epi64(R, T[n]); R = _mm256_add_epi64(R, CARRY); CARRY = _mm256_srli_epi64(R, DIGIT_SIZE); R = _mm256_and_si256(R, DIG_MASK); _mm256_store_si256(&pr[n], R); } /* correct last digit */ R = _mm256_and_si256(R, MSD_MASK); _mm256_store_si256(&pr[len52 - 1], R); } /* r = (a-b) mod m */ void ifma_modsub52x10_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]) { ifma_modsub52xN_mb4(res, inpA, inpB, inpM, MS_DIGIT_MASK(BITSIZE_512, 52), NUMBER_OF_DIGITS(BITSIZE_512, 52)); } void ifma_modsub52x20_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]) { ifma_modsub52xN_mb4(res, inpA, inpB, inpM, MS_DIGIT_MASK(BITSIZE_1024, 52), NUMBER_OF_DIGITS(BITSIZE_1024, 52)); } void ifma_modsub52x30_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]) { ifma_modsub52xN_mb4(res, inpA, inpB, inpM, MS_DIGIT_MASK(BITSIZE_1536, 52), NUMBER_OF_DIGITS(BITSIZE_1536, 52)); } void ifma_modsub52x40_mb4(int64u res[][4], const int64u inpA[][4], const int64u inpB[][4], const int64u inpM[][4]) { ifma_modsub52xN_mb4(res, inpA, inpB, inpM, MS_DIGIT_MASK(BITSIZE_2048, 52), NUMBER_OF_DIGITS(BITSIZE_2048, 52)); } /* r += a*b */ __MBX_INLINE void ifma_addmul52xN_mb4(int64u pRes[][4], const int64u inpA[][4], const int64u inpB[][4], const int len52) { __m256i *pr = (__m256i *)pRes; const __m256i DIG_MASK = _mm256_set1_epi64x(DIGIT_MASK); __m256i R[40]; assert(len52 <= 40); int i; for (i = 0; i < len52; i++) R[i] = pr[i]; for (i = 0; i < len52; i++) { const __m256i *pa = (const __m256i *)inpA; const __m256i *pb = (const __m256i *)&inpB[i][0]; const __m256i Bi = pb[0]; const __m256i nxtR = pr[i + len52]; int j; for (j = 0; j < len52; j++) R[j] = _mm256_madd52lo_epu64(R[j], Bi, pa[j]); /* store normalized result */ pr[i] = _mm256_and_si256(R[0], DIG_MASK); R[1] = _mm256_add_epi64(R[1], _mm256_srli_epi64(R[0], DIGIT_SIZE)); for (j = 0; j < (len52 - 1); j++) R[j] = _mm256_madd52hi_epu64(R[j + 1], Bi, pa[j]); R[j] = _mm256_madd52hi_epu64(nxtR, Bi, pa[j]); } /* normalization */ __m256i T = _mm256_srli_epi64(R[0], DIGIT_SIZE); pr[len52] = _mm256_and_si256(R[0], DIG_MASK); for (i = 1; i < (len52 - 1); i++) { const __m256i C = _mm256_add_epi64(R[i], T); T = _mm256_srli_epi64(C, DIGIT_SIZE); pr[len52 + i] = _mm256_and_si256(C, DIG_MASK); } R[i] = _mm256_add_epi64(R[i], T); pr[len52 + i] = _mm256_and_si256(R[i], DIG_MASK); } /* r += a*b */ void ifma_addmul52x10_mb4(int64u pRes[][4], const int64u inpA[][4], const int64u inpB[][4]) { ifma_addmul52xN_mb4(pRes, inpA, inpB, NUMBER_OF_DIGITS(BITSIZE_512, 52)); } /* r += a*b */ void ifma_addmul52x20_mb4(int64u pRes[][4], const int64u inpA[][4], const int64u inpB[][4]) { ifma_addmul52xN_mb4(pRes, inpA, inpB, NUMBER_OF_DIGITS(BITSIZE_1024, 52)); } /* r += a*b */ void ifma_addmul52x30_mb4(int64u pRes[][4], const int64u inpA[][4], const int64u inpB[][4]) { ifma_addmul52xN_mb4(pRes, inpA, inpB, NUMBER_OF_DIGITS(BITSIZE_1536, 52)); } /* r += a*b */ void ifma_addmul52x40_mb4(int64u pRes[][4], const int64u inpA[][4], const int64u inpB[][4]) { ifma_addmul52xN_mb4(pRes, inpA, inpB, NUMBER_OF_DIGITS(BITSIZE_2048, 52)); } /* r = x * (R^-1) mod q */ __MBX_INLINE void ifma_amred52xN_mb4(int64u res[][4], const int64u inpA[][4], /* int nsA == 2*nsM */ const int64u inpM[][4], /* int nsM == len52 */ const int64u k0[4], const int len52) { const __m256i *pA = (const __m256i *)inpA; const __m256i *pM = (const __m256i *)inpM; __m256i *pR = (__m256i *)res; const __m256i *pK0 = (const __m256i *)k0; const __m256i K = pK0[0]; __m256i R[40]; assert(len52 <= 40); int i; /* load A[nsM-1],...,A[0] */ for (i = 0; i < len52; i++) R[i] = pA[i]; for (i = 0; i < len52; i++) { const __m256i Yi = _mm256_madd52lo_epu64(_mm256_setzero_si256(), R[0], K); const __m256i nxtA = pA[i + len52]; int j; for (j = 0; j < len52; j++) R[j] = _mm256_madd52lo_epu64(R[j], Yi, pM[j]); R[1] = _mm256_add_epi64(R[1], _mm256_srli_epi64(R[0], DIGIT_SIZE)); for (j = 0; j < (len52 - 1); j++) R[j] = _mm256_madd52hi_epu64(R[j + 1], Yi, pM[j]); R[j] = _mm256_madd52hi_epu64(nxtA, Yi, pM[j]); } /* normalization */ __m256i T = _mm256_srli_epi64(R[0], DIGIT_SIZE); const __m256i DIG_MASK = _mm256_set1_epi64x(DIGIT_MASK); pR[0] = _mm256_and_si256(R[0], DIG_MASK); for (i = 1; i < (len52 - 1); i++) { const __m256i C = _mm256_add_epi64(R[i], T); T = _mm256_srli_epi64(C, DIGIT_SIZE); pR[i] = _mm256_and_si256(C, DIG_MASK); } R[i] = _mm256_add_epi64(R[i], T); pR[i] = _mm256_and_si256(R[i], DIG_MASK); } /* r = x * (R^-1) mod q */ void ifma_amred52x10_mb4(int64u res[][4], const int64u inpA[][4], /* int nsA == 2*nsM */ const int64u inpM[][4], /* int nsM == 10 */ const int64u k0[4]) { ifma_amred52xN_mb4(res, inpA, inpM, k0, 10); } void ifma_amred52x20_mb4(int64u res[][4], const int64u inpA[][4], /* int nsA == 2*nsM */ const int64u inpM[][4], /* int nsM == 20 */ const int64u k0[4]) { ifma_amred52xN_mb4(res, inpA, inpM, k0, 20); } void ifma_amred52x30_mb4(int64u res[][4], const int64u inpA[][4], /* int nsA == 2*nsM */ const int64u inpM[][4], /* int nsM == 30 */ const int64u k0[4]) { ifma_amred52xN_mb4(res, inpA, inpM, k0, 30); } void ifma_amred52x40_mb4(int64u res[][4], const int64u inpA[][4], /* int nsA == 2*nsM */ const int64u inpM[][4], /* int nsM == 40 */ const int64u k0[4]) { ifma_amred52xN_mb4(res, inpA, inpM, k0, 40); } ////////////////////////////////////////////////////////////////////// /* * out[] = inp[] << nbit * * nbits < DIGIT_SIZE * out occupied enough memory (at least ns+1) */ static void lshift52x_mb4(int64u pOut[][4], int64u pInp[][4], int ns, const __m256i sbiL) { const __m256i sbiR = _mm256_sub_epi64(_mm256_set1_epi64x(DIGIT_SIZE), sbiL); const __m256i digMask = _mm256_set1_epi64x(DIGIT_MASK); __m256i *in = (__m256i *)pInp; __m256i *out = (__m256i *)pOut; __m256i shiftedR = _mm256_setzero_si256(); int n; for (n = 0; n < ns; n++) { const __m256i in0 = _mm256_loadu_si256(&in[n]); const __m256i k0 = _mm256_or_si256(shiftedR, _mm256_sllv_epi64(in0, sbiL)); const __m256i t0 = _mm256_and_si256(k0, digMask); _mm256_store_si256(&out[n], t0); shiftedR = _mm256_srlv_epi64(in0, sbiR); } } /* out[] = inp[] >> nbit */ static void rshift52x_mb4(int64u pOut[][4], int64u pInp[][4], int ns, const __m256i sbiR) { const __m256i sbiL = _mm256_sub_epi64(_mm256_set1_epi64x(DIGIT_SIZE), sbiR); const __m256i digMask = _mm256_set1_epi64x(DIGIT_MASK); __m256i *in = (__m256i *)pInp; __m256i *out = (__m256i *)pOut; __m256i shiftedL = _mm256_setzero_si256(); int n; for (n = ns; n > 0; n--) { const int i = (n - 1); const __m256i in0 = _mm256_loadu_si256(&in[i]); const __m256i k0 = _mm256_or_si256(shiftedL, _mm256_srlv_epi64(in0, sbiR)); const __m256i t0 = _mm256_and_si256(k0, digMask); _mm256_store_si256(&out[i], t0); shiftedL = _mm256_sllv_epi64(in0, sbiL); } } /* // believe the following works: // // right = {r1:r0} - high and low // left = {l1:l0} - high and low // // if(r1!=l1) // return r1>l1; // else // return r0>l0; */ static __m256i left_gt_right_mb4(const __m256i left_hi, const __m256i left_lo, const __m256i right_hi, const __m256i right_lo) { const __m256i k0 = _mm256_cmpeq_epi64(left_hi, right_hi); const __m256i k1 = _mm256_or_si256(_mm256_andnot_si256(k0, _mm256_cmpgt_epi64(left_hi, right_hi)), _mm256_and_si256(k0, _mm256_cmpgt_epi64(left_lo, right_lo))); return k1; } /* * sub multiplied_by_digit */ static void ifma_sub_muldig52x_mb4(__m256i *pRes, const __m256i *pM, int nsM, const __m256i dig) { const __m256i MASK = _mm256_set1_epi64x(DIGIT_MASK); __m256i prodLO = _mm256_setzero_si256(); __m256i prodHI = _mm256_setzero_si256(); __m256i cf = _mm256_setzero_si256(); __m256i T; int n; /* multiply dig*pM[] and sub from pRes[] */ for (n = 0; n < nsM; n++) { prodLO = _mm256_madd52lo_epu64(prodHI, dig, pM[n]); prodHI = _mm256_madd52hi_epu64(_mm256_setzero_si256(), dig, pM[n]); T = _mm256_sub_epi64(pRes[n], prodLO); T = _mm256_add_epi64(T, cf); cf = _mm256_srai_epi64_wrapper(T, DIGIT_SIZE); T = _mm256_and_si256(T, MASK); pRes[n] = T; } T = _mm256_sub_epi64(pRes[n], prodHI); T = _mm256_add_epi64(T, cf); cf = _mm256_srai_epi64_wrapper(T, DIGIT_SIZE); T = _mm256_and_si256(T, MASK); pRes[n] = T; /* set mask if borrow */ const __m256i k = _mm256_cmpeq_epi64(cf, _mm256_setzero_si256()); /* masked add pM[] */ cf = _mm256_setzero_si256(); for (n = 0; n < nsM; n++) { T = pRes[n]; T = _mm256_or_si256(_mm256_and_si256(k, T), _mm256_andnot_si256(k, _mm256_add_epi64(T, pM[n]))); T = _mm256_add_epi64(T, cf); cf = _mm256_srai_epi64_wrapper(T, DIGIT_SIZE); T = _mm256_and_si256(T, MASK); pRes[n] = T; } T = _mm256_add_epi64(cf, pRes[n]); pRes[n] = T; } // from Cristina // each 64-bit SIMD element should be in the [0, 2^52) range // perform division of (Ah[k]*2^52 + Al[k])/B[k], k=0..7 // Return quotients (as well as remainders via pointer) // Note: There is no checking for B==0 static __m256i __div_104_by_52_256b(__m256i Ah, __m256i Al, __m256i B, __m256i *prem) { __m256i Rem, Qh, Ql; __m256d db, dah, dal, dbr, dqh, dql, dqh2; // limit range of Ah, Al, B inputs to 52 bits (optional?) const __m256i msk52 = _mm256_set1_epi64x(0x00ffffffffffffffULL); B = _mm256_and_si256(B, msk52); Ah = _mm256_and_si256(Ah, msk52); Al = _mm256_and_si256(Al, msk52); // convert inputs to double precision // conversion will be exact db = _mm256_cvtepu64_pd_wrapper(B); dah = _mm256_cvtepu64_pd_wrapper(Ah); dal = _mm256_cvtepu64_pd_wrapper(Al); const int rounding_mode = _MM_GET_ROUNDING_MODE(); // get reciprocal of B, RZ mode const __m256d d_one = _mm256_set1_pd((double)1.0); _MM_SET_ROUNDING_MODE(_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); dbr = _mm256_div_pd(d_one, db); // estimate quotient Qh = (dah*dbr)_RZ ~ Ah/B _MM_SET_ROUNDING_MODE(_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC); dqh = _mm256_mul_pd(dah, dbr); // truncate dqh to integral dqh = _mm256_round_pd(dqh, 3); // get remainder term: dah_new -= dqh*dbh // 0 <= dah_new <= B (due to rounding direction and rounding error magnitude in dbr, dqh) dah = _mm256_fnmadd_pd(db, dqh, dah); // estimate quotient Ql = (dal*dbr)_RZ ~ Al/B dql = _mm256_mul_pd(dal, dbr); // truncate dql to integral dql = _mm256_round_pd(dql, 3); // get remainder term: dal_new -= dql*dbh // 0 <= dal_new <= B (similar to above) dal = _mm256_fnmadd_pd(db, dql, dal); // convert remainder term back to (signed) 64-bit integer Al = _mm256_cvtpd_epi64_wrapper(dal); // scale dah by 2^52 const __m256d two52 = _mm256_set1_pd((double)(1ULL << 52)); dah = _mm256_mul_pd(dah, two52); // estimate quotient Qh2 = ((2^52)*dah)_RU/db dqh2 = _mm256_mul_pd(dah, dbr); _MM_SET_ROUNDING_MODE(rounding_mode); // truncate dqh2 to integral dqh2 = _mm256_round_pd(dqh2, 3); // remainder term: dah_new2 = dah - db*dqh2 // dah_new2 in (-B, 2B) dah = _mm256_fnmadd_pd(db, dqh2, dah); // convert remainder term back to (signed) 64-bit integer Ah = _mm256_cvtpd_epi64_wrapper(dah); // add and convert low quotients: Qh2+Ql dql = _mm256_add_pd(dql, dqh2); Ql = _mm256_cvtpd_epi64_wrapper(dql); // convert high quotient Qh = _mm256_cvtpd_epi64_wrapper(dqh); // remainder term in (-B, 3B) Rem = _mm256_add_epi64(Ah, Al); // Rem < 0? const __m256i sgn_mask = _mm256_srai_epi64_wrapper(Rem, 63); const __m256i B_corr = _mm256_and_si256(B, sgn_mask); // Rem > B? const __m256i corr_ge_mask1 = _mm256_or_si256(_mm256_cmpeq_epi64(Rem, B), _mm256_cmpgt_epi64(Rem, B)); // apply correction if B < 0 Rem = _mm256_add_epi64(Rem, B_corr); Ql = _mm256_add_epi64(Ql, sgn_mask); // if Rem> B, apply correction const __m256i one = _mm256_set1_epi64x(0x0000000000000001ULL); const __m256i Rem_sub_B1 = _mm256_and_si256(_mm256_sub_epi64(Rem, B), corr_ge_mask1); const __m256i Ql_add_one1 = _mm256_and_si256(_mm256_add_epi64(Ql, one), corr_ge_mask1); Rem = _mm256_or_si256(_mm256_andnot_si256(corr_ge_mask1, Rem), Rem_sub_B1); Ql = _mm256_or_si256(_mm256_andnot_si256(corr_ge_mask1, Ql), Ql_add_one1); // Rem > B? const __m256i corr_ge_mask2 = _mm256_or_si256(_mm256_cmpeq_epi64(Rem, B), _mm256_cmpgt_epi64(Rem, B)); // if Rem > B, apply correction // this is the final remainder const __m256i Rem_sub_B2 = _mm256_and_si256(_mm256_sub_epi64(Rem, B), corr_ge_mask2); const __m256i Ql_add_one2 = _mm256_and_si256(_mm256_add_epi64(Ql, one), corr_ge_mask2); *prem = _mm256_or_si256(_mm256_andnot_si256(corr_ge_mask2, Rem), Rem_sub_B2); Ql = _mm256_or_si256(_mm256_andnot_si256(corr_ge_mask2, Ql), Ql_add_one2); // now add the high part of the quotient Qh = _mm256_slli_epi64(Qh, 52); Ql = _mm256_add_epi64(Ql, Qh); return Ql; } /* compute estimation of quotient digit (exactq): q-1 <= exactq <= q */ /* * x0 - top, x1, x2 - bottom * y0 - top (high divisor's digit (B=base52)), y1 - bottom */ static __m256i estimateq_mb4(const __m256i x0, const __m256i x1, const __m256i x2, const __m256i y0, const __m256i y1) { const __m256i base52 = _mm256_set1_epi64x(DIGIT_BASE); const __m256i one = _mm256_set1_epi64x(1); __m256i quo, rem; __m256i left_lo = _mm256_setzero_si256(); __m256i left_hi = _mm256_setzero_si256(); __m256i k1, k0; quo = __div_104_by_52_256b(x0, x1, y0, &rem); /* * compare {y0:y1}*quo and {x0:x1:x2} * left = quo*y1 * right = rem*B + x2 */ left_lo = _mm256_madd52lo_epu64(left_lo, y1, quo); // left = y1*quo left_hi = _mm256_madd52hi_epu64(left_hi, y1, quo); // right = rem*B + x2 => pair of digits {r:x2} // k1 = left>right k1 = left_gt_right_mb4(left_hi, left_lo, rem, x2); // if(left>right) const __m256i quo_sub_one = _mm256_and_si256(_mm256_sub_epi64(quo, one), k1); const __m256i rem_add_y0 = _mm256_and_si256(_mm256_add_epi64(rem, y0), k1); quo = _mm256_or_si256(_mm256_andnot_si256(k1, quo), quo_sub_one); // quo -= 1 rem = _mm256_or_si256(_mm256_andnot_si256(k1, rem), rem_add_y0); // rem += y0 , note "right" increased at the same time k0 = _mm256_and_si256(_mm256_cmpgt_epi64(y1, left_lo), k1); // k0 = left_lo < y1 const __m256i left_lo_sub_y1 = _mm256_and_si256(_mm256_sub_epi64(left_lo, y1), k1); // left -= y1 const __m256i left_hi_sub_one = _mm256_and_si256(_mm256_sub_epi64(left_hi, one), k0); left_lo = _mm256_or_si256(_mm256_andnot_si256(k1, left_lo), left_lo_sub_y1); left_hi = _mm256_or_si256(_mm256_andnot_si256(k0, left_hi), left_hi_sub_one); // k0 = rem < B k0 = _mm256_cmpgt_epi64(base52, rem); // k1 = left>right k1 = _mm256_and_si256(k0, left_gt_right_mb4(left_hi, left_lo, rem, x2)); const __m256i quo_sub_one2 = _mm256_and_si256(_mm256_sub_epi64(quo, one), k1); quo = _mm256_or_si256(_mm256_andnot_si256(k1, quo), quo_sub_one2); // quo -= 1 return quo; } __MBX_INLINE __m256i lzcnt_epi64(const __m256i a) { __m256i lzcnt = _mm256_setzero_si256(); __m256i stop_count = _mm256_setzero_si256(); __m256i vmask = _mm256_set1_epi64x(1ULL << 63); const __m256i vone = _mm256_set1_epi64x(1); int i; for (i = 0; i < 64; i++) { const __m256i is_not_zero = _mm256_cmpeq_epi64(_mm256_and_si256(a, vmask), vmask); stop_count = _mm256_or_si256(stop_count, is_not_zero); if (_mm256_movemask_epi8(stop_count) == 0xffffffff) break; lzcnt = _mm256_or_si256(_mm256_and_si256(stop_count, lzcnt), _mm256_andnot_si256(stop_count, _mm256_add_epi64(lzcnt, vone))); vmask = _mm256_srli_epi64(vmask, 1); } return lzcnt; } /* x = x % m */ void ifma_mreduce52x_mb4(int64u pX[][4], int nsX, int64u pM[][4], int nsM) { /* usually divider have to be normilized */ __m256i *pMtop = (__m256i *)(pM[nsM - 1]); /* top of M */ const __m256i normBits = _mm256_sub_epi64(lzcnt_epi64(pMtop[0]), _mm256_set1_epi64x(64 - DIGIT_SIZE)); /* normalize both divisor and shift dividentr */ lshift52x_mb4(pM, pM, nsM, normBits); /* expand and shift X */ __m256i *pXextend = (__m256i *)&pX[nsX]; pXextend[0] = _mm256_setzero_si256(); lshift52x_mb4(pX, pX, nsX + 1, normBits); // division __m256i *pXtop = (__m256i *)(pX[nsX]); /* top of X (zero value) -- &X[nsX] */ __m256i *pXbot = (__m256i *)(pX[nsX - nsM]); /* bot of X -- &X[nsQ-1] */ while (pXbot >= (__m256i *)pX) { /* compute estimation of quotient digit q */ const __m256i q = estimateq_mb4(pXtop[0], pXtop[-1], pXtop[-2], pMtop[0], pMtop[-1]); /* multiply and sub */ ifma_sub_muldig52x_mb4(pXbot, (__m256i *)pM, nsM, q); /* move by 4x64-bits */ pXtop -= 1; pXbot -= 1; } rshift52x_mb4(pX, pX, nsM, normBits); rshift52x_mb4(pM, pM, nsM, normBits); } /* bitsize of 2^64 representation => bitsize of 2^52 representation */ #define BASE52_BITSIZE(b64bitsize) ((b64bitsize) + ((DIGIT_SIZE - ((b64bitsize) % DIGIT_SIZE)) % DIGIT_SIZE)) /* rr = 2^(2*ifmaBitLen) mod m */ void ifma_montRR52x_mb4(int64u pRR[][4], int64u pM[][4], int convBitLen) { #define MAX_IFMA_MODULUS_BITLEN BASE52_BITSIZE(RSA_4K) /* buffer to hold 2^(2*MAX_IFMA_MODULUS_BITLEN) */ __ALIGN64 int64u pwr2_mb4[(NUMBER_OF_DIGITS(2 * MAX_IFMA_MODULUS_BITLEN + 1, DIGIT_SIZE)) + 1] [4]; /* +1 is necessary extension for ifma_mreduce52x_mb4() purpose */ __m256i *pPwr2_mb4 = (__m256i *)pwr2_mb4; const int ifmaBitLen = BASE52_BITSIZE(convBitLen); const int ifmaLen = NUMBER_OF_DIGITS(ifmaBitLen, DIGIT_SIZE); const int pwr = 2 * ifmaBitLen; const int s = pwr % DIGIT_SIZE; const int pwrLen = NUMBER_OF_DIGITS(pwr + 1, DIGIT_SIZE); /* set 2^(ifmaBitLen*2) */ zero_mb4(pwr2_mb4, pwrLen); const __m256i two_power_s = _mm256_slli_epi64(_mm256_set1_epi64x(1), s); pPwr2_mb4[pwrLen - 1] = two_power_s; /* 2^(ifmaBitLen*2) mod M */ ifma_mreduce52x_mb4(pwr2_mb4, pwrLen, pM, ifmaLen); /* copy result */ int i; __m256i *pR = (__m256i *)pRR; for (i = 0; i < ifmaLen; i++) pR[i] = pPwr2_mb4[i]; #undef MAX_IFMA_MODULUS_BITLEN } /* Normalization without clearing top bits - add bits 52..63 to the next word - each word is 64-bits (multi-buffer 4) Output out_mb4: normalized in_mb Input in_mb4 : input multi-buffer array N : number of words to normalize */ void ifma_normalize_52xN_mb4(void *out_mb4, const void *in_mb4, const int N) { const __m256i *res = (const __m256i *) in_mb4; register __m256i T = _mm256_srli_epi64(res[0], DIGIT_SIZE); __m256i *out = (__m256i *)out_mb4; int i; out[0] = res[0]; for (i = 1; i < (N - 1); i++) { const __m256i C = _mm256_add_epi64(res[i], T); T = _mm256_srli_epi64(C, DIGIT_SIZE); out[i] = C; } out[i] = _mm256_add_epi64(res[i], T); } /* Normalization with clearing top bits - add bits 52..63 to the next word & clear these bits 52..63 in the current word - each word is 64-bits (multi-buffer 4) Output out_mb4: normalized in_mb Input in_mb4 : input multi-buffer array N : number of words to normalize */ void ifma_normalize_clear_52xN_mb4(void *out_mb4, const void *in_mb4, const int N) { const __m256i *res = (const __m256i *) in_mb4; const __m256i DIG_MASK = _mm256_set1_epi64x(DIGIT_MASK); register __m256i T = _mm256_srli_epi64(res[0], DIGIT_SIZE); __m256i *out = (__m256i *)out_mb4; int i; out[0] = _mm256_and_si256(res[0], DIG_MASK); for (i = 1; i < (N - 1); i++) { const __m256i C = _mm256_add_epi64(res[i], T); T = _mm256_srli_epi64(C, DIGIT_SIZE); out[i] = _mm256_and_si256(C, DIG_MASK); } T = _mm256_add_epi64(res[i], T); out[i] = _mm256_and_si256(T, DIG_MASK); } /* Normalization after AMS (clearing the top bits) - carry over top bits of word index N-1 to N - follow with standard normalization from index N and size N ([N..2*N-1]) Output out_mb4: normalized in_mb (N size) Input in_mb4 : input multi-buffer array (2*N size) N : number of words to normalize */ void ifma_normalize_ams_52xN_mb4(void *out_mb4, const void *in_mb4, const int N) { const __m256i DIG_MASK = _mm256_set1_epi64x(DIGIT_MASK); __m256i *out = (__m256i *)out_mb4; const __m256i *res = (const __m256i *)in_mb4; register __m256i T = _mm256_add_epi64(res[N], _mm256_srli_epi64(res[N - 1], DIGIT_SIZE)); int i; out[0] = _mm256_and_si256(T, DIG_MASK); T = _mm256_srli_epi64(T, DIGIT_SIZE); for (i = 1; i < (N - 1); i++) { const __m256i C = _mm256_add_epi64(res[N + i], T); T = _mm256_srli_epi64(C, DIGIT_SIZE); out[i] = _mm256_and_si256(C, DIG_MASK); } T = _mm256_add_epi64(res[N + i], T); out[i] = _mm256_and_si256(T, DIG_MASK); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_layer_mb8.c000066400000000000000000000407601470420105600305010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) /* // public exponent e=65537 implied */ void ifma_cp_rsa_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const n_pa[8], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer) { int len52 = NUMBER_OF_DIGITS(rsaBitlen, DIGIT_SIZE); /* 64-byte aligned buffer of int64[8] */ pint64u_x8 pBuffer_x8 = (pint64u_x8)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb8 buffers */ pint64u_x8 k0_mb8 = pBuffer_x8; pint64u_x8 rr_mb8 = k0_mb8 + 1; pint64u_x8 inout_mb8 = rr_mb8 + len52; pint64u_x8 n_mb8 = inout_mb8 + len52; pint64u_x8 work_buffer = n_mb8 + len52; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(len52, 10)); ifma_BNU_to_mb8(n_mb8, n_pa, rsaBitlen); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8[0], n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, rsaBitlen); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, rsaBitlen); /* exponentiation */ m->expfunc65537( inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8[0], (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, rsaBitlen); } /* // private key */ void ifma_cp_rsa_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const d_pa[8], const int64u *const n_pa[8], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer) { int len52 = NUMBER_OF_DIGITS(rsaBitlen, DIGIT_SIZE); int len64 = NUMBER_OF_DIGITS(rsaBitlen, 64); /* 64-byte aligned buffer of int64[8] */ pint64u_x8 pBuffer_x8 = (pint64u_x8)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb8 buffers */ pint64u_x8 k0_mb8 = pBuffer_x8; pint64u_x8 d_mb8 = k0_mb8 + 1; pint64u_x8 rr_mb8 = d_mb8 + len64; pint64u_x8 inout_mb8 = rr_mb8 + len52; pint64u_x8 n_mb8 = inout_mb8 + len52; pint64u_x8 work_buffer = n_mb8 + len52; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(len52, 10)); ifma_BNU_to_mb8(n_mb8, n_pa, rsaBitlen); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8[0], n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, rsaBitlen); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, rsaBitlen); /* re-arrange exps to ifma */ ifma_BNU_transpose_copy(d_mb8, d_pa, rsaBitlen); /* exponentiation */ m->expfun(inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8[0], (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, rsaBitlen); /* clear exponents */ zero_mb8(d_mb8, len64); } /* // private key (ctr) */ void ifma_cp_rsa_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const p_pa[8], const int64u *const q_pa[8], const int64u *const dp_pa[8], const int64u *const dq_pa[8], const int64u *const iq_pa[8], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer) { int factorBitlen = rsaBitlen / 2; int len52 = NUMBER_OF_DIGITS(factorBitlen, DIGIT_SIZE); int len64 = NUMBER_OF_DIGITS(factorBitlen, 64); /* 64-byte aligned buffer of int64[8] */ pint64u_x8 pBuffer_x8 = (pint64u_x8)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb8 buffers */ pint64u_x8 k0_mb8 = pBuffer_x8; pint64u_x8 p_mb8 = k0_mb8 + 1; pint64u_x8 q_mb8 = p_mb8 + len52; pint64u_x8 d_mb8 = q_mb8 + len52; pint64u_x8 rr_mb8 = d_mb8 + len64; pint64u_x8 xp_mb8 = rr_mb8 + len52; pint64u_x8 xq_mb8 = xp_mb8 + len52; pint64u_x8 inp_mb8 = xq_mb8 + len52; pint64u_x8 work_buffer = inp_mb8 + len52 * 2; /* convert input to ifma fmt */ zero_mb8(inp_mb8, len52 * 2); ifma_HexStr8_to_mb8(inp_mb8, from_pa, rsaBitlen); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BNU_to_mb8(q_mb8, q_pa, factorBitlen); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8[0], q_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, q_mb8, factorBitlen); /* xq = x mod q */ m->amred52x(xq_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])q_mb8, k0_mb8[0]); m->ammul52x((int64u *)xq_mb8, (int64u *)xq_mb8, (int64u *)rr_mb8, (int64u *)q_mb8, k0_mb8[0]); m->modsub52x(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])q_mb8); // ?? /* re-arrange exps to ifma */ ifma_BNU_transpose_copy(d_mb8, dq_pa, factorBitlen); m->expfun(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])rr_mb8, k0_mb8[0], (int64u(*)[8])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BNU_to_mb8(p_mb8, p_pa, factorBitlen); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8[0], p_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, p_mb8, factorBitlen); /* xq = x mod q */ m->amred52x(xp_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])p_mb8, k0_mb8[0]); m->ammul52x((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)rr_mb8, (int64u *)p_mb8, k0_mb8[0]); m->modsub52x(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); // ?? /* re-arrange exps to ifma */ ifma_BNU_transpose_copy(d_mb8, dp_pa, factorBitlen); m->expfun(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])rr_mb8, k0_mb8[0], (int64u(*)[8])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ m->modsub52x(inp_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* for specific case pmodsub52x(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])p_mb8); /* xp = (xp*coef) mod p */ ifma_BNU_to_mb8(inp_mb8, iq_pa, factorBitlen); /* coef */ m->ammul52x((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)rr_mb8, (int64u *)p_mb8, k0_mb8[0]); /* -> mont domain */ m->ammul52x((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)inp_mb8, (int64u *)p_mb8, k0_mb8[0]); /* mmul */ m->modsub52x(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* correction */ /* xp = (xp*q + xq) */ zero_mb8(inp_mb8, len52 * 2); copy_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, len52); m->mla52x(inp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])q_mb8); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inp_mb8, rsaBitlen); /* clear exponents, p, q */ zero_mb8(d_mb8, len64); zero_mb8(q_mb8, len52); zero_mb8(p_mb8, len52); } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) /* // public exponent e=65537 implied */ void ifma_cp_rsa_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const int64u *const n_pa[4], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer) { int len52 = NUMBER_OF_DIGITS(rsaBitlen, DIGIT_SIZE); /* 64-byte aligned buffer of int64[8] */ pint64u_x4 pBuffer_x4 = (pint64u_x4)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb8 buffers */ pint64u_x4 k0_mb4 = pBuffer_x4; pint64u_x4 rr_mb4 = k0_mb4 + 1; pint64u_x4 inout_mb4 = rr_mb4 + len52; pint64u_x4 n_mb4 = inout_mb4 + len52; pint64u_x4 work_buffer = n_mb4 + len52; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(len52, 10)); ifma_BNU_to_mb4(n_mb4, n_pa, rsaBitlen); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4[0], n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, rsaBitlen); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, rsaBitlen); /* exponentiation */ m->expfunc65537( inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4[0], (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, rsaBitlen); } /* // private key */ void ifma_cp_rsa_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const int64u *const d_pa[4], const int64u *const n_pa[4], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer) { int len52 = NUMBER_OF_DIGITS(rsaBitlen, DIGIT_SIZE); int len64 = NUMBER_OF_DIGITS(rsaBitlen, 64); /* 64-byte aligned buffer of int64[4] */ pint64u_x4 pBuffer_x4 = (pint64u_x4)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb4 buffers */ pint64u_x4 k0_mb4 = pBuffer_x4; pint64u_x4 d_mb4 = k0_mb4 + 1; pint64u_x4 rr_mb4 = d_mb4 + len64; pint64u_x4 inout_mb4 = rr_mb4 + len52; pint64u_x4 n_mb4 = inout_mb4 + len52; pint64u_x4 work_buffer = n_mb4 + len52; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(len52, 10)); ifma_BNU_to_mb4(n_mb4, n_pa, rsaBitlen); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4[0], n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, rsaBitlen); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, rsaBitlen); /* re-arrange exps to ifma */ ifma_BNU_transpose_copy_mb4(d_mb4, d_pa, rsaBitlen); /* exponentiation */ m->expfun(inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4[0], (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, rsaBitlen); /* clear exponents */ zero_mb4(d_mb4, len64); } /* // private key (ctr) */ void ifma_cp_rsa_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const int64u *const p_pa[4], const int64u *const q_pa[4], const int64u *const dp_pa[4], const int64u *const dq_pa[4], const int64u *const iq_pa[4], int rsaBitlen, const mbx_RSA_Method *m, int8u *pBuffer) { int factorBitlen = rsaBitlen / 2; int len52 = NUMBER_OF_DIGITS(factorBitlen, DIGIT_SIZE); int len64 = NUMBER_OF_DIGITS(factorBitlen, 64); /* 64-byte aligned buffer of int64[4] */ pint64u_x4 pBuffer_x4 = (pint64u_x4)IFMA_ALIGNED_PTR(pBuffer, 64); /* allocate mb4 buffers */ pint64u_x4 k0_mb4 = pBuffer_x4; pint64u_x4 p_mb4 = k0_mb4 + 1; pint64u_x4 q_mb4 = p_mb4 + len52; pint64u_x4 d_mb4 = q_mb4 + len52; pint64u_x4 rr_mb4 = d_mb4 + len64; pint64u_x4 xp_mb4 = rr_mb4 + len52; pint64u_x4 xq_mb4 = xp_mb4 + len52; pint64u_x4 inp_mb4 = xq_mb4 + len52; pint64u_x4 work_buffer = inp_mb4 + len52 * 2; /* convert input to ifma fmt */ zero_mb4(inp_mb4, len52 * 2); ifma_HexStr4_to_mb4(inp_mb4, from_pa, rsaBitlen); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BNU_to_mb4(q_mb4, q_pa, factorBitlen); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4[0], q_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, q_mb4, factorBitlen); /* xq = x mod q */ m->amred52x(xq_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])q_mb4, k0_mb4[0]); m->ammul52x((int64u *)xq_mb4, (int64u *)xq_mb4, (int64u *)rr_mb4, (int64u *)q_mb4, k0_mb4[0]); m->modsub52x(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])q_mb4); // ?? /* re-arrange exps to ifma */ ifma_BNU_transpose_copy_mb4(d_mb4, dq_pa, factorBitlen); m->expfun(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])rr_mb4, k0_mb4[0], (int64u(*)[4])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BNU_to_mb4(p_mb4, p_pa, factorBitlen); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4[0], p_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, p_mb4, factorBitlen); /* xq = x mod q */ m->amred52x(xp_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])p_mb4, k0_mb4[0]); m->ammul52x((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)rr_mb4, (int64u *)p_mb4, k0_mb4[0]); m->modsub52x(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); // ?? /* re-arrange exps to ifma */ ifma_BNU_transpose_copy_mb4(d_mb4, dp_pa, factorBitlen); m->expfun(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])rr_mb4, k0_mb4[0], (int64u(*)[4])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ m->modsub52x(inp_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* for specific case pmodsub52x(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])p_mb4); /* xp = (xp*coef) mod p */ ifma_BNU_to_mb4(inp_mb4, iq_pa, factorBitlen); /* coef */ m->ammul52x((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)rr_mb4, (int64u *)p_mb4, k0_mb4[0]); /* -> mont domain */ m->ammul52x((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)inp_mb4, (int64u *)p_mb4, k0_mb4[0]); /* mmul */ m->modsub52x(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* correction */ /* xp = (xp*q + xq) */ zero_mb4(inp_mb4, len52 * 2); copy_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, len52); m->mla52x(inp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])q_mb4); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inp_mb4, rsaBitlen); /* clear exponents, p, q */ zero_mb4(d_mb4, len64); zero_mb4(q_mb4, len52); zero_mb4(p_mb4, len52); } #endif /* #if (_MBX >= _MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_mb8.c000066400000000000000000000263011470420105600273000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if !defined(NO_USE_MALLOC) #include #endif // y = x^65537 mod n DLL_PUBLIC mbx_status OWNAPI(mbx_rsa_public_mb8)(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const n_pa[8], int expected_rsa_bitsize, const mbx_RSA_Method *m, int8u *pBuffer) { #if ((_MBX <= _MBX_L9) && !(_MBX_AVX_IFMA_SUPPORTED)) mbx_status status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); return status; #else const mbx_RSA_Method *meth = m; mbx_status status = 0; int buf_no; /* test input pointers */ if (NULL == from_pa || NULL == to_pa || NULL == n_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test rsa modulus size */ if (RSA_1K != expected_rsa_bitsize && RSA_2K != expected_rsa_bitsize && RSA_3K != expected_rsa_bitsize && RSA_4K != expected_rsa_bitsize) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u *inp = from_pa[buf_no]; int8u *out = to_pa[buf_no]; const int64u *n = n_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == inp || NULL == out || NULL == n) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } } /* test method */ if (NULL == meth) { meth = mbx_RSA_pub65537_Method(expected_rsa_bitsize); if (NULL == meth) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } } /* check if requested operation matched to method's */ if (RSA_PUB_KEY != OP_RSA_ID(meth->id)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check if requested RSA matched to method's */ if (expected_rsa_bitsize != BISIZE_RSA_ID(meth->id)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* // processing */ if (MBX_IS_ANY_OK_STS(status)) { int8u *buffer = pBuffer; #if !defined(NO_USE_MALLOC) int allocated_buf = 0; /* check if allocated buffer) */ if (NULL == buffer) { buffer = (int8u *)(malloc(meth->buffSize)); if (NULL == buffer) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } allocated_buf = 1; } #endif #if (_MBX >= _MBX_K1) ifma_cp_rsa_pub_layer_mb8(from_pa, to_pa, n_pa, expected_rsa_bitsize, meth, buffer); #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_cp_rsa_pub_layer_mb4(&from_pa[0], &to_pa[0], &n_pa[0], expected_rsa_bitsize, meth, buffer); ifma_cp_rsa_pub_layer_mb4(&from_pa[4], &to_pa[4], &n_pa[4], expected_rsa_bitsize, meth, buffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX >= _MBX_K1) */ #if !defined(NO_USE_MALLOC) /* release buffer */ if (allocated_buf) free(buffer); #endif } return status; #endif } DLL_PUBLIC mbx_status OWNAPI(mbx_rsa_private_mb8)(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const d_pa[8], const int64u *const n_pa[8], int expected_rsa_bitsize, const mbx_RSA_Method *m, int8u *pBuffer) { #if ((_MBX <= _MBX_L9) && !(_MBX_AVX_IFMA_SUPPORTED)) mbx_status status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); return status; #else const mbx_RSA_Method *meth = m; mbx_status status = 0; int buf_no; /* test input pointers */ if (NULL == from_pa || NULL == to_pa || NULL == d_pa || NULL == n_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test rsa modulus size */ if (RSA_1K != expected_rsa_bitsize && RSA_2K != expected_rsa_bitsize && RSA_3K != expected_rsa_bitsize && RSA_4K != expected_rsa_bitsize) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u *inp = from_pa[buf_no]; int8u *out = to_pa[buf_no]; const int64u *d = d_pa[buf_no]; const int64u *n = n_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == inp || NULL == out || NULL == d || NULL == n) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } } /* test method */ if (NULL == meth) { meth = mbx_RSA_private_Method(expected_rsa_bitsize); if (NULL == meth) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } } /* check if requested operation matched to method's */ if (RSA_PRV2_KEY != OP_RSA_ID(meth->id)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check if requested RSA matched to method's */ if (expected_rsa_bitsize != BISIZE_RSA_ID(meth->id)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* // processing */ if (MBX_IS_ANY_OK_STS(status)) { int8u *buffer = pBuffer; #if !defined(NO_USE_MALLOC) int allocated_buf = 0; /* check if allocated buffer) */ if (NULL == buffer) { buffer = (int8u *)(malloc(meth->buffSize)); if (NULL == buffer) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } allocated_buf = 1; } #endif #if (_MBX >= _MBX_K1) ifma_cp_rsa_prv2_layer_mb8(from_pa, to_pa, d_pa, n_pa, expected_rsa_bitsize, meth, buffer); #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_cp_rsa_prv2_layer_mb4(&from_pa[0], &to_pa[0], &d_pa[0], &n_pa[0], expected_rsa_bitsize, meth, buffer); ifma_cp_rsa_prv2_layer_mb4(&from_pa[4], &to_pa[4], &d_pa[4], &n_pa[4], expected_rsa_bitsize, meth, buffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX >= _MBX_K1) */ #if !defined(NO_USE_MALLOC) /* release buffer */ if (allocated_buf) free(buffer); #endif } return status; #endif } DLL_PUBLIC mbx_status OWNAPI(mbx_rsa_private_crt_mb8)(const int8u *const from_pa[8], int8u *const to_pa[8], const int64u *const p_pa[8], const int64u *const q_pa[8], const int64u *const dp_pa[8], const int64u *const dq_pa[8], const int64u *const iq_pa[8], int expected_rsa_bitsize, const mbx_RSA_Method *m, int8u *pBuffer) { #if ((_MBX <= _MBX_L9) && !(_MBX_AVX_IFMA_SUPPORTED)) mbx_status status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); return status; #else const mbx_RSA_Method *meth = m; mbx_status status = 0; int buf_no; /* test input pointers */ if (NULL == from_pa || NULL == to_pa || NULL == p_pa || NULL == q_pa || NULL == dp_pa || NULL == dq_pa || NULL == iq_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test rsa modulus size */ if (RSA_1K != expected_rsa_bitsize && RSA_2K != expected_rsa_bitsize && RSA_3K != expected_rsa_bitsize && RSA_4K != expected_rsa_bitsize) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u *inp = from_pa[buf_no]; int8u *out = to_pa[buf_no]; const int64u *p = p_pa[buf_no]; const int64u *q = q_pa[buf_no]; const int64u *dp = dp_pa[buf_no]; const int64u *dq = dq_pa[buf_no]; const int64u *iq = iq_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == inp || NULL == out || NULL == q || NULL == p || NULL == dq || NULL == dp || NULL == iq) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } } /* test method */ if (NULL == meth) { meth = mbx_RSA_private_crt_Method(expected_rsa_bitsize); if (NULL == meth) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } } /* check if requested operation matched to method's */ if (RSA_PRV5_KEY != OP_RSA_ID(meth->id)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check if requested RSA matched to method's */ if (expected_rsa_bitsize != BISIZE_RSA_ID(meth->id)) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* // processing */ if (MBX_IS_ANY_OK_STS(status)) { int8u *buffer = pBuffer; #if !defined(NO_USE_MALLOC) int allocated_buf = 0; /* check if allocated buffer) */ if (NULL == buffer) { buffer = (int8u *)(malloc(meth->buffSize)); if (NULL == buffer) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } allocated_buf = 1; } #endif #if (_MBX >= _MBX_K1) ifma_cp_rsa_prv5_layer_mb8(from_pa, to_pa, p_pa, q_pa, dp_pa, dq_pa, iq_pa, expected_rsa_bitsize, meth, buffer); #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_cp_rsa_prv5_layer_mb4(&from_pa[0], &to_pa[0], &p_pa[0], &q_pa[0], &dp_pa[0], &dq_pa[0], &iq_pa[0], expected_rsa_bitsize, meth, buffer); ifma_cp_rsa_prv5_layer_mb4(&from_pa[4], &to_pa[4], &p_pa[4], &q_pa[4], &dp_pa[4], &dq_pa[4], &iq_pa[4], expected_rsa_bitsize, meth, buffer); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX >= _MBX_K1) */ #if !defined(NO_USE_MALLOC) /* release buffer */ if (allocated_buf) free(buffer); #endif } return status; #endif } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_ssl_prv2_layer_mb8.c000066400000000000000000000365571470420105600323440ustar00rootroot00000000000000typedef int to_avoid_translation_unit_is_empty_warning; #ifndef BN_OPENSSL_DISABLE /************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) /* // y = x^d mod n */ void ifma_ssl_rsa1K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x20_mb8(inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); /* clear exponents */ zero_mb8(d_mb8, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa2K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x40_mb8(inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); /* clear exponents */ zero_mb8(d_mb8, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa3K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x60_mb8(inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); /* clear exponents */ zero_mb8(d_mb8, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa4K_prv2_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x79_mb8(inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); /* clear exponents */ zero_mb8(d_mb8, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) /* // y = x^d mod n */ void ifma_ssl_rsa1K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x20_mb4(inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); /* clear exponents */ zero_mb4(d_mb4, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa2K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x40_mb4(inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); /* clear exponents */ zero_mb4(d_mb4, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa3K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x60_mb4(inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); /* clear exponents */ zero_mb4(d_mb4, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa4K_prv2_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const d_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(RSA_BITLEN, 64)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, d_pa, RSA_BITLEN); /* exponentiation */ EXP52x79_mb4(inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); /* clear exponents */ zero_mb4(d_mb4, LEN64); #undef RSA_BITLEN #undef LEN52 #undef LEN64 } #endif /* #if (_MBX >= _MBX_K1) */ #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_ssl_prv2_mb8.c000066400000000000000000000112101470420105600311230ustar00rootroot00000000000000typedef int to_avoid_translation_unit_is_empty_warning; #ifndef BN_OPENSSL_DISABLE /************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 // y = x^d mod n DLL_PUBLIC mbx_status mbx_rsa_private_ssl_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const d_pa[8], const BIGNUM *const n_pa[8], int expected_rsa_bitsize) { mbx_status status = 0; int buf_no; /* test input pointers */ if (NULL == from_pa || NULL == to_pa || NULL == d_pa || NULL == n_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test rsa modulus size */ if (RSA_1K != expected_rsa_bitsize && RSA_2K != expected_rsa_bitsize && RSA_3K != expected_rsa_bitsize && RSA_4K != expected_rsa_bitsize) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u *inp = from_pa[buf_no]; int8u *out = to_pa[buf_no]; const BIGNUM *d = d_pa[buf_no]; const BIGNUM *n = n_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == inp || NULL == out || NULL == d || NULL == n) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } /* check rsa size */ if (expected_rsa_bitsize != BN_num_bits(n)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); continue; } } #if (_MBX >= _MBX_K1) /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { /* select exponentiation */ switch (expected_rsa_bitsize) { case RSA_1K: ifma_ssl_rsa1K_prv2_layer_mb8(from_pa, to_pa, d_pa, n_pa); break; case RSA_2K: ifma_ssl_rsa2K_prv2_layer_mb8(from_pa, to_pa, d_pa, n_pa); break; case RSA_3K: ifma_ssl_rsa3K_prv2_layer_mb8(from_pa, to_pa, d_pa, n_pa); break; case RSA_4K: ifma_ssl_rsa4K_prv2_layer_mb8(from_pa, to_pa, d_pa, n_pa); break; } } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { /* select exponentiation */ switch (expected_rsa_bitsize) { case RSA_1K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa1K_prv2_layer_mb4(&from_pa[0], &to_pa[0], &d_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa1K_prv2_layer_mb4(&from_pa[4], &to_pa[4], &d_pa[4], &n_pa[4]); break; case RSA_2K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa2K_prv2_layer_mb4(&from_pa[0], &to_pa[0], &d_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa2K_prv2_layer_mb4(&from_pa[4], &to_pa[4], &d_pa[4], &n_pa[4]); break; case RSA_3K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa3K_prv2_layer_mb4(&from_pa[0], &to_pa[0], &d_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa3K_prv2_layer_mb4(&from_pa[4], &to_pa[4], &d_pa[4], &n_pa[4]); break; case RSA_4K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa4K_prv2_layer_mb4(&from_pa[0], &to_pa[0], &d_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa4K_prv2_layer_mb4(&from_pa[4], &to_pa[4], &d_pa[4], &n_pa[4]); break; } } #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX >= _MBX_K1) */ return status; } #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_ssl_prv5_layer_mb8.c000066400000000000000000001131711470420105600323330ustar00rootroot00000000000000typedef int to_avoid_translation_unit_is_empty_warning; #ifndef BN_OPENSSL_DISABLE /************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) /* // y = x^d mod n (crt) */ void ifma_ssl_rsa1K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]) { #define RSA_BITLEN (RSA_1K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u p_mb8[LEN52][8]; __ALIGN64 int64u q_mb8[LEN52][8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u xp_mb8[LEN52][8]; __ALIGN64 int64u xq_mb8[LEN52][8]; __ALIGN64 int64u inp_mb8[LEN52 * 2][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert input to ifma fmt */ zero_mb8(inp_mb8, LEN52 * 2); ifma_HexStr8_to_mb8(inp_mb8, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(q_mb8, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, q_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, q_mb8, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x10_mb8(xq_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])q_mb8, k0_mb8); ifma_amm52x10_mb8((int64u *)xq_mb8, (int64u *)xq_mb8, (int64u *)rr_mb8, (int64u *)q_mb8, k0_mb8); ifma_modsub52x10_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])q_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dq_pa, FACTOR_BITLEN); EXP52x10_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(p_mb8, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, p_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, p_mb8, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x10_mb8(xp_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])p_mb8, k0_mb8); ifma_amm52x10_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)rr_mb8, (int64u *)p_mb8, k0_mb8); ifma_modsub52x10_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dp_pa, FACTOR_BITLEN); EXP52x10_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x10_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* for specific case p mont domain */ ifma_amm52x10_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)inp_mb8, (int64u *)p_mb8, k0_mb8); /* mmul */ ifma_modsub52x10_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* correction */ /* xp = (xp*q + xq) */ zero_mb8(inp_mb8, LEN52 * 2); copy_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, LEN52); ifma_addmul52x10_mb8(inp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])q_mb8); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inp_mb8, RSA_BITLEN); /* clear exponents, p, q */ zero_mb8(d_mb8, LEN64); zero_mb8(q_mb8, LEN52); zero_mb8(p_mb8, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa2K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]) { #define RSA_BITLEN (RSA_2K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u p_mb8[LEN52][8]; __ALIGN64 int64u q_mb8[LEN52][8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u xp_mb8[LEN52][8]; __ALIGN64 int64u xq_mb8[LEN52][8]; __ALIGN64 int64u inp_mb8[LEN52 * 2][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert input to ifma fmt */ zero_mb8(inp_mb8, LEN52 * 2); ifma_HexStr8_to_mb8(inp_mb8, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(q_mb8, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, q_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, q_mb8, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x20_mb8(xq_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])q_mb8, k0_mb8); ifma_amm52x20_mb8((int64u *)xq_mb8, (int64u *)xq_mb8, (int64u *)rr_mb8, (int64u *)q_mb8, k0_mb8); ifma_modsub52x20_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])q_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dq_pa, FACTOR_BITLEN); EXP52x20_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(p_mb8, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, p_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, p_mb8, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x20_mb8(xp_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])p_mb8, k0_mb8); ifma_amm52x20_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)rr_mb8, (int64u *)p_mb8, k0_mb8); ifma_modsub52x20_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dp_pa, FACTOR_BITLEN); EXP52x20_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x20_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* for specific case p mont domain */ ifma_amm52x20_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)inp_mb8, (int64u *)p_mb8, k0_mb8); /* mmul */ ifma_modsub52x20_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* correction */ /* xp = (xp*q + xq) */ zero_mb8(inp_mb8, LEN52 * 2); copy_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, LEN52); ifma_addmul52x20_mb8(inp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])q_mb8); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inp_mb8, RSA_BITLEN); /* clear exponents, p, q */ zero_mb8(d_mb8, LEN64); zero_mb8(q_mb8, LEN52); zero_mb8(p_mb8, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa3K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]) { #define RSA_BITLEN (RSA_3K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u p_mb8[LEN52][8]; __ALIGN64 int64u q_mb8[LEN52][8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u xp_mb8[LEN52][8]; __ALIGN64 int64u xq_mb8[LEN52][8]; __ALIGN64 int64u inp_mb8[LEN52 * 2][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert input to ifma fmt */ zero_mb8(inp_mb8, LEN52 * 2); ifma_HexStr8_to_mb8(inp_mb8, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(q_mb8, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, q_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, q_mb8, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x30_mb8(xq_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])q_mb8, k0_mb8); ifma_amm52x30_mb8((int64u *)xq_mb8, (int64u *)xq_mb8, (int64u *)rr_mb8, (int64u *)q_mb8, k0_mb8); ifma_modsub52x30_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])q_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dq_pa, FACTOR_BITLEN); EXP52x30_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(p_mb8, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, p_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, p_mb8, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x30_mb8(xp_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])p_mb8, k0_mb8); ifma_amm52x30_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)rr_mb8, (int64u *)p_mb8, k0_mb8); ifma_modsub52x30_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dp_pa, FACTOR_BITLEN); EXP52x30_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x30_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* for specific case p mont domain */ ifma_amm52x30_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)inp_mb8, (int64u *)p_mb8, k0_mb8); /* mmul */ ifma_modsub52x30_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* correction */ /* xp = (xp*q + xq) */ zero_mb8(inp_mb8, LEN52 * 2); copy_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, LEN52); ifma_addmul52x30_mb8(inp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])q_mb8); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inp_mb8, RSA_BITLEN); /* clear exponents, p, q */ zero_mb8(d_mb8, LEN64); zero_mb8(q_mb8, LEN52); zero_mb8(p_mb8, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa4K_prv5_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8]) { #define RSA_BITLEN (RSA_4K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u p_mb8[LEN52][8]; __ALIGN64 int64u q_mb8[LEN52][8]; __ALIGN64 int64u d_mb8[LEN64][8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u xp_mb8[LEN52][8]; __ALIGN64 int64u xq_mb8[LEN52][8]; __ALIGN64 int64u inp_mb8[LEN52 * 2][8]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][8]; /* convert input to ifma fmt */ zero_mb8(inp_mb8, LEN52 * 2); ifma_HexStr8_to_mb8(inp_mb8, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(q_mb8, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, q_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, q_mb8, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x40_mb8(xq_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])q_mb8, k0_mb8); ifma_amm52x40_mb8((int64u *)xq_mb8, (int64u *)xq_mb8, (int64u *)rr_mb8, (int64u *)q_mb8, k0_mb8); ifma_modsub52x40_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])q_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dq_pa, FACTOR_BITLEN); EXP52x40_mb8(xq_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])q_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb8(p_mb8, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, p_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, p_mb8, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x40_mb8(xp_mb8, (const int64u(*)[8])inp_mb8, (const int64u(*)[8])p_mb8, k0_mb8); ifma_amm52x40_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)rr_mb8, (int64u *)p_mb8, k0_mb8); ifma_modsub52x40_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy(d_mb8, dp_pa, FACTOR_BITLEN); EXP52x40_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])d_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x40_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* for specific case p mont domain */ ifma_amm52x40_mb8((int64u *)xp_mb8, (int64u *)xp_mb8, (int64u *)inp_mb8, (int64u *)p_mb8, k0_mb8); /* mmul */ ifma_modsub52x40_mb8(xp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])p_mb8, (const int64u(*)[8])p_mb8); /* correction */ /* xp = (xp*q + xq) */ zero_mb8(inp_mb8, LEN52 * 2); copy_mb8(inp_mb8, (const int64u(*)[8])xq_mb8, LEN52); ifma_addmul52x40_mb8(inp_mb8, (const int64u(*)[8])xp_mb8, (const int64u(*)[8])q_mb8); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inp_mb8, RSA_BITLEN); /* clear exponents, p, q */ zero_mb8(d_mb8, LEN64); zero_mb8(q_mb8, LEN52); zero_mb8(p_mb8, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #define EXP_WIN_SIZE (5) //(4) #define EXP_WIN_MASK ((1 << EXP_WIN_SIZE) - 1) /* // y = x^d mod n (crt) */ void ifma_ssl_rsa1K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]) { #define RSA_BITLEN (RSA_1K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u p_mb4[LEN52][4]; __ALIGN64 int64u q_mb4[LEN52][4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u xp_mb4[LEN52][4]; __ALIGN64 int64u xq_mb4[LEN52][4]; __ALIGN64 int64u inp_mb4[LEN52 * 2][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert input to ifma fmt */ zero_mb4(inp_mb4, LEN52 * 2); ifma_HexStr4_to_mb4(inp_mb4, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(q_mb4, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, q_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, q_mb4, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x10_mb4(xq_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])q_mb4, k0_mb4); ifma_amm52x10_mb4((int64u *)xq_mb4, (int64u *)xq_mb4, (int64u *)rr_mb4, (int64u *)q_mb4, k0_mb4); ifma_modsub52x10_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])q_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dq_pa, FACTOR_BITLEN); EXP52x10_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(p_mb4, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, p_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, p_mb4, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x10_mb4(xp_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])p_mb4, k0_mb4); ifma_amm52x10_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)rr_mb4, (int64u *)p_mb4, k0_mb4); ifma_modsub52x10_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dp_pa, FACTOR_BITLEN); EXP52x10_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x10_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* for specific case p mont domain */ ifma_amm52x10_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)inp_mb4, (int64u *)p_mb4, k0_mb4); /* mmul */ ifma_modsub52x10_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* correction */ /* xp = (xp*q + xq) */ zero_mb4(inp_mb4, LEN52 * 2); copy_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, LEN52); ifma_addmul52x10_mb4(inp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])q_mb4); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inp_mb4, RSA_BITLEN); /* clear exponents, p, q */ zero_mb4(d_mb4, LEN64); zero_mb4(q_mb4, LEN52); zero_mb4(p_mb4, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa2K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]) { #define RSA_BITLEN (RSA_2K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u p_mb4[LEN52][4]; __ALIGN64 int64u q_mb4[LEN52][4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u xp_mb4[LEN52][4]; __ALIGN64 int64u xq_mb4[LEN52][4]; __ALIGN64 int64u inp_mb4[LEN52 * 2][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert input to ifma fmt */ zero_mb4(inp_mb4, LEN52 * 2); ifma_HexStr4_to_mb4(inp_mb4, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(q_mb4, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, q_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, q_mb4, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x20_mb4(xq_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])q_mb4, k0_mb4); ifma_amm52x20_mb4((int64u *)xq_mb4, (int64u *)xq_mb4, (int64u *)rr_mb4, (int64u *)q_mb4, k0_mb4); ifma_modsub52x20_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])q_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dq_pa, FACTOR_BITLEN); EXP52x20_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(p_mb4, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, p_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, p_mb4, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x20_mb4(xp_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])p_mb4, k0_mb4); ifma_amm52x20_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)rr_mb4, (int64u *)p_mb4, k0_mb4); ifma_modsub52x20_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dp_pa, FACTOR_BITLEN); EXP52x20_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x20_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* for specific case p mont domain */ ifma_amm52x20_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)inp_mb4, (int64u *)p_mb4, k0_mb4); /* mmul */ ifma_modsub52x20_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* correction */ /* xp = (xp*q + xq) */ zero_mb4(inp_mb4, LEN52 * 2); copy_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, LEN52); ifma_addmul52x20_mb4(inp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])q_mb4); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inp_mb4, RSA_BITLEN); /* clear exponents, p, q */ zero_mb4(d_mb4, LEN64); zero_mb4(q_mb4, LEN52); zero_mb4(p_mb4, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa3K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]) { #define RSA_BITLEN (RSA_3K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u p_mb4[LEN52][4]; __ALIGN64 int64u q_mb4[LEN52][4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u xp_mb4[LEN52][4]; __ALIGN64 int64u xq_mb4[LEN52][4]; __ALIGN64 int64u inp_mb4[LEN52 * 2][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert input to ifma fmt */ zero_mb4(inp_mb4, LEN52 * 2); ifma_HexStr4_to_mb4(inp_mb4, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(q_mb4, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, q_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, q_mb4, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x30_mb4(xq_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])q_mb4, k0_mb4); ifma_amm52x30_mb4((int64u *)xq_mb4, (int64u *)xq_mb4, (int64u *)rr_mb4, (int64u *)q_mb4, k0_mb4); ifma_modsub52x30_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])q_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dq_pa, FACTOR_BITLEN); EXP52x30_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(p_mb4, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, p_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, p_mb4, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x30_mb4(xp_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])p_mb4, k0_mb4); ifma_amm52x30_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)rr_mb4, (int64u *)p_mb4, k0_mb4); ifma_modsub52x30_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dp_pa, FACTOR_BITLEN); EXP52x30_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x30_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* for specific case p mont domain */ ifma_amm52x30_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)inp_mb4, (int64u *)p_mb4, k0_mb4); /* mmul */ ifma_modsub52x30_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* correction */ /* xp = (xp*q + xq) */ zero_mb4(inp_mb4, LEN52 * 2); copy_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, LEN52); ifma_addmul52x30_mb4(inp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])q_mb4); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inp_mb4, RSA_BITLEN); /* clear exponents, p, q */ zero_mb4(d_mb4, LEN64); zero_mb4(q_mb4, LEN52); zero_mb4(p_mb4, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } void ifma_ssl_rsa4K_prv5_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const p_pa[4], const BIGNUM *const q_pa[4], const BIGNUM *const dp_pa[4], const BIGNUM *const dq_pa[4], const BIGNUM *const iq_pa[4]) { #define RSA_BITLEN (RSA_4K) #define FACTOR_BITLEN (RSA_BITLEN / 2) #define LEN52 (NUMBER_OF_DIGITS(FACTOR_BITLEN, DIGIT_SIZE)) #define LEN64 (NUMBER_OF_DIGITS(FACTOR_BITLEN, 64)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u p_mb4[LEN52][4]; __ALIGN64 int64u q_mb4[LEN52][4]; __ALIGN64 int64u d_mb4[LEN64][4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u xp_mb4[LEN52][4]; __ALIGN64 int64u xq_mb4[LEN52][4]; __ALIGN64 int64u inp_mb4[LEN52 * 2][4]; /* allocate stack for red(undant) result, multiplier, for exponent X and for pre-computed table of base powers */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1 + (LEN64 + 1) + (1 << EXP_WIN_SIZE) * LEN52][4]; /* convert input to ifma fmt */ zero_mb4(inp_mb4, LEN52 * 2); ifma_HexStr4_to_mb4(inp_mb4, from_pa, RSA_BITLEN); /* // q exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(q_mb4, q_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, q_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, q_mb4, FACTOR_BITLEN); /* xq = x mod q */ ifma_amred52x40_mb4(xq_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])q_mb4, k0_mb4); ifma_amm52x40_mb4((int64u *)xq_mb4, (int64u *)xq_mb4, (int64u *)rr_mb4, (int64u *)q_mb4, k0_mb4); ifma_modsub52x40_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])q_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dq_pa, FACTOR_BITLEN); EXP52x40_mb4(xq_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])q_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // p exponentiation */ /* convert modulus to ifma fmt */ ifma_BN_to_mb4(p_mb4, p_pa, FACTOR_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, p_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, p_mb4, FACTOR_BITLEN); /* xp = x mod p */ ifma_amred52x40_mb4(xp_mb4, (const int64u(*)[4])inp_mb4, (const int64u(*)[4])p_mb4, k0_mb4); ifma_amm52x40_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)rr_mb4, (int64u *)p_mb4, k0_mb4); ifma_modsub52x40_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); // ?? /* re-arrange exps to ifma */ ifma_BN_transpose_copy_mb4(d_mb4, dp_pa, FACTOR_BITLEN); EXP52x40_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])d_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* // crt recombination */ /* xp = (xp-xq) mod p */ ifma_modsub52x40_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* for specific case p mont domain */ ifma_amm52x40_mb4((int64u *)xp_mb4, (int64u *)xp_mb4, (int64u *)inp_mb4, (int64u *)p_mb4, k0_mb4); /* mmul */ ifma_modsub52x40_mb4(xp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])p_mb4, (const int64u(*)[4])p_mb4); /* correction */ /* xp = (xp*q + xq) */ zero_mb4(inp_mb4, LEN52 * 2); copy_mb4(inp_mb4, (const int64u(*)[4])xq_mb4, LEN52); ifma_addmul52x40_mb4(inp_mb4, (const int64u(*)[4])xp_mb4, (const int64u(*)[4])q_mb4); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inp_mb4, RSA_BITLEN); /* clear exponents, p, q */ zero_mb4(d_mb4, LEN64); zero_mb4(q_mb4, LEN52); zero_mb4(p_mb4, LEN52); #undef RSA_BITLEN #undef FACTOR_BITLEN #undef LEN52 #undef LEN64 } #endif /* #if (_MBX >= _MBX_K1) */ #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_ssl_prv5_mb8.c000066400000000000000000000130541470420105600311360ustar00rootroot00000000000000typedef int to_avoid_translation_unit_is_empty_warning; #ifndef BN_OPENSSL_DISABLE /************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 // y = x^d mod n (crt) DLL_PUBLIC mbx_status mbx_rsa_private_crt_ssl_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const p_pa[8], const BIGNUM *const q_pa[8], const BIGNUM *const dp_pa[8], const BIGNUM *const dq_pa[8], const BIGNUM *const iq_pa[8], int expected_rsa_bitsize) { mbx_status status = 0; int buf_no; /* test input pointers */ if (NULL == from_pa || NULL == to_pa || NULL == p_pa || NULL == q_pa || NULL == dp_pa || NULL == dq_pa || NULL == iq_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test rsa modulus size */ if (RSA_1K != expected_rsa_bitsize && RSA_2K != expected_rsa_bitsize && RSA_3K != expected_rsa_bitsize && RSA_4K != expected_rsa_bitsize) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u *inp = from_pa[buf_no]; int8u *out = to_pa[buf_no]; const BIGNUM *q = q_pa[buf_no]; const BIGNUM *p = p_pa[buf_no]; const BIGNUM *dq = dq_pa[buf_no]; const BIGNUM *dp = dp_pa[buf_no]; const BIGNUM *iq = iq_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == inp || NULL == out || NULL == q || NULL == p || NULL == dq || NULL == dp || NULL == iq) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } /* check rsa's factors */ if (((expected_rsa_bitsize / 2) != BN_num_bits(p)) || ((expected_rsa_bitsize / 2) != BN_num_bits(q))) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); continue; } } #if (_MBX >= _MBX_K1) /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { // int factor_bitsize = expected_rsa_bitsize/2; /* select exponentiation and other functions */ switch (expected_rsa_bitsize) { case RSA_1K: ifma_ssl_rsa1K_prv5_layer_mb8(from_pa, to_pa, p_pa, q_pa, dp_pa, dq_pa, iq_pa); break; case RSA_2K: ifma_ssl_rsa2K_prv5_layer_mb8(from_pa, to_pa, p_pa, q_pa, dp_pa, dq_pa, iq_pa); break; case RSA_3K: ifma_ssl_rsa3K_prv5_layer_mb8(from_pa, to_pa, p_pa, q_pa, dp_pa, dq_pa, iq_pa); break; case RSA_4K: ifma_ssl_rsa4K_prv5_layer_mb8(from_pa, to_pa, p_pa, q_pa, dp_pa, dq_pa, iq_pa); break; } } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { /* select exponentiation */ switch (expected_rsa_bitsize) { case RSA_1K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa1K_prv5_layer_mb4(&from_pa[0], &to_pa[0], &p_pa[0], &q_pa[0], &dp_pa[0], &dq_pa[0], &iq_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa1K_prv5_layer_mb4(&from_pa[4], &to_pa[4], &p_pa[4], &q_pa[4], &dp_pa[4], &dq_pa[4], &iq_pa[4]); break; case RSA_2K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa2K_prv5_layer_mb4(&from_pa[0], &to_pa[0], &p_pa[0], &q_pa[0], &dp_pa[0], &dq_pa[0], &iq_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa2K_prv5_layer_mb4(&from_pa[4], &to_pa[4], &p_pa[4], &q_pa[4], &dp_pa[4], &dq_pa[4], &iq_pa[4]); break; case RSA_3K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa3K_prv5_layer_mb4(&from_pa[0], &to_pa[0], &p_pa[0], &q_pa[0], &dp_pa[0], &dq_pa[0], &iq_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa3K_prv5_layer_mb4(&from_pa[4], &to_pa[4], &p_pa[4], &q_pa[4], &dp_pa[4], &dq_pa[4], &iq_pa[4]); break; case RSA_4K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa4K_prv5_layer_mb4(&from_pa[0], &to_pa[0], &p_pa[0], &q_pa[0], &dp_pa[0], &dq_pa[0], &iq_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa4K_prv5_layer_mb4(&from_pa[4], &to_pa[4], &p_pa[4], &q_pa[4], &dp_pa[4], &dq_pa[4], &iq_pa[4]); break; } } #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX >= _MBX_K1) */ return status; } #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_ssl_pub65537_mb8.c000066400000000000000000000113511470420105600314400ustar00rootroot00000000000000typedef int to_avoid_translation_unit_is_empty_warning; #ifndef BN_OPENSSL_DISABLE /************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 // y = x^65537 mod n DLL_PUBLIC mbx_status mbx_rsa_public_ssl_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const e_pa[8], const BIGNUM *const n_pa[8], int expected_rsa_bitsize) { /* check pointers and values */ const int64u expected_pub_exp = 65537; mbx_status status = 0; int buf_no; /* test input pointers */ if (NULL == from_pa || NULL == to_pa || NULL == e_pa || NULL == n_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* test rsa modulus size */ if (RSA_1K != expected_rsa_bitsize && RSA_2K != expected_rsa_bitsize && RSA_3K != expected_rsa_bitsize && RSA_4K != expected_rsa_bitsize) { status = MBX_SET_STS_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* check pointers and values */ for (buf_no = 0; buf_no < 8; buf_no++) { const int8u *inp = from_pa[buf_no]; int8u *out = to_pa[buf_no]; const BIGNUM *e = e_pa[buf_no]; const BIGNUM *n = n_pa[buf_no]; /* if any of pointer NULL set error status */ if (NULL == inp || NULL == out || NULL == e || NULL == n) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } /* check public exponent */ if (!BN_is_word(e, expected_pub_exp)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); continue; } /* check rsa size */ if (expected_rsa_bitsize != BN_num_bits(n)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); continue; } } #if (_MBX >= _MBX_K1) /* continue processing if there are correct parameters */ if (MBX_IS_ANY_OK_STS(status)) { /* use suitable implementation */ switch (expected_rsa_bitsize) { case RSA_1K: ifma_ssl_rsa1K_pub_layer_mb8(from_pa, to_pa, n_pa); break; case RSA_2K: ifma_ssl_rsa2K_pub_layer_mb8(from_pa, to_pa, n_pa); break; case RSA_3K: ifma_ssl_rsa3K_pub_layer_mb8(from_pa, to_pa, n_pa); break; case RSA_4K: ifma_ssl_rsa4K_pub_layer_mb8(from_pa, to_pa, n_pa); break; } } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) if (MBX_IS_ANY_OK_STS(status)) { /* use suitable implementation */ switch (expected_rsa_bitsize) { case RSA_1K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa1K_pub_layer_mb4(&from_pa[0], &to_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa1K_pub_layer_mb4(&from_pa[4], &to_pa[4], &n_pa[4]); break; case RSA_2K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa2K_pub_layer_mb4(&from_pa[0], &to_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa2K_pub_layer_mb4(&from_pa[4], &to_pa[4], &n_pa[4]); break; case RSA_3K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa3K_pub_layer_mb4(&from_pa[0], &to_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa3K_pub_layer_mb4(&from_pa[4], &to_pa[4], &n_pa[4]); break; case RSA_4K: if (MBX_IS_ANY_0_TO_3_OK_STS(status)) ifma_ssl_rsa4K_pub_layer_mb4(&from_pa[0], &to_pa[0], &n_pa[0]); if (MBX_IS_ANY_4_TO_7_OK_STS(status)) ifma_ssl_rsa4K_pub_layer_mb4(&from_pa[4], &to_pa[4], &n_pa[4]); break; } } #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX >= _MBX_K1) */ return status; } #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/ifma_rsa_ssl_pub_layer_mb8.c000066400000000000000000000267731470420105600322400ustar00rootroot00000000000000typedef int to_avoid_translation_unit_is_empty_warning; #ifndef BN_OPENSSL_DISABLE /************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) /* // public exponent e=65537 implied */ void ifma_ssl_rsa1K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x20_pub65537_mb8( inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } void ifma_ssl_rsa2K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x40_pub65537_mb8( inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } void ifma_ssl_rsa3K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x60_pub65537_mb8( inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } void ifma_ssl_rsa4K_pub_layer_mb8(const int8u *const from_pa[8], int8u *const to_pa[8], const BIGNUM *const n_pa[8]) { #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb8 buffers */ __ALIGN64 int64u k0_mb8[8]; __ALIGN64 int64u rr_mb8[LEN52][8]; __ALIGN64 int64u inout_mb8[LEN52][8]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb8() implementation specific */ __ALIGN64 int64u n_mb8[MULTIPLE_OF(LEN52, 10)][8]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1][8]; /* convert modulus to ifma fmt */ zero_mb8(n_mb8, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb8(n_mb8, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb8(k0_mb8, n_mb8[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb8(rr_mb8, n_mb8, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr8_to_mb8(inout_mb8, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x79_pub65537_mb8( inout_mb8, (const int64u(*)[8])inout_mb8, (const int64u(*)[8])n_mb8, (const int64u(*)[8])rr_mb8, k0_mb8, (int64u(*)[8])work_buffer); /* convert result from ifma fmt */ ifma_mb8_to_HexStr8(to_pa, (const int64u(*)[8])inout_mb8, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } #elif ((_MBX >= _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) /* // public exponent e=65537 implied */ void ifma_ssl_rsa1K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_1K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x20_pub65537_mb4( inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } void ifma_ssl_rsa2K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_2K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x40_pub65537_mb4( inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } void ifma_ssl_rsa3K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_3K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x60_pub65537_mb4( inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } void ifma_ssl_rsa4K_pub_layer_mb4(const int8u *const from_pa[4], int8u *const to_pa[4], const BIGNUM *const n_pa[4]) { #define RSA_BITLEN (RSA_4K) #define LEN52 (NUMBER_OF_DIGITS(RSA_BITLEN, DIGIT_SIZE)) /* allocate mb4 buffers */ __ALIGN64 int64u k0_mb4[4]; __ALIGN64 int64u rr_mb4[LEN52][4]; __ALIGN64 int64u inout_mb4[LEN52][4]; /* MULTIPLE_OF_10 because of AMS5x52x79_diagonal_mb4() implementation specific */ __ALIGN64 int64u n_mb4[MULTIPLE_OF(LEN52, 10)][4]; /* allocate stack for red(undant) result and multiplier */ __ALIGN64 int64u work_buffer[LEN52 * 2 + 1][4]; /* convert modulus to ifma fmt */ zero_mb4(n_mb4, MULTIPLE_OF(LEN52, 10)); ifma_BN_to_mb4(n_mb4, n_pa, RSA_BITLEN); /* compute k0[] */ ifma_montFactor52_mb4(k0_mb4, n_mb4[0]); /* compute to_Montgomery domain converters */ ifma_montRR52x_mb4(rr_mb4, n_mb4, RSA_BITLEN); /* convert input to ifma fmt */ ifma_HexStr4_to_mb4(inout_mb4, from_pa, RSA_BITLEN); /* exponentiation */ EXP52x79_pub65537_mb4( inout_mb4, (const int64u(*)[4])inout_mb4, (const int64u(*)[4])n_mb4, (const int64u(*)[4])rr_mb4, k0_mb4, (int64u(*)[4])work_buffer); /* convert result from ifma fmt */ ifma_mb4_to_HexStr4(to_pa, (const int64u(*)[4])inout_mb4, RSA_BITLEN); #undef RSA_BITLEN #undef LEN52 } #endif /* #if (_MBX >= _MBX_K1) */ #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/000077500000000000000000000000001470420105600273575ustar00rootroot00000000000000AMS4x52x20_diagonal_stitched_with_extract_mb4.c000066400000000000000000000100201470420105600401060ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2023-2024 Intel Corporation * * 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 /* Two independent functions are stitched: - 4 squarings - Extracting values from the precomputed tables MulTbl and MulTblx For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void AMS4x52x20_diagonal_stitched_with_extract_mb4(int64u *out_mb, U64 *mulb, U64 *mulbx, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb, int64u MulTbl[][redLen2K][4], int64u MulTblx[][redLen2K][4], const __m256i idx_target0) { const int N = 20; const size_t N_x4_sz = (N * 4 * sizeof(uint64_t)); const __m256i *pMulTbl = (const __m256i *)&MulTbl[0][0]; const __m256i *pMulTblx = (const __m256i *)&MulTblx[0][0]; for (int iter = 0; iter < 4; ++iter) { /* square */ AMS52x20_diagonal_mb4(out_mb, inpA_mb, inpM_mb, k0_mb); inpA_mb = out_mb; //*******BEGIN EXTRACTION CODE SEGMENT****************************// extract_mb4((__m256i *)mulb, pMulTbl, iter, idx_target0, N); extract_mb4((__m256i *)mulbx, pMulTblx, iter, idx_target0, N); pMulTbl += ((4 * N_x4_sz) / sizeof(__m256i)); pMulTblx += ((4 * N_x4_sz) / sizeof(__m256i)); //*******END EXTRACTION CODE SEGMENT******************************// } } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) AMS4x52x30_diagonal_stitched_with_extract_mb4.c000066400000000000000000000100131470420105600401110ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 /* Two independent functions are stitched: - 4 squarings - Extracting values from the precomputed tables MulTbl and MulTblx For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void AMS4x52x30_diagonal_stitched_with_extract_mb4(int64u *out_mb, U64 *mulb, U64 *mulbx, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb, int64u MulTbl[][redLen3K][4], int64u MulTblx[][redLen3K][4], const __m256i idx_target0) { const int N = 30; const size_t N_x4_sz = (N * 4 * sizeof(uint64_t)); const __m256i *pMulTbl = (const __m256i *)&MulTbl[0][0]; const __m256i *pMulTblx = (const __m256i *)&MulTblx[0][0]; for (int iter = 0; iter < 4; ++iter) { /* square */ AMS52x30_diagonal_mb4(out_mb, inpA_mb, inpM_mb, k0_mb); inpA_mb = out_mb; //*******BEGIN EXTRACTION CODE SEGMENT****************************// extract_mb4((__m256i *)mulb, pMulTbl, iter, idx_target0, N); extract_mb4((__m256i *)mulbx, pMulTblx, iter, idx_target0, N); pMulTbl += ((4 * N_x4_sz) / sizeof(__m256i)); pMulTblx += ((4 * N_x4_sz) / sizeof(__m256i)); //*******END EXTRACTION CODE SEGMENT******************************// } } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) AMS4x52x40_diagonal_stitched_with_extract_mb4.c000066400000000000000000000100131470420105600401120ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 /* Two independent functions are stitched: - 4 squarings - Extracting values from the precomputed tables MulTbl and MulTblx For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void AMS4x52x40_diagonal_stitched_with_extract_mb4(int64u *out_mb, U64 *mulb, U64 *mulbx, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb, int64u MulTbl[][redLen4K][4], int64u MulTblx[][redLen4K][4], const __m256i idx_target0) { const int N = 40; const size_t N_x4_sz = (N * 4 * sizeof(uint64_t)); const __m256i *pMulTbl = (const __m256i *)&MulTbl[0][0]; const __m256i *pMulTblx = (const __m256i *)&MulTblx[0][0]; for (int iter = 0; iter < 4; ++iter) { /* square */ AMS52x40_diagonal_mb4(out_mb, inpA_mb, inpM_mb, k0_mb); inpA_mb = out_mb; //*******BEGIN EXTRACTION CODE SEGMENT****************************// extract_mb4((__m256i *)mulb, pMulTbl, iter, idx_target0, N); extract_mb4((__m256i *)mulbx, pMulTblx, iter, idx_target0, N); pMulTbl += ((4 * N_x4_sz) / sizeof(__m256i)); pMulTblx += ((4 * N_x4_sz) / sizeof(__m256i)); //*******END EXTRACTION CODE SEGMENT******************************// } } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_ahmm52x20_mb4.c000066400000000000000000000025161470420105600327100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_ahmm52x20_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpBx_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_ahmm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpBx_mb, inpM_mb, k0_mb, 20); } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_ahmm52x30_mb4.c000066400000000000000000000025111470420105600327040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_ahmm52x30_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpBx_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_ahmm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpBx_mb, inpM_mb, k0_mb, 30); } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_ahmm52x40_mb4.c000066400000000000000000000025121470420105600327060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_ahmm52x40_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpBx_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_ahmm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpBx_mb, inpM_mb, k0_mb, 40); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_ahmr52x20_mb4.c000066400000000000000000000022241470420105600327110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_ahmr52x20_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_ahmr52xN_mb4(out_mb, inpA_mb, inpM_mb, k0_mb, 20); } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_ahmr52x30_mb4.c000066400000000000000000000022201470420105600327060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_ahmr52x30_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_ahmr52xN_mb4(out_mb, inpA_mb, inpM_mb, k0_mb, 30); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_ahmr52x40_mb4.c000066400000000000000000000022201470420105600327070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_ahmr52x40_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_ahmr52xN_mb4(out_mb, inpA_mb, inpM_mb, k0_mb, 40); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_amm52x10_mb4.c000066400000000000000000000022121470420105600325300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_amm52x10_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_amm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpM_mb, k0_mb, 10); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_amm52x20_mb4.c000066400000000000000000000022121470420105600325310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_amm52x20_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_amm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpM_mb, k0_mb, 20); } #endif //#if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_amm52x30_mb4.c000066400000000000000000000022131470420105600325330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_amm52x30_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_amm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpM_mb, k0_mb, 30); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_amm52x40_mb4.c000066400000000000000000000022131470420105600325340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_amm52x40_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_amm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpM_mb, k0_mb, 40); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_amm52x60_mb4.c000066400000000000000000000022131470420105600325360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_amm52x60_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_amm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpM_mb, k0_mb, 60); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/ifma_amm52x79_mb4.c000066400000000000000000000022131470420105600325500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include void ifma_amm52x79_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { ifma_amm52xN_mb4(out_mb, inpA_mb, inpB_mb, inpM_mb, k0_mb, 79); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_ams52x10_diagonal_mb4.c000066400000000000000000000317671470420105600343360ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include static void ams52x10_square_diagonal_mb4(__m256i *res, const int64u *inpA_mb) { const __m256i *inpA = (const __m256i *)inpA_mb; register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, AL; const int N = 10; const __m256i zero_simd = _mm256_setzero_si256(); // 1st triangle - sum the products, double and square r0 = zero_simd; res[0] = _mm256_madd52lo_epu64(r0, inpA[0], inpA[0]); r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(1) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(2) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(8) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(1) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(2) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(8) AL = inpA[1]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[2]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[3]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[4]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[5]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[6]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[7]); // Sum(8) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[2]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[3]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[4]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[5]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[6]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[7]); // Sum(8) AL = inpA[2]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[3]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[4]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[5]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[6]); // Sum(8) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[3]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[4]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[5]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[6]); // Sum(8) AL = inpA[3]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[4]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[5]); // Sum(8) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[4]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[5]); // Sum(8) r0 = _mm256_add_epi64(r0, r0); // Double(1) r0 = _mm256_madd52hi_epu64(r0, inpA[0], inpA[0]); // Add square(1) res[1] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(2) r1 = _mm256_madd52lo_epu64(r1, inpA[1], inpA[1]); // Add square(2) res[2] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(3) r2 = _mm256_madd52hi_epu64(r2, inpA[1], inpA[1]); // Add square(3) res[3] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(4) r3 = _mm256_madd52lo_epu64(r3, inpA[2], inpA[2]); // Add square(4) res[4] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(5) r4 = _mm256_madd52hi_epu64(r4, inpA[2], inpA[2]); // Add square(5) res[5] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(6) r5 = _mm256_madd52lo_epu64(r5, inpA[3], inpA[3]); // Add square(6) res[6] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(7) r6 = _mm256_madd52hi_epu64(r6, inpA[3], inpA[3]); // Add square(7) res[7] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(8) r7 = _mm256_madd52lo_epu64(r7, inpA[4], inpA[4]); // Add square(8) res[8] = r7; r0 = r8; r1 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(9) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(9) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(9) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(9) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(9) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(9) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(9) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(9) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(9) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(9) AL = inpA[5]; AL = inpA[6]; AL = inpA[7]; r0 = _mm256_add_epi64(r0, r0); // Double(9) r0 = _mm256_madd52hi_epu64(r0, inpA[4], inpA[4]); // Add square(9) res[9] = r0; r0 = r1; res[10] = r0; // finish up 1st triangle ASM("jmp l0\nl0:\n"); // 2nd triangle - sum the products, double and square r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(11) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(12) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(13) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(14) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(15) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(16) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(17) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(18) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(11) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(12) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(13) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(14) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(15) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(16) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(17) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(18) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[2]); // Sum(11) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[3]); // Sum(12) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[4]); // Sum(13) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[5]); // Sum(14) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[6]); // Sum(15) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[7]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[2]); // Sum(11) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[3]); // Sum(12) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[4]); // Sum(13) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[5]); // Sum(14) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[6]); // Sum(15) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[7]); // Sum(16) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[3]); // Sum(11) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[4]); // Sum(12) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[5]); // Sum(13) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[6]); // Sum(14) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[3]); // Sum(11) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[4]); // Sum(12) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[5]); // Sum(13) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[6]); // Sum(14) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[4]); // Sum(11) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[5]); // Sum(12) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[4]); // Sum(11) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[5]); // Sum(12) r0 = _mm256_add_epi64(r0, r0); // Double(10) r0 = _mm256_madd52lo_epu64(r0, inpA[5], inpA[5]); // Add square(10) res[N + 0] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(11) r1 = _mm256_madd52hi_epu64(r1, inpA[5], inpA[5]); // Add square(11) res[N + 1] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(12) r2 = _mm256_madd52lo_epu64(r2, inpA[6], inpA[6]); // Add square(12) res[N + 2] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(13) r3 = _mm256_madd52hi_epu64(r3, inpA[6], inpA[6]); // Add square(13) res[N + 3] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(14) r4 = _mm256_madd52lo_epu64(r4, inpA[7], inpA[7]); // Add square(14) res[N + 4] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(15) r5 = _mm256_madd52hi_epu64(r5, inpA[7], inpA[7]); // Add square(15) res[N + 5] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(16) r6 = _mm256_madd52lo_epu64(r6, inpA[8], inpA[8]); // Add square(16) res[N + 6] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(17) r7 = _mm256_madd52hi_epu64(r7, inpA[8], inpA[8]); // Add square(17) res[N + 7] = r7; r0 = r8; r1 = zero_simd; r0 = _mm256_add_epi64(r0, r0); // Double(18) r0 = _mm256_madd52lo_epu64(r0, inpA[9], inpA[9]); // Add square(18) res[N + 8] = r0; r0 = r1; // finish up doubling res[N + 9] = _mm256_madd52hi_epu64(zero_simd, inpA[9], inpA[9]); } void AMS52x10_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { const int N = 10; __m256i res[10 * 2]; /* Square only */ ams52x10_square_diagonal_mb4(res, inpA_mb); /* Generate u_i and begin reduction */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_ams52x20_diagonal_mb4.c000066400000000000000000001112011470420105600343150ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include static void ams52x20_square_diagonal_mb4(__m256i *res, const int64u *inpA_mb) { const __m256i *inpA = (const __m256i *)inpA_mb; register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, AL; const int N = 20; const __m256i zero_simd = _mm256_setzero_si256(); // 1st triangle - sum the products, double and square r0 = zero_simd; res[0] = _mm256_madd52lo_epu64(r0, inpA[0], inpA[0]); r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(1) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(2) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(8) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(1) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(2) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(8) AL = inpA[1]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[2]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[3]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[4]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[5]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[6]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[7]); // Sum(8) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[2]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[3]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[4]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[5]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[6]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[7]); // Sum(8) AL = inpA[2]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[3]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[4]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[5]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[6]); // Sum(8) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[3]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[4]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[5]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[6]); // Sum(8) AL = inpA[3]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[4]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[5]); // Sum(8) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[4]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[5]); // Sum(8) r0 = _mm256_add_epi64(r0, r0); // Double(1) r0 = _mm256_madd52hi_epu64(r0, inpA[0], inpA[0]); // Add square(1) res[1] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(2) r1 = _mm256_madd52lo_epu64(r1, inpA[1], inpA[1]); // Add square(2) res[2] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(3) r2 = _mm256_madd52hi_epu64(r2, inpA[1], inpA[1]); // Add square(3) res[3] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(4) r3 = _mm256_madd52lo_epu64(r3, inpA[2], inpA[2]); // Add square(4) res[4] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(5) r4 = _mm256_madd52hi_epu64(r4, inpA[2], inpA[2]); // Add square(5) res[5] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(6) r5 = _mm256_madd52lo_epu64(r5, inpA[3], inpA[3]); // Add square(6) res[6] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(7) r6 = _mm256_madd52hi_epu64(r6, inpA[3], inpA[3]); // Add square(7) res[7] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(8) r7 = _mm256_madd52lo_epu64(r7, inpA[4], inpA[4]); // Add square(8) res[8] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(16) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(16) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(16) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(16) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(16) AL = inpA[5]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(16) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(16) AL = inpA[6]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(16) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(16) AL = inpA[7]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(16) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(16) r0 = _mm256_add_epi64(r0, r0); // Double(9) r0 = _mm256_madd52hi_epu64(r0, inpA[4], inpA[4]); // Add square(9) res[9] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(10) r1 = _mm256_madd52lo_epu64(r1, inpA[5], inpA[5]); // Add square(10) res[10] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(11) r2 = _mm256_madd52hi_epu64(r2, inpA[5], inpA[5]); // Add square(11) res[11] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(12) r3 = _mm256_madd52lo_epu64(r3, inpA[6], inpA[6]); // Add square(12) res[12] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(13) r4 = _mm256_madd52hi_epu64(r4, inpA[6], inpA[6]); // Add square(13) res[13] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(14) r5 = _mm256_madd52lo_epu64(r5, inpA[7], inpA[7]); // Add square(14) res[14] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(15) r6 = _mm256_madd52hi_epu64(r6, inpA[7], inpA[7]); // Add square(15) res[15] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(16) r7 = _mm256_madd52lo_epu64(r7, inpA[8], inpA[8]); // Add square(16) res[16] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(19) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(19) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(19) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(19) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(19) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(19) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(19) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(19) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(19) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(19) AL = inpA[9]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(19) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(19) AL = inpA[10]; AL = inpA[11]; r0 = _mm256_add_epi64(r0, r0); // Double(17) r0 = _mm256_madd52hi_epu64(r0, inpA[8], inpA[8]); // Add square(17) res[17] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(18) r1 = _mm256_madd52lo_epu64(r1, inpA[9], inpA[9]); // Add square(18) res[18] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(19) r2 = _mm256_madd52hi_epu64(r2, inpA[9], inpA[9]); // Add square(19) res[19] = r2; r0 = r3; res[20] = r0; // finish up 1st triangle ASM("jmp l0\nl0:\n"); // 2nd triangle - sum the products, double and square r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(26) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(27) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(28) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(26) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(27) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(28) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[2]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[3]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[4]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[5]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[6]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[7]); // Sum(26) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(27) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(28) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[2]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[3]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[4]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[5]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[6]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[7]); // Sum(26) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(27) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(28) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[3]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[4]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[5]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[6]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(26) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(27) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(28) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[3]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[4]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[5]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[6]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(26) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(27) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(28) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[4]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[5]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(26) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(27) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(28) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[4]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[5]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(26) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(27) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(28) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(26) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(27) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(28) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(26) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(27) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(28) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(26) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(27) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(28) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(26) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(27) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(28) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(24) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(25) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(26) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(25) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(26) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(22) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(23) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(22) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(23) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(24) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(21) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(22) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(21) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(22) r0 = _mm256_add_epi64(r0, r0); // Double(20) r0 = _mm256_madd52lo_epu64(r0, inpA[10], inpA[10]); // Add square(20) res[N + 0] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(21) r1 = _mm256_madd52hi_epu64(r1, inpA[10], inpA[10]); // Add square(21) res[N + 1] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(22) r2 = _mm256_madd52lo_epu64(r2, inpA[11], inpA[11]); // Add square(22) res[N + 2] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(23) r3 = _mm256_madd52hi_epu64(r3, inpA[11], inpA[11]); // Add square(23) res[N + 3] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(24) r4 = _mm256_madd52lo_epu64(r4, inpA[12], inpA[12]); // Add square(24) res[N + 4] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(25) r5 = _mm256_madd52hi_epu64(r5, inpA[12], inpA[12]); // Add square(25) res[N + 5] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(26) r6 = _mm256_madd52lo_epu64(r6, inpA[13], inpA[13]); // Add square(26) res[N + 6] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(27) r7 = _mm256_madd52hi_epu64(r7, inpA[13], inpA[13]); // Add square(27) res[N + 7] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(29) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(30) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(31) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(32) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(33) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(34) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(35) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(36) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(29) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(30) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(31) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(32) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(33) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(34) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(35) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(36) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(29) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(30) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(31) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(32) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(33) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(34) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(35) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(36) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(29) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(30) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(31) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(32) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(33) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(34) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(35) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(36) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(29) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(30) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(31) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(32) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(33) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(34) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(29) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(30) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(31) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(32) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(33) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(34) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(29) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(30) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(31) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(29) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(30) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(31) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(32) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(29) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(30) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(29) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(30) r0 = _mm256_add_epi64(r0, r0); // Double(28) r0 = _mm256_madd52lo_epu64(r0, inpA[14], inpA[14]); // Add square(28) res[N + 8] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(29) r1 = _mm256_madd52hi_epu64(r1, inpA[14], inpA[14]); // Add square(29) res[N + 9] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(30) r2 = _mm256_madd52lo_epu64(r2, inpA[15], inpA[15]); // Add square(30) res[N + 10] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(31) r3 = _mm256_madd52hi_epu64(r3, inpA[15], inpA[15]); // Add square(31) res[N + 11] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(32) r4 = _mm256_madd52lo_epu64(r4, inpA[16], inpA[16]); // Add square(32) res[N + 12] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(33) r5 = _mm256_madd52hi_epu64(r5, inpA[16], inpA[16]); // Add square(33) res[N + 13] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(34) r6 = _mm256_madd52lo_epu64(r6, inpA[17], inpA[17]); // Add square(34) res[N + 14] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(35) r7 = _mm256_madd52hi_epu64(r7, inpA[17], inpA[17]); // Add square(35) res[N + 15] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(37) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(37) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(38) r0 = _mm256_add_epi64(r0, r0); // Double(36) r0 = _mm256_madd52lo_epu64(r0, inpA[18], inpA[18]); // Add square(36) res[N + 16] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(37) r1 = _mm256_madd52hi_epu64(r1, inpA[18], inpA[18]); // Add square(37) res[N + 17] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(38) r2 = _mm256_madd52lo_epu64(r2, inpA[19], inpA[19]); // Add square(38) res[N + 18] = r2; r0 = r3; // finish up doubling res[N + 19] = _mm256_madd52hi_epu64(zero_simd, inpA[19], inpA[19]); } void AMS52x20_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { const int N = 20; __m256i res[20 * 2]; /* Square only */ ams52x20_square_diagonal_mb4(res, inpA_mb); /* Generate u_i and begin reduction */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_ams52x30_diagonal_mb4.c000066400000000000000000002227361470420105600343360ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include static void ams52x30_square_diagonal_mb4(__m256i *res, const int64u *inpA_mb) { const __m256i *inpA = (const __m256i *)inpA_mb; register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, AL; const int N = 30; const __m256i zero_simd = _mm256_setzero_si256(); // 1st triangle - sum the products, double and square r0 = zero_simd; res[0] = _mm256_madd52lo_epu64(r0, inpA[0], inpA[0]); r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(1) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(2) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(8) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(1) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(2) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(8) AL = inpA[1]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[2]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[3]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[4]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[5]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[6]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[7]); // Sum(8) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[2]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[3]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[4]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[5]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[6]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[7]); // Sum(8) AL = inpA[2]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[3]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[4]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[5]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[6]); // Sum(8) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[3]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[4]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[5]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[6]); // Sum(8) AL = inpA[3]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[4]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[5]); // Sum(8) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[4]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[5]); // Sum(8) r0 = _mm256_add_epi64(r0, r0); // Double(1) r0 = _mm256_madd52hi_epu64(r0, inpA[0], inpA[0]); // Add square(1) res[1] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(2) r1 = _mm256_madd52lo_epu64(r1, inpA[1], inpA[1]); // Add square(2) res[2] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(3) r2 = _mm256_madd52hi_epu64(r2, inpA[1], inpA[1]); // Add square(3) res[3] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(4) r3 = _mm256_madd52lo_epu64(r3, inpA[2], inpA[2]); // Add square(4) res[4] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(5) r4 = _mm256_madd52hi_epu64(r4, inpA[2], inpA[2]); // Add square(5) res[5] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(6) r5 = _mm256_madd52lo_epu64(r5, inpA[3], inpA[3]); // Add square(6) res[6] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(7) r6 = _mm256_madd52hi_epu64(r6, inpA[3], inpA[3]); // Add square(7) res[7] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(8) r7 = _mm256_madd52lo_epu64(r7, inpA[4], inpA[4]); // Add square(8) res[8] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(16) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(16) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(16) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(16) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(16) AL = inpA[5]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(16) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(16) AL = inpA[6]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(16) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(16) AL = inpA[7]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(16) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(16) r0 = _mm256_add_epi64(r0, r0); // Double(9) r0 = _mm256_madd52hi_epu64(r0, inpA[4], inpA[4]); // Add square(9) res[9] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(10) r1 = _mm256_madd52lo_epu64(r1, inpA[5], inpA[5]); // Add square(10) res[10] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(11) r2 = _mm256_madd52hi_epu64(r2, inpA[5], inpA[5]); // Add square(11) res[11] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(12) r3 = _mm256_madd52lo_epu64(r3, inpA[6], inpA[6]); // Add square(12) res[12] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(13) r4 = _mm256_madd52hi_epu64(r4, inpA[6], inpA[6]); // Add square(13) res[13] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(14) r5 = _mm256_madd52lo_epu64(r5, inpA[7], inpA[7]); // Add square(14) res[14] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(15) r6 = _mm256_madd52hi_epu64(r6, inpA[7], inpA[7]); // Add square(15) res[15] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(16) r7 = _mm256_madd52lo_epu64(r7, inpA[8], inpA[8]); // Add square(16) res[16] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(24) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(24) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(24) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(24) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(24) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(24) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(24) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(24) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(24) AL = inpA[9]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(24) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(24) AL = inpA[10]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(24) AL = inpA[11]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(24) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(24) r0 = _mm256_add_epi64(r0, r0); // Double(17) r0 = _mm256_madd52hi_epu64(r0, inpA[8], inpA[8]); // Add square(17) res[17] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(18) r1 = _mm256_madd52lo_epu64(r1, inpA[9], inpA[9]); // Add square(18) res[18] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(19) r2 = _mm256_madd52hi_epu64(r2, inpA[9], inpA[9]); // Add square(19) res[19] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(20) r3 = _mm256_madd52lo_epu64(r3, inpA[10], inpA[10]); // Add square(20) res[20] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(21) r4 = _mm256_madd52hi_epu64(r4, inpA[10], inpA[10]); // Add square(21) res[21] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(22) r5 = _mm256_madd52lo_epu64(r5, inpA[11], inpA[11]); // Add square(22) res[22] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(23) r6 = _mm256_madd52hi_epu64(r6, inpA[11], inpA[11]); // Add square(23) res[23] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(24) r7 = _mm256_madd52lo_epu64(r7, inpA[12], inpA[12]); // Add square(24) res[24] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(29) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(29) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(29) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(29) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(29) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(29) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(29) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(29) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(29) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(29) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(29) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(29) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(29) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(29) AL = inpA[13]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(29) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(29) AL = inpA[14]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(29) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(29) AL = inpA[15]; r0 = _mm256_add_epi64(r0, r0); // Double(25) r0 = _mm256_madd52hi_epu64(r0, inpA[12], inpA[12]); // Add square(25) res[25] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(26) r1 = _mm256_madd52lo_epu64(r1, inpA[13], inpA[13]); // Add square(26) res[26] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(27) r2 = _mm256_madd52hi_epu64(r2, inpA[13], inpA[13]); // Add square(27) res[27] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(28) r3 = _mm256_madd52lo_epu64(r3, inpA[14], inpA[14]); // Add square(28) res[28] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(29) r4 = _mm256_madd52hi_epu64(r4, inpA[14], inpA[14]); // Add square(29) res[29] = r4; r0 = r5; res[30] = r0; // finish up 1st triangle ASM("jmp l0\nl0:\n"); // 2nd triangle - sum the products, double and square r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(38) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[2]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[3]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[4]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[5]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[6]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[7]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[2]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[3]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[4]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[5]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[6]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[7]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(38) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[3]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[4]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[5]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[6]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[3]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[4]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[5]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[6]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(38) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[4]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[5]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[4]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[5]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(38) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(38) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(38) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(38) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(38) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(38) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(38) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(36) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(37) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(38) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(36) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(37) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(38) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(34) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(35) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(36) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(34) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(35) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(36) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(32) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(33) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(34) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(33) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(34) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(31) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(31) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(32) r0 = _mm256_add_epi64(r0, r0); // Double(30) r0 = _mm256_madd52lo_epu64(r0, inpA[15], inpA[15]); // Add square(30) res[N + 0] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(31) r1 = _mm256_madd52hi_epu64(r1, inpA[15], inpA[15]); // Add square(31) res[N + 1] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(32) r2 = _mm256_madd52lo_epu64(r2, inpA[16], inpA[16]); // Add square(32) res[N + 2] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(33) r3 = _mm256_madd52hi_epu64(r3, inpA[16], inpA[16]); // Add square(33) res[N + 3] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(34) r4 = _mm256_madd52lo_epu64(r4, inpA[17], inpA[17]); // Add square(34) res[N + 4] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(35) r5 = _mm256_madd52hi_epu64(r5, inpA[17], inpA[17]); // Add square(35) res[N + 5] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(36) r6 = _mm256_madd52lo_epu64(r6, inpA[18], inpA[18]); // Add square(36) res[N + 6] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(37) r7 = _mm256_madd52hi_epu64(r7, inpA[18], inpA[18]); // Add square(37) res[N + 7] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(46) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(46) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(46) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(46) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(46) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(46) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(44) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(45) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(44) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(45) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(46) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(42) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(43) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(44) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(42) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(43) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(44) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(40) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(41) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(42) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(41) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(42) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(39) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(39) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(40) r0 = _mm256_add_epi64(r0, r0); // Double(38) r0 = _mm256_madd52lo_epu64(r0, inpA[19], inpA[19]); // Add square(38) res[N + 8] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(39) r1 = _mm256_madd52hi_epu64(r1, inpA[19], inpA[19]); // Add square(39) res[N + 9] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(40) r2 = _mm256_madd52lo_epu64(r2, inpA[20], inpA[20]); // Add square(40) res[N + 10] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(41) r3 = _mm256_madd52hi_epu64(r3, inpA[20], inpA[20]); // Add square(41) res[N + 11] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(42) r4 = _mm256_madd52lo_epu64(r4, inpA[21], inpA[21]); // Add square(42) res[N + 12] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(43) r5 = _mm256_madd52hi_epu64(r5, inpA[21], inpA[21]); // Add square(43) res[N + 13] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(44) r6 = _mm256_madd52lo_epu64(r6, inpA[22], inpA[22]); // Add square(44) res[N + 14] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(45) r7 = _mm256_madd52hi_epu64(r7, inpA[22], inpA[22]); // Add square(45) res[N + 15] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(47) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(48) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(49) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(50) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(51) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(52) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(53) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(54) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(47) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(49) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(50) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(51) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(52) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(53) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(54) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(47) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(48) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(49) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(50) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(51) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(52) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(53) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(54) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(47) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(49) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(50) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(51) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(52) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(53) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(54) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(47) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(48) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(49) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(50) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(51) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(52) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(53) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(54) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(47) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(49) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(50) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(51) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(52) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(53) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(54) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(47) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(48) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(49) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(50) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(51) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(52) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(47) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(49) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(50) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(51) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(52) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(47) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(48) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(49) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(50) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(47) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(49) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(50) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(47) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(47) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(48) r0 = _mm256_add_epi64(r0, r0); // Double(46) r0 = _mm256_madd52lo_epu64(r0, inpA[23], inpA[23]); // Add square(46) res[N + 16] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(47) r1 = _mm256_madd52hi_epu64(r1, inpA[23], inpA[23]); // Add square(47) res[N + 17] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(48) r2 = _mm256_madd52lo_epu64(r2, inpA[24], inpA[24]); // Add square(48) res[N + 18] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(49) r3 = _mm256_madd52hi_epu64(r3, inpA[24], inpA[24]); // Add square(49) res[N + 19] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(50) r4 = _mm256_madd52lo_epu64(r4, inpA[25], inpA[25]); // Add square(50) res[N + 20] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(51) r5 = _mm256_madd52hi_epu64(r5, inpA[25], inpA[25]); // Add square(51) res[N + 21] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(52) r6 = _mm256_madd52lo_epu64(r6, inpA[26], inpA[26]); // Add square(52) res[N + 22] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(53) r7 = _mm256_madd52hi_epu64(r7, inpA[26], inpA[26]); // Add square(53) res[N + 23] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(55) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(56) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(57) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(58) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(55) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(56) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(57) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(58) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(55) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(55) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(56) r0 = _mm256_add_epi64(r0, r0); // Double(54) r0 = _mm256_madd52lo_epu64(r0, inpA[27], inpA[27]); // Add square(54) res[N + 24] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(55) r1 = _mm256_madd52hi_epu64(r1, inpA[27], inpA[27]); // Add square(55) res[N + 25] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(56) r2 = _mm256_madd52lo_epu64(r2, inpA[28], inpA[28]); // Add square(56) res[N + 26] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(57) r3 = _mm256_madd52hi_epu64(r3, inpA[28], inpA[28]); // Add square(57) res[N + 27] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(58) r4 = _mm256_madd52lo_epu64(r4, inpA[29], inpA[29]); // Add square(58) res[N + 28] = r4; r0 = r5; // finish up doubling res[N + 29] = _mm256_madd52hi_epu64(zero_simd, inpA[29], inpA[29]); } void AMS52x30_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { const int N = 30; __m256i res[30 * 2]; /* Square only */ ams52x30_square_diagonal_mb4(res, inpA_mb); /* Generate u_i and begin reduction */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_ams52x40_diagonal_mb4.c000066400000000000000000003672451470420105600343440ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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. *************************************************************************/ /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #include #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include static void ams52x40_square_diagonal_mb4(__m256i *res, const int64u *inpA_mb) { const __m256i *inpA = (const __m256i *)inpA_mb; register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, AL; const int N = 40; const __m256i zero_simd = _mm256_setzero_si256(); // 1st triangle - sum the products, double and square r0 = zero_simd; res[0] = _mm256_madd52lo_epu64(r0, inpA[0], inpA[0]); r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(1) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(2) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(8) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(1) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(2) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(8) AL = inpA[1]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[2]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[3]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[4]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[5]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[6]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[7]); // Sum(8) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[2]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[3]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[4]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[5]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[6]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[7]); // Sum(8) AL = inpA[2]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[3]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[4]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[5]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[6]); // Sum(8) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[3]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[4]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[5]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[6]); // Sum(8) AL = inpA[3]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[4]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[5]); // Sum(8) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[4]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[5]); // Sum(8) r0 = _mm256_add_epi64(r0, r0); // Double(1) r0 = _mm256_madd52hi_epu64(r0, inpA[0], inpA[0]); // Add square(1) res[1] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(2) r1 = _mm256_madd52lo_epu64(r1, inpA[1], inpA[1]); // Add square(2) res[2] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(3) r2 = _mm256_madd52hi_epu64(r2, inpA[1], inpA[1]); // Add square(3) res[3] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(4) r3 = _mm256_madd52lo_epu64(r3, inpA[2], inpA[2]); // Add square(4) res[4] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(5) r4 = _mm256_madd52hi_epu64(r4, inpA[2], inpA[2]); // Add square(5) res[5] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(6) r5 = _mm256_madd52lo_epu64(r5, inpA[3], inpA[3]); // Add square(6) res[6] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(7) r6 = _mm256_madd52hi_epu64(r6, inpA[3], inpA[3]); // Add square(7) res[7] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(8) r7 = _mm256_madd52lo_epu64(r7, inpA[4], inpA[4]); // Add square(8) res[8] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(16) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(16) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(16) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(16) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(16) AL = inpA[5]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(16) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(16) AL = inpA[6]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(16) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(16) AL = inpA[7]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(16) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(16) r0 = _mm256_add_epi64(r0, r0); // Double(9) r0 = _mm256_madd52hi_epu64(r0, inpA[4], inpA[4]); // Add square(9) res[9] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(10) r1 = _mm256_madd52lo_epu64(r1, inpA[5], inpA[5]); // Add square(10) res[10] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(11) r2 = _mm256_madd52hi_epu64(r2, inpA[5], inpA[5]); // Add square(11) res[11] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(12) r3 = _mm256_madd52lo_epu64(r3, inpA[6], inpA[6]); // Add square(12) res[12] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(13) r4 = _mm256_madd52hi_epu64(r4, inpA[6], inpA[6]); // Add square(13) res[13] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(14) r5 = _mm256_madd52lo_epu64(r5, inpA[7], inpA[7]); // Add square(14) res[14] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(15) r6 = _mm256_madd52hi_epu64(r6, inpA[7], inpA[7]); // Add square(15) res[15] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(16) r7 = _mm256_madd52lo_epu64(r7, inpA[8], inpA[8]); // Add square(16) res[16] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(24) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(24) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(24) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(24) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(24) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(24) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(24) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(24) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(24) AL = inpA[9]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(24) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(24) AL = inpA[10]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(24) AL = inpA[11]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(24) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(24) r0 = _mm256_add_epi64(r0, r0); // Double(17) r0 = _mm256_madd52hi_epu64(r0, inpA[8], inpA[8]); // Add square(17) res[17] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(18) r1 = _mm256_madd52lo_epu64(r1, inpA[9], inpA[9]); // Add square(18) res[18] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(19) r2 = _mm256_madd52hi_epu64(r2, inpA[9], inpA[9]); // Add square(19) res[19] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(20) r3 = _mm256_madd52lo_epu64(r3, inpA[10], inpA[10]); // Add square(20) res[20] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(21) r4 = _mm256_madd52hi_epu64(r4, inpA[10], inpA[10]); // Add square(21) res[21] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(22) r5 = _mm256_madd52lo_epu64(r5, inpA[11], inpA[11]); // Add square(22) res[22] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(23) r6 = _mm256_madd52hi_epu64(r6, inpA[11], inpA[11]); // Add square(23) res[23] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(24) r7 = _mm256_madd52lo_epu64(r7, inpA[12], inpA[12]); // Add square(24) res[24] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(32) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(32) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(32) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(32) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(32) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(32) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(32) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(32) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(32) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(32) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(32) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(32) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(32) AL = inpA[13]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(32) AL = inpA[14]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(32) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(32) AL = inpA[15]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(32) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(32) r0 = _mm256_add_epi64(r0, r0); // Double(25) r0 = _mm256_madd52hi_epu64(r0, inpA[12], inpA[12]); // Add square(25) res[25] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(26) r1 = _mm256_madd52lo_epu64(r1, inpA[13], inpA[13]); // Add square(26) res[26] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(27) r2 = _mm256_madd52hi_epu64(r2, inpA[13], inpA[13]); // Add square(27) res[27] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(28) r3 = _mm256_madd52lo_epu64(r3, inpA[14], inpA[14]); // Add square(28) res[28] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(29) r4 = _mm256_madd52hi_epu64(r4, inpA[14], inpA[14]); // Add square(29) res[29] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(30) r5 = _mm256_madd52lo_epu64(r5, inpA[15], inpA[15]); // Add square(30) res[30] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(31) r6 = _mm256_madd52hi_epu64(r6, inpA[15], inpA[15]); // Add square(31) res[31] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(32) r7 = _mm256_madd52lo_epu64(r7, inpA[16], inpA[16]); // Add square(32) res[32] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(39) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(39) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(39) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(39) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(39) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(39) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(39) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(39) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(39) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(39) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(39) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(39) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(39) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(39) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(39) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(39) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(39) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(39) AL = inpA[17]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(39) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(39) AL = inpA[18]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(39) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(39) AL = inpA[19]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(39) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(39) r0 = _mm256_add_epi64(r0, r0); // Double(33) r0 = _mm256_madd52hi_epu64(r0, inpA[16], inpA[16]); // Add square(33) res[33] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(34) r1 = _mm256_madd52lo_epu64(r1, inpA[17], inpA[17]); // Add square(34) res[34] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(35) r2 = _mm256_madd52hi_epu64(r2, inpA[17], inpA[17]); // Add square(35) res[35] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(36) r3 = _mm256_madd52lo_epu64(r3, inpA[18], inpA[18]); // Add square(36) res[36] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(37) r4 = _mm256_madd52hi_epu64(r4, inpA[18], inpA[18]); // Add square(37) res[37] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(38) r5 = _mm256_madd52lo_epu64(r5, inpA[19], inpA[19]); // Add square(38) res[38] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(39) r6 = _mm256_madd52hi_epu64(r6, inpA[19], inpA[19]); // Add square(39) res[39] = r6; r0 = r7; res[40] = r0; // finish up 1st triangle ASM("jmp l0\nl0:\n"); // 2nd triangle - sum the products, double and square r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(48) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[2]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[3]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[4]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[5]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[6]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[7]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[2]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[3]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[4]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[5]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[6]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[7]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(48) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[3]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[4]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[5]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[6]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[3]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[4]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[5]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[6]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(48) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[4]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[5]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[4]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[5]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(48) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(48) AL = inpA[34]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(48) AL = inpA[33]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(48) AL = inpA[32]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(48) AL = inpA[31]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(48) AL = inpA[30]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(48) AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(48) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(48) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(48) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(48) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(48) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(48) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(46) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(46) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(44) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(44) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(42) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(42) r0 = _mm256_add_epi64(r0, r0); // Double(40) r0 = _mm256_madd52lo_epu64(r0, inpA[20], inpA[20]); // Add square(40) res[N + 0] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(41) r1 = _mm256_madd52hi_epu64(r1, inpA[20], inpA[20]); // Add square(41) res[N + 1] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(42) r2 = _mm256_madd52lo_epu64(r2, inpA[21], inpA[21]); // Add square(42) res[N + 2] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(43) r3 = _mm256_madd52hi_epu64(r3, inpA[21], inpA[21]); // Add square(43) res[N + 3] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(44) r4 = _mm256_madd52lo_epu64(r4, inpA[22], inpA[22]); // Add square(44) res[N + 4] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(45) r5 = _mm256_madd52hi_epu64(r5, inpA[22], inpA[22]); // Add square(45) res[N + 5] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(46) r6 = _mm256_madd52lo_epu64(r6, inpA[23], inpA[23]); // Add square(46) res[N + 6] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(47) r7 = _mm256_madd52hi_epu64(r7, inpA[23], inpA[23]); // Add square(47) res[N + 7] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(56) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(56) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(56) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(56) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(56) AL = inpA[34]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(56) AL = inpA[33]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(56) AL = inpA[32]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(56) AL = inpA[31]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(56) AL = inpA[30]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(56) AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(56) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(56) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(54) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(54) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(52) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(52) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(50) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(50) r0 = _mm256_add_epi64(r0, r0); // Double(48) r0 = _mm256_madd52lo_epu64(r0, inpA[24], inpA[24]); // Add square(48) res[N + 8] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(49) r1 = _mm256_madd52hi_epu64(r1, inpA[24], inpA[24]); // Add square(49) res[N + 9] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(50) r2 = _mm256_madd52lo_epu64(r2, inpA[25], inpA[25]); // Add square(50) res[N + 10] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(51) r3 = _mm256_madd52hi_epu64(r3, inpA[25], inpA[25]); // Add square(51) res[N + 11] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(52) r4 = _mm256_madd52lo_epu64(r4, inpA[26], inpA[26]); // Add square(52) res[N + 12] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(53) r5 = _mm256_madd52hi_epu64(r5, inpA[26], inpA[26]); // Add square(53) res[N + 13] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(54) r6 = _mm256_madd52lo_epu64(r6, inpA[27], inpA[27]); // Add square(54) res[N + 14] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(55) r7 = _mm256_madd52hi_epu64(r7, inpA[27], inpA[27]); // Add square(55) res[N + 15] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(64) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(64) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(64) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(64) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(64) AL = inpA[34]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(64) AL = inpA[33]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(64) AL = inpA[32]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(64) AL = inpA[31]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(62) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(62) AL = inpA[30]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(60) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(60) AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(58) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(58) r0 = _mm256_add_epi64(r0, r0); // Double(56) r0 = _mm256_madd52lo_epu64(r0, inpA[28], inpA[28]); // Add square(56) res[N + 16] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(57) r1 = _mm256_madd52hi_epu64(r1, inpA[28], inpA[28]); // Add square(57) res[N + 17] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(58) r2 = _mm256_madd52lo_epu64(r2, inpA[29], inpA[29]); // Add square(58) res[N + 18] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(59) r3 = _mm256_madd52hi_epu64(r3, inpA[29], inpA[29]); // Add square(59) res[N + 19] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(60) r4 = _mm256_madd52lo_epu64(r4, inpA[30], inpA[30]); // Add square(60) res[N + 20] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(61) r5 = _mm256_madd52hi_epu64(r5, inpA[30], inpA[30]); // Add square(61) res[N + 21] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(62) r6 = _mm256_madd52lo_epu64(r6, inpA[31], inpA[31]); // Add square(62) res[N + 22] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(63) r7 = _mm256_madd52hi_epu64(r7, inpA[31], inpA[31]); // Add square(63) res[N + 23] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(72) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(72) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(72) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(72) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(70) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(70) AL = inpA[34]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(68) AL = inpA[33]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(66) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(66) r0 = _mm256_add_epi64(r0, r0); // Double(64) r0 = _mm256_madd52lo_epu64(r0, inpA[32], inpA[32]); // Add square(64) res[N + 24] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(65) r1 = _mm256_madd52hi_epu64(r1, inpA[32], inpA[32]); // Add square(65) res[N + 25] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(66) r2 = _mm256_madd52lo_epu64(r2, inpA[33], inpA[33]); // Add square(66) res[N + 26] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(67) r3 = _mm256_madd52hi_epu64(r3, inpA[33], inpA[33]); // Add square(67) res[N + 27] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(68) r4 = _mm256_madd52lo_epu64(r4, inpA[34], inpA[34]); // Add square(68) res[N + 28] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(69) r5 = _mm256_madd52hi_epu64(r5, inpA[34], inpA[34]); // Add square(69) res[N + 29] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(70) r6 = _mm256_madd52lo_epu64(r6, inpA[35], inpA[35]); // Add square(70) res[N + 30] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(71) r7 = _mm256_madd52hi_epu64(r7, inpA[35], inpA[35]); // Add square(71) res[N + 31] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(78) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(76) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(74) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(74) r0 = _mm256_add_epi64(r0, r0); // Double(72) r0 = _mm256_madd52lo_epu64(r0, inpA[36], inpA[36]); // Add square(72) res[N + 32] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(73) r1 = _mm256_madd52hi_epu64(r1, inpA[36], inpA[36]); // Add square(73) res[N + 33] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(74) r2 = _mm256_madd52lo_epu64(r2, inpA[37], inpA[37]); // Add square(74) res[N + 34] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(75) r3 = _mm256_madd52hi_epu64(r3, inpA[37], inpA[37]); // Add square(75) res[N + 35] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(76) r4 = _mm256_madd52lo_epu64(r4, inpA[38], inpA[38]); // Add square(76) res[N + 36] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(77) r5 = _mm256_madd52hi_epu64(r5, inpA[38], inpA[38]); // Add square(77) res[N + 37] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(78) r6 = _mm256_madd52lo_epu64(r6, inpA[39], inpA[39]); // Add square(78) res[N + 38] = r6; r0 = r7; // finish up doubling res[N + 39] = _mm256_madd52hi_epu64(zero_simd, inpA[39], inpA[39]); } void AMS52x40_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { const int N = 40; __m256i res[40 * 2]; /* Square only */ ams52x40_square_diagonal_mb4(res, inpA_mb); /* Generate u_i and begin reduction */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_ams52x60_diagonal_mb4.c000066400000000000000000010221061470420105600343270ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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. *************************************************************************/ /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #include #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include static void ams52x60_square_diagonal_mb4(__m256i *res, const int64u *inpA_mb) { const __m256i *inpA = (const __m256i *)inpA_mb; register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, AL; const int N = 60; const __m256i zero_simd = _mm256_setzero_si256(); // 1st triangle - sum the products, double and square r0 = zero_simd; res[0] = _mm256_madd52lo_epu64(r0, inpA[0], inpA[0]); r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(1) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(2) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(8) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(1) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(2) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(8) AL = inpA[1]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[2]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[3]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[4]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[5]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[6]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[7]); // Sum(8) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[2]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[3]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[4]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[5]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[6]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[7]); // Sum(8) AL = inpA[2]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[3]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[4]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[5]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[6]); // Sum(8) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[3]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[4]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[5]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[6]); // Sum(8) AL = inpA[3]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[4]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[5]); // Sum(8) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[4]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[5]); // Sum(8) r0 = _mm256_add_epi64(r0, r0); // Double(1) r0 = _mm256_madd52hi_epu64(r0, inpA[0], inpA[0]); // Add square(1) res[1] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(2) r1 = _mm256_madd52lo_epu64(r1, inpA[1], inpA[1]); // Add square(2) res[2] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(3) r2 = _mm256_madd52hi_epu64(r2, inpA[1], inpA[1]); // Add square(3) res[3] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(4) r3 = _mm256_madd52lo_epu64(r3, inpA[2], inpA[2]); // Add square(4) res[4] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(5) r4 = _mm256_madd52hi_epu64(r4, inpA[2], inpA[2]); // Add square(5) res[5] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(6) r5 = _mm256_madd52lo_epu64(r5, inpA[3], inpA[3]); // Add square(6) res[6] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(7) r6 = _mm256_madd52hi_epu64(r6, inpA[3], inpA[3]); // Add square(7) res[7] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(8) r7 = _mm256_madd52lo_epu64(r7, inpA[4], inpA[4]); // Add square(8) res[8] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(16) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(16) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(16) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(16) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(16) AL = inpA[5]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(16) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(16) AL = inpA[6]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(16) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(16) AL = inpA[7]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(16) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(16) r0 = _mm256_add_epi64(r0, r0); // Double(9) r0 = _mm256_madd52hi_epu64(r0, inpA[4], inpA[4]); // Add square(9) res[9] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(10) r1 = _mm256_madd52lo_epu64(r1, inpA[5], inpA[5]); // Add square(10) res[10] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(11) r2 = _mm256_madd52hi_epu64(r2, inpA[5], inpA[5]); // Add square(11) res[11] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(12) r3 = _mm256_madd52lo_epu64(r3, inpA[6], inpA[6]); // Add square(12) res[12] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(13) r4 = _mm256_madd52hi_epu64(r4, inpA[6], inpA[6]); // Add square(13) res[13] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(14) r5 = _mm256_madd52lo_epu64(r5, inpA[7], inpA[7]); // Add square(14) res[14] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(15) r6 = _mm256_madd52hi_epu64(r6, inpA[7], inpA[7]); // Add square(15) res[15] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(16) r7 = _mm256_madd52lo_epu64(r7, inpA[8], inpA[8]); // Add square(16) res[16] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(24) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(24) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(24) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(24) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(24) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(24) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(24) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(24) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(24) AL = inpA[9]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(24) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(24) AL = inpA[10]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(24) AL = inpA[11]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(24) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(24) r0 = _mm256_add_epi64(r0, r0); // Double(17) r0 = _mm256_madd52hi_epu64(r0, inpA[8], inpA[8]); // Add square(17) res[17] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(18) r1 = _mm256_madd52lo_epu64(r1, inpA[9], inpA[9]); // Add square(18) res[18] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(19) r2 = _mm256_madd52hi_epu64(r2, inpA[9], inpA[9]); // Add square(19) res[19] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(20) r3 = _mm256_madd52lo_epu64(r3, inpA[10], inpA[10]); // Add square(20) res[20] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(21) r4 = _mm256_madd52hi_epu64(r4, inpA[10], inpA[10]); // Add square(21) res[21] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(22) r5 = _mm256_madd52lo_epu64(r5, inpA[11], inpA[11]); // Add square(22) res[22] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(23) r6 = _mm256_madd52hi_epu64(r6, inpA[11], inpA[11]); // Add square(23) res[23] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(24) r7 = _mm256_madd52lo_epu64(r7, inpA[12], inpA[12]); // Add square(24) res[24] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(32) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(32) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(32) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(32) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(32) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(32) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(32) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(32) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(32) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(32) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(32) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(32) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(32) AL = inpA[13]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(32) AL = inpA[14]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(32) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(32) AL = inpA[15]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(32) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(32) r0 = _mm256_add_epi64(r0, r0); // Double(25) r0 = _mm256_madd52hi_epu64(r0, inpA[12], inpA[12]); // Add square(25) res[25] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(26) r1 = _mm256_madd52lo_epu64(r1, inpA[13], inpA[13]); // Add square(26) res[26] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(27) r2 = _mm256_madd52hi_epu64(r2, inpA[13], inpA[13]); // Add square(27) res[27] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(28) r3 = _mm256_madd52lo_epu64(r3, inpA[14], inpA[14]); // Add square(28) res[28] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(29) r4 = _mm256_madd52hi_epu64(r4, inpA[14], inpA[14]); // Add square(29) res[29] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(30) r5 = _mm256_madd52lo_epu64(r5, inpA[15], inpA[15]); // Add square(30) res[30] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(31) r6 = _mm256_madd52hi_epu64(r6, inpA[15], inpA[15]); // Add square(31) res[31] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(32) r7 = _mm256_madd52lo_epu64(r7, inpA[16], inpA[16]); // Add square(32) res[32] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(40) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(40) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(40) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(40) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(40) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(40) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(40) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(40) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(40) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(40) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(40) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(40) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(40) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(40) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(40) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(40) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(40) AL = inpA[17]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(40) AL = inpA[18]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(40) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(40) AL = inpA[19]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(40) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(40) r0 = _mm256_add_epi64(r0, r0); // Double(33) r0 = _mm256_madd52hi_epu64(r0, inpA[16], inpA[16]); // Add square(33) res[33] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(34) r1 = _mm256_madd52lo_epu64(r1, inpA[17], inpA[17]); // Add square(34) res[34] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(35) r2 = _mm256_madd52hi_epu64(r2, inpA[17], inpA[17]); // Add square(35) res[35] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(36) r3 = _mm256_madd52lo_epu64(r3, inpA[18], inpA[18]); // Add square(36) res[36] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(37) r4 = _mm256_madd52hi_epu64(r4, inpA[18], inpA[18]); // Add square(37) res[37] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(38) r5 = _mm256_madd52lo_epu64(r5, inpA[19], inpA[19]); // Add square(38) res[38] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(39) r6 = _mm256_madd52hi_epu64(r6, inpA[19], inpA[19]); // Add square(39) res[39] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(40) r7 = _mm256_madd52lo_epu64(r7, inpA[20], inpA[20]); // Add square(40) res[40] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(48) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(48) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(48) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(48) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(48) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(48) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(48) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(48) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(48) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(48) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(48) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(48) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(48) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(48) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(48) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(48) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(48) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(48) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(48) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(48) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(48) AL = inpA[21]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(48) AL = inpA[22]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(48) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(48) AL = inpA[23]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(48) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(48) r0 = _mm256_add_epi64(r0, r0); // Double(41) r0 = _mm256_madd52hi_epu64(r0, inpA[20], inpA[20]); // Add square(41) res[41] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(42) r1 = _mm256_madd52lo_epu64(r1, inpA[21], inpA[21]); // Add square(42) res[42] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(43) r2 = _mm256_madd52hi_epu64(r2, inpA[21], inpA[21]); // Add square(43) res[43] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(44) r3 = _mm256_madd52lo_epu64(r3, inpA[22], inpA[22]); // Add square(44) res[44] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(45) r4 = _mm256_madd52hi_epu64(r4, inpA[22], inpA[22]); // Add square(45) res[45] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(46) r5 = _mm256_madd52lo_epu64(r5, inpA[23], inpA[23]); // Add square(46) res[46] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(47) r6 = _mm256_madd52hi_epu64(r6, inpA[23], inpA[23]); // Add square(47) res[47] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(48) r7 = _mm256_madd52lo_epu64(r7, inpA[24], inpA[24]); // Add square(48) res[48] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(56) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[55]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[55]); // Sum(56) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(56) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(56) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(56) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(56) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(56) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(56) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(56) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(56) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(56) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(56) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(56) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(56) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(56) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(56) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(56) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(56) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(56) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(56) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(56) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(56) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(56) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(56) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(56) AL = inpA[25]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(56) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(56) AL = inpA[26]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(56) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(56) AL = inpA[27]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(56) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(56) r0 = _mm256_add_epi64(r0, r0); // Double(49) r0 = _mm256_madd52hi_epu64(r0, inpA[24], inpA[24]); // Add square(49) res[49] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(50) r1 = _mm256_madd52lo_epu64(r1, inpA[25], inpA[25]); // Add square(50) res[50] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(51) r2 = _mm256_madd52hi_epu64(r2, inpA[25], inpA[25]); // Add square(51) res[51] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(52) r3 = _mm256_madd52lo_epu64(r3, inpA[26], inpA[26]); // Add square(52) res[52] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(53) r4 = _mm256_madd52hi_epu64(r4, inpA[26], inpA[26]); // Add square(53) res[53] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(54) r5 = _mm256_madd52lo_epu64(r5, inpA[27], inpA[27]); // Add square(54) res[54] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(55) r6 = _mm256_madd52hi_epu64(r6, inpA[27], inpA[27]); // Add square(55) res[55] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(56) r7 = _mm256_madd52lo_epu64(r7, inpA[28], inpA[28]); // Add square(56) res[56] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(59) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[56]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[57]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[58]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[56]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[57]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[58]); // Sum(59) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[56]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[57]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[56]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[57]); // Sum(59) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(59) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(59) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(59) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(59) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(59) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(59) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(59) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(59) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(59) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(59) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(59) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(59) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(59) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(59) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(59) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(59) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(59) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(59) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(59) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(59) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(59) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(59) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(59) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(59) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(59) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(59) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(59) AL = inpA[29]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(59) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(59) AL = inpA[30]; AL = inpA[31]; r0 = _mm256_add_epi64(r0, r0); // Double(57) r0 = _mm256_madd52hi_epu64(r0, inpA[28], inpA[28]); // Add square(57) res[57] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(58) r1 = _mm256_madd52lo_epu64(r1, inpA[29], inpA[29]); // Add square(58) res[58] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(59) r2 = _mm256_madd52hi_epu64(r2, inpA[29], inpA[29]); // Add square(59) res[59] = r2; r0 = r3; res[60] = r0; // finish up 1st triangle ASM("jmp l0\nl0:\n"); // 2nd triangle - sum the products, double and square r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(68) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[2]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[3]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[4]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[5]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[6]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[7]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[2]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[3]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[4]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[5]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[6]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[7]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(68) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[3]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[4]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[5]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[6]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[3]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[4]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[5]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[6]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(68) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[4]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[5]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[4]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[5]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(68) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(68) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(68) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(68) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(68) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(68) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(68) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(68) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(68) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(68) AL = inpA[46]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(68) AL = inpA[45]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(68) AL = inpA[44]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(68) AL = inpA[43]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(68) AL = inpA[42]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(68) AL = inpA[41]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(68) AL = inpA[40]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(68) AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(68) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(68) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(68) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(68) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(68) AL = inpA[34]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(66) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(67) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(68) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(66) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(67) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(68) AL = inpA[33]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(64) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(65) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(66) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(65) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(66) AL = inpA[32]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(62) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(63) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(62) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(63) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(64) AL = inpA[31]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(61) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(62) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(61) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(62) r0 = _mm256_add_epi64(r0, r0); // Double(60) r0 = _mm256_madd52lo_epu64(r0, inpA[30], inpA[30]); // Add square(60) res[N + 0] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(61) r1 = _mm256_madd52hi_epu64(r1, inpA[30], inpA[30]); // Add square(61) res[N + 1] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(62) r2 = _mm256_madd52lo_epu64(r2, inpA[31], inpA[31]); // Add square(62) res[N + 2] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(63) r3 = _mm256_madd52hi_epu64(r3, inpA[31], inpA[31]); // Add square(63) res[N + 3] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(64) r4 = _mm256_madd52lo_epu64(r4, inpA[32], inpA[32]); // Add square(64) res[N + 4] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(65) r5 = _mm256_madd52hi_epu64(r5, inpA[32], inpA[32]); // Add square(65) res[N + 5] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(66) r6 = _mm256_madd52lo_epu64(r6, inpA[33], inpA[33]); // Add square(66) res[N + 6] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(67) r7 = _mm256_madd52hi_epu64(r7, inpA[33], inpA[33]); // Add square(67) res[N + 7] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(76) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(76) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(76) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(76) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(76) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(76) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(76) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(76) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(76) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(76) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(76) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(76) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(76) AL = inpA[46]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(76) AL = inpA[45]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(76) AL = inpA[44]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(76) AL = inpA[43]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(76) AL = inpA[42]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(76) AL = inpA[41]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(76) AL = inpA[40]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(76) AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(76) AL = inpA[38]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(74) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(75) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(76) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(74) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(75) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(76) AL = inpA[37]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(72) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(73) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(74) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(73) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(74) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(70) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(71) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(70) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(71) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(72) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(69) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(70) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(69) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(70) r0 = _mm256_add_epi64(r0, r0); // Double(68) r0 = _mm256_madd52lo_epu64(r0, inpA[34], inpA[34]); // Add square(68) res[N + 8] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(69) r1 = _mm256_madd52hi_epu64(r1, inpA[34], inpA[34]); // Add square(69) res[N + 9] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(70) r2 = _mm256_madd52lo_epu64(r2, inpA[35], inpA[35]); // Add square(70) res[N + 10] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(71) r3 = _mm256_madd52hi_epu64(r3, inpA[35], inpA[35]); // Add square(71) res[N + 11] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(72) r4 = _mm256_madd52lo_epu64(r4, inpA[36], inpA[36]); // Add square(72) res[N + 12] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(73) r5 = _mm256_madd52hi_epu64(r5, inpA[36], inpA[36]); // Add square(73) res[N + 13] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(74) r6 = _mm256_madd52lo_epu64(r6, inpA[37], inpA[37]); // Add square(74) res[N + 14] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(75) r7 = _mm256_madd52hi_epu64(r7, inpA[37], inpA[37]); // Add square(75) res[N + 15] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(84) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(84) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(84) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(84) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(84) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(84) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(84) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(84) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(84) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(84) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(84) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(84) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(84) AL = inpA[46]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(84) AL = inpA[45]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(84) AL = inpA[44]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(84) AL = inpA[43]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(84) AL = inpA[42]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(82) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(83) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(82) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(83) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(84) AL = inpA[41]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(80) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(81) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(82) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(80) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(81) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(82) AL = inpA[40]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(78) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(79) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(80) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(79) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(80) AL = inpA[39]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(77) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(77) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(78) r0 = _mm256_add_epi64(r0, r0); // Double(76) r0 = _mm256_madd52lo_epu64(r0, inpA[38], inpA[38]); // Add square(76) res[N + 16] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(77) r1 = _mm256_madd52hi_epu64(r1, inpA[38], inpA[38]); // Add square(77) res[N + 17] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(78) r2 = _mm256_madd52lo_epu64(r2, inpA[39], inpA[39]); // Add square(78) res[N + 18] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(79) r3 = _mm256_madd52hi_epu64(r3, inpA[39], inpA[39]); // Add square(79) res[N + 19] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(80) r4 = _mm256_madd52lo_epu64(r4, inpA[40], inpA[40]); // Add square(80) res[N + 20] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(81) r5 = _mm256_madd52hi_epu64(r5, inpA[40], inpA[40]); // Add square(81) res[N + 21] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(82) r6 = _mm256_madd52lo_epu64(r6, inpA[41], inpA[41]); // Add square(82) res[N + 22] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(83) r7 = _mm256_madd52hi_epu64(r7, inpA[41], inpA[41]); // Add square(83) res[N + 23] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(92) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(92) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(92) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(92) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(92) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(92) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(92) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(92) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(92) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(92) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(92) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(92) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(92) AL = inpA[46]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(90) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(91) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(90) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(91) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(92) AL = inpA[45]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(88) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(89) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(90) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(88) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(89) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(90) AL = inpA[44]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(86) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(87) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(88) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(86) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(87) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(88) AL = inpA[43]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(85) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(86) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(85) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(86) r0 = _mm256_add_epi64(r0, r0); // Double(84) r0 = _mm256_madd52lo_epu64(r0, inpA[42], inpA[42]); // Add square(84) res[N + 24] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(85) r1 = _mm256_madd52hi_epu64(r1, inpA[42], inpA[42]); // Add square(85) res[N + 25] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(86) r2 = _mm256_madd52lo_epu64(r2, inpA[43], inpA[43]); // Add square(86) res[N + 26] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(87) r3 = _mm256_madd52hi_epu64(r3, inpA[43], inpA[43]); // Add square(87) res[N + 27] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(88) r4 = _mm256_madd52lo_epu64(r4, inpA[44], inpA[44]); // Add square(88) res[N + 28] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(89) r5 = _mm256_madd52hi_epu64(r5, inpA[44], inpA[44]); // Add square(89) res[N + 29] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(90) r6 = _mm256_madd52lo_epu64(r6, inpA[45], inpA[45]); // Add square(90) res[N + 30] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(91) r7 = _mm256_madd52hi_epu64(r7, inpA[45], inpA[45]); // Add square(91) res[N + 31] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(100) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(100) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(100) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(100) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(100) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(100) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(100) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(100) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(100) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(98) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(99) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(98) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(99) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(100) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(96) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(97) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(98) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(96) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(97) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(98) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(94) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(95) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(96) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(94) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(95) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(96) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(93) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(94) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(93) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(94) r0 = _mm256_add_epi64(r0, r0); // Double(92) r0 = _mm256_madd52lo_epu64(r0, inpA[46], inpA[46]); // Add square(92) res[N + 32] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(93) r1 = _mm256_madd52hi_epu64(r1, inpA[46], inpA[46]); // Add square(93) res[N + 33] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(94) r2 = _mm256_madd52lo_epu64(r2, inpA[47], inpA[47]); // Add square(94) res[N + 34] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(95) r3 = _mm256_madd52hi_epu64(r3, inpA[47], inpA[47]); // Add square(95) res[N + 35] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(96) r4 = _mm256_madd52lo_epu64(r4, inpA[48], inpA[48]); // Add square(96) res[N + 36] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(97) r5 = _mm256_madd52hi_epu64(r5, inpA[48], inpA[48]); // Add square(97) res[N + 37] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(98) r6 = _mm256_madd52lo_epu64(r6, inpA[49], inpA[49]); // Add square(98) res[N + 38] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(99) r7 = _mm256_madd52hi_epu64(r7, inpA[49], inpA[49]); // Add square(99) res[N + 39] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(106) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(107) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(106) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(107) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(108) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(106) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(107) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(106) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(107) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(108) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(106) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(107) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(106) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(107) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(108) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(106) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(107) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(106) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(107) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(108) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(106) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(107) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(106) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(107) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(108) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(106) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(107) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(106) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(107) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(108) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(104) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(105) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(106) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(104) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(105) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(106) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(102) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(103) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(104) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(102) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(103) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(104) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(101) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(102) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(101) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(102) r0 = _mm256_add_epi64(r0, r0); // Double(100) r0 = _mm256_madd52lo_epu64(r0, inpA[50], inpA[50]); // Add square(100) res[N + 40] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(101) r1 = _mm256_madd52hi_epu64(r1, inpA[50], inpA[50]); // Add square(101) res[N + 41] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(102) r2 = _mm256_madd52lo_epu64(r2, inpA[51], inpA[51]); // Add square(102) res[N + 42] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(103) r3 = _mm256_madd52hi_epu64(r3, inpA[51], inpA[51]); // Add square(103) res[N + 43] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(104) r4 = _mm256_madd52lo_epu64(r4, inpA[52], inpA[52]); // Add square(104) res[N + 44] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(105) r5 = _mm256_madd52hi_epu64(r5, inpA[52], inpA[52]); // Add square(105) res[N + 45] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(106) r6 = _mm256_madd52lo_epu64(r6, inpA[53], inpA[53]); // Add square(106) res[N + 46] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(107) r7 = _mm256_madd52hi_epu64(r7, inpA[53], inpA[53]); // Add square(107) res[N + 47] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(109) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(110) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(111) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(112) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(113) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(114) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(115) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(116) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(109) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(110) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(111) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(112) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(113) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(114) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(115) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(116) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(109) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(110) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(111) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(112) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(113) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(114) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[56]); // Sum(115) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[57]); // Sum(116) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(109) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(110) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(111) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(112) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(113) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(114) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[56]); // Sum(115) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[57]); // Sum(116) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(109) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(110) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(111) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(112) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(113) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(114) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(109) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(110) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(111) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(112) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(113) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(114) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(109) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(110) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(111) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(112) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(109) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(110) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(111) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(112) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(109) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(110) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(109) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(110) r0 = _mm256_add_epi64(r0, r0); // Double(108) r0 = _mm256_madd52lo_epu64(r0, inpA[54], inpA[54]); // Add square(108) res[N + 48] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(109) r1 = _mm256_madd52hi_epu64(r1, inpA[54], inpA[54]); // Add square(109) res[N + 49] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(110) r2 = _mm256_madd52lo_epu64(r2, inpA[55], inpA[55]); // Add square(110) res[N + 50] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(111) r3 = _mm256_madd52hi_epu64(r3, inpA[55], inpA[55]); // Add square(111) res[N + 51] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(112) r4 = _mm256_madd52lo_epu64(r4, inpA[56], inpA[56]); // Add square(112) res[N + 52] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(113) r5 = _mm256_madd52hi_epu64(r5, inpA[56], inpA[56]); // Add square(113) res[N + 53] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(114) r6 = _mm256_madd52lo_epu64(r6, inpA[57], inpA[57]); // Add square(114) res[N + 54] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(115) r7 = _mm256_madd52hi_epu64(r7, inpA[57], inpA[57]); // Add square(115) res[N + 55] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(117) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(118) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(117) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(118) r0 = _mm256_add_epi64(r0, r0); // Double(116) r0 = _mm256_madd52lo_epu64(r0, inpA[58], inpA[58]); // Add square(116) res[N + 56] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(117) r1 = _mm256_madd52hi_epu64(r1, inpA[58], inpA[58]); // Add square(117) res[N + 57] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(118) r2 = _mm256_madd52lo_epu64(r2, inpA[59], inpA[59]); // Add square(118) res[N + 58] = r2; r0 = r3; // finish up doubling res[N + 59] = _mm256_madd52hi_epu64(zero_simd, inpA[59], inpA[59]); } void AMS52x60_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { const int N = 60; __m256i res[60 * 2]; /* Square only */ ams52x60_square_diagonal_mb4(res, inpA_mb); /* Generate u_i and begin reduction */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) ifma_ams52x79_diagonal_mb4.c000066400000000000000000016032721470420105600343520ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx2/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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. *************************************************************************/ /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #include #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) #include static void ams52x79_square_diagonal_mb4(__m256i *res, const int64u *inpA_mb) { const __m256i *inpA = (const __m256i *)inpA_mb; register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, AL; const int N = 79; const __m256i zero_simd = _mm256_setzero_si256(); // 1st triangle - sum the products, double and square r0 = zero_simd; res[0] = _mm256_madd52lo_epu64(r0, inpA[0], inpA[0]); r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(1) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(2) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(8) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(1) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(2) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(8) AL = inpA[1]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[2]); // Sum(3) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[3]); // Sum(4) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[4]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[5]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[6]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[7]); // Sum(8) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[2]); // Sum(3) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[3]); // Sum(4) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[4]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[5]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[6]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[7]); // Sum(8) AL = inpA[2]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[3]); // Sum(5) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[4]); // Sum(6) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[5]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[6]); // Sum(8) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[3]); // Sum(5) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[4]); // Sum(6) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[5]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[6]); // Sum(8) AL = inpA[3]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[4]); // Sum(7) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[5]); // Sum(8) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[4]); // Sum(7) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[5]); // Sum(8) r0 = _mm256_add_epi64(r0, r0); // Double(1) r0 = _mm256_madd52hi_epu64(r0, inpA[0], inpA[0]); // Add square(1) res[1] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(2) r1 = _mm256_madd52lo_epu64(r1, inpA[1], inpA[1]); // Add square(2) res[2] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(3) r2 = _mm256_madd52hi_epu64(r2, inpA[1], inpA[1]); // Add square(3) res[3] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(4) r3 = _mm256_madd52lo_epu64(r3, inpA[2], inpA[2]); // Add square(4) res[4] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(5) r4 = _mm256_madd52hi_epu64(r4, inpA[2], inpA[2]); // Add square(5) res[5] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(6) r5 = _mm256_madd52lo_epu64(r5, inpA[3], inpA[3]); // Add square(6) res[6] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(7) r6 = _mm256_madd52hi_epu64(r6, inpA[3], inpA[3]); // Add square(7) res[7] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(8) r7 = _mm256_madd52lo_epu64(r7, inpA[4], inpA[4]); // Add square(8) res[8] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(16) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(16) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(16) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(16) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(9) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(10) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(16) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(9) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(10) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(16) AL = inpA[5]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(11) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(12) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(16) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(11) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(12) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(16) AL = inpA[6]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(13) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(14) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(16) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(13) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(14) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(16) AL = inpA[7]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(15) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(16) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(15) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(16) r0 = _mm256_add_epi64(r0, r0); // Double(9) r0 = _mm256_madd52hi_epu64(r0, inpA[4], inpA[4]); // Add square(9) res[9] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(10) r1 = _mm256_madd52lo_epu64(r1, inpA[5], inpA[5]); // Add square(10) res[10] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(11) r2 = _mm256_madd52hi_epu64(r2, inpA[5], inpA[5]); // Add square(11) res[11] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(12) r3 = _mm256_madd52lo_epu64(r3, inpA[6], inpA[6]); // Add square(12) res[12] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(13) r4 = _mm256_madd52hi_epu64(r4, inpA[6], inpA[6]); // Add square(13) res[13] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(14) r5 = _mm256_madd52lo_epu64(r5, inpA[7], inpA[7]); // Add square(14) res[14] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(15) r6 = _mm256_madd52hi_epu64(r6, inpA[7], inpA[7]); // Add square(15) res[15] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(16) r7 = _mm256_madd52lo_epu64(r7, inpA[8], inpA[8]); // Add square(16) res[16] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(24) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(24) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(24) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(24) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(24) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(24) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(24) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(24) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(17) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(18) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(24) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(17) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(18) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(24) AL = inpA[9]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(19) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(20) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(24) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(19) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(20) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(24) AL = inpA[10]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(21) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(22) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(24) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(21) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(22) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(24) AL = inpA[11]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(23) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(24) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(23) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(24) r0 = _mm256_add_epi64(r0, r0); // Double(17) r0 = _mm256_madd52hi_epu64(r0, inpA[8], inpA[8]); // Add square(17) res[17] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(18) r1 = _mm256_madd52lo_epu64(r1, inpA[9], inpA[9]); // Add square(18) res[18] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(19) r2 = _mm256_madd52hi_epu64(r2, inpA[9], inpA[9]); // Add square(19) res[19] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(20) r3 = _mm256_madd52lo_epu64(r3, inpA[10], inpA[10]); // Add square(20) res[20] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(21) r4 = _mm256_madd52hi_epu64(r4, inpA[10], inpA[10]); // Add square(21) res[21] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(22) r5 = _mm256_madd52lo_epu64(r5, inpA[11], inpA[11]); // Add square(22) res[22] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(23) r6 = _mm256_madd52hi_epu64(r6, inpA[11], inpA[11]); // Add square(23) res[23] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(24) r7 = _mm256_madd52lo_epu64(r7, inpA[12], inpA[12]); // Add square(24) res[24] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(32) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(32) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(32) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(32) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(32) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(32) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(32) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(32) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(32) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(32) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(32) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(32) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(25) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(26) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(32) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(25) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(26) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(32) AL = inpA[13]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(27) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(28) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(32) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(27) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(28) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(32) AL = inpA[14]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(29) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(30) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(32) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(29) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(30) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(32) AL = inpA[15]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(31) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(32) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(31) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(32) r0 = _mm256_add_epi64(r0, r0); // Double(25) r0 = _mm256_madd52hi_epu64(r0, inpA[12], inpA[12]); // Add square(25) res[25] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(26) r1 = _mm256_madd52lo_epu64(r1, inpA[13], inpA[13]); // Add square(26) res[26] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(27) r2 = _mm256_madd52hi_epu64(r2, inpA[13], inpA[13]); // Add square(27) res[27] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(28) r3 = _mm256_madd52lo_epu64(r3, inpA[14], inpA[14]); // Add square(28) res[28] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(29) r4 = _mm256_madd52hi_epu64(r4, inpA[14], inpA[14]); // Add square(29) res[29] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(30) r5 = _mm256_madd52lo_epu64(r5, inpA[15], inpA[15]); // Add square(30) res[30] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(31) r6 = _mm256_madd52hi_epu64(r6, inpA[15], inpA[15]); // Add square(31) res[31] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(32) r7 = _mm256_madd52lo_epu64(r7, inpA[16], inpA[16]); // Add square(32) res[32] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(40) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(40) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(40) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(40) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(40) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(40) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(40) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(40) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(40) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(40) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(40) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(40) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(40) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(40) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(40) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(40) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(33) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(34) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(40) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(33) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(34) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(40) AL = inpA[17]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(35) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(36) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(40) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(35) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(36) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(40) AL = inpA[18]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(37) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(38) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(40) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(37) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(38) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(40) AL = inpA[19]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(39) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(40) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(39) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(40) r0 = _mm256_add_epi64(r0, r0); // Double(33) r0 = _mm256_madd52hi_epu64(r0, inpA[16], inpA[16]); // Add square(33) res[33] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(34) r1 = _mm256_madd52lo_epu64(r1, inpA[17], inpA[17]); // Add square(34) res[34] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(35) r2 = _mm256_madd52hi_epu64(r2, inpA[17], inpA[17]); // Add square(35) res[35] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(36) r3 = _mm256_madd52lo_epu64(r3, inpA[18], inpA[18]); // Add square(36) res[36] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(37) r4 = _mm256_madd52hi_epu64(r4, inpA[18], inpA[18]); // Add square(37) res[37] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(38) r5 = _mm256_madd52lo_epu64(r5, inpA[19], inpA[19]); // Add square(38) res[38] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(39) r6 = _mm256_madd52hi_epu64(r6, inpA[19], inpA[19]); // Add square(39) res[39] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(40) r7 = _mm256_madd52lo_epu64(r7, inpA[20], inpA[20]); // Add square(40) res[40] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(48) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(48) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(48) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(48) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(48) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(48) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(48) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(48) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(48) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(48) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(48) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(48) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(48) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(48) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(48) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(48) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(48) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(48) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(48) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(48) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(41) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(42) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(48) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(41) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(42) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(48) AL = inpA[21]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(43) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(44) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(48) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(43) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(44) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(48) AL = inpA[22]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(45) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(46) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(48) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(45) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(46) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(48) AL = inpA[23]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(47) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(48) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(47) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(48) r0 = _mm256_add_epi64(r0, r0); // Double(41) r0 = _mm256_madd52hi_epu64(r0, inpA[20], inpA[20]); // Add square(41) res[41] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(42) r1 = _mm256_madd52lo_epu64(r1, inpA[21], inpA[21]); // Add square(42) res[42] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(43) r2 = _mm256_madd52hi_epu64(r2, inpA[21], inpA[21]); // Add square(43) res[43] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(44) r3 = _mm256_madd52lo_epu64(r3, inpA[22], inpA[22]); // Add square(44) res[44] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(45) r4 = _mm256_madd52hi_epu64(r4, inpA[22], inpA[22]); // Add square(45) res[45] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(46) r5 = _mm256_madd52lo_epu64(r5, inpA[23], inpA[23]); // Add square(46) res[46] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(47) r6 = _mm256_madd52hi_epu64(r6, inpA[23], inpA[23]); // Add square(47) res[47] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(48) r7 = _mm256_madd52lo_epu64(r7, inpA[24], inpA[24]); // Add square(48) res[48] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(56) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[55]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[55]); // Sum(56) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(56) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(56) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(56) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(56) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(56) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(56) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(56) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(56) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(56) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(56) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(56) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(56) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(56) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(56) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(56) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(56) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(56) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(56) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(56) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(56) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(56) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(56) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(49) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(50) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(56) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(49) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(50) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(56) AL = inpA[25]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(51) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(52) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(56) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(51) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(52) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(56) AL = inpA[26]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(53) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(54) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(56) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(53) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(54) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(56) AL = inpA[27]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(55) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(56) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(55) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(56) r0 = _mm256_add_epi64(r0, r0); // Double(49) r0 = _mm256_madd52hi_epu64(r0, inpA[24], inpA[24]); // Add square(49) res[49] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(50) r1 = _mm256_madd52lo_epu64(r1, inpA[25], inpA[25]); // Add square(50) res[50] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(51) r2 = _mm256_madd52hi_epu64(r2, inpA[25], inpA[25]); // Add square(51) res[51] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(52) r3 = _mm256_madd52lo_epu64(r3, inpA[26], inpA[26]); // Add square(52) res[52] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(53) r4 = _mm256_madd52hi_epu64(r4, inpA[26], inpA[26]); // Add square(53) res[53] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(54) r5 = _mm256_madd52lo_epu64(r5, inpA[27], inpA[27]); // Add square(54) res[54] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(55) r6 = _mm256_madd52hi_epu64(r6, inpA[27], inpA[27]); // Add square(55) res[55] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(56) r7 = _mm256_madd52lo_epu64(r7, inpA[28], inpA[28]); // Add square(56) res[56] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[60]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[61]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[62]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[63]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[64]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[60]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[61]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[62]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[63]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[64]); // Sum(64) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[56]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[57]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[58]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[59]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[60]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[61]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[62]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[63]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[56]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[57]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[58]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[59]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[60]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[61]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[62]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[63]); // Sum(64) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[56]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[57]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[58]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[59]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[60]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[61]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[62]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[56]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[57]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[58]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[59]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[60]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[61]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[62]); // Sum(64) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[57]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[58]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[59]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[60]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[61]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[57]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[58]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[59]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[60]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[61]); // Sum(64) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[56]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[57]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[58]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[59]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[60]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[56]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[57]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[58]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[59]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[60]); // Sum(64) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[56]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[57]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[58]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[59]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[56]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[57]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[58]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[59]); // Sum(64) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[57]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[58]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[57]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[58]); // Sum(64) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[56]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[57]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[56]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[57]); // Sum(64) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(64) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[55]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[55]); // Sum(64) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(64) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(64) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(64) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(64) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(64) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(64) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(64) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(64) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(64) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(64) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(64) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(64) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(64) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(64) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(64) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(64) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(64) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(64) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(57) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(58) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(64) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(57) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(58) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(64) AL = inpA[29]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(59) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(60) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(64) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(59) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(60) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(64) AL = inpA[30]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(61) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(62) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(64) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(61) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(62) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(64) AL = inpA[31]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(63) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(64) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(63) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(64) r0 = _mm256_add_epi64(r0, r0); // Double(57) r0 = _mm256_madd52hi_epu64(r0, inpA[28], inpA[28]); // Add square(57) res[57] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(58) r1 = _mm256_madd52lo_epu64(r1, inpA[29], inpA[29]); // Add square(58) res[58] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(59) r2 = _mm256_madd52hi_epu64(r2, inpA[29], inpA[29]); // Add square(59) res[59] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(60) r3 = _mm256_madd52lo_epu64(r3, inpA[30], inpA[30]); // Add square(60) res[60] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(61) r4 = _mm256_madd52hi_epu64(r4, inpA[30], inpA[30]); // Add square(61) res[61] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(62) r5 = _mm256_madd52lo_epu64(r5, inpA[31], inpA[31]); // Add square(62) res[62] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(63) r6 = _mm256_madd52hi_epu64(r6, inpA[31], inpA[31]); // Add square(63) res[63] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(64) r7 = _mm256_madd52lo_epu64(r7, inpA[32], inpA[32]); // Add square(64) res[64] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[65]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[66]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[67]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[68]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[69]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[70]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[71]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[72]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[65]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[66]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[67]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[68]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[69]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[70]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[71]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[72]); // Sum(72) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[64]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[65]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[66]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[67]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[68]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[69]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[70]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[71]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[64]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[65]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[66]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[67]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[68]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[69]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[70]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[71]); // Sum(72) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[63]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[64]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[65]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[66]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[67]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[68]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[69]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[70]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[63]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[64]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[65]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[66]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[67]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[68]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[69]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[70]); // Sum(72) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[62]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[63]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[64]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[65]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[66]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[67]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[68]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[69]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[62]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[63]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[64]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[65]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[66]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[67]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[68]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[69]); // Sum(72) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[61]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[62]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[63]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[64]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[65]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[66]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[67]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[68]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[61]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[62]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[63]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[64]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[65]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[66]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[67]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[68]); // Sum(72) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[60]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[61]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[62]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[63]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[64]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[65]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[66]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[67]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[60]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[61]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[62]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[63]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[64]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[65]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[66]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[67]); // Sum(72) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[59]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[60]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[61]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[62]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[63]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[64]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[65]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[66]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[59]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[60]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[61]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[62]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[63]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[64]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[65]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[66]); // Sum(72) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[58]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[59]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[60]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[61]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[62]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[63]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[64]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[65]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[58]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[59]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[60]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[61]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[62]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[63]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[64]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[65]); // Sum(72) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[60]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[61]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[62]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[63]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[64]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[60]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[61]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[62]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[63]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[64]); // Sum(72) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[56]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[57]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[58]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[59]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[60]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[61]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[62]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[63]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[56]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[57]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[58]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[59]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[60]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[61]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[62]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[63]); // Sum(72) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[56]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[57]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[58]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[59]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[60]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[61]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[62]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[56]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[57]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[58]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[59]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[60]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[61]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[62]); // Sum(72) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[57]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[58]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[59]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[60]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[61]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[57]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[58]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[59]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[60]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[61]); // Sum(72) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[56]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[57]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[58]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[59]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[60]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[56]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[57]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[58]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[59]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[60]); // Sum(72) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[56]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[57]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[58]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[59]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[56]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[57]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[58]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[59]); // Sum(72) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[57]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[58]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[57]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[58]); // Sum(72) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[56]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[57]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[56]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[57]); // Sum(72) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(72) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[55]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[55]); // Sum(72) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(72) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(72) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(72) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(72) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(72) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(72) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(72) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(72) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(72) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(72) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(72) AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(72) AL = inpA[30]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(72) AL = inpA[31]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(72) AL = inpA[32]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(65) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(66) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(72) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(65) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(66) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(72) AL = inpA[33]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(67) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(68) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(72) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(67) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(68) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(72) AL = inpA[34]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(69) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(70) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(72) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(69) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(70) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(72) AL = inpA[35]; r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(71) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(72) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(71) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(72) r0 = _mm256_add_epi64(r0, r0); // Double(65) r0 = _mm256_madd52hi_epu64(r0, inpA[32], inpA[32]); // Add square(65) res[65] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(66) r1 = _mm256_madd52lo_epu64(r1, inpA[33], inpA[33]); // Add square(66) res[66] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(67) r2 = _mm256_madd52hi_epu64(r2, inpA[33], inpA[33]); // Add square(67) res[67] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(68) r3 = _mm256_madd52lo_epu64(r3, inpA[34], inpA[34]); // Add square(68) res[68] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(69) r4 = _mm256_madd52hi_epu64(r4, inpA[34], inpA[34]); // Add square(69) res[69] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(70) r5 = _mm256_madd52lo_epu64(r5, inpA[35], inpA[35]); // Add square(70) res[70] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(71) r6 = _mm256_madd52hi_epu64(r6, inpA[35], inpA[35]); // Add square(71) res[71] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(72) r7 = _mm256_madd52lo_epu64(r7, inpA[36], inpA[36]); // Add square(72) res[72] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; AL = inpA[0]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[73]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[74]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[75]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[76]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[77]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[78]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[73]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[74]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[75]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[76]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[77]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[78]); // Sum(78) AL = inpA[1]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[72]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[73]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[74]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[75]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[76]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[77]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[72]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[73]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[74]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[75]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[76]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[77]); // Sum(78) AL = inpA[2]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[71]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[72]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[73]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[74]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[75]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[76]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[71]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[72]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[73]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[74]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[75]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[76]); // Sum(78) AL = inpA[3]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[70]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[71]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[72]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[73]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[74]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[75]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[70]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[71]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[72]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[73]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[74]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[75]); // Sum(78) AL = inpA[4]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[69]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[70]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[71]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[72]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[73]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[74]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[69]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[70]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[71]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[72]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[73]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[74]); // Sum(78) AL = inpA[5]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[68]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[69]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[70]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[71]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[72]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[73]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[68]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[69]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[70]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[71]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[72]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[73]); // Sum(78) AL = inpA[6]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[67]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[68]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[69]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[70]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[71]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[72]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[67]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[68]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[69]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[70]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[71]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[72]); // Sum(78) AL = inpA[7]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[66]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[67]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[68]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[69]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[70]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[71]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[66]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[67]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[68]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[69]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[70]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[71]); // Sum(78) AL = inpA[8]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[65]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[66]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[67]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[68]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[69]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[70]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[65]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[66]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[67]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[68]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[69]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[70]); // Sum(78) AL = inpA[9]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[64]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[65]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[66]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[67]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[68]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[69]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[64]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[65]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[66]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[67]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[68]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[69]); // Sum(78) AL = inpA[10]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[63]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[64]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[65]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[66]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[67]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[68]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[63]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[64]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[65]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[66]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[67]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[68]); // Sum(78) AL = inpA[11]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[62]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[63]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[64]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[65]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[66]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[67]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[62]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[63]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[64]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[65]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[66]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[67]); // Sum(78) AL = inpA[12]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[61]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[62]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[63]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[64]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[65]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[66]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[61]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[62]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[63]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[64]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[65]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[66]); // Sum(78) AL = inpA[13]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[60]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[61]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[62]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[63]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[64]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[65]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[60]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[61]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[62]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[63]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[64]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[65]); // Sum(78) AL = inpA[14]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[59]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[60]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[61]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[62]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[63]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[64]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[59]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[60]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[61]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[62]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[63]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[64]); // Sum(78) AL = inpA[15]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[58]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[59]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[60]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[61]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[62]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[63]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[58]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[59]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[60]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[61]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[62]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[63]); // Sum(78) AL = inpA[16]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[60]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[61]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[62]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[60]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[61]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[62]); // Sum(78) AL = inpA[17]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[56]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[57]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[58]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[59]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[60]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[61]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[56]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[57]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[58]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[59]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[60]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[61]); // Sum(78) AL = inpA[18]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[56]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[57]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[58]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[59]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[60]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[56]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[57]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[58]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[59]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[60]); // Sum(78) AL = inpA[19]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[57]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[58]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[59]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[57]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[58]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[59]); // Sum(78) AL = inpA[20]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[56]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[57]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[58]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[56]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[57]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[58]); // Sum(78) AL = inpA[21]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[56]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[57]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[56]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[57]); // Sum(78) AL = inpA[22]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(78) AL = inpA[23]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(78) AL = inpA[24]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(78) AL = inpA[25]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(78) AL = inpA[26]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(78) AL = inpA[27]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(78) AL = inpA[28]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(78) AL = inpA[29]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(78) AL = inpA[30]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(78) AL = inpA[31]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(78) AL = inpA[32]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(78) AL = inpA[33]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(78) AL = inpA[34]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(78) AL = inpA[35]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(78) AL = inpA[36]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(73) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(74) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(78) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(73) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(74) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(78) AL = inpA[37]; r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(75) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(76) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(78) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(75) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(76) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(78) AL = inpA[38]; r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(77) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(78) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(77) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(78) AL = inpA[39]; r0 = _mm256_add_epi64(r0, r0); // Double(73) r0 = _mm256_madd52hi_epu64(r0, inpA[36], inpA[36]); // Add square(73) res[73] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(74) r1 = _mm256_madd52lo_epu64(r1, inpA[37], inpA[37]); // Add square(74) res[74] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(75) r2 = _mm256_madd52hi_epu64(r2, inpA[37], inpA[37]); // Add square(75) res[75] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(76) r3 = _mm256_madd52lo_epu64(r3, inpA[38], inpA[38]); // Add square(76) res[76] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(77) r4 = _mm256_madd52hi_epu64(r4, inpA[38], inpA[38]); // Add square(77) res[77] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(78) r5 = _mm256_madd52lo_epu64(r5, inpA[39], inpA[39]); // Add square(78) res[78] = r5; r0 = r6; res[79] = r0; // finish up 1st triangle ASM("jmp l0\nl0:\n"); // 2nd triangle - sum the products, double and square r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[1]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[2]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[3]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[4]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[5]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[6]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[7]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[8]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[1]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[2]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[3]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[4]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[5]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[6]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[7]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[8]); // Sum(87) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[2]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[3]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[4]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[5]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[6]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[7]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[8]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[9]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[2]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[3]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[4]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[5]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[6]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[7]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[8]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[9]); // Sum(87) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[3]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[4]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[5]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[6]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[7]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[8]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[9]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[10]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[3]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[4]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[5]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[6]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[7]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[8]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[9]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[10]); // Sum(87) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[4]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[5]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[6]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[7]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[8]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[9]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[10]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[11]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[4]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[5]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[6]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[7]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[8]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[9]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[10]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[11]); // Sum(87) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[5]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[6]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[7]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[8]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[9]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[10]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[11]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[12]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[5]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[6]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[7]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[8]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[9]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[10]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[11]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[12]); // Sum(87) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[6]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[7]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[8]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[9]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[10]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[11]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[12]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[13]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[6]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[7]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[8]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[9]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[10]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[11]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[12]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[13]); // Sum(87) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[7]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[8]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[9]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[10]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[11]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[12]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[13]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[14]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[7]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[8]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[9]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[10]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[11]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[12]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[13]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[14]); // Sum(87) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[8]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[9]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[10]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[11]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[12]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[13]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[14]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[15]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[8]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[9]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[10]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[11]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[12]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[13]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[14]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[15]); // Sum(87) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(87) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(87) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(87) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(87) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(87) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(87) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(87) AL = inpA[63]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(87) AL = inpA[62]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(87) AL = inpA[61]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(87) AL = inpA[60]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(87) AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(87) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(87) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(87) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(87) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(87) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(87) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(87) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(87) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(87) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(87) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(87) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(87) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(87) AL = inpA[46]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(87) AL = inpA[45]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(87) AL = inpA[44]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(86) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(87) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(86) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(87) AL = inpA[43]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(84) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(85) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(86) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(84) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(85) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(86) AL = inpA[42]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(82) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(83) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(84) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(82) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(83) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(84) AL = inpA[41]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(80) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(81) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(82) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(80) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(81) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(82) AL = inpA[40]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(80) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(80) r0 = _mm256_add_epi64(r0, r0); // Double(79) r0 = _mm256_madd52hi_epu64(r0, inpA[39], inpA[39]); // Add square(79) res[N + 0] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(80) r1 = _mm256_madd52lo_epu64(r1, inpA[40], inpA[40]); // Add square(80) res[N + 1] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(81) r2 = _mm256_madd52hi_epu64(r2, inpA[40], inpA[40]); // Add square(81) res[N + 2] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(82) r3 = _mm256_madd52lo_epu64(r3, inpA[41], inpA[41]); // Add square(82) res[N + 3] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(83) r4 = _mm256_madd52hi_epu64(r4, inpA[41], inpA[41]); // Add square(83) res[N + 4] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(84) r5 = _mm256_madd52lo_epu64(r5, inpA[42], inpA[42]); // Add square(84) res[N + 5] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(85) r6 = _mm256_madd52hi_epu64(r6, inpA[42], inpA[42]); // Add square(85) res[N + 6] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(86) r7 = _mm256_madd52lo_epu64(r7, inpA[43], inpA[43]); // Add square(86) res[N + 7] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[9]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[10]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[11]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[12]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[13]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[14]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[15]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[16]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[9]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[10]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[11]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[12]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[13]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[14]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[15]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[16]); // Sum(95) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[10]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[11]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[12]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[13]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[14]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[15]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[16]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[17]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[10]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[11]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[12]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[13]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[14]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[15]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[16]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[17]); // Sum(95) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[11]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[12]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[13]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[14]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[15]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[16]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[17]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[18]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[11]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[12]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[13]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[14]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[15]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[16]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[17]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[18]); // Sum(95) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[12]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[13]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[14]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[15]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[16]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[17]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[18]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[19]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[12]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[13]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[14]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[15]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[16]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[17]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[18]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[19]); // Sum(95) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[13]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[14]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[15]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[16]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[17]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[18]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[19]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[20]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[13]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[14]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[15]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[16]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[17]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[18]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[19]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[20]); // Sum(95) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[14]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[15]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[16]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[17]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[18]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[19]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[20]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[21]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[14]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[15]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[16]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[17]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[18]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[19]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[20]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[21]); // Sum(95) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[15]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[16]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[17]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[18]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[19]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[20]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[21]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[22]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[15]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[16]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[17]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[18]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[19]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[20]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[21]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[22]); // Sum(95) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[16]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[17]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[18]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[19]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[20]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[21]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[22]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[23]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[16]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[17]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[18]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[19]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[20]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[21]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[22]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[23]); // Sum(95) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(95) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(95) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(95) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(95) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(95) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(95) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(95) AL = inpA[63]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(95) AL = inpA[62]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(95) AL = inpA[61]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(95) AL = inpA[60]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(95) AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(95) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(95) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(95) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(95) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(95) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(95) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(95) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(95) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(95) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(95) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(95) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(94) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(95) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(94) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(95) AL = inpA[47]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(92) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(93) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(94) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(92) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(93) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(94) AL = inpA[46]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(90) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(91) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(92) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(90) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(91) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(92) AL = inpA[45]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(88) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(89) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(90) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(88) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(89) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(90) AL = inpA[44]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(88) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(88) r0 = _mm256_add_epi64(r0, r0); // Double(87) r0 = _mm256_madd52hi_epu64(r0, inpA[43], inpA[43]); // Add square(87) res[N + 8] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(88) r1 = _mm256_madd52lo_epu64(r1, inpA[44], inpA[44]); // Add square(88) res[N + 9] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(89) r2 = _mm256_madd52hi_epu64(r2, inpA[44], inpA[44]); // Add square(89) res[N + 10] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(90) r3 = _mm256_madd52lo_epu64(r3, inpA[45], inpA[45]); // Add square(90) res[N + 11] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(91) r4 = _mm256_madd52hi_epu64(r4, inpA[45], inpA[45]); // Add square(91) res[N + 12] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(92) r5 = _mm256_madd52lo_epu64(r5, inpA[46], inpA[46]); // Add square(92) res[N + 13] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(93) r6 = _mm256_madd52hi_epu64(r6, inpA[46], inpA[46]); // Add square(93) res[N + 14] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(94) r7 = _mm256_madd52lo_epu64(r7, inpA[47], inpA[47]); // Add square(94) res[N + 15] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[17]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[18]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[19]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[20]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[21]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[22]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[23]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[24]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[17]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[18]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[19]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[20]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[21]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[22]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[23]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[24]); // Sum(103) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[18]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[19]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[20]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[21]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[22]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[23]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[24]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[25]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[18]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[19]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[20]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[21]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[22]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[23]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[24]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[25]); // Sum(103) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[19]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[20]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[21]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[22]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[23]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[24]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[25]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[26]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[19]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[20]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[21]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[22]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[23]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[24]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[25]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[26]); // Sum(103) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[20]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[21]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[22]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[23]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[24]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[25]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[26]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[27]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[20]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[21]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[22]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[23]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[24]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[25]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[26]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[27]); // Sum(103) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[21]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[22]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[23]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[24]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[25]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[26]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[27]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[28]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[21]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[22]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[23]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[24]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[25]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[26]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[27]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[28]); // Sum(103) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[22]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[23]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[24]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[25]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[26]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[27]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[28]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[29]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[22]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[23]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[24]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[25]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[26]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[27]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[28]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[29]); // Sum(103) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[23]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[24]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[25]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[26]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[27]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[28]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[29]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[30]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[23]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[24]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[25]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[26]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[27]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[28]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[29]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[30]); // Sum(103) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[24]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[25]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[26]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[27]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[28]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[29]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[30]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[31]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[24]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[25]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[26]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[27]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[28]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[29]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[30]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[31]); // Sum(103) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(103) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(103) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(103) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(103) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(103) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(103) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(103) AL = inpA[63]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(103) AL = inpA[62]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(103) AL = inpA[61]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(103) AL = inpA[60]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(103) AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(103) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(103) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(103) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(103) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(103) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(103) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(103) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(102) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(103) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(102) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(103) AL = inpA[51]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(100) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(101) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(102) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(100) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(101) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(102) AL = inpA[50]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(98) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(99) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(100) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(98) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(99) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(100) AL = inpA[49]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(96) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(97) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(98) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(96) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(97) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(98) AL = inpA[48]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(96) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(96) r0 = _mm256_add_epi64(r0, r0); // Double(95) r0 = _mm256_madd52hi_epu64(r0, inpA[47], inpA[47]); // Add square(95) res[N + 16] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(96) r1 = _mm256_madd52lo_epu64(r1, inpA[48], inpA[48]); // Add square(96) res[N + 17] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(97) r2 = _mm256_madd52hi_epu64(r2, inpA[48], inpA[48]); // Add square(97) res[N + 18] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(98) r3 = _mm256_madd52lo_epu64(r3, inpA[49], inpA[49]); // Add square(98) res[N + 19] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(99) r4 = _mm256_madd52hi_epu64(r4, inpA[49], inpA[49]); // Add square(99) res[N + 20] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(100) r5 = _mm256_madd52lo_epu64(r5, inpA[50], inpA[50]); // Add square(100) res[N + 21] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(101) r6 = _mm256_madd52hi_epu64(r6, inpA[50], inpA[50]); // Add square(101) res[N + 22] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(102) r7 = _mm256_madd52lo_epu64(r7, inpA[51], inpA[51]); // Add square(102) res[N + 23] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[25]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[26]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[27]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[28]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[29]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[30]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[31]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[32]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[25]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[26]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[27]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[28]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[29]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[30]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[31]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[32]); // Sum(111) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[26]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[27]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[28]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[29]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[30]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[31]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[32]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[33]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[26]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[27]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[28]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[29]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[30]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[31]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[32]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[33]); // Sum(111) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[27]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[28]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[29]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[30]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[31]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[32]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[33]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[34]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[27]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[28]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[29]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[30]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[31]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[32]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[33]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[34]); // Sum(111) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[28]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[29]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[30]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[31]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[32]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[33]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[34]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[35]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[28]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[29]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[30]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[31]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[32]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[33]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[34]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[35]); // Sum(111) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[29]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[30]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[31]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[32]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[33]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[34]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[35]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[36]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[29]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[30]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[31]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[32]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[33]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[34]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[35]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[36]); // Sum(111) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[30]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[31]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[32]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[33]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[34]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[35]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[36]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[37]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[30]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[31]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[32]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[33]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[34]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[35]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[36]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[37]); // Sum(111) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[31]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[32]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[33]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[34]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[35]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[36]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[37]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[38]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[31]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[32]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[33]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[34]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[35]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[36]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[37]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[38]); // Sum(111) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[32]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[33]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[34]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[35]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[36]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[37]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[38]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[39]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[32]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[33]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[34]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[35]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[36]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[37]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[38]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[39]); // Sum(111) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(111) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(111) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(111) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(111) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(111) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(111) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(111) AL = inpA[63]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(111) AL = inpA[62]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(111) AL = inpA[61]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(111) AL = inpA[60]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(111) AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(111) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(111) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(111) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(110) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(111) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(110) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(111) AL = inpA[55]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(108) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(109) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(110) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(108) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(109) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(110) AL = inpA[54]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(106) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(107) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(108) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(106) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(107) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(108) AL = inpA[53]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(104) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(105) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(106) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(104) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(105) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(106) AL = inpA[52]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(104) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(104) r0 = _mm256_add_epi64(r0, r0); // Double(103) r0 = _mm256_madd52hi_epu64(r0, inpA[51], inpA[51]); // Add square(103) res[N + 24] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(104) r1 = _mm256_madd52lo_epu64(r1, inpA[52], inpA[52]); // Add square(104) res[N + 25] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(105) r2 = _mm256_madd52hi_epu64(r2, inpA[52], inpA[52]); // Add square(105) res[N + 26] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(106) r3 = _mm256_madd52lo_epu64(r3, inpA[53], inpA[53]); // Add square(106) res[N + 27] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(107) r4 = _mm256_madd52hi_epu64(r4, inpA[53], inpA[53]); // Add square(107) res[N + 28] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(108) r5 = _mm256_madd52lo_epu64(r5, inpA[54], inpA[54]); // Add square(108) res[N + 29] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(109) r6 = _mm256_madd52hi_epu64(r6, inpA[54], inpA[54]); // Add square(109) res[N + 30] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(110) r7 = _mm256_madd52lo_epu64(r7, inpA[55], inpA[55]); // Add square(110) res[N + 31] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[33]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[34]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[35]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[36]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[37]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[38]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[39]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[40]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[33]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[34]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[35]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[36]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[37]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[38]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[39]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[40]); // Sum(119) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[34]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[35]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[36]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[37]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[38]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[39]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[40]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[41]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[34]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[35]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[36]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[37]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[38]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[39]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[40]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[41]); // Sum(119) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[35]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[36]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[37]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[38]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[39]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[40]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[41]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[42]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[35]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[36]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[37]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[38]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[39]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[40]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[41]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[42]); // Sum(119) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[36]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[37]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[38]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[39]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[40]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[41]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[42]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[43]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[36]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[37]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[38]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[39]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[40]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[41]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[42]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[43]); // Sum(119) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[37]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[38]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[39]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[40]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[41]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[42]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[43]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[44]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[37]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[38]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[39]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[40]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[41]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[42]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[43]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[44]); // Sum(119) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[38]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[39]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[40]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[41]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[42]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[43]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[44]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[45]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[38]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[39]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[40]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[41]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[42]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[43]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[44]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[45]); // Sum(119) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[39]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[40]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[41]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[42]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[43]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[44]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[45]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[46]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[39]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[40]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[41]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[42]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[43]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[44]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[45]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[46]); // Sum(119) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[40]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[41]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[42]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[43]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[44]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[45]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[46]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[47]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[40]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[41]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[42]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[43]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[44]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[45]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[46]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[47]); // Sum(119) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(119) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(119) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(119) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(119) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(119) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(119) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(119) AL = inpA[63]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[55]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[55]); // Sum(119) AL = inpA[62]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(119) AL = inpA[61]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[56]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[57]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[56]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[57]); // Sum(119) AL = inpA[60]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[57]); // Sum(118) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[58]); // Sum(119) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[57]); // Sum(118) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[58]); // Sum(119) AL = inpA[59]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[56]); // Sum(116) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[57]); // Sum(117) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[58]); // Sum(118) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[56]); // Sum(116) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[57]); // Sum(117) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[58]); // Sum(118) AL = inpA[58]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(114) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[56]); // Sum(115) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[57]); // Sum(116) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(114) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[56]); // Sum(115) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[57]); // Sum(116) AL = inpA[57]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(112) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(113) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(114) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(112) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(113) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(114) AL = inpA[56]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(112) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(112) r0 = _mm256_add_epi64(r0, r0); // Double(111) r0 = _mm256_madd52hi_epu64(r0, inpA[55], inpA[55]); // Add square(111) res[N + 32] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(112) r1 = _mm256_madd52lo_epu64(r1, inpA[56], inpA[56]); // Add square(112) res[N + 33] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(113) r2 = _mm256_madd52hi_epu64(r2, inpA[56], inpA[56]); // Add square(113) res[N + 34] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(114) r3 = _mm256_madd52lo_epu64(r3, inpA[57], inpA[57]); // Add square(114) res[N + 35] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(115) r4 = _mm256_madd52hi_epu64(r4, inpA[57], inpA[57]); // Add square(115) res[N + 36] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(116) r5 = _mm256_madd52lo_epu64(r5, inpA[58], inpA[58]); // Add square(116) res[N + 37] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(117) r6 = _mm256_madd52hi_epu64(r6, inpA[58], inpA[58]); // Add square(117) res[N + 38] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(118) r7 = _mm256_madd52lo_epu64(r7, inpA[59], inpA[59]); // Add square(118) res[N + 39] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[41]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[42]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[43]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[44]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[45]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[46]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[47]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[48]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[41]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[42]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[43]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[44]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[45]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[46]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[47]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[48]); // Sum(127) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[42]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[43]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[44]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[45]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[46]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[47]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[48]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[49]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[42]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[43]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[44]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[45]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[46]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[47]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[48]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[49]); // Sum(127) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[43]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[44]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[45]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[46]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[47]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[48]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[49]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[50]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[43]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[44]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[45]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[46]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[47]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[48]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[49]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[50]); // Sum(127) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[44]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[45]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[46]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[47]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[48]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[49]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[50]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[51]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[44]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[45]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[46]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[47]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[48]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[49]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[50]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[51]); // Sum(127) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[45]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[46]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[47]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[48]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[49]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[50]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[51]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[52]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[45]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[46]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[47]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[48]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[49]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[50]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[51]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[52]); // Sum(127) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[46]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[47]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[48]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[49]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[50]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[51]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[52]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[53]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[46]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[47]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[48]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[49]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[50]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[51]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[52]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[53]); // Sum(127) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[47]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[48]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[49]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[50]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[51]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[52]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[53]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[54]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[47]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[48]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[49]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[50]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[51]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[52]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[53]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[54]); // Sum(127) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[48]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[49]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[50]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[51]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[52]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[53]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[54]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[55]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[48]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[49]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[50]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[51]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[52]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[53]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[54]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[55]); // Sum(127) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(127) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[56]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[57]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[56]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[57]); // Sum(127) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[57]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[58]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[57]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[58]); // Sum(127) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[56]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[57]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[58]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[59]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[56]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[57]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[58]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[59]); // Sum(127) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[56]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[57]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[58]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[59]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[60]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[56]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[57]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[58]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[59]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[60]); // Sum(127) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[57]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[58]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[59]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[60]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[61]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[57]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[58]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[59]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[60]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[61]); // Sum(127) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[56]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[57]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[58]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[59]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[60]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[61]); // Sum(126) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[62]); // Sum(127) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[56]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[57]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[58]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[59]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[60]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[61]); // Sum(126) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[62]); // Sum(127) AL = inpA[63]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[56]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[57]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[58]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[59]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[60]); // Sum(124) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[61]); // Sum(125) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[62]); // Sum(126) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[56]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[57]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[58]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[59]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[60]); // Sum(124) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[61]); // Sum(125) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[62]); // Sum(126) AL = inpA[62]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(122) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[60]); // Sum(123) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[61]); // Sum(124) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(122) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[60]); // Sum(123) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[61]); // Sum(124) AL = inpA[61]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[58]); // Sum(120) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[59]); // Sum(121) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[60]); // Sum(122) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[58]); // Sum(120) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[59]); // Sum(121) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[60]); // Sum(122) AL = inpA[60]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[59]); // Sum(120) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[59]); // Sum(120) r0 = _mm256_add_epi64(r0, r0); // Double(119) r0 = _mm256_madd52hi_epu64(r0, inpA[59], inpA[59]); // Add square(119) res[N + 40] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(120) r1 = _mm256_madd52lo_epu64(r1, inpA[60], inpA[60]); // Add square(120) res[N + 41] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(121) r2 = _mm256_madd52hi_epu64(r2, inpA[60], inpA[60]); // Add square(121) res[N + 42] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(122) r3 = _mm256_madd52lo_epu64(r3, inpA[61], inpA[61]); // Add square(122) res[N + 43] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(123) r4 = _mm256_madd52hi_epu64(r4, inpA[61], inpA[61]); // Add square(123) res[N + 44] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(124) r5 = _mm256_madd52lo_epu64(r5, inpA[62], inpA[62]); // Add square(124) res[N + 45] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(125) r6 = _mm256_madd52hi_epu64(r6, inpA[62], inpA[62]); // Add square(125) res[N + 46] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(126) r7 = _mm256_madd52lo_epu64(r7, inpA[63], inpA[63]); // Add square(126) res[N + 47] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[49]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[50]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[51]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[52]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[53]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[54]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[55]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[56]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[49]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[50]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[51]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[52]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[53]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[54]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[55]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[56]); // Sum(135) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[50]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[51]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[52]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[53]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[54]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[55]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[56]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[57]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[50]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[51]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[52]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[53]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[54]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[55]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[56]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[57]); // Sum(135) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[51]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[52]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[53]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[54]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[55]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[56]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[57]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[58]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[51]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[52]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[53]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[54]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[55]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[56]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[57]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[58]); // Sum(135) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[52]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[53]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[54]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[55]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[56]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[57]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[58]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[59]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[52]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[53]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[54]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[55]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[56]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[57]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[58]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[59]); // Sum(135) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[53]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[54]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[55]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[56]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[57]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[58]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[59]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[60]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[53]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[54]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[55]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[56]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[57]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[58]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[59]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[60]); // Sum(135) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[54]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[55]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[56]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[57]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[58]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[59]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[60]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[61]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[54]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[55]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[56]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[57]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[58]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[59]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[60]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[61]); // Sum(135) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[55]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[56]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[57]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[58]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[59]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[60]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[61]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[62]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[55]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[56]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[57]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[58]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[59]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[60]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[61]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[62]); // Sum(135) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[56]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[57]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[58]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[59]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[60]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[61]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[62]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[63]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[56]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[57]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[58]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[59]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[60]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[61]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[62]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[63]); // Sum(135) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[60]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[61]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[62]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[63]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[64]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[60]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[61]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[62]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[63]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[64]); // Sum(135) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[58]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[59]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[60]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[61]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[62]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[63]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[64]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[65]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[58]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[59]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[60]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[61]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[62]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[63]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[64]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[65]); // Sum(135) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[59]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[60]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[61]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[62]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[63]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[64]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[65]); // Sum(134) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[66]); // Sum(135) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[59]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[60]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[61]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[62]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[63]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[64]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[65]); // Sum(134) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[66]); // Sum(135) AL = inpA[67]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[60]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[61]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[62]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[63]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[64]); // Sum(132) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[65]); // Sum(133) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[66]); // Sum(134) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[60]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[61]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[62]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[63]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[64]); // Sum(132) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[65]); // Sum(133) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[66]); // Sum(134) AL = inpA[66]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[61]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[62]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[63]); // Sum(130) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[64]); // Sum(131) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[65]); // Sum(132) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[61]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[62]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[63]); // Sum(130) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[64]); // Sum(131) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[65]); // Sum(132) AL = inpA[65]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[62]); // Sum(128) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[63]); // Sum(129) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[64]); // Sum(130) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[62]); // Sum(128) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[63]); // Sum(129) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[64]); // Sum(130) AL = inpA[64]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[63]); // Sum(128) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[63]); // Sum(128) r0 = _mm256_add_epi64(r0, r0); // Double(127) r0 = _mm256_madd52hi_epu64(r0, inpA[63], inpA[63]); // Add square(127) res[N + 48] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(128) r1 = _mm256_madd52lo_epu64(r1, inpA[64], inpA[64]); // Add square(128) res[N + 49] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(129) r2 = _mm256_madd52hi_epu64(r2, inpA[64], inpA[64]); // Add square(129) res[N + 50] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(130) r3 = _mm256_madd52lo_epu64(r3, inpA[65], inpA[65]); // Add square(130) res[N + 51] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(131) r4 = _mm256_madd52hi_epu64(r4, inpA[65], inpA[65]); // Add square(131) res[N + 52] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(132) r5 = _mm256_madd52lo_epu64(r5, inpA[66], inpA[66]); // Add square(132) res[N + 53] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(133) r6 = _mm256_madd52hi_epu64(r6, inpA[66], inpA[66]); // Add square(133) res[N + 54] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(134) r7 = _mm256_madd52lo_epu64(r7, inpA[67], inpA[67]); // Add square(134) res[N + 55] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[57]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[58]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[59]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[60]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[61]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[62]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[63]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[64]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[57]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[58]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[59]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[60]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[61]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[62]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[63]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[64]); // Sum(143) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[58]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[59]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[60]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[61]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[62]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[63]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[64]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[65]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[58]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[59]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[60]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[61]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[62]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[63]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[64]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[65]); // Sum(143) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[59]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[60]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[61]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[62]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[63]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[64]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[65]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[66]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[59]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[60]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[61]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[62]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[63]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[64]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[65]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[66]); // Sum(143) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[60]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[61]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[62]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[63]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[64]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[65]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[66]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[67]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[60]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[61]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[62]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[63]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[64]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[65]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[66]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[67]); // Sum(143) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[61]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[62]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[63]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[64]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[65]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[66]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[67]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[68]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[61]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[62]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[63]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[64]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[65]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[66]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[67]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[68]); // Sum(143) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[62]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[63]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[64]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[65]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[66]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[67]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[68]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[69]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[62]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[63]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[64]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[65]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[66]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[67]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[68]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[69]); // Sum(143) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[63]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[64]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[65]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[66]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[67]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[68]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[69]); // Sum(142) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[70]); // Sum(143) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[63]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[64]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[65]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[66]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[67]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[68]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[69]); // Sum(142) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[70]); // Sum(143) AL = inpA[71]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[64]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[65]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[66]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[67]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[68]); // Sum(140) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[69]); // Sum(141) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[70]); // Sum(142) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[64]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[65]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[66]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[67]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[68]); // Sum(140) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[69]); // Sum(141) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[70]); // Sum(142) AL = inpA[70]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[65]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[66]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[67]); // Sum(138) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[68]); // Sum(139) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[69]); // Sum(140) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[65]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[66]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[67]); // Sum(138) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[68]); // Sum(139) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[69]); // Sum(140) AL = inpA[69]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[66]); // Sum(136) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[67]); // Sum(137) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[68]); // Sum(138) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[66]); // Sum(136) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[67]); // Sum(137) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[68]); // Sum(138) AL = inpA[68]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[67]); // Sum(136) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[67]); // Sum(136) r0 = _mm256_add_epi64(r0, r0); // Double(135) r0 = _mm256_madd52hi_epu64(r0, inpA[67], inpA[67]); // Add square(135) res[N + 56] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(136) r1 = _mm256_madd52lo_epu64(r1, inpA[68], inpA[68]); // Add square(136) res[N + 57] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(137) r2 = _mm256_madd52hi_epu64(r2, inpA[68], inpA[68]); // Add square(137) res[N + 58] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(138) r3 = _mm256_madd52lo_epu64(r3, inpA[69], inpA[69]); // Add square(138) res[N + 59] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(139) r4 = _mm256_madd52hi_epu64(r4, inpA[69], inpA[69]); // Add square(139) res[N + 60] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(140) r5 = _mm256_madd52lo_epu64(r5, inpA[70], inpA[70]); // Add square(140) res[N + 61] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(141) r6 = _mm256_madd52hi_epu64(r6, inpA[70], inpA[70]); // Add square(141) res[N + 62] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(142) r7 = _mm256_madd52lo_epu64(r7, inpA[71], inpA[71]); // Add square(142) res[N + 63] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; r7 = zero_simd; r8 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[65]); // Sum(144) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[66]); // Sum(145) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[67]); // Sum(146) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[68]); // Sum(147) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[69]); // Sum(148) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[70]); // Sum(149) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[71]); // Sum(150) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[72]); // Sum(151) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[65]); // Sum(144) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[66]); // Sum(145) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[67]); // Sum(146) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[68]); // Sum(147) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[69]); // Sum(148) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[70]); // Sum(149) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[71]); // Sum(150) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[72]); // Sum(151) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[66]); // Sum(144) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[67]); // Sum(145) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[68]); // Sum(146) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[69]); // Sum(147) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[70]); // Sum(148) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[71]); // Sum(149) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[72]); // Sum(150) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[73]); // Sum(151) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[66]); // Sum(144) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[67]); // Sum(145) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[68]); // Sum(146) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[69]); // Sum(147) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[70]); // Sum(148) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[71]); // Sum(149) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[72]); // Sum(150) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[73]); // Sum(151) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[67]); // Sum(144) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[68]); // Sum(145) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[69]); // Sum(146) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[70]); // Sum(147) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[71]); // Sum(148) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[72]); // Sum(149) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[73]); // Sum(150) r7 = _mm256_madd52lo_epu64(r7, AL, inpA[74]); // Sum(151) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[67]); // Sum(144) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[68]); // Sum(145) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[69]); // Sum(146) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[70]); // Sum(147) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[71]); // Sum(148) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[72]); // Sum(149) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[73]); // Sum(150) r8 = _mm256_madd52hi_epu64(r8, AL, inpA[74]); // Sum(151) AL = inpA[75]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[68]); // Sum(144) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[69]); // Sum(145) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[70]); // Sum(146) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[71]); // Sum(147) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[72]); // Sum(148) r5 = _mm256_madd52lo_epu64(r5, AL, inpA[73]); // Sum(149) r6 = _mm256_madd52lo_epu64(r6, AL, inpA[74]); // Sum(150) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[68]); // Sum(144) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[69]); // Sum(145) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[70]); // Sum(146) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[71]); // Sum(147) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[72]); // Sum(148) r6 = _mm256_madd52hi_epu64(r6, AL, inpA[73]); // Sum(149) r7 = _mm256_madd52hi_epu64(r7, AL, inpA[74]); // Sum(150) AL = inpA[74]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[69]); // Sum(144) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[70]); // Sum(145) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[71]); // Sum(146) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[72]); // Sum(147) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[73]); // Sum(148) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[69]); // Sum(144) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[70]); // Sum(145) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[71]); // Sum(146) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[72]); // Sum(147) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[73]); // Sum(148) AL = inpA[73]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[70]); // Sum(144) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[71]); // Sum(145) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[72]); // Sum(146) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[70]); // Sum(144) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[71]); // Sum(145) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[72]); // Sum(146) AL = inpA[72]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[71]); // Sum(144) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[71]); // Sum(144) r0 = _mm256_add_epi64(r0, r0); // Double(143) r0 = _mm256_madd52hi_epu64(r0, inpA[71], inpA[71]); // Add square(143) res[N + 64] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(144) r1 = _mm256_madd52lo_epu64(r1, inpA[72], inpA[72]); // Add square(144) res[N + 65] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(145) r2 = _mm256_madd52hi_epu64(r2, inpA[72], inpA[72]); // Add square(145) res[N + 66] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(146) r3 = _mm256_madd52lo_epu64(r3, inpA[73], inpA[73]); // Add square(146) res[N + 67] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(147) r4 = _mm256_madd52hi_epu64(r4, inpA[73], inpA[73]); // Add square(147) res[N + 68] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(148) r5 = _mm256_madd52lo_epu64(r5, inpA[74], inpA[74]); // Add square(148) res[N + 69] = r5; r6 = _mm256_add_epi64(r6, r6); // Double(149) r6 = _mm256_madd52hi_epu64(r6, inpA[74], inpA[74]); // Add square(149) res[N + 70] = r6; r7 = _mm256_add_epi64(r7, r7); // Double(150) r7 = _mm256_madd52lo_epu64(r7, inpA[75], inpA[75]); // Add square(150) res[N + 71] = r7; r0 = r8; r1 = zero_simd; r2 = zero_simd; r3 = zero_simd; r4 = zero_simd; r5 = zero_simd; r6 = zero_simd; AL = inpA[78]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[73]); // Sum(152) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[74]); // Sum(153) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[75]); // Sum(154) r3 = _mm256_madd52lo_epu64(r3, AL, inpA[76]); // Sum(155) r4 = _mm256_madd52lo_epu64(r4, AL, inpA[77]); // Sum(156) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[73]); // Sum(152) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[74]); // Sum(153) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[75]); // Sum(154) r4 = _mm256_madd52hi_epu64(r4, AL, inpA[76]); // Sum(155) r5 = _mm256_madd52hi_epu64(r5, AL, inpA[77]); // Sum(156) AL = inpA[77]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[74]); // Sum(152) r1 = _mm256_madd52lo_epu64(r1, AL, inpA[75]); // Sum(153) r2 = _mm256_madd52lo_epu64(r2, AL, inpA[76]); // Sum(154) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[74]); // Sum(152) r2 = _mm256_madd52hi_epu64(r2, AL, inpA[75]); // Sum(153) r3 = _mm256_madd52hi_epu64(r3, AL, inpA[76]); // Sum(154) AL = inpA[76]; r0 = _mm256_madd52lo_epu64(r0, AL, inpA[75]); // Sum(152) r1 = _mm256_madd52hi_epu64(r1, AL, inpA[75]); // Sum(152) r0 = _mm256_add_epi64(r0, r0); // Double(151) r0 = _mm256_madd52hi_epu64(r0, inpA[75], inpA[75]); // Add square(151) res[N + 72] = r0; r1 = _mm256_add_epi64(r1, r1); // Double(152) r1 = _mm256_madd52lo_epu64(r1, inpA[76], inpA[76]); // Add square(152) res[N + 73] = r1; r2 = _mm256_add_epi64(r2, r2); // Double(153) r2 = _mm256_madd52hi_epu64(r2, inpA[76], inpA[76]); // Add square(153) res[N + 74] = r2; r3 = _mm256_add_epi64(r3, r3); // Double(154) r3 = _mm256_madd52lo_epu64(r3, inpA[77], inpA[77]); // Add square(154) res[N + 75] = r3; r4 = _mm256_add_epi64(r4, r4); // Double(155) r4 = _mm256_madd52hi_epu64(r4, inpA[77], inpA[77]); // Add square(155) res[N + 76] = r4; r5 = _mm256_add_epi64(r5, r5); // Double(156) r5 = _mm256_madd52lo_epu64(r5, inpA[78], inpA[78]); // Add square(156) res[N + 77] = r5; r0 = r6; // finish up doubling res[N + 78] = _mm256_madd52hi_epu64(zero_simd, inpA[78], inpA[78]); } void AMS52x79_diagonal_mb4(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { const int N = 79; __m256i res[79 * 2]; /* Square only */ ams52x79_square_diagonal_mb4(res, inpA_mb); /* Generate u_i and begin reduction */ ams_reduce_52xN_mb4(res, inpM_mb, k0_mb, N); /* Normalize */ ifma_normalize_ams_52xN_mb4(out_mb, res, N); } #endif // #if ((_MBX == _MBX_L9) && _MBX_AVX_IFMA_SUPPORTED) cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/000077500000000000000000000000001470420105600275255ustar00rootroot00000000000000AMS4x52x20_diagonal_stitched_with_extract_mb8.c000066400000000000000000003035301470420105600402730ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2023-2024 Intel Corporation * * 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 /* Two independent functions are stitched: - 4 squarings - Extracting values from the precomputed tables MulTbl and MulTblx For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if (_MBX >= _MBX_K1) void AMS4x52x20_diagonal_stitched_with_extract_mb8(int64u *out_mb, U64 *mulb, U64 *mulbx, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb, int64u MulTbl[][redLen2K][8], int64u MulTblx[][redLen2K][8], const int64u Idx[8]) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29, res30, res31, res32, res33, res34, res35, res36, res37, res38, res39; const U64 mont_constant = loadu64((U64 *)k0_mb); U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; U64 idx_target = loadu64((U64 *)Idx); __mmask8 extract_sel_mask = cmpeq64_mask(set64(0), idx_target); for (int iter = 0; iter < 4; ++iter) { res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = res30 = res31 = res32 = res33 = res34 = res35 = res36 = res37 = res38 = res39 = get_zero64(); // Calculate full square // stitched with extraction code //*******BEGIN SQUARING CODE SEGMENT************// res01 = fma52lo(res01, a[0], a[1]); // Sum(1) res02 = fma52hi(res02, a[0], a[1]); // Sum(1) res02 = fma52lo(res02, a[0], a[2]); // Sum(2) res03 = fma52hi(res03, a[0], a[2]); // Sum(2) res03 = fma52lo(res03, a[1], a[2]); // Sum(3) res04 = fma52hi(res04, a[1], a[2]); // Sum(3) res03 = fma52lo(res03, a[0], a[3]); // Sum(3) res04 = fma52hi(res04, a[0], a[3]); // Sum(3) res04 = fma52lo(res04, a[1], a[3]); // Sum(4) res05 = fma52hi(res05, a[1], a[3]); // Sum(4) res05 = fma52lo(res05, a[2], a[3]); // Sum(5) res06 = fma52hi(res06, a[2], a[3]); // Sum(5) res04 = fma52lo(res04, a[0], a[4]); // Sum(4) res05 = fma52hi(res05, a[0], a[4]); // Sum(4) res05 = fma52lo(res05, a[1], a[4]); // Sum(5) res06 = fma52hi(res06, a[1], a[4]); // Sum(5) res06 = fma52lo(res06, a[2], a[4]); // Sum(6) res07 = fma52hi(res07, a[2], a[4]); // Sum(6) res07 = fma52lo(res07, a[3], a[4]); // Sum(7) res08 = fma52hi(res08, a[3], a[4]); // Sum(7) res05 = fma52lo(res05, a[0], a[5]); // Sum(5) res06 = fma52hi(res06, a[0], a[5]); // Sum(5) res06 = fma52lo(res06, a[1], a[5]); // Sum(6) res07 = fma52hi(res07, a[1], a[5]); // Sum(6) res07 = fma52lo(res07, a[2], a[5]); // Sum(7) res08 = fma52hi(res08, a[2], a[5]); // Sum(7) res08 = fma52lo(res08, a[3], a[5]); // Sum(8) res09 = fma52hi(res09, a[3], a[5]); // Sum(8) res09 = fma52lo(res09, a[4], a[5]); // Sum(9) res10 = fma52hi(res10, a[4], a[5]); // Sum(9) res06 = fma52lo(res06, a[0], a[6]); // Sum(6) res07 = fma52hi(res07, a[0], a[6]); // Sum(6) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// U64 idx_curr = set64(1 + 4 * iter); __mmask8 extract_sel_mask_next = cmpeq64_mask(idx_curr, idx_target); U64 temp = loadstream64(MulTbl[0 + 4 * iter][0]); mulb[0] = _mm512_mask_mov_epi64(mulb[0], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][1]); mulb[1] = _mm512_mask_mov_epi64(mulb[1], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][2]); mulb[2] = _mm512_mask_mov_epi64(mulb[2], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][3]); mulb[3] = _mm512_mask_mov_epi64(mulb[3], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res07 = fma52lo(res07, a[1], a[6]); // Sum(7) res08 = fma52hi(res08, a[1], a[6]); // Sum(7) res08 = fma52lo(res08, a[2], a[6]); // Sum(8) res09 = fma52hi(res09, a[2], a[6]); // Sum(8) res09 = fma52lo(res09, a[3], a[6]); // Sum(9) res10 = fma52hi(res10, a[3], a[6]); // Sum(9) res10 = fma52lo(res10, a[4], a[6]); // Sum(10) res11 = fma52hi(res11, a[4], a[6]); // Sum(10) res11 = fma52lo(res11, a[5], a[6]); // Sum(11) res12 = fma52hi(res12, a[5], a[6]); // Sum(11) res07 = fma52lo(res07, a[0], a[7]); // Sum(7) res08 = fma52hi(res08, a[0], a[7]); // Sum(7) res08 = fma52lo(res08, a[1], a[7]); // Sum(8) res09 = fma52hi(res09, a[1], a[7]); // Sum(8) res09 = fma52lo(res09, a[2], a[7]); // Sum(9) res10 = fma52hi(res10, a[2], a[7]); // Sum(9) res10 = fma52lo(res10, a[3], a[7]); // Sum(10) res11 = fma52hi(res11, a[3], a[7]); // Sum(10) res11 = fma52lo(res11, a[4], a[7]); // Sum(11) res12 = fma52hi(res12, a[4], a[7]); // Sum(11) res08 = fma52lo(res08, a[0], a[8]); // Sum(8) res09 = fma52hi(res09, a[0], a[8]); // Sum(8) res09 = fma52lo(res09, a[1], a[8]); // Sum(9) res10 = fma52hi(res10, a[1], a[8]); // Sum(9) res10 = fma52lo(res10, a[2], a[8]); // Sum(10) res11 = fma52hi(res11, a[2], a[8]); // Sum(10) res11 = fma52lo(res11, a[3], a[8]); // Sum(11) res12 = fma52hi(res12, a[3], a[8]); // Sum(11) res09 = fma52lo(res09, a[0], a[9]); // Sum(9) res10 = fma52hi(res10, a[0], a[9]); // Sum(9) res10 = fma52lo(res10, a[1], a[9]); // Sum(10) res11 = fma52hi(res11, a[1], a[9]); // Sum(10 //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[0 + 4 * iter][4]); mulb[4] = _mm512_mask_mov_epi64(mulb[4], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][5]); mulb[5] = _mm512_mask_mov_epi64(mulb[5], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][6]); mulb[6] = _mm512_mask_mov_epi64(mulb[6], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][7]); mulb[7] = _mm512_mask_mov_epi64(mulb[7], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res11 = fma52lo(res11, a[2], a[9]); // Sum(11) res12 = fma52hi(res12, a[2], a[9]); // Sum(11) res10 = fma52lo(res10, a[0], a[10]); // Sum(10) res11 = fma52hi(res11, a[0], a[10]); // Sum(10) res11 = fma52lo(res11, a[1], a[10]); // Sum(11) res12 = fma52hi(res12, a[1], a[10]); // Sum(11) res11 = fma52lo(res11, a[0], a[11]); // Sum(11) res12 = fma52hi(res12, a[0], a[11]); // Sum(11) res01 = add64(res01, res01); // Double(1) res02 = add64(res02, res02); // Double(2) res03 = add64(res03, res03); // Double(3) res04 = add64(res04, res04); // Double(4) res05 = add64(res05, res05); // Double(5) res06 = add64(res06, res06); // Double(6) res07 = add64(res07, res07); // Double(7) res08 = add64(res08, res08); // Double(8) res09 = add64(res09, res09); // Double(9) res10 = add64(res10, res10); // Double(10) res11 = add64(res11, res11); // Double(11) res00 = fma52lo(res00, a[0], a[0]); // Add sqr(0) res01 = fma52hi(res01, a[0], a[0]); // Add sqr(0) res02 = fma52lo(res02, a[1], a[1]); // Add sqr(2) res03 = fma52hi(res03, a[1], a[1]); // Add sqr(2) res04 = fma52lo(res04, a[2], a[2]); // Add sqr(4) res05 = fma52hi(res05, a[2], a[2]); // Add sqr(4) res06 = fma52lo(res06, a[3], a[3]); // Add sqr(6) res07 = fma52hi(res07, a[3], a[3]); // Add sqr(6) res08 = fma52lo(res08, a[4], a[4]); // Add sqr(8) res09 = fma52hi(res09, a[4], a[4]); // Add sqr(8) res10 = fma52lo(res10, a[5], a[5]); // Add sqr(10) res11 = fma52hi(res11, a[5], a[5]); // Add sqr(10) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[0 + 4 * iter][8]); mulb[8] = _mm512_mask_mov_epi64(mulb[8], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][9]); mulb[9] = _mm512_mask_mov_epi64(mulb[9], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][10]); mulb[10] = _mm512_mask_mov_epi64(mulb[10], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][11]); mulb[11] = _mm512_mask_mov_epi64(mulb[11], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res12 = fma52lo(res12, a[5], a[7]); // Sum(12) res13 = fma52hi(res13, a[5], a[7]); // Sum(12) res13 = fma52lo(res13, a[6], a[7]); // Sum(13) res14 = fma52hi(res14, a[6], a[7]); // Sum(13) res12 = fma52lo(res12, a[4], a[8]); // Sum(12) res13 = fma52hi(res13, a[4], a[8]); // Sum(12) res13 = fma52lo(res13, a[5], a[8]); // Sum(13) res14 = fma52hi(res14, a[5], a[8]); // Sum(13) res14 = fma52lo(res14, a[6], a[8]); // Sum(14) res15 = fma52hi(res15, a[6], a[8]); // Sum(14) res15 = fma52lo(res15, a[7], a[8]); // Sum(15) res16 = fma52hi(res16, a[7], a[8]); // Sum(15) res12 = fma52lo(res12, a[3], a[9]); // Sum(12) res13 = fma52hi(res13, a[3], a[9]); // Sum(12) res13 = fma52lo(res13, a[4], a[9]); // Sum(13) res14 = fma52hi(res14, a[4], a[9]); // Sum(13) res14 = fma52lo(res14, a[5], a[9]); // Sum(14) res15 = fma52hi(res15, a[5], a[9]); // Sum(14) res15 = fma52lo(res15, a[6], a[9]); // Sum(15) res16 = fma52hi(res16, a[6], a[9]); // Sum(15) res16 = fma52lo(res16, a[7], a[9]); // Sum(16) res17 = fma52hi(res17, a[7], a[9]); // Sum(16) res17 = fma52lo(res17, a[8], a[9]); // Sum(17) res18 = fma52hi(res18, a[8], a[9]); // Sum(17) res12 = fma52lo(res12, a[2], a[10]); // Sum(12) res13 = fma52hi(res13, a[2], a[10]); // Sum(12) res13 = fma52lo(res13, a[3], a[10]); // Sum(13) res14 = fma52hi(res14, a[3], a[10]); // Sum(13) res14 = fma52lo(res14, a[4], a[10]); // Sum(14) res15 = fma52hi(res15, a[4], a[10]); // Sum(14) res15 = fma52lo(res15, a[5], a[10]); // Sum(15) res16 = fma52hi(res16, a[5], a[10]); // Sum(15) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[0 + 4 * iter][12]); mulb[12] = _mm512_mask_mov_epi64(mulb[12], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][13]); mulb[13] = _mm512_mask_mov_epi64(mulb[13], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][14]); mulb[14] = _mm512_mask_mov_epi64(mulb[14], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][15]); mulb[15] = _mm512_mask_mov_epi64(mulb[15], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res16 = fma52lo(res16, a[6], a[10]); // Sum(16) res17 = fma52hi(res17, a[6], a[10]); // Sum(16) res17 = fma52lo(res17, a[7], a[10]); // Sum(17) res18 = fma52hi(res18, a[7], a[10]); // Sum(17) res18 = fma52lo(res18, a[8], a[10]); // Sum(18) res19 = fma52hi(res19, a[8], a[10]); // Sum(18) res19 = fma52lo(res19, a[9], a[10]); // Sum(19) res20 = fma52hi(res20, a[9], a[10]); // Sum(19) res12 = fma52lo(res12, a[1], a[11]); // Sum(12) res13 = fma52hi(res13, a[1], a[11]); // Sum(12) res13 = fma52lo(res13, a[2], a[11]); // Sum(13) res14 = fma52hi(res14, a[2], a[11]); // Sum(13) res14 = fma52lo(res14, a[3], a[11]); // Sum(14) res15 = fma52hi(res15, a[3], a[11]); // Sum(14) res15 = fma52lo(res15, a[4], a[11]); // Sum(15) res16 = fma52hi(res16, a[4], a[11]); // Sum(15) res16 = fma52lo(res16, a[5], a[11]); // Sum(16) res17 = fma52hi(res17, a[5], a[11]); // Sum(16) res17 = fma52lo(res17, a[6], a[11]); // Sum(17) res18 = fma52hi(res18, a[6], a[11]); // Sum(17) res18 = fma52lo(res18, a[7], a[11]); // Sum(18) res19 = fma52hi(res19, a[7], a[11]); // Sum(18) res19 = fma52lo(res19, a[8], a[11]); // Sum(19) res20 = fma52hi(res20, a[8], a[11]); // Sum(19) res20 = fma52lo(res20, a[9], a[11]); // Sum(20) res21 = fma52hi(res21, a[9], a[11]); // Sum(20) res21 = fma52lo(res21, a[10], a[11]); // Sum(21) res22 = fma52hi(res22, a[10], a[11]); // Sum(21) res12 = fma52lo(res12, a[0], a[12]); // Sum(12) res13 = fma52hi(res13, a[0], a[12]); // Sum(12) res13 = fma52lo(res13, a[1], a[12]); // Sum(13) res14 = fma52hi(res14, a[1], a[12]); // Sum(13) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[0 + 4 * iter][16]); mulb[16] = _mm512_mask_mov_epi64(mulb[16], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][17]); mulb[17] = _mm512_mask_mov_epi64(mulb[17], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][18]); mulb[18] = _mm512_mask_mov_epi64(mulb[18], extract_sel_mask, temp); temp = loadstream64(MulTbl[0 + 4 * iter][19]); mulb[19] = _mm512_mask_mov_epi64(mulb[19], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res14 = fma52lo(res14, a[2], a[12]); // Sum(14) res15 = fma52hi(res15, a[2], a[12]); // Sum(14) res15 = fma52lo(res15, a[3], a[12]); // Sum(15) res16 = fma52hi(res16, a[3], a[12]); // Sum(15) res16 = fma52lo(res16, a[4], a[12]); // Sum(16) res17 = fma52hi(res17, a[4], a[12]); // Sum(16) res17 = fma52lo(res17, a[5], a[12]); // Sum(17) res18 = fma52hi(res18, a[5], a[12]); // Sum(17) res18 = fma52lo(res18, a[6], a[12]); // Sum(18) res19 = fma52hi(res19, a[6], a[12]); // Sum(18) res19 = fma52lo(res19, a[7], a[12]); // Sum(19) res20 = fma52hi(res20, a[7], a[12]); // Sum(19) res20 = fma52lo(res20, a[8], a[12]); // Sum(20) res21 = fma52hi(res21, a[8], a[12]); // Sum(20) res21 = fma52lo(res21, a[9], a[12]); // Sum(21) res22 = fma52hi(res22, a[9], a[12]); // Sum(21) res22 = fma52lo(res22, a[10], a[12]); // Sum(22) res23 = fma52hi(res23, a[10], a[12]); // Sum(22) res23 = fma52lo(res23, a[11], a[12]); // Sum(23) res24 = fma52hi(res24, a[11], a[12]); // Sum(23) res13 = fma52lo(res13, a[0], a[13]); // Sum(13) res14 = fma52hi(res14, a[0], a[13]); // Sum(13) res14 = fma52lo(res14, a[1], a[13]); // Sum(14) res15 = fma52hi(res15, a[1], a[13]); // Sum(14) res15 = fma52lo(res15, a[2], a[13]); // Sum(15) res16 = fma52hi(res16, a[2], a[13]); // Sum(15) res16 = fma52lo(res16, a[3], a[13]); // Sum(16) res17 = fma52hi(res17, a[3], a[13]); // Sum(16) res17 = fma52lo(res17, a[4], a[13]); // Sum(17) res18 = fma52hi(res18, a[4], a[13]); // Sum(17) res18 = fma52lo(res18, a[5], a[13]); // Sum(18) res19 = fma52hi(res19, a[5], a[13]); // Sum(18) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// U64 tempx = loadstream64(MulTblx[0 + 4 * iter][0]); mulbx[0] = _mm512_mask_mov_epi64(mulbx[0], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][1]); mulbx[1] = _mm512_mask_mov_epi64(mulbx[1], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][2]); mulbx[2] = _mm512_mask_mov_epi64(mulbx[2], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][3]); mulbx[3] = _mm512_mask_mov_epi64(mulbx[3], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res19 = fma52lo(res19, a[6], a[13]); // Sum(19) res20 = fma52hi(res20, a[6], a[13]); // Sum(19) res20 = fma52lo(res20, a[7], a[13]); // Sum(20) res21 = fma52hi(res21, a[7], a[13]); // Sum(20) res21 = fma52lo(res21, a[8], a[13]); // Sum(21) res22 = fma52hi(res22, a[8], a[13]); // Sum(21) res22 = fma52lo(res22, a[9], a[13]); // Sum(22) res23 = fma52hi(res23, a[9], a[13]); // Sum(22) res23 = fma52lo(res23, a[10], a[13]); // Sum(23) res24 = fma52hi(res24, a[10], a[13]); // Sum(23) res14 = fma52lo(res14, a[0], a[14]); // Sum(14) res15 = fma52hi(res15, a[0], a[14]); // Sum(14) res15 = fma52lo(res15, a[1], a[14]); // Sum(15) res16 = fma52hi(res16, a[1], a[14]); // Sum(15) res16 = fma52lo(res16, a[2], a[14]); // Sum(16) res17 = fma52hi(res17, a[2], a[14]); // Sum(16) res17 = fma52lo(res17, a[3], a[14]); // Sum(17) res18 = fma52hi(res18, a[3], a[14]); // Sum(17) res18 = fma52lo(res18, a[4], a[14]); // Sum(18) res19 = fma52hi(res19, a[4], a[14]); // Sum(18) res19 = fma52lo(res19, a[5], a[14]); // Sum(19) res20 = fma52hi(res20, a[5], a[14]); // Sum(19) res20 = fma52lo(res20, a[6], a[14]); // Sum(20) res21 = fma52hi(res21, a[6], a[14]); // Sum(20) res21 = fma52lo(res21, a[7], a[14]); // Sum(21) res22 = fma52hi(res22, a[7], a[14]); // Sum(21) res22 = fma52lo(res22, a[8], a[14]); // Sum(22) res23 = fma52hi(res23, a[8], a[14]); // Sum(22) res23 = fma52lo(res23, a[9], a[14]); // Sum(23) res24 = fma52hi(res24, a[9], a[14]); // Sum(23) res15 = fma52lo(res15, a[0], a[15]); // Sum(15) res16 = fma52hi(res16, a[0], a[15]); // Sum(15) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[0 + 4 * iter][4]); mulbx[4] = _mm512_mask_mov_epi64(mulbx[4], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][5]); mulbx[5] = _mm512_mask_mov_epi64(mulbx[5], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][6]); mulbx[6] = _mm512_mask_mov_epi64(mulbx[6], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][7]); mulbx[7] = _mm512_mask_mov_epi64(mulbx[7], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res16 = fma52lo(res16, a[1], a[15]); // Sum(16) res17 = fma52hi(res17, a[1], a[15]); // Sum(16) res17 = fma52lo(res17, a[2], a[15]); // Sum(17) res18 = fma52hi(res18, a[2], a[15]); // Sum(17) res18 = fma52lo(res18, a[3], a[15]); // Sum(18) res19 = fma52hi(res19, a[3], a[15]); // Sum(18) res19 = fma52lo(res19, a[4], a[15]); // Sum(19) res20 = fma52hi(res20, a[4], a[15]); // Sum(19) res20 = fma52lo(res20, a[5], a[15]); // Sum(20) res21 = fma52hi(res21, a[5], a[15]); // Sum(20) res21 = fma52lo(res21, a[6], a[15]); // Sum(21) res22 = fma52hi(res22, a[6], a[15]); // Sum(21) res22 = fma52lo(res22, a[7], a[15]); // Sum(22) res23 = fma52hi(res23, a[7], a[15]); // Sum(22) res23 = fma52lo(res23, a[8], a[15]); // Sum(23) res24 = fma52hi(res24, a[8], a[15]); // Sum(23) res16 = fma52lo(res16, a[0], a[16]); // Sum(16) res17 = fma52hi(res17, a[0], a[16]); // Sum(16) res17 = fma52lo(res17, a[1], a[16]); // Sum(17) res18 = fma52hi(res18, a[1], a[16]); // Sum(17) res18 = fma52lo(res18, a[2], a[16]); // Sum(18) res19 = fma52hi(res19, a[2], a[16]); // Sum(18) res19 = fma52lo(res19, a[3], a[16]); // Sum(19) res20 = fma52hi(res20, a[3], a[16]); // Sum(19) res20 = fma52lo(res20, a[4], a[16]); // Sum(20) res21 = fma52hi(res21, a[4], a[16]); // Sum(20) res21 = fma52lo(res21, a[5], a[16]); // Sum(21) res22 = fma52hi(res22, a[5], a[16]); // Sum(21) res22 = fma52lo(res22, a[6], a[16]); // Sum(22) res23 = fma52hi(res23, a[6], a[16]); // Sum(22) res23 = fma52lo(res23, a[7], a[16]); // Sum(23) res24 = fma52hi(res24, a[7], a[16]); // Sum(23) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[0 + 4 * iter][8]); mulbx[8] = _mm512_mask_mov_epi64(mulbx[8], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][9]); mulbx[9] = _mm512_mask_mov_epi64(mulbx[9], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][10]); mulbx[10] = _mm512_mask_mov_epi64(mulbx[10], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][11]); mulbx[11] = _mm512_mask_mov_epi64(mulbx[11], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res17 = fma52lo(res17, a[0], a[17]); // Sum(17) res18 = fma52hi(res18, a[0], a[17]); // Sum(17) res18 = fma52lo(res18, a[1], a[17]); // Sum(18) res19 = fma52hi(res19, a[1], a[17]); // Sum(18) res19 = fma52lo(res19, a[2], a[17]); // Sum(19) res20 = fma52hi(res20, a[2], a[17]); // Sum(19) res20 = fma52lo(res20, a[3], a[17]); // Sum(20) res21 = fma52hi(res21, a[3], a[17]); // Sum(20) res21 = fma52lo(res21, a[4], a[17]); // Sum(21) res22 = fma52hi(res22, a[4], a[17]); // Sum(21) res22 = fma52lo(res22, a[5], a[17]); // Sum(22) res23 = fma52hi(res23, a[5], a[17]); // Sum(22) res23 = fma52lo(res23, a[6], a[17]); // Sum(23) res24 = fma52hi(res24, a[6], a[17]); // Sum(23) res18 = fma52lo(res18, a[0], a[18]); // Sum(18) res19 = fma52hi(res19, a[0], a[18]); // Sum(18) res19 = fma52lo(res19, a[1], a[18]); // Sum(19) res20 = fma52hi(res20, a[1], a[18]); // Sum(19) res20 = fma52lo(res20, a[2], a[18]); // Sum(20) res21 = fma52hi(res21, a[2], a[18]); // Sum(20) res21 = fma52lo(res21, a[3], a[18]); // Sum(21) res22 = fma52hi(res22, a[3], a[18]); // Sum(21) res22 = fma52lo(res22, a[4], a[18]); // Sum(22) res23 = fma52hi(res23, a[4], a[18]); // Sum(22) res23 = fma52lo(res23, a[5], a[18]); // Sum(23) res24 = fma52hi(res24, a[5], a[18]); // Sum(23) res19 = fma52lo(res19, a[0], a[19]); // Sum(19) res20 = fma52hi(res20, a[0], a[19]); // Sum(19) res20 = fma52lo(res20, a[1], a[19]); // Sum(20) res21 = fma52hi(res21, a[1], a[19]); // Sum(20) res21 = fma52lo(res21, a[2], a[19]); // Sum(21) res22 = fma52hi(res22, a[2], a[19]); // Sum(21) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[0 + 4 * iter][12]); mulbx[12] = _mm512_mask_mov_epi64(mulbx[12], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][13]); mulbx[13] = _mm512_mask_mov_epi64(mulbx[13], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][14]); mulbx[14] = _mm512_mask_mov_epi64(mulbx[14], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][15]); mulbx[15] = _mm512_mask_mov_epi64(mulbx[15], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res22 = fma52lo(res22, a[3], a[19]); // Sum(22) res23 = fma52hi(res23, a[3], a[19]); // Sum(22) res23 = fma52lo(res23, a[4], a[19]); // Sum(23) res24 = fma52hi(res24, a[4], a[19]); // Sum(23) res12 = add64(res12, res12); // Double(12) res13 = add64(res13, res13); // Double(13) res14 = add64(res14, res14); // Double(14) res15 = add64(res15, res15); // Double(15) res16 = add64(res16, res16); // Double(16) res17 = add64(res17, res17); // Double(17) res18 = add64(res18, res18); // Double(18) res19 = add64(res19, res19); // Double(19) res20 = add64(res20, res20); // Double(20) res21 = add64(res21, res21); // Double(21) res22 = add64(res22, res22); // Double(22) res23 = add64(res23, res23); // Double(23) res12 = fma52lo(res12, a[6], a[6]); // Add sqr(12) res13 = fma52hi(res13, a[6], a[6]); // Add sqr(12) res14 = fma52lo(res14, a[7], a[7]); // Add sqr(14) res15 = fma52hi(res15, a[7], a[7]); // Add sqr(14) res16 = fma52lo(res16, a[8], a[8]); // Add sqr(16) res17 = fma52hi(res17, a[8], a[8]); // Add sqr(16) res18 = fma52lo(res18, a[9], a[9]); // Add sqr(18) res19 = fma52hi(res19, a[9], a[9]); // Add sqr(18) res20 = fma52lo(res20, a[10], a[10]); // Add sqr(20) res21 = fma52hi(res21, a[10], a[10]); // Add sqr(20) res22 = fma52lo(res22, a[11], a[11]); // Add sqr(22) res23 = fma52hi(res23, a[11], a[11]); // Add sqr(22) res24 = fma52lo(res24, a[11], a[13]); // Sum(24) res25 = fma52hi(res25, a[11], a[13]); // Sum(24) res25 = fma52lo(res25, a[12], a[13]); // Sum(25) res26 = fma52hi(res26, a[12], a[13]); // Sum(25) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[0 + 4 * iter][16]); mulbx[16] = _mm512_mask_mov_epi64(mulbx[16], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][17]); mulbx[17] = _mm512_mask_mov_epi64(mulbx[17], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][18]); mulbx[18] = _mm512_mask_mov_epi64(mulbx[18], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[0 + 4 * iter][19]); mulbx[19] = _mm512_mask_mov_epi64(mulbx[19], extract_sel_mask, tempx); extract_sel_mask = extract_sel_mask_next; //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res24 = fma52lo(res24, a[10], a[14]); // Sum(24) res25 = fma52hi(res25, a[10], a[14]); // Sum(24) res25 = fma52lo(res25, a[11], a[14]); // Sum(25) res26 = fma52hi(res26, a[11], a[14]); // Sum(25) res26 = fma52lo(res26, a[12], a[14]); // Sum(26) res27 = fma52hi(res27, a[12], a[14]); // Sum(26) res27 = fma52lo(res27, a[13], a[14]); // Sum(27) res28 = fma52hi(res28, a[13], a[14]); // Sum(27) res24 = fma52lo(res24, a[9], a[15]); // Sum(24) res25 = fma52hi(res25, a[9], a[15]); // Sum(24) res25 = fma52lo(res25, a[10], a[15]); // Sum(25) res26 = fma52hi(res26, a[10], a[15]); // Sum(25) res26 = fma52lo(res26, a[11], a[15]); // Sum(26) res27 = fma52hi(res27, a[11], a[15]); // Sum(26) res27 = fma52lo(res27, a[12], a[15]); // Sum(27) res28 = fma52hi(res28, a[12], a[15]); // Sum(27) res28 = fma52lo(res28, a[13], a[15]); // Sum(28) res29 = fma52hi(res29, a[13], a[15]); // Sum(28) res29 = fma52lo(res29, a[14], a[15]); // Sum(29) res30 = fma52hi(res30, a[14], a[15]); // Sum(29) res24 = fma52lo(res24, a[8], a[16]); // Sum(24) res25 = fma52hi(res25, a[8], a[16]); // Sum(24) res25 = fma52lo(res25, a[9], a[16]); // Sum(25) res26 = fma52hi(res26, a[9], a[16]); // Sum(25) res26 = fma52lo(res26, a[10], a[16]); // Sum(26) res27 = fma52hi(res27, a[10], a[16]); // Sum(26) res27 = fma52lo(res27, a[11], a[16]); // Sum(27) res28 = fma52hi(res28, a[11], a[16]); // Sum(27) res28 = fma52lo(res28, a[12], a[16]); // Sum(28) res29 = fma52hi(res29, a[12], a[16]); // Sum(28) res29 = fma52lo(res29, a[13], a[16]); // Sum(29) res30 = fma52hi(res30, a[13], a[16]); // Sum(29) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// idx_curr = set64(2 + 4 * iter); extract_sel_mask_next = cmpeq64_mask(idx_curr, idx_target); temp = loadstream64(MulTbl[1 + 4 * iter][0]); mulb[0] = _mm512_mask_mov_epi64(mulb[0], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][1]); mulb[1] = _mm512_mask_mov_epi64(mulb[1], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][2]); mulb[2] = _mm512_mask_mov_epi64(mulb[2], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][3]); mulb[3] = _mm512_mask_mov_epi64(mulb[3], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res30 = fma52lo(res30, a[14], a[16]); // Sum(30) res31 = fma52hi(res31, a[14], a[16]); // Sum(30) res31 = fma52lo(res31, a[15], a[16]); // Sum(31) res32 = fma52hi(res32, a[15], a[16]); // Sum(31) res24 = fma52lo(res24, a[7], a[17]); // Sum(24) res25 = fma52hi(res25, a[7], a[17]); // Sum(24) res25 = fma52lo(res25, a[8], a[17]); // Sum(25) res26 = fma52hi(res26, a[8], a[17]); // Sum(25) res26 = fma52lo(res26, a[9], a[17]); // Sum(26) res27 = fma52hi(res27, a[9], a[17]); // Sum(26) res27 = fma52lo(res27, a[10], a[17]); // Sum(27) res28 = fma52hi(res28, a[10], a[17]); // Sum(27) res28 = fma52lo(res28, a[11], a[17]); // Sum(28) res29 = fma52hi(res29, a[11], a[17]); // Sum(28) res29 = fma52lo(res29, a[12], a[17]); // Sum(29) res30 = fma52hi(res30, a[12], a[17]); // Sum(29) res30 = fma52lo(res30, a[13], a[17]); // Sum(30) res31 = fma52hi(res31, a[13], a[17]); // Sum(30) res31 = fma52lo(res31, a[14], a[17]); // Sum(31) res32 = fma52hi(res32, a[14], a[17]); // Sum(31) res32 = fma52lo(res32, a[15], a[17]); // Sum(32) res33 = fma52hi(res33, a[15], a[17]); // Sum(32) res33 = fma52lo(res33, a[16], a[17]); // Sum(33) res34 = fma52hi(res34, a[16], a[17]); // Sum(33) res24 = fma52lo(res24, a[6], a[18]); // Sum(24) res25 = fma52hi(res25, a[6], a[18]); // Sum(24) res25 = fma52lo(res25, a[7], a[18]); // Sum(25) res26 = fma52hi(res26, a[7], a[18]); // Sum(25) res26 = fma52lo(res26, a[8], a[18]); // Sum(26) res27 = fma52hi(res27, a[8], a[18]); // Sum(26) res27 = fma52lo(res27, a[9], a[18]); // Sum(27) res28 = fma52hi(res28, a[9], a[18]); // Sum(27) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[1 + 4 * iter][4]); mulb[4] = _mm512_mask_mov_epi64(mulb[4], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][5]); mulb[5] = _mm512_mask_mov_epi64(mulb[5], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][6]); mulb[6] = _mm512_mask_mov_epi64(mulb[6], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][7]); mulb[7] = _mm512_mask_mov_epi64(mulb[7], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res28 = fma52lo(res28, a[10], a[18]); // Sum(28) res29 = fma52hi(res29, a[10], a[18]); // Sum(28) res29 = fma52lo(res29, a[11], a[18]); // Sum(29) res30 = fma52hi(res30, a[11], a[18]); // Sum(29) res30 = fma52lo(res30, a[12], a[18]); // Sum(30) res31 = fma52hi(res31, a[12], a[18]); // Sum(30) res31 = fma52lo(res31, a[13], a[18]); // Sum(31) res32 = fma52hi(res32, a[13], a[18]); // Sum(31) res32 = fma52lo(res32, a[14], a[18]); // Sum(32) res33 = fma52hi(res33, a[14], a[18]); // Sum(32) res33 = fma52lo(res33, a[15], a[18]); // Sum(33) res34 = fma52hi(res34, a[15], a[18]); // Sum(33) res34 = fma52lo(res34, a[16], a[18]); // Sum(34) res35 = fma52hi(res35, a[16], a[18]); // Sum(34) res35 = fma52lo(res35, a[17], a[18]); // Sum(35) res36 = fma52hi(res36, a[17], a[18]); // Sum(35) res24 = fma52lo(res24, a[5], a[19]); // Sum(24) res25 = fma52hi(res25, a[5], a[19]); // Sum(24) res25 = fma52lo(res25, a[6], a[19]); // Sum(25) res26 = fma52hi(res26, a[6], a[19]); // Sum(25) res26 = fma52lo(res26, a[7], a[19]); // Sum(26) res27 = fma52hi(res27, a[7], a[19]); // Sum(26) res27 = fma52lo(res27, a[8], a[19]); // Sum(27) res28 = fma52hi(res28, a[8], a[19]); // Sum(27) res28 = fma52lo(res28, a[9], a[19]); // Sum(28) res29 = fma52hi(res29, a[9], a[19]); // Sum(28) res29 = fma52lo(res29, a[10], a[19]); // Sum(29) res30 = fma52hi(res30, a[10], a[19]); // Sum(29) res30 = fma52lo(res30, a[11], a[19]); // Sum(30) res31 = fma52hi(res31, a[11], a[19]); // Sum(30) res31 = fma52lo(res31, a[12], a[19]); // Sum(31) res32 = fma52hi(res32, a[12], a[19]); // Sum(31) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[1 + 4 * iter][8]); mulb[8] = _mm512_mask_mov_epi64(mulb[8], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][9]); mulb[9] = _mm512_mask_mov_epi64(mulb[9], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][10]); mulb[10] = _mm512_mask_mov_epi64(mulb[10], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][11]); mulb[11] = _mm512_mask_mov_epi64(mulb[11], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res32 = fma52lo(res32, a[13], a[19]); // Sum(32) res33 = fma52hi(res33, a[13], a[19]); // Sum(32) res33 = fma52lo(res33, a[14], a[19]); // Sum(33) res34 = fma52hi(res34, a[14], a[19]); // Sum(33) res34 = fma52lo(res34, a[15], a[19]); // Sum(34) res35 = fma52hi(res35, a[15], a[19]); // Sum(34) res35 = fma52lo(res35, a[16], a[19]); // Sum(35) res36 = fma52hi(res36, a[16], a[19]); // Sum(35) res24 = add64(res24, res24); // Double(24) res25 = add64(res25, res25); // Double(25) res26 = add64(res26, res26); // Double(26) res27 = add64(res27, res27); // Double(27) res28 = add64(res28, res28); // Double(28) res29 = add64(res29, res29); // Double(29) res30 = add64(res30, res30); // Double(30) res31 = add64(res31, res31); // Double(31) res32 = add64(res32, res32); // Double(32) res33 = add64(res33, res33); // Double(33) res34 = add64(res34, res34); // Double(34) res35 = add64(res35, res35); // Double(35) res24 = fma52lo(res24, a[12], a[12]); // Add sqr(24) res25 = fma52hi(res25, a[12], a[12]); // Add sqr(24) res26 = fma52lo(res26, a[13], a[13]); // Add sqr(26) res27 = fma52hi(res27, a[13], a[13]); // Add sqr(26) res28 = fma52lo(res28, a[14], a[14]); // Add sqr(28) res29 = fma52hi(res29, a[14], a[14]); // Add sqr(28) res30 = fma52lo(res30, a[15], a[15]); // Add sqr(30) res31 = fma52hi(res31, a[15], a[15]); // Add sqr(30) res32 = fma52lo(res32, a[16], a[16]); // Add sqr(32) res33 = fma52hi(res33, a[16], a[16]); // Add sqr(32) res34 = fma52lo(res34, a[17], a[17]); // Add sqr(34) res35 = fma52hi(res35, a[17], a[17]); // Add sqr(34) //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[1 + 4 * iter][12]); mulb[12] = _mm512_mask_mov_epi64(mulb[12], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][13]); mulb[13] = _mm512_mask_mov_epi64(mulb[13], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][14]); mulb[14] = _mm512_mask_mov_epi64(mulb[14], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][15]); mulb[15] = _mm512_mask_mov_epi64(mulb[15], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res36 = fma52lo(res36, a[17], a[19]); // Sum(36) res37 = fma52hi(res37, a[17], a[19]); // Sum(36) res37 = fma52lo(res37, a[18], a[19]); // Sum(37) res38 = fma52hi(res38, a[18], a[19]); // Sum(37) res36 = add64(res36, res36); // Double(36) res37 = add64(res37, res37); // Double(37) res38 = add64(res38, res38); // Double(38) res36 = fma52lo(res36, a[18], a[18]); // Add sqr(36) res37 = fma52hi(res37, a[18], a[18]); // Add sqr(36) res38 = fma52lo(res38, a[19], a[19]); // Add sqr(38) res39 = fma52hi(res39, a[19], a[19]); // Add sqr(38) // Begin Reduction U64 u0 = mul52lo(res00, mont_constant); res00 = fma52lo(res00, u0, m[0]); res01 = fma52hi(res01, u0, m[0]); res01 = fma52lo(res01, u0, m[1]); res02 = fma52hi(res02, u0, m[1]); res01 = add64(res01, srli64(res00, DIGIT_SIZE)); U64 u1 = mul52lo(res01, mont_constant); // early multiplication for the reduction of res01 res02 = fma52lo(res02, u0, m[2]); res03 = fma52hi(res03, u0, m[2]); res03 = fma52lo(res03, u0, m[3]); res04 = fma52hi(res04, u0, m[3]); res04 = fma52lo(res04, u0, m[4]); res05 = fma52hi(res05, u0, m[4]); res05 = fma52lo(res05, u0, m[5]); res06 = fma52hi(res06, u0, m[5]); res06 = fma52lo(res06, u0, m[6]); res07 = fma52hi(res07, u0, m[6]); res07 = fma52lo(res07, u0, m[7]); res08 = fma52hi(res08, u0, m[7]); res08 = fma52lo(res08, u0, m[8]); res09 = fma52hi(res09, u0, m[8]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[1 + 4 * iter][16]); mulb[16] = _mm512_mask_mov_epi64(mulb[16], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][17]); mulb[17] = _mm512_mask_mov_epi64(mulb[17], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][18]); mulb[18] = _mm512_mask_mov_epi64(mulb[18], extract_sel_mask, temp); temp = loadstream64(MulTbl[1 + 4 * iter][19]); mulb[19] = _mm512_mask_mov_epi64(mulb[19], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res09 = fma52lo(res09, u0, m[9]); res10 = fma52hi(res10, u0, m[9]); res10 = fma52lo(res10, u0, m[10]); res11 = fma52hi(res11, u0, m[10]); res11 = fma52lo(res11, u0, m[11]); res12 = fma52hi(res12, u0, m[11]); res12 = fma52lo(res12, u0, m[12]); res13 = fma52hi(res13, u0, m[12]); res13 = fma52lo(res13, u0, m[13]); res14 = fma52hi(res14, u0, m[13]); res14 = fma52lo(res14, u0, m[14]); res15 = fma52hi(res15, u0, m[14]); res15 = fma52lo(res15, u0, m[15]); res16 = fma52hi(res16, u0, m[15]); res16 = fma52lo(res16, u0, m[16]); res17 = fma52hi(res17, u0, m[16]); res17 = fma52lo(res17, u0, m[17]); res18 = fma52hi(res18, u0, m[17]); res18 = fma52lo(res18, u0, m[18]); res19 = fma52hi(res19, u0, m[18]); res19 = fma52lo(res19, u0, m[19]); res20 = fma52hi(res20, u0, m[19]); res01 = fma52lo(res01, u1, m[0]); res02 = fma52hi(res02, u1, m[0]); res02 = fma52lo(res02, u1, m[1]); res03 = fma52hi(res03, u1, m[1]); res02 = add64(res02, srli64(res01, DIGIT_SIZE)); U64 u2 = mul52lo(res02, mont_constant); // early multiplication for the reduction of res02 res03 = fma52lo(res03, u1, m[2]); res04 = fma52hi(res04, u1, m[2]); res04 = fma52lo(res04, u1, m[3]); res05 = fma52hi(res05, u1, m[3]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[1 + 4 * iter][0]); mulbx[0] = _mm512_mask_mov_epi64(mulbx[0], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][1]); mulbx[1] = _mm512_mask_mov_epi64(mulbx[1], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][2]); mulbx[2] = _mm512_mask_mov_epi64(mulbx[2], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][3]); mulbx[3] = _mm512_mask_mov_epi64(mulbx[3], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res05 = fma52lo(res05, u1, m[4]); res06 = fma52hi(res06, u1, m[4]); res06 = fma52lo(res06, u1, m[5]); res07 = fma52hi(res07, u1, m[5]); res07 = fma52lo(res07, u1, m[6]); res08 = fma52hi(res08, u1, m[6]); res08 = fma52lo(res08, u1, m[7]); res09 = fma52hi(res09, u1, m[7]); res09 = fma52lo(res09, u1, m[8]); res10 = fma52hi(res10, u1, m[8]); res10 = fma52lo(res10, u1, m[9]); res11 = fma52hi(res11, u1, m[9]); res11 = fma52lo(res11, u1, m[10]); res12 = fma52hi(res12, u1, m[10]); res12 = fma52lo(res12, u1, m[11]); res13 = fma52hi(res13, u1, m[11]); res13 = fma52lo(res13, u1, m[12]); res14 = fma52hi(res14, u1, m[12]); res14 = fma52lo(res14, u1, m[13]); res15 = fma52hi(res15, u1, m[13]); res15 = fma52lo(res15, u1, m[14]); res16 = fma52hi(res16, u1, m[14]); res16 = fma52lo(res16, u1, m[15]); res17 = fma52hi(res17, u1, m[15]); res17 = fma52lo(res17, u1, m[16]); res18 = fma52hi(res18, u1, m[16]); res18 = fma52lo(res18, u1, m[17]); res19 = fma52hi(res19, u1, m[17]); res19 = fma52lo(res19, u1, m[18]); res20 = fma52hi(res20, u1, m[18]); res20 = fma52lo(res20, u1, m[19]); res21 = fma52hi(res21, u1, m[19]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[1 + 4 * iter][4]); mulbx[4] = _mm512_mask_mov_epi64(mulbx[4], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][5]); mulbx[5] = _mm512_mask_mov_epi64(mulbx[5], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][6]); mulbx[6] = _mm512_mask_mov_epi64(mulbx[6], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][7]); mulbx[7] = _mm512_mask_mov_epi64(mulbx[7], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res02 = fma52lo(res02, u2, m[0]); res03 = fma52hi(res03, u2, m[0]); res03 = fma52lo(res03, u2, m[1]); res04 = fma52hi(res04, u2, m[1]); res03 = add64(res03, srli64(res02, DIGIT_SIZE)); U64 u3 = mul52lo(res03, mont_constant); // early multiplication for the reduction of res03 res04 = fma52lo(res04, u2, m[2]); res05 = fma52hi(res05, u2, m[2]); res05 = fma52lo(res05, u2, m[3]); res06 = fma52hi(res06, u2, m[3]); res06 = fma52lo(res06, u2, m[4]); res07 = fma52hi(res07, u2, m[4]); res07 = fma52lo(res07, u2, m[5]); res08 = fma52hi(res08, u2, m[5]); res08 = fma52lo(res08, u2, m[6]); res09 = fma52hi(res09, u2, m[6]); res09 = fma52lo(res09, u2, m[7]); res10 = fma52hi(res10, u2, m[7]); res10 = fma52lo(res10, u2, m[8]); res11 = fma52hi(res11, u2, m[8]); res11 = fma52lo(res11, u2, m[9]); res12 = fma52hi(res12, u2, m[9]); res12 = fma52lo(res12, u2, m[10]); res13 = fma52hi(res13, u2, m[10]); res13 = fma52lo(res13, u2, m[11]); res14 = fma52hi(res14, u2, m[11]); res14 = fma52lo(res14, u2, m[12]); res15 = fma52hi(res15, u2, m[12]); res15 = fma52lo(res15, u2, m[13]); res16 = fma52hi(res16, u2, m[13]); res16 = fma52lo(res16, u2, m[14]); res17 = fma52hi(res17, u2, m[14]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[1 + 4 * iter][8]); mulbx[8] = _mm512_mask_mov_epi64(mulbx[8], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][9]); mulbx[9] = _mm512_mask_mov_epi64(mulbx[9], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][10]); mulbx[10] = _mm512_mask_mov_epi64(mulbx[10], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][11]); mulbx[11] = _mm512_mask_mov_epi64(mulbx[11], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res17 = fma52lo(res17, u2, m[15]); res18 = fma52hi(res18, u2, m[15]); res18 = fma52lo(res18, u2, m[16]); res19 = fma52hi(res19, u2, m[16]); res19 = fma52lo(res19, u2, m[17]); res20 = fma52hi(res20, u2, m[17]); res20 = fma52lo(res20, u2, m[18]); res21 = fma52hi(res21, u2, m[18]); res21 = fma52lo(res21, u2, m[19]); res22 = fma52hi(res22, u2, m[19]); res03 = fma52lo(res03, u3, m[0]); res04 = fma52hi(res04, u3, m[0]); res04 = fma52lo(res04, u3, m[1]); res05 = fma52hi(res05, u3, m[1]); res04 = add64(res04, srli64(res03, DIGIT_SIZE)); U64 u4 = mul52lo(res04, mont_constant); // early multiplication for the reduction of res04 res05 = fma52lo(res05, u3, m[2]); res06 = fma52hi(res06, u3, m[2]); res06 = fma52lo(res06, u3, m[3]); res07 = fma52hi(res07, u3, m[3]); res07 = fma52lo(res07, u3, m[4]); res08 = fma52hi(res08, u3, m[4]); res08 = fma52lo(res08, u3, m[5]); res09 = fma52hi(res09, u3, m[5]); res09 = fma52lo(res09, u3, m[6]); res10 = fma52hi(res10, u3, m[6]); res10 = fma52lo(res10, u3, m[7]); res11 = fma52hi(res11, u3, m[7]); res11 = fma52lo(res11, u3, m[8]); res12 = fma52hi(res12, u3, m[8]); res12 = fma52lo(res12, u3, m[9]); res13 = fma52hi(res13, u3, m[9]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[1 + 4 * iter][12]); mulbx[12] = _mm512_mask_mov_epi64(mulbx[12], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][13]); mulbx[13] = _mm512_mask_mov_epi64(mulbx[13], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][14]); mulbx[14] = _mm512_mask_mov_epi64(mulbx[14], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][15]); mulbx[15] = _mm512_mask_mov_epi64(mulbx[15], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res13 = fma52lo(res13, u3, m[10]); res14 = fma52hi(res14, u3, m[10]); res14 = fma52lo(res14, u3, m[11]); res15 = fma52hi(res15, u3, m[11]); res15 = fma52lo(res15, u3, m[12]); res16 = fma52hi(res16, u3, m[12]); res16 = fma52lo(res16, u3, m[13]); res17 = fma52hi(res17, u3, m[13]); res17 = fma52lo(res17, u3, m[14]); res18 = fma52hi(res18, u3, m[14]); res18 = fma52lo(res18, u3, m[15]); res19 = fma52hi(res19, u3, m[15]); res19 = fma52lo(res19, u3, m[16]); res20 = fma52hi(res20, u3, m[16]); res20 = fma52lo(res20, u3, m[17]); res21 = fma52hi(res21, u3, m[17]); res21 = fma52lo(res21, u3, m[18]); res22 = fma52hi(res22, u3, m[18]); res22 = fma52lo(res22, u3, m[19]); res23 = fma52hi(res23, u3, m[19]); res04 = fma52lo(res04, u4, m[0]); res05 = fma52hi(res05, u4, m[0]); res05 = fma52lo(res05, u4, m[1]); res06 = fma52hi(res06, u4, m[1]); res05 = add64(res05, srli64(res04, DIGIT_SIZE)); U64 u5 = mul52lo(res05, mont_constant); // early multiplication for the reduction of res05 res06 = fma52lo(res06, u4, m[2]); res07 = fma52hi(res07, u4, m[2]); res07 = fma52lo(res07, u4, m[3]); res08 = fma52hi(res08, u4, m[3]); res08 = fma52lo(res08, u4, m[4]); res09 = fma52hi(res09, u4, m[4]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[1 + 4 * iter][16]); mulbx[16] = _mm512_mask_mov_epi64(mulbx[16], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][17]); mulbx[17] = _mm512_mask_mov_epi64(mulbx[17], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][18]); mulbx[18] = _mm512_mask_mov_epi64(mulbx[18], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[1 + 4 * iter][19]); mulbx[19] = _mm512_mask_mov_epi64(mulbx[19], extract_sel_mask, tempx); extract_sel_mask = extract_sel_mask_next; //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res09 = fma52lo(res09, u4, m[5]); res10 = fma52hi(res10, u4, m[5]); res10 = fma52lo(res10, u4, m[6]); res11 = fma52hi(res11, u4, m[6]); res11 = fma52lo(res11, u4, m[7]); res12 = fma52hi(res12, u4, m[7]); res12 = fma52lo(res12, u4, m[8]); res13 = fma52hi(res13, u4, m[8]); res13 = fma52lo(res13, u4, m[9]); res14 = fma52hi(res14, u4, m[9]); res14 = fma52lo(res14, u4, m[10]); res15 = fma52hi(res15, u4, m[10]); res15 = fma52lo(res15, u4, m[11]); res16 = fma52hi(res16, u4, m[11]); res16 = fma52lo(res16, u4, m[12]); res17 = fma52hi(res17, u4, m[12]); res17 = fma52lo(res17, u4, m[13]); res18 = fma52hi(res18, u4, m[13]); res18 = fma52lo(res18, u4, m[14]); res19 = fma52hi(res19, u4, m[14]); res19 = fma52lo(res19, u4, m[15]); res20 = fma52hi(res20, u4, m[15]); res20 = fma52lo(res20, u4, m[16]); res21 = fma52hi(res21, u4, m[16]); res21 = fma52lo(res21, u4, m[17]); res22 = fma52hi(res22, u4, m[17]); res22 = fma52lo(res22, u4, m[18]); res23 = fma52hi(res23, u4, m[18]); res23 = fma52lo(res23, u4, m[19]); res24 = fma52hi(res24, u4, m[19]); res05 = fma52lo(res05, u5, m[0]); res06 = fma52hi(res06, u5, m[0]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// idx_curr = set64(3 + 4 * iter); extract_sel_mask_next = cmpeq64_mask(idx_curr, idx_target); temp = loadstream64(MulTbl[2 + 4 * iter][0]); mulb[0] = _mm512_mask_mov_epi64(mulb[0], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][1]); mulb[1] = _mm512_mask_mov_epi64(mulb[1], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][2]); mulb[2] = _mm512_mask_mov_epi64(mulb[2], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][3]); mulb[3] = _mm512_mask_mov_epi64(mulb[3], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res06 = fma52lo(res06, u5, m[1]); res07 = fma52hi(res07, u5, m[1]); res06 = add64(res06, srli64(res05, DIGIT_SIZE)); U64 u6 = mul52lo(res06, mont_constant); // early multiplication for the reduction of res06 res07 = fma52lo(res07, u5, m[2]); res08 = fma52hi(res08, u5, m[2]); res08 = fma52lo(res08, u5, m[3]); res09 = fma52hi(res09, u5, m[3]); res09 = fma52lo(res09, u5, m[4]); res10 = fma52hi(res10, u5, m[4]); res10 = fma52lo(res10, u5, m[5]); res11 = fma52hi(res11, u5, m[5]); res11 = fma52lo(res11, u5, m[6]); res12 = fma52hi(res12, u5, m[6]); res12 = fma52lo(res12, u5, m[7]); res13 = fma52hi(res13, u5, m[7]); res13 = fma52lo(res13, u5, m[8]); res14 = fma52hi(res14, u5, m[8]); res14 = fma52lo(res14, u5, m[9]); res15 = fma52hi(res15, u5, m[9]); res15 = fma52lo(res15, u5, m[10]); res16 = fma52hi(res16, u5, m[10]); res16 = fma52lo(res16, u5, m[11]); res17 = fma52hi(res17, u5, m[11]); res17 = fma52lo(res17, u5, m[12]); res18 = fma52hi(res18, u5, m[12]); res18 = fma52lo(res18, u5, m[13]); res19 = fma52hi(res19, u5, m[13]); res19 = fma52lo(res19, u5, m[14]); res20 = fma52hi(res20, u5, m[14]); res20 = fma52lo(res20, u5, m[15]); res21 = fma52hi(res21, u5, m[15]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[2 + 4 * iter][4]); mulb[4] = _mm512_mask_mov_epi64(mulb[4], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][5]); mulb[5] = _mm512_mask_mov_epi64(mulb[5], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][6]); mulb[6] = _mm512_mask_mov_epi64(mulb[6], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][7]); mulb[7] = _mm512_mask_mov_epi64(mulb[7], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res21 = fma52lo(res21, u5, m[16]); res22 = fma52hi(res22, u5, m[16]); res22 = fma52lo(res22, u5, m[17]); res23 = fma52hi(res23, u5, m[17]); res23 = fma52lo(res23, u5, m[18]); res24 = fma52hi(res24, u5, m[18]); res24 = fma52lo(res24, u5, m[19]); res25 = fma52hi(res25, u5, m[19]); res06 = fma52lo(res06, u6, m[0]); res07 = fma52hi(res07, u6, m[0]); res07 = fma52lo(res07, u6, m[1]); res08 = fma52hi(res08, u6, m[1]); res07 = add64(res07, srli64(res06, DIGIT_SIZE)); U64 u7 = mul52lo(res07, mont_constant); // early multiplication for the reduction of res07 res08 = fma52lo(res08, u6, m[2]); res09 = fma52hi(res09, u6, m[2]); res09 = fma52lo(res09, u6, m[3]); res10 = fma52hi(res10, u6, m[3]); res10 = fma52lo(res10, u6, m[4]); res11 = fma52hi(res11, u6, m[4]); res11 = fma52lo(res11, u6, m[5]); res12 = fma52hi(res12, u6, m[5]); res12 = fma52lo(res12, u6, m[6]); res13 = fma52hi(res13, u6, m[6]); res13 = fma52lo(res13, u6, m[7]); res14 = fma52hi(res14, u6, m[7]); res14 = fma52lo(res14, u6, m[8]); res15 = fma52hi(res15, u6, m[8]); res15 = fma52lo(res15, u6, m[9]); res16 = fma52hi(res16, u6, m[9]); res16 = fma52lo(res16, u6, m[10]); res17 = fma52hi(res17, u6, m[10]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[2 + 4 * iter][8]); mulb[8] = _mm512_mask_mov_epi64(mulb[8], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][9]); mulb[9] = _mm512_mask_mov_epi64(mulb[9], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][10]); mulb[10] = _mm512_mask_mov_epi64(mulb[10], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][11]); mulb[11] = _mm512_mask_mov_epi64(mulb[11], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res17 = fma52lo(res17, u6, m[11]); res18 = fma52hi(res18, u6, m[11]); res18 = fma52lo(res18, u6, m[12]); res19 = fma52hi(res19, u6, m[12]); res19 = fma52lo(res19, u6, m[13]); res20 = fma52hi(res20, u6, m[13]); res20 = fma52lo(res20, u6, m[14]); res21 = fma52hi(res21, u6, m[14]); res21 = fma52lo(res21, u6, m[15]); res22 = fma52hi(res22, u6, m[15]); res22 = fma52lo(res22, u6, m[16]); res23 = fma52hi(res23, u6, m[16]); res23 = fma52lo(res23, u6, m[17]); res24 = fma52hi(res24, u6, m[17]); res24 = fma52lo(res24, u6, m[18]); res25 = fma52hi(res25, u6, m[18]); res25 = fma52lo(res25, u6, m[19]); res26 = fma52hi(res26, u6, m[19]); res07 = fma52lo(res07, u7, m[0]); res08 = fma52hi(res08, u7, m[0]); res08 = fma52lo(res08, u7, m[1]); res09 = fma52hi(res09, u7, m[1]); res08 = add64(res08, srli64(res07, DIGIT_SIZE)); U64 u8 = mul52lo(res08, mont_constant); // early multiplication for the reduction of res08 res09 = fma52lo(res09, u7, m[2]); res10 = fma52hi(res10, u7, m[2]); res10 = fma52lo(res10, u7, m[3]); res11 = fma52hi(res11, u7, m[3]); res11 = fma52lo(res11, u7, m[4]); res12 = fma52hi(res12, u7, m[4]); res12 = fma52lo(res12, u7, m[5]); res13 = fma52hi(res13, u7, m[5]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[2 + 4 * iter][12]); mulb[12] = _mm512_mask_mov_epi64(mulb[12], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][13]); mulb[13] = _mm512_mask_mov_epi64(mulb[13], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][14]); mulb[14] = _mm512_mask_mov_epi64(mulb[14], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][15]); mulb[15] = _mm512_mask_mov_epi64(mulb[15], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res13 = fma52lo(res13, u7, m[6]); res14 = fma52hi(res14, u7, m[6]); res14 = fma52lo(res14, u7, m[7]); res15 = fma52hi(res15, u7, m[7]); res15 = fma52lo(res15, u7, m[8]); res16 = fma52hi(res16, u7, m[8]); res16 = fma52lo(res16, u7, m[9]); res17 = fma52hi(res17, u7, m[9]); res17 = fma52lo(res17, u7, m[10]); res18 = fma52hi(res18, u7, m[10]); res18 = fma52lo(res18, u7, m[11]); res19 = fma52hi(res19, u7, m[11]); res19 = fma52lo(res19, u7, m[12]); res20 = fma52hi(res20, u7, m[12]); res20 = fma52lo(res20, u7, m[13]); res21 = fma52hi(res21, u7, m[13]); res21 = fma52lo(res21, u7, m[14]); res22 = fma52hi(res22, u7, m[14]); res22 = fma52lo(res22, u7, m[15]); res23 = fma52hi(res23, u7, m[15]); res23 = fma52lo(res23, u7, m[16]); res24 = fma52hi(res24, u7, m[16]); res24 = fma52lo(res24, u7, m[17]); res25 = fma52hi(res25, u7, m[17]); res25 = fma52lo(res25, u7, m[18]); res26 = fma52hi(res26, u7, m[18]); res26 = fma52lo(res26, u7, m[19]); res27 = fma52hi(res27, u7, m[19]); res08 = fma52lo(res08, u8, m[0]); res09 = fma52hi(res09, u8, m[0]); res09 = fma52lo(res09, u8, m[1]); res10 = fma52hi(res10, u8, m[1]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[2 + 4 * iter][16]); mulb[16] = _mm512_mask_mov_epi64(mulb[16], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][17]); mulb[17] = _mm512_mask_mov_epi64(mulb[17], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][18]); mulb[18] = _mm512_mask_mov_epi64(mulb[18], extract_sel_mask, temp); temp = loadstream64(MulTbl[2 + 4 * iter][19]); mulb[19] = _mm512_mask_mov_epi64(mulb[19], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res09 = add64(res09, srli64(res08, DIGIT_SIZE)); U64 u9 = mul52lo(res09, mont_constant); // early multiplication for the reduction of res09 res10 = fma52lo(res10, u8, m[2]); res11 = fma52hi(res11, u8, m[2]); res11 = fma52lo(res11, u8, m[3]); res12 = fma52hi(res12, u8, m[3]); res12 = fma52lo(res12, u8, m[4]); res13 = fma52hi(res13, u8, m[4]); res13 = fma52lo(res13, u8, m[5]); res14 = fma52hi(res14, u8, m[5]); res14 = fma52lo(res14, u8, m[6]); res15 = fma52hi(res15, u8, m[6]); res15 = fma52lo(res15, u8, m[7]); res16 = fma52hi(res16, u8, m[7]); res16 = fma52lo(res16, u8, m[8]); res17 = fma52hi(res17, u8, m[8]); res17 = fma52lo(res17, u8, m[9]); res18 = fma52hi(res18, u8, m[9]); res18 = fma52lo(res18, u8, m[10]); res19 = fma52hi(res19, u8, m[10]); res19 = fma52lo(res19, u8, m[11]); res20 = fma52hi(res20, u8, m[11]); res20 = fma52lo(res20, u8, m[12]); res21 = fma52hi(res21, u8, m[12]); res21 = fma52lo(res21, u8, m[13]); res22 = fma52hi(res22, u8, m[13]); res22 = fma52lo(res22, u8, m[14]); res23 = fma52hi(res23, u8, m[14]); res23 = fma52lo(res23, u8, m[15]); res24 = fma52hi(res24, u8, m[15]); res24 = fma52lo(res24, u8, m[16]); res25 = fma52hi(res25, u8, m[16]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[2 + 4 * iter][0]); mulbx[0] = _mm512_mask_mov_epi64(mulbx[0], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][1]); mulbx[1] = _mm512_mask_mov_epi64(mulbx[1], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][2]); mulbx[2] = _mm512_mask_mov_epi64(mulbx[2], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][3]); mulbx[3] = _mm512_mask_mov_epi64(mulbx[3], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res25 = fma52lo(res25, u8, m[17]); res26 = fma52hi(res26, u8, m[17]); res26 = fma52lo(res26, u8, m[18]); res27 = fma52hi(res27, u8, m[18]); res27 = fma52lo(res27, u8, m[19]); res28 = fma52hi(res28, u8, m[19]); res09 = fma52lo(res09, u9, m[0]); res10 = fma52hi(res10, u9, m[0]); res10 = fma52lo(res10, u9, m[1]); res11 = fma52hi(res11, u9, m[1]); res10 = add64(res10, srli64(res09, DIGIT_SIZE)); U64 u10 = mul52lo(res10, mont_constant); // early multiplication for the reduction of res10 res11 = fma52lo(res11, u9, m[2]); res12 = fma52hi(res12, u9, m[2]); res12 = fma52lo(res12, u9, m[3]); res13 = fma52hi(res13, u9, m[3]); res13 = fma52lo(res13, u9, m[4]); res14 = fma52hi(res14, u9, m[4]); res14 = fma52lo(res14, u9, m[5]); res15 = fma52hi(res15, u9, m[5]); res15 = fma52lo(res15, u9, m[6]); res16 = fma52hi(res16, u9, m[6]); res16 = fma52lo(res16, u9, m[7]); res17 = fma52hi(res17, u9, m[7]); res17 = fma52lo(res17, u9, m[8]); res18 = fma52hi(res18, u9, m[8]); res18 = fma52lo(res18, u9, m[9]); res19 = fma52hi(res19, u9, m[9]); res19 = fma52lo(res19, u9, m[10]); res20 = fma52hi(res20, u9, m[10]); res20 = fma52lo(res20, u9, m[11]); res21 = fma52hi(res21, u9, m[11]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[2 + 4 * iter][4]); mulbx[4] = _mm512_mask_mov_epi64(mulbx[4], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][5]); mulbx[5] = _mm512_mask_mov_epi64(mulbx[5], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][6]); mulbx[6] = _mm512_mask_mov_epi64(mulbx[6], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][7]); mulbx[7] = _mm512_mask_mov_epi64(mulbx[7], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res21 = fma52lo(res21, u9, m[12]); res22 = fma52hi(res22, u9, m[12]); res22 = fma52lo(res22, u9, m[13]); res23 = fma52hi(res23, u9, m[13]); res23 = fma52lo(res23, u9, m[14]); res24 = fma52hi(res24, u9, m[14]); res24 = fma52lo(res24, u9, m[15]); res25 = fma52hi(res25, u9, m[15]); res25 = fma52lo(res25, u9, m[16]); res26 = fma52hi(res26, u9, m[16]); res26 = fma52lo(res26, u9, m[17]); res27 = fma52hi(res27, u9, m[17]); res27 = fma52lo(res27, u9, m[18]); res28 = fma52hi(res28, u9, m[18]); res28 = fma52lo(res28, u9, m[19]); res29 = fma52hi(res29, u9, m[19]); res10 = fma52lo(res10, u10, m[0]); res11 = fma52hi(res11, u10, m[0]); res11 = fma52lo(res11, u10, m[1]); res12 = fma52hi(res12, u10, m[1]); res11 = add64(res11, srli64(res10, DIGIT_SIZE)); U64 u11 = mul52lo(res11, mont_constant); // early multiplication for the reduction of res11 res12 = fma52lo(res12, u10, m[2]); res13 = fma52hi(res13, u10, m[2]); res13 = fma52lo(res13, u10, m[3]); res14 = fma52hi(res14, u10, m[3]); res14 = fma52lo(res14, u10, m[4]); res15 = fma52hi(res15, u10, m[4]); res15 = fma52lo(res15, u10, m[5]); res16 = fma52hi(res16, u10, m[5]); res16 = fma52lo(res16, u10, m[6]); res17 = fma52hi(res17, u10, m[6]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[2 + 4 * iter][8]); mulbx[8] = _mm512_mask_mov_epi64(mulbx[8], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][9]); mulbx[9] = _mm512_mask_mov_epi64(mulbx[9], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][10]); mulbx[10] = _mm512_mask_mov_epi64(mulbx[10], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][11]); mulbx[11] = _mm512_mask_mov_epi64(mulbx[11], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res17 = fma52lo(res17, u10, m[7]); res18 = fma52hi(res18, u10, m[7]); res18 = fma52lo(res18, u10, m[8]); res19 = fma52hi(res19, u10, m[8]); res19 = fma52lo(res19, u10, m[9]); res20 = fma52hi(res20, u10, m[9]); res20 = fma52lo(res20, u10, m[10]); res21 = fma52hi(res21, u10, m[10]); res21 = fma52lo(res21, u10, m[11]); res22 = fma52hi(res22, u10, m[11]); res22 = fma52lo(res22, u10, m[12]); res23 = fma52hi(res23, u10, m[12]); res23 = fma52lo(res23, u10, m[13]); res24 = fma52hi(res24, u10, m[13]); res24 = fma52lo(res24, u10, m[14]); res25 = fma52hi(res25, u10, m[14]); res25 = fma52lo(res25, u10, m[15]); res26 = fma52hi(res26, u10, m[15]); res26 = fma52lo(res26, u10, m[16]); res27 = fma52hi(res27, u10, m[16]); res27 = fma52lo(res27, u10, m[17]); res28 = fma52hi(res28, u10, m[17]); res28 = fma52lo(res28, u10, m[18]); res29 = fma52hi(res29, u10, m[18]); res29 = fma52lo(res29, u10, m[19]); res30 = fma52hi(res30, u10, m[19]); res11 = fma52lo(res11, u11, m[0]); res12 = fma52hi(res12, u11, m[0]); res12 = fma52lo(res12, u11, m[1]); res13 = fma52hi(res13, u11, m[1]); res12 = add64(res12, srli64(res11, DIGIT_SIZE)); U64 u12 = mul52lo(res12, mont_constant); // early multiplication for the reduction of res12 //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[2 + 4 * iter][12]); mulbx[12] = _mm512_mask_mov_epi64(mulbx[12], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][13]); mulbx[13] = _mm512_mask_mov_epi64(mulbx[13], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][14]); mulbx[14] = _mm512_mask_mov_epi64(mulbx[14], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][15]); mulbx[15] = _mm512_mask_mov_epi64(mulbx[15], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res13 = fma52lo(res13, u11, m[2]); res14 = fma52hi(res14, u11, m[2]); res14 = fma52lo(res14, u11, m[3]); res15 = fma52hi(res15, u11, m[3]); res15 = fma52lo(res15, u11, m[4]); res16 = fma52hi(res16, u11, m[4]); res16 = fma52lo(res16, u11, m[5]); res17 = fma52hi(res17, u11, m[5]); res17 = fma52lo(res17, u11, m[6]); res18 = fma52hi(res18, u11, m[6]); res18 = fma52lo(res18, u11, m[7]); res19 = fma52hi(res19, u11, m[7]); res19 = fma52lo(res19, u11, m[8]); res20 = fma52hi(res20, u11, m[8]); res20 = fma52lo(res20, u11, m[9]); res21 = fma52hi(res21, u11, m[9]); res21 = fma52lo(res21, u11, m[10]); res22 = fma52hi(res22, u11, m[10]); res22 = fma52lo(res22, u11, m[11]); res23 = fma52hi(res23, u11, m[11]); res23 = fma52lo(res23, u11, m[12]); res24 = fma52hi(res24, u11, m[12]); res24 = fma52lo(res24, u11, m[13]); res25 = fma52hi(res25, u11, m[13]); res25 = fma52lo(res25, u11, m[14]); res26 = fma52hi(res26, u11, m[14]); res26 = fma52lo(res26, u11, m[15]); res27 = fma52hi(res27, u11, m[15]); res27 = fma52lo(res27, u11, m[16]); res28 = fma52hi(res28, u11, m[16]); res28 = fma52lo(res28, u11, m[17]); res29 = fma52hi(res29, u11, m[17]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[2 + 4 * iter][16]); mulbx[16] = _mm512_mask_mov_epi64(mulbx[16], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][17]); mulbx[17] = _mm512_mask_mov_epi64(mulbx[17], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][18]); mulbx[18] = _mm512_mask_mov_epi64(mulbx[18], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[2 + 4 * iter][19]); mulbx[19] = _mm512_mask_mov_epi64(mulbx[19], extract_sel_mask, tempx); extract_sel_mask = extract_sel_mask_next; //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res29 = fma52lo(res29, u11, m[18]); res30 = fma52hi(res30, u11, m[18]); res30 = fma52lo(res30, u11, m[19]); res31 = fma52hi(res31, u11, m[19]); res12 = fma52lo(res12, u12, m[0]); res13 = fma52hi(res13, u12, m[0]); res13 = fma52lo(res13, u12, m[1]); res14 = fma52hi(res14, u12, m[1]); res13 = add64(res13, srli64(res12, DIGIT_SIZE)); U64 u13 = mul52lo(res13, mont_constant); // early multiplication for the reduction of res13 res14 = fma52lo(res14, u12, m[2]); res15 = fma52hi(res15, u12, m[2]); res15 = fma52lo(res15, u12, m[3]); res16 = fma52hi(res16, u12, m[3]); res16 = fma52lo(res16, u12, m[4]); res17 = fma52hi(res17, u12, m[4]); res17 = fma52lo(res17, u12, m[5]); res18 = fma52hi(res18, u12, m[5]); res18 = fma52lo(res18, u12, m[6]); res19 = fma52hi(res19, u12, m[6]); res19 = fma52lo(res19, u12, m[7]); res20 = fma52hi(res20, u12, m[7]); res20 = fma52lo(res20, u12, m[8]); res21 = fma52hi(res21, u12, m[8]); res21 = fma52lo(res21, u12, m[9]); res22 = fma52hi(res22, u12, m[9]); res22 = fma52lo(res22, u12, m[10]); res23 = fma52hi(res23, u12, m[10]); res23 = fma52lo(res23, u12, m[11]); res24 = fma52hi(res24, u12, m[11]); res24 = fma52lo(res24, u12, m[12]); res25 = fma52hi(res25, u12, m[12]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// idx_curr = set64(4 + 4 * iter); extract_sel_mask_next = cmpeq64_mask(idx_curr, idx_target); temp = loadstream64(MulTbl[3 + 4 * iter][0]); mulb[0] = _mm512_mask_mov_epi64(mulb[0], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][1]); mulb[1] = _mm512_mask_mov_epi64(mulb[1], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][2]); mulb[2] = _mm512_mask_mov_epi64(mulb[2], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][3]); mulb[3] = _mm512_mask_mov_epi64(mulb[3], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res25 = fma52lo(res25, u12, m[13]); res26 = fma52hi(res26, u12, m[13]); res26 = fma52lo(res26, u12, m[14]); res27 = fma52hi(res27, u12, m[14]); res27 = fma52lo(res27, u12, m[15]); res28 = fma52hi(res28, u12, m[15]); res28 = fma52lo(res28, u12, m[16]); res29 = fma52hi(res29, u12, m[16]); res29 = fma52lo(res29, u12, m[17]); res30 = fma52hi(res30, u12, m[17]); res30 = fma52lo(res30, u12, m[18]); res31 = fma52hi(res31, u12, m[18]); res31 = fma52lo(res31, u12, m[19]); res32 = fma52hi(res32, u12, m[19]); res13 = fma52lo(res13, u13, m[0]); res14 = fma52hi(res14, u13, m[0]); res14 = fma52lo(res14, u13, m[1]); res15 = fma52hi(res15, u13, m[1]); res14 = add64(res14, srli64(res13, DIGIT_SIZE)); U64 u14 = mul52lo(res14, mont_constant); // early multiplication for the reduction of res14 res15 = fma52lo(res15, u13, m[2]); res16 = fma52hi(res16, u13, m[2]); res16 = fma52lo(res16, u13, m[3]); res17 = fma52hi(res17, u13, m[3]); res17 = fma52lo(res17, u13, m[4]); res18 = fma52hi(res18, u13, m[4]); res18 = fma52lo(res18, u13, m[5]); res19 = fma52hi(res19, u13, m[5]); res19 = fma52lo(res19, u13, m[6]); res20 = fma52hi(res20, u13, m[6]); res20 = fma52lo(res20, u13, m[7]); res21 = fma52hi(res21, u13, m[7]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[3 + 4 * iter][4]); mulb[4] = _mm512_mask_mov_epi64(mulb[4], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][5]); mulb[5] = _mm512_mask_mov_epi64(mulb[5], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][6]); mulb[6] = _mm512_mask_mov_epi64(mulb[6], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][7]); mulb[7] = _mm512_mask_mov_epi64(mulb[7], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res21 = fma52lo(res21, u13, m[8]); res22 = fma52hi(res22, u13, m[8]); res22 = fma52lo(res22, u13, m[9]); res23 = fma52hi(res23, u13, m[9]); res23 = fma52lo(res23, u13, m[10]); res24 = fma52hi(res24, u13, m[10]); res24 = fma52lo(res24, u13, m[11]); res25 = fma52hi(res25, u13, m[11]); res25 = fma52lo(res25, u13, m[12]); res26 = fma52hi(res26, u13, m[12]); res26 = fma52lo(res26, u13, m[13]); res27 = fma52hi(res27, u13, m[13]); res27 = fma52lo(res27, u13, m[14]); res28 = fma52hi(res28, u13, m[14]); res28 = fma52lo(res28, u13, m[15]); res29 = fma52hi(res29, u13, m[15]); res29 = fma52lo(res29, u13, m[16]); res30 = fma52hi(res30, u13, m[16]); res30 = fma52lo(res30, u13, m[17]); res31 = fma52hi(res31, u13, m[17]); res31 = fma52lo(res31, u13, m[18]); res32 = fma52hi(res32, u13, m[18]); res32 = fma52lo(res32, u13, m[19]); res33 = fma52hi(res33, u13, m[19]); res14 = fma52lo(res14, u14, m[0]); res15 = fma52hi(res15, u14, m[0]); res15 = fma52lo(res15, u14, m[1]); res16 = fma52hi(res16, u14, m[1]); res15 = add64(res15, srli64(res14, DIGIT_SIZE)); U64 u15 = mul52lo(res15, mont_constant); // early multiplication for the reduction of res15 res16 = fma52lo(res16, u14, m[2]); res17 = fma52hi(res17, u14, m[2]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[3 + 4 * iter][8]); mulb[8] = _mm512_mask_mov_epi64(mulb[8], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][9]); mulb[9] = _mm512_mask_mov_epi64(mulb[9], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][10]); mulb[10] = _mm512_mask_mov_epi64(mulb[10], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][11]); mulb[11] = _mm512_mask_mov_epi64(mulb[11], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res17 = fma52lo(res17, u14, m[3]); res18 = fma52hi(res18, u14, m[3]); res18 = fma52lo(res18, u14, m[4]); res19 = fma52hi(res19, u14, m[4]); res19 = fma52lo(res19, u14, m[5]); res20 = fma52hi(res20, u14, m[5]); res20 = fma52lo(res20, u14, m[6]); res21 = fma52hi(res21, u14, m[6]); res21 = fma52lo(res21, u14, m[7]); res22 = fma52hi(res22, u14, m[7]); res22 = fma52lo(res22, u14, m[8]); res23 = fma52hi(res23, u14, m[8]); res23 = fma52lo(res23, u14, m[9]); res24 = fma52hi(res24, u14, m[9]); res24 = fma52lo(res24, u14, m[10]); res25 = fma52hi(res25, u14, m[10]); res25 = fma52lo(res25, u14, m[11]); res26 = fma52hi(res26, u14, m[11]); res26 = fma52lo(res26, u14, m[12]); res27 = fma52hi(res27, u14, m[12]); res27 = fma52lo(res27, u14, m[13]); res28 = fma52hi(res28, u14, m[13]); res28 = fma52lo(res28, u14, m[14]); res29 = fma52hi(res29, u14, m[14]); res29 = fma52lo(res29, u14, m[15]); res30 = fma52hi(res30, u14, m[15]); res30 = fma52lo(res30, u14, m[16]); res31 = fma52hi(res31, u14, m[16]); res31 = fma52lo(res31, u14, m[17]); res32 = fma52hi(res32, u14, m[17]); res32 = fma52lo(res32, u14, m[18]); res33 = fma52hi(res33, u14, m[18]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[3 + 4 * iter][12]); mulb[12] = _mm512_mask_mov_epi64(mulb[12], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][13]); mulb[13] = _mm512_mask_mov_epi64(mulb[13], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][14]); mulb[14] = _mm512_mask_mov_epi64(mulb[14], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][15]); mulb[15] = _mm512_mask_mov_epi64(mulb[15], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res33 = fma52lo(res33, u14, m[19]); res34 = fma52hi(res34, u14, m[19]); res15 = fma52lo(res15, u15, m[0]); res16 = fma52hi(res16, u15, m[0]); res16 = fma52lo(res16, u15, m[1]); res17 = fma52hi(res17, u15, m[1]); res16 = add64(res16, srli64(res15, DIGIT_SIZE)); U64 u16 = mul52lo(res16, mont_constant); // early multiplication for the reduction of res16 res17 = fma52lo(res17, u15, m[2]); res18 = fma52hi(res18, u15, m[2]); res18 = fma52lo(res18, u15, m[3]); res19 = fma52hi(res19, u15, m[3]); res19 = fma52lo(res19, u15, m[4]); res20 = fma52hi(res20, u15, m[4]); res20 = fma52lo(res20, u15, m[5]); res21 = fma52hi(res21, u15, m[5]); res21 = fma52lo(res21, u15, m[6]); res22 = fma52hi(res22, u15, m[6]); res22 = fma52lo(res22, u15, m[7]); res23 = fma52hi(res23, u15, m[7]); res23 = fma52lo(res23, u15, m[8]); res24 = fma52hi(res24, u15, m[8]); res24 = fma52lo(res24, u15, m[9]); res25 = fma52hi(res25, u15, m[9]); res25 = fma52lo(res25, u15, m[10]); res26 = fma52hi(res26, u15, m[10]); res26 = fma52lo(res26, u15, m[11]); res27 = fma52hi(res27, u15, m[11]); res27 = fma52lo(res27, u15, m[12]); res28 = fma52hi(res28, u15, m[12]); res28 = fma52lo(res28, u15, m[13]); res29 = fma52hi(res29, u15, m[13]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// temp = loadstream64(MulTbl[3 + 4 * iter][16]); mulb[16] = _mm512_mask_mov_epi64(mulb[16], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][17]); mulb[17] = _mm512_mask_mov_epi64(mulb[17], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][18]); mulb[18] = _mm512_mask_mov_epi64(mulb[18], extract_sel_mask, temp); temp = loadstream64(MulTbl[3 + 4 * iter][19]); mulb[19] = _mm512_mask_mov_epi64(mulb[19], extract_sel_mask, temp); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res29 = fma52lo(res29, u15, m[14]); res30 = fma52hi(res30, u15, m[14]); res30 = fma52lo(res30, u15, m[15]); res31 = fma52hi(res31, u15, m[15]); res31 = fma52lo(res31, u15, m[16]); res32 = fma52hi(res32, u15, m[16]); res32 = fma52lo(res32, u15, m[17]); res33 = fma52hi(res33, u15, m[17]); res33 = fma52lo(res33, u15, m[18]); res34 = fma52hi(res34, u15, m[18]); res34 = fma52lo(res34, u15, m[19]); res35 = fma52hi(res35, u15, m[19]); res16 = fma52lo(res16, u16, m[0]); res17 = fma52hi(res17, u16, m[0]); res17 = fma52lo(res17, u16, m[1]); res18 = fma52hi(res18, u16, m[1]); res17 = add64(res17, srli64(res16, DIGIT_SIZE)); U64 u17 = mul52lo(res17, mont_constant); // early multiplication for the reduction of res17 res18 = fma52lo(res18, u16, m[2]); res19 = fma52hi(res19, u16, m[2]); res19 = fma52lo(res19, u16, m[3]); res20 = fma52hi(res20, u16, m[3]); res20 = fma52lo(res20, u16, m[4]); res21 = fma52hi(res21, u16, m[4]); res21 = fma52lo(res21, u16, m[5]); res22 = fma52hi(res22, u16, m[5]); res22 = fma52lo(res22, u16, m[6]); res23 = fma52hi(res23, u16, m[6]); res23 = fma52lo(res23, u16, m[7]); res24 = fma52hi(res24, u16, m[7]); res24 = fma52lo(res24, u16, m[8]); res25 = fma52hi(res25, u16, m[8]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[3 + 4 * iter][0]); mulbx[0] = _mm512_mask_mov_epi64(mulbx[0], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][1]); mulbx[1] = _mm512_mask_mov_epi64(mulbx[1], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][2]); mulbx[2] = _mm512_mask_mov_epi64(mulbx[2], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][3]); mulbx[3] = _mm512_mask_mov_epi64(mulbx[3], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res25 = fma52lo(res25, u16, m[9]); res26 = fma52hi(res26, u16, m[9]); res26 = fma52lo(res26, u16, m[10]); res27 = fma52hi(res27, u16, m[10]); res27 = fma52lo(res27, u16, m[11]); res28 = fma52hi(res28, u16, m[11]); res28 = fma52lo(res28, u16, m[12]); res29 = fma52hi(res29, u16, m[12]); res29 = fma52lo(res29, u16, m[13]); res30 = fma52hi(res30, u16, m[13]); res30 = fma52lo(res30, u16, m[14]); res31 = fma52hi(res31, u16, m[14]); res31 = fma52lo(res31, u16, m[15]); res32 = fma52hi(res32, u16, m[15]); res32 = fma52lo(res32, u16, m[16]); res33 = fma52hi(res33, u16, m[16]); res33 = fma52lo(res33, u16, m[17]); res34 = fma52hi(res34, u16, m[17]); res34 = fma52lo(res34, u16, m[18]); res35 = fma52hi(res35, u16, m[18]); res35 = fma52lo(res35, u16, m[19]); res36 = fma52hi(res36, u16, m[19]); res17 = fma52lo(res17, u17, m[0]); res18 = fma52hi(res18, u17, m[0]); res18 = fma52lo(res18, u17, m[1]); res19 = fma52hi(res19, u17, m[1]); res18 = add64(res18, srli64(res17, DIGIT_SIZE)); U64 u18 = mul52lo(res18, mont_constant); // early multiplication for the reduction of res18 res19 = fma52lo(res19, u17, m[2]); res20 = fma52hi(res20, u17, m[2]); res20 = fma52lo(res20, u17, m[3]); res21 = fma52hi(res21, u17, m[3]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[3 + 4 * iter][4]); mulbx[4] = _mm512_mask_mov_epi64(mulbx[4], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][5]); mulbx[5] = _mm512_mask_mov_epi64(mulbx[5], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][6]); mulbx[6] = _mm512_mask_mov_epi64(mulbx[6], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][7]); mulbx[7] = _mm512_mask_mov_epi64(mulbx[7], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res21 = fma52lo(res21, u17, m[4]); res22 = fma52hi(res22, u17, m[4]); res22 = fma52lo(res22, u17, m[5]); res23 = fma52hi(res23, u17, m[5]); res23 = fma52lo(res23, u17, m[6]); res24 = fma52hi(res24, u17, m[6]); res24 = fma52lo(res24, u17, m[7]); res25 = fma52hi(res25, u17, m[7]); res25 = fma52lo(res25, u17, m[8]); res26 = fma52hi(res26, u17, m[8]); res26 = fma52lo(res26, u17, m[9]); res27 = fma52hi(res27, u17, m[9]); res27 = fma52lo(res27, u17, m[10]); res28 = fma52hi(res28, u17, m[10]); res28 = fma52lo(res28, u17, m[11]); res29 = fma52hi(res29, u17, m[11]); res29 = fma52lo(res29, u17, m[12]); res30 = fma52hi(res30, u17, m[12]); res30 = fma52lo(res30, u17, m[13]); res31 = fma52hi(res31, u17, m[13]); res31 = fma52lo(res31, u17, m[14]); res32 = fma52hi(res32, u17, m[14]); res32 = fma52lo(res32, u17, m[15]); res33 = fma52hi(res33, u17, m[15]); res33 = fma52lo(res33, u17, m[16]); res34 = fma52hi(res34, u17, m[16]); res34 = fma52lo(res34, u17, m[17]); res35 = fma52hi(res35, u17, m[17]); res35 = fma52lo(res35, u17, m[18]); res36 = fma52hi(res36, u17, m[18]); res36 = fma52lo(res36, u17, m[19]); res37 = fma52hi(res37, u17, m[19]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[3 + 4 * iter][8]); mulbx[8] = _mm512_mask_mov_epi64(mulbx[8], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][9]); mulbx[9] = _mm512_mask_mov_epi64(mulbx[9], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][10]); mulbx[10] = _mm512_mask_mov_epi64(mulbx[10], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][11]); mulbx[11] = _mm512_mask_mov_epi64(mulbx[11], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res18 = fma52lo(res18, u18, m[0]); res19 = fma52hi(res19, u18, m[0]); res19 = fma52lo(res19, u18, m[1]); res20 = fma52hi(res20, u18, m[1]); res19 = add64(res19, srli64(res18, DIGIT_SIZE)); U64 u19 = mul52lo(res19, mont_constant); // early multiplication for the reduction of res19 res20 = fma52lo(res20, u18, m[2]); res21 = fma52hi(res21, u18, m[2]); res21 = fma52lo(res21, u18, m[3]); res22 = fma52hi(res22, u18, m[3]); res22 = fma52lo(res22, u18, m[4]); res23 = fma52hi(res23, u18, m[4]); res23 = fma52lo(res23, u18, m[5]); res24 = fma52hi(res24, u18, m[5]); res24 = fma52lo(res24, u18, m[6]); res25 = fma52hi(res25, u18, m[6]); res25 = fma52lo(res25, u18, m[7]); res26 = fma52hi(res26, u18, m[7]); res26 = fma52lo(res26, u18, m[8]); res27 = fma52hi(res27, u18, m[8]); res27 = fma52lo(res27, u18, m[9]); res28 = fma52hi(res28, u18, m[9]); res28 = fma52lo(res28, u18, m[10]); res29 = fma52hi(res29, u18, m[10]); res29 = fma52lo(res29, u18, m[11]); res30 = fma52hi(res30, u18, m[11]); res30 = fma52lo(res30, u18, m[12]); res31 = fma52hi(res31, u18, m[12]); res31 = fma52lo(res31, u18, m[13]); res32 = fma52hi(res32, u18, m[13]); res32 = fma52lo(res32, u18, m[14]); res33 = fma52hi(res33, u18, m[14]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[3 + 4 * iter][12]); mulbx[12] = _mm512_mask_mov_epi64(mulbx[12], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][13]); mulbx[13] = _mm512_mask_mov_epi64(mulbx[13], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][14]); mulbx[14] = _mm512_mask_mov_epi64(mulbx[14], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][15]); mulbx[15] = _mm512_mask_mov_epi64(mulbx[15], extract_sel_mask, tempx); //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res33 = fma52lo(res33, u18, m[15]); res34 = fma52hi(res34, u18, m[15]); res34 = fma52lo(res34, u18, m[16]); res35 = fma52hi(res35, u18, m[16]); res35 = fma52lo(res35, u18, m[17]); res36 = fma52hi(res36, u18, m[17]); res36 = fma52lo(res36, u18, m[18]); res37 = fma52hi(res37, u18, m[18]); res37 = fma52lo(res37, u18, m[19]); res38 = fma52hi(res38, u18, m[19]); res19 = fma52lo(res19, u19, m[0]); res20 = fma52hi(res20, u19, m[0]); res20 = fma52lo(res20, u19, m[1]); res21 = fma52hi(res21, u19, m[1]); res20 = add64(res20, srli64(res19, DIGIT_SIZE)); res21 = fma52lo(res21, u19, m[2]); res22 = fma52hi(res22, u19, m[2]); res22 = fma52lo(res22, u19, m[3]); res23 = fma52hi(res23, u19, m[3]); res23 = fma52lo(res23, u19, m[4]); res24 = fma52hi(res24, u19, m[4]); res24 = fma52lo(res24, u19, m[5]); res25 = fma52hi(res25, u19, m[5]); res25 = fma52lo(res25, u19, m[6]); res26 = fma52hi(res26, u19, m[6]); res26 = fma52lo(res26, u19, m[7]); res27 = fma52hi(res27, u19, m[7]); res27 = fma52lo(res27, u19, m[8]); res28 = fma52hi(res28, u19, m[8]); res28 = fma52lo(res28, u19, m[9]); res29 = fma52hi(res29, u19, m[9]); res29 = fma52lo(res29, u19, m[10]); //*******END SQUARING CODE SEGMENT**************// //*******BEGIN EXTRACTION CODE SEGMENT****************************// tempx = loadstream64(MulTblx[3 + 4 * iter][16]); mulbx[16] = _mm512_mask_mov_epi64(mulbx[16], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][17]); mulbx[17] = _mm512_mask_mov_epi64(mulbx[17], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][18]); mulbx[18] = _mm512_mask_mov_epi64(mulbx[18], extract_sel_mask, tempx); tempx = loadstream64(MulTblx[3 + 4 * iter][19]); mulbx[19] = _mm512_mask_mov_epi64(mulbx[19], extract_sel_mask, tempx); extract_sel_mask = extract_sel_mask_next; //*******END EXTRACTION CODE SEGMENT******************************// //*******BEGIN SQUARING CODE SEGMENT************// res30 = fma52hi(res30, u19, m[10]); res30 = fma52lo(res30, u19, m[11]); res31 = fma52hi(res31, u19, m[11]); res31 = fma52lo(res31, u19, m[12]); res32 = fma52hi(res32, u19, m[12]); res32 = fma52lo(res32, u19, m[13]); res33 = fma52hi(res33, u19, m[13]); res33 = fma52lo(res33, u19, m[14]); res34 = fma52hi(res34, u19, m[14]); res34 = fma52lo(res34, u19, m[15]); res35 = fma52hi(res35, u19, m[15]); res35 = fma52lo(res35, u19, m[16]); res36 = fma52hi(res36, u19, m[16]); res36 = fma52lo(res36, u19, m[17]); res37 = fma52hi(res37, u19, m[17]); res37 = fma52lo(res37, u19, m[18]); res38 = fma52hi(res38, u19, m[18]); res38 = fma52lo(res38, u19, m[19]); res39 = fma52hi(res39, u19, m[19]); // Normalization // We do not need to zero out the top bits // They will not be used by the fma53lo/hi instructios r[0] = res20; res21 = add64(res21, srli64(res20, DIGIT_SIZE)); r[1] = res21; res22 = add64(res22, srli64(res21, DIGIT_SIZE)); r[2] = res22; res23 = add64(res23, srli64(res22, DIGIT_SIZE)); r[3] = res23; res24 = add64(res24, srli64(res23, DIGIT_SIZE)); r[4] = res24; res25 = add64(res25, srli64(res24, DIGIT_SIZE)); r[5] = res25; res26 = add64(res26, srli64(res25, DIGIT_SIZE)); r[6] = res26; res27 = add64(res27, srli64(res26, DIGIT_SIZE)); r[7] = res27; res28 = add64(res28, srli64(res27, DIGIT_SIZE)); r[8] = res28; res29 = add64(res29, srli64(res28, DIGIT_SIZE)); r[9] = res29; res30 = add64(res30, srli64(res29, DIGIT_SIZE)); r[10] = res30; res31 = add64(res31, srli64(res30, DIGIT_SIZE)); r[11] = res31; res32 = add64(res32, srli64(res31, DIGIT_SIZE)); r[12] = res32; res33 = add64(res33, srli64(res32, DIGIT_SIZE)); r[13] = res33; res34 = add64(res34, srli64(res33, DIGIT_SIZE)); r[14] = res34; res35 = add64(res35, srli64(res34, DIGIT_SIZE)); r[15] = res35; res36 = add64(res36, srli64(res35, DIGIT_SIZE)); r[16] = res36; res37 = add64(res37, srli64(res36, DIGIT_SIZE)); r[17] = res37; res38 = add64(res38, srli64(res37, DIGIT_SIZE)); r[18] = res38; res39 = add64(res39, srli64(res38, DIGIT_SIZE)); r[19] = res39; a = (U64 *)out_mb; //*******END SQUARING CODE SEGMENT**************// } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_ahmm52x20_mb8.c000066400000000000000000000270011470420105600330560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023-2024 Intel Corporation * * 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 /* Almost Half Montgomery Multiplication (AHMM) Output: out_mb : c = A*B*(2^(-20*52)) mod M Inputs: inpA_mb : A inpB_mb : B inpBx_mb : K = B*(2^(-10*52)) mod M inpM_mb : M k0_mb : mont_constant = (-M^(-1) mod 2^(52)) AL=A[ 9: 0] AH=A[19:10] C=0 for i from 0 to 9: C=C+AL[i]*K+AH[i]*B T=C[0]*mu // discard T[1] C=C+T[0]*M // C[0] is zero C=C>>52 // at each step of the for loop, divide the result by 2^52 return C */ #if (_MBX >= _MBX_K1) void ifma_ahmm52x20_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpBx_mb, const int64u *inpM_mb, const int64u *k0_mb) { // Temporary Registers to hold 20 52-bit intermediate results U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20; // Precomputed Montgomery constant (-M^(-1) mod 2^(52)) const U64 mont_constant = loadu64(k0_mb); // C = 0 res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = get_zero64(); U64 *A = (U64 *)inpA_mb; U64 *M = (U64 *)inpM_mb; U64 *mulb = (U64 *)inpB_mb; U64 *mulbx = (U64 *)inpBx_mb; for (int itr = 0; itr < 10; itr++) { //****************************************************** // C=C+AL[i]*K+AH[i]*B //****************************************************** // C=C+AH[i]*B // load AH[i] const U64 AHi = A[itr + 10]; // AH=A[19:10] res00 = fma52lo(res00, AHi, mulb[0]); res01 = fma52hi(res01, AHi, mulb[0]); res01 = fma52lo(res01, AHi, mulb[1]); res02 = fma52hi(res02, AHi, mulb[1]); res02 = fma52lo(res02, AHi, mulb[2]); res03 = fma52hi(res03, AHi, mulb[2]); res03 = fma52lo(res03, AHi, mulb[3]); res04 = fma52hi(res04, AHi, mulb[3]); res04 = fma52lo(res04, AHi, mulb[4]); res05 = fma52hi(res05, AHi, mulb[4]); res05 = fma52lo(res05, AHi, mulb[5]); res06 = fma52hi(res06, AHi, mulb[5]); res06 = fma52lo(res06, AHi, mulb[6]); res07 = fma52hi(res07, AHi, mulb[6]); res07 = fma52lo(res07, AHi, mulb[7]); res08 = fma52hi(res08, AHi, mulb[7]); res08 = fma52lo(res08, AHi, mulb[8]); res09 = fma52hi(res09, AHi, mulb[8]); res09 = fma52lo(res09, AHi, mulb[9]); res10 = fma52hi(res10, AHi, mulb[9]); res10 = fma52lo(res10, AHi, mulb[10]); res11 = fma52hi(res11, AHi, mulb[10]); res11 = fma52lo(res11, AHi, mulb[11]); res12 = fma52hi(res12, AHi, mulb[11]); res12 = fma52lo(res12, AHi, mulb[12]); res13 = fma52hi(res13, AHi, mulb[12]); res13 = fma52lo(res13, AHi, mulb[13]); res14 = fma52hi(res14, AHi, mulb[13]); res14 = fma52lo(res14, AHi, mulb[14]); res15 = fma52hi(res15, AHi, mulb[14]); res15 = fma52lo(res15, AHi, mulb[15]); res16 = fma52hi(res16, AHi, mulb[15]); res16 = fma52lo(res16, AHi, mulb[16]); res17 = fma52hi(res17, AHi, mulb[16]); res17 = fma52lo(res17, AHi, mulb[17]); res18 = fma52hi(res18, AHi, mulb[17]); res18 = fma52lo(res18, AHi, mulb[18]); res19 = fma52hi(res19, AHi, mulb[18]); res19 = fma52lo(res19, AHi, mulb[19]); res20 = fma52hi(get_zero64(), AHi, mulb[19]); // C=C+AL[i]*K (low part) // load AL[i] const U64 ALi = A[itr]; // AL=A[ 9: 0] res00 = fma52lo(res00, ALi, mulbx[0]); res01 = fma52hi(res01, ALi, mulbx[0]); res01 = fma52lo(res01, ALi, mulbx[1]); res02 = fma52hi(res02, ALi, mulbx[1]); res02 = fma52lo(res02, ALi, mulbx[2]); res03 = fma52hi(res03, ALi, mulbx[2]); res03 = fma52lo(res03, ALi, mulbx[3]); res04 = fma52hi(res04, ALi, mulbx[3]); res04 = fma52lo(res04, ALi, mulbx[4]); res05 = fma52hi(res05, ALi, mulbx[4]); res05 = fma52lo(res05, ALi, mulbx[5]); res06 = fma52hi(res06, ALi, mulbx[5]); res06 = fma52lo(res06, ALi, mulbx[6]); res07 = fma52hi(res07, ALi, mulbx[6]); res07 = fma52lo(res07, ALi, mulbx[7]); res08 = fma52hi(res08, ALi, mulbx[7]); res08 = fma52lo(res08, ALi, mulbx[8]); res09 = fma52hi(res09, ALi, mulbx[8]); res09 = fma52lo(res09, ALi, mulbx[9]); res10 = fma52hi(res10, ALi, mulbx[9]); res10 = fma52lo(res10, ALi, mulbx[10]); res11 = fma52hi(res11, ALi, mulbx[10]); res11 = fma52lo(res11, ALi, mulbx[11]); res12 = fma52hi(res12, ALi, mulbx[11]); res12 = fma52lo(res12, ALi, mulbx[12]); res13 = fma52hi(res13, ALi, mulbx[12]); res13 = fma52lo(res13, ALi, mulbx[13]); res14 = fma52hi(res14, ALi, mulbx[13]); res14 = fma52lo(res14, ALi, mulbx[14]); res15 = fma52hi(res15, ALi, mulbx[14]); res15 = fma52lo(res15, ALi, mulbx[15]); res16 = fma52hi(res16, ALi, mulbx[15]); res16 = fma52lo(res16, ALi, mulbx[16]); res17 = fma52hi(res17, ALi, mulbx[16]); res17 = fma52lo(res17, ALi, mulbx[17]); res18 = fma52hi(res18, ALi, mulbx[17]); res18 = fma52lo(res18, ALi, mulbx[18]); res19 = fma52hi(res19, ALi, mulbx[18]); res19 = fma52lo(res19, ALi, mulbx[19]); res20 = fma52hi(res20, ALi, mulbx[19]); // done: C=C+AL[i]*K+AH[i]*B //****************************************************** // T=C[0]*mu U64 T = fma52lo(get_zero64(), res00, mont_constant); // C=C+T[0]*M (low part) res00 = fma52lo(res00, T, M[0]); // low 52 (DIGIT_SIZE) bits of res00 are 0 // high 12 bits are accumulated to res01 (same bit-weight) res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); res01 = fma52lo(res01, T, M[1]); res00 = fma52hi(res01, T, M[0]); res02 = fma52lo(res02, T, M[2]); res01 = fma52hi(res02, T, M[1]); res03 = fma52lo(res03, T, M[3]); res02 = fma52hi(res03, T, M[2]); res04 = fma52lo(res04, T, M[4]); res03 = fma52hi(res04, T, M[3]); res05 = fma52lo(res05, T, M[5]); res04 = fma52hi(res05, T, M[4]); res06 = fma52lo(res06, T, M[6]); res05 = fma52hi(res06, T, M[5]); res07 = fma52lo(res07, T, M[7]); res06 = fma52hi(res07, T, M[6]); res08 = fma52lo(res08, T, M[8]); res07 = fma52hi(res08, T, M[7]); res09 = fma52lo(res09, T, M[9]); res08 = fma52hi(res09, T, M[8]); res10 = fma52lo(res10, T, M[10]); res09 = fma52hi(res10, T, M[9]); res11 = fma52lo(res11, T, M[11]); res10 = fma52hi(res11, T, M[10]); res12 = fma52lo(res12, T, M[12]); res11 = fma52hi(res12, T, M[11]); res13 = fma52lo(res13, T, M[13]); res12 = fma52hi(res13, T, M[12]); res14 = fma52lo(res14, T, M[14]); res13 = fma52hi(res14, T, M[13]); res15 = fma52lo(res15, T, M[15]); res14 = fma52hi(res15, T, M[14]); res16 = fma52lo(res16, T, M[16]); res15 = fma52hi(res16, T, M[15]); res17 = fma52lo(res17, T, M[17]); res16 = fma52hi(res17, T, M[16]); res18 = fma52lo(res18, T, M[18]); res17 = fma52hi(res18, T, M[17]); res19 = fma52lo(res19, T, M[19]); res18 = fma52hi(res19, T, M[18]); res19 = fma52hi(res20, T, M[19]); } // Normalization U64 High_Extra_Bits = srli64(res00, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, High_Extra_Bits); High_Extra_Bits = srli64(res01, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, High_Extra_Bits); High_Extra_Bits = srli64(res02, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, High_Extra_Bits); High_Extra_Bits = srli64(res03, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, High_Extra_Bits); High_Extra_Bits = srli64(res04, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, High_Extra_Bits); High_Extra_Bits = srli64(res05, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, High_Extra_Bits); High_Extra_Bits = srli64(res06, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, High_Extra_Bits); High_Extra_Bits = srli64(res07, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, High_Extra_Bits); High_Extra_Bits = srli64(res08, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, High_Extra_Bits); High_Extra_Bits = srli64(res09, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, High_Extra_Bits); High_Extra_Bits = srli64(res10, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, High_Extra_Bits); High_Extra_Bits = srli64(res11, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, High_Extra_Bits); High_Extra_Bits = srli64(res12, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, High_Extra_Bits); High_Extra_Bits = srli64(res13, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, High_Extra_Bits); High_Extra_Bits = srli64(res14, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, High_Extra_Bits); High_Extra_Bits = srli64(res15, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, High_Extra_Bits); High_Extra_Bits = srli64(res16, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, High_Extra_Bits); High_Extra_Bits = srli64(res17, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, High_Extra_Bits); High_Extra_Bits = srli64(res18, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, High_Extra_Bits); storeu64(out_mb + MB_WIDTH * 19, res19); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_ahmr52x20_mb8.c000066400000000000000000000202371470420105600330670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) /* Almost Half Montgomery Reduction (AHMR) Output: out_mb : C = A*(2^(-10*52)) mod M Inputs: inpA_mb : A inpM_mb : M k0_mb : mont_constant = (-M^(-1) mod 2^(52)) C=A for i from 0 to 9: T=C[0]*mu // discard T[1] C=C+T[0]*M // C[0] is zero C=C>>52 // at each step of the for loop, divide the result by 2^52 return C */ void ifma_ahmr52x20_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19; const U64 mont_constant = loadu64(k0_mb); res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = get_zero64(); // top 12 bits of 64-bit digits of the input A are junk data // they need to be masked out before the reduction operation const U64 MASK52 = set64(DIGIT_MASK); U64 *M = (U64 *)inpM_mb; // C=A // res00:res19 are temporary registers holding intermediate result C res00 = loadu64(inpA_mb + 0 * MB_WIDTH); res00 = and64(res00, MASK52); res01 = loadu64(inpA_mb + 1 * MB_WIDTH); res01 = and64(res01, MASK52); res02 = loadu64(inpA_mb + 2 * MB_WIDTH); res02 = and64(res02, MASK52); res03 = loadu64(inpA_mb + 3 * MB_WIDTH); res03 = and64(res03, MASK52); res04 = loadu64(inpA_mb + 4 * MB_WIDTH); res04 = and64(res04, MASK52); res05 = loadu64(inpA_mb + 5 * MB_WIDTH); res05 = and64(res05, MASK52); res06 = loadu64(inpA_mb + 6 * MB_WIDTH); res06 = and64(res06, MASK52); res07 = loadu64(inpA_mb + 7 * MB_WIDTH); res07 = and64(res07, MASK52); res08 = loadu64(inpA_mb + 8 * MB_WIDTH); res08 = and64(res08, MASK52); res09 = loadu64(inpA_mb + 9 * MB_WIDTH); res09 = and64(res09, MASK52); res10 = loadu64(inpA_mb + 10 * MB_WIDTH); res10 = and64(res10, MASK52); res11 = loadu64(inpA_mb + 11 * MB_WIDTH); res11 = and64(res11, MASK52); res12 = loadu64(inpA_mb + 12 * MB_WIDTH); res12 = and64(res12, MASK52); res13 = loadu64(inpA_mb + 13 * MB_WIDTH); res13 = and64(res13, MASK52); res14 = loadu64(inpA_mb + 14 * MB_WIDTH); res14 = and64(res14, MASK52); res15 = loadu64(inpA_mb + 15 * MB_WIDTH); res15 = and64(res15, MASK52); res16 = loadu64(inpA_mb + 16 * MB_WIDTH); res16 = and64(res16, MASK52); res17 = loadu64(inpA_mb + 17 * MB_WIDTH); res17 = and64(res17, MASK52); res18 = loadu64(inpA_mb + 18 * MB_WIDTH); res18 = and64(res18, MASK52); res19 = loadu64(inpA_mb + 19 * MB_WIDTH); res19 = and64(res19, MASK52); for (int itr = 0; itr < 10; itr++) { // T=C[0]*mu const U64 T = fma52lo(get_zero64(), res00, mont_constant); // C=C+T[0]*M (low part) res00 = fma52lo(res00, T, M[0]); // low 52 (DIGIT_SIZE) bits of res00 are 0 // high 12 bits are accumulated to res01 (same bit-weight) res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); res01 = fma52lo(res01, T, M[1]); res00 = fma52hi(res01, T, M[0]); res02 = fma52lo(res02, T, M[2]); res01 = fma52hi(res02, T, M[1]); res03 = fma52lo(res03, T, M[3]); res02 = fma52hi(res03, T, M[2]); res04 = fma52lo(res04, T, M[4]); res03 = fma52hi(res04, T, M[3]); res05 = fma52lo(res05, T, M[5]); res04 = fma52hi(res05, T, M[4]); res06 = fma52lo(res06, T, M[6]); res05 = fma52hi(res06, T, M[5]); res07 = fma52lo(res07, T, M[7]); res06 = fma52hi(res07, T, M[6]); res08 = fma52lo(res08, T, M[8]); res07 = fma52hi(res08, T, M[7]); res09 = fma52lo(res09, T, M[9]); res08 = fma52hi(res09, T, M[8]); res10 = fma52lo(res10, T, M[10]); res09 = fma52hi(res10, T, M[9]); res11 = fma52lo(res11, T, M[11]); res10 = fma52hi(res11, T, M[10]); res12 = fma52lo(res12, T, M[12]); res11 = fma52hi(res12, T, M[11]); res13 = fma52lo(res13, T, M[13]); res12 = fma52hi(res13, T, M[12]); res14 = fma52lo(res14, T, M[14]); res13 = fma52hi(res14, T, M[13]); res15 = fma52lo(res15, T, M[15]); res14 = fma52hi(res15, T, M[14]); res16 = fma52lo(res16, T, M[16]); res15 = fma52hi(res16, T, M[15]); res17 = fma52lo(res17, T, M[17]); res16 = fma52hi(res17, T, M[16]); res18 = fma52lo(res18, T, M[18]); res17 = fma52hi(res18, T, M[17]); res19 = fma52lo(res19, T, M[19]); res18 = fma52hi(res19, T, M[18]); res19 = fma52hi(get_zero64(), T, M[19]); } // Normalization U64 High_Extra_Bits = srli64(res00, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, High_Extra_Bits); High_Extra_Bits = srli64(res01, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, High_Extra_Bits); High_Extra_Bits = srli64(res02, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, High_Extra_Bits); High_Extra_Bits = srli64(res03, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, High_Extra_Bits); High_Extra_Bits = srli64(res04, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, High_Extra_Bits); High_Extra_Bits = srli64(res05, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, High_Extra_Bits); High_Extra_Bits = srli64(res06, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, High_Extra_Bits); High_Extra_Bits = srli64(res07, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, High_Extra_Bits); High_Extra_Bits = srli64(res08, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, High_Extra_Bits); High_Extra_Bits = srli64(res09, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, High_Extra_Bits); High_Extra_Bits = srli64(res10, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, High_Extra_Bits); High_Extra_Bits = srli64(res11, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, High_Extra_Bits); High_Extra_Bits = srli64(res12, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, High_Extra_Bits); High_Extra_Bits = srli64(res13, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, High_Extra_Bits); High_Extra_Bits = srli64(res14, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, High_Extra_Bits); High_Extra_Bits = srli64(res15, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, High_Extra_Bits); High_Extra_Bits = srli64(res16, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, High_Extra_Bits); High_Extra_Bits = srli64(res17, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, High_Extra_Bits); High_Extra_Bits = srli64(res18, DIGIT_SIZE); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, High_Extra_Bits); storeu64(out_mb + MB_WIDTH * 19, res19); } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_amm52x10_mb8.c000066400000000000000000000126261470420105600327140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void ifma_amm52x10_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09; U64 K = loadu64(k0_mb); int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = get_zero64(); for (itr = 0; itr < 10; itr++) { U64 Yi; U64 Bi = loadu64(inpB_mb); inpB_mb += MB_WIDTH; fma52lo_mem(res00, res00, Bi, inpA_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Bi, inpA_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Bi, inpA_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Bi, inpA_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Bi, inpA_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Bi, inpA_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Bi, inpA_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Bi, inpA_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Bi, inpA_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Bi, inpA_mb, SIMD_BYTES * 9); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res02, Bi, inpA_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res03, Bi, inpA_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res04, Bi, inpA_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res05, Bi, inpA_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res06, Bi, inpA_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res07, Bi, inpA_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res08, Bi, inpA_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res09, Bi, inpA_mb, SIMD_BYTES * 8); fma52hi_mem(res09, get_zero64(), Bi, inpA_mb, SIMD_BYTES * 9); fma52hi_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); } // Normalization { U64 T = get_zero64(); U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); res00 = and64(res00, MASK); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); res01 = and64(res01, MASK); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); res02 = and64(res02, MASK); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); res03 = and64(res03, MASK); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); res04 = and64(res04, MASK); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); res05 = and64(res05, MASK); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); res06 = and64(res06, MASK); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); res07 = and64(res07, MASK); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); res08 = and64(res08, MASK); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, T); res09 = and64(res09, MASK); storeu64(out_mb + MB_WIDTH * 9, res09); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_amm52x20_mb8.c000066400000000000000000000230051470420105600327060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void ifma_amm52x20_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19; U64 K = loadu64(k0_mb); int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = get_zero64(); for (itr = 0; itr < 20; itr++) { U64 Yi; U64 Bi = loadu64(inpB_mb); inpB_mb += MB_WIDTH; fma52lo_mem(res00, res00, Bi, inpA_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Bi, inpA_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Bi, inpA_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Bi, inpA_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Bi, inpA_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Bi, inpA_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Bi, inpA_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Bi, inpA_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Bi, inpA_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Bi, inpA_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Bi, inpA_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Bi, inpA_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Bi, inpA_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Bi, inpA_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Bi, inpA_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Bi, inpA_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Bi, inpA_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Bi, inpA_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Bi, inpA_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Bi, inpA_mb, SIMD_BYTES * 19); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res02, Bi, inpA_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res03, Bi, inpA_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res04, Bi, inpA_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res05, Bi, inpA_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res06, Bi, inpA_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res07, Bi, inpA_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res08, Bi, inpA_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res09, Bi, inpA_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res10, Bi, inpA_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res11, Bi, inpA_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res12, Bi, inpA_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res13, Bi, inpA_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res14, Bi, inpA_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res15, Bi, inpA_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res16, Bi, inpA_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res17, Bi, inpA_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res18, Bi, inpA_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res19, Bi, inpA_mb, SIMD_BYTES * 18); fma52hi_mem(res19, get_zero64(), Bi, inpA_mb, SIMD_BYTES * 19); fma52hi_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); } // Normalization { U64 T = get_zero64(); U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); res00 = and64(res00, MASK); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); res01 = and64(res01, MASK); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); res02 = and64(res02, MASK); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); res03 = and64(res03, MASK); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); res04 = and64(res04, MASK); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); res05 = and64(res05, MASK); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); res06 = and64(res06, MASK); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); res07 = and64(res07, MASK); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); res08 = and64(res08, MASK); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, T); T = srli64(res09, DIGIT_SIZE); res09 = and64(res09, MASK); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, T); T = srli64(res10, DIGIT_SIZE); res10 = and64(res10, MASK); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, T); T = srli64(res11, DIGIT_SIZE); res11 = and64(res11, MASK); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, T); T = srli64(res12, DIGIT_SIZE); res12 = and64(res12, MASK); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, T); T = srli64(res13, DIGIT_SIZE); res13 = and64(res13, MASK); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, T); T = srli64(res14, DIGIT_SIZE); res14 = and64(res14, MASK); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, T); T = srli64(res15, DIGIT_SIZE); res15 = and64(res15, MASK); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, T); T = srli64(res16, DIGIT_SIZE); res16 = and64(res16, MASK); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, T); T = srli64(res17, DIGIT_SIZE); res17 = and64(res17, MASK); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, T); T = srli64(res18, DIGIT_SIZE); res18 = and64(res18, MASK); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, T); res19 = and64(res19, MASK); storeu64(out_mb + MB_WIDTH * 19, res19); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_amm52x30_mb8.c000066400000000000000000000331631470420105600327150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void ifma_amm52x30_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29; U64 K = loadu64(k0_mb); int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = get_zero64(); for (itr = 0; itr < 30; itr++) { U64 Yi; U64 Bi = loadu64(inpB_mb); inpB_mb += MB_WIDTH; fma52lo_mem(res00, res00, Bi, inpA_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Bi, inpA_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Bi, inpA_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Bi, inpA_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Bi, inpA_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Bi, inpA_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Bi, inpA_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Bi, inpA_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Bi, inpA_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Bi, inpA_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Bi, inpA_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Bi, inpA_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Bi, inpA_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Bi, inpA_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Bi, inpA_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Bi, inpA_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Bi, inpA_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Bi, inpA_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Bi, inpA_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Bi, inpA_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Bi, inpA_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Bi, inpA_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Bi, inpA_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Bi, inpA_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Bi, inpA_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Bi, inpA_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Bi, inpA_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Bi, inpA_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Bi, inpA_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Bi, inpA_mb, SIMD_BYTES * 29); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res02, Bi, inpA_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res03, Bi, inpA_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res04, Bi, inpA_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res05, Bi, inpA_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res06, Bi, inpA_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res07, Bi, inpA_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res08, Bi, inpA_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res09, Bi, inpA_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res10, Bi, inpA_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res11, Bi, inpA_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res12, Bi, inpA_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res13, Bi, inpA_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res14, Bi, inpA_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res15, Bi, inpA_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res16, Bi, inpA_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res17, Bi, inpA_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res18, Bi, inpA_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res19, Bi, inpA_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res20, Bi, inpA_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res21, Bi, inpA_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res22, Bi, inpA_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res23, Bi, inpA_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res24, Bi, inpA_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res25, Bi, inpA_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res26, Bi, inpA_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res27, Bi, inpA_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res28, Bi, inpA_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res29, Bi, inpA_mb, SIMD_BYTES * 28); fma52hi_mem(res29, get_zero64(), Bi, inpA_mb, SIMD_BYTES * 29); fma52hi_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); } // Normalization { U64 T = get_zero64(); U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); res00 = and64(res00, MASK); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); res01 = and64(res01, MASK); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); res02 = and64(res02, MASK); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); res03 = and64(res03, MASK); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); res04 = and64(res04, MASK); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); res05 = and64(res05, MASK); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); res06 = and64(res06, MASK); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); res07 = and64(res07, MASK); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); res08 = and64(res08, MASK); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, T); T = srli64(res09, DIGIT_SIZE); res09 = and64(res09, MASK); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, T); T = srli64(res10, DIGIT_SIZE); res10 = and64(res10, MASK); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, T); T = srli64(res11, DIGIT_SIZE); res11 = and64(res11, MASK); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, T); T = srli64(res12, DIGIT_SIZE); res12 = and64(res12, MASK); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, T); T = srli64(res13, DIGIT_SIZE); res13 = and64(res13, MASK); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, T); T = srli64(res14, DIGIT_SIZE); res14 = and64(res14, MASK); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, T); T = srli64(res15, DIGIT_SIZE); res15 = and64(res15, MASK); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, T); T = srli64(res16, DIGIT_SIZE); res16 = and64(res16, MASK); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, T); T = srli64(res17, DIGIT_SIZE); res17 = and64(res17, MASK); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, T); T = srli64(res18, DIGIT_SIZE); res18 = and64(res18, MASK); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, T); T = srli64(res19, DIGIT_SIZE); res19 = and64(res19, MASK); storeu64(out_mb + MB_WIDTH * 19, res19); res20 = add64(res20, T); T = srli64(res20, DIGIT_SIZE); res20 = and64(res20, MASK); storeu64(out_mb + MB_WIDTH * 20, res20); res21 = add64(res21, T); T = srli64(res21, DIGIT_SIZE); res21 = and64(res21, MASK); storeu64(out_mb + MB_WIDTH * 21, res21); res22 = add64(res22, T); T = srli64(res22, DIGIT_SIZE); res22 = and64(res22, MASK); storeu64(out_mb + MB_WIDTH * 22, res22); res23 = add64(res23, T); T = srli64(res23, DIGIT_SIZE); res23 = and64(res23, MASK); storeu64(out_mb + MB_WIDTH * 23, res23); res24 = add64(res24, T); T = srli64(res24, DIGIT_SIZE); res24 = and64(res24, MASK); storeu64(out_mb + MB_WIDTH * 24, res24); res25 = add64(res25, T); T = srli64(res25, DIGIT_SIZE); res25 = and64(res25, MASK); storeu64(out_mb + MB_WIDTH * 25, res25); res26 = add64(res26, T); T = srli64(res26, DIGIT_SIZE); res26 = and64(res26, MASK); storeu64(out_mb + MB_WIDTH * 26, res26); res27 = add64(res27, T); T = srli64(res27, DIGIT_SIZE); res27 = and64(res27, MASK); storeu64(out_mb + MB_WIDTH * 27, res27); res28 = add64(res28, T); T = srli64(res28, DIGIT_SIZE); res28 = and64(res28, MASK); storeu64(out_mb + MB_WIDTH * 28, res28); res29 = add64(res29, T); res29 = and64(res29, MASK); storeu64(out_mb + MB_WIDTH * 29, res29); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_amm52x40_mb8.c000066400000000000000000000433441470420105600327200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void ifma_amm52x40_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29, res30, res31, res32, res33, res34, res35, res36, res37, res38, res39; U64 K = loadu64(k0_mb); int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = res30 = res31 = res32 = res33 = res34 = res35 = res36 = res37 = res38 = res39 = get_zero64(); for (itr = 0; itr < 40; itr++) { U64 Yi; U64 Bi = loadu64(inpB_mb); inpB_mb += MB_WIDTH; fma52lo_mem(res00, res00, Bi, inpA_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Bi, inpA_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Bi, inpA_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Bi, inpA_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Bi, inpA_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Bi, inpA_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Bi, inpA_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Bi, inpA_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Bi, inpA_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Bi, inpA_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Bi, inpA_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Bi, inpA_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Bi, inpA_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Bi, inpA_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Bi, inpA_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Bi, inpA_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Bi, inpA_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Bi, inpA_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Bi, inpA_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Bi, inpA_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Bi, inpA_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Bi, inpA_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Bi, inpA_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Bi, inpA_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Bi, inpA_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Bi, inpA_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Bi, inpA_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Bi, inpA_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Bi, inpA_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Bi, inpA_mb, SIMD_BYTES * 29); fma52lo_mem(res30, res30, Bi, inpA_mb, SIMD_BYTES * 30); fma52lo_mem(res31, res31, Bi, inpA_mb, SIMD_BYTES * 31); fma52lo_mem(res32, res32, Bi, inpA_mb, SIMD_BYTES * 32); fma52lo_mem(res33, res33, Bi, inpA_mb, SIMD_BYTES * 33); fma52lo_mem(res34, res34, Bi, inpA_mb, SIMD_BYTES * 34); fma52lo_mem(res35, res35, Bi, inpA_mb, SIMD_BYTES * 35); fma52lo_mem(res36, res36, Bi, inpA_mb, SIMD_BYTES * 36); fma52lo_mem(res37, res37, Bi, inpA_mb, SIMD_BYTES * 37); fma52lo_mem(res38, res38, Bi, inpA_mb, SIMD_BYTES * 38); fma52lo_mem(res39, res39, Bi, inpA_mb, SIMD_BYTES * 39); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); fma52lo_mem(res30, res30, Yi, inpM_mb, SIMD_BYTES * 30); fma52lo_mem(res31, res31, Yi, inpM_mb, SIMD_BYTES * 31); fma52lo_mem(res32, res32, Yi, inpM_mb, SIMD_BYTES * 32); fma52lo_mem(res33, res33, Yi, inpM_mb, SIMD_BYTES * 33); fma52lo_mem(res34, res34, Yi, inpM_mb, SIMD_BYTES * 34); fma52lo_mem(res35, res35, Yi, inpM_mb, SIMD_BYTES * 35); fma52lo_mem(res36, res36, Yi, inpM_mb, SIMD_BYTES * 36); fma52lo_mem(res37, res37, Yi, inpM_mb, SIMD_BYTES * 37); fma52lo_mem(res38, res38, Yi, inpM_mb, SIMD_BYTES * 38); fma52lo_mem(res39, res39, Yi, inpM_mb, SIMD_BYTES * 39); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res02, Bi, inpA_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res03, Bi, inpA_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res04, Bi, inpA_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res05, Bi, inpA_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res06, Bi, inpA_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res07, Bi, inpA_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res08, Bi, inpA_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res09, Bi, inpA_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res10, Bi, inpA_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res11, Bi, inpA_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res12, Bi, inpA_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res13, Bi, inpA_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res14, Bi, inpA_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res15, Bi, inpA_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res16, Bi, inpA_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res17, Bi, inpA_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res18, Bi, inpA_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res19, Bi, inpA_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res20, Bi, inpA_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res21, Bi, inpA_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res22, Bi, inpA_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res23, Bi, inpA_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res24, Bi, inpA_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res25, Bi, inpA_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res26, Bi, inpA_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res27, Bi, inpA_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res28, Bi, inpA_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res29, Bi, inpA_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res30, Bi, inpA_mb, SIMD_BYTES * 29); fma52hi_mem(res30, res31, Bi, inpA_mb, SIMD_BYTES * 30); fma52hi_mem(res31, res32, Bi, inpA_mb, SIMD_BYTES * 31); fma52hi_mem(res32, res33, Bi, inpA_mb, SIMD_BYTES * 32); fma52hi_mem(res33, res34, Bi, inpA_mb, SIMD_BYTES * 33); fma52hi_mem(res34, res35, Bi, inpA_mb, SIMD_BYTES * 34); fma52hi_mem(res35, res36, Bi, inpA_mb, SIMD_BYTES * 35); fma52hi_mem(res36, res37, Bi, inpA_mb, SIMD_BYTES * 36); fma52hi_mem(res37, res38, Bi, inpA_mb, SIMD_BYTES * 37); fma52hi_mem(res38, res39, Bi, inpA_mb, SIMD_BYTES * 38); fma52hi_mem(res39, get_zero64(), Bi, inpA_mb, SIMD_BYTES * 39); fma52hi_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); fma52hi_mem(res30, res30, Yi, inpM_mb, SIMD_BYTES * 30); fma52hi_mem(res31, res31, Yi, inpM_mb, SIMD_BYTES * 31); fma52hi_mem(res32, res32, Yi, inpM_mb, SIMD_BYTES * 32); fma52hi_mem(res33, res33, Yi, inpM_mb, SIMD_BYTES * 33); fma52hi_mem(res34, res34, Yi, inpM_mb, SIMD_BYTES * 34); fma52hi_mem(res35, res35, Yi, inpM_mb, SIMD_BYTES * 35); fma52hi_mem(res36, res36, Yi, inpM_mb, SIMD_BYTES * 36); fma52hi_mem(res37, res37, Yi, inpM_mb, SIMD_BYTES * 37); fma52hi_mem(res38, res38, Yi, inpM_mb, SIMD_BYTES * 38); fma52hi_mem(res39, res39, Yi, inpM_mb, SIMD_BYTES * 39); } // Normalization { U64 T = get_zero64(); U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); res00 = and64(res00, MASK); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); res01 = and64(res01, MASK); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); res02 = and64(res02, MASK); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); res03 = and64(res03, MASK); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); res04 = and64(res04, MASK); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); res05 = and64(res05, MASK); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); res06 = and64(res06, MASK); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); res07 = and64(res07, MASK); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); res08 = and64(res08, MASK); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, T); T = srli64(res09, DIGIT_SIZE); res09 = and64(res09, MASK); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, T); T = srli64(res10, DIGIT_SIZE); res10 = and64(res10, MASK); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, T); T = srli64(res11, DIGIT_SIZE); res11 = and64(res11, MASK); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, T); T = srli64(res12, DIGIT_SIZE); res12 = and64(res12, MASK); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, T); T = srli64(res13, DIGIT_SIZE); res13 = and64(res13, MASK); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, T); T = srli64(res14, DIGIT_SIZE); res14 = and64(res14, MASK); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, T); T = srli64(res15, DIGIT_SIZE); res15 = and64(res15, MASK); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, T); T = srli64(res16, DIGIT_SIZE); res16 = and64(res16, MASK); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, T); T = srli64(res17, DIGIT_SIZE); res17 = and64(res17, MASK); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, T); T = srli64(res18, DIGIT_SIZE); res18 = and64(res18, MASK); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, T); T = srli64(res19, DIGIT_SIZE); res19 = and64(res19, MASK); storeu64(out_mb + MB_WIDTH * 19, res19); res20 = add64(res20, T); T = srli64(res20, DIGIT_SIZE); res20 = and64(res20, MASK); storeu64(out_mb + MB_WIDTH * 20, res20); res21 = add64(res21, T); T = srli64(res21, DIGIT_SIZE); res21 = and64(res21, MASK); storeu64(out_mb + MB_WIDTH * 21, res21); res22 = add64(res22, T); T = srli64(res22, DIGIT_SIZE); res22 = and64(res22, MASK); storeu64(out_mb + MB_WIDTH * 22, res22); res23 = add64(res23, T); T = srli64(res23, DIGIT_SIZE); res23 = and64(res23, MASK); storeu64(out_mb + MB_WIDTH * 23, res23); res24 = add64(res24, T); T = srli64(res24, DIGIT_SIZE); res24 = and64(res24, MASK); storeu64(out_mb + MB_WIDTH * 24, res24); res25 = add64(res25, T); T = srli64(res25, DIGIT_SIZE); res25 = and64(res25, MASK); storeu64(out_mb + MB_WIDTH * 25, res25); res26 = add64(res26, T); T = srli64(res26, DIGIT_SIZE); res26 = and64(res26, MASK); storeu64(out_mb + MB_WIDTH * 26, res26); res27 = add64(res27, T); T = srli64(res27, DIGIT_SIZE); res27 = and64(res27, MASK); storeu64(out_mb + MB_WIDTH * 27, res27); res28 = add64(res28, T); T = srli64(res28, DIGIT_SIZE); res28 = and64(res28, MASK); storeu64(out_mb + MB_WIDTH * 28, res28); res29 = add64(res29, T); T = srli64(res29, DIGIT_SIZE); res29 = and64(res29, MASK); storeu64(out_mb + MB_WIDTH * 29, res29); res30 = add64(res30, T); T = srli64(res30, DIGIT_SIZE); res30 = and64(res30, MASK); storeu64(out_mb + MB_WIDTH * 30, res30); res31 = add64(res31, T); T = srli64(res31, DIGIT_SIZE); res31 = and64(res31, MASK); storeu64(out_mb + MB_WIDTH * 31, res31); res32 = add64(res32, T); T = srli64(res32, DIGIT_SIZE); res32 = and64(res32, MASK); storeu64(out_mb + MB_WIDTH * 32, res32); res33 = add64(res33, T); T = srli64(res33, DIGIT_SIZE); res33 = and64(res33, MASK); storeu64(out_mb + MB_WIDTH * 33, res33); res34 = add64(res34, T); T = srli64(res34, DIGIT_SIZE); res34 = and64(res34, MASK); storeu64(out_mb + MB_WIDTH * 34, res34); res35 = add64(res35, T); T = srli64(res35, DIGIT_SIZE); res35 = and64(res35, MASK); storeu64(out_mb + MB_WIDTH * 35, res35); res36 = add64(res36, T); T = srli64(res36, DIGIT_SIZE); res36 = and64(res36, MASK); storeu64(out_mb + MB_WIDTH * 36, res36); res37 = add64(res37, T); T = srli64(res37, DIGIT_SIZE); res37 = and64(res37, MASK); storeu64(out_mb + MB_WIDTH * 37, res37); res38 = add64(res38, T); T = srli64(res38, DIGIT_SIZE); res38 = and64(res38, MASK); storeu64(out_mb + MB_WIDTH * 38, res38); res39 = add64(res39, T); res39 = and64(res39, MASK); storeu64(out_mb + MB_WIDTH * 39, res39); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_amm52x60_mb8.c000066400000000000000000000637061470420105600327260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void ifma_amm52x60_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29, res30, res31, res32, res33, res34, res35, res36, res37, res38, res39, res40, res41, res42, res43, res44, res45, res46, res47, res48, res49, res50, res51, res52, res53, res54, res55, res56, res57, res58, res59; U64 K = loadu64(k0_mb); int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = res30 = res31 = res32 = res33 = res34 = res35 = res36 = res37 = res38 = res39 = res40 = res41 = res42 = res43 = res44 = res45 = res46 = res47 = res48 = res49 = res50 = res51 = res52 = res53 = res54 = res55 = res56 = res57 = res58 = res59 = get_zero64(); for (itr = 0; itr < 60; itr++) { U64 Yi; U64 Bi = loadu64(inpB_mb); inpB_mb += MB_WIDTH; fma52lo_mem(res00, res00, Bi, inpA_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Bi, inpA_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Bi, inpA_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Bi, inpA_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Bi, inpA_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Bi, inpA_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Bi, inpA_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Bi, inpA_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Bi, inpA_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Bi, inpA_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Bi, inpA_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Bi, inpA_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Bi, inpA_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Bi, inpA_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Bi, inpA_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Bi, inpA_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Bi, inpA_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Bi, inpA_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Bi, inpA_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Bi, inpA_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Bi, inpA_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Bi, inpA_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Bi, inpA_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Bi, inpA_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Bi, inpA_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Bi, inpA_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Bi, inpA_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Bi, inpA_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Bi, inpA_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Bi, inpA_mb, SIMD_BYTES * 29); fma52lo_mem(res30, res30, Bi, inpA_mb, SIMD_BYTES * 30); fma52lo_mem(res31, res31, Bi, inpA_mb, SIMD_BYTES * 31); fma52lo_mem(res32, res32, Bi, inpA_mb, SIMD_BYTES * 32); fma52lo_mem(res33, res33, Bi, inpA_mb, SIMD_BYTES * 33); fma52lo_mem(res34, res34, Bi, inpA_mb, SIMD_BYTES * 34); fma52lo_mem(res35, res35, Bi, inpA_mb, SIMD_BYTES * 35); fma52lo_mem(res36, res36, Bi, inpA_mb, SIMD_BYTES * 36); fma52lo_mem(res37, res37, Bi, inpA_mb, SIMD_BYTES * 37); fma52lo_mem(res38, res38, Bi, inpA_mb, SIMD_BYTES * 38); fma52lo_mem(res39, res39, Bi, inpA_mb, SIMD_BYTES * 39); fma52lo_mem(res40, res40, Bi, inpA_mb, SIMD_BYTES * 40); fma52lo_mem(res41, res41, Bi, inpA_mb, SIMD_BYTES * 41); fma52lo_mem(res42, res42, Bi, inpA_mb, SIMD_BYTES * 42); fma52lo_mem(res43, res43, Bi, inpA_mb, SIMD_BYTES * 43); fma52lo_mem(res44, res44, Bi, inpA_mb, SIMD_BYTES * 44); fma52lo_mem(res45, res45, Bi, inpA_mb, SIMD_BYTES * 45); fma52lo_mem(res46, res46, Bi, inpA_mb, SIMD_BYTES * 46); fma52lo_mem(res47, res47, Bi, inpA_mb, SIMD_BYTES * 47); fma52lo_mem(res48, res48, Bi, inpA_mb, SIMD_BYTES * 48); fma52lo_mem(res49, res49, Bi, inpA_mb, SIMD_BYTES * 49); fma52lo_mem(res50, res50, Bi, inpA_mb, SIMD_BYTES * 50); fma52lo_mem(res51, res51, Bi, inpA_mb, SIMD_BYTES * 51); fma52lo_mem(res52, res52, Bi, inpA_mb, SIMD_BYTES * 52); fma52lo_mem(res53, res53, Bi, inpA_mb, SIMD_BYTES * 53); fma52lo_mem(res54, res54, Bi, inpA_mb, SIMD_BYTES * 54); fma52lo_mem(res55, res55, Bi, inpA_mb, SIMD_BYTES * 55); fma52lo_mem(res56, res56, Bi, inpA_mb, SIMD_BYTES * 56); fma52lo_mem(res57, res57, Bi, inpA_mb, SIMD_BYTES * 57); fma52lo_mem(res58, res58, Bi, inpA_mb, SIMD_BYTES * 58); fma52lo_mem(res59, res59, Bi, inpA_mb, SIMD_BYTES * 59); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); fma52lo_mem(res30, res30, Yi, inpM_mb, SIMD_BYTES * 30); fma52lo_mem(res31, res31, Yi, inpM_mb, SIMD_BYTES * 31); fma52lo_mem(res32, res32, Yi, inpM_mb, SIMD_BYTES * 32); fma52lo_mem(res33, res33, Yi, inpM_mb, SIMD_BYTES * 33); fma52lo_mem(res34, res34, Yi, inpM_mb, SIMD_BYTES * 34); fma52lo_mem(res35, res35, Yi, inpM_mb, SIMD_BYTES * 35); fma52lo_mem(res36, res36, Yi, inpM_mb, SIMD_BYTES * 36); fma52lo_mem(res37, res37, Yi, inpM_mb, SIMD_BYTES * 37); fma52lo_mem(res38, res38, Yi, inpM_mb, SIMD_BYTES * 38); fma52lo_mem(res39, res39, Yi, inpM_mb, SIMD_BYTES * 39); fma52lo_mem(res40, res40, Yi, inpM_mb, SIMD_BYTES * 40); fma52lo_mem(res41, res41, Yi, inpM_mb, SIMD_BYTES * 41); fma52lo_mem(res42, res42, Yi, inpM_mb, SIMD_BYTES * 42); fma52lo_mem(res43, res43, Yi, inpM_mb, SIMD_BYTES * 43); fma52lo_mem(res44, res44, Yi, inpM_mb, SIMD_BYTES * 44); fma52lo_mem(res45, res45, Yi, inpM_mb, SIMD_BYTES * 45); fma52lo_mem(res46, res46, Yi, inpM_mb, SIMD_BYTES * 46); fma52lo_mem(res47, res47, Yi, inpM_mb, SIMD_BYTES * 47); fma52lo_mem(res48, res48, Yi, inpM_mb, SIMD_BYTES * 48); fma52lo_mem(res49, res49, Yi, inpM_mb, SIMD_BYTES * 49); fma52lo_mem(res50, res50, Yi, inpM_mb, SIMD_BYTES * 50); fma52lo_mem(res51, res51, Yi, inpM_mb, SIMD_BYTES * 51); fma52lo_mem(res52, res52, Yi, inpM_mb, SIMD_BYTES * 52); fma52lo_mem(res53, res53, Yi, inpM_mb, SIMD_BYTES * 53); fma52lo_mem(res54, res54, Yi, inpM_mb, SIMD_BYTES * 54); fma52lo_mem(res55, res55, Yi, inpM_mb, SIMD_BYTES * 55); fma52lo_mem(res56, res56, Yi, inpM_mb, SIMD_BYTES * 56); fma52lo_mem(res57, res57, Yi, inpM_mb, SIMD_BYTES * 57); fma52lo_mem(res58, res58, Yi, inpM_mb, SIMD_BYTES * 58); fma52lo_mem(res59, res59, Yi, inpM_mb, SIMD_BYTES * 59); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res02, Bi, inpA_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res03, Bi, inpA_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res04, Bi, inpA_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res05, Bi, inpA_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res06, Bi, inpA_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res07, Bi, inpA_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res08, Bi, inpA_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res09, Bi, inpA_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res10, Bi, inpA_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res11, Bi, inpA_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res12, Bi, inpA_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res13, Bi, inpA_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res14, Bi, inpA_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res15, Bi, inpA_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res16, Bi, inpA_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res17, Bi, inpA_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res18, Bi, inpA_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res19, Bi, inpA_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res20, Bi, inpA_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res21, Bi, inpA_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res22, Bi, inpA_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res23, Bi, inpA_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res24, Bi, inpA_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res25, Bi, inpA_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res26, Bi, inpA_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res27, Bi, inpA_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res28, Bi, inpA_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res29, Bi, inpA_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res30, Bi, inpA_mb, SIMD_BYTES * 29); fma52hi_mem(res30, res31, Bi, inpA_mb, SIMD_BYTES * 30); fma52hi_mem(res31, res32, Bi, inpA_mb, SIMD_BYTES * 31); fma52hi_mem(res32, res33, Bi, inpA_mb, SIMD_BYTES * 32); fma52hi_mem(res33, res34, Bi, inpA_mb, SIMD_BYTES * 33); fma52hi_mem(res34, res35, Bi, inpA_mb, SIMD_BYTES * 34); fma52hi_mem(res35, res36, Bi, inpA_mb, SIMD_BYTES * 35); fma52hi_mem(res36, res37, Bi, inpA_mb, SIMD_BYTES * 36); fma52hi_mem(res37, res38, Bi, inpA_mb, SIMD_BYTES * 37); fma52hi_mem(res38, res39, Bi, inpA_mb, SIMD_BYTES * 38); fma52hi_mem(res39, res40, Bi, inpA_mb, SIMD_BYTES * 39); fma52hi_mem(res40, res41, Bi, inpA_mb, SIMD_BYTES * 40); fma52hi_mem(res41, res42, Bi, inpA_mb, SIMD_BYTES * 41); fma52hi_mem(res42, res43, Bi, inpA_mb, SIMD_BYTES * 42); fma52hi_mem(res43, res44, Bi, inpA_mb, SIMD_BYTES * 43); fma52hi_mem(res44, res45, Bi, inpA_mb, SIMD_BYTES * 44); fma52hi_mem(res45, res46, Bi, inpA_mb, SIMD_BYTES * 45); fma52hi_mem(res46, res47, Bi, inpA_mb, SIMD_BYTES * 46); fma52hi_mem(res47, res48, Bi, inpA_mb, SIMD_BYTES * 47); fma52hi_mem(res48, res49, Bi, inpA_mb, SIMD_BYTES * 48); fma52hi_mem(res49, res50, Bi, inpA_mb, SIMD_BYTES * 49); fma52hi_mem(res50, res51, Bi, inpA_mb, SIMD_BYTES * 50); fma52hi_mem(res51, res52, Bi, inpA_mb, SIMD_BYTES * 51); fma52hi_mem(res52, res53, Bi, inpA_mb, SIMD_BYTES * 52); fma52hi_mem(res53, res54, Bi, inpA_mb, SIMD_BYTES * 53); fma52hi_mem(res54, res55, Bi, inpA_mb, SIMD_BYTES * 54); fma52hi_mem(res55, res56, Bi, inpA_mb, SIMD_BYTES * 55); fma52hi_mem(res56, res57, Bi, inpA_mb, SIMD_BYTES * 56); fma52hi_mem(res57, res58, Bi, inpA_mb, SIMD_BYTES * 57); fma52hi_mem(res58, res59, Bi, inpA_mb, SIMD_BYTES * 58); fma52hi_mem(res59, get_zero64(), Bi, inpA_mb, SIMD_BYTES * 59); fma52hi_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); fma52hi_mem(res30, res30, Yi, inpM_mb, SIMD_BYTES * 30); fma52hi_mem(res31, res31, Yi, inpM_mb, SIMD_BYTES * 31); fma52hi_mem(res32, res32, Yi, inpM_mb, SIMD_BYTES * 32); fma52hi_mem(res33, res33, Yi, inpM_mb, SIMD_BYTES * 33); fma52hi_mem(res34, res34, Yi, inpM_mb, SIMD_BYTES * 34); fma52hi_mem(res35, res35, Yi, inpM_mb, SIMD_BYTES * 35); fma52hi_mem(res36, res36, Yi, inpM_mb, SIMD_BYTES * 36); fma52hi_mem(res37, res37, Yi, inpM_mb, SIMD_BYTES * 37); fma52hi_mem(res38, res38, Yi, inpM_mb, SIMD_BYTES * 38); fma52hi_mem(res39, res39, Yi, inpM_mb, SIMD_BYTES * 39); fma52hi_mem(res40, res40, Yi, inpM_mb, SIMD_BYTES * 40); fma52hi_mem(res41, res41, Yi, inpM_mb, SIMD_BYTES * 41); fma52hi_mem(res42, res42, Yi, inpM_mb, SIMD_BYTES * 42); fma52hi_mem(res43, res43, Yi, inpM_mb, SIMD_BYTES * 43); fma52hi_mem(res44, res44, Yi, inpM_mb, SIMD_BYTES * 44); fma52hi_mem(res45, res45, Yi, inpM_mb, SIMD_BYTES * 45); fma52hi_mem(res46, res46, Yi, inpM_mb, SIMD_BYTES * 46); fma52hi_mem(res47, res47, Yi, inpM_mb, SIMD_BYTES * 47); fma52hi_mem(res48, res48, Yi, inpM_mb, SIMD_BYTES * 48); fma52hi_mem(res49, res49, Yi, inpM_mb, SIMD_BYTES * 49); fma52hi_mem(res50, res50, Yi, inpM_mb, SIMD_BYTES * 50); fma52hi_mem(res51, res51, Yi, inpM_mb, SIMD_BYTES * 51); fma52hi_mem(res52, res52, Yi, inpM_mb, SIMD_BYTES * 52); fma52hi_mem(res53, res53, Yi, inpM_mb, SIMD_BYTES * 53); fma52hi_mem(res54, res54, Yi, inpM_mb, SIMD_BYTES * 54); fma52hi_mem(res55, res55, Yi, inpM_mb, SIMD_BYTES * 55); fma52hi_mem(res56, res56, Yi, inpM_mb, SIMD_BYTES * 56); fma52hi_mem(res57, res57, Yi, inpM_mb, SIMD_BYTES * 57); fma52hi_mem(res58, res58, Yi, inpM_mb, SIMD_BYTES * 58); fma52hi_mem(res59, res59, Yi, inpM_mb, SIMD_BYTES * 59); } // Normalization { U64 T = get_zero64(); U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); res00 = and64(res00, MASK); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); res01 = and64(res01, MASK); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); res02 = and64(res02, MASK); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); res03 = and64(res03, MASK); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); res04 = and64(res04, MASK); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); res05 = and64(res05, MASK); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); res06 = and64(res06, MASK); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); res07 = and64(res07, MASK); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); res08 = and64(res08, MASK); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, T); T = srli64(res09, DIGIT_SIZE); res09 = and64(res09, MASK); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, T); T = srli64(res10, DIGIT_SIZE); res10 = and64(res10, MASK); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, T); T = srli64(res11, DIGIT_SIZE); res11 = and64(res11, MASK); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, T); T = srli64(res12, DIGIT_SIZE); res12 = and64(res12, MASK); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, T); T = srli64(res13, DIGIT_SIZE); res13 = and64(res13, MASK); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, T); T = srli64(res14, DIGIT_SIZE); res14 = and64(res14, MASK); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, T); T = srli64(res15, DIGIT_SIZE); res15 = and64(res15, MASK); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, T); T = srli64(res16, DIGIT_SIZE); res16 = and64(res16, MASK); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, T); T = srli64(res17, DIGIT_SIZE); res17 = and64(res17, MASK); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, T); T = srli64(res18, DIGIT_SIZE); res18 = and64(res18, MASK); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, T); T = srli64(res19, DIGIT_SIZE); res19 = and64(res19, MASK); storeu64(out_mb + MB_WIDTH * 19, res19); res20 = add64(res20, T); T = srli64(res20, DIGIT_SIZE); res20 = and64(res20, MASK); storeu64(out_mb + MB_WIDTH * 20, res20); res21 = add64(res21, T); T = srli64(res21, DIGIT_SIZE); res21 = and64(res21, MASK); storeu64(out_mb + MB_WIDTH * 21, res21); res22 = add64(res22, T); T = srli64(res22, DIGIT_SIZE); res22 = and64(res22, MASK); storeu64(out_mb + MB_WIDTH * 22, res22); res23 = add64(res23, T); T = srli64(res23, DIGIT_SIZE); res23 = and64(res23, MASK); storeu64(out_mb + MB_WIDTH * 23, res23); res24 = add64(res24, T); T = srli64(res24, DIGIT_SIZE); res24 = and64(res24, MASK); storeu64(out_mb + MB_WIDTH * 24, res24); res25 = add64(res25, T); T = srli64(res25, DIGIT_SIZE); res25 = and64(res25, MASK); storeu64(out_mb + MB_WIDTH * 25, res25); res26 = add64(res26, T); T = srli64(res26, DIGIT_SIZE); res26 = and64(res26, MASK); storeu64(out_mb + MB_WIDTH * 26, res26); res27 = add64(res27, T); T = srli64(res27, DIGIT_SIZE); res27 = and64(res27, MASK); storeu64(out_mb + MB_WIDTH * 27, res27); res28 = add64(res28, T); T = srli64(res28, DIGIT_SIZE); res28 = and64(res28, MASK); storeu64(out_mb + MB_WIDTH * 28, res28); res29 = add64(res29, T); T = srli64(res29, DIGIT_SIZE); res29 = and64(res29, MASK); storeu64(out_mb + MB_WIDTH * 29, res29); res30 = add64(res30, T); T = srli64(res30, DIGIT_SIZE); res30 = and64(res30, MASK); storeu64(out_mb + MB_WIDTH * 30, res30); res31 = add64(res31, T); T = srli64(res31, DIGIT_SIZE); res31 = and64(res31, MASK); storeu64(out_mb + MB_WIDTH * 31, res31); res32 = add64(res32, T); T = srli64(res32, DIGIT_SIZE); res32 = and64(res32, MASK); storeu64(out_mb + MB_WIDTH * 32, res32); res33 = add64(res33, T); T = srli64(res33, DIGIT_SIZE); res33 = and64(res33, MASK); storeu64(out_mb + MB_WIDTH * 33, res33); res34 = add64(res34, T); T = srli64(res34, DIGIT_SIZE); res34 = and64(res34, MASK); storeu64(out_mb + MB_WIDTH * 34, res34); res35 = add64(res35, T); T = srli64(res35, DIGIT_SIZE); res35 = and64(res35, MASK); storeu64(out_mb + MB_WIDTH * 35, res35); res36 = add64(res36, T); T = srli64(res36, DIGIT_SIZE); res36 = and64(res36, MASK); storeu64(out_mb + MB_WIDTH * 36, res36); res37 = add64(res37, T); T = srli64(res37, DIGIT_SIZE); res37 = and64(res37, MASK); storeu64(out_mb + MB_WIDTH * 37, res37); res38 = add64(res38, T); T = srli64(res38, DIGIT_SIZE); res38 = and64(res38, MASK); storeu64(out_mb + MB_WIDTH * 38, res38); res39 = add64(res39, T); T = srli64(res39, DIGIT_SIZE); res39 = and64(res39, MASK); storeu64(out_mb + MB_WIDTH * 39, res39); res40 = add64(res40, T); T = srli64(res40, DIGIT_SIZE); res40 = and64(res40, MASK); storeu64(out_mb + MB_WIDTH * 40, res40); res41 = add64(res41, T); T = srli64(res41, DIGIT_SIZE); res41 = and64(res41, MASK); storeu64(out_mb + MB_WIDTH * 41, res41); res42 = add64(res42, T); T = srli64(res42, DIGIT_SIZE); res42 = and64(res42, MASK); storeu64(out_mb + MB_WIDTH * 42, res42); res43 = add64(res43, T); T = srli64(res43, DIGIT_SIZE); res43 = and64(res43, MASK); storeu64(out_mb + MB_WIDTH * 43, res43); res44 = add64(res44, T); T = srli64(res44, DIGIT_SIZE); res44 = and64(res44, MASK); storeu64(out_mb + MB_WIDTH * 44, res44); res45 = add64(res45, T); T = srli64(res45, DIGIT_SIZE); res45 = and64(res45, MASK); storeu64(out_mb + MB_WIDTH * 45, res45); res46 = add64(res46, T); T = srli64(res46, DIGIT_SIZE); res46 = and64(res46, MASK); storeu64(out_mb + MB_WIDTH * 46, res46); res47 = add64(res47, T); T = srli64(res47, DIGIT_SIZE); res47 = and64(res47, MASK); storeu64(out_mb + MB_WIDTH * 47, res47); res48 = add64(res48, T); T = srli64(res48, DIGIT_SIZE); res48 = and64(res48, MASK); storeu64(out_mb + MB_WIDTH * 48, res48); res49 = add64(res49, T); T = srli64(res49, DIGIT_SIZE); res49 = and64(res49, MASK); storeu64(out_mb + MB_WIDTH * 49, res49); res50 = add64(res50, T); T = srli64(res50, DIGIT_SIZE); res50 = and64(res50, MASK); storeu64(out_mb + MB_WIDTH * 50, res50); res51 = add64(res51, T); T = srli64(res51, DIGIT_SIZE); res51 = and64(res51, MASK); storeu64(out_mb + MB_WIDTH * 51, res51); res52 = add64(res52, T); T = srli64(res52, DIGIT_SIZE); res52 = and64(res52, MASK); storeu64(out_mb + MB_WIDTH * 52, res52); res53 = add64(res53, T); T = srli64(res53, DIGIT_SIZE); res53 = and64(res53, MASK); storeu64(out_mb + MB_WIDTH * 53, res53); res54 = add64(res54, T); T = srli64(res54, DIGIT_SIZE); res54 = and64(res54, MASK); storeu64(out_mb + MB_WIDTH * 54, res54); res55 = add64(res55, T); T = srli64(res55, DIGIT_SIZE); res55 = and64(res55, MASK); storeu64(out_mb + MB_WIDTH * 55, res55); res56 = add64(res56, T); T = srli64(res56, DIGIT_SIZE); res56 = and64(res56, MASK); storeu64(out_mb + MB_WIDTH * 56, res56); res57 = add64(res57, T); T = srli64(res57, DIGIT_SIZE); res57 = and64(res57, MASK); storeu64(out_mb + MB_WIDTH * 57, res57); res58 = add64(res58, T); T = srli64(res58, DIGIT_SIZE); res58 = and64(res58, MASK); storeu64(out_mb + MB_WIDTH * 58, res58); res59 = add64(res59, T); res59 = and64(res59, MASK); storeu64(out_mb + MB_WIDTH * 59, res59); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/ifma_amm52x79_mb8.c000066400000000000000000001034071470420105600327310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void ifma_amm52x79_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpB_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29, res30, res31, res32, res33, res34, res35, res36, res37, res38, res39, res40, res41, res42, res43, res44, res45, res46, res47, res48, res49, res50, res51, res52, res53, res54, res55, res56, res57, res58, res59, res60, res61, res62, res63, res64, res65, res66, res67, res68, res69, res70, res71, res72, res73, res74, res75, res76, res77, res78; U64 K = loadu64(k0_mb); int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = res30 = res31 = res32 = res33 = res34 = res35 = res36 = res37 = res38 = res39 = res40 = res41 = res42 = res43 = res44 = res45 = res46 = res47 = res48 = res49 = res50 = res51 = res52 = res53 = res54 = res55 = res56 = res57 = res58 = res59 = res60 = res61 = res62 = res63 = res64 = res65 = res66 = res67 = res68 = res69 = res70 = res71 = res72 = res73 = res74 = res75 = res76 = res77 = res78 = get_zero64(); for (itr = 0; itr < 79; itr++) { U64 Yi; U64 Bi = loadu64(inpB_mb); inpB_mb += MB_WIDTH; fma52lo_mem(res00, res00, Bi, inpA_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Bi, inpA_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Bi, inpA_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Bi, inpA_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Bi, inpA_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Bi, inpA_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Bi, inpA_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Bi, inpA_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Bi, inpA_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Bi, inpA_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Bi, inpA_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Bi, inpA_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Bi, inpA_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Bi, inpA_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Bi, inpA_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Bi, inpA_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Bi, inpA_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Bi, inpA_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Bi, inpA_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Bi, inpA_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Bi, inpA_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Bi, inpA_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Bi, inpA_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Bi, inpA_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Bi, inpA_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Bi, inpA_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Bi, inpA_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Bi, inpA_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Bi, inpA_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Bi, inpA_mb, SIMD_BYTES * 29); fma52lo_mem(res30, res30, Bi, inpA_mb, SIMD_BYTES * 30); fma52lo_mem(res31, res31, Bi, inpA_mb, SIMD_BYTES * 31); fma52lo_mem(res32, res32, Bi, inpA_mb, SIMD_BYTES * 32); fma52lo_mem(res33, res33, Bi, inpA_mb, SIMD_BYTES * 33); fma52lo_mem(res34, res34, Bi, inpA_mb, SIMD_BYTES * 34); fma52lo_mem(res35, res35, Bi, inpA_mb, SIMD_BYTES * 35); fma52lo_mem(res36, res36, Bi, inpA_mb, SIMD_BYTES * 36); fma52lo_mem(res37, res37, Bi, inpA_mb, SIMD_BYTES * 37); fma52lo_mem(res38, res38, Bi, inpA_mb, SIMD_BYTES * 38); fma52lo_mem(res39, res39, Bi, inpA_mb, SIMD_BYTES * 39); fma52lo_mem(res40, res40, Bi, inpA_mb, SIMD_BYTES * 40); fma52lo_mem(res41, res41, Bi, inpA_mb, SIMD_BYTES * 41); fma52lo_mem(res42, res42, Bi, inpA_mb, SIMD_BYTES * 42); fma52lo_mem(res43, res43, Bi, inpA_mb, SIMD_BYTES * 43); fma52lo_mem(res44, res44, Bi, inpA_mb, SIMD_BYTES * 44); fma52lo_mem(res45, res45, Bi, inpA_mb, SIMD_BYTES * 45); fma52lo_mem(res46, res46, Bi, inpA_mb, SIMD_BYTES * 46); fma52lo_mem(res47, res47, Bi, inpA_mb, SIMD_BYTES * 47); fma52lo_mem(res48, res48, Bi, inpA_mb, SIMD_BYTES * 48); fma52lo_mem(res49, res49, Bi, inpA_mb, SIMD_BYTES * 49); fma52lo_mem(res50, res50, Bi, inpA_mb, SIMD_BYTES * 50); fma52lo_mem(res51, res51, Bi, inpA_mb, SIMD_BYTES * 51); fma52lo_mem(res52, res52, Bi, inpA_mb, SIMD_BYTES * 52); fma52lo_mem(res53, res53, Bi, inpA_mb, SIMD_BYTES * 53); fma52lo_mem(res54, res54, Bi, inpA_mb, SIMD_BYTES * 54); fma52lo_mem(res55, res55, Bi, inpA_mb, SIMD_BYTES * 55); fma52lo_mem(res56, res56, Bi, inpA_mb, SIMD_BYTES * 56); fma52lo_mem(res57, res57, Bi, inpA_mb, SIMD_BYTES * 57); fma52lo_mem(res58, res58, Bi, inpA_mb, SIMD_BYTES * 58); fma52lo_mem(res59, res59, Bi, inpA_mb, SIMD_BYTES * 59); fma52lo_mem(res60, res60, Bi, inpA_mb, SIMD_BYTES * 60); fma52lo_mem(res61, res61, Bi, inpA_mb, SIMD_BYTES * 61); fma52lo_mem(res62, res62, Bi, inpA_mb, SIMD_BYTES * 62); fma52lo_mem(res63, res63, Bi, inpA_mb, SIMD_BYTES * 63); fma52lo_mem(res64, res64, Bi, inpA_mb, SIMD_BYTES * 64); fma52lo_mem(res65, res65, Bi, inpA_mb, SIMD_BYTES * 65); fma52lo_mem(res66, res66, Bi, inpA_mb, SIMD_BYTES * 66); fma52lo_mem(res67, res67, Bi, inpA_mb, SIMD_BYTES * 67); fma52lo_mem(res68, res68, Bi, inpA_mb, SIMD_BYTES * 68); fma52lo_mem(res69, res69, Bi, inpA_mb, SIMD_BYTES * 69); fma52lo_mem(res70, res70, Bi, inpA_mb, SIMD_BYTES * 70); fma52lo_mem(res71, res71, Bi, inpA_mb, SIMD_BYTES * 71); fma52lo_mem(res72, res72, Bi, inpA_mb, SIMD_BYTES * 72); fma52lo_mem(res73, res73, Bi, inpA_mb, SIMD_BYTES * 73); fma52lo_mem(res74, res74, Bi, inpA_mb, SIMD_BYTES * 74); fma52lo_mem(res75, res75, Bi, inpA_mb, SIMD_BYTES * 75); fma52lo_mem(res76, res76, Bi, inpA_mb, SIMD_BYTES * 76); fma52lo_mem(res77, res77, Bi, inpA_mb, SIMD_BYTES * 77); fma52lo_mem(res78, res78, Bi, inpA_mb, SIMD_BYTES * 78); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52lo_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52lo_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52lo_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52lo_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52lo_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52lo_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52lo_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52lo_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52lo_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52lo_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52lo_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52lo_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52lo_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52lo_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52lo_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52lo_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52lo_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52lo_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52lo_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52lo_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52lo_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52lo_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52lo_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52lo_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52lo_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52lo_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52lo_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52lo_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52lo_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); fma52lo_mem(res30, res30, Yi, inpM_mb, SIMD_BYTES * 30); fma52lo_mem(res31, res31, Yi, inpM_mb, SIMD_BYTES * 31); fma52lo_mem(res32, res32, Yi, inpM_mb, SIMD_BYTES * 32); fma52lo_mem(res33, res33, Yi, inpM_mb, SIMD_BYTES * 33); fma52lo_mem(res34, res34, Yi, inpM_mb, SIMD_BYTES * 34); fma52lo_mem(res35, res35, Yi, inpM_mb, SIMD_BYTES * 35); fma52lo_mem(res36, res36, Yi, inpM_mb, SIMD_BYTES * 36); fma52lo_mem(res37, res37, Yi, inpM_mb, SIMD_BYTES * 37); fma52lo_mem(res38, res38, Yi, inpM_mb, SIMD_BYTES * 38); fma52lo_mem(res39, res39, Yi, inpM_mb, SIMD_BYTES * 39); fma52lo_mem(res40, res40, Yi, inpM_mb, SIMD_BYTES * 40); fma52lo_mem(res41, res41, Yi, inpM_mb, SIMD_BYTES * 41); fma52lo_mem(res42, res42, Yi, inpM_mb, SIMD_BYTES * 42); fma52lo_mem(res43, res43, Yi, inpM_mb, SIMD_BYTES * 43); fma52lo_mem(res44, res44, Yi, inpM_mb, SIMD_BYTES * 44); fma52lo_mem(res45, res45, Yi, inpM_mb, SIMD_BYTES * 45); fma52lo_mem(res46, res46, Yi, inpM_mb, SIMD_BYTES * 46); fma52lo_mem(res47, res47, Yi, inpM_mb, SIMD_BYTES * 47); fma52lo_mem(res48, res48, Yi, inpM_mb, SIMD_BYTES * 48); fma52lo_mem(res49, res49, Yi, inpM_mb, SIMD_BYTES * 49); fma52lo_mem(res50, res50, Yi, inpM_mb, SIMD_BYTES * 50); fma52lo_mem(res51, res51, Yi, inpM_mb, SIMD_BYTES * 51); fma52lo_mem(res52, res52, Yi, inpM_mb, SIMD_BYTES * 52); fma52lo_mem(res53, res53, Yi, inpM_mb, SIMD_BYTES * 53); fma52lo_mem(res54, res54, Yi, inpM_mb, SIMD_BYTES * 54); fma52lo_mem(res55, res55, Yi, inpM_mb, SIMD_BYTES * 55); fma52lo_mem(res56, res56, Yi, inpM_mb, SIMD_BYTES * 56); fma52lo_mem(res57, res57, Yi, inpM_mb, SIMD_BYTES * 57); fma52lo_mem(res58, res58, Yi, inpM_mb, SIMD_BYTES * 58); fma52lo_mem(res59, res59, Yi, inpM_mb, SIMD_BYTES * 59); fma52lo_mem(res60, res60, Yi, inpM_mb, SIMD_BYTES * 60); fma52lo_mem(res61, res61, Yi, inpM_mb, SIMD_BYTES * 61); fma52lo_mem(res62, res62, Yi, inpM_mb, SIMD_BYTES * 62); fma52lo_mem(res63, res63, Yi, inpM_mb, SIMD_BYTES * 63); fma52lo_mem(res64, res64, Yi, inpM_mb, SIMD_BYTES * 64); fma52lo_mem(res65, res65, Yi, inpM_mb, SIMD_BYTES * 65); fma52lo_mem(res66, res66, Yi, inpM_mb, SIMD_BYTES * 66); fma52lo_mem(res67, res67, Yi, inpM_mb, SIMD_BYTES * 67); fma52lo_mem(res68, res68, Yi, inpM_mb, SIMD_BYTES * 68); fma52lo_mem(res69, res69, Yi, inpM_mb, SIMD_BYTES * 69); fma52lo_mem(res70, res70, Yi, inpM_mb, SIMD_BYTES * 70); fma52lo_mem(res71, res71, Yi, inpM_mb, SIMD_BYTES * 71); fma52lo_mem(res72, res72, Yi, inpM_mb, SIMD_BYTES * 72); fma52lo_mem(res73, res73, Yi, inpM_mb, SIMD_BYTES * 73); fma52lo_mem(res74, res74, Yi, inpM_mb, SIMD_BYTES * 74); fma52lo_mem(res75, res75, Yi, inpM_mb, SIMD_BYTES * 75); fma52lo_mem(res76, res76, Yi, inpM_mb, SIMD_BYTES * 76); fma52lo_mem(res77, res77, Yi, inpM_mb, SIMD_BYTES * 77); fma52lo_mem(res78, res78, Yi, inpM_mb, SIMD_BYTES * 78); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res02, Bi, inpA_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res03, Bi, inpA_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res04, Bi, inpA_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res05, Bi, inpA_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res06, Bi, inpA_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res07, Bi, inpA_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res08, Bi, inpA_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res09, Bi, inpA_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res10, Bi, inpA_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res11, Bi, inpA_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res12, Bi, inpA_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res13, Bi, inpA_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res14, Bi, inpA_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res15, Bi, inpA_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res16, Bi, inpA_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res17, Bi, inpA_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res18, Bi, inpA_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res19, Bi, inpA_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res20, Bi, inpA_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res21, Bi, inpA_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res22, Bi, inpA_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res23, Bi, inpA_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res24, Bi, inpA_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res25, Bi, inpA_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res26, Bi, inpA_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res27, Bi, inpA_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res28, Bi, inpA_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res29, Bi, inpA_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res30, Bi, inpA_mb, SIMD_BYTES * 29); fma52hi_mem(res30, res31, Bi, inpA_mb, SIMD_BYTES * 30); fma52hi_mem(res31, res32, Bi, inpA_mb, SIMD_BYTES * 31); fma52hi_mem(res32, res33, Bi, inpA_mb, SIMD_BYTES * 32); fma52hi_mem(res33, res34, Bi, inpA_mb, SIMD_BYTES * 33); fma52hi_mem(res34, res35, Bi, inpA_mb, SIMD_BYTES * 34); fma52hi_mem(res35, res36, Bi, inpA_mb, SIMD_BYTES * 35); fma52hi_mem(res36, res37, Bi, inpA_mb, SIMD_BYTES * 36); fma52hi_mem(res37, res38, Bi, inpA_mb, SIMD_BYTES * 37); fma52hi_mem(res38, res39, Bi, inpA_mb, SIMD_BYTES * 38); fma52hi_mem(res39, res40, Bi, inpA_mb, SIMD_BYTES * 39); fma52hi_mem(res40, res41, Bi, inpA_mb, SIMD_BYTES * 40); fma52hi_mem(res41, res42, Bi, inpA_mb, SIMD_BYTES * 41); fma52hi_mem(res42, res43, Bi, inpA_mb, SIMD_BYTES * 42); fma52hi_mem(res43, res44, Bi, inpA_mb, SIMD_BYTES * 43); fma52hi_mem(res44, res45, Bi, inpA_mb, SIMD_BYTES * 44); fma52hi_mem(res45, res46, Bi, inpA_mb, SIMD_BYTES * 45); fma52hi_mem(res46, res47, Bi, inpA_mb, SIMD_BYTES * 46); fma52hi_mem(res47, res48, Bi, inpA_mb, SIMD_BYTES * 47); fma52hi_mem(res48, res49, Bi, inpA_mb, SIMD_BYTES * 48); fma52hi_mem(res49, res50, Bi, inpA_mb, SIMD_BYTES * 49); fma52hi_mem(res50, res51, Bi, inpA_mb, SIMD_BYTES * 50); fma52hi_mem(res51, res52, Bi, inpA_mb, SIMD_BYTES * 51); fma52hi_mem(res52, res53, Bi, inpA_mb, SIMD_BYTES * 52); fma52hi_mem(res53, res54, Bi, inpA_mb, SIMD_BYTES * 53); fma52hi_mem(res54, res55, Bi, inpA_mb, SIMD_BYTES * 54); fma52hi_mem(res55, res56, Bi, inpA_mb, SIMD_BYTES * 55); fma52hi_mem(res56, res57, Bi, inpA_mb, SIMD_BYTES * 56); fma52hi_mem(res57, res58, Bi, inpA_mb, SIMD_BYTES * 57); fma52hi_mem(res58, res59, Bi, inpA_mb, SIMD_BYTES * 58); fma52hi_mem(res59, res60, Bi, inpA_mb, SIMD_BYTES * 59); fma52hi_mem(res60, res61, Bi, inpA_mb, SIMD_BYTES * 60); fma52hi_mem(res61, res62, Bi, inpA_mb, SIMD_BYTES * 61); fma52hi_mem(res62, res63, Bi, inpA_mb, SIMD_BYTES * 62); fma52hi_mem(res63, res64, Bi, inpA_mb, SIMD_BYTES * 63); fma52hi_mem(res64, res65, Bi, inpA_mb, SIMD_BYTES * 64); fma52hi_mem(res65, res66, Bi, inpA_mb, SIMD_BYTES * 65); fma52hi_mem(res66, res67, Bi, inpA_mb, SIMD_BYTES * 66); fma52hi_mem(res67, res68, Bi, inpA_mb, SIMD_BYTES * 67); fma52hi_mem(res68, res69, Bi, inpA_mb, SIMD_BYTES * 68); fma52hi_mem(res69, res70, Bi, inpA_mb, SIMD_BYTES * 69); fma52hi_mem(res70, res71, Bi, inpA_mb, SIMD_BYTES * 70); fma52hi_mem(res71, res72, Bi, inpA_mb, SIMD_BYTES * 71); fma52hi_mem(res72, res73, Bi, inpA_mb, SIMD_BYTES * 72); fma52hi_mem(res73, res74, Bi, inpA_mb, SIMD_BYTES * 73); fma52hi_mem(res74, res75, Bi, inpA_mb, SIMD_BYTES * 74); fma52hi_mem(res75, res76, Bi, inpA_mb, SIMD_BYTES * 75); fma52hi_mem(res76, res77, Bi, inpA_mb, SIMD_BYTES * 76); fma52hi_mem(res77, res78, Bi, inpA_mb, SIMD_BYTES * 77); fma52hi_mem(res78, get_zero64(), Bi, inpA_mb, SIMD_BYTES * 78); fma52hi_mem(res00, res00, Yi, inpM_mb, SIMD_BYTES * 0); fma52hi_mem(res01, res01, Yi, inpM_mb, SIMD_BYTES * 1); fma52hi_mem(res02, res02, Yi, inpM_mb, SIMD_BYTES * 2); fma52hi_mem(res03, res03, Yi, inpM_mb, SIMD_BYTES * 3); fma52hi_mem(res04, res04, Yi, inpM_mb, SIMD_BYTES * 4); fma52hi_mem(res05, res05, Yi, inpM_mb, SIMD_BYTES * 5); fma52hi_mem(res06, res06, Yi, inpM_mb, SIMD_BYTES * 6); fma52hi_mem(res07, res07, Yi, inpM_mb, SIMD_BYTES * 7); fma52hi_mem(res08, res08, Yi, inpM_mb, SIMD_BYTES * 8); fma52hi_mem(res09, res09, Yi, inpM_mb, SIMD_BYTES * 9); fma52hi_mem(res10, res10, Yi, inpM_mb, SIMD_BYTES * 10); fma52hi_mem(res11, res11, Yi, inpM_mb, SIMD_BYTES * 11); fma52hi_mem(res12, res12, Yi, inpM_mb, SIMD_BYTES * 12); fma52hi_mem(res13, res13, Yi, inpM_mb, SIMD_BYTES * 13); fma52hi_mem(res14, res14, Yi, inpM_mb, SIMD_BYTES * 14); fma52hi_mem(res15, res15, Yi, inpM_mb, SIMD_BYTES * 15); fma52hi_mem(res16, res16, Yi, inpM_mb, SIMD_BYTES * 16); fma52hi_mem(res17, res17, Yi, inpM_mb, SIMD_BYTES * 17); fma52hi_mem(res18, res18, Yi, inpM_mb, SIMD_BYTES * 18); fma52hi_mem(res19, res19, Yi, inpM_mb, SIMD_BYTES * 19); fma52hi_mem(res20, res20, Yi, inpM_mb, SIMD_BYTES * 20); fma52hi_mem(res21, res21, Yi, inpM_mb, SIMD_BYTES * 21); fma52hi_mem(res22, res22, Yi, inpM_mb, SIMD_BYTES * 22); fma52hi_mem(res23, res23, Yi, inpM_mb, SIMD_BYTES * 23); fma52hi_mem(res24, res24, Yi, inpM_mb, SIMD_BYTES * 24); fma52hi_mem(res25, res25, Yi, inpM_mb, SIMD_BYTES * 25); fma52hi_mem(res26, res26, Yi, inpM_mb, SIMD_BYTES * 26); fma52hi_mem(res27, res27, Yi, inpM_mb, SIMD_BYTES * 27); fma52hi_mem(res28, res28, Yi, inpM_mb, SIMD_BYTES * 28); fma52hi_mem(res29, res29, Yi, inpM_mb, SIMD_BYTES * 29); fma52hi_mem(res30, res30, Yi, inpM_mb, SIMD_BYTES * 30); fma52hi_mem(res31, res31, Yi, inpM_mb, SIMD_BYTES * 31); fma52hi_mem(res32, res32, Yi, inpM_mb, SIMD_BYTES * 32); fma52hi_mem(res33, res33, Yi, inpM_mb, SIMD_BYTES * 33); fma52hi_mem(res34, res34, Yi, inpM_mb, SIMD_BYTES * 34); fma52hi_mem(res35, res35, Yi, inpM_mb, SIMD_BYTES * 35); fma52hi_mem(res36, res36, Yi, inpM_mb, SIMD_BYTES * 36); fma52hi_mem(res37, res37, Yi, inpM_mb, SIMD_BYTES * 37); fma52hi_mem(res38, res38, Yi, inpM_mb, SIMD_BYTES * 38); fma52hi_mem(res39, res39, Yi, inpM_mb, SIMD_BYTES * 39); fma52hi_mem(res40, res40, Yi, inpM_mb, SIMD_BYTES * 40); fma52hi_mem(res41, res41, Yi, inpM_mb, SIMD_BYTES * 41); fma52hi_mem(res42, res42, Yi, inpM_mb, SIMD_BYTES * 42); fma52hi_mem(res43, res43, Yi, inpM_mb, SIMD_BYTES * 43); fma52hi_mem(res44, res44, Yi, inpM_mb, SIMD_BYTES * 44); fma52hi_mem(res45, res45, Yi, inpM_mb, SIMD_BYTES * 45); fma52hi_mem(res46, res46, Yi, inpM_mb, SIMD_BYTES * 46); fma52hi_mem(res47, res47, Yi, inpM_mb, SIMD_BYTES * 47); fma52hi_mem(res48, res48, Yi, inpM_mb, SIMD_BYTES * 48); fma52hi_mem(res49, res49, Yi, inpM_mb, SIMD_BYTES * 49); fma52hi_mem(res50, res50, Yi, inpM_mb, SIMD_BYTES * 50); fma52hi_mem(res51, res51, Yi, inpM_mb, SIMD_BYTES * 51); fma52hi_mem(res52, res52, Yi, inpM_mb, SIMD_BYTES * 52); fma52hi_mem(res53, res53, Yi, inpM_mb, SIMD_BYTES * 53); fma52hi_mem(res54, res54, Yi, inpM_mb, SIMD_BYTES * 54); fma52hi_mem(res55, res55, Yi, inpM_mb, SIMD_BYTES * 55); fma52hi_mem(res56, res56, Yi, inpM_mb, SIMD_BYTES * 56); fma52hi_mem(res57, res57, Yi, inpM_mb, SIMD_BYTES * 57); fma52hi_mem(res58, res58, Yi, inpM_mb, SIMD_BYTES * 58); fma52hi_mem(res59, res59, Yi, inpM_mb, SIMD_BYTES * 59); fma52hi_mem(res60, res60, Yi, inpM_mb, SIMD_BYTES * 60); fma52hi_mem(res61, res61, Yi, inpM_mb, SIMD_BYTES * 61); fma52hi_mem(res62, res62, Yi, inpM_mb, SIMD_BYTES * 62); fma52hi_mem(res63, res63, Yi, inpM_mb, SIMD_BYTES * 63); fma52hi_mem(res64, res64, Yi, inpM_mb, SIMD_BYTES * 64); fma52hi_mem(res65, res65, Yi, inpM_mb, SIMD_BYTES * 65); fma52hi_mem(res66, res66, Yi, inpM_mb, SIMD_BYTES * 66); fma52hi_mem(res67, res67, Yi, inpM_mb, SIMD_BYTES * 67); fma52hi_mem(res68, res68, Yi, inpM_mb, SIMD_BYTES * 68); fma52hi_mem(res69, res69, Yi, inpM_mb, SIMD_BYTES * 69); fma52hi_mem(res70, res70, Yi, inpM_mb, SIMD_BYTES * 70); fma52hi_mem(res71, res71, Yi, inpM_mb, SIMD_BYTES * 71); fma52hi_mem(res72, res72, Yi, inpM_mb, SIMD_BYTES * 72); fma52hi_mem(res73, res73, Yi, inpM_mb, SIMD_BYTES * 73); fma52hi_mem(res74, res74, Yi, inpM_mb, SIMD_BYTES * 74); fma52hi_mem(res75, res75, Yi, inpM_mb, SIMD_BYTES * 75); fma52hi_mem(res76, res76, Yi, inpM_mb, SIMD_BYTES * 76); fma52hi_mem(res77, res77, Yi, inpM_mb, SIMD_BYTES * 77); fma52hi_mem(res78, res78, Yi, inpM_mb, SIMD_BYTES * 78); } // Normalization { U64 T = get_zero64(); U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); res00 = and64(res00, MASK); storeu64(out_mb + MB_WIDTH * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); res01 = and64(res01, MASK); storeu64(out_mb + MB_WIDTH * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); res02 = and64(res02, MASK); storeu64(out_mb + MB_WIDTH * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); res03 = and64(res03, MASK); storeu64(out_mb + MB_WIDTH * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); res04 = and64(res04, MASK); storeu64(out_mb + MB_WIDTH * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); res05 = and64(res05, MASK); storeu64(out_mb + MB_WIDTH * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); res06 = and64(res06, MASK); storeu64(out_mb + MB_WIDTH * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); res07 = and64(res07, MASK); storeu64(out_mb + MB_WIDTH * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); res08 = and64(res08, MASK); storeu64(out_mb + MB_WIDTH * 8, res08); res09 = add64(res09, T); T = srli64(res09, DIGIT_SIZE); res09 = and64(res09, MASK); storeu64(out_mb + MB_WIDTH * 9, res09); res10 = add64(res10, T); T = srli64(res10, DIGIT_SIZE); res10 = and64(res10, MASK); storeu64(out_mb + MB_WIDTH * 10, res10); res11 = add64(res11, T); T = srli64(res11, DIGIT_SIZE); res11 = and64(res11, MASK); storeu64(out_mb + MB_WIDTH * 11, res11); res12 = add64(res12, T); T = srli64(res12, DIGIT_SIZE); res12 = and64(res12, MASK); storeu64(out_mb + MB_WIDTH * 12, res12); res13 = add64(res13, T); T = srli64(res13, DIGIT_SIZE); res13 = and64(res13, MASK); storeu64(out_mb + MB_WIDTH * 13, res13); res14 = add64(res14, T); T = srli64(res14, DIGIT_SIZE); res14 = and64(res14, MASK); storeu64(out_mb + MB_WIDTH * 14, res14); res15 = add64(res15, T); T = srli64(res15, DIGIT_SIZE); res15 = and64(res15, MASK); storeu64(out_mb + MB_WIDTH * 15, res15); res16 = add64(res16, T); T = srli64(res16, DIGIT_SIZE); res16 = and64(res16, MASK); storeu64(out_mb + MB_WIDTH * 16, res16); res17 = add64(res17, T); T = srli64(res17, DIGIT_SIZE); res17 = and64(res17, MASK); storeu64(out_mb + MB_WIDTH * 17, res17); res18 = add64(res18, T); T = srli64(res18, DIGIT_SIZE); res18 = and64(res18, MASK); storeu64(out_mb + MB_WIDTH * 18, res18); res19 = add64(res19, T); T = srli64(res19, DIGIT_SIZE); res19 = and64(res19, MASK); storeu64(out_mb + MB_WIDTH * 19, res19); res20 = add64(res20, T); T = srli64(res20, DIGIT_SIZE); res20 = and64(res20, MASK); storeu64(out_mb + MB_WIDTH * 20, res20); res21 = add64(res21, T); T = srli64(res21, DIGIT_SIZE); res21 = and64(res21, MASK); storeu64(out_mb + MB_WIDTH * 21, res21); res22 = add64(res22, T); T = srli64(res22, DIGIT_SIZE); res22 = and64(res22, MASK); storeu64(out_mb + MB_WIDTH * 22, res22); res23 = add64(res23, T); T = srli64(res23, DIGIT_SIZE); res23 = and64(res23, MASK); storeu64(out_mb + MB_WIDTH * 23, res23); res24 = add64(res24, T); T = srli64(res24, DIGIT_SIZE); res24 = and64(res24, MASK); storeu64(out_mb + MB_WIDTH * 24, res24); res25 = add64(res25, T); T = srli64(res25, DIGIT_SIZE); res25 = and64(res25, MASK); storeu64(out_mb + MB_WIDTH * 25, res25); res26 = add64(res26, T); T = srli64(res26, DIGIT_SIZE); res26 = and64(res26, MASK); storeu64(out_mb + MB_WIDTH * 26, res26); res27 = add64(res27, T); T = srli64(res27, DIGIT_SIZE); res27 = and64(res27, MASK); storeu64(out_mb + MB_WIDTH * 27, res27); res28 = add64(res28, T); T = srli64(res28, DIGIT_SIZE); res28 = and64(res28, MASK); storeu64(out_mb + MB_WIDTH * 28, res28); res29 = add64(res29, T); T = srli64(res29, DIGIT_SIZE); res29 = and64(res29, MASK); storeu64(out_mb + MB_WIDTH * 29, res29); res30 = add64(res30, T); T = srli64(res30, DIGIT_SIZE); res30 = and64(res30, MASK); storeu64(out_mb + MB_WIDTH * 30, res30); res31 = add64(res31, T); T = srli64(res31, DIGIT_SIZE); res31 = and64(res31, MASK); storeu64(out_mb + MB_WIDTH * 31, res31); res32 = add64(res32, T); T = srli64(res32, DIGIT_SIZE); res32 = and64(res32, MASK); storeu64(out_mb + MB_WIDTH * 32, res32); res33 = add64(res33, T); T = srli64(res33, DIGIT_SIZE); res33 = and64(res33, MASK); storeu64(out_mb + MB_WIDTH * 33, res33); res34 = add64(res34, T); T = srli64(res34, DIGIT_SIZE); res34 = and64(res34, MASK); storeu64(out_mb + MB_WIDTH * 34, res34); res35 = add64(res35, T); T = srli64(res35, DIGIT_SIZE); res35 = and64(res35, MASK); storeu64(out_mb + MB_WIDTH * 35, res35); res36 = add64(res36, T); T = srli64(res36, DIGIT_SIZE); res36 = and64(res36, MASK); storeu64(out_mb + MB_WIDTH * 36, res36); res37 = add64(res37, T); T = srli64(res37, DIGIT_SIZE); res37 = and64(res37, MASK); storeu64(out_mb + MB_WIDTH * 37, res37); res38 = add64(res38, T); T = srli64(res38, DIGIT_SIZE); res38 = and64(res38, MASK); storeu64(out_mb + MB_WIDTH * 38, res38); res39 = add64(res39, T); T = srli64(res39, DIGIT_SIZE); res39 = and64(res39, MASK); storeu64(out_mb + MB_WIDTH * 39, res39); res40 = add64(res40, T); T = srli64(res40, DIGIT_SIZE); res40 = and64(res40, MASK); storeu64(out_mb + MB_WIDTH * 40, res40); res41 = add64(res41, T); T = srli64(res41, DIGIT_SIZE); res41 = and64(res41, MASK); storeu64(out_mb + MB_WIDTH * 41, res41); res42 = add64(res42, T); T = srli64(res42, DIGIT_SIZE); res42 = and64(res42, MASK); storeu64(out_mb + MB_WIDTH * 42, res42); res43 = add64(res43, T); T = srli64(res43, DIGIT_SIZE); res43 = and64(res43, MASK); storeu64(out_mb + MB_WIDTH * 43, res43); res44 = add64(res44, T); T = srli64(res44, DIGIT_SIZE); res44 = and64(res44, MASK); storeu64(out_mb + MB_WIDTH * 44, res44); res45 = add64(res45, T); T = srli64(res45, DIGIT_SIZE); res45 = and64(res45, MASK); storeu64(out_mb + MB_WIDTH * 45, res45); res46 = add64(res46, T); T = srli64(res46, DIGIT_SIZE); res46 = and64(res46, MASK); storeu64(out_mb + MB_WIDTH * 46, res46); res47 = add64(res47, T); T = srli64(res47, DIGIT_SIZE); res47 = and64(res47, MASK); storeu64(out_mb + MB_WIDTH * 47, res47); res48 = add64(res48, T); T = srli64(res48, DIGIT_SIZE); res48 = and64(res48, MASK); storeu64(out_mb + MB_WIDTH * 48, res48); res49 = add64(res49, T); T = srli64(res49, DIGIT_SIZE); res49 = and64(res49, MASK); storeu64(out_mb + MB_WIDTH * 49, res49); res50 = add64(res50, T); T = srli64(res50, DIGIT_SIZE); res50 = and64(res50, MASK); storeu64(out_mb + MB_WIDTH * 50, res50); res51 = add64(res51, T); T = srli64(res51, DIGIT_SIZE); res51 = and64(res51, MASK); storeu64(out_mb + MB_WIDTH * 51, res51); res52 = add64(res52, T); T = srli64(res52, DIGIT_SIZE); res52 = and64(res52, MASK); storeu64(out_mb + MB_WIDTH * 52, res52); res53 = add64(res53, T); T = srli64(res53, DIGIT_SIZE); res53 = and64(res53, MASK); storeu64(out_mb + MB_WIDTH * 53, res53); res54 = add64(res54, T); T = srli64(res54, DIGIT_SIZE); res54 = and64(res54, MASK); storeu64(out_mb + MB_WIDTH * 54, res54); res55 = add64(res55, T); T = srli64(res55, DIGIT_SIZE); res55 = and64(res55, MASK); storeu64(out_mb + MB_WIDTH * 55, res55); res56 = add64(res56, T); T = srli64(res56, DIGIT_SIZE); res56 = and64(res56, MASK); storeu64(out_mb + MB_WIDTH * 56, res56); res57 = add64(res57, T); T = srli64(res57, DIGIT_SIZE); res57 = and64(res57, MASK); storeu64(out_mb + MB_WIDTH * 57, res57); res58 = add64(res58, T); T = srli64(res58, DIGIT_SIZE); res58 = and64(res58, MASK); storeu64(out_mb + MB_WIDTH * 58, res58); res59 = add64(res59, T); T = srli64(res59, DIGIT_SIZE); res59 = and64(res59, MASK); storeu64(out_mb + MB_WIDTH * 59, res59); res60 = add64(res60, T); T = srli64(res60, DIGIT_SIZE); res60 = and64(res60, MASK); storeu64(out_mb + MB_WIDTH * 60, res60); res61 = add64(res61, T); T = srli64(res61, DIGIT_SIZE); res61 = and64(res61, MASK); storeu64(out_mb + MB_WIDTH * 61, res61); res62 = add64(res62, T); T = srli64(res62, DIGIT_SIZE); res62 = and64(res62, MASK); storeu64(out_mb + MB_WIDTH * 62, res62); res63 = add64(res63, T); T = srli64(res63, DIGIT_SIZE); res63 = and64(res63, MASK); storeu64(out_mb + MB_WIDTH * 63, res63); res64 = add64(res64, T); T = srli64(res64, DIGIT_SIZE); res64 = and64(res64, MASK); storeu64(out_mb + MB_WIDTH * 64, res64); res65 = add64(res65, T); T = srli64(res65, DIGIT_SIZE); res65 = and64(res65, MASK); storeu64(out_mb + MB_WIDTH * 65, res65); res66 = add64(res66, T); T = srli64(res66, DIGIT_SIZE); res66 = and64(res66, MASK); storeu64(out_mb + MB_WIDTH * 66, res66); res67 = add64(res67, T); T = srli64(res67, DIGIT_SIZE); res67 = and64(res67, MASK); storeu64(out_mb + MB_WIDTH * 67, res67); res68 = add64(res68, T); T = srli64(res68, DIGIT_SIZE); res68 = and64(res68, MASK); storeu64(out_mb + MB_WIDTH * 68, res68); res69 = add64(res69, T); T = srli64(res69, DIGIT_SIZE); res69 = and64(res69, MASK); storeu64(out_mb + MB_WIDTH * 69, res69); res70 = add64(res70, T); T = srli64(res70, DIGIT_SIZE); res70 = and64(res70, MASK); storeu64(out_mb + MB_WIDTH * 70, res70); res71 = add64(res71, T); T = srli64(res71, DIGIT_SIZE); res71 = and64(res71, MASK); storeu64(out_mb + MB_WIDTH * 71, res71); res72 = add64(res72, T); T = srli64(res72, DIGIT_SIZE); res72 = and64(res72, MASK); storeu64(out_mb + MB_WIDTH * 72, res72); res73 = add64(res73, T); T = srli64(res73, DIGIT_SIZE); res73 = and64(res73, MASK); storeu64(out_mb + MB_WIDTH * 73, res73); res74 = add64(res74, T); T = srli64(res74, DIGIT_SIZE); res74 = and64(res74, MASK); storeu64(out_mb + MB_WIDTH * 74, res74); res75 = add64(res75, T); T = srli64(res75, DIGIT_SIZE); res75 = and64(res75, MASK); storeu64(out_mb + MB_WIDTH * 75, res75); res76 = add64(res76, T); T = srli64(res76, DIGIT_SIZE); res76 = and64(res76, MASK); storeu64(out_mb + MB_WIDTH * 76, res76); res77 = add64(res77, T); T = srli64(res77, DIGIT_SIZE); res77 = and64(res77, MASK); storeu64(out_mb + MB_WIDTH * 77, res77); res78 = add64(res78, T); res78 = and64(res78, MASK); storeu64(out_mb + MB_WIDTH * 78, res78); } } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams52x10_diagonal_mb8.c000066400000000000000000000450361470420105600345020ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void AMS52x10_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res0, res1, res2, res3, res4, res5, res6, res7, res8, res9, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; U64 k = loadu64((U64 *)k0_mb); res0 = res1 = res2 = res3 = res4 = res5 = res6 = res7 = res8 = res9 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = get_zero64(); res1 = fma52lo(res1, a[0], a[1]); // Sum(1) res2 = fma52hi(res2, a[0], a[1]); // Sum(1) res2 = fma52lo(res2, a[0], a[2]); // Sum(2) res3 = fma52hi(res3, a[0], a[2]); // Sum(2) res3 = fma52lo(res3, a[1], a[2]); // Sum(3) res4 = fma52hi(res4, a[1], a[2]); // Sum(3) res3 = fma52lo(res3, a[0], a[3]); // Sum(3) res4 = fma52hi(res4, a[0], a[3]); // Sum(3) res4 = fma52lo(res4, a[1], a[3]); // Sum(4) res5 = fma52hi(res5, a[1], a[3]); // Sum(4) res5 = fma52lo(res5, a[2], a[3]); // Sum(5) res6 = fma52hi(res6, a[2], a[3]); // Sum(5) res4 = fma52lo(res4, a[0], a[4]); // Sum(4) res5 = fma52hi(res5, a[0], a[4]); // Sum(4) res5 = fma52lo(res5, a[1], a[4]); // Sum(5) res6 = fma52hi(res6, a[1], a[4]); // Sum(5) res6 = fma52lo(res6, a[2], a[4]); // Sum(6) res7 = fma52hi(res7, a[2], a[4]); // Sum(6) res7 = fma52lo(res7, a[3], a[4]); // Sum(7) res8 = fma52hi(res8, a[3], a[4]); // Sum(7) res5 = fma52lo(res5, a[0], a[5]); // Sum(5) res6 = fma52hi(res6, a[0], a[5]); // Sum(5) res6 = fma52lo(res6, a[1], a[5]); // Sum(6) res7 = fma52hi(res7, a[1], a[5]); // Sum(6) res7 = fma52lo(res7, a[2], a[5]); // Sum(7) res8 = fma52hi(res8, a[2], a[5]); // Sum(7) res8 = fma52lo(res8, a[3], a[5]); // Sum(8) res9 = fma52hi(res9, a[3], a[5]); // Sum(8) res9 = fma52lo(res9, a[4], a[5]); // Sum(9) res10 = fma52hi(res10, a[4], a[5]); // Sum(9) res6 = fma52lo(res6, a[0], a[6]); // Sum(6) res7 = fma52hi(res7, a[0], a[6]); // Sum(6) res7 = fma52lo(res7, a[1], a[6]); // Sum(7) res8 = fma52hi(res8, a[1], a[6]); // Sum(7) res8 = fma52lo(res8, a[2], a[6]); // Sum(8) res9 = fma52hi(res9, a[2], a[6]); // Sum(8) res9 = fma52lo(res9, a[3], a[6]); // Sum(9) res10 = fma52hi(res10, a[3], a[6]); // Sum(9) res10 = fma52lo(res10, a[4], a[6]); // Sum(10) res11 = fma52hi(res11, a[4], a[6]); // Sum(10) res11 = fma52lo(res11, a[5], a[6]); // Sum(11) res12 = fma52hi(res12, a[5], a[6]); // Sum(11) res7 = fma52lo(res7, a[0], a[7]); // Sum(7) res8 = fma52hi(res8, a[0], a[7]); // Sum(7) res8 = fma52lo(res8, a[1], a[7]); // Sum(8) res9 = fma52hi(res9, a[1], a[7]); // Sum(8) res9 = fma52lo(res9, a[2], a[7]); // Sum(9) res10 = fma52hi(res10, a[2], a[7]); // Sum(9) res10 = fma52lo(res10, a[3], a[7]); // Sum(10) res11 = fma52hi(res11, a[3], a[7]); // Sum(10) res11 = fma52lo(res11, a[4], a[7]); // Sum(11) res12 = fma52hi(res12, a[4], a[7]); // Sum(11) res8 = fma52lo(res8, a[0], a[8]); // Sum(8) res9 = fma52hi(res9, a[0], a[8]); // Sum(8) res9 = fma52lo(res9, a[1], a[8]); // Sum(9) res10 = fma52hi(res10, a[1], a[8]); // Sum(9) res10 = fma52lo(res10, a[2], a[8]); // Sum(10) res11 = fma52hi(res11, a[2], a[8]); // Sum(10) res11 = fma52lo(res11, a[3], a[8]); // Sum(11) res12 = fma52hi(res12, a[3], a[8]); // Sum(11) res9 = fma52lo(res9, a[0], a[9]); // Sum(9) res10 = fma52hi(res10, a[0], a[9]); // Sum(9) res10 = fma52lo(res10, a[1], a[9]); // Sum(10) res11 = fma52hi(res11, a[1], a[9]); // Sum(10) res11 = fma52lo(res11, a[2], a[9]); // Sum(11) res12 = fma52hi(res12, a[2], a[9]); // Sum(11) res0 = add64(res0, res0); // Double(0) res1 = add64(res1, res1); // Double(1) res2 = add64(res2, res2); // Double(2) res3 = add64(res3, res3); // Double(3) res4 = add64(res4, res4); // Double(4) res5 = add64(res5, res5); // Double(5) res6 = add64(res6, res6); // Double(6) res7 = add64(res7, res7); // Double(7) res8 = add64(res8, res8); // Double(8) res9 = add64(res9, res9); // Double(9) res10 = add64(res10, res10); // Double(10) res11 = add64(res11, res11); // Double(11) res0 = fma52lo(res0, a[0], a[0]); // Add sqr(0) res1 = fma52hi(res1, a[0], a[0]); // Add sqr(0) res2 = fma52lo(res2, a[1], a[1]); // Add sqr(2) res3 = fma52hi(res3, a[1], a[1]); // Add sqr(2) res4 = fma52lo(res4, a[2], a[2]); // Add sqr(4) res5 = fma52hi(res5, a[2], a[2]); // Add sqr(4) res6 = fma52lo(res6, a[3], a[3]); // Add sqr(6) res7 = fma52hi(res7, a[3], a[3]); // Add sqr(6) res8 = fma52lo(res8, a[4], a[4]); // Add sqr(8) res9 = fma52hi(res9, a[4], a[4]); // Add sqr(8) res10 = fma52lo(res10, a[5], a[5]); // Add sqr(10) res11 = fma52hi(res11, a[5], a[5]); // Add sqr(10) res12 = fma52lo(res12, a[5], a[7]); // Sum(12) res13 = fma52hi(res13, a[5], a[7]); // Sum(12) res13 = fma52lo(res13, a[6], a[7]); // Sum(13) res14 = fma52hi(res14, a[6], a[7]); // Sum(13) res12 = fma52lo(res12, a[4], a[8]); // Sum(12) res13 = fma52hi(res13, a[4], a[8]); // Sum(12) res13 = fma52lo(res13, a[5], a[8]); // Sum(13) res14 = fma52hi(res14, a[5], a[8]); // Sum(13) res14 = fma52lo(res14, a[6], a[8]); // Sum(14) res15 = fma52hi(res15, a[6], a[8]); // Sum(14) res15 = fma52lo(res15, a[7], a[8]); // Sum(15) res16 = fma52hi(res16, a[7], a[8]); // Sum(15) res12 = fma52lo(res12, a[3], a[9]); // Sum(12) res13 = fma52hi(res13, a[3], a[9]); // Sum(12) res13 = fma52lo(res13, a[4], a[9]); // Sum(13) res14 = fma52hi(res14, a[4], a[9]); // Sum(13) res14 = fma52lo(res14, a[5], a[9]); // Sum(14) res15 = fma52hi(res15, a[5], a[9]); // Sum(14) res15 = fma52lo(res15, a[6], a[9]); // Sum(15) res16 = fma52hi(res16, a[6], a[9]); // Sum(15) res16 = fma52lo(res16, a[7], a[9]); // Sum(16) res17 = fma52hi(res17, a[7], a[9]); // Sum(16) res17 = fma52lo(res17, a[8], a[9]); // Sum(17) res18 = fma52hi(res18, a[8], a[9]); // Sum(17) res12 = add64(res12, res12); // Double(12) res13 = add64(res13, res13); // Double(13) res14 = add64(res14, res14); // Double(14) res15 = add64(res15, res15); // Double(15) res16 = add64(res16, res16); // Double(16) res17 = add64(res17, res17); // Double(17) res18 = add64(res18, res18); // Double(18) res12 = fma52lo(res12, a[6], a[6]); // Add sqr(12) res13 = fma52hi(res13, a[6], a[6]); // Add sqr(12) res14 = fma52lo(res14, a[7], a[7]); // Add sqr(14) res15 = fma52hi(res15, a[7], a[7]); // Add sqr(14) res16 = fma52lo(res16, a[8], a[8]); // Add sqr(16) res17 = fma52hi(res17, a[8], a[8]); // Add sqr(16) res18 = fma52lo(res18, a[9], a[9]); // Add sqr(18) res19 = fma52hi(res19, a[9], a[9]); // Add sqr(18) // Generate u_i U64 u0 = mul52lo(res0, k); ASM("jmp l0\nl0:\n"); // Create u0 fma52lo_mem(res0, res0, u0, m, SIMD_BYTES * 0); fma52hi_mem(res1, res1, u0, m, SIMD_BYTES * 0); res1 = fma52lo(res1, u0, m[1]); res2 = fma52hi(res2, u0, m[1]); res1 = add64(res1, srli64(res0, DIGIT_SIZE)); U64 u1 = mul52lo(res1, k); fma52lo_mem(res2, res2, u0, m, SIMD_BYTES * 2); fma52hi_mem(res3, res3, u0, m, SIMD_BYTES * 2); res3 = fma52lo(res3, u0, m[3]); res4 = fma52hi(res4, u0, m[3]); fma52lo_mem(res4, res4, u0, m, SIMD_BYTES * 4); fma52hi_mem(res5, res5, u0, m, SIMD_BYTES * 4); res5 = fma52lo(res5, u0, m[5]); res6 = fma52hi(res6, u0, m[5]); fma52lo_mem(res6, res6, u0, m, SIMD_BYTES * 6); fma52hi_mem(res7, res7, u0, m, SIMD_BYTES * 6); res7 = fma52lo(res7, u0, m[7]); res8 = fma52hi(res8, u0, m[7]); fma52lo_mem(res8, res8, u0, m, SIMD_BYTES * 8); fma52hi_mem(res9, res9, u0, m, SIMD_BYTES * 8); res9 = fma52lo(res9, u0, m[9]); res10 = fma52hi(res10, u0, m[9]); // Create u1 fma52lo_mem(res1, res1, u1, m, SIMD_BYTES * 0); fma52hi_mem(res2, res2, u1, m, SIMD_BYTES * 0); res2 = fma52lo(res2, u1, m[1]); res3 = fma52hi(res3, u1, m[1]); res2 = add64(res2, srli64(res1, DIGIT_SIZE)); U64 u2 = mul52lo(res2, k); fma52lo_mem(res3, res3, u1, m, SIMD_BYTES * 2); fma52hi_mem(res4, res4, u1, m, SIMD_BYTES * 2); res4 = fma52lo(res4, u1, m[3]); res5 = fma52hi(res5, u1, m[3]); fma52lo_mem(res5, res5, u1, m, SIMD_BYTES * 4); fma52hi_mem(res6, res6, u1, m, SIMD_BYTES * 4); res6 = fma52lo(res6, u1, m[5]); res7 = fma52hi(res7, u1, m[5]); fma52lo_mem(res7, res7, u1, m, SIMD_BYTES * 6); fma52hi_mem(res8, res8, u1, m, SIMD_BYTES * 6); res8 = fma52lo(res8, u1, m[7]); res9 = fma52hi(res9, u1, m[7]); fma52lo_mem(res9, res9, u1, m, SIMD_BYTES * 8); fma52hi_mem(res10, res10, u1, m, SIMD_BYTES * 8); res10 = fma52lo(res10, u1, m[9]); res11 = fma52hi(res11, u1, m[9]); ASM("jmp l2\nl2:\n"); // Create u2 fma52lo_mem(res2, res2, u2, m, SIMD_BYTES * 0); fma52hi_mem(res3, res3, u2, m, SIMD_BYTES * 0); res3 = fma52lo(res3, u2, m[1]); res4 = fma52hi(res4, u2, m[1]); res3 = add64(res3, srli64(res2, DIGIT_SIZE)); U64 u3 = mul52lo(res3, k); fma52lo_mem(res4, res4, u2, m, SIMD_BYTES * 2); fma52hi_mem(res5, res5, u2, m, SIMD_BYTES * 2); res5 = fma52lo(res5, u2, m[3]); res6 = fma52hi(res6, u2, m[3]); fma52lo_mem(res6, res6, u2, m, SIMD_BYTES * 4); fma52hi_mem(res7, res7, u2, m, SIMD_BYTES * 4); res7 = fma52lo(res7, u2, m[5]); res8 = fma52hi(res8, u2, m[5]); fma52lo_mem(res8, res8, u2, m, SIMD_BYTES * 6); fma52hi_mem(res9, res9, u2, m, SIMD_BYTES * 6); res9 = fma52lo(res9, u2, m[7]); res10 = fma52hi(res10, u2, m[7]); fma52lo_mem(res10, res10, u2, m, SIMD_BYTES * 8); fma52hi_mem(res11, res11, u2, m, SIMD_BYTES * 8); res11 = fma52lo(res11, u2, m[9]); res12 = fma52hi(res12, u2, m[9]); // Create u3 fma52lo_mem(res3, res3, u3, m, SIMD_BYTES * 0); fma52hi_mem(res4, res4, u3, m, SIMD_BYTES * 0); res4 = fma52lo(res4, u3, m[1]); res5 = fma52hi(res5, u3, m[1]); res4 = add64(res4, srli64(res3, DIGIT_SIZE)); U64 u4 = mul52lo(res4, k); fma52lo_mem(res5, res5, u3, m, SIMD_BYTES * 2); fma52hi_mem(res6, res6, u3, m, SIMD_BYTES * 2); res6 = fma52lo(res6, u3, m[3]); res7 = fma52hi(res7, u3, m[3]); fma52lo_mem(res7, res7, u3, m, SIMD_BYTES * 4); fma52hi_mem(res8, res8, u3, m, SIMD_BYTES * 4); res8 = fma52lo(res8, u3, m[5]); res9 = fma52hi(res9, u3, m[5]); fma52lo_mem(res9, res9, u3, m, SIMD_BYTES * 6); fma52hi_mem(res10, res10, u3, m, SIMD_BYTES * 6); res10 = fma52lo(res10, u3, m[7]); res11 = fma52hi(res11, u3, m[7]); fma52lo_mem(res11, res11, u3, m, SIMD_BYTES * 8); fma52hi_mem(res12, res12, u3, m, SIMD_BYTES * 8); res12 = fma52lo(res12, u3, m[9]); res13 = fma52hi(res13, u3, m[9]); ASM("jmp l4\nl4:\n"); // Create u4 fma52lo_mem(res4, res4, u4, m, SIMD_BYTES * 0); fma52hi_mem(res5, res5, u4, m, SIMD_BYTES * 0); res5 = fma52lo(res5, u4, m[1]); res6 = fma52hi(res6, u4, m[1]); res5 = add64(res5, srli64(res4, DIGIT_SIZE)); U64 u5 = mul52lo(res5, k); fma52lo_mem(res6, res6, u4, m, SIMD_BYTES * 2); fma52hi_mem(res7, res7, u4, m, SIMD_BYTES * 2); res7 = fma52lo(res7, u4, m[3]); res8 = fma52hi(res8, u4, m[3]); fma52lo_mem(res8, res8, u4, m, SIMD_BYTES * 4); fma52hi_mem(res9, res9, u4, m, SIMD_BYTES * 4); res9 = fma52lo(res9, u4, m[5]); res10 = fma52hi(res10, u4, m[5]); fma52lo_mem(res10, res10, u4, m, SIMD_BYTES * 6); fma52hi_mem(res11, res11, u4, m, SIMD_BYTES * 6); res11 = fma52lo(res11, u4, m[7]); res12 = fma52hi(res12, u4, m[7]); fma52lo_mem(res12, res12, u4, m, SIMD_BYTES * 8); fma52hi_mem(res13, res13, u4, m, SIMD_BYTES * 8); res13 = fma52lo(res13, u4, m[9]); res14 = fma52hi(res14, u4, m[9]); // Create u5 fma52lo_mem(res5, res5, u5, m, SIMD_BYTES * 0); fma52hi_mem(res6, res6, u5, m, SIMD_BYTES * 0); res6 = fma52lo(res6, u5, m[1]); res7 = fma52hi(res7, u5, m[1]); res6 = add64(res6, srli64(res5, DIGIT_SIZE)); U64 u6 = mul52lo(res6, k); fma52lo_mem(res7, res7, u5, m, SIMD_BYTES * 2); fma52hi_mem(res8, res8, u5, m, SIMD_BYTES * 2); res8 = fma52lo(res8, u5, m[3]); res9 = fma52hi(res9, u5, m[3]); fma52lo_mem(res9, res9, u5, m, SIMD_BYTES * 4); fma52hi_mem(res10, res10, u5, m, SIMD_BYTES * 4); res10 = fma52lo(res10, u5, m[5]); res11 = fma52hi(res11, u5, m[5]); fma52lo_mem(res11, res11, u5, m, SIMD_BYTES * 6); fma52hi_mem(res12, res12, u5, m, SIMD_BYTES * 6); res12 = fma52lo(res12, u5, m[7]); res13 = fma52hi(res13, u5, m[7]); fma52lo_mem(res13, res13, u5, m, SIMD_BYTES * 8); fma52hi_mem(res14, res14, u5, m, SIMD_BYTES * 8); res14 = fma52lo(res14, u5, m[9]); res15 = fma52hi(res15, u5, m[9]); ASM("jmp l6\nl6:\n"); // Create u6 fma52lo_mem(res6, res6, u6, m, SIMD_BYTES * 0); fma52hi_mem(res7, res7, u6, m, SIMD_BYTES * 0); res7 = fma52lo(res7, u6, m[1]); res8 = fma52hi(res8, u6, m[1]); res7 = add64(res7, srli64(res6, DIGIT_SIZE)); U64 u7 = mul52lo(res7, k); fma52lo_mem(res8, res8, u6, m, SIMD_BYTES * 2); fma52hi_mem(res9, res9, u6, m, SIMD_BYTES * 2); res9 = fma52lo(res9, u6, m[3]); res10 = fma52hi(res10, u6, m[3]); fma52lo_mem(res10, res10, u6, m, SIMD_BYTES * 4); fma52hi_mem(res11, res11, u6, m, SIMD_BYTES * 4); res11 = fma52lo(res11, u6, m[5]); res12 = fma52hi(res12, u6, m[5]); fma52lo_mem(res12, res12, u6, m, SIMD_BYTES * 6); fma52hi_mem(res13, res13, u6, m, SIMD_BYTES * 6); res13 = fma52lo(res13, u6, m[7]); res14 = fma52hi(res14, u6, m[7]); fma52lo_mem(res14, res14, u6, m, SIMD_BYTES * 8); fma52hi_mem(res15, res15, u6, m, SIMD_BYTES * 8); res15 = fma52lo(res15, u6, m[9]); res16 = fma52hi(res16, u6, m[9]); // Create u7 fma52lo_mem(res7, res7, u7, m, SIMD_BYTES * 0); fma52hi_mem(res8, res8, u7, m, SIMD_BYTES * 0); res8 = fma52lo(res8, u7, m[1]); res9 = fma52hi(res9, u7, m[1]); res8 = add64(res8, srli64(res7, DIGIT_SIZE)); U64 u8 = mul52lo(res8, k); fma52lo_mem(res9, res9, u7, m, SIMD_BYTES * 2); fma52hi_mem(res10, res10, u7, m, SIMD_BYTES * 2); res10 = fma52lo(res10, u7, m[3]); res11 = fma52hi(res11, u7, m[3]); fma52lo_mem(res11, res11, u7, m, SIMD_BYTES * 4); fma52hi_mem(res12, res12, u7, m, SIMD_BYTES * 4); res12 = fma52lo(res12, u7, m[5]); res13 = fma52hi(res13, u7, m[5]); fma52lo_mem(res13, res13, u7, m, SIMD_BYTES * 6); fma52hi_mem(res14, res14, u7, m, SIMD_BYTES * 6); res14 = fma52lo(res14, u7, m[7]); res15 = fma52hi(res15, u7, m[7]); fma52lo_mem(res15, res15, u7, m, SIMD_BYTES * 8); fma52hi_mem(res16, res16, u7, m, SIMD_BYTES * 8); res16 = fma52lo(res16, u7, m[9]); res17 = fma52hi(res17, u7, m[9]); ASM("jmp l8\nl8:\n"); // Create u8 fma52lo_mem(res8, res8, u8, m, SIMD_BYTES * 0); fma52hi_mem(res9, res9, u8, m, SIMD_BYTES * 0); res9 = fma52lo(res9, u8, m[1]); res10 = fma52hi(res10, u8, m[1]); res9 = add64(res9, srli64(res8, DIGIT_SIZE)); U64 u9 = mul52lo(res9, k); fma52lo_mem(res10, res10, u8, m, SIMD_BYTES * 2); fma52hi_mem(res11, res11, u8, m, SIMD_BYTES * 2); res11 = fma52lo(res11, u8, m[3]); res12 = fma52hi(res12, u8, m[3]); fma52lo_mem(res12, res12, u8, m, SIMD_BYTES * 4); fma52hi_mem(res13, res13, u8, m, SIMD_BYTES * 4); res13 = fma52lo(res13, u8, m[5]); res14 = fma52hi(res14, u8, m[5]); fma52lo_mem(res14, res14, u8, m, SIMD_BYTES * 6); fma52hi_mem(res15, res15, u8, m, SIMD_BYTES * 6); res15 = fma52lo(res15, u8, m[7]); res16 = fma52hi(res16, u8, m[7]); fma52lo_mem(res16, res16, u8, m, SIMD_BYTES * 8); fma52hi_mem(res17, res17, u8, m, SIMD_BYTES * 8); res17 = fma52lo(res17, u8, m[9]); res18 = fma52hi(res18, u8, m[9]); // Create u9 fma52lo_mem(res9, res9, u9, m, SIMD_BYTES * 0); fma52hi_mem(res10, res10, u9, m, SIMD_BYTES * 0); res10 = fma52lo(res10, u9, m[1]); res11 = fma52hi(res11, u9, m[1]); res10 = add64(res10, srli64(res9, DIGIT_SIZE)); fma52lo_mem(res11, res11, u9, m, SIMD_BYTES * 2); fma52hi_mem(res12, res12, u9, m, SIMD_BYTES * 2); res12 = fma52lo(res12, u9, m[3]); res13 = fma52hi(res13, u9, m[3]); fma52lo_mem(res13, res13, u9, m, SIMD_BYTES * 4); fma52hi_mem(res14, res14, u9, m, SIMD_BYTES * 4); res14 = fma52lo(res14, u9, m[5]); res15 = fma52hi(res15, u9, m[5]); fma52lo_mem(res15, res15, u9, m, SIMD_BYTES * 6); fma52hi_mem(res16, res16, u9, m, SIMD_BYTES * 6); res16 = fma52lo(res16, u9, m[7]); res17 = fma52hi(res17, u9, m[7]); fma52lo_mem(res17, res17, u9, m, SIMD_BYTES * 8); fma52hi_mem(res18, res18, u9, m, SIMD_BYTES * 8); res18 = fma52lo(res18, u9, m[9]); res19 = fma52hi(res19, u9, m[9]); // Normalization r[0] = and64_const(res10, DIGIT_MASK); res11 = add64(res11, srli64(res10, DIGIT_SIZE)); r[1] = and64_const(res11, DIGIT_MASK); res12 = add64(res12, srli64(res11, DIGIT_SIZE)); r[2] = and64_const(res12, DIGIT_MASK); res13 = add64(res13, srli64(res12, DIGIT_SIZE)); r[3] = and64_const(res13, DIGIT_MASK); res14 = add64(res14, srli64(res13, DIGIT_SIZE)); r[4] = and64_const(res14, DIGIT_MASK); res15 = add64(res15, srli64(res14, DIGIT_SIZE)); r[5] = and64_const(res15, DIGIT_MASK); res16 = add64(res16, srli64(res15, DIGIT_SIZE)); r[6] = and64_const(res16, DIGIT_MASK); res17 = add64(res17, srli64(res16, DIGIT_SIZE)); r[7] = and64_const(res17, DIGIT_MASK); res18 = add64(res18, srli64(res17, DIGIT_SIZE)); r[8] = and64_const(res18, DIGIT_MASK); res19 = add64(res19, srli64(res18, DIGIT_SIZE)); r[9] = and64_const(res19, DIGIT_MASK); } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams52x20_diagonal_mb8.c000066400000000000000000002307401470420105600345010ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 /* For squaring, an optimized approach is utilized. As an example, suppose we are multiplying two 4-digit numbers: | a3 | a2 | a1 | a0 | | b3 | b2 | b1 | b0 | X______________________ | a3 * b3 | a2 * b2 | a1 * b1 | a0 * b0 | | a3 * b2 | a2 * b1 | a1 * b0 | | a2 * b3 | a1 * b2 | a0 * b1 | | a3 * b1 | a2 * b0 | | a1 * b3 | a0 * b2 | | a3 * b0 | | a0 * b3 | This operation is realized with 4x4=16 digit-wise multiplications. When a=b (for squaring), multiplication operation is optimizes as follows: | a3 | a2 | a1 | a0 | | a3 | a2 | a1 | a0 | X______________________ | a3 * a3 | a2 * a2 | a1 * a1 | a0 * a0 | 2* | a3 * a2 | a2 * a1 | a1 * a0 | 2* | a3 * a1 | a2 * a0 | 2* | a3 * a0 | This operation is realized with 10 digit-wise multiplications. For an n-digit squaring operation, (n^2-n)/2 less digit-wise multiplications are required. The number of digit-wise multiplications for n-digit squaring can be calculated with the following equation: n^2 - (n^2-n)/2 multiplication by 2 operations are realized with add64 instructions. */ #if (_MBX >= _MBX_K1) #include void AMS52x20_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res0, res1, res2, res3, res4, res5, res6, res7, res8, res9, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29, res30, res31, res32, res33, res34, res35, res36, res37, res38, res39; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; U64 k = loadu64((U64 *)k0_mb); res0 = res1 = res2 = res3 = res4 = res5 = res6 = res7 = res8 = res9 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = res30 = res31 = res32 = res33 = res34 = res35 = res36 = res37 = res38 = res39 = get_zero64(); res1 = fma52lo(res1, a[0], a[1]); // Sum(1) res2 = fma52hi(res2, a[0], a[1]); // Sum(1) res2 = fma52lo(res2, a[0], a[2]); // Sum(2) res3 = fma52hi(res3, a[0], a[2]); // Sum(2) res3 = fma52lo(res3, a[1], a[2]); // Sum(3) res4 = fma52hi(res4, a[1], a[2]); // Sum(3) res3 = fma52lo(res3, a[0], a[3]); // Sum(3) res4 = fma52hi(res4, a[0], a[3]); // Sum(3) res4 = fma52lo(res4, a[1], a[3]); // Sum(4) res5 = fma52hi(res5, a[1], a[3]); // Sum(4) res5 = fma52lo(res5, a[2], a[3]); // Sum(5) res6 = fma52hi(res6, a[2], a[3]); // Sum(5) res4 = fma52lo(res4, a[0], a[4]); // Sum(4) res5 = fma52hi(res5, a[0], a[4]); // Sum(4) res5 = fma52lo(res5, a[1], a[4]); // Sum(5) res6 = fma52hi(res6, a[1], a[4]); // Sum(5) res6 = fma52lo(res6, a[2], a[4]); // Sum(6) res7 = fma52hi(res7, a[2], a[4]); // Sum(6) res7 = fma52lo(res7, a[3], a[4]); // Sum(7) res8 = fma52hi(res8, a[3], a[4]); // Sum(7) res5 = fma52lo(res5, a[0], a[5]); // Sum(5) res6 = fma52hi(res6, a[0], a[5]); // Sum(5) res6 = fma52lo(res6, a[1], a[5]); // Sum(6) res7 = fma52hi(res7, a[1], a[5]); // Sum(6) res7 = fma52lo(res7, a[2], a[5]); // Sum(7) res8 = fma52hi(res8, a[2], a[5]); // Sum(7) res8 = fma52lo(res8, a[3], a[5]); // Sum(8) res9 = fma52hi(res9, a[3], a[5]); // Sum(8) res9 = fma52lo(res9, a[4], a[5]); // Sum(9) res10 = fma52hi(res10, a[4], a[5]); // Sum(9) res6 = fma52lo(res6, a[0], a[6]); // Sum(6) res7 = fma52hi(res7, a[0], a[6]); // Sum(6) res7 = fma52lo(res7, a[1], a[6]); // Sum(7) res8 = fma52hi(res8, a[1], a[6]); // Sum(7) res8 = fma52lo(res8, a[2], a[6]); // Sum(8) res9 = fma52hi(res9, a[2], a[6]); // Sum(8) res9 = fma52lo(res9, a[3], a[6]); // Sum(9) res10 = fma52hi(res10, a[3], a[6]); // Sum(9) res10 = fma52lo(res10, a[4], a[6]); // Sum(10) res11 = fma52hi(res11, a[4], a[6]); // Sum(10) res11 = fma52lo(res11, a[5], a[6]); // Sum(11) res12 = fma52hi(res12, a[5], a[6]); // Sum(11) res7 = fma52lo(res7, a[0], a[7]); // Sum(7) res8 = fma52hi(res8, a[0], a[7]); // Sum(7) res8 = fma52lo(res8, a[1], a[7]); // Sum(8) res9 = fma52hi(res9, a[1], a[7]); // Sum(8) res9 = fma52lo(res9, a[2], a[7]); // Sum(9) res10 = fma52hi(res10, a[2], a[7]); // Sum(9) res10 = fma52lo(res10, a[3], a[7]); // Sum(10) res11 = fma52hi(res11, a[3], a[7]); // Sum(10) res11 = fma52lo(res11, a[4], a[7]); // Sum(11) res12 = fma52hi(res12, a[4], a[7]); // Sum(11) res8 = fma52lo(res8, a[0], a[8]); // Sum(8) res9 = fma52hi(res9, a[0], a[8]); // Sum(8) res9 = fma52lo(res9, a[1], a[8]); // Sum(9) res10 = fma52hi(res10, a[1], a[8]); // Sum(9) res10 = fma52lo(res10, a[2], a[8]); // Sum(10) res11 = fma52hi(res11, a[2], a[8]); // Sum(10) res11 = fma52lo(res11, a[3], a[8]); // Sum(11) res12 = fma52hi(res12, a[3], a[8]); // Sum(11) res9 = fma52lo(res9, a[0], a[9]); // Sum(9) res10 = fma52hi(res10, a[0], a[9]); // Sum(9) res10 = fma52lo(res10, a[1], a[9]); // Sum(10) res11 = fma52hi(res11, a[1], a[9]); // Sum(10) res11 = fma52lo(res11, a[2], a[9]); // Sum(11) res12 = fma52hi(res12, a[2], a[9]); // Sum(11) res10 = fma52lo(res10, a[0], a[10]); // Sum(10) res11 = fma52hi(res11, a[0], a[10]); // Sum(10) res11 = fma52lo(res11, a[1], a[10]); // Sum(11) res12 = fma52hi(res12, a[1], a[10]); // Sum(11) res11 = fma52lo(res11, a[0], a[11]); // Sum(11) res12 = fma52hi(res12, a[0], a[11]); // Sum(11) res0 = add64(res0, res0); // Double(0) res1 = add64(res1, res1); // Double(1) res2 = add64(res2, res2); // Double(2) res3 = add64(res3, res3); // Double(3) res4 = add64(res4, res4); // Double(4) res5 = add64(res5, res5); // Double(5) res6 = add64(res6, res6); // Double(6) res7 = add64(res7, res7); // Double(7) res8 = add64(res8, res8); // Double(8) res9 = add64(res9, res9); // Double(9) res10 = add64(res10, res10); // Double(10) res11 = add64(res11, res11); // Double(11) res0 = fma52lo(res0, a[0], a[0]); // Add sqr(0) res1 = fma52hi(res1, a[0], a[0]); // Add sqr(0) res2 = fma52lo(res2, a[1], a[1]); // Add sqr(2) res3 = fma52hi(res3, a[1], a[1]); // Add sqr(2) res4 = fma52lo(res4, a[2], a[2]); // Add sqr(4) res5 = fma52hi(res5, a[2], a[2]); // Add sqr(4) res6 = fma52lo(res6, a[3], a[3]); // Add sqr(6) res7 = fma52hi(res7, a[3], a[3]); // Add sqr(6) res8 = fma52lo(res8, a[4], a[4]); // Add sqr(8) res9 = fma52hi(res9, a[4], a[4]); // Add sqr(8) res10 = fma52lo(res10, a[5], a[5]); // Add sqr(10) res11 = fma52hi(res11, a[5], a[5]); // Add sqr(10) res12 = fma52lo(res12, a[5], a[7]); // Sum(12) res13 = fma52hi(res13, a[5], a[7]); // Sum(12) res13 = fma52lo(res13, a[6], a[7]); // Sum(13) res14 = fma52hi(res14, a[6], a[7]); // Sum(13) res12 = fma52lo(res12, a[4], a[8]); // Sum(12) res13 = fma52hi(res13, a[4], a[8]); // Sum(12) res13 = fma52lo(res13, a[5], a[8]); // Sum(13) res14 = fma52hi(res14, a[5], a[8]); // Sum(13) res14 = fma52lo(res14, a[6], a[8]); // Sum(14) res15 = fma52hi(res15, a[6], a[8]); // Sum(14) res15 = fma52lo(res15, a[7], a[8]); // Sum(15) res16 = fma52hi(res16, a[7], a[8]); // Sum(15) res12 = fma52lo(res12, a[3], a[9]); // Sum(12) res13 = fma52hi(res13, a[3], a[9]); // Sum(12) res13 = fma52lo(res13, a[4], a[9]); // Sum(13) res14 = fma52hi(res14, a[4], a[9]); // Sum(13) res14 = fma52lo(res14, a[5], a[9]); // Sum(14) res15 = fma52hi(res15, a[5], a[9]); // Sum(14) res15 = fma52lo(res15, a[6], a[9]); // Sum(15) res16 = fma52hi(res16, a[6], a[9]); // Sum(15) res16 = fma52lo(res16, a[7], a[9]); // Sum(16) res17 = fma52hi(res17, a[7], a[9]); // Sum(16) res17 = fma52lo(res17, a[8], a[9]); // Sum(17) res18 = fma52hi(res18, a[8], a[9]); // Sum(17) res12 = fma52lo(res12, a[2], a[10]); // Sum(12) res13 = fma52hi(res13, a[2], a[10]); // Sum(12) res13 = fma52lo(res13, a[3], a[10]); // Sum(13) res14 = fma52hi(res14, a[3], a[10]); // Sum(13) res14 = fma52lo(res14, a[4], a[10]); // Sum(14) res15 = fma52hi(res15, a[4], a[10]); // Sum(14) res15 = fma52lo(res15, a[5], a[10]); // Sum(15) res16 = fma52hi(res16, a[5], a[10]); // Sum(15) res16 = fma52lo(res16, a[6], a[10]); // Sum(16) res17 = fma52hi(res17, a[6], a[10]); // Sum(16) res17 = fma52lo(res17, a[7], a[10]); // Sum(17) res18 = fma52hi(res18, a[7], a[10]); // Sum(17) res18 = fma52lo(res18, a[8], a[10]); // Sum(18) res19 = fma52hi(res19, a[8], a[10]); // Sum(18) res19 = fma52lo(res19, a[9], a[10]); // Sum(19) res20 = fma52hi(res20, a[9], a[10]); // Sum(19) res12 = fma52lo(res12, a[1], a[11]); // Sum(12) res13 = fma52hi(res13, a[1], a[11]); // Sum(12) res13 = fma52lo(res13, a[2], a[11]); // Sum(13) res14 = fma52hi(res14, a[2], a[11]); // Sum(13) res14 = fma52lo(res14, a[3], a[11]); // Sum(14) res15 = fma52hi(res15, a[3], a[11]); // Sum(14) res15 = fma52lo(res15, a[4], a[11]); // Sum(15) res16 = fma52hi(res16, a[4], a[11]); // Sum(15) res16 = fma52lo(res16, a[5], a[11]); // Sum(16) res17 = fma52hi(res17, a[5], a[11]); // Sum(16) res17 = fma52lo(res17, a[6], a[11]); // Sum(17) res18 = fma52hi(res18, a[6], a[11]); // Sum(17) res18 = fma52lo(res18, a[7], a[11]); // Sum(18) res19 = fma52hi(res19, a[7], a[11]); // Sum(18) res19 = fma52lo(res19, a[8], a[11]); // Sum(19) res20 = fma52hi(res20, a[8], a[11]); // Sum(19) res20 = fma52lo(res20, a[9], a[11]); // Sum(20) res21 = fma52hi(res21, a[9], a[11]); // Sum(20) res21 = fma52lo(res21, a[10], a[11]); // Sum(21) res22 = fma52hi(res22, a[10], a[11]); // Sum(21) res12 = fma52lo(res12, a[0], a[12]); // Sum(12) res13 = fma52hi(res13, a[0], a[12]); // Sum(12) res13 = fma52lo(res13, a[1], a[12]); // Sum(13) res14 = fma52hi(res14, a[1], a[12]); // Sum(13) res14 = fma52lo(res14, a[2], a[12]); // Sum(14) res15 = fma52hi(res15, a[2], a[12]); // Sum(14) res15 = fma52lo(res15, a[3], a[12]); // Sum(15) res16 = fma52hi(res16, a[3], a[12]); // Sum(15) res16 = fma52lo(res16, a[4], a[12]); // Sum(16) res17 = fma52hi(res17, a[4], a[12]); // Sum(16) res17 = fma52lo(res17, a[5], a[12]); // Sum(17) res18 = fma52hi(res18, a[5], a[12]); // Sum(17) res18 = fma52lo(res18, a[6], a[12]); // Sum(18) res19 = fma52hi(res19, a[6], a[12]); // Sum(18) res19 = fma52lo(res19, a[7], a[12]); // Sum(19) res20 = fma52hi(res20, a[7], a[12]); // Sum(19) res20 = fma52lo(res20, a[8], a[12]); // Sum(20) res21 = fma52hi(res21, a[8], a[12]); // Sum(20) res21 = fma52lo(res21, a[9], a[12]); // Sum(21) res22 = fma52hi(res22, a[9], a[12]); // Sum(21) res22 = fma52lo(res22, a[10], a[12]); // Sum(22) res23 = fma52hi(res23, a[10], a[12]); // Sum(22) res23 = fma52lo(res23, a[11], a[12]); // Sum(23) res24 = fma52hi(res24, a[11], a[12]); // Sum(23) res13 = fma52lo(res13, a[0], a[13]); // Sum(13) res14 = fma52hi(res14, a[0], a[13]); // Sum(13) res14 = fma52lo(res14, a[1], a[13]); // Sum(14) res15 = fma52hi(res15, a[1], a[13]); // Sum(14) res15 = fma52lo(res15, a[2], a[13]); // Sum(15) res16 = fma52hi(res16, a[2], a[13]); // Sum(15) res16 = fma52lo(res16, a[3], a[13]); // Sum(16) res17 = fma52hi(res17, a[3], a[13]); // Sum(16) res17 = fma52lo(res17, a[4], a[13]); // Sum(17) res18 = fma52hi(res18, a[4], a[13]); // Sum(17) res18 = fma52lo(res18, a[5], a[13]); // Sum(18) res19 = fma52hi(res19, a[5], a[13]); // Sum(18) res19 = fma52lo(res19, a[6], a[13]); // Sum(19) res20 = fma52hi(res20, a[6], a[13]); // Sum(19) res20 = fma52lo(res20, a[7], a[13]); // Sum(20) res21 = fma52hi(res21, a[7], a[13]); // Sum(20) res21 = fma52lo(res21, a[8], a[13]); // Sum(21) res22 = fma52hi(res22, a[8], a[13]); // Sum(21) res22 = fma52lo(res22, a[9], a[13]); // Sum(22) res23 = fma52hi(res23, a[9], a[13]); // Sum(22) res23 = fma52lo(res23, a[10], a[13]); // Sum(23) res24 = fma52hi(res24, a[10], a[13]); // Sum(23) res14 = fma52lo(res14, a[0], a[14]); // Sum(14) res15 = fma52hi(res15, a[0], a[14]); // Sum(14) res15 = fma52lo(res15, a[1], a[14]); // Sum(15) res16 = fma52hi(res16, a[1], a[14]); // Sum(15) res16 = fma52lo(res16, a[2], a[14]); // Sum(16) res17 = fma52hi(res17, a[2], a[14]); // Sum(16) res17 = fma52lo(res17, a[3], a[14]); // Sum(17) res18 = fma52hi(res18, a[3], a[14]); // Sum(17) res18 = fma52lo(res18, a[4], a[14]); // Sum(18) res19 = fma52hi(res19, a[4], a[14]); // Sum(18) res19 = fma52lo(res19, a[5], a[14]); // Sum(19) res20 = fma52hi(res20, a[5], a[14]); // Sum(19) res20 = fma52lo(res20, a[6], a[14]); // Sum(20) res21 = fma52hi(res21, a[6], a[14]); // Sum(20) res21 = fma52lo(res21, a[7], a[14]); // Sum(21) res22 = fma52hi(res22, a[7], a[14]); // Sum(21) res22 = fma52lo(res22, a[8], a[14]); // Sum(22) res23 = fma52hi(res23, a[8], a[14]); // Sum(22) res23 = fma52lo(res23, a[9], a[14]); // Sum(23) res24 = fma52hi(res24, a[9], a[14]); // Sum(23) res15 = fma52lo(res15, a[0], a[15]); // Sum(15) res16 = fma52hi(res16, a[0], a[15]); // Sum(15) res16 = fma52lo(res16, a[1], a[15]); // Sum(16) res17 = fma52hi(res17, a[1], a[15]); // Sum(16) res17 = fma52lo(res17, a[2], a[15]); // Sum(17) res18 = fma52hi(res18, a[2], a[15]); // Sum(17) res18 = fma52lo(res18, a[3], a[15]); // Sum(18) res19 = fma52hi(res19, a[3], a[15]); // Sum(18) res19 = fma52lo(res19, a[4], a[15]); // Sum(19) res20 = fma52hi(res20, a[4], a[15]); // Sum(19) res20 = fma52lo(res20, a[5], a[15]); // Sum(20) res21 = fma52hi(res21, a[5], a[15]); // Sum(20) res21 = fma52lo(res21, a[6], a[15]); // Sum(21) res22 = fma52hi(res22, a[6], a[15]); // Sum(21) res22 = fma52lo(res22, a[7], a[15]); // Sum(22) res23 = fma52hi(res23, a[7], a[15]); // Sum(22) res23 = fma52lo(res23, a[8], a[15]); // Sum(23) res24 = fma52hi(res24, a[8], a[15]); // Sum(23) res16 = fma52lo(res16, a[0], a[16]); // Sum(16) res17 = fma52hi(res17, a[0], a[16]); // Sum(16) res17 = fma52lo(res17, a[1], a[16]); // Sum(17) res18 = fma52hi(res18, a[1], a[16]); // Sum(17) res18 = fma52lo(res18, a[2], a[16]); // Sum(18) res19 = fma52hi(res19, a[2], a[16]); // Sum(18) res19 = fma52lo(res19, a[3], a[16]); // Sum(19) res20 = fma52hi(res20, a[3], a[16]); // Sum(19) res20 = fma52lo(res20, a[4], a[16]); // Sum(20) res21 = fma52hi(res21, a[4], a[16]); // Sum(20) res21 = fma52lo(res21, a[5], a[16]); // Sum(21) res22 = fma52hi(res22, a[5], a[16]); // Sum(21) res22 = fma52lo(res22, a[6], a[16]); // Sum(22) res23 = fma52hi(res23, a[6], a[16]); // Sum(22) res23 = fma52lo(res23, a[7], a[16]); // Sum(23) res24 = fma52hi(res24, a[7], a[16]); // Sum(23) res17 = fma52lo(res17, a[0], a[17]); // Sum(17) res18 = fma52hi(res18, a[0], a[17]); // Sum(17) res18 = fma52lo(res18, a[1], a[17]); // Sum(18) res19 = fma52hi(res19, a[1], a[17]); // Sum(18) res19 = fma52lo(res19, a[2], a[17]); // Sum(19) res20 = fma52hi(res20, a[2], a[17]); // Sum(19) res20 = fma52lo(res20, a[3], a[17]); // Sum(20) res21 = fma52hi(res21, a[3], a[17]); // Sum(20) res21 = fma52lo(res21, a[4], a[17]); // Sum(21) res22 = fma52hi(res22, a[4], a[17]); // Sum(21) res22 = fma52lo(res22, a[5], a[17]); // Sum(22) res23 = fma52hi(res23, a[5], a[17]); // Sum(22) res23 = fma52lo(res23, a[6], a[17]); // Sum(23) res24 = fma52hi(res24, a[6], a[17]); // Sum(23) res18 = fma52lo(res18, a[0], a[18]); // Sum(18) res19 = fma52hi(res19, a[0], a[18]); // Sum(18) res19 = fma52lo(res19, a[1], a[18]); // Sum(19) res20 = fma52hi(res20, a[1], a[18]); // Sum(19) res20 = fma52lo(res20, a[2], a[18]); // Sum(20) res21 = fma52hi(res21, a[2], a[18]); // Sum(20) res21 = fma52lo(res21, a[3], a[18]); // Sum(21) res22 = fma52hi(res22, a[3], a[18]); // Sum(21) res22 = fma52lo(res22, a[4], a[18]); // Sum(22) res23 = fma52hi(res23, a[4], a[18]); // Sum(22) res23 = fma52lo(res23, a[5], a[18]); // Sum(23) res24 = fma52hi(res24, a[5], a[18]); // Sum(23) res19 = fma52lo(res19, a[0], a[19]); // Sum(19) res20 = fma52hi(res20, a[0], a[19]); // Sum(19) res20 = fma52lo(res20, a[1], a[19]); // Sum(20) res21 = fma52hi(res21, a[1], a[19]); // Sum(20) res21 = fma52lo(res21, a[2], a[19]); // Sum(21) res22 = fma52hi(res22, a[2], a[19]); // Sum(21) res22 = fma52lo(res22, a[3], a[19]); // Sum(22) res23 = fma52hi(res23, a[3], a[19]); // Sum(22) res23 = fma52lo(res23, a[4], a[19]); // Sum(23) res24 = fma52hi(res24, a[4], a[19]); // Sum(23) res12 = add64(res12, res12); // Double(12) res13 = add64(res13, res13); // Double(13) res14 = add64(res14, res14); // Double(14) res15 = add64(res15, res15); // Double(15) res16 = add64(res16, res16); // Double(16) res17 = add64(res17, res17); // Double(17) res18 = add64(res18, res18); // Double(18) res19 = add64(res19, res19); // Double(19) res20 = add64(res20, res20); // Double(20) res21 = add64(res21, res21); // Double(21) res22 = add64(res22, res22); // Double(22) res23 = add64(res23, res23); // Double(23) res12 = fma52lo(res12, a[6], a[6]); // Add sqr(12) res13 = fma52hi(res13, a[6], a[6]); // Add sqr(12) res14 = fma52lo(res14, a[7], a[7]); // Add sqr(14) res15 = fma52hi(res15, a[7], a[7]); // Add sqr(14) res16 = fma52lo(res16, a[8], a[8]); // Add sqr(16) res17 = fma52hi(res17, a[8], a[8]); // Add sqr(16) res18 = fma52lo(res18, a[9], a[9]); // Add sqr(18) res19 = fma52hi(res19, a[9], a[9]); // Add sqr(18) res20 = fma52lo(res20, a[10], a[10]); // Add sqr(20) res21 = fma52hi(res21, a[10], a[10]); // Add sqr(20) res22 = fma52lo(res22, a[11], a[11]); // Add sqr(22) res23 = fma52hi(res23, a[11], a[11]); // Add sqr(22) res24 = fma52lo(res24, a[11], a[13]); // Sum(24) res25 = fma52hi(res25, a[11], a[13]); // Sum(24) res25 = fma52lo(res25, a[12], a[13]); // Sum(25) res26 = fma52hi(res26, a[12], a[13]); // Sum(25) res24 = fma52lo(res24, a[10], a[14]); // Sum(24) res25 = fma52hi(res25, a[10], a[14]); // Sum(24) res25 = fma52lo(res25, a[11], a[14]); // Sum(25) res26 = fma52hi(res26, a[11], a[14]); // Sum(25) res26 = fma52lo(res26, a[12], a[14]); // Sum(26) res27 = fma52hi(res27, a[12], a[14]); // Sum(26) res27 = fma52lo(res27, a[13], a[14]); // Sum(27) res28 = fma52hi(res28, a[13], a[14]); // Sum(27) res24 = fma52lo(res24, a[9], a[15]); // Sum(24) res25 = fma52hi(res25, a[9], a[15]); // Sum(24) res25 = fma52lo(res25, a[10], a[15]); // Sum(25) res26 = fma52hi(res26, a[10], a[15]); // Sum(25) res26 = fma52lo(res26, a[11], a[15]); // Sum(26) res27 = fma52hi(res27, a[11], a[15]); // Sum(26) res27 = fma52lo(res27, a[12], a[15]); // Sum(27) res28 = fma52hi(res28, a[12], a[15]); // Sum(27) res28 = fma52lo(res28, a[13], a[15]); // Sum(28) res29 = fma52hi(res29, a[13], a[15]); // Sum(28) res29 = fma52lo(res29, a[14], a[15]); // Sum(29) res30 = fma52hi(res30, a[14], a[15]); // Sum(29) res24 = fma52lo(res24, a[8], a[16]); // Sum(24) res25 = fma52hi(res25, a[8], a[16]); // Sum(24) res25 = fma52lo(res25, a[9], a[16]); // Sum(25) res26 = fma52hi(res26, a[9], a[16]); // Sum(25) res26 = fma52lo(res26, a[10], a[16]); // Sum(26) res27 = fma52hi(res27, a[10], a[16]); // Sum(26) res27 = fma52lo(res27, a[11], a[16]); // Sum(27) res28 = fma52hi(res28, a[11], a[16]); // Sum(27) res28 = fma52lo(res28, a[12], a[16]); // Sum(28) res29 = fma52hi(res29, a[12], a[16]); // Sum(28) res29 = fma52lo(res29, a[13], a[16]); // Sum(29) res30 = fma52hi(res30, a[13], a[16]); // Sum(29) res30 = fma52lo(res30, a[14], a[16]); // Sum(30) res31 = fma52hi(res31, a[14], a[16]); // Sum(30) res31 = fma52lo(res31, a[15], a[16]); // Sum(31) res32 = fma52hi(res32, a[15], a[16]); // Sum(31) res24 = fma52lo(res24, a[7], a[17]); // Sum(24) res25 = fma52hi(res25, a[7], a[17]); // Sum(24) res25 = fma52lo(res25, a[8], a[17]); // Sum(25) res26 = fma52hi(res26, a[8], a[17]); // Sum(25) res26 = fma52lo(res26, a[9], a[17]); // Sum(26) res27 = fma52hi(res27, a[9], a[17]); // Sum(26) res27 = fma52lo(res27, a[10], a[17]); // Sum(27) res28 = fma52hi(res28, a[10], a[17]); // Sum(27) res28 = fma52lo(res28, a[11], a[17]); // Sum(28) res29 = fma52hi(res29, a[11], a[17]); // Sum(28) res29 = fma52lo(res29, a[12], a[17]); // Sum(29) res30 = fma52hi(res30, a[12], a[17]); // Sum(29) res30 = fma52lo(res30, a[13], a[17]); // Sum(30) res31 = fma52hi(res31, a[13], a[17]); // Sum(30) res31 = fma52lo(res31, a[14], a[17]); // Sum(31) res32 = fma52hi(res32, a[14], a[17]); // Sum(31) res32 = fma52lo(res32, a[15], a[17]); // Sum(32) res33 = fma52hi(res33, a[15], a[17]); // Sum(32) res33 = fma52lo(res33, a[16], a[17]); // Sum(33) res34 = fma52hi(res34, a[16], a[17]); // Sum(33) res24 = fma52lo(res24, a[6], a[18]); // Sum(24) res25 = fma52hi(res25, a[6], a[18]); // Sum(24) res25 = fma52lo(res25, a[7], a[18]); // Sum(25) res26 = fma52hi(res26, a[7], a[18]); // Sum(25) res26 = fma52lo(res26, a[8], a[18]); // Sum(26) res27 = fma52hi(res27, a[8], a[18]); // Sum(26) res27 = fma52lo(res27, a[9], a[18]); // Sum(27) res28 = fma52hi(res28, a[9], a[18]); // Sum(27) res28 = fma52lo(res28, a[10], a[18]); // Sum(28) res29 = fma52hi(res29, a[10], a[18]); // Sum(28) res29 = fma52lo(res29, a[11], a[18]); // Sum(29) res30 = fma52hi(res30, a[11], a[18]); // Sum(29) res30 = fma52lo(res30, a[12], a[18]); // Sum(30) res31 = fma52hi(res31, a[12], a[18]); // Sum(30) res31 = fma52lo(res31, a[13], a[18]); // Sum(31) res32 = fma52hi(res32, a[13], a[18]); // Sum(31) res32 = fma52lo(res32, a[14], a[18]); // Sum(32) res33 = fma52hi(res33, a[14], a[18]); // Sum(32) res33 = fma52lo(res33, a[15], a[18]); // Sum(33) res34 = fma52hi(res34, a[15], a[18]); // Sum(33) res34 = fma52lo(res34, a[16], a[18]); // Sum(34) res35 = fma52hi(res35, a[16], a[18]); // Sum(34) res35 = fma52lo(res35, a[17], a[18]); // Sum(35) res36 = fma52hi(res36, a[17], a[18]); // Sum(35) res24 = fma52lo(res24, a[5], a[19]); // Sum(24) res25 = fma52hi(res25, a[5], a[19]); // Sum(24) res25 = fma52lo(res25, a[6], a[19]); // Sum(25) res26 = fma52hi(res26, a[6], a[19]); // Sum(25) res26 = fma52lo(res26, a[7], a[19]); // Sum(26) res27 = fma52hi(res27, a[7], a[19]); // Sum(26) res27 = fma52lo(res27, a[8], a[19]); // Sum(27) res28 = fma52hi(res28, a[8], a[19]); // Sum(27) res28 = fma52lo(res28, a[9], a[19]); // Sum(28) res29 = fma52hi(res29, a[9], a[19]); // Sum(28) res29 = fma52lo(res29, a[10], a[19]); // Sum(29) res30 = fma52hi(res30, a[10], a[19]); // Sum(29) res30 = fma52lo(res30, a[11], a[19]); // Sum(30) res31 = fma52hi(res31, a[11], a[19]); // Sum(30) res31 = fma52lo(res31, a[12], a[19]); // Sum(31) res32 = fma52hi(res32, a[12], a[19]); // Sum(31) res32 = fma52lo(res32, a[13], a[19]); // Sum(32) res33 = fma52hi(res33, a[13], a[19]); // Sum(32) res33 = fma52lo(res33, a[14], a[19]); // Sum(33) res34 = fma52hi(res34, a[14], a[19]); // Sum(33) res34 = fma52lo(res34, a[15], a[19]); // Sum(34) res35 = fma52hi(res35, a[15], a[19]); // Sum(34) res35 = fma52lo(res35, a[16], a[19]); // Sum(35) res36 = fma52hi(res36, a[16], a[19]); // Sum(35) res24 = add64(res24, res24); // Double(24) res25 = add64(res25, res25); // Double(25) res26 = add64(res26, res26); // Double(26) res27 = add64(res27, res27); // Double(27) res28 = add64(res28, res28); // Double(28) res29 = add64(res29, res29); // Double(29) res30 = add64(res30, res30); // Double(30) res31 = add64(res31, res31); // Double(31) res32 = add64(res32, res32); // Double(32) res33 = add64(res33, res33); // Double(33) res34 = add64(res34, res34); // Double(34) res35 = add64(res35, res35); // Double(35) res24 = fma52lo(res24, a[12], a[12]); // Add sqr(24) res25 = fma52hi(res25, a[12], a[12]); // Add sqr(24) res26 = fma52lo(res26, a[13], a[13]); // Add sqr(26) res27 = fma52hi(res27, a[13], a[13]); // Add sqr(26) res28 = fma52lo(res28, a[14], a[14]); // Add sqr(28) res29 = fma52hi(res29, a[14], a[14]); // Add sqr(28) res30 = fma52lo(res30, a[15], a[15]); // Add sqr(30) res31 = fma52hi(res31, a[15], a[15]); // Add sqr(30) res32 = fma52lo(res32, a[16], a[16]); // Add sqr(32) res33 = fma52hi(res33, a[16], a[16]); // Add sqr(32) res34 = fma52lo(res34, a[17], a[17]); // Add sqr(34) res35 = fma52hi(res35, a[17], a[17]); // Add sqr(34) res36 = fma52lo(res36, a[17], a[19]); // Sum(36) res37 = fma52hi(res37, a[17], a[19]); // Sum(36) res37 = fma52lo(res37, a[18], a[19]); // Sum(37) res38 = fma52hi(res38, a[18], a[19]); // Sum(37) res36 = add64(res36, res36); // Double(36) res37 = add64(res37, res37); // Double(37) res38 = add64(res38, res38); // Double(38) res36 = fma52lo(res36, a[18], a[18]); // Add sqr(36) res37 = fma52hi(res37, a[18], a[18]); // Add sqr(36) res38 = fma52lo(res38, a[19], a[19]); // Add sqr(38) res39 = fma52hi(res39, a[19], a[19]); // Add sqr(38) // Generate u_i U64 u0 = mul52lo(res0, k); ASM("jmp l0\nl0:\n"); // Create u0 fma52lo_mem(res0, res0, u0, m, SIMD_BYTES * 0); fma52hi_mem(res1, res1, u0, m, SIMD_BYTES * 0); res1 = fma52lo(res1, u0, m[1]); res2 = fma52hi(res2, u0, m[1]); res1 = add64(res1, srli64(res0, DIGIT_SIZE)); U64 u1 = mul52lo(res1, k); fma52lo_mem(res2, res2, u0, m, SIMD_BYTES * 2); fma52hi_mem(res3, res3, u0, m, SIMD_BYTES * 2); res3 = fma52lo(res3, u0, m[3]); res4 = fma52hi(res4, u0, m[3]); fma52lo_mem(res4, res4, u0, m, SIMD_BYTES * 4); fma52hi_mem(res5, res5, u0, m, SIMD_BYTES * 4); res5 = fma52lo(res5, u0, m[5]); res6 = fma52hi(res6, u0, m[5]); fma52lo_mem(res6, res6, u0, m, SIMD_BYTES * 6); fma52hi_mem(res7, res7, u0, m, SIMD_BYTES * 6); res7 = fma52lo(res7, u0, m[7]); res8 = fma52hi(res8, u0, m[7]); fma52lo_mem(res8, res8, u0, m, SIMD_BYTES * 8); fma52hi_mem(res9, res9, u0, m, SIMD_BYTES * 8); res9 = fma52lo(res9, u0, m[9]); res10 = fma52hi(res10, u0, m[9]); fma52lo_mem(res10, res10, u0, m, SIMD_BYTES * 10); fma52hi_mem(res11, res11, u0, m, SIMD_BYTES * 10); res11 = fma52lo(res11, u0, m[11]); res12 = fma52hi(res12, u0, m[11]); fma52lo_mem(res12, res12, u0, m, SIMD_BYTES * 12); fma52hi_mem(res13, res13, u0, m, SIMD_BYTES * 12); res13 = fma52lo(res13, u0, m[13]); res14 = fma52hi(res14, u0, m[13]); fma52lo_mem(res14, res14, u0, m, SIMD_BYTES * 14); fma52hi_mem(res15, res15, u0, m, SIMD_BYTES * 14); res15 = fma52lo(res15, u0, m[15]); res16 = fma52hi(res16, u0, m[15]); fma52lo_mem(res16, res16, u0, m, SIMD_BYTES * 16); fma52hi_mem(res17, res17, u0, m, SIMD_BYTES * 16); res17 = fma52lo(res17, u0, m[17]); res18 = fma52hi(res18, u0, m[17]); fma52lo_mem(res18, res18, u0, m, SIMD_BYTES * 18); fma52hi_mem(res19, res19, u0, m, SIMD_BYTES * 18); res19 = fma52lo(res19, u0, m[19]); res20 = fma52hi(res20, u0, m[19]); // Create u1 fma52lo_mem(res1, res1, u1, m, SIMD_BYTES * 0); fma52hi_mem(res2, res2, u1, m, SIMD_BYTES * 0); res2 = fma52lo(res2, u1, m[1]); res3 = fma52hi(res3, u1, m[1]); res2 = add64(res2, srli64(res1, DIGIT_SIZE)); U64 u2 = mul52lo(res2, k); fma52lo_mem(res3, res3, u1, m, SIMD_BYTES * 2); fma52hi_mem(res4, res4, u1, m, SIMD_BYTES * 2); res4 = fma52lo(res4, u1, m[3]); res5 = fma52hi(res5, u1, m[3]); fma52lo_mem(res5, res5, u1, m, SIMD_BYTES * 4); fma52hi_mem(res6, res6, u1, m, SIMD_BYTES * 4); res6 = fma52lo(res6, u1, m[5]); res7 = fma52hi(res7, u1, m[5]); fma52lo_mem(res7, res7, u1, m, SIMD_BYTES * 6); fma52hi_mem(res8, res8, u1, m, SIMD_BYTES * 6); res8 = fma52lo(res8, u1, m[7]); res9 = fma52hi(res9, u1, m[7]); fma52lo_mem(res9, res9, u1, m, SIMD_BYTES * 8); fma52hi_mem(res10, res10, u1, m, SIMD_BYTES * 8); res10 = fma52lo(res10, u1, m[9]); res11 = fma52hi(res11, u1, m[9]); fma52lo_mem(res11, res11, u1, m, SIMD_BYTES * 10); fma52hi_mem(res12, res12, u1, m, SIMD_BYTES * 10); res12 = fma52lo(res12, u1, m[11]); res13 = fma52hi(res13, u1, m[11]); fma52lo_mem(res13, res13, u1, m, SIMD_BYTES * 12); fma52hi_mem(res14, res14, u1, m, SIMD_BYTES * 12); res14 = fma52lo(res14, u1, m[13]); res15 = fma52hi(res15, u1, m[13]); fma52lo_mem(res15, res15, u1, m, SIMD_BYTES * 14); fma52hi_mem(res16, res16, u1, m, SIMD_BYTES * 14); res16 = fma52lo(res16, u1, m[15]); res17 = fma52hi(res17, u1, m[15]); fma52lo_mem(res17, res17, u1, m, SIMD_BYTES * 16); fma52hi_mem(res18, res18, u1, m, SIMD_BYTES * 16); res18 = fma52lo(res18, u1, m[17]); res19 = fma52hi(res19, u1, m[17]); fma52lo_mem(res19, res19, u1, m, SIMD_BYTES * 18); fma52hi_mem(res20, res20, u1, m, SIMD_BYTES * 18); res20 = fma52lo(res20, u1, m[19]); res21 = fma52hi(res21, u1, m[19]); ASM("jmp l2\nl2:\n"); // Create u2 fma52lo_mem(res2, res2, u2, m, SIMD_BYTES * 0); fma52hi_mem(res3, res3, u2, m, SIMD_BYTES * 0); res3 = fma52lo(res3, u2, m[1]); res4 = fma52hi(res4, u2, m[1]); res3 = add64(res3, srli64(res2, DIGIT_SIZE)); U64 u3 = mul52lo(res3, k); fma52lo_mem(res4, res4, u2, m, SIMD_BYTES * 2); fma52hi_mem(res5, res5, u2, m, SIMD_BYTES * 2); res5 = fma52lo(res5, u2, m[3]); res6 = fma52hi(res6, u2, m[3]); fma52lo_mem(res6, res6, u2, m, SIMD_BYTES * 4); fma52hi_mem(res7, res7, u2, m, SIMD_BYTES * 4); res7 = fma52lo(res7, u2, m[5]); res8 = fma52hi(res8, u2, m[5]); fma52lo_mem(res8, res8, u2, m, SIMD_BYTES * 6); fma52hi_mem(res9, res9, u2, m, SIMD_BYTES * 6); res9 = fma52lo(res9, u2, m[7]); res10 = fma52hi(res10, u2, m[7]); fma52lo_mem(res10, res10, u2, m, SIMD_BYTES * 8); fma52hi_mem(res11, res11, u2, m, SIMD_BYTES * 8); res11 = fma52lo(res11, u2, m[9]); res12 = fma52hi(res12, u2, m[9]); fma52lo_mem(res12, res12, u2, m, SIMD_BYTES * 10); fma52hi_mem(res13, res13, u2, m, SIMD_BYTES * 10); res13 = fma52lo(res13, u2, m[11]); res14 = fma52hi(res14, u2, m[11]); fma52lo_mem(res14, res14, u2, m, SIMD_BYTES * 12); fma52hi_mem(res15, res15, u2, m, SIMD_BYTES * 12); res15 = fma52lo(res15, u2, m[13]); res16 = fma52hi(res16, u2, m[13]); fma52lo_mem(res16, res16, u2, m, SIMD_BYTES * 14); fma52hi_mem(res17, res17, u2, m, SIMD_BYTES * 14); res17 = fma52lo(res17, u2, m[15]); res18 = fma52hi(res18, u2, m[15]); fma52lo_mem(res18, res18, u2, m, SIMD_BYTES * 16); fma52hi_mem(res19, res19, u2, m, SIMD_BYTES * 16); res19 = fma52lo(res19, u2, m[17]); res20 = fma52hi(res20, u2, m[17]); fma52lo_mem(res20, res20, u2, m, SIMD_BYTES * 18); fma52hi_mem(res21, res21, u2, m, SIMD_BYTES * 18); res21 = fma52lo(res21, u2, m[19]); res22 = fma52hi(res22, u2, m[19]); // Create u3 fma52lo_mem(res3, res3, u3, m, SIMD_BYTES * 0); fma52hi_mem(res4, res4, u3, m, SIMD_BYTES * 0); res4 = fma52lo(res4, u3, m[1]); res5 = fma52hi(res5, u3, m[1]); res4 = add64(res4, srli64(res3, DIGIT_SIZE)); U64 u4 = mul52lo(res4, k); fma52lo_mem(res5, res5, u3, m, SIMD_BYTES * 2); fma52hi_mem(res6, res6, u3, m, SIMD_BYTES * 2); res6 = fma52lo(res6, u3, m[3]); res7 = fma52hi(res7, u3, m[3]); fma52lo_mem(res7, res7, u3, m, SIMD_BYTES * 4); fma52hi_mem(res8, res8, u3, m, SIMD_BYTES * 4); res8 = fma52lo(res8, u3, m[5]); res9 = fma52hi(res9, u3, m[5]); fma52lo_mem(res9, res9, u3, m, SIMD_BYTES * 6); fma52hi_mem(res10, res10, u3, m, SIMD_BYTES * 6); res10 = fma52lo(res10, u3, m[7]); res11 = fma52hi(res11, u3, m[7]); fma52lo_mem(res11, res11, u3, m, SIMD_BYTES * 8); fma52hi_mem(res12, res12, u3, m, SIMD_BYTES * 8); res12 = fma52lo(res12, u3, m[9]); res13 = fma52hi(res13, u3, m[9]); fma52lo_mem(res13, res13, u3, m, SIMD_BYTES * 10); fma52hi_mem(res14, res14, u3, m, SIMD_BYTES * 10); res14 = fma52lo(res14, u3, m[11]); res15 = fma52hi(res15, u3, m[11]); fma52lo_mem(res15, res15, u3, m, SIMD_BYTES * 12); fma52hi_mem(res16, res16, u3, m, SIMD_BYTES * 12); res16 = fma52lo(res16, u3, m[13]); res17 = fma52hi(res17, u3, m[13]); fma52lo_mem(res17, res17, u3, m, SIMD_BYTES * 14); fma52hi_mem(res18, res18, u3, m, SIMD_BYTES * 14); res18 = fma52lo(res18, u3, m[15]); res19 = fma52hi(res19, u3, m[15]); fma52lo_mem(res19, res19, u3, m, SIMD_BYTES * 16); fma52hi_mem(res20, res20, u3, m, SIMD_BYTES * 16); res20 = fma52lo(res20, u3, m[17]); res21 = fma52hi(res21, u3, m[17]); fma52lo_mem(res21, res21, u3, m, SIMD_BYTES * 18); fma52hi_mem(res22, res22, u3, m, SIMD_BYTES * 18); res22 = fma52lo(res22, u3, m[19]); res23 = fma52hi(res23, u3, m[19]); ASM("jmp l4\nl4:\n"); // Create u4 fma52lo_mem(res4, res4, u4, m, SIMD_BYTES * 0); fma52hi_mem(res5, res5, u4, m, SIMD_BYTES * 0); res5 = fma52lo(res5, u4, m[1]); res6 = fma52hi(res6, u4, m[1]); res5 = add64(res5, srli64(res4, DIGIT_SIZE)); U64 u5 = mul52lo(res5, k); fma52lo_mem(res6, res6, u4, m, SIMD_BYTES * 2); fma52hi_mem(res7, res7, u4, m, SIMD_BYTES * 2); res7 = fma52lo(res7, u4, m[3]); res8 = fma52hi(res8, u4, m[3]); fma52lo_mem(res8, res8, u4, m, SIMD_BYTES * 4); fma52hi_mem(res9, res9, u4, m, SIMD_BYTES * 4); res9 = fma52lo(res9, u4, m[5]); res10 = fma52hi(res10, u4, m[5]); fma52lo_mem(res10, res10, u4, m, SIMD_BYTES * 6); fma52hi_mem(res11, res11, u4, m, SIMD_BYTES * 6); res11 = fma52lo(res11, u4, m[7]); res12 = fma52hi(res12, u4, m[7]); fma52lo_mem(res12, res12, u4, m, SIMD_BYTES * 8); fma52hi_mem(res13, res13, u4, m, SIMD_BYTES * 8); res13 = fma52lo(res13, u4, m[9]); res14 = fma52hi(res14, u4, m[9]); fma52lo_mem(res14, res14, u4, m, SIMD_BYTES * 10); fma52hi_mem(res15, res15, u4, m, SIMD_BYTES * 10); res15 = fma52lo(res15, u4, m[11]); res16 = fma52hi(res16, u4, m[11]); fma52lo_mem(res16, res16, u4, m, SIMD_BYTES * 12); fma52hi_mem(res17, res17, u4, m, SIMD_BYTES * 12); res17 = fma52lo(res17, u4, m[13]); res18 = fma52hi(res18, u4, m[13]); fma52lo_mem(res18, res18, u4, m, SIMD_BYTES * 14); fma52hi_mem(res19, res19, u4, m, SIMD_BYTES * 14); res19 = fma52lo(res19, u4, m[15]); res20 = fma52hi(res20, u4, m[15]); fma52lo_mem(res20, res20, u4, m, SIMD_BYTES * 16); fma52hi_mem(res21, res21, u4, m, SIMD_BYTES * 16); res21 = fma52lo(res21, u4, m[17]); res22 = fma52hi(res22, u4, m[17]); fma52lo_mem(res22, res22, u4, m, SIMD_BYTES * 18); fma52hi_mem(res23, res23, u4, m, SIMD_BYTES * 18); res23 = fma52lo(res23, u4, m[19]); res24 = fma52hi(res24, u4, m[19]); // Create u5 fma52lo_mem(res5, res5, u5, m, SIMD_BYTES * 0); fma52hi_mem(res6, res6, u5, m, SIMD_BYTES * 0); res6 = fma52lo(res6, u5, m[1]); res7 = fma52hi(res7, u5, m[1]); res6 = add64(res6, srli64(res5, DIGIT_SIZE)); U64 u6 = mul52lo(res6, k); fma52lo_mem(res7, res7, u5, m, SIMD_BYTES * 2); fma52hi_mem(res8, res8, u5, m, SIMD_BYTES * 2); res8 = fma52lo(res8, u5, m[3]); res9 = fma52hi(res9, u5, m[3]); fma52lo_mem(res9, res9, u5, m, SIMD_BYTES * 4); fma52hi_mem(res10, res10, u5, m, SIMD_BYTES * 4); res10 = fma52lo(res10, u5, m[5]); res11 = fma52hi(res11, u5, m[5]); fma52lo_mem(res11, res11, u5, m, SIMD_BYTES * 6); fma52hi_mem(res12, res12, u5, m, SIMD_BYTES * 6); res12 = fma52lo(res12, u5, m[7]); res13 = fma52hi(res13, u5, m[7]); fma52lo_mem(res13, res13, u5, m, SIMD_BYTES * 8); fma52hi_mem(res14, res14, u5, m, SIMD_BYTES * 8); res14 = fma52lo(res14, u5, m[9]); res15 = fma52hi(res15, u5, m[9]); fma52lo_mem(res15, res15, u5, m, SIMD_BYTES * 10); fma52hi_mem(res16, res16, u5, m, SIMD_BYTES * 10); res16 = fma52lo(res16, u5, m[11]); res17 = fma52hi(res17, u5, m[11]); fma52lo_mem(res17, res17, u5, m, SIMD_BYTES * 12); fma52hi_mem(res18, res18, u5, m, SIMD_BYTES * 12); res18 = fma52lo(res18, u5, m[13]); res19 = fma52hi(res19, u5, m[13]); fma52lo_mem(res19, res19, u5, m, SIMD_BYTES * 14); fma52hi_mem(res20, res20, u5, m, SIMD_BYTES * 14); res20 = fma52lo(res20, u5, m[15]); res21 = fma52hi(res21, u5, m[15]); fma52lo_mem(res21, res21, u5, m, SIMD_BYTES * 16); fma52hi_mem(res22, res22, u5, m, SIMD_BYTES * 16); res22 = fma52lo(res22, u5, m[17]); res23 = fma52hi(res23, u5, m[17]); fma52lo_mem(res23, res23, u5, m, SIMD_BYTES * 18); fma52hi_mem(res24, res24, u5, m, SIMD_BYTES * 18); res24 = fma52lo(res24, u5, m[19]); res25 = fma52hi(res25, u5, m[19]); ASM("jmp l6\nl6:\n"); // Create u6 fma52lo_mem(res6, res6, u6, m, SIMD_BYTES * 0); fma52hi_mem(res7, res7, u6, m, SIMD_BYTES * 0); res7 = fma52lo(res7, u6, m[1]); res8 = fma52hi(res8, u6, m[1]); res7 = add64(res7, srli64(res6, DIGIT_SIZE)); U64 u7 = mul52lo(res7, k); fma52lo_mem(res8, res8, u6, m, SIMD_BYTES * 2); fma52hi_mem(res9, res9, u6, m, SIMD_BYTES * 2); res9 = fma52lo(res9, u6, m[3]); res10 = fma52hi(res10, u6, m[3]); fma52lo_mem(res10, res10, u6, m, SIMD_BYTES * 4); fma52hi_mem(res11, res11, u6, m, SIMD_BYTES * 4); res11 = fma52lo(res11, u6, m[5]); res12 = fma52hi(res12, u6, m[5]); fma52lo_mem(res12, res12, u6, m, SIMD_BYTES * 6); fma52hi_mem(res13, res13, u6, m, SIMD_BYTES * 6); res13 = fma52lo(res13, u6, m[7]); res14 = fma52hi(res14, u6, m[7]); fma52lo_mem(res14, res14, u6, m, SIMD_BYTES * 8); fma52hi_mem(res15, res15, u6, m, SIMD_BYTES * 8); res15 = fma52lo(res15, u6, m[9]); res16 = fma52hi(res16, u6, m[9]); fma52lo_mem(res16, res16, u6, m, SIMD_BYTES * 10); fma52hi_mem(res17, res17, u6, m, SIMD_BYTES * 10); res17 = fma52lo(res17, u6, m[11]); res18 = fma52hi(res18, u6, m[11]); fma52lo_mem(res18, res18, u6, m, SIMD_BYTES * 12); fma52hi_mem(res19, res19, u6, m, SIMD_BYTES * 12); res19 = fma52lo(res19, u6, m[13]); res20 = fma52hi(res20, u6, m[13]); fma52lo_mem(res20, res20, u6, m, SIMD_BYTES * 14); fma52hi_mem(res21, res21, u6, m, SIMD_BYTES * 14); res21 = fma52lo(res21, u6, m[15]); res22 = fma52hi(res22, u6, m[15]); fma52lo_mem(res22, res22, u6, m, SIMD_BYTES * 16); fma52hi_mem(res23, res23, u6, m, SIMD_BYTES * 16); res23 = fma52lo(res23, u6, m[17]); res24 = fma52hi(res24, u6, m[17]); fma52lo_mem(res24, res24, u6, m, SIMD_BYTES * 18); fma52hi_mem(res25, res25, u6, m, SIMD_BYTES * 18); res25 = fma52lo(res25, u6, m[19]); res26 = fma52hi(res26, u6, m[19]); // Create u7 fma52lo_mem(res7, res7, u7, m, SIMD_BYTES * 0); fma52hi_mem(res8, res8, u7, m, SIMD_BYTES * 0); res8 = fma52lo(res8, u7, m[1]); res9 = fma52hi(res9, u7, m[1]); res8 = add64(res8, srli64(res7, DIGIT_SIZE)); U64 u8 = mul52lo(res8, k); fma52lo_mem(res9, res9, u7, m, SIMD_BYTES * 2); fma52hi_mem(res10, res10, u7, m, SIMD_BYTES * 2); res10 = fma52lo(res10, u7, m[3]); res11 = fma52hi(res11, u7, m[3]); fma52lo_mem(res11, res11, u7, m, SIMD_BYTES * 4); fma52hi_mem(res12, res12, u7, m, SIMD_BYTES * 4); res12 = fma52lo(res12, u7, m[5]); res13 = fma52hi(res13, u7, m[5]); fma52lo_mem(res13, res13, u7, m, SIMD_BYTES * 6); fma52hi_mem(res14, res14, u7, m, SIMD_BYTES * 6); res14 = fma52lo(res14, u7, m[7]); res15 = fma52hi(res15, u7, m[7]); fma52lo_mem(res15, res15, u7, m, SIMD_BYTES * 8); fma52hi_mem(res16, res16, u7, m, SIMD_BYTES * 8); res16 = fma52lo(res16, u7, m[9]); res17 = fma52hi(res17, u7, m[9]); fma52lo_mem(res17, res17, u7, m, SIMD_BYTES * 10); fma52hi_mem(res18, res18, u7, m, SIMD_BYTES * 10); res18 = fma52lo(res18, u7, m[11]); res19 = fma52hi(res19, u7, m[11]); fma52lo_mem(res19, res19, u7, m, SIMD_BYTES * 12); fma52hi_mem(res20, res20, u7, m, SIMD_BYTES * 12); res20 = fma52lo(res20, u7, m[13]); res21 = fma52hi(res21, u7, m[13]); fma52lo_mem(res21, res21, u7, m, SIMD_BYTES * 14); fma52hi_mem(res22, res22, u7, m, SIMD_BYTES * 14); res22 = fma52lo(res22, u7, m[15]); res23 = fma52hi(res23, u7, m[15]); fma52lo_mem(res23, res23, u7, m, SIMD_BYTES * 16); fma52hi_mem(res24, res24, u7, m, SIMD_BYTES * 16); res24 = fma52lo(res24, u7, m[17]); res25 = fma52hi(res25, u7, m[17]); fma52lo_mem(res25, res25, u7, m, SIMD_BYTES * 18); fma52hi_mem(res26, res26, u7, m, SIMD_BYTES * 18); res26 = fma52lo(res26, u7, m[19]); res27 = fma52hi(res27, u7, m[19]); ASM("jmp l8\nl8:\n"); // Create u8 fma52lo_mem(res8, res8, u8, m, SIMD_BYTES * 0); fma52hi_mem(res9, res9, u8, m, SIMD_BYTES * 0); res9 = fma52lo(res9, u8, m[1]); res10 = fma52hi(res10, u8, m[1]); res9 = add64(res9, srli64(res8, DIGIT_SIZE)); U64 u9 = mul52lo(res9, k); fma52lo_mem(res10, res10, u8, m, SIMD_BYTES * 2); fma52hi_mem(res11, res11, u8, m, SIMD_BYTES * 2); res11 = fma52lo(res11, u8, m[3]); res12 = fma52hi(res12, u8, m[3]); fma52lo_mem(res12, res12, u8, m, SIMD_BYTES * 4); fma52hi_mem(res13, res13, u8, m, SIMD_BYTES * 4); res13 = fma52lo(res13, u8, m[5]); res14 = fma52hi(res14, u8, m[5]); fma52lo_mem(res14, res14, u8, m, SIMD_BYTES * 6); fma52hi_mem(res15, res15, u8, m, SIMD_BYTES * 6); res15 = fma52lo(res15, u8, m[7]); res16 = fma52hi(res16, u8, m[7]); fma52lo_mem(res16, res16, u8, m, SIMD_BYTES * 8); fma52hi_mem(res17, res17, u8, m, SIMD_BYTES * 8); res17 = fma52lo(res17, u8, m[9]); res18 = fma52hi(res18, u8, m[9]); fma52lo_mem(res18, res18, u8, m, SIMD_BYTES * 10); fma52hi_mem(res19, res19, u8, m, SIMD_BYTES * 10); res19 = fma52lo(res19, u8, m[11]); res20 = fma52hi(res20, u8, m[11]); fma52lo_mem(res20, res20, u8, m, SIMD_BYTES * 12); fma52hi_mem(res21, res21, u8, m, SIMD_BYTES * 12); res21 = fma52lo(res21, u8, m[13]); res22 = fma52hi(res22, u8, m[13]); fma52lo_mem(res22, res22, u8, m, SIMD_BYTES * 14); fma52hi_mem(res23, res23, u8, m, SIMD_BYTES * 14); res23 = fma52lo(res23, u8, m[15]); res24 = fma52hi(res24, u8, m[15]); fma52lo_mem(res24, res24, u8, m, SIMD_BYTES * 16); fma52hi_mem(res25, res25, u8, m, SIMD_BYTES * 16); res25 = fma52lo(res25, u8, m[17]); res26 = fma52hi(res26, u8, m[17]); fma52lo_mem(res26, res26, u8, m, SIMD_BYTES * 18); fma52hi_mem(res27, res27, u8, m, SIMD_BYTES * 18); res27 = fma52lo(res27, u8, m[19]); res28 = fma52hi(res28, u8, m[19]); // Create u9 fma52lo_mem(res9, res9, u9, m, SIMD_BYTES * 0); fma52hi_mem(res10, res10, u9, m, SIMD_BYTES * 0); res10 = fma52lo(res10, u9, m[1]); res11 = fma52hi(res11, u9, m[1]); res10 = add64(res10, srli64(res9, DIGIT_SIZE)); U64 u10 = mul52lo(res10, k); fma52lo_mem(res11, res11, u9, m, SIMD_BYTES * 2); fma52hi_mem(res12, res12, u9, m, SIMD_BYTES * 2); res12 = fma52lo(res12, u9, m[3]); res13 = fma52hi(res13, u9, m[3]); fma52lo_mem(res13, res13, u9, m, SIMD_BYTES * 4); fma52hi_mem(res14, res14, u9, m, SIMD_BYTES * 4); res14 = fma52lo(res14, u9, m[5]); res15 = fma52hi(res15, u9, m[5]); fma52lo_mem(res15, res15, u9, m, SIMD_BYTES * 6); fma52hi_mem(res16, res16, u9, m, SIMD_BYTES * 6); res16 = fma52lo(res16, u9, m[7]); res17 = fma52hi(res17, u9, m[7]); fma52lo_mem(res17, res17, u9, m, SIMD_BYTES * 8); fma52hi_mem(res18, res18, u9, m, SIMD_BYTES * 8); res18 = fma52lo(res18, u9, m[9]); res19 = fma52hi(res19, u9, m[9]); fma52lo_mem(res19, res19, u9, m, SIMD_BYTES * 10); fma52hi_mem(res20, res20, u9, m, SIMD_BYTES * 10); res20 = fma52lo(res20, u9, m[11]); res21 = fma52hi(res21, u9, m[11]); fma52lo_mem(res21, res21, u9, m, SIMD_BYTES * 12); fma52hi_mem(res22, res22, u9, m, SIMD_BYTES * 12); res22 = fma52lo(res22, u9, m[13]); res23 = fma52hi(res23, u9, m[13]); fma52lo_mem(res23, res23, u9, m, SIMD_BYTES * 14); fma52hi_mem(res24, res24, u9, m, SIMD_BYTES * 14); res24 = fma52lo(res24, u9, m[15]); res25 = fma52hi(res25, u9, m[15]); fma52lo_mem(res25, res25, u9, m, SIMD_BYTES * 16); fma52hi_mem(res26, res26, u9, m, SIMD_BYTES * 16); res26 = fma52lo(res26, u9, m[17]); res27 = fma52hi(res27, u9, m[17]); fma52lo_mem(res27, res27, u9, m, SIMD_BYTES * 18); fma52hi_mem(res28, res28, u9, m, SIMD_BYTES * 18); res28 = fma52lo(res28, u9, m[19]); res29 = fma52hi(res29, u9, m[19]); ASM("jmp l10\nl10:\n"); // Create u10 fma52lo_mem(res10, res10, u10, m, SIMD_BYTES * 0); fma52hi_mem(res11, res11, u10, m, SIMD_BYTES * 0); res11 = fma52lo(res11, u10, m[1]); res12 = fma52hi(res12, u10, m[1]); res11 = add64(res11, srli64(res10, DIGIT_SIZE)); U64 u11 = mul52lo(res11, k); fma52lo_mem(res12, res12, u10, m, SIMD_BYTES * 2); fma52hi_mem(res13, res13, u10, m, SIMD_BYTES * 2); res13 = fma52lo(res13, u10, m[3]); res14 = fma52hi(res14, u10, m[3]); fma52lo_mem(res14, res14, u10, m, SIMD_BYTES * 4); fma52hi_mem(res15, res15, u10, m, SIMD_BYTES * 4); res15 = fma52lo(res15, u10, m[5]); res16 = fma52hi(res16, u10, m[5]); fma52lo_mem(res16, res16, u10, m, SIMD_BYTES * 6); fma52hi_mem(res17, res17, u10, m, SIMD_BYTES * 6); res17 = fma52lo(res17, u10, m[7]); res18 = fma52hi(res18, u10, m[7]); fma52lo_mem(res18, res18, u10, m, SIMD_BYTES * 8); fma52hi_mem(res19, res19, u10, m, SIMD_BYTES * 8); res19 = fma52lo(res19, u10, m[9]); res20 = fma52hi(res20, u10, m[9]); fma52lo_mem(res20, res20, u10, m, SIMD_BYTES * 10); fma52hi_mem(res21, res21, u10, m, SIMD_BYTES * 10); res21 = fma52lo(res21, u10, m[11]); res22 = fma52hi(res22, u10, m[11]); fma52lo_mem(res22, res22, u10, m, SIMD_BYTES * 12); fma52hi_mem(res23, res23, u10, m, SIMD_BYTES * 12); res23 = fma52lo(res23, u10, m[13]); res24 = fma52hi(res24, u10, m[13]); fma52lo_mem(res24, res24, u10, m, SIMD_BYTES * 14); fma52hi_mem(res25, res25, u10, m, SIMD_BYTES * 14); res25 = fma52lo(res25, u10, m[15]); res26 = fma52hi(res26, u10, m[15]); fma52lo_mem(res26, res26, u10, m, SIMD_BYTES * 16); fma52hi_mem(res27, res27, u10, m, SIMD_BYTES * 16); res27 = fma52lo(res27, u10, m[17]); res28 = fma52hi(res28, u10, m[17]); fma52lo_mem(res28, res28, u10, m, SIMD_BYTES * 18); fma52hi_mem(res29, res29, u10, m, SIMD_BYTES * 18); res29 = fma52lo(res29, u10, m[19]); res30 = fma52hi(res30, u10, m[19]); // Create u11 fma52lo_mem(res11, res11, u11, m, SIMD_BYTES * 0); fma52hi_mem(res12, res12, u11, m, SIMD_BYTES * 0); res12 = fma52lo(res12, u11, m[1]); res13 = fma52hi(res13, u11, m[1]); res12 = add64(res12, srli64(res11, DIGIT_SIZE)); U64 u12 = mul52lo(res12, k); fma52lo_mem(res13, res13, u11, m, SIMD_BYTES * 2); fma52hi_mem(res14, res14, u11, m, SIMD_BYTES * 2); res14 = fma52lo(res14, u11, m[3]); res15 = fma52hi(res15, u11, m[3]); fma52lo_mem(res15, res15, u11, m, SIMD_BYTES * 4); fma52hi_mem(res16, res16, u11, m, SIMD_BYTES * 4); res16 = fma52lo(res16, u11, m[5]); res17 = fma52hi(res17, u11, m[5]); fma52lo_mem(res17, res17, u11, m, SIMD_BYTES * 6); fma52hi_mem(res18, res18, u11, m, SIMD_BYTES * 6); res18 = fma52lo(res18, u11, m[7]); res19 = fma52hi(res19, u11, m[7]); fma52lo_mem(res19, res19, u11, m, SIMD_BYTES * 8); fma52hi_mem(res20, res20, u11, m, SIMD_BYTES * 8); res20 = fma52lo(res20, u11, m[9]); res21 = fma52hi(res21, u11, m[9]); fma52lo_mem(res21, res21, u11, m, SIMD_BYTES * 10); fma52hi_mem(res22, res22, u11, m, SIMD_BYTES * 10); res22 = fma52lo(res22, u11, m[11]); res23 = fma52hi(res23, u11, m[11]); fma52lo_mem(res23, res23, u11, m, SIMD_BYTES * 12); fma52hi_mem(res24, res24, u11, m, SIMD_BYTES * 12); res24 = fma52lo(res24, u11, m[13]); res25 = fma52hi(res25, u11, m[13]); fma52lo_mem(res25, res25, u11, m, SIMD_BYTES * 14); fma52hi_mem(res26, res26, u11, m, SIMD_BYTES * 14); res26 = fma52lo(res26, u11, m[15]); res27 = fma52hi(res27, u11, m[15]); fma52lo_mem(res27, res27, u11, m, SIMD_BYTES * 16); fma52hi_mem(res28, res28, u11, m, SIMD_BYTES * 16); res28 = fma52lo(res28, u11, m[17]); res29 = fma52hi(res29, u11, m[17]); fma52lo_mem(res29, res29, u11, m, SIMD_BYTES * 18); fma52hi_mem(res30, res30, u11, m, SIMD_BYTES * 18); res30 = fma52lo(res30, u11, m[19]); res31 = fma52hi(res31, u11, m[19]); ASM("jmp l12\nl12:\n"); // Create u12 fma52lo_mem(res12, res12, u12, m, SIMD_BYTES * 0); fma52hi_mem(res13, res13, u12, m, SIMD_BYTES * 0); res13 = fma52lo(res13, u12, m[1]); res14 = fma52hi(res14, u12, m[1]); res13 = add64(res13, srli64(res12, DIGIT_SIZE)); U64 u13 = mul52lo(res13, k); fma52lo_mem(res14, res14, u12, m, SIMD_BYTES * 2); fma52hi_mem(res15, res15, u12, m, SIMD_BYTES * 2); res15 = fma52lo(res15, u12, m[3]); res16 = fma52hi(res16, u12, m[3]); fma52lo_mem(res16, res16, u12, m, SIMD_BYTES * 4); fma52hi_mem(res17, res17, u12, m, SIMD_BYTES * 4); res17 = fma52lo(res17, u12, m[5]); res18 = fma52hi(res18, u12, m[5]); fma52lo_mem(res18, res18, u12, m, SIMD_BYTES * 6); fma52hi_mem(res19, res19, u12, m, SIMD_BYTES * 6); res19 = fma52lo(res19, u12, m[7]); res20 = fma52hi(res20, u12, m[7]); fma52lo_mem(res20, res20, u12, m, SIMD_BYTES * 8); fma52hi_mem(res21, res21, u12, m, SIMD_BYTES * 8); res21 = fma52lo(res21, u12, m[9]); res22 = fma52hi(res22, u12, m[9]); fma52lo_mem(res22, res22, u12, m, SIMD_BYTES * 10); fma52hi_mem(res23, res23, u12, m, SIMD_BYTES * 10); res23 = fma52lo(res23, u12, m[11]); res24 = fma52hi(res24, u12, m[11]); fma52lo_mem(res24, res24, u12, m, SIMD_BYTES * 12); fma52hi_mem(res25, res25, u12, m, SIMD_BYTES * 12); res25 = fma52lo(res25, u12, m[13]); res26 = fma52hi(res26, u12, m[13]); fma52lo_mem(res26, res26, u12, m, SIMD_BYTES * 14); fma52hi_mem(res27, res27, u12, m, SIMD_BYTES * 14); res27 = fma52lo(res27, u12, m[15]); res28 = fma52hi(res28, u12, m[15]); fma52lo_mem(res28, res28, u12, m, SIMD_BYTES * 16); fma52hi_mem(res29, res29, u12, m, SIMD_BYTES * 16); res29 = fma52lo(res29, u12, m[17]); res30 = fma52hi(res30, u12, m[17]); fma52lo_mem(res30, res30, u12, m, SIMD_BYTES * 18); fma52hi_mem(res31, res31, u12, m, SIMD_BYTES * 18); res31 = fma52lo(res31, u12, m[19]); res32 = fma52hi(res32, u12, m[19]); // Create u13 fma52lo_mem(res13, res13, u13, m, SIMD_BYTES * 0); fma52hi_mem(res14, res14, u13, m, SIMD_BYTES * 0); res14 = fma52lo(res14, u13, m[1]); res15 = fma52hi(res15, u13, m[1]); res14 = add64(res14, srli64(res13, DIGIT_SIZE)); U64 u14 = mul52lo(res14, k); fma52lo_mem(res15, res15, u13, m, SIMD_BYTES * 2); fma52hi_mem(res16, res16, u13, m, SIMD_BYTES * 2); res16 = fma52lo(res16, u13, m[3]); res17 = fma52hi(res17, u13, m[3]); fma52lo_mem(res17, res17, u13, m, SIMD_BYTES * 4); fma52hi_mem(res18, res18, u13, m, SIMD_BYTES * 4); res18 = fma52lo(res18, u13, m[5]); res19 = fma52hi(res19, u13, m[5]); fma52lo_mem(res19, res19, u13, m, SIMD_BYTES * 6); fma52hi_mem(res20, res20, u13, m, SIMD_BYTES * 6); res20 = fma52lo(res20, u13, m[7]); res21 = fma52hi(res21, u13, m[7]); fma52lo_mem(res21, res21, u13, m, SIMD_BYTES * 8); fma52hi_mem(res22, res22, u13, m, SIMD_BYTES * 8); res22 = fma52lo(res22, u13, m[9]); res23 = fma52hi(res23, u13, m[9]); fma52lo_mem(res23, res23, u13, m, SIMD_BYTES * 10); fma52hi_mem(res24, res24, u13, m, SIMD_BYTES * 10); res24 = fma52lo(res24, u13, m[11]); res25 = fma52hi(res25, u13, m[11]); fma52lo_mem(res25, res25, u13, m, SIMD_BYTES * 12); fma52hi_mem(res26, res26, u13, m, SIMD_BYTES * 12); res26 = fma52lo(res26, u13, m[13]); res27 = fma52hi(res27, u13, m[13]); fma52lo_mem(res27, res27, u13, m, SIMD_BYTES * 14); fma52hi_mem(res28, res28, u13, m, SIMD_BYTES * 14); res28 = fma52lo(res28, u13, m[15]); res29 = fma52hi(res29, u13, m[15]); fma52lo_mem(res29, res29, u13, m, SIMD_BYTES * 16); fma52hi_mem(res30, res30, u13, m, SIMD_BYTES * 16); res30 = fma52lo(res30, u13, m[17]); res31 = fma52hi(res31, u13, m[17]); fma52lo_mem(res31, res31, u13, m, SIMD_BYTES * 18); fma52hi_mem(res32, res32, u13, m, SIMD_BYTES * 18); res32 = fma52lo(res32, u13, m[19]); res33 = fma52hi(res33, u13, m[19]); ASM("jmp l14\nl14:\n"); // Create u14 fma52lo_mem(res14, res14, u14, m, SIMD_BYTES * 0); fma52hi_mem(res15, res15, u14, m, SIMD_BYTES * 0); res15 = fma52lo(res15, u14, m[1]); res16 = fma52hi(res16, u14, m[1]); res15 = add64(res15, srli64(res14, DIGIT_SIZE)); U64 u15 = mul52lo(res15, k); fma52lo_mem(res16, res16, u14, m, SIMD_BYTES * 2); fma52hi_mem(res17, res17, u14, m, SIMD_BYTES * 2); res17 = fma52lo(res17, u14, m[3]); res18 = fma52hi(res18, u14, m[3]); fma52lo_mem(res18, res18, u14, m, SIMD_BYTES * 4); fma52hi_mem(res19, res19, u14, m, SIMD_BYTES * 4); res19 = fma52lo(res19, u14, m[5]); res20 = fma52hi(res20, u14, m[5]); fma52lo_mem(res20, res20, u14, m, SIMD_BYTES * 6); fma52hi_mem(res21, res21, u14, m, SIMD_BYTES * 6); res21 = fma52lo(res21, u14, m[7]); res22 = fma52hi(res22, u14, m[7]); fma52lo_mem(res22, res22, u14, m, SIMD_BYTES * 8); fma52hi_mem(res23, res23, u14, m, SIMD_BYTES * 8); res23 = fma52lo(res23, u14, m[9]); res24 = fma52hi(res24, u14, m[9]); fma52lo_mem(res24, res24, u14, m, SIMD_BYTES * 10); fma52hi_mem(res25, res25, u14, m, SIMD_BYTES * 10); res25 = fma52lo(res25, u14, m[11]); res26 = fma52hi(res26, u14, m[11]); fma52lo_mem(res26, res26, u14, m, SIMD_BYTES * 12); fma52hi_mem(res27, res27, u14, m, SIMD_BYTES * 12); res27 = fma52lo(res27, u14, m[13]); res28 = fma52hi(res28, u14, m[13]); fma52lo_mem(res28, res28, u14, m, SIMD_BYTES * 14); fma52hi_mem(res29, res29, u14, m, SIMD_BYTES * 14); res29 = fma52lo(res29, u14, m[15]); res30 = fma52hi(res30, u14, m[15]); fma52lo_mem(res30, res30, u14, m, SIMD_BYTES * 16); fma52hi_mem(res31, res31, u14, m, SIMD_BYTES * 16); res31 = fma52lo(res31, u14, m[17]); res32 = fma52hi(res32, u14, m[17]); fma52lo_mem(res32, res32, u14, m, SIMD_BYTES * 18); fma52hi_mem(res33, res33, u14, m, SIMD_BYTES * 18); res33 = fma52lo(res33, u14, m[19]); res34 = fma52hi(res34, u14, m[19]); // Create u15 fma52lo_mem(res15, res15, u15, m, SIMD_BYTES * 0); fma52hi_mem(res16, res16, u15, m, SIMD_BYTES * 0); res16 = fma52lo(res16, u15, m[1]); res17 = fma52hi(res17, u15, m[1]); res16 = add64(res16, srli64(res15, DIGIT_SIZE)); U64 u16 = mul52lo(res16, k); fma52lo_mem(res17, res17, u15, m, SIMD_BYTES * 2); fma52hi_mem(res18, res18, u15, m, SIMD_BYTES * 2); res18 = fma52lo(res18, u15, m[3]); res19 = fma52hi(res19, u15, m[3]); fma52lo_mem(res19, res19, u15, m, SIMD_BYTES * 4); fma52hi_mem(res20, res20, u15, m, SIMD_BYTES * 4); res20 = fma52lo(res20, u15, m[5]); res21 = fma52hi(res21, u15, m[5]); fma52lo_mem(res21, res21, u15, m, SIMD_BYTES * 6); fma52hi_mem(res22, res22, u15, m, SIMD_BYTES * 6); res22 = fma52lo(res22, u15, m[7]); res23 = fma52hi(res23, u15, m[7]); fma52lo_mem(res23, res23, u15, m, SIMD_BYTES * 8); fma52hi_mem(res24, res24, u15, m, SIMD_BYTES * 8); res24 = fma52lo(res24, u15, m[9]); res25 = fma52hi(res25, u15, m[9]); fma52lo_mem(res25, res25, u15, m, SIMD_BYTES * 10); fma52hi_mem(res26, res26, u15, m, SIMD_BYTES * 10); res26 = fma52lo(res26, u15, m[11]); res27 = fma52hi(res27, u15, m[11]); fma52lo_mem(res27, res27, u15, m, SIMD_BYTES * 12); fma52hi_mem(res28, res28, u15, m, SIMD_BYTES * 12); res28 = fma52lo(res28, u15, m[13]); res29 = fma52hi(res29, u15, m[13]); fma52lo_mem(res29, res29, u15, m, SIMD_BYTES * 14); fma52hi_mem(res30, res30, u15, m, SIMD_BYTES * 14); res30 = fma52lo(res30, u15, m[15]); res31 = fma52hi(res31, u15, m[15]); fma52lo_mem(res31, res31, u15, m, SIMD_BYTES * 16); fma52hi_mem(res32, res32, u15, m, SIMD_BYTES * 16); res32 = fma52lo(res32, u15, m[17]); res33 = fma52hi(res33, u15, m[17]); fma52lo_mem(res33, res33, u15, m, SIMD_BYTES * 18); fma52hi_mem(res34, res34, u15, m, SIMD_BYTES * 18); res34 = fma52lo(res34, u15, m[19]); res35 = fma52hi(res35, u15, m[19]); ASM("jmp l16\nl16:\n"); // Create u16 fma52lo_mem(res16, res16, u16, m, SIMD_BYTES * 0); fma52hi_mem(res17, res17, u16, m, SIMD_BYTES * 0); res17 = fma52lo(res17, u16, m[1]); res18 = fma52hi(res18, u16, m[1]); res17 = add64(res17, srli64(res16, DIGIT_SIZE)); U64 u17 = mul52lo(res17, k); fma52lo_mem(res18, res18, u16, m, SIMD_BYTES * 2); fma52hi_mem(res19, res19, u16, m, SIMD_BYTES * 2); res19 = fma52lo(res19, u16, m[3]); res20 = fma52hi(res20, u16, m[3]); fma52lo_mem(res20, res20, u16, m, SIMD_BYTES * 4); fma52hi_mem(res21, res21, u16, m, SIMD_BYTES * 4); res21 = fma52lo(res21, u16, m[5]); res22 = fma52hi(res22, u16, m[5]); fma52lo_mem(res22, res22, u16, m, SIMD_BYTES * 6); fma52hi_mem(res23, res23, u16, m, SIMD_BYTES * 6); res23 = fma52lo(res23, u16, m[7]); res24 = fma52hi(res24, u16, m[7]); fma52lo_mem(res24, res24, u16, m, SIMD_BYTES * 8); fma52hi_mem(res25, res25, u16, m, SIMD_BYTES * 8); res25 = fma52lo(res25, u16, m[9]); res26 = fma52hi(res26, u16, m[9]); fma52lo_mem(res26, res26, u16, m, SIMD_BYTES * 10); fma52hi_mem(res27, res27, u16, m, SIMD_BYTES * 10); res27 = fma52lo(res27, u16, m[11]); res28 = fma52hi(res28, u16, m[11]); fma52lo_mem(res28, res28, u16, m, SIMD_BYTES * 12); fma52hi_mem(res29, res29, u16, m, SIMD_BYTES * 12); res29 = fma52lo(res29, u16, m[13]); res30 = fma52hi(res30, u16, m[13]); fma52lo_mem(res30, res30, u16, m, SIMD_BYTES * 14); fma52hi_mem(res31, res31, u16, m, SIMD_BYTES * 14); res31 = fma52lo(res31, u16, m[15]); res32 = fma52hi(res32, u16, m[15]); fma52lo_mem(res32, res32, u16, m, SIMD_BYTES * 16); fma52hi_mem(res33, res33, u16, m, SIMD_BYTES * 16); res33 = fma52lo(res33, u16, m[17]); res34 = fma52hi(res34, u16, m[17]); fma52lo_mem(res34, res34, u16, m, SIMD_BYTES * 18); fma52hi_mem(res35, res35, u16, m, SIMD_BYTES * 18); res35 = fma52lo(res35, u16, m[19]); res36 = fma52hi(res36, u16, m[19]); // Create u17 fma52lo_mem(res17, res17, u17, m, SIMD_BYTES * 0); fma52hi_mem(res18, res18, u17, m, SIMD_BYTES * 0); res18 = fma52lo(res18, u17, m[1]); res19 = fma52hi(res19, u17, m[1]); res18 = add64(res18, srli64(res17, DIGIT_SIZE)); U64 u18 = mul52lo(res18, k); fma52lo_mem(res19, res19, u17, m, SIMD_BYTES * 2); fma52hi_mem(res20, res20, u17, m, SIMD_BYTES * 2); res20 = fma52lo(res20, u17, m[3]); res21 = fma52hi(res21, u17, m[3]); fma52lo_mem(res21, res21, u17, m, SIMD_BYTES * 4); fma52hi_mem(res22, res22, u17, m, SIMD_BYTES * 4); res22 = fma52lo(res22, u17, m[5]); res23 = fma52hi(res23, u17, m[5]); fma52lo_mem(res23, res23, u17, m, SIMD_BYTES * 6); fma52hi_mem(res24, res24, u17, m, SIMD_BYTES * 6); res24 = fma52lo(res24, u17, m[7]); res25 = fma52hi(res25, u17, m[7]); fma52lo_mem(res25, res25, u17, m, SIMD_BYTES * 8); fma52hi_mem(res26, res26, u17, m, SIMD_BYTES * 8); res26 = fma52lo(res26, u17, m[9]); res27 = fma52hi(res27, u17, m[9]); fma52lo_mem(res27, res27, u17, m, SIMD_BYTES * 10); fma52hi_mem(res28, res28, u17, m, SIMD_BYTES * 10); res28 = fma52lo(res28, u17, m[11]); res29 = fma52hi(res29, u17, m[11]); fma52lo_mem(res29, res29, u17, m, SIMD_BYTES * 12); fma52hi_mem(res30, res30, u17, m, SIMD_BYTES * 12); res30 = fma52lo(res30, u17, m[13]); res31 = fma52hi(res31, u17, m[13]); fma52lo_mem(res31, res31, u17, m, SIMD_BYTES * 14); fma52hi_mem(res32, res32, u17, m, SIMD_BYTES * 14); res32 = fma52lo(res32, u17, m[15]); res33 = fma52hi(res33, u17, m[15]); fma52lo_mem(res33, res33, u17, m, SIMD_BYTES * 16); fma52hi_mem(res34, res34, u17, m, SIMD_BYTES * 16); res34 = fma52lo(res34, u17, m[17]); res35 = fma52hi(res35, u17, m[17]); fma52lo_mem(res35, res35, u17, m, SIMD_BYTES * 18); fma52hi_mem(res36, res36, u17, m, SIMD_BYTES * 18); res36 = fma52lo(res36, u17, m[19]); res37 = fma52hi(res37, u17, m[19]); ASM("jmp l18\nl18:\n"); // Create u18 fma52lo_mem(res18, res18, u18, m, SIMD_BYTES * 0); fma52hi_mem(res19, res19, u18, m, SIMD_BYTES * 0); res19 = fma52lo(res19, u18, m[1]); res20 = fma52hi(res20, u18, m[1]); res19 = add64(res19, srli64(res18, DIGIT_SIZE)); U64 u19 = mul52lo(res19, k); fma52lo_mem(res20, res20, u18, m, SIMD_BYTES * 2); fma52hi_mem(res21, res21, u18, m, SIMD_BYTES * 2); res21 = fma52lo(res21, u18, m[3]); res22 = fma52hi(res22, u18, m[3]); fma52lo_mem(res22, res22, u18, m, SIMD_BYTES * 4); fma52hi_mem(res23, res23, u18, m, SIMD_BYTES * 4); res23 = fma52lo(res23, u18, m[5]); res24 = fma52hi(res24, u18, m[5]); fma52lo_mem(res24, res24, u18, m, SIMD_BYTES * 6); fma52hi_mem(res25, res25, u18, m, SIMD_BYTES * 6); res25 = fma52lo(res25, u18, m[7]); res26 = fma52hi(res26, u18, m[7]); fma52lo_mem(res26, res26, u18, m, SIMD_BYTES * 8); fma52hi_mem(res27, res27, u18, m, SIMD_BYTES * 8); res27 = fma52lo(res27, u18, m[9]); res28 = fma52hi(res28, u18, m[9]); fma52lo_mem(res28, res28, u18, m, SIMD_BYTES * 10); fma52hi_mem(res29, res29, u18, m, SIMD_BYTES * 10); res29 = fma52lo(res29, u18, m[11]); res30 = fma52hi(res30, u18, m[11]); fma52lo_mem(res30, res30, u18, m, SIMD_BYTES * 12); fma52hi_mem(res31, res31, u18, m, SIMD_BYTES * 12); res31 = fma52lo(res31, u18, m[13]); res32 = fma52hi(res32, u18, m[13]); fma52lo_mem(res32, res32, u18, m, SIMD_BYTES * 14); fma52hi_mem(res33, res33, u18, m, SIMD_BYTES * 14); res33 = fma52lo(res33, u18, m[15]); res34 = fma52hi(res34, u18, m[15]); fma52lo_mem(res34, res34, u18, m, SIMD_BYTES * 16); fma52hi_mem(res35, res35, u18, m, SIMD_BYTES * 16); res35 = fma52lo(res35, u18, m[17]); res36 = fma52hi(res36, u18, m[17]); fma52lo_mem(res36, res36, u18, m, SIMD_BYTES * 18); fma52hi_mem(res37, res37, u18, m, SIMD_BYTES * 18); res37 = fma52lo(res37, u18, m[19]); res38 = fma52hi(res38, u18, m[19]); // Create u19 fma52lo_mem(res19, res19, u19, m, SIMD_BYTES * 0); fma52hi_mem(res20, res20, u19, m, SIMD_BYTES * 0); res20 = fma52lo(res20, u19, m[1]); res21 = fma52hi(res21, u19, m[1]); res20 = add64(res20, srli64(res19, DIGIT_SIZE)); fma52lo_mem(res21, res21, u19, m, SIMD_BYTES * 2); fma52hi_mem(res22, res22, u19, m, SIMD_BYTES * 2); res22 = fma52lo(res22, u19, m[3]); res23 = fma52hi(res23, u19, m[3]); fma52lo_mem(res23, res23, u19, m, SIMD_BYTES * 4); fma52hi_mem(res24, res24, u19, m, SIMD_BYTES * 4); res24 = fma52lo(res24, u19, m[5]); res25 = fma52hi(res25, u19, m[5]); fma52lo_mem(res25, res25, u19, m, SIMD_BYTES * 6); fma52hi_mem(res26, res26, u19, m, SIMD_BYTES * 6); res26 = fma52lo(res26, u19, m[7]); res27 = fma52hi(res27, u19, m[7]); fma52lo_mem(res27, res27, u19, m, SIMD_BYTES * 8); fma52hi_mem(res28, res28, u19, m, SIMD_BYTES * 8); res28 = fma52lo(res28, u19, m[9]); res29 = fma52hi(res29, u19, m[9]); fma52lo_mem(res29, res29, u19, m, SIMD_BYTES * 10); fma52hi_mem(res30, res30, u19, m, SIMD_BYTES * 10); res30 = fma52lo(res30, u19, m[11]); res31 = fma52hi(res31, u19, m[11]); fma52lo_mem(res31, res31, u19, m, SIMD_BYTES * 12); fma52hi_mem(res32, res32, u19, m, SIMD_BYTES * 12); res32 = fma52lo(res32, u19, m[13]); res33 = fma52hi(res33, u19, m[13]); fma52lo_mem(res33, res33, u19, m, SIMD_BYTES * 14); fma52hi_mem(res34, res34, u19, m, SIMD_BYTES * 14); res34 = fma52lo(res34, u19, m[15]); res35 = fma52hi(res35, u19, m[15]); fma52lo_mem(res35, res35, u19, m, SIMD_BYTES * 16); fma52hi_mem(res36, res36, u19, m, SIMD_BYTES * 16); res36 = fma52lo(res36, u19, m[17]); res37 = fma52hi(res37, u19, m[17]); fma52lo_mem(res37, res37, u19, m, SIMD_BYTES * 18); fma52hi_mem(res38, res38, u19, m, SIMD_BYTES * 18); res38 = fma52lo(res38, u19, m[19]); res39 = fma52hi(res39, u19, m[19]); // Normalization r[0] = and64_const(res20, DIGIT_MASK); res21 = add64(res21, srli64(res20, DIGIT_SIZE)); r[1] = and64_const(res21, DIGIT_MASK); res22 = add64(res22, srli64(res21, DIGIT_SIZE)); r[2] = and64_const(res22, DIGIT_MASK); res23 = add64(res23, srli64(res22, DIGIT_SIZE)); r[3] = and64_const(res23, DIGIT_MASK); res24 = add64(res24, srli64(res23, DIGIT_SIZE)); r[4] = and64_const(res24, DIGIT_MASK); res25 = add64(res25, srli64(res24, DIGIT_SIZE)); r[5] = and64_const(res25, DIGIT_MASK); res26 = add64(res26, srli64(res25, DIGIT_SIZE)); r[6] = and64_const(res26, DIGIT_MASK); res27 = add64(res27, srli64(res26, DIGIT_SIZE)); r[7] = and64_const(res27, DIGIT_MASK); res28 = add64(res28, srli64(res27, DIGIT_SIZE)); r[8] = and64_const(res28, DIGIT_MASK); res29 = add64(res29, srli64(res28, DIGIT_SIZE)); r[9] = and64_const(res29, DIGIT_MASK); res30 = add64(res30, srli64(res29, DIGIT_SIZE)); r[10] = and64_const(res30, DIGIT_MASK); res31 = add64(res31, srli64(res30, DIGIT_SIZE)); r[11] = and64_const(res31, DIGIT_MASK); res32 = add64(res32, srli64(res31, DIGIT_SIZE)); r[12] = and64_const(res32, DIGIT_MASK); res33 = add64(res33, srli64(res32, DIGIT_SIZE)); r[13] = and64_const(res33, DIGIT_MASK); res34 = add64(res34, srli64(res33, DIGIT_SIZE)); r[14] = and64_const(res34, DIGIT_MASK); res35 = add64(res35, srli64(res34, DIGIT_SIZE)); r[15] = and64_const(res35, DIGIT_MASK); res36 = add64(res36, srli64(res35, DIGIT_SIZE)); r[16] = and64_const(res36, DIGIT_MASK); res37 = add64(res37, srli64(res36, DIGIT_SIZE)); r[17] = and64_const(res37, DIGIT_MASK); res38 = add64(res38, srli64(res37, DIGIT_SIZE)); r[18] = and64_const(res38, DIGIT_MASK); res39 = add64(res39, srli64(res38, DIGIT_SIZE)); r[19] = and64_const(res39, DIGIT_MASK); } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams52x30_diagonal_mb8.c000066400000000000000000002644641470420105600345140ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void AMS52x30_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { __ALIGN64 U64 res[60]; __ALIGN64 U64 u[30]; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; k = loadu64((U64 *)k0_mb); int i; for (i = 0; i < 60; ++i) res[i] = get_zero64(); res[1] = fma52lo(res[1], a[0], a[1]); // Sum(1) res[2] = fma52hi(res[2], a[0], a[1]); // Sum(1) res[2] = fma52lo(res[2], a[0], a[2]); // Sum(2) res[3] = fma52hi(res[3], a[0], a[2]); // Sum(2) res[3] = fma52lo(res[3], a[1], a[2]); // Sum(3) res[4] = fma52hi(res[4], a[1], a[2]); // Sum(3) res[3] = fma52lo(res[3], a[0], a[3]); // Sum(3) res[4] = fma52hi(res[4], a[0], a[3]); // Sum(3) res[4] = fma52lo(res[4], a[1], a[3]); // Sum(4) res[5] = fma52hi(res[5], a[1], a[3]); // Sum(4) res[5] = fma52lo(res[5], a[2], a[3]); // Sum(5) res[6] = fma52hi(res[6], a[2], a[3]); // Sum(5) res[4] = fma52lo(res[4], a[0], a[4]); // Sum(4) res[5] = fma52hi(res[5], a[0], a[4]); // Sum(4) res[5] = fma52lo(res[5], a[1], a[4]); // Sum(5) res[6] = fma52hi(res[6], a[1], a[4]); // Sum(5) res[6] = fma52lo(res[6], a[2], a[4]); // Sum(6) res[7] = fma52hi(res[7], a[2], a[4]); // Sum(6) res[7] = fma52lo(res[7], a[3], a[4]); // Sum(7) res[8] = fma52hi(res[8], a[3], a[4]); // Sum(7) res[5] = fma52lo(res[5], a[0], a[5]); // Sum(5) res[6] = fma52hi(res[6], a[0], a[5]); // Sum(5) res[6] = fma52lo(res[6], a[1], a[5]); // Sum(6) res[7] = fma52hi(res[7], a[1], a[5]); // Sum(6) res[7] = fma52lo(res[7], a[2], a[5]); // Sum(7) res[8] = fma52hi(res[8], a[2], a[5]); // Sum(7) res[8] = fma52lo(res[8], a[3], a[5]); // Sum(8) res[9] = fma52hi(res[9], a[3], a[5]); // Sum(8) res[9] = fma52lo(res[9], a[4], a[5]); // Sum(9) res[10] = fma52hi(res[10], a[4], a[5]); // Sum(9) res[6] = fma52lo(res[6], a[0], a[6]); // Sum(6) res[7] = fma52hi(res[7], a[0], a[6]); // Sum(6) res[7] = fma52lo(res[7], a[1], a[6]); // Sum(7) res[8] = fma52hi(res[8], a[1], a[6]); // Sum(7) res[8] = fma52lo(res[8], a[2], a[6]); // Sum(8) res[9] = fma52hi(res[9], a[2], a[6]); // Sum(8) res[9] = fma52lo(res[9], a[3], a[6]); // Sum(9) res[10] = fma52hi(res[10], a[3], a[6]); // Sum(9) res[10] = fma52lo(res[10], a[4], a[6]); // Sum(10) res[11] = fma52hi(res[11], a[4], a[6]); // Sum(10) res[11] = fma52lo(res[11], a[5], a[6]); // Sum(11) res[12] = fma52hi(res[12], a[5], a[6]); // Sum(11) res[7] = fma52lo(res[7], a[0], a[7]); // Sum(7) res[8] = fma52hi(res[8], a[0], a[7]); // Sum(7) res[8] = fma52lo(res[8], a[1], a[7]); // Sum(8) res[9] = fma52hi(res[9], a[1], a[7]); // Sum(8) res[9] = fma52lo(res[9], a[2], a[7]); // Sum(9) res[10] = fma52hi(res[10], a[2], a[7]); // Sum(9) res[10] = fma52lo(res[10], a[3], a[7]); // Sum(10) res[11] = fma52hi(res[11], a[3], a[7]); // Sum(10) res[11] = fma52lo(res[11], a[4], a[7]); // Sum(11) res[12] = fma52hi(res[12], a[4], a[7]); // Sum(11) res[8] = fma52lo(res[8], a[0], a[8]); // Sum(8) res[9] = fma52hi(res[9], a[0], a[8]); // Sum(8) res[9] = fma52lo(res[9], a[1], a[8]); // Sum(9) res[10] = fma52hi(res[10], a[1], a[8]); // Sum(9) res[10] = fma52lo(res[10], a[2], a[8]); // Sum(10) res[11] = fma52hi(res[11], a[2], a[8]); // Sum(10) res[11] = fma52lo(res[11], a[3], a[8]); // Sum(11) res[12] = fma52hi(res[12], a[3], a[8]); // Sum(11) res[9] = fma52lo(res[9], a[0], a[9]); // Sum(9) res[10] = fma52hi(res[10], a[0], a[9]); // Sum(9) res[10] = fma52lo(res[10], a[1], a[9]); // Sum(10) res[11] = fma52hi(res[11], a[1], a[9]); // Sum(10) res[11] = fma52lo(res[11], a[2], a[9]); // Sum(11) res[12] = fma52hi(res[12], a[2], a[9]); // Sum(11) res[10] = fma52lo(res[10], a[0], a[10]); // Sum(10) res[11] = fma52hi(res[11], a[0], a[10]); // Sum(10) res[11] = fma52lo(res[11], a[1], a[10]); // Sum(11) res[12] = fma52hi(res[12], a[1], a[10]); // Sum(11) res[11] = fma52lo(res[11], a[0], a[11]); // Sum(11) res[12] = fma52hi(res[12], a[0], a[11]); // Sum(11) res[0] = add64(res[0], res[0]); // Double(0) res[1] = add64(res[1], res[1]); // Double(1) res[2] = add64(res[2], res[2]); // Double(2) res[3] = add64(res[3], res[3]); // Double(3) res[4] = add64(res[4], res[4]); // Double(4) res[5] = add64(res[5], res[5]); // Double(5) res[6] = add64(res[6], res[6]); // Double(6) res[7] = add64(res[7], res[7]); // Double(7) res[8] = add64(res[8], res[8]); // Double(8) res[9] = add64(res[9], res[9]); // Double(9) res[10] = add64(res[10], res[10]); // Double(10) res[11] = add64(res[11], res[11]); // Double(11) res[0] = fma52lo(res[0], a[0], a[0]); // Add sqr(0) res[1] = fma52hi(res[1], a[0], a[0]); // Add sqr(0) res[2] = fma52lo(res[2], a[1], a[1]); // Add sqr(2) res[3] = fma52hi(res[3], a[1], a[1]); // Add sqr(2) res[4] = fma52lo(res[4], a[2], a[2]); // Add sqr(4) res[5] = fma52hi(res[5], a[2], a[2]); // Add sqr(4) res[6] = fma52lo(res[6], a[3], a[3]); // Add sqr(6) res[7] = fma52hi(res[7], a[3], a[3]); // Add sqr(6) res[8] = fma52lo(res[8], a[4], a[4]); // Add sqr(8) res[9] = fma52hi(res[9], a[4], a[4]); // Add sqr(8) res[10] = fma52lo(res[10], a[5], a[5]); // Add sqr(10) res[11] = fma52hi(res[11], a[5], a[5]); // Add sqr(10) res[12] = fma52lo(res[12], a[5], a[7]); // Sum(12) res[13] = fma52hi(res[13], a[5], a[7]); // Sum(12) res[13] = fma52lo(res[13], a[6], a[7]); // Sum(13) res[14] = fma52hi(res[14], a[6], a[7]); // Sum(13) res[12] = fma52lo(res[12], a[4], a[8]); // Sum(12) res[13] = fma52hi(res[13], a[4], a[8]); // Sum(12) res[13] = fma52lo(res[13], a[5], a[8]); // Sum(13) res[14] = fma52hi(res[14], a[5], a[8]); // Sum(13) res[14] = fma52lo(res[14], a[6], a[8]); // Sum(14) res[15] = fma52hi(res[15], a[6], a[8]); // Sum(14) res[15] = fma52lo(res[15], a[7], a[8]); // Sum(15) res[16] = fma52hi(res[16], a[7], a[8]); // Sum(15) res[12] = fma52lo(res[12], a[3], a[9]); // Sum(12) res[13] = fma52hi(res[13], a[3], a[9]); // Sum(12) res[13] = fma52lo(res[13], a[4], a[9]); // Sum(13) res[14] = fma52hi(res[14], a[4], a[9]); // Sum(13) res[14] = fma52lo(res[14], a[5], a[9]); // Sum(14) res[15] = fma52hi(res[15], a[5], a[9]); // Sum(14) res[15] = fma52lo(res[15], a[6], a[9]); // Sum(15) res[16] = fma52hi(res[16], a[6], a[9]); // Sum(15) res[16] = fma52lo(res[16], a[7], a[9]); // Sum(16) res[17] = fma52hi(res[17], a[7], a[9]); // Sum(16) res[17] = fma52lo(res[17], a[8], a[9]); // Sum(17) res[18] = fma52hi(res[18], a[8], a[9]); // Sum(17) res[12] = fma52lo(res[12], a[2], a[10]); // Sum(12) res[13] = fma52hi(res[13], a[2], a[10]); // Sum(12) res[13] = fma52lo(res[13], a[3], a[10]); // Sum(13) res[14] = fma52hi(res[14], a[3], a[10]); // Sum(13) res[14] = fma52lo(res[14], a[4], a[10]); // Sum(14) res[15] = fma52hi(res[15], a[4], a[10]); // Sum(14) res[15] = fma52lo(res[15], a[5], a[10]); // Sum(15) res[16] = fma52hi(res[16], a[5], a[10]); // Sum(15) res[16] = fma52lo(res[16], a[6], a[10]); // Sum(16) res[17] = fma52hi(res[17], a[6], a[10]); // Sum(16) res[17] = fma52lo(res[17], a[7], a[10]); // Sum(17) res[18] = fma52hi(res[18], a[7], a[10]); // Sum(17) res[18] = fma52lo(res[18], a[8], a[10]); // Sum(18) res[19] = fma52hi(res[19], a[8], a[10]); // Sum(18) res[19] = fma52lo(res[19], a[9], a[10]); // Sum(19) res[20] = fma52hi(res[20], a[9], a[10]); // Sum(19) res[12] = fma52lo(res[12], a[1], a[11]); // Sum(12) res[13] = fma52hi(res[13], a[1], a[11]); // Sum(12) res[13] = fma52lo(res[13], a[2], a[11]); // Sum(13) res[14] = fma52hi(res[14], a[2], a[11]); // Sum(13) res[14] = fma52lo(res[14], a[3], a[11]); // Sum(14) res[15] = fma52hi(res[15], a[3], a[11]); // Sum(14) res[15] = fma52lo(res[15], a[4], a[11]); // Sum(15) res[16] = fma52hi(res[16], a[4], a[11]); // Sum(15) res[16] = fma52lo(res[16], a[5], a[11]); // Sum(16) res[17] = fma52hi(res[17], a[5], a[11]); // Sum(16) res[17] = fma52lo(res[17], a[6], a[11]); // Sum(17) res[18] = fma52hi(res[18], a[6], a[11]); // Sum(17) res[18] = fma52lo(res[18], a[7], a[11]); // Sum(18) res[19] = fma52hi(res[19], a[7], a[11]); // Sum(18) res[19] = fma52lo(res[19], a[8], a[11]); // Sum(19) res[20] = fma52hi(res[20], a[8], a[11]); // Sum(19) res[20] = fma52lo(res[20], a[9], a[11]); // Sum(20) res[21] = fma52hi(res[21], a[9], a[11]); // Sum(20) res[21] = fma52lo(res[21], a[10], a[11]); // Sum(21) res[22] = fma52hi(res[22], a[10], a[11]); // Sum(21) res[12] = fma52lo(res[12], a[0], a[12]); // Sum(12) res[13] = fma52hi(res[13], a[0], a[12]); // Sum(12) res[13] = fma52lo(res[13], a[1], a[12]); // Sum(13) res[14] = fma52hi(res[14], a[1], a[12]); // Sum(13) res[14] = fma52lo(res[14], a[2], a[12]); // Sum(14) res[15] = fma52hi(res[15], a[2], a[12]); // Sum(14) res[15] = fma52lo(res[15], a[3], a[12]); // Sum(15) res[16] = fma52hi(res[16], a[3], a[12]); // Sum(15) res[16] = fma52lo(res[16], a[4], a[12]); // Sum(16) res[17] = fma52hi(res[17], a[4], a[12]); // Sum(16) res[17] = fma52lo(res[17], a[5], a[12]); // Sum(17) res[18] = fma52hi(res[18], a[5], a[12]); // Sum(17) res[18] = fma52lo(res[18], a[6], a[12]); // Sum(18) res[19] = fma52hi(res[19], a[6], a[12]); // Sum(18) res[19] = fma52lo(res[19], a[7], a[12]); // Sum(19) res[20] = fma52hi(res[20], a[7], a[12]); // Sum(19) res[20] = fma52lo(res[20], a[8], a[12]); // Sum(20) res[21] = fma52hi(res[21], a[8], a[12]); // Sum(20) res[21] = fma52lo(res[21], a[9], a[12]); // Sum(21) res[22] = fma52hi(res[22], a[9], a[12]); // Sum(21) res[22] = fma52lo(res[22], a[10], a[12]); // Sum(22) res[23] = fma52hi(res[23], a[10], a[12]); // Sum(22) res[23] = fma52lo(res[23], a[11], a[12]); // Sum(23) res[24] = fma52hi(res[24], a[11], a[12]); // Sum(23) res[13] = fma52lo(res[13], a[0], a[13]); // Sum(13) res[14] = fma52hi(res[14], a[0], a[13]); // Sum(13) res[14] = fma52lo(res[14], a[1], a[13]); // Sum(14) res[15] = fma52hi(res[15], a[1], a[13]); // Sum(14) res[15] = fma52lo(res[15], a[2], a[13]); // Sum(15) res[16] = fma52hi(res[16], a[2], a[13]); // Sum(15) res[16] = fma52lo(res[16], a[3], a[13]); // Sum(16) res[17] = fma52hi(res[17], a[3], a[13]); // Sum(16) res[17] = fma52lo(res[17], a[4], a[13]); // Sum(17) res[18] = fma52hi(res[18], a[4], a[13]); // Sum(17) res[18] = fma52lo(res[18], a[5], a[13]); // Sum(18) res[19] = fma52hi(res[19], a[5], a[13]); // Sum(18) res[19] = fma52lo(res[19], a[6], a[13]); // Sum(19) res[20] = fma52hi(res[20], a[6], a[13]); // Sum(19) res[20] = fma52lo(res[20], a[7], a[13]); // Sum(20) res[21] = fma52hi(res[21], a[7], a[13]); // Sum(20) res[21] = fma52lo(res[21], a[8], a[13]); // Sum(21) res[22] = fma52hi(res[22], a[8], a[13]); // Sum(21) res[22] = fma52lo(res[22], a[9], a[13]); // Sum(22) res[23] = fma52hi(res[23], a[9], a[13]); // Sum(22) res[23] = fma52lo(res[23], a[10], a[13]); // Sum(23) res[24] = fma52hi(res[24], a[10], a[13]); // Sum(23) res[14] = fma52lo(res[14], a[0], a[14]); // Sum(14) res[15] = fma52hi(res[15], a[0], a[14]); // Sum(14) res[15] = fma52lo(res[15], a[1], a[14]); // Sum(15) res[16] = fma52hi(res[16], a[1], a[14]); // Sum(15) res[16] = fma52lo(res[16], a[2], a[14]); // Sum(16) res[17] = fma52hi(res[17], a[2], a[14]); // Sum(16) res[17] = fma52lo(res[17], a[3], a[14]); // Sum(17) res[18] = fma52hi(res[18], a[3], a[14]); // Sum(17) res[18] = fma52lo(res[18], a[4], a[14]); // Sum(18) res[19] = fma52hi(res[19], a[4], a[14]); // Sum(18) res[19] = fma52lo(res[19], a[5], a[14]); // Sum(19) res[20] = fma52hi(res[20], a[5], a[14]); // Sum(19) res[20] = fma52lo(res[20], a[6], a[14]); // Sum(20) res[21] = fma52hi(res[21], a[6], a[14]); // Sum(20) res[21] = fma52lo(res[21], a[7], a[14]); // Sum(21) res[22] = fma52hi(res[22], a[7], a[14]); // Sum(21) res[22] = fma52lo(res[22], a[8], a[14]); // Sum(22) res[23] = fma52hi(res[23], a[8], a[14]); // Sum(22) res[23] = fma52lo(res[23], a[9], a[14]); // Sum(23) res[24] = fma52hi(res[24], a[9], a[14]); // Sum(23) res[15] = fma52lo(res[15], a[0], a[15]); // Sum(15) res[16] = fma52hi(res[16], a[0], a[15]); // Sum(15) res[16] = fma52lo(res[16], a[1], a[15]); // Sum(16) res[17] = fma52hi(res[17], a[1], a[15]); // Sum(16) res[17] = fma52lo(res[17], a[2], a[15]); // Sum(17) res[18] = fma52hi(res[18], a[2], a[15]); // Sum(17) res[18] = fma52lo(res[18], a[3], a[15]); // Sum(18) res[19] = fma52hi(res[19], a[3], a[15]); // Sum(18) res[19] = fma52lo(res[19], a[4], a[15]); // Sum(19) res[20] = fma52hi(res[20], a[4], a[15]); // Sum(19) res[20] = fma52lo(res[20], a[5], a[15]); // Sum(20) res[21] = fma52hi(res[21], a[5], a[15]); // Sum(20) res[21] = fma52lo(res[21], a[6], a[15]); // Sum(21) res[22] = fma52hi(res[22], a[6], a[15]); // Sum(21) res[22] = fma52lo(res[22], a[7], a[15]); // Sum(22) res[23] = fma52hi(res[23], a[7], a[15]); // Sum(22) res[23] = fma52lo(res[23], a[8], a[15]); // Sum(23) res[24] = fma52hi(res[24], a[8], a[15]); // Sum(23) res[16] = fma52lo(res[16], a[0], a[16]); // Sum(16) res[17] = fma52hi(res[17], a[0], a[16]); // Sum(16) res[17] = fma52lo(res[17], a[1], a[16]); // Sum(17) res[18] = fma52hi(res[18], a[1], a[16]); // Sum(17) res[18] = fma52lo(res[18], a[2], a[16]); // Sum(18) res[19] = fma52hi(res[19], a[2], a[16]); // Sum(18) res[19] = fma52lo(res[19], a[3], a[16]); // Sum(19) res[20] = fma52hi(res[20], a[3], a[16]); // Sum(19) res[20] = fma52lo(res[20], a[4], a[16]); // Sum(20) res[21] = fma52hi(res[21], a[4], a[16]); // Sum(20) res[21] = fma52lo(res[21], a[5], a[16]); // Sum(21) res[22] = fma52hi(res[22], a[5], a[16]); // Sum(21) res[22] = fma52lo(res[22], a[6], a[16]); // Sum(22) res[23] = fma52hi(res[23], a[6], a[16]); // Sum(22) res[23] = fma52lo(res[23], a[7], a[16]); // Sum(23) res[24] = fma52hi(res[24], a[7], a[16]); // Sum(23) res[17] = fma52lo(res[17], a[0], a[17]); // Sum(17) res[18] = fma52hi(res[18], a[0], a[17]); // Sum(17) res[18] = fma52lo(res[18], a[1], a[17]); // Sum(18) res[19] = fma52hi(res[19], a[1], a[17]); // Sum(18) res[19] = fma52lo(res[19], a[2], a[17]); // Sum(19) res[20] = fma52hi(res[20], a[2], a[17]); // Sum(19) res[20] = fma52lo(res[20], a[3], a[17]); // Sum(20) res[21] = fma52hi(res[21], a[3], a[17]); // Sum(20) res[21] = fma52lo(res[21], a[4], a[17]); // Sum(21) res[22] = fma52hi(res[22], a[4], a[17]); // Sum(21) res[22] = fma52lo(res[22], a[5], a[17]); // Sum(22) res[23] = fma52hi(res[23], a[5], a[17]); // Sum(22) res[23] = fma52lo(res[23], a[6], a[17]); // Sum(23) res[24] = fma52hi(res[24], a[6], a[17]); // Sum(23) res[18] = fma52lo(res[18], a[0], a[18]); // Sum(18) res[19] = fma52hi(res[19], a[0], a[18]); // Sum(18) res[19] = fma52lo(res[19], a[1], a[18]); // Sum(19) res[20] = fma52hi(res[20], a[1], a[18]); // Sum(19) res[20] = fma52lo(res[20], a[2], a[18]); // Sum(20) res[21] = fma52hi(res[21], a[2], a[18]); // Sum(20) res[21] = fma52lo(res[21], a[3], a[18]); // Sum(21) res[22] = fma52hi(res[22], a[3], a[18]); // Sum(21) res[22] = fma52lo(res[22], a[4], a[18]); // Sum(22) res[23] = fma52hi(res[23], a[4], a[18]); // Sum(22) res[23] = fma52lo(res[23], a[5], a[18]); // Sum(23) res[24] = fma52hi(res[24], a[5], a[18]); // Sum(23) res[19] = fma52lo(res[19], a[0], a[19]); // Sum(19) res[20] = fma52hi(res[20], a[0], a[19]); // Sum(19) res[20] = fma52lo(res[20], a[1], a[19]); // Sum(20) res[21] = fma52hi(res[21], a[1], a[19]); // Sum(20) res[21] = fma52lo(res[21], a[2], a[19]); // Sum(21) res[22] = fma52hi(res[22], a[2], a[19]); // Sum(21) res[22] = fma52lo(res[22], a[3], a[19]); // Sum(22) res[23] = fma52hi(res[23], a[3], a[19]); // Sum(22) res[23] = fma52lo(res[23], a[4], a[19]); // Sum(23) res[24] = fma52hi(res[24], a[4], a[19]); // Sum(23) res[20] = fma52lo(res[20], a[0], a[20]); // Sum(20) res[21] = fma52hi(res[21], a[0], a[20]); // Sum(20) res[21] = fma52lo(res[21], a[1], a[20]); // Sum(21) res[22] = fma52hi(res[22], a[1], a[20]); // Sum(21) res[22] = fma52lo(res[22], a[2], a[20]); // Sum(22) res[23] = fma52hi(res[23], a[2], a[20]); // Sum(22) res[23] = fma52lo(res[23], a[3], a[20]); // Sum(23) res[24] = fma52hi(res[24], a[3], a[20]); // Sum(23) res[21] = fma52lo(res[21], a[0], a[21]); // Sum(21) res[22] = fma52hi(res[22], a[0], a[21]); // Sum(21) res[22] = fma52lo(res[22], a[1], a[21]); // Sum(22) res[23] = fma52hi(res[23], a[1], a[21]); // Sum(22) res[23] = fma52lo(res[23], a[2], a[21]); // Sum(23) res[24] = fma52hi(res[24], a[2], a[21]); // Sum(23) res[22] = fma52lo(res[22], a[0], a[22]); // Sum(22) res[23] = fma52hi(res[23], a[0], a[22]); // Sum(22) res[23] = fma52lo(res[23], a[1], a[22]); // Sum(23) res[24] = fma52hi(res[24], a[1], a[22]); // Sum(23) res[23] = fma52lo(res[23], a[0], a[23]); // Sum(23) res[24] = fma52hi(res[24], a[0], a[23]); // Sum(23) res[12] = add64(res[12], res[12]); // Double(12) res[13] = add64(res[13], res[13]); // Double(13) res[14] = add64(res[14], res[14]); // Double(14) res[15] = add64(res[15], res[15]); // Double(15) res[16] = add64(res[16], res[16]); // Double(16) res[17] = add64(res[17], res[17]); // Double(17) res[18] = add64(res[18], res[18]); // Double(18) res[19] = add64(res[19], res[19]); // Double(19) res[20] = add64(res[20], res[20]); // Double(20) res[21] = add64(res[21], res[21]); // Double(21) res[22] = add64(res[22], res[22]); // Double(22) res[23] = add64(res[23], res[23]); // Double(23) res[12] = fma52lo(res[12], a[6], a[6]); // Add sqr(12) res[13] = fma52hi(res[13], a[6], a[6]); // Add sqr(12) res[14] = fma52lo(res[14], a[7], a[7]); // Add sqr(14) res[15] = fma52hi(res[15], a[7], a[7]); // Add sqr(14) res[16] = fma52lo(res[16], a[8], a[8]); // Add sqr(16) res[17] = fma52hi(res[17], a[8], a[8]); // Add sqr(16) res[18] = fma52lo(res[18], a[9], a[9]); // Add sqr(18) res[19] = fma52hi(res[19], a[9], a[9]); // Add sqr(18) res[20] = fma52lo(res[20], a[10], a[10]); // Add sqr(20) res[21] = fma52hi(res[21], a[10], a[10]); // Add sqr(20) res[22] = fma52lo(res[22], a[11], a[11]); // Add sqr(22) res[23] = fma52hi(res[23], a[11], a[11]); // Add sqr(22) res[24] = fma52lo(res[24], a[11], a[13]); // Sum(24) res[25] = fma52hi(res[25], a[11], a[13]); // Sum(24) res[25] = fma52lo(res[25], a[12], a[13]); // Sum(25) res[26] = fma52hi(res[26], a[12], a[13]); // Sum(25) res[24] = fma52lo(res[24], a[10], a[14]); // Sum(24) res[25] = fma52hi(res[25], a[10], a[14]); // Sum(24) res[25] = fma52lo(res[25], a[11], a[14]); // Sum(25) res[26] = fma52hi(res[26], a[11], a[14]); // Sum(25) res[26] = fma52lo(res[26], a[12], a[14]); // Sum(26) res[27] = fma52hi(res[27], a[12], a[14]); // Sum(26) res[27] = fma52lo(res[27], a[13], a[14]); // Sum(27) res[28] = fma52hi(res[28], a[13], a[14]); // Sum(27) res[24] = fma52lo(res[24], a[9], a[15]); // Sum(24) res[25] = fma52hi(res[25], a[9], a[15]); // Sum(24) res[25] = fma52lo(res[25], a[10], a[15]); // Sum(25) res[26] = fma52hi(res[26], a[10], a[15]); // Sum(25) res[26] = fma52lo(res[26], a[11], a[15]); // Sum(26) res[27] = fma52hi(res[27], a[11], a[15]); // Sum(26) res[27] = fma52lo(res[27], a[12], a[15]); // Sum(27) res[28] = fma52hi(res[28], a[12], a[15]); // Sum(27) res[28] = fma52lo(res[28], a[13], a[15]); // Sum(28) res[29] = fma52hi(res[29], a[13], a[15]); // Sum(28) res[29] = fma52lo(res[29], a[14], a[15]); // Sum(29) res[30] = fma52hi(res[30], a[14], a[15]); // Sum(29) res[24] = fma52lo(res[24], a[8], a[16]); // Sum(24) res[25] = fma52hi(res[25], a[8], a[16]); // Sum(24) res[25] = fma52lo(res[25], a[9], a[16]); // Sum(25) res[26] = fma52hi(res[26], a[9], a[16]); // Sum(25) res[26] = fma52lo(res[26], a[10], a[16]); // Sum(26) res[27] = fma52hi(res[27], a[10], a[16]); // Sum(26) res[27] = fma52lo(res[27], a[11], a[16]); // Sum(27) res[28] = fma52hi(res[28], a[11], a[16]); // Sum(27) res[28] = fma52lo(res[28], a[12], a[16]); // Sum(28) res[29] = fma52hi(res[29], a[12], a[16]); // Sum(28) res[29] = fma52lo(res[29], a[13], a[16]); // Sum(29) res[30] = fma52hi(res[30], a[13], a[16]); // Sum(29) res[30] = fma52lo(res[30], a[14], a[16]); // Sum(30) res[31] = fma52hi(res[31], a[14], a[16]); // Sum(30) res[31] = fma52lo(res[31], a[15], a[16]); // Sum(31) res[32] = fma52hi(res[32], a[15], a[16]); // Sum(31) res[24] = fma52lo(res[24], a[7], a[17]); // Sum(24) res[25] = fma52hi(res[25], a[7], a[17]); // Sum(24) res[25] = fma52lo(res[25], a[8], a[17]); // Sum(25) res[26] = fma52hi(res[26], a[8], a[17]); // Sum(25) res[26] = fma52lo(res[26], a[9], a[17]); // Sum(26) res[27] = fma52hi(res[27], a[9], a[17]); // Sum(26) res[27] = fma52lo(res[27], a[10], a[17]); // Sum(27) res[28] = fma52hi(res[28], a[10], a[17]); // Sum(27) res[28] = fma52lo(res[28], a[11], a[17]); // Sum(28) res[29] = fma52hi(res[29], a[11], a[17]); // Sum(28) res[29] = fma52lo(res[29], a[12], a[17]); // Sum(29) res[30] = fma52hi(res[30], a[12], a[17]); // Sum(29) res[30] = fma52lo(res[30], a[13], a[17]); // Sum(30) res[31] = fma52hi(res[31], a[13], a[17]); // Sum(30) res[31] = fma52lo(res[31], a[14], a[17]); // Sum(31) res[32] = fma52hi(res[32], a[14], a[17]); // Sum(31) res[32] = fma52lo(res[32], a[15], a[17]); // Sum(32) res[33] = fma52hi(res[33], a[15], a[17]); // Sum(32) res[33] = fma52lo(res[33], a[16], a[17]); // Sum(33) res[34] = fma52hi(res[34], a[16], a[17]); // Sum(33) res[24] = fma52lo(res[24], a[6], a[18]); // Sum(24) res[25] = fma52hi(res[25], a[6], a[18]); // Sum(24) res[25] = fma52lo(res[25], a[7], a[18]); // Sum(25) res[26] = fma52hi(res[26], a[7], a[18]); // Sum(25) res[26] = fma52lo(res[26], a[8], a[18]); // Sum(26) res[27] = fma52hi(res[27], a[8], a[18]); // Sum(26) res[27] = fma52lo(res[27], a[9], a[18]); // Sum(27) res[28] = fma52hi(res[28], a[9], a[18]); // Sum(27) res[28] = fma52lo(res[28], a[10], a[18]); // Sum(28) res[29] = fma52hi(res[29], a[10], a[18]); // Sum(28) res[29] = fma52lo(res[29], a[11], a[18]); // Sum(29) res[30] = fma52hi(res[30], a[11], a[18]); // Sum(29) res[30] = fma52lo(res[30], a[12], a[18]); // Sum(30) res[31] = fma52hi(res[31], a[12], a[18]); // Sum(30) res[31] = fma52lo(res[31], a[13], a[18]); // Sum(31) res[32] = fma52hi(res[32], a[13], a[18]); // Sum(31) res[32] = fma52lo(res[32], a[14], a[18]); // Sum(32) res[33] = fma52hi(res[33], a[14], a[18]); // Sum(32) res[33] = fma52lo(res[33], a[15], a[18]); // Sum(33) res[34] = fma52hi(res[34], a[15], a[18]); // Sum(33) res[34] = fma52lo(res[34], a[16], a[18]); // Sum(34) res[35] = fma52hi(res[35], a[16], a[18]); // Sum(34) res[35] = fma52lo(res[35], a[17], a[18]); // Sum(35) res[36] = fma52hi(res[36], a[17], a[18]); // Sum(35) res[24] = fma52lo(res[24], a[5], a[19]); // Sum(24) res[25] = fma52hi(res[25], a[5], a[19]); // Sum(24) res[25] = fma52lo(res[25], a[6], a[19]); // Sum(25) res[26] = fma52hi(res[26], a[6], a[19]); // Sum(25) res[26] = fma52lo(res[26], a[7], a[19]); // Sum(26) res[27] = fma52hi(res[27], a[7], a[19]); // Sum(26) res[27] = fma52lo(res[27], a[8], a[19]); // Sum(27) res[28] = fma52hi(res[28], a[8], a[19]); // Sum(27) res[28] = fma52lo(res[28], a[9], a[19]); // Sum(28) res[29] = fma52hi(res[29], a[9], a[19]); // Sum(28) res[29] = fma52lo(res[29], a[10], a[19]); // Sum(29) res[30] = fma52hi(res[30], a[10], a[19]); // Sum(29) res[30] = fma52lo(res[30], a[11], a[19]); // Sum(30) res[31] = fma52hi(res[31], a[11], a[19]); // Sum(30) res[31] = fma52lo(res[31], a[12], a[19]); // Sum(31) res[32] = fma52hi(res[32], a[12], a[19]); // Sum(31) res[32] = fma52lo(res[32], a[13], a[19]); // Sum(32) res[33] = fma52hi(res[33], a[13], a[19]); // Sum(32) res[33] = fma52lo(res[33], a[14], a[19]); // Sum(33) res[34] = fma52hi(res[34], a[14], a[19]); // Sum(33) res[34] = fma52lo(res[34], a[15], a[19]); // Sum(34) res[35] = fma52hi(res[35], a[15], a[19]); // Sum(34) res[35] = fma52lo(res[35], a[16], a[19]); // Sum(35) res[36] = fma52hi(res[36], a[16], a[19]); // Sum(35) res[24] = fma52lo(res[24], a[4], a[20]); // Sum(24) res[25] = fma52hi(res[25], a[4], a[20]); // Sum(24) res[25] = fma52lo(res[25], a[5], a[20]); // Sum(25) res[26] = fma52hi(res[26], a[5], a[20]); // Sum(25) res[26] = fma52lo(res[26], a[6], a[20]); // Sum(26) res[27] = fma52hi(res[27], a[6], a[20]); // Sum(26) res[27] = fma52lo(res[27], a[7], a[20]); // Sum(27) res[28] = fma52hi(res[28], a[7], a[20]); // Sum(27) res[28] = fma52lo(res[28], a[8], a[20]); // Sum(28) res[29] = fma52hi(res[29], a[8], a[20]); // Sum(28) res[29] = fma52lo(res[29], a[9], a[20]); // Sum(29) res[30] = fma52hi(res[30], a[9], a[20]); // Sum(29) res[30] = fma52lo(res[30], a[10], a[20]); // Sum(30) res[31] = fma52hi(res[31], a[10], a[20]); // Sum(30) res[31] = fma52lo(res[31], a[11], a[20]); // Sum(31) res[32] = fma52hi(res[32], a[11], a[20]); // Sum(31) res[32] = fma52lo(res[32], a[12], a[20]); // Sum(32) res[33] = fma52hi(res[33], a[12], a[20]); // Sum(32) res[33] = fma52lo(res[33], a[13], a[20]); // Sum(33) res[34] = fma52hi(res[34], a[13], a[20]); // Sum(33) res[34] = fma52lo(res[34], a[14], a[20]); // Sum(34) res[35] = fma52hi(res[35], a[14], a[20]); // Sum(34) res[35] = fma52lo(res[35], a[15], a[20]); // Sum(35) res[36] = fma52hi(res[36], a[15], a[20]); // Sum(35) res[24] = fma52lo(res[24], a[3], a[21]); // Sum(24) res[25] = fma52hi(res[25], a[3], a[21]); // Sum(24) res[25] = fma52lo(res[25], a[4], a[21]); // Sum(25) res[26] = fma52hi(res[26], a[4], a[21]); // Sum(25) res[26] = fma52lo(res[26], a[5], a[21]); // Sum(26) res[27] = fma52hi(res[27], a[5], a[21]); // Sum(26) res[27] = fma52lo(res[27], a[6], a[21]); // Sum(27) res[28] = fma52hi(res[28], a[6], a[21]); // Sum(27) res[28] = fma52lo(res[28], a[7], a[21]); // Sum(28) res[29] = fma52hi(res[29], a[7], a[21]); // Sum(28) res[29] = fma52lo(res[29], a[8], a[21]); // Sum(29) res[30] = fma52hi(res[30], a[8], a[21]); // Sum(29) res[30] = fma52lo(res[30], a[9], a[21]); // Sum(30) res[31] = fma52hi(res[31], a[9], a[21]); // Sum(30) res[31] = fma52lo(res[31], a[10], a[21]); // Sum(31) res[32] = fma52hi(res[32], a[10], a[21]); // Sum(31) res[32] = fma52lo(res[32], a[11], a[21]); // Sum(32) res[33] = fma52hi(res[33], a[11], a[21]); // Sum(32) res[33] = fma52lo(res[33], a[12], a[21]); // Sum(33) res[34] = fma52hi(res[34], a[12], a[21]); // Sum(33) res[34] = fma52lo(res[34], a[13], a[21]); // Sum(34) res[35] = fma52hi(res[35], a[13], a[21]); // Sum(34) res[35] = fma52lo(res[35], a[14], a[21]); // Sum(35) res[36] = fma52hi(res[36], a[14], a[21]); // Sum(35) res[24] = fma52lo(res[24], a[2], a[22]); // Sum(24) res[25] = fma52hi(res[25], a[2], a[22]); // Sum(24) res[25] = fma52lo(res[25], a[3], a[22]); // Sum(25) res[26] = fma52hi(res[26], a[3], a[22]); // Sum(25) res[26] = fma52lo(res[26], a[4], a[22]); // Sum(26) res[27] = fma52hi(res[27], a[4], a[22]); // Sum(26) res[27] = fma52lo(res[27], a[5], a[22]); // Sum(27) res[28] = fma52hi(res[28], a[5], a[22]); // Sum(27) res[28] = fma52lo(res[28], a[6], a[22]); // Sum(28) res[29] = fma52hi(res[29], a[6], a[22]); // Sum(28) res[29] = fma52lo(res[29], a[7], a[22]); // Sum(29) res[30] = fma52hi(res[30], a[7], a[22]); // Sum(29) res[30] = fma52lo(res[30], a[8], a[22]); // Sum(30) res[31] = fma52hi(res[31], a[8], a[22]); // Sum(30) res[31] = fma52lo(res[31], a[9], a[22]); // Sum(31) res[32] = fma52hi(res[32], a[9], a[22]); // Sum(31) res[32] = fma52lo(res[32], a[10], a[22]); // Sum(32) res[33] = fma52hi(res[33], a[10], a[22]); // Sum(32) res[33] = fma52lo(res[33], a[11], a[22]); // Sum(33) res[34] = fma52hi(res[34], a[11], a[22]); // Sum(33) res[34] = fma52lo(res[34], a[12], a[22]); // Sum(34) res[35] = fma52hi(res[35], a[12], a[22]); // Sum(34) res[35] = fma52lo(res[35], a[13], a[22]); // Sum(35) res[36] = fma52hi(res[36], a[13], a[22]); // Sum(35) res[24] = fma52lo(res[24], a[1], a[23]); // Sum(24) res[25] = fma52hi(res[25], a[1], a[23]); // Sum(24) res[25] = fma52lo(res[25], a[2], a[23]); // Sum(25) res[26] = fma52hi(res[26], a[2], a[23]); // Sum(25) res[26] = fma52lo(res[26], a[3], a[23]); // Sum(26) res[27] = fma52hi(res[27], a[3], a[23]); // Sum(26) res[27] = fma52lo(res[27], a[4], a[23]); // Sum(27) res[28] = fma52hi(res[28], a[4], a[23]); // Sum(27) res[28] = fma52lo(res[28], a[5], a[23]); // Sum(28) res[29] = fma52hi(res[29], a[5], a[23]); // Sum(28) res[29] = fma52lo(res[29], a[6], a[23]); // Sum(29) res[30] = fma52hi(res[30], a[6], a[23]); // Sum(29) res[30] = fma52lo(res[30], a[7], a[23]); // Sum(30) res[31] = fma52hi(res[31], a[7], a[23]); // Sum(30) res[31] = fma52lo(res[31], a[8], a[23]); // Sum(31) res[32] = fma52hi(res[32], a[8], a[23]); // Sum(31) res[32] = fma52lo(res[32], a[9], a[23]); // Sum(32) res[33] = fma52hi(res[33], a[9], a[23]); // Sum(32) res[33] = fma52lo(res[33], a[10], a[23]); // Sum(33) res[34] = fma52hi(res[34], a[10], a[23]); // Sum(33) res[34] = fma52lo(res[34], a[11], a[23]); // Sum(34) res[35] = fma52hi(res[35], a[11], a[23]); // Sum(34) res[35] = fma52lo(res[35], a[12], a[23]); // Sum(35) res[36] = fma52hi(res[36], a[12], a[23]); // Sum(35) res[24] = fma52lo(res[24], a[0], a[24]); // Sum(24) res[25] = fma52hi(res[25], a[0], a[24]); // Sum(24) res[25] = fma52lo(res[25], a[1], a[24]); // Sum(25) res[26] = fma52hi(res[26], a[1], a[24]); // Sum(25) res[26] = fma52lo(res[26], a[2], a[24]); // Sum(26) res[27] = fma52hi(res[27], a[2], a[24]); // Sum(26) res[27] = fma52lo(res[27], a[3], a[24]); // Sum(27) res[28] = fma52hi(res[28], a[3], a[24]); // Sum(27) res[28] = fma52lo(res[28], a[4], a[24]); // Sum(28) res[29] = fma52hi(res[29], a[4], a[24]); // Sum(28) res[29] = fma52lo(res[29], a[5], a[24]); // Sum(29) res[30] = fma52hi(res[30], a[5], a[24]); // Sum(29) res[30] = fma52lo(res[30], a[6], a[24]); // Sum(30) res[31] = fma52hi(res[31], a[6], a[24]); // Sum(30) res[31] = fma52lo(res[31], a[7], a[24]); // Sum(31) res[32] = fma52hi(res[32], a[7], a[24]); // Sum(31) res[32] = fma52lo(res[32], a[8], a[24]); // Sum(32) res[33] = fma52hi(res[33], a[8], a[24]); // Sum(32) res[33] = fma52lo(res[33], a[9], a[24]); // Sum(33) res[34] = fma52hi(res[34], a[9], a[24]); // Sum(33) res[34] = fma52lo(res[34], a[10], a[24]); // Sum(34) res[35] = fma52hi(res[35], a[10], a[24]); // Sum(34) res[35] = fma52lo(res[35], a[11], a[24]); // Sum(35) res[36] = fma52hi(res[36], a[11], a[24]); // Sum(35) res[25] = fma52lo(res[25], a[0], a[25]); // Sum(25) res[26] = fma52hi(res[26], a[0], a[25]); // Sum(25) res[26] = fma52lo(res[26], a[1], a[25]); // Sum(26) res[27] = fma52hi(res[27], a[1], a[25]); // Sum(26) res[27] = fma52lo(res[27], a[2], a[25]); // Sum(27) res[28] = fma52hi(res[28], a[2], a[25]); // Sum(27) res[28] = fma52lo(res[28], a[3], a[25]); // Sum(28) res[29] = fma52hi(res[29], a[3], a[25]); // Sum(28) res[29] = fma52lo(res[29], a[4], a[25]); // Sum(29) res[30] = fma52hi(res[30], a[4], a[25]); // Sum(29) res[30] = fma52lo(res[30], a[5], a[25]); // Sum(30) res[31] = fma52hi(res[31], a[5], a[25]); // Sum(30) res[31] = fma52lo(res[31], a[6], a[25]); // Sum(31) res[32] = fma52hi(res[32], a[6], a[25]); // Sum(31) res[32] = fma52lo(res[32], a[7], a[25]); // Sum(32) res[33] = fma52hi(res[33], a[7], a[25]); // Sum(32) res[33] = fma52lo(res[33], a[8], a[25]); // Sum(33) res[34] = fma52hi(res[34], a[8], a[25]); // Sum(33) res[34] = fma52lo(res[34], a[9], a[25]); // Sum(34) res[35] = fma52hi(res[35], a[9], a[25]); // Sum(34) res[35] = fma52lo(res[35], a[10], a[25]); // Sum(35) res[36] = fma52hi(res[36], a[10], a[25]); // Sum(35) res[26] = fma52lo(res[26], a[0], a[26]); // Sum(26) res[27] = fma52hi(res[27], a[0], a[26]); // Sum(26) res[27] = fma52lo(res[27], a[1], a[26]); // Sum(27) res[28] = fma52hi(res[28], a[1], a[26]); // Sum(27) res[28] = fma52lo(res[28], a[2], a[26]); // Sum(28) res[29] = fma52hi(res[29], a[2], a[26]); // Sum(28) res[29] = fma52lo(res[29], a[3], a[26]); // Sum(29) res[30] = fma52hi(res[30], a[3], a[26]); // Sum(29) res[30] = fma52lo(res[30], a[4], a[26]); // Sum(30) res[31] = fma52hi(res[31], a[4], a[26]); // Sum(30) res[31] = fma52lo(res[31], a[5], a[26]); // Sum(31) res[32] = fma52hi(res[32], a[5], a[26]); // Sum(31) res[32] = fma52lo(res[32], a[6], a[26]); // Sum(32) res[33] = fma52hi(res[33], a[6], a[26]); // Sum(32) res[33] = fma52lo(res[33], a[7], a[26]); // Sum(33) res[34] = fma52hi(res[34], a[7], a[26]); // Sum(33) res[34] = fma52lo(res[34], a[8], a[26]); // Sum(34) res[35] = fma52hi(res[35], a[8], a[26]); // Sum(34) res[35] = fma52lo(res[35], a[9], a[26]); // Sum(35) res[36] = fma52hi(res[36], a[9], a[26]); // Sum(35) res[27] = fma52lo(res[27], a[0], a[27]); // Sum(27) res[28] = fma52hi(res[28], a[0], a[27]); // Sum(27) res[28] = fma52lo(res[28], a[1], a[27]); // Sum(28) res[29] = fma52hi(res[29], a[1], a[27]); // Sum(28) res[29] = fma52lo(res[29], a[2], a[27]); // Sum(29) res[30] = fma52hi(res[30], a[2], a[27]); // Sum(29) res[30] = fma52lo(res[30], a[3], a[27]); // Sum(30) res[31] = fma52hi(res[31], a[3], a[27]); // Sum(30) res[31] = fma52lo(res[31], a[4], a[27]); // Sum(31) res[32] = fma52hi(res[32], a[4], a[27]); // Sum(31) res[32] = fma52lo(res[32], a[5], a[27]); // Sum(32) res[33] = fma52hi(res[33], a[5], a[27]); // Sum(32) res[33] = fma52lo(res[33], a[6], a[27]); // Sum(33) res[34] = fma52hi(res[34], a[6], a[27]); // Sum(33) res[34] = fma52lo(res[34], a[7], a[27]); // Sum(34) res[35] = fma52hi(res[35], a[7], a[27]); // Sum(34) res[35] = fma52lo(res[35], a[8], a[27]); // Sum(35) res[36] = fma52hi(res[36], a[8], a[27]); // Sum(35) res[28] = fma52lo(res[28], a[0], a[28]); // Sum(28) res[29] = fma52hi(res[29], a[0], a[28]); // Sum(28) res[29] = fma52lo(res[29], a[1], a[28]); // Sum(29) res[30] = fma52hi(res[30], a[1], a[28]); // Sum(29) res[30] = fma52lo(res[30], a[2], a[28]); // Sum(30) res[31] = fma52hi(res[31], a[2], a[28]); // Sum(30) res[31] = fma52lo(res[31], a[3], a[28]); // Sum(31) res[32] = fma52hi(res[32], a[3], a[28]); // Sum(31) res[32] = fma52lo(res[32], a[4], a[28]); // Sum(32) res[33] = fma52hi(res[33], a[4], a[28]); // Sum(32) res[33] = fma52lo(res[33], a[5], a[28]); // Sum(33) res[34] = fma52hi(res[34], a[5], a[28]); // Sum(33) res[34] = fma52lo(res[34], a[6], a[28]); // Sum(34) res[35] = fma52hi(res[35], a[6], a[28]); // Sum(34) res[35] = fma52lo(res[35], a[7], a[28]); // Sum(35) res[36] = fma52hi(res[36], a[7], a[28]); // Sum(35) res[29] = fma52lo(res[29], a[0], a[29]); // Sum(29) res[30] = fma52hi(res[30], a[0], a[29]); // Sum(29) res[30] = fma52lo(res[30], a[1], a[29]); // Sum(30) res[31] = fma52hi(res[31], a[1], a[29]); // Sum(30) res[31] = fma52lo(res[31], a[2], a[29]); // Sum(31) res[32] = fma52hi(res[32], a[2], a[29]); // Sum(31) res[32] = fma52lo(res[32], a[3], a[29]); // Sum(32) res[33] = fma52hi(res[33], a[3], a[29]); // Sum(32) res[33] = fma52lo(res[33], a[4], a[29]); // Sum(33) res[34] = fma52hi(res[34], a[4], a[29]); // Sum(33) res[34] = fma52lo(res[34], a[5], a[29]); // Sum(34) res[35] = fma52hi(res[35], a[5], a[29]); // Sum(34) res[35] = fma52lo(res[35], a[6], a[29]); // Sum(35) res[36] = fma52hi(res[36], a[6], a[29]); // Sum(35) res[24] = add64(res[24], res[24]); // Double(24) res[25] = add64(res[25], res[25]); // Double(25) res[26] = add64(res[26], res[26]); // Double(26) res[27] = add64(res[27], res[27]); // Double(27) res[28] = add64(res[28], res[28]); // Double(28) res[29] = add64(res[29], res[29]); // Double(29) res[30] = add64(res[30], res[30]); // Double(30) res[31] = add64(res[31], res[31]); // Double(31) res[32] = add64(res[32], res[32]); // Double(32) res[33] = add64(res[33], res[33]); // Double(33) res[34] = add64(res[34], res[34]); // Double(34) res[35] = add64(res[35], res[35]); // Double(35) res[24] = fma52lo(res[24], a[12], a[12]); // Add sqr(24) res[25] = fma52hi(res[25], a[12], a[12]); // Add sqr(24) res[26] = fma52lo(res[26], a[13], a[13]); // Add sqr(26) res[27] = fma52hi(res[27], a[13], a[13]); // Add sqr(26) res[28] = fma52lo(res[28], a[14], a[14]); // Add sqr(28) res[29] = fma52hi(res[29], a[14], a[14]); // Add sqr(28) res[30] = fma52lo(res[30], a[15], a[15]); // Add sqr(30) res[31] = fma52hi(res[31], a[15], a[15]); // Add sqr(30) res[32] = fma52lo(res[32], a[16], a[16]); // Add sqr(32) res[33] = fma52hi(res[33], a[16], a[16]); // Add sqr(32) res[34] = fma52lo(res[34], a[17], a[17]); // Add sqr(34) res[35] = fma52hi(res[35], a[17], a[17]); // Add sqr(34) res[36] = fma52lo(res[36], a[17], a[19]); // Sum(36) res[37] = fma52hi(res[37], a[17], a[19]); // Sum(36) res[37] = fma52lo(res[37], a[18], a[19]); // Sum(37) res[38] = fma52hi(res[38], a[18], a[19]); // Sum(37) res[36] = fma52lo(res[36], a[16], a[20]); // Sum(36) res[37] = fma52hi(res[37], a[16], a[20]); // Sum(36) res[37] = fma52lo(res[37], a[17], a[20]); // Sum(37) res[38] = fma52hi(res[38], a[17], a[20]); // Sum(37) res[38] = fma52lo(res[38], a[18], a[20]); // Sum(38) res[39] = fma52hi(res[39], a[18], a[20]); // Sum(38) res[39] = fma52lo(res[39], a[19], a[20]); // Sum(39) res[40] = fma52hi(res[40], a[19], a[20]); // Sum(39) res[36] = fma52lo(res[36], a[15], a[21]); // Sum(36) res[37] = fma52hi(res[37], a[15], a[21]); // Sum(36) res[37] = fma52lo(res[37], a[16], a[21]); // Sum(37) res[38] = fma52hi(res[38], a[16], a[21]); // Sum(37) res[38] = fma52lo(res[38], a[17], a[21]); // Sum(38) res[39] = fma52hi(res[39], a[17], a[21]); // Sum(38) res[39] = fma52lo(res[39], a[18], a[21]); // Sum(39) res[40] = fma52hi(res[40], a[18], a[21]); // Sum(39) res[40] = fma52lo(res[40], a[19], a[21]); // Sum(40) res[41] = fma52hi(res[41], a[19], a[21]); // Sum(40) res[41] = fma52lo(res[41], a[20], a[21]); // Sum(41) res[42] = fma52hi(res[42], a[20], a[21]); // Sum(41) res[36] = fma52lo(res[36], a[14], a[22]); // Sum(36) res[37] = fma52hi(res[37], a[14], a[22]); // Sum(36) res[37] = fma52lo(res[37], a[15], a[22]); // Sum(37) res[38] = fma52hi(res[38], a[15], a[22]); // Sum(37) res[38] = fma52lo(res[38], a[16], a[22]); // Sum(38) res[39] = fma52hi(res[39], a[16], a[22]); // Sum(38) res[39] = fma52lo(res[39], a[17], a[22]); // Sum(39) res[40] = fma52hi(res[40], a[17], a[22]); // Sum(39) res[40] = fma52lo(res[40], a[18], a[22]); // Sum(40) res[41] = fma52hi(res[41], a[18], a[22]); // Sum(40) res[41] = fma52lo(res[41], a[19], a[22]); // Sum(41) res[42] = fma52hi(res[42], a[19], a[22]); // Sum(41) res[42] = fma52lo(res[42], a[20], a[22]); // Sum(42) res[43] = fma52hi(res[43], a[20], a[22]); // Sum(42) res[43] = fma52lo(res[43], a[21], a[22]); // Sum(43) res[44] = fma52hi(res[44], a[21], a[22]); // Sum(43) res[36] = fma52lo(res[36], a[13], a[23]); // Sum(36) res[37] = fma52hi(res[37], a[13], a[23]); // Sum(36) res[37] = fma52lo(res[37], a[14], a[23]); // Sum(37) res[38] = fma52hi(res[38], a[14], a[23]); // Sum(37) res[38] = fma52lo(res[38], a[15], a[23]); // Sum(38) res[39] = fma52hi(res[39], a[15], a[23]); // Sum(38) res[39] = fma52lo(res[39], a[16], a[23]); // Sum(39) res[40] = fma52hi(res[40], a[16], a[23]); // Sum(39) res[40] = fma52lo(res[40], a[17], a[23]); // Sum(40) res[41] = fma52hi(res[41], a[17], a[23]); // Sum(40) res[41] = fma52lo(res[41], a[18], a[23]); // Sum(41) res[42] = fma52hi(res[42], a[18], a[23]); // Sum(41) res[42] = fma52lo(res[42], a[19], a[23]); // Sum(42) res[43] = fma52hi(res[43], a[19], a[23]); // Sum(42) res[43] = fma52lo(res[43], a[20], a[23]); // Sum(43) res[44] = fma52hi(res[44], a[20], a[23]); // Sum(43) res[44] = fma52lo(res[44], a[21], a[23]); // Sum(44) res[45] = fma52hi(res[45], a[21], a[23]); // Sum(44) res[45] = fma52lo(res[45], a[22], a[23]); // Sum(45) res[46] = fma52hi(res[46], a[22], a[23]); // Sum(45) res[36] = fma52lo(res[36], a[12], a[24]); // Sum(36) res[37] = fma52hi(res[37], a[12], a[24]); // Sum(36) res[37] = fma52lo(res[37], a[13], a[24]); // Sum(37) res[38] = fma52hi(res[38], a[13], a[24]); // Sum(37) res[38] = fma52lo(res[38], a[14], a[24]); // Sum(38) res[39] = fma52hi(res[39], a[14], a[24]); // Sum(38) res[39] = fma52lo(res[39], a[15], a[24]); // Sum(39) res[40] = fma52hi(res[40], a[15], a[24]); // Sum(39) res[40] = fma52lo(res[40], a[16], a[24]); // Sum(40) res[41] = fma52hi(res[41], a[16], a[24]); // Sum(40) res[41] = fma52lo(res[41], a[17], a[24]); // Sum(41) res[42] = fma52hi(res[42], a[17], a[24]); // Sum(41) res[42] = fma52lo(res[42], a[18], a[24]); // Sum(42) res[43] = fma52hi(res[43], a[18], a[24]); // Sum(42) res[43] = fma52lo(res[43], a[19], a[24]); // Sum(43) res[44] = fma52hi(res[44], a[19], a[24]); // Sum(43) res[44] = fma52lo(res[44], a[20], a[24]); // Sum(44) res[45] = fma52hi(res[45], a[20], a[24]); // Sum(44) res[45] = fma52lo(res[45], a[21], a[24]); // Sum(45) res[46] = fma52hi(res[46], a[21], a[24]); // Sum(45) res[46] = fma52lo(res[46], a[22], a[24]); // Sum(46) res[47] = fma52hi(res[47], a[22], a[24]); // Sum(46) res[47] = fma52lo(res[47], a[23], a[24]); // Sum(47) res[48] = fma52hi(res[48], a[23], a[24]); // Sum(47) res[36] = fma52lo(res[36], a[11], a[25]); // Sum(36) res[37] = fma52hi(res[37], a[11], a[25]); // Sum(36) res[37] = fma52lo(res[37], a[12], a[25]); // Sum(37) res[38] = fma52hi(res[38], a[12], a[25]); // Sum(37) res[38] = fma52lo(res[38], a[13], a[25]); // Sum(38) res[39] = fma52hi(res[39], a[13], a[25]); // Sum(38) res[39] = fma52lo(res[39], a[14], a[25]); // Sum(39) res[40] = fma52hi(res[40], a[14], a[25]); // Sum(39) res[40] = fma52lo(res[40], a[15], a[25]); // Sum(40) res[41] = fma52hi(res[41], a[15], a[25]); // Sum(40) res[41] = fma52lo(res[41], a[16], a[25]); // Sum(41) res[42] = fma52hi(res[42], a[16], a[25]); // Sum(41) res[42] = fma52lo(res[42], a[17], a[25]); // Sum(42) res[43] = fma52hi(res[43], a[17], a[25]); // Sum(42) res[43] = fma52lo(res[43], a[18], a[25]); // Sum(43) res[44] = fma52hi(res[44], a[18], a[25]); // Sum(43) res[44] = fma52lo(res[44], a[19], a[25]); // Sum(44) res[45] = fma52hi(res[45], a[19], a[25]); // Sum(44) res[45] = fma52lo(res[45], a[20], a[25]); // Sum(45) res[46] = fma52hi(res[46], a[20], a[25]); // Sum(45) res[46] = fma52lo(res[46], a[21], a[25]); // Sum(46) res[47] = fma52hi(res[47], a[21], a[25]); // Sum(46) res[47] = fma52lo(res[47], a[22], a[25]); // Sum(47) res[48] = fma52hi(res[48], a[22], a[25]); // Sum(47) res[36] = fma52lo(res[36], a[10], a[26]); // Sum(36) res[37] = fma52hi(res[37], a[10], a[26]); // Sum(36) res[37] = fma52lo(res[37], a[11], a[26]); // Sum(37) res[38] = fma52hi(res[38], a[11], a[26]); // Sum(37) res[38] = fma52lo(res[38], a[12], a[26]); // Sum(38) res[39] = fma52hi(res[39], a[12], a[26]); // Sum(38) res[39] = fma52lo(res[39], a[13], a[26]); // Sum(39) res[40] = fma52hi(res[40], a[13], a[26]); // Sum(39) res[40] = fma52lo(res[40], a[14], a[26]); // Sum(40) res[41] = fma52hi(res[41], a[14], a[26]); // Sum(40) res[41] = fma52lo(res[41], a[15], a[26]); // Sum(41) res[42] = fma52hi(res[42], a[15], a[26]); // Sum(41) res[42] = fma52lo(res[42], a[16], a[26]); // Sum(42) res[43] = fma52hi(res[43], a[16], a[26]); // Sum(42) res[43] = fma52lo(res[43], a[17], a[26]); // Sum(43) res[44] = fma52hi(res[44], a[17], a[26]); // Sum(43) res[44] = fma52lo(res[44], a[18], a[26]); // Sum(44) res[45] = fma52hi(res[45], a[18], a[26]); // Sum(44) res[45] = fma52lo(res[45], a[19], a[26]); // Sum(45) res[46] = fma52hi(res[46], a[19], a[26]); // Sum(45) res[46] = fma52lo(res[46], a[20], a[26]); // Sum(46) res[47] = fma52hi(res[47], a[20], a[26]); // Sum(46) res[47] = fma52lo(res[47], a[21], a[26]); // Sum(47) res[48] = fma52hi(res[48], a[21], a[26]); // Sum(47) res[36] = fma52lo(res[36], a[9], a[27]); // Sum(36) res[37] = fma52hi(res[37], a[9], a[27]); // Sum(36) res[37] = fma52lo(res[37], a[10], a[27]); // Sum(37) res[38] = fma52hi(res[38], a[10], a[27]); // Sum(37) res[38] = fma52lo(res[38], a[11], a[27]); // Sum(38) res[39] = fma52hi(res[39], a[11], a[27]); // Sum(38) res[39] = fma52lo(res[39], a[12], a[27]); // Sum(39) res[40] = fma52hi(res[40], a[12], a[27]); // Sum(39) res[40] = fma52lo(res[40], a[13], a[27]); // Sum(40) res[41] = fma52hi(res[41], a[13], a[27]); // Sum(40) res[41] = fma52lo(res[41], a[14], a[27]); // Sum(41) res[42] = fma52hi(res[42], a[14], a[27]); // Sum(41) res[42] = fma52lo(res[42], a[15], a[27]); // Sum(42) res[43] = fma52hi(res[43], a[15], a[27]); // Sum(42) res[43] = fma52lo(res[43], a[16], a[27]); // Sum(43) res[44] = fma52hi(res[44], a[16], a[27]); // Sum(43) res[44] = fma52lo(res[44], a[17], a[27]); // Sum(44) res[45] = fma52hi(res[45], a[17], a[27]); // Sum(44) res[45] = fma52lo(res[45], a[18], a[27]); // Sum(45) res[46] = fma52hi(res[46], a[18], a[27]); // Sum(45) res[46] = fma52lo(res[46], a[19], a[27]); // Sum(46) res[47] = fma52hi(res[47], a[19], a[27]); // Sum(46) res[47] = fma52lo(res[47], a[20], a[27]); // Sum(47) res[48] = fma52hi(res[48], a[20], a[27]); // Sum(47) res[36] = fma52lo(res[36], a[8], a[28]); // Sum(36) res[37] = fma52hi(res[37], a[8], a[28]); // Sum(36) res[37] = fma52lo(res[37], a[9], a[28]); // Sum(37) res[38] = fma52hi(res[38], a[9], a[28]); // Sum(37) res[38] = fma52lo(res[38], a[10], a[28]); // Sum(38) res[39] = fma52hi(res[39], a[10], a[28]); // Sum(38) res[39] = fma52lo(res[39], a[11], a[28]); // Sum(39) res[40] = fma52hi(res[40], a[11], a[28]); // Sum(39) res[40] = fma52lo(res[40], a[12], a[28]); // Sum(40) res[41] = fma52hi(res[41], a[12], a[28]); // Sum(40) res[41] = fma52lo(res[41], a[13], a[28]); // Sum(41) res[42] = fma52hi(res[42], a[13], a[28]); // Sum(41) res[42] = fma52lo(res[42], a[14], a[28]); // Sum(42) res[43] = fma52hi(res[43], a[14], a[28]); // Sum(42) res[43] = fma52lo(res[43], a[15], a[28]); // Sum(43) res[44] = fma52hi(res[44], a[15], a[28]); // Sum(43) res[44] = fma52lo(res[44], a[16], a[28]); // Sum(44) res[45] = fma52hi(res[45], a[16], a[28]); // Sum(44) res[45] = fma52lo(res[45], a[17], a[28]); // Sum(45) res[46] = fma52hi(res[46], a[17], a[28]); // Sum(45) res[46] = fma52lo(res[46], a[18], a[28]); // Sum(46) res[47] = fma52hi(res[47], a[18], a[28]); // Sum(46) res[47] = fma52lo(res[47], a[19], a[28]); // Sum(47) res[48] = fma52hi(res[48], a[19], a[28]); // Sum(47) res[36] = fma52lo(res[36], a[7], a[29]); // Sum(36) res[37] = fma52hi(res[37], a[7], a[29]); // Sum(36) res[37] = fma52lo(res[37], a[8], a[29]); // Sum(37) res[38] = fma52hi(res[38], a[8], a[29]); // Sum(37) res[38] = fma52lo(res[38], a[9], a[29]); // Sum(38) res[39] = fma52hi(res[39], a[9], a[29]); // Sum(38) res[39] = fma52lo(res[39], a[10], a[29]); // Sum(39) res[40] = fma52hi(res[40], a[10], a[29]); // Sum(39) res[40] = fma52lo(res[40], a[11], a[29]); // Sum(40) res[41] = fma52hi(res[41], a[11], a[29]); // Sum(40) res[41] = fma52lo(res[41], a[12], a[29]); // Sum(41) res[42] = fma52hi(res[42], a[12], a[29]); // Sum(41) res[42] = fma52lo(res[42], a[13], a[29]); // Sum(42) res[43] = fma52hi(res[43], a[13], a[29]); // Sum(42) res[43] = fma52lo(res[43], a[14], a[29]); // Sum(43) res[44] = fma52hi(res[44], a[14], a[29]); // Sum(43) res[44] = fma52lo(res[44], a[15], a[29]); // Sum(44) res[45] = fma52hi(res[45], a[15], a[29]); // Sum(44) res[45] = fma52lo(res[45], a[16], a[29]); // Sum(45) res[46] = fma52hi(res[46], a[16], a[29]); // Sum(45) res[46] = fma52lo(res[46], a[17], a[29]); // Sum(46) res[47] = fma52hi(res[47], a[17], a[29]); // Sum(46) res[47] = fma52lo(res[47], a[18], a[29]); // Sum(47) res[48] = fma52hi(res[48], a[18], a[29]); // Sum(47) res[36] = add64(res[36], res[36]); // Double(36) res[37] = add64(res[37], res[37]); // Double(37) res[38] = add64(res[38], res[38]); // Double(38) res[39] = add64(res[39], res[39]); // Double(39) res[40] = add64(res[40], res[40]); // Double(40) res[41] = add64(res[41], res[41]); // Double(41) res[42] = add64(res[42], res[42]); // Double(42) res[43] = add64(res[43], res[43]); // Double(43) res[44] = add64(res[44], res[44]); // Double(44) res[45] = add64(res[45], res[45]); // Double(45) res[46] = add64(res[46], res[46]); // Double(46) res[47] = add64(res[47], res[47]); // Double(47) res[36] = fma52lo(res[36], a[18], a[18]); // Add sqr(36) res[37] = fma52hi(res[37], a[18], a[18]); // Add sqr(36) res[38] = fma52lo(res[38], a[19], a[19]); // Add sqr(38) res[39] = fma52hi(res[39], a[19], a[19]); // Add sqr(38) res[40] = fma52lo(res[40], a[20], a[20]); // Add sqr(40) res[41] = fma52hi(res[41], a[20], a[20]); // Add sqr(40) res[42] = fma52lo(res[42], a[21], a[21]); // Add sqr(42) res[43] = fma52hi(res[43], a[21], a[21]); // Add sqr(42) res[44] = fma52lo(res[44], a[22], a[22]); // Add sqr(44) res[45] = fma52hi(res[45], a[22], a[22]); // Add sqr(44) res[46] = fma52lo(res[46], a[23], a[23]); // Add sqr(46) res[47] = fma52hi(res[47], a[23], a[23]); // Add sqr(46) res[48] = fma52lo(res[48], a[23], a[25]); // Sum(48) res[49] = fma52hi(res[49], a[23], a[25]); // Sum(48) res[49] = fma52lo(res[49], a[24], a[25]); // Sum(49) res[50] = fma52hi(res[50], a[24], a[25]); // Sum(49) res[48] = fma52lo(res[48], a[22], a[26]); // Sum(48) res[49] = fma52hi(res[49], a[22], a[26]); // Sum(48) res[49] = fma52lo(res[49], a[23], a[26]); // Sum(49) res[50] = fma52hi(res[50], a[23], a[26]); // Sum(49) res[50] = fma52lo(res[50], a[24], a[26]); // Sum(50) res[51] = fma52hi(res[51], a[24], a[26]); // Sum(50) res[51] = fma52lo(res[51], a[25], a[26]); // Sum(51) res[52] = fma52hi(res[52], a[25], a[26]); // Sum(51) res[48] = fma52lo(res[48], a[21], a[27]); // Sum(48) res[49] = fma52hi(res[49], a[21], a[27]); // Sum(48) res[49] = fma52lo(res[49], a[22], a[27]); // Sum(49) res[50] = fma52hi(res[50], a[22], a[27]); // Sum(49) res[50] = fma52lo(res[50], a[23], a[27]); // Sum(50) res[51] = fma52hi(res[51], a[23], a[27]); // Sum(50) res[51] = fma52lo(res[51], a[24], a[27]); // Sum(51) res[52] = fma52hi(res[52], a[24], a[27]); // Sum(51) res[52] = fma52lo(res[52], a[25], a[27]); // Sum(52) res[53] = fma52hi(res[53], a[25], a[27]); // Sum(52) res[53] = fma52lo(res[53], a[26], a[27]); // Sum(53) res[54] = fma52hi(res[54], a[26], a[27]); // Sum(53) res[48] = fma52lo(res[48], a[20], a[28]); // Sum(48) res[49] = fma52hi(res[49], a[20], a[28]); // Sum(48) res[49] = fma52lo(res[49], a[21], a[28]); // Sum(49) res[50] = fma52hi(res[50], a[21], a[28]); // Sum(49) res[50] = fma52lo(res[50], a[22], a[28]); // Sum(50) res[51] = fma52hi(res[51], a[22], a[28]); // Sum(50) res[51] = fma52lo(res[51], a[23], a[28]); // Sum(51) res[52] = fma52hi(res[52], a[23], a[28]); // Sum(51) res[52] = fma52lo(res[52], a[24], a[28]); // Sum(52) res[53] = fma52hi(res[53], a[24], a[28]); // Sum(52) res[53] = fma52lo(res[53], a[25], a[28]); // Sum(53) res[54] = fma52hi(res[54], a[25], a[28]); // Sum(53) res[54] = fma52lo(res[54], a[26], a[28]); // Sum(54) res[55] = fma52hi(res[55], a[26], a[28]); // Sum(54) res[55] = fma52lo(res[55], a[27], a[28]); // Sum(55) res[56] = fma52hi(res[56], a[27], a[28]); // Sum(55) res[48] = fma52lo(res[48], a[19], a[29]); // Sum(48) res[49] = fma52hi(res[49], a[19], a[29]); // Sum(48) res[49] = fma52lo(res[49], a[20], a[29]); // Sum(49) res[50] = fma52hi(res[50], a[20], a[29]); // Sum(49) res[50] = fma52lo(res[50], a[21], a[29]); // Sum(50) res[51] = fma52hi(res[51], a[21], a[29]); // Sum(50) res[51] = fma52lo(res[51], a[22], a[29]); // Sum(51) res[52] = fma52hi(res[52], a[22], a[29]); // Sum(51) res[52] = fma52lo(res[52], a[23], a[29]); // Sum(52) res[53] = fma52hi(res[53], a[23], a[29]); // Sum(52) res[53] = fma52lo(res[53], a[24], a[29]); // Sum(53) res[54] = fma52hi(res[54], a[24], a[29]); // Sum(53) res[54] = fma52lo(res[54], a[25], a[29]); // Sum(54) res[55] = fma52hi(res[55], a[25], a[29]); // Sum(54) res[55] = fma52lo(res[55], a[26], a[29]); // Sum(55) res[56] = fma52hi(res[56], a[26], a[29]); // Sum(55) res[56] = fma52lo(res[56], a[27], a[29]); // Sum(56) res[57] = fma52hi(res[57], a[27], a[29]); // Sum(56) res[57] = fma52lo(res[57], a[28], a[29]); // Sum(57) res[58] = fma52hi(res[58], a[28], a[29]); // Sum(57) res[48] = add64(res[48], res[48]); // Double(48) res[49] = add64(res[49], res[49]); // Double(49) res[50] = add64(res[50], res[50]); // Double(50) res[51] = add64(res[51], res[51]); // Double(51) res[52] = add64(res[52], res[52]); // Double(52) res[53] = add64(res[53], res[53]); // Double(53) res[54] = add64(res[54], res[54]); // Double(54) res[55] = add64(res[55], res[55]); // Double(55) res[56] = add64(res[56], res[56]); // Double(56) res[57] = add64(res[57], res[57]); // Double(57) res[58] = add64(res[58], res[58]); // Double(58) res[48] = fma52lo(res[48], a[24], a[24]); // Add sqr(48) res[49] = fma52hi(res[49], a[24], a[24]); // Add sqr(48) res[50] = fma52lo(res[50], a[25], a[25]); // Add sqr(50) res[51] = fma52hi(res[51], a[25], a[25]); // Add sqr(50) res[52] = fma52lo(res[52], a[26], a[26]); // Add sqr(52) res[53] = fma52hi(res[53], a[26], a[26]); // Add sqr(52) res[54] = fma52lo(res[54], a[27], a[27]); // Add sqr(54) res[55] = fma52hi(res[55], a[27], a[27]); // Add sqr(54) res[56] = fma52lo(res[56], a[28], a[28]); // Add sqr(56) res[57] = fma52hi(res[57], a[28], a[28]); // Add sqr(56) res[58] = fma52lo(res[58], a[29], a[29]); // Add sqr(58) res[59] = fma52hi(res[59], a[29], a[29]); // Add sqr(58) // Montgomery Reduction int it; for (it = 0; it < 30; it += 10) { // Reduction step int jt = 0; if ((it + 0) > 0) res[it + 0] = add64(res[it + 0], srli64(res[it + -1], DIGIT_SIZE)); u[it + 0] = mul52lo(res[it + 0], k); res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + 1] = add64(res[it + 1], srli64(res[it + 0], DIGIT_SIZE)); u[it + 1] = mul52lo(res[it + 1], k); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + 2] = add64(res[it + 2], srli64(res[it + 1], DIGIT_SIZE)); u[it + 2] = mul52lo(res[it + 2], k); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + 3] = add64(res[it + 3], srli64(res[it + 2], DIGIT_SIZE)); u[it + 3] = mul52lo(res[it + 3], k); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + 4] = add64(res[it + 4], srli64(res[it + 3], DIGIT_SIZE)); u[it + 4] = mul52lo(res[it + 4], k); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + 5] = add64(res[it + 5], srli64(res[it + 4], DIGIT_SIZE)); u[it + 5] = mul52lo(res[it + 5], k); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + 6] = add64(res[it + 6], srli64(res[it + 5], DIGIT_SIZE)); u[it + 6] = mul52lo(res[it + 6], k); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + 7] = add64(res[it + 7], srli64(res[it + 6], DIGIT_SIZE)); u[it + 7] = mul52lo(res[it + 7], k); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + 8] = add64(res[it + 8], srli64(res[it + 7], DIGIT_SIZE)); u[it + 8] = mul52lo(res[it + 8], k); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + 9] = add64(res[it + 9], srli64(res[it + 8], DIGIT_SIZE)); u[it + 9] = mul52lo(res[it + 9], k); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); for (jt = 10; jt < 30; jt += 10) { // Poly tile res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); } } // Normalization res[30] = add64(res[30], srli64(res[29], DIGIT_SIZE)); r[0] = and64_const(res[30], DIGIT_MASK); res[31] = add64(res[31], srli64(res[30], DIGIT_SIZE)); r[1] = and64_const(res[31], DIGIT_MASK); res[32] = add64(res[32], srli64(res[31], DIGIT_SIZE)); r[2] = and64_const(res[32], DIGIT_MASK); res[33] = add64(res[33], srli64(res[32], DIGIT_SIZE)); r[3] = and64_const(res[33], DIGIT_MASK); res[34] = add64(res[34], srli64(res[33], DIGIT_SIZE)); r[4] = and64_const(res[34], DIGIT_MASK); res[35] = add64(res[35], srli64(res[34], DIGIT_SIZE)); r[5] = and64_const(res[35], DIGIT_MASK); res[36] = add64(res[36], srli64(res[35], DIGIT_SIZE)); r[6] = and64_const(res[36], DIGIT_MASK); res[37] = add64(res[37], srli64(res[36], DIGIT_SIZE)); r[7] = and64_const(res[37], DIGIT_MASK); res[38] = add64(res[38], srli64(res[37], DIGIT_SIZE)); r[8] = and64_const(res[38], DIGIT_MASK); res[39] = add64(res[39], srli64(res[38], DIGIT_SIZE)); r[9] = and64_const(res[39], DIGIT_MASK); res[40] = add64(res[40], srli64(res[39], DIGIT_SIZE)); r[10] = and64_const(res[40], DIGIT_MASK); res[41] = add64(res[41], srli64(res[40], DIGIT_SIZE)); r[11] = and64_const(res[41], DIGIT_MASK); res[42] = add64(res[42], srli64(res[41], DIGIT_SIZE)); r[12] = and64_const(res[42], DIGIT_MASK); res[43] = add64(res[43], srli64(res[42], DIGIT_SIZE)); r[13] = and64_const(res[43], DIGIT_MASK); res[44] = add64(res[44], srli64(res[43], DIGIT_SIZE)); r[14] = and64_const(res[44], DIGIT_MASK); res[45] = add64(res[45], srli64(res[44], DIGIT_SIZE)); r[15] = and64_const(res[45], DIGIT_MASK); res[46] = add64(res[46], srli64(res[45], DIGIT_SIZE)); r[16] = and64_const(res[46], DIGIT_MASK); res[47] = add64(res[47], srli64(res[46], DIGIT_SIZE)); r[17] = and64_const(res[47], DIGIT_MASK); res[48] = add64(res[48], srli64(res[47], DIGIT_SIZE)); r[18] = and64_const(res[48], DIGIT_MASK); res[49] = add64(res[49], srli64(res[48], DIGIT_SIZE)); r[19] = and64_const(res[49], DIGIT_MASK); res[50] = add64(res[50], srli64(res[49], DIGIT_SIZE)); r[20] = and64_const(res[50], DIGIT_MASK); res[51] = add64(res[51], srli64(res[50], DIGIT_SIZE)); r[21] = and64_const(res[51], DIGIT_MASK); res[52] = add64(res[52], srli64(res[51], DIGIT_SIZE)); r[22] = and64_const(res[52], DIGIT_MASK); res[53] = add64(res[53], srli64(res[52], DIGIT_SIZE)); r[23] = and64_const(res[53], DIGIT_MASK); res[54] = add64(res[54], srli64(res[53], DIGIT_SIZE)); r[24] = and64_const(res[54], DIGIT_MASK); res[55] = add64(res[55], srli64(res[54], DIGIT_SIZE)); r[25] = and64_const(res[55], DIGIT_MASK); res[56] = add64(res[56], srli64(res[55], DIGIT_SIZE)); r[26] = and64_const(res[56], DIGIT_MASK); res[57] = add64(res[57], srli64(res[56], DIGIT_SIZE)); r[27] = and64_const(res[57], DIGIT_MASK); res[58] = add64(res[58], srli64(res[57], DIGIT_SIZE)); r[28] = and64_const(res[58], DIGIT_MASK); res[59] = add64(res[59], srli64(res[58], DIGIT_SIZE)); r[29] = and64_const(res[59], DIGIT_MASK); } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams52x40_diagonal_mb8.c000066400000000000000000004066111470420105600345050ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void AMS52x40_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { __ALIGN64 U64 res[80]; __ALIGN64 U64 u[40]; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; k = loadu64((U64 *)k0_mb); int i; for (i = 0; i < 80; ++i) res[i] = get_zero64(); res[1] = fma52lo(res[1], a[0], a[1]); // Sum(1) res[2] = fma52hi(res[2], a[0], a[1]); // Sum(1) res[2] = fma52lo(res[2], a[0], a[2]); // Sum(2) res[3] = fma52hi(res[3], a[0], a[2]); // Sum(2) res[3] = fma52lo(res[3], a[1], a[2]); // Sum(3) res[4] = fma52hi(res[4], a[1], a[2]); // Sum(3) res[3] = fma52lo(res[3], a[0], a[3]); // Sum(3) res[4] = fma52hi(res[4], a[0], a[3]); // Sum(3) res[4] = fma52lo(res[4], a[1], a[3]); // Sum(4) res[5] = fma52hi(res[5], a[1], a[3]); // Sum(4) res[5] = fma52lo(res[5], a[2], a[3]); // Sum(5) res[6] = fma52hi(res[6], a[2], a[3]); // Sum(5) res[4] = fma52lo(res[4], a[0], a[4]); // Sum(4) res[5] = fma52hi(res[5], a[0], a[4]); // Sum(4) res[5] = fma52lo(res[5], a[1], a[4]); // Sum(5) res[6] = fma52hi(res[6], a[1], a[4]); // Sum(5) res[6] = fma52lo(res[6], a[2], a[4]); // Sum(6) res[7] = fma52hi(res[7], a[2], a[4]); // Sum(6) res[7] = fma52lo(res[7], a[3], a[4]); // Sum(7) res[8] = fma52hi(res[8], a[3], a[4]); // Sum(7) res[5] = fma52lo(res[5], a[0], a[5]); // Sum(5) res[6] = fma52hi(res[6], a[0], a[5]); // Sum(5) res[6] = fma52lo(res[6], a[1], a[5]); // Sum(6) res[7] = fma52hi(res[7], a[1], a[5]); // Sum(6) res[7] = fma52lo(res[7], a[2], a[5]); // Sum(7) res[8] = fma52hi(res[8], a[2], a[5]); // Sum(7) res[8] = fma52lo(res[8], a[3], a[5]); // Sum(8) res[9] = fma52hi(res[9], a[3], a[5]); // Sum(8) res[9] = fma52lo(res[9], a[4], a[5]); // Sum(9) res[10] = fma52hi(res[10], a[4], a[5]); // Sum(9) res[6] = fma52lo(res[6], a[0], a[6]); // Sum(6) res[7] = fma52hi(res[7], a[0], a[6]); // Sum(6) res[7] = fma52lo(res[7], a[1], a[6]); // Sum(7) res[8] = fma52hi(res[8], a[1], a[6]); // Sum(7) res[8] = fma52lo(res[8], a[2], a[6]); // Sum(8) res[9] = fma52hi(res[9], a[2], a[6]); // Sum(8) res[9] = fma52lo(res[9], a[3], a[6]); // Sum(9) res[10] = fma52hi(res[10], a[3], a[6]); // Sum(9) res[10] = fma52lo(res[10], a[4], a[6]); // Sum(10) res[11] = fma52hi(res[11], a[4], a[6]); // Sum(10) res[11] = fma52lo(res[11], a[5], a[6]); // Sum(11) res[12] = fma52hi(res[12], a[5], a[6]); // Sum(11) res[7] = fma52lo(res[7], a[0], a[7]); // Sum(7) res[8] = fma52hi(res[8], a[0], a[7]); // Sum(7) res[8] = fma52lo(res[8], a[1], a[7]); // Sum(8) res[9] = fma52hi(res[9], a[1], a[7]); // Sum(8) res[9] = fma52lo(res[9], a[2], a[7]); // Sum(9) res[10] = fma52hi(res[10], a[2], a[7]); // Sum(9) res[10] = fma52lo(res[10], a[3], a[7]); // Sum(10) res[11] = fma52hi(res[11], a[3], a[7]); // Sum(10) res[11] = fma52lo(res[11], a[4], a[7]); // Sum(11) res[12] = fma52hi(res[12], a[4], a[7]); // Sum(11) res[8] = fma52lo(res[8], a[0], a[8]); // Sum(8) res[9] = fma52hi(res[9], a[0], a[8]); // Sum(8) res[9] = fma52lo(res[9], a[1], a[8]); // Sum(9) res[10] = fma52hi(res[10], a[1], a[8]); // Sum(9) res[10] = fma52lo(res[10], a[2], a[8]); // Sum(10) res[11] = fma52hi(res[11], a[2], a[8]); // Sum(10) res[11] = fma52lo(res[11], a[3], a[8]); // Sum(11) res[12] = fma52hi(res[12], a[3], a[8]); // Sum(11) res[9] = fma52lo(res[9], a[0], a[9]); // Sum(9) res[10] = fma52hi(res[10], a[0], a[9]); // Sum(9) res[10] = fma52lo(res[10], a[1], a[9]); // Sum(10) res[11] = fma52hi(res[11], a[1], a[9]); // Sum(10) res[11] = fma52lo(res[11], a[2], a[9]); // Sum(11) res[12] = fma52hi(res[12], a[2], a[9]); // Sum(11) res[10] = fma52lo(res[10], a[0], a[10]); // Sum(10) res[11] = fma52hi(res[11], a[0], a[10]); // Sum(10) res[11] = fma52lo(res[11], a[1], a[10]); // Sum(11) res[12] = fma52hi(res[12], a[1], a[10]); // Sum(11) res[11] = fma52lo(res[11], a[0], a[11]); // Sum(11) res[12] = fma52hi(res[12], a[0], a[11]); // Sum(11) res[0] = add64(res[0], res[0]); // Double(0) res[1] = add64(res[1], res[1]); // Double(1) res[2] = add64(res[2], res[2]); // Double(2) res[3] = add64(res[3], res[3]); // Double(3) res[4] = add64(res[4], res[4]); // Double(4) res[5] = add64(res[5], res[5]); // Double(5) res[6] = add64(res[6], res[6]); // Double(6) res[7] = add64(res[7], res[7]); // Double(7) res[8] = add64(res[8], res[8]); // Double(8) res[9] = add64(res[9], res[9]); // Double(9) res[10] = add64(res[10], res[10]); // Double(10) res[11] = add64(res[11], res[11]); // Double(11) res[0] = fma52lo(res[0], a[0], a[0]); // Add sqr(0) res[1] = fma52hi(res[1], a[0], a[0]); // Add sqr(0) res[2] = fma52lo(res[2], a[1], a[1]); // Add sqr(2) res[3] = fma52hi(res[3], a[1], a[1]); // Add sqr(2) res[4] = fma52lo(res[4], a[2], a[2]); // Add sqr(4) res[5] = fma52hi(res[5], a[2], a[2]); // Add sqr(4) res[6] = fma52lo(res[6], a[3], a[3]); // Add sqr(6) res[7] = fma52hi(res[7], a[3], a[3]); // Add sqr(6) res[8] = fma52lo(res[8], a[4], a[4]); // Add sqr(8) res[9] = fma52hi(res[9], a[4], a[4]); // Add sqr(8) res[10] = fma52lo(res[10], a[5], a[5]); // Add sqr(10) res[11] = fma52hi(res[11], a[5], a[5]); // Add sqr(10) res[12] = fma52lo(res[12], a[5], a[7]); // Sum(12) res[13] = fma52hi(res[13], a[5], a[7]); // Sum(12) res[13] = fma52lo(res[13], a[6], a[7]); // Sum(13) res[14] = fma52hi(res[14], a[6], a[7]); // Sum(13) res[12] = fma52lo(res[12], a[4], a[8]); // Sum(12) res[13] = fma52hi(res[13], a[4], a[8]); // Sum(12) res[13] = fma52lo(res[13], a[5], a[8]); // Sum(13) res[14] = fma52hi(res[14], a[5], a[8]); // Sum(13) res[14] = fma52lo(res[14], a[6], a[8]); // Sum(14) res[15] = fma52hi(res[15], a[6], a[8]); // Sum(14) res[15] = fma52lo(res[15], a[7], a[8]); // Sum(15) res[16] = fma52hi(res[16], a[7], a[8]); // Sum(15) res[12] = fma52lo(res[12], a[3], a[9]); // Sum(12) res[13] = fma52hi(res[13], a[3], a[9]); // Sum(12) res[13] = fma52lo(res[13], a[4], a[9]); // Sum(13) res[14] = fma52hi(res[14], a[4], a[9]); // Sum(13) res[14] = fma52lo(res[14], a[5], a[9]); // Sum(14) res[15] = fma52hi(res[15], a[5], a[9]); // Sum(14) res[15] = fma52lo(res[15], a[6], a[9]); // Sum(15) res[16] = fma52hi(res[16], a[6], a[9]); // Sum(15) res[16] = fma52lo(res[16], a[7], a[9]); // Sum(16) res[17] = fma52hi(res[17], a[7], a[9]); // Sum(16) res[17] = fma52lo(res[17], a[8], a[9]); // Sum(17) res[18] = fma52hi(res[18], a[8], a[9]); // Sum(17) res[12] = fma52lo(res[12], a[2], a[10]); // Sum(12) res[13] = fma52hi(res[13], a[2], a[10]); // Sum(12) res[13] = fma52lo(res[13], a[3], a[10]); // Sum(13) res[14] = fma52hi(res[14], a[3], a[10]); // Sum(13) res[14] = fma52lo(res[14], a[4], a[10]); // Sum(14) res[15] = fma52hi(res[15], a[4], a[10]); // Sum(14) res[15] = fma52lo(res[15], a[5], a[10]); // Sum(15) res[16] = fma52hi(res[16], a[5], a[10]); // Sum(15) res[16] = fma52lo(res[16], a[6], a[10]); // Sum(16) res[17] = fma52hi(res[17], a[6], a[10]); // Sum(16) res[17] = fma52lo(res[17], a[7], a[10]); // Sum(17) res[18] = fma52hi(res[18], a[7], a[10]); // Sum(17) res[18] = fma52lo(res[18], a[8], a[10]); // Sum(18) res[19] = fma52hi(res[19], a[8], a[10]); // Sum(18) res[19] = fma52lo(res[19], a[9], a[10]); // Sum(19) res[20] = fma52hi(res[20], a[9], a[10]); // Sum(19) res[12] = fma52lo(res[12], a[1], a[11]); // Sum(12) res[13] = fma52hi(res[13], a[1], a[11]); // Sum(12) res[13] = fma52lo(res[13], a[2], a[11]); // Sum(13) res[14] = fma52hi(res[14], a[2], a[11]); // Sum(13) res[14] = fma52lo(res[14], a[3], a[11]); // Sum(14) res[15] = fma52hi(res[15], a[3], a[11]); // Sum(14) res[15] = fma52lo(res[15], a[4], a[11]); // Sum(15) res[16] = fma52hi(res[16], a[4], a[11]); // Sum(15) res[16] = fma52lo(res[16], a[5], a[11]); // Sum(16) res[17] = fma52hi(res[17], a[5], a[11]); // Sum(16) res[17] = fma52lo(res[17], a[6], a[11]); // Sum(17) res[18] = fma52hi(res[18], a[6], a[11]); // Sum(17) res[18] = fma52lo(res[18], a[7], a[11]); // Sum(18) res[19] = fma52hi(res[19], a[7], a[11]); // Sum(18) res[19] = fma52lo(res[19], a[8], a[11]); // Sum(19) res[20] = fma52hi(res[20], a[8], a[11]); // Sum(19) res[20] = fma52lo(res[20], a[9], a[11]); // Sum(20) res[21] = fma52hi(res[21], a[9], a[11]); // Sum(20) res[21] = fma52lo(res[21], a[10], a[11]); // Sum(21) res[22] = fma52hi(res[22], a[10], a[11]); // Sum(21) res[12] = fma52lo(res[12], a[0], a[12]); // Sum(12) res[13] = fma52hi(res[13], a[0], a[12]); // Sum(12) res[13] = fma52lo(res[13], a[1], a[12]); // Sum(13) res[14] = fma52hi(res[14], a[1], a[12]); // Sum(13) res[14] = fma52lo(res[14], a[2], a[12]); // Sum(14) res[15] = fma52hi(res[15], a[2], a[12]); // Sum(14) res[15] = fma52lo(res[15], a[3], a[12]); // Sum(15) res[16] = fma52hi(res[16], a[3], a[12]); // Sum(15) res[16] = fma52lo(res[16], a[4], a[12]); // Sum(16) res[17] = fma52hi(res[17], a[4], a[12]); // Sum(16) res[17] = fma52lo(res[17], a[5], a[12]); // Sum(17) res[18] = fma52hi(res[18], a[5], a[12]); // Sum(17) res[18] = fma52lo(res[18], a[6], a[12]); // Sum(18) res[19] = fma52hi(res[19], a[6], a[12]); // Sum(18) res[19] = fma52lo(res[19], a[7], a[12]); // Sum(19) res[20] = fma52hi(res[20], a[7], a[12]); // Sum(19) res[20] = fma52lo(res[20], a[8], a[12]); // Sum(20) res[21] = fma52hi(res[21], a[8], a[12]); // Sum(20) res[21] = fma52lo(res[21], a[9], a[12]); // Sum(21) res[22] = fma52hi(res[22], a[9], a[12]); // Sum(21) res[22] = fma52lo(res[22], a[10], a[12]); // Sum(22) res[23] = fma52hi(res[23], a[10], a[12]); // Sum(22) res[23] = fma52lo(res[23], a[11], a[12]); // Sum(23) res[24] = fma52hi(res[24], a[11], a[12]); // Sum(23) res[13] = fma52lo(res[13], a[0], a[13]); // Sum(13) res[14] = fma52hi(res[14], a[0], a[13]); // Sum(13) res[14] = fma52lo(res[14], a[1], a[13]); // Sum(14) res[15] = fma52hi(res[15], a[1], a[13]); // Sum(14) res[15] = fma52lo(res[15], a[2], a[13]); // Sum(15) res[16] = fma52hi(res[16], a[2], a[13]); // Sum(15) res[16] = fma52lo(res[16], a[3], a[13]); // Sum(16) res[17] = fma52hi(res[17], a[3], a[13]); // Sum(16) res[17] = fma52lo(res[17], a[4], a[13]); // Sum(17) res[18] = fma52hi(res[18], a[4], a[13]); // Sum(17) res[18] = fma52lo(res[18], a[5], a[13]); // Sum(18) res[19] = fma52hi(res[19], a[5], a[13]); // Sum(18) res[19] = fma52lo(res[19], a[6], a[13]); // Sum(19) res[20] = fma52hi(res[20], a[6], a[13]); // Sum(19) res[20] = fma52lo(res[20], a[7], a[13]); // Sum(20) res[21] = fma52hi(res[21], a[7], a[13]); // Sum(20) res[21] = fma52lo(res[21], a[8], a[13]); // Sum(21) res[22] = fma52hi(res[22], a[8], a[13]); // Sum(21) res[22] = fma52lo(res[22], a[9], a[13]); // Sum(22) res[23] = fma52hi(res[23], a[9], a[13]); // Sum(22) res[23] = fma52lo(res[23], a[10], a[13]); // Sum(23) res[24] = fma52hi(res[24], a[10], a[13]); // Sum(23) res[14] = fma52lo(res[14], a[0], a[14]); // Sum(14) res[15] = fma52hi(res[15], a[0], a[14]); // Sum(14) res[15] = fma52lo(res[15], a[1], a[14]); // Sum(15) res[16] = fma52hi(res[16], a[1], a[14]); // Sum(15) res[16] = fma52lo(res[16], a[2], a[14]); // Sum(16) res[17] = fma52hi(res[17], a[2], a[14]); // Sum(16) res[17] = fma52lo(res[17], a[3], a[14]); // Sum(17) res[18] = fma52hi(res[18], a[3], a[14]); // Sum(17) res[18] = fma52lo(res[18], a[4], a[14]); // Sum(18) res[19] = fma52hi(res[19], a[4], a[14]); // Sum(18) res[19] = fma52lo(res[19], a[5], a[14]); // Sum(19) res[20] = fma52hi(res[20], a[5], a[14]); // Sum(19) res[20] = fma52lo(res[20], a[6], a[14]); // Sum(20) res[21] = fma52hi(res[21], a[6], a[14]); // Sum(20) res[21] = fma52lo(res[21], a[7], a[14]); // Sum(21) res[22] = fma52hi(res[22], a[7], a[14]); // Sum(21) res[22] = fma52lo(res[22], a[8], a[14]); // Sum(22) res[23] = fma52hi(res[23], a[8], a[14]); // Sum(22) res[23] = fma52lo(res[23], a[9], a[14]); // Sum(23) res[24] = fma52hi(res[24], a[9], a[14]); // Sum(23) res[15] = fma52lo(res[15], a[0], a[15]); // Sum(15) res[16] = fma52hi(res[16], a[0], a[15]); // Sum(15) res[16] = fma52lo(res[16], a[1], a[15]); // Sum(16) res[17] = fma52hi(res[17], a[1], a[15]); // Sum(16) res[17] = fma52lo(res[17], a[2], a[15]); // Sum(17) res[18] = fma52hi(res[18], a[2], a[15]); // Sum(17) res[18] = fma52lo(res[18], a[3], a[15]); // Sum(18) res[19] = fma52hi(res[19], a[3], a[15]); // Sum(18) res[19] = fma52lo(res[19], a[4], a[15]); // Sum(19) res[20] = fma52hi(res[20], a[4], a[15]); // Sum(19) res[20] = fma52lo(res[20], a[5], a[15]); // Sum(20) res[21] = fma52hi(res[21], a[5], a[15]); // Sum(20) res[21] = fma52lo(res[21], a[6], a[15]); // Sum(21) res[22] = fma52hi(res[22], a[6], a[15]); // Sum(21) res[22] = fma52lo(res[22], a[7], a[15]); // Sum(22) res[23] = fma52hi(res[23], a[7], a[15]); // Sum(22) res[23] = fma52lo(res[23], a[8], a[15]); // Sum(23) res[24] = fma52hi(res[24], a[8], a[15]); // Sum(23) res[16] = fma52lo(res[16], a[0], a[16]); // Sum(16) res[17] = fma52hi(res[17], a[0], a[16]); // Sum(16) res[17] = fma52lo(res[17], a[1], a[16]); // Sum(17) res[18] = fma52hi(res[18], a[1], a[16]); // Sum(17) res[18] = fma52lo(res[18], a[2], a[16]); // Sum(18) res[19] = fma52hi(res[19], a[2], a[16]); // Sum(18) res[19] = fma52lo(res[19], a[3], a[16]); // Sum(19) res[20] = fma52hi(res[20], a[3], a[16]); // Sum(19) res[20] = fma52lo(res[20], a[4], a[16]); // Sum(20) res[21] = fma52hi(res[21], a[4], a[16]); // Sum(20) res[21] = fma52lo(res[21], a[5], a[16]); // Sum(21) res[22] = fma52hi(res[22], a[5], a[16]); // Sum(21) res[22] = fma52lo(res[22], a[6], a[16]); // Sum(22) res[23] = fma52hi(res[23], a[6], a[16]); // Sum(22) res[23] = fma52lo(res[23], a[7], a[16]); // Sum(23) res[24] = fma52hi(res[24], a[7], a[16]); // Sum(23) res[17] = fma52lo(res[17], a[0], a[17]); // Sum(17) res[18] = fma52hi(res[18], a[0], a[17]); // Sum(17) res[18] = fma52lo(res[18], a[1], a[17]); // Sum(18) res[19] = fma52hi(res[19], a[1], a[17]); // Sum(18) res[19] = fma52lo(res[19], a[2], a[17]); // Sum(19) res[20] = fma52hi(res[20], a[2], a[17]); // Sum(19) res[20] = fma52lo(res[20], a[3], a[17]); // Sum(20) res[21] = fma52hi(res[21], a[3], a[17]); // Sum(20) res[21] = fma52lo(res[21], a[4], a[17]); // Sum(21) res[22] = fma52hi(res[22], a[4], a[17]); // Sum(21) res[22] = fma52lo(res[22], a[5], a[17]); // Sum(22) res[23] = fma52hi(res[23], a[5], a[17]); // Sum(22) res[23] = fma52lo(res[23], a[6], a[17]); // Sum(23) res[24] = fma52hi(res[24], a[6], a[17]); // Sum(23) res[18] = fma52lo(res[18], a[0], a[18]); // Sum(18) res[19] = fma52hi(res[19], a[0], a[18]); // Sum(18) res[19] = fma52lo(res[19], a[1], a[18]); // Sum(19) res[20] = fma52hi(res[20], a[1], a[18]); // Sum(19) res[20] = fma52lo(res[20], a[2], a[18]); // Sum(20) res[21] = fma52hi(res[21], a[2], a[18]); // Sum(20) res[21] = fma52lo(res[21], a[3], a[18]); // Sum(21) res[22] = fma52hi(res[22], a[3], a[18]); // Sum(21) res[22] = fma52lo(res[22], a[4], a[18]); // Sum(22) res[23] = fma52hi(res[23], a[4], a[18]); // Sum(22) res[23] = fma52lo(res[23], a[5], a[18]); // Sum(23) res[24] = fma52hi(res[24], a[5], a[18]); // Sum(23) res[19] = fma52lo(res[19], a[0], a[19]); // Sum(19) res[20] = fma52hi(res[20], a[0], a[19]); // Sum(19) res[20] = fma52lo(res[20], a[1], a[19]); // Sum(20) res[21] = fma52hi(res[21], a[1], a[19]); // Sum(20) res[21] = fma52lo(res[21], a[2], a[19]); // Sum(21) res[22] = fma52hi(res[22], a[2], a[19]); // Sum(21) res[22] = fma52lo(res[22], a[3], a[19]); // Sum(22) res[23] = fma52hi(res[23], a[3], a[19]); // Sum(22) res[23] = fma52lo(res[23], a[4], a[19]); // Sum(23) res[24] = fma52hi(res[24], a[4], a[19]); // Sum(23) res[20] = fma52lo(res[20], a[0], a[20]); // Sum(20) res[21] = fma52hi(res[21], a[0], a[20]); // Sum(20) res[21] = fma52lo(res[21], a[1], a[20]); // Sum(21) res[22] = fma52hi(res[22], a[1], a[20]); // Sum(21) res[22] = fma52lo(res[22], a[2], a[20]); // Sum(22) res[23] = fma52hi(res[23], a[2], a[20]); // Sum(22) res[23] = fma52lo(res[23], a[3], a[20]); // Sum(23) res[24] = fma52hi(res[24], a[3], a[20]); // Sum(23) res[21] = fma52lo(res[21], a[0], a[21]); // Sum(21) res[22] = fma52hi(res[22], a[0], a[21]); // Sum(21) res[22] = fma52lo(res[22], a[1], a[21]); // Sum(22) res[23] = fma52hi(res[23], a[1], a[21]); // Sum(22) res[23] = fma52lo(res[23], a[2], a[21]); // Sum(23) res[24] = fma52hi(res[24], a[2], a[21]); // Sum(23) res[22] = fma52lo(res[22], a[0], a[22]); // Sum(22) res[23] = fma52hi(res[23], a[0], a[22]); // Sum(22) res[23] = fma52lo(res[23], a[1], a[22]); // Sum(23) res[24] = fma52hi(res[24], a[1], a[22]); // Sum(23) res[23] = fma52lo(res[23], a[0], a[23]); // Sum(23) res[24] = fma52hi(res[24], a[0], a[23]); // Sum(23) res[12] = add64(res[12], res[12]); // Double(12) res[13] = add64(res[13], res[13]); // Double(13) res[14] = add64(res[14], res[14]); // Double(14) res[15] = add64(res[15], res[15]); // Double(15) res[16] = add64(res[16], res[16]); // Double(16) res[17] = add64(res[17], res[17]); // Double(17) res[18] = add64(res[18], res[18]); // Double(18) res[19] = add64(res[19], res[19]); // Double(19) res[20] = add64(res[20], res[20]); // Double(20) res[21] = add64(res[21], res[21]); // Double(21) res[22] = add64(res[22], res[22]); // Double(22) res[23] = add64(res[23], res[23]); // Double(23) res[12] = fma52lo(res[12], a[6], a[6]); // Add sqr(12) res[13] = fma52hi(res[13], a[6], a[6]); // Add sqr(12) res[14] = fma52lo(res[14], a[7], a[7]); // Add sqr(14) res[15] = fma52hi(res[15], a[7], a[7]); // Add sqr(14) res[16] = fma52lo(res[16], a[8], a[8]); // Add sqr(16) res[17] = fma52hi(res[17], a[8], a[8]); // Add sqr(16) res[18] = fma52lo(res[18], a[9], a[9]); // Add sqr(18) res[19] = fma52hi(res[19], a[9], a[9]); // Add sqr(18) res[20] = fma52lo(res[20], a[10], a[10]); // Add sqr(20) res[21] = fma52hi(res[21], a[10], a[10]); // Add sqr(20) res[22] = fma52lo(res[22], a[11], a[11]); // Add sqr(22) res[23] = fma52hi(res[23], a[11], a[11]); // Add sqr(22) res[24] = fma52lo(res[24], a[11], a[13]); // Sum(24) res[25] = fma52hi(res[25], a[11], a[13]); // Sum(24) res[25] = fma52lo(res[25], a[12], a[13]); // Sum(25) res[26] = fma52hi(res[26], a[12], a[13]); // Sum(25) res[24] = fma52lo(res[24], a[10], a[14]); // Sum(24) res[25] = fma52hi(res[25], a[10], a[14]); // Sum(24) res[25] = fma52lo(res[25], a[11], a[14]); // Sum(25) res[26] = fma52hi(res[26], a[11], a[14]); // Sum(25) res[26] = fma52lo(res[26], a[12], a[14]); // Sum(26) res[27] = fma52hi(res[27], a[12], a[14]); // Sum(26) res[27] = fma52lo(res[27], a[13], a[14]); // Sum(27) res[28] = fma52hi(res[28], a[13], a[14]); // Sum(27) res[24] = fma52lo(res[24], a[9], a[15]); // Sum(24) res[25] = fma52hi(res[25], a[9], a[15]); // Sum(24) res[25] = fma52lo(res[25], a[10], a[15]); // Sum(25) res[26] = fma52hi(res[26], a[10], a[15]); // Sum(25) res[26] = fma52lo(res[26], a[11], a[15]); // Sum(26) res[27] = fma52hi(res[27], a[11], a[15]); // Sum(26) res[27] = fma52lo(res[27], a[12], a[15]); // Sum(27) res[28] = fma52hi(res[28], a[12], a[15]); // Sum(27) res[28] = fma52lo(res[28], a[13], a[15]); // Sum(28) res[29] = fma52hi(res[29], a[13], a[15]); // Sum(28) res[29] = fma52lo(res[29], a[14], a[15]); // Sum(29) res[30] = fma52hi(res[30], a[14], a[15]); // Sum(29) res[24] = fma52lo(res[24], a[8], a[16]); // Sum(24) res[25] = fma52hi(res[25], a[8], a[16]); // Sum(24) res[25] = fma52lo(res[25], a[9], a[16]); // Sum(25) res[26] = fma52hi(res[26], a[9], a[16]); // Sum(25) res[26] = fma52lo(res[26], a[10], a[16]); // Sum(26) res[27] = fma52hi(res[27], a[10], a[16]); // Sum(26) res[27] = fma52lo(res[27], a[11], a[16]); // Sum(27) res[28] = fma52hi(res[28], a[11], a[16]); // Sum(27) res[28] = fma52lo(res[28], a[12], a[16]); // Sum(28) res[29] = fma52hi(res[29], a[12], a[16]); // Sum(28) res[29] = fma52lo(res[29], a[13], a[16]); // Sum(29) res[30] = fma52hi(res[30], a[13], a[16]); // Sum(29) res[30] = fma52lo(res[30], a[14], a[16]); // Sum(30) res[31] = fma52hi(res[31], a[14], a[16]); // Sum(30) res[31] = fma52lo(res[31], a[15], a[16]); // Sum(31) res[32] = fma52hi(res[32], a[15], a[16]); // Sum(31) res[24] = fma52lo(res[24], a[7], a[17]); // Sum(24) res[25] = fma52hi(res[25], a[7], a[17]); // Sum(24) res[25] = fma52lo(res[25], a[8], a[17]); // Sum(25) res[26] = fma52hi(res[26], a[8], a[17]); // Sum(25) res[26] = fma52lo(res[26], a[9], a[17]); // Sum(26) res[27] = fma52hi(res[27], a[9], a[17]); // Sum(26) res[27] = fma52lo(res[27], a[10], a[17]); // Sum(27) res[28] = fma52hi(res[28], a[10], a[17]); // Sum(27) res[28] = fma52lo(res[28], a[11], a[17]); // Sum(28) res[29] = fma52hi(res[29], a[11], a[17]); // Sum(28) res[29] = fma52lo(res[29], a[12], a[17]); // Sum(29) res[30] = fma52hi(res[30], a[12], a[17]); // Sum(29) res[30] = fma52lo(res[30], a[13], a[17]); // Sum(30) res[31] = fma52hi(res[31], a[13], a[17]); // Sum(30) res[31] = fma52lo(res[31], a[14], a[17]); // Sum(31) res[32] = fma52hi(res[32], a[14], a[17]); // Sum(31) res[32] = fma52lo(res[32], a[15], a[17]); // Sum(32) res[33] = fma52hi(res[33], a[15], a[17]); // Sum(32) res[33] = fma52lo(res[33], a[16], a[17]); // Sum(33) res[34] = fma52hi(res[34], a[16], a[17]); // Sum(33) res[24] = fma52lo(res[24], a[6], a[18]); // Sum(24) res[25] = fma52hi(res[25], a[6], a[18]); // Sum(24) res[25] = fma52lo(res[25], a[7], a[18]); // Sum(25) res[26] = fma52hi(res[26], a[7], a[18]); // Sum(25) res[26] = fma52lo(res[26], a[8], a[18]); // Sum(26) res[27] = fma52hi(res[27], a[8], a[18]); // Sum(26) res[27] = fma52lo(res[27], a[9], a[18]); // Sum(27) res[28] = fma52hi(res[28], a[9], a[18]); // Sum(27) res[28] = fma52lo(res[28], a[10], a[18]); // Sum(28) res[29] = fma52hi(res[29], a[10], a[18]); // Sum(28) res[29] = fma52lo(res[29], a[11], a[18]); // Sum(29) res[30] = fma52hi(res[30], a[11], a[18]); // Sum(29) res[30] = fma52lo(res[30], a[12], a[18]); // Sum(30) res[31] = fma52hi(res[31], a[12], a[18]); // Sum(30) res[31] = fma52lo(res[31], a[13], a[18]); // Sum(31) res[32] = fma52hi(res[32], a[13], a[18]); // Sum(31) res[32] = fma52lo(res[32], a[14], a[18]); // Sum(32) res[33] = fma52hi(res[33], a[14], a[18]); // Sum(32) res[33] = fma52lo(res[33], a[15], a[18]); // Sum(33) res[34] = fma52hi(res[34], a[15], a[18]); // Sum(33) res[34] = fma52lo(res[34], a[16], a[18]); // Sum(34) res[35] = fma52hi(res[35], a[16], a[18]); // Sum(34) res[35] = fma52lo(res[35], a[17], a[18]); // Sum(35) res[36] = fma52hi(res[36], a[17], a[18]); // Sum(35) res[24] = fma52lo(res[24], a[5], a[19]); // Sum(24) res[25] = fma52hi(res[25], a[5], a[19]); // Sum(24) res[25] = fma52lo(res[25], a[6], a[19]); // Sum(25) res[26] = fma52hi(res[26], a[6], a[19]); // Sum(25) res[26] = fma52lo(res[26], a[7], a[19]); // Sum(26) res[27] = fma52hi(res[27], a[7], a[19]); // Sum(26) res[27] = fma52lo(res[27], a[8], a[19]); // Sum(27) res[28] = fma52hi(res[28], a[8], a[19]); // Sum(27) res[28] = fma52lo(res[28], a[9], a[19]); // Sum(28) res[29] = fma52hi(res[29], a[9], a[19]); // Sum(28) res[29] = fma52lo(res[29], a[10], a[19]); // Sum(29) res[30] = fma52hi(res[30], a[10], a[19]); // Sum(29) res[30] = fma52lo(res[30], a[11], a[19]); // Sum(30) res[31] = fma52hi(res[31], a[11], a[19]); // Sum(30) res[31] = fma52lo(res[31], a[12], a[19]); // Sum(31) res[32] = fma52hi(res[32], a[12], a[19]); // Sum(31) res[32] = fma52lo(res[32], a[13], a[19]); // Sum(32) res[33] = fma52hi(res[33], a[13], a[19]); // Sum(32) res[33] = fma52lo(res[33], a[14], a[19]); // Sum(33) res[34] = fma52hi(res[34], a[14], a[19]); // Sum(33) res[34] = fma52lo(res[34], a[15], a[19]); // Sum(34) res[35] = fma52hi(res[35], a[15], a[19]); // Sum(34) res[35] = fma52lo(res[35], a[16], a[19]); // Sum(35) res[36] = fma52hi(res[36], a[16], a[19]); // Sum(35) res[24] = fma52lo(res[24], a[4], a[20]); // Sum(24) res[25] = fma52hi(res[25], a[4], a[20]); // Sum(24) res[25] = fma52lo(res[25], a[5], a[20]); // Sum(25) res[26] = fma52hi(res[26], a[5], a[20]); // Sum(25) res[26] = fma52lo(res[26], a[6], a[20]); // Sum(26) res[27] = fma52hi(res[27], a[6], a[20]); // Sum(26) res[27] = fma52lo(res[27], a[7], a[20]); // Sum(27) res[28] = fma52hi(res[28], a[7], a[20]); // Sum(27) res[28] = fma52lo(res[28], a[8], a[20]); // Sum(28) res[29] = fma52hi(res[29], a[8], a[20]); // Sum(28) res[29] = fma52lo(res[29], a[9], a[20]); // Sum(29) res[30] = fma52hi(res[30], a[9], a[20]); // Sum(29) res[30] = fma52lo(res[30], a[10], a[20]); // Sum(30) res[31] = fma52hi(res[31], a[10], a[20]); // Sum(30) res[31] = fma52lo(res[31], a[11], a[20]); // Sum(31) res[32] = fma52hi(res[32], a[11], a[20]); // Sum(31) res[32] = fma52lo(res[32], a[12], a[20]); // Sum(32) res[33] = fma52hi(res[33], a[12], a[20]); // Sum(32) res[33] = fma52lo(res[33], a[13], a[20]); // Sum(33) res[34] = fma52hi(res[34], a[13], a[20]); // Sum(33) res[34] = fma52lo(res[34], a[14], a[20]); // Sum(34) res[35] = fma52hi(res[35], a[14], a[20]); // Sum(34) res[35] = fma52lo(res[35], a[15], a[20]); // Sum(35) res[36] = fma52hi(res[36], a[15], a[20]); // Sum(35) res[24] = fma52lo(res[24], a[3], a[21]); // Sum(24) res[25] = fma52hi(res[25], a[3], a[21]); // Sum(24) res[25] = fma52lo(res[25], a[4], a[21]); // Sum(25) res[26] = fma52hi(res[26], a[4], a[21]); // Sum(25) res[26] = fma52lo(res[26], a[5], a[21]); // Sum(26) res[27] = fma52hi(res[27], a[5], a[21]); // Sum(26) res[27] = fma52lo(res[27], a[6], a[21]); // Sum(27) res[28] = fma52hi(res[28], a[6], a[21]); // Sum(27) res[28] = fma52lo(res[28], a[7], a[21]); // Sum(28) res[29] = fma52hi(res[29], a[7], a[21]); // Sum(28) res[29] = fma52lo(res[29], a[8], a[21]); // Sum(29) res[30] = fma52hi(res[30], a[8], a[21]); // Sum(29) res[30] = fma52lo(res[30], a[9], a[21]); // Sum(30) res[31] = fma52hi(res[31], a[9], a[21]); // Sum(30) res[31] = fma52lo(res[31], a[10], a[21]); // Sum(31) res[32] = fma52hi(res[32], a[10], a[21]); // Sum(31) res[32] = fma52lo(res[32], a[11], a[21]); // Sum(32) res[33] = fma52hi(res[33], a[11], a[21]); // Sum(32) res[33] = fma52lo(res[33], a[12], a[21]); // Sum(33) res[34] = fma52hi(res[34], a[12], a[21]); // Sum(33) res[34] = fma52lo(res[34], a[13], a[21]); // Sum(34) res[35] = fma52hi(res[35], a[13], a[21]); // Sum(34) res[35] = fma52lo(res[35], a[14], a[21]); // Sum(35) res[36] = fma52hi(res[36], a[14], a[21]); // Sum(35) res[24] = fma52lo(res[24], a[2], a[22]); // Sum(24) res[25] = fma52hi(res[25], a[2], a[22]); // Sum(24) res[25] = fma52lo(res[25], a[3], a[22]); // Sum(25) res[26] = fma52hi(res[26], a[3], a[22]); // Sum(25) res[26] = fma52lo(res[26], a[4], a[22]); // Sum(26) res[27] = fma52hi(res[27], a[4], a[22]); // Sum(26) res[27] = fma52lo(res[27], a[5], a[22]); // Sum(27) res[28] = fma52hi(res[28], a[5], a[22]); // Sum(27) res[28] = fma52lo(res[28], a[6], a[22]); // Sum(28) res[29] = fma52hi(res[29], a[6], a[22]); // Sum(28) res[29] = fma52lo(res[29], a[7], a[22]); // Sum(29) res[30] = fma52hi(res[30], a[7], a[22]); // Sum(29) res[30] = fma52lo(res[30], a[8], a[22]); // Sum(30) res[31] = fma52hi(res[31], a[8], a[22]); // Sum(30) res[31] = fma52lo(res[31], a[9], a[22]); // Sum(31) res[32] = fma52hi(res[32], a[9], a[22]); // Sum(31) res[32] = fma52lo(res[32], a[10], a[22]); // Sum(32) res[33] = fma52hi(res[33], a[10], a[22]); // Sum(32) res[33] = fma52lo(res[33], a[11], a[22]); // Sum(33) res[34] = fma52hi(res[34], a[11], a[22]); // Sum(33) res[34] = fma52lo(res[34], a[12], a[22]); // Sum(34) res[35] = fma52hi(res[35], a[12], a[22]); // Sum(34) res[35] = fma52lo(res[35], a[13], a[22]); // Sum(35) res[36] = fma52hi(res[36], a[13], a[22]); // Sum(35) res[24] = fma52lo(res[24], a[1], a[23]); // Sum(24) res[25] = fma52hi(res[25], a[1], a[23]); // Sum(24) res[25] = fma52lo(res[25], a[2], a[23]); // Sum(25) res[26] = fma52hi(res[26], a[2], a[23]); // Sum(25) res[26] = fma52lo(res[26], a[3], a[23]); // Sum(26) res[27] = fma52hi(res[27], a[3], a[23]); // Sum(26) res[27] = fma52lo(res[27], a[4], a[23]); // Sum(27) res[28] = fma52hi(res[28], a[4], a[23]); // Sum(27) res[28] = fma52lo(res[28], a[5], a[23]); // Sum(28) res[29] = fma52hi(res[29], a[5], a[23]); // Sum(28) res[29] = fma52lo(res[29], a[6], a[23]); // Sum(29) res[30] = fma52hi(res[30], a[6], a[23]); // Sum(29) res[30] = fma52lo(res[30], a[7], a[23]); // Sum(30) res[31] = fma52hi(res[31], a[7], a[23]); // Sum(30) res[31] = fma52lo(res[31], a[8], a[23]); // Sum(31) res[32] = fma52hi(res[32], a[8], a[23]); // Sum(31) res[32] = fma52lo(res[32], a[9], a[23]); // Sum(32) res[33] = fma52hi(res[33], a[9], a[23]); // Sum(32) res[33] = fma52lo(res[33], a[10], a[23]); // Sum(33) res[34] = fma52hi(res[34], a[10], a[23]); // Sum(33) res[34] = fma52lo(res[34], a[11], a[23]); // Sum(34) res[35] = fma52hi(res[35], a[11], a[23]); // Sum(34) res[35] = fma52lo(res[35], a[12], a[23]); // Sum(35) res[36] = fma52hi(res[36], a[12], a[23]); // Sum(35) res[24] = fma52lo(res[24], a[0], a[24]); // Sum(24) res[25] = fma52hi(res[25], a[0], a[24]); // Sum(24) res[25] = fma52lo(res[25], a[1], a[24]); // Sum(25) res[26] = fma52hi(res[26], a[1], a[24]); // Sum(25) res[26] = fma52lo(res[26], a[2], a[24]); // Sum(26) res[27] = fma52hi(res[27], a[2], a[24]); // Sum(26) res[27] = fma52lo(res[27], a[3], a[24]); // Sum(27) res[28] = fma52hi(res[28], a[3], a[24]); // Sum(27) res[28] = fma52lo(res[28], a[4], a[24]); // Sum(28) res[29] = fma52hi(res[29], a[4], a[24]); // Sum(28) res[29] = fma52lo(res[29], a[5], a[24]); // Sum(29) res[30] = fma52hi(res[30], a[5], a[24]); // Sum(29) res[30] = fma52lo(res[30], a[6], a[24]); // Sum(30) res[31] = fma52hi(res[31], a[6], a[24]); // Sum(30) res[31] = fma52lo(res[31], a[7], a[24]); // Sum(31) res[32] = fma52hi(res[32], a[7], a[24]); // Sum(31) res[32] = fma52lo(res[32], a[8], a[24]); // Sum(32) res[33] = fma52hi(res[33], a[8], a[24]); // Sum(32) res[33] = fma52lo(res[33], a[9], a[24]); // Sum(33) res[34] = fma52hi(res[34], a[9], a[24]); // Sum(33) res[34] = fma52lo(res[34], a[10], a[24]); // Sum(34) res[35] = fma52hi(res[35], a[10], a[24]); // Sum(34) res[35] = fma52lo(res[35], a[11], a[24]); // Sum(35) res[36] = fma52hi(res[36], a[11], a[24]); // Sum(35) res[25] = fma52lo(res[25], a[0], a[25]); // Sum(25) res[26] = fma52hi(res[26], a[0], a[25]); // Sum(25) res[26] = fma52lo(res[26], a[1], a[25]); // Sum(26) res[27] = fma52hi(res[27], a[1], a[25]); // Sum(26) res[27] = fma52lo(res[27], a[2], a[25]); // Sum(27) res[28] = fma52hi(res[28], a[2], a[25]); // Sum(27) res[28] = fma52lo(res[28], a[3], a[25]); // Sum(28) res[29] = fma52hi(res[29], a[3], a[25]); // Sum(28) res[29] = fma52lo(res[29], a[4], a[25]); // Sum(29) res[30] = fma52hi(res[30], a[4], a[25]); // Sum(29) res[30] = fma52lo(res[30], a[5], a[25]); // Sum(30) res[31] = fma52hi(res[31], a[5], a[25]); // Sum(30) res[31] = fma52lo(res[31], a[6], a[25]); // Sum(31) res[32] = fma52hi(res[32], a[6], a[25]); // Sum(31) res[32] = fma52lo(res[32], a[7], a[25]); // Sum(32) res[33] = fma52hi(res[33], a[7], a[25]); // Sum(32) res[33] = fma52lo(res[33], a[8], a[25]); // Sum(33) res[34] = fma52hi(res[34], a[8], a[25]); // Sum(33) res[34] = fma52lo(res[34], a[9], a[25]); // Sum(34) res[35] = fma52hi(res[35], a[9], a[25]); // Sum(34) res[35] = fma52lo(res[35], a[10], a[25]); // Sum(35) res[36] = fma52hi(res[36], a[10], a[25]); // Sum(35) res[26] = fma52lo(res[26], a[0], a[26]); // Sum(26) res[27] = fma52hi(res[27], a[0], a[26]); // Sum(26) res[27] = fma52lo(res[27], a[1], a[26]); // Sum(27) res[28] = fma52hi(res[28], a[1], a[26]); // Sum(27) res[28] = fma52lo(res[28], a[2], a[26]); // Sum(28) res[29] = fma52hi(res[29], a[2], a[26]); // Sum(28) res[29] = fma52lo(res[29], a[3], a[26]); // Sum(29) res[30] = fma52hi(res[30], a[3], a[26]); // Sum(29) res[30] = fma52lo(res[30], a[4], a[26]); // Sum(30) res[31] = fma52hi(res[31], a[4], a[26]); // Sum(30) res[31] = fma52lo(res[31], a[5], a[26]); // Sum(31) res[32] = fma52hi(res[32], a[5], a[26]); // Sum(31) res[32] = fma52lo(res[32], a[6], a[26]); // Sum(32) res[33] = fma52hi(res[33], a[6], a[26]); // Sum(32) res[33] = fma52lo(res[33], a[7], a[26]); // Sum(33) res[34] = fma52hi(res[34], a[7], a[26]); // Sum(33) res[34] = fma52lo(res[34], a[8], a[26]); // Sum(34) res[35] = fma52hi(res[35], a[8], a[26]); // Sum(34) res[35] = fma52lo(res[35], a[9], a[26]); // Sum(35) res[36] = fma52hi(res[36], a[9], a[26]); // Sum(35) res[27] = fma52lo(res[27], a[0], a[27]); // Sum(27) res[28] = fma52hi(res[28], a[0], a[27]); // Sum(27) res[28] = fma52lo(res[28], a[1], a[27]); // Sum(28) res[29] = fma52hi(res[29], a[1], a[27]); // Sum(28) res[29] = fma52lo(res[29], a[2], a[27]); // Sum(29) res[30] = fma52hi(res[30], a[2], a[27]); // Sum(29) res[30] = fma52lo(res[30], a[3], a[27]); // Sum(30) res[31] = fma52hi(res[31], a[3], a[27]); // Sum(30) res[31] = fma52lo(res[31], a[4], a[27]); // Sum(31) res[32] = fma52hi(res[32], a[4], a[27]); // Sum(31) res[32] = fma52lo(res[32], a[5], a[27]); // Sum(32) res[33] = fma52hi(res[33], a[5], a[27]); // Sum(32) res[33] = fma52lo(res[33], a[6], a[27]); // Sum(33) res[34] = fma52hi(res[34], a[6], a[27]); // Sum(33) res[34] = fma52lo(res[34], a[7], a[27]); // Sum(34) res[35] = fma52hi(res[35], a[7], a[27]); // Sum(34) res[35] = fma52lo(res[35], a[8], a[27]); // Sum(35) res[36] = fma52hi(res[36], a[8], a[27]); // Sum(35) res[28] = fma52lo(res[28], a[0], a[28]); // Sum(28) res[29] = fma52hi(res[29], a[0], a[28]); // Sum(28) res[29] = fma52lo(res[29], a[1], a[28]); // Sum(29) res[30] = fma52hi(res[30], a[1], a[28]); // Sum(29) res[30] = fma52lo(res[30], a[2], a[28]); // Sum(30) res[31] = fma52hi(res[31], a[2], a[28]); // Sum(30) res[31] = fma52lo(res[31], a[3], a[28]); // Sum(31) res[32] = fma52hi(res[32], a[3], a[28]); // Sum(31) res[32] = fma52lo(res[32], a[4], a[28]); // Sum(32) res[33] = fma52hi(res[33], a[4], a[28]); // Sum(32) res[33] = fma52lo(res[33], a[5], a[28]); // Sum(33) res[34] = fma52hi(res[34], a[5], a[28]); // Sum(33) res[34] = fma52lo(res[34], a[6], a[28]); // Sum(34) res[35] = fma52hi(res[35], a[6], a[28]); // Sum(34) res[35] = fma52lo(res[35], a[7], a[28]); // Sum(35) res[36] = fma52hi(res[36], a[7], a[28]); // Sum(35) res[29] = fma52lo(res[29], a[0], a[29]); // Sum(29) res[30] = fma52hi(res[30], a[0], a[29]); // Sum(29) res[30] = fma52lo(res[30], a[1], a[29]); // Sum(30) res[31] = fma52hi(res[31], a[1], a[29]); // Sum(30) res[31] = fma52lo(res[31], a[2], a[29]); // Sum(31) res[32] = fma52hi(res[32], a[2], a[29]); // Sum(31) res[32] = fma52lo(res[32], a[3], a[29]); // Sum(32) res[33] = fma52hi(res[33], a[3], a[29]); // Sum(32) res[33] = fma52lo(res[33], a[4], a[29]); // Sum(33) res[34] = fma52hi(res[34], a[4], a[29]); // Sum(33) res[34] = fma52lo(res[34], a[5], a[29]); // Sum(34) res[35] = fma52hi(res[35], a[5], a[29]); // Sum(34) res[35] = fma52lo(res[35], a[6], a[29]); // Sum(35) res[36] = fma52hi(res[36], a[6], a[29]); // Sum(35) res[30] = fma52lo(res[30], a[0], a[30]); // Sum(30) res[31] = fma52hi(res[31], a[0], a[30]); // Sum(30) res[31] = fma52lo(res[31], a[1], a[30]); // Sum(31) res[32] = fma52hi(res[32], a[1], a[30]); // Sum(31) res[32] = fma52lo(res[32], a[2], a[30]); // Sum(32) res[33] = fma52hi(res[33], a[2], a[30]); // Sum(32) res[33] = fma52lo(res[33], a[3], a[30]); // Sum(33) res[34] = fma52hi(res[34], a[3], a[30]); // Sum(33) res[34] = fma52lo(res[34], a[4], a[30]); // Sum(34) res[35] = fma52hi(res[35], a[4], a[30]); // Sum(34) res[35] = fma52lo(res[35], a[5], a[30]); // Sum(35) res[36] = fma52hi(res[36], a[5], a[30]); // Sum(35) res[31] = fma52lo(res[31], a[0], a[31]); // Sum(31) res[32] = fma52hi(res[32], a[0], a[31]); // Sum(31) res[32] = fma52lo(res[32], a[1], a[31]); // Sum(32) res[33] = fma52hi(res[33], a[1], a[31]); // Sum(32) res[33] = fma52lo(res[33], a[2], a[31]); // Sum(33) res[34] = fma52hi(res[34], a[2], a[31]); // Sum(33) res[34] = fma52lo(res[34], a[3], a[31]); // Sum(34) res[35] = fma52hi(res[35], a[3], a[31]); // Sum(34) res[35] = fma52lo(res[35], a[4], a[31]); // Sum(35) res[36] = fma52hi(res[36], a[4], a[31]); // Sum(35) res[32] = fma52lo(res[32], a[0], a[32]); // Sum(32) res[33] = fma52hi(res[33], a[0], a[32]); // Sum(32) res[33] = fma52lo(res[33], a[1], a[32]); // Sum(33) res[34] = fma52hi(res[34], a[1], a[32]); // Sum(33) res[34] = fma52lo(res[34], a[2], a[32]); // Sum(34) res[35] = fma52hi(res[35], a[2], a[32]); // Sum(34) res[35] = fma52lo(res[35], a[3], a[32]); // Sum(35) res[36] = fma52hi(res[36], a[3], a[32]); // Sum(35) res[33] = fma52lo(res[33], a[0], a[33]); // Sum(33) res[34] = fma52hi(res[34], a[0], a[33]); // Sum(33) res[34] = fma52lo(res[34], a[1], a[33]); // Sum(34) res[35] = fma52hi(res[35], a[1], a[33]); // Sum(34) res[35] = fma52lo(res[35], a[2], a[33]); // Sum(35) res[36] = fma52hi(res[36], a[2], a[33]); // Sum(35) res[34] = fma52lo(res[34], a[0], a[34]); // Sum(34) res[35] = fma52hi(res[35], a[0], a[34]); // Sum(34) res[35] = fma52lo(res[35], a[1], a[34]); // Sum(35) res[36] = fma52hi(res[36], a[1], a[34]); // Sum(35) res[35] = fma52lo(res[35], a[0], a[35]); // Sum(35) res[36] = fma52hi(res[36], a[0], a[35]); // Sum(35) res[24] = add64(res[24], res[24]); // Double(24) res[25] = add64(res[25], res[25]); // Double(25) res[26] = add64(res[26], res[26]); // Double(26) res[27] = add64(res[27], res[27]); // Double(27) res[28] = add64(res[28], res[28]); // Double(28) res[29] = add64(res[29], res[29]); // Double(29) res[30] = add64(res[30], res[30]); // Double(30) res[31] = add64(res[31], res[31]); // Double(31) res[32] = add64(res[32], res[32]); // Double(32) res[33] = add64(res[33], res[33]); // Double(33) res[34] = add64(res[34], res[34]); // Double(34) res[35] = add64(res[35], res[35]); // Double(35) res[24] = fma52lo(res[24], a[12], a[12]); // Add sqr(24) res[25] = fma52hi(res[25], a[12], a[12]); // Add sqr(24) res[26] = fma52lo(res[26], a[13], a[13]); // Add sqr(26) res[27] = fma52hi(res[27], a[13], a[13]); // Add sqr(26) res[28] = fma52lo(res[28], a[14], a[14]); // Add sqr(28) res[29] = fma52hi(res[29], a[14], a[14]); // Add sqr(28) res[30] = fma52lo(res[30], a[15], a[15]); // Add sqr(30) res[31] = fma52hi(res[31], a[15], a[15]); // Add sqr(30) res[32] = fma52lo(res[32], a[16], a[16]); // Add sqr(32) res[33] = fma52hi(res[33], a[16], a[16]); // Add sqr(32) res[34] = fma52lo(res[34], a[17], a[17]); // Add sqr(34) res[35] = fma52hi(res[35], a[17], a[17]); // Add sqr(34) res[36] = fma52lo(res[36], a[17], a[19]); // Sum(36) res[37] = fma52hi(res[37], a[17], a[19]); // Sum(36) res[37] = fma52lo(res[37], a[18], a[19]); // Sum(37) res[38] = fma52hi(res[38], a[18], a[19]); // Sum(37) res[36] = fma52lo(res[36], a[16], a[20]); // Sum(36) res[37] = fma52hi(res[37], a[16], a[20]); // Sum(36) res[37] = fma52lo(res[37], a[17], a[20]); // Sum(37) res[38] = fma52hi(res[38], a[17], a[20]); // Sum(37) res[38] = fma52lo(res[38], a[18], a[20]); // Sum(38) res[39] = fma52hi(res[39], a[18], a[20]); // Sum(38) res[39] = fma52lo(res[39], a[19], a[20]); // Sum(39) res[40] = fma52hi(res[40], a[19], a[20]); // Sum(39) res[36] = fma52lo(res[36], a[15], a[21]); // Sum(36) res[37] = fma52hi(res[37], a[15], a[21]); // Sum(36) res[37] = fma52lo(res[37], a[16], a[21]); // Sum(37) res[38] = fma52hi(res[38], a[16], a[21]); // Sum(37) res[38] = fma52lo(res[38], a[17], a[21]); // Sum(38) res[39] = fma52hi(res[39], a[17], a[21]); // Sum(38) res[39] = fma52lo(res[39], a[18], a[21]); // Sum(39) res[40] = fma52hi(res[40], a[18], a[21]); // Sum(39) res[40] = fma52lo(res[40], a[19], a[21]); // Sum(40) res[41] = fma52hi(res[41], a[19], a[21]); // Sum(40) res[41] = fma52lo(res[41], a[20], a[21]); // Sum(41) res[42] = fma52hi(res[42], a[20], a[21]); // Sum(41) res[36] = fma52lo(res[36], a[14], a[22]); // Sum(36) res[37] = fma52hi(res[37], a[14], a[22]); // Sum(36) res[37] = fma52lo(res[37], a[15], a[22]); // Sum(37) res[38] = fma52hi(res[38], a[15], a[22]); // Sum(37) res[38] = fma52lo(res[38], a[16], a[22]); // Sum(38) res[39] = fma52hi(res[39], a[16], a[22]); // Sum(38) res[39] = fma52lo(res[39], a[17], a[22]); // Sum(39) res[40] = fma52hi(res[40], a[17], a[22]); // Sum(39) res[40] = fma52lo(res[40], a[18], a[22]); // Sum(40) res[41] = fma52hi(res[41], a[18], a[22]); // Sum(40) res[41] = fma52lo(res[41], a[19], a[22]); // Sum(41) res[42] = fma52hi(res[42], a[19], a[22]); // Sum(41) res[42] = fma52lo(res[42], a[20], a[22]); // Sum(42) res[43] = fma52hi(res[43], a[20], a[22]); // Sum(42) res[43] = fma52lo(res[43], a[21], a[22]); // Sum(43) res[44] = fma52hi(res[44], a[21], a[22]); // Sum(43) res[36] = fma52lo(res[36], a[13], a[23]); // Sum(36) res[37] = fma52hi(res[37], a[13], a[23]); // Sum(36) res[37] = fma52lo(res[37], a[14], a[23]); // Sum(37) res[38] = fma52hi(res[38], a[14], a[23]); // Sum(37) res[38] = fma52lo(res[38], a[15], a[23]); // Sum(38) res[39] = fma52hi(res[39], a[15], a[23]); // Sum(38) res[39] = fma52lo(res[39], a[16], a[23]); // Sum(39) res[40] = fma52hi(res[40], a[16], a[23]); // Sum(39) res[40] = fma52lo(res[40], a[17], a[23]); // Sum(40) res[41] = fma52hi(res[41], a[17], a[23]); // Sum(40) res[41] = fma52lo(res[41], a[18], a[23]); // Sum(41) res[42] = fma52hi(res[42], a[18], a[23]); // Sum(41) res[42] = fma52lo(res[42], a[19], a[23]); // Sum(42) res[43] = fma52hi(res[43], a[19], a[23]); // Sum(42) res[43] = fma52lo(res[43], a[20], a[23]); // Sum(43) res[44] = fma52hi(res[44], a[20], a[23]); // Sum(43) res[44] = fma52lo(res[44], a[21], a[23]); // Sum(44) res[45] = fma52hi(res[45], a[21], a[23]); // Sum(44) res[45] = fma52lo(res[45], a[22], a[23]); // Sum(45) res[46] = fma52hi(res[46], a[22], a[23]); // Sum(45) res[36] = fma52lo(res[36], a[12], a[24]); // Sum(36) res[37] = fma52hi(res[37], a[12], a[24]); // Sum(36) res[37] = fma52lo(res[37], a[13], a[24]); // Sum(37) res[38] = fma52hi(res[38], a[13], a[24]); // Sum(37) res[38] = fma52lo(res[38], a[14], a[24]); // Sum(38) res[39] = fma52hi(res[39], a[14], a[24]); // Sum(38) res[39] = fma52lo(res[39], a[15], a[24]); // Sum(39) res[40] = fma52hi(res[40], a[15], a[24]); // Sum(39) res[40] = fma52lo(res[40], a[16], a[24]); // Sum(40) res[41] = fma52hi(res[41], a[16], a[24]); // Sum(40) res[41] = fma52lo(res[41], a[17], a[24]); // Sum(41) res[42] = fma52hi(res[42], a[17], a[24]); // Sum(41) res[42] = fma52lo(res[42], a[18], a[24]); // Sum(42) res[43] = fma52hi(res[43], a[18], a[24]); // Sum(42) res[43] = fma52lo(res[43], a[19], a[24]); // Sum(43) res[44] = fma52hi(res[44], a[19], a[24]); // Sum(43) res[44] = fma52lo(res[44], a[20], a[24]); // Sum(44) res[45] = fma52hi(res[45], a[20], a[24]); // Sum(44) res[45] = fma52lo(res[45], a[21], a[24]); // Sum(45) res[46] = fma52hi(res[46], a[21], a[24]); // Sum(45) res[46] = fma52lo(res[46], a[22], a[24]); // Sum(46) res[47] = fma52hi(res[47], a[22], a[24]); // Sum(46) res[47] = fma52lo(res[47], a[23], a[24]); // Sum(47) res[48] = fma52hi(res[48], a[23], a[24]); // Sum(47) res[36] = fma52lo(res[36], a[11], a[25]); // Sum(36) res[37] = fma52hi(res[37], a[11], a[25]); // Sum(36) res[37] = fma52lo(res[37], a[12], a[25]); // Sum(37) res[38] = fma52hi(res[38], a[12], a[25]); // Sum(37) res[38] = fma52lo(res[38], a[13], a[25]); // Sum(38) res[39] = fma52hi(res[39], a[13], a[25]); // Sum(38) res[39] = fma52lo(res[39], a[14], a[25]); // Sum(39) res[40] = fma52hi(res[40], a[14], a[25]); // Sum(39) res[40] = fma52lo(res[40], a[15], a[25]); // Sum(40) res[41] = fma52hi(res[41], a[15], a[25]); // Sum(40) res[41] = fma52lo(res[41], a[16], a[25]); // Sum(41) res[42] = fma52hi(res[42], a[16], a[25]); // Sum(41) res[42] = fma52lo(res[42], a[17], a[25]); // Sum(42) res[43] = fma52hi(res[43], a[17], a[25]); // Sum(42) res[43] = fma52lo(res[43], a[18], a[25]); // Sum(43) res[44] = fma52hi(res[44], a[18], a[25]); // Sum(43) res[44] = fma52lo(res[44], a[19], a[25]); // Sum(44) res[45] = fma52hi(res[45], a[19], a[25]); // Sum(44) res[45] = fma52lo(res[45], a[20], a[25]); // Sum(45) res[46] = fma52hi(res[46], a[20], a[25]); // Sum(45) res[46] = fma52lo(res[46], a[21], a[25]); // Sum(46) res[47] = fma52hi(res[47], a[21], a[25]); // Sum(46) res[47] = fma52lo(res[47], a[22], a[25]); // Sum(47) res[48] = fma52hi(res[48], a[22], a[25]); // Sum(47) res[36] = fma52lo(res[36], a[10], a[26]); // Sum(36) res[37] = fma52hi(res[37], a[10], a[26]); // Sum(36) res[37] = fma52lo(res[37], a[11], a[26]); // Sum(37) res[38] = fma52hi(res[38], a[11], a[26]); // Sum(37) res[38] = fma52lo(res[38], a[12], a[26]); // Sum(38) res[39] = fma52hi(res[39], a[12], a[26]); // Sum(38) res[39] = fma52lo(res[39], a[13], a[26]); // Sum(39) res[40] = fma52hi(res[40], a[13], a[26]); // Sum(39) res[40] = fma52lo(res[40], a[14], a[26]); // Sum(40) res[41] = fma52hi(res[41], a[14], a[26]); // Sum(40) res[41] = fma52lo(res[41], a[15], a[26]); // Sum(41) res[42] = fma52hi(res[42], a[15], a[26]); // Sum(41) res[42] = fma52lo(res[42], a[16], a[26]); // Sum(42) res[43] = fma52hi(res[43], a[16], a[26]); // Sum(42) res[43] = fma52lo(res[43], a[17], a[26]); // Sum(43) res[44] = fma52hi(res[44], a[17], a[26]); // Sum(43) res[44] = fma52lo(res[44], a[18], a[26]); // Sum(44) res[45] = fma52hi(res[45], a[18], a[26]); // Sum(44) res[45] = fma52lo(res[45], a[19], a[26]); // Sum(45) res[46] = fma52hi(res[46], a[19], a[26]); // Sum(45) res[46] = fma52lo(res[46], a[20], a[26]); // Sum(46) res[47] = fma52hi(res[47], a[20], a[26]); // Sum(46) res[47] = fma52lo(res[47], a[21], a[26]); // Sum(47) res[48] = fma52hi(res[48], a[21], a[26]); // Sum(47) res[36] = fma52lo(res[36], a[9], a[27]); // Sum(36) res[37] = fma52hi(res[37], a[9], a[27]); // Sum(36) res[37] = fma52lo(res[37], a[10], a[27]); // Sum(37) res[38] = fma52hi(res[38], a[10], a[27]); // Sum(37) res[38] = fma52lo(res[38], a[11], a[27]); // Sum(38) res[39] = fma52hi(res[39], a[11], a[27]); // Sum(38) res[39] = fma52lo(res[39], a[12], a[27]); // Sum(39) res[40] = fma52hi(res[40], a[12], a[27]); // Sum(39) res[40] = fma52lo(res[40], a[13], a[27]); // Sum(40) res[41] = fma52hi(res[41], a[13], a[27]); // Sum(40) res[41] = fma52lo(res[41], a[14], a[27]); // Sum(41) res[42] = fma52hi(res[42], a[14], a[27]); // Sum(41) res[42] = fma52lo(res[42], a[15], a[27]); // Sum(42) res[43] = fma52hi(res[43], a[15], a[27]); // Sum(42) res[43] = fma52lo(res[43], a[16], a[27]); // Sum(43) res[44] = fma52hi(res[44], a[16], a[27]); // Sum(43) res[44] = fma52lo(res[44], a[17], a[27]); // Sum(44) res[45] = fma52hi(res[45], a[17], a[27]); // Sum(44) res[45] = fma52lo(res[45], a[18], a[27]); // Sum(45) res[46] = fma52hi(res[46], a[18], a[27]); // Sum(45) res[46] = fma52lo(res[46], a[19], a[27]); // Sum(46) res[47] = fma52hi(res[47], a[19], a[27]); // Sum(46) res[47] = fma52lo(res[47], a[20], a[27]); // Sum(47) res[48] = fma52hi(res[48], a[20], a[27]); // Sum(47) res[36] = fma52lo(res[36], a[8], a[28]); // Sum(36) res[37] = fma52hi(res[37], a[8], a[28]); // Sum(36) res[37] = fma52lo(res[37], a[9], a[28]); // Sum(37) res[38] = fma52hi(res[38], a[9], a[28]); // Sum(37) res[38] = fma52lo(res[38], a[10], a[28]); // Sum(38) res[39] = fma52hi(res[39], a[10], a[28]); // Sum(38) res[39] = fma52lo(res[39], a[11], a[28]); // Sum(39) res[40] = fma52hi(res[40], a[11], a[28]); // Sum(39) res[40] = fma52lo(res[40], a[12], a[28]); // Sum(40) res[41] = fma52hi(res[41], a[12], a[28]); // Sum(40) res[41] = fma52lo(res[41], a[13], a[28]); // Sum(41) res[42] = fma52hi(res[42], a[13], a[28]); // Sum(41) res[42] = fma52lo(res[42], a[14], a[28]); // Sum(42) res[43] = fma52hi(res[43], a[14], a[28]); // Sum(42) res[43] = fma52lo(res[43], a[15], a[28]); // Sum(43) res[44] = fma52hi(res[44], a[15], a[28]); // Sum(43) res[44] = fma52lo(res[44], a[16], a[28]); // Sum(44) res[45] = fma52hi(res[45], a[16], a[28]); // Sum(44) res[45] = fma52lo(res[45], a[17], a[28]); // Sum(45) res[46] = fma52hi(res[46], a[17], a[28]); // Sum(45) res[46] = fma52lo(res[46], a[18], a[28]); // Sum(46) res[47] = fma52hi(res[47], a[18], a[28]); // Sum(46) res[47] = fma52lo(res[47], a[19], a[28]); // Sum(47) res[48] = fma52hi(res[48], a[19], a[28]); // Sum(47) res[36] = fma52lo(res[36], a[7], a[29]); // Sum(36) res[37] = fma52hi(res[37], a[7], a[29]); // Sum(36) res[37] = fma52lo(res[37], a[8], a[29]); // Sum(37) res[38] = fma52hi(res[38], a[8], a[29]); // Sum(37) res[38] = fma52lo(res[38], a[9], a[29]); // Sum(38) res[39] = fma52hi(res[39], a[9], a[29]); // Sum(38) res[39] = fma52lo(res[39], a[10], a[29]); // Sum(39) res[40] = fma52hi(res[40], a[10], a[29]); // Sum(39) res[40] = fma52lo(res[40], a[11], a[29]); // Sum(40) res[41] = fma52hi(res[41], a[11], a[29]); // Sum(40) res[41] = fma52lo(res[41], a[12], a[29]); // Sum(41) res[42] = fma52hi(res[42], a[12], a[29]); // Sum(41) res[42] = fma52lo(res[42], a[13], a[29]); // Sum(42) res[43] = fma52hi(res[43], a[13], a[29]); // Sum(42) res[43] = fma52lo(res[43], a[14], a[29]); // Sum(43) res[44] = fma52hi(res[44], a[14], a[29]); // Sum(43) res[44] = fma52lo(res[44], a[15], a[29]); // Sum(44) res[45] = fma52hi(res[45], a[15], a[29]); // Sum(44) res[45] = fma52lo(res[45], a[16], a[29]); // Sum(45) res[46] = fma52hi(res[46], a[16], a[29]); // Sum(45) res[46] = fma52lo(res[46], a[17], a[29]); // Sum(46) res[47] = fma52hi(res[47], a[17], a[29]); // Sum(46) res[47] = fma52lo(res[47], a[18], a[29]); // Sum(47) res[48] = fma52hi(res[48], a[18], a[29]); // Sum(47) res[36] = fma52lo(res[36], a[6], a[30]); // Sum(36) res[37] = fma52hi(res[37], a[6], a[30]); // Sum(36) res[37] = fma52lo(res[37], a[7], a[30]); // Sum(37) res[38] = fma52hi(res[38], a[7], a[30]); // Sum(37) res[38] = fma52lo(res[38], a[8], a[30]); // Sum(38) res[39] = fma52hi(res[39], a[8], a[30]); // Sum(38) res[39] = fma52lo(res[39], a[9], a[30]); // Sum(39) res[40] = fma52hi(res[40], a[9], a[30]); // Sum(39) res[40] = fma52lo(res[40], a[10], a[30]); // Sum(40) res[41] = fma52hi(res[41], a[10], a[30]); // Sum(40) res[41] = fma52lo(res[41], a[11], a[30]); // Sum(41) res[42] = fma52hi(res[42], a[11], a[30]); // Sum(41) res[42] = fma52lo(res[42], a[12], a[30]); // Sum(42) res[43] = fma52hi(res[43], a[12], a[30]); // Sum(42) res[43] = fma52lo(res[43], a[13], a[30]); // Sum(43) res[44] = fma52hi(res[44], a[13], a[30]); // Sum(43) res[44] = fma52lo(res[44], a[14], a[30]); // Sum(44) res[45] = fma52hi(res[45], a[14], a[30]); // Sum(44) res[45] = fma52lo(res[45], a[15], a[30]); // Sum(45) res[46] = fma52hi(res[46], a[15], a[30]); // Sum(45) res[46] = fma52lo(res[46], a[16], a[30]); // Sum(46) res[47] = fma52hi(res[47], a[16], a[30]); // Sum(46) res[47] = fma52lo(res[47], a[17], a[30]); // Sum(47) res[48] = fma52hi(res[48], a[17], a[30]); // Sum(47) res[36] = fma52lo(res[36], a[5], a[31]); // Sum(36) res[37] = fma52hi(res[37], a[5], a[31]); // Sum(36) res[37] = fma52lo(res[37], a[6], a[31]); // Sum(37) res[38] = fma52hi(res[38], a[6], a[31]); // Sum(37) res[38] = fma52lo(res[38], a[7], a[31]); // Sum(38) res[39] = fma52hi(res[39], a[7], a[31]); // Sum(38) res[39] = fma52lo(res[39], a[8], a[31]); // Sum(39) res[40] = fma52hi(res[40], a[8], a[31]); // Sum(39) res[40] = fma52lo(res[40], a[9], a[31]); // Sum(40) res[41] = fma52hi(res[41], a[9], a[31]); // Sum(40) res[41] = fma52lo(res[41], a[10], a[31]); // Sum(41) res[42] = fma52hi(res[42], a[10], a[31]); // Sum(41) res[42] = fma52lo(res[42], a[11], a[31]); // Sum(42) res[43] = fma52hi(res[43], a[11], a[31]); // Sum(42) res[43] = fma52lo(res[43], a[12], a[31]); // Sum(43) res[44] = fma52hi(res[44], a[12], a[31]); // Sum(43) res[44] = fma52lo(res[44], a[13], a[31]); // Sum(44) res[45] = fma52hi(res[45], a[13], a[31]); // Sum(44) res[45] = fma52lo(res[45], a[14], a[31]); // Sum(45) res[46] = fma52hi(res[46], a[14], a[31]); // Sum(45) res[46] = fma52lo(res[46], a[15], a[31]); // Sum(46) res[47] = fma52hi(res[47], a[15], a[31]); // Sum(46) res[47] = fma52lo(res[47], a[16], a[31]); // Sum(47) res[48] = fma52hi(res[48], a[16], a[31]); // Sum(47) res[36] = fma52lo(res[36], a[4], a[32]); // Sum(36) res[37] = fma52hi(res[37], a[4], a[32]); // Sum(36) res[37] = fma52lo(res[37], a[5], a[32]); // Sum(37) res[38] = fma52hi(res[38], a[5], a[32]); // Sum(37) res[38] = fma52lo(res[38], a[6], a[32]); // Sum(38) res[39] = fma52hi(res[39], a[6], a[32]); // Sum(38) res[39] = fma52lo(res[39], a[7], a[32]); // Sum(39) res[40] = fma52hi(res[40], a[7], a[32]); // Sum(39) res[40] = fma52lo(res[40], a[8], a[32]); // Sum(40) res[41] = fma52hi(res[41], a[8], a[32]); // Sum(40) res[41] = fma52lo(res[41], a[9], a[32]); // Sum(41) res[42] = fma52hi(res[42], a[9], a[32]); // Sum(41) res[42] = fma52lo(res[42], a[10], a[32]); // Sum(42) res[43] = fma52hi(res[43], a[10], a[32]); // Sum(42) res[43] = fma52lo(res[43], a[11], a[32]); // Sum(43) res[44] = fma52hi(res[44], a[11], a[32]); // Sum(43) res[44] = fma52lo(res[44], a[12], a[32]); // Sum(44) res[45] = fma52hi(res[45], a[12], a[32]); // Sum(44) res[45] = fma52lo(res[45], a[13], a[32]); // Sum(45) res[46] = fma52hi(res[46], a[13], a[32]); // Sum(45) res[46] = fma52lo(res[46], a[14], a[32]); // Sum(46) res[47] = fma52hi(res[47], a[14], a[32]); // Sum(46) res[47] = fma52lo(res[47], a[15], a[32]); // Sum(47) res[48] = fma52hi(res[48], a[15], a[32]); // Sum(47) res[36] = fma52lo(res[36], a[3], a[33]); // Sum(36) res[37] = fma52hi(res[37], a[3], a[33]); // Sum(36) res[37] = fma52lo(res[37], a[4], a[33]); // Sum(37) res[38] = fma52hi(res[38], a[4], a[33]); // Sum(37) res[38] = fma52lo(res[38], a[5], a[33]); // Sum(38) res[39] = fma52hi(res[39], a[5], a[33]); // Sum(38) res[39] = fma52lo(res[39], a[6], a[33]); // Sum(39) res[40] = fma52hi(res[40], a[6], a[33]); // Sum(39) res[40] = fma52lo(res[40], a[7], a[33]); // Sum(40) res[41] = fma52hi(res[41], a[7], a[33]); // Sum(40) res[41] = fma52lo(res[41], a[8], a[33]); // Sum(41) res[42] = fma52hi(res[42], a[8], a[33]); // Sum(41) res[42] = fma52lo(res[42], a[9], a[33]); // Sum(42) res[43] = fma52hi(res[43], a[9], a[33]); // Sum(42) res[43] = fma52lo(res[43], a[10], a[33]); // Sum(43) res[44] = fma52hi(res[44], a[10], a[33]); // Sum(43) res[44] = fma52lo(res[44], a[11], a[33]); // Sum(44) res[45] = fma52hi(res[45], a[11], a[33]); // Sum(44) res[45] = fma52lo(res[45], a[12], a[33]); // Sum(45) res[46] = fma52hi(res[46], a[12], a[33]); // Sum(45) res[46] = fma52lo(res[46], a[13], a[33]); // Sum(46) res[47] = fma52hi(res[47], a[13], a[33]); // Sum(46) res[47] = fma52lo(res[47], a[14], a[33]); // Sum(47) res[48] = fma52hi(res[48], a[14], a[33]); // Sum(47) res[36] = fma52lo(res[36], a[2], a[34]); // Sum(36) res[37] = fma52hi(res[37], a[2], a[34]); // Sum(36) res[37] = fma52lo(res[37], a[3], a[34]); // Sum(37) res[38] = fma52hi(res[38], a[3], a[34]); // Sum(37) res[38] = fma52lo(res[38], a[4], a[34]); // Sum(38) res[39] = fma52hi(res[39], a[4], a[34]); // Sum(38) res[39] = fma52lo(res[39], a[5], a[34]); // Sum(39) res[40] = fma52hi(res[40], a[5], a[34]); // Sum(39) res[40] = fma52lo(res[40], a[6], a[34]); // Sum(40) res[41] = fma52hi(res[41], a[6], a[34]); // Sum(40) res[41] = fma52lo(res[41], a[7], a[34]); // Sum(41) res[42] = fma52hi(res[42], a[7], a[34]); // Sum(41) res[42] = fma52lo(res[42], a[8], a[34]); // Sum(42) res[43] = fma52hi(res[43], a[8], a[34]); // Sum(42) res[43] = fma52lo(res[43], a[9], a[34]); // Sum(43) res[44] = fma52hi(res[44], a[9], a[34]); // Sum(43) res[44] = fma52lo(res[44], a[10], a[34]); // Sum(44) res[45] = fma52hi(res[45], a[10], a[34]); // Sum(44) res[45] = fma52lo(res[45], a[11], a[34]); // Sum(45) res[46] = fma52hi(res[46], a[11], a[34]); // Sum(45) res[46] = fma52lo(res[46], a[12], a[34]); // Sum(46) res[47] = fma52hi(res[47], a[12], a[34]); // Sum(46) res[47] = fma52lo(res[47], a[13], a[34]); // Sum(47) res[48] = fma52hi(res[48], a[13], a[34]); // Sum(47) res[36] = fma52lo(res[36], a[1], a[35]); // Sum(36) res[37] = fma52hi(res[37], a[1], a[35]); // Sum(36) res[37] = fma52lo(res[37], a[2], a[35]); // Sum(37) res[38] = fma52hi(res[38], a[2], a[35]); // Sum(37) res[38] = fma52lo(res[38], a[3], a[35]); // Sum(38) res[39] = fma52hi(res[39], a[3], a[35]); // Sum(38) res[39] = fma52lo(res[39], a[4], a[35]); // Sum(39) res[40] = fma52hi(res[40], a[4], a[35]); // Sum(39) res[40] = fma52lo(res[40], a[5], a[35]); // Sum(40) res[41] = fma52hi(res[41], a[5], a[35]); // Sum(40) res[41] = fma52lo(res[41], a[6], a[35]); // Sum(41) res[42] = fma52hi(res[42], a[6], a[35]); // Sum(41) res[42] = fma52lo(res[42], a[7], a[35]); // Sum(42) res[43] = fma52hi(res[43], a[7], a[35]); // Sum(42) res[43] = fma52lo(res[43], a[8], a[35]); // Sum(43) res[44] = fma52hi(res[44], a[8], a[35]); // Sum(43) res[44] = fma52lo(res[44], a[9], a[35]); // Sum(44) res[45] = fma52hi(res[45], a[9], a[35]); // Sum(44) res[45] = fma52lo(res[45], a[10], a[35]); // Sum(45) res[46] = fma52hi(res[46], a[10], a[35]); // Sum(45) res[46] = fma52lo(res[46], a[11], a[35]); // Sum(46) res[47] = fma52hi(res[47], a[11], a[35]); // Sum(46) res[47] = fma52lo(res[47], a[12], a[35]); // Sum(47) res[48] = fma52hi(res[48], a[12], a[35]); // Sum(47) res[36] = fma52lo(res[36], a[0], a[36]); // Sum(36) res[37] = fma52hi(res[37], a[0], a[36]); // Sum(36) res[37] = fma52lo(res[37], a[1], a[36]); // Sum(37) res[38] = fma52hi(res[38], a[1], a[36]); // Sum(37) res[38] = fma52lo(res[38], a[2], a[36]); // Sum(38) res[39] = fma52hi(res[39], a[2], a[36]); // Sum(38) res[39] = fma52lo(res[39], a[3], a[36]); // Sum(39) res[40] = fma52hi(res[40], a[3], a[36]); // Sum(39) res[40] = fma52lo(res[40], a[4], a[36]); // Sum(40) res[41] = fma52hi(res[41], a[4], a[36]); // Sum(40) res[41] = fma52lo(res[41], a[5], a[36]); // Sum(41) res[42] = fma52hi(res[42], a[5], a[36]); // Sum(41) res[42] = fma52lo(res[42], a[6], a[36]); // Sum(42) res[43] = fma52hi(res[43], a[6], a[36]); // Sum(42) res[43] = fma52lo(res[43], a[7], a[36]); // Sum(43) res[44] = fma52hi(res[44], a[7], a[36]); // Sum(43) res[44] = fma52lo(res[44], a[8], a[36]); // Sum(44) res[45] = fma52hi(res[45], a[8], a[36]); // Sum(44) res[45] = fma52lo(res[45], a[9], a[36]); // Sum(45) res[46] = fma52hi(res[46], a[9], a[36]); // Sum(45) res[46] = fma52lo(res[46], a[10], a[36]); // Sum(46) res[47] = fma52hi(res[47], a[10], a[36]); // Sum(46) res[47] = fma52lo(res[47], a[11], a[36]); // Sum(47) res[48] = fma52hi(res[48], a[11], a[36]); // Sum(47) res[37] = fma52lo(res[37], a[0], a[37]); // Sum(37) res[38] = fma52hi(res[38], a[0], a[37]); // Sum(37) res[38] = fma52lo(res[38], a[1], a[37]); // Sum(38) res[39] = fma52hi(res[39], a[1], a[37]); // Sum(38) res[39] = fma52lo(res[39], a[2], a[37]); // Sum(39) res[40] = fma52hi(res[40], a[2], a[37]); // Sum(39) res[40] = fma52lo(res[40], a[3], a[37]); // Sum(40) res[41] = fma52hi(res[41], a[3], a[37]); // Sum(40) res[41] = fma52lo(res[41], a[4], a[37]); // Sum(41) res[42] = fma52hi(res[42], a[4], a[37]); // Sum(41) res[42] = fma52lo(res[42], a[5], a[37]); // Sum(42) res[43] = fma52hi(res[43], a[5], a[37]); // Sum(42) res[43] = fma52lo(res[43], a[6], a[37]); // Sum(43) res[44] = fma52hi(res[44], a[6], a[37]); // Sum(43) res[44] = fma52lo(res[44], a[7], a[37]); // Sum(44) res[45] = fma52hi(res[45], a[7], a[37]); // Sum(44) res[45] = fma52lo(res[45], a[8], a[37]); // Sum(45) res[46] = fma52hi(res[46], a[8], a[37]); // Sum(45) res[46] = fma52lo(res[46], a[9], a[37]); // Sum(46) res[47] = fma52hi(res[47], a[9], a[37]); // Sum(46) res[47] = fma52lo(res[47], a[10], a[37]); // Sum(47) res[48] = fma52hi(res[48], a[10], a[37]); // Sum(47) res[38] = fma52lo(res[38], a[0], a[38]); // Sum(38) res[39] = fma52hi(res[39], a[0], a[38]); // Sum(38) res[39] = fma52lo(res[39], a[1], a[38]); // Sum(39) res[40] = fma52hi(res[40], a[1], a[38]); // Sum(39) res[40] = fma52lo(res[40], a[2], a[38]); // Sum(40) res[41] = fma52hi(res[41], a[2], a[38]); // Sum(40) res[41] = fma52lo(res[41], a[3], a[38]); // Sum(41) res[42] = fma52hi(res[42], a[3], a[38]); // Sum(41) res[42] = fma52lo(res[42], a[4], a[38]); // Sum(42) res[43] = fma52hi(res[43], a[4], a[38]); // Sum(42) res[43] = fma52lo(res[43], a[5], a[38]); // Sum(43) res[44] = fma52hi(res[44], a[5], a[38]); // Sum(43) res[44] = fma52lo(res[44], a[6], a[38]); // Sum(44) res[45] = fma52hi(res[45], a[6], a[38]); // Sum(44) res[45] = fma52lo(res[45], a[7], a[38]); // Sum(45) res[46] = fma52hi(res[46], a[7], a[38]); // Sum(45) res[46] = fma52lo(res[46], a[8], a[38]); // Sum(46) res[47] = fma52hi(res[47], a[8], a[38]); // Sum(46) res[47] = fma52lo(res[47], a[9], a[38]); // Sum(47) res[48] = fma52hi(res[48], a[9], a[38]); // Sum(47) res[39] = fma52lo(res[39], a[0], a[39]); // Sum(39) res[40] = fma52hi(res[40], a[0], a[39]); // Sum(39) res[40] = fma52lo(res[40], a[1], a[39]); // Sum(40) res[41] = fma52hi(res[41], a[1], a[39]); // Sum(40) res[41] = fma52lo(res[41], a[2], a[39]); // Sum(41) res[42] = fma52hi(res[42], a[2], a[39]); // Sum(41) res[42] = fma52lo(res[42], a[3], a[39]); // Sum(42) res[43] = fma52hi(res[43], a[3], a[39]); // Sum(42) res[43] = fma52lo(res[43], a[4], a[39]); // Sum(43) res[44] = fma52hi(res[44], a[4], a[39]); // Sum(43) res[44] = fma52lo(res[44], a[5], a[39]); // Sum(44) res[45] = fma52hi(res[45], a[5], a[39]); // Sum(44) res[45] = fma52lo(res[45], a[6], a[39]); // Sum(45) res[46] = fma52hi(res[46], a[6], a[39]); // Sum(45) res[46] = fma52lo(res[46], a[7], a[39]); // Sum(46) res[47] = fma52hi(res[47], a[7], a[39]); // Sum(46) res[47] = fma52lo(res[47], a[8], a[39]); // Sum(47) res[48] = fma52hi(res[48], a[8], a[39]); // Sum(47) res[36] = add64(res[36], res[36]); // Double(36) res[37] = add64(res[37], res[37]); // Double(37) res[38] = add64(res[38], res[38]); // Double(38) res[39] = add64(res[39], res[39]); // Double(39) res[40] = add64(res[40], res[40]); // Double(40) res[41] = add64(res[41], res[41]); // Double(41) res[42] = add64(res[42], res[42]); // Double(42) res[43] = add64(res[43], res[43]); // Double(43) res[44] = add64(res[44], res[44]); // Double(44) res[45] = add64(res[45], res[45]); // Double(45) res[46] = add64(res[46], res[46]); // Double(46) res[47] = add64(res[47], res[47]); // Double(47) res[36] = fma52lo(res[36], a[18], a[18]); // Add sqr(36) res[37] = fma52hi(res[37], a[18], a[18]); // Add sqr(36) res[38] = fma52lo(res[38], a[19], a[19]); // Add sqr(38) res[39] = fma52hi(res[39], a[19], a[19]); // Add sqr(38) res[40] = fma52lo(res[40], a[20], a[20]); // Add sqr(40) res[41] = fma52hi(res[41], a[20], a[20]); // Add sqr(40) res[42] = fma52lo(res[42], a[21], a[21]); // Add sqr(42) res[43] = fma52hi(res[43], a[21], a[21]); // Add sqr(42) res[44] = fma52lo(res[44], a[22], a[22]); // Add sqr(44) res[45] = fma52hi(res[45], a[22], a[22]); // Add sqr(44) res[46] = fma52lo(res[46], a[23], a[23]); // Add sqr(46) res[47] = fma52hi(res[47], a[23], a[23]); // Add sqr(46) res[48] = fma52lo(res[48], a[23], a[25]); // Sum(48) res[49] = fma52hi(res[49], a[23], a[25]); // Sum(48) res[49] = fma52lo(res[49], a[24], a[25]); // Sum(49) res[50] = fma52hi(res[50], a[24], a[25]); // Sum(49) res[48] = fma52lo(res[48], a[22], a[26]); // Sum(48) res[49] = fma52hi(res[49], a[22], a[26]); // Sum(48) res[49] = fma52lo(res[49], a[23], a[26]); // Sum(49) res[50] = fma52hi(res[50], a[23], a[26]); // Sum(49) res[50] = fma52lo(res[50], a[24], a[26]); // Sum(50) res[51] = fma52hi(res[51], a[24], a[26]); // Sum(50) res[51] = fma52lo(res[51], a[25], a[26]); // Sum(51) res[52] = fma52hi(res[52], a[25], a[26]); // Sum(51) res[48] = fma52lo(res[48], a[21], a[27]); // Sum(48) res[49] = fma52hi(res[49], a[21], a[27]); // Sum(48) res[49] = fma52lo(res[49], a[22], a[27]); // Sum(49) res[50] = fma52hi(res[50], a[22], a[27]); // Sum(49) res[50] = fma52lo(res[50], a[23], a[27]); // Sum(50) res[51] = fma52hi(res[51], a[23], a[27]); // Sum(50) res[51] = fma52lo(res[51], a[24], a[27]); // Sum(51) res[52] = fma52hi(res[52], a[24], a[27]); // Sum(51) res[52] = fma52lo(res[52], a[25], a[27]); // Sum(52) res[53] = fma52hi(res[53], a[25], a[27]); // Sum(52) res[53] = fma52lo(res[53], a[26], a[27]); // Sum(53) res[54] = fma52hi(res[54], a[26], a[27]); // Sum(53) res[48] = fma52lo(res[48], a[20], a[28]); // Sum(48) res[49] = fma52hi(res[49], a[20], a[28]); // Sum(48) res[49] = fma52lo(res[49], a[21], a[28]); // Sum(49) res[50] = fma52hi(res[50], a[21], a[28]); // Sum(49) res[50] = fma52lo(res[50], a[22], a[28]); // Sum(50) res[51] = fma52hi(res[51], a[22], a[28]); // Sum(50) res[51] = fma52lo(res[51], a[23], a[28]); // Sum(51) res[52] = fma52hi(res[52], a[23], a[28]); // Sum(51) res[52] = fma52lo(res[52], a[24], a[28]); // Sum(52) res[53] = fma52hi(res[53], a[24], a[28]); // Sum(52) res[53] = fma52lo(res[53], a[25], a[28]); // Sum(53) res[54] = fma52hi(res[54], a[25], a[28]); // Sum(53) res[54] = fma52lo(res[54], a[26], a[28]); // Sum(54) res[55] = fma52hi(res[55], a[26], a[28]); // Sum(54) res[55] = fma52lo(res[55], a[27], a[28]); // Sum(55) res[56] = fma52hi(res[56], a[27], a[28]); // Sum(55) res[48] = fma52lo(res[48], a[19], a[29]); // Sum(48) res[49] = fma52hi(res[49], a[19], a[29]); // Sum(48) res[49] = fma52lo(res[49], a[20], a[29]); // Sum(49) res[50] = fma52hi(res[50], a[20], a[29]); // Sum(49) res[50] = fma52lo(res[50], a[21], a[29]); // Sum(50) res[51] = fma52hi(res[51], a[21], a[29]); // Sum(50) res[51] = fma52lo(res[51], a[22], a[29]); // Sum(51) res[52] = fma52hi(res[52], a[22], a[29]); // Sum(51) res[52] = fma52lo(res[52], a[23], a[29]); // Sum(52) res[53] = fma52hi(res[53], a[23], a[29]); // Sum(52) res[53] = fma52lo(res[53], a[24], a[29]); // Sum(53) res[54] = fma52hi(res[54], a[24], a[29]); // Sum(53) res[54] = fma52lo(res[54], a[25], a[29]); // Sum(54) res[55] = fma52hi(res[55], a[25], a[29]); // Sum(54) res[55] = fma52lo(res[55], a[26], a[29]); // Sum(55) res[56] = fma52hi(res[56], a[26], a[29]); // Sum(55) res[56] = fma52lo(res[56], a[27], a[29]); // Sum(56) res[57] = fma52hi(res[57], a[27], a[29]); // Sum(56) res[57] = fma52lo(res[57], a[28], a[29]); // Sum(57) res[58] = fma52hi(res[58], a[28], a[29]); // Sum(57) res[48] = fma52lo(res[48], a[18], a[30]); // Sum(48) res[49] = fma52hi(res[49], a[18], a[30]); // Sum(48) res[49] = fma52lo(res[49], a[19], a[30]); // Sum(49) res[50] = fma52hi(res[50], a[19], a[30]); // Sum(49) res[50] = fma52lo(res[50], a[20], a[30]); // Sum(50) res[51] = fma52hi(res[51], a[20], a[30]); // Sum(50) res[51] = fma52lo(res[51], a[21], a[30]); // Sum(51) res[52] = fma52hi(res[52], a[21], a[30]); // Sum(51) res[52] = fma52lo(res[52], a[22], a[30]); // Sum(52) res[53] = fma52hi(res[53], a[22], a[30]); // Sum(52) res[53] = fma52lo(res[53], a[23], a[30]); // Sum(53) res[54] = fma52hi(res[54], a[23], a[30]); // Sum(53) res[54] = fma52lo(res[54], a[24], a[30]); // Sum(54) res[55] = fma52hi(res[55], a[24], a[30]); // Sum(54) res[55] = fma52lo(res[55], a[25], a[30]); // Sum(55) res[56] = fma52hi(res[56], a[25], a[30]); // Sum(55) res[56] = fma52lo(res[56], a[26], a[30]); // Sum(56) res[57] = fma52hi(res[57], a[26], a[30]); // Sum(56) res[57] = fma52lo(res[57], a[27], a[30]); // Sum(57) res[58] = fma52hi(res[58], a[27], a[30]); // Sum(57) res[58] = fma52lo(res[58], a[28], a[30]); // Sum(58) res[59] = fma52hi(res[59], a[28], a[30]); // Sum(58) res[59] = fma52lo(res[59], a[29], a[30]); // Sum(59) res[60] = fma52hi(res[60], a[29], a[30]); // Sum(59) res[48] = fma52lo(res[48], a[17], a[31]); // Sum(48) res[49] = fma52hi(res[49], a[17], a[31]); // Sum(48) res[49] = fma52lo(res[49], a[18], a[31]); // Sum(49) res[50] = fma52hi(res[50], a[18], a[31]); // Sum(49) res[50] = fma52lo(res[50], a[19], a[31]); // Sum(50) res[51] = fma52hi(res[51], a[19], a[31]); // Sum(50) res[51] = fma52lo(res[51], a[20], a[31]); // Sum(51) res[52] = fma52hi(res[52], a[20], a[31]); // Sum(51) res[52] = fma52lo(res[52], a[21], a[31]); // Sum(52) res[53] = fma52hi(res[53], a[21], a[31]); // Sum(52) res[53] = fma52lo(res[53], a[22], a[31]); // Sum(53) res[54] = fma52hi(res[54], a[22], a[31]); // Sum(53) res[54] = fma52lo(res[54], a[23], a[31]); // Sum(54) res[55] = fma52hi(res[55], a[23], a[31]); // Sum(54) res[55] = fma52lo(res[55], a[24], a[31]); // Sum(55) res[56] = fma52hi(res[56], a[24], a[31]); // Sum(55) res[56] = fma52lo(res[56], a[25], a[31]); // Sum(56) res[57] = fma52hi(res[57], a[25], a[31]); // Sum(56) res[57] = fma52lo(res[57], a[26], a[31]); // Sum(57) res[58] = fma52hi(res[58], a[26], a[31]); // Sum(57) res[58] = fma52lo(res[58], a[27], a[31]); // Sum(58) res[59] = fma52hi(res[59], a[27], a[31]); // Sum(58) res[59] = fma52lo(res[59], a[28], a[31]); // Sum(59) res[60] = fma52hi(res[60], a[28], a[31]); // Sum(59) res[48] = fma52lo(res[48], a[16], a[32]); // Sum(48) res[49] = fma52hi(res[49], a[16], a[32]); // Sum(48) res[49] = fma52lo(res[49], a[17], a[32]); // Sum(49) res[50] = fma52hi(res[50], a[17], a[32]); // Sum(49) res[50] = fma52lo(res[50], a[18], a[32]); // Sum(50) res[51] = fma52hi(res[51], a[18], a[32]); // Sum(50) res[51] = fma52lo(res[51], a[19], a[32]); // Sum(51) res[52] = fma52hi(res[52], a[19], a[32]); // Sum(51) res[52] = fma52lo(res[52], a[20], a[32]); // Sum(52) res[53] = fma52hi(res[53], a[20], a[32]); // Sum(52) res[53] = fma52lo(res[53], a[21], a[32]); // Sum(53) res[54] = fma52hi(res[54], a[21], a[32]); // Sum(53) res[54] = fma52lo(res[54], a[22], a[32]); // Sum(54) res[55] = fma52hi(res[55], a[22], a[32]); // Sum(54) res[55] = fma52lo(res[55], a[23], a[32]); // Sum(55) res[56] = fma52hi(res[56], a[23], a[32]); // Sum(55) res[56] = fma52lo(res[56], a[24], a[32]); // Sum(56) res[57] = fma52hi(res[57], a[24], a[32]); // Sum(56) res[57] = fma52lo(res[57], a[25], a[32]); // Sum(57) res[58] = fma52hi(res[58], a[25], a[32]); // Sum(57) res[58] = fma52lo(res[58], a[26], a[32]); // Sum(58) res[59] = fma52hi(res[59], a[26], a[32]); // Sum(58) res[59] = fma52lo(res[59], a[27], a[32]); // Sum(59) res[60] = fma52hi(res[60], a[27], a[32]); // Sum(59) res[48] = fma52lo(res[48], a[15], a[33]); // Sum(48) res[49] = fma52hi(res[49], a[15], a[33]); // Sum(48) res[49] = fma52lo(res[49], a[16], a[33]); // Sum(49) res[50] = fma52hi(res[50], a[16], a[33]); // Sum(49) res[50] = fma52lo(res[50], a[17], a[33]); // Sum(50) res[51] = fma52hi(res[51], a[17], a[33]); // Sum(50) res[51] = fma52lo(res[51], a[18], a[33]); // Sum(51) res[52] = fma52hi(res[52], a[18], a[33]); // Sum(51) res[52] = fma52lo(res[52], a[19], a[33]); // Sum(52) res[53] = fma52hi(res[53], a[19], a[33]); // Sum(52) res[53] = fma52lo(res[53], a[20], a[33]); // Sum(53) res[54] = fma52hi(res[54], a[20], a[33]); // Sum(53) res[54] = fma52lo(res[54], a[21], a[33]); // Sum(54) res[55] = fma52hi(res[55], a[21], a[33]); // Sum(54) res[55] = fma52lo(res[55], a[22], a[33]); // Sum(55) res[56] = fma52hi(res[56], a[22], a[33]); // Sum(55) res[56] = fma52lo(res[56], a[23], a[33]); // Sum(56) res[57] = fma52hi(res[57], a[23], a[33]); // Sum(56) res[57] = fma52lo(res[57], a[24], a[33]); // Sum(57) res[58] = fma52hi(res[58], a[24], a[33]); // Sum(57) res[58] = fma52lo(res[58], a[25], a[33]); // Sum(58) res[59] = fma52hi(res[59], a[25], a[33]); // Sum(58) res[59] = fma52lo(res[59], a[26], a[33]); // Sum(59) res[60] = fma52hi(res[60], a[26], a[33]); // Sum(59) res[48] = fma52lo(res[48], a[14], a[34]); // Sum(48) res[49] = fma52hi(res[49], a[14], a[34]); // Sum(48) res[49] = fma52lo(res[49], a[15], a[34]); // Sum(49) res[50] = fma52hi(res[50], a[15], a[34]); // Sum(49) res[50] = fma52lo(res[50], a[16], a[34]); // Sum(50) res[51] = fma52hi(res[51], a[16], a[34]); // Sum(50) res[51] = fma52lo(res[51], a[17], a[34]); // Sum(51) res[52] = fma52hi(res[52], a[17], a[34]); // Sum(51) res[52] = fma52lo(res[52], a[18], a[34]); // Sum(52) res[53] = fma52hi(res[53], a[18], a[34]); // Sum(52) res[53] = fma52lo(res[53], a[19], a[34]); // Sum(53) res[54] = fma52hi(res[54], a[19], a[34]); // Sum(53) res[54] = fma52lo(res[54], a[20], a[34]); // Sum(54) res[55] = fma52hi(res[55], a[20], a[34]); // Sum(54) res[55] = fma52lo(res[55], a[21], a[34]); // Sum(55) res[56] = fma52hi(res[56], a[21], a[34]); // Sum(55) res[56] = fma52lo(res[56], a[22], a[34]); // Sum(56) res[57] = fma52hi(res[57], a[22], a[34]); // Sum(56) res[57] = fma52lo(res[57], a[23], a[34]); // Sum(57) res[58] = fma52hi(res[58], a[23], a[34]); // Sum(57) res[58] = fma52lo(res[58], a[24], a[34]); // Sum(58) res[59] = fma52hi(res[59], a[24], a[34]); // Sum(58) res[59] = fma52lo(res[59], a[25], a[34]); // Sum(59) res[60] = fma52hi(res[60], a[25], a[34]); // Sum(59) res[48] = fma52lo(res[48], a[13], a[35]); // Sum(48) res[49] = fma52hi(res[49], a[13], a[35]); // Sum(48) res[49] = fma52lo(res[49], a[14], a[35]); // Sum(49) res[50] = fma52hi(res[50], a[14], a[35]); // Sum(49) res[50] = fma52lo(res[50], a[15], a[35]); // Sum(50) res[51] = fma52hi(res[51], a[15], a[35]); // Sum(50) res[51] = fma52lo(res[51], a[16], a[35]); // Sum(51) res[52] = fma52hi(res[52], a[16], a[35]); // Sum(51) res[52] = fma52lo(res[52], a[17], a[35]); // Sum(52) res[53] = fma52hi(res[53], a[17], a[35]); // Sum(52) res[53] = fma52lo(res[53], a[18], a[35]); // Sum(53) res[54] = fma52hi(res[54], a[18], a[35]); // Sum(53) res[54] = fma52lo(res[54], a[19], a[35]); // Sum(54) res[55] = fma52hi(res[55], a[19], a[35]); // Sum(54) res[55] = fma52lo(res[55], a[20], a[35]); // Sum(55) res[56] = fma52hi(res[56], a[20], a[35]); // Sum(55) res[56] = fma52lo(res[56], a[21], a[35]); // Sum(56) res[57] = fma52hi(res[57], a[21], a[35]); // Sum(56) res[57] = fma52lo(res[57], a[22], a[35]); // Sum(57) res[58] = fma52hi(res[58], a[22], a[35]); // Sum(57) res[58] = fma52lo(res[58], a[23], a[35]); // Sum(58) res[59] = fma52hi(res[59], a[23], a[35]); // Sum(58) res[59] = fma52lo(res[59], a[24], a[35]); // Sum(59) res[60] = fma52hi(res[60], a[24], a[35]); // Sum(59) res[48] = fma52lo(res[48], a[12], a[36]); // Sum(48) res[49] = fma52hi(res[49], a[12], a[36]); // Sum(48) res[49] = fma52lo(res[49], a[13], a[36]); // Sum(49) res[50] = fma52hi(res[50], a[13], a[36]); // Sum(49) res[50] = fma52lo(res[50], a[14], a[36]); // Sum(50) res[51] = fma52hi(res[51], a[14], a[36]); // Sum(50) res[51] = fma52lo(res[51], a[15], a[36]); // Sum(51) res[52] = fma52hi(res[52], a[15], a[36]); // Sum(51) res[52] = fma52lo(res[52], a[16], a[36]); // Sum(52) res[53] = fma52hi(res[53], a[16], a[36]); // Sum(52) res[53] = fma52lo(res[53], a[17], a[36]); // Sum(53) res[54] = fma52hi(res[54], a[17], a[36]); // Sum(53) res[54] = fma52lo(res[54], a[18], a[36]); // Sum(54) res[55] = fma52hi(res[55], a[18], a[36]); // Sum(54) res[55] = fma52lo(res[55], a[19], a[36]); // Sum(55) res[56] = fma52hi(res[56], a[19], a[36]); // Sum(55) res[56] = fma52lo(res[56], a[20], a[36]); // Sum(56) res[57] = fma52hi(res[57], a[20], a[36]); // Sum(56) res[57] = fma52lo(res[57], a[21], a[36]); // Sum(57) res[58] = fma52hi(res[58], a[21], a[36]); // Sum(57) res[58] = fma52lo(res[58], a[22], a[36]); // Sum(58) res[59] = fma52hi(res[59], a[22], a[36]); // Sum(58) res[59] = fma52lo(res[59], a[23], a[36]); // Sum(59) res[60] = fma52hi(res[60], a[23], a[36]); // Sum(59) res[48] = fma52lo(res[48], a[11], a[37]); // Sum(48) res[49] = fma52hi(res[49], a[11], a[37]); // Sum(48) res[49] = fma52lo(res[49], a[12], a[37]); // Sum(49) res[50] = fma52hi(res[50], a[12], a[37]); // Sum(49) res[50] = fma52lo(res[50], a[13], a[37]); // Sum(50) res[51] = fma52hi(res[51], a[13], a[37]); // Sum(50) res[51] = fma52lo(res[51], a[14], a[37]); // Sum(51) res[52] = fma52hi(res[52], a[14], a[37]); // Sum(51) res[52] = fma52lo(res[52], a[15], a[37]); // Sum(52) res[53] = fma52hi(res[53], a[15], a[37]); // Sum(52) res[53] = fma52lo(res[53], a[16], a[37]); // Sum(53) res[54] = fma52hi(res[54], a[16], a[37]); // Sum(53) res[54] = fma52lo(res[54], a[17], a[37]); // Sum(54) res[55] = fma52hi(res[55], a[17], a[37]); // Sum(54) res[55] = fma52lo(res[55], a[18], a[37]); // Sum(55) res[56] = fma52hi(res[56], a[18], a[37]); // Sum(55) res[56] = fma52lo(res[56], a[19], a[37]); // Sum(56) res[57] = fma52hi(res[57], a[19], a[37]); // Sum(56) res[57] = fma52lo(res[57], a[20], a[37]); // Sum(57) res[58] = fma52hi(res[58], a[20], a[37]); // Sum(57) res[58] = fma52lo(res[58], a[21], a[37]); // Sum(58) res[59] = fma52hi(res[59], a[21], a[37]); // Sum(58) res[59] = fma52lo(res[59], a[22], a[37]); // Sum(59) res[60] = fma52hi(res[60], a[22], a[37]); // Sum(59) res[48] = fma52lo(res[48], a[10], a[38]); // Sum(48) res[49] = fma52hi(res[49], a[10], a[38]); // Sum(48) res[49] = fma52lo(res[49], a[11], a[38]); // Sum(49) res[50] = fma52hi(res[50], a[11], a[38]); // Sum(49) res[50] = fma52lo(res[50], a[12], a[38]); // Sum(50) res[51] = fma52hi(res[51], a[12], a[38]); // Sum(50) res[51] = fma52lo(res[51], a[13], a[38]); // Sum(51) res[52] = fma52hi(res[52], a[13], a[38]); // Sum(51) res[52] = fma52lo(res[52], a[14], a[38]); // Sum(52) res[53] = fma52hi(res[53], a[14], a[38]); // Sum(52) res[53] = fma52lo(res[53], a[15], a[38]); // Sum(53) res[54] = fma52hi(res[54], a[15], a[38]); // Sum(53) res[54] = fma52lo(res[54], a[16], a[38]); // Sum(54) res[55] = fma52hi(res[55], a[16], a[38]); // Sum(54) res[55] = fma52lo(res[55], a[17], a[38]); // Sum(55) res[56] = fma52hi(res[56], a[17], a[38]); // Sum(55) res[56] = fma52lo(res[56], a[18], a[38]); // Sum(56) res[57] = fma52hi(res[57], a[18], a[38]); // Sum(56) res[57] = fma52lo(res[57], a[19], a[38]); // Sum(57) res[58] = fma52hi(res[58], a[19], a[38]); // Sum(57) res[58] = fma52lo(res[58], a[20], a[38]); // Sum(58) res[59] = fma52hi(res[59], a[20], a[38]); // Sum(58) res[59] = fma52lo(res[59], a[21], a[38]); // Sum(59) res[60] = fma52hi(res[60], a[21], a[38]); // Sum(59) res[48] = fma52lo(res[48], a[9], a[39]); // Sum(48) res[49] = fma52hi(res[49], a[9], a[39]); // Sum(48) res[49] = fma52lo(res[49], a[10], a[39]); // Sum(49) res[50] = fma52hi(res[50], a[10], a[39]); // Sum(49) res[50] = fma52lo(res[50], a[11], a[39]); // Sum(50) res[51] = fma52hi(res[51], a[11], a[39]); // Sum(50) res[51] = fma52lo(res[51], a[12], a[39]); // Sum(51) res[52] = fma52hi(res[52], a[12], a[39]); // Sum(51) res[52] = fma52lo(res[52], a[13], a[39]); // Sum(52) res[53] = fma52hi(res[53], a[13], a[39]); // Sum(52) res[53] = fma52lo(res[53], a[14], a[39]); // Sum(53) res[54] = fma52hi(res[54], a[14], a[39]); // Sum(53) res[54] = fma52lo(res[54], a[15], a[39]); // Sum(54) res[55] = fma52hi(res[55], a[15], a[39]); // Sum(54) res[55] = fma52lo(res[55], a[16], a[39]); // Sum(55) res[56] = fma52hi(res[56], a[16], a[39]); // Sum(55) res[56] = fma52lo(res[56], a[17], a[39]); // Sum(56) res[57] = fma52hi(res[57], a[17], a[39]); // Sum(56) res[57] = fma52lo(res[57], a[18], a[39]); // Sum(57) res[58] = fma52hi(res[58], a[18], a[39]); // Sum(57) res[58] = fma52lo(res[58], a[19], a[39]); // Sum(58) res[59] = fma52hi(res[59], a[19], a[39]); // Sum(58) res[59] = fma52lo(res[59], a[20], a[39]); // Sum(59) res[60] = fma52hi(res[60], a[20], a[39]); // Sum(59) res[48] = add64(res[48], res[48]); // Double(48) res[49] = add64(res[49], res[49]); // Double(49) res[50] = add64(res[50], res[50]); // Double(50) res[51] = add64(res[51], res[51]); // Double(51) res[52] = add64(res[52], res[52]); // Double(52) res[53] = add64(res[53], res[53]); // Double(53) res[54] = add64(res[54], res[54]); // Double(54) res[55] = add64(res[55], res[55]); // Double(55) res[56] = add64(res[56], res[56]); // Double(56) res[57] = add64(res[57], res[57]); // Double(57) res[58] = add64(res[58], res[58]); // Double(58) res[59] = add64(res[59], res[59]); // Double(59) res[48] = fma52lo(res[48], a[24], a[24]); // Add sqr(48) res[49] = fma52hi(res[49], a[24], a[24]); // Add sqr(48) res[50] = fma52lo(res[50], a[25], a[25]); // Add sqr(50) res[51] = fma52hi(res[51], a[25], a[25]); // Add sqr(50) res[52] = fma52lo(res[52], a[26], a[26]); // Add sqr(52) res[53] = fma52hi(res[53], a[26], a[26]); // Add sqr(52) res[54] = fma52lo(res[54], a[27], a[27]); // Add sqr(54) res[55] = fma52hi(res[55], a[27], a[27]); // Add sqr(54) res[56] = fma52lo(res[56], a[28], a[28]); // Add sqr(56) res[57] = fma52hi(res[57], a[28], a[28]); // Add sqr(56) res[58] = fma52lo(res[58], a[29], a[29]); // Add sqr(58) res[59] = fma52hi(res[59], a[29], a[29]); // Add sqr(58) res[60] = fma52lo(res[60], a[29], a[31]); // Sum(60) res[61] = fma52hi(res[61], a[29], a[31]); // Sum(60) res[61] = fma52lo(res[61], a[30], a[31]); // Sum(61) res[62] = fma52hi(res[62], a[30], a[31]); // Sum(61) res[60] = fma52lo(res[60], a[28], a[32]); // Sum(60) res[61] = fma52hi(res[61], a[28], a[32]); // Sum(60) res[61] = fma52lo(res[61], a[29], a[32]); // Sum(61) res[62] = fma52hi(res[62], a[29], a[32]); // Sum(61) res[62] = fma52lo(res[62], a[30], a[32]); // Sum(62) res[63] = fma52hi(res[63], a[30], a[32]); // Sum(62) res[63] = fma52lo(res[63], a[31], a[32]); // Sum(63) res[64] = fma52hi(res[64], a[31], a[32]); // Sum(63) res[60] = fma52lo(res[60], a[27], a[33]); // Sum(60) res[61] = fma52hi(res[61], a[27], a[33]); // Sum(60) res[61] = fma52lo(res[61], a[28], a[33]); // Sum(61) res[62] = fma52hi(res[62], a[28], a[33]); // Sum(61) res[62] = fma52lo(res[62], a[29], a[33]); // Sum(62) res[63] = fma52hi(res[63], a[29], a[33]); // Sum(62) res[63] = fma52lo(res[63], a[30], a[33]); // Sum(63) res[64] = fma52hi(res[64], a[30], a[33]); // Sum(63) res[64] = fma52lo(res[64], a[31], a[33]); // Sum(64) res[65] = fma52hi(res[65], a[31], a[33]); // Sum(64) res[65] = fma52lo(res[65], a[32], a[33]); // Sum(65) res[66] = fma52hi(res[66], a[32], a[33]); // Sum(65) res[60] = fma52lo(res[60], a[26], a[34]); // Sum(60) res[61] = fma52hi(res[61], a[26], a[34]); // Sum(60) res[61] = fma52lo(res[61], a[27], a[34]); // Sum(61) res[62] = fma52hi(res[62], a[27], a[34]); // Sum(61) res[62] = fma52lo(res[62], a[28], a[34]); // Sum(62) res[63] = fma52hi(res[63], a[28], a[34]); // Sum(62) res[63] = fma52lo(res[63], a[29], a[34]); // Sum(63) res[64] = fma52hi(res[64], a[29], a[34]); // Sum(63) res[64] = fma52lo(res[64], a[30], a[34]); // Sum(64) res[65] = fma52hi(res[65], a[30], a[34]); // Sum(64) res[65] = fma52lo(res[65], a[31], a[34]); // Sum(65) res[66] = fma52hi(res[66], a[31], a[34]); // Sum(65) res[66] = fma52lo(res[66], a[32], a[34]); // Sum(66) res[67] = fma52hi(res[67], a[32], a[34]); // Sum(66) res[67] = fma52lo(res[67], a[33], a[34]); // Sum(67) res[68] = fma52hi(res[68], a[33], a[34]); // Sum(67) res[60] = fma52lo(res[60], a[25], a[35]); // Sum(60) res[61] = fma52hi(res[61], a[25], a[35]); // Sum(60) res[61] = fma52lo(res[61], a[26], a[35]); // Sum(61) res[62] = fma52hi(res[62], a[26], a[35]); // Sum(61) res[62] = fma52lo(res[62], a[27], a[35]); // Sum(62) res[63] = fma52hi(res[63], a[27], a[35]); // Sum(62) res[63] = fma52lo(res[63], a[28], a[35]); // Sum(63) res[64] = fma52hi(res[64], a[28], a[35]); // Sum(63) res[64] = fma52lo(res[64], a[29], a[35]); // Sum(64) res[65] = fma52hi(res[65], a[29], a[35]); // Sum(64) res[65] = fma52lo(res[65], a[30], a[35]); // Sum(65) res[66] = fma52hi(res[66], a[30], a[35]); // Sum(65) res[66] = fma52lo(res[66], a[31], a[35]); // Sum(66) res[67] = fma52hi(res[67], a[31], a[35]); // Sum(66) res[67] = fma52lo(res[67], a[32], a[35]); // Sum(67) res[68] = fma52hi(res[68], a[32], a[35]); // Sum(67) res[68] = fma52lo(res[68], a[33], a[35]); // Sum(68) res[69] = fma52hi(res[69], a[33], a[35]); // Sum(68) res[69] = fma52lo(res[69], a[34], a[35]); // Sum(69) res[70] = fma52hi(res[70], a[34], a[35]); // Sum(69) res[60] = fma52lo(res[60], a[24], a[36]); // Sum(60) res[61] = fma52hi(res[61], a[24], a[36]); // Sum(60) res[61] = fma52lo(res[61], a[25], a[36]); // Sum(61) res[62] = fma52hi(res[62], a[25], a[36]); // Sum(61) res[62] = fma52lo(res[62], a[26], a[36]); // Sum(62) res[63] = fma52hi(res[63], a[26], a[36]); // Sum(62) res[63] = fma52lo(res[63], a[27], a[36]); // Sum(63) res[64] = fma52hi(res[64], a[27], a[36]); // Sum(63) res[64] = fma52lo(res[64], a[28], a[36]); // Sum(64) res[65] = fma52hi(res[65], a[28], a[36]); // Sum(64) res[65] = fma52lo(res[65], a[29], a[36]); // Sum(65) res[66] = fma52hi(res[66], a[29], a[36]); // Sum(65) res[66] = fma52lo(res[66], a[30], a[36]); // Sum(66) res[67] = fma52hi(res[67], a[30], a[36]); // Sum(66) res[67] = fma52lo(res[67], a[31], a[36]); // Sum(67) res[68] = fma52hi(res[68], a[31], a[36]); // Sum(67) res[68] = fma52lo(res[68], a[32], a[36]); // Sum(68) res[69] = fma52hi(res[69], a[32], a[36]); // Sum(68) res[69] = fma52lo(res[69], a[33], a[36]); // Sum(69) res[70] = fma52hi(res[70], a[33], a[36]); // Sum(69) res[70] = fma52lo(res[70], a[34], a[36]); // Sum(70) res[71] = fma52hi(res[71], a[34], a[36]); // Sum(70) res[71] = fma52lo(res[71], a[35], a[36]); // Sum(71) res[72] = fma52hi(res[72], a[35], a[36]); // Sum(71) res[60] = fma52lo(res[60], a[23], a[37]); // Sum(60) res[61] = fma52hi(res[61], a[23], a[37]); // Sum(60) res[61] = fma52lo(res[61], a[24], a[37]); // Sum(61) res[62] = fma52hi(res[62], a[24], a[37]); // Sum(61) res[62] = fma52lo(res[62], a[25], a[37]); // Sum(62) res[63] = fma52hi(res[63], a[25], a[37]); // Sum(62) res[63] = fma52lo(res[63], a[26], a[37]); // Sum(63) res[64] = fma52hi(res[64], a[26], a[37]); // Sum(63) res[64] = fma52lo(res[64], a[27], a[37]); // Sum(64) res[65] = fma52hi(res[65], a[27], a[37]); // Sum(64) res[65] = fma52lo(res[65], a[28], a[37]); // Sum(65) res[66] = fma52hi(res[66], a[28], a[37]); // Sum(65) res[66] = fma52lo(res[66], a[29], a[37]); // Sum(66) res[67] = fma52hi(res[67], a[29], a[37]); // Sum(66) res[67] = fma52lo(res[67], a[30], a[37]); // Sum(67) res[68] = fma52hi(res[68], a[30], a[37]); // Sum(67) res[68] = fma52lo(res[68], a[31], a[37]); // Sum(68) res[69] = fma52hi(res[69], a[31], a[37]); // Sum(68) res[69] = fma52lo(res[69], a[32], a[37]); // Sum(69) res[70] = fma52hi(res[70], a[32], a[37]); // Sum(69) res[70] = fma52lo(res[70], a[33], a[37]); // Sum(70) res[71] = fma52hi(res[71], a[33], a[37]); // Sum(70) res[71] = fma52lo(res[71], a[34], a[37]); // Sum(71) res[72] = fma52hi(res[72], a[34], a[37]); // Sum(71) res[60] = fma52lo(res[60], a[22], a[38]); // Sum(60) res[61] = fma52hi(res[61], a[22], a[38]); // Sum(60) res[61] = fma52lo(res[61], a[23], a[38]); // Sum(61) res[62] = fma52hi(res[62], a[23], a[38]); // Sum(61) res[62] = fma52lo(res[62], a[24], a[38]); // Sum(62) res[63] = fma52hi(res[63], a[24], a[38]); // Sum(62) res[63] = fma52lo(res[63], a[25], a[38]); // Sum(63) res[64] = fma52hi(res[64], a[25], a[38]); // Sum(63) res[64] = fma52lo(res[64], a[26], a[38]); // Sum(64) res[65] = fma52hi(res[65], a[26], a[38]); // Sum(64) res[65] = fma52lo(res[65], a[27], a[38]); // Sum(65) res[66] = fma52hi(res[66], a[27], a[38]); // Sum(65) res[66] = fma52lo(res[66], a[28], a[38]); // Sum(66) res[67] = fma52hi(res[67], a[28], a[38]); // Sum(66) res[67] = fma52lo(res[67], a[29], a[38]); // Sum(67) res[68] = fma52hi(res[68], a[29], a[38]); // Sum(67) res[68] = fma52lo(res[68], a[30], a[38]); // Sum(68) res[69] = fma52hi(res[69], a[30], a[38]); // Sum(68) res[69] = fma52lo(res[69], a[31], a[38]); // Sum(69) res[70] = fma52hi(res[70], a[31], a[38]); // Sum(69) res[70] = fma52lo(res[70], a[32], a[38]); // Sum(70) res[71] = fma52hi(res[71], a[32], a[38]); // Sum(70) res[71] = fma52lo(res[71], a[33], a[38]); // Sum(71) res[72] = fma52hi(res[72], a[33], a[38]); // Sum(71) res[60] = fma52lo(res[60], a[21], a[39]); // Sum(60) res[61] = fma52hi(res[61], a[21], a[39]); // Sum(60) res[61] = fma52lo(res[61], a[22], a[39]); // Sum(61) res[62] = fma52hi(res[62], a[22], a[39]); // Sum(61) res[62] = fma52lo(res[62], a[23], a[39]); // Sum(62) res[63] = fma52hi(res[63], a[23], a[39]); // Sum(62) res[63] = fma52lo(res[63], a[24], a[39]); // Sum(63) res[64] = fma52hi(res[64], a[24], a[39]); // Sum(63) res[64] = fma52lo(res[64], a[25], a[39]); // Sum(64) res[65] = fma52hi(res[65], a[25], a[39]); // Sum(64) res[65] = fma52lo(res[65], a[26], a[39]); // Sum(65) res[66] = fma52hi(res[66], a[26], a[39]); // Sum(65) res[66] = fma52lo(res[66], a[27], a[39]); // Sum(66) res[67] = fma52hi(res[67], a[27], a[39]); // Sum(66) res[67] = fma52lo(res[67], a[28], a[39]); // Sum(67) res[68] = fma52hi(res[68], a[28], a[39]); // Sum(67) res[68] = fma52lo(res[68], a[29], a[39]); // Sum(68) res[69] = fma52hi(res[69], a[29], a[39]); // Sum(68) res[69] = fma52lo(res[69], a[30], a[39]); // Sum(69) res[70] = fma52hi(res[70], a[30], a[39]); // Sum(69) res[70] = fma52lo(res[70], a[31], a[39]); // Sum(70) res[71] = fma52hi(res[71], a[31], a[39]); // Sum(70) res[71] = fma52lo(res[71], a[32], a[39]); // Sum(71) res[72] = fma52hi(res[72], a[32], a[39]); // Sum(71) res[60] = add64(res[60], res[60]); // Double(60) res[61] = add64(res[61], res[61]); // Double(61) res[62] = add64(res[62], res[62]); // Double(62) res[63] = add64(res[63], res[63]); // Double(63) res[64] = add64(res[64], res[64]); // Double(64) res[65] = add64(res[65], res[65]); // Double(65) res[66] = add64(res[66], res[66]); // Double(66) res[67] = add64(res[67], res[67]); // Double(67) res[68] = add64(res[68], res[68]); // Double(68) res[69] = add64(res[69], res[69]); // Double(69) res[70] = add64(res[70], res[70]); // Double(70) res[71] = add64(res[71], res[71]); // Double(71) res[60] = fma52lo(res[60], a[30], a[30]); // Add sqr(60) res[61] = fma52hi(res[61], a[30], a[30]); // Add sqr(60) res[62] = fma52lo(res[62], a[31], a[31]); // Add sqr(62) res[63] = fma52hi(res[63], a[31], a[31]); // Add sqr(62) res[64] = fma52lo(res[64], a[32], a[32]); // Add sqr(64) res[65] = fma52hi(res[65], a[32], a[32]); // Add sqr(64) res[66] = fma52lo(res[66], a[33], a[33]); // Add sqr(66) res[67] = fma52hi(res[67], a[33], a[33]); // Add sqr(66) res[68] = fma52lo(res[68], a[34], a[34]); // Add sqr(68) res[69] = fma52hi(res[69], a[34], a[34]); // Add sqr(68) res[70] = fma52lo(res[70], a[35], a[35]); // Add sqr(70) res[71] = fma52hi(res[71], a[35], a[35]); // Add sqr(70) res[72] = fma52lo(res[72], a[35], a[37]); // Sum(72) res[73] = fma52hi(res[73], a[35], a[37]); // Sum(72) res[73] = fma52lo(res[73], a[36], a[37]); // Sum(73) res[74] = fma52hi(res[74], a[36], a[37]); // Sum(73) res[72] = fma52lo(res[72], a[34], a[38]); // Sum(72) res[73] = fma52hi(res[73], a[34], a[38]); // Sum(72) res[73] = fma52lo(res[73], a[35], a[38]); // Sum(73) res[74] = fma52hi(res[74], a[35], a[38]); // Sum(73) res[74] = fma52lo(res[74], a[36], a[38]); // Sum(74) res[75] = fma52hi(res[75], a[36], a[38]); // Sum(74) res[75] = fma52lo(res[75], a[37], a[38]); // Sum(75) res[76] = fma52hi(res[76], a[37], a[38]); // Sum(75) res[72] = fma52lo(res[72], a[33], a[39]); // Sum(72) res[73] = fma52hi(res[73], a[33], a[39]); // Sum(72) res[73] = fma52lo(res[73], a[34], a[39]); // Sum(73) res[74] = fma52hi(res[74], a[34], a[39]); // Sum(73) res[74] = fma52lo(res[74], a[35], a[39]); // Sum(74) res[75] = fma52hi(res[75], a[35], a[39]); // Sum(74) res[75] = fma52lo(res[75], a[36], a[39]); // Sum(75) res[76] = fma52hi(res[76], a[36], a[39]); // Sum(75) res[76] = fma52lo(res[76], a[37], a[39]); // Sum(76) res[77] = fma52hi(res[77], a[37], a[39]); // Sum(76) res[77] = fma52lo(res[77], a[38], a[39]); // Sum(77) res[78] = fma52hi(res[78], a[38], a[39]); // Sum(77) res[72] = add64(res[72], res[72]); // Double(72) res[73] = add64(res[73], res[73]); // Double(73) res[74] = add64(res[74], res[74]); // Double(74) res[75] = add64(res[75], res[75]); // Double(75) res[76] = add64(res[76], res[76]); // Double(76) res[77] = add64(res[77], res[77]); // Double(77) res[78] = add64(res[78], res[78]); // Double(78) res[72] = fma52lo(res[72], a[36], a[36]); // Add sqr(72) res[73] = fma52hi(res[73], a[36], a[36]); // Add sqr(72) res[74] = fma52lo(res[74], a[37], a[37]); // Add sqr(74) res[75] = fma52hi(res[75], a[37], a[37]); // Add sqr(74) res[76] = fma52lo(res[76], a[38], a[38]); // Add sqr(76) res[77] = fma52hi(res[77], a[38], a[38]); // Add sqr(76) res[78] = fma52lo(res[78], a[39], a[39]); // Add sqr(78) res[79] = fma52hi(res[79], a[39], a[39]); // Add sqr(78) // Montgomery Reduction int it; for (it = 0; it < 40; it += 10) { // Reduction step int jt = 0; if ((it + 0) > 0) res[it + 0] = add64(res[it + 0], srli64(res[it + -1], DIGIT_SIZE)); u[it + 0] = mul52lo(res[it + 0], k); res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + 1] = add64(res[it + 1], srli64(res[it + 0], DIGIT_SIZE)); u[it + 1] = mul52lo(res[it + 1], k); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + 2] = add64(res[it + 2], srli64(res[it + 1], DIGIT_SIZE)); u[it + 2] = mul52lo(res[it + 2], k); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + 3] = add64(res[it + 3], srli64(res[it + 2], DIGIT_SIZE)); u[it + 3] = mul52lo(res[it + 3], k); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + 4] = add64(res[it + 4], srli64(res[it + 3], DIGIT_SIZE)); u[it + 4] = mul52lo(res[it + 4], k); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + 5] = add64(res[it + 5], srli64(res[it + 4], DIGIT_SIZE)); u[it + 5] = mul52lo(res[it + 5], k); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + 6] = add64(res[it + 6], srli64(res[it + 5], DIGIT_SIZE)); u[it + 6] = mul52lo(res[it + 6], k); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + 7] = add64(res[it + 7], srli64(res[it + 6], DIGIT_SIZE)); u[it + 7] = mul52lo(res[it + 7], k); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + 8] = add64(res[it + 8], srli64(res[it + 7], DIGIT_SIZE)); u[it + 8] = mul52lo(res[it + 8], k); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + 9] = add64(res[it + 9], srli64(res[it + 8], DIGIT_SIZE)); u[it + 9] = mul52lo(res[it + 9], k); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); for (jt = 10; jt < 40; jt += 10) { // Poly tile res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); } } // Normalization res[40] = add64(res[40], srli64(res[39], DIGIT_SIZE)); r[0] = and64_const(res[40], DIGIT_MASK); res[41] = add64(res[41], srli64(res[40], DIGIT_SIZE)); r[1] = and64_const(res[41], DIGIT_MASK); res[42] = add64(res[42], srli64(res[41], DIGIT_SIZE)); r[2] = and64_const(res[42], DIGIT_MASK); res[43] = add64(res[43], srli64(res[42], DIGIT_SIZE)); r[3] = and64_const(res[43], DIGIT_MASK); res[44] = add64(res[44], srli64(res[43], DIGIT_SIZE)); r[4] = and64_const(res[44], DIGIT_MASK); res[45] = add64(res[45], srli64(res[44], DIGIT_SIZE)); r[5] = and64_const(res[45], DIGIT_MASK); res[46] = add64(res[46], srli64(res[45], DIGIT_SIZE)); r[6] = and64_const(res[46], DIGIT_MASK); res[47] = add64(res[47], srli64(res[46], DIGIT_SIZE)); r[7] = and64_const(res[47], DIGIT_MASK); res[48] = add64(res[48], srli64(res[47], DIGIT_SIZE)); r[8] = and64_const(res[48], DIGIT_MASK); res[49] = add64(res[49], srli64(res[48], DIGIT_SIZE)); r[9] = and64_const(res[49], DIGIT_MASK); res[50] = add64(res[50], srli64(res[49], DIGIT_SIZE)); r[10] = and64_const(res[50], DIGIT_MASK); res[51] = add64(res[51], srli64(res[50], DIGIT_SIZE)); r[11] = and64_const(res[51], DIGIT_MASK); res[52] = add64(res[52], srli64(res[51], DIGIT_SIZE)); r[12] = and64_const(res[52], DIGIT_MASK); res[53] = add64(res[53], srli64(res[52], DIGIT_SIZE)); r[13] = and64_const(res[53], DIGIT_MASK); res[54] = add64(res[54], srli64(res[53], DIGIT_SIZE)); r[14] = and64_const(res[54], DIGIT_MASK); res[55] = add64(res[55], srli64(res[54], DIGIT_SIZE)); r[15] = and64_const(res[55], DIGIT_MASK); res[56] = add64(res[56], srli64(res[55], DIGIT_SIZE)); r[16] = and64_const(res[56], DIGIT_MASK); res[57] = add64(res[57], srli64(res[56], DIGIT_SIZE)); r[17] = and64_const(res[57], DIGIT_MASK); res[58] = add64(res[58], srli64(res[57], DIGIT_SIZE)); r[18] = and64_const(res[58], DIGIT_MASK); res[59] = add64(res[59], srli64(res[58], DIGIT_SIZE)); r[19] = and64_const(res[59], DIGIT_MASK); res[60] = add64(res[60], srli64(res[59], DIGIT_SIZE)); r[20] = and64_const(res[60], DIGIT_MASK); res[61] = add64(res[61], srli64(res[60], DIGIT_SIZE)); r[21] = and64_const(res[61], DIGIT_MASK); res[62] = add64(res[62], srli64(res[61], DIGIT_SIZE)); r[22] = and64_const(res[62], DIGIT_MASK); res[63] = add64(res[63], srli64(res[62], DIGIT_SIZE)); r[23] = and64_const(res[63], DIGIT_MASK); res[64] = add64(res[64], srli64(res[63], DIGIT_SIZE)); r[24] = and64_const(res[64], DIGIT_MASK); res[65] = add64(res[65], srli64(res[64], DIGIT_SIZE)); r[25] = and64_const(res[65], DIGIT_MASK); res[66] = add64(res[66], srli64(res[65], DIGIT_SIZE)); r[26] = and64_const(res[66], DIGIT_MASK); res[67] = add64(res[67], srli64(res[66], DIGIT_SIZE)); r[27] = and64_const(res[67], DIGIT_MASK); res[68] = add64(res[68], srli64(res[67], DIGIT_SIZE)); r[28] = and64_const(res[68], DIGIT_MASK); res[69] = add64(res[69], srli64(res[68], DIGIT_SIZE)); r[29] = and64_const(res[69], DIGIT_MASK); res[70] = add64(res[70], srli64(res[69], DIGIT_SIZE)); r[30] = and64_const(res[70], DIGIT_MASK); res[71] = add64(res[71], srli64(res[70], DIGIT_SIZE)); r[31] = and64_const(res[71], DIGIT_MASK); res[72] = add64(res[72], srli64(res[71], DIGIT_SIZE)); r[32] = and64_const(res[72], DIGIT_MASK); res[73] = add64(res[73], srli64(res[72], DIGIT_SIZE)); r[33] = and64_const(res[73], DIGIT_MASK); res[74] = add64(res[74], srli64(res[73], DIGIT_SIZE)); r[34] = and64_const(res[74], DIGIT_MASK); res[75] = add64(res[75], srli64(res[74], DIGIT_SIZE)); r[35] = and64_const(res[75], DIGIT_MASK); res[76] = add64(res[76], srli64(res[75], DIGIT_SIZE)); r[36] = and64_const(res[76], DIGIT_MASK); res[77] = add64(res[77], srli64(res[76], DIGIT_SIZE)); r[37] = and64_const(res[77], DIGIT_MASK); res[78] = add64(res[78], srli64(res[77], DIGIT_SIZE)); r[38] = and64_const(res[78], DIGIT_MASK); res[79] = add64(res[79], srli64(res[78], DIGIT_SIZE)); r[39] = and64_const(res[79], DIGIT_MASK); } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams52x60_diagonal_mb8.c000066400000000000000000007742131470420105600345150ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void AMS52x60_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { __ALIGN64 U64 res[120]; __ALIGN64 U64 u[60]; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; k = loadu64((U64 *)k0_mb); int i; for (i = 0; i < 120; ++i) res[i] = get_zero64(); res[1] = fma52lo(res[1], a[0], a[1]); // Sum(1) res[2] = fma52hi(res[2], a[0], a[1]); // Sum(1) res[2] = fma52lo(res[2], a[0], a[2]); // Sum(2) res[3] = fma52hi(res[3], a[0], a[2]); // Sum(2) res[3] = fma52lo(res[3], a[1], a[2]); // Sum(3) res[4] = fma52hi(res[4], a[1], a[2]); // Sum(3) res[3] = fma52lo(res[3], a[0], a[3]); // Sum(3) res[4] = fma52hi(res[4], a[0], a[3]); // Sum(3) res[4] = fma52lo(res[4], a[1], a[3]); // Sum(4) res[5] = fma52hi(res[5], a[1], a[3]); // Sum(4) res[5] = fma52lo(res[5], a[2], a[3]); // Sum(5) res[6] = fma52hi(res[6], a[2], a[3]); // Sum(5) res[4] = fma52lo(res[4], a[0], a[4]); // Sum(4) res[5] = fma52hi(res[5], a[0], a[4]); // Sum(4) res[5] = fma52lo(res[5], a[1], a[4]); // Sum(5) res[6] = fma52hi(res[6], a[1], a[4]); // Sum(5) res[6] = fma52lo(res[6], a[2], a[4]); // Sum(6) res[7] = fma52hi(res[7], a[2], a[4]); // Sum(6) res[7] = fma52lo(res[7], a[3], a[4]); // Sum(7) res[8] = fma52hi(res[8], a[3], a[4]); // Sum(7) res[5] = fma52lo(res[5], a[0], a[5]); // Sum(5) res[6] = fma52hi(res[6], a[0], a[5]); // Sum(5) res[6] = fma52lo(res[6], a[1], a[5]); // Sum(6) res[7] = fma52hi(res[7], a[1], a[5]); // Sum(6) res[7] = fma52lo(res[7], a[2], a[5]); // Sum(7) res[8] = fma52hi(res[8], a[2], a[5]); // Sum(7) res[8] = fma52lo(res[8], a[3], a[5]); // Sum(8) res[9] = fma52hi(res[9], a[3], a[5]); // Sum(8) res[9] = fma52lo(res[9], a[4], a[5]); // Sum(9) res[10] = fma52hi(res[10], a[4], a[5]); // Sum(9) res[6] = fma52lo(res[6], a[0], a[6]); // Sum(6) res[7] = fma52hi(res[7], a[0], a[6]); // Sum(6) res[7] = fma52lo(res[7], a[1], a[6]); // Sum(7) res[8] = fma52hi(res[8], a[1], a[6]); // Sum(7) res[8] = fma52lo(res[8], a[2], a[6]); // Sum(8) res[9] = fma52hi(res[9], a[2], a[6]); // Sum(8) res[9] = fma52lo(res[9], a[3], a[6]); // Sum(9) res[10] = fma52hi(res[10], a[3], a[6]); // Sum(9) res[10] = fma52lo(res[10], a[4], a[6]); // Sum(10) res[11] = fma52hi(res[11], a[4], a[6]); // Sum(10) res[11] = fma52lo(res[11], a[5], a[6]); // Sum(11) res[12] = fma52hi(res[12], a[5], a[6]); // Sum(11) res[7] = fma52lo(res[7], a[0], a[7]); // Sum(7) res[8] = fma52hi(res[8], a[0], a[7]); // Sum(7) res[8] = fma52lo(res[8], a[1], a[7]); // Sum(8) res[9] = fma52hi(res[9], a[1], a[7]); // Sum(8) res[9] = fma52lo(res[9], a[2], a[7]); // Sum(9) res[10] = fma52hi(res[10], a[2], a[7]); // Sum(9) res[10] = fma52lo(res[10], a[3], a[7]); // Sum(10) res[11] = fma52hi(res[11], a[3], a[7]); // Sum(10) res[11] = fma52lo(res[11], a[4], a[7]); // Sum(11) res[12] = fma52hi(res[12], a[4], a[7]); // Sum(11) res[8] = fma52lo(res[8], a[0], a[8]); // Sum(8) res[9] = fma52hi(res[9], a[0], a[8]); // Sum(8) res[9] = fma52lo(res[9], a[1], a[8]); // Sum(9) res[10] = fma52hi(res[10], a[1], a[8]); // Sum(9) res[10] = fma52lo(res[10], a[2], a[8]); // Sum(10) res[11] = fma52hi(res[11], a[2], a[8]); // Sum(10) res[11] = fma52lo(res[11], a[3], a[8]); // Sum(11) res[12] = fma52hi(res[12], a[3], a[8]); // Sum(11) res[9] = fma52lo(res[9], a[0], a[9]); // Sum(9) res[10] = fma52hi(res[10], a[0], a[9]); // Sum(9) res[10] = fma52lo(res[10], a[1], a[9]); // Sum(10) res[11] = fma52hi(res[11], a[1], a[9]); // Sum(10) res[11] = fma52lo(res[11], a[2], a[9]); // Sum(11) res[12] = fma52hi(res[12], a[2], a[9]); // Sum(11) res[10] = fma52lo(res[10], a[0], a[10]); // Sum(10) res[11] = fma52hi(res[11], a[0], a[10]); // Sum(10) res[11] = fma52lo(res[11], a[1], a[10]); // Sum(11) res[12] = fma52hi(res[12], a[1], a[10]); // Sum(11) res[11] = fma52lo(res[11], a[0], a[11]); // Sum(11) res[12] = fma52hi(res[12], a[0], a[11]); // Sum(11) res[0] = add64(res[0], res[0]); // Double(0) res[1] = add64(res[1], res[1]); // Double(1) res[2] = add64(res[2], res[2]); // Double(2) res[3] = add64(res[3], res[3]); // Double(3) res[4] = add64(res[4], res[4]); // Double(4) res[5] = add64(res[5], res[5]); // Double(5) res[6] = add64(res[6], res[6]); // Double(6) res[7] = add64(res[7], res[7]); // Double(7) res[8] = add64(res[8], res[8]); // Double(8) res[9] = add64(res[9], res[9]); // Double(9) res[10] = add64(res[10], res[10]); // Double(10) res[11] = add64(res[11], res[11]); // Double(11) res[0] = fma52lo(res[0], a[0], a[0]); // Add sqr(0) res[1] = fma52hi(res[1], a[0], a[0]); // Add sqr(0) res[2] = fma52lo(res[2], a[1], a[1]); // Add sqr(2) res[3] = fma52hi(res[3], a[1], a[1]); // Add sqr(2) res[4] = fma52lo(res[4], a[2], a[2]); // Add sqr(4) res[5] = fma52hi(res[5], a[2], a[2]); // Add sqr(4) res[6] = fma52lo(res[6], a[3], a[3]); // Add sqr(6) res[7] = fma52hi(res[7], a[3], a[3]); // Add sqr(6) res[8] = fma52lo(res[8], a[4], a[4]); // Add sqr(8) res[9] = fma52hi(res[9], a[4], a[4]); // Add sqr(8) res[10] = fma52lo(res[10], a[5], a[5]); // Add sqr(10) res[11] = fma52hi(res[11], a[5], a[5]); // Add sqr(10) res[12] = fma52lo(res[12], a[5], a[7]); // Sum(12) res[13] = fma52hi(res[13], a[5], a[7]); // Sum(12) res[13] = fma52lo(res[13], a[6], a[7]); // Sum(13) res[14] = fma52hi(res[14], a[6], a[7]); // Sum(13) res[12] = fma52lo(res[12], a[4], a[8]); // Sum(12) res[13] = fma52hi(res[13], a[4], a[8]); // Sum(12) res[13] = fma52lo(res[13], a[5], a[8]); // Sum(13) res[14] = fma52hi(res[14], a[5], a[8]); // Sum(13) res[14] = fma52lo(res[14], a[6], a[8]); // Sum(14) res[15] = fma52hi(res[15], a[6], a[8]); // Sum(14) res[15] = fma52lo(res[15], a[7], a[8]); // Sum(15) res[16] = fma52hi(res[16], a[7], a[8]); // Sum(15) res[12] = fma52lo(res[12], a[3], a[9]); // Sum(12) res[13] = fma52hi(res[13], a[3], a[9]); // Sum(12) res[13] = fma52lo(res[13], a[4], a[9]); // Sum(13) res[14] = fma52hi(res[14], a[4], a[9]); // Sum(13) res[14] = fma52lo(res[14], a[5], a[9]); // Sum(14) res[15] = fma52hi(res[15], a[5], a[9]); // Sum(14) res[15] = fma52lo(res[15], a[6], a[9]); // Sum(15) res[16] = fma52hi(res[16], a[6], a[9]); // Sum(15) res[16] = fma52lo(res[16], a[7], a[9]); // Sum(16) res[17] = fma52hi(res[17], a[7], a[9]); // Sum(16) res[17] = fma52lo(res[17], a[8], a[9]); // Sum(17) res[18] = fma52hi(res[18], a[8], a[9]); // Sum(17) res[12] = fma52lo(res[12], a[2], a[10]); // Sum(12) res[13] = fma52hi(res[13], a[2], a[10]); // Sum(12) res[13] = fma52lo(res[13], a[3], a[10]); // Sum(13) res[14] = fma52hi(res[14], a[3], a[10]); // Sum(13) res[14] = fma52lo(res[14], a[4], a[10]); // Sum(14) res[15] = fma52hi(res[15], a[4], a[10]); // Sum(14) res[15] = fma52lo(res[15], a[5], a[10]); // Sum(15) res[16] = fma52hi(res[16], a[5], a[10]); // Sum(15) res[16] = fma52lo(res[16], a[6], a[10]); // Sum(16) res[17] = fma52hi(res[17], a[6], a[10]); // Sum(16) res[17] = fma52lo(res[17], a[7], a[10]); // Sum(17) res[18] = fma52hi(res[18], a[7], a[10]); // Sum(17) res[18] = fma52lo(res[18], a[8], a[10]); // Sum(18) res[19] = fma52hi(res[19], a[8], a[10]); // Sum(18) res[19] = fma52lo(res[19], a[9], a[10]); // Sum(19) res[20] = fma52hi(res[20], a[9], a[10]); // Sum(19) res[12] = fma52lo(res[12], a[1], a[11]); // Sum(12) res[13] = fma52hi(res[13], a[1], a[11]); // Sum(12) res[13] = fma52lo(res[13], a[2], a[11]); // Sum(13) res[14] = fma52hi(res[14], a[2], a[11]); // Sum(13) res[14] = fma52lo(res[14], a[3], a[11]); // Sum(14) res[15] = fma52hi(res[15], a[3], a[11]); // Sum(14) res[15] = fma52lo(res[15], a[4], a[11]); // Sum(15) res[16] = fma52hi(res[16], a[4], a[11]); // Sum(15) res[16] = fma52lo(res[16], a[5], a[11]); // Sum(16) res[17] = fma52hi(res[17], a[5], a[11]); // Sum(16) res[17] = fma52lo(res[17], a[6], a[11]); // Sum(17) res[18] = fma52hi(res[18], a[6], a[11]); // Sum(17) res[18] = fma52lo(res[18], a[7], a[11]); // Sum(18) res[19] = fma52hi(res[19], a[7], a[11]); // Sum(18) res[19] = fma52lo(res[19], a[8], a[11]); // Sum(19) res[20] = fma52hi(res[20], a[8], a[11]); // Sum(19) res[20] = fma52lo(res[20], a[9], a[11]); // Sum(20) res[21] = fma52hi(res[21], a[9], a[11]); // Sum(20) res[21] = fma52lo(res[21], a[10], a[11]); // Sum(21) res[22] = fma52hi(res[22], a[10], a[11]); // Sum(21) res[12] = fma52lo(res[12], a[0], a[12]); // Sum(12) res[13] = fma52hi(res[13], a[0], a[12]); // Sum(12) res[13] = fma52lo(res[13], a[1], a[12]); // Sum(13) res[14] = fma52hi(res[14], a[1], a[12]); // Sum(13) res[14] = fma52lo(res[14], a[2], a[12]); // Sum(14) res[15] = fma52hi(res[15], a[2], a[12]); // Sum(14) res[15] = fma52lo(res[15], a[3], a[12]); // Sum(15) res[16] = fma52hi(res[16], a[3], a[12]); // Sum(15) res[16] = fma52lo(res[16], a[4], a[12]); // Sum(16) res[17] = fma52hi(res[17], a[4], a[12]); // Sum(16) res[17] = fma52lo(res[17], a[5], a[12]); // Sum(17) res[18] = fma52hi(res[18], a[5], a[12]); // Sum(17) res[18] = fma52lo(res[18], a[6], a[12]); // Sum(18) res[19] = fma52hi(res[19], a[6], a[12]); // Sum(18) res[19] = fma52lo(res[19], a[7], a[12]); // Sum(19) res[20] = fma52hi(res[20], a[7], a[12]); // Sum(19) res[20] = fma52lo(res[20], a[8], a[12]); // Sum(20) res[21] = fma52hi(res[21], a[8], a[12]); // Sum(20) res[21] = fma52lo(res[21], a[9], a[12]); // Sum(21) res[22] = fma52hi(res[22], a[9], a[12]); // Sum(21) res[22] = fma52lo(res[22], a[10], a[12]); // Sum(22) res[23] = fma52hi(res[23], a[10], a[12]); // Sum(22) res[23] = fma52lo(res[23], a[11], a[12]); // Sum(23) res[24] = fma52hi(res[24], a[11], a[12]); // Sum(23) res[13] = fma52lo(res[13], a[0], a[13]); // Sum(13) res[14] = fma52hi(res[14], a[0], a[13]); // Sum(13) res[14] = fma52lo(res[14], a[1], a[13]); // Sum(14) res[15] = fma52hi(res[15], a[1], a[13]); // Sum(14) res[15] = fma52lo(res[15], a[2], a[13]); // Sum(15) res[16] = fma52hi(res[16], a[2], a[13]); // Sum(15) res[16] = fma52lo(res[16], a[3], a[13]); // Sum(16) res[17] = fma52hi(res[17], a[3], a[13]); // Sum(16) res[17] = fma52lo(res[17], a[4], a[13]); // Sum(17) res[18] = fma52hi(res[18], a[4], a[13]); // Sum(17) res[18] = fma52lo(res[18], a[5], a[13]); // Sum(18) res[19] = fma52hi(res[19], a[5], a[13]); // Sum(18) res[19] = fma52lo(res[19], a[6], a[13]); // Sum(19) res[20] = fma52hi(res[20], a[6], a[13]); // Sum(19) res[20] = fma52lo(res[20], a[7], a[13]); // Sum(20) res[21] = fma52hi(res[21], a[7], a[13]); // Sum(20) res[21] = fma52lo(res[21], a[8], a[13]); // Sum(21) res[22] = fma52hi(res[22], a[8], a[13]); // Sum(21) res[22] = fma52lo(res[22], a[9], a[13]); // Sum(22) res[23] = fma52hi(res[23], a[9], a[13]); // Sum(22) res[23] = fma52lo(res[23], a[10], a[13]); // Sum(23) res[24] = fma52hi(res[24], a[10], a[13]); // Sum(23) res[14] = fma52lo(res[14], a[0], a[14]); // Sum(14) res[15] = fma52hi(res[15], a[0], a[14]); // Sum(14) res[15] = fma52lo(res[15], a[1], a[14]); // Sum(15) res[16] = fma52hi(res[16], a[1], a[14]); // Sum(15) res[16] = fma52lo(res[16], a[2], a[14]); // Sum(16) res[17] = fma52hi(res[17], a[2], a[14]); // Sum(16) res[17] = fma52lo(res[17], a[3], a[14]); // Sum(17) res[18] = fma52hi(res[18], a[3], a[14]); // Sum(17) res[18] = fma52lo(res[18], a[4], a[14]); // Sum(18) res[19] = fma52hi(res[19], a[4], a[14]); // Sum(18) res[19] = fma52lo(res[19], a[5], a[14]); // Sum(19) res[20] = fma52hi(res[20], a[5], a[14]); // Sum(19) res[20] = fma52lo(res[20], a[6], a[14]); // Sum(20) res[21] = fma52hi(res[21], a[6], a[14]); // Sum(20) res[21] = fma52lo(res[21], a[7], a[14]); // Sum(21) res[22] = fma52hi(res[22], a[7], a[14]); // Sum(21) res[22] = fma52lo(res[22], a[8], a[14]); // Sum(22) res[23] = fma52hi(res[23], a[8], a[14]); // Sum(22) res[23] = fma52lo(res[23], a[9], a[14]); // Sum(23) res[24] = fma52hi(res[24], a[9], a[14]); // Sum(23) res[15] = fma52lo(res[15], a[0], a[15]); // Sum(15) res[16] = fma52hi(res[16], a[0], a[15]); // Sum(15) res[16] = fma52lo(res[16], a[1], a[15]); // Sum(16) res[17] = fma52hi(res[17], a[1], a[15]); // Sum(16) res[17] = fma52lo(res[17], a[2], a[15]); // Sum(17) res[18] = fma52hi(res[18], a[2], a[15]); // Sum(17) res[18] = fma52lo(res[18], a[3], a[15]); // Sum(18) res[19] = fma52hi(res[19], a[3], a[15]); // Sum(18) res[19] = fma52lo(res[19], a[4], a[15]); // Sum(19) res[20] = fma52hi(res[20], a[4], a[15]); // Sum(19) res[20] = fma52lo(res[20], a[5], a[15]); // Sum(20) res[21] = fma52hi(res[21], a[5], a[15]); // Sum(20) res[21] = fma52lo(res[21], a[6], a[15]); // Sum(21) res[22] = fma52hi(res[22], a[6], a[15]); // Sum(21) res[22] = fma52lo(res[22], a[7], a[15]); // Sum(22) res[23] = fma52hi(res[23], a[7], a[15]); // Sum(22) res[23] = fma52lo(res[23], a[8], a[15]); // Sum(23) res[24] = fma52hi(res[24], a[8], a[15]); // Sum(23) res[16] = fma52lo(res[16], a[0], a[16]); // Sum(16) res[17] = fma52hi(res[17], a[0], a[16]); // Sum(16) res[17] = fma52lo(res[17], a[1], a[16]); // Sum(17) res[18] = fma52hi(res[18], a[1], a[16]); // Sum(17) res[18] = fma52lo(res[18], a[2], a[16]); // Sum(18) res[19] = fma52hi(res[19], a[2], a[16]); // Sum(18) res[19] = fma52lo(res[19], a[3], a[16]); // Sum(19) res[20] = fma52hi(res[20], a[3], a[16]); // Sum(19) res[20] = fma52lo(res[20], a[4], a[16]); // Sum(20) res[21] = fma52hi(res[21], a[4], a[16]); // Sum(20) res[21] = fma52lo(res[21], a[5], a[16]); // Sum(21) res[22] = fma52hi(res[22], a[5], a[16]); // Sum(21) res[22] = fma52lo(res[22], a[6], a[16]); // Sum(22) res[23] = fma52hi(res[23], a[6], a[16]); // Sum(22) res[23] = fma52lo(res[23], a[7], a[16]); // Sum(23) res[24] = fma52hi(res[24], a[7], a[16]); // Sum(23) res[17] = fma52lo(res[17], a[0], a[17]); // Sum(17) res[18] = fma52hi(res[18], a[0], a[17]); // Sum(17) res[18] = fma52lo(res[18], a[1], a[17]); // Sum(18) res[19] = fma52hi(res[19], a[1], a[17]); // Sum(18) res[19] = fma52lo(res[19], a[2], a[17]); // Sum(19) res[20] = fma52hi(res[20], a[2], a[17]); // Sum(19) res[20] = fma52lo(res[20], a[3], a[17]); // Sum(20) res[21] = fma52hi(res[21], a[3], a[17]); // Sum(20) res[21] = fma52lo(res[21], a[4], a[17]); // Sum(21) res[22] = fma52hi(res[22], a[4], a[17]); // Sum(21) res[22] = fma52lo(res[22], a[5], a[17]); // Sum(22) res[23] = fma52hi(res[23], a[5], a[17]); // Sum(22) res[23] = fma52lo(res[23], a[6], a[17]); // Sum(23) res[24] = fma52hi(res[24], a[6], a[17]); // Sum(23) res[18] = fma52lo(res[18], a[0], a[18]); // Sum(18) res[19] = fma52hi(res[19], a[0], a[18]); // Sum(18) res[19] = fma52lo(res[19], a[1], a[18]); // Sum(19) res[20] = fma52hi(res[20], a[1], a[18]); // Sum(19) res[20] = fma52lo(res[20], a[2], a[18]); // Sum(20) res[21] = fma52hi(res[21], a[2], a[18]); // Sum(20) res[21] = fma52lo(res[21], a[3], a[18]); // Sum(21) res[22] = fma52hi(res[22], a[3], a[18]); // Sum(21) res[22] = fma52lo(res[22], a[4], a[18]); // Sum(22) res[23] = fma52hi(res[23], a[4], a[18]); // Sum(22) res[23] = fma52lo(res[23], a[5], a[18]); // Sum(23) res[24] = fma52hi(res[24], a[5], a[18]); // Sum(23) res[19] = fma52lo(res[19], a[0], a[19]); // Sum(19) res[20] = fma52hi(res[20], a[0], a[19]); // Sum(19) res[20] = fma52lo(res[20], a[1], a[19]); // Sum(20) res[21] = fma52hi(res[21], a[1], a[19]); // Sum(20) res[21] = fma52lo(res[21], a[2], a[19]); // Sum(21) res[22] = fma52hi(res[22], a[2], a[19]); // Sum(21) res[22] = fma52lo(res[22], a[3], a[19]); // Sum(22) res[23] = fma52hi(res[23], a[3], a[19]); // Sum(22) res[23] = fma52lo(res[23], a[4], a[19]); // Sum(23) res[24] = fma52hi(res[24], a[4], a[19]); // Sum(23) res[20] = fma52lo(res[20], a[0], a[20]); // Sum(20) res[21] = fma52hi(res[21], a[0], a[20]); // Sum(20) res[21] = fma52lo(res[21], a[1], a[20]); // Sum(21) res[22] = fma52hi(res[22], a[1], a[20]); // Sum(21) res[22] = fma52lo(res[22], a[2], a[20]); // Sum(22) res[23] = fma52hi(res[23], a[2], a[20]); // Sum(22) res[23] = fma52lo(res[23], a[3], a[20]); // Sum(23) res[24] = fma52hi(res[24], a[3], a[20]); // Sum(23) res[21] = fma52lo(res[21], a[0], a[21]); // Sum(21) res[22] = fma52hi(res[22], a[0], a[21]); // Sum(21) res[22] = fma52lo(res[22], a[1], a[21]); // Sum(22) res[23] = fma52hi(res[23], a[1], a[21]); // Sum(22) res[23] = fma52lo(res[23], a[2], a[21]); // Sum(23) res[24] = fma52hi(res[24], a[2], a[21]); // Sum(23) res[22] = fma52lo(res[22], a[0], a[22]); // Sum(22) res[23] = fma52hi(res[23], a[0], a[22]); // Sum(22) res[23] = fma52lo(res[23], a[1], a[22]); // Sum(23) res[24] = fma52hi(res[24], a[1], a[22]); // Sum(23) res[23] = fma52lo(res[23], a[0], a[23]); // Sum(23) res[24] = fma52hi(res[24], a[0], a[23]); // Sum(23) res[12] = add64(res[12], res[12]); // Double(12) res[13] = add64(res[13], res[13]); // Double(13) res[14] = add64(res[14], res[14]); // Double(14) res[15] = add64(res[15], res[15]); // Double(15) res[16] = add64(res[16], res[16]); // Double(16) res[17] = add64(res[17], res[17]); // Double(17) res[18] = add64(res[18], res[18]); // Double(18) res[19] = add64(res[19], res[19]); // Double(19) res[20] = add64(res[20], res[20]); // Double(20) res[21] = add64(res[21], res[21]); // Double(21) res[22] = add64(res[22], res[22]); // Double(22) res[23] = add64(res[23], res[23]); // Double(23) res[12] = fma52lo(res[12], a[6], a[6]); // Add sqr(12) res[13] = fma52hi(res[13], a[6], a[6]); // Add sqr(12) res[14] = fma52lo(res[14], a[7], a[7]); // Add sqr(14) res[15] = fma52hi(res[15], a[7], a[7]); // Add sqr(14) res[16] = fma52lo(res[16], a[8], a[8]); // Add sqr(16) res[17] = fma52hi(res[17], a[8], a[8]); // Add sqr(16) res[18] = fma52lo(res[18], a[9], a[9]); // Add sqr(18) res[19] = fma52hi(res[19], a[9], a[9]); // Add sqr(18) res[20] = fma52lo(res[20], a[10], a[10]); // Add sqr(20) res[21] = fma52hi(res[21], a[10], a[10]); // Add sqr(20) res[22] = fma52lo(res[22], a[11], a[11]); // Add sqr(22) res[23] = fma52hi(res[23], a[11], a[11]); // Add sqr(22) res[24] = fma52lo(res[24], a[11], a[13]); // Sum(24) res[25] = fma52hi(res[25], a[11], a[13]); // Sum(24) res[25] = fma52lo(res[25], a[12], a[13]); // Sum(25) res[26] = fma52hi(res[26], a[12], a[13]); // Sum(25) res[24] = fma52lo(res[24], a[10], a[14]); // Sum(24) res[25] = fma52hi(res[25], a[10], a[14]); // Sum(24) res[25] = fma52lo(res[25], a[11], a[14]); // Sum(25) res[26] = fma52hi(res[26], a[11], a[14]); // Sum(25) res[26] = fma52lo(res[26], a[12], a[14]); // Sum(26) res[27] = fma52hi(res[27], a[12], a[14]); // Sum(26) res[27] = fma52lo(res[27], a[13], a[14]); // Sum(27) res[28] = fma52hi(res[28], a[13], a[14]); // Sum(27) res[24] = fma52lo(res[24], a[9], a[15]); // Sum(24) res[25] = fma52hi(res[25], a[9], a[15]); // Sum(24) res[25] = fma52lo(res[25], a[10], a[15]); // Sum(25) res[26] = fma52hi(res[26], a[10], a[15]); // Sum(25) res[26] = fma52lo(res[26], a[11], a[15]); // Sum(26) res[27] = fma52hi(res[27], a[11], a[15]); // Sum(26) res[27] = fma52lo(res[27], a[12], a[15]); // Sum(27) res[28] = fma52hi(res[28], a[12], a[15]); // Sum(27) res[28] = fma52lo(res[28], a[13], a[15]); // Sum(28) res[29] = fma52hi(res[29], a[13], a[15]); // Sum(28) res[29] = fma52lo(res[29], a[14], a[15]); // Sum(29) res[30] = fma52hi(res[30], a[14], a[15]); // Sum(29) res[24] = fma52lo(res[24], a[8], a[16]); // Sum(24) res[25] = fma52hi(res[25], a[8], a[16]); // Sum(24) res[25] = fma52lo(res[25], a[9], a[16]); // Sum(25) res[26] = fma52hi(res[26], a[9], a[16]); // Sum(25) res[26] = fma52lo(res[26], a[10], a[16]); // Sum(26) res[27] = fma52hi(res[27], a[10], a[16]); // Sum(26) res[27] = fma52lo(res[27], a[11], a[16]); // Sum(27) res[28] = fma52hi(res[28], a[11], a[16]); // Sum(27) res[28] = fma52lo(res[28], a[12], a[16]); // Sum(28) res[29] = fma52hi(res[29], a[12], a[16]); // Sum(28) res[29] = fma52lo(res[29], a[13], a[16]); // Sum(29) res[30] = fma52hi(res[30], a[13], a[16]); // Sum(29) res[30] = fma52lo(res[30], a[14], a[16]); // Sum(30) res[31] = fma52hi(res[31], a[14], a[16]); // Sum(30) res[31] = fma52lo(res[31], a[15], a[16]); // Sum(31) res[32] = fma52hi(res[32], a[15], a[16]); // Sum(31) res[24] = fma52lo(res[24], a[7], a[17]); // Sum(24) res[25] = fma52hi(res[25], a[7], a[17]); // Sum(24) res[25] = fma52lo(res[25], a[8], a[17]); // Sum(25) res[26] = fma52hi(res[26], a[8], a[17]); // Sum(25) res[26] = fma52lo(res[26], a[9], a[17]); // Sum(26) res[27] = fma52hi(res[27], a[9], a[17]); // Sum(26) res[27] = fma52lo(res[27], a[10], a[17]); // Sum(27) res[28] = fma52hi(res[28], a[10], a[17]); // Sum(27) res[28] = fma52lo(res[28], a[11], a[17]); // Sum(28) res[29] = fma52hi(res[29], a[11], a[17]); // Sum(28) res[29] = fma52lo(res[29], a[12], a[17]); // Sum(29) res[30] = fma52hi(res[30], a[12], a[17]); // Sum(29) res[30] = fma52lo(res[30], a[13], a[17]); // Sum(30) res[31] = fma52hi(res[31], a[13], a[17]); // Sum(30) res[31] = fma52lo(res[31], a[14], a[17]); // Sum(31) res[32] = fma52hi(res[32], a[14], a[17]); // Sum(31) res[32] = fma52lo(res[32], a[15], a[17]); // Sum(32) res[33] = fma52hi(res[33], a[15], a[17]); // Sum(32) res[33] = fma52lo(res[33], a[16], a[17]); // Sum(33) res[34] = fma52hi(res[34], a[16], a[17]); // Sum(33) res[24] = fma52lo(res[24], a[6], a[18]); // Sum(24) res[25] = fma52hi(res[25], a[6], a[18]); // Sum(24) res[25] = fma52lo(res[25], a[7], a[18]); // Sum(25) res[26] = fma52hi(res[26], a[7], a[18]); // Sum(25) res[26] = fma52lo(res[26], a[8], a[18]); // Sum(26) res[27] = fma52hi(res[27], a[8], a[18]); // Sum(26) res[27] = fma52lo(res[27], a[9], a[18]); // Sum(27) res[28] = fma52hi(res[28], a[9], a[18]); // Sum(27) res[28] = fma52lo(res[28], a[10], a[18]); // Sum(28) res[29] = fma52hi(res[29], a[10], a[18]); // Sum(28) res[29] = fma52lo(res[29], a[11], a[18]); // Sum(29) res[30] = fma52hi(res[30], a[11], a[18]); // Sum(29) res[30] = fma52lo(res[30], a[12], a[18]); // Sum(30) res[31] = fma52hi(res[31], a[12], a[18]); // Sum(30) res[31] = fma52lo(res[31], a[13], a[18]); // Sum(31) res[32] = fma52hi(res[32], a[13], a[18]); // Sum(31) res[32] = fma52lo(res[32], a[14], a[18]); // Sum(32) res[33] = fma52hi(res[33], a[14], a[18]); // Sum(32) res[33] = fma52lo(res[33], a[15], a[18]); // Sum(33) res[34] = fma52hi(res[34], a[15], a[18]); // Sum(33) res[34] = fma52lo(res[34], a[16], a[18]); // Sum(34) res[35] = fma52hi(res[35], a[16], a[18]); // Sum(34) res[35] = fma52lo(res[35], a[17], a[18]); // Sum(35) res[36] = fma52hi(res[36], a[17], a[18]); // Sum(35) res[24] = fma52lo(res[24], a[5], a[19]); // Sum(24) res[25] = fma52hi(res[25], a[5], a[19]); // Sum(24) res[25] = fma52lo(res[25], a[6], a[19]); // Sum(25) res[26] = fma52hi(res[26], a[6], a[19]); // Sum(25) res[26] = fma52lo(res[26], a[7], a[19]); // Sum(26) res[27] = fma52hi(res[27], a[7], a[19]); // Sum(26) res[27] = fma52lo(res[27], a[8], a[19]); // Sum(27) res[28] = fma52hi(res[28], a[8], a[19]); // Sum(27) res[28] = fma52lo(res[28], a[9], a[19]); // Sum(28) res[29] = fma52hi(res[29], a[9], a[19]); // Sum(28) res[29] = fma52lo(res[29], a[10], a[19]); // Sum(29) res[30] = fma52hi(res[30], a[10], a[19]); // Sum(29) res[30] = fma52lo(res[30], a[11], a[19]); // Sum(30) res[31] = fma52hi(res[31], a[11], a[19]); // Sum(30) res[31] = fma52lo(res[31], a[12], a[19]); // Sum(31) res[32] = fma52hi(res[32], a[12], a[19]); // Sum(31) res[32] = fma52lo(res[32], a[13], a[19]); // Sum(32) res[33] = fma52hi(res[33], a[13], a[19]); // Sum(32) res[33] = fma52lo(res[33], a[14], a[19]); // Sum(33) res[34] = fma52hi(res[34], a[14], a[19]); // Sum(33) res[34] = fma52lo(res[34], a[15], a[19]); // Sum(34) res[35] = fma52hi(res[35], a[15], a[19]); // Sum(34) res[35] = fma52lo(res[35], a[16], a[19]); // Sum(35) res[36] = fma52hi(res[36], a[16], a[19]); // Sum(35) res[24] = fma52lo(res[24], a[4], a[20]); // Sum(24) res[25] = fma52hi(res[25], a[4], a[20]); // Sum(24) res[25] = fma52lo(res[25], a[5], a[20]); // Sum(25) res[26] = fma52hi(res[26], a[5], a[20]); // Sum(25) res[26] = fma52lo(res[26], a[6], a[20]); // Sum(26) res[27] = fma52hi(res[27], a[6], a[20]); // Sum(26) res[27] = fma52lo(res[27], a[7], a[20]); // Sum(27) res[28] = fma52hi(res[28], a[7], a[20]); // Sum(27) res[28] = fma52lo(res[28], a[8], a[20]); // Sum(28) res[29] = fma52hi(res[29], a[8], a[20]); // Sum(28) res[29] = fma52lo(res[29], a[9], a[20]); // Sum(29) res[30] = fma52hi(res[30], a[9], a[20]); // Sum(29) res[30] = fma52lo(res[30], a[10], a[20]); // Sum(30) res[31] = fma52hi(res[31], a[10], a[20]); // Sum(30) res[31] = fma52lo(res[31], a[11], a[20]); // Sum(31) res[32] = fma52hi(res[32], a[11], a[20]); // Sum(31) res[32] = fma52lo(res[32], a[12], a[20]); // Sum(32) res[33] = fma52hi(res[33], a[12], a[20]); // Sum(32) res[33] = fma52lo(res[33], a[13], a[20]); // Sum(33) res[34] = fma52hi(res[34], a[13], a[20]); // Sum(33) res[34] = fma52lo(res[34], a[14], a[20]); // Sum(34) res[35] = fma52hi(res[35], a[14], a[20]); // Sum(34) res[35] = fma52lo(res[35], a[15], a[20]); // Sum(35) res[36] = fma52hi(res[36], a[15], a[20]); // Sum(35) res[24] = fma52lo(res[24], a[3], a[21]); // Sum(24) res[25] = fma52hi(res[25], a[3], a[21]); // Sum(24) res[25] = fma52lo(res[25], a[4], a[21]); // Sum(25) res[26] = fma52hi(res[26], a[4], a[21]); // Sum(25) res[26] = fma52lo(res[26], a[5], a[21]); // Sum(26) res[27] = fma52hi(res[27], a[5], a[21]); // Sum(26) res[27] = fma52lo(res[27], a[6], a[21]); // Sum(27) res[28] = fma52hi(res[28], a[6], a[21]); // Sum(27) res[28] = fma52lo(res[28], a[7], a[21]); // Sum(28) res[29] = fma52hi(res[29], a[7], a[21]); // Sum(28) res[29] = fma52lo(res[29], a[8], a[21]); // Sum(29) res[30] = fma52hi(res[30], a[8], a[21]); // Sum(29) res[30] = fma52lo(res[30], a[9], a[21]); // Sum(30) res[31] = fma52hi(res[31], a[9], a[21]); // Sum(30) res[31] = fma52lo(res[31], a[10], a[21]); // Sum(31) res[32] = fma52hi(res[32], a[10], a[21]); // Sum(31) res[32] = fma52lo(res[32], a[11], a[21]); // Sum(32) res[33] = fma52hi(res[33], a[11], a[21]); // Sum(32) res[33] = fma52lo(res[33], a[12], a[21]); // Sum(33) res[34] = fma52hi(res[34], a[12], a[21]); // Sum(33) res[34] = fma52lo(res[34], a[13], a[21]); // Sum(34) res[35] = fma52hi(res[35], a[13], a[21]); // Sum(34) res[35] = fma52lo(res[35], a[14], a[21]); // Sum(35) res[36] = fma52hi(res[36], a[14], a[21]); // Sum(35) res[24] = fma52lo(res[24], a[2], a[22]); // Sum(24) res[25] = fma52hi(res[25], a[2], a[22]); // Sum(24) res[25] = fma52lo(res[25], a[3], a[22]); // Sum(25) res[26] = fma52hi(res[26], a[3], a[22]); // Sum(25) res[26] = fma52lo(res[26], a[4], a[22]); // Sum(26) res[27] = fma52hi(res[27], a[4], a[22]); // Sum(26) res[27] = fma52lo(res[27], a[5], a[22]); // Sum(27) res[28] = fma52hi(res[28], a[5], a[22]); // Sum(27) res[28] = fma52lo(res[28], a[6], a[22]); // Sum(28) res[29] = fma52hi(res[29], a[6], a[22]); // Sum(28) res[29] = fma52lo(res[29], a[7], a[22]); // Sum(29) res[30] = fma52hi(res[30], a[7], a[22]); // Sum(29) res[30] = fma52lo(res[30], a[8], a[22]); // Sum(30) res[31] = fma52hi(res[31], a[8], a[22]); // Sum(30) res[31] = fma52lo(res[31], a[9], a[22]); // Sum(31) res[32] = fma52hi(res[32], a[9], a[22]); // Sum(31) res[32] = fma52lo(res[32], a[10], a[22]); // Sum(32) res[33] = fma52hi(res[33], a[10], a[22]); // Sum(32) res[33] = fma52lo(res[33], a[11], a[22]); // Sum(33) res[34] = fma52hi(res[34], a[11], a[22]); // Sum(33) res[34] = fma52lo(res[34], a[12], a[22]); // Sum(34) res[35] = fma52hi(res[35], a[12], a[22]); // Sum(34) res[35] = fma52lo(res[35], a[13], a[22]); // Sum(35) res[36] = fma52hi(res[36], a[13], a[22]); // Sum(35) res[24] = fma52lo(res[24], a[1], a[23]); // Sum(24) res[25] = fma52hi(res[25], a[1], a[23]); // Sum(24) res[25] = fma52lo(res[25], a[2], a[23]); // Sum(25) res[26] = fma52hi(res[26], a[2], a[23]); // Sum(25) res[26] = fma52lo(res[26], a[3], a[23]); // Sum(26) res[27] = fma52hi(res[27], a[3], a[23]); // Sum(26) res[27] = fma52lo(res[27], a[4], a[23]); // Sum(27) res[28] = fma52hi(res[28], a[4], a[23]); // Sum(27) res[28] = fma52lo(res[28], a[5], a[23]); // Sum(28) res[29] = fma52hi(res[29], a[5], a[23]); // Sum(28) res[29] = fma52lo(res[29], a[6], a[23]); // Sum(29) res[30] = fma52hi(res[30], a[6], a[23]); // Sum(29) res[30] = fma52lo(res[30], a[7], a[23]); // Sum(30) res[31] = fma52hi(res[31], a[7], a[23]); // Sum(30) res[31] = fma52lo(res[31], a[8], a[23]); // Sum(31) res[32] = fma52hi(res[32], a[8], a[23]); // Sum(31) res[32] = fma52lo(res[32], a[9], a[23]); // Sum(32) res[33] = fma52hi(res[33], a[9], a[23]); // Sum(32) res[33] = fma52lo(res[33], a[10], a[23]); // Sum(33) res[34] = fma52hi(res[34], a[10], a[23]); // Sum(33) res[34] = fma52lo(res[34], a[11], a[23]); // Sum(34) res[35] = fma52hi(res[35], a[11], a[23]); // Sum(34) res[35] = fma52lo(res[35], a[12], a[23]); // Sum(35) res[36] = fma52hi(res[36], a[12], a[23]); // Sum(35) res[24] = fma52lo(res[24], a[0], a[24]); // Sum(24) res[25] = fma52hi(res[25], a[0], a[24]); // Sum(24) res[25] = fma52lo(res[25], a[1], a[24]); // Sum(25) res[26] = fma52hi(res[26], a[1], a[24]); // Sum(25) res[26] = fma52lo(res[26], a[2], a[24]); // Sum(26) res[27] = fma52hi(res[27], a[2], a[24]); // Sum(26) res[27] = fma52lo(res[27], a[3], a[24]); // Sum(27) res[28] = fma52hi(res[28], a[3], a[24]); // Sum(27) res[28] = fma52lo(res[28], a[4], a[24]); // Sum(28) res[29] = fma52hi(res[29], a[4], a[24]); // Sum(28) res[29] = fma52lo(res[29], a[5], a[24]); // Sum(29) res[30] = fma52hi(res[30], a[5], a[24]); // Sum(29) res[30] = fma52lo(res[30], a[6], a[24]); // Sum(30) res[31] = fma52hi(res[31], a[6], a[24]); // Sum(30) res[31] = fma52lo(res[31], a[7], a[24]); // Sum(31) res[32] = fma52hi(res[32], a[7], a[24]); // Sum(31) res[32] = fma52lo(res[32], a[8], a[24]); // Sum(32) res[33] = fma52hi(res[33], a[8], a[24]); // Sum(32) res[33] = fma52lo(res[33], a[9], a[24]); // Sum(33) res[34] = fma52hi(res[34], a[9], a[24]); // Sum(33) res[34] = fma52lo(res[34], a[10], a[24]); // Sum(34) res[35] = fma52hi(res[35], a[10], a[24]); // Sum(34) res[35] = fma52lo(res[35], a[11], a[24]); // Sum(35) res[36] = fma52hi(res[36], a[11], a[24]); // Sum(35) res[25] = fma52lo(res[25], a[0], a[25]); // Sum(25) res[26] = fma52hi(res[26], a[0], a[25]); // Sum(25) res[26] = fma52lo(res[26], a[1], a[25]); // Sum(26) res[27] = fma52hi(res[27], a[1], a[25]); // Sum(26) res[27] = fma52lo(res[27], a[2], a[25]); // Sum(27) res[28] = fma52hi(res[28], a[2], a[25]); // Sum(27) res[28] = fma52lo(res[28], a[3], a[25]); // Sum(28) res[29] = fma52hi(res[29], a[3], a[25]); // Sum(28) res[29] = fma52lo(res[29], a[4], a[25]); // Sum(29) res[30] = fma52hi(res[30], a[4], a[25]); // Sum(29) res[30] = fma52lo(res[30], a[5], a[25]); // Sum(30) res[31] = fma52hi(res[31], a[5], a[25]); // Sum(30) res[31] = fma52lo(res[31], a[6], a[25]); // Sum(31) res[32] = fma52hi(res[32], a[6], a[25]); // Sum(31) res[32] = fma52lo(res[32], a[7], a[25]); // Sum(32) res[33] = fma52hi(res[33], a[7], a[25]); // Sum(32) res[33] = fma52lo(res[33], a[8], a[25]); // Sum(33) res[34] = fma52hi(res[34], a[8], a[25]); // Sum(33) res[34] = fma52lo(res[34], a[9], a[25]); // Sum(34) res[35] = fma52hi(res[35], a[9], a[25]); // Sum(34) res[35] = fma52lo(res[35], a[10], a[25]); // Sum(35) res[36] = fma52hi(res[36], a[10], a[25]); // Sum(35) res[26] = fma52lo(res[26], a[0], a[26]); // Sum(26) res[27] = fma52hi(res[27], a[0], a[26]); // Sum(26) res[27] = fma52lo(res[27], a[1], a[26]); // Sum(27) res[28] = fma52hi(res[28], a[1], a[26]); // Sum(27) res[28] = fma52lo(res[28], a[2], a[26]); // Sum(28) res[29] = fma52hi(res[29], a[2], a[26]); // Sum(28) res[29] = fma52lo(res[29], a[3], a[26]); // Sum(29) res[30] = fma52hi(res[30], a[3], a[26]); // Sum(29) res[30] = fma52lo(res[30], a[4], a[26]); // Sum(30) res[31] = fma52hi(res[31], a[4], a[26]); // Sum(30) res[31] = fma52lo(res[31], a[5], a[26]); // Sum(31) res[32] = fma52hi(res[32], a[5], a[26]); // Sum(31) res[32] = fma52lo(res[32], a[6], a[26]); // Sum(32) res[33] = fma52hi(res[33], a[6], a[26]); // Sum(32) res[33] = fma52lo(res[33], a[7], a[26]); // Sum(33) res[34] = fma52hi(res[34], a[7], a[26]); // Sum(33) res[34] = fma52lo(res[34], a[8], a[26]); // Sum(34) res[35] = fma52hi(res[35], a[8], a[26]); // Sum(34) res[35] = fma52lo(res[35], a[9], a[26]); // Sum(35) res[36] = fma52hi(res[36], a[9], a[26]); // Sum(35) res[27] = fma52lo(res[27], a[0], a[27]); // Sum(27) res[28] = fma52hi(res[28], a[0], a[27]); // Sum(27) res[28] = fma52lo(res[28], a[1], a[27]); // Sum(28) res[29] = fma52hi(res[29], a[1], a[27]); // Sum(28) res[29] = fma52lo(res[29], a[2], a[27]); // Sum(29) res[30] = fma52hi(res[30], a[2], a[27]); // Sum(29) res[30] = fma52lo(res[30], a[3], a[27]); // Sum(30) res[31] = fma52hi(res[31], a[3], a[27]); // Sum(30) res[31] = fma52lo(res[31], a[4], a[27]); // Sum(31) res[32] = fma52hi(res[32], a[4], a[27]); // Sum(31) res[32] = fma52lo(res[32], a[5], a[27]); // Sum(32) res[33] = fma52hi(res[33], a[5], a[27]); // Sum(32) res[33] = fma52lo(res[33], a[6], a[27]); // Sum(33) res[34] = fma52hi(res[34], a[6], a[27]); // Sum(33) res[34] = fma52lo(res[34], a[7], a[27]); // Sum(34) res[35] = fma52hi(res[35], a[7], a[27]); // Sum(34) res[35] = fma52lo(res[35], a[8], a[27]); // Sum(35) res[36] = fma52hi(res[36], a[8], a[27]); // Sum(35) res[28] = fma52lo(res[28], a[0], a[28]); // Sum(28) res[29] = fma52hi(res[29], a[0], a[28]); // Sum(28) res[29] = fma52lo(res[29], a[1], a[28]); // Sum(29) res[30] = fma52hi(res[30], a[1], a[28]); // Sum(29) res[30] = fma52lo(res[30], a[2], a[28]); // Sum(30) res[31] = fma52hi(res[31], a[2], a[28]); // Sum(30) res[31] = fma52lo(res[31], a[3], a[28]); // Sum(31) res[32] = fma52hi(res[32], a[3], a[28]); // Sum(31) res[32] = fma52lo(res[32], a[4], a[28]); // Sum(32) res[33] = fma52hi(res[33], a[4], a[28]); // Sum(32) res[33] = fma52lo(res[33], a[5], a[28]); // Sum(33) res[34] = fma52hi(res[34], a[5], a[28]); // Sum(33) res[34] = fma52lo(res[34], a[6], a[28]); // Sum(34) res[35] = fma52hi(res[35], a[6], a[28]); // Sum(34) res[35] = fma52lo(res[35], a[7], a[28]); // Sum(35) res[36] = fma52hi(res[36], a[7], a[28]); // Sum(35) res[29] = fma52lo(res[29], a[0], a[29]); // Sum(29) res[30] = fma52hi(res[30], a[0], a[29]); // Sum(29) res[30] = fma52lo(res[30], a[1], a[29]); // Sum(30) res[31] = fma52hi(res[31], a[1], a[29]); // Sum(30) res[31] = fma52lo(res[31], a[2], a[29]); // Sum(31) res[32] = fma52hi(res[32], a[2], a[29]); // Sum(31) res[32] = fma52lo(res[32], a[3], a[29]); // Sum(32) res[33] = fma52hi(res[33], a[3], a[29]); // Sum(32) res[33] = fma52lo(res[33], a[4], a[29]); // Sum(33) res[34] = fma52hi(res[34], a[4], a[29]); // Sum(33) res[34] = fma52lo(res[34], a[5], a[29]); // Sum(34) res[35] = fma52hi(res[35], a[5], a[29]); // Sum(34) res[35] = fma52lo(res[35], a[6], a[29]); // Sum(35) res[36] = fma52hi(res[36], a[6], a[29]); // Sum(35) res[30] = fma52lo(res[30], a[0], a[30]); // Sum(30) res[31] = fma52hi(res[31], a[0], a[30]); // Sum(30) res[31] = fma52lo(res[31], a[1], a[30]); // Sum(31) res[32] = fma52hi(res[32], a[1], a[30]); // Sum(31) res[32] = fma52lo(res[32], a[2], a[30]); // Sum(32) res[33] = fma52hi(res[33], a[2], a[30]); // Sum(32) res[33] = fma52lo(res[33], a[3], a[30]); // Sum(33) res[34] = fma52hi(res[34], a[3], a[30]); // Sum(33) res[34] = fma52lo(res[34], a[4], a[30]); // Sum(34) res[35] = fma52hi(res[35], a[4], a[30]); // Sum(34) res[35] = fma52lo(res[35], a[5], a[30]); // Sum(35) res[36] = fma52hi(res[36], a[5], a[30]); // Sum(35) res[31] = fma52lo(res[31], a[0], a[31]); // Sum(31) res[32] = fma52hi(res[32], a[0], a[31]); // Sum(31) res[32] = fma52lo(res[32], a[1], a[31]); // Sum(32) res[33] = fma52hi(res[33], a[1], a[31]); // Sum(32) res[33] = fma52lo(res[33], a[2], a[31]); // Sum(33) res[34] = fma52hi(res[34], a[2], a[31]); // Sum(33) res[34] = fma52lo(res[34], a[3], a[31]); // Sum(34) res[35] = fma52hi(res[35], a[3], a[31]); // Sum(34) res[35] = fma52lo(res[35], a[4], a[31]); // Sum(35) res[36] = fma52hi(res[36], a[4], a[31]); // Sum(35) res[32] = fma52lo(res[32], a[0], a[32]); // Sum(32) res[33] = fma52hi(res[33], a[0], a[32]); // Sum(32) res[33] = fma52lo(res[33], a[1], a[32]); // Sum(33) res[34] = fma52hi(res[34], a[1], a[32]); // Sum(33) res[34] = fma52lo(res[34], a[2], a[32]); // Sum(34) res[35] = fma52hi(res[35], a[2], a[32]); // Sum(34) res[35] = fma52lo(res[35], a[3], a[32]); // Sum(35) res[36] = fma52hi(res[36], a[3], a[32]); // Sum(35) res[33] = fma52lo(res[33], a[0], a[33]); // Sum(33) res[34] = fma52hi(res[34], a[0], a[33]); // Sum(33) res[34] = fma52lo(res[34], a[1], a[33]); // Sum(34) res[35] = fma52hi(res[35], a[1], a[33]); // Sum(34) res[35] = fma52lo(res[35], a[2], a[33]); // Sum(35) res[36] = fma52hi(res[36], a[2], a[33]); // Sum(35) res[34] = fma52lo(res[34], a[0], a[34]); // Sum(34) res[35] = fma52hi(res[35], a[0], a[34]); // Sum(34) res[35] = fma52lo(res[35], a[1], a[34]); // Sum(35) res[36] = fma52hi(res[36], a[1], a[34]); // Sum(35) res[35] = fma52lo(res[35], a[0], a[35]); // Sum(35) res[36] = fma52hi(res[36], a[0], a[35]); // Sum(35) res[24] = add64(res[24], res[24]); // Double(24) res[25] = add64(res[25], res[25]); // Double(25) res[26] = add64(res[26], res[26]); // Double(26) res[27] = add64(res[27], res[27]); // Double(27) res[28] = add64(res[28], res[28]); // Double(28) res[29] = add64(res[29], res[29]); // Double(29) res[30] = add64(res[30], res[30]); // Double(30) res[31] = add64(res[31], res[31]); // Double(31) res[32] = add64(res[32], res[32]); // Double(32) res[33] = add64(res[33], res[33]); // Double(33) res[34] = add64(res[34], res[34]); // Double(34) res[35] = add64(res[35], res[35]); // Double(35) res[24] = fma52lo(res[24], a[12], a[12]); // Add sqr(24) res[25] = fma52hi(res[25], a[12], a[12]); // Add sqr(24) res[26] = fma52lo(res[26], a[13], a[13]); // Add sqr(26) res[27] = fma52hi(res[27], a[13], a[13]); // Add sqr(26) res[28] = fma52lo(res[28], a[14], a[14]); // Add sqr(28) res[29] = fma52hi(res[29], a[14], a[14]); // Add sqr(28) res[30] = fma52lo(res[30], a[15], a[15]); // Add sqr(30) res[31] = fma52hi(res[31], a[15], a[15]); // Add sqr(30) res[32] = fma52lo(res[32], a[16], a[16]); // Add sqr(32) res[33] = fma52hi(res[33], a[16], a[16]); // Add sqr(32) res[34] = fma52lo(res[34], a[17], a[17]); // Add sqr(34) res[35] = fma52hi(res[35], a[17], a[17]); // Add sqr(34) res[36] = fma52lo(res[36], a[17], a[19]); // Sum(36) res[37] = fma52hi(res[37], a[17], a[19]); // Sum(36) res[37] = fma52lo(res[37], a[18], a[19]); // Sum(37) res[38] = fma52hi(res[38], a[18], a[19]); // Sum(37) res[36] = fma52lo(res[36], a[16], a[20]); // Sum(36) res[37] = fma52hi(res[37], a[16], a[20]); // Sum(36) res[37] = fma52lo(res[37], a[17], a[20]); // Sum(37) res[38] = fma52hi(res[38], a[17], a[20]); // Sum(37) res[38] = fma52lo(res[38], a[18], a[20]); // Sum(38) res[39] = fma52hi(res[39], a[18], a[20]); // Sum(38) res[39] = fma52lo(res[39], a[19], a[20]); // Sum(39) res[40] = fma52hi(res[40], a[19], a[20]); // Sum(39) res[36] = fma52lo(res[36], a[15], a[21]); // Sum(36) res[37] = fma52hi(res[37], a[15], a[21]); // Sum(36) res[37] = fma52lo(res[37], a[16], a[21]); // Sum(37) res[38] = fma52hi(res[38], a[16], a[21]); // Sum(37) res[38] = fma52lo(res[38], a[17], a[21]); // Sum(38) res[39] = fma52hi(res[39], a[17], a[21]); // Sum(38) res[39] = fma52lo(res[39], a[18], a[21]); // Sum(39) res[40] = fma52hi(res[40], a[18], a[21]); // Sum(39) res[40] = fma52lo(res[40], a[19], a[21]); // Sum(40) res[41] = fma52hi(res[41], a[19], a[21]); // Sum(40) res[41] = fma52lo(res[41], a[20], a[21]); // Sum(41) res[42] = fma52hi(res[42], a[20], a[21]); // Sum(41) res[36] = fma52lo(res[36], a[14], a[22]); // Sum(36) res[37] = fma52hi(res[37], a[14], a[22]); // Sum(36) res[37] = fma52lo(res[37], a[15], a[22]); // Sum(37) res[38] = fma52hi(res[38], a[15], a[22]); // Sum(37) res[38] = fma52lo(res[38], a[16], a[22]); // Sum(38) res[39] = fma52hi(res[39], a[16], a[22]); // Sum(38) res[39] = fma52lo(res[39], a[17], a[22]); // Sum(39) res[40] = fma52hi(res[40], a[17], a[22]); // Sum(39) res[40] = fma52lo(res[40], a[18], a[22]); // Sum(40) res[41] = fma52hi(res[41], a[18], a[22]); // Sum(40) res[41] = fma52lo(res[41], a[19], a[22]); // Sum(41) res[42] = fma52hi(res[42], a[19], a[22]); // Sum(41) res[42] = fma52lo(res[42], a[20], a[22]); // Sum(42) res[43] = fma52hi(res[43], a[20], a[22]); // Sum(42) res[43] = fma52lo(res[43], a[21], a[22]); // Sum(43) res[44] = fma52hi(res[44], a[21], a[22]); // Sum(43) res[36] = fma52lo(res[36], a[13], a[23]); // Sum(36) res[37] = fma52hi(res[37], a[13], a[23]); // Sum(36) res[37] = fma52lo(res[37], a[14], a[23]); // Sum(37) res[38] = fma52hi(res[38], a[14], a[23]); // Sum(37) res[38] = fma52lo(res[38], a[15], a[23]); // Sum(38) res[39] = fma52hi(res[39], a[15], a[23]); // Sum(38) res[39] = fma52lo(res[39], a[16], a[23]); // Sum(39) res[40] = fma52hi(res[40], a[16], a[23]); // Sum(39) res[40] = fma52lo(res[40], a[17], a[23]); // Sum(40) res[41] = fma52hi(res[41], a[17], a[23]); // Sum(40) res[41] = fma52lo(res[41], a[18], a[23]); // Sum(41) res[42] = fma52hi(res[42], a[18], a[23]); // Sum(41) res[42] = fma52lo(res[42], a[19], a[23]); // Sum(42) res[43] = fma52hi(res[43], a[19], a[23]); // Sum(42) res[43] = fma52lo(res[43], a[20], a[23]); // Sum(43) res[44] = fma52hi(res[44], a[20], a[23]); // Sum(43) res[44] = fma52lo(res[44], a[21], a[23]); // Sum(44) res[45] = fma52hi(res[45], a[21], a[23]); // Sum(44) res[45] = fma52lo(res[45], a[22], a[23]); // Sum(45) res[46] = fma52hi(res[46], a[22], a[23]); // Sum(45) res[36] = fma52lo(res[36], a[12], a[24]); // Sum(36) res[37] = fma52hi(res[37], a[12], a[24]); // Sum(36) res[37] = fma52lo(res[37], a[13], a[24]); // Sum(37) res[38] = fma52hi(res[38], a[13], a[24]); // Sum(37) res[38] = fma52lo(res[38], a[14], a[24]); // Sum(38) res[39] = fma52hi(res[39], a[14], a[24]); // Sum(38) res[39] = fma52lo(res[39], a[15], a[24]); // Sum(39) res[40] = fma52hi(res[40], a[15], a[24]); // Sum(39) res[40] = fma52lo(res[40], a[16], a[24]); // Sum(40) res[41] = fma52hi(res[41], a[16], a[24]); // Sum(40) res[41] = fma52lo(res[41], a[17], a[24]); // Sum(41) res[42] = fma52hi(res[42], a[17], a[24]); // Sum(41) res[42] = fma52lo(res[42], a[18], a[24]); // Sum(42) res[43] = fma52hi(res[43], a[18], a[24]); // Sum(42) res[43] = fma52lo(res[43], a[19], a[24]); // Sum(43) res[44] = fma52hi(res[44], a[19], a[24]); // Sum(43) res[44] = fma52lo(res[44], a[20], a[24]); // Sum(44) res[45] = fma52hi(res[45], a[20], a[24]); // Sum(44) res[45] = fma52lo(res[45], a[21], a[24]); // Sum(45) res[46] = fma52hi(res[46], a[21], a[24]); // Sum(45) res[46] = fma52lo(res[46], a[22], a[24]); // Sum(46) res[47] = fma52hi(res[47], a[22], a[24]); // Sum(46) res[47] = fma52lo(res[47], a[23], a[24]); // Sum(47) res[48] = fma52hi(res[48], a[23], a[24]); // Sum(47) res[36] = fma52lo(res[36], a[11], a[25]); // Sum(36) res[37] = fma52hi(res[37], a[11], a[25]); // Sum(36) res[37] = fma52lo(res[37], a[12], a[25]); // Sum(37) res[38] = fma52hi(res[38], a[12], a[25]); // Sum(37) res[38] = fma52lo(res[38], a[13], a[25]); // Sum(38) res[39] = fma52hi(res[39], a[13], a[25]); // Sum(38) res[39] = fma52lo(res[39], a[14], a[25]); // Sum(39) res[40] = fma52hi(res[40], a[14], a[25]); // Sum(39) res[40] = fma52lo(res[40], a[15], a[25]); // Sum(40) res[41] = fma52hi(res[41], a[15], a[25]); // Sum(40) res[41] = fma52lo(res[41], a[16], a[25]); // Sum(41) res[42] = fma52hi(res[42], a[16], a[25]); // Sum(41) res[42] = fma52lo(res[42], a[17], a[25]); // Sum(42) res[43] = fma52hi(res[43], a[17], a[25]); // Sum(42) res[43] = fma52lo(res[43], a[18], a[25]); // Sum(43) res[44] = fma52hi(res[44], a[18], a[25]); // Sum(43) res[44] = fma52lo(res[44], a[19], a[25]); // Sum(44) res[45] = fma52hi(res[45], a[19], a[25]); // Sum(44) res[45] = fma52lo(res[45], a[20], a[25]); // Sum(45) res[46] = fma52hi(res[46], a[20], a[25]); // Sum(45) res[46] = fma52lo(res[46], a[21], a[25]); // Sum(46) res[47] = fma52hi(res[47], a[21], a[25]); // Sum(46) res[47] = fma52lo(res[47], a[22], a[25]); // Sum(47) res[48] = fma52hi(res[48], a[22], a[25]); // Sum(47) res[36] = fma52lo(res[36], a[10], a[26]); // Sum(36) res[37] = fma52hi(res[37], a[10], a[26]); // Sum(36) res[37] = fma52lo(res[37], a[11], a[26]); // Sum(37) res[38] = fma52hi(res[38], a[11], a[26]); // Sum(37) res[38] = fma52lo(res[38], a[12], a[26]); // Sum(38) res[39] = fma52hi(res[39], a[12], a[26]); // Sum(38) res[39] = fma52lo(res[39], a[13], a[26]); // Sum(39) res[40] = fma52hi(res[40], a[13], a[26]); // Sum(39) res[40] = fma52lo(res[40], a[14], a[26]); // Sum(40) res[41] = fma52hi(res[41], a[14], a[26]); // Sum(40) res[41] = fma52lo(res[41], a[15], a[26]); // Sum(41) res[42] = fma52hi(res[42], a[15], a[26]); // Sum(41) res[42] = fma52lo(res[42], a[16], a[26]); // Sum(42) res[43] = fma52hi(res[43], a[16], a[26]); // Sum(42) res[43] = fma52lo(res[43], a[17], a[26]); // Sum(43) res[44] = fma52hi(res[44], a[17], a[26]); // Sum(43) res[44] = fma52lo(res[44], a[18], a[26]); // Sum(44) res[45] = fma52hi(res[45], a[18], a[26]); // Sum(44) res[45] = fma52lo(res[45], a[19], a[26]); // Sum(45) res[46] = fma52hi(res[46], a[19], a[26]); // Sum(45) res[46] = fma52lo(res[46], a[20], a[26]); // Sum(46) res[47] = fma52hi(res[47], a[20], a[26]); // Sum(46) res[47] = fma52lo(res[47], a[21], a[26]); // Sum(47) res[48] = fma52hi(res[48], a[21], a[26]); // Sum(47) res[36] = fma52lo(res[36], a[9], a[27]); // Sum(36) res[37] = fma52hi(res[37], a[9], a[27]); // Sum(36) res[37] = fma52lo(res[37], a[10], a[27]); // Sum(37) res[38] = fma52hi(res[38], a[10], a[27]); // Sum(37) res[38] = fma52lo(res[38], a[11], a[27]); // Sum(38) res[39] = fma52hi(res[39], a[11], a[27]); // Sum(38) res[39] = fma52lo(res[39], a[12], a[27]); // Sum(39) res[40] = fma52hi(res[40], a[12], a[27]); // Sum(39) res[40] = fma52lo(res[40], a[13], a[27]); // Sum(40) res[41] = fma52hi(res[41], a[13], a[27]); // Sum(40) res[41] = fma52lo(res[41], a[14], a[27]); // Sum(41) res[42] = fma52hi(res[42], a[14], a[27]); // Sum(41) res[42] = fma52lo(res[42], a[15], a[27]); // Sum(42) res[43] = fma52hi(res[43], a[15], a[27]); // Sum(42) res[43] = fma52lo(res[43], a[16], a[27]); // Sum(43) res[44] = fma52hi(res[44], a[16], a[27]); // Sum(43) res[44] = fma52lo(res[44], a[17], a[27]); // Sum(44) res[45] = fma52hi(res[45], a[17], a[27]); // Sum(44) res[45] = fma52lo(res[45], a[18], a[27]); // Sum(45) res[46] = fma52hi(res[46], a[18], a[27]); // Sum(45) res[46] = fma52lo(res[46], a[19], a[27]); // Sum(46) res[47] = fma52hi(res[47], a[19], a[27]); // Sum(46) res[47] = fma52lo(res[47], a[20], a[27]); // Sum(47) res[48] = fma52hi(res[48], a[20], a[27]); // Sum(47) res[36] = fma52lo(res[36], a[8], a[28]); // Sum(36) res[37] = fma52hi(res[37], a[8], a[28]); // Sum(36) res[37] = fma52lo(res[37], a[9], a[28]); // Sum(37) res[38] = fma52hi(res[38], a[9], a[28]); // Sum(37) res[38] = fma52lo(res[38], a[10], a[28]); // Sum(38) res[39] = fma52hi(res[39], a[10], a[28]); // Sum(38) res[39] = fma52lo(res[39], a[11], a[28]); // Sum(39) res[40] = fma52hi(res[40], a[11], a[28]); // Sum(39) res[40] = fma52lo(res[40], a[12], a[28]); // Sum(40) res[41] = fma52hi(res[41], a[12], a[28]); // Sum(40) res[41] = fma52lo(res[41], a[13], a[28]); // Sum(41) res[42] = fma52hi(res[42], a[13], a[28]); // Sum(41) res[42] = fma52lo(res[42], a[14], a[28]); // Sum(42) res[43] = fma52hi(res[43], a[14], a[28]); // Sum(42) res[43] = fma52lo(res[43], a[15], a[28]); // Sum(43) res[44] = fma52hi(res[44], a[15], a[28]); // Sum(43) res[44] = fma52lo(res[44], a[16], a[28]); // Sum(44) res[45] = fma52hi(res[45], a[16], a[28]); // Sum(44) res[45] = fma52lo(res[45], a[17], a[28]); // Sum(45) res[46] = fma52hi(res[46], a[17], a[28]); // Sum(45) res[46] = fma52lo(res[46], a[18], a[28]); // Sum(46) res[47] = fma52hi(res[47], a[18], a[28]); // Sum(46) res[47] = fma52lo(res[47], a[19], a[28]); // Sum(47) res[48] = fma52hi(res[48], a[19], a[28]); // Sum(47) res[36] = fma52lo(res[36], a[7], a[29]); // Sum(36) res[37] = fma52hi(res[37], a[7], a[29]); // Sum(36) res[37] = fma52lo(res[37], a[8], a[29]); // Sum(37) res[38] = fma52hi(res[38], a[8], a[29]); // Sum(37) res[38] = fma52lo(res[38], a[9], a[29]); // Sum(38) res[39] = fma52hi(res[39], a[9], a[29]); // Sum(38) res[39] = fma52lo(res[39], a[10], a[29]); // Sum(39) res[40] = fma52hi(res[40], a[10], a[29]); // Sum(39) res[40] = fma52lo(res[40], a[11], a[29]); // Sum(40) res[41] = fma52hi(res[41], a[11], a[29]); // Sum(40) res[41] = fma52lo(res[41], a[12], a[29]); // Sum(41) res[42] = fma52hi(res[42], a[12], a[29]); // Sum(41) res[42] = fma52lo(res[42], a[13], a[29]); // Sum(42) res[43] = fma52hi(res[43], a[13], a[29]); // Sum(42) res[43] = fma52lo(res[43], a[14], a[29]); // Sum(43) res[44] = fma52hi(res[44], a[14], a[29]); // Sum(43) res[44] = fma52lo(res[44], a[15], a[29]); // Sum(44) res[45] = fma52hi(res[45], a[15], a[29]); // Sum(44) res[45] = fma52lo(res[45], a[16], a[29]); // Sum(45) res[46] = fma52hi(res[46], a[16], a[29]); // Sum(45) res[46] = fma52lo(res[46], a[17], a[29]); // Sum(46) res[47] = fma52hi(res[47], a[17], a[29]); // Sum(46) res[47] = fma52lo(res[47], a[18], a[29]); // Sum(47) res[48] = fma52hi(res[48], a[18], a[29]); // Sum(47) res[36] = fma52lo(res[36], a[6], a[30]); // Sum(36) res[37] = fma52hi(res[37], a[6], a[30]); // Sum(36) res[37] = fma52lo(res[37], a[7], a[30]); // Sum(37) res[38] = fma52hi(res[38], a[7], a[30]); // Sum(37) res[38] = fma52lo(res[38], a[8], a[30]); // Sum(38) res[39] = fma52hi(res[39], a[8], a[30]); // Sum(38) res[39] = fma52lo(res[39], a[9], a[30]); // Sum(39) res[40] = fma52hi(res[40], a[9], a[30]); // Sum(39) res[40] = fma52lo(res[40], a[10], a[30]); // Sum(40) res[41] = fma52hi(res[41], a[10], a[30]); // Sum(40) res[41] = fma52lo(res[41], a[11], a[30]); // Sum(41) res[42] = fma52hi(res[42], a[11], a[30]); // Sum(41) res[42] = fma52lo(res[42], a[12], a[30]); // Sum(42) res[43] = fma52hi(res[43], a[12], a[30]); // Sum(42) res[43] = fma52lo(res[43], a[13], a[30]); // Sum(43) res[44] = fma52hi(res[44], a[13], a[30]); // Sum(43) res[44] = fma52lo(res[44], a[14], a[30]); // Sum(44) res[45] = fma52hi(res[45], a[14], a[30]); // Sum(44) res[45] = fma52lo(res[45], a[15], a[30]); // Sum(45) res[46] = fma52hi(res[46], a[15], a[30]); // Sum(45) res[46] = fma52lo(res[46], a[16], a[30]); // Sum(46) res[47] = fma52hi(res[47], a[16], a[30]); // Sum(46) res[47] = fma52lo(res[47], a[17], a[30]); // Sum(47) res[48] = fma52hi(res[48], a[17], a[30]); // Sum(47) res[36] = fma52lo(res[36], a[5], a[31]); // Sum(36) res[37] = fma52hi(res[37], a[5], a[31]); // Sum(36) res[37] = fma52lo(res[37], a[6], a[31]); // Sum(37) res[38] = fma52hi(res[38], a[6], a[31]); // Sum(37) res[38] = fma52lo(res[38], a[7], a[31]); // Sum(38) res[39] = fma52hi(res[39], a[7], a[31]); // Sum(38) res[39] = fma52lo(res[39], a[8], a[31]); // Sum(39) res[40] = fma52hi(res[40], a[8], a[31]); // Sum(39) res[40] = fma52lo(res[40], a[9], a[31]); // Sum(40) res[41] = fma52hi(res[41], a[9], a[31]); // Sum(40) res[41] = fma52lo(res[41], a[10], a[31]); // Sum(41) res[42] = fma52hi(res[42], a[10], a[31]); // Sum(41) res[42] = fma52lo(res[42], a[11], a[31]); // Sum(42) res[43] = fma52hi(res[43], a[11], a[31]); // Sum(42) res[43] = fma52lo(res[43], a[12], a[31]); // Sum(43) res[44] = fma52hi(res[44], a[12], a[31]); // Sum(43) res[44] = fma52lo(res[44], a[13], a[31]); // Sum(44) res[45] = fma52hi(res[45], a[13], a[31]); // Sum(44) res[45] = fma52lo(res[45], a[14], a[31]); // Sum(45) res[46] = fma52hi(res[46], a[14], a[31]); // Sum(45) res[46] = fma52lo(res[46], a[15], a[31]); // Sum(46) res[47] = fma52hi(res[47], a[15], a[31]); // Sum(46) res[47] = fma52lo(res[47], a[16], a[31]); // Sum(47) res[48] = fma52hi(res[48], a[16], a[31]); // Sum(47) res[36] = fma52lo(res[36], a[4], a[32]); // Sum(36) res[37] = fma52hi(res[37], a[4], a[32]); // Sum(36) res[37] = fma52lo(res[37], a[5], a[32]); // Sum(37) res[38] = fma52hi(res[38], a[5], a[32]); // Sum(37) res[38] = fma52lo(res[38], a[6], a[32]); // Sum(38) res[39] = fma52hi(res[39], a[6], a[32]); // Sum(38) res[39] = fma52lo(res[39], a[7], a[32]); // Sum(39) res[40] = fma52hi(res[40], a[7], a[32]); // Sum(39) res[40] = fma52lo(res[40], a[8], a[32]); // Sum(40) res[41] = fma52hi(res[41], a[8], a[32]); // Sum(40) res[41] = fma52lo(res[41], a[9], a[32]); // Sum(41) res[42] = fma52hi(res[42], a[9], a[32]); // Sum(41) res[42] = fma52lo(res[42], a[10], a[32]); // Sum(42) res[43] = fma52hi(res[43], a[10], a[32]); // Sum(42) res[43] = fma52lo(res[43], a[11], a[32]); // Sum(43) res[44] = fma52hi(res[44], a[11], a[32]); // Sum(43) res[44] = fma52lo(res[44], a[12], a[32]); // Sum(44) res[45] = fma52hi(res[45], a[12], a[32]); // Sum(44) res[45] = fma52lo(res[45], a[13], a[32]); // Sum(45) res[46] = fma52hi(res[46], a[13], a[32]); // Sum(45) res[46] = fma52lo(res[46], a[14], a[32]); // Sum(46) res[47] = fma52hi(res[47], a[14], a[32]); // Sum(46) res[47] = fma52lo(res[47], a[15], a[32]); // Sum(47) res[48] = fma52hi(res[48], a[15], a[32]); // Sum(47) res[36] = fma52lo(res[36], a[3], a[33]); // Sum(36) res[37] = fma52hi(res[37], a[3], a[33]); // Sum(36) res[37] = fma52lo(res[37], a[4], a[33]); // Sum(37) res[38] = fma52hi(res[38], a[4], a[33]); // Sum(37) res[38] = fma52lo(res[38], a[5], a[33]); // Sum(38) res[39] = fma52hi(res[39], a[5], a[33]); // Sum(38) res[39] = fma52lo(res[39], a[6], a[33]); // Sum(39) res[40] = fma52hi(res[40], a[6], a[33]); // Sum(39) res[40] = fma52lo(res[40], a[7], a[33]); // Sum(40) res[41] = fma52hi(res[41], a[7], a[33]); // Sum(40) res[41] = fma52lo(res[41], a[8], a[33]); // Sum(41) res[42] = fma52hi(res[42], a[8], a[33]); // Sum(41) res[42] = fma52lo(res[42], a[9], a[33]); // Sum(42) res[43] = fma52hi(res[43], a[9], a[33]); // Sum(42) res[43] = fma52lo(res[43], a[10], a[33]); // Sum(43) res[44] = fma52hi(res[44], a[10], a[33]); // Sum(43) res[44] = fma52lo(res[44], a[11], a[33]); // Sum(44) res[45] = fma52hi(res[45], a[11], a[33]); // Sum(44) res[45] = fma52lo(res[45], a[12], a[33]); // Sum(45) res[46] = fma52hi(res[46], a[12], a[33]); // Sum(45) res[46] = fma52lo(res[46], a[13], a[33]); // Sum(46) res[47] = fma52hi(res[47], a[13], a[33]); // Sum(46) res[47] = fma52lo(res[47], a[14], a[33]); // Sum(47) res[48] = fma52hi(res[48], a[14], a[33]); // Sum(47) res[36] = fma52lo(res[36], a[2], a[34]); // Sum(36) res[37] = fma52hi(res[37], a[2], a[34]); // Sum(36) res[37] = fma52lo(res[37], a[3], a[34]); // Sum(37) res[38] = fma52hi(res[38], a[3], a[34]); // Sum(37) res[38] = fma52lo(res[38], a[4], a[34]); // Sum(38) res[39] = fma52hi(res[39], a[4], a[34]); // Sum(38) res[39] = fma52lo(res[39], a[5], a[34]); // Sum(39) res[40] = fma52hi(res[40], a[5], a[34]); // Sum(39) res[40] = fma52lo(res[40], a[6], a[34]); // Sum(40) res[41] = fma52hi(res[41], a[6], a[34]); // Sum(40) res[41] = fma52lo(res[41], a[7], a[34]); // Sum(41) res[42] = fma52hi(res[42], a[7], a[34]); // Sum(41) res[42] = fma52lo(res[42], a[8], a[34]); // Sum(42) res[43] = fma52hi(res[43], a[8], a[34]); // Sum(42) res[43] = fma52lo(res[43], a[9], a[34]); // Sum(43) res[44] = fma52hi(res[44], a[9], a[34]); // Sum(43) res[44] = fma52lo(res[44], a[10], a[34]); // Sum(44) res[45] = fma52hi(res[45], a[10], a[34]); // Sum(44) res[45] = fma52lo(res[45], a[11], a[34]); // Sum(45) res[46] = fma52hi(res[46], a[11], a[34]); // Sum(45) res[46] = fma52lo(res[46], a[12], a[34]); // Sum(46) res[47] = fma52hi(res[47], a[12], a[34]); // Sum(46) res[47] = fma52lo(res[47], a[13], a[34]); // Sum(47) res[48] = fma52hi(res[48], a[13], a[34]); // Sum(47) res[36] = fma52lo(res[36], a[1], a[35]); // Sum(36) res[37] = fma52hi(res[37], a[1], a[35]); // Sum(36) res[37] = fma52lo(res[37], a[2], a[35]); // Sum(37) res[38] = fma52hi(res[38], a[2], a[35]); // Sum(37) res[38] = fma52lo(res[38], a[3], a[35]); // Sum(38) res[39] = fma52hi(res[39], a[3], a[35]); // Sum(38) res[39] = fma52lo(res[39], a[4], a[35]); // Sum(39) res[40] = fma52hi(res[40], a[4], a[35]); // Sum(39) res[40] = fma52lo(res[40], a[5], a[35]); // Sum(40) res[41] = fma52hi(res[41], a[5], a[35]); // Sum(40) res[41] = fma52lo(res[41], a[6], a[35]); // Sum(41) res[42] = fma52hi(res[42], a[6], a[35]); // Sum(41) res[42] = fma52lo(res[42], a[7], a[35]); // Sum(42) res[43] = fma52hi(res[43], a[7], a[35]); // Sum(42) res[43] = fma52lo(res[43], a[8], a[35]); // Sum(43) res[44] = fma52hi(res[44], a[8], a[35]); // Sum(43) res[44] = fma52lo(res[44], a[9], a[35]); // Sum(44) res[45] = fma52hi(res[45], a[9], a[35]); // Sum(44) res[45] = fma52lo(res[45], a[10], a[35]); // Sum(45) res[46] = fma52hi(res[46], a[10], a[35]); // Sum(45) res[46] = fma52lo(res[46], a[11], a[35]); // Sum(46) res[47] = fma52hi(res[47], a[11], a[35]); // Sum(46) res[47] = fma52lo(res[47], a[12], a[35]); // Sum(47) res[48] = fma52hi(res[48], a[12], a[35]); // Sum(47) res[36] = fma52lo(res[36], a[0], a[36]); // Sum(36) res[37] = fma52hi(res[37], a[0], a[36]); // Sum(36) res[37] = fma52lo(res[37], a[1], a[36]); // Sum(37) res[38] = fma52hi(res[38], a[1], a[36]); // Sum(37) res[38] = fma52lo(res[38], a[2], a[36]); // Sum(38) res[39] = fma52hi(res[39], a[2], a[36]); // Sum(38) res[39] = fma52lo(res[39], a[3], a[36]); // Sum(39) res[40] = fma52hi(res[40], a[3], a[36]); // Sum(39) res[40] = fma52lo(res[40], a[4], a[36]); // Sum(40) res[41] = fma52hi(res[41], a[4], a[36]); // Sum(40) res[41] = fma52lo(res[41], a[5], a[36]); // Sum(41) res[42] = fma52hi(res[42], a[5], a[36]); // Sum(41) res[42] = fma52lo(res[42], a[6], a[36]); // Sum(42) res[43] = fma52hi(res[43], a[6], a[36]); // Sum(42) res[43] = fma52lo(res[43], a[7], a[36]); // Sum(43) res[44] = fma52hi(res[44], a[7], a[36]); // Sum(43) res[44] = fma52lo(res[44], a[8], a[36]); // Sum(44) res[45] = fma52hi(res[45], a[8], a[36]); // Sum(44) res[45] = fma52lo(res[45], a[9], a[36]); // Sum(45) res[46] = fma52hi(res[46], a[9], a[36]); // Sum(45) res[46] = fma52lo(res[46], a[10], a[36]); // Sum(46) res[47] = fma52hi(res[47], a[10], a[36]); // Sum(46) res[47] = fma52lo(res[47], a[11], a[36]); // Sum(47) res[48] = fma52hi(res[48], a[11], a[36]); // Sum(47) res[37] = fma52lo(res[37], a[0], a[37]); // Sum(37) res[38] = fma52hi(res[38], a[0], a[37]); // Sum(37) res[38] = fma52lo(res[38], a[1], a[37]); // Sum(38) res[39] = fma52hi(res[39], a[1], a[37]); // Sum(38) res[39] = fma52lo(res[39], a[2], a[37]); // Sum(39) res[40] = fma52hi(res[40], a[2], a[37]); // Sum(39) res[40] = fma52lo(res[40], a[3], a[37]); // Sum(40) res[41] = fma52hi(res[41], a[3], a[37]); // Sum(40) res[41] = fma52lo(res[41], a[4], a[37]); // Sum(41) res[42] = fma52hi(res[42], a[4], a[37]); // Sum(41) res[42] = fma52lo(res[42], a[5], a[37]); // Sum(42) res[43] = fma52hi(res[43], a[5], a[37]); // Sum(42) res[43] = fma52lo(res[43], a[6], a[37]); // Sum(43) res[44] = fma52hi(res[44], a[6], a[37]); // Sum(43) res[44] = fma52lo(res[44], a[7], a[37]); // Sum(44) res[45] = fma52hi(res[45], a[7], a[37]); // Sum(44) res[45] = fma52lo(res[45], a[8], a[37]); // Sum(45) res[46] = fma52hi(res[46], a[8], a[37]); // Sum(45) res[46] = fma52lo(res[46], a[9], a[37]); // Sum(46) res[47] = fma52hi(res[47], a[9], a[37]); // Sum(46) res[47] = fma52lo(res[47], a[10], a[37]); // Sum(47) res[48] = fma52hi(res[48], a[10], a[37]); // Sum(47) res[38] = fma52lo(res[38], a[0], a[38]); // Sum(38) res[39] = fma52hi(res[39], a[0], a[38]); // Sum(38) res[39] = fma52lo(res[39], a[1], a[38]); // Sum(39) res[40] = fma52hi(res[40], a[1], a[38]); // Sum(39) res[40] = fma52lo(res[40], a[2], a[38]); // Sum(40) res[41] = fma52hi(res[41], a[2], a[38]); // Sum(40) res[41] = fma52lo(res[41], a[3], a[38]); // Sum(41) res[42] = fma52hi(res[42], a[3], a[38]); // Sum(41) res[42] = fma52lo(res[42], a[4], a[38]); // Sum(42) res[43] = fma52hi(res[43], a[4], a[38]); // Sum(42) res[43] = fma52lo(res[43], a[5], a[38]); // Sum(43) res[44] = fma52hi(res[44], a[5], a[38]); // Sum(43) res[44] = fma52lo(res[44], a[6], a[38]); // Sum(44) res[45] = fma52hi(res[45], a[6], a[38]); // Sum(44) res[45] = fma52lo(res[45], a[7], a[38]); // Sum(45) res[46] = fma52hi(res[46], a[7], a[38]); // Sum(45) res[46] = fma52lo(res[46], a[8], a[38]); // Sum(46) res[47] = fma52hi(res[47], a[8], a[38]); // Sum(46) res[47] = fma52lo(res[47], a[9], a[38]); // Sum(47) res[48] = fma52hi(res[48], a[9], a[38]); // Sum(47) res[39] = fma52lo(res[39], a[0], a[39]); // Sum(39) res[40] = fma52hi(res[40], a[0], a[39]); // Sum(39) res[40] = fma52lo(res[40], a[1], a[39]); // Sum(40) res[41] = fma52hi(res[41], a[1], a[39]); // Sum(40) res[41] = fma52lo(res[41], a[2], a[39]); // Sum(41) res[42] = fma52hi(res[42], a[2], a[39]); // Sum(41) res[42] = fma52lo(res[42], a[3], a[39]); // Sum(42) res[43] = fma52hi(res[43], a[3], a[39]); // Sum(42) res[43] = fma52lo(res[43], a[4], a[39]); // Sum(43) res[44] = fma52hi(res[44], a[4], a[39]); // Sum(43) res[44] = fma52lo(res[44], a[5], a[39]); // Sum(44) res[45] = fma52hi(res[45], a[5], a[39]); // Sum(44) res[45] = fma52lo(res[45], a[6], a[39]); // Sum(45) res[46] = fma52hi(res[46], a[6], a[39]); // Sum(45) res[46] = fma52lo(res[46], a[7], a[39]); // Sum(46) res[47] = fma52hi(res[47], a[7], a[39]); // Sum(46) res[47] = fma52lo(res[47], a[8], a[39]); // Sum(47) res[48] = fma52hi(res[48], a[8], a[39]); // Sum(47) res[40] = fma52lo(res[40], a[0], a[40]); // Sum(40) res[41] = fma52hi(res[41], a[0], a[40]); // Sum(40) res[41] = fma52lo(res[41], a[1], a[40]); // Sum(41) res[42] = fma52hi(res[42], a[1], a[40]); // Sum(41) res[42] = fma52lo(res[42], a[2], a[40]); // Sum(42) res[43] = fma52hi(res[43], a[2], a[40]); // Sum(42) res[43] = fma52lo(res[43], a[3], a[40]); // Sum(43) res[44] = fma52hi(res[44], a[3], a[40]); // Sum(43) res[44] = fma52lo(res[44], a[4], a[40]); // Sum(44) res[45] = fma52hi(res[45], a[4], a[40]); // Sum(44) res[45] = fma52lo(res[45], a[5], a[40]); // Sum(45) res[46] = fma52hi(res[46], a[5], a[40]); // Sum(45) res[46] = fma52lo(res[46], a[6], a[40]); // Sum(46) res[47] = fma52hi(res[47], a[6], a[40]); // Sum(46) res[47] = fma52lo(res[47], a[7], a[40]); // Sum(47) res[48] = fma52hi(res[48], a[7], a[40]); // Sum(47) res[41] = fma52lo(res[41], a[0], a[41]); // Sum(41) res[42] = fma52hi(res[42], a[0], a[41]); // Sum(41) res[42] = fma52lo(res[42], a[1], a[41]); // Sum(42) res[43] = fma52hi(res[43], a[1], a[41]); // Sum(42) res[43] = fma52lo(res[43], a[2], a[41]); // Sum(43) res[44] = fma52hi(res[44], a[2], a[41]); // Sum(43) res[44] = fma52lo(res[44], a[3], a[41]); // Sum(44) res[45] = fma52hi(res[45], a[3], a[41]); // Sum(44) res[45] = fma52lo(res[45], a[4], a[41]); // Sum(45) res[46] = fma52hi(res[46], a[4], a[41]); // Sum(45) res[46] = fma52lo(res[46], a[5], a[41]); // Sum(46) res[47] = fma52hi(res[47], a[5], a[41]); // Sum(46) res[47] = fma52lo(res[47], a[6], a[41]); // Sum(47) res[48] = fma52hi(res[48], a[6], a[41]); // Sum(47) res[42] = fma52lo(res[42], a[0], a[42]); // Sum(42) res[43] = fma52hi(res[43], a[0], a[42]); // Sum(42) res[43] = fma52lo(res[43], a[1], a[42]); // Sum(43) res[44] = fma52hi(res[44], a[1], a[42]); // Sum(43) res[44] = fma52lo(res[44], a[2], a[42]); // Sum(44) res[45] = fma52hi(res[45], a[2], a[42]); // Sum(44) res[45] = fma52lo(res[45], a[3], a[42]); // Sum(45) res[46] = fma52hi(res[46], a[3], a[42]); // Sum(45) res[46] = fma52lo(res[46], a[4], a[42]); // Sum(46) res[47] = fma52hi(res[47], a[4], a[42]); // Sum(46) res[47] = fma52lo(res[47], a[5], a[42]); // Sum(47) res[48] = fma52hi(res[48], a[5], a[42]); // Sum(47) res[43] = fma52lo(res[43], a[0], a[43]); // Sum(43) res[44] = fma52hi(res[44], a[0], a[43]); // Sum(43) res[44] = fma52lo(res[44], a[1], a[43]); // Sum(44) res[45] = fma52hi(res[45], a[1], a[43]); // Sum(44) res[45] = fma52lo(res[45], a[2], a[43]); // Sum(45) res[46] = fma52hi(res[46], a[2], a[43]); // Sum(45) res[46] = fma52lo(res[46], a[3], a[43]); // Sum(46) res[47] = fma52hi(res[47], a[3], a[43]); // Sum(46) res[47] = fma52lo(res[47], a[4], a[43]); // Sum(47) res[48] = fma52hi(res[48], a[4], a[43]); // Sum(47) res[44] = fma52lo(res[44], a[0], a[44]); // Sum(44) res[45] = fma52hi(res[45], a[0], a[44]); // Sum(44) res[45] = fma52lo(res[45], a[1], a[44]); // Sum(45) res[46] = fma52hi(res[46], a[1], a[44]); // Sum(45) res[46] = fma52lo(res[46], a[2], a[44]); // Sum(46) res[47] = fma52hi(res[47], a[2], a[44]); // Sum(46) res[47] = fma52lo(res[47], a[3], a[44]); // Sum(47) res[48] = fma52hi(res[48], a[3], a[44]); // Sum(47) res[45] = fma52lo(res[45], a[0], a[45]); // Sum(45) res[46] = fma52hi(res[46], a[0], a[45]); // Sum(45) res[46] = fma52lo(res[46], a[1], a[45]); // Sum(46) res[47] = fma52hi(res[47], a[1], a[45]); // Sum(46) res[47] = fma52lo(res[47], a[2], a[45]); // Sum(47) res[48] = fma52hi(res[48], a[2], a[45]); // Sum(47) res[46] = fma52lo(res[46], a[0], a[46]); // Sum(46) res[47] = fma52hi(res[47], a[0], a[46]); // Sum(46) res[47] = fma52lo(res[47], a[1], a[46]); // Sum(47) res[48] = fma52hi(res[48], a[1], a[46]); // Sum(47) res[47] = fma52lo(res[47], a[0], a[47]); // Sum(47) res[48] = fma52hi(res[48], a[0], a[47]); // Sum(47) res[36] = add64(res[36], res[36]); // Double(36) res[37] = add64(res[37], res[37]); // Double(37) res[38] = add64(res[38], res[38]); // Double(38) res[39] = add64(res[39], res[39]); // Double(39) res[40] = add64(res[40], res[40]); // Double(40) res[41] = add64(res[41], res[41]); // Double(41) res[42] = add64(res[42], res[42]); // Double(42) res[43] = add64(res[43], res[43]); // Double(43) res[44] = add64(res[44], res[44]); // Double(44) res[45] = add64(res[45], res[45]); // Double(45) res[46] = add64(res[46], res[46]); // Double(46) res[47] = add64(res[47], res[47]); // Double(47) res[36] = fma52lo(res[36], a[18], a[18]); // Add sqr(36) res[37] = fma52hi(res[37], a[18], a[18]); // Add sqr(36) res[38] = fma52lo(res[38], a[19], a[19]); // Add sqr(38) res[39] = fma52hi(res[39], a[19], a[19]); // Add sqr(38) res[40] = fma52lo(res[40], a[20], a[20]); // Add sqr(40) res[41] = fma52hi(res[41], a[20], a[20]); // Add sqr(40) res[42] = fma52lo(res[42], a[21], a[21]); // Add sqr(42) res[43] = fma52hi(res[43], a[21], a[21]); // Add sqr(42) res[44] = fma52lo(res[44], a[22], a[22]); // Add sqr(44) res[45] = fma52hi(res[45], a[22], a[22]); // Add sqr(44) res[46] = fma52lo(res[46], a[23], a[23]); // Add sqr(46) res[47] = fma52hi(res[47], a[23], a[23]); // Add sqr(46) res[48] = fma52lo(res[48], a[23], a[25]); // Sum(48) res[49] = fma52hi(res[49], a[23], a[25]); // Sum(48) res[49] = fma52lo(res[49], a[24], a[25]); // Sum(49) res[50] = fma52hi(res[50], a[24], a[25]); // Sum(49) res[48] = fma52lo(res[48], a[22], a[26]); // Sum(48) res[49] = fma52hi(res[49], a[22], a[26]); // Sum(48) res[49] = fma52lo(res[49], a[23], a[26]); // Sum(49) res[50] = fma52hi(res[50], a[23], a[26]); // Sum(49) res[50] = fma52lo(res[50], a[24], a[26]); // Sum(50) res[51] = fma52hi(res[51], a[24], a[26]); // Sum(50) res[51] = fma52lo(res[51], a[25], a[26]); // Sum(51) res[52] = fma52hi(res[52], a[25], a[26]); // Sum(51) res[48] = fma52lo(res[48], a[21], a[27]); // Sum(48) res[49] = fma52hi(res[49], a[21], a[27]); // Sum(48) res[49] = fma52lo(res[49], a[22], a[27]); // Sum(49) res[50] = fma52hi(res[50], a[22], a[27]); // Sum(49) res[50] = fma52lo(res[50], a[23], a[27]); // Sum(50) res[51] = fma52hi(res[51], a[23], a[27]); // Sum(50) res[51] = fma52lo(res[51], a[24], a[27]); // Sum(51) res[52] = fma52hi(res[52], a[24], a[27]); // Sum(51) res[52] = fma52lo(res[52], a[25], a[27]); // Sum(52) res[53] = fma52hi(res[53], a[25], a[27]); // Sum(52) res[53] = fma52lo(res[53], a[26], a[27]); // Sum(53) res[54] = fma52hi(res[54], a[26], a[27]); // Sum(53) res[48] = fma52lo(res[48], a[20], a[28]); // Sum(48) res[49] = fma52hi(res[49], a[20], a[28]); // Sum(48) res[49] = fma52lo(res[49], a[21], a[28]); // Sum(49) res[50] = fma52hi(res[50], a[21], a[28]); // Sum(49) res[50] = fma52lo(res[50], a[22], a[28]); // Sum(50) res[51] = fma52hi(res[51], a[22], a[28]); // Sum(50) res[51] = fma52lo(res[51], a[23], a[28]); // Sum(51) res[52] = fma52hi(res[52], a[23], a[28]); // Sum(51) res[52] = fma52lo(res[52], a[24], a[28]); // Sum(52) res[53] = fma52hi(res[53], a[24], a[28]); // Sum(52) res[53] = fma52lo(res[53], a[25], a[28]); // Sum(53) res[54] = fma52hi(res[54], a[25], a[28]); // Sum(53) res[54] = fma52lo(res[54], a[26], a[28]); // Sum(54) res[55] = fma52hi(res[55], a[26], a[28]); // Sum(54) res[55] = fma52lo(res[55], a[27], a[28]); // Sum(55) res[56] = fma52hi(res[56], a[27], a[28]); // Sum(55) res[48] = fma52lo(res[48], a[19], a[29]); // Sum(48) res[49] = fma52hi(res[49], a[19], a[29]); // Sum(48) res[49] = fma52lo(res[49], a[20], a[29]); // Sum(49) res[50] = fma52hi(res[50], a[20], a[29]); // Sum(49) res[50] = fma52lo(res[50], a[21], a[29]); // Sum(50) res[51] = fma52hi(res[51], a[21], a[29]); // Sum(50) res[51] = fma52lo(res[51], a[22], a[29]); // Sum(51) res[52] = fma52hi(res[52], a[22], a[29]); // Sum(51) res[52] = fma52lo(res[52], a[23], a[29]); // Sum(52) res[53] = fma52hi(res[53], a[23], a[29]); // Sum(52) res[53] = fma52lo(res[53], a[24], a[29]); // Sum(53) res[54] = fma52hi(res[54], a[24], a[29]); // Sum(53) res[54] = fma52lo(res[54], a[25], a[29]); // Sum(54) res[55] = fma52hi(res[55], a[25], a[29]); // Sum(54) res[55] = fma52lo(res[55], a[26], a[29]); // Sum(55) res[56] = fma52hi(res[56], a[26], a[29]); // Sum(55) res[56] = fma52lo(res[56], a[27], a[29]); // Sum(56) res[57] = fma52hi(res[57], a[27], a[29]); // Sum(56) res[57] = fma52lo(res[57], a[28], a[29]); // Sum(57) res[58] = fma52hi(res[58], a[28], a[29]); // Sum(57) res[48] = fma52lo(res[48], a[18], a[30]); // Sum(48) res[49] = fma52hi(res[49], a[18], a[30]); // Sum(48) res[49] = fma52lo(res[49], a[19], a[30]); // Sum(49) res[50] = fma52hi(res[50], a[19], a[30]); // Sum(49) res[50] = fma52lo(res[50], a[20], a[30]); // Sum(50) res[51] = fma52hi(res[51], a[20], a[30]); // Sum(50) res[51] = fma52lo(res[51], a[21], a[30]); // Sum(51) res[52] = fma52hi(res[52], a[21], a[30]); // Sum(51) res[52] = fma52lo(res[52], a[22], a[30]); // Sum(52) res[53] = fma52hi(res[53], a[22], a[30]); // Sum(52) res[53] = fma52lo(res[53], a[23], a[30]); // Sum(53) res[54] = fma52hi(res[54], a[23], a[30]); // Sum(53) res[54] = fma52lo(res[54], a[24], a[30]); // Sum(54) res[55] = fma52hi(res[55], a[24], a[30]); // Sum(54) res[55] = fma52lo(res[55], a[25], a[30]); // Sum(55) res[56] = fma52hi(res[56], a[25], a[30]); // Sum(55) res[56] = fma52lo(res[56], a[26], a[30]); // Sum(56) res[57] = fma52hi(res[57], a[26], a[30]); // Sum(56) res[57] = fma52lo(res[57], a[27], a[30]); // Sum(57) res[58] = fma52hi(res[58], a[27], a[30]); // Sum(57) res[58] = fma52lo(res[58], a[28], a[30]); // Sum(58) res[59] = fma52hi(res[59], a[28], a[30]); // Sum(58) res[59] = fma52lo(res[59], a[29], a[30]); // Sum(59) res[60] = fma52hi(res[60], a[29], a[30]); // Sum(59) res[48] = fma52lo(res[48], a[17], a[31]); // Sum(48) res[49] = fma52hi(res[49], a[17], a[31]); // Sum(48) res[49] = fma52lo(res[49], a[18], a[31]); // Sum(49) res[50] = fma52hi(res[50], a[18], a[31]); // Sum(49) res[50] = fma52lo(res[50], a[19], a[31]); // Sum(50) res[51] = fma52hi(res[51], a[19], a[31]); // Sum(50) res[51] = fma52lo(res[51], a[20], a[31]); // Sum(51) res[52] = fma52hi(res[52], a[20], a[31]); // Sum(51) res[52] = fma52lo(res[52], a[21], a[31]); // Sum(52) res[53] = fma52hi(res[53], a[21], a[31]); // Sum(52) res[53] = fma52lo(res[53], a[22], a[31]); // Sum(53) res[54] = fma52hi(res[54], a[22], a[31]); // Sum(53) res[54] = fma52lo(res[54], a[23], a[31]); // Sum(54) res[55] = fma52hi(res[55], a[23], a[31]); // Sum(54) res[55] = fma52lo(res[55], a[24], a[31]); // Sum(55) res[56] = fma52hi(res[56], a[24], a[31]); // Sum(55) res[56] = fma52lo(res[56], a[25], a[31]); // Sum(56) res[57] = fma52hi(res[57], a[25], a[31]); // Sum(56) res[57] = fma52lo(res[57], a[26], a[31]); // Sum(57) res[58] = fma52hi(res[58], a[26], a[31]); // Sum(57) res[58] = fma52lo(res[58], a[27], a[31]); // Sum(58) res[59] = fma52hi(res[59], a[27], a[31]); // Sum(58) res[59] = fma52lo(res[59], a[28], a[31]); // Sum(59) res[60] = fma52hi(res[60], a[28], a[31]); // Sum(59) res[48] = fma52lo(res[48], a[16], a[32]); // Sum(48) res[49] = fma52hi(res[49], a[16], a[32]); // Sum(48) res[49] = fma52lo(res[49], a[17], a[32]); // Sum(49) res[50] = fma52hi(res[50], a[17], a[32]); // Sum(49) res[50] = fma52lo(res[50], a[18], a[32]); // Sum(50) res[51] = fma52hi(res[51], a[18], a[32]); // Sum(50) res[51] = fma52lo(res[51], a[19], a[32]); // Sum(51) res[52] = fma52hi(res[52], a[19], a[32]); // Sum(51) res[52] = fma52lo(res[52], a[20], a[32]); // Sum(52) res[53] = fma52hi(res[53], a[20], a[32]); // Sum(52) res[53] = fma52lo(res[53], a[21], a[32]); // Sum(53) res[54] = fma52hi(res[54], a[21], a[32]); // Sum(53) res[54] = fma52lo(res[54], a[22], a[32]); // Sum(54) res[55] = fma52hi(res[55], a[22], a[32]); // Sum(54) res[55] = fma52lo(res[55], a[23], a[32]); // Sum(55) res[56] = fma52hi(res[56], a[23], a[32]); // Sum(55) res[56] = fma52lo(res[56], a[24], a[32]); // Sum(56) res[57] = fma52hi(res[57], a[24], a[32]); // Sum(56) res[57] = fma52lo(res[57], a[25], a[32]); // Sum(57) res[58] = fma52hi(res[58], a[25], a[32]); // Sum(57) res[58] = fma52lo(res[58], a[26], a[32]); // Sum(58) res[59] = fma52hi(res[59], a[26], a[32]); // Sum(58) res[59] = fma52lo(res[59], a[27], a[32]); // Sum(59) res[60] = fma52hi(res[60], a[27], a[32]); // Sum(59) res[48] = fma52lo(res[48], a[15], a[33]); // Sum(48) res[49] = fma52hi(res[49], a[15], a[33]); // Sum(48) res[49] = fma52lo(res[49], a[16], a[33]); // Sum(49) res[50] = fma52hi(res[50], a[16], a[33]); // Sum(49) res[50] = fma52lo(res[50], a[17], a[33]); // Sum(50) res[51] = fma52hi(res[51], a[17], a[33]); // Sum(50) res[51] = fma52lo(res[51], a[18], a[33]); // Sum(51) res[52] = fma52hi(res[52], a[18], a[33]); // Sum(51) res[52] = fma52lo(res[52], a[19], a[33]); // Sum(52) res[53] = fma52hi(res[53], a[19], a[33]); // Sum(52) res[53] = fma52lo(res[53], a[20], a[33]); // Sum(53) res[54] = fma52hi(res[54], a[20], a[33]); // Sum(53) res[54] = fma52lo(res[54], a[21], a[33]); // Sum(54) res[55] = fma52hi(res[55], a[21], a[33]); // Sum(54) res[55] = fma52lo(res[55], a[22], a[33]); // Sum(55) res[56] = fma52hi(res[56], a[22], a[33]); // Sum(55) res[56] = fma52lo(res[56], a[23], a[33]); // Sum(56) res[57] = fma52hi(res[57], a[23], a[33]); // Sum(56) res[57] = fma52lo(res[57], a[24], a[33]); // Sum(57) res[58] = fma52hi(res[58], a[24], a[33]); // Sum(57) res[58] = fma52lo(res[58], a[25], a[33]); // Sum(58) res[59] = fma52hi(res[59], a[25], a[33]); // Sum(58) res[59] = fma52lo(res[59], a[26], a[33]); // Sum(59) res[60] = fma52hi(res[60], a[26], a[33]); // Sum(59) res[48] = fma52lo(res[48], a[14], a[34]); // Sum(48) res[49] = fma52hi(res[49], a[14], a[34]); // Sum(48) res[49] = fma52lo(res[49], a[15], a[34]); // Sum(49) res[50] = fma52hi(res[50], a[15], a[34]); // Sum(49) res[50] = fma52lo(res[50], a[16], a[34]); // Sum(50) res[51] = fma52hi(res[51], a[16], a[34]); // Sum(50) res[51] = fma52lo(res[51], a[17], a[34]); // Sum(51) res[52] = fma52hi(res[52], a[17], a[34]); // Sum(51) res[52] = fma52lo(res[52], a[18], a[34]); // Sum(52) res[53] = fma52hi(res[53], a[18], a[34]); // Sum(52) res[53] = fma52lo(res[53], a[19], a[34]); // Sum(53) res[54] = fma52hi(res[54], a[19], a[34]); // Sum(53) res[54] = fma52lo(res[54], a[20], a[34]); // Sum(54) res[55] = fma52hi(res[55], a[20], a[34]); // Sum(54) res[55] = fma52lo(res[55], a[21], a[34]); // Sum(55) res[56] = fma52hi(res[56], a[21], a[34]); // Sum(55) res[56] = fma52lo(res[56], a[22], a[34]); // Sum(56) res[57] = fma52hi(res[57], a[22], a[34]); // Sum(56) res[57] = fma52lo(res[57], a[23], a[34]); // Sum(57) res[58] = fma52hi(res[58], a[23], a[34]); // Sum(57) res[58] = fma52lo(res[58], a[24], a[34]); // Sum(58) res[59] = fma52hi(res[59], a[24], a[34]); // Sum(58) res[59] = fma52lo(res[59], a[25], a[34]); // Sum(59) res[60] = fma52hi(res[60], a[25], a[34]); // Sum(59) res[48] = fma52lo(res[48], a[13], a[35]); // Sum(48) res[49] = fma52hi(res[49], a[13], a[35]); // Sum(48) res[49] = fma52lo(res[49], a[14], a[35]); // Sum(49) res[50] = fma52hi(res[50], a[14], a[35]); // Sum(49) res[50] = fma52lo(res[50], a[15], a[35]); // Sum(50) res[51] = fma52hi(res[51], a[15], a[35]); // Sum(50) res[51] = fma52lo(res[51], a[16], a[35]); // Sum(51) res[52] = fma52hi(res[52], a[16], a[35]); // Sum(51) res[52] = fma52lo(res[52], a[17], a[35]); // Sum(52) res[53] = fma52hi(res[53], a[17], a[35]); // Sum(52) res[53] = fma52lo(res[53], a[18], a[35]); // Sum(53) res[54] = fma52hi(res[54], a[18], a[35]); // Sum(53) res[54] = fma52lo(res[54], a[19], a[35]); // Sum(54) res[55] = fma52hi(res[55], a[19], a[35]); // Sum(54) res[55] = fma52lo(res[55], a[20], a[35]); // Sum(55) res[56] = fma52hi(res[56], a[20], a[35]); // Sum(55) res[56] = fma52lo(res[56], a[21], a[35]); // Sum(56) res[57] = fma52hi(res[57], a[21], a[35]); // Sum(56) res[57] = fma52lo(res[57], a[22], a[35]); // Sum(57) res[58] = fma52hi(res[58], a[22], a[35]); // Sum(57) res[58] = fma52lo(res[58], a[23], a[35]); // Sum(58) res[59] = fma52hi(res[59], a[23], a[35]); // Sum(58) res[59] = fma52lo(res[59], a[24], a[35]); // Sum(59) res[60] = fma52hi(res[60], a[24], a[35]); // Sum(59) res[48] = fma52lo(res[48], a[12], a[36]); // Sum(48) res[49] = fma52hi(res[49], a[12], a[36]); // Sum(48) res[49] = fma52lo(res[49], a[13], a[36]); // Sum(49) res[50] = fma52hi(res[50], a[13], a[36]); // Sum(49) res[50] = fma52lo(res[50], a[14], a[36]); // Sum(50) res[51] = fma52hi(res[51], a[14], a[36]); // Sum(50) res[51] = fma52lo(res[51], a[15], a[36]); // Sum(51) res[52] = fma52hi(res[52], a[15], a[36]); // Sum(51) res[52] = fma52lo(res[52], a[16], a[36]); // Sum(52) res[53] = fma52hi(res[53], a[16], a[36]); // Sum(52) res[53] = fma52lo(res[53], a[17], a[36]); // Sum(53) res[54] = fma52hi(res[54], a[17], a[36]); // Sum(53) res[54] = fma52lo(res[54], a[18], a[36]); // Sum(54) res[55] = fma52hi(res[55], a[18], a[36]); // Sum(54) res[55] = fma52lo(res[55], a[19], a[36]); // Sum(55) res[56] = fma52hi(res[56], a[19], a[36]); // Sum(55) res[56] = fma52lo(res[56], a[20], a[36]); // Sum(56) res[57] = fma52hi(res[57], a[20], a[36]); // Sum(56) res[57] = fma52lo(res[57], a[21], a[36]); // Sum(57) res[58] = fma52hi(res[58], a[21], a[36]); // Sum(57) res[58] = fma52lo(res[58], a[22], a[36]); // Sum(58) res[59] = fma52hi(res[59], a[22], a[36]); // Sum(58) res[59] = fma52lo(res[59], a[23], a[36]); // Sum(59) res[60] = fma52hi(res[60], a[23], a[36]); // Sum(59) res[48] = fma52lo(res[48], a[11], a[37]); // Sum(48) res[49] = fma52hi(res[49], a[11], a[37]); // Sum(48) res[49] = fma52lo(res[49], a[12], a[37]); // Sum(49) res[50] = fma52hi(res[50], a[12], a[37]); // Sum(49) res[50] = fma52lo(res[50], a[13], a[37]); // Sum(50) res[51] = fma52hi(res[51], a[13], a[37]); // Sum(50) res[51] = fma52lo(res[51], a[14], a[37]); // Sum(51) res[52] = fma52hi(res[52], a[14], a[37]); // Sum(51) res[52] = fma52lo(res[52], a[15], a[37]); // Sum(52) res[53] = fma52hi(res[53], a[15], a[37]); // Sum(52) res[53] = fma52lo(res[53], a[16], a[37]); // Sum(53) res[54] = fma52hi(res[54], a[16], a[37]); // Sum(53) res[54] = fma52lo(res[54], a[17], a[37]); // Sum(54) res[55] = fma52hi(res[55], a[17], a[37]); // Sum(54) res[55] = fma52lo(res[55], a[18], a[37]); // Sum(55) res[56] = fma52hi(res[56], a[18], a[37]); // Sum(55) res[56] = fma52lo(res[56], a[19], a[37]); // Sum(56) res[57] = fma52hi(res[57], a[19], a[37]); // Sum(56) res[57] = fma52lo(res[57], a[20], a[37]); // Sum(57) res[58] = fma52hi(res[58], a[20], a[37]); // Sum(57) res[58] = fma52lo(res[58], a[21], a[37]); // Sum(58) res[59] = fma52hi(res[59], a[21], a[37]); // Sum(58) res[59] = fma52lo(res[59], a[22], a[37]); // Sum(59) res[60] = fma52hi(res[60], a[22], a[37]); // Sum(59) res[48] = fma52lo(res[48], a[10], a[38]); // Sum(48) res[49] = fma52hi(res[49], a[10], a[38]); // Sum(48) res[49] = fma52lo(res[49], a[11], a[38]); // Sum(49) res[50] = fma52hi(res[50], a[11], a[38]); // Sum(49) res[50] = fma52lo(res[50], a[12], a[38]); // Sum(50) res[51] = fma52hi(res[51], a[12], a[38]); // Sum(50) res[51] = fma52lo(res[51], a[13], a[38]); // Sum(51) res[52] = fma52hi(res[52], a[13], a[38]); // Sum(51) res[52] = fma52lo(res[52], a[14], a[38]); // Sum(52) res[53] = fma52hi(res[53], a[14], a[38]); // Sum(52) res[53] = fma52lo(res[53], a[15], a[38]); // Sum(53) res[54] = fma52hi(res[54], a[15], a[38]); // Sum(53) res[54] = fma52lo(res[54], a[16], a[38]); // Sum(54) res[55] = fma52hi(res[55], a[16], a[38]); // Sum(54) res[55] = fma52lo(res[55], a[17], a[38]); // Sum(55) res[56] = fma52hi(res[56], a[17], a[38]); // Sum(55) res[56] = fma52lo(res[56], a[18], a[38]); // Sum(56) res[57] = fma52hi(res[57], a[18], a[38]); // Sum(56) res[57] = fma52lo(res[57], a[19], a[38]); // Sum(57) res[58] = fma52hi(res[58], a[19], a[38]); // Sum(57) res[58] = fma52lo(res[58], a[20], a[38]); // Sum(58) res[59] = fma52hi(res[59], a[20], a[38]); // Sum(58) res[59] = fma52lo(res[59], a[21], a[38]); // Sum(59) res[60] = fma52hi(res[60], a[21], a[38]); // Sum(59) res[48] = fma52lo(res[48], a[9], a[39]); // Sum(48) res[49] = fma52hi(res[49], a[9], a[39]); // Sum(48) res[49] = fma52lo(res[49], a[10], a[39]); // Sum(49) res[50] = fma52hi(res[50], a[10], a[39]); // Sum(49) res[50] = fma52lo(res[50], a[11], a[39]); // Sum(50) res[51] = fma52hi(res[51], a[11], a[39]); // Sum(50) res[51] = fma52lo(res[51], a[12], a[39]); // Sum(51) res[52] = fma52hi(res[52], a[12], a[39]); // Sum(51) res[52] = fma52lo(res[52], a[13], a[39]); // Sum(52) res[53] = fma52hi(res[53], a[13], a[39]); // Sum(52) res[53] = fma52lo(res[53], a[14], a[39]); // Sum(53) res[54] = fma52hi(res[54], a[14], a[39]); // Sum(53) res[54] = fma52lo(res[54], a[15], a[39]); // Sum(54) res[55] = fma52hi(res[55], a[15], a[39]); // Sum(54) res[55] = fma52lo(res[55], a[16], a[39]); // Sum(55) res[56] = fma52hi(res[56], a[16], a[39]); // Sum(55) res[56] = fma52lo(res[56], a[17], a[39]); // Sum(56) res[57] = fma52hi(res[57], a[17], a[39]); // Sum(56) res[57] = fma52lo(res[57], a[18], a[39]); // Sum(57) res[58] = fma52hi(res[58], a[18], a[39]); // Sum(57) res[58] = fma52lo(res[58], a[19], a[39]); // Sum(58) res[59] = fma52hi(res[59], a[19], a[39]); // Sum(58) res[59] = fma52lo(res[59], a[20], a[39]); // Sum(59) res[60] = fma52hi(res[60], a[20], a[39]); // Sum(59) res[48] = fma52lo(res[48], a[8], a[40]); // Sum(48) res[49] = fma52hi(res[49], a[8], a[40]); // Sum(48) res[49] = fma52lo(res[49], a[9], a[40]); // Sum(49) res[50] = fma52hi(res[50], a[9], a[40]); // Sum(49) res[50] = fma52lo(res[50], a[10], a[40]); // Sum(50) res[51] = fma52hi(res[51], a[10], a[40]); // Sum(50) res[51] = fma52lo(res[51], a[11], a[40]); // Sum(51) res[52] = fma52hi(res[52], a[11], a[40]); // Sum(51) res[52] = fma52lo(res[52], a[12], a[40]); // Sum(52) res[53] = fma52hi(res[53], a[12], a[40]); // Sum(52) res[53] = fma52lo(res[53], a[13], a[40]); // Sum(53) res[54] = fma52hi(res[54], a[13], a[40]); // Sum(53) res[54] = fma52lo(res[54], a[14], a[40]); // Sum(54) res[55] = fma52hi(res[55], a[14], a[40]); // Sum(54) res[55] = fma52lo(res[55], a[15], a[40]); // Sum(55) res[56] = fma52hi(res[56], a[15], a[40]); // Sum(55) res[56] = fma52lo(res[56], a[16], a[40]); // Sum(56) res[57] = fma52hi(res[57], a[16], a[40]); // Sum(56) res[57] = fma52lo(res[57], a[17], a[40]); // Sum(57) res[58] = fma52hi(res[58], a[17], a[40]); // Sum(57) res[58] = fma52lo(res[58], a[18], a[40]); // Sum(58) res[59] = fma52hi(res[59], a[18], a[40]); // Sum(58) res[59] = fma52lo(res[59], a[19], a[40]); // Sum(59) res[60] = fma52hi(res[60], a[19], a[40]); // Sum(59) res[48] = fma52lo(res[48], a[7], a[41]); // Sum(48) res[49] = fma52hi(res[49], a[7], a[41]); // Sum(48) res[49] = fma52lo(res[49], a[8], a[41]); // Sum(49) res[50] = fma52hi(res[50], a[8], a[41]); // Sum(49) res[50] = fma52lo(res[50], a[9], a[41]); // Sum(50) res[51] = fma52hi(res[51], a[9], a[41]); // Sum(50) res[51] = fma52lo(res[51], a[10], a[41]); // Sum(51) res[52] = fma52hi(res[52], a[10], a[41]); // Sum(51) res[52] = fma52lo(res[52], a[11], a[41]); // Sum(52) res[53] = fma52hi(res[53], a[11], a[41]); // Sum(52) res[53] = fma52lo(res[53], a[12], a[41]); // Sum(53) res[54] = fma52hi(res[54], a[12], a[41]); // Sum(53) res[54] = fma52lo(res[54], a[13], a[41]); // Sum(54) res[55] = fma52hi(res[55], a[13], a[41]); // Sum(54) res[55] = fma52lo(res[55], a[14], a[41]); // Sum(55) res[56] = fma52hi(res[56], a[14], a[41]); // Sum(55) res[56] = fma52lo(res[56], a[15], a[41]); // Sum(56) res[57] = fma52hi(res[57], a[15], a[41]); // Sum(56) res[57] = fma52lo(res[57], a[16], a[41]); // Sum(57) res[58] = fma52hi(res[58], a[16], a[41]); // Sum(57) res[58] = fma52lo(res[58], a[17], a[41]); // Sum(58) res[59] = fma52hi(res[59], a[17], a[41]); // Sum(58) res[59] = fma52lo(res[59], a[18], a[41]); // Sum(59) res[60] = fma52hi(res[60], a[18], a[41]); // Sum(59) res[48] = fma52lo(res[48], a[6], a[42]); // Sum(48) res[49] = fma52hi(res[49], a[6], a[42]); // Sum(48) res[49] = fma52lo(res[49], a[7], a[42]); // Sum(49) res[50] = fma52hi(res[50], a[7], a[42]); // Sum(49) res[50] = fma52lo(res[50], a[8], a[42]); // Sum(50) res[51] = fma52hi(res[51], a[8], a[42]); // Sum(50) res[51] = fma52lo(res[51], a[9], a[42]); // Sum(51) res[52] = fma52hi(res[52], a[9], a[42]); // Sum(51) res[52] = fma52lo(res[52], a[10], a[42]); // Sum(52) res[53] = fma52hi(res[53], a[10], a[42]); // Sum(52) res[53] = fma52lo(res[53], a[11], a[42]); // Sum(53) res[54] = fma52hi(res[54], a[11], a[42]); // Sum(53) res[54] = fma52lo(res[54], a[12], a[42]); // Sum(54) res[55] = fma52hi(res[55], a[12], a[42]); // Sum(54) res[55] = fma52lo(res[55], a[13], a[42]); // Sum(55) res[56] = fma52hi(res[56], a[13], a[42]); // Sum(55) res[56] = fma52lo(res[56], a[14], a[42]); // Sum(56) res[57] = fma52hi(res[57], a[14], a[42]); // Sum(56) res[57] = fma52lo(res[57], a[15], a[42]); // Sum(57) res[58] = fma52hi(res[58], a[15], a[42]); // Sum(57) res[58] = fma52lo(res[58], a[16], a[42]); // Sum(58) res[59] = fma52hi(res[59], a[16], a[42]); // Sum(58) res[59] = fma52lo(res[59], a[17], a[42]); // Sum(59) res[60] = fma52hi(res[60], a[17], a[42]); // Sum(59) res[48] = fma52lo(res[48], a[5], a[43]); // Sum(48) res[49] = fma52hi(res[49], a[5], a[43]); // Sum(48) res[49] = fma52lo(res[49], a[6], a[43]); // Sum(49) res[50] = fma52hi(res[50], a[6], a[43]); // Sum(49) res[50] = fma52lo(res[50], a[7], a[43]); // Sum(50) res[51] = fma52hi(res[51], a[7], a[43]); // Sum(50) res[51] = fma52lo(res[51], a[8], a[43]); // Sum(51) res[52] = fma52hi(res[52], a[8], a[43]); // Sum(51) res[52] = fma52lo(res[52], a[9], a[43]); // Sum(52) res[53] = fma52hi(res[53], a[9], a[43]); // Sum(52) res[53] = fma52lo(res[53], a[10], a[43]); // Sum(53) res[54] = fma52hi(res[54], a[10], a[43]); // Sum(53) res[54] = fma52lo(res[54], a[11], a[43]); // Sum(54) res[55] = fma52hi(res[55], a[11], a[43]); // Sum(54) res[55] = fma52lo(res[55], a[12], a[43]); // Sum(55) res[56] = fma52hi(res[56], a[12], a[43]); // Sum(55) res[56] = fma52lo(res[56], a[13], a[43]); // Sum(56) res[57] = fma52hi(res[57], a[13], a[43]); // Sum(56) res[57] = fma52lo(res[57], a[14], a[43]); // Sum(57) res[58] = fma52hi(res[58], a[14], a[43]); // Sum(57) res[58] = fma52lo(res[58], a[15], a[43]); // Sum(58) res[59] = fma52hi(res[59], a[15], a[43]); // Sum(58) res[59] = fma52lo(res[59], a[16], a[43]); // Sum(59) res[60] = fma52hi(res[60], a[16], a[43]); // Sum(59) res[48] = fma52lo(res[48], a[4], a[44]); // Sum(48) res[49] = fma52hi(res[49], a[4], a[44]); // Sum(48) res[49] = fma52lo(res[49], a[5], a[44]); // Sum(49) res[50] = fma52hi(res[50], a[5], a[44]); // Sum(49) res[50] = fma52lo(res[50], a[6], a[44]); // Sum(50) res[51] = fma52hi(res[51], a[6], a[44]); // Sum(50) res[51] = fma52lo(res[51], a[7], a[44]); // Sum(51) res[52] = fma52hi(res[52], a[7], a[44]); // Sum(51) res[52] = fma52lo(res[52], a[8], a[44]); // Sum(52) res[53] = fma52hi(res[53], a[8], a[44]); // Sum(52) res[53] = fma52lo(res[53], a[9], a[44]); // Sum(53) res[54] = fma52hi(res[54], a[9], a[44]); // Sum(53) res[54] = fma52lo(res[54], a[10], a[44]); // Sum(54) res[55] = fma52hi(res[55], a[10], a[44]); // Sum(54) res[55] = fma52lo(res[55], a[11], a[44]); // Sum(55) res[56] = fma52hi(res[56], a[11], a[44]); // Sum(55) res[56] = fma52lo(res[56], a[12], a[44]); // Sum(56) res[57] = fma52hi(res[57], a[12], a[44]); // Sum(56) res[57] = fma52lo(res[57], a[13], a[44]); // Sum(57) res[58] = fma52hi(res[58], a[13], a[44]); // Sum(57) res[58] = fma52lo(res[58], a[14], a[44]); // Sum(58) res[59] = fma52hi(res[59], a[14], a[44]); // Sum(58) res[59] = fma52lo(res[59], a[15], a[44]); // Sum(59) res[60] = fma52hi(res[60], a[15], a[44]); // Sum(59) res[48] = fma52lo(res[48], a[3], a[45]); // Sum(48) res[49] = fma52hi(res[49], a[3], a[45]); // Sum(48) res[49] = fma52lo(res[49], a[4], a[45]); // Sum(49) res[50] = fma52hi(res[50], a[4], a[45]); // Sum(49) res[50] = fma52lo(res[50], a[5], a[45]); // Sum(50) res[51] = fma52hi(res[51], a[5], a[45]); // Sum(50) res[51] = fma52lo(res[51], a[6], a[45]); // Sum(51) res[52] = fma52hi(res[52], a[6], a[45]); // Sum(51) res[52] = fma52lo(res[52], a[7], a[45]); // Sum(52) res[53] = fma52hi(res[53], a[7], a[45]); // Sum(52) res[53] = fma52lo(res[53], a[8], a[45]); // Sum(53) res[54] = fma52hi(res[54], a[8], a[45]); // Sum(53) res[54] = fma52lo(res[54], a[9], a[45]); // Sum(54) res[55] = fma52hi(res[55], a[9], a[45]); // Sum(54) res[55] = fma52lo(res[55], a[10], a[45]); // Sum(55) res[56] = fma52hi(res[56], a[10], a[45]); // Sum(55) res[56] = fma52lo(res[56], a[11], a[45]); // Sum(56) res[57] = fma52hi(res[57], a[11], a[45]); // Sum(56) res[57] = fma52lo(res[57], a[12], a[45]); // Sum(57) res[58] = fma52hi(res[58], a[12], a[45]); // Sum(57) res[58] = fma52lo(res[58], a[13], a[45]); // Sum(58) res[59] = fma52hi(res[59], a[13], a[45]); // Sum(58) res[59] = fma52lo(res[59], a[14], a[45]); // Sum(59) res[60] = fma52hi(res[60], a[14], a[45]); // Sum(59) res[48] = fma52lo(res[48], a[2], a[46]); // Sum(48) res[49] = fma52hi(res[49], a[2], a[46]); // Sum(48) res[49] = fma52lo(res[49], a[3], a[46]); // Sum(49) res[50] = fma52hi(res[50], a[3], a[46]); // Sum(49) res[50] = fma52lo(res[50], a[4], a[46]); // Sum(50) res[51] = fma52hi(res[51], a[4], a[46]); // Sum(50) res[51] = fma52lo(res[51], a[5], a[46]); // Sum(51) res[52] = fma52hi(res[52], a[5], a[46]); // Sum(51) res[52] = fma52lo(res[52], a[6], a[46]); // Sum(52) res[53] = fma52hi(res[53], a[6], a[46]); // Sum(52) res[53] = fma52lo(res[53], a[7], a[46]); // Sum(53) res[54] = fma52hi(res[54], a[7], a[46]); // Sum(53) res[54] = fma52lo(res[54], a[8], a[46]); // Sum(54) res[55] = fma52hi(res[55], a[8], a[46]); // Sum(54) res[55] = fma52lo(res[55], a[9], a[46]); // Sum(55) res[56] = fma52hi(res[56], a[9], a[46]); // Sum(55) res[56] = fma52lo(res[56], a[10], a[46]); // Sum(56) res[57] = fma52hi(res[57], a[10], a[46]); // Sum(56) res[57] = fma52lo(res[57], a[11], a[46]); // Sum(57) res[58] = fma52hi(res[58], a[11], a[46]); // Sum(57) res[58] = fma52lo(res[58], a[12], a[46]); // Sum(58) res[59] = fma52hi(res[59], a[12], a[46]); // Sum(58) res[59] = fma52lo(res[59], a[13], a[46]); // Sum(59) res[60] = fma52hi(res[60], a[13], a[46]); // Sum(59) res[48] = fma52lo(res[48], a[1], a[47]); // Sum(48) res[49] = fma52hi(res[49], a[1], a[47]); // Sum(48) res[49] = fma52lo(res[49], a[2], a[47]); // Sum(49) res[50] = fma52hi(res[50], a[2], a[47]); // Sum(49) res[50] = fma52lo(res[50], a[3], a[47]); // Sum(50) res[51] = fma52hi(res[51], a[3], a[47]); // Sum(50) res[51] = fma52lo(res[51], a[4], a[47]); // Sum(51) res[52] = fma52hi(res[52], a[4], a[47]); // Sum(51) res[52] = fma52lo(res[52], a[5], a[47]); // Sum(52) res[53] = fma52hi(res[53], a[5], a[47]); // Sum(52) res[53] = fma52lo(res[53], a[6], a[47]); // Sum(53) res[54] = fma52hi(res[54], a[6], a[47]); // Sum(53) res[54] = fma52lo(res[54], a[7], a[47]); // Sum(54) res[55] = fma52hi(res[55], a[7], a[47]); // Sum(54) res[55] = fma52lo(res[55], a[8], a[47]); // Sum(55) res[56] = fma52hi(res[56], a[8], a[47]); // Sum(55) res[56] = fma52lo(res[56], a[9], a[47]); // Sum(56) res[57] = fma52hi(res[57], a[9], a[47]); // Sum(56) res[57] = fma52lo(res[57], a[10], a[47]); // Sum(57) res[58] = fma52hi(res[58], a[10], a[47]); // Sum(57) res[58] = fma52lo(res[58], a[11], a[47]); // Sum(58) res[59] = fma52hi(res[59], a[11], a[47]); // Sum(58) res[59] = fma52lo(res[59], a[12], a[47]); // Sum(59) res[60] = fma52hi(res[60], a[12], a[47]); // Sum(59) res[48] = fma52lo(res[48], a[0], a[48]); // Sum(48) res[49] = fma52hi(res[49], a[0], a[48]); // Sum(48) res[49] = fma52lo(res[49], a[1], a[48]); // Sum(49) res[50] = fma52hi(res[50], a[1], a[48]); // Sum(49) res[50] = fma52lo(res[50], a[2], a[48]); // Sum(50) res[51] = fma52hi(res[51], a[2], a[48]); // Sum(50) res[51] = fma52lo(res[51], a[3], a[48]); // Sum(51) res[52] = fma52hi(res[52], a[3], a[48]); // Sum(51) res[52] = fma52lo(res[52], a[4], a[48]); // Sum(52) res[53] = fma52hi(res[53], a[4], a[48]); // Sum(52) res[53] = fma52lo(res[53], a[5], a[48]); // Sum(53) res[54] = fma52hi(res[54], a[5], a[48]); // Sum(53) res[54] = fma52lo(res[54], a[6], a[48]); // Sum(54) res[55] = fma52hi(res[55], a[6], a[48]); // Sum(54) res[55] = fma52lo(res[55], a[7], a[48]); // Sum(55) res[56] = fma52hi(res[56], a[7], a[48]); // Sum(55) res[56] = fma52lo(res[56], a[8], a[48]); // Sum(56) res[57] = fma52hi(res[57], a[8], a[48]); // Sum(56) res[57] = fma52lo(res[57], a[9], a[48]); // Sum(57) res[58] = fma52hi(res[58], a[9], a[48]); // Sum(57) res[58] = fma52lo(res[58], a[10], a[48]); // Sum(58) res[59] = fma52hi(res[59], a[10], a[48]); // Sum(58) res[59] = fma52lo(res[59], a[11], a[48]); // Sum(59) res[60] = fma52hi(res[60], a[11], a[48]); // Sum(59) res[49] = fma52lo(res[49], a[0], a[49]); // Sum(49) res[50] = fma52hi(res[50], a[0], a[49]); // Sum(49) res[50] = fma52lo(res[50], a[1], a[49]); // Sum(50) res[51] = fma52hi(res[51], a[1], a[49]); // Sum(50) res[51] = fma52lo(res[51], a[2], a[49]); // Sum(51) res[52] = fma52hi(res[52], a[2], a[49]); // Sum(51) res[52] = fma52lo(res[52], a[3], a[49]); // Sum(52) res[53] = fma52hi(res[53], a[3], a[49]); // Sum(52) res[53] = fma52lo(res[53], a[4], a[49]); // Sum(53) res[54] = fma52hi(res[54], a[4], a[49]); // Sum(53) res[54] = fma52lo(res[54], a[5], a[49]); // Sum(54) res[55] = fma52hi(res[55], a[5], a[49]); // Sum(54) res[55] = fma52lo(res[55], a[6], a[49]); // Sum(55) res[56] = fma52hi(res[56], a[6], a[49]); // Sum(55) res[56] = fma52lo(res[56], a[7], a[49]); // Sum(56) res[57] = fma52hi(res[57], a[7], a[49]); // Sum(56) res[57] = fma52lo(res[57], a[8], a[49]); // Sum(57) res[58] = fma52hi(res[58], a[8], a[49]); // Sum(57) res[58] = fma52lo(res[58], a[9], a[49]); // Sum(58) res[59] = fma52hi(res[59], a[9], a[49]); // Sum(58) res[59] = fma52lo(res[59], a[10], a[49]); // Sum(59) res[60] = fma52hi(res[60], a[10], a[49]); // Sum(59) res[50] = fma52lo(res[50], a[0], a[50]); // Sum(50) res[51] = fma52hi(res[51], a[0], a[50]); // Sum(50) res[51] = fma52lo(res[51], a[1], a[50]); // Sum(51) res[52] = fma52hi(res[52], a[1], a[50]); // Sum(51) res[52] = fma52lo(res[52], a[2], a[50]); // Sum(52) res[53] = fma52hi(res[53], a[2], a[50]); // Sum(52) res[53] = fma52lo(res[53], a[3], a[50]); // Sum(53) res[54] = fma52hi(res[54], a[3], a[50]); // Sum(53) res[54] = fma52lo(res[54], a[4], a[50]); // Sum(54) res[55] = fma52hi(res[55], a[4], a[50]); // Sum(54) res[55] = fma52lo(res[55], a[5], a[50]); // Sum(55) res[56] = fma52hi(res[56], a[5], a[50]); // Sum(55) res[56] = fma52lo(res[56], a[6], a[50]); // Sum(56) res[57] = fma52hi(res[57], a[6], a[50]); // Sum(56) res[57] = fma52lo(res[57], a[7], a[50]); // Sum(57) res[58] = fma52hi(res[58], a[7], a[50]); // Sum(57) res[58] = fma52lo(res[58], a[8], a[50]); // Sum(58) res[59] = fma52hi(res[59], a[8], a[50]); // Sum(58) res[59] = fma52lo(res[59], a[9], a[50]); // Sum(59) res[60] = fma52hi(res[60], a[9], a[50]); // Sum(59) res[51] = fma52lo(res[51], a[0], a[51]); // Sum(51) res[52] = fma52hi(res[52], a[0], a[51]); // Sum(51) res[52] = fma52lo(res[52], a[1], a[51]); // Sum(52) res[53] = fma52hi(res[53], a[1], a[51]); // Sum(52) res[53] = fma52lo(res[53], a[2], a[51]); // Sum(53) res[54] = fma52hi(res[54], a[2], a[51]); // Sum(53) res[54] = fma52lo(res[54], a[3], a[51]); // Sum(54) res[55] = fma52hi(res[55], a[3], a[51]); // Sum(54) res[55] = fma52lo(res[55], a[4], a[51]); // Sum(55) res[56] = fma52hi(res[56], a[4], a[51]); // Sum(55) res[56] = fma52lo(res[56], a[5], a[51]); // Sum(56) res[57] = fma52hi(res[57], a[5], a[51]); // Sum(56) res[57] = fma52lo(res[57], a[6], a[51]); // Sum(57) res[58] = fma52hi(res[58], a[6], a[51]); // Sum(57) res[58] = fma52lo(res[58], a[7], a[51]); // Sum(58) res[59] = fma52hi(res[59], a[7], a[51]); // Sum(58) res[59] = fma52lo(res[59], a[8], a[51]); // Sum(59) res[60] = fma52hi(res[60], a[8], a[51]); // Sum(59) res[52] = fma52lo(res[52], a[0], a[52]); // Sum(52) res[53] = fma52hi(res[53], a[0], a[52]); // Sum(52) res[53] = fma52lo(res[53], a[1], a[52]); // Sum(53) res[54] = fma52hi(res[54], a[1], a[52]); // Sum(53) res[54] = fma52lo(res[54], a[2], a[52]); // Sum(54) res[55] = fma52hi(res[55], a[2], a[52]); // Sum(54) res[55] = fma52lo(res[55], a[3], a[52]); // Sum(55) res[56] = fma52hi(res[56], a[3], a[52]); // Sum(55) res[56] = fma52lo(res[56], a[4], a[52]); // Sum(56) res[57] = fma52hi(res[57], a[4], a[52]); // Sum(56) res[57] = fma52lo(res[57], a[5], a[52]); // Sum(57) res[58] = fma52hi(res[58], a[5], a[52]); // Sum(57) res[58] = fma52lo(res[58], a[6], a[52]); // Sum(58) res[59] = fma52hi(res[59], a[6], a[52]); // Sum(58) res[59] = fma52lo(res[59], a[7], a[52]); // Sum(59) res[60] = fma52hi(res[60], a[7], a[52]); // Sum(59) res[53] = fma52lo(res[53], a[0], a[53]); // Sum(53) res[54] = fma52hi(res[54], a[0], a[53]); // Sum(53) res[54] = fma52lo(res[54], a[1], a[53]); // Sum(54) res[55] = fma52hi(res[55], a[1], a[53]); // Sum(54) res[55] = fma52lo(res[55], a[2], a[53]); // Sum(55) res[56] = fma52hi(res[56], a[2], a[53]); // Sum(55) res[56] = fma52lo(res[56], a[3], a[53]); // Sum(56) res[57] = fma52hi(res[57], a[3], a[53]); // Sum(56) res[57] = fma52lo(res[57], a[4], a[53]); // Sum(57) res[58] = fma52hi(res[58], a[4], a[53]); // Sum(57) res[58] = fma52lo(res[58], a[5], a[53]); // Sum(58) res[59] = fma52hi(res[59], a[5], a[53]); // Sum(58) res[59] = fma52lo(res[59], a[6], a[53]); // Sum(59) res[60] = fma52hi(res[60], a[6], a[53]); // Sum(59) res[54] = fma52lo(res[54], a[0], a[54]); // Sum(54) res[55] = fma52hi(res[55], a[0], a[54]); // Sum(54) res[55] = fma52lo(res[55], a[1], a[54]); // Sum(55) res[56] = fma52hi(res[56], a[1], a[54]); // Sum(55) res[56] = fma52lo(res[56], a[2], a[54]); // Sum(56) res[57] = fma52hi(res[57], a[2], a[54]); // Sum(56) res[57] = fma52lo(res[57], a[3], a[54]); // Sum(57) res[58] = fma52hi(res[58], a[3], a[54]); // Sum(57) res[58] = fma52lo(res[58], a[4], a[54]); // Sum(58) res[59] = fma52hi(res[59], a[4], a[54]); // Sum(58) res[59] = fma52lo(res[59], a[5], a[54]); // Sum(59) res[60] = fma52hi(res[60], a[5], a[54]); // Sum(59) res[55] = fma52lo(res[55], a[0], a[55]); // Sum(55) res[56] = fma52hi(res[56], a[0], a[55]); // Sum(55) res[56] = fma52lo(res[56], a[1], a[55]); // Sum(56) res[57] = fma52hi(res[57], a[1], a[55]); // Sum(56) res[57] = fma52lo(res[57], a[2], a[55]); // Sum(57) res[58] = fma52hi(res[58], a[2], a[55]); // Sum(57) res[58] = fma52lo(res[58], a[3], a[55]); // Sum(58) res[59] = fma52hi(res[59], a[3], a[55]); // Sum(58) res[59] = fma52lo(res[59], a[4], a[55]); // Sum(59) res[60] = fma52hi(res[60], a[4], a[55]); // Sum(59) res[56] = fma52lo(res[56], a[0], a[56]); // Sum(56) res[57] = fma52hi(res[57], a[0], a[56]); // Sum(56) res[57] = fma52lo(res[57], a[1], a[56]); // Sum(57) res[58] = fma52hi(res[58], a[1], a[56]); // Sum(57) res[58] = fma52lo(res[58], a[2], a[56]); // Sum(58) res[59] = fma52hi(res[59], a[2], a[56]); // Sum(58) res[59] = fma52lo(res[59], a[3], a[56]); // Sum(59) res[60] = fma52hi(res[60], a[3], a[56]); // Sum(59) res[57] = fma52lo(res[57], a[0], a[57]); // Sum(57) res[58] = fma52hi(res[58], a[0], a[57]); // Sum(57) res[58] = fma52lo(res[58], a[1], a[57]); // Sum(58) res[59] = fma52hi(res[59], a[1], a[57]); // Sum(58) res[59] = fma52lo(res[59], a[2], a[57]); // Sum(59) res[60] = fma52hi(res[60], a[2], a[57]); // Sum(59) res[58] = fma52lo(res[58], a[0], a[58]); // Sum(58) res[59] = fma52hi(res[59], a[0], a[58]); // Sum(58) res[59] = fma52lo(res[59], a[1], a[58]); // Sum(59) res[60] = fma52hi(res[60], a[1], a[58]); // Sum(59) res[59] = fma52lo(res[59], a[0], a[59]); // Sum(59) res[60] = fma52hi(res[60], a[0], a[59]); // Sum(59) res[48] = add64(res[48], res[48]); // Double(48) res[49] = add64(res[49], res[49]); // Double(49) res[50] = add64(res[50], res[50]); // Double(50) res[51] = add64(res[51], res[51]); // Double(51) res[52] = add64(res[52], res[52]); // Double(52) res[53] = add64(res[53], res[53]); // Double(53) res[54] = add64(res[54], res[54]); // Double(54) res[55] = add64(res[55], res[55]); // Double(55) res[56] = add64(res[56], res[56]); // Double(56) res[57] = add64(res[57], res[57]); // Double(57) res[58] = add64(res[58], res[58]); // Double(58) res[59] = add64(res[59], res[59]); // Double(59) res[48] = fma52lo(res[48], a[24], a[24]); // Add sqr(48) res[49] = fma52hi(res[49], a[24], a[24]); // Add sqr(48) res[50] = fma52lo(res[50], a[25], a[25]); // Add sqr(50) res[51] = fma52hi(res[51], a[25], a[25]); // Add sqr(50) res[52] = fma52lo(res[52], a[26], a[26]); // Add sqr(52) res[53] = fma52hi(res[53], a[26], a[26]); // Add sqr(52) res[54] = fma52lo(res[54], a[27], a[27]); // Add sqr(54) res[55] = fma52hi(res[55], a[27], a[27]); // Add sqr(54) res[56] = fma52lo(res[56], a[28], a[28]); // Add sqr(56) res[57] = fma52hi(res[57], a[28], a[28]); // Add sqr(56) res[58] = fma52lo(res[58], a[29], a[29]); // Add sqr(58) res[59] = fma52hi(res[59], a[29], a[29]); // Add sqr(58) res[60] = fma52lo(res[60], a[29], a[31]); // Sum(60) res[61] = fma52hi(res[61], a[29], a[31]); // Sum(60) res[61] = fma52lo(res[61], a[30], a[31]); // Sum(61) res[62] = fma52hi(res[62], a[30], a[31]); // Sum(61) res[60] = fma52lo(res[60], a[28], a[32]); // Sum(60) res[61] = fma52hi(res[61], a[28], a[32]); // Sum(60) res[61] = fma52lo(res[61], a[29], a[32]); // Sum(61) res[62] = fma52hi(res[62], a[29], a[32]); // Sum(61) res[62] = fma52lo(res[62], a[30], a[32]); // Sum(62) res[63] = fma52hi(res[63], a[30], a[32]); // Sum(62) res[63] = fma52lo(res[63], a[31], a[32]); // Sum(63) res[64] = fma52hi(res[64], a[31], a[32]); // Sum(63) res[60] = fma52lo(res[60], a[27], a[33]); // Sum(60) res[61] = fma52hi(res[61], a[27], a[33]); // Sum(60) res[61] = fma52lo(res[61], a[28], a[33]); // Sum(61) res[62] = fma52hi(res[62], a[28], a[33]); // Sum(61) res[62] = fma52lo(res[62], a[29], a[33]); // Sum(62) res[63] = fma52hi(res[63], a[29], a[33]); // Sum(62) res[63] = fma52lo(res[63], a[30], a[33]); // Sum(63) res[64] = fma52hi(res[64], a[30], a[33]); // Sum(63) res[64] = fma52lo(res[64], a[31], a[33]); // Sum(64) res[65] = fma52hi(res[65], a[31], a[33]); // Sum(64) res[65] = fma52lo(res[65], a[32], a[33]); // Sum(65) res[66] = fma52hi(res[66], a[32], a[33]); // Sum(65) res[60] = fma52lo(res[60], a[26], a[34]); // Sum(60) res[61] = fma52hi(res[61], a[26], a[34]); // Sum(60) res[61] = fma52lo(res[61], a[27], a[34]); // Sum(61) res[62] = fma52hi(res[62], a[27], a[34]); // Sum(61) res[62] = fma52lo(res[62], a[28], a[34]); // Sum(62) res[63] = fma52hi(res[63], a[28], a[34]); // Sum(62) res[63] = fma52lo(res[63], a[29], a[34]); // Sum(63) res[64] = fma52hi(res[64], a[29], a[34]); // Sum(63) res[64] = fma52lo(res[64], a[30], a[34]); // Sum(64) res[65] = fma52hi(res[65], a[30], a[34]); // Sum(64) res[65] = fma52lo(res[65], a[31], a[34]); // Sum(65) res[66] = fma52hi(res[66], a[31], a[34]); // Sum(65) res[66] = fma52lo(res[66], a[32], a[34]); // Sum(66) res[67] = fma52hi(res[67], a[32], a[34]); // Sum(66) res[67] = fma52lo(res[67], a[33], a[34]); // Sum(67) res[68] = fma52hi(res[68], a[33], a[34]); // Sum(67) res[60] = fma52lo(res[60], a[25], a[35]); // Sum(60) res[61] = fma52hi(res[61], a[25], a[35]); // Sum(60) res[61] = fma52lo(res[61], a[26], a[35]); // Sum(61) res[62] = fma52hi(res[62], a[26], a[35]); // Sum(61) res[62] = fma52lo(res[62], a[27], a[35]); // Sum(62) res[63] = fma52hi(res[63], a[27], a[35]); // Sum(62) res[63] = fma52lo(res[63], a[28], a[35]); // Sum(63) res[64] = fma52hi(res[64], a[28], a[35]); // Sum(63) res[64] = fma52lo(res[64], a[29], a[35]); // Sum(64) res[65] = fma52hi(res[65], a[29], a[35]); // Sum(64) res[65] = fma52lo(res[65], a[30], a[35]); // Sum(65) res[66] = fma52hi(res[66], a[30], a[35]); // Sum(65) res[66] = fma52lo(res[66], a[31], a[35]); // Sum(66) res[67] = fma52hi(res[67], a[31], a[35]); // Sum(66) res[67] = fma52lo(res[67], a[32], a[35]); // Sum(67) res[68] = fma52hi(res[68], a[32], a[35]); // Sum(67) res[68] = fma52lo(res[68], a[33], a[35]); // Sum(68) res[69] = fma52hi(res[69], a[33], a[35]); // Sum(68) res[69] = fma52lo(res[69], a[34], a[35]); // Sum(69) res[70] = fma52hi(res[70], a[34], a[35]); // Sum(69) res[60] = fma52lo(res[60], a[24], a[36]); // Sum(60) res[61] = fma52hi(res[61], a[24], a[36]); // Sum(60) res[61] = fma52lo(res[61], a[25], a[36]); // Sum(61) res[62] = fma52hi(res[62], a[25], a[36]); // Sum(61) res[62] = fma52lo(res[62], a[26], a[36]); // Sum(62) res[63] = fma52hi(res[63], a[26], a[36]); // Sum(62) res[63] = fma52lo(res[63], a[27], a[36]); // Sum(63) res[64] = fma52hi(res[64], a[27], a[36]); // Sum(63) res[64] = fma52lo(res[64], a[28], a[36]); // Sum(64) res[65] = fma52hi(res[65], a[28], a[36]); // Sum(64) res[65] = fma52lo(res[65], a[29], a[36]); // Sum(65) res[66] = fma52hi(res[66], a[29], a[36]); // Sum(65) res[66] = fma52lo(res[66], a[30], a[36]); // Sum(66) res[67] = fma52hi(res[67], a[30], a[36]); // Sum(66) res[67] = fma52lo(res[67], a[31], a[36]); // Sum(67) res[68] = fma52hi(res[68], a[31], a[36]); // Sum(67) res[68] = fma52lo(res[68], a[32], a[36]); // Sum(68) res[69] = fma52hi(res[69], a[32], a[36]); // Sum(68) res[69] = fma52lo(res[69], a[33], a[36]); // Sum(69) res[70] = fma52hi(res[70], a[33], a[36]); // Sum(69) res[70] = fma52lo(res[70], a[34], a[36]); // Sum(70) res[71] = fma52hi(res[71], a[34], a[36]); // Sum(70) res[71] = fma52lo(res[71], a[35], a[36]); // Sum(71) res[72] = fma52hi(res[72], a[35], a[36]); // Sum(71) res[60] = fma52lo(res[60], a[23], a[37]); // Sum(60) res[61] = fma52hi(res[61], a[23], a[37]); // Sum(60) res[61] = fma52lo(res[61], a[24], a[37]); // Sum(61) res[62] = fma52hi(res[62], a[24], a[37]); // Sum(61) res[62] = fma52lo(res[62], a[25], a[37]); // Sum(62) res[63] = fma52hi(res[63], a[25], a[37]); // Sum(62) res[63] = fma52lo(res[63], a[26], a[37]); // Sum(63) res[64] = fma52hi(res[64], a[26], a[37]); // Sum(63) res[64] = fma52lo(res[64], a[27], a[37]); // Sum(64) res[65] = fma52hi(res[65], a[27], a[37]); // Sum(64) res[65] = fma52lo(res[65], a[28], a[37]); // Sum(65) res[66] = fma52hi(res[66], a[28], a[37]); // Sum(65) res[66] = fma52lo(res[66], a[29], a[37]); // Sum(66) res[67] = fma52hi(res[67], a[29], a[37]); // Sum(66) res[67] = fma52lo(res[67], a[30], a[37]); // Sum(67) res[68] = fma52hi(res[68], a[30], a[37]); // Sum(67) res[68] = fma52lo(res[68], a[31], a[37]); // Sum(68) res[69] = fma52hi(res[69], a[31], a[37]); // Sum(68) res[69] = fma52lo(res[69], a[32], a[37]); // Sum(69) res[70] = fma52hi(res[70], a[32], a[37]); // Sum(69) res[70] = fma52lo(res[70], a[33], a[37]); // Sum(70) res[71] = fma52hi(res[71], a[33], a[37]); // Sum(70) res[71] = fma52lo(res[71], a[34], a[37]); // Sum(71) res[72] = fma52hi(res[72], a[34], a[37]); // Sum(71) res[60] = fma52lo(res[60], a[22], a[38]); // Sum(60) res[61] = fma52hi(res[61], a[22], a[38]); // Sum(60) res[61] = fma52lo(res[61], a[23], a[38]); // Sum(61) res[62] = fma52hi(res[62], a[23], a[38]); // Sum(61) res[62] = fma52lo(res[62], a[24], a[38]); // Sum(62) res[63] = fma52hi(res[63], a[24], a[38]); // Sum(62) res[63] = fma52lo(res[63], a[25], a[38]); // Sum(63) res[64] = fma52hi(res[64], a[25], a[38]); // Sum(63) res[64] = fma52lo(res[64], a[26], a[38]); // Sum(64) res[65] = fma52hi(res[65], a[26], a[38]); // Sum(64) res[65] = fma52lo(res[65], a[27], a[38]); // Sum(65) res[66] = fma52hi(res[66], a[27], a[38]); // Sum(65) res[66] = fma52lo(res[66], a[28], a[38]); // Sum(66) res[67] = fma52hi(res[67], a[28], a[38]); // Sum(66) res[67] = fma52lo(res[67], a[29], a[38]); // Sum(67) res[68] = fma52hi(res[68], a[29], a[38]); // Sum(67) res[68] = fma52lo(res[68], a[30], a[38]); // Sum(68) res[69] = fma52hi(res[69], a[30], a[38]); // Sum(68) res[69] = fma52lo(res[69], a[31], a[38]); // Sum(69) res[70] = fma52hi(res[70], a[31], a[38]); // Sum(69) res[70] = fma52lo(res[70], a[32], a[38]); // Sum(70) res[71] = fma52hi(res[71], a[32], a[38]); // Sum(70) res[71] = fma52lo(res[71], a[33], a[38]); // Sum(71) res[72] = fma52hi(res[72], a[33], a[38]); // Sum(71) res[60] = fma52lo(res[60], a[21], a[39]); // Sum(60) res[61] = fma52hi(res[61], a[21], a[39]); // Sum(60) res[61] = fma52lo(res[61], a[22], a[39]); // Sum(61) res[62] = fma52hi(res[62], a[22], a[39]); // Sum(61) res[62] = fma52lo(res[62], a[23], a[39]); // Sum(62) res[63] = fma52hi(res[63], a[23], a[39]); // Sum(62) res[63] = fma52lo(res[63], a[24], a[39]); // Sum(63) res[64] = fma52hi(res[64], a[24], a[39]); // Sum(63) res[64] = fma52lo(res[64], a[25], a[39]); // Sum(64) res[65] = fma52hi(res[65], a[25], a[39]); // Sum(64) res[65] = fma52lo(res[65], a[26], a[39]); // Sum(65) res[66] = fma52hi(res[66], a[26], a[39]); // Sum(65) res[66] = fma52lo(res[66], a[27], a[39]); // Sum(66) res[67] = fma52hi(res[67], a[27], a[39]); // Sum(66) res[67] = fma52lo(res[67], a[28], a[39]); // Sum(67) res[68] = fma52hi(res[68], a[28], a[39]); // Sum(67) res[68] = fma52lo(res[68], a[29], a[39]); // Sum(68) res[69] = fma52hi(res[69], a[29], a[39]); // Sum(68) res[69] = fma52lo(res[69], a[30], a[39]); // Sum(69) res[70] = fma52hi(res[70], a[30], a[39]); // Sum(69) res[70] = fma52lo(res[70], a[31], a[39]); // Sum(70) res[71] = fma52hi(res[71], a[31], a[39]); // Sum(70) res[71] = fma52lo(res[71], a[32], a[39]); // Sum(71) res[72] = fma52hi(res[72], a[32], a[39]); // Sum(71) res[60] = fma52lo(res[60], a[20], a[40]); // Sum(60) res[61] = fma52hi(res[61], a[20], a[40]); // Sum(60) res[61] = fma52lo(res[61], a[21], a[40]); // Sum(61) res[62] = fma52hi(res[62], a[21], a[40]); // Sum(61) res[62] = fma52lo(res[62], a[22], a[40]); // Sum(62) res[63] = fma52hi(res[63], a[22], a[40]); // Sum(62) res[63] = fma52lo(res[63], a[23], a[40]); // Sum(63) res[64] = fma52hi(res[64], a[23], a[40]); // Sum(63) res[64] = fma52lo(res[64], a[24], a[40]); // Sum(64) res[65] = fma52hi(res[65], a[24], a[40]); // Sum(64) res[65] = fma52lo(res[65], a[25], a[40]); // Sum(65) res[66] = fma52hi(res[66], a[25], a[40]); // Sum(65) res[66] = fma52lo(res[66], a[26], a[40]); // Sum(66) res[67] = fma52hi(res[67], a[26], a[40]); // Sum(66) res[67] = fma52lo(res[67], a[27], a[40]); // Sum(67) res[68] = fma52hi(res[68], a[27], a[40]); // Sum(67) res[68] = fma52lo(res[68], a[28], a[40]); // Sum(68) res[69] = fma52hi(res[69], a[28], a[40]); // Sum(68) res[69] = fma52lo(res[69], a[29], a[40]); // Sum(69) res[70] = fma52hi(res[70], a[29], a[40]); // Sum(69) res[70] = fma52lo(res[70], a[30], a[40]); // Sum(70) res[71] = fma52hi(res[71], a[30], a[40]); // Sum(70) res[71] = fma52lo(res[71], a[31], a[40]); // Sum(71) res[72] = fma52hi(res[72], a[31], a[40]); // Sum(71) res[60] = fma52lo(res[60], a[19], a[41]); // Sum(60) res[61] = fma52hi(res[61], a[19], a[41]); // Sum(60) res[61] = fma52lo(res[61], a[20], a[41]); // Sum(61) res[62] = fma52hi(res[62], a[20], a[41]); // Sum(61) res[62] = fma52lo(res[62], a[21], a[41]); // Sum(62) res[63] = fma52hi(res[63], a[21], a[41]); // Sum(62) res[63] = fma52lo(res[63], a[22], a[41]); // Sum(63) res[64] = fma52hi(res[64], a[22], a[41]); // Sum(63) res[64] = fma52lo(res[64], a[23], a[41]); // Sum(64) res[65] = fma52hi(res[65], a[23], a[41]); // Sum(64) res[65] = fma52lo(res[65], a[24], a[41]); // Sum(65) res[66] = fma52hi(res[66], a[24], a[41]); // Sum(65) res[66] = fma52lo(res[66], a[25], a[41]); // Sum(66) res[67] = fma52hi(res[67], a[25], a[41]); // Sum(66) res[67] = fma52lo(res[67], a[26], a[41]); // Sum(67) res[68] = fma52hi(res[68], a[26], a[41]); // Sum(67) res[68] = fma52lo(res[68], a[27], a[41]); // Sum(68) res[69] = fma52hi(res[69], a[27], a[41]); // Sum(68) res[69] = fma52lo(res[69], a[28], a[41]); // Sum(69) res[70] = fma52hi(res[70], a[28], a[41]); // Sum(69) res[70] = fma52lo(res[70], a[29], a[41]); // Sum(70) res[71] = fma52hi(res[71], a[29], a[41]); // Sum(70) res[71] = fma52lo(res[71], a[30], a[41]); // Sum(71) res[72] = fma52hi(res[72], a[30], a[41]); // Sum(71) res[60] = fma52lo(res[60], a[18], a[42]); // Sum(60) res[61] = fma52hi(res[61], a[18], a[42]); // Sum(60) res[61] = fma52lo(res[61], a[19], a[42]); // Sum(61) res[62] = fma52hi(res[62], a[19], a[42]); // Sum(61) res[62] = fma52lo(res[62], a[20], a[42]); // Sum(62) res[63] = fma52hi(res[63], a[20], a[42]); // Sum(62) res[63] = fma52lo(res[63], a[21], a[42]); // Sum(63) res[64] = fma52hi(res[64], a[21], a[42]); // Sum(63) res[64] = fma52lo(res[64], a[22], a[42]); // Sum(64) res[65] = fma52hi(res[65], a[22], a[42]); // Sum(64) res[65] = fma52lo(res[65], a[23], a[42]); // Sum(65) res[66] = fma52hi(res[66], a[23], a[42]); // Sum(65) res[66] = fma52lo(res[66], a[24], a[42]); // Sum(66) res[67] = fma52hi(res[67], a[24], a[42]); // Sum(66) res[67] = fma52lo(res[67], a[25], a[42]); // Sum(67) res[68] = fma52hi(res[68], a[25], a[42]); // Sum(67) res[68] = fma52lo(res[68], a[26], a[42]); // Sum(68) res[69] = fma52hi(res[69], a[26], a[42]); // Sum(68) res[69] = fma52lo(res[69], a[27], a[42]); // Sum(69) res[70] = fma52hi(res[70], a[27], a[42]); // Sum(69) res[70] = fma52lo(res[70], a[28], a[42]); // Sum(70) res[71] = fma52hi(res[71], a[28], a[42]); // Sum(70) res[71] = fma52lo(res[71], a[29], a[42]); // Sum(71) res[72] = fma52hi(res[72], a[29], a[42]); // Sum(71) res[60] = fma52lo(res[60], a[17], a[43]); // Sum(60) res[61] = fma52hi(res[61], a[17], a[43]); // Sum(60) res[61] = fma52lo(res[61], a[18], a[43]); // Sum(61) res[62] = fma52hi(res[62], a[18], a[43]); // Sum(61) res[62] = fma52lo(res[62], a[19], a[43]); // Sum(62) res[63] = fma52hi(res[63], a[19], a[43]); // Sum(62) res[63] = fma52lo(res[63], a[20], a[43]); // Sum(63) res[64] = fma52hi(res[64], a[20], a[43]); // Sum(63) res[64] = fma52lo(res[64], a[21], a[43]); // Sum(64) res[65] = fma52hi(res[65], a[21], a[43]); // Sum(64) res[65] = fma52lo(res[65], a[22], a[43]); // Sum(65) res[66] = fma52hi(res[66], a[22], a[43]); // Sum(65) res[66] = fma52lo(res[66], a[23], a[43]); // Sum(66) res[67] = fma52hi(res[67], a[23], a[43]); // Sum(66) res[67] = fma52lo(res[67], a[24], a[43]); // Sum(67) res[68] = fma52hi(res[68], a[24], a[43]); // Sum(67) res[68] = fma52lo(res[68], a[25], a[43]); // Sum(68) res[69] = fma52hi(res[69], a[25], a[43]); // Sum(68) res[69] = fma52lo(res[69], a[26], a[43]); // Sum(69) res[70] = fma52hi(res[70], a[26], a[43]); // Sum(69) res[70] = fma52lo(res[70], a[27], a[43]); // Sum(70) res[71] = fma52hi(res[71], a[27], a[43]); // Sum(70) res[71] = fma52lo(res[71], a[28], a[43]); // Sum(71) res[72] = fma52hi(res[72], a[28], a[43]); // Sum(71) res[60] = fma52lo(res[60], a[16], a[44]); // Sum(60) res[61] = fma52hi(res[61], a[16], a[44]); // Sum(60) res[61] = fma52lo(res[61], a[17], a[44]); // Sum(61) res[62] = fma52hi(res[62], a[17], a[44]); // Sum(61) res[62] = fma52lo(res[62], a[18], a[44]); // Sum(62) res[63] = fma52hi(res[63], a[18], a[44]); // Sum(62) res[63] = fma52lo(res[63], a[19], a[44]); // Sum(63) res[64] = fma52hi(res[64], a[19], a[44]); // Sum(63) res[64] = fma52lo(res[64], a[20], a[44]); // Sum(64) res[65] = fma52hi(res[65], a[20], a[44]); // Sum(64) res[65] = fma52lo(res[65], a[21], a[44]); // Sum(65) res[66] = fma52hi(res[66], a[21], a[44]); // Sum(65) res[66] = fma52lo(res[66], a[22], a[44]); // Sum(66) res[67] = fma52hi(res[67], a[22], a[44]); // Sum(66) res[67] = fma52lo(res[67], a[23], a[44]); // Sum(67) res[68] = fma52hi(res[68], a[23], a[44]); // Sum(67) res[68] = fma52lo(res[68], a[24], a[44]); // Sum(68) res[69] = fma52hi(res[69], a[24], a[44]); // Sum(68) res[69] = fma52lo(res[69], a[25], a[44]); // Sum(69) res[70] = fma52hi(res[70], a[25], a[44]); // Sum(69) res[70] = fma52lo(res[70], a[26], a[44]); // Sum(70) res[71] = fma52hi(res[71], a[26], a[44]); // Sum(70) res[71] = fma52lo(res[71], a[27], a[44]); // Sum(71) res[72] = fma52hi(res[72], a[27], a[44]); // Sum(71) res[60] = fma52lo(res[60], a[15], a[45]); // Sum(60) res[61] = fma52hi(res[61], a[15], a[45]); // Sum(60) res[61] = fma52lo(res[61], a[16], a[45]); // Sum(61) res[62] = fma52hi(res[62], a[16], a[45]); // Sum(61) res[62] = fma52lo(res[62], a[17], a[45]); // Sum(62) res[63] = fma52hi(res[63], a[17], a[45]); // Sum(62) res[63] = fma52lo(res[63], a[18], a[45]); // Sum(63) res[64] = fma52hi(res[64], a[18], a[45]); // Sum(63) res[64] = fma52lo(res[64], a[19], a[45]); // Sum(64) res[65] = fma52hi(res[65], a[19], a[45]); // Sum(64) res[65] = fma52lo(res[65], a[20], a[45]); // Sum(65) res[66] = fma52hi(res[66], a[20], a[45]); // Sum(65) res[66] = fma52lo(res[66], a[21], a[45]); // Sum(66) res[67] = fma52hi(res[67], a[21], a[45]); // Sum(66) res[67] = fma52lo(res[67], a[22], a[45]); // Sum(67) res[68] = fma52hi(res[68], a[22], a[45]); // Sum(67) res[68] = fma52lo(res[68], a[23], a[45]); // Sum(68) res[69] = fma52hi(res[69], a[23], a[45]); // Sum(68) res[69] = fma52lo(res[69], a[24], a[45]); // Sum(69) res[70] = fma52hi(res[70], a[24], a[45]); // Sum(69) res[70] = fma52lo(res[70], a[25], a[45]); // Sum(70) res[71] = fma52hi(res[71], a[25], a[45]); // Sum(70) res[71] = fma52lo(res[71], a[26], a[45]); // Sum(71) res[72] = fma52hi(res[72], a[26], a[45]); // Sum(71) res[60] = fma52lo(res[60], a[14], a[46]); // Sum(60) res[61] = fma52hi(res[61], a[14], a[46]); // Sum(60) res[61] = fma52lo(res[61], a[15], a[46]); // Sum(61) res[62] = fma52hi(res[62], a[15], a[46]); // Sum(61) res[62] = fma52lo(res[62], a[16], a[46]); // Sum(62) res[63] = fma52hi(res[63], a[16], a[46]); // Sum(62) res[63] = fma52lo(res[63], a[17], a[46]); // Sum(63) res[64] = fma52hi(res[64], a[17], a[46]); // Sum(63) res[64] = fma52lo(res[64], a[18], a[46]); // Sum(64) res[65] = fma52hi(res[65], a[18], a[46]); // Sum(64) res[65] = fma52lo(res[65], a[19], a[46]); // Sum(65) res[66] = fma52hi(res[66], a[19], a[46]); // Sum(65) res[66] = fma52lo(res[66], a[20], a[46]); // Sum(66) res[67] = fma52hi(res[67], a[20], a[46]); // Sum(66) res[67] = fma52lo(res[67], a[21], a[46]); // Sum(67) res[68] = fma52hi(res[68], a[21], a[46]); // Sum(67) res[68] = fma52lo(res[68], a[22], a[46]); // Sum(68) res[69] = fma52hi(res[69], a[22], a[46]); // Sum(68) res[69] = fma52lo(res[69], a[23], a[46]); // Sum(69) res[70] = fma52hi(res[70], a[23], a[46]); // Sum(69) res[70] = fma52lo(res[70], a[24], a[46]); // Sum(70) res[71] = fma52hi(res[71], a[24], a[46]); // Sum(70) res[71] = fma52lo(res[71], a[25], a[46]); // Sum(71) res[72] = fma52hi(res[72], a[25], a[46]); // Sum(71) res[60] = fma52lo(res[60], a[13], a[47]); // Sum(60) res[61] = fma52hi(res[61], a[13], a[47]); // Sum(60) res[61] = fma52lo(res[61], a[14], a[47]); // Sum(61) res[62] = fma52hi(res[62], a[14], a[47]); // Sum(61) res[62] = fma52lo(res[62], a[15], a[47]); // Sum(62) res[63] = fma52hi(res[63], a[15], a[47]); // Sum(62) res[63] = fma52lo(res[63], a[16], a[47]); // Sum(63) res[64] = fma52hi(res[64], a[16], a[47]); // Sum(63) res[64] = fma52lo(res[64], a[17], a[47]); // Sum(64) res[65] = fma52hi(res[65], a[17], a[47]); // Sum(64) res[65] = fma52lo(res[65], a[18], a[47]); // Sum(65) res[66] = fma52hi(res[66], a[18], a[47]); // Sum(65) res[66] = fma52lo(res[66], a[19], a[47]); // Sum(66) res[67] = fma52hi(res[67], a[19], a[47]); // Sum(66) res[67] = fma52lo(res[67], a[20], a[47]); // Sum(67) res[68] = fma52hi(res[68], a[20], a[47]); // Sum(67) res[68] = fma52lo(res[68], a[21], a[47]); // Sum(68) res[69] = fma52hi(res[69], a[21], a[47]); // Sum(68) res[69] = fma52lo(res[69], a[22], a[47]); // Sum(69) res[70] = fma52hi(res[70], a[22], a[47]); // Sum(69) res[70] = fma52lo(res[70], a[23], a[47]); // Sum(70) res[71] = fma52hi(res[71], a[23], a[47]); // Sum(70) res[71] = fma52lo(res[71], a[24], a[47]); // Sum(71) res[72] = fma52hi(res[72], a[24], a[47]); // Sum(71) res[60] = fma52lo(res[60], a[12], a[48]); // Sum(60) res[61] = fma52hi(res[61], a[12], a[48]); // Sum(60) res[61] = fma52lo(res[61], a[13], a[48]); // Sum(61) res[62] = fma52hi(res[62], a[13], a[48]); // Sum(61) res[62] = fma52lo(res[62], a[14], a[48]); // Sum(62) res[63] = fma52hi(res[63], a[14], a[48]); // Sum(62) res[63] = fma52lo(res[63], a[15], a[48]); // Sum(63) res[64] = fma52hi(res[64], a[15], a[48]); // Sum(63) res[64] = fma52lo(res[64], a[16], a[48]); // Sum(64) res[65] = fma52hi(res[65], a[16], a[48]); // Sum(64) res[65] = fma52lo(res[65], a[17], a[48]); // Sum(65) res[66] = fma52hi(res[66], a[17], a[48]); // Sum(65) res[66] = fma52lo(res[66], a[18], a[48]); // Sum(66) res[67] = fma52hi(res[67], a[18], a[48]); // Sum(66) res[67] = fma52lo(res[67], a[19], a[48]); // Sum(67) res[68] = fma52hi(res[68], a[19], a[48]); // Sum(67) res[68] = fma52lo(res[68], a[20], a[48]); // Sum(68) res[69] = fma52hi(res[69], a[20], a[48]); // Sum(68) res[69] = fma52lo(res[69], a[21], a[48]); // Sum(69) res[70] = fma52hi(res[70], a[21], a[48]); // Sum(69) res[70] = fma52lo(res[70], a[22], a[48]); // Sum(70) res[71] = fma52hi(res[71], a[22], a[48]); // Sum(70) res[71] = fma52lo(res[71], a[23], a[48]); // Sum(71) res[72] = fma52hi(res[72], a[23], a[48]); // Sum(71) res[60] = fma52lo(res[60], a[11], a[49]); // Sum(60) res[61] = fma52hi(res[61], a[11], a[49]); // Sum(60) res[61] = fma52lo(res[61], a[12], a[49]); // Sum(61) res[62] = fma52hi(res[62], a[12], a[49]); // Sum(61) res[62] = fma52lo(res[62], a[13], a[49]); // Sum(62) res[63] = fma52hi(res[63], a[13], a[49]); // Sum(62) res[63] = fma52lo(res[63], a[14], a[49]); // Sum(63) res[64] = fma52hi(res[64], a[14], a[49]); // Sum(63) res[64] = fma52lo(res[64], a[15], a[49]); // Sum(64) res[65] = fma52hi(res[65], a[15], a[49]); // Sum(64) res[65] = fma52lo(res[65], a[16], a[49]); // Sum(65) res[66] = fma52hi(res[66], a[16], a[49]); // Sum(65) res[66] = fma52lo(res[66], a[17], a[49]); // Sum(66) res[67] = fma52hi(res[67], a[17], a[49]); // Sum(66) res[67] = fma52lo(res[67], a[18], a[49]); // Sum(67) res[68] = fma52hi(res[68], a[18], a[49]); // Sum(67) res[68] = fma52lo(res[68], a[19], a[49]); // Sum(68) res[69] = fma52hi(res[69], a[19], a[49]); // Sum(68) res[69] = fma52lo(res[69], a[20], a[49]); // Sum(69) res[70] = fma52hi(res[70], a[20], a[49]); // Sum(69) res[70] = fma52lo(res[70], a[21], a[49]); // Sum(70) res[71] = fma52hi(res[71], a[21], a[49]); // Sum(70) res[71] = fma52lo(res[71], a[22], a[49]); // Sum(71) res[72] = fma52hi(res[72], a[22], a[49]); // Sum(71) res[60] = fma52lo(res[60], a[10], a[50]); // Sum(60) res[61] = fma52hi(res[61], a[10], a[50]); // Sum(60) res[61] = fma52lo(res[61], a[11], a[50]); // Sum(61) res[62] = fma52hi(res[62], a[11], a[50]); // Sum(61) res[62] = fma52lo(res[62], a[12], a[50]); // Sum(62) res[63] = fma52hi(res[63], a[12], a[50]); // Sum(62) res[63] = fma52lo(res[63], a[13], a[50]); // Sum(63) res[64] = fma52hi(res[64], a[13], a[50]); // Sum(63) res[64] = fma52lo(res[64], a[14], a[50]); // Sum(64) res[65] = fma52hi(res[65], a[14], a[50]); // Sum(64) res[65] = fma52lo(res[65], a[15], a[50]); // Sum(65) res[66] = fma52hi(res[66], a[15], a[50]); // Sum(65) res[66] = fma52lo(res[66], a[16], a[50]); // Sum(66) res[67] = fma52hi(res[67], a[16], a[50]); // Sum(66) res[67] = fma52lo(res[67], a[17], a[50]); // Sum(67) res[68] = fma52hi(res[68], a[17], a[50]); // Sum(67) res[68] = fma52lo(res[68], a[18], a[50]); // Sum(68) res[69] = fma52hi(res[69], a[18], a[50]); // Sum(68) res[69] = fma52lo(res[69], a[19], a[50]); // Sum(69) res[70] = fma52hi(res[70], a[19], a[50]); // Sum(69) res[70] = fma52lo(res[70], a[20], a[50]); // Sum(70) res[71] = fma52hi(res[71], a[20], a[50]); // Sum(70) res[71] = fma52lo(res[71], a[21], a[50]); // Sum(71) res[72] = fma52hi(res[72], a[21], a[50]); // Sum(71) res[60] = fma52lo(res[60], a[9], a[51]); // Sum(60) res[61] = fma52hi(res[61], a[9], a[51]); // Sum(60) res[61] = fma52lo(res[61], a[10], a[51]); // Sum(61) res[62] = fma52hi(res[62], a[10], a[51]); // Sum(61) res[62] = fma52lo(res[62], a[11], a[51]); // Sum(62) res[63] = fma52hi(res[63], a[11], a[51]); // Sum(62) res[63] = fma52lo(res[63], a[12], a[51]); // Sum(63) res[64] = fma52hi(res[64], a[12], a[51]); // Sum(63) res[64] = fma52lo(res[64], a[13], a[51]); // Sum(64) res[65] = fma52hi(res[65], a[13], a[51]); // Sum(64) res[65] = fma52lo(res[65], a[14], a[51]); // Sum(65) res[66] = fma52hi(res[66], a[14], a[51]); // Sum(65) res[66] = fma52lo(res[66], a[15], a[51]); // Sum(66) res[67] = fma52hi(res[67], a[15], a[51]); // Sum(66) res[67] = fma52lo(res[67], a[16], a[51]); // Sum(67) res[68] = fma52hi(res[68], a[16], a[51]); // Sum(67) res[68] = fma52lo(res[68], a[17], a[51]); // Sum(68) res[69] = fma52hi(res[69], a[17], a[51]); // Sum(68) res[69] = fma52lo(res[69], a[18], a[51]); // Sum(69) res[70] = fma52hi(res[70], a[18], a[51]); // Sum(69) res[70] = fma52lo(res[70], a[19], a[51]); // Sum(70) res[71] = fma52hi(res[71], a[19], a[51]); // Sum(70) res[71] = fma52lo(res[71], a[20], a[51]); // Sum(71) res[72] = fma52hi(res[72], a[20], a[51]); // Sum(71) res[60] = fma52lo(res[60], a[8], a[52]); // Sum(60) res[61] = fma52hi(res[61], a[8], a[52]); // Sum(60) res[61] = fma52lo(res[61], a[9], a[52]); // Sum(61) res[62] = fma52hi(res[62], a[9], a[52]); // Sum(61) res[62] = fma52lo(res[62], a[10], a[52]); // Sum(62) res[63] = fma52hi(res[63], a[10], a[52]); // Sum(62) res[63] = fma52lo(res[63], a[11], a[52]); // Sum(63) res[64] = fma52hi(res[64], a[11], a[52]); // Sum(63) res[64] = fma52lo(res[64], a[12], a[52]); // Sum(64) res[65] = fma52hi(res[65], a[12], a[52]); // Sum(64) res[65] = fma52lo(res[65], a[13], a[52]); // Sum(65) res[66] = fma52hi(res[66], a[13], a[52]); // Sum(65) res[66] = fma52lo(res[66], a[14], a[52]); // Sum(66) res[67] = fma52hi(res[67], a[14], a[52]); // Sum(66) res[67] = fma52lo(res[67], a[15], a[52]); // Sum(67) res[68] = fma52hi(res[68], a[15], a[52]); // Sum(67) res[68] = fma52lo(res[68], a[16], a[52]); // Sum(68) res[69] = fma52hi(res[69], a[16], a[52]); // Sum(68) res[69] = fma52lo(res[69], a[17], a[52]); // Sum(69) res[70] = fma52hi(res[70], a[17], a[52]); // Sum(69) res[70] = fma52lo(res[70], a[18], a[52]); // Sum(70) res[71] = fma52hi(res[71], a[18], a[52]); // Sum(70) res[71] = fma52lo(res[71], a[19], a[52]); // Sum(71) res[72] = fma52hi(res[72], a[19], a[52]); // Sum(71) res[60] = fma52lo(res[60], a[7], a[53]); // Sum(60) res[61] = fma52hi(res[61], a[7], a[53]); // Sum(60) res[61] = fma52lo(res[61], a[8], a[53]); // Sum(61) res[62] = fma52hi(res[62], a[8], a[53]); // Sum(61) res[62] = fma52lo(res[62], a[9], a[53]); // Sum(62) res[63] = fma52hi(res[63], a[9], a[53]); // Sum(62) res[63] = fma52lo(res[63], a[10], a[53]); // Sum(63) res[64] = fma52hi(res[64], a[10], a[53]); // Sum(63) res[64] = fma52lo(res[64], a[11], a[53]); // Sum(64) res[65] = fma52hi(res[65], a[11], a[53]); // Sum(64) res[65] = fma52lo(res[65], a[12], a[53]); // Sum(65) res[66] = fma52hi(res[66], a[12], a[53]); // Sum(65) res[66] = fma52lo(res[66], a[13], a[53]); // Sum(66) res[67] = fma52hi(res[67], a[13], a[53]); // Sum(66) res[67] = fma52lo(res[67], a[14], a[53]); // Sum(67) res[68] = fma52hi(res[68], a[14], a[53]); // Sum(67) res[68] = fma52lo(res[68], a[15], a[53]); // Sum(68) res[69] = fma52hi(res[69], a[15], a[53]); // Sum(68) res[69] = fma52lo(res[69], a[16], a[53]); // Sum(69) res[70] = fma52hi(res[70], a[16], a[53]); // Sum(69) res[70] = fma52lo(res[70], a[17], a[53]); // Sum(70) res[71] = fma52hi(res[71], a[17], a[53]); // Sum(70) res[71] = fma52lo(res[71], a[18], a[53]); // Sum(71) res[72] = fma52hi(res[72], a[18], a[53]); // Sum(71) res[60] = fma52lo(res[60], a[6], a[54]); // Sum(60) res[61] = fma52hi(res[61], a[6], a[54]); // Sum(60) res[61] = fma52lo(res[61], a[7], a[54]); // Sum(61) res[62] = fma52hi(res[62], a[7], a[54]); // Sum(61) res[62] = fma52lo(res[62], a[8], a[54]); // Sum(62) res[63] = fma52hi(res[63], a[8], a[54]); // Sum(62) res[63] = fma52lo(res[63], a[9], a[54]); // Sum(63) res[64] = fma52hi(res[64], a[9], a[54]); // Sum(63) res[64] = fma52lo(res[64], a[10], a[54]); // Sum(64) res[65] = fma52hi(res[65], a[10], a[54]); // Sum(64) res[65] = fma52lo(res[65], a[11], a[54]); // Sum(65) res[66] = fma52hi(res[66], a[11], a[54]); // Sum(65) res[66] = fma52lo(res[66], a[12], a[54]); // Sum(66) res[67] = fma52hi(res[67], a[12], a[54]); // Sum(66) res[67] = fma52lo(res[67], a[13], a[54]); // Sum(67) res[68] = fma52hi(res[68], a[13], a[54]); // Sum(67) res[68] = fma52lo(res[68], a[14], a[54]); // Sum(68) res[69] = fma52hi(res[69], a[14], a[54]); // Sum(68) res[69] = fma52lo(res[69], a[15], a[54]); // Sum(69) res[70] = fma52hi(res[70], a[15], a[54]); // Sum(69) res[70] = fma52lo(res[70], a[16], a[54]); // Sum(70) res[71] = fma52hi(res[71], a[16], a[54]); // Sum(70) res[71] = fma52lo(res[71], a[17], a[54]); // Sum(71) res[72] = fma52hi(res[72], a[17], a[54]); // Sum(71) res[60] = fma52lo(res[60], a[5], a[55]); // Sum(60) res[61] = fma52hi(res[61], a[5], a[55]); // Sum(60) res[61] = fma52lo(res[61], a[6], a[55]); // Sum(61) res[62] = fma52hi(res[62], a[6], a[55]); // Sum(61) res[62] = fma52lo(res[62], a[7], a[55]); // Sum(62) res[63] = fma52hi(res[63], a[7], a[55]); // Sum(62) res[63] = fma52lo(res[63], a[8], a[55]); // Sum(63) res[64] = fma52hi(res[64], a[8], a[55]); // Sum(63) res[64] = fma52lo(res[64], a[9], a[55]); // Sum(64) res[65] = fma52hi(res[65], a[9], a[55]); // Sum(64) res[65] = fma52lo(res[65], a[10], a[55]); // Sum(65) res[66] = fma52hi(res[66], a[10], a[55]); // Sum(65) res[66] = fma52lo(res[66], a[11], a[55]); // Sum(66) res[67] = fma52hi(res[67], a[11], a[55]); // Sum(66) res[67] = fma52lo(res[67], a[12], a[55]); // Sum(67) res[68] = fma52hi(res[68], a[12], a[55]); // Sum(67) res[68] = fma52lo(res[68], a[13], a[55]); // Sum(68) res[69] = fma52hi(res[69], a[13], a[55]); // Sum(68) res[69] = fma52lo(res[69], a[14], a[55]); // Sum(69) res[70] = fma52hi(res[70], a[14], a[55]); // Sum(69) res[70] = fma52lo(res[70], a[15], a[55]); // Sum(70) res[71] = fma52hi(res[71], a[15], a[55]); // Sum(70) res[71] = fma52lo(res[71], a[16], a[55]); // Sum(71) res[72] = fma52hi(res[72], a[16], a[55]); // Sum(71) res[60] = fma52lo(res[60], a[4], a[56]); // Sum(60) res[61] = fma52hi(res[61], a[4], a[56]); // Sum(60) res[61] = fma52lo(res[61], a[5], a[56]); // Sum(61) res[62] = fma52hi(res[62], a[5], a[56]); // Sum(61) res[62] = fma52lo(res[62], a[6], a[56]); // Sum(62) res[63] = fma52hi(res[63], a[6], a[56]); // Sum(62) res[63] = fma52lo(res[63], a[7], a[56]); // Sum(63) res[64] = fma52hi(res[64], a[7], a[56]); // Sum(63) res[64] = fma52lo(res[64], a[8], a[56]); // Sum(64) res[65] = fma52hi(res[65], a[8], a[56]); // Sum(64) res[65] = fma52lo(res[65], a[9], a[56]); // Sum(65) res[66] = fma52hi(res[66], a[9], a[56]); // Sum(65) res[66] = fma52lo(res[66], a[10], a[56]); // Sum(66) res[67] = fma52hi(res[67], a[10], a[56]); // Sum(66) res[67] = fma52lo(res[67], a[11], a[56]); // Sum(67) res[68] = fma52hi(res[68], a[11], a[56]); // Sum(67) res[68] = fma52lo(res[68], a[12], a[56]); // Sum(68) res[69] = fma52hi(res[69], a[12], a[56]); // Sum(68) res[69] = fma52lo(res[69], a[13], a[56]); // Sum(69) res[70] = fma52hi(res[70], a[13], a[56]); // Sum(69) res[70] = fma52lo(res[70], a[14], a[56]); // Sum(70) res[71] = fma52hi(res[71], a[14], a[56]); // Sum(70) res[71] = fma52lo(res[71], a[15], a[56]); // Sum(71) res[72] = fma52hi(res[72], a[15], a[56]); // Sum(71) res[60] = fma52lo(res[60], a[3], a[57]); // Sum(60) res[61] = fma52hi(res[61], a[3], a[57]); // Sum(60) res[61] = fma52lo(res[61], a[4], a[57]); // Sum(61) res[62] = fma52hi(res[62], a[4], a[57]); // Sum(61) res[62] = fma52lo(res[62], a[5], a[57]); // Sum(62) res[63] = fma52hi(res[63], a[5], a[57]); // Sum(62) res[63] = fma52lo(res[63], a[6], a[57]); // Sum(63) res[64] = fma52hi(res[64], a[6], a[57]); // Sum(63) res[64] = fma52lo(res[64], a[7], a[57]); // Sum(64) res[65] = fma52hi(res[65], a[7], a[57]); // Sum(64) res[65] = fma52lo(res[65], a[8], a[57]); // Sum(65) res[66] = fma52hi(res[66], a[8], a[57]); // Sum(65) res[66] = fma52lo(res[66], a[9], a[57]); // Sum(66) res[67] = fma52hi(res[67], a[9], a[57]); // Sum(66) res[67] = fma52lo(res[67], a[10], a[57]); // Sum(67) res[68] = fma52hi(res[68], a[10], a[57]); // Sum(67) res[68] = fma52lo(res[68], a[11], a[57]); // Sum(68) res[69] = fma52hi(res[69], a[11], a[57]); // Sum(68) res[69] = fma52lo(res[69], a[12], a[57]); // Sum(69) res[70] = fma52hi(res[70], a[12], a[57]); // Sum(69) res[70] = fma52lo(res[70], a[13], a[57]); // Sum(70) res[71] = fma52hi(res[71], a[13], a[57]); // Sum(70) res[71] = fma52lo(res[71], a[14], a[57]); // Sum(71) res[72] = fma52hi(res[72], a[14], a[57]); // Sum(71) res[60] = fma52lo(res[60], a[2], a[58]); // Sum(60) res[61] = fma52hi(res[61], a[2], a[58]); // Sum(60) res[61] = fma52lo(res[61], a[3], a[58]); // Sum(61) res[62] = fma52hi(res[62], a[3], a[58]); // Sum(61) res[62] = fma52lo(res[62], a[4], a[58]); // Sum(62) res[63] = fma52hi(res[63], a[4], a[58]); // Sum(62) res[63] = fma52lo(res[63], a[5], a[58]); // Sum(63) res[64] = fma52hi(res[64], a[5], a[58]); // Sum(63) res[64] = fma52lo(res[64], a[6], a[58]); // Sum(64) res[65] = fma52hi(res[65], a[6], a[58]); // Sum(64) res[65] = fma52lo(res[65], a[7], a[58]); // Sum(65) res[66] = fma52hi(res[66], a[7], a[58]); // Sum(65) res[66] = fma52lo(res[66], a[8], a[58]); // Sum(66) res[67] = fma52hi(res[67], a[8], a[58]); // Sum(66) res[67] = fma52lo(res[67], a[9], a[58]); // Sum(67) res[68] = fma52hi(res[68], a[9], a[58]); // Sum(67) res[68] = fma52lo(res[68], a[10], a[58]); // Sum(68) res[69] = fma52hi(res[69], a[10], a[58]); // Sum(68) res[69] = fma52lo(res[69], a[11], a[58]); // Sum(69) res[70] = fma52hi(res[70], a[11], a[58]); // Sum(69) res[70] = fma52lo(res[70], a[12], a[58]); // Sum(70) res[71] = fma52hi(res[71], a[12], a[58]); // Sum(70) res[71] = fma52lo(res[71], a[13], a[58]); // Sum(71) res[72] = fma52hi(res[72], a[13], a[58]); // Sum(71) res[60] = fma52lo(res[60], a[1], a[59]); // Sum(60) res[61] = fma52hi(res[61], a[1], a[59]); // Sum(60) res[61] = fma52lo(res[61], a[2], a[59]); // Sum(61) res[62] = fma52hi(res[62], a[2], a[59]); // Sum(61) res[62] = fma52lo(res[62], a[3], a[59]); // Sum(62) res[63] = fma52hi(res[63], a[3], a[59]); // Sum(62) res[63] = fma52lo(res[63], a[4], a[59]); // Sum(63) res[64] = fma52hi(res[64], a[4], a[59]); // Sum(63) res[64] = fma52lo(res[64], a[5], a[59]); // Sum(64) res[65] = fma52hi(res[65], a[5], a[59]); // Sum(64) res[65] = fma52lo(res[65], a[6], a[59]); // Sum(65) res[66] = fma52hi(res[66], a[6], a[59]); // Sum(65) res[66] = fma52lo(res[66], a[7], a[59]); // Sum(66) res[67] = fma52hi(res[67], a[7], a[59]); // Sum(66) res[67] = fma52lo(res[67], a[8], a[59]); // Sum(67) res[68] = fma52hi(res[68], a[8], a[59]); // Sum(67) res[68] = fma52lo(res[68], a[9], a[59]); // Sum(68) res[69] = fma52hi(res[69], a[9], a[59]); // Sum(68) res[69] = fma52lo(res[69], a[10], a[59]); // Sum(69) res[70] = fma52hi(res[70], a[10], a[59]); // Sum(69) res[70] = fma52lo(res[70], a[11], a[59]); // Sum(70) res[71] = fma52hi(res[71], a[11], a[59]); // Sum(70) res[71] = fma52lo(res[71], a[12], a[59]); // Sum(71) res[72] = fma52hi(res[72], a[12], a[59]); // Sum(71) res[60] = add64(res[60], res[60]); // Double(60) res[61] = add64(res[61], res[61]); // Double(61) res[62] = add64(res[62], res[62]); // Double(62) res[63] = add64(res[63], res[63]); // Double(63) res[64] = add64(res[64], res[64]); // Double(64) res[65] = add64(res[65], res[65]); // Double(65) res[66] = add64(res[66], res[66]); // Double(66) res[67] = add64(res[67], res[67]); // Double(67) res[68] = add64(res[68], res[68]); // Double(68) res[69] = add64(res[69], res[69]); // Double(69) res[70] = add64(res[70], res[70]); // Double(70) res[71] = add64(res[71], res[71]); // Double(71) res[60] = fma52lo(res[60], a[30], a[30]); // Add sqr(60) res[61] = fma52hi(res[61], a[30], a[30]); // Add sqr(60) res[62] = fma52lo(res[62], a[31], a[31]); // Add sqr(62) res[63] = fma52hi(res[63], a[31], a[31]); // Add sqr(62) res[64] = fma52lo(res[64], a[32], a[32]); // Add sqr(64) res[65] = fma52hi(res[65], a[32], a[32]); // Add sqr(64) res[66] = fma52lo(res[66], a[33], a[33]); // Add sqr(66) res[67] = fma52hi(res[67], a[33], a[33]); // Add sqr(66) res[68] = fma52lo(res[68], a[34], a[34]); // Add sqr(68) res[69] = fma52hi(res[69], a[34], a[34]); // Add sqr(68) res[70] = fma52lo(res[70], a[35], a[35]); // Add sqr(70) res[71] = fma52hi(res[71], a[35], a[35]); // Add sqr(70) res[72] = fma52lo(res[72], a[35], a[37]); // Sum(72) res[73] = fma52hi(res[73], a[35], a[37]); // Sum(72) res[73] = fma52lo(res[73], a[36], a[37]); // Sum(73) res[74] = fma52hi(res[74], a[36], a[37]); // Sum(73) res[72] = fma52lo(res[72], a[34], a[38]); // Sum(72) res[73] = fma52hi(res[73], a[34], a[38]); // Sum(72) res[73] = fma52lo(res[73], a[35], a[38]); // Sum(73) res[74] = fma52hi(res[74], a[35], a[38]); // Sum(73) res[74] = fma52lo(res[74], a[36], a[38]); // Sum(74) res[75] = fma52hi(res[75], a[36], a[38]); // Sum(74) res[75] = fma52lo(res[75], a[37], a[38]); // Sum(75) res[76] = fma52hi(res[76], a[37], a[38]); // Sum(75) res[72] = fma52lo(res[72], a[33], a[39]); // Sum(72) res[73] = fma52hi(res[73], a[33], a[39]); // Sum(72) res[73] = fma52lo(res[73], a[34], a[39]); // Sum(73) res[74] = fma52hi(res[74], a[34], a[39]); // Sum(73) res[74] = fma52lo(res[74], a[35], a[39]); // Sum(74) res[75] = fma52hi(res[75], a[35], a[39]); // Sum(74) res[75] = fma52lo(res[75], a[36], a[39]); // Sum(75) res[76] = fma52hi(res[76], a[36], a[39]); // Sum(75) res[76] = fma52lo(res[76], a[37], a[39]); // Sum(76) res[77] = fma52hi(res[77], a[37], a[39]); // Sum(76) res[77] = fma52lo(res[77], a[38], a[39]); // Sum(77) res[78] = fma52hi(res[78], a[38], a[39]); // Sum(77) res[72] = fma52lo(res[72], a[32], a[40]); // Sum(72) res[73] = fma52hi(res[73], a[32], a[40]); // Sum(72) res[73] = fma52lo(res[73], a[33], a[40]); // Sum(73) res[74] = fma52hi(res[74], a[33], a[40]); // Sum(73) res[74] = fma52lo(res[74], a[34], a[40]); // Sum(74) res[75] = fma52hi(res[75], a[34], a[40]); // Sum(74) res[75] = fma52lo(res[75], a[35], a[40]); // Sum(75) res[76] = fma52hi(res[76], a[35], a[40]); // Sum(75) res[76] = fma52lo(res[76], a[36], a[40]); // Sum(76) res[77] = fma52hi(res[77], a[36], a[40]); // Sum(76) res[77] = fma52lo(res[77], a[37], a[40]); // Sum(77) res[78] = fma52hi(res[78], a[37], a[40]); // Sum(77) res[78] = fma52lo(res[78], a[38], a[40]); // Sum(78) res[79] = fma52hi(res[79], a[38], a[40]); // Sum(78) res[79] = fma52lo(res[79], a[39], a[40]); // Sum(79) res[80] = fma52hi(res[80], a[39], a[40]); // Sum(79) res[72] = fma52lo(res[72], a[31], a[41]); // Sum(72) res[73] = fma52hi(res[73], a[31], a[41]); // Sum(72) res[73] = fma52lo(res[73], a[32], a[41]); // Sum(73) res[74] = fma52hi(res[74], a[32], a[41]); // Sum(73) res[74] = fma52lo(res[74], a[33], a[41]); // Sum(74) res[75] = fma52hi(res[75], a[33], a[41]); // Sum(74) res[75] = fma52lo(res[75], a[34], a[41]); // Sum(75) res[76] = fma52hi(res[76], a[34], a[41]); // Sum(75) res[76] = fma52lo(res[76], a[35], a[41]); // Sum(76) res[77] = fma52hi(res[77], a[35], a[41]); // Sum(76) res[77] = fma52lo(res[77], a[36], a[41]); // Sum(77) res[78] = fma52hi(res[78], a[36], a[41]); // Sum(77) res[78] = fma52lo(res[78], a[37], a[41]); // Sum(78) res[79] = fma52hi(res[79], a[37], a[41]); // Sum(78) res[79] = fma52lo(res[79], a[38], a[41]); // Sum(79) res[80] = fma52hi(res[80], a[38], a[41]); // Sum(79) res[80] = fma52lo(res[80], a[39], a[41]); // Sum(80) res[81] = fma52hi(res[81], a[39], a[41]); // Sum(80) res[81] = fma52lo(res[81], a[40], a[41]); // Sum(81) res[82] = fma52hi(res[82], a[40], a[41]); // Sum(81) res[72] = fma52lo(res[72], a[30], a[42]); // Sum(72) res[73] = fma52hi(res[73], a[30], a[42]); // Sum(72) res[73] = fma52lo(res[73], a[31], a[42]); // Sum(73) res[74] = fma52hi(res[74], a[31], a[42]); // Sum(73) res[74] = fma52lo(res[74], a[32], a[42]); // Sum(74) res[75] = fma52hi(res[75], a[32], a[42]); // Sum(74) res[75] = fma52lo(res[75], a[33], a[42]); // Sum(75) res[76] = fma52hi(res[76], a[33], a[42]); // Sum(75) res[76] = fma52lo(res[76], a[34], a[42]); // Sum(76) res[77] = fma52hi(res[77], a[34], a[42]); // Sum(76) res[77] = fma52lo(res[77], a[35], a[42]); // Sum(77) res[78] = fma52hi(res[78], a[35], a[42]); // Sum(77) res[78] = fma52lo(res[78], a[36], a[42]); // Sum(78) res[79] = fma52hi(res[79], a[36], a[42]); // Sum(78) res[79] = fma52lo(res[79], a[37], a[42]); // Sum(79) res[80] = fma52hi(res[80], a[37], a[42]); // Sum(79) res[80] = fma52lo(res[80], a[38], a[42]); // Sum(80) res[81] = fma52hi(res[81], a[38], a[42]); // Sum(80) res[81] = fma52lo(res[81], a[39], a[42]); // Sum(81) res[82] = fma52hi(res[82], a[39], a[42]); // Sum(81) res[82] = fma52lo(res[82], a[40], a[42]); // Sum(82) res[83] = fma52hi(res[83], a[40], a[42]); // Sum(82) res[83] = fma52lo(res[83], a[41], a[42]); // Sum(83) res[84] = fma52hi(res[84], a[41], a[42]); // Sum(83) res[72] = fma52lo(res[72], a[29], a[43]); // Sum(72) res[73] = fma52hi(res[73], a[29], a[43]); // Sum(72) res[73] = fma52lo(res[73], a[30], a[43]); // Sum(73) res[74] = fma52hi(res[74], a[30], a[43]); // Sum(73) res[74] = fma52lo(res[74], a[31], a[43]); // Sum(74) res[75] = fma52hi(res[75], a[31], a[43]); // Sum(74) res[75] = fma52lo(res[75], a[32], a[43]); // Sum(75) res[76] = fma52hi(res[76], a[32], a[43]); // Sum(75) res[76] = fma52lo(res[76], a[33], a[43]); // Sum(76) res[77] = fma52hi(res[77], a[33], a[43]); // Sum(76) res[77] = fma52lo(res[77], a[34], a[43]); // Sum(77) res[78] = fma52hi(res[78], a[34], a[43]); // Sum(77) res[78] = fma52lo(res[78], a[35], a[43]); // Sum(78) res[79] = fma52hi(res[79], a[35], a[43]); // Sum(78) res[79] = fma52lo(res[79], a[36], a[43]); // Sum(79) res[80] = fma52hi(res[80], a[36], a[43]); // Sum(79) res[80] = fma52lo(res[80], a[37], a[43]); // Sum(80) res[81] = fma52hi(res[81], a[37], a[43]); // Sum(80) res[81] = fma52lo(res[81], a[38], a[43]); // Sum(81) res[82] = fma52hi(res[82], a[38], a[43]); // Sum(81) res[82] = fma52lo(res[82], a[39], a[43]); // Sum(82) res[83] = fma52hi(res[83], a[39], a[43]); // Sum(82) res[83] = fma52lo(res[83], a[40], a[43]); // Sum(83) res[84] = fma52hi(res[84], a[40], a[43]); // Sum(83) res[72] = fma52lo(res[72], a[28], a[44]); // Sum(72) res[73] = fma52hi(res[73], a[28], a[44]); // Sum(72) res[73] = fma52lo(res[73], a[29], a[44]); // Sum(73) res[74] = fma52hi(res[74], a[29], a[44]); // Sum(73) res[74] = fma52lo(res[74], a[30], a[44]); // Sum(74) res[75] = fma52hi(res[75], a[30], a[44]); // Sum(74) res[75] = fma52lo(res[75], a[31], a[44]); // Sum(75) res[76] = fma52hi(res[76], a[31], a[44]); // Sum(75) res[76] = fma52lo(res[76], a[32], a[44]); // Sum(76) res[77] = fma52hi(res[77], a[32], a[44]); // Sum(76) res[77] = fma52lo(res[77], a[33], a[44]); // Sum(77) res[78] = fma52hi(res[78], a[33], a[44]); // Sum(77) res[78] = fma52lo(res[78], a[34], a[44]); // Sum(78) res[79] = fma52hi(res[79], a[34], a[44]); // Sum(78) res[79] = fma52lo(res[79], a[35], a[44]); // Sum(79) res[80] = fma52hi(res[80], a[35], a[44]); // Sum(79) res[80] = fma52lo(res[80], a[36], a[44]); // Sum(80) res[81] = fma52hi(res[81], a[36], a[44]); // Sum(80) res[81] = fma52lo(res[81], a[37], a[44]); // Sum(81) res[82] = fma52hi(res[82], a[37], a[44]); // Sum(81) res[82] = fma52lo(res[82], a[38], a[44]); // Sum(82) res[83] = fma52hi(res[83], a[38], a[44]); // Sum(82) res[83] = fma52lo(res[83], a[39], a[44]); // Sum(83) res[84] = fma52hi(res[84], a[39], a[44]); // Sum(83) res[72] = fma52lo(res[72], a[27], a[45]); // Sum(72) res[73] = fma52hi(res[73], a[27], a[45]); // Sum(72) res[73] = fma52lo(res[73], a[28], a[45]); // Sum(73) res[74] = fma52hi(res[74], a[28], a[45]); // Sum(73) res[74] = fma52lo(res[74], a[29], a[45]); // Sum(74) res[75] = fma52hi(res[75], a[29], a[45]); // Sum(74) res[75] = fma52lo(res[75], a[30], a[45]); // Sum(75) res[76] = fma52hi(res[76], a[30], a[45]); // Sum(75) res[76] = fma52lo(res[76], a[31], a[45]); // Sum(76) res[77] = fma52hi(res[77], a[31], a[45]); // Sum(76) res[77] = fma52lo(res[77], a[32], a[45]); // Sum(77) res[78] = fma52hi(res[78], a[32], a[45]); // Sum(77) res[78] = fma52lo(res[78], a[33], a[45]); // Sum(78) res[79] = fma52hi(res[79], a[33], a[45]); // Sum(78) res[79] = fma52lo(res[79], a[34], a[45]); // Sum(79) res[80] = fma52hi(res[80], a[34], a[45]); // Sum(79) res[80] = fma52lo(res[80], a[35], a[45]); // Sum(80) res[81] = fma52hi(res[81], a[35], a[45]); // Sum(80) res[81] = fma52lo(res[81], a[36], a[45]); // Sum(81) res[82] = fma52hi(res[82], a[36], a[45]); // Sum(81) res[82] = fma52lo(res[82], a[37], a[45]); // Sum(82) res[83] = fma52hi(res[83], a[37], a[45]); // Sum(82) res[83] = fma52lo(res[83], a[38], a[45]); // Sum(83) res[84] = fma52hi(res[84], a[38], a[45]); // Sum(83) res[72] = fma52lo(res[72], a[26], a[46]); // Sum(72) res[73] = fma52hi(res[73], a[26], a[46]); // Sum(72) res[73] = fma52lo(res[73], a[27], a[46]); // Sum(73) res[74] = fma52hi(res[74], a[27], a[46]); // Sum(73) res[74] = fma52lo(res[74], a[28], a[46]); // Sum(74) res[75] = fma52hi(res[75], a[28], a[46]); // Sum(74) res[75] = fma52lo(res[75], a[29], a[46]); // Sum(75) res[76] = fma52hi(res[76], a[29], a[46]); // Sum(75) res[76] = fma52lo(res[76], a[30], a[46]); // Sum(76) res[77] = fma52hi(res[77], a[30], a[46]); // Sum(76) res[77] = fma52lo(res[77], a[31], a[46]); // Sum(77) res[78] = fma52hi(res[78], a[31], a[46]); // Sum(77) res[78] = fma52lo(res[78], a[32], a[46]); // Sum(78) res[79] = fma52hi(res[79], a[32], a[46]); // Sum(78) res[79] = fma52lo(res[79], a[33], a[46]); // Sum(79) res[80] = fma52hi(res[80], a[33], a[46]); // Sum(79) res[80] = fma52lo(res[80], a[34], a[46]); // Sum(80) res[81] = fma52hi(res[81], a[34], a[46]); // Sum(80) res[81] = fma52lo(res[81], a[35], a[46]); // Sum(81) res[82] = fma52hi(res[82], a[35], a[46]); // Sum(81) res[82] = fma52lo(res[82], a[36], a[46]); // Sum(82) res[83] = fma52hi(res[83], a[36], a[46]); // Sum(82) res[83] = fma52lo(res[83], a[37], a[46]); // Sum(83) res[84] = fma52hi(res[84], a[37], a[46]); // Sum(83) res[72] = fma52lo(res[72], a[25], a[47]); // Sum(72) res[73] = fma52hi(res[73], a[25], a[47]); // Sum(72) res[73] = fma52lo(res[73], a[26], a[47]); // Sum(73) res[74] = fma52hi(res[74], a[26], a[47]); // Sum(73) res[74] = fma52lo(res[74], a[27], a[47]); // Sum(74) res[75] = fma52hi(res[75], a[27], a[47]); // Sum(74) res[75] = fma52lo(res[75], a[28], a[47]); // Sum(75) res[76] = fma52hi(res[76], a[28], a[47]); // Sum(75) res[76] = fma52lo(res[76], a[29], a[47]); // Sum(76) res[77] = fma52hi(res[77], a[29], a[47]); // Sum(76) res[77] = fma52lo(res[77], a[30], a[47]); // Sum(77) res[78] = fma52hi(res[78], a[30], a[47]); // Sum(77) res[78] = fma52lo(res[78], a[31], a[47]); // Sum(78) res[79] = fma52hi(res[79], a[31], a[47]); // Sum(78) res[79] = fma52lo(res[79], a[32], a[47]); // Sum(79) res[80] = fma52hi(res[80], a[32], a[47]); // Sum(79) res[80] = fma52lo(res[80], a[33], a[47]); // Sum(80) res[81] = fma52hi(res[81], a[33], a[47]); // Sum(80) res[81] = fma52lo(res[81], a[34], a[47]); // Sum(81) res[82] = fma52hi(res[82], a[34], a[47]); // Sum(81) res[82] = fma52lo(res[82], a[35], a[47]); // Sum(82) res[83] = fma52hi(res[83], a[35], a[47]); // Sum(82) res[83] = fma52lo(res[83], a[36], a[47]); // Sum(83) res[84] = fma52hi(res[84], a[36], a[47]); // Sum(83) res[72] = fma52lo(res[72], a[24], a[48]); // Sum(72) res[73] = fma52hi(res[73], a[24], a[48]); // Sum(72) res[73] = fma52lo(res[73], a[25], a[48]); // Sum(73) res[74] = fma52hi(res[74], a[25], a[48]); // Sum(73) res[74] = fma52lo(res[74], a[26], a[48]); // Sum(74) res[75] = fma52hi(res[75], a[26], a[48]); // Sum(74) res[75] = fma52lo(res[75], a[27], a[48]); // Sum(75) res[76] = fma52hi(res[76], a[27], a[48]); // Sum(75) res[76] = fma52lo(res[76], a[28], a[48]); // Sum(76) res[77] = fma52hi(res[77], a[28], a[48]); // Sum(76) res[77] = fma52lo(res[77], a[29], a[48]); // Sum(77) res[78] = fma52hi(res[78], a[29], a[48]); // Sum(77) res[78] = fma52lo(res[78], a[30], a[48]); // Sum(78) res[79] = fma52hi(res[79], a[30], a[48]); // Sum(78) res[79] = fma52lo(res[79], a[31], a[48]); // Sum(79) res[80] = fma52hi(res[80], a[31], a[48]); // Sum(79) res[80] = fma52lo(res[80], a[32], a[48]); // Sum(80) res[81] = fma52hi(res[81], a[32], a[48]); // Sum(80) res[81] = fma52lo(res[81], a[33], a[48]); // Sum(81) res[82] = fma52hi(res[82], a[33], a[48]); // Sum(81) res[82] = fma52lo(res[82], a[34], a[48]); // Sum(82) res[83] = fma52hi(res[83], a[34], a[48]); // Sum(82) res[83] = fma52lo(res[83], a[35], a[48]); // Sum(83) res[84] = fma52hi(res[84], a[35], a[48]); // Sum(83) res[72] = fma52lo(res[72], a[23], a[49]); // Sum(72) res[73] = fma52hi(res[73], a[23], a[49]); // Sum(72) res[73] = fma52lo(res[73], a[24], a[49]); // Sum(73) res[74] = fma52hi(res[74], a[24], a[49]); // Sum(73) res[74] = fma52lo(res[74], a[25], a[49]); // Sum(74) res[75] = fma52hi(res[75], a[25], a[49]); // Sum(74) res[75] = fma52lo(res[75], a[26], a[49]); // Sum(75) res[76] = fma52hi(res[76], a[26], a[49]); // Sum(75) res[76] = fma52lo(res[76], a[27], a[49]); // Sum(76) res[77] = fma52hi(res[77], a[27], a[49]); // Sum(76) res[77] = fma52lo(res[77], a[28], a[49]); // Sum(77) res[78] = fma52hi(res[78], a[28], a[49]); // Sum(77) res[78] = fma52lo(res[78], a[29], a[49]); // Sum(78) res[79] = fma52hi(res[79], a[29], a[49]); // Sum(78) res[79] = fma52lo(res[79], a[30], a[49]); // Sum(79) res[80] = fma52hi(res[80], a[30], a[49]); // Sum(79) res[80] = fma52lo(res[80], a[31], a[49]); // Sum(80) res[81] = fma52hi(res[81], a[31], a[49]); // Sum(80) res[81] = fma52lo(res[81], a[32], a[49]); // Sum(81) res[82] = fma52hi(res[82], a[32], a[49]); // Sum(81) res[82] = fma52lo(res[82], a[33], a[49]); // Sum(82) res[83] = fma52hi(res[83], a[33], a[49]); // Sum(82) res[83] = fma52lo(res[83], a[34], a[49]); // Sum(83) res[84] = fma52hi(res[84], a[34], a[49]); // Sum(83) res[72] = fma52lo(res[72], a[22], a[50]); // Sum(72) res[73] = fma52hi(res[73], a[22], a[50]); // Sum(72) res[73] = fma52lo(res[73], a[23], a[50]); // Sum(73) res[74] = fma52hi(res[74], a[23], a[50]); // Sum(73) res[74] = fma52lo(res[74], a[24], a[50]); // Sum(74) res[75] = fma52hi(res[75], a[24], a[50]); // Sum(74) res[75] = fma52lo(res[75], a[25], a[50]); // Sum(75) res[76] = fma52hi(res[76], a[25], a[50]); // Sum(75) res[76] = fma52lo(res[76], a[26], a[50]); // Sum(76) res[77] = fma52hi(res[77], a[26], a[50]); // Sum(76) res[77] = fma52lo(res[77], a[27], a[50]); // Sum(77) res[78] = fma52hi(res[78], a[27], a[50]); // Sum(77) res[78] = fma52lo(res[78], a[28], a[50]); // Sum(78) res[79] = fma52hi(res[79], a[28], a[50]); // Sum(78) res[79] = fma52lo(res[79], a[29], a[50]); // Sum(79) res[80] = fma52hi(res[80], a[29], a[50]); // Sum(79) res[80] = fma52lo(res[80], a[30], a[50]); // Sum(80) res[81] = fma52hi(res[81], a[30], a[50]); // Sum(80) res[81] = fma52lo(res[81], a[31], a[50]); // Sum(81) res[82] = fma52hi(res[82], a[31], a[50]); // Sum(81) res[82] = fma52lo(res[82], a[32], a[50]); // Sum(82) res[83] = fma52hi(res[83], a[32], a[50]); // Sum(82) res[83] = fma52lo(res[83], a[33], a[50]); // Sum(83) res[84] = fma52hi(res[84], a[33], a[50]); // Sum(83) res[72] = fma52lo(res[72], a[21], a[51]); // Sum(72) res[73] = fma52hi(res[73], a[21], a[51]); // Sum(72) res[73] = fma52lo(res[73], a[22], a[51]); // Sum(73) res[74] = fma52hi(res[74], a[22], a[51]); // Sum(73) res[74] = fma52lo(res[74], a[23], a[51]); // Sum(74) res[75] = fma52hi(res[75], a[23], a[51]); // Sum(74) res[75] = fma52lo(res[75], a[24], a[51]); // Sum(75) res[76] = fma52hi(res[76], a[24], a[51]); // Sum(75) res[76] = fma52lo(res[76], a[25], a[51]); // Sum(76) res[77] = fma52hi(res[77], a[25], a[51]); // Sum(76) res[77] = fma52lo(res[77], a[26], a[51]); // Sum(77) res[78] = fma52hi(res[78], a[26], a[51]); // Sum(77) res[78] = fma52lo(res[78], a[27], a[51]); // Sum(78) res[79] = fma52hi(res[79], a[27], a[51]); // Sum(78) res[79] = fma52lo(res[79], a[28], a[51]); // Sum(79) res[80] = fma52hi(res[80], a[28], a[51]); // Sum(79) res[80] = fma52lo(res[80], a[29], a[51]); // Sum(80) res[81] = fma52hi(res[81], a[29], a[51]); // Sum(80) res[81] = fma52lo(res[81], a[30], a[51]); // Sum(81) res[82] = fma52hi(res[82], a[30], a[51]); // Sum(81) res[82] = fma52lo(res[82], a[31], a[51]); // Sum(82) res[83] = fma52hi(res[83], a[31], a[51]); // Sum(82) res[83] = fma52lo(res[83], a[32], a[51]); // Sum(83) res[84] = fma52hi(res[84], a[32], a[51]); // Sum(83) res[72] = fma52lo(res[72], a[20], a[52]); // Sum(72) res[73] = fma52hi(res[73], a[20], a[52]); // Sum(72) res[73] = fma52lo(res[73], a[21], a[52]); // Sum(73) res[74] = fma52hi(res[74], a[21], a[52]); // Sum(73) res[74] = fma52lo(res[74], a[22], a[52]); // Sum(74) res[75] = fma52hi(res[75], a[22], a[52]); // Sum(74) res[75] = fma52lo(res[75], a[23], a[52]); // Sum(75) res[76] = fma52hi(res[76], a[23], a[52]); // Sum(75) res[76] = fma52lo(res[76], a[24], a[52]); // Sum(76) res[77] = fma52hi(res[77], a[24], a[52]); // Sum(76) res[77] = fma52lo(res[77], a[25], a[52]); // Sum(77) res[78] = fma52hi(res[78], a[25], a[52]); // Sum(77) res[78] = fma52lo(res[78], a[26], a[52]); // Sum(78) res[79] = fma52hi(res[79], a[26], a[52]); // Sum(78) res[79] = fma52lo(res[79], a[27], a[52]); // Sum(79) res[80] = fma52hi(res[80], a[27], a[52]); // Sum(79) res[80] = fma52lo(res[80], a[28], a[52]); // Sum(80) res[81] = fma52hi(res[81], a[28], a[52]); // Sum(80) res[81] = fma52lo(res[81], a[29], a[52]); // Sum(81) res[82] = fma52hi(res[82], a[29], a[52]); // Sum(81) res[82] = fma52lo(res[82], a[30], a[52]); // Sum(82) res[83] = fma52hi(res[83], a[30], a[52]); // Sum(82) res[83] = fma52lo(res[83], a[31], a[52]); // Sum(83) res[84] = fma52hi(res[84], a[31], a[52]); // Sum(83) res[72] = fma52lo(res[72], a[19], a[53]); // Sum(72) res[73] = fma52hi(res[73], a[19], a[53]); // Sum(72) res[73] = fma52lo(res[73], a[20], a[53]); // Sum(73) res[74] = fma52hi(res[74], a[20], a[53]); // Sum(73) res[74] = fma52lo(res[74], a[21], a[53]); // Sum(74) res[75] = fma52hi(res[75], a[21], a[53]); // Sum(74) res[75] = fma52lo(res[75], a[22], a[53]); // Sum(75) res[76] = fma52hi(res[76], a[22], a[53]); // Sum(75) res[76] = fma52lo(res[76], a[23], a[53]); // Sum(76) res[77] = fma52hi(res[77], a[23], a[53]); // Sum(76) res[77] = fma52lo(res[77], a[24], a[53]); // Sum(77) res[78] = fma52hi(res[78], a[24], a[53]); // Sum(77) res[78] = fma52lo(res[78], a[25], a[53]); // Sum(78) res[79] = fma52hi(res[79], a[25], a[53]); // Sum(78) res[79] = fma52lo(res[79], a[26], a[53]); // Sum(79) res[80] = fma52hi(res[80], a[26], a[53]); // Sum(79) res[80] = fma52lo(res[80], a[27], a[53]); // Sum(80) res[81] = fma52hi(res[81], a[27], a[53]); // Sum(80) res[81] = fma52lo(res[81], a[28], a[53]); // Sum(81) res[82] = fma52hi(res[82], a[28], a[53]); // Sum(81) res[82] = fma52lo(res[82], a[29], a[53]); // Sum(82) res[83] = fma52hi(res[83], a[29], a[53]); // Sum(82) res[83] = fma52lo(res[83], a[30], a[53]); // Sum(83) res[84] = fma52hi(res[84], a[30], a[53]); // Sum(83) res[72] = fma52lo(res[72], a[18], a[54]); // Sum(72) res[73] = fma52hi(res[73], a[18], a[54]); // Sum(72) res[73] = fma52lo(res[73], a[19], a[54]); // Sum(73) res[74] = fma52hi(res[74], a[19], a[54]); // Sum(73) res[74] = fma52lo(res[74], a[20], a[54]); // Sum(74) res[75] = fma52hi(res[75], a[20], a[54]); // Sum(74) res[75] = fma52lo(res[75], a[21], a[54]); // Sum(75) res[76] = fma52hi(res[76], a[21], a[54]); // Sum(75) res[76] = fma52lo(res[76], a[22], a[54]); // Sum(76) res[77] = fma52hi(res[77], a[22], a[54]); // Sum(76) res[77] = fma52lo(res[77], a[23], a[54]); // Sum(77) res[78] = fma52hi(res[78], a[23], a[54]); // Sum(77) res[78] = fma52lo(res[78], a[24], a[54]); // Sum(78) res[79] = fma52hi(res[79], a[24], a[54]); // Sum(78) res[79] = fma52lo(res[79], a[25], a[54]); // Sum(79) res[80] = fma52hi(res[80], a[25], a[54]); // Sum(79) res[80] = fma52lo(res[80], a[26], a[54]); // Sum(80) res[81] = fma52hi(res[81], a[26], a[54]); // Sum(80) res[81] = fma52lo(res[81], a[27], a[54]); // Sum(81) res[82] = fma52hi(res[82], a[27], a[54]); // Sum(81) res[82] = fma52lo(res[82], a[28], a[54]); // Sum(82) res[83] = fma52hi(res[83], a[28], a[54]); // Sum(82) res[83] = fma52lo(res[83], a[29], a[54]); // Sum(83) res[84] = fma52hi(res[84], a[29], a[54]); // Sum(83) res[72] = fma52lo(res[72], a[17], a[55]); // Sum(72) res[73] = fma52hi(res[73], a[17], a[55]); // Sum(72) res[73] = fma52lo(res[73], a[18], a[55]); // Sum(73) res[74] = fma52hi(res[74], a[18], a[55]); // Sum(73) res[74] = fma52lo(res[74], a[19], a[55]); // Sum(74) res[75] = fma52hi(res[75], a[19], a[55]); // Sum(74) res[75] = fma52lo(res[75], a[20], a[55]); // Sum(75) res[76] = fma52hi(res[76], a[20], a[55]); // Sum(75) res[76] = fma52lo(res[76], a[21], a[55]); // Sum(76) res[77] = fma52hi(res[77], a[21], a[55]); // Sum(76) res[77] = fma52lo(res[77], a[22], a[55]); // Sum(77) res[78] = fma52hi(res[78], a[22], a[55]); // Sum(77) res[78] = fma52lo(res[78], a[23], a[55]); // Sum(78) res[79] = fma52hi(res[79], a[23], a[55]); // Sum(78) res[79] = fma52lo(res[79], a[24], a[55]); // Sum(79) res[80] = fma52hi(res[80], a[24], a[55]); // Sum(79) res[80] = fma52lo(res[80], a[25], a[55]); // Sum(80) res[81] = fma52hi(res[81], a[25], a[55]); // Sum(80) res[81] = fma52lo(res[81], a[26], a[55]); // Sum(81) res[82] = fma52hi(res[82], a[26], a[55]); // Sum(81) res[82] = fma52lo(res[82], a[27], a[55]); // Sum(82) res[83] = fma52hi(res[83], a[27], a[55]); // Sum(82) res[83] = fma52lo(res[83], a[28], a[55]); // Sum(83) res[84] = fma52hi(res[84], a[28], a[55]); // Sum(83) res[72] = fma52lo(res[72], a[16], a[56]); // Sum(72) res[73] = fma52hi(res[73], a[16], a[56]); // Sum(72) res[73] = fma52lo(res[73], a[17], a[56]); // Sum(73) res[74] = fma52hi(res[74], a[17], a[56]); // Sum(73) res[74] = fma52lo(res[74], a[18], a[56]); // Sum(74) res[75] = fma52hi(res[75], a[18], a[56]); // Sum(74) res[75] = fma52lo(res[75], a[19], a[56]); // Sum(75) res[76] = fma52hi(res[76], a[19], a[56]); // Sum(75) res[76] = fma52lo(res[76], a[20], a[56]); // Sum(76) res[77] = fma52hi(res[77], a[20], a[56]); // Sum(76) res[77] = fma52lo(res[77], a[21], a[56]); // Sum(77) res[78] = fma52hi(res[78], a[21], a[56]); // Sum(77) res[78] = fma52lo(res[78], a[22], a[56]); // Sum(78) res[79] = fma52hi(res[79], a[22], a[56]); // Sum(78) res[79] = fma52lo(res[79], a[23], a[56]); // Sum(79) res[80] = fma52hi(res[80], a[23], a[56]); // Sum(79) res[80] = fma52lo(res[80], a[24], a[56]); // Sum(80) res[81] = fma52hi(res[81], a[24], a[56]); // Sum(80) res[81] = fma52lo(res[81], a[25], a[56]); // Sum(81) res[82] = fma52hi(res[82], a[25], a[56]); // Sum(81) res[82] = fma52lo(res[82], a[26], a[56]); // Sum(82) res[83] = fma52hi(res[83], a[26], a[56]); // Sum(82) res[83] = fma52lo(res[83], a[27], a[56]); // Sum(83) res[84] = fma52hi(res[84], a[27], a[56]); // Sum(83) res[72] = fma52lo(res[72], a[15], a[57]); // Sum(72) res[73] = fma52hi(res[73], a[15], a[57]); // Sum(72) res[73] = fma52lo(res[73], a[16], a[57]); // Sum(73) res[74] = fma52hi(res[74], a[16], a[57]); // Sum(73) res[74] = fma52lo(res[74], a[17], a[57]); // Sum(74) res[75] = fma52hi(res[75], a[17], a[57]); // Sum(74) res[75] = fma52lo(res[75], a[18], a[57]); // Sum(75) res[76] = fma52hi(res[76], a[18], a[57]); // Sum(75) res[76] = fma52lo(res[76], a[19], a[57]); // Sum(76) res[77] = fma52hi(res[77], a[19], a[57]); // Sum(76) res[77] = fma52lo(res[77], a[20], a[57]); // Sum(77) res[78] = fma52hi(res[78], a[20], a[57]); // Sum(77) res[78] = fma52lo(res[78], a[21], a[57]); // Sum(78) res[79] = fma52hi(res[79], a[21], a[57]); // Sum(78) res[79] = fma52lo(res[79], a[22], a[57]); // Sum(79) res[80] = fma52hi(res[80], a[22], a[57]); // Sum(79) res[80] = fma52lo(res[80], a[23], a[57]); // Sum(80) res[81] = fma52hi(res[81], a[23], a[57]); // Sum(80) res[81] = fma52lo(res[81], a[24], a[57]); // Sum(81) res[82] = fma52hi(res[82], a[24], a[57]); // Sum(81) res[82] = fma52lo(res[82], a[25], a[57]); // Sum(82) res[83] = fma52hi(res[83], a[25], a[57]); // Sum(82) res[83] = fma52lo(res[83], a[26], a[57]); // Sum(83) res[84] = fma52hi(res[84], a[26], a[57]); // Sum(83) res[72] = fma52lo(res[72], a[14], a[58]); // Sum(72) res[73] = fma52hi(res[73], a[14], a[58]); // Sum(72) res[73] = fma52lo(res[73], a[15], a[58]); // Sum(73) res[74] = fma52hi(res[74], a[15], a[58]); // Sum(73) res[74] = fma52lo(res[74], a[16], a[58]); // Sum(74) res[75] = fma52hi(res[75], a[16], a[58]); // Sum(74) res[75] = fma52lo(res[75], a[17], a[58]); // Sum(75) res[76] = fma52hi(res[76], a[17], a[58]); // Sum(75) res[76] = fma52lo(res[76], a[18], a[58]); // Sum(76) res[77] = fma52hi(res[77], a[18], a[58]); // Sum(76) res[77] = fma52lo(res[77], a[19], a[58]); // Sum(77) res[78] = fma52hi(res[78], a[19], a[58]); // Sum(77) res[78] = fma52lo(res[78], a[20], a[58]); // Sum(78) res[79] = fma52hi(res[79], a[20], a[58]); // Sum(78) res[79] = fma52lo(res[79], a[21], a[58]); // Sum(79) res[80] = fma52hi(res[80], a[21], a[58]); // Sum(79) res[80] = fma52lo(res[80], a[22], a[58]); // Sum(80) res[81] = fma52hi(res[81], a[22], a[58]); // Sum(80) res[81] = fma52lo(res[81], a[23], a[58]); // Sum(81) res[82] = fma52hi(res[82], a[23], a[58]); // Sum(81) res[82] = fma52lo(res[82], a[24], a[58]); // Sum(82) res[83] = fma52hi(res[83], a[24], a[58]); // Sum(82) res[83] = fma52lo(res[83], a[25], a[58]); // Sum(83) res[84] = fma52hi(res[84], a[25], a[58]); // Sum(83) res[72] = fma52lo(res[72], a[13], a[59]); // Sum(72) res[73] = fma52hi(res[73], a[13], a[59]); // Sum(72) res[73] = fma52lo(res[73], a[14], a[59]); // Sum(73) res[74] = fma52hi(res[74], a[14], a[59]); // Sum(73) res[74] = fma52lo(res[74], a[15], a[59]); // Sum(74) res[75] = fma52hi(res[75], a[15], a[59]); // Sum(74) res[75] = fma52lo(res[75], a[16], a[59]); // Sum(75) res[76] = fma52hi(res[76], a[16], a[59]); // Sum(75) res[76] = fma52lo(res[76], a[17], a[59]); // Sum(76) res[77] = fma52hi(res[77], a[17], a[59]); // Sum(76) res[77] = fma52lo(res[77], a[18], a[59]); // Sum(77) res[78] = fma52hi(res[78], a[18], a[59]); // Sum(77) res[78] = fma52lo(res[78], a[19], a[59]); // Sum(78) res[79] = fma52hi(res[79], a[19], a[59]); // Sum(78) res[79] = fma52lo(res[79], a[20], a[59]); // Sum(79) res[80] = fma52hi(res[80], a[20], a[59]); // Sum(79) res[80] = fma52lo(res[80], a[21], a[59]); // Sum(80) res[81] = fma52hi(res[81], a[21], a[59]); // Sum(80) res[81] = fma52lo(res[81], a[22], a[59]); // Sum(81) res[82] = fma52hi(res[82], a[22], a[59]); // Sum(81) res[82] = fma52lo(res[82], a[23], a[59]); // Sum(82) res[83] = fma52hi(res[83], a[23], a[59]); // Sum(82) res[83] = fma52lo(res[83], a[24], a[59]); // Sum(83) res[84] = fma52hi(res[84], a[24], a[59]); // Sum(83) res[72] = add64(res[72], res[72]); // Double(72) res[73] = add64(res[73], res[73]); // Double(73) res[74] = add64(res[74], res[74]); // Double(74) res[75] = add64(res[75], res[75]); // Double(75) res[76] = add64(res[76], res[76]); // Double(76) res[77] = add64(res[77], res[77]); // Double(77) res[78] = add64(res[78], res[78]); // Double(78) res[79] = add64(res[79], res[79]); // Double(79) res[80] = add64(res[80], res[80]); // Double(80) res[81] = add64(res[81], res[81]); // Double(81) res[82] = add64(res[82], res[82]); // Double(82) res[83] = add64(res[83], res[83]); // Double(83) res[72] = fma52lo(res[72], a[36], a[36]); // Add sqr(72) res[73] = fma52hi(res[73], a[36], a[36]); // Add sqr(72) res[74] = fma52lo(res[74], a[37], a[37]); // Add sqr(74) res[75] = fma52hi(res[75], a[37], a[37]); // Add sqr(74) res[76] = fma52lo(res[76], a[38], a[38]); // Add sqr(76) res[77] = fma52hi(res[77], a[38], a[38]); // Add sqr(76) res[78] = fma52lo(res[78], a[39], a[39]); // Add sqr(78) res[79] = fma52hi(res[79], a[39], a[39]); // Add sqr(78) res[80] = fma52lo(res[80], a[40], a[40]); // Add sqr(80) res[81] = fma52hi(res[81], a[40], a[40]); // Add sqr(80) res[82] = fma52lo(res[82], a[41], a[41]); // Add sqr(82) res[83] = fma52hi(res[83], a[41], a[41]); // Add sqr(82) res[84] = fma52lo(res[84], a[41], a[43]); // Sum(84) res[85] = fma52hi(res[85], a[41], a[43]); // Sum(84) res[85] = fma52lo(res[85], a[42], a[43]); // Sum(85) res[86] = fma52hi(res[86], a[42], a[43]); // Sum(85) res[84] = fma52lo(res[84], a[40], a[44]); // Sum(84) res[85] = fma52hi(res[85], a[40], a[44]); // Sum(84) res[85] = fma52lo(res[85], a[41], a[44]); // Sum(85) res[86] = fma52hi(res[86], a[41], a[44]); // Sum(85) res[86] = fma52lo(res[86], a[42], a[44]); // Sum(86) res[87] = fma52hi(res[87], a[42], a[44]); // Sum(86) res[87] = fma52lo(res[87], a[43], a[44]); // Sum(87) res[88] = fma52hi(res[88], a[43], a[44]); // Sum(87) res[84] = fma52lo(res[84], a[39], a[45]); // Sum(84) res[85] = fma52hi(res[85], a[39], a[45]); // Sum(84) res[85] = fma52lo(res[85], a[40], a[45]); // Sum(85) res[86] = fma52hi(res[86], a[40], a[45]); // Sum(85) res[86] = fma52lo(res[86], a[41], a[45]); // Sum(86) res[87] = fma52hi(res[87], a[41], a[45]); // Sum(86) res[87] = fma52lo(res[87], a[42], a[45]); // Sum(87) res[88] = fma52hi(res[88], a[42], a[45]); // Sum(87) res[88] = fma52lo(res[88], a[43], a[45]); // Sum(88) res[89] = fma52hi(res[89], a[43], a[45]); // Sum(88) res[89] = fma52lo(res[89], a[44], a[45]); // Sum(89) res[90] = fma52hi(res[90], a[44], a[45]); // Sum(89) res[84] = fma52lo(res[84], a[38], a[46]); // Sum(84) res[85] = fma52hi(res[85], a[38], a[46]); // Sum(84) res[85] = fma52lo(res[85], a[39], a[46]); // Sum(85) res[86] = fma52hi(res[86], a[39], a[46]); // Sum(85) res[86] = fma52lo(res[86], a[40], a[46]); // Sum(86) res[87] = fma52hi(res[87], a[40], a[46]); // Sum(86) res[87] = fma52lo(res[87], a[41], a[46]); // Sum(87) res[88] = fma52hi(res[88], a[41], a[46]); // Sum(87) res[88] = fma52lo(res[88], a[42], a[46]); // Sum(88) res[89] = fma52hi(res[89], a[42], a[46]); // Sum(88) res[89] = fma52lo(res[89], a[43], a[46]); // Sum(89) res[90] = fma52hi(res[90], a[43], a[46]); // Sum(89) res[90] = fma52lo(res[90], a[44], a[46]); // Sum(90) res[91] = fma52hi(res[91], a[44], a[46]); // Sum(90) res[91] = fma52lo(res[91], a[45], a[46]); // Sum(91) res[92] = fma52hi(res[92], a[45], a[46]); // Sum(91) res[84] = fma52lo(res[84], a[37], a[47]); // Sum(84) res[85] = fma52hi(res[85], a[37], a[47]); // Sum(84) res[85] = fma52lo(res[85], a[38], a[47]); // Sum(85) res[86] = fma52hi(res[86], a[38], a[47]); // Sum(85) res[86] = fma52lo(res[86], a[39], a[47]); // Sum(86) res[87] = fma52hi(res[87], a[39], a[47]); // Sum(86) res[87] = fma52lo(res[87], a[40], a[47]); // Sum(87) res[88] = fma52hi(res[88], a[40], a[47]); // Sum(87) res[88] = fma52lo(res[88], a[41], a[47]); // Sum(88) res[89] = fma52hi(res[89], a[41], a[47]); // Sum(88) res[89] = fma52lo(res[89], a[42], a[47]); // Sum(89) res[90] = fma52hi(res[90], a[42], a[47]); // Sum(89) res[90] = fma52lo(res[90], a[43], a[47]); // Sum(90) res[91] = fma52hi(res[91], a[43], a[47]); // Sum(90) res[91] = fma52lo(res[91], a[44], a[47]); // Sum(91) res[92] = fma52hi(res[92], a[44], a[47]); // Sum(91) res[92] = fma52lo(res[92], a[45], a[47]); // Sum(92) res[93] = fma52hi(res[93], a[45], a[47]); // Sum(92) res[93] = fma52lo(res[93], a[46], a[47]); // Sum(93) res[94] = fma52hi(res[94], a[46], a[47]); // Sum(93) res[84] = fma52lo(res[84], a[36], a[48]); // Sum(84) res[85] = fma52hi(res[85], a[36], a[48]); // Sum(84) res[85] = fma52lo(res[85], a[37], a[48]); // Sum(85) res[86] = fma52hi(res[86], a[37], a[48]); // Sum(85) res[86] = fma52lo(res[86], a[38], a[48]); // Sum(86) res[87] = fma52hi(res[87], a[38], a[48]); // Sum(86) res[87] = fma52lo(res[87], a[39], a[48]); // Sum(87) res[88] = fma52hi(res[88], a[39], a[48]); // Sum(87) res[88] = fma52lo(res[88], a[40], a[48]); // Sum(88) res[89] = fma52hi(res[89], a[40], a[48]); // Sum(88) res[89] = fma52lo(res[89], a[41], a[48]); // Sum(89) res[90] = fma52hi(res[90], a[41], a[48]); // Sum(89) res[90] = fma52lo(res[90], a[42], a[48]); // Sum(90) res[91] = fma52hi(res[91], a[42], a[48]); // Sum(90) res[91] = fma52lo(res[91], a[43], a[48]); // Sum(91) res[92] = fma52hi(res[92], a[43], a[48]); // Sum(91) res[92] = fma52lo(res[92], a[44], a[48]); // Sum(92) res[93] = fma52hi(res[93], a[44], a[48]); // Sum(92) res[93] = fma52lo(res[93], a[45], a[48]); // Sum(93) res[94] = fma52hi(res[94], a[45], a[48]); // Sum(93) res[94] = fma52lo(res[94], a[46], a[48]); // Sum(94) res[95] = fma52hi(res[95], a[46], a[48]); // Sum(94) res[95] = fma52lo(res[95], a[47], a[48]); // Sum(95) res[96] = fma52hi(res[96], a[47], a[48]); // Sum(95) res[84] = fma52lo(res[84], a[35], a[49]); // Sum(84) res[85] = fma52hi(res[85], a[35], a[49]); // Sum(84) res[85] = fma52lo(res[85], a[36], a[49]); // Sum(85) res[86] = fma52hi(res[86], a[36], a[49]); // Sum(85) res[86] = fma52lo(res[86], a[37], a[49]); // Sum(86) res[87] = fma52hi(res[87], a[37], a[49]); // Sum(86) res[87] = fma52lo(res[87], a[38], a[49]); // Sum(87) res[88] = fma52hi(res[88], a[38], a[49]); // Sum(87) res[88] = fma52lo(res[88], a[39], a[49]); // Sum(88) res[89] = fma52hi(res[89], a[39], a[49]); // Sum(88) res[89] = fma52lo(res[89], a[40], a[49]); // Sum(89) res[90] = fma52hi(res[90], a[40], a[49]); // Sum(89) res[90] = fma52lo(res[90], a[41], a[49]); // Sum(90) res[91] = fma52hi(res[91], a[41], a[49]); // Sum(90) res[91] = fma52lo(res[91], a[42], a[49]); // Sum(91) res[92] = fma52hi(res[92], a[42], a[49]); // Sum(91) res[92] = fma52lo(res[92], a[43], a[49]); // Sum(92) res[93] = fma52hi(res[93], a[43], a[49]); // Sum(92) res[93] = fma52lo(res[93], a[44], a[49]); // Sum(93) res[94] = fma52hi(res[94], a[44], a[49]); // Sum(93) res[94] = fma52lo(res[94], a[45], a[49]); // Sum(94) res[95] = fma52hi(res[95], a[45], a[49]); // Sum(94) res[95] = fma52lo(res[95], a[46], a[49]); // Sum(95) res[96] = fma52hi(res[96], a[46], a[49]); // Sum(95) res[84] = fma52lo(res[84], a[34], a[50]); // Sum(84) res[85] = fma52hi(res[85], a[34], a[50]); // Sum(84) res[85] = fma52lo(res[85], a[35], a[50]); // Sum(85) res[86] = fma52hi(res[86], a[35], a[50]); // Sum(85) res[86] = fma52lo(res[86], a[36], a[50]); // Sum(86) res[87] = fma52hi(res[87], a[36], a[50]); // Sum(86) res[87] = fma52lo(res[87], a[37], a[50]); // Sum(87) res[88] = fma52hi(res[88], a[37], a[50]); // Sum(87) res[88] = fma52lo(res[88], a[38], a[50]); // Sum(88) res[89] = fma52hi(res[89], a[38], a[50]); // Sum(88) res[89] = fma52lo(res[89], a[39], a[50]); // Sum(89) res[90] = fma52hi(res[90], a[39], a[50]); // Sum(89) res[90] = fma52lo(res[90], a[40], a[50]); // Sum(90) res[91] = fma52hi(res[91], a[40], a[50]); // Sum(90) res[91] = fma52lo(res[91], a[41], a[50]); // Sum(91) res[92] = fma52hi(res[92], a[41], a[50]); // Sum(91) res[92] = fma52lo(res[92], a[42], a[50]); // Sum(92) res[93] = fma52hi(res[93], a[42], a[50]); // Sum(92) res[93] = fma52lo(res[93], a[43], a[50]); // Sum(93) res[94] = fma52hi(res[94], a[43], a[50]); // Sum(93) res[94] = fma52lo(res[94], a[44], a[50]); // Sum(94) res[95] = fma52hi(res[95], a[44], a[50]); // Sum(94) res[95] = fma52lo(res[95], a[45], a[50]); // Sum(95) res[96] = fma52hi(res[96], a[45], a[50]); // Sum(95) res[84] = fma52lo(res[84], a[33], a[51]); // Sum(84) res[85] = fma52hi(res[85], a[33], a[51]); // Sum(84) res[85] = fma52lo(res[85], a[34], a[51]); // Sum(85) res[86] = fma52hi(res[86], a[34], a[51]); // Sum(85) res[86] = fma52lo(res[86], a[35], a[51]); // Sum(86) res[87] = fma52hi(res[87], a[35], a[51]); // Sum(86) res[87] = fma52lo(res[87], a[36], a[51]); // Sum(87) res[88] = fma52hi(res[88], a[36], a[51]); // Sum(87) res[88] = fma52lo(res[88], a[37], a[51]); // Sum(88) res[89] = fma52hi(res[89], a[37], a[51]); // Sum(88) res[89] = fma52lo(res[89], a[38], a[51]); // Sum(89) res[90] = fma52hi(res[90], a[38], a[51]); // Sum(89) res[90] = fma52lo(res[90], a[39], a[51]); // Sum(90) res[91] = fma52hi(res[91], a[39], a[51]); // Sum(90) res[91] = fma52lo(res[91], a[40], a[51]); // Sum(91) res[92] = fma52hi(res[92], a[40], a[51]); // Sum(91) res[92] = fma52lo(res[92], a[41], a[51]); // Sum(92) res[93] = fma52hi(res[93], a[41], a[51]); // Sum(92) res[93] = fma52lo(res[93], a[42], a[51]); // Sum(93) res[94] = fma52hi(res[94], a[42], a[51]); // Sum(93) res[94] = fma52lo(res[94], a[43], a[51]); // Sum(94) res[95] = fma52hi(res[95], a[43], a[51]); // Sum(94) res[95] = fma52lo(res[95], a[44], a[51]); // Sum(95) res[96] = fma52hi(res[96], a[44], a[51]); // Sum(95) res[84] = fma52lo(res[84], a[32], a[52]); // Sum(84) res[85] = fma52hi(res[85], a[32], a[52]); // Sum(84) res[85] = fma52lo(res[85], a[33], a[52]); // Sum(85) res[86] = fma52hi(res[86], a[33], a[52]); // Sum(85) res[86] = fma52lo(res[86], a[34], a[52]); // Sum(86) res[87] = fma52hi(res[87], a[34], a[52]); // Sum(86) res[87] = fma52lo(res[87], a[35], a[52]); // Sum(87) res[88] = fma52hi(res[88], a[35], a[52]); // Sum(87) res[88] = fma52lo(res[88], a[36], a[52]); // Sum(88) res[89] = fma52hi(res[89], a[36], a[52]); // Sum(88) res[89] = fma52lo(res[89], a[37], a[52]); // Sum(89) res[90] = fma52hi(res[90], a[37], a[52]); // Sum(89) res[90] = fma52lo(res[90], a[38], a[52]); // Sum(90) res[91] = fma52hi(res[91], a[38], a[52]); // Sum(90) res[91] = fma52lo(res[91], a[39], a[52]); // Sum(91) res[92] = fma52hi(res[92], a[39], a[52]); // Sum(91) res[92] = fma52lo(res[92], a[40], a[52]); // Sum(92) res[93] = fma52hi(res[93], a[40], a[52]); // Sum(92) res[93] = fma52lo(res[93], a[41], a[52]); // Sum(93) res[94] = fma52hi(res[94], a[41], a[52]); // Sum(93) res[94] = fma52lo(res[94], a[42], a[52]); // Sum(94) res[95] = fma52hi(res[95], a[42], a[52]); // Sum(94) res[95] = fma52lo(res[95], a[43], a[52]); // Sum(95) res[96] = fma52hi(res[96], a[43], a[52]); // Sum(95) res[84] = fma52lo(res[84], a[31], a[53]); // Sum(84) res[85] = fma52hi(res[85], a[31], a[53]); // Sum(84) res[85] = fma52lo(res[85], a[32], a[53]); // Sum(85) res[86] = fma52hi(res[86], a[32], a[53]); // Sum(85) res[86] = fma52lo(res[86], a[33], a[53]); // Sum(86) res[87] = fma52hi(res[87], a[33], a[53]); // Sum(86) res[87] = fma52lo(res[87], a[34], a[53]); // Sum(87) res[88] = fma52hi(res[88], a[34], a[53]); // Sum(87) res[88] = fma52lo(res[88], a[35], a[53]); // Sum(88) res[89] = fma52hi(res[89], a[35], a[53]); // Sum(88) res[89] = fma52lo(res[89], a[36], a[53]); // Sum(89) res[90] = fma52hi(res[90], a[36], a[53]); // Sum(89) res[90] = fma52lo(res[90], a[37], a[53]); // Sum(90) res[91] = fma52hi(res[91], a[37], a[53]); // Sum(90) res[91] = fma52lo(res[91], a[38], a[53]); // Sum(91) res[92] = fma52hi(res[92], a[38], a[53]); // Sum(91) res[92] = fma52lo(res[92], a[39], a[53]); // Sum(92) res[93] = fma52hi(res[93], a[39], a[53]); // Sum(92) res[93] = fma52lo(res[93], a[40], a[53]); // Sum(93) res[94] = fma52hi(res[94], a[40], a[53]); // Sum(93) res[94] = fma52lo(res[94], a[41], a[53]); // Sum(94) res[95] = fma52hi(res[95], a[41], a[53]); // Sum(94) res[95] = fma52lo(res[95], a[42], a[53]); // Sum(95) res[96] = fma52hi(res[96], a[42], a[53]); // Sum(95) res[84] = fma52lo(res[84], a[30], a[54]); // Sum(84) res[85] = fma52hi(res[85], a[30], a[54]); // Sum(84) res[85] = fma52lo(res[85], a[31], a[54]); // Sum(85) res[86] = fma52hi(res[86], a[31], a[54]); // Sum(85) res[86] = fma52lo(res[86], a[32], a[54]); // Sum(86) res[87] = fma52hi(res[87], a[32], a[54]); // Sum(86) res[87] = fma52lo(res[87], a[33], a[54]); // Sum(87) res[88] = fma52hi(res[88], a[33], a[54]); // Sum(87) res[88] = fma52lo(res[88], a[34], a[54]); // Sum(88) res[89] = fma52hi(res[89], a[34], a[54]); // Sum(88) res[89] = fma52lo(res[89], a[35], a[54]); // Sum(89) res[90] = fma52hi(res[90], a[35], a[54]); // Sum(89) res[90] = fma52lo(res[90], a[36], a[54]); // Sum(90) res[91] = fma52hi(res[91], a[36], a[54]); // Sum(90) res[91] = fma52lo(res[91], a[37], a[54]); // Sum(91) res[92] = fma52hi(res[92], a[37], a[54]); // Sum(91) res[92] = fma52lo(res[92], a[38], a[54]); // Sum(92) res[93] = fma52hi(res[93], a[38], a[54]); // Sum(92) res[93] = fma52lo(res[93], a[39], a[54]); // Sum(93) res[94] = fma52hi(res[94], a[39], a[54]); // Sum(93) res[94] = fma52lo(res[94], a[40], a[54]); // Sum(94) res[95] = fma52hi(res[95], a[40], a[54]); // Sum(94) res[95] = fma52lo(res[95], a[41], a[54]); // Sum(95) res[96] = fma52hi(res[96], a[41], a[54]); // Sum(95) res[84] = fma52lo(res[84], a[29], a[55]); // Sum(84) res[85] = fma52hi(res[85], a[29], a[55]); // Sum(84) res[85] = fma52lo(res[85], a[30], a[55]); // Sum(85) res[86] = fma52hi(res[86], a[30], a[55]); // Sum(85) res[86] = fma52lo(res[86], a[31], a[55]); // Sum(86) res[87] = fma52hi(res[87], a[31], a[55]); // Sum(86) res[87] = fma52lo(res[87], a[32], a[55]); // Sum(87) res[88] = fma52hi(res[88], a[32], a[55]); // Sum(87) res[88] = fma52lo(res[88], a[33], a[55]); // Sum(88) res[89] = fma52hi(res[89], a[33], a[55]); // Sum(88) res[89] = fma52lo(res[89], a[34], a[55]); // Sum(89) res[90] = fma52hi(res[90], a[34], a[55]); // Sum(89) res[90] = fma52lo(res[90], a[35], a[55]); // Sum(90) res[91] = fma52hi(res[91], a[35], a[55]); // Sum(90) res[91] = fma52lo(res[91], a[36], a[55]); // Sum(91) res[92] = fma52hi(res[92], a[36], a[55]); // Sum(91) res[92] = fma52lo(res[92], a[37], a[55]); // Sum(92) res[93] = fma52hi(res[93], a[37], a[55]); // Sum(92) res[93] = fma52lo(res[93], a[38], a[55]); // Sum(93) res[94] = fma52hi(res[94], a[38], a[55]); // Sum(93) res[94] = fma52lo(res[94], a[39], a[55]); // Sum(94) res[95] = fma52hi(res[95], a[39], a[55]); // Sum(94) res[95] = fma52lo(res[95], a[40], a[55]); // Sum(95) res[96] = fma52hi(res[96], a[40], a[55]); // Sum(95) res[84] = fma52lo(res[84], a[28], a[56]); // Sum(84) res[85] = fma52hi(res[85], a[28], a[56]); // Sum(84) res[85] = fma52lo(res[85], a[29], a[56]); // Sum(85) res[86] = fma52hi(res[86], a[29], a[56]); // Sum(85) res[86] = fma52lo(res[86], a[30], a[56]); // Sum(86) res[87] = fma52hi(res[87], a[30], a[56]); // Sum(86) res[87] = fma52lo(res[87], a[31], a[56]); // Sum(87) res[88] = fma52hi(res[88], a[31], a[56]); // Sum(87) res[88] = fma52lo(res[88], a[32], a[56]); // Sum(88) res[89] = fma52hi(res[89], a[32], a[56]); // Sum(88) res[89] = fma52lo(res[89], a[33], a[56]); // Sum(89) res[90] = fma52hi(res[90], a[33], a[56]); // Sum(89) res[90] = fma52lo(res[90], a[34], a[56]); // Sum(90) res[91] = fma52hi(res[91], a[34], a[56]); // Sum(90) res[91] = fma52lo(res[91], a[35], a[56]); // Sum(91) res[92] = fma52hi(res[92], a[35], a[56]); // Sum(91) res[92] = fma52lo(res[92], a[36], a[56]); // Sum(92) res[93] = fma52hi(res[93], a[36], a[56]); // Sum(92) res[93] = fma52lo(res[93], a[37], a[56]); // Sum(93) res[94] = fma52hi(res[94], a[37], a[56]); // Sum(93) res[94] = fma52lo(res[94], a[38], a[56]); // Sum(94) res[95] = fma52hi(res[95], a[38], a[56]); // Sum(94) res[95] = fma52lo(res[95], a[39], a[56]); // Sum(95) res[96] = fma52hi(res[96], a[39], a[56]); // Sum(95) res[84] = fma52lo(res[84], a[27], a[57]); // Sum(84) res[85] = fma52hi(res[85], a[27], a[57]); // Sum(84) res[85] = fma52lo(res[85], a[28], a[57]); // Sum(85) res[86] = fma52hi(res[86], a[28], a[57]); // Sum(85) res[86] = fma52lo(res[86], a[29], a[57]); // Sum(86) res[87] = fma52hi(res[87], a[29], a[57]); // Sum(86) res[87] = fma52lo(res[87], a[30], a[57]); // Sum(87) res[88] = fma52hi(res[88], a[30], a[57]); // Sum(87) res[88] = fma52lo(res[88], a[31], a[57]); // Sum(88) res[89] = fma52hi(res[89], a[31], a[57]); // Sum(88) res[89] = fma52lo(res[89], a[32], a[57]); // Sum(89) res[90] = fma52hi(res[90], a[32], a[57]); // Sum(89) res[90] = fma52lo(res[90], a[33], a[57]); // Sum(90) res[91] = fma52hi(res[91], a[33], a[57]); // Sum(90) res[91] = fma52lo(res[91], a[34], a[57]); // Sum(91) res[92] = fma52hi(res[92], a[34], a[57]); // Sum(91) res[92] = fma52lo(res[92], a[35], a[57]); // Sum(92) res[93] = fma52hi(res[93], a[35], a[57]); // Sum(92) res[93] = fma52lo(res[93], a[36], a[57]); // Sum(93) res[94] = fma52hi(res[94], a[36], a[57]); // Sum(93) res[94] = fma52lo(res[94], a[37], a[57]); // Sum(94) res[95] = fma52hi(res[95], a[37], a[57]); // Sum(94) res[95] = fma52lo(res[95], a[38], a[57]); // Sum(95) res[96] = fma52hi(res[96], a[38], a[57]); // Sum(95) res[84] = fma52lo(res[84], a[26], a[58]); // Sum(84) res[85] = fma52hi(res[85], a[26], a[58]); // Sum(84) res[85] = fma52lo(res[85], a[27], a[58]); // Sum(85) res[86] = fma52hi(res[86], a[27], a[58]); // Sum(85) res[86] = fma52lo(res[86], a[28], a[58]); // Sum(86) res[87] = fma52hi(res[87], a[28], a[58]); // Sum(86) res[87] = fma52lo(res[87], a[29], a[58]); // Sum(87) res[88] = fma52hi(res[88], a[29], a[58]); // Sum(87) res[88] = fma52lo(res[88], a[30], a[58]); // Sum(88) res[89] = fma52hi(res[89], a[30], a[58]); // Sum(88) res[89] = fma52lo(res[89], a[31], a[58]); // Sum(89) res[90] = fma52hi(res[90], a[31], a[58]); // Sum(89) res[90] = fma52lo(res[90], a[32], a[58]); // Sum(90) res[91] = fma52hi(res[91], a[32], a[58]); // Sum(90) res[91] = fma52lo(res[91], a[33], a[58]); // Sum(91) res[92] = fma52hi(res[92], a[33], a[58]); // Sum(91) res[92] = fma52lo(res[92], a[34], a[58]); // Sum(92) res[93] = fma52hi(res[93], a[34], a[58]); // Sum(92) res[93] = fma52lo(res[93], a[35], a[58]); // Sum(93) res[94] = fma52hi(res[94], a[35], a[58]); // Sum(93) res[94] = fma52lo(res[94], a[36], a[58]); // Sum(94) res[95] = fma52hi(res[95], a[36], a[58]); // Sum(94) res[95] = fma52lo(res[95], a[37], a[58]); // Sum(95) res[96] = fma52hi(res[96], a[37], a[58]); // Sum(95) res[84] = fma52lo(res[84], a[25], a[59]); // Sum(84) res[85] = fma52hi(res[85], a[25], a[59]); // Sum(84) res[85] = fma52lo(res[85], a[26], a[59]); // Sum(85) res[86] = fma52hi(res[86], a[26], a[59]); // Sum(85) res[86] = fma52lo(res[86], a[27], a[59]); // Sum(86) res[87] = fma52hi(res[87], a[27], a[59]); // Sum(86) res[87] = fma52lo(res[87], a[28], a[59]); // Sum(87) res[88] = fma52hi(res[88], a[28], a[59]); // Sum(87) res[88] = fma52lo(res[88], a[29], a[59]); // Sum(88) res[89] = fma52hi(res[89], a[29], a[59]); // Sum(88) res[89] = fma52lo(res[89], a[30], a[59]); // Sum(89) res[90] = fma52hi(res[90], a[30], a[59]); // Sum(89) res[90] = fma52lo(res[90], a[31], a[59]); // Sum(90) res[91] = fma52hi(res[91], a[31], a[59]); // Sum(90) res[91] = fma52lo(res[91], a[32], a[59]); // Sum(91) res[92] = fma52hi(res[92], a[32], a[59]); // Sum(91) res[92] = fma52lo(res[92], a[33], a[59]); // Sum(92) res[93] = fma52hi(res[93], a[33], a[59]); // Sum(92) res[93] = fma52lo(res[93], a[34], a[59]); // Sum(93) res[94] = fma52hi(res[94], a[34], a[59]); // Sum(93) res[94] = fma52lo(res[94], a[35], a[59]); // Sum(94) res[95] = fma52hi(res[95], a[35], a[59]); // Sum(94) res[95] = fma52lo(res[95], a[36], a[59]); // Sum(95) res[96] = fma52hi(res[96], a[36], a[59]); // Sum(95) res[84] = add64(res[84], res[84]); // Double(84) res[85] = add64(res[85], res[85]); // Double(85) res[86] = add64(res[86], res[86]); // Double(86) res[87] = add64(res[87], res[87]); // Double(87) res[88] = add64(res[88], res[88]); // Double(88) res[89] = add64(res[89], res[89]); // Double(89) res[90] = add64(res[90], res[90]); // Double(90) res[91] = add64(res[91], res[91]); // Double(91) res[92] = add64(res[92], res[92]); // Double(92) res[93] = add64(res[93], res[93]); // Double(93) res[94] = add64(res[94], res[94]); // Double(94) res[95] = add64(res[95], res[95]); // Double(95) res[84] = fma52lo(res[84], a[42], a[42]); // Add sqr(84) res[85] = fma52hi(res[85], a[42], a[42]); // Add sqr(84) res[86] = fma52lo(res[86], a[43], a[43]); // Add sqr(86) res[87] = fma52hi(res[87], a[43], a[43]); // Add sqr(86) res[88] = fma52lo(res[88], a[44], a[44]); // Add sqr(88) res[89] = fma52hi(res[89], a[44], a[44]); // Add sqr(88) res[90] = fma52lo(res[90], a[45], a[45]); // Add sqr(90) res[91] = fma52hi(res[91], a[45], a[45]); // Add sqr(90) res[92] = fma52lo(res[92], a[46], a[46]); // Add sqr(92) res[93] = fma52hi(res[93], a[46], a[46]); // Add sqr(92) res[94] = fma52lo(res[94], a[47], a[47]); // Add sqr(94) res[95] = fma52hi(res[95], a[47], a[47]); // Add sqr(94) res[96] = fma52lo(res[96], a[47], a[49]); // Sum(96) res[97] = fma52hi(res[97], a[47], a[49]); // Sum(96) res[97] = fma52lo(res[97], a[48], a[49]); // Sum(97) res[98] = fma52hi(res[98], a[48], a[49]); // Sum(97) res[96] = fma52lo(res[96], a[46], a[50]); // Sum(96) res[97] = fma52hi(res[97], a[46], a[50]); // Sum(96) res[97] = fma52lo(res[97], a[47], a[50]); // Sum(97) res[98] = fma52hi(res[98], a[47], a[50]); // Sum(97) res[98] = fma52lo(res[98], a[48], a[50]); // Sum(98) res[99] = fma52hi(res[99], a[48], a[50]); // Sum(98) res[99] = fma52lo(res[99], a[49], a[50]); // Sum(99) res[100] = fma52hi(res[100], a[49], a[50]); // Sum(99) res[96] = fma52lo(res[96], a[45], a[51]); // Sum(96) res[97] = fma52hi(res[97], a[45], a[51]); // Sum(96) res[97] = fma52lo(res[97], a[46], a[51]); // Sum(97) res[98] = fma52hi(res[98], a[46], a[51]); // Sum(97) res[98] = fma52lo(res[98], a[47], a[51]); // Sum(98) res[99] = fma52hi(res[99], a[47], a[51]); // Sum(98) res[99] = fma52lo(res[99], a[48], a[51]); // Sum(99) res[100] = fma52hi(res[100], a[48], a[51]); // Sum(99) res[100] = fma52lo(res[100], a[49], a[51]); // Sum(100) res[101] = fma52hi(res[101], a[49], a[51]); // Sum(100) res[101] = fma52lo(res[101], a[50], a[51]); // Sum(101) res[102] = fma52hi(res[102], a[50], a[51]); // Sum(101) res[96] = fma52lo(res[96], a[44], a[52]); // Sum(96) res[97] = fma52hi(res[97], a[44], a[52]); // Sum(96) res[97] = fma52lo(res[97], a[45], a[52]); // Sum(97) res[98] = fma52hi(res[98], a[45], a[52]); // Sum(97) res[98] = fma52lo(res[98], a[46], a[52]); // Sum(98) res[99] = fma52hi(res[99], a[46], a[52]); // Sum(98) res[99] = fma52lo(res[99], a[47], a[52]); // Sum(99) res[100] = fma52hi(res[100], a[47], a[52]); // Sum(99) res[100] = fma52lo(res[100], a[48], a[52]); // Sum(100) res[101] = fma52hi(res[101], a[48], a[52]); // Sum(100) res[101] = fma52lo(res[101], a[49], a[52]); // Sum(101) res[102] = fma52hi(res[102], a[49], a[52]); // Sum(101) res[102] = fma52lo(res[102], a[50], a[52]); // Sum(102) res[103] = fma52hi(res[103], a[50], a[52]); // Sum(102) res[103] = fma52lo(res[103], a[51], a[52]); // Sum(103) res[104] = fma52hi(res[104], a[51], a[52]); // Sum(103) res[96] = fma52lo(res[96], a[43], a[53]); // Sum(96) res[97] = fma52hi(res[97], a[43], a[53]); // Sum(96) res[97] = fma52lo(res[97], a[44], a[53]); // Sum(97) res[98] = fma52hi(res[98], a[44], a[53]); // Sum(97) res[98] = fma52lo(res[98], a[45], a[53]); // Sum(98) res[99] = fma52hi(res[99], a[45], a[53]); // Sum(98) res[99] = fma52lo(res[99], a[46], a[53]); // Sum(99) res[100] = fma52hi(res[100], a[46], a[53]); // Sum(99) res[100] = fma52lo(res[100], a[47], a[53]); // Sum(100) res[101] = fma52hi(res[101], a[47], a[53]); // Sum(100) res[101] = fma52lo(res[101], a[48], a[53]); // Sum(101) res[102] = fma52hi(res[102], a[48], a[53]); // Sum(101) res[102] = fma52lo(res[102], a[49], a[53]); // Sum(102) res[103] = fma52hi(res[103], a[49], a[53]); // Sum(102) res[103] = fma52lo(res[103], a[50], a[53]); // Sum(103) res[104] = fma52hi(res[104], a[50], a[53]); // Sum(103) res[104] = fma52lo(res[104], a[51], a[53]); // Sum(104) res[105] = fma52hi(res[105], a[51], a[53]); // Sum(104) res[105] = fma52lo(res[105], a[52], a[53]); // Sum(105) res[106] = fma52hi(res[106], a[52], a[53]); // Sum(105) res[96] = fma52lo(res[96], a[42], a[54]); // Sum(96) res[97] = fma52hi(res[97], a[42], a[54]); // Sum(96) res[97] = fma52lo(res[97], a[43], a[54]); // Sum(97) res[98] = fma52hi(res[98], a[43], a[54]); // Sum(97) res[98] = fma52lo(res[98], a[44], a[54]); // Sum(98) res[99] = fma52hi(res[99], a[44], a[54]); // Sum(98) res[99] = fma52lo(res[99], a[45], a[54]); // Sum(99) res[100] = fma52hi(res[100], a[45], a[54]); // Sum(99) res[100] = fma52lo(res[100], a[46], a[54]); // Sum(100) res[101] = fma52hi(res[101], a[46], a[54]); // Sum(100) res[101] = fma52lo(res[101], a[47], a[54]); // Sum(101) res[102] = fma52hi(res[102], a[47], a[54]); // Sum(101) res[102] = fma52lo(res[102], a[48], a[54]); // Sum(102) res[103] = fma52hi(res[103], a[48], a[54]); // Sum(102) res[103] = fma52lo(res[103], a[49], a[54]); // Sum(103) res[104] = fma52hi(res[104], a[49], a[54]); // Sum(103) res[104] = fma52lo(res[104], a[50], a[54]); // Sum(104) res[105] = fma52hi(res[105], a[50], a[54]); // Sum(104) res[105] = fma52lo(res[105], a[51], a[54]); // Sum(105) res[106] = fma52hi(res[106], a[51], a[54]); // Sum(105) res[106] = fma52lo(res[106], a[52], a[54]); // Sum(106) res[107] = fma52hi(res[107], a[52], a[54]); // Sum(106) res[107] = fma52lo(res[107], a[53], a[54]); // Sum(107) res[108] = fma52hi(res[108], a[53], a[54]); // Sum(107) res[96] = fma52lo(res[96], a[41], a[55]); // Sum(96) res[97] = fma52hi(res[97], a[41], a[55]); // Sum(96) res[97] = fma52lo(res[97], a[42], a[55]); // Sum(97) res[98] = fma52hi(res[98], a[42], a[55]); // Sum(97) res[98] = fma52lo(res[98], a[43], a[55]); // Sum(98) res[99] = fma52hi(res[99], a[43], a[55]); // Sum(98) res[99] = fma52lo(res[99], a[44], a[55]); // Sum(99) res[100] = fma52hi(res[100], a[44], a[55]); // Sum(99) res[100] = fma52lo(res[100], a[45], a[55]); // Sum(100) res[101] = fma52hi(res[101], a[45], a[55]); // Sum(100) res[101] = fma52lo(res[101], a[46], a[55]); // Sum(101) res[102] = fma52hi(res[102], a[46], a[55]); // Sum(101) res[102] = fma52lo(res[102], a[47], a[55]); // Sum(102) res[103] = fma52hi(res[103], a[47], a[55]); // Sum(102) res[103] = fma52lo(res[103], a[48], a[55]); // Sum(103) res[104] = fma52hi(res[104], a[48], a[55]); // Sum(103) res[104] = fma52lo(res[104], a[49], a[55]); // Sum(104) res[105] = fma52hi(res[105], a[49], a[55]); // Sum(104) res[105] = fma52lo(res[105], a[50], a[55]); // Sum(105) res[106] = fma52hi(res[106], a[50], a[55]); // Sum(105) res[106] = fma52lo(res[106], a[51], a[55]); // Sum(106) res[107] = fma52hi(res[107], a[51], a[55]); // Sum(106) res[107] = fma52lo(res[107], a[52], a[55]); // Sum(107) res[108] = fma52hi(res[108], a[52], a[55]); // Sum(107) res[96] = fma52lo(res[96], a[40], a[56]); // Sum(96) res[97] = fma52hi(res[97], a[40], a[56]); // Sum(96) res[97] = fma52lo(res[97], a[41], a[56]); // Sum(97) res[98] = fma52hi(res[98], a[41], a[56]); // Sum(97) res[98] = fma52lo(res[98], a[42], a[56]); // Sum(98) res[99] = fma52hi(res[99], a[42], a[56]); // Sum(98) res[99] = fma52lo(res[99], a[43], a[56]); // Sum(99) res[100] = fma52hi(res[100], a[43], a[56]); // Sum(99) res[100] = fma52lo(res[100], a[44], a[56]); // Sum(100) res[101] = fma52hi(res[101], a[44], a[56]); // Sum(100) res[101] = fma52lo(res[101], a[45], a[56]); // Sum(101) res[102] = fma52hi(res[102], a[45], a[56]); // Sum(101) res[102] = fma52lo(res[102], a[46], a[56]); // Sum(102) res[103] = fma52hi(res[103], a[46], a[56]); // Sum(102) res[103] = fma52lo(res[103], a[47], a[56]); // Sum(103) res[104] = fma52hi(res[104], a[47], a[56]); // Sum(103) res[104] = fma52lo(res[104], a[48], a[56]); // Sum(104) res[105] = fma52hi(res[105], a[48], a[56]); // Sum(104) res[105] = fma52lo(res[105], a[49], a[56]); // Sum(105) res[106] = fma52hi(res[106], a[49], a[56]); // Sum(105) res[106] = fma52lo(res[106], a[50], a[56]); // Sum(106) res[107] = fma52hi(res[107], a[50], a[56]); // Sum(106) res[107] = fma52lo(res[107], a[51], a[56]); // Sum(107) res[108] = fma52hi(res[108], a[51], a[56]); // Sum(107) res[96] = fma52lo(res[96], a[39], a[57]); // Sum(96) res[97] = fma52hi(res[97], a[39], a[57]); // Sum(96) res[97] = fma52lo(res[97], a[40], a[57]); // Sum(97) res[98] = fma52hi(res[98], a[40], a[57]); // Sum(97) res[98] = fma52lo(res[98], a[41], a[57]); // Sum(98) res[99] = fma52hi(res[99], a[41], a[57]); // Sum(98) res[99] = fma52lo(res[99], a[42], a[57]); // Sum(99) res[100] = fma52hi(res[100], a[42], a[57]); // Sum(99) res[100] = fma52lo(res[100], a[43], a[57]); // Sum(100) res[101] = fma52hi(res[101], a[43], a[57]); // Sum(100) res[101] = fma52lo(res[101], a[44], a[57]); // Sum(101) res[102] = fma52hi(res[102], a[44], a[57]); // Sum(101) res[102] = fma52lo(res[102], a[45], a[57]); // Sum(102) res[103] = fma52hi(res[103], a[45], a[57]); // Sum(102) res[103] = fma52lo(res[103], a[46], a[57]); // Sum(103) res[104] = fma52hi(res[104], a[46], a[57]); // Sum(103) res[104] = fma52lo(res[104], a[47], a[57]); // Sum(104) res[105] = fma52hi(res[105], a[47], a[57]); // Sum(104) res[105] = fma52lo(res[105], a[48], a[57]); // Sum(105) res[106] = fma52hi(res[106], a[48], a[57]); // Sum(105) res[106] = fma52lo(res[106], a[49], a[57]); // Sum(106) res[107] = fma52hi(res[107], a[49], a[57]); // Sum(106) res[107] = fma52lo(res[107], a[50], a[57]); // Sum(107) res[108] = fma52hi(res[108], a[50], a[57]); // Sum(107) res[96] = fma52lo(res[96], a[38], a[58]); // Sum(96) res[97] = fma52hi(res[97], a[38], a[58]); // Sum(96) res[97] = fma52lo(res[97], a[39], a[58]); // Sum(97) res[98] = fma52hi(res[98], a[39], a[58]); // Sum(97) res[98] = fma52lo(res[98], a[40], a[58]); // Sum(98) res[99] = fma52hi(res[99], a[40], a[58]); // Sum(98) res[99] = fma52lo(res[99], a[41], a[58]); // Sum(99) res[100] = fma52hi(res[100], a[41], a[58]); // Sum(99) res[100] = fma52lo(res[100], a[42], a[58]); // Sum(100) res[101] = fma52hi(res[101], a[42], a[58]); // Sum(100) res[101] = fma52lo(res[101], a[43], a[58]); // Sum(101) res[102] = fma52hi(res[102], a[43], a[58]); // Sum(101) res[102] = fma52lo(res[102], a[44], a[58]); // Sum(102) res[103] = fma52hi(res[103], a[44], a[58]); // Sum(102) res[103] = fma52lo(res[103], a[45], a[58]); // Sum(103) res[104] = fma52hi(res[104], a[45], a[58]); // Sum(103) res[104] = fma52lo(res[104], a[46], a[58]); // Sum(104) res[105] = fma52hi(res[105], a[46], a[58]); // Sum(104) res[105] = fma52lo(res[105], a[47], a[58]); // Sum(105) res[106] = fma52hi(res[106], a[47], a[58]); // Sum(105) res[106] = fma52lo(res[106], a[48], a[58]); // Sum(106) res[107] = fma52hi(res[107], a[48], a[58]); // Sum(106) res[107] = fma52lo(res[107], a[49], a[58]); // Sum(107) res[108] = fma52hi(res[108], a[49], a[58]); // Sum(107) res[96] = fma52lo(res[96], a[37], a[59]); // Sum(96) res[97] = fma52hi(res[97], a[37], a[59]); // Sum(96) res[97] = fma52lo(res[97], a[38], a[59]); // Sum(97) res[98] = fma52hi(res[98], a[38], a[59]); // Sum(97) res[98] = fma52lo(res[98], a[39], a[59]); // Sum(98) res[99] = fma52hi(res[99], a[39], a[59]); // Sum(98) res[99] = fma52lo(res[99], a[40], a[59]); // Sum(99) res[100] = fma52hi(res[100], a[40], a[59]); // Sum(99) res[100] = fma52lo(res[100], a[41], a[59]); // Sum(100) res[101] = fma52hi(res[101], a[41], a[59]); // Sum(100) res[101] = fma52lo(res[101], a[42], a[59]); // Sum(101) res[102] = fma52hi(res[102], a[42], a[59]); // Sum(101) res[102] = fma52lo(res[102], a[43], a[59]); // Sum(102) res[103] = fma52hi(res[103], a[43], a[59]); // Sum(102) res[103] = fma52lo(res[103], a[44], a[59]); // Sum(103) res[104] = fma52hi(res[104], a[44], a[59]); // Sum(103) res[104] = fma52lo(res[104], a[45], a[59]); // Sum(104) res[105] = fma52hi(res[105], a[45], a[59]); // Sum(104) res[105] = fma52lo(res[105], a[46], a[59]); // Sum(105) res[106] = fma52hi(res[106], a[46], a[59]); // Sum(105) res[106] = fma52lo(res[106], a[47], a[59]); // Sum(106) res[107] = fma52hi(res[107], a[47], a[59]); // Sum(106) res[107] = fma52lo(res[107], a[48], a[59]); // Sum(107) res[108] = fma52hi(res[108], a[48], a[59]); // Sum(107) res[96] = add64(res[96], res[96]); // Double(96) res[97] = add64(res[97], res[97]); // Double(97) res[98] = add64(res[98], res[98]); // Double(98) res[99] = add64(res[99], res[99]); // Double(99) res[100] = add64(res[100], res[100]); // Double(100) res[101] = add64(res[101], res[101]); // Double(101) res[102] = add64(res[102], res[102]); // Double(102) res[103] = add64(res[103], res[103]); // Double(103) res[104] = add64(res[104], res[104]); // Double(104) res[105] = add64(res[105], res[105]); // Double(105) res[106] = add64(res[106], res[106]); // Double(106) res[107] = add64(res[107], res[107]); // Double(107) res[96] = fma52lo(res[96], a[48], a[48]); // Add sqr(96) res[97] = fma52hi(res[97], a[48], a[48]); // Add sqr(96) res[98] = fma52lo(res[98], a[49], a[49]); // Add sqr(98) res[99] = fma52hi(res[99], a[49], a[49]); // Add sqr(98) res[100] = fma52lo(res[100], a[50], a[50]); // Add sqr(100) res[101] = fma52hi(res[101], a[50], a[50]); // Add sqr(100) res[102] = fma52lo(res[102], a[51], a[51]); // Add sqr(102) res[103] = fma52hi(res[103], a[51], a[51]); // Add sqr(102) res[104] = fma52lo(res[104], a[52], a[52]); // Add sqr(104) res[105] = fma52hi(res[105], a[52], a[52]); // Add sqr(104) res[106] = fma52lo(res[106], a[53], a[53]); // Add sqr(106) res[107] = fma52hi(res[107], a[53], a[53]); // Add sqr(106) res[108] = fma52lo(res[108], a[53], a[55]); // Sum(108) res[109] = fma52hi(res[109], a[53], a[55]); // Sum(108) res[109] = fma52lo(res[109], a[54], a[55]); // Sum(109) res[110] = fma52hi(res[110], a[54], a[55]); // Sum(109) res[108] = fma52lo(res[108], a[52], a[56]); // Sum(108) res[109] = fma52hi(res[109], a[52], a[56]); // Sum(108) res[109] = fma52lo(res[109], a[53], a[56]); // Sum(109) res[110] = fma52hi(res[110], a[53], a[56]); // Sum(109) res[110] = fma52lo(res[110], a[54], a[56]); // Sum(110) res[111] = fma52hi(res[111], a[54], a[56]); // Sum(110) res[111] = fma52lo(res[111], a[55], a[56]); // Sum(111) res[112] = fma52hi(res[112], a[55], a[56]); // Sum(111) res[108] = fma52lo(res[108], a[51], a[57]); // Sum(108) res[109] = fma52hi(res[109], a[51], a[57]); // Sum(108) res[109] = fma52lo(res[109], a[52], a[57]); // Sum(109) res[110] = fma52hi(res[110], a[52], a[57]); // Sum(109) res[110] = fma52lo(res[110], a[53], a[57]); // Sum(110) res[111] = fma52hi(res[111], a[53], a[57]); // Sum(110) res[111] = fma52lo(res[111], a[54], a[57]); // Sum(111) res[112] = fma52hi(res[112], a[54], a[57]); // Sum(111) res[112] = fma52lo(res[112], a[55], a[57]); // Sum(112) res[113] = fma52hi(res[113], a[55], a[57]); // Sum(112) res[113] = fma52lo(res[113], a[56], a[57]); // Sum(113) res[114] = fma52hi(res[114], a[56], a[57]); // Sum(113) res[108] = fma52lo(res[108], a[50], a[58]); // Sum(108) res[109] = fma52hi(res[109], a[50], a[58]); // Sum(108) res[109] = fma52lo(res[109], a[51], a[58]); // Sum(109) res[110] = fma52hi(res[110], a[51], a[58]); // Sum(109) res[110] = fma52lo(res[110], a[52], a[58]); // Sum(110) res[111] = fma52hi(res[111], a[52], a[58]); // Sum(110) res[111] = fma52lo(res[111], a[53], a[58]); // Sum(111) res[112] = fma52hi(res[112], a[53], a[58]); // Sum(111) res[112] = fma52lo(res[112], a[54], a[58]); // Sum(112) res[113] = fma52hi(res[113], a[54], a[58]); // Sum(112) res[113] = fma52lo(res[113], a[55], a[58]); // Sum(113) res[114] = fma52hi(res[114], a[55], a[58]); // Sum(113) res[114] = fma52lo(res[114], a[56], a[58]); // Sum(114) res[115] = fma52hi(res[115], a[56], a[58]); // Sum(114) res[115] = fma52lo(res[115], a[57], a[58]); // Sum(115) res[116] = fma52hi(res[116], a[57], a[58]); // Sum(115) res[108] = fma52lo(res[108], a[49], a[59]); // Sum(108) res[109] = fma52hi(res[109], a[49], a[59]); // Sum(108) res[109] = fma52lo(res[109], a[50], a[59]); // Sum(109) res[110] = fma52hi(res[110], a[50], a[59]); // Sum(109) res[110] = fma52lo(res[110], a[51], a[59]); // Sum(110) res[111] = fma52hi(res[111], a[51], a[59]); // Sum(110) res[111] = fma52lo(res[111], a[52], a[59]); // Sum(111) res[112] = fma52hi(res[112], a[52], a[59]); // Sum(111) res[112] = fma52lo(res[112], a[53], a[59]); // Sum(112) res[113] = fma52hi(res[113], a[53], a[59]); // Sum(112) res[113] = fma52lo(res[113], a[54], a[59]); // Sum(113) res[114] = fma52hi(res[114], a[54], a[59]); // Sum(113) res[114] = fma52lo(res[114], a[55], a[59]); // Sum(114) res[115] = fma52hi(res[115], a[55], a[59]); // Sum(114) res[115] = fma52lo(res[115], a[56], a[59]); // Sum(115) res[116] = fma52hi(res[116], a[56], a[59]); // Sum(115) res[116] = fma52lo(res[116], a[57], a[59]); // Sum(116) res[117] = fma52hi(res[117], a[57], a[59]); // Sum(116) res[117] = fma52lo(res[117], a[58], a[59]); // Sum(117) res[118] = fma52hi(res[118], a[58], a[59]); // Sum(117) res[108] = add64(res[108], res[108]); // Double(108) res[109] = add64(res[109], res[109]); // Double(109) res[110] = add64(res[110], res[110]); // Double(110) res[111] = add64(res[111], res[111]); // Double(111) res[112] = add64(res[112], res[112]); // Double(112) res[113] = add64(res[113], res[113]); // Double(113) res[114] = add64(res[114], res[114]); // Double(114) res[115] = add64(res[115], res[115]); // Double(115) res[116] = add64(res[116], res[116]); // Double(116) res[117] = add64(res[117], res[117]); // Double(117) res[118] = add64(res[118], res[118]); // Double(118) res[108] = fma52lo(res[108], a[54], a[54]); // Add sqr(108) res[109] = fma52hi(res[109], a[54], a[54]); // Add sqr(108) res[110] = fma52lo(res[110], a[55], a[55]); // Add sqr(110) res[111] = fma52hi(res[111], a[55], a[55]); // Add sqr(110) res[112] = fma52lo(res[112], a[56], a[56]); // Add sqr(112) res[113] = fma52hi(res[113], a[56], a[56]); // Add sqr(112) res[114] = fma52lo(res[114], a[57], a[57]); // Add sqr(114) res[115] = fma52hi(res[115], a[57], a[57]); // Add sqr(114) res[116] = fma52lo(res[116], a[58], a[58]); // Add sqr(116) res[117] = fma52hi(res[117], a[58], a[58]); // Add sqr(116) res[118] = fma52lo(res[118], a[59], a[59]); // Add sqr(118) res[119] = fma52hi(res[119], a[59], a[59]); // Add sqr(118) // Montgomery Reduction int it; for (it = 0; it < 60; it += 10) { // Reduction step int jt = 0; if ((it + 0) > 0) res[it + 0] = add64(res[it + 0], srli64(res[it + -1], DIGIT_SIZE)); u[it + 0] = mul52lo(res[it + 0], k); res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + 1] = add64(res[it + 1], srli64(res[it + 0], DIGIT_SIZE)); u[it + 1] = mul52lo(res[it + 1], k); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + 2] = add64(res[it + 2], srli64(res[it + 1], DIGIT_SIZE)); u[it + 2] = mul52lo(res[it + 2], k); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + 3] = add64(res[it + 3], srli64(res[it + 2], DIGIT_SIZE)); u[it + 3] = mul52lo(res[it + 3], k); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + 4] = add64(res[it + 4], srli64(res[it + 3], DIGIT_SIZE)); u[it + 4] = mul52lo(res[it + 4], k); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + 5] = add64(res[it + 5], srli64(res[it + 4], DIGIT_SIZE)); u[it + 5] = mul52lo(res[it + 5], k); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + 6] = add64(res[it + 6], srli64(res[it + 5], DIGIT_SIZE)); u[it + 6] = mul52lo(res[it + 6], k); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + 7] = add64(res[it + 7], srli64(res[it + 6], DIGIT_SIZE)); u[it + 7] = mul52lo(res[it + 7], k); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + 8] = add64(res[it + 8], srli64(res[it + 7], DIGIT_SIZE)); u[it + 8] = mul52lo(res[it + 8], k); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + 9] = add64(res[it + 9], srli64(res[it + 8], DIGIT_SIZE)); u[it + 9] = mul52lo(res[it + 9], k); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); for (jt = 10; jt < 60; jt += 10) { // Poly tile res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); } } // Normalization res[60] = add64(res[60], srli64(res[59], DIGIT_SIZE)); r[0] = and64_const(res[60], DIGIT_MASK); res[61] = add64(res[61], srli64(res[60], DIGIT_SIZE)); r[1] = and64_const(res[61], DIGIT_MASK); res[62] = add64(res[62], srli64(res[61], DIGIT_SIZE)); r[2] = and64_const(res[62], DIGIT_MASK); res[63] = add64(res[63], srli64(res[62], DIGIT_SIZE)); r[3] = and64_const(res[63], DIGIT_MASK); res[64] = add64(res[64], srli64(res[63], DIGIT_SIZE)); r[4] = and64_const(res[64], DIGIT_MASK); res[65] = add64(res[65], srli64(res[64], DIGIT_SIZE)); r[5] = and64_const(res[65], DIGIT_MASK); res[66] = add64(res[66], srli64(res[65], DIGIT_SIZE)); r[6] = and64_const(res[66], DIGIT_MASK); res[67] = add64(res[67], srli64(res[66], DIGIT_SIZE)); r[7] = and64_const(res[67], DIGIT_MASK); res[68] = add64(res[68], srli64(res[67], DIGIT_SIZE)); r[8] = and64_const(res[68], DIGIT_MASK); res[69] = add64(res[69], srli64(res[68], DIGIT_SIZE)); r[9] = and64_const(res[69], DIGIT_MASK); res[70] = add64(res[70], srli64(res[69], DIGIT_SIZE)); r[10] = and64_const(res[70], DIGIT_MASK); res[71] = add64(res[71], srli64(res[70], DIGIT_SIZE)); r[11] = and64_const(res[71], DIGIT_MASK); res[72] = add64(res[72], srli64(res[71], DIGIT_SIZE)); r[12] = and64_const(res[72], DIGIT_MASK); res[73] = add64(res[73], srli64(res[72], DIGIT_SIZE)); r[13] = and64_const(res[73], DIGIT_MASK); res[74] = add64(res[74], srli64(res[73], DIGIT_SIZE)); r[14] = and64_const(res[74], DIGIT_MASK); res[75] = add64(res[75], srli64(res[74], DIGIT_SIZE)); r[15] = and64_const(res[75], DIGIT_MASK); res[76] = add64(res[76], srli64(res[75], DIGIT_SIZE)); r[16] = and64_const(res[76], DIGIT_MASK); res[77] = add64(res[77], srli64(res[76], DIGIT_SIZE)); r[17] = and64_const(res[77], DIGIT_MASK); res[78] = add64(res[78], srli64(res[77], DIGIT_SIZE)); r[18] = and64_const(res[78], DIGIT_MASK); res[79] = add64(res[79], srli64(res[78], DIGIT_SIZE)); r[19] = and64_const(res[79], DIGIT_MASK); res[80] = add64(res[80], srli64(res[79], DIGIT_SIZE)); r[20] = and64_const(res[80], DIGIT_MASK); res[81] = add64(res[81], srli64(res[80], DIGIT_SIZE)); r[21] = and64_const(res[81], DIGIT_MASK); res[82] = add64(res[82], srli64(res[81], DIGIT_SIZE)); r[22] = and64_const(res[82], DIGIT_MASK); res[83] = add64(res[83], srli64(res[82], DIGIT_SIZE)); r[23] = and64_const(res[83], DIGIT_MASK); res[84] = add64(res[84], srli64(res[83], DIGIT_SIZE)); r[24] = and64_const(res[84], DIGIT_MASK); res[85] = add64(res[85], srli64(res[84], DIGIT_SIZE)); r[25] = and64_const(res[85], DIGIT_MASK); res[86] = add64(res[86], srli64(res[85], DIGIT_SIZE)); r[26] = and64_const(res[86], DIGIT_MASK); res[87] = add64(res[87], srli64(res[86], DIGIT_SIZE)); r[27] = and64_const(res[87], DIGIT_MASK); res[88] = add64(res[88], srli64(res[87], DIGIT_SIZE)); r[28] = and64_const(res[88], DIGIT_MASK); res[89] = add64(res[89], srli64(res[88], DIGIT_SIZE)); r[29] = and64_const(res[89], DIGIT_MASK); res[90] = add64(res[90], srli64(res[89], DIGIT_SIZE)); r[30] = and64_const(res[90], DIGIT_MASK); res[91] = add64(res[91], srli64(res[90], DIGIT_SIZE)); r[31] = and64_const(res[91], DIGIT_MASK); res[92] = add64(res[92], srli64(res[91], DIGIT_SIZE)); r[32] = and64_const(res[92], DIGIT_MASK); res[93] = add64(res[93], srli64(res[92], DIGIT_SIZE)); r[33] = and64_const(res[93], DIGIT_MASK); res[94] = add64(res[94], srli64(res[93], DIGIT_SIZE)); r[34] = and64_const(res[94], DIGIT_MASK); res[95] = add64(res[95], srli64(res[94], DIGIT_SIZE)); r[35] = and64_const(res[95], DIGIT_MASK); res[96] = add64(res[96], srli64(res[95], DIGIT_SIZE)); r[36] = and64_const(res[96], DIGIT_MASK); res[97] = add64(res[97], srli64(res[96], DIGIT_SIZE)); r[37] = and64_const(res[97], DIGIT_MASK); res[98] = add64(res[98], srli64(res[97], DIGIT_SIZE)); r[38] = and64_const(res[98], DIGIT_MASK); res[99] = add64(res[99], srli64(res[98], DIGIT_SIZE)); r[39] = and64_const(res[99], DIGIT_MASK); res[100] = add64(res[100], srli64(res[99], DIGIT_SIZE)); r[40] = and64_const(res[100], DIGIT_MASK); res[101] = add64(res[101], srli64(res[100], DIGIT_SIZE)); r[41] = and64_const(res[101], DIGIT_MASK); res[102] = add64(res[102], srli64(res[101], DIGIT_SIZE)); r[42] = and64_const(res[102], DIGIT_MASK); res[103] = add64(res[103], srli64(res[102], DIGIT_SIZE)); r[43] = and64_const(res[103], DIGIT_MASK); res[104] = add64(res[104], srli64(res[103], DIGIT_SIZE)); r[44] = and64_const(res[104], DIGIT_MASK); res[105] = add64(res[105], srli64(res[104], DIGIT_SIZE)); r[45] = and64_const(res[105], DIGIT_MASK); res[106] = add64(res[106], srli64(res[105], DIGIT_SIZE)); r[46] = and64_const(res[106], DIGIT_MASK); res[107] = add64(res[107], srli64(res[106], DIGIT_SIZE)); r[47] = and64_const(res[107], DIGIT_MASK); res[108] = add64(res[108], srli64(res[107], DIGIT_SIZE)); r[48] = and64_const(res[108], DIGIT_MASK); res[109] = add64(res[109], srli64(res[108], DIGIT_SIZE)); r[49] = and64_const(res[109], DIGIT_MASK); res[110] = add64(res[110], srli64(res[109], DIGIT_SIZE)); r[50] = and64_const(res[110], DIGIT_MASK); res[111] = add64(res[111], srli64(res[110], DIGIT_SIZE)); r[51] = and64_const(res[111], DIGIT_MASK); res[112] = add64(res[112], srli64(res[111], DIGIT_SIZE)); r[52] = and64_const(res[112], DIGIT_MASK); res[113] = add64(res[113], srli64(res[112], DIGIT_SIZE)); r[53] = and64_const(res[113], DIGIT_MASK); res[114] = add64(res[114], srli64(res[113], DIGIT_SIZE)); r[54] = and64_const(res[114], DIGIT_MASK); res[115] = add64(res[115], srli64(res[114], DIGIT_SIZE)); r[55] = and64_const(res[115], DIGIT_MASK); res[116] = add64(res[116], srli64(res[115], DIGIT_SIZE)); r[56] = and64_const(res[116], DIGIT_MASK); res[117] = add64(res[117], srli64(res[116], DIGIT_SIZE)); r[57] = and64_const(res[117], DIGIT_MASK); res[118] = add64(res[118], srli64(res[117], DIGIT_SIZE)); r[58] = and64_const(res[118], DIGIT_MASK); res[119] = add64(res[119], srli64(res[118], DIGIT_SIZE)); r[59] = and64_const(res[119], DIGIT_MASK); } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams52x79_diagonal_mb8.c000066400000000000000000014654551470420105600345350ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) #include void AMS52x79_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { __ALIGN64 U64 res[160]; __ALIGN64 U64 u[80]; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; k = loadu64((U64 *)k0_mb); int i; for (i = 0; i < 160; ++i) res[i] = get_zero64(); // Calculate full square res[1] = fma52lo(res[1], a[0], a[1]); // Sum(1) res[2] = fma52hi(res[2], a[0], a[1]); // Sum(1) res[2] = fma52lo(res[2], a[0], a[2]); // Sum(2) res[3] = fma52hi(res[3], a[0], a[2]); // Sum(2) res[3] = fma52lo(res[3], a[1], a[2]); // Sum(3) res[4] = fma52hi(res[4], a[1], a[2]); // Sum(3) res[3] = fma52lo(res[3], a[0], a[3]); // Sum(3) res[4] = fma52hi(res[4], a[0], a[3]); // Sum(3) res[4] = fma52lo(res[4], a[1], a[3]); // Sum(4) res[5] = fma52hi(res[5], a[1], a[3]); // Sum(4) res[5] = fma52lo(res[5], a[2], a[3]); // Sum(5) res[6] = fma52hi(res[6], a[2], a[3]); // Sum(5) res[4] = fma52lo(res[4], a[0], a[4]); // Sum(4) res[5] = fma52hi(res[5], a[0], a[4]); // Sum(4) res[5] = fma52lo(res[5], a[1], a[4]); // Sum(5) res[6] = fma52hi(res[6], a[1], a[4]); // Sum(5) res[6] = fma52lo(res[6], a[2], a[4]); // Sum(6) res[7] = fma52hi(res[7], a[2], a[4]); // Sum(6) res[7] = fma52lo(res[7], a[3], a[4]); // Sum(7) res[8] = fma52hi(res[8], a[3], a[4]); // Sum(7) res[5] = fma52lo(res[5], a[0], a[5]); // Sum(5) res[6] = fma52hi(res[6], a[0], a[5]); // Sum(5) res[6] = fma52lo(res[6], a[1], a[5]); // Sum(6) res[7] = fma52hi(res[7], a[1], a[5]); // Sum(6) res[7] = fma52lo(res[7], a[2], a[5]); // Sum(7) res[8] = fma52hi(res[8], a[2], a[5]); // Sum(7) res[8] = fma52lo(res[8], a[3], a[5]); // Sum(8) res[9] = fma52hi(res[9], a[3], a[5]); // Sum(8) res[9] = fma52lo(res[9], a[4], a[5]); // Sum(9) res[10] = fma52hi(res[10], a[4], a[5]); // Sum(9) res[6] = fma52lo(res[6], a[0], a[6]); // Sum(6) res[7] = fma52hi(res[7], a[0], a[6]); // Sum(6) res[7] = fma52lo(res[7], a[1], a[6]); // Sum(7) res[8] = fma52hi(res[8], a[1], a[6]); // Sum(7) res[8] = fma52lo(res[8], a[2], a[6]); // Sum(8) res[9] = fma52hi(res[9], a[2], a[6]); // Sum(8) res[9] = fma52lo(res[9], a[3], a[6]); // Sum(9) res[10] = fma52hi(res[10], a[3], a[6]); // Sum(9) res[10] = fma52lo(res[10], a[4], a[6]); // Sum(10) res[11] = fma52hi(res[11], a[4], a[6]); // Sum(10) res[11] = fma52lo(res[11], a[5], a[6]); // Sum(11) res[12] = fma52hi(res[12], a[5], a[6]); // Sum(11) res[7] = fma52lo(res[7], a[0], a[7]); // Sum(7) res[8] = fma52hi(res[8], a[0], a[7]); // Sum(7) res[8] = fma52lo(res[8], a[1], a[7]); // Sum(8) res[9] = fma52hi(res[9], a[1], a[7]); // Sum(8) res[9] = fma52lo(res[9], a[2], a[7]); // Sum(9) res[10] = fma52hi(res[10], a[2], a[7]); // Sum(9) res[10] = fma52lo(res[10], a[3], a[7]); // Sum(10) res[11] = fma52hi(res[11], a[3], a[7]); // Sum(10) res[11] = fma52lo(res[11], a[4], a[7]); // Sum(11) res[12] = fma52hi(res[12], a[4], a[7]); // Sum(11) res[8] = fma52lo(res[8], a[0], a[8]); // Sum(8) res[9] = fma52hi(res[9], a[0], a[8]); // Sum(8) res[9] = fma52lo(res[9], a[1], a[8]); // Sum(9) res[10] = fma52hi(res[10], a[1], a[8]); // Sum(9) res[10] = fma52lo(res[10], a[2], a[8]); // Sum(10) res[11] = fma52hi(res[11], a[2], a[8]); // Sum(10) res[11] = fma52lo(res[11], a[3], a[8]); // Sum(11) res[12] = fma52hi(res[12], a[3], a[8]); // Sum(11) res[9] = fma52lo(res[9], a[0], a[9]); // Sum(9) res[10] = fma52hi(res[10], a[0], a[9]); // Sum(9) res[10] = fma52lo(res[10], a[1], a[9]); // Sum(10) res[11] = fma52hi(res[11], a[1], a[9]); // Sum(10) res[11] = fma52lo(res[11], a[2], a[9]); // Sum(11) res[12] = fma52hi(res[12], a[2], a[9]); // Sum(11) res[10] = fma52lo(res[10], a[0], a[10]); // Sum(10) res[11] = fma52hi(res[11], a[0], a[10]); // Sum(10) res[11] = fma52lo(res[11], a[1], a[10]); // Sum(11) res[12] = fma52hi(res[12], a[1], a[10]); // Sum(11) res[11] = fma52lo(res[11], a[0], a[11]); // Sum(11) res[12] = fma52hi(res[12], a[0], a[11]); // Sum(11) res[0] = add64(res[0], res[0]); // Double(0) res[1] = add64(res[1], res[1]); // Double(1) res[2] = add64(res[2], res[2]); // Double(2) res[3] = add64(res[3], res[3]); // Double(3) res[4] = add64(res[4], res[4]); // Double(4) res[5] = add64(res[5], res[5]); // Double(5) res[6] = add64(res[6], res[6]); // Double(6) res[7] = add64(res[7], res[7]); // Double(7) res[8] = add64(res[8], res[8]); // Double(8) res[9] = add64(res[9], res[9]); // Double(9) res[10] = add64(res[10], res[10]); // Double(10) res[11] = add64(res[11], res[11]); // Double(11) res[0] = fma52lo(res[0], a[0], a[0]); // Add sqr(0) res[1] = fma52hi(res[1], a[0], a[0]); // Add sqr(0) res[2] = fma52lo(res[2], a[1], a[1]); // Add sqr(2) res[3] = fma52hi(res[3], a[1], a[1]); // Add sqr(2) res[4] = fma52lo(res[4], a[2], a[2]); // Add sqr(4) res[5] = fma52hi(res[5], a[2], a[2]); // Add sqr(4) res[6] = fma52lo(res[6], a[3], a[3]); // Add sqr(6) res[7] = fma52hi(res[7], a[3], a[3]); // Add sqr(6) res[8] = fma52lo(res[8], a[4], a[4]); // Add sqr(8) res[9] = fma52hi(res[9], a[4], a[4]); // Add sqr(8) res[10] = fma52lo(res[10], a[5], a[5]); // Add sqr(10) res[11] = fma52hi(res[11], a[5], a[5]); // Add sqr(10) res[12] = fma52lo(res[12], a[5], a[7]); // Sum(12) res[13] = fma52hi(res[13], a[5], a[7]); // Sum(12) res[13] = fma52lo(res[13], a[6], a[7]); // Sum(13) res[14] = fma52hi(res[14], a[6], a[7]); // Sum(13) res[12] = fma52lo(res[12], a[4], a[8]); // Sum(12) res[13] = fma52hi(res[13], a[4], a[8]); // Sum(12) res[13] = fma52lo(res[13], a[5], a[8]); // Sum(13) res[14] = fma52hi(res[14], a[5], a[8]); // Sum(13) res[14] = fma52lo(res[14], a[6], a[8]); // Sum(14) res[15] = fma52hi(res[15], a[6], a[8]); // Sum(14) res[15] = fma52lo(res[15], a[7], a[8]); // Sum(15) res[16] = fma52hi(res[16], a[7], a[8]); // Sum(15) res[12] = fma52lo(res[12], a[3], a[9]); // Sum(12) res[13] = fma52hi(res[13], a[3], a[9]); // Sum(12) res[13] = fma52lo(res[13], a[4], a[9]); // Sum(13) res[14] = fma52hi(res[14], a[4], a[9]); // Sum(13) res[14] = fma52lo(res[14], a[5], a[9]); // Sum(14) res[15] = fma52hi(res[15], a[5], a[9]); // Sum(14) res[15] = fma52lo(res[15], a[6], a[9]); // Sum(15) res[16] = fma52hi(res[16], a[6], a[9]); // Sum(15) res[16] = fma52lo(res[16], a[7], a[9]); // Sum(16) res[17] = fma52hi(res[17], a[7], a[9]); // Sum(16) res[17] = fma52lo(res[17], a[8], a[9]); // Sum(17) res[18] = fma52hi(res[18], a[8], a[9]); // Sum(17) res[12] = fma52lo(res[12], a[2], a[10]); // Sum(12) res[13] = fma52hi(res[13], a[2], a[10]); // Sum(12) res[13] = fma52lo(res[13], a[3], a[10]); // Sum(13) res[14] = fma52hi(res[14], a[3], a[10]); // Sum(13) res[14] = fma52lo(res[14], a[4], a[10]); // Sum(14) res[15] = fma52hi(res[15], a[4], a[10]); // Sum(14) res[15] = fma52lo(res[15], a[5], a[10]); // Sum(15) res[16] = fma52hi(res[16], a[5], a[10]); // Sum(15) res[16] = fma52lo(res[16], a[6], a[10]); // Sum(16) res[17] = fma52hi(res[17], a[6], a[10]); // Sum(16) res[17] = fma52lo(res[17], a[7], a[10]); // Sum(17) res[18] = fma52hi(res[18], a[7], a[10]); // Sum(17) res[18] = fma52lo(res[18], a[8], a[10]); // Sum(18) res[19] = fma52hi(res[19], a[8], a[10]); // Sum(18) res[19] = fma52lo(res[19], a[9], a[10]); // Sum(19) res[20] = fma52hi(res[20], a[9], a[10]); // Sum(19) res[12] = fma52lo(res[12], a[1], a[11]); // Sum(12) res[13] = fma52hi(res[13], a[1], a[11]); // Sum(12) res[13] = fma52lo(res[13], a[2], a[11]); // Sum(13) res[14] = fma52hi(res[14], a[2], a[11]); // Sum(13) res[14] = fma52lo(res[14], a[3], a[11]); // Sum(14) res[15] = fma52hi(res[15], a[3], a[11]); // Sum(14) res[15] = fma52lo(res[15], a[4], a[11]); // Sum(15) res[16] = fma52hi(res[16], a[4], a[11]); // Sum(15) res[16] = fma52lo(res[16], a[5], a[11]); // Sum(16) res[17] = fma52hi(res[17], a[5], a[11]); // Sum(16) res[17] = fma52lo(res[17], a[6], a[11]); // Sum(17) res[18] = fma52hi(res[18], a[6], a[11]); // Sum(17) res[18] = fma52lo(res[18], a[7], a[11]); // Sum(18) res[19] = fma52hi(res[19], a[7], a[11]); // Sum(18) res[19] = fma52lo(res[19], a[8], a[11]); // Sum(19) res[20] = fma52hi(res[20], a[8], a[11]); // Sum(19) res[20] = fma52lo(res[20], a[9], a[11]); // Sum(20) res[21] = fma52hi(res[21], a[9], a[11]); // Sum(20) res[21] = fma52lo(res[21], a[10], a[11]); // Sum(21) res[22] = fma52hi(res[22], a[10], a[11]); // Sum(21) res[12] = fma52lo(res[12], a[0], a[12]); // Sum(12) res[13] = fma52hi(res[13], a[0], a[12]); // Sum(12) res[13] = fma52lo(res[13], a[1], a[12]); // Sum(13) res[14] = fma52hi(res[14], a[1], a[12]); // Sum(13) res[14] = fma52lo(res[14], a[2], a[12]); // Sum(14) res[15] = fma52hi(res[15], a[2], a[12]); // Sum(14) res[15] = fma52lo(res[15], a[3], a[12]); // Sum(15) res[16] = fma52hi(res[16], a[3], a[12]); // Sum(15) res[16] = fma52lo(res[16], a[4], a[12]); // Sum(16) res[17] = fma52hi(res[17], a[4], a[12]); // Sum(16) res[17] = fma52lo(res[17], a[5], a[12]); // Sum(17) res[18] = fma52hi(res[18], a[5], a[12]); // Sum(17) res[18] = fma52lo(res[18], a[6], a[12]); // Sum(18) res[19] = fma52hi(res[19], a[6], a[12]); // Sum(18) res[19] = fma52lo(res[19], a[7], a[12]); // Sum(19) res[20] = fma52hi(res[20], a[7], a[12]); // Sum(19) res[20] = fma52lo(res[20], a[8], a[12]); // Sum(20) res[21] = fma52hi(res[21], a[8], a[12]); // Sum(20) res[21] = fma52lo(res[21], a[9], a[12]); // Sum(21) res[22] = fma52hi(res[22], a[9], a[12]); // Sum(21) res[22] = fma52lo(res[22], a[10], a[12]); // Sum(22) res[23] = fma52hi(res[23], a[10], a[12]); // Sum(22) res[23] = fma52lo(res[23], a[11], a[12]); // Sum(23) res[24] = fma52hi(res[24], a[11], a[12]); // Sum(23) res[13] = fma52lo(res[13], a[0], a[13]); // Sum(13) res[14] = fma52hi(res[14], a[0], a[13]); // Sum(13) res[14] = fma52lo(res[14], a[1], a[13]); // Sum(14) res[15] = fma52hi(res[15], a[1], a[13]); // Sum(14) res[15] = fma52lo(res[15], a[2], a[13]); // Sum(15) res[16] = fma52hi(res[16], a[2], a[13]); // Sum(15) res[16] = fma52lo(res[16], a[3], a[13]); // Sum(16) res[17] = fma52hi(res[17], a[3], a[13]); // Sum(16) res[17] = fma52lo(res[17], a[4], a[13]); // Sum(17) res[18] = fma52hi(res[18], a[4], a[13]); // Sum(17) res[18] = fma52lo(res[18], a[5], a[13]); // Sum(18) res[19] = fma52hi(res[19], a[5], a[13]); // Sum(18) res[19] = fma52lo(res[19], a[6], a[13]); // Sum(19) res[20] = fma52hi(res[20], a[6], a[13]); // Sum(19) res[20] = fma52lo(res[20], a[7], a[13]); // Sum(20) res[21] = fma52hi(res[21], a[7], a[13]); // Sum(20) res[21] = fma52lo(res[21], a[8], a[13]); // Sum(21) res[22] = fma52hi(res[22], a[8], a[13]); // Sum(21) res[22] = fma52lo(res[22], a[9], a[13]); // Sum(22) res[23] = fma52hi(res[23], a[9], a[13]); // Sum(22) res[23] = fma52lo(res[23], a[10], a[13]); // Sum(23) res[24] = fma52hi(res[24], a[10], a[13]); // Sum(23) res[14] = fma52lo(res[14], a[0], a[14]); // Sum(14) res[15] = fma52hi(res[15], a[0], a[14]); // Sum(14) res[15] = fma52lo(res[15], a[1], a[14]); // Sum(15) res[16] = fma52hi(res[16], a[1], a[14]); // Sum(15) res[16] = fma52lo(res[16], a[2], a[14]); // Sum(16) res[17] = fma52hi(res[17], a[2], a[14]); // Sum(16) res[17] = fma52lo(res[17], a[3], a[14]); // Sum(17) res[18] = fma52hi(res[18], a[3], a[14]); // Sum(17) res[18] = fma52lo(res[18], a[4], a[14]); // Sum(18) res[19] = fma52hi(res[19], a[4], a[14]); // Sum(18) res[19] = fma52lo(res[19], a[5], a[14]); // Sum(19) res[20] = fma52hi(res[20], a[5], a[14]); // Sum(19) res[20] = fma52lo(res[20], a[6], a[14]); // Sum(20) res[21] = fma52hi(res[21], a[6], a[14]); // Sum(20) res[21] = fma52lo(res[21], a[7], a[14]); // Sum(21) res[22] = fma52hi(res[22], a[7], a[14]); // Sum(21) res[22] = fma52lo(res[22], a[8], a[14]); // Sum(22) res[23] = fma52hi(res[23], a[8], a[14]); // Sum(22) res[23] = fma52lo(res[23], a[9], a[14]); // Sum(23) res[24] = fma52hi(res[24], a[9], a[14]); // Sum(23) res[15] = fma52lo(res[15], a[0], a[15]); // Sum(15) res[16] = fma52hi(res[16], a[0], a[15]); // Sum(15) res[16] = fma52lo(res[16], a[1], a[15]); // Sum(16) res[17] = fma52hi(res[17], a[1], a[15]); // Sum(16) res[17] = fma52lo(res[17], a[2], a[15]); // Sum(17) res[18] = fma52hi(res[18], a[2], a[15]); // Sum(17) res[18] = fma52lo(res[18], a[3], a[15]); // Sum(18) res[19] = fma52hi(res[19], a[3], a[15]); // Sum(18) res[19] = fma52lo(res[19], a[4], a[15]); // Sum(19) res[20] = fma52hi(res[20], a[4], a[15]); // Sum(19) res[20] = fma52lo(res[20], a[5], a[15]); // Sum(20) res[21] = fma52hi(res[21], a[5], a[15]); // Sum(20) res[21] = fma52lo(res[21], a[6], a[15]); // Sum(21) res[22] = fma52hi(res[22], a[6], a[15]); // Sum(21) res[22] = fma52lo(res[22], a[7], a[15]); // Sum(22) res[23] = fma52hi(res[23], a[7], a[15]); // Sum(22) res[23] = fma52lo(res[23], a[8], a[15]); // Sum(23) res[24] = fma52hi(res[24], a[8], a[15]); // Sum(23) res[16] = fma52lo(res[16], a[0], a[16]); // Sum(16) res[17] = fma52hi(res[17], a[0], a[16]); // Sum(16) res[17] = fma52lo(res[17], a[1], a[16]); // Sum(17) res[18] = fma52hi(res[18], a[1], a[16]); // Sum(17) res[18] = fma52lo(res[18], a[2], a[16]); // Sum(18) res[19] = fma52hi(res[19], a[2], a[16]); // Sum(18) res[19] = fma52lo(res[19], a[3], a[16]); // Sum(19) res[20] = fma52hi(res[20], a[3], a[16]); // Sum(19) res[20] = fma52lo(res[20], a[4], a[16]); // Sum(20) res[21] = fma52hi(res[21], a[4], a[16]); // Sum(20) res[21] = fma52lo(res[21], a[5], a[16]); // Sum(21) res[22] = fma52hi(res[22], a[5], a[16]); // Sum(21) res[22] = fma52lo(res[22], a[6], a[16]); // Sum(22) res[23] = fma52hi(res[23], a[6], a[16]); // Sum(22) res[23] = fma52lo(res[23], a[7], a[16]); // Sum(23) res[24] = fma52hi(res[24], a[7], a[16]); // Sum(23) res[17] = fma52lo(res[17], a[0], a[17]); // Sum(17) res[18] = fma52hi(res[18], a[0], a[17]); // Sum(17) res[18] = fma52lo(res[18], a[1], a[17]); // Sum(18) res[19] = fma52hi(res[19], a[1], a[17]); // Sum(18) res[19] = fma52lo(res[19], a[2], a[17]); // Sum(19) res[20] = fma52hi(res[20], a[2], a[17]); // Sum(19) res[20] = fma52lo(res[20], a[3], a[17]); // Sum(20) res[21] = fma52hi(res[21], a[3], a[17]); // Sum(20) res[21] = fma52lo(res[21], a[4], a[17]); // Sum(21) res[22] = fma52hi(res[22], a[4], a[17]); // Sum(21) res[22] = fma52lo(res[22], a[5], a[17]); // Sum(22) res[23] = fma52hi(res[23], a[5], a[17]); // Sum(22) res[23] = fma52lo(res[23], a[6], a[17]); // Sum(23) res[24] = fma52hi(res[24], a[6], a[17]); // Sum(23) res[18] = fma52lo(res[18], a[0], a[18]); // Sum(18) res[19] = fma52hi(res[19], a[0], a[18]); // Sum(18) res[19] = fma52lo(res[19], a[1], a[18]); // Sum(19) res[20] = fma52hi(res[20], a[1], a[18]); // Sum(19) res[20] = fma52lo(res[20], a[2], a[18]); // Sum(20) res[21] = fma52hi(res[21], a[2], a[18]); // Sum(20) res[21] = fma52lo(res[21], a[3], a[18]); // Sum(21) res[22] = fma52hi(res[22], a[3], a[18]); // Sum(21) res[22] = fma52lo(res[22], a[4], a[18]); // Sum(22) res[23] = fma52hi(res[23], a[4], a[18]); // Sum(22) res[23] = fma52lo(res[23], a[5], a[18]); // Sum(23) res[24] = fma52hi(res[24], a[5], a[18]); // Sum(23) res[19] = fma52lo(res[19], a[0], a[19]); // Sum(19) res[20] = fma52hi(res[20], a[0], a[19]); // Sum(19) res[20] = fma52lo(res[20], a[1], a[19]); // Sum(20) res[21] = fma52hi(res[21], a[1], a[19]); // Sum(20) res[21] = fma52lo(res[21], a[2], a[19]); // Sum(21) res[22] = fma52hi(res[22], a[2], a[19]); // Sum(21) res[22] = fma52lo(res[22], a[3], a[19]); // Sum(22) res[23] = fma52hi(res[23], a[3], a[19]); // Sum(22) res[23] = fma52lo(res[23], a[4], a[19]); // Sum(23) res[24] = fma52hi(res[24], a[4], a[19]); // Sum(23) res[20] = fma52lo(res[20], a[0], a[20]); // Sum(20) res[21] = fma52hi(res[21], a[0], a[20]); // Sum(20) res[21] = fma52lo(res[21], a[1], a[20]); // Sum(21) res[22] = fma52hi(res[22], a[1], a[20]); // Sum(21) res[22] = fma52lo(res[22], a[2], a[20]); // Sum(22) res[23] = fma52hi(res[23], a[2], a[20]); // Sum(22) res[23] = fma52lo(res[23], a[3], a[20]); // Sum(23) res[24] = fma52hi(res[24], a[3], a[20]); // Sum(23) res[21] = fma52lo(res[21], a[0], a[21]); // Sum(21) res[22] = fma52hi(res[22], a[0], a[21]); // Sum(21) res[22] = fma52lo(res[22], a[1], a[21]); // Sum(22) res[23] = fma52hi(res[23], a[1], a[21]); // Sum(22) res[23] = fma52lo(res[23], a[2], a[21]); // Sum(23) res[24] = fma52hi(res[24], a[2], a[21]); // Sum(23) res[22] = fma52lo(res[22], a[0], a[22]); // Sum(22) res[23] = fma52hi(res[23], a[0], a[22]); // Sum(22) res[23] = fma52lo(res[23], a[1], a[22]); // Sum(23) res[24] = fma52hi(res[24], a[1], a[22]); // Sum(23) res[23] = fma52lo(res[23], a[0], a[23]); // Sum(23) res[24] = fma52hi(res[24], a[0], a[23]); // Sum(23) res[12] = add64(res[12], res[12]); // Double(12) res[13] = add64(res[13], res[13]); // Double(13) res[14] = add64(res[14], res[14]); // Double(14) res[15] = add64(res[15], res[15]); // Double(15) res[16] = add64(res[16], res[16]); // Double(16) res[17] = add64(res[17], res[17]); // Double(17) res[18] = add64(res[18], res[18]); // Double(18) res[19] = add64(res[19], res[19]); // Double(19) res[20] = add64(res[20], res[20]); // Double(20) res[21] = add64(res[21], res[21]); // Double(21) res[22] = add64(res[22], res[22]); // Double(22) res[23] = add64(res[23], res[23]); // Double(23) res[12] = fma52lo(res[12], a[6], a[6]); // Add sqr(12) res[13] = fma52hi(res[13], a[6], a[6]); // Add sqr(12) res[14] = fma52lo(res[14], a[7], a[7]); // Add sqr(14) res[15] = fma52hi(res[15], a[7], a[7]); // Add sqr(14) res[16] = fma52lo(res[16], a[8], a[8]); // Add sqr(16) res[17] = fma52hi(res[17], a[8], a[8]); // Add sqr(16) res[18] = fma52lo(res[18], a[9], a[9]); // Add sqr(18) res[19] = fma52hi(res[19], a[9], a[9]); // Add sqr(18) res[20] = fma52lo(res[20], a[10], a[10]); // Add sqr(20) res[21] = fma52hi(res[21], a[10], a[10]); // Add sqr(20) res[22] = fma52lo(res[22], a[11], a[11]); // Add sqr(22) res[23] = fma52hi(res[23], a[11], a[11]); // Add sqr(22) res[24] = fma52lo(res[24], a[11], a[13]); // Sum(24) res[25] = fma52hi(res[25], a[11], a[13]); // Sum(24) res[25] = fma52lo(res[25], a[12], a[13]); // Sum(25) res[26] = fma52hi(res[26], a[12], a[13]); // Sum(25) res[24] = fma52lo(res[24], a[10], a[14]); // Sum(24) res[25] = fma52hi(res[25], a[10], a[14]); // Sum(24) res[25] = fma52lo(res[25], a[11], a[14]); // Sum(25) res[26] = fma52hi(res[26], a[11], a[14]); // Sum(25) res[26] = fma52lo(res[26], a[12], a[14]); // Sum(26) res[27] = fma52hi(res[27], a[12], a[14]); // Sum(26) res[27] = fma52lo(res[27], a[13], a[14]); // Sum(27) res[28] = fma52hi(res[28], a[13], a[14]); // Sum(27) res[24] = fma52lo(res[24], a[9], a[15]); // Sum(24) res[25] = fma52hi(res[25], a[9], a[15]); // Sum(24) res[25] = fma52lo(res[25], a[10], a[15]); // Sum(25) res[26] = fma52hi(res[26], a[10], a[15]); // Sum(25) res[26] = fma52lo(res[26], a[11], a[15]); // Sum(26) res[27] = fma52hi(res[27], a[11], a[15]); // Sum(26) res[27] = fma52lo(res[27], a[12], a[15]); // Sum(27) res[28] = fma52hi(res[28], a[12], a[15]); // Sum(27) res[28] = fma52lo(res[28], a[13], a[15]); // Sum(28) res[29] = fma52hi(res[29], a[13], a[15]); // Sum(28) res[29] = fma52lo(res[29], a[14], a[15]); // Sum(29) res[30] = fma52hi(res[30], a[14], a[15]); // Sum(29) res[24] = fma52lo(res[24], a[8], a[16]); // Sum(24) res[25] = fma52hi(res[25], a[8], a[16]); // Sum(24) res[25] = fma52lo(res[25], a[9], a[16]); // Sum(25) res[26] = fma52hi(res[26], a[9], a[16]); // Sum(25) res[26] = fma52lo(res[26], a[10], a[16]); // Sum(26) res[27] = fma52hi(res[27], a[10], a[16]); // Sum(26) res[27] = fma52lo(res[27], a[11], a[16]); // Sum(27) res[28] = fma52hi(res[28], a[11], a[16]); // Sum(27) res[28] = fma52lo(res[28], a[12], a[16]); // Sum(28) res[29] = fma52hi(res[29], a[12], a[16]); // Sum(28) res[29] = fma52lo(res[29], a[13], a[16]); // Sum(29) res[30] = fma52hi(res[30], a[13], a[16]); // Sum(29) res[30] = fma52lo(res[30], a[14], a[16]); // Sum(30) res[31] = fma52hi(res[31], a[14], a[16]); // Sum(30) res[31] = fma52lo(res[31], a[15], a[16]); // Sum(31) res[32] = fma52hi(res[32], a[15], a[16]); // Sum(31) res[24] = fma52lo(res[24], a[7], a[17]); // Sum(24) res[25] = fma52hi(res[25], a[7], a[17]); // Sum(24) res[25] = fma52lo(res[25], a[8], a[17]); // Sum(25) res[26] = fma52hi(res[26], a[8], a[17]); // Sum(25) res[26] = fma52lo(res[26], a[9], a[17]); // Sum(26) res[27] = fma52hi(res[27], a[9], a[17]); // Sum(26) res[27] = fma52lo(res[27], a[10], a[17]); // Sum(27) res[28] = fma52hi(res[28], a[10], a[17]); // Sum(27) res[28] = fma52lo(res[28], a[11], a[17]); // Sum(28) res[29] = fma52hi(res[29], a[11], a[17]); // Sum(28) res[29] = fma52lo(res[29], a[12], a[17]); // Sum(29) res[30] = fma52hi(res[30], a[12], a[17]); // Sum(29) res[30] = fma52lo(res[30], a[13], a[17]); // Sum(30) res[31] = fma52hi(res[31], a[13], a[17]); // Sum(30) res[31] = fma52lo(res[31], a[14], a[17]); // Sum(31) res[32] = fma52hi(res[32], a[14], a[17]); // Sum(31) res[32] = fma52lo(res[32], a[15], a[17]); // Sum(32) res[33] = fma52hi(res[33], a[15], a[17]); // Sum(32) res[33] = fma52lo(res[33], a[16], a[17]); // Sum(33) res[34] = fma52hi(res[34], a[16], a[17]); // Sum(33) res[24] = fma52lo(res[24], a[6], a[18]); // Sum(24) res[25] = fma52hi(res[25], a[6], a[18]); // Sum(24) res[25] = fma52lo(res[25], a[7], a[18]); // Sum(25) res[26] = fma52hi(res[26], a[7], a[18]); // Sum(25) res[26] = fma52lo(res[26], a[8], a[18]); // Sum(26) res[27] = fma52hi(res[27], a[8], a[18]); // Sum(26) res[27] = fma52lo(res[27], a[9], a[18]); // Sum(27) res[28] = fma52hi(res[28], a[9], a[18]); // Sum(27) res[28] = fma52lo(res[28], a[10], a[18]); // Sum(28) res[29] = fma52hi(res[29], a[10], a[18]); // Sum(28) res[29] = fma52lo(res[29], a[11], a[18]); // Sum(29) res[30] = fma52hi(res[30], a[11], a[18]); // Sum(29) res[30] = fma52lo(res[30], a[12], a[18]); // Sum(30) res[31] = fma52hi(res[31], a[12], a[18]); // Sum(30) res[31] = fma52lo(res[31], a[13], a[18]); // Sum(31) res[32] = fma52hi(res[32], a[13], a[18]); // Sum(31) res[32] = fma52lo(res[32], a[14], a[18]); // Sum(32) res[33] = fma52hi(res[33], a[14], a[18]); // Sum(32) res[33] = fma52lo(res[33], a[15], a[18]); // Sum(33) res[34] = fma52hi(res[34], a[15], a[18]); // Sum(33) res[34] = fma52lo(res[34], a[16], a[18]); // Sum(34) res[35] = fma52hi(res[35], a[16], a[18]); // Sum(34) res[35] = fma52lo(res[35], a[17], a[18]); // Sum(35) res[36] = fma52hi(res[36], a[17], a[18]); // Sum(35) res[24] = fma52lo(res[24], a[5], a[19]); // Sum(24) res[25] = fma52hi(res[25], a[5], a[19]); // Sum(24) res[25] = fma52lo(res[25], a[6], a[19]); // Sum(25) res[26] = fma52hi(res[26], a[6], a[19]); // Sum(25) res[26] = fma52lo(res[26], a[7], a[19]); // Sum(26) res[27] = fma52hi(res[27], a[7], a[19]); // Sum(26) res[27] = fma52lo(res[27], a[8], a[19]); // Sum(27) res[28] = fma52hi(res[28], a[8], a[19]); // Sum(27) res[28] = fma52lo(res[28], a[9], a[19]); // Sum(28) res[29] = fma52hi(res[29], a[9], a[19]); // Sum(28) res[29] = fma52lo(res[29], a[10], a[19]); // Sum(29) res[30] = fma52hi(res[30], a[10], a[19]); // Sum(29) res[30] = fma52lo(res[30], a[11], a[19]); // Sum(30) res[31] = fma52hi(res[31], a[11], a[19]); // Sum(30) res[31] = fma52lo(res[31], a[12], a[19]); // Sum(31) res[32] = fma52hi(res[32], a[12], a[19]); // Sum(31) res[32] = fma52lo(res[32], a[13], a[19]); // Sum(32) res[33] = fma52hi(res[33], a[13], a[19]); // Sum(32) res[33] = fma52lo(res[33], a[14], a[19]); // Sum(33) res[34] = fma52hi(res[34], a[14], a[19]); // Sum(33) res[34] = fma52lo(res[34], a[15], a[19]); // Sum(34) res[35] = fma52hi(res[35], a[15], a[19]); // Sum(34) res[35] = fma52lo(res[35], a[16], a[19]); // Sum(35) res[36] = fma52hi(res[36], a[16], a[19]); // Sum(35) res[24] = fma52lo(res[24], a[4], a[20]); // Sum(24) res[25] = fma52hi(res[25], a[4], a[20]); // Sum(24) res[25] = fma52lo(res[25], a[5], a[20]); // Sum(25) res[26] = fma52hi(res[26], a[5], a[20]); // Sum(25) res[26] = fma52lo(res[26], a[6], a[20]); // Sum(26) res[27] = fma52hi(res[27], a[6], a[20]); // Sum(26) res[27] = fma52lo(res[27], a[7], a[20]); // Sum(27) res[28] = fma52hi(res[28], a[7], a[20]); // Sum(27) res[28] = fma52lo(res[28], a[8], a[20]); // Sum(28) res[29] = fma52hi(res[29], a[8], a[20]); // Sum(28) res[29] = fma52lo(res[29], a[9], a[20]); // Sum(29) res[30] = fma52hi(res[30], a[9], a[20]); // Sum(29) res[30] = fma52lo(res[30], a[10], a[20]); // Sum(30) res[31] = fma52hi(res[31], a[10], a[20]); // Sum(30) res[31] = fma52lo(res[31], a[11], a[20]); // Sum(31) res[32] = fma52hi(res[32], a[11], a[20]); // Sum(31) res[32] = fma52lo(res[32], a[12], a[20]); // Sum(32) res[33] = fma52hi(res[33], a[12], a[20]); // Sum(32) res[33] = fma52lo(res[33], a[13], a[20]); // Sum(33) res[34] = fma52hi(res[34], a[13], a[20]); // Sum(33) res[34] = fma52lo(res[34], a[14], a[20]); // Sum(34) res[35] = fma52hi(res[35], a[14], a[20]); // Sum(34) res[35] = fma52lo(res[35], a[15], a[20]); // Sum(35) res[36] = fma52hi(res[36], a[15], a[20]); // Sum(35) res[24] = fma52lo(res[24], a[3], a[21]); // Sum(24) res[25] = fma52hi(res[25], a[3], a[21]); // Sum(24) res[25] = fma52lo(res[25], a[4], a[21]); // Sum(25) res[26] = fma52hi(res[26], a[4], a[21]); // Sum(25) res[26] = fma52lo(res[26], a[5], a[21]); // Sum(26) res[27] = fma52hi(res[27], a[5], a[21]); // Sum(26) res[27] = fma52lo(res[27], a[6], a[21]); // Sum(27) res[28] = fma52hi(res[28], a[6], a[21]); // Sum(27) res[28] = fma52lo(res[28], a[7], a[21]); // Sum(28) res[29] = fma52hi(res[29], a[7], a[21]); // Sum(28) res[29] = fma52lo(res[29], a[8], a[21]); // Sum(29) res[30] = fma52hi(res[30], a[8], a[21]); // Sum(29) res[30] = fma52lo(res[30], a[9], a[21]); // Sum(30) res[31] = fma52hi(res[31], a[9], a[21]); // Sum(30) res[31] = fma52lo(res[31], a[10], a[21]); // Sum(31) res[32] = fma52hi(res[32], a[10], a[21]); // Sum(31) res[32] = fma52lo(res[32], a[11], a[21]); // Sum(32) res[33] = fma52hi(res[33], a[11], a[21]); // Sum(32) res[33] = fma52lo(res[33], a[12], a[21]); // Sum(33) res[34] = fma52hi(res[34], a[12], a[21]); // Sum(33) res[34] = fma52lo(res[34], a[13], a[21]); // Sum(34) res[35] = fma52hi(res[35], a[13], a[21]); // Sum(34) res[35] = fma52lo(res[35], a[14], a[21]); // Sum(35) res[36] = fma52hi(res[36], a[14], a[21]); // Sum(35) res[24] = fma52lo(res[24], a[2], a[22]); // Sum(24) res[25] = fma52hi(res[25], a[2], a[22]); // Sum(24) res[25] = fma52lo(res[25], a[3], a[22]); // Sum(25) res[26] = fma52hi(res[26], a[3], a[22]); // Sum(25) res[26] = fma52lo(res[26], a[4], a[22]); // Sum(26) res[27] = fma52hi(res[27], a[4], a[22]); // Sum(26) res[27] = fma52lo(res[27], a[5], a[22]); // Sum(27) res[28] = fma52hi(res[28], a[5], a[22]); // Sum(27) res[28] = fma52lo(res[28], a[6], a[22]); // Sum(28) res[29] = fma52hi(res[29], a[6], a[22]); // Sum(28) res[29] = fma52lo(res[29], a[7], a[22]); // Sum(29) res[30] = fma52hi(res[30], a[7], a[22]); // Sum(29) res[30] = fma52lo(res[30], a[8], a[22]); // Sum(30) res[31] = fma52hi(res[31], a[8], a[22]); // Sum(30) res[31] = fma52lo(res[31], a[9], a[22]); // Sum(31) res[32] = fma52hi(res[32], a[9], a[22]); // Sum(31) res[32] = fma52lo(res[32], a[10], a[22]); // Sum(32) res[33] = fma52hi(res[33], a[10], a[22]); // Sum(32) res[33] = fma52lo(res[33], a[11], a[22]); // Sum(33) res[34] = fma52hi(res[34], a[11], a[22]); // Sum(33) res[34] = fma52lo(res[34], a[12], a[22]); // Sum(34) res[35] = fma52hi(res[35], a[12], a[22]); // Sum(34) res[35] = fma52lo(res[35], a[13], a[22]); // Sum(35) res[36] = fma52hi(res[36], a[13], a[22]); // Sum(35) res[24] = fma52lo(res[24], a[1], a[23]); // Sum(24) res[25] = fma52hi(res[25], a[1], a[23]); // Sum(24) res[25] = fma52lo(res[25], a[2], a[23]); // Sum(25) res[26] = fma52hi(res[26], a[2], a[23]); // Sum(25) res[26] = fma52lo(res[26], a[3], a[23]); // Sum(26) res[27] = fma52hi(res[27], a[3], a[23]); // Sum(26) res[27] = fma52lo(res[27], a[4], a[23]); // Sum(27) res[28] = fma52hi(res[28], a[4], a[23]); // Sum(27) res[28] = fma52lo(res[28], a[5], a[23]); // Sum(28) res[29] = fma52hi(res[29], a[5], a[23]); // Sum(28) res[29] = fma52lo(res[29], a[6], a[23]); // Sum(29) res[30] = fma52hi(res[30], a[6], a[23]); // Sum(29) res[30] = fma52lo(res[30], a[7], a[23]); // Sum(30) res[31] = fma52hi(res[31], a[7], a[23]); // Sum(30) res[31] = fma52lo(res[31], a[8], a[23]); // Sum(31) res[32] = fma52hi(res[32], a[8], a[23]); // Sum(31) res[32] = fma52lo(res[32], a[9], a[23]); // Sum(32) res[33] = fma52hi(res[33], a[9], a[23]); // Sum(32) res[33] = fma52lo(res[33], a[10], a[23]); // Sum(33) res[34] = fma52hi(res[34], a[10], a[23]); // Sum(33) res[34] = fma52lo(res[34], a[11], a[23]); // Sum(34) res[35] = fma52hi(res[35], a[11], a[23]); // Sum(34) res[35] = fma52lo(res[35], a[12], a[23]); // Sum(35) res[36] = fma52hi(res[36], a[12], a[23]); // Sum(35) res[24] = fma52lo(res[24], a[0], a[24]); // Sum(24) res[25] = fma52hi(res[25], a[0], a[24]); // Sum(24) res[25] = fma52lo(res[25], a[1], a[24]); // Sum(25) res[26] = fma52hi(res[26], a[1], a[24]); // Sum(25) res[26] = fma52lo(res[26], a[2], a[24]); // Sum(26) res[27] = fma52hi(res[27], a[2], a[24]); // Sum(26) res[27] = fma52lo(res[27], a[3], a[24]); // Sum(27) res[28] = fma52hi(res[28], a[3], a[24]); // Sum(27) res[28] = fma52lo(res[28], a[4], a[24]); // Sum(28) res[29] = fma52hi(res[29], a[4], a[24]); // Sum(28) res[29] = fma52lo(res[29], a[5], a[24]); // Sum(29) res[30] = fma52hi(res[30], a[5], a[24]); // Sum(29) res[30] = fma52lo(res[30], a[6], a[24]); // Sum(30) res[31] = fma52hi(res[31], a[6], a[24]); // Sum(30) res[31] = fma52lo(res[31], a[7], a[24]); // Sum(31) res[32] = fma52hi(res[32], a[7], a[24]); // Sum(31) res[32] = fma52lo(res[32], a[8], a[24]); // Sum(32) res[33] = fma52hi(res[33], a[8], a[24]); // Sum(32) res[33] = fma52lo(res[33], a[9], a[24]); // Sum(33) res[34] = fma52hi(res[34], a[9], a[24]); // Sum(33) res[34] = fma52lo(res[34], a[10], a[24]); // Sum(34) res[35] = fma52hi(res[35], a[10], a[24]); // Sum(34) res[35] = fma52lo(res[35], a[11], a[24]); // Sum(35) res[36] = fma52hi(res[36], a[11], a[24]); // Sum(35) res[25] = fma52lo(res[25], a[0], a[25]); // Sum(25) res[26] = fma52hi(res[26], a[0], a[25]); // Sum(25) res[26] = fma52lo(res[26], a[1], a[25]); // Sum(26) res[27] = fma52hi(res[27], a[1], a[25]); // Sum(26) res[27] = fma52lo(res[27], a[2], a[25]); // Sum(27) res[28] = fma52hi(res[28], a[2], a[25]); // Sum(27) res[28] = fma52lo(res[28], a[3], a[25]); // Sum(28) res[29] = fma52hi(res[29], a[3], a[25]); // Sum(28) res[29] = fma52lo(res[29], a[4], a[25]); // Sum(29) res[30] = fma52hi(res[30], a[4], a[25]); // Sum(29) res[30] = fma52lo(res[30], a[5], a[25]); // Sum(30) res[31] = fma52hi(res[31], a[5], a[25]); // Sum(30) res[31] = fma52lo(res[31], a[6], a[25]); // Sum(31) res[32] = fma52hi(res[32], a[6], a[25]); // Sum(31) res[32] = fma52lo(res[32], a[7], a[25]); // Sum(32) res[33] = fma52hi(res[33], a[7], a[25]); // Sum(32) res[33] = fma52lo(res[33], a[8], a[25]); // Sum(33) res[34] = fma52hi(res[34], a[8], a[25]); // Sum(33) res[34] = fma52lo(res[34], a[9], a[25]); // Sum(34) res[35] = fma52hi(res[35], a[9], a[25]); // Sum(34) res[35] = fma52lo(res[35], a[10], a[25]); // Sum(35) res[36] = fma52hi(res[36], a[10], a[25]); // Sum(35) res[26] = fma52lo(res[26], a[0], a[26]); // Sum(26) res[27] = fma52hi(res[27], a[0], a[26]); // Sum(26) res[27] = fma52lo(res[27], a[1], a[26]); // Sum(27) res[28] = fma52hi(res[28], a[1], a[26]); // Sum(27) res[28] = fma52lo(res[28], a[2], a[26]); // Sum(28) res[29] = fma52hi(res[29], a[2], a[26]); // Sum(28) res[29] = fma52lo(res[29], a[3], a[26]); // Sum(29) res[30] = fma52hi(res[30], a[3], a[26]); // Sum(29) res[30] = fma52lo(res[30], a[4], a[26]); // Sum(30) res[31] = fma52hi(res[31], a[4], a[26]); // Sum(30) res[31] = fma52lo(res[31], a[5], a[26]); // Sum(31) res[32] = fma52hi(res[32], a[5], a[26]); // Sum(31) res[32] = fma52lo(res[32], a[6], a[26]); // Sum(32) res[33] = fma52hi(res[33], a[6], a[26]); // Sum(32) res[33] = fma52lo(res[33], a[7], a[26]); // Sum(33) res[34] = fma52hi(res[34], a[7], a[26]); // Sum(33) res[34] = fma52lo(res[34], a[8], a[26]); // Sum(34) res[35] = fma52hi(res[35], a[8], a[26]); // Sum(34) res[35] = fma52lo(res[35], a[9], a[26]); // Sum(35) res[36] = fma52hi(res[36], a[9], a[26]); // Sum(35) res[27] = fma52lo(res[27], a[0], a[27]); // Sum(27) res[28] = fma52hi(res[28], a[0], a[27]); // Sum(27) res[28] = fma52lo(res[28], a[1], a[27]); // Sum(28) res[29] = fma52hi(res[29], a[1], a[27]); // Sum(28) res[29] = fma52lo(res[29], a[2], a[27]); // Sum(29) res[30] = fma52hi(res[30], a[2], a[27]); // Sum(29) res[30] = fma52lo(res[30], a[3], a[27]); // Sum(30) res[31] = fma52hi(res[31], a[3], a[27]); // Sum(30) res[31] = fma52lo(res[31], a[4], a[27]); // Sum(31) res[32] = fma52hi(res[32], a[4], a[27]); // Sum(31) res[32] = fma52lo(res[32], a[5], a[27]); // Sum(32) res[33] = fma52hi(res[33], a[5], a[27]); // Sum(32) res[33] = fma52lo(res[33], a[6], a[27]); // Sum(33) res[34] = fma52hi(res[34], a[6], a[27]); // Sum(33) res[34] = fma52lo(res[34], a[7], a[27]); // Sum(34) res[35] = fma52hi(res[35], a[7], a[27]); // Sum(34) res[35] = fma52lo(res[35], a[8], a[27]); // Sum(35) res[36] = fma52hi(res[36], a[8], a[27]); // Sum(35) res[28] = fma52lo(res[28], a[0], a[28]); // Sum(28) res[29] = fma52hi(res[29], a[0], a[28]); // Sum(28) res[29] = fma52lo(res[29], a[1], a[28]); // Sum(29) res[30] = fma52hi(res[30], a[1], a[28]); // Sum(29) res[30] = fma52lo(res[30], a[2], a[28]); // Sum(30) res[31] = fma52hi(res[31], a[2], a[28]); // Sum(30) res[31] = fma52lo(res[31], a[3], a[28]); // Sum(31) res[32] = fma52hi(res[32], a[3], a[28]); // Sum(31) res[32] = fma52lo(res[32], a[4], a[28]); // Sum(32) res[33] = fma52hi(res[33], a[4], a[28]); // Sum(32) res[33] = fma52lo(res[33], a[5], a[28]); // Sum(33) res[34] = fma52hi(res[34], a[5], a[28]); // Sum(33) res[34] = fma52lo(res[34], a[6], a[28]); // Sum(34) res[35] = fma52hi(res[35], a[6], a[28]); // Sum(34) res[35] = fma52lo(res[35], a[7], a[28]); // Sum(35) res[36] = fma52hi(res[36], a[7], a[28]); // Sum(35) res[29] = fma52lo(res[29], a[0], a[29]); // Sum(29) res[30] = fma52hi(res[30], a[0], a[29]); // Sum(29) res[30] = fma52lo(res[30], a[1], a[29]); // Sum(30) res[31] = fma52hi(res[31], a[1], a[29]); // Sum(30) res[31] = fma52lo(res[31], a[2], a[29]); // Sum(31) res[32] = fma52hi(res[32], a[2], a[29]); // Sum(31) res[32] = fma52lo(res[32], a[3], a[29]); // Sum(32) res[33] = fma52hi(res[33], a[3], a[29]); // Sum(32) res[33] = fma52lo(res[33], a[4], a[29]); // Sum(33) res[34] = fma52hi(res[34], a[4], a[29]); // Sum(33) res[34] = fma52lo(res[34], a[5], a[29]); // Sum(34) res[35] = fma52hi(res[35], a[5], a[29]); // Sum(34) res[35] = fma52lo(res[35], a[6], a[29]); // Sum(35) res[36] = fma52hi(res[36], a[6], a[29]); // Sum(35) res[30] = fma52lo(res[30], a[0], a[30]); // Sum(30) res[31] = fma52hi(res[31], a[0], a[30]); // Sum(30) res[31] = fma52lo(res[31], a[1], a[30]); // Sum(31) res[32] = fma52hi(res[32], a[1], a[30]); // Sum(31) res[32] = fma52lo(res[32], a[2], a[30]); // Sum(32) res[33] = fma52hi(res[33], a[2], a[30]); // Sum(32) res[33] = fma52lo(res[33], a[3], a[30]); // Sum(33) res[34] = fma52hi(res[34], a[3], a[30]); // Sum(33) res[34] = fma52lo(res[34], a[4], a[30]); // Sum(34) res[35] = fma52hi(res[35], a[4], a[30]); // Sum(34) res[35] = fma52lo(res[35], a[5], a[30]); // Sum(35) res[36] = fma52hi(res[36], a[5], a[30]); // Sum(35) res[31] = fma52lo(res[31], a[0], a[31]); // Sum(31) res[32] = fma52hi(res[32], a[0], a[31]); // Sum(31) res[32] = fma52lo(res[32], a[1], a[31]); // Sum(32) res[33] = fma52hi(res[33], a[1], a[31]); // Sum(32) res[33] = fma52lo(res[33], a[2], a[31]); // Sum(33) res[34] = fma52hi(res[34], a[2], a[31]); // Sum(33) res[34] = fma52lo(res[34], a[3], a[31]); // Sum(34) res[35] = fma52hi(res[35], a[3], a[31]); // Sum(34) res[35] = fma52lo(res[35], a[4], a[31]); // Sum(35) res[36] = fma52hi(res[36], a[4], a[31]); // Sum(35) res[32] = fma52lo(res[32], a[0], a[32]); // Sum(32) res[33] = fma52hi(res[33], a[0], a[32]); // Sum(32) res[33] = fma52lo(res[33], a[1], a[32]); // Sum(33) res[34] = fma52hi(res[34], a[1], a[32]); // Sum(33) res[34] = fma52lo(res[34], a[2], a[32]); // Sum(34) res[35] = fma52hi(res[35], a[2], a[32]); // Sum(34) res[35] = fma52lo(res[35], a[3], a[32]); // Sum(35) res[36] = fma52hi(res[36], a[3], a[32]); // Sum(35) res[33] = fma52lo(res[33], a[0], a[33]); // Sum(33) res[34] = fma52hi(res[34], a[0], a[33]); // Sum(33) res[34] = fma52lo(res[34], a[1], a[33]); // Sum(34) res[35] = fma52hi(res[35], a[1], a[33]); // Sum(34) res[35] = fma52lo(res[35], a[2], a[33]); // Sum(35) res[36] = fma52hi(res[36], a[2], a[33]); // Sum(35) res[34] = fma52lo(res[34], a[0], a[34]); // Sum(34) res[35] = fma52hi(res[35], a[0], a[34]); // Sum(34) res[35] = fma52lo(res[35], a[1], a[34]); // Sum(35) res[36] = fma52hi(res[36], a[1], a[34]); // Sum(35) res[35] = fma52lo(res[35], a[0], a[35]); // Sum(35) res[36] = fma52hi(res[36], a[0], a[35]); // Sum(35) res[24] = add64(res[24], res[24]); // Double(24) res[25] = add64(res[25], res[25]); // Double(25) res[26] = add64(res[26], res[26]); // Double(26) res[27] = add64(res[27], res[27]); // Double(27) res[28] = add64(res[28], res[28]); // Double(28) res[29] = add64(res[29], res[29]); // Double(29) res[30] = add64(res[30], res[30]); // Double(30) res[31] = add64(res[31], res[31]); // Double(31) res[32] = add64(res[32], res[32]); // Double(32) res[33] = add64(res[33], res[33]); // Double(33) res[34] = add64(res[34], res[34]); // Double(34) res[35] = add64(res[35], res[35]); // Double(35) res[24] = fma52lo(res[24], a[12], a[12]); // Add sqr(24) res[25] = fma52hi(res[25], a[12], a[12]); // Add sqr(24) res[26] = fma52lo(res[26], a[13], a[13]); // Add sqr(26) res[27] = fma52hi(res[27], a[13], a[13]); // Add sqr(26) res[28] = fma52lo(res[28], a[14], a[14]); // Add sqr(28) res[29] = fma52hi(res[29], a[14], a[14]); // Add sqr(28) res[30] = fma52lo(res[30], a[15], a[15]); // Add sqr(30) res[31] = fma52hi(res[31], a[15], a[15]); // Add sqr(30) res[32] = fma52lo(res[32], a[16], a[16]); // Add sqr(32) res[33] = fma52hi(res[33], a[16], a[16]); // Add sqr(32) res[34] = fma52lo(res[34], a[17], a[17]); // Add sqr(34) res[35] = fma52hi(res[35], a[17], a[17]); // Add sqr(34) res[36] = fma52lo(res[36], a[17], a[19]); // Sum(36) res[37] = fma52hi(res[37], a[17], a[19]); // Sum(36) res[37] = fma52lo(res[37], a[18], a[19]); // Sum(37) res[38] = fma52hi(res[38], a[18], a[19]); // Sum(37) res[36] = fma52lo(res[36], a[16], a[20]); // Sum(36) res[37] = fma52hi(res[37], a[16], a[20]); // Sum(36) res[37] = fma52lo(res[37], a[17], a[20]); // Sum(37) res[38] = fma52hi(res[38], a[17], a[20]); // Sum(37) res[38] = fma52lo(res[38], a[18], a[20]); // Sum(38) res[39] = fma52hi(res[39], a[18], a[20]); // Sum(38) res[39] = fma52lo(res[39], a[19], a[20]); // Sum(39) res[40] = fma52hi(res[40], a[19], a[20]); // Sum(39) res[36] = fma52lo(res[36], a[15], a[21]); // Sum(36) res[37] = fma52hi(res[37], a[15], a[21]); // Sum(36) res[37] = fma52lo(res[37], a[16], a[21]); // Sum(37) res[38] = fma52hi(res[38], a[16], a[21]); // Sum(37) res[38] = fma52lo(res[38], a[17], a[21]); // Sum(38) res[39] = fma52hi(res[39], a[17], a[21]); // Sum(38) res[39] = fma52lo(res[39], a[18], a[21]); // Sum(39) res[40] = fma52hi(res[40], a[18], a[21]); // Sum(39) res[40] = fma52lo(res[40], a[19], a[21]); // Sum(40) res[41] = fma52hi(res[41], a[19], a[21]); // Sum(40) res[41] = fma52lo(res[41], a[20], a[21]); // Sum(41) res[42] = fma52hi(res[42], a[20], a[21]); // Sum(41) res[36] = fma52lo(res[36], a[14], a[22]); // Sum(36) res[37] = fma52hi(res[37], a[14], a[22]); // Sum(36) res[37] = fma52lo(res[37], a[15], a[22]); // Sum(37) res[38] = fma52hi(res[38], a[15], a[22]); // Sum(37) res[38] = fma52lo(res[38], a[16], a[22]); // Sum(38) res[39] = fma52hi(res[39], a[16], a[22]); // Sum(38) res[39] = fma52lo(res[39], a[17], a[22]); // Sum(39) res[40] = fma52hi(res[40], a[17], a[22]); // Sum(39) res[40] = fma52lo(res[40], a[18], a[22]); // Sum(40) res[41] = fma52hi(res[41], a[18], a[22]); // Sum(40) res[41] = fma52lo(res[41], a[19], a[22]); // Sum(41) res[42] = fma52hi(res[42], a[19], a[22]); // Sum(41) res[42] = fma52lo(res[42], a[20], a[22]); // Sum(42) res[43] = fma52hi(res[43], a[20], a[22]); // Sum(42) res[43] = fma52lo(res[43], a[21], a[22]); // Sum(43) res[44] = fma52hi(res[44], a[21], a[22]); // Sum(43) res[36] = fma52lo(res[36], a[13], a[23]); // Sum(36) res[37] = fma52hi(res[37], a[13], a[23]); // Sum(36) res[37] = fma52lo(res[37], a[14], a[23]); // Sum(37) res[38] = fma52hi(res[38], a[14], a[23]); // Sum(37) res[38] = fma52lo(res[38], a[15], a[23]); // Sum(38) res[39] = fma52hi(res[39], a[15], a[23]); // Sum(38) res[39] = fma52lo(res[39], a[16], a[23]); // Sum(39) res[40] = fma52hi(res[40], a[16], a[23]); // Sum(39) res[40] = fma52lo(res[40], a[17], a[23]); // Sum(40) res[41] = fma52hi(res[41], a[17], a[23]); // Sum(40) res[41] = fma52lo(res[41], a[18], a[23]); // Sum(41) res[42] = fma52hi(res[42], a[18], a[23]); // Sum(41) res[42] = fma52lo(res[42], a[19], a[23]); // Sum(42) res[43] = fma52hi(res[43], a[19], a[23]); // Sum(42) res[43] = fma52lo(res[43], a[20], a[23]); // Sum(43) res[44] = fma52hi(res[44], a[20], a[23]); // Sum(43) res[44] = fma52lo(res[44], a[21], a[23]); // Sum(44) res[45] = fma52hi(res[45], a[21], a[23]); // Sum(44) res[45] = fma52lo(res[45], a[22], a[23]); // Sum(45) res[46] = fma52hi(res[46], a[22], a[23]); // Sum(45) res[36] = fma52lo(res[36], a[12], a[24]); // Sum(36) res[37] = fma52hi(res[37], a[12], a[24]); // Sum(36) res[37] = fma52lo(res[37], a[13], a[24]); // Sum(37) res[38] = fma52hi(res[38], a[13], a[24]); // Sum(37) res[38] = fma52lo(res[38], a[14], a[24]); // Sum(38) res[39] = fma52hi(res[39], a[14], a[24]); // Sum(38) res[39] = fma52lo(res[39], a[15], a[24]); // Sum(39) res[40] = fma52hi(res[40], a[15], a[24]); // Sum(39) res[40] = fma52lo(res[40], a[16], a[24]); // Sum(40) res[41] = fma52hi(res[41], a[16], a[24]); // Sum(40) res[41] = fma52lo(res[41], a[17], a[24]); // Sum(41) res[42] = fma52hi(res[42], a[17], a[24]); // Sum(41) res[42] = fma52lo(res[42], a[18], a[24]); // Sum(42) res[43] = fma52hi(res[43], a[18], a[24]); // Sum(42) res[43] = fma52lo(res[43], a[19], a[24]); // Sum(43) res[44] = fma52hi(res[44], a[19], a[24]); // Sum(43) res[44] = fma52lo(res[44], a[20], a[24]); // Sum(44) res[45] = fma52hi(res[45], a[20], a[24]); // Sum(44) res[45] = fma52lo(res[45], a[21], a[24]); // Sum(45) res[46] = fma52hi(res[46], a[21], a[24]); // Sum(45) res[46] = fma52lo(res[46], a[22], a[24]); // Sum(46) res[47] = fma52hi(res[47], a[22], a[24]); // Sum(46) res[47] = fma52lo(res[47], a[23], a[24]); // Sum(47) res[48] = fma52hi(res[48], a[23], a[24]); // Sum(47) res[36] = fma52lo(res[36], a[11], a[25]); // Sum(36) res[37] = fma52hi(res[37], a[11], a[25]); // Sum(36) res[37] = fma52lo(res[37], a[12], a[25]); // Sum(37) res[38] = fma52hi(res[38], a[12], a[25]); // Sum(37) res[38] = fma52lo(res[38], a[13], a[25]); // Sum(38) res[39] = fma52hi(res[39], a[13], a[25]); // Sum(38) res[39] = fma52lo(res[39], a[14], a[25]); // Sum(39) res[40] = fma52hi(res[40], a[14], a[25]); // Sum(39) res[40] = fma52lo(res[40], a[15], a[25]); // Sum(40) res[41] = fma52hi(res[41], a[15], a[25]); // Sum(40) res[41] = fma52lo(res[41], a[16], a[25]); // Sum(41) res[42] = fma52hi(res[42], a[16], a[25]); // Sum(41) res[42] = fma52lo(res[42], a[17], a[25]); // Sum(42) res[43] = fma52hi(res[43], a[17], a[25]); // Sum(42) res[43] = fma52lo(res[43], a[18], a[25]); // Sum(43) res[44] = fma52hi(res[44], a[18], a[25]); // Sum(43) res[44] = fma52lo(res[44], a[19], a[25]); // Sum(44) res[45] = fma52hi(res[45], a[19], a[25]); // Sum(44) res[45] = fma52lo(res[45], a[20], a[25]); // Sum(45) res[46] = fma52hi(res[46], a[20], a[25]); // Sum(45) res[46] = fma52lo(res[46], a[21], a[25]); // Sum(46) res[47] = fma52hi(res[47], a[21], a[25]); // Sum(46) res[47] = fma52lo(res[47], a[22], a[25]); // Sum(47) res[48] = fma52hi(res[48], a[22], a[25]); // Sum(47) res[36] = fma52lo(res[36], a[10], a[26]); // Sum(36) res[37] = fma52hi(res[37], a[10], a[26]); // Sum(36) res[37] = fma52lo(res[37], a[11], a[26]); // Sum(37) res[38] = fma52hi(res[38], a[11], a[26]); // Sum(37) res[38] = fma52lo(res[38], a[12], a[26]); // Sum(38) res[39] = fma52hi(res[39], a[12], a[26]); // Sum(38) res[39] = fma52lo(res[39], a[13], a[26]); // Sum(39) res[40] = fma52hi(res[40], a[13], a[26]); // Sum(39) res[40] = fma52lo(res[40], a[14], a[26]); // Sum(40) res[41] = fma52hi(res[41], a[14], a[26]); // Sum(40) res[41] = fma52lo(res[41], a[15], a[26]); // Sum(41) res[42] = fma52hi(res[42], a[15], a[26]); // Sum(41) res[42] = fma52lo(res[42], a[16], a[26]); // Sum(42) res[43] = fma52hi(res[43], a[16], a[26]); // Sum(42) res[43] = fma52lo(res[43], a[17], a[26]); // Sum(43) res[44] = fma52hi(res[44], a[17], a[26]); // Sum(43) res[44] = fma52lo(res[44], a[18], a[26]); // Sum(44) res[45] = fma52hi(res[45], a[18], a[26]); // Sum(44) res[45] = fma52lo(res[45], a[19], a[26]); // Sum(45) res[46] = fma52hi(res[46], a[19], a[26]); // Sum(45) res[46] = fma52lo(res[46], a[20], a[26]); // Sum(46) res[47] = fma52hi(res[47], a[20], a[26]); // Sum(46) res[47] = fma52lo(res[47], a[21], a[26]); // Sum(47) res[48] = fma52hi(res[48], a[21], a[26]); // Sum(47) res[36] = fma52lo(res[36], a[9], a[27]); // Sum(36) res[37] = fma52hi(res[37], a[9], a[27]); // Sum(36) res[37] = fma52lo(res[37], a[10], a[27]); // Sum(37) res[38] = fma52hi(res[38], a[10], a[27]); // Sum(37) res[38] = fma52lo(res[38], a[11], a[27]); // Sum(38) res[39] = fma52hi(res[39], a[11], a[27]); // Sum(38) res[39] = fma52lo(res[39], a[12], a[27]); // Sum(39) res[40] = fma52hi(res[40], a[12], a[27]); // Sum(39) res[40] = fma52lo(res[40], a[13], a[27]); // Sum(40) res[41] = fma52hi(res[41], a[13], a[27]); // Sum(40) res[41] = fma52lo(res[41], a[14], a[27]); // Sum(41) res[42] = fma52hi(res[42], a[14], a[27]); // Sum(41) res[42] = fma52lo(res[42], a[15], a[27]); // Sum(42) res[43] = fma52hi(res[43], a[15], a[27]); // Sum(42) res[43] = fma52lo(res[43], a[16], a[27]); // Sum(43) res[44] = fma52hi(res[44], a[16], a[27]); // Sum(43) res[44] = fma52lo(res[44], a[17], a[27]); // Sum(44) res[45] = fma52hi(res[45], a[17], a[27]); // Sum(44) res[45] = fma52lo(res[45], a[18], a[27]); // Sum(45) res[46] = fma52hi(res[46], a[18], a[27]); // Sum(45) res[46] = fma52lo(res[46], a[19], a[27]); // Sum(46) res[47] = fma52hi(res[47], a[19], a[27]); // Sum(46) res[47] = fma52lo(res[47], a[20], a[27]); // Sum(47) res[48] = fma52hi(res[48], a[20], a[27]); // Sum(47) res[36] = fma52lo(res[36], a[8], a[28]); // Sum(36) res[37] = fma52hi(res[37], a[8], a[28]); // Sum(36) res[37] = fma52lo(res[37], a[9], a[28]); // Sum(37) res[38] = fma52hi(res[38], a[9], a[28]); // Sum(37) res[38] = fma52lo(res[38], a[10], a[28]); // Sum(38) res[39] = fma52hi(res[39], a[10], a[28]); // Sum(38) res[39] = fma52lo(res[39], a[11], a[28]); // Sum(39) res[40] = fma52hi(res[40], a[11], a[28]); // Sum(39) res[40] = fma52lo(res[40], a[12], a[28]); // Sum(40) res[41] = fma52hi(res[41], a[12], a[28]); // Sum(40) res[41] = fma52lo(res[41], a[13], a[28]); // Sum(41) res[42] = fma52hi(res[42], a[13], a[28]); // Sum(41) res[42] = fma52lo(res[42], a[14], a[28]); // Sum(42) res[43] = fma52hi(res[43], a[14], a[28]); // Sum(42) res[43] = fma52lo(res[43], a[15], a[28]); // Sum(43) res[44] = fma52hi(res[44], a[15], a[28]); // Sum(43) res[44] = fma52lo(res[44], a[16], a[28]); // Sum(44) res[45] = fma52hi(res[45], a[16], a[28]); // Sum(44) res[45] = fma52lo(res[45], a[17], a[28]); // Sum(45) res[46] = fma52hi(res[46], a[17], a[28]); // Sum(45) res[46] = fma52lo(res[46], a[18], a[28]); // Sum(46) res[47] = fma52hi(res[47], a[18], a[28]); // Sum(46) res[47] = fma52lo(res[47], a[19], a[28]); // Sum(47) res[48] = fma52hi(res[48], a[19], a[28]); // Sum(47) res[36] = fma52lo(res[36], a[7], a[29]); // Sum(36) res[37] = fma52hi(res[37], a[7], a[29]); // Sum(36) res[37] = fma52lo(res[37], a[8], a[29]); // Sum(37) res[38] = fma52hi(res[38], a[8], a[29]); // Sum(37) res[38] = fma52lo(res[38], a[9], a[29]); // Sum(38) res[39] = fma52hi(res[39], a[9], a[29]); // Sum(38) res[39] = fma52lo(res[39], a[10], a[29]); // Sum(39) res[40] = fma52hi(res[40], a[10], a[29]); // Sum(39) res[40] = fma52lo(res[40], a[11], a[29]); // Sum(40) res[41] = fma52hi(res[41], a[11], a[29]); // Sum(40) res[41] = fma52lo(res[41], a[12], a[29]); // Sum(41) res[42] = fma52hi(res[42], a[12], a[29]); // Sum(41) res[42] = fma52lo(res[42], a[13], a[29]); // Sum(42) res[43] = fma52hi(res[43], a[13], a[29]); // Sum(42) res[43] = fma52lo(res[43], a[14], a[29]); // Sum(43) res[44] = fma52hi(res[44], a[14], a[29]); // Sum(43) res[44] = fma52lo(res[44], a[15], a[29]); // Sum(44) res[45] = fma52hi(res[45], a[15], a[29]); // Sum(44) res[45] = fma52lo(res[45], a[16], a[29]); // Sum(45) res[46] = fma52hi(res[46], a[16], a[29]); // Sum(45) res[46] = fma52lo(res[46], a[17], a[29]); // Sum(46) res[47] = fma52hi(res[47], a[17], a[29]); // Sum(46) res[47] = fma52lo(res[47], a[18], a[29]); // Sum(47) res[48] = fma52hi(res[48], a[18], a[29]); // Sum(47) res[36] = fma52lo(res[36], a[6], a[30]); // Sum(36) res[37] = fma52hi(res[37], a[6], a[30]); // Sum(36) res[37] = fma52lo(res[37], a[7], a[30]); // Sum(37) res[38] = fma52hi(res[38], a[7], a[30]); // Sum(37) res[38] = fma52lo(res[38], a[8], a[30]); // Sum(38) res[39] = fma52hi(res[39], a[8], a[30]); // Sum(38) res[39] = fma52lo(res[39], a[9], a[30]); // Sum(39) res[40] = fma52hi(res[40], a[9], a[30]); // Sum(39) res[40] = fma52lo(res[40], a[10], a[30]); // Sum(40) res[41] = fma52hi(res[41], a[10], a[30]); // Sum(40) res[41] = fma52lo(res[41], a[11], a[30]); // Sum(41) res[42] = fma52hi(res[42], a[11], a[30]); // Sum(41) res[42] = fma52lo(res[42], a[12], a[30]); // Sum(42) res[43] = fma52hi(res[43], a[12], a[30]); // Sum(42) res[43] = fma52lo(res[43], a[13], a[30]); // Sum(43) res[44] = fma52hi(res[44], a[13], a[30]); // Sum(43) res[44] = fma52lo(res[44], a[14], a[30]); // Sum(44) res[45] = fma52hi(res[45], a[14], a[30]); // Sum(44) res[45] = fma52lo(res[45], a[15], a[30]); // Sum(45) res[46] = fma52hi(res[46], a[15], a[30]); // Sum(45) res[46] = fma52lo(res[46], a[16], a[30]); // Sum(46) res[47] = fma52hi(res[47], a[16], a[30]); // Sum(46) res[47] = fma52lo(res[47], a[17], a[30]); // Sum(47) res[48] = fma52hi(res[48], a[17], a[30]); // Sum(47) res[36] = fma52lo(res[36], a[5], a[31]); // Sum(36) res[37] = fma52hi(res[37], a[5], a[31]); // Sum(36) res[37] = fma52lo(res[37], a[6], a[31]); // Sum(37) res[38] = fma52hi(res[38], a[6], a[31]); // Sum(37) res[38] = fma52lo(res[38], a[7], a[31]); // Sum(38) res[39] = fma52hi(res[39], a[7], a[31]); // Sum(38) res[39] = fma52lo(res[39], a[8], a[31]); // Sum(39) res[40] = fma52hi(res[40], a[8], a[31]); // Sum(39) res[40] = fma52lo(res[40], a[9], a[31]); // Sum(40) res[41] = fma52hi(res[41], a[9], a[31]); // Sum(40) res[41] = fma52lo(res[41], a[10], a[31]); // Sum(41) res[42] = fma52hi(res[42], a[10], a[31]); // Sum(41) res[42] = fma52lo(res[42], a[11], a[31]); // Sum(42) res[43] = fma52hi(res[43], a[11], a[31]); // Sum(42) res[43] = fma52lo(res[43], a[12], a[31]); // Sum(43) res[44] = fma52hi(res[44], a[12], a[31]); // Sum(43) res[44] = fma52lo(res[44], a[13], a[31]); // Sum(44) res[45] = fma52hi(res[45], a[13], a[31]); // Sum(44) res[45] = fma52lo(res[45], a[14], a[31]); // Sum(45) res[46] = fma52hi(res[46], a[14], a[31]); // Sum(45) res[46] = fma52lo(res[46], a[15], a[31]); // Sum(46) res[47] = fma52hi(res[47], a[15], a[31]); // Sum(46) res[47] = fma52lo(res[47], a[16], a[31]); // Sum(47) res[48] = fma52hi(res[48], a[16], a[31]); // Sum(47) res[36] = fma52lo(res[36], a[4], a[32]); // Sum(36) res[37] = fma52hi(res[37], a[4], a[32]); // Sum(36) res[37] = fma52lo(res[37], a[5], a[32]); // Sum(37) res[38] = fma52hi(res[38], a[5], a[32]); // Sum(37) res[38] = fma52lo(res[38], a[6], a[32]); // Sum(38) res[39] = fma52hi(res[39], a[6], a[32]); // Sum(38) res[39] = fma52lo(res[39], a[7], a[32]); // Sum(39) res[40] = fma52hi(res[40], a[7], a[32]); // Sum(39) res[40] = fma52lo(res[40], a[8], a[32]); // Sum(40) res[41] = fma52hi(res[41], a[8], a[32]); // Sum(40) res[41] = fma52lo(res[41], a[9], a[32]); // Sum(41) res[42] = fma52hi(res[42], a[9], a[32]); // Sum(41) res[42] = fma52lo(res[42], a[10], a[32]); // Sum(42) res[43] = fma52hi(res[43], a[10], a[32]); // Sum(42) res[43] = fma52lo(res[43], a[11], a[32]); // Sum(43) res[44] = fma52hi(res[44], a[11], a[32]); // Sum(43) res[44] = fma52lo(res[44], a[12], a[32]); // Sum(44) res[45] = fma52hi(res[45], a[12], a[32]); // Sum(44) res[45] = fma52lo(res[45], a[13], a[32]); // Sum(45) res[46] = fma52hi(res[46], a[13], a[32]); // Sum(45) res[46] = fma52lo(res[46], a[14], a[32]); // Sum(46) res[47] = fma52hi(res[47], a[14], a[32]); // Sum(46) res[47] = fma52lo(res[47], a[15], a[32]); // Sum(47) res[48] = fma52hi(res[48], a[15], a[32]); // Sum(47) res[36] = fma52lo(res[36], a[3], a[33]); // Sum(36) res[37] = fma52hi(res[37], a[3], a[33]); // Sum(36) res[37] = fma52lo(res[37], a[4], a[33]); // Sum(37) res[38] = fma52hi(res[38], a[4], a[33]); // Sum(37) res[38] = fma52lo(res[38], a[5], a[33]); // Sum(38) res[39] = fma52hi(res[39], a[5], a[33]); // Sum(38) res[39] = fma52lo(res[39], a[6], a[33]); // Sum(39) res[40] = fma52hi(res[40], a[6], a[33]); // Sum(39) res[40] = fma52lo(res[40], a[7], a[33]); // Sum(40) res[41] = fma52hi(res[41], a[7], a[33]); // Sum(40) res[41] = fma52lo(res[41], a[8], a[33]); // Sum(41) res[42] = fma52hi(res[42], a[8], a[33]); // Sum(41) res[42] = fma52lo(res[42], a[9], a[33]); // Sum(42) res[43] = fma52hi(res[43], a[9], a[33]); // Sum(42) res[43] = fma52lo(res[43], a[10], a[33]); // Sum(43) res[44] = fma52hi(res[44], a[10], a[33]); // Sum(43) res[44] = fma52lo(res[44], a[11], a[33]); // Sum(44) res[45] = fma52hi(res[45], a[11], a[33]); // Sum(44) res[45] = fma52lo(res[45], a[12], a[33]); // Sum(45) res[46] = fma52hi(res[46], a[12], a[33]); // Sum(45) res[46] = fma52lo(res[46], a[13], a[33]); // Sum(46) res[47] = fma52hi(res[47], a[13], a[33]); // Sum(46) res[47] = fma52lo(res[47], a[14], a[33]); // Sum(47) res[48] = fma52hi(res[48], a[14], a[33]); // Sum(47) res[36] = fma52lo(res[36], a[2], a[34]); // Sum(36) res[37] = fma52hi(res[37], a[2], a[34]); // Sum(36) res[37] = fma52lo(res[37], a[3], a[34]); // Sum(37) res[38] = fma52hi(res[38], a[3], a[34]); // Sum(37) res[38] = fma52lo(res[38], a[4], a[34]); // Sum(38) res[39] = fma52hi(res[39], a[4], a[34]); // Sum(38) res[39] = fma52lo(res[39], a[5], a[34]); // Sum(39) res[40] = fma52hi(res[40], a[5], a[34]); // Sum(39) res[40] = fma52lo(res[40], a[6], a[34]); // Sum(40) res[41] = fma52hi(res[41], a[6], a[34]); // Sum(40) res[41] = fma52lo(res[41], a[7], a[34]); // Sum(41) res[42] = fma52hi(res[42], a[7], a[34]); // Sum(41) res[42] = fma52lo(res[42], a[8], a[34]); // Sum(42) res[43] = fma52hi(res[43], a[8], a[34]); // Sum(42) res[43] = fma52lo(res[43], a[9], a[34]); // Sum(43) res[44] = fma52hi(res[44], a[9], a[34]); // Sum(43) res[44] = fma52lo(res[44], a[10], a[34]); // Sum(44) res[45] = fma52hi(res[45], a[10], a[34]); // Sum(44) res[45] = fma52lo(res[45], a[11], a[34]); // Sum(45) res[46] = fma52hi(res[46], a[11], a[34]); // Sum(45) res[46] = fma52lo(res[46], a[12], a[34]); // Sum(46) res[47] = fma52hi(res[47], a[12], a[34]); // Sum(46) res[47] = fma52lo(res[47], a[13], a[34]); // Sum(47) res[48] = fma52hi(res[48], a[13], a[34]); // Sum(47) res[36] = fma52lo(res[36], a[1], a[35]); // Sum(36) res[37] = fma52hi(res[37], a[1], a[35]); // Sum(36) res[37] = fma52lo(res[37], a[2], a[35]); // Sum(37) res[38] = fma52hi(res[38], a[2], a[35]); // Sum(37) res[38] = fma52lo(res[38], a[3], a[35]); // Sum(38) res[39] = fma52hi(res[39], a[3], a[35]); // Sum(38) res[39] = fma52lo(res[39], a[4], a[35]); // Sum(39) res[40] = fma52hi(res[40], a[4], a[35]); // Sum(39) res[40] = fma52lo(res[40], a[5], a[35]); // Sum(40) res[41] = fma52hi(res[41], a[5], a[35]); // Sum(40) res[41] = fma52lo(res[41], a[6], a[35]); // Sum(41) res[42] = fma52hi(res[42], a[6], a[35]); // Sum(41) res[42] = fma52lo(res[42], a[7], a[35]); // Sum(42) res[43] = fma52hi(res[43], a[7], a[35]); // Sum(42) res[43] = fma52lo(res[43], a[8], a[35]); // Sum(43) res[44] = fma52hi(res[44], a[8], a[35]); // Sum(43) res[44] = fma52lo(res[44], a[9], a[35]); // Sum(44) res[45] = fma52hi(res[45], a[9], a[35]); // Sum(44) res[45] = fma52lo(res[45], a[10], a[35]); // Sum(45) res[46] = fma52hi(res[46], a[10], a[35]); // Sum(45) res[46] = fma52lo(res[46], a[11], a[35]); // Sum(46) res[47] = fma52hi(res[47], a[11], a[35]); // Sum(46) res[47] = fma52lo(res[47], a[12], a[35]); // Sum(47) res[48] = fma52hi(res[48], a[12], a[35]); // Sum(47) res[36] = fma52lo(res[36], a[0], a[36]); // Sum(36) res[37] = fma52hi(res[37], a[0], a[36]); // Sum(36) res[37] = fma52lo(res[37], a[1], a[36]); // Sum(37) res[38] = fma52hi(res[38], a[1], a[36]); // Sum(37) res[38] = fma52lo(res[38], a[2], a[36]); // Sum(38) res[39] = fma52hi(res[39], a[2], a[36]); // Sum(38) res[39] = fma52lo(res[39], a[3], a[36]); // Sum(39) res[40] = fma52hi(res[40], a[3], a[36]); // Sum(39) res[40] = fma52lo(res[40], a[4], a[36]); // Sum(40) res[41] = fma52hi(res[41], a[4], a[36]); // Sum(40) res[41] = fma52lo(res[41], a[5], a[36]); // Sum(41) res[42] = fma52hi(res[42], a[5], a[36]); // Sum(41) res[42] = fma52lo(res[42], a[6], a[36]); // Sum(42) res[43] = fma52hi(res[43], a[6], a[36]); // Sum(42) res[43] = fma52lo(res[43], a[7], a[36]); // Sum(43) res[44] = fma52hi(res[44], a[7], a[36]); // Sum(43) res[44] = fma52lo(res[44], a[8], a[36]); // Sum(44) res[45] = fma52hi(res[45], a[8], a[36]); // Sum(44) res[45] = fma52lo(res[45], a[9], a[36]); // Sum(45) res[46] = fma52hi(res[46], a[9], a[36]); // Sum(45) res[46] = fma52lo(res[46], a[10], a[36]); // Sum(46) res[47] = fma52hi(res[47], a[10], a[36]); // Sum(46) res[47] = fma52lo(res[47], a[11], a[36]); // Sum(47) res[48] = fma52hi(res[48], a[11], a[36]); // Sum(47) res[37] = fma52lo(res[37], a[0], a[37]); // Sum(37) res[38] = fma52hi(res[38], a[0], a[37]); // Sum(37) res[38] = fma52lo(res[38], a[1], a[37]); // Sum(38) res[39] = fma52hi(res[39], a[1], a[37]); // Sum(38) res[39] = fma52lo(res[39], a[2], a[37]); // Sum(39) res[40] = fma52hi(res[40], a[2], a[37]); // Sum(39) res[40] = fma52lo(res[40], a[3], a[37]); // Sum(40) res[41] = fma52hi(res[41], a[3], a[37]); // Sum(40) res[41] = fma52lo(res[41], a[4], a[37]); // Sum(41) res[42] = fma52hi(res[42], a[4], a[37]); // Sum(41) res[42] = fma52lo(res[42], a[5], a[37]); // Sum(42) res[43] = fma52hi(res[43], a[5], a[37]); // Sum(42) res[43] = fma52lo(res[43], a[6], a[37]); // Sum(43) res[44] = fma52hi(res[44], a[6], a[37]); // Sum(43) res[44] = fma52lo(res[44], a[7], a[37]); // Sum(44) res[45] = fma52hi(res[45], a[7], a[37]); // Sum(44) res[45] = fma52lo(res[45], a[8], a[37]); // Sum(45) res[46] = fma52hi(res[46], a[8], a[37]); // Sum(45) res[46] = fma52lo(res[46], a[9], a[37]); // Sum(46) res[47] = fma52hi(res[47], a[9], a[37]); // Sum(46) res[47] = fma52lo(res[47], a[10], a[37]); // Sum(47) res[48] = fma52hi(res[48], a[10], a[37]); // Sum(47) res[38] = fma52lo(res[38], a[0], a[38]); // Sum(38) res[39] = fma52hi(res[39], a[0], a[38]); // Sum(38) res[39] = fma52lo(res[39], a[1], a[38]); // Sum(39) res[40] = fma52hi(res[40], a[1], a[38]); // Sum(39) res[40] = fma52lo(res[40], a[2], a[38]); // Sum(40) res[41] = fma52hi(res[41], a[2], a[38]); // Sum(40) res[41] = fma52lo(res[41], a[3], a[38]); // Sum(41) res[42] = fma52hi(res[42], a[3], a[38]); // Sum(41) res[42] = fma52lo(res[42], a[4], a[38]); // Sum(42) res[43] = fma52hi(res[43], a[4], a[38]); // Sum(42) res[43] = fma52lo(res[43], a[5], a[38]); // Sum(43) res[44] = fma52hi(res[44], a[5], a[38]); // Sum(43) res[44] = fma52lo(res[44], a[6], a[38]); // Sum(44) res[45] = fma52hi(res[45], a[6], a[38]); // Sum(44) res[45] = fma52lo(res[45], a[7], a[38]); // Sum(45) res[46] = fma52hi(res[46], a[7], a[38]); // Sum(45) res[46] = fma52lo(res[46], a[8], a[38]); // Sum(46) res[47] = fma52hi(res[47], a[8], a[38]); // Sum(46) res[47] = fma52lo(res[47], a[9], a[38]); // Sum(47) res[48] = fma52hi(res[48], a[9], a[38]); // Sum(47) res[39] = fma52lo(res[39], a[0], a[39]); // Sum(39) res[40] = fma52hi(res[40], a[0], a[39]); // Sum(39) res[40] = fma52lo(res[40], a[1], a[39]); // Sum(40) res[41] = fma52hi(res[41], a[1], a[39]); // Sum(40) res[41] = fma52lo(res[41], a[2], a[39]); // Sum(41) res[42] = fma52hi(res[42], a[2], a[39]); // Sum(41) res[42] = fma52lo(res[42], a[3], a[39]); // Sum(42) res[43] = fma52hi(res[43], a[3], a[39]); // Sum(42) res[43] = fma52lo(res[43], a[4], a[39]); // Sum(43) res[44] = fma52hi(res[44], a[4], a[39]); // Sum(43) res[44] = fma52lo(res[44], a[5], a[39]); // Sum(44) res[45] = fma52hi(res[45], a[5], a[39]); // Sum(44) res[45] = fma52lo(res[45], a[6], a[39]); // Sum(45) res[46] = fma52hi(res[46], a[6], a[39]); // Sum(45) res[46] = fma52lo(res[46], a[7], a[39]); // Sum(46) res[47] = fma52hi(res[47], a[7], a[39]); // Sum(46) res[47] = fma52lo(res[47], a[8], a[39]); // Sum(47) res[48] = fma52hi(res[48], a[8], a[39]); // Sum(47) res[40] = fma52lo(res[40], a[0], a[40]); // Sum(40) res[41] = fma52hi(res[41], a[0], a[40]); // Sum(40) res[41] = fma52lo(res[41], a[1], a[40]); // Sum(41) res[42] = fma52hi(res[42], a[1], a[40]); // Sum(41) res[42] = fma52lo(res[42], a[2], a[40]); // Sum(42) res[43] = fma52hi(res[43], a[2], a[40]); // Sum(42) res[43] = fma52lo(res[43], a[3], a[40]); // Sum(43) res[44] = fma52hi(res[44], a[3], a[40]); // Sum(43) res[44] = fma52lo(res[44], a[4], a[40]); // Sum(44) res[45] = fma52hi(res[45], a[4], a[40]); // Sum(44) res[45] = fma52lo(res[45], a[5], a[40]); // Sum(45) res[46] = fma52hi(res[46], a[5], a[40]); // Sum(45) res[46] = fma52lo(res[46], a[6], a[40]); // Sum(46) res[47] = fma52hi(res[47], a[6], a[40]); // Sum(46) res[47] = fma52lo(res[47], a[7], a[40]); // Sum(47) res[48] = fma52hi(res[48], a[7], a[40]); // Sum(47) res[41] = fma52lo(res[41], a[0], a[41]); // Sum(41) res[42] = fma52hi(res[42], a[0], a[41]); // Sum(41) res[42] = fma52lo(res[42], a[1], a[41]); // Sum(42) res[43] = fma52hi(res[43], a[1], a[41]); // Sum(42) res[43] = fma52lo(res[43], a[2], a[41]); // Sum(43) res[44] = fma52hi(res[44], a[2], a[41]); // Sum(43) res[44] = fma52lo(res[44], a[3], a[41]); // Sum(44) res[45] = fma52hi(res[45], a[3], a[41]); // Sum(44) res[45] = fma52lo(res[45], a[4], a[41]); // Sum(45) res[46] = fma52hi(res[46], a[4], a[41]); // Sum(45) res[46] = fma52lo(res[46], a[5], a[41]); // Sum(46) res[47] = fma52hi(res[47], a[5], a[41]); // Sum(46) res[47] = fma52lo(res[47], a[6], a[41]); // Sum(47) res[48] = fma52hi(res[48], a[6], a[41]); // Sum(47) res[42] = fma52lo(res[42], a[0], a[42]); // Sum(42) res[43] = fma52hi(res[43], a[0], a[42]); // Sum(42) res[43] = fma52lo(res[43], a[1], a[42]); // Sum(43) res[44] = fma52hi(res[44], a[1], a[42]); // Sum(43) res[44] = fma52lo(res[44], a[2], a[42]); // Sum(44) res[45] = fma52hi(res[45], a[2], a[42]); // Sum(44) res[45] = fma52lo(res[45], a[3], a[42]); // Sum(45) res[46] = fma52hi(res[46], a[3], a[42]); // Sum(45) res[46] = fma52lo(res[46], a[4], a[42]); // Sum(46) res[47] = fma52hi(res[47], a[4], a[42]); // Sum(46) res[47] = fma52lo(res[47], a[5], a[42]); // Sum(47) res[48] = fma52hi(res[48], a[5], a[42]); // Sum(47) res[43] = fma52lo(res[43], a[0], a[43]); // Sum(43) res[44] = fma52hi(res[44], a[0], a[43]); // Sum(43) res[44] = fma52lo(res[44], a[1], a[43]); // Sum(44) res[45] = fma52hi(res[45], a[1], a[43]); // Sum(44) res[45] = fma52lo(res[45], a[2], a[43]); // Sum(45) res[46] = fma52hi(res[46], a[2], a[43]); // Sum(45) res[46] = fma52lo(res[46], a[3], a[43]); // Sum(46) res[47] = fma52hi(res[47], a[3], a[43]); // Sum(46) res[47] = fma52lo(res[47], a[4], a[43]); // Sum(47) res[48] = fma52hi(res[48], a[4], a[43]); // Sum(47) res[44] = fma52lo(res[44], a[0], a[44]); // Sum(44) res[45] = fma52hi(res[45], a[0], a[44]); // Sum(44) res[45] = fma52lo(res[45], a[1], a[44]); // Sum(45) res[46] = fma52hi(res[46], a[1], a[44]); // Sum(45) res[46] = fma52lo(res[46], a[2], a[44]); // Sum(46) res[47] = fma52hi(res[47], a[2], a[44]); // Sum(46) res[47] = fma52lo(res[47], a[3], a[44]); // Sum(47) res[48] = fma52hi(res[48], a[3], a[44]); // Sum(47) res[45] = fma52lo(res[45], a[0], a[45]); // Sum(45) res[46] = fma52hi(res[46], a[0], a[45]); // Sum(45) res[46] = fma52lo(res[46], a[1], a[45]); // Sum(46) res[47] = fma52hi(res[47], a[1], a[45]); // Sum(46) res[47] = fma52lo(res[47], a[2], a[45]); // Sum(47) res[48] = fma52hi(res[48], a[2], a[45]); // Sum(47) res[46] = fma52lo(res[46], a[0], a[46]); // Sum(46) res[47] = fma52hi(res[47], a[0], a[46]); // Sum(46) res[47] = fma52lo(res[47], a[1], a[46]); // Sum(47) res[48] = fma52hi(res[48], a[1], a[46]); // Sum(47) res[47] = fma52lo(res[47], a[0], a[47]); // Sum(47) res[48] = fma52hi(res[48], a[0], a[47]); // Sum(47) res[36] = add64(res[36], res[36]); // Double(36) res[37] = add64(res[37], res[37]); // Double(37) res[38] = add64(res[38], res[38]); // Double(38) res[39] = add64(res[39], res[39]); // Double(39) res[40] = add64(res[40], res[40]); // Double(40) res[41] = add64(res[41], res[41]); // Double(41) res[42] = add64(res[42], res[42]); // Double(42) res[43] = add64(res[43], res[43]); // Double(43) res[44] = add64(res[44], res[44]); // Double(44) res[45] = add64(res[45], res[45]); // Double(45) res[46] = add64(res[46], res[46]); // Double(46) res[47] = add64(res[47], res[47]); // Double(47) res[36] = fma52lo(res[36], a[18], a[18]); // Add sqr(36) res[37] = fma52hi(res[37], a[18], a[18]); // Add sqr(36) res[38] = fma52lo(res[38], a[19], a[19]); // Add sqr(38) res[39] = fma52hi(res[39], a[19], a[19]); // Add sqr(38) res[40] = fma52lo(res[40], a[20], a[20]); // Add sqr(40) res[41] = fma52hi(res[41], a[20], a[20]); // Add sqr(40) res[42] = fma52lo(res[42], a[21], a[21]); // Add sqr(42) res[43] = fma52hi(res[43], a[21], a[21]); // Add sqr(42) res[44] = fma52lo(res[44], a[22], a[22]); // Add sqr(44) res[45] = fma52hi(res[45], a[22], a[22]); // Add sqr(44) res[46] = fma52lo(res[46], a[23], a[23]); // Add sqr(46) res[47] = fma52hi(res[47], a[23], a[23]); // Add sqr(46) res[48] = fma52lo(res[48], a[23], a[25]); // Sum(48) res[49] = fma52hi(res[49], a[23], a[25]); // Sum(48) res[49] = fma52lo(res[49], a[24], a[25]); // Sum(49) res[50] = fma52hi(res[50], a[24], a[25]); // Sum(49) res[48] = fma52lo(res[48], a[22], a[26]); // Sum(48) res[49] = fma52hi(res[49], a[22], a[26]); // Sum(48) res[49] = fma52lo(res[49], a[23], a[26]); // Sum(49) res[50] = fma52hi(res[50], a[23], a[26]); // Sum(49) res[50] = fma52lo(res[50], a[24], a[26]); // Sum(50) res[51] = fma52hi(res[51], a[24], a[26]); // Sum(50) res[51] = fma52lo(res[51], a[25], a[26]); // Sum(51) res[52] = fma52hi(res[52], a[25], a[26]); // Sum(51) res[48] = fma52lo(res[48], a[21], a[27]); // Sum(48) res[49] = fma52hi(res[49], a[21], a[27]); // Sum(48) res[49] = fma52lo(res[49], a[22], a[27]); // Sum(49) res[50] = fma52hi(res[50], a[22], a[27]); // Sum(49) res[50] = fma52lo(res[50], a[23], a[27]); // Sum(50) res[51] = fma52hi(res[51], a[23], a[27]); // Sum(50) res[51] = fma52lo(res[51], a[24], a[27]); // Sum(51) res[52] = fma52hi(res[52], a[24], a[27]); // Sum(51) res[52] = fma52lo(res[52], a[25], a[27]); // Sum(52) res[53] = fma52hi(res[53], a[25], a[27]); // Sum(52) res[53] = fma52lo(res[53], a[26], a[27]); // Sum(53) res[54] = fma52hi(res[54], a[26], a[27]); // Sum(53) res[48] = fma52lo(res[48], a[20], a[28]); // Sum(48) res[49] = fma52hi(res[49], a[20], a[28]); // Sum(48) res[49] = fma52lo(res[49], a[21], a[28]); // Sum(49) res[50] = fma52hi(res[50], a[21], a[28]); // Sum(49) res[50] = fma52lo(res[50], a[22], a[28]); // Sum(50) res[51] = fma52hi(res[51], a[22], a[28]); // Sum(50) res[51] = fma52lo(res[51], a[23], a[28]); // Sum(51) res[52] = fma52hi(res[52], a[23], a[28]); // Sum(51) res[52] = fma52lo(res[52], a[24], a[28]); // Sum(52) res[53] = fma52hi(res[53], a[24], a[28]); // Sum(52) res[53] = fma52lo(res[53], a[25], a[28]); // Sum(53) res[54] = fma52hi(res[54], a[25], a[28]); // Sum(53) res[54] = fma52lo(res[54], a[26], a[28]); // Sum(54) res[55] = fma52hi(res[55], a[26], a[28]); // Sum(54) res[55] = fma52lo(res[55], a[27], a[28]); // Sum(55) res[56] = fma52hi(res[56], a[27], a[28]); // Sum(55) res[48] = fma52lo(res[48], a[19], a[29]); // Sum(48) res[49] = fma52hi(res[49], a[19], a[29]); // Sum(48) res[49] = fma52lo(res[49], a[20], a[29]); // Sum(49) res[50] = fma52hi(res[50], a[20], a[29]); // Sum(49) res[50] = fma52lo(res[50], a[21], a[29]); // Sum(50) res[51] = fma52hi(res[51], a[21], a[29]); // Sum(50) res[51] = fma52lo(res[51], a[22], a[29]); // Sum(51) res[52] = fma52hi(res[52], a[22], a[29]); // Sum(51) res[52] = fma52lo(res[52], a[23], a[29]); // Sum(52) res[53] = fma52hi(res[53], a[23], a[29]); // Sum(52) res[53] = fma52lo(res[53], a[24], a[29]); // Sum(53) res[54] = fma52hi(res[54], a[24], a[29]); // Sum(53) res[54] = fma52lo(res[54], a[25], a[29]); // Sum(54) res[55] = fma52hi(res[55], a[25], a[29]); // Sum(54) res[55] = fma52lo(res[55], a[26], a[29]); // Sum(55) res[56] = fma52hi(res[56], a[26], a[29]); // Sum(55) res[56] = fma52lo(res[56], a[27], a[29]); // Sum(56) res[57] = fma52hi(res[57], a[27], a[29]); // Sum(56) res[57] = fma52lo(res[57], a[28], a[29]); // Sum(57) res[58] = fma52hi(res[58], a[28], a[29]); // Sum(57) res[48] = fma52lo(res[48], a[18], a[30]); // Sum(48) res[49] = fma52hi(res[49], a[18], a[30]); // Sum(48) res[49] = fma52lo(res[49], a[19], a[30]); // Sum(49) res[50] = fma52hi(res[50], a[19], a[30]); // Sum(49) res[50] = fma52lo(res[50], a[20], a[30]); // Sum(50) res[51] = fma52hi(res[51], a[20], a[30]); // Sum(50) res[51] = fma52lo(res[51], a[21], a[30]); // Sum(51) res[52] = fma52hi(res[52], a[21], a[30]); // Sum(51) res[52] = fma52lo(res[52], a[22], a[30]); // Sum(52) res[53] = fma52hi(res[53], a[22], a[30]); // Sum(52) res[53] = fma52lo(res[53], a[23], a[30]); // Sum(53) res[54] = fma52hi(res[54], a[23], a[30]); // Sum(53) res[54] = fma52lo(res[54], a[24], a[30]); // Sum(54) res[55] = fma52hi(res[55], a[24], a[30]); // Sum(54) res[55] = fma52lo(res[55], a[25], a[30]); // Sum(55) res[56] = fma52hi(res[56], a[25], a[30]); // Sum(55) res[56] = fma52lo(res[56], a[26], a[30]); // Sum(56) res[57] = fma52hi(res[57], a[26], a[30]); // Sum(56) res[57] = fma52lo(res[57], a[27], a[30]); // Sum(57) res[58] = fma52hi(res[58], a[27], a[30]); // Sum(57) res[58] = fma52lo(res[58], a[28], a[30]); // Sum(58) res[59] = fma52hi(res[59], a[28], a[30]); // Sum(58) res[59] = fma52lo(res[59], a[29], a[30]); // Sum(59) res[60] = fma52hi(res[60], a[29], a[30]); // Sum(59) res[48] = fma52lo(res[48], a[17], a[31]); // Sum(48) res[49] = fma52hi(res[49], a[17], a[31]); // Sum(48) res[49] = fma52lo(res[49], a[18], a[31]); // Sum(49) res[50] = fma52hi(res[50], a[18], a[31]); // Sum(49) res[50] = fma52lo(res[50], a[19], a[31]); // Sum(50) res[51] = fma52hi(res[51], a[19], a[31]); // Sum(50) res[51] = fma52lo(res[51], a[20], a[31]); // Sum(51) res[52] = fma52hi(res[52], a[20], a[31]); // Sum(51) res[52] = fma52lo(res[52], a[21], a[31]); // Sum(52) res[53] = fma52hi(res[53], a[21], a[31]); // Sum(52) res[53] = fma52lo(res[53], a[22], a[31]); // Sum(53) res[54] = fma52hi(res[54], a[22], a[31]); // Sum(53) res[54] = fma52lo(res[54], a[23], a[31]); // Sum(54) res[55] = fma52hi(res[55], a[23], a[31]); // Sum(54) res[55] = fma52lo(res[55], a[24], a[31]); // Sum(55) res[56] = fma52hi(res[56], a[24], a[31]); // Sum(55) res[56] = fma52lo(res[56], a[25], a[31]); // Sum(56) res[57] = fma52hi(res[57], a[25], a[31]); // Sum(56) res[57] = fma52lo(res[57], a[26], a[31]); // Sum(57) res[58] = fma52hi(res[58], a[26], a[31]); // Sum(57) res[58] = fma52lo(res[58], a[27], a[31]); // Sum(58) res[59] = fma52hi(res[59], a[27], a[31]); // Sum(58) res[59] = fma52lo(res[59], a[28], a[31]); // Sum(59) res[60] = fma52hi(res[60], a[28], a[31]); // Sum(59) res[48] = fma52lo(res[48], a[16], a[32]); // Sum(48) res[49] = fma52hi(res[49], a[16], a[32]); // Sum(48) res[49] = fma52lo(res[49], a[17], a[32]); // Sum(49) res[50] = fma52hi(res[50], a[17], a[32]); // Sum(49) res[50] = fma52lo(res[50], a[18], a[32]); // Sum(50) res[51] = fma52hi(res[51], a[18], a[32]); // Sum(50) res[51] = fma52lo(res[51], a[19], a[32]); // Sum(51) res[52] = fma52hi(res[52], a[19], a[32]); // Sum(51) res[52] = fma52lo(res[52], a[20], a[32]); // Sum(52) res[53] = fma52hi(res[53], a[20], a[32]); // Sum(52) res[53] = fma52lo(res[53], a[21], a[32]); // Sum(53) res[54] = fma52hi(res[54], a[21], a[32]); // Sum(53) res[54] = fma52lo(res[54], a[22], a[32]); // Sum(54) res[55] = fma52hi(res[55], a[22], a[32]); // Sum(54) res[55] = fma52lo(res[55], a[23], a[32]); // Sum(55) res[56] = fma52hi(res[56], a[23], a[32]); // Sum(55) res[56] = fma52lo(res[56], a[24], a[32]); // Sum(56) res[57] = fma52hi(res[57], a[24], a[32]); // Sum(56) res[57] = fma52lo(res[57], a[25], a[32]); // Sum(57) res[58] = fma52hi(res[58], a[25], a[32]); // Sum(57) res[58] = fma52lo(res[58], a[26], a[32]); // Sum(58) res[59] = fma52hi(res[59], a[26], a[32]); // Sum(58) res[59] = fma52lo(res[59], a[27], a[32]); // Sum(59) res[60] = fma52hi(res[60], a[27], a[32]); // Sum(59) res[48] = fma52lo(res[48], a[15], a[33]); // Sum(48) res[49] = fma52hi(res[49], a[15], a[33]); // Sum(48) res[49] = fma52lo(res[49], a[16], a[33]); // Sum(49) res[50] = fma52hi(res[50], a[16], a[33]); // Sum(49) res[50] = fma52lo(res[50], a[17], a[33]); // Sum(50) res[51] = fma52hi(res[51], a[17], a[33]); // Sum(50) res[51] = fma52lo(res[51], a[18], a[33]); // Sum(51) res[52] = fma52hi(res[52], a[18], a[33]); // Sum(51) res[52] = fma52lo(res[52], a[19], a[33]); // Sum(52) res[53] = fma52hi(res[53], a[19], a[33]); // Sum(52) res[53] = fma52lo(res[53], a[20], a[33]); // Sum(53) res[54] = fma52hi(res[54], a[20], a[33]); // Sum(53) res[54] = fma52lo(res[54], a[21], a[33]); // Sum(54) res[55] = fma52hi(res[55], a[21], a[33]); // Sum(54) res[55] = fma52lo(res[55], a[22], a[33]); // Sum(55) res[56] = fma52hi(res[56], a[22], a[33]); // Sum(55) res[56] = fma52lo(res[56], a[23], a[33]); // Sum(56) res[57] = fma52hi(res[57], a[23], a[33]); // Sum(56) res[57] = fma52lo(res[57], a[24], a[33]); // Sum(57) res[58] = fma52hi(res[58], a[24], a[33]); // Sum(57) res[58] = fma52lo(res[58], a[25], a[33]); // Sum(58) res[59] = fma52hi(res[59], a[25], a[33]); // Sum(58) res[59] = fma52lo(res[59], a[26], a[33]); // Sum(59) res[60] = fma52hi(res[60], a[26], a[33]); // Sum(59) res[48] = fma52lo(res[48], a[14], a[34]); // Sum(48) res[49] = fma52hi(res[49], a[14], a[34]); // Sum(48) res[49] = fma52lo(res[49], a[15], a[34]); // Sum(49) res[50] = fma52hi(res[50], a[15], a[34]); // Sum(49) res[50] = fma52lo(res[50], a[16], a[34]); // Sum(50) res[51] = fma52hi(res[51], a[16], a[34]); // Sum(50) res[51] = fma52lo(res[51], a[17], a[34]); // Sum(51) res[52] = fma52hi(res[52], a[17], a[34]); // Sum(51) res[52] = fma52lo(res[52], a[18], a[34]); // Sum(52) res[53] = fma52hi(res[53], a[18], a[34]); // Sum(52) res[53] = fma52lo(res[53], a[19], a[34]); // Sum(53) res[54] = fma52hi(res[54], a[19], a[34]); // Sum(53) res[54] = fma52lo(res[54], a[20], a[34]); // Sum(54) res[55] = fma52hi(res[55], a[20], a[34]); // Sum(54) res[55] = fma52lo(res[55], a[21], a[34]); // Sum(55) res[56] = fma52hi(res[56], a[21], a[34]); // Sum(55) res[56] = fma52lo(res[56], a[22], a[34]); // Sum(56) res[57] = fma52hi(res[57], a[22], a[34]); // Sum(56) res[57] = fma52lo(res[57], a[23], a[34]); // Sum(57) res[58] = fma52hi(res[58], a[23], a[34]); // Sum(57) res[58] = fma52lo(res[58], a[24], a[34]); // Sum(58) res[59] = fma52hi(res[59], a[24], a[34]); // Sum(58) res[59] = fma52lo(res[59], a[25], a[34]); // Sum(59) res[60] = fma52hi(res[60], a[25], a[34]); // Sum(59) res[48] = fma52lo(res[48], a[13], a[35]); // Sum(48) res[49] = fma52hi(res[49], a[13], a[35]); // Sum(48) res[49] = fma52lo(res[49], a[14], a[35]); // Sum(49) res[50] = fma52hi(res[50], a[14], a[35]); // Sum(49) res[50] = fma52lo(res[50], a[15], a[35]); // Sum(50) res[51] = fma52hi(res[51], a[15], a[35]); // Sum(50) res[51] = fma52lo(res[51], a[16], a[35]); // Sum(51) res[52] = fma52hi(res[52], a[16], a[35]); // Sum(51) res[52] = fma52lo(res[52], a[17], a[35]); // Sum(52) res[53] = fma52hi(res[53], a[17], a[35]); // Sum(52) res[53] = fma52lo(res[53], a[18], a[35]); // Sum(53) res[54] = fma52hi(res[54], a[18], a[35]); // Sum(53) res[54] = fma52lo(res[54], a[19], a[35]); // Sum(54) res[55] = fma52hi(res[55], a[19], a[35]); // Sum(54) res[55] = fma52lo(res[55], a[20], a[35]); // Sum(55) res[56] = fma52hi(res[56], a[20], a[35]); // Sum(55) res[56] = fma52lo(res[56], a[21], a[35]); // Sum(56) res[57] = fma52hi(res[57], a[21], a[35]); // Sum(56) res[57] = fma52lo(res[57], a[22], a[35]); // Sum(57) res[58] = fma52hi(res[58], a[22], a[35]); // Sum(57) res[58] = fma52lo(res[58], a[23], a[35]); // Sum(58) res[59] = fma52hi(res[59], a[23], a[35]); // Sum(58) res[59] = fma52lo(res[59], a[24], a[35]); // Sum(59) res[60] = fma52hi(res[60], a[24], a[35]); // Sum(59) res[48] = fma52lo(res[48], a[12], a[36]); // Sum(48) res[49] = fma52hi(res[49], a[12], a[36]); // Sum(48) res[49] = fma52lo(res[49], a[13], a[36]); // Sum(49) res[50] = fma52hi(res[50], a[13], a[36]); // Sum(49) res[50] = fma52lo(res[50], a[14], a[36]); // Sum(50) res[51] = fma52hi(res[51], a[14], a[36]); // Sum(50) res[51] = fma52lo(res[51], a[15], a[36]); // Sum(51) res[52] = fma52hi(res[52], a[15], a[36]); // Sum(51) res[52] = fma52lo(res[52], a[16], a[36]); // Sum(52) res[53] = fma52hi(res[53], a[16], a[36]); // Sum(52) res[53] = fma52lo(res[53], a[17], a[36]); // Sum(53) res[54] = fma52hi(res[54], a[17], a[36]); // Sum(53) res[54] = fma52lo(res[54], a[18], a[36]); // Sum(54) res[55] = fma52hi(res[55], a[18], a[36]); // Sum(54) res[55] = fma52lo(res[55], a[19], a[36]); // Sum(55) res[56] = fma52hi(res[56], a[19], a[36]); // Sum(55) res[56] = fma52lo(res[56], a[20], a[36]); // Sum(56) res[57] = fma52hi(res[57], a[20], a[36]); // Sum(56) res[57] = fma52lo(res[57], a[21], a[36]); // Sum(57) res[58] = fma52hi(res[58], a[21], a[36]); // Sum(57) res[58] = fma52lo(res[58], a[22], a[36]); // Sum(58) res[59] = fma52hi(res[59], a[22], a[36]); // Sum(58) res[59] = fma52lo(res[59], a[23], a[36]); // Sum(59) res[60] = fma52hi(res[60], a[23], a[36]); // Sum(59) res[48] = fma52lo(res[48], a[11], a[37]); // Sum(48) res[49] = fma52hi(res[49], a[11], a[37]); // Sum(48) res[49] = fma52lo(res[49], a[12], a[37]); // Sum(49) res[50] = fma52hi(res[50], a[12], a[37]); // Sum(49) res[50] = fma52lo(res[50], a[13], a[37]); // Sum(50) res[51] = fma52hi(res[51], a[13], a[37]); // Sum(50) res[51] = fma52lo(res[51], a[14], a[37]); // Sum(51) res[52] = fma52hi(res[52], a[14], a[37]); // Sum(51) res[52] = fma52lo(res[52], a[15], a[37]); // Sum(52) res[53] = fma52hi(res[53], a[15], a[37]); // Sum(52) res[53] = fma52lo(res[53], a[16], a[37]); // Sum(53) res[54] = fma52hi(res[54], a[16], a[37]); // Sum(53) res[54] = fma52lo(res[54], a[17], a[37]); // Sum(54) res[55] = fma52hi(res[55], a[17], a[37]); // Sum(54) res[55] = fma52lo(res[55], a[18], a[37]); // Sum(55) res[56] = fma52hi(res[56], a[18], a[37]); // Sum(55) res[56] = fma52lo(res[56], a[19], a[37]); // Sum(56) res[57] = fma52hi(res[57], a[19], a[37]); // Sum(56) res[57] = fma52lo(res[57], a[20], a[37]); // Sum(57) res[58] = fma52hi(res[58], a[20], a[37]); // Sum(57) res[58] = fma52lo(res[58], a[21], a[37]); // Sum(58) res[59] = fma52hi(res[59], a[21], a[37]); // Sum(58) res[59] = fma52lo(res[59], a[22], a[37]); // Sum(59) res[60] = fma52hi(res[60], a[22], a[37]); // Sum(59) res[48] = fma52lo(res[48], a[10], a[38]); // Sum(48) res[49] = fma52hi(res[49], a[10], a[38]); // Sum(48) res[49] = fma52lo(res[49], a[11], a[38]); // Sum(49) res[50] = fma52hi(res[50], a[11], a[38]); // Sum(49) res[50] = fma52lo(res[50], a[12], a[38]); // Sum(50) res[51] = fma52hi(res[51], a[12], a[38]); // Sum(50) res[51] = fma52lo(res[51], a[13], a[38]); // Sum(51) res[52] = fma52hi(res[52], a[13], a[38]); // Sum(51) res[52] = fma52lo(res[52], a[14], a[38]); // Sum(52) res[53] = fma52hi(res[53], a[14], a[38]); // Sum(52) res[53] = fma52lo(res[53], a[15], a[38]); // Sum(53) res[54] = fma52hi(res[54], a[15], a[38]); // Sum(53) res[54] = fma52lo(res[54], a[16], a[38]); // Sum(54) res[55] = fma52hi(res[55], a[16], a[38]); // Sum(54) res[55] = fma52lo(res[55], a[17], a[38]); // Sum(55) res[56] = fma52hi(res[56], a[17], a[38]); // Sum(55) res[56] = fma52lo(res[56], a[18], a[38]); // Sum(56) res[57] = fma52hi(res[57], a[18], a[38]); // Sum(56) res[57] = fma52lo(res[57], a[19], a[38]); // Sum(57) res[58] = fma52hi(res[58], a[19], a[38]); // Sum(57) res[58] = fma52lo(res[58], a[20], a[38]); // Sum(58) res[59] = fma52hi(res[59], a[20], a[38]); // Sum(58) res[59] = fma52lo(res[59], a[21], a[38]); // Sum(59) res[60] = fma52hi(res[60], a[21], a[38]); // Sum(59) res[48] = fma52lo(res[48], a[9], a[39]); // Sum(48) res[49] = fma52hi(res[49], a[9], a[39]); // Sum(48) res[49] = fma52lo(res[49], a[10], a[39]); // Sum(49) res[50] = fma52hi(res[50], a[10], a[39]); // Sum(49) res[50] = fma52lo(res[50], a[11], a[39]); // Sum(50) res[51] = fma52hi(res[51], a[11], a[39]); // Sum(50) res[51] = fma52lo(res[51], a[12], a[39]); // Sum(51) res[52] = fma52hi(res[52], a[12], a[39]); // Sum(51) res[52] = fma52lo(res[52], a[13], a[39]); // Sum(52) res[53] = fma52hi(res[53], a[13], a[39]); // Sum(52) res[53] = fma52lo(res[53], a[14], a[39]); // Sum(53) res[54] = fma52hi(res[54], a[14], a[39]); // Sum(53) res[54] = fma52lo(res[54], a[15], a[39]); // Sum(54) res[55] = fma52hi(res[55], a[15], a[39]); // Sum(54) res[55] = fma52lo(res[55], a[16], a[39]); // Sum(55) res[56] = fma52hi(res[56], a[16], a[39]); // Sum(55) res[56] = fma52lo(res[56], a[17], a[39]); // Sum(56) res[57] = fma52hi(res[57], a[17], a[39]); // Sum(56) res[57] = fma52lo(res[57], a[18], a[39]); // Sum(57) res[58] = fma52hi(res[58], a[18], a[39]); // Sum(57) res[58] = fma52lo(res[58], a[19], a[39]); // Sum(58) res[59] = fma52hi(res[59], a[19], a[39]); // Sum(58) res[59] = fma52lo(res[59], a[20], a[39]); // Sum(59) res[60] = fma52hi(res[60], a[20], a[39]); // Sum(59) res[48] = fma52lo(res[48], a[8], a[40]); // Sum(48) res[49] = fma52hi(res[49], a[8], a[40]); // Sum(48) res[49] = fma52lo(res[49], a[9], a[40]); // Sum(49) res[50] = fma52hi(res[50], a[9], a[40]); // Sum(49) res[50] = fma52lo(res[50], a[10], a[40]); // Sum(50) res[51] = fma52hi(res[51], a[10], a[40]); // Sum(50) res[51] = fma52lo(res[51], a[11], a[40]); // Sum(51) res[52] = fma52hi(res[52], a[11], a[40]); // Sum(51) res[52] = fma52lo(res[52], a[12], a[40]); // Sum(52) res[53] = fma52hi(res[53], a[12], a[40]); // Sum(52) res[53] = fma52lo(res[53], a[13], a[40]); // Sum(53) res[54] = fma52hi(res[54], a[13], a[40]); // Sum(53) res[54] = fma52lo(res[54], a[14], a[40]); // Sum(54) res[55] = fma52hi(res[55], a[14], a[40]); // Sum(54) res[55] = fma52lo(res[55], a[15], a[40]); // Sum(55) res[56] = fma52hi(res[56], a[15], a[40]); // Sum(55) res[56] = fma52lo(res[56], a[16], a[40]); // Sum(56) res[57] = fma52hi(res[57], a[16], a[40]); // Sum(56) res[57] = fma52lo(res[57], a[17], a[40]); // Sum(57) res[58] = fma52hi(res[58], a[17], a[40]); // Sum(57) res[58] = fma52lo(res[58], a[18], a[40]); // Sum(58) res[59] = fma52hi(res[59], a[18], a[40]); // Sum(58) res[59] = fma52lo(res[59], a[19], a[40]); // Sum(59) res[60] = fma52hi(res[60], a[19], a[40]); // Sum(59) res[48] = fma52lo(res[48], a[7], a[41]); // Sum(48) res[49] = fma52hi(res[49], a[7], a[41]); // Sum(48) res[49] = fma52lo(res[49], a[8], a[41]); // Sum(49) res[50] = fma52hi(res[50], a[8], a[41]); // Sum(49) res[50] = fma52lo(res[50], a[9], a[41]); // Sum(50) res[51] = fma52hi(res[51], a[9], a[41]); // Sum(50) res[51] = fma52lo(res[51], a[10], a[41]); // Sum(51) res[52] = fma52hi(res[52], a[10], a[41]); // Sum(51) res[52] = fma52lo(res[52], a[11], a[41]); // Sum(52) res[53] = fma52hi(res[53], a[11], a[41]); // Sum(52) res[53] = fma52lo(res[53], a[12], a[41]); // Sum(53) res[54] = fma52hi(res[54], a[12], a[41]); // Sum(53) res[54] = fma52lo(res[54], a[13], a[41]); // Sum(54) res[55] = fma52hi(res[55], a[13], a[41]); // Sum(54) res[55] = fma52lo(res[55], a[14], a[41]); // Sum(55) res[56] = fma52hi(res[56], a[14], a[41]); // Sum(55) res[56] = fma52lo(res[56], a[15], a[41]); // Sum(56) res[57] = fma52hi(res[57], a[15], a[41]); // Sum(56) res[57] = fma52lo(res[57], a[16], a[41]); // Sum(57) res[58] = fma52hi(res[58], a[16], a[41]); // Sum(57) res[58] = fma52lo(res[58], a[17], a[41]); // Sum(58) res[59] = fma52hi(res[59], a[17], a[41]); // Sum(58) res[59] = fma52lo(res[59], a[18], a[41]); // Sum(59) res[60] = fma52hi(res[60], a[18], a[41]); // Sum(59) res[48] = fma52lo(res[48], a[6], a[42]); // Sum(48) res[49] = fma52hi(res[49], a[6], a[42]); // Sum(48) res[49] = fma52lo(res[49], a[7], a[42]); // Sum(49) res[50] = fma52hi(res[50], a[7], a[42]); // Sum(49) res[50] = fma52lo(res[50], a[8], a[42]); // Sum(50) res[51] = fma52hi(res[51], a[8], a[42]); // Sum(50) res[51] = fma52lo(res[51], a[9], a[42]); // Sum(51) res[52] = fma52hi(res[52], a[9], a[42]); // Sum(51) res[52] = fma52lo(res[52], a[10], a[42]); // Sum(52) res[53] = fma52hi(res[53], a[10], a[42]); // Sum(52) res[53] = fma52lo(res[53], a[11], a[42]); // Sum(53) res[54] = fma52hi(res[54], a[11], a[42]); // Sum(53) res[54] = fma52lo(res[54], a[12], a[42]); // Sum(54) res[55] = fma52hi(res[55], a[12], a[42]); // Sum(54) res[55] = fma52lo(res[55], a[13], a[42]); // Sum(55) res[56] = fma52hi(res[56], a[13], a[42]); // Sum(55) res[56] = fma52lo(res[56], a[14], a[42]); // Sum(56) res[57] = fma52hi(res[57], a[14], a[42]); // Sum(56) res[57] = fma52lo(res[57], a[15], a[42]); // Sum(57) res[58] = fma52hi(res[58], a[15], a[42]); // Sum(57) res[58] = fma52lo(res[58], a[16], a[42]); // Sum(58) res[59] = fma52hi(res[59], a[16], a[42]); // Sum(58) res[59] = fma52lo(res[59], a[17], a[42]); // Sum(59) res[60] = fma52hi(res[60], a[17], a[42]); // Sum(59) res[48] = fma52lo(res[48], a[5], a[43]); // Sum(48) res[49] = fma52hi(res[49], a[5], a[43]); // Sum(48) res[49] = fma52lo(res[49], a[6], a[43]); // Sum(49) res[50] = fma52hi(res[50], a[6], a[43]); // Sum(49) res[50] = fma52lo(res[50], a[7], a[43]); // Sum(50) res[51] = fma52hi(res[51], a[7], a[43]); // Sum(50) res[51] = fma52lo(res[51], a[8], a[43]); // Sum(51) res[52] = fma52hi(res[52], a[8], a[43]); // Sum(51) res[52] = fma52lo(res[52], a[9], a[43]); // Sum(52) res[53] = fma52hi(res[53], a[9], a[43]); // Sum(52) res[53] = fma52lo(res[53], a[10], a[43]); // Sum(53) res[54] = fma52hi(res[54], a[10], a[43]); // Sum(53) res[54] = fma52lo(res[54], a[11], a[43]); // Sum(54) res[55] = fma52hi(res[55], a[11], a[43]); // Sum(54) res[55] = fma52lo(res[55], a[12], a[43]); // Sum(55) res[56] = fma52hi(res[56], a[12], a[43]); // Sum(55) res[56] = fma52lo(res[56], a[13], a[43]); // Sum(56) res[57] = fma52hi(res[57], a[13], a[43]); // Sum(56) res[57] = fma52lo(res[57], a[14], a[43]); // Sum(57) res[58] = fma52hi(res[58], a[14], a[43]); // Sum(57) res[58] = fma52lo(res[58], a[15], a[43]); // Sum(58) res[59] = fma52hi(res[59], a[15], a[43]); // Sum(58) res[59] = fma52lo(res[59], a[16], a[43]); // Sum(59) res[60] = fma52hi(res[60], a[16], a[43]); // Sum(59) res[48] = fma52lo(res[48], a[4], a[44]); // Sum(48) res[49] = fma52hi(res[49], a[4], a[44]); // Sum(48) res[49] = fma52lo(res[49], a[5], a[44]); // Sum(49) res[50] = fma52hi(res[50], a[5], a[44]); // Sum(49) res[50] = fma52lo(res[50], a[6], a[44]); // Sum(50) res[51] = fma52hi(res[51], a[6], a[44]); // Sum(50) res[51] = fma52lo(res[51], a[7], a[44]); // Sum(51) res[52] = fma52hi(res[52], a[7], a[44]); // Sum(51) res[52] = fma52lo(res[52], a[8], a[44]); // Sum(52) res[53] = fma52hi(res[53], a[8], a[44]); // Sum(52) res[53] = fma52lo(res[53], a[9], a[44]); // Sum(53) res[54] = fma52hi(res[54], a[9], a[44]); // Sum(53) res[54] = fma52lo(res[54], a[10], a[44]); // Sum(54) res[55] = fma52hi(res[55], a[10], a[44]); // Sum(54) res[55] = fma52lo(res[55], a[11], a[44]); // Sum(55) res[56] = fma52hi(res[56], a[11], a[44]); // Sum(55) res[56] = fma52lo(res[56], a[12], a[44]); // Sum(56) res[57] = fma52hi(res[57], a[12], a[44]); // Sum(56) res[57] = fma52lo(res[57], a[13], a[44]); // Sum(57) res[58] = fma52hi(res[58], a[13], a[44]); // Sum(57) res[58] = fma52lo(res[58], a[14], a[44]); // Sum(58) res[59] = fma52hi(res[59], a[14], a[44]); // Sum(58) res[59] = fma52lo(res[59], a[15], a[44]); // Sum(59) res[60] = fma52hi(res[60], a[15], a[44]); // Sum(59) res[48] = fma52lo(res[48], a[3], a[45]); // Sum(48) res[49] = fma52hi(res[49], a[3], a[45]); // Sum(48) res[49] = fma52lo(res[49], a[4], a[45]); // Sum(49) res[50] = fma52hi(res[50], a[4], a[45]); // Sum(49) res[50] = fma52lo(res[50], a[5], a[45]); // Sum(50) res[51] = fma52hi(res[51], a[5], a[45]); // Sum(50) res[51] = fma52lo(res[51], a[6], a[45]); // Sum(51) res[52] = fma52hi(res[52], a[6], a[45]); // Sum(51) res[52] = fma52lo(res[52], a[7], a[45]); // Sum(52) res[53] = fma52hi(res[53], a[7], a[45]); // Sum(52) res[53] = fma52lo(res[53], a[8], a[45]); // Sum(53) res[54] = fma52hi(res[54], a[8], a[45]); // Sum(53) res[54] = fma52lo(res[54], a[9], a[45]); // Sum(54) res[55] = fma52hi(res[55], a[9], a[45]); // Sum(54) res[55] = fma52lo(res[55], a[10], a[45]); // Sum(55) res[56] = fma52hi(res[56], a[10], a[45]); // Sum(55) res[56] = fma52lo(res[56], a[11], a[45]); // Sum(56) res[57] = fma52hi(res[57], a[11], a[45]); // Sum(56) res[57] = fma52lo(res[57], a[12], a[45]); // Sum(57) res[58] = fma52hi(res[58], a[12], a[45]); // Sum(57) res[58] = fma52lo(res[58], a[13], a[45]); // Sum(58) res[59] = fma52hi(res[59], a[13], a[45]); // Sum(58) res[59] = fma52lo(res[59], a[14], a[45]); // Sum(59) res[60] = fma52hi(res[60], a[14], a[45]); // Sum(59) res[48] = fma52lo(res[48], a[2], a[46]); // Sum(48) res[49] = fma52hi(res[49], a[2], a[46]); // Sum(48) res[49] = fma52lo(res[49], a[3], a[46]); // Sum(49) res[50] = fma52hi(res[50], a[3], a[46]); // Sum(49) res[50] = fma52lo(res[50], a[4], a[46]); // Sum(50) res[51] = fma52hi(res[51], a[4], a[46]); // Sum(50) res[51] = fma52lo(res[51], a[5], a[46]); // Sum(51) res[52] = fma52hi(res[52], a[5], a[46]); // Sum(51) res[52] = fma52lo(res[52], a[6], a[46]); // Sum(52) res[53] = fma52hi(res[53], a[6], a[46]); // Sum(52) res[53] = fma52lo(res[53], a[7], a[46]); // Sum(53) res[54] = fma52hi(res[54], a[7], a[46]); // Sum(53) res[54] = fma52lo(res[54], a[8], a[46]); // Sum(54) res[55] = fma52hi(res[55], a[8], a[46]); // Sum(54) res[55] = fma52lo(res[55], a[9], a[46]); // Sum(55) res[56] = fma52hi(res[56], a[9], a[46]); // Sum(55) res[56] = fma52lo(res[56], a[10], a[46]); // Sum(56) res[57] = fma52hi(res[57], a[10], a[46]); // Sum(56) res[57] = fma52lo(res[57], a[11], a[46]); // Sum(57) res[58] = fma52hi(res[58], a[11], a[46]); // Sum(57) res[58] = fma52lo(res[58], a[12], a[46]); // Sum(58) res[59] = fma52hi(res[59], a[12], a[46]); // Sum(58) res[59] = fma52lo(res[59], a[13], a[46]); // Sum(59) res[60] = fma52hi(res[60], a[13], a[46]); // Sum(59) res[48] = fma52lo(res[48], a[1], a[47]); // Sum(48) res[49] = fma52hi(res[49], a[1], a[47]); // Sum(48) res[49] = fma52lo(res[49], a[2], a[47]); // Sum(49) res[50] = fma52hi(res[50], a[2], a[47]); // Sum(49) res[50] = fma52lo(res[50], a[3], a[47]); // Sum(50) res[51] = fma52hi(res[51], a[3], a[47]); // Sum(50) res[51] = fma52lo(res[51], a[4], a[47]); // Sum(51) res[52] = fma52hi(res[52], a[4], a[47]); // Sum(51) res[52] = fma52lo(res[52], a[5], a[47]); // Sum(52) res[53] = fma52hi(res[53], a[5], a[47]); // Sum(52) res[53] = fma52lo(res[53], a[6], a[47]); // Sum(53) res[54] = fma52hi(res[54], a[6], a[47]); // Sum(53) res[54] = fma52lo(res[54], a[7], a[47]); // Sum(54) res[55] = fma52hi(res[55], a[7], a[47]); // Sum(54) res[55] = fma52lo(res[55], a[8], a[47]); // Sum(55) res[56] = fma52hi(res[56], a[8], a[47]); // Sum(55) res[56] = fma52lo(res[56], a[9], a[47]); // Sum(56) res[57] = fma52hi(res[57], a[9], a[47]); // Sum(56) res[57] = fma52lo(res[57], a[10], a[47]); // Sum(57) res[58] = fma52hi(res[58], a[10], a[47]); // Sum(57) res[58] = fma52lo(res[58], a[11], a[47]); // Sum(58) res[59] = fma52hi(res[59], a[11], a[47]); // Sum(58) res[59] = fma52lo(res[59], a[12], a[47]); // Sum(59) res[60] = fma52hi(res[60], a[12], a[47]); // Sum(59) res[48] = fma52lo(res[48], a[0], a[48]); // Sum(48) res[49] = fma52hi(res[49], a[0], a[48]); // Sum(48) res[49] = fma52lo(res[49], a[1], a[48]); // Sum(49) res[50] = fma52hi(res[50], a[1], a[48]); // Sum(49) res[50] = fma52lo(res[50], a[2], a[48]); // Sum(50) res[51] = fma52hi(res[51], a[2], a[48]); // Sum(50) res[51] = fma52lo(res[51], a[3], a[48]); // Sum(51) res[52] = fma52hi(res[52], a[3], a[48]); // Sum(51) res[52] = fma52lo(res[52], a[4], a[48]); // Sum(52) res[53] = fma52hi(res[53], a[4], a[48]); // Sum(52) res[53] = fma52lo(res[53], a[5], a[48]); // Sum(53) res[54] = fma52hi(res[54], a[5], a[48]); // Sum(53) res[54] = fma52lo(res[54], a[6], a[48]); // Sum(54) res[55] = fma52hi(res[55], a[6], a[48]); // Sum(54) res[55] = fma52lo(res[55], a[7], a[48]); // Sum(55) res[56] = fma52hi(res[56], a[7], a[48]); // Sum(55) res[56] = fma52lo(res[56], a[8], a[48]); // Sum(56) res[57] = fma52hi(res[57], a[8], a[48]); // Sum(56) res[57] = fma52lo(res[57], a[9], a[48]); // Sum(57) res[58] = fma52hi(res[58], a[9], a[48]); // Sum(57) res[58] = fma52lo(res[58], a[10], a[48]); // Sum(58) res[59] = fma52hi(res[59], a[10], a[48]); // Sum(58) res[59] = fma52lo(res[59], a[11], a[48]); // Sum(59) res[60] = fma52hi(res[60], a[11], a[48]); // Sum(59) res[49] = fma52lo(res[49], a[0], a[49]); // Sum(49) res[50] = fma52hi(res[50], a[0], a[49]); // Sum(49) res[50] = fma52lo(res[50], a[1], a[49]); // Sum(50) res[51] = fma52hi(res[51], a[1], a[49]); // Sum(50) res[51] = fma52lo(res[51], a[2], a[49]); // Sum(51) res[52] = fma52hi(res[52], a[2], a[49]); // Sum(51) res[52] = fma52lo(res[52], a[3], a[49]); // Sum(52) res[53] = fma52hi(res[53], a[3], a[49]); // Sum(52) res[53] = fma52lo(res[53], a[4], a[49]); // Sum(53) res[54] = fma52hi(res[54], a[4], a[49]); // Sum(53) res[54] = fma52lo(res[54], a[5], a[49]); // Sum(54) res[55] = fma52hi(res[55], a[5], a[49]); // Sum(54) res[55] = fma52lo(res[55], a[6], a[49]); // Sum(55) res[56] = fma52hi(res[56], a[6], a[49]); // Sum(55) res[56] = fma52lo(res[56], a[7], a[49]); // Sum(56) res[57] = fma52hi(res[57], a[7], a[49]); // Sum(56) res[57] = fma52lo(res[57], a[8], a[49]); // Sum(57) res[58] = fma52hi(res[58], a[8], a[49]); // Sum(57) res[58] = fma52lo(res[58], a[9], a[49]); // Sum(58) res[59] = fma52hi(res[59], a[9], a[49]); // Sum(58) res[59] = fma52lo(res[59], a[10], a[49]); // Sum(59) res[60] = fma52hi(res[60], a[10], a[49]); // Sum(59) res[50] = fma52lo(res[50], a[0], a[50]); // Sum(50) res[51] = fma52hi(res[51], a[0], a[50]); // Sum(50) res[51] = fma52lo(res[51], a[1], a[50]); // Sum(51) res[52] = fma52hi(res[52], a[1], a[50]); // Sum(51) res[52] = fma52lo(res[52], a[2], a[50]); // Sum(52) res[53] = fma52hi(res[53], a[2], a[50]); // Sum(52) res[53] = fma52lo(res[53], a[3], a[50]); // Sum(53) res[54] = fma52hi(res[54], a[3], a[50]); // Sum(53) res[54] = fma52lo(res[54], a[4], a[50]); // Sum(54) res[55] = fma52hi(res[55], a[4], a[50]); // Sum(54) res[55] = fma52lo(res[55], a[5], a[50]); // Sum(55) res[56] = fma52hi(res[56], a[5], a[50]); // Sum(55) res[56] = fma52lo(res[56], a[6], a[50]); // Sum(56) res[57] = fma52hi(res[57], a[6], a[50]); // Sum(56) res[57] = fma52lo(res[57], a[7], a[50]); // Sum(57) res[58] = fma52hi(res[58], a[7], a[50]); // Sum(57) res[58] = fma52lo(res[58], a[8], a[50]); // Sum(58) res[59] = fma52hi(res[59], a[8], a[50]); // Sum(58) res[59] = fma52lo(res[59], a[9], a[50]); // Sum(59) res[60] = fma52hi(res[60], a[9], a[50]); // Sum(59) res[51] = fma52lo(res[51], a[0], a[51]); // Sum(51) res[52] = fma52hi(res[52], a[0], a[51]); // Sum(51) res[52] = fma52lo(res[52], a[1], a[51]); // Sum(52) res[53] = fma52hi(res[53], a[1], a[51]); // Sum(52) res[53] = fma52lo(res[53], a[2], a[51]); // Sum(53) res[54] = fma52hi(res[54], a[2], a[51]); // Sum(53) res[54] = fma52lo(res[54], a[3], a[51]); // Sum(54) res[55] = fma52hi(res[55], a[3], a[51]); // Sum(54) res[55] = fma52lo(res[55], a[4], a[51]); // Sum(55) res[56] = fma52hi(res[56], a[4], a[51]); // Sum(55) res[56] = fma52lo(res[56], a[5], a[51]); // Sum(56) res[57] = fma52hi(res[57], a[5], a[51]); // Sum(56) res[57] = fma52lo(res[57], a[6], a[51]); // Sum(57) res[58] = fma52hi(res[58], a[6], a[51]); // Sum(57) res[58] = fma52lo(res[58], a[7], a[51]); // Sum(58) res[59] = fma52hi(res[59], a[7], a[51]); // Sum(58) res[59] = fma52lo(res[59], a[8], a[51]); // Sum(59) res[60] = fma52hi(res[60], a[8], a[51]); // Sum(59) res[52] = fma52lo(res[52], a[0], a[52]); // Sum(52) res[53] = fma52hi(res[53], a[0], a[52]); // Sum(52) res[53] = fma52lo(res[53], a[1], a[52]); // Sum(53) res[54] = fma52hi(res[54], a[1], a[52]); // Sum(53) res[54] = fma52lo(res[54], a[2], a[52]); // Sum(54) res[55] = fma52hi(res[55], a[2], a[52]); // Sum(54) res[55] = fma52lo(res[55], a[3], a[52]); // Sum(55) res[56] = fma52hi(res[56], a[3], a[52]); // Sum(55) res[56] = fma52lo(res[56], a[4], a[52]); // Sum(56) res[57] = fma52hi(res[57], a[4], a[52]); // Sum(56) res[57] = fma52lo(res[57], a[5], a[52]); // Sum(57) res[58] = fma52hi(res[58], a[5], a[52]); // Sum(57) res[58] = fma52lo(res[58], a[6], a[52]); // Sum(58) res[59] = fma52hi(res[59], a[6], a[52]); // Sum(58) res[59] = fma52lo(res[59], a[7], a[52]); // Sum(59) res[60] = fma52hi(res[60], a[7], a[52]); // Sum(59) res[53] = fma52lo(res[53], a[0], a[53]); // Sum(53) res[54] = fma52hi(res[54], a[0], a[53]); // Sum(53) res[54] = fma52lo(res[54], a[1], a[53]); // Sum(54) res[55] = fma52hi(res[55], a[1], a[53]); // Sum(54) res[55] = fma52lo(res[55], a[2], a[53]); // Sum(55) res[56] = fma52hi(res[56], a[2], a[53]); // Sum(55) res[56] = fma52lo(res[56], a[3], a[53]); // Sum(56) res[57] = fma52hi(res[57], a[3], a[53]); // Sum(56) res[57] = fma52lo(res[57], a[4], a[53]); // Sum(57) res[58] = fma52hi(res[58], a[4], a[53]); // Sum(57) res[58] = fma52lo(res[58], a[5], a[53]); // Sum(58) res[59] = fma52hi(res[59], a[5], a[53]); // Sum(58) res[59] = fma52lo(res[59], a[6], a[53]); // Sum(59) res[60] = fma52hi(res[60], a[6], a[53]); // Sum(59) res[54] = fma52lo(res[54], a[0], a[54]); // Sum(54) res[55] = fma52hi(res[55], a[0], a[54]); // Sum(54) res[55] = fma52lo(res[55], a[1], a[54]); // Sum(55) res[56] = fma52hi(res[56], a[1], a[54]); // Sum(55) res[56] = fma52lo(res[56], a[2], a[54]); // Sum(56) res[57] = fma52hi(res[57], a[2], a[54]); // Sum(56) res[57] = fma52lo(res[57], a[3], a[54]); // Sum(57) res[58] = fma52hi(res[58], a[3], a[54]); // Sum(57) res[58] = fma52lo(res[58], a[4], a[54]); // Sum(58) res[59] = fma52hi(res[59], a[4], a[54]); // Sum(58) res[59] = fma52lo(res[59], a[5], a[54]); // Sum(59) res[60] = fma52hi(res[60], a[5], a[54]); // Sum(59) res[55] = fma52lo(res[55], a[0], a[55]); // Sum(55) res[56] = fma52hi(res[56], a[0], a[55]); // Sum(55) res[56] = fma52lo(res[56], a[1], a[55]); // Sum(56) res[57] = fma52hi(res[57], a[1], a[55]); // Sum(56) res[57] = fma52lo(res[57], a[2], a[55]); // Sum(57) res[58] = fma52hi(res[58], a[2], a[55]); // Sum(57) res[58] = fma52lo(res[58], a[3], a[55]); // Sum(58) res[59] = fma52hi(res[59], a[3], a[55]); // Sum(58) res[59] = fma52lo(res[59], a[4], a[55]); // Sum(59) res[60] = fma52hi(res[60], a[4], a[55]); // Sum(59) res[56] = fma52lo(res[56], a[0], a[56]); // Sum(56) res[57] = fma52hi(res[57], a[0], a[56]); // Sum(56) res[57] = fma52lo(res[57], a[1], a[56]); // Sum(57) res[58] = fma52hi(res[58], a[1], a[56]); // Sum(57) res[58] = fma52lo(res[58], a[2], a[56]); // Sum(58) res[59] = fma52hi(res[59], a[2], a[56]); // Sum(58) res[59] = fma52lo(res[59], a[3], a[56]); // Sum(59) res[60] = fma52hi(res[60], a[3], a[56]); // Sum(59) res[57] = fma52lo(res[57], a[0], a[57]); // Sum(57) res[58] = fma52hi(res[58], a[0], a[57]); // Sum(57) res[58] = fma52lo(res[58], a[1], a[57]); // Sum(58) res[59] = fma52hi(res[59], a[1], a[57]); // Sum(58) res[59] = fma52lo(res[59], a[2], a[57]); // Sum(59) res[60] = fma52hi(res[60], a[2], a[57]); // Sum(59) res[58] = fma52lo(res[58], a[0], a[58]); // Sum(58) res[59] = fma52hi(res[59], a[0], a[58]); // Sum(58) res[59] = fma52lo(res[59], a[1], a[58]); // Sum(59) res[60] = fma52hi(res[60], a[1], a[58]); // Sum(59) res[59] = fma52lo(res[59], a[0], a[59]); // Sum(59) res[60] = fma52hi(res[60], a[0], a[59]); // Sum(59) res[48] = add64(res[48], res[48]); // Double(48) res[49] = add64(res[49], res[49]); // Double(49) res[50] = add64(res[50], res[50]); // Double(50) res[51] = add64(res[51], res[51]); // Double(51) res[52] = add64(res[52], res[52]); // Double(52) res[53] = add64(res[53], res[53]); // Double(53) res[54] = add64(res[54], res[54]); // Double(54) res[55] = add64(res[55], res[55]); // Double(55) res[56] = add64(res[56], res[56]); // Double(56) res[57] = add64(res[57], res[57]); // Double(57) res[58] = add64(res[58], res[58]); // Double(58) res[59] = add64(res[59], res[59]); // Double(59) res[48] = fma52lo(res[48], a[24], a[24]); // Add sqr(48) res[49] = fma52hi(res[49], a[24], a[24]); // Add sqr(48) res[50] = fma52lo(res[50], a[25], a[25]); // Add sqr(50) res[51] = fma52hi(res[51], a[25], a[25]); // Add sqr(50) res[52] = fma52lo(res[52], a[26], a[26]); // Add sqr(52) res[53] = fma52hi(res[53], a[26], a[26]); // Add sqr(52) res[54] = fma52lo(res[54], a[27], a[27]); // Add sqr(54) res[55] = fma52hi(res[55], a[27], a[27]); // Add sqr(54) res[56] = fma52lo(res[56], a[28], a[28]); // Add sqr(56) res[57] = fma52hi(res[57], a[28], a[28]); // Add sqr(56) res[58] = fma52lo(res[58], a[29], a[29]); // Add sqr(58) res[59] = fma52hi(res[59], a[29], a[29]); // Add sqr(58) res[60] = fma52lo(res[60], a[29], a[31]); // Sum(60) res[61] = fma52hi(res[61], a[29], a[31]); // Sum(60) res[61] = fma52lo(res[61], a[30], a[31]); // Sum(61) res[62] = fma52hi(res[62], a[30], a[31]); // Sum(61) res[60] = fma52lo(res[60], a[28], a[32]); // Sum(60) res[61] = fma52hi(res[61], a[28], a[32]); // Sum(60) res[61] = fma52lo(res[61], a[29], a[32]); // Sum(61) res[62] = fma52hi(res[62], a[29], a[32]); // Sum(61) res[62] = fma52lo(res[62], a[30], a[32]); // Sum(62) res[63] = fma52hi(res[63], a[30], a[32]); // Sum(62) res[63] = fma52lo(res[63], a[31], a[32]); // Sum(63) res[64] = fma52hi(res[64], a[31], a[32]); // Sum(63) res[60] = fma52lo(res[60], a[27], a[33]); // Sum(60) res[61] = fma52hi(res[61], a[27], a[33]); // Sum(60) res[61] = fma52lo(res[61], a[28], a[33]); // Sum(61) res[62] = fma52hi(res[62], a[28], a[33]); // Sum(61) res[62] = fma52lo(res[62], a[29], a[33]); // Sum(62) res[63] = fma52hi(res[63], a[29], a[33]); // Sum(62) res[63] = fma52lo(res[63], a[30], a[33]); // Sum(63) res[64] = fma52hi(res[64], a[30], a[33]); // Sum(63) res[64] = fma52lo(res[64], a[31], a[33]); // Sum(64) res[65] = fma52hi(res[65], a[31], a[33]); // Sum(64) res[65] = fma52lo(res[65], a[32], a[33]); // Sum(65) res[66] = fma52hi(res[66], a[32], a[33]); // Sum(65) res[60] = fma52lo(res[60], a[26], a[34]); // Sum(60) res[61] = fma52hi(res[61], a[26], a[34]); // Sum(60) res[61] = fma52lo(res[61], a[27], a[34]); // Sum(61) res[62] = fma52hi(res[62], a[27], a[34]); // Sum(61) res[62] = fma52lo(res[62], a[28], a[34]); // Sum(62) res[63] = fma52hi(res[63], a[28], a[34]); // Sum(62) res[63] = fma52lo(res[63], a[29], a[34]); // Sum(63) res[64] = fma52hi(res[64], a[29], a[34]); // Sum(63) res[64] = fma52lo(res[64], a[30], a[34]); // Sum(64) res[65] = fma52hi(res[65], a[30], a[34]); // Sum(64) res[65] = fma52lo(res[65], a[31], a[34]); // Sum(65) res[66] = fma52hi(res[66], a[31], a[34]); // Sum(65) res[66] = fma52lo(res[66], a[32], a[34]); // Sum(66) res[67] = fma52hi(res[67], a[32], a[34]); // Sum(66) res[67] = fma52lo(res[67], a[33], a[34]); // Sum(67) res[68] = fma52hi(res[68], a[33], a[34]); // Sum(67) res[60] = fma52lo(res[60], a[25], a[35]); // Sum(60) res[61] = fma52hi(res[61], a[25], a[35]); // Sum(60) res[61] = fma52lo(res[61], a[26], a[35]); // Sum(61) res[62] = fma52hi(res[62], a[26], a[35]); // Sum(61) res[62] = fma52lo(res[62], a[27], a[35]); // Sum(62) res[63] = fma52hi(res[63], a[27], a[35]); // Sum(62) res[63] = fma52lo(res[63], a[28], a[35]); // Sum(63) res[64] = fma52hi(res[64], a[28], a[35]); // Sum(63) res[64] = fma52lo(res[64], a[29], a[35]); // Sum(64) res[65] = fma52hi(res[65], a[29], a[35]); // Sum(64) res[65] = fma52lo(res[65], a[30], a[35]); // Sum(65) res[66] = fma52hi(res[66], a[30], a[35]); // Sum(65) res[66] = fma52lo(res[66], a[31], a[35]); // Sum(66) res[67] = fma52hi(res[67], a[31], a[35]); // Sum(66) res[67] = fma52lo(res[67], a[32], a[35]); // Sum(67) res[68] = fma52hi(res[68], a[32], a[35]); // Sum(67) res[68] = fma52lo(res[68], a[33], a[35]); // Sum(68) res[69] = fma52hi(res[69], a[33], a[35]); // Sum(68) res[69] = fma52lo(res[69], a[34], a[35]); // Sum(69) res[70] = fma52hi(res[70], a[34], a[35]); // Sum(69) res[60] = fma52lo(res[60], a[24], a[36]); // Sum(60) res[61] = fma52hi(res[61], a[24], a[36]); // Sum(60) res[61] = fma52lo(res[61], a[25], a[36]); // Sum(61) res[62] = fma52hi(res[62], a[25], a[36]); // Sum(61) res[62] = fma52lo(res[62], a[26], a[36]); // Sum(62) res[63] = fma52hi(res[63], a[26], a[36]); // Sum(62) res[63] = fma52lo(res[63], a[27], a[36]); // Sum(63) res[64] = fma52hi(res[64], a[27], a[36]); // Sum(63) res[64] = fma52lo(res[64], a[28], a[36]); // Sum(64) res[65] = fma52hi(res[65], a[28], a[36]); // Sum(64) res[65] = fma52lo(res[65], a[29], a[36]); // Sum(65) res[66] = fma52hi(res[66], a[29], a[36]); // Sum(65) res[66] = fma52lo(res[66], a[30], a[36]); // Sum(66) res[67] = fma52hi(res[67], a[30], a[36]); // Sum(66) res[67] = fma52lo(res[67], a[31], a[36]); // Sum(67) res[68] = fma52hi(res[68], a[31], a[36]); // Sum(67) res[68] = fma52lo(res[68], a[32], a[36]); // Sum(68) res[69] = fma52hi(res[69], a[32], a[36]); // Sum(68) res[69] = fma52lo(res[69], a[33], a[36]); // Sum(69) res[70] = fma52hi(res[70], a[33], a[36]); // Sum(69) res[70] = fma52lo(res[70], a[34], a[36]); // Sum(70) res[71] = fma52hi(res[71], a[34], a[36]); // Sum(70) res[71] = fma52lo(res[71], a[35], a[36]); // Sum(71) res[72] = fma52hi(res[72], a[35], a[36]); // Sum(71) res[60] = fma52lo(res[60], a[23], a[37]); // Sum(60) res[61] = fma52hi(res[61], a[23], a[37]); // Sum(60) res[61] = fma52lo(res[61], a[24], a[37]); // Sum(61) res[62] = fma52hi(res[62], a[24], a[37]); // Sum(61) res[62] = fma52lo(res[62], a[25], a[37]); // Sum(62) res[63] = fma52hi(res[63], a[25], a[37]); // Sum(62) res[63] = fma52lo(res[63], a[26], a[37]); // Sum(63) res[64] = fma52hi(res[64], a[26], a[37]); // Sum(63) res[64] = fma52lo(res[64], a[27], a[37]); // Sum(64) res[65] = fma52hi(res[65], a[27], a[37]); // Sum(64) res[65] = fma52lo(res[65], a[28], a[37]); // Sum(65) res[66] = fma52hi(res[66], a[28], a[37]); // Sum(65) res[66] = fma52lo(res[66], a[29], a[37]); // Sum(66) res[67] = fma52hi(res[67], a[29], a[37]); // Sum(66) res[67] = fma52lo(res[67], a[30], a[37]); // Sum(67) res[68] = fma52hi(res[68], a[30], a[37]); // Sum(67) res[68] = fma52lo(res[68], a[31], a[37]); // Sum(68) res[69] = fma52hi(res[69], a[31], a[37]); // Sum(68) res[69] = fma52lo(res[69], a[32], a[37]); // Sum(69) res[70] = fma52hi(res[70], a[32], a[37]); // Sum(69) res[70] = fma52lo(res[70], a[33], a[37]); // Sum(70) res[71] = fma52hi(res[71], a[33], a[37]); // Sum(70) res[71] = fma52lo(res[71], a[34], a[37]); // Sum(71) res[72] = fma52hi(res[72], a[34], a[37]); // Sum(71) res[60] = fma52lo(res[60], a[22], a[38]); // Sum(60) res[61] = fma52hi(res[61], a[22], a[38]); // Sum(60) res[61] = fma52lo(res[61], a[23], a[38]); // Sum(61) res[62] = fma52hi(res[62], a[23], a[38]); // Sum(61) res[62] = fma52lo(res[62], a[24], a[38]); // Sum(62) res[63] = fma52hi(res[63], a[24], a[38]); // Sum(62) res[63] = fma52lo(res[63], a[25], a[38]); // Sum(63) res[64] = fma52hi(res[64], a[25], a[38]); // Sum(63) res[64] = fma52lo(res[64], a[26], a[38]); // Sum(64) res[65] = fma52hi(res[65], a[26], a[38]); // Sum(64) res[65] = fma52lo(res[65], a[27], a[38]); // Sum(65) res[66] = fma52hi(res[66], a[27], a[38]); // Sum(65) res[66] = fma52lo(res[66], a[28], a[38]); // Sum(66) res[67] = fma52hi(res[67], a[28], a[38]); // Sum(66) res[67] = fma52lo(res[67], a[29], a[38]); // Sum(67) res[68] = fma52hi(res[68], a[29], a[38]); // Sum(67) res[68] = fma52lo(res[68], a[30], a[38]); // Sum(68) res[69] = fma52hi(res[69], a[30], a[38]); // Sum(68) res[69] = fma52lo(res[69], a[31], a[38]); // Sum(69) res[70] = fma52hi(res[70], a[31], a[38]); // Sum(69) res[70] = fma52lo(res[70], a[32], a[38]); // Sum(70) res[71] = fma52hi(res[71], a[32], a[38]); // Sum(70) res[71] = fma52lo(res[71], a[33], a[38]); // Sum(71) res[72] = fma52hi(res[72], a[33], a[38]); // Sum(71) res[60] = fma52lo(res[60], a[21], a[39]); // Sum(60) res[61] = fma52hi(res[61], a[21], a[39]); // Sum(60) res[61] = fma52lo(res[61], a[22], a[39]); // Sum(61) res[62] = fma52hi(res[62], a[22], a[39]); // Sum(61) res[62] = fma52lo(res[62], a[23], a[39]); // Sum(62) res[63] = fma52hi(res[63], a[23], a[39]); // Sum(62) res[63] = fma52lo(res[63], a[24], a[39]); // Sum(63) res[64] = fma52hi(res[64], a[24], a[39]); // Sum(63) res[64] = fma52lo(res[64], a[25], a[39]); // Sum(64) res[65] = fma52hi(res[65], a[25], a[39]); // Sum(64) res[65] = fma52lo(res[65], a[26], a[39]); // Sum(65) res[66] = fma52hi(res[66], a[26], a[39]); // Sum(65) res[66] = fma52lo(res[66], a[27], a[39]); // Sum(66) res[67] = fma52hi(res[67], a[27], a[39]); // Sum(66) res[67] = fma52lo(res[67], a[28], a[39]); // Sum(67) res[68] = fma52hi(res[68], a[28], a[39]); // Sum(67) res[68] = fma52lo(res[68], a[29], a[39]); // Sum(68) res[69] = fma52hi(res[69], a[29], a[39]); // Sum(68) res[69] = fma52lo(res[69], a[30], a[39]); // Sum(69) res[70] = fma52hi(res[70], a[30], a[39]); // Sum(69) res[70] = fma52lo(res[70], a[31], a[39]); // Sum(70) res[71] = fma52hi(res[71], a[31], a[39]); // Sum(70) res[71] = fma52lo(res[71], a[32], a[39]); // Sum(71) res[72] = fma52hi(res[72], a[32], a[39]); // Sum(71) res[60] = fma52lo(res[60], a[20], a[40]); // Sum(60) res[61] = fma52hi(res[61], a[20], a[40]); // Sum(60) res[61] = fma52lo(res[61], a[21], a[40]); // Sum(61) res[62] = fma52hi(res[62], a[21], a[40]); // Sum(61) res[62] = fma52lo(res[62], a[22], a[40]); // Sum(62) res[63] = fma52hi(res[63], a[22], a[40]); // Sum(62) res[63] = fma52lo(res[63], a[23], a[40]); // Sum(63) res[64] = fma52hi(res[64], a[23], a[40]); // Sum(63) res[64] = fma52lo(res[64], a[24], a[40]); // Sum(64) res[65] = fma52hi(res[65], a[24], a[40]); // Sum(64) res[65] = fma52lo(res[65], a[25], a[40]); // Sum(65) res[66] = fma52hi(res[66], a[25], a[40]); // Sum(65) res[66] = fma52lo(res[66], a[26], a[40]); // Sum(66) res[67] = fma52hi(res[67], a[26], a[40]); // Sum(66) res[67] = fma52lo(res[67], a[27], a[40]); // Sum(67) res[68] = fma52hi(res[68], a[27], a[40]); // Sum(67) res[68] = fma52lo(res[68], a[28], a[40]); // Sum(68) res[69] = fma52hi(res[69], a[28], a[40]); // Sum(68) res[69] = fma52lo(res[69], a[29], a[40]); // Sum(69) res[70] = fma52hi(res[70], a[29], a[40]); // Sum(69) res[70] = fma52lo(res[70], a[30], a[40]); // Sum(70) res[71] = fma52hi(res[71], a[30], a[40]); // Sum(70) res[71] = fma52lo(res[71], a[31], a[40]); // Sum(71) res[72] = fma52hi(res[72], a[31], a[40]); // Sum(71) res[60] = fma52lo(res[60], a[19], a[41]); // Sum(60) res[61] = fma52hi(res[61], a[19], a[41]); // Sum(60) res[61] = fma52lo(res[61], a[20], a[41]); // Sum(61) res[62] = fma52hi(res[62], a[20], a[41]); // Sum(61) res[62] = fma52lo(res[62], a[21], a[41]); // Sum(62) res[63] = fma52hi(res[63], a[21], a[41]); // Sum(62) res[63] = fma52lo(res[63], a[22], a[41]); // Sum(63) res[64] = fma52hi(res[64], a[22], a[41]); // Sum(63) res[64] = fma52lo(res[64], a[23], a[41]); // Sum(64) res[65] = fma52hi(res[65], a[23], a[41]); // Sum(64) res[65] = fma52lo(res[65], a[24], a[41]); // Sum(65) res[66] = fma52hi(res[66], a[24], a[41]); // Sum(65) res[66] = fma52lo(res[66], a[25], a[41]); // Sum(66) res[67] = fma52hi(res[67], a[25], a[41]); // Sum(66) res[67] = fma52lo(res[67], a[26], a[41]); // Sum(67) res[68] = fma52hi(res[68], a[26], a[41]); // Sum(67) res[68] = fma52lo(res[68], a[27], a[41]); // Sum(68) res[69] = fma52hi(res[69], a[27], a[41]); // Sum(68) res[69] = fma52lo(res[69], a[28], a[41]); // Sum(69) res[70] = fma52hi(res[70], a[28], a[41]); // Sum(69) res[70] = fma52lo(res[70], a[29], a[41]); // Sum(70) res[71] = fma52hi(res[71], a[29], a[41]); // Sum(70) res[71] = fma52lo(res[71], a[30], a[41]); // Sum(71) res[72] = fma52hi(res[72], a[30], a[41]); // Sum(71) res[60] = fma52lo(res[60], a[18], a[42]); // Sum(60) res[61] = fma52hi(res[61], a[18], a[42]); // Sum(60) res[61] = fma52lo(res[61], a[19], a[42]); // Sum(61) res[62] = fma52hi(res[62], a[19], a[42]); // Sum(61) res[62] = fma52lo(res[62], a[20], a[42]); // Sum(62) res[63] = fma52hi(res[63], a[20], a[42]); // Sum(62) res[63] = fma52lo(res[63], a[21], a[42]); // Sum(63) res[64] = fma52hi(res[64], a[21], a[42]); // Sum(63) res[64] = fma52lo(res[64], a[22], a[42]); // Sum(64) res[65] = fma52hi(res[65], a[22], a[42]); // Sum(64) res[65] = fma52lo(res[65], a[23], a[42]); // Sum(65) res[66] = fma52hi(res[66], a[23], a[42]); // Sum(65) res[66] = fma52lo(res[66], a[24], a[42]); // Sum(66) res[67] = fma52hi(res[67], a[24], a[42]); // Sum(66) res[67] = fma52lo(res[67], a[25], a[42]); // Sum(67) res[68] = fma52hi(res[68], a[25], a[42]); // Sum(67) res[68] = fma52lo(res[68], a[26], a[42]); // Sum(68) res[69] = fma52hi(res[69], a[26], a[42]); // Sum(68) res[69] = fma52lo(res[69], a[27], a[42]); // Sum(69) res[70] = fma52hi(res[70], a[27], a[42]); // Sum(69) res[70] = fma52lo(res[70], a[28], a[42]); // Sum(70) res[71] = fma52hi(res[71], a[28], a[42]); // Sum(70) res[71] = fma52lo(res[71], a[29], a[42]); // Sum(71) res[72] = fma52hi(res[72], a[29], a[42]); // Sum(71) res[60] = fma52lo(res[60], a[17], a[43]); // Sum(60) res[61] = fma52hi(res[61], a[17], a[43]); // Sum(60) res[61] = fma52lo(res[61], a[18], a[43]); // Sum(61) res[62] = fma52hi(res[62], a[18], a[43]); // Sum(61) res[62] = fma52lo(res[62], a[19], a[43]); // Sum(62) res[63] = fma52hi(res[63], a[19], a[43]); // Sum(62) res[63] = fma52lo(res[63], a[20], a[43]); // Sum(63) res[64] = fma52hi(res[64], a[20], a[43]); // Sum(63) res[64] = fma52lo(res[64], a[21], a[43]); // Sum(64) res[65] = fma52hi(res[65], a[21], a[43]); // Sum(64) res[65] = fma52lo(res[65], a[22], a[43]); // Sum(65) res[66] = fma52hi(res[66], a[22], a[43]); // Sum(65) res[66] = fma52lo(res[66], a[23], a[43]); // Sum(66) res[67] = fma52hi(res[67], a[23], a[43]); // Sum(66) res[67] = fma52lo(res[67], a[24], a[43]); // Sum(67) res[68] = fma52hi(res[68], a[24], a[43]); // Sum(67) res[68] = fma52lo(res[68], a[25], a[43]); // Sum(68) res[69] = fma52hi(res[69], a[25], a[43]); // Sum(68) res[69] = fma52lo(res[69], a[26], a[43]); // Sum(69) res[70] = fma52hi(res[70], a[26], a[43]); // Sum(69) res[70] = fma52lo(res[70], a[27], a[43]); // Sum(70) res[71] = fma52hi(res[71], a[27], a[43]); // Sum(70) res[71] = fma52lo(res[71], a[28], a[43]); // Sum(71) res[72] = fma52hi(res[72], a[28], a[43]); // Sum(71) res[60] = fma52lo(res[60], a[16], a[44]); // Sum(60) res[61] = fma52hi(res[61], a[16], a[44]); // Sum(60) res[61] = fma52lo(res[61], a[17], a[44]); // Sum(61) res[62] = fma52hi(res[62], a[17], a[44]); // Sum(61) res[62] = fma52lo(res[62], a[18], a[44]); // Sum(62) res[63] = fma52hi(res[63], a[18], a[44]); // Sum(62) res[63] = fma52lo(res[63], a[19], a[44]); // Sum(63) res[64] = fma52hi(res[64], a[19], a[44]); // Sum(63) res[64] = fma52lo(res[64], a[20], a[44]); // Sum(64) res[65] = fma52hi(res[65], a[20], a[44]); // Sum(64) res[65] = fma52lo(res[65], a[21], a[44]); // Sum(65) res[66] = fma52hi(res[66], a[21], a[44]); // Sum(65) res[66] = fma52lo(res[66], a[22], a[44]); // Sum(66) res[67] = fma52hi(res[67], a[22], a[44]); // Sum(66) res[67] = fma52lo(res[67], a[23], a[44]); // Sum(67) res[68] = fma52hi(res[68], a[23], a[44]); // Sum(67) res[68] = fma52lo(res[68], a[24], a[44]); // Sum(68) res[69] = fma52hi(res[69], a[24], a[44]); // Sum(68) res[69] = fma52lo(res[69], a[25], a[44]); // Sum(69) res[70] = fma52hi(res[70], a[25], a[44]); // Sum(69) res[70] = fma52lo(res[70], a[26], a[44]); // Sum(70) res[71] = fma52hi(res[71], a[26], a[44]); // Sum(70) res[71] = fma52lo(res[71], a[27], a[44]); // Sum(71) res[72] = fma52hi(res[72], a[27], a[44]); // Sum(71) res[60] = fma52lo(res[60], a[15], a[45]); // Sum(60) res[61] = fma52hi(res[61], a[15], a[45]); // Sum(60) res[61] = fma52lo(res[61], a[16], a[45]); // Sum(61) res[62] = fma52hi(res[62], a[16], a[45]); // Sum(61) res[62] = fma52lo(res[62], a[17], a[45]); // Sum(62) res[63] = fma52hi(res[63], a[17], a[45]); // Sum(62) res[63] = fma52lo(res[63], a[18], a[45]); // Sum(63) res[64] = fma52hi(res[64], a[18], a[45]); // Sum(63) res[64] = fma52lo(res[64], a[19], a[45]); // Sum(64) res[65] = fma52hi(res[65], a[19], a[45]); // Sum(64) res[65] = fma52lo(res[65], a[20], a[45]); // Sum(65) res[66] = fma52hi(res[66], a[20], a[45]); // Sum(65) res[66] = fma52lo(res[66], a[21], a[45]); // Sum(66) res[67] = fma52hi(res[67], a[21], a[45]); // Sum(66) res[67] = fma52lo(res[67], a[22], a[45]); // Sum(67) res[68] = fma52hi(res[68], a[22], a[45]); // Sum(67) res[68] = fma52lo(res[68], a[23], a[45]); // Sum(68) res[69] = fma52hi(res[69], a[23], a[45]); // Sum(68) res[69] = fma52lo(res[69], a[24], a[45]); // Sum(69) res[70] = fma52hi(res[70], a[24], a[45]); // Sum(69) res[70] = fma52lo(res[70], a[25], a[45]); // Sum(70) res[71] = fma52hi(res[71], a[25], a[45]); // Sum(70) res[71] = fma52lo(res[71], a[26], a[45]); // Sum(71) res[72] = fma52hi(res[72], a[26], a[45]); // Sum(71) res[60] = fma52lo(res[60], a[14], a[46]); // Sum(60) res[61] = fma52hi(res[61], a[14], a[46]); // Sum(60) res[61] = fma52lo(res[61], a[15], a[46]); // Sum(61) res[62] = fma52hi(res[62], a[15], a[46]); // Sum(61) res[62] = fma52lo(res[62], a[16], a[46]); // Sum(62) res[63] = fma52hi(res[63], a[16], a[46]); // Sum(62) res[63] = fma52lo(res[63], a[17], a[46]); // Sum(63) res[64] = fma52hi(res[64], a[17], a[46]); // Sum(63) res[64] = fma52lo(res[64], a[18], a[46]); // Sum(64) res[65] = fma52hi(res[65], a[18], a[46]); // Sum(64) res[65] = fma52lo(res[65], a[19], a[46]); // Sum(65) res[66] = fma52hi(res[66], a[19], a[46]); // Sum(65) res[66] = fma52lo(res[66], a[20], a[46]); // Sum(66) res[67] = fma52hi(res[67], a[20], a[46]); // Sum(66) res[67] = fma52lo(res[67], a[21], a[46]); // Sum(67) res[68] = fma52hi(res[68], a[21], a[46]); // Sum(67) res[68] = fma52lo(res[68], a[22], a[46]); // Sum(68) res[69] = fma52hi(res[69], a[22], a[46]); // Sum(68) res[69] = fma52lo(res[69], a[23], a[46]); // Sum(69) res[70] = fma52hi(res[70], a[23], a[46]); // Sum(69) res[70] = fma52lo(res[70], a[24], a[46]); // Sum(70) res[71] = fma52hi(res[71], a[24], a[46]); // Sum(70) res[71] = fma52lo(res[71], a[25], a[46]); // Sum(71) res[72] = fma52hi(res[72], a[25], a[46]); // Sum(71) res[60] = fma52lo(res[60], a[13], a[47]); // Sum(60) res[61] = fma52hi(res[61], a[13], a[47]); // Sum(60) res[61] = fma52lo(res[61], a[14], a[47]); // Sum(61) res[62] = fma52hi(res[62], a[14], a[47]); // Sum(61) res[62] = fma52lo(res[62], a[15], a[47]); // Sum(62) res[63] = fma52hi(res[63], a[15], a[47]); // Sum(62) res[63] = fma52lo(res[63], a[16], a[47]); // Sum(63) res[64] = fma52hi(res[64], a[16], a[47]); // Sum(63) res[64] = fma52lo(res[64], a[17], a[47]); // Sum(64) res[65] = fma52hi(res[65], a[17], a[47]); // Sum(64) res[65] = fma52lo(res[65], a[18], a[47]); // Sum(65) res[66] = fma52hi(res[66], a[18], a[47]); // Sum(65) res[66] = fma52lo(res[66], a[19], a[47]); // Sum(66) res[67] = fma52hi(res[67], a[19], a[47]); // Sum(66) res[67] = fma52lo(res[67], a[20], a[47]); // Sum(67) res[68] = fma52hi(res[68], a[20], a[47]); // Sum(67) res[68] = fma52lo(res[68], a[21], a[47]); // Sum(68) res[69] = fma52hi(res[69], a[21], a[47]); // Sum(68) res[69] = fma52lo(res[69], a[22], a[47]); // Sum(69) res[70] = fma52hi(res[70], a[22], a[47]); // Sum(69) res[70] = fma52lo(res[70], a[23], a[47]); // Sum(70) res[71] = fma52hi(res[71], a[23], a[47]); // Sum(70) res[71] = fma52lo(res[71], a[24], a[47]); // Sum(71) res[72] = fma52hi(res[72], a[24], a[47]); // Sum(71) res[60] = fma52lo(res[60], a[12], a[48]); // Sum(60) res[61] = fma52hi(res[61], a[12], a[48]); // Sum(60) res[61] = fma52lo(res[61], a[13], a[48]); // Sum(61) res[62] = fma52hi(res[62], a[13], a[48]); // Sum(61) res[62] = fma52lo(res[62], a[14], a[48]); // Sum(62) res[63] = fma52hi(res[63], a[14], a[48]); // Sum(62) res[63] = fma52lo(res[63], a[15], a[48]); // Sum(63) res[64] = fma52hi(res[64], a[15], a[48]); // Sum(63) res[64] = fma52lo(res[64], a[16], a[48]); // Sum(64) res[65] = fma52hi(res[65], a[16], a[48]); // Sum(64) res[65] = fma52lo(res[65], a[17], a[48]); // Sum(65) res[66] = fma52hi(res[66], a[17], a[48]); // Sum(65) res[66] = fma52lo(res[66], a[18], a[48]); // Sum(66) res[67] = fma52hi(res[67], a[18], a[48]); // Sum(66) res[67] = fma52lo(res[67], a[19], a[48]); // Sum(67) res[68] = fma52hi(res[68], a[19], a[48]); // Sum(67) res[68] = fma52lo(res[68], a[20], a[48]); // Sum(68) res[69] = fma52hi(res[69], a[20], a[48]); // Sum(68) res[69] = fma52lo(res[69], a[21], a[48]); // Sum(69) res[70] = fma52hi(res[70], a[21], a[48]); // Sum(69) res[70] = fma52lo(res[70], a[22], a[48]); // Sum(70) res[71] = fma52hi(res[71], a[22], a[48]); // Sum(70) res[71] = fma52lo(res[71], a[23], a[48]); // Sum(71) res[72] = fma52hi(res[72], a[23], a[48]); // Sum(71) res[60] = fma52lo(res[60], a[11], a[49]); // Sum(60) res[61] = fma52hi(res[61], a[11], a[49]); // Sum(60) res[61] = fma52lo(res[61], a[12], a[49]); // Sum(61) res[62] = fma52hi(res[62], a[12], a[49]); // Sum(61) res[62] = fma52lo(res[62], a[13], a[49]); // Sum(62) res[63] = fma52hi(res[63], a[13], a[49]); // Sum(62) res[63] = fma52lo(res[63], a[14], a[49]); // Sum(63) res[64] = fma52hi(res[64], a[14], a[49]); // Sum(63) res[64] = fma52lo(res[64], a[15], a[49]); // Sum(64) res[65] = fma52hi(res[65], a[15], a[49]); // Sum(64) res[65] = fma52lo(res[65], a[16], a[49]); // Sum(65) res[66] = fma52hi(res[66], a[16], a[49]); // Sum(65) res[66] = fma52lo(res[66], a[17], a[49]); // Sum(66) res[67] = fma52hi(res[67], a[17], a[49]); // Sum(66) res[67] = fma52lo(res[67], a[18], a[49]); // Sum(67) res[68] = fma52hi(res[68], a[18], a[49]); // Sum(67) res[68] = fma52lo(res[68], a[19], a[49]); // Sum(68) res[69] = fma52hi(res[69], a[19], a[49]); // Sum(68) res[69] = fma52lo(res[69], a[20], a[49]); // Sum(69) res[70] = fma52hi(res[70], a[20], a[49]); // Sum(69) res[70] = fma52lo(res[70], a[21], a[49]); // Sum(70) res[71] = fma52hi(res[71], a[21], a[49]); // Sum(70) res[71] = fma52lo(res[71], a[22], a[49]); // Sum(71) res[72] = fma52hi(res[72], a[22], a[49]); // Sum(71) res[60] = fma52lo(res[60], a[10], a[50]); // Sum(60) res[61] = fma52hi(res[61], a[10], a[50]); // Sum(60) res[61] = fma52lo(res[61], a[11], a[50]); // Sum(61) res[62] = fma52hi(res[62], a[11], a[50]); // Sum(61) res[62] = fma52lo(res[62], a[12], a[50]); // Sum(62) res[63] = fma52hi(res[63], a[12], a[50]); // Sum(62) res[63] = fma52lo(res[63], a[13], a[50]); // Sum(63) res[64] = fma52hi(res[64], a[13], a[50]); // Sum(63) res[64] = fma52lo(res[64], a[14], a[50]); // Sum(64) res[65] = fma52hi(res[65], a[14], a[50]); // Sum(64) res[65] = fma52lo(res[65], a[15], a[50]); // Sum(65) res[66] = fma52hi(res[66], a[15], a[50]); // Sum(65) res[66] = fma52lo(res[66], a[16], a[50]); // Sum(66) res[67] = fma52hi(res[67], a[16], a[50]); // Sum(66) res[67] = fma52lo(res[67], a[17], a[50]); // Sum(67) res[68] = fma52hi(res[68], a[17], a[50]); // Sum(67) res[68] = fma52lo(res[68], a[18], a[50]); // Sum(68) res[69] = fma52hi(res[69], a[18], a[50]); // Sum(68) res[69] = fma52lo(res[69], a[19], a[50]); // Sum(69) res[70] = fma52hi(res[70], a[19], a[50]); // Sum(69) res[70] = fma52lo(res[70], a[20], a[50]); // Sum(70) res[71] = fma52hi(res[71], a[20], a[50]); // Sum(70) res[71] = fma52lo(res[71], a[21], a[50]); // Sum(71) res[72] = fma52hi(res[72], a[21], a[50]); // Sum(71) res[60] = fma52lo(res[60], a[9], a[51]); // Sum(60) res[61] = fma52hi(res[61], a[9], a[51]); // Sum(60) res[61] = fma52lo(res[61], a[10], a[51]); // Sum(61) res[62] = fma52hi(res[62], a[10], a[51]); // Sum(61) res[62] = fma52lo(res[62], a[11], a[51]); // Sum(62) res[63] = fma52hi(res[63], a[11], a[51]); // Sum(62) res[63] = fma52lo(res[63], a[12], a[51]); // Sum(63) res[64] = fma52hi(res[64], a[12], a[51]); // Sum(63) res[64] = fma52lo(res[64], a[13], a[51]); // Sum(64) res[65] = fma52hi(res[65], a[13], a[51]); // Sum(64) res[65] = fma52lo(res[65], a[14], a[51]); // Sum(65) res[66] = fma52hi(res[66], a[14], a[51]); // Sum(65) res[66] = fma52lo(res[66], a[15], a[51]); // Sum(66) res[67] = fma52hi(res[67], a[15], a[51]); // Sum(66) res[67] = fma52lo(res[67], a[16], a[51]); // Sum(67) res[68] = fma52hi(res[68], a[16], a[51]); // Sum(67) res[68] = fma52lo(res[68], a[17], a[51]); // Sum(68) res[69] = fma52hi(res[69], a[17], a[51]); // Sum(68) res[69] = fma52lo(res[69], a[18], a[51]); // Sum(69) res[70] = fma52hi(res[70], a[18], a[51]); // Sum(69) res[70] = fma52lo(res[70], a[19], a[51]); // Sum(70) res[71] = fma52hi(res[71], a[19], a[51]); // Sum(70) res[71] = fma52lo(res[71], a[20], a[51]); // Sum(71) res[72] = fma52hi(res[72], a[20], a[51]); // Sum(71) res[60] = fma52lo(res[60], a[8], a[52]); // Sum(60) res[61] = fma52hi(res[61], a[8], a[52]); // Sum(60) res[61] = fma52lo(res[61], a[9], a[52]); // Sum(61) res[62] = fma52hi(res[62], a[9], a[52]); // Sum(61) res[62] = fma52lo(res[62], a[10], a[52]); // Sum(62) res[63] = fma52hi(res[63], a[10], a[52]); // Sum(62) res[63] = fma52lo(res[63], a[11], a[52]); // Sum(63) res[64] = fma52hi(res[64], a[11], a[52]); // Sum(63) res[64] = fma52lo(res[64], a[12], a[52]); // Sum(64) res[65] = fma52hi(res[65], a[12], a[52]); // Sum(64) res[65] = fma52lo(res[65], a[13], a[52]); // Sum(65) res[66] = fma52hi(res[66], a[13], a[52]); // Sum(65) res[66] = fma52lo(res[66], a[14], a[52]); // Sum(66) res[67] = fma52hi(res[67], a[14], a[52]); // Sum(66) res[67] = fma52lo(res[67], a[15], a[52]); // Sum(67) res[68] = fma52hi(res[68], a[15], a[52]); // Sum(67) res[68] = fma52lo(res[68], a[16], a[52]); // Sum(68) res[69] = fma52hi(res[69], a[16], a[52]); // Sum(68) res[69] = fma52lo(res[69], a[17], a[52]); // Sum(69) res[70] = fma52hi(res[70], a[17], a[52]); // Sum(69) res[70] = fma52lo(res[70], a[18], a[52]); // Sum(70) res[71] = fma52hi(res[71], a[18], a[52]); // Sum(70) res[71] = fma52lo(res[71], a[19], a[52]); // Sum(71) res[72] = fma52hi(res[72], a[19], a[52]); // Sum(71) res[60] = fma52lo(res[60], a[7], a[53]); // Sum(60) res[61] = fma52hi(res[61], a[7], a[53]); // Sum(60) res[61] = fma52lo(res[61], a[8], a[53]); // Sum(61) res[62] = fma52hi(res[62], a[8], a[53]); // Sum(61) res[62] = fma52lo(res[62], a[9], a[53]); // Sum(62) res[63] = fma52hi(res[63], a[9], a[53]); // Sum(62) res[63] = fma52lo(res[63], a[10], a[53]); // Sum(63) res[64] = fma52hi(res[64], a[10], a[53]); // Sum(63) res[64] = fma52lo(res[64], a[11], a[53]); // Sum(64) res[65] = fma52hi(res[65], a[11], a[53]); // Sum(64) res[65] = fma52lo(res[65], a[12], a[53]); // Sum(65) res[66] = fma52hi(res[66], a[12], a[53]); // Sum(65) res[66] = fma52lo(res[66], a[13], a[53]); // Sum(66) res[67] = fma52hi(res[67], a[13], a[53]); // Sum(66) res[67] = fma52lo(res[67], a[14], a[53]); // Sum(67) res[68] = fma52hi(res[68], a[14], a[53]); // Sum(67) res[68] = fma52lo(res[68], a[15], a[53]); // Sum(68) res[69] = fma52hi(res[69], a[15], a[53]); // Sum(68) res[69] = fma52lo(res[69], a[16], a[53]); // Sum(69) res[70] = fma52hi(res[70], a[16], a[53]); // Sum(69) res[70] = fma52lo(res[70], a[17], a[53]); // Sum(70) res[71] = fma52hi(res[71], a[17], a[53]); // Sum(70) res[71] = fma52lo(res[71], a[18], a[53]); // Sum(71) res[72] = fma52hi(res[72], a[18], a[53]); // Sum(71) res[60] = fma52lo(res[60], a[6], a[54]); // Sum(60) res[61] = fma52hi(res[61], a[6], a[54]); // Sum(60) res[61] = fma52lo(res[61], a[7], a[54]); // Sum(61) res[62] = fma52hi(res[62], a[7], a[54]); // Sum(61) res[62] = fma52lo(res[62], a[8], a[54]); // Sum(62) res[63] = fma52hi(res[63], a[8], a[54]); // Sum(62) res[63] = fma52lo(res[63], a[9], a[54]); // Sum(63) res[64] = fma52hi(res[64], a[9], a[54]); // Sum(63) res[64] = fma52lo(res[64], a[10], a[54]); // Sum(64) res[65] = fma52hi(res[65], a[10], a[54]); // Sum(64) res[65] = fma52lo(res[65], a[11], a[54]); // Sum(65) res[66] = fma52hi(res[66], a[11], a[54]); // Sum(65) res[66] = fma52lo(res[66], a[12], a[54]); // Sum(66) res[67] = fma52hi(res[67], a[12], a[54]); // Sum(66) res[67] = fma52lo(res[67], a[13], a[54]); // Sum(67) res[68] = fma52hi(res[68], a[13], a[54]); // Sum(67) res[68] = fma52lo(res[68], a[14], a[54]); // Sum(68) res[69] = fma52hi(res[69], a[14], a[54]); // Sum(68) res[69] = fma52lo(res[69], a[15], a[54]); // Sum(69) res[70] = fma52hi(res[70], a[15], a[54]); // Sum(69) res[70] = fma52lo(res[70], a[16], a[54]); // Sum(70) res[71] = fma52hi(res[71], a[16], a[54]); // Sum(70) res[71] = fma52lo(res[71], a[17], a[54]); // Sum(71) res[72] = fma52hi(res[72], a[17], a[54]); // Sum(71) res[60] = fma52lo(res[60], a[5], a[55]); // Sum(60) res[61] = fma52hi(res[61], a[5], a[55]); // Sum(60) res[61] = fma52lo(res[61], a[6], a[55]); // Sum(61) res[62] = fma52hi(res[62], a[6], a[55]); // Sum(61) res[62] = fma52lo(res[62], a[7], a[55]); // Sum(62) res[63] = fma52hi(res[63], a[7], a[55]); // Sum(62) res[63] = fma52lo(res[63], a[8], a[55]); // Sum(63) res[64] = fma52hi(res[64], a[8], a[55]); // Sum(63) res[64] = fma52lo(res[64], a[9], a[55]); // Sum(64) res[65] = fma52hi(res[65], a[9], a[55]); // Sum(64) res[65] = fma52lo(res[65], a[10], a[55]); // Sum(65) res[66] = fma52hi(res[66], a[10], a[55]); // Sum(65) res[66] = fma52lo(res[66], a[11], a[55]); // Sum(66) res[67] = fma52hi(res[67], a[11], a[55]); // Sum(66) res[67] = fma52lo(res[67], a[12], a[55]); // Sum(67) res[68] = fma52hi(res[68], a[12], a[55]); // Sum(67) res[68] = fma52lo(res[68], a[13], a[55]); // Sum(68) res[69] = fma52hi(res[69], a[13], a[55]); // Sum(68) res[69] = fma52lo(res[69], a[14], a[55]); // Sum(69) res[70] = fma52hi(res[70], a[14], a[55]); // Sum(69) res[70] = fma52lo(res[70], a[15], a[55]); // Sum(70) res[71] = fma52hi(res[71], a[15], a[55]); // Sum(70) res[71] = fma52lo(res[71], a[16], a[55]); // Sum(71) res[72] = fma52hi(res[72], a[16], a[55]); // Sum(71) res[60] = fma52lo(res[60], a[4], a[56]); // Sum(60) res[61] = fma52hi(res[61], a[4], a[56]); // Sum(60) res[61] = fma52lo(res[61], a[5], a[56]); // Sum(61) res[62] = fma52hi(res[62], a[5], a[56]); // Sum(61) res[62] = fma52lo(res[62], a[6], a[56]); // Sum(62) res[63] = fma52hi(res[63], a[6], a[56]); // Sum(62) res[63] = fma52lo(res[63], a[7], a[56]); // Sum(63) res[64] = fma52hi(res[64], a[7], a[56]); // Sum(63) res[64] = fma52lo(res[64], a[8], a[56]); // Sum(64) res[65] = fma52hi(res[65], a[8], a[56]); // Sum(64) res[65] = fma52lo(res[65], a[9], a[56]); // Sum(65) res[66] = fma52hi(res[66], a[9], a[56]); // Sum(65) res[66] = fma52lo(res[66], a[10], a[56]); // Sum(66) res[67] = fma52hi(res[67], a[10], a[56]); // Sum(66) res[67] = fma52lo(res[67], a[11], a[56]); // Sum(67) res[68] = fma52hi(res[68], a[11], a[56]); // Sum(67) res[68] = fma52lo(res[68], a[12], a[56]); // Sum(68) res[69] = fma52hi(res[69], a[12], a[56]); // Sum(68) res[69] = fma52lo(res[69], a[13], a[56]); // Sum(69) res[70] = fma52hi(res[70], a[13], a[56]); // Sum(69) res[70] = fma52lo(res[70], a[14], a[56]); // Sum(70) res[71] = fma52hi(res[71], a[14], a[56]); // Sum(70) res[71] = fma52lo(res[71], a[15], a[56]); // Sum(71) res[72] = fma52hi(res[72], a[15], a[56]); // Sum(71) res[60] = fma52lo(res[60], a[3], a[57]); // Sum(60) res[61] = fma52hi(res[61], a[3], a[57]); // Sum(60) res[61] = fma52lo(res[61], a[4], a[57]); // Sum(61) res[62] = fma52hi(res[62], a[4], a[57]); // Sum(61) res[62] = fma52lo(res[62], a[5], a[57]); // Sum(62) res[63] = fma52hi(res[63], a[5], a[57]); // Sum(62) res[63] = fma52lo(res[63], a[6], a[57]); // Sum(63) res[64] = fma52hi(res[64], a[6], a[57]); // Sum(63) res[64] = fma52lo(res[64], a[7], a[57]); // Sum(64) res[65] = fma52hi(res[65], a[7], a[57]); // Sum(64) res[65] = fma52lo(res[65], a[8], a[57]); // Sum(65) res[66] = fma52hi(res[66], a[8], a[57]); // Sum(65) res[66] = fma52lo(res[66], a[9], a[57]); // Sum(66) res[67] = fma52hi(res[67], a[9], a[57]); // Sum(66) res[67] = fma52lo(res[67], a[10], a[57]); // Sum(67) res[68] = fma52hi(res[68], a[10], a[57]); // Sum(67) res[68] = fma52lo(res[68], a[11], a[57]); // Sum(68) res[69] = fma52hi(res[69], a[11], a[57]); // Sum(68) res[69] = fma52lo(res[69], a[12], a[57]); // Sum(69) res[70] = fma52hi(res[70], a[12], a[57]); // Sum(69) res[70] = fma52lo(res[70], a[13], a[57]); // Sum(70) res[71] = fma52hi(res[71], a[13], a[57]); // Sum(70) res[71] = fma52lo(res[71], a[14], a[57]); // Sum(71) res[72] = fma52hi(res[72], a[14], a[57]); // Sum(71) res[60] = fma52lo(res[60], a[2], a[58]); // Sum(60) res[61] = fma52hi(res[61], a[2], a[58]); // Sum(60) res[61] = fma52lo(res[61], a[3], a[58]); // Sum(61) res[62] = fma52hi(res[62], a[3], a[58]); // Sum(61) res[62] = fma52lo(res[62], a[4], a[58]); // Sum(62) res[63] = fma52hi(res[63], a[4], a[58]); // Sum(62) res[63] = fma52lo(res[63], a[5], a[58]); // Sum(63) res[64] = fma52hi(res[64], a[5], a[58]); // Sum(63) res[64] = fma52lo(res[64], a[6], a[58]); // Sum(64) res[65] = fma52hi(res[65], a[6], a[58]); // Sum(64) res[65] = fma52lo(res[65], a[7], a[58]); // Sum(65) res[66] = fma52hi(res[66], a[7], a[58]); // Sum(65) res[66] = fma52lo(res[66], a[8], a[58]); // Sum(66) res[67] = fma52hi(res[67], a[8], a[58]); // Sum(66) res[67] = fma52lo(res[67], a[9], a[58]); // Sum(67) res[68] = fma52hi(res[68], a[9], a[58]); // Sum(67) res[68] = fma52lo(res[68], a[10], a[58]); // Sum(68) res[69] = fma52hi(res[69], a[10], a[58]); // Sum(68) res[69] = fma52lo(res[69], a[11], a[58]); // Sum(69) res[70] = fma52hi(res[70], a[11], a[58]); // Sum(69) res[70] = fma52lo(res[70], a[12], a[58]); // Sum(70) res[71] = fma52hi(res[71], a[12], a[58]); // Sum(70) res[71] = fma52lo(res[71], a[13], a[58]); // Sum(71) res[72] = fma52hi(res[72], a[13], a[58]); // Sum(71) res[60] = fma52lo(res[60], a[1], a[59]); // Sum(60) res[61] = fma52hi(res[61], a[1], a[59]); // Sum(60) res[61] = fma52lo(res[61], a[2], a[59]); // Sum(61) res[62] = fma52hi(res[62], a[2], a[59]); // Sum(61) res[62] = fma52lo(res[62], a[3], a[59]); // Sum(62) res[63] = fma52hi(res[63], a[3], a[59]); // Sum(62) res[63] = fma52lo(res[63], a[4], a[59]); // Sum(63) res[64] = fma52hi(res[64], a[4], a[59]); // Sum(63) res[64] = fma52lo(res[64], a[5], a[59]); // Sum(64) res[65] = fma52hi(res[65], a[5], a[59]); // Sum(64) res[65] = fma52lo(res[65], a[6], a[59]); // Sum(65) res[66] = fma52hi(res[66], a[6], a[59]); // Sum(65) res[66] = fma52lo(res[66], a[7], a[59]); // Sum(66) res[67] = fma52hi(res[67], a[7], a[59]); // Sum(66) res[67] = fma52lo(res[67], a[8], a[59]); // Sum(67) res[68] = fma52hi(res[68], a[8], a[59]); // Sum(67) res[68] = fma52lo(res[68], a[9], a[59]); // Sum(68) res[69] = fma52hi(res[69], a[9], a[59]); // Sum(68) res[69] = fma52lo(res[69], a[10], a[59]); // Sum(69) res[70] = fma52hi(res[70], a[10], a[59]); // Sum(69) res[70] = fma52lo(res[70], a[11], a[59]); // Sum(70) res[71] = fma52hi(res[71], a[11], a[59]); // Sum(70) res[71] = fma52lo(res[71], a[12], a[59]); // Sum(71) res[72] = fma52hi(res[72], a[12], a[59]); // Sum(71) res[60] = fma52lo(res[60], a[0], a[60]); // Sum(60) res[61] = fma52hi(res[61], a[0], a[60]); // Sum(60) res[61] = fma52lo(res[61], a[1], a[60]); // Sum(61) res[62] = fma52hi(res[62], a[1], a[60]); // Sum(61) res[62] = fma52lo(res[62], a[2], a[60]); // Sum(62) res[63] = fma52hi(res[63], a[2], a[60]); // Sum(62) res[63] = fma52lo(res[63], a[3], a[60]); // Sum(63) res[64] = fma52hi(res[64], a[3], a[60]); // Sum(63) res[64] = fma52lo(res[64], a[4], a[60]); // Sum(64) res[65] = fma52hi(res[65], a[4], a[60]); // Sum(64) res[65] = fma52lo(res[65], a[5], a[60]); // Sum(65) res[66] = fma52hi(res[66], a[5], a[60]); // Sum(65) res[66] = fma52lo(res[66], a[6], a[60]); // Sum(66) res[67] = fma52hi(res[67], a[6], a[60]); // Sum(66) res[67] = fma52lo(res[67], a[7], a[60]); // Sum(67) res[68] = fma52hi(res[68], a[7], a[60]); // Sum(67) res[68] = fma52lo(res[68], a[8], a[60]); // Sum(68) res[69] = fma52hi(res[69], a[8], a[60]); // Sum(68) res[69] = fma52lo(res[69], a[9], a[60]); // Sum(69) res[70] = fma52hi(res[70], a[9], a[60]); // Sum(69) res[70] = fma52lo(res[70], a[10], a[60]); // Sum(70) res[71] = fma52hi(res[71], a[10], a[60]); // Sum(70) res[71] = fma52lo(res[71], a[11], a[60]); // Sum(71) res[72] = fma52hi(res[72], a[11], a[60]); // Sum(71) res[61] = fma52lo(res[61], a[0], a[61]); // Sum(61) res[62] = fma52hi(res[62], a[0], a[61]); // Sum(61) res[62] = fma52lo(res[62], a[1], a[61]); // Sum(62) res[63] = fma52hi(res[63], a[1], a[61]); // Sum(62) res[63] = fma52lo(res[63], a[2], a[61]); // Sum(63) res[64] = fma52hi(res[64], a[2], a[61]); // Sum(63) res[64] = fma52lo(res[64], a[3], a[61]); // Sum(64) res[65] = fma52hi(res[65], a[3], a[61]); // Sum(64) res[65] = fma52lo(res[65], a[4], a[61]); // Sum(65) res[66] = fma52hi(res[66], a[4], a[61]); // Sum(65) res[66] = fma52lo(res[66], a[5], a[61]); // Sum(66) res[67] = fma52hi(res[67], a[5], a[61]); // Sum(66) res[67] = fma52lo(res[67], a[6], a[61]); // Sum(67) res[68] = fma52hi(res[68], a[6], a[61]); // Sum(67) res[68] = fma52lo(res[68], a[7], a[61]); // Sum(68) res[69] = fma52hi(res[69], a[7], a[61]); // Sum(68) res[69] = fma52lo(res[69], a[8], a[61]); // Sum(69) res[70] = fma52hi(res[70], a[8], a[61]); // Sum(69) res[70] = fma52lo(res[70], a[9], a[61]); // Sum(70) res[71] = fma52hi(res[71], a[9], a[61]); // Sum(70) res[71] = fma52lo(res[71], a[10], a[61]); // Sum(71) res[72] = fma52hi(res[72], a[10], a[61]); // Sum(71) res[62] = fma52lo(res[62], a[0], a[62]); // Sum(62) res[63] = fma52hi(res[63], a[0], a[62]); // Sum(62) res[63] = fma52lo(res[63], a[1], a[62]); // Sum(63) res[64] = fma52hi(res[64], a[1], a[62]); // Sum(63) res[64] = fma52lo(res[64], a[2], a[62]); // Sum(64) res[65] = fma52hi(res[65], a[2], a[62]); // Sum(64) res[65] = fma52lo(res[65], a[3], a[62]); // Sum(65) res[66] = fma52hi(res[66], a[3], a[62]); // Sum(65) res[66] = fma52lo(res[66], a[4], a[62]); // Sum(66) res[67] = fma52hi(res[67], a[4], a[62]); // Sum(66) res[67] = fma52lo(res[67], a[5], a[62]); // Sum(67) res[68] = fma52hi(res[68], a[5], a[62]); // Sum(67) res[68] = fma52lo(res[68], a[6], a[62]); // Sum(68) res[69] = fma52hi(res[69], a[6], a[62]); // Sum(68) res[69] = fma52lo(res[69], a[7], a[62]); // Sum(69) res[70] = fma52hi(res[70], a[7], a[62]); // Sum(69) res[70] = fma52lo(res[70], a[8], a[62]); // Sum(70) res[71] = fma52hi(res[71], a[8], a[62]); // Sum(70) res[71] = fma52lo(res[71], a[9], a[62]); // Sum(71) res[72] = fma52hi(res[72], a[9], a[62]); // Sum(71) res[63] = fma52lo(res[63], a[0], a[63]); // Sum(63) res[64] = fma52hi(res[64], a[0], a[63]); // Sum(63) res[64] = fma52lo(res[64], a[1], a[63]); // Sum(64) res[65] = fma52hi(res[65], a[1], a[63]); // Sum(64) res[65] = fma52lo(res[65], a[2], a[63]); // Sum(65) res[66] = fma52hi(res[66], a[2], a[63]); // Sum(65) res[66] = fma52lo(res[66], a[3], a[63]); // Sum(66) res[67] = fma52hi(res[67], a[3], a[63]); // Sum(66) res[67] = fma52lo(res[67], a[4], a[63]); // Sum(67) res[68] = fma52hi(res[68], a[4], a[63]); // Sum(67) res[68] = fma52lo(res[68], a[5], a[63]); // Sum(68) res[69] = fma52hi(res[69], a[5], a[63]); // Sum(68) res[69] = fma52lo(res[69], a[6], a[63]); // Sum(69) res[70] = fma52hi(res[70], a[6], a[63]); // Sum(69) res[70] = fma52lo(res[70], a[7], a[63]); // Sum(70) res[71] = fma52hi(res[71], a[7], a[63]); // Sum(70) res[71] = fma52lo(res[71], a[8], a[63]); // Sum(71) res[72] = fma52hi(res[72], a[8], a[63]); // Sum(71) res[64] = fma52lo(res[64], a[0], a[64]); // Sum(64) res[65] = fma52hi(res[65], a[0], a[64]); // Sum(64) res[65] = fma52lo(res[65], a[1], a[64]); // Sum(65) res[66] = fma52hi(res[66], a[1], a[64]); // Sum(65) res[66] = fma52lo(res[66], a[2], a[64]); // Sum(66) res[67] = fma52hi(res[67], a[2], a[64]); // Sum(66) res[67] = fma52lo(res[67], a[3], a[64]); // Sum(67) res[68] = fma52hi(res[68], a[3], a[64]); // Sum(67) res[68] = fma52lo(res[68], a[4], a[64]); // Sum(68) res[69] = fma52hi(res[69], a[4], a[64]); // Sum(68) res[69] = fma52lo(res[69], a[5], a[64]); // Sum(69) res[70] = fma52hi(res[70], a[5], a[64]); // Sum(69) res[70] = fma52lo(res[70], a[6], a[64]); // Sum(70) res[71] = fma52hi(res[71], a[6], a[64]); // Sum(70) res[71] = fma52lo(res[71], a[7], a[64]); // Sum(71) res[72] = fma52hi(res[72], a[7], a[64]); // Sum(71) res[65] = fma52lo(res[65], a[0], a[65]); // Sum(65) res[66] = fma52hi(res[66], a[0], a[65]); // Sum(65) res[66] = fma52lo(res[66], a[1], a[65]); // Sum(66) res[67] = fma52hi(res[67], a[1], a[65]); // Sum(66) res[67] = fma52lo(res[67], a[2], a[65]); // Sum(67) res[68] = fma52hi(res[68], a[2], a[65]); // Sum(67) res[68] = fma52lo(res[68], a[3], a[65]); // Sum(68) res[69] = fma52hi(res[69], a[3], a[65]); // Sum(68) res[69] = fma52lo(res[69], a[4], a[65]); // Sum(69) res[70] = fma52hi(res[70], a[4], a[65]); // Sum(69) res[70] = fma52lo(res[70], a[5], a[65]); // Sum(70) res[71] = fma52hi(res[71], a[5], a[65]); // Sum(70) res[71] = fma52lo(res[71], a[6], a[65]); // Sum(71) res[72] = fma52hi(res[72], a[6], a[65]); // Sum(71) res[66] = fma52lo(res[66], a[0], a[66]); // Sum(66) res[67] = fma52hi(res[67], a[0], a[66]); // Sum(66) res[67] = fma52lo(res[67], a[1], a[66]); // Sum(67) res[68] = fma52hi(res[68], a[1], a[66]); // Sum(67) res[68] = fma52lo(res[68], a[2], a[66]); // Sum(68) res[69] = fma52hi(res[69], a[2], a[66]); // Sum(68) res[69] = fma52lo(res[69], a[3], a[66]); // Sum(69) res[70] = fma52hi(res[70], a[3], a[66]); // Sum(69) res[70] = fma52lo(res[70], a[4], a[66]); // Sum(70) res[71] = fma52hi(res[71], a[4], a[66]); // Sum(70) res[71] = fma52lo(res[71], a[5], a[66]); // Sum(71) res[72] = fma52hi(res[72], a[5], a[66]); // Sum(71) res[67] = fma52lo(res[67], a[0], a[67]); // Sum(67) res[68] = fma52hi(res[68], a[0], a[67]); // Sum(67) res[68] = fma52lo(res[68], a[1], a[67]); // Sum(68) res[69] = fma52hi(res[69], a[1], a[67]); // Sum(68) res[69] = fma52lo(res[69], a[2], a[67]); // Sum(69) res[70] = fma52hi(res[70], a[2], a[67]); // Sum(69) res[70] = fma52lo(res[70], a[3], a[67]); // Sum(70) res[71] = fma52hi(res[71], a[3], a[67]); // Sum(70) res[71] = fma52lo(res[71], a[4], a[67]); // Sum(71) res[72] = fma52hi(res[72], a[4], a[67]); // Sum(71) res[68] = fma52lo(res[68], a[0], a[68]); // Sum(68) res[69] = fma52hi(res[69], a[0], a[68]); // Sum(68) res[69] = fma52lo(res[69], a[1], a[68]); // Sum(69) res[70] = fma52hi(res[70], a[1], a[68]); // Sum(69) res[70] = fma52lo(res[70], a[2], a[68]); // Sum(70) res[71] = fma52hi(res[71], a[2], a[68]); // Sum(70) res[71] = fma52lo(res[71], a[3], a[68]); // Sum(71) res[72] = fma52hi(res[72], a[3], a[68]); // Sum(71) res[69] = fma52lo(res[69], a[0], a[69]); // Sum(69) res[70] = fma52hi(res[70], a[0], a[69]); // Sum(69) res[70] = fma52lo(res[70], a[1], a[69]); // Sum(70) res[71] = fma52hi(res[71], a[1], a[69]); // Sum(70) res[71] = fma52lo(res[71], a[2], a[69]); // Sum(71) res[72] = fma52hi(res[72], a[2], a[69]); // Sum(71) res[70] = fma52lo(res[70], a[0], a[70]); // Sum(70) res[71] = fma52hi(res[71], a[0], a[70]); // Sum(70) res[71] = fma52lo(res[71], a[1], a[70]); // Sum(71) res[72] = fma52hi(res[72], a[1], a[70]); // Sum(71) res[71] = fma52lo(res[71], a[0], a[71]); // Sum(71) res[72] = fma52hi(res[72], a[0], a[71]); // Sum(71) res[60] = add64(res[60], res[60]); // Double(60) res[61] = add64(res[61], res[61]); // Double(61) res[62] = add64(res[62], res[62]); // Double(62) res[63] = add64(res[63], res[63]); // Double(63) res[64] = add64(res[64], res[64]); // Double(64) res[65] = add64(res[65], res[65]); // Double(65) res[66] = add64(res[66], res[66]); // Double(66) res[67] = add64(res[67], res[67]); // Double(67) res[68] = add64(res[68], res[68]); // Double(68) res[69] = add64(res[69], res[69]); // Double(69) res[70] = add64(res[70], res[70]); // Double(70) res[71] = add64(res[71], res[71]); // Double(71) res[60] = fma52lo(res[60], a[30], a[30]); // Add sqr(60) res[61] = fma52hi(res[61], a[30], a[30]); // Add sqr(60) res[62] = fma52lo(res[62], a[31], a[31]); // Add sqr(62) res[63] = fma52hi(res[63], a[31], a[31]); // Add sqr(62) res[64] = fma52lo(res[64], a[32], a[32]); // Add sqr(64) res[65] = fma52hi(res[65], a[32], a[32]); // Add sqr(64) res[66] = fma52lo(res[66], a[33], a[33]); // Add sqr(66) res[67] = fma52hi(res[67], a[33], a[33]); // Add sqr(66) res[68] = fma52lo(res[68], a[34], a[34]); // Add sqr(68) res[69] = fma52hi(res[69], a[34], a[34]); // Add sqr(68) res[70] = fma52lo(res[70], a[35], a[35]); // Add sqr(70) res[71] = fma52hi(res[71], a[35], a[35]); // Add sqr(70) res[72] = fma52lo(res[72], a[35], a[37]); // Sum(72) res[73] = fma52hi(res[73], a[35], a[37]); // Sum(72) res[73] = fma52lo(res[73], a[36], a[37]); // Sum(73) res[74] = fma52hi(res[74], a[36], a[37]); // Sum(73) res[72] = fma52lo(res[72], a[34], a[38]); // Sum(72) res[73] = fma52hi(res[73], a[34], a[38]); // Sum(72) res[73] = fma52lo(res[73], a[35], a[38]); // Sum(73) res[74] = fma52hi(res[74], a[35], a[38]); // Sum(73) res[74] = fma52lo(res[74], a[36], a[38]); // Sum(74) res[75] = fma52hi(res[75], a[36], a[38]); // Sum(74) res[75] = fma52lo(res[75], a[37], a[38]); // Sum(75) res[76] = fma52hi(res[76], a[37], a[38]); // Sum(75) res[72] = fma52lo(res[72], a[33], a[39]); // Sum(72) res[73] = fma52hi(res[73], a[33], a[39]); // Sum(72) res[73] = fma52lo(res[73], a[34], a[39]); // Sum(73) res[74] = fma52hi(res[74], a[34], a[39]); // Sum(73) res[74] = fma52lo(res[74], a[35], a[39]); // Sum(74) res[75] = fma52hi(res[75], a[35], a[39]); // Sum(74) res[75] = fma52lo(res[75], a[36], a[39]); // Sum(75) res[76] = fma52hi(res[76], a[36], a[39]); // Sum(75) res[76] = fma52lo(res[76], a[37], a[39]); // Sum(76) res[77] = fma52hi(res[77], a[37], a[39]); // Sum(76) res[77] = fma52lo(res[77], a[38], a[39]); // Sum(77) res[78] = fma52hi(res[78], a[38], a[39]); // Sum(77) res[72] = fma52lo(res[72], a[32], a[40]); // Sum(72) res[73] = fma52hi(res[73], a[32], a[40]); // Sum(72) res[73] = fma52lo(res[73], a[33], a[40]); // Sum(73) res[74] = fma52hi(res[74], a[33], a[40]); // Sum(73) res[74] = fma52lo(res[74], a[34], a[40]); // Sum(74) res[75] = fma52hi(res[75], a[34], a[40]); // Sum(74) res[75] = fma52lo(res[75], a[35], a[40]); // Sum(75) res[76] = fma52hi(res[76], a[35], a[40]); // Sum(75) res[76] = fma52lo(res[76], a[36], a[40]); // Sum(76) res[77] = fma52hi(res[77], a[36], a[40]); // Sum(76) res[77] = fma52lo(res[77], a[37], a[40]); // Sum(77) res[78] = fma52hi(res[78], a[37], a[40]); // Sum(77) res[78] = fma52lo(res[78], a[38], a[40]); // Sum(78) res[79] = fma52hi(res[79], a[38], a[40]); // Sum(78) res[79] = fma52lo(res[79], a[39], a[40]); // Sum(79) res[80] = fma52hi(res[80], a[39], a[40]); // Sum(79) res[72] = fma52lo(res[72], a[31], a[41]); // Sum(72) res[73] = fma52hi(res[73], a[31], a[41]); // Sum(72) res[73] = fma52lo(res[73], a[32], a[41]); // Sum(73) res[74] = fma52hi(res[74], a[32], a[41]); // Sum(73) res[74] = fma52lo(res[74], a[33], a[41]); // Sum(74) res[75] = fma52hi(res[75], a[33], a[41]); // Sum(74) res[75] = fma52lo(res[75], a[34], a[41]); // Sum(75) res[76] = fma52hi(res[76], a[34], a[41]); // Sum(75) res[76] = fma52lo(res[76], a[35], a[41]); // Sum(76) res[77] = fma52hi(res[77], a[35], a[41]); // Sum(76) res[77] = fma52lo(res[77], a[36], a[41]); // Sum(77) res[78] = fma52hi(res[78], a[36], a[41]); // Sum(77) res[78] = fma52lo(res[78], a[37], a[41]); // Sum(78) res[79] = fma52hi(res[79], a[37], a[41]); // Sum(78) res[79] = fma52lo(res[79], a[38], a[41]); // Sum(79) res[80] = fma52hi(res[80], a[38], a[41]); // Sum(79) res[80] = fma52lo(res[80], a[39], a[41]); // Sum(80) res[81] = fma52hi(res[81], a[39], a[41]); // Sum(80) res[81] = fma52lo(res[81], a[40], a[41]); // Sum(81) res[82] = fma52hi(res[82], a[40], a[41]); // Sum(81) res[72] = fma52lo(res[72], a[30], a[42]); // Sum(72) res[73] = fma52hi(res[73], a[30], a[42]); // Sum(72) res[73] = fma52lo(res[73], a[31], a[42]); // Sum(73) res[74] = fma52hi(res[74], a[31], a[42]); // Sum(73) res[74] = fma52lo(res[74], a[32], a[42]); // Sum(74) res[75] = fma52hi(res[75], a[32], a[42]); // Sum(74) res[75] = fma52lo(res[75], a[33], a[42]); // Sum(75) res[76] = fma52hi(res[76], a[33], a[42]); // Sum(75) res[76] = fma52lo(res[76], a[34], a[42]); // Sum(76) res[77] = fma52hi(res[77], a[34], a[42]); // Sum(76) res[77] = fma52lo(res[77], a[35], a[42]); // Sum(77) res[78] = fma52hi(res[78], a[35], a[42]); // Sum(77) res[78] = fma52lo(res[78], a[36], a[42]); // Sum(78) res[79] = fma52hi(res[79], a[36], a[42]); // Sum(78) res[79] = fma52lo(res[79], a[37], a[42]); // Sum(79) res[80] = fma52hi(res[80], a[37], a[42]); // Sum(79) res[80] = fma52lo(res[80], a[38], a[42]); // Sum(80) res[81] = fma52hi(res[81], a[38], a[42]); // Sum(80) res[81] = fma52lo(res[81], a[39], a[42]); // Sum(81) res[82] = fma52hi(res[82], a[39], a[42]); // Sum(81) res[82] = fma52lo(res[82], a[40], a[42]); // Sum(82) res[83] = fma52hi(res[83], a[40], a[42]); // Sum(82) res[83] = fma52lo(res[83], a[41], a[42]); // Sum(83) res[84] = fma52hi(res[84], a[41], a[42]); // Sum(83) res[72] = fma52lo(res[72], a[29], a[43]); // Sum(72) res[73] = fma52hi(res[73], a[29], a[43]); // Sum(72) res[73] = fma52lo(res[73], a[30], a[43]); // Sum(73) res[74] = fma52hi(res[74], a[30], a[43]); // Sum(73) res[74] = fma52lo(res[74], a[31], a[43]); // Sum(74) res[75] = fma52hi(res[75], a[31], a[43]); // Sum(74) res[75] = fma52lo(res[75], a[32], a[43]); // Sum(75) res[76] = fma52hi(res[76], a[32], a[43]); // Sum(75) res[76] = fma52lo(res[76], a[33], a[43]); // Sum(76) res[77] = fma52hi(res[77], a[33], a[43]); // Sum(76) res[77] = fma52lo(res[77], a[34], a[43]); // Sum(77) res[78] = fma52hi(res[78], a[34], a[43]); // Sum(77) res[78] = fma52lo(res[78], a[35], a[43]); // Sum(78) res[79] = fma52hi(res[79], a[35], a[43]); // Sum(78) res[79] = fma52lo(res[79], a[36], a[43]); // Sum(79) res[80] = fma52hi(res[80], a[36], a[43]); // Sum(79) res[80] = fma52lo(res[80], a[37], a[43]); // Sum(80) res[81] = fma52hi(res[81], a[37], a[43]); // Sum(80) res[81] = fma52lo(res[81], a[38], a[43]); // Sum(81) res[82] = fma52hi(res[82], a[38], a[43]); // Sum(81) res[82] = fma52lo(res[82], a[39], a[43]); // Sum(82) res[83] = fma52hi(res[83], a[39], a[43]); // Sum(82) res[83] = fma52lo(res[83], a[40], a[43]); // Sum(83) res[84] = fma52hi(res[84], a[40], a[43]); // Sum(83) res[72] = fma52lo(res[72], a[28], a[44]); // Sum(72) res[73] = fma52hi(res[73], a[28], a[44]); // Sum(72) res[73] = fma52lo(res[73], a[29], a[44]); // Sum(73) res[74] = fma52hi(res[74], a[29], a[44]); // Sum(73) res[74] = fma52lo(res[74], a[30], a[44]); // Sum(74) res[75] = fma52hi(res[75], a[30], a[44]); // Sum(74) res[75] = fma52lo(res[75], a[31], a[44]); // Sum(75) res[76] = fma52hi(res[76], a[31], a[44]); // Sum(75) res[76] = fma52lo(res[76], a[32], a[44]); // Sum(76) res[77] = fma52hi(res[77], a[32], a[44]); // Sum(76) res[77] = fma52lo(res[77], a[33], a[44]); // Sum(77) res[78] = fma52hi(res[78], a[33], a[44]); // Sum(77) res[78] = fma52lo(res[78], a[34], a[44]); // Sum(78) res[79] = fma52hi(res[79], a[34], a[44]); // Sum(78) res[79] = fma52lo(res[79], a[35], a[44]); // Sum(79) res[80] = fma52hi(res[80], a[35], a[44]); // Sum(79) res[80] = fma52lo(res[80], a[36], a[44]); // Sum(80) res[81] = fma52hi(res[81], a[36], a[44]); // Sum(80) res[81] = fma52lo(res[81], a[37], a[44]); // Sum(81) res[82] = fma52hi(res[82], a[37], a[44]); // Sum(81) res[82] = fma52lo(res[82], a[38], a[44]); // Sum(82) res[83] = fma52hi(res[83], a[38], a[44]); // Sum(82) res[83] = fma52lo(res[83], a[39], a[44]); // Sum(83) res[84] = fma52hi(res[84], a[39], a[44]); // Sum(83) res[72] = fma52lo(res[72], a[27], a[45]); // Sum(72) res[73] = fma52hi(res[73], a[27], a[45]); // Sum(72) res[73] = fma52lo(res[73], a[28], a[45]); // Sum(73) res[74] = fma52hi(res[74], a[28], a[45]); // Sum(73) res[74] = fma52lo(res[74], a[29], a[45]); // Sum(74) res[75] = fma52hi(res[75], a[29], a[45]); // Sum(74) res[75] = fma52lo(res[75], a[30], a[45]); // Sum(75) res[76] = fma52hi(res[76], a[30], a[45]); // Sum(75) res[76] = fma52lo(res[76], a[31], a[45]); // Sum(76) res[77] = fma52hi(res[77], a[31], a[45]); // Sum(76) res[77] = fma52lo(res[77], a[32], a[45]); // Sum(77) res[78] = fma52hi(res[78], a[32], a[45]); // Sum(77) res[78] = fma52lo(res[78], a[33], a[45]); // Sum(78) res[79] = fma52hi(res[79], a[33], a[45]); // Sum(78) res[79] = fma52lo(res[79], a[34], a[45]); // Sum(79) res[80] = fma52hi(res[80], a[34], a[45]); // Sum(79) res[80] = fma52lo(res[80], a[35], a[45]); // Sum(80) res[81] = fma52hi(res[81], a[35], a[45]); // Sum(80) res[81] = fma52lo(res[81], a[36], a[45]); // Sum(81) res[82] = fma52hi(res[82], a[36], a[45]); // Sum(81) res[82] = fma52lo(res[82], a[37], a[45]); // Sum(82) res[83] = fma52hi(res[83], a[37], a[45]); // Sum(82) res[83] = fma52lo(res[83], a[38], a[45]); // Sum(83) res[84] = fma52hi(res[84], a[38], a[45]); // Sum(83) res[72] = fma52lo(res[72], a[26], a[46]); // Sum(72) res[73] = fma52hi(res[73], a[26], a[46]); // Sum(72) res[73] = fma52lo(res[73], a[27], a[46]); // Sum(73) res[74] = fma52hi(res[74], a[27], a[46]); // Sum(73) res[74] = fma52lo(res[74], a[28], a[46]); // Sum(74) res[75] = fma52hi(res[75], a[28], a[46]); // Sum(74) res[75] = fma52lo(res[75], a[29], a[46]); // Sum(75) res[76] = fma52hi(res[76], a[29], a[46]); // Sum(75) res[76] = fma52lo(res[76], a[30], a[46]); // Sum(76) res[77] = fma52hi(res[77], a[30], a[46]); // Sum(76) res[77] = fma52lo(res[77], a[31], a[46]); // Sum(77) res[78] = fma52hi(res[78], a[31], a[46]); // Sum(77) res[78] = fma52lo(res[78], a[32], a[46]); // Sum(78) res[79] = fma52hi(res[79], a[32], a[46]); // Sum(78) res[79] = fma52lo(res[79], a[33], a[46]); // Sum(79) res[80] = fma52hi(res[80], a[33], a[46]); // Sum(79) res[80] = fma52lo(res[80], a[34], a[46]); // Sum(80) res[81] = fma52hi(res[81], a[34], a[46]); // Sum(80) res[81] = fma52lo(res[81], a[35], a[46]); // Sum(81) res[82] = fma52hi(res[82], a[35], a[46]); // Sum(81) res[82] = fma52lo(res[82], a[36], a[46]); // Sum(82) res[83] = fma52hi(res[83], a[36], a[46]); // Sum(82) res[83] = fma52lo(res[83], a[37], a[46]); // Sum(83) res[84] = fma52hi(res[84], a[37], a[46]); // Sum(83) res[72] = fma52lo(res[72], a[25], a[47]); // Sum(72) res[73] = fma52hi(res[73], a[25], a[47]); // Sum(72) res[73] = fma52lo(res[73], a[26], a[47]); // Sum(73) res[74] = fma52hi(res[74], a[26], a[47]); // Sum(73) res[74] = fma52lo(res[74], a[27], a[47]); // Sum(74) res[75] = fma52hi(res[75], a[27], a[47]); // Sum(74) res[75] = fma52lo(res[75], a[28], a[47]); // Sum(75) res[76] = fma52hi(res[76], a[28], a[47]); // Sum(75) res[76] = fma52lo(res[76], a[29], a[47]); // Sum(76) res[77] = fma52hi(res[77], a[29], a[47]); // Sum(76) res[77] = fma52lo(res[77], a[30], a[47]); // Sum(77) res[78] = fma52hi(res[78], a[30], a[47]); // Sum(77) res[78] = fma52lo(res[78], a[31], a[47]); // Sum(78) res[79] = fma52hi(res[79], a[31], a[47]); // Sum(78) res[79] = fma52lo(res[79], a[32], a[47]); // Sum(79) res[80] = fma52hi(res[80], a[32], a[47]); // Sum(79) res[80] = fma52lo(res[80], a[33], a[47]); // Sum(80) res[81] = fma52hi(res[81], a[33], a[47]); // Sum(80) res[81] = fma52lo(res[81], a[34], a[47]); // Sum(81) res[82] = fma52hi(res[82], a[34], a[47]); // Sum(81) res[82] = fma52lo(res[82], a[35], a[47]); // Sum(82) res[83] = fma52hi(res[83], a[35], a[47]); // Sum(82) res[83] = fma52lo(res[83], a[36], a[47]); // Sum(83) res[84] = fma52hi(res[84], a[36], a[47]); // Sum(83) res[72] = fma52lo(res[72], a[24], a[48]); // Sum(72) res[73] = fma52hi(res[73], a[24], a[48]); // Sum(72) res[73] = fma52lo(res[73], a[25], a[48]); // Sum(73) res[74] = fma52hi(res[74], a[25], a[48]); // Sum(73) res[74] = fma52lo(res[74], a[26], a[48]); // Sum(74) res[75] = fma52hi(res[75], a[26], a[48]); // Sum(74) res[75] = fma52lo(res[75], a[27], a[48]); // Sum(75) res[76] = fma52hi(res[76], a[27], a[48]); // Sum(75) res[76] = fma52lo(res[76], a[28], a[48]); // Sum(76) res[77] = fma52hi(res[77], a[28], a[48]); // Sum(76) res[77] = fma52lo(res[77], a[29], a[48]); // Sum(77) res[78] = fma52hi(res[78], a[29], a[48]); // Sum(77) res[78] = fma52lo(res[78], a[30], a[48]); // Sum(78) res[79] = fma52hi(res[79], a[30], a[48]); // Sum(78) res[79] = fma52lo(res[79], a[31], a[48]); // Sum(79) res[80] = fma52hi(res[80], a[31], a[48]); // Sum(79) res[80] = fma52lo(res[80], a[32], a[48]); // Sum(80) res[81] = fma52hi(res[81], a[32], a[48]); // Sum(80) res[81] = fma52lo(res[81], a[33], a[48]); // Sum(81) res[82] = fma52hi(res[82], a[33], a[48]); // Sum(81) res[82] = fma52lo(res[82], a[34], a[48]); // Sum(82) res[83] = fma52hi(res[83], a[34], a[48]); // Sum(82) res[83] = fma52lo(res[83], a[35], a[48]); // Sum(83) res[84] = fma52hi(res[84], a[35], a[48]); // Sum(83) res[72] = fma52lo(res[72], a[23], a[49]); // Sum(72) res[73] = fma52hi(res[73], a[23], a[49]); // Sum(72) res[73] = fma52lo(res[73], a[24], a[49]); // Sum(73) res[74] = fma52hi(res[74], a[24], a[49]); // Sum(73) res[74] = fma52lo(res[74], a[25], a[49]); // Sum(74) res[75] = fma52hi(res[75], a[25], a[49]); // Sum(74) res[75] = fma52lo(res[75], a[26], a[49]); // Sum(75) res[76] = fma52hi(res[76], a[26], a[49]); // Sum(75) res[76] = fma52lo(res[76], a[27], a[49]); // Sum(76) res[77] = fma52hi(res[77], a[27], a[49]); // Sum(76) res[77] = fma52lo(res[77], a[28], a[49]); // Sum(77) res[78] = fma52hi(res[78], a[28], a[49]); // Sum(77) res[78] = fma52lo(res[78], a[29], a[49]); // Sum(78) res[79] = fma52hi(res[79], a[29], a[49]); // Sum(78) res[79] = fma52lo(res[79], a[30], a[49]); // Sum(79) res[80] = fma52hi(res[80], a[30], a[49]); // Sum(79) res[80] = fma52lo(res[80], a[31], a[49]); // Sum(80) res[81] = fma52hi(res[81], a[31], a[49]); // Sum(80) res[81] = fma52lo(res[81], a[32], a[49]); // Sum(81) res[82] = fma52hi(res[82], a[32], a[49]); // Sum(81) res[82] = fma52lo(res[82], a[33], a[49]); // Sum(82) res[83] = fma52hi(res[83], a[33], a[49]); // Sum(82) res[83] = fma52lo(res[83], a[34], a[49]); // Sum(83) res[84] = fma52hi(res[84], a[34], a[49]); // Sum(83) res[72] = fma52lo(res[72], a[22], a[50]); // Sum(72) res[73] = fma52hi(res[73], a[22], a[50]); // Sum(72) res[73] = fma52lo(res[73], a[23], a[50]); // Sum(73) res[74] = fma52hi(res[74], a[23], a[50]); // Sum(73) res[74] = fma52lo(res[74], a[24], a[50]); // Sum(74) res[75] = fma52hi(res[75], a[24], a[50]); // Sum(74) res[75] = fma52lo(res[75], a[25], a[50]); // Sum(75) res[76] = fma52hi(res[76], a[25], a[50]); // Sum(75) res[76] = fma52lo(res[76], a[26], a[50]); // Sum(76) res[77] = fma52hi(res[77], a[26], a[50]); // Sum(76) res[77] = fma52lo(res[77], a[27], a[50]); // Sum(77) res[78] = fma52hi(res[78], a[27], a[50]); // Sum(77) res[78] = fma52lo(res[78], a[28], a[50]); // Sum(78) res[79] = fma52hi(res[79], a[28], a[50]); // Sum(78) res[79] = fma52lo(res[79], a[29], a[50]); // Sum(79) res[80] = fma52hi(res[80], a[29], a[50]); // Sum(79) res[80] = fma52lo(res[80], a[30], a[50]); // Sum(80) res[81] = fma52hi(res[81], a[30], a[50]); // Sum(80) res[81] = fma52lo(res[81], a[31], a[50]); // Sum(81) res[82] = fma52hi(res[82], a[31], a[50]); // Sum(81) res[82] = fma52lo(res[82], a[32], a[50]); // Sum(82) res[83] = fma52hi(res[83], a[32], a[50]); // Sum(82) res[83] = fma52lo(res[83], a[33], a[50]); // Sum(83) res[84] = fma52hi(res[84], a[33], a[50]); // Sum(83) res[72] = fma52lo(res[72], a[21], a[51]); // Sum(72) res[73] = fma52hi(res[73], a[21], a[51]); // Sum(72) res[73] = fma52lo(res[73], a[22], a[51]); // Sum(73) res[74] = fma52hi(res[74], a[22], a[51]); // Sum(73) res[74] = fma52lo(res[74], a[23], a[51]); // Sum(74) res[75] = fma52hi(res[75], a[23], a[51]); // Sum(74) res[75] = fma52lo(res[75], a[24], a[51]); // Sum(75) res[76] = fma52hi(res[76], a[24], a[51]); // Sum(75) res[76] = fma52lo(res[76], a[25], a[51]); // Sum(76) res[77] = fma52hi(res[77], a[25], a[51]); // Sum(76) res[77] = fma52lo(res[77], a[26], a[51]); // Sum(77) res[78] = fma52hi(res[78], a[26], a[51]); // Sum(77) res[78] = fma52lo(res[78], a[27], a[51]); // Sum(78) res[79] = fma52hi(res[79], a[27], a[51]); // Sum(78) res[79] = fma52lo(res[79], a[28], a[51]); // Sum(79) res[80] = fma52hi(res[80], a[28], a[51]); // Sum(79) res[80] = fma52lo(res[80], a[29], a[51]); // Sum(80) res[81] = fma52hi(res[81], a[29], a[51]); // Sum(80) res[81] = fma52lo(res[81], a[30], a[51]); // Sum(81) res[82] = fma52hi(res[82], a[30], a[51]); // Sum(81) res[82] = fma52lo(res[82], a[31], a[51]); // Sum(82) res[83] = fma52hi(res[83], a[31], a[51]); // Sum(82) res[83] = fma52lo(res[83], a[32], a[51]); // Sum(83) res[84] = fma52hi(res[84], a[32], a[51]); // Sum(83) res[72] = fma52lo(res[72], a[20], a[52]); // Sum(72) res[73] = fma52hi(res[73], a[20], a[52]); // Sum(72) res[73] = fma52lo(res[73], a[21], a[52]); // Sum(73) res[74] = fma52hi(res[74], a[21], a[52]); // Sum(73) res[74] = fma52lo(res[74], a[22], a[52]); // Sum(74) res[75] = fma52hi(res[75], a[22], a[52]); // Sum(74) res[75] = fma52lo(res[75], a[23], a[52]); // Sum(75) res[76] = fma52hi(res[76], a[23], a[52]); // Sum(75) res[76] = fma52lo(res[76], a[24], a[52]); // Sum(76) res[77] = fma52hi(res[77], a[24], a[52]); // Sum(76) res[77] = fma52lo(res[77], a[25], a[52]); // Sum(77) res[78] = fma52hi(res[78], a[25], a[52]); // Sum(77) res[78] = fma52lo(res[78], a[26], a[52]); // Sum(78) res[79] = fma52hi(res[79], a[26], a[52]); // Sum(78) res[79] = fma52lo(res[79], a[27], a[52]); // Sum(79) res[80] = fma52hi(res[80], a[27], a[52]); // Sum(79) res[80] = fma52lo(res[80], a[28], a[52]); // Sum(80) res[81] = fma52hi(res[81], a[28], a[52]); // Sum(80) res[81] = fma52lo(res[81], a[29], a[52]); // Sum(81) res[82] = fma52hi(res[82], a[29], a[52]); // Sum(81) res[82] = fma52lo(res[82], a[30], a[52]); // Sum(82) res[83] = fma52hi(res[83], a[30], a[52]); // Sum(82) res[83] = fma52lo(res[83], a[31], a[52]); // Sum(83) res[84] = fma52hi(res[84], a[31], a[52]); // Sum(83) res[72] = fma52lo(res[72], a[19], a[53]); // Sum(72) res[73] = fma52hi(res[73], a[19], a[53]); // Sum(72) res[73] = fma52lo(res[73], a[20], a[53]); // Sum(73) res[74] = fma52hi(res[74], a[20], a[53]); // Sum(73) res[74] = fma52lo(res[74], a[21], a[53]); // Sum(74) res[75] = fma52hi(res[75], a[21], a[53]); // Sum(74) res[75] = fma52lo(res[75], a[22], a[53]); // Sum(75) res[76] = fma52hi(res[76], a[22], a[53]); // Sum(75) res[76] = fma52lo(res[76], a[23], a[53]); // Sum(76) res[77] = fma52hi(res[77], a[23], a[53]); // Sum(76) res[77] = fma52lo(res[77], a[24], a[53]); // Sum(77) res[78] = fma52hi(res[78], a[24], a[53]); // Sum(77) res[78] = fma52lo(res[78], a[25], a[53]); // Sum(78) res[79] = fma52hi(res[79], a[25], a[53]); // Sum(78) res[79] = fma52lo(res[79], a[26], a[53]); // Sum(79) res[80] = fma52hi(res[80], a[26], a[53]); // Sum(79) res[80] = fma52lo(res[80], a[27], a[53]); // Sum(80) res[81] = fma52hi(res[81], a[27], a[53]); // Sum(80) res[81] = fma52lo(res[81], a[28], a[53]); // Sum(81) res[82] = fma52hi(res[82], a[28], a[53]); // Sum(81) res[82] = fma52lo(res[82], a[29], a[53]); // Sum(82) res[83] = fma52hi(res[83], a[29], a[53]); // Sum(82) res[83] = fma52lo(res[83], a[30], a[53]); // Sum(83) res[84] = fma52hi(res[84], a[30], a[53]); // Sum(83) res[72] = fma52lo(res[72], a[18], a[54]); // Sum(72) res[73] = fma52hi(res[73], a[18], a[54]); // Sum(72) res[73] = fma52lo(res[73], a[19], a[54]); // Sum(73) res[74] = fma52hi(res[74], a[19], a[54]); // Sum(73) res[74] = fma52lo(res[74], a[20], a[54]); // Sum(74) res[75] = fma52hi(res[75], a[20], a[54]); // Sum(74) res[75] = fma52lo(res[75], a[21], a[54]); // Sum(75) res[76] = fma52hi(res[76], a[21], a[54]); // Sum(75) res[76] = fma52lo(res[76], a[22], a[54]); // Sum(76) res[77] = fma52hi(res[77], a[22], a[54]); // Sum(76) res[77] = fma52lo(res[77], a[23], a[54]); // Sum(77) res[78] = fma52hi(res[78], a[23], a[54]); // Sum(77) res[78] = fma52lo(res[78], a[24], a[54]); // Sum(78) res[79] = fma52hi(res[79], a[24], a[54]); // Sum(78) res[79] = fma52lo(res[79], a[25], a[54]); // Sum(79) res[80] = fma52hi(res[80], a[25], a[54]); // Sum(79) res[80] = fma52lo(res[80], a[26], a[54]); // Sum(80) res[81] = fma52hi(res[81], a[26], a[54]); // Sum(80) res[81] = fma52lo(res[81], a[27], a[54]); // Sum(81) res[82] = fma52hi(res[82], a[27], a[54]); // Sum(81) res[82] = fma52lo(res[82], a[28], a[54]); // Sum(82) res[83] = fma52hi(res[83], a[28], a[54]); // Sum(82) res[83] = fma52lo(res[83], a[29], a[54]); // Sum(83) res[84] = fma52hi(res[84], a[29], a[54]); // Sum(83) res[72] = fma52lo(res[72], a[17], a[55]); // Sum(72) res[73] = fma52hi(res[73], a[17], a[55]); // Sum(72) res[73] = fma52lo(res[73], a[18], a[55]); // Sum(73) res[74] = fma52hi(res[74], a[18], a[55]); // Sum(73) res[74] = fma52lo(res[74], a[19], a[55]); // Sum(74) res[75] = fma52hi(res[75], a[19], a[55]); // Sum(74) res[75] = fma52lo(res[75], a[20], a[55]); // Sum(75) res[76] = fma52hi(res[76], a[20], a[55]); // Sum(75) res[76] = fma52lo(res[76], a[21], a[55]); // Sum(76) res[77] = fma52hi(res[77], a[21], a[55]); // Sum(76) res[77] = fma52lo(res[77], a[22], a[55]); // Sum(77) res[78] = fma52hi(res[78], a[22], a[55]); // Sum(77) res[78] = fma52lo(res[78], a[23], a[55]); // Sum(78) res[79] = fma52hi(res[79], a[23], a[55]); // Sum(78) res[79] = fma52lo(res[79], a[24], a[55]); // Sum(79) res[80] = fma52hi(res[80], a[24], a[55]); // Sum(79) res[80] = fma52lo(res[80], a[25], a[55]); // Sum(80) res[81] = fma52hi(res[81], a[25], a[55]); // Sum(80) res[81] = fma52lo(res[81], a[26], a[55]); // Sum(81) res[82] = fma52hi(res[82], a[26], a[55]); // Sum(81) res[82] = fma52lo(res[82], a[27], a[55]); // Sum(82) res[83] = fma52hi(res[83], a[27], a[55]); // Sum(82) res[83] = fma52lo(res[83], a[28], a[55]); // Sum(83) res[84] = fma52hi(res[84], a[28], a[55]); // Sum(83) res[72] = fma52lo(res[72], a[16], a[56]); // Sum(72) res[73] = fma52hi(res[73], a[16], a[56]); // Sum(72) res[73] = fma52lo(res[73], a[17], a[56]); // Sum(73) res[74] = fma52hi(res[74], a[17], a[56]); // Sum(73) res[74] = fma52lo(res[74], a[18], a[56]); // Sum(74) res[75] = fma52hi(res[75], a[18], a[56]); // Sum(74) res[75] = fma52lo(res[75], a[19], a[56]); // Sum(75) res[76] = fma52hi(res[76], a[19], a[56]); // Sum(75) res[76] = fma52lo(res[76], a[20], a[56]); // Sum(76) res[77] = fma52hi(res[77], a[20], a[56]); // Sum(76) res[77] = fma52lo(res[77], a[21], a[56]); // Sum(77) res[78] = fma52hi(res[78], a[21], a[56]); // Sum(77) res[78] = fma52lo(res[78], a[22], a[56]); // Sum(78) res[79] = fma52hi(res[79], a[22], a[56]); // Sum(78) res[79] = fma52lo(res[79], a[23], a[56]); // Sum(79) res[80] = fma52hi(res[80], a[23], a[56]); // Sum(79) res[80] = fma52lo(res[80], a[24], a[56]); // Sum(80) res[81] = fma52hi(res[81], a[24], a[56]); // Sum(80) res[81] = fma52lo(res[81], a[25], a[56]); // Sum(81) res[82] = fma52hi(res[82], a[25], a[56]); // Sum(81) res[82] = fma52lo(res[82], a[26], a[56]); // Sum(82) res[83] = fma52hi(res[83], a[26], a[56]); // Sum(82) res[83] = fma52lo(res[83], a[27], a[56]); // Sum(83) res[84] = fma52hi(res[84], a[27], a[56]); // Sum(83) res[72] = fma52lo(res[72], a[15], a[57]); // Sum(72) res[73] = fma52hi(res[73], a[15], a[57]); // Sum(72) res[73] = fma52lo(res[73], a[16], a[57]); // Sum(73) res[74] = fma52hi(res[74], a[16], a[57]); // Sum(73) res[74] = fma52lo(res[74], a[17], a[57]); // Sum(74) res[75] = fma52hi(res[75], a[17], a[57]); // Sum(74) res[75] = fma52lo(res[75], a[18], a[57]); // Sum(75) res[76] = fma52hi(res[76], a[18], a[57]); // Sum(75) res[76] = fma52lo(res[76], a[19], a[57]); // Sum(76) res[77] = fma52hi(res[77], a[19], a[57]); // Sum(76) res[77] = fma52lo(res[77], a[20], a[57]); // Sum(77) res[78] = fma52hi(res[78], a[20], a[57]); // Sum(77) res[78] = fma52lo(res[78], a[21], a[57]); // Sum(78) res[79] = fma52hi(res[79], a[21], a[57]); // Sum(78) res[79] = fma52lo(res[79], a[22], a[57]); // Sum(79) res[80] = fma52hi(res[80], a[22], a[57]); // Sum(79) res[80] = fma52lo(res[80], a[23], a[57]); // Sum(80) res[81] = fma52hi(res[81], a[23], a[57]); // Sum(80) res[81] = fma52lo(res[81], a[24], a[57]); // Sum(81) res[82] = fma52hi(res[82], a[24], a[57]); // Sum(81) res[82] = fma52lo(res[82], a[25], a[57]); // Sum(82) res[83] = fma52hi(res[83], a[25], a[57]); // Sum(82) res[83] = fma52lo(res[83], a[26], a[57]); // Sum(83) res[84] = fma52hi(res[84], a[26], a[57]); // Sum(83) res[72] = fma52lo(res[72], a[14], a[58]); // Sum(72) res[73] = fma52hi(res[73], a[14], a[58]); // Sum(72) res[73] = fma52lo(res[73], a[15], a[58]); // Sum(73) res[74] = fma52hi(res[74], a[15], a[58]); // Sum(73) res[74] = fma52lo(res[74], a[16], a[58]); // Sum(74) res[75] = fma52hi(res[75], a[16], a[58]); // Sum(74) res[75] = fma52lo(res[75], a[17], a[58]); // Sum(75) res[76] = fma52hi(res[76], a[17], a[58]); // Sum(75) res[76] = fma52lo(res[76], a[18], a[58]); // Sum(76) res[77] = fma52hi(res[77], a[18], a[58]); // Sum(76) res[77] = fma52lo(res[77], a[19], a[58]); // Sum(77) res[78] = fma52hi(res[78], a[19], a[58]); // Sum(77) res[78] = fma52lo(res[78], a[20], a[58]); // Sum(78) res[79] = fma52hi(res[79], a[20], a[58]); // Sum(78) res[79] = fma52lo(res[79], a[21], a[58]); // Sum(79) res[80] = fma52hi(res[80], a[21], a[58]); // Sum(79) res[80] = fma52lo(res[80], a[22], a[58]); // Sum(80) res[81] = fma52hi(res[81], a[22], a[58]); // Sum(80) res[81] = fma52lo(res[81], a[23], a[58]); // Sum(81) res[82] = fma52hi(res[82], a[23], a[58]); // Sum(81) res[82] = fma52lo(res[82], a[24], a[58]); // Sum(82) res[83] = fma52hi(res[83], a[24], a[58]); // Sum(82) res[83] = fma52lo(res[83], a[25], a[58]); // Sum(83) res[84] = fma52hi(res[84], a[25], a[58]); // Sum(83) res[72] = fma52lo(res[72], a[13], a[59]); // Sum(72) res[73] = fma52hi(res[73], a[13], a[59]); // Sum(72) res[73] = fma52lo(res[73], a[14], a[59]); // Sum(73) res[74] = fma52hi(res[74], a[14], a[59]); // Sum(73) res[74] = fma52lo(res[74], a[15], a[59]); // Sum(74) res[75] = fma52hi(res[75], a[15], a[59]); // Sum(74) res[75] = fma52lo(res[75], a[16], a[59]); // Sum(75) res[76] = fma52hi(res[76], a[16], a[59]); // Sum(75) res[76] = fma52lo(res[76], a[17], a[59]); // Sum(76) res[77] = fma52hi(res[77], a[17], a[59]); // Sum(76) res[77] = fma52lo(res[77], a[18], a[59]); // Sum(77) res[78] = fma52hi(res[78], a[18], a[59]); // Sum(77) res[78] = fma52lo(res[78], a[19], a[59]); // Sum(78) res[79] = fma52hi(res[79], a[19], a[59]); // Sum(78) res[79] = fma52lo(res[79], a[20], a[59]); // Sum(79) res[80] = fma52hi(res[80], a[20], a[59]); // Sum(79) res[80] = fma52lo(res[80], a[21], a[59]); // Sum(80) res[81] = fma52hi(res[81], a[21], a[59]); // Sum(80) res[81] = fma52lo(res[81], a[22], a[59]); // Sum(81) res[82] = fma52hi(res[82], a[22], a[59]); // Sum(81) res[82] = fma52lo(res[82], a[23], a[59]); // Sum(82) res[83] = fma52hi(res[83], a[23], a[59]); // Sum(82) res[83] = fma52lo(res[83], a[24], a[59]); // Sum(83) res[84] = fma52hi(res[84], a[24], a[59]); // Sum(83) res[72] = fma52lo(res[72], a[12], a[60]); // Sum(72) res[73] = fma52hi(res[73], a[12], a[60]); // Sum(72) res[73] = fma52lo(res[73], a[13], a[60]); // Sum(73) res[74] = fma52hi(res[74], a[13], a[60]); // Sum(73) res[74] = fma52lo(res[74], a[14], a[60]); // Sum(74) res[75] = fma52hi(res[75], a[14], a[60]); // Sum(74) res[75] = fma52lo(res[75], a[15], a[60]); // Sum(75) res[76] = fma52hi(res[76], a[15], a[60]); // Sum(75) res[76] = fma52lo(res[76], a[16], a[60]); // Sum(76) res[77] = fma52hi(res[77], a[16], a[60]); // Sum(76) res[77] = fma52lo(res[77], a[17], a[60]); // Sum(77) res[78] = fma52hi(res[78], a[17], a[60]); // Sum(77) res[78] = fma52lo(res[78], a[18], a[60]); // Sum(78) res[79] = fma52hi(res[79], a[18], a[60]); // Sum(78) res[79] = fma52lo(res[79], a[19], a[60]); // Sum(79) res[80] = fma52hi(res[80], a[19], a[60]); // Sum(79) res[80] = fma52lo(res[80], a[20], a[60]); // Sum(80) res[81] = fma52hi(res[81], a[20], a[60]); // Sum(80) res[81] = fma52lo(res[81], a[21], a[60]); // Sum(81) res[82] = fma52hi(res[82], a[21], a[60]); // Sum(81) res[82] = fma52lo(res[82], a[22], a[60]); // Sum(82) res[83] = fma52hi(res[83], a[22], a[60]); // Sum(82) res[83] = fma52lo(res[83], a[23], a[60]); // Sum(83) res[84] = fma52hi(res[84], a[23], a[60]); // Sum(83) res[72] = fma52lo(res[72], a[11], a[61]); // Sum(72) res[73] = fma52hi(res[73], a[11], a[61]); // Sum(72) res[73] = fma52lo(res[73], a[12], a[61]); // Sum(73) res[74] = fma52hi(res[74], a[12], a[61]); // Sum(73) res[74] = fma52lo(res[74], a[13], a[61]); // Sum(74) res[75] = fma52hi(res[75], a[13], a[61]); // Sum(74) res[75] = fma52lo(res[75], a[14], a[61]); // Sum(75) res[76] = fma52hi(res[76], a[14], a[61]); // Sum(75) res[76] = fma52lo(res[76], a[15], a[61]); // Sum(76) res[77] = fma52hi(res[77], a[15], a[61]); // Sum(76) res[77] = fma52lo(res[77], a[16], a[61]); // Sum(77) res[78] = fma52hi(res[78], a[16], a[61]); // Sum(77) res[78] = fma52lo(res[78], a[17], a[61]); // Sum(78) res[79] = fma52hi(res[79], a[17], a[61]); // Sum(78) res[79] = fma52lo(res[79], a[18], a[61]); // Sum(79) res[80] = fma52hi(res[80], a[18], a[61]); // Sum(79) res[80] = fma52lo(res[80], a[19], a[61]); // Sum(80) res[81] = fma52hi(res[81], a[19], a[61]); // Sum(80) res[81] = fma52lo(res[81], a[20], a[61]); // Sum(81) res[82] = fma52hi(res[82], a[20], a[61]); // Sum(81) res[82] = fma52lo(res[82], a[21], a[61]); // Sum(82) res[83] = fma52hi(res[83], a[21], a[61]); // Sum(82) res[83] = fma52lo(res[83], a[22], a[61]); // Sum(83) res[84] = fma52hi(res[84], a[22], a[61]); // Sum(83) res[72] = fma52lo(res[72], a[10], a[62]); // Sum(72) res[73] = fma52hi(res[73], a[10], a[62]); // Sum(72) res[73] = fma52lo(res[73], a[11], a[62]); // Sum(73) res[74] = fma52hi(res[74], a[11], a[62]); // Sum(73) res[74] = fma52lo(res[74], a[12], a[62]); // Sum(74) res[75] = fma52hi(res[75], a[12], a[62]); // Sum(74) res[75] = fma52lo(res[75], a[13], a[62]); // Sum(75) res[76] = fma52hi(res[76], a[13], a[62]); // Sum(75) res[76] = fma52lo(res[76], a[14], a[62]); // Sum(76) res[77] = fma52hi(res[77], a[14], a[62]); // Sum(76) res[77] = fma52lo(res[77], a[15], a[62]); // Sum(77) res[78] = fma52hi(res[78], a[15], a[62]); // Sum(77) res[78] = fma52lo(res[78], a[16], a[62]); // Sum(78) res[79] = fma52hi(res[79], a[16], a[62]); // Sum(78) res[79] = fma52lo(res[79], a[17], a[62]); // Sum(79) res[80] = fma52hi(res[80], a[17], a[62]); // Sum(79) res[80] = fma52lo(res[80], a[18], a[62]); // Sum(80) res[81] = fma52hi(res[81], a[18], a[62]); // Sum(80) res[81] = fma52lo(res[81], a[19], a[62]); // Sum(81) res[82] = fma52hi(res[82], a[19], a[62]); // Sum(81) res[82] = fma52lo(res[82], a[20], a[62]); // Sum(82) res[83] = fma52hi(res[83], a[20], a[62]); // Sum(82) res[83] = fma52lo(res[83], a[21], a[62]); // Sum(83) res[84] = fma52hi(res[84], a[21], a[62]); // Sum(83) res[72] = fma52lo(res[72], a[9], a[63]); // Sum(72) res[73] = fma52hi(res[73], a[9], a[63]); // Sum(72) res[73] = fma52lo(res[73], a[10], a[63]); // Sum(73) res[74] = fma52hi(res[74], a[10], a[63]); // Sum(73) res[74] = fma52lo(res[74], a[11], a[63]); // Sum(74) res[75] = fma52hi(res[75], a[11], a[63]); // Sum(74) res[75] = fma52lo(res[75], a[12], a[63]); // Sum(75) res[76] = fma52hi(res[76], a[12], a[63]); // Sum(75) res[76] = fma52lo(res[76], a[13], a[63]); // Sum(76) res[77] = fma52hi(res[77], a[13], a[63]); // Sum(76) res[77] = fma52lo(res[77], a[14], a[63]); // Sum(77) res[78] = fma52hi(res[78], a[14], a[63]); // Sum(77) res[78] = fma52lo(res[78], a[15], a[63]); // Sum(78) res[79] = fma52hi(res[79], a[15], a[63]); // Sum(78) res[79] = fma52lo(res[79], a[16], a[63]); // Sum(79) res[80] = fma52hi(res[80], a[16], a[63]); // Sum(79) res[80] = fma52lo(res[80], a[17], a[63]); // Sum(80) res[81] = fma52hi(res[81], a[17], a[63]); // Sum(80) res[81] = fma52lo(res[81], a[18], a[63]); // Sum(81) res[82] = fma52hi(res[82], a[18], a[63]); // Sum(81) res[82] = fma52lo(res[82], a[19], a[63]); // Sum(82) res[83] = fma52hi(res[83], a[19], a[63]); // Sum(82) res[83] = fma52lo(res[83], a[20], a[63]); // Sum(83) res[84] = fma52hi(res[84], a[20], a[63]); // Sum(83) res[72] = fma52lo(res[72], a[8], a[64]); // Sum(72) res[73] = fma52hi(res[73], a[8], a[64]); // Sum(72) res[73] = fma52lo(res[73], a[9], a[64]); // Sum(73) res[74] = fma52hi(res[74], a[9], a[64]); // Sum(73) res[74] = fma52lo(res[74], a[10], a[64]); // Sum(74) res[75] = fma52hi(res[75], a[10], a[64]); // Sum(74) res[75] = fma52lo(res[75], a[11], a[64]); // Sum(75) res[76] = fma52hi(res[76], a[11], a[64]); // Sum(75) res[76] = fma52lo(res[76], a[12], a[64]); // Sum(76) res[77] = fma52hi(res[77], a[12], a[64]); // Sum(76) res[77] = fma52lo(res[77], a[13], a[64]); // Sum(77) res[78] = fma52hi(res[78], a[13], a[64]); // Sum(77) res[78] = fma52lo(res[78], a[14], a[64]); // Sum(78) res[79] = fma52hi(res[79], a[14], a[64]); // Sum(78) res[79] = fma52lo(res[79], a[15], a[64]); // Sum(79) res[80] = fma52hi(res[80], a[15], a[64]); // Sum(79) res[80] = fma52lo(res[80], a[16], a[64]); // Sum(80) res[81] = fma52hi(res[81], a[16], a[64]); // Sum(80) res[81] = fma52lo(res[81], a[17], a[64]); // Sum(81) res[82] = fma52hi(res[82], a[17], a[64]); // Sum(81) res[82] = fma52lo(res[82], a[18], a[64]); // Sum(82) res[83] = fma52hi(res[83], a[18], a[64]); // Sum(82) res[83] = fma52lo(res[83], a[19], a[64]); // Sum(83) res[84] = fma52hi(res[84], a[19], a[64]); // Sum(83) res[72] = fma52lo(res[72], a[7], a[65]); // Sum(72) res[73] = fma52hi(res[73], a[7], a[65]); // Sum(72) res[73] = fma52lo(res[73], a[8], a[65]); // Sum(73) res[74] = fma52hi(res[74], a[8], a[65]); // Sum(73) res[74] = fma52lo(res[74], a[9], a[65]); // Sum(74) res[75] = fma52hi(res[75], a[9], a[65]); // Sum(74) res[75] = fma52lo(res[75], a[10], a[65]); // Sum(75) res[76] = fma52hi(res[76], a[10], a[65]); // Sum(75) res[76] = fma52lo(res[76], a[11], a[65]); // Sum(76) res[77] = fma52hi(res[77], a[11], a[65]); // Sum(76) res[77] = fma52lo(res[77], a[12], a[65]); // Sum(77) res[78] = fma52hi(res[78], a[12], a[65]); // Sum(77) res[78] = fma52lo(res[78], a[13], a[65]); // Sum(78) res[79] = fma52hi(res[79], a[13], a[65]); // Sum(78) res[79] = fma52lo(res[79], a[14], a[65]); // Sum(79) res[80] = fma52hi(res[80], a[14], a[65]); // Sum(79) res[80] = fma52lo(res[80], a[15], a[65]); // Sum(80) res[81] = fma52hi(res[81], a[15], a[65]); // Sum(80) res[81] = fma52lo(res[81], a[16], a[65]); // Sum(81) res[82] = fma52hi(res[82], a[16], a[65]); // Sum(81) res[82] = fma52lo(res[82], a[17], a[65]); // Sum(82) res[83] = fma52hi(res[83], a[17], a[65]); // Sum(82) res[83] = fma52lo(res[83], a[18], a[65]); // Sum(83) res[84] = fma52hi(res[84], a[18], a[65]); // Sum(83) res[72] = fma52lo(res[72], a[6], a[66]); // Sum(72) res[73] = fma52hi(res[73], a[6], a[66]); // Sum(72) res[73] = fma52lo(res[73], a[7], a[66]); // Sum(73) res[74] = fma52hi(res[74], a[7], a[66]); // Sum(73) res[74] = fma52lo(res[74], a[8], a[66]); // Sum(74) res[75] = fma52hi(res[75], a[8], a[66]); // Sum(74) res[75] = fma52lo(res[75], a[9], a[66]); // Sum(75) res[76] = fma52hi(res[76], a[9], a[66]); // Sum(75) res[76] = fma52lo(res[76], a[10], a[66]); // Sum(76) res[77] = fma52hi(res[77], a[10], a[66]); // Sum(76) res[77] = fma52lo(res[77], a[11], a[66]); // Sum(77) res[78] = fma52hi(res[78], a[11], a[66]); // Sum(77) res[78] = fma52lo(res[78], a[12], a[66]); // Sum(78) res[79] = fma52hi(res[79], a[12], a[66]); // Sum(78) res[79] = fma52lo(res[79], a[13], a[66]); // Sum(79) res[80] = fma52hi(res[80], a[13], a[66]); // Sum(79) res[80] = fma52lo(res[80], a[14], a[66]); // Sum(80) res[81] = fma52hi(res[81], a[14], a[66]); // Sum(80) res[81] = fma52lo(res[81], a[15], a[66]); // Sum(81) res[82] = fma52hi(res[82], a[15], a[66]); // Sum(81) res[82] = fma52lo(res[82], a[16], a[66]); // Sum(82) res[83] = fma52hi(res[83], a[16], a[66]); // Sum(82) res[83] = fma52lo(res[83], a[17], a[66]); // Sum(83) res[84] = fma52hi(res[84], a[17], a[66]); // Sum(83) res[72] = fma52lo(res[72], a[5], a[67]); // Sum(72) res[73] = fma52hi(res[73], a[5], a[67]); // Sum(72) res[73] = fma52lo(res[73], a[6], a[67]); // Sum(73) res[74] = fma52hi(res[74], a[6], a[67]); // Sum(73) res[74] = fma52lo(res[74], a[7], a[67]); // Sum(74) res[75] = fma52hi(res[75], a[7], a[67]); // Sum(74) res[75] = fma52lo(res[75], a[8], a[67]); // Sum(75) res[76] = fma52hi(res[76], a[8], a[67]); // Sum(75) res[76] = fma52lo(res[76], a[9], a[67]); // Sum(76) res[77] = fma52hi(res[77], a[9], a[67]); // Sum(76) res[77] = fma52lo(res[77], a[10], a[67]); // Sum(77) res[78] = fma52hi(res[78], a[10], a[67]); // Sum(77) res[78] = fma52lo(res[78], a[11], a[67]); // Sum(78) res[79] = fma52hi(res[79], a[11], a[67]); // Sum(78) res[79] = fma52lo(res[79], a[12], a[67]); // Sum(79) res[80] = fma52hi(res[80], a[12], a[67]); // Sum(79) res[80] = fma52lo(res[80], a[13], a[67]); // Sum(80) res[81] = fma52hi(res[81], a[13], a[67]); // Sum(80) res[81] = fma52lo(res[81], a[14], a[67]); // Sum(81) res[82] = fma52hi(res[82], a[14], a[67]); // Sum(81) res[82] = fma52lo(res[82], a[15], a[67]); // Sum(82) res[83] = fma52hi(res[83], a[15], a[67]); // Sum(82) res[83] = fma52lo(res[83], a[16], a[67]); // Sum(83) res[84] = fma52hi(res[84], a[16], a[67]); // Sum(83) res[72] = fma52lo(res[72], a[4], a[68]); // Sum(72) res[73] = fma52hi(res[73], a[4], a[68]); // Sum(72) res[73] = fma52lo(res[73], a[5], a[68]); // Sum(73) res[74] = fma52hi(res[74], a[5], a[68]); // Sum(73) res[74] = fma52lo(res[74], a[6], a[68]); // Sum(74) res[75] = fma52hi(res[75], a[6], a[68]); // Sum(74) res[75] = fma52lo(res[75], a[7], a[68]); // Sum(75) res[76] = fma52hi(res[76], a[7], a[68]); // Sum(75) res[76] = fma52lo(res[76], a[8], a[68]); // Sum(76) res[77] = fma52hi(res[77], a[8], a[68]); // Sum(76) res[77] = fma52lo(res[77], a[9], a[68]); // Sum(77) res[78] = fma52hi(res[78], a[9], a[68]); // Sum(77) res[78] = fma52lo(res[78], a[10], a[68]); // Sum(78) res[79] = fma52hi(res[79], a[10], a[68]); // Sum(78) res[79] = fma52lo(res[79], a[11], a[68]); // Sum(79) res[80] = fma52hi(res[80], a[11], a[68]); // Sum(79) res[80] = fma52lo(res[80], a[12], a[68]); // Sum(80) res[81] = fma52hi(res[81], a[12], a[68]); // Sum(80) res[81] = fma52lo(res[81], a[13], a[68]); // Sum(81) res[82] = fma52hi(res[82], a[13], a[68]); // Sum(81) res[82] = fma52lo(res[82], a[14], a[68]); // Sum(82) res[83] = fma52hi(res[83], a[14], a[68]); // Sum(82) res[83] = fma52lo(res[83], a[15], a[68]); // Sum(83) res[84] = fma52hi(res[84], a[15], a[68]); // Sum(83) res[72] = fma52lo(res[72], a[3], a[69]); // Sum(72) res[73] = fma52hi(res[73], a[3], a[69]); // Sum(72) res[73] = fma52lo(res[73], a[4], a[69]); // Sum(73) res[74] = fma52hi(res[74], a[4], a[69]); // Sum(73) res[74] = fma52lo(res[74], a[5], a[69]); // Sum(74) res[75] = fma52hi(res[75], a[5], a[69]); // Sum(74) res[75] = fma52lo(res[75], a[6], a[69]); // Sum(75) res[76] = fma52hi(res[76], a[6], a[69]); // Sum(75) res[76] = fma52lo(res[76], a[7], a[69]); // Sum(76) res[77] = fma52hi(res[77], a[7], a[69]); // Sum(76) res[77] = fma52lo(res[77], a[8], a[69]); // Sum(77) res[78] = fma52hi(res[78], a[8], a[69]); // Sum(77) res[78] = fma52lo(res[78], a[9], a[69]); // Sum(78) res[79] = fma52hi(res[79], a[9], a[69]); // Sum(78) res[79] = fma52lo(res[79], a[10], a[69]); // Sum(79) res[80] = fma52hi(res[80], a[10], a[69]); // Sum(79) res[80] = fma52lo(res[80], a[11], a[69]); // Sum(80) res[81] = fma52hi(res[81], a[11], a[69]); // Sum(80) res[81] = fma52lo(res[81], a[12], a[69]); // Sum(81) res[82] = fma52hi(res[82], a[12], a[69]); // Sum(81) res[82] = fma52lo(res[82], a[13], a[69]); // Sum(82) res[83] = fma52hi(res[83], a[13], a[69]); // Sum(82) res[83] = fma52lo(res[83], a[14], a[69]); // Sum(83) res[84] = fma52hi(res[84], a[14], a[69]); // Sum(83) res[72] = fma52lo(res[72], a[2], a[70]); // Sum(72) res[73] = fma52hi(res[73], a[2], a[70]); // Sum(72) res[73] = fma52lo(res[73], a[3], a[70]); // Sum(73) res[74] = fma52hi(res[74], a[3], a[70]); // Sum(73) res[74] = fma52lo(res[74], a[4], a[70]); // Sum(74) res[75] = fma52hi(res[75], a[4], a[70]); // Sum(74) res[75] = fma52lo(res[75], a[5], a[70]); // Sum(75) res[76] = fma52hi(res[76], a[5], a[70]); // Sum(75) res[76] = fma52lo(res[76], a[6], a[70]); // Sum(76) res[77] = fma52hi(res[77], a[6], a[70]); // Sum(76) res[77] = fma52lo(res[77], a[7], a[70]); // Sum(77) res[78] = fma52hi(res[78], a[7], a[70]); // Sum(77) res[78] = fma52lo(res[78], a[8], a[70]); // Sum(78) res[79] = fma52hi(res[79], a[8], a[70]); // Sum(78) res[79] = fma52lo(res[79], a[9], a[70]); // Sum(79) res[80] = fma52hi(res[80], a[9], a[70]); // Sum(79) res[80] = fma52lo(res[80], a[10], a[70]); // Sum(80) res[81] = fma52hi(res[81], a[10], a[70]); // Sum(80) res[81] = fma52lo(res[81], a[11], a[70]); // Sum(81) res[82] = fma52hi(res[82], a[11], a[70]); // Sum(81) res[82] = fma52lo(res[82], a[12], a[70]); // Sum(82) res[83] = fma52hi(res[83], a[12], a[70]); // Sum(82) res[83] = fma52lo(res[83], a[13], a[70]); // Sum(83) res[84] = fma52hi(res[84], a[13], a[70]); // Sum(83) res[72] = fma52lo(res[72], a[1], a[71]); // Sum(72) res[73] = fma52hi(res[73], a[1], a[71]); // Sum(72) res[73] = fma52lo(res[73], a[2], a[71]); // Sum(73) res[74] = fma52hi(res[74], a[2], a[71]); // Sum(73) res[74] = fma52lo(res[74], a[3], a[71]); // Sum(74) res[75] = fma52hi(res[75], a[3], a[71]); // Sum(74) res[75] = fma52lo(res[75], a[4], a[71]); // Sum(75) res[76] = fma52hi(res[76], a[4], a[71]); // Sum(75) res[76] = fma52lo(res[76], a[5], a[71]); // Sum(76) res[77] = fma52hi(res[77], a[5], a[71]); // Sum(76) res[77] = fma52lo(res[77], a[6], a[71]); // Sum(77) res[78] = fma52hi(res[78], a[6], a[71]); // Sum(77) res[78] = fma52lo(res[78], a[7], a[71]); // Sum(78) res[79] = fma52hi(res[79], a[7], a[71]); // Sum(78) res[79] = fma52lo(res[79], a[8], a[71]); // Sum(79) res[80] = fma52hi(res[80], a[8], a[71]); // Sum(79) res[80] = fma52lo(res[80], a[9], a[71]); // Sum(80) res[81] = fma52hi(res[81], a[9], a[71]); // Sum(80) res[81] = fma52lo(res[81], a[10], a[71]); // Sum(81) res[82] = fma52hi(res[82], a[10], a[71]); // Sum(81) res[82] = fma52lo(res[82], a[11], a[71]); // Sum(82) res[83] = fma52hi(res[83], a[11], a[71]); // Sum(82) res[83] = fma52lo(res[83], a[12], a[71]); // Sum(83) res[84] = fma52hi(res[84], a[12], a[71]); // Sum(83) res[72] = fma52lo(res[72], a[0], a[72]); // Sum(72) res[73] = fma52hi(res[73], a[0], a[72]); // Sum(72) res[73] = fma52lo(res[73], a[1], a[72]); // Sum(73) res[74] = fma52hi(res[74], a[1], a[72]); // Sum(73) res[74] = fma52lo(res[74], a[2], a[72]); // Sum(74) res[75] = fma52hi(res[75], a[2], a[72]); // Sum(74) res[75] = fma52lo(res[75], a[3], a[72]); // Sum(75) res[76] = fma52hi(res[76], a[3], a[72]); // Sum(75) res[76] = fma52lo(res[76], a[4], a[72]); // Sum(76) res[77] = fma52hi(res[77], a[4], a[72]); // Sum(76) res[77] = fma52lo(res[77], a[5], a[72]); // Sum(77) res[78] = fma52hi(res[78], a[5], a[72]); // Sum(77) res[78] = fma52lo(res[78], a[6], a[72]); // Sum(78) res[79] = fma52hi(res[79], a[6], a[72]); // Sum(78) res[79] = fma52lo(res[79], a[7], a[72]); // Sum(79) res[80] = fma52hi(res[80], a[7], a[72]); // Sum(79) res[80] = fma52lo(res[80], a[8], a[72]); // Sum(80) res[81] = fma52hi(res[81], a[8], a[72]); // Sum(80) res[81] = fma52lo(res[81], a[9], a[72]); // Sum(81) res[82] = fma52hi(res[82], a[9], a[72]); // Sum(81) res[82] = fma52lo(res[82], a[10], a[72]); // Sum(82) res[83] = fma52hi(res[83], a[10], a[72]); // Sum(82) res[83] = fma52lo(res[83], a[11], a[72]); // Sum(83) res[84] = fma52hi(res[84], a[11], a[72]); // Sum(83) res[73] = fma52lo(res[73], a[0], a[73]); // Sum(73) res[74] = fma52hi(res[74], a[0], a[73]); // Sum(73) res[74] = fma52lo(res[74], a[1], a[73]); // Sum(74) res[75] = fma52hi(res[75], a[1], a[73]); // Sum(74) res[75] = fma52lo(res[75], a[2], a[73]); // Sum(75) res[76] = fma52hi(res[76], a[2], a[73]); // Sum(75) res[76] = fma52lo(res[76], a[3], a[73]); // Sum(76) res[77] = fma52hi(res[77], a[3], a[73]); // Sum(76) res[77] = fma52lo(res[77], a[4], a[73]); // Sum(77) res[78] = fma52hi(res[78], a[4], a[73]); // Sum(77) res[78] = fma52lo(res[78], a[5], a[73]); // Sum(78) res[79] = fma52hi(res[79], a[5], a[73]); // Sum(78) res[79] = fma52lo(res[79], a[6], a[73]); // Sum(79) res[80] = fma52hi(res[80], a[6], a[73]); // Sum(79) res[80] = fma52lo(res[80], a[7], a[73]); // Sum(80) res[81] = fma52hi(res[81], a[7], a[73]); // Sum(80) res[81] = fma52lo(res[81], a[8], a[73]); // Sum(81) res[82] = fma52hi(res[82], a[8], a[73]); // Sum(81) res[82] = fma52lo(res[82], a[9], a[73]); // Sum(82) res[83] = fma52hi(res[83], a[9], a[73]); // Sum(82) res[83] = fma52lo(res[83], a[10], a[73]); // Sum(83) res[84] = fma52hi(res[84], a[10], a[73]); // Sum(83) res[74] = fma52lo(res[74], a[0], a[74]); // Sum(74) res[75] = fma52hi(res[75], a[0], a[74]); // Sum(74) res[75] = fma52lo(res[75], a[1], a[74]); // Sum(75) res[76] = fma52hi(res[76], a[1], a[74]); // Sum(75) res[76] = fma52lo(res[76], a[2], a[74]); // Sum(76) res[77] = fma52hi(res[77], a[2], a[74]); // Sum(76) res[77] = fma52lo(res[77], a[3], a[74]); // Sum(77) res[78] = fma52hi(res[78], a[3], a[74]); // Sum(77) res[78] = fma52lo(res[78], a[4], a[74]); // Sum(78) res[79] = fma52hi(res[79], a[4], a[74]); // Sum(78) res[79] = fma52lo(res[79], a[5], a[74]); // Sum(79) res[80] = fma52hi(res[80], a[5], a[74]); // Sum(79) res[80] = fma52lo(res[80], a[6], a[74]); // Sum(80) res[81] = fma52hi(res[81], a[6], a[74]); // Sum(80) res[81] = fma52lo(res[81], a[7], a[74]); // Sum(81) res[82] = fma52hi(res[82], a[7], a[74]); // Sum(81) res[82] = fma52lo(res[82], a[8], a[74]); // Sum(82) res[83] = fma52hi(res[83], a[8], a[74]); // Sum(82) res[83] = fma52lo(res[83], a[9], a[74]); // Sum(83) res[84] = fma52hi(res[84], a[9], a[74]); // Sum(83) res[75] = fma52lo(res[75], a[0], a[75]); // Sum(75) res[76] = fma52hi(res[76], a[0], a[75]); // Sum(75) res[76] = fma52lo(res[76], a[1], a[75]); // Sum(76) res[77] = fma52hi(res[77], a[1], a[75]); // Sum(76) res[77] = fma52lo(res[77], a[2], a[75]); // Sum(77) res[78] = fma52hi(res[78], a[2], a[75]); // Sum(77) res[78] = fma52lo(res[78], a[3], a[75]); // Sum(78) res[79] = fma52hi(res[79], a[3], a[75]); // Sum(78) res[79] = fma52lo(res[79], a[4], a[75]); // Sum(79) res[80] = fma52hi(res[80], a[4], a[75]); // Sum(79) res[80] = fma52lo(res[80], a[5], a[75]); // Sum(80) res[81] = fma52hi(res[81], a[5], a[75]); // Sum(80) res[81] = fma52lo(res[81], a[6], a[75]); // Sum(81) res[82] = fma52hi(res[82], a[6], a[75]); // Sum(81) res[82] = fma52lo(res[82], a[7], a[75]); // Sum(82) res[83] = fma52hi(res[83], a[7], a[75]); // Sum(82) res[83] = fma52lo(res[83], a[8], a[75]); // Sum(83) res[84] = fma52hi(res[84], a[8], a[75]); // Sum(83) res[76] = fma52lo(res[76], a[0], a[76]); // Sum(76) res[77] = fma52hi(res[77], a[0], a[76]); // Sum(76) res[77] = fma52lo(res[77], a[1], a[76]); // Sum(77) res[78] = fma52hi(res[78], a[1], a[76]); // Sum(77) res[78] = fma52lo(res[78], a[2], a[76]); // Sum(78) res[79] = fma52hi(res[79], a[2], a[76]); // Sum(78) res[79] = fma52lo(res[79], a[3], a[76]); // Sum(79) res[80] = fma52hi(res[80], a[3], a[76]); // Sum(79) res[80] = fma52lo(res[80], a[4], a[76]); // Sum(80) res[81] = fma52hi(res[81], a[4], a[76]); // Sum(80) res[81] = fma52lo(res[81], a[5], a[76]); // Sum(81) res[82] = fma52hi(res[82], a[5], a[76]); // Sum(81) res[82] = fma52lo(res[82], a[6], a[76]); // Sum(82) res[83] = fma52hi(res[83], a[6], a[76]); // Sum(82) res[83] = fma52lo(res[83], a[7], a[76]); // Sum(83) res[84] = fma52hi(res[84], a[7], a[76]); // Sum(83) res[77] = fma52lo(res[77], a[0], a[77]); // Sum(77) res[78] = fma52hi(res[78], a[0], a[77]); // Sum(77) res[78] = fma52lo(res[78], a[1], a[77]); // Sum(78) res[79] = fma52hi(res[79], a[1], a[77]); // Sum(78) res[79] = fma52lo(res[79], a[2], a[77]); // Sum(79) res[80] = fma52hi(res[80], a[2], a[77]); // Sum(79) res[80] = fma52lo(res[80], a[3], a[77]); // Sum(80) res[81] = fma52hi(res[81], a[3], a[77]); // Sum(80) res[81] = fma52lo(res[81], a[4], a[77]); // Sum(81) res[82] = fma52hi(res[82], a[4], a[77]); // Sum(81) res[82] = fma52lo(res[82], a[5], a[77]); // Sum(82) res[83] = fma52hi(res[83], a[5], a[77]); // Sum(82) res[83] = fma52lo(res[83], a[6], a[77]); // Sum(83) res[84] = fma52hi(res[84], a[6], a[77]); // Sum(83) res[78] = fma52lo(res[78], a[0], a[78]); // Sum(78) res[79] = fma52hi(res[79], a[0], a[78]); // Sum(78) res[79] = fma52lo(res[79], a[1], a[78]); // Sum(79) res[80] = fma52hi(res[80], a[1], a[78]); // Sum(79) res[80] = fma52lo(res[80], a[2], a[78]); // Sum(80) res[81] = fma52hi(res[81], a[2], a[78]); // Sum(80) res[81] = fma52lo(res[81], a[3], a[78]); // Sum(81) res[82] = fma52hi(res[82], a[3], a[78]); // Sum(81) res[82] = fma52lo(res[82], a[4], a[78]); // Sum(82) res[83] = fma52hi(res[83], a[4], a[78]); // Sum(82) res[83] = fma52lo(res[83], a[5], a[78]); // Sum(83) res[84] = fma52hi(res[84], a[5], a[78]); // Sum(83) res[72] = add64(res[72], res[72]); // Double(72) res[73] = add64(res[73], res[73]); // Double(73) res[74] = add64(res[74], res[74]); // Double(74) res[75] = add64(res[75], res[75]); // Double(75) res[76] = add64(res[76], res[76]); // Double(76) res[77] = add64(res[77], res[77]); // Double(77) res[78] = add64(res[78], res[78]); // Double(78) res[79] = add64(res[79], res[79]); // Double(79) res[80] = add64(res[80], res[80]); // Double(80) res[81] = add64(res[81], res[81]); // Double(81) res[82] = add64(res[82], res[82]); // Double(82) res[83] = add64(res[83], res[83]); // Double(83) res[72] = fma52lo(res[72], a[36], a[36]); // Add sqr(72) res[73] = fma52hi(res[73], a[36], a[36]); // Add sqr(72) res[74] = fma52lo(res[74], a[37], a[37]); // Add sqr(74) res[75] = fma52hi(res[75], a[37], a[37]); // Add sqr(74) res[76] = fma52lo(res[76], a[38], a[38]); // Add sqr(76) res[77] = fma52hi(res[77], a[38], a[38]); // Add sqr(76) res[78] = fma52lo(res[78], a[39], a[39]); // Add sqr(78) res[79] = fma52hi(res[79], a[39], a[39]); // Add sqr(78) res[80] = fma52lo(res[80], a[40], a[40]); // Add sqr(80) res[81] = fma52hi(res[81], a[40], a[40]); // Add sqr(80) res[82] = fma52lo(res[82], a[41], a[41]); // Add sqr(82) res[83] = fma52hi(res[83], a[41], a[41]); // Add sqr(82) res[84] = fma52lo(res[84], a[41], a[43]); // Sum(84) res[85] = fma52hi(res[85], a[41], a[43]); // Sum(84) res[85] = fma52lo(res[85], a[42], a[43]); // Sum(85) res[86] = fma52hi(res[86], a[42], a[43]); // Sum(85) res[84] = fma52lo(res[84], a[40], a[44]); // Sum(84) res[85] = fma52hi(res[85], a[40], a[44]); // Sum(84) res[85] = fma52lo(res[85], a[41], a[44]); // Sum(85) res[86] = fma52hi(res[86], a[41], a[44]); // Sum(85) res[86] = fma52lo(res[86], a[42], a[44]); // Sum(86) res[87] = fma52hi(res[87], a[42], a[44]); // Sum(86) res[87] = fma52lo(res[87], a[43], a[44]); // Sum(87) res[88] = fma52hi(res[88], a[43], a[44]); // Sum(87) res[84] = fma52lo(res[84], a[39], a[45]); // Sum(84) res[85] = fma52hi(res[85], a[39], a[45]); // Sum(84) res[85] = fma52lo(res[85], a[40], a[45]); // Sum(85) res[86] = fma52hi(res[86], a[40], a[45]); // Sum(85) res[86] = fma52lo(res[86], a[41], a[45]); // Sum(86) res[87] = fma52hi(res[87], a[41], a[45]); // Sum(86) res[87] = fma52lo(res[87], a[42], a[45]); // Sum(87) res[88] = fma52hi(res[88], a[42], a[45]); // Sum(87) res[88] = fma52lo(res[88], a[43], a[45]); // Sum(88) res[89] = fma52hi(res[89], a[43], a[45]); // Sum(88) res[89] = fma52lo(res[89], a[44], a[45]); // Sum(89) res[90] = fma52hi(res[90], a[44], a[45]); // Sum(89) res[84] = fma52lo(res[84], a[38], a[46]); // Sum(84) res[85] = fma52hi(res[85], a[38], a[46]); // Sum(84) res[85] = fma52lo(res[85], a[39], a[46]); // Sum(85) res[86] = fma52hi(res[86], a[39], a[46]); // Sum(85) res[86] = fma52lo(res[86], a[40], a[46]); // Sum(86) res[87] = fma52hi(res[87], a[40], a[46]); // Sum(86) res[87] = fma52lo(res[87], a[41], a[46]); // Sum(87) res[88] = fma52hi(res[88], a[41], a[46]); // Sum(87) res[88] = fma52lo(res[88], a[42], a[46]); // Sum(88) res[89] = fma52hi(res[89], a[42], a[46]); // Sum(88) res[89] = fma52lo(res[89], a[43], a[46]); // Sum(89) res[90] = fma52hi(res[90], a[43], a[46]); // Sum(89) res[90] = fma52lo(res[90], a[44], a[46]); // Sum(90) res[91] = fma52hi(res[91], a[44], a[46]); // Sum(90) res[91] = fma52lo(res[91], a[45], a[46]); // Sum(91) res[92] = fma52hi(res[92], a[45], a[46]); // Sum(91) res[84] = fma52lo(res[84], a[37], a[47]); // Sum(84) res[85] = fma52hi(res[85], a[37], a[47]); // Sum(84) res[85] = fma52lo(res[85], a[38], a[47]); // Sum(85) res[86] = fma52hi(res[86], a[38], a[47]); // Sum(85) res[86] = fma52lo(res[86], a[39], a[47]); // Sum(86) res[87] = fma52hi(res[87], a[39], a[47]); // Sum(86) res[87] = fma52lo(res[87], a[40], a[47]); // Sum(87) res[88] = fma52hi(res[88], a[40], a[47]); // Sum(87) res[88] = fma52lo(res[88], a[41], a[47]); // Sum(88) res[89] = fma52hi(res[89], a[41], a[47]); // Sum(88) res[89] = fma52lo(res[89], a[42], a[47]); // Sum(89) res[90] = fma52hi(res[90], a[42], a[47]); // Sum(89) res[90] = fma52lo(res[90], a[43], a[47]); // Sum(90) res[91] = fma52hi(res[91], a[43], a[47]); // Sum(90) res[91] = fma52lo(res[91], a[44], a[47]); // Sum(91) res[92] = fma52hi(res[92], a[44], a[47]); // Sum(91) res[92] = fma52lo(res[92], a[45], a[47]); // Sum(92) res[93] = fma52hi(res[93], a[45], a[47]); // Sum(92) res[93] = fma52lo(res[93], a[46], a[47]); // Sum(93) res[94] = fma52hi(res[94], a[46], a[47]); // Sum(93) res[84] = fma52lo(res[84], a[36], a[48]); // Sum(84) res[85] = fma52hi(res[85], a[36], a[48]); // Sum(84) res[85] = fma52lo(res[85], a[37], a[48]); // Sum(85) res[86] = fma52hi(res[86], a[37], a[48]); // Sum(85) res[86] = fma52lo(res[86], a[38], a[48]); // Sum(86) res[87] = fma52hi(res[87], a[38], a[48]); // Sum(86) res[87] = fma52lo(res[87], a[39], a[48]); // Sum(87) res[88] = fma52hi(res[88], a[39], a[48]); // Sum(87) res[88] = fma52lo(res[88], a[40], a[48]); // Sum(88) res[89] = fma52hi(res[89], a[40], a[48]); // Sum(88) res[89] = fma52lo(res[89], a[41], a[48]); // Sum(89) res[90] = fma52hi(res[90], a[41], a[48]); // Sum(89) res[90] = fma52lo(res[90], a[42], a[48]); // Sum(90) res[91] = fma52hi(res[91], a[42], a[48]); // Sum(90) res[91] = fma52lo(res[91], a[43], a[48]); // Sum(91) res[92] = fma52hi(res[92], a[43], a[48]); // Sum(91) res[92] = fma52lo(res[92], a[44], a[48]); // Sum(92) res[93] = fma52hi(res[93], a[44], a[48]); // Sum(92) res[93] = fma52lo(res[93], a[45], a[48]); // Sum(93) res[94] = fma52hi(res[94], a[45], a[48]); // Sum(93) res[94] = fma52lo(res[94], a[46], a[48]); // Sum(94) res[95] = fma52hi(res[95], a[46], a[48]); // Sum(94) res[95] = fma52lo(res[95], a[47], a[48]); // Sum(95) res[96] = fma52hi(res[96], a[47], a[48]); // Sum(95) res[84] = fma52lo(res[84], a[35], a[49]); // Sum(84) res[85] = fma52hi(res[85], a[35], a[49]); // Sum(84) res[85] = fma52lo(res[85], a[36], a[49]); // Sum(85) res[86] = fma52hi(res[86], a[36], a[49]); // Sum(85) res[86] = fma52lo(res[86], a[37], a[49]); // Sum(86) res[87] = fma52hi(res[87], a[37], a[49]); // Sum(86) res[87] = fma52lo(res[87], a[38], a[49]); // Sum(87) res[88] = fma52hi(res[88], a[38], a[49]); // Sum(87) res[88] = fma52lo(res[88], a[39], a[49]); // Sum(88) res[89] = fma52hi(res[89], a[39], a[49]); // Sum(88) res[89] = fma52lo(res[89], a[40], a[49]); // Sum(89) res[90] = fma52hi(res[90], a[40], a[49]); // Sum(89) res[90] = fma52lo(res[90], a[41], a[49]); // Sum(90) res[91] = fma52hi(res[91], a[41], a[49]); // Sum(90) res[91] = fma52lo(res[91], a[42], a[49]); // Sum(91) res[92] = fma52hi(res[92], a[42], a[49]); // Sum(91) res[92] = fma52lo(res[92], a[43], a[49]); // Sum(92) res[93] = fma52hi(res[93], a[43], a[49]); // Sum(92) res[93] = fma52lo(res[93], a[44], a[49]); // Sum(93) res[94] = fma52hi(res[94], a[44], a[49]); // Sum(93) res[94] = fma52lo(res[94], a[45], a[49]); // Sum(94) res[95] = fma52hi(res[95], a[45], a[49]); // Sum(94) res[95] = fma52lo(res[95], a[46], a[49]); // Sum(95) res[96] = fma52hi(res[96], a[46], a[49]); // Sum(95) res[84] = fma52lo(res[84], a[34], a[50]); // Sum(84) res[85] = fma52hi(res[85], a[34], a[50]); // Sum(84) res[85] = fma52lo(res[85], a[35], a[50]); // Sum(85) res[86] = fma52hi(res[86], a[35], a[50]); // Sum(85) res[86] = fma52lo(res[86], a[36], a[50]); // Sum(86) res[87] = fma52hi(res[87], a[36], a[50]); // Sum(86) res[87] = fma52lo(res[87], a[37], a[50]); // Sum(87) res[88] = fma52hi(res[88], a[37], a[50]); // Sum(87) res[88] = fma52lo(res[88], a[38], a[50]); // Sum(88) res[89] = fma52hi(res[89], a[38], a[50]); // Sum(88) res[89] = fma52lo(res[89], a[39], a[50]); // Sum(89) res[90] = fma52hi(res[90], a[39], a[50]); // Sum(89) res[90] = fma52lo(res[90], a[40], a[50]); // Sum(90) res[91] = fma52hi(res[91], a[40], a[50]); // Sum(90) res[91] = fma52lo(res[91], a[41], a[50]); // Sum(91) res[92] = fma52hi(res[92], a[41], a[50]); // Sum(91) res[92] = fma52lo(res[92], a[42], a[50]); // Sum(92) res[93] = fma52hi(res[93], a[42], a[50]); // Sum(92) res[93] = fma52lo(res[93], a[43], a[50]); // Sum(93) res[94] = fma52hi(res[94], a[43], a[50]); // Sum(93) res[94] = fma52lo(res[94], a[44], a[50]); // Sum(94) res[95] = fma52hi(res[95], a[44], a[50]); // Sum(94) res[95] = fma52lo(res[95], a[45], a[50]); // Sum(95) res[96] = fma52hi(res[96], a[45], a[50]); // Sum(95) res[84] = fma52lo(res[84], a[33], a[51]); // Sum(84) res[85] = fma52hi(res[85], a[33], a[51]); // Sum(84) res[85] = fma52lo(res[85], a[34], a[51]); // Sum(85) res[86] = fma52hi(res[86], a[34], a[51]); // Sum(85) res[86] = fma52lo(res[86], a[35], a[51]); // Sum(86) res[87] = fma52hi(res[87], a[35], a[51]); // Sum(86) res[87] = fma52lo(res[87], a[36], a[51]); // Sum(87) res[88] = fma52hi(res[88], a[36], a[51]); // Sum(87) res[88] = fma52lo(res[88], a[37], a[51]); // Sum(88) res[89] = fma52hi(res[89], a[37], a[51]); // Sum(88) res[89] = fma52lo(res[89], a[38], a[51]); // Sum(89) res[90] = fma52hi(res[90], a[38], a[51]); // Sum(89) res[90] = fma52lo(res[90], a[39], a[51]); // Sum(90) res[91] = fma52hi(res[91], a[39], a[51]); // Sum(90) res[91] = fma52lo(res[91], a[40], a[51]); // Sum(91) res[92] = fma52hi(res[92], a[40], a[51]); // Sum(91) res[92] = fma52lo(res[92], a[41], a[51]); // Sum(92) res[93] = fma52hi(res[93], a[41], a[51]); // Sum(92) res[93] = fma52lo(res[93], a[42], a[51]); // Sum(93) res[94] = fma52hi(res[94], a[42], a[51]); // Sum(93) res[94] = fma52lo(res[94], a[43], a[51]); // Sum(94) res[95] = fma52hi(res[95], a[43], a[51]); // Sum(94) res[95] = fma52lo(res[95], a[44], a[51]); // Sum(95) res[96] = fma52hi(res[96], a[44], a[51]); // Sum(95) res[84] = fma52lo(res[84], a[32], a[52]); // Sum(84) res[85] = fma52hi(res[85], a[32], a[52]); // Sum(84) res[85] = fma52lo(res[85], a[33], a[52]); // Sum(85) res[86] = fma52hi(res[86], a[33], a[52]); // Sum(85) res[86] = fma52lo(res[86], a[34], a[52]); // Sum(86) res[87] = fma52hi(res[87], a[34], a[52]); // Sum(86) res[87] = fma52lo(res[87], a[35], a[52]); // Sum(87) res[88] = fma52hi(res[88], a[35], a[52]); // Sum(87) res[88] = fma52lo(res[88], a[36], a[52]); // Sum(88) res[89] = fma52hi(res[89], a[36], a[52]); // Sum(88) res[89] = fma52lo(res[89], a[37], a[52]); // Sum(89) res[90] = fma52hi(res[90], a[37], a[52]); // Sum(89) res[90] = fma52lo(res[90], a[38], a[52]); // Sum(90) res[91] = fma52hi(res[91], a[38], a[52]); // Sum(90) res[91] = fma52lo(res[91], a[39], a[52]); // Sum(91) res[92] = fma52hi(res[92], a[39], a[52]); // Sum(91) res[92] = fma52lo(res[92], a[40], a[52]); // Sum(92) res[93] = fma52hi(res[93], a[40], a[52]); // Sum(92) res[93] = fma52lo(res[93], a[41], a[52]); // Sum(93) res[94] = fma52hi(res[94], a[41], a[52]); // Sum(93) res[94] = fma52lo(res[94], a[42], a[52]); // Sum(94) res[95] = fma52hi(res[95], a[42], a[52]); // Sum(94) res[95] = fma52lo(res[95], a[43], a[52]); // Sum(95) res[96] = fma52hi(res[96], a[43], a[52]); // Sum(95) res[84] = fma52lo(res[84], a[31], a[53]); // Sum(84) res[85] = fma52hi(res[85], a[31], a[53]); // Sum(84) res[85] = fma52lo(res[85], a[32], a[53]); // Sum(85) res[86] = fma52hi(res[86], a[32], a[53]); // Sum(85) res[86] = fma52lo(res[86], a[33], a[53]); // Sum(86) res[87] = fma52hi(res[87], a[33], a[53]); // Sum(86) res[87] = fma52lo(res[87], a[34], a[53]); // Sum(87) res[88] = fma52hi(res[88], a[34], a[53]); // Sum(87) res[88] = fma52lo(res[88], a[35], a[53]); // Sum(88) res[89] = fma52hi(res[89], a[35], a[53]); // Sum(88) res[89] = fma52lo(res[89], a[36], a[53]); // Sum(89) res[90] = fma52hi(res[90], a[36], a[53]); // Sum(89) res[90] = fma52lo(res[90], a[37], a[53]); // Sum(90) res[91] = fma52hi(res[91], a[37], a[53]); // Sum(90) res[91] = fma52lo(res[91], a[38], a[53]); // Sum(91) res[92] = fma52hi(res[92], a[38], a[53]); // Sum(91) res[92] = fma52lo(res[92], a[39], a[53]); // Sum(92) res[93] = fma52hi(res[93], a[39], a[53]); // Sum(92) res[93] = fma52lo(res[93], a[40], a[53]); // Sum(93) res[94] = fma52hi(res[94], a[40], a[53]); // Sum(93) res[94] = fma52lo(res[94], a[41], a[53]); // Sum(94) res[95] = fma52hi(res[95], a[41], a[53]); // Sum(94) res[95] = fma52lo(res[95], a[42], a[53]); // Sum(95) res[96] = fma52hi(res[96], a[42], a[53]); // Sum(95) res[84] = fma52lo(res[84], a[30], a[54]); // Sum(84) res[85] = fma52hi(res[85], a[30], a[54]); // Sum(84) res[85] = fma52lo(res[85], a[31], a[54]); // Sum(85) res[86] = fma52hi(res[86], a[31], a[54]); // Sum(85) res[86] = fma52lo(res[86], a[32], a[54]); // Sum(86) res[87] = fma52hi(res[87], a[32], a[54]); // Sum(86) res[87] = fma52lo(res[87], a[33], a[54]); // Sum(87) res[88] = fma52hi(res[88], a[33], a[54]); // Sum(87) res[88] = fma52lo(res[88], a[34], a[54]); // Sum(88) res[89] = fma52hi(res[89], a[34], a[54]); // Sum(88) res[89] = fma52lo(res[89], a[35], a[54]); // Sum(89) res[90] = fma52hi(res[90], a[35], a[54]); // Sum(89) res[90] = fma52lo(res[90], a[36], a[54]); // Sum(90) res[91] = fma52hi(res[91], a[36], a[54]); // Sum(90) res[91] = fma52lo(res[91], a[37], a[54]); // Sum(91) res[92] = fma52hi(res[92], a[37], a[54]); // Sum(91) res[92] = fma52lo(res[92], a[38], a[54]); // Sum(92) res[93] = fma52hi(res[93], a[38], a[54]); // Sum(92) res[93] = fma52lo(res[93], a[39], a[54]); // Sum(93) res[94] = fma52hi(res[94], a[39], a[54]); // Sum(93) res[94] = fma52lo(res[94], a[40], a[54]); // Sum(94) res[95] = fma52hi(res[95], a[40], a[54]); // Sum(94) res[95] = fma52lo(res[95], a[41], a[54]); // Sum(95) res[96] = fma52hi(res[96], a[41], a[54]); // Sum(95) res[84] = fma52lo(res[84], a[29], a[55]); // Sum(84) res[85] = fma52hi(res[85], a[29], a[55]); // Sum(84) res[85] = fma52lo(res[85], a[30], a[55]); // Sum(85) res[86] = fma52hi(res[86], a[30], a[55]); // Sum(85) res[86] = fma52lo(res[86], a[31], a[55]); // Sum(86) res[87] = fma52hi(res[87], a[31], a[55]); // Sum(86) res[87] = fma52lo(res[87], a[32], a[55]); // Sum(87) res[88] = fma52hi(res[88], a[32], a[55]); // Sum(87) res[88] = fma52lo(res[88], a[33], a[55]); // Sum(88) res[89] = fma52hi(res[89], a[33], a[55]); // Sum(88) res[89] = fma52lo(res[89], a[34], a[55]); // Sum(89) res[90] = fma52hi(res[90], a[34], a[55]); // Sum(89) res[90] = fma52lo(res[90], a[35], a[55]); // Sum(90) res[91] = fma52hi(res[91], a[35], a[55]); // Sum(90) res[91] = fma52lo(res[91], a[36], a[55]); // Sum(91) res[92] = fma52hi(res[92], a[36], a[55]); // Sum(91) res[92] = fma52lo(res[92], a[37], a[55]); // Sum(92) res[93] = fma52hi(res[93], a[37], a[55]); // Sum(92) res[93] = fma52lo(res[93], a[38], a[55]); // Sum(93) res[94] = fma52hi(res[94], a[38], a[55]); // Sum(93) res[94] = fma52lo(res[94], a[39], a[55]); // Sum(94) res[95] = fma52hi(res[95], a[39], a[55]); // Sum(94) res[95] = fma52lo(res[95], a[40], a[55]); // Sum(95) res[96] = fma52hi(res[96], a[40], a[55]); // Sum(95) res[84] = fma52lo(res[84], a[28], a[56]); // Sum(84) res[85] = fma52hi(res[85], a[28], a[56]); // Sum(84) res[85] = fma52lo(res[85], a[29], a[56]); // Sum(85) res[86] = fma52hi(res[86], a[29], a[56]); // Sum(85) res[86] = fma52lo(res[86], a[30], a[56]); // Sum(86) res[87] = fma52hi(res[87], a[30], a[56]); // Sum(86) res[87] = fma52lo(res[87], a[31], a[56]); // Sum(87) res[88] = fma52hi(res[88], a[31], a[56]); // Sum(87) res[88] = fma52lo(res[88], a[32], a[56]); // Sum(88) res[89] = fma52hi(res[89], a[32], a[56]); // Sum(88) res[89] = fma52lo(res[89], a[33], a[56]); // Sum(89) res[90] = fma52hi(res[90], a[33], a[56]); // Sum(89) res[90] = fma52lo(res[90], a[34], a[56]); // Sum(90) res[91] = fma52hi(res[91], a[34], a[56]); // Sum(90) res[91] = fma52lo(res[91], a[35], a[56]); // Sum(91) res[92] = fma52hi(res[92], a[35], a[56]); // Sum(91) res[92] = fma52lo(res[92], a[36], a[56]); // Sum(92) res[93] = fma52hi(res[93], a[36], a[56]); // Sum(92) res[93] = fma52lo(res[93], a[37], a[56]); // Sum(93) res[94] = fma52hi(res[94], a[37], a[56]); // Sum(93) res[94] = fma52lo(res[94], a[38], a[56]); // Sum(94) res[95] = fma52hi(res[95], a[38], a[56]); // Sum(94) res[95] = fma52lo(res[95], a[39], a[56]); // Sum(95) res[96] = fma52hi(res[96], a[39], a[56]); // Sum(95) res[84] = fma52lo(res[84], a[27], a[57]); // Sum(84) res[85] = fma52hi(res[85], a[27], a[57]); // Sum(84) res[85] = fma52lo(res[85], a[28], a[57]); // Sum(85) res[86] = fma52hi(res[86], a[28], a[57]); // Sum(85) res[86] = fma52lo(res[86], a[29], a[57]); // Sum(86) res[87] = fma52hi(res[87], a[29], a[57]); // Sum(86) res[87] = fma52lo(res[87], a[30], a[57]); // Sum(87) res[88] = fma52hi(res[88], a[30], a[57]); // Sum(87) res[88] = fma52lo(res[88], a[31], a[57]); // Sum(88) res[89] = fma52hi(res[89], a[31], a[57]); // Sum(88) res[89] = fma52lo(res[89], a[32], a[57]); // Sum(89) res[90] = fma52hi(res[90], a[32], a[57]); // Sum(89) res[90] = fma52lo(res[90], a[33], a[57]); // Sum(90) res[91] = fma52hi(res[91], a[33], a[57]); // Sum(90) res[91] = fma52lo(res[91], a[34], a[57]); // Sum(91) res[92] = fma52hi(res[92], a[34], a[57]); // Sum(91) res[92] = fma52lo(res[92], a[35], a[57]); // Sum(92) res[93] = fma52hi(res[93], a[35], a[57]); // Sum(92) res[93] = fma52lo(res[93], a[36], a[57]); // Sum(93) res[94] = fma52hi(res[94], a[36], a[57]); // Sum(93) res[94] = fma52lo(res[94], a[37], a[57]); // Sum(94) res[95] = fma52hi(res[95], a[37], a[57]); // Sum(94) res[95] = fma52lo(res[95], a[38], a[57]); // Sum(95) res[96] = fma52hi(res[96], a[38], a[57]); // Sum(95) res[84] = fma52lo(res[84], a[26], a[58]); // Sum(84) res[85] = fma52hi(res[85], a[26], a[58]); // Sum(84) res[85] = fma52lo(res[85], a[27], a[58]); // Sum(85) res[86] = fma52hi(res[86], a[27], a[58]); // Sum(85) res[86] = fma52lo(res[86], a[28], a[58]); // Sum(86) res[87] = fma52hi(res[87], a[28], a[58]); // Sum(86) res[87] = fma52lo(res[87], a[29], a[58]); // Sum(87) res[88] = fma52hi(res[88], a[29], a[58]); // Sum(87) res[88] = fma52lo(res[88], a[30], a[58]); // Sum(88) res[89] = fma52hi(res[89], a[30], a[58]); // Sum(88) res[89] = fma52lo(res[89], a[31], a[58]); // Sum(89) res[90] = fma52hi(res[90], a[31], a[58]); // Sum(89) res[90] = fma52lo(res[90], a[32], a[58]); // Sum(90) res[91] = fma52hi(res[91], a[32], a[58]); // Sum(90) res[91] = fma52lo(res[91], a[33], a[58]); // Sum(91) res[92] = fma52hi(res[92], a[33], a[58]); // Sum(91) res[92] = fma52lo(res[92], a[34], a[58]); // Sum(92) res[93] = fma52hi(res[93], a[34], a[58]); // Sum(92) res[93] = fma52lo(res[93], a[35], a[58]); // Sum(93) res[94] = fma52hi(res[94], a[35], a[58]); // Sum(93) res[94] = fma52lo(res[94], a[36], a[58]); // Sum(94) res[95] = fma52hi(res[95], a[36], a[58]); // Sum(94) res[95] = fma52lo(res[95], a[37], a[58]); // Sum(95) res[96] = fma52hi(res[96], a[37], a[58]); // Sum(95) res[84] = fma52lo(res[84], a[25], a[59]); // Sum(84) res[85] = fma52hi(res[85], a[25], a[59]); // Sum(84) res[85] = fma52lo(res[85], a[26], a[59]); // Sum(85) res[86] = fma52hi(res[86], a[26], a[59]); // Sum(85) res[86] = fma52lo(res[86], a[27], a[59]); // Sum(86) res[87] = fma52hi(res[87], a[27], a[59]); // Sum(86) res[87] = fma52lo(res[87], a[28], a[59]); // Sum(87) res[88] = fma52hi(res[88], a[28], a[59]); // Sum(87) res[88] = fma52lo(res[88], a[29], a[59]); // Sum(88) res[89] = fma52hi(res[89], a[29], a[59]); // Sum(88) res[89] = fma52lo(res[89], a[30], a[59]); // Sum(89) res[90] = fma52hi(res[90], a[30], a[59]); // Sum(89) res[90] = fma52lo(res[90], a[31], a[59]); // Sum(90) res[91] = fma52hi(res[91], a[31], a[59]); // Sum(90) res[91] = fma52lo(res[91], a[32], a[59]); // Sum(91) res[92] = fma52hi(res[92], a[32], a[59]); // Sum(91) res[92] = fma52lo(res[92], a[33], a[59]); // Sum(92) res[93] = fma52hi(res[93], a[33], a[59]); // Sum(92) res[93] = fma52lo(res[93], a[34], a[59]); // Sum(93) res[94] = fma52hi(res[94], a[34], a[59]); // Sum(93) res[94] = fma52lo(res[94], a[35], a[59]); // Sum(94) res[95] = fma52hi(res[95], a[35], a[59]); // Sum(94) res[95] = fma52lo(res[95], a[36], a[59]); // Sum(95) res[96] = fma52hi(res[96], a[36], a[59]); // Sum(95) res[84] = fma52lo(res[84], a[24], a[60]); // Sum(84) res[85] = fma52hi(res[85], a[24], a[60]); // Sum(84) res[85] = fma52lo(res[85], a[25], a[60]); // Sum(85) res[86] = fma52hi(res[86], a[25], a[60]); // Sum(85) res[86] = fma52lo(res[86], a[26], a[60]); // Sum(86) res[87] = fma52hi(res[87], a[26], a[60]); // Sum(86) res[87] = fma52lo(res[87], a[27], a[60]); // Sum(87) res[88] = fma52hi(res[88], a[27], a[60]); // Sum(87) res[88] = fma52lo(res[88], a[28], a[60]); // Sum(88) res[89] = fma52hi(res[89], a[28], a[60]); // Sum(88) res[89] = fma52lo(res[89], a[29], a[60]); // Sum(89) res[90] = fma52hi(res[90], a[29], a[60]); // Sum(89) res[90] = fma52lo(res[90], a[30], a[60]); // Sum(90) res[91] = fma52hi(res[91], a[30], a[60]); // Sum(90) res[91] = fma52lo(res[91], a[31], a[60]); // Sum(91) res[92] = fma52hi(res[92], a[31], a[60]); // Sum(91) res[92] = fma52lo(res[92], a[32], a[60]); // Sum(92) res[93] = fma52hi(res[93], a[32], a[60]); // Sum(92) res[93] = fma52lo(res[93], a[33], a[60]); // Sum(93) res[94] = fma52hi(res[94], a[33], a[60]); // Sum(93) res[94] = fma52lo(res[94], a[34], a[60]); // Sum(94) res[95] = fma52hi(res[95], a[34], a[60]); // Sum(94) res[95] = fma52lo(res[95], a[35], a[60]); // Sum(95) res[96] = fma52hi(res[96], a[35], a[60]); // Sum(95) res[84] = fma52lo(res[84], a[23], a[61]); // Sum(84) res[85] = fma52hi(res[85], a[23], a[61]); // Sum(84) res[85] = fma52lo(res[85], a[24], a[61]); // Sum(85) res[86] = fma52hi(res[86], a[24], a[61]); // Sum(85) res[86] = fma52lo(res[86], a[25], a[61]); // Sum(86) res[87] = fma52hi(res[87], a[25], a[61]); // Sum(86) res[87] = fma52lo(res[87], a[26], a[61]); // Sum(87) res[88] = fma52hi(res[88], a[26], a[61]); // Sum(87) res[88] = fma52lo(res[88], a[27], a[61]); // Sum(88) res[89] = fma52hi(res[89], a[27], a[61]); // Sum(88) res[89] = fma52lo(res[89], a[28], a[61]); // Sum(89) res[90] = fma52hi(res[90], a[28], a[61]); // Sum(89) res[90] = fma52lo(res[90], a[29], a[61]); // Sum(90) res[91] = fma52hi(res[91], a[29], a[61]); // Sum(90) res[91] = fma52lo(res[91], a[30], a[61]); // Sum(91) res[92] = fma52hi(res[92], a[30], a[61]); // Sum(91) res[92] = fma52lo(res[92], a[31], a[61]); // Sum(92) res[93] = fma52hi(res[93], a[31], a[61]); // Sum(92) res[93] = fma52lo(res[93], a[32], a[61]); // Sum(93) res[94] = fma52hi(res[94], a[32], a[61]); // Sum(93) res[94] = fma52lo(res[94], a[33], a[61]); // Sum(94) res[95] = fma52hi(res[95], a[33], a[61]); // Sum(94) res[95] = fma52lo(res[95], a[34], a[61]); // Sum(95) res[96] = fma52hi(res[96], a[34], a[61]); // Sum(95) res[84] = fma52lo(res[84], a[22], a[62]); // Sum(84) res[85] = fma52hi(res[85], a[22], a[62]); // Sum(84) res[85] = fma52lo(res[85], a[23], a[62]); // Sum(85) res[86] = fma52hi(res[86], a[23], a[62]); // Sum(85) res[86] = fma52lo(res[86], a[24], a[62]); // Sum(86) res[87] = fma52hi(res[87], a[24], a[62]); // Sum(86) res[87] = fma52lo(res[87], a[25], a[62]); // Sum(87) res[88] = fma52hi(res[88], a[25], a[62]); // Sum(87) res[88] = fma52lo(res[88], a[26], a[62]); // Sum(88) res[89] = fma52hi(res[89], a[26], a[62]); // Sum(88) res[89] = fma52lo(res[89], a[27], a[62]); // Sum(89) res[90] = fma52hi(res[90], a[27], a[62]); // Sum(89) res[90] = fma52lo(res[90], a[28], a[62]); // Sum(90) res[91] = fma52hi(res[91], a[28], a[62]); // Sum(90) res[91] = fma52lo(res[91], a[29], a[62]); // Sum(91) res[92] = fma52hi(res[92], a[29], a[62]); // Sum(91) res[92] = fma52lo(res[92], a[30], a[62]); // Sum(92) res[93] = fma52hi(res[93], a[30], a[62]); // Sum(92) res[93] = fma52lo(res[93], a[31], a[62]); // Sum(93) res[94] = fma52hi(res[94], a[31], a[62]); // Sum(93) res[94] = fma52lo(res[94], a[32], a[62]); // Sum(94) res[95] = fma52hi(res[95], a[32], a[62]); // Sum(94) res[95] = fma52lo(res[95], a[33], a[62]); // Sum(95) res[96] = fma52hi(res[96], a[33], a[62]); // Sum(95) res[84] = fma52lo(res[84], a[21], a[63]); // Sum(84) res[85] = fma52hi(res[85], a[21], a[63]); // Sum(84) res[85] = fma52lo(res[85], a[22], a[63]); // Sum(85) res[86] = fma52hi(res[86], a[22], a[63]); // Sum(85) res[86] = fma52lo(res[86], a[23], a[63]); // Sum(86) res[87] = fma52hi(res[87], a[23], a[63]); // Sum(86) res[87] = fma52lo(res[87], a[24], a[63]); // Sum(87) res[88] = fma52hi(res[88], a[24], a[63]); // Sum(87) res[88] = fma52lo(res[88], a[25], a[63]); // Sum(88) res[89] = fma52hi(res[89], a[25], a[63]); // Sum(88) res[89] = fma52lo(res[89], a[26], a[63]); // Sum(89) res[90] = fma52hi(res[90], a[26], a[63]); // Sum(89) res[90] = fma52lo(res[90], a[27], a[63]); // Sum(90) res[91] = fma52hi(res[91], a[27], a[63]); // Sum(90) res[91] = fma52lo(res[91], a[28], a[63]); // Sum(91) res[92] = fma52hi(res[92], a[28], a[63]); // Sum(91) res[92] = fma52lo(res[92], a[29], a[63]); // Sum(92) res[93] = fma52hi(res[93], a[29], a[63]); // Sum(92) res[93] = fma52lo(res[93], a[30], a[63]); // Sum(93) res[94] = fma52hi(res[94], a[30], a[63]); // Sum(93) res[94] = fma52lo(res[94], a[31], a[63]); // Sum(94) res[95] = fma52hi(res[95], a[31], a[63]); // Sum(94) res[95] = fma52lo(res[95], a[32], a[63]); // Sum(95) res[96] = fma52hi(res[96], a[32], a[63]); // Sum(95) res[84] = fma52lo(res[84], a[20], a[64]); // Sum(84) res[85] = fma52hi(res[85], a[20], a[64]); // Sum(84) res[85] = fma52lo(res[85], a[21], a[64]); // Sum(85) res[86] = fma52hi(res[86], a[21], a[64]); // Sum(85) res[86] = fma52lo(res[86], a[22], a[64]); // Sum(86) res[87] = fma52hi(res[87], a[22], a[64]); // Sum(86) res[87] = fma52lo(res[87], a[23], a[64]); // Sum(87) res[88] = fma52hi(res[88], a[23], a[64]); // Sum(87) res[88] = fma52lo(res[88], a[24], a[64]); // Sum(88) res[89] = fma52hi(res[89], a[24], a[64]); // Sum(88) res[89] = fma52lo(res[89], a[25], a[64]); // Sum(89) res[90] = fma52hi(res[90], a[25], a[64]); // Sum(89) res[90] = fma52lo(res[90], a[26], a[64]); // Sum(90) res[91] = fma52hi(res[91], a[26], a[64]); // Sum(90) res[91] = fma52lo(res[91], a[27], a[64]); // Sum(91) res[92] = fma52hi(res[92], a[27], a[64]); // Sum(91) res[92] = fma52lo(res[92], a[28], a[64]); // Sum(92) res[93] = fma52hi(res[93], a[28], a[64]); // Sum(92) res[93] = fma52lo(res[93], a[29], a[64]); // Sum(93) res[94] = fma52hi(res[94], a[29], a[64]); // Sum(93) res[94] = fma52lo(res[94], a[30], a[64]); // Sum(94) res[95] = fma52hi(res[95], a[30], a[64]); // Sum(94) res[95] = fma52lo(res[95], a[31], a[64]); // Sum(95) res[96] = fma52hi(res[96], a[31], a[64]); // Sum(95) res[84] = fma52lo(res[84], a[19], a[65]); // Sum(84) res[85] = fma52hi(res[85], a[19], a[65]); // Sum(84) res[85] = fma52lo(res[85], a[20], a[65]); // Sum(85) res[86] = fma52hi(res[86], a[20], a[65]); // Sum(85) res[86] = fma52lo(res[86], a[21], a[65]); // Sum(86) res[87] = fma52hi(res[87], a[21], a[65]); // Sum(86) res[87] = fma52lo(res[87], a[22], a[65]); // Sum(87) res[88] = fma52hi(res[88], a[22], a[65]); // Sum(87) res[88] = fma52lo(res[88], a[23], a[65]); // Sum(88) res[89] = fma52hi(res[89], a[23], a[65]); // Sum(88) res[89] = fma52lo(res[89], a[24], a[65]); // Sum(89) res[90] = fma52hi(res[90], a[24], a[65]); // Sum(89) res[90] = fma52lo(res[90], a[25], a[65]); // Sum(90) res[91] = fma52hi(res[91], a[25], a[65]); // Sum(90) res[91] = fma52lo(res[91], a[26], a[65]); // Sum(91) res[92] = fma52hi(res[92], a[26], a[65]); // Sum(91) res[92] = fma52lo(res[92], a[27], a[65]); // Sum(92) res[93] = fma52hi(res[93], a[27], a[65]); // Sum(92) res[93] = fma52lo(res[93], a[28], a[65]); // Sum(93) res[94] = fma52hi(res[94], a[28], a[65]); // Sum(93) res[94] = fma52lo(res[94], a[29], a[65]); // Sum(94) res[95] = fma52hi(res[95], a[29], a[65]); // Sum(94) res[95] = fma52lo(res[95], a[30], a[65]); // Sum(95) res[96] = fma52hi(res[96], a[30], a[65]); // Sum(95) res[84] = fma52lo(res[84], a[18], a[66]); // Sum(84) res[85] = fma52hi(res[85], a[18], a[66]); // Sum(84) res[85] = fma52lo(res[85], a[19], a[66]); // Sum(85) res[86] = fma52hi(res[86], a[19], a[66]); // Sum(85) res[86] = fma52lo(res[86], a[20], a[66]); // Sum(86) res[87] = fma52hi(res[87], a[20], a[66]); // Sum(86) res[87] = fma52lo(res[87], a[21], a[66]); // Sum(87) res[88] = fma52hi(res[88], a[21], a[66]); // Sum(87) res[88] = fma52lo(res[88], a[22], a[66]); // Sum(88) res[89] = fma52hi(res[89], a[22], a[66]); // Sum(88) res[89] = fma52lo(res[89], a[23], a[66]); // Sum(89) res[90] = fma52hi(res[90], a[23], a[66]); // Sum(89) res[90] = fma52lo(res[90], a[24], a[66]); // Sum(90) res[91] = fma52hi(res[91], a[24], a[66]); // Sum(90) res[91] = fma52lo(res[91], a[25], a[66]); // Sum(91) res[92] = fma52hi(res[92], a[25], a[66]); // Sum(91) res[92] = fma52lo(res[92], a[26], a[66]); // Sum(92) res[93] = fma52hi(res[93], a[26], a[66]); // Sum(92) res[93] = fma52lo(res[93], a[27], a[66]); // Sum(93) res[94] = fma52hi(res[94], a[27], a[66]); // Sum(93) res[94] = fma52lo(res[94], a[28], a[66]); // Sum(94) res[95] = fma52hi(res[95], a[28], a[66]); // Sum(94) res[95] = fma52lo(res[95], a[29], a[66]); // Sum(95) res[96] = fma52hi(res[96], a[29], a[66]); // Sum(95) res[84] = fma52lo(res[84], a[17], a[67]); // Sum(84) res[85] = fma52hi(res[85], a[17], a[67]); // Sum(84) res[85] = fma52lo(res[85], a[18], a[67]); // Sum(85) res[86] = fma52hi(res[86], a[18], a[67]); // Sum(85) res[86] = fma52lo(res[86], a[19], a[67]); // Sum(86) res[87] = fma52hi(res[87], a[19], a[67]); // Sum(86) res[87] = fma52lo(res[87], a[20], a[67]); // Sum(87) res[88] = fma52hi(res[88], a[20], a[67]); // Sum(87) res[88] = fma52lo(res[88], a[21], a[67]); // Sum(88) res[89] = fma52hi(res[89], a[21], a[67]); // Sum(88) res[89] = fma52lo(res[89], a[22], a[67]); // Sum(89) res[90] = fma52hi(res[90], a[22], a[67]); // Sum(89) res[90] = fma52lo(res[90], a[23], a[67]); // Sum(90) res[91] = fma52hi(res[91], a[23], a[67]); // Sum(90) res[91] = fma52lo(res[91], a[24], a[67]); // Sum(91) res[92] = fma52hi(res[92], a[24], a[67]); // Sum(91) res[92] = fma52lo(res[92], a[25], a[67]); // Sum(92) res[93] = fma52hi(res[93], a[25], a[67]); // Sum(92) res[93] = fma52lo(res[93], a[26], a[67]); // Sum(93) res[94] = fma52hi(res[94], a[26], a[67]); // Sum(93) res[94] = fma52lo(res[94], a[27], a[67]); // Sum(94) res[95] = fma52hi(res[95], a[27], a[67]); // Sum(94) res[95] = fma52lo(res[95], a[28], a[67]); // Sum(95) res[96] = fma52hi(res[96], a[28], a[67]); // Sum(95) res[84] = fma52lo(res[84], a[16], a[68]); // Sum(84) res[85] = fma52hi(res[85], a[16], a[68]); // Sum(84) res[85] = fma52lo(res[85], a[17], a[68]); // Sum(85) res[86] = fma52hi(res[86], a[17], a[68]); // Sum(85) res[86] = fma52lo(res[86], a[18], a[68]); // Sum(86) res[87] = fma52hi(res[87], a[18], a[68]); // Sum(86) res[87] = fma52lo(res[87], a[19], a[68]); // Sum(87) res[88] = fma52hi(res[88], a[19], a[68]); // Sum(87) res[88] = fma52lo(res[88], a[20], a[68]); // Sum(88) res[89] = fma52hi(res[89], a[20], a[68]); // Sum(88) res[89] = fma52lo(res[89], a[21], a[68]); // Sum(89) res[90] = fma52hi(res[90], a[21], a[68]); // Sum(89) res[90] = fma52lo(res[90], a[22], a[68]); // Sum(90) res[91] = fma52hi(res[91], a[22], a[68]); // Sum(90) res[91] = fma52lo(res[91], a[23], a[68]); // Sum(91) res[92] = fma52hi(res[92], a[23], a[68]); // Sum(91) res[92] = fma52lo(res[92], a[24], a[68]); // Sum(92) res[93] = fma52hi(res[93], a[24], a[68]); // Sum(92) res[93] = fma52lo(res[93], a[25], a[68]); // Sum(93) res[94] = fma52hi(res[94], a[25], a[68]); // Sum(93) res[94] = fma52lo(res[94], a[26], a[68]); // Sum(94) res[95] = fma52hi(res[95], a[26], a[68]); // Sum(94) res[95] = fma52lo(res[95], a[27], a[68]); // Sum(95) res[96] = fma52hi(res[96], a[27], a[68]); // Sum(95) res[84] = fma52lo(res[84], a[15], a[69]); // Sum(84) res[85] = fma52hi(res[85], a[15], a[69]); // Sum(84) res[85] = fma52lo(res[85], a[16], a[69]); // Sum(85) res[86] = fma52hi(res[86], a[16], a[69]); // Sum(85) res[86] = fma52lo(res[86], a[17], a[69]); // Sum(86) res[87] = fma52hi(res[87], a[17], a[69]); // Sum(86) res[87] = fma52lo(res[87], a[18], a[69]); // Sum(87) res[88] = fma52hi(res[88], a[18], a[69]); // Sum(87) res[88] = fma52lo(res[88], a[19], a[69]); // Sum(88) res[89] = fma52hi(res[89], a[19], a[69]); // Sum(88) res[89] = fma52lo(res[89], a[20], a[69]); // Sum(89) res[90] = fma52hi(res[90], a[20], a[69]); // Sum(89) res[90] = fma52lo(res[90], a[21], a[69]); // Sum(90) res[91] = fma52hi(res[91], a[21], a[69]); // Sum(90) res[91] = fma52lo(res[91], a[22], a[69]); // Sum(91) res[92] = fma52hi(res[92], a[22], a[69]); // Sum(91) res[92] = fma52lo(res[92], a[23], a[69]); // Sum(92) res[93] = fma52hi(res[93], a[23], a[69]); // Sum(92) res[93] = fma52lo(res[93], a[24], a[69]); // Sum(93) res[94] = fma52hi(res[94], a[24], a[69]); // Sum(93) res[94] = fma52lo(res[94], a[25], a[69]); // Sum(94) res[95] = fma52hi(res[95], a[25], a[69]); // Sum(94) res[95] = fma52lo(res[95], a[26], a[69]); // Sum(95) res[96] = fma52hi(res[96], a[26], a[69]); // Sum(95) res[84] = fma52lo(res[84], a[14], a[70]); // Sum(84) res[85] = fma52hi(res[85], a[14], a[70]); // Sum(84) res[85] = fma52lo(res[85], a[15], a[70]); // Sum(85) res[86] = fma52hi(res[86], a[15], a[70]); // Sum(85) res[86] = fma52lo(res[86], a[16], a[70]); // Sum(86) res[87] = fma52hi(res[87], a[16], a[70]); // Sum(86) res[87] = fma52lo(res[87], a[17], a[70]); // Sum(87) res[88] = fma52hi(res[88], a[17], a[70]); // Sum(87) res[88] = fma52lo(res[88], a[18], a[70]); // Sum(88) res[89] = fma52hi(res[89], a[18], a[70]); // Sum(88) res[89] = fma52lo(res[89], a[19], a[70]); // Sum(89) res[90] = fma52hi(res[90], a[19], a[70]); // Sum(89) res[90] = fma52lo(res[90], a[20], a[70]); // Sum(90) res[91] = fma52hi(res[91], a[20], a[70]); // Sum(90) res[91] = fma52lo(res[91], a[21], a[70]); // Sum(91) res[92] = fma52hi(res[92], a[21], a[70]); // Sum(91) res[92] = fma52lo(res[92], a[22], a[70]); // Sum(92) res[93] = fma52hi(res[93], a[22], a[70]); // Sum(92) res[93] = fma52lo(res[93], a[23], a[70]); // Sum(93) res[94] = fma52hi(res[94], a[23], a[70]); // Sum(93) res[94] = fma52lo(res[94], a[24], a[70]); // Sum(94) res[95] = fma52hi(res[95], a[24], a[70]); // Sum(94) res[95] = fma52lo(res[95], a[25], a[70]); // Sum(95) res[96] = fma52hi(res[96], a[25], a[70]); // Sum(95) res[84] = fma52lo(res[84], a[13], a[71]); // Sum(84) res[85] = fma52hi(res[85], a[13], a[71]); // Sum(84) res[85] = fma52lo(res[85], a[14], a[71]); // Sum(85) res[86] = fma52hi(res[86], a[14], a[71]); // Sum(85) res[86] = fma52lo(res[86], a[15], a[71]); // Sum(86) res[87] = fma52hi(res[87], a[15], a[71]); // Sum(86) res[87] = fma52lo(res[87], a[16], a[71]); // Sum(87) res[88] = fma52hi(res[88], a[16], a[71]); // Sum(87) res[88] = fma52lo(res[88], a[17], a[71]); // Sum(88) res[89] = fma52hi(res[89], a[17], a[71]); // Sum(88) res[89] = fma52lo(res[89], a[18], a[71]); // Sum(89) res[90] = fma52hi(res[90], a[18], a[71]); // Sum(89) res[90] = fma52lo(res[90], a[19], a[71]); // Sum(90) res[91] = fma52hi(res[91], a[19], a[71]); // Sum(90) res[91] = fma52lo(res[91], a[20], a[71]); // Sum(91) res[92] = fma52hi(res[92], a[20], a[71]); // Sum(91) res[92] = fma52lo(res[92], a[21], a[71]); // Sum(92) res[93] = fma52hi(res[93], a[21], a[71]); // Sum(92) res[93] = fma52lo(res[93], a[22], a[71]); // Sum(93) res[94] = fma52hi(res[94], a[22], a[71]); // Sum(93) res[94] = fma52lo(res[94], a[23], a[71]); // Sum(94) res[95] = fma52hi(res[95], a[23], a[71]); // Sum(94) res[95] = fma52lo(res[95], a[24], a[71]); // Sum(95) res[96] = fma52hi(res[96], a[24], a[71]); // Sum(95) res[84] = fma52lo(res[84], a[12], a[72]); // Sum(84) res[85] = fma52hi(res[85], a[12], a[72]); // Sum(84) res[85] = fma52lo(res[85], a[13], a[72]); // Sum(85) res[86] = fma52hi(res[86], a[13], a[72]); // Sum(85) res[86] = fma52lo(res[86], a[14], a[72]); // Sum(86) res[87] = fma52hi(res[87], a[14], a[72]); // Sum(86) res[87] = fma52lo(res[87], a[15], a[72]); // Sum(87) res[88] = fma52hi(res[88], a[15], a[72]); // Sum(87) res[88] = fma52lo(res[88], a[16], a[72]); // Sum(88) res[89] = fma52hi(res[89], a[16], a[72]); // Sum(88) res[89] = fma52lo(res[89], a[17], a[72]); // Sum(89) res[90] = fma52hi(res[90], a[17], a[72]); // Sum(89) res[90] = fma52lo(res[90], a[18], a[72]); // Sum(90) res[91] = fma52hi(res[91], a[18], a[72]); // Sum(90) res[91] = fma52lo(res[91], a[19], a[72]); // Sum(91) res[92] = fma52hi(res[92], a[19], a[72]); // Sum(91) res[92] = fma52lo(res[92], a[20], a[72]); // Sum(92) res[93] = fma52hi(res[93], a[20], a[72]); // Sum(92) res[93] = fma52lo(res[93], a[21], a[72]); // Sum(93) res[94] = fma52hi(res[94], a[21], a[72]); // Sum(93) res[94] = fma52lo(res[94], a[22], a[72]); // Sum(94) res[95] = fma52hi(res[95], a[22], a[72]); // Sum(94) res[95] = fma52lo(res[95], a[23], a[72]); // Sum(95) res[96] = fma52hi(res[96], a[23], a[72]); // Sum(95) res[84] = fma52lo(res[84], a[11], a[73]); // Sum(84) res[85] = fma52hi(res[85], a[11], a[73]); // Sum(84) res[85] = fma52lo(res[85], a[12], a[73]); // Sum(85) res[86] = fma52hi(res[86], a[12], a[73]); // Sum(85) res[86] = fma52lo(res[86], a[13], a[73]); // Sum(86) res[87] = fma52hi(res[87], a[13], a[73]); // Sum(86) res[87] = fma52lo(res[87], a[14], a[73]); // Sum(87) res[88] = fma52hi(res[88], a[14], a[73]); // Sum(87) res[88] = fma52lo(res[88], a[15], a[73]); // Sum(88) res[89] = fma52hi(res[89], a[15], a[73]); // Sum(88) res[89] = fma52lo(res[89], a[16], a[73]); // Sum(89) res[90] = fma52hi(res[90], a[16], a[73]); // Sum(89) res[90] = fma52lo(res[90], a[17], a[73]); // Sum(90) res[91] = fma52hi(res[91], a[17], a[73]); // Sum(90) res[91] = fma52lo(res[91], a[18], a[73]); // Sum(91) res[92] = fma52hi(res[92], a[18], a[73]); // Sum(91) res[92] = fma52lo(res[92], a[19], a[73]); // Sum(92) res[93] = fma52hi(res[93], a[19], a[73]); // Sum(92) res[93] = fma52lo(res[93], a[20], a[73]); // Sum(93) res[94] = fma52hi(res[94], a[20], a[73]); // Sum(93) res[94] = fma52lo(res[94], a[21], a[73]); // Sum(94) res[95] = fma52hi(res[95], a[21], a[73]); // Sum(94) res[95] = fma52lo(res[95], a[22], a[73]); // Sum(95) res[96] = fma52hi(res[96], a[22], a[73]); // Sum(95) res[84] = fma52lo(res[84], a[10], a[74]); // Sum(84) res[85] = fma52hi(res[85], a[10], a[74]); // Sum(84) res[85] = fma52lo(res[85], a[11], a[74]); // Sum(85) res[86] = fma52hi(res[86], a[11], a[74]); // Sum(85) res[86] = fma52lo(res[86], a[12], a[74]); // Sum(86) res[87] = fma52hi(res[87], a[12], a[74]); // Sum(86) res[87] = fma52lo(res[87], a[13], a[74]); // Sum(87) res[88] = fma52hi(res[88], a[13], a[74]); // Sum(87) res[88] = fma52lo(res[88], a[14], a[74]); // Sum(88) res[89] = fma52hi(res[89], a[14], a[74]); // Sum(88) res[89] = fma52lo(res[89], a[15], a[74]); // Sum(89) res[90] = fma52hi(res[90], a[15], a[74]); // Sum(89) res[90] = fma52lo(res[90], a[16], a[74]); // Sum(90) res[91] = fma52hi(res[91], a[16], a[74]); // Sum(90) res[91] = fma52lo(res[91], a[17], a[74]); // Sum(91) res[92] = fma52hi(res[92], a[17], a[74]); // Sum(91) res[92] = fma52lo(res[92], a[18], a[74]); // Sum(92) res[93] = fma52hi(res[93], a[18], a[74]); // Sum(92) res[93] = fma52lo(res[93], a[19], a[74]); // Sum(93) res[94] = fma52hi(res[94], a[19], a[74]); // Sum(93) res[94] = fma52lo(res[94], a[20], a[74]); // Sum(94) res[95] = fma52hi(res[95], a[20], a[74]); // Sum(94) res[95] = fma52lo(res[95], a[21], a[74]); // Sum(95) res[96] = fma52hi(res[96], a[21], a[74]); // Sum(95) res[84] = fma52lo(res[84], a[9], a[75]); // Sum(84) res[85] = fma52hi(res[85], a[9], a[75]); // Sum(84) res[85] = fma52lo(res[85], a[10], a[75]); // Sum(85) res[86] = fma52hi(res[86], a[10], a[75]); // Sum(85) res[86] = fma52lo(res[86], a[11], a[75]); // Sum(86) res[87] = fma52hi(res[87], a[11], a[75]); // Sum(86) res[87] = fma52lo(res[87], a[12], a[75]); // Sum(87) res[88] = fma52hi(res[88], a[12], a[75]); // Sum(87) res[88] = fma52lo(res[88], a[13], a[75]); // Sum(88) res[89] = fma52hi(res[89], a[13], a[75]); // Sum(88) res[89] = fma52lo(res[89], a[14], a[75]); // Sum(89) res[90] = fma52hi(res[90], a[14], a[75]); // Sum(89) res[90] = fma52lo(res[90], a[15], a[75]); // Sum(90) res[91] = fma52hi(res[91], a[15], a[75]); // Sum(90) res[91] = fma52lo(res[91], a[16], a[75]); // Sum(91) res[92] = fma52hi(res[92], a[16], a[75]); // Sum(91) res[92] = fma52lo(res[92], a[17], a[75]); // Sum(92) res[93] = fma52hi(res[93], a[17], a[75]); // Sum(92) res[93] = fma52lo(res[93], a[18], a[75]); // Sum(93) res[94] = fma52hi(res[94], a[18], a[75]); // Sum(93) res[94] = fma52lo(res[94], a[19], a[75]); // Sum(94) res[95] = fma52hi(res[95], a[19], a[75]); // Sum(94) res[95] = fma52lo(res[95], a[20], a[75]); // Sum(95) res[96] = fma52hi(res[96], a[20], a[75]); // Sum(95) res[84] = fma52lo(res[84], a[8], a[76]); // Sum(84) res[85] = fma52hi(res[85], a[8], a[76]); // Sum(84) res[85] = fma52lo(res[85], a[9], a[76]); // Sum(85) res[86] = fma52hi(res[86], a[9], a[76]); // Sum(85) res[86] = fma52lo(res[86], a[10], a[76]); // Sum(86) res[87] = fma52hi(res[87], a[10], a[76]); // Sum(86) res[87] = fma52lo(res[87], a[11], a[76]); // Sum(87) res[88] = fma52hi(res[88], a[11], a[76]); // Sum(87) res[88] = fma52lo(res[88], a[12], a[76]); // Sum(88) res[89] = fma52hi(res[89], a[12], a[76]); // Sum(88) res[89] = fma52lo(res[89], a[13], a[76]); // Sum(89) res[90] = fma52hi(res[90], a[13], a[76]); // Sum(89) res[90] = fma52lo(res[90], a[14], a[76]); // Sum(90) res[91] = fma52hi(res[91], a[14], a[76]); // Sum(90) res[91] = fma52lo(res[91], a[15], a[76]); // Sum(91) res[92] = fma52hi(res[92], a[15], a[76]); // Sum(91) res[92] = fma52lo(res[92], a[16], a[76]); // Sum(92) res[93] = fma52hi(res[93], a[16], a[76]); // Sum(92) res[93] = fma52lo(res[93], a[17], a[76]); // Sum(93) res[94] = fma52hi(res[94], a[17], a[76]); // Sum(93) res[94] = fma52lo(res[94], a[18], a[76]); // Sum(94) res[95] = fma52hi(res[95], a[18], a[76]); // Sum(94) res[95] = fma52lo(res[95], a[19], a[76]); // Sum(95) res[96] = fma52hi(res[96], a[19], a[76]); // Sum(95) res[84] = fma52lo(res[84], a[7], a[77]); // Sum(84) res[85] = fma52hi(res[85], a[7], a[77]); // Sum(84) res[85] = fma52lo(res[85], a[8], a[77]); // Sum(85) res[86] = fma52hi(res[86], a[8], a[77]); // Sum(85) res[86] = fma52lo(res[86], a[9], a[77]); // Sum(86) res[87] = fma52hi(res[87], a[9], a[77]); // Sum(86) res[87] = fma52lo(res[87], a[10], a[77]); // Sum(87) res[88] = fma52hi(res[88], a[10], a[77]); // Sum(87) res[88] = fma52lo(res[88], a[11], a[77]); // Sum(88) res[89] = fma52hi(res[89], a[11], a[77]); // Sum(88) res[89] = fma52lo(res[89], a[12], a[77]); // Sum(89) res[90] = fma52hi(res[90], a[12], a[77]); // Sum(89) res[90] = fma52lo(res[90], a[13], a[77]); // Sum(90) res[91] = fma52hi(res[91], a[13], a[77]); // Sum(90) res[91] = fma52lo(res[91], a[14], a[77]); // Sum(91) res[92] = fma52hi(res[92], a[14], a[77]); // Sum(91) res[92] = fma52lo(res[92], a[15], a[77]); // Sum(92) res[93] = fma52hi(res[93], a[15], a[77]); // Sum(92) res[93] = fma52lo(res[93], a[16], a[77]); // Sum(93) res[94] = fma52hi(res[94], a[16], a[77]); // Sum(93) res[94] = fma52lo(res[94], a[17], a[77]); // Sum(94) res[95] = fma52hi(res[95], a[17], a[77]); // Sum(94) res[95] = fma52lo(res[95], a[18], a[77]); // Sum(95) res[96] = fma52hi(res[96], a[18], a[77]); // Sum(95) res[84] = fma52lo(res[84], a[6], a[78]); // Sum(84) res[85] = fma52hi(res[85], a[6], a[78]); // Sum(84) res[85] = fma52lo(res[85], a[7], a[78]); // Sum(85) res[86] = fma52hi(res[86], a[7], a[78]); // Sum(85) res[86] = fma52lo(res[86], a[8], a[78]); // Sum(86) res[87] = fma52hi(res[87], a[8], a[78]); // Sum(86) res[87] = fma52lo(res[87], a[9], a[78]); // Sum(87) res[88] = fma52hi(res[88], a[9], a[78]); // Sum(87) res[88] = fma52lo(res[88], a[10], a[78]); // Sum(88) res[89] = fma52hi(res[89], a[10], a[78]); // Sum(88) res[89] = fma52lo(res[89], a[11], a[78]); // Sum(89) res[90] = fma52hi(res[90], a[11], a[78]); // Sum(89) res[90] = fma52lo(res[90], a[12], a[78]); // Sum(90) res[91] = fma52hi(res[91], a[12], a[78]); // Sum(90) res[91] = fma52lo(res[91], a[13], a[78]); // Sum(91) res[92] = fma52hi(res[92], a[13], a[78]); // Sum(91) res[92] = fma52lo(res[92], a[14], a[78]); // Sum(92) res[93] = fma52hi(res[93], a[14], a[78]); // Sum(92) res[93] = fma52lo(res[93], a[15], a[78]); // Sum(93) res[94] = fma52hi(res[94], a[15], a[78]); // Sum(93) res[94] = fma52lo(res[94], a[16], a[78]); // Sum(94) res[95] = fma52hi(res[95], a[16], a[78]); // Sum(94) res[95] = fma52lo(res[95], a[17], a[78]); // Sum(95) res[96] = fma52hi(res[96], a[17], a[78]); // Sum(95) res[84] = add64(res[84], res[84]); // Double(84) res[85] = add64(res[85], res[85]); // Double(85) res[86] = add64(res[86], res[86]); // Double(86) res[87] = add64(res[87], res[87]); // Double(87) res[88] = add64(res[88], res[88]); // Double(88) res[89] = add64(res[89], res[89]); // Double(89) res[90] = add64(res[90], res[90]); // Double(90) res[91] = add64(res[91], res[91]); // Double(91) res[92] = add64(res[92], res[92]); // Double(92) res[93] = add64(res[93], res[93]); // Double(93) res[94] = add64(res[94], res[94]); // Double(94) res[95] = add64(res[95], res[95]); // Double(95) res[84] = fma52lo(res[84], a[42], a[42]); // Add sqr(84) res[85] = fma52hi(res[85], a[42], a[42]); // Add sqr(84) res[86] = fma52lo(res[86], a[43], a[43]); // Add sqr(86) res[87] = fma52hi(res[87], a[43], a[43]); // Add sqr(86) res[88] = fma52lo(res[88], a[44], a[44]); // Add sqr(88) res[89] = fma52hi(res[89], a[44], a[44]); // Add sqr(88) res[90] = fma52lo(res[90], a[45], a[45]); // Add sqr(90) res[91] = fma52hi(res[91], a[45], a[45]); // Add sqr(90) res[92] = fma52lo(res[92], a[46], a[46]); // Add sqr(92) res[93] = fma52hi(res[93], a[46], a[46]); // Add sqr(92) res[94] = fma52lo(res[94], a[47], a[47]); // Add sqr(94) res[95] = fma52hi(res[95], a[47], a[47]); // Add sqr(94) res[96] = fma52lo(res[96], a[47], a[49]); // Sum(96) res[97] = fma52hi(res[97], a[47], a[49]); // Sum(96) res[97] = fma52lo(res[97], a[48], a[49]); // Sum(97) res[98] = fma52hi(res[98], a[48], a[49]); // Sum(97) res[96] = fma52lo(res[96], a[46], a[50]); // Sum(96) res[97] = fma52hi(res[97], a[46], a[50]); // Sum(96) res[97] = fma52lo(res[97], a[47], a[50]); // Sum(97) res[98] = fma52hi(res[98], a[47], a[50]); // Sum(97) res[98] = fma52lo(res[98], a[48], a[50]); // Sum(98) res[99] = fma52hi(res[99], a[48], a[50]); // Sum(98) res[99] = fma52lo(res[99], a[49], a[50]); // Sum(99) res[100] = fma52hi(res[100], a[49], a[50]); // Sum(99) res[96] = fma52lo(res[96], a[45], a[51]); // Sum(96) res[97] = fma52hi(res[97], a[45], a[51]); // Sum(96) res[97] = fma52lo(res[97], a[46], a[51]); // Sum(97) res[98] = fma52hi(res[98], a[46], a[51]); // Sum(97) res[98] = fma52lo(res[98], a[47], a[51]); // Sum(98) res[99] = fma52hi(res[99], a[47], a[51]); // Sum(98) res[99] = fma52lo(res[99], a[48], a[51]); // Sum(99) res[100] = fma52hi(res[100], a[48], a[51]); // Sum(99) res[100] = fma52lo(res[100], a[49], a[51]); // Sum(100) res[101] = fma52hi(res[101], a[49], a[51]); // Sum(100) res[101] = fma52lo(res[101], a[50], a[51]); // Sum(101) res[102] = fma52hi(res[102], a[50], a[51]); // Sum(101) res[96] = fma52lo(res[96], a[44], a[52]); // Sum(96) res[97] = fma52hi(res[97], a[44], a[52]); // Sum(96) res[97] = fma52lo(res[97], a[45], a[52]); // Sum(97) res[98] = fma52hi(res[98], a[45], a[52]); // Sum(97) res[98] = fma52lo(res[98], a[46], a[52]); // Sum(98) res[99] = fma52hi(res[99], a[46], a[52]); // Sum(98) res[99] = fma52lo(res[99], a[47], a[52]); // Sum(99) res[100] = fma52hi(res[100], a[47], a[52]); // Sum(99) res[100] = fma52lo(res[100], a[48], a[52]); // Sum(100) res[101] = fma52hi(res[101], a[48], a[52]); // Sum(100) res[101] = fma52lo(res[101], a[49], a[52]); // Sum(101) res[102] = fma52hi(res[102], a[49], a[52]); // Sum(101) res[102] = fma52lo(res[102], a[50], a[52]); // Sum(102) res[103] = fma52hi(res[103], a[50], a[52]); // Sum(102) res[103] = fma52lo(res[103], a[51], a[52]); // Sum(103) res[104] = fma52hi(res[104], a[51], a[52]); // Sum(103) res[96] = fma52lo(res[96], a[43], a[53]); // Sum(96) res[97] = fma52hi(res[97], a[43], a[53]); // Sum(96) res[97] = fma52lo(res[97], a[44], a[53]); // Sum(97) res[98] = fma52hi(res[98], a[44], a[53]); // Sum(97) res[98] = fma52lo(res[98], a[45], a[53]); // Sum(98) res[99] = fma52hi(res[99], a[45], a[53]); // Sum(98) res[99] = fma52lo(res[99], a[46], a[53]); // Sum(99) res[100] = fma52hi(res[100], a[46], a[53]); // Sum(99) res[100] = fma52lo(res[100], a[47], a[53]); // Sum(100) res[101] = fma52hi(res[101], a[47], a[53]); // Sum(100) res[101] = fma52lo(res[101], a[48], a[53]); // Sum(101) res[102] = fma52hi(res[102], a[48], a[53]); // Sum(101) res[102] = fma52lo(res[102], a[49], a[53]); // Sum(102) res[103] = fma52hi(res[103], a[49], a[53]); // Sum(102) res[103] = fma52lo(res[103], a[50], a[53]); // Sum(103) res[104] = fma52hi(res[104], a[50], a[53]); // Sum(103) res[104] = fma52lo(res[104], a[51], a[53]); // Sum(104) res[105] = fma52hi(res[105], a[51], a[53]); // Sum(104) res[105] = fma52lo(res[105], a[52], a[53]); // Sum(105) res[106] = fma52hi(res[106], a[52], a[53]); // Sum(105) res[96] = fma52lo(res[96], a[42], a[54]); // Sum(96) res[97] = fma52hi(res[97], a[42], a[54]); // Sum(96) res[97] = fma52lo(res[97], a[43], a[54]); // Sum(97) res[98] = fma52hi(res[98], a[43], a[54]); // Sum(97) res[98] = fma52lo(res[98], a[44], a[54]); // Sum(98) res[99] = fma52hi(res[99], a[44], a[54]); // Sum(98) res[99] = fma52lo(res[99], a[45], a[54]); // Sum(99) res[100] = fma52hi(res[100], a[45], a[54]); // Sum(99) res[100] = fma52lo(res[100], a[46], a[54]); // Sum(100) res[101] = fma52hi(res[101], a[46], a[54]); // Sum(100) res[101] = fma52lo(res[101], a[47], a[54]); // Sum(101) res[102] = fma52hi(res[102], a[47], a[54]); // Sum(101) res[102] = fma52lo(res[102], a[48], a[54]); // Sum(102) res[103] = fma52hi(res[103], a[48], a[54]); // Sum(102) res[103] = fma52lo(res[103], a[49], a[54]); // Sum(103) res[104] = fma52hi(res[104], a[49], a[54]); // Sum(103) res[104] = fma52lo(res[104], a[50], a[54]); // Sum(104) res[105] = fma52hi(res[105], a[50], a[54]); // Sum(104) res[105] = fma52lo(res[105], a[51], a[54]); // Sum(105) res[106] = fma52hi(res[106], a[51], a[54]); // Sum(105) res[106] = fma52lo(res[106], a[52], a[54]); // Sum(106) res[107] = fma52hi(res[107], a[52], a[54]); // Sum(106) res[107] = fma52lo(res[107], a[53], a[54]); // Sum(107) res[108] = fma52hi(res[108], a[53], a[54]); // Sum(107) res[96] = fma52lo(res[96], a[41], a[55]); // Sum(96) res[97] = fma52hi(res[97], a[41], a[55]); // Sum(96) res[97] = fma52lo(res[97], a[42], a[55]); // Sum(97) res[98] = fma52hi(res[98], a[42], a[55]); // Sum(97) res[98] = fma52lo(res[98], a[43], a[55]); // Sum(98) res[99] = fma52hi(res[99], a[43], a[55]); // Sum(98) res[99] = fma52lo(res[99], a[44], a[55]); // Sum(99) res[100] = fma52hi(res[100], a[44], a[55]); // Sum(99) res[100] = fma52lo(res[100], a[45], a[55]); // Sum(100) res[101] = fma52hi(res[101], a[45], a[55]); // Sum(100) res[101] = fma52lo(res[101], a[46], a[55]); // Sum(101) res[102] = fma52hi(res[102], a[46], a[55]); // Sum(101) res[102] = fma52lo(res[102], a[47], a[55]); // Sum(102) res[103] = fma52hi(res[103], a[47], a[55]); // Sum(102) res[103] = fma52lo(res[103], a[48], a[55]); // Sum(103) res[104] = fma52hi(res[104], a[48], a[55]); // Sum(103) res[104] = fma52lo(res[104], a[49], a[55]); // Sum(104) res[105] = fma52hi(res[105], a[49], a[55]); // Sum(104) res[105] = fma52lo(res[105], a[50], a[55]); // Sum(105) res[106] = fma52hi(res[106], a[50], a[55]); // Sum(105) res[106] = fma52lo(res[106], a[51], a[55]); // Sum(106) res[107] = fma52hi(res[107], a[51], a[55]); // Sum(106) res[107] = fma52lo(res[107], a[52], a[55]); // Sum(107) res[108] = fma52hi(res[108], a[52], a[55]); // Sum(107) res[96] = fma52lo(res[96], a[40], a[56]); // Sum(96) res[97] = fma52hi(res[97], a[40], a[56]); // Sum(96) res[97] = fma52lo(res[97], a[41], a[56]); // Sum(97) res[98] = fma52hi(res[98], a[41], a[56]); // Sum(97) res[98] = fma52lo(res[98], a[42], a[56]); // Sum(98) res[99] = fma52hi(res[99], a[42], a[56]); // Sum(98) res[99] = fma52lo(res[99], a[43], a[56]); // Sum(99) res[100] = fma52hi(res[100], a[43], a[56]); // Sum(99) res[100] = fma52lo(res[100], a[44], a[56]); // Sum(100) res[101] = fma52hi(res[101], a[44], a[56]); // Sum(100) res[101] = fma52lo(res[101], a[45], a[56]); // Sum(101) res[102] = fma52hi(res[102], a[45], a[56]); // Sum(101) res[102] = fma52lo(res[102], a[46], a[56]); // Sum(102) res[103] = fma52hi(res[103], a[46], a[56]); // Sum(102) res[103] = fma52lo(res[103], a[47], a[56]); // Sum(103) res[104] = fma52hi(res[104], a[47], a[56]); // Sum(103) res[104] = fma52lo(res[104], a[48], a[56]); // Sum(104) res[105] = fma52hi(res[105], a[48], a[56]); // Sum(104) res[105] = fma52lo(res[105], a[49], a[56]); // Sum(105) res[106] = fma52hi(res[106], a[49], a[56]); // Sum(105) res[106] = fma52lo(res[106], a[50], a[56]); // Sum(106) res[107] = fma52hi(res[107], a[50], a[56]); // Sum(106) res[107] = fma52lo(res[107], a[51], a[56]); // Sum(107) res[108] = fma52hi(res[108], a[51], a[56]); // Sum(107) res[96] = fma52lo(res[96], a[39], a[57]); // Sum(96) res[97] = fma52hi(res[97], a[39], a[57]); // Sum(96) res[97] = fma52lo(res[97], a[40], a[57]); // Sum(97) res[98] = fma52hi(res[98], a[40], a[57]); // Sum(97) res[98] = fma52lo(res[98], a[41], a[57]); // Sum(98) res[99] = fma52hi(res[99], a[41], a[57]); // Sum(98) res[99] = fma52lo(res[99], a[42], a[57]); // Sum(99) res[100] = fma52hi(res[100], a[42], a[57]); // Sum(99) res[100] = fma52lo(res[100], a[43], a[57]); // Sum(100) res[101] = fma52hi(res[101], a[43], a[57]); // Sum(100) res[101] = fma52lo(res[101], a[44], a[57]); // Sum(101) res[102] = fma52hi(res[102], a[44], a[57]); // Sum(101) res[102] = fma52lo(res[102], a[45], a[57]); // Sum(102) res[103] = fma52hi(res[103], a[45], a[57]); // Sum(102) res[103] = fma52lo(res[103], a[46], a[57]); // Sum(103) res[104] = fma52hi(res[104], a[46], a[57]); // Sum(103) res[104] = fma52lo(res[104], a[47], a[57]); // Sum(104) res[105] = fma52hi(res[105], a[47], a[57]); // Sum(104) res[105] = fma52lo(res[105], a[48], a[57]); // Sum(105) res[106] = fma52hi(res[106], a[48], a[57]); // Sum(105) res[106] = fma52lo(res[106], a[49], a[57]); // Sum(106) res[107] = fma52hi(res[107], a[49], a[57]); // Sum(106) res[107] = fma52lo(res[107], a[50], a[57]); // Sum(107) res[108] = fma52hi(res[108], a[50], a[57]); // Sum(107) res[96] = fma52lo(res[96], a[38], a[58]); // Sum(96) res[97] = fma52hi(res[97], a[38], a[58]); // Sum(96) res[97] = fma52lo(res[97], a[39], a[58]); // Sum(97) res[98] = fma52hi(res[98], a[39], a[58]); // Sum(97) res[98] = fma52lo(res[98], a[40], a[58]); // Sum(98) res[99] = fma52hi(res[99], a[40], a[58]); // Sum(98) res[99] = fma52lo(res[99], a[41], a[58]); // Sum(99) res[100] = fma52hi(res[100], a[41], a[58]); // Sum(99) res[100] = fma52lo(res[100], a[42], a[58]); // Sum(100) res[101] = fma52hi(res[101], a[42], a[58]); // Sum(100) res[101] = fma52lo(res[101], a[43], a[58]); // Sum(101) res[102] = fma52hi(res[102], a[43], a[58]); // Sum(101) res[102] = fma52lo(res[102], a[44], a[58]); // Sum(102) res[103] = fma52hi(res[103], a[44], a[58]); // Sum(102) res[103] = fma52lo(res[103], a[45], a[58]); // Sum(103) res[104] = fma52hi(res[104], a[45], a[58]); // Sum(103) res[104] = fma52lo(res[104], a[46], a[58]); // Sum(104) res[105] = fma52hi(res[105], a[46], a[58]); // Sum(104) res[105] = fma52lo(res[105], a[47], a[58]); // Sum(105) res[106] = fma52hi(res[106], a[47], a[58]); // Sum(105) res[106] = fma52lo(res[106], a[48], a[58]); // Sum(106) res[107] = fma52hi(res[107], a[48], a[58]); // Sum(106) res[107] = fma52lo(res[107], a[49], a[58]); // Sum(107) res[108] = fma52hi(res[108], a[49], a[58]); // Sum(107) res[96] = fma52lo(res[96], a[37], a[59]); // Sum(96) res[97] = fma52hi(res[97], a[37], a[59]); // Sum(96) res[97] = fma52lo(res[97], a[38], a[59]); // Sum(97) res[98] = fma52hi(res[98], a[38], a[59]); // Sum(97) res[98] = fma52lo(res[98], a[39], a[59]); // Sum(98) res[99] = fma52hi(res[99], a[39], a[59]); // Sum(98) res[99] = fma52lo(res[99], a[40], a[59]); // Sum(99) res[100] = fma52hi(res[100], a[40], a[59]); // Sum(99) res[100] = fma52lo(res[100], a[41], a[59]); // Sum(100) res[101] = fma52hi(res[101], a[41], a[59]); // Sum(100) res[101] = fma52lo(res[101], a[42], a[59]); // Sum(101) res[102] = fma52hi(res[102], a[42], a[59]); // Sum(101) res[102] = fma52lo(res[102], a[43], a[59]); // Sum(102) res[103] = fma52hi(res[103], a[43], a[59]); // Sum(102) res[103] = fma52lo(res[103], a[44], a[59]); // Sum(103) res[104] = fma52hi(res[104], a[44], a[59]); // Sum(103) res[104] = fma52lo(res[104], a[45], a[59]); // Sum(104) res[105] = fma52hi(res[105], a[45], a[59]); // Sum(104) res[105] = fma52lo(res[105], a[46], a[59]); // Sum(105) res[106] = fma52hi(res[106], a[46], a[59]); // Sum(105) res[106] = fma52lo(res[106], a[47], a[59]); // Sum(106) res[107] = fma52hi(res[107], a[47], a[59]); // Sum(106) res[107] = fma52lo(res[107], a[48], a[59]); // Sum(107) res[108] = fma52hi(res[108], a[48], a[59]); // Sum(107) res[96] = fma52lo(res[96], a[36], a[60]); // Sum(96) res[97] = fma52hi(res[97], a[36], a[60]); // Sum(96) res[97] = fma52lo(res[97], a[37], a[60]); // Sum(97) res[98] = fma52hi(res[98], a[37], a[60]); // Sum(97) res[98] = fma52lo(res[98], a[38], a[60]); // Sum(98) res[99] = fma52hi(res[99], a[38], a[60]); // Sum(98) res[99] = fma52lo(res[99], a[39], a[60]); // Sum(99) res[100] = fma52hi(res[100], a[39], a[60]); // Sum(99) res[100] = fma52lo(res[100], a[40], a[60]); // Sum(100) res[101] = fma52hi(res[101], a[40], a[60]); // Sum(100) res[101] = fma52lo(res[101], a[41], a[60]); // Sum(101) res[102] = fma52hi(res[102], a[41], a[60]); // Sum(101) res[102] = fma52lo(res[102], a[42], a[60]); // Sum(102) res[103] = fma52hi(res[103], a[42], a[60]); // Sum(102) res[103] = fma52lo(res[103], a[43], a[60]); // Sum(103) res[104] = fma52hi(res[104], a[43], a[60]); // Sum(103) res[104] = fma52lo(res[104], a[44], a[60]); // Sum(104) res[105] = fma52hi(res[105], a[44], a[60]); // Sum(104) res[105] = fma52lo(res[105], a[45], a[60]); // Sum(105) res[106] = fma52hi(res[106], a[45], a[60]); // Sum(105) res[106] = fma52lo(res[106], a[46], a[60]); // Sum(106) res[107] = fma52hi(res[107], a[46], a[60]); // Sum(106) res[107] = fma52lo(res[107], a[47], a[60]); // Sum(107) res[108] = fma52hi(res[108], a[47], a[60]); // Sum(107) res[96] = fma52lo(res[96], a[35], a[61]); // Sum(96) res[97] = fma52hi(res[97], a[35], a[61]); // Sum(96) res[97] = fma52lo(res[97], a[36], a[61]); // Sum(97) res[98] = fma52hi(res[98], a[36], a[61]); // Sum(97) res[98] = fma52lo(res[98], a[37], a[61]); // Sum(98) res[99] = fma52hi(res[99], a[37], a[61]); // Sum(98) res[99] = fma52lo(res[99], a[38], a[61]); // Sum(99) res[100] = fma52hi(res[100], a[38], a[61]); // Sum(99) res[100] = fma52lo(res[100], a[39], a[61]); // Sum(100) res[101] = fma52hi(res[101], a[39], a[61]); // Sum(100) res[101] = fma52lo(res[101], a[40], a[61]); // Sum(101) res[102] = fma52hi(res[102], a[40], a[61]); // Sum(101) res[102] = fma52lo(res[102], a[41], a[61]); // Sum(102) res[103] = fma52hi(res[103], a[41], a[61]); // Sum(102) res[103] = fma52lo(res[103], a[42], a[61]); // Sum(103) res[104] = fma52hi(res[104], a[42], a[61]); // Sum(103) res[104] = fma52lo(res[104], a[43], a[61]); // Sum(104) res[105] = fma52hi(res[105], a[43], a[61]); // Sum(104) res[105] = fma52lo(res[105], a[44], a[61]); // Sum(105) res[106] = fma52hi(res[106], a[44], a[61]); // Sum(105) res[106] = fma52lo(res[106], a[45], a[61]); // Sum(106) res[107] = fma52hi(res[107], a[45], a[61]); // Sum(106) res[107] = fma52lo(res[107], a[46], a[61]); // Sum(107) res[108] = fma52hi(res[108], a[46], a[61]); // Sum(107) res[96] = fma52lo(res[96], a[34], a[62]); // Sum(96) res[97] = fma52hi(res[97], a[34], a[62]); // Sum(96) res[97] = fma52lo(res[97], a[35], a[62]); // Sum(97) res[98] = fma52hi(res[98], a[35], a[62]); // Sum(97) res[98] = fma52lo(res[98], a[36], a[62]); // Sum(98) res[99] = fma52hi(res[99], a[36], a[62]); // Sum(98) res[99] = fma52lo(res[99], a[37], a[62]); // Sum(99) res[100] = fma52hi(res[100], a[37], a[62]); // Sum(99) res[100] = fma52lo(res[100], a[38], a[62]); // Sum(100) res[101] = fma52hi(res[101], a[38], a[62]); // Sum(100) res[101] = fma52lo(res[101], a[39], a[62]); // Sum(101) res[102] = fma52hi(res[102], a[39], a[62]); // Sum(101) res[102] = fma52lo(res[102], a[40], a[62]); // Sum(102) res[103] = fma52hi(res[103], a[40], a[62]); // Sum(102) res[103] = fma52lo(res[103], a[41], a[62]); // Sum(103) res[104] = fma52hi(res[104], a[41], a[62]); // Sum(103) res[104] = fma52lo(res[104], a[42], a[62]); // Sum(104) res[105] = fma52hi(res[105], a[42], a[62]); // Sum(104) res[105] = fma52lo(res[105], a[43], a[62]); // Sum(105) res[106] = fma52hi(res[106], a[43], a[62]); // Sum(105) res[106] = fma52lo(res[106], a[44], a[62]); // Sum(106) res[107] = fma52hi(res[107], a[44], a[62]); // Sum(106) res[107] = fma52lo(res[107], a[45], a[62]); // Sum(107) res[108] = fma52hi(res[108], a[45], a[62]); // Sum(107) res[96] = fma52lo(res[96], a[33], a[63]); // Sum(96) res[97] = fma52hi(res[97], a[33], a[63]); // Sum(96) res[97] = fma52lo(res[97], a[34], a[63]); // Sum(97) res[98] = fma52hi(res[98], a[34], a[63]); // Sum(97) res[98] = fma52lo(res[98], a[35], a[63]); // Sum(98) res[99] = fma52hi(res[99], a[35], a[63]); // Sum(98) res[99] = fma52lo(res[99], a[36], a[63]); // Sum(99) res[100] = fma52hi(res[100], a[36], a[63]); // Sum(99) res[100] = fma52lo(res[100], a[37], a[63]); // Sum(100) res[101] = fma52hi(res[101], a[37], a[63]); // Sum(100) res[101] = fma52lo(res[101], a[38], a[63]); // Sum(101) res[102] = fma52hi(res[102], a[38], a[63]); // Sum(101) res[102] = fma52lo(res[102], a[39], a[63]); // Sum(102) res[103] = fma52hi(res[103], a[39], a[63]); // Sum(102) res[103] = fma52lo(res[103], a[40], a[63]); // Sum(103) res[104] = fma52hi(res[104], a[40], a[63]); // Sum(103) res[104] = fma52lo(res[104], a[41], a[63]); // Sum(104) res[105] = fma52hi(res[105], a[41], a[63]); // Sum(104) res[105] = fma52lo(res[105], a[42], a[63]); // Sum(105) res[106] = fma52hi(res[106], a[42], a[63]); // Sum(105) res[106] = fma52lo(res[106], a[43], a[63]); // Sum(106) res[107] = fma52hi(res[107], a[43], a[63]); // Sum(106) res[107] = fma52lo(res[107], a[44], a[63]); // Sum(107) res[108] = fma52hi(res[108], a[44], a[63]); // Sum(107) res[96] = fma52lo(res[96], a[32], a[64]); // Sum(96) res[97] = fma52hi(res[97], a[32], a[64]); // Sum(96) res[97] = fma52lo(res[97], a[33], a[64]); // Sum(97) res[98] = fma52hi(res[98], a[33], a[64]); // Sum(97) res[98] = fma52lo(res[98], a[34], a[64]); // Sum(98) res[99] = fma52hi(res[99], a[34], a[64]); // Sum(98) res[99] = fma52lo(res[99], a[35], a[64]); // Sum(99) res[100] = fma52hi(res[100], a[35], a[64]); // Sum(99) res[100] = fma52lo(res[100], a[36], a[64]); // Sum(100) res[101] = fma52hi(res[101], a[36], a[64]); // Sum(100) res[101] = fma52lo(res[101], a[37], a[64]); // Sum(101) res[102] = fma52hi(res[102], a[37], a[64]); // Sum(101) res[102] = fma52lo(res[102], a[38], a[64]); // Sum(102) res[103] = fma52hi(res[103], a[38], a[64]); // Sum(102) res[103] = fma52lo(res[103], a[39], a[64]); // Sum(103) res[104] = fma52hi(res[104], a[39], a[64]); // Sum(103) res[104] = fma52lo(res[104], a[40], a[64]); // Sum(104) res[105] = fma52hi(res[105], a[40], a[64]); // Sum(104) res[105] = fma52lo(res[105], a[41], a[64]); // Sum(105) res[106] = fma52hi(res[106], a[41], a[64]); // Sum(105) res[106] = fma52lo(res[106], a[42], a[64]); // Sum(106) res[107] = fma52hi(res[107], a[42], a[64]); // Sum(106) res[107] = fma52lo(res[107], a[43], a[64]); // Sum(107) res[108] = fma52hi(res[108], a[43], a[64]); // Sum(107) res[96] = fma52lo(res[96], a[31], a[65]); // Sum(96) res[97] = fma52hi(res[97], a[31], a[65]); // Sum(96) res[97] = fma52lo(res[97], a[32], a[65]); // Sum(97) res[98] = fma52hi(res[98], a[32], a[65]); // Sum(97) res[98] = fma52lo(res[98], a[33], a[65]); // Sum(98) res[99] = fma52hi(res[99], a[33], a[65]); // Sum(98) res[99] = fma52lo(res[99], a[34], a[65]); // Sum(99) res[100] = fma52hi(res[100], a[34], a[65]); // Sum(99) res[100] = fma52lo(res[100], a[35], a[65]); // Sum(100) res[101] = fma52hi(res[101], a[35], a[65]); // Sum(100) res[101] = fma52lo(res[101], a[36], a[65]); // Sum(101) res[102] = fma52hi(res[102], a[36], a[65]); // Sum(101) res[102] = fma52lo(res[102], a[37], a[65]); // Sum(102) res[103] = fma52hi(res[103], a[37], a[65]); // Sum(102) res[103] = fma52lo(res[103], a[38], a[65]); // Sum(103) res[104] = fma52hi(res[104], a[38], a[65]); // Sum(103) res[104] = fma52lo(res[104], a[39], a[65]); // Sum(104) res[105] = fma52hi(res[105], a[39], a[65]); // Sum(104) res[105] = fma52lo(res[105], a[40], a[65]); // Sum(105) res[106] = fma52hi(res[106], a[40], a[65]); // Sum(105) res[106] = fma52lo(res[106], a[41], a[65]); // Sum(106) res[107] = fma52hi(res[107], a[41], a[65]); // Sum(106) res[107] = fma52lo(res[107], a[42], a[65]); // Sum(107) res[108] = fma52hi(res[108], a[42], a[65]); // Sum(107) res[96] = fma52lo(res[96], a[30], a[66]); // Sum(96) res[97] = fma52hi(res[97], a[30], a[66]); // Sum(96) res[97] = fma52lo(res[97], a[31], a[66]); // Sum(97) res[98] = fma52hi(res[98], a[31], a[66]); // Sum(97) res[98] = fma52lo(res[98], a[32], a[66]); // Sum(98) res[99] = fma52hi(res[99], a[32], a[66]); // Sum(98) res[99] = fma52lo(res[99], a[33], a[66]); // Sum(99) res[100] = fma52hi(res[100], a[33], a[66]); // Sum(99) res[100] = fma52lo(res[100], a[34], a[66]); // Sum(100) res[101] = fma52hi(res[101], a[34], a[66]); // Sum(100) res[101] = fma52lo(res[101], a[35], a[66]); // Sum(101) res[102] = fma52hi(res[102], a[35], a[66]); // Sum(101) res[102] = fma52lo(res[102], a[36], a[66]); // Sum(102) res[103] = fma52hi(res[103], a[36], a[66]); // Sum(102) res[103] = fma52lo(res[103], a[37], a[66]); // Sum(103) res[104] = fma52hi(res[104], a[37], a[66]); // Sum(103) res[104] = fma52lo(res[104], a[38], a[66]); // Sum(104) res[105] = fma52hi(res[105], a[38], a[66]); // Sum(104) res[105] = fma52lo(res[105], a[39], a[66]); // Sum(105) res[106] = fma52hi(res[106], a[39], a[66]); // Sum(105) res[106] = fma52lo(res[106], a[40], a[66]); // Sum(106) res[107] = fma52hi(res[107], a[40], a[66]); // Sum(106) res[107] = fma52lo(res[107], a[41], a[66]); // Sum(107) res[108] = fma52hi(res[108], a[41], a[66]); // Sum(107) res[96] = fma52lo(res[96], a[29], a[67]); // Sum(96) res[97] = fma52hi(res[97], a[29], a[67]); // Sum(96) res[97] = fma52lo(res[97], a[30], a[67]); // Sum(97) res[98] = fma52hi(res[98], a[30], a[67]); // Sum(97) res[98] = fma52lo(res[98], a[31], a[67]); // Sum(98) res[99] = fma52hi(res[99], a[31], a[67]); // Sum(98) res[99] = fma52lo(res[99], a[32], a[67]); // Sum(99) res[100] = fma52hi(res[100], a[32], a[67]); // Sum(99) res[100] = fma52lo(res[100], a[33], a[67]); // Sum(100) res[101] = fma52hi(res[101], a[33], a[67]); // Sum(100) res[101] = fma52lo(res[101], a[34], a[67]); // Sum(101) res[102] = fma52hi(res[102], a[34], a[67]); // Sum(101) res[102] = fma52lo(res[102], a[35], a[67]); // Sum(102) res[103] = fma52hi(res[103], a[35], a[67]); // Sum(102) res[103] = fma52lo(res[103], a[36], a[67]); // Sum(103) res[104] = fma52hi(res[104], a[36], a[67]); // Sum(103) res[104] = fma52lo(res[104], a[37], a[67]); // Sum(104) res[105] = fma52hi(res[105], a[37], a[67]); // Sum(104) res[105] = fma52lo(res[105], a[38], a[67]); // Sum(105) res[106] = fma52hi(res[106], a[38], a[67]); // Sum(105) res[106] = fma52lo(res[106], a[39], a[67]); // Sum(106) res[107] = fma52hi(res[107], a[39], a[67]); // Sum(106) res[107] = fma52lo(res[107], a[40], a[67]); // Sum(107) res[108] = fma52hi(res[108], a[40], a[67]); // Sum(107) res[96] = fma52lo(res[96], a[28], a[68]); // Sum(96) res[97] = fma52hi(res[97], a[28], a[68]); // Sum(96) res[97] = fma52lo(res[97], a[29], a[68]); // Sum(97) res[98] = fma52hi(res[98], a[29], a[68]); // Sum(97) res[98] = fma52lo(res[98], a[30], a[68]); // Sum(98) res[99] = fma52hi(res[99], a[30], a[68]); // Sum(98) res[99] = fma52lo(res[99], a[31], a[68]); // Sum(99) res[100] = fma52hi(res[100], a[31], a[68]); // Sum(99) res[100] = fma52lo(res[100], a[32], a[68]); // Sum(100) res[101] = fma52hi(res[101], a[32], a[68]); // Sum(100) res[101] = fma52lo(res[101], a[33], a[68]); // Sum(101) res[102] = fma52hi(res[102], a[33], a[68]); // Sum(101) res[102] = fma52lo(res[102], a[34], a[68]); // Sum(102) res[103] = fma52hi(res[103], a[34], a[68]); // Sum(102) res[103] = fma52lo(res[103], a[35], a[68]); // Sum(103) res[104] = fma52hi(res[104], a[35], a[68]); // Sum(103) res[104] = fma52lo(res[104], a[36], a[68]); // Sum(104) res[105] = fma52hi(res[105], a[36], a[68]); // Sum(104) res[105] = fma52lo(res[105], a[37], a[68]); // Sum(105) res[106] = fma52hi(res[106], a[37], a[68]); // Sum(105) res[106] = fma52lo(res[106], a[38], a[68]); // Sum(106) res[107] = fma52hi(res[107], a[38], a[68]); // Sum(106) res[107] = fma52lo(res[107], a[39], a[68]); // Sum(107) res[108] = fma52hi(res[108], a[39], a[68]); // Sum(107) res[96] = fma52lo(res[96], a[27], a[69]); // Sum(96) res[97] = fma52hi(res[97], a[27], a[69]); // Sum(96) res[97] = fma52lo(res[97], a[28], a[69]); // Sum(97) res[98] = fma52hi(res[98], a[28], a[69]); // Sum(97) res[98] = fma52lo(res[98], a[29], a[69]); // Sum(98) res[99] = fma52hi(res[99], a[29], a[69]); // Sum(98) res[99] = fma52lo(res[99], a[30], a[69]); // Sum(99) res[100] = fma52hi(res[100], a[30], a[69]); // Sum(99) res[100] = fma52lo(res[100], a[31], a[69]); // Sum(100) res[101] = fma52hi(res[101], a[31], a[69]); // Sum(100) res[101] = fma52lo(res[101], a[32], a[69]); // Sum(101) res[102] = fma52hi(res[102], a[32], a[69]); // Sum(101) res[102] = fma52lo(res[102], a[33], a[69]); // Sum(102) res[103] = fma52hi(res[103], a[33], a[69]); // Sum(102) res[103] = fma52lo(res[103], a[34], a[69]); // Sum(103) res[104] = fma52hi(res[104], a[34], a[69]); // Sum(103) res[104] = fma52lo(res[104], a[35], a[69]); // Sum(104) res[105] = fma52hi(res[105], a[35], a[69]); // Sum(104) res[105] = fma52lo(res[105], a[36], a[69]); // Sum(105) res[106] = fma52hi(res[106], a[36], a[69]); // Sum(105) res[106] = fma52lo(res[106], a[37], a[69]); // Sum(106) res[107] = fma52hi(res[107], a[37], a[69]); // Sum(106) res[107] = fma52lo(res[107], a[38], a[69]); // Sum(107) res[108] = fma52hi(res[108], a[38], a[69]); // Sum(107) res[96] = fma52lo(res[96], a[26], a[70]); // Sum(96) res[97] = fma52hi(res[97], a[26], a[70]); // Sum(96) res[97] = fma52lo(res[97], a[27], a[70]); // Sum(97) res[98] = fma52hi(res[98], a[27], a[70]); // Sum(97) res[98] = fma52lo(res[98], a[28], a[70]); // Sum(98) res[99] = fma52hi(res[99], a[28], a[70]); // Sum(98) res[99] = fma52lo(res[99], a[29], a[70]); // Sum(99) res[100] = fma52hi(res[100], a[29], a[70]); // Sum(99) res[100] = fma52lo(res[100], a[30], a[70]); // Sum(100) res[101] = fma52hi(res[101], a[30], a[70]); // Sum(100) res[101] = fma52lo(res[101], a[31], a[70]); // Sum(101) res[102] = fma52hi(res[102], a[31], a[70]); // Sum(101) res[102] = fma52lo(res[102], a[32], a[70]); // Sum(102) res[103] = fma52hi(res[103], a[32], a[70]); // Sum(102) res[103] = fma52lo(res[103], a[33], a[70]); // Sum(103) res[104] = fma52hi(res[104], a[33], a[70]); // Sum(103) res[104] = fma52lo(res[104], a[34], a[70]); // Sum(104) res[105] = fma52hi(res[105], a[34], a[70]); // Sum(104) res[105] = fma52lo(res[105], a[35], a[70]); // Sum(105) res[106] = fma52hi(res[106], a[35], a[70]); // Sum(105) res[106] = fma52lo(res[106], a[36], a[70]); // Sum(106) res[107] = fma52hi(res[107], a[36], a[70]); // Sum(106) res[107] = fma52lo(res[107], a[37], a[70]); // Sum(107) res[108] = fma52hi(res[108], a[37], a[70]); // Sum(107) res[96] = fma52lo(res[96], a[25], a[71]); // Sum(96) res[97] = fma52hi(res[97], a[25], a[71]); // Sum(96) res[97] = fma52lo(res[97], a[26], a[71]); // Sum(97) res[98] = fma52hi(res[98], a[26], a[71]); // Sum(97) res[98] = fma52lo(res[98], a[27], a[71]); // Sum(98) res[99] = fma52hi(res[99], a[27], a[71]); // Sum(98) res[99] = fma52lo(res[99], a[28], a[71]); // Sum(99) res[100] = fma52hi(res[100], a[28], a[71]); // Sum(99) res[100] = fma52lo(res[100], a[29], a[71]); // Sum(100) res[101] = fma52hi(res[101], a[29], a[71]); // Sum(100) res[101] = fma52lo(res[101], a[30], a[71]); // Sum(101) res[102] = fma52hi(res[102], a[30], a[71]); // Sum(101) res[102] = fma52lo(res[102], a[31], a[71]); // Sum(102) res[103] = fma52hi(res[103], a[31], a[71]); // Sum(102) res[103] = fma52lo(res[103], a[32], a[71]); // Sum(103) res[104] = fma52hi(res[104], a[32], a[71]); // Sum(103) res[104] = fma52lo(res[104], a[33], a[71]); // Sum(104) res[105] = fma52hi(res[105], a[33], a[71]); // Sum(104) res[105] = fma52lo(res[105], a[34], a[71]); // Sum(105) res[106] = fma52hi(res[106], a[34], a[71]); // Sum(105) res[106] = fma52lo(res[106], a[35], a[71]); // Sum(106) res[107] = fma52hi(res[107], a[35], a[71]); // Sum(106) res[107] = fma52lo(res[107], a[36], a[71]); // Sum(107) res[108] = fma52hi(res[108], a[36], a[71]); // Sum(107) res[96] = fma52lo(res[96], a[24], a[72]); // Sum(96) res[97] = fma52hi(res[97], a[24], a[72]); // Sum(96) res[97] = fma52lo(res[97], a[25], a[72]); // Sum(97) res[98] = fma52hi(res[98], a[25], a[72]); // Sum(97) res[98] = fma52lo(res[98], a[26], a[72]); // Sum(98) res[99] = fma52hi(res[99], a[26], a[72]); // Sum(98) res[99] = fma52lo(res[99], a[27], a[72]); // Sum(99) res[100] = fma52hi(res[100], a[27], a[72]); // Sum(99) res[100] = fma52lo(res[100], a[28], a[72]); // Sum(100) res[101] = fma52hi(res[101], a[28], a[72]); // Sum(100) res[101] = fma52lo(res[101], a[29], a[72]); // Sum(101) res[102] = fma52hi(res[102], a[29], a[72]); // Sum(101) res[102] = fma52lo(res[102], a[30], a[72]); // Sum(102) res[103] = fma52hi(res[103], a[30], a[72]); // Sum(102) res[103] = fma52lo(res[103], a[31], a[72]); // Sum(103) res[104] = fma52hi(res[104], a[31], a[72]); // Sum(103) res[104] = fma52lo(res[104], a[32], a[72]); // Sum(104) res[105] = fma52hi(res[105], a[32], a[72]); // Sum(104) res[105] = fma52lo(res[105], a[33], a[72]); // Sum(105) res[106] = fma52hi(res[106], a[33], a[72]); // Sum(105) res[106] = fma52lo(res[106], a[34], a[72]); // Sum(106) res[107] = fma52hi(res[107], a[34], a[72]); // Sum(106) res[107] = fma52lo(res[107], a[35], a[72]); // Sum(107) res[108] = fma52hi(res[108], a[35], a[72]); // Sum(107) res[96] = fma52lo(res[96], a[23], a[73]); // Sum(96) res[97] = fma52hi(res[97], a[23], a[73]); // Sum(96) res[97] = fma52lo(res[97], a[24], a[73]); // Sum(97) res[98] = fma52hi(res[98], a[24], a[73]); // Sum(97) res[98] = fma52lo(res[98], a[25], a[73]); // Sum(98) res[99] = fma52hi(res[99], a[25], a[73]); // Sum(98) res[99] = fma52lo(res[99], a[26], a[73]); // Sum(99) res[100] = fma52hi(res[100], a[26], a[73]); // Sum(99) res[100] = fma52lo(res[100], a[27], a[73]); // Sum(100) res[101] = fma52hi(res[101], a[27], a[73]); // Sum(100) res[101] = fma52lo(res[101], a[28], a[73]); // Sum(101) res[102] = fma52hi(res[102], a[28], a[73]); // Sum(101) res[102] = fma52lo(res[102], a[29], a[73]); // Sum(102) res[103] = fma52hi(res[103], a[29], a[73]); // Sum(102) res[103] = fma52lo(res[103], a[30], a[73]); // Sum(103) res[104] = fma52hi(res[104], a[30], a[73]); // Sum(103) res[104] = fma52lo(res[104], a[31], a[73]); // Sum(104) res[105] = fma52hi(res[105], a[31], a[73]); // Sum(104) res[105] = fma52lo(res[105], a[32], a[73]); // Sum(105) res[106] = fma52hi(res[106], a[32], a[73]); // Sum(105) res[106] = fma52lo(res[106], a[33], a[73]); // Sum(106) res[107] = fma52hi(res[107], a[33], a[73]); // Sum(106) res[107] = fma52lo(res[107], a[34], a[73]); // Sum(107) res[108] = fma52hi(res[108], a[34], a[73]); // Sum(107) res[96] = fma52lo(res[96], a[22], a[74]); // Sum(96) res[97] = fma52hi(res[97], a[22], a[74]); // Sum(96) res[97] = fma52lo(res[97], a[23], a[74]); // Sum(97) res[98] = fma52hi(res[98], a[23], a[74]); // Sum(97) res[98] = fma52lo(res[98], a[24], a[74]); // Sum(98) res[99] = fma52hi(res[99], a[24], a[74]); // Sum(98) res[99] = fma52lo(res[99], a[25], a[74]); // Sum(99) res[100] = fma52hi(res[100], a[25], a[74]); // Sum(99) res[100] = fma52lo(res[100], a[26], a[74]); // Sum(100) res[101] = fma52hi(res[101], a[26], a[74]); // Sum(100) res[101] = fma52lo(res[101], a[27], a[74]); // Sum(101) res[102] = fma52hi(res[102], a[27], a[74]); // Sum(101) res[102] = fma52lo(res[102], a[28], a[74]); // Sum(102) res[103] = fma52hi(res[103], a[28], a[74]); // Sum(102) res[103] = fma52lo(res[103], a[29], a[74]); // Sum(103) res[104] = fma52hi(res[104], a[29], a[74]); // Sum(103) res[104] = fma52lo(res[104], a[30], a[74]); // Sum(104) res[105] = fma52hi(res[105], a[30], a[74]); // Sum(104) res[105] = fma52lo(res[105], a[31], a[74]); // Sum(105) res[106] = fma52hi(res[106], a[31], a[74]); // Sum(105) res[106] = fma52lo(res[106], a[32], a[74]); // Sum(106) res[107] = fma52hi(res[107], a[32], a[74]); // Sum(106) res[107] = fma52lo(res[107], a[33], a[74]); // Sum(107) res[108] = fma52hi(res[108], a[33], a[74]); // Sum(107) res[96] = fma52lo(res[96], a[21], a[75]); // Sum(96) res[97] = fma52hi(res[97], a[21], a[75]); // Sum(96) res[97] = fma52lo(res[97], a[22], a[75]); // Sum(97) res[98] = fma52hi(res[98], a[22], a[75]); // Sum(97) res[98] = fma52lo(res[98], a[23], a[75]); // Sum(98) res[99] = fma52hi(res[99], a[23], a[75]); // Sum(98) res[99] = fma52lo(res[99], a[24], a[75]); // Sum(99) res[100] = fma52hi(res[100], a[24], a[75]); // Sum(99) res[100] = fma52lo(res[100], a[25], a[75]); // Sum(100) res[101] = fma52hi(res[101], a[25], a[75]); // Sum(100) res[101] = fma52lo(res[101], a[26], a[75]); // Sum(101) res[102] = fma52hi(res[102], a[26], a[75]); // Sum(101) res[102] = fma52lo(res[102], a[27], a[75]); // Sum(102) res[103] = fma52hi(res[103], a[27], a[75]); // Sum(102) res[103] = fma52lo(res[103], a[28], a[75]); // Sum(103) res[104] = fma52hi(res[104], a[28], a[75]); // Sum(103) res[104] = fma52lo(res[104], a[29], a[75]); // Sum(104) res[105] = fma52hi(res[105], a[29], a[75]); // Sum(104) res[105] = fma52lo(res[105], a[30], a[75]); // Sum(105) res[106] = fma52hi(res[106], a[30], a[75]); // Sum(105) res[106] = fma52lo(res[106], a[31], a[75]); // Sum(106) res[107] = fma52hi(res[107], a[31], a[75]); // Sum(106) res[107] = fma52lo(res[107], a[32], a[75]); // Sum(107) res[108] = fma52hi(res[108], a[32], a[75]); // Sum(107) res[96] = fma52lo(res[96], a[20], a[76]); // Sum(96) res[97] = fma52hi(res[97], a[20], a[76]); // Sum(96) res[97] = fma52lo(res[97], a[21], a[76]); // Sum(97) res[98] = fma52hi(res[98], a[21], a[76]); // Sum(97) res[98] = fma52lo(res[98], a[22], a[76]); // Sum(98) res[99] = fma52hi(res[99], a[22], a[76]); // Sum(98) res[99] = fma52lo(res[99], a[23], a[76]); // Sum(99) res[100] = fma52hi(res[100], a[23], a[76]); // Sum(99) res[100] = fma52lo(res[100], a[24], a[76]); // Sum(100) res[101] = fma52hi(res[101], a[24], a[76]); // Sum(100) res[101] = fma52lo(res[101], a[25], a[76]); // Sum(101) res[102] = fma52hi(res[102], a[25], a[76]); // Sum(101) res[102] = fma52lo(res[102], a[26], a[76]); // Sum(102) res[103] = fma52hi(res[103], a[26], a[76]); // Sum(102) res[103] = fma52lo(res[103], a[27], a[76]); // Sum(103) res[104] = fma52hi(res[104], a[27], a[76]); // Sum(103) res[104] = fma52lo(res[104], a[28], a[76]); // Sum(104) res[105] = fma52hi(res[105], a[28], a[76]); // Sum(104) res[105] = fma52lo(res[105], a[29], a[76]); // Sum(105) res[106] = fma52hi(res[106], a[29], a[76]); // Sum(105) res[106] = fma52lo(res[106], a[30], a[76]); // Sum(106) res[107] = fma52hi(res[107], a[30], a[76]); // Sum(106) res[107] = fma52lo(res[107], a[31], a[76]); // Sum(107) res[108] = fma52hi(res[108], a[31], a[76]); // Sum(107) res[96] = fma52lo(res[96], a[19], a[77]); // Sum(96) res[97] = fma52hi(res[97], a[19], a[77]); // Sum(96) res[97] = fma52lo(res[97], a[20], a[77]); // Sum(97) res[98] = fma52hi(res[98], a[20], a[77]); // Sum(97) res[98] = fma52lo(res[98], a[21], a[77]); // Sum(98) res[99] = fma52hi(res[99], a[21], a[77]); // Sum(98) res[99] = fma52lo(res[99], a[22], a[77]); // Sum(99) res[100] = fma52hi(res[100], a[22], a[77]); // Sum(99) res[100] = fma52lo(res[100], a[23], a[77]); // Sum(100) res[101] = fma52hi(res[101], a[23], a[77]); // Sum(100) res[101] = fma52lo(res[101], a[24], a[77]); // Sum(101) res[102] = fma52hi(res[102], a[24], a[77]); // Sum(101) res[102] = fma52lo(res[102], a[25], a[77]); // Sum(102) res[103] = fma52hi(res[103], a[25], a[77]); // Sum(102) res[103] = fma52lo(res[103], a[26], a[77]); // Sum(103) res[104] = fma52hi(res[104], a[26], a[77]); // Sum(103) res[104] = fma52lo(res[104], a[27], a[77]); // Sum(104) res[105] = fma52hi(res[105], a[27], a[77]); // Sum(104) res[105] = fma52lo(res[105], a[28], a[77]); // Sum(105) res[106] = fma52hi(res[106], a[28], a[77]); // Sum(105) res[106] = fma52lo(res[106], a[29], a[77]); // Sum(106) res[107] = fma52hi(res[107], a[29], a[77]); // Sum(106) res[107] = fma52lo(res[107], a[30], a[77]); // Sum(107) res[108] = fma52hi(res[108], a[30], a[77]); // Sum(107) res[96] = fma52lo(res[96], a[18], a[78]); // Sum(96) res[97] = fma52hi(res[97], a[18], a[78]); // Sum(96) res[97] = fma52lo(res[97], a[19], a[78]); // Sum(97) res[98] = fma52hi(res[98], a[19], a[78]); // Sum(97) res[98] = fma52lo(res[98], a[20], a[78]); // Sum(98) res[99] = fma52hi(res[99], a[20], a[78]); // Sum(98) res[99] = fma52lo(res[99], a[21], a[78]); // Sum(99) res[100] = fma52hi(res[100], a[21], a[78]); // Sum(99) res[100] = fma52lo(res[100], a[22], a[78]); // Sum(100) res[101] = fma52hi(res[101], a[22], a[78]); // Sum(100) res[101] = fma52lo(res[101], a[23], a[78]); // Sum(101) res[102] = fma52hi(res[102], a[23], a[78]); // Sum(101) res[102] = fma52lo(res[102], a[24], a[78]); // Sum(102) res[103] = fma52hi(res[103], a[24], a[78]); // Sum(102) res[103] = fma52lo(res[103], a[25], a[78]); // Sum(103) res[104] = fma52hi(res[104], a[25], a[78]); // Sum(103) res[104] = fma52lo(res[104], a[26], a[78]); // Sum(104) res[105] = fma52hi(res[105], a[26], a[78]); // Sum(104) res[105] = fma52lo(res[105], a[27], a[78]); // Sum(105) res[106] = fma52hi(res[106], a[27], a[78]); // Sum(105) res[106] = fma52lo(res[106], a[28], a[78]); // Sum(106) res[107] = fma52hi(res[107], a[28], a[78]); // Sum(106) res[107] = fma52lo(res[107], a[29], a[78]); // Sum(107) res[108] = fma52hi(res[108], a[29], a[78]); // Sum(107) res[96] = add64(res[96], res[96]); // Double(96) res[97] = add64(res[97], res[97]); // Double(97) res[98] = add64(res[98], res[98]); // Double(98) res[99] = add64(res[99], res[99]); // Double(99) res[100] = add64(res[100], res[100]); // Double(100) res[101] = add64(res[101], res[101]); // Double(101) res[102] = add64(res[102], res[102]); // Double(102) res[103] = add64(res[103], res[103]); // Double(103) res[104] = add64(res[104], res[104]); // Double(104) res[105] = add64(res[105], res[105]); // Double(105) res[106] = add64(res[106], res[106]); // Double(106) res[107] = add64(res[107], res[107]); // Double(107) res[96] = fma52lo(res[96], a[48], a[48]); // Add sqr(96) res[97] = fma52hi(res[97], a[48], a[48]); // Add sqr(96) res[98] = fma52lo(res[98], a[49], a[49]); // Add sqr(98) res[99] = fma52hi(res[99], a[49], a[49]); // Add sqr(98) res[100] = fma52lo(res[100], a[50], a[50]); // Add sqr(100) res[101] = fma52hi(res[101], a[50], a[50]); // Add sqr(100) res[102] = fma52lo(res[102], a[51], a[51]); // Add sqr(102) res[103] = fma52hi(res[103], a[51], a[51]); // Add sqr(102) res[104] = fma52lo(res[104], a[52], a[52]); // Add sqr(104) res[105] = fma52hi(res[105], a[52], a[52]); // Add sqr(104) res[106] = fma52lo(res[106], a[53], a[53]); // Add sqr(106) res[107] = fma52hi(res[107], a[53], a[53]); // Add sqr(106) res[108] = fma52lo(res[108], a[53], a[55]); // Sum(108) res[109] = fma52hi(res[109], a[53], a[55]); // Sum(108) res[109] = fma52lo(res[109], a[54], a[55]); // Sum(109) res[110] = fma52hi(res[110], a[54], a[55]); // Sum(109) res[108] = fma52lo(res[108], a[52], a[56]); // Sum(108) res[109] = fma52hi(res[109], a[52], a[56]); // Sum(108) res[109] = fma52lo(res[109], a[53], a[56]); // Sum(109) res[110] = fma52hi(res[110], a[53], a[56]); // Sum(109) res[110] = fma52lo(res[110], a[54], a[56]); // Sum(110) res[111] = fma52hi(res[111], a[54], a[56]); // Sum(110) res[111] = fma52lo(res[111], a[55], a[56]); // Sum(111) res[112] = fma52hi(res[112], a[55], a[56]); // Sum(111) res[108] = fma52lo(res[108], a[51], a[57]); // Sum(108) res[109] = fma52hi(res[109], a[51], a[57]); // Sum(108) res[109] = fma52lo(res[109], a[52], a[57]); // Sum(109) res[110] = fma52hi(res[110], a[52], a[57]); // Sum(109) res[110] = fma52lo(res[110], a[53], a[57]); // Sum(110) res[111] = fma52hi(res[111], a[53], a[57]); // Sum(110) res[111] = fma52lo(res[111], a[54], a[57]); // Sum(111) res[112] = fma52hi(res[112], a[54], a[57]); // Sum(111) res[112] = fma52lo(res[112], a[55], a[57]); // Sum(112) res[113] = fma52hi(res[113], a[55], a[57]); // Sum(112) res[113] = fma52lo(res[113], a[56], a[57]); // Sum(113) res[114] = fma52hi(res[114], a[56], a[57]); // Sum(113) res[108] = fma52lo(res[108], a[50], a[58]); // Sum(108) res[109] = fma52hi(res[109], a[50], a[58]); // Sum(108) res[109] = fma52lo(res[109], a[51], a[58]); // Sum(109) res[110] = fma52hi(res[110], a[51], a[58]); // Sum(109) res[110] = fma52lo(res[110], a[52], a[58]); // Sum(110) res[111] = fma52hi(res[111], a[52], a[58]); // Sum(110) res[111] = fma52lo(res[111], a[53], a[58]); // Sum(111) res[112] = fma52hi(res[112], a[53], a[58]); // Sum(111) res[112] = fma52lo(res[112], a[54], a[58]); // Sum(112) res[113] = fma52hi(res[113], a[54], a[58]); // Sum(112) res[113] = fma52lo(res[113], a[55], a[58]); // Sum(113) res[114] = fma52hi(res[114], a[55], a[58]); // Sum(113) res[114] = fma52lo(res[114], a[56], a[58]); // Sum(114) res[115] = fma52hi(res[115], a[56], a[58]); // Sum(114) res[115] = fma52lo(res[115], a[57], a[58]); // Sum(115) res[116] = fma52hi(res[116], a[57], a[58]); // Sum(115) res[108] = fma52lo(res[108], a[49], a[59]); // Sum(108) res[109] = fma52hi(res[109], a[49], a[59]); // Sum(108) res[109] = fma52lo(res[109], a[50], a[59]); // Sum(109) res[110] = fma52hi(res[110], a[50], a[59]); // Sum(109) res[110] = fma52lo(res[110], a[51], a[59]); // Sum(110) res[111] = fma52hi(res[111], a[51], a[59]); // Sum(110) res[111] = fma52lo(res[111], a[52], a[59]); // Sum(111) res[112] = fma52hi(res[112], a[52], a[59]); // Sum(111) res[112] = fma52lo(res[112], a[53], a[59]); // Sum(112) res[113] = fma52hi(res[113], a[53], a[59]); // Sum(112) res[113] = fma52lo(res[113], a[54], a[59]); // Sum(113) res[114] = fma52hi(res[114], a[54], a[59]); // Sum(113) res[114] = fma52lo(res[114], a[55], a[59]); // Sum(114) res[115] = fma52hi(res[115], a[55], a[59]); // Sum(114) res[115] = fma52lo(res[115], a[56], a[59]); // Sum(115) res[116] = fma52hi(res[116], a[56], a[59]); // Sum(115) res[116] = fma52lo(res[116], a[57], a[59]); // Sum(116) res[117] = fma52hi(res[117], a[57], a[59]); // Sum(116) res[117] = fma52lo(res[117], a[58], a[59]); // Sum(117) res[118] = fma52hi(res[118], a[58], a[59]); // Sum(117) res[108] = fma52lo(res[108], a[48], a[60]); // Sum(108) res[109] = fma52hi(res[109], a[48], a[60]); // Sum(108) res[109] = fma52lo(res[109], a[49], a[60]); // Sum(109) res[110] = fma52hi(res[110], a[49], a[60]); // Sum(109) res[110] = fma52lo(res[110], a[50], a[60]); // Sum(110) res[111] = fma52hi(res[111], a[50], a[60]); // Sum(110) res[111] = fma52lo(res[111], a[51], a[60]); // Sum(111) res[112] = fma52hi(res[112], a[51], a[60]); // Sum(111) res[112] = fma52lo(res[112], a[52], a[60]); // Sum(112) res[113] = fma52hi(res[113], a[52], a[60]); // Sum(112) res[113] = fma52lo(res[113], a[53], a[60]); // Sum(113) res[114] = fma52hi(res[114], a[53], a[60]); // Sum(113) res[114] = fma52lo(res[114], a[54], a[60]); // Sum(114) res[115] = fma52hi(res[115], a[54], a[60]); // Sum(114) res[115] = fma52lo(res[115], a[55], a[60]); // Sum(115) res[116] = fma52hi(res[116], a[55], a[60]); // Sum(115) res[116] = fma52lo(res[116], a[56], a[60]); // Sum(116) res[117] = fma52hi(res[117], a[56], a[60]); // Sum(116) res[117] = fma52lo(res[117], a[57], a[60]); // Sum(117) res[118] = fma52hi(res[118], a[57], a[60]); // Sum(117) res[118] = fma52lo(res[118], a[58], a[60]); // Sum(118) res[119] = fma52hi(res[119], a[58], a[60]); // Sum(118) res[119] = fma52lo(res[119], a[59], a[60]); // Sum(119) res[120] = fma52hi(res[120], a[59], a[60]); // Sum(119) res[108] = fma52lo(res[108], a[47], a[61]); // Sum(108) res[109] = fma52hi(res[109], a[47], a[61]); // Sum(108) res[109] = fma52lo(res[109], a[48], a[61]); // Sum(109) res[110] = fma52hi(res[110], a[48], a[61]); // Sum(109) res[110] = fma52lo(res[110], a[49], a[61]); // Sum(110) res[111] = fma52hi(res[111], a[49], a[61]); // Sum(110) res[111] = fma52lo(res[111], a[50], a[61]); // Sum(111) res[112] = fma52hi(res[112], a[50], a[61]); // Sum(111) res[112] = fma52lo(res[112], a[51], a[61]); // Sum(112) res[113] = fma52hi(res[113], a[51], a[61]); // Sum(112) res[113] = fma52lo(res[113], a[52], a[61]); // Sum(113) res[114] = fma52hi(res[114], a[52], a[61]); // Sum(113) res[114] = fma52lo(res[114], a[53], a[61]); // Sum(114) res[115] = fma52hi(res[115], a[53], a[61]); // Sum(114) res[115] = fma52lo(res[115], a[54], a[61]); // Sum(115) res[116] = fma52hi(res[116], a[54], a[61]); // Sum(115) res[116] = fma52lo(res[116], a[55], a[61]); // Sum(116) res[117] = fma52hi(res[117], a[55], a[61]); // Sum(116) res[117] = fma52lo(res[117], a[56], a[61]); // Sum(117) res[118] = fma52hi(res[118], a[56], a[61]); // Sum(117) res[118] = fma52lo(res[118], a[57], a[61]); // Sum(118) res[119] = fma52hi(res[119], a[57], a[61]); // Sum(118) res[119] = fma52lo(res[119], a[58], a[61]); // Sum(119) res[120] = fma52hi(res[120], a[58], a[61]); // Sum(119) res[108] = fma52lo(res[108], a[46], a[62]); // Sum(108) res[109] = fma52hi(res[109], a[46], a[62]); // Sum(108) res[109] = fma52lo(res[109], a[47], a[62]); // Sum(109) res[110] = fma52hi(res[110], a[47], a[62]); // Sum(109) res[110] = fma52lo(res[110], a[48], a[62]); // Sum(110) res[111] = fma52hi(res[111], a[48], a[62]); // Sum(110) res[111] = fma52lo(res[111], a[49], a[62]); // Sum(111) res[112] = fma52hi(res[112], a[49], a[62]); // Sum(111) res[112] = fma52lo(res[112], a[50], a[62]); // Sum(112) res[113] = fma52hi(res[113], a[50], a[62]); // Sum(112) res[113] = fma52lo(res[113], a[51], a[62]); // Sum(113) res[114] = fma52hi(res[114], a[51], a[62]); // Sum(113) res[114] = fma52lo(res[114], a[52], a[62]); // Sum(114) res[115] = fma52hi(res[115], a[52], a[62]); // Sum(114) res[115] = fma52lo(res[115], a[53], a[62]); // Sum(115) res[116] = fma52hi(res[116], a[53], a[62]); // Sum(115) res[116] = fma52lo(res[116], a[54], a[62]); // Sum(116) res[117] = fma52hi(res[117], a[54], a[62]); // Sum(116) res[117] = fma52lo(res[117], a[55], a[62]); // Sum(117) res[118] = fma52hi(res[118], a[55], a[62]); // Sum(117) res[118] = fma52lo(res[118], a[56], a[62]); // Sum(118) res[119] = fma52hi(res[119], a[56], a[62]); // Sum(118) res[119] = fma52lo(res[119], a[57], a[62]); // Sum(119) res[120] = fma52hi(res[120], a[57], a[62]); // Sum(119) res[108] = fma52lo(res[108], a[45], a[63]); // Sum(108) res[109] = fma52hi(res[109], a[45], a[63]); // Sum(108) res[109] = fma52lo(res[109], a[46], a[63]); // Sum(109) res[110] = fma52hi(res[110], a[46], a[63]); // Sum(109) res[110] = fma52lo(res[110], a[47], a[63]); // Sum(110) res[111] = fma52hi(res[111], a[47], a[63]); // Sum(110) res[111] = fma52lo(res[111], a[48], a[63]); // Sum(111) res[112] = fma52hi(res[112], a[48], a[63]); // Sum(111) res[112] = fma52lo(res[112], a[49], a[63]); // Sum(112) res[113] = fma52hi(res[113], a[49], a[63]); // Sum(112) res[113] = fma52lo(res[113], a[50], a[63]); // Sum(113) res[114] = fma52hi(res[114], a[50], a[63]); // Sum(113) res[114] = fma52lo(res[114], a[51], a[63]); // Sum(114) res[115] = fma52hi(res[115], a[51], a[63]); // Sum(114) res[115] = fma52lo(res[115], a[52], a[63]); // Sum(115) res[116] = fma52hi(res[116], a[52], a[63]); // Sum(115) res[116] = fma52lo(res[116], a[53], a[63]); // Sum(116) res[117] = fma52hi(res[117], a[53], a[63]); // Sum(116) res[117] = fma52lo(res[117], a[54], a[63]); // Sum(117) res[118] = fma52hi(res[118], a[54], a[63]); // Sum(117) res[118] = fma52lo(res[118], a[55], a[63]); // Sum(118) res[119] = fma52hi(res[119], a[55], a[63]); // Sum(118) res[119] = fma52lo(res[119], a[56], a[63]); // Sum(119) res[120] = fma52hi(res[120], a[56], a[63]); // Sum(119) res[108] = fma52lo(res[108], a[44], a[64]); // Sum(108) res[109] = fma52hi(res[109], a[44], a[64]); // Sum(108) res[109] = fma52lo(res[109], a[45], a[64]); // Sum(109) res[110] = fma52hi(res[110], a[45], a[64]); // Sum(109) res[110] = fma52lo(res[110], a[46], a[64]); // Sum(110) res[111] = fma52hi(res[111], a[46], a[64]); // Sum(110) res[111] = fma52lo(res[111], a[47], a[64]); // Sum(111) res[112] = fma52hi(res[112], a[47], a[64]); // Sum(111) res[112] = fma52lo(res[112], a[48], a[64]); // Sum(112) res[113] = fma52hi(res[113], a[48], a[64]); // Sum(112) res[113] = fma52lo(res[113], a[49], a[64]); // Sum(113) res[114] = fma52hi(res[114], a[49], a[64]); // Sum(113) res[114] = fma52lo(res[114], a[50], a[64]); // Sum(114) res[115] = fma52hi(res[115], a[50], a[64]); // Sum(114) res[115] = fma52lo(res[115], a[51], a[64]); // Sum(115) res[116] = fma52hi(res[116], a[51], a[64]); // Sum(115) res[116] = fma52lo(res[116], a[52], a[64]); // Sum(116) res[117] = fma52hi(res[117], a[52], a[64]); // Sum(116) res[117] = fma52lo(res[117], a[53], a[64]); // Sum(117) res[118] = fma52hi(res[118], a[53], a[64]); // Sum(117) res[118] = fma52lo(res[118], a[54], a[64]); // Sum(118) res[119] = fma52hi(res[119], a[54], a[64]); // Sum(118) res[119] = fma52lo(res[119], a[55], a[64]); // Sum(119) res[120] = fma52hi(res[120], a[55], a[64]); // Sum(119) res[108] = fma52lo(res[108], a[43], a[65]); // Sum(108) res[109] = fma52hi(res[109], a[43], a[65]); // Sum(108) res[109] = fma52lo(res[109], a[44], a[65]); // Sum(109) res[110] = fma52hi(res[110], a[44], a[65]); // Sum(109) res[110] = fma52lo(res[110], a[45], a[65]); // Sum(110) res[111] = fma52hi(res[111], a[45], a[65]); // Sum(110) res[111] = fma52lo(res[111], a[46], a[65]); // Sum(111) res[112] = fma52hi(res[112], a[46], a[65]); // Sum(111) res[112] = fma52lo(res[112], a[47], a[65]); // Sum(112) res[113] = fma52hi(res[113], a[47], a[65]); // Sum(112) res[113] = fma52lo(res[113], a[48], a[65]); // Sum(113) res[114] = fma52hi(res[114], a[48], a[65]); // Sum(113) res[114] = fma52lo(res[114], a[49], a[65]); // Sum(114) res[115] = fma52hi(res[115], a[49], a[65]); // Sum(114) res[115] = fma52lo(res[115], a[50], a[65]); // Sum(115) res[116] = fma52hi(res[116], a[50], a[65]); // Sum(115) res[116] = fma52lo(res[116], a[51], a[65]); // Sum(116) res[117] = fma52hi(res[117], a[51], a[65]); // Sum(116) res[117] = fma52lo(res[117], a[52], a[65]); // Sum(117) res[118] = fma52hi(res[118], a[52], a[65]); // Sum(117) res[118] = fma52lo(res[118], a[53], a[65]); // Sum(118) res[119] = fma52hi(res[119], a[53], a[65]); // Sum(118) res[119] = fma52lo(res[119], a[54], a[65]); // Sum(119) res[120] = fma52hi(res[120], a[54], a[65]); // Sum(119) res[108] = fma52lo(res[108], a[42], a[66]); // Sum(108) res[109] = fma52hi(res[109], a[42], a[66]); // Sum(108) res[109] = fma52lo(res[109], a[43], a[66]); // Sum(109) res[110] = fma52hi(res[110], a[43], a[66]); // Sum(109) res[110] = fma52lo(res[110], a[44], a[66]); // Sum(110) res[111] = fma52hi(res[111], a[44], a[66]); // Sum(110) res[111] = fma52lo(res[111], a[45], a[66]); // Sum(111) res[112] = fma52hi(res[112], a[45], a[66]); // Sum(111) res[112] = fma52lo(res[112], a[46], a[66]); // Sum(112) res[113] = fma52hi(res[113], a[46], a[66]); // Sum(112) res[113] = fma52lo(res[113], a[47], a[66]); // Sum(113) res[114] = fma52hi(res[114], a[47], a[66]); // Sum(113) res[114] = fma52lo(res[114], a[48], a[66]); // Sum(114) res[115] = fma52hi(res[115], a[48], a[66]); // Sum(114) res[115] = fma52lo(res[115], a[49], a[66]); // Sum(115) res[116] = fma52hi(res[116], a[49], a[66]); // Sum(115) res[116] = fma52lo(res[116], a[50], a[66]); // Sum(116) res[117] = fma52hi(res[117], a[50], a[66]); // Sum(116) res[117] = fma52lo(res[117], a[51], a[66]); // Sum(117) res[118] = fma52hi(res[118], a[51], a[66]); // Sum(117) res[118] = fma52lo(res[118], a[52], a[66]); // Sum(118) res[119] = fma52hi(res[119], a[52], a[66]); // Sum(118) res[119] = fma52lo(res[119], a[53], a[66]); // Sum(119) res[120] = fma52hi(res[120], a[53], a[66]); // Sum(119) res[108] = fma52lo(res[108], a[41], a[67]); // Sum(108) res[109] = fma52hi(res[109], a[41], a[67]); // Sum(108) res[109] = fma52lo(res[109], a[42], a[67]); // Sum(109) res[110] = fma52hi(res[110], a[42], a[67]); // Sum(109) res[110] = fma52lo(res[110], a[43], a[67]); // Sum(110) res[111] = fma52hi(res[111], a[43], a[67]); // Sum(110) res[111] = fma52lo(res[111], a[44], a[67]); // Sum(111) res[112] = fma52hi(res[112], a[44], a[67]); // Sum(111) res[112] = fma52lo(res[112], a[45], a[67]); // Sum(112) res[113] = fma52hi(res[113], a[45], a[67]); // Sum(112) res[113] = fma52lo(res[113], a[46], a[67]); // Sum(113) res[114] = fma52hi(res[114], a[46], a[67]); // Sum(113) res[114] = fma52lo(res[114], a[47], a[67]); // Sum(114) res[115] = fma52hi(res[115], a[47], a[67]); // Sum(114) res[115] = fma52lo(res[115], a[48], a[67]); // Sum(115) res[116] = fma52hi(res[116], a[48], a[67]); // Sum(115) res[116] = fma52lo(res[116], a[49], a[67]); // Sum(116) res[117] = fma52hi(res[117], a[49], a[67]); // Sum(116) res[117] = fma52lo(res[117], a[50], a[67]); // Sum(117) res[118] = fma52hi(res[118], a[50], a[67]); // Sum(117) res[118] = fma52lo(res[118], a[51], a[67]); // Sum(118) res[119] = fma52hi(res[119], a[51], a[67]); // Sum(118) res[119] = fma52lo(res[119], a[52], a[67]); // Sum(119) res[120] = fma52hi(res[120], a[52], a[67]); // Sum(119) res[108] = fma52lo(res[108], a[40], a[68]); // Sum(108) res[109] = fma52hi(res[109], a[40], a[68]); // Sum(108) res[109] = fma52lo(res[109], a[41], a[68]); // Sum(109) res[110] = fma52hi(res[110], a[41], a[68]); // Sum(109) res[110] = fma52lo(res[110], a[42], a[68]); // Sum(110) res[111] = fma52hi(res[111], a[42], a[68]); // Sum(110) res[111] = fma52lo(res[111], a[43], a[68]); // Sum(111) res[112] = fma52hi(res[112], a[43], a[68]); // Sum(111) res[112] = fma52lo(res[112], a[44], a[68]); // Sum(112) res[113] = fma52hi(res[113], a[44], a[68]); // Sum(112) res[113] = fma52lo(res[113], a[45], a[68]); // Sum(113) res[114] = fma52hi(res[114], a[45], a[68]); // Sum(113) res[114] = fma52lo(res[114], a[46], a[68]); // Sum(114) res[115] = fma52hi(res[115], a[46], a[68]); // Sum(114) res[115] = fma52lo(res[115], a[47], a[68]); // Sum(115) res[116] = fma52hi(res[116], a[47], a[68]); // Sum(115) res[116] = fma52lo(res[116], a[48], a[68]); // Sum(116) res[117] = fma52hi(res[117], a[48], a[68]); // Sum(116) res[117] = fma52lo(res[117], a[49], a[68]); // Sum(117) res[118] = fma52hi(res[118], a[49], a[68]); // Sum(117) res[118] = fma52lo(res[118], a[50], a[68]); // Sum(118) res[119] = fma52hi(res[119], a[50], a[68]); // Sum(118) res[119] = fma52lo(res[119], a[51], a[68]); // Sum(119) res[120] = fma52hi(res[120], a[51], a[68]); // Sum(119) res[108] = fma52lo(res[108], a[39], a[69]); // Sum(108) res[109] = fma52hi(res[109], a[39], a[69]); // Sum(108) res[109] = fma52lo(res[109], a[40], a[69]); // Sum(109) res[110] = fma52hi(res[110], a[40], a[69]); // Sum(109) res[110] = fma52lo(res[110], a[41], a[69]); // Sum(110) res[111] = fma52hi(res[111], a[41], a[69]); // Sum(110) res[111] = fma52lo(res[111], a[42], a[69]); // Sum(111) res[112] = fma52hi(res[112], a[42], a[69]); // Sum(111) res[112] = fma52lo(res[112], a[43], a[69]); // Sum(112) res[113] = fma52hi(res[113], a[43], a[69]); // Sum(112) res[113] = fma52lo(res[113], a[44], a[69]); // Sum(113) res[114] = fma52hi(res[114], a[44], a[69]); // Sum(113) res[114] = fma52lo(res[114], a[45], a[69]); // Sum(114) res[115] = fma52hi(res[115], a[45], a[69]); // Sum(114) res[115] = fma52lo(res[115], a[46], a[69]); // Sum(115) res[116] = fma52hi(res[116], a[46], a[69]); // Sum(115) res[116] = fma52lo(res[116], a[47], a[69]); // Sum(116) res[117] = fma52hi(res[117], a[47], a[69]); // Sum(116) res[117] = fma52lo(res[117], a[48], a[69]); // Sum(117) res[118] = fma52hi(res[118], a[48], a[69]); // Sum(117) res[118] = fma52lo(res[118], a[49], a[69]); // Sum(118) res[119] = fma52hi(res[119], a[49], a[69]); // Sum(118) res[119] = fma52lo(res[119], a[50], a[69]); // Sum(119) res[120] = fma52hi(res[120], a[50], a[69]); // Sum(119) res[108] = fma52lo(res[108], a[38], a[70]); // Sum(108) res[109] = fma52hi(res[109], a[38], a[70]); // Sum(108) res[109] = fma52lo(res[109], a[39], a[70]); // Sum(109) res[110] = fma52hi(res[110], a[39], a[70]); // Sum(109) res[110] = fma52lo(res[110], a[40], a[70]); // Sum(110) res[111] = fma52hi(res[111], a[40], a[70]); // Sum(110) res[111] = fma52lo(res[111], a[41], a[70]); // Sum(111) res[112] = fma52hi(res[112], a[41], a[70]); // Sum(111) res[112] = fma52lo(res[112], a[42], a[70]); // Sum(112) res[113] = fma52hi(res[113], a[42], a[70]); // Sum(112) res[113] = fma52lo(res[113], a[43], a[70]); // Sum(113) res[114] = fma52hi(res[114], a[43], a[70]); // Sum(113) res[114] = fma52lo(res[114], a[44], a[70]); // Sum(114) res[115] = fma52hi(res[115], a[44], a[70]); // Sum(114) res[115] = fma52lo(res[115], a[45], a[70]); // Sum(115) res[116] = fma52hi(res[116], a[45], a[70]); // Sum(115) res[116] = fma52lo(res[116], a[46], a[70]); // Sum(116) res[117] = fma52hi(res[117], a[46], a[70]); // Sum(116) res[117] = fma52lo(res[117], a[47], a[70]); // Sum(117) res[118] = fma52hi(res[118], a[47], a[70]); // Sum(117) res[118] = fma52lo(res[118], a[48], a[70]); // Sum(118) res[119] = fma52hi(res[119], a[48], a[70]); // Sum(118) res[119] = fma52lo(res[119], a[49], a[70]); // Sum(119) res[120] = fma52hi(res[120], a[49], a[70]); // Sum(119) res[108] = fma52lo(res[108], a[37], a[71]); // Sum(108) res[109] = fma52hi(res[109], a[37], a[71]); // Sum(108) res[109] = fma52lo(res[109], a[38], a[71]); // Sum(109) res[110] = fma52hi(res[110], a[38], a[71]); // Sum(109) res[110] = fma52lo(res[110], a[39], a[71]); // Sum(110) res[111] = fma52hi(res[111], a[39], a[71]); // Sum(110) res[111] = fma52lo(res[111], a[40], a[71]); // Sum(111) res[112] = fma52hi(res[112], a[40], a[71]); // Sum(111) res[112] = fma52lo(res[112], a[41], a[71]); // Sum(112) res[113] = fma52hi(res[113], a[41], a[71]); // Sum(112) res[113] = fma52lo(res[113], a[42], a[71]); // Sum(113) res[114] = fma52hi(res[114], a[42], a[71]); // Sum(113) res[114] = fma52lo(res[114], a[43], a[71]); // Sum(114) res[115] = fma52hi(res[115], a[43], a[71]); // Sum(114) res[115] = fma52lo(res[115], a[44], a[71]); // Sum(115) res[116] = fma52hi(res[116], a[44], a[71]); // Sum(115) res[116] = fma52lo(res[116], a[45], a[71]); // Sum(116) res[117] = fma52hi(res[117], a[45], a[71]); // Sum(116) res[117] = fma52lo(res[117], a[46], a[71]); // Sum(117) res[118] = fma52hi(res[118], a[46], a[71]); // Sum(117) res[118] = fma52lo(res[118], a[47], a[71]); // Sum(118) res[119] = fma52hi(res[119], a[47], a[71]); // Sum(118) res[119] = fma52lo(res[119], a[48], a[71]); // Sum(119) res[120] = fma52hi(res[120], a[48], a[71]); // Sum(119) res[108] = fma52lo(res[108], a[36], a[72]); // Sum(108) res[109] = fma52hi(res[109], a[36], a[72]); // Sum(108) res[109] = fma52lo(res[109], a[37], a[72]); // Sum(109) res[110] = fma52hi(res[110], a[37], a[72]); // Sum(109) res[110] = fma52lo(res[110], a[38], a[72]); // Sum(110) res[111] = fma52hi(res[111], a[38], a[72]); // Sum(110) res[111] = fma52lo(res[111], a[39], a[72]); // Sum(111) res[112] = fma52hi(res[112], a[39], a[72]); // Sum(111) res[112] = fma52lo(res[112], a[40], a[72]); // Sum(112) res[113] = fma52hi(res[113], a[40], a[72]); // Sum(112) res[113] = fma52lo(res[113], a[41], a[72]); // Sum(113) res[114] = fma52hi(res[114], a[41], a[72]); // Sum(113) res[114] = fma52lo(res[114], a[42], a[72]); // Sum(114) res[115] = fma52hi(res[115], a[42], a[72]); // Sum(114) res[115] = fma52lo(res[115], a[43], a[72]); // Sum(115) res[116] = fma52hi(res[116], a[43], a[72]); // Sum(115) res[116] = fma52lo(res[116], a[44], a[72]); // Sum(116) res[117] = fma52hi(res[117], a[44], a[72]); // Sum(116) res[117] = fma52lo(res[117], a[45], a[72]); // Sum(117) res[118] = fma52hi(res[118], a[45], a[72]); // Sum(117) res[118] = fma52lo(res[118], a[46], a[72]); // Sum(118) res[119] = fma52hi(res[119], a[46], a[72]); // Sum(118) res[119] = fma52lo(res[119], a[47], a[72]); // Sum(119) res[120] = fma52hi(res[120], a[47], a[72]); // Sum(119) res[108] = fma52lo(res[108], a[35], a[73]); // Sum(108) res[109] = fma52hi(res[109], a[35], a[73]); // Sum(108) res[109] = fma52lo(res[109], a[36], a[73]); // Sum(109) res[110] = fma52hi(res[110], a[36], a[73]); // Sum(109) res[110] = fma52lo(res[110], a[37], a[73]); // Sum(110) res[111] = fma52hi(res[111], a[37], a[73]); // Sum(110) res[111] = fma52lo(res[111], a[38], a[73]); // Sum(111) res[112] = fma52hi(res[112], a[38], a[73]); // Sum(111) res[112] = fma52lo(res[112], a[39], a[73]); // Sum(112) res[113] = fma52hi(res[113], a[39], a[73]); // Sum(112) res[113] = fma52lo(res[113], a[40], a[73]); // Sum(113) res[114] = fma52hi(res[114], a[40], a[73]); // Sum(113) res[114] = fma52lo(res[114], a[41], a[73]); // Sum(114) res[115] = fma52hi(res[115], a[41], a[73]); // Sum(114) res[115] = fma52lo(res[115], a[42], a[73]); // Sum(115) res[116] = fma52hi(res[116], a[42], a[73]); // Sum(115) res[116] = fma52lo(res[116], a[43], a[73]); // Sum(116) res[117] = fma52hi(res[117], a[43], a[73]); // Sum(116) res[117] = fma52lo(res[117], a[44], a[73]); // Sum(117) res[118] = fma52hi(res[118], a[44], a[73]); // Sum(117) res[118] = fma52lo(res[118], a[45], a[73]); // Sum(118) res[119] = fma52hi(res[119], a[45], a[73]); // Sum(118) res[119] = fma52lo(res[119], a[46], a[73]); // Sum(119) res[120] = fma52hi(res[120], a[46], a[73]); // Sum(119) res[108] = fma52lo(res[108], a[34], a[74]); // Sum(108) res[109] = fma52hi(res[109], a[34], a[74]); // Sum(108) res[109] = fma52lo(res[109], a[35], a[74]); // Sum(109) res[110] = fma52hi(res[110], a[35], a[74]); // Sum(109) res[110] = fma52lo(res[110], a[36], a[74]); // Sum(110) res[111] = fma52hi(res[111], a[36], a[74]); // Sum(110) res[111] = fma52lo(res[111], a[37], a[74]); // Sum(111) res[112] = fma52hi(res[112], a[37], a[74]); // Sum(111) res[112] = fma52lo(res[112], a[38], a[74]); // Sum(112) res[113] = fma52hi(res[113], a[38], a[74]); // Sum(112) res[113] = fma52lo(res[113], a[39], a[74]); // Sum(113) res[114] = fma52hi(res[114], a[39], a[74]); // Sum(113) res[114] = fma52lo(res[114], a[40], a[74]); // Sum(114) res[115] = fma52hi(res[115], a[40], a[74]); // Sum(114) res[115] = fma52lo(res[115], a[41], a[74]); // Sum(115) res[116] = fma52hi(res[116], a[41], a[74]); // Sum(115) res[116] = fma52lo(res[116], a[42], a[74]); // Sum(116) res[117] = fma52hi(res[117], a[42], a[74]); // Sum(116) res[117] = fma52lo(res[117], a[43], a[74]); // Sum(117) res[118] = fma52hi(res[118], a[43], a[74]); // Sum(117) res[118] = fma52lo(res[118], a[44], a[74]); // Sum(118) res[119] = fma52hi(res[119], a[44], a[74]); // Sum(118) res[119] = fma52lo(res[119], a[45], a[74]); // Sum(119) res[120] = fma52hi(res[120], a[45], a[74]); // Sum(119) res[108] = fma52lo(res[108], a[33], a[75]); // Sum(108) res[109] = fma52hi(res[109], a[33], a[75]); // Sum(108) res[109] = fma52lo(res[109], a[34], a[75]); // Sum(109) res[110] = fma52hi(res[110], a[34], a[75]); // Sum(109) res[110] = fma52lo(res[110], a[35], a[75]); // Sum(110) res[111] = fma52hi(res[111], a[35], a[75]); // Sum(110) res[111] = fma52lo(res[111], a[36], a[75]); // Sum(111) res[112] = fma52hi(res[112], a[36], a[75]); // Sum(111) res[112] = fma52lo(res[112], a[37], a[75]); // Sum(112) res[113] = fma52hi(res[113], a[37], a[75]); // Sum(112) res[113] = fma52lo(res[113], a[38], a[75]); // Sum(113) res[114] = fma52hi(res[114], a[38], a[75]); // Sum(113) res[114] = fma52lo(res[114], a[39], a[75]); // Sum(114) res[115] = fma52hi(res[115], a[39], a[75]); // Sum(114) res[115] = fma52lo(res[115], a[40], a[75]); // Sum(115) res[116] = fma52hi(res[116], a[40], a[75]); // Sum(115) res[116] = fma52lo(res[116], a[41], a[75]); // Sum(116) res[117] = fma52hi(res[117], a[41], a[75]); // Sum(116) res[117] = fma52lo(res[117], a[42], a[75]); // Sum(117) res[118] = fma52hi(res[118], a[42], a[75]); // Sum(117) res[118] = fma52lo(res[118], a[43], a[75]); // Sum(118) res[119] = fma52hi(res[119], a[43], a[75]); // Sum(118) res[119] = fma52lo(res[119], a[44], a[75]); // Sum(119) res[120] = fma52hi(res[120], a[44], a[75]); // Sum(119) res[108] = fma52lo(res[108], a[32], a[76]); // Sum(108) res[109] = fma52hi(res[109], a[32], a[76]); // Sum(108) res[109] = fma52lo(res[109], a[33], a[76]); // Sum(109) res[110] = fma52hi(res[110], a[33], a[76]); // Sum(109) res[110] = fma52lo(res[110], a[34], a[76]); // Sum(110) res[111] = fma52hi(res[111], a[34], a[76]); // Sum(110) res[111] = fma52lo(res[111], a[35], a[76]); // Sum(111) res[112] = fma52hi(res[112], a[35], a[76]); // Sum(111) res[112] = fma52lo(res[112], a[36], a[76]); // Sum(112) res[113] = fma52hi(res[113], a[36], a[76]); // Sum(112) res[113] = fma52lo(res[113], a[37], a[76]); // Sum(113) res[114] = fma52hi(res[114], a[37], a[76]); // Sum(113) res[114] = fma52lo(res[114], a[38], a[76]); // Sum(114) res[115] = fma52hi(res[115], a[38], a[76]); // Sum(114) res[115] = fma52lo(res[115], a[39], a[76]); // Sum(115) res[116] = fma52hi(res[116], a[39], a[76]); // Sum(115) res[116] = fma52lo(res[116], a[40], a[76]); // Sum(116) res[117] = fma52hi(res[117], a[40], a[76]); // Sum(116) res[117] = fma52lo(res[117], a[41], a[76]); // Sum(117) res[118] = fma52hi(res[118], a[41], a[76]); // Sum(117) res[118] = fma52lo(res[118], a[42], a[76]); // Sum(118) res[119] = fma52hi(res[119], a[42], a[76]); // Sum(118) res[119] = fma52lo(res[119], a[43], a[76]); // Sum(119) res[120] = fma52hi(res[120], a[43], a[76]); // Sum(119) res[108] = fma52lo(res[108], a[31], a[77]); // Sum(108) res[109] = fma52hi(res[109], a[31], a[77]); // Sum(108) res[109] = fma52lo(res[109], a[32], a[77]); // Sum(109) res[110] = fma52hi(res[110], a[32], a[77]); // Sum(109) res[110] = fma52lo(res[110], a[33], a[77]); // Sum(110) res[111] = fma52hi(res[111], a[33], a[77]); // Sum(110) res[111] = fma52lo(res[111], a[34], a[77]); // Sum(111) res[112] = fma52hi(res[112], a[34], a[77]); // Sum(111) res[112] = fma52lo(res[112], a[35], a[77]); // Sum(112) res[113] = fma52hi(res[113], a[35], a[77]); // Sum(112) res[113] = fma52lo(res[113], a[36], a[77]); // Sum(113) res[114] = fma52hi(res[114], a[36], a[77]); // Sum(113) res[114] = fma52lo(res[114], a[37], a[77]); // Sum(114) res[115] = fma52hi(res[115], a[37], a[77]); // Sum(114) res[115] = fma52lo(res[115], a[38], a[77]); // Sum(115) res[116] = fma52hi(res[116], a[38], a[77]); // Sum(115) res[116] = fma52lo(res[116], a[39], a[77]); // Sum(116) res[117] = fma52hi(res[117], a[39], a[77]); // Sum(116) res[117] = fma52lo(res[117], a[40], a[77]); // Sum(117) res[118] = fma52hi(res[118], a[40], a[77]); // Sum(117) res[118] = fma52lo(res[118], a[41], a[77]); // Sum(118) res[119] = fma52hi(res[119], a[41], a[77]); // Sum(118) res[119] = fma52lo(res[119], a[42], a[77]); // Sum(119) res[120] = fma52hi(res[120], a[42], a[77]); // Sum(119) res[108] = fma52lo(res[108], a[30], a[78]); // Sum(108) res[109] = fma52hi(res[109], a[30], a[78]); // Sum(108) res[109] = fma52lo(res[109], a[31], a[78]); // Sum(109) res[110] = fma52hi(res[110], a[31], a[78]); // Sum(109) res[110] = fma52lo(res[110], a[32], a[78]); // Sum(110) res[111] = fma52hi(res[111], a[32], a[78]); // Sum(110) res[111] = fma52lo(res[111], a[33], a[78]); // Sum(111) res[112] = fma52hi(res[112], a[33], a[78]); // Sum(111) res[112] = fma52lo(res[112], a[34], a[78]); // Sum(112) res[113] = fma52hi(res[113], a[34], a[78]); // Sum(112) res[113] = fma52lo(res[113], a[35], a[78]); // Sum(113) res[114] = fma52hi(res[114], a[35], a[78]); // Sum(113) res[114] = fma52lo(res[114], a[36], a[78]); // Sum(114) res[115] = fma52hi(res[115], a[36], a[78]); // Sum(114) res[115] = fma52lo(res[115], a[37], a[78]); // Sum(115) res[116] = fma52hi(res[116], a[37], a[78]); // Sum(115) res[116] = fma52lo(res[116], a[38], a[78]); // Sum(116) res[117] = fma52hi(res[117], a[38], a[78]); // Sum(116) res[117] = fma52lo(res[117], a[39], a[78]); // Sum(117) res[118] = fma52hi(res[118], a[39], a[78]); // Sum(117) res[118] = fma52lo(res[118], a[40], a[78]); // Sum(118) res[119] = fma52hi(res[119], a[40], a[78]); // Sum(118) res[119] = fma52lo(res[119], a[41], a[78]); // Sum(119) res[120] = fma52hi(res[120], a[41], a[78]); // Sum(119) res[108] = add64(res[108], res[108]); // Double(108) res[109] = add64(res[109], res[109]); // Double(109) res[110] = add64(res[110], res[110]); // Double(110) res[111] = add64(res[111], res[111]); // Double(111) res[112] = add64(res[112], res[112]); // Double(112) res[113] = add64(res[113], res[113]); // Double(113) res[114] = add64(res[114], res[114]); // Double(114) res[115] = add64(res[115], res[115]); // Double(115) res[116] = add64(res[116], res[116]); // Double(116) res[117] = add64(res[117], res[117]); // Double(117) res[118] = add64(res[118], res[118]); // Double(118) res[119] = add64(res[119], res[119]); // Double(119) res[108] = fma52lo(res[108], a[54], a[54]); // Add sqr(108) res[109] = fma52hi(res[109], a[54], a[54]); // Add sqr(108) res[110] = fma52lo(res[110], a[55], a[55]); // Add sqr(110) res[111] = fma52hi(res[111], a[55], a[55]); // Add sqr(110) res[112] = fma52lo(res[112], a[56], a[56]); // Add sqr(112) res[113] = fma52hi(res[113], a[56], a[56]); // Add sqr(112) res[114] = fma52lo(res[114], a[57], a[57]); // Add sqr(114) res[115] = fma52hi(res[115], a[57], a[57]); // Add sqr(114) res[116] = fma52lo(res[116], a[58], a[58]); // Add sqr(116) res[117] = fma52hi(res[117], a[58], a[58]); // Add sqr(116) res[118] = fma52lo(res[118], a[59], a[59]); // Add sqr(118) res[119] = fma52hi(res[119], a[59], a[59]); // Add sqr(118) res[120] = fma52lo(res[120], a[59], a[61]); // Sum(120) res[121] = fma52hi(res[121], a[59], a[61]); // Sum(120) res[121] = fma52lo(res[121], a[60], a[61]); // Sum(121) res[122] = fma52hi(res[122], a[60], a[61]); // Sum(121) res[120] = fma52lo(res[120], a[58], a[62]); // Sum(120) res[121] = fma52hi(res[121], a[58], a[62]); // Sum(120) res[121] = fma52lo(res[121], a[59], a[62]); // Sum(121) res[122] = fma52hi(res[122], a[59], a[62]); // Sum(121) res[122] = fma52lo(res[122], a[60], a[62]); // Sum(122) res[123] = fma52hi(res[123], a[60], a[62]); // Sum(122) res[123] = fma52lo(res[123], a[61], a[62]); // Sum(123) res[124] = fma52hi(res[124], a[61], a[62]); // Sum(123) res[120] = fma52lo(res[120], a[57], a[63]); // Sum(120) res[121] = fma52hi(res[121], a[57], a[63]); // Sum(120) res[121] = fma52lo(res[121], a[58], a[63]); // Sum(121) res[122] = fma52hi(res[122], a[58], a[63]); // Sum(121) res[122] = fma52lo(res[122], a[59], a[63]); // Sum(122) res[123] = fma52hi(res[123], a[59], a[63]); // Sum(122) res[123] = fma52lo(res[123], a[60], a[63]); // Sum(123) res[124] = fma52hi(res[124], a[60], a[63]); // Sum(123) res[124] = fma52lo(res[124], a[61], a[63]); // Sum(124) res[125] = fma52hi(res[125], a[61], a[63]); // Sum(124) res[125] = fma52lo(res[125], a[62], a[63]); // Sum(125) res[126] = fma52hi(res[126], a[62], a[63]); // Sum(125) res[120] = fma52lo(res[120], a[56], a[64]); // Sum(120) res[121] = fma52hi(res[121], a[56], a[64]); // Sum(120) res[121] = fma52lo(res[121], a[57], a[64]); // Sum(121) res[122] = fma52hi(res[122], a[57], a[64]); // Sum(121) res[122] = fma52lo(res[122], a[58], a[64]); // Sum(122) res[123] = fma52hi(res[123], a[58], a[64]); // Sum(122) res[123] = fma52lo(res[123], a[59], a[64]); // Sum(123) res[124] = fma52hi(res[124], a[59], a[64]); // Sum(123) res[124] = fma52lo(res[124], a[60], a[64]); // Sum(124) res[125] = fma52hi(res[125], a[60], a[64]); // Sum(124) res[125] = fma52lo(res[125], a[61], a[64]); // Sum(125) res[126] = fma52hi(res[126], a[61], a[64]); // Sum(125) res[126] = fma52lo(res[126], a[62], a[64]); // Sum(126) res[127] = fma52hi(res[127], a[62], a[64]); // Sum(126) res[127] = fma52lo(res[127], a[63], a[64]); // Sum(127) res[128] = fma52hi(res[128], a[63], a[64]); // Sum(127) res[120] = fma52lo(res[120], a[55], a[65]); // Sum(120) res[121] = fma52hi(res[121], a[55], a[65]); // Sum(120) res[121] = fma52lo(res[121], a[56], a[65]); // Sum(121) res[122] = fma52hi(res[122], a[56], a[65]); // Sum(121) res[122] = fma52lo(res[122], a[57], a[65]); // Sum(122) res[123] = fma52hi(res[123], a[57], a[65]); // Sum(122) res[123] = fma52lo(res[123], a[58], a[65]); // Sum(123) res[124] = fma52hi(res[124], a[58], a[65]); // Sum(123) res[124] = fma52lo(res[124], a[59], a[65]); // Sum(124) res[125] = fma52hi(res[125], a[59], a[65]); // Sum(124) res[125] = fma52lo(res[125], a[60], a[65]); // Sum(125) res[126] = fma52hi(res[126], a[60], a[65]); // Sum(125) res[126] = fma52lo(res[126], a[61], a[65]); // Sum(126) res[127] = fma52hi(res[127], a[61], a[65]); // Sum(126) res[127] = fma52lo(res[127], a[62], a[65]); // Sum(127) res[128] = fma52hi(res[128], a[62], a[65]); // Sum(127) res[128] = fma52lo(res[128], a[63], a[65]); // Sum(128) res[129] = fma52hi(res[129], a[63], a[65]); // Sum(128) res[129] = fma52lo(res[129], a[64], a[65]); // Sum(129) res[130] = fma52hi(res[130], a[64], a[65]); // Sum(129) res[120] = fma52lo(res[120], a[54], a[66]); // Sum(120) res[121] = fma52hi(res[121], a[54], a[66]); // Sum(120) res[121] = fma52lo(res[121], a[55], a[66]); // Sum(121) res[122] = fma52hi(res[122], a[55], a[66]); // Sum(121) res[122] = fma52lo(res[122], a[56], a[66]); // Sum(122) res[123] = fma52hi(res[123], a[56], a[66]); // Sum(122) res[123] = fma52lo(res[123], a[57], a[66]); // Sum(123) res[124] = fma52hi(res[124], a[57], a[66]); // Sum(123) res[124] = fma52lo(res[124], a[58], a[66]); // Sum(124) res[125] = fma52hi(res[125], a[58], a[66]); // Sum(124) res[125] = fma52lo(res[125], a[59], a[66]); // Sum(125) res[126] = fma52hi(res[126], a[59], a[66]); // Sum(125) res[126] = fma52lo(res[126], a[60], a[66]); // Sum(126) res[127] = fma52hi(res[127], a[60], a[66]); // Sum(126) res[127] = fma52lo(res[127], a[61], a[66]); // Sum(127) res[128] = fma52hi(res[128], a[61], a[66]); // Sum(127) res[128] = fma52lo(res[128], a[62], a[66]); // Sum(128) res[129] = fma52hi(res[129], a[62], a[66]); // Sum(128) res[129] = fma52lo(res[129], a[63], a[66]); // Sum(129) res[130] = fma52hi(res[130], a[63], a[66]); // Sum(129) res[130] = fma52lo(res[130], a[64], a[66]); // Sum(130) res[131] = fma52hi(res[131], a[64], a[66]); // Sum(130) res[131] = fma52lo(res[131], a[65], a[66]); // Sum(131) res[132] = fma52hi(res[132], a[65], a[66]); // Sum(131) res[120] = fma52lo(res[120], a[53], a[67]); // Sum(120) res[121] = fma52hi(res[121], a[53], a[67]); // Sum(120) res[121] = fma52lo(res[121], a[54], a[67]); // Sum(121) res[122] = fma52hi(res[122], a[54], a[67]); // Sum(121) res[122] = fma52lo(res[122], a[55], a[67]); // Sum(122) res[123] = fma52hi(res[123], a[55], a[67]); // Sum(122) res[123] = fma52lo(res[123], a[56], a[67]); // Sum(123) res[124] = fma52hi(res[124], a[56], a[67]); // Sum(123) res[124] = fma52lo(res[124], a[57], a[67]); // Sum(124) res[125] = fma52hi(res[125], a[57], a[67]); // Sum(124) res[125] = fma52lo(res[125], a[58], a[67]); // Sum(125) res[126] = fma52hi(res[126], a[58], a[67]); // Sum(125) res[126] = fma52lo(res[126], a[59], a[67]); // Sum(126) res[127] = fma52hi(res[127], a[59], a[67]); // Sum(126) res[127] = fma52lo(res[127], a[60], a[67]); // Sum(127) res[128] = fma52hi(res[128], a[60], a[67]); // Sum(127) res[128] = fma52lo(res[128], a[61], a[67]); // Sum(128) res[129] = fma52hi(res[129], a[61], a[67]); // Sum(128) res[129] = fma52lo(res[129], a[62], a[67]); // Sum(129) res[130] = fma52hi(res[130], a[62], a[67]); // Sum(129) res[130] = fma52lo(res[130], a[63], a[67]); // Sum(130) res[131] = fma52hi(res[131], a[63], a[67]); // Sum(130) res[131] = fma52lo(res[131], a[64], a[67]); // Sum(131) res[132] = fma52hi(res[132], a[64], a[67]); // Sum(131) res[120] = fma52lo(res[120], a[52], a[68]); // Sum(120) res[121] = fma52hi(res[121], a[52], a[68]); // Sum(120) res[121] = fma52lo(res[121], a[53], a[68]); // Sum(121) res[122] = fma52hi(res[122], a[53], a[68]); // Sum(121) res[122] = fma52lo(res[122], a[54], a[68]); // Sum(122) res[123] = fma52hi(res[123], a[54], a[68]); // Sum(122) res[123] = fma52lo(res[123], a[55], a[68]); // Sum(123) res[124] = fma52hi(res[124], a[55], a[68]); // Sum(123) res[124] = fma52lo(res[124], a[56], a[68]); // Sum(124) res[125] = fma52hi(res[125], a[56], a[68]); // Sum(124) res[125] = fma52lo(res[125], a[57], a[68]); // Sum(125) res[126] = fma52hi(res[126], a[57], a[68]); // Sum(125) res[126] = fma52lo(res[126], a[58], a[68]); // Sum(126) res[127] = fma52hi(res[127], a[58], a[68]); // Sum(126) res[127] = fma52lo(res[127], a[59], a[68]); // Sum(127) res[128] = fma52hi(res[128], a[59], a[68]); // Sum(127) res[128] = fma52lo(res[128], a[60], a[68]); // Sum(128) res[129] = fma52hi(res[129], a[60], a[68]); // Sum(128) res[129] = fma52lo(res[129], a[61], a[68]); // Sum(129) res[130] = fma52hi(res[130], a[61], a[68]); // Sum(129) res[130] = fma52lo(res[130], a[62], a[68]); // Sum(130) res[131] = fma52hi(res[131], a[62], a[68]); // Sum(130) res[131] = fma52lo(res[131], a[63], a[68]); // Sum(131) res[132] = fma52hi(res[132], a[63], a[68]); // Sum(131) res[120] = fma52lo(res[120], a[51], a[69]); // Sum(120) res[121] = fma52hi(res[121], a[51], a[69]); // Sum(120) res[121] = fma52lo(res[121], a[52], a[69]); // Sum(121) res[122] = fma52hi(res[122], a[52], a[69]); // Sum(121) res[122] = fma52lo(res[122], a[53], a[69]); // Sum(122) res[123] = fma52hi(res[123], a[53], a[69]); // Sum(122) res[123] = fma52lo(res[123], a[54], a[69]); // Sum(123) res[124] = fma52hi(res[124], a[54], a[69]); // Sum(123) res[124] = fma52lo(res[124], a[55], a[69]); // Sum(124) res[125] = fma52hi(res[125], a[55], a[69]); // Sum(124) res[125] = fma52lo(res[125], a[56], a[69]); // Sum(125) res[126] = fma52hi(res[126], a[56], a[69]); // Sum(125) res[126] = fma52lo(res[126], a[57], a[69]); // Sum(126) res[127] = fma52hi(res[127], a[57], a[69]); // Sum(126) res[127] = fma52lo(res[127], a[58], a[69]); // Sum(127) res[128] = fma52hi(res[128], a[58], a[69]); // Sum(127) res[128] = fma52lo(res[128], a[59], a[69]); // Sum(128) res[129] = fma52hi(res[129], a[59], a[69]); // Sum(128) res[129] = fma52lo(res[129], a[60], a[69]); // Sum(129) res[130] = fma52hi(res[130], a[60], a[69]); // Sum(129) res[130] = fma52lo(res[130], a[61], a[69]); // Sum(130) res[131] = fma52hi(res[131], a[61], a[69]); // Sum(130) res[131] = fma52lo(res[131], a[62], a[69]); // Sum(131) res[132] = fma52hi(res[132], a[62], a[69]); // Sum(131) res[120] = fma52lo(res[120], a[50], a[70]); // Sum(120) res[121] = fma52hi(res[121], a[50], a[70]); // Sum(120) res[121] = fma52lo(res[121], a[51], a[70]); // Sum(121) res[122] = fma52hi(res[122], a[51], a[70]); // Sum(121) res[122] = fma52lo(res[122], a[52], a[70]); // Sum(122) res[123] = fma52hi(res[123], a[52], a[70]); // Sum(122) res[123] = fma52lo(res[123], a[53], a[70]); // Sum(123) res[124] = fma52hi(res[124], a[53], a[70]); // Sum(123) res[124] = fma52lo(res[124], a[54], a[70]); // Sum(124) res[125] = fma52hi(res[125], a[54], a[70]); // Sum(124) res[125] = fma52lo(res[125], a[55], a[70]); // Sum(125) res[126] = fma52hi(res[126], a[55], a[70]); // Sum(125) res[126] = fma52lo(res[126], a[56], a[70]); // Sum(126) res[127] = fma52hi(res[127], a[56], a[70]); // Sum(126) res[127] = fma52lo(res[127], a[57], a[70]); // Sum(127) res[128] = fma52hi(res[128], a[57], a[70]); // Sum(127) res[128] = fma52lo(res[128], a[58], a[70]); // Sum(128) res[129] = fma52hi(res[129], a[58], a[70]); // Sum(128) res[129] = fma52lo(res[129], a[59], a[70]); // Sum(129) res[130] = fma52hi(res[130], a[59], a[70]); // Sum(129) res[130] = fma52lo(res[130], a[60], a[70]); // Sum(130) res[131] = fma52hi(res[131], a[60], a[70]); // Sum(130) res[131] = fma52lo(res[131], a[61], a[70]); // Sum(131) res[132] = fma52hi(res[132], a[61], a[70]); // Sum(131) res[120] = fma52lo(res[120], a[49], a[71]); // Sum(120) res[121] = fma52hi(res[121], a[49], a[71]); // Sum(120) res[121] = fma52lo(res[121], a[50], a[71]); // Sum(121) res[122] = fma52hi(res[122], a[50], a[71]); // Sum(121) res[122] = fma52lo(res[122], a[51], a[71]); // Sum(122) res[123] = fma52hi(res[123], a[51], a[71]); // Sum(122) res[123] = fma52lo(res[123], a[52], a[71]); // Sum(123) res[124] = fma52hi(res[124], a[52], a[71]); // Sum(123) res[124] = fma52lo(res[124], a[53], a[71]); // Sum(124) res[125] = fma52hi(res[125], a[53], a[71]); // Sum(124) res[125] = fma52lo(res[125], a[54], a[71]); // Sum(125) res[126] = fma52hi(res[126], a[54], a[71]); // Sum(125) res[126] = fma52lo(res[126], a[55], a[71]); // Sum(126) res[127] = fma52hi(res[127], a[55], a[71]); // Sum(126) res[127] = fma52lo(res[127], a[56], a[71]); // Sum(127) res[128] = fma52hi(res[128], a[56], a[71]); // Sum(127) res[128] = fma52lo(res[128], a[57], a[71]); // Sum(128) res[129] = fma52hi(res[129], a[57], a[71]); // Sum(128) res[129] = fma52lo(res[129], a[58], a[71]); // Sum(129) res[130] = fma52hi(res[130], a[58], a[71]); // Sum(129) res[130] = fma52lo(res[130], a[59], a[71]); // Sum(130) res[131] = fma52hi(res[131], a[59], a[71]); // Sum(130) res[131] = fma52lo(res[131], a[60], a[71]); // Sum(131) res[132] = fma52hi(res[132], a[60], a[71]); // Sum(131) res[120] = fma52lo(res[120], a[48], a[72]); // Sum(120) res[121] = fma52hi(res[121], a[48], a[72]); // Sum(120) res[121] = fma52lo(res[121], a[49], a[72]); // Sum(121) res[122] = fma52hi(res[122], a[49], a[72]); // Sum(121) res[122] = fma52lo(res[122], a[50], a[72]); // Sum(122) res[123] = fma52hi(res[123], a[50], a[72]); // Sum(122) res[123] = fma52lo(res[123], a[51], a[72]); // Sum(123) res[124] = fma52hi(res[124], a[51], a[72]); // Sum(123) res[124] = fma52lo(res[124], a[52], a[72]); // Sum(124) res[125] = fma52hi(res[125], a[52], a[72]); // Sum(124) res[125] = fma52lo(res[125], a[53], a[72]); // Sum(125) res[126] = fma52hi(res[126], a[53], a[72]); // Sum(125) res[126] = fma52lo(res[126], a[54], a[72]); // Sum(126) res[127] = fma52hi(res[127], a[54], a[72]); // Sum(126) res[127] = fma52lo(res[127], a[55], a[72]); // Sum(127) res[128] = fma52hi(res[128], a[55], a[72]); // Sum(127) res[128] = fma52lo(res[128], a[56], a[72]); // Sum(128) res[129] = fma52hi(res[129], a[56], a[72]); // Sum(128) res[129] = fma52lo(res[129], a[57], a[72]); // Sum(129) res[130] = fma52hi(res[130], a[57], a[72]); // Sum(129) res[130] = fma52lo(res[130], a[58], a[72]); // Sum(130) res[131] = fma52hi(res[131], a[58], a[72]); // Sum(130) res[131] = fma52lo(res[131], a[59], a[72]); // Sum(131) res[132] = fma52hi(res[132], a[59], a[72]); // Sum(131) res[120] = fma52lo(res[120], a[47], a[73]); // Sum(120) res[121] = fma52hi(res[121], a[47], a[73]); // Sum(120) res[121] = fma52lo(res[121], a[48], a[73]); // Sum(121) res[122] = fma52hi(res[122], a[48], a[73]); // Sum(121) res[122] = fma52lo(res[122], a[49], a[73]); // Sum(122) res[123] = fma52hi(res[123], a[49], a[73]); // Sum(122) res[123] = fma52lo(res[123], a[50], a[73]); // Sum(123) res[124] = fma52hi(res[124], a[50], a[73]); // Sum(123) res[124] = fma52lo(res[124], a[51], a[73]); // Sum(124) res[125] = fma52hi(res[125], a[51], a[73]); // Sum(124) res[125] = fma52lo(res[125], a[52], a[73]); // Sum(125) res[126] = fma52hi(res[126], a[52], a[73]); // Sum(125) res[126] = fma52lo(res[126], a[53], a[73]); // Sum(126) res[127] = fma52hi(res[127], a[53], a[73]); // Sum(126) res[127] = fma52lo(res[127], a[54], a[73]); // Sum(127) res[128] = fma52hi(res[128], a[54], a[73]); // Sum(127) res[128] = fma52lo(res[128], a[55], a[73]); // Sum(128) res[129] = fma52hi(res[129], a[55], a[73]); // Sum(128) res[129] = fma52lo(res[129], a[56], a[73]); // Sum(129) res[130] = fma52hi(res[130], a[56], a[73]); // Sum(129) res[130] = fma52lo(res[130], a[57], a[73]); // Sum(130) res[131] = fma52hi(res[131], a[57], a[73]); // Sum(130) res[131] = fma52lo(res[131], a[58], a[73]); // Sum(131) res[132] = fma52hi(res[132], a[58], a[73]); // Sum(131) res[120] = fma52lo(res[120], a[46], a[74]); // Sum(120) res[121] = fma52hi(res[121], a[46], a[74]); // Sum(120) res[121] = fma52lo(res[121], a[47], a[74]); // Sum(121) res[122] = fma52hi(res[122], a[47], a[74]); // Sum(121) res[122] = fma52lo(res[122], a[48], a[74]); // Sum(122) res[123] = fma52hi(res[123], a[48], a[74]); // Sum(122) res[123] = fma52lo(res[123], a[49], a[74]); // Sum(123) res[124] = fma52hi(res[124], a[49], a[74]); // Sum(123) res[124] = fma52lo(res[124], a[50], a[74]); // Sum(124) res[125] = fma52hi(res[125], a[50], a[74]); // Sum(124) res[125] = fma52lo(res[125], a[51], a[74]); // Sum(125) res[126] = fma52hi(res[126], a[51], a[74]); // Sum(125) res[126] = fma52lo(res[126], a[52], a[74]); // Sum(126) res[127] = fma52hi(res[127], a[52], a[74]); // Sum(126) res[127] = fma52lo(res[127], a[53], a[74]); // Sum(127) res[128] = fma52hi(res[128], a[53], a[74]); // Sum(127) res[128] = fma52lo(res[128], a[54], a[74]); // Sum(128) res[129] = fma52hi(res[129], a[54], a[74]); // Sum(128) res[129] = fma52lo(res[129], a[55], a[74]); // Sum(129) res[130] = fma52hi(res[130], a[55], a[74]); // Sum(129) res[130] = fma52lo(res[130], a[56], a[74]); // Sum(130) res[131] = fma52hi(res[131], a[56], a[74]); // Sum(130) res[131] = fma52lo(res[131], a[57], a[74]); // Sum(131) res[132] = fma52hi(res[132], a[57], a[74]); // Sum(131) res[120] = fma52lo(res[120], a[45], a[75]); // Sum(120) res[121] = fma52hi(res[121], a[45], a[75]); // Sum(120) res[121] = fma52lo(res[121], a[46], a[75]); // Sum(121) res[122] = fma52hi(res[122], a[46], a[75]); // Sum(121) res[122] = fma52lo(res[122], a[47], a[75]); // Sum(122) res[123] = fma52hi(res[123], a[47], a[75]); // Sum(122) res[123] = fma52lo(res[123], a[48], a[75]); // Sum(123) res[124] = fma52hi(res[124], a[48], a[75]); // Sum(123) res[124] = fma52lo(res[124], a[49], a[75]); // Sum(124) res[125] = fma52hi(res[125], a[49], a[75]); // Sum(124) res[125] = fma52lo(res[125], a[50], a[75]); // Sum(125) res[126] = fma52hi(res[126], a[50], a[75]); // Sum(125) res[126] = fma52lo(res[126], a[51], a[75]); // Sum(126) res[127] = fma52hi(res[127], a[51], a[75]); // Sum(126) res[127] = fma52lo(res[127], a[52], a[75]); // Sum(127) res[128] = fma52hi(res[128], a[52], a[75]); // Sum(127) res[128] = fma52lo(res[128], a[53], a[75]); // Sum(128) res[129] = fma52hi(res[129], a[53], a[75]); // Sum(128) res[129] = fma52lo(res[129], a[54], a[75]); // Sum(129) res[130] = fma52hi(res[130], a[54], a[75]); // Sum(129) res[130] = fma52lo(res[130], a[55], a[75]); // Sum(130) res[131] = fma52hi(res[131], a[55], a[75]); // Sum(130) res[131] = fma52lo(res[131], a[56], a[75]); // Sum(131) res[132] = fma52hi(res[132], a[56], a[75]); // Sum(131) res[120] = fma52lo(res[120], a[44], a[76]); // Sum(120) res[121] = fma52hi(res[121], a[44], a[76]); // Sum(120) res[121] = fma52lo(res[121], a[45], a[76]); // Sum(121) res[122] = fma52hi(res[122], a[45], a[76]); // Sum(121) res[122] = fma52lo(res[122], a[46], a[76]); // Sum(122) res[123] = fma52hi(res[123], a[46], a[76]); // Sum(122) res[123] = fma52lo(res[123], a[47], a[76]); // Sum(123) res[124] = fma52hi(res[124], a[47], a[76]); // Sum(123) res[124] = fma52lo(res[124], a[48], a[76]); // Sum(124) res[125] = fma52hi(res[125], a[48], a[76]); // Sum(124) res[125] = fma52lo(res[125], a[49], a[76]); // Sum(125) res[126] = fma52hi(res[126], a[49], a[76]); // Sum(125) res[126] = fma52lo(res[126], a[50], a[76]); // Sum(126) res[127] = fma52hi(res[127], a[50], a[76]); // Sum(126) res[127] = fma52lo(res[127], a[51], a[76]); // Sum(127) res[128] = fma52hi(res[128], a[51], a[76]); // Sum(127) res[128] = fma52lo(res[128], a[52], a[76]); // Sum(128) res[129] = fma52hi(res[129], a[52], a[76]); // Sum(128) res[129] = fma52lo(res[129], a[53], a[76]); // Sum(129) res[130] = fma52hi(res[130], a[53], a[76]); // Sum(129) res[130] = fma52lo(res[130], a[54], a[76]); // Sum(130) res[131] = fma52hi(res[131], a[54], a[76]); // Sum(130) res[131] = fma52lo(res[131], a[55], a[76]); // Sum(131) res[132] = fma52hi(res[132], a[55], a[76]); // Sum(131) res[120] = fma52lo(res[120], a[43], a[77]); // Sum(120) res[121] = fma52hi(res[121], a[43], a[77]); // Sum(120) res[121] = fma52lo(res[121], a[44], a[77]); // Sum(121) res[122] = fma52hi(res[122], a[44], a[77]); // Sum(121) res[122] = fma52lo(res[122], a[45], a[77]); // Sum(122) res[123] = fma52hi(res[123], a[45], a[77]); // Sum(122) res[123] = fma52lo(res[123], a[46], a[77]); // Sum(123) res[124] = fma52hi(res[124], a[46], a[77]); // Sum(123) res[124] = fma52lo(res[124], a[47], a[77]); // Sum(124) res[125] = fma52hi(res[125], a[47], a[77]); // Sum(124) res[125] = fma52lo(res[125], a[48], a[77]); // Sum(125) res[126] = fma52hi(res[126], a[48], a[77]); // Sum(125) res[126] = fma52lo(res[126], a[49], a[77]); // Sum(126) res[127] = fma52hi(res[127], a[49], a[77]); // Sum(126) res[127] = fma52lo(res[127], a[50], a[77]); // Sum(127) res[128] = fma52hi(res[128], a[50], a[77]); // Sum(127) res[128] = fma52lo(res[128], a[51], a[77]); // Sum(128) res[129] = fma52hi(res[129], a[51], a[77]); // Sum(128) res[129] = fma52lo(res[129], a[52], a[77]); // Sum(129) res[130] = fma52hi(res[130], a[52], a[77]); // Sum(129) res[130] = fma52lo(res[130], a[53], a[77]); // Sum(130) res[131] = fma52hi(res[131], a[53], a[77]); // Sum(130) res[131] = fma52lo(res[131], a[54], a[77]); // Sum(131) res[132] = fma52hi(res[132], a[54], a[77]); // Sum(131) res[120] = fma52lo(res[120], a[42], a[78]); // Sum(120) res[121] = fma52hi(res[121], a[42], a[78]); // Sum(120) res[121] = fma52lo(res[121], a[43], a[78]); // Sum(121) res[122] = fma52hi(res[122], a[43], a[78]); // Sum(121) res[122] = fma52lo(res[122], a[44], a[78]); // Sum(122) res[123] = fma52hi(res[123], a[44], a[78]); // Sum(122) res[123] = fma52lo(res[123], a[45], a[78]); // Sum(123) res[124] = fma52hi(res[124], a[45], a[78]); // Sum(123) res[124] = fma52lo(res[124], a[46], a[78]); // Sum(124) res[125] = fma52hi(res[125], a[46], a[78]); // Sum(124) res[125] = fma52lo(res[125], a[47], a[78]); // Sum(125) res[126] = fma52hi(res[126], a[47], a[78]); // Sum(125) res[126] = fma52lo(res[126], a[48], a[78]); // Sum(126) res[127] = fma52hi(res[127], a[48], a[78]); // Sum(126) res[127] = fma52lo(res[127], a[49], a[78]); // Sum(127) res[128] = fma52hi(res[128], a[49], a[78]); // Sum(127) res[128] = fma52lo(res[128], a[50], a[78]); // Sum(128) res[129] = fma52hi(res[129], a[50], a[78]); // Sum(128) res[129] = fma52lo(res[129], a[51], a[78]); // Sum(129) res[130] = fma52hi(res[130], a[51], a[78]); // Sum(129) res[130] = fma52lo(res[130], a[52], a[78]); // Sum(130) res[131] = fma52hi(res[131], a[52], a[78]); // Sum(130) res[131] = fma52lo(res[131], a[53], a[78]); // Sum(131) res[132] = fma52hi(res[132], a[53], a[78]); // Sum(131) res[120] = add64(res[120], res[120]); // Double(120) res[121] = add64(res[121], res[121]); // Double(121) res[122] = add64(res[122], res[122]); // Double(122) res[123] = add64(res[123], res[123]); // Double(123) res[124] = add64(res[124], res[124]); // Double(124) res[125] = add64(res[125], res[125]); // Double(125) res[126] = add64(res[126], res[126]); // Double(126) res[127] = add64(res[127], res[127]); // Double(127) res[128] = add64(res[128], res[128]); // Double(128) res[129] = add64(res[129], res[129]); // Double(129) res[130] = add64(res[130], res[130]); // Double(130) res[131] = add64(res[131], res[131]); // Double(131) res[120] = fma52lo(res[120], a[60], a[60]); // Add sqr(120) res[121] = fma52hi(res[121], a[60], a[60]); // Add sqr(120) res[122] = fma52lo(res[122], a[61], a[61]); // Add sqr(122) res[123] = fma52hi(res[123], a[61], a[61]); // Add sqr(122) res[124] = fma52lo(res[124], a[62], a[62]); // Add sqr(124) res[125] = fma52hi(res[125], a[62], a[62]); // Add sqr(124) res[126] = fma52lo(res[126], a[63], a[63]); // Add sqr(126) res[127] = fma52hi(res[127], a[63], a[63]); // Add sqr(126) res[128] = fma52lo(res[128], a[64], a[64]); // Add sqr(128) res[129] = fma52hi(res[129], a[64], a[64]); // Add sqr(128) res[130] = fma52lo(res[130], a[65], a[65]); // Add sqr(130) res[131] = fma52hi(res[131], a[65], a[65]); // Add sqr(130) res[132] = fma52lo(res[132], a[65], a[67]); // Sum(132) res[133] = fma52hi(res[133], a[65], a[67]); // Sum(132) res[133] = fma52lo(res[133], a[66], a[67]); // Sum(133) res[134] = fma52hi(res[134], a[66], a[67]); // Sum(133) res[132] = fma52lo(res[132], a[64], a[68]); // Sum(132) res[133] = fma52hi(res[133], a[64], a[68]); // Sum(132) res[133] = fma52lo(res[133], a[65], a[68]); // Sum(133) res[134] = fma52hi(res[134], a[65], a[68]); // Sum(133) res[134] = fma52lo(res[134], a[66], a[68]); // Sum(134) res[135] = fma52hi(res[135], a[66], a[68]); // Sum(134) res[135] = fma52lo(res[135], a[67], a[68]); // Sum(135) res[136] = fma52hi(res[136], a[67], a[68]); // Sum(135) res[132] = fma52lo(res[132], a[63], a[69]); // Sum(132) res[133] = fma52hi(res[133], a[63], a[69]); // Sum(132) res[133] = fma52lo(res[133], a[64], a[69]); // Sum(133) res[134] = fma52hi(res[134], a[64], a[69]); // Sum(133) res[134] = fma52lo(res[134], a[65], a[69]); // Sum(134) res[135] = fma52hi(res[135], a[65], a[69]); // Sum(134) res[135] = fma52lo(res[135], a[66], a[69]); // Sum(135) res[136] = fma52hi(res[136], a[66], a[69]); // Sum(135) res[136] = fma52lo(res[136], a[67], a[69]); // Sum(136) res[137] = fma52hi(res[137], a[67], a[69]); // Sum(136) res[137] = fma52lo(res[137], a[68], a[69]); // Sum(137) res[138] = fma52hi(res[138], a[68], a[69]); // Sum(137) res[132] = fma52lo(res[132], a[62], a[70]); // Sum(132) res[133] = fma52hi(res[133], a[62], a[70]); // Sum(132) res[133] = fma52lo(res[133], a[63], a[70]); // Sum(133) res[134] = fma52hi(res[134], a[63], a[70]); // Sum(133) res[134] = fma52lo(res[134], a[64], a[70]); // Sum(134) res[135] = fma52hi(res[135], a[64], a[70]); // Sum(134) res[135] = fma52lo(res[135], a[65], a[70]); // Sum(135) res[136] = fma52hi(res[136], a[65], a[70]); // Sum(135) res[136] = fma52lo(res[136], a[66], a[70]); // Sum(136) res[137] = fma52hi(res[137], a[66], a[70]); // Sum(136) res[137] = fma52lo(res[137], a[67], a[70]); // Sum(137) res[138] = fma52hi(res[138], a[67], a[70]); // Sum(137) res[138] = fma52lo(res[138], a[68], a[70]); // Sum(138) res[139] = fma52hi(res[139], a[68], a[70]); // Sum(138) res[139] = fma52lo(res[139], a[69], a[70]); // Sum(139) res[140] = fma52hi(res[140], a[69], a[70]); // Sum(139) res[132] = fma52lo(res[132], a[61], a[71]); // Sum(132) res[133] = fma52hi(res[133], a[61], a[71]); // Sum(132) res[133] = fma52lo(res[133], a[62], a[71]); // Sum(133) res[134] = fma52hi(res[134], a[62], a[71]); // Sum(133) res[134] = fma52lo(res[134], a[63], a[71]); // Sum(134) res[135] = fma52hi(res[135], a[63], a[71]); // Sum(134) res[135] = fma52lo(res[135], a[64], a[71]); // Sum(135) res[136] = fma52hi(res[136], a[64], a[71]); // Sum(135) res[136] = fma52lo(res[136], a[65], a[71]); // Sum(136) res[137] = fma52hi(res[137], a[65], a[71]); // Sum(136) res[137] = fma52lo(res[137], a[66], a[71]); // Sum(137) res[138] = fma52hi(res[138], a[66], a[71]); // Sum(137) res[138] = fma52lo(res[138], a[67], a[71]); // Sum(138) res[139] = fma52hi(res[139], a[67], a[71]); // Sum(138) res[139] = fma52lo(res[139], a[68], a[71]); // Sum(139) res[140] = fma52hi(res[140], a[68], a[71]); // Sum(139) res[140] = fma52lo(res[140], a[69], a[71]); // Sum(140) res[141] = fma52hi(res[141], a[69], a[71]); // Sum(140) res[141] = fma52lo(res[141], a[70], a[71]); // Sum(141) res[142] = fma52hi(res[142], a[70], a[71]); // Sum(141) res[132] = fma52lo(res[132], a[60], a[72]); // Sum(132) res[133] = fma52hi(res[133], a[60], a[72]); // Sum(132) res[133] = fma52lo(res[133], a[61], a[72]); // Sum(133) res[134] = fma52hi(res[134], a[61], a[72]); // Sum(133) res[134] = fma52lo(res[134], a[62], a[72]); // Sum(134) res[135] = fma52hi(res[135], a[62], a[72]); // Sum(134) res[135] = fma52lo(res[135], a[63], a[72]); // Sum(135) res[136] = fma52hi(res[136], a[63], a[72]); // Sum(135) res[136] = fma52lo(res[136], a[64], a[72]); // Sum(136) res[137] = fma52hi(res[137], a[64], a[72]); // Sum(136) res[137] = fma52lo(res[137], a[65], a[72]); // Sum(137) res[138] = fma52hi(res[138], a[65], a[72]); // Sum(137) res[138] = fma52lo(res[138], a[66], a[72]); // Sum(138) res[139] = fma52hi(res[139], a[66], a[72]); // Sum(138) res[139] = fma52lo(res[139], a[67], a[72]); // Sum(139) res[140] = fma52hi(res[140], a[67], a[72]); // Sum(139) res[140] = fma52lo(res[140], a[68], a[72]); // Sum(140) res[141] = fma52hi(res[141], a[68], a[72]); // Sum(140) res[141] = fma52lo(res[141], a[69], a[72]); // Sum(141) res[142] = fma52hi(res[142], a[69], a[72]); // Sum(141) res[142] = fma52lo(res[142], a[70], a[72]); // Sum(142) res[143] = fma52hi(res[143], a[70], a[72]); // Sum(142) res[143] = fma52lo(res[143], a[71], a[72]); // Sum(143) res[144] = fma52hi(res[144], a[71], a[72]); // Sum(143) res[132] = fma52lo(res[132], a[59], a[73]); // Sum(132) res[133] = fma52hi(res[133], a[59], a[73]); // Sum(132) res[133] = fma52lo(res[133], a[60], a[73]); // Sum(133) res[134] = fma52hi(res[134], a[60], a[73]); // Sum(133) res[134] = fma52lo(res[134], a[61], a[73]); // Sum(134) res[135] = fma52hi(res[135], a[61], a[73]); // Sum(134) res[135] = fma52lo(res[135], a[62], a[73]); // Sum(135) res[136] = fma52hi(res[136], a[62], a[73]); // Sum(135) res[136] = fma52lo(res[136], a[63], a[73]); // Sum(136) res[137] = fma52hi(res[137], a[63], a[73]); // Sum(136) res[137] = fma52lo(res[137], a[64], a[73]); // Sum(137) res[138] = fma52hi(res[138], a[64], a[73]); // Sum(137) res[138] = fma52lo(res[138], a[65], a[73]); // Sum(138) res[139] = fma52hi(res[139], a[65], a[73]); // Sum(138) res[139] = fma52lo(res[139], a[66], a[73]); // Sum(139) res[140] = fma52hi(res[140], a[66], a[73]); // Sum(139) res[140] = fma52lo(res[140], a[67], a[73]); // Sum(140) res[141] = fma52hi(res[141], a[67], a[73]); // Sum(140) res[141] = fma52lo(res[141], a[68], a[73]); // Sum(141) res[142] = fma52hi(res[142], a[68], a[73]); // Sum(141) res[142] = fma52lo(res[142], a[69], a[73]); // Sum(142) res[143] = fma52hi(res[143], a[69], a[73]); // Sum(142) res[143] = fma52lo(res[143], a[70], a[73]); // Sum(143) res[144] = fma52hi(res[144], a[70], a[73]); // Sum(143) res[132] = fma52lo(res[132], a[58], a[74]); // Sum(132) res[133] = fma52hi(res[133], a[58], a[74]); // Sum(132) res[133] = fma52lo(res[133], a[59], a[74]); // Sum(133) res[134] = fma52hi(res[134], a[59], a[74]); // Sum(133) res[134] = fma52lo(res[134], a[60], a[74]); // Sum(134) res[135] = fma52hi(res[135], a[60], a[74]); // Sum(134) res[135] = fma52lo(res[135], a[61], a[74]); // Sum(135) res[136] = fma52hi(res[136], a[61], a[74]); // Sum(135) res[136] = fma52lo(res[136], a[62], a[74]); // Sum(136) res[137] = fma52hi(res[137], a[62], a[74]); // Sum(136) res[137] = fma52lo(res[137], a[63], a[74]); // Sum(137) res[138] = fma52hi(res[138], a[63], a[74]); // Sum(137) res[138] = fma52lo(res[138], a[64], a[74]); // Sum(138) res[139] = fma52hi(res[139], a[64], a[74]); // Sum(138) res[139] = fma52lo(res[139], a[65], a[74]); // Sum(139) res[140] = fma52hi(res[140], a[65], a[74]); // Sum(139) res[140] = fma52lo(res[140], a[66], a[74]); // Sum(140) res[141] = fma52hi(res[141], a[66], a[74]); // Sum(140) res[141] = fma52lo(res[141], a[67], a[74]); // Sum(141) res[142] = fma52hi(res[142], a[67], a[74]); // Sum(141) res[142] = fma52lo(res[142], a[68], a[74]); // Sum(142) res[143] = fma52hi(res[143], a[68], a[74]); // Sum(142) res[143] = fma52lo(res[143], a[69], a[74]); // Sum(143) res[144] = fma52hi(res[144], a[69], a[74]); // Sum(143) res[132] = fma52lo(res[132], a[57], a[75]); // Sum(132) res[133] = fma52hi(res[133], a[57], a[75]); // Sum(132) res[133] = fma52lo(res[133], a[58], a[75]); // Sum(133) res[134] = fma52hi(res[134], a[58], a[75]); // Sum(133) res[134] = fma52lo(res[134], a[59], a[75]); // Sum(134) res[135] = fma52hi(res[135], a[59], a[75]); // Sum(134) res[135] = fma52lo(res[135], a[60], a[75]); // Sum(135) res[136] = fma52hi(res[136], a[60], a[75]); // Sum(135) res[136] = fma52lo(res[136], a[61], a[75]); // Sum(136) res[137] = fma52hi(res[137], a[61], a[75]); // Sum(136) res[137] = fma52lo(res[137], a[62], a[75]); // Sum(137) res[138] = fma52hi(res[138], a[62], a[75]); // Sum(137) res[138] = fma52lo(res[138], a[63], a[75]); // Sum(138) res[139] = fma52hi(res[139], a[63], a[75]); // Sum(138) res[139] = fma52lo(res[139], a[64], a[75]); // Sum(139) res[140] = fma52hi(res[140], a[64], a[75]); // Sum(139) res[140] = fma52lo(res[140], a[65], a[75]); // Sum(140) res[141] = fma52hi(res[141], a[65], a[75]); // Sum(140) res[141] = fma52lo(res[141], a[66], a[75]); // Sum(141) res[142] = fma52hi(res[142], a[66], a[75]); // Sum(141) res[142] = fma52lo(res[142], a[67], a[75]); // Sum(142) res[143] = fma52hi(res[143], a[67], a[75]); // Sum(142) res[143] = fma52lo(res[143], a[68], a[75]); // Sum(143) res[144] = fma52hi(res[144], a[68], a[75]); // Sum(143) res[132] = fma52lo(res[132], a[56], a[76]); // Sum(132) res[133] = fma52hi(res[133], a[56], a[76]); // Sum(132) res[133] = fma52lo(res[133], a[57], a[76]); // Sum(133) res[134] = fma52hi(res[134], a[57], a[76]); // Sum(133) res[134] = fma52lo(res[134], a[58], a[76]); // Sum(134) res[135] = fma52hi(res[135], a[58], a[76]); // Sum(134) res[135] = fma52lo(res[135], a[59], a[76]); // Sum(135) res[136] = fma52hi(res[136], a[59], a[76]); // Sum(135) res[136] = fma52lo(res[136], a[60], a[76]); // Sum(136) res[137] = fma52hi(res[137], a[60], a[76]); // Sum(136) res[137] = fma52lo(res[137], a[61], a[76]); // Sum(137) res[138] = fma52hi(res[138], a[61], a[76]); // Sum(137) res[138] = fma52lo(res[138], a[62], a[76]); // Sum(138) res[139] = fma52hi(res[139], a[62], a[76]); // Sum(138) res[139] = fma52lo(res[139], a[63], a[76]); // Sum(139) res[140] = fma52hi(res[140], a[63], a[76]); // Sum(139) res[140] = fma52lo(res[140], a[64], a[76]); // Sum(140) res[141] = fma52hi(res[141], a[64], a[76]); // Sum(140) res[141] = fma52lo(res[141], a[65], a[76]); // Sum(141) res[142] = fma52hi(res[142], a[65], a[76]); // Sum(141) res[142] = fma52lo(res[142], a[66], a[76]); // Sum(142) res[143] = fma52hi(res[143], a[66], a[76]); // Sum(142) res[143] = fma52lo(res[143], a[67], a[76]); // Sum(143) res[144] = fma52hi(res[144], a[67], a[76]); // Sum(143) res[132] = fma52lo(res[132], a[55], a[77]); // Sum(132) res[133] = fma52hi(res[133], a[55], a[77]); // Sum(132) res[133] = fma52lo(res[133], a[56], a[77]); // Sum(133) res[134] = fma52hi(res[134], a[56], a[77]); // Sum(133) res[134] = fma52lo(res[134], a[57], a[77]); // Sum(134) res[135] = fma52hi(res[135], a[57], a[77]); // Sum(134) res[135] = fma52lo(res[135], a[58], a[77]); // Sum(135) res[136] = fma52hi(res[136], a[58], a[77]); // Sum(135) res[136] = fma52lo(res[136], a[59], a[77]); // Sum(136) res[137] = fma52hi(res[137], a[59], a[77]); // Sum(136) res[137] = fma52lo(res[137], a[60], a[77]); // Sum(137) res[138] = fma52hi(res[138], a[60], a[77]); // Sum(137) res[138] = fma52lo(res[138], a[61], a[77]); // Sum(138) res[139] = fma52hi(res[139], a[61], a[77]); // Sum(138) res[139] = fma52lo(res[139], a[62], a[77]); // Sum(139) res[140] = fma52hi(res[140], a[62], a[77]); // Sum(139) res[140] = fma52lo(res[140], a[63], a[77]); // Sum(140) res[141] = fma52hi(res[141], a[63], a[77]); // Sum(140) res[141] = fma52lo(res[141], a[64], a[77]); // Sum(141) res[142] = fma52hi(res[142], a[64], a[77]); // Sum(141) res[142] = fma52lo(res[142], a[65], a[77]); // Sum(142) res[143] = fma52hi(res[143], a[65], a[77]); // Sum(142) res[143] = fma52lo(res[143], a[66], a[77]); // Sum(143) res[144] = fma52hi(res[144], a[66], a[77]); // Sum(143) res[132] = fma52lo(res[132], a[54], a[78]); // Sum(132) res[133] = fma52hi(res[133], a[54], a[78]); // Sum(132) res[133] = fma52lo(res[133], a[55], a[78]); // Sum(133) res[134] = fma52hi(res[134], a[55], a[78]); // Sum(133) res[134] = fma52lo(res[134], a[56], a[78]); // Sum(134) res[135] = fma52hi(res[135], a[56], a[78]); // Sum(134) res[135] = fma52lo(res[135], a[57], a[78]); // Sum(135) res[136] = fma52hi(res[136], a[57], a[78]); // Sum(135) res[136] = fma52lo(res[136], a[58], a[78]); // Sum(136) res[137] = fma52hi(res[137], a[58], a[78]); // Sum(136) res[137] = fma52lo(res[137], a[59], a[78]); // Sum(137) res[138] = fma52hi(res[138], a[59], a[78]); // Sum(137) res[138] = fma52lo(res[138], a[60], a[78]); // Sum(138) res[139] = fma52hi(res[139], a[60], a[78]); // Sum(138) res[139] = fma52lo(res[139], a[61], a[78]); // Sum(139) res[140] = fma52hi(res[140], a[61], a[78]); // Sum(139) res[140] = fma52lo(res[140], a[62], a[78]); // Sum(140) res[141] = fma52hi(res[141], a[62], a[78]); // Sum(140) res[141] = fma52lo(res[141], a[63], a[78]); // Sum(141) res[142] = fma52hi(res[142], a[63], a[78]); // Sum(141) res[142] = fma52lo(res[142], a[64], a[78]); // Sum(142) res[143] = fma52hi(res[143], a[64], a[78]); // Sum(142) res[143] = fma52lo(res[143], a[65], a[78]); // Sum(143) res[144] = fma52hi(res[144], a[65], a[78]); // Sum(143) res[132] = add64(res[132], res[132]); // Double(132) res[133] = add64(res[133], res[133]); // Double(133) res[134] = add64(res[134], res[134]); // Double(134) res[135] = add64(res[135], res[135]); // Double(135) res[136] = add64(res[136], res[136]); // Double(136) res[137] = add64(res[137], res[137]); // Double(137) res[138] = add64(res[138], res[138]); // Double(138) res[139] = add64(res[139], res[139]); // Double(139) res[140] = add64(res[140], res[140]); // Double(140) res[141] = add64(res[141], res[141]); // Double(141) res[142] = add64(res[142], res[142]); // Double(142) res[143] = add64(res[143], res[143]); // Double(143) res[132] = fma52lo(res[132], a[66], a[66]); // Add sqr(132) res[133] = fma52hi(res[133], a[66], a[66]); // Add sqr(132) res[134] = fma52lo(res[134], a[67], a[67]); // Add sqr(134) res[135] = fma52hi(res[135], a[67], a[67]); // Add sqr(134) res[136] = fma52lo(res[136], a[68], a[68]); // Add sqr(136) res[137] = fma52hi(res[137], a[68], a[68]); // Add sqr(136) res[138] = fma52lo(res[138], a[69], a[69]); // Add sqr(138) res[139] = fma52hi(res[139], a[69], a[69]); // Add sqr(138) res[140] = fma52lo(res[140], a[70], a[70]); // Add sqr(140) res[141] = fma52hi(res[141], a[70], a[70]); // Add sqr(140) res[142] = fma52lo(res[142], a[71], a[71]); // Add sqr(142) res[143] = fma52hi(res[143], a[71], a[71]); // Add sqr(142) res[144] = fma52lo(res[144], a[71], a[73]); // Sum(144) res[145] = fma52hi(res[145], a[71], a[73]); // Sum(144) res[145] = fma52lo(res[145], a[72], a[73]); // Sum(145) res[146] = fma52hi(res[146], a[72], a[73]); // Sum(145) res[144] = fma52lo(res[144], a[70], a[74]); // Sum(144) res[145] = fma52hi(res[145], a[70], a[74]); // Sum(144) res[145] = fma52lo(res[145], a[71], a[74]); // Sum(145) res[146] = fma52hi(res[146], a[71], a[74]); // Sum(145) res[146] = fma52lo(res[146], a[72], a[74]); // Sum(146) res[147] = fma52hi(res[147], a[72], a[74]); // Sum(146) res[147] = fma52lo(res[147], a[73], a[74]); // Sum(147) res[148] = fma52hi(res[148], a[73], a[74]); // Sum(147) res[144] = fma52lo(res[144], a[69], a[75]); // Sum(144) res[145] = fma52hi(res[145], a[69], a[75]); // Sum(144) res[145] = fma52lo(res[145], a[70], a[75]); // Sum(145) res[146] = fma52hi(res[146], a[70], a[75]); // Sum(145) res[146] = fma52lo(res[146], a[71], a[75]); // Sum(146) res[147] = fma52hi(res[147], a[71], a[75]); // Sum(146) res[147] = fma52lo(res[147], a[72], a[75]); // Sum(147) res[148] = fma52hi(res[148], a[72], a[75]); // Sum(147) res[148] = fma52lo(res[148], a[73], a[75]); // Sum(148) res[149] = fma52hi(res[149], a[73], a[75]); // Sum(148) res[149] = fma52lo(res[149], a[74], a[75]); // Sum(149) res[150] = fma52hi(res[150], a[74], a[75]); // Sum(149) res[144] = fma52lo(res[144], a[68], a[76]); // Sum(144) res[145] = fma52hi(res[145], a[68], a[76]); // Sum(144) res[145] = fma52lo(res[145], a[69], a[76]); // Sum(145) res[146] = fma52hi(res[146], a[69], a[76]); // Sum(145) res[146] = fma52lo(res[146], a[70], a[76]); // Sum(146) res[147] = fma52hi(res[147], a[70], a[76]); // Sum(146) res[147] = fma52lo(res[147], a[71], a[76]); // Sum(147) res[148] = fma52hi(res[148], a[71], a[76]); // Sum(147) res[148] = fma52lo(res[148], a[72], a[76]); // Sum(148) res[149] = fma52hi(res[149], a[72], a[76]); // Sum(148) res[149] = fma52lo(res[149], a[73], a[76]); // Sum(149) res[150] = fma52hi(res[150], a[73], a[76]); // Sum(149) res[150] = fma52lo(res[150], a[74], a[76]); // Sum(150) res[151] = fma52hi(res[151], a[74], a[76]); // Sum(150) res[151] = fma52lo(res[151], a[75], a[76]); // Sum(151) res[152] = fma52hi(res[152], a[75], a[76]); // Sum(151) res[144] = fma52lo(res[144], a[67], a[77]); // Sum(144) res[145] = fma52hi(res[145], a[67], a[77]); // Sum(144) res[145] = fma52lo(res[145], a[68], a[77]); // Sum(145) res[146] = fma52hi(res[146], a[68], a[77]); // Sum(145) res[146] = fma52lo(res[146], a[69], a[77]); // Sum(146) res[147] = fma52hi(res[147], a[69], a[77]); // Sum(146) res[147] = fma52lo(res[147], a[70], a[77]); // Sum(147) res[148] = fma52hi(res[148], a[70], a[77]); // Sum(147) res[148] = fma52lo(res[148], a[71], a[77]); // Sum(148) res[149] = fma52hi(res[149], a[71], a[77]); // Sum(148) res[149] = fma52lo(res[149], a[72], a[77]); // Sum(149) res[150] = fma52hi(res[150], a[72], a[77]); // Sum(149) res[150] = fma52lo(res[150], a[73], a[77]); // Sum(150) res[151] = fma52hi(res[151], a[73], a[77]); // Sum(150) res[151] = fma52lo(res[151], a[74], a[77]); // Sum(151) res[152] = fma52hi(res[152], a[74], a[77]); // Sum(151) res[152] = fma52lo(res[152], a[75], a[77]); // Sum(152) res[153] = fma52hi(res[153], a[75], a[77]); // Sum(152) res[153] = fma52lo(res[153], a[76], a[77]); // Sum(153) res[154] = fma52hi(res[154], a[76], a[77]); // Sum(153) res[144] = fma52lo(res[144], a[66], a[78]); // Sum(144) res[145] = fma52hi(res[145], a[66], a[78]); // Sum(144) res[145] = fma52lo(res[145], a[67], a[78]); // Sum(145) res[146] = fma52hi(res[146], a[67], a[78]); // Sum(145) res[146] = fma52lo(res[146], a[68], a[78]); // Sum(146) res[147] = fma52hi(res[147], a[68], a[78]); // Sum(146) res[147] = fma52lo(res[147], a[69], a[78]); // Sum(147) res[148] = fma52hi(res[148], a[69], a[78]); // Sum(147) res[148] = fma52lo(res[148], a[70], a[78]); // Sum(148) res[149] = fma52hi(res[149], a[70], a[78]); // Sum(148) res[149] = fma52lo(res[149], a[71], a[78]); // Sum(149) res[150] = fma52hi(res[150], a[71], a[78]); // Sum(149) res[150] = fma52lo(res[150], a[72], a[78]); // Sum(150) res[151] = fma52hi(res[151], a[72], a[78]); // Sum(150) res[151] = fma52lo(res[151], a[73], a[78]); // Sum(151) res[152] = fma52hi(res[152], a[73], a[78]); // Sum(151) res[152] = fma52lo(res[152], a[74], a[78]); // Sum(152) res[153] = fma52hi(res[153], a[74], a[78]); // Sum(152) res[153] = fma52lo(res[153], a[75], a[78]); // Sum(153) res[154] = fma52hi(res[154], a[75], a[78]); // Sum(153) res[154] = fma52lo(res[154], a[76], a[78]); // Sum(154) res[155] = fma52hi(res[155], a[76], a[78]); // Sum(154) res[155] = fma52lo(res[155], a[77], a[78]); // Sum(155) res[156] = fma52hi(res[156], a[77], a[78]); // Sum(155) res[144] = add64(res[144], res[144]); // Double(144) res[145] = add64(res[145], res[145]); // Double(145) res[146] = add64(res[146], res[146]); // Double(146) res[147] = add64(res[147], res[147]); // Double(147) res[148] = add64(res[148], res[148]); // Double(148) res[149] = add64(res[149], res[149]); // Double(149) res[150] = add64(res[150], res[150]); // Double(150) res[151] = add64(res[151], res[151]); // Double(151) res[152] = add64(res[152], res[152]); // Double(152) res[153] = add64(res[153], res[153]); // Double(153) res[154] = add64(res[154], res[154]); // Double(154) res[155] = add64(res[155], res[155]); // Double(155) res[144] = fma52lo(res[144], a[72], a[72]); // Add sqr(144) res[145] = fma52hi(res[145], a[72], a[72]); // Add sqr(144) res[146] = fma52lo(res[146], a[73], a[73]); // Add sqr(146) res[147] = fma52hi(res[147], a[73], a[73]); // Add sqr(146) res[148] = fma52lo(res[148], a[74], a[74]); // Add sqr(148) res[149] = fma52hi(res[149], a[74], a[74]); // Add sqr(148) res[150] = fma52lo(res[150], a[75], a[75]); // Add sqr(150) res[151] = fma52hi(res[151], a[75], a[75]); // Add sqr(150) res[152] = fma52lo(res[152], a[76], a[76]); // Add sqr(152) res[153] = fma52hi(res[153], a[76], a[76]); // Add sqr(152) res[154] = fma52lo(res[154], a[77], a[77]); // Add sqr(154) res[155] = fma52hi(res[155], a[77], a[77]); // Add sqr(154) res[156] = add64(res[156], res[156]); // Double(156) res[156] = fma52lo(res[156], a[78], a[78]); // Add sqr(156) res[157] = fma52hi(res[157], a[78], a[78]); // Add sqr(156) // Montgomery Reduction int it; for (it = 0; it < 80; it += 10) { // Reduction step int jt = 0; if ((it + 0) > 0) res[it + 0] = add64(res[it + 0], srli64(res[it + -1], DIGIT_SIZE)); u[it + 0] = mul52lo(res[it + 0], k); res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + 1] = add64(res[it + 1], srli64(res[it + 0], DIGIT_SIZE)); u[it + 1] = mul52lo(res[it + 1], k); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + 2] = add64(res[it + 2], srli64(res[it + 1], DIGIT_SIZE)); u[it + 2] = mul52lo(res[it + 2], k); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + 3] = add64(res[it + 3], srli64(res[it + 2], DIGIT_SIZE)); u[it + 3] = mul52lo(res[it + 3], k); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + 4] = add64(res[it + 4], srli64(res[it + 3], DIGIT_SIZE)); u[it + 4] = mul52lo(res[it + 4], k); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + 5] = add64(res[it + 5], srli64(res[it + 4], DIGIT_SIZE)); u[it + 5] = mul52lo(res[it + 5], k); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + 6] = add64(res[it + 6], srli64(res[it + 5], DIGIT_SIZE)); u[it + 6] = mul52lo(res[it + 6], k); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + 7] = add64(res[it + 7], srli64(res[it + 6], DIGIT_SIZE)); u[it + 7] = mul52lo(res[it + 7], k); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + 8] = add64(res[it + 8], srli64(res[it + 7], DIGIT_SIZE)); u[it + 8] = mul52lo(res[it + 8], k); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + 9] = add64(res[it + 9], srli64(res[it + 8], DIGIT_SIZE)); u[it + 9] = (it + 9 < 79) ? mul52lo(res[it + 9], k) : get_zero64(); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); for (jt = 10; jt < 80; jt += 10) { // Poly tile res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); } } // Normalization r[0] = and64_const(res[79], DIGIT_MASK); res[80] = add64(res[80], srli64(res[79], DIGIT_SIZE)); r[1] = and64_const(res[80], DIGIT_MASK); res[81] = add64(res[81], srli64(res[80], DIGIT_SIZE)); r[2] = and64_const(res[81], DIGIT_MASK); res[82] = add64(res[82], srli64(res[81], DIGIT_SIZE)); r[3] = and64_const(res[82], DIGIT_MASK); res[83] = add64(res[83], srli64(res[82], DIGIT_SIZE)); r[4] = and64_const(res[83], DIGIT_MASK); res[84] = add64(res[84], srli64(res[83], DIGIT_SIZE)); r[5] = and64_const(res[84], DIGIT_MASK); res[85] = add64(res[85], srli64(res[84], DIGIT_SIZE)); r[6] = and64_const(res[85], DIGIT_MASK); res[86] = add64(res[86], srli64(res[85], DIGIT_SIZE)); r[7] = and64_const(res[86], DIGIT_MASK); res[87] = add64(res[87], srli64(res[86], DIGIT_SIZE)); r[8] = and64_const(res[87], DIGIT_MASK); res[88] = add64(res[88], srli64(res[87], DIGIT_SIZE)); r[9] = and64_const(res[88], DIGIT_MASK); res[89] = add64(res[89], srli64(res[88], DIGIT_SIZE)); r[10] = and64_const(res[89], DIGIT_MASK); res[90] = add64(res[90], srli64(res[89], DIGIT_SIZE)); r[11] = and64_const(res[90], DIGIT_MASK); res[91] = add64(res[91], srli64(res[90], DIGIT_SIZE)); r[12] = and64_const(res[91], DIGIT_MASK); res[92] = add64(res[92], srli64(res[91], DIGIT_SIZE)); r[13] = and64_const(res[92], DIGIT_MASK); res[93] = add64(res[93], srli64(res[92], DIGIT_SIZE)); r[14] = and64_const(res[93], DIGIT_MASK); res[94] = add64(res[94], srli64(res[93], DIGIT_SIZE)); r[15] = and64_const(res[94], DIGIT_MASK); res[95] = add64(res[95], srli64(res[94], DIGIT_SIZE)); r[16] = and64_const(res[95], DIGIT_MASK); res[96] = add64(res[96], srli64(res[95], DIGIT_SIZE)); r[17] = and64_const(res[96], DIGIT_MASK); res[97] = add64(res[97], srli64(res[96], DIGIT_SIZE)); r[18] = and64_const(res[97], DIGIT_MASK); res[98] = add64(res[98], srli64(res[97], DIGIT_SIZE)); r[19] = and64_const(res[98], DIGIT_MASK); res[99] = add64(res[99], srli64(res[98], DIGIT_SIZE)); r[20] = and64_const(res[99], DIGIT_MASK); res[100] = add64(res[100], srli64(res[99], DIGIT_SIZE)); r[21] = and64_const(res[100], DIGIT_MASK); res[101] = add64(res[101], srli64(res[100], DIGIT_SIZE)); r[22] = and64_const(res[101], DIGIT_MASK); res[102] = add64(res[102], srli64(res[101], DIGIT_SIZE)); r[23] = and64_const(res[102], DIGIT_MASK); res[103] = add64(res[103], srli64(res[102], DIGIT_SIZE)); r[24] = and64_const(res[103], DIGIT_MASK); res[104] = add64(res[104], srli64(res[103], DIGIT_SIZE)); r[25] = and64_const(res[104], DIGIT_MASK); res[105] = add64(res[105], srli64(res[104], DIGIT_SIZE)); r[26] = and64_const(res[105], DIGIT_MASK); res[106] = add64(res[106], srli64(res[105], DIGIT_SIZE)); r[27] = and64_const(res[106], DIGIT_MASK); res[107] = add64(res[107], srli64(res[106], DIGIT_SIZE)); r[28] = and64_const(res[107], DIGIT_MASK); res[108] = add64(res[108], srli64(res[107], DIGIT_SIZE)); r[29] = and64_const(res[108], DIGIT_MASK); res[109] = add64(res[109], srli64(res[108], DIGIT_SIZE)); r[30] = and64_const(res[109], DIGIT_MASK); res[110] = add64(res[110], srli64(res[109], DIGIT_SIZE)); r[31] = and64_const(res[110], DIGIT_MASK); res[111] = add64(res[111], srli64(res[110], DIGIT_SIZE)); r[32] = and64_const(res[111], DIGIT_MASK); res[112] = add64(res[112], srli64(res[111], DIGIT_SIZE)); r[33] = and64_const(res[112], DIGIT_MASK); res[113] = add64(res[113], srli64(res[112], DIGIT_SIZE)); r[34] = and64_const(res[113], DIGIT_MASK); res[114] = add64(res[114], srli64(res[113], DIGIT_SIZE)); r[35] = and64_const(res[114], DIGIT_MASK); res[115] = add64(res[115], srli64(res[114], DIGIT_SIZE)); r[36] = and64_const(res[115], DIGIT_MASK); res[116] = add64(res[116], srli64(res[115], DIGIT_SIZE)); r[37] = and64_const(res[116], DIGIT_MASK); res[117] = add64(res[117], srli64(res[116], DIGIT_SIZE)); r[38] = and64_const(res[117], DIGIT_MASK); res[118] = add64(res[118], srli64(res[117], DIGIT_SIZE)); r[39] = and64_const(res[118], DIGIT_MASK); res[119] = add64(res[119], srli64(res[118], DIGIT_SIZE)); r[40] = and64_const(res[119], DIGIT_MASK); res[120] = add64(res[120], srli64(res[119], DIGIT_SIZE)); r[41] = and64_const(res[120], DIGIT_MASK); res[121] = add64(res[121], srli64(res[120], DIGIT_SIZE)); r[42] = and64_const(res[121], DIGIT_MASK); res[122] = add64(res[122], srli64(res[121], DIGIT_SIZE)); r[43] = and64_const(res[122], DIGIT_MASK); res[123] = add64(res[123], srli64(res[122], DIGIT_SIZE)); r[44] = and64_const(res[123], DIGIT_MASK); res[124] = add64(res[124], srli64(res[123], DIGIT_SIZE)); r[45] = and64_const(res[124], DIGIT_MASK); res[125] = add64(res[125], srli64(res[124], DIGIT_SIZE)); r[46] = and64_const(res[125], DIGIT_MASK); res[126] = add64(res[126], srli64(res[125], DIGIT_SIZE)); r[47] = and64_const(res[126], DIGIT_MASK); res[127] = add64(res[127], srli64(res[126], DIGIT_SIZE)); r[48] = and64_const(res[127], DIGIT_MASK); res[128] = add64(res[128], srli64(res[127], DIGIT_SIZE)); r[49] = and64_const(res[128], DIGIT_MASK); res[129] = add64(res[129], srli64(res[128], DIGIT_SIZE)); r[50] = and64_const(res[129], DIGIT_MASK); res[130] = add64(res[130], srli64(res[129], DIGIT_SIZE)); r[51] = and64_const(res[130], DIGIT_MASK); res[131] = add64(res[131], srli64(res[130], DIGIT_SIZE)); r[52] = and64_const(res[131], DIGIT_MASK); res[132] = add64(res[132], srli64(res[131], DIGIT_SIZE)); r[53] = and64_const(res[132], DIGIT_MASK); res[133] = add64(res[133], srli64(res[132], DIGIT_SIZE)); r[54] = and64_const(res[133], DIGIT_MASK); res[134] = add64(res[134], srli64(res[133], DIGIT_SIZE)); r[55] = and64_const(res[134], DIGIT_MASK); res[135] = add64(res[135], srli64(res[134], DIGIT_SIZE)); r[56] = and64_const(res[135], DIGIT_MASK); res[136] = add64(res[136], srli64(res[135], DIGIT_SIZE)); r[57] = and64_const(res[136], DIGIT_MASK); res[137] = add64(res[137], srli64(res[136], DIGIT_SIZE)); r[58] = and64_const(res[137], DIGIT_MASK); res[138] = add64(res[138], srli64(res[137], DIGIT_SIZE)); r[59] = and64_const(res[138], DIGIT_MASK); res[139] = add64(res[139], srli64(res[138], DIGIT_SIZE)); r[60] = and64_const(res[139], DIGIT_MASK); res[140] = add64(res[140], srli64(res[139], DIGIT_SIZE)); r[61] = and64_const(res[140], DIGIT_MASK); res[141] = add64(res[141], srli64(res[140], DIGIT_SIZE)); r[62] = and64_const(res[141], DIGIT_MASK); res[142] = add64(res[142], srli64(res[141], DIGIT_SIZE)); r[63] = and64_const(res[142], DIGIT_MASK); res[143] = add64(res[143], srli64(res[142], DIGIT_SIZE)); r[64] = and64_const(res[143], DIGIT_MASK); res[144] = add64(res[144], srli64(res[143], DIGIT_SIZE)); r[65] = and64_const(res[144], DIGIT_MASK); res[145] = add64(res[145], srli64(res[144], DIGIT_SIZE)); r[66] = and64_const(res[145], DIGIT_MASK); res[146] = add64(res[146], srli64(res[145], DIGIT_SIZE)); r[67] = and64_const(res[146], DIGIT_MASK); res[147] = add64(res[147], srli64(res[146], DIGIT_SIZE)); r[68] = and64_const(res[147], DIGIT_MASK); res[148] = add64(res[148], srli64(res[147], DIGIT_SIZE)); r[69] = and64_const(res[148], DIGIT_MASK); res[149] = add64(res[149], srli64(res[148], DIGIT_SIZE)); r[70] = and64_const(res[149], DIGIT_MASK); res[150] = add64(res[150], srli64(res[149], DIGIT_SIZE)); r[71] = and64_const(res[150], DIGIT_MASK); res[151] = add64(res[151], srli64(res[150], DIGIT_SIZE)); r[72] = and64_const(res[151], DIGIT_MASK); res[152] = add64(res[152], srli64(res[151], DIGIT_SIZE)); r[73] = and64_const(res[152], DIGIT_MASK); res[153] = add64(res[153], srli64(res[152], DIGIT_SIZE)); r[74] = and64_const(res[153], DIGIT_MASK); res[154] = add64(res[154], srli64(res[153], DIGIT_SIZE)); r[75] = and64_const(res[154], DIGIT_MASK); res[155] = add64(res[155], srli64(res[154], DIGIT_SIZE)); r[76] = and64_const(res[155], DIGIT_MASK); res[156] = add64(res[156], srli64(res[155], DIGIT_SIZE)); r[77] = and64_const(res[156], DIGIT_MASK); res[157] = add64(res[157], srli64(res[156], DIGIT_SIZE)); r[78] = and64_const(res[157], DIGIT_MASK); } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams5x52x10_diagonal_mb8.c000066400000000000000000000467071470420105600347650ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) void AMS5x52x10_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res0, res1, res2, res3, res4, res5, res6, res7, res8, res9, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; int iter; const int iters = 5; k = loadu64((U64 *)k0_mb); for (iter = 0; iter < iters; ++iter) { res0 = res1 = res2 = res3 = res4 = res5 = res6 = res7 = res8 = res9 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = get_zero64(); // Calculate full square res1 = fma52lo(res1, a[0], a[1]); // Sum(1) res2 = fma52hi(res2, a[0], a[1]); // Sum(1) res2 = fma52lo(res2, a[0], a[2]); // Sum(2) res3 = fma52hi(res3, a[0], a[2]); // Sum(2) res3 = fma52lo(res3, a[1], a[2]); // Sum(3) res4 = fma52hi(res4, a[1], a[2]); // Sum(3) res3 = fma52lo(res3, a[0], a[3]); // Sum(3) res4 = fma52hi(res4, a[0], a[3]); // Sum(3) res4 = fma52lo(res4, a[1], a[3]); // Sum(4) res5 = fma52hi(res5, a[1], a[3]); // Sum(4) res5 = fma52lo(res5, a[2], a[3]); // Sum(5) res6 = fma52hi(res6, a[2], a[3]); // Sum(5) res4 = fma52lo(res4, a[0], a[4]); // Sum(4) res5 = fma52hi(res5, a[0], a[4]); // Sum(4) res5 = fma52lo(res5, a[1], a[4]); // Sum(5) res6 = fma52hi(res6, a[1], a[4]); // Sum(5) res6 = fma52lo(res6, a[2], a[4]); // Sum(6) res7 = fma52hi(res7, a[2], a[4]); // Sum(6) res7 = fma52lo(res7, a[3], a[4]); // Sum(7) res8 = fma52hi(res8, a[3], a[4]); // Sum(7) res5 = fma52lo(res5, a[0], a[5]); // Sum(5) res6 = fma52hi(res6, a[0], a[5]); // Sum(5) res6 = fma52lo(res6, a[1], a[5]); // Sum(6) res7 = fma52hi(res7, a[1], a[5]); // Sum(6) res7 = fma52lo(res7, a[2], a[5]); // Sum(7) res8 = fma52hi(res8, a[2], a[5]); // Sum(7) res8 = fma52lo(res8, a[3], a[5]); // Sum(8) res9 = fma52hi(res9, a[3], a[5]); // Sum(8) res9 = fma52lo(res9, a[4], a[5]); // Sum(9) res10 = fma52hi(res10, a[4], a[5]); // Sum(9) res6 = fma52lo(res6, a[0], a[6]); // Sum(6) res7 = fma52hi(res7, a[0], a[6]); // Sum(6) res7 = fma52lo(res7, a[1], a[6]); // Sum(7) res8 = fma52hi(res8, a[1], a[6]); // Sum(7) res8 = fma52lo(res8, a[2], a[6]); // Sum(8) res9 = fma52hi(res9, a[2], a[6]); // Sum(8) res9 = fma52lo(res9, a[3], a[6]); // Sum(9) res10 = fma52hi(res10, a[3], a[6]); // Sum(9) res10 = fma52lo(res10, a[4], a[6]); // Sum(10) res11 = fma52hi(res11, a[4], a[6]); // Sum(10) res11 = fma52lo(res11, a[5], a[6]); // Sum(11) res12 = fma52hi(res12, a[5], a[6]); // Sum(11) res7 = fma52lo(res7, a[0], a[7]); // Sum(7) res8 = fma52hi(res8, a[0], a[7]); // Sum(7) res8 = fma52lo(res8, a[1], a[7]); // Sum(8) res9 = fma52hi(res9, a[1], a[7]); // Sum(8) res9 = fma52lo(res9, a[2], a[7]); // Sum(9) res10 = fma52hi(res10, a[2], a[7]); // Sum(9) res10 = fma52lo(res10, a[3], a[7]); // Sum(10) res11 = fma52hi(res11, a[3], a[7]); // Sum(10) res11 = fma52lo(res11, a[4], a[7]); // Sum(11) res12 = fma52hi(res12, a[4], a[7]); // Sum(11) res8 = fma52lo(res8, a[0], a[8]); // Sum(8) res9 = fma52hi(res9, a[0], a[8]); // Sum(8) res9 = fma52lo(res9, a[1], a[8]); // Sum(9) res10 = fma52hi(res10, a[1], a[8]); // Sum(9) res10 = fma52lo(res10, a[2], a[8]); // Sum(10) res11 = fma52hi(res11, a[2], a[8]); // Sum(10) res11 = fma52lo(res11, a[3], a[8]); // Sum(11) res12 = fma52hi(res12, a[3], a[8]); // Sum(11) res9 = fma52lo(res9, a[0], a[9]); // Sum(9) res10 = fma52hi(res10, a[0], a[9]); // Sum(9) res10 = fma52lo(res10, a[1], a[9]); // Sum(10) res11 = fma52hi(res11, a[1], a[9]); // Sum(10) res11 = fma52lo(res11, a[2], a[9]); // Sum(11) res12 = fma52hi(res12, a[2], a[9]); // Sum(11) res0 = add64(res0, res0); // Double(0) res1 = add64(res1, res1); // Double(1) res2 = add64(res2, res2); // Double(2) res3 = add64(res3, res3); // Double(3) res4 = add64(res4, res4); // Double(4) res5 = add64(res5, res5); // Double(5) res6 = add64(res6, res6); // Double(6) res7 = add64(res7, res7); // Double(7) res8 = add64(res8, res8); // Double(8) res9 = add64(res9, res9); // Double(9) res10 = add64(res10, res10); // Double(10) res11 = add64(res11, res11); // Double(11) res0 = fma52lo(res0, a[0], a[0]); // Add sqr(0) res1 = fma52hi(res1, a[0], a[0]); // Add sqr(0) res2 = fma52lo(res2, a[1], a[1]); // Add sqr(2) res3 = fma52hi(res3, a[1], a[1]); // Add sqr(2) res4 = fma52lo(res4, a[2], a[2]); // Add sqr(4) res5 = fma52hi(res5, a[2], a[2]); // Add sqr(4) res6 = fma52lo(res6, a[3], a[3]); // Add sqr(6) res7 = fma52hi(res7, a[3], a[3]); // Add sqr(6) res8 = fma52lo(res8, a[4], a[4]); // Add sqr(8) res9 = fma52hi(res9, a[4], a[4]); // Add sqr(8) res10 = fma52lo(res10, a[5], a[5]); // Add sqr(10) res11 = fma52hi(res11, a[5], a[5]); // Add sqr(10) res12 = fma52lo(res12, a[5], a[7]); // Sum(12) res13 = fma52hi(res13, a[5], a[7]); // Sum(12) res13 = fma52lo(res13, a[6], a[7]); // Sum(13) res14 = fma52hi(res14, a[6], a[7]); // Sum(13) res12 = fma52lo(res12, a[4], a[8]); // Sum(12) res13 = fma52hi(res13, a[4], a[8]); // Sum(12) res13 = fma52lo(res13, a[5], a[8]); // Sum(13) res14 = fma52hi(res14, a[5], a[8]); // Sum(13) res14 = fma52lo(res14, a[6], a[8]); // Sum(14) res15 = fma52hi(res15, a[6], a[8]); // Sum(14) res15 = fma52lo(res15, a[7], a[8]); // Sum(15) res16 = fma52hi(res16, a[7], a[8]); // Sum(15) res12 = fma52lo(res12, a[3], a[9]); // Sum(12) res13 = fma52hi(res13, a[3], a[9]); // Sum(12) res13 = fma52lo(res13, a[4], a[9]); // Sum(13) res14 = fma52hi(res14, a[4], a[9]); // Sum(13) res14 = fma52lo(res14, a[5], a[9]); // Sum(14) res15 = fma52hi(res15, a[5], a[9]); // Sum(14) res15 = fma52lo(res15, a[6], a[9]); // Sum(15) res16 = fma52hi(res16, a[6], a[9]); // Sum(15) res16 = fma52lo(res16, a[7], a[9]); // Sum(16) res17 = fma52hi(res17, a[7], a[9]); // Sum(16) res17 = fma52lo(res17, a[8], a[9]); // Sum(17) res18 = fma52hi(res18, a[8], a[9]); // Sum(17) res12 = add64(res12, res12); // Double(12) res13 = add64(res13, res13); // Double(13) res14 = add64(res14, res14); // Double(14) res15 = add64(res15, res15); // Double(15) res16 = add64(res16, res16); // Double(16) res17 = add64(res17, res17); // Double(17) res18 = add64(res18, res18); // Double(18) res12 = fma52lo(res12, a[6], a[6]); // Add sqr(12) res13 = fma52hi(res13, a[6], a[6]); // Add sqr(12) res14 = fma52lo(res14, a[7], a[7]); // Add sqr(14) res15 = fma52hi(res15, a[7], a[7]); // Add sqr(14) res16 = fma52lo(res16, a[8], a[8]); // Add sqr(16) res17 = fma52hi(res17, a[8], a[8]); // Add sqr(16) res18 = fma52lo(res18, a[9], a[9]); // Add sqr(18) res19 = fma52hi(res19, a[9], a[9]); // Add sqr(18) // Generate u_i U64 u0 = mul52lo(res0, k); ASM("jmp l0\nl0:\n"); // Create u0 fma52lo_mem(res0, res0, u0, m, SIMD_BYTES * 0); fma52hi_mem(res1, res1, u0, m, SIMD_BYTES * 0); res1 = fma52lo(res1, u0, m[1]); res2 = fma52hi(res2, u0, m[1]); res1 = add64(res1, srli64(res0, DIGIT_SIZE)); U64 u1 = mul52lo(res1, k); fma52lo_mem(res2, res2, u0, m, SIMD_BYTES * 2); fma52hi_mem(res3, res3, u0, m, SIMD_BYTES * 2); res3 = fma52lo(res3, u0, m[3]); res4 = fma52hi(res4, u0, m[3]); fma52lo_mem(res4, res4, u0, m, SIMD_BYTES * 4); fma52hi_mem(res5, res5, u0, m, SIMD_BYTES * 4); res5 = fma52lo(res5, u0, m[5]); res6 = fma52hi(res6, u0, m[5]); fma52lo_mem(res6, res6, u0, m, SIMD_BYTES * 6); fma52hi_mem(res7, res7, u0, m, SIMD_BYTES * 6); res7 = fma52lo(res7, u0, m[7]); res8 = fma52hi(res8, u0, m[7]); fma52lo_mem(res8, res8, u0, m, SIMD_BYTES * 8); fma52hi_mem(res9, res9, u0, m, SIMD_BYTES * 8); res9 = fma52lo(res9, u0, m[9]); res10 = fma52hi(res10, u0, m[9]); // Create u1 fma52lo_mem(res1, res1, u1, m, SIMD_BYTES * 0); fma52hi_mem(res2, res2, u1, m, SIMD_BYTES * 0); res2 = fma52lo(res2, u1, m[1]); res3 = fma52hi(res3, u1, m[1]); res2 = add64(res2, srli64(res1, DIGIT_SIZE)); U64 u2 = mul52lo(res2, k); fma52lo_mem(res3, res3, u1, m, SIMD_BYTES * 2); fma52hi_mem(res4, res4, u1, m, SIMD_BYTES * 2); res4 = fma52lo(res4, u1, m[3]); res5 = fma52hi(res5, u1, m[3]); fma52lo_mem(res5, res5, u1, m, SIMD_BYTES * 4); fma52hi_mem(res6, res6, u1, m, SIMD_BYTES * 4); res6 = fma52lo(res6, u1, m[5]); res7 = fma52hi(res7, u1, m[5]); fma52lo_mem(res7, res7, u1, m, SIMD_BYTES * 6); fma52hi_mem(res8, res8, u1, m, SIMD_BYTES * 6); res8 = fma52lo(res8, u1, m[7]); res9 = fma52hi(res9, u1, m[7]); fma52lo_mem(res9, res9, u1, m, SIMD_BYTES * 8); fma52hi_mem(res10, res10, u1, m, SIMD_BYTES * 8); res10 = fma52lo(res10, u1, m[9]); res11 = fma52hi(res11, u1, m[9]); ASM("jmp l2\nl2:\n"); // Create u2 fma52lo_mem(res2, res2, u2, m, SIMD_BYTES * 0); fma52hi_mem(res3, res3, u2, m, SIMD_BYTES * 0); res3 = fma52lo(res3, u2, m[1]); res4 = fma52hi(res4, u2, m[1]); res3 = add64(res3, srli64(res2, DIGIT_SIZE)); U64 u3 = mul52lo(res3, k); fma52lo_mem(res4, res4, u2, m, SIMD_BYTES * 2); fma52hi_mem(res5, res5, u2, m, SIMD_BYTES * 2); res5 = fma52lo(res5, u2, m[3]); res6 = fma52hi(res6, u2, m[3]); fma52lo_mem(res6, res6, u2, m, SIMD_BYTES * 4); fma52hi_mem(res7, res7, u2, m, SIMD_BYTES * 4); res7 = fma52lo(res7, u2, m[5]); res8 = fma52hi(res8, u2, m[5]); fma52lo_mem(res8, res8, u2, m, SIMD_BYTES * 6); fma52hi_mem(res9, res9, u2, m, SIMD_BYTES * 6); res9 = fma52lo(res9, u2, m[7]); res10 = fma52hi(res10, u2, m[7]); fma52lo_mem(res10, res10, u2, m, SIMD_BYTES * 8); fma52hi_mem(res11, res11, u2, m, SIMD_BYTES * 8); res11 = fma52lo(res11, u2, m[9]); res12 = fma52hi(res12, u2, m[9]); // Create u3 fma52lo_mem(res3, res3, u3, m, SIMD_BYTES * 0); fma52hi_mem(res4, res4, u3, m, SIMD_BYTES * 0); res4 = fma52lo(res4, u3, m[1]); res5 = fma52hi(res5, u3, m[1]); res4 = add64(res4, srli64(res3, DIGIT_SIZE)); U64 u4 = mul52lo(res4, k); fma52lo_mem(res5, res5, u3, m, SIMD_BYTES * 2); fma52hi_mem(res6, res6, u3, m, SIMD_BYTES * 2); res6 = fma52lo(res6, u3, m[3]); res7 = fma52hi(res7, u3, m[3]); fma52lo_mem(res7, res7, u3, m, SIMD_BYTES * 4); fma52hi_mem(res8, res8, u3, m, SIMD_BYTES * 4); res8 = fma52lo(res8, u3, m[5]); res9 = fma52hi(res9, u3, m[5]); fma52lo_mem(res9, res9, u3, m, SIMD_BYTES * 6); fma52hi_mem(res10, res10, u3, m, SIMD_BYTES * 6); res10 = fma52lo(res10, u3, m[7]); res11 = fma52hi(res11, u3, m[7]); fma52lo_mem(res11, res11, u3, m, SIMD_BYTES * 8); fma52hi_mem(res12, res12, u3, m, SIMD_BYTES * 8); res12 = fma52lo(res12, u3, m[9]); res13 = fma52hi(res13, u3, m[9]); ASM("jmp l4\nl4:\n"); // Create u4 fma52lo_mem(res4, res4, u4, m, SIMD_BYTES * 0); fma52hi_mem(res5, res5, u4, m, SIMD_BYTES * 0); res5 = fma52lo(res5, u4, m[1]); res6 = fma52hi(res6, u4, m[1]); res5 = add64(res5, srli64(res4, DIGIT_SIZE)); U64 u5 = mul52lo(res5, k); fma52lo_mem(res6, res6, u4, m, SIMD_BYTES * 2); fma52hi_mem(res7, res7, u4, m, SIMD_BYTES * 2); res7 = fma52lo(res7, u4, m[3]); res8 = fma52hi(res8, u4, m[3]); fma52lo_mem(res8, res8, u4, m, SIMD_BYTES * 4); fma52hi_mem(res9, res9, u4, m, SIMD_BYTES * 4); res9 = fma52lo(res9, u4, m[5]); res10 = fma52hi(res10, u4, m[5]); fma52lo_mem(res10, res10, u4, m, SIMD_BYTES * 6); fma52hi_mem(res11, res11, u4, m, SIMD_BYTES * 6); res11 = fma52lo(res11, u4, m[7]); res12 = fma52hi(res12, u4, m[7]); fma52lo_mem(res12, res12, u4, m, SIMD_BYTES * 8); fma52hi_mem(res13, res13, u4, m, SIMD_BYTES * 8); res13 = fma52lo(res13, u4, m[9]); res14 = fma52hi(res14, u4, m[9]); // Create u5 fma52lo_mem(res5, res5, u5, m, SIMD_BYTES * 0); fma52hi_mem(res6, res6, u5, m, SIMD_BYTES * 0); res6 = fma52lo(res6, u5, m[1]); res7 = fma52hi(res7, u5, m[1]); res6 = add64(res6, srli64(res5, DIGIT_SIZE)); U64 u6 = mul52lo(res6, k); fma52lo_mem(res7, res7, u5, m, SIMD_BYTES * 2); fma52hi_mem(res8, res8, u5, m, SIMD_BYTES * 2); res8 = fma52lo(res8, u5, m[3]); res9 = fma52hi(res9, u5, m[3]); fma52lo_mem(res9, res9, u5, m, SIMD_BYTES * 4); fma52hi_mem(res10, res10, u5, m, SIMD_BYTES * 4); res10 = fma52lo(res10, u5, m[5]); res11 = fma52hi(res11, u5, m[5]); fma52lo_mem(res11, res11, u5, m, SIMD_BYTES * 6); fma52hi_mem(res12, res12, u5, m, SIMD_BYTES * 6); res12 = fma52lo(res12, u5, m[7]); res13 = fma52hi(res13, u5, m[7]); fma52lo_mem(res13, res13, u5, m, SIMD_BYTES * 8); fma52hi_mem(res14, res14, u5, m, SIMD_BYTES * 8); res14 = fma52lo(res14, u5, m[9]); res15 = fma52hi(res15, u5, m[9]); ASM("jmp l6\nl6:\n"); // Create u6 fma52lo_mem(res6, res6, u6, m, SIMD_BYTES * 0); fma52hi_mem(res7, res7, u6, m, SIMD_BYTES * 0); res7 = fma52lo(res7, u6, m[1]); res8 = fma52hi(res8, u6, m[1]); res7 = add64(res7, srli64(res6, DIGIT_SIZE)); U64 u7 = mul52lo(res7, k); fma52lo_mem(res8, res8, u6, m, SIMD_BYTES * 2); fma52hi_mem(res9, res9, u6, m, SIMD_BYTES * 2); res9 = fma52lo(res9, u6, m[3]); res10 = fma52hi(res10, u6, m[3]); fma52lo_mem(res10, res10, u6, m, SIMD_BYTES * 4); fma52hi_mem(res11, res11, u6, m, SIMD_BYTES * 4); res11 = fma52lo(res11, u6, m[5]); res12 = fma52hi(res12, u6, m[5]); fma52lo_mem(res12, res12, u6, m, SIMD_BYTES * 6); fma52hi_mem(res13, res13, u6, m, SIMD_BYTES * 6); res13 = fma52lo(res13, u6, m[7]); res14 = fma52hi(res14, u6, m[7]); fma52lo_mem(res14, res14, u6, m, SIMD_BYTES * 8); fma52hi_mem(res15, res15, u6, m, SIMD_BYTES * 8); res15 = fma52lo(res15, u6, m[9]); res16 = fma52hi(res16, u6, m[9]); // Create u7 fma52lo_mem(res7, res7, u7, m, SIMD_BYTES * 0); fma52hi_mem(res8, res8, u7, m, SIMD_BYTES * 0); res8 = fma52lo(res8, u7, m[1]); res9 = fma52hi(res9, u7, m[1]); res8 = add64(res8, srli64(res7, DIGIT_SIZE)); U64 u8 = mul52lo(res8, k); fma52lo_mem(res9, res9, u7, m, SIMD_BYTES * 2); fma52hi_mem(res10, res10, u7, m, SIMD_BYTES * 2); res10 = fma52lo(res10, u7, m[3]); res11 = fma52hi(res11, u7, m[3]); fma52lo_mem(res11, res11, u7, m, SIMD_BYTES * 4); fma52hi_mem(res12, res12, u7, m, SIMD_BYTES * 4); res12 = fma52lo(res12, u7, m[5]); res13 = fma52hi(res13, u7, m[5]); fma52lo_mem(res13, res13, u7, m, SIMD_BYTES * 6); fma52hi_mem(res14, res14, u7, m, SIMD_BYTES * 6); res14 = fma52lo(res14, u7, m[7]); res15 = fma52hi(res15, u7, m[7]); fma52lo_mem(res15, res15, u7, m, SIMD_BYTES * 8); fma52hi_mem(res16, res16, u7, m, SIMD_BYTES * 8); res16 = fma52lo(res16, u7, m[9]); res17 = fma52hi(res17, u7, m[9]); ASM("jmp l8\nl8:\n"); // Create u8 fma52lo_mem(res8, res8, u8, m, SIMD_BYTES * 0); fma52hi_mem(res9, res9, u8, m, SIMD_BYTES * 0); res9 = fma52lo(res9, u8, m[1]); res10 = fma52hi(res10, u8, m[1]); res9 = add64(res9, srli64(res8, DIGIT_SIZE)); U64 u9 = mul52lo(res9, k); fma52lo_mem(res10, res10, u8, m, SIMD_BYTES * 2); fma52hi_mem(res11, res11, u8, m, SIMD_BYTES * 2); res11 = fma52lo(res11, u8, m[3]); res12 = fma52hi(res12, u8, m[3]); fma52lo_mem(res12, res12, u8, m, SIMD_BYTES * 4); fma52hi_mem(res13, res13, u8, m, SIMD_BYTES * 4); res13 = fma52lo(res13, u8, m[5]); res14 = fma52hi(res14, u8, m[5]); fma52lo_mem(res14, res14, u8, m, SIMD_BYTES * 6); fma52hi_mem(res15, res15, u8, m, SIMD_BYTES * 6); res15 = fma52lo(res15, u8, m[7]); res16 = fma52hi(res16, u8, m[7]); fma52lo_mem(res16, res16, u8, m, SIMD_BYTES * 8); fma52hi_mem(res17, res17, u8, m, SIMD_BYTES * 8); res17 = fma52lo(res17, u8, m[9]); res18 = fma52hi(res18, u8, m[9]); // Create u9 fma52lo_mem(res9, res9, u9, m, SIMD_BYTES * 0); fma52hi_mem(res10, res10, u9, m, SIMD_BYTES * 0); res10 = fma52lo(res10, u9, m[1]); res11 = fma52hi(res11, u9, m[1]); res10 = add64(res10, srli64(res9, DIGIT_SIZE)); fma52lo_mem(res11, res11, u9, m, SIMD_BYTES * 2); fma52hi_mem(res12, res12, u9, m, SIMD_BYTES * 2); res12 = fma52lo(res12, u9, m[3]); res13 = fma52hi(res13, u9, m[3]); fma52lo_mem(res13, res13, u9, m, SIMD_BYTES * 4); fma52hi_mem(res14, res14, u9, m, SIMD_BYTES * 4); res14 = fma52lo(res14, u9, m[5]); res15 = fma52hi(res15, u9, m[5]); fma52lo_mem(res15, res15, u9, m, SIMD_BYTES * 6); fma52hi_mem(res16, res16, u9, m, SIMD_BYTES * 6); res16 = fma52lo(res16, u9, m[7]); res17 = fma52hi(res17, u9, m[7]); fma52lo_mem(res17, res17, u9, m, SIMD_BYTES * 8); fma52hi_mem(res18, res18, u9, m, SIMD_BYTES * 8); res18 = fma52lo(res18, u9, m[9]); res19 = fma52hi(res19, u9, m[9]); // Normalization r[0] = res10; res11 = add64(res11, srli64(res10, DIGIT_SIZE)); r[1] = res11; res12 = add64(res12, srli64(res11, DIGIT_SIZE)); r[2] = res12; res13 = add64(res13, srli64(res12, DIGIT_SIZE)); r[3] = res13; res14 = add64(res14, srli64(res13, DIGIT_SIZE)); r[4] = res14; res15 = add64(res15, srli64(res14, DIGIT_SIZE)); r[5] = res15; res16 = add64(res16, srli64(res15, DIGIT_SIZE)); r[6] = res16; res17 = add64(res17, srli64(res16, DIGIT_SIZE)); r[7] = res17; res18 = add64(res18, srli64(res17, DIGIT_SIZE)); r[8] = res18; res19 = add64(res19, srli64(res18, DIGIT_SIZE)); r[9] = res19; a = (U64 *)out_mb; } } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams5x52x20_diagonal_mb8.c000066400000000000000000002114711470420105600347560ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) void AMS5x52x20_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { U64 res0, res1, res2, res3, res4, res5, res6, res7, res8, res9, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19, res20, res21, res22, res23, res24, res25, res26, res27, res28, res29, res30, res31, res32, res33, res34, res35, res36, res37, res38, res39; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; int iter; const int iters = 5; k = loadu64((U64 *)k0_mb); for (iter = 0; iter < iters; ++iter) { res0 = res1 = res2 = res3 = res4 = res5 = res6 = res7 = res8 = res9 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = res20 = res21 = res22 = res23 = res24 = res25 = res26 = res27 = res28 = res29 = res30 = res31 = res32 = res33 = res34 = res35 = res36 = res37 = res38 = res39 = get_zero64(); // Calculate full square res1 = fma52lo(res1, a[0], a[1]); // Sum(1) res2 = fma52hi(res2, a[0], a[1]); // Sum(1) res2 = fma52lo(res2, a[0], a[2]); // Sum(2) res3 = fma52hi(res3, a[0], a[2]); // Sum(2) res3 = fma52lo(res3, a[1], a[2]); // Sum(3) res4 = fma52hi(res4, a[1], a[2]); // Sum(3) res3 = fma52lo(res3, a[0], a[3]); // Sum(3) res4 = fma52hi(res4, a[0], a[3]); // Sum(3) res4 = fma52lo(res4, a[1], a[3]); // Sum(4) res5 = fma52hi(res5, a[1], a[3]); // Sum(4) res5 = fma52lo(res5, a[2], a[3]); // Sum(5) res6 = fma52hi(res6, a[2], a[3]); // Sum(5) res4 = fma52lo(res4, a[0], a[4]); // Sum(4) res5 = fma52hi(res5, a[0], a[4]); // Sum(4) res5 = fma52lo(res5, a[1], a[4]); // Sum(5) res6 = fma52hi(res6, a[1], a[4]); // Sum(5) res6 = fma52lo(res6, a[2], a[4]); // Sum(6) res7 = fma52hi(res7, a[2], a[4]); // Sum(6) res7 = fma52lo(res7, a[3], a[4]); // Sum(7) res8 = fma52hi(res8, a[3], a[4]); // Sum(7) res5 = fma52lo(res5, a[0], a[5]); // Sum(5) res6 = fma52hi(res6, a[0], a[5]); // Sum(5) res6 = fma52lo(res6, a[1], a[5]); // Sum(6) res7 = fma52hi(res7, a[1], a[5]); // Sum(6) res7 = fma52lo(res7, a[2], a[5]); // Sum(7) res8 = fma52hi(res8, a[2], a[5]); // Sum(7) res8 = fma52lo(res8, a[3], a[5]); // Sum(8) res9 = fma52hi(res9, a[3], a[5]); // Sum(8) res9 = fma52lo(res9, a[4], a[5]); // Sum(9) res10 = fma52hi(res10, a[4], a[5]); // Sum(9) res6 = fma52lo(res6, a[0], a[6]); // Sum(6) res7 = fma52hi(res7, a[0], a[6]); // Sum(6) res7 = fma52lo(res7, a[1], a[6]); // Sum(7) res8 = fma52hi(res8, a[1], a[6]); // Sum(7) res8 = fma52lo(res8, a[2], a[6]); // Sum(8) res9 = fma52hi(res9, a[2], a[6]); // Sum(8) res9 = fma52lo(res9, a[3], a[6]); // Sum(9) res10 = fma52hi(res10, a[3], a[6]); // Sum(9) res10 = fma52lo(res10, a[4], a[6]); // Sum(10) res11 = fma52hi(res11, a[4], a[6]); // Sum(10) res11 = fma52lo(res11, a[5], a[6]); // Sum(11) res12 = fma52hi(res12, a[5], a[6]); // Sum(11) res7 = fma52lo(res7, a[0], a[7]); // Sum(7) res8 = fma52hi(res8, a[0], a[7]); // Sum(7) res8 = fma52lo(res8, a[1], a[7]); // Sum(8) res9 = fma52hi(res9, a[1], a[7]); // Sum(8) res9 = fma52lo(res9, a[2], a[7]); // Sum(9) res10 = fma52hi(res10, a[2], a[7]); // Sum(9) res10 = fma52lo(res10, a[3], a[7]); // Sum(10) res11 = fma52hi(res11, a[3], a[7]); // Sum(10) res11 = fma52lo(res11, a[4], a[7]); // Sum(11) res12 = fma52hi(res12, a[4], a[7]); // Sum(11) res8 = fma52lo(res8, a[0], a[8]); // Sum(8) res9 = fma52hi(res9, a[0], a[8]); // Sum(8) res9 = fma52lo(res9, a[1], a[8]); // Sum(9) res10 = fma52hi(res10, a[1], a[8]); // Sum(9) res10 = fma52lo(res10, a[2], a[8]); // Sum(10) res11 = fma52hi(res11, a[2], a[8]); // Sum(10) res11 = fma52lo(res11, a[3], a[8]); // Sum(11) res12 = fma52hi(res12, a[3], a[8]); // Sum(11) res9 = fma52lo(res9, a[0], a[9]); // Sum(9) res10 = fma52hi(res10, a[0], a[9]); // Sum(9) res10 = fma52lo(res10, a[1], a[9]); // Sum(10) res11 = fma52hi(res11, a[1], a[9]); // Sum(10) res11 = fma52lo(res11, a[2], a[9]); // Sum(11) res12 = fma52hi(res12, a[2], a[9]); // Sum(11) res10 = fma52lo(res10, a[0], a[10]); // Sum(10) res11 = fma52hi(res11, a[0], a[10]); // Sum(10) res11 = fma52lo(res11, a[1], a[10]); // Sum(11) res12 = fma52hi(res12, a[1], a[10]); // Sum(11) res11 = fma52lo(res11, a[0], a[11]); // Sum(11) res12 = fma52hi(res12, a[0], a[11]); // Sum(11) res0 = add64(res0, res0); // Double(0) res1 = add64(res1, res1); // Double(1) res2 = add64(res2, res2); // Double(2) res3 = add64(res3, res3); // Double(3) res4 = add64(res4, res4); // Double(4) res5 = add64(res5, res5); // Double(5) res6 = add64(res6, res6); // Double(6) res7 = add64(res7, res7); // Double(7) res8 = add64(res8, res8); // Double(8) res9 = add64(res9, res9); // Double(9) res10 = add64(res10, res10); // Double(10) res11 = add64(res11, res11); // Double(11) res0 = fma52lo(res0, a[0], a[0]); // Add sqr(0) res1 = fma52hi(res1, a[0], a[0]); // Add sqr(0) res2 = fma52lo(res2, a[1], a[1]); // Add sqr(2) res3 = fma52hi(res3, a[1], a[1]); // Add sqr(2) res4 = fma52lo(res4, a[2], a[2]); // Add sqr(4) res5 = fma52hi(res5, a[2], a[2]); // Add sqr(4) res6 = fma52lo(res6, a[3], a[3]); // Add sqr(6) res7 = fma52hi(res7, a[3], a[3]); // Add sqr(6) res8 = fma52lo(res8, a[4], a[4]); // Add sqr(8) res9 = fma52hi(res9, a[4], a[4]); // Add sqr(8) res10 = fma52lo(res10, a[5], a[5]); // Add sqr(10) res11 = fma52hi(res11, a[5], a[5]); // Add sqr(10) res12 = fma52lo(res12, a[5], a[7]); // Sum(12) res13 = fma52hi(res13, a[5], a[7]); // Sum(12) res13 = fma52lo(res13, a[6], a[7]); // Sum(13) res14 = fma52hi(res14, a[6], a[7]); // Sum(13) res12 = fma52lo(res12, a[4], a[8]); // Sum(12) res13 = fma52hi(res13, a[4], a[8]); // Sum(12) res13 = fma52lo(res13, a[5], a[8]); // Sum(13) res14 = fma52hi(res14, a[5], a[8]); // Sum(13) res14 = fma52lo(res14, a[6], a[8]); // Sum(14) res15 = fma52hi(res15, a[6], a[8]); // Sum(14) res15 = fma52lo(res15, a[7], a[8]); // Sum(15) res16 = fma52hi(res16, a[7], a[8]); // Sum(15) res12 = fma52lo(res12, a[3], a[9]); // Sum(12) res13 = fma52hi(res13, a[3], a[9]); // Sum(12) res13 = fma52lo(res13, a[4], a[9]); // Sum(13) res14 = fma52hi(res14, a[4], a[9]); // Sum(13) res14 = fma52lo(res14, a[5], a[9]); // Sum(14) res15 = fma52hi(res15, a[5], a[9]); // Sum(14) res15 = fma52lo(res15, a[6], a[9]); // Sum(15) res16 = fma52hi(res16, a[6], a[9]); // Sum(15) res16 = fma52lo(res16, a[7], a[9]); // Sum(16) res17 = fma52hi(res17, a[7], a[9]); // Sum(16) res17 = fma52lo(res17, a[8], a[9]); // Sum(17) res18 = fma52hi(res18, a[8], a[9]); // Sum(17) res12 = fma52lo(res12, a[2], a[10]); // Sum(12) res13 = fma52hi(res13, a[2], a[10]); // Sum(12) res13 = fma52lo(res13, a[3], a[10]); // Sum(13) res14 = fma52hi(res14, a[3], a[10]); // Sum(13) res14 = fma52lo(res14, a[4], a[10]); // Sum(14) res15 = fma52hi(res15, a[4], a[10]); // Sum(14) res15 = fma52lo(res15, a[5], a[10]); // Sum(15) res16 = fma52hi(res16, a[5], a[10]); // Sum(15) res16 = fma52lo(res16, a[6], a[10]); // Sum(16) res17 = fma52hi(res17, a[6], a[10]); // Sum(16) res17 = fma52lo(res17, a[7], a[10]); // Sum(17) res18 = fma52hi(res18, a[7], a[10]); // Sum(17) res18 = fma52lo(res18, a[8], a[10]); // Sum(18) res19 = fma52hi(res19, a[8], a[10]); // Sum(18) res19 = fma52lo(res19, a[9], a[10]); // Sum(19) res20 = fma52hi(res20, a[9], a[10]); // Sum(19) res12 = fma52lo(res12, a[1], a[11]); // Sum(12) res13 = fma52hi(res13, a[1], a[11]); // Sum(12) res13 = fma52lo(res13, a[2], a[11]); // Sum(13) res14 = fma52hi(res14, a[2], a[11]); // Sum(13) res14 = fma52lo(res14, a[3], a[11]); // Sum(14) res15 = fma52hi(res15, a[3], a[11]); // Sum(14) res15 = fma52lo(res15, a[4], a[11]); // Sum(15) res16 = fma52hi(res16, a[4], a[11]); // Sum(15) res16 = fma52lo(res16, a[5], a[11]); // Sum(16) res17 = fma52hi(res17, a[5], a[11]); // Sum(16) res17 = fma52lo(res17, a[6], a[11]); // Sum(17) res18 = fma52hi(res18, a[6], a[11]); // Sum(17) res18 = fma52lo(res18, a[7], a[11]); // Sum(18) res19 = fma52hi(res19, a[7], a[11]); // Sum(18) res19 = fma52lo(res19, a[8], a[11]); // Sum(19) res20 = fma52hi(res20, a[8], a[11]); // Sum(19) res20 = fma52lo(res20, a[9], a[11]); // Sum(20) res21 = fma52hi(res21, a[9], a[11]); // Sum(20) res21 = fma52lo(res21, a[10], a[11]); // Sum(21) res22 = fma52hi(res22, a[10], a[11]); // Sum(21) res12 = fma52lo(res12, a[0], a[12]); // Sum(12) res13 = fma52hi(res13, a[0], a[12]); // Sum(12) res13 = fma52lo(res13, a[1], a[12]); // Sum(13) res14 = fma52hi(res14, a[1], a[12]); // Sum(13) res14 = fma52lo(res14, a[2], a[12]); // Sum(14) res15 = fma52hi(res15, a[2], a[12]); // Sum(14) res15 = fma52lo(res15, a[3], a[12]); // Sum(15) res16 = fma52hi(res16, a[3], a[12]); // Sum(15) res16 = fma52lo(res16, a[4], a[12]); // Sum(16) res17 = fma52hi(res17, a[4], a[12]); // Sum(16) res17 = fma52lo(res17, a[5], a[12]); // Sum(17) res18 = fma52hi(res18, a[5], a[12]); // Sum(17) res18 = fma52lo(res18, a[6], a[12]); // Sum(18) res19 = fma52hi(res19, a[6], a[12]); // Sum(18) res19 = fma52lo(res19, a[7], a[12]); // Sum(19) res20 = fma52hi(res20, a[7], a[12]); // Sum(19) res20 = fma52lo(res20, a[8], a[12]); // Sum(20) res21 = fma52hi(res21, a[8], a[12]); // Sum(20) res21 = fma52lo(res21, a[9], a[12]); // Sum(21) res22 = fma52hi(res22, a[9], a[12]); // Sum(21) res22 = fma52lo(res22, a[10], a[12]); // Sum(22) res23 = fma52hi(res23, a[10], a[12]); // Sum(22) res23 = fma52lo(res23, a[11], a[12]); // Sum(23) res24 = fma52hi(res24, a[11], a[12]); // Sum(23) res13 = fma52lo(res13, a[0], a[13]); // Sum(13) res14 = fma52hi(res14, a[0], a[13]); // Sum(13) res14 = fma52lo(res14, a[1], a[13]); // Sum(14) res15 = fma52hi(res15, a[1], a[13]); // Sum(14) res15 = fma52lo(res15, a[2], a[13]); // Sum(15) res16 = fma52hi(res16, a[2], a[13]); // Sum(15) res16 = fma52lo(res16, a[3], a[13]); // Sum(16) res17 = fma52hi(res17, a[3], a[13]); // Sum(16) res17 = fma52lo(res17, a[4], a[13]); // Sum(17) res18 = fma52hi(res18, a[4], a[13]); // Sum(17) res18 = fma52lo(res18, a[5], a[13]); // Sum(18) res19 = fma52hi(res19, a[5], a[13]); // Sum(18) res19 = fma52lo(res19, a[6], a[13]); // Sum(19) res20 = fma52hi(res20, a[6], a[13]); // Sum(19) res20 = fma52lo(res20, a[7], a[13]); // Sum(20) res21 = fma52hi(res21, a[7], a[13]); // Sum(20) res21 = fma52lo(res21, a[8], a[13]); // Sum(21) res22 = fma52hi(res22, a[8], a[13]); // Sum(21) res22 = fma52lo(res22, a[9], a[13]); // Sum(22) res23 = fma52hi(res23, a[9], a[13]); // Sum(22) res23 = fma52lo(res23, a[10], a[13]); // Sum(23) res24 = fma52hi(res24, a[10], a[13]); // Sum(23) res14 = fma52lo(res14, a[0], a[14]); // Sum(14) res15 = fma52hi(res15, a[0], a[14]); // Sum(14) res15 = fma52lo(res15, a[1], a[14]); // Sum(15) res16 = fma52hi(res16, a[1], a[14]); // Sum(15) res16 = fma52lo(res16, a[2], a[14]); // Sum(16) res17 = fma52hi(res17, a[2], a[14]); // Sum(16) res17 = fma52lo(res17, a[3], a[14]); // Sum(17) res18 = fma52hi(res18, a[3], a[14]); // Sum(17) res18 = fma52lo(res18, a[4], a[14]); // Sum(18) res19 = fma52hi(res19, a[4], a[14]); // Sum(18) res19 = fma52lo(res19, a[5], a[14]); // Sum(19) res20 = fma52hi(res20, a[5], a[14]); // Sum(19) res20 = fma52lo(res20, a[6], a[14]); // Sum(20) res21 = fma52hi(res21, a[6], a[14]); // Sum(20) res21 = fma52lo(res21, a[7], a[14]); // Sum(21) res22 = fma52hi(res22, a[7], a[14]); // Sum(21) res22 = fma52lo(res22, a[8], a[14]); // Sum(22) res23 = fma52hi(res23, a[8], a[14]); // Sum(22) res23 = fma52lo(res23, a[9], a[14]); // Sum(23) res24 = fma52hi(res24, a[9], a[14]); // Sum(23) res15 = fma52lo(res15, a[0], a[15]); // Sum(15) res16 = fma52hi(res16, a[0], a[15]); // Sum(15) res16 = fma52lo(res16, a[1], a[15]); // Sum(16) res17 = fma52hi(res17, a[1], a[15]); // Sum(16) res17 = fma52lo(res17, a[2], a[15]); // Sum(17) res18 = fma52hi(res18, a[2], a[15]); // Sum(17) res18 = fma52lo(res18, a[3], a[15]); // Sum(18) res19 = fma52hi(res19, a[3], a[15]); // Sum(18) res19 = fma52lo(res19, a[4], a[15]); // Sum(19) res20 = fma52hi(res20, a[4], a[15]); // Sum(19) res20 = fma52lo(res20, a[5], a[15]); // Sum(20) res21 = fma52hi(res21, a[5], a[15]); // Sum(20) res21 = fma52lo(res21, a[6], a[15]); // Sum(21) res22 = fma52hi(res22, a[6], a[15]); // Sum(21) res22 = fma52lo(res22, a[7], a[15]); // Sum(22) res23 = fma52hi(res23, a[7], a[15]); // Sum(22) res23 = fma52lo(res23, a[8], a[15]); // Sum(23) res24 = fma52hi(res24, a[8], a[15]); // Sum(23) res16 = fma52lo(res16, a[0], a[16]); // Sum(16) res17 = fma52hi(res17, a[0], a[16]); // Sum(16) res17 = fma52lo(res17, a[1], a[16]); // Sum(17) res18 = fma52hi(res18, a[1], a[16]); // Sum(17) res18 = fma52lo(res18, a[2], a[16]); // Sum(18) res19 = fma52hi(res19, a[2], a[16]); // Sum(18) res19 = fma52lo(res19, a[3], a[16]); // Sum(19) res20 = fma52hi(res20, a[3], a[16]); // Sum(19) res20 = fma52lo(res20, a[4], a[16]); // Sum(20) res21 = fma52hi(res21, a[4], a[16]); // Sum(20) res21 = fma52lo(res21, a[5], a[16]); // Sum(21) res22 = fma52hi(res22, a[5], a[16]); // Sum(21) res22 = fma52lo(res22, a[6], a[16]); // Sum(22) res23 = fma52hi(res23, a[6], a[16]); // Sum(22) res23 = fma52lo(res23, a[7], a[16]); // Sum(23) res24 = fma52hi(res24, a[7], a[16]); // Sum(23) res17 = fma52lo(res17, a[0], a[17]); // Sum(17) res18 = fma52hi(res18, a[0], a[17]); // Sum(17) res18 = fma52lo(res18, a[1], a[17]); // Sum(18) res19 = fma52hi(res19, a[1], a[17]); // Sum(18) res19 = fma52lo(res19, a[2], a[17]); // Sum(19) res20 = fma52hi(res20, a[2], a[17]); // Sum(19) res20 = fma52lo(res20, a[3], a[17]); // Sum(20) res21 = fma52hi(res21, a[3], a[17]); // Sum(20) res21 = fma52lo(res21, a[4], a[17]); // Sum(21) res22 = fma52hi(res22, a[4], a[17]); // Sum(21) res22 = fma52lo(res22, a[5], a[17]); // Sum(22) res23 = fma52hi(res23, a[5], a[17]); // Sum(22) res23 = fma52lo(res23, a[6], a[17]); // Sum(23) res24 = fma52hi(res24, a[6], a[17]); // Sum(23) res18 = fma52lo(res18, a[0], a[18]); // Sum(18) res19 = fma52hi(res19, a[0], a[18]); // Sum(18) res19 = fma52lo(res19, a[1], a[18]); // Sum(19) res20 = fma52hi(res20, a[1], a[18]); // Sum(19) res20 = fma52lo(res20, a[2], a[18]); // Sum(20) res21 = fma52hi(res21, a[2], a[18]); // Sum(20) res21 = fma52lo(res21, a[3], a[18]); // Sum(21) res22 = fma52hi(res22, a[3], a[18]); // Sum(21) res22 = fma52lo(res22, a[4], a[18]); // Sum(22) res23 = fma52hi(res23, a[4], a[18]); // Sum(22) res23 = fma52lo(res23, a[5], a[18]); // Sum(23) res24 = fma52hi(res24, a[5], a[18]); // Sum(23) res19 = fma52lo(res19, a[0], a[19]); // Sum(19) res20 = fma52hi(res20, a[0], a[19]); // Sum(19) res20 = fma52lo(res20, a[1], a[19]); // Sum(20) res21 = fma52hi(res21, a[1], a[19]); // Sum(20) res21 = fma52lo(res21, a[2], a[19]); // Sum(21) res22 = fma52hi(res22, a[2], a[19]); // Sum(21) res22 = fma52lo(res22, a[3], a[19]); // Sum(22) res23 = fma52hi(res23, a[3], a[19]); // Sum(22) res23 = fma52lo(res23, a[4], a[19]); // Sum(23) res24 = fma52hi(res24, a[4], a[19]); // Sum(23) res12 = add64(res12, res12); // Double(12) res13 = add64(res13, res13); // Double(13) res14 = add64(res14, res14); // Double(14) res15 = add64(res15, res15); // Double(15) res16 = add64(res16, res16); // Double(16) res17 = add64(res17, res17); // Double(17) res18 = add64(res18, res18); // Double(18) res19 = add64(res19, res19); // Double(19) res20 = add64(res20, res20); // Double(20) res21 = add64(res21, res21); // Double(21) res22 = add64(res22, res22); // Double(22) res23 = add64(res23, res23); // Double(23) res12 = fma52lo(res12, a[6], a[6]); // Add sqr(12) res13 = fma52hi(res13, a[6], a[6]); // Add sqr(12) res14 = fma52lo(res14, a[7], a[7]); // Add sqr(14) res15 = fma52hi(res15, a[7], a[7]); // Add sqr(14) res16 = fma52lo(res16, a[8], a[8]); // Add sqr(16) res17 = fma52hi(res17, a[8], a[8]); // Add sqr(16) res18 = fma52lo(res18, a[9], a[9]); // Add sqr(18) res19 = fma52hi(res19, a[9], a[9]); // Add sqr(18) res20 = fma52lo(res20, a[10], a[10]); // Add sqr(20) res21 = fma52hi(res21, a[10], a[10]); // Add sqr(20) res22 = fma52lo(res22, a[11], a[11]); // Add sqr(22) res23 = fma52hi(res23, a[11], a[11]); // Add sqr(22) res24 = fma52lo(res24, a[11], a[13]); // Sum(24) res25 = fma52hi(res25, a[11], a[13]); // Sum(24) res25 = fma52lo(res25, a[12], a[13]); // Sum(25) res26 = fma52hi(res26, a[12], a[13]); // Sum(25) res24 = fma52lo(res24, a[10], a[14]); // Sum(24) res25 = fma52hi(res25, a[10], a[14]); // Sum(24) res25 = fma52lo(res25, a[11], a[14]); // Sum(25) res26 = fma52hi(res26, a[11], a[14]); // Sum(25) res26 = fma52lo(res26, a[12], a[14]); // Sum(26) res27 = fma52hi(res27, a[12], a[14]); // Sum(26) res27 = fma52lo(res27, a[13], a[14]); // Sum(27) res28 = fma52hi(res28, a[13], a[14]); // Sum(27) res24 = fma52lo(res24, a[9], a[15]); // Sum(24) res25 = fma52hi(res25, a[9], a[15]); // Sum(24) res25 = fma52lo(res25, a[10], a[15]); // Sum(25) res26 = fma52hi(res26, a[10], a[15]); // Sum(25) res26 = fma52lo(res26, a[11], a[15]); // Sum(26) res27 = fma52hi(res27, a[11], a[15]); // Sum(26) res27 = fma52lo(res27, a[12], a[15]); // Sum(27) res28 = fma52hi(res28, a[12], a[15]); // Sum(27) res28 = fma52lo(res28, a[13], a[15]); // Sum(28) res29 = fma52hi(res29, a[13], a[15]); // Sum(28) res29 = fma52lo(res29, a[14], a[15]); // Sum(29) res30 = fma52hi(res30, a[14], a[15]); // Sum(29) res24 = fma52lo(res24, a[8], a[16]); // Sum(24) res25 = fma52hi(res25, a[8], a[16]); // Sum(24) res25 = fma52lo(res25, a[9], a[16]); // Sum(25) res26 = fma52hi(res26, a[9], a[16]); // Sum(25) res26 = fma52lo(res26, a[10], a[16]); // Sum(26) res27 = fma52hi(res27, a[10], a[16]); // Sum(26) res27 = fma52lo(res27, a[11], a[16]); // Sum(27) res28 = fma52hi(res28, a[11], a[16]); // Sum(27) res28 = fma52lo(res28, a[12], a[16]); // Sum(28) res29 = fma52hi(res29, a[12], a[16]); // Sum(28) res29 = fma52lo(res29, a[13], a[16]); // Sum(29) res30 = fma52hi(res30, a[13], a[16]); // Sum(29) res30 = fma52lo(res30, a[14], a[16]); // Sum(30) res31 = fma52hi(res31, a[14], a[16]); // Sum(30) res31 = fma52lo(res31, a[15], a[16]); // Sum(31) res32 = fma52hi(res32, a[15], a[16]); // Sum(31) res24 = fma52lo(res24, a[7], a[17]); // Sum(24) res25 = fma52hi(res25, a[7], a[17]); // Sum(24) res25 = fma52lo(res25, a[8], a[17]); // Sum(25) res26 = fma52hi(res26, a[8], a[17]); // Sum(25) res26 = fma52lo(res26, a[9], a[17]); // Sum(26) res27 = fma52hi(res27, a[9], a[17]); // Sum(26) res27 = fma52lo(res27, a[10], a[17]); // Sum(27) res28 = fma52hi(res28, a[10], a[17]); // Sum(27) res28 = fma52lo(res28, a[11], a[17]); // Sum(28) res29 = fma52hi(res29, a[11], a[17]); // Sum(28) res29 = fma52lo(res29, a[12], a[17]); // Sum(29) res30 = fma52hi(res30, a[12], a[17]); // Sum(29) res30 = fma52lo(res30, a[13], a[17]); // Sum(30) res31 = fma52hi(res31, a[13], a[17]); // Sum(30) res31 = fma52lo(res31, a[14], a[17]); // Sum(31) res32 = fma52hi(res32, a[14], a[17]); // Sum(31) res32 = fma52lo(res32, a[15], a[17]); // Sum(32) res33 = fma52hi(res33, a[15], a[17]); // Sum(32) res33 = fma52lo(res33, a[16], a[17]); // Sum(33) res34 = fma52hi(res34, a[16], a[17]); // Sum(33) res24 = fma52lo(res24, a[6], a[18]); // Sum(24) res25 = fma52hi(res25, a[6], a[18]); // Sum(24) res25 = fma52lo(res25, a[7], a[18]); // Sum(25) res26 = fma52hi(res26, a[7], a[18]); // Sum(25) res26 = fma52lo(res26, a[8], a[18]); // Sum(26) res27 = fma52hi(res27, a[8], a[18]); // Sum(26) res27 = fma52lo(res27, a[9], a[18]); // Sum(27) res28 = fma52hi(res28, a[9], a[18]); // Sum(27) res28 = fma52lo(res28, a[10], a[18]); // Sum(28) res29 = fma52hi(res29, a[10], a[18]); // Sum(28) res29 = fma52lo(res29, a[11], a[18]); // Sum(29) res30 = fma52hi(res30, a[11], a[18]); // Sum(29) res30 = fma52lo(res30, a[12], a[18]); // Sum(30) res31 = fma52hi(res31, a[12], a[18]); // Sum(30) res31 = fma52lo(res31, a[13], a[18]); // Sum(31) res32 = fma52hi(res32, a[13], a[18]); // Sum(31) res32 = fma52lo(res32, a[14], a[18]); // Sum(32) res33 = fma52hi(res33, a[14], a[18]); // Sum(32) res33 = fma52lo(res33, a[15], a[18]); // Sum(33) res34 = fma52hi(res34, a[15], a[18]); // Sum(33) res34 = fma52lo(res34, a[16], a[18]); // Sum(34) res35 = fma52hi(res35, a[16], a[18]); // Sum(34) res35 = fma52lo(res35, a[17], a[18]); // Sum(35) res36 = fma52hi(res36, a[17], a[18]); // Sum(35) res24 = fma52lo(res24, a[5], a[19]); // Sum(24) res25 = fma52hi(res25, a[5], a[19]); // Sum(24) res25 = fma52lo(res25, a[6], a[19]); // Sum(25) res26 = fma52hi(res26, a[6], a[19]); // Sum(25) res26 = fma52lo(res26, a[7], a[19]); // Sum(26) res27 = fma52hi(res27, a[7], a[19]); // Sum(26) res27 = fma52lo(res27, a[8], a[19]); // Sum(27) res28 = fma52hi(res28, a[8], a[19]); // Sum(27) res28 = fma52lo(res28, a[9], a[19]); // Sum(28) res29 = fma52hi(res29, a[9], a[19]); // Sum(28) res29 = fma52lo(res29, a[10], a[19]); // Sum(29) res30 = fma52hi(res30, a[10], a[19]); // Sum(29) res30 = fma52lo(res30, a[11], a[19]); // Sum(30) res31 = fma52hi(res31, a[11], a[19]); // Sum(30) res31 = fma52lo(res31, a[12], a[19]); // Sum(31) res32 = fma52hi(res32, a[12], a[19]); // Sum(31) res32 = fma52lo(res32, a[13], a[19]); // Sum(32) res33 = fma52hi(res33, a[13], a[19]); // Sum(32) res33 = fma52lo(res33, a[14], a[19]); // Sum(33) res34 = fma52hi(res34, a[14], a[19]); // Sum(33) res34 = fma52lo(res34, a[15], a[19]); // Sum(34) res35 = fma52hi(res35, a[15], a[19]); // Sum(34) res35 = fma52lo(res35, a[16], a[19]); // Sum(35) res36 = fma52hi(res36, a[16], a[19]); // Sum(35) res24 = add64(res24, res24); // Double(24) res25 = add64(res25, res25); // Double(25) res26 = add64(res26, res26); // Double(26) res27 = add64(res27, res27); // Double(27) res28 = add64(res28, res28); // Double(28) res29 = add64(res29, res29); // Double(29) res30 = add64(res30, res30); // Double(30) res31 = add64(res31, res31); // Double(31) res32 = add64(res32, res32); // Double(32) res33 = add64(res33, res33); // Double(33) res34 = add64(res34, res34); // Double(34) res35 = add64(res35, res35); // Double(35) res24 = fma52lo(res24, a[12], a[12]); // Add sqr(24) res25 = fma52hi(res25, a[12], a[12]); // Add sqr(24) res26 = fma52lo(res26, a[13], a[13]); // Add sqr(26) res27 = fma52hi(res27, a[13], a[13]); // Add sqr(26) res28 = fma52lo(res28, a[14], a[14]); // Add sqr(28) res29 = fma52hi(res29, a[14], a[14]); // Add sqr(28) res30 = fma52lo(res30, a[15], a[15]); // Add sqr(30) res31 = fma52hi(res31, a[15], a[15]); // Add sqr(30) res32 = fma52lo(res32, a[16], a[16]); // Add sqr(32) res33 = fma52hi(res33, a[16], a[16]); // Add sqr(32) res34 = fma52lo(res34, a[17], a[17]); // Add sqr(34) res35 = fma52hi(res35, a[17], a[17]); // Add sqr(34) res36 = fma52lo(res36, a[17], a[19]); // Sum(36) res37 = fma52hi(res37, a[17], a[19]); // Sum(36) res37 = fma52lo(res37, a[18], a[19]); // Sum(37) res38 = fma52hi(res38, a[18], a[19]); // Sum(37) res36 = add64(res36, res36); // Double(36) res37 = add64(res37, res37); // Double(37) res38 = add64(res38, res38); // Double(38) res36 = fma52lo(res36, a[18], a[18]); // Add sqr(36) res37 = fma52hi(res37, a[18], a[18]); // Add sqr(36) res38 = fma52lo(res38, a[19], a[19]); // Add sqr(38) res39 = fma52hi(res39, a[19], a[19]); // Add sqr(38) // Generate u_i U64 u0 = mul52lo(res0, k); ASM("jmp l0\nl0:\n"); // Create u0 fma52lo_mem(res0, res0, u0, m, SIMD_BYTES * 0); fma52hi_mem(res1, res1, u0, m, SIMD_BYTES * 0); res1 = fma52lo(res1, u0, m[1]); res2 = fma52hi(res2, u0, m[1]); res1 = add64(res1, srli64(res0, DIGIT_SIZE)); U64 u1 = mul52lo(res1, k); fma52lo_mem(res2, res2, u0, m, SIMD_BYTES * 2); fma52hi_mem(res3, res3, u0, m, SIMD_BYTES * 2); res3 = fma52lo(res3, u0, m[3]); res4 = fma52hi(res4, u0, m[3]); fma52lo_mem(res4, res4, u0, m, SIMD_BYTES * 4); fma52hi_mem(res5, res5, u0, m, SIMD_BYTES * 4); res5 = fma52lo(res5, u0, m[5]); res6 = fma52hi(res6, u0, m[5]); fma52lo_mem(res6, res6, u0, m, SIMD_BYTES * 6); fma52hi_mem(res7, res7, u0, m, SIMD_BYTES * 6); res7 = fma52lo(res7, u0, m[7]); res8 = fma52hi(res8, u0, m[7]); fma52lo_mem(res8, res8, u0, m, SIMD_BYTES * 8); fma52hi_mem(res9, res9, u0, m, SIMD_BYTES * 8); res9 = fma52lo(res9, u0, m[9]); res10 = fma52hi(res10, u0, m[9]); fma52lo_mem(res10, res10, u0, m, SIMD_BYTES * 10); fma52hi_mem(res11, res11, u0, m, SIMD_BYTES * 10); res11 = fma52lo(res11, u0, m[11]); res12 = fma52hi(res12, u0, m[11]); fma52lo_mem(res12, res12, u0, m, SIMD_BYTES * 12); fma52hi_mem(res13, res13, u0, m, SIMD_BYTES * 12); res13 = fma52lo(res13, u0, m[13]); res14 = fma52hi(res14, u0, m[13]); fma52lo_mem(res14, res14, u0, m, SIMD_BYTES * 14); fma52hi_mem(res15, res15, u0, m, SIMD_BYTES * 14); res15 = fma52lo(res15, u0, m[15]); res16 = fma52hi(res16, u0, m[15]); fma52lo_mem(res16, res16, u0, m, SIMD_BYTES * 16); fma52hi_mem(res17, res17, u0, m, SIMD_BYTES * 16); res17 = fma52lo(res17, u0, m[17]); res18 = fma52hi(res18, u0, m[17]); fma52lo_mem(res18, res18, u0, m, SIMD_BYTES * 18); fma52hi_mem(res19, res19, u0, m, SIMD_BYTES * 18); res19 = fma52lo(res19, u0, m[19]); res20 = fma52hi(res20, u0, m[19]); // Create u1 fma52lo_mem(res1, res1, u1, m, SIMD_BYTES * 0); fma52hi_mem(res2, res2, u1, m, SIMD_BYTES * 0); res2 = fma52lo(res2, u1, m[1]); res3 = fma52hi(res3, u1, m[1]); res2 = add64(res2, srli64(res1, DIGIT_SIZE)); U64 u2 = mul52lo(res2, k); fma52lo_mem(res3, res3, u1, m, SIMD_BYTES * 2); fma52hi_mem(res4, res4, u1, m, SIMD_BYTES * 2); res4 = fma52lo(res4, u1, m[3]); res5 = fma52hi(res5, u1, m[3]); fma52lo_mem(res5, res5, u1, m, SIMD_BYTES * 4); fma52hi_mem(res6, res6, u1, m, SIMD_BYTES * 4); res6 = fma52lo(res6, u1, m[5]); res7 = fma52hi(res7, u1, m[5]); fma52lo_mem(res7, res7, u1, m, SIMD_BYTES * 6); fma52hi_mem(res8, res8, u1, m, SIMD_BYTES * 6); res8 = fma52lo(res8, u1, m[7]); res9 = fma52hi(res9, u1, m[7]); fma52lo_mem(res9, res9, u1, m, SIMD_BYTES * 8); fma52hi_mem(res10, res10, u1, m, SIMD_BYTES * 8); res10 = fma52lo(res10, u1, m[9]); res11 = fma52hi(res11, u1, m[9]); fma52lo_mem(res11, res11, u1, m, SIMD_BYTES * 10); fma52hi_mem(res12, res12, u1, m, SIMD_BYTES * 10); res12 = fma52lo(res12, u1, m[11]); res13 = fma52hi(res13, u1, m[11]); fma52lo_mem(res13, res13, u1, m, SIMD_BYTES * 12); fma52hi_mem(res14, res14, u1, m, SIMD_BYTES * 12); res14 = fma52lo(res14, u1, m[13]); res15 = fma52hi(res15, u1, m[13]); fma52lo_mem(res15, res15, u1, m, SIMD_BYTES * 14); fma52hi_mem(res16, res16, u1, m, SIMD_BYTES * 14); res16 = fma52lo(res16, u1, m[15]); res17 = fma52hi(res17, u1, m[15]); fma52lo_mem(res17, res17, u1, m, SIMD_BYTES * 16); fma52hi_mem(res18, res18, u1, m, SIMD_BYTES * 16); res18 = fma52lo(res18, u1, m[17]); res19 = fma52hi(res19, u1, m[17]); fma52lo_mem(res19, res19, u1, m, SIMD_BYTES * 18); fma52hi_mem(res20, res20, u1, m, SIMD_BYTES * 18); res20 = fma52lo(res20, u1, m[19]); res21 = fma52hi(res21, u1, m[19]); ASM("jmp l2\nl2:\n"); // Create u2 fma52lo_mem(res2, res2, u2, m, SIMD_BYTES * 0); fma52hi_mem(res3, res3, u2, m, SIMD_BYTES * 0); res3 = fma52lo(res3, u2, m[1]); res4 = fma52hi(res4, u2, m[1]); res3 = add64(res3, srli64(res2, DIGIT_SIZE)); U64 u3 = mul52lo(res3, k); fma52lo_mem(res4, res4, u2, m, SIMD_BYTES * 2); fma52hi_mem(res5, res5, u2, m, SIMD_BYTES * 2); res5 = fma52lo(res5, u2, m[3]); res6 = fma52hi(res6, u2, m[3]); fma52lo_mem(res6, res6, u2, m, SIMD_BYTES * 4); fma52hi_mem(res7, res7, u2, m, SIMD_BYTES * 4); res7 = fma52lo(res7, u2, m[5]); res8 = fma52hi(res8, u2, m[5]); fma52lo_mem(res8, res8, u2, m, SIMD_BYTES * 6); fma52hi_mem(res9, res9, u2, m, SIMD_BYTES * 6); res9 = fma52lo(res9, u2, m[7]); res10 = fma52hi(res10, u2, m[7]); fma52lo_mem(res10, res10, u2, m, SIMD_BYTES * 8); fma52hi_mem(res11, res11, u2, m, SIMD_BYTES * 8); res11 = fma52lo(res11, u2, m[9]); res12 = fma52hi(res12, u2, m[9]); fma52lo_mem(res12, res12, u2, m, SIMD_BYTES * 10); fma52hi_mem(res13, res13, u2, m, SIMD_BYTES * 10); res13 = fma52lo(res13, u2, m[11]); res14 = fma52hi(res14, u2, m[11]); fma52lo_mem(res14, res14, u2, m, SIMD_BYTES * 12); fma52hi_mem(res15, res15, u2, m, SIMD_BYTES * 12); res15 = fma52lo(res15, u2, m[13]); res16 = fma52hi(res16, u2, m[13]); fma52lo_mem(res16, res16, u2, m, SIMD_BYTES * 14); fma52hi_mem(res17, res17, u2, m, SIMD_BYTES * 14); res17 = fma52lo(res17, u2, m[15]); res18 = fma52hi(res18, u2, m[15]); fma52lo_mem(res18, res18, u2, m, SIMD_BYTES * 16); fma52hi_mem(res19, res19, u2, m, SIMD_BYTES * 16); res19 = fma52lo(res19, u2, m[17]); res20 = fma52hi(res20, u2, m[17]); fma52lo_mem(res20, res20, u2, m, SIMD_BYTES * 18); fma52hi_mem(res21, res21, u2, m, SIMD_BYTES * 18); res21 = fma52lo(res21, u2, m[19]); res22 = fma52hi(res22, u2, m[19]); // Create u3 fma52lo_mem(res3, res3, u3, m, SIMD_BYTES * 0); fma52hi_mem(res4, res4, u3, m, SIMD_BYTES * 0); res4 = fma52lo(res4, u3, m[1]); res5 = fma52hi(res5, u3, m[1]); res4 = add64(res4, srli64(res3, DIGIT_SIZE)); U64 u4 = mul52lo(res4, k); fma52lo_mem(res5, res5, u3, m, SIMD_BYTES * 2); fma52hi_mem(res6, res6, u3, m, SIMD_BYTES * 2); res6 = fma52lo(res6, u3, m[3]); res7 = fma52hi(res7, u3, m[3]); fma52lo_mem(res7, res7, u3, m, SIMD_BYTES * 4); fma52hi_mem(res8, res8, u3, m, SIMD_BYTES * 4); res8 = fma52lo(res8, u3, m[5]); res9 = fma52hi(res9, u3, m[5]); fma52lo_mem(res9, res9, u3, m, SIMD_BYTES * 6); fma52hi_mem(res10, res10, u3, m, SIMD_BYTES * 6); res10 = fma52lo(res10, u3, m[7]); res11 = fma52hi(res11, u3, m[7]); fma52lo_mem(res11, res11, u3, m, SIMD_BYTES * 8); fma52hi_mem(res12, res12, u3, m, SIMD_BYTES * 8); res12 = fma52lo(res12, u3, m[9]); res13 = fma52hi(res13, u3, m[9]); fma52lo_mem(res13, res13, u3, m, SIMD_BYTES * 10); fma52hi_mem(res14, res14, u3, m, SIMD_BYTES * 10); res14 = fma52lo(res14, u3, m[11]); res15 = fma52hi(res15, u3, m[11]); fma52lo_mem(res15, res15, u3, m, SIMD_BYTES * 12); fma52hi_mem(res16, res16, u3, m, SIMD_BYTES * 12); res16 = fma52lo(res16, u3, m[13]); res17 = fma52hi(res17, u3, m[13]); fma52lo_mem(res17, res17, u3, m, SIMD_BYTES * 14); fma52hi_mem(res18, res18, u3, m, SIMD_BYTES * 14); res18 = fma52lo(res18, u3, m[15]); res19 = fma52hi(res19, u3, m[15]); fma52lo_mem(res19, res19, u3, m, SIMD_BYTES * 16); fma52hi_mem(res20, res20, u3, m, SIMD_BYTES * 16); res20 = fma52lo(res20, u3, m[17]); res21 = fma52hi(res21, u3, m[17]); fma52lo_mem(res21, res21, u3, m, SIMD_BYTES * 18); fma52hi_mem(res22, res22, u3, m, SIMD_BYTES * 18); res22 = fma52lo(res22, u3, m[19]); res23 = fma52hi(res23, u3, m[19]); ASM("jmp l4\nl4:\n"); // Create u4 fma52lo_mem(res4, res4, u4, m, SIMD_BYTES * 0); fma52hi_mem(res5, res5, u4, m, SIMD_BYTES * 0); res5 = fma52lo(res5, u4, m[1]); res6 = fma52hi(res6, u4, m[1]); res5 = add64(res5, srli64(res4, DIGIT_SIZE)); U64 u5 = mul52lo(res5, k); fma52lo_mem(res6, res6, u4, m, SIMD_BYTES * 2); fma52hi_mem(res7, res7, u4, m, SIMD_BYTES * 2); res7 = fma52lo(res7, u4, m[3]); res8 = fma52hi(res8, u4, m[3]); fma52lo_mem(res8, res8, u4, m, SIMD_BYTES * 4); fma52hi_mem(res9, res9, u4, m, SIMD_BYTES * 4); res9 = fma52lo(res9, u4, m[5]); res10 = fma52hi(res10, u4, m[5]); fma52lo_mem(res10, res10, u4, m, SIMD_BYTES * 6); fma52hi_mem(res11, res11, u4, m, SIMD_BYTES * 6); res11 = fma52lo(res11, u4, m[7]); res12 = fma52hi(res12, u4, m[7]); fma52lo_mem(res12, res12, u4, m, SIMD_BYTES * 8); fma52hi_mem(res13, res13, u4, m, SIMD_BYTES * 8); res13 = fma52lo(res13, u4, m[9]); res14 = fma52hi(res14, u4, m[9]); fma52lo_mem(res14, res14, u4, m, SIMD_BYTES * 10); fma52hi_mem(res15, res15, u4, m, SIMD_BYTES * 10); res15 = fma52lo(res15, u4, m[11]); res16 = fma52hi(res16, u4, m[11]); fma52lo_mem(res16, res16, u4, m, SIMD_BYTES * 12); fma52hi_mem(res17, res17, u4, m, SIMD_BYTES * 12); res17 = fma52lo(res17, u4, m[13]); res18 = fma52hi(res18, u4, m[13]); fma52lo_mem(res18, res18, u4, m, SIMD_BYTES * 14); fma52hi_mem(res19, res19, u4, m, SIMD_BYTES * 14); res19 = fma52lo(res19, u4, m[15]); res20 = fma52hi(res20, u4, m[15]); fma52lo_mem(res20, res20, u4, m, SIMD_BYTES * 16); fma52hi_mem(res21, res21, u4, m, SIMD_BYTES * 16); res21 = fma52lo(res21, u4, m[17]); res22 = fma52hi(res22, u4, m[17]); fma52lo_mem(res22, res22, u4, m, SIMD_BYTES * 18); fma52hi_mem(res23, res23, u4, m, SIMD_BYTES * 18); res23 = fma52lo(res23, u4, m[19]); res24 = fma52hi(res24, u4, m[19]); // Create u5 fma52lo_mem(res5, res5, u5, m, SIMD_BYTES * 0); fma52hi_mem(res6, res6, u5, m, SIMD_BYTES * 0); res6 = fma52lo(res6, u5, m[1]); res7 = fma52hi(res7, u5, m[1]); res6 = add64(res6, srli64(res5, DIGIT_SIZE)); U64 u6 = mul52lo(res6, k); fma52lo_mem(res7, res7, u5, m, SIMD_BYTES * 2); fma52hi_mem(res8, res8, u5, m, SIMD_BYTES * 2); res8 = fma52lo(res8, u5, m[3]); res9 = fma52hi(res9, u5, m[3]); fma52lo_mem(res9, res9, u5, m, SIMD_BYTES * 4); fma52hi_mem(res10, res10, u5, m, SIMD_BYTES * 4); res10 = fma52lo(res10, u5, m[5]); res11 = fma52hi(res11, u5, m[5]); fma52lo_mem(res11, res11, u5, m, SIMD_BYTES * 6); fma52hi_mem(res12, res12, u5, m, SIMD_BYTES * 6); res12 = fma52lo(res12, u5, m[7]); res13 = fma52hi(res13, u5, m[7]); fma52lo_mem(res13, res13, u5, m, SIMD_BYTES * 8); fma52hi_mem(res14, res14, u5, m, SIMD_BYTES * 8); res14 = fma52lo(res14, u5, m[9]); res15 = fma52hi(res15, u5, m[9]); fma52lo_mem(res15, res15, u5, m, SIMD_BYTES * 10); fma52hi_mem(res16, res16, u5, m, SIMD_BYTES * 10); res16 = fma52lo(res16, u5, m[11]); res17 = fma52hi(res17, u5, m[11]); fma52lo_mem(res17, res17, u5, m, SIMD_BYTES * 12); fma52hi_mem(res18, res18, u5, m, SIMD_BYTES * 12); res18 = fma52lo(res18, u5, m[13]); res19 = fma52hi(res19, u5, m[13]); fma52lo_mem(res19, res19, u5, m, SIMD_BYTES * 14); fma52hi_mem(res20, res20, u5, m, SIMD_BYTES * 14); res20 = fma52lo(res20, u5, m[15]); res21 = fma52hi(res21, u5, m[15]); fma52lo_mem(res21, res21, u5, m, SIMD_BYTES * 16); fma52hi_mem(res22, res22, u5, m, SIMD_BYTES * 16); res22 = fma52lo(res22, u5, m[17]); res23 = fma52hi(res23, u5, m[17]); fma52lo_mem(res23, res23, u5, m, SIMD_BYTES * 18); fma52hi_mem(res24, res24, u5, m, SIMD_BYTES * 18); res24 = fma52lo(res24, u5, m[19]); res25 = fma52hi(res25, u5, m[19]); ASM("jmp l6\nl6:\n"); // Create u6 fma52lo_mem(res6, res6, u6, m, SIMD_BYTES * 0); fma52hi_mem(res7, res7, u6, m, SIMD_BYTES * 0); res7 = fma52lo(res7, u6, m[1]); res8 = fma52hi(res8, u6, m[1]); res7 = add64(res7, srli64(res6, DIGIT_SIZE)); U64 u7 = mul52lo(res7, k); fma52lo_mem(res8, res8, u6, m, SIMD_BYTES * 2); fma52hi_mem(res9, res9, u6, m, SIMD_BYTES * 2); res9 = fma52lo(res9, u6, m[3]); res10 = fma52hi(res10, u6, m[3]); fma52lo_mem(res10, res10, u6, m, SIMD_BYTES * 4); fma52hi_mem(res11, res11, u6, m, SIMD_BYTES * 4); res11 = fma52lo(res11, u6, m[5]); res12 = fma52hi(res12, u6, m[5]); fma52lo_mem(res12, res12, u6, m, SIMD_BYTES * 6); fma52hi_mem(res13, res13, u6, m, SIMD_BYTES * 6); res13 = fma52lo(res13, u6, m[7]); res14 = fma52hi(res14, u6, m[7]); fma52lo_mem(res14, res14, u6, m, SIMD_BYTES * 8); fma52hi_mem(res15, res15, u6, m, SIMD_BYTES * 8); res15 = fma52lo(res15, u6, m[9]); res16 = fma52hi(res16, u6, m[9]); fma52lo_mem(res16, res16, u6, m, SIMD_BYTES * 10); fma52hi_mem(res17, res17, u6, m, SIMD_BYTES * 10); res17 = fma52lo(res17, u6, m[11]); res18 = fma52hi(res18, u6, m[11]); fma52lo_mem(res18, res18, u6, m, SIMD_BYTES * 12); fma52hi_mem(res19, res19, u6, m, SIMD_BYTES * 12); res19 = fma52lo(res19, u6, m[13]); res20 = fma52hi(res20, u6, m[13]); fma52lo_mem(res20, res20, u6, m, SIMD_BYTES * 14); fma52hi_mem(res21, res21, u6, m, SIMD_BYTES * 14); res21 = fma52lo(res21, u6, m[15]); res22 = fma52hi(res22, u6, m[15]); fma52lo_mem(res22, res22, u6, m, SIMD_BYTES * 16); fma52hi_mem(res23, res23, u6, m, SIMD_BYTES * 16); res23 = fma52lo(res23, u6, m[17]); res24 = fma52hi(res24, u6, m[17]); fma52lo_mem(res24, res24, u6, m, SIMD_BYTES * 18); fma52hi_mem(res25, res25, u6, m, SIMD_BYTES * 18); res25 = fma52lo(res25, u6, m[19]); res26 = fma52hi(res26, u6, m[19]); // Create u7 fma52lo_mem(res7, res7, u7, m, SIMD_BYTES * 0); fma52hi_mem(res8, res8, u7, m, SIMD_BYTES * 0); res8 = fma52lo(res8, u7, m[1]); res9 = fma52hi(res9, u7, m[1]); res8 = add64(res8, srli64(res7, DIGIT_SIZE)); U64 u8 = mul52lo(res8, k); fma52lo_mem(res9, res9, u7, m, SIMD_BYTES * 2); fma52hi_mem(res10, res10, u7, m, SIMD_BYTES * 2); res10 = fma52lo(res10, u7, m[3]); res11 = fma52hi(res11, u7, m[3]); fma52lo_mem(res11, res11, u7, m, SIMD_BYTES * 4); fma52hi_mem(res12, res12, u7, m, SIMD_BYTES * 4); res12 = fma52lo(res12, u7, m[5]); res13 = fma52hi(res13, u7, m[5]); fma52lo_mem(res13, res13, u7, m, SIMD_BYTES * 6); fma52hi_mem(res14, res14, u7, m, SIMD_BYTES * 6); res14 = fma52lo(res14, u7, m[7]); res15 = fma52hi(res15, u7, m[7]); fma52lo_mem(res15, res15, u7, m, SIMD_BYTES * 8); fma52hi_mem(res16, res16, u7, m, SIMD_BYTES * 8); res16 = fma52lo(res16, u7, m[9]); res17 = fma52hi(res17, u7, m[9]); fma52lo_mem(res17, res17, u7, m, SIMD_BYTES * 10); fma52hi_mem(res18, res18, u7, m, SIMD_BYTES * 10); res18 = fma52lo(res18, u7, m[11]); res19 = fma52hi(res19, u7, m[11]); fma52lo_mem(res19, res19, u7, m, SIMD_BYTES * 12); fma52hi_mem(res20, res20, u7, m, SIMD_BYTES * 12); res20 = fma52lo(res20, u7, m[13]); res21 = fma52hi(res21, u7, m[13]); fma52lo_mem(res21, res21, u7, m, SIMD_BYTES * 14); fma52hi_mem(res22, res22, u7, m, SIMD_BYTES * 14); res22 = fma52lo(res22, u7, m[15]); res23 = fma52hi(res23, u7, m[15]); fma52lo_mem(res23, res23, u7, m, SIMD_BYTES * 16); fma52hi_mem(res24, res24, u7, m, SIMD_BYTES * 16); res24 = fma52lo(res24, u7, m[17]); res25 = fma52hi(res25, u7, m[17]); fma52lo_mem(res25, res25, u7, m, SIMD_BYTES * 18); fma52hi_mem(res26, res26, u7, m, SIMD_BYTES * 18); res26 = fma52lo(res26, u7, m[19]); res27 = fma52hi(res27, u7, m[19]); ASM("jmp l8\nl8:\n"); // Create u8 fma52lo_mem(res8, res8, u8, m, SIMD_BYTES * 0); fma52hi_mem(res9, res9, u8, m, SIMD_BYTES * 0); res9 = fma52lo(res9, u8, m[1]); res10 = fma52hi(res10, u8, m[1]); res9 = add64(res9, srli64(res8, DIGIT_SIZE)); U64 u9 = mul52lo(res9, k); fma52lo_mem(res10, res10, u8, m, SIMD_BYTES * 2); fma52hi_mem(res11, res11, u8, m, SIMD_BYTES * 2); res11 = fma52lo(res11, u8, m[3]); res12 = fma52hi(res12, u8, m[3]); fma52lo_mem(res12, res12, u8, m, SIMD_BYTES * 4); fma52hi_mem(res13, res13, u8, m, SIMD_BYTES * 4); res13 = fma52lo(res13, u8, m[5]); res14 = fma52hi(res14, u8, m[5]); fma52lo_mem(res14, res14, u8, m, SIMD_BYTES * 6); fma52hi_mem(res15, res15, u8, m, SIMD_BYTES * 6); res15 = fma52lo(res15, u8, m[7]); res16 = fma52hi(res16, u8, m[7]); fma52lo_mem(res16, res16, u8, m, SIMD_BYTES * 8); fma52hi_mem(res17, res17, u8, m, SIMD_BYTES * 8); res17 = fma52lo(res17, u8, m[9]); res18 = fma52hi(res18, u8, m[9]); fma52lo_mem(res18, res18, u8, m, SIMD_BYTES * 10); fma52hi_mem(res19, res19, u8, m, SIMD_BYTES * 10); res19 = fma52lo(res19, u8, m[11]); res20 = fma52hi(res20, u8, m[11]); fma52lo_mem(res20, res20, u8, m, SIMD_BYTES * 12); fma52hi_mem(res21, res21, u8, m, SIMD_BYTES * 12); res21 = fma52lo(res21, u8, m[13]); res22 = fma52hi(res22, u8, m[13]); fma52lo_mem(res22, res22, u8, m, SIMD_BYTES * 14); fma52hi_mem(res23, res23, u8, m, SIMD_BYTES * 14); res23 = fma52lo(res23, u8, m[15]); res24 = fma52hi(res24, u8, m[15]); fma52lo_mem(res24, res24, u8, m, SIMD_BYTES * 16); fma52hi_mem(res25, res25, u8, m, SIMD_BYTES * 16); res25 = fma52lo(res25, u8, m[17]); res26 = fma52hi(res26, u8, m[17]); fma52lo_mem(res26, res26, u8, m, SIMD_BYTES * 18); fma52hi_mem(res27, res27, u8, m, SIMD_BYTES * 18); res27 = fma52lo(res27, u8, m[19]); res28 = fma52hi(res28, u8, m[19]); // Create u9 fma52lo_mem(res9, res9, u9, m, SIMD_BYTES * 0); fma52hi_mem(res10, res10, u9, m, SIMD_BYTES * 0); res10 = fma52lo(res10, u9, m[1]); res11 = fma52hi(res11, u9, m[1]); res10 = add64(res10, srli64(res9, DIGIT_SIZE)); U64 u10 = mul52lo(res10, k); fma52lo_mem(res11, res11, u9, m, SIMD_BYTES * 2); fma52hi_mem(res12, res12, u9, m, SIMD_BYTES * 2); res12 = fma52lo(res12, u9, m[3]); res13 = fma52hi(res13, u9, m[3]); fma52lo_mem(res13, res13, u9, m, SIMD_BYTES * 4); fma52hi_mem(res14, res14, u9, m, SIMD_BYTES * 4); res14 = fma52lo(res14, u9, m[5]); res15 = fma52hi(res15, u9, m[5]); fma52lo_mem(res15, res15, u9, m, SIMD_BYTES * 6); fma52hi_mem(res16, res16, u9, m, SIMD_BYTES * 6); res16 = fma52lo(res16, u9, m[7]); res17 = fma52hi(res17, u9, m[7]); fma52lo_mem(res17, res17, u9, m, SIMD_BYTES * 8); fma52hi_mem(res18, res18, u9, m, SIMD_BYTES * 8); res18 = fma52lo(res18, u9, m[9]); res19 = fma52hi(res19, u9, m[9]); fma52lo_mem(res19, res19, u9, m, SIMD_BYTES * 10); fma52hi_mem(res20, res20, u9, m, SIMD_BYTES * 10); res20 = fma52lo(res20, u9, m[11]); res21 = fma52hi(res21, u9, m[11]); fma52lo_mem(res21, res21, u9, m, SIMD_BYTES * 12); fma52hi_mem(res22, res22, u9, m, SIMD_BYTES * 12); res22 = fma52lo(res22, u9, m[13]); res23 = fma52hi(res23, u9, m[13]); fma52lo_mem(res23, res23, u9, m, SIMD_BYTES * 14); fma52hi_mem(res24, res24, u9, m, SIMD_BYTES * 14); res24 = fma52lo(res24, u9, m[15]); res25 = fma52hi(res25, u9, m[15]); fma52lo_mem(res25, res25, u9, m, SIMD_BYTES * 16); fma52hi_mem(res26, res26, u9, m, SIMD_BYTES * 16); res26 = fma52lo(res26, u9, m[17]); res27 = fma52hi(res27, u9, m[17]); fma52lo_mem(res27, res27, u9, m, SIMD_BYTES * 18); fma52hi_mem(res28, res28, u9, m, SIMD_BYTES * 18); res28 = fma52lo(res28, u9, m[19]); res29 = fma52hi(res29, u9, m[19]); ASM("jmp l10\nl10:\n"); // Create u10 fma52lo_mem(res10, res10, u10, m, SIMD_BYTES * 0); fma52hi_mem(res11, res11, u10, m, SIMD_BYTES * 0); res11 = fma52lo(res11, u10, m[1]); res12 = fma52hi(res12, u10, m[1]); res11 = add64(res11, srli64(res10, DIGIT_SIZE)); U64 u11 = mul52lo(res11, k); fma52lo_mem(res12, res12, u10, m, SIMD_BYTES * 2); fma52hi_mem(res13, res13, u10, m, SIMD_BYTES * 2); res13 = fma52lo(res13, u10, m[3]); res14 = fma52hi(res14, u10, m[3]); fma52lo_mem(res14, res14, u10, m, SIMD_BYTES * 4); fma52hi_mem(res15, res15, u10, m, SIMD_BYTES * 4); res15 = fma52lo(res15, u10, m[5]); res16 = fma52hi(res16, u10, m[5]); fma52lo_mem(res16, res16, u10, m, SIMD_BYTES * 6); fma52hi_mem(res17, res17, u10, m, SIMD_BYTES * 6); res17 = fma52lo(res17, u10, m[7]); res18 = fma52hi(res18, u10, m[7]); fma52lo_mem(res18, res18, u10, m, SIMD_BYTES * 8); fma52hi_mem(res19, res19, u10, m, SIMD_BYTES * 8); res19 = fma52lo(res19, u10, m[9]); res20 = fma52hi(res20, u10, m[9]); fma52lo_mem(res20, res20, u10, m, SIMD_BYTES * 10); fma52hi_mem(res21, res21, u10, m, SIMD_BYTES * 10); res21 = fma52lo(res21, u10, m[11]); res22 = fma52hi(res22, u10, m[11]); fma52lo_mem(res22, res22, u10, m, SIMD_BYTES * 12); fma52hi_mem(res23, res23, u10, m, SIMD_BYTES * 12); res23 = fma52lo(res23, u10, m[13]); res24 = fma52hi(res24, u10, m[13]); fma52lo_mem(res24, res24, u10, m, SIMD_BYTES * 14); fma52hi_mem(res25, res25, u10, m, SIMD_BYTES * 14); res25 = fma52lo(res25, u10, m[15]); res26 = fma52hi(res26, u10, m[15]); fma52lo_mem(res26, res26, u10, m, SIMD_BYTES * 16); fma52hi_mem(res27, res27, u10, m, SIMD_BYTES * 16); res27 = fma52lo(res27, u10, m[17]); res28 = fma52hi(res28, u10, m[17]); fma52lo_mem(res28, res28, u10, m, SIMD_BYTES * 18); fma52hi_mem(res29, res29, u10, m, SIMD_BYTES * 18); res29 = fma52lo(res29, u10, m[19]); res30 = fma52hi(res30, u10, m[19]); // Create u11 fma52lo_mem(res11, res11, u11, m, SIMD_BYTES * 0); fma52hi_mem(res12, res12, u11, m, SIMD_BYTES * 0); res12 = fma52lo(res12, u11, m[1]); res13 = fma52hi(res13, u11, m[1]); res12 = add64(res12, srli64(res11, DIGIT_SIZE)); U64 u12 = mul52lo(res12, k); fma52lo_mem(res13, res13, u11, m, SIMD_BYTES * 2); fma52hi_mem(res14, res14, u11, m, SIMD_BYTES * 2); res14 = fma52lo(res14, u11, m[3]); res15 = fma52hi(res15, u11, m[3]); fma52lo_mem(res15, res15, u11, m, SIMD_BYTES * 4); fma52hi_mem(res16, res16, u11, m, SIMD_BYTES * 4); res16 = fma52lo(res16, u11, m[5]); res17 = fma52hi(res17, u11, m[5]); fma52lo_mem(res17, res17, u11, m, SIMD_BYTES * 6); fma52hi_mem(res18, res18, u11, m, SIMD_BYTES * 6); res18 = fma52lo(res18, u11, m[7]); res19 = fma52hi(res19, u11, m[7]); fma52lo_mem(res19, res19, u11, m, SIMD_BYTES * 8); fma52hi_mem(res20, res20, u11, m, SIMD_BYTES * 8); res20 = fma52lo(res20, u11, m[9]); res21 = fma52hi(res21, u11, m[9]); fma52lo_mem(res21, res21, u11, m, SIMD_BYTES * 10); fma52hi_mem(res22, res22, u11, m, SIMD_BYTES * 10); res22 = fma52lo(res22, u11, m[11]); res23 = fma52hi(res23, u11, m[11]); fma52lo_mem(res23, res23, u11, m, SIMD_BYTES * 12); fma52hi_mem(res24, res24, u11, m, SIMD_BYTES * 12); res24 = fma52lo(res24, u11, m[13]); res25 = fma52hi(res25, u11, m[13]); fma52lo_mem(res25, res25, u11, m, SIMD_BYTES * 14); fma52hi_mem(res26, res26, u11, m, SIMD_BYTES * 14); res26 = fma52lo(res26, u11, m[15]); res27 = fma52hi(res27, u11, m[15]); fma52lo_mem(res27, res27, u11, m, SIMD_BYTES * 16); fma52hi_mem(res28, res28, u11, m, SIMD_BYTES * 16); res28 = fma52lo(res28, u11, m[17]); res29 = fma52hi(res29, u11, m[17]); fma52lo_mem(res29, res29, u11, m, SIMD_BYTES * 18); fma52hi_mem(res30, res30, u11, m, SIMD_BYTES * 18); res30 = fma52lo(res30, u11, m[19]); res31 = fma52hi(res31, u11, m[19]); ASM("jmp l12\nl12:\n"); // Create u12 fma52lo_mem(res12, res12, u12, m, SIMD_BYTES * 0); fma52hi_mem(res13, res13, u12, m, SIMD_BYTES * 0); res13 = fma52lo(res13, u12, m[1]); res14 = fma52hi(res14, u12, m[1]); res13 = add64(res13, srli64(res12, DIGIT_SIZE)); U64 u13 = mul52lo(res13, k); fma52lo_mem(res14, res14, u12, m, SIMD_BYTES * 2); fma52hi_mem(res15, res15, u12, m, SIMD_BYTES * 2); res15 = fma52lo(res15, u12, m[3]); res16 = fma52hi(res16, u12, m[3]); fma52lo_mem(res16, res16, u12, m, SIMD_BYTES * 4); fma52hi_mem(res17, res17, u12, m, SIMD_BYTES * 4); res17 = fma52lo(res17, u12, m[5]); res18 = fma52hi(res18, u12, m[5]); fma52lo_mem(res18, res18, u12, m, SIMD_BYTES * 6); fma52hi_mem(res19, res19, u12, m, SIMD_BYTES * 6); res19 = fma52lo(res19, u12, m[7]); res20 = fma52hi(res20, u12, m[7]); fma52lo_mem(res20, res20, u12, m, SIMD_BYTES * 8); fma52hi_mem(res21, res21, u12, m, SIMD_BYTES * 8); res21 = fma52lo(res21, u12, m[9]); res22 = fma52hi(res22, u12, m[9]); fma52lo_mem(res22, res22, u12, m, SIMD_BYTES * 10); fma52hi_mem(res23, res23, u12, m, SIMD_BYTES * 10); res23 = fma52lo(res23, u12, m[11]); res24 = fma52hi(res24, u12, m[11]); fma52lo_mem(res24, res24, u12, m, SIMD_BYTES * 12); fma52hi_mem(res25, res25, u12, m, SIMD_BYTES * 12); res25 = fma52lo(res25, u12, m[13]); res26 = fma52hi(res26, u12, m[13]); fma52lo_mem(res26, res26, u12, m, SIMD_BYTES * 14); fma52hi_mem(res27, res27, u12, m, SIMD_BYTES * 14); res27 = fma52lo(res27, u12, m[15]); res28 = fma52hi(res28, u12, m[15]); fma52lo_mem(res28, res28, u12, m, SIMD_BYTES * 16); fma52hi_mem(res29, res29, u12, m, SIMD_BYTES * 16); res29 = fma52lo(res29, u12, m[17]); res30 = fma52hi(res30, u12, m[17]); fma52lo_mem(res30, res30, u12, m, SIMD_BYTES * 18); fma52hi_mem(res31, res31, u12, m, SIMD_BYTES * 18); res31 = fma52lo(res31, u12, m[19]); res32 = fma52hi(res32, u12, m[19]); // Create u13 fma52lo_mem(res13, res13, u13, m, SIMD_BYTES * 0); fma52hi_mem(res14, res14, u13, m, SIMD_BYTES * 0); res14 = fma52lo(res14, u13, m[1]); res15 = fma52hi(res15, u13, m[1]); res14 = add64(res14, srli64(res13, DIGIT_SIZE)); U64 u14 = mul52lo(res14, k); fma52lo_mem(res15, res15, u13, m, SIMD_BYTES * 2); fma52hi_mem(res16, res16, u13, m, SIMD_BYTES * 2); res16 = fma52lo(res16, u13, m[3]); res17 = fma52hi(res17, u13, m[3]); fma52lo_mem(res17, res17, u13, m, SIMD_BYTES * 4); fma52hi_mem(res18, res18, u13, m, SIMD_BYTES * 4); res18 = fma52lo(res18, u13, m[5]); res19 = fma52hi(res19, u13, m[5]); fma52lo_mem(res19, res19, u13, m, SIMD_BYTES * 6); fma52hi_mem(res20, res20, u13, m, SIMD_BYTES * 6); res20 = fma52lo(res20, u13, m[7]); res21 = fma52hi(res21, u13, m[7]); fma52lo_mem(res21, res21, u13, m, SIMD_BYTES * 8); fma52hi_mem(res22, res22, u13, m, SIMD_BYTES * 8); res22 = fma52lo(res22, u13, m[9]); res23 = fma52hi(res23, u13, m[9]); fma52lo_mem(res23, res23, u13, m, SIMD_BYTES * 10); fma52hi_mem(res24, res24, u13, m, SIMD_BYTES * 10); res24 = fma52lo(res24, u13, m[11]); res25 = fma52hi(res25, u13, m[11]); fma52lo_mem(res25, res25, u13, m, SIMD_BYTES * 12); fma52hi_mem(res26, res26, u13, m, SIMD_BYTES * 12); res26 = fma52lo(res26, u13, m[13]); res27 = fma52hi(res27, u13, m[13]); fma52lo_mem(res27, res27, u13, m, SIMD_BYTES * 14); fma52hi_mem(res28, res28, u13, m, SIMD_BYTES * 14); res28 = fma52lo(res28, u13, m[15]); res29 = fma52hi(res29, u13, m[15]); fma52lo_mem(res29, res29, u13, m, SIMD_BYTES * 16); fma52hi_mem(res30, res30, u13, m, SIMD_BYTES * 16); res30 = fma52lo(res30, u13, m[17]); res31 = fma52hi(res31, u13, m[17]); fma52lo_mem(res31, res31, u13, m, SIMD_BYTES * 18); fma52hi_mem(res32, res32, u13, m, SIMD_BYTES * 18); res32 = fma52lo(res32, u13, m[19]); res33 = fma52hi(res33, u13, m[19]); ASM("jmp l14\nl14:\n"); // Create u14 fma52lo_mem(res14, res14, u14, m, SIMD_BYTES * 0); fma52hi_mem(res15, res15, u14, m, SIMD_BYTES * 0); res15 = fma52lo(res15, u14, m[1]); res16 = fma52hi(res16, u14, m[1]); res15 = add64(res15, srli64(res14, DIGIT_SIZE)); U64 u15 = mul52lo(res15, k); fma52lo_mem(res16, res16, u14, m, SIMD_BYTES * 2); fma52hi_mem(res17, res17, u14, m, SIMD_BYTES * 2); res17 = fma52lo(res17, u14, m[3]); res18 = fma52hi(res18, u14, m[3]); fma52lo_mem(res18, res18, u14, m, SIMD_BYTES * 4); fma52hi_mem(res19, res19, u14, m, SIMD_BYTES * 4); res19 = fma52lo(res19, u14, m[5]); res20 = fma52hi(res20, u14, m[5]); fma52lo_mem(res20, res20, u14, m, SIMD_BYTES * 6); fma52hi_mem(res21, res21, u14, m, SIMD_BYTES * 6); res21 = fma52lo(res21, u14, m[7]); res22 = fma52hi(res22, u14, m[7]); fma52lo_mem(res22, res22, u14, m, SIMD_BYTES * 8); fma52hi_mem(res23, res23, u14, m, SIMD_BYTES * 8); res23 = fma52lo(res23, u14, m[9]); res24 = fma52hi(res24, u14, m[9]); fma52lo_mem(res24, res24, u14, m, SIMD_BYTES * 10); fma52hi_mem(res25, res25, u14, m, SIMD_BYTES * 10); res25 = fma52lo(res25, u14, m[11]); res26 = fma52hi(res26, u14, m[11]); fma52lo_mem(res26, res26, u14, m, SIMD_BYTES * 12); fma52hi_mem(res27, res27, u14, m, SIMD_BYTES * 12); res27 = fma52lo(res27, u14, m[13]); res28 = fma52hi(res28, u14, m[13]); fma52lo_mem(res28, res28, u14, m, SIMD_BYTES * 14); fma52hi_mem(res29, res29, u14, m, SIMD_BYTES * 14); res29 = fma52lo(res29, u14, m[15]); res30 = fma52hi(res30, u14, m[15]); fma52lo_mem(res30, res30, u14, m, SIMD_BYTES * 16); fma52hi_mem(res31, res31, u14, m, SIMD_BYTES * 16); res31 = fma52lo(res31, u14, m[17]); res32 = fma52hi(res32, u14, m[17]); fma52lo_mem(res32, res32, u14, m, SIMD_BYTES * 18); fma52hi_mem(res33, res33, u14, m, SIMD_BYTES * 18); res33 = fma52lo(res33, u14, m[19]); res34 = fma52hi(res34, u14, m[19]); // Create u15 fma52lo_mem(res15, res15, u15, m, SIMD_BYTES * 0); fma52hi_mem(res16, res16, u15, m, SIMD_BYTES * 0); res16 = fma52lo(res16, u15, m[1]); res17 = fma52hi(res17, u15, m[1]); res16 = add64(res16, srli64(res15, DIGIT_SIZE)); U64 u16 = mul52lo(res16, k); fma52lo_mem(res17, res17, u15, m, SIMD_BYTES * 2); fma52hi_mem(res18, res18, u15, m, SIMD_BYTES * 2); res18 = fma52lo(res18, u15, m[3]); res19 = fma52hi(res19, u15, m[3]); fma52lo_mem(res19, res19, u15, m, SIMD_BYTES * 4); fma52hi_mem(res20, res20, u15, m, SIMD_BYTES * 4); res20 = fma52lo(res20, u15, m[5]); res21 = fma52hi(res21, u15, m[5]); fma52lo_mem(res21, res21, u15, m, SIMD_BYTES * 6); fma52hi_mem(res22, res22, u15, m, SIMD_BYTES * 6); res22 = fma52lo(res22, u15, m[7]); res23 = fma52hi(res23, u15, m[7]); fma52lo_mem(res23, res23, u15, m, SIMD_BYTES * 8); fma52hi_mem(res24, res24, u15, m, SIMD_BYTES * 8); res24 = fma52lo(res24, u15, m[9]); res25 = fma52hi(res25, u15, m[9]); fma52lo_mem(res25, res25, u15, m, SIMD_BYTES * 10); fma52hi_mem(res26, res26, u15, m, SIMD_BYTES * 10); res26 = fma52lo(res26, u15, m[11]); res27 = fma52hi(res27, u15, m[11]); fma52lo_mem(res27, res27, u15, m, SIMD_BYTES * 12); fma52hi_mem(res28, res28, u15, m, SIMD_BYTES * 12); res28 = fma52lo(res28, u15, m[13]); res29 = fma52hi(res29, u15, m[13]); fma52lo_mem(res29, res29, u15, m, SIMD_BYTES * 14); fma52hi_mem(res30, res30, u15, m, SIMD_BYTES * 14); res30 = fma52lo(res30, u15, m[15]); res31 = fma52hi(res31, u15, m[15]); fma52lo_mem(res31, res31, u15, m, SIMD_BYTES * 16); fma52hi_mem(res32, res32, u15, m, SIMD_BYTES * 16); res32 = fma52lo(res32, u15, m[17]); res33 = fma52hi(res33, u15, m[17]); fma52lo_mem(res33, res33, u15, m, SIMD_BYTES * 18); fma52hi_mem(res34, res34, u15, m, SIMD_BYTES * 18); res34 = fma52lo(res34, u15, m[19]); res35 = fma52hi(res35, u15, m[19]); ASM("jmp l16\nl16:\n"); // Create u16 fma52lo_mem(res16, res16, u16, m, SIMD_BYTES * 0); fma52hi_mem(res17, res17, u16, m, SIMD_BYTES * 0); res17 = fma52lo(res17, u16, m[1]); res18 = fma52hi(res18, u16, m[1]); res17 = add64(res17, srli64(res16, DIGIT_SIZE)); U64 u17 = mul52lo(res17, k); fma52lo_mem(res18, res18, u16, m, SIMD_BYTES * 2); fma52hi_mem(res19, res19, u16, m, SIMD_BYTES * 2); res19 = fma52lo(res19, u16, m[3]); res20 = fma52hi(res20, u16, m[3]); fma52lo_mem(res20, res20, u16, m, SIMD_BYTES * 4); fma52hi_mem(res21, res21, u16, m, SIMD_BYTES * 4); res21 = fma52lo(res21, u16, m[5]); res22 = fma52hi(res22, u16, m[5]); fma52lo_mem(res22, res22, u16, m, SIMD_BYTES * 6); fma52hi_mem(res23, res23, u16, m, SIMD_BYTES * 6); res23 = fma52lo(res23, u16, m[7]); res24 = fma52hi(res24, u16, m[7]); fma52lo_mem(res24, res24, u16, m, SIMD_BYTES * 8); fma52hi_mem(res25, res25, u16, m, SIMD_BYTES * 8); res25 = fma52lo(res25, u16, m[9]); res26 = fma52hi(res26, u16, m[9]); fma52lo_mem(res26, res26, u16, m, SIMD_BYTES * 10); fma52hi_mem(res27, res27, u16, m, SIMD_BYTES * 10); res27 = fma52lo(res27, u16, m[11]); res28 = fma52hi(res28, u16, m[11]); fma52lo_mem(res28, res28, u16, m, SIMD_BYTES * 12); fma52hi_mem(res29, res29, u16, m, SIMD_BYTES * 12); res29 = fma52lo(res29, u16, m[13]); res30 = fma52hi(res30, u16, m[13]); fma52lo_mem(res30, res30, u16, m, SIMD_BYTES * 14); fma52hi_mem(res31, res31, u16, m, SIMD_BYTES * 14); res31 = fma52lo(res31, u16, m[15]); res32 = fma52hi(res32, u16, m[15]); fma52lo_mem(res32, res32, u16, m, SIMD_BYTES * 16); fma52hi_mem(res33, res33, u16, m, SIMD_BYTES * 16); res33 = fma52lo(res33, u16, m[17]); res34 = fma52hi(res34, u16, m[17]); fma52lo_mem(res34, res34, u16, m, SIMD_BYTES * 18); fma52hi_mem(res35, res35, u16, m, SIMD_BYTES * 18); res35 = fma52lo(res35, u16, m[19]); res36 = fma52hi(res36, u16, m[19]); // Create u17 fma52lo_mem(res17, res17, u17, m, SIMD_BYTES * 0); fma52hi_mem(res18, res18, u17, m, SIMD_BYTES * 0); res18 = fma52lo(res18, u17, m[1]); res19 = fma52hi(res19, u17, m[1]); res18 = add64(res18, srli64(res17, DIGIT_SIZE)); U64 u18 = mul52lo(res18, k); fma52lo_mem(res19, res19, u17, m, SIMD_BYTES * 2); fma52hi_mem(res20, res20, u17, m, SIMD_BYTES * 2); res20 = fma52lo(res20, u17, m[3]); res21 = fma52hi(res21, u17, m[3]); fma52lo_mem(res21, res21, u17, m, SIMD_BYTES * 4); fma52hi_mem(res22, res22, u17, m, SIMD_BYTES * 4); res22 = fma52lo(res22, u17, m[5]); res23 = fma52hi(res23, u17, m[5]); fma52lo_mem(res23, res23, u17, m, SIMD_BYTES * 6); fma52hi_mem(res24, res24, u17, m, SIMD_BYTES * 6); res24 = fma52lo(res24, u17, m[7]); res25 = fma52hi(res25, u17, m[7]); fma52lo_mem(res25, res25, u17, m, SIMD_BYTES * 8); fma52hi_mem(res26, res26, u17, m, SIMD_BYTES * 8); res26 = fma52lo(res26, u17, m[9]); res27 = fma52hi(res27, u17, m[9]); fma52lo_mem(res27, res27, u17, m, SIMD_BYTES * 10); fma52hi_mem(res28, res28, u17, m, SIMD_BYTES * 10); res28 = fma52lo(res28, u17, m[11]); res29 = fma52hi(res29, u17, m[11]); fma52lo_mem(res29, res29, u17, m, SIMD_BYTES * 12); fma52hi_mem(res30, res30, u17, m, SIMD_BYTES * 12); res30 = fma52lo(res30, u17, m[13]); res31 = fma52hi(res31, u17, m[13]); fma52lo_mem(res31, res31, u17, m, SIMD_BYTES * 14); fma52hi_mem(res32, res32, u17, m, SIMD_BYTES * 14); res32 = fma52lo(res32, u17, m[15]); res33 = fma52hi(res33, u17, m[15]); fma52lo_mem(res33, res33, u17, m, SIMD_BYTES * 16); fma52hi_mem(res34, res34, u17, m, SIMD_BYTES * 16); res34 = fma52lo(res34, u17, m[17]); res35 = fma52hi(res35, u17, m[17]); fma52lo_mem(res35, res35, u17, m, SIMD_BYTES * 18); fma52hi_mem(res36, res36, u17, m, SIMD_BYTES * 18); res36 = fma52lo(res36, u17, m[19]); res37 = fma52hi(res37, u17, m[19]); ASM("jmp l18\nl18:\n"); // Create u18 fma52lo_mem(res18, res18, u18, m, SIMD_BYTES * 0); fma52hi_mem(res19, res19, u18, m, SIMD_BYTES * 0); res19 = fma52lo(res19, u18, m[1]); res20 = fma52hi(res20, u18, m[1]); res19 = add64(res19, srli64(res18, DIGIT_SIZE)); U64 u19 = mul52lo(res19, k); fma52lo_mem(res20, res20, u18, m, SIMD_BYTES * 2); fma52hi_mem(res21, res21, u18, m, SIMD_BYTES * 2); res21 = fma52lo(res21, u18, m[3]); res22 = fma52hi(res22, u18, m[3]); fma52lo_mem(res22, res22, u18, m, SIMD_BYTES * 4); fma52hi_mem(res23, res23, u18, m, SIMD_BYTES * 4); res23 = fma52lo(res23, u18, m[5]); res24 = fma52hi(res24, u18, m[5]); fma52lo_mem(res24, res24, u18, m, SIMD_BYTES * 6); fma52hi_mem(res25, res25, u18, m, SIMD_BYTES * 6); res25 = fma52lo(res25, u18, m[7]); res26 = fma52hi(res26, u18, m[7]); fma52lo_mem(res26, res26, u18, m, SIMD_BYTES * 8); fma52hi_mem(res27, res27, u18, m, SIMD_BYTES * 8); res27 = fma52lo(res27, u18, m[9]); res28 = fma52hi(res28, u18, m[9]); fma52lo_mem(res28, res28, u18, m, SIMD_BYTES * 10); fma52hi_mem(res29, res29, u18, m, SIMD_BYTES * 10); res29 = fma52lo(res29, u18, m[11]); res30 = fma52hi(res30, u18, m[11]); fma52lo_mem(res30, res30, u18, m, SIMD_BYTES * 12); fma52hi_mem(res31, res31, u18, m, SIMD_BYTES * 12); res31 = fma52lo(res31, u18, m[13]); res32 = fma52hi(res32, u18, m[13]); fma52lo_mem(res32, res32, u18, m, SIMD_BYTES * 14); fma52hi_mem(res33, res33, u18, m, SIMD_BYTES * 14); res33 = fma52lo(res33, u18, m[15]); res34 = fma52hi(res34, u18, m[15]); fma52lo_mem(res34, res34, u18, m, SIMD_BYTES * 16); fma52hi_mem(res35, res35, u18, m, SIMD_BYTES * 16); res35 = fma52lo(res35, u18, m[17]); res36 = fma52hi(res36, u18, m[17]); fma52lo_mem(res36, res36, u18, m, SIMD_BYTES * 18); fma52hi_mem(res37, res37, u18, m, SIMD_BYTES * 18); res37 = fma52lo(res37, u18, m[19]); res38 = fma52hi(res38, u18, m[19]); // Create u19 fma52lo_mem(res19, res19, u19, m, SIMD_BYTES * 0); fma52hi_mem(res20, res20, u19, m, SIMD_BYTES * 0); res20 = fma52lo(res20, u19, m[1]); res21 = fma52hi(res21, u19, m[1]); res20 = add64(res20, srli64(res19, DIGIT_SIZE)); fma52lo_mem(res21, res21, u19, m, SIMD_BYTES * 2); fma52hi_mem(res22, res22, u19, m, SIMD_BYTES * 2); res22 = fma52lo(res22, u19, m[3]); res23 = fma52hi(res23, u19, m[3]); fma52lo_mem(res23, res23, u19, m, SIMD_BYTES * 4); fma52hi_mem(res24, res24, u19, m, SIMD_BYTES * 4); res24 = fma52lo(res24, u19, m[5]); res25 = fma52hi(res25, u19, m[5]); fma52lo_mem(res25, res25, u19, m, SIMD_BYTES * 6); fma52hi_mem(res26, res26, u19, m, SIMD_BYTES * 6); res26 = fma52lo(res26, u19, m[7]); res27 = fma52hi(res27, u19, m[7]); fma52lo_mem(res27, res27, u19, m, SIMD_BYTES * 8); fma52hi_mem(res28, res28, u19, m, SIMD_BYTES * 8); res28 = fma52lo(res28, u19, m[9]); res29 = fma52hi(res29, u19, m[9]); fma52lo_mem(res29, res29, u19, m, SIMD_BYTES * 10); fma52hi_mem(res30, res30, u19, m, SIMD_BYTES * 10); res30 = fma52lo(res30, u19, m[11]); res31 = fma52hi(res31, u19, m[11]); fma52lo_mem(res31, res31, u19, m, SIMD_BYTES * 12); fma52hi_mem(res32, res32, u19, m, SIMD_BYTES * 12); res32 = fma52lo(res32, u19, m[13]); res33 = fma52hi(res33, u19, m[13]); fma52lo_mem(res33, res33, u19, m, SIMD_BYTES * 14); fma52hi_mem(res34, res34, u19, m, SIMD_BYTES * 14); res34 = fma52lo(res34, u19, m[15]); res35 = fma52hi(res35, u19, m[15]); fma52lo_mem(res35, res35, u19, m, SIMD_BYTES * 16); fma52hi_mem(res36, res36, u19, m, SIMD_BYTES * 16); res36 = fma52lo(res36, u19, m[17]); res37 = fma52hi(res37, u19, m[17]); fma52lo_mem(res37, res37, u19, m, SIMD_BYTES * 18); fma52hi_mem(res38, res38, u19, m, SIMD_BYTES * 18); res38 = fma52lo(res38, u19, m[19]); res39 = fma52hi(res39, u19, m[19]); // Normalization r[0] = res20; res21 = add64(res21, srli64(res20, DIGIT_SIZE)); r[1] = res21; res22 = add64(res22, srli64(res21, DIGIT_SIZE)); r[2] = res22; res23 = add64(res23, srli64(res22, DIGIT_SIZE)); r[3] = res23; res24 = add64(res24, srli64(res23, DIGIT_SIZE)); r[4] = res24; res25 = add64(res25, srli64(res24, DIGIT_SIZE)); r[5] = res25; res26 = add64(res26, srli64(res25, DIGIT_SIZE)); r[6] = res26; res27 = add64(res27, srli64(res26, DIGIT_SIZE)); r[7] = res27; res28 = add64(res28, srli64(res27, DIGIT_SIZE)); r[8] = res28; res29 = add64(res29, srli64(res28, DIGIT_SIZE)); r[9] = res29; res30 = add64(res30, srli64(res29, DIGIT_SIZE)); r[10] = res30; res31 = add64(res31, srli64(res30, DIGIT_SIZE)); r[11] = res31; res32 = add64(res32, srli64(res31, DIGIT_SIZE)); r[12] = res32; res33 = add64(res33, srli64(res32, DIGIT_SIZE)); r[13] = res33; res34 = add64(res34, srli64(res33, DIGIT_SIZE)); r[14] = res34; res35 = add64(res35, srli64(res34, DIGIT_SIZE)); r[15] = res35; res36 = add64(res36, srli64(res35, DIGIT_SIZE)); r[16] = res36; res37 = add64(res37, srli64(res36, DIGIT_SIZE)); r[17] = res37; res38 = add64(res38, srli64(res37, DIGIT_SIZE)); r[18] = res38; res39 = add64(res39, srli64(res38, DIGIT_SIZE)); r[19] = res39; a = (U64 *)out_mb; } } #endif /* #if (_MBX>=_MBX_K1) */ ifma_ams5x52x40_diagonal_mb8.c000066400000000000000000004221311470420105600347550ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) void AMS5x52x40_diagonal_mb8(int64u *out_mb, const int64u *inpA_mb, const int64u *inpM_mb, const int64u *k0_mb) { __ALIGN64 U64 res[80]; __ALIGN64 U64 u[40]; U64 k; U64 *a = (U64 *)inpA_mb; U64 *m = (U64 *)inpM_mb; U64 *r = (U64 *)out_mb; int iter; const int iters = 5; k = loadu64((U64 *)k0_mb); for (iter = 0; iter < iters; ++iter) { int i; for (i = 0; i < 80; ++i) res[i] = get_zero64(); // Calculate full square res[1] = fma52lo(res[1], a[0], a[1]); // Sum(1) res[2] = fma52hi(res[2], a[0], a[1]); // Sum(1) res[2] = fma52lo(res[2], a[0], a[2]); // Sum(2) res[3] = fma52hi(res[3], a[0], a[2]); // Sum(2) res[3] = fma52lo(res[3], a[1], a[2]); // Sum(3) res[4] = fma52hi(res[4], a[1], a[2]); // Sum(3) res[3] = fma52lo(res[3], a[0], a[3]); // Sum(3) res[4] = fma52hi(res[4], a[0], a[3]); // Sum(3) res[4] = fma52lo(res[4], a[1], a[3]); // Sum(4) res[5] = fma52hi(res[5], a[1], a[3]); // Sum(4) res[5] = fma52lo(res[5], a[2], a[3]); // Sum(5) res[6] = fma52hi(res[6], a[2], a[3]); // Sum(5) res[4] = fma52lo(res[4], a[0], a[4]); // Sum(4) res[5] = fma52hi(res[5], a[0], a[4]); // Sum(4) res[5] = fma52lo(res[5], a[1], a[4]); // Sum(5) res[6] = fma52hi(res[6], a[1], a[4]); // Sum(5) res[6] = fma52lo(res[6], a[2], a[4]); // Sum(6) res[7] = fma52hi(res[7], a[2], a[4]); // Sum(6) res[7] = fma52lo(res[7], a[3], a[4]); // Sum(7) res[8] = fma52hi(res[8], a[3], a[4]); // Sum(7) res[5] = fma52lo(res[5], a[0], a[5]); // Sum(5) res[6] = fma52hi(res[6], a[0], a[5]); // Sum(5) res[6] = fma52lo(res[6], a[1], a[5]); // Sum(6) res[7] = fma52hi(res[7], a[1], a[5]); // Sum(6) res[7] = fma52lo(res[7], a[2], a[5]); // Sum(7) res[8] = fma52hi(res[8], a[2], a[5]); // Sum(7) res[8] = fma52lo(res[8], a[3], a[5]); // Sum(8) res[9] = fma52hi(res[9], a[3], a[5]); // Sum(8) res[9] = fma52lo(res[9], a[4], a[5]); // Sum(9) res[10] = fma52hi(res[10], a[4], a[5]); // Sum(9) res[6] = fma52lo(res[6], a[0], a[6]); // Sum(6) res[7] = fma52hi(res[7], a[0], a[6]); // Sum(6) res[7] = fma52lo(res[7], a[1], a[6]); // Sum(7) res[8] = fma52hi(res[8], a[1], a[6]); // Sum(7) res[8] = fma52lo(res[8], a[2], a[6]); // Sum(8) res[9] = fma52hi(res[9], a[2], a[6]); // Sum(8) res[9] = fma52lo(res[9], a[3], a[6]); // Sum(9) res[10] = fma52hi(res[10], a[3], a[6]); // Sum(9) res[10] = fma52lo(res[10], a[4], a[6]); // Sum(10) res[11] = fma52hi(res[11], a[4], a[6]); // Sum(10) res[11] = fma52lo(res[11], a[5], a[6]); // Sum(11) res[12] = fma52hi(res[12], a[5], a[6]); // Sum(11) res[7] = fma52lo(res[7], a[0], a[7]); // Sum(7) res[8] = fma52hi(res[8], a[0], a[7]); // Sum(7) res[8] = fma52lo(res[8], a[1], a[7]); // Sum(8) res[9] = fma52hi(res[9], a[1], a[7]); // Sum(8) res[9] = fma52lo(res[9], a[2], a[7]); // Sum(9) res[10] = fma52hi(res[10], a[2], a[7]); // Sum(9) res[10] = fma52lo(res[10], a[3], a[7]); // Sum(10) res[11] = fma52hi(res[11], a[3], a[7]); // Sum(10) res[11] = fma52lo(res[11], a[4], a[7]); // Sum(11) res[12] = fma52hi(res[12], a[4], a[7]); // Sum(11) res[8] = fma52lo(res[8], a[0], a[8]); // Sum(8) res[9] = fma52hi(res[9], a[0], a[8]); // Sum(8) res[9] = fma52lo(res[9], a[1], a[8]); // Sum(9) res[10] = fma52hi(res[10], a[1], a[8]); // Sum(9) res[10] = fma52lo(res[10], a[2], a[8]); // Sum(10) res[11] = fma52hi(res[11], a[2], a[8]); // Sum(10) res[11] = fma52lo(res[11], a[3], a[8]); // Sum(11) res[12] = fma52hi(res[12], a[3], a[8]); // Sum(11) res[9] = fma52lo(res[9], a[0], a[9]); // Sum(9) res[10] = fma52hi(res[10], a[0], a[9]); // Sum(9) res[10] = fma52lo(res[10], a[1], a[9]); // Sum(10) res[11] = fma52hi(res[11], a[1], a[9]); // Sum(10) res[11] = fma52lo(res[11], a[2], a[9]); // Sum(11) res[12] = fma52hi(res[12], a[2], a[9]); // Sum(11) res[10] = fma52lo(res[10], a[0], a[10]); // Sum(10) res[11] = fma52hi(res[11], a[0], a[10]); // Sum(10) res[11] = fma52lo(res[11], a[1], a[10]); // Sum(11) res[12] = fma52hi(res[12], a[1], a[10]); // Sum(11) res[11] = fma52lo(res[11], a[0], a[11]); // Sum(11) res[12] = fma52hi(res[12], a[0], a[11]); // Sum(11) res[0] = add64(res[0], res[0]); // Double(0) res[1] = add64(res[1], res[1]); // Double(1) res[2] = add64(res[2], res[2]); // Double(2) res[3] = add64(res[3], res[3]); // Double(3) res[4] = add64(res[4], res[4]); // Double(4) res[5] = add64(res[5], res[5]); // Double(5) res[6] = add64(res[6], res[6]); // Double(6) res[7] = add64(res[7], res[7]); // Double(7) res[8] = add64(res[8], res[8]); // Double(8) res[9] = add64(res[9], res[9]); // Double(9) res[10] = add64(res[10], res[10]); // Double(10) res[11] = add64(res[11], res[11]); // Double(11) res[0] = fma52lo(res[0], a[0], a[0]); // Add sqr(0) res[1] = fma52hi(res[1], a[0], a[0]); // Add sqr(0) res[2] = fma52lo(res[2], a[1], a[1]); // Add sqr(2) res[3] = fma52hi(res[3], a[1], a[1]); // Add sqr(2) res[4] = fma52lo(res[4], a[2], a[2]); // Add sqr(4) res[5] = fma52hi(res[5], a[2], a[2]); // Add sqr(4) res[6] = fma52lo(res[6], a[3], a[3]); // Add sqr(6) res[7] = fma52hi(res[7], a[3], a[3]); // Add sqr(6) res[8] = fma52lo(res[8], a[4], a[4]); // Add sqr(8) res[9] = fma52hi(res[9], a[4], a[4]); // Add sqr(8) res[10] = fma52lo(res[10], a[5], a[5]); // Add sqr(10) res[11] = fma52hi(res[11], a[5], a[5]); // Add sqr(10) res[12] = fma52lo(res[12], a[5], a[7]); // Sum(12) res[13] = fma52hi(res[13], a[5], a[7]); // Sum(12) res[13] = fma52lo(res[13], a[6], a[7]); // Sum(13) res[14] = fma52hi(res[14], a[6], a[7]); // Sum(13) res[12] = fma52lo(res[12], a[4], a[8]); // Sum(12) res[13] = fma52hi(res[13], a[4], a[8]); // Sum(12) res[13] = fma52lo(res[13], a[5], a[8]); // Sum(13) res[14] = fma52hi(res[14], a[5], a[8]); // Sum(13) res[14] = fma52lo(res[14], a[6], a[8]); // Sum(14) res[15] = fma52hi(res[15], a[6], a[8]); // Sum(14) res[15] = fma52lo(res[15], a[7], a[8]); // Sum(15) res[16] = fma52hi(res[16], a[7], a[8]); // Sum(15) res[12] = fma52lo(res[12], a[3], a[9]); // Sum(12) res[13] = fma52hi(res[13], a[3], a[9]); // Sum(12) res[13] = fma52lo(res[13], a[4], a[9]); // Sum(13) res[14] = fma52hi(res[14], a[4], a[9]); // Sum(13) res[14] = fma52lo(res[14], a[5], a[9]); // Sum(14) res[15] = fma52hi(res[15], a[5], a[9]); // Sum(14) res[15] = fma52lo(res[15], a[6], a[9]); // Sum(15) res[16] = fma52hi(res[16], a[6], a[9]); // Sum(15) res[16] = fma52lo(res[16], a[7], a[9]); // Sum(16) res[17] = fma52hi(res[17], a[7], a[9]); // Sum(16) res[17] = fma52lo(res[17], a[8], a[9]); // Sum(17) res[18] = fma52hi(res[18], a[8], a[9]); // Sum(17) res[12] = fma52lo(res[12], a[2], a[10]); // Sum(12) res[13] = fma52hi(res[13], a[2], a[10]); // Sum(12) res[13] = fma52lo(res[13], a[3], a[10]); // Sum(13) res[14] = fma52hi(res[14], a[3], a[10]); // Sum(13) res[14] = fma52lo(res[14], a[4], a[10]); // Sum(14) res[15] = fma52hi(res[15], a[4], a[10]); // Sum(14) res[15] = fma52lo(res[15], a[5], a[10]); // Sum(15) res[16] = fma52hi(res[16], a[5], a[10]); // Sum(15) res[16] = fma52lo(res[16], a[6], a[10]); // Sum(16) res[17] = fma52hi(res[17], a[6], a[10]); // Sum(16) res[17] = fma52lo(res[17], a[7], a[10]); // Sum(17) res[18] = fma52hi(res[18], a[7], a[10]); // Sum(17) res[18] = fma52lo(res[18], a[8], a[10]); // Sum(18) res[19] = fma52hi(res[19], a[8], a[10]); // Sum(18) res[19] = fma52lo(res[19], a[9], a[10]); // Sum(19) res[20] = fma52hi(res[20], a[9], a[10]); // Sum(19) res[12] = fma52lo(res[12], a[1], a[11]); // Sum(12) res[13] = fma52hi(res[13], a[1], a[11]); // Sum(12) res[13] = fma52lo(res[13], a[2], a[11]); // Sum(13) res[14] = fma52hi(res[14], a[2], a[11]); // Sum(13) res[14] = fma52lo(res[14], a[3], a[11]); // Sum(14) res[15] = fma52hi(res[15], a[3], a[11]); // Sum(14) res[15] = fma52lo(res[15], a[4], a[11]); // Sum(15) res[16] = fma52hi(res[16], a[4], a[11]); // Sum(15) res[16] = fma52lo(res[16], a[5], a[11]); // Sum(16) res[17] = fma52hi(res[17], a[5], a[11]); // Sum(16) res[17] = fma52lo(res[17], a[6], a[11]); // Sum(17) res[18] = fma52hi(res[18], a[6], a[11]); // Sum(17) res[18] = fma52lo(res[18], a[7], a[11]); // Sum(18) res[19] = fma52hi(res[19], a[7], a[11]); // Sum(18) res[19] = fma52lo(res[19], a[8], a[11]); // Sum(19) res[20] = fma52hi(res[20], a[8], a[11]); // Sum(19) res[20] = fma52lo(res[20], a[9], a[11]); // Sum(20) res[21] = fma52hi(res[21], a[9], a[11]); // Sum(20) res[21] = fma52lo(res[21], a[10], a[11]); // Sum(21) res[22] = fma52hi(res[22], a[10], a[11]); // Sum(21) res[12] = fma52lo(res[12], a[0], a[12]); // Sum(12) res[13] = fma52hi(res[13], a[0], a[12]); // Sum(12) res[13] = fma52lo(res[13], a[1], a[12]); // Sum(13) res[14] = fma52hi(res[14], a[1], a[12]); // Sum(13) res[14] = fma52lo(res[14], a[2], a[12]); // Sum(14) res[15] = fma52hi(res[15], a[2], a[12]); // Sum(14) res[15] = fma52lo(res[15], a[3], a[12]); // Sum(15) res[16] = fma52hi(res[16], a[3], a[12]); // Sum(15) res[16] = fma52lo(res[16], a[4], a[12]); // Sum(16) res[17] = fma52hi(res[17], a[4], a[12]); // Sum(16) res[17] = fma52lo(res[17], a[5], a[12]); // Sum(17) res[18] = fma52hi(res[18], a[5], a[12]); // Sum(17) res[18] = fma52lo(res[18], a[6], a[12]); // Sum(18) res[19] = fma52hi(res[19], a[6], a[12]); // Sum(18) res[19] = fma52lo(res[19], a[7], a[12]); // Sum(19) res[20] = fma52hi(res[20], a[7], a[12]); // Sum(19) res[20] = fma52lo(res[20], a[8], a[12]); // Sum(20) res[21] = fma52hi(res[21], a[8], a[12]); // Sum(20) res[21] = fma52lo(res[21], a[9], a[12]); // Sum(21) res[22] = fma52hi(res[22], a[9], a[12]); // Sum(21) res[22] = fma52lo(res[22], a[10], a[12]); // Sum(22) res[23] = fma52hi(res[23], a[10], a[12]); // Sum(22) res[23] = fma52lo(res[23], a[11], a[12]); // Sum(23) res[24] = fma52hi(res[24], a[11], a[12]); // Sum(23) res[13] = fma52lo(res[13], a[0], a[13]); // Sum(13) res[14] = fma52hi(res[14], a[0], a[13]); // Sum(13) res[14] = fma52lo(res[14], a[1], a[13]); // Sum(14) res[15] = fma52hi(res[15], a[1], a[13]); // Sum(14) res[15] = fma52lo(res[15], a[2], a[13]); // Sum(15) res[16] = fma52hi(res[16], a[2], a[13]); // Sum(15) res[16] = fma52lo(res[16], a[3], a[13]); // Sum(16) res[17] = fma52hi(res[17], a[3], a[13]); // Sum(16) res[17] = fma52lo(res[17], a[4], a[13]); // Sum(17) res[18] = fma52hi(res[18], a[4], a[13]); // Sum(17) res[18] = fma52lo(res[18], a[5], a[13]); // Sum(18) res[19] = fma52hi(res[19], a[5], a[13]); // Sum(18) res[19] = fma52lo(res[19], a[6], a[13]); // Sum(19) res[20] = fma52hi(res[20], a[6], a[13]); // Sum(19) res[20] = fma52lo(res[20], a[7], a[13]); // Sum(20) res[21] = fma52hi(res[21], a[7], a[13]); // Sum(20) res[21] = fma52lo(res[21], a[8], a[13]); // Sum(21) res[22] = fma52hi(res[22], a[8], a[13]); // Sum(21) res[22] = fma52lo(res[22], a[9], a[13]); // Sum(22) res[23] = fma52hi(res[23], a[9], a[13]); // Sum(22) res[23] = fma52lo(res[23], a[10], a[13]); // Sum(23) res[24] = fma52hi(res[24], a[10], a[13]); // Sum(23) res[14] = fma52lo(res[14], a[0], a[14]); // Sum(14) res[15] = fma52hi(res[15], a[0], a[14]); // Sum(14) res[15] = fma52lo(res[15], a[1], a[14]); // Sum(15) res[16] = fma52hi(res[16], a[1], a[14]); // Sum(15) res[16] = fma52lo(res[16], a[2], a[14]); // Sum(16) res[17] = fma52hi(res[17], a[2], a[14]); // Sum(16) res[17] = fma52lo(res[17], a[3], a[14]); // Sum(17) res[18] = fma52hi(res[18], a[3], a[14]); // Sum(17) res[18] = fma52lo(res[18], a[4], a[14]); // Sum(18) res[19] = fma52hi(res[19], a[4], a[14]); // Sum(18) res[19] = fma52lo(res[19], a[5], a[14]); // Sum(19) res[20] = fma52hi(res[20], a[5], a[14]); // Sum(19) res[20] = fma52lo(res[20], a[6], a[14]); // Sum(20) res[21] = fma52hi(res[21], a[6], a[14]); // Sum(20) res[21] = fma52lo(res[21], a[7], a[14]); // Sum(21) res[22] = fma52hi(res[22], a[7], a[14]); // Sum(21) res[22] = fma52lo(res[22], a[8], a[14]); // Sum(22) res[23] = fma52hi(res[23], a[8], a[14]); // Sum(22) res[23] = fma52lo(res[23], a[9], a[14]); // Sum(23) res[24] = fma52hi(res[24], a[9], a[14]); // Sum(23) res[15] = fma52lo(res[15], a[0], a[15]); // Sum(15) res[16] = fma52hi(res[16], a[0], a[15]); // Sum(15) res[16] = fma52lo(res[16], a[1], a[15]); // Sum(16) res[17] = fma52hi(res[17], a[1], a[15]); // Sum(16) res[17] = fma52lo(res[17], a[2], a[15]); // Sum(17) res[18] = fma52hi(res[18], a[2], a[15]); // Sum(17) res[18] = fma52lo(res[18], a[3], a[15]); // Sum(18) res[19] = fma52hi(res[19], a[3], a[15]); // Sum(18) res[19] = fma52lo(res[19], a[4], a[15]); // Sum(19) res[20] = fma52hi(res[20], a[4], a[15]); // Sum(19) res[20] = fma52lo(res[20], a[5], a[15]); // Sum(20) res[21] = fma52hi(res[21], a[5], a[15]); // Sum(20) res[21] = fma52lo(res[21], a[6], a[15]); // Sum(21) res[22] = fma52hi(res[22], a[6], a[15]); // Sum(21) res[22] = fma52lo(res[22], a[7], a[15]); // Sum(22) res[23] = fma52hi(res[23], a[7], a[15]); // Sum(22) res[23] = fma52lo(res[23], a[8], a[15]); // Sum(23) res[24] = fma52hi(res[24], a[8], a[15]); // Sum(23) res[16] = fma52lo(res[16], a[0], a[16]); // Sum(16) res[17] = fma52hi(res[17], a[0], a[16]); // Sum(16) res[17] = fma52lo(res[17], a[1], a[16]); // Sum(17) res[18] = fma52hi(res[18], a[1], a[16]); // Sum(17) res[18] = fma52lo(res[18], a[2], a[16]); // Sum(18) res[19] = fma52hi(res[19], a[2], a[16]); // Sum(18) res[19] = fma52lo(res[19], a[3], a[16]); // Sum(19) res[20] = fma52hi(res[20], a[3], a[16]); // Sum(19) res[20] = fma52lo(res[20], a[4], a[16]); // Sum(20) res[21] = fma52hi(res[21], a[4], a[16]); // Sum(20) res[21] = fma52lo(res[21], a[5], a[16]); // Sum(21) res[22] = fma52hi(res[22], a[5], a[16]); // Sum(21) res[22] = fma52lo(res[22], a[6], a[16]); // Sum(22) res[23] = fma52hi(res[23], a[6], a[16]); // Sum(22) res[23] = fma52lo(res[23], a[7], a[16]); // Sum(23) res[24] = fma52hi(res[24], a[7], a[16]); // Sum(23) res[17] = fma52lo(res[17], a[0], a[17]); // Sum(17) res[18] = fma52hi(res[18], a[0], a[17]); // Sum(17) res[18] = fma52lo(res[18], a[1], a[17]); // Sum(18) res[19] = fma52hi(res[19], a[1], a[17]); // Sum(18) res[19] = fma52lo(res[19], a[2], a[17]); // Sum(19) res[20] = fma52hi(res[20], a[2], a[17]); // Sum(19) res[20] = fma52lo(res[20], a[3], a[17]); // Sum(20) res[21] = fma52hi(res[21], a[3], a[17]); // Sum(20) res[21] = fma52lo(res[21], a[4], a[17]); // Sum(21) res[22] = fma52hi(res[22], a[4], a[17]); // Sum(21) res[22] = fma52lo(res[22], a[5], a[17]); // Sum(22) res[23] = fma52hi(res[23], a[5], a[17]); // Sum(22) res[23] = fma52lo(res[23], a[6], a[17]); // Sum(23) res[24] = fma52hi(res[24], a[6], a[17]); // Sum(23) res[18] = fma52lo(res[18], a[0], a[18]); // Sum(18) res[19] = fma52hi(res[19], a[0], a[18]); // Sum(18) res[19] = fma52lo(res[19], a[1], a[18]); // Sum(19) res[20] = fma52hi(res[20], a[1], a[18]); // Sum(19) res[20] = fma52lo(res[20], a[2], a[18]); // Sum(20) res[21] = fma52hi(res[21], a[2], a[18]); // Sum(20) res[21] = fma52lo(res[21], a[3], a[18]); // Sum(21) res[22] = fma52hi(res[22], a[3], a[18]); // Sum(21) res[22] = fma52lo(res[22], a[4], a[18]); // Sum(22) res[23] = fma52hi(res[23], a[4], a[18]); // Sum(22) res[23] = fma52lo(res[23], a[5], a[18]); // Sum(23) res[24] = fma52hi(res[24], a[5], a[18]); // Sum(23) res[19] = fma52lo(res[19], a[0], a[19]); // Sum(19) res[20] = fma52hi(res[20], a[0], a[19]); // Sum(19) res[20] = fma52lo(res[20], a[1], a[19]); // Sum(20) res[21] = fma52hi(res[21], a[1], a[19]); // Sum(20) res[21] = fma52lo(res[21], a[2], a[19]); // Sum(21) res[22] = fma52hi(res[22], a[2], a[19]); // Sum(21) res[22] = fma52lo(res[22], a[3], a[19]); // Sum(22) res[23] = fma52hi(res[23], a[3], a[19]); // Sum(22) res[23] = fma52lo(res[23], a[4], a[19]); // Sum(23) res[24] = fma52hi(res[24], a[4], a[19]); // Sum(23) res[20] = fma52lo(res[20], a[0], a[20]); // Sum(20) res[21] = fma52hi(res[21], a[0], a[20]); // Sum(20) res[21] = fma52lo(res[21], a[1], a[20]); // Sum(21) res[22] = fma52hi(res[22], a[1], a[20]); // Sum(21) res[22] = fma52lo(res[22], a[2], a[20]); // Sum(22) res[23] = fma52hi(res[23], a[2], a[20]); // Sum(22) res[23] = fma52lo(res[23], a[3], a[20]); // Sum(23) res[24] = fma52hi(res[24], a[3], a[20]); // Sum(23) res[21] = fma52lo(res[21], a[0], a[21]); // Sum(21) res[22] = fma52hi(res[22], a[0], a[21]); // Sum(21) res[22] = fma52lo(res[22], a[1], a[21]); // Sum(22) res[23] = fma52hi(res[23], a[1], a[21]); // Sum(22) res[23] = fma52lo(res[23], a[2], a[21]); // Sum(23) res[24] = fma52hi(res[24], a[2], a[21]); // Sum(23) res[22] = fma52lo(res[22], a[0], a[22]); // Sum(22) res[23] = fma52hi(res[23], a[0], a[22]); // Sum(22) res[23] = fma52lo(res[23], a[1], a[22]); // Sum(23) res[24] = fma52hi(res[24], a[1], a[22]); // Sum(23) res[23] = fma52lo(res[23], a[0], a[23]); // Sum(23) res[24] = fma52hi(res[24], a[0], a[23]); // Sum(23) res[12] = add64(res[12], res[12]); // Double(12) res[13] = add64(res[13], res[13]); // Double(13) res[14] = add64(res[14], res[14]); // Double(14) res[15] = add64(res[15], res[15]); // Double(15) res[16] = add64(res[16], res[16]); // Double(16) res[17] = add64(res[17], res[17]); // Double(17) res[18] = add64(res[18], res[18]); // Double(18) res[19] = add64(res[19], res[19]); // Double(19) res[20] = add64(res[20], res[20]); // Double(20) res[21] = add64(res[21], res[21]); // Double(21) res[22] = add64(res[22], res[22]); // Double(22) res[23] = add64(res[23], res[23]); // Double(23) res[12] = fma52lo(res[12], a[6], a[6]); // Add sqr(12) res[13] = fma52hi(res[13], a[6], a[6]); // Add sqr(12) res[14] = fma52lo(res[14], a[7], a[7]); // Add sqr(14) res[15] = fma52hi(res[15], a[7], a[7]); // Add sqr(14) res[16] = fma52lo(res[16], a[8], a[8]); // Add sqr(16) res[17] = fma52hi(res[17], a[8], a[8]); // Add sqr(16) res[18] = fma52lo(res[18], a[9], a[9]); // Add sqr(18) res[19] = fma52hi(res[19], a[9], a[9]); // Add sqr(18) res[20] = fma52lo(res[20], a[10], a[10]); // Add sqr(20) res[21] = fma52hi(res[21], a[10], a[10]); // Add sqr(20) res[22] = fma52lo(res[22], a[11], a[11]); // Add sqr(22) res[23] = fma52hi(res[23], a[11], a[11]); // Add sqr(22) res[24] = fma52lo(res[24], a[11], a[13]); // Sum(24) res[25] = fma52hi(res[25], a[11], a[13]); // Sum(24) res[25] = fma52lo(res[25], a[12], a[13]); // Sum(25) res[26] = fma52hi(res[26], a[12], a[13]); // Sum(25) res[24] = fma52lo(res[24], a[10], a[14]); // Sum(24) res[25] = fma52hi(res[25], a[10], a[14]); // Sum(24) res[25] = fma52lo(res[25], a[11], a[14]); // Sum(25) res[26] = fma52hi(res[26], a[11], a[14]); // Sum(25) res[26] = fma52lo(res[26], a[12], a[14]); // Sum(26) res[27] = fma52hi(res[27], a[12], a[14]); // Sum(26) res[27] = fma52lo(res[27], a[13], a[14]); // Sum(27) res[28] = fma52hi(res[28], a[13], a[14]); // Sum(27) res[24] = fma52lo(res[24], a[9], a[15]); // Sum(24) res[25] = fma52hi(res[25], a[9], a[15]); // Sum(24) res[25] = fma52lo(res[25], a[10], a[15]); // Sum(25) res[26] = fma52hi(res[26], a[10], a[15]); // Sum(25) res[26] = fma52lo(res[26], a[11], a[15]); // Sum(26) res[27] = fma52hi(res[27], a[11], a[15]); // Sum(26) res[27] = fma52lo(res[27], a[12], a[15]); // Sum(27) res[28] = fma52hi(res[28], a[12], a[15]); // Sum(27) res[28] = fma52lo(res[28], a[13], a[15]); // Sum(28) res[29] = fma52hi(res[29], a[13], a[15]); // Sum(28) res[29] = fma52lo(res[29], a[14], a[15]); // Sum(29) res[30] = fma52hi(res[30], a[14], a[15]); // Sum(29) res[24] = fma52lo(res[24], a[8], a[16]); // Sum(24) res[25] = fma52hi(res[25], a[8], a[16]); // Sum(24) res[25] = fma52lo(res[25], a[9], a[16]); // Sum(25) res[26] = fma52hi(res[26], a[9], a[16]); // Sum(25) res[26] = fma52lo(res[26], a[10], a[16]); // Sum(26) res[27] = fma52hi(res[27], a[10], a[16]); // Sum(26) res[27] = fma52lo(res[27], a[11], a[16]); // Sum(27) res[28] = fma52hi(res[28], a[11], a[16]); // Sum(27) res[28] = fma52lo(res[28], a[12], a[16]); // Sum(28) res[29] = fma52hi(res[29], a[12], a[16]); // Sum(28) res[29] = fma52lo(res[29], a[13], a[16]); // Sum(29) res[30] = fma52hi(res[30], a[13], a[16]); // Sum(29) res[30] = fma52lo(res[30], a[14], a[16]); // Sum(30) res[31] = fma52hi(res[31], a[14], a[16]); // Sum(30) res[31] = fma52lo(res[31], a[15], a[16]); // Sum(31) res[32] = fma52hi(res[32], a[15], a[16]); // Sum(31) res[24] = fma52lo(res[24], a[7], a[17]); // Sum(24) res[25] = fma52hi(res[25], a[7], a[17]); // Sum(24) res[25] = fma52lo(res[25], a[8], a[17]); // Sum(25) res[26] = fma52hi(res[26], a[8], a[17]); // Sum(25) res[26] = fma52lo(res[26], a[9], a[17]); // Sum(26) res[27] = fma52hi(res[27], a[9], a[17]); // Sum(26) res[27] = fma52lo(res[27], a[10], a[17]); // Sum(27) res[28] = fma52hi(res[28], a[10], a[17]); // Sum(27) res[28] = fma52lo(res[28], a[11], a[17]); // Sum(28) res[29] = fma52hi(res[29], a[11], a[17]); // Sum(28) res[29] = fma52lo(res[29], a[12], a[17]); // Sum(29) res[30] = fma52hi(res[30], a[12], a[17]); // Sum(29) res[30] = fma52lo(res[30], a[13], a[17]); // Sum(30) res[31] = fma52hi(res[31], a[13], a[17]); // Sum(30) res[31] = fma52lo(res[31], a[14], a[17]); // Sum(31) res[32] = fma52hi(res[32], a[14], a[17]); // Sum(31) res[32] = fma52lo(res[32], a[15], a[17]); // Sum(32) res[33] = fma52hi(res[33], a[15], a[17]); // Sum(32) res[33] = fma52lo(res[33], a[16], a[17]); // Sum(33) res[34] = fma52hi(res[34], a[16], a[17]); // Sum(33) res[24] = fma52lo(res[24], a[6], a[18]); // Sum(24) res[25] = fma52hi(res[25], a[6], a[18]); // Sum(24) res[25] = fma52lo(res[25], a[7], a[18]); // Sum(25) res[26] = fma52hi(res[26], a[7], a[18]); // Sum(25) res[26] = fma52lo(res[26], a[8], a[18]); // Sum(26) res[27] = fma52hi(res[27], a[8], a[18]); // Sum(26) res[27] = fma52lo(res[27], a[9], a[18]); // Sum(27) res[28] = fma52hi(res[28], a[9], a[18]); // Sum(27) res[28] = fma52lo(res[28], a[10], a[18]); // Sum(28) res[29] = fma52hi(res[29], a[10], a[18]); // Sum(28) res[29] = fma52lo(res[29], a[11], a[18]); // Sum(29) res[30] = fma52hi(res[30], a[11], a[18]); // Sum(29) res[30] = fma52lo(res[30], a[12], a[18]); // Sum(30) res[31] = fma52hi(res[31], a[12], a[18]); // Sum(30) res[31] = fma52lo(res[31], a[13], a[18]); // Sum(31) res[32] = fma52hi(res[32], a[13], a[18]); // Sum(31) res[32] = fma52lo(res[32], a[14], a[18]); // Sum(32) res[33] = fma52hi(res[33], a[14], a[18]); // Sum(32) res[33] = fma52lo(res[33], a[15], a[18]); // Sum(33) res[34] = fma52hi(res[34], a[15], a[18]); // Sum(33) res[34] = fma52lo(res[34], a[16], a[18]); // Sum(34) res[35] = fma52hi(res[35], a[16], a[18]); // Sum(34) res[35] = fma52lo(res[35], a[17], a[18]); // Sum(35) res[36] = fma52hi(res[36], a[17], a[18]); // Sum(35) res[24] = fma52lo(res[24], a[5], a[19]); // Sum(24) res[25] = fma52hi(res[25], a[5], a[19]); // Sum(24) res[25] = fma52lo(res[25], a[6], a[19]); // Sum(25) res[26] = fma52hi(res[26], a[6], a[19]); // Sum(25) res[26] = fma52lo(res[26], a[7], a[19]); // Sum(26) res[27] = fma52hi(res[27], a[7], a[19]); // Sum(26) res[27] = fma52lo(res[27], a[8], a[19]); // Sum(27) res[28] = fma52hi(res[28], a[8], a[19]); // Sum(27) res[28] = fma52lo(res[28], a[9], a[19]); // Sum(28) res[29] = fma52hi(res[29], a[9], a[19]); // Sum(28) res[29] = fma52lo(res[29], a[10], a[19]); // Sum(29) res[30] = fma52hi(res[30], a[10], a[19]); // Sum(29) res[30] = fma52lo(res[30], a[11], a[19]); // Sum(30) res[31] = fma52hi(res[31], a[11], a[19]); // Sum(30) res[31] = fma52lo(res[31], a[12], a[19]); // Sum(31) res[32] = fma52hi(res[32], a[12], a[19]); // Sum(31) res[32] = fma52lo(res[32], a[13], a[19]); // Sum(32) res[33] = fma52hi(res[33], a[13], a[19]); // Sum(32) res[33] = fma52lo(res[33], a[14], a[19]); // Sum(33) res[34] = fma52hi(res[34], a[14], a[19]); // Sum(33) res[34] = fma52lo(res[34], a[15], a[19]); // Sum(34) res[35] = fma52hi(res[35], a[15], a[19]); // Sum(34) res[35] = fma52lo(res[35], a[16], a[19]); // Sum(35) res[36] = fma52hi(res[36], a[16], a[19]); // Sum(35) res[24] = fma52lo(res[24], a[4], a[20]); // Sum(24) res[25] = fma52hi(res[25], a[4], a[20]); // Sum(24) res[25] = fma52lo(res[25], a[5], a[20]); // Sum(25) res[26] = fma52hi(res[26], a[5], a[20]); // Sum(25) res[26] = fma52lo(res[26], a[6], a[20]); // Sum(26) res[27] = fma52hi(res[27], a[6], a[20]); // Sum(26) res[27] = fma52lo(res[27], a[7], a[20]); // Sum(27) res[28] = fma52hi(res[28], a[7], a[20]); // Sum(27) res[28] = fma52lo(res[28], a[8], a[20]); // Sum(28) res[29] = fma52hi(res[29], a[8], a[20]); // Sum(28) res[29] = fma52lo(res[29], a[9], a[20]); // Sum(29) res[30] = fma52hi(res[30], a[9], a[20]); // Sum(29) res[30] = fma52lo(res[30], a[10], a[20]); // Sum(30) res[31] = fma52hi(res[31], a[10], a[20]); // Sum(30) res[31] = fma52lo(res[31], a[11], a[20]); // Sum(31) res[32] = fma52hi(res[32], a[11], a[20]); // Sum(31) res[32] = fma52lo(res[32], a[12], a[20]); // Sum(32) res[33] = fma52hi(res[33], a[12], a[20]); // Sum(32) res[33] = fma52lo(res[33], a[13], a[20]); // Sum(33) res[34] = fma52hi(res[34], a[13], a[20]); // Sum(33) res[34] = fma52lo(res[34], a[14], a[20]); // Sum(34) res[35] = fma52hi(res[35], a[14], a[20]); // Sum(34) res[35] = fma52lo(res[35], a[15], a[20]); // Sum(35) res[36] = fma52hi(res[36], a[15], a[20]); // Sum(35) res[24] = fma52lo(res[24], a[3], a[21]); // Sum(24) res[25] = fma52hi(res[25], a[3], a[21]); // Sum(24) res[25] = fma52lo(res[25], a[4], a[21]); // Sum(25) res[26] = fma52hi(res[26], a[4], a[21]); // Sum(25) res[26] = fma52lo(res[26], a[5], a[21]); // Sum(26) res[27] = fma52hi(res[27], a[5], a[21]); // Sum(26) res[27] = fma52lo(res[27], a[6], a[21]); // Sum(27) res[28] = fma52hi(res[28], a[6], a[21]); // Sum(27) res[28] = fma52lo(res[28], a[7], a[21]); // Sum(28) res[29] = fma52hi(res[29], a[7], a[21]); // Sum(28) res[29] = fma52lo(res[29], a[8], a[21]); // Sum(29) res[30] = fma52hi(res[30], a[8], a[21]); // Sum(29) res[30] = fma52lo(res[30], a[9], a[21]); // Sum(30) res[31] = fma52hi(res[31], a[9], a[21]); // Sum(30) res[31] = fma52lo(res[31], a[10], a[21]); // Sum(31) res[32] = fma52hi(res[32], a[10], a[21]); // Sum(31) res[32] = fma52lo(res[32], a[11], a[21]); // Sum(32) res[33] = fma52hi(res[33], a[11], a[21]); // Sum(32) res[33] = fma52lo(res[33], a[12], a[21]); // Sum(33) res[34] = fma52hi(res[34], a[12], a[21]); // Sum(33) res[34] = fma52lo(res[34], a[13], a[21]); // Sum(34) res[35] = fma52hi(res[35], a[13], a[21]); // Sum(34) res[35] = fma52lo(res[35], a[14], a[21]); // Sum(35) res[36] = fma52hi(res[36], a[14], a[21]); // Sum(35) res[24] = fma52lo(res[24], a[2], a[22]); // Sum(24) res[25] = fma52hi(res[25], a[2], a[22]); // Sum(24) res[25] = fma52lo(res[25], a[3], a[22]); // Sum(25) res[26] = fma52hi(res[26], a[3], a[22]); // Sum(25) res[26] = fma52lo(res[26], a[4], a[22]); // Sum(26) res[27] = fma52hi(res[27], a[4], a[22]); // Sum(26) res[27] = fma52lo(res[27], a[5], a[22]); // Sum(27) res[28] = fma52hi(res[28], a[5], a[22]); // Sum(27) res[28] = fma52lo(res[28], a[6], a[22]); // Sum(28) res[29] = fma52hi(res[29], a[6], a[22]); // Sum(28) res[29] = fma52lo(res[29], a[7], a[22]); // Sum(29) res[30] = fma52hi(res[30], a[7], a[22]); // Sum(29) res[30] = fma52lo(res[30], a[8], a[22]); // Sum(30) res[31] = fma52hi(res[31], a[8], a[22]); // Sum(30) res[31] = fma52lo(res[31], a[9], a[22]); // Sum(31) res[32] = fma52hi(res[32], a[9], a[22]); // Sum(31) res[32] = fma52lo(res[32], a[10], a[22]); // Sum(32) res[33] = fma52hi(res[33], a[10], a[22]); // Sum(32) res[33] = fma52lo(res[33], a[11], a[22]); // Sum(33) res[34] = fma52hi(res[34], a[11], a[22]); // Sum(33) res[34] = fma52lo(res[34], a[12], a[22]); // Sum(34) res[35] = fma52hi(res[35], a[12], a[22]); // Sum(34) res[35] = fma52lo(res[35], a[13], a[22]); // Sum(35) res[36] = fma52hi(res[36], a[13], a[22]); // Sum(35) res[24] = fma52lo(res[24], a[1], a[23]); // Sum(24) res[25] = fma52hi(res[25], a[1], a[23]); // Sum(24) res[25] = fma52lo(res[25], a[2], a[23]); // Sum(25) res[26] = fma52hi(res[26], a[2], a[23]); // Sum(25) res[26] = fma52lo(res[26], a[3], a[23]); // Sum(26) res[27] = fma52hi(res[27], a[3], a[23]); // Sum(26) res[27] = fma52lo(res[27], a[4], a[23]); // Sum(27) res[28] = fma52hi(res[28], a[4], a[23]); // Sum(27) res[28] = fma52lo(res[28], a[5], a[23]); // Sum(28) res[29] = fma52hi(res[29], a[5], a[23]); // Sum(28) res[29] = fma52lo(res[29], a[6], a[23]); // Sum(29) res[30] = fma52hi(res[30], a[6], a[23]); // Sum(29) res[30] = fma52lo(res[30], a[7], a[23]); // Sum(30) res[31] = fma52hi(res[31], a[7], a[23]); // Sum(30) res[31] = fma52lo(res[31], a[8], a[23]); // Sum(31) res[32] = fma52hi(res[32], a[8], a[23]); // Sum(31) res[32] = fma52lo(res[32], a[9], a[23]); // Sum(32) res[33] = fma52hi(res[33], a[9], a[23]); // Sum(32) res[33] = fma52lo(res[33], a[10], a[23]); // Sum(33) res[34] = fma52hi(res[34], a[10], a[23]); // Sum(33) res[34] = fma52lo(res[34], a[11], a[23]); // Sum(34) res[35] = fma52hi(res[35], a[11], a[23]); // Sum(34) res[35] = fma52lo(res[35], a[12], a[23]); // Sum(35) res[36] = fma52hi(res[36], a[12], a[23]); // Sum(35) res[24] = fma52lo(res[24], a[0], a[24]); // Sum(24) res[25] = fma52hi(res[25], a[0], a[24]); // Sum(24) res[25] = fma52lo(res[25], a[1], a[24]); // Sum(25) res[26] = fma52hi(res[26], a[1], a[24]); // Sum(25) res[26] = fma52lo(res[26], a[2], a[24]); // Sum(26) res[27] = fma52hi(res[27], a[2], a[24]); // Sum(26) res[27] = fma52lo(res[27], a[3], a[24]); // Sum(27) res[28] = fma52hi(res[28], a[3], a[24]); // Sum(27) res[28] = fma52lo(res[28], a[4], a[24]); // Sum(28) res[29] = fma52hi(res[29], a[4], a[24]); // Sum(28) res[29] = fma52lo(res[29], a[5], a[24]); // Sum(29) res[30] = fma52hi(res[30], a[5], a[24]); // Sum(29) res[30] = fma52lo(res[30], a[6], a[24]); // Sum(30) res[31] = fma52hi(res[31], a[6], a[24]); // Sum(30) res[31] = fma52lo(res[31], a[7], a[24]); // Sum(31) res[32] = fma52hi(res[32], a[7], a[24]); // Sum(31) res[32] = fma52lo(res[32], a[8], a[24]); // Sum(32) res[33] = fma52hi(res[33], a[8], a[24]); // Sum(32) res[33] = fma52lo(res[33], a[9], a[24]); // Sum(33) res[34] = fma52hi(res[34], a[9], a[24]); // Sum(33) res[34] = fma52lo(res[34], a[10], a[24]); // Sum(34) res[35] = fma52hi(res[35], a[10], a[24]); // Sum(34) res[35] = fma52lo(res[35], a[11], a[24]); // Sum(35) res[36] = fma52hi(res[36], a[11], a[24]); // Sum(35) res[25] = fma52lo(res[25], a[0], a[25]); // Sum(25) res[26] = fma52hi(res[26], a[0], a[25]); // Sum(25) res[26] = fma52lo(res[26], a[1], a[25]); // Sum(26) res[27] = fma52hi(res[27], a[1], a[25]); // Sum(26) res[27] = fma52lo(res[27], a[2], a[25]); // Sum(27) res[28] = fma52hi(res[28], a[2], a[25]); // Sum(27) res[28] = fma52lo(res[28], a[3], a[25]); // Sum(28) res[29] = fma52hi(res[29], a[3], a[25]); // Sum(28) res[29] = fma52lo(res[29], a[4], a[25]); // Sum(29) res[30] = fma52hi(res[30], a[4], a[25]); // Sum(29) res[30] = fma52lo(res[30], a[5], a[25]); // Sum(30) res[31] = fma52hi(res[31], a[5], a[25]); // Sum(30) res[31] = fma52lo(res[31], a[6], a[25]); // Sum(31) res[32] = fma52hi(res[32], a[6], a[25]); // Sum(31) res[32] = fma52lo(res[32], a[7], a[25]); // Sum(32) res[33] = fma52hi(res[33], a[7], a[25]); // Sum(32) res[33] = fma52lo(res[33], a[8], a[25]); // Sum(33) res[34] = fma52hi(res[34], a[8], a[25]); // Sum(33) res[34] = fma52lo(res[34], a[9], a[25]); // Sum(34) res[35] = fma52hi(res[35], a[9], a[25]); // Sum(34) res[35] = fma52lo(res[35], a[10], a[25]); // Sum(35) res[36] = fma52hi(res[36], a[10], a[25]); // Sum(35) res[26] = fma52lo(res[26], a[0], a[26]); // Sum(26) res[27] = fma52hi(res[27], a[0], a[26]); // Sum(26) res[27] = fma52lo(res[27], a[1], a[26]); // Sum(27) res[28] = fma52hi(res[28], a[1], a[26]); // Sum(27) res[28] = fma52lo(res[28], a[2], a[26]); // Sum(28) res[29] = fma52hi(res[29], a[2], a[26]); // Sum(28) res[29] = fma52lo(res[29], a[3], a[26]); // Sum(29) res[30] = fma52hi(res[30], a[3], a[26]); // Sum(29) res[30] = fma52lo(res[30], a[4], a[26]); // Sum(30) res[31] = fma52hi(res[31], a[4], a[26]); // Sum(30) res[31] = fma52lo(res[31], a[5], a[26]); // Sum(31) res[32] = fma52hi(res[32], a[5], a[26]); // Sum(31) res[32] = fma52lo(res[32], a[6], a[26]); // Sum(32) res[33] = fma52hi(res[33], a[6], a[26]); // Sum(32) res[33] = fma52lo(res[33], a[7], a[26]); // Sum(33) res[34] = fma52hi(res[34], a[7], a[26]); // Sum(33) res[34] = fma52lo(res[34], a[8], a[26]); // Sum(34) res[35] = fma52hi(res[35], a[8], a[26]); // Sum(34) res[35] = fma52lo(res[35], a[9], a[26]); // Sum(35) res[36] = fma52hi(res[36], a[9], a[26]); // Sum(35) res[27] = fma52lo(res[27], a[0], a[27]); // Sum(27) res[28] = fma52hi(res[28], a[0], a[27]); // Sum(27) res[28] = fma52lo(res[28], a[1], a[27]); // Sum(28) res[29] = fma52hi(res[29], a[1], a[27]); // Sum(28) res[29] = fma52lo(res[29], a[2], a[27]); // Sum(29) res[30] = fma52hi(res[30], a[2], a[27]); // Sum(29) res[30] = fma52lo(res[30], a[3], a[27]); // Sum(30) res[31] = fma52hi(res[31], a[3], a[27]); // Sum(30) res[31] = fma52lo(res[31], a[4], a[27]); // Sum(31) res[32] = fma52hi(res[32], a[4], a[27]); // Sum(31) res[32] = fma52lo(res[32], a[5], a[27]); // Sum(32) res[33] = fma52hi(res[33], a[5], a[27]); // Sum(32) res[33] = fma52lo(res[33], a[6], a[27]); // Sum(33) res[34] = fma52hi(res[34], a[6], a[27]); // Sum(33) res[34] = fma52lo(res[34], a[7], a[27]); // Sum(34) res[35] = fma52hi(res[35], a[7], a[27]); // Sum(34) res[35] = fma52lo(res[35], a[8], a[27]); // Sum(35) res[36] = fma52hi(res[36], a[8], a[27]); // Sum(35) res[28] = fma52lo(res[28], a[0], a[28]); // Sum(28) res[29] = fma52hi(res[29], a[0], a[28]); // Sum(28) res[29] = fma52lo(res[29], a[1], a[28]); // Sum(29) res[30] = fma52hi(res[30], a[1], a[28]); // Sum(29) res[30] = fma52lo(res[30], a[2], a[28]); // Sum(30) res[31] = fma52hi(res[31], a[2], a[28]); // Sum(30) res[31] = fma52lo(res[31], a[3], a[28]); // Sum(31) res[32] = fma52hi(res[32], a[3], a[28]); // Sum(31) res[32] = fma52lo(res[32], a[4], a[28]); // Sum(32) res[33] = fma52hi(res[33], a[4], a[28]); // Sum(32) res[33] = fma52lo(res[33], a[5], a[28]); // Sum(33) res[34] = fma52hi(res[34], a[5], a[28]); // Sum(33) res[34] = fma52lo(res[34], a[6], a[28]); // Sum(34) res[35] = fma52hi(res[35], a[6], a[28]); // Sum(34) res[35] = fma52lo(res[35], a[7], a[28]); // Sum(35) res[36] = fma52hi(res[36], a[7], a[28]); // Sum(35) res[29] = fma52lo(res[29], a[0], a[29]); // Sum(29) res[30] = fma52hi(res[30], a[0], a[29]); // Sum(29) res[30] = fma52lo(res[30], a[1], a[29]); // Sum(30) res[31] = fma52hi(res[31], a[1], a[29]); // Sum(30) res[31] = fma52lo(res[31], a[2], a[29]); // Sum(31) res[32] = fma52hi(res[32], a[2], a[29]); // Sum(31) res[32] = fma52lo(res[32], a[3], a[29]); // Sum(32) res[33] = fma52hi(res[33], a[3], a[29]); // Sum(32) res[33] = fma52lo(res[33], a[4], a[29]); // Sum(33) res[34] = fma52hi(res[34], a[4], a[29]); // Sum(33) res[34] = fma52lo(res[34], a[5], a[29]); // Sum(34) res[35] = fma52hi(res[35], a[5], a[29]); // Sum(34) res[35] = fma52lo(res[35], a[6], a[29]); // Sum(35) res[36] = fma52hi(res[36], a[6], a[29]); // Sum(35) res[30] = fma52lo(res[30], a[0], a[30]); // Sum(30) res[31] = fma52hi(res[31], a[0], a[30]); // Sum(30) res[31] = fma52lo(res[31], a[1], a[30]); // Sum(31) res[32] = fma52hi(res[32], a[1], a[30]); // Sum(31) res[32] = fma52lo(res[32], a[2], a[30]); // Sum(32) res[33] = fma52hi(res[33], a[2], a[30]); // Sum(32) res[33] = fma52lo(res[33], a[3], a[30]); // Sum(33) res[34] = fma52hi(res[34], a[3], a[30]); // Sum(33) res[34] = fma52lo(res[34], a[4], a[30]); // Sum(34) res[35] = fma52hi(res[35], a[4], a[30]); // Sum(34) res[35] = fma52lo(res[35], a[5], a[30]); // Sum(35) res[36] = fma52hi(res[36], a[5], a[30]); // Sum(35) res[31] = fma52lo(res[31], a[0], a[31]); // Sum(31) res[32] = fma52hi(res[32], a[0], a[31]); // Sum(31) res[32] = fma52lo(res[32], a[1], a[31]); // Sum(32) res[33] = fma52hi(res[33], a[1], a[31]); // Sum(32) res[33] = fma52lo(res[33], a[2], a[31]); // Sum(33) res[34] = fma52hi(res[34], a[2], a[31]); // Sum(33) res[34] = fma52lo(res[34], a[3], a[31]); // Sum(34) res[35] = fma52hi(res[35], a[3], a[31]); // Sum(34) res[35] = fma52lo(res[35], a[4], a[31]); // Sum(35) res[36] = fma52hi(res[36], a[4], a[31]); // Sum(35) res[32] = fma52lo(res[32], a[0], a[32]); // Sum(32) res[33] = fma52hi(res[33], a[0], a[32]); // Sum(32) res[33] = fma52lo(res[33], a[1], a[32]); // Sum(33) res[34] = fma52hi(res[34], a[1], a[32]); // Sum(33) res[34] = fma52lo(res[34], a[2], a[32]); // Sum(34) res[35] = fma52hi(res[35], a[2], a[32]); // Sum(34) res[35] = fma52lo(res[35], a[3], a[32]); // Sum(35) res[36] = fma52hi(res[36], a[3], a[32]); // Sum(35) res[33] = fma52lo(res[33], a[0], a[33]); // Sum(33) res[34] = fma52hi(res[34], a[0], a[33]); // Sum(33) res[34] = fma52lo(res[34], a[1], a[33]); // Sum(34) res[35] = fma52hi(res[35], a[1], a[33]); // Sum(34) res[35] = fma52lo(res[35], a[2], a[33]); // Sum(35) res[36] = fma52hi(res[36], a[2], a[33]); // Sum(35) res[34] = fma52lo(res[34], a[0], a[34]); // Sum(34) res[35] = fma52hi(res[35], a[0], a[34]); // Sum(34) res[35] = fma52lo(res[35], a[1], a[34]); // Sum(35) res[36] = fma52hi(res[36], a[1], a[34]); // Sum(35) res[35] = fma52lo(res[35], a[0], a[35]); // Sum(35) res[36] = fma52hi(res[36], a[0], a[35]); // Sum(35) res[24] = add64(res[24], res[24]); // Double(24) res[25] = add64(res[25], res[25]); // Double(25) res[26] = add64(res[26], res[26]); // Double(26) res[27] = add64(res[27], res[27]); // Double(27) res[28] = add64(res[28], res[28]); // Double(28) res[29] = add64(res[29], res[29]); // Double(29) res[30] = add64(res[30], res[30]); // Double(30) res[31] = add64(res[31], res[31]); // Double(31) res[32] = add64(res[32], res[32]); // Double(32) res[33] = add64(res[33], res[33]); // Double(33) res[34] = add64(res[34], res[34]); // Double(34) res[35] = add64(res[35], res[35]); // Double(35) res[24] = fma52lo(res[24], a[12], a[12]); // Add sqr(24) res[25] = fma52hi(res[25], a[12], a[12]); // Add sqr(24) res[26] = fma52lo(res[26], a[13], a[13]); // Add sqr(26) res[27] = fma52hi(res[27], a[13], a[13]); // Add sqr(26) res[28] = fma52lo(res[28], a[14], a[14]); // Add sqr(28) res[29] = fma52hi(res[29], a[14], a[14]); // Add sqr(28) res[30] = fma52lo(res[30], a[15], a[15]); // Add sqr(30) res[31] = fma52hi(res[31], a[15], a[15]); // Add sqr(30) res[32] = fma52lo(res[32], a[16], a[16]); // Add sqr(32) res[33] = fma52hi(res[33], a[16], a[16]); // Add sqr(32) res[34] = fma52lo(res[34], a[17], a[17]); // Add sqr(34) res[35] = fma52hi(res[35], a[17], a[17]); // Add sqr(34) res[36] = fma52lo(res[36], a[17], a[19]); // Sum(36) res[37] = fma52hi(res[37], a[17], a[19]); // Sum(36) res[37] = fma52lo(res[37], a[18], a[19]); // Sum(37) res[38] = fma52hi(res[38], a[18], a[19]); // Sum(37) res[36] = fma52lo(res[36], a[16], a[20]); // Sum(36) res[37] = fma52hi(res[37], a[16], a[20]); // Sum(36) res[37] = fma52lo(res[37], a[17], a[20]); // Sum(37) res[38] = fma52hi(res[38], a[17], a[20]); // Sum(37) res[38] = fma52lo(res[38], a[18], a[20]); // Sum(38) res[39] = fma52hi(res[39], a[18], a[20]); // Sum(38) res[39] = fma52lo(res[39], a[19], a[20]); // Sum(39) res[40] = fma52hi(res[40], a[19], a[20]); // Sum(39) res[36] = fma52lo(res[36], a[15], a[21]); // Sum(36) res[37] = fma52hi(res[37], a[15], a[21]); // Sum(36) res[37] = fma52lo(res[37], a[16], a[21]); // Sum(37) res[38] = fma52hi(res[38], a[16], a[21]); // Sum(37) res[38] = fma52lo(res[38], a[17], a[21]); // Sum(38) res[39] = fma52hi(res[39], a[17], a[21]); // Sum(38) res[39] = fma52lo(res[39], a[18], a[21]); // Sum(39) res[40] = fma52hi(res[40], a[18], a[21]); // Sum(39) res[40] = fma52lo(res[40], a[19], a[21]); // Sum(40) res[41] = fma52hi(res[41], a[19], a[21]); // Sum(40) res[41] = fma52lo(res[41], a[20], a[21]); // Sum(41) res[42] = fma52hi(res[42], a[20], a[21]); // Sum(41) res[36] = fma52lo(res[36], a[14], a[22]); // Sum(36) res[37] = fma52hi(res[37], a[14], a[22]); // Sum(36) res[37] = fma52lo(res[37], a[15], a[22]); // Sum(37) res[38] = fma52hi(res[38], a[15], a[22]); // Sum(37) res[38] = fma52lo(res[38], a[16], a[22]); // Sum(38) res[39] = fma52hi(res[39], a[16], a[22]); // Sum(38) res[39] = fma52lo(res[39], a[17], a[22]); // Sum(39) res[40] = fma52hi(res[40], a[17], a[22]); // Sum(39) res[40] = fma52lo(res[40], a[18], a[22]); // Sum(40) res[41] = fma52hi(res[41], a[18], a[22]); // Sum(40) res[41] = fma52lo(res[41], a[19], a[22]); // Sum(41) res[42] = fma52hi(res[42], a[19], a[22]); // Sum(41) res[42] = fma52lo(res[42], a[20], a[22]); // Sum(42) res[43] = fma52hi(res[43], a[20], a[22]); // Sum(42) res[43] = fma52lo(res[43], a[21], a[22]); // Sum(43) res[44] = fma52hi(res[44], a[21], a[22]); // Sum(43) res[36] = fma52lo(res[36], a[13], a[23]); // Sum(36) res[37] = fma52hi(res[37], a[13], a[23]); // Sum(36) res[37] = fma52lo(res[37], a[14], a[23]); // Sum(37) res[38] = fma52hi(res[38], a[14], a[23]); // Sum(37) res[38] = fma52lo(res[38], a[15], a[23]); // Sum(38) res[39] = fma52hi(res[39], a[15], a[23]); // Sum(38) res[39] = fma52lo(res[39], a[16], a[23]); // Sum(39) res[40] = fma52hi(res[40], a[16], a[23]); // Sum(39) res[40] = fma52lo(res[40], a[17], a[23]); // Sum(40) res[41] = fma52hi(res[41], a[17], a[23]); // Sum(40) res[41] = fma52lo(res[41], a[18], a[23]); // Sum(41) res[42] = fma52hi(res[42], a[18], a[23]); // Sum(41) res[42] = fma52lo(res[42], a[19], a[23]); // Sum(42) res[43] = fma52hi(res[43], a[19], a[23]); // Sum(42) res[43] = fma52lo(res[43], a[20], a[23]); // Sum(43) res[44] = fma52hi(res[44], a[20], a[23]); // Sum(43) res[44] = fma52lo(res[44], a[21], a[23]); // Sum(44) res[45] = fma52hi(res[45], a[21], a[23]); // Sum(44) res[45] = fma52lo(res[45], a[22], a[23]); // Sum(45) res[46] = fma52hi(res[46], a[22], a[23]); // Sum(45) res[36] = fma52lo(res[36], a[12], a[24]); // Sum(36) res[37] = fma52hi(res[37], a[12], a[24]); // Sum(36) res[37] = fma52lo(res[37], a[13], a[24]); // Sum(37) res[38] = fma52hi(res[38], a[13], a[24]); // Sum(37) res[38] = fma52lo(res[38], a[14], a[24]); // Sum(38) res[39] = fma52hi(res[39], a[14], a[24]); // Sum(38) res[39] = fma52lo(res[39], a[15], a[24]); // Sum(39) res[40] = fma52hi(res[40], a[15], a[24]); // Sum(39) res[40] = fma52lo(res[40], a[16], a[24]); // Sum(40) res[41] = fma52hi(res[41], a[16], a[24]); // Sum(40) res[41] = fma52lo(res[41], a[17], a[24]); // Sum(41) res[42] = fma52hi(res[42], a[17], a[24]); // Sum(41) res[42] = fma52lo(res[42], a[18], a[24]); // Sum(42) res[43] = fma52hi(res[43], a[18], a[24]); // Sum(42) res[43] = fma52lo(res[43], a[19], a[24]); // Sum(43) res[44] = fma52hi(res[44], a[19], a[24]); // Sum(43) res[44] = fma52lo(res[44], a[20], a[24]); // Sum(44) res[45] = fma52hi(res[45], a[20], a[24]); // Sum(44) res[45] = fma52lo(res[45], a[21], a[24]); // Sum(45) res[46] = fma52hi(res[46], a[21], a[24]); // Sum(45) res[46] = fma52lo(res[46], a[22], a[24]); // Sum(46) res[47] = fma52hi(res[47], a[22], a[24]); // Sum(46) res[47] = fma52lo(res[47], a[23], a[24]); // Sum(47) res[48] = fma52hi(res[48], a[23], a[24]); // Sum(47) res[36] = fma52lo(res[36], a[11], a[25]); // Sum(36) res[37] = fma52hi(res[37], a[11], a[25]); // Sum(36) res[37] = fma52lo(res[37], a[12], a[25]); // Sum(37) res[38] = fma52hi(res[38], a[12], a[25]); // Sum(37) res[38] = fma52lo(res[38], a[13], a[25]); // Sum(38) res[39] = fma52hi(res[39], a[13], a[25]); // Sum(38) res[39] = fma52lo(res[39], a[14], a[25]); // Sum(39) res[40] = fma52hi(res[40], a[14], a[25]); // Sum(39) res[40] = fma52lo(res[40], a[15], a[25]); // Sum(40) res[41] = fma52hi(res[41], a[15], a[25]); // Sum(40) res[41] = fma52lo(res[41], a[16], a[25]); // Sum(41) res[42] = fma52hi(res[42], a[16], a[25]); // Sum(41) res[42] = fma52lo(res[42], a[17], a[25]); // Sum(42) res[43] = fma52hi(res[43], a[17], a[25]); // Sum(42) res[43] = fma52lo(res[43], a[18], a[25]); // Sum(43) res[44] = fma52hi(res[44], a[18], a[25]); // Sum(43) res[44] = fma52lo(res[44], a[19], a[25]); // Sum(44) res[45] = fma52hi(res[45], a[19], a[25]); // Sum(44) res[45] = fma52lo(res[45], a[20], a[25]); // Sum(45) res[46] = fma52hi(res[46], a[20], a[25]); // Sum(45) res[46] = fma52lo(res[46], a[21], a[25]); // Sum(46) res[47] = fma52hi(res[47], a[21], a[25]); // Sum(46) res[47] = fma52lo(res[47], a[22], a[25]); // Sum(47) res[48] = fma52hi(res[48], a[22], a[25]); // Sum(47) res[36] = fma52lo(res[36], a[10], a[26]); // Sum(36) res[37] = fma52hi(res[37], a[10], a[26]); // Sum(36) res[37] = fma52lo(res[37], a[11], a[26]); // Sum(37) res[38] = fma52hi(res[38], a[11], a[26]); // Sum(37) res[38] = fma52lo(res[38], a[12], a[26]); // Sum(38) res[39] = fma52hi(res[39], a[12], a[26]); // Sum(38) res[39] = fma52lo(res[39], a[13], a[26]); // Sum(39) res[40] = fma52hi(res[40], a[13], a[26]); // Sum(39) res[40] = fma52lo(res[40], a[14], a[26]); // Sum(40) res[41] = fma52hi(res[41], a[14], a[26]); // Sum(40) res[41] = fma52lo(res[41], a[15], a[26]); // Sum(41) res[42] = fma52hi(res[42], a[15], a[26]); // Sum(41) res[42] = fma52lo(res[42], a[16], a[26]); // Sum(42) res[43] = fma52hi(res[43], a[16], a[26]); // Sum(42) res[43] = fma52lo(res[43], a[17], a[26]); // Sum(43) res[44] = fma52hi(res[44], a[17], a[26]); // Sum(43) res[44] = fma52lo(res[44], a[18], a[26]); // Sum(44) res[45] = fma52hi(res[45], a[18], a[26]); // Sum(44) res[45] = fma52lo(res[45], a[19], a[26]); // Sum(45) res[46] = fma52hi(res[46], a[19], a[26]); // Sum(45) res[46] = fma52lo(res[46], a[20], a[26]); // Sum(46) res[47] = fma52hi(res[47], a[20], a[26]); // Sum(46) res[47] = fma52lo(res[47], a[21], a[26]); // Sum(47) res[48] = fma52hi(res[48], a[21], a[26]); // Sum(47) res[36] = fma52lo(res[36], a[9], a[27]); // Sum(36) res[37] = fma52hi(res[37], a[9], a[27]); // Sum(36) res[37] = fma52lo(res[37], a[10], a[27]); // Sum(37) res[38] = fma52hi(res[38], a[10], a[27]); // Sum(37) res[38] = fma52lo(res[38], a[11], a[27]); // Sum(38) res[39] = fma52hi(res[39], a[11], a[27]); // Sum(38) res[39] = fma52lo(res[39], a[12], a[27]); // Sum(39) res[40] = fma52hi(res[40], a[12], a[27]); // Sum(39) res[40] = fma52lo(res[40], a[13], a[27]); // Sum(40) res[41] = fma52hi(res[41], a[13], a[27]); // Sum(40) res[41] = fma52lo(res[41], a[14], a[27]); // Sum(41) res[42] = fma52hi(res[42], a[14], a[27]); // Sum(41) res[42] = fma52lo(res[42], a[15], a[27]); // Sum(42) res[43] = fma52hi(res[43], a[15], a[27]); // Sum(42) res[43] = fma52lo(res[43], a[16], a[27]); // Sum(43) res[44] = fma52hi(res[44], a[16], a[27]); // Sum(43) res[44] = fma52lo(res[44], a[17], a[27]); // Sum(44) res[45] = fma52hi(res[45], a[17], a[27]); // Sum(44) res[45] = fma52lo(res[45], a[18], a[27]); // Sum(45) res[46] = fma52hi(res[46], a[18], a[27]); // Sum(45) res[46] = fma52lo(res[46], a[19], a[27]); // Sum(46) res[47] = fma52hi(res[47], a[19], a[27]); // Sum(46) res[47] = fma52lo(res[47], a[20], a[27]); // Sum(47) res[48] = fma52hi(res[48], a[20], a[27]); // Sum(47) res[36] = fma52lo(res[36], a[8], a[28]); // Sum(36) res[37] = fma52hi(res[37], a[8], a[28]); // Sum(36) res[37] = fma52lo(res[37], a[9], a[28]); // Sum(37) res[38] = fma52hi(res[38], a[9], a[28]); // Sum(37) res[38] = fma52lo(res[38], a[10], a[28]); // Sum(38) res[39] = fma52hi(res[39], a[10], a[28]); // Sum(38) res[39] = fma52lo(res[39], a[11], a[28]); // Sum(39) res[40] = fma52hi(res[40], a[11], a[28]); // Sum(39) res[40] = fma52lo(res[40], a[12], a[28]); // Sum(40) res[41] = fma52hi(res[41], a[12], a[28]); // Sum(40) res[41] = fma52lo(res[41], a[13], a[28]); // Sum(41) res[42] = fma52hi(res[42], a[13], a[28]); // Sum(41) res[42] = fma52lo(res[42], a[14], a[28]); // Sum(42) res[43] = fma52hi(res[43], a[14], a[28]); // Sum(42) res[43] = fma52lo(res[43], a[15], a[28]); // Sum(43) res[44] = fma52hi(res[44], a[15], a[28]); // Sum(43) res[44] = fma52lo(res[44], a[16], a[28]); // Sum(44) res[45] = fma52hi(res[45], a[16], a[28]); // Sum(44) res[45] = fma52lo(res[45], a[17], a[28]); // Sum(45) res[46] = fma52hi(res[46], a[17], a[28]); // Sum(45) res[46] = fma52lo(res[46], a[18], a[28]); // Sum(46) res[47] = fma52hi(res[47], a[18], a[28]); // Sum(46) res[47] = fma52lo(res[47], a[19], a[28]); // Sum(47) res[48] = fma52hi(res[48], a[19], a[28]); // Sum(47) res[36] = fma52lo(res[36], a[7], a[29]); // Sum(36) res[37] = fma52hi(res[37], a[7], a[29]); // Sum(36) res[37] = fma52lo(res[37], a[8], a[29]); // Sum(37) res[38] = fma52hi(res[38], a[8], a[29]); // Sum(37) res[38] = fma52lo(res[38], a[9], a[29]); // Sum(38) res[39] = fma52hi(res[39], a[9], a[29]); // Sum(38) res[39] = fma52lo(res[39], a[10], a[29]); // Sum(39) res[40] = fma52hi(res[40], a[10], a[29]); // Sum(39) res[40] = fma52lo(res[40], a[11], a[29]); // Sum(40) res[41] = fma52hi(res[41], a[11], a[29]); // Sum(40) res[41] = fma52lo(res[41], a[12], a[29]); // Sum(41) res[42] = fma52hi(res[42], a[12], a[29]); // Sum(41) res[42] = fma52lo(res[42], a[13], a[29]); // Sum(42) res[43] = fma52hi(res[43], a[13], a[29]); // Sum(42) res[43] = fma52lo(res[43], a[14], a[29]); // Sum(43) res[44] = fma52hi(res[44], a[14], a[29]); // Sum(43) res[44] = fma52lo(res[44], a[15], a[29]); // Sum(44) res[45] = fma52hi(res[45], a[15], a[29]); // Sum(44) res[45] = fma52lo(res[45], a[16], a[29]); // Sum(45) res[46] = fma52hi(res[46], a[16], a[29]); // Sum(45) res[46] = fma52lo(res[46], a[17], a[29]); // Sum(46) res[47] = fma52hi(res[47], a[17], a[29]); // Sum(46) res[47] = fma52lo(res[47], a[18], a[29]); // Sum(47) res[48] = fma52hi(res[48], a[18], a[29]); // Sum(47) res[36] = fma52lo(res[36], a[6], a[30]); // Sum(36) res[37] = fma52hi(res[37], a[6], a[30]); // Sum(36) res[37] = fma52lo(res[37], a[7], a[30]); // Sum(37) res[38] = fma52hi(res[38], a[7], a[30]); // Sum(37) res[38] = fma52lo(res[38], a[8], a[30]); // Sum(38) res[39] = fma52hi(res[39], a[8], a[30]); // Sum(38) res[39] = fma52lo(res[39], a[9], a[30]); // Sum(39) res[40] = fma52hi(res[40], a[9], a[30]); // Sum(39) res[40] = fma52lo(res[40], a[10], a[30]); // Sum(40) res[41] = fma52hi(res[41], a[10], a[30]); // Sum(40) res[41] = fma52lo(res[41], a[11], a[30]); // Sum(41) res[42] = fma52hi(res[42], a[11], a[30]); // Sum(41) res[42] = fma52lo(res[42], a[12], a[30]); // Sum(42) res[43] = fma52hi(res[43], a[12], a[30]); // Sum(42) res[43] = fma52lo(res[43], a[13], a[30]); // Sum(43) res[44] = fma52hi(res[44], a[13], a[30]); // Sum(43) res[44] = fma52lo(res[44], a[14], a[30]); // Sum(44) res[45] = fma52hi(res[45], a[14], a[30]); // Sum(44) res[45] = fma52lo(res[45], a[15], a[30]); // Sum(45) res[46] = fma52hi(res[46], a[15], a[30]); // Sum(45) res[46] = fma52lo(res[46], a[16], a[30]); // Sum(46) res[47] = fma52hi(res[47], a[16], a[30]); // Sum(46) res[47] = fma52lo(res[47], a[17], a[30]); // Sum(47) res[48] = fma52hi(res[48], a[17], a[30]); // Sum(47) res[36] = fma52lo(res[36], a[5], a[31]); // Sum(36) res[37] = fma52hi(res[37], a[5], a[31]); // Sum(36) res[37] = fma52lo(res[37], a[6], a[31]); // Sum(37) res[38] = fma52hi(res[38], a[6], a[31]); // Sum(37) res[38] = fma52lo(res[38], a[7], a[31]); // Sum(38) res[39] = fma52hi(res[39], a[7], a[31]); // Sum(38) res[39] = fma52lo(res[39], a[8], a[31]); // Sum(39) res[40] = fma52hi(res[40], a[8], a[31]); // Sum(39) res[40] = fma52lo(res[40], a[9], a[31]); // Sum(40) res[41] = fma52hi(res[41], a[9], a[31]); // Sum(40) res[41] = fma52lo(res[41], a[10], a[31]); // Sum(41) res[42] = fma52hi(res[42], a[10], a[31]); // Sum(41) res[42] = fma52lo(res[42], a[11], a[31]); // Sum(42) res[43] = fma52hi(res[43], a[11], a[31]); // Sum(42) res[43] = fma52lo(res[43], a[12], a[31]); // Sum(43) res[44] = fma52hi(res[44], a[12], a[31]); // Sum(43) res[44] = fma52lo(res[44], a[13], a[31]); // Sum(44) res[45] = fma52hi(res[45], a[13], a[31]); // Sum(44) res[45] = fma52lo(res[45], a[14], a[31]); // Sum(45) res[46] = fma52hi(res[46], a[14], a[31]); // Sum(45) res[46] = fma52lo(res[46], a[15], a[31]); // Sum(46) res[47] = fma52hi(res[47], a[15], a[31]); // Sum(46) res[47] = fma52lo(res[47], a[16], a[31]); // Sum(47) res[48] = fma52hi(res[48], a[16], a[31]); // Sum(47) res[36] = fma52lo(res[36], a[4], a[32]); // Sum(36) res[37] = fma52hi(res[37], a[4], a[32]); // Sum(36) res[37] = fma52lo(res[37], a[5], a[32]); // Sum(37) res[38] = fma52hi(res[38], a[5], a[32]); // Sum(37) res[38] = fma52lo(res[38], a[6], a[32]); // Sum(38) res[39] = fma52hi(res[39], a[6], a[32]); // Sum(38) res[39] = fma52lo(res[39], a[7], a[32]); // Sum(39) res[40] = fma52hi(res[40], a[7], a[32]); // Sum(39) res[40] = fma52lo(res[40], a[8], a[32]); // Sum(40) res[41] = fma52hi(res[41], a[8], a[32]); // Sum(40) res[41] = fma52lo(res[41], a[9], a[32]); // Sum(41) res[42] = fma52hi(res[42], a[9], a[32]); // Sum(41) res[42] = fma52lo(res[42], a[10], a[32]); // Sum(42) res[43] = fma52hi(res[43], a[10], a[32]); // Sum(42) res[43] = fma52lo(res[43], a[11], a[32]); // Sum(43) res[44] = fma52hi(res[44], a[11], a[32]); // Sum(43) res[44] = fma52lo(res[44], a[12], a[32]); // Sum(44) res[45] = fma52hi(res[45], a[12], a[32]); // Sum(44) res[45] = fma52lo(res[45], a[13], a[32]); // Sum(45) res[46] = fma52hi(res[46], a[13], a[32]); // Sum(45) res[46] = fma52lo(res[46], a[14], a[32]); // Sum(46) res[47] = fma52hi(res[47], a[14], a[32]); // Sum(46) res[47] = fma52lo(res[47], a[15], a[32]); // Sum(47) res[48] = fma52hi(res[48], a[15], a[32]); // Sum(47) res[36] = fma52lo(res[36], a[3], a[33]); // Sum(36) res[37] = fma52hi(res[37], a[3], a[33]); // Sum(36) res[37] = fma52lo(res[37], a[4], a[33]); // Sum(37) res[38] = fma52hi(res[38], a[4], a[33]); // Sum(37) res[38] = fma52lo(res[38], a[5], a[33]); // Sum(38) res[39] = fma52hi(res[39], a[5], a[33]); // Sum(38) res[39] = fma52lo(res[39], a[6], a[33]); // Sum(39) res[40] = fma52hi(res[40], a[6], a[33]); // Sum(39) res[40] = fma52lo(res[40], a[7], a[33]); // Sum(40) res[41] = fma52hi(res[41], a[7], a[33]); // Sum(40) res[41] = fma52lo(res[41], a[8], a[33]); // Sum(41) res[42] = fma52hi(res[42], a[8], a[33]); // Sum(41) res[42] = fma52lo(res[42], a[9], a[33]); // Sum(42) res[43] = fma52hi(res[43], a[9], a[33]); // Sum(42) res[43] = fma52lo(res[43], a[10], a[33]); // Sum(43) res[44] = fma52hi(res[44], a[10], a[33]); // Sum(43) res[44] = fma52lo(res[44], a[11], a[33]); // Sum(44) res[45] = fma52hi(res[45], a[11], a[33]); // Sum(44) res[45] = fma52lo(res[45], a[12], a[33]); // Sum(45) res[46] = fma52hi(res[46], a[12], a[33]); // Sum(45) res[46] = fma52lo(res[46], a[13], a[33]); // Sum(46) res[47] = fma52hi(res[47], a[13], a[33]); // Sum(46) res[47] = fma52lo(res[47], a[14], a[33]); // Sum(47) res[48] = fma52hi(res[48], a[14], a[33]); // Sum(47) res[36] = fma52lo(res[36], a[2], a[34]); // Sum(36) res[37] = fma52hi(res[37], a[2], a[34]); // Sum(36) res[37] = fma52lo(res[37], a[3], a[34]); // Sum(37) res[38] = fma52hi(res[38], a[3], a[34]); // Sum(37) res[38] = fma52lo(res[38], a[4], a[34]); // Sum(38) res[39] = fma52hi(res[39], a[4], a[34]); // Sum(38) res[39] = fma52lo(res[39], a[5], a[34]); // Sum(39) res[40] = fma52hi(res[40], a[5], a[34]); // Sum(39) res[40] = fma52lo(res[40], a[6], a[34]); // Sum(40) res[41] = fma52hi(res[41], a[6], a[34]); // Sum(40) res[41] = fma52lo(res[41], a[7], a[34]); // Sum(41) res[42] = fma52hi(res[42], a[7], a[34]); // Sum(41) res[42] = fma52lo(res[42], a[8], a[34]); // Sum(42) res[43] = fma52hi(res[43], a[8], a[34]); // Sum(42) res[43] = fma52lo(res[43], a[9], a[34]); // Sum(43) res[44] = fma52hi(res[44], a[9], a[34]); // Sum(43) res[44] = fma52lo(res[44], a[10], a[34]); // Sum(44) res[45] = fma52hi(res[45], a[10], a[34]); // Sum(44) res[45] = fma52lo(res[45], a[11], a[34]); // Sum(45) res[46] = fma52hi(res[46], a[11], a[34]); // Sum(45) res[46] = fma52lo(res[46], a[12], a[34]); // Sum(46) res[47] = fma52hi(res[47], a[12], a[34]); // Sum(46) res[47] = fma52lo(res[47], a[13], a[34]); // Sum(47) res[48] = fma52hi(res[48], a[13], a[34]); // Sum(47) res[36] = fma52lo(res[36], a[1], a[35]); // Sum(36) res[37] = fma52hi(res[37], a[1], a[35]); // Sum(36) res[37] = fma52lo(res[37], a[2], a[35]); // Sum(37) res[38] = fma52hi(res[38], a[2], a[35]); // Sum(37) res[38] = fma52lo(res[38], a[3], a[35]); // Sum(38) res[39] = fma52hi(res[39], a[3], a[35]); // Sum(38) res[39] = fma52lo(res[39], a[4], a[35]); // Sum(39) res[40] = fma52hi(res[40], a[4], a[35]); // Sum(39) res[40] = fma52lo(res[40], a[5], a[35]); // Sum(40) res[41] = fma52hi(res[41], a[5], a[35]); // Sum(40) res[41] = fma52lo(res[41], a[6], a[35]); // Sum(41) res[42] = fma52hi(res[42], a[6], a[35]); // Sum(41) res[42] = fma52lo(res[42], a[7], a[35]); // Sum(42) res[43] = fma52hi(res[43], a[7], a[35]); // Sum(42) res[43] = fma52lo(res[43], a[8], a[35]); // Sum(43) res[44] = fma52hi(res[44], a[8], a[35]); // Sum(43) res[44] = fma52lo(res[44], a[9], a[35]); // Sum(44) res[45] = fma52hi(res[45], a[9], a[35]); // Sum(44) res[45] = fma52lo(res[45], a[10], a[35]); // Sum(45) res[46] = fma52hi(res[46], a[10], a[35]); // Sum(45) res[46] = fma52lo(res[46], a[11], a[35]); // Sum(46) res[47] = fma52hi(res[47], a[11], a[35]); // Sum(46) res[47] = fma52lo(res[47], a[12], a[35]); // Sum(47) res[48] = fma52hi(res[48], a[12], a[35]); // Sum(47) res[36] = fma52lo(res[36], a[0], a[36]); // Sum(36) res[37] = fma52hi(res[37], a[0], a[36]); // Sum(36) res[37] = fma52lo(res[37], a[1], a[36]); // Sum(37) res[38] = fma52hi(res[38], a[1], a[36]); // Sum(37) res[38] = fma52lo(res[38], a[2], a[36]); // Sum(38) res[39] = fma52hi(res[39], a[2], a[36]); // Sum(38) res[39] = fma52lo(res[39], a[3], a[36]); // Sum(39) res[40] = fma52hi(res[40], a[3], a[36]); // Sum(39) res[40] = fma52lo(res[40], a[4], a[36]); // Sum(40) res[41] = fma52hi(res[41], a[4], a[36]); // Sum(40) res[41] = fma52lo(res[41], a[5], a[36]); // Sum(41) res[42] = fma52hi(res[42], a[5], a[36]); // Sum(41) res[42] = fma52lo(res[42], a[6], a[36]); // Sum(42) res[43] = fma52hi(res[43], a[6], a[36]); // Sum(42) res[43] = fma52lo(res[43], a[7], a[36]); // Sum(43) res[44] = fma52hi(res[44], a[7], a[36]); // Sum(43) res[44] = fma52lo(res[44], a[8], a[36]); // Sum(44) res[45] = fma52hi(res[45], a[8], a[36]); // Sum(44) res[45] = fma52lo(res[45], a[9], a[36]); // Sum(45) res[46] = fma52hi(res[46], a[9], a[36]); // Sum(45) res[46] = fma52lo(res[46], a[10], a[36]); // Sum(46) res[47] = fma52hi(res[47], a[10], a[36]); // Sum(46) res[47] = fma52lo(res[47], a[11], a[36]); // Sum(47) res[48] = fma52hi(res[48], a[11], a[36]); // Sum(47) res[37] = fma52lo(res[37], a[0], a[37]); // Sum(37) res[38] = fma52hi(res[38], a[0], a[37]); // Sum(37) res[38] = fma52lo(res[38], a[1], a[37]); // Sum(38) res[39] = fma52hi(res[39], a[1], a[37]); // Sum(38) res[39] = fma52lo(res[39], a[2], a[37]); // Sum(39) res[40] = fma52hi(res[40], a[2], a[37]); // Sum(39) res[40] = fma52lo(res[40], a[3], a[37]); // Sum(40) res[41] = fma52hi(res[41], a[3], a[37]); // Sum(40) res[41] = fma52lo(res[41], a[4], a[37]); // Sum(41) res[42] = fma52hi(res[42], a[4], a[37]); // Sum(41) res[42] = fma52lo(res[42], a[5], a[37]); // Sum(42) res[43] = fma52hi(res[43], a[5], a[37]); // Sum(42) res[43] = fma52lo(res[43], a[6], a[37]); // Sum(43) res[44] = fma52hi(res[44], a[6], a[37]); // Sum(43) res[44] = fma52lo(res[44], a[7], a[37]); // Sum(44) res[45] = fma52hi(res[45], a[7], a[37]); // Sum(44) res[45] = fma52lo(res[45], a[8], a[37]); // Sum(45) res[46] = fma52hi(res[46], a[8], a[37]); // Sum(45) res[46] = fma52lo(res[46], a[9], a[37]); // Sum(46) res[47] = fma52hi(res[47], a[9], a[37]); // Sum(46) res[47] = fma52lo(res[47], a[10], a[37]); // Sum(47) res[48] = fma52hi(res[48], a[10], a[37]); // Sum(47) res[38] = fma52lo(res[38], a[0], a[38]); // Sum(38) res[39] = fma52hi(res[39], a[0], a[38]); // Sum(38) res[39] = fma52lo(res[39], a[1], a[38]); // Sum(39) res[40] = fma52hi(res[40], a[1], a[38]); // Sum(39) res[40] = fma52lo(res[40], a[2], a[38]); // Sum(40) res[41] = fma52hi(res[41], a[2], a[38]); // Sum(40) res[41] = fma52lo(res[41], a[3], a[38]); // Sum(41) res[42] = fma52hi(res[42], a[3], a[38]); // Sum(41) res[42] = fma52lo(res[42], a[4], a[38]); // Sum(42) res[43] = fma52hi(res[43], a[4], a[38]); // Sum(42) res[43] = fma52lo(res[43], a[5], a[38]); // Sum(43) res[44] = fma52hi(res[44], a[5], a[38]); // Sum(43) res[44] = fma52lo(res[44], a[6], a[38]); // Sum(44) res[45] = fma52hi(res[45], a[6], a[38]); // Sum(44) res[45] = fma52lo(res[45], a[7], a[38]); // Sum(45) res[46] = fma52hi(res[46], a[7], a[38]); // Sum(45) res[46] = fma52lo(res[46], a[8], a[38]); // Sum(46) res[47] = fma52hi(res[47], a[8], a[38]); // Sum(46) res[47] = fma52lo(res[47], a[9], a[38]); // Sum(47) res[48] = fma52hi(res[48], a[9], a[38]); // Sum(47) res[39] = fma52lo(res[39], a[0], a[39]); // Sum(39) res[40] = fma52hi(res[40], a[0], a[39]); // Sum(39) res[40] = fma52lo(res[40], a[1], a[39]); // Sum(40) res[41] = fma52hi(res[41], a[1], a[39]); // Sum(40) res[41] = fma52lo(res[41], a[2], a[39]); // Sum(41) res[42] = fma52hi(res[42], a[2], a[39]); // Sum(41) res[42] = fma52lo(res[42], a[3], a[39]); // Sum(42) res[43] = fma52hi(res[43], a[3], a[39]); // Sum(42) res[43] = fma52lo(res[43], a[4], a[39]); // Sum(43) res[44] = fma52hi(res[44], a[4], a[39]); // Sum(43) res[44] = fma52lo(res[44], a[5], a[39]); // Sum(44) res[45] = fma52hi(res[45], a[5], a[39]); // Sum(44) res[45] = fma52lo(res[45], a[6], a[39]); // Sum(45) res[46] = fma52hi(res[46], a[6], a[39]); // Sum(45) res[46] = fma52lo(res[46], a[7], a[39]); // Sum(46) res[47] = fma52hi(res[47], a[7], a[39]); // Sum(46) res[47] = fma52lo(res[47], a[8], a[39]); // Sum(47) res[48] = fma52hi(res[48], a[8], a[39]); // Sum(47) res[36] = add64(res[36], res[36]); // Double(36) res[37] = add64(res[37], res[37]); // Double(37) res[38] = add64(res[38], res[38]); // Double(38) res[39] = add64(res[39], res[39]); // Double(39) res[40] = add64(res[40], res[40]); // Double(40) res[41] = add64(res[41], res[41]); // Double(41) res[42] = add64(res[42], res[42]); // Double(42) res[43] = add64(res[43], res[43]); // Double(43) res[44] = add64(res[44], res[44]); // Double(44) res[45] = add64(res[45], res[45]); // Double(45) res[46] = add64(res[46], res[46]); // Double(46) res[47] = add64(res[47], res[47]); // Double(47) res[36] = fma52lo(res[36], a[18], a[18]); // Add sqr(36) res[37] = fma52hi(res[37], a[18], a[18]); // Add sqr(36) res[38] = fma52lo(res[38], a[19], a[19]); // Add sqr(38) res[39] = fma52hi(res[39], a[19], a[19]); // Add sqr(38) res[40] = fma52lo(res[40], a[20], a[20]); // Add sqr(40) res[41] = fma52hi(res[41], a[20], a[20]); // Add sqr(40) res[42] = fma52lo(res[42], a[21], a[21]); // Add sqr(42) res[43] = fma52hi(res[43], a[21], a[21]); // Add sqr(42) res[44] = fma52lo(res[44], a[22], a[22]); // Add sqr(44) res[45] = fma52hi(res[45], a[22], a[22]); // Add sqr(44) res[46] = fma52lo(res[46], a[23], a[23]); // Add sqr(46) res[47] = fma52hi(res[47], a[23], a[23]); // Add sqr(46) res[48] = fma52lo(res[48], a[23], a[25]); // Sum(48) res[49] = fma52hi(res[49], a[23], a[25]); // Sum(48) res[49] = fma52lo(res[49], a[24], a[25]); // Sum(49) res[50] = fma52hi(res[50], a[24], a[25]); // Sum(49) res[48] = fma52lo(res[48], a[22], a[26]); // Sum(48) res[49] = fma52hi(res[49], a[22], a[26]); // Sum(48) res[49] = fma52lo(res[49], a[23], a[26]); // Sum(49) res[50] = fma52hi(res[50], a[23], a[26]); // Sum(49) res[50] = fma52lo(res[50], a[24], a[26]); // Sum(50) res[51] = fma52hi(res[51], a[24], a[26]); // Sum(50) res[51] = fma52lo(res[51], a[25], a[26]); // Sum(51) res[52] = fma52hi(res[52], a[25], a[26]); // Sum(51) res[48] = fma52lo(res[48], a[21], a[27]); // Sum(48) res[49] = fma52hi(res[49], a[21], a[27]); // Sum(48) res[49] = fma52lo(res[49], a[22], a[27]); // Sum(49) res[50] = fma52hi(res[50], a[22], a[27]); // Sum(49) res[50] = fma52lo(res[50], a[23], a[27]); // Sum(50) res[51] = fma52hi(res[51], a[23], a[27]); // Sum(50) res[51] = fma52lo(res[51], a[24], a[27]); // Sum(51) res[52] = fma52hi(res[52], a[24], a[27]); // Sum(51) res[52] = fma52lo(res[52], a[25], a[27]); // Sum(52) res[53] = fma52hi(res[53], a[25], a[27]); // Sum(52) res[53] = fma52lo(res[53], a[26], a[27]); // Sum(53) res[54] = fma52hi(res[54], a[26], a[27]); // Sum(53) res[48] = fma52lo(res[48], a[20], a[28]); // Sum(48) res[49] = fma52hi(res[49], a[20], a[28]); // Sum(48) res[49] = fma52lo(res[49], a[21], a[28]); // Sum(49) res[50] = fma52hi(res[50], a[21], a[28]); // Sum(49) res[50] = fma52lo(res[50], a[22], a[28]); // Sum(50) res[51] = fma52hi(res[51], a[22], a[28]); // Sum(50) res[51] = fma52lo(res[51], a[23], a[28]); // Sum(51) res[52] = fma52hi(res[52], a[23], a[28]); // Sum(51) res[52] = fma52lo(res[52], a[24], a[28]); // Sum(52) res[53] = fma52hi(res[53], a[24], a[28]); // Sum(52) res[53] = fma52lo(res[53], a[25], a[28]); // Sum(53) res[54] = fma52hi(res[54], a[25], a[28]); // Sum(53) res[54] = fma52lo(res[54], a[26], a[28]); // Sum(54) res[55] = fma52hi(res[55], a[26], a[28]); // Sum(54) res[55] = fma52lo(res[55], a[27], a[28]); // Sum(55) res[56] = fma52hi(res[56], a[27], a[28]); // Sum(55) res[48] = fma52lo(res[48], a[19], a[29]); // Sum(48) res[49] = fma52hi(res[49], a[19], a[29]); // Sum(48) res[49] = fma52lo(res[49], a[20], a[29]); // Sum(49) res[50] = fma52hi(res[50], a[20], a[29]); // Sum(49) res[50] = fma52lo(res[50], a[21], a[29]); // Sum(50) res[51] = fma52hi(res[51], a[21], a[29]); // Sum(50) res[51] = fma52lo(res[51], a[22], a[29]); // Sum(51) res[52] = fma52hi(res[52], a[22], a[29]); // Sum(51) res[52] = fma52lo(res[52], a[23], a[29]); // Sum(52) res[53] = fma52hi(res[53], a[23], a[29]); // Sum(52) res[53] = fma52lo(res[53], a[24], a[29]); // Sum(53) res[54] = fma52hi(res[54], a[24], a[29]); // Sum(53) res[54] = fma52lo(res[54], a[25], a[29]); // Sum(54) res[55] = fma52hi(res[55], a[25], a[29]); // Sum(54) res[55] = fma52lo(res[55], a[26], a[29]); // Sum(55) res[56] = fma52hi(res[56], a[26], a[29]); // Sum(55) res[56] = fma52lo(res[56], a[27], a[29]); // Sum(56) res[57] = fma52hi(res[57], a[27], a[29]); // Sum(56) res[57] = fma52lo(res[57], a[28], a[29]); // Sum(57) res[58] = fma52hi(res[58], a[28], a[29]); // Sum(57) res[48] = fma52lo(res[48], a[18], a[30]); // Sum(48) res[49] = fma52hi(res[49], a[18], a[30]); // Sum(48) res[49] = fma52lo(res[49], a[19], a[30]); // Sum(49) res[50] = fma52hi(res[50], a[19], a[30]); // Sum(49) res[50] = fma52lo(res[50], a[20], a[30]); // Sum(50) res[51] = fma52hi(res[51], a[20], a[30]); // Sum(50) res[51] = fma52lo(res[51], a[21], a[30]); // Sum(51) res[52] = fma52hi(res[52], a[21], a[30]); // Sum(51) res[52] = fma52lo(res[52], a[22], a[30]); // Sum(52) res[53] = fma52hi(res[53], a[22], a[30]); // Sum(52) res[53] = fma52lo(res[53], a[23], a[30]); // Sum(53) res[54] = fma52hi(res[54], a[23], a[30]); // Sum(53) res[54] = fma52lo(res[54], a[24], a[30]); // Sum(54) res[55] = fma52hi(res[55], a[24], a[30]); // Sum(54) res[55] = fma52lo(res[55], a[25], a[30]); // Sum(55) res[56] = fma52hi(res[56], a[25], a[30]); // Sum(55) res[56] = fma52lo(res[56], a[26], a[30]); // Sum(56) res[57] = fma52hi(res[57], a[26], a[30]); // Sum(56) res[57] = fma52lo(res[57], a[27], a[30]); // Sum(57) res[58] = fma52hi(res[58], a[27], a[30]); // Sum(57) res[58] = fma52lo(res[58], a[28], a[30]); // Sum(58) res[59] = fma52hi(res[59], a[28], a[30]); // Sum(58) res[59] = fma52lo(res[59], a[29], a[30]); // Sum(59) res[60] = fma52hi(res[60], a[29], a[30]); // Sum(59) res[48] = fma52lo(res[48], a[17], a[31]); // Sum(48) res[49] = fma52hi(res[49], a[17], a[31]); // Sum(48) res[49] = fma52lo(res[49], a[18], a[31]); // Sum(49) res[50] = fma52hi(res[50], a[18], a[31]); // Sum(49) res[50] = fma52lo(res[50], a[19], a[31]); // Sum(50) res[51] = fma52hi(res[51], a[19], a[31]); // Sum(50) res[51] = fma52lo(res[51], a[20], a[31]); // Sum(51) res[52] = fma52hi(res[52], a[20], a[31]); // Sum(51) res[52] = fma52lo(res[52], a[21], a[31]); // Sum(52) res[53] = fma52hi(res[53], a[21], a[31]); // Sum(52) res[53] = fma52lo(res[53], a[22], a[31]); // Sum(53) res[54] = fma52hi(res[54], a[22], a[31]); // Sum(53) res[54] = fma52lo(res[54], a[23], a[31]); // Sum(54) res[55] = fma52hi(res[55], a[23], a[31]); // Sum(54) res[55] = fma52lo(res[55], a[24], a[31]); // Sum(55) res[56] = fma52hi(res[56], a[24], a[31]); // Sum(55) res[56] = fma52lo(res[56], a[25], a[31]); // Sum(56) res[57] = fma52hi(res[57], a[25], a[31]); // Sum(56) res[57] = fma52lo(res[57], a[26], a[31]); // Sum(57) res[58] = fma52hi(res[58], a[26], a[31]); // Sum(57) res[58] = fma52lo(res[58], a[27], a[31]); // Sum(58) res[59] = fma52hi(res[59], a[27], a[31]); // Sum(58) res[59] = fma52lo(res[59], a[28], a[31]); // Sum(59) res[60] = fma52hi(res[60], a[28], a[31]); // Sum(59) res[48] = fma52lo(res[48], a[16], a[32]); // Sum(48) res[49] = fma52hi(res[49], a[16], a[32]); // Sum(48) res[49] = fma52lo(res[49], a[17], a[32]); // Sum(49) res[50] = fma52hi(res[50], a[17], a[32]); // Sum(49) res[50] = fma52lo(res[50], a[18], a[32]); // Sum(50) res[51] = fma52hi(res[51], a[18], a[32]); // Sum(50) res[51] = fma52lo(res[51], a[19], a[32]); // Sum(51) res[52] = fma52hi(res[52], a[19], a[32]); // Sum(51) res[52] = fma52lo(res[52], a[20], a[32]); // Sum(52) res[53] = fma52hi(res[53], a[20], a[32]); // Sum(52) res[53] = fma52lo(res[53], a[21], a[32]); // Sum(53) res[54] = fma52hi(res[54], a[21], a[32]); // Sum(53) res[54] = fma52lo(res[54], a[22], a[32]); // Sum(54) res[55] = fma52hi(res[55], a[22], a[32]); // Sum(54) res[55] = fma52lo(res[55], a[23], a[32]); // Sum(55) res[56] = fma52hi(res[56], a[23], a[32]); // Sum(55) res[56] = fma52lo(res[56], a[24], a[32]); // Sum(56) res[57] = fma52hi(res[57], a[24], a[32]); // Sum(56) res[57] = fma52lo(res[57], a[25], a[32]); // Sum(57) res[58] = fma52hi(res[58], a[25], a[32]); // Sum(57) res[58] = fma52lo(res[58], a[26], a[32]); // Sum(58) res[59] = fma52hi(res[59], a[26], a[32]); // Sum(58) res[59] = fma52lo(res[59], a[27], a[32]); // Sum(59) res[60] = fma52hi(res[60], a[27], a[32]); // Sum(59) res[48] = fma52lo(res[48], a[15], a[33]); // Sum(48) res[49] = fma52hi(res[49], a[15], a[33]); // Sum(48) res[49] = fma52lo(res[49], a[16], a[33]); // Sum(49) res[50] = fma52hi(res[50], a[16], a[33]); // Sum(49) res[50] = fma52lo(res[50], a[17], a[33]); // Sum(50) res[51] = fma52hi(res[51], a[17], a[33]); // Sum(50) res[51] = fma52lo(res[51], a[18], a[33]); // Sum(51) res[52] = fma52hi(res[52], a[18], a[33]); // Sum(51) res[52] = fma52lo(res[52], a[19], a[33]); // Sum(52) res[53] = fma52hi(res[53], a[19], a[33]); // Sum(52) res[53] = fma52lo(res[53], a[20], a[33]); // Sum(53) res[54] = fma52hi(res[54], a[20], a[33]); // Sum(53) res[54] = fma52lo(res[54], a[21], a[33]); // Sum(54) res[55] = fma52hi(res[55], a[21], a[33]); // Sum(54) res[55] = fma52lo(res[55], a[22], a[33]); // Sum(55) res[56] = fma52hi(res[56], a[22], a[33]); // Sum(55) res[56] = fma52lo(res[56], a[23], a[33]); // Sum(56) res[57] = fma52hi(res[57], a[23], a[33]); // Sum(56) res[57] = fma52lo(res[57], a[24], a[33]); // Sum(57) res[58] = fma52hi(res[58], a[24], a[33]); // Sum(57) res[58] = fma52lo(res[58], a[25], a[33]); // Sum(58) res[59] = fma52hi(res[59], a[25], a[33]); // Sum(58) res[59] = fma52lo(res[59], a[26], a[33]); // Sum(59) res[60] = fma52hi(res[60], a[26], a[33]); // Sum(59) res[48] = fma52lo(res[48], a[14], a[34]); // Sum(48) res[49] = fma52hi(res[49], a[14], a[34]); // Sum(48) res[49] = fma52lo(res[49], a[15], a[34]); // Sum(49) res[50] = fma52hi(res[50], a[15], a[34]); // Sum(49) res[50] = fma52lo(res[50], a[16], a[34]); // Sum(50) res[51] = fma52hi(res[51], a[16], a[34]); // Sum(50) res[51] = fma52lo(res[51], a[17], a[34]); // Sum(51) res[52] = fma52hi(res[52], a[17], a[34]); // Sum(51) res[52] = fma52lo(res[52], a[18], a[34]); // Sum(52) res[53] = fma52hi(res[53], a[18], a[34]); // Sum(52) res[53] = fma52lo(res[53], a[19], a[34]); // Sum(53) res[54] = fma52hi(res[54], a[19], a[34]); // Sum(53) res[54] = fma52lo(res[54], a[20], a[34]); // Sum(54) res[55] = fma52hi(res[55], a[20], a[34]); // Sum(54) res[55] = fma52lo(res[55], a[21], a[34]); // Sum(55) res[56] = fma52hi(res[56], a[21], a[34]); // Sum(55) res[56] = fma52lo(res[56], a[22], a[34]); // Sum(56) res[57] = fma52hi(res[57], a[22], a[34]); // Sum(56) res[57] = fma52lo(res[57], a[23], a[34]); // Sum(57) res[58] = fma52hi(res[58], a[23], a[34]); // Sum(57) res[58] = fma52lo(res[58], a[24], a[34]); // Sum(58) res[59] = fma52hi(res[59], a[24], a[34]); // Sum(58) res[59] = fma52lo(res[59], a[25], a[34]); // Sum(59) res[60] = fma52hi(res[60], a[25], a[34]); // Sum(59) res[48] = fma52lo(res[48], a[13], a[35]); // Sum(48) res[49] = fma52hi(res[49], a[13], a[35]); // Sum(48) res[49] = fma52lo(res[49], a[14], a[35]); // Sum(49) res[50] = fma52hi(res[50], a[14], a[35]); // Sum(49) res[50] = fma52lo(res[50], a[15], a[35]); // Sum(50) res[51] = fma52hi(res[51], a[15], a[35]); // Sum(50) res[51] = fma52lo(res[51], a[16], a[35]); // Sum(51) res[52] = fma52hi(res[52], a[16], a[35]); // Sum(51) res[52] = fma52lo(res[52], a[17], a[35]); // Sum(52) res[53] = fma52hi(res[53], a[17], a[35]); // Sum(52) res[53] = fma52lo(res[53], a[18], a[35]); // Sum(53) res[54] = fma52hi(res[54], a[18], a[35]); // Sum(53) res[54] = fma52lo(res[54], a[19], a[35]); // Sum(54) res[55] = fma52hi(res[55], a[19], a[35]); // Sum(54) res[55] = fma52lo(res[55], a[20], a[35]); // Sum(55) res[56] = fma52hi(res[56], a[20], a[35]); // Sum(55) res[56] = fma52lo(res[56], a[21], a[35]); // Sum(56) res[57] = fma52hi(res[57], a[21], a[35]); // Sum(56) res[57] = fma52lo(res[57], a[22], a[35]); // Sum(57) res[58] = fma52hi(res[58], a[22], a[35]); // Sum(57) res[58] = fma52lo(res[58], a[23], a[35]); // Sum(58) res[59] = fma52hi(res[59], a[23], a[35]); // Sum(58) res[59] = fma52lo(res[59], a[24], a[35]); // Sum(59) res[60] = fma52hi(res[60], a[24], a[35]); // Sum(59) res[48] = fma52lo(res[48], a[12], a[36]); // Sum(48) res[49] = fma52hi(res[49], a[12], a[36]); // Sum(48) res[49] = fma52lo(res[49], a[13], a[36]); // Sum(49) res[50] = fma52hi(res[50], a[13], a[36]); // Sum(49) res[50] = fma52lo(res[50], a[14], a[36]); // Sum(50) res[51] = fma52hi(res[51], a[14], a[36]); // Sum(50) res[51] = fma52lo(res[51], a[15], a[36]); // Sum(51) res[52] = fma52hi(res[52], a[15], a[36]); // Sum(51) res[52] = fma52lo(res[52], a[16], a[36]); // Sum(52) res[53] = fma52hi(res[53], a[16], a[36]); // Sum(52) res[53] = fma52lo(res[53], a[17], a[36]); // Sum(53) res[54] = fma52hi(res[54], a[17], a[36]); // Sum(53) res[54] = fma52lo(res[54], a[18], a[36]); // Sum(54) res[55] = fma52hi(res[55], a[18], a[36]); // Sum(54) res[55] = fma52lo(res[55], a[19], a[36]); // Sum(55) res[56] = fma52hi(res[56], a[19], a[36]); // Sum(55) res[56] = fma52lo(res[56], a[20], a[36]); // Sum(56) res[57] = fma52hi(res[57], a[20], a[36]); // Sum(56) res[57] = fma52lo(res[57], a[21], a[36]); // Sum(57) res[58] = fma52hi(res[58], a[21], a[36]); // Sum(57) res[58] = fma52lo(res[58], a[22], a[36]); // Sum(58) res[59] = fma52hi(res[59], a[22], a[36]); // Sum(58) res[59] = fma52lo(res[59], a[23], a[36]); // Sum(59) res[60] = fma52hi(res[60], a[23], a[36]); // Sum(59) res[48] = fma52lo(res[48], a[11], a[37]); // Sum(48) res[49] = fma52hi(res[49], a[11], a[37]); // Sum(48) res[49] = fma52lo(res[49], a[12], a[37]); // Sum(49) res[50] = fma52hi(res[50], a[12], a[37]); // Sum(49) res[50] = fma52lo(res[50], a[13], a[37]); // Sum(50) res[51] = fma52hi(res[51], a[13], a[37]); // Sum(50) res[51] = fma52lo(res[51], a[14], a[37]); // Sum(51) res[52] = fma52hi(res[52], a[14], a[37]); // Sum(51) res[52] = fma52lo(res[52], a[15], a[37]); // Sum(52) res[53] = fma52hi(res[53], a[15], a[37]); // Sum(52) res[53] = fma52lo(res[53], a[16], a[37]); // Sum(53) res[54] = fma52hi(res[54], a[16], a[37]); // Sum(53) res[54] = fma52lo(res[54], a[17], a[37]); // Sum(54) res[55] = fma52hi(res[55], a[17], a[37]); // Sum(54) res[55] = fma52lo(res[55], a[18], a[37]); // Sum(55) res[56] = fma52hi(res[56], a[18], a[37]); // Sum(55) res[56] = fma52lo(res[56], a[19], a[37]); // Sum(56) res[57] = fma52hi(res[57], a[19], a[37]); // Sum(56) res[57] = fma52lo(res[57], a[20], a[37]); // Sum(57) res[58] = fma52hi(res[58], a[20], a[37]); // Sum(57) res[58] = fma52lo(res[58], a[21], a[37]); // Sum(58) res[59] = fma52hi(res[59], a[21], a[37]); // Sum(58) res[59] = fma52lo(res[59], a[22], a[37]); // Sum(59) res[60] = fma52hi(res[60], a[22], a[37]); // Sum(59) res[48] = fma52lo(res[48], a[10], a[38]); // Sum(48) res[49] = fma52hi(res[49], a[10], a[38]); // Sum(48) res[49] = fma52lo(res[49], a[11], a[38]); // Sum(49) res[50] = fma52hi(res[50], a[11], a[38]); // Sum(49) res[50] = fma52lo(res[50], a[12], a[38]); // Sum(50) res[51] = fma52hi(res[51], a[12], a[38]); // Sum(50) res[51] = fma52lo(res[51], a[13], a[38]); // Sum(51) res[52] = fma52hi(res[52], a[13], a[38]); // Sum(51) res[52] = fma52lo(res[52], a[14], a[38]); // Sum(52) res[53] = fma52hi(res[53], a[14], a[38]); // Sum(52) res[53] = fma52lo(res[53], a[15], a[38]); // Sum(53) res[54] = fma52hi(res[54], a[15], a[38]); // Sum(53) res[54] = fma52lo(res[54], a[16], a[38]); // Sum(54) res[55] = fma52hi(res[55], a[16], a[38]); // Sum(54) res[55] = fma52lo(res[55], a[17], a[38]); // Sum(55) res[56] = fma52hi(res[56], a[17], a[38]); // Sum(55) res[56] = fma52lo(res[56], a[18], a[38]); // Sum(56) res[57] = fma52hi(res[57], a[18], a[38]); // Sum(56) res[57] = fma52lo(res[57], a[19], a[38]); // Sum(57) res[58] = fma52hi(res[58], a[19], a[38]); // Sum(57) res[58] = fma52lo(res[58], a[20], a[38]); // Sum(58) res[59] = fma52hi(res[59], a[20], a[38]); // Sum(58) res[59] = fma52lo(res[59], a[21], a[38]); // Sum(59) res[60] = fma52hi(res[60], a[21], a[38]); // Sum(59) res[48] = fma52lo(res[48], a[9], a[39]); // Sum(48) res[49] = fma52hi(res[49], a[9], a[39]); // Sum(48) res[49] = fma52lo(res[49], a[10], a[39]); // Sum(49) res[50] = fma52hi(res[50], a[10], a[39]); // Sum(49) res[50] = fma52lo(res[50], a[11], a[39]); // Sum(50) res[51] = fma52hi(res[51], a[11], a[39]); // Sum(50) res[51] = fma52lo(res[51], a[12], a[39]); // Sum(51) res[52] = fma52hi(res[52], a[12], a[39]); // Sum(51) res[52] = fma52lo(res[52], a[13], a[39]); // Sum(52) res[53] = fma52hi(res[53], a[13], a[39]); // Sum(52) res[53] = fma52lo(res[53], a[14], a[39]); // Sum(53) res[54] = fma52hi(res[54], a[14], a[39]); // Sum(53) res[54] = fma52lo(res[54], a[15], a[39]); // Sum(54) res[55] = fma52hi(res[55], a[15], a[39]); // Sum(54) res[55] = fma52lo(res[55], a[16], a[39]); // Sum(55) res[56] = fma52hi(res[56], a[16], a[39]); // Sum(55) res[56] = fma52lo(res[56], a[17], a[39]); // Sum(56) res[57] = fma52hi(res[57], a[17], a[39]); // Sum(56) res[57] = fma52lo(res[57], a[18], a[39]); // Sum(57) res[58] = fma52hi(res[58], a[18], a[39]); // Sum(57) res[58] = fma52lo(res[58], a[19], a[39]); // Sum(58) res[59] = fma52hi(res[59], a[19], a[39]); // Sum(58) res[59] = fma52lo(res[59], a[20], a[39]); // Sum(59) res[60] = fma52hi(res[60], a[20], a[39]); // Sum(59) res[48] = add64(res[48], res[48]); // Double(48) res[49] = add64(res[49], res[49]); // Double(49) res[50] = add64(res[50], res[50]); // Double(50) res[51] = add64(res[51], res[51]); // Double(51) res[52] = add64(res[52], res[52]); // Double(52) res[53] = add64(res[53], res[53]); // Double(53) res[54] = add64(res[54], res[54]); // Double(54) res[55] = add64(res[55], res[55]); // Double(55) res[56] = add64(res[56], res[56]); // Double(56) res[57] = add64(res[57], res[57]); // Double(57) res[58] = add64(res[58], res[58]); // Double(58) res[59] = add64(res[59], res[59]); // Double(59) res[48] = fma52lo(res[48], a[24], a[24]); // Add sqr(48) res[49] = fma52hi(res[49], a[24], a[24]); // Add sqr(48) res[50] = fma52lo(res[50], a[25], a[25]); // Add sqr(50) res[51] = fma52hi(res[51], a[25], a[25]); // Add sqr(50) res[52] = fma52lo(res[52], a[26], a[26]); // Add sqr(52) res[53] = fma52hi(res[53], a[26], a[26]); // Add sqr(52) res[54] = fma52lo(res[54], a[27], a[27]); // Add sqr(54) res[55] = fma52hi(res[55], a[27], a[27]); // Add sqr(54) res[56] = fma52lo(res[56], a[28], a[28]); // Add sqr(56) res[57] = fma52hi(res[57], a[28], a[28]); // Add sqr(56) res[58] = fma52lo(res[58], a[29], a[29]); // Add sqr(58) res[59] = fma52hi(res[59], a[29], a[29]); // Add sqr(58) res[60] = fma52lo(res[60], a[29], a[31]); // Sum(60) res[61] = fma52hi(res[61], a[29], a[31]); // Sum(60) res[61] = fma52lo(res[61], a[30], a[31]); // Sum(61) res[62] = fma52hi(res[62], a[30], a[31]); // Sum(61) res[60] = fma52lo(res[60], a[28], a[32]); // Sum(60) res[61] = fma52hi(res[61], a[28], a[32]); // Sum(60) res[61] = fma52lo(res[61], a[29], a[32]); // Sum(61) res[62] = fma52hi(res[62], a[29], a[32]); // Sum(61) res[62] = fma52lo(res[62], a[30], a[32]); // Sum(62) res[63] = fma52hi(res[63], a[30], a[32]); // Sum(62) res[63] = fma52lo(res[63], a[31], a[32]); // Sum(63) res[64] = fma52hi(res[64], a[31], a[32]); // Sum(63) res[60] = fma52lo(res[60], a[27], a[33]); // Sum(60) res[61] = fma52hi(res[61], a[27], a[33]); // Sum(60) res[61] = fma52lo(res[61], a[28], a[33]); // Sum(61) res[62] = fma52hi(res[62], a[28], a[33]); // Sum(61) res[62] = fma52lo(res[62], a[29], a[33]); // Sum(62) res[63] = fma52hi(res[63], a[29], a[33]); // Sum(62) res[63] = fma52lo(res[63], a[30], a[33]); // Sum(63) res[64] = fma52hi(res[64], a[30], a[33]); // Sum(63) res[64] = fma52lo(res[64], a[31], a[33]); // Sum(64) res[65] = fma52hi(res[65], a[31], a[33]); // Sum(64) res[65] = fma52lo(res[65], a[32], a[33]); // Sum(65) res[66] = fma52hi(res[66], a[32], a[33]); // Sum(65) res[60] = fma52lo(res[60], a[26], a[34]); // Sum(60) res[61] = fma52hi(res[61], a[26], a[34]); // Sum(60) res[61] = fma52lo(res[61], a[27], a[34]); // Sum(61) res[62] = fma52hi(res[62], a[27], a[34]); // Sum(61) res[62] = fma52lo(res[62], a[28], a[34]); // Sum(62) res[63] = fma52hi(res[63], a[28], a[34]); // Sum(62) res[63] = fma52lo(res[63], a[29], a[34]); // Sum(63) res[64] = fma52hi(res[64], a[29], a[34]); // Sum(63) res[64] = fma52lo(res[64], a[30], a[34]); // Sum(64) res[65] = fma52hi(res[65], a[30], a[34]); // Sum(64) res[65] = fma52lo(res[65], a[31], a[34]); // Sum(65) res[66] = fma52hi(res[66], a[31], a[34]); // Sum(65) res[66] = fma52lo(res[66], a[32], a[34]); // Sum(66) res[67] = fma52hi(res[67], a[32], a[34]); // Sum(66) res[67] = fma52lo(res[67], a[33], a[34]); // Sum(67) res[68] = fma52hi(res[68], a[33], a[34]); // Sum(67) res[60] = fma52lo(res[60], a[25], a[35]); // Sum(60) res[61] = fma52hi(res[61], a[25], a[35]); // Sum(60) res[61] = fma52lo(res[61], a[26], a[35]); // Sum(61) res[62] = fma52hi(res[62], a[26], a[35]); // Sum(61) res[62] = fma52lo(res[62], a[27], a[35]); // Sum(62) res[63] = fma52hi(res[63], a[27], a[35]); // Sum(62) res[63] = fma52lo(res[63], a[28], a[35]); // Sum(63) res[64] = fma52hi(res[64], a[28], a[35]); // Sum(63) res[64] = fma52lo(res[64], a[29], a[35]); // Sum(64) res[65] = fma52hi(res[65], a[29], a[35]); // Sum(64) res[65] = fma52lo(res[65], a[30], a[35]); // Sum(65) res[66] = fma52hi(res[66], a[30], a[35]); // Sum(65) res[66] = fma52lo(res[66], a[31], a[35]); // Sum(66) res[67] = fma52hi(res[67], a[31], a[35]); // Sum(66) res[67] = fma52lo(res[67], a[32], a[35]); // Sum(67) res[68] = fma52hi(res[68], a[32], a[35]); // Sum(67) res[68] = fma52lo(res[68], a[33], a[35]); // Sum(68) res[69] = fma52hi(res[69], a[33], a[35]); // Sum(68) res[69] = fma52lo(res[69], a[34], a[35]); // Sum(69) res[70] = fma52hi(res[70], a[34], a[35]); // Sum(69) res[60] = fma52lo(res[60], a[24], a[36]); // Sum(60) res[61] = fma52hi(res[61], a[24], a[36]); // Sum(60) res[61] = fma52lo(res[61], a[25], a[36]); // Sum(61) res[62] = fma52hi(res[62], a[25], a[36]); // Sum(61) res[62] = fma52lo(res[62], a[26], a[36]); // Sum(62) res[63] = fma52hi(res[63], a[26], a[36]); // Sum(62) res[63] = fma52lo(res[63], a[27], a[36]); // Sum(63) res[64] = fma52hi(res[64], a[27], a[36]); // Sum(63) res[64] = fma52lo(res[64], a[28], a[36]); // Sum(64) res[65] = fma52hi(res[65], a[28], a[36]); // Sum(64) res[65] = fma52lo(res[65], a[29], a[36]); // Sum(65) res[66] = fma52hi(res[66], a[29], a[36]); // Sum(65) res[66] = fma52lo(res[66], a[30], a[36]); // Sum(66) res[67] = fma52hi(res[67], a[30], a[36]); // Sum(66) res[67] = fma52lo(res[67], a[31], a[36]); // Sum(67) res[68] = fma52hi(res[68], a[31], a[36]); // Sum(67) res[68] = fma52lo(res[68], a[32], a[36]); // Sum(68) res[69] = fma52hi(res[69], a[32], a[36]); // Sum(68) res[69] = fma52lo(res[69], a[33], a[36]); // Sum(69) res[70] = fma52hi(res[70], a[33], a[36]); // Sum(69) res[70] = fma52lo(res[70], a[34], a[36]); // Sum(70) res[71] = fma52hi(res[71], a[34], a[36]); // Sum(70) res[71] = fma52lo(res[71], a[35], a[36]); // Sum(71) res[72] = fma52hi(res[72], a[35], a[36]); // Sum(71) res[60] = fma52lo(res[60], a[23], a[37]); // Sum(60) res[61] = fma52hi(res[61], a[23], a[37]); // Sum(60) res[61] = fma52lo(res[61], a[24], a[37]); // Sum(61) res[62] = fma52hi(res[62], a[24], a[37]); // Sum(61) res[62] = fma52lo(res[62], a[25], a[37]); // Sum(62) res[63] = fma52hi(res[63], a[25], a[37]); // Sum(62) res[63] = fma52lo(res[63], a[26], a[37]); // Sum(63) res[64] = fma52hi(res[64], a[26], a[37]); // Sum(63) res[64] = fma52lo(res[64], a[27], a[37]); // Sum(64) res[65] = fma52hi(res[65], a[27], a[37]); // Sum(64) res[65] = fma52lo(res[65], a[28], a[37]); // Sum(65) res[66] = fma52hi(res[66], a[28], a[37]); // Sum(65) res[66] = fma52lo(res[66], a[29], a[37]); // Sum(66) res[67] = fma52hi(res[67], a[29], a[37]); // Sum(66) res[67] = fma52lo(res[67], a[30], a[37]); // Sum(67) res[68] = fma52hi(res[68], a[30], a[37]); // Sum(67) res[68] = fma52lo(res[68], a[31], a[37]); // Sum(68) res[69] = fma52hi(res[69], a[31], a[37]); // Sum(68) res[69] = fma52lo(res[69], a[32], a[37]); // Sum(69) res[70] = fma52hi(res[70], a[32], a[37]); // Sum(69) res[70] = fma52lo(res[70], a[33], a[37]); // Sum(70) res[71] = fma52hi(res[71], a[33], a[37]); // Sum(70) res[71] = fma52lo(res[71], a[34], a[37]); // Sum(71) res[72] = fma52hi(res[72], a[34], a[37]); // Sum(71) res[60] = fma52lo(res[60], a[22], a[38]); // Sum(60) res[61] = fma52hi(res[61], a[22], a[38]); // Sum(60) res[61] = fma52lo(res[61], a[23], a[38]); // Sum(61) res[62] = fma52hi(res[62], a[23], a[38]); // Sum(61) res[62] = fma52lo(res[62], a[24], a[38]); // Sum(62) res[63] = fma52hi(res[63], a[24], a[38]); // Sum(62) res[63] = fma52lo(res[63], a[25], a[38]); // Sum(63) res[64] = fma52hi(res[64], a[25], a[38]); // Sum(63) res[64] = fma52lo(res[64], a[26], a[38]); // Sum(64) res[65] = fma52hi(res[65], a[26], a[38]); // Sum(64) res[65] = fma52lo(res[65], a[27], a[38]); // Sum(65) res[66] = fma52hi(res[66], a[27], a[38]); // Sum(65) res[66] = fma52lo(res[66], a[28], a[38]); // Sum(66) res[67] = fma52hi(res[67], a[28], a[38]); // Sum(66) res[67] = fma52lo(res[67], a[29], a[38]); // Sum(67) res[68] = fma52hi(res[68], a[29], a[38]); // Sum(67) res[68] = fma52lo(res[68], a[30], a[38]); // Sum(68) res[69] = fma52hi(res[69], a[30], a[38]); // Sum(68) res[69] = fma52lo(res[69], a[31], a[38]); // Sum(69) res[70] = fma52hi(res[70], a[31], a[38]); // Sum(69) res[70] = fma52lo(res[70], a[32], a[38]); // Sum(70) res[71] = fma52hi(res[71], a[32], a[38]); // Sum(70) res[71] = fma52lo(res[71], a[33], a[38]); // Sum(71) res[72] = fma52hi(res[72], a[33], a[38]); // Sum(71) res[60] = fma52lo(res[60], a[21], a[39]); // Sum(60) res[61] = fma52hi(res[61], a[21], a[39]); // Sum(60) res[61] = fma52lo(res[61], a[22], a[39]); // Sum(61) res[62] = fma52hi(res[62], a[22], a[39]); // Sum(61) res[62] = fma52lo(res[62], a[23], a[39]); // Sum(62) res[63] = fma52hi(res[63], a[23], a[39]); // Sum(62) res[63] = fma52lo(res[63], a[24], a[39]); // Sum(63) res[64] = fma52hi(res[64], a[24], a[39]); // Sum(63) res[64] = fma52lo(res[64], a[25], a[39]); // Sum(64) res[65] = fma52hi(res[65], a[25], a[39]); // Sum(64) res[65] = fma52lo(res[65], a[26], a[39]); // Sum(65) res[66] = fma52hi(res[66], a[26], a[39]); // Sum(65) res[66] = fma52lo(res[66], a[27], a[39]); // Sum(66) res[67] = fma52hi(res[67], a[27], a[39]); // Sum(66) res[67] = fma52lo(res[67], a[28], a[39]); // Sum(67) res[68] = fma52hi(res[68], a[28], a[39]); // Sum(67) res[68] = fma52lo(res[68], a[29], a[39]); // Sum(68) res[69] = fma52hi(res[69], a[29], a[39]); // Sum(68) res[69] = fma52lo(res[69], a[30], a[39]); // Sum(69) res[70] = fma52hi(res[70], a[30], a[39]); // Sum(69) res[70] = fma52lo(res[70], a[31], a[39]); // Sum(70) res[71] = fma52hi(res[71], a[31], a[39]); // Sum(70) res[71] = fma52lo(res[71], a[32], a[39]); // Sum(71) res[72] = fma52hi(res[72], a[32], a[39]); // Sum(71) res[60] = add64(res[60], res[60]); // Double(60) res[61] = add64(res[61], res[61]); // Double(61) res[62] = add64(res[62], res[62]); // Double(62) res[63] = add64(res[63], res[63]); // Double(63) res[64] = add64(res[64], res[64]); // Double(64) res[65] = add64(res[65], res[65]); // Double(65) res[66] = add64(res[66], res[66]); // Double(66) res[67] = add64(res[67], res[67]); // Double(67) res[68] = add64(res[68], res[68]); // Double(68) res[69] = add64(res[69], res[69]); // Double(69) res[70] = add64(res[70], res[70]); // Double(70) res[71] = add64(res[71], res[71]); // Double(71) res[60] = fma52lo(res[60], a[30], a[30]); // Add sqr(60) res[61] = fma52hi(res[61], a[30], a[30]); // Add sqr(60) res[62] = fma52lo(res[62], a[31], a[31]); // Add sqr(62) res[63] = fma52hi(res[63], a[31], a[31]); // Add sqr(62) res[64] = fma52lo(res[64], a[32], a[32]); // Add sqr(64) res[65] = fma52hi(res[65], a[32], a[32]); // Add sqr(64) res[66] = fma52lo(res[66], a[33], a[33]); // Add sqr(66) res[67] = fma52hi(res[67], a[33], a[33]); // Add sqr(66) res[68] = fma52lo(res[68], a[34], a[34]); // Add sqr(68) res[69] = fma52hi(res[69], a[34], a[34]); // Add sqr(68) res[70] = fma52lo(res[70], a[35], a[35]); // Add sqr(70) res[71] = fma52hi(res[71], a[35], a[35]); // Add sqr(70) res[72] = fma52lo(res[72], a[35], a[37]); // Sum(72) res[73] = fma52hi(res[73], a[35], a[37]); // Sum(72) res[73] = fma52lo(res[73], a[36], a[37]); // Sum(73) res[74] = fma52hi(res[74], a[36], a[37]); // Sum(73) res[72] = fma52lo(res[72], a[34], a[38]); // Sum(72) res[73] = fma52hi(res[73], a[34], a[38]); // Sum(72) res[73] = fma52lo(res[73], a[35], a[38]); // Sum(73) res[74] = fma52hi(res[74], a[35], a[38]); // Sum(73) res[74] = fma52lo(res[74], a[36], a[38]); // Sum(74) res[75] = fma52hi(res[75], a[36], a[38]); // Sum(74) res[75] = fma52lo(res[75], a[37], a[38]); // Sum(75) res[76] = fma52hi(res[76], a[37], a[38]); // Sum(75) res[72] = fma52lo(res[72], a[33], a[39]); // Sum(72) res[73] = fma52hi(res[73], a[33], a[39]); // Sum(72) res[73] = fma52lo(res[73], a[34], a[39]); // Sum(73) res[74] = fma52hi(res[74], a[34], a[39]); // Sum(73) res[74] = fma52lo(res[74], a[35], a[39]); // Sum(74) res[75] = fma52hi(res[75], a[35], a[39]); // Sum(74) res[75] = fma52lo(res[75], a[36], a[39]); // Sum(75) res[76] = fma52hi(res[76], a[36], a[39]); // Sum(75) res[76] = fma52lo(res[76], a[37], a[39]); // Sum(76) res[77] = fma52hi(res[77], a[37], a[39]); // Sum(76) res[77] = fma52lo(res[77], a[38], a[39]); // Sum(77) res[78] = fma52hi(res[78], a[38], a[39]); // Sum(77) res[72] = add64(res[72], res[72]); // Double(72) res[73] = add64(res[73], res[73]); // Double(73) res[74] = add64(res[74], res[74]); // Double(74) res[75] = add64(res[75], res[75]); // Double(75) res[76] = add64(res[76], res[76]); // Double(76) res[77] = add64(res[77], res[77]); // Double(77) res[78] = add64(res[78], res[78]); // Double(78) res[72] = fma52lo(res[72], a[36], a[36]); // Add sqr(72) res[73] = fma52hi(res[73], a[36], a[36]); // Add sqr(72) res[74] = fma52lo(res[74], a[37], a[37]); // Add sqr(74) res[75] = fma52hi(res[75], a[37], a[37]); // Add sqr(74) res[76] = fma52lo(res[76], a[38], a[38]); // Add sqr(76) res[77] = fma52hi(res[77], a[38], a[38]); // Add sqr(76) res[78] = fma52lo(res[78], a[39], a[39]); // Add sqr(78) res[79] = fma52hi(res[79], a[39], a[39]); // Add sqr(78) // Montgomery Reduction int it; for (it = 0; it < 40; it += 10) { // Reduction step int jt = 0; if ((it + 0) > 0) res[it + 0] = add64(res[it + 0], srli64(res[it + -1], DIGIT_SIZE)); u[it + 0] = mul52lo(res[it + 0], k); res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + 1] = add64(res[it + 1], srli64(res[it + 0], DIGIT_SIZE)); u[it + 1] = mul52lo(res[it + 1], k); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + 2] = add64(res[it + 2], srli64(res[it + 1], DIGIT_SIZE)); u[it + 2] = mul52lo(res[it + 2], k); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + 3] = add64(res[it + 3], srli64(res[it + 2], DIGIT_SIZE)); u[it + 3] = mul52lo(res[it + 3], k); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + 4] = add64(res[it + 4], srli64(res[it + 3], DIGIT_SIZE)); u[it + 4] = mul52lo(res[it + 4], k); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + 5] = add64(res[it + 5], srli64(res[it + 4], DIGIT_SIZE)); u[it + 5] = mul52lo(res[it + 5], k); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + 6] = add64(res[it + 6], srli64(res[it + 5], DIGIT_SIZE)); u[it + 6] = mul52lo(res[it + 6], k); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + 7] = add64(res[it + 7], srli64(res[it + 6], DIGIT_SIZE)); u[it + 7] = mul52lo(res[it + 7], k); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + 8] = add64(res[it + 8], srli64(res[it + 7], DIGIT_SIZE)); u[it + 8] = mul52lo(res[it + 8], k); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + 9] = add64(res[it + 9], srli64(res[it + 8], DIGIT_SIZE)); u[it + 9] = mul52lo(res[it + 9], k); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); for (jt = 10; jt < 40; jt += 10) { // Poly tile res[it + jt + 0] = fma52lo(res[it + jt + 0], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52hi(res[it + jt + 1], u[it + 0], m[jt + 0]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 0], m[jt + 1]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 0], m[jt + 2]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 0], m[jt + 3]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 0], m[jt + 4]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 0], m[jt + 5]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 0], m[jt + 6]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 0], m[jt + 7]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 0], m[jt + 8]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 0], m[jt + 9]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 0], m[jt + 9]); res[it + jt + 1] = fma52lo(res[it + jt + 1], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52hi(res[it + jt + 2], u[it + 1], m[jt + 0]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 1], m[jt + 1]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 1], m[jt + 2]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 1], m[jt + 3]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 1], m[jt + 4]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 1], m[jt + 5]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 1], m[jt + 6]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 1], m[jt + 7]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 1], m[jt + 8]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 1], m[jt + 9]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 1], m[jt + 9]); res[it + jt + 2] = fma52lo(res[it + jt + 2], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52hi(res[it + jt + 3], u[it + 2], m[jt + 0]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 2], m[jt + 1]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 2], m[jt + 2]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 2], m[jt + 3]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 2], m[jt + 4]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 2], m[jt + 5]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 2], m[jt + 6]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 2], m[jt + 7]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 2], m[jt + 8]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 2], m[jt + 9]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 2], m[jt + 9]); res[it + jt + 3] = fma52lo(res[it + jt + 3], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52hi(res[it + jt + 4], u[it + 3], m[jt + 0]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 3], m[jt + 1]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 3], m[jt + 2]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 3], m[jt + 3]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 3], m[jt + 4]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 3], m[jt + 5]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 3], m[jt + 6]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 3], m[jt + 7]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 3], m[jt + 8]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 3], m[jt + 9]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 3], m[jt + 9]); res[it + jt + 4] = fma52lo(res[it + jt + 4], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52hi(res[it + jt + 5], u[it + 4], m[jt + 0]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 4], m[jt + 1]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 4], m[jt + 2]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 4], m[jt + 3]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 4], m[jt + 4]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 4], m[jt + 5]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 4], m[jt + 6]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 4], m[jt + 7]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 4], m[jt + 8]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 4], m[jt + 9]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 4], m[jt + 9]); res[it + jt + 5] = fma52lo(res[it + jt + 5], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52hi(res[it + jt + 6], u[it + 5], m[jt + 0]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 5], m[jt + 1]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 5], m[jt + 2]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 5], m[jt + 3]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 5], m[jt + 4]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 5], m[jt + 5]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 5], m[jt + 6]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 5], m[jt + 7]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 5], m[jt + 8]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 5], m[jt + 9]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 5], m[jt + 9]); res[it + jt + 6] = fma52lo(res[it + jt + 6], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52hi(res[it + jt + 7], u[it + 6], m[jt + 0]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 6], m[jt + 1]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 6], m[jt + 2]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 6], m[jt + 3]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 6], m[jt + 4]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 6], m[jt + 5]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 6], m[jt + 6]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 6], m[jt + 7]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 6], m[jt + 8]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 6], m[jt + 9]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 6], m[jt + 9]); res[it + jt + 7] = fma52lo(res[it + jt + 7], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52hi(res[it + jt + 8], u[it + 7], m[jt + 0]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 7], m[jt + 1]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 7], m[jt + 2]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 7], m[jt + 3]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 7], m[jt + 4]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 7], m[jt + 5]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 7], m[jt + 6]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 7], m[jt + 7]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 7], m[jt + 8]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 7], m[jt + 9]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 7], m[jt + 9]); res[it + jt + 8] = fma52lo(res[it + jt + 8], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52hi(res[it + jt + 9], u[it + 8], m[jt + 0]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 8], m[jt + 1]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 8], m[jt + 2]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 8], m[jt + 3]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 8], m[jt + 4]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 8], m[jt + 5]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 8], m[jt + 6]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 8], m[jt + 7]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 8], m[jt + 8]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 8], m[jt + 9]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 8], m[jt + 9]); res[it + jt + 9] = fma52lo(res[it + jt + 9], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52hi(res[it + jt + 10], u[it + 9], m[jt + 0]); res[it + jt + 10] = fma52lo(res[it + jt + 10], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52hi(res[it + jt + 11], u[it + 9], m[jt + 1]); res[it + jt + 11] = fma52lo(res[it + jt + 11], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52hi(res[it + jt + 12], u[it + 9], m[jt + 2]); res[it + jt + 12] = fma52lo(res[it + jt + 12], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52hi(res[it + jt + 13], u[it + 9], m[jt + 3]); res[it + jt + 13] = fma52lo(res[it + jt + 13], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52hi(res[it + jt + 14], u[it + 9], m[jt + 4]); res[it + jt + 14] = fma52lo(res[it + jt + 14], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52hi(res[it + jt + 15], u[it + 9], m[jt + 5]); res[it + jt + 15] = fma52lo(res[it + jt + 15], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52hi(res[it + jt + 16], u[it + 9], m[jt + 6]); res[it + jt + 16] = fma52lo(res[it + jt + 16], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52hi(res[it + jt + 17], u[it + 9], m[jt + 7]); res[it + jt + 17] = fma52lo(res[it + jt + 17], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52hi(res[it + jt + 18], u[it + 9], m[jt + 8]); res[it + jt + 18] = fma52lo(res[it + jt + 18], u[it + 9], m[jt + 9]); res[it + jt + 19] = fma52hi(res[it + jt + 19], u[it + 9], m[jt + 9]); } } // Normalization res[40] = add64(res[40], srli64(res[39], DIGIT_SIZE)); r[0] = res[40]; res[41] = add64(res[41], srli64(res[40], DIGIT_SIZE)); r[1] = res[41]; res[42] = add64(res[42], srli64(res[41], DIGIT_SIZE)); r[2] = res[42]; res[43] = add64(res[43], srli64(res[42], DIGIT_SIZE)); r[3] = res[43]; res[44] = add64(res[44], srli64(res[43], DIGIT_SIZE)); r[4] = res[44]; res[45] = add64(res[45], srli64(res[44], DIGIT_SIZE)); r[5] = res[45]; res[46] = add64(res[46], srli64(res[45], DIGIT_SIZE)); r[6] = res[46]; res[47] = add64(res[47], srli64(res[46], DIGIT_SIZE)); r[7] = res[47]; res[48] = add64(res[48], srli64(res[47], DIGIT_SIZE)); r[8] = res[48]; res[49] = add64(res[49], srli64(res[48], DIGIT_SIZE)); r[9] = res[49]; res[50] = add64(res[50], srli64(res[49], DIGIT_SIZE)); r[10] = res[50]; res[51] = add64(res[51], srli64(res[50], DIGIT_SIZE)); r[11] = res[51]; res[52] = add64(res[52], srli64(res[51], DIGIT_SIZE)); r[12] = res[52]; res[53] = add64(res[53], srli64(res[52], DIGIT_SIZE)); r[13] = res[53]; res[54] = add64(res[54], srli64(res[53], DIGIT_SIZE)); r[14] = res[54]; res[55] = add64(res[55], srli64(res[54], DIGIT_SIZE)); r[15] = res[55]; res[56] = add64(res[56], srli64(res[55], DIGIT_SIZE)); r[16] = res[56]; res[57] = add64(res[57], srli64(res[56], DIGIT_SIZE)); r[17] = res[57]; res[58] = add64(res[58], srli64(res[57], DIGIT_SIZE)); r[18] = res[58]; res[59] = add64(res[59], srli64(res[58], DIGIT_SIZE)); r[19] = res[59]; res[60] = add64(res[60], srli64(res[59], DIGIT_SIZE)); r[20] = res[60]; res[61] = add64(res[61], srli64(res[60], DIGIT_SIZE)); r[21] = res[61]; res[62] = add64(res[62], srli64(res[61], DIGIT_SIZE)); r[22] = res[62]; res[63] = add64(res[63], srli64(res[62], DIGIT_SIZE)); r[23] = res[63]; res[64] = add64(res[64], srli64(res[63], DIGIT_SIZE)); r[24] = res[64]; res[65] = add64(res[65], srli64(res[64], DIGIT_SIZE)); r[25] = res[65]; res[66] = add64(res[66], srli64(res[65], DIGIT_SIZE)); r[26] = res[66]; res[67] = add64(res[67], srli64(res[66], DIGIT_SIZE)); r[27] = res[67]; res[68] = add64(res[68], srli64(res[67], DIGIT_SIZE)); r[28] = res[68]; res[69] = add64(res[69], srli64(res[68], DIGIT_SIZE)); r[29] = res[69]; res[70] = add64(res[70], srli64(res[69], DIGIT_SIZE)); r[30] = res[70]; res[71] = add64(res[71], srli64(res[70], DIGIT_SIZE)); r[31] = res[71]; res[72] = add64(res[72], srli64(res[71], DIGIT_SIZE)); r[32] = res[72]; res[73] = add64(res[73], srli64(res[72], DIGIT_SIZE)); r[33] = res[73]; res[74] = add64(res[74], srli64(res[73], DIGIT_SIZE)); r[34] = res[74]; res[75] = add64(res[75], srli64(res[74], DIGIT_SIZE)); r[35] = res[75]; res[76] = add64(res[76], srli64(res[75], DIGIT_SIZE)); r[36] = res[76]; res[77] = add64(res[77], srli64(res[76], DIGIT_SIZE)); r[37] = res[77]; res[78] = add64(res[78], srli64(res[77], DIGIT_SIZE)); r[38] = res[78]; res[79] = add64(res[79], srli64(res[78], DIGIT_SIZE)); r[39] = res[79]; a = (U64 *)out_mb; } } #endif /* #if (_MBX>=_MBX_K1) */ ifma_extract_amm52x20_mb8.c000066400000000000000000000270441470420105600343700ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/rsa/internal_avx512/************************************************************************* * Copyright (C) 2019-2024 Intel Corporation * * 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 #if (_MBX >= _MBX_K1) void ifma_extract_amm52x20_mb8(int64u *out_mb8, const int64u *inpA_mb8, int64u MulTbl[][redLen2K][8], const int64u Idx[8], const int64u *inpM_mb8, const int64u *k0_mb8) { U64 res00, res01, res02, res03, res04, res05, res06, res07, res08, res09, res10, res11, res12, res13, res14, res15, res16, res17, res18, res19; U64 mulB00, mulB01, mulB02, mulB03, mulB04, mulB05, mulB06, mulB07, mulB08, mulB09, mulB10, mulB11, mulB12, mulB13, mulB14, mulB15, mulB16, mulB17, mulB18, mulB19; U64 K = loadu64(k0_mb8); /* k0[] */ __mmask8 k; __ALIGN64 U64 inpB_mb8[20]; int itr; res00 = res01 = res02 = res03 = res04 = res05 = res06 = res07 = res08 = res09 = res10 = res11 = res12 = res13 = res14 = res15 = res16 = res17 = res18 = res19 = get_zero64(); U64 idx_target = loadu64((U64 *)Idx); k = cmpeq64_mask(set64(1), idx_target); mulB00 = loadu64(MulTbl[0][0]); mulB01 = loadu64(MulTbl[0][1]); mulB02 = loadu64(MulTbl[0][2]); mulB03 = loadu64(MulTbl[0][3]); mulB04 = loadu64(MulTbl[0][4]); mulB05 = loadu64(MulTbl[0][5]); mulB06 = loadu64(MulTbl[0][6]); mulB07 = loadu64(MulTbl[0][7]); mulB08 = loadu64(MulTbl[0][8]); mulB09 = loadu64(MulTbl[0][9]); mulB10 = loadu64(MulTbl[0][10]); mulB11 = loadu64(MulTbl[0][11]); mulB12 = loadu64(MulTbl[0][12]); mulB13 = loadu64(MulTbl[0][13]); mulB14 = loadu64(MulTbl[0][14]); mulB15 = loadu64(MulTbl[0][15]); mulB16 = loadu64(MulTbl[0][16]); mulB17 = loadu64(MulTbl[0][17]); mulB18 = loadu64(MulTbl[0][18]); mulB19 = loadu64(MulTbl[0][19]); for (itr = 1; itr < (1 << 5); ++itr) { U64 idx_curr = set64(itr + 1); __mmask8 k_new = cmpeq64_mask(idx_curr, idx_target); mulB00 = select64(k, mulB00, (U64 *)MulTbl[itr][0]); mulB01 = select64(k, mulB01, (U64 *)MulTbl[itr][1]); mulB02 = select64(k, mulB02, (U64 *)MulTbl[itr][2]); mulB03 = select64(k, mulB03, (U64 *)MulTbl[itr][3]); mulB04 = select64(k, mulB04, (U64 *)MulTbl[itr][4]); mulB05 = select64(k, mulB05, (U64 *)MulTbl[itr][5]); mulB06 = select64(k, mulB06, (U64 *)MulTbl[itr][6]); mulB07 = select64(k, mulB07, (U64 *)MulTbl[itr][7]); mulB08 = select64(k, mulB08, (U64 *)MulTbl[itr][8]); mulB09 = select64(k, mulB09, (U64 *)MulTbl[itr][9]); mulB10 = select64(k, mulB10, (U64 *)MulTbl[itr][10]); mulB11 = select64(k, mulB11, (U64 *)MulTbl[itr][11]); mulB12 = select64(k, mulB12, (U64 *)MulTbl[itr][12]); mulB13 = select64(k, mulB13, (U64 *)MulTbl[itr][13]); mulB14 = select64(k, mulB14, (U64 *)MulTbl[itr][14]); mulB15 = select64(k, mulB15, (U64 *)MulTbl[itr][15]); mulB16 = select64(k, mulB16, (U64 *)MulTbl[itr][16]); mulB17 = select64(k, mulB17, (U64 *)MulTbl[itr][17]); mulB18 = select64(k, mulB18, (U64 *)MulTbl[itr][18]); mulB19 = select64(k, mulB19, (U64 *)MulTbl[itr][19]); k = k_new; } inpB_mb8[0] = mulB00; inpB_mb8[1] = mulB01; inpB_mb8[2] = mulB02; inpB_mb8[3] = mulB03; inpB_mb8[4] = mulB04; inpB_mb8[5] = mulB05; inpB_mb8[6] = mulB06; inpB_mb8[7] = mulB07; inpB_mb8[8] = mulB08; inpB_mb8[9] = mulB09; inpB_mb8[10] = mulB10; inpB_mb8[11] = mulB11; inpB_mb8[12] = mulB12; inpB_mb8[13] = mulB13; inpB_mb8[14] = mulB14; inpB_mb8[15] = mulB15; inpB_mb8[16] = mulB16; inpB_mb8[17] = mulB17; inpB_mb8[18] = mulB18; inpB_mb8[19] = mulB19; for (itr = 0; itr < 20; itr++) { U64 Yi; U64 Bi = inpB_mb8[itr]; fma52lo_mem(res00, res00, Bi, inpA_mb8, 64 * 0); fma52lo_mem(res01, res01, Bi, inpA_mb8, 64 * 1); fma52lo_mem(res02, res02, Bi, inpA_mb8, 64 * 2); fma52lo_mem(res03, res03, Bi, inpA_mb8, 64 * 3); fma52lo_mem(res04, res04, Bi, inpA_mb8, 64 * 4); fma52lo_mem(res05, res05, Bi, inpA_mb8, 64 * 5); fma52lo_mem(res06, res06, Bi, inpA_mb8, 64 * 6); fma52lo_mem(res07, res07, Bi, inpA_mb8, 64 * 7); fma52lo_mem(res08, res08, Bi, inpA_mb8, 64 * 8); fma52lo_mem(res09, res09, Bi, inpA_mb8, 64 * 9); fma52lo_mem(res10, res10, Bi, inpA_mb8, 64 * 10); fma52lo_mem(res11, res11, Bi, inpA_mb8, 64 * 11); fma52lo_mem(res12, res12, Bi, inpA_mb8, 64 * 12); fma52lo_mem(res13, res13, Bi, inpA_mb8, 64 * 13); fma52lo_mem(res14, res14, Bi, inpA_mb8, 64 * 14); fma52lo_mem(res15, res15, Bi, inpA_mb8, 64 * 15); fma52lo_mem(res16, res16, Bi, inpA_mb8, 64 * 16); fma52lo_mem(res17, res17, Bi, inpA_mb8, 64 * 17); fma52lo_mem(res18, res18, Bi, inpA_mb8, 64 * 18); fma52lo_mem(res19, res19, Bi, inpA_mb8, 64 * 19); Yi = fma52lo(get_zero64(), res00, K); fma52lo_mem(res00, res00, Yi, inpM_mb8, 64 * 0); fma52lo_mem(res01, res01, Yi, inpM_mb8, 64 * 1); fma52lo_mem(res02, res02, Yi, inpM_mb8, 64 * 2); fma52lo_mem(res03, res03, Yi, inpM_mb8, 64 * 3); fma52lo_mem(res04, res04, Yi, inpM_mb8, 64 * 4); fma52lo_mem(res05, res05, Yi, inpM_mb8, 64 * 5); fma52lo_mem(res06, res06, Yi, inpM_mb8, 64 * 6); fma52lo_mem(res07, res07, Yi, inpM_mb8, 64 * 7); fma52lo_mem(res08, res08, Yi, inpM_mb8, 64 * 8); fma52lo_mem(res09, res09, Yi, inpM_mb8, 64 * 9); fma52lo_mem(res10, res10, Yi, inpM_mb8, 64 * 10); fma52lo_mem(res11, res11, Yi, inpM_mb8, 64 * 11); fma52lo_mem(res12, res12, Yi, inpM_mb8, 64 * 12); fma52lo_mem(res13, res13, Yi, inpM_mb8, 64 * 13); fma52lo_mem(res14, res14, Yi, inpM_mb8, 64 * 14); fma52lo_mem(res15, res15, Yi, inpM_mb8, 64 * 15); fma52lo_mem(res16, res16, Yi, inpM_mb8, 64 * 16); fma52lo_mem(res17, res17, Yi, inpM_mb8, 64 * 17); fma52lo_mem(res18, res18, Yi, inpM_mb8, 64 * 18); fma52lo_mem(res19, res19, Yi, inpM_mb8, 64 * 19); res00 = srli64(res00, DIGIT_SIZE); res01 = add64(res01, res00); fma52hi_mem(res00, res01, Bi, inpA_mb8, 64 * 0); fma52hi_mem(res01, res02, Bi, inpA_mb8, 64 * 1); fma52hi_mem(res02, res03, Bi, inpA_mb8, 64 * 2); fma52hi_mem(res03, res04, Bi, inpA_mb8, 64 * 3); fma52hi_mem(res04, res05, Bi, inpA_mb8, 64 * 4); fma52hi_mem(res05, res06, Bi, inpA_mb8, 64 * 5); fma52hi_mem(res06, res07, Bi, inpA_mb8, 64 * 6); fma52hi_mem(res07, res08, Bi, inpA_mb8, 64 * 7); fma52hi_mem(res08, res09, Bi, inpA_mb8, 64 * 8); fma52hi_mem(res09, res10, Bi, inpA_mb8, 64 * 9); fma52hi_mem(res10, res11, Bi, inpA_mb8, 64 * 10); fma52hi_mem(res11, res12, Bi, inpA_mb8, 64 * 11); fma52hi_mem(res12, res13, Bi, inpA_mb8, 64 * 12); fma52hi_mem(res13, res14, Bi, inpA_mb8, 64 * 13); fma52hi_mem(res14, res15, Bi, inpA_mb8, 64 * 14); fma52hi_mem(res15, res16, Bi, inpA_mb8, 64 * 15); fma52hi_mem(res16, res17, Bi, inpA_mb8, 64 * 16); fma52hi_mem(res17, res18, Bi, inpA_mb8, 64 * 17); fma52hi_mem(res18, res19, Bi, inpA_mb8, 64 * 18); fma52hi_mem(res19, get_zero64(), Bi, inpA_mb8, 64 * 19); fma52hi_mem(res00, res00, Yi, inpM_mb8, 64 * 0); fma52hi_mem(res01, res01, Yi, inpM_mb8, 64 * 1); fma52hi_mem(res02, res02, Yi, inpM_mb8, 64 * 2); fma52hi_mem(res03, res03, Yi, inpM_mb8, 64 * 3); fma52hi_mem(res04, res04, Yi, inpM_mb8, 64 * 4); fma52hi_mem(res05, res05, Yi, inpM_mb8, 64 * 5); fma52hi_mem(res06, res06, Yi, inpM_mb8, 64 * 6); fma52hi_mem(res07, res07, Yi, inpM_mb8, 64 * 7); fma52hi_mem(res08, res08, Yi, inpM_mb8, 64 * 8); fma52hi_mem(res09, res09, Yi, inpM_mb8, 64 * 9); fma52hi_mem(res10, res10, Yi, inpM_mb8, 64 * 10); fma52hi_mem(res11, res11, Yi, inpM_mb8, 64 * 11); fma52hi_mem(res12, res12, Yi, inpM_mb8, 64 * 12); fma52hi_mem(res13, res13, Yi, inpM_mb8, 64 * 13); fma52hi_mem(res14, res14, Yi, inpM_mb8, 64 * 14); fma52hi_mem(res15, res15, Yi, inpM_mb8, 64 * 15); fma52hi_mem(res16, res16, Yi, inpM_mb8, 64 * 16); fma52hi_mem(res17, res17, Yi, inpM_mb8, 64 * 17); fma52hi_mem(res18, res18, Yi, inpM_mb8, 64 * 18); fma52hi_mem(res19, res19, Yi, inpM_mb8, 64 * 19); } // Normalization { U64 T = get_zero64(); // U64 MASK = set64(DIGIT_MASK); T = srli64(res00, DIGIT_SIZE); storeu64(out_mb8 + 8 * 0, res00); res01 = add64(res01, T); T = srli64(res01, DIGIT_SIZE); storeu64(out_mb8 + 8 * 1, res01); res02 = add64(res02, T); T = srli64(res02, DIGIT_SIZE); storeu64(out_mb8 + 8 * 2, res02); res03 = add64(res03, T); T = srli64(res03, DIGIT_SIZE); storeu64(out_mb8 + 8 * 3, res03); res04 = add64(res04, T); T = srli64(res04, DIGIT_SIZE); storeu64(out_mb8 + 8 * 4, res04); res05 = add64(res05, T); T = srli64(res05, DIGIT_SIZE); storeu64(out_mb8 + 8 * 5, res05); res06 = add64(res06, T); T = srli64(res06, DIGIT_SIZE); storeu64(out_mb8 + 8 * 6, res06); res07 = add64(res07, T); T = srli64(res07, DIGIT_SIZE); storeu64(out_mb8 + 8 * 7, res07); res08 = add64(res08, T); T = srli64(res08, DIGIT_SIZE); storeu64(out_mb8 + 8 * 8, res08); res09 = add64(res09, T); T = srli64(res09, DIGIT_SIZE); storeu64(out_mb8 + 8 * 9, res09); res10 = add64(res10, T); T = srli64(res10, DIGIT_SIZE); storeu64(out_mb8 + 8 * 10, res10); res11 = add64(res11, T); T = srli64(res11, DIGIT_SIZE); storeu64(out_mb8 + 8 * 11, res11); res12 = add64(res12, T); T = srli64(res12, DIGIT_SIZE); storeu64(out_mb8 + 8 * 12, res12); res13 = add64(res13, T); T = srli64(res13, DIGIT_SIZE); storeu64(out_mb8 + 8 * 13, res13); res14 = add64(res14, T); T = srli64(res14, DIGIT_SIZE); storeu64(out_mb8 + 8 * 14, res14); res15 = add64(res15, T); T = srli64(res15, DIGIT_SIZE); storeu64(out_mb8 + 8 * 15, res15); res16 = add64(res16, T); T = srli64(res16, DIGIT_SIZE); storeu64(out_mb8 + 8 * 16, res16); res17 = add64(res17, T); T = srli64(res17, DIGIT_SIZE); storeu64(out_mb8 + 8 * 17, res17); res18 = add64(res18, T); T = srli64(res18, DIGIT_SIZE); storeu64(out_mb8 + 8 * 18, res18); res19 = add64(res19, T); storeu64(out_mb8 + 8 * 19, res19); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/000077500000000000000000000000001470420105600245175ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/ifma_arith_nsm2.c000066400000000000000000000143411470420105600277300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Constants */ #define LEN52 NUMBER_OF_DIGITS(256,DIGIT_SIZE) /* // EC SM2 prime base point order // in 2^52 radix */ __ALIGN64 static const int64u nsm2_mb[LEN52][8] = { { REP8_DECL(0x000bf40939d54123) }, { REP8_DECL(0x0006b21c6052b53b) }, { REP8_DECL(0x000fffffff7203df) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000fffffffeffff) } }; __ALIGN64 static const int64u nsm2x2_mb[LEN52][8] = { { REP8_DECL(0x0007e81273aa8246) }, { REP8_DECL(0x000d6438c0a56a77) }, { REP8_DECL(0x000ffffffee407be) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0001fffffffdffff) } }; /* k0 = -( (1/nsm2 mod 2^DIGIT_SIZE) ) mod 2^DIGIT_SIZE */ __ALIGN64 static const int64u nsm2_k0_mb[8] = { REP8_DECL(0x000f9e8872350975) }; /* to Montgomery conversion constant // rr = 2^((LEN52*DIGIT_SIZE)*2) mod nsm2 */ __ALIGN64 static const int64u nsm2_rr_mb[LEN52][8] = { { REP8_DECL(0x000c16674a517de6) }, { REP8_DECL(0x000507a6e5f7c418) }, { REP8_DECL(0x000fe0d44507dc1c) }, { REP8_DECL(0x0003b620fc84c3af) }, { REP8_DECL(0x0000b5e412c02b3d) } }; /*===================================================================== Specialized single operations in nsm2 - sqr & mul =====================================================================*/ EXTERN_C U64* MB_FUNC_NAME(ifma_nsm2_)(void) { return (U64*)nsm2_mb; } void MB_FUNC_NAME(ifma_ams52_nsm2_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_ams52x5_)(r, a, (U64*)nsm2_mb, nsm2_k0_mb); } void MB_FUNC_NAME(ifma_amm52_nsm2_)(U64 r[], const U64 a[], const U64 b[]) { MB_FUNC_NAME(ifma_amm52x5_)(r, a, b, (U64*)nsm2_mb, nsm2_k0_mb); } void MB_FUNC_NAME(ifma_tomont52_nsm2_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52x5_)(r, a, (U64*)nsm2_rr_mb, (U64*)nsm2_mb, nsm2_k0_mb); } void MB_FUNC_NAME(ifma_frommont52_nsm2_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_amm52_nsm2_)(r, a, (U64*)ones); MB_FUNC_NAME(ifma_fastred52_pnsm2_)(r, r); } /* // computes r = 1/z = z^(nsm2-2) mod nsm2 // // note: z in in Montgomery domain (as soon mul() and sqr() below are amm-functions // r in Montgomery domain too */ #define sqr_nsm2 MB_FUNC_NAME(ifma_ams52_nsm2_) #define mul_nsm2 MB_FUNC_NAME(ifma_amm52_nsm2_) void MB_FUNC_NAME(ifma_aminv52_nsm2_)(U64 r[], const U64 z[]) { int i; // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 U64 pwr_z_Tbl[16][LEN52]; MB_FUNC_NAME(ifma_tomont52_nsm2_)(pwr_z_Tbl[0], (U64*)ones); MB_FUNC_NAME(mov_FESM2_)(pwr_z_Tbl[1], z); for(i=2; i<16; i+=2) { sqr_nsm2(pwr_z_Tbl[i], pwr_z_Tbl[i/2]); mul_nsm2(pwr_z_Tbl[i+1], pwr_z_Tbl[i], z); } // pwr = (nsm2-2) in big endian int8u pwr[] = "\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x72\x03\xDF\x6B\x21\xC6\x05\x2B" "\x53\xBB\xF4\x09\x39\xD5\x41\x21"; // init r = 1 MB_FUNC_NAME(mov_FESM2_)(r, pwr_z_Tbl[0]); for(i=0; i<32; i++) { int v = pwr[i]; int hi = (v>>4) &0xF; int lo = v & 0xF; sqr_nsm2(r, r); sqr_nsm2(r, r); sqr_nsm2(r, r); sqr_nsm2(r, r); if(hi) mul_nsm2(r, r, pwr_z_Tbl[hi]); sqr_nsm2(r, r); sqr_nsm2(r, r); sqr_nsm2(r, r); sqr_nsm2(r, r); if(lo) mul_nsm2(r, r, pwr_z_Tbl[lo]); } } /*===================================================================== Specialized single operations in nsm2 - add, sub & neg =====================================================================*/ void MB_FUNC_NAME(ifma_add52_nsm2_)(U64 r[], const U64 a[], const U64 b[]) { MB_FUNC_NAME(ifma_add52x5_)(r, a, b, (U64*)nsm2x2_mb); } void MB_FUNC_NAME(ifma_sub52_nsm2_)(U64 r[], const U64 a[], const U64 b[]) { MB_FUNC_NAME(ifma_sub52x5_)(r, a, b, (U64*)nsm2x2_mb); } void MB_FUNC_NAME(ifma_neg52_nsm2_)(U64 r[], const U64 a[]) { MB_FUNC_NAME(ifma_neg52x5_)(r, a, (U64*)nsm2x2_mb); } static __mb_mask MB_FUNC_NAME(lt_mbx_digit_)(const U64 a, const U64 b, const __mb_mask lt_mask) { U64 d = mask_sub64(sub64(a, b), lt_mask, sub64(a, b), set1(1)); return cmp64_mask(d, get_zero64(), _MM_CMPINT_LT); } /* r = (a>=nsm2)? a-nsm2 : a */ void MB_FUNC_NAME(ifma_fastred52_pnsm2_)(U64 R[], const U64 A[]) { /* r = a - b */ U64 r0 = sub64(A[0], ((U64*)(nsm2_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(nsm2_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(nsm2_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(nsm2_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(nsm2_mb))[4]); /* lt = {r0 - r4} < 0 */ __mb_mask lt = MB_FUNC_NAME(lt_mbx_digit_)(r0, get_zero64(), 0); lt = MB_FUNC_NAME(lt_mbx_digit_)(r1, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r2, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r3, get_zero64(), lt); lt = MB_FUNC_NAME(lt_mbx_digit_)(r4, get_zero64(), lt); r0 = mask_mov64(A[0], ~lt, r0); r1 = mask_mov64(A[1], ~lt, r1); r2 = mask_mov64(A[2], ~lt, r2); r3 = mask_mov64(A[3], ~lt, r3); r4 = mask_mov64(A[4], ~lt, r4); /* normalize r0 - r4 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) R[0] = r0; R[1] = r1; R[2] = r2; R[3] = r3; R[4] = r4; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_nsm2_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FESM2_)(a,(const U64 (*))nsm2_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_nsm2_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FESM2_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_nsm2_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/ifma_arith_psm2.c000066400000000000000000000325221470420105600277330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // prime256 = 2^256 - 2^224 - 2^96 + 2^64 - 1 // in 2^52 radix */ __ALIGN64 static const int64u psm2_mb[PSM2_LEN52][8] = { { REP8_DECL(0xfffffffffffff) }, { REP8_DECL(0xff00000000fff) }, { REP8_DECL(0xfffffffffffff) }, { REP8_DECL(0xfffffffffffff) }, { REP8_DECL(0x0fffffffeffff) } }; __ALIGN64 static const int64u psm2x2_mb[PSM2_LEN52][8] = { { REP8_DECL(0xffffffffffffe) }, { REP8_DECL(0xfe00000001fff) }, { REP8_DECL(0xfffffffffffff) }, { REP8_DECL(0xfffffffffffff) }, { REP8_DECL(0x1fffffffdffff) } }; /* to Montgomery conversion constant // rr = 2^((PSM2_LEN52*DIGIT_SIZE)*2) mod psm2 */ __ALIGN64 static const int64u psm2_rr_mb[PSM2_LEN52][8] = { { REP8_DECL(0x0020000000300) }, { REP8_DECL(0xffffffff00000) }, { REP8_DECL(0x0000100000002) }, { REP8_DECL(0x0200000001000) }, { REP8_DECL(0x0000004000000) } }; /* other constants */ __ALIGN64 static const int64u VDIGIT_MASK_[8] = {DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK, DIGIT_MASK}; #define VDIGIT_MASK loadu64(VDIGIT_MASK_) #define ROUND_MUL(I, J, LO, HI) \ LO = fma52lo(LO, va[I], vb[J]); \ HI = fma52hi(HI, va[I], vb[J]) //TODO: reduction #define MUL_ADD_PSM2(u, res0, res1, res2, res3, res4, res5) \ { \ /* a * ( 2^52 - 1 ) = 2^52 * a - a */ \ U64 u = and64(res0, VDIGIT_MASK); \ /* res0 = sub64(res0, u); */ /* Zero out low 52 bits */ \ res1 = add64(res1, srli64(res0, DIGIT_SIZE)); /* Carry propagation */ \ res1 = add64(res1, u); \ res1 = fma52lo(res1, u, ((U64*)psm2_mb)[1]); \ res2 = fma52hi(res2, u, ((U64*)psm2_mb)[1]); \ res2 = sub64(res2, u); \ res4 = add64(res4, u); \ res4 = fma52lo(res4, u, ((U64*)psm2_mb)[4]); \ res5 = fma52hi(res5, u, ((U64*)psm2_mb)[4]); \ } void MB_FUNC_NAME(ifma_amm52_psm2_)(U64 r[], const U64 va[], const U64 vb[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // full multiplication ROUND_MUL(0, 0, r0, r1); ROUND_MUL(1, 0, r1, r2); ROUND_MUL(2, 0, r2, r3); ROUND_MUL(3, 0, r3, r4); ROUND_MUL(4, 0, r4, r5); ROUND_MUL(0, 1, r1, r2); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 1, r3, r4); ROUND_MUL(3, 1, r4, r5); ROUND_MUL(4, 1, r5, r6); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(3, 2, r5, r6); ROUND_MUL(4, 2, r6, r7); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(2, 3, r5, r6); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 3, r7, r8); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(4, 4, r8, r9); //reduction MUL_ADD_PSM2(u0, r0, r1, r2, r3, r4, r5); MUL_ADD_PSM2(u1, r1, r2, r3, r4, r5, r6); MUL_ADD_PSM2(u2, r2, r3, r4, r5, r6, r7); MUL_ADD_PSM2(u3, r3, r4, r5, r6, r7, r8); MUL_ADD_PSM2(u4, r4, r5, r6, r7, r8, r9); NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) NORM_LSHIFTR(r, 7, 8) NORM_LSHIFTR(r, 8, 9) r[0] = r5; r[1] = r6; r[2] = r7; r[3] = r8; r[4] = r9; } void MB_FUNC_NAME(ifma_ams52_psm2_)(U64 r[], const U64 va[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); const U64* vb = va; ROUND_MUL(0, 1, r1, r2); ROUND_MUL(0, 2, r2, r3); ROUND_MUL(0, 3, r3, r4); ROUND_MUL(0, 4, r4, r5); ROUND_MUL(1, 4, r5, r6); ROUND_MUL(2, 4, r6, r7); ROUND_MUL(3, 4, r7, r8); ROUND_MUL(1, 2, r3, r4); ROUND_MUL(1, 3, r4, r5); ROUND_MUL(2, 3, r5, r6); r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); ROUND_MUL(0, 0, r0, r1); ROUND_MUL(1, 1, r2, r3); ROUND_MUL(2, 2, r4, r5); ROUND_MUL(3, 3, r6, r7); ROUND_MUL(4, 4, r8, r9); //reduction MUL_ADD_PSM2(u0, r0, r1, r2, r3, r4, r5); MUL_ADD_PSM2(u1, r1, r2, r3, r4, r5, r6); MUL_ADD_PSM2(u2, r2, r3, r4, r5, r6, r7); MUL_ADD_PSM2(u3, r3, r4, r5, r6, r7, r8); MUL_ADD_PSM2(u4, r4, r5, r6, r7, r8, r9); NORM_LSHIFTR(r, 5, 6) NORM_LSHIFTR(r, 6, 7) NORM_LSHIFTR(r, 7, 8) NORM_LSHIFTR(r, 8, 9) r[0] = r5; r[1] = r6; r[2] = r7; r[3] = r8; r[4] = r9; } #define sqr_psm2 MB_FUNC_NAME(ifma_ams52_psm2_) #define mul_psm2 MB_FUNC_NAME(ifma_amm52_psm2_) #define sqr_psm2_x2(res,target) \ { \ sqr_psm2(res,target); \ sqr_psm2(res,res); \ } #define sqr_psm2_x4(res,target) \ { \ sqr_psm2_x2(res,target); \ sqr_psm2_x2(res,res); \ } #define sqr_psm2_x8(res,target) \ { \ sqr_psm2_x4(res,target); \ sqr_psm2_x4(res,res); \ } #define sqr_psm2_x16(res,target) \ { \ sqr_psm2_x8(res,target); \ sqr_psm2_x8(res,res); \ } #define sqr_psm2_x32(res,target) \ { \ sqr_psm2_x16(res,target); \ sqr_psm2_x16(res,res); \ } #define sqr_psm2_x64(res,target) \ { \ sqr_psm2_x32(res,target); \ sqr_psm2_x32(res,res); \ } void MB_FUNC_NAME(ifma_aminv52_psm2_)(U64 r[], const U64 z[]) { __ALIGN64 U64 tmp1[PSM2_LEN52]; __ALIGN64 U64 tmp2[PSM2_LEN52]; __ALIGN64 U64 D[PSM2_LEN52]; __ALIGN64 U64 E[PSM2_LEN52]; __ALIGN64 U64 F[PSM2_LEN52]; sqr_psm2(tmp1,z); mul_psm2(F,tmp1,z); /* F = z^3 */ /* tmp2 = z^0xC */ sqr_psm2_x2(tmp2,F); mul_psm2(D, tmp2, z); /* D = z^0xD */ mul_psm2(E, tmp2, tmp1); /* E = z^0xE */ mul_psm2(F, tmp2, F); /* F = z^0xF */ /* tmp2 = z^0xF0 */ sqr_psm2_x4(tmp2,F); mul_psm2(D, tmp2, D); /* D = z^0xFD */ mul_psm2(E, tmp2, E); /* E = z^0xFE */ mul_psm2(F, tmp2, F); /* F = z^0xFF */ /* tmp2 = z^0xFF00 */ sqr_psm2_x8(tmp2,F); mul_psm2(D, tmp2, D); /* D = z^0xFFFD */ mul_psm2(E, tmp2, E); /* E = z^0xFFFE */ mul_psm2(F, tmp2, F); /* F = z^0xFFFF */ /* tmp2 = z^0xFFFF0000 */ sqr_psm2_x16(tmp2,F); mul_psm2(D, tmp2, D); /* D = z^0xFFFFFFFD */ mul_psm2(E, tmp2, E); /* E = z^0xFFFFFFFE */ mul_psm2(F, tmp2, F); /* F = z^0xFFFFFFFF */ /* z ^ FFFFFFFE 00000000 */ sqr_psm2_x32(r,E); /* z ^ FFFFFFFE FFFFFFFF */ mul_psm2(r,r,F); /* z ^ FFFFFFFE FFFFFFFF 00000000 */ sqr_psm2_x32(r,r); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF */ mul_psm2(r,r,F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF 00000000 */ sqr_psm2_x32(r,r); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF */ mul_psm2(r,r,F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 00000000 */ sqr_psm2_x32(r,r); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF */ mul_psm2(r,r,F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 00000000 */ sqr_psm2_x64(r,r); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF */ mul_psm2(r,r,F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF 00000000 */ sqr_psm2_x32(r,r); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFD */ mul_psm2(r,r,D); } void MB_FUNC_NAME(ifma_reduce52_psm2_)(U64 R[], const U64 A[]) { /* r = a - p384_mb */ U64 r0 = sub64(A[0], ((U64*)(psm2_mb))[0]); U64 r1 = sub64(A[1], ((U64*)(psm2_mb))[1]); U64 r2 = sub64(A[2], ((U64*)(psm2_mb))[2]); U64 r3 = sub64(A[3], ((U64*)(psm2_mb))[3]); U64 r4 = sub64(A[4], ((U64*)(psm2_mb))[4]); /* normalize r0 - r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) /* r = a> 1 */ mask = sub64(get_zero64(), and64(t1, one)); t0 = add64(t0, and64(base, mask)); t0 = srli64(t0, 1); mask = sub64(get_zero64(), and64(t2, one)); t1 = add64(t1, and64(base, mask)); t1 = srli64(t1, 1); mask = sub64(get_zero64(), and64(t3, one)); t2 = add64(t2, and64(base, mask)); t2 = srli64(t2, 1); mask = sub64(get_zero64(), and64(t4, one)); t3 = add64(t3, and64(base, mask)); t3 = srli64(t3, 1); t4 = srli64(t4, 1); /* normalize t0, t1, t2, t3, t4 */ NORM_LSHIFTR(t, 0,1) NORM_LSHIFTR(t, 1,2) NORM_LSHIFTR(t, 2,3) NORM_LSHIFTR(t, 3,4) r[0] = t0; r[1] = t1; r[2] = t2; r[3] = t3; r[4] = t4; } __mb_mask MB_FUNC_NAME(ifma_cmp_lt_psm2_)(const U64 a[]) { return MB_FUNC_NAME(cmp_lt_FESM2_)(a,(const U64 (*))psm2_mb); } __mb_mask MB_FUNC_NAME(ifma_check_range_psm2_)(const U64 A[]) { __mb_mask mask = MB_FUNC_NAME(is_zero_FESM2_)(A); mask |= ~MB_FUNC_NAME(ifma_cmp_lt_psm2_)(A); return mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/ifma_ecdh_sm2.c000066400000000000000000000114701470420105600273460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE /* // Computes shared key // pa_shared_key[] array of pointers to the shared keys // pa_skey[] array of pointers to the own (ephemeral) private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer // // Note: // input party's public key depends on is pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates // or // - in (x:y) affine coordinate */ DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecdh_ssl_mb8)(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const BIGNUM* skey = pa_skey[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey|| NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecdh_ssl_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecdh_mb8)(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_pubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int8u* shared = pa_shared_key[buf_no]; const int64u* skey = pa_skey[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==skey || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecdh_mb8(pa_shared_key, pa_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/ifma_ecdsa_sm2.c000077500000000000000000000326751470420105600275370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* // Computes SM2 ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_user_id[] array of pointers to the users ID // user_id_len[] array of users ID length // pa_msg[] array of pointers to the messages are being signed // msg_len[] array of messages length // pa_eph_skey[] array of pointers to the signer's ephemeral private keys // pa_reg_skey[] array of pointers to the signer's regular private keys // pa_pubx[] array of pointers to the party's public keys X-coordinates // pa_puby[] array of pointers to the party's public keys Y-coordinates // pa_pubz[] array of pointers to the party's public keys Z-coordinates // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecdsa_sign_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_user_id || NULL==user_id_len || NULL==pa_msg || NULL==msg_len || NULL==pa_eph_skey || NULL==pa_reg_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } int user_id_len_checked[8]; /* check pointers and values */ for(int buf_no=0; buf_no<8; buf_no++) { const int8u* r = pa_sign_r[buf_no]; const int8u* s = pa_sign_s[buf_no]; const int8u* id = pa_user_id[buf_no]; const int8u* msg = pa_msg[buf_no]; const int64u* eph_key = pa_eph_skey[buf_no]; const int64u* reg_key = pa_reg_skey[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; user_id_len_checked[buf_no] = user_id_len[buf_no]; /* if any of pointer NULL set error status */ if(NULL==r || NULL==s || NULL==id || NULL==msg || NULL==eph_key || NULL==reg_key || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } if (msg_len[buf_no] < 0) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } if ((user_id_len[buf_no] > 0xFFFF) || (user_id_len[buf_no] < 0)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); user_id_len_checked[buf_no] = 0; } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecdsa_sign_mb8(pa_sign_r, pa_sign_s, pa_user_id, user_id_len, pa_msg, msg_len, pa_eph_skey, \ pa_reg_skey, pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords, user_id_len_checked); #else MBX_UNREFERENCED_PARAMETER(user_id_len_checked); status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // Verifies SM2 ECDSA signature // pa_sign_r[] array of pointers to the computed r-components of the signatures // pa_sign_s[] array of pointers to the computed s-components of the signatures // pa_msg[] array of pointers to the messages that have been signed // pa_user_id[] array of pointers to the users ID // user_id_len[] array of users ID length // pa_msg[] array of pointers to the messages are being signed // msg_len[] array of messages length // pa_pubx[] array of pointers to the signer's public keys X-coordinates // pa_puby[] array of pointers to the signer's public keys Y-coordinates // pa_pubz[] array of pointers to the signer's public keys Z-coordinates (or NULL, if affine coordinate requested) // pBuffer pointer to the scratch buffer */ DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecdsa_verify_mb8)(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_user_id || NULL==user_id_len || NULL==pa_msg || NULL==msg_len || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } int user_id_len_checked[8]; /* check pointers and values */ for(int buf_no=0; buf_no<8; buf_no++) { const int8u* r = pa_sign_r[buf_no]; const int8u* s = pa_sign_s[buf_no]; const int8u* id = pa_user_id[buf_no]; const int8u* msg = pa_msg[buf_no]; const int64u* pubx = pa_pubx[buf_no]; const int64u* puby = pa_puby[buf_no]; const int64u* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; user_id_len_checked[buf_no] = user_id_len[buf_no]; /* if any of pointer NULL set error status */ if(NULL==r || NULL==s || NULL==id || NULL==msg || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } if (msg_len[buf_no] < 0) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } if ((user_id_len[buf_no] > 0xFFFF) || (user_id_len[buf_no] < 0)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); user_id_len_checked[buf_no] = 0; } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecdsa_verify_mb8(pa_sign_r, pa_sign_s, pa_user_id, user_id_len, pa_msg, msg_len, pa_pubx, pa_puby, \ pa_pubz, pBuffer, use_jproj_coords, user_id_len_checked); #else MBX_UNREFERENCED_PARAMETER(user_id_len_checked); status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } /* // OpenSSL's specific implementations */ #ifndef BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecdsa_sign_ssl_mb8)(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_sign_r || NULL==pa_sign_s || NULL==pa_user_id || NULL==user_id_len || NULL==pa_msg || NULL==msg_len || NULL==pa_eph_skey || NULL==pa_reg_skey || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } int user_id_len_checked[8]; /* check pointers and values */ for(int buf_no=0; buf_no<8; buf_no++) { const int8u* r = pa_sign_r[buf_no]; const int8u* s = pa_sign_s[buf_no]; const int8u* id = pa_user_id[buf_no]; const int8u* msg = pa_msg[buf_no]; const BIGNUM* eph_key = pa_eph_skey[buf_no]; const BIGNUM* reg_key = pa_reg_skey[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; user_id_len_checked[buf_no] = user_id_len[buf_no]; /* if any of pointer NULL set error status */ if(NULL==r || NULL==s || NULL==id || NULL==msg || NULL==eph_key || NULL==reg_key || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } if (msg_len[buf_no] < 0) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } if ((user_id_len[buf_no] > 0xFFFF) || (user_id_len[buf_no] < 0)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); user_id_len_checked[buf_no] = 0; } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecdsa_sign_ssl_mb8(pa_sign_r, pa_sign_s, pa_user_id, user_id_len, pa_msg, msg_len, pa_eph_skey, pa_reg_skey, \ pa_pubx, pa_puby, pa_pubz, pBuffer, use_jproj_coords, user_id_len_checked); #else MBX_UNREFERENCED_PARAMETER(user_id_len_checked); status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecdsa_verify_ssl_mb8)(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer) { mbx_status status = 0; int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_sig || NULL==pa_user_id || NULL==user_id_len || NULL==pa_msg || NULL==msg_len || NULL==pa_pubx || NULL==pa_puby) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } int user_id_len_checked[8]; /* check pointers and values */ for(int buf_no=0; buf_no<8; buf_no++) { const ECDSA_SIG* sig = pa_sig[buf_no]; const int8u* id = pa_user_id[buf_no]; const int8u* msg = pa_msg[buf_no]; const BIGNUM* pubx = pa_pubx[buf_no]; const BIGNUM* puby = pa_puby[buf_no]; const BIGNUM* pubz = use_jproj_coords? pa_pubz[buf_no] : NULL; user_id_len_checked[buf_no] = user_id_len[buf_no]; /* if any of pointer NULL set error status */ if(NULL==sig || NULL==id || NULL==msg || NULL==pubx || NULL==puby || (use_jproj_coords && NULL==pubz)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } if (msg_len[buf_no] < 0) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } if ((user_id_len[buf_no] > 0xFFFF) || (user_id_len[buf_no] < 0)) { status |= MBX_SET_STS(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); user_id_len_checked[buf_no] = 0; } } if(!MBX_IS_ANY_OK_STS(status) ) return status; #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecdsa_verify_ssl_mb8(pa_sig, pa_user_id, user_id_len, pa_msg, msg_len, pa_pubx, pa_puby, pa_pubz, pBuffer, \ use_jproj_coords, user_id_len_checked); #else MBX_UNREFERENCED_PARAMETER(user_id_len_checked); status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif /* BN_OPENSSL_DISABLE */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/ifma_ecpoint_sm2.c000066400000000000000000000531221470420105600301040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* simplify naming */ #define sqr MB_FUNC_NAME(ifma_ams52_psm2_) #define mul MB_FUNC_NAME(ifma_amm52_psm2_) #define add MB_FUNC_NAME(ifma_add52_psm2_) #define sub MB_FUNC_NAME(ifma_sub52_psm2_) #define mul2 MB_FUNC_NAME(ifma_double52_psm2_) #define mul3 MB_FUNC_NAME(ifma_tripple52_psm2_) #define div2 MB_FUNC_NAME(ifma_half52_psm2_) /* // Presentation of point at infinity: // - projective (X : Y : 0) // - affine (0 : 0) */ /* // R(X3:Y3:Z3) = [2]P(X1:Y1:Z1) // // formulas: // A = 4*X1*Y1^2 // B = 3*(X1^2-Z1^4) // X3= B^2 -2*A // Y3= B*(A-X3) -8*Y1^4 // Z3= 2*Y1*Z1 // // cost: 4S+4M+9A // */ void MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(SM2_POINT* r, const SM2_POINT* p) { __ALIGN64 U64 T[PSM2_LEN52]; __ALIGN64 U64 U[PSM2_LEN52]; __ALIGN64 U64 V[PSM2_LEN52]; __ALIGN64 U64 A[PSM2_LEN52]; __ALIGN64 U64 B[PSM2_LEN52]; const U64* X1 = p->X; /* input point */ const U64* Y1 = p->Y; const U64* Z1 = p->Z; U64* X3 = r->X; /* output point */ U64* Y3 = r->Y; U64* Z3 = r->Z; mul2(T, Y1); /* T = 2*Y1 */ sqr(V, T); /* V = 4*Y1^2 */ /* sqr_dual */ sqr(U, Z1); /* U = Z1^2 */ sub(B, X1, U); /* B = X1-Z1^2 */ add(U, X1, U); /* U = X1+Z1^2 */ mul(A, V, X1); /* A = 4*X*Y1^2 */ /* mul_dual */ mul(B, B, U); /* B = (X1^2-Z1^4) */ mul2(X3, A); /* X3 = 2*A */ mul3(B, B); /* B = 3*(X1^2-Z1^4) */ sqr(U, B); /* U = B^2 */ /* sqr_dual */ sqr(Y3, V); /* Y3= V^2 = 16*Y1^4 */ sub(X3, U, X3); /* X3=B^2 - 2*A */ div2(Y3,Y3); /* Y3=Y3/2 = 8*Y1^4 */ sub(U, A, X3); /* U = A-X3 */ mul(Z3, T, Z1); /* Z3= 2*Y1*Z1 */ /* mul_dual */ mul(U, U, B); /* U = B*(A-X3) */ sub(Y3, U, Y3); /* Y3 = B*(A-X3) -8*Y1^4 */ } /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // cost: 4S+12M+7A // */ void MB_FUNC_NAME(ifma_ec_sm2_add_point_)(SM2_POINT* r, const SM2_POINT* p, const SM2_POINT* q) { /* coordinates of p */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q */ const U64* X2 = q->X; const U64* Y2 = q->Y; const U64* Z2 = q->Z; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->Z); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[PSM2_LEN52]; __ALIGN64 U64 Y3[PSM2_LEN52]; __ALIGN64 U64 Z3[PSM2_LEN52]; /* temporary */ __ALIGN64 U64 U1[PSM2_LEN52]; __ALIGN64 U64 U2[PSM2_LEN52]; __ALIGN64 U64 S1[PSM2_LEN52]; __ALIGN64 U64 S2[PSM2_LEN52]; __ALIGN64 U64 H[PSM2_LEN52]; __ALIGN64 U64 R[PSM2_LEN52]; mul(S1, Y1, Z2); /* S1 = Y1*Z2 */ sqr(U1, Z2); /* U1 = Z2^2 */ mul(S2, Y2, Z1); /* S2 = Y2*Z1 */ sqr(U2, Z1); /* U2 = Z1^2 */ mul(S1, S1, U1); /* S1 = Y1*Z2^3 */ mul(S2, S2, U2); /* S2 = Y2*Z1^3 */ mul(U1, X1, U1); /* U1 = X1*Z2^2 */ mul(U2, X2, U2); /* U2 = X2*Z1^2 */ sub(R, S2, S1); /* R = S2-S1 */ sub(H, U2, U1); /* H = U2-U1 */ /* check if affine (p.x:p.y) == (q.x:q.y) and and do doubling if this happens */ __mb_mask x_are_equal = MB_FUNC_NAME(is_zero_FESM2_)(H); __mb_mask y_are_equal = MB_FUNC_NAME(is_zero_FESM2_)(R); __mb_mask points_are_equal = (x_are_equal & y_are_equal & (~p_at_infinity) & (~q_at_infinity)); SM2_POINT P2; MB_FUNC_NAME(set_point_to_infinity_)(&P2); if (points_are_equal) { MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&P2, p); } mul(Z3, Z1, Z2); /* Z3 = Z1*Z2 */ sqr(U2, H); /* U2 = H^2 */ mul(Z3, Z3, H); /* Z3 = (Z1*Z2)*H */ sqr(S2, R); /* S2 = R^2 */ mul(H, H, U2); /* H = H^3 */ mul(U1, U1, U2); /* U1 = U1*H^2 */ sub(X3, S2, H); /* X3 = R^2 - H^3 */ mul2(U2, U1); /* U2 = 2*U1*H^2 */ mul(S1, S1, H); /* S1 = S1*H^3 */ sub(X3, X3, U2); /* X3 = (R^2 - H^3) -2*U1*H^2 */ sub(Y3, U1, X3); /* Y3 = R*(U1*H^2 - X3) -S1*H^3 */ mul(Y3, Y3, R); sub(Y3, Y3, S1); /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FESM2_)(X3, X3, p_at_infinity, q->X); MB_FUNC_NAME(mask_mov_FESM2_)(Y3, Y3, p_at_infinity, q->Y); MB_FUNC_NAME(mask_mov_FESM2_)(Z3, Z3, p_at_infinity, q->Z); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FESM2_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FESM2_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FESM2_)(Z3, Z3, q_at_infinity, p->Z); /* r = points_are_equal? P2 : T */ MB_FUNC_NAME(mask_mov_FESM2_)(r->X, X3, points_are_equal, P2.X); MB_FUNC_NAME(mask_mov_FESM2_)(r->Y, Y3, points_are_equal, P2.Y); MB_FUNC_NAME(mask_mov_FESM2_)(r->Z, Z3, points_are_equal, P2.Z); } /* to Montgomery conversion constant // r = 2^(PSM2_LEN52*DIGIT_SIZE) mod psm2 */ __ALIGN64 static const int64u psm2_r_mb[PSM2_LEN52][sizeof(U64)/sizeof(int64u)] = { { REP8_DECL(0x0000000000000010) }, { REP8_DECL(0x0000ffffffff0000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000000000) }, { REP8_DECL(0x0000000000100000) } }; const U64* MB_FUNC_NAME(ifma_ec_sm2_coord_one_)(void) { return (U64*)psm2_r_mb; } /* // R(X3:Y3:Z3) = P(X1:Y1:Z1) + Q(X2:Y2:Z2=1) // // formulas: // A = X1*Z2^2 B = X2*Z1^2 C = Y1*Z2^3 D = Y2*Z1^3 // E = B-A F = D-C // X3= -E^3 -2*A*E^2 + F^2 // Y3= -C*E^3 + F*(A*E^2 -X3) // Z3= Z1*Z2*E // // if Z2=1, then // A = X1 B = X2*Z1^2 C = Y1 D = Y2*Z1^3 // E = B-X1 F = D-Y1 // X3= -E^3 -2*X1*E^2 + F^2 // Y3= -Y1*E^3 + F*(X1*E^2 -X3) // Z3= Z1*E // // cost: 3S+8M+7A */ void MB_FUNC_NAME(ifma_ec_sm2_add_point_affine_)(SM2_POINT* r, const SM2_POINT* p, const SM2_POINT_AFFINE* q) { /* coordinates of p (projective) */ const U64* X1 = p->X; const U64* Y1 = p->Y; const U64* Z1 = p->Z; __mb_mask p_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(p->Z); /* coordinates of q (affine) */ const U64* X2 = q->x; const U64* Y2 = q->y; __mb_mask q_at_infinity = MB_FUNC_NAME(is_zero_point_cordinate_)(q->x) & MB_FUNC_NAME(is_zero_point_cordinate_)(q->y); /* coordinates of temp point T(X3:Y3:Z3) */ __ALIGN64 U64 X3[PSM2_LEN52]; __ALIGN64 U64 Y3[PSM2_LEN52]; __ALIGN64 U64 Z3[PSM2_LEN52]; __ALIGN64 U64 U2[PSM2_LEN52]; __ALIGN64 U64 S2[PSM2_LEN52]; __ALIGN64 U64 H[PSM2_LEN52]; __ALIGN64 U64 R[PSM2_LEN52]; sqr(R, Z1); // R = Z1^2 mul(S2, Y2, Z1); // S2 = Y2*Z1 mul(U2, X2, R); // U2 = X2*Z1^2 mul(S2, S2, R); // S2 = Y2*Z1^3 sub(H, U2, X1); // H = U2-X1 sub(R, S2, Y1); // R = S2-Y1 mul(Z3, H, Z1); // Z3 = H*Z1 sqr(U2, H); // U2 = H^2 sqr(S2, R); // S2 = R^2 mul(H, H, U2); // H = H^3 mul(U2, U2, X1); // U2 = X1*H^2 mul(Y3, H, Y1); // T = Y1*H^3 mul2(X3, U2); // X3 = 2*X1*H^2 sub(X3, S2, X3); // X3 = R^2 - 2*X1*H^2 sub(X3, X3, H); // X3 = R^2 - 2*X1*H^2 -H^3 sub(U2, U2, X3); // U2 = X1*H^2 - X3 mul(U2, U2, R); // U2 = R*(X1*H^2 - X3) sub(Y3, U2, Y3); // Y3 = -Y1*H^3 + R*(X1*H^2 - X3) /* T = p_at_infinity? q : T */ MB_FUNC_NAME(mask_mov_FESM2_)(X3, X3, p_at_infinity, q->x); MB_FUNC_NAME(mask_mov_FESM2_)(Y3, Y3, p_at_infinity, q->y); MB_FUNC_NAME(mask_mov_FESM2_)(Z3, Z3, p_at_infinity, (U64*)psm2_r_mb); /* T = q_at_infinity? p : T */ MB_FUNC_NAME(mask_mov_FESM2_)(X3, X3, q_at_infinity, p->X); MB_FUNC_NAME(mask_mov_FESM2_)(Y3, Y3, q_at_infinity, p->Y); MB_FUNC_NAME(mask_mov_FESM2_)(Z3, Z3, q_at_infinity, p->Z); /* r = T */ MB_FUNC_NAME(mov_FESM2_)(r->X, X3); MB_FUNC_NAME(mov_FESM2_)(r->Y, Y3); MB_FUNC_NAME(mov_FESM2_)(r->Z, Z3); } void MB_FUNC_NAME(get_sm2_ec_affine_coords_)(U64 x[], U64 y[], const SM2_POINT* P) { __ALIGN64 U64 invZ1[PSM2_LEN52]; __ALIGN64 U64 invZn[PSM2_LEN52]; /* 1/Z and 1/Z^2 */ MB_FUNC_NAME(ifma_aminv52_psm2_)(invZ1, P->Z); MB_FUNC_NAME(ifma_ams52_psm2_)(invZn, invZ1); /* if affine P.x requested */ if(x) MB_FUNC_NAME(ifma_amm52_psm2_)(x, P->X, invZn); /* if affine P.y requested */ if(y) { MB_FUNC_NAME(ifma_amm52_psm2_)(invZn, invZn, invZ1); MB_FUNC_NAME(ifma_amm52_psm2_)(y, P->Y, invZn); } } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// static __NOINLINE void clear_secret_context(U64* wval, U64* dval, __mb_mask* dsign) { *wval = get_zero64(); *dval = get_zero64(); *dsign = 0; return; } #define WIN_SIZE (4) /* s = (Ipp8u)(~((wvalue >> ws) - 1)); //sign d = (1 << (ws+1)) - wvalue - 1; // digit, win size "ws" d = (d & s) | (wvaluen & ~s); d = (d >> 1) + (d & 1); *sign = s & 1; *digit = (Ipp8u)d; */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract point */ static void MB_FUNC_NAME(extract_point_)(SM2_POINT* r, const SM2_POINT tbl[], U64 idx) { /* decrenent index (the table does not contain [0]*P */ U64 idx_target = sub64(idx, set1(1)); /* assume the point at infinity is what need */ SM2_POINT R; MB_FUNC_NAME(set_point_to_infinity_)(&R); /* find out what we actually need or just keep original infinity */ int32u n; for(n=0; n<(1<<(WIN_SIZE-1)); n++) { U64 idx_curr = set1(n); __mb_mask k = cmp64_mask(idx_curr, idx_target, _MM_CMPINT_EQ); /* R = k? tbl[] : R */ MB_FUNC_NAME(secure_mask_mov_FESM2_)(R.X, R.X, k, tbl[n].X); MB_FUNC_NAME(secure_mask_mov_FESM2_)(R.Y, R.Y, k, tbl[n].Y); MB_FUNC_NAME(secure_mask_mov_FESM2_)(R.Z, R.Z, k, tbl[n].Z); } MB_FUNC_NAME(mov_FESM2_)(r->X, R.X); MB_FUNC_NAME(mov_FESM2_)(r->Y, R.Y); MB_FUNC_NAME(mov_FESM2_)(r->Z, R.Z); } void MB_FUNC_NAME(ifma_ec_sm2_mul_point_)(SM2_POINT* r, const SM2_POINT* p, const U64 scalar[]) { /* pre-computed table */ __ALIGN64 SM2_POINT tbl[1<<(WIN_SIZE-1)]; /* // compute tbl[] = [n]P, n=1,..,2^(WIN_SIZE-1): // // tbl[2*n] = tbl[2*n-1]+p // tbl[2*n+1] = [2]*tbl[n] */ /* tbl[0] = p */ MB_FUNC_NAME(mov_FESM2_)(tbl[0].X, p->X); MB_FUNC_NAME(mov_FESM2_)(tbl[0].Y, p->Y); MB_FUNC_NAME(mov_FESM2_)(tbl[0].Z, p->Z); /* tbl[1] = [2]*p */ MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&tbl[1], p); int n; for(n=1; n < (1<<(WIN_SIZE-1))/2; n++) { MB_FUNC_NAME(ifma_ec_sm2_add_point_)(&tbl[2*n], &tbl[2*n-1], p); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&tbl[2*n+1], &tbl[n]); } SM2_POINT R; SM2_POINT T; U64 Ty[PSM2_LEN52]; /* // point (LR) multiplication */ U64 idx_mask = set1( (1<<(WIN_SIZE+1))-1 ); int bit = PSM2_BITSIZE-(PSM2_BITSIZE % WIN_SIZE); int chunk_no = (bit-1)/64; int chunk_shift = (bit-1)%64; /* first window */ U64 wvalue = loadu64(&scalar[chunk_no]); wvalue = and64( srli64(wvalue, chunk_shift), idx_mask); U64 dvalue; __mb_mask dsign; MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&R, tbl, dvalue); for(bit-=WIN_SIZE; bit>=WIN_SIZE; bit-=WIN_SIZE) { /* doubling */ MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); #endif /* extract precomputed []P */ chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); /* T = dsign? -T : T */ MB_FUNC_NAME(ifma_neg52_psm2_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FESM2_)(T.Y, T.Y, dsign, Ty); /* accumulate T */ MB_FUNC_NAME(ifma_ec_sm2_add_point_)(&R, &R, &T); } /* last window */ MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); #if (WIN_SIZE==5) MB_FUNC_NAME(ifma_ec_sm2_dbl_point_)(&R, &R); #endif wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_)(&T, tbl, dvalue); MB_FUNC_NAME(ifma_neg52_psm2_)(Ty, T.Y); MB_FUNC_NAME(secure_mask_mov_FESM2_)(T.Y, T.Y, dsign, Ty); MB_FUNC_NAME(ifma_ec_sm2_add_point_)(&R, &R, &T); /* r = R */ MB_FUNC_NAME(mov_FESM2_)(r->X, R.X); MB_FUNC_NAME(mov_FESM2_)(r->Y, R.Y); MB_FUNC_NAME(mov_FESM2_)(r->Z, R.Z); /* clear r (to fix potential secutity flaw in case of ecdh */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef WIN_SIZE ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// #include #define BP_WIN_SIZE MUL_BASEPOINT_WIN_SIZE /* defined in the header above */ __MBX_INLINE void MB_FUNC_NAME(booth_recode_bp_)(__mb_mask* sign, U64* dvalue, U64 wvalue) { U64 one = set1(1); U64 zero = get_zero64(); U64 t = srli64(wvalue, BP_WIN_SIZE); __mb_mask s = cmp64_mask(t, zero, _MM_CMPINT_NE); U64 d = sub64( sub64(set1(1<<(BP_WIN_SIZE+1)), wvalue), one); d = mask_mov64(wvalue, s, d); U64 odd = and64(d, one); d = add64( srli64(d, 1), odd); *sign = s; *dvalue = d; } /* extract affine affine point */ __MBX_INLINE void MB_FUNC_NAME(extract_point_affine_)(SM2_POINT_AFFINE* r, const SINGLE_SM2_POINT_AFFINE* tbl, U64 idx) { /* decrement index (the table does not contain [0]*P */ U64 targIdx = sub64(idx, set1(1)); U64 ax0, ax1, ax2, ax3, ax4, ay0, ay1, ay2, ay3, ay4; /* assume the point at infinity is what need */ ax0 = ax1 = ax2 = ax3 = ax4 = ay0 = ay1 = ay2 = ay3 = ay4 = get_zero64(); /* find out what we actually need or just keep original infinity */ int n; U64 currIdx = get_zero64(); for(n=0; n<(1<<(BP_WIN_SIZE-1)); n++, tbl++, currIdx = add64(currIdx, set1(1))) { __mb_mask k = cmp64_mask(currIdx, targIdx, _MM_CMPINT_EQ); /* R = k? set1( tbl[] ) : R */ ax0 = mask_add64(ax0, k, ax0, set1( tbl->x[0] )); ax1 = mask_add64(ax1, k, ax1, set1( tbl->x[1] )); ax2 = mask_add64(ax2, k, ax2, set1( tbl->x[2] )); ax3 = mask_add64(ax3, k, ax3, set1( tbl->x[3] )); ax4 = mask_add64(ax4, k, ax4, set1( tbl->x[4] )); ay0 = mask_add64(ay0, k, ay0, set1( tbl->y[0] )); ay1 = mask_add64(ay1, k, ay1, set1( tbl->y[1] )); ay2 = mask_add64(ay2, k, ay2, set1( tbl->y[2] )); ay3 = mask_add64(ay3, k, ay3, set1( tbl->y[3] )); ay4 = mask_add64(ay4, k, ay4, set1( tbl->y[4] )); } r->x[0] = ax0; r->x[1] = ax1; r->x[2] = ax2; r->x[3] = ax3; r->x[4] = ax4; r->y[0] = ay0; r->y[1] = ay1; r->y[2] = ay2; r->y[3] = ay3; r->y[4] = ay4; } void MB_FUNC_NAME(ifma_ec_sm2_mul_pointbase_)(SM2_POINT* r, const U64 scalar[]) { /* pre-computed table of base powers */ SINGLE_SM2_POINT_AFFINE* tbl = &ifma_ec_sm2_bp_precomp[0][0]; SM2_POINT R; SM2_POINT_AFFINE A; U64 Ty[PSM2_LEN52]; /* R = O */ MB_FUNC_NAME(set_point_to_infinity_)(&R); /* // base point (RL) multiplication */ U64 wvalue, dvalue; __mb_mask dsign; U64 idx_mask = set1( (1<<(BP_WIN_SIZE+1))-1 ); int bit = 0; /* first window - window[0] */ wvalue = loadu64(&scalar[0]); wvalue = and64( slli64(wvalue, 1), idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_psm2_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FESM2_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_sm2_add_point_affine_)(&R, &R, &A); int chunk_no; int chunk_shift; for(bit+=BP_WIN_SIZE; bit<=PSM2_BITSIZE; bit+=BP_WIN_SIZE) { chunk_no = (bit-1)/64; chunk_shift = (bit-1)%64; wvalue = loadu64(&scalar[chunk_no]); #if (_MSC_VER <= 1916) /* VS 2017 not supported _mm512_shrdv_epi64 */ { __m512i t_lo_ = _mm512_srlv_epi64(wvalue, set64(chunk_shift)); __m512i t_hi_ = _mm512_sllv_epi64(loadu64(&scalar[chunk_no+1]), set64(64-chunk_shift)); wvalue = or64(t_lo_, t_hi_); } #else wvalue = _mm512_shrdv_epi64(wvalue, loadu64(&scalar[chunk_no+1]), set1((int32u)chunk_shift)); #endif wvalue = and64(wvalue, idx_mask); MB_FUNC_NAME(booth_recode_bp_)(&dsign, &dvalue, wvalue); MB_FUNC_NAME(extract_point_affine_)(&A, tbl, dvalue); tbl+=BP_N_ENTRY; /* A = dsign? -A : A */ MB_FUNC_NAME(ifma_neg52_psm2_)(Ty, A.y); MB_FUNC_NAME(secure_mask_mov_FESM2_)(A.y, A.y, dsign, Ty); /* R += A */ MB_FUNC_NAME(ifma_ec_sm2_add_point_affine_)(&R, &R, &A); } /* r = R */ MB_FUNC_NAME(mov_FESM2_)(r->X, R.X); MB_FUNC_NAME(mov_FESM2_)(r->Y, R.Y); MB_FUNC_NAME(mov_FESM2_)(r->Z, R.Z); /* clear stubs of secret scalar */ clear_secret_context(&wvalue, &dvalue, &dsign); } #undef BP_WIN_SIZE /* SM2 parameters: mont(a), mont(b) */ __ALIGN64 static const int64u mont_a_psm2_mb[PSM2_LEN52][8] = { { REP8_DECL(0x000fffffffffffcf) }, { REP8_DECL(0x000cf00000030fff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x000fffffffffffff) }, { REP8_DECL(0x0000ffffffceffff) } }; __ALIGN64 static const int64u mont_b_psm2_mb[PSM2_LEN52][8] = { { REP8_DECL(0x00030632bc0dd422) }, { REP8_DECL(0x000b09b537ab70d2) }, { REP8_DECL(0x000a51c3c71cf379) }, { REP8_DECL(0x0002c8527981505e) }, { REP8_DECL(0x000040fe188da20e) } }; /* // We have a curve defined by a Weierstrass equation: y^2 = x^3 + a*x + b. // // The points are considered in Jacobian projective coordinates // where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). // Substituting this and multiplying by Z^6 transforms the above equation into // Y^2 = X^3 + a*X*Z^4 + b*Z^6 // To test this, we add up the right-hand side in 'rh'. */ __mb_mask MB_FUNC_NAME(ifma_is_on_curve_psm2_)(const SM2_POINT* p, int use_jproj_coords) { U64 rh[PSM2_LEN52]; U64 Z4[PSM2_LEN52], Z6[PSM2_LEN52], tmp[PSM2_LEN52]; /* rh := X^2 */ MB_FUNC_NAME(ifma_ams52_psm2_)(rh, p->X); /* if Z!=1, then rh = X^3 + a*X*Z^4 + b*Z^6 = X*(X^2 + a*X*Z^4) + b*Z^6 */ if(use_jproj_coords) { MB_FUNC_NAME(ifma_ams52_psm2_)(tmp, p->Z); /* tmp = Z^2 */ MB_FUNC_NAME(ifma_ams52_psm2_)(Z4, tmp); /* Z4 = Z^4 */ MB_FUNC_NAME(ifma_amm52_psm2_)(Z6, Z4, tmp); /* Z6 = Z^6 */ MB_FUNC_NAME(ifma_add52_psm2_)(tmp, Z4, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_add52_psm2_)(tmp, tmp, Z4); /* tmp = 2*Z^4 */ MB_FUNC_NAME(ifma_sub52_psm2_)(rh, rh, tmp); /* rh = X^2 + a*Z^4 */ MB_FUNC_NAME(ifma_amm52_psm2_)(rh, rh, p->X); /* rh = (X^2 + a*Z^4)*X */ MB_FUNC_NAME(ifma_amm52_psm2_)(tmp, Z6, (U64*)mont_b_psm2_mb); MB_FUNC_NAME(ifma_add52_psm2_)(rh, rh, tmp); /* rh = (X^2 + a*Z^4)*X + b*Z^6 */ } /* if Z==1, then rh = X^3 + a*X + b = X*(X^2 +a) b */ else { MB_FUNC_NAME(ifma_add52_psm2_)(rh, rh, (U64*)mont_a_psm2_mb); /* rh = X^2+a */ MB_FUNC_NAME(ifma_amm52_psm2_)(rh, rh, p->X); /* rh = (X^2+a)*X */ MB_FUNC_NAME(ifma_add52_psm2_)(rh, rh, (U64*)mont_b_psm2_mb); /* rh = (X^2+a)*X + b */ } MB_FUNC_NAME(ifma_frommont52_psm2_)(rh, rh); /* rl = tmp = Y^2 */ MB_FUNC_NAME(ifma_ams52_psm2_)(tmp, p->Y); MB_FUNC_NAME(ifma_frommont52_psm2_)(tmp, tmp); /* mask = rl==rh */ __mb_mask is_on_curve_mask = MB_FUNC_NAME(cmp_eq_FESM2_)(tmp, rh); return is_on_curve_mask; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/ifma_ecpubkey_sm2.c000066400000000000000000000110251470420105600302460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE /* // Computes public key // pa_pubx[] array of pointers to the public keys X-coordinates // pa_puby[] array of pointers to the public keys Y-coordinates // pa_pubz[] array of pointers to the public keys Z-coordinates (or NULL, if affine coordinate requested) // pa_skey[] array of pointers to the private keys // pBuffer pointer to the scratch buffer // // Note: // output public key depends on pa_pubz[] parameter and represented either // - in (X:Y:Z) projective Jacobian coordinates if pa_pubz[] != NULL // or // - in (x:y) affine coordinate if pa_pubz[] == NULL */ DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecpublic_key_ssl_mb8)(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { BIGNUM* out_x = pa_pubx[buf_no]; BIGNUM* out_y = pa_puby[buf_no]; BIGNUM* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const BIGNUM* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecpublic_key_ssl_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } #endif // BN_OPENSSL_DISABLE DLL_PUBLIC mbx_status OWNAPI(mbx_sm2_ecpublic_key_mb8)(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer) { mbx_status status = 0; int buf_no; /* pa_bubz!=0 means the output is in Jacobian projective coordinates */ int use_jproj_coords = NULL!=pa_pubz; /* test input pointers */ if(NULL==pa_pubx || NULL==pa_puby || NULL==pa_skey) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int64u* out_x = pa_pubx[buf_no]; int64u* out_y = pa_puby[buf_no]; int64u* out_z = use_jproj_coords? pa_pubz[buf_no] : NULL; const int64u* key = pa_skey[buf_no]; /* if any of pointer NULL set error status */ if(NULL==out_x || NULL==out_y || (use_jproj_coords && NULL==out_z) || NULL==key) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); } } if(!MBX_IS_ANY_OK_STS(status)) return status; /* // processing */ #if (_MBX>=_MBX_K1) status |= internal_avx512_sm2_ecpublic_key_mb8(pa_pubx, pa_puby, pa_pubz, pa_skey, pBuffer, use_jproj_coords); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/internal_avx512/000077500000000000000000000000001470420105600274415ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/internal_avx512/internal_ecdsa_sm2.c000066400000000000000000000675621470420105600333610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE #include #include #ifdef OPENSSL_IS_BORINGSSL #include #endif #endif /* constants for Z digest computation */ /* EC SM2 equation coefficient a, big endian */ static const int8u a[] = "\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC"; /* EC SM2 equation coefficient b, big endian */ static const int8u b[] = "\x28\xE9\xFA\x9E\x9D\x9F\x5E\x34\x4D\x5A\x9E\x4B\xCF\x65\x09\xA7\xF3\x97\x89\xF5\x15\xAB\x8F\x92\xDD\xBC\xBD\x41\x4D\x94\x0E\x93"; /* x coordinate of the EC SM2 generator point in affine coordinates, big endian */ static const int8u xG[] = "\x32\xC4\xAE\x2C\x1F\x19\x81\x19\x5F\x99\x04\x46\x6A\x39\xC9\x94\x8F\xE3\x0B\xBF\xF2\x66\x0B\xE1\x71\x5A\x45\x89\x33\x4C\x74\xC7"; /* y coordinate of the EC SM2 generator point in affine coordinates, big endian */ static const int8u yG[] = "\xBC\x37\x36\xA2\xF4\xF6\x77\x9C\x59\xBD\xCE\xE3\x6B\x69\x21\x53\xD0\xA9\x87\x7C\xC6\x2A\x47\x40\x02\xDF\x32\xE5\x21\x39\xF0\xA0"; static const int8u * pa_a[] = {REP8_DECL( a)}; static const int8u * pa_b[] = {REP8_DECL( b)}; static const int8u * pa_xG[] = {REP8_DECL(xG)}; static const int8u * pa_yG[] = {REP8_DECL(yG)}; static int len_2[8] = {REP8_DECL( 2)}; static int len_32[8] = {REP8_DECL(32)}; /* // common functions */ /* compute Z digest = SM3( ENTL || ID || a || b ||xG || yG || xA || yA ) */ static void sm2_ecdsa_compute_z_digest(int8u* pa_z_digest[8], const int8u* pa_user_id[8], const int user_id_len[8], const int8u* pa_pubx[8], const int8u* pa_puby[8]) { SM3_CTX_mb8 ctx; SM3_CTX_mb8* p_ctx = &ctx; sm3_init_mb8(p_ctx); int8u entl_data[8][2]; const int8u* pa_entl[8]; for (int i = 0; i < 8; ++i) { int entl = ((user_id_len[i] * 8) & 0xFFFF); entl_data[i][1] = entl & 0xFF; entl_data[i][0] = entl >> 8; pa_entl[i] = &(entl_data[i][0]); } sm3_update_mb8(pa_entl, len_2, p_ctx); sm3_update_mb8(pa_user_id, (int *)user_id_len, p_ctx); sm3_update_mb8(pa_a, len_32, p_ctx); sm3_update_mb8(pa_b, len_32, p_ctx); sm3_update_mb8(pa_xG, len_32, p_ctx); sm3_update_mb8(pa_yG, len_32, p_ctx); sm3_update_mb8(pa_pubx, len_32, p_ctx); sm3_update_mb8(pa_puby, len_32, p_ctx); sm3_final_mb8(pa_z_digest, p_ctx); return; } static void sm2_ecdsa_compute_msg_digest(int8u* pa_msg_digest[8], const int8u* pa_z_digest[8], const int8u* pa_msg[8], const int msg_len[8]) { SM3_CTX_mb8 ctx; SM3_CTX_mb8* p_ctx = &ctx; sm3_init_mb8(p_ctx); sm3_update_mb8(pa_z_digest, len_32, p_ctx); sm3_update_mb8(pa_msg, (int*)msg_len, p_ctx); sm3_final_mb8(pa_msg_digest, p_ctx); return; } static void reverse_inplace(int8u* inp, int len) { for(int i = 0; i < len/2; ++i) { int8u a = inp[i]; inp[i] = inp[len - 1 - i]; inp[len - 1 - i] = a; } return; } /* // SM2_POINT* P - Public key in Jacobian projective coordinates, coordinates are in Montgomery over p // int64u* pa_rev_bytes_pubX[8] - X coordinate (affine), bytes reversed for future hashing // int64u* pa_rev_bytes_pubY[8] - Y coordinate (affine), bytes reversed for future hashing */ static mbx_status sm2_ecdsa_process_pubkeys(SM2_POINT* P, int64u* pa_rev_bytes_pubX[8], int64u* pa_rev_bytes_pubY[8], int use_jproj_coords, mbx_status current_status) { mbx_status status = current_status; status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_psm2_)(P->X), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_psm2_)(P->Y), MBX_STATUS_MISMATCH_PARAM_ERR); if(use_jproj_coords) { status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_psm2_)(P->Z), MBX_STATUS_MISMATCH_PARAM_ERR); MB_FUNC_NAME(ifma_tomont52_psm2_)(P->X, P->X); MB_FUNC_NAME(ifma_tomont52_psm2_)(P->Y, P->Y); MB_FUNC_NAME(ifma_tomont52_psm2_)(P->Z, P->Z); __ALIGN64 U64 X[PSM2_LEN52]; __ALIGN64 U64 Y[PSM2_LEN52]; MB_FUNC_NAME(get_sm2_ec_affine_coords_)(X, Y, P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_psm2_)(X, X); MB_FUNC_NAME(ifma_frommont52_psm2_)(Y, Y); /* convert P coordinates to radix 64 */ ifma_mb8_to_BNU(pa_rev_bytes_pubX, (const int64u (*)[8])X, PSM2_BITSIZE); ifma_mb8_to_BNU(pa_rev_bytes_pubY, (const int64u (*)[8])Y, PSM2_BITSIZE); } else { ifma_mb8_to_BNU(pa_rev_bytes_pubX, (const int64u (*)[8])P->X, PSM2_BITSIZE); ifma_mb8_to_BNU(pa_rev_bytes_pubY, (const int64u (*)[8])P->Y, PSM2_BITSIZE); MB_FUNC_NAME(ifma_tomont52_psm2_)(P->X, P->X); MB_FUNC_NAME(ifma_tomont52_psm2_)(P->Y, P->Y); MB_FUNC_NAME(ifma_tomont52_psm2_)(P->Z, (U64*)ones); } for(int i = 0; i < 8; ++i) { reverse_inplace((int8u*)pa_rev_bytes_pubX[i], PSM2_LEN8); reverse_inplace((int8u*)pa_rev_bytes_pubY[i], PSM2_LEN8); } return status; } /* compute and check signature components */ static mbx_status sm2_ecdsa_sign_mb8(U64 sign_r[], U64 sign_s[], U64 msg_digest[], U64 scalar_eph_skey[], U64 eph_skey[], U64 reg_skey[], mbx_status current_status) { mbx_status status = current_status; /* compute public keys from ephemeral private keys */ SM2_POINT P_eph; /* (x1, y1) = [k]G */ MB_FUNC_NAME(ifma_ec_sm2_mul_pointbase_)(&P_eph, scalar_eph_skey); /* extract affine P.x */ MB_FUNC_NAME(get_sm2_ec_affine_coords_)(/* x = */ P_eph.X, /* y = */ NULL, &P_eph); MB_FUNC_NAME(ifma_frommont52_psm2_)(P_eph.X, P_eph.X); /* x = x mod n */ MB_FUNC_NAME(ifma_fastred52_pnsm2_)(P_eph.X, P_eph.X); /* r = (e + x1) mod n */ MB_FUNC_NAME(ifma_tomont52_nsm2_)(sign_r, P_eph.X); MB_FUNC_NAME(ifma_tomont52_nsm2_)(msg_digest, msg_digest); MB_FUNC_NAME(ifma_add52_nsm2_)(sign_r, sign_r, msg_digest); /* sign_r = (e + x1) */ /* check r component */ MB_FUNC_NAME(ifma_tomont52_nsm2_)(eph_skey, eph_skey); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(sign_r), MBX_STATUS_SIGNATURE_ERR); __ALIGN64 U64 tmp[PSM2_LEN52]; /* sign_r + eph_skey == n */ MB_FUNC_NAME(ifma_add52_nsm2_)(tmp, sign_r, eph_skey); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(tmp), MBX_STATUS_SIGNATURE_ERR); if(!MBX_IS_ANY_OK_STS(status) ) return status; MB_FUNC_NAME(zero_)((int64u (*)[8])tmp, sizeof(tmp)/sizeof(U64)); /* s = ( (1 + da)^-(1) * (k - r*da) ) */ MB_FUNC_NAME(ifma_tomont52_nsm2_)(tmp, (U64*)ones); MB_FUNC_NAME(ifma_tomont52_nsm2_)(reg_skey, reg_skey); MB_FUNC_NAME(ifma_amm52_nsm2_)(sign_s, sign_r, reg_skey); /* sign_s = r * da */ MB_FUNC_NAME(ifma_add52_nsm2_)(reg_skey, reg_skey, tmp); /* reg_skey = 1 + da */ MB_FUNC_NAME(ifma_aminv52_nsm2_)(reg_skey, reg_skey); /* reg_skey = (1 + da)^(-1) */ MB_FUNC_NAME(ifma_sub52_nsm2_)(sign_s, eph_skey, sign_s); /* sign_s = k - r * da */ MB_FUNC_NAME(ifma_amm52_nsm2_)(sign_s, sign_s, reg_skey); /* sign_s = ( (1 + da)^-(1) * (k - r*da) ) */ MB_FUNC_NAME(ifma_frommont52_nsm2_)(sign_r, sign_r); MB_FUNC_NAME(ifma_frommont52_nsm2_)(sign_s, sign_s); /* check s component */ status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(sign_s), MBX_STATUS_SIGNATURE_ERR); return status; } /* verify signature components */ static mbx_status sm2_ecdsa_verify_mb8(U64 sign_r[], U64 sign_s[], U64 msg_digest[], SM2_POINT* P, mbx_status current_status) { mbx_status status = current_status; __ALIGN64 U64 t[PSM2_LEN52]; __ALIGN64 U64 h[PSM2_LEN52]; /* t = (r + s) mod n */ MB_FUNC_NAME(ifma_tomont52_nsm2_)(t, sign_r); MB_FUNC_NAME(ifma_tomont52_nsm2_)(h, sign_s); MB_FUNC_NAME(ifma_add52_nsm2_)(t, h, t); /* t = (r + s) */ MB_FUNC_NAME(ifma_frommont52_nsm2_)(t, t); /* check t != 0 */ __mb_mask signature_err_mask = MB_FUNC_NAME(is_zero_FE256_)(t); __ALIGN64 int64u tmp[8][PSM2_LEN64]; int64u* pa_tmp[8] = {tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7]}; /* (x1`, y1`) = [s]G + [t]P */ /* convert sign_s to scalar - s */ ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])sign_s, PSM2_BITSIZE); ifma_BNU_transpose_copy((int64u (*)[8])sign_s, (const int64u(**))pa_tmp, PSM2_BITSIZE); sign_s[PSM2_LEN64] = get_zero64(); SM2_POINT sG; MB_FUNC_NAME(ifma_ec_sm2_mul_pointbase_)(&sG, sign_s); /* [s]G */ /* convert t to scalar - t */ ifma_mb8_to_BNU(pa_tmp, (const int64u(*)[8])t, PSM2_BITSIZE); ifma_BNU_transpose_copy((int64u(*)[8])t, (const int64u(**))pa_tmp, PSM2_BITSIZE); t[PSM2_LEN64] = get_zero64(); MB_FUNC_NAME(ifma_ec_sm2_mul_point_)(P, P, t); /* [t]P */ MB_FUNC_NAME(ifma_ec_sm2_add_point_)(P, P, &sG); /* P = [s]G + [t]P */ __ALIGN64 U64 sign_r_restored[PSM2_LEN52]; /* extract affine P.x */ MB_FUNC_NAME(get_sm2_ec_affine_coords_)(/* x = */ sign_r_restored, /* y = */ NULL, P); /* form Montgomery domain | x = x mod n */ MB_FUNC_NAME(ifma_frommont52_psm2_)(sign_r_restored, sign_r_restored); MB_FUNC_NAME(ifma_fastred52_pnsm2_)(sign_r_restored, sign_r_restored); /* r = (e + x1) mod n */ MB_FUNC_NAME(ifma_tomont52_nsm2_)(sign_r_restored, sign_r_restored); MB_FUNC_NAME(ifma_tomont52_nsm2_)(msg_digest, msg_digest); MB_FUNC_NAME(ifma_add52_nsm2_)(sign_r_restored, sign_r_restored, msg_digest); MB_FUNC_NAME(ifma_frommont52_nsm2_)(sign_r_restored, sign_r_restored); /* check equal */ signature_err_mask |= ~(MB_FUNC_NAME(cmp_eq_FESM2_)(sign_r_restored, sign_r)); status |= MBX_SET_STS_BY_MASK(status, signature_err_mask, MBX_STATUS_SIGNATURE_ERR); return status; } mbx_status internal_avx512_sm2_ecdsa_sign_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_eph_skey[8], const int64u* const pa_reg_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked) { mbx_status status = 0; /* load and check secret keys */ __ALIGN64 U64 reg_skey[PSM2_LEN52]; __ALIGN64 U64 eph_skey[PSM2_LEN52]; ifma_BNU_to_mb8((int64u (*)[8])reg_skey, pa_reg_skey, PSM2_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])eph_skey, pa_eph_skey, PSM2_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(reg_skey), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(eph_skey), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])eph_skey, sizeof(eph_skey)/sizeof(U64)); return status; } __ALIGN64 int64u rev_bytes_pubX[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubX[8] = {rev_bytes_pubX[0], rev_bytes_pubX[1], rev_bytes_pubX[2], rev_bytes_pubX[3], rev_bytes_pubX[4], rev_bytes_pubX[5], rev_bytes_pubX[6], rev_bytes_pubX[7]}; __ALIGN64 int64u rev_bytes_pubY[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubY[8] = {rev_bytes_pubY[0], rev_bytes_pubY[1], rev_bytes_pubY[2], rev_bytes_pubY[3], rev_bytes_pubY[4], rev_bytes_pubY[5], rev_bytes_pubY[6], rev_bytes_pubY[7]}; SM2_POINT P; ifma_BNU_to_mb8((int64u (*)[8])P.X, (const int64u* (*))pa_pubx, PSM2_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])P.Y, (const int64u* (*))pa_puby, PSM2_BITSIZE); if(use_jproj_coords) { ifma_BNU_to_mb8((int64u (*)[8])P.Z, (const int64u* (*))pa_pubz, PSM2_BITSIZE); } status = sm2_ecdsa_process_pubkeys(&P, pa_rev_bytes_pubX, pa_rev_bytes_pubY, use_jproj_coords, status); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])eph_skey, sizeof(eph_skey)/sizeof(U64)); return status; } __ALIGN64 int8u msg_digest[8][PSM2_LEN8]; int8u* pa_msg_digest[8] = {msg_digest[0], msg_digest[1], msg_digest[2], msg_digest[3], msg_digest[4], msg_digest[5], msg_digest[6], msg_digest[7]}; /* compute z digest */ sm2_ecdsa_compute_z_digest(pa_msg_digest, (const int8u **)pa_user_id, (const int *)user_id_len_checked, (const int8u **)pa_rev_bytes_pubX, (const int8u **)pa_rev_bytes_pubY); /* compute msg digest */ sm2_ecdsa_compute_msg_digest(pa_msg_digest, (const int8u **)pa_msg_digest, (const int8u **)pa_msg, (const int *)msg_len); /* zero padded keys */ U64 scalar_eph_skey[PSM2_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalar_eph_skey, pa_eph_skey, PSM2_BITSIZE); scalar_eph_skey[PSM2_LEN64] = get_zero64(); __ALIGN64 U64 sign_r[PSM2_LEN52]; __ALIGN64 U64 sign_s[PSM2_LEN52]; __ALIGN64 U64 msg[PSM2_LEN52]; ifma_HexStr8_to_mb8((int64u (*)[8])msg, (const int8u* const*)pa_msg_digest, PSM2_BITSIZE); /* compute and check signature components */ status = sm2_ecdsa_sign_mb8(sign_r, sign_s, msg, scalar_eph_skey, eph_skey, reg_skey, status); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalar_eph_skey, sizeof(scalar_eph_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])eph_skey, sizeof(eph_skey)/sizeof(U64)); if(!MBX_IS_ANY_OK_STS(status) ) return status; ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, PSM2_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, PSM2_BITSIZE); return status; } mbx_status internal_avx512_sm2_ecdsa_verify_mb8(const int8u* const pa_sign_r[8], const int8u* const pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked) { mbx_status status = 0; __ALIGN64 U64 sign_r[PSM2_LEN52]; __ALIGN64 U64 sign_s[PSM2_LEN52]; ifma_HexStr8_to_mb8((int64u (*)[8])sign_r, (const int8u* const*)pa_sign_r, PSM2_BITSIZE); ifma_HexStr8_to_mb8((int64u (*)[8])sign_s, (const int8u* const*)pa_sign_s, PSM2_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_nsm2_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_nsm2_)(sign_s), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) return status; __ALIGN64 int64u rev_bytes_pubX[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubX[8] = {rev_bytes_pubX[0], rev_bytes_pubX[1], rev_bytes_pubX[2], rev_bytes_pubX[3], rev_bytes_pubX[4], rev_bytes_pubX[5], rev_bytes_pubX[6], rev_bytes_pubX[7]}; __ALIGN64 int64u rev_bytes_pubY[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubY[8] = {rev_bytes_pubY[0], rev_bytes_pubY[1], rev_bytes_pubY[2], rev_bytes_pubY[3], rev_bytes_pubY[4], rev_bytes_pubY[5], rev_bytes_pubY[6], rev_bytes_pubY[7]}; SM2_POINT P; ifma_BNU_to_mb8((int64u (*)[8])P.X, (const int64u* (*))pa_pubx, PSM2_BITSIZE); ifma_BNU_to_mb8((int64u (*)[8])P.Y, (const int64u* (*))pa_puby, PSM2_BITSIZE); if(use_jproj_coords) { ifma_BNU_to_mb8((int64u (*)[8])P.Z, (const int64u* (*))pa_pubz, PSM2_BITSIZE); } status = sm2_ecdsa_process_pubkeys(&P, pa_rev_bytes_pubX, pa_rev_bytes_pubY, use_jproj_coords, status); if(!MBX_IS_ANY_OK_STS(status)) return status; __ALIGN64 int8u msg_digest[8][PSM2_LEN8]; int8u* pa_msg_digest[8] = {msg_digest[0], msg_digest[1], msg_digest[2], msg_digest[3], msg_digest[4], msg_digest[5], msg_digest[6], msg_digest[7]}; /* compute z digest */ sm2_ecdsa_compute_z_digest(pa_msg_digest, (const int8u **)pa_user_id, (const int *)user_id_len_checked, (const int8u **)pa_rev_bytes_pubX, (const int8u **)pa_rev_bytes_pubY); /* compute msg digest */ sm2_ecdsa_compute_msg_digest(pa_msg_digest, (const int8u **)pa_msg_digest, (const int8u **)pa_msg, (const int *)msg_len); __ALIGN64 U64 msg[PSM2_LEN52]; ifma_HexStr8_to_mb8((int64u (*)[8])msg, (const int8u* const*)pa_msg_digest, PSM2_BITSIZE); status = sm2_ecdsa_verify_mb8(sign_r, sign_s, msg, &P, status); return status; } #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_sm2_ecdsa_sign_ssl_mb8(int8u* pa_sign_r[8], int8u* pa_sign_s[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_eph_skey[8], const BIGNUM* const pa_reg_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked) { mbx_status status = 0; /* load and check secret keys */ __ALIGN64 U64 reg_skey[PSM2_LEN52]; __ALIGN64 U64 eph_skey[PSM2_LEN52]; ifma_BN_to_mb8((int64u (*)[8])reg_skey, pa_reg_skey, PSM2_BITSIZE); ifma_BN_to_mb8((int64u (*)[8])eph_skey, pa_eph_skey, PSM2_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(reg_skey), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(is_zero_FESM2_)(eph_skey), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])eph_skey, sizeof(eph_skey)/sizeof(U64)); return status; } __ALIGN64 int64u rev_bytes_pubX[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubX[8] = {rev_bytes_pubX[0], rev_bytes_pubX[1], rev_bytes_pubX[2], rev_bytes_pubX[3], rev_bytes_pubX[4], rev_bytes_pubX[5], rev_bytes_pubX[6], rev_bytes_pubX[7]}; __ALIGN64 int64u rev_bytes_pubY[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubY[8] = {rev_bytes_pubY[0], rev_bytes_pubY[1], rev_bytes_pubY[2], rev_bytes_pubY[3], rev_bytes_pubY[4], rev_bytes_pubY[5], rev_bytes_pubY[6], rev_bytes_pubY[7]}; SM2_POINT P; ifma_BN_to_mb8((int64u (*)[8])P.X, pa_pubx, PSM2_BITSIZE); ifma_BN_to_mb8((int64u (*)[8])P.Y, pa_puby, PSM2_BITSIZE); if(use_jproj_coords) { ifma_BN_to_mb8((int64u (*)[8])P.Z, pa_pubz, PSM2_BITSIZE); } status = sm2_ecdsa_process_pubkeys(&P, pa_rev_bytes_pubX, pa_rev_bytes_pubY, use_jproj_coords, status); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])eph_skey, sizeof(eph_skey)/sizeof(U64)); return status; } __ALIGN64 int8u msg_digest[8][PSM2_LEN8]; int8u* pa_msg_digest[8] = {msg_digest[0], msg_digest[1], msg_digest[2], msg_digest[3], msg_digest[4], msg_digest[5], msg_digest[6], msg_digest[7]}; /* compute z digest */ sm2_ecdsa_compute_z_digest(pa_msg_digest, (const int8u **)pa_user_id, (const int *)user_id_len_checked, (const int8u **)pa_rev_bytes_pubX, (const int8u **)pa_rev_bytes_pubY); /* compute msg digest */ sm2_ecdsa_compute_msg_digest(pa_msg_digest, (const int8u **)pa_msg_digest, (const int8u **)pa_msg, (const int *)msg_len); /* zero padded keys */ U64 scalar_eph_skey[PSM2_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])scalar_eph_skey, pa_eph_skey, PSM2_BITSIZE); scalar_eph_skey[PSM2_LEN64] = get_zero64(); __ALIGN64 U64 sign_r[PSM2_LEN52]; __ALIGN64 U64 sign_s[PSM2_LEN52]; __ALIGN64 U64 msg[PSM2_LEN52]; ifma_HexStr8_to_mb8((int64u (*)[8])msg, (const int8u* const*)pa_msg_digest, PSM2_BITSIZE); /* compute and check signature components */ status = sm2_ecdsa_sign_mb8(sign_r, sign_s, msg, scalar_eph_skey, eph_skey, reg_skey, status); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalar_eph_skey, sizeof(scalar_eph_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])reg_skey, sizeof(reg_skey)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])eph_skey, sizeof(eph_skey)/sizeof(U64)); if(!MBX_IS_ANY_OK_STS(status) ) return status; ifma_mb8_to_HexStr8(pa_sign_r, (const int64u(*)[8])sign_r, PSM2_BITSIZE); ifma_mb8_to_HexStr8(pa_sign_s, (const int64u(*)[8])sign_s, PSM2_BITSIZE); return status; } mbx_status internal_avx512_sm2_ecdsa_verify_ssl_mb8(const ECDSA_SIG* const pa_sig[8], const int8u* const pa_user_id[8], const int user_id_len[8], const int8u* const pa_msg[8], const int msg_len[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords, int* user_id_len_checked) { mbx_status status = 0; BIGNUM* pa_sign_r[8] = { 0,0,0,0,0,0,0,0 }; BIGNUM* pa_sign_s[8] = { 0,0,0,0,0,0,0,0 }; for (int buf_no = 0; buf_no < 8; buf_no++) { if(pa_sig[buf_no] != NULL) { ECDSA_SIG_get0(pa_sig[buf_no], (const BIGNUM(**))pa_sign_r + buf_no, (const BIGNUM(**))pa_sign_s + buf_no); } } __ALIGN64 U64 sign_r[PSM2_LEN52]; __ALIGN64 U64 sign_s[PSM2_LEN52]; ifma_BN_to_mb8((int64u (*)[8])sign_r, (const BIGNUM(**))pa_sign_r, PSM2_BITSIZE); ifma_BN_to_mb8((int64u (*)[8])sign_s, (const BIGNUM(**))pa_sign_s, PSM2_BITSIZE); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_nsm2_)(sign_r), MBX_STATUS_MISMATCH_PARAM_ERR); status |= MBX_SET_STS_BY_MASK(status, MB_FUNC_NAME(ifma_check_range_nsm2_)(sign_s), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) return status; __ALIGN64 int64u rev_bytes_pubX[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubX[8] = {rev_bytes_pubX[0], rev_bytes_pubX[1], rev_bytes_pubX[2], rev_bytes_pubX[3], rev_bytes_pubX[4], rev_bytes_pubX[5], rev_bytes_pubX[6], rev_bytes_pubX[7]}; __ALIGN64 int64u rev_bytes_pubY[8][PSM2_LEN64]; int64u* pa_rev_bytes_pubY[8] = {rev_bytes_pubY[0], rev_bytes_pubY[1], rev_bytes_pubY[2], rev_bytes_pubY[3], rev_bytes_pubY[4], rev_bytes_pubY[5], rev_bytes_pubY[6], rev_bytes_pubY[7]}; SM2_POINT P; ifma_BN_to_mb8((int64u (*)[8])P.X, pa_pubx, PSM2_BITSIZE); ifma_BN_to_mb8((int64u (*)[8])P.Y, pa_puby, PSM2_BITSIZE); if(use_jproj_coords) { ifma_BN_to_mb8((int64u (*)[8])P.Z, pa_pubz, PSM2_BITSIZE); } status = sm2_ecdsa_process_pubkeys(&P, pa_rev_bytes_pubX, pa_rev_bytes_pubY, use_jproj_coords, status); if(!MBX_IS_ANY_OK_STS(status)) return status; __ALIGN64 int8u msg_digest[8][PSM2_LEN8]; int8u* pa_msg_digest[8] = {msg_digest[0], msg_digest[1], msg_digest[2], msg_digest[3], msg_digest[4], msg_digest[5], msg_digest[6], msg_digest[7]}; /* compute z digest */ sm2_ecdsa_compute_z_digest(pa_msg_digest, (const int8u **)pa_user_id, (const int *)user_id_len_checked, (const int8u **)pa_rev_bytes_pubX, (const int8u **)pa_rev_bytes_pubY); /* compute msg digest */ sm2_ecdsa_compute_msg_digest(pa_msg_digest, (const int8u **)pa_msg_digest, (const int8u **)pa_msg, (const int *)msg_len); __ALIGN64 U64 msg[PSM2_LEN52]; ifma_HexStr8_to_mb8((int64u (*)[8])msg, (const int8u* const*)pa_msg_digest, PSM2_BITSIZE); status = sm2_ecdsa_verify_mb8(sign_r, sign_s, msg, &P, status); return status; } #endif /* BN_OPENSSL_DISABLE */ #endif /* #if (_MBX>=_MBX_K1) */internal_ifma_ecdh_sm2.c000066400000000000000000000150741470420105600341110ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_sm2_ecdh_ssl_mb8(int8u* pa_shared_key[8], const BIGNUM* const pa_skey[8], const BIGNUM* const pa_pubx[8], const BIGNUM* const pa_puby[8], const BIGNUM* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[PSM2_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])secretz, (const BIGNUM**)pa_skey, PSM2_BITSIZE); secretz[PSM2_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, PSM2_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } SM2_POINT P; /* set party's public */ ifma_BN_to_mb8((int64u (*)[8])P.X, (const BIGNUM* (*))pa_pubx, PSM2_BITSIZE); /* P-> radix 2^52 */ ifma_BN_to_mb8((int64u (*)[8])P.Y, (const BIGNUM* (*))pa_puby, PSM2_BITSIZE); if(use_jproj_coords) ifma_BN_to_mb8((int64u (*)[8])P.Z, (const BIGNUM* (*))pa_pubz, PSM2_BITSIZE); else MB_FUNC_NAME(mov_FESM2_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_psm2_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_psm2_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_psm2_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_psm2_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } SM2_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_sm2_mul_point_)(&R, &P, secretz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[PSM2_LEN52]; ifma_aminv52_psm2_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_psm2_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_psm2_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_psm2_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, PSM2_BITSIZE); /* clear computed shared keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif // BN_OPENSSL_DISABLE mbx_status internal_avx512_sm2_ecdh_mb8(int8u* pa_shared_key[8], const int64u* const pa_skey[8], const int64u* const pa_pubx[8], const int64u* const pa_puby[8], const int64u* const pa_pubz[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded private keys */ U64 secretz[PSM2_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])secretz, (const int64u**)pa_skey, PSM2_BITSIZE); secretz[PSM2_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(secretz, PSM2_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } SM2_POINT P; /* set party's public */ ifma_BNU_to_mb8((int64u (*)[8])P.X, (const int64u* (*))pa_pubx, PSM2_BITSIZE); // P-> crypto_mb radix 2^52 ifma_BNU_to_mb8((int64u (*)[8])P.Y, (const int64u* (*))pa_puby, PSM2_BITSIZE); if(use_jproj_coords) ifma_BNU_to_mb8((int64u (*)[8])P.Z, (const int64u* (*))pa_pubz, PSM2_BITSIZE); else MB_FUNC_NAME(mov_FESM2_)(P.Z, (U64*)ones); /* convert to Montgomery */ MB_FUNC_NAME(ifma_tomont52_psm2_)(P.X, P.X); MB_FUNC_NAME(ifma_tomont52_psm2_)(P.Y, P.Y); MB_FUNC_NAME(ifma_tomont52_psm2_)(P.Z, P.Z); /* check if P does not belong to EC */ __mb_mask not_on_curve_mask = ~MB_FUNC_NAME(ifma_is_on_curve_psm2_)(&P, use_jproj_coords); /* set points out of EC to infinity */ MB_FUNC_NAME(mask_set_point_to_infinity_)(&P, not_on_curve_mask); /* update status */ status |= MBX_SET_STS_BY_MASK(status, not_on_curve_mask, MBX_STATUS_MISMATCH_PARAM_ERR); if(!MBX_IS_ANY_OK_STS(status)) { /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); return status; } SM2_POINT R; /* compute R = [secretz]*P */ MB_FUNC_NAME(ifma_ec_sm2_mul_point_)(&R, &P, secretz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])secretz, sizeof(secretz)/sizeof(U64)); /* return affine R.x */ __ALIGN64 U64 Z2[PSM2_LEN52]; ifma_aminv52_psm2_mb8(Z2, R.Z); /* 1/Z */ ifma_ams52_psm2_mb8(Z2, Z2); /* 1/Z^2 */ ifma_amm52_psm2_mb8(R.X, R.X, Z2); /* x = (X) * (1/Z^2) */ /* to regular domain */ MB_FUNC_NAME(ifma_frommont52_psm2_)(R.X, R.X); /* store result */ ifma_mb8_to_HexStr8(pa_shared_key, (const int64u (*)[8])R.X, PSM2_BITSIZE); /* clear computed shared keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])&R, sizeof(R)/sizeof(U64)); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_ifma_ecpubkey_sm2.c000066400000000000000000000120551470420105600350110ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm2/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef BN_OPENSSL_DISABLE #include #endif #ifndef BN_OPENSSL_DISABLE mbx_status internal_avx512_sm2_ecpublic_key_ssl_mb8(BIGNUM* pa_pubx[8], BIGNUM* pa_puby[8], BIGNUM* pa_pubz[8], const BIGNUM* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; int buf_no = 0; /* zero padded keys */ U64 scalarz[PSM2_LEN64+1]; ifma_BN_transpose_copy((int64u (*)[8])scalarz, pa_skey, PSM2_BITSIZE); scalarz[PSM2_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, PSM2_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ SM2_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_sm2_mul_pointbase_)(&P, scalarz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_sm2_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_psm2_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_psm2_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_psm2_)(P.Z, P.Z); /* convert public key and store BIGNUM result */ const int len_coord = NUMBER_OF_DIGITS(PSM2_BITSIZE,8); int8u tmp[8][NUMBER_OF_DIGITS(PSM2_BITSIZE,8)]; /* need set inplace - MSVC compiler problem */ int8u* const pa_tmp[8] = {tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5],tmp[6],tmp[7]}; /* X */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.X, PSM2_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], len_coord, pa_pubx[buf_no]); } /* Y */ ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Y, PSM2_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], len_coord, pa_puby[buf_no]); } /* Z */ if(use_jproj_coords) { ifma_mb8_to_HexStr8(pa_tmp, (const int64u (*)[8])P.Z, PSM2_BITSIZE); for(buf_no=0; (buf_no<8) && (0==MBX_GET_STS(status, buf_no)); buf_no++) { BN_bin2bn(pa_tmp[buf_no], len_coord, pa_pubz[buf_no]); } } return status; } #endif // BN_OPENSSL_DISABLE mbx_status internal_avx512_sm2_ecpublic_key_mb8(int64u* pa_pubx[8], int64u* pa_puby[8], int64u* pa_pubz[8], const int64u* const pa_skey[8], int8u* pBuffer, int use_jproj_coords) { mbx_status status = 0; /* zero padded keys */ U64 scalarz[PSM2_LEN64+1]; ifma_BNU_transpose_copy((int64u (*)[8])scalarz, pa_skey, PSM2_BITSIZE); scalarz[PSM2_LEN64] = get_zero64(); status |= MBX_SET_STS_BY_MASK(status, is_zero(scalarz, PSM2_LEN64+1), MBX_STATUS_MISMATCH_PARAM_ERR); /* do not need to clear copy of secret keys before this return - all of them is NULL or zero */ if(!MBX_IS_ANY_OK_STS(status)) return status; /* public key */ SM2_POINT P; /* compute public keys */ MB_FUNC_NAME(ifma_ec_sm2_mul_pointbase_)(&P, scalarz); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalarz, sizeof(scalarz)/sizeof(U64)); if(!use_jproj_coords) MB_FUNC_NAME(get_sm2_ec_affine_coords_)(P.X, P.Y, &P); /* convert P coordinates to regular domain */ MB_FUNC_NAME(ifma_frommont52_psm2_)(P.X, P.X); MB_FUNC_NAME(ifma_frommont52_psm2_)(P.Y, P.Y); if(use_jproj_coords) MB_FUNC_NAME(ifma_frommont52_psm2_)(P.Z, P.Z); /* store result */ ifma_mb8_to_BNU(pa_pubx, (const int64u (*)[8])P.X, PSM2_BITSIZE); ifma_mb8_to_BNU(pa_puby, (const int64u (*)[8])P.Y, PSM2_BITSIZE); if(use_jproj_coords) ifma_mb8_to_BNU(pa_pubz, (const int64u (*)[8])P.Z, PSM2_BITSIZE); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/000077500000000000000000000000001470420105600245205ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/internal_avx512/000077500000000000000000000000001470420105600274425ustar00rootroot00000000000000internal_sm3_final_mb16.c000066400000000000000000000132351470420105600341270ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 internal_avx512_sm3_final_mb16(int8u* hash_pa[16], SM3_CTX_mb16* p_state) { mbx_status16 status = 0; int i; __ALIGN64 int input_len[SM3_NUM_BUFFERS]; __ALIGN64 int buffer_len[SM3_NUM_BUFFERS]; __ALIGN64 int64u sum_msg_len[SM3_NUM_BUFFERS]; /* allocate local buffer */ __ALIGN64 int8u loc_buffer[SM3_NUM_BUFFERS][SM3_MSG_BLOCK_SIZE*2]; const int8u* buffer_pa[SM3_NUM_BUFFERS] = { loc_buffer[0], loc_buffer[1], loc_buffer[2], loc_buffer[3], loc_buffer[4], loc_buffer[5], loc_buffer[6], loc_buffer[7], loc_buffer[8], loc_buffer[9], loc_buffer[10], loc_buffer[11], loc_buffer[12], loc_buffer[13], loc_buffer[14], loc_buffer[15] }; __m512i zero_buffer = _mm512_setzero_si512(); /* // create __mmask8 and __mmask16 based on input hash_pa // corresponding element in mask = 0 if hash_pa[i] = 0 */ __mmask8 mb_mask8[2]; mb_mask8[0] = _mm512_cmp_epi64_mask(_mm512_loadu_si512(hash_pa), zero_buffer, _MM_CMPINT_NE); mb_mask8[1] = _mm512_cmp_epi64_mask(_mm512_loadu_si512(hash_pa + 8), zero_buffer, _MM_CMPINT_NE); __mmask16 mb_mask16 = *(__mmask16*)mb_mask8; __m512i sum_msg_len_m512_low = _mm512_maskz_loadu_epi64(mb_mask8[0], MSG_LEN(p_state)); __m512i sum_msg_len_m512_high = _mm512_maskz_loadu_epi64(mb_mask8[1], MSG_LEN(p_state) + 8); /* put processed message length in bits */ sum_msg_len_m512_low = _mm512_rol_epi64(sum_msg_len_m512_low, 3); sum_msg_len_m512_high = _mm512_rol_epi64(sum_msg_len_m512_high, 3); sum_msg_len_m512_low = _mm512_shuffle_epi8(sum_msg_len_m512_low, _mm512_loadu_si512(swapBytes)); sum_msg_len_m512_high = _mm512_shuffle_epi8(sum_msg_len_m512_high, _mm512_loadu_si512(swapBytes)); _mm512_storeu_si512(sum_msg_len, sum_msg_len_m512_low); _mm512_storeu_si512(sum_msg_len + 8, sum_msg_len_m512_high); __m512i input_len_m512 = _mm512_maskz_loadu_epi32(mb_mask16, HASH_BUFFIDX(p_state)); _mm512_storeu_si512(input_len, input_len_m512); __mmask16 tmp_mask = _mm512_cmplt_epi32_mask(input_len_m512, _mm512_set1_epi32(SM3_MSG_BLOCK_SIZE - (int)SM3_MSG_LEN_REPR)); __m512i buffer_len_m512 = _mm512_mask_set1_epi32(_mm512_set1_epi32(SM3_MSG_BLOCK_SIZE * 2), tmp_mask, SM3_MSG_BLOCK_SIZE); buffer_len_m512 = _mm512_mask_set1_epi32(buffer_len_m512, ~mb_mask16, 0); buffer_len_m512 = _mm512_mask_set1_epi32(buffer_len_m512, ~mb_mask16, 0); _mm512_storeu_si512(buffer_len, buffer_len_m512); for (i = 0; i < SM3_NUM_BUFFERS; i++) { /* Copy rest of message into internal buffer */ if ((mb_mask16 >> i) & 0x1) { __mmask64 mb_mask64 = ~(0xFFFFFFFFFFFFFFFF << input_len[i]); __m512i loc_buffer_m512 = _mm512_maskz_loadu_epi8(mb_mask64, HASH_BUFF(p_state)[i]); _mm512_storeu_si512(loc_buffer[i], loc_buffer_m512); /* Pad message */ loc_buffer[i][input_len[i]++] = 0x80; pad_block(0, loc_buffer[i] + input_len[i], (int)(buffer_len[i] - input_len[i] - (int)SM3_MSG_LEN_REPR)); ((int64u*)(loc_buffer[i] + buffer_len[i]))[-1] = sum_msg_len[i]; } } /* Copmplete hash computation */ sm3_avx512_mb16(HASH_VALUE(p_state), buffer_pa, buffer_len); /* Convert hash into big endian */ __m512i T[8]; const int32u* p_T[8] = { (int32u*)&T[0], (int32u*)&T[1], (int32u*)&T[2], (int32u*)&T[3], (int32u*)&T[4], (int32u*)&T[5], (int32u*)&T[6], (int32u*)&T[7] }; T[0] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[0])); T[1] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[1])); T[2] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[2])); T[3] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[3])); T[4] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[4])); T[5] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[5])); T[6] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[6])); T[7] = SIMD_ENDIANNESS32(_mm512_loadu_si512(HASH_VALUE(p_state)[7])); /* Transpose hash and store in array with pointers to hash values */ TRANSPOSE_8X16_I32((int32u**)hash_pa, p_T, mb_mask16); /* re-init hash value using mb masks */ _mm512_storeu_si512(MSG_LEN(p_state), _mm512_mask_set1_epi64(_mm512_loadu_si512(MSG_LEN(p_state)), mb_mask8[0], 0)); _mm512_storeu_si512(MSG_LEN(p_state)+8, _mm512_mask_set1_epi64(_mm512_loadu_si512(MSG_LEN(p_state)+8), mb_mask8[1], 0)); _mm512_storeu_si512(HASH_BUFFIDX(p_state), _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_BUFFIDX(p_state)), mb_mask16, 0)); internal_avx512_sm3_mask_init_mb16(p_state, mb_mask16); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_sm3_init_mb16.c000066400000000000000000000056511470420105600340040ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 internal_avx512_sm3_mask_init_mb16(SM3_CTX_mb16 * p_state, __mmask16 mb_mask) { mbx_status16 status = 0; __mmask8 mb_mask8[2]; mb_mask8[0] = (__mmask8)mb_mask; mb_mask8[1] = *((__mmask8*)&mb_mask + 1); /* clear buffer index */ _mm512_storeu_si512(HASH_BUFFIDX(p_state), _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_BUFFIDX(p_state)), mb_mask, 0)); /* clear summary message length */ _mm512_storeu_si512(MSG_LEN(p_state), _mm512_maskz_loadu_epi64(~mb_mask8[0], MSG_LEN(p_state))); _mm512_storeu_si512(MSG_LEN(p_state) + 8, _mm512_maskz_loadu_epi64(~mb_mask8[1], MSG_LEN(p_state) + 8)); /* clear buffer */ for (int i = 0; i < SM3_NUM_BUFFERS; i++) { if ((mb_mask >> i) & 1) _mm512_storeu_si512(HASH_BUFF(p_state)[i], _mm512_setzero_si512()); } /* setup initial digest in multi-buffer format */ _mm512_storeu_si512(HASH_VALUE(p_state)[0], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[0]), mb_mask, (int)sm3_iv[0])); _mm512_storeu_si512(HASH_VALUE(p_state)[1], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[1]), mb_mask, (int)sm3_iv[1])); _mm512_storeu_si512(HASH_VALUE(p_state)[2], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[2]), mb_mask, (int)sm3_iv[2])); _mm512_storeu_si512(HASH_VALUE(p_state)[3], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[3]), mb_mask, (int)sm3_iv[3])); _mm512_storeu_si512(HASH_VALUE(p_state)[4], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[4]), mb_mask, (int)sm3_iv[4])); _mm512_storeu_si512(HASH_VALUE(p_state)[5], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[5]), mb_mask, (int)sm3_iv[5])); _mm512_storeu_si512(HASH_VALUE(p_state)[6], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[6]), mb_mask, (int)sm3_iv[6])); _mm512_storeu_si512(HASH_VALUE(p_state)[7], _mm512_mask_set1_epi32(_mm512_loadu_si512(HASH_VALUE(p_state)[7]), mb_mask, (int)sm3_iv[7])); return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_sm3_messagedigest_mb16.c000066400000000000000000000032351470420105600356610ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 internal_avx512_sm3_msg_digest_mb16(const int8u* const msg_pa[16], int len[16], int8u* hash_pa[16]) { mbx_status16 status = 0; for (int buf_no = 0; buf_no < SM3_NUM_BUFFERS; buf_no++) { if ((len[buf_no] && !hash_pa[buf_no]) || (len[buf_no] && !msg_pa[buf_no])) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); return status; } } /* initialize the context of SM3 hash */ SM3_CTX_mb16 p_state; mbx_sm3_init_mb16(&p_state); /* process main part of the message */ status = mbx_sm3_update_mb16(msg_pa, len, &p_state); if(MBX_IS_ANY_OK_STS16(status)) { /* finalize message processing */ status = mbx_sm3_final_mb16(hash_pa, &p_state); } return status; } #endif /* #if (_MBX>=_MBX_K1) */ internal_sm3_update_mb16.c000066400000000000000000000201611470420105600343140ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 internal_avx512_sm3_update_mb16(const int8u* const msg_pa[16], int len[16], SM3_CTX_mb16* p_state) { mbx_status16 status = 0; int i; __m512i loc_len = _mm512_loadu_si512(len); int* p_loc_len = (int*)&loc_len; /* generate mask based on array with messages lengths */ __m512i zero_buffer = _mm512_setzero_si512(); __mmask16 mb_mask16 = _mm512_cmp_epi32_mask(loc_len, zero_buffer, _MM_CMPINT_NE); /* generate mask based on array with pointers to messages */ __mmask8 mb_mask8[2]; mb_mask8[0] = _mm512_cmp_epi64_mask(_mm512_loadu_si512(msg_pa), zero_buffer, _MM_CMPINT_NE); mb_mask8[1] = _mm512_cmp_epi64_mask(_mm512_loadu_si512(msg_pa + 8), zero_buffer, _MM_CMPINT_NE); /* don't process the data from i buffer if in msg_pa[i] == 0 or len[i] == 0 */ mb_mask16 &= *(__mmask16*)mb_mask8; mb_mask8[0] = (__mmask8)mb_mask16; mb_mask8[1] = *((__mmask8*)&mb_mask16 + 1); /* handle non empty request */ if (mb_mask16) { __ALIGN64 const int8u* loc_src[SM3_NUM_BUFFERS]; /* We need the address of the zero_buffer to form the fully valid array of pointers loc_src */ _mm512_storeu_si512((void*)loc_src, _mm512_mask_loadu_epi64(_mm512_set1_epi64((long long)&zero_buffer), mb_mask8[0], msg_pa)); _mm512_storeu_si512((void *)(loc_src + 8), _mm512_mask_loadu_epi64(_mm512_set1_epi64((long long)&zero_buffer), mb_mask8[1], msg_pa + 8)); __m512i proc_len; __m512i idx = _mm512_loadu_si512(HASH_BUFFIDX(p_state)); int* p_proc_len = (int*)&proc_len; int* p_idx = (int*)&idx; __ALIGN64 int64u sum_msg_len[SM3_NUM_BUFFERS] = { (int64u)p_loc_len[0], (int64u)p_loc_len[1], (int64u)p_loc_len[2], (int64u)p_loc_len[3], (int64u)p_loc_len[4], (int64u)p_loc_len[5], (int64u)p_loc_len[6], (int64u)p_loc_len[7], (int64u)p_loc_len[8], (int64u)p_loc_len[9], (int64u)p_loc_len[10], (int64u)p_loc_len[11], (int64u)p_loc_len[12], (int64u)p_loc_len[13], (int64u)p_loc_len[14], (int64u)p_loc_len[15] }; __ALIGN64 int8u* p_buffer[SM3_NUM_BUFFERS] = { HASH_BUFF(p_state)[0], HASH_BUFF(p_state)[1], HASH_BUFF(p_state)[2], HASH_BUFF(p_state)[3], HASH_BUFF(p_state)[4], HASH_BUFF(p_state)[5], HASH_BUFF(p_state)[6], HASH_BUFF(p_state)[7], HASH_BUFF(p_state)[8], HASH_BUFF(p_state)[9], HASH_BUFF(p_state)[10], HASH_BUFF(p_state)[11], HASH_BUFF(p_state)[12], HASH_BUFF(p_state)[13], HASH_BUFF(p_state)[14], HASH_BUFF(p_state)[15] }; __mmask16 processed_mask = _mm512_cmp_epi32_mask(idx, zero_buffer, _MM_CMPINT_NE); __m512i sum_msg_len_m512_low = _mm512_loadu_si512(sum_msg_len); __m512i sum_msg_len_m512_high = _mm512_loadu_si512(sum_msg_len + 8); sum_msg_len_m512_low = _mm512_mask_add_epi64(sum_msg_len_m512_low, mb_mask8[0], _mm512_loadu_si512(MSG_LEN(p_state)), sum_msg_len_m512_low); sum_msg_len_m512_high = _mm512_mask_add_epi64(sum_msg_len_m512_high, mb_mask8[1], _mm512_loadu_si512(MSG_LEN(p_state) + 8), sum_msg_len_m512_high); _mm512_storeu_si512(sum_msg_len, sum_msg_len_m512_low); _mm512_storeu_si512(sum_msg_len + 8, sum_msg_len_m512_high); __m512i loc_src_m512_low = _mm512_loadu_si512(loc_src); __m512i loc_src_m512_high = _mm512_loadu_si512(loc_src + 8); /* if non empty internal buffer filling */ if (processed_mask) { /* calculate how many bytes need to be added in the internal buffer */ __m512i empty_bytes_buffer = _mm512_sub_epi32(_mm512_set1_epi32(SM3_MSG_BLOCK_SIZE), idx); processed_mask = _mm512_cmp_epi32_mask(_mm512_sub_epi32(loc_len, empty_bytes_buffer), zero_buffer, _MM_CMPINT_LT); proc_len = _mm512_mask_loadu_epi32(empty_bytes_buffer, processed_mask, p_loc_len); /* copy from valid input streams to the internal buffers as much as possible */ for (i = 0; i < SM3_NUM_BUFFERS; i++) { if ((mb_mask16 >> i) & 0x1) { __mmask64 mb_mask64 = 0xFFFFFFFFFFFFFFFF >> (SM3_MSG_BLOCK_SIZE - p_proc_len[i]); _mm512_storeu_si512(p_buffer[i] + p_idx[i], _mm512_mask_loadu_epi8(_mm512_loadu_si512(p_buffer[i] + p_idx[i]), mb_mask64, loc_src[i])); } } idx = _mm512_add_epi32(idx, proc_len); loc_len = _mm512_sub_epi32(loc_len, proc_len); loc_src_m512_low = _mm512_add_epi64(loc_src_m512_low, _mm512_cvtepu32_epi64(_mm512_castsi512_si256(proc_len))); loc_src_m512_high = _mm512_add_epi64(loc_src_m512_high, _mm512_cvtepu32_epi64(_mm512_extracti32x8_epi32(proc_len, 1))); _mm512_storeu_si512((void*)loc_src, loc_src_m512_low); _mm512_storeu_si512((void*)(loc_src + 8), loc_src_m512_high); processed_mask = _mm512_cmp_epi32_mask(idx, _mm512_set1_epi32(SM3_MSG_BLOCK_SIZE), _MM_CMPINT_EQ); proc_len = _mm512_maskz_set1_epi32(processed_mask, SM3_MSG_BLOCK_SIZE); /* update digest if at least one buffer is full */ if (processed_mask) { sm3_avx512_mb16(HASH_VALUE(p_state), (const int8u **)p_buffer, p_proc_len); idx = _mm512_mask_set1_epi32(idx, ~_mm512_cmp_epi32_mask(proc_len, zero_buffer, _MM_CMPINT_LE), 0); } } /* main message part processing */ proc_len = _mm512_and_epi32(loc_len, _mm512_set1_epi32(-SM3_MSG_BLOCK_SIZE)); processed_mask = _mm512_cmp_epi32_mask(proc_len, zero_buffer, _MM_CMPINT_NLT); if (processed_mask) sm3_avx512_mb16(HASH_VALUE(p_state), loc_src, p_proc_len); loc_len = _mm512_sub_epi32(loc_len, proc_len); loc_src_m512_low = _mm512_add_epi64(loc_src_m512_low, _mm512_cvtepu32_epi64(_mm512_castsi512_si256(proc_len))); loc_src_m512_high = _mm512_add_epi64(loc_src_m512_high, _mm512_cvtepu32_epi64(_mm512_extracti32x8_epi32(proc_len, 1))); _mm512_storeu_si512((void*)loc_src, loc_src_m512_low); _mm512_storeu_si512((void*)(loc_src + 8), loc_src_m512_high); processed_mask = _mm512_cmp_epi32_mask(loc_len, zero_buffer, _MM_CMPINT_NLE); /* store rest of message into the internal buffer */ for (i = 0; i < SM3_NUM_BUFFERS; i++) { if ((processed_mask >> i) & 0x1) { __mmask64 mb_mask64 = ~(0xFFFFFFFFFFFFFFFF << *(p_loc_len + i)); _mm512_storeu_si512(p_buffer[i], _mm512_maskz_loadu_epi8(mb_mask64, loc_src[i])); } } idx = _mm512_add_epi32(idx, loc_len); /* Update length of processed message */ _mm512_storeu_si512(MSG_LEN(p_state), _mm512_mask_loadu_epi64(_mm512_loadu_si512(MSG_LEN(p_state)), mb_mask8[0], sum_msg_len)); _mm512_storeu_si512(MSG_LEN(p_state) + 8, _mm512_mask_loadu_epi64(_mm512_loadu_si512(MSG_LEN(p_state) + 8), mb_mask8[1], sum_msg_len + 8)); _mm512_storeu_si512(HASH_BUFFIDX(p_state), _mm512_mask_loadu_epi32(_mm512_loadu_si512(HASH_BUFFIDX(p_state)), mb_mask16, p_idx)); } return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_avx512_mb16.c000066400000000000000000000424501470420105600273260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) __MBX_INLINE void TRANSPOSE_16X16_I32(int32u out[][16], const int32u* const inp[16]) { __m512i r0 = _mm512_loadu_si512(inp[0]); __m512i r1 = _mm512_loadu_si512(inp[1]); __m512i r2 = _mm512_loadu_si512(inp[2]); __m512i r3 = _mm512_loadu_si512(inp[3]); __m512i r4 = _mm512_loadu_si512(inp[4]); __m512i r5 = _mm512_loadu_si512(inp[5]); __m512i r6 = _mm512_loadu_si512(inp[6]); __m512i r7 = _mm512_loadu_si512(inp[7]); __m512i r8 = _mm512_loadu_si512(inp[8]); __m512i r9 = _mm512_loadu_si512(inp[9]); __m512i r10 = _mm512_loadu_si512(inp[10]); __m512i r11 = _mm512_loadu_si512(inp[11]); __m512i r12 = _mm512_loadu_si512(inp[12]); __m512i r13 = _mm512_loadu_si512(inp[13]); __m512i r14 = _mm512_loadu_si512(inp[14]); __m512i r15 = _mm512_loadu_si512(inp[15]); // tansposition __m512i t0 = _mm512_unpacklo_epi32(r0, r1); // 0 16 1 17 4 20 5 21 8 24 9 25 12 28 13 29 __m512i t1 = _mm512_unpackhi_epi32(r0, r1); // 2 18 3 19 6 22 7 23 10 26 11 27 14 30 15 31 __m512i t2 = _mm512_unpacklo_epi32(r2, r3); // 32 48 33 49 ... __m512i t3 = _mm512_unpackhi_epi32(r2, r3); // 34 50 35 51 ... __m512i t4 = _mm512_unpacklo_epi32(r4, r5); // 64 80 65 81 ... __m512i t5 = _mm512_unpackhi_epi32(r4, r5); // 66 82 67 83 ... __m512i t6 = _mm512_unpacklo_epi32(r6, r7); // 96 112 97 113 ... __m512i t7 = _mm512_unpackhi_epi32(r6, r7); // 98 114 99 115 ... __m512i t8 = _mm512_unpacklo_epi32(r8, r9); // 128 ... __m512i t9 = _mm512_unpackhi_epi32(r8, r9); // 130 ... __m512i t10 = _mm512_unpacklo_epi32(r10, r11); // 160 ... __m512i t11 = _mm512_unpackhi_epi32(r10, r11); // 162 ... __m512i t12 = _mm512_unpacklo_epi32(r12, r13); // 196 ... __m512i t13 = _mm512_unpackhi_epi32(r12, r13); // 198 ... __m512i t14 = _mm512_unpacklo_epi32(r14, r15); // 228 ... __m512i t15 = _mm512_unpackhi_epi32(r14, r15); // 230 ... r0 = _mm512_unpacklo_epi64(t0, t2); // 0 16 32 48 ... r1 = _mm512_unpackhi_epi64(t0, t2); // 1 17 33 49 ... r2 = _mm512_unpacklo_epi64(t1, t3); // 2 18 34 49 ... r3 = _mm512_unpackhi_epi64(t1, t3); // 3 19 35 51 ... r4 = _mm512_unpacklo_epi64(t4, t6); // 64 80 96 112 ... r5 = _mm512_unpackhi_epi64(t4, t6); // 65 81 97 114 ... r6 = _mm512_unpacklo_epi64(t5, t7); // 66 82 98 113 ... r7 = _mm512_unpackhi_epi64(t5, t7); // 67 83 99 115 ... r8 = _mm512_unpacklo_epi64(t8, t10); // 128 144 160 176 ... r9 = _mm512_unpackhi_epi64(t8, t10); // 129 145 161 178 ... r10 = _mm512_unpacklo_epi64(t9, t11); // 130 146 162 177 ... r11 = _mm512_unpackhi_epi64(t9, t11); // 131 147 163 179 ... r12 = _mm512_unpacklo_epi64(t12, t14); // 192 208 228 240 ... r13 = _mm512_unpackhi_epi64(t12, t14); // 193 209 229 241 ... r14 = _mm512_unpacklo_epi64(t13, t15); // 194 210 230 242 ... r15 = _mm512_unpackhi_epi64(t13, t15); // 195 211 231 243 ... t0 = _mm512_shuffle_i32x4(r0, r4, 0x88); // 0 16 32 48 8 24 40 56 64 80 96 112 ... t1 = _mm512_shuffle_i32x4(r1, r5, 0x88); // 1 17 33 49 ... t2 = _mm512_shuffle_i32x4(r2, r6, 0x88); // 2 18 34 50 ... t3 = _mm512_shuffle_i32x4(r3, r7, 0x88); // 3 19 35 51 ... t4 = _mm512_shuffle_i32x4(r0, r4, 0xdd); // 4 20 36 52 ... t5 = _mm512_shuffle_i32x4(r1, r5, 0xdd); // 5 21 37 53 ... t6 = _mm512_shuffle_i32x4(r2, r6, 0xdd); // 6 22 38 54 ... t7 = _mm512_shuffle_i32x4(r3, r7, 0xdd); // 7 23 39 55 ... t8 = _mm512_shuffle_i32x4(r8, r12, 0x88); // 128 144 160 176 ... t9 = _mm512_shuffle_i32x4(r9, r13, 0x88); // 129 145 161 177 ... t10 = _mm512_shuffle_i32x4(r10, r14, 0x88); // 130 146 162 178 ... t11 = _mm512_shuffle_i32x4(r11, r15, 0x88); // 131 147 163 179 ... t12 = _mm512_shuffle_i32x4(r8, r12, 0xdd); // 132 148 164 180 ... t13 = _mm512_shuffle_i32x4(r9, r13, 0xdd); // 133 149 165 181 ... t14 = _mm512_shuffle_i32x4(r10, r14, 0xdd); // 134 150 166 182 ... t15 = _mm512_shuffle_i32x4(r11, r15, 0xdd); // 135 151 167 183 ... r0 = _mm512_shuffle_i32x4(t0, t8, 0x88); // 0 16 32 48 64 80 96 112 ... 240 r1 = _mm512_shuffle_i32x4(t1, t9, 0x88); // 1 17 33 49 66 81 97 113 ... 241 r2 = _mm512_shuffle_i32x4(t2, t10, 0x88); // 2 18 34 50 67 82 98 114 ... 242 r3 = _mm512_shuffle_i32x4(t3, t11, 0x88); // 3 19 35 51 68 83 99 115 ... 243 r4 = _mm512_shuffle_i32x4(t4, t12, 0x88); // 4 ... r5 = _mm512_shuffle_i32x4(t5, t13, 0x88); // 5 ... r6 = _mm512_shuffle_i32x4(t6, t14, 0x88); // 6 ... r7 = _mm512_shuffle_i32x4(t7, t15, 0x88); // 7 ... r8 = _mm512_shuffle_i32x4(t0, t8, 0xdd); // 8 ... r9 = _mm512_shuffle_i32x4(t1, t9, 0xdd); // 9 ... r10 = _mm512_shuffle_i32x4(t2, t10, 0xdd); // 10 ... r11 = _mm512_shuffle_i32x4(t3, t11, 0xdd); // 11 ... r12 = _mm512_shuffle_i32x4(t4, t12, 0xdd); // 12 ... r13 = _mm512_shuffle_i32x4(t5, t13, 0xdd); // 13 ... r14 = _mm512_shuffle_i32x4(t6, t14, 0xdd); // 14 ... r15 = _mm512_shuffle_i32x4(t7, t15, 0xdd); // 15 31 47 63 79 96 111 127 ... 255 _mm512_storeu_si512(out[0], r0); _mm512_storeu_si512(out[1], r1); _mm512_storeu_si512(out[2], r2); _mm512_storeu_si512(out[3], r3); _mm512_storeu_si512(out[4], r4); _mm512_storeu_si512(out[5], r5); _mm512_storeu_si512(out[6], r6); _mm512_storeu_si512(out[7], r7); _mm512_storeu_si512(out[8], r8); _mm512_storeu_si512(out[9], r9); _mm512_storeu_si512(out[10], r10); _mm512_storeu_si512(out[11], r11); _mm512_storeu_si512(out[12], r12); _mm512_storeu_si512(out[13], r13); _mm512_storeu_si512(out[14], r14); _mm512_storeu_si512(out[15], r15); } /* Boolean functions (0<=nr<16) */ #define FF1(X,Y,Z) (_mm512_xor_epi32(_mm512_xor_epi32(X,Y), Z)) #define GG1(X,Y,Z) (_mm512_xor_epi32(_mm512_xor_epi32(X,Y), Z)) /* Boolean functions (16<=nr<64) */ #define FF2(X,Y,Z) (_mm512_or_epi32(_mm512_or_epi32(_mm512_and_epi32(X,Y),_mm512_and_epi32(X,Z)),_mm512_and_epi32(Y,Z))) #define GG2(X,Y,Z) (_mm512_or_epi32(_mm512_and_epi32(X,Y),_mm512_andnot_epi32(X,Z))) /* P0 permutation: */ #define P0(X) (_mm512_xor_epi32(_mm512_xor_epi32(X, _mm512_rol_epi32 (X, 9)), _mm512_rol_epi32 (X, 17))) /* P1 permutation: */ #define P1(X) (_mm512_xor_epi32(_mm512_xor_epi32(X, _mm512_rol_epi32 (X, 15)), _mm512_rol_epi32 (X, 23))) /* Update W */ #define WUPDATE(nr, W) (_mm512_xor_epi32(_mm512_xor_epi32(P1(_mm512_xor_epi32(_mm512_xor_epi32(W[(nr-16)&15], W[(nr-9)&15]), _mm512_rol_epi32 (W[(nr-3)&15], 15))), _mm512_rol_epi32(W[(nr-13)&15],7)), W[(nr-6)&15])) // SM3 steps /* (0<=nr<16) */ #define STEP1_SM3(nr, A,B,C,D,E,F,G,H, Tj, W) {\ __m512i SS1 = _mm512_rol_epi32(_mm512_add_epi32(_mm512_add_epi32(_mm512_rol_epi32(A, 12), E), _mm512_set1_epi32((int)Tj)),7);\ __m512i SS2 = _mm512_xor_epi32(SS1, _mm512_rol_epi32(A, 12));\ __m512i TT1 = _mm512_add_epi32(_mm512_add_epi32(_mm512_add_epi32(FF1(A, B, C), D), SS2), _mm512_xor_epi32(W[nr&15], W[(nr+4)&15]));\ __m512i TT2 = _mm512_add_epi32(_mm512_add_epi32(_mm512_add_epi32(GG1(E, F, G), H), SS1), W[nr&15]);\ D = _mm512_load_epi32((void*)&C); \ C = _mm512_rol_epi32(B, 9); \ B = _mm512_load_epi32((void*)&A); \ A = _mm512_load_epi32((void*)&TT1);\ H = _mm512_load_epi32((void*)&G); \ G = _mm512_rol_epi32(F, 19); \ F = _mm512_load_epi32((void*)&E); \ E = P0(TT2); \ W[(nr)&15]=WUPDATE(nr, W); \ } /* (16<=nr<64) */ #define STEP2_SM3(nr, A,B,C,D,E,F,G,H, Tj, W) {\ __m512i SS1 = _mm512_rol_epi32(_mm512_add_epi32(_mm512_add_epi32(_mm512_rol_epi32(A, 12), E), _mm512_set1_epi32((int)Tj)),7);\ __m512i SS2 = _mm512_xor_epi32(SS1, _mm512_rol_epi32(A, 12));\ __m512i TT1 = _mm512_add_epi32(_mm512_add_epi32(_mm512_add_epi32(FF2(A, B, C), D), SS2), _mm512_xor_epi32(W[nr&15], W[(nr+4)&15]));\ __m512i TT2 = _mm512_add_epi32(_mm512_add_epi32(_mm512_add_epi32(GG2(E, F, G), H), SS1), W[nr&15]);\ D = _mm512_load_epi32((void*)&C); \ C = _mm512_rol_epi32(B, 9); \ B = _mm512_load_epi32((void*)&A); \ A = _mm512_load_epi32((void*)&TT1);\ H = _mm512_load_epi32((void*)&G); \ G = _mm512_rol_epi32(F, 19); \ F = _mm512_load_epi32((void*)&E); \ E = P0(TT2); \ W[(nr)&15]=WUPDATE(nr, W); \ } void sm3_avx512_mb16(int32u hash_pa[][16], const int8u* const msg_pa[16], int len[16]) { int i; __ALIGN64 int32u* loc_data[SM3_NUM_BUFFERS]; __m512i W[16]; __m512i Vi[8]; __m512i A, B, C, D, E, F, G, H; /* Allocate memory to handle numBuffers < 16, set data in not valid buffers to zero */ __m512i zero_buffer = _mm512_setzero_si512(); /* Load processing mask */ __mmask16 mb_mask = _mm512_cmp_epi32_mask(_mm512_loadu_si512(len), zero_buffer, _MM_CMPINT_NLE); /* Load data and set the data to zero in not valid buffers */ __m512i loc_len_m512 = _mm512_loadu_si512(len); /* We need the address of the zero_buffer to form the fully valid array of pointers loc_src */ _mm512_storeu_si512(loc_data, _mm512_mask_loadu_epi64(_mm512_set1_epi64((long long)&zero_buffer), (__mmask8)mb_mask, msg_pa)); _mm512_storeu_si512(loc_data+8, _mm512_mask_loadu_epi64(_mm512_set1_epi64((long long)&zero_buffer), *((__mmask8*)&mb_mask + 1), msg_pa + 8)); /* Load hash value */ A = _mm512_loadu_si512(hash_pa); B = _mm512_loadu_si512(hash_pa + 1); C = _mm512_loadu_si512(hash_pa + 2); D = _mm512_loadu_si512(hash_pa + 3); E = _mm512_loadu_si512(hash_pa + 4); F = _mm512_loadu_si512(hash_pa + 5); G = _mm512_loadu_si512(hash_pa + 6); H = _mm512_loadu_si512(hash_pa + 7); /* Loop over the message */ while (mb_mask){ /* Transpose the message data */ TRANSPOSE_16X16_I32((int32u(*)[16])W, (const int32u**)loc_data); /* Init W (remember about endian) */ for (i = 0; i < 16; i++) { W[i] = SIMD_ENDIANNESS32(W[i]); } /* Store previous hash for xor operation V(i+1) = ABCDEFGH XOR V(i) */ Vi[0] = _mm512_load_epi32((void*)&A); Vi[1] = _mm512_load_epi32((void*)&B); Vi[2] = _mm512_load_epi32((void*)&C); Vi[3] = _mm512_load_epi32((void*)&D); Vi[4] = _mm512_load_epi32((void*)&E); Vi[5] = _mm512_load_epi32((void*)&F); Vi[6] = _mm512_load_epi32((void*)&G); Vi[7] = _mm512_load_epi32((void*)&H); /* Compression function */ { STEP1_SM3(0, A, B, C, D, E, F, G, H, tj_calculated[0], W); STEP1_SM3(1, A, B, C, D, E, F, G, H, tj_calculated[1], W); STEP1_SM3(2, A, B, C, D, E, F, G, H, tj_calculated[2], W); STEP1_SM3(3, A, B, C, D, E, F, G, H, tj_calculated[3], W); STEP1_SM3(4, A, B, C, D, E, F, G, H, tj_calculated[4], W); STEP1_SM3(5, A, B, C, D, E, F, G, H, tj_calculated[5], W); STEP1_SM3(6, A, B, C, D, E, F, G, H, tj_calculated[6], W); STEP1_SM3(7, A, B, C, D, E, F, G, H, tj_calculated[7], W); STEP1_SM3(8, A, B, C, D, E, F, G, H, tj_calculated[8], W); STEP1_SM3(9, A, B, C, D, E, F, G, H, tj_calculated[9], W); STEP1_SM3(10, A, B, C, D, E, F, G, H, tj_calculated[10], W); STEP1_SM3(11, A, B, C, D, E, F, G, H, tj_calculated[11], W); STEP1_SM3(12, A, B, C, D, E, F, G, H, tj_calculated[12], W); STEP1_SM3(13, A, B, C, D, E, F, G, H, tj_calculated[13], W); STEP1_SM3(14, A, B, C, D, E, F, G, H, tj_calculated[14], W); STEP1_SM3(15, A, B, C, D, E, F, G, H, tj_calculated[15], W); STEP2_SM3(16, A, B, C, D, E, F, G, H, tj_calculated[16], W); STEP2_SM3(17, A, B, C, D, E, F, G, H, tj_calculated[17], W); STEP2_SM3(18, A, B, C, D, E, F, G, H, tj_calculated[18], W); STEP2_SM3(19, A, B, C, D, E, F, G, H, tj_calculated[19], W); STEP2_SM3(20, A, B, C, D, E, F, G, H, tj_calculated[20], W); STEP2_SM3(21, A, B, C, D, E, F, G, H, tj_calculated[21], W); STEP2_SM3(22, A, B, C, D, E, F, G, H, tj_calculated[22], W); STEP2_SM3(23, A, B, C, D, E, F, G, H, tj_calculated[23], W); STEP2_SM3(24, A, B, C, D, E, F, G, H, tj_calculated[24], W); STEP2_SM3(25, A, B, C, D, E, F, G, H, tj_calculated[25], W); STEP2_SM3(26, A, B, C, D, E, F, G, H, tj_calculated[26], W); STEP2_SM3(27, A, B, C, D, E, F, G, H, tj_calculated[27], W); STEP2_SM3(28, A, B, C, D, E, F, G, H, tj_calculated[28], W); STEP2_SM3(29, A, B, C, D, E, F, G, H, tj_calculated[29], W); STEP2_SM3(30, A, B, C, D, E, F, G, H, tj_calculated[30], W); STEP2_SM3(31, A, B, C, D, E, F, G, H, tj_calculated[31], W); STEP2_SM3(32, A, B, C, D, E, F, G, H, tj_calculated[32], W); STEP2_SM3(33, A, B, C, D, E, F, G, H, tj_calculated[33], W); STEP2_SM3(34, A, B, C, D, E, F, G, H, tj_calculated[34], W); STEP2_SM3(35, A, B, C, D, E, F, G, H, tj_calculated[35], W); STEP2_SM3(36, A, B, C, D, E, F, G, H, tj_calculated[36], W); STEP2_SM3(37, A, B, C, D, E, F, G, H, tj_calculated[37], W); STEP2_SM3(38, A, B, C, D, E, F, G, H, tj_calculated[38], W); STEP2_SM3(39, A, B, C, D, E, F, G, H, tj_calculated[39], W); STEP2_SM3(40, A, B, C, D, E, F, G, H, tj_calculated[40], W); STEP2_SM3(41, A, B, C, D, E, F, G, H, tj_calculated[41], W); STEP2_SM3(42, A, B, C, D, E, F, G, H, tj_calculated[42], W); STEP2_SM3(43, A, B, C, D, E, F, G, H, tj_calculated[43], W); STEP2_SM3(44, A, B, C, D, E, F, G, H, tj_calculated[44], W); STEP2_SM3(45, A, B, C, D, E, F, G, H, tj_calculated[45], W); STEP2_SM3(46, A, B, C, D, E, F, G, H, tj_calculated[46], W); STEP2_SM3(47, A, B, C, D, E, F, G, H, tj_calculated[47], W); STEP2_SM3(48, A, B, C, D, E, F, G, H, tj_calculated[16], W); STEP2_SM3(49, A, B, C, D, E, F, G, H, tj_calculated[17], W); STEP2_SM3(50, A, B, C, D, E, F, G, H, tj_calculated[18], W); STEP2_SM3(51, A, B, C, D, E, F, G, H, tj_calculated[19], W); STEP2_SM3(52, A, B, C, D, E, F, G, H, tj_calculated[20], W); STEP2_SM3(53, A, B, C, D, E, F, G, H, tj_calculated[21], W); STEP2_SM3(54, A, B, C, D, E, F, G, H, tj_calculated[22], W); STEP2_SM3(55, A, B, C, D, E, F, G, H, tj_calculated[23], W); STEP2_SM3(56, A, B, C, D, E, F, G, H, tj_calculated[24], W); STEP2_SM3(57, A, B, C, D, E, F, G, H, tj_calculated[25], W); STEP2_SM3(58, A, B, C, D, E, F, G, H, tj_calculated[26], W); STEP2_SM3(59, A, B, C, D, E, F, G, H, tj_calculated[27], W); STEP2_SM3(60, A, B, C, D, E, F, G, H, tj_calculated[28], W); STEP2_SM3(61, A, B, C, D, E, F, G, H, tj_calculated[29], W); STEP2_SM3(62, A, B, C, D, E, F, G, H, tj_calculated[30], W); STEP2_SM3(63, A, B, C, D, E, F, G, H, tj_calculated[31], W); } A = _mm512_mask_xor_epi32(Vi[0], mb_mask, A, Vi[0]); B = _mm512_mask_xor_epi32(Vi[1], mb_mask, B, Vi[1]); C = _mm512_mask_xor_epi32(Vi[2], mb_mask, C, Vi[2]); D = _mm512_mask_xor_epi32(Vi[3], mb_mask, D, Vi[3]); E = _mm512_mask_xor_epi32(Vi[4], mb_mask, E, Vi[4]); F = _mm512_mask_xor_epi32(Vi[5], mb_mask, F, Vi[5]); G = _mm512_mask_xor_epi32(Vi[6], mb_mask, G, Vi[6]); H = _mm512_mask_xor_epi32(Vi[7], mb_mask, H, Vi[7]); _mm512_storeu_si512(hash_pa, A); _mm512_storeu_si512(hash_pa + 1, B); _mm512_storeu_si512(hash_pa + 2, C); _mm512_storeu_si512(hash_pa + 3, D); _mm512_storeu_si512(hash_pa + 4, E); _mm512_storeu_si512(hash_pa + 5, F); _mm512_storeu_si512(hash_pa + 6, G); _mm512_storeu_si512(hash_pa + 7, H); /* Update pointers to data, local lengths and mask */ _mm512_storeu_si512(loc_data, _mm512_mask_add_epi64(_mm512_set1_epi64((long long)&zero_buffer), (__mmask8)mb_mask, _mm512_loadu_si512(loc_data), _mm512_set1_epi64(SM3_MSG_BLOCK_SIZE))); _mm512_storeu_si512(loc_data + 8, _mm512_mask_add_epi64(_mm512_set1_epi64((long long)&zero_buffer), *((__mmask8*)&mb_mask + 1), _mm512_loadu_si512(loc_data+8), _mm512_set1_epi64(SM3_MSG_BLOCK_SIZE))); loc_len_m512 = _mm512_mask_sub_epi32(zero_buffer, mb_mask, loc_len_m512, _mm512_set1_epi32(SM3_MSG_BLOCK_SIZE)); mb_mask = _mm512_cmp_epi32_mask(loc_len_m512, zero_buffer, _MM_CMPINT_NLE); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_avx512_mb8.c000066400000000000000000000273621470420105600272540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* Boolean functions (0<=nr<16) */ #define FF1(X,Y,Z) (_mm256_xor_si256(_mm256_xor_si256(X,Y), Z)) #define GG1(X,Y,Z) (_mm256_xor_si256(_mm256_xor_si256(X,Y), Z)) /* Boolean functions (16<=nr<64) */ #define FF2(X,Y,Z) (_mm256_or_si256(_mm256_or_si256(_mm256_and_si256(X,Y),_mm256_and_si256(X,Z)),_mm256_and_si256(Y,Z))) #define GG2(X,Y,Z) (_mm256_or_si256(_mm256_and_si256(X,Y),_mm256_andnot_si256(X,Z))) /* P0 permutation: */ #define P0(X) (_mm256_xor_si256(_mm256_xor_si256(X, _mm256_rol_epi32 (X, 9)), _mm256_rol_epi32 (X, 17))) /* P1 permutation: */ #define P1(X) (_mm256_xor_si256(_mm256_xor_si256(X, _mm256_rol_epi32 (X, 15)), _mm256_rol_epi32 (X, 23))) /* Update W */ #define WUPDATE(nr, W) (_mm256_xor_si256(_mm256_xor_si256(P1(_mm256_xor_si256(_mm256_xor_si256(W[(nr-16)&15], W[(nr-9)&15]), _mm256_rol_epi32 (W[(nr-3)&15], 15))), _mm256_rol_epi32(W[(nr-13)&15],7)), W[(nr-6)&15])) // SM3 steps /* (0<=nr<16) */ #define STEP1_SM3(nr, A,B,C,D,E,F,G,H, Tj, W) {\ __m256i SS1 = _mm256_rol_epi32(_mm256_add_epi32(_mm256_add_epi32(_mm256_rol_epi32(A, 12), E), _mm256_set1_epi32((int)Tj)),7);\ __m256i SS2 = _mm256_xor_si256(SS1, _mm256_rol_epi32(A, 12));\ __m256i TT1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_add_epi32(FF1(A, B, C), D), SS2), _mm256_xor_si256(W[nr&15], W[(nr+4)&15]));\ __m256i TT2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_add_epi32(GG1(E, F, G), H), SS1), W[nr&15]);\ D = _mm256_loadu_si256((void*)&C); \ C = _mm256_rol_epi32(B, 9); \ B = _mm256_loadu_si256((void*)&A); \ A = _mm256_loadu_si256((void*)&TT1);\ H = _mm256_loadu_si256((void*)&G); \ G = _mm256_rol_epi32(F, 19); \ F = _mm256_loadu_si256((void*)&E); \ E = P0(TT2); \ W[(nr)&15]=WUPDATE(nr, W); \ } /* (16<=nr<64) */ #define STEP2_SM3(nr, A,B,C,D,E,F,G,H, Tj, W) {\ __m256i SS1 = _mm256_rol_epi32(_mm256_add_epi32(_mm256_add_epi32(_mm256_rol_epi32(A, 12), E), _mm256_set1_epi32((int)Tj)),7);\ __m256i SS2 = _mm256_xor_si256(SS1, _mm256_rol_epi32(A, 12));\ __m256i TT1 = _mm256_add_epi32(_mm256_add_epi32(_mm256_add_epi32(FF2(A, B, C), D), SS2), _mm256_xor_si256(W[nr&15], W[(nr+4)&15]));\ __m256i TT2 = _mm256_add_epi32(_mm256_add_epi32(_mm256_add_epi32(GG2(E, F, G), H), SS1), W[nr&15]);\ D = _mm256_loadu_si256((void*)&C); \ C = _mm256_rol_epi32(B, 9); \ B = _mm256_loadu_si256((void*)&A); \ A = _mm256_loadu_si256((void*)&TT1);\ H = _mm256_loadu_si256((void*)&G); \ G = _mm256_rol_epi32(F, 19); \ F = _mm256_loadu_si256((void*)&E); \ E = P0(TT2); \ W[(nr)&15]=WUPDATE(nr, W); \ } void sm3_avx512_mb8(int32u hash_pa[][8], const int8u* const msg_pa[8], int len[8]) { int i; __ALIGN64 int32u* loc_data[SM3_NUM_BUFFERS8]; __m256i W[16]; int32u* p_W[16] = { (int32u*)&W[0], (int32u*)&W[1], (int32u*)&W[2], (int32u*)&W[3], (int32u*)&W[4], (int32u*)&W[5], (int32u*)&W[6], (int32u*)&W[7], (int32u*)&W[8], (int32u*)&W[9], (int32u*)&W[10], (int32u*)&W[11], (int32u*)&W[12], (int32u*)&W[13], (int32u*)&W[14], (int32u*)&W[15] }; __m256i Vi[8]; __m256i A, B, C, D, E, F, G, H; /* Allocate memory to handle numBuffers < 16, set data in not valid buffers to zero */ __m512i zero_buffer = _mm512_setzero_si512(); /* Load processing mask */ __mmask8 mb_mask = _mm256_cmp_epi32_mask(_mm256_loadu_si256((__m256i*)len), _mm256_setzero_si256(), _MM_CMPINT_NE); /* Load data and set the data to zero in not valid buffers */ __m256i loc_len_m256 = _mm256_loadu_si256((__m256i*)len); /* We need the address of the zero_buffer to form the fully valid array of pointers loc_src */ _mm512_storeu_si512(loc_data, _mm512_mask_loadu_epi64(_mm512_set1_epi64((long long)&zero_buffer), mb_mask, msg_pa)); /* Load hash value */ A = _mm256_loadu_si256((__m256i*)hash_pa); B = _mm256_loadu_si256((__m256i*)(hash_pa + 1)); C = _mm256_loadu_si256((__m256i*)(hash_pa + 2)); D = _mm256_loadu_si256((__m256i*)(hash_pa + 3)); E = _mm256_loadu_si256((__m256i*)(hash_pa + 4)); F = _mm256_loadu_si256((__m256i*)(hash_pa + 5)); G = _mm256_loadu_si256((__m256i*)(hash_pa + 6)); H = _mm256_loadu_si256((__m256i*)(hash_pa + 7)); /* Loop over the message */ while (mb_mask){ /* Transpose the message data */ TRANSPOSE_8X16_I32(p_W, (const int32u**)loc_data, 0xFFFF); /* Init W (remember about endian) */ for (i = 0; i < 16; i++) { W[i] = SIMD_ENDIANNESS32(W[i]); } /* Store previous hash for xor operation V(i+1) = ABCDEFGH XOR V(i) */ Vi[0] = _mm256_loadu_si256((void*)&A); Vi[1] = _mm256_loadu_si256((void*)&B); Vi[2] = _mm256_loadu_si256((void*)&C); Vi[3] = _mm256_loadu_si256((void*)&D); Vi[4] = _mm256_loadu_si256((void*)&E); Vi[5] = _mm256_loadu_si256((void*)&F); Vi[6] = _mm256_loadu_si256((void*)&G); Vi[7] = _mm256_loadu_si256((void*)&H); /* Compression function */ { STEP1_SM3(0, A, B, C, D, E, F, G, H, tj_calculated[0], W); STEP1_SM3(1, A, B, C, D, E, F, G, H, tj_calculated[1], W); STEP1_SM3(2, A, B, C, D, E, F, G, H, tj_calculated[2], W); STEP1_SM3(3, A, B, C, D, E, F, G, H, tj_calculated[3], W); STEP1_SM3(4, A, B, C, D, E, F, G, H, tj_calculated[4], W); STEP1_SM3(5, A, B, C, D, E, F, G, H, tj_calculated[5], W); STEP1_SM3(6, A, B, C, D, E, F, G, H, tj_calculated[6], W); STEP1_SM3(7, A, B, C, D, E, F, G, H, tj_calculated[7], W); STEP1_SM3(8, A, B, C, D, E, F, G, H, tj_calculated[8], W); STEP1_SM3(9, A, B, C, D, E, F, G, H, tj_calculated[9], W); STEP1_SM3(10, A, B, C, D, E, F, G, H, tj_calculated[10], W); STEP1_SM3(11, A, B, C, D, E, F, G, H, tj_calculated[11], W); STEP1_SM3(12, A, B, C, D, E, F, G, H, tj_calculated[12], W); STEP1_SM3(13, A, B, C, D, E, F, G, H, tj_calculated[13], W); STEP1_SM3(14, A, B, C, D, E, F, G, H, tj_calculated[14], W); STEP1_SM3(15, A, B, C, D, E, F, G, H, tj_calculated[15], W); STEP2_SM3(16, A, B, C, D, E, F, G, H, tj_calculated[16], W); STEP2_SM3(17, A, B, C, D, E, F, G, H, tj_calculated[17], W); STEP2_SM3(18, A, B, C, D, E, F, G, H, tj_calculated[18], W); STEP2_SM3(19, A, B, C, D, E, F, G, H, tj_calculated[19], W); STEP2_SM3(20, A, B, C, D, E, F, G, H, tj_calculated[20], W); STEP2_SM3(21, A, B, C, D, E, F, G, H, tj_calculated[21], W); STEP2_SM3(22, A, B, C, D, E, F, G, H, tj_calculated[22], W); STEP2_SM3(23, A, B, C, D, E, F, G, H, tj_calculated[23], W); STEP2_SM3(24, A, B, C, D, E, F, G, H, tj_calculated[24], W); STEP2_SM3(25, A, B, C, D, E, F, G, H, tj_calculated[25], W); STEP2_SM3(26, A, B, C, D, E, F, G, H, tj_calculated[26], W); STEP2_SM3(27, A, B, C, D, E, F, G, H, tj_calculated[27], W); STEP2_SM3(28, A, B, C, D, E, F, G, H, tj_calculated[28], W); STEP2_SM3(29, A, B, C, D, E, F, G, H, tj_calculated[29], W); STEP2_SM3(30, A, B, C, D, E, F, G, H, tj_calculated[30], W); STEP2_SM3(31, A, B, C, D, E, F, G, H, tj_calculated[31], W); STEP2_SM3(32, A, B, C, D, E, F, G, H, tj_calculated[32], W); STEP2_SM3(33, A, B, C, D, E, F, G, H, tj_calculated[33], W); STEP2_SM3(34, A, B, C, D, E, F, G, H, tj_calculated[34], W); STEP2_SM3(35, A, B, C, D, E, F, G, H, tj_calculated[35], W); STEP2_SM3(36, A, B, C, D, E, F, G, H, tj_calculated[36], W); STEP2_SM3(37, A, B, C, D, E, F, G, H, tj_calculated[37], W); STEP2_SM3(38, A, B, C, D, E, F, G, H, tj_calculated[38], W); STEP2_SM3(39, A, B, C, D, E, F, G, H, tj_calculated[39], W); STEP2_SM3(40, A, B, C, D, E, F, G, H, tj_calculated[40], W); STEP2_SM3(41, A, B, C, D, E, F, G, H, tj_calculated[41], W); STEP2_SM3(42, A, B, C, D, E, F, G, H, tj_calculated[42], W); STEP2_SM3(43, A, B, C, D, E, F, G, H, tj_calculated[43], W); STEP2_SM3(44, A, B, C, D, E, F, G, H, tj_calculated[44], W); STEP2_SM3(45, A, B, C, D, E, F, G, H, tj_calculated[45], W); STEP2_SM3(46, A, B, C, D, E, F, G, H, tj_calculated[46], W); STEP2_SM3(47, A, B, C, D, E, F, G, H, tj_calculated[47], W); STEP2_SM3(48, A, B, C, D, E, F, G, H, tj_calculated[16], W); STEP2_SM3(49, A, B, C, D, E, F, G, H, tj_calculated[17], W); STEP2_SM3(50, A, B, C, D, E, F, G, H, tj_calculated[18], W); STEP2_SM3(51, A, B, C, D, E, F, G, H, tj_calculated[19], W); STEP2_SM3(52, A, B, C, D, E, F, G, H, tj_calculated[20], W); STEP2_SM3(53, A, B, C, D, E, F, G, H, tj_calculated[21], W); STEP2_SM3(54, A, B, C, D, E, F, G, H, tj_calculated[22], W); STEP2_SM3(55, A, B, C, D, E, F, G, H, tj_calculated[23], W); STEP2_SM3(56, A, B, C, D, E, F, G, H, tj_calculated[24], W); STEP2_SM3(57, A, B, C, D, E, F, G, H, tj_calculated[25], W); STEP2_SM3(58, A, B, C, D, E, F, G, H, tj_calculated[26], W); STEP2_SM3(59, A, B, C, D, E, F, G, H, tj_calculated[27], W); STEP2_SM3(60, A, B, C, D, E, F, G, H, tj_calculated[28], W); STEP2_SM3(61, A, B, C, D, E, F, G, H, tj_calculated[29], W); STEP2_SM3(62, A, B, C, D, E, F, G, H, tj_calculated[30], W); STEP2_SM3(63, A, B, C, D, E, F, G, H, tj_calculated[31], W); } A = _mm256_mask_xor_epi32(Vi[0], mb_mask, A, Vi[0]); B = _mm256_mask_xor_epi32(Vi[1], mb_mask, B, Vi[1]); C = _mm256_mask_xor_epi32(Vi[2], mb_mask, C, Vi[2]); D = _mm256_mask_xor_epi32(Vi[3], mb_mask, D, Vi[3]); E = _mm256_mask_xor_epi32(Vi[4], mb_mask, E, Vi[4]); F = _mm256_mask_xor_epi32(Vi[5], mb_mask, F, Vi[5]); G = _mm256_mask_xor_epi32(Vi[6], mb_mask, G, Vi[6]); H = _mm256_mask_xor_epi32(Vi[7], mb_mask, H, Vi[7]); _mm256_storeu_si256((__m256i*)hash_pa, A); _mm256_storeu_si256((__m256i*)(hash_pa + 1), B); _mm256_storeu_si256((__m256i*)(hash_pa + 2), C); _mm256_storeu_si256((__m256i*)(hash_pa + 3), D); _mm256_storeu_si256((__m256i*)(hash_pa + 4), E); _mm256_storeu_si256((__m256i*)(hash_pa + 5), F); _mm256_storeu_si256((__m256i*)(hash_pa + 6), G); _mm256_storeu_si256((__m256i*)(hash_pa + 7), H); /* Update pointers to data, local lengths and mask */ _mm512_storeu_si512(loc_data, _mm512_mask_add_epi64(zero_buffer, (__mmask8)mb_mask, _mm512_loadu_si512(loc_data), _mm512_set1_epi64(SM3_MSG_BLOCK_SIZE))); loc_len_m256 = _mm256_mask_sub_epi32(_mm256_setzero_si256(), mb_mask, loc_len_m256, _mm256_set1_epi32(SM3_MSG_BLOCK_SIZE)); mb_mask = _mm256_cmp_epi32_mask(loc_len_m256, _mm256_setzero_si256(), _MM_CMPINT_NE); } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_final_mb16.c000066400000000000000000000026001470420105600273620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm3_final_mb16)(int8u* hash_pa[16], SM3_CTX_mb16* p_state) { mbx_status16 status = 0; /* test input pointers */ if(NULL==hash_pa || NULL==p_state) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) status |= internal_avx512_sm3_final_mb16(hash_pa, p_state); #else status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_final_mb8.c000066400000000000000000000114401470420105600273050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status sm3_final_mb8(int8u* hash_pa[8], SM3_CTX_mb8* p_state) { int i; mbx_status status = 0; /* test input pointers */ if(NULL==hash_pa || NULL==p_state) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } __ALIGN64 int input_len[SM3_NUM_BUFFERS8]; __ALIGN64 int buffer_len[SM3_NUM_BUFFERS8]; __ALIGN64 int64u sum_msg_len[SM3_NUM_BUFFERS8]; /* allocate local buffer */ __ALIGN64 int8u loc_buffer[SM3_NUM_BUFFERS8][SM3_MSG_BLOCK_SIZE*2]; const int8u* buffer_pa[SM3_NUM_BUFFERS8] = { loc_buffer[0], loc_buffer[1], loc_buffer[2], loc_buffer[3], loc_buffer[4], loc_buffer[5], loc_buffer[6], loc_buffer[7] }; /* // create __mmask8 based on input hash_pa // corresponding element in mask = 0 if hash_pa[i] = 0 */ __m512i zero_buffer = _mm512_setzero_si512(); __mmask8 mb_mask8 = _mm512_cmp_epi64_mask(_mm512_loadu_si512(hash_pa), zero_buffer, _MM_CMPINT_NE); __m512i sum_msg_len_m512 = _mm512_maskz_loadu_epi64(mb_mask8, MSG_LEN(p_state)); /* put processed message length in bits */ sum_msg_len_m512 = _mm512_shuffle_epi8(_mm512_rol_epi64(sum_msg_len_m512, 3), _mm512_loadu_si512(swapBytes)); _mm512_storeu_si512(sum_msg_len, sum_msg_len_m512); __m256i input_len_m256 = _mm256_maskz_loadu_epi32(mb_mask8, HASH_BUFFIDX(p_state)); __mmask8 tmp_mask = _mm256_cmplt_epi32_mask(input_len_m256, _mm256_set1_epi32(SM3_MSG_BLOCK_SIZE - (int)SM3_MSG_LEN_REPR)); __m256i buffer_len_m256 = _mm256_mask_set1_epi32(_mm256_set1_epi32(SM3_MSG_BLOCK_SIZE * 2), tmp_mask, SM3_MSG_BLOCK_SIZE); buffer_len_m256 = _mm256_mask_set1_epi32(buffer_len_m256, ~mb_mask8, 0); _mm256_storeu_si256((__m256i*)input_len, input_len_m256); _mm256_storeu_si256((__m256i*)buffer_len, buffer_len_m256); __mmask64 mb_mask64; for (i = 0; i < SM3_NUM_BUFFERS8; i++) { /* Copy rest of message into internal buffer */ mb_mask64 = ~(0xFFFFFFFFFFFFFFFF << input_len[i]); _mm512_storeu_si512(loc_buffer[i], _mm512_maskz_loadu_epi8(mb_mask64, HASH_BUFF(p_state)[i])); /* Pad message */ loc_buffer[i][input_len[i]++] = 0x80; pad_block(0, loc_buffer[i] + input_len[i], (int)(buffer_len[i] - input_len[i] - (int)SM3_MSG_LEN_REPR)); ((int64u*)(loc_buffer[i] + buffer_len[i]))[-1] = sum_msg_len[i]; } /* Copmplete hash computation */ sm3_avx512_mb8(HASH_VALUE(p_state), buffer_pa, buffer_len); /* Convert hash into big endian */ __m256i T[8]; const int32u* p_T[8] = { (int32u*)&T[0], (int32u*)&T[1], (int32u*)&T[2], (int32u*)&T[3], (int32u*)&T[4], (int32u*)&T[5], (int32u*)&T[6], (int32u*)&T[7] }; T[0] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[0])); T[1] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[1])); T[2] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[2])); T[3] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[3])); T[4] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[4])); T[5] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[5])); T[6] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[6])); T[7] = SIMD_ENDIANNESS32(_mm256_loadu_si256((__m256i*)HASH_VALUE(p_state)[7])); /* Transpose hash and store in array with pointers to hash values */ MASK_TRANSPOSE_8X8_I32((int32u**)hash_pa, p_T, mb_mask8); /* re-init hash value using mb masks */ _mm512_storeu_si512(MSG_LEN(p_state), _mm512_mask_set1_epi64(_mm512_loadu_si512(MSG_LEN(p_state)), mb_mask8, 0)); _mm256_storeu_si256((__m256i*)HASH_BUFFIDX(p_state), _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i*)HASH_BUFFIDX(p_state)), mb_mask8, 0)); sm3_mask_init_mb8(p_state, mb_mask8); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_init_mb16.c000066400000000000000000000025031470420105600272360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm3_init_mb16)(SM3_CTX_mb16 * p_state) { mbx_status16 status = 0; /* test state pointer */ if(NULL==p_state) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) status |= internal_avx512_sm3_mask_init_mb16(p_state, 0xFFFF); #else status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_init_mb8.c000066400000000000000000000061271470420105600271650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) void sm3_mask_init_mb8(SM3_CTX_mb8* p_state, __mmask8 mb_mask) { /* clear buffer index */ _mm256_storeu_si256((__m256i *)HASH_BUFFIDX(p_state), _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_BUFFIDX(p_state)), mb_mask, 0)); /* clear summary message length */ _mm512_storeu_si512(MSG_LEN(p_state), _mm512_maskz_loadu_epi64(~mb_mask, MSG_LEN(p_state))); /* clear buffer */ for (int i = 0; i < SM3_NUM_BUFFERS8; i++) { if ((mb_mask >> i) & 1) _mm512_storeu_si512(HASH_BUFF(p_state)[i], _mm512_setzero_si512()); } /* setup initial digest in multi-buffer format */ _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[0], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[0]), mb_mask, (int)sm3_iv[0])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[1], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[1]), mb_mask, (int)sm3_iv[1])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[2], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[2]), mb_mask, (int)sm3_iv[2])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[3], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[3]), mb_mask, (int)sm3_iv[3])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[4], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[4]), mb_mask, (int)sm3_iv[4])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[5], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[5]), mb_mask, (int)sm3_iv[5])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[6], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[6]), mb_mask, (int)sm3_iv[6])); _mm256_storeu_si256((__m256i *)HASH_VALUE(p_state)[7], _mm256_mask_set1_epi32(_mm256_loadu_si256((__m256i *)HASH_VALUE(p_state)[7]), mb_mask, (int)sm3_iv[7])); } mbx_status sm3_init_mb8(SM3_CTX_mb8* p_state) { mbx_status status = 0; /* test state pointer */ if(NULL==p_state) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } sm3_mask_init_mb8(p_state, 0xFF); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_messagedigest_mb16.c000066400000000000000000000027561470420105600311310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm3_msg_digest_mb16)(const int8u* const msg_pa[16], int len[16], int8u* hash_pa[16]) { mbx_status16 status = 0; /* test input pointers */ if(NULL==msg_pa || NULL==len || NULL==hash_pa) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) status |= internal_avx512_sm3_msg_digest_mb16(msg_pa, len, hash_pa); #else status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_messagedigest_mb8.c000066400000000000000000000035201470420105600310400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status sm3_msg_digest_mb8(const int8u* const msg_pa[8], int len[8], int8u* hash_pa[8]) { int buf_no; mbx_status status = 0; /* test input pointers */ if(NULL==msg_pa || NULL==len || NULL==hash_pa) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } for (buf_no = 0; buf_no < SM3_NUM_BUFFERS8; buf_no++) { if ((len[buf_no] && !hash_pa[buf_no]) || (len[buf_no] && !msg_pa[buf_no])) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); return status; } } /* initialize the context of SM3 hash */ SM3_CTX_mb8 p_state; sm3_init_mb8(&p_state); /* process main part of the message */ status = sm3_update_mb8(msg_pa, len, &p_state); if(MBX_IS_ANY_OK_STS(status)) { /* finalize message processing */ status = sm3_final_mb8(hash_pa, &p_state); } return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_update_mb16.c000066400000000000000000000031631470420105600275600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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 // Disable optimization for VS17 #if defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__INTEL_COMPILER) #pragma optimize( "", off ) #endif DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm3_update_mb16)(const int8u* const msg_pa[16], int len[16], SM3_CTX_mb16* p_state) { mbx_status16 status = 0; /* test input pointers */ if (NULL == msg_pa || NULL == len || NULL == p_state) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } #if (_MBX>=_MBX_K1) status |= internal_avx512_sm3_update_mb16(msg_pa, len, p_state); #else status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm3/sm3_update_mb8.c000066400000000000000000000150511470420105600275000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) // Disable optimization for VS17 #if defined(_MSC_VER) && (_MSC_VER < 1920) && !defined(__INTEL_COMPILER) #pragma optimize( "", off ) #endif mbx_status sm3_update_mb8(const int8u* const msg_pa[8], int len[8], SM3_CTX_mb8* p_state) { int i; mbx_status status = 0; /* test input pointers */ if (NULL == msg_pa || NULL == len || NULL == p_state) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } __ALIGN64 const int8u* loc_src[SM3_NUM_BUFFERS8]; __m256i loc_len = _mm256_loadu_si256((__m256i*)len); int* p_loc_len = (int*)&loc_len; __m512i zero_buffer = _mm512_setzero_si512(); /* generate mask based on array with messages lengths */ __mmask8 mb_mask = _mm256_cmp_epi32_mask(loc_len, _mm256_setzero_si256(), _MM_CMPINT_NE); /* generate mask based on msg_pa[]. Don't process the data from i buffer if in msg_pa[i] == 0 or len[i] == 0 */ mb_mask &= _mm512_cmp_epi64_mask(_mm512_loadu_si512(msg_pa), zero_buffer, _MM_CMPINT_NE); /* handle non empty message */ if (mb_mask) { /* We need the address of the zero_buffer to form the fully valid array of pointers loc_src */ _mm512_storeu_si512((void *)loc_src, _mm512_mask_loadu_epi64(_mm512_set1_epi64((long long)&zero_buffer), mb_mask, msg_pa)); __m256i proc_len; __m256i idx = _mm256_loadu_si256((__m256i*)HASH_BUFFIDX(p_state)); int* p_proc_len = (int*)&proc_len; int* p_idx = (int*)&idx; __ALIGN64 int64u sum_msg_len[SM3_NUM_BUFFERS8] = { (int64u)p_loc_len[0], (int64u)p_loc_len[1], (int64u)p_loc_len[2], (int64u)p_loc_len[3], (int64u)p_loc_len[4], (int64u)p_loc_len[5], (int64u)p_loc_len[6], (int64u)p_loc_len[7] }; __ALIGN64 int8u* p_buffer[SM3_NUM_BUFFERS8] = { HASH_BUFF(p_state)[0], HASH_BUFF(p_state)[1], HASH_BUFF(p_state)[2], HASH_BUFF(p_state)[3], HASH_BUFF(p_state)[4], HASH_BUFF(p_state)[5], HASH_BUFF(p_state)[6], HASH_BUFF(p_state)[7] }; __mmask8 processed_mask = _mm256_cmp_epi32_mask(idx, _mm256_setzero_si256(), _MM_CMPINT_NE); __m512i sum_msg_len_m512 = _mm512_loadu_si512(sum_msg_len); sum_msg_len_m512 = _mm512_mask_add_epi64(sum_msg_len_m512, mb_mask, _mm512_loadu_si512(MSG_LEN(p_state)), sum_msg_len_m512); _mm512_storeu_si512(sum_msg_len, sum_msg_len_m512); __m512i loc_src_m512 = _mm512_loadu_si512(loc_src); /* if non empty internal buffer filling */ if (processed_mask) { __m256i tmp = _mm256_sub_epi32(_mm256_set1_epi32(SM3_MSG_BLOCK_SIZE), idx); processed_mask = _mm256_cmp_epi32_mask(_mm256_sub_epi32(loc_len, tmp), _mm256_setzero_si256(), _MM_CMPINT_LT); /* p_proc_len[i] = MIN(p_loc_len[i], (SM3_MSG_BLOCK_SIZE - p_idx[i])) */ proc_len = _mm256_mask_loadu_epi32(tmp, processed_mask, p_loc_len); /* copy from input stream to the internal buffer as match as possible */ for (i = 0; i < SM3_NUM_BUFFERS8; i++) { /* copy from input stream to the internal buffer as match as possible */ __mmask64 mb_mask64 = ~(0xFFFFFFFFFFFFFFFF << p_proc_len[i]); _mm512_storeu_si512(p_buffer[i] + p_idx[i], _mm512_mask_loadu_epi8(_mm512_loadu_si512(p_buffer[i] + p_idx[i]), mb_mask64, loc_src[i])); } idx = _mm256_add_epi32(idx, proc_len); loc_len = _mm256_sub_epi32(loc_len, proc_len); loc_src_m512 = _mm512_add_epi64(loc_src_m512, _mm512_cvtepu32_epi64(proc_len)); _mm512_storeu_si512((void*)loc_src, loc_src_m512); processed_mask = _mm256_cmp_epi32_mask(idx, _mm256_set1_epi32(SM3_MSG_BLOCK_SIZE), _MM_CMPINT_EQ); proc_len = _mm256_mask_set1_epi32(proc_len, processed_mask, SM3_MSG_BLOCK_SIZE); /* update digest if at least one buffer is full */ if (processed_mask) { sm3_avx512_mb8(HASH_VALUE(p_state), (const int8u **)p_buffer, p_proc_len); idx = _mm256_mask_set1_epi32(idx, ~_mm256_cmp_epi32_mask(proc_len, _mm256_setzero_si256(), 2), _MM_CMPINT_EQ); } } /* main message part processing */ proc_len = _mm256_and_si256(loc_len, _mm256_set1_epi32(-SM3_MSG_BLOCK_SIZE)); processed_mask = _mm256_cmp_epi32_mask(proc_len, _mm256_setzero_si256(), _MM_CMPINT_NLT); if (processed_mask) sm3_avx512_mb8(HASH_VALUE(p_state), loc_src, p_proc_len); loc_len = _mm256_sub_epi32(loc_len, proc_len); loc_src_m512 = _mm512_add_epi64(loc_src_m512, _mm512_cvtepu32_epi64(proc_len)); _mm512_storeu_si512((void*)loc_src, loc_src_m512); processed_mask = _mm256_cmp_epi32_mask(loc_len, _mm256_setzero_si256(), _MM_CMPINT_NLE); /* store rest of message into the internal buffer */ if (processed_mask) { for (i = 0; i < SM3_NUM_BUFFERS8; i++) { /* copy from input stream to the internal buffer as match as possible */ __mmask64 mb_mask64 = ~(0xFFFFFFFFFFFFFFFF << *(p_loc_len + i)); _mm512_storeu_si512(p_buffer[i], _mm512_maskz_loadu_epi8(mb_mask64, loc_src[i])); } idx = _mm256_maskz_add_epi32(0xFF, idx, loc_len); } /* Update length of processed message */ _mm512_storeu_si512(MSG_LEN(p_state), _mm512_mask_loadu_epi64(_mm512_loadu_si512(MSG_LEN(p_state)), mb_mask, sum_msg_len)); _mm512_storeu_si512(HASH_BUFFIDX(p_state), _mm512_mask_loadu_epi32(_mm512_loadu_si512(HASH_BUFFIDX(p_state)), mb_mask, p_idx)); } return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/000077500000000000000000000000001470420105600245215ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/000077500000000000000000000000001470420105600252635ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/000077500000000000000000000000001470420105600302055ustar00rootroot00000000000000sm4_ccm_decrypt_mb16.c000066400000000000000000000071641470420105600342060ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* * This function performs decryption with CTR and then authentication with CBC-MAC on plaintext. * Function returns mask where bit is set to 1 if length of given data for buffer is overflowed. */ mbx_status16 sm4_ccm_decrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { mbx_status16 status = 0; __m128i *hash = SM4_CCM_CONTEXT_HASH(p_context); __m128i *ctr = SM4_CCM_CONTEXT_CTR(p_context); const int8u *hash_ptrs[SM4_LINES]; int8u *pa_ctr[SM4_LINES]; unsigned i; int full_hash_len[SM4_LINES]; int partial_hash_len[SM4_LINES]; int8u padded_hash[SM4_LINES][SM4_BLOCK_SIZE]; int8u *pa_padded_hash[SM4_LINES]; __mmask16 partial_block_mask = 0; /* No AAD processed */ if (SM4_CCM_CONTEXT_STATE(p_context) == sm4_ccm_update_aad) { int aad_lens[SM4_LINES]; PadBlock(0, aad_lens, sizeof(aad_lens)); sm4_ccm_update_aad_mb16(NULL, aad_lens, 0xFFFF, p_context); } /* Switch context state to decryption */ SM4_CCM_CONTEXT_STATE(p_context) = sm4_ccm_dec; for (i = 0; i < SM4_LINES; i++) { hash_ptrs[i] = (int8u *) &hash[i]; pa_ctr[i] = (int8u *) &ctr[i]; full_hash_len[i] = in_len[i] & 0xFFFFFFF0; } /* Decrypt first */ sm4_ctr128_kernel_mb16(pa_out, (const int8u **) pa_in, in_len, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), mb_mask, pa_ctr); /* Authenticate the plaintext */ sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) pa_out, full_hash_len, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), mb_mask, hash_ptrs); /* Handle partial blocks of plaintext */ for (i = 0; i < SM4_LINES; i++) { partial_hash_len[i] = in_len[i] & 0xF; if (partial_hash_len[i] == 0) continue; pa_padded_hash[i] = padded_hash[i]; PadBlock(0, pa_padded_hash[i], SM4_BLOCK_SIZE); CopyBlock(pa_out[i] + full_hash_len[i], pa_padded_hash[i], partial_hash_len[i]); full_hash_len[i] = SM4_BLOCK_SIZE; partial_block_mask |= (1 << i); } if (partial_block_mask != 0) { sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) pa_padded_hash, full_hash_len, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), partial_block_mask, hash_ptrs); SM4_CCM_CONTEXT_STATE(p_context) = sm4_ccm_get_tag; } return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_encrypt_mb16.c000066400000000000000000000070171470420105600342150ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* * This function performs authentication with CBC-MAC on plaintext and encryption with CTR. */ mbx_status16 sm4_ccm_encrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { mbx_status16 status = 0; __m128i *hash = SM4_CCM_CONTEXT_HASH(p_context); __m128i *ctr = SM4_CCM_CONTEXT_CTR(p_context); const int8u *hash_ptrs[SM4_LINES]; int8u *pa_ctr[SM4_LINES]; unsigned i; int full_hash_len[SM4_LINES]; int partial_hash_len[SM4_LINES]; int8u padded_hash[SM4_LINES][SM4_BLOCK_SIZE]; int8u *pa_padded_hash[SM4_LINES]; __mmask16 partial_block_mask = 0; /* No AAD processed */ if (SM4_CCM_CONTEXT_STATE(p_context) == sm4_ccm_update_aad) { int aad_lens[SM4_LINES]; PadBlock(0, aad_lens, sizeof(aad_lens)); sm4_ccm_update_aad_mb16(NULL, aad_lens, 0xFFFF, p_context); } /* Switch context state to encryption */ SM4_CCM_CONTEXT_STATE(p_context) = sm4_ccm_enc; for (i = 0; i < SM4_LINES; i++) { hash_ptrs[i] = (int8u *) &hash[i]; pa_ctr[i] = (int8u *) &ctr[i]; full_hash_len[i] = in_len[i] & 0xFFFFFFF0; /* Get full block lengths */ } sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) pa_in, full_hash_len, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), mb_mask, hash_ptrs); /* Handle partial blocks of plaintext */ for (i = 0; i < SM4_LINES; i++) { partial_hash_len[i] = in_len[i] & 0xF; /* Retrieve partial block lengths */ if (partial_hash_len[i] == 0) continue; pa_padded_hash[i] = padded_hash[i]; PadBlock(0, pa_padded_hash[i], SM4_BLOCK_SIZE); CopyBlock(pa_in[i] + full_hash_len[i], pa_padded_hash[i], partial_hash_len[i]); full_hash_len[i] = SM4_BLOCK_SIZE; partial_block_mask |= (1 << i); } if (partial_block_mask != 0) { sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) pa_padded_hash, full_hash_len, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), partial_block_mask, hash_ptrs); SM4_CCM_CONTEXT_STATE(p_context) = sm4_ccm_get_tag; } sm4_ctr128_kernel_mb16(pa_out, (const int8u **) pa_in, in_len, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), mb_mask, pa_ctr); return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_get_tag_mb16.c000066400000000000000000000102761470420105600341440ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 /* for zero_mb8 */ #if (_MBX>=_MBX_K1) static void sm4_encrypt_ctr0_mb16(SM4_CCM_CTX_mb16 *p_context, __m512i *s0_blocks) { const mbx_sm4_key_schedule *key_sched = (const mbx_sm4_key_schedule *)SM4_CCM_CONTEXT_KEY(p_context); __m128i *ctr0 = SM4_CCM_CONTEXT_CTR0(p_context); const int8u *pa_inp[SM4_LINES]; for (int i = 0; i < SM4_LINES; i++) pa_inp[i] = (unsigned char *)(ctr0 + i); TRANSPOSE_16x4_I32_EPI32(&s0_blocks[0], &s0_blocks[1], &s0_blocks[2], &s0_blocks[3], pa_inp, 0xFFFF); const __m512i *p_rk = (const __m512i *)key_sched; __m512i tmp; for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) SM4_FOUR_ROUNDS(s0_blocks[0], s0_blocks[1], s0_blocks[2], s0_blocks[3], tmp, p_rk, 1); __m512i T1_0 = unpacklo_epi32(s0_blocks[0], s0_blocks[1]); __m512i T1_1 = unpackhi_epi32(s0_blocks[0], s0_blocks[1]); __m512i T1_2 = unpacklo_epi32(s0_blocks[2], s0_blocks[3]); __m512i T1_3 = unpackhi_epi32(s0_blocks[2], s0_blocks[3]); s0_blocks[0] = unpacklo_epi64(T1_0, T1_2); s0_blocks[1] = unpackhi_epi64(T1_0, T1_2); s0_blocks[2] = unpacklo_epi64(T1_1, T1_3); s0_blocks[3] = unpackhi_epi64(T1_1, T1_3); s0_blocks[0] = shuffle_epi8(s0_blocks[0], M512(swapEndianness)); s0_blocks[1] = shuffle_epi8(s0_blocks[1], M512(swapEndianness)); s0_blocks[2] = shuffle_epi8(s0_blocks[2], M512(swapEndianness)); s0_blocks[3] = shuffle_epi8(s0_blocks[3], M512(swapEndianness)); T1_0 = _mm512_shuffle_i64x2(s0_blocks[0], s0_blocks[1], 0x44); T1_1 = _mm512_shuffle_i64x2(s0_blocks[0], s0_blocks[1], 0xEE); T1_2 = _mm512_shuffle_i64x2(s0_blocks[2], s0_blocks[3], 0x44); T1_3 = _mm512_shuffle_i64x2(s0_blocks[2], s0_blocks[3], 0xEE); s0_blocks[0] = _mm512_shuffle_i64x2(T1_0, T1_2, 0x88); s0_blocks[1] = _mm512_shuffle_i64x2(T1_0, T1_2, 0xDD); s0_blocks[2] = _mm512_shuffle_i64x2(T1_1, T1_3, 0x88); s0_blocks[3] = _mm512_shuffle_i64x2(T1_1, T1_3, 0xDD); } mbx_status16 sm4_ccm_get_tag_mb16(int8u *pa_out[SM4_LINES], const int tag_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { mbx_status16 status = 0; __m512i s0_blocks[4]; __m512i hash_blocks[4]; __m128i *hash = SM4_CCM_CONTEXT_HASH(p_context); /* Calculate S0 */ sm4_encrypt_ctr0_mb16(p_context, s0_blocks); hash_blocks[0] = loadu(hash); hash_blocks[1] = loadu(hash + 4); hash_blocks[2] = loadu(hash + 4*2); hash_blocks[3] = loadu(hash + 4*3); __m512i tag_blocks[4]; /* XOR with previously encrypted J0 */ tag_blocks[0] = xor(hash_blocks[0], s0_blocks[0]); tag_blocks[1] = xor(hash_blocks[1], s0_blocks[1]); tag_blocks[2] = xor(hash_blocks[2], s0_blocks[2]); tag_blocks[3] = xor(hash_blocks[3], s0_blocks[3]); /* Store result */ for (int i = 0; i < SM4_LINES; i++) { __m128i one_block = M128((__m128i *)tag_blocks + i); __mmask16 tagMask = ~(0xFFFF << (tag_len[i])) * ((mb_mask >> i) & 0x1); _mm_mask_storeu_epi8((void *)(pa_out[i]), tagMask, one_block); } /* Clear local copy of sensitive data */ zero_mb8((int64u(*)[8])tag_blocks, sizeof(tag_blocks) / sizeof(tag_blocks[0])); zero_mb8((int64u(*)[8])hash_blocks, sizeof(hash_blocks) / sizeof(hash_blocks[0])); zero_mb8((int64u(*)[8])s0_blocks, sizeof(s0_blocks) / sizeof(s0_blocks[0])); return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_init_mb16.c000066400000000000000000000047531470420105600335000ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 internal_avx512_sm4_ccm_init_mb16(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], const int tag_len[SM4_LINES], const int64u msg_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context, __mmask16 mb_mask) { mbx_status16 status = 0; /* // Compute SM4 keys // initialize int32u mbx_sm4_key_schedule[SM4_ROUNDS][SM4_LINES] buffer in context // keys layout for each round: // key0 key4 key8 key12 key1 key5 key9 key13 key2 key6 key10 key14 key3 key7 key11 key15 */ internal_avx512_sm4_set_round_keys_mb16((int32u **)SM4_CCM_CONTEXT_KEY(p_context), (const int8u **)pa_key, mb_mask); /* Process IV */ sm4_ccm_update_iv_mb16(pa_iv, iv_len, mb_mask, p_context); /* Zero initial msg and tag lengths */ PadBlock(0, SM4_CCM_CONTEXT_MSG_LEN(p_context), sizeof(int64u)*SM4_LINES); PadBlock(0, SM4_CCM_CONTEXT_PROCESSED_LEN(p_context), sizeof(int64u)*SM4_LINES); PadBlock(0, SM4_CCM_CONTEXT_TAG_LEN(p_context), sizeof(int)*SM4_LINES); /* Process msg and tag lengths */ sm4_ccm_set_msg_len_mb16(msg_len, mb_mask, p_context); sm4_ccm_set_tag_len_mb16(tag_len, mb_mask, p_context); /* Zero initial hash values */ PadBlock(0, SM4_CCM_CONTEXT_HASH(p_context), 16*SM4_LINES); SM4_CCM_CONTEXT_STATE(p_context) = sm4_ccm_update_aad; return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_set_msg_len_mb16.c000066400000000000000000000021731470420105600350260ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) void sm4_ccm_set_msg_len_mb16(const int64u msg_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { int64u *msg_len_ctx = SM4_CCM_CONTEXT_MSG_LEN(p_context); unsigned i; for (i = 0; i < SM4_LINES; i++) if (mb_mask & (1 << i)) msg_len_ctx[i] = msg_len[i]; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_set_tag_len_mb16.c000066400000000000000000000022111470420105600350040ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) void sm4_ccm_set_tag_len_mb16(const int tag_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { int *tag_len_ctx = SM4_CCM_CONTEXT_TAG_LEN(p_context); unsigned i; for (i = 0; i < SM4_LINES; i++) { if (mb_mask & (1 << i)) { tag_len_ctx[i] = tag_len[i]; } } } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_update_aad_mb16.c000066400000000000000000000151521470420105600346170ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define MAX_AAD_SIZE_BLOCKS_0_3 46 /* * This function process 16 buffers with additional authentication data (AAD), * up to 2^16 - 2^8 bytes */ mbx_status16 sm4_ccm_update_aad_mb16(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { mbx_status16 status = 0; __m128i *ctr0 = SM4_CCM_CONTEXT_CTR0(p_context); int *tag_len = SM4_CCM_CONTEXT_TAG_LEN(p_context); int *iv_len = SM4_CCM_CONTEXT_IV_LEN(p_context); int64u *msg_len = SM4_CCM_CONTEXT_MSG_LEN(p_context); __m128i *hash = SM4_CCM_CONTEXT_HASH(p_context); /* Scratch memory to construct up to 4 blocks to authenticate (up to 46 byte of AAD) */ int8u tmp[SM4_LINES][SM4_BLOCK_SIZE*4]; const int8u *block_ptrs[SM4_LINES]; const int8u *hash_ptrs[SM4_LINES]; int auth_lens[SM4_LINES]; unsigned i, j; int8u iv[SM4_LINES][SM4_BLOCK_SIZE]; const int8u *iv_ptrs[SM4_LINES]; int additional_lens[SM4_LINES]; __m512i max_msg16b_len = set1_epi64(0xFFFF); __mmask16 additional_len_mask = _mm512_cmp_epi32_mask(set1_epi32(MAX_AAD_SIZE_BLOCKS_0_3), loadu(aad_len), _MM_CMPINT_LT); __mmask8 msg_len_overflow_lo_mask = _mm512_cmp_epi64_mask(max_msg16b_len, loadu(msg_len), _MM_CMPINT_LE); __mmask8 msg_len_overflow_hi_mask = _mm512_cmp_epi64_mask(max_msg16b_len, loadu(msg_len + 8), _MM_CMPINT_LE); __mmask16 msg_len_overflow_mask = (__mmask16) msg_len_overflow_hi_mask << 8 | (__mmask16) msg_len_overflow_lo_mask; additional_len_mask = _mm512_kand(additional_len_mask, mb_mask); PadBlock(0, tmp, sizeof(tmp)); PadBlock(0, iv, sizeof(iv)); for (i = 0; i < SM4_LINES; i++) { additional_lens[i] = 0; if ((mb_mask & (1 << i)) == 0) { auth_lens[i] = 0; block_ptrs[i] = NULL; hash_ptrs[i] = NULL; iv_ptrs[i] = NULL; continue; } CopyBlock(&ctr0[i], tmp[i], SM4_BLOCK_SIZE); int8u flags = tmp[i][0]; int8u tag_len_enc = (tag_len[i] - 2) >> 1; flags |= (tag_len_enc) << 3; auth_lens[i] = SM4_BLOCK_SIZE; block_ptrs[i] = tmp[i]; hash_ptrs[i] = (int8u *) &hash[i]; iv_ptrs[i] = iv[i]; if (aad_len[i]) { int len; if (aad_len[i] > MAX_AAD_SIZE_BLOCKS_0_3) { len = MAX_AAD_SIZE_BLOCKS_0_3; additional_lens[i] = aad_len[i] - MAX_AAD_SIZE_BLOCKS_0_3; } else len = aad_len[i]; flags |= 1 << 6; /* Copy AAD length to first 2 bytes of B_1 */ tmp[i][16] = (int8u) (aad_len[i] >> 8); tmp[i][17] = (int8u) aad_len[i]; /* Copy AAD afterwards */ CopyBlock(pa_aad[i], &tmp[i][18], len); auth_lens[i] += (2 + 15 + len); auth_lens[i] &= 0xfff0; /* Multiple of 16 bytes */ } tmp[i][0] = flags; tmp[i][15] = (int8u) msg_len[i]; tmp[i][14] = (int8u) (msg_len[i] >> 8); } /* Check if message is longer than 2^16 - 1 and set the length appropriately in block 0 */ if (msg_len_overflow_mask) { for (i = 0; i < SM4_LINES; i++) { const unsigned num_bits_msg_len = 15 - iv_len[i]; const int64u max_len = (num_bits_msg_len == 8) ? 0xFFFFFFFFFFFFFFFF : (1ULL << (num_bits_msg_len << 3)); if (msg_len[i] < max_len) { for (j = 2; j < num_bits_msg_len; j++) tmp[i][15-j] = (int8u) (msg_len[i] >> (8*j)); } } } sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) block_ptrs, auth_lens, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), mb_mask, iv_ptrs); /* More AAD to process */ if (additional_len_mask) { for (i = 0; i < SM4_LINES; i++) { if (additional_lens[i]) { block_ptrs[i] = pa_aad[i] + MAX_AAD_SIZE_BLOCKS_0_3; /* First 46 bytes have been processed */ auth_lens[i] = additional_lens[i] & 0xfff0; /* Multiple of 16 bytes */ additional_lens[i] -= auth_lens[i]; if (auth_lens[i] == 0) additional_len_mask &= ~(1 << i); } } sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) block_ptrs, auth_lens, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), additional_len_mask, hash_ptrs); additional_len_mask = _mm512_cmp_epi32_mask(set1_epi32(0), loadu(additional_lens), _MM_CMPINT_NE); /* Process last blocks (up to 15 bytes) */ for (i = 0; i < SM4_LINES; i++) { if (additional_lens[i]) { block_ptrs[i] = tmp[i]; /* First 46 bytes have been processed */ PadBlock(0, tmp[i], SM4_BLOCK_SIZE); CopyBlock(pa_aad[i] + MAX_AAD_SIZE_BLOCKS_0_3 + auth_lens[i], tmp[i], additional_lens[i]); auth_lens[i] = SM4_BLOCK_SIZE; } } sm4_cbc_mac_kernel_mb16(hash, (const int8u *const *) block_ptrs, auth_lens, (const int32u **)SM4_CCM_CONTEXT_KEY(p_context), additional_len_mask, hash_ptrs); } if (cmp_epi32_mask(loadu(aad_len), setzero(), _MM_CMPINT_EQ) != 0xFFFF) SM4_CCM_CONTEXT_STATE(p_context) = sm4_ccm_start_encdec; return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_ccm_update_iv_mb16.c000066400000000000000000000041101470420105600345000ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function process 16 buffers with initialization vector (IV) data */ void sm4_ccm_update_iv_mb16(const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], __mmask16 mb_mask, SM4_CCM_CTX_mb16 *p_context) { int *iv_len_ctx = SM4_CCM_CONTEXT_IV_LEN(p_context); __m128i *ctr0 = SM4_CCM_CONTEXT_CTR0(p_context); __m128i *ctr = SM4_CCM_CONTEXT_CTR(p_context); unsigned i; for (i = 0; i < SM4_LINES; i++) { if (mb_mask & (1 << i)) { int8u flags; unsigned L; int iv_len_i = iv_len[i]; L = 15 - iv_len_i; flags = L - 1; /* Update CTR0 for each lane */ int8u *ctr0_nonce_ptr = (int8u *) &(ctr0[i]); PadBlock(0, ctr0_nonce_ptr, 16); CopyBlock(pa_iv[i], ctr0_nonce_ptr + 1, iv_len_i); ctr0_nonce_ptr[0] = flags; /* Update CTR for each lane (counter = 1 to start encryption) */ int8u *ctr_nonce_ptr = (int8u *) &(ctr[i]); PadBlock(0, ctr_nonce_ptr, 16); CopyBlock(pa_iv[i], ctr_nonce_ptr + 1, iv_len_i); ctr_nonce_ptr[0] = flags; ctr_nonce_ptr[15] = 1; iv_len_ctx[i] = iv_len[i]; } } } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/sm4_ccm_decrypt_mb16_api.c000066400000000000000000000055401470420105600321700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_ccm_decrypt_mb16)(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; int64u *processed_len = SM4_CCM_CONTEXT_PROCESSED_LEN(p_context); int64u *msg_len = SM4_CCM_CONTEXT_MSG_LEN(p_context); /* Test input pointers */ if (NULL == pa_out || NULL == pa_in || NULL == in_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_ccm_update_aad != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_start_encdec != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_dec != SM4_CCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with NULL pointers or wrong input length */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_in[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } if (in_len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } processed_len[buf_no] += in_len[buf_no]; /* Check if total processed length will exceed the total message length passed at init */ if (processed_len[buf_no] > msg_len[buf_no]) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ccm_decrypt_mb16(pa_out, pa_in, in_len, (__mmask16)mb_mask, p_context); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/sm4_ccm_encrypt_mb16_api.c000066400000000000000000000055371470420105600322100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_ccm_encrypt_mb16)(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; int64u *processed_len = SM4_CCM_CONTEXT_PROCESSED_LEN(p_context); int64u *msg_len = SM4_CCM_CONTEXT_MSG_LEN(p_context); /* Test input pointers */ if (NULL == pa_out || NULL == pa_in || NULL == in_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_ccm_update_aad != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_start_encdec != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_enc != SM4_CCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with NULL pointers or invalid lengths */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_in[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } if (in_len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } processed_len[buf_no] += in_len[buf_no]; /* Check if total processed length will exceed the total message length passed at init */ if (processed_len[buf_no] > msg_len[buf_no]) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ccm_encrypt_mb16(pa_out, pa_in, in_len, (__mmask16)mb_mask, p_context); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/sm4_ccm_get_tag_mb16_api.c000066400000000000000000000057351470420105600321360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_ccm_get_tag_mb16)(int8u *pa_tag[SM4_LINES], const int tag_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; int64u *processed_len = SM4_CCM_CONTEXT_PROCESSED_LEN(p_context); int64u *msg_len = SM4_CCM_CONTEXT_MSG_LEN(p_context); /* Test input pointers */ if (NULL == pa_tag || NULL == tag_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_ccm_update_aad != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_start_encdec != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_enc != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_dec != SM4_CCM_CONTEXT_STATE(p_context) && sm4_ccm_get_tag != SM4_CCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero and set bad status for tags of invalid length */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_tag[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } else { if (tag_len[buf_no] < 4 || tag_len[buf_no] > 16 || tag_len[buf_no] & 0x1) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } else { /* Check if total processed length is not equal to total message length passed at init */ if (processed_len[buf_no] != msg_len[buf_no]) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) { status |= sm4_ccm_get_tag_mb16(pa_tag, tag_len, (__mmask16)mb_mask, p_context); } #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/sm4_ccm_init_mb16_api.c000066400000000000000000000066171470420105600314670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_ccm_init_mb16)(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], const int tag_len[SM4_LINES], const int64u msg_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_key || NULL == pa_iv || NULL == iv_len || NULL == tag_len || NULL == msg_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero and set bad status for IV with zero length */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_key[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } if (pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } if ((iv_len[buf_no] < MIN_CCM_IV_LENGTH || iv_len[buf_no] > MAX_CCM_IV_LENGTH)) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } if ((tag_len[buf_no] < MIN_CCM_TAG_LENGTH) || (tag_len[buf_no] > MAX_CCM_TAG_LENGTH) || (tag_len[buf_no] & 0x1)) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } /* Check maximum message length allowed, given the number of bytes to encode message length */ int q = 15 - iv_len[buf_no]; int64u max_len = (q == 8) ? 0xFFFFFFFFFFFFFFFF : ((1ULL << (q << 3)) - 1); /* (2^(q * 8) - 1 */ if (msg_len[buf_no] > max_len) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= internal_avx512_sm4_ccm_init_mb16(pa_key, pa_iv, iv_len, tag_len, msg_len, p_context, (__mmask16)mb_mask); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/ccm/sm4_ccm_update_aad_mb16_api.c000066400000000000000000000043571470420105600326120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_ccm_update_aad_mb16)(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], SM4_CCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_aad || NULL == aad_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_ccm_update_aad != SM4_CCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_aad[buf_no] == NULL) { if (aad_len[buf_no] != 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); continue; } } if (aad_len[buf_no] < 0 || aad_len[buf_no] > MAX_CCM_AAD_LENGTH) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ccm_update_aad_mb16(pa_aad, aad_len, (__mmask16)mb_mask, p_context); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/000077500000000000000000000000001470420105600252675ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/000077500000000000000000000000001470420105600302115ustar00rootroot00000000000000sm4_gcm_decrypt_mb16.c000066400000000000000000000104371470420105600342130ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function performs decryption of given data and updates ghash with given data. // Function returns mask where bit is set to 1 if length of given data for buffer is overflowed. */ __mmask16 sm4_gcm_decrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { if (SM4_GCM_CONTEXT_STATE(p_context) == sm4_gcm_update_iv) { /* Finalize IVs */ sm4_gcm_finalize_iv_mb16(NULL, mb_mask, p_context); } /* Switch context state to decryption */ SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_dec; const int8u *loc_pa_in[SM4_LINES]; int in_len_rearranged[SM4_LINES]; /* Rearrange input pointers and lengths to required layout */ rearrange(loc_pa_in, pa_in); rearrange(in_len_rearranged, in_len); __m512i loc_in_len = loadu(in_len_rearranged); __mmask16 overflow_mask = 0x0000; __m512i max_txt_len = set1_epi64(0xFFFFFFFE0); /* (2^39 - 256) div 8 */ /* // Update txt length // // TXT length is passed as 32 bit integer // TXT length is used to construct last block for ghash computation as follow: // 64 bits with AAD length | 64 bits with TXT length // Length of AAD and TXT is stored in context in this form // // Code below transforms 32 bit input integers into the following block: // 64 bits with TXT length | 64 zero bits // and add it to length stored in context // // The whole operation is the following for each buffer: // 64 bits with AAD len in context | 64 bits with TXT len in context // + // 64 zero bits | 32 zero bits | 32 bits with input TXT len */ for (int i = 0; i < 4; i++) { __m512i len_updade = maskz_expandloadu_epi32(0x1111, (void *)(in_len_rearranged + i * 4)); /* Load txt len to high part of registry */ __m512i len_context = loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), i)); len_context = add_epi64(len_context, len_updade); storeu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), i), len_context); __mmask8 overflow_mask_part = cmp_epi64_mask(max_txt_len, len_context, _MM_CMPINT_LE); overflow_mask_part = (overflow_mask_part & 0x01) | (overflow_mask_part & 0x04) >> 1 | (overflow_mask_part & 0x10) >> 2 | (overflow_mask_part & 0x40) >> 3; overflow_mask = overflow_mask | overflow_mask_part << (i * 4); } /* Update intermediate ghash value with full blocks of given data */ sm4_gcm_update_ghash_full_blocks_mb16(SM4_GCM_CONTEXT_GHASH(p_context), loc_pa_in, &loc_in_len, SM4_GCM_CONTEXT_HASHKEY(p_context), mb_mask); if (cmp_epi32_mask(loc_in_len, setzero(), _MM_CMPINT_EQ) != 0xFFFF) { /* Update intermediate ghash value with partial blocks of given data */ sm4_gcm_update_ghash_partial_blocks_mb16( SM4_GCM_CONTEXT_GHASH(p_context), loc_pa_in, &loc_in_len, SM4_GCM_CONTEXT_HASHKEY(p_context)[0], mb_mask); /* Switch context state to tag computation to prevent decryption after any partial blocks are processed */ SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_get_tag; } const mbx_sm4_key_schedule *key_sched = (const mbx_sm4_key_schedule *)SM4_GCM_CONTEXT_KEY(p_context); /* Decrypt */ sm4_gctr_kernel_mb16(pa_out, pa_in, in_len, (const int32u **)key_sched, mb_mask, p_context); return overflow_mask; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_encrypt_j0_mb16.c000066400000000000000000000053601470420105600346150ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function encrypts J0 to use it for tag computation // Encrypted J0 value XOR'ed with accumulated GHASH value in function sm4_gcm_get_tag_mb16 */ void sm4_encrypt_j0_mb16(SM4_GCM_CTX_mb16 *p_context) { const mbx_sm4_key_schedule *key_sched = (const mbx_sm4_key_schedule *)SM4_GCM_CONTEXT_KEY(context); __m512i j0_blocks[4]; __m128i *j0 = SM4_GCM_CONTEXT_J0(p_context); int tagRearrange[] = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; const int8u *pa_inp[SM4_LINES]; for (int i = 0; i < SM4_LINES; i++) { pa_inp[i] = (unsigned char *)(j0 + tagRearrange[i]); } TRANSPOSE_16x4_I32_EPI32(&j0_blocks[0], &j0_blocks[1], &j0_blocks[2], &j0_blocks[3], pa_inp, 0xFFFF); const __m512i *p_rk = (const __m512i *)key_sched; __m512i tmp; for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) { SM4_FOUR_ROUNDS(j0_blocks[0], j0_blocks[1], j0_blocks[2], j0_blocks[3], tmp, p_rk, 1); } tmp = j0_blocks[0]; j0_blocks[0] = j0_blocks[3]; j0_blocks[3] = tmp; tmp = j0_blocks[1]; j0_blocks[1] = j0_blocks[2]; j0_blocks[2] = tmp; __m512i T1_0 = unpacklo_epi32(j0_blocks[0], j0_blocks[1]); __m512i T1_1 = unpackhi_epi32(j0_blocks[0], j0_blocks[1]); __m512i T1_2 = unpacklo_epi32(j0_blocks[2], j0_blocks[3]); __m512i T1_3 = unpackhi_epi32(j0_blocks[2], j0_blocks[3]); j0_blocks[0] = unpacklo_epi64(T1_0, T1_2); j0_blocks[1] = unpackhi_epi64(T1_0, T1_2); j0_blocks[2] = unpacklo_epi64(T1_1, T1_3); j0_blocks[3] = unpackhi_epi64(T1_1, T1_3); j0_blocks[0] = shuffle_epi8(j0_blocks[0], M512(swapBytes)); j0_blocks[1] = shuffle_epi8(j0_blocks[1], M512(swapBytes)); j0_blocks[2] = shuffle_epi8(j0_blocks[2], M512(swapBytes)); j0_blocks[3] = shuffle_epi8(j0_blocks[3], M512(swapBytes)); storeu(j0 + 0, j0_blocks[0]); storeu(j0 + 4, j0_blocks[1]); storeu(j0 + 8, j0_blocks[2]); storeu(j0 + 12, j0_blocks[3]); } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_encrypt_mb16.c000066400000000000000000000105241470420105600342220ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function performs encryption of given data and updates ghash with encrypted data. // Function returns mask where bit is set to 1 if length of given data for buffer is overflowed. */ __mmask16 sm4_gcm_encrypt_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { if (SM4_GCM_CONTEXT_STATE(p_context) == sm4_gcm_update_iv) { /* Finalize IVs */ sm4_gcm_finalize_iv_mb16(NULL, mb_mask, p_context); } /* Switch context state to encryption */ SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_enc; const mbx_sm4_key_schedule *key_sched = (const mbx_sm4_key_schedule *)SM4_GCM_CONTEXT_KEY(p_context); /* Encrypt */ sm4_gctr_kernel_mb16(pa_out, pa_in, in_len, (const int32u **)key_sched, mb_mask, p_context); int8u *loc_pa_out[SM4_LINES]; int in_len_rearranged[SM4_LINES]; /* Rearrange input pointers and lengths to required layout */ rearrange(loc_pa_out, pa_out); rearrange(in_len_rearranged, in_len); __m512i loc_in_len = loadu(in_len_rearranged); __mmask16 overflow_mask = 0x0000; __m512i max_txt_len = set1_epi64(0xFFFFFFFE0); /* (2^39 - 256) div 8 */ /* // Update txt length // // TXT length is passed as 32 bit integer // TXT length is used to construct last block for ghash computation as follow: // 64 bits with AAD length | 64 bits with TXT length // Length of AAD and TXT is stored in context in this form // // Code below transforms 32 bit input integers into the following block: // 64 bits with TXT length | 64 zero bits // and add it to length stored in context // // The whole operation is the following for each buffer: // 64 bits with AAD len in context | 64 bits with TXT len in context // + // 64 zero bits | 32 zero bits | 32 bits with input TXT len */ for (int i = 0; i < 4; i++) { __m512i len_updade = maskz_expandloadu_epi32(0x1111, (void *)(in_len_rearranged + i * 4)); /* Load txt len to high part of _m512iistry */ __m512i len_context = loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), i)); len_context = add_epi64(len_context, len_updade); storeu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), i), len_context); __mmask8 overflow_mask_part = cmp_epi64_mask(max_txt_len, len_context, _MM_CMPINT_LE); overflow_mask_part = (overflow_mask_part & 0x01) | (overflow_mask_part & 0x04) >> 1 | (overflow_mask_part & 0x10) >> 2 | (overflow_mask_part & 0x40) >> 3; overflow_mask = overflow_mask | overflow_mask_part << (i * 4); } /* Update intermediate ghash value with full blocks of encrypted data */ sm4_gcm_update_ghash_full_blocks_mb16( SM4_GCM_CONTEXT_GHASH(p_context), (const int8u **)loc_pa_out, &loc_in_len, SM4_GCM_CONTEXT_HASHKEY(p_context), mb_mask); if (cmp_epi32_mask(loc_in_len, setzero(), _MM_CMPINT_EQ) != 0xFFFF) { /* Update intermediate ghash value with partial blocks of encrypted data */ sm4_gcm_update_ghash_partial_blocks_mb16( SM4_GCM_CONTEXT_GHASH(p_context), (const int8u **)loc_pa_out, &loc_in_len, SM4_GCM_CONTEXT_HASHKEY(p_context)[0], mb_mask); /* Switch context state to tag computation to prevent decryption after any partial blocks are processed */ SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_get_tag; } return overflow_mask; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_finalize_iv_mb16.c000066400000000000000000000206231470420105600350360ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function performs IV finalization (computes J0) in the follow way: // If bitlen(IV) == 96, then let J0 = IV || 0^31 ||1. // If bitlen(IV) != 96, then let s = 128 * [bitlen(IV) / 128] - bitlen(IV), and let J0 = GHASH(IV || 0^(s+64) || bitlen(IV)). // // 0^s means the bit string that consists of s '0' bits here // [x] means the least integer that is not less than the real number x here // // This function also encrypts J0 by calling sm4_encrypt_j0_mb16(), to use it later for tag computation */ void sm4_gcm_finalize_iv_mb16(const int8u *const pa_iv[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { __m128i *ctr = SM4_GCM_CONTEXT_CTR(p_context); __m128i *j0 = SM4_GCM_CONTEXT_J0(p_context); __m128i *hashkey = SM4_GCM_CONTEXT_HASHKEY(p_context)[0]; int64u *iv_len = SM4_GCM_CONTEXT_LEN(p_context); __m512i hashkeys_4_0, hashkeys_4_1, hashkeys_4_2, hashkeys_4_3; __m512i *hashkeys[] = { &hashkeys_4_0, &hashkeys_4_1, &hashkeys_4_2, &hashkeys_4_3 }; __m512i iv_blocks_4_0, iv_blocks_4_1, iv_blocks_4_2, iv_blocks_4_3; __m512i *data_blocks[] = { &iv_blocks_4_0, &iv_blocks_4_1, &iv_blocks_4_2, &iv_blocks_4_3 }; __m512i len_hi = loadu(iv_len); __m512i len_lo = loadu(iv_len + 8); __mmask8 eq_12_mask_hi = cmp_epi64_mask(len_hi, set1_epi64(12), _MM_CMPINT_EQ); __mmask8 eq_12_mask_lo = cmp_epi64_mask(len_lo, set1_epi64(12), _MM_CMPINT_EQ); __mmask8 eq_0_mask_hi = cmp_epi64_mask(len_hi, setzero(), _MM_CMPINT_EQ); __mmask8 eq_0_mask_lo = cmp_epi64_mask(len_lo, setzero(), _MM_CMPINT_EQ); __mmask16 eq_12_mask = eq_12_mask_lo << 8 | eq_12_mask_hi; __mmask16 eq_0_mask = eq_0_mask_lo << 8 | eq_0_mask_hi; __mmask16 load_mask = ~eq_12_mask | ~eq_0_mask; /* Finalize IVs of length != 96 bit */ if (load_mask) { hashkeys_4_0 = loadu(hashkey + 0); hashkeys_4_1 = loadu(hashkey + 4); hashkeys_4_2 = loadu(hashkey + 8); hashkeys_4_3 = loadu(hashkey + 12); iv_blocks_4_0 = setzero(); iv_blocks_4_1 = setzero(); iv_blocks_4_2 = setzero(); iv_blocks_4_3 = setzero(); /* // Loop with 4 iterations here does not unrolled by some compilers // Unrolled explicitly because insert32x4 require the last parameter to be const */ /* Begin of explicitly unrolled loop */ __m128i input_block_0 = _mm_maskz_set1_epi64(1, *(iv_len + (0 + 4 * 0)) << 3); __m128i input_block_1 = _mm_maskz_set1_epi64(1, *(iv_len + (0 + 4 * 1)) << 3); __m128i input_block_2 = _mm_maskz_set1_epi64(1, *(iv_len + (0 + 4 * 2)) << 3); __m128i input_block_3 = _mm_maskz_set1_epi64(1, *(iv_len + (0 + 4 * 3)) << 3); iv_blocks_4_0 = insert32x4(iv_blocks_4_0, input_block_0, 0); iv_blocks_4_1 = insert32x4(iv_blocks_4_1, input_block_1, 0); iv_blocks_4_2 = insert32x4(iv_blocks_4_2, input_block_2, 0); iv_blocks_4_3 = insert32x4(iv_blocks_4_3, input_block_3, 0); input_block_0 = _mm_maskz_set1_epi64(1, *(iv_len + (1 + 4 * 0)) << 3); input_block_1 = _mm_maskz_set1_epi64(1, *(iv_len + (1 + 4 * 1)) << 3); input_block_2 = _mm_maskz_set1_epi64(1, *(iv_len + (1 + 4 * 2)) << 3); input_block_3 = _mm_maskz_set1_epi64(1, *(iv_len + (1 + 4 * 3)) << 3); iv_blocks_4_0 = insert32x4(iv_blocks_4_0, input_block_0, 1); iv_blocks_4_1 = insert32x4(iv_blocks_4_1, input_block_1, 1); iv_blocks_4_2 = insert32x4(iv_blocks_4_2, input_block_2, 1); iv_blocks_4_3 = insert32x4(iv_blocks_4_3, input_block_3, 1); input_block_0 = _mm_maskz_set1_epi64(1, *(iv_len + (2 + 4 * 0)) << 3); input_block_1 = _mm_maskz_set1_epi64(1, *(iv_len + (2 + 4 * 1)) << 3); input_block_2 = _mm_maskz_set1_epi64(1, *(iv_len + (2 + 4 * 2)) << 3); input_block_3 = _mm_maskz_set1_epi64(1, *(iv_len + (2 + 4 * 3)) << 3); iv_blocks_4_0 = insert32x4(iv_blocks_4_0, input_block_0, 2); iv_blocks_4_1 = insert32x4(iv_blocks_4_1, input_block_1, 2); iv_blocks_4_2 = insert32x4(iv_blocks_4_2, input_block_2, 2); iv_blocks_4_3 = insert32x4(iv_blocks_4_3, input_block_3, 2); input_block_0 = _mm_maskz_set1_epi64(1, *(iv_len + (3 + 4 * 0)) << 3); input_block_1 = _mm_maskz_set1_epi64(1, *(iv_len + (3 + 4 * 1)) << 3); input_block_2 = _mm_maskz_set1_epi64(1, *(iv_len + (3 + 4 * 2)) << 3); input_block_3 = _mm_maskz_set1_epi64(1, *(iv_len + (3 + 4 * 3)) << 3); iv_blocks_4_0 = insert32x4(iv_blocks_4_0, input_block_0, 3); iv_blocks_4_1 = insert32x4(iv_blocks_4_1, input_block_1, 3); iv_blocks_4_2 = insert32x4(iv_blocks_4_2, input_block_2, 3); iv_blocks_4_3 = insert32x4(iv_blocks_4_3, input_block_3, 3); /* End of explicitly unrolled loop */ iv_blocks_4_0 = xor(iv_blocks_4_0, loadu(j0 + 0)); iv_blocks_4_1 = xor(iv_blocks_4_1, loadu(j0 + 4)); iv_blocks_4_2 = xor(iv_blocks_4_2, loadu(j0 + 8)); iv_blocks_4_3 = xor(iv_blocks_4_3, loadu(j0 + 12)); sm4_gcm_ghash_mul_single_block_mb16(data_blocks, hashkeys); iv_blocks_4_0 = shuffle_epi8(iv_blocks_4_0, M512(swapEndianness)); iv_blocks_4_1 = shuffle_epi8(iv_blocks_4_1, M512(swapEndianness)); iv_blocks_4_2 = shuffle_epi8(iv_blocks_4_2, M512(swapEndianness)); iv_blocks_4_3 = shuffle_epi8(iv_blocks_4_3, M512(swapEndianness)); __mmask8 store_mask_0 = 0x03 * (0x1 & ((load_mask >> 0 * 4) >> 0)) | 0x0C * (0x1 & ((load_mask >> 0 * 4) >> 1)) | 0x30 * (0x1 & ((load_mask >> 0 * 4) >> 2)) | 0xC0 * (0x1 & ((load_mask >> 0 * 4) >> 3)); __mmask8 store_mask_1 = 0x03 * (0x1 & ((load_mask >> 1 * 4) >> 0)) | 0x0C * (0x1 & ((load_mask >> 1 * 4) >> 1)) | 0x30 * (0x1 & ((load_mask >> 1 * 4) >> 2)) | 0xC0 * (0x1 & ((load_mask >> 1 * 4) >> 3)); __mmask8 store_mask_2 = 0x03 * (0x1 & ((load_mask >> 2 * 4) >> 0)) | 0x0C * (0x1 & ((load_mask >> 2 * 4) >> 1)) | 0x30 * (0x1 & ((load_mask >> 2 * 4) >> 2)) | 0xC0 * (0x1 & ((load_mask >> 2 * 4) >> 3)); __mmask8 store_mask_3 = 0x03 * (0x1 & ((load_mask >> 3 * 4) >> 0)) | 0x0C * (0x1 & ((load_mask >> 3 * 4) >> 1)) | 0x30 * (0x1 & ((load_mask >> 3 * 4) >> 2)) | 0xC0 * (0x1 & ((load_mask >> 3 * 4) >> 3)); mask_storeu_epi64(j0 + 0, store_mask_0, iv_blocks_4_0); mask_storeu_epi64(j0 + 4, store_mask_1, iv_blocks_4_1); mask_storeu_epi64(j0 + 8, store_mask_2, iv_blocks_4_2); mask_storeu_epi64(j0 + 12, store_mask_3, iv_blocks_4_3); } /* Finalize IVs of length == 96 bit */ if (eq_12_mask != 0 && pa_iv != NULL) { __m128i iv_block; for (int i = 0; i < SM4_LINES; i++) { iv_block = _mm_mask_loadu_epi8(M128(one_f), 0x0FFF * (0x1 & eq_12_mask), (void *)pa_iv[i]); _mm_mask_storeu_epi8(j0 + i, 0xFFFF * (0x1 & eq_12_mask), iv_block); eq_12_mask >>= 1; } } /* Store initial counter */ storeu(ctr + 0, inc_block32(shuffle_epi8(loadu(j0 + 0), M512(swapEndianness)), initialInc)); storeu(ctr + 4, inc_block32(shuffle_epi8(loadu(j0 + 4), M512(swapEndianness)), initialInc)); storeu(ctr + 8, inc_block32(shuffle_epi8(loadu(j0 + 8), M512(swapEndianness)), initialInc)); storeu(ctr + 12, inc_block32(shuffle_epi8(loadu(j0 + 12), M512(swapEndianness)), initialInc)); sm4_encrypt_j0_mb16(p_context); /* Clear length buffer to reuse it for TXT and AAD length */ SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 0)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 1)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 2)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 3)); } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_gctr_kernel_mb16.c000066400000000000000000000411111470420105600350310ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 /* for zero_mb8 */ #if (_MBX>=_MBX_K1) /* // These functions performs GCTR encryption/decryption // Implementation is the same with SM4-CTR */ __MBX_INLINE __m128i IncBlock128(__m128i x, int32u increment) { return _mm_add_epi32(x, _mm_maskz_loadu_epi32(1, &increment)); } static void sm4_gctr_mask_kernel_mb16(__m512i *CTR, const __m512i *p_rk, __m512i loc_len, const int8u **loc_inp, int8u **loc_out, int8u *inc, __mmask16 tmp_mask, __mmask16 mb_mask) { __m512i TMP[20]; while (tmp_mask) { *CTR = inc_block32(*CTR, inc); *(CTR + 1) = inc_block32(*(CTR + 1), inc); *(CTR + 2) = inc_block32(*(CTR + 2), inc); *(CTR + 3) = inc_block32(*(CTR + 3), inc); TMP[0] = shuffle_epi8(*CTR, M512(swapWordsOrder)); TMP[1] = shuffle_epi8(*(CTR + 1), M512(swapWordsOrder)); TMP[2] = shuffle_epi8(*(CTR + 2), M512(swapWordsOrder)); TMP[3] = shuffle_epi8(*(CTR + 3), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); *(CTR + 4) = inc_block32(*(CTR + 4), inc); *(CTR + 5) = inc_block32(*(CTR + 5), inc); *(CTR + 6) = inc_block32(*(CTR + 6), inc); *(CTR + 7) = inc_block32(*(CTR + 7), inc); TMP[0] = shuffle_epi8(*(CTR + 4), M512(swapWordsOrder)); TMP[1] = shuffle_epi8(*(CTR + 5), M512(swapWordsOrder)); TMP[2] = shuffle_epi8(*(CTR + 6), M512(swapWordsOrder)); TMP[3] = shuffle_epi8(*(CTR + 7), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); *(CTR + 8) = inc_block32(*(CTR + 8), inc); *(CTR + 9) = inc_block32(*(CTR + 9), inc); *(CTR + 10) = inc_block32(*(CTR + 10), inc); *(CTR + 11) = inc_block32(*(CTR + 11), inc); TMP[0] = shuffle_epi8(*(CTR + 8), M512(swapWordsOrder)); TMP[1] = shuffle_epi8(*(CTR + 9), M512(swapWordsOrder)); TMP[2] = shuffle_epi8(*(CTR + 10), M512(swapWordsOrder)); TMP[3] = shuffle_epi8(*(CTR + 11), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); *(CTR + 12) = inc_block32(*(CTR + 12), inc); *(CTR + 13) = inc_block32(*(CTR + 13), inc); *(CTR + 14) = inc_block32(*(CTR + 14), inc); *(CTR + 15) = inc_block32(*(CTR + 15), inc); TMP[0] = shuffle_epi8(*(CTR + 12), M512(swapWordsOrder)); TMP[1] = shuffle_epi8(*(CTR + 13), M512(swapWordsOrder)); TMP[2] = shuffle_epi8(*(CTR + 14), M512(swapWordsOrder)); TMP[3] = shuffle_epi8(*(CTR + 15), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, 1); p_rk -= SM4_ROUNDS; /* Mask for data loading */ __mmask64 stream_mask; int *p_loc_len = (int *)&loc_len; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[0], stream_mask, xor(TMP[0], maskz_loadu_epi8(stream_mask, loc_inp[0]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[1], stream_mask, xor(TMP[1], maskz_loadu_epi8(stream_mask, loc_inp[1]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[2], stream_mask, xor(TMP[2], maskz_loadu_epi8(stream_mask, loc_inp[2]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[3], stream_mask, xor(TMP[3], maskz_loadu_epi8(stream_mask, loc_inp[3]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[4], stream_mask, xor(TMP[0], maskz_loadu_epi8(stream_mask, loc_inp[4]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[5], stream_mask, xor(TMP[1], maskz_loadu_epi8(stream_mask, loc_inp[5]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[6], stream_mask, xor(TMP[2], maskz_loadu_epi8(stream_mask, loc_inp[6]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[7], stream_mask, xor(TMP[3], maskz_loadu_epi8(stream_mask, loc_inp[7]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[8], stream_mask, xor(TMP[0], maskz_loadu_epi8(stream_mask, loc_inp[8]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[9], stream_mask, xor(TMP[1], maskz_loadu_epi8(stream_mask, loc_inp[9]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[10], stream_mask, xor(TMP[2], maskz_loadu_epi8(stream_mask, loc_inp[10]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[11], stream_mask, xor(TMP[3], maskz_loadu_epi8(stream_mask, loc_inp[11]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[12], stream_mask, xor(TMP[0], maskz_loadu_epi8(stream_mask, loc_inp[12]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[13], stream_mask, xor(TMP[1], maskz_loadu_epi8(stream_mask, loc_inp[13]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[14], stream_mask, xor(TMP[2], maskz_loadu_epi8(stream_mask, loc_inp[14]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) mask_storeu_epi8((__m512i *)loc_out[15], stream_mask, xor(TMP[3], maskz_loadu_epi8(stream_mask, loc_inp[15]))); /* Update pointers to data */ M512(loc_inp) = add_epi64(loadu(loc_inp), set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = add_epi64(loadu(loc_inp + 8), set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = add_epi64(loadu(loc_out), set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = add_epi64(loadu(loc_out + 8), set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = sub_epi32(loc_len, set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = mask_cmp_epi32_mask(mb_mask, loc_len, set1_epi32(0), _MM_CMPINT_NLE); inc = (int8u *)nextInc; } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); } void sm4_gctr_kernel_mb16(int8u *pa_out[SM4_LINES], const int8u *const pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u *key_sched[SM4_ROUNDS], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { __mmask16 loc_mb_mask = 0; for (int i = 0; i < SM4_LINES; i++) { __mmask16 tmp = mb_mask & (0x1 << rearrangeOrder[i]); tmp = tmp >> rearrangeOrder[i]; loc_mb_mask = loc_mb_mask | tmp << i; } mb_mask = loc_mb_mask; const int8u *loc_inp[SM4_LINES]; int8u *loc_out[SM4_LINES]; /* Create the local copy of the input data length in bytes and set it to zero for non-valid buffers */ __m512i loc_len; loc_len = loadu(len); loc_len = mask_set1_epi32(loc_len, ~mb_mask, 0); /* input blocks loc_blks[] = ceil(loc_len[]/SM4_BLOCK_SIZE) */ int32u loc_blks[SM4_LINES]; storeu(loc_blks, srli_epi32(add_epi32(loc_len, set1_epi32(SM4_BLOCK_SIZE - 1)), 4)); /* Local copies of the pointers to input and output buffers */ storeu((void *)loc_inp, loadu(pa_inp)); storeu((void *)(loc_inp + 8), loadu(pa_inp + 8)); storeu(loc_out, loadu(pa_out)); storeu(loc_out + 8, loadu(pa_out + 8)); /* Pointer p_rk is set to the beginning of the key schedule */ const __m512i *p_rk = (const __m512i *)key_sched; /* TMP[] - temporary buffer for processing */ /* CTR - store CTR values */ __m512i TMP[20]; __m512i CTR[SM4_LINES]; __m128i loc_ctr[SM4_LINES]; /* Load CTR value from valid buffers and rearrange it */ mb_mask = mask_cmp_epi32_mask(mb_mask, loc_len, setzero(), _MM_CMPINT_NLE); int ctrRearrange[] = { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; for (int i = 0; i < SM4_LINES; i++) { if (0x1 & (mb_mask >> i)) { loc_ctr[i] = _mm_loadu_si128(SM4_GCM_CONTEXT_CTR(p_context) + ctrRearrange[i]); } else { loc_ctr[i] = _mm_setzero_si128(); } CTR[i] = broadcast_i64x2(loc_ctr[i]); } /* Generate the mask to process 4 blocks from each buffer */ __mmask16 tmp_mask = mask_cmp_epi32_mask(mb_mask, loc_len, set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); int8u *inc = (int8u *)firstInc; /* Go to this loop if all 16 buffers contain at least 4 blocks each */ while (tmp_mask == 0xFFFF) { CTR[0] = inc_block32(CTR[0], inc); CTR[1] = inc_block32(CTR[1], inc); CTR[2] = inc_block32(CTR[2], inc); CTR[3] = inc_block32(CTR[3], inc); TMP[0] = shuffle_epi8(CTR[0], M512(swapWordsOrder)); TMP[1] = shuffle_epi8(CTR[1], M512(swapWordsOrder)); TMP[2] = shuffle_epi8(CTR[2], M512(swapWordsOrder)); TMP[3] = shuffle_epi8(CTR[3], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); CTR[4] = inc_block32(CTR[4], inc); CTR[5] = inc_block32(CTR[5], inc); CTR[6] = inc_block32(CTR[6], inc); CTR[7] = inc_block32(CTR[7], inc); TMP[0] = shuffle_epi8(CTR[4], M512(swapWordsOrder)); TMP[1] = shuffle_epi8(CTR[5], M512(swapWordsOrder)); TMP[2] = shuffle_epi8(CTR[6], M512(swapWordsOrder)); TMP[3] = shuffle_epi8(CTR[7], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); CTR[8] = inc_block32(CTR[8], inc); CTR[9] = inc_block32(CTR[9], inc); CTR[10] = inc_block32(CTR[10], inc); CTR[11] = inc_block32(CTR[11], inc); TMP[0] = shuffle_epi8(CTR[8], M512(swapWordsOrder)); TMP[1] = shuffle_epi8(CTR[9], M512(swapWordsOrder)); TMP[2] = shuffle_epi8(CTR[10], M512(swapWordsOrder)); TMP[3] = shuffle_epi8(CTR[11], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); CTR[12] = inc_block32(CTR[12], inc); CTR[13] = inc_block32(CTR[13], inc); CTR[14] = inc_block32(CTR[14], inc); CTR[15] = inc_block32(CTR[15], inc); TMP[0] = shuffle_epi8(CTR[12], M512(swapWordsOrder)); TMP[1] = shuffle_epi8(CTR[13], M512(swapWordsOrder)); TMP[2] = shuffle_epi8(CTR[14], M512(swapWordsOrder)); TMP[3] = shuffle_epi8(CTR[15], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, 1); p_rk -= SM4_ROUNDS; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); storeu((__m512i *)loc_out[0], xor(TMP[0], loadu(loc_inp[0]))); storeu((__m512i *)loc_out[1], xor(TMP[1], loadu(loc_inp[1]))); storeu((__m512i *)loc_out[2], xor(TMP[2], loadu(loc_inp[2]))); storeu((__m512i *)loc_out[3], xor(TMP[3], loadu(loc_inp[3]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); storeu((__m512i *)loc_out[4], xor(TMP[0], loadu(loc_inp[4]))); storeu((__m512i *)loc_out[5], xor(TMP[1], loadu(loc_inp[5]))); storeu((__m512i *)loc_out[6], xor(TMP[2], loadu(loc_inp[6]))); storeu((__m512i *)loc_out[7], xor(TMP[3], loadu(loc_inp[7]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); storeu((__m512i *)loc_out[8], xor(TMP[0], loadu(loc_inp[8]))); storeu((__m512i *)loc_out[9], xor(TMP[1], loadu(loc_inp[9]))); storeu((__m512i *)loc_out[10], xor(TMP[2], loadu(loc_inp[10]))); storeu((__m512i *)loc_out[11], xor(TMP[3], loadu(loc_inp[11]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = shuffle_epi8(TMP[3], M512(swapBytes)); storeu((__m512i *)loc_out[12], xor(TMP[0], loadu(loc_inp[12]))); storeu((__m512i *)loc_out[13], xor(TMP[1], loadu(loc_inp[13]))); storeu((__m512i *)loc_out[14], xor(TMP[2], loadu(loc_inp[14]))); storeu((__m512i *)loc_out[15], xor(TMP[3], loadu(loc_inp[15]))); /* Update pointers to data */ M512(loc_inp) = add_epi64(loadu(loc_inp), set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = add_epi64(loadu(loc_inp + 8), set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = add_epi64(loadu(loc_out), set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = add_epi64(loadu(loc_out + 8), set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = sub_epi32(loc_len, set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = mask_cmp_epi32_mask(mb_mask, loc_len, set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); inc = (int8u *)nextInc; } /* Check if we have any data */ tmp_mask = mask_cmp_epi32_mask(mb_mask, loc_len, setzero(), _MM_CMPINT_NLE); if (tmp_mask) { sm4_gctr_mask_kernel_mb16(CTR, p_rk, loc_len, loc_inp, loc_out, inc, tmp_mask, mb_mask); } /* update and store counters */ for (int i = 0; i < SM4_LINES; i++) { if (0x1 & (mb_mask >> i)) { loc_ctr[i] = IncBlock128(loc_ctr[i], loc_blks[i]); _mm_storeu_si128(SM4_GCM_CONTEXT_CTR(p_context) + ctrRearrange[i], loc_ctr[i]); loc_ctr[i] = _mm_setzero_si128(); } } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); zero_mb8((int64u(*)[8])CTR, sizeof(CTR) / sizeof(CTR[0])); } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_get_tag_mb16.c000066400000000000000000000105321470420105600341470ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 /* for zero_mb8 */ #if (_MBX>=_MBX_K1) /* // This function performs tag computation as follow: // v = 128 * [bitlen(AAD) / 128] - bitlen(AAD) // u = 128 * [bitlen(TXT) / 128] - bitlen(TXT) // S = GHASH (AAD || 0^v || ciphTXT || 0^u || bitlen(AAD) || bitlen(ciphTXT)). // tag = S xor J0 // // J0 is previously encrypted // // 0^s means the bit string that consists of s '0' bits here // [x] means the least integer that is not less than the real number x here */ mbx_status16 sm4_gcm_get_tag_mb16(int8u *pa_out[SM4_LINES], const int tag_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { mbx_status16 status = 0; __m512i hashkeys_4_0, hashkeys_4_1, hashkeys_4_2, hashkeys_4_3; __m512i *hashkeys[] = { &hashkeys_4_0, &hashkeys_4_1, &hashkeys_4_2, &hashkeys_4_3 }; __m512i data_len_blocks_4_0, data_len_blocks_4_1, data_len_blocks_4_2, data_len_blocks_4_3; __m512i *data_blocks[] = { &data_len_blocks_4_0, &data_len_blocks_4_1, &data_len_blocks_4_2, &data_len_blocks_4_3 }; __m128i *hashkey = SM4_GCM_CONTEXT_HASHKEY(p_context)[0]; hashkeys_4_0 = loadu(hashkey + 0); hashkeys_4_1 = loadu(hashkey + 4); hashkeys_4_2 = loadu(hashkey + 8); hashkeys_4_3 = loadu(hashkey + 12); /* Convert length in bytes to length in bits */ data_len_blocks_4_0 = sll_epi32(loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 0)), M128(bytes_to_bits_shift)); data_len_blocks_4_1 = sll_epi32(loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 1)), M128(bytes_to_bits_shift)); data_len_blocks_4_2 = sll_epi32(loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 2)), M128(bytes_to_bits_shift)); data_len_blocks_4_3 = sll_epi32(loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 3)), M128(bytes_to_bits_shift)); /* XOR with accumulated GHASH value */ __m128i *ghash = SM4_GCM_CONTEXT_GHASH(p_context); data_len_blocks_4_0 = xor(data_len_blocks_4_0, loadu(ghash + 0)); data_len_blocks_4_1 = xor(data_len_blocks_4_1, loadu(ghash + 4)); data_len_blocks_4_2 = xor(data_len_blocks_4_2, loadu(ghash + 8)); data_len_blocks_4_3 = xor(data_len_blocks_4_3, loadu(ghash + 12)); /* Update GHASH value */ sm4_gcm_ghash_mul_single_block_mb16(data_blocks, hashkeys); data_len_blocks_4_0 = shuffle_epi8(data_len_blocks_4_0, M512(swapEndianness)); data_len_blocks_4_1 = shuffle_epi8(data_len_blocks_4_1, M512(swapEndianness)); data_len_blocks_4_2 = shuffle_epi8(data_len_blocks_4_2, M512(swapEndianness)); data_len_blocks_4_3 = shuffle_epi8(data_len_blocks_4_3, M512(swapEndianness)); __m512i j0_blocks[4]; __m128i *j0 = SM4_GCM_CONTEXT_J0(p_context); j0_blocks[0] = loadu(j0 + 0); j0_blocks[1] = loadu(j0 + 4); j0_blocks[2] = loadu(j0 + 8); j0_blocks[3] = loadu(j0 + 12); __m512i tag_blocks[4]; /* XOR with previously encrypted J0 */ tag_blocks[0] = xor(data_len_blocks_4_0, j0_blocks[0]); tag_blocks[1] = xor(data_len_blocks_4_1, j0_blocks[1]); tag_blocks[2] = xor(data_len_blocks_4_2, j0_blocks[2]); tag_blocks[3] = xor(data_len_blocks_4_3, j0_blocks[3]); /* Store result */ for (int i = 0; i < SM4_LINES; i++) { __m128i one_block = M128((__m128i *)tag_blocks + i); __mmask16 tagMask = ~(0xFFFF << (tag_len[rearrangeOrder[i]])) * ((mb_mask >> i) & 0x1); _mm_mask_storeu_epi8((void *)(pa_out[rearrangeOrder[i]]), tagMask, one_block); } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])tag_blocks, sizeof(tag_blocks) / sizeof(tag_blocks[0])); return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_ghash_mul_single_block_mb16.c000066400000000000000000000124251470420105600372220ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function performs GHASH multiplication: // Multiplication operation for the binary Galois (finite) field of 2^128 elements. // // Details about this operation can be found in NIST SP 800-38D // // This code is a port of GCM part of Intel(R) IPSec AES-GCM code // Code modified to work with multi-buffer approach */ void sm4_gcm_ghash_mul_single_block_mb16(__m512i *data_blocks[], __m512i *hashkeys[]) { __m512i T1_0, T2_0, T3_0; __m512i T1_1, T2_1, T3_1; __m512i T1_2, T2_2, T3_2; __m512i T1_3, T2_3, T3_3; T1_0 = clmul(*(hashkeys[0]), *(data_blocks[0]), 0x11); // T1 = a1*b1 T1_1 = clmul(*(hashkeys[1]), *(data_blocks[1]), 0x11); T1_2 = clmul(*(hashkeys[2]), *(data_blocks[2]), 0x11); T1_3 = clmul(*(hashkeys[3]), *(data_blocks[3]), 0x11); T2_0 = clmul(*(hashkeys[0]), *(data_blocks[0]), 0x00); // T1 = a0*b0 T2_1 = clmul(*(hashkeys[1]), *(data_blocks[1]), 0x00); T2_2 = clmul(*(hashkeys[2]), *(data_blocks[2]), 0x00); T2_3 = clmul(*(hashkeys[3]), *(data_blocks[3]), 0x00); T3_0 = clmul(*(hashkeys[0]), *(data_blocks[0]), 0x01); // T3 = a1*b0 T3_1 = clmul(*(hashkeys[1]), *(data_blocks[1]), 0x01); T3_2 = clmul(*(hashkeys[2]), *(data_blocks[2]), 0x01); T3_3 = clmul(*(hashkeys[3]), *(data_blocks[3]), 0x01); *(data_blocks[0]) = clmul(*(hashkeys[0]), *(data_blocks[0]), 0x10); // T3 = a0*b1 *(data_blocks[1]) = clmul(*(hashkeys[1]), *(data_blocks[1]), 0x10); *(data_blocks[2]) = clmul(*(hashkeys[2]), *(data_blocks[2]), 0x10); *(data_blocks[3]) = clmul(*(hashkeys[3]), *(data_blocks[3]), 0x10); *(data_blocks[0]) = xor(*(data_blocks[0]), T3_0); *(data_blocks[1]) = xor(*(data_blocks[1]), T3_1); *(data_blocks[2]) = xor(*(data_blocks[2]), T3_2); *(data_blocks[3]) = xor(*(data_blocks[3]), T3_3); T3_0 = bsrli_epi128(*(data_blocks[0]), 8); T3_1 = bsrli_epi128(*(data_blocks[1]), 8); T3_2 = bsrli_epi128(*(data_blocks[2]), 8); T3_3 = bsrli_epi128(*(data_blocks[3]), 8); *(data_blocks[0]) = bslli_epi128(*(data_blocks[0]), 8); *(data_blocks[1]) = bslli_epi128(*(data_blocks[1]), 8); *(data_blocks[2]) = bslli_epi128(*(data_blocks[2]), 8); *(data_blocks[3]) = bslli_epi128(*(data_blocks[3]), 8); T1_0 = xor(T1_0, T3_0); T1_1 = xor(T1_1, T3_1); T1_2 = xor(T1_2, T3_2); T1_3 = xor(T1_3, T3_3); *(data_blocks[0]) = xor(*(data_blocks[0]), T2_0); *(data_blocks[1]) = xor(*(data_blocks[1]), T2_1); *(data_blocks[2]) = xor(*(data_blocks[2]), T2_2); *(data_blocks[3]) = xor(*(data_blocks[3]), T2_3); /* first phase of the reduction */ T2_0 = clmul(M512(gcm_poly2), *(data_blocks[0]), 0x01); T2_1 = clmul(M512(gcm_poly2), *(data_blocks[1]), 0x01); T2_2 = clmul(M512(gcm_poly2), *(data_blocks[2]), 0x01); T2_3 = clmul(M512(gcm_poly2), *(data_blocks[3]), 0x01); T2_0 = bslli_epi128(T2_0, 8); T2_1 = bslli_epi128(T2_1, 8); T2_2 = bslli_epi128(T2_2, 8); T2_3 = bslli_epi128(T2_3, 8); *(data_blocks[0]) = xor(*(data_blocks[0]), T2_0); *(data_blocks[1]) = xor(*(data_blocks[1]), T2_1); *(data_blocks[2]) = xor(*(data_blocks[2]), T2_2); *(data_blocks[3]) = xor(*(data_blocks[3]), T2_3); /* second phase of the reduction */ T2_0 = clmul(M512(gcm_poly2), *(data_blocks[0]), 0x00); T2_1 = clmul(M512(gcm_poly2), *(data_blocks[1]), 0x00); T2_2 = clmul(M512(gcm_poly2), *(data_blocks[2]), 0x00); T2_3 = clmul(M512(gcm_poly2), *(data_blocks[3]), 0x00); T2_0 = bsrli_epi128(T2_0, 4); T2_1 = bsrli_epi128(T2_1, 4); T2_2 = bsrli_epi128(T2_2, 4); T2_3 = bsrli_epi128(T2_3, 4); *(data_blocks[0]) = clmul(M512(gcm_poly2), *(data_blocks[0]), 0x10); *(data_blocks[1]) = clmul(M512(gcm_poly2), *(data_blocks[1]), 0x10); *(data_blocks[2]) = clmul(M512(gcm_poly2), *(data_blocks[2]), 0x10); *(data_blocks[3]) = clmul(M512(gcm_poly2), *(data_blocks[3]), 0x10); *(data_blocks[0]) = bslli_epi128(*(data_blocks[0]), 4); *(data_blocks[1]) = bslli_epi128(*(data_blocks[1]), 4); *(data_blocks[2]) = bslli_epi128(*(data_blocks[2]), 4); *(data_blocks[3]) = bslli_epi128(*(data_blocks[3]), 4); *(data_blocks[0]) = xor(*(data_blocks[0]), T2_0); *(data_blocks[1]) = xor(*(data_blocks[1]), T2_1); *(data_blocks[2]) = xor(*(data_blocks[2]), T2_2); *(data_blocks[3]) = xor(*(data_blocks[3]), T2_3); *(data_blocks[0]) = xor(*(data_blocks[0]), T1_0); *(data_blocks[1]) = xor(*(data_blocks[1]), T1_1); *(data_blocks[2]) = xor(*(data_blocks[2]), T1_2); *(data_blocks[3]) = xor(*(data_blocks[3]), T1_3); } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_init_mb16.c000066400000000000000000000056511470420105600335060ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 internal_avx512_sm4_gcm_init_mb16(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context, __mmask16 mb_mask_rearranged, __mmask16 mb_mask) { mbx_status16 status = 0; /* Clear buffers */ SM4_GCM_CLEAR_BUFFER((SM4_GCM_CONTEXT_BUFFER_SLOT_TYPE *)SM4_GCM_CONTEXT_J0(p_context)); SM4_GCM_CLEAR_BUFFER((SM4_GCM_CONTEXT_BUFFER_SLOT_TYPE *)SM4_GCM_CONTEXT_GHASH(p_context)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 0)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 1)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 2)); SM4_GCM_CLEAR_LEN(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 3)); /* // Compute SM4 keys // initialize int32u mbx_sm4_key_schedule[SM4_ROUNDS][SM4_LINES] buffer in context // keys layout for each round: // key0 key4 key8 key12 key1 key5 key9 key13 key2 key6 key10 key14 key3 key7 key11 key15 */ internal_avx512_sm4_set_round_keys_mb16((int32u **)SM4_GCM_CONTEXT_KEY(p_context), (const int8u **)pa_key, mb_mask); /* // Compute hashkeys // initialize __m128i hashkey[SM4_GCM_HASHKEY_PWR_NUM][SM4_LINES] buffer in context // hashkeys layout for each hashkey power: // hashkey0 hashkey4 hashkey8 hashkey12 hashkey1 hashkey5 hashkey9 hashkey13 hashkey2 hashkey6 hashkey10 hashkey14 hashkey3 hashkey7 hashkey11 hashkey15 */ sm4_gcm_precompute_hashkey_mb16((const mbx_sm4_key_schedule *)SM4_GCM_CONTEXT_KEY(p_context), p_context); /* Process IV */ __mmask16 overflow_mask = sm4_gcm_update_iv_mb16(pa_iv, iv_len, mb_mask_rearranged, p_context); /* Set bad status for buffers with overflowed lengths */ for (int buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (overflow_mask >> buf_no & 1) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } } return status; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_precompute_hashkey_mb16.c000066400000000000000000000140641470420105600364400ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function precomputes haskeys for delayed reduction: // hashkeys >> 1 mod poly and hashkeys ^ 2 >> 1 mod poly ... hashkeys ^ 7 >> 1 mod poly // // This code is a port of GCM part of Intel(R) IPSec AES-GCM code // Code modified to work with multi-buffer approach */ void sm4_gcm_precompute_hashkey_mb16(const mbx_sm4_key_schedule *key_sched, SM4_GCM_CTX_mb16 *p_context) { const __m512i *p_rk = (const __m512i *)key_sched; __m512i tmp; /* Encrypt zero blocks */ __m512i hashkey_blocks_4_0 = setzero(); __m512i hashkey_blocks_4_1 = setzero(); __m512i hashkey_blocks_4_2 = setzero(); __m512i hashkey_blocks_4_3 = setzero(); for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) { SM4_FOUR_ROUNDS(hashkey_blocks_4_0, hashkey_blocks_4_1, hashkey_blocks_4_2, hashkey_blocks_4_3, tmp, p_rk, 1); } tmp = hashkey_blocks_4_0; hashkey_blocks_4_0 = hashkey_blocks_4_3; hashkey_blocks_4_3 = tmp; tmp = hashkey_blocks_4_1; hashkey_blocks_4_1 = hashkey_blocks_4_2; hashkey_blocks_4_2 = tmp; /* Get the right endianness */ __m512i T1_0 = unpacklo_epi32(hashkey_blocks_4_0, hashkey_blocks_4_1); __m512i T1_1 = unpackhi_epi32(hashkey_blocks_4_0, hashkey_blocks_4_1); __m512i T1_2 = unpacklo_epi32(hashkey_blocks_4_2, hashkey_blocks_4_3); __m512i T1_3 = unpackhi_epi32(hashkey_blocks_4_2, hashkey_blocks_4_3); hashkey_blocks_4_0 = unpacklo_epi64(T1_0, T1_2); hashkey_blocks_4_1 = unpackhi_epi64(T1_0, T1_2); hashkey_blocks_4_2 = unpacklo_epi64(T1_1, T1_3); hashkey_blocks_4_3 = unpackhi_epi64(T1_1, T1_3); hashkey_blocks_4_0 = shuffle_epi8(hashkey_blocks_4_0, M512(swapWordsOrder)); hashkey_blocks_4_1 = shuffle_epi8(hashkey_blocks_4_1, M512(swapWordsOrder)); hashkey_blocks_4_2 = shuffle_epi8(hashkey_blocks_4_2, M512(swapWordsOrder)); hashkey_blocks_4_3 = shuffle_epi8(hashkey_blocks_4_3, M512(swapWordsOrder)); /* compute hashkeys >> 1 mod poly */ T1_0 = srli_epi64(hashkey_blocks_4_0, 63); T1_1 = srli_epi64(hashkey_blocks_4_1, 63); T1_2 = srli_epi64(hashkey_blocks_4_2, 63); T1_3 = srli_epi64(hashkey_blocks_4_3, 63); hashkey_blocks_4_0 = slli_epi64(hashkey_blocks_4_0, 1); hashkey_blocks_4_1 = slli_epi64(hashkey_blocks_4_1, 1); hashkey_blocks_4_2 = slli_epi64(hashkey_blocks_4_2, 1); hashkey_blocks_4_3 = slli_epi64(hashkey_blocks_4_3, 1); __m512i T2_0 = bsrli_epi128(T1_0, 8); __m512i T2_1 = bsrli_epi128(T1_1, 8); __m512i T2_2 = bsrli_epi128(T1_2, 8); __m512i T2_3 = bsrli_epi128(T1_3, 8); T1_0 = bslli_epi128(T1_0, 8); T1_1 = bslli_epi128(T1_1, 8); T1_2 = bslli_epi128(T1_2, 8); T1_3 = bslli_epi128(T1_3, 8); hashkey_blocks_4_0 = or (hashkey_blocks_4_0, T1_0); hashkey_blocks_4_1 = or (hashkey_blocks_4_1, T1_1); hashkey_blocks_4_2 = or (hashkey_blocks_4_2, T1_2); hashkey_blocks_4_3 = or (hashkey_blocks_4_3, T1_3); T1_0 = shuffle_epi32(T2_0, 0b00100100); T1_1 = shuffle_epi32(T2_1, 0b00100100); T1_2 = shuffle_epi32(T2_2, 0b00100100); T1_3 = shuffle_epi32(T2_3, 0b00100100); __mmask16 cmp_mask_0 = cmpeq_epi32_mask(T1_0, M512(two_one)); __mmask16 cmp_mask_1 = cmpeq_epi32_mask(T1_1, M512(two_one)); __mmask16 cmp_mask_2 = cmpeq_epi32_mask(T1_2, M512(two_one)); __mmask16 cmp_mask_3 = cmpeq_epi32_mask(T1_3, M512(two_one)); T1_0 = mask_set1_epi32(T1_0, cmp_mask_0, 0xFFFFFFFF); T1_1 = mask_set1_epi32(T1_1, cmp_mask_1, 0xFFFFFFFF); T1_2 = mask_set1_epi32(T1_2, cmp_mask_2, 0xFFFFFFFF); T1_3 = mask_set1_epi32(T1_3, cmp_mask_3, 0xFFFFFFFF); T1_0 = and(T1_0, M512(gcm_poly)); T1_1 = and(T1_1, M512(gcm_poly)); T1_2 = and(T1_2, M512(gcm_poly)); T1_3 = and(T1_3, M512(gcm_poly)); hashkey_blocks_4_0 = xor(hashkey_blocks_4_0, T1_0); hashkey_blocks_4_1 = xor(hashkey_blocks_4_1, T1_1); hashkey_blocks_4_2 = xor(hashkey_blocks_4_2, T1_2); hashkey_blocks_4_3 = xor(hashkey_blocks_4_3, T1_3); __m128i *p_hashkey = (__m128i *)SM4_GCM_CONTEXT_HASHKEY(p_context)[0]; storeu(p_hashkey + 0, hashkey_blocks_4_0); storeu(p_hashkey + 4, hashkey_blocks_4_1); storeu(p_hashkey + 8, hashkey_blocks_4_2); storeu(p_hashkey + 12, hashkey_blocks_4_3); /* compute hashkeys ^ 2 >> 1 mod poly ... hashkeys ^ 7 >> 1 mod poly */ __m512i hashkey_pwr_blocks_4_0 = hashkey_blocks_4_0; __m512i hashkey_pwr_blocks_4_1 = hashkey_blocks_4_1; __m512i hashkey_pwr_blocks_4_2 = hashkey_blocks_4_2; __m512i hashkey_pwr_blocks_4_3 = hashkey_blocks_4_3; __m512i *hashkey[] = { &hashkey_blocks_4_0, &hashkey_blocks_4_1, &hashkey_blocks_4_2, &hashkey_blocks_4_3 }; __m512i *hashkey_pwr[] = { &hashkey_pwr_blocks_4_0, &hashkey_pwr_blocks_4_1, &hashkey_pwr_blocks_4_2, &hashkey_pwr_blocks_4_3 }; for (int i = 1; i < 8; i++) { sm4_gcm_ghash_mul_single_block_mb16(hashkey_pwr, hashkey); p_hashkey = (__m128i *)SM4_GCM_CONTEXT_HASHKEY(p_context)[i]; storeu(p_hashkey + 0, hashkey_pwr_blocks_4_0); storeu(p_hashkey + 4, hashkey_pwr_blocks_4_1); storeu(p_hashkey + 8, hashkey_pwr_blocks_4_2); storeu(p_hashkey + 12, hashkey_pwr_blocks_4_3); } } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_update_aad_mb16.c000066400000000000000000000071611470420105600346300ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function process 16 buffers with additional authentication data (AAD) */ __mmask16 sm4_gcm_update_aad_mb16(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { if (SM4_GCM_CONTEXT_STATE(p_context) == sm4_gcm_update_iv) { /* Finalize IVs */ sm4_gcm_finalize_iv_mb16(NULL, mb_mask, p_context); SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_update_aad; } __m128i *ghash = SM4_GCM_CONTEXT_GHASH(p_context); const int8u *loc_pa_aad[SM4_LINES]; int aad_len_rearranged[SM4_LINES]; /* Rearrange pointers and lengths to right layout */ rearrange(loc_pa_aad, pa_aad); rearrange(aad_len_rearranged, aad_len); __m512i loc_aad_len = loadu(aad_len_rearranged); __mmask16 overflow_mask = 0x0000; __m512i max_aad_len = set1_epi64(0x1FFFFFFFFFFFFFFF); /* (2^64 - 1) div 8 */ /* // Update aad len // // AAD length is passed as 32 bit integer // AAD length is used to construct last block for ghahs computation as follow: // 64 bits with AAD length | 64 bits with TXT length // Length of AAD and TXT is stored in context in this form // // Code below transforms 32 bit input integers into the following block: // 64 bits with AAD length | 64 zero bits // and add it to length stored in context // // The whole operation is the following for each buffer: // 64 bits with AAD len in context | 64 bits with TXT len in context // + // 32 zero bits | 32 bits with input AAD len | 64 zero bits */ for (int i = 0; i < 4; i++) { __m512i len_updade = maskz_expandloadu_epi32(0x4444, (void *)(aad_len_rearranged + i * 4)); /* Load aad len to low part of _m512iistry */ __m512i len_context = loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), i)); len_context = add_epi64(len_context, len_updade); storeu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), i), len_context); __mmask8 overflow_mask_part = cmp_epi64_mask(max_aad_len, len_context, _MM_CMPINT_LT); overflow_mask_part = (overflow_mask_part & 0x02) >> 1 | (overflow_mask_part & 0x08) >> 2 | (overflow_mask_part & 0x20) >> 3 | (overflow_mask_part & 0x80) >> 4; overflow_mask = overflow_mask | overflow_mask_part << (i * 4); } /* Process full blocks of AADs */ sm4_gcm_update_ghash_full_blocks_mb16(ghash, loc_pa_aad, &loc_aad_len, SM4_GCM_CONTEXT_HASHKEY(p_context), mb_mask); if (cmp_epi32_mask(loc_aad_len, setzero(), _MM_CMPINT_EQ) != 0xFFFF) { /* Process partial blocks of AADs */ sm4_gcm_update_ghash_partial_blocks_mb16(ghash, loc_pa_aad, &loc_aad_len, SM4_GCM_CONTEXT_HASHKEY(p_context)[0], mb_mask); SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_start_encdec; } return overflow_mask; } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_update_ghash_full_blocks_mb16.c000066400000000000000000000517311470420105600375560ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) __MBX_INLINE void read_first(__m512i *data_blocks[4], const int8u *const pa_input[SM4_LINES], __mmask16 load_mask) { __mmask16 load_mask_0 = load_mask >> 0 * 4; __mmask16 load_mask_1 = load_mask >> 1 * 4; __mmask16 load_mask_2 = load_mask >> 2 * 4; __mmask16 load_mask_3 = load_mask >> 3 * 4; *(data_blocks[0]) = setzero(); *(data_blocks[1]) = setzero(); *(data_blocks[2]) = setzero(); *(data_blocks[3]) = setzero(); /* // Loop with 4 iterations here does not unrolled by some compilers // Unrolled explicitly because insert32x4 require the last parameter to be const */ /* Begin of explicitly unrolled loop */ __m128i input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)pa_input[0 + 4 * 0]); __m128i input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)pa_input[0 + 4 * 1]); __m128i input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)pa_input[0 + 4 * 2]); __m128i input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)pa_input[0 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 0); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 0); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 0); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 0); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)pa_input[1 + 4 * 0]); input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)pa_input[1 + 4 * 1]); input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)pa_input[1 + 4 * 2]); input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)pa_input[1 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 1); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 1); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 1); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 1); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)pa_input[2 + 4 * 0]); input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)pa_input[2 + 4 * 1]); input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)pa_input[2 + 4 * 2]); input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)pa_input[2 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 2); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 2); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 2); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 2); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)pa_input[3 + 4 * 0]); input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)pa_input[3 + 4 * 1]); input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)pa_input[3 + 4 * 2]); input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)pa_input[3 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 3); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 3); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 3); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 3); /* End of explicitly unrolled loop */ } __MBX_INLINE void read_next(__m512i *data_blocks[4], const int8u *const pa_input[SM4_LINES], int block_number, __mmask16 load_mask) { __mmask16 load_mask_0 = load_mask >> 0 * 4; __mmask16 load_mask_1 = load_mask >> 1 * 4; __mmask16 load_mask_2 = load_mask >> 2 * 4; __mmask16 load_mask_3 = load_mask >> 3 * 4; *(data_blocks[0]) = setzero(); *(data_blocks[1]) = setzero(); *(data_blocks[2]) = setzero(); *(data_blocks[3]) = setzero(); /* // Loop with 4 iterations here does not unrolled by some compilers // Unrolled explicitly because insert32x4 require the last parameter to be const */ /* Begin of explicitly unrolled loop */ __m128i input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)(pa_input[0 + 4 * 0] + block_number * 16)); __m128i input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)(pa_input[0 + 4 * 1] + block_number * 16)); __m128i input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)(pa_input[0 + 4 * 2] + block_number * 16)); __m128i input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)(pa_input[0 + 4 * 3] + block_number * 16)); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 0); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 0); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 0); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 0); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)(pa_input[1 + 4 * 0] + block_number * 16)); input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)(pa_input[1 + 4 * 1] + block_number * 16)); input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)(pa_input[1 + 4 * 2] + block_number * 16)); input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)(pa_input[1 + 4 * 3] + block_number * 16)); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 1); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 1); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 1); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 1); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)(pa_input[2 + 4 * 0] + block_number * 16)); input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)(pa_input[2 + 4 * 1] + block_number * 16)); input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)(pa_input[2 + 4 * 2] + block_number * 16)); input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)(pa_input[2 + 4 * 3] + block_number * 16)); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 2); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 2); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 2); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 2); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_0), (void *)(pa_input[3 + 4 * 0] + block_number * 16)); input_block_1 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_1), (void *)(pa_input[3 + 4 * 1] + block_number * 16)); input_block_2 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_2), (void *)(pa_input[3 + 4 * 2] + block_number * 16)); input_block_3 = _mm_maskz_loadu_epi8(0xFFFF * (0x1 & load_mask_3), (void *)(pa_input[3 + 4 * 3] + block_number * 16)); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 3); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 3); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 3); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 3); /* End of explicitly unrolled loop */ } /* // This function updates 16 blocks of ghash by processing full blocks (128 bit blocks) of data // // This code is a port of GCM part of Intel(R) IPSec AES-GCM code // Code modified to work with multi-buffer approach */ void sm4_gcm_update_ghash_full_blocks_mb16(__m128i ghash[SM4_LINES], const int8u *const pa_input[SM4_LINES], __m512i *input_len, __m128i hashkey[SM4_GCM_HASHKEY_PWR_NUM][SM4_LINES], __mmask16 mb_mask) { int stream_len = 0; __mmask16 load_mask = 0; __m512i hashkeys_4_0, hashkeys_4_1, hashkeys_4_2, hashkeys_4_3; __m512i data_blocks_4_0, data_blocks_4_1, data_blocks_4_2, data_blocks_4_3; __m512i *data_blocks[] = { &data_blocks_4_0, &data_blocks_4_1, &data_blocks_4_2, &data_blocks_4_3 }; __m512i T1_0, T2_0, T3_0, T4_0; __m512i T1_1, T2_1, T3_1, T4_1; __m512i T1_2, T2_2, T3_2, T4_2; __m512i T1_3, T2_3, T3_3, T4_3; /* Calculate how many blocks can be processed with delayed reduction */ for (int i = 8; i > 0; i--) { __mmask16 max_stream_len_mask = cmp_epi32_mask((*input_len), set1_epi32(16 * i), _MM_CMPINT_GE); __mmask16 less_16_mask = cmp_epi32_mask((*input_len), set1_epi32(16), _MM_CMPINT_LT); __mmask16 stream_mask = max_stream_len_mask | less_16_mask; load_mask = load_mask * (load_mask != 0) | max_stream_len_mask * (stream_mask == 0xFFFF) * (load_mask == 0) * (less_16_mask != 0xFFFF); stream_len = stream_len + i * (stream_mask == 0xFFFF) * (stream_len == 0) * (less_16_mask != 0xFFFF); } load_mask &= mb_mask; while (load_mask) { /* Process first block using hashkey of highest power */ hashkeys_4_0 = loadu(hashkey[stream_len - 1] + 0); hashkeys_4_1 = loadu(hashkey[stream_len - 1] + 4); hashkeys_4_2 = loadu(hashkey[stream_len - 1] + 8); hashkeys_4_3 = loadu(hashkey[stream_len - 1] + 12); read_first(data_blocks, pa_input, load_mask); data_blocks_4_0 = xor(data_blocks_4_0, loadu(ghash + 0)); data_blocks_4_1 = xor(data_blocks_4_1, loadu(ghash + 4)); data_blocks_4_2 = xor(data_blocks_4_2, loadu(ghash + 8)); data_blocks_4_3 = xor(data_blocks_4_3, loadu(ghash + 12)); T1_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x11); T1_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x11); T1_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x11); T1_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x11); T2_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x00); T2_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x00); T2_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x00); T2_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x00); T3_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x01); T3_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x01); T3_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x01); T3_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x01); T4_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x10); T4_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x10); T4_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x10); T4_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x10); T3_0 = xor(T4_0, T3_0); T3_1 = xor(T4_1, T3_1); T3_2 = xor(T4_2, T3_2); T3_3 = xor(T4_3, T3_3); /* Process the rest of blocks */ for (int i = 1; i < stream_len; i++) { read_next(data_blocks, pa_input, i, load_mask); hashkeys_4_0 = loadu(hashkey[stream_len - i - 1] + 0); hashkeys_4_1 = loadu(hashkey[stream_len - i - 1] + 4); hashkeys_4_2 = loadu(hashkey[stream_len - i - 1] + 8); hashkeys_4_3 = loadu(hashkey[stream_len - i - 1] + 12); T4_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x11); T4_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x11); T4_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x11); T4_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x11); T1_0 = xor(T4_0, T1_0); T1_1 = xor(T4_1, T1_1); T1_2 = xor(T4_2, T1_2); T1_3 = xor(T4_3, T1_3); T4_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x00); T4_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x00); T4_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x00); T4_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x00); T2_0 = xor(T4_0, T2_0); T2_1 = xor(T4_1, T2_1); T2_2 = xor(T4_2, T2_2); T2_3 = xor(T4_3, T2_3); T4_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x01); T4_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x01); T4_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x01); T4_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x01); T3_0 = xor(T4_0, T3_0); T3_1 = xor(T4_1, T3_1); T3_2 = xor(T4_2, T3_2); T3_3 = xor(T4_3, T3_3); T4_0 = clmul(hashkeys_4_0, data_blocks_4_0, 0x10); T4_1 = clmul(hashkeys_4_1, data_blocks_4_1, 0x10); T4_2 = clmul(hashkeys_4_2, data_blocks_4_2, 0x10); T4_3 = clmul(hashkeys_4_3, data_blocks_4_3, 0x10); T3_0 = xor(T4_0, T3_0); T3_1 = xor(T4_1, T3_1); T3_2 = xor(T4_2, T3_2); T3_3 = xor(T4_3, T3_3); } /* Accumulate non-redused result */ T4_0 = bslli_epi128(T3_0, 8); T4_1 = bslli_epi128(T3_1, 8); T4_2 = bslli_epi128(T3_2, 8); T4_3 = bslli_epi128(T3_3, 8); T3_0 = bsrli_epi128(T3_0, 8); T3_1 = bsrli_epi128(T3_1, 8); T3_2 = bsrli_epi128(T3_2, 8); T3_3 = bsrli_epi128(T3_3, 8); T2_0 = xor(T2_0, T4_0); T2_1 = xor(T2_1, T4_1); T2_2 = xor(T2_2, T4_2); T2_3 = xor(T2_3, T4_3); T1_0 = xor(T1_0, T3_0); T1_1 = xor(T1_1, T3_1); T1_2 = xor(T1_2, T3_2); T1_3 = xor(T1_3, T3_3); /* First phase of the reduction */ T3_0 = clmul(M512(gcm_poly2), T2_0, 0x01); T3_1 = clmul(M512(gcm_poly2), T2_1, 0x01); T3_2 = clmul(M512(gcm_poly2), T2_2, 0x01); T3_3 = clmul(M512(gcm_poly2), T2_3, 0x01); T3_0 = bslli_epi128(T3_0, 8); T3_1 = bslli_epi128(T3_1, 8); T3_2 = bslli_epi128(T3_2, 8); T3_3 = bslli_epi128(T3_3, 8); T2_0 = xor(T3_0, T2_0); T2_1 = xor(T3_1, T2_1); T2_2 = xor(T3_2, T2_2); T2_3 = xor(T3_3, T2_3); /* Second phase of the reduction */ T3_0 = clmul(M512(gcm_poly2), T2_0, 0x00); T3_1 = clmul(M512(gcm_poly2), T2_1, 0x00); T3_2 = clmul(M512(gcm_poly2), T2_2, 0x00); T3_3 = clmul(M512(gcm_poly2), T2_3, 0x00); T3_0 = bsrli_epi128(T3_0, 4); T3_1 = bsrli_epi128(T3_1, 4); T3_2 = bsrli_epi128(T3_2, 4); T3_3 = bsrli_epi128(T3_3, 4); T4_0 = clmul(M512(gcm_poly2), T2_0, 0x10); T4_1 = clmul(M512(gcm_poly2), T2_1, 0x10); T4_2 = clmul(M512(gcm_poly2), T2_2, 0x10); T4_3 = clmul(M512(gcm_poly2), T2_3, 0x10); T4_0 = bslli_epi128(T4_0, 4); T4_1 = bslli_epi128(T4_1, 4); T4_2 = bslli_epi128(T4_2, 4); T4_3 = bslli_epi128(T4_3, 4); T4_0 = xor(T4_0, T3_0); T4_1 = xor(T4_1, T3_1); T4_2 = xor(T4_2, T3_2); T4_3 = xor(T4_3, T3_3); T4_0 = xor(T4_0, T1_0); T4_1 = xor(T4_1, T1_1); T4_2 = xor(T4_2, T1_2); T4_3 = xor(T4_3, T1_3); /* Reduction complete, store result */ __mmask8 store_mask_0 = 0x03 * (0x1 & ((load_mask >> 0 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 0 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 0 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 0 * 4) >> 3)); // __mmask8 store_mask_1 = 0x03 * (0x1 & ((load_mask >> 1 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 1 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 1 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 1 * 4) >> 3)); // __mmask8 store_mask_2 = 0x03 * (0x1 & ((load_mask >> 2 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 2 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 2 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 2 * 4) >> 3)); // __mmask8 store_mask_3 = 0x03 * (0x1 & ((load_mask >> 3 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 3 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 3 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 3 * 4) >> 3)); // mask_storeu_epi64(ghash + 0, store_mask_0, T4_0); mask_storeu_epi64(ghash + 4, store_mask_1, T4_1); mask_storeu_epi64(ghash + 8, store_mask_2, T4_2); mask_storeu_epi64(ghash + 12, store_mask_3, T4_3); /* Update pointers and lengths */ (*input_len) = mask_sub_epi32((*input_len), load_mask, (*input_len), set1_epi32(16 * stream_len)); __mmask8 ptr_update_mask_lo = load_mask & 0xFF; __mmask8 ptr_update_mask_hi = (load_mask >> 8) & 0xFF; __m512i loc_pa_input_lo = loadu(pa_input); __m512i loc_pa_input_hi = loadu(pa_input + 8); loc_pa_input_lo = mask_add_epi64(loc_pa_input_lo, ptr_update_mask_lo, loc_pa_input_lo, set1_epi64(16 * stream_len)); loc_pa_input_hi = mask_add_epi64(loc_pa_input_hi, ptr_update_mask_hi, loc_pa_input_hi, set1_epi64(16 * stream_len)); storeu((void *)pa_input, loc_pa_input_lo); storeu((void *)(pa_input + 8), loc_pa_input_hi); stream_len = 0; load_mask = 0; /* Calculate how many blocks can be processed with delayed reduction */ for (int i = 8; i > 0; i--) { __mmask16 max_stream_len_mask = cmp_epi32_mask((*input_len), set1_epi32(16 * i), _MM_CMPINT_GE); __mmask16 less_16_mask = cmp_epi32_mask((*input_len), set1_epi32(16), _MM_CMPINT_LT); __mmask16 stream_mask = max_stream_len_mask | less_16_mask; load_mask = load_mask * (load_mask != 0) | max_stream_len_mask * (stream_mask == 0xFFFF) * (load_mask == 0) * (less_16_mask != 0xFFFF); stream_len = stream_len + i * (stream_mask == 0xFFFF) * (stream_len == 0) * (less_16_mask != 0xFFFF); } load_mask &= mb_mask; } } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_update_ghash_partial_blocks_mb16.c000066400000000000000000000230131470420105600402400ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) __MBX_INLINE void read_first(__m512i *data_blocks[4], const int8u *const pa_input[SM4_LINES], __m512i *input_len, __mmask16 load_mask) { __mmask16 load_mask_0 = load_mask >> 0 * 4; __mmask16 load_mask_1 = load_mask >> 1 * 4; __mmask16 load_mask_2 = load_mask >> 2 * 4; __mmask16 load_mask_3 = load_mask >> 3 * 4; *(data_blocks[0]) = setzero(); *(data_blocks[1]) = setzero(); *(data_blocks[2]) = setzero(); *(data_blocks[3]) = setzero(); /* // Loop with 4 iterations here does not unrolled by some compilers // Unrolled explicitly because insert32x4 require the last parameter to be const */ /* Begin of explicitly unrolled loop */ __m128i input_block_0 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (0 + 4 * 0)))) * (0x1 & load_mask_0), (void *)pa_input[0 + 4 * 0]); __m128i input_block_1 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (0 + 4 * 1)))) * (0x1 & load_mask_1), (void *)pa_input[0 + 4 * 1]); __m128i input_block_2 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (0 + 4 * 2)))) * (0x1 & load_mask_2), (void *)pa_input[0 + 4 * 2]); __m128i input_block_3 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (0 + 4 * 3)))) * (0x1 & load_mask_3), (void *)pa_input[0 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 0); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 0); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 0); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 0); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (1 + 4 * 0)))) * (0x1 & load_mask_0), (void *)pa_input[1 + 4 * 0]); input_block_1 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (1 + 4 * 1)))) * (0x1 & load_mask_1), (void *)pa_input[1 + 4 * 1]); input_block_2 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (1 + 4 * 2)))) * (0x1 & load_mask_2), (void *)pa_input[1 + 4 * 2]); input_block_3 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (1 + 4 * 3)))) * (0x1 & load_mask_3), (void *)pa_input[1 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 1); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 1); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 1); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 1); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (2 + 4 * 0)))) * (0x1 & load_mask_0), (void *)pa_input[2 + 4 * 0]); input_block_1 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (2 + 4 * 1)))) * (0x1 & load_mask_1), (void *)pa_input[2 + 4 * 1]); input_block_2 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (2 + 4 * 2)))) * (0x1 & load_mask_2), (void *)pa_input[2 + 4 * 2]); input_block_3 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (2 + 4 * 3)))) * (0x1 & load_mask_3), (void *)pa_input[2 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 2); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 2); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 2); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 2); load_mask_0 >>= 1; load_mask_1 >>= 1; load_mask_2 >>= 1; load_mask_3 >>= 1; input_block_0 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (3 + 4 * 0)))) * (0x1 & load_mask_0), (void *)pa_input[3 + 4 * 0]); input_block_1 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (3 + 4 * 1)))) * (0x1 & load_mask_1), (void *)pa_input[3 + 4 * 1]); input_block_2 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (3 + 4 * 2)))) * (0x1 & load_mask_2), (void *)pa_input[3 + 4 * 2]); input_block_3 = _mm_maskz_loadu_epi8((0xFFFF >> (16 - *((int *)input_len + (3 + 4 * 3)))) * (0x1 & load_mask_3), (void *)pa_input[3 + 4 * 3]); input_block_0 = _mm_shuffle_epi8(input_block_0, M128(swapEndianness)); input_block_1 = _mm_shuffle_epi8(input_block_1, M128(swapEndianness)); input_block_2 = _mm_shuffle_epi8(input_block_2, M128(swapEndianness)); input_block_3 = _mm_shuffle_epi8(input_block_3, M128(swapEndianness)); *(data_blocks[0]) = insert32x4(*(data_blocks[0]), input_block_0, 3); *(data_blocks[1]) = insert32x4(*(data_blocks[1]), input_block_1, 3); *(data_blocks[2]) = insert32x4(*(data_blocks[2]), input_block_2, 3); *(data_blocks[3]) = insert32x4(*(data_blocks[3]), input_block_3, 3); /* End of explicitly unrolled loop */ } /* // This function updates 16 blocks of ghash by processing partial blocks ( < 128 bit blocks) of data // // This code is a port of GCM part of Intel(R) IPSec AES-GCM code // Code modified to work with multi-buffer approach */ void sm4_gcm_update_ghash_partial_blocks_mb16(__m128i ghash[SM4_LINES], const int8u *const pa_input[SM4_LINES], __m512i *input_len, __m128i hashkey[SM4_LINES], __mmask16 mb_mask) { __m512i hashkeys_4_0, hashkeys_4_1, hashkeys_4_2, hashkeys_4_3; __m512i *hashkeys[] = { &hashkeys_4_0, &hashkeys_4_1, &hashkeys_4_2, &hashkeys_4_3 }; __m512i data_blocks_4_0, data_blocks_4_1, data_blocks_4_2, data_blocks_4_3; __m512i *data_blocks[] = { &data_blocks_4_0, &data_blocks_4_1, &data_blocks_4_2, &data_blocks_4_3 }; __mmask16 load_mask = ~cmp_epi32_mask((*input_len), setzero(), _MM_CMPINT_EQ) & mb_mask; if (load_mask) { hashkeys_4_0 = loadu(hashkey + 0); hashkeys_4_1 = loadu(hashkey + 4); hashkeys_4_2 = loadu(hashkey + 8); hashkeys_4_3 = loadu(hashkey + 12); read_first(data_blocks, pa_input, input_len, load_mask); data_blocks_4_0 = xor(data_blocks_4_0, loadu(ghash + 0)); data_blocks_4_1 = xor(data_blocks_4_1, loadu(ghash + 4)); data_blocks_4_2 = xor(data_blocks_4_2, loadu(ghash + 8)); data_blocks_4_3 = xor(data_blocks_4_3, loadu(ghash + 12)); sm4_gcm_ghash_mul_single_block_mb16(data_blocks, hashkeys); __mmask8 store_mask_0 = 0x03 * (0x1 & ((load_mask >> 0 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 0 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 0 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 0 * 4) >> 3)); // __mmask8 store_mask_1 = 0x03 * (0x1 & ((load_mask >> 1 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 1 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 1 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 1 * 4) >> 3)); // __mmask8 store_mask_2 = 0x03 * (0x1 & ((load_mask >> 2 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 2 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 2 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 2 * 4) >> 3)); // __mmask8 store_mask_3 = 0x03 * (0x1 & ((load_mask >> 3 * 4) >> 0)) | // 0x0C * (0x1 & ((load_mask >> 3 * 4) >> 1)) | // 0x30 * (0x1 & ((load_mask >> 3 * 4) >> 2)) | // 0xC0 * (0x1 & ((load_mask >> 3 * 4) >> 3)); // mask_storeu_epi64(ghash + 0, store_mask_0, data_blocks_4_0); mask_storeu_epi64(ghash + 4, store_mask_1, data_blocks_4_1); mask_storeu_epi64(ghash + 8, store_mask_2, data_blocks_4_2); mask_storeu_epi64(ghash + 12, store_mask_3, data_blocks_4_3); } } #endif /* #if (_MBX>=_MBX_K1) */ sm4_gcm_update_iv_mb16.c000066400000000000000000000066701470420105600345250ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/internal_avx512/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* // This function process 16 buffers with initialization vector (IV) data */ __mmask16 sm4_gcm_update_iv_mb16(const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], __mmask16 mb_mask, SM4_GCM_CTX_mb16 *p_context) { SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_update_iv; __m128i *j0 = SM4_GCM_CONTEXT_J0(p_context); const int8u *loc_pa_iv[SM4_LINES]; int iv_len_rearranged[SM4_LINES]; /* Rearrange pointers and lengths to right layout */ rearrange(loc_pa_iv, pa_iv); rearrange(iv_len_rearranged, iv_len); __m512i loc_iv_len = loadu(iv_len_rearranged); __m512i max_iv_len = set1_epi64(0x1FFFFFFFFFFFFFFF); /* (2^64 - 1) div 8 */ /* // Update full IV length // // IV length is passed as 32 bit integer // IV length is used to construct last block for ghash computation as follow: // 64 zero bits | 64 IV len bits // Length of IV is stored in context in 64 bits // // Code below transforms 32 bit input integers into the following block: // 32 zero bits | 32 IV len bits // and add it to length stored in context // // The whole operation is following for each buffer: // 64 bits with IV len in context // + // 32 zero bits | 32 bits with input IV len // // Last J0 block is constructed in IV finalization */ __m512i full_iv_len = maskz_expandloadu_epi32(0x5555, iv_len_rearranged); full_iv_len = add_epi64(full_iv_len, loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 0))); storeu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 0), full_iv_len); __mmask8 mask_overflow_lo = cmp_epi64_mask(max_iv_len, full_iv_len, _MM_CMPINT_LT); full_iv_len = maskz_expandloadu_epi32(0x5555, iv_len_rearranged + 8); full_iv_len = add_epi64(full_iv_len, loadu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 1))); storeu(BUFFER_REG_NUM(SM4_GCM_CONTEXT_LEN(p_context), 1), full_iv_len); __mmask8 mask_overflow_hi = cmp_epi64_mask(max_iv_len, full_iv_len, _MM_CMPINT_LT); __mmask16 mask_overflow = mask_overflow_hi << 8 | mask_overflow_lo; /* Process full blocks of IVs */ sm4_gcm_update_ghash_full_blocks_mb16(j0, loc_pa_iv, &loc_iv_len, SM4_GCM_CONTEXT_HASHKEY(p_context), mb_mask); if (cmp_epi32_mask(loc_iv_len, setzero(), _MM_CMPINT_EQ) != 0xFFFF) { /* Process partial blocks of IVs and finalize IVs */ sm4_gcm_update_ghash_partial_blocks_mb16(j0, loc_pa_iv, &loc_iv_len, SM4_GCM_CONTEXT_HASHKEY(p_context)[0], mb_mask); sm4_gcm_finalize_iv_mb16(loc_pa_iv, mb_mask, p_context); SM4_GCM_CONTEXT_STATE(p_context) = sm4_gcm_update_aad; } return mask_overflow; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/sm4_gcm_decrypt_mb16_api.c000066400000000000000000000065711470420105600322050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_gcm_decrypt_mb16)(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_in || NULL == in_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_gcm_update_iv != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_update_aad != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_start_encdec != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_dec != SM4_GCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_in[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } if (in_len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } /* We take elements from the SM4_GCM_CONTEXT_LEN(p_context) array by the formula [1+buf_no*2], because of the layout of length data in the context. Refer to sources/ippcp/crypto_mb/include/crypto_mb/sm4_gcm.h file for details. */ int length_data_position = 1+buf_no*2; if( ((int64u)in_len[buf_no] >= MAX_TXT_LEN) || (SM4_GCM_CONTEXT_LEN(p_context)[length_data_position] >= MAX_TXT_LEN - (int64u)in_len[buf_no]) || ((SM4_GCM_CONTEXT_LEN(p_context)[length_data_position] + (int64u)in_len[buf_no]) < (int64u)in_len[buf_no])) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) { __mmask16 overflow_mask = sm4_gcm_decrypt_mb16(pa_out, pa_in, in_len, (__mmask16)mb_mask, p_context); /* Set bad status for buffers with overflowed lengths */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (overflow_mask >> buf_no & 1) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } } } #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/sm4_gcm_encrypt_mb16_api.c000066400000000000000000000065711470420105600322170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_gcm_encrypt_mb16)(int8u *pa_out[SM4_LINES], const int8u *const pa_in[SM4_LINES], const int in_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_in || NULL == in_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_gcm_update_iv != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_update_aad != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_start_encdec != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_enc != SM4_GCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_in[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } if (in_len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } /* We take elements from the SM4_GCM_CONTEXT_LEN(p_context) array by the formula [1+buf_no*2], because of the layout of length data in the context. Refer to sources/ippcp/crypto_mb/include/crypto_mb/sm4_gcm.h file for details. */ int length_data_position = 1+buf_no*2; if( ((int64u)in_len[buf_no] >= MAX_TXT_LEN) || (SM4_GCM_CONTEXT_LEN(p_context)[length_data_position] >= MAX_TXT_LEN - (int64u)in_len[buf_no]) || ((SM4_GCM_CONTEXT_LEN(p_context)[length_data_position] + (int64u)in_len[buf_no]) < (int64u)in_len[buf_no])) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) { __mmask16 overflow_mask = sm4_gcm_encrypt_mb16(pa_out, pa_in, in_len, (__mmask16)mb_mask, p_context); /* Set bad status for buffers with overflowed lengths */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (overflow_mask >> buf_no & 1) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } } } #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/sm4_gcm_get_tag_mb16_api.c000066400000000000000000000045761470420105600321500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_gcm_get_tag_mb16)(int8u *pa_tag[SM4_LINES], const int tag_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_tag || NULL == tag_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_gcm_update_aad != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_start_encdec != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_enc != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_dec != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_get_tag != SM4_GCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero and set bad status for tags of invalid length */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_tag[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } if (tag_len[buf_no] < 0 || tag_len[buf_no] > 16) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_gcm_get_tag_mb16(pa_tag, tag_len, (__mmask16)mb_mask, p_context); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/sm4_gcm_init_mb16_api.c000066400000000000000000000047701470420105600314750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_gcm_init_mb16)(const sm4_key *const pa_key[SM4_LINES], const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; int16u mb_mask_rearranged = 0xFFFF; /* Test input pointers */ if (NULL == pa_key || NULL == pa_iv || NULL == iv_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero and set bad status for IV with zero length */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_key[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } if (pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask_rearranged &= ~(0x1 << rearrangeOrder[buf_no]); } if (iv_len[buf_no] <= 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask_rearranged &= ~(0x1 << rearrangeOrder[buf_no]); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= internal_avx512_sm4_gcm_init_mb16(pa_key, pa_iv, iv_len, p_context, (__mmask16)mb_mask_rearranged, (__mmask16)mb_mask); #else MBX_UNREFERENCED_PARAMETER(mb_mask); MBX_UNREFERENCED_PARAMETER(mb_mask_rearranged); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/sm4_gcm_update_aad_mb16_api.c000066400000000000000000000047611470420105600326210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_gcm_update_aad_mb16)(const int8u *const pa_aad[SM4_LINES], const int aad_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_aad || NULL == aad_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_gcm_update_iv != SM4_GCM_CONTEXT_STATE(p_context) && sm4_gcm_update_aad != SM4_GCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_aad[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } if (aad_len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) { __mmask16 overflow_mask = sm4_gcm_update_aad_mb16(pa_aad, aad_len, (__mmask16)mb_mask, p_context); /* Set bad status for buffers with overflowed lengths */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (overflow_mask >> buf_no & 1) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } } } #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/gcm/sm4_gcm_update_iv_mb16_api.c000066400000000000000000000047311470420105600325070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_gcm_update_iv_mb16)(const int8u *const pa_iv[SM4_LINES], const int iv_len[SM4_LINES], SM4_GCM_CTX_mb16 *p_context) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Check input pointers */ if (NULL == pa_iv || NULL == iv_len || NULL == p_context) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Check state */ if (sm4_gcm_update_iv != SM4_GCM_CONTEXT_STATE(p_context)) { status = MBX_SET_STS16_ALL(MBX_STATUS_MISMATCH_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero and set bad status for IV with zero length */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } if (iv_len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); mb_mask &= ~(0x1 << rearrangeOrder[buf_no]); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) { __mmask16 overflow_mask = sm4_gcm_update_iv_mb16(pa_iv, iv_len, (__mmask16)mb_mask, p_context); /* Set bad status for buffers with overflowed lengths */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (overflow_mask >> buf_no & 1) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); } } } #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/000077500000000000000000000000001470420105600274435ustar00rootroot00000000000000internal_sm4_setkey_mb16.c000066400000000000000000000102251470420105600343400ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) /* FK[] constants */ static const int32u SM4_FK[4] = { 0xA3B1BAC6,0x56AA3350,0x677D9197,0xB27022DC }; /* CK[] constants */ static const int32u SM4_CK[32] = { 0x00070E15,0x1C232A31,0x383F464D,0x545B6269, 0x70777E85,0x8C939AA1,0xA8AFB6BD,0xC4CBD2D9, 0xE0E7EEF5,0xFC030A11,0x181F262D,0x343B4249, 0x50575E65,0x6C737A81,0x888F969D,0xA4ABB2B9, 0xC0C7CED5,0xDCE3EAF1,0xF8FF060D,0x141B2229, 0x30373E45,0x4C535A61,0x686F767D,0x848B9299, 0xA0A7AEB5,0xBCC3CAD1,0xD8DFE6ED,0xF4FB0209, 0x10171E25,0x2C333A41,0x484F565D,0x646B7279 }; #define SM4_ONE_RK(K0, K1, K2, K3, TMP, CK, OUT) { \ /* (Ki+1 ^ Ki+2 ^ Ki+3 ^ CKi) */ \ TMP = _mm512_xor_epi32(_mm512_xor_epi32(_mm512_xor_epi32(K1, K2), K3), _mm512_set1_epi32(CK)); \ /* T'(Ki+1 ^ Ki+2 ^ Ki+3 ^ CKi) */ \ TMP = sBox512(TMP); \ TMP = _mm512_xor_epi32(TMP, Lkey512(TMP)); \ /* Ki+4 = Ki ^ T'(Ki+1 ^ Ki+2 ^ Ki+3 ^ CKi) */ \ K0 = _mm512_xor_epi32(K0, TMP); \ _mm512_storeu_si512((void*)OUT, K0); \ } #define SM4_FOUR_RK(K0, K1, K2, K3, TMP, CK, OUT) { \ SM4_ONE_RK(K0, K1, K2, K3, TMP, CK[0], OUT); \ SM4_ONE_RK(K1, K2, K3, K0, TMP, CK[1], (OUT + 1)); \ SM4_ONE_RK(K2, K3, K0, K1, TMP, CK[2], (OUT + 2)); \ SM4_ONE_RK(K3, K0, K1, K2, TMP, CK[3], (OUT + 3)); \ } mbx_status16 internal_avx512_sm4_set_round_keys_mb16(int32u* key_sched[SM4_ROUNDS], const int8u* pa_inp_key[SM4_LINES], __mmask16 mb_mask) { mbx_status16 status = 0; __m512i rki = _mm512_setzero_si512(); __m512i z0, z1, z2, z3; TRANSPOSE_16x4_I32_EPI32(&z0, &z1, &z2, &z3, pa_inp_key, mb_mask); /* (K0, K1, K2, K3) = (MK0 ^ FK0, MK1 ^ FK1, MK2 ^ FK2, MK3 ^ FK3) */ z0 = _mm512_xor_epi32(z0, _mm512_set1_epi32(SM4_FK[0])); z1 = _mm512_xor_epi32(z1, _mm512_set1_epi32(SM4_FK[1])); z2 = _mm512_xor_epi32(z2, _mm512_set1_epi32(SM4_FK[2])); z3 = _mm512_xor_epi32(z3, _mm512_set1_epi32(SM4_FK[3])); const int32u* pCK = SM4_CK; const __m512i* p_rk = (const __m512i*)key_sched; int itr; for (itr = 0; itr < SM4_ROUNDS; itr += 4, pCK += 4, p_rk += 4) SM4_FOUR_RK(z0, z1, z2, z3, rki, pCK, p_rk); /* clear copies of sensitive data and round keys */ zero_mb8((int64u(*)[8])&z0, 1); zero_mb8((int64u(*)[8])&z1, 1); zero_mb8((int64u(*)[8])&z2, 1); zero_mb8((int64u(*)[8])&z3, 1); zero_mb8((int64u(*)[8])&rki, 1); return status; } mbx_status16 internal_avx512_sm4_xts_set_keys_mb16(mbx_sm4_key_schedule* key_sched1, mbx_sm4_key_schedule* key_sched2, const sm4_xts_key* pa_key[SM4_LINES], __mmask16 mb_mask) { mbx_status16 status = 0; /* Generate round keys for key1 */ internal_avx512_sm4_set_round_keys_mb16((int32u**)key_sched1, (const int8u**)pa_key, mb_mask); const sm4_key* pa_key2[SM4_LINES]; for (int i = 0; i < SM4_LINES; i++) pa_key2[i] = (const sm4_key*)&((int8u*)pa_key[i])[16]; /* Generate round keys for key2 */ internal_avx512_sm4_set_round_keys_mb16((int32u**)key_sched2, (const int8u**)pa_key2, mb_mask); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/sm4_cbc_mb16.c000066400000000000000000000705741470420105600317630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 sm4_cbc_enc_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, const int8u* pa_iv[SM4_LINES]) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Length of the input data in 128-bit chunks - number of SM4 blocks */ __m512i num_blocks; GET_NUM_BLOCKS(num_blocks, len, SM4_BLOCK_SIZE); /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Set p_rk pointer to the beginning of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched; /* Check if we have any data */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); __m512i iv0, iv1, iv2, iv3; __m512i z0, z1, z2, z3, xi; /* Load and transpose iv */ TRANSPOSE_16x4_I32_EPI32(&iv0, &iv1, &iv2, &iv3, pa_iv, tmp_mask); while (tmp_mask) { /* Transpose input data */ TRANSPOSE_16x4_I32_EPI32(&z0, &z1, &z2, &z3, loc_inp, tmp_mask); z0 = _mm512_xor_epi32(z0, iv0); z1 = _mm512_xor_epi32(z1, iv1); z2 = _mm512_xor_epi32(z2, iv2); z3 = _mm512_xor_epi32(z3, iv3); for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) SM4_FOUR_ROUNDS(z0, z1, z2, z3, xi, p_rk, 1); p_rk -= SM4_ROUNDS; iv0 = z3; iv1 = z2; iv2 = z1; iv3 = z0; /* Transpose and store encrypted blocks */ TRANSPOSE_4x16_I32_EPI32(&z0, &z1, &z2, &z3, loc_out, tmp_mask); /* Update pointers to data */ _mm512_storeu_si512((void*)loc_inp, _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512(loc_out, _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512((loc_out + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE))); /* Update number of blocks left and processing mask */ num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(1)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])&z0, 1); zero_mb8((int64u(*)[8])&z1, 1); zero_mb8((int64u(*)[8])&z2, 1); zero_mb8((int64u(*)[8])&z3, 1); zero_mb8((int64u(*)[8])&xi, 1); return status; } /* * Perform SM4-CBC-MAC on 16 buffers and generate their authentication tag. * * @param[out] pa_out Array of pointers to authentication tag * @param[in] pa_in Array of pointers to input buffers * @param[in] len Array of buffer lengths * @param[in] key_sched Array of SM4 scheduled keys * @param[in] mb_mask Bitmask selecting which lines to generate tag * @param[in] pa_iv Array of IV pointers */ void sm4_cbc_mac_kernel_mb16(__m128i pa_out[SM4_LINES], const int8u *const pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, const int8u *pa_iv[SM4_LINES]) { __ALIGN64 const int8u* loc_inp[SM4_LINES]; /* Length of the input data in 128-bit chunks - number of SM4 blocks */ __m512i num_blocks; GET_NUM_BLOCKS(num_blocks, len, SM4_BLOCK_SIZE); /* Local copies of the pointers to input buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); /* Set p_rk pointer to the beginning of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched; /* Check if we have any data */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); __m512i iv0, iv1, iv2, iv3; __m512i z0, z1, z2, z3, xi; __m512i in0, in1, in2, in3; mb_mask = tmp_mask; z0 = _mm512_setzero_si512(); z1 = _mm512_setzero_si512(); z2 = _mm512_setzero_si512(); z3 = _mm512_setzero_si512(); /* Load and transpose iv */ TRANSPOSE_16x4_I32_EPI32(&iv0, &iv1, &iv2, &iv3, pa_iv, tmp_mask); while (tmp_mask) { /* Transpose input data */ TRANSPOSE_16x4_I32_EPI32(&in0, &in1, &in2, &in3, loc_inp, tmp_mask); z0 = _mm512_mask_xor_epi32(z0, tmp_mask, in0, iv0); z1 = _mm512_mask_xor_epi32(z1, tmp_mask, in1, iv1); z2 = _mm512_mask_xor_epi32(z2, tmp_mask, in2, iv2); z3 = _mm512_mask_xor_epi32(z3, tmp_mask, in3, iv3); for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) SM4_FOUR_ROUNDS_MASKED(z0, z1, z2, z3, xi, tmp_mask, p_rk, 1); p_rk -= SM4_ROUNDS; iv0 = z3; iv1 = z2; iv2 = z1; iv3 = z0; /* Update pointers to data */ _mm512_storeu_si512((void*)loc_inp, _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE))); /* Update number of blocks left and processing mask */ num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(1)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); } /* Transpose and store result MAC */ TRANSPOSE_4x16_I32_O128_EPI32(&z0, &z1, &z2, &z3, pa_out, mb_mask); /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])&z0, 1); zero_mb8((int64u(*)[8])&z1, 1); zero_mb8((int64u(*)[8])&z2, 1); zero_mb8((int64u(*)[8])&z3, 1); zero_mb8((int64u(*)[8])&xi, 1); } static void sm4_cbc_dec_incomplete_buff_mb16(const int8u* loc_inp[SM4_LINES], int8u* loc_out[SM4_LINES], __m512i num_blocks, const __m512i* p_rk, __mmask16 mb_mask, __m512i TMP[20], __m512i STORED_CT[16]); mbx_status16 sm4_cbc_dec_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, const int8u* pa_iv[SM4_LINES]) { mbx_status16 status = 0; const int8u* loc_inp[SM4_LINES]; int8u* loc_out[SM4_LINES]; /* Load the constant value */ const __m512i swap_m512i = _mm512_loadu_si512(swapBytes); /* Registers to store ciphertext blocks to be XOR'ed with output of SM4 cipher stage */ __m512i STORED_CT[16]; /* Length of the input data in 128-bit chunks - number of SM4 blocks */ __m512i num_blocks; GET_NUM_BLOCKS(num_blocks, len, SM4_BLOCK_SIZE); /* Don't process empty buffers */ mb_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NE); /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Set p_rk pointer to the end of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched + (SM4_ROUNDS - 1); __ALIGN64 __m512i TMP[20]; __mmask16 loc_mb_mask = mb_mask; /* Store first ciphertext block for next round */ for (int i = 0; i < SM4_LINES; i++) { STORED_CT[i] = _mm512_setzero_epi32(); __m128i data_block = _mm_maskz_loadu_epi32(0x000F * (0x1&loc_mb_mask), loc_inp[i]); STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], data_block, 3); loc_mb_mask >>= 1; } /* Process the first block from each buffer, because it contains IV specific */ /* Load and transpose input data */ TRANSPOSE_16x4_I32_EPI32(&TMP[0], &TMP[1], &TMP[2], &TMP[3], loc_inp, mb_mask); for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk -= 4) SM4_FOUR_ROUNDS(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], p_rk, -1); p_rk += SM4_ROUNDS; /* Transpose and store first encrypted block for each buffer */ TRANSPOSE_AND_XOR_4x16_I32_EPI32(&TMP[0], &TMP[1], &TMP[2], &TMP[3], loc_out, pa_iv, mb_mask); /* Update pointers to data */ _mm512_storeu_si512((void*)loc_inp, _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512(loc_out, _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(SM4_BLOCK_SIZE))); _mm512_storeu_si512((loc_out + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE))); num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(1)); /* Generate the mask to process 4 blocks from each buffer */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(4), _MM_CMPINT_NLT); /* Go to this loop if all 16 buffers contain at least 4 blocks each */ while (tmp_mask == 0xFFFF) { TMP[0] = _mm512_loadu_si512(loc_inp[0]); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[1])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[2])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[3])); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(loc_inp[4])); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[5])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[6])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[7])); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(loc_inp[8])); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[9])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[10])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[11])); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(loc_inp[12])); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[13])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[14])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[15])); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, -1); p_rk += SM4_ROUNDS; for (int i = 0; i < SM4_LINES; i++) STORED_CT[i] = _mm512_alignr_epi64(_mm512_loadu_si512(loc_inp[i]), STORED_CT[i], 6); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[4] = _mm512_xor_si512(TMP[0], STORED_CT[0]); TMP[5] = _mm512_xor_si512(TMP[1], STORED_CT[1]); TMP[6] = _mm512_xor_si512(TMP[2], STORED_CT[2]); TMP[7] = _mm512_xor_si512(TMP[3], STORED_CT[3]); /* Store last block of ciphertext for next iteration */ for (int i = 0; i < 4; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[0]), TMP[4]); _mm512_storeu_si512((__m512i*)(loc_out[1]), TMP[5]); _mm512_storeu_si512((__m512i*)(loc_out[2]), TMP[6]); _mm512_storeu_si512((__m512i*)(loc_out[3]), TMP[7]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[8] = _mm512_xor_si512(TMP[0], STORED_CT[4]); TMP[9] = _mm512_xor_si512(TMP[1], STORED_CT[5]); TMP[10] = _mm512_xor_si512(TMP[2], STORED_CT[6]); TMP[11] = _mm512_xor_si512(TMP[3], STORED_CT[7]); /* Store last block of ciphertext for next iteration */ for (int i = 4; i < 8; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[4]), TMP[8]); _mm512_storeu_si512((__m512i*)(loc_out[5]), TMP[9]); _mm512_storeu_si512((__m512i*)(loc_out[6]), TMP[10]); _mm512_storeu_si512((__m512i*)(loc_out[7]), TMP[11]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[12] = _mm512_xor_si512(TMP[0], STORED_CT[8]); TMP[13] = _mm512_xor_si512(TMP[1], STORED_CT[9]); TMP[14] = _mm512_xor_si512(TMP[2], STORED_CT[10]); TMP[15] = _mm512_xor_si512(TMP[3], STORED_CT[11]); /* Store last block of ciphertext for next iteration */ for (int i = 8; i < 12; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[8]), TMP[12]); _mm512_storeu_si512((__m512i*)(loc_out[9]), TMP[13]); _mm512_storeu_si512((__m512i*)(loc_out[10]), TMP[14]); _mm512_storeu_si512((__m512i*)(loc_out[11]), TMP[15]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[16] = _mm512_xor_si512(TMP[0], STORED_CT[12]); TMP[17] = _mm512_xor_si512(TMP[1], STORED_CT[13]); TMP[18] = _mm512_xor_si512(TMP[2], STORED_CT[14]); TMP[19] = _mm512_xor_si512(TMP[3], STORED_CT[15]); for (int i = 12; i < SM4_LINES; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[12]), TMP[16]); _mm512_storeu_si512((__m512i*)(loc_out[13]), TMP[17]); _mm512_storeu_si512((__m512i*)(loc_out[14]), TMP[18]); _mm512_storeu_si512((__m512i*)(loc_out[15]), TMP[19]); /* Update pointers to data */ _mm512_storeu_si512((void*)loc_inp, _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); _mm512_storeu_si512(loc_out, _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); _mm512_storeu_si512((loc_out + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); /* Update number of blocks left and processing mask */ num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(4)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(4), _MM_CMPINT_NLT); } /* compute incomplete buffer loading */ sm4_cbc_dec_incomplete_buff_mb16(loc_inp, loc_out, num_blocks, p_rk, mb_mask, TMP, STORED_CT); /* clear local copy of sensitive data */ zero_mb8((int64u (*)[8])TMP, sizeof(TMP)/sizeof(TMP[0])); return status; } // Disable optimization for VS19 (>= 19.27) OPTIMIZE_OFF_VS19 static void sm4_cbc_dec_incomplete_buff_mb16(const int8u* loc_inp[SM4_LINES], int8u* loc_out[SM4_LINES], __m512i num_blocks, const __m512i* p_rk, __mmask16 mb_mask, __m512i TMP[20], __m512i STORED_CT[16]){ /* Load the constant value */ const __m512i swap_m512i = _mm512_loadu_si512(swapBytes); /* Check if we have any data */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); while (tmp_mask) { /* Generate the array of masks for data loading. 0 - 4 blocks will be can load from each buffer - depend on the amount of remaining data */ __ALIGN64 __mmask8 block_mask[16]; tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(4), _MM_CMPINT_NLT); /* Will be loaded 4 blocks of data */ M128(block_mask) = _mm_maskz_set1_epi8(tmp_mask, 0xFF); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(3), _MM_CMPINT_EQ); /* Will be loaded 3 blocks of data */ M128(block_mask) = _mm_mask_set1_epi8(M128(block_mask), tmp_mask, 0x3F); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(2), _MM_CMPINT_EQ); /* Will be loaded 2 blocks of data */ M128(block_mask) = _mm_mask_set1_epi8(M128(block_mask), tmp_mask, 0xF); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(1), _MM_CMPINT_EQ); /* Will be loaded 1 block of data */ M128(block_mask) = _mm_mask_set1_epi8(M128(block_mask), tmp_mask, 0x3); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[0], loc_inp[0]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[1], loc_inp[1]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[2], loc_inp[2]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[3], loc_inp[3]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[4], loc_inp[4]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[5], loc_inp[5]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[6], loc_inp[6]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[7], loc_inp[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[8], loc_inp[8]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[9], loc_inp[9]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[10], loc_inp[10]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[11], loc_inp[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[12], loc_inp[12]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[13], loc_inp[13]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[14], loc_inp[14]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[15], loc_inp[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, -1); p_rk += SM4_ROUNDS; for (int i = 0; i < SM4_LINES; i++) STORED_CT[i] = _mm512_alignr_epi64(_mm512_maskz_loadu_epi64(block_mask[i], (__m128i *const)loc_inp[i]), STORED_CT[i], 6); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[4] = _mm512_xor_si512(TMP[0], STORED_CT[0]); TMP[5] = _mm512_xor_si512(TMP[1], STORED_CT[1]); TMP[6] = _mm512_xor_si512(TMP[2], STORED_CT[2]); TMP[7] = _mm512_xor_si512(TMP[3], STORED_CT[3]); /* Store last block of ciphertext for next iteration */ for (int i = 0; i < 4; i++) { __mmask8 write_block_mask = _kshiftri_mask8(block_mask[i], 6); __m128i data_block = _mm_maskz_loadu_epi64(write_block_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_mask_inserti64x2(STORED_CT[i], block_mask[i], STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi64(loc_out[0], block_mask[0], TMP[4]); _mm512_mask_storeu_epi64(loc_out[1], block_mask[1], TMP[5]); _mm512_mask_storeu_epi64(loc_out[2], block_mask[2], TMP[6]); _mm512_mask_storeu_epi64(loc_out[3], block_mask[3], TMP[7]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[8] = _mm512_xor_si512(TMP[0], STORED_CT[4]); TMP[9] = _mm512_xor_si512(TMP[1], STORED_CT[5]); TMP[10] = _mm512_xor_si512(TMP[2], STORED_CT[6]); TMP[11] = _mm512_xor_si512(TMP[3], STORED_CT[7]); /* Store last block of ciphertext for next iteration */ for (int i = 4; i < 8; i++) { __mmask8 write_block_mask = _kshiftri_mask8(block_mask[i], 6); __m128i data_block = _mm_maskz_loadu_epi64(write_block_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_mask_inserti64x2(STORED_CT[i], block_mask[i], STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi64(loc_out[4], block_mask[4], TMP[8]); _mm512_mask_storeu_epi64(loc_out[5], block_mask[5], TMP[9]); _mm512_mask_storeu_epi64(loc_out[6], block_mask[6], TMP[10]); _mm512_mask_storeu_epi64(loc_out[7], block_mask[7], TMP[11]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[12] = _mm512_xor_si512(TMP[0], STORED_CT[8]); TMP[13] = _mm512_xor_si512(TMP[1], STORED_CT[9]); TMP[14] = _mm512_xor_si512(TMP[2], STORED_CT[10]); TMP[15] = _mm512_xor_si512(TMP[3], STORED_CT[11]); /* Store last block of ciphertext for next iteration */ for (int i = 8; i < 12; i++) { __mmask8 write_block_mask = _kshiftri_mask8(block_mask[i], 6); __m128i data_block = _mm_maskz_loadu_epi64(write_block_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_mask_inserti64x2(STORED_CT[i], block_mask[i], STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi64(loc_out[8], block_mask[8], TMP[12]); _mm512_mask_storeu_epi64(loc_out[9], block_mask[9], TMP[13]); _mm512_mask_storeu_epi64(loc_out[10], block_mask[10], TMP[14]); _mm512_mask_storeu_epi64(loc_out[11], block_mask[11], TMP[15]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], swap_m512i); TMP[1] = _mm512_shuffle_epi8(TMP[1], swap_m512i); TMP[2] = _mm512_shuffle_epi8(TMP[2], swap_m512i); TMP[3] = _mm512_shuffle_epi8(TMP[3], swap_m512i); /* xor with IVs */ TMP[16] = _mm512_xor_si512(TMP[0], STORED_CT[12]); TMP[17] = _mm512_xor_si512(TMP[1], STORED_CT[13]); TMP[18] = _mm512_xor_si512(TMP[2], STORED_CT[14]); TMP[19] = _mm512_xor_si512(TMP[3], STORED_CT[15]); /* Store last block of ciphertext for next iteration */ for (int i = 12; i < SM4_LINES; i++) { __mmask8 write_block_mask = _kshiftri_mask8(block_mask[i], 6); __m128i data_block = _mm_maskz_loadu_epi64(write_block_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_mask_inserti64x2(STORED_CT[i], block_mask[i], STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi64(loc_out[12], block_mask[12], TMP[16]); _mm512_mask_storeu_epi64(loc_out[13], block_mask[13], TMP[17]); _mm512_mask_storeu_epi64(loc_out[14], block_mask[14], TMP[18]); _mm512_mask_storeu_epi64(loc_out[15], block_mask[15], TMP[19]); /* Update pointers to data */ _mm512_storeu_si512((void*)loc_inp, _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); _mm512_storeu_si512(loc_out, _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); _mm512_storeu_si512((loc_out + 8), _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE))); /* Update the number of blocks. For some buffers, the value can become zero or a negative number - these buffers will not be processed */ num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(4)); /* Check if we have any data */ tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); } return; } // Enable optimization for VS19 (>= 19.27) OPTIMIZE_ON_VS19 #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/sm4_cfb_mb16.c000066400000000000000000000565121470420105600317620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 sm4_cfb128_enc_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], const int8u* pa_iv[SM4_LINES], __mmask16 mb_mask) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Get the copy of input data lengths in bytes */ __m512i loc_len = _mm512_loadu_si512(len); int* p_loc_len = (int*)&loc_len; /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Set p_rk pointer to the beginning of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched; /* Check if we have any data */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); /* Load and transpose iv */ __m512i iv0, iv1, iv2, iv3; TRANSPOSE_16x4_I32_EPI32(&iv0, &iv1, &iv2, &iv3, (const int8u**)pa_iv, tmp_mask); /* Main loop */ __m512i z0, z1, z2, z3, tmp; while (tmp_mask) { for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) SM4_FOUR_ROUNDS(iv0, iv1, iv2, iv3, tmp, p_rk, 1); p_rk -= SM4_ROUNDS; /* Load and transpose plaintext */ TRANSPOSE_16x4_I32_EPI32(&z0, &z1, &z2, &z3, (const int8u**)loc_inp, tmp_mask); /* Change the order of blocks (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) and xor with plain text */ tmp = iv0; iv0 = _mm512_xor_epi32(iv3, z0); iv3 = _mm512_xor_epi32(tmp, z3); tmp = iv1; iv1 = _mm512_xor_epi32(iv2, z1); iv2 = _mm512_xor_epi32(tmp, z2); /* Transpose and store encrypted blocks by bytes */ TRANSPOSE_4x16_I32_EPI8(iv0, iv1, iv2, iv3, loc_out, p_loc_len, tmp_mask); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])&iv0, 1); zero_mb8((int64u(*)[8])&iv1, 1); zero_mb8((int64u(*)[8])&iv2, 1); zero_mb8((int64u(*)[8])&iv3, 1); zero_mb8((int64u(*)[8])&z0, 1); zero_mb8((int64u(*)[8])&z1, 1); zero_mb8((int64u(*)[8])&z2, 1); zero_mb8((int64u(*)[8])&z3, 1); zero_mb8((int64u(*)[8])&tmp, 1); return status; } static void sm4_cfb128_mask_dec_kernel_mb16(const int8u** loc_inp, int8u** loc_out, __m512i loc_len, const __m512i* p_rk, __mmask16 tmp_mask, __m512i STORED_CT[16]) { __m512i TMP[20]; while (tmp_mask) { /* Generate the array of masks for data loading */ __mmask64 stream_mask[16]; int* p_loc_len = (int*)&loc_len; for (int i = 0; i < SM4_LINES; i++) { UPDATE_STREAM_MASK_64(stream_mask[i], p_loc_len); } for (int i = 0; i < SM4_LINES; i++) STORED_CT[i] = _mm512_alignr_epi64(_mm512_maskz_loadu_epi8(stream_mask[i], (__m128i *const)loc_inp[i]), STORED_CT[i], 6); TMP[0] = _mm512_shuffle_epi8(STORED_CT[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_shuffle_epi8(STORED_CT[4], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[5], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[6], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[7], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_shuffle_epi8(STORED_CT[8], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[9], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[10], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[11], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_shuffle_epi8(STORED_CT[12], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[13], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[14], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[15], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, 1); p_rk -= SM4_ROUNDS; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[4] = _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask[0], loc_inp[0])); TMP[5] = _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask[1], loc_inp[1])); TMP[6] = _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask[2], loc_inp[2])); TMP[7] = _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask[3], loc_inp[3])); /* Store last block of ciphertext for next iteration */ for (int i = 0; i < 4; i++) { __mmask64 write_stream_mask = _kshiftri_mask64(stream_mask[i], 8*6); __m128i data_block = _mm_maskz_loadu_epi8((__mmask16) write_stream_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi8(loc_out[0], stream_mask[0], TMP[4]); _mm512_mask_storeu_epi8(loc_out[1], stream_mask[1], TMP[5]); _mm512_mask_storeu_epi8(loc_out[2], stream_mask[2], TMP[6]); _mm512_mask_storeu_epi8(loc_out[3], stream_mask[3], TMP[7]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[8] = _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask[4], loc_inp[4])); TMP[9] = _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask[5], loc_inp[5])); TMP[10] = _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask[6], loc_inp[6])); TMP[11] = _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask[7], loc_inp[7])); /* Store last block of ciphertext for next iteration */ for (int i = 4; i < 8; i++) { __mmask64 write_stream_mask = _kshiftri_mask64(stream_mask[i], 8*6); __m128i data_block = _mm_maskz_loadu_epi8((__mmask16) write_stream_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi8(loc_out[4], stream_mask[4], TMP[8]); _mm512_mask_storeu_epi8(loc_out[5], stream_mask[5], TMP[9]); _mm512_mask_storeu_epi8(loc_out[6], stream_mask[6], TMP[10]); _mm512_mask_storeu_epi8(loc_out[7], stream_mask[7], TMP[11]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[12] = _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask[8], loc_inp[8])); TMP[13] = _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask[9], loc_inp[9])); TMP[14] = _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask[10], loc_inp[10])); TMP[15] = _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask[11], loc_inp[11])); /* Store last block of ciphertext for next iteration */ for (int i = 8; i < 12; i++) { __mmask64 write_stream_mask = _kshiftri_mask64(stream_mask[i], 8*6); __m128i data_block = _mm_maskz_loadu_epi8((__mmask16) write_stream_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi8(loc_out[8], stream_mask[8], TMP[12]); _mm512_mask_storeu_epi8(loc_out[9], stream_mask[9], TMP[13]); _mm512_mask_storeu_epi8(loc_out[10], stream_mask[10], TMP[14]); _mm512_mask_storeu_epi8(loc_out[11], stream_mask[11], TMP[15]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[16] = _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask[12], loc_inp[12])); TMP[17] = _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask[13], loc_inp[13])); TMP[18] = _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask[14], loc_inp[14])); TMP[19] = _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask[15], loc_inp[15])); /* Store last block of ciphertext for next iteration */ for (int i = 12; i < SM4_LINES; i++) { __mmask64 write_stream_mask = _kshiftri_mask64(stream_mask[i], 8*6); __m128i data_block = _mm_maskz_loadu_epi8((__mmask16) write_stream_mask, (__m128i const*)loc_inp[i] + 3); STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], data_block, 3); } _mm512_mask_storeu_epi8(loc_out[12], stream_mask[12], TMP[16]); _mm512_mask_storeu_epi8(loc_out[13], stream_mask[13], TMP[17]); _mm512_mask_storeu_epi8(loc_out[14], stream_mask[14], TMP[18]); _mm512_mask_storeu_epi8(loc_out[15], stream_mask[15], TMP[19]); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update the number of blocks. For some buffers, the value can become zero or a negative number - these buffers will not be processed */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE)); /* Check if we have any data */ tmp_mask = _mm512_mask_cmp_epi32_mask(tmp_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); } mbx_status16 sm4_cfb128_dec_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], const int8u* pa_iv[SM4_LINES], __mmask16 mb_mask) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Registers to store ciphertext blocks to be XOR'ed with output of SM4 cipher stage */ __m512i STORED_CT[16]; /* Get the copy of input data lengths in bytes */ __m512i loc_len = _mm512_loadu_si512(len); /* Don't process empty buffers */ mb_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Set p_rk pointer to the beginning of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched; __m512i TMP[20]; __mmask16 loc_mb_mask = mb_mask; /* Store first ciphertext block for next round */ for (int i = 0; i < SM4_LINES; i++) { STORED_CT[i] = _mm512_setzero_epi32(); __m128i data_block = _mm_maskz_loadu_epi32(0x000F * (0x1&loc_mb_mask), loc_inp[i]); STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], data_block, 3); loc_mb_mask >>= 1; } /* Process the first block from each buffer, because it contains IV specific */ /* Load and transpose iv */ TRANSPOSE_16x4_I32_EPI32(&TMP[4], &TMP[5], &TMP[6], &TMP[7], (const int8u**)pa_iv, mb_mask); for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) SM4_FOUR_ROUNDS(TMP[4], TMP[5], TMP[6], TMP[7], TMP[8], p_rk, 1); p_rk = (const __m512i*)key_sched; /* Load and transpose ciphertext */ TRANSPOSE_16x4_I32_EPI32(&TMP[9], &TMP[10], &TMP[11], &TMP[12], (const int8u**)loc_inp, mb_mask); /* Change the order of blocks (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) and xor with plain text */ TMP[8] = TMP[4]; TMP[4] = _mm512_xor_epi32(TMP[7], TMP[9]); TMP[7] = _mm512_xor_epi32(TMP[8], TMP[12]); TMP[8] = TMP[5]; TMP[5] = _mm512_xor_epi32(TMP[6], TMP[10]); TMP[6] = _mm512_xor_epi32(TMP[8], TMP[11]); /* Transpose and store encrypted blocks by bytes */ int *p_loc_len = (int*)&loc_len; TRANSPOSE_4x16_I32_EPI8(TMP[4], TMP[5], TMP[6], TMP[7], loc_out, p_loc_len, mb_mask); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE)); loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(SM4_BLOCK_SIZE)); /* Generate the mask to process 4 blocks from each buffer */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); /* Go to this loop if all 16 buffers contain at least 4 blocks each */ while (tmp_mask == 0xFFFF) { for (int i = 0; i < SM4_LINES; i++) STORED_CT[i] = _mm512_alignr_epi64(_mm512_loadu_si512(loc_inp[i]), STORED_CT[i], 6); TMP[0] = _mm512_shuffle_epi8(STORED_CT[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_shuffle_epi8(STORED_CT[4], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[5], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[6], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[7], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_shuffle_epi8(STORED_CT[8], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[9], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[10], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[11], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_shuffle_epi8(STORED_CT[12], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(STORED_CT[13], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(STORED_CT[14], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(STORED_CT[15], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, 1); p_rk -= SM4_ROUNDS; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[4] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[0])); TMP[5] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[1])); TMP[6] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[2])); TMP[7] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[3])); /* Store last block of ciphertext for next iteration */ for (int i = 0; i < 4; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[0]), TMP[4]); _mm512_storeu_si512((__m512i*)(loc_out[1]), TMP[5]); _mm512_storeu_si512((__m512i*)(loc_out[2]), TMP[6]); _mm512_storeu_si512((__m512i*)(loc_out[3]), TMP[7]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[8] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[4])); TMP[9] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[5])); TMP[10] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[6])); TMP[11] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[7])); /* Store last block of ciphertext for next iteration */ for (int i = 4; i < 8; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[4]), TMP[8]); _mm512_storeu_si512((__m512i*)(loc_out[5]), TMP[9]); _mm512_storeu_si512((__m512i*)(loc_out[6]), TMP[10]); _mm512_storeu_si512((__m512i*)(loc_out[7]), TMP[11]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[12] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[8])); TMP[13] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[9])); TMP[14] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[10])); TMP[15] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[11])); /* Store last block of ciphertext for next iteration */ for (int i = 8; i < 12; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[8]), TMP[12]); _mm512_storeu_si512((__m512i*)(loc_out[9]), TMP[13]); _mm512_storeu_si512((__m512i*)(loc_out[10]), TMP[14]); _mm512_storeu_si512((__m512i*)(loc_out[11]), TMP[15]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); /* xor with ciphertext */ TMP[16] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[12])); TMP[17] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[13])); TMP[18] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[14])); TMP[19] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[15])); for (int i = 12; i < SM4_LINES; i++) STORED_CT[i] = _mm512_inserti64x2(STORED_CT[i], _mm_loadu_si128((__m128i const*)loc_inp[i] + 3), 3); _mm512_storeu_si512((__m512i*)(loc_out[12]), TMP[16]); _mm512_storeu_si512((__m512i*)(loc_out[13]), TMP[17]); _mm512_storeu_si512((__m512i*)(loc_out[14]), TMP[18]); _mm512_storeu_si512((__m512i*)(loc_out[15]), TMP[19]); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); } /* Check if we have any data */ tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); if (tmp_mask) sm4_cfb128_mask_dec_kernel_mb16(loc_inp, loc_out, loc_len, p_rk, tmp_mask, STORED_CT); /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/sm4_ctr_mb16.c000066400000000000000000000444371470420105600320230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) static void sm4_ctr128_mask_kernel_mb16(__m512i* CTR, const __m512i* p_rk, __m512i loc_len, const int8u** loc_inp, int8u** loc_out, int8u* inc, __mmask16 tmp_mask, __mmask16 mb_mask) { __m512i TMP[20]; while (tmp_mask) { *CTR = IncBlock512(*CTR, inc); *(CTR + 1) = IncBlock512(*(CTR + 1), inc); *(CTR + 2) = IncBlock512(*(CTR + 2), inc); *(CTR + 3) = IncBlock512(*(CTR + 3), inc); TMP[0] = _mm512_shuffle_epi8(*CTR, M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(*(CTR + 1), M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(*(CTR + 2), M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(*(CTR + 3), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); *(CTR + 4) = IncBlock512(*(CTR + 4), inc); *(CTR + 5) = IncBlock512(*(CTR + 5), inc); *(CTR + 6) = IncBlock512(*(CTR + 6), inc); *(CTR + 7) = IncBlock512(*(CTR + 7), inc); TMP[0] = _mm512_shuffle_epi8(*(CTR + 4), M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(*(CTR + 5), M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(*(CTR + 6), M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(*(CTR + 7), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); *(CTR + 8) = IncBlock512(*(CTR + 8), inc); *(CTR + 9) = IncBlock512(*(CTR + 9), inc); *(CTR + 10) = IncBlock512(*(CTR + 10), inc); *(CTR + 11) = IncBlock512(*(CTR + 11), inc); TMP[0] = _mm512_shuffle_epi8(*(CTR + 8), M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(*(CTR + 9), M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(*(CTR + 10), M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(*(CTR + 11), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); *(CTR + 12) = IncBlock512(*(CTR + 12), inc); *(CTR + 13) = IncBlock512(*(CTR + 13), inc); *(CTR + 14) = IncBlock512(*(CTR + 14), inc); *(CTR + 15) = IncBlock512(*(CTR + 15), inc); TMP[0] = _mm512_shuffle_epi8(*(CTR + 12), M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(*(CTR + 13), M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(*(CTR + 14), M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(*(CTR + 15), M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, 1); p_rk -= SM4_ROUNDS; /* Mask for data loading */ __mmask64 stream_mask; int* p_loc_len = (int*)&loc_len; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[0], stream_mask, _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[0]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[1], stream_mask, _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[1]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[2], stream_mask, _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[2]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[3], stream_mask, _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[3]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[4], stream_mask, _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[4]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[5], stream_mask, _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[5]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[6], stream_mask, _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[6]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[7], stream_mask, _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[7]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[8], stream_mask, _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[8]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[9], stream_mask, _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[9]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[10], stream_mask, _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[10]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[11], stream_mask, _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[11]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[12], stream_mask, _mm512_xor_si512(TMP[0], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[12]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[13], stream_mask, _mm512_xor_si512(TMP[1], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[13]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[14], stream_mask, _mm512_xor_si512(TMP[2], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[14]))); UPDATE_STREAM_MASK_64(stream_mask, p_loc_len) _mm512_mask_storeu_epi8((__m512i*)loc_out[15], stream_mask, _mm512_xor_si512(TMP[3], _mm512_maskz_loadu_epi8(stream_mask, loc_inp[15]))); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(0), _MM_CMPINT_NLE); inc = (int8u*)nextInc; } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); } __MBX_INLINE __m128i IncBlock128(__m128i x, int32u increment) { __m128i t = _mm_add_epi64(x, _mm_maskz_loadu_epi32(1, &increment)); __mmask8 carryMask = _mm_cmplt_epu64_mask(t, x); carryMask = (__mmask8)(carryMask << 1); t = _mm_add_epi64(t, _mm_mask_set1_epi64(_mm_setzero_si128(), carryMask, 1)); return t; } mbx_status16 sm4_ctr128_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, int8u* pa_ctr[SM4_LINES]) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Create the local copy of the input data length in bytes and set it to zero for non-valid buffers */ __m512i loc_len; loc_len = _mm512_loadu_si512(len); loc_len = _mm512_mask_set1_epi32(loc_len, ~mb_mask, 0); /* input blocks loc_blks[] = ceil(loc_len[]/SM4_BLOCK_SIZE) */ int32u loc_blks[SM4_LINES]; _mm512_storeu_si512(loc_blks, _mm512_srli_epi32(_mm512_add_epi32(loc_len, _mm512_set1_epi32(SM4_BLOCK_SIZE - 1)), 4)); /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Pointer p_rk is set to the beginning of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched; /* TMP[] - temporary buffer for processing */ /* CTR - store CTR values */ __m512i TMP[20]; __m512i CTR[SM4_LINES]; __m128i loc_ctr[SM4_LINES]; /* Load CTR value from valid buffers */ mb_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); for (int i = 0; i < SM4_LINES; i++) { if (0x1 & (mb_mask >> i)) { loc_ctr[i] = _mm_loadu_si128((__m128i*)pa_ctr[i]); /* Read string counter and convert to numerical */ loc_ctr[i] = _mm_shuffle_epi8(loc_ctr[i], M128(swapEndianness)); } else loc_ctr[i] = _mm_setzero_si128(); CTR[i] = _mm512_broadcast_i64x2(loc_ctr[i]); } /* Generate the mask to process 4 blocks from each buffer */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); int8u* inc = (int8u*)firstInc; /* Go to this loop if all 16 buffers contain at least 4 blocks each */ while (tmp_mask == 0xFFFF) { CTR[0] = IncBlock512(CTR[0], inc); CTR[1] = IncBlock512(CTR[1], inc); CTR[2] = IncBlock512(CTR[2], inc); CTR[3] = IncBlock512(CTR[3], inc); TMP[0] = _mm512_shuffle_epi8(CTR[0], M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(CTR[1], M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(CTR[2], M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(CTR[3], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); CTR[4] = IncBlock512(CTR[4], inc); CTR[5] = IncBlock512(CTR[5], inc); CTR[6] = IncBlock512(CTR[6], inc); CTR[7] = IncBlock512(CTR[7], inc); TMP[0] = _mm512_shuffle_epi8(CTR[4], M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(CTR[5], M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(CTR[6], M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(CTR[7], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); CTR[8] = IncBlock512(CTR[8], inc); CTR[9] = IncBlock512(CTR[9], inc); CTR[10] = IncBlock512(CTR[10], inc); CTR[11] = IncBlock512(CTR[11], inc); TMP[0] = _mm512_shuffle_epi8(CTR[8], M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(CTR[9], M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(CTR[10], M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(CTR[11], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); CTR[12] = IncBlock512(CTR[12], inc); CTR[13] = IncBlock512(CTR[13], inc); CTR[14] = IncBlock512(CTR[14], inc); CTR[15] = IncBlock512(CTR[15], inc); TMP[0] = _mm512_shuffle_epi8(CTR[12], M512(swapWordsOrder)); TMP[1] = _mm512_shuffle_epi8(CTR[13], M512(swapWordsOrder)); TMP[2] = _mm512_shuffle_epi8(CTR[14], M512(swapWordsOrder)); TMP[3] = _mm512_shuffle_epi8(CTR[15], M512(swapWordsOrder)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, 1); p_rk -= SM4_ROUNDS; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[0], _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[0]))); _mm512_storeu_si512((__m512i*)loc_out[1], _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[1]))); _mm512_storeu_si512((__m512i*)loc_out[2], _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[2]))); _mm512_storeu_si512((__m512i*)loc_out[3], _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[3]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[4], _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[4]))); _mm512_storeu_si512((__m512i*)loc_out[5], _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[5]))); _mm512_storeu_si512((__m512i*)loc_out[6], _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[6]))); _mm512_storeu_si512((__m512i*)loc_out[7], _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[7]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[8], _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[8]))); _mm512_storeu_si512((__m512i*)loc_out[9], _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[9]))); _mm512_storeu_si512((__m512i*)loc_out[10], _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[10]))); _mm512_storeu_si512((__m512i*)loc_out[11], _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[11]))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[12], _mm512_xor_si512(TMP[0], _mm512_loadu_si512(loc_inp[12]))); _mm512_storeu_si512((__m512i*)loc_out[13], _mm512_xor_si512(TMP[1], _mm512_loadu_si512(loc_inp[13]))); _mm512_storeu_si512((__m512i*)loc_out[14], _mm512_xor_si512(TMP[2], _mm512_loadu_si512(loc_inp[14]))); _mm512_storeu_si512((__m512i*)loc_out[15], _mm512_xor_si512(TMP[3], _mm512_loadu_si512(loc_inp[15]))); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); inc = (int8u*)nextInc; } /* Check if we have any data */ tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); if (tmp_mask) sm4_ctr128_mask_kernel_mb16(CTR, p_rk, loc_len, loc_inp, loc_out, inc, tmp_mask, mb_mask); /* update and store counters */ for (int i = 0; i < SM4_LINES; i++) { if (0x1 & (mb_mask >> i)) { loc_ctr[i] = IncBlock128(loc_ctr[i], loc_blks[i]); loc_ctr[i] = _mm_shuffle_epi8(loc_ctr[i], M128(swapEndianness)); _mm_storeu_si128((__m128i*)pa_ctr[i], loc_ctr[i]); loc_ctr[i] = _mm_setzero_si128(); } } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); zero_mb8((int64u(*)[8])CTR, sizeof(CTR) / sizeof(CTR[0])); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/sm4_ecb_mb16.c000066400000000000000000000374721470420105600317650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) static void sm4_ecb_incomplete_buff_mb16(const int8u* loc_inp[SM4_LINES], int8u* loc_out[SM4_LINES], __m512i num_blocks, const __m512i* p_rk, const int sign, __mmask16 mb_mask, __m512i TMP[20]); mbx_status16 sm4_ecb_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, int operation) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Length of the input data in 128-bit chunks - number of SM4 blocks */ __m512i num_blocks; GET_NUM_BLOCKS(num_blocks, len, SM4_BLOCK_SIZE); /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* p_rk set to the beginning or to the end of the key schedule */ const __m512i* p_rk = (operation == SM4_ENC) ? (const __m512i*)key_sched : ((const __m512i*)key_sched + (SM4_ROUNDS - 1)); __ALIGN64 __m512i TMP[20]; /* Generate the mask to process 4 blocks from each buffer */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(4), _MM_CMPINT_NLT); /* Go to this loop if all 16 buffers contain at least 4 blocks each */ while (tmp_mask == 0xFFFF) { TMP[0] = _mm512_loadu_si512(loc_inp[0]); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[1])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[2])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[3])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(loc_inp[4])); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[5])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[6])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[7])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(loc_inp[8])); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[9])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[10])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[11])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(loc_inp[12])); TMP[1] = _mm512_loadu_si512((__m512i*)(loc_inp[13])); TMP[2] = _mm512_loadu_si512((__m512i*)(loc_inp[14])); TMP[3] = _mm512_loadu_si512((__m512i*)(loc_inp[15])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, operation); p_rk -= operation*SM4_ROUNDS; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(loc_out[0]), TMP[0]); _mm512_storeu_si512((__m512i*)(loc_out[1]), TMP[1]); _mm512_storeu_si512((__m512i*)(loc_out[2]), TMP[2]); _mm512_storeu_si512((__m512i*)(loc_out[3]), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(loc_out[4]), TMP[0]); _mm512_storeu_si512((__m512i*)(loc_out[5]), TMP[1]); _mm512_storeu_si512((__m512i*)(loc_out[6]), TMP[2]); _mm512_storeu_si512((__m512i*)(loc_out[7]), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(loc_out[8]), TMP[0]); _mm512_storeu_si512((__m512i*)(loc_out[9]), TMP[1]); _mm512_storeu_si512((__m512i*)(loc_out[10]), TMP[2]); _mm512_storeu_si512((__m512i*)(loc_out[11]), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(loc_out[12]), TMP[0]); _mm512_storeu_si512((__m512i*)(loc_out[13]), TMP[1]); _mm512_storeu_si512((__m512i*)(loc_out[14]), TMP[2]); _mm512_storeu_si512((__m512i*)(loc_out[15]), TMP[3]); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(4)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(4), _MM_CMPINT_NLT); } /* compute incomplete buffer loading */ sm4_ecb_incomplete_buff_mb16(loc_inp, loc_out, num_blocks, p_rk, operation, mb_mask, TMP); /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); return status; } // Disable optimization for VS19 (>= 19.27) OPTIMIZE_OFF_VS19 static void sm4_ecb_incomplete_buff_mb16(const int8u* loc_inp[SM4_LINES], int8u* loc_out[SM4_LINES], __m512i num_blocks, const __m512i* p_rk, const int sign, __mmask16 mb_mask, __m512i TMP[20]){ /* Check if we have any data */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); while (tmp_mask) { /* Generate the array of masks for data loading. 0 - 4 blocks will be can load from each buffer - depend on the amount of remaining data */ __ALIGN64 __mmask8 block_mask[SM4_LINES]; tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(4), _MM_CMPINT_NLT); /* Will be loaded 4 blocks of data */ M128(block_mask) = _mm_maskz_set1_epi8(tmp_mask, 0xFF); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(3), _MM_CMPINT_EQ); /* Will be loaded 3 blocks of data */ M128(block_mask) = _mm_mask_set1_epi8(M128(block_mask), tmp_mask, 0x3F); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(2), _MM_CMPINT_EQ); /* Will be loaded 2 blocks of data */ M128(block_mask) = _mm_mask_set1_epi8(M128(block_mask), tmp_mask, 0xF); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_set1_epi32(1), _MM_CMPINT_EQ); /* Will be loaded 1 block of data */ M128(block_mask) = _mm_mask_set1_epi8(M128(block_mask), tmp_mask, 0x3); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[0], loc_inp[0]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[1], loc_inp[1]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[2], loc_inp[2]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[3], loc_inp[3]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[4], loc_inp[4]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[5], loc_inp[5]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[6], loc_inp[6]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[7], loc_inp[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[8], loc_inp[8]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[9], loc_inp[9]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[10], loc_inp[10]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[11], loc_inp[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_maskz_loadu_epi64(block_mask[12], loc_inp[12]); TMP[1] = _mm512_maskz_loadu_epi64(block_mask[13], loc_inp[13]); TMP[2] = _mm512_maskz_loadu_epi64(block_mask[14], loc_inp[14]); TMP[3] = _mm512_maskz_loadu_epi64(block_mask[15], loc_inp[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, sign); p_rk -= sign*SM4_ROUNDS; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi64(loc_out[0], block_mask[0], TMP[0]); _mm512_mask_storeu_epi64(loc_out[1], block_mask[1], TMP[1]); _mm512_mask_storeu_epi64(loc_out[2], block_mask[2], TMP[2]); _mm512_mask_storeu_epi64(loc_out[3], block_mask[3], TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi64(loc_out[4], block_mask[4], TMP[0]); _mm512_mask_storeu_epi64(loc_out[5], block_mask[5], TMP[1]); _mm512_mask_storeu_epi64(loc_out[6], block_mask[6], TMP[2]); _mm512_mask_storeu_epi64(loc_out[7], block_mask[7], TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi64(loc_out[8], block_mask[8], TMP[0]); _mm512_mask_storeu_epi64(loc_out[9], block_mask[9], TMP[1]); _mm512_mask_storeu_epi64(loc_out[10], block_mask[10], TMP[2]); _mm512_mask_storeu_epi64(loc_out[11], block_mask[11], TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi64(loc_out[12], block_mask[12], TMP[0]); _mm512_mask_storeu_epi64(loc_out[13], block_mask[13], TMP[1]); _mm512_mask_storeu_epi64(loc_out[14], block_mask[14], TMP[2]); _mm512_mask_storeu_epi64(loc_out[15], block_mask[15], TMP[3]); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update the number of blocks. For some buffers, the value can become zero or a negative number - these buffers will not be processed */ num_blocks = _mm512_sub_epi32(num_blocks, _mm512_set1_epi32(4)); /* Check if we have any data */ tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, num_blocks, _mm512_setzero_si512(), _MM_CMPINT_NLE); } return; } // Enable optimization for VS19 (>= 19.27) OPTIMIZE_ON_VS19 #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/sm4_ofb_mb16.c000066400000000000000000000073041470420105600317710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) mbx_status16 sm4_ofb_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched[SM4_ROUNDS], __mmask16 mb_mask, int8u* pa_iv[SM4_LINES]) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Get the copy of input data lengths in bytes */ __m512i loc_len = _mm512_loadu_si512(len); int* p_loc_len = (int*)&loc_len; /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Set p_rk pointer to the beginning of the key schedule */ const __m512i* p_rk = (const __m512i*)key_sched; /* Check if we have any data */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); __m512i iv0, iv1, iv2, iv3; /* Load and transpose iv */ TRANSPOSE_16x4_I32_EPI32(&iv0, &iv1, &iv2, &iv3, (const int8u**)pa_iv, tmp_mask); /* Main loop */ __m512i tmp; while (tmp_mask) { for (int itr = 0; itr < SM4_ROUNDS; itr += 4, p_rk += 4) SM4_FOUR_ROUNDS(iv0, iv1, iv2, iv3, tmp, p_rk, 1); p_rk -= SM4_ROUNDS; /* Change the order of blocks (Y0, Y1, Y2, Y3) = R(X32, X33, X34, X35) = (X35, X34, X33, X32) */ tmp = iv0; iv0 = iv3; iv3 = tmp; tmp = iv1; iv1 = iv2; iv2 = tmp; /* Transpose and store encrypted blocks by bytes */ TRANSPOSE_AND_XOR_4x16_I32_EPI8(iv0, iv1, iv2, iv3, loc_out, loc_inp, p_loc_len, tmp_mask); /* Update pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); } /* Update ofb values */ TRANSPOSE_4x16_I32_EPI32(&iv0, &iv1, &iv2, &iv3, pa_iv, tmp_mask); /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])&iv0, 1); zero_mb8((int64u(*)[8])&iv1, 1); zero_mb8((int64u(*)[8])&iv2, 1); zero_mb8((int64u(*)[8])&iv3, 1); zero_mb8((int64u(*)[8])&tmp, 1); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/internal_avx512/sm4_xts_mb16.c000066400000000000000000000726251470420105600320510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #define FIRST_TWEAKS 1 #define NEXT_TWEAKS 0 /* Generate the next 4 tweaks for a given buffer */ static void generate_next_4_tweaks(const __m512i *PREV_TWEAK, __m512i *NEXT_TWEAK, const __m512i z_shuf_mask, const __m512i z_poly, const int first_tweaks) { __m512i TMP1, TMP2, TMP3, TMP4; const __mmask8 xor_mask = _cvtu32_mask8(0xAA); TMP1 = _mm512_shuffle_epi8(*PREV_TWEAK, z_shuf_mask); /* * In case of the first 4 tweaks, the shifts are variable, * as we are start from tweak 1 in all 128-bit lanes, to construct * tweaks 1, 2, 3 and 4 */ if (first_tweaks) { const __m512i z_dq3210 = _mm512_loadu_si512(xts_const_dq3210); const __m512i z_dq5678 = _mm512_loadu_si512(xts_const_dq5678); TMP2 = _mm512_sllv_epi64(*PREV_TWEAK, z_dq3210); TMP3 = _mm512_srlv_epi64(TMP1, z_dq5678); /* * For following tweaks, the shifts are constant, * as we calculate the next 4 tweaks, parting from tweaks N-4, N-3, N-2 and N, * to construct tweaks N, N+1, N+2, N+3 */ } else { TMP2 = _mm512_slli_epi64(*PREV_TWEAK, 4); TMP3 = _mm512_srli_epi64(TMP1, 4); } TMP4 = _mm512_clmulepi64_epi128(TMP3, z_poly, 0); TMP2 = _mm512_mask_xor_epi64(TMP2, xor_mask, TMP2, TMP3); *NEXT_TWEAK = _mm512_xor_epi32(TMP4, TMP2); } /* Prepare the last tweaks for a given buffer, if it has a partial block */ static void prepare_last_tweaks(__m512i *TWEAK, __m512i *NEXT_TWEAK, const int operation, int num_remain_full_blocks) { /* * For the encryption case, we need to prepare the tweak * for the partial block to be at the beginning of NEXT_TWEAK, * so depending on the number of remaining full blocks, its position * will vary, so the permute mask will be different. In case, there are 4 full blocks, * the newly generated NEXT_TWEAK will be positioned correctly. */ if (operation == SM4_ENC) { if (num_remain_full_blocks == 1) *NEXT_TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_next_tweak_permq_enc[0]), *TWEAK); else if (num_remain_full_blocks == 2) *NEXT_TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_next_tweak_permq_enc[1*8]), *TWEAK); else if (num_remain_full_blocks == 3) *NEXT_TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_next_tweak_permq_enc[2*8]), *TWEAK); /* * For the decryption case, it is a bit more complicated. * In case of a partial block, the last two tweaks (the last tweak of the last full block) * and the tweak of the last block, need to be interchanged. * TWEAK will have the tweaks for the last FULL blocks and *NEXT_TWEAK, * as earlier, will have the tweak for the last partial block. */ } else { if (num_remain_full_blocks == 1) { *NEXT_TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_next_tweak_permq[0]), *TWEAK); *TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_tweak_permq[0]), *TWEAK); } else if (num_remain_full_blocks == 2) { *NEXT_TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_next_tweak_permq[1*8]), *TWEAK); *TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_tweak_permq[1*8]), *TWEAK); } else if (num_remain_full_blocks == 3) { *NEXT_TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_next_tweak_permq[2*8]), *TWEAK); *TWEAK = _mm512_permutexvar_epi64(_mm512_loadu_si512(&xts_tweak_permq[2*8]), *TWEAK); } else if (num_remain_full_blocks == 4) { *NEXT_TWEAK = _mm512_permutex2var_epi64(*NEXT_TWEAK, _mm512_loadu_si512(&xts_next_tweak_permq[3*8]), *TWEAK); *TWEAK = _mm512_permutex2var_epi64(*TWEAK, _mm512_loadu_si512(&xts_tweak_permq[3*8]), *NEXT_TWEAK); } } } static void sm4_xts_mask_kernel_mb16(__m512i* NEXT_TWEAK, const __m512i* p_rk, __m512i loc_len32, const int8u** loc_inp, int8u** loc_out, __mmask16 mb_mask, const int operation) { __m512i TMP[20]; const __m512i z_poly = _mm512_loadu_si512(xts_poly); const __m512i z_partial_block_mask = _mm512_loadu_si512(xts_partial_block_mask); const __m512i z_full_block_mask = _mm512_loadu_si512(xts_full_block_mask); const __m512i z_shuf_mask = _mm512_loadu_si512(xts_shuf_mask); /* Length in bytes of partial blocks for all buffers */ const __m512i partial_len32 = _mm512_and_si512(loc_len32, z_partial_block_mask); /* Length in bytes of full blocks for all buffers */ loc_len32 = _mm512_and_si512(loc_len32, z_full_block_mask); __mmask16 ge_64_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len32, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); __mmask8 ge_64_mask_0_7 = (__mmask8) ge_64_mask; __mmask8 ge_64_mask_8_15 = (__mmask8) _kshiftri_mask16(ge_64_mask, 8); /* Expand 32-bit lengths to 64-bit lengths for 16 buffers */ const __mmask16 expand_mask = _cvtu32_mask16(0x5555); __m512i remain_len64_0_7 = _mm512_maskz_permutexvar_epi32(expand_mask, _mm512_loadu_si512(xts_dw0_7_to_qw_idx), loc_len32); __m512i remain_len64_8_15 = _mm512_maskz_permutexvar_epi32(expand_mask, _mm512_loadu_si512(xts_dw8_15_to_qw_idx), loc_len32); __m512i processed_len64_0_7; __m512i processed_len64_8_15; __m512i TWEAK[SM4_LINES]; __m512i num_remain_full_blocks = _mm512_srli_epi32(loc_len32, 4); /* Calculate bitmask of buffers with at least one full block */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len32, _mm512_set1_epi32(0), _MM_CMPINT_NLE); /* * While there is at least one full block in any of the buffer, keep encrypting * (this loop only handles full blocks, but some buffers will have here * less than 4 full blocks) */ while (tmp_mask) { /* Mask for data loading */ __mmask64 stream_mask[16]; int i; int* p_loc_len32 = (int*)&loc_len32; int* p_num_remain_full_blocks = (int*)&num_remain_full_blocks; int* p_partial_block = (int*)&partial_len32; /* Generate tweaks for next rounds */ for (i = 0; i < SM4_LINES; i++) { TWEAK[i] = NEXT_TWEAK[i]; /* * If there are at least 4 more full blocks to process, * at least one more tweak will be needed (for more full blocks or * for a last partial block) */ if (p_num_remain_full_blocks[i] >= 4) generate_next_4_tweaks(&TWEAK[i], &NEXT_TWEAK[i], z_shuf_mask, z_poly, NEXT_TWEAKS); /* If there is a partial block, tweaks need to be rearranged depending on cipher direction */ if ((p_partial_block[i] > 0) & (p_num_remain_full_blocks[i] <= 4)) prepare_last_tweaks(&TWEAK[i], &NEXT_TWEAK[i], operation, p_num_remain_full_blocks[i]); } num_remain_full_blocks = _mm512_sub_epi32(num_remain_full_blocks, _mm512_set1_epi32(4)); /* * XOR plaintext from each lane with the 4 tweaks and transpose to prepare for encryption. * Since some buffers will have less than 4 full blocks, * a bitmask is required to load less than 64 bytes (stream_mask) */ UPDATE_STREAM_MASK_64(stream_mask[0], p_loc_len32) TMP[0] = _mm512_xor_si512(TWEAK[0], _mm512_maskz_loadu_epi8(stream_mask[0], loc_inp[0])); UPDATE_STREAM_MASK_64(stream_mask[1], p_loc_len32) TMP[1] = _mm512_xor_si512(TWEAK[1], _mm512_maskz_loadu_epi8(stream_mask[1], loc_inp[1])); UPDATE_STREAM_MASK_64(stream_mask[2], p_loc_len32) TMP[2] = _mm512_xor_si512(TWEAK[2], _mm512_maskz_loadu_epi8(stream_mask[2], loc_inp[2])); UPDATE_STREAM_MASK_64(stream_mask[3], p_loc_len32) TMP[3] = _mm512_xor_si512(TWEAK[3], _mm512_maskz_loadu_epi8(stream_mask[3], loc_inp[3])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); UPDATE_STREAM_MASK_64(stream_mask[4], p_loc_len32) TMP[0] = _mm512_xor_si512(TWEAK[4], _mm512_maskz_loadu_epi8(stream_mask[4], loc_inp[4])); UPDATE_STREAM_MASK_64(stream_mask[5], p_loc_len32) TMP[1] = _mm512_xor_si512(TWEAK[5], _mm512_maskz_loadu_epi8(stream_mask[5], loc_inp[5])); UPDATE_STREAM_MASK_64(stream_mask[6], p_loc_len32) TMP[2] = _mm512_xor_si512(TWEAK[6], _mm512_maskz_loadu_epi8(stream_mask[6], loc_inp[6])); UPDATE_STREAM_MASK_64(stream_mask[7], p_loc_len32) TMP[3] = _mm512_xor_si512(TWEAK[7], _mm512_maskz_loadu_epi8(stream_mask[7], loc_inp[7])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); UPDATE_STREAM_MASK_64(stream_mask[8], p_loc_len32) TMP[0] = _mm512_xor_si512(TWEAK[8], _mm512_maskz_loadu_epi8(stream_mask[8], loc_inp[8])); UPDATE_STREAM_MASK_64(stream_mask[9], p_loc_len32) TMP[1] = _mm512_xor_si512(TWEAK[9], _mm512_maskz_loadu_epi8(stream_mask[9], loc_inp[9])); UPDATE_STREAM_MASK_64(stream_mask[10], p_loc_len32) TMP[2] = _mm512_xor_si512(TWEAK[10], _mm512_maskz_loadu_epi8(stream_mask[10], loc_inp[10])); UPDATE_STREAM_MASK_64(stream_mask[11], p_loc_len32) TMP[3] = _mm512_xor_si512(TWEAK[11], _mm512_maskz_loadu_epi8(stream_mask[11], loc_inp[11])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); UPDATE_STREAM_MASK_64(stream_mask[12], p_loc_len32) TMP[0] = _mm512_xor_si512(TWEAK[12], _mm512_maskz_loadu_epi8(stream_mask[12], loc_inp[12])); UPDATE_STREAM_MASK_64(stream_mask[13], p_loc_len32) TMP[1] = _mm512_xor_si512(TWEAK[13], _mm512_maskz_loadu_epi8(stream_mask[13], loc_inp[13])); UPDATE_STREAM_MASK_64(stream_mask[14], p_loc_len32) TMP[2] = _mm512_xor_si512(TWEAK[14], _mm512_maskz_loadu_epi8(stream_mask[14], loc_inp[14])); UPDATE_STREAM_MASK_64(stream_mask[15], p_loc_len32) TMP[3] = _mm512_xor_si512(TWEAK[15], _mm512_maskz_loadu_epi8(stream_mask[15], loc_inp[15])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk, operation); p_rk -= operation*SM4_ROUNDS; /* Transpose, XOR with the tweaks again and write data out */ TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi8((__m512i*)loc_out[0], stream_mask[0], _mm512_xor_si512(TMP[0], TWEAK[0])); _mm512_mask_storeu_epi8((__m512i*)loc_out[1], stream_mask[1], _mm512_xor_si512(TMP[1], TWEAK[1])); _mm512_mask_storeu_epi8((__m512i*)loc_out[2], stream_mask[2], _mm512_xor_si512(TMP[2], TWEAK[2])); _mm512_mask_storeu_epi8((__m512i*)loc_out[3], stream_mask[3], _mm512_xor_si512(TMP[3], TWEAK[3])); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi8((__m512i*)loc_out[4], stream_mask[4], _mm512_xor_si512(TMP[0], TWEAK[4])); _mm512_mask_storeu_epi8((__m512i*)loc_out[5], stream_mask[5], _mm512_xor_si512(TMP[1], TWEAK[5])); _mm512_mask_storeu_epi8((__m512i*)loc_out[6], stream_mask[6], _mm512_xor_si512(TMP[2], TWEAK[6])); _mm512_mask_storeu_epi8((__m512i*)loc_out[7], stream_mask[7], _mm512_xor_si512(TMP[3], TWEAK[7])); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi8((__m512i*)loc_out[8], stream_mask[8], _mm512_xor_si512(TMP[0], TWEAK[8])); _mm512_mask_storeu_epi8((__m512i*)loc_out[9], stream_mask[9], _mm512_xor_si512(TMP[1], TWEAK[9])); _mm512_mask_storeu_epi8((__m512i*)loc_out[10], stream_mask[10], _mm512_xor_si512(TMP[2],TWEAK[10])); _mm512_mask_storeu_epi8((__m512i*)loc_out[11], stream_mask[11], _mm512_xor_si512(TMP[3],TWEAK[11])); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_mask_storeu_epi8((__m512i*)loc_out[12], stream_mask[12], _mm512_xor_si512(TMP[0], TWEAK[12])); _mm512_mask_storeu_epi8((__m512i*)loc_out[13], stream_mask[13], _mm512_xor_si512(TMP[1], TWEAK[13])); _mm512_mask_storeu_epi8((__m512i*)loc_out[14], stream_mask[14], _mm512_xor_si512(TMP[2], TWEAK[14])); _mm512_mask_storeu_epi8((__m512i*)loc_out[15], stream_mask[15], _mm512_xor_si512(TMP[3], TWEAK[15])); /* Update input/output pointers to data */ processed_len64_0_7 = _mm512_mask_blend_epi64(ge_64_mask_0_7, remain_len64_0_7, _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); processed_len64_8_15 = _mm512_mask_blend_epi64(ge_64_mask_8_15, remain_len64_8_15, _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), processed_len64_0_7); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), processed_len64_8_15); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), processed_len64_0_7); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), processed_len64_8_15); /* Update number of blocks left and processing mask */ remain_len64_0_7 = _mm512_sub_epi64(remain_len64_0_7, processed_len64_0_7); remain_len64_8_15 = _mm512_sub_epi64(remain_len64_8_15, processed_len64_8_15); loc_len32 = _mm512_sub_epi32(loc_len32, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len32, _mm512_set1_epi32(0), _MM_CMPINT_NLE); ge_64_mask_0_7 = _mm512_cmp_epi64_mask(remain_len64_0_7, _mm512_set1_epi64(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); ge_64_mask_8_15 = _mm512_cmp_epi64_mask(remain_len64_8_15, _mm512_set1_epi64(4 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); } /* At this stage, all buffers have at most 15 bytes (a partial block) */ /* Calculate bitmask of buffers with a partial block */ tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, partial_len32, _mm512_set1_epi32(0), _MM_CMPINT_NLE); if (tmp_mask) { /* Encrypt last plaintext using bytes from previous ciphertext block */ __mmask64 stream_mask[16]; int* p_loc_len32 = (int*)&partial_len32; __m128i XTMP[16]; int i; for (i = 0; i < SM4_LINES; i++) { /* Get right tweak (position tweak in last 16 bytes of ZMM register) */ UPDATE_STREAM_MASK_64(stream_mask[i], p_loc_len32); /* Read final bytes of input partial block */ XTMP[i] = _mm_maskz_loadu_epi8((__mmask16)stream_mask[i], loc_inp[i]); /* * Read last bytes of previous output block to form 16 bytes * (only if there is a partial block at the end of the buffer) */ if (stream_mask[i] == 0) continue; __m128i XOUT = _mm_maskz_loadu_epi8((__mmask16)~stream_mask[i], (loc_out[i] - 16)); XTMP[i] = _mm_or_si128(XTMP[i], XOUT); /* Initial XOR of new constructed input with tweak */ XTMP[i] = _mm_xor_si128(XTMP[i], _mm512_castsi512_si128(NEXT_TWEAK[i])); } /* Encrypt final block from all lanes, compressing the 16 XMMs into 4 ZMMs */ TRANSPOSE_16x4_I32_XMM_EPI32(&TMP[0], &TMP[1], &TMP[2], &TMP[3], XTMP); for (i = 0; i < SM4_ROUNDS; i += 4, p_rk += 4*operation) SM4_FOUR_ROUNDS(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], p_rk, operation); p_rk -= operation*SM4_ROUNDS; /* Spread out the 4 ZMMs into 16 XMMs */ TRANSPOSE_4x16_I32_XMM_EPI32(&TMP[0], &TMP[1], &TMP[2], &TMP[3], XTMP); for (i = 0; i < SM4_LINES; i++) { /* Skip the buffer if there is no partial block left */ if (stream_mask[i] == 0) continue; /* * Final XOR of output with tweak (it will be always * in the beginning of NEXT_TWEAK, hence the cast) */ XTMP[i] = _mm_xor_si128(XTMP[i], _mm512_castsi512_si128(NEXT_TWEAK[i])); /* Write first bytes of previous output block as the output of the partial block */ __m128i XOUT = _mm_maskz_loadu_epi8((__mmask16)stream_mask[i], (loc_out[i] - 16)); _mm_mask_storeu_epi8(loc_out[i], (__mmask16)stream_mask[i], XOUT); /* Write last output as the output of the previous block */ _mm_storeu_si128((__m128i*)(loc_out[i] - 16), XTMP[i]); } } /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); } mbx_status16 sm4_xts_kernel_mb16(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const int32u* key_sched1[SM4_ROUNDS], const int32u* key_sched2[SM4_ROUNDS], const int8u* pa_tweak[SM4_LINES], __mmask16 mb_mask, const int operation) { mbx_status16 status = 0; __ALIGN64 const int8u* loc_inp[SM4_LINES]; __ALIGN64 int8u* loc_out[SM4_LINES]; /* Create the local copy of the input data length in bytes and set it to zero for non-valid buffers */ __m512i loc_len; loc_len = _mm512_loadu_si512(len); loc_len = _mm512_mask_set1_epi32(loc_len, ~mb_mask, 0); /* Local copies of the pointers to input and output buffers */ _mm512_storeu_si512((void*)loc_inp, _mm512_loadu_si512(pa_inp)); _mm512_storeu_si512((void*)(loc_inp + 8), _mm512_loadu_si512(pa_inp + 8)); _mm512_storeu_si512(loc_out, _mm512_loadu_si512(pa_out)); _mm512_storeu_si512(loc_out + 8, _mm512_loadu_si512(pa_out + 8)); /* Depending on the operation(enc or dec): sign allows to go up and down on the key schedule * p_rk set to the beginning or to the end of the key schedule */ const __m512i* p_rk1 = (operation == SM4_ENC) ? (const __m512i*)key_sched1 : ((const __m512i*)key_sched1 + (SM4_ROUNDS - 1)); /* Pointer p_rk2 is set to the beginning of the key schedule, * as it always encrypts the tweak, regardless the direction */ const __m512i* p_rk2 = (const __m512i*)key_sched2; /* TMP[] - temporary buffer for processing */ /* TWEAK - tweak values for current blocks (4 blocks per buffer) */ /* NEXT_TWEAK - tweak values for following blocks (4 blocks per buffer) */ /* inital_tweak - first tweak for all buffers */ __m512i TMP[20]; __m512i TWEAK[SM4_LINES]; __m512i NEXT_TWEAK[SM4_LINES]; __m128i initial_tweak[SM4_LINES]; int i; const __m512i z_poly = _mm512_loadu_si512(xts_poly); const __m512i z_shuf_mask = _mm512_loadu_si512(xts_shuf_mask); /* Encrypt initial tweak */ TRANSPOSE_16x4_I32_EPI32(&TMP[0], &TMP[1], &TMP[2], &TMP[3], pa_tweak, mb_mask); for (i = 0; i < SM4_ROUNDS; i += 4, p_rk2 += 4) SM4_FOUR_ROUNDS(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], p_rk2, SM4_ENC); p_rk2 -= SM4_ROUNDS; TRANSPOSE_4x16_I32_O128_EPI32(&TMP[0], &TMP[1], &TMP[2], &TMP[3], initial_tweak, mb_mask); /* Load TWEAK value from valid buffers and generate first 4 values */ for (i = 0; i < SM4_LINES; i++) { TWEAK[i] = _mm512_broadcast_i64x2(initial_tweak[i]); generate_next_4_tweaks(&TWEAK[i], &NEXT_TWEAK[i], z_shuf_mask, z_poly, FIRST_TWEAKS); } /* * Generate the mask to process 4 full blocks from each buffer. * Less than 5 full blocks requires sm4_xts_mask_kernel_mb16 to handle it, * as it is the function that can handle partial blocks. */ __mmask16 tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(5 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); /* Go to this loop if all 16 buffers contain at least 5 full blocks each */ while (tmp_mask == 0xFFFF) { for (i = 0; i < SM4_LINES; i++) { TWEAK[i] = NEXT_TWEAK[i]; /* Update tweaks for next rounds */ generate_next_4_tweaks(&TWEAK[i], &NEXT_TWEAK[i], z_shuf_mask, z_poly, NEXT_TWEAKS); } /* XOR plaintext from each lane with the 4 tweaks and transpose to prepare for encryption */ TMP[0] = _mm512_xor_si512(TWEAK[0], _mm512_loadu_si512(loc_inp[0])); TMP[1] = _mm512_xor_si512(TWEAK[1], _mm512_loadu_si512(loc_inp[1])); TMP[2] = _mm512_xor_si512(TWEAK[2], _mm512_loadu_si512(loc_inp[2])); TMP[3] = _mm512_xor_si512(TWEAK[3], _mm512_loadu_si512(loc_inp[3])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_xor_si512(TWEAK[4], _mm512_loadu_si512(loc_inp[4])); TMP[1] = _mm512_xor_si512(TWEAK[5], _mm512_loadu_si512(loc_inp[5])); TMP[2] = _mm512_xor_si512(TWEAK[6], _mm512_loadu_si512(loc_inp[6])); TMP[3] = _mm512_xor_si512(TWEAK[7], _mm512_loadu_si512(loc_inp[7])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_xor_si512(TWEAK[8], _mm512_loadu_si512(loc_inp[8])); TMP[1] = _mm512_xor_si512(TWEAK[9], _mm512_loadu_si512(loc_inp[9])); TMP[2] = _mm512_xor_si512(TWEAK[10], _mm512_loadu_si512(loc_inp[10])); TMP[3] = _mm512_xor_si512(TWEAK[11], _mm512_loadu_si512(loc_inp[11])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_xor_si512(TWEAK[12], _mm512_loadu_si512(loc_inp[12])); TMP[1] = _mm512_xor_si512(TWEAK[13], _mm512_loadu_si512(loc_inp[13])); TMP[2] = _mm512_xor_si512(TWEAK[14], _mm512_loadu_si512(loc_inp[14])); TMP[3] = _mm512_xor_si512(TWEAK[15], _mm512_loadu_si512(loc_inp[15])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); SM4_KERNEL(TMP, p_rk1, operation); p_rk1 -= operation*SM4_ROUNDS; /* Transpose, XOR with the tweaks again and write data out */ TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[0], _mm512_xor_si512(TMP[0], TWEAK[0])); _mm512_storeu_si512((__m512i*)loc_out[1], _mm512_xor_si512(TMP[1], TWEAK[1])); _mm512_storeu_si512((__m512i*)loc_out[2], _mm512_xor_si512(TMP[2], TWEAK[2])); _mm512_storeu_si512((__m512i*)loc_out[3], _mm512_xor_si512(TMP[3], TWEAK[3])); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[4], _mm512_xor_si512(TMP[0], TWEAK[4])); _mm512_storeu_si512((__m512i*)loc_out[5], _mm512_xor_si512(TMP[1], TWEAK[5])); _mm512_storeu_si512((__m512i*)loc_out[6], _mm512_xor_si512(TMP[2], TWEAK[6])); _mm512_storeu_si512((__m512i*)loc_out[7], _mm512_xor_si512(TMP[3], TWEAK[7])); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[8], _mm512_xor_si512(TMP[0], TWEAK[8])); _mm512_storeu_si512((__m512i*)loc_out[9], _mm512_xor_si512(TMP[1], TWEAK[9])); _mm512_storeu_si512((__m512i*)loc_out[10], _mm512_xor_si512(TMP[2], TWEAK[10])); _mm512_storeu_si512((__m512i*)loc_out[11], _mm512_xor_si512(TMP[3], TWEAK[11])); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)loc_out[13], _mm512_xor_si512(TMP[1], TWEAK[13])); _mm512_storeu_si512((__m512i*)loc_out[13], _mm512_xor_si512(TMP[1], TWEAK[13])); _mm512_storeu_si512((__m512i*)loc_out[14], _mm512_xor_si512(TMP[2], TWEAK[14])); _mm512_storeu_si512((__m512i*)loc_out[15], _mm512_xor_si512(TMP[3], TWEAK[15])); /* Update input/output pointers to data */ M512(loc_inp) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_inp + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_inp + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out) = _mm512_add_epi64(_mm512_loadu_si512(loc_out), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); M512(loc_out + 8) = _mm512_add_epi64(_mm512_loadu_si512(loc_out + 8), _mm512_set1_epi64(4 * SM4_BLOCK_SIZE)); /* Update number of blocks left and processing mask */ loc_len = _mm512_sub_epi32(loc_len, _mm512_set1_epi32(4 * SM4_BLOCK_SIZE)); tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_set1_epi32(5 * SM4_BLOCK_SIZE), _MM_CMPINT_NLT); } /* Check if we have any data left on any of the buffers */ tmp_mask = _mm512_mask_cmp_epi32_mask(mb_mask, loc_len, _mm512_setzero_si512(), _MM_CMPINT_NLE); /* * At this point, at least one buffer has less than 5 full blocks, * so dealing with a partial block might be needed. */ if (tmp_mask) sm4_xts_mask_kernel_mb16(NEXT_TWEAK, p_rk1, loc_len, loc_inp, loc_out, mb_mask, operation); /* clear local copy of sensitive data */ zero_mb8((int64u(*)[8])TMP, sizeof(TMP) / sizeof(TMP[0])); zero_mb8((int64u(*)[8])TWEAK, sizeof(TWEAK) / sizeof(TWEAK[0])); return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_cbc_dec_mb16.c000066400000000000000000000045051470420105600276430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_decrypt_cbc_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched || NULL == pa_iv) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length and integrity for each buffer */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if ((len[buf_no] < 0) || (len[buf_no]&(SM4_BLOCK_SIZE-1))) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_cbc_dec_kernel_mb16(pa_out, pa_inp, len, (const int32u**)key_sched, (__mmask16)mb_mask, pa_iv); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_cbc_enc_mb16.c000066400000000000000000000045441470420105600276600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_encrypt_cbc_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched || NULL == pa_iv) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length and integrity for each buffer */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if ((len[buf_no] < 0) || (len[buf_no]&(SM4_BLOCK_SIZE-1))) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_cbc_enc_kernel_mb16(pa_out, pa_inp, len, (const int32u**)key_sched, (__mmask16)mb_mask, pa_iv); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_cfb_dec_mb16.c000066400000000000000000000045601470420105600276470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_decrypt_cfb128_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched || NULL == pa_iv) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length, input pointers and stream integrity*/ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if ((len[buf_no] < 0) || (len[buf_no] & (SM4_BLOCK_SIZE - 1))) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_cfb128_dec_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched, pa_iv, (__mmask16)mb_mask); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_cfb_enc_mb16.c000066400000000000000000000045571470420105600276670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_encrypt_cfb128_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, const int8u* pa_iv[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched || NULL == pa_iv) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length, input pointers and stream integrity*/ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if ((len[buf_no] < 0) || (len[buf_no] & (SM4_BLOCK_SIZE - 1))) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status|= sm4_cfb128_enc_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched, pa_iv, (__mmask16)mb_mask); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_ctr_dec_mb16.c000066400000000000000000000021601470420105600276770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_decrypt_ctr128_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_ctr[SM4_LINES]) { return mbx_sm4_encrypt_ctr128_mb16(pa_out, pa_inp, len, key_sched, pa_ctr); } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_ctr_enc_mb16.c000066400000000000000000000044571470420105600277240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_encrypt_ctr128_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_ctr[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched || NULL == pa_ctr) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length and input pointers */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_ctr[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if (len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ctr128_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched, (__mmask16)mb_mask, pa_ctr); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_ecb_dec_mb16.c000066400000000000000000000044651470420105600276520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_decrypt_ecb_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length and integrity for each buffer */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if ((len[buf_no] < 0) || (len[buf_no]&(SM4_BLOCK_SIZE-1))) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ecb_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched, (__mmask16)mb_mask, SM4_DEC); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_ecb_enc_mb16.c000066400000000000000000000044251470420105600276600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_encrypt_ecb_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length and integrity for each buffer */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if ((len[buf_no] < 0) || (len[buf_no]&(SM4_BLOCK_SIZE-1))) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ecb_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched, (__mmask16)mb_mask, SM4_ENC); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_ofb_dec_mb16.c000066400000000000000000000022201470420105600276520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_decrypt_ofb_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_iv[SM4_LINES]) { return mbx_sm4_encrypt_ofb_mb16(pa_out, pa_inp, len, key_sched, pa_iv); } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_ofb_enc_mb16.c000066400000000000000000000044661470420105600277020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_encrypt_ofb_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched, int8u* pa_iv[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched || NULL == pa_iv) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Test input data length, input pointers and stream integrity*/ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_iv[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if (len[buf_no] < 0) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_ofb_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched, (__mmask16)mb_mask, pa_iv); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_setkey_mb16.c000066400000000000000000000057321470420105600276100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_set_key_mb16)(mbx_sm4_key_schedule* key_sched, const sm4_key* pa_key[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == key_sched || NULL == pa_key) { status = MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* Don't process buffers with input pointers equal to zero */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_key[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= internal_avx512_sm4_set_round_keys_mb16((int32u**)key_sched, (const int8u**)pa_key, (__mmask16)mb_mask); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_xts_set_keys_mb16)(mbx_sm4_key_schedule* key_sched1, mbx_sm4_key_schedule* key_sched2, const sm4_xts_key* pa_key[SM4_LINES]) { int buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == key_sched1 || NULL == key_sched2 || NULL == pa_key) return MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); /* Don't process buffers with input pointers equal to zero */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_key[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= internal_avx512_sm4_xts_set_keys_mb16(key_sched1, key_sched2, pa_key, (__mmask16)mb_mask); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_xts_dec_mb16.c000066400000000000000000000054471470420105600277400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_xts_decrypt_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched1, const mbx_sm4_key_schedule* key_sched2, const int8u* pa_tweak[SM4_LINES]) { unsigned buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched1 || NULL == key_sched2 || NULL == pa_tweak) return MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); /* Test input data length and input pointers */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_tweak[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if (len[buf_no] < SM4_BLOCK_SIZE) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } if (len[buf_no] > SM4_XTS_MAX_SIZE) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_xts_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched1, (const int32u**)key_sched2, pa_tweak, (__mmask16)mb_mask, SM4_DEC); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/sm4/sm4_xts_enc_mb16.c000066400000000000000000000054471470420105600277520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 DLL_PUBLIC mbx_status16 OWNAPI(mbx_sm4_xts_encrypt_mb16)(int8u* pa_out[SM4_LINES], const int8u* pa_inp[SM4_LINES], const int len[SM4_LINES], const mbx_sm4_key_schedule* key_sched1, const mbx_sm4_key_schedule* key_sched2, const int8u* pa_tweak[SM4_LINES]) { unsigned buf_no; mbx_status16 status = 0; int16u mb_mask = 0xFFFF; /* Test input pointers */ if (NULL == pa_out || NULL == pa_inp || NULL == len || NULL == key_sched1 || NULL == key_sched2 || NULL == pa_tweak) return MBX_SET_STS16_ALL(MBX_STATUS_NULL_PARAM_ERR); /* Test input data length and input pointers */ for (buf_no = 0; buf_no < SM4_LINES; buf_no++) { if (pa_out[buf_no] == NULL || pa_inp[buf_no] == NULL || pa_tweak[buf_no] == NULL) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); /* Do not process empty buffers */ mb_mask &= ~(0x1 << buf_no); } if (len[buf_no] < SM4_BLOCK_SIZE) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } if (len[buf_no] > SM4_XTS_MAX_SIZE) { status = MBX_SET_STS16(status, buf_no, MBX_STATUS_MISMATCH_PARAM_ERR); /* Do not process non-valid buffers */ mb_mask &= ~(0x1 << buf_no); } } #if (_MBX>=_MBX_K1) if (MBX_IS_ANY_OK_STS16(status)) status |= sm4_xts_kernel_mb16(pa_out, (const int8u**)pa_inp, (const int*)len, (const int32u**)key_sched1, (const int32u**)key_sched2, pa_tweak, (__mmask16)mb_mask, SM4_ENC); #else MBX_UNREFERENCED_PARAMETER(mb_mask); status = MBX_SET_STS16_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/x25519/000077500000000000000000000000001470420105600246735ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/x25519/ifma_x25519.c000066400000000000000000000061451470420105600267160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 DLL_PUBLIC mbx_status OWNAPI(mbx_x25519_mb8)(int8u* const pa_shared_key[8], const int8u* const pa_private_key[8], const int8u* const pa_public_key[8]) { mbx_status status = 0; int buf_no; /* test input pointers */ if(NULL==pa_shared_key || NULL==pa_private_key || NULL==pa_public_key) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ for(buf_no=0; buf_no<8; buf_no++) { int64u* shared = (int64u*) pa_shared_key[buf_no]; const int64u* own_private = (const int64u*) pa_private_key[buf_no]; const int64u* party_public = (const int64u*) pa_public_key[buf_no]; /* if any of pointer NULL set error status */ if(NULL==shared || NULL==own_private || NULL==party_public) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } } #if (_MBX>=_MBX_K1) status |= internal_avx512_x25519_mb8(pa_shared_key, pa_private_key, pa_public_key); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } DLL_PUBLIC mbx_status OWNAPI(mbx_x25519_public_key_mb8)(int8u* const pa_public_key[8], const int8u* const pa_private_key[8]) { mbx_status status = 0; /* test input pointers */ if(NULL==pa_private_key || NULL==pa_public_key) { status = MBX_SET_STS_ALL(MBX_STATUS_NULL_PARAM_ERR); return status; } /* check pointers and values */ int buf_no; for(buf_no=0; buf_no<8; buf_no++) { const int64u* own_private = (const int64u*) pa_private_key[buf_no]; const int64u* party_public = (const int64u*) pa_public_key[buf_no]; /* if any of pointer NULL set error status */ if(NULL==own_private || NULL==party_public) { status = MBX_SET_STS(status, buf_no, MBX_STATUS_NULL_PARAM_ERR); continue; } } #if (_MBX>=_MBX_K1) status |= internal_avx512_x25519_public_key_mb8(pa_public_key, pa_private_key); #else status = MBX_SET_STS_ALL(MBX_STATUS_UNSUPPORTED_ISA_ERR); #endif /* #if (_MBX>=_MBX_K1) */ return status; } cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/x25519/internal_avx512/000077500000000000000000000000001470420105600276155ustar00rootroot00000000000000internal_ifma_x25519.c000066400000000000000000002051141470420105600334520ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/crypto_mb/src/x25519/internal_avx512/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 #if (_MBX>=_MBX_K1) #ifndef __GNUC__ #pragma warning(disable:4013) #endif #define MASK47 ((1ULL << (255 - 52 * 4)) - 1) __ALIGN64 static const int64u MASK47_[8] = {MASK47, MASK47, MASK47, MASK47, MASK47, MASK47, MASK47, MASK47}; __ALIGN64 static const int64u MOD_2_255_[8] = {19, 19, 19, 19, 19, 19, 19, 19}; __ALIGN64 static const int64u MOD_2_260_[8] = {19*32, 19*32, 19*32, 19*32, 19*32, 19*32, 19*32, 19*32}; #define MASK_47 loadu64(MASK47_) #define MOD_2_255 loadu64(MOD_2_255_) #define MOD_2_260 loadu64(MOD_2_260_) #define ROUND_MUL_SRC(I, J, S_LO, R_LO, S_HI, R_HI) \ R_LO = fma52lo(S_LO, va[I], vb[J]); \ R_HI = fma52hi(S_HI, va[I], vb[J]); #define ROUND_MUL(I, J, M0, M1) \ ROUND_MUL_SRC(I, J, M0, M0, M1, M1) #define REDUCE_ROUND(R0, R1, R5) \ r##R0 = fma52lo(r##R0, r##R5, MOD_2_260); \ r##R1 = fma52lo( fma52hi(r##R1, r##R5, MOD_2_260), \ srli64(r##R5, 52), MOD_2_260); #define NORM(I, J) \ r##J = add64(r##J, srli64(r##I, 52)); \ r##I = and64_const(r##I, (1ULL << 52) - 1); //////////////////////////////////////////////////////////// __MBX_INLINE void ed25519_mul(U64 out[], const U64 a[], const U64 b[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; U64 *va = (U64*) a; U64 *vb = (U64*) b; U64 *vr = (U64*) out; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // Full multiplication ROUND_MUL(4, 4, r8, r9) ROUND_MUL(3, 0, r3, r4) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(2, 1, r3, r4) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(3, 1, r4, r5) ROUND_MUL(4, 0, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(2, 3, r5, r6) ROUND_MUL(3, 2, r5, r6) ROUND_MUL(4, 1, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 2, r6, r7) ROUND_MUL(0, 0, r0, r1) ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(1, 0, r1, r2) ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 0, r2, r3) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(4, 3, r7, r8) r4 = fma52lo(r4, r9, MOD_2_260); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); r4 = and64(r4, MASK_47); REDUCE_ROUND(0, 1, 5); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(3, 4, 8); // Normalize result NORM(0,1) NORM(1,2) NORM(2,3) NORM(3,4) storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } /* SQR c=0 (0,0) c=1 (0,1) c=2 (0,2) (1,1) c=3 (0,3) (1,2) c=4 (0,4) (1,3) (2,2) c=5 (1,4) (2,3) c=6 (2,4) (3,3) c=7 (3,4) c=8 (4,4) */ __MBX_INLINE void ed25519_sqr(U64 out[], const U64 a[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; U64 *va = (U64*) a; U64 *vb = (U64*) a; U64 *vr = (U64*) out; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // Square ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(2, 3, r5, r6) r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); ROUND_MUL(0, 0, r0, r1) ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 4, r8, r9) // Reduce r4 upper bits r4 = fma52lo(r4, r9, MOD_2_260); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); r4 = and64(r4, MASK_47); REDUCE_ROUND(0, 1, 5); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(3, 4, 8); // Normalize result NORM(0,1) NORM(1,2) NORM(2,3) NORM(3,4) storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } #define ROUND_MUL_SRC_A(I, J, S_LO, R_LO, S_HI, R_HI) \ R_LO = fma52lo(S_LO, a##I, a##J); \ R_HI = fma52hi(S_HI, a##I, a##J); #define ROUND_MUL_A(I, J, M0, M1) \ ROUND_MUL_SRC_A(I, J, M0, M0, M1, M1) #define NORM(I, J) \ r##J = add64(r##J, srli64(r##I, 52)); \ r##I = and64_const(r##I, (1ULL << 52) - 1); static void MB_FUNC_NAME(ed25519_sqr_latency_)(U64 out[], const U64 a[], int count) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; U64 a0, a1, a2, a3, a4; U64 r4_1; int i; U64 *vr = (U64*) out; a0 = a[0]; a1 = a[1]; a2 = a[2]; a3 = a[3]; a4 = a[4]; for (i = 0; i < count; ++i) { r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); r4_1 = get_zero64(); // Square ROUND_MUL_A(0, 1, r1, r2) ROUND_MUL_A(0, 2, r2, r3) ROUND_MUL_A(0, 3, r3, r4_1) ROUND_MUL_A(0, 4, r4_1, r5) ROUND_MUL_A(1, 4, r5, r6) ROUND_MUL_A(2, 4, r6, r7) ROUND_MUL_A(3, 4, r7, r8) ROUND_MUL_A(1, 2, r3, r4) ROUND_MUL_A(1, 3, r4, r5) ROUND_MUL_A(2, 3, r5, r6) r1 = add64(r1, r1); r2 = add64(r2, r2); r3 = add64(r3, r3); r4 = add64(r4, r4_1); r4 = add64(r4, r4); r5 = add64(r5, r5); r6 = add64(r6, r6); r7 = add64(r7, r7); r8 = add64(r8, r8); ROUND_MUL_A(0, 0, r0, r1) ROUND_MUL_A(1, 1, r2, r3) ROUND_MUL_A(2, 2, r4, r5) ROUND_MUL_A(3, 3, r6, r7) ROUND_MUL_A(4, 4, r8, r9) r4 = fma52lo(r4, r9, MOD_2_260); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); r4 = and64(r4, MASK_47); REDUCE_ROUND(0, 1, 5); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(3, 4, 8); // Normalize result NORM(0,1) NORM(1,2) NORM(2,3) NORM(3,4) a0 = r0; a1 = r1; a2 = r2; a3 = r3; a4 = r4; } storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } #define MASK_R4 ((1ULL << (255 - 52 * 4)) - 1) static const int64u VMASK_R4[8] = {MASK_R4, MASK_R4, MASK_R4, MASK_R4, MASK_R4, MASK_R4, MASK_R4, MASK_R4}; #define MASK52 ((1ULL << 52) - 1) static const int64u VMASK52[8] = {MASK52, MASK52, MASK52, MASK52, MASK52, MASK52, MASK52, MASK52}; #define REDUCE_ROUND_(R, R0, R1, R5) \ R##R0 = fma52lo(R##R0, R##R5, MOD_2_260); \ R##R1 = fma52lo( fma52hi(R##R1, R##R5, MOD_2_260), \ srli64(R##R5, 52), MOD_2_260); #define NORM_(R, I, J) \ R##J = add64(R##J, srli64(R##I, 52)); \ R##I = and64(R##I, loadu64(VMASK52)); #define REDUCE_R4_N_R9(R) \ R##4 = fma52lo(R##4, R##9, MOD_2_260); \ R##0 = fma52lo(R##0, srli64(R##4, 47), MOD_2_255); \ R##4 = and64(R##4, loadu64(VMASK_R4)); __MBX_INLINE void ed25519_mul_dual(U64 out0[], U64 out1[], const U64 a0[], const U64 b0[], const U64 a1[], const U64 b1[]) { U64 r00, r01, r02, r03, r04, r05, r06, r07, r08, r09; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; U64 *vr0 = (U64*) out0; U64 *vr1 = (U64*) out1; r00 = r01 = r02 = r03 = r04 = r05 = r06 = r07 = r08 = r09 = get_zero64(); r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = get_zero64(); // Full multiplication U64 *va = (U64*) a0; U64 *vb = (U64*) b0; ROUND_MUL(4, 4, r08, r09) ROUND_MUL(3, 0, r03, r04) ROUND_MUL(1, 2, r03, r04) ROUND_MUL(0, 3, r03, r04) ROUND_MUL(2, 1, r03, r04) ROUND_MUL(2, 2, r04, r05) ROUND_MUL(0, 4, r04, r05) ROUND_MUL(1, 3, r04, r05) ROUND_MUL(3, 1, r04, r05) ROUND_MUL(4, 0, r04, r05) ROUND_MUL(1, 4, r05, r06) ROUND_MUL(2, 3, r05, r06) ROUND_MUL(3, 2, r05, r06) ROUND_MUL(4, 1, r05, r06) ROUND_MUL(2, 4, r06, r07) ROUND_MUL(3, 3, r06, r07) ROUND_MUL(4, 2, r06, r07) ROUND_MUL(0, 0, r00, r01) ROUND_MUL(0, 1, r01, r02) ROUND_MUL(0, 2, r02, r03) ROUND_MUL(1, 0, r01, r02) ROUND_MUL(1, 1, r02, r03) ROUND_MUL(2, 0, r02, r03) ROUND_MUL(3, 4, r07, r08) ROUND_MUL(4, 3, r07, r08) va = (U64*) a1; vb = (U64*) b1; ROUND_MUL(4, 4, r18, r19) ROUND_MUL(3, 0, r13, r14) ROUND_MUL(1, 2, r13, r14) ROUND_MUL(0, 3, r13, r14) ROUND_MUL(2, 1, r13, r14) ROUND_MUL(2, 2, r14, r15) ROUND_MUL(0, 4, r14, r15) ROUND_MUL(1, 3, r14, r15) ROUND_MUL(3, 1, r14, r15) ROUND_MUL(4, 0, r14, r15) ROUND_MUL(1, 4, r15, r16) ROUND_MUL(2, 3, r15, r16) ROUND_MUL(3, 2, r15, r16) ROUND_MUL(4, 1, r15, r16) ROUND_MUL(2, 4, r16, r17) ROUND_MUL(3, 3, r16, r17) ROUND_MUL(4, 2, r16, r17) ROUND_MUL(0, 0, r10, r11) ROUND_MUL(0, 1, r11, r12) ROUND_MUL(0, 2, r12, r13) ROUND_MUL(1, 0, r11, r12) ROUND_MUL(1, 1, r12, r13) ROUND_MUL(2, 0, r12, r13) ROUND_MUL(3, 4, r17, r18) ROUND_MUL(4, 3, r17, r18) REDUCE_R4_N_R9(r0) REDUCE_R4_N_R9(r1) REDUCE_ROUND_(r0, 0, 1, 5); REDUCE_ROUND_(r0, 1, 2, 6); REDUCE_ROUND_(r0, 2, 3, 7); REDUCE_ROUND_(r0, 3, 4, 8); REDUCE_ROUND_(r1, 0, 1, 5); REDUCE_ROUND_(r1, 1, 2, 6); REDUCE_ROUND_(r1, 2, 3, 7); REDUCE_ROUND_(r1, 3, 4, 8); // Normalize result NORM_(r0, 0,1) NORM_(r0, 1,2) NORM_(r0, 2,3) NORM_(r0, 3,4) NORM_(r1, 0,1) NORM_(r1, 1,2) NORM_(r1, 2,3) NORM_(r1, 3,4) storeu64(&vr0[0], r00); storeu64(&vr0[1], r01); storeu64(&vr0[2], r02); storeu64(&vr0[3], r03); storeu64(&vr0[4], r04); storeu64(&vr1[0], r10); storeu64(&vr1[1], r11); storeu64(&vr1[2], r12); storeu64(&vr1[3], r13); storeu64(&vr1[4], r14); } __MBX_INLINE void ed25519_sqr_dual(U64 out0[], U64 out1[], const U64 a0[], const U64 a1[]) { U64 r00, r01, r02, r03, r04, r05, r06, r07, r08, r09; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; U64 *vr0 = (U64*) out0; U64 *vr1 = (U64*) out1; r00 = r01 = r02 = r03 = r04 = r05 = r06 = r07 = r08 = r09 = get_zero64(); r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = get_zero64(); // Square U64 *va = (U64*) a0; U64 *vb = (U64*) a0; ROUND_MUL(0, 1, r01, r02) ROUND_MUL(0, 2, r02, r03) ROUND_MUL(0, 3, r03, r04) ROUND_MUL(0, 4, r04, r05) ROUND_MUL(1, 4, r05, r06) ROUND_MUL(2, 4, r06, r07) ROUND_MUL(3, 4, r07, r08) ROUND_MUL(1, 2, r03, r04) ROUND_MUL(1, 3, r04, r05) ROUND_MUL(2, 3, r05, r06) r01 = add64(r01, r01); r02 = add64(r02, r02); r03 = add64(r03, r03); r04 = add64(r04, r04); r05 = add64(r05, r05); r06 = add64(r06, r06); r07 = add64(r07, r07); r08 = add64(r08, r08); ROUND_MUL(0, 0, r00, r01) ROUND_MUL(1, 1, r02, r03) ROUND_MUL(2, 2, r04, r05) ROUND_MUL(3, 3, r06, r07) ROUND_MUL(4, 4, r08, r09) va = (U64*) a1; vb = (U64*) a1; ROUND_MUL(0, 1, r11, r12) ROUND_MUL(0, 2, r12, r13) ROUND_MUL(0, 3, r13, r14) ROUND_MUL(0, 4, r14, r15) ROUND_MUL(1, 4, r15, r16) ROUND_MUL(2, 4, r16, r17) ROUND_MUL(3, 4, r17, r18) ROUND_MUL(1, 2, r13, r14) ROUND_MUL(1, 3, r14, r15) ROUND_MUL(2, 3, r15, r16) r11 = add64(r11, r11); r12 = add64(r12, r12); r13 = add64(r13, r13); r14 = add64(r14, r14); r15 = add64(r15, r15); r16 = add64(r16, r16); r17 = add64(r17, r17); r18 = add64(r18, r18); ROUND_MUL(0, 0, r10, r11) ROUND_MUL(1, 1, r12, r13) ROUND_MUL(2, 2, r14, r15) ROUND_MUL(3, 3, r16, r17) ROUND_MUL(4, 4, r18, r19) REDUCE_R4_N_R9(r0) REDUCE_R4_N_R9(r1) REDUCE_ROUND_(r0, 0, 1, 5); REDUCE_ROUND_(r0, 1, 2, 6); REDUCE_ROUND_(r0, 2, 3, 7); REDUCE_ROUND_(r0, 3, 4, 8); REDUCE_ROUND_(r1, 0, 1, 5); REDUCE_ROUND_(r1, 1, 2, 6); REDUCE_ROUND_(r1, 2, 3, 7); REDUCE_ROUND_(r1, 3, 4, 8); // Normalize result NORM_(r0, 0,1) NORM_(r0, 1,2) NORM_(r0, 2,3) NORM_(r0, 3,4) NORM_(r1, 0,1) NORM_(r1, 1,2) NORM_(r1, 2,3) NORM_(r1, 3,4) storeu64(&vr0[0], r00); storeu64(&vr0[1], r01); storeu64(&vr0[2], r02); storeu64(&vr0[3], r03); storeu64(&vr0[4], r04); storeu64(&vr1[0], r10); storeu64(&vr1[1], r11); storeu64(&vr1[2], r12); storeu64(&vr1[3], r13); storeu64(&vr1[4], r14); } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// __MBX_INLINE void fe52mb8_set(U64 out[], int64u value) { storeu64(&out[0], set64((long long)value)); storeu64(&out[1], get_zero64()); storeu64(&out[2], get_zero64()); storeu64(&out[3], get_zero64()); storeu64(&out[4], get_zero64()); } __MBX_INLINE void fe52mb8_copy(U64 out[], const U64 in[]) { storeu64(&out[0], loadu64(&in[0])); storeu64(&out[1], loadu64(&in[1])); storeu64(&out[2], loadu64(&in[2])); storeu64(&out[3], loadu64(&in[3])); storeu64(&out[4], loadu64(&in[4])); } // Clang warning -Wunused-function #if(0) __MBX_INLINE void fe52mb8_mul_mod25519(U64 vr[], const U64 va[], const U64 vb[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // Full multiplication ROUND_MUL(4, 4, r8, r9) ROUND_MUL(3, 0, r3, r4) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(2, 1, r3, r4) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(3, 1, r4, r5) ROUND_MUL(4, 0, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(2, 3, r5, r6) ROUND_MUL(3, 2, r5, r6) ROUND_MUL(4, 1, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 2, r6, r7) ROUND_MUL(0, 0, r0, r1) ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(1, 0, r1, r2) ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 0, r2, r3) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(4, 3, r7, r8) //REDUCE_ROUND(4, 5, 9); r4 = fma52lo(r4, r9, MOD_2_260); //r9 always contributes 0 to r5 (if input normalized?) REDUCE_ROUND(3, 4, 8); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(0, 1, 5); // Reduce r4 upper bits r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); // Trim top r4 bits that were already reduced above r4 = and64(r4, MASK_47); // Normalize result NORM(0,1) NORM(1,2) NORM(2,3) NORM(3,4) storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } __MBX_INLINE void fe52mb8_sqr_mod25519(U64 out[], const U64 a[]) { fe52mb8_mul_mod25519(out, a, a); } #endif __MBX_INLINE void fe52mb8_mul121666_mod25519(U64 vr[], const U64 va[]) { U64 multiplier = set64(121666); U64 r0, r1, r2, r3, r4, r5; r0 = r1 = r2 = r3 = r4 = r5 = get_zero64(); // multiply r0 = fma52lo(r0, va[0], multiplier); r1 = fma52lo(r1, va[1], multiplier); r2 = fma52lo(r2, va[2], multiplier); r3 = fma52lo(r3, va[3], multiplier); r4 = fma52lo(r4, va[4], multiplier); r5 = fma52hi(r5, va[4], multiplier); r1 = fma52hi(r1, va[0], multiplier); r2 = fma52hi(r2, va[1], multiplier); r3 = fma52hi(r3, va[2], multiplier); r4 = fma52hi(r4, va[3], multiplier); // reduce REDUCE_ROUND(0, 1, 5); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); // trim top r4 bits that were already reduced above r4 = and64(r4, MASK_47); // normalize NORM(0,1) NORM(1,2) NORM(2,3) NORM(3,4) storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } #define PRIME25519_LO 0x000FFFFFFFFFFFED #define PRIME25519_MID 0x000FFFFFFFFFFFFF #define PRIME25519_HI 0x00007FFFFFFFFFFF // __ALIGN64 static const int64u prime25519[5] = { // PRIME25519_LO, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_HI}; __ALIGN64 static const int64u VPRIME25519_LO[8] = { PRIME25519_LO, PRIME25519_LO, PRIME25519_LO, PRIME25519_LO, PRIME25519_LO, PRIME25519_LO, PRIME25519_LO, PRIME25519_LO }; __ALIGN64 static const int64u VPRIME25519_MID[8] = { PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID, PRIME25519_MID }; __ALIGN64 static const int64u VPRIME25519_HI[8] = { PRIME25519_HI, PRIME25519_HI, PRIME25519_HI, PRIME25519_HI, PRIME25519_HI, PRIME25519_HI, PRIME25519_HI, PRIME25519_HI }; __MBX_INLINE U64 cmov_U64(U64 a, U64 b, __mb_mask kmask) { return mask_mov64 (a, kmask, b); } #define NORM_ASHIFTR(R, I, J) \ R##J = add64(R##J, srai64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); #define NORM_LSHIFTR(R, I, J) \ R##J = add64(R##J, srli64(R##I, DIGIT_SIZE)); \ R##I = and64(R##I, loadu64(VMASK52)); __MBX_INLINE void fe52mb8_add_mod25519(U64 vr[], const U64 va[], const U64 vb[]) { /* r = a+b */ U64 r0 = add64(va[0], vb[0]); U64 r1 = add64(va[1], vb[1]); U64 r2 = add64(va[2], vb[2]); U64 r3 = add64(va[3], vb[3]); U64 r4 = add64(va[4], vb[4]); /* t = r-modulus (2^255-19) */ U64 t0 = sub64(r0, loadu64(VPRIME25519_LO )); U64 t1 = sub64(r1, loadu64(VPRIME25519_MID)); U64 t2 = sub64(r2, loadu64(VPRIME25519_MID)); U64 t3 = sub64(r3, loadu64(VPRIME25519_MID)); U64 t4 = sub64(r4, loadu64(VPRIME25519_HI )); /* normalize r0, r1, r2, r3, r4 */ NORM_LSHIFTR(r, 0,1) NORM_LSHIFTR(r, 1,2) NORM_LSHIFTR(r, 2,3) NORM_LSHIFTR(r, 3,4) /* normalize t0, t1, t2, t3, t4 */ NORM_ASHIFTR(t, 0,1) NORM_ASHIFTR(t, 1,2) NORM_ASHIFTR(t, 2,3) NORM_ASHIFTR(t, 3,4) /* condition mask t4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(t4, get_zero64(), _MM_CMPINT_LT); storeu64(&vr[0], cmov_U64(t0, r0, cmask)); storeu64(&vr[1], cmov_U64(t1, r1, cmask)); storeu64(&vr[2], cmov_U64(t2, r2, cmask)); storeu64(&vr[3], cmov_U64(t3, r3, cmask)); storeu64(&vr[4], cmov_U64(t4, r4, cmask)); } __MBX_INLINE void fe52mb8_sub_mod25519(U64 vr[], const U64 va[], const U64 vb[]) { /* r = a-b */ U64 r0 = sub64(va[0], vb[0]); U64 r1 = sub64(va[1], vb[1]); U64 r2 = sub64(va[2], vb[2]); U64 r3 = sub64(va[3], vb[3]); U64 r4 = sub64(va[4], vb[4]); /* t = r+modulus (2^255-19) */ U64 t0 = add64(r0, loadu64(VPRIME25519_LO )); U64 t1 = add64(r1, loadu64(VPRIME25519_MID)); U64 t2 = add64(r2, loadu64(VPRIME25519_MID)); U64 t3 = add64(r3, loadu64(VPRIME25519_MID)); U64 t4 = add64(r4, loadu64(VPRIME25519_HI )); /* normalize r0, r1, r2, r3, r4 */ NORM_ASHIFTR(r, 0,1) NORM_ASHIFTR(r, 1,2) NORM_ASHIFTR(r, 2,3) NORM_ASHIFTR(r, 3,4) /* normalize t0, t1, t2, t3, t4 */ NORM_ASHIFTR(t, 0,1) NORM_ASHIFTR(t, 1,2) NORM_ASHIFTR(t, 2,3) NORM_ASHIFTR(t, 3,4) /* condition mask r4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(r4, get_zero64(), _MM_CMPINT_LT); storeu64(&vr[0], cmov_U64(r0, t0, cmask)); storeu64(&vr[1], cmov_U64(r1, t1, cmask)); storeu64(&vr[2], cmov_U64(r2, t2, cmask)); storeu64(&vr[3], cmov_U64(r3, t3, cmask)); storeu64(&vr[4], cmov_U64(r4, t4, cmask)); } __MBX_INLINE void fe52mb8_red_p25519(U64 vr[], const U64 va[]) { /* r = a-p */ U64 r0 = sub64(va[0], loadu64(VPRIME25519_LO)); U64 r1 = sub64(va[1], loadu64(VPRIME25519_MID)); U64 r2 = sub64(va[2], loadu64(VPRIME25519_MID)); U64 r3 = sub64(va[3], loadu64(VPRIME25519_MID)); U64 r4 = sub64(va[4], loadu64(VPRIME25519_HI)); /* normalize r0, r1, r2, r3, r4 */ NORM_ASHIFTR(r, 0, 1) NORM_ASHIFTR(r, 1, 2) NORM_ASHIFTR(r, 2, 3) NORM_ASHIFTR(r, 3, 4) /* condition mask r4<0? (-1) : 0 */ __mb_mask cmask = cmp64_mask(r4, get_zero64(), _MM_CMPINT_LT); storeu64(&vr[0], cmov_U64(r0, va[0], cmask)); storeu64(&vr[1], cmov_U64(r1, va[1], cmask)); storeu64(&vr[2], cmov_U64(r2, va[2], cmask)); storeu64(&vr[3], cmov_U64(r3, va[3], cmask)); storeu64(&vr[4], cmov_U64(r4, va[4], cmask)); } // #define USE_DUAL_MUL_SQR // #define fe52_mul fe52mb8_mul_mod25519 // #define fe52_sqr fe52mb8_sqr_mod25519 #define fe52_mul ed25519_mul #define fe52_sqr ed25519_sqr #define fe52_add fe52mb8_add_mod25519 #define fe52_sub fe52mb8_sub_mod25519 #define fe52_mul121666 fe52mb8_mul121666_mod25519 #define fe52_sqr_power MB_FUNC_NAME(ed25519_sqr_latency_) /* Compute 1/z = z^(2^255 - 19 - 2) considering the exponent as 2^255 - 21 = (2^5) * (2^250 - 1) + 11. */ __MBX_INLINE void fe52mb8_inv_mod25519(U64 out[], const U64 z[]) { __ALIGN64 U64 t0[5]; __ALIGN64 U64 t1[5]; __ALIGN64 U64 t2[5]; __ALIGN64 U64 t3[5]; /* t0 = z ** 2 */ fe52_sqr(t0, z); /* t1 = t0 ** (2 ** 2) = z ** 8 */ fe52_sqr(t1, t0); fe52_sqr(t1, t1); /* t1 = z * t1 = z ** 9 */ fe52_mul(t1, z, t1); /* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */ fe52_mul(t0, t0, t1); /* t2 = t0 ** 2 = z ** 22 */ fe52_sqr(t2, t0); /* t1 = t1 * t2 = z ** (2 ** 5 - 1) */ fe52_mul(t1, t1, t2); /* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */ fe52_sqr_power(t2, t1, 5); /* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */ fe52_mul(t1, t2, t1); /* Continuing similarly... */ /* t2 = z ** (2 ** 20 - 1) */ fe52_sqr_power(t2, t1, 10); fe52_mul(t2, t2, t1); /* t2 = z ** (2 ** 40 - 1) */ fe52_sqr_power(t3, t2, 20); fe52_mul(t2, t3, t2); /* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */ fe52_sqr_power(t2, t2, 10); /* t1 = z ** (2 ** 50 - 1) */ fe52_mul(t1, t2, t1); /* t2 = z ** (2 ** 100 - 1) */ fe52_sqr_power(t2, t1, 50); fe52_mul(t2, t2, t1); /* t2 = z ** (2 ** 200 - 1) */ fe52_sqr_power(t3, t2, 100); fe52_mul(t2, t3, t2); /* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */ fe52_sqr_power(t2, t2, 50); /* t1 = z ** (2 ** 250 - 1) */ fe52_mul(t1, t2, t1); /* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */ fe52_sqr_power(t1, t1, 5); /* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */ fe52_mul(out, t1, t0); } #define cswap_U64(a, b, kmask) { \ U64 ta = mask_mov64((a), (kmask), (b)); \ (b) = mask_mov64((b), (kmask), (a)); \ (a) = ta; \ } static void fe52mb8_cswap(U64 a[], U64 b[], __mb_mask k) { cswap_U64(a[0], b[0], k) cswap_U64(a[1], b[1], k) cswap_U64(a[2], b[2], k) cswap_U64(a[3], b[3], k) cswap_U64(a[4], b[4], k) } #if 0 static void x25519_scalar_mul(U64 out[], U64 scalar[], U64 point[]) { __ALIGN64 U64 x1[5], x2[5], x3[5]; __ALIGN64 U64 z2[5], z3[5]; __ALIGN64 U64 tmp0[5], tmp1[5]; fe52mb8_copy(x1, point); fe52mb8_set(x2, 1); fe52mb8_set(z2, 0); fe52mb8_copy(x3, x1); fe52mb8_set(z3, 1); /* read high and remove (zero) bit 63 */ U64 e = loadu64(&scalar[3]); e = slli64(e, 1); __mb_mask swap = get_mask(0); int bitpos; for (bitpos=254; bitpos>= 0; bitpos--) { if(63==(bitpos%64)) e = loadu64(&scalar[bitpos/64]); __mb_mask b = cmp64_mask(e, get_zero64(), _MM_CMPINT_LT); swap = mask_xor (swap, b); fe52mb8_cswap(x2, x3, swap); fe52mb8_cswap(z2, z3, swap); swap = b; fe52_sub(tmp0, x3, z3); fe52_sub(tmp1, x2, z2); fe52_add(x2, x2, z2); fe52_add(z2, x3, z3); #ifdef USE_DUAL_MUL_SQR ed25519_mul_dual(z3, z2, x2, tmp0, z2, tmp1); #else fe52_mul(z3, x2, tmp0); fe52_mul(z2, z2, tmp1); #endif #ifdef USE_DUAL_MUL_SQR ed25519_sqr_dual(tmp0, tmp1, tmp1, x2); #else fe52_sqr(tmp0, tmp1); fe52_sqr(tmp1, x2); #endif fe52_add(x3, z3, z2); fe52_sub(z2, z3, z2); fe52_mul(x2, tmp1, tmp0); fe52_sub(tmp1, tmp1, tmp0); fe52_sqr(z2, z2); fe52_mul121666(z3, tmp1); fe52_sqr(x3, x3); fe52_add(tmp0, tmp0, z3); #ifdef USE_DUAL_MUL_SQR ed25519_mul_dual(z3, z2, x1, z2, tmp1, tmp0); #else fe52_mul(z3, x1, z2); fe52_mul(z2, tmp1, tmp0); #endif e = slli64(e, 1); } fe52mb8_inv_mod25519(z2, z2); fe52_mul(out, x2, z2); } #endif ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// __MBX_INLINE void ed25519_mul_dual_wonorm(U64 out0[], U64 out1[], const U64 a0[], const U64 b0[], const U64 a1[], const U64 b1[]) { U64 r00, r01, r02, r03, r04, r05, r06, r07, r08, r09; U64 r10, r11, r12, r13, r14, r15, r16, r17, r18, r19; U64 *vr0 = (U64*) out0; U64 *vr1 = (U64*) out1; r00 = r01 = r02 = r03 = r04 = r05 = r06 = r07 = r08 = r09 = get_zero64(); r10 = r11 = r12 = r13 = r14 = r15 = r16 = r17 = r18 = r19 = get_zero64(); // Full multiplication U64 *va = (U64*) a0; U64 *vb = (U64*) b0; ROUND_MUL(4, 4, r08, r09) ROUND_MUL(3, 0, r03, r04) ROUND_MUL(1, 2, r03, r04) ROUND_MUL(0, 3, r03, r04) ROUND_MUL(2, 1, r03, r04) ROUND_MUL(2, 2, r04, r05) ROUND_MUL(0, 4, r04, r05) ROUND_MUL(1, 3, r04, r05) ROUND_MUL(3, 1, r04, r05) ROUND_MUL(4, 0, r04, r05) ROUND_MUL(1, 4, r05, r06) ROUND_MUL(2, 3, r05, r06) ROUND_MUL(3, 2, r05, r06) ROUND_MUL(4, 1, r05, r06) ROUND_MUL(2, 4, r06, r07) ROUND_MUL(3, 3, r06, r07) ROUND_MUL(4, 2, r06, r07) ROUND_MUL(0, 0, r00, r01) ROUND_MUL(0, 1, r01, r02) ROUND_MUL(0, 2, r02, r03) ROUND_MUL(1, 0, r01, r02) ROUND_MUL(1, 1, r02, r03) ROUND_MUL(2, 0, r02, r03) ROUND_MUL(3, 4, r07, r08) ROUND_MUL(4, 3, r07, r08) va = (U64*) a1; vb = (U64*) b1; ROUND_MUL(4, 4, r18, r19) ROUND_MUL(3, 0, r13, r14) ROUND_MUL(1, 2, r13, r14) ROUND_MUL(0, 3, r13, r14) ROUND_MUL(2, 1, r13, r14) ROUND_MUL(2, 2, r14, r15) ROUND_MUL(0, 4, r14, r15) ROUND_MUL(1, 3, r14, r15) ROUND_MUL(3, 1, r14, r15) ROUND_MUL(4, 0, r14, r15) ROUND_MUL(1, 4, r15, r16) ROUND_MUL(2, 3, r15, r16) ROUND_MUL(3, 2, r15, r16) ROUND_MUL(4, 1, r15, r16) ROUND_MUL(2, 4, r16, r17) ROUND_MUL(3, 3, r16, r17) ROUND_MUL(4, 2, r16, r17) ROUND_MUL(0, 0, r10, r11) ROUND_MUL(0, 1, r11, r12) ROUND_MUL(0, 2, r12, r13) ROUND_MUL(1, 0, r11, r12) ROUND_MUL(1, 1, r12, r13) ROUND_MUL(2, 0, r12, r13) ROUND_MUL(3, 4, r17, r18) ROUND_MUL(4, 3, r17, r18) REDUCE_R4_N_R9(r0) REDUCE_R4_N_R9(r1) REDUCE_ROUND_(r0, 0, 1, 5); REDUCE_ROUND_(r0, 1, 2, 6); REDUCE_ROUND_(r0, 2, 3, 7); REDUCE_ROUND_(r0, 3, 4, 8); REDUCE_ROUND_(r1, 0, 1, 5); REDUCE_ROUND_(r1, 1, 2, 6); REDUCE_ROUND_(r1, 2, 3, 7); REDUCE_ROUND_(r1, 3, 4, 8); storeu64(&vr0[0], r00); storeu64(&vr0[1], r01); storeu64(&vr0[2], r02); storeu64(&vr0[3], r03); storeu64(&vr0[4], r04); storeu64(&vr1[0], r10); storeu64(&vr1[1], r11); storeu64(&vr1[2], r12); storeu64(&vr1[3], r13); storeu64(&vr1[4], r14); } __MBX_INLINE void fe52mb8_mul_mod25519_wonorm(U64 vr[], const U64 va[], const U64 vb[]) { U64 r0, r1, r2, r3, r4, r5, r6, r7, r8, r9; r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = r8 = r9 = get_zero64(); // Full multiplication ROUND_MUL(4, 4, r8, r9) ROUND_MUL(3, 0, r3, r4) ROUND_MUL(1, 2, r3, r4) ROUND_MUL(0, 3, r3, r4) ROUND_MUL(2, 1, r3, r4) ROUND_MUL(2, 2, r4, r5) ROUND_MUL(0, 4, r4, r5) ROUND_MUL(1, 3, r4, r5) ROUND_MUL(3, 1, r4, r5) ROUND_MUL(4, 0, r4, r5) ROUND_MUL(1, 4, r5, r6) ROUND_MUL(2, 3, r5, r6) ROUND_MUL(3, 2, r5, r6) ROUND_MUL(4, 1, r5, r6) ROUND_MUL(2, 4, r6, r7) ROUND_MUL(3, 3, r6, r7) ROUND_MUL(4, 2, r6, r7) ROUND_MUL(0, 0, r0, r1) ROUND_MUL(0, 1, r1, r2) ROUND_MUL(0, 2, r2, r3) ROUND_MUL(1, 0, r1, r2) ROUND_MUL(1, 1, r2, r3) ROUND_MUL(2, 0, r2, r3) ROUND_MUL(3, 4, r7, r8) ROUND_MUL(4, 3, r7, r8) //REDUCE_ROUND(4, 5, 9); r4 = fma52lo(r4, r9, MOD_2_260); //r9 always contributes 0 to r5 (if input normalized?) REDUCE_ROUND(3, 4, 8); REDUCE_ROUND(2, 3, 7); REDUCE_ROUND(1, 2, 6); REDUCE_ROUND(0, 1, 5); // Reduce r4 upper bits r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); // Trim top r4 bits that were already reduced above r4 = and64(r4, MASK_47); storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } __MBX_INLINE void fe52mb8_mul121666_mod25519_wonorm(U64 vr[], const U64 va[]) { U64 multiplier = set64(121666); U64 r0, r1, r2, r3, r4, r5; r0 = r1 = r2 = r3 = r4 = r5 = get_zero64(); // multiply r0 = fma52lo(r0, va[0], multiplier); r1 = fma52lo(r1, va[1], multiplier); r2 = fma52lo(r2, va[2], multiplier); r3 = fma52lo(r3, va[3], multiplier); r4 = fma52lo(r4, va[4], multiplier); r5 = fma52hi(r5, va[4], multiplier); r1 = fma52hi(r1, va[0], multiplier); r2 = fma52hi(r2, va[1], multiplier); r3 = fma52hi(r3, va[2], multiplier); r4 = fma52hi(r4, va[3], multiplier); // reduce REDUCE_ROUND(0, 1, 5); r0 = fma52lo(r0, srli64(r4, 47), MOD_2_255); // trim top r4 bits that were already reduced above r4 = and64(r4, MASK_47); storeu64(&vr[0], r0); storeu64(&vr[1], r1); storeu64(&vr[2], r2); storeu64(&vr[3], r3); storeu64(&vr[4], r4); } __MBX_INLINE void x25519_scalar_mul_dual(U64 out[], U64 scalar[], U64 point[]) { __ALIGN64 U64 x1[5], x2[5], x3[5]; __ALIGN64 U64 z2[5], z3[5]; __ALIGN64 U64 tmp0[5], tmp1[5]; fe52mb8_copy(x1, point); fe52mb8_set(x2, 1); fe52mb8_set(z2, 0); fe52mb8_copy(x3, x1); fe52mb8_set(z3, 1); /* read high and remove (zero) bit 63 */ U64 e = loadu64(&scalar[3]); U64 vmask = slli64( xor64(e, srli64(e, 1)), 1); __mb_mask swap = cmp64_mask(vmask, get_zero64(), _MM_CMPINT_LT); int bitpos; for (bitpos = 254; bitpos >= 0; bitpos--) { if (63 == (bitpos % 64)) { U64 t = e; e = loadu64(&scalar[bitpos/64]); vmask = xor64(slli64(t, 63), xor64(e, srli64(e, 1))); swap = cmp64_mask(vmask, get_zero64(), _MM_CMPINT_LT); } fe52mb8_cswap(x2, x3, swap); fe52mb8_cswap(z2, z3, swap); #if (defined(linux) && ((SIMD_LEN)==512)) // Avoid reordering optimization by compiler U64 Z = get_zero64(); __asm__ ("vpsllq $1, %0, %0 \n" "vpcmpq $1, %2, %0, %1\n" : "+x" (vmask), "=k" (swap): "x" (Z) : ); #else vmask = slli64(vmask, 1); swap = cmp64_mask(vmask, get_zero64(), _MM_CMPINT_LT); #endif fe52_sub(tmp0, x3, z3); fe52_sub(tmp1, x2, z2); fe52_add(x2, x2, z2); fe52_add(z2, x3, z3); ed25519_mul_dual_wonorm(z3, z2, x2,tmp0, z2,tmp1); ed25519_sqr_dual(tmp0, tmp1, tmp1, x2); fe52_add(x3, z3, z2); fe52_sub(z2, z3, z2); fe52mb8_mul_mod25519_wonorm(x2, tmp1, tmp0); fe52_sub(tmp1, tmp1, tmp0); ed25519_sqr_dual(z2, x3, z2, x3); fe52mb8_mul121666_mod25519_wonorm(z3, tmp1); fe52_add(tmp0, tmp0, z3); ed25519_mul_dual_wonorm(z3, z2, x1,z2, tmp1,tmp0); } // normalize z2 and x2 before inversion { U64 r0 = z2[0]; U64 r1 = z2[1]; U64 r2 = z2[2]; U64 r3 = z2[3]; U64 r4 = z2[4]; NORM_(r, 0,1) NORM_(r, 1,2) NORM_(r, 2,3) NORM_(r, 3,4) storeu64(&z2[0], r0); storeu64(&z2[1], r1); storeu64(&z2[2], r2); storeu64(&z2[3], r3); storeu64(&z2[4], r4); r0 = x2[0]; r1 = x2[1]; r2 = x2[2]; r3 = x2[3]; r4 = x2[4]; NORM_(r, 0,1) NORM_(r, 1,2) NORM_(r, 2,3) NORM_(r, 3,4) storeu64(&x2[0], r0); storeu64(&x2[1], r1); storeu64(&x2[2], r2); storeu64(&x2[3], r3); storeu64(&x2[4], r4); } fe52mb8_inv_mod25519(z2, z2); fe52_mul(x2, x2, z2); fe52mb8_red_p25519(out, x2); } mbx_status MB_FUNC_NAME(internal_avx512_x25519_)(int8u* const pa_shared_key[8], const int8u* const pa_private_key[8], const int8u* const pa_public_key[8]) { mbx_status status = 0; /* continue processing if there are correct parameters */ if( MBX_IS_ANY_OK_STS(status) ) { __ALIGN64 U64 private64_mb8[4]; __ALIGN64 U64 pub52_mb8[5]; __ALIGN64 U64 shared52_mb8[5]; /* get scalars and convert to MB8 */ ifma_BNU_transpose_copy((int64u (*)[8])private64_mb8, (const int64u * const*)pa_private_key, 256); /* decode keys into scalars according to RFC7748 */ private64_mb8[0] = and64_const(private64_mb8[0], 0xfffffffffffffff8); private64_mb8[3] = and64_const(private64_mb8[3], 0x7fffffffffffffff); private64_mb8[3] = or64(private64_mb8[3], set64(0x4000000000000000)); /* get peer's public keys and convert to MB8 */ ifma_BNU_to_mb8((int64u (*)[8])pub52_mb8, (const int64u * const*)pa_public_key, 256); /* RFC7748: (x25519) ... MUST mask the most significant bit in the final byte. This is done to preserve compatibility with point formats .. (compact format??) */ pub52_mb8[4] = and64(pub52_mb8[4], loadu64(VPRIME25519_HI)); /* point multiplication */ x25519_scalar_mul_dual(shared52_mb8, private64_mb8, pub52_mb8); /* test shared secret before return; all-zero output results when the input is a point of small order. */ __ALIGN64 U64 shared52_sum = shared52_mb8[0]; shared52_sum = or64(shared52_sum, shared52_mb8[1]); shared52_sum = or64(shared52_sum, shared52_mb8[2]); shared52_sum = or64(shared52_sum, shared52_mb8[3]); shared52_sum = or64(shared52_sum, shared52_mb8[4]); int8u stt_mask = cmpeq64_mask(shared52_sum, get_zero64()); status |= MBX_SET_STS_BY_MASK(status, stt_mask, MBX_STATUS_LOW_ORDER_ERR); /* convert result back */ ifma_mb8_to_BNU((int64u* const *)pa_shared_key, (const int64u (*)[8])shared52_mb8, 256); /* clear computed shared keys and it sum */ MB_FUNC_NAME(zero_)((int64u (*)[8])shared52_mb8, sizeof(shared52_mb8)/sizeof(U64)); MB_FUNC_NAME(zero_)((int64u (*)[8])&shared52_sum, 1); /* clear copy of the secret keys */ MB_FUNC_NAME(zero_)((int64u (*)[8])private64_mb8, sizeof(private64_mb8)/sizeof(U64)); } return status; } ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /* the fe64 muTBL52[] table in radix52 */ __ALIGN64 static int64u muTBL52[255][NUMBER_OF_DIGITS(256,DIGIT_SIZE)] = { {0x000ffffffffffff3, 0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff, 0x00005fffffffffff}, {0x000220f416aafe96, 0x0002b4f566a346b8, 0x0005a5950f82ebeb, 0x00088f4d5a9a5b07, 0x00005142b2cf4b24}, {0x000ebc750069680c, 0x00020a0f99c416aa, 0x000b56d0f489cf78, 0x00011a42a58d9183, 0x00004b5aca80e360}, {0x000132348c29745d, 0x00016e1642fd7329, 0x000f67bc34f4a2e6, 0x0009b4a1e45bb03f, 0x0000306912d0f42a}, {0x00086507e6af7154, 0x00013dfeec82fff8, 0x000abab5ce04f50e, 0x000f222aa512fe82, 0x0000174e251a68d5}, {0x0006700d82028898, 0x000370a2c02c5cf9, 0x0004e86eaa1743e3, 0x000482e379eec98b, 0x00000c59888a51e0}, {0x000bf1d699b5d189, 0x000d58e9fdc84fbc, 0x00031f7614acaef0, 0x000f972c1c20d062, 0x00002938218da274}, {0x000f49beff1d7f18, 0x00022387ac9c2f6a, 0x000015c56bcc541c, 0x00013a996fcc9ef4, 0x000069c1627c6909}, {0x0006fd2f4733db0e, 0x000f29e087de97a8, 0x000ea2a229fdb8c4, 0x0007a79095e4b1a8, 0x00001ad7a7c829b3}, {0x000d89cad17ea0c0, 0x000a6cced2051342, 0x000bb42f7467bedd, 0x000acbb19ca31bf2, 0x00003df7b4c84980}, {0x0006444dc80ad883, 0x0000366e3ab85a8c, 0x000164f6d8b91e44, 0x000e668c215cda00, 0x00003d867c6ef247}, {0x000d582bcc3e658c, 0x00048ee0e5528c7d, 0x000c9f4f71fd2c47, 0x0005ddfa0fd9b95c, 0x00007529d871b067}, {0x000568b42d3cbd78, 0x0001b91f3da82b8f, 0x000a7c3b62123301, 0x00086032dce6ccd4, 0x000075e7fc8e9e49}, {0x000f13f1fcd0b6ec, 0x0001f29ff7a452f4, 0x000981e29bf1a8ca, 0x000b56ac249c1a72, 0x00006ebe0dbb8c83}, {0x0004fa8d170bb222, 0x000d5bf93935f711, 0x00059c979a65a2dc, 0x0009289bdc41f68b, 0x00002f0eef79a2ce}, {0x000cbf0c083c37ce, 0x00009ec49632242e, 0x000cfeac0d2930bc, 0x000bb80f294b0c19, 0x00003780aa4bedfa}, {0x00017d3e7cead929, 0x000eb2e5722c556c, 0x000dbfe15ae7cb4b, 0x00052f80ce931732, 0x000041b883c76210}, {0x00075ca0c3d25350, 0x000086eb1e351dbf, 0x0004a9b2122936be, 0x00025aac936e03cb, 0x00001d45bf823222}, {0x000ab1036a024cc5, 0x0001c304c9a72e81, 0x000832b1fce21220, 0x0009581c5d73fba6, 0x000020ffdb5a4d83}, {0x0003d367be5d0fad, 0x000ca8b164475a28, 0x000caaf22e6c2b25, 0x000ff499d4935467, 0x00005166408eee85}, {0x0007baa2fab4e361, 0x000c67ef35cef3c6, 0x0001159b1cb3e433, 0x000ab33525972924, 0x00006a621892d5b0}, {0x00074a387555cdcb, 0x0000e1208923f20b, 0x0002281dd1532aa1, 0x00044bfeaa17b776, 0x000061ab3443f05c}, {0x000a6c422324def8, 0x0001017e3cf7f257, 0x000630a257131c6c, 0x000858023758739f, 0x0000295a407a01a7}, {0x000443246d5da8d9, 0x000450c52fa5df8c, 0x00031bf83d19d775, 0x00047002afcfc927, 0x00007d10c8e81b2b}, {0x0000271f70baa20b, 0x000867ca63957c8e, 0x000b7ed4bb993748, 0x00029755412efb3c, 0x00003196d36173e6}, {0x000bcad141c7dffc, 0x000d2b395c848de5, 0x00011af3cb47cc8c, 0x000cec2a34cd942e, 0x00000256dbf2d04e}, {0x000ab7e94b0e667f, 0x00083c0850d10875, 0x000e72c79fcad4dd, 0x000b19b47f12e8f4, 0x00005f1a87bb8c85}, {0x0009d0b6437f51b8, 0x00055188790657ae, 0x000cf77aee12c7ce, 0x00056272ade09fe5, 0x000023a05a2f7d2c}, {0x0008e128f17c169a, 0x000dd8ad0852d590, 0x000b102f64f77498, 0x000984574b4c4cea, 0x0000183abadd1013}, {0x0005ba8daa92aaac, 0x0009599386705b16, 0x0008fc40d1d5c5ef, 0x0004514be2f8f0cf, 0x00002701e635ee20}, {0x000fa80020156514, 0x0008764a8c1ce629, 0x000b3f060ef22386, 0x000a3fa5b894fff0, 0x000060d9944cf708}, {0x000a001a1c7a201f, 0x000633ee2ce63aee, 0x000c7a07e1ebf16a, 0x00008cb6f7709594, 0x000079b958150d02}, {0x00055e5301d410e7, 0x000dff3fdc84d24b, 0x00004032d8e3a34e, 0x000aeecd88768e49, 0x0000131384427b3a}, {0x0005e51286234f14, 0x00039adb4c529840, 0x0000634ffd14dc47, 0x000ff93b8a2b5b25, 0x00002fe2a94ad8a7}, {0x000c57efe843fadd, 0x00040f0bb9918ec5, 0x000f3d63052843ce, 0x000777ea4b561d6c, 0x0000743629bde8fb}, {0x000edd46bbaf738f, 0x00028b101a651343, 0x00082c797aed9818, 0x0008730a401760b8, 0x00001fc223e28dc8}, {0x00004e91fc0fba0e, 0x0008f052c6fa4486, 0x0009e9239cb637f7, 0x000687c91ccac3d0, 0x000023f7eed4437a}, {0x0003b1118d9bd800, 0x000b63189d4a7517, 0x0008bbc58629d641, 0x0001df5fdbf17798, 0x00002959894fcad8}, {0x000c8ef3b4bbc899, 0x0005ab26992b9aeb, 0x0004f92cfb414899, 0x000dee824e20b013, 0x000040d158894a05}, {0x00000b1185af76f6, 0x0007873187a7946b, 0x000b8fff5f26bac7, 0x00024d73dc0bf95a, 0x00002a608bd89455}, {0x00049588bd446302, 0x0001c0388439c264, 0x0003bd11b27c4bc2, 0x00076b98e98a4f38, 0x000026218d7bc9d8}, {0x00081542997c178a, 0x000a86fb6606fe30, 0x000a2793743c2d29, 0x000b1fa5c217736f, 0x00007dde05734afe}, {0x00010e3906d42bab, 0x0003e1980649c3bf, 0x000595bf7ae4f780, 0x0005530e6053bf89, 0x0000394faf38da24}, {0x000efb58896928f4, 0x000e9cc6a113c7a8, 0x0000af596ffbc778, 0x0006cf772670ce33, 0x000048f222a81d3d}, {0x000fce410d72caa7, 0x000c7213b5595f01, 0x0001fa14835a20ec, 0x000a7417bc21165c, 0x000007f89ae31da8}, {0x0002c2b4c6830ff9, 0x0000fc631629305d, 0x0006d3a904d43e33, 0x00033b6a5a5590a9, 0x0000705edb91a653}, {0x000ee15e0bb9a5f7, 0x000ca9e0aaf5d048, 0x000dc4a40b3240cf, 0x0004a6d8f4b71cee, 0x0000621c0da3de54}, {0x00072836a08c4091, 0x000b010c91445928, 0x000f276394ce8375, 0x00036358a72eb524, 0x00002667fcfa7ec8}, {0x000c173345e8752a, 0x000feee7079a57f4, 0x000f86ff34061b47, 0x000c89c25dd9afa9, 0x00003780cef5425d}, {0x0006035a513bb4e9, 0x00079ac575ada1a4, 0x000fa24b503e1ef3, 0x0009f22c78c5f1c5, 0x0000321a967634fd}, {0x000707b8826e27fa, 0x000d64c506fd0946, 0x0005e914363dca84, 0x0008484c18921807, 0x00006d9284169b3b}, {0x0007e840383f2ddf, 0x000a30c4f9b753a6, 0x000783ef4733eec9, 0x000fbc43ec7c86fa, 0x000026ec449fbac9}, {0x000f38cba09b9e7d, 0x000c762a3478c5c0, 0x0006fc121c81168c, 0x000dcdd3e23b0d30, 0x00005a238aa0a5ef}, {0x00026121c4ea43ff, 0x0007f7c8832b51ba, 0x000adcf99a36f8c7, 0x000ebf988fbea0b0, 0x00005ca9938ec25b}, {0x00036a5e51fccda0, 0x00097c2cd893bd54, 0x0003224a081dbc47, 0x000f46619346a65d, 0x00000f5034e49b9a}, {0x000c3967a1e0b96e, 0x000fa867a4d88f23, 0x0007341679e58b08, 0x0006946fb2fabc6a, 0x00002a75381eb602}, {0x000a3be4c19420ac, 0x000c681f2b6dcc80, 0x0001e9338866b1f6, 0x000a4c47cf703676, 0x000025abbbd8a660}, {0x000a12ba14fd5198, 0x000fc4a3cffa991e, 0x0000f5ad28684950, 0x000a441f82684213, 0x00003ea988f75301}, {0x0008109a695f8c6f, 0x0004a0530c3f3c97, 0x00044599951746eb, 0x0005cc7444d6d77b, 0x000075952b8c054e}, {0x00003f7915f4d6aa, 0x000202f2647d8a37, 0x00011d644b66c346, 0x000d71fd01469df8, 0x000077fea47d81a5}, {0x0009529ef57ca381, 0x000b9ce2f881ac5e, 0x0008009bd66eeeb4, 0x0003fecb6e91a28e, 0x00004b80be3e9afc}, {0x000773c526aed2c5, 0x000b453c9a49d7e3, 0x000affb24d1b4afc, 0x000400ea920bdd7b, 0x00007c54699f122d}, {0x0006c8e14fa94bc8, 0x000ce2952ed5eef4, 0x000bd885d5e0b074, 0x000712cbea450e1d, 0x000061b68649320f}, {0x00085f7309ccbdd1, 0x0000d7d4d1a2d8a4, 0x00022dbef4bd0632, 0x000f770252329733, 0x0000445dc4758c17}, {0x000434177cc8933c, 0x0002175ea059fdb0, 0x000053db34ed6fe8, 0x000af991efebefdc, 0x00004adbe867c65d}, {0x000d71a2a90609df, 0x000856dd040503ac, 0x000157c23ce5e991, 0x000fe4d1ec69b688, 0x0000697427f6885c}, {0x000e7b9b65e1a851, 0x000d522c536ddd7b, 0x000fd2b645a03d28, 0x00041e128399d658, 0x000049e5b7e17c26}, {0x000c3a98700457a4, 0x000a25ebb67786f8, 0x000382960f5078f0, 0x00084b1d13c3ccbc, 0x00002e003258a7df}, {0x0001f39be6296a1c, 0x000652a5fbfb28ad, 0x000d26f3cbc1eeaa, 0x0002ccc33ee0673f, 0x000059256173a69d}, {0x000a07aa4e18fc41, 0x000527c87a51e41e, 0x000831ca6fd9fc19, 0x000694fbdaacb805, 0x0000445b652dc916}, {0x0002a3a7f2172315, 0x0002de11b9964ce9, 0x00004c314a1edc28, 0x000f586a1823aafe, 0x0000790a2d94437c}, {0x000447fb93f6e009, 0x000672284527671c, 0x00004f51698922a5, 0x00019febf70903b2, 0x00002f7a89891ba3}, {0x00008eb577e2140c, 0x000d4427bdcf402a, 0x0004323cd1ed9a4e, 0x000355b5253ec44e, 0x00003e88363c14e9}, {0x0006c14277110b8c, 0x0001610a23390aa6, 0x00093fc2a21ae039, 0x000c7ab2030bd12c, 0x00003ee141579555}, {0x0004de3a6d6e7d41, 0x0008607f17efe921, 0x0008e112173ccdd8, 0x00093d0674f1288f, 0x00005682250f329f}, {0x00000b136d2e396e, 0x0006f1014debf6cf, 0x000fcc4e836e4cf8, 0x00016b65930b1b5b, 0x0000047069b48aba}, {0x000ce4ab69b20793, 0x0001a97d0fb9e0d4, 0x000e00d01db24db9, 0x000ddb5cdfa50f54, 0x0000221b1085368b}, {0x00059468b1e3d8d2, 0x00063bd122f93e7e, 0x0000663f0953c565, 0x0003d42eee8a903e, 0x000061efa662cbbe}, {0x0008ddddde6eab2a, 0x000d51435f2312cf, 0x0009f049739bf80a, 0x0009b275deadacec, 0x000029275b5d41d2}, {0x000e0f0895ebf14f, 0x0006b054905a7cfd, 0x0001c420fdb9aab9, 0x000bbc7cae80dd9a, 0x00000a63bf2f1673}, {0x000f6e11958fbc8c, 0x000e804822fad092, 0x0000d52517672a81, 0x00092f8cac835156, 0x00006f3f7722c8f1}, {0x000a90ccc2e894b7, 0x000a438ff9f0df8b, 0x000ae523592c7557, 0x0003d69894d1d855, 0x000068e122157b74}, {0x000e5570cfb919f3, 0x000cd95798db9d87, 0x0000c0a2ce3f2cde, 0x000c5b2212115471, 0x00003c66a115246d}, {0x000dc562294ecb72, 0x000c36a280b16cbe, 0x0004078b67ba7143, 0x0004b1e9610c2efd, 0x00006144735d946a}, {0x000f111ed75b3350, 0x0008c2041d81b536, 0x000e10413c0211db, 0x0008876f93cb1000, 0x0000149dfd3c039e}, {0x0009dde46b63155b, 0x000e93c837976d47, 0x000f13e038b66e15, 0x0000b35dafde43b1, 0x00005fafda1a2e4b}, {0x0000bbdf17197581, 0x0000bbe3cd2c2360, 0x000dd5be86397205, 0x000860f5938906db, 0x000034fce5e43f9b}, {0x0008a4cd42d14d02, 0x000c53441df6575a, 0x0002e131d3828dab, 0x000d25f33dcabedd, 0x00003ebad76fb814}, {0x00006f566f70e10f, 0x000aa51690f5ad49, 0x0006cefcf25d12f7, 0x000299945adb16e7, 0x000001f768aead23}, {0x000cc77b6248febd, 0x00028ec3aaffd2b6, 0x0004ef486a3cd306, 0x0006c23ce1c0b80d, 0x00004c3bff2ea6f6}, {0x000ec4094aeaeb5f, 0x000286e372ca73f2, 0x000e2a701d61b19b, 0x000e3ef5eefa966d, 0x000023b20565de55}, {0x0001ca5279d58557, 0x000ce27c2874fe30, 0x000dcf1d6707b2d4, 0x000ff56a532cd8a9, 0x00002a52fee23f2b}, {0x0004efb37cd8663d, 0x00020ffbd7594862, 0x0002d37445bbc7ac, 0x000ec6657b85e9c8, 0x00007b3052cb86a6}, {0x0002f0ad2525e91e, 0x00043d28edca0348, 0x000e1b003a2cb680, 0x0001b0aaf4f6d052, 0x0000185f8c252978}, {0x0001de5bd80ce0d6, 0x000416853e9d6aa4, 0x00057f4c3a9407b2, 0x0007bce563ec36e3, 0x00004cc4b8dd0e29}, {0x000c1a52ffb8730e, 0x0006e67058e37a2f, 0x000ddf4ee11811f1, 0x000f09910f9a366c, 0x000072f4a0c4a0b9}, {0x0006c06f663f4ea7, 0x000f74e970fba8c1, 0x00069ec345693b3a, 0x00080892102e7f1d, 0x00000ba53cbc968a}, {0x000d9dc7fea15537, 0x000bb51536493ca3, 0x00044006b14c6824, 0x000cc60b98863148, 0x000040d2a72ab454}, {0x0006a1b712570975, 0x00048debda657593, 0x00064330ea91b9d6, 0x00051d03344094bb, 0x0000006ba10d12ee}, {0x00028468f5de5d58, 0x0004c38cc05b0192, 0x00056019900eb12f, 0x0000e0ba1039f9dd, 0x00004502d4ce4fff}, {0x000054106837c189, 0x0004c6dd3b93ceb2, 0x000416d74fd0f654, 0x0002ef040727064c, 0x00006e15c6114b50}, {0x0002a398cfb1a76b, 0x0007419f2f6b14df, 0x00066e604311256c, 0x0005b444a4979620, 0x0000705b3aab4135}, {0x000ef536d797b1d8, 0x000d622ddf0db365, 0x0000575a8800076b, 0x000ca4d3bbf33b0e, 0x00003777aa05c8e4}, {0x000745c85578db5f, 0x00049dbae5ae2392, 0x000adc98676fda41, 0x0001da3b1f0b00b8, 0x000009963437d36f}, {0x00024e90a5dc3853, 0x000641f135cbd7e8, 0x0007ce8fccccb5f6, 0x000249f6736d86c8, 0x0000625f3ce26604}, {0x000ac8059502f63f, 0x0000a2e351469af8, 0x00064b63050c05e7, 0x0003ac335292e9c7, 0x00001a394360c7e2}, {0x0006d53251183264, 0x000bd43c2b74fd5c, 0x000b973f9b62065a, 0x0006e5eb5fbf5d03, 0x000013a3da366120}, {0x000d5837725d94e5, 0x00012205016c5c6b, 0x0000033c6818e309, 0x00079872088ce157, 0x00007fba1f495c83}, {0x000c7423f2f9079d, 0x0007b34023fc55a8, 0x0002fab351173515, 0x000e33ce4f9b49ad, 0x00006691ff72c878}, {0x000c2adedc5eff3e, 0x000f1d8956cf4122, 0x000e9e5bdaf8dd4b, 0x000c743eb86205d9, 0x0000049b92b9d975}, {0x00079730b0f6c05a, 0x000acc6f3a553a53, 0x00020dcd6d72a0ff, 0x000164ab0032c34b, 0x0000470e9dbc88d5}, {0x000cf10ca237c047, 0x000711f6c81a2b19, 0x000dd80b43b65466, 0x000be8eb3321bd16, 0x000048c14f600c5f}, {0x00051c264aa6c803, 0x00004a4fa7da6664, 0x0003128395b66e39, 0x000bc10d45f19b0b, 0x000031602627c3c9}, {0x0000dc4832e4e10d, 0x0006756c717f7312, 0x0007280294eb20c4, 0x000c50900f52e3f6, 0x0000566d4fc14730}, {0x000a5d40fd837206, 0x000dc7159547a7e3, 0x00068d6095c1e926, 0x000cea7216730fba, 0x000022e8c3843f69}, {0x000074e8930e4b2b, 0x0000e84d1581633d, 0x0006ba2365b6e435, 0x000f3f35534c26ad, 0x00007773c12f89f1}, {0x000a404da57962aa, 0x000a81999ce568cb, 0x00021692fc5b9897, 0x000c291508e862f1, 0x00003a81907fa093}, {0x000ed0ff4725a510, 0x00010673fc5030dd, 0x000f1f4e8910d8cc, 0x000a44c5b9d151c9, 0x000032a5c1d5cb09}, {0x000aa442b90541fb, 0x0007cc1b485db1e0, 0x000a9df2e55f85eb, 0x0002236bee595ce8, 0x000025e496c72242}, {0x000f3c46cd0fe5b9, 0x0007ed2a433885ed, 0x000761e35234e75a, 0x000545ce488de11d, 0x00000e878a01a085}, {0x00093c77e021bb04, 0x00043c7df899aba4, 0x000ae80d672b4d18, 0x00017949ea37a487, 0x000067a9958011e4}, {0x0008051a6697b065, 0x0007d8d6ba6d44b5, 0x0003ca46c147e33f, 0x000db0dbb4da8d48, 0x000068becaa181c2}, {0x000980e90b989aa5, 0x0004a2c93c99b8d8, 0x00096e73a2f95eb1, 0x000b56951c6c7c47, 0x00006e228363b5ef}, {0x000bc0b02dd624c8, 0x0007dec8170eec6b, 0x0004cfafa9777eb4, 0x000bf9b3cde15a00, 0x00001dc6bc087160}, {0x0007e043eec34002, 0x000677a68dc7f2e0, 0x000bd15b9a18e9fc, 0x0008253d8da03188, 0x000048fbc3bb0056}, {0x00047d4cfb654ce1, 0x00082a058e2ad575, 0x000f154478d3565b, 0x000bb18f63eaf0bb, 0x000047531ef114df}, {0x000c630a4278c587, 0x00046ca8e83f3e1e, 0x000adc0c2b5507d5, 0x000844e85e135c63, 0x00000aa7efa85682}, {0x00091ba8b3e1f615, 0x000701fbe3ffa726, 0x0009bb786832b4e9, 0x00039e897b6d92e3, 0x00002cfe53dea02e}, {0x000392cd85cd52b0, 0x000c910e29831687, 0x0009832d0627ff66, 0x000f8a097134556a, 0x0000269bb0360a84}, {0x000e55457643f85c, 0x0008c9b597d1b706, 0x0006efa4723734a4, 0x000d9e07aee91e8c, 0x00005cd6abc198a9}, {0x0004de06cb3ce41a, 0x000893402e1380e0, 0x00086e3772d8c6eb, 0x000a8c8904659bb6, 0x00007215c371746b}, {0x0002a97eeae4a2d9, 0x000516394f2c5fd1, 0x000208f2949514b7, 0x00026b9266fd5809, 0x00005c847085619a}, {0x00085410fed694ea, 0x000934a2ed254529, 0x000d3be4673c905b, 0x000e9e110bb47692, 0x0000063b3d2d69e5}, {0x000726eedda57deb, 0x000ae10f41891472, 0x000b307614efb6c4, 0x0005b7c2b1641917, 0x0000117c554fc4f4}, {0x000cf3118f9d8812, 0x0002050017939c07, 0x00071b282701dbd8, 0x00025ead7e803f41, 0x00001015e87487d2}, {0x000de3fed23acc4d, 0x000c294a7be2dc58, 0x000c9cf45750db91, 0x000524a0b94d43d1, 0x00006b1640fa6e37}, {0x000f346c5fda0d09, 0x00059fa4d3151692, 0x000777a296200b1c, 0x000fbcfb8c46f760, 0x00004b38395f3ffd}, {0x00025e00be54d671, 0x00082bec8aba618d, 0x000b78b98260d505, 0x000043287ad8f263, 0x000050fdf64e9cda}, {0x000567aac578dcf0, 0x0000ef2a3133b90f, 0x0002d9de71ef1e9b, 0x00001c70eebba924, 0x000015473c9bf031}, {0x0007e8ae56b78095, 0x000666e6f078e7c7, 0x000348ba1fb678e7, 0x0003f0b2da0b9615, 0x00007cf931c1ff73}, {0x000357f50a0a366c, 0x000f42b87d73226b, 0x00091cb2c0e9708c, 0x000bb4cc13aeea5f, 0x000035d90c991143}, {0x0001c404a9a0d9dc, 0x000451972d25147c, 0x0003b38c31659e58, 0x0001f243875a8c47, 0x00001fbd9ed37956}, {0x000abc6fd41ec28d, 0x000e3cd2a2dca11f, 0x000c4045957ef8df, 0x0002f2772e73b5d8, 0x00006135fa4954b7}, {0x000c32a2de24b69c, 0x0008c1f095d88ccf, 0x000ac3f9293f5569, 0x0007eebbe3350ed5, 0x00005e9bf806ca47}, {0x000e8fb63c309f68, 0x0003565e1f9f4e9c, 0x000a6393f15376f6, 0x0003506d1afcfb35, 0x00006632a1ede562}, {0x000d6c390c2ded4c, 0x00081df04cb1f0b7, 0x0009ecc3c756cb32, 0x000a72a66305a124, 0x00005d588b60a38c}, {0x000cbf78e8e5f42d, 0x0004b3c8a3eeca6e, 0x000bd2160486eeb4, 0x0006731ec219c48f, 0x00001aaf1af517c3}, {0x0006a2836769bde7, 0x000622b1e2adbc30, 0x000bff94a6208280, 0x000f26b8027f51ff, 0x000076cfa1ce1124}, {0x000b00562422abb6, 0x000d58f8c29c318e, 0x000531561af377c4, 0x0008a274dbbc207f, 0x00000253b7f08212}, {0x000f091cb62c17e0, 0x000abd64628a93d1, 0x00009d42534860e1, 0x000e57652d174363, 0x0000356f97e13efa}, {0x0001e11aa150535b, 0x000bb1dd878ccd35, 0x000ed92c983e6b45, 0x00085b80c776128b, 0x00001d34ae930328}, {0x0000488ca85ba4c3, 0x000c33c9ce6ce4ba, 0x0007bda770985348, 0x000124a66124c6f9, 0x00000f81a0290654}, {0x00009ca6569b86fd, 0x000fd18af9a2d9ed, 0x0003d8c20a811009, 0x000f26bff08d03f9, 0x000052a148199fae}, {0x0003f9dc2d8d1b73, 0x0001873961a703e0, 0x0001a35970420580, 0x000d549c0d987f04, 0x000007aa1f15a1c0}, {0x00046ce08cd27224, 0x0004f934e4239dfd, 0x0009897b596d0a02, 0x00095a2808a7a639, 0x00000a4556e9e13d}, {0x000a991fe9c13045, 0x00048fe7751b8d21, 0x000bf300359b0e85, 0x000f7215da643cb4, 0x000077db28d63940}, {0x000eeb614adc9011, 0x0009ae8c411ebfc5, 0x000d1dcf74522941, 0x0004cb59ec3e7787, 0x0000340d053e216e}, {0x0007af39b48df2b4, 0x0002871a10a94cac, 0x000ca575edc0faec, 0x0003a4c140a69245, 0x00000cf1c3713427}, {0x000e306ac224b8a5, 0x0007ccb4930b0c8e, 0x000acbe74f57eaee, 0x000657da1e806bda, 0x00007d9a62742eeb}, {0x0006b6ef546c4830, 0x0001fddb36e2e9eb, 0x000f0d7105885cca, 0x0000412e6b9f383e, 0x000058654fef9d2e}, {0x0005c4ffbe0e8e26, 0x000df9b31816ea90, 0x00002e88e1942de5, 0x000408d497d723f8, 0x000030684dea602f}, {0x0005a278a3e6cb34, 0x0006f5b151dc421e, 0x000d77ca15aefb6e, 0x0008981b30b8e049, 0x000028c3c9cf53b9}, {0x000fb721556cdd2a, 0x000a897022274287, 0x000a5432580d317c, 0x000642f7468c7423, 0x00004a7f11464eb5}, {0x0007a4774d193aa6, 0x0006ea92129a1a23, 0x00087c1a88d86598, 0x000f5eb24c515ecf, 0x0000604003575f39}, {0x0009f189570a9b27, 0x000de465e4b7847b, 0x000bb85c202b98ce, 0x0001901026df551d, 0x000074fcd91047e2}, {0x0002a90a23c1bfa3, 0x0004e478519f613e, 0x000af6cf440cb007, 0x0002dbe5ff1cbbe3, 0x000067fe5438be81}, {0x000cf64fa40f05b0, 0x0002f32283787d13, 0x000f0d2aea054dfb, 0x0000d4e4173915b7, 0x0000482f144f1f61}, {0x00010201b47f8234, 0x000929e70b990f62, 0x000049567c5d0ae1, 0x0006f01dcd7f455b, 0x00007e93d0f1f091}, {0x0009cbf18a7db4fa, 0x000bf6f74c62fdd7, 0x000b8291bdbe8391, 0x0001705027145d14, 0x0000585a73ea2cbf}, {0x000ca03e928a0db2, 0x000a5742857e7485, 0x0006d551a710fc01, 0x000db8a2f482edbd, 0x00000f0433b5048f}, {0x000a2e8dd7dc6247, 0x000d38cd4819a60d, 0x0001f6669788b4c9, 0x0007d7513033ac00, 0x0000273b24fe3b36}, {0x0008f66a31b3b9d4, 0x000a494df49d5c6e, 0x0008b23da7281514, 0x000e548d1726fdfc, 0x00004b3ae7d103de}, {0x00056e19ce4b9d7e, 0x000f186e3c61cc62, 0x000b8ec145ff5c5c, 0x0006574acc63ca34, 0x000074621888fee6}, {0x000f409645290a1e, 0x000e3263a962e956, 0x000ec2647bef0bf8, 0x0007502ed6a50eb5, 0x00000694283a9dca}, {0x000b963643a2dcd1, 0x000ea09fc5353769, 0x0003397eab42b7c8, 0x000d63a4f002aee1, 0x000063005e2c19b7}, {0x000736da63023bea, 0x0006db12a99b7ca6, 0x000537c5e1966c7f, 0x00089eeace09390c, 0x00000b696063a1aa}, {0x00003e97288c56e5, 0x0009f938c8be8ebb, 0x000b717f71432a9f, 0x0009d97a6a5a93d5, 0x00001a5fb4c3e18f}, {0x0004e7ad1c60cdce, 0x00043fc02c4a01c9, 0x0007c46a20ee202a, 0x0007b588dafe4d86, 0x00000a10263c8ac2}, {0x000ea9dfe4432a4a, 0x0007bbe9277c5d0d, 0x000212c71a856af8, 0x0001e91ce8472acc, 0x00006f151b6d9bbb}, {0x00076c527ceed56a, 0x000b7fbf8faec267, 0x000d4609cc7d211c, 0x0000c4237ae66a6f, 0x00001f81b702d277}, {0x0000b057eac58392, 0x000fe29744e9d2fb, 0x0007beb4f8e1dd89, 0x000d41ec964f8eb1, 0x000029571073c9a2}, {0x0008a18981c0e254, 0x0009b65b22830a94, 0x000fcfd3c62df636, 0x000a01fa33eb2d75, 0x0000078cd6ec4199}, {0x00084a41ad900d2f, 0x00078e2c74c524a5, 0x000431c97832142b, 0x0009fc268c4e8338, 0x00007f69ea900868}, {0x0002c81e46a38265, 0x0002d04a832fd52f, 0x0005359e94fd7807, 0x00029d28cd7d5fa2, 0x00004de71b7454cc}, {0x000b60ad1eda6ac9, 0x000dfdbc09c3a42e, 0x00033cc1910aad37, 0x000803c81004b71e, 0x000044e6be345122}, {0x000e8388ba1920db, 0x00032150db00803f, 0x000af60c29f5d57c, 0x0001aee49c8c4281, 0x000021edb518de70}, {0x00063e418f06dc99, 0x00099c166d7b87fb, 0x000e520a83a4460d, 0x000835824dd5248c, 0x00005ec3ad712b92}, {0x00022a5fbd17930f, 0x00077d82570e3150, 0x0005783712a4f64a, 0x0000abb12bc8d691, 0x0000498194c0fc62}, {0x0002d9d255686c82, 0x000d9193e21f038a, 0x00024a5484785c6b, 0x0000989e4d5c81ab, 0x000056307860b2e2}, {0x000d55f78b4d74c4, 0x0004643350131429, 0x0008c71fff22f183, 0x00083ef1e60c2459, 0x000059f2f0149799}, {0x00047d56eb494a44, 0x00054d636a18e46a, 0x0004491c3b3e22a8, 0x000cde7b346e1527, 0x00002ceafd4e5390}, {0x000a8538be0d6675, 0x000bb50818e23ba8, 0x0005d304c34b9074, 0x00092c4cbdab8908, 0x000061a24fe0e561}, {0x000615e6db525bcb, 0x00035a567e4cacb7, 0x000afcdd69dd7d8c, 0x0009766e6b4153ac, 0x00002d668e097f3c}, {0x000e7e265ce55ef0, 0x000527cd4b967a57, 0x00092fd1e55d9f4e, 0x000f7aefbc836064, 0x0000090d52beb7c3}, {0x0009515a1e7b4d7c, 0x0002599da44c009b, 0x0002c555041f266a, 0x00015cca1c49548e, 0x00007ef04287126f}, {0x0001659dbd30ef15, 0x000eec4e0277bfed, 0x0005df32918b4ab9, 0x000f788884d6236a, 0x00001fd96ea6bf5c}, {0x000161981f190d9a, 0x000507e6052c142a, 0x00085a2cd561d849, 0x00085d89fe113bf2, 0x00007c22d676dbad}, {0x000770ed2bfbd27d, 0x000ece996f5a582e, 0x00009001504c05b2, 0x000bf64cd40a9c2b, 0x00005895319213d9}, {0x000c5d703fea2e08, 0x0001258e2188ce7c, 0x0008205bf0b50c49, 0x0002d62cce30baa4, 0x0000537c659ccfa3}, {0x0006623a98cfc088, 0x0001fa4d6aca437b, 0x0006a8d1b0fe9bed, 0x000957504d29b8e5, 0x0000725f71c40b51}, {0x0007f89cd0339ce6, 0x0004469ddc18b28c, 0x0006a1652c8367b1, 0x0006c17883ada83a, 0x0000585f1974034d}, {0x000fb266f1b19188, 0x00063e7c3521789c, 0x0004c0526ae63b48, 0x0004635d88c9da6b, 0x00003e035c9df095}, {0x000d5412fb45de9d, 0x00032e4cff40ddd9, 0x00051d671cdd6845, 0x000f6904b5c999b1, 0x00002d8c2cc811e7}, {0x0004be1d90055d40, 0x000df464aaf407f5, 0x0000e917bea464c5, 0x0006b3033979624f, 0x00002c018dc52735}, {0x00015024e330b3d4, 0x00096691652d3a54, 0x000f9b59f173ff3d, 0x0008e5a94ec42c4e, 0x00000747201618d0}, {0x000ca48aca411c53, 0x0002fcfa661194d6, 0x0001e227ff66415f, 0x000f7eb9c4dd4005, 0x000059810bc09a02}, {0x000eb171b3dc101d, 0x000b99ffef68e2a7, 0x0003b359ea441c5a, 0x000112f32025c9b9, 0x00005e8ce0a71e9d}, {0x000ccb92429503fd, 0x000752f095d55bfc, 0x00072d091ed271ba, 0x00003ba345ead5e9, 0x000018c8df11a831}, {0x000d949a9aed0f4c, 0x000cb6660e37e90c, 0x0006c52e0bc5d1f4, 0x0008e0db8cac52d5, 0x00006e42e400c580}, {0x00046966eeaefd23, 0x0000be39ecdcaa3b, 0x000683a51d0c4f1f, 0x000351b189dc8c9d, 0x000051f27f054c09}, {0x00087ccd2a320682, 0x0005bb3df1c964c4, 0x00055cb8e8587ea9, 0x000d73dc8ccf79e5, 0x0000547dc829a206}, {0x0002a6cd80c39b06, 0x000732000d4c6b82, 0x0001463b4de96d54, 0x0006e1d28535b6f9, 0x0000228f4660e248}, {0x00099538de8d3abf, 0x0000045ebca6e987, 0x000221e7388cd833, 0x000d2bb79952a008, 0x00004322e1a7535c}, {0x0004c11819d1801c, 0x000d84f3f5ec7b11, 0x0009260f4c2016e4, 0x0007266dd0e2df40, 0x00005ec362c0ae5f}, {0x00062b18b8b2b4ee, 0x00050274d1afbc04, 0x00036b02d27cc8d9, 0x000ccd3f25f71054, 0x000043bbf8dcbff9}, {0x000d1767a039e9df, 0x000a8f69d3583b6a, 0x00042931f5b0714d, 0x00009615e55fa18b, 0x00004ed5558f33c6}, {0x00037901c647a5dd, 0x0001f8081d3571fe, 0x00013fd7a6593ddf, 0x000af610249a4fd8, 0x000069acca274e9c}, {0x000ba3ea330721c9, 0x000c20e7e1ea0047, 0x0001314a6083423f, 0x00095271df4c0af0, 0x000009a62dab8928}, {0x000325a49cc6cb00, 0x000c654b56cb6a5b, 0x000dc994a0e94b5d, 0x0004aad3be28779a, 0x00004296e8f8ba3a}, {0x000689761e451eab, 0x0008bff59594a328, 0x0007a7084a2e4d59, 0x00020a849b96853d, 0x00004980a3196014}, {0x0005b9e12f552c42, 0x000db7100fe96956, 0x0003add0d78a5318, 0x0004eda05c90b4d4, 0x0000538b4cd66a5d}, {0x00094fc3e89f039f, 0x000f26f618045f4e, 0x000d4b9550592c9a, 0x000141908a36eb5f, 0x000025fffaf6c2ed}, {0x00034459cc79d354, 0x000b4b1d5476b344, 0x0001615d99eeecbf, 0x000b773ddeb34a06, 0x00005129cecceb64}, {0x0003215894993520, 0x0007cf14c0b3bee4, 0x0006bedad5772f9c, 0x0006a97d2e2fce30, 0x0000715f42b546f0}, {0x000ecdceda5b5f1a, 0x00015a49741a9434, 0x0003edad2e0da171, 0x0009041680bd77c7, 0x0000487c02354edd}, {0x000feff3a70ed9c4, 0x000a3e857e302b8e, 0x0008a2a5a056a32a, 0x000c444df3a68bd4, 0x000007f650b73176}, {0x000b9b1626e0ccb1, 0x000c18b09fb36e38, 0x0009f9496479e053, 0x000f5c456d90319c, 0x00001ca941e7ac9f}, {0x0004df29162fa0bb, 0x0003282b3330549c, 0x000abb437d8488cf, 0x000ad8695dfda14c, 0x00003391f78264d5}, {0x000ae06ae2b5095d, 0x000d73259a946729, 0x00013921edd58a58, 0x000b592e9834262d, 0x000027fedafaa54b}, {0x000dc5b829ad48bb, 0x00042499ee260a99, 0x000d7513fd5f0257, 0x000d938802c8ecd5, 0x000078ceb3ef3f6d}, {0x0002f44f8a135d94, 0x00044828cdda3c34, 0x000537cfe77b9edb, 0x000b4c89436d11a0, 0x00005064b164ec1a}, {0x0000eccfd37eb2fc, 0x0003ed90d25fc702, 0x000fa1bb341f31ea, 0x00030441b930d7bd, 0x00005344467a4811}, {0x00073170f25e6dfb, 0x0001a50114cc8700, 0x0008fc4f00e385dc, 0x00040d82348698ac, 0x00002a77a55284dd}, {0x0006afe0c98c6ce4, 0x00096dddfd6e4fe0, 0x0003bf1ed3c235df, 0x000bdaf1428d01e3, 0x0000785768ec9300}, {0x0002e57a91deb63b, 0x000bfe5ce8b80970, 0x000d1d58ac61bdb8, 0x00057bc645b426f3, 0x00004804a82227a5}, {0x0007048ab44d2601, 0x0001a4b3a69358e5, 0x0009e1c29368d650, 0x00063e2c39c9ec3f, 0x00004172f257d4de}, {0x0008b450330c6401, 0x00017418f2391d36, 0x0000b7d90d040d30, 0x000d51f2c34bb609, 0x000016f649228fdf}, {0x0006818e2b928ef5, 0x00091cdc11e72bea, 0x00077a36cde28ccf, 0x000fd0f594aaa68e, 0x0000313034806c7f}, {0x000d27ac2249bd65, 0x00064018e95128a9, 0x0002b37ec719a3b4, 0x0007b21c26ccff35, 0x0000056f68341d79}, {0x0009d6757efd2327, 0x000b6553afe155e7, 0x000eaf5a60fabdbc, 0x000743bd3e7222c6, 0x00007046c76d4dae}, {0x000be872b18d4a55, 0x00018574e1496660, 0x00002bdcbb199925, 0x0008e8ec103053a3, 0x00003ed8e9800b21}, {0x000b9239fa75e03e, 0x000684633c0837b0, 0x00091a7793efe9fb, 0x000fe3498a35fbe3, 0x00006065510fe2d0}, {0x000b668548abad0c, 0x00048da87e52755c, 0x000107c1ddb45845, 0x000de352c43ecea0, 0x0000526028809372}, {0x0005c56af9213b1f, 0x0004d017e98db341, 0x0005cf709b5bee1a, 0x0009ab613f6b105b, 0x00005ff20e3482b2}, {0x00029c75cc2e6c90, 0x000ca3a70e2060aa, 0x0004b5c515fc7d73, 0x000c207899fc38fc, 0x0000250386b124ff}, {0x000a28d5ae3d2b56, 0x0009dd6de60ce54e, 0x000f06d6c1991314, 0x0008fc716694fc58, 0x000046b23975eb01}, {0x000a6a0fb4b7b4e2, 0x0005a8f7253de470, 0x000fbd3adb5d9247, 0x0006968abeee5b52, 0x00007fa20801a080}, {0x0003faf19f7714d2, 0x000c12f4660c376f, 0x000212744eb3e840, 0x0002dd20fb4cd8df, 0x00004b065a251d3a}, {0x000bde383d77cd4a, 0x000df882c9cb15ce, 0x00009af7596adf39, 0x0006422a2dd242eb, 0x00003147c0e50e5f}, {0x000ca5101d1350db, 0x00079c33fc962164, 0x0003e5da08f8d134, 0x000f8bae640ce4d1, 0x00004bdee0c45061}, {0x00046dc1a4edb1c9, 0x000b6437fd98ad7c, 0x0002a1c00b5514d7, 0x000710e58942f6bb, 0x00002dffb2ab1d70}, {0x000fcf2fc18b6d68, 0x000a8b7806167ccd, 0x000e2937e3a8ebcb, 0x0006e8c980697f95, 0x000002fbba1cd012}, {0x0008c360adff4565, 0x000d24bdb1519cb9, 0x0005fb15d5447101, 0x000a27d98c4c8747, 0x000005f8c76d6e22}, {0x0009e5dffeb9f494, 0x0009d18406b75ab6, 0x0004a42d1dae09c7, 0x000fa84199b45fb9, 0x000079710aebae2a}, {0x000deda7f334d2df, 0x00051af2a57b4a6a, 0x0006dceaa87bde9c, 0x000d07ba98fc64f8, 0x00006bbe0335c20e}, }; __ALIGN64 static const int64u U2_0[8] = {0x000b1e0137d48290, 0x000b1e0137d48290, 0x000b1e0137d48290, 0x000b1e0137d48290, 0x000b1e0137d48290, 0x000b1e0137d48290, 0x000b1e0137d48290, 0x000b1e0137d48290}; __ALIGN64 static const int64u U2_1[8] = {0x00051eb4d1207816, 0x00051eb4d1207816, 0x00051eb4d1207816, 0x00051eb4d1207816, 0x00051eb4d1207816, 0x00051eb4d1207816, 0x00051eb4d1207816, 0x00051eb4d1207816}; __ALIGN64 static const int64u U2_2[8] = {0x000ca2b71d440f6a, 0x000ca2b71d440f6a, 0x000ca2b71d440f6a, 0x000ca2b71d440f6a, 0x000ca2b71d440f6a, 0x000ca2b71d440f6a, 0x000ca2b71d440f6a, 0x000ca2b71d440f6a}; __ALIGN64 static const int64u U2_3[8] = {0x00054cb52385f46d, 0x00054cb52385f46d, 0x00054cb52385f46d, 0x00054cb52385f46d, 0x00054cb52385f46d, 0x00054cb52385f46d, 0x00054cb52385f46d, 0x00054cb52385f46d}; __ALIGN64 static const int64u U2_4[8] = {0x0000215132111d83, 0x0000215132111d83, 0x0000215132111d83, 0x0000215132111d83, 0x0000215132111d83, 0x0000215132111d83, 0x0000215132111d83, 0x0000215132111d83}; mbx_status MB_FUNC_NAME(internal_avx512_x25519_public_key_)(int8u* const pa_public_key[8], const int8u* const pa_private_key[8]) { mbx_status status = 0; /* continue processing if there are correct parameters */ if( MBX_IS_ANY_OK_STS(status) ) { /* convert private to to MB8 and decode */ __ALIGN64 U64 scalar_mb8[4]; ifma_BNU_transpose_copy((int64u (*)[8])scalar_mb8, (const int64u * const*)pa_private_key, 256); /* decode keys into scalars according to RFC4448 */ scalar_mb8[0] = and64_const(scalar_mb8[0], 0xfffffffffffffff8); scalar_mb8[3] = and64_const(scalar_mb8[3], 0x7fffffffffffffff); scalar_mb8[3] = or64(scalar_mb8[3], set64(0x4000000000000000)); /* set up: "special" point S = {1:?:1} => {u1:z1} */ __ALIGN64 U64 U1[5]; __ALIGN64 U64 Z1[5]; fe52mb8_set(U1, 1); fe52mb8_set(Z1, 1); /* set up: pre-computed G-S (base and "special") */ __ALIGN64 U64 Z2[5]; __ALIGN64 U64 U2[5] = { loadu64(U2_0), loadu64(U2_1), loadu64(U2_2), loadu64(U2_3), loadu64(U2_4) }; fe52mb8_set(Z2, 1); __ALIGN64 U64 A[5], B[5], C[5], D[5]; /* scalar template is usual [01xx..xxx] [xxx..xxx] [xxx..xxx] [xxx..000] processing scalar in L->R fashion: - first process scalar' = scalar >>3 - than 3 doubling */ __mb_mask swap = get_mask(0xff); /* read low and remove (zero) bits 0,1,2 */ U64 e = loadu64(&scalar_mb8[0]); e = srli64(e, 3); int bitpos; for (bitpos=3; bitpos<255; bitpos++) { if(0==(bitpos%64)) e = loadu64(&scalar_mb8[bitpos/64]); __mb_mask b = cmp64_mask(and64_const(e, 1), get_zero64(), _MM_CMPINT_NE); swap = mask_xor (swap, b); fe52mb8_cswap(U1, U2, swap); fe52mb8_cswap(Z1, Z2, swap); swap = b; /* load mu = muTBL[bitpos-3] */ U64 mu[5]; mu[0] = set64((long long)muTBL52[bitpos-3][0]); mu[1] = set64((long long)muTBL52[bitpos-3][1]); mu[2] = set64((long long)muTBL52[bitpos-3][2]); mu[3] = set64((long long)muTBL52[bitpos-3][3]); mu[4] = set64((long long)muTBL52[bitpos-3][4]); /* diff addition */ fe52_sub(B, U1, Z1); /* B = U1-Z1 */ fe52_add(A, U1, Z1); /* A = U1+Z1 */ fe52_mul(C, mu, B); /* C = mu*B */ fe52_sub(B, A, C); /* B = (U1+Z1) - mu*(U1-Z1) */ fe52_add(A, A, C); /* A = (Ur+Z1) + mu*(U1-Z1) */ ed25519_sqr_dual(A, B, A, B); ed25519_mul_dual(U1, Z1, Z2, A, U2, B); e = srli64(e, 1); } /* 3 doublings */ for(bitpos=0; bitpos<3; bitpos++) { fe52_add(A, U1, Z1); /* A = U1+Z1 */ fe52_sub(B, U1, Z1); /* B = U1-Z1 */ fe52_sqr(A, A); /* A = A^2 */ fe52_sqr(B, B); /* B = B^*2 */ fe52_sub(C, A, B); /* C = A-B */ fe52_mul121666(D, C); /* D = (A+2)/4 * C*/ fe52_add(D, D, B); /* D = D+B */ fe52_mul(U1, A, B); /* U1 = A*B */ fe52_mul(Z1, C, D); /* Z1 = C*D */ } fe52mb8_inv_mod25519(A, Z1); fe52_mul(U1, U1, A); fe52mb8_red_p25519(U1, U1); /* convert result back */ ifma_mb8_to_BNU((int64u * const*)pa_public_key, (const int64u (*)[8])U1, 256); /* clear secret */ MB_FUNC_NAME(zero_)((int64u (*)[8])scalar_mb8, sizeof(scalar_mb8)/sizeof(U64)); } return status; } #endif /* #if (_MBX>=_MBX_K1) */ cryptography-primitives-1.0.0/sources/ippcp/emptyfile.c000066400000000000000000000016361470420105600234010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ typedef int to_avoid_translation_unit_is_empty_warning; /* The empty file to build a dynamic library in Visual Studio. The IDE does not produce a dll without source files */ cryptography-primitives-1.0.0/sources/ippcp/exports.linux.lib-export000066400000000000000000000561701470420105600261130ustar00rootroot00000000000000EXTERN (ippcpInit) EXTERN (cpGetReg) EXTERN (cpStartTscp) EXTERN (cpStopTscp) EXTERN (cpStartTsc) EXTERN (cpStopTsc) EXTERN (cpGetCacheSize) EXTERN (cpGetFeature) EXTERN (ippcpSetCpuFeatures) EXTERN (ippcpGetCpuFeatures) EXTERN (ippcpGetCpuClocks) EXTERN (ippcpSetNumThreads) EXTERN (ippcpGetNumThreads) EXTERN (ippcpGetEnabledCpuFeatures) EXTERN (ippcpGetEnabledNumThreads) EXTERN (ippcpGetStatusString) EXTERN (ippcpGetLibVersion) EXTERN (cryptoGetLibVersion) EXTERN (ippsDESGetSize) EXTERN (ippsDESInit) EXTERN (ippsDESPack) EXTERN (ippsDESUnpack) EXTERN (ippsTDESEncryptECB) EXTERN (ippsTDESDecryptECB) EXTERN (ippsTDESEncryptCBC) EXTERN (ippsTDESDecryptCBC) EXTERN (ippsTDESEncryptCFB) EXTERN (ippsTDESDecryptCFB) EXTERN (ippsTDESEncryptOFB) EXTERN (ippsTDESDecryptOFB) EXTERN (ippsTDESEncryptCTR) EXTERN (ippsTDESDecryptCTR) EXTERN (ippsAESGetSize) EXTERN (ippsAESInit) EXTERN (ippsAESSetKey) EXTERN (ippsAESPack) EXTERN (ippsAESUnpack) EXTERN (ippsAESSetupNoise) EXTERN (ippsAES_GCMSetupNoise) EXTERN (ippsAES_CMACSetupNoise) EXTERN (ippsAESEncryptECB) EXTERN (ippsAESDecryptECB) EXTERN (ippsAESEncryptCBC) EXTERN (ippsAESEncryptCBC_CS1) EXTERN (ippsAESEncryptCBC_CS2) EXTERN (ippsAESEncryptCBC_CS3) EXTERN (ippsAESDecryptCBC) EXTERN (ippsAESDecryptCBC_CS1) EXTERN (ippsAESDecryptCBC_CS2) EXTERN (ippsAESDecryptCBC_CS3) EXTERN (ippsAESEncryptCFB) EXTERN (ippsAESDecryptCFB) EXTERN (ippsAESEncryptOFB) EXTERN (ippsAESDecryptOFB) EXTERN (ippsAESEncryptCTR) EXTERN (ippsAESDecryptCTR) EXTERN (ippsAESEncryptXTS_Direct) EXTERN (ippsAESDecryptXTS_Direct) EXTERN (ippsAES_EncryptCFB16_MB) EXTERN (ippsSMS4GetSize) EXTERN (ippsSMS4Init) EXTERN (ippsSMS4SetKey) EXTERN (ippsSMS4EncryptECB) EXTERN (ippsSMS4DecryptECB) EXTERN (ippsSMS4EncryptCBC) EXTERN (ippsSMS4EncryptCBC_CS1) EXTERN (ippsSMS4EncryptCBC_CS2) EXTERN (ippsSMS4EncryptCBC_CS3) EXTERN (ippsSMS4DecryptCBC) EXTERN (ippsSMS4DecryptCBC_CS1) EXTERN (ippsSMS4DecryptCBC_CS2) EXTERN (ippsSMS4DecryptCBC_CS3) EXTERN (ippsSMS4EncryptCFB) EXTERN (ippsSMS4DecryptCFB) EXTERN (ippsSMS4EncryptOFB) EXTERN (ippsSMS4DecryptOFB) EXTERN (ippsSMS4EncryptCTR) EXTERN (ippsSMS4DecryptCTR) EXTERN (ippsSMS4_CCMGetSize) EXTERN (ippsSMS4_CCMInit) EXTERN (ippsSMS4_CCMMessageLen) EXTERN (ippsSMS4_CCMTagLen) EXTERN (ippsSMS4_CCMStart) EXTERN (ippsSMS4_CCMEncrypt) EXTERN (ippsSMS4_CCMDecrypt) EXTERN (ippsSMS4_CCMGetTag) EXTERN (ippsAES_CCMGetSize) EXTERN (ippsAES_CCMInit) EXTERN (ippsAES_CCMMessageLen) EXTERN (ippsAES_CCMTagLen) EXTERN (ippsAES_CCMStart) EXTERN (ippsAES_CCMEncrypt) EXTERN (ippsAES_CCMDecrypt) EXTERN (ippsAES_CCMGetTag) EXTERN (ippsAES_GCMGetSize) EXTERN (ippsAES_GCMInit) EXTERN (ippsAES_GCMReinit) EXTERN (ippsAES_GCMReset) EXTERN (ippsAES_GCMProcessIV) EXTERN (ippsAES_GCMProcessAAD) EXTERN (ippsAES_GCMStart) EXTERN (ippsAES_GCMEncrypt) EXTERN (ippsAES_GCMDecrypt) EXTERN (ippsAES_GCMGetTag) EXTERN (ippsAES_XTSGetSize) EXTERN (ippsAES_XTSInit) EXTERN (ippsAES_XTSEncrypt) EXTERN (ippsAES_XTSDecrypt) EXTERN (ippsAES_S2V_CMAC) EXTERN (ippsAES_SIVEncrypt) EXTERN (ippsAES_SIVDecrypt) EXTERN (ippsAES_CMACGetSize) EXTERN (ippsAES_CMACInit) EXTERN (ippsAES_CMACUpdate) EXTERN (ippsAES_CMACFinal) EXTERN (ippsAES_CMACGetTag) EXTERN (ippsARCFourCheckKey) EXTERN (ippsARCFourGetSize) EXTERN (ippsARCFourInit) EXTERN (ippsARCFourReset) EXTERN (ippsARCFourPack) EXTERN (ippsARCFourUnpack) EXTERN (ippsARCFourEncrypt) EXTERN (ippsARCFourDecrypt) EXTERN (ippsHashGetSize) EXTERN (ippsHashInit) EXTERN (ippsHashPack) EXTERN (ippsHashUnpack) EXTERN (ippsHashDuplicate) EXTERN (ippsHashUpdate) EXTERN (ippsHashGetTag) EXTERN (ippsHashFinal) EXTERN (ippsHashMessage) EXTERN (ippsHashMethodGetSize) EXTERN (ippsHashMethodSet_MD5) EXTERN (ippsHashMethodSet_SM3) EXTERN (ippsHashMethodSet_SHA1) EXTERN (ippsHashMethodSet_SHA1_NI) EXTERN (ippsHashMethodSet_SHA1_TT) EXTERN (ippsHashMethodSet_SHA256) EXTERN (ippsHashMethodSet_SHA256_NI) EXTERN (ippsHashMethodSet_SHA256_TT) EXTERN (ippsHashMethodSet_SHA224) EXTERN (ippsHashMethodSet_SHA224_NI) EXTERN (ippsHashMethodSet_SHA224_TT) EXTERN (ippsHashMethodSet_SHA512) EXTERN (ippsHashMethodSet_SHA384) EXTERN (ippsHashMethodSet_SHA512_256) EXTERN (ippsHashMethodSet_SHA512_224) EXTERN (ippsHashStateMethodSet_SM3) EXTERN (ippsHashStateMethodSet_SHA256) EXTERN (ippsHashStateMethodSet_SHA256_NI) EXTERN (ippsHashStateMethodSet_SHA256_TT) EXTERN (ippsHashStateMethodSet_SHA224) EXTERN (ippsHashStateMethodSet_SHA224_NI) EXTERN (ippsHashStateMethodSet_SHA224_TT) EXTERN (ippsHashStateMethodSet_SHA512) EXTERN (ippsHashStateMethodSet_SHA384) EXTERN (ippsHashStateMethodSet_SHA512_256) EXTERN (ippsHashStateMethodSet_SHA512_224) EXTERN (ippsHashMethod_MD5) EXTERN (ippsHashMethod_SM3) EXTERN (ippsHashMethod_SHA1) EXTERN (ippsHashMethod_SHA1_NI) EXTERN (ippsHashMethod_SHA1_TT) EXTERN (ippsHashMethod_SHA256) EXTERN (ippsHashMethod_SHA256_NI) EXTERN (ippsHashMethod_SHA256_TT) EXTERN (ippsHashMethod_SHA224) EXTERN (ippsHashMethod_SHA224_NI) EXTERN (ippsHashMethod_SHA224_TT) EXTERN (ippsHashMethod_SHA512) EXTERN (ippsHashMethod_SHA384) EXTERN (ippsHashMethod_SHA512_256) EXTERN (ippsHashMethod_SHA512_224) EXTERN (ippsHashMethodGetInfo) EXTERN (ippsHashGetSize_rmf) EXTERN (ippsHashInit_rmf) EXTERN (ippsHashPack_rmf) EXTERN (ippsHashUnpack_rmf) EXTERN (ippsHashDuplicate_rmf) EXTERN (ippsHashUpdate_rmf) EXTERN (ippsHashGetTag_rmf) EXTERN (ippsHashFinal_rmf) EXTERN (ippsHashMessage_rmf) EXTERN (ippsHashGetInfo_rmf) EXTERN (ippsMGF) EXTERN (ippsMGF1_rmf) EXTERN (ippsMGF2_rmf) EXTERN (ippsHMAC_GetSize) EXTERN (ippsHMAC_Init) EXTERN (ippsHMAC_Pack) EXTERN (ippsHMAC_Unpack) EXTERN (ippsHMAC_Duplicate) EXTERN (ippsHMAC_Update) EXTERN (ippsHMAC_Final) EXTERN (ippsHMAC_GetTag) EXTERN (ippsHMAC_Message) EXTERN (ippsHMACGetSize_rmf) EXTERN (ippsHMACInit_rmf) EXTERN (ippsHMACPack_rmf) EXTERN (ippsHMACUnpack_rmf) EXTERN (ippsHMACDuplicate_rmf) EXTERN (ippsHMACUpdate_rmf) EXTERN (ippsHMACFinal_rmf) EXTERN (ippsHMACGetTag_rmf) EXTERN (ippsHMACMessage_rmf) EXTERN (ippsBigNumGetSize) EXTERN (ippsBigNumInit) EXTERN (ippsCmpZero_BN) EXTERN (ippsCmp_BN) EXTERN (ippsGetSize_BN) EXTERN (ippsSet_BN) EXTERN (ippsGet_BN) EXTERN (ippsRef_BN) EXTERN (ippsExtGet_BN) EXTERN (ippsAdd_BN) EXTERN (ippsSub_BN) EXTERN (ippsMul_BN) EXTERN (ippsMAC_BN_I) EXTERN (ippsDiv_BN) EXTERN (ippsMod_BN) EXTERN (ippsGcd_BN) EXTERN (ippsModInv_BN) EXTERN (ippsSetOctString_BN) EXTERN (ippsGetOctString_BN) EXTERN (ippsMontGetSize) EXTERN (ippsMontInit) EXTERN (ippsMontSet) EXTERN (ippsMontGet) EXTERN (ippsMontForm) EXTERN (ippsMontMul) EXTERN (ippsMontExp) EXTERN (ippsPRNGGetSize) EXTERN (ippsPRNGInit) EXTERN (ippsPRNGSetModulus) EXTERN (ippsPRNGSetH0) EXTERN (ippsPRNGSetAugment) EXTERN (ippsPRNGSetSeed) EXTERN (ippsPRNGGetSeed) EXTERN (ippsPRNGen) EXTERN (ippsPRNGen_BN) EXTERN (ippsPRNGenRDRAND) EXTERN (ippsPRNGenRDRAND_BN) EXTERN (ippsTRNGenRDSEED) EXTERN (ippsTRNGenRDSEED_BN) EXTERN (ippsPrimeGetSize) EXTERN (ippsPrimeInit) EXTERN (ippsPrimeGen) EXTERN (ippsPrimeTest) EXTERN (ippsPrimeGen_BN) EXTERN (ippsPrimeTest_BN) EXTERN (ippsPrimeGet) EXTERN (ippsPrimeGet_BN) EXTERN (ippsPrimeSet) EXTERN (ippsPrimeSet_BN) EXTERN (ippsRSA_GetSizePublicKey) EXTERN (ippsRSA_InitPublicKey) EXTERN (ippsRSA_SetPublicKey) EXTERN (ippsRSA_GetPublicKey) EXTERN (ippsRSA_GetSizePrivateKeyType1) EXTERN (ippsRSA_InitPrivateKeyType1) EXTERN (ippsRSA_SetPrivateKeyType1) EXTERN (ippsRSA_GetPrivateKeyType1) EXTERN (ippsRSA_GetSizePrivateKeyType2) EXTERN (ippsRSA_InitPrivateKeyType2) EXTERN (ippsRSA_SetPrivateKeyType2) EXTERN (ippsRSA_GetPrivateKeyType2) EXTERN (ippsRSA_GetBufferSizePublicKey) EXTERN (ippsRSA_GetBufferSizePrivateKey) EXTERN (ippsRSA_Encrypt) EXTERN (ippsRSA_Decrypt) EXTERN (ippsRSA_GenerateKeys) EXTERN (ippsRSA_ValidateKeys) EXTERN (ippsRSAEncrypt_OAEP) EXTERN (ippsRSADecrypt_OAEP) EXTERN (ippsRSAEncrypt_OAEP_rmf) EXTERN (ippsRSADecrypt_OAEP_rmf) EXTERN (ippsRSAEncrypt_PKCSv15) EXTERN (ippsRSADecrypt_PKCSv15) EXTERN (ippsRSASign_PSS) EXTERN (ippsRSAVerify_PSS) EXTERN (ippsRSASign_PSS_rmf) EXTERN (ippsRSAVerify_PSS_rmf) EXTERN (ippsRSASign_PKCS1v15) EXTERN (ippsRSAVerify_PKCS1v15) EXTERN (ippsRSASign_PKCS1v15_rmf) EXTERN (ippsRSAVerify_PKCS1v15_rmf) EXTERN (ippsDLGetResultString) EXTERN (ippsDLPGetSize) EXTERN (ippsDLPInit) EXTERN (ippsDLPPack) EXTERN (ippsDLPUnpack) EXTERN (ippsDLPSet) EXTERN (ippsDLPGet) EXTERN (ippsDLPSetDP) EXTERN (ippsDLPGetDP) EXTERN (ippsDLPGenKeyPair) EXTERN (ippsDLPPublicKey) EXTERN (ippsDLPValidateKeyPair) EXTERN (ippsDLPSetKeyPair) EXTERN (ippsDLPSignDSA) EXTERN (ippsDLPVerifyDSA) EXTERN (ippsDLPSharedSecretDH) EXTERN (ippsDLPGenerateDSA) EXTERN (ippsDLPValidateDSA) EXTERN (ippsDLPGenerateDH) EXTERN (ippsDLPValidateDH) EXTERN (ippsECCGetResultString) EXTERN (ippsGFpGetSize) EXTERN (ippsGFpInitArbitrary) EXTERN (ippsGFpInitFixed) EXTERN (ippsGFpInit) EXTERN (ippsGFpMethod_p192r1) EXTERN (ippsGFpMethod_p224r1) EXTERN (ippsGFpMethod_p256r1) EXTERN (ippsGFpMethod_p384r1) EXTERN (ippsGFpMethod_p521r1) EXTERN (ippsGFpMethod_p256sm2) EXTERN (ippsGFpMethod_p256bn) EXTERN (ippsGFpMethod_p256) EXTERN (ippsGFpMethod_pArb) EXTERN (ippsGFpxGetSize) EXTERN (ippsGFpxInit) EXTERN (ippsGFpxInitBinomial) EXTERN (ippsGFpxMethod_binom2_epid2) EXTERN (ippsGFpxMethod_binom3_epid2) EXTERN (ippsGFpxMethod_binom2) EXTERN (ippsGFpxMethod_binom3) EXTERN (ippsGFpxMethod_binom) EXTERN (ippsGFpxMethod_com) EXTERN (ippsGFpScratchBufferSize) EXTERN (ippsGFpElementGetSize) EXTERN (ippsGFpElementInit) EXTERN (ippsGFpSetElement) EXTERN (ippsGFpSetElementRegular) EXTERN (ippsGFpSetElementOctString) EXTERN (ippsGFpSetElementRandom) EXTERN (ippsGFpSetElementHash) EXTERN (ippsGFpSetElementHash_rmf) EXTERN (ippsGFpCpyElement) EXTERN (ippsGFpGetElement) EXTERN (ippsGFpGetElementOctString) EXTERN (ippsGFpCmpElement) EXTERN (ippsGFpIsZeroElement) EXTERN (ippsGFpIsUnityElement) EXTERN (ippsGFpConj) EXTERN (ippsGFpNeg) EXTERN (ippsGFpInv) EXTERN (ippsGFpSqrt) EXTERN (ippsGFpSqr) EXTERN (ippsGFpAdd) EXTERN (ippsGFpSub) EXTERN (ippsGFpMul) EXTERN (ippsGFpExp) EXTERN (ippsGFpMultiExp) EXTERN (ippsGFpAdd_PE) EXTERN (ippsGFpSub_PE) EXTERN (ippsGFpMul_PE) EXTERN (ippsGFpGetInfo) EXTERN (ippsGFpECGetSize) EXTERN (ippsGFpECInit) EXTERN (ippsGFpECSet) EXTERN (ippsGFpECSetSubgroup) EXTERN (ippsGFpECInitStd128r1) EXTERN (ippsGFpECInitStd128r2) EXTERN (ippsGFpECInitStd192r1) EXTERN (ippsGFpECInitStd224r1) EXTERN (ippsGFpECInitStd256r1) EXTERN (ippsGFpECInitStd384r1) EXTERN (ippsGFpECInitStd521r1) EXTERN (ippsGFpECInitStdSM2) EXTERN (ippsGFpECInitStdBN256) EXTERN (ippsGFpECBindGxyTblStd192r1) EXTERN (ippsGFpECBindGxyTblStd224r1) EXTERN (ippsGFpECBindGxyTblStd256r1) EXTERN (ippsGFpECBindGxyTblStd384r1) EXTERN (ippsGFpECBindGxyTblStd521r1) EXTERN (ippsGFpECBindGxyTblStdSM2) EXTERN (ippsGFpECGet) EXTERN (ippsGFpECGetInfo_GF) EXTERN (ippsGFpECGetSubgroup) EXTERN (ippsGFpECScratchBufferSize) EXTERN (ippsGFpECVerify) EXTERN (ippsGFpECPointGetSize) EXTERN (ippsGFpECPointInit) EXTERN (ippsGFpECSetPointAtInfinity) EXTERN (ippsGFpECSetPoint) EXTERN (ippsGFpECSetPointRegular) EXTERN (ippsGFpECSetPointRandom) EXTERN (ippsGFpECMakePoint) EXTERN (ippsGFpECSetPointHash) EXTERN (ippsGFpECSetPointHash_rmf) EXTERN (ippsGFpECSetPointHashBackCompatible) EXTERN (ippsGFpECSetPointHashBackCompatible_rmf) EXTERN (ippsGFpECGetPoint) EXTERN (ippsGFpECGetPointRegular) EXTERN (ippsGFpECTstPoint) EXTERN (ippsGFpECTstPointInSubgroup) EXTERN (ippsGFpECCpyPoint) EXTERN (ippsGFpECCmpPoint) EXTERN (ippsGFpECNegPoint) EXTERN (ippsGFpECAddPoint) EXTERN (ippsGFpECMulPoint) EXTERN (ippsGFpECPrivateKey) EXTERN (ippsGFpECPublicKey) EXTERN (ippsGFpECTstKeyPair) EXTERN (ippsGFpECSharedSecretDH) EXTERN (ippsGFpECSharedSecretDHC) EXTERN (ippsGFpECSignDSA) EXTERN (ippsGFpECVerifyDSA) EXTERN (ippsGFpECSignNR) EXTERN (ippsGFpECVerifyNR) EXTERN (ippsGFpECSignSM2) EXTERN (ippsGFpECVerifySM2) EXTERN (ippsGFpECUserIDHashSM2) EXTERN (ippsGFpECMessageRepresentationSM2) EXTERN (ippsGFpECKeyExchangeSM2_GetSize) EXTERN (ippsGFpECKeyExchangeSM2_Init) EXTERN (ippsGFpECKeyExchangeSM2_Setup) EXTERN (ippsGFpECKeyExchangeSM2_SharedKey) EXTERN (ippsGFpECKeyExchangeSM2_Confirm) EXTERN (ippsGFpECEncryptSM2_Ext_EncMsgSize) EXTERN (ippsGFpECEncryptSM2_Ext) EXTERN (ippsGFpECDecryptSM2_Ext_DecMsgSize) EXTERN (ippsGFpECDecryptSM2_Ext) EXTERN (ippsGFpECESGetSize_SM2) EXTERN (ippsGFpECESInit_SM2) EXTERN (ippsGFpECESSetKey_SM2) EXTERN (ippsGFpECESStart_SM2) EXTERN (ippsGFpECESEncrypt_SM2) EXTERN (ippsGFpECESDecrypt_SM2) EXTERN (ippsGFpECESFinal_SM2) EXTERN (ippsGFpECESGetBuffersSize_SM2) EXTERN (ippsGFpECSetPointOctString) EXTERN (ippsGFpECGetPointOctString) EXTERN (ippsXMSSVerify) EXTERN (ippsXMSSSetPublicKeyState) EXTERN (ippsXMSSSetSignatureState) EXTERN (ippsXMSSSignatureStateGetSize) EXTERN (ippsXMSSPublicKeyStateGetSize) EXTERN (ippsXMSSBufferGetSize) EXTERN (ippsLMSBufferGetSize) EXTERN (ippsLMSSignatureStateGetSize) EXTERN (ippsLMSPublicKeyStateGetSize) EXTERN (ippsLMSSetPublicKeyState) EXTERN (ippsLMSSetSignatureState) EXTERN (ippsLMSVerify) VERSION { { global: ippcpInit; cpGetReg; cpStartTscp; cpStopTscp; cpStartTsc; cpStopTsc; cpGetCacheSize; cpGetFeature; ippcpSetCpuFeatures; ippcpGetCpuFeatures; ippcpGetCpuClocks; ippcpSetNumThreads; ippcpGetNumThreads; ippcpGetEnabledCpuFeatures; ippcpGetEnabledNumThreads; ippcpGetStatusString; ippcpGetLibVersion; cryptoGetLibVersion; ippsDESGetSize; ippsDESInit; ippsDESPack; ippsDESUnpack; ippsTDESEncryptECB; ippsTDESDecryptECB; ippsTDESEncryptCBC; ippsTDESDecryptCBC; ippsTDESEncryptCFB; ippsTDESDecryptCFB; ippsTDESEncryptOFB; ippsTDESDecryptOFB; ippsTDESEncryptCTR; ippsTDESDecryptCTR; ippsAESGetSize; ippsAESInit; ippsAESSetKey; ippsAESPack; ippsAESUnpack; ippsAESSetupNoise; ippsAES_GCMSetupNoise; ippsAES_CMACSetupNoise; ippsAESEncryptECB; ippsAESDecryptECB; ippsAESEncryptCBC; ippsAESEncryptCBC_CS1; ippsAESEncryptCBC_CS2; ippsAESEncryptCBC_CS3; ippsAESDecryptCBC; ippsAESDecryptCBC_CS1; ippsAESDecryptCBC_CS2; ippsAESDecryptCBC_CS3; ippsAESEncryptCFB; ippsAESDecryptCFB; ippsAESEncryptOFB; ippsAESDecryptOFB; ippsAESEncryptCTR; ippsAESDecryptCTR; ippsAESEncryptXTS_Direct; ippsAESDecryptXTS_Direct; ippsAES_EncryptCFB16_MB; ippsSMS4GetSize; ippsSMS4Init; ippsSMS4SetKey; ippsSMS4EncryptECB; ippsSMS4DecryptECB; ippsSMS4EncryptCBC; ippsSMS4EncryptCBC_CS1; ippsSMS4EncryptCBC_CS2; ippsSMS4EncryptCBC_CS3; ippsSMS4DecryptCBC; ippsSMS4DecryptCBC_CS1; ippsSMS4DecryptCBC_CS2; ippsSMS4DecryptCBC_CS3; ippsSMS4EncryptCFB; ippsSMS4DecryptCFB; ippsSMS4EncryptOFB; ippsSMS4DecryptOFB; ippsSMS4EncryptCTR; ippsSMS4DecryptCTR; ippsSMS4_CCMGetSize; ippsSMS4_CCMInit; ippsSMS4_CCMMessageLen; ippsSMS4_CCMTagLen; ippsSMS4_CCMStart; ippsSMS4_CCMEncrypt; ippsSMS4_CCMDecrypt; ippsSMS4_CCMGetTag; ippsAES_CCMGetSize; ippsAES_CCMInit; ippsAES_CCMMessageLen; ippsAES_CCMTagLen; ippsAES_CCMStart; ippsAES_CCMEncrypt; ippsAES_CCMDecrypt; ippsAES_CCMGetTag; ippsAES_GCMGetSize; ippsAES_GCMInit; ippsAES_GCMReinit; ippsAES_GCMReset; ippsAES_GCMProcessIV; ippsAES_GCMProcessAAD; ippsAES_GCMStart; ippsAES_GCMEncrypt; ippsAES_GCMDecrypt; ippsAES_GCMGetTag; ippsAES_XTSGetSize; ippsAES_XTSInit; ippsAES_XTSEncrypt; ippsAES_XTSDecrypt; ippsAES_S2V_CMAC; ippsAES_SIVEncrypt; ippsAES_SIVDecrypt; ippsAES_CMACGetSize; ippsAES_CMACInit; ippsAES_CMACUpdate; ippsAES_CMACFinal; ippsAES_CMACGetTag; ippsARCFourCheckKey; ippsARCFourGetSize; ippsARCFourInit; ippsARCFourReset; ippsARCFourPack; ippsARCFourUnpack; ippsARCFourEncrypt; ippsARCFourDecrypt; ippsHashGetSize; ippsHashInit; ippsHashPack; ippsHashUnpack; ippsHashDuplicate; ippsHashUpdate; ippsHashGetTag; ippsHashFinal; ippsHashMessage; ippsHashMethodGetSize; ippsHashMethodSet_MD5; ippsHashMethodSet_SM3; ippsHashMethodSet_SHA1; ippsHashMethodSet_SHA1_NI; ippsHashMethodSet_SHA1_TT; ippsHashMethodSet_SHA256; ippsHashMethodSet_SHA256_NI; ippsHashMethodSet_SHA256_TT; ippsHashMethodSet_SHA224; ippsHashMethodSet_SHA224_NI; ippsHashMethodSet_SHA224_TT; ippsHashMethodSet_SHA512; ippsHashMethodSet_SHA384; ippsHashMethodSet_SHA512_256; ippsHashMethodSet_SHA512_224; ippsHashStateMethodSet_SM3; ippsHashStateMethodSet_SHA256; ippsHashStateMethodSet_SHA256_NI; ippsHashStateMethodSet_SHA256_TT; ippsHashStateMethodSet_SHA224; ippsHashStateMethodSet_SHA224_NI; ippsHashStateMethodSet_SHA224_TT; ippsHashStateMethodSet_SHA512; ippsHashStateMethodSet_SHA384; ippsHashStateMethodSet_SHA512_256; ippsHashStateMethodSet_SHA512_224; ippsHashMethod_MD5; ippsHashMethod_SM3; ippsHashMethod_SHA1; ippsHashMethod_SHA1_NI; ippsHashMethod_SHA1_TT; ippsHashMethod_SHA256; ippsHashMethod_SHA256_NI; ippsHashMethod_SHA256_TT; ippsHashMethod_SHA224; ippsHashMethod_SHA224_NI; ippsHashMethod_SHA224_TT; ippsHashMethod_SHA512; ippsHashMethod_SHA384; ippsHashMethod_SHA512_256; ippsHashMethod_SHA512_224; ippsHashMethodGetInfo; ippsHashGetSize_rmf; ippsHashInit_rmf; ippsHashPack_rmf; ippsHashUnpack_rmf; ippsHashDuplicate_rmf; ippsHashUpdate_rmf; ippsHashGetTag_rmf; ippsHashFinal_rmf; ippsHashMessage_rmf; ippsHashGetInfo_rmf; ippsMGF; ippsMGF1_rmf; ippsMGF2_rmf; ippsHMAC_GetSize; ippsHMAC_Init; ippsHMAC_Pack; ippsHMAC_Unpack; ippsHMAC_Duplicate; ippsHMAC_Update; ippsHMAC_Final; ippsHMAC_GetTag; ippsHMAC_Message; ippsHMACGetSize_rmf; ippsHMACInit_rmf; ippsHMACPack_rmf; ippsHMACUnpack_rmf; ippsHMACDuplicate_rmf; ippsHMACUpdate_rmf; ippsHMACFinal_rmf; ippsHMACGetTag_rmf; ippsHMACMessage_rmf; ippsBigNumGetSize; ippsBigNumInit; ippsCmpZero_BN; ippsCmp_BN; ippsGetSize_BN; ippsSet_BN; ippsGet_BN; ippsRef_BN; ippsExtGet_BN; ippsAdd_BN; ippsSub_BN; ippsMul_BN; ippsMAC_BN_I; ippsDiv_BN; ippsMod_BN; ippsGcd_BN; ippsModInv_BN; ippsSetOctString_BN; ippsGetOctString_BN; ippsMontGetSize; ippsMontInit; ippsMontSet; ippsMontGet; ippsMontForm; ippsMontMul; ippsMontExp; ippsPRNGGetSize; ippsPRNGInit; ippsPRNGSetModulus; ippsPRNGSetH0; ippsPRNGSetAugment; ippsPRNGSetSeed; ippsPRNGGetSeed; ippsPRNGen; ippsPRNGen_BN; ippsPRNGenRDRAND; ippsPRNGenRDRAND_BN; ippsTRNGenRDSEED; ippsTRNGenRDSEED_BN; ippsPrimeGetSize; ippsPrimeInit; ippsPrimeGen; ippsPrimeTest; ippsPrimeGen_BN; ippsPrimeTest_BN; ippsPrimeGet; ippsPrimeGet_BN; ippsPrimeSet; ippsPrimeSet_BN; ippsRSA_GetSizePublicKey; ippsRSA_InitPublicKey; ippsRSA_SetPublicKey; ippsRSA_GetPublicKey; ippsRSA_GetSizePrivateKeyType1; ippsRSA_InitPrivateKeyType1; ippsRSA_SetPrivateKeyType1; ippsRSA_GetPrivateKeyType1; ippsRSA_GetSizePrivateKeyType2; ippsRSA_InitPrivateKeyType2; ippsRSA_SetPrivateKeyType2; ippsRSA_GetPrivateKeyType2; ippsRSA_GetBufferSizePublicKey; ippsRSA_GetBufferSizePrivateKey; ippsRSA_Encrypt; ippsRSA_Decrypt; ippsRSA_GenerateKeys; ippsRSA_ValidateKeys; ippsRSAEncrypt_OAEP; ippsRSADecrypt_OAEP; ippsRSAEncrypt_OAEP_rmf; ippsRSADecrypt_OAEP_rmf; ippsRSAEncrypt_PKCSv15; ippsRSADecrypt_PKCSv15; ippsRSASign_PSS; ippsRSAVerify_PSS; ippsRSASign_PSS_rmf; ippsRSAVerify_PSS_rmf; ippsRSASign_PKCS1v15; ippsRSAVerify_PKCS1v15; ippsRSASign_PKCS1v15_rmf; ippsRSAVerify_PKCS1v15_rmf; ippsDLGetResultString; ippsDLPGetSize; ippsDLPInit; ippsDLPPack; ippsDLPUnpack; ippsDLPSet; ippsDLPGet; ippsDLPSetDP; ippsDLPGetDP; ippsDLPGenKeyPair; ippsDLPPublicKey; ippsDLPValidateKeyPair; ippsDLPSetKeyPair; ippsDLPSignDSA; ippsDLPVerifyDSA; ippsDLPSharedSecretDH; ippsDLPGenerateDSA; ippsDLPValidateDSA; ippsDLPGenerateDH; ippsDLPValidateDH; ippsECCGetResultString; ippsGFpGetSize; ippsGFpInitArbitrary; ippsGFpInitFixed; ippsGFpInit; ippsGFpMethod_p192r1; ippsGFpMethod_p224r1; ippsGFpMethod_p256r1; ippsGFpMethod_p384r1; ippsGFpMethod_p521r1; ippsGFpMethod_p256sm2; ippsGFpMethod_p256bn; ippsGFpMethod_p256; ippsGFpMethod_pArb; ippsGFpxGetSize; ippsGFpxInit; ippsGFpxInitBinomial; ippsGFpxMethod_binom2_epid2; ippsGFpxMethod_binom3_epid2; ippsGFpxMethod_binom2; ippsGFpxMethod_binom3; ippsGFpxMethod_binom; ippsGFpxMethod_com; ippsGFpScratchBufferSize; ippsGFpElementGetSize; ippsGFpElementInit; ippsGFpSetElement; ippsGFpSetElementRegular; ippsGFpSetElementOctString; ippsGFpSetElementRandom; ippsGFpSetElementHash; ippsGFpSetElementHash_rmf; ippsGFpCpyElement; ippsGFpGetElement; ippsGFpGetElementOctString; ippsGFpCmpElement; ippsGFpIsZeroElement; ippsGFpIsUnityElement; ippsGFpConj; ippsGFpNeg; ippsGFpInv; ippsGFpSqrt; ippsGFpSqr; ippsGFpAdd; ippsGFpSub; ippsGFpMul; ippsGFpExp; ippsGFpMultiExp; ippsGFpAdd_PE; ippsGFpSub_PE; ippsGFpMul_PE; ippsGFpGetInfo; ippsGFpECGetSize; ippsGFpECInit; ippsGFpECSet; ippsGFpECSetSubgroup; ippsGFpECInitStd128r1; ippsGFpECInitStd128r2; ippsGFpECInitStd192r1; ippsGFpECInitStd224r1; ippsGFpECInitStd256r1; ippsGFpECInitStd384r1; ippsGFpECInitStd521r1; ippsGFpECInitStdSM2; ippsGFpECInitStdBN256; ippsGFpECBindGxyTblStd192r1; ippsGFpECBindGxyTblStd224r1; ippsGFpECBindGxyTblStd256r1; ippsGFpECBindGxyTblStd384r1; ippsGFpECBindGxyTblStd521r1; ippsGFpECBindGxyTblStdSM2; ippsGFpECGet; ippsGFpECGetInfo_GF; ippsGFpECGetSubgroup; ippsGFpECScratchBufferSize; ippsGFpECVerify; ippsGFpECPointGetSize; ippsGFpECPointInit; ippsGFpECSetPointAtInfinity; ippsGFpECSetPoint; ippsGFpECSetPointRegular; ippsGFpECSetPointRandom; ippsGFpECMakePoint; ippsGFpECSetPointHash; ippsGFpECSetPointHash_rmf; ippsGFpECSetPointHashBackCompatible; ippsGFpECSetPointHashBackCompatible_rmf; ippsGFpECGetPoint; ippsGFpECGetPointRegular; ippsGFpECTstPoint; ippsGFpECTstPointInSubgroup; ippsGFpECCpyPoint; ippsGFpECCmpPoint; ippsGFpECNegPoint; ippsGFpECAddPoint; ippsGFpECMulPoint; ippsGFpECPrivateKey; ippsGFpECPublicKey; ippsGFpECTstKeyPair; ippsGFpECSharedSecretDH; ippsGFpECSharedSecretDHC; ippsGFpECSignDSA; ippsGFpECVerifyDSA; ippsGFpECSignNR; ippsGFpECVerifyNR; ippsGFpECSignSM2; ippsGFpECVerifySM2; ippsGFpECUserIDHashSM2; ippsGFpECMessageRepresentationSM2; ippsGFpECKeyExchangeSM2_GetSize; ippsGFpECKeyExchangeSM2_Init; ippsGFpECKeyExchangeSM2_Setup; ippsGFpECKeyExchangeSM2_SharedKey; ippsGFpECKeyExchangeSM2_Confirm; ippsGFpECEncryptSM2_Ext_EncMsgSize; ippsGFpECEncryptSM2_Ext; ippsGFpECDecryptSM2_Ext_DecMsgSize; ippsGFpECDecryptSM2_Ext; ippsGFpECESGetSize_SM2; ippsGFpECESInit_SM2; ippsGFpECESSetKey_SM2; ippsGFpECESStart_SM2; ippsGFpECESEncrypt_SM2; ippsGFpECESDecrypt_SM2; ippsGFpECESFinal_SM2; ippsGFpECESGetBuffersSize_SM2; ippsGFpECSetPointOctString; ippsGFpECGetPointOctString; ippsXMSSVerify; ippsXMSSSetPublicKeyState; ippsXMSSSetSignatureState; ippsXMSSSignatureStateGetSize; ippsXMSSPublicKeyStateGetSize; ippsXMSSBufferGetSize; ippsLMSBufferGetSize; ippsLMSSignatureStateGetSize; ippsLMSPublicKeyStateGetSize; ippsLMSSetPublicKeyState; ippsLMSSetSignatureState; ippsLMSVerify; local: *; }; } cryptography-primitives-1.0.0/sources/ippcp/exports.linux.selftests-export000066400000000000000000000674021470420105600273610ustar00rootroot00000000000000EXTERN (ippcpInit) EXTERN (cpGetReg) EXTERN (cpStartTscp) EXTERN (cpStopTscp) EXTERN (cpStartTsc) EXTERN (cpStopTsc) EXTERN (cpGetCacheSize) EXTERN (cpGetFeature) EXTERN (ippcpSetCpuFeatures) EXTERN (ippcpGetCpuFeatures) EXTERN (ippcpGetCpuClocks) EXTERN (ippcpSetNumThreads) EXTERN (ippcpGetNumThreads) EXTERN (ippcpGetEnabledCpuFeatures) EXTERN (ippcpGetEnabledNumThreads) EXTERN (ippcpGetStatusString) EXTERN (ippcpGetLibVersion) EXTERN (cryptoGetLibVersion) EXTERN (ippsDESGetSize) EXTERN (ippsDESInit) EXTERN (ippsDESPack) EXTERN (ippsDESUnpack) EXTERN (ippsTDESEncryptECB) EXTERN (ippsTDESDecryptECB) EXTERN (ippsTDESEncryptCBC) EXTERN (ippsTDESDecryptCBC) EXTERN (ippsTDESEncryptCFB) EXTERN (ippsTDESDecryptCFB) EXTERN (ippsTDESEncryptOFB) EXTERN (ippsTDESDecryptOFB) EXTERN (ippsTDESEncryptCTR) EXTERN (ippsTDESDecryptCTR) EXTERN (ippsAESGetSize) EXTERN (ippsAESInit) EXTERN (ippsAESSetKey) EXTERN (ippsAESPack) EXTERN (ippsAESUnpack) EXTERN (ippsAESSetupNoise) EXTERN (ippsAES_GCMSetupNoise) EXTERN (ippsAES_CMACSetupNoise) EXTERN (ippsAESEncryptECB) EXTERN (ippsAESDecryptECB) EXTERN (ippsAESEncryptCBC) EXTERN (ippsAESEncryptCBC_CS1) EXTERN (ippsAESEncryptCBC_CS2) EXTERN (ippsAESEncryptCBC_CS3) EXTERN (ippsAESDecryptCBC) EXTERN (ippsAESDecryptCBC_CS1) EXTERN (ippsAESDecryptCBC_CS2) EXTERN (ippsAESDecryptCBC_CS3) EXTERN (ippsAESEncryptCFB) EXTERN (ippsAESDecryptCFB) EXTERN (ippsAESEncryptOFB) EXTERN (ippsAESDecryptOFB) EXTERN (ippsAESEncryptCTR) EXTERN (ippsAESDecryptCTR) EXTERN (ippsAESEncryptXTS_Direct) EXTERN (ippsAESDecryptXTS_Direct) EXTERN (ippsAES_EncryptCFB16_MB) EXTERN (ippsSMS4GetSize) EXTERN (ippsSMS4Init) EXTERN (ippsSMS4SetKey) EXTERN (ippsSMS4EncryptECB) EXTERN (ippsSMS4DecryptECB) EXTERN (ippsSMS4EncryptCBC) EXTERN (ippsSMS4EncryptCBC_CS1) EXTERN (ippsSMS4EncryptCBC_CS2) EXTERN (ippsSMS4EncryptCBC_CS3) EXTERN (ippsSMS4DecryptCBC) EXTERN (ippsSMS4DecryptCBC_CS1) EXTERN (ippsSMS4DecryptCBC_CS2) EXTERN (ippsSMS4DecryptCBC_CS3) EXTERN (ippsSMS4EncryptCFB) EXTERN (ippsSMS4DecryptCFB) EXTERN (ippsSMS4EncryptOFB) EXTERN (ippsSMS4DecryptOFB) EXTERN (ippsSMS4EncryptCTR) EXTERN (ippsSMS4DecryptCTR) EXTERN (ippsSMS4_CCMGetSize) EXTERN (ippsSMS4_CCMInit) EXTERN (ippsSMS4_CCMMessageLen) EXTERN (ippsSMS4_CCMTagLen) EXTERN (ippsSMS4_CCMStart) EXTERN (ippsSMS4_CCMEncrypt) EXTERN (ippsSMS4_CCMDecrypt) EXTERN (ippsSMS4_CCMGetTag) EXTERN (ippsAES_CCMGetSize) EXTERN (ippsAES_CCMInit) EXTERN (ippsAES_CCMMessageLen) EXTERN (ippsAES_CCMTagLen) EXTERN (ippsAES_CCMStart) EXTERN (ippsAES_CCMEncrypt) EXTERN (ippsAES_CCMDecrypt) EXTERN (ippsAES_CCMGetTag) EXTERN (ippsAES_GCMGetSize) EXTERN (ippsAES_GCMInit) EXTERN (ippsAES_GCMReinit) EXTERN (ippsAES_GCMReset) EXTERN (ippsAES_GCMProcessIV) EXTERN (ippsAES_GCMProcessAAD) EXTERN (ippsAES_GCMStart) EXTERN (ippsAES_GCMEncrypt) EXTERN (ippsAES_GCMDecrypt) EXTERN (ippsAES_GCMGetTag) EXTERN (ippsAES_XTSGetSize) EXTERN (ippsAES_XTSInit) EXTERN (ippsAES_XTSEncrypt) EXTERN (ippsAES_XTSDecrypt) EXTERN (ippsAES_S2V_CMAC) EXTERN (ippsAES_SIVEncrypt) EXTERN (ippsAES_SIVDecrypt) EXTERN (ippsAES_CMACGetSize) EXTERN (ippsAES_CMACInit) EXTERN (ippsAES_CMACUpdate) EXTERN (ippsAES_CMACFinal) EXTERN (ippsAES_CMACGetTag) EXTERN (ippsARCFourCheckKey) EXTERN (ippsARCFourGetSize) EXTERN (ippsARCFourInit) EXTERN (ippsARCFourReset) EXTERN (ippsARCFourPack) EXTERN (ippsARCFourUnpack) EXTERN (ippsARCFourEncrypt) EXTERN (ippsARCFourDecrypt) EXTERN (ippsHashGetSize) EXTERN (ippsHashInit) EXTERN (ippsHashPack) EXTERN (ippsHashUnpack) EXTERN (ippsHashDuplicate) EXTERN (ippsHashUpdate) EXTERN (ippsHashGetTag) EXTERN (ippsHashFinal) EXTERN (ippsHashMessage) EXTERN (ippsHashMethodGetSize) EXTERN (ippsHashMethodSet_MD5) EXTERN (ippsHashMethodSet_SM3) EXTERN (ippsHashMethodSet_SHA1) EXTERN (ippsHashMethodSet_SHA1_NI) EXTERN (ippsHashMethodSet_SHA1_TT) EXTERN (ippsHashMethodSet_SHA256) EXTERN (ippsHashMethodSet_SHA256_NI) EXTERN (ippsHashMethodSet_SHA256_TT) EXTERN (ippsHashMethodSet_SHA224) EXTERN (ippsHashMethodSet_SHA224_NI) EXTERN (ippsHashMethodSet_SHA224_TT) EXTERN (ippsHashMethodSet_SHA512) EXTERN (ippsHashMethodSet_SHA384) EXTERN (ippsHashMethodSet_SHA512_256) EXTERN (ippsHashMethodSet_SHA512_224) EXTERN (ippsHashStateMethodSet_SM3) EXTERN (ippsHashStateMethodSet_SHA256) EXTERN (ippsHashStateMethodSet_SHA256_NI) EXTERN (ippsHashStateMethodSet_SHA256_TT) EXTERN (ippsHashStateMethodSet_SHA224) EXTERN (ippsHashStateMethodSet_SHA224_NI) EXTERN (ippsHashStateMethodSet_SHA224_TT) EXTERN (ippsHashStateMethodSet_SHA512) EXTERN (ippsHashStateMethodSet_SHA384) EXTERN (ippsHashStateMethodSet_SHA512_256) EXTERN (ippsHashStateMethodSet_SHA512_224) EXTERN (ippsHashMethod_MD5) EXTERN (ippsHashMethod_SM3) EXTERN (ippsHashMethod_SHA1) EXTERN (ippsHashMethod_SHA1_NI) EXTERN (ippsHashMethod_SHA1_TT) EXTERN (ippsHashMethod_SHA256) EXTERN (ippsHashMethod_SHA256_NI) EXTERN (ippsHashMethod_SHA256_TT) EXTERN (ippsHashMethod_SHA224) EXTERN (ippsHashMethod_SHA224_NI) EXTERN (ippsHashMethod_SHA224_TT) EXTERN (ippsHashMethod_SHA512) EXTERN (ippsHashMethod_SHA384) EXTERN (ippsHashMethod_SHA512_256) EXTERN (ippsHashMethod_SHA512_224) EXTERN (ippsHashMethodGetInfo) EXTERN (ippsHashGetSize_rmf) EXTERN (ippsHashInit_rmf) EXTERN (ippsHashPack_rmf) EXTERN (ippsHashUnpack_rmf) EXTERN (ippsHashDuplicate_rmf) EXTERN (ippsHashUpdate_rmf) EXTERN (ippsHashGetTag_rmf) EXTERN (ippsHashFinal_rmf) EXTERN (ippsHashMessage_rmf) EXTERN (ippsHashGetInfo_rmf) EXTERN (ippsMGF) EXTERN (ippsMGF1_rmf) EXTERN (ippsMGF2_rmf) EXTERN (ippsHMAC_GetSize) EXTERN (ippsHMAC_Init) EXTERN (ippsHMAC_Pack) EXTERN (ippsHMAC_Unpack) EXTERN (ippsHMAC_Duplicate) EXTERN (ippsHMAC_Update) EXTERN (ippsHMAC_Final) EXTERN (ippsHMAC_GetTag) EXTERN (ippsHMAC_Message) EXTERN (ippsHMACGetSize_rmf) EXTERN (ippsHMACInit_rmf) EXTERN (ippsHMACPack_rmf) EXTERN (ippsHMACUnpack_rmf) EXTERN (ippsHMACDuplicate_rmf) EXTERN (ippsHMACUpdate_rmf) EXTERN (ippsHMACFinal_rmf) EXTERN (ippsHMACGetTag_rmf) EXTERN (ippsHMACMessage_rmf) EXTERN (ippsBigNumGetSize) EXTERN (ippsBigNumInit) EXTERN (ippsCmpZero_BN) EXTERN (ippsCmp_BN) EXTERN (ippsGetSize_BN) EXTERN (ippsSet_BN) EXTERN (ippsGet_BN) EXTERN (ippsRef_BN) EXTERN (ippsExtGet_BN) EXTERN (ippsAdd_BN) EXTERN (ippsSub_BN) EXTERN (ippsMul_BN) EXTERN (ippsMAC_BN_I) EXTERN (ippsDiv_BN) EXTERN (ippsMod_BN) EXTERN (ippsGcd_BN) EXTERN (ippsModInv_BN) EXTERN (ippsSetOctString_BN) EXTERN (ippsGetOctString_BN) EXTERN (ippsMontGetSize) EXTERN (ippsMontInit) EXTERN (ippsMontSet) EXTERN (ippsMontGet) EXTERN (ippsMontForm) EXTERN (ippsMontMul) EXTERN (ippsMontExp) EXTERN (ippsPRNGGetSize) EXTERN (ippsPRNGInit) EXTERN (ippsPRNGSetModulus) EXTERN (ippsPRNGSetH0) EXTERN (ippsPRNGSetAugment) EXTERN (ippsPRNGSetSeed) EXTERN (ippsPRNGGetSeed) EXTERN (ippsPRNGen) EXTERN (ippsPRNGen_BN) EXTERN (ippsPRNGenRDRAND) EXTERN (ippsPRNGenRDRAND_BN) EXTERN (ippsTRNGenRDSEED) EXTERN (ippsTRNGenRDSEED_BN) EXTERN (ippsPrimeGetSize) EXTERN (ippsPrimeInit) EXTERN (ippsPrimeGen) EXTERN (ippsPrimeTest) EXTERN (ippsPrimeGen_BN) EXTERN (ippsPrimeTest_BN) EXTERN (ippsPrimeGet) EXTERN (ippsPrimeGet_BN) EXTERN (ippsPrimeSet) EXTERN (ippsPrimeSet_BN) EXTERN (ippsRSA_GetSizePublicKey) EXTERN (ippsRSA_InitPublicKey) EXTERN (ippsRSA_SetPublicKey) EXTERN (ippsRSA_GetPublicKey) EXTERN (ippsRSA_GetSizePrivateKeyType1) EXTERN (ippsRSA_InitPrivateKeyType1) EXTERN (ippsRSA_SetPrivateKeyType1) EXTERN (ippsRSA_GetPrivateKeyType1) EXTERN (ippsRSA_GetSizePrivateKeyType2) EXTERN (ippsRSA_InitPrivateKeyType2) EXTERN (ippsRSA_SetPrivateKeyType2) EXTERN (ippsRSA_GetPrivateKeyType2) EXTERN (ippsRSA_GetBufferSizePublicKey) EXTERN (ippsRSA_GetBufferSizePrivateKey) EXTERN (ippsRSA_Encrypt) EXTERN (ippsRSA_Decrypt) EXTERN (ippsRSA_GenerateKeys) EXTERN (ippsRSA_ValidateKeys) EXTERN (ippsRSAEncrypt_OAEP) EXTERN (ippsRSADecrypt_OAEP) EXTERN (ippsRSAEncrypt_OAEP_rmf) EXTERN (ippsRSADecrypt_OAEP_rmf) EXTERN (ippsRSAEncrypt_PKCSv15) EXTERN (ippsRSADecrypt_PKCSv15) EXTERN (ippsRSASign_PSS) EXTERN (ippsRSAVerify_PSS) EXTERN (ippsRSASign_PSS_rmf) EXTERN (ippsRSAVerify_PSS_rmf) EXTERN (ippsRSASign_PKCS1v15) EXTERN (ippsRSAVerify_PKCS1v15) EXTERN (ippsRSASign_PKCS1v15_rmf) EXTERN (ippsRSAVerify_PKCS1v15_rmf) EXTERN (ippsDLGetResultString) EXTERN (ippsDLPGetSize) EXTERN (ippsDLPInit) EXTERN (ippsDLPPack) EXTERN (ippsDLPUnpack) EXTERN (ippsDLPSet) EXTERN (ippsDLPGet) EXTERN (ippsDLPSetDP) EXTERN (ippsDLPGetDP) EXTERN (ippsDLPGenKeyPair) EXTERN (ippsDLPPublicKey) EXTERN (ippsDLPValidateKeyPair) EXTERN (ippsDLPSetKeyPair) EXTERN (ippsDLPSignDSA) EXTERN (ippsDLPVerifyDSA) EXTERN (ippsDLPSharedSecretDH) EXTERN (ippsDLPGenerateDSA) EXTERN (ippsDLPValidateDSA) EXTERN (ippsDLPGenerateDH) EXTERN (ippsDLPValidateDH) EXTERN (ippsECCGetResultString) EXTERN (ippsGFpGetSize) EXTERN (ippsGFpInitArbitrary) EXTERN (ippsGFpInitFixed) EXTERN (ippsGFpInit) EXTERN (ippsGFpMethod_p192r1) EXTERN (ippsGFpMethod_p224r1) EXTERN (ippsGFpMethod_p256r1) EXTERN (ippsGFpMethod_p384r1) EXTERN (ippsGFpMethod_p521r1) EXTERN (ippsGFpMethod_p256sm2) EXTERN (ippsGFpMethod_p256bn) EXTERN (ippsGFpMethod_p256) EXTERN (ippsGFpMethod_pArb) EXTERN (ippsGFpxGetSize) EXTERN (ippsGFpxInit) EXTERN (ippsGFpxInitBinomial) EXTERN (ippsGFpxMethod_binom2_epid2) EXTERN (ippsGFpxMethod_binom3_epid2) EXTERN (ippsGFpxMethod_binom2) EXTERN (ippsGFpxMethod_binom3) EXTERN (ippsGFpxMethod_binom) EXTERN (ippsGFpxMethod_com) EXTERN (ippsGFpScratchBufferSize) EXTERN (ippsGFpElementGetSize) EXTERN (ippsGFpElementInit) EXTERN (ippsGFpSetElement) EXTERN (ippsGFpSetElementRegular) EXTERN (ippsGFpSetElementOctString) EXTERN (ippsGFpSetElementRandom) EXTERN (ippsGFpSetElementHash) EXTERN (ippsGFpSetElementHash_rmf) EXTERN (ippsGFpCpyElement) EXTERN (ippsGFpGetElement) EXTERN (ippsGFpGetElementOctString) EXTERN (ippsGFpCmpElement) EXTERN (ippsGFpIsZeroElement) EXTERN (ippsGFpIsUnityElement) EXTERN (ippsGFpConj) EXTERN (ippsGFpNeg) EXTERN (ippsGFpInv) EXTERN (ippsGFpSqrt) EXTERN (ippsGFpSqr) EXTERN (ippsGFpAdd) EXTERN (ippsGFpSub) EXTERN (ippsGFpMul) EXTERN (ippsGFpExp) EXTERN (ippsGFpMultiExp) EXTERN (ippsGFpAdd_PE) EXTERN (ippsGFpSub_PE) EXTERN (ippsGFpMul_PE) EXTERN (ippsGFpGetInfo) EXTERN (ippsGFpECGetSize) EXTERN (ippsGFpECInit) EXTERN (ippsGFpECSet) EXTERN (ippsGFpECSetSubgroup) EXTERN (ippsGFpECInitStd128r1) EXTERN (ippsGFpECInitStd128r2) EXTERN (ippsGFpECInitStd192r1) EXTERN (ippsGFpECInitStd224r1) EXTERN (ippsGFpECInitStd256r1) EXTERN (ippsGFpECInitStd384r1) EXTERN (ippsGFpECInitStd521r1) EXTERN (ippsGFpECInitStdSM2) EXTERN (ippsGFpECInitStdBN256) EXTERN (ippsGFpECBindGxyTblStd192r1) EXTERN (ippsGFpECBindGxyTblStd224r1) EXTERN (ippsGFpECBindGxyTblStd256r1) EXTERN (ippsGFpECBindGxyTblStd384r1) EXTERN (ippsGFpECBindGxyTblStd521r1) EXTERN (ippsGFpECBindGxyTblStdSM2) EXTERN (ippsGFpECGet) EXTERN (ippsGFpECGetInfo_GF) EXTERN (ippsGFpECGetSubgroup) EXTERN (ippsGFpECScratchBufferSize) EXTERN (ippsGFpECVerify) EXTERN (ippsGFpECPointGetSize) EXTERN (ippsGFpECPointInit) EXTERN (ippsGFpECSetPointAtInfinity) EXTERN (ippsGFpECSetPoint) EXTERN (ippsGFpECSetPointRegular) EXTERN (ippsGFpECSetPointRandom) EXTERN (ippsGFpECMakePoint) EXTERN (ippsGFpECSetPointHash) EXTERN (ippsGFpECSetPointHash_rmf) EXTERN (ippsGFpECSetPointHashBackCompatible) EXTERN (ippsGFpECSetPointHashBackCompatible_rmf) EXTERN (ippsGFpECGetPoint) EXTERN (ippsGFpECGetPointRegular) EXTERN (ippsGFpECTstPoint) EXTERN (ippsGFpECTstPointInSubgroup) EXTERN (ippsGFpECCpyPoint) EXTERN (ippsGFpECCmpPoint) EXTERN (ippsGFpECNegPoint) EXTERN (ippsGFpECAddPoint) EXTERN (ippsGFpECMulPoint) EXTERN (ippsGFpECPrivateKey) EXTERN (ippsGFpECPublicKey) EXTERN (ippsGFpECTstKeyPair) EXTERN (ippsGFpECSharedSecretDH) EXTERN (ippsGFpECSharedSecretDHC) EXTERN (ippsGFpECSignDSA) EXTERN (ippsGFpECVerifyDSA) EXTERN (ippsGFpECSignNR) EXTERN (ippsGFpECVerifyNR) EXTERN (ippsGFpECSignSM2) EXTERN (ippsGFpECVerifySM2) EXTERN (ippsGFpECUserIDHashSM2) EXTERN (ippsGFpECMessageRepresentationSM2) EXTERN (ippsGFpECKeyExchangeSM2_GetSize) EXTERN (ippsGFpECKeyExchangeSM2_Init) EXTERN (ippsGFpECKeyExchangeSM2_Setup) EXTERN (ippsGFpECKeyExchangeSM2_SharedKey) EXTERN (ippsGFpECKeyExchangeSM2_Confirm) EXTERN (ippsGFpECEncryptSM2_Ext_EncMsgSize) EXTERN (ippsGFpECEncryptSM2_Ext) EXTERN (ippsGFpECDecryptSM2_Ext_DecMsgSize) EXTERN (ippsGFpECDecryptSM2_Ext) EXTERN (ippsGFpECESGetSize_SM2) EXTERN (ippsGFpECESInit_SM2) EXTERN (ippsGFpECESSetKey_SM2) EXTERN (ippsGFpECESStart_SM2) EXTERN (ippsGFpECESEncrypt_SM2) EXTERN (ippsGFpECESDecrypt_SM2) EXTERN (ippsGFpECESFinal_SM2) EXTERN (ippsGFpECESGetBuffersSize_SM2) EXTERN (ippsGFpECSetPointOctString) EXTERN (ippsGFpECGetPointOctString) EXTERN (ippsXMSSVerify) EXTERN (ippsXMSSSetPublicKeyState) EXTERN (ippsXMSSSetSignatureState) EXTERN (ippsXMSSSignatureStateGetSize) EXTERN (ippsXMSSPublicKeyStateGetSize) EXTERN (ippsXMSSBufferGetSize) EXTERN (ippsLMSBufferGetSize) EXTERN (ippsLMSSignatureStateGetSize) EXTERN (ippsLMSPublicKeyStateGetSize) EXTERN (ippsLMSSetPublicKeyState) EXTERN (ippsLMSSetSignatureState) EXTERN (ippsLMSVerify) EXTERN (ippcp_is_fips_approved_func) EXTERN (fips_selftest_ippsAESEncryptDecrypt_get_size) EXTERN (fips_selftest_ippsAESEncryptCBC) EXTERN (fips_selftest_ippsAESDecryptCBC) EXTERN (fips_selftest_ippsAESEncryptCBC_CS1) EXTERN (fips_selftest_ippsAESEncryptCBC_CS2) EXTERN (fips_selftest_ippsAESEncryptCBC_CS3) EXTERN (fips_selftest_ippsAESDecryptCBC_CS1) EXTERN (fips_selftest_ippsAESDecryptCBC_CS2) EXTERN (fips_selftest_ippsAESDecryptCBC_CS3) EXTERN (fips_selftest_ippsAESEncryptCFB) EXTERN (fips_selftest_ippsAESDecryptCFB) EXTERN (fips_selftest_ippsAESEncryptOFB) EXTERN (fips_selftest_ippsAESDecryptOFB) EXTERN (fips_selftest_ippsAESEncryptCTR) EXTERN (fips_selftest_ippsAESDecryptCTR) EXTERN (fips_selftest_ippsAESEncryptDecryptCCM_get_size) EXTERN (fips_selftest_ippsAES_CCMEncrypt) EXTERN (fips_selftest_ippsAES_CCMDecrypt) EXTERN (fips_selftest_ippsAES_GCM_get_size) EXTERN (fips_selftest_ippsAES_GCMEncrypt) EXTERN (fips_selftest_ippsAES_GCMDecrypt) EXTERN (fips_selftest_ippsAES_CMAC_get_size) EXTERN (fips_selftest_ippsAES_CMACUpdate) EXTERN (fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys) EXTERN (fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size) EXTERN (fips_selftest_ippsRSAEncrypt_OAEP_rmf) EXTERN (fips_selftest_ippsRSADecrypt_OAEP_rmf) EXTERN (fips_selftest_ippsHash_rmf_get_size) EXTERN (fips_selftest_ippsHashUpdate_rmf) EXTERN (fips_selftest_ippsHashMessage_rmf) EXTERN (fips_selftest_ippsHMAC_rmf_get_size) EXTERN (fips_selftest_ippsHMACUpdate_rmf) EXTERN (fips_selftest_ippsHMACMessage_rmf) EXTERN (fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys) EXTERN (fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size) EXTERN (fips_selftest_ippsRSASign_PKCS1v15_rmf) EXTERN (fips_selftest_ippsRSAVerify_PKCS1v15_rmf) EXTERN (fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys) EXTERN (fips_selftest_ippsRSASignVerify_PSS_rmf_get_size) EXTERN (fips_selftest_ippsRSASign_PSS_rmf) EXTERN (fips_selftest_ippsRSAVerify_PSS_rmf) EXTERN (fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff) EXTERN (fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff) EXTERN (fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff) EXTERN (fips_selftest_ippsGFpECSignDSA) EXTERN (fips_selftest_ippsGFpECVerifyDSA) EXTERN (fips_selftest_ippsGFpECPublicKey) EXTERN (fips_selftest_ippsGFpECPrivateKey) EXTERN (fips_selftest_ippsRSA_GenerateKeys) EXTERN (fips_selftest_ippsGFpECSharedSecretDH) EXTERN (fips_selftest_ippsLMSVerify) EXTERN (fips_selftest_ippsLMSVerify_get_size) VERSION { { global: ippcpInit; cpGetReg; cpStartTscp; cpStopTscp; cpStartTsc; cpStopTsc; cpGetCacheSize; cpGetFeature; ippcpSetCpuFeatures; ippcpGetCpuFeatures; ippcpGetCpuClocks; ippcpSetNumThreads; ippcpGetNumThreads; ippcpGetEnabledCpuFeatures; ippcpGetEnabledNumThreads; ippcpGetStatusString; ippcpGetLibVersion; cryptoGetLibVersion; ippsDESGetSize; ippsDESInit; ippsDESPack; ippsDESUnpack; ippsTDESEncryptECB; ippsTDESDecryptECB; ippsTDESEncryptCBC; ippsTDESDecryptCBC; ippsTDESEncryptCFB; ippsTDESDecryptCFB; ippsTDESEncryptOFB; ippsTDESDecryptOFB; ippsTDESEncryptCTR; ippsTDESDecryptCTR; ippsAESGetSize; ippsAESInit; ippsAESSetKey; ippsAESPack; ippsAESUnpack; ippsAESSetupNoise; ippsAES_GCMSetupNoise; ippsAES_CMACSetupNoise; ippsAESEncryptECB; ippsAESDecryptECB; ippsAESEncryptCBC; ippsAESEncryptCBC_CS1; ippsAESEncryptCBC_CS2; ippsAESEncryptCBC_CS3; ippsAESDecryptCBC; ippsAESDecryptCBC_CS1; ippsAESDecryptCBC_CS2; ippsAESDecryptCBC_CS3; ippsAESEncryptCFB; ippsAESDecryptCFB; ippsAESEncryptOFB; ippsAESDecryptOFB; ippsAESEncryptCTR; ippsAESDecryptCTR; ippsAESEncryptXTS_Direct; ippsAESDecryptXTS_Direct; ippsAES_EncryptCFB16_MB; ippsSMS4GetSize; ippsSMS4Init; ippsSMS4SetKey; ippsSMS4EncryptECB; ippsSMS4DecryptECB; ippsSMS4EncryptCBC; ippsSMS4EncryptCBC_CS1; ippsSMS4EncryptCBC_CS2; ippsSMS4EncryptCBC_CS3; ippsSMS4DecryptCBC; ippsSMS4DecryptCBC_CS1; ippsSMS4DecryptCBC_CS2; ippsSMS4DecryptCBC_CS3; ippsSMS4EncryptCFB; ippsSMS4DecryptCFB; ippsSMS4EncryptOFB; ippsSMS4DecryptOFB; ippsSMS4EncryptCTR; ippsSMS4DecryptCTR; ippsSMS4_CCMGetSize; ippsSMS4_CCMInit; ippsSMS4_CCMMessageLen; ippsSMS4_CCMTagLen; ippsSMS4_CCMStart; ippsSMS4_CCMEncrypt; ippsSMS4_CCMDecrypt; ippsSMS4_CCMGetTag; ippsAES_CCMGetSize; ippsAES_CCMInit; ippsAES_CCMMessageLen; ippsAES_CCMTagLen; ippsAES_CCMStart; ippsAES_CCMEncrypt; ippsAES_CCMDecrypt; ippsAES_CCMGetTag; ippsAES_GCMGetSize; ippsAES_GCMInit; ippsAES_GCMReinit; ippsAES_GCMReset; ippsAES_GCMProcessIV; ippsAES_GCMProcessAAD; ippsAES_GCMStart; ippsAES_GCMEncrypt; ippsAES_GCMDecrypt; ippsAES_GCMGetTag; ippsAES_XTSGetSize; ippsAES_XTSInit; ippsAES_XTSEncrypt; ippsAES_XTSDecrypt; ippsAES_S2V_CMAC; ippsAES_SIVEncrypt; ippsAES_SIVDecrypt; ippsAES_CMACGetSize; ippsAES_CMACInit; ippsAES_CMACUpdate; ippsAES_CMACFinal; ippsAES_CMACGetTag; ippsARCFourCheckKey; ippsARCFourGetSize; ippsARCFourInit; ippsARCFourReset; ippsARCFourPack; ippsARCFourUnpack; ippsARCFourEncrypt; ippsARCFourDecrypt; ippsHashGetSize; ippsHashInit; ippsHashPack; ippsHashUnpack; ippsHashDuplicate; ippsHashUpdate; ippsHashGetTag; ippsHashFinal; ippsHashMessage; ippsHashMethodGetSize; ippsHashMethodSet_MD5; ippsHashMethodSet_SM3; ippsHashMethodSet_SHA1; ippsHashMethodSet_SHA1_NI; ippsHashMethodSet_SHA1_TT; ippsHashMethodSet_SHA256; ippsHashMethodSet_SHA256_NI; ippsHashMethodSet_SHA256_TT; ippsHashMethodSet_SHA224; ippsHashMethodSet_SHA224_NI; ippsHashMethodSet_SHA224_TT; ippsHashMethodSet_SHA512; ippsHashMethodSet_SHA384; ippsHashMethodSet_SHA512_256; ippsHashMethodSet_SHA512_224; ippsHashStateMethodSet_SM3; ippsHashStateMethodSet_SHA256; ippsHashStateMethodSet_SHA256_NI; ippsHashStateMethodSet_SHA256_TT; ippsHashStateMethodSet_SHA224; ippsHashStateMethodSet_SHA224_NI; ippsHashStateMethodSet_SHA224_TT; ippsHashStateMethodSet_SHA512; ippsHashStateMethodSet_SHA384; ippsHashStateMethodSet_SHA512_256; ippsHashStateMethodSet_SHA512_224; ippsHashMethod_MD5; ippsHashMethod_SM3; ippsHashMethod_SHA1; ippsHashMethod_SHA1_NI; ippsHashMethod_SHA1_TT; ippsHashMethod_SHA256; ippsHashMethod_SHA256_NI; ippsHashMethod_SHA256_TT; ippsHashMethod_SHA224; ippsHashMethod_SHA224_NI; ippsHashMethod_SHA224_TT; ippsHashMethod_SHA512; ippsHashMethod_SHA384; ippsHashMethod_SHA512_256; ippsHashMethod_SHA512_224; ippsHashMethodGetInfo; ippsHashGetSize_rmf; ippsHashInit_rmf; ippsHashPack_rmf; ippsHashUnpack_rmf; ippsHashDuplicate_rmf; ippsHashUpdate_rmf; ippsHashGetTag_rmf; ippsHashFinal_rmf; ippsHashMessage_rmf; ippsHashGetInfo_rmf; ippsMGF; ippsMGF1_rmf; ippsMGF2_rmf; ippsHMAC_GetSize; ippsHMAC_Init; ippsHMAC_Pack; ippsHMAC_Unpack; ippsHMAC_Duplicate; ippsHMAC_Update; ippsHMAC_Final; ippsHMAC_GetTag; ippsHMAC_Message; ippsHMACGetSize_rmf; ippsHMACInit_rmf; ippsHMACPack_rmf; ippsHMACUnpack_rmf; ippsHMACDuplicate_rmf; ippsHMACUpdate_rmf; ippsHMACFinal_rmf; ippsHMACGetTag_rmf; ippsHMACMessage_rmf; ippsBigNumGetSize; ippsBigNumInit; ippsCmpZero_BN; ippsCmp_BN; ippsGetSize_BN; ippsSet_BN; ippsGet_BN; ippsRef_BN; ippsExtGet_BN; ippsAdd_BN; ippsSub_BN; ippsMul_BN; ippsMAC_BN_I; ippsDiv_BN; ippsMod_BN; ippsGcd_BN; ippsModInv_BN; ippsSetOctString_BN; ippsGetOctString_BN; ippsMontGetSize; ippsMontInit; ippsMontSet; ippsMontGet; ippsMontForm; ippsMontMul; ippsMontExp; ippsPRNGGetSize; ippsPRNGInit; ippsPRNGSetModulus; ippsPRNGSetH0; ippsPRNGSetAugment; ippsPRNGSetSeed; ippsPRNGGetSeed; ippsPRNGen; ippsPRNGen_BN; ippsPRNGenRDRAND; ippsPRNGenRDRAND_BN; ippsTRNGenRDSEED; ippsTRNGenRDSEED_BN; ippsPrimeGetSize; ippsPrimeInit; ippsPrimeGen; ippsPrimeTest; ippsPrimeGen_BN; ippsPrimeTest_BN; ippsPrimeGet; ippsPrimeGet_BN; ippsPrimeSet; ippsPrimeSet_BN; ippsRSA_GetSizePublicKey; ippsRSA_InitPublicKey; ippsRSA_SetPublicKey; ippsRSA_GetPublicKey; ippsRSA_GetSizePrivateKeyType1; ippsRSA_InitPrivateKeyType1; ippsRSA_SetPrivateKeyType1; ippsRSA_GetPrivateKeyType1; ippsRSA_GetSizePrivateKeyType2; ippsRSA_InitPrivateKeyType2; ippsRSA_SetPrivateKeyType2; ippsRSA_GetPrivateKeyType2; ippsRSA_GetBufferSizePublicKey; ippsRSA_GetBufferSizePrivateKey; ippsRSA_Encrypt; ippsRSA_Decrypt; ippsRSA_GenerateKeys; ippsRSA_ValidateKeys; ippsRSAEncrypt_OAEP; ippsRSADecrypt_OAEP; ippsRSAEncrypt_OAEP_rmf; ippsRSADecrypt_OAEP_rmf; ippsRSAEncrypt_PKCSv15; ippsRSADecrypt_PKCSv15; ippsRSASign_PSS; ippsRSAVerify_PSS; ippsRSASign_PSS_rmf; ippsRSAVerify_PSS_rmf; ippsRSASign_PKCS1v15; ippsRSAVerify_PKCS1v15; ippsRSASign_PKCS1v15_rmf; ippsRSAVerify_PKCS1v15_rmf; ippsDLGetResultString; ippsDLPGetSize; ippsDLPInit; ippsDLPPack; ippsDLPUnpack; ippsDLPSet; ippsDLPGet; ippsDLPSetDP; ippsDLPGetDP; ippsDLPGenKeyPair; ippsDLPPublicKey; ippsDLPValidateKeyPair; ippsDLPSetKeyPair; ippsDLPSignDSA; ippsDLPVerifyDSA; ippsDLPSharedSecretDH; ippsDLPGenerateDSA; ippsDLPValidateDSA; ippsDLPGenerateDH; ippsDLPValidateDH; ippsECCGetResultString; ippsGFpGetSize; ippsGFpInitArbitrary; ippsGFpInitFixed; ippsGFpInit; ippsGFpMethod_p192r1; ippsGFpMethod_p224r1; ippsGFpMethod_p256r1; ippsGFpMethod_p384r1; ippsGFpMethod_p521r1; ippsGFpMethod_p256sm2; ippsGFpMethod_p256bn; ippsGFpMethod_p256; ippsGFpMethod_pArb; ippsGFpxGetSize; ippsGFpxInit; ippsGFpxInitBinomial; ippsGFpxMethod_binom2_epid2; ippsGFpxMethod_binom3_epid2; ippsGFpxMethod_binom2; ippsGFpxMethod_binom3; ippsGFpxMethod_binom; ippsGFpxMethod_com; ippsGFpScratchBufferSize; ippsGFpElementGetSize; ippsGFpElementInit; ippsGFpSetElement; ippsGFpSetElementRegular; ippsGFpSetElementOctString; ippsGFpSetElementRandom; ippsGFpSetElementHash; ippsGFpSetElementHash_rmf; ippsGFpCpyElement; ippsGFpGetElement; ippsGFpGetElementOctString; ippsGFpCmpElement; ippsGFpIsZeroElement; ippsGFpIsUnityElement; ippsGFpConj; ippsGFpNeg; ippsGFpInv; ippsGFpSqrt; ippsGFpSqr; ippsGFpAdd; ippsGFpSub; ippsGFpMul; ippsGFpExp; ippsGFpMultiExp; ippsGFpAdd_PE; ippsGFpSub_PE; ippsGFpMul_PE; ippsGFpGetInfo; ippsGFpECGetSize; ippsGFpECInit; ippsGFpECSet; ippsGFpECSetSubgroup; ippsGFpECInitStd128r1; ippsGFpECInitStd128r2; ippsGFpECInitStd192r1; ippsGFpECInitStd224r1; ippsGFpECInitStd256r1; ippsGFpECInitStd384r1; ippsGFpECInitStd521r1; ippsGFpECInitStdSM2; ippsGFpECInitStdBN256; ippsGFpECBindGxyTblStd192r1; ippsGFpECBindGxyTblStd224r1; ippsGFpECBindGxyTblStd256r1; ippsGFpECBindGxyTblStd384r1; ippsGFpECBindGxyTblStd521r1; ippsGFpECBindGxyTblStdSM2; ippsGFpECGet; ippsGFpECGetInfo_GF; ippsGFpECGetSubgroup; ippsGFpECScratchBufferSize; ippsGFpECVerify; ippsGFpECPointGetSize; ippsGFpECPointInit; ippsGFpECSetPointAtInfinity; ippsGFpECSetPoint; ippsGFpECSetPointRegular; ippsGFpECSetPointRandom; ippsGFpECMakePoint; ippsGFpECSetPointHash; ippsGFpECSetPointHash_rmf; ippsGFpECSetPointHashBackCompatible; ippsGFpECSetPointHashBackCompatible_rmf; ippsGFpECGetPoint; ippsGFpECGetPointRegular; ippsGFpECTstPoint; ippsGFpECTstPointInSubgroup; ippsGFpECCpyPoint; ippsGFpECCmpPoint; ippsGFpECNegPoint; ippsGFpECAddPoint; ippsGFpECMulPoint; ippsGFpECPrivateKey; ippsGFpECPublicKey; ippsGFpECTstKeyPair; ippsGFpECSharedSecretDH; ippsGFpECSharedSecretDHC; ippsGFpECSignDSA; ippsGFpECVerifyDSA; ippsGFpECSignNR; ippsGFpECVerifyNR; ippsGFpECSignSM2; ippsGFpECVerifySM2; ippsGFpECUserIDHashSM2; ippsGFpECMessageRepresentationSM2; ippsGFpECKeyExchangeSM2_GetSize; ippsGFpECKeyExchangeSM2_Init; ippsGFpECKeyExchangeSM2_Setup; ippsGFpECKeyExchangeSM2_SharedKey; ippsGFpECKeyExchangeSM2_Confirm; ippsGFpECEncryptSM2_Ext_EncMsgSize; ippsGFpECEncryptSM2_Ext; ippsGFpECDecryptSM2_Ext_DecMsgSize; ippsGFpECDecryptSM2_Ext; ippsGFpECESGetSize_SM2; ippsGFpECESInit_SM2; ippsGFpECESSetKey_SM2; ippsGFpECESStart_SM2; ippsGFpECESEncrypt_SM2; ippsGFpECESDecrypt_SM2; ippsGFpECESFinal_SM2; ippsGFpECESGetBuffersSize_SM2; ippsGFpECSetPointOctString; ippsGFpECGetPointOctString; ippsXMSSVerify; ippsXMSSSetPublicKeyState; ippsXMSSSetSignatureState; ippsXMSSSignatureStateGetSize; ippsXMSSPublicKeyStateGetSize; ippsXMSSBufferGetSize; ippsLMSBufferGetSize; ippsLMSSignatureStateGetSize; ippsLMSPublicKeyStateGetSize; ippsLMSSetPublicKeyState; ippsLMSSetSignatureState; ippsLMSVerify; ippcp_is_fips_approved_func; fips_selftest_ippsAESEncryptDecrypt_get_size; fips_selftest_ippsAESEncryptCBC; fips_selftest_ippsAESDecryptCBC; fips_selftest_ippsAESEncryptCBC_CS1; fips_selftest_ippsAESEncryptCBC_CS2; fips_selftest_ippsAESEncryptCBC_CS3; fips_selftest_ippsAESDecryptCBC_CS1; fips_selftest_ippsAESDecryptCBC_CS2; fips_selftest_ippsAESDecryptCBC_CS3; fips_selftest_ippsAESEncryptCFB; fips_selftest_ippsAESDecryptCFB; fips_selftest_ippsAESEncryptOFB; fips_selftest_ippsAESDecryptOFB; fips_selftest_ippsAESEncryptCTR; fips_selftest_ippsAESDecryptCTR; fips_selftest_ippsAESEncryptDecryptCCM_get_size; fips_selftest_ippsAES_CCMEncrypt; fips_selftest_ippsAES_CCMDecrypt; fips_selftest_ippsAES_GCM_get_size; fips_selftest_ippsAES_GCMEncrypt; fips_selftest_ippsAES_GCMDecrypt; fips_selftest_ippsAES_CMAC_get_size; fips_selftest_ippsAES_CMACUpdate; fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys; fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size; fips_selftest_ippsRSAEncrypt_OAEP_rmf; fips_selftest_ippsRSADecrypt_OAEP_rmf; fips_selftest_ippsHash_rmf_get_size; fips_selftest_ippsHashUpdate_rmf; fips_selftest_ippsHashMessage_rmf; fips_selftest_ippsHMAC_rmf_get_size; fips_selftest_ippsHMACUpdate_rmf; fips_selftest_ippsHMACMessage_rmf; fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys; fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size; fips_selftest_ippsRSASign_PKCS1v15_rmf; fips_selftest_ippsRSAVerify_PKCS1v15_rmf; fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys; fips_selftest_ippsRSASignVerify_PSS_rmf_get_size; fips_selftest_ippsRSASign_PSS_rmf; fips_selftest_ippsRSAVerify_PSS_rmf; fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff; fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff; fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff; fips_selftest_ippsGFpECSignDSA; fips_selftest_ippsGFpECVerifyDSA; fips_selftest_ippsGFpECPublicKey; fips_selftest_ippsGFpECPrivateKey; fips_selftest_ippsRSA_GenerateKeys; fips_selftest_ippsGFpECSharedSecretDH; fips_selftest_ippsLMSVerify_get_size; fips_selftest_ippsLMSVerify; local: *; }; } cryptography-primitives-1.0.0/sources/ippcp/exports.macosx.lib-export000066400000000000000000000222071470420105600262400ustar00rootroot00000000000000_ippcpInit _cpGetReg _cpStartTscp _cpStopTscp _cpStartTsc _cpStopTsc _cpGetCacheSize _cpGetFeature _ippcpSetCpuFeatures _ippcpGetCpuFeatures _ippcpGetCpuClocks _ippcpSetNumThreads _ippcpGetNumThreads _ippcpGetEnabledCpuFeatures _ippcpGetEnabledNumThreads _ippcpGetStatusString _ippcpGetLibVersion _cryptoGetLibVersion _ippsDESGetSize _ippsDESInit _ippsDESPack _ippsDESUnpack _ippsTDESEncryptECB _ippsTDESDecryptECB _ippsTDESEncryptCBC _ippsTDESDecryptCBC _ippsTDESEncryptCFB _ippsTDESDecryptCFB _ippsTDESEncryptOFB _ippsTDESDecryptOFB _ippsTDESEncryptCTR _ippsTDESDecryptCTR _ippsAESGetSize _ippsAESInit _ippsAESSetKey _ippsAESPack _ippsAESUnpack _ippsAESSetupNoise _ippsAES_GCMSetupNoise _ippsAES_CMACSetupNoise _ippsAESEncryptECB _ippsAESDecryptECB _ippsAESEncryptCBC _ippsAESEncryptCBC_CS1 _ippsAESEncryptCBC_CS2 _ippsAESEncryptCBC_CS3 _ippsAESDecryptCBC _ippsAESDecryptCBC_CS1 _ippsAESDecryptCBC_CS2 _ippsAESDecryptCBC_CS3 _ippsAESEncryptCFB _ippsAESDecryptCFB _ippsAESEncryptOFB _ippsAESDecryptOFB _ippsAESEncryptCTR _ippsAESDecryptCTR _ippsAESEncryptXTS_Direct _ippsAESDecryptXTS_Direct _ippsAES_EncryptCFB16_MB _ippsSMS4GetSize _ippsSMS4Init _ippsSMS4SetKey _ippsSMS4EncryptECB _ippsSMS4DecryptECB _ippsSMS4EncryptCBC _ippsSMS4EncryptCBC_CS1 _ippsSMS4EncryptCBC_CS2 _ippsSMS4EncryptCBC_CS3 _ippsSMS4DecryptCBC _ippsSMS4DecryptCBC_CS1 _ippsSMS4DecryptCBC_CS2 _ippsSMS4DecryptCBC_CS3 _ippsSMS4EncryptCFB _ippsSMS4DecryptCFB _ippsSMS4EncryptOFB _ippsSMS4DecryptOFB _ippsSMS4EncryptCTR _ippsSMS4DecryptCTR _ippsSMS4_CCMGetSize _ippsSMS4_CCMInit _ippsSMS4_CCMMessageLen _ippsSMS4_CCMTagLen _ippsSMS4_CCMStart _ippsSMS4_CCMEncrypt _ippsSMS4_CCMDecrypt _ippsSMS4_CCMGetTag _ippsAES_CCMGetSize _ippsAES_CCMInit _ippsAES_CCMMessageLen _ippsAES_CCMTagLen _ippsAES_CCMStart _ippsAES_CCMEncrypt _ippsAES_CCMDecrypt _ippsAES_CCMGetTag _ippsAES_GCMGetSize _ippsAES_GCMInit _ippsAES_GCMReinit _ippsAES_GCMReset _ippsAES_GCMProcessIV _ippsAES_GCMProcessAAD _ippsAES_GCMStart _ippsAES_GCMEncrypt _ippsAES_GCMDecrypt _ippsAES_GCMGetTag _ippsAES_XTSGetSize _ippsAES_XTSInit _ippsAES_XTSEncrypt _ippsAES_XTSDecrypt _ippsAES_S2V_CMAC _ippsAES_SIVEncrypt _ippsAES_SIVDecrypt _ippsAES_CMACGetSize _ippsAES_CMACInit _ippsAES_CMACUpdate _ippsAES_CMACFinal _ippsAES_CMACGetTag _ippsARCFourCheckKey _ippsARCFourGetSize _ippsARCFourInit _ippsARCFourReset _ippsARCFourPack _ippsARCFourUnpack _ippsARCFourEncrypt _ippsARCFourDecrypt _ippsHashGetSize _ippsHashInit _ippsHashPack _ippsHashUnpack _ippsHashDuplicate _ippsHashUpdate _ippsHashGetTag _ippsHashFinal _ippsHashMessage _ippsHashMethodGetSize _ippsHashMethodSet_MD5 _ippsHashMethodSet_SM3 _ippsHashMethodSet_SHA1 _ippsHashMethodSet_SHA1_NI _ippsHashMethodSet_SHA1_TT _ippsHashMethodSet_SHA256 _ippsHashMethodSet_SHA256_NI _ippsHashMethodSet_SHA256_TT _ippsHashMethodSet_SHA224 _ippsHashMethodSet_SHA224_NI _ippsHashMethodSet_SHA224_TT _ippsHashMethodSet_SHA512 _ippsHashMethodSet_SHA384 _ippsHashMethodSet_SHA512_256 _ippsHashMethodSet_SHA512_224 _ippsHashStateMethodSet_SM3 _ippsHashStateMethodSet_SHA256 _ippsHashStateMethodSet_SHA256_NI _ippsHashStateMethodSet_SHA256_TT _ippsHashStateMethodSet_SHA224 _ippsHashStateMethodSet_SHA224_NI _ippsHashStateMethodSet_SHA224_TT _ippsHashStateMethodSet_SHA512 _ippsHashStateMethodSet_SHA384 _ippsHashStateMethodSet_SHA512_256 _ippsHashStateMethodSet_SHA512_224 _ippsHashMethod_MD5 _ippsHashMethod_SM3 _ippsHashMethod_SHA1 _ippsHashMethod_SHA1_NI _ippsHashMethod_SHA1_TT _ippsHashMethod_SHA256 _ippsHashMethod_SHA256_NI _ippsHashMethod_SHA256_TT _ippsHashMethod_SHA224 _ippsHashMethod_SHA224_NI _ippsHashMethod_SHA224_TT _ippsHashMethod_SHA512 _ippsHashMethod_SHA384 _ippsHashMethod_SHA512_256 _ippsHashMethod_SHA512_224 _ippsHashMethodGetInfo _ippsHashGetSize_rmf _ippsHashInit_rmf _ippsHashPack_rmf _ippsHashUnpack_rmf _ippsHashDuplicate_rmf _ippsHashUpdate_rmf _ippsHashGetTag_rmf _ippsHashFinal_rmf _ippsHashMessage_rmf _ippsHashGetInfo_rmf _ippsMGF _ippsMGF1_rmf _ippsMGF2_rmf _ippsHMAC_GetSize _ippsHMAC_Init _ippsHMAC_Pack _ippsHMAC_Unpack _ippsHMAC_Duplicate _ippsHMAC_Update _ippsHMAC_Final _ippsHMAC_GetTag _ippsHMAC_Message _ippsHMACGetSize_rmf _ippsHMACInit_rmf _ippsHMACPack_rmf _ippsHMACUnpack_rmf _ippsHMACDuplicate_rmf _ippsHMACUpdate_rmf _ippsHMACFinal_rmf _ippsHMACGetTag_rmf _ippsHMACMessage_rmf _ippsBigNumGetSize _ippsBigNumInit _ippsCmpZero_BN _ippsCmp_BN _ippsGetSize_BN _ippsSet_BN _ippsGet_BN _ippsRef_BN _ippsExtGet_BN _ippsAdd_BN _ippsSub_BN _ippsMul_BN _ippsMAC_BN_I _ippsDiv_BN _ippsMod_BN _ippsGcd_BN _ippsModInv_BN _ippsSetOctString_BN _ippsGetOctString_BN _ippsMontGetSize _ippsMontInit _ippsMontSet _ippsMontGet _ippsMontForm _ippsMontMul _ippsMontExp _ippsPRNGGetSize _ippsPRNGInit _ippsPRNGSetModulus _ippsPRNGSetH0 _ippsPRNGSetAugment _ippsPRNGSetSeed _ippsPRNGGetSeed _ippsPRNGen _ippsPRNGen_BN _ippsPRNGenRDRAND _ippsPRNGenRDRAND_BN _ippsTRNGenRDSEED _ippsTRNGenRDSEED_BN _ippsPrimeGetSize _ippsPrimeInit _ippsPrimeGen _ippsPrimeTest _ippsPrimeGen_BN _ippsPrimeTest_BN _ippsPrimeGet _ippsPrimeGet_BN _ippsPrimeSet _ippsPrimeSet_BN _ippsRSA_GetSizePublicKey _ippsRSA_InitPublicKey _ippsRSA_SetPublicKey _ippsRSA_GetPublicKey _ippsRSA_GetSizePrivateKeyType1 _ippsRSA_InitPrivateKeyType1 _ippsRSA_SetPrivateKeyType1 _ippsRSA_GetPrivateKeyType1 _ippsRSA_GetSizePrivateKeyType2 _ippsRSA_InitPrivateKeyType2 _ippsRSA_SetPrivateKeyType2 _ippsRSA_GetPrivateKeyType2 _ippsRSA_GetBufferSizePublicKey _ippsRSA_GetBufferSizePrivateKey _ippsRSA_Encrypt _ippsRSA_Decrypt _ippsRSA_GenerateKeys _ippsRSA_ValidateKeys _ippsRSAEncrypt_OAEP _ippsRSADecrypt_OAEP _ippsRSAEncrypt_OAEP_rmf _ippsRSADecrypt_OAEP_rmf _ippsRSAEncrypt_PKCSv15 _ippsRSADecrypt_PKCSv15 _ippsRSASign_PSS _ippsRSAVerify_PSS _ippsRSASign_PSS_rmf _ippsRSAVerify_PSS_rmf _ippsRSASign_PKCS1v15 _ippsRSAVerify_PKCS1v15 _ippsRSASign_PKCS1v15_rmf _ippsRSAVerify_PKCS1v15_rmf _ippsDLGetResultString _ippsDLPGetSize _ippsDLPInit _ippsDLPPack _ippsDLPUnpack _ippsDLPSet _ippsDLPGet _ippsDLPSetDP _ippsDLPGetDP _ippsDLPGenKeyPair _ippsDLPPublicKey _ippsDLPValidateKeyPair _ippsDLPSetKeyPair _ippsDLPSignDSA _ippsDLPVerifyDSA _ippsDLPSharedSecretDH _ippsDLPGenerateDSA _ippsDLPValidateDSA _ippsDLPGenerateDH _ippsDLPValidateDH _ippsECCGetResultString _ippsGFpGetSize _ippsGFpInitArbitrary _ippsGFpInitFixed _ippsGFpInit _ippsGFpMethod_p192r1 _ippsGFpMethod_p224r1 _ippsGFpMethod_p256r1 _ippsGFpMethod_p384r1 _ippsGFpMethod_p521r1 _ippsGFpMethod_p256sm2 _ippsGFpMethod_p256bn _ippsGFpMethod_p256 _ippsGFpMethod_pArb _ippsGFpxGetSize _ippsGFpxInit _ippsGFpxInitBinomial _ippsGFpxMethod_binom2_epid2 _ippsGFpxMethod_binom3_epid2 _ippsGFpxMethod_binom2 _ippsGFpxMethod_binom3 _ippsGFpxMethod_binom _ippsGFpxMethod_com _ippsGFpScratchBufferSize _ippsGFpElementGetSize _ippsGFpElementInit _ippsGFpSetElement _ippsGFpSetElementRegular _ippsGFpSetElementOctString _ippsGFpSetElementRandom _ippsGFpSetElementHash _ippsGFpSetElementHash_rmf _ippsGFpCpyElement _ippsGFpGetElement _ippsGFpGetElementOctString _ippsGFpCmpElement _ippsGFpIsZeroElement _ippsGFpIsUnityElement _ippsGFpConj _ippsGFpNeg _ippsGFpInv _ippsGFpSqrt _ippsGFpSqr _ippsGFpAdd _ippsGFpSub _ippsGFpMul _ippsGFpExp _ippsGFpMultiExp _ippsGFpAdd_PE _ippsGFpSub_PE _ippsGFpMul_PE _ippsGFpGetInfo _ippsGFpECGetSize _ippsGFpECInit _ippsGFpECSet _ippsGFpECSetSubgroup _ippsGFpECInitStd128r1 _ippsGFpECInitStd128r2 _ippsGFpECInitStd192r1 _ippsGFpECInitStd224r1 _ippsGFpECInitStd256r1 _ippsGFpECInitStd384r1 _ippsGFpECInitStd521r1 _ippsGFpECInitStdSM2 _ippsGFpECInitStdBN256 _ippsGFpECBindGxyTblStd192r1 _ippsGFpECBindGxyTblStd224r1 _ippsGFpECBindGxyTblStd256r1 _ippsGFpECBindGxyTblStd384r1 _ippsGFpECBindGxyTblStd521r1 _ippsGFpECBindGxyTblStdSM2 _ippsGFpECGet _ippsGFpECGetInfo_GF _ippsGFpECGetSubgroup _ippsGFpECScratchBufferSize _ippsGFpECVerify _ippsGFpECPointGetSize _ippsGFpECPointInit _ippsGFpECSetPointAtInfinity _ippsGFpECSetPoint _ippsGFpECSetPointRegular _ippsGFpECSetPointRandom _ippsGFpECMakePoint _ippsGFpECSetPointHash _ippsGFpECSetPointHash_rmf _ippsGFpECSetPointHashBackCompatible _ippsGFpECSetPointHashBackCompatible_rmf _ippsGFpECGetPoint _ippsGFpECGetPointRegular _ippsGFpECTstPoint _ippsGFpECTstPointInSubgroup _ippsGFpECCpyPoint _ippsGFpECCmpPoint _ippsGFpECNegPoint _ippsGFpECAddPoint _ippsGFpECMulPoint _ippsGFpECPrivateKey _ippsGFpECPublicKey _ippsGFpECTstKeyPair _ippsGFpECSharedSecretDH _ippsGFpECSharedSecretDHC _ippsGFpECSignDSA _ippsGFpECVerifyDSA _ippsGFpECSignNR _ippsGFpECVerifyNR _ippsGFpECSignSM2 _ippsGFpECVerifySM2 _ippsGFpECUserIDHashSM2 _ippsGFpECMessageRepresentationSM2 _ippsGFpECKeyExchangeSM2_GetSize _ippsGFpECKeyExchangeSM2_Init _ippsGFpECKeyExchangeSM2_Setup _ippsGFpECKeyExchangeSM2_SharedKey _ippsGFpECKeyExchangeSM2_Confirm _ippsGFpECEncryptSM2_Ext_EncMsgSize _ippsGFpECEncryptSM2_Ext _ippsGFpECDecryptSM2_Ext_DecMsgSize _ippsGFpECDecryptSM2_Ext _ippsGFpECESGetSize_SM2 _ippsGFpECESInit_SM2 _ippsGFpECESSetKey_SM2 _ippsGFpECESStart_SM2 _ippsGFpECESEncrypt_SM2 _ippsGFpECESDecrypt_SM2 _ippsGFpECESFinal_SM2 _ippsGFpECESGetBuffersSize_SM2 _ippsGFpECSetPointOctString _ippsGFpECGetPointOctString _ippsXMSSVerify _ippsXMSSSetPublicKeyState _ippsXMSSSetSignatureState _ippsXMSSSignatureStateGetSize _ippsXMSSPublicKeyStateGetSize _ippsXMSSBufferGetSize _ippsLMSBufferGetSize _ippsLMSSignatureStateGetSize _ippsLMSPublicKeyStateGetSize _ippsLMSSetPublicKeyState _ippsLMSSetSignatureState _ippsLMSVerify cryptography-primitives-1.0.0/sources/ippcp/exports.macosx.selftests-export000066400000000000000000000040601470420105600275030ustar00rootroot00000000000000_ippcp_is_fips_approved_func _fips_selftest_ippsAESEncryptDecrypt_get_size _fips_selftest_ippsAESEncryptCBC _fips_selftest_ippsAESDecryptCBC _fips_selftest_ippsAESEncryptCBC_CS1 _fips_selftest_ippsAESEncryptCBC_CS2 _fips_selftest_ippsAESEncryptCBC_CS3 _fips_selftest_ippsAESDecryptCBC_CS1 _fips_selftest_ippsAESDecryptCBC_CS2 _fips_selftest_ippsAESDecryptCBC_CS3 _fips_selftest_ippsAESEncryptCFB _fips_selftest_ippsAESDecryptCFB _fips_selftest_ippsAESEncryptOFB _fips_selftest_ippsAESDecryptOFB _fips_selftest_ippsAESEncryptCTR _fips_selftest_ippsAESDecryptCTR _fips_selftest_ippsAESEncryptDecryptCCM_get_size _fips_selftest_ippsAES_CCMEncrypt _fips_selftest_ippsAES_CCMDecrypt _fips_selftest_ippsAES_GCM_get_size _fips_selftest_ippsAES_GCMEncrypt _fips_selftest_ippsAES_GCMDecrypt _fips_selftest_ippsAES_CMAC_get_size _fips_selftest_ippsAES_CMACUpdate _fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys _fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size _fips_selftest_ippsRSAEncrypt_OAEP_rmf _fips_selftest_ippsRSADecrypt_OAEP_rmf _fips_selftest_ippsHash_rmf_get_size _fips_selftest_ippsHashUpdate_rmf _fips_selftest_ippsHashMessage_rmf _fips_selftest_ippsHMAC_rmf_get_size _fips_selftest_ippsHMACUpdate_rmf _fips_selftest_ippsHMACMessage_rmf _fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys _fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size _fips_selftest_ippsRSASign_PKCS1v15_rmf _fips_selftest_ippsRSAVerify_PKCS1v15_rmf _fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys _fips_selftest_ippsRSASignVerify_PSS_rmf_get_size _fips_selftest_ippsRSASign_PSS_rmf _fips_selftest_ippsRSAVerify_PSS_rmf _fips_selftest_ippsRSA_GenerateKeys _fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff _fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff _fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff _fips_selftest_ippsGFpECSignDSA _fips_selftest_ippsGFpECVerifyDSA _fips_selftest_ippsGFpECPublicKey _fips_selftest_ippsGFpECPrivateKey _fips_selftest_ippsGFpECSharedSecretDH _fips_selftest_ippsLMSVerify_get_size _fips_selftest_ippsLMSVerify cryptography-primitives-1.0.0/sources/ippcp/fips_cert/000077500000000000000000000000001470420105600232075ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/fips_cert/common.c000066400000000000000000000025721470420105600246510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #if defined( _IPP_DATA ) IPPFUN(func_fips_approved, ippcp_is_fips_approved_func, (enum FIPS_IPPCP_FUNC function)) { return ((int)function > 0); } #endif // _IPP_DATA IPP_OWN_DEFN (int, ippcp_is_mem_eq, (const Ipp8u *p1, Ipp32u p1_byte_len, const Ipp8u *p2, Ipp32u p2_byte_len)) { if (p1_byte_len != p2_byte_len){ return 0; } while (p1_byte_len) { if (*p1 != *p2) { return 0; } ++p1; ++p2; --p1_byte_len; } return 1; } #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_cbc.c000066400000000000000000000127201470420105600303050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" /* KAT TEST */ /* initialization vector */ static const Ipp8u iv[IPPCP_IV128_BYTE_LEN] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c}; /* plaintext */ static const Ipp8u ptext[IPPCP_AES_MSG_BYTE_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10}; /* ciphertext */ static const Ipp8u ctext[IPPCP_AES_MSG_BYTE_LEN] = { 0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d, 0x50,0x86,0xcb,0x9b,0x50,0x72,0x19,0xee,0x95,0xdb,0x11,0x3a,0x91,0x76,0x78,0xb2, 0x73,0xbe,0xd6,0xb8,0xe3,0xc1,0x74,0x3b,0x71,0x16,0xe6,0x9e,0x22,0x22,0x95,0x16, 0x3f,0xf1,0xca,0xa1,0x68,0x1f,0xac,0x09,0x12,0x0e,0xca,0x30,0x75,0x86,0xe1,0xa7}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptDecrypt_get_size, (int *pBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsAESGetSize(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_AES_ALIGNMENT; *pBuffSize = ctx_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptCBC, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAESGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptCBC(ptext, out_ctext, IPPCP_AES_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, IPPCP_AES_MSG_BYTE_LEN, ctext, IPPCP_AES_MSG_BYTE_LEN)) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptCBC, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptCBC(ctext, out_ptext, IPPCP_AES_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, IPPCP_AES_MSG_BYTE_LEN, ptext, IPPCP_AES_MSG_BYTE_LEN)) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_cbc_cs.c000066400000000000000000000254001470420105600307710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define AES_CBC_CS_MSG_BYTE_LEN ((IPPCP_AES_MSG_BYTE_LEN) - 1) /* KAT TEST */ /* initialization vector */ static const Ipp8u iv[IPPCP_IV128_BYTE_LEN] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c}; /* plaintext */ static const Ipp8u ptext[AES_CBC_CS_MSG_BYTE_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37}; /* ciphertexts */ static const Ipp8u ctext_cs1[AES_CBC_CS_MSG_BYTE_LEN] = { 0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d, 0x50,0x86,0xcb,0x9b,0x50,0x72,0x19,0xee,0x95,0xdb,0x11,0x3a,0x91,0x76,0x78,0xb2, 0x73,0xbe,0xd6,0xb8,0xe3,0xc1,0x74,0x3b,0x71,0x16,0xe6,0x9e,0x22,0x22,0x95,0xb6, 0x00,0xb4,0xb5,0x52,0x17,0xe8,0x13,0x0e,0x89,0xaa,0x96,0xbe,0xc6,0x9c,0xca}; static const Ipp8u ctext_cs2[AES_CBC_CS_MSG_BYTE_LEN] = { 0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d, 0x50,0x86,0xcb,0x9b,0x50,0x72,0x19,0xee,0x95,0xdb,0x11,0x3a,0x91,0x76,0x78,0xb2, 0xb6,0x00,0xb4,0xb5,0x52,0x17,0xe8,0x13,0x0e,0x89,0xaa,0x96,0xbe,0xc6,0x9c,0xca, 0x73,0xbe,0xd6,0xb8,0xe3,0xc1,0x74,0x3b,0x71,0x16,0xe6,0x9e,0x22,0x22,0x95}; static const Ipp8u ctext_cs3[AES_CBC_CS_MSG_BYTE_LEN] = { 0x76,0x49,0xab,0xac,0x81,0x19,0xb2,0x46,0xce,0xe9,0x8e,0x9b,0x12,0xe9,0x19,0x7d, 0x50,0x86,0xcb,0x9b,0x50,0x72,0x19,0xee,0x95,0xdb,0x11,0x3a,0x91,0x76,0x78,0xb2, 0xb6,0x00,0xb4,0xb5,0x52,0x17,0xe8,0x13,0x0e,0x89,0xaa,0x96,0xbe,0xc6,0x9c,0xca, 0x73,0xbe,0xd6,0xb8,0xe3,0xc1,0x74,0x3b,0x71,0x16,0xe6,0x9e,0x22,0x22,0x95}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptCBC_CS1, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[AES_CBC_CS_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptCBC_CS1(ptext, out_ctext, AES_CBC_CS_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, AES_CBC_CS_MSG_BYTE_LEN, ctext_cs1, AES_CBC_CS_MSG_BYTE_LEN)) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptCBC_CS1, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in use malloc mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[AES_CBC_CS_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptCBC_CS1(ctext_cs1, out_ptext, AES_CBC_CS_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, AES_CBC_CS_MSG_BYTE_LEN, ptext, AES_CBC_CS_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptCBC_CS2, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[AES_CBC_CS_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptCBC_CS2(ptext, out_ctext, AES_CBC_CS_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, AES_CBC_CS_MSG_BYTE_LEN, ctext_cs2, AES_CBC_CS_MSG_BYTE_LEN)) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptCBC_CS2, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[AES_CBC_CS_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptCBC_CS2(ctext_cs2, out_ptext, AES_CBC_CS_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, AES_CBC_CS_MSG_BYTE_LEN, ptext, AES_CBC_CS_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptCBC_CS3, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[AES_CBC_CS_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptCBC_CS3(ptext, out_ctext, AES_CBC_CS_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, AES_CBC_CS_MSG_BYTE_LEN, ctext_cs3, AES_CBC_CS_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptCBC_CS3, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /*output plaintext*/ Ipp8u out_ptext[AES_CBC_CS_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptCBC_CS3(ctext_cs3, out_ptext, AES_CBC_CS_MSG_BYTE_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, AES_CBC_CS_MSG_BYTE_LEN, ptext, AES_CBC_CS_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_ccm.c000066400000000000000000000166671470420105600303360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define IPPCP_IV_BYTE_LEN (7) // initialization vector #define IPPCP_AAD_BYTE_LEN (8) // additional authenticated data #define IPPCP_MSG_BYTE_LEN (4) #define IPPCP_TAG_BYTE_LEN (4) /* KAT TEST */ /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47, 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; /* initialization vector */ static const Ipp8u iv[IPPCP_IV_BYTE_LEN] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16}; /* plaintext */ static const Ipp8u ptext[IPPCP_MSG_BYTE_LEN] = {0x20,0x21,0x22,0x23}; /* ciphertext */ static const Ipp8u ctext[IPPCP_MSG_BYTE_LEN] = {0x71,0x62,0x01,0x5b}; /* tag */ static const Ipp8u tag[IPPCP_TAG_BYTE_LEN] = {0x4d,0xac,0x25,0x5d}; /* additional authenticated data */ static const Ipp8u ad[IPPCP_AAD_BYTE_LEN] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptDecryptCCM_get_size, (int *pBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsAES_CCMGetSize(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_AES_ALIGNMENT; *pBuffSize = ctx_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_CCMEncrypt, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecryptCCM_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[IPPCP_MSG_BYTE_LEN]; /* output tag */ Ipp8u out_tag[IPPCP_TAG_BYTE_LEN]; /* context */ IppsAES_CCMState* state = (IppsAES_CCMState*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAES_CCMGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CCMInit(key, IPPCP_AES_KEY128_BYTE_LEN, state, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* encryption setup */ sts = ippsAES_CCMMessageLen(IPPCP_MSG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CCMTagLen(IPPCP_TAG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CCMStart(iv, IPPCP_IV_BYTE_LEN, ad, IPPCP_AAD_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* encryption */ for (int i = 0; i < IPPCP_MSG_BYTE_LEN; ++i){ sts = ippsAES_CCMEncrypt(ptext + i, out_ctext + i, 1, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } } /* get tag */ sts = ippsAES_CCMGetTag(out_tag, IPPCP_TAG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_tag, IPPCP_TAG_BYTE_LEN, tag, IPPCP_TAG_BYTE_LEN)){ // tag MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } if (!ippcp_is_mem_eq(out_ctext, IPPCP_MSG_BYTE_LEN, ctext, IPPCP_MSG_BYTE_LEN)) { // ctext MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_CCMDecrypt, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecryptCCM_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[IPPCP_MSG_BYTE_LEN]; /* output tag */ Ipp8u out_tag[IPPCP_TAG_BYTE_LEN]; /* context */ IppsAES_CCMState* state = (IppsAES_CCMState*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAES_CCMGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CCMInit(key, IPPCP_AES_KEY128_BYTE_LEN, state, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* decryption setup */ sts = ippsAES_CCMMessageLen(IPPCP_MSG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CCMTagLen(IPPCP_TAG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CCMStart(iv,IPPCP_IV_BYTE_LEN, ad, IPPCP_AAD_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* decryption */ for (int i = 0; i < IPPCP_MSG_BYTE_LEN; ++i){ sts = ippsAES_CCMDecrypt(ctext + i, out_ptext + i, 1, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } } /* get tag */ sts = ippsAES_CCMGetTag(out_tag, IPPCP_TAG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_tag, IPPCP_TAG_BYTE_LEN, tag, IPPCP_TAG_BYTE_LEN)){ // tag MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } if (!ippcp_is_mem_eq(out_ptext, IPPCP_MSG_BYTE_LEN, ptext, IPPCP_MSG_BYTE_LEN)){ // ptext MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_cfb.c000066400000000000000000000121031470420105600303030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define IPPCP_CFB_BLOCK_LEN (16) /* KAT TEST */ /* initialization vector */ static const Ipp8u iv[IPPCP_IV128_BYTE_LEN] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c}; /* plaintext */ static const Ipp8u ptext[IPPCP_AES_MSG_BYTE_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10}; /* ciphertext */ static const Ipp8u ctext[IPPCP_AES_MSG_BYTE_LEN] = { 0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20,0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a, 0xc8,0xa6,0x45,0x37,0xa0,0xb3,0xa9,0x3f,0xcd,0xe3,0xcd,0xad,0x9f,0x1c,0xe5,0x8b, 0x26,0x75,0x1f,0x67,0xa3,0xcb,0xb1,0x40,0xb1,0x80,0x8c,0xf1,0x87,0xa4,0xf4,0xdf, 0xc0,0x4b,0x05,0x35,0x7c,0x5d,0x1c,0x0e,0xea,0xc4,0xc6,0x6f,0x9f,0xf7,0xf2,0xe6}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptCFB, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptCFB(ptext, out_ctext, IPPCP_AES_MSG_BYTE_LEN, IPPCP_CFB_BLOCK_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, IPPCP_AES_MSG_BYTE_LEN, ctext, IPPCP_AES_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptCFB, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAESGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptCFB(ctext, out_ptext, IPPCP_AES_MSG_BYTE_LEN, IPPCP_CFB_BLOCK_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, IPPCP_AES_MSG_BYTE_LEN, ptext, IPPCP_AES_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_ctr.c000066400000000000000000000130751470420105600303520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #if defined( _IPP_DATA ) #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define IPPCP_CTR_BYTE_LEN (16) #define IPPCP_CTR_BIT_LEN ((IPPCP_CTR_BYTE_LEN) * 8) /* KAT TEST */ /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c}; /* plaintext */ static const Ipp8u ptext[IPPCP_AES_MSG_BYTE_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10}; /* ciphertext */ static const Ipp8u ctext[IPPCP_AES_MSG_BYTE_LEN] = { 0x87,0x4d,0x61,0x91,0xb6,0x20,0xe3,0x26,0x1b,0xef,0x68,0x64,0x99,0x0d,0xb6,0xce, 0x98,0x06,0xf6,0x6b,0x79,0x70,0xfd,0xff,0x86,0x17,0x18,0x7b,0xb9,0xff,0xfd,0xff, 0x5a,0xe4,0xdf,0x3e,0xdb,0xd5,0xd3,0x5e,0x5b,0x4f,0x09,0x02,0x0d,0xb0,0x3e,0xab, 0x1e,0x03,0x1d,0xda,0x2f,0xbe,0x03,0xd1,0x79,0x21,0x70,0xa0,0xf3,0x00,0x9c,0xee}; /* counter after enc|dec */ static const Ipp8u out_ctr[IPPCP_CTR_BYTE_LEN] = { 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xff,0x03}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptCTR, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* counter */ Ipp8u ctr[IPPCP_CTR_BYTE_LEN] = { 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff}; /* output ciphertext */ Ipp8u out_ctext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAESGetSize(&ctx_size); sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptCTR(ptext, out_ctext, IPPCP_AES_MSG_BYTE_LEN, spec, ctr, IPPCP_CTR_BIT_LEN); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, IPPCP_AES_MSG_BYTE_LEN, ctext, IPPCP_AES_MSG_BYTE_LEN) || // ciphertext !ippcp_is_mem_eq( out_ctr, IPPCP_CTR_BYTE_LEN, ctr, IPPCP_CTR_BYTE_LEN)){ // counter MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptCTR, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* counter */ Ipp8u ctr[IPPCP_CTR_BYTE_LEN] = { 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff}; /* output plaintext */ Ipp8u out_ptext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAESGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptCTR(ctext, out_ptext, IPPCP_AES_MSG_BYTE_LEN, spec, ctr, IPPCP_CTR_BIT_LEN); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, IPPCP_AES_MSG_BYTE_LEN, ptext, IPPCP_AES_MSG_BYTE_LEN) || // plaintext !ippcp_is_mem_eq( out_ctr, IPPCP_CTR_BYTE_LEN, ctr, IPPCP_CTR_BYTE_LEN)){ // counter MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_gcm.c000066400000000000000000000165101470420105600303250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define IV_BYTE_LEN (12) // initialization vector #define AD_BYTE_LEN (20) // additional authenticated data #define MSG_BYTE_LEN (60) #define TAG_BYTE_LEN (16) /* KAT TEST */ /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c, 0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08}; /* initialization vector */ static const Ipp8u iv[IV_BYTE_LEN] = {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad, 0xde,0xca,0xf8,0x88}; /* plaintext */ static const Ipp8u ptext[MSG_BYTE_LEN] = { 0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a, 0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72, 0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25, 0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39}; /* ciphertext */ static const Ipp8u ctext[MSG_BYTE_LEN] = { 0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c, 0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e, 0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05, 0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91}; /* tag */ static const Ipp8u tag[TAG_BYTE_LEN] = {0x5b,0xc9,0x4f,0xbc,0x32,0x21,0xa5,0xdb, 0x94,0xfa,0xe9,0x5a,0xe7,0x12,0x1a,0x47}; /* additional authenticated data */ static const Ipp8u ad[AD_BYTE_LEN] = {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef, 0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef, 0xab,0xad,0xda,0xd2}; IPPFUN(fips_test_status, fips_selftest_ippsAES_GCM_get_size, (int *pBufferSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsAES_GCMGetSize(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_AES_ALIGNMENT; *pBufferSize = ctx_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_GCMEncrypt, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAES_GCM_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[MSG_BYTE_LEN]; /* output tag */ Ipp8u out_tag[TAG_BYTE_LEN]; /* context */ IppsAES_GCMState *state = (IppsAES_GCMState *)IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT); /* context initialization */ ippsAES_GCMGetSize(&ctx_size); sts = ippsAES_GCMInit(key, IPPCP_AES_KEY128_BYTE_LEN, state, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* encryption setup */ sts = ippsAES_GCMStart(iv, IV_BYTE_LEN, ad, AD_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* encryption */ for (int i = 0; i < MSG_BYTE_LEN; ++i){ sts = ippsAES_GCMEncrypt(ptext + i, out_ctext + i, 1, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } } /* get tag */ sts = ippsAES_GCMGetTag(out_tag, TAG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer*/ if (!ippcp_is_mem_eq(out_tag, TAG_BYTE_LEN, tag, TAG_BYTE_LEN)) { // tag MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } if (!ippcp_is_mem_eq(out_ctext, MSG_BYTE_LEN, ctext, MSG_BYTE_LEN)) { // ctext MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_GCMDecrypt, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAES_GCM_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[MSG_BYTE_LEN]; /* output tag */ Ipp8u out_tag[TAG_BYTE_LEN]; /* context */ IppsAES_GCMState *state = (IppsAES_GCMState *)IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT); /* context initialization */ sts = ippsAES_GCMGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_GCMInit(key, IPPCP_AES_KEY128_BYTE_LEN, state, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* decryption setup */ sts = ippsAES_GCMStart(iv,IV_BYTE_LEN, ad, AD_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* decryption */ for (int i = 0; i < MSG_BYTE_LEN; ++i){ sts = ippsAES_GCMDecrypt(ctext + i, out_ptext + i, 1, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } } /* get tag */ sts = ippsAES_GCMGetTag(out_tag, TAG_BYTE_LEN, state); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_tag, TAG_BYTE_LEN, tag, TAG_BYTE_LEN)){ // tag MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } if (!ippcp_is_mem_eq(out_ptext, MSG_BYTE_LEN, ptext, MSG_BYTE_LEN)){ // ptext MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_ofb.c000066400000000000000000000134021470420105600303220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define OFB_BLOCK_LEN (16) /* KAT TEST */ /* secret key */ static const Ipp8u key[IPPCP_AES_KEY128_BYTE_LEN] = { 0x2b,0x7e,0x15,0x16,0x28,0xae,0xd2,0xa6, 0xab,0xf7,0x15,0x88,0x09,0xcf,0x4f,0x3c}; /* plaintext */ static const Ipp8u ptext[IPPCP_AES_MSG_BYTE_LEN] = { 0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a, 0xae,0x2d,0x8a,0x57,0x1e,0x03,0xac,0x9c,0x9e,0xb7,0x6f,0xac,0x45,0xaf,0x8e,0x51, 0x30,0xc8,0x1c,0x46,0xa3,0x5c,0xe4,0x11,0xe5,0xfb,0xc1,0x19,0x1a,0x0a,0x52,0xef, 0xf6,0x9f,0x24,0x45,0xdf,0x4f,0x9b,0x17,0xad,0x2b,0x41,0x7b,0xe6,0x6c,0x37,0x10}; /* ciphertext */ static const Ipp8u ctext[IPPCP_AES_MSG_BYTE_LEN] = { 0x3b,0x3f,0xd9,0x2e,0xb7,0x2d,0xad,0x20,0x33,0x34,0x49,0xf8,0xe8,0x3c,0xfb,0x4a, 0x77,0x89,0x50,0x8d,0x16,0x91,0x8f,0x03,0xf5,0x3c,0x52,0xda,0xc5,0x4e,0xd8,0x25, 0x97,0x40,0x05,0x1e,0x9c,0x5f,0xec,0xf6,0x43,0x44,0xf7,0xa8,0x22,0x60,0xed,0xcc, 0x30,0x4c,0x65,0x28,0xf6,0x59,0xc7,0x78,0x66,0xa5,0x10,0xd9,0xc1,0xd6,0xae,0x5e}; /* initialization vector after enc|dec */ static const Ipp8u out_iv[IPPCP_IV128_BYTE_LEN] = { 0xc6,0xd3,0x41,0x6d,0x29,0x16,0x5c,0x6f, 0xcb,0x8e,0x51,0xa2,0x27,0xba,0x99,0x4e}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptOFB, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* initialization vector */ Ipp8u iv[IPPCP_IV128_BYTE_LEN] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; /* output ciphertext */ Ipp8u out_ctext[IPPCP_AES_MSG_BYTE_LEN]; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAESGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESEncryptOFB(ptext, out_ctext, IPPCP_AES_MSG_BYTE_LEN, OFB_BLOCK_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, IPPCP_AES_MSG_BYTE_LEN, ctext, IPPCP_AES_MSG_BYTE_LEN) || // ciphertext !ippcp_is_mem_eq( out_iv, IPPCP_IV128_BYTE_LEN, iv, IPPCP_IV128_BYTE_LEN)){ // initialization vector MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAESDecryptOFB, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAESEncryptDecrypt_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[IPPCP_AES_MSG_BYTE_LEN]; /* initialization vector */ Ipp8u iv[IPPCP_IV128_BYTE_LEN] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; /* context */ IppsAESSpec* spec = (IppsAESSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAESGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAESInit(key, IPPCP_AES_KEY128_BYTE_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAESDecryptOFB(ctext, out_ptext, IPPCP_AES_MSG_BYTE_LEN, OFB_BLOCK_LEN, spec, iv); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, IPPCP_AES_MSG_BYTE_LEN, ptext, IPPCP_AES_MSG_BYTE_LEN) || // plaintext !ippcp_is_mem_eq( out_iv, IPPCP_IV128_BYTE_LEN, iv, IPPCP_IV128_BYTE_LEN)){ // initialization vector MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_enc_dec_xts.c000066400000000000000000000130051470420105600303710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif /* Selftests are disabled for now, since AES-XTS algorithm didn't pass CAVP testing */ #if 0 #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #define IPPCP_AES_KEY256_BIT_LEN (256) #define IPPCP_DATA_UNIT_BIT_LEN (128) #define IPPCP_TWEAK_BYTE_LEN (16) #define IPPCP_MSG_BYTE_LEN (16) #define IPPCP_START_CIPHER_BLOCK_NUM (0) /* KAT TEST */ /* tweak vector */ static const Ipp8u tweak[IPPCP_TWEAK_BYTE_LEN] = { 0x4f,0xae,0xf7,0x11,0x7c,0xda,0x59,0xc6, 0x6e,0x4b,0x92,0x01,0x3e,0x76,0x8a,0xd5}; /* secret key */ static const Ipp8u key[IPPCP_AES_KEY256_BYTE_LEN] = { 0xa1,0xb9,0x0c,0xba,0x3f,0x06,0xac,0x35,0x3b,0x2c,0x34,0x38,0x76,0x08,0x17,0x62, 0x09,0x09,0x23,0x02,0x6e,0x91,0x77,0x18,0x15,0xf2,0x9d,0xab,0x01,0x93,0x2f,0x2f}; /* plaintext */ static const Ipp8u ptext[IPPCP_MSG_BYTE_LEN] = { 0xeb,0xab,0xce,0x95,0xb1,0x4d,0x3c,0x8d, 0x6f,0xb3,0x50,0x39,0x07,0x90,0x31,0x1c}; /* ciphertext */ static const Ipp8u ctext[IPPCP_MSG_BYTE_LEN] = { 0x77,0x8a,0xe8,0xb4,0x3c,0xb9,0x8d,0x5a, 0x82,0x50,0x81,0xd5,0xbe,0x47,0x1c,0x63}; IPPFUN(fips_test_status, fips_selftest_ippsAESEncryptDecryptXTS_get_size, (int* pBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsAES_XTSGetSize(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_AES_ALIGNMENT; *pBuffSize = ctx_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_XTSEncrypt, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecryptXTS_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output ciphertext */ Ipp8u out_ctext[IPPCP_MSG_BYTE_LEN]; /* context */ IppsAES_XTSSpec* spec = (IppsAES_XTSSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAES_XTSGetSize(&ctx_size); sts = ippsAES_XTSInit(key, IPPCP_AES_KEY256_BIT_LEN, IPPCP_DATA_UNIT_BIT_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAES_XTSEncrypt(ptext, out_ctext, IPPCP_DATA_UNIT_BIT_LEN, spec, tweak, IPPCP_START_CIPHER_BLOCK_NUM); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ctext, IPPCP_MSG_BYTE_LEN, ctext, IPPCP_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_XTSDecrypt, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; fips_selftest_ippsAESEncryptDecryptXTS_get_size(&ctx_size); BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output plaintext */ Ipp8u out_ptext[IPPCP_MSG_BYTE_LEN]; /* context */ IppsAES_XTSSpec* spec = (IppsAES_XTSSpec*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ ippsAES_XTSGetSize(&ctx_size); sts = ippsAES_XTSInit(key, IPPCP_AES_KEY256_BIT_LEN, IPPCP_DATA_UNIT_BIT_LEN, spec, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAES_XTSDecrypt(ctext, out_ptext, IPPCP_DATA_UNIT_BIT_LEN, spec, tweak, IPPCP_START_CIPHER_BLOCK_NUM); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(out_ptext, IPPCP_MSG_BYTE_LEN, ptext, IPPCP_MSG_BYTE_LEN)){ MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE #endif cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_upd_cmac.c000066400000000000000000000101541470420105600276700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" /* * KAT TEST * taken from Wycheproof testing */ // message static const Ipp8u msg[] = { 0x61, 0x23, 0xc5, 0x56, 0xc5, 0xcc }; // key static const Ipp8u key[] = { 0x48,0x14,0x40,0x29,0x85,0x25,0xcc,0x26,0x1f,0x81,0x59,0x15,0x9a,0xed,0xf6,0x2d }; // known tag static const Ipp8u tag[] = { 0xa2,0x81,0xe0,0xd2,0xd5,0x37,0x8d,0xfd,0xcc,0x13,0x10,0xfd,0x97,0x82,0xca,0x56 }; static const int msgByteLen = sizeof(msg); static const int keyByteSize = sizeof(key); #define IPPCP_TAG_BYTE_SIZE (sizeof(tag)) IPPFUN(fips_test_status, fips_selftest_ippsAES_CMAC_get_size, (int *pBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsAES_CMACGetSize(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_AES_ALIGNMENT; *pBuffSize = ctx_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsAES_CMACUpdate, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsAES_CMAC_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output hash */ Ipp8u outTagBuff[IPPCP_TAG_BYTE_SIZE]; Ipp8u outTagFinBuff[IPPCP_TAG_BYTE_SIZE]; /* context */ IppsAES_CMACState* pCtx = (IppsAES_CMACState*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_AES_ALIGNMENT)); /* context initialization */ sts = ippsAES_CMACGetSize(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CMACInit(key, keyByteSize, pCtx, ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsAES_CMACUpdate(msg, msgByteLen, pCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CMACGetTag(outTagBuff, IPPCP_TAG_BYTE_SIZE, pCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsAES_CMACFinal(outTagFinBuff, IPPCP_TAG_BYTE_SIZE, pCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ int isEqual; isEqual = ippcp_is_mem_eq(outTagBuff, IPPCP_TAG_BYTE_SIZE, tag, IPPCP_TAG_BYTE_SIZE); isEqual &= ippcp_is_mem_eq(outTagFinBuff, IPPCP_TAG_BYTE_SIZE, tag, IPPCP_TAG_BYTE_SIZE); if (!isEqual) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_aes_upd_hmac.c000066400000000000000000000133351470420105600277010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" #include "hash/pcphashmethod_rmf.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" /* * KAT TEST * taken from Wycheproof testing */ // message static const Ipp8u msg[] = { 0x2f,0xa4,0x3a,0x14,0xae,0x50,0x05,0x07,0xde,0xb9,0x5a,0xb5,0xbd,0x32,0xb0,0xfe }; // key static const Ipp8u key[] = { 0xac,0x68,0x6b,0xa0,0xf1,0xa5,0x1b,0x4e,0xc4,0xf0,0xb3,0x04,0x92,0xb7,0xf5,0x56 }; // known tag static const Ipp8u tag[] = { 0x00,0x85,0x32,0xa5,0x3d,0x0c,0x0a,0xb2,0x20,0x27,0xae,0x24,0x90,0x23,0x37,0x53, 0x74,0xe2,0x23,0x9b,0x95,0x96,0x09,0xe8,0x33,0x9b,0x05,0xa1,0x57,0x42,0xa6,0x75 }; static const int msgByteLen = sizeof(msg); static const int keyByteSize = sizeof(key); #define IPPCP_TAG_BYTE_SIZE (sizeof(tag)) IPPFUN(fips_test_status, fips_selftest_ippsHMAC_rmf_get_size, (int *pBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsHMACGetSize_rmf(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_HMAC_ALIGNMENT; int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } *pBuffSize = ctx_size + hash_method_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsHMACUpdate_rmf, (Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = fips_selftest_ippsHMAC_rmf_get_size(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, ctx_size, IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) /* output hash */ Ipp8u outTagBuff[IPPCP_TAG_BYTE_SIZE]; Ipp8u outTagFinBuff[IPPCP_TAG_BYTE_SIZE]; int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* context */ IppsHMACState_rmf* pCtx = (IppsHMACState_rmf*)(IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_HMAC_ALIGNMENT)); /* context initialization */ sts = ippsHMACGetSize_rmf(&ctx_size); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsHMACInit_rmf(key, keyByteSize, pCtx, locMethod); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsHMACUpdate_rmf(msg, msgByteLen, pCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsHMACGetTag_rmf(outTagBuff, IPPCP_TAG_BYTE_SIZE, pCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsHMACFinal_rmf(outTagFinBuff, IPPCP_TAG_BYTE_SIZE, pCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ int isEqual; isEqual = ippcp_is_mem_eq(outTagBuff, IPPCP_TAG_BYTE_SIZE, tag, IPPCP_TAG_BYTE_SIZE); isEqual &= ippcp_is_mem_eq(outTagFinBuff, IPPCP_TAG_BYTE_SIZE, tag, IPPCP_TAG_BYTE_SIZE); if (!isEqual) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsHMACMessage_rmf, (void)) { IppStatus sts = ippStsNoErr; /* output hash */ Ipp8u outTagBuff[IPPCP_TAG_BYTE_SIZE]; Ipp8u hashMethodArr[sizeof(IppsHashMethod)]; IppsHashMethod* locMethod = (IppsHashMethod*)hashMethodArr; sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsHMACMessage_rmf(msg, msgByteLen, key, keyByteSize, outTagBuff, IPPCP_TAG_BYTE_SIZE, locMethod); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } if (!ippcp_is_mem_eq(outTagBuff, IPPCP_TAG_BYTE_SIZE, tag, IPPCP_TAG_BYTE_SIZE)) { return IPPCP_ALGO_SELFTEST_KAT_ERR; } return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_ecdsa_shared_secret.c000066400000000000000000000200661470420105600312420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #include "fips_cert_internal/bn_common.h" /* * KAT * taken from wycheproof testing */ /* public */ static const Ipp8u pub_x[] = {0x26,0x4f,0xe4,0xaf,0x31,0xd7,0x61,0xfa, 0xfd,0x0b,0x8b,0x86,0x46,0x70,0xe0,0x28, 0x24,0x50,0x0f,0x5d,0x71,0x40,0xa0,0x85, 0xfe,0x75,0xaf,0x72,0x33,0xbd,0xd5,0x62}; static const Ipp8u pub_y[] = {0xcf,0x30,0x4e,0x01,0x5a,0x27,0x7d,0xa0, 0xb4,0x72,0x88,0xc3,0xc8,0x41,0xb7,0x0e, 0x99,0x13,0x8d,0xbf,0xb5,0x95,0x5a,0xcd, 0x81,0x0a,0xe7,0xa9,0x93,0x3a,0x33,0xac}; /* private */ static const Ipp8u prv_key[] = {0x46,0xc3,0x10,0x2c,0xe0,0x52,0x53,0x7b, 0x64,0x38,0x41,0xf8,0xae,0x53,0xbb,0xfe, 0xd3,0xbf,0xce,0x6b,0x0a,0x5b,0x85,0x17, 0xab,0x23,0xa0,0x89,0x5c,0x46,0x12,0x06}; /* shared key */ static const Ipp8u sh_key[] = {0x85,0x42,0x71,0xe1,0x95,0x08,0xbc,0x93, 0x5a,0xb2,0x2b,0x95,0xcd,0x2b,0xe1,0x3a, 0x0e,0x78,0x26,0x5f,0x52,0x8b,0x65,0x8b, 0x32,0x19,0x02,0x8b,0x90,0x0d,0x02,0x53}; IPPFUN(fips_test_status, fips_selftest_ippsGFpECSharedSecretDH, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; const unsigned int primeBitSize = 256; const unsigned int primeWordSize = 8; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pGFpBuff == NULL || pGFpECBuff == NULL || pDataBuff == NULL) { internalMemMgm = 1; int gfpBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff(&gfpBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpBuff = malloc((size_t)gfpBuffSize); int gfpECBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff(&gfpECBuffSize, pGFpBuff); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpECBuff = malloc((size_t)gfpECBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff(&dataBuffSize, pGFpBuff, pGFpECBuff); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pDataBuff = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pGFpBuff) || (NULL == pGFpECBuff) || (NULL == pDataBuff), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Init GFp context */ IppsGFpState* pGF = (IppsGFpState*)(IPP_ALIGNED_PTR(pGFpBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Init GFpEC context */ IppsGFpECState* pEC = (IppsGFpECState*)(IPP_ALIGNED_PTR(pGFpECBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECInitStd256r1(pGF, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pLocDataBuff = pDataBuff; /* private key */ int regKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, ®KeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnPrivate = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnPrivate, primeWordSize, ippBigNumPOS, (const Ipp32u *)prv_key, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += regKeyCtxByteSize; /* shared key */ int sharedKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, &sharedKeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnShared = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnShared, primeWordSize, ippBigNumPOS, (const Ipp32u *) /*empty*/ prv_key, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sharedKeyCtxByteSize; /* public key */ // element int sizeElem; sts = ippsGFpElementGetSize(pGF, &sizeElem); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsGFpElement* pubXElement = (IppsGFpElement*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpElementInit((Ipp32u*) pub_x, primeWordSize, pubXElement, pGF); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sizeElem; IppsGFpElement* pubYElement = (IppsGFpElement*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpElementInit((Ipp32u*) pub_y, primeWordSize, pubYElement, pGF); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sizeElem; // point int sizePoint; sts = ippsGFpECPointGetSize(pEC, &sizePoint); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsGFpECPoint* regPublic = (IppsGFpECPoint*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECPointInit(pubXElement, pubYElement, regPublic, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sizePoint; /* Shared Key Generation */ sts = ippsGFpECSharedSecretDH(bnPrivate, regPublic, bnShared, pEC, pLocDataBuff); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u pOut[sizeof(sh_key)]; int len; IppsBigNumSGN sgn; sts = ippsGet_BN(&sgn, &len, (Ipp32u*)pOut, bnShared); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } int sigFlagErr; sigFlagErr = ippcp_is_mem_eq(sh_key, sizeof(sh_key), pOut, sizeof(sh_key)); if( 1 != sigFlagErr ) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return test_result; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_ecdsa_sign_verify.c000066400000000000000000000652071470420105600307610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #include "fips_cert_internal/bn_common.h" /* * KAT * vectors are taken from FIPS 186 testing vectors set * msg == * "5905238877c77421f73e43ee3da6f2d9e2ccad5fc942dcec0cbd25482935faaf" * "416983fe165b1a045ee2bcd2e6dca3bdf46c4310a7461f9a37960ca672d3feb5" * "473e253605fb1ddfd28065b53cb5858a8ad28175bf9bd386a5e471ea7a65c17c" * "c934a9d791e91491eb3754d03799790fe2d308d16146d5c9b0d0debd97d79ce8" */ /* msgDigest == SHA-256(msg) */ static const Ipp8u msg_digest[] = { 0x56,0xec,0x33,0xa1,0xa6,0xe7,0xc4,0xdb,0x77,0x03,0x90,0x1a,0xfb,0x2e,0x1e,0x4e, 0x50,0x09,0xfe,0x04,0x72,0x89,0xc5,0xc2,0x42,0x13,0x6c,0xe3,0xb7,0xf6,0xac,0x44 }; /* key pair */ static const Ipp8u d[] = { 0x64,0xb4,0x72,0xda,0x6d,0xa5,0x54,0xca,0xac,0x3e,0x4e,0x0b,0x13,0xc8,0x44,0x5b, 0x1a,0x77,0xf4,0x59,0xee,0xa8,0x4f,0x1f,0x58,0x8b,0x5f,0x71,0x3d,0x42,0x9b,0x51 }; static const Ipp8u k[] = { 0xde,0x68,0x2a,0x64,0x87,0x07,0x67,0xb9,0x33,0x5d,0x4f,0x82,0x47,0x62,0x4a,0x3b, 0x7f,0x3c,0xe9,0xf9,0x45,0xf2,0x80,0xa2,0x61,0x6a,0x90,0x4b,0xb1,0xbb,0xa1,0x94 }; /* signature */ static const Ipp8u r[] = { 0xac,0xc2,0xc8,0x79,0x6f,0x5e,0xbb,0xca,0x7a,0x5a,0x55,0x6a,0x1f,0x6b,0xfd,0x2a, 0xed,0x27,0x95,0x62,0xd6,0xe3,0x43,0x88,0x5b,0x79,0x14,0xb5,0x61,0x80,0xac,0xf3 }; static const Ipp8u s[] = { 0x03,0x89,0x05,0xcc,0x2a,0xda,0xcd,0x3c,0x5a,0x17,0x6f,0xe9,0x18,0xb2,0x97,0xef, 0x1c,0x37,0xf7,0x2b,0x26,0x76,0x6c,0x78,0xb2,0xa6,0x05,0xca,0x19,0x78,0xf7,0x8b }; static const unsigned int primeBitSize = 256; static const unsigned int ordWordSize = 8; static const unsigned int msgWordSize = 8; static const unsigned int primeWordSize = 8; IPPFUN(fips_test_status, fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff, (int *pGFpBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pGFpBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); int ctx_size = 0; IppStatus sts = ippsGFpGetSize(primeBitSize, &ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } *pGFpBuffSize = ctx_size + IPPCP_GFP_ALIGNMENT; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff, (int *pGFpECBuffSize, Ipp8u *pGFpBuff)) { /* return bad status if input pointers are NULL */ IPP_BADARG_RET((NULL == pGFpECBuffSize) || (NULL == pGFpBuff), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; IppsGFpState* pGF = (IppsGFpState*)(IPP_ALIGNED_PTR(pGFpBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* GFpEC context size */ int ctx_size = 0; sts = ippsGFpECGetSize(pGF, &ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } *pGFpECBuffSize = ctx_size + IPPCP_GFP_ALIGNMENT; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff, (int *pDataBuffSize, Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff)) { /* return bad status if input pointers are NULL */ IPP_BADARG_RET((NULL == pDataBuffSize) || (NULL == pGFpBuff) || (NULL == pGFpECBuff), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; int tmp_size = 0; IppsGFpState* pGF = (IppsGFpState*)pGFpBuff; sts = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* GFpEC context size */ IppsGFpECState* pEC = (IppsGFpECState*)pGFpECBuff; sts = ippsGFpECInitStd256r1(pGF, pEC); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* signature */ sts = ippsBigNumGetSize(ordWordSize, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (2*(tmp_size + IPPCP_GFP_ALIGNMENT)); // bnR and bnS /* message */ sts = ippsBigNumGetSize(msgWordSize, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size+IPPCP_GFP_ALIGNMENT); /* Reg and eph keys */ sts = ippsBigNumGetSize(primeWordSize, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (2*(tmp_size + IPPCP_GFP_ALIGNMENT)); // bnRegPrivate and bnEphPrivate /* Public key x and y coordinates */ sts = ippsGFpElementGetSize(pGF, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (2*(tmp_size + IPPCP_GFP_ALIGNMENT)); // pubGxCtxByteSize and pubGyCtxByteSize /* Public key */ sts = ippsGFpECPointGetSize(pEC, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size+IPPCP_GFP_ALIGNMENT); sts = ippsPRNGGetSize(&tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size+IPPCP_GFP_ALIGNMENT); /* Scratch buffer */ sts = ippsGFpECScratchBufferSize(2, pEC, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size+IPPCP_GFP_ALIGNMENT); *pDataBuffSize = total_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsGFpECSignDSA, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pGFpBuff == NULL || pGFpECBuff == NULL || pDataBuff == NULL) { internalMemMgm = 1; int gfpBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff(&gfpBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpBuff = malloc((size_t)gfpBuffSize); int gfpECBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff(&gfpECBuffSize, pGFpBuff); if (sts != ippStsNoErr) { MEMORY_FREE(pGFpBuff) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpECBuff = malloc((size_t)gfpECBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff(&dataBuffSize, pGFpBuff, pGFpECBuff); if (sts != ippStsNoErr) { MEMORY_FREE_2(pGFpBuff, pGFpECBuff) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pDataBuff = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pGFpBuff) || (NULL == pGFpECBuff) || (NULL == pDataBuff), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Init GFp context */ IppsGFpState* pGF = (IppsGFpState*)(IPP_ALIGNED_PTR(pGFpBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Init GFpEC context */ IppsGFpECState* pEC = (IppsGFpECState*)(IPP_ALIGNED_PTR(pGFpECBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECInitStd256r1(pGF, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pLocDataBuff = pDataBuff; /* signature */ int sByteSize; sts = ippsBigNumGetSize(ordWordSize, &sByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnS = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnS, ordWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, ordWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sByteSize; int rByteSize; sts = ippsBigNumGetSize(ordWordSize, &rByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnR = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnR, ordWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, ordWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += rByteSize; /* message */ int msgCtxByteSize; sts = ippsBigNumGetSize(msgWordSize, &msgCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnMsgDigest = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnMsgDigest, msgWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, msgWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += msgCtxByteSize; /* Reg and eph keys */ int regKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, ®KeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnRegPrivate = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnRegPrivate, primeWordSize, ippBigNumPOS, (const Ipp32u *)d, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += regKeyCtxByteSize; int ephKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, &ephKeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnEphPrivate = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnEphPrivate, primeWordSize, ippBigNumPOS, (const Ipp32u *)k, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += ephKeyCtxByteSize; int scratchSize; sts = ippsGFpECScratchBufferSize(2, pEC, &scratchSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pScratchBuffer = pLocDataBuff; /* RSA Signature Generation */ sts = ippsGFpECSignDSA(bnMsgDigest, bnRegPrivate, bnEphPrivate, bnR, bnS, pEC, pScratchBuffer); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u pOutR[32]; Ipp8u pOutS[32]; int lenR, lenS; IppsBigNumSGN sgn; ippsGet_BN(&sgn, &lenR, (Ipp32u*)pOutR, bnR); ippsGet_BN(&sgn, &lenS, (Ipp32u*)pOutS, bnS); int sigFlagErr; sigFlagErr = ippcp_is_mem_eq(r, sizeof(r), pOutR, sizeof(r)); sigFlagErr &= ippcp_is_mem_eq(s, sizeof(s), pOutS, sizeof(s)); if(1 != sigFlagErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return test_result; } IPPFUN(fips_test_status, fips_selftest_ippsGFpECVerifyDSA, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pGFpBuff == NULL || pGFpECBuff == NULL || pDataBuff == NULL) { internalMemMgm = 1; int gfpBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff(&gfpBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpBuff = malloc((size_t)gfpBuffSize); int gfpECBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff(&gfpECBuffSize, pGFpBuff); if (sts != ippStsNoErr) { MEMORY_FREE(pGFpBuff) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpECBuff = malloc((size_t)gfpECBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff(&dataBuffSize, pGFpBuff, pGFpECBuff); if (sts != ippStsNoErr) { MEMORY_FREE_2(pGFpBuff, pGFpECBuff) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pDataBuff = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pGFpBuff) || (NULL == pGFpECBuff) || (NULL == pDataBuff), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Init GFp context */ IppsGFpState* pGF = (IppsGFpState*)(IPP_ALIGNED_PTR(pGFpBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Init GFpEC context */ IppsGFpECState* pEC = (IppsGFpECState*)(IPP_ALIGNED_PTR(pGFpECBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECInitStd256r1(pGF, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pLocDataBuff = pDataBuff; /* signature */ int sByteSize; sts = ippsBigNumGetSize(ordWordSize, &sByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnS = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnS, ordWordSize, ippBigNumPOS, (const Ipp32u *)s, ordWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sByteSize; int rByteSize; sts = ippsBigNumGetSize(ordWordSize, &rByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnR = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnR, ordWordSize, ippBigNumPOS, (const Ipp32u *)r, ordWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += rByteSize; /* message */ int msgCtxByteSize; sts = ippsBigNumGetSize(msgWordSize, &msgCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnMsgDigest = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnMsgDigest, msgWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, msgWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += msgCtxByteSize; /* Reg private key */ int regKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, ®KeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnRegPrivate = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnRegPrivate, primeWordSize, ippBigNumPOS, (const Ipp32u *)d, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += regKeyCtxByteSize; // Generate public key int pubKeyCtxByteSize; sts = ippsGFpECPointGetSize(pEC, &pubKeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsGFpECPoint* regPublic = (IppsGFpECPoint*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECPointInit(NULL, NULL, regPublic, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += pubKeyCtxByteSize; sts = ippsGFpECPublicKey(bnRegPrivate, regPublic, pEC, pLocDataBuff); if( ippStsNoErr != sts ) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA Signature Verification */ IppECResult verifRes; sts = ippsGFpECVerifyDSA(bnMsgDigest, regPublic, bnR, bnS, &verifRes, pEC, pLocDataBuff); if( ippECValid != verifRes || ippStsNoErr != sts ) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return test_result; } // test can be the same as the test above IPPFUN(fips_test_status, fips_selftest_ippsGFpECPublicKey, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) { return fips_selftest_ippsGFpECVerifyDSA(pGFpBuff, pGFpECBuff, pDataBuff); } IPPFUN(fips_test_status, fips_selftest_ippsGFpECPrivateKey, (Ipp8u *pGFpBuff, Ipp8u *pGFpECBuff, Ipp8u *pDataBuff)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pGFpBuff == NULL || pGFpECBuff == NULL || pDataBuff == NULL) { internalMemMgm = 1; int gfpBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff(&gfpBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpBuff = malloc((size_t)gfpBuffSize); int gfpECBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff(&gfpECBuffSize, pGFpBuff); if (sts != ippStsNoErr) { MEMORY_FREE(pGFpBuff) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pGFpECBuff = malloc((size_t)gfpECBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff(&dataBuffSize, pGFpBuff, pGFpECBuff); if (sts != ippStsNoErr) { MEMORY_FREE_2(pGFpBuff, pGFpECBuff) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pDataBuff = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pGFpBuff) || (NULL == pGFpECBuff) || (NULL == pDataBuff), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Init GFp context */ IppsGFpState* pGF = (IppsGFpState*)(IPP_ALIGNED_PTR(pGFpBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpInitFixed(primeBitSize, ippsGFpMethod_p256r1(), pGF); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Init GFpEC context */ IppsGFpECState* pEC = (IppsGFpECState*)(IPP_ALIGNED_PTR(pGFpECBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECInitStd256r1(pGF, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pLocDataBuff = pDataBuff; /* signature */ int sByteSize; sts = ippsBigNumGetSize(ordWordSize, &sByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnS = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnS, ordWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, ordWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += sByteSize; int rByteSize; sts = ippsBigNumGetSize(ordWordSize, &rByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnR = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnR, ordWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, ordWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += rByteSize; /* message */ int msgCtxByteSize; sts = ippsBigNumGetSize(msgWordSize, &msgCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnMsgDigest = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnMsgDigest, msgWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, msgWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += msgCtxByteSize; // Generate private key int prngCtxByteSize; sts = ippsPRNGGetSize(&prngCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsPRNGState* pRand = (IppsPRNGState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsPRNGInit(160, pRand); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += prngCtxByteSize; int regKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, ®KeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* regPrivate = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(regPrivate, primeWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsGFpECPrivateKey(regPrivate, pEC, ippsPRNGen, pRand); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += regKeyCtxByteSize; int pubKeyCtxByteSize; sts = ippsGFpECPointGetSize(pEC, &pubKeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } // Generate public key IppsGFpECPoint* regPublic = (IppsGFpECPoint*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippsGFpECPointInit(NULL, NULL, regPublic, pEC); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += pubKeyCtxByteSize; sts = ippsGFpECPublicKey(regPrivate, regPublic, pEC, pLocDataBuff); if( ippStsNoErr != sts ) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } int ephKeyCtxByteSize; sts = ippsBigNumGetSize(primeWordSize, &ephKeyCtxByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsBigNumState* bnEphPrivate = (IppsBigNumState*)(IPP_ALIGNED_PTR(pLocDataBuff, IPPCP_GFP_ALIGNMENT)); sts = ippcp_init_set_bn(bnEphPrivate, primeWordSize, ippBigNumPOS, (const Ipp32u *)msg_digest, primeWordSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsGFpECPrivateKey(bnEphPrivate, pEC, ippsPRNGen, pRand); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocDataBuff += ephKeyCtxByteSize; int scratchSize; sts = ippsGFpECScratchBufferSize(2, pEC, &scratchSize); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pScratchBuffer = pLocDataBuff; /* RSA Signature Generation */ sts = ippsGFpECSignDSA(bnMsgDigest, regPrivate, bnEphPrivate, bnR, bnS, pEC, pScratchBuffer); if(sts != ippStsNoErr) { MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA Signature Verification */ IppECResult verifRes; sts = ippsGFpECVerifyDSA(bnMsgDigest, regPublic, bnR, bnS, &verifRes, pEC, pScratchBuffer); if( ippECValid != verifRes || ippStsNoErr != sts ) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_3(pGFpBuff, pGFpECBuff, pDataBuff, memMgmFlag) return test_result; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_hash_msg_upd_sha.c000066400000000000000000000164371470420105600305730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" #include "hash/pcphashmethod_rmf.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" /* * KAT TEST * taken from the regular known-answer testing */ // message static const Ipp8u msg[] = "abc"; // known digests static const Ipp8u sha256_md[] = "\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23" "\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad"; static const Ipp8u sha512_md[] = "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31" "\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a" "\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd" "\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f"; static const int msgByteLen = sizeof(msg)-1; #define IPP_SHA256_DIGEST_BYTESIZE (IPP_SHA256_DIGEST_BITSIZE/8) #define IPP_SHA512_DIGEST_BYTESIZE (IPP_SHA512_DIGEST_BITSIZE/8) /* * Since ippcp's implementation of hashes reuses each other, only two methods - * ippsHashMethod_SHA256 and ippsHashMethod_SHA512 may be tested: * CAST for SHA-256 is required; * CAST for SHA-224 is covered by CAST for SHA-256; * CAST for SHA-512 is required; * CAST for SHA-512/224 and SHA-512/256 are covered by CAST for SHA-512; * CAST for SHA-384 is covered by CAST for SHA-512; */ static IppStatus selftestSetTestingMethod(const IppHashAlgId hashAlgIdIn, IppsHashMethod* locMethod, Ipp32u* hashSize, Ipp8u** pMD) { IppStatus sts = ippStsNoErr; switch (hashAlgIdIn) { case IPP_ALG_HASH_SHA224: case IPP_ALG_HASH_SHA256: { sts = ippsHashMethodSet_SHA256_TT(locMethod); *hashSize = IPP_SHA256_DIGEST_BYTESIZE; *pMD = (Ipp8u*)sha256_md; return sts; } case IPP_ALG_HASH_SHA384: case IPP_ALG_HASH_SHA512_224: case IPP_ALG_HASH_SHA512_256: case IPP_ALG_HASH_SHA512: { sts = ippsHashMethodSet_SHA512(locMethod); *hashSize = IPP_SHA512_DIGEST_BYTESIZE; *pMD = (Ipp8u*)sha512_md; return sts; } default: break; } return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IPPFUN(fips_test_status, fips_selftest_ippsHash_rmf_get_size, (int *pBuffSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBuffSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int ctx_size = 0; sts = ippsHashGetSize_rmf(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_HASH_ALIGNMENT; int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } *pBuffSize = ctx_size + hash_method_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsHashUpdate_rmf, (IppHashAlgId hashAlgId, Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; /* check input pointers and allocate memory in "use malloc" mode */ int internalMemMgm = 0; int ctx_size = 0; sts = ippsHashGetSize_rmf(&ctx_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } ctx_size += IPPCP_HASH_ALIGNMENT; int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } BUF_CHECK_NULL_AND_ALLOC(pBuffer, internalMemMgm, (ctx_size + hash_method_size + IPPCP_HASH_ALIGNMENT), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR) Ipp32u locHashByteSize = 0; Ipp8u* md = NULL; IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer + ctx_size + IPPCP_HASH_ALIGNMENT); sts = selftestSetTestingMethod(hashAlgId, locMethod, &locHashByteSize, &md); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* output hash */ Ipp8u outHashBuff[IPP_SHA512_DIGEST_BYTESIZE]; Ipp8u outTagBuff[IPP_SHA512_DIGEST_BYTESIZE]; /* context */ IppsHashState_rmf* hashCtx = (IppsHashState_rmf*)(IPP_ALIGNED_PTR(pBuffer, IPPCP_HASH_ALIGNMENT)); /* context initialization */ sts = ippsHashInit_rmf(hashCtx, locMethod); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* function call */ sts = ippsHashUpdate_rmf(msg, msgByteLen, hashCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsHashGetTag_rmf(outTagBuff, (int)locHashByteSize, hashCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsHashFinal_rmf(outHashBuff, hashCtx); if (sts != ippStsNoErr) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ int isEqual; isEqual = ippcp_is_mem_eq(outTagBuff, locHashByteSize, md, locHashByteSize); isEqual &= ippcp_is_mem_eq(outHashBuff, locHashByteSize, md, locHashByteSize); if (!isEqual) { MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, internalMemMgm) return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsHashMessage_rmf, (IppHashAlgId hashAlgId)) { IppStatus sts = ippStsNoErr; Ipp32u locHashByteSize = 0; Ipp8u* md = NULL; Ipp8u hashMethodArr[sizeof(IppsHashMethod)]; IppsHashMethod* locMethod = (IppsHashMethod*)hashMethodArr; sts = selftestSetTestingMethod(hashAlgId, locMethod, &locHashByteSize, &md); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* output hash */ Ipp8u outHashArr[IPP_SHA512_DIGEST_BYTESIZE]; sts = ippsHashMessage_rmf(msg, msgByteLen, outHashArr, locMethod); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* compare output to known answer */ if (!ippcp_is_mem_eq(outHashArr, locHashByteSize, md, locHashByteSize)) { return IPPCP_ALGO_SELFTEST_KAT_ERR; } return IPPCP_ALGO_SELFTEST_OK; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_lms_verify.c000066400000000000000000000423061470420105600274500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #define IPPCP_PREVIEW_LMS 1 #include "ippcp.h" #include "ippcpdefs.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include #include #include /* * KAT * vectors are generated by NIST CAVP procedure */ /* Message */ __ALIGN64 static const Ipp8u pMsg[] = { 0x04,0x3d,0x64,0x00,0x10,0x3b,0x16,0x0c,0xf1,0x89,0xb4,0xcf,0xff,0x08,0x06,0xfe, 0xe3,0xe1,0x56,0x7f,0x2c,0x31,0x71,0x0f,0x82,0x84,0x52,0x74,0xf6,0xed,0x23,0x8e, 0x14,0xde,0x4d,0x53,0x99,0x86,0x88,0x99,0xab,0x6b,0xcf,0x00,0x98,0x08,0xb8,0xca, 0x30,0x81,0xed,0x11,0xaa,0x70,0x35,0x52,0x90,0xfd,0x86,0x98,0xd4,0xc1,0x77,0xc1, 0x89,0x4c,0xd8,0xb8,0xd3,0x36,0x7f,0xd0,0xf3,0x00,0xef,0x62,0x83,0x02,0x0d,0x09, 0x1c,0x27,0x35,0x6d,0xaf,0xad,0xdb,0xed,0x96,0x21,0x8a,0x19,0x56,0x7b,0x99,0x9a, 0xcd,0x53,0x02,0xa5,0x11,0xd4,0xf1,0x65,0xef,0x9c,0xbe,0x85,0x5d,0xcc,0x73,0x1b, 0x16,0xdd,0x13,0x6e,0x5c,0x44,0x15,0x8b,0xf1,0xe9,0x8c,0xc5,0x9c,0x6f,0x6c,0xb2 }; /* Data for the public key*/ __ALIGN64 static const Ipp8u pI[] = { 0x05,0xbd,0x3d,0x90,0xcc,0xa2,0x47,0x08,0xe4,0x20,0x55,0x3e,0x5a,0xf7,0xb9,0xc8 }; __ALIGN64 static const Ipp8u pK[] = { 0x21,0xf9,0xd9,0x09,0x97,0x11,0xef,0x5b,0x14,0x50,0x0b,0x6a,0x18,0x1e,0x73,0x9e, 0xd3,0x12,0x74,0xdb,0x72,0xac,0xe7,0xcf,0x29,0x32,0x9a,0x45,0xe8,0xde,0x11,0xfe }; /* Data for the signature */ __ALIGN64 static const Ipp8u pC[] = { 0x67,0x79,0x57,0x17,0x51,0x05,0x2c,0xe8,0xfe,0xe9,0x23,0xda,0x26,0xef,0x27,0x1e, 0x62,0xbe,0x08,0x43,0xaa,0xdf,0x7c,0x69,0x19,0x68,0x43,0x32,0x8c,0xb0,0x4e,0x3d }; __ALIGN64 static const Ipp8u pY[] = { 0x57,0x71,0xa7,0x12,0x2b,0x87,0xf2,0xbd,0x61,0x11,0x9c,0xd4,0x20,0x56,0xec,0x04, 0xc0,0x60,0xbe,0x2a,0xe2,0xc2,0xd6,0x72,0xa8,0x1f,0x1a,0x4a,0x6a,0x76,0xc2,0x4c, 0x01,0xa0,0x69,0x63,0x7f,0x85,0xdd,0xb4,0x5d,0x8d,0x19,0xd7,0xef,0x7c,0xc8,0x9a, 0x47,0xfe,0x1e,0x79,0xfd,0x80,0x65,0x51,0x17,0xed,0xb6,0x3f,0x17,0xd0,0xb6,0xcc, 0x0f,0xca,0xa9,0x28,0xc2,0xef,0x1e,0x41,0x4e,0xf7,0x34,0xa8,0xda,0xfe,0xbc,0x82, 0xdb,0x33,0x3e,0x03,0xba,0x51,0x40,0x6e,0x07,0x6b,0xfc,0x2d,0x3e,0x81,0x30,0x09, 0xd9,0x68,0xa8,0x71,0x00,0xf0,0x33,0xcf,0x0b,0x57,0x04,0xfc,0x4e,0x61,0x8a,0xa5, 0x80,0xa1,0xe0,0x48,0xef,0xc3,0xd5,0x6e,0xe7,0xa2,0xea,0x02,0x14,0xa6,0xfe,0x1f, 0x39,0xa4,0xf2,0xfb,0x61,0x2f,0x44,0xbe,0xde,0xd3,0x73,0x34,0x0e,0x76,0x48,0x27, 0xc5,0xc5,0x8c,0xb9,0x07,0xcd,0x08,0xdd,0xfb,0xde,0x01,0xbb,0x11,0xff,0x3a,0x89, 0xff,0xaa,0xd8,0xcd,0x7c,0x17,0x02,0x71,0x08,0x3c,0xe5,0x0f,0x0f,0xb9,0xea,0xbb, 0xa8,0x9d,0xb6,0x0b,0x00,0x73,0xe7,0xaf,0xc8,0x1e,0x4c,0x6f,0x82,0x4a,0xef,0x09, 0xf8,0xbf,0xc9,0x49,0x67,0x16,0x9b,0xcf,0xa0,0x84,0x76,0x55,0x57,0x41,0x10,0x19, 0x37,0x0b,0x29,0xba,0x0d,0x32,0xa8,0x8e,0x84,0x2c,0x19,0xdf,0x14,0x5a,0x69,0x36, 0x8d,0xf7,0xe1,0x55,0x7d,0x93,0x7a,0xae,0xdb,0x07,0xf6,0xbc,0xda,0xf9,0x78,0xeb, 0x9e,0x50,0xf3,0xc8,0x47,0x38,0x2a,0xd4,0x3b,0xfc,0xc0,0xe0,0xd0,0xbf,0xd8,0x60, 0x46,0x63,0xc7,0xfb,0xa8,0x84,0x45,0x4d,0x23,0x98,0x96,0xd8,0xff,0x8a,0x99,0xa3, 0x34,0xf0,0xd3,0x32,0x22,0xaa,0x15,0xbd,0x47,0x9f,0xcd,0x49,0x52,0x0b,0x5b,0x2d, 0x83,0xd8,0xbf,0x4d,0xbd,0x3d,0x7e,0x9d,0xc8,0x0b,0x62,0x0c,0xc7,0x03,0x45,0x7f, 0x55,0x90,0x35,0xdd,0x1f,0x53,0xdc,0xec,0x0b,0x4d,0x89,0xca,0xb1,0xa3,0xb8,0x87, 0x7b,0x31,0x1c,0x24,0x90,0x44,0x9d,0xf7,0xa6,0x1c,0xf8,0xed,0xf3,0x29,0xd6,0x96, 0x26,0xca,0x42,0x4b,0xdf,0x61,0x00,0x91,0x92,0x08,0x37,0x76,0xbb,0x96,0x9e,0xd5, 0x8d,0x76,0xa9,0x52,0x40,0xdb,0x3f,0xd6,0xec,0xa0,0x06,0x89,0x88,0x11,0x18,0x38, 0xae,0xcb,0xa0,0x71,0xab,0x3b,0x7b,0xe0,0x94,0x30,0x59,0x38,0xaf,0xb0,0x8c,0xdd, 0xf9,0xcd,0xaf,0x82,0x49,0x90,0x29,0xf6,0x24,0x9a,0xa5,0x51,0x1b,0x99,0x45,0x64, 0x13,0x94,0x9e,0x3e,0x4e,0x43,0x40,0x73,0x0d,0x68,0x0b,0x68,0xde,0xb5,0xc9,0xd5, 0xce,0xef,0x7b,0x8b,0x1e,0xd9,0x7e,0xc8,0xa1,0x69,0xb5,0x2b,0xd0,0x54,0xb0,0x53, 0x41,0x9f,0xfa,0x77,0x34,0x55,0xcd,0xf4,0x79,0xa6,0x0d,0x3c,0xc7,0x05,0xd8,0xf2, 0x08,0x48,0x32,0xb7,0x96,0x22,0xb6,0xe5,0xac,0x83,0x06,0xa7,0x68,0x3f,0xea,0x03, 0xcd,0x79,0xe8,0xff,0x54,0xe2,0xf5,0xa0,0x6b,0x69,0xc1,0xca,0xb3,0xd4,0x2b,0x60, 0xa8,0xa8,0xbe,0xcb,0x9e,0x94,0x2e,0xf1,0xfc,0xd7,0x55,0xac,0x08,0xd7,0xc4,0x22, 0x4f,0xf3,0xf5,0xbf,0x49,0xb8,0xf7,0x5f,0xae,0x60,0x92,0xe4,0x3a,0x8f,0x30,0x35, 0x41,0x8c,0xd4,0x03,0x31,0x6c,0x08,0xa8,0x08,0x37,0xb4,0x6c,0x22,0xca,0xa2,0xf7, 0xff,0xc1,0x62,0x49,0xcd,0x5c,0x17,0x25,0xc5,0x4e,0xaa,0x26,0xb9,0xd7,0x72,0xf9, 0x61,0x21,0xbf,0x95,0xda,0xcf,0x30,0x1d,0x42,0x8c,0x9d,0xf4,0x57,0x36,0x25,0xb7, 0xfb,0xfa,0x64,0xba,0x7f,0x3e,0x0d,0x5a,0x72,0xa7,0x8d,0x13,0xf6,0x2d,0x57,0x76, 0xa4,0x61,0x59,0x9d,0x4d,0xd5,0x99,0x0e,0xae,0x73,0x6b,0x6a,0xf1,0x64,0x93,0xf1, 0xa7,0xd0,0xe4,0x4f,0x2b,0x71,0xd9,0x6e,0x0e,0x89,0x28,0x5a,0xec,0xc1,0x15,0x50, 0x81,0x21,0x6c,0xe0,0xba,0xbb,0xce,0x4f,0x4e,0x0b,0x80,0xa1,0x92,0x6a,0xea,0x6a, 0xcb,0x3e,0xa3,0xcb,0x7a,0x23,0x61,0x5d,0x41,0x08,0xba,0xf4,0x51,0x9b,0xf7,0x10, 0x27,0x0e,0x89,0x6b,0x42,0xc5,0x5c,0x3c,0x9e,0x60,0x42,0x43,0x29,0xbf,0xbc,0x8a, 0xd5,0x9f,0x4c,0xa2,0x0b,0x5e,0xbb,0xa4,0x93,0xe0,0xb3,0x9d,0xb9,0x7e,0xc7,0x9b, 0x36,0x2a,0xc7,0x21,0x5e,0x25,0x5d,0xeb,0x74,0x68,0xfd,0xf4,0x0e,0x0f,0x39,0x0c, 0x65,0x0c,0x66,0x51,0x0c,0xf4,0xad,0x9c,0x44,0x94,0x34,0xae,0x25,0x8b,0x56,0x1e, 0x8e,0xc1,0x57,0x29,0xa6,0x90,0x62,0xb8,0xb2,0x8d,0x6c,0x79,0xf4,0x90,0x64,0xd2, 0x4a,0x52,0xe9,0x15,0x95,0xc9,0x3f,0x83,0xc4,0x0f,0xec,0xa2,0x11,0xe2,0x8b,0x50, 0x1f,0x13,0xcc,0x80,0x2f,0x0b,0x36,0x35,0x2c,0x85,0x41,0x79,0xd2,0xce,0x46,0x12, 0xc7,0xf0,0xd3,0x96,0x04,0x4d,0x1c,0x69,0x4f,0x8f,0xe3,0xa0,0x1c,0xe2,0xa8,0x8c, 0xe8,0xd1,0x74,0xca,0x66,0x99,0x1b,0x9d,0x6c,0x50,0x72,0xf2,0xd2,0x01,0x60,0xdf, 0x74,0x81,0xaf,0xbd,0x7a,0xc9,0xd2,0xf7,0x5a,0x7d,0xfe,0x36,0x9c,0x61,0xed,0xc9, 0xfb,0x27,0xbb,0xa3,0xd8,0x71,0x3c,0x57,0x5d,0xdd,0xab,0xcc,0x27,0xc6,0xb9,0x42, 0x9b,0xcb,0x7e,0xec,0xf8,0x53,0x2e,0xf0,0xf4,0xc9,0x46,0x46,0xd8,0x94,0xd6,0xf7, 0x8d,0x64,0xd7,0xba,0xb1,0x39,0x8e,0x7f,0xef,0xfd,0xb0,0xb0,0x31,0x4f,0x43,0x0f, 0xec,0xa8,0x70,0x57,0x3a,0xe3,0x88,0xbc,0xa7,0xd9,0xf9,0x39,0xa4,0xb9,0x91,0x59, 0xc7,0xbf,0xec,0x78,0xa9,0xce,0x33,0x99,0xf3,0x83,0xfa,0xaf,0x59,0xab,0x65,0xc6, 0xe2,0xaa,0x30,0x08,0xd7,0x99,0x71,0x65,0xf1,0xb6,0xfc,0x4f,0xf1,0x68,0xa2,0xd8, 0x61,0x8a,0xe5,0x0f,0x2b,0x60,0xda,0x8d,0xea,0x7e,0xf6,0x2c,0xae,0xeb,0x26,0xae, 0x29,0x5d,0xab,0xc7,0x3f,0x27,0x2c,0x51,0xf1,0x3f,0x22,0x22,0xef,0x52,0x4e,0xcb, 0x70,0xd8,0xba,0x41,0x53,0xb4,0xd9,0xdd,0xdc,0xe8,0xcd,0x7f,0xc1,0xb8,0x2b,0x8e, 0x3b,0x3b,0x86,0xd7,0x4c,0x36,0x69,0xf6,0x31,0xcf,0x37,0xbd,0x16,0xe9,0x2f,0x4f, 0xf9,0x13,0x19,0xf2,0x3b,0x41,0x1c,0x78,0x62,0x9c,0x5f,0x95,0xab,0xdd,0x17,0xe7, 0x2e,0x8f,0x92,0x79,0xe0,0xeb,0xe0,0x49,0x58,0x6d,0x3c,0x26,0xb8,0x5c,0x93,0xb9, 0xd7,0x6e,0xca,0x28,0x70,0x9c,0xbe,0xef,0x08,0x4e,0xe2,0x20,0x3a,0xdb,0x92,0x0b, 0x29,0x2f,0xfd,0xc8,0x3a,0x4a,0x7c,0xa4,0x87,0x6f,0x33,0x8d,0x8e,0x7f,0x51,0x6f, 0xab,0x11,0x42,0xc3,0x75,0xed,0x69,0xb1,0xf1,0x32,0xd8,0xd8,0xe2,0xc2,0x0d,0x52, 0x21,0xad,0x97,0x05,0x60,0x1d,0x43,0x52,0x4c,0xb1,0x61,0x49,0xef,0x2c,0xc1,0xad, 0x4c,0x0c,0xe7,0x1b,0x81,0xc6,0x2f,0x47,0xe2,0xb0,0xe6,0x6c,0xb8,0xd0,0x2d,0xe4, 0x46,0xd2,0x0a,0x13,0xab,0xb3,0xb9,0x13,0x9e,0x41,0xba,0x06,0x2d,0x11,0xe4,0xe6 }; __ALIGN64 static const Ipp8u pAuthPath[] = { 0xc7,0x14,0x06,0x72,0xbf,0x82,0x00,0x91,0xe3,0xd5,0xd6,0x4c,0x2a,0x71,0x21,0x83, 0x3b,0xea,0xb1,0x16,0x74,0xd8,0xae,0x4e,0xe3,0x15,0xe7,0x85,0x4d,0xa7,0xa1,0x00, 0x4b,0x2b,0x7b,0xc6,0xad,0x89,0xa8,0x6c,0xe8,0xf6,0x60,0x22,0x19,0xb9,0xc3,0x37, 0x5b,0xca,0x93,0xf1,0x0e,0xa3,0x2f,0x10,0xfb,0x2f,0x39,0x21,0x1c,0x33,0x78,0xb7, 0x89,0x0f,0x77,0x18,0xe8,0x73,0x04,0x54,0x71,0x08,0x0b,0x86,0x94,0x9e,0xc7,0x55, 0x25,0xb9,0x4a,0xe1,0xbb,0x45,0x06,0x00,0x66,0xdf,0x75,0x17,0x8b,0x0d,0xc3,0xa6, 0x65,0x9a,0x5e,0xc7,0x5d,0xe5,0xc1,0x29,0x1f,0x5f,0xfc,0xcb,0x89,0x84,0x5c,0xfb, 0x7a,0x81,0xe2,0x54,0x05,0xd1,0x90,0xe3,0x7d,0xe4,0x3c,0x9f,0xe2,0xdc,0xd3,0xfd, 0x7e,0x6e,0x72,0xfa,0xc7,0xbe,0xcb,0xd5,0xd0,0x1e,0xc4,0xae,0x48,0x9a,0x92,0x45, 0xc3,0xc2,0xc1,0x06,0x91,0xbe,0x15,0x1f,0xa6,0xa1,0x87,0xbb,0x7c,0x68,0x7b,0xb8 }; static const Ipp32u msgByteLen = sizeof(pMsg); static const Ipp32u q = 0x00000009; static const IppsLMOTSAlgo lmotsAlgo = LMOTS_SHA256_N32_W8; static const IppsLMOTSAlgo lmotsAlgoSig = LMOTS_SHA256_N32_W8; static const IppsLMSAlgo lmsAlgo = LMS_SHA256_M32_H5; static const IppsLMSAlgo lmsAlgoSig = LMS_SHA256_M32_H5; IPPFUN(fips_test_status, fips_selftest_ippsLMSVerify_get_size, (int *pBufferSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; int tmp_size = 0; IppsLMSAlgoType lmsAlgTypePk; lmsAlgTypePk.lmotsOIDAlgo = lmotsAlgo; lmsAlgTypePk.lmsOIDAlgo = lmsAlgo; /* temporary buf size */ sts = ippsLMSBufferGetSize(&tmp_size, msgByteLen, lmsAlgTypePk); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_HASH_ALIGNMENT); sts = ippsLMSPublicKeyStateGetSize(&tmp_size, lmsAlgTypePk); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_HASH_ALIGNMENT); sts = ippsLMSSignatureStateGetSize(&tmp_size, lmsAlgTypePk); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_HASH_ALIGNMENT); *pBufferSize = total_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsLMSVerify,(Ipp8u *pBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Test underlying Hash Message function */ const IppHashAlgId hash_method = ippHashAlg_SHA256; test_result = fips_selftest_ippsHashMessage_rmf(hash_method); if (test_result != IPPCP_ALGO_SELFTEST_OK) { return test_result; } /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL) { internalMemMgm = 1; int dataBuffSize = 0; sts = fips_selftest_ippsLMSVerify_get_size(&dataBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif Ipp8u* pLocBuffer = pBuffer; IppsLMSAlgoType lmsAlgTypePk; lmsAlgTypePk.lmotsOIDAlgo = lmotsAlgo; lmsAlgTypePk.lmsOIDAlgo = lmsAlgo; /* buffer for the public key */ int pubKeySize; sts = ippsLMSPublicKeyStateGetSize(&pubKeySize, lmsAlgTypePk); if(sts != ippStsNoErr) { MEMORY_FREE(pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocBuffer = (IPP_ALIGNED_PTR(pLocBuffer, IPPCP_HASH_ALIGNMENT)); IppsLMSPublicKeyState* pPubKey = (IppsLMSPublicKeyState*)pLocBuffer; pLocBuffer += pubKeySize; /* buffer for the generated signature */ int sigBuffSize = 0; sts = ippsLMSSignatureStateGetSize(&sigBuffSize, lmsAlgTypePk); if(sts != ippStsNoErr) { MEMORY_FREE(pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocBuffer = (IPP_ALIGNED_PTR(pLocBuffer, IPPCP_HASH_ALIGNMENT)); IppsLMSSignatureState* pSignature = (IppsLMSSignatureState*)pLocBuffer; pLocBuffer += sigBuffSize; /* buffer for the temporary memory */ int buffSize; sts = ippsLMSBufferGetSize(&buffSize, msgByteLen, lmsAlgTypePk); if(sts != ippStsNoErr) { MEMORY_FREE(pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocBuffer = (IPP_ALIGNED_PTR(pLocBuffer, IPPCP_HASH_ALIGNMENT)); Ipp8u* pScratchBuffer = pLocBuffer; pLocBuffer += buffSize; /* Initialize the public key */ sts = ippsLMSSetPublicKeyState(lmsAlgTypePk, pI, pK, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE(pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize the signature */ IppsLMSAlgoType lmsAlgTypeSig; lmsAlgTypeSig.lmotsOIDAlgo = lmotsAlgoSig; lmsAlgTypeSig.lmsOIDAlgo = lmsAlgoSig; sts = ippsLMSSetSignatureState(lmsAlgTypeSig, q, pC, pY, pAuthPath, pSignature); if(sts != ippStsNoErr) { MEMORY_FREE(pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Call the LMS verification function */ int is_valid=0; sts = ippsLMSVerify(pMsg, msgByteLen, pSignature, &is_valid, pPubKey, pScratchBuffer); if(sts != ippStsNoErr) { MEMORY_FREE(pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Check if verification is failed */ if(1 != is_valid) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE(pBuffer, memMgmFlag) return test_result; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_rsa_enc_dec_oaep.c000066400000000000000000000541611470420105600305240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #include "fips_cert_internal/bn_common.h" /* * KAT * vectors are taken from Wycheproof testing */ // KAT plaintext __ALIGN64 static const Ipp8u pMsg[] = { 0x31,0x32,0x33,0x34,0x30,0x30 }; // KAT seed (all 1) __ALIGN64 static const Ipp8u seed[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff"; // KAT ciphertext __ALIGN64 static const Ipp8u ctext[] = { 0x50,0xc2,0x3e,0x2a,0xd6,0xe3,0xf3,0xb1,0x0a,0x57,0x16,0xcb,0xf6,0x0e,0xfc,0xc9, 0xf6,0x6d,0x2c,0x6f,0x17,0xbf,0x05,0x0b,0xa0,0x15,0x3b,0x87,0x7b,0xa2,0x75,0x5e, 0x8a,0x0d,0x54,0x06,0x00,0x34,0x56,0x22,0x66,0x15,0x57,0x44,0xef,0x80,0x54,0x7b, 0x8a,0xf7,0x77,0xb0,0xff,0x76,0x4f,0xbb,0x12,0xba,0xae,0x49,0xd0,0x2b,0x4f,0x6d, 0x65,0xb6,0xcd,0x8f,0x0a,0x39,0x78,0x39,0x10,0x1d,0x32,0xae,0x16,0x3f,0xf2,0xe6, 0x07,0x27,0x48,0xd6,0xb8,0x01,0x7e,0x5e,0x73,0xe3,0x32,0xd5,0x3f,0x4e,0x91,0xfe, 0x62,0x33,0xa8,0x2d,0xbf,0x54,0xf3,0x14,0x6b,0x48,0x98,0x03,0x57,0x5c,0x5e,0xa3, 0x7a,0xb5,0x5a,0x9e,0xa7,0xea,0xe4,0x7a,0xd4,0xf1,0x72,0x7d,0x45,0x82,0x2b,0x56, 0x9c,0xd6,0xe5,0xd4,0xb6,0xab,0x75,0x98,0x50,0x94,0x81,0x86,0x61,0x6b,0x5d,0xa2, 0xa9,0xa3,0x16,0xf5,0x7d,0x89,0x9f,0x91,0x93,0x4b,0xbb,0x27,0xed,0xcd,0xfa,0x19, 0x53,0x2b,0xa1,0xc0,0x1f,0x37,0x24,0x73,0x8d,0xaf,0xfd,0xd8,0x8c,0x9a,0x18,0x56, 0x2e,0xbc,0xbc,0x49,0x18,0x5b,0x0a,0x81,0x74,0x07,0x90,0x34,0x76,0xd4,0x42,0xc4, 0x24,0xc8,0x1b,0x63,0xae,0xb8,0xf9,0xd1,0xb1,0x84,0x75,0x6e,0x0c,0xc0,0xa3,0x81, 0xea,0xba,0x45,0xa8,0x5c,0x8b,0xbc,0x67,0x70,0xfd,0x04,0x7f,0xf1,0xa6,0x40,0x4a, 0x38,0x45,0x99,0xfb,0xbd,0x6a,0x40,0xb2,0x12,0xa0,0x66,0xe2,0x3f,0x6a,0x15,0xcf, 0x13,0xe4,0x2c,0x0e,0xa8,0x8c,0x71,0x0e,0x4d,0x70,0xc6,0x12,0x07,0x49,0x68,0xe5 }; // KAT modulus, public and private exponents __ALIGN64 static const Ipp8u dataN[] = { 0xd5,0xb9,0x42,0xf7,0x83,0x02,0x82,0xf7,0x9c,0x2e,0x4c,0x5b,0x1f,0x3d,0x45,0x6f, 0x06,0x73,0xe7,0x30,0xa5,0xe5,0x02,0x9a,0x3b,0x7d,0x80,0x62,0x9a,0x56,0x12,0x5d, 0xa4,0xc1,0xf7,0xc0,0x5a,0x4e,0x2c,0xc2,0x9b,0x5d,0x00,0x75,0x79,0x5e,0xf8,0xf9, 0xd8,0x60,0xd4,0x79,0xae,0x9c,0x4d,0x1b,0xba,0xcb,0x8b,0x69,0x48,0x6f,0x81,0x69, 0x19,0x5a,0x97,0x90,0xf5,0x22,0x64,0x12,0xf1,0xa0,0xad,0x09,0x3e,0xfc,0x7a,0xfd, 0x05,0xaf,0x8d,0x87,0xeb,0x11,0x54,0xed,0xd4,0x95,0x34,0x5d,0x5b,0x14,0x03,0x4c, 0x6b,0xce,0x1e,0x4d,0xde,0x82,0xbe,0x12,0x5a,0x94,0x8d,0xa0,0xec,0xfc,0xd0,0x21, 0xc0,0xf5,0x66,0x42,0x59,0x58,0x96,0x7d,0x9c,0xe0,0x28,0x04,0x61,0xda,0x22,0x4c, 0x81,0xd9,0x15,0x96,0x29,0x81,0xed,0x90,0xf4,0x26,0xce,0x8d,0x6a,0xa2,0x1f,0x7a, 0x39,0x29,0xa0,0xe1,0x17,0x8f,0xff,0x3e,0xa0,0x13,0x53,0x76,0xe9,0x2f,0x4a,0x25, 0x8e,0xc9,0x48,0x6e,0xe4,0x42,0x3e,0x3d,0x7f,0x24,0xe8,0x15,0x9c,0xf7,0x20,0xcd, 0xfa,0x53,0x12,0x1a,0x71,0xa7,0xd8,0x2e,0x51,0x92,0xdb,0x89,0x31,0x39,0xab,0xb5, 0x97,0x50,0x84,0xc8,0xea,0xd6,0x89,0x9e,0x42,0x69,0xb4,0x03,0x59,0xf6,0x00,0x17, 0x5a,0xef,0xb6,0x25,0x03,0xd8,0x78,0x18,0xd3,0xaf,0x7c,0x3f,0x6d,0x74,0xf9,0x37, 0xe6,0x24,0x22,0xe8,0xfe,0xa1,0x4f,0x09,0x17,0xf7,0xbe,0x2e,0x46,0x5b,0x8a,0x4a, 0x51,0x50,0x35,0x51,0x71,0x56,0x45,0x6e,0xf9,0xa5,0x0a,0x7d,0xa0,0x51,0xb4,0xa2 }; __ALIGN64 static const Ipp8u dataD[] = { 0xc1,0x67,0xc4,0x89,0x72,0xbe,0xec,0xb1,0xb7,0x1b,0x17,0xdf,0xdc,0xec,0x0e,0x72, 0x00,0xb7,0xf3,0xfe,0xc6,0x04,0x6d,0xf6,0xd6,0xb0,0x85,0x09,0xf5,0x15,0xe7,0xba, 0xf8,0xe6,0xba,0x50,0x69,0xa7,0x8d,0xbc,0x59,0x12,0xc0,0xaf,0xc5,0xf4,0xdf,0xb8, 0x94,0xee,0xe7,0x26,0xa1,0xe5,0x73,0x86,0x6c,0x3b,0xc4,0xd5,0x4a,0xdb,0xe8,0x95, 0x59,0xa9,0x51,0xb6,0xa8,0x9e,0xdb,0xfb,0xc8,0x3a,0x4c,0x07,0x1c,0xd0,0xac,0xa1, 0x0a,0x05,0x51,0x9f,0x38,0x97,0xc1,0x4f,0x23,0x2b,0x75,0x0d,0xbf,0x0b,0xae,0x29, 0xec,0x33,0x62,0xb9,0x96,0x6c,0xf7,0x99,0x43,0xff,0x1e,0x28,0xd9,0x1e,0xcc,0xe6, 0xc2,0x09,0x99,0x5b,0xe0,0x5a,0xd4,0xfd,0xa0,0x66,0x43,0xf4,0x37,0xf5,0x7b,0x51, 0xee,0xeb,0x21,0x78,0x2d,0x24,0x54,0x66,0xff,0xca,0xc8,0x3f,0xac,0x93,0x7d,0x6f, 0x13,0x9f,0x7c,0x79,0x4c,0x05,0xb5,0xff,0xaa,0xaa,0x20,0x10,0xde,0x41,0x47,0x4b, 0x0b,0xe0,0xdb,0x19,0xbf,0xdb,0x42,0xe0,0xcd,0x4a,0xdb,0x67,0x09,0xc1,0xe7,0xc4, 0x99,0xe8,0xc4,0x10,0x03,0x11,0x2e,0x23,0x90,0xb3,0x04,0x72,0xb1,0x68,0x7a,0xac, 0xe2,0x4f,0xc8,0xce,0xcf,0x77,0xf4,0x6f,0x3f,0x82,0x05,0x3d,0xac,0x4d,0x3a,0x54, 0x64,0x9f,0x13,0xe7,0x0a,0xfa,0x0b,0xa0,0xc4,0xf3,0xc6,0xef,0x88,0xfa,0xa4,0x3c, 0x57,0xb7,0x66,0x3c,0x5b,0x6a,0x30,0x9b,0x81,0xee,0xdc,0x9d,0xcb,0x2c,0x17,0xa7, 0xc3,0x31,0xcd,0x3e,0x05,0x52,0x8e,0x26,0x27,0x2a,0x7b,0x56,0xf3,0xee,0x27,0x76 }; __ALIGN64 static const Ipp8u dataE[] = { 0x01, 0x00, 0x01 }; static const unsigned int pubExpBitSize = 17; static const unsigned int privExpBitSize = 2048; static const unsigned int modulusBitSize = 2048; #define IPPCP_MSG_BYTE_LEN sizeof(pMsg) #define IPPCP_CTEXT_BYTE_LEN sizeof(ctext) #define IPPCP_PRIV_EXP_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(privExpBitSize)) #define IPPCP_PUB_EXP_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(pubExpBitSize)) #define IPPCP_MODULUS_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(modulusBitSize)) IPPFUN(fips_test_status, fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys, (int *pKeysBufferSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pKeysBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; int tmp_size = 0; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size + IPPCP_BN_ALIGNMENT); // E sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size + IPPCP_BN_ALIGNMENT); // D sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size + IPPCP_BN_ALIGNMENT); // N sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size + IPPCP_RSA_ALIGNMENT); // pPubKey sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &tmp_size); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size += (tmp_size + IPPCP_RSA_ALIGNMENT); // pPrivKey *pKeysBufferSize = total_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size, (int *pBufferSize, Ipp8u *pKeysBuffer)) { /* return bad status if input pointers are NULL */ IPP_BADARG_RET((NULL == pBufferSize) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataE, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataD, IPPCP_PRIV_EXP_WORD_SIZE); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataN, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* Initialize key pair - necessary to obtain signature size */ // private key int privKeyByteSize = 0; sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &privKeyByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrivKey = (IppsRSAPrivateKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPrivateKeyType1(modulusBitSize, privExpBitSize, pPrivKey, privKeyByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; pLocKeysBuffer+=privKeyByteSize; // public key int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* Set key pair */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; sts = ippsRSA_SetPrivateKeyType1(bnN, bnD, pPrivKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* RSA decryption and encryption buffers */ int decBufSize; sts = ippsRSA_GetBufferSizePrivateKey(&decBufSize, pPrivKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; int encBufSize; sts = ippsRSA_GetBufferSizePublicKey(&encBufSize, pPubKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; total_size = IPP_MAX(decBufSize, encBufSize) + IPPCP_RSA_ALIGNMENT; /* Add an extra memory for the hash method*/ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } *pBufferSize = total_size + hash_method_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsRSAEncrypt_OAEP_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys(&keysBuffSize); pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size(&dataBuffSize, pKeysBuffer); pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Buffer for the encrypted text */ Ipp8u OutCtxt[IPPCP_CTEXT_BYTE_LEN]; Ipp8u* pOutCtxt = OutCtxt; Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataE, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataN, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize public key */ int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Set public key */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA encryption */ int encBufSize; sts = ippsRSA_GetBufferSizePublicKey(&encBufSize, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* encScratchBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); sts = ippsRSAEncrypt_OAEP_rmf(pMsg, IPPCP_MSG_BYTE_LEN, 0, 0, seed, pOutCtxt, pPubKey, locMethod, encScratchBuffer); int sigFlagErr = ippcp_is_mem_eq(ctext, IPPCP_CTEXT_BYTE_LEN, pOutCtxt, IPPCP_CTEXT_BYTE_LEN); if(1 != sigFlagErr || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } IPPFUN(fips_test_status, fips_selftest_ippsRSADecrypt_OAEP_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys(&keysBuffSize); pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size(&dataBuffSize, pKeysBuffer); pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Buffer for the deciphered text */ Ipp8u OutPtxt[IPPCP_MSG_BYTE_LEN]; Ipp8u* pOutPtxt = OutPtxt; Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataD, IPPCP_PRIV_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)dataN, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize private key */ int privKeyByteSize = 0; sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &privKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrivKey = (IppsRSAPrivateKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPrivateKeyType1(modulusBitSize, privExpBitSize, pPrivKey, privKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Set private key */ sts = ippsRSA_SetPrivateKeyType1(bnN, bnD, pPrivKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA decryption */ int decBufSize; sts = ippsRSA_GetBufferSizePrivateKey(&decBufSize, pPrivKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* decScratchBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); int ptxtLen; sts = ippsRSADecrypt_OAEP_rmf(ctext, 0, 0, pOutPtxt, &ptxtLen, pPrivKey, locMethod, decScratchBuffer); int sigFlagErr = ippcp_is_mem_eq(pMsg, IPPCP_MSG_BYTE_LEN, pOutPtxt, IPPCP_MSG_BYTE_LEN); if(1 != sigFlagErr || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_rsa_sign_verify_pkcs_v15.c000066400000000000000000000563411470420105600322010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include "ippcp/fips_cert.h" #include "fips_cert_internal/common.h" #include "fips_cert_internal/bn_common.h" /* * KAT * vectors are taken from Wycheproof */ __ALIGN64 static const Ipp8u pPrivExp[] = { 0xc1,0x67,0xc4,0x89,0x72,0xbe,0xec,0xb1,0xb7,0x1b,0x17,0xdf,0xdc,0xec,0x0e,0x72, 0x00,0xb7,0xf3,0xfe,0xc6,0x04,0x6d,0xf6,0xd6,0xb0,0x85,0x09,0xf5,0x15,0xe7,0xba, 0xf8,0xe6,0xba,0x50,0x69,0xa7,0x8d,0xbc,0x59,0x12,0xc0,0xaf,0xc5,0xf4,0xdf,0xb8, 0x94,0xee,0xe7,0x26,0xa1,0xe5,0x73,0x86,0x6c,0x3b,0xc4,0xd5,0x4a,0xdb,0xe8,0x95, 0x59,0xa9,0x51,0xb6,0xa8,0x9e,0xdb,0xfb,0xc8,0x3a,0x4c,0x07,0x1c,0xd0,0xac,0xa1, 0x0a,0x05,0x51,0x9f,0x38,0x97,0xc1,0x4f,0x23,0x2b,0x75,0x0d,0xbf,0x0b,0xae,0x29, 0xec,0x33,0x62,0xb9,0x96,0x6c,0xf7,0x99,0x43,0xff,0x1e,0x28,0xd9,0x1e,0xcc,0xe6, 0xc2,0x09,0x99,0x5b,0xe0,0x5a,0xd4,0xfd,0xa0,0x66,0x43,0xf4,0x37,0xf5,0x7b,0x51, 0xee,0xeb,0x21,0x78,0x2d,0x24,0x54,0x66,0xff,0xca,0xc8,0x3f,0xac,0x93,0x7d,0x6f, 0x13,0x9f,0x7c,0x79,0x4c,0x05,0xb5,0xff,0xaa,0xaa,0x20,0x10,0xde,0x41,0x47,0x4b, 0x0b,0xe0,0xdb,0x19,0xbf,0xdb,0x42,0xe0,0xcd,0x4a,0xdb,0x67,0x09,0xc1,0xe7,0xc4, 0x99,0xe8,0xc4,0x10,0x03,0x11,0x2e,0x23,0x90,0xb3,0x04,0x72,0xb1,0x68,0x7a,0xac, 0xe2,0x4f,0xc8,0xce,0xcf,0x77,0xf4,0x6f,0x3f,0x82,0x05,0x3d,0xac,0x4d,0x3a,0x54, 0x64,0x9f,0x13,0xe7,0x0a,0xfa,0x0b,0xa0,0xc4,0xf3,0xc6,0xef,0x88,0xfa,0xa4,0x3c, 0x57,0xb7,0x66,0x3c,0x5b,0x6a,0x30,0x9b,0x81,0xee,0xdc,0x9d,0xcb,0x2c,0x17,0xa7, 0xc3,0x31,0xcd,0x3e,0x05,0x52,0x8e,0x26,0x27,0x2a,0x7b,0x56,0xf3,0xee,0x27,0x76 }; __ALIGN64 static const Ipp8u pPubExp[] = { 0x01,0x00,0x01}; __ALIGN64 static const Ipp8u pModulus[] = { 0xd5,0xb9,0x42,0xf7,0x83,0x02,0x82,0xf7,0x9c,0x2e,0x4c,0x5b,0x1f,0x3d,0x45,0x6f, 0x06,0x73,0xe7,0x30,0xa5,0xe5,0x02,0x9a,0x3b,0x7d,0x80,0x62,0x9a,0x56,0x12,0x5d, 0xa4,0xc1,0xf7,0xc0,0x5a,0x4e,0x2c,0xc2,0x9b,0x5d,0x00,0x75,0x79,0x5e,0xf8,0xf9, 0xd8,0x60,0xd4,0x79,0xae,0x9c,0x4d,0x1b,0xba,0xcb,0x8b,0x69,0x48,0x6f,0x81,0x69, 0x19,0x5a,0x97,0x90,0xf5,0x22,0x64,0x12,0xf1,0xa0,0xad,0x09,0x3e,0xfc,0x7a,0xfd, 0x05,0xaf,0x8d,0x87,0xeb,0x11,0x54,0xed,0xd4,0x95,0x34,0x5d,0x5b,0x14,0x03,0x4c, 0x6b,0xce,0x1e,0x4d,0xde,0x82,0xbe,0x12,0x5a,0x94,0x8d,0xa0,0xec,0xfc,0xd0,0x21, 0xc0,0xf5,0x66,0x42,0x59,0x58,0x96,0x7d,0x9c,0xe0,0x28,0x04,0x61,0xda,0x22,0x4c, 0x81,0xd9,0x15,0x96,0x29,0x81,0xed,0x90,0xf4,0x26,0xce,0x8d,0x6a,0xa2,0x1f,0x7a, 0x39,0x29,0xa0,0xe1,0x17,0x8f,0xff,0x3e,0xa0,0x13,0x53,0x76,0xe9,0x2f,0x4a,0x25, 0x8e,0xc9,0x48,0x6e,0xe4,0x42,0x3e,0x3d,0x7f,0x24,0xe8,0x15,0x9c,0xf7,0x20,0xcd, 0xfa,0x53,0x12,0x1a,0x71,0xa7,0xd8,0x2e,0x51,0x92,0xdb,0x89,0x31,0x39,0xab,0xb5, 0x97,0x50,0x84,0xc8,0xea,0xd6,0x89,0x9e,0x42,0x69,0xb4,0x03,0x59,0xf6,0x00,0x17, 0x5a,0xef,0xb6,0x25,0x03,0xd8,0x78,0x18,0xd3,0xaf,0x7c,0x3f,0x6d,0x74,0xf9,0x37, 0xe6,0x24,0x22,0xe8,0xfe,0xa1,0x4f,0x09,0x17,0xf7,0xbe,0x2e,0x46,0x5b,0x8a,0x4a, 0x51,0x50,0x35,0x51,0x71,0x56,0x45,0x6e,0xf9,0xa5,0x0a,0x7d,0xa0,0x51,0xb4,0xa2 }; __ALIGN64 static const Ipp8u pMsg[] = { 0x54, 0x65, 0x73, 0x74 }; __ALIGN64 static const Ipp8u pSig[] = { 0x26,0x44,0x91,0xe8,0x44,0xc1,0x19,0xf1,0x4e,0x42,0x5c,0x03,0x28,0x21,0x39,0xa5, 0x58,0xdc,0xda,0xeb,0x82,0xa4,0x62,0x81,0x73,0xcd,0x40,0x7f,0xd3,0x19,0xf9,0x07, 0x6e,0xae,0xbc,0x0d,0xd8,0x7a,0x1c,0x22,0xe4,0xd1,0x78,0x39,0x09,0x68,0x86,0xd5, 0x8a,0x9d,0x5b,0x7f,0x7a,0xeb,0x63,0xef,0xec,0x56,0xc4,0x5a,0xc7,0xbe,0xad,0x42, 0x03,0xb6,0x88,0x6e,0x1f,0xaa,0x90,0xe0,0x28,0xec,0x0a,0xe0,0x94,0xd4,0x6b,0xf3, 0xf9,0x7e,0xfd,0xd1,0x90,0x45,0xcf,0xbc,0x25,0xa1,0xab,0xda,0x24,0x32,0x63,0x9f, 0x98,0x76,0x40,0x5c,0x0d,0x68,0xf8,0xed,0xbf,0x04,0x7c,0x12,0xa4,0x54,0xf7,0x68, 0x1d,0x5d,0x5a,0x2b,0x54,0xbd,0x37,0x23,0xd1,0x93,0xdb,0xad,0x43,0x38,0xba,0xad, 0x75,0x32,0x64,0x00,0x6e,0x2d,0x08,0x93,0x1c,0x4b,0x8b,0xb7,0x9a,0xa1,0xc9,0xca, 0xd1,0x0e,0xb6,0x60,0x5f,0x87,0xc5,0x83,0x1f,0x6e,0x2b,0x08,0xe0,0x02,0xf9,0xc6, 0xf2,0x11,0x41,0xf5,0x84,0x1d,0x92,0x72,0x7d,0xd3,0xe1,0xd9,0x9c,0x36,0xbc,0x56, 0x0d,0xa3,0xc9,0x06,0x7d,0xf9,0x9f,0xca,0xf8,0x18,0x94,0x1f,0x72,0x58,0x8b,0xe3, 0x30,0x32,0xba,0xd2,0x2c,0xaf,0x67,0x04,0x22,0x3b,0xb1,0x14,0xd5,0x75,0xb6,0xd0, 0x2d,0x9d,0x22,0x2b,0x58,0x00,0x05,0xd9,0x30,0xe8,0xf4,0x0c,0xce,0x9f,0x67,0x2e, 0xeb,0xb6,0x34,0xa2,0x01,0x77,0xd8,0x43,0x51,0x62,0x79,0x64,0xb8,0x3f,0x20,0x53, 0xd7,0x36,0xa8,0x4a,0xb1,0xa0,0x05,0xf6,0x3b,0xd5,0xba,0x94,0x3d,0xe6,0x20,0x5c }; static const unsigned int msgByteLen = sizeof(pMsg); static const unsigned int pubExpBitSize = 24; static const unsigned int privExpBitSize = 2048; static const unsigned int modulusBitSize = 2048; #define IPPCP_PUB_EXP_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(pubExpBitSize)) #define IPPCP_PRIV_EXP_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(privExpBitSize)) #define IPPCP_MODULUS_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(modulusBitSize)) IPPFUN(fips_test_status, fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys, (int *pKeysBufferSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pKeysBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; int tmp_size = 0; /* BIGNUMs sizes */ sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_BN_ALIGNMENT); // D sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_BN_ALIGNMENT); // E sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_BN_ALIGNMENT); // N /* Public and private keys context size */ sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_RSA_ALIGNMENT); // pPubKey sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += (tmp_size + IPPCP_RSA_ALIGNMENT); // pPrvKey *pKeysBufferSize = total_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size, (int *pBufferSize, Ipp8u *pKeysBuffer)) { /* return bad status if input pointers are NULL */ IPP_BADARG_RET((NULL == pKeysBuffer) || (NULL == pBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; Ipp8u *pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPrivExp, IPPCP_PRIV_EXP_WORD_SIZE); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize key pair - necessary to obtain signature size */ int pubKeySize; // public key sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer+=pubKeySize; // private key int privKeySize; ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &privKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrvKey = (IppsRSAPrivateKeyState*)(pLocKeysBuffer); sts = ippsRSA_InitPrivateKeyType1(modulusBitSize, privExpBitSize, pPrvKey, privKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer+=privKeySize; /* Set public and private keys */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsRSA_SetPrivateKeyType1(bnN, bnD, pPrvKey); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA signature and verification buffers */ int buffSize = 0; sts = ippsRSA_GetBufferSizePublicKey(&buffSize, pPubKey); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } int buffSizePrivKey = 0; sts = ippsRSA_GetBufferSizePrivateKey(&buffSizePrivKey, pPrvKey); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Resize buffer */ total_size = IPP_MAX(buffSize, buffSizePrivKey) + IPPCP_RSA_ALIGNMENT; /* Add an extra memory for the hash method*/ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } *pBufferSize = total_size + hash_method_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsRSASign_PKCS1v15_rmf, (Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys(&keysBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size(&dataBuffSize, pKeysBuffer); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* Buffer for the generated signature */ Ipp8u pOutSig[256] = {0}; Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPrivExp, IPPCP_PRIV_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize key pair */ // private key int privKeyByteSize = 0; sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &privKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrvKey = (IppsRSAPrivateKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPrivateKeyType1(modulusBitSize, privExpBitSize, pPrvKey, privKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer += privKeyByteSize; // public key int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Set public and private keys */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsRSA_SetPrivateKeyType1(bnN, bnD, pPrvKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA Signature Generation */ Ipp8u* pLocSignBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); sts = ippsRSASign_PKCS1v15_rmf(pMsg, msgByteLen, pOutSig, pPrvKey, pPubKey, locMethod, pLocSignBuffer); int sigFlagErr = ippcp_is_mem_eq(pSig, sizeof(pSig), pOutSig, sizeof(pSig)); if(1 != sigFlagErr || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } IPPFUN(fips_test_status, fips_selftest_ippsRSAVerify_PKCS1v15_rmf,(Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys(&keysBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size(&dataBuffSize, pKeysBuffer); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize public key */ int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Set public and private keys */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pLocVerifBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); /* RSA Signature Verification */ int isValid; sts = ippsRSAVerify_PKCS1v15_rmf(pMsg,msgByteLen, pSig, &isValid, pPubKey, locMethod, pLocVerifBuffer); if(!isValid || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/fips_cert/selftest_rsa_sign_verify_pss.c000066400000000000000000001030221470420105600313400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ #ifdef IPPCP_FIPS_MODE #include "ippcp.h" #include "owndefs.h" #include "dispatcher.h" // FIPS selftests are not processed by dispatcher. // Prevent several copies of the same functions. #ifdef _IPP_DATA #include #include #include /* * KAT * vectors are taken from FIPS 186 testing vectors set */ __ALIGN64 static const Ipp8u pPrivExp[] = { 0x9f,0x06,0xd2,0x01,0x39,0xfc,0x4f,0x7a,0x86,0x83,0xc2,0xc9,0x1c,0xe9, 0xd3,0x0e,0x2b,0x87,0x5e,0x07,0x8e,0xa3,0xeb,0x3e,0xe3,0x13,0x5d,0x0b, 0x40,0x9d,0x86,0xf4,0xdf,0xb4,0x72,0xd9,0xda,0x0a,0x24,0xdf,0x6b,0x90, 0x7c,0x6c,0xd6,0xec,0x98,0xc6,0x5c,0x92,0x04,0x0c,0x24,0xe4,0xc3,0xe8, 0xe3,0x20,0x31,0xba,0xc7,0x0f,0x32,0x9a,0x44,0xa2,0x41,0x9a,0xd2,0x1e, 0xaf,0x91,0x2f,0x72,0x71,0x8c,0x0a,0xc9,0x93,0x10,0xcf,0x6a,0x02,0x95, 0xb5,0x21,0x1f,0xa4,0x74,0xfe,0xe5,0x54,0xa0,0xed,0x65,0x93,0xba,0x33, 0x2c,0xb6,0xc4,0x86,0x3e,0xfa,0xd3,0x98,0xc7,0x09,0xfa,0x50,0xa9,0xb3, 0xc2,0x96,0xa7,0xb0,0xf5,0x4b,0x7e,0xbd,0xfe,0xea,0xa4,0x49,0x5f,0x3e, 0xb6,0x54,0x7a,0xa3,0x2b,0x06,0xe9,0x03,0xc0,0xac,0xad,0xb2,0x5d,0xce, 0x6d,0x12,0xd3,0x65,0x81,0x1a,0xd7,0x65,0x94,0x1e,0xbe,0x8a,0x74,0x2d, 0xbb,0x78,0xc9,0x50,0x02,0x9d,0x5c,0x1e,0xfd,0x54,0x00,0x81,0xf7,0xc9, 0x0d,0xc8,0x9d,0x1b,0x44,0x8a,0x53,0x95,0x4a,0x6c,0x06,0xc8,0x87,0x60, 0x3c,0xb9,0xdd,0xe7,0x8c,0xdb,0x0d,0x17,0x67,0x79,0x9b,0xf3,0x43,0xa4, 0xec,0x88,0x9b,0xfd,0xc9,0xc0,0xaf,0xff,0xa9,0x6b,0xe1,0x55,0x5f,0x7c, 0x33,0x04,0x48,0x94,0xf7,0x7a,0xb9,0xd8,0x23,0x4a,0x4c,0x2d,0xa5,0xee, 0x87,0x2a,0x30,0x15,0x47,0xab,0x74,0xe5,0x08,0x8f,0x48,0x28,0xd1,0x75, 0x9b,0x37,0x75,0x88,0x08,0xde,0x7b,0x32,0x86,0x45,0xf9,0x32,0xd3,0xb4, 0x6b,0x78,0xe5,0x49 }; __ALIGN64 static const Ipp8u pPubExp[] = { 0x4f,0xc9,0x86 }; __ALIGN64 static const Ipp8u pModulus[] = { 0xef,0x05,0x18,0x6b,0x85,0xe9,0xc6,0x0f,0xfc,0xa3,0xde,0x11,0xeb,0x94, 0x5c,0xaf,0x0a,0x45,0xad,0x50,0xa8,0xf1,0xd9,0x59,0x33,0x12,0x37,0xfd, 0xe7,0x5f,0xe6,0x3e,0xac,0x43,0x6f,0xce,0xbe,0xb4,0x49,0xd5,0xf9,0xa7, 0xe0,0x7e,0x5f,0xd7,0x66,0x64,0x94,0x5b,0x58,0x27,0xdd,0x0b,0xb4,0x12, 0xc4,0x12,0xc0,0x0d,0xf4,0x05,0xf2,0xbe,0xa1,0x1c,0x12,0xf1,0x52,0xf3, 0x3a,0xb5,0x90,0x87,0x28,0xf5,0xb4,0xb1,0xd1,0x31,0x33,0x94,0x3a,0x5a, 0x63,0x3f,0x03,0x7f,0xca,0xda,0xf9,0xc7,0x01,0x66,0x89,0xea,0xff,0x2e, 0xfd,0xd5,0x20,0xa6,0x89,0x1c,0xf8,0x36,0x8c,0xea,0xac,0x89,0x3a,0x35, 0xbd,0x19,0xab,0xe2,0x37,0x19,0x17,0xd8,0xac,0x9c,0xe8,0x67,0xac,0x6b, 0x6b,0x31,0x3d,0xcb,0xee,0x24,0xb7,0xf5,0x2f,0xe6,0x0a,0xdb,0x55,0x67, 0xa3,0x3e,0x14,0x13,0x84,0xb2,0xff,0xeb,0x3e,0xff,0xd7,0x44,0xd9,0xe2, 0x7b,0x15,0x13,0x11,0xc7,0xbe,0xc5,0x6b,0xb8,0x23,0x64,0x33,0x70,0x96, 0xc9,0x09,0x6f,0xb2,0xb6,0x15,0xee,0x2f,0x2b,0xd4,0x26,0xcb,0xb9,0x2c, 0x9c,0x74,0xe5,0x1d,0x58,0x90,0xd7,0xf9,0xb9,0x37,0x04,0x43,0x26,0xf8, 0xe4,0x45,0xc4,0x7d,0xef,0x0f,0x6c,0x8b,0x17,0xc6,0x3b,0x57,0x81,0xd2, 0x08,0xc3,0x52,0xa7,0xbc,0x59,0xca,0x59,0x93,0x77,0xbe,0x6a,0x12,0x8f, 0x32,0xff,0x48,0x59,0xbb,0x0b,0x93,0x1a,0xfd,0xec,0x5f,0x10,0x13,0x2e, 0x6c,0xd5,0x5d,0xf7,0x4c,0xf1,0xba,0x5d,0x1e,0x5e,0x76,0x9c,0x53,0xd8, 0x58,0x2b,0x06,0xc5 }; __ALIGN64 static const Ipp8u pMsg[] = { 0xdf,0xc2,0x26,0x04,0xb9,0x5d,0x15,0x32,0x80,0x59,0x74,0x5c,0x6c,0x98, 0xeb,0x9d,0xfb,0x34,0x7c,0xf9,0xf1,0x70,0xaf,0xf1,0x9d,0xee,0xec,0x55, 0x5f,0x22,0x28,0x5a,0x67,0x06,0xc4,0xec,0xbf,0x0f,0xb1,0x45,0x8c,0x60, 0xd9,0xbf,0x91,0x3f,0xba,0xe6,0xf4,0xc5,0x54,0xd2,0x45,0xd9,0x46,0xb4, 0xbc,0x5f,0x34,0xae,0xc2,0xac,0x6b,0xe8,0xb3,0x3d,0xc8,0xe0,0xe3,0xa9, 0xd6,0x01,0xdf,0xd5,0x36,0x78,0xf5,0x67,0x44,0x43,0xf6,0x7d,0xf7,0x8a, 0x3a,0x9e,0x09,0x33,0xe5,0xf1,0x58,0xb1,0x69,0xac,0x8d,0x1c,0x4c,0xd0, 0xfb,0x87,0x2c,0x14,0xca,0x8e,0x00,0x1e,0x54,0x2e,0xa0,0xf9,0xcf,0xda, 0x88,0xc4,0x2d,0xca,0xd8,0xa7,0x40,0x97,0xa0,0x0c,0x22,0x05,0x5b,0x0b, 0xd4,0x1f }; __ALIGN64 static const Ipp8u pSig[] = { 0x8b,0x46,0xf2,0xc8,0x89,0xd8,0x19,0xf8,0x60,0xaf,0x0a,0x6c,0x4c,0x88, 0x9e,0x4d,0x14,0x36,0xc6,0xca,0x17,0x44,0x64,0xd2,0x2a,0xe1,0x1b,0x9c, 0xcc,0x26,0x5d,0x74,0x3c,0x67,0xe5,0x69,0xac,0xcb,0xc5,0xa8,0x0d,0x4d, 0xd5,0xf1,0xbf,0x40,0x39,0xe2,0x3d,0xe5,0x2a,0xec,0xe4,0x02,0x91,0xc7, 0x5f,0x89,0x36,0xc5,0x8c,0x9a,0x2f,0x77,0xa7,0x80,0xbb,0xe7,0xad,0x31, 0xeb,0x76,0x74,0x2f,0x7b,0x2b,0x8b,0x14,0xca,0x1a,0x71,0x96,0xaf,0x7e, 0x67,0x3a,0x3c,0xfc,0x23,0x7d,0x50,0xf6,0x15,0xb7,0x5c,0xf4,0xa7,0xea, 0x78,0xa9,0x48,0xbe,0xda,0xf9,0x24,0x24,0x94,0xb4,0x1e,0x1d,0xb5,0x1f, 0x43,0x7f,0x15,0xfd,0x25,0x51,0xbb,0x5d,0x24,0xee,0xfb,0x1c,0x3e,0x60, 0xf0,0x36,0x94,0xd0,0x03,0x3a,0x1e,0x0a,0x9b,0x9f,0x5e,0x4a,0xb9,0x7d, 0x45,0x7d,0xff,0x9b,0x9d,0xa5,0x16,0xdc,0x22,0x6d,0x6d,0x65,0x29,0x50, 0x03,0x08,0xed,0x74,0xa2,0xe6,0xd9,0xf3,0xc1,0x05,0x95,0x78,0x8a,0x52, 0xa1,0xbc,0x06,0x64,0xae,0xdf,0x33,0xef,0xc8,0xba,0xdd,0x03,0x7e,0xb7, 0xb8,0x80,0x77,0x2b,0xdb,0x04,0xa6,0x04,0x6e,0x9e,0xde,0xee,0x41,0x97, 0xc2,0x55,0x07,0xfb,0x0f,0x11,0xab,0x1c,0x9f,0x63,0xf5,0x3c,0x88,0x20, 0xea,0x84,0x05,0xcf,0xd7,0x72,0x16,0x92,0x47,0x5b,0x4d,0x72,0x35,0x5f, 0xa9,0xa3,0x80,0x4f,0x29,0xe6,0xb6,0xa7,0xb0,0x59,0xc4,0x44,0x1d,0x54, 0xb2,0x8e,0x4e,0xed,0x25,0x29,0xc6,0x10,0x3b,0x54,0x32,0xc7,0x13,0x32, 0xce,0x74,0x2b,0xcc}; __ALIGN64 static const Ipp8u pSalt[] = { 0xe1,0x25,0x6f,0xc1,0xee,0xef,0x81,0x77,0x3f,0xdd,0x54,0x65,0x7e,0x40, 0x07,0xfd,0xe6,0xbc,0xb9,0xb1 }; static const unsigned int msgByteLen = sizeof(pMsg); static const unsigned int saltByteLen = sizeof(pSalt); static const unsigned int pubExpBitSize = 24; static const unsigned int privExpBitSize = 2048; static const unsigned int modulusBitSize = 2048; static const unsigned int primeBitsize = 1024; #define IPPCP_PUB_EXP_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(pubExpBitSize)) #define IPPCP_PRIV_EXP_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(privExpBitSize)) #define IPPCP_MODULUS_WORD_SIZE (IPPCP_BITSIZE_2_WORDSIZE(modulusBitSize)) IPPFUN(fips_test_status, fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys, (int *pKeysBufferSize)) { /* return bad status if input pointer is NULL */ IPP_BADARG_RET((NULL == pKeysBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; int tmp_size = 0; /* BIGNUMs sizes */ sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += tmp_size; // D sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += tmp_size; // E sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += tmp_size; // N /* Public and private keys context size */ sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += tmp_size; // pPubKey sts = ippsPrimeGetSize(primeBitsize, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += tmp_size; // pPrimeG sts = ippsPRNGGetSize(&tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += tmp_size; // pRand sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &tmp_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } int tmp_size_2 = 0; sts = ippsRSA_GetSizePrivateKeyType2(primeBitsize, privExpBitSize - primeBitsize, &tmp_size_2); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += IPP_MAX(tmp_size, tmp_size_2); // pPrvKey *pKeysBufferSize = total_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsRSASignVerify_PSS_rmf_get_size, (int *pBufferSize, Ipp8u *pKeysBuffer)) { /* return bad status if input pointers are NULL */ IPP_BADARG_RET((NULL == pKeysBuffer) || (NULL == pBufferSize), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); IppStatus sts = ippStsNoErr; int total_size = 0; Ipp8u *pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPrivExp, IPPCP_PRIV_EXP_WORD_SIZE); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize public and private keys - necessary to obtain signature size */ // public key int pubKeySize; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer+=pubKeySize; // private key int privKeySize; sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &privKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrvKey = (IppsRSAPrivateKeyState*)(pLocKeysBuffer); sts = ippsRSA_InitPrivateKeyType1(modulusBitSize, privExpBitSize, pPrvKey, privKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer+=privKeySize; sts = ippsRSA_GetSizePrivateKeyType2(primeBitsize, privExpBitSize - primeBitsize, &privKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsRSAPrivateKeyState* pPrvKey2 = (IppsRSAPrivateKeyState*)(pLocKeysBuffer); sts = ippsRSA_InitPrivateKeyType2(primeBitsize, privExpBitSize - primeBitsize, pPrvKey2, privKeySize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } int buffSizePrivKey2 = 0; sts = ippsRSA_GetBufferSizePrivateKey(&buffSizePrivKey2, pPrvKey2); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* set public and private keys */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; sts = ippsRSA_SetPrivateKeyType1(bnN, bnD, pPrvKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* RSA signature and verification buffers */ int buffSizeSignVerify = 0; sts = ippsRSA_GetBufferSizePublicKey(&buffSizeSignVerify, pPubKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; // private int buffSizePrivKey1 = 0; sts = ippsRSA_GetBufferSizePrivateKey(&buffSizePrivKey1, pPrvKey); if(sts != ippStsNoErr) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; /* resize buffer */ total_size = IPP_MAX(IPP_MAX(buffSizeSignVerify, buffSizePrivKey1), buffSizePrivKey2) + IPPCP_RSA_ALIGNMENT; /* Add an extra memory for the hash method*/ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } total_size += hash_method_size; *pBufferSize = total_size; return IPPCP_ALGO_SELFTEST_OK; } IPPFUN(fips_test_status, fips_selftest_ippsRSASign_PSS_rmf,(Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys(&keysBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PSS_rmf_get_size(&dataBuffSize, pKeysBuffer); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* buffer for the generated signature */ Ipp8u pOutSig[256] = {0}; Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPrivExp, IPPCP_PRIV_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize key pair */ // private key int privKeyByteSize = 0; sts = ippsRSA_GetSizePrivateKeyType1(modulusBitSize, privExpBitSize, &privKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrvKey = (IppsRSAPrivateKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPrivateKeyType1(modulusBitSize, privExpBitSize, pPrvKey, privKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer += (privKeyByteSize); // public key int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* set public and private keys */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsRSA_SetPrivateKeyType1(bnN, bnD, pPrvKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA Signature Generation */ Ipp8u* pLocSignBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); sts = ippsRSASign_PSS_rmf(pMsg, msgByteLen, pSalt, saltByteLen, pOutSig, pPrvKey, pPubKey, locMethod, pLocSignBuffer); int sigFlagErr = ippcp_is_mem_eq(pSig, sizeof(pSig), pOutSig, sizeof(pSig)); if(1 != sigFlagErr || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } IPPFUN(fips_test_status, fips_selftest_ippsRSAVerify_PSS_rmf,(Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys(&keysBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PSS_rmf_get_size(&dataBuffSize, pKeysBuffer); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Initialize and set public key */ int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } Ipp8u* pLocVerifBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); /* RSA Signature Verification */ int isValid; sts = ippsRSAVerify_PSS_rmf(pMsg,msgByteLen, pSig, &isValid, pPubKey, locMethod, pLocVerifBuffer); if(!isValid || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } IPPFUN(fips_test_status, fips_selftest_ippsRSA_GenerateKeys,(Ipp8u *pBuffer, Ipp8u *pKeysBuffer)) { IppStatus sts = ippStsNoErr; fips_test_status test_result = IPPCP_ALGO_SELFTEST_OK; /* Internal memory allocation feature */ int internalMemMgm = 0; #if IPPCP_SELFTEST_USE_MALLOC if(pBuffer == NULL || pKeysBuffer == NULL) { internalMemMgm = 1; int keysBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys(&keysBuffSize); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pKeysBuffer = malloc((size_t)keysBuffSize); int dataBuffSize = 0; sts = fips_selftest_ippsRSASignVerify_PSS_rmf_get_size(&dataBuffSize, pKeysBuffer); if (sts != ippStsNoErr) { return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pBuffer = malloc((size_t)dataBuffSize); } #else IPP_BADARG_RET((NULL == pBuffer) || (NULL == pKeysBuffer), IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR); #endif /* buffer for the generated signature */ Ipp8u pOutSig[256] = {0}; Ipp8u* pLocKeysBuffer = pKeysBuffer; /* Initialize BigNumber-s */ int dByteSize; sts = ippsBigNumGetSize(IPPCP_PRIV_EXP_WORD_SIZE, &dByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnD = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += dByteSize; int eByteSize; sts = ippsBigNumGetSize(IPPCP_PUB_EXP_WORD_SIZE, &eByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnE = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += eByteSize; int nByteSize; sts = ippsBigNumGetSize(IPPCP_MODULUS_WORD_SIZE, &nByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_BN_ALIGNMENT)); IppsBigNumState* bnN = (IppsBigNumState *)pLocKeysBuffer; pLocKeysBuffer += nByteSize; sts = ippcp_init_set_bn(bnD, IPPCP_PRIV_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPrivExp, IPPCP_PRIV_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnE, IPPCP_PUB_EXP_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pPubExp, IPPCP_PUB_EXP_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } sts = ippcp_init_set_bn(bnN, IPPCP_MODULUS_WORD_SIZE, ippBigNumPOS, (const Ipp32u *)pModulus, IPPCP_MODULUS_WORD_SIZE); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } // prime generator int size; sts = ippsPrimeGetSize(primeBitsize, &size); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsPrimeState* pPrimeG = (IppsPrimeState*)(IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_GFP_ALIGNMENT)); sts = ippsPrimeInit(primeBitsize, pPrimeG); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer += size; int privKey2ByteSize = 0; sts = ippsRSA_GetSizePrivateKeyType2(primeBitsize, privExpBitSize - primeBitsize, &privKey2ByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPrivateKeyState* pPrvKey2 = (IppsRSAPrivateKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPrivateKeyType2(primeBitsize, privExpBitSize - primeBitsize, pPrvKey2, privKey2ByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer += (privKey2ByteSize); // initialize RNG int pRandSize; const int seedBitsize = 160; sts = ippsPRNGGetSize(&pRandSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsPRNGState* pRand = (IppsPRNGState*)pLocKeysBuffer; sts = ippsPRNGInit(seedBitsize, pRand); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer += (pRandSize); // generate keys Ipp8u* pLocGenerateKeysBuffer = (IPP_ALIGNED_PTR(pBuffer, IPPCP_RSA_ALIGNMENT)); sts = ippStsInsufficientEntropy; for(int loop_count = 0; loop_count < 100 && ippStsInsufficientEntropy == sts; ++loop_count) { sts = ippsRSA_GenerateKeys(bnE, bnN, bnE, bnD, pPrvKey2, pLocGenerateKeysBuffer, 0, pPrimeG, ippsPRNGen, pRand); } if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } // public key int pubKeyByteSize = 0; sts = ippsRSA_GetSizePublicKey(modulusBitSize, pubExpBitSize, &pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } pLocKeysBuffer = (IPP_ALIGNED_PTR(pLocKeysBuffer, IPPCP_RSA_ALIGNMENT)); IppsRSAPublicKeyState* pPubKey = (IppsRSAPublicKeyState*)pLocKeysBuffer; sts = ippsRSA_InitPublicKey(modulusBitSize, pubExpBitSize, pPubKey, pubKeyByteSize); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* set public and private keys */ sts = ippsRSA_SetPublicKey(bnN, bnE, pPubKey); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* Get memory offset and set Hash Method */ int hash_method_size = 0; sts = ippsHashMethodGetSize(&hash_method_size); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } IppsHashMethod* locMethod = (IppsHashMethod*)(pBuffer); sts = ippsHashMethodSet_SHA256_TT(locMethod); if (sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA Signature Generation */ Ipp8u* pLocSignBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); sts = ippsRSASign_PSS_rmf(pMsg, msgByteLen, pSalt, saltByteLen, pOutSig, pPrvKey2, pPubKey, locMethod, pLocSignBuffer); if(sts != ippStsNoErr) { MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return IPPCP_ALGO_SELFTEST_BAD_ARGS_ERR; } /* RSA Signature Verification */ int isValid; Ipp8u* pLocVerifBuffer = (IPP_ALIGNED_PTR(pBuffer + hash_method_size, IPPCP_RSA_ALIGNMENT)); sts = ippsRSAVerify_PSS_rmf(pMsg,msgByteLen, pOutSig, &isValid, pPubKey, locMethod, pLocVerifBuffer); if(!isValid || sts != ippStsNoErr) { test_result = IPPCP_ALGO_SELFTEST_KAT_ERR; } MEMORY_FREE_2(pKeysBuffer, pBuffer, memMgmFlag) return test_result; } #endif // _IPP_DATA #endif // IPPCP_FIPS_MODE cryptography-primitives-1.0.0/sources/ippcp/gfpec/000077500000000000000000000000001470420105600223155ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/000077500000000000000000000000001470420105600236025ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_alias_avx512.h000066400000000000000000000046441470420105600271560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_MATH_AVX512_H #define IFMA_MATH_AVX512_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include typedef __m512i m512; typedef __mmask8 mask8; typedef __mmask64 mask64; /* set */ #define setzero_i64 _mm512_setzero_si512 #define set1_i64 _mm512_set1_epi64 #if 0 /* Note: intrinsics below not available in GCC 8.4 */ #define set_i8 _mm512_set_epi8 #define set_i16 _mm512_set_epi16 #endif #define set_i64 _mm512_set_epi64 /* load/store */ #define loadu_i64 _mm512_loadu_si512 #define maskz_loadu_i64 _mm512_maskz_loadu_epi64 #define storeu_i64 _mm512_storeu_si512 #define mask_storeu_i64 _mm512_mask_storeu_epi64 /* logical shift */ #define srli_i64 _mm512_srli_epi64 #define srlv_i64 _mm512_srlv_epi64 #define slli_i64 _mm512_slli_epi64 #define sllv_i64 _mm512_sllv_epi64 /* arithmetic shift */ #define srai_i64 _mm512_srai_epi64 #define maskz_srai_i64 _mm512_maskz_srai_epi64 #define maskz_srli_i64 _mm512_maskz_srli_epi64 /* logical */ #define and_i64 _mm512_and_epi64 #define or_i64 _mm512_or_si512 /* add */ #define add_i64 _mm512_add_epi64 #define mask_add_i64 _mm512_mask_add_epi64 /* sub */ #define sub_i64 _mm512_sub_epi64 #define mask_sub_i64 _mm512_mask_sub_epi64 /* cmp */ #define cmp_i64_mask _mm512_cmp_epi64_mask #define cmp_u64_mask _mm512_cmp_epu64_mask /* perm */ #define maskz_permutexvar_i8 _mm512_maskz_permutexvar_epi8 #define permutexvar_i8 _mm512_permutexvar_epi8 #define permutexvar_i16 _mm512_permutexvar_epi16 /* move */ #define mask_mov_i64 _mm512_mask_mov_epi64 /* ifma */ #define madd52lo_i64 _mm512_madd52lo_epu64 #define madd52hi_i64 _mm512_madd52hi_epu64 #define alignr_i64 _mm512_alignr_epi64 #endif // if (_IPP32E >= _IPP32E_K1) #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_alias_avx512vl.h000066400000000000000000000053431470420105600275150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ALIAS_AVX512VL_H #define IFMA_ALIAS_AVX512VL_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include typedef __m256i m256i; typedef __mmask8 mask8; typedef __mmask32 mask32; typedef __mmask64 mask64; /* load/store */ #define m256_loadu_i64(A) _mm256_maskz_loadu_epi64(0xFF, (A)) #define m256_maskz_loadu_i64 _mm256_maskz_loadu_epi64 #define m256_storeu_i64(R, A) _mm256_mask_storeu_epi64((R), 0xFF, (A)) #define m256_mask_storeu_i64 _mm256_mask_storeu_epi64 /* cmp */ #define m256_cmp_i64_mask _mm256_cmp_epi64_mask /* mov */ #define m256_mask_mov_i64 _mm256_mask_mov_epi64 /* set */ #define m256_setzero_i64 _mm256_setzero_si256 #define m256_set_i8 _mm256_set_epi8 #define m256_set_i16 _mm256_set_epi16 #define m256_set_i64 _mm256_set_epi64x #define m256_set1_i64 _mm256_set1_epi64x /* shift permutexvar */ #define m256_permutexvar_i8 _mm256_permutexvar_epi8 #define m256_permutexvar_i16 _mm256_permutexvar_epi16 #define m256_maskz_permutexvar_i8 _mm256_maskz_permutexvar_epi8 /* shift logic/arithmetic */ #define m256_srli_i64 _mm256_srli_epi64 #define m256_slli_i64 _mm256_slli_epi64 #define m256_srlv_i64 _mm256_srlv_epi64 #define m256_sllv_i64 _mm256_sllv_epi64 #define m256_srai_i64 _mm256_srai_epi64 #define m256_maskz_srli_i64 _mm256_maskz_srli_epi64 #define m256_maskz_srai_i64 _mm256_maskz_srai_epi64 #define m256_maskz_slli_i64 _mm256_maskz_slli_epi64 #define m256_alignr_i64 _mm256_alignr_epi64 /* and/or */ #define m256_and_i64 _mm256_and_si256 #define m256_or_i64 _mm256_or_si256 /* add/sub */ #define m256_add_i64 _mm256_add_epi64 #define m256_mask_add_i64 _mm256_mask_add_epi64 #define m256_maskz_add_i64 _mm256_maskz_add_epi64 #define m256_sub_i64 _mm256_sub_epi64 #define m256_mask_sub_i64 _mm256_mask_sub_epi64 /* ifma */ #define m256_madd52lo_i64 _mm256_madd52lo_epu64 #define m256_madd52hi_i64 _mm256_madd52hi_epu64 #define m256_maskz_madd52lo_i64 _mm256_maskz_madd52lo_epu64 #define m256_maskz_madd52hi_i64 _mm256_maskz_madd52hi_epu64 #endif // (_IPP32E >= _IPP32E_K1) #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method.h000066400000000000000000000065241470420105600274250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 IFMA_ARITH_METHOD_H #define IFMA_ARITH_METHOD_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "owncp.h" #include "ifma_alias_avx512.h" /* Modular arith methods based on 2^52 radix number representation */ IPP_OWN_FUNPTR(m512, ifma_import, (const Ipp64u *arad64)) IPP_OWN_FUNPTR(void, ifma_export, (Ipp64u *rrad64, const m512 arad52)) IPP_OWN_FUNPTR(m512, ifma_encode, (const m512 a)) IPP_OWN_FUNPTR(m512, ifma_decode, (const m512 a)) IPP_OWN_FUNPTR(m512, ifma_mul, (const m512 a, const m512 b)) IPP_OWN_FUNPTR(void, ifma_mul_dual, (m512 *r1, const m512 a1, const m512 b1, m512 *r2, const m512 a2, const m512 b2)) IPP_OWN_FUNPTR(m512, ifma_sqr, (const m512 a)) IPP_OWN_FUNPTR(void, ifma_sqr_dual, (m512 * r1, const m512 a1, m512 *r2, const m512 a2)) IPP_OWN_FUNPTR(m512, ifma_norm, (const m512 a)) IPP_OWN_FUNPTR(void, ifma_norm_dual, (m512 *r1, const m512 a1, m512 *r2, const m512 a2)) IPP_OWN_FUNPTR(m512, ifma_lnorm, (const m512 a)) IPP_OWN_FUNPTR(void, ifma_lnorm_dual, (m512 *r1, const m512 a1, m512 *r2, const m512 a2)) IPP_OWN_FUNPTR(m512, ifma_add, (const m512 a, const m512 b)) IPP_OWN_FUNPTR(m512, ifma_sub, (const m512 a, const m512 b)) IPP_OWN_FUNPTR(m512, ifma_neg, (const m512 a)) IPP_OWN_FUNPTR(m512, ifma_div2, (const m512 a)) IPP_OWN_FUNPTR(m512, ifma_inv, (const m512 z)) IPP_OWN_FUNPTR(m512, ifma_red, (const m512 a)) typedef struct _ifmaArithMethod { ifma_import import_to52; ifma_export export_to64; ifma_encode encode; ifma_decode decode; ifma_mul mul; ifma_mul_dual mul_dual; ifma_sqr sqr; ifma_sqr_dual sqr_dual; ifma_norm norm; ifma_norm_dual norm_dual; ifma_lnorm lnorm; ifma_lnorm_dual lnorm_dual; ifma_add add; ifma_sub sub; ifma_neg neg; ifma_div2 div2; ifma_inv inv; ifma_red red; } ifmaArithMethod; /* Pre-defined AVX512IFMA ISA based methods */ #define gsArithGF_p256r1_avx512 OWNAPI(gsArithGF_p256r1_avx512) IPP_OWN_DECL(ifmaArithMethod *, gsArithGF_p256r1_avx512, (void)) #define gsArithGF_n256r1_avx512 OWNAPI(gsArithGF_n256r1_avx512) IPP_OWN_DECL(ifmaArithMethod *, gsArithGF_n256r1_avx512, (void)) #define gsArithGF_p384r1_avx512 OWNAPI(gsArithGF_p384r1_avx512) IPP_OWN_DECL(ifmaArithMethod *, gsArithGF_p384r1_avx512, (void)) #define gsArithGF_n384r1_avx512 OWNAPI(gsArithGF_n384r1_avx512) IPP_OWN_DECL(ifmaArithMethod *, gsArithGF_n384r1_avx512, (void)) static __NOINLINE void clear_secrets(m512 *a, m512 *b, m512 *c) { if (NULL != a) *a = setzero_i64(); if (NULL != b) *b = setzero_i64(); if (NULL != c) *c = setzero_i64(); } #endif /* #if (_IPP32E >= _IPP32E_K1) */ #endif /* #ifndef IFMA_ARITH_METHOD_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_n256.c000066400000000000000000000033101470420105600301600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_arith_p256.h" #include "gfpec/ecnist/ifma_arith_n256.h" IPP_OWN_DEFN(ifmaArithMethod *, gsArithGF_n256r1_avx512, (void)) { static ifmaArithMethod m = { /* import_to52 = */ convert_radix_to_52x5, /* export_to64 = */ convert_radix_to_64x4, /* encode = */ ifma_tomont52_n256, /* decode = */ ifma_frommont52_n256, /* mul = */ ifma_amm52_n256, /* mul_dual = */ 0, /* sqr = */ 0, /* sqr_dual = */ 0, /* norm = */ 0, /* norm_dual = */ 0, /* lnorm = */ 0, /* lnorm_dual = */ 0, /* add = */ ifma_add52_n256, /* sub = */ 0, /* neg = */ 0, /* div2 = */ 0, /* inv = */ ifma_aminv52_n256, /* red = */ ifma_fastred52_n256 }; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_n384.c000066400000000000000000000033101470420105600301620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_arith_p384.h" #include "gfpec/ecnist/ifma_arith_n384.h" IPP_OWN_DEFN(ifmaArithMethod *, gsArithGF_n384r1_avx512, (void)) { static ifmaArithMethod m = { /* import_to52 = */ convert_radix_to_52x8, /* export_to64 = */ convert_radix_to_64x6, /* encode = */ ifma_tomont52_n384, /* decode = */ ifma_frommont52_n384, /* mul = */ ifma_amm52_n384, /* mul_dual = */ 0, /* sqr = */ 0, /* sqr_dual = */ 0, /* norm = */ 0, /* norm_dual = */ 0, /* lnorm = */ 0, /* lnorm_dual = */ 0, /* add = */ ifma_add52_n384, /* sub = */ 0, /* neg = */ 0, /* div2 = */ 0, /* inv = */ ifma_aminv52_n384, /* red = */ ifma_fastred52_n384 }; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_n521.c000066400000000000000000000025761470420105600301700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_arith_p521.h" #include "gfpec/ecnist/ifma_arith_n521.h" IPP_OWN_DEFN(ifmaArithMethod_p521 *, gsArithGF_n521r1_avx512, (void)) { static ifmaArithMethod_p521 m = { convert_radix_to_52_p521, convert_radix_to_64_p521, ifma_tomont52_n521, ifma_frommont52_n521, ifma_amm52_n521, 0, 0, 0, 0, 0, 0, 0, ifma_add52_n521, 0, 0, ifma_aminv52_n521, ifma_fastred52_n521 }; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_p256.c000066400000000000000000000034031470420105600301650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_arith_p256.h" IPP_OWN_DEFN(ifmaArithMethod *, gsArithGF_p256r1_avx512, (void)) { static ifmaArithMethod m = { /* import_to52 = */ convert_radix_to_52x5, /* export_to64 = */ convert_radix_to_64x4, /* encode = */ ifma_tomont52_p256, /* decode = */ ifma_frommont52_p256, /* mul = */ ifma_amm52_p256, /* mul_dual = */ ifma_amm52_dual_p256, /* sqr = */ ifma_ams52_p256, /* sqr_dual = */ ifma_ams52_dual_p256, /* norm = */ ifma_norm52, /* norm_dual = */ ifma_norm52_dual, /* lnorm = */ ifma_lnorm52, /* lnorm_dual = */ ifma_lnorm52_dual, /* add = */ 0, /* sub = */ 0, /* neg = */ ifma_neg52_p256, /* div2 = */ ifma_half52_p256, /* inv = */ ifma_aminv52_p256, /* red = */ 0 }; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_p384.c000066400000000000000000000034031470420105600301670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_arith_p384.h" IPP_OWN_DEFN(ifmaArithMethod *, gsArithGF_p384r1_avx512, (void)) { static ifmaArithMethod m = { /* import_to52 = */ convert_radix_to_52x8, /* export_to64 = */ convert_radix_to_64x6, /* encode = */ ifma_tomont52_p384, /* decode = */ ifma_frommont52_p384, /* mul = */ ifma_amm52_p384, /* mul_dual = */ ifma_amm52_dual_p384, /* sqr = */ ifma_ams52_p384, /* sqr_dual = */ ifma_ams52_dual_p384, /* norm = */ ifma_norm52, /* norm_dual = */ ifma_norm52_dual, /* lnorm = */ ifma_lnorm52, /* lnorm_dual = */ ifma_lnorm52_dual, /* add = */ 0, /* sub = */ 0, /* neg = */ ifma_neg52_p384, /* div2 = */ ifma_half52_p384, /* inv = */ ifma_aminv52_p384, /* red = */ 0 }; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_p521.c000066400000000000000000000027151470420105600301650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_arith_p521.h" IPP_OWN_DEFN(ifmaArithMethod_p521 *, gsArithGF_p521r1_avx512, (void)) { static ifmaArithMethod_p521 m = { convert_radix_to_52_p521, convert_radix_to_64_p521, ifma_tomont52_p521, ifma_frommont52_p521, ifma_amm52_p521, ifma_amm52_dual_p521, ifma_ams52_p521, ifma_ams52_dual_p521, ifma_norm52_p521, ifma_norm52_dual_p521, ifma_lnorm52_p521, ifma_lnorm52_dual_p521, 0, ifma_neg52_p521, ifma_half52_p521, ifma_aminv52_p521, 0 }; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_method_p521.h000066400000000000000000000064421470420105600301730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 IFMA_ARITH_METHOD_P521_H #define IFMA_ARITH_METHOD_P521_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_defs_p521.h" /* Modular arith methods based on 2^52 radix number representation */ IPP_OWN_FUNPTR(void, ifma_import, (fe521 pr[], const Ipp64u arad64[P521R1_LEN64])) IPP_OWN_FUNPTR(void, ifma_export, (Ipp64u rrad64[P521R1_LEN64], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_encode, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_decode, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_mul, (fe521 pr[], const fe521 a, const fe521 b)) IPP_OWN_FUNPTR(void, ifma_mul_dual, (fe521 pr1[], const fe521 a1, const fe521 b1, fe521 pr2[], const fe521 a2, const fe521 b2)) IPP_OWN_FUNPTR(void, ifma_sqr, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_sqr_dual, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) IPP_OWN_FUNPTR(void, ifma_norm, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_norm_dual, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) IPP_OWN_FUNPTR(void, ifma_lnorm, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_lnorm_dual, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) IPP_OWN_FUNPTR(void, ifma_add, (fe521 pr[], const fe521 a, const fe521 b)) IPP_OWN_FUNPTR(void, ifma_div2, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_neg, (fe521 pr[], const fe521 a)) IPP_OWN_FUNPTR(void, ifma_inv, (fe521 pr[], const fe521 z)) IPP_OWN_FUNPTR(void, ifma_red, (fe521 pr[], const fe521 a)) typedef struct _ifmaArithMethod_p521 { ifma_import import_to52; ifma_export export_to64; ifma_encode encode; ifma_decode decode; ifma_mul mul; ifma_mul_dual mul_dual; ifma_sqr sqr; ifma_sqr_dual sqr_dual; ifma_norm norm; ifma_norm_dual norm_dual; ifma_lnorm lnorm; ifma_lnorm_dual lnorm_dual; ifma_add add; ifma_neg neg; ifma_div2 div2; ifma_inv inv; ifma_red red; } ifmaArithMethod_p521; /* Pre-defined AVX512IFMA ISA based methods */ #define gsArithGF_p521r1_avx512 OWNAPI(gsArithGF_p521r1_avx512) IPP_OWN_DECL(ifmaArithMethod_p521 *, gsArithGF_p521r1_avx512, (void)) #define gsArithGF_n521r1_avx512 OWNAPI(gsArithGF_n521r1_avx512) IPP_OWN_DECL(ifmaArithMethod_p521 *, gsArithGF_n521r1_avx512, (void)) static __NOINLINE void clear_secrets(fe521 *a, fe521 *b, fe521 *c) { if (NULL != a) FE521_SET(*a) = m256_setzero_i64(); if (NULL != b) FE521_SET(*b) = m256_setzero_i64(); if (NULL != c) FE521_SET(*c) = m256_setzero_i64(); } #endif /* #if (_IPP32E >= _IPP32E_K1) */ #endif /* #ifndef IFMA_ARITH_METHOD_P521_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_n256.c000066400000000000000000000177621470420105600266400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_n256.h" #include "gfpec/ecnist/ifma_arith_p256.h" #include "gfpec/ecnist/ifma_defs.h" /* Constants */ #define LEN52 (5 + 3) /* 5 digits + 3 zero padding */ /* * EC NIST-P256 base point order * in 2^52 radix */ static const __ALIGN64 Ipp64u n256_x1[LEN52] = { 0x0009cac2fc632551, 0x000ada7179e84f3b, 0x000fffffffbce6fa, 0x0000000fffffffff, 0x0000ffffffff0000, 0x0, 0x0, 0x0 }; static const __ALIGN64 Ipp64u n256_x2[LEN52] = { 0x00039585f8c64aa2, 0x0005b4e2f3d09e77, 0x000fffffff79cdf5, 0x0000001fffffffff, 0x0001fffffffe0000, 0x0, 0x0, 0x0 }; /* k0 = (-1/n256) mod 2^52 */ static const __ALIGN64 Ipp64u n256_k0 = 0x1c8aaee00bc4f; /* * r = 2^((52*5)) mod n256 */ static const __ALIGN64 Ipp64u n256_r[LEN52] = { 0x000353d039cdaaf0, 0x000258e8617b0c46, 0x0000000004319055, 0x000fff0000000000, 0x00000000000fffff, 0x0, 0x0, 0x0 }; /* To Montgomery conversion constant * r = 2^((52*5)*2) mod n256 */ static const __ALIGN64 Ipp64u n256_rr[LEN52] = { 0x0005cc0dea6dc3ba, 0x000192a067d8a084, 0x000bec59615571bb, 0x0001fc245b2392b6, 0x0000e12d9559d956, 0x0, 0x0, 0x0 }; static const __ALIGN64 Ipp64u ones[LEN52] = { 1, 0, 0, 0, 0, 0, 0, 0 }; #define MUL_RED_ROUND(R, A, B, IDX) \ { \ const m512 Bi = permutexvar_i8(idx_b##IDX, (B)); \ m512 Rlo = madd52lo_i64(zero, (A), Bi); \ m512 tmp = madd52hi_i64(zero, (A), Bi); \ \ (R) = add_i64((R), Rlo); \ /* broadcast R[0] */ \ const m512 R0 = permutexvar_i8(idx_b0, (R)); \ const m512 Yi = madd52lo_i64(zero, k0, R0); \ (R) = madd52lo_i64((R), N, Yi); \ tmp = madd52hi_i64(tmp, N, Yi); \ /* shift */ \ const m512 carry = maskz_srli_i64(maskone, (R), DIGIT_SIZE); \ tmp = add_i64(tmp, carry); \ (R) = maskz_permutexvar_i8(mask_sr64, idx_sr64, (R)); \ /* hi */ \ (R) = add_i64((R), tmp); \ } /* R = (A*B) */ IPP_OWN_DEFN(m512, ifma_amm52_n256, (const m512 a, const m512 b)) { const m512 N = loadu_i64(n256_x1); /* modulus */ const m512 k0 = set1_i64(n256_k0); /* k0 */ const m512 zero = setzero_i64(); const mask8 maskone = 0x1; /* Index broadcast */ const m512 idx_b0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const m512 idx_b1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const m512 idx_b2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const m512 idx_b3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const m512 idx_b4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 /* Mask to shift zmm register right on 64-bit */ const mask64 mask_sr64 = 0x00ffffffffffffff; const m512 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 r = setzero_i64(); MUL_RED_ROUND(r, a, b, 0) MUL_RED_ROUND(r, a, b, 1) MUL_RED_ROUND(r, a, b, 2) MUL_RED_ROUND(r, a, b, 3) MUL_RED_ROUND(r, a, b, 4) r = ifma_lnorm52(r); return r; } IPP_OWN_DEFN(m512, ifma_add52_n256, (const m512 a, const m512 b)) { const m512 zero = setzero_i64(); const m512 Nx2 = loadu_i64(n256_x2); /* r = a + b */ m512 r = add_i64(a, b); r = ifma_lnorm52(r); /* t = r - N */ m512 t = sub_i64(r, Nx2); t = ifma_norm52(t); /* lt = t < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(t, DIGIT_SIZE - 1), _MM_CMPINT_LT); const mask8 mask = check_bit(lt, 4); // check sign in 5h digit /* mask != 0 ? r : t */ r = mask_mov_i64(t, mask, r); return r; } static m512 ifma_ams52_n256(const m512 a) { return ifma_amm52_n256(a, a); } IPP_OWN_DEFN(m512, ifma_fastred52_n256, (const m512 a)) { const m512 N = loadu_i64(n256_x1); const m512 zero = setzero_i64(); /* r = a - N */ m512 r = sub_i64(a, N); r = ifma_norm52(r); /* 1 < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE - 1), _MM_CMPINT_LT); const mask8 mask = check_bit(lt, 4); // check sign in 5th digit /* mask != 0 ? a : r */ r = mask_mov_i64(r, mask, a); return r; } IPP_OWN_DEFN(m512, ifma_tomont52_n256, (const m512 a)) { return ifma_amm52_n256(a, loadu_i64(n256_rr)); } IPP_OWN_DEFN(m512, ifma_frommont52_n256, (const m512 a)) { m512 r = ifma_amm52_n256(a, loadu_i64(ones)); return ifma_fastred52_n256(r); } #define sqr(R, A) (R) = ifma_ams52_n256((A)) #define mul(R, A, B) (R) = ifma_amm52_n256((A), (B)) /* * computes r = 1/z = z^(n256-2) mod n256 * * note: z in in Montgomery domain * r in Montgomery domain */ __IPPCP_INLINE m512 ifma_ams52_n256_ntimes(const m512 a, int n) { m512 r = a; for (; n > 0; --n) { sqr(r, r); } return r; } #define sqr_ntimes(R, A, N) (R) = ifma_ams52_n256_ntimes((A), (N)) /* * computes r = 1/z = z^(n256-2) mod n256 * * note: z is in Montgomery domain * (as soon mul() and sqr() below are amm-functions, * the result is in Montgomery domain too) */ IPP_OWN_DEFN(m512, ifma_aminv52_n256, (const m512 z)) { const m512 r_n256 = loadu_i64(n256_r); int i; // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 m512 pwr_z_tbl[16]; m512 r; pwr_z_tbl[0] = r_n256; pwr_z_tbl[1] = z; for (i = 2; i < 16; i += 2) { sqr(pwr_z_tbl[i], pwr_z_tbl[i / 2]); mul(pwr_z_tbl[i + 1], pwr_z_tbl[i], z); } // pwr = (n256-2) in big endian Ipp8u pwr[] = "\xFF\xFF\xFF\xFF\x00\x00\x00\x00" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84" "\xF3\xB9\xCA\xC2\xFC\x63\x25\x4F"; // init r = 1 r = r_n256; for (i = 0; i < 32; i++) { int v = pwr[i]; int hi = (v >> 4) & 0xF; int lo = v & 0xF; sqr(r, r); sqr(r, r); sqr(r, r); sqr(r, r); if (hi) mul(r, r, pwr_z_tbl[hi]); sqr(r, r); sqr(r, r); sqr(r, r); sqr(r, r); if (lo) mul(r, r, pwr_z_tbl[lo]); } return r; } #undef sqr #undef mul #undef sqr_ntimes #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_n256.h000066400000000000000000000042721470420105600266350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ARITH_N256R1_H_) #define _IFMA_ARITH_N256R1_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "ifma_alias_avx512.h" /** * \brief * * Montgomery multiplication * * a * b * R mod n, where R = 2^(6*52) mod n * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_amm52_n256, (const m512 a, const m512 b)) /** * \brief * * A + B (mod n) * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_add52_n256, (const m512 a, const m512 b)) /** * \brief * * Reduction modulo n (subgroup order). * * (a >= n256) ? a - n256 : a * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_fastred52_n256, (const m512 a)) /** * \brief * * Conversion to Montgomery domain modulo n (subgroup order). * * a * R mod n, where R = 2^(6*52) mod n * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_tomont52_n256, (const m512 a)) /** * \brief * * Conversion from Montgomery domain modulo n (subgroup order). * * a mod n * * \param[in] p value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_frommont52_n256, (const m512 a)) /** * \brief * * Modular inverse modulo n (subgroup order). * * 1/z mod n * * \param[in] z value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_aminv52_n256, (const m512 z)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ARITH_N256R1_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_n384.c000066400000000000000000000247541470420105600266410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_n384.h" #include "gfpec/ecnist/ifma_arith_p384.h" #include "gfpec/ecnist/ifma_defs.h" /* Constants */ #define LEN52 (NUMBER_OF_DIGITS(384, 52)) /* * EC NIST-P384 base point order * in 2^52 radix */ static const __ALIGN64 Ipp64u n384_x1[LEN52] = { 0x000c196accc52973, 0x000b248b0a77aece, 0x0004372ddf581a0d, 0x000ffffc7634d81f, 0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff, 0x00000000000fffff }; /* k0 = (-1/n384) mod 2^52 */ static const __ALIGN64 Ipp64u n384_k0 = 0x00046089e88fdc45; /* r = 2^((52*8)) mod n384 */ static const __ALIGN64 Ipp64u n384_r[LEN52] = { 0x000ad68d00000000, 0x000851313e695333, 0x0007e5f24db74f58, 0x000b27e0bc8d220a, 0x000000000000389c, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; /* To Montgomery conversion constant * rr = 2^((52*8)*2) mod n384 */ static const __ALIGN64 Ipp64u n384_rr[LEN52] = { 0x00034124f50ddb2d, 0x000c974971bd0d8d, 0x0002118942bfd3cc, 0x0009f43be8072178, 0x0005bf030606de60, 0x0000d49174aab1cc, 0x000b7a28266895d4, 0x000000000003fb05 }; static const __ALIGN64 Ipp64u ones[LEN52] = { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; #define MULT_ROUND(R, A, B, IDX) \ const m512 Bi##R##IDX = permutexvar_i8(idx_b##IDX, (B)); \ const m512 amBiLo##R##IDX = madd52lo_i64(zero, (A), Bi##R##IDX); \ m512 tr##R##IDX = madd52hi_i64(zero, (A), Bi##R##IDX); \ { \ /* low */ \ (R) = add_i64((R), amBiLo##R##IDX); \ const m512 R0 = permutexvar_i8(idx_b0, (R)); \ const m512 u = madd52lo_i64(zero, K0, R0); \ tr##R##IDX = madd52hi_i64(tr##R##IDX, N, u); \ (R) = madd52lo_i64((R), N, u); \ /* shift */ \ const m512 carryone = maskz_srai_i64(maskone, (R), DIGIT_SIZE); \ tr##R##IDX = add_i64(tr##R##IDX, carryone); \ (R) = maskz_permutexvar_i8(mask_sr64, idx_sr64, (R)); \ /* hi */ \ (R) = add_i64((R), tr##R##IDX); \ } /* R = (A*B) - no normalization (in radix 2^52) */ IPP_OWN_DEFN(m512, ifma_amm52_n384, (const m512 a, const m512 b)) { const m512 N = loadu_i64(n384_x1); /* n */ const m512 K0 = set1_i64(n384_k0); /* k0 */ const m512 zero = setzero_i64(); const mask8 maskone = 0x1; /* Index broadcast */ const m512 idx_b0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const m512 idx_b1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const m512 idx_b2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const m512 idx_b3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const m512 idx_b4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const m512 idx_b5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 const m512 idx_b6 = set_i64(REPL8(0x3736353433323130)); // 55, 54, 53, 52, 51, 50, 49, 48 const m512 idx_b7 = set_i64(REPL8(0x3f3e3d3c3b3a3938)); // 63, 62, 61, 60, 59, 58, 57, 56 /* Mask to shift zmm register right on 64-bit */ const mask64 mask_sr64 = 0x00ffffffffffffff; const m512 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 r = setzero_i64(); /* N384 * m' mod b = 46089e88fdc45 * * Algorithm * a[] b[] - input data ((in radix 2^52)) m[] - module n384 * * where u = R[0]*m' mod b * 1) R = R + a[] * b[i] (lo) * 2) R = R + m[] * u (lo) * 3) R = R >> 64 * 4) R = R + a[] * b[i] (hi) * 5) R = R + m[] * u (hi) */ /* one round = O(32) */ MULT_ROUND(r, a, b, 0) MULT_ROUND(r, a, b, 1) MULT_ROUND(r, a, b, 2) MULT_ROUND(r, a, b, 3) MULT_ROUND(r, a, b, 4) MULT_ROUND(r, a, b, 5) MULT_ROUND(r, a, b, 6) MULT_ROUND(r, a, b, 7) r = ifma_lnorm52(r); return r; } IPP_OWN_DEFN(m512, ifma_add52_n384, (const m512 a, const m512 b)) { const m512 zero = setzero_i64(); const m512 N = loadu_i64(n384_x1); /* r = a + b */ m512 r = add_i64(a, b); r = ifma_lnorm52(r); /* t = r - N */ m512 t = sub_i64(r, N); t = ifma_norm52(t); /* lt = t < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(t, DIGIT_SIZE - 1), _MM_CMPINT_LT); const mask8 mask = check_bit(lt, 7); /* mask != 0 ? r : t */ r = mask_mov_i64(t, mask, r); return r; } static m512 ifma_ams52_n384(const m512 a) { return ifma_amm52_n384(a, a); } IPP_OWN_DEFN(m512, ifma_tomont52_n384, (const m512 a)) { const m512 RR = loadu_i64(n384_rr); return ifma_amm52_n384(a, RR); } IPP_OWN_DEFN(m512, ifma_fastred52_n384, (const m512 a)) { const m512 N = loadu_i64(n384_x1); const m512 zero = setzero_i64(); /* r = a - N */ m512 r = sub_i64(a, N); r = ifma_norm52(r); /* 1 < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE - 1), _MM_CMPINT_LT); const mask8 mask = check_bit(lt, 7); /* mask != 0 ? a : r */ r = mask_mov_i64(r, mask, a); return r; } IPP_OWN_DEFN(m512, ifma_frommont52_n384, (const m512 a)) { const m512 ONE = loadu_i64(ones); m512 r = ifma_amm52_n384(a, ONE); return ifma_fastred52_n384(r); } #define sqr(R, A) (R) = ifma_ams52_n384((A)) #define mul(R, A, B) (R) = ifma_amm52_n384((A), (B)) /* * computes r = 1/z = z^(n384-2) mod n384 * * note: z in in Montgomery domain * r in Montgomery domain */ __IPPCP_INLINE m512 ifma_ams52_n384_ntimes(const m512 a, int n) { m512 r = a; for (; n > 0; --n) { sqr(r, r); } return r; } #define sqr_ntimes(R, A, N) (R) = ifma_ams52_n384_ntimes((A), (N)) IPP_OWN_DEFN(m512, ifma_aminv52_n384, (const m512 z)) { const m512 r_norder = loadu_i64(n384_r); /* table pwr_z_Tbl[i] = z^i, i = 0,..,15 */ __ALIGN64 m512 pwr_z_tbl[16]; m512 lexp; lexp = setzero_i64(); /* fill table */ pwr_z_tbl[0] = r_norder; pwr_z_tbl[1] = z; for (int i = 2; i < 16; i += 2) { sqr(pwr_z_tbl[i], pwr_z_tbl[i / 2]); mul(pwr_z_tbl[i + 1], pwr_z_tbl[i], z); } // pwr = (n384-2) in big endian const Ipp8u pwr[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xC7\x63\x4D\x81\xF4\x37\x2D\xDF" "\x58\x1A\x0D\xB2\x48\xB0\xA7\x7A" "\xEC\xEC\x19\x6A\xCC\xC5\x29\x71"; /* * process low part of the exponent: "0xc7634d81f4372ddf 0x581a0db248b0a77a 0xecec196accc52973" */ /* init result */ lexp = r_norder; for (Ipp32u i = 24u; i < (sizeof(pwr) - 1u); ++i) { const int v = (int)(pwr[i]); const int hi = (v >> 4) & 0xF; const int lo = v & 0xF; sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); if (0 != hi) mul(lexp, lexp, pwr_z_tbl[hi]); sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); if (0 != lo) mul(lexp, lexp, pwr_z_tbl[lo]); } m512 u, v; u = v = setzero_i64(); sqr(v, z); /* v = z^2 */ mul(u, v, z); /* u = z^2 * z = z^3 */ /**/ sqr_ntimes(v, u, 2); /* v = (z^3)^(2^2) = z^12 */ mul(u, v, u); /* u = z^12 * z^3 = z^15 = z^(0xF) */ /**/ sqr_ntimes(v, u, 4); /* v = (z^0xF)^(2^4) = z^(0xF0) */ mul(u, v, u); /* u = z^0xF0 * z^(0xF) = z^(0xFF) */ /**/ sqr_ntimes(v, u, 8); /* v = (z^0xFF)^(2^8) = z^(0xFF00) */ mul(u, v, u); /* u = z^0xFF00 * z^(0xFF) = z^(0xFFFF) */ /**/ sqr_ntimes(v, u, 16); /* v = (z^0xFFFF)^(2^16) = z^(0xFFFF0000) */ mul(u, v, u); /* u = z^0xFFFF0000 * z^(0xFFFF) = z^(0xFFFFFFFF) */ /**/ sqr_ntimes(v, u, 32); /* v = (z^0xFFFFFFFF)^(2^32) = z^(0xFFFFFFFF00000000) */ mul(u, v, u); /* u = z^0xFFFFFFFF00000000 * z^(0xFFFFFFFF) = z^(0xFFFFFFFFFFFFFFFF) */ /**/ sqr_ntimes(v, u, 64); /**/ mul(v, v, u); /* v = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /**/ sqr_ntimes(v, v, 64); /**/ mul(v, v, u); /* v = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /* combine low and high results */ sqr_ntimes(v, v, 64 * 3); /* u = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000.0000000000000000.0000000000000000) */ m512 r = setzero_i64(); /**/ mul(r, v, lexp); /* r = z^(0xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.c7634d81f4372ddf.581a0db248b0a77a.ecec196accc52973) */ return r; } #undef sqr #undef mul #undef sqr_ntimes #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_n384.h000066400000000000000000000043021470420105600266310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ARITH_N384R1_H_) #define _IFMA_ARITH_N384R1_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "ifma_alias_avx512.h" /** * \brief * * Montgomery multiplication * * a * b * R mod n, where R = 2^(5*52) mod n * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_amm52_n384, (const m512 a, const m512 b)) /** * \brief * * A + B (in 2^52 radix) * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_add52_n384, (const m512 a, const m512 b)) /** * \brief * * Reduction modulo n (subgroup order). * * (a >= n384) ? a - n384 : a * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_fastred52_n384, (const m512 a)) /** * \brief * * Conversion to Montgomery domain modulo n (subgroup order). * * a * R mod n, where R = 2^(5*52) mod n * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_tomont52_n384, (const m512 a)) /** * \brief * * Conversion from Montgomery domain modulo n (subgroup order). * * a mod n * * \param[in] p value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_frommont52_n384, (const m512 a)) /** * \brief * * Modular inverse modulo n (subgroup order). * * 1/z mod n * * \param[in] z value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_aminv52_n384, (const m512 z)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ARITH_N384R1_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_n521.c000066400000000000000000000315001470420105600266150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p521.h" /* // EC NIST-P521 prime base point order // in 2^52 radix */ static const __ALIGN64 Ipp64u n521_x1[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x000fb71e91386409, 0x000b8899c47aebb6, 0x000709a5d03bb5c9, 0x000966b7fcc0148f }, { 0x000a51868783bf2f, 0x000fffffffffffff, 0x000fffffffffffff, 0x000fffffffffffff }, { 0x000fffffffffffff, 0x000fffffffffffff, 0x0000000000000001, 0x0000000000000000 } }; static const __ALIGN64 Ipp64u n521_k0 = 0x000f5ccd79a995c7; /* to Montgomery conversion constant // rr = 2^((P521_LEN52*DIGIT_SIZE)*2) mod n521 */ static const __ALIGN64 Ipp64u n521_rr[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x0003b4d7a5b140ce, 0x000cb0bf26c55bf9, 0x00037e5396c67ee9, 0x0002bd1c80cf7b13 }, { 0x00073cbe28f15e41, 0x000dd6e23d82e49c, 0x0003d142b7756e3e, 0x00061a8e567bccff }, { 0x00092d0d455bcc6d, 0x000383d2d8e03d14, 0x0000000000000000, 0x0000000000000000 } }; /* ifma_tomont52_n521_(1) */ static const __ALIGN64 Ipp64u n521_r[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x0008000000000000, 0x00082470b763cdfb, 0x00023bb31dc28a24, 0x00047b2d17e2251b }, { 0x00034ca4019ff5b8, 0x0002d73cbc3e2068, 0x0000000000000000, 0x0000000000000000 }, { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 } }; #define group_madd52hi_i64(R, A, B, C) \ FE521_LO(R) = m256_madd52hi_i64(FE521_LO(A), FE521_LO(B), (C)); \ FE521_MID(R) = m256_madd52hi_i64(FE521_MID(A), FE521_MID(B), (C)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(A), FE521_HI(B), (C)) #define group_madd52lo_i64(R, A, B, C) \ FE521_LO(R) = m256_madd52lo_i64(FE521_LO(A), FE521_LO(B), (C)); \ FE521_MID(R) = m256_madd52lo_i64(FE521_MID(A), FE521_MID(B), (C)); \ FE521_HI(R) = m256_madd52lo_i64(FE521_HI(A), FE521_HI(B), (C)) #define NEW_MUL_ROUND(R, A, IDX8, B) \ const m256i Bi##R##IDX8 = m256_permutexvar_i8((IDX8), (B)); \ fe521 amBiLo##R##IDX8, tr##R##IDX8; \ /* (lo/hi) a[]*b[i] */ \ FE521_LO(amBiLo##R##IDX8) = m256_madd52lo_i64(zero, FE521_LO((A)), (Bi##R##IDX8)); \ FE521_MID(amBiLo##R##IDX8) = m256_madd52lo_i64(zero, FE521_MID((A)), (Bi##R##IDX8)); \ FE521_HI(amBiLo##R##IDX8) = m256_madd52lo_i64(zero, FE521_HI((A)), (Bi##R##IDX8)); \ FE521_LO(tr##R##IDX8) = m256_madd52hi_i64(zero, FE521_LO((A)), (Bi##R##IDX8)); \ FE521_MID(tr##R##IDX8) = m256_madd52hi_i64(zero, FE521_MID((A)), (Bi##R##IDX8)); \ FE521_HI(tr##R##IDX8) = m256_madd52hi_i64(zero, FE521_HI((A)), (Bi##R##IDX8)); \ { \ /* R = R + a[]*b[i](lo) */ \ fe521_add_no_red(R, R, amBiLo##R##IDX8); \ /* u = R[0] * 1 */ \ const m256i R0 = m256_permutexvar_i8(idx0, FE521_LO((R))); \ const m256i u = m256_madd52lo_i64(zero, R0, K0); \ /* R = R + m[]*u (lo/hi) */ \ group_madd52hi_i64(tr##R##IDX8, tr##R##IDX8, N, u); \ group_madd52lo_i64(R, R, N, u); \ /* get carry low + add hi compute */ \ const m256i carryone = m256_maskz_srai_i64(0x1, FE521_LO(R), DIGIT_SIZE_52); \ FE521_LO(tr##R##IDX8) = m256_add_i64(FE521_LO(tr##R##IDX8), carryone); \ /* shift */ \ FE521_LO(R) = m256_alignr_i64(FE521_MID(R), FE521_LO(R), 1); \ FE521_MID(R) = m256_alignr_i64(FE521_HI(R), FE521_MID(R), 1); \ FE521_HI(R) = m256_maskz_permutexvar_i8(mask_sr64, idx_sr64, FE521_HI(R)); \ /* add hi compute */ \ fe521_add_no_red(R, R, tr##R##IDX8); \ } IPP_OWN_DEFN(void, ifma_amm52_n521, (fe521 pr[], const fe521 a, const fe521 b)) { /* k0 */ const m256i K0 = m256_set1_i64(n521_k0); fe521 N; FE521_LOADU(N, n521_x1); const m256i zero = m256_setzero_i64(); /* chunk2 shift bit >> 64 */ const mask32 mask_sr64 = 0x00FFFFFF; const m256i idx_sr64 = m256_set_i8(0, 0, 0, 0, 0, 0, 0, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8); // IDX const m256i idx0 = m256_set_i8(REPL4(7, 6, 5, 4, 3, 2, 1, 0)); const m256i idx1 = m256_set_i8(REPL4(15, 14, 13, 12, 11, 10, 9, 8)); const m256i idx2 = m256_set_i8(REPL4(23, 22, 21, 20, 19, 18, 17, 16)); const m256i idx3 = m256_set_i8(REPL4(31, 30, 29, 28, 27, 26, 25, 24)); const m256i idx4 = m256_set_i8(REPL4(7, 6, 5, 4, 3, 2, 1, 0)); const m256i idx5 = m256_set_i8(REPL4(15, 14, 13, 12, 11, 10, 9, 8)); const m256i idx6 = m256_set_i8(REPL4(23, 22, 21, 20, 19, 18, 17, 16)); const m256i idx7 = m256_set_i8(REPL4(31, 30, 29, 28, 27, 26, 25, 24)); const m256i idx8 = m256_set_i8(REPL4(7, 6, 5, 4, 3, 2, 1, 0)); const m256i idx9 = m256_set_i8(REPL4(15, 14, 13, 12, 11, 10, 9, 8)); const m256i idx10 = m256_set_i8(REPL4(23, 22, 21, 20, 19, 18, 17, 16)); fe521 r; FE521_SET(r) = m256_setzero_i64(); NEW_MUL_ROUND(r, a, idx0, FE521_LO(b)) NEW_MUL_ROUND(r, a, idx1, FE521_LO(b)) NEW_MUL_ROUND(r, a, idx2, FE521_LO(b)) NEW_MUL_ROUND(r, a, idx3, FE521_LO(b)) NEW_MUL_ROUND(r, a, idx4, FE521_MID(b)) NEW_MUL_ROUND(r, a, idx5, FE521_MID(b)) NEW_MUL_ROUND(r, a, idx6, FE521_MID(b)) NEW_MUL_ROUND(r, a, idx7, FE521_MID(b)) NEW_MUL_ROUND(r, a, idx8, FE521_HI(b)) NEW_MUL_ROUND(r, a, idx9, FE521_HI(b)) NEW_MUL_ROUND(r, a, idx10, FE521_HI(b)) ifma_lnorm52_p521(&r, r); FE521_COPY(*pr, r); return; } #undef group_madd52hi_i64 #undef group_madd52lo_i64 #undef NEW_MUL_ROUND IPP_OWN_DEFN(void, ifma_add52_n521, (fe521 pr[], const fe521 a, const fe521 b)) { const m256i zero = m256_setzero_i64(); fe521 N; FE521_LOADU(N, n521_x1); /* r = a + b */ fe521 r; fe521_add_no_red(r, a, b); ifma_lnorm52_p521(&r, r); /* t = r - N */ fe521 t; fe521_sub_no_red(t, r, N); ifma_norm52_p521(&t, t); /* lt = t < 0 */ const mask8 lt = m256_cmp_i64_mask(zero, m256_srli_i64(FE521_HI(t), DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 2) & 1)); /* mask != 0 ? a : r */ FE521_MASK_MOV(r, t, mask, r); FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, ifma_tomont52_n521, (fe521 pr[], const fe521 a)) { fe521 RR; FE521_LOADU(RR, n521_rr); ifma_amm52_n521(pr, a, RR); return; } IPP_OWN_DEFN(void, ifma_fastred52_n521, (fe521 pr[], const fe521 a)) { fe521 N; FE521_LOADU(N, n521_x1); const m256i zero = m256_setzero_i64(); fe521 r; fe521_sub_no_red(r, a, N); ifma_norm52_p521(&r, r); const mask8 lt = m256_cmp_i64_mask(zero, m256_srli_i64(FE521_HI(r), DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 2) & 1)); /* mask != 0 ? a : r */ FE521_MASK_MOV(r, r, mask, a); FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, ifma_frommont52_n521, (fe521 pr[], const fe521 a)) { fe521 ONE; FE521_LOADU(ONE, P521R1_ONE52); ifma_amm52_n521(pr, a, ONE); ifma_fastred52_n521(pr, *pr); return; } static void ifma_ams52_n521(fe521 pr[], const fe521 a) { ifma_amm52_n521(pr, a, a); } #define mul(R, A, B) ifma_amm52_n521(&(R), (A), (B)) #define sqr(R, A) ifma_ams52_n521(&(R), (A)) /* r = base^(2^n) */ __IPPCP_INLINE IPP_OWN_DEFN(void, ifma_ams52_p521_ntimes, (fe521 pr[], const fe521 a, int n)) { fe521 r; FE521_COPY(r, a); for (; n > 0; --n) sqr(r, r); FE521_COPY(*pr, r); return; } #define sqr_ntimes(R, A, N) ifma_ams52_p521_ntimes(&(R), (A), (N)) IPP_OWN_DEFN(void, ifma_aminv52_n521, (fe521 pr[], const fe521 z)) { Ipp32u i; fe521 n521r1_r; FE521_LOADU(n521r1_r, n521_r); // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 fe521 pwr_z_Tbl[16]; __ALIGN64 fe521 lexp; FE521_COPY(pwr_z_Tbl[0], n521r1_r); FE521_COPY(pwr_z_Tbl[1], z); for (i = 2u; i < 16u; i += 2u) { sqr(pwr_z_Tbl[i], pwr_z_Tbl[i / 2u]); mul(pwr_z_Tbl[i + 1u], pwr_z_Tbl[i], z); } // pwr = (n521-2) in big endian const Ipp8u pwr[] = "\x1\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFA" "\x51\x86\x87\x83\xBF\x2F\x96\x6B" "\x7F\xCC\x01\x48\xF7\x09\xA5\xD0" "\x3B\xB5\xC9\xB8\x89\x9C\x47\xAE" "\xBB\x6F\xB7\x1E\x91\x38\x64\x07"; /* // process 25 low bytes of the exponent: :FA 51 86 ... 64 07" */ /* init result */ FE521_COPY(lexp, n521r1_r); for (i = 33u; i < sizeof(pwr) - 1u; ++i) { const int v = pwr[i]; const int hi = (v >> 4) & 0xF; const int lo = v & 0xF; sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); if (hi) mul(lexp, lexp, pwr_z_Tbl[hi]); sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); sqr(lexp, lexp); if (lo) mul(lexp, lexp, pwr_z_Tbl[lo]); } /* // process high part of the exponent: "0x1 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff" */ fe521 u, v; FE521_SET(u) = FE521_SET(v) = m256_setzero_i64(); FE521_COPY(u, pwr_z_Tbl[15]); /* u = z^0xF */ /**/ sqr_ntimes(v, u, 4); /* v = (z^0xF)^(2^4) = z^(0xF0) */ mul(u, v, u); /* u = z^0xF0 * z^(0xF) = z^(0xFF) */ /**/ sqr_ntimes(v, u, 8); /* v = (z^0xFF)^(2^8) = z^(0xFF00) */ mul(u, v, u); /* u = z^0xFF00 * z^(0xFF) = z^(0xFFFF) */ /**/ sqr_ntimes(v, u, 16); /* v = (z^0xFFFF)^(2^16) = z^(0xFFFF0000) */ mul(u, v, u); /* u = z^0xFFFF0000 * z^(0xFFFF) = z^(0xFFFFFFFF) */ /**/ sqr_ntimes(v, u, 32); /* v = (z^0xFFFFFFFF)^(2^32) = z^(0xFFFFFFFF00000000) */ mul(u, v, u); /* u = z^0xFFFFFFFF00000000 * z^(0xFFFFFFFF) = z^(0xFFFFFFFFFFFFFFFF) */ /**/ sqr_ntimes(v, z, 64); /**/ mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF) */ /**/ sqr_ntimes(v, v, 64); /**/ mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /**/ sqr_ntimes(v, v, 64); /**/ mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /**/ sqr_ntimes(v, v, 64); /**/ mul(v, v, u); /* v = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF) */ /* combine low and high results */ sqr_ntimes(v, v, 64 * 4 + 8); /* u = z^(0x1.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.00.0000000000000000.0000000000000000.0000000000000000.0000000000000000) */ mul(*pr, v, lexp); /* r = z^(0x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFA.51868783BF2F966B.7FCC0148F709A5D0.3BB5C9B8899C47AE.BB6FB71E91386407) */ return; } #undef mul #undef sqr #undef sqr_ntimes #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_n521.h000066400000000000000000000042741470420105600266320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ARITH_N521_H #define IFMA_ARITH_N521_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_defs_p521.h" /** * \brief * R = (A * B) - in domain n521r1 * \param[out] pr value no normalization * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_amm52_n521, (fe521 pr[], const fe521 a, const fe521 b)) /** * \brief * R = (A + B) mod n521r1 * \param[out] pr value (in radix 2^52) * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_add52_n521, (fe521 pr[], const fe521 a, const fe521 b)) /** * \brief * to Montgomery domain * \param[out] pr value (in radix 2^52) * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_tomont52_n521, (fe521 pr[], const fe521 a)) /** * \brief * fast reduction order n521r1 * \param[out] pr value (in radix 2^52) * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_fastred52_n521, (fe521 pr[], const fe521 a)) /** * \brief * from Montgomery domain * \param[out] pr value (in radix 2^52) * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_frommont52_n521, (fe521 pr[], const fe521 a)) /** * \brief * inverse R = 1/z * \param[out] pr value (in radix 2^52) * \param[in] z value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_aminv52_n521, (fe521 pr[], const fe521 z)) #endif // (_IPP32E >= _IPP32E_K1) #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_p256.c000066400000000000000000000400741470420105600266320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p256.h" #include "gfpec/ecnist/ifma_defs.h" #define LEN52 (5 + 3) /* 5 digits + 3 zero padding */ /* Modulus p256r1 */ static const __ALIGN64 Ipp64u p256_x1[LEN52] = { 0x000fffffffffffff, 0x00000fffffffffff, 0x0000000000000000, 0x0000001000000000, 0x0000ffffffff0000, 0x0, 0x0, 0x0 }; /* Scaled modulus 4*p256r1 */ static const __ALIGN64 Ipp64u p256_x4[LEN52] = { 0x000ffffffffffffc, 0x00003fffffffffff, 0x0000000000000000, 0x0000004000000000, 0x0003fffffffc0000, 0x0, 0x0, 0x0 }; /* To Montgomery domain conversion constant * * The extended Montgomery domain here with R = 2^(6*52) instead of 2^(5*62) is * chosen to use NRMM field multiplication routine in the sequence of EC group * operations (point multiplication on scalar / addition) without modulo * reductions in the field addition (see Chapter 4 in "Enhanced Montgomery * Multiplication" DOI:10.1155/2008/583926). According to the paper the chosen * |s| in NRMM^s(a,b) shall be equal to n + 2*kmax, with kmax = 4 for EC group * operations, so s = 264. 5 digits capacity is only 260 bits, so purely IFMA-based * implementation shall use 6 digits. * * rr = 2^((52*6))*2) mod p256 */ static const __ALIGN64 Ipp64u p256_rr6[LEN52] = { 0x0002fffffffdffff, 0x0000100050000000, 0x000ffd0000000500, 0x0000000fff9fffff, 0x0000fff9fffefffe, 0x0, 0x0, 0x0 }; #if 0 /* * rr = 2^((52*5))*2) mod p256 */ static const __ALIGN64 Ipp64u p256_rr5[LEN52] = { 0x0000000000000300, 0x000ffffffff00000, 0x000ffffefffffffb, 0x000fdfffffffffff, 0x0000000004ffffff, 0x0, 0x0, 0x0 }; #endif static const __ALIGN64 Ipp64u ones[LEN52] = { 1, 0, 0, 0, 0, 0, 0, 0 }; #define MUL_RED_ROUND(R, A, B, IDX) \ { \ const m512 Bi = permutexvar_i8(idx_b##IDX, (B)); \ m512 Rlo = madd52lo_i64(zero, (A), Bi); \ m512 tmp = madd52hi_i64(zero, (A), Bi); \ \ (R) = add_i64((R), Rlo); \ /* broadcast R[0] */ \ const m512 R0 = permutexvar_i8(idx_b0, (R)); \ (R) = madd52lo_i64((R), M, R0); \ tmp = madd52hi_i64(tmp, M, R0); \ /* shift */ \ const m512 carry = maskz_srli_i64(maskone, (R), DIGIT_SIZE); \ tmp = add_i64(tmp, carry); \ (R) = maskz_permutexvar_i8(mask_sr64, idx_sr64, (R)); \ /* hi */ \ (R) = add_i64((R), tmp); \ } /* R = (A*B) - no normalization radix 52 */ IPP_OWN_DEFN(m512, ifma_amm52_p256, (const m512 a, const m512 b)) { const m512 M = loadu_i64(p256_x1); const m512 zero = setzero_i64(); const mask8 maskone = 0x1; /* Index broadcast */ const m512 idx_b0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const m512 idx_b1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const m512 idx_b2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const m512 idx_b3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const m512 idx_b4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const m512 idx_b5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 /* Mask to shift zmm register right on 64-bit */ const mask64 mask_sr64 = 0x00ffffffffffffff; const m512 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 r = setzero_i64(); MUL_RED_ROUND(r, a, b, 0) MUL_RED_ROUND(r, a, b, 1) MUL_RED_ROUND(r, a, b, 2) MUL_RED_ROUND(r, a, b, 3) MUL_RED_ROUND(r, a, b, 4) MUL_RED_ROUND(r, a, b, 5) return r; } IPP_OWN_DEFN(void, ifma_amm52_dual_p256, (m512 * r1, const m512 a1, const m512 b1, m512 *r2, const m512 a2, const m512 b2)) { const m512 M = loadu_i64(p256_x1); const m512 zero = setzero_i64(); const mask8 maskone = 0x1; /* Index broadcast */ const m512 idx_b0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const m512 idx_b1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const m512 idx_b2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const m512 idx_b3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const m512 idx_b4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const m512 idx_b5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 /* Mask to shift zmm register right on 64-bit */ const mask64 mask_sr64 = 0x00ffffffffffffff; const m512 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 t1 = setzero_i64(); m512 t2 = setzero_i64(); MUL_RED_ROUND(t1, a1, b1, 0) MUL_RED_ROUND(t2, a2, b2, 0) MUL_RED_ROUND(t1, a1, b1, 1) MUL_RED_ROUND(t2, a2, b2, 1) MUL_RED_ROUND(t1, a1, b1, 2) MUL_RED_ROUND(t2, a2, b2, 2) MUL_RED_ROUND(t1, a1, b1, 3) MUL_RED_ROUND(t2, a2, b2, 3) MUL_RED_ROUND(t1, a1, b1, 4) MUL_RED_ROUND(t2, a2, b2, 4) MUL_RED_ROUND(t1, a1, b1, 5) MUL_RED_ROUND(t2, a2, b2, 5) *r1 = t1; *r2 = t2; } /* R = (A*B) with norm */ __IPPCP_INLINE m512 ifma_amm52_p256_norm(const m512 a, const m512 b) { m512 r = ifma_amm52_p256(a, b); return ifma_lnorm52(r); } /* R = (A*A) with norm */ __IPPCP_INLINE m512 ifma_ams52_p256_norm(const m512 a) { return ifma_amm52_p256_norm(a, a); } /* R = (A/2) */ IPP_OWN_DEFN(m512, ifma_half52_p256, (const m512 a)) { const m512 M = loadu_i64(p256_x1); const m512 zero = setzero_i64(); const m512 one = set1_i64(1LL); const mask8 is_last_one = cmp_i64_mask(and_i64(a, one), zero, _MM_CMPINT_EQ); const mask8 mask = (mask8)((is_last_one & 1) - 1); const mask64 mask_shift = 0x00ffffffffffffff; const m512 idx_shift = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 r = mask_add_i64(a, mask, a, M); r = ifma_lnorm52(r); m512 leftBit = maskz_permutexvar_i8(mask_shift, idx_shift, and_i64(r, one)); leftBit = slli_i64(leftBit, DIGIT_SIZE - 1); r = srli_i64(r, 1); r = add_i64(r, leftBit); return r; } IPP_OWN_DEFN(m512, ifma_neg52_p256, (const m512 a)) { const m512 M4 = loadu_i64(p256_x4); /* a == 0 ? 0xFF : 0 */ const mask8 mask_zero = is_zero_i64(a); /* r = 4*p - a */ m512 r = mask_sub_i64(a, ~mask_zero, M4, a); r = ifma_norm52(r); return r; } static m512 mod_reduction_p256(const m512 a) { const m512 M = loadu_i64(p256_x1); const m512 zero = setzero_i64(); /* r = a - M */ m512 r = sub_i64(a, M); r = ifma_norm52(r); /* 1 < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE - 1), _MM_CMPINT_LT); const mask8 mask = check_bit(lt, 4); // check sign in 5th digit /* mask != 0 ? a : r */ r = mask_mov_i64(r, mask, a); return r; } /* to Montgomery domain */ IPP_OWN_DEFN(m512, ifma_tomont52_p256, (const m512 a)) { return ifma_amm52_p256_norm(a, loadu_i64(p256_rr6)); } /* from Montgomery domain */ IPP_OWN_DEFN(m512, ifma_frommont52_p256, (const m512 a)) { m512 r = ifma_amm52_p256_norm(a, loadu_i64(ones)); r = mod_reduction_p256(r); return r; } #define sqr(R, A) (R) = ifma_ams52_p256_norm((A)) #define mul(R, A, B) (R) = ifma_amm52_p256_norm((A), (B)); __IPPCP_INLINE m512 ifma_ams52_p256_ntimes(m512 a, Ipp32s n) { for (; n > 0; --n) sqr(a, a); return a; } #define sqr_ntimes(R, A, N) (R) = ifma_ams52_p256_ntimes((A), (N)) /* R = 1/z */ IPP_OWN_DEFN(m512, ifma_aminv52_p256, (const m512 z)) { __ALIGN64 m512 tmp1; __ALIGN64 m512 tmp2; /* Each eI holds z^(2^I-1) */ __ALIGN64 m512 e2; __ALIGN64 m512 e4; __ALIGN64 m512 e8; __ALIGN64 m512 e16; __ALIGN64 m512 e32; __ALIGN64 m512 e64; /* tmp1 = z^(2^1) */ sqr(tmp1, z); /* e2 = tmp1 = tmp1 * z = z^(2^2 - 2^0) */ mul(tmp1, tmp1, z); e2 = tmp1; /* tmp1 = tmp1^2 = z^(2^2 - 2^0)*2 = z^(2^3 - 2^1) */ sqr(tmp1, tmp1); /* tmp1 = tmp1^2 = z^(2^3 - 2^1)*2 = z^(2^4 - 2^2) */ sqr(tmp1, tmp1); /* e4 = tmp1 = tmp1*e2 = z^(2^4 - 2^2) * z^(2^2 - 2^0) = z^(2^4 - 2^2 + 2^2 - 2^0) = z^(2^4 - 2^0)*/ mul(tmp1, tmp1, e2); e4 = tmp1; /* tmp1 = tmp1^2 = z^(2^4 - 2^0)*2 = z^(2^5 - 2^1) */ sqr(tmp1, tmp1); /* tmp1 = tmp1^2 = z^(2^5 - 2^1)*2 = z^(2^6 - 2^2) */ sqr(tmp1, tmp1); /* tmp1 = tmp1^2 = z^(2^6 - 2^2)*2 = z^(2^7 - 2^3) */ sqr(tmp1, tmp1); /* tmp1 = tmp1^2 = z^(2^7 - 2^3)*2 = z^(2^8 - 2^4) */ sqr(tmp1, tmp1); /* e8 = tmp1 = tmp1*e4 = z^(2^8 - 2^4) * z^(2^4 - 2^0) = z^(2^8 - 2^4 + 2^4 - 2^0) = z^(2^8 - 2^0)*/ mul(tmp1, tmp1, e4); e8 = tmp1; /* tmp1 = tmp1^(2^8) = z^(2^8 - 2^0)*2^8 = z^(2^16 - 2^8) */ sqr_ntimes(tmp1, tmp1, 8); /* e16 = tmp1 = tmp1*e8 = z^(2^16 - 2^8) * z^(2^8 - 2^0) = z^(2^16 - 2^8 + 2^8 - 2^0) = z^(2^16 - 2^0)*/ mul(tmp1, tmp1, e8); e16 = tmp1; /* tmp1 = tmp1^(2^16) = z^(2^16 - 2^0)*2^16 = z^(2^32 - 2^16) */ sqr_ntimes(tmp1, tmp1, 16); /* e32 = tmp1 = tmp1*e16 = z^(2^32 - 2^16) * z^(2^16 - 2^0) = z^(2^32 - 2^16 + 2^16 - 2^0) = z^(2^32 - 2^0)*/ mul(tmp1, tmp1, e16); e32 = tmp1; /* e64 = tmp1 = tmp1^(2^32) = z^(2^32 - 2^0)*2^32 = z^(2^64 - 2^32) */ sqr_ntimes(tmp1, tmp1, 32); e64 = tmp1; /* tmp1 = tmp1*z = z^(2^64 - 2^32) * z = z^(2^64 - 2^32 + 2^0)*/ mul(tmp1, tmp1, z); /* tmp1 = tmp1^(2^192) = z^(2^64 - 2^32 + 2^0)*2^192 = z^(2^256 - 2^224 + 2^192) */ sqr_ntimes(tmp1, tmp1, 192); /* tmp2 = e64*e32 = z^(2^64 - 2^32) * z^(2^32 - 2^0) = z^(2^64 - 2^32 + 2^32 - 2^0) = z^(2^64 - 2^0)*/ mul(tmp2, e64, e32); /* tmp2 = tmp2^(2^16) = z^(2^64 - 2^0)*2^16 = z^(2^80 - 2^16) */ sqr_ntimes(tmp2, tmp2, 16); /* tmp2 = tmp2*e16 = z^(2^80 - 2^16) * z^(2^16 - 2^0) = z^(2^80 - 2^16 + 2^16 - 2^0) = z^(2^80 - 2^0)*/ mul(tmp2, tmp2, e16); /* tmp2 = tmp2^(2^8) = z^(2^80 - 2^0)*2^8 = z^(2^88 - 2^8) */ sqr_ntimes(tmp2, tmp2, 8); /* tmp2 = tmp2*e8 = z^(2^88 - 2^8) * z^(2^8 - 2^0) = z^(2^88 - 2^8 + 2^8 - 2^0) = z^(2^88 - 2^0)*/ mul(tmp2, tmp2, e8); /* tmp2 = tmp2^(2^4) = z^(2^88 - 2^0)*2^4 = z^(2^92 - 2^4) */ sqr_ntimes(tmp2, tmp2, 4); /* tmp2 = tmp2*e4 = z^(2^92 - 2^4) * z^(2^4 - 2^0) = z^(2^92 - 2^4 + 2^4 - 2^0) = z^(2^92 - 2^0)*/ mul(tmp2, tmp2, e4); /* tmp2 = tmp2^2 = z^(2^92 - 2^0)*2^1 = z^(2^93 - 2^1) */ sqr(tmp2, tmp2); /* tmp2 = tmp2^2 = z^(2^93 - 2^1)*2^1 = z^(2^94 - 2^2) */ sqr(tmp2, tmp2); /* tmp2 = tmp2*e2 = z^(2^94 - 2^2) * z^(2^2 - 2^0) = z^(2^94 - 2^2 + 2^2 - 2^0) = z^(2^94 - 2^0)*/ mul(tmp2, tmp2, e2); /* tmp2 = tmp2^2 = z^(2^94 - 2^0)*2^1 = z^(2^95 - 2^1) */ sqr(tmp2, tmp2); /* tmp2 = tmp2^2 = z^(2^95 - 2^1)*2^1 = z^(2^96 - 2^2) */ sqr(tmp2, tmp2); /* tmp2 = tmp2*z = z^(2^96 - 2^2) * z = z^(2^96 - 2^2 + 1) = z^(2^96 - 3) */ mul(tmp2, tmp2, z); /* r = tmp1*tmp2 = z^(2^256 - 2^224 + 2^192) * z^(2^96 - 3) = z^(2^256 - 2^224 + 2^192 + 2^96 - 3) */ m512 r = setzero_i64(); mul(r, tmp1, tmp2); return r; } #undef sqr #undef mul #undef sqr_ntimes IPP_OWN_DEFN(m512, convert_radix_to_52x5, (const Ipp64u *arad64)) { const m512 mask_rad52 = set1_i64(DIGIT_MASK); const m512 idx16 = set_i64( 0x0019001800170016, // 25, 24, 23, 22, 0x0016001500140013, // 22, 21, 20, 19, 0x0013001200110010, // 19, 18, 17, 16, 0x0010000f000e000d, // 16, 15, 14, 13, 0x000c000b000a0009, // 12, 11, 10, 9, 0x0009000800070006, // 9, 8, 7, 6, 0x0006000500040003, // 6, 5, 4, 3, 0x0003000200010000); // 3, 2, 1, 0 const __m512i shiftR = set_i64( 12, 8, 4, 0, 12, 8, 4, 0); m512 r = maskz_loadu_i64(0xf, arad64); // load 4 digits r = permutexvar_i16(idx16, r); r = srlv_i64(r, shiftR); r = and_i64(mask_rad52, r); return r; } IPP_OWN_DEFN(void, convert_radix_to_64x4, (Ipp64u * rrad64, const m512 arad52)) { const m512 shiftL = set_i64( 4, 0, 4, 0, 4, 0, 4, 0); const m512 perm1 = set_i64( 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3e3d3c3b, // {63,63,63,63,62,61,60,59} 0x3737363534333231, // {55,55,54,53,52,51,50,49} 0x302e2d2c2b2a2928, // {48,46,45,44,43,42,41,40} 0x1f1f1f1f1f1f1e1d, // {31,31,31,31,31,31,30,29} 0x1717171716151413, // {23,23,23,23,22,21,20,19} 0x0f0f0f0e0d0c0b0a, // {15,15,15,14,13,12,11,10} 0x0706050403020100); // { 7, 6, 5, 4, 3, 2, 1, 0} const m512 perm2 = set_i64( 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3a39383737373737, // {58,57,56,55,55,55,55,55} 0x2727272727272726, // {39,39,39,39,39,39,39,38} 0x2524232221201f1f, // {37,36,35,34,33,32,31,31} 0x1c1b1a1918171717, // {28,27,26,25,24,23,23,23} 0x1211100f0f0f0f0f, // {18,17,16,15,15,15,15,15} 0x0908070707070707); // { 9, 8, 7, 7, 7, 7, 7, 7} m512 r = arad52; r = sllv_i64(r, shiftL); m512 T = permutexvar_i8(perm1, r); r = permutexvar_i8(perm2, r); r = or_i64(r, T); mask_storeu_i64(rrad64, 0xf, r); // store 4 digits } #endif // #if (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_p256.h000066400000000000000000000075031470420105600266370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ARITH_P256R1_H_) #define _IFMA_ARITH_P256R1_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "ifma_alias_avx512.h" #include "gfpec/ecnist/ifma_norm.h" /** * \brief * * Montgomery multiplication * * a * b * r mod n, where r = 2^(6*52) mod n * * Note: final normalization to 2^52 radix is not performed and shall be * handled separately. * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_amm52_p256, (const m512 a, const m512 b)) /** * \brief * * Dual variant of ifma_amm52_p256() function. * * \param[out] r1 a1 * b1 mod p * \param[in] a1 first value (in radix 2^52) * \param[in] b1 second value (in radix 2^52) * \param[out] r2 a2 * b2 mod p * \param[in] a2 first value (in radix 2^52) * \param[in] b2 second value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_amm52_dual_p256, (m512 *r1, const m512 a1, const m512 b1, m512 *r2, const m512 a2, const m512 b2)) /** * \brief * * A * A * * Note: final normalization to 2^52 radix is not performed and shall be * handled separately. * * \param[in] a value (in radix 2^52) */ __IPPCP_INLINE IPP_OWN_DEFN(m512, ifma_ams52_p256, (const m512 a)) { return ifma_amm52_p256(a, a); } /** * \brief * * Dual variant of ifma_ams52_p256() function. * * \param[out] r1 * \param[in] a1 value (in radix 2^52) * \param[out] r2 * \param[in] a2 value (in radix 2^52) */ __IPPCP_INLINE IPP_OWN_DEFN(void, ifma_ams52_dual_p256, (m512 * r1, const m512 a1, m512 *r2, const m512 a2)) { ifma_amm52_dual_p256(r1, a1, a1, r2, a2, a2); return; } /** * \brief * * A / 2 * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_half52_p256, (const m512 a)) /** * \brief * * Modular inverse modulo p. * * 1/z mod p * * \param[in] z value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_aminv52_p256, (const m512 z)) /** * \brief * * (-A) mod p * * \param[in] a input value */ IPP_OWN_DECL(m512, ifma_neg52_p256, (const m512 a)) /** * \brief * * Conversion to Montgomery domain modulo p. * * a * r mod p, where r = 2^(6*52) mod p * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_tomont52_p256, (const m512 a)) /** * \brief * * Conversion from Montgomery domain modulo p. * * a mod p * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_frommont52_p256, (const m512 a)) /* ===================================================================================== */ /* ===================================================================================== */ /** * \brief * * Convert to radix 2^52 from radix 2^64. * * \param[in] pa pointer to array of 4 64-bit chunks */ IPP_OWN_DECL(m512, convert_radix_to_52x5, (const Ipp64u *pa)) /** * \brief * * Convert to radix 2^64 from radix 2^52. * * \param[out] pr pointer to array of 4 64-bit chunks * \param[in] a array of 5 64-bit chunks */ IPP_OWN_DECL(void, convert_radix_to_64x4, (Ipp64u * rrad64, const m512 arad52)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ARITH_P256R1_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_p384.c000066400000000000000000000414651470420105600266410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p384.h" #include "gfpec/ecnist/ifma_defs.h" #define LEN52 (NUMBER_OF_DIGITS(384, 52)) /* p384r1: p = 2^384 - 2^128 - 2^96 + 2^32 - 1 */ static const __ALIGN64 Ipp64u p384_x1[LEN52] = { 0x00000000FFFFFFFF, 0x000FF00000000000, 0x000FFFFFFEFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000000FFFFF }; /* modulus 4*p */ static const __ALIGN64 Ipp64u p384_x4[LEN52] = { 0x00000003FFFFFFFC, 0x000FC00000000000, 0x000FFFFFFBFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000003FFFFF }; /* to Montgomery conversion constant * rr = 2^((P384_LEN52*DIGIT_SIZE)*2) mod p384 */ static const __ALIGN64 Ipp64u p384_rr[LEN52] = { 0x0000000000000000, 0x000FE00000001000, 0x0000000000FFFFFF, 0x0000000000000020, 0x0000FFFFFFFE0000, 0x0000000020000000, 0x0000000000000100, 0x0000000000000000 }; static const __ALIGN64 Ipp64u ones[LEN52] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* R = (A/2) */ IPP_OWN_DEFN(m512, ifma_half52_p384, (const m512 a)) { const m512 M = loadu_i64(p384_x1); const m512 zero = setzero_i64(); const m512 one = set1_i64(1LL); const mask8 is_last_one = cmp_i64_mask(and_i64(a, one), zero, _MM_CMPINT_EQ); const mask8 mask = (mask8)((is_last_one & 1) - 1); m512 r = mask_add_i64(a, mask, a, M); r = ifma_lnorm52(r); /* 1-bit shift right */ /* extract last bit + >> 64 */ const mask64 mask_shift = 0x00ffffffffffffff; const m512 idx_shift = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 shift_right = maskz_permutexvar_i8(mask_shift, idx_shift, and_i64(r, one)); /* set last bit is first bit (52 radix) */ shift_right = slli_i64(shift_right, DIGIT_SIZE - 1); /* join first new bit */ r = srli_i64(r, 1); /* create slot by first bit 1111 -> 0111 */ r = add_i64(r, shift_right); /* join first and other bit */ return r; } IPP_OWN_DEFN(m512, ifma_neg52_p384, (const m512 a)) { const m512 M4 = loadu_i64(p384_x4); /* a == 0 ? 0xFF : 0 */ const mask8 mask_zero = is_zero_i64(a); /* r = 4*p - a */ m512 r = mask_sub_i64(a, ~mask_zero, M4, a); r = ifma_norm52(r); return r; } #define MULT_ROUND(R, A, B, IDX) \ const m512 Bi##R##IDX = permutexvar_i8(idx_b##IDX, (B)); \ const m512 amBiLo##R##IDX = madd52lo_i64(zero, (A), Bi##R##IDX); \ m512 tr##R##IDX = madd52hi_i64(zero, (A), Bi##R##IDX); \ { \ /* low */ \ (R) = add_i64((R), amBiLo##R##IDX); \ const m512 R0 = permutexvar_i8(idx_b0, (R)); \ const m512 u = add_i64(slli_i64(R0, 32), R0); \ tr##R##IDX = madd52hi_i64(tr##R##IDX, M, u); \ (R) = madd52lo_i64((R), M, u); \ /* shift */ \ const m512 carryone = maskz_srai_i64(maskone, (R), DIGIT_SIZE); \ tr##R##IDX = add_i64(tr##R##IDX, carryone); \ (R) = maskz_permutexvar_i8(mask_sr64, idx_sr64, (R)); \ /* hi */ \ (R) = add_i64((R), tr##R##IDX); \ } /* gueron data */ /* R = (A*B) - no normalization radix 52 */ IPP_OWN_DEFN(m512, ifma_amm52_p384, (const m512 a, const m512 b)) { const m512 M = loadu_i64(p384_x1); /* p */ const m512 zero = setzero_i64(); const mask8 maskone = 0x1; /* Index broadcast */ const m512 idx_b0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const m512 idx_b1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const m512 idx_b2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const m512 idx_b3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const m512 idx_b4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const m512 idx_b5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 const m512 idx_b6 = set_i64(REPL8(0x3736353433323130)); // 55, 54, 53, 52, 51, 50, 49, 48 const m512 idx_b7 = set_i64(REPL8(0x3f3e3d3c3b3a3938)); // 63, 62, 61, 60, 59, 58, 57, 56 /* Mask to shift zmm register right on 64-bit */ const mask64 mask_sr64 = 0x00ffffffffffffff; const m512 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 r = setzero_i64(); /* P384 * m' mod b = 2^32 + 1 * * Algorithm * a[] b[] - input data ((in radix 2^52)) m[] - module p384 * * when u = R[0]*m' mod b * 1) R = R + a[] * b[i] (lo) * 2) R = R + m[] * u (lo) * 3) R = R >> 64 * 4) R = R + a[] * b[i] (hi) * 5) R = R + m[] * u (hi) */ /* one round = O(32) */ MULT_ROUND(r, a, b, 0) MULT_ROUND(r, a, b, 1) MULT_ROUND(r, a, b, 2) MULT_ROUND(r, a, b, 3) MULT_ROUND(r, a, b, 4) MULT_ROUND(r, a, b, 5) MULT_ROUND(r, a, b, 6) MULT_ROUND(r, a, b, 7) return r; } IPP_OWN_DEFN(void, ifma_amm52_dual_p384, (m512 * pr1, const m512 a1, const m512 b1, m512 *pr2, const m512 a2, const m512 b2)) { const m512 M = loadu_i64(p384_x1); /* p */ const m512 zero = setzero_i64(); const mask8 maskone = 0x1; /* Index broadcast */ const m512 idx_b0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const m512 idx_b1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const m512 idx_b2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const m512 idx_b3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const m512 idx_b4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const m512 idx_b5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 const m512 idx_b6 = set_i64(REPL8(0x3736353433323130)); // 55, 54, 53, 52, 51, 50, 49, 48 const m512 idx_b7 = set_i64(REPL8(0x3f3e3d3c3b3a3938)); // 63, 62, 61, 60, 59, 58, 57, 56 /* Mask to shift zmm register right on 64-bit */ const mask64 mask_sr64 = 0x00ffffffffffffff; const m512 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 m512 r1 = setzero_i64(); m512 r2 = setzero_i64(); /* P384 * m' mod b = 2^32 + 1 * * Algorithm * a[] b[] - input data ((in radix 2^52)) m[] - module p384 * * when u = R[0]*m' mod b * 1) R = R + a[] * b[i] (lo) * 2) R = R + m[] * u (lo) * 3) R = R >> 64 * 4) R = R + a[] * b[i] (hi) * 5) R = R + m[] * u (hi) */ /* one round = O(32) */ /* 0-1 */ MULT_ROUND(r1, a1, b1, 0) MULT_ROUND(r1, a1, b1, 1) /* 0-1 */ MULT_ROUND(r2, a2, b2, 0) MULT_ROUND(r2, a2, b2, 1) /* 2-3 */ MULT_ROUND(r1, a1, b1, 2) MULT_ROUND(r1, a1, b1, 3) /* 2-3 */ MULT_ROUND(r2, a2, b2, 2) MULT_ROUND(r2, a2, b2, 3) /* 4-5 */ MULT_ROUND(r1, a1, b1, 4) MULT_ROUND(r1, a1, b1, 5) /* 4-5 */ MULT_ROUND(r2, a2, b2, 4) MULT_ROUND(r2, a2, b2, 5) /* 6-7 */ MULT_ROUND(r1, a1, b1, 6) MULT_ROUND(r1, a1, b1, 7) /* 6-7 */ MULT_ROUND(r2, a2, b2, 6) MULT_ROUND(r2, a2, b2, 7) /* set out */ *pr1 = r1; *pr2 = r2; return; } /* R = (A*B) with norm */ __IPPCP_INLINE m512 ifma_amm52_p384_norm(const m512 a, const m512 b) { m512 r = ifma_amm52_p384(a, b); /* normalization */ return ifma_lnorm52(r); } /* R = (A*A) with norm */ __IPPCP_INLINE m512 m512_sqr_norm(const m512 a) { return ifma_amm52_p384_norm(a, a); } /* to Montgomery domain */ IPP_OWN_DEFN(m512, ifma_tomont52_p384, (const m512 a)) { const m512 RR = loadu_i64(p384_rr); return ifma_amm52_p384_norm(a, RR); } static m512 mod_reduction_p384(const m512 a) { const m512 M = loadu_i64(p384_x1); const m512 zero = setzero_i64(); /* r = a - M */ m512 r = sub_i64(a, M); r = ifma_norm52(r); /* 1 < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE - 1), _MM_CMPINT_LT); const mask8 mask = check_bit(lt, 7); /* mask != 0 ? a : r */ r = mask_mov_i64(r, mask, a); return r; } /* from Montgomery domain */ IPP_OWN_DEFN(m512, ifma_frommont52_p384, (const m512 a)) { const m512 one = loadu_i64(ones); /* from mont */ m512 r = ifma_amm52_p384_norm(a, one); r = mod_reduction_p384(r); return r; } #define sqr(R, A) (R) = m512_sqr_norm((A)) #define mul(R, A, B) (R) = ifma_amm52_p384_norm((A), (B)); #define mul_dual(R1, A1, B1, R2, A2, B2) \ ifma_amm52_dual_p384(&(R1), (A1), (B1), &(R2), (A2), (B2)); \ ifma_lnorm52_dual(&(R1), (R1), &(R2), (R2)) __IPPCP_INLINE m512 ifma_ams52_p384_ntimes(const m512 a, Ipp32s n) { m512 r = a; for (; n > 0; --n) sqr(r, r); return r; } #define sqr_ntimes(R, A, N) (R) = ifma_ams52_p384_ntimes((A), (N)) /* R = 1/z */ IPP_OWN_DEFN(m512, ifma_aminv52_p384, (const m512 z)) { m512 u, v, zD, zE, zF; u = v = zD = zE = zF = setzero_i64(); sqr(u, z); /* u = z^2 */ mul(v, u, z); /* v = z^2 * z = z^3 */ sqr_ntimes(zF, v, 2); /* zF = (z^3)^(2^2) = z^12 */ /**/ mul(zD, zF, z); /* zD = z^11 * z = z^xD */ mul_dual(zE, zF, u, /* zE = z^11 * z^2 = z^xE */ zF, zF, v); /* zF = z^11 * z^3 = z^xF */ /**/ sqr_ntimes(u, zF, 4); /* u = (z^xF)^(2^4) = z^xF0 */ mul_dual(zD, u, zD, /* zD = z^xF0 * z^xD = z^xFD */ zE, u, zE); /* zE = z^xF0 * z^xE = z^xFE */ mul(zF, u, zF); /* zF = z^xF0 * z^xF = z^xFF */ /**/ sqr_ntimes(u, zF, 8); /* u = (z^xFF)^(2^8) = z^xFF00 */ mul_dual(zD, u, zD, /* zD = z^xFF00 * z^xFD = z^xFFFD */ zE, u, zE); /* zE = z^xFF00 * z^xFE = z^xFFFE */ mul(zF, u, zF); /* zF = z^xFF00 * z^xFF = z^xFFFF */ /**/ sqr_ntimes(u, zF, 16); /* u = (z^xFFFF)^(2^16) = z^xFFFF0000 */ mul_dual(zD, u, zD, /* zD = z^xFFFF0000 * z^xFFFD = z^xFFFFFFFD */ zE, u, zE); /* zE = z^xFFFF0000 * z^xFFFE = z^xFFFFFFFE */ mul(zF, u, zF); /* zF = z^xFFFF0000 * z^xFFFF = z^xFFFFFFFF */ /**/ sqr_ntimes(u, zF, 32); /* u = (z^xFFFFFFFF)^(2^32) = z^xFFFFFFFF00000000 */ mul_dual(zE, u, zE, /* zE = z^xFFFFFFFF00000000 * z^xFFFFFFFE = z^xFFFFFFFFFFFFFFFE */ zF, u, zF); /* zF = z^xFFFFFFFF00000000 * z^xFFFFFFFF = z^xFFFFFFFFFFFFFFFF */ /* v = z^xFFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, zF, 64); mul(v, v, zF); /* v = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFE = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE */ sqr_ntimes(v, v, 64); mul(v, v, zE); /* v = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.0000000000000000 * z^xFFFFFFFF00000000 = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFF00000000 */ sqr_ntimes(v, v, 64); mul(v, v, u); /* r = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFF00000000.0000000000000000 * z^xFFFFFFFD = z^xFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFF00000000.00000000FFFFFFFD */ sqr_ntimes(v, v, 64); m512 r = setzero_i64(); mul(r, v, zD); return r; } #undef sqr #undef mul #undef mul_dual #undef sqr_ntimes IPP_OWN_DEFN(m512, convert_radix_to_52x8, (const Ipp64u *arad64)) { /* load mask to register */ const mask8 mask_load = 0x3f; const m512 mask_rad52 = set1_i64(DIGIT_MASK); /* set data */ const m512 idx16 = set_i64( 0x0019001800170016, // 25, 24, 23, 22, 0x0016001500140013, // 22, 21, 20, 19, 0x0013001200110010, // 19, 18, 17, 16, 0x0010000f000e000d, // 16, 15, 14, 13, 0x000c000b000a0009, // 12, 11, 10, 9, 0x0009000800070006, // 9, 8, 7, 6, 0x0006000500040003, // 6, 5, 4, 3, 0x0003000200010000); // 3, 2, 1, 0 const m512 shift_right = set_i64(12LL, 8LL, 4LL, 0LL, 12LL, 8LL, 4LL, 0LL); m512 r = maskz_loadu_i64(mask_load, arad64); r = permutexvar_i16(idx16, r); r = srlv_i64(r, shift_right); r = and_i64(mask_rad52, r); return r; } IPP_OWN_DEFN(void, convert_radix_to_64x6, (Ipp64u * rrad64, const m512 arad52)) { /* mask store */ const mask8 mask_store = 0x3f; const m512 shift_left = set_i64(4LL, 0LL, 4LL, 0LL, 4LL, 0LL, 4LL, 0LL); const m512 idx_up8 = set_i64( 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3e3d3c3b, // {63,63,63,63,62,61,60,59} 0x3737363534333231, // {55,55,54,53,52,51,50,49} 0x302e2d2c2b2a2928, // {48,46,45,44,43,42,41,40} 0x1f1f1f1f1f1f1e1d, // {31,31,31,31,31,31,30,29} 0x1717171716151413, // {23,23,23,23,22,21,20,19} 0x0f0f0f0e0d0c0b0a, // {15,15,15,14,13,12,11,10} 0x0706050403020100); // { 7, 6, 5, 4, 3, 2, 1, 0} const m512 idx_down8 = set_i64( 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3a39383737373737, // {58,57,56,55,55,55,55,55} 0x2727272727272726, // {39,39,39,39,39,39,39,38} 0x2524232221201f1f, // {37,36,35,34,33,32,31,31} 0x1c1b1a1918171717, // {28,27,26,25,24,23,23,23} 0x1211100f0f0f0f0f, // {18,17,16,15,15,15,15,15} 0x0908070707070707); // { 9, 8, 7, 7, 7, 7, 7, 7} m512 r = arad52; r = sllv_i64(r, shift_left); m512 T = permutexvar_i8(idx_up8, r); r = permutexvar_i8(idx_down8, r); r = or_i64(r, T); mask_storeu_i64(rrad64, mask_store, r); return; } #endif // #if (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_p384.h000066400000000000000000000073111470420105600266360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ARITH_P384R1_H_) #define _IFMA_ARITH_P384R1_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "ifma_alias_avx512.h" #include "gfpec/ecnist/ifma_norm.h" /** * \brief * * Montgomery multiplication * * a * b * r mod n, where r = 2^(6*52) mod n * * Note: final normalization to 2^52 radix is not performed and shall be * handled separately. * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_amm52_p384, (const m512 a, const m512 b)) /** * \brief * * Dual variant of ifma_amm52_p384() function. * * \param[out] r1 * \param[in] a1 first value (in radix 2^52) * \param[in] b1 second value (in radix 2^52) * \param[out] r2 * \param[in] a2 first value (in radix 2^52) * \param[in] b2 second value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_amm52_dual_p384, (m512 * r1, const m512 a1, const m512 b1, m512 *r2, const m512 a2, const m512 b2)) /** * \brief * * A * A * * Note: final normalization to 2^52 radix is not performed and shall be * handled separately. * * \param[in] a value (in radix 2^52) */ __IPPCP_INLINE IPP_OWN_DEFN(m512, ifma_ams52_p384, (const m512 a)) { return ifma_amm52_p384(a, a); } /** * \brief * * Dual variant of ifma_ams52_p384() function. * * \param[out] r1 * \param[in] a1 value (in radix 2^52) * \param[out] r2 * \param[in] a2 value (in radix 2^52) */ __IPPCP_INLINE IPP_OWN_DEFN(void, ifma_ams52_dual_p384, (m512 * r1, const m512 a1, m512 *r2, const m512 a2)) { ifma_amm52_dual_p384(r1, a1, a1, r2, a2, a2); return; } /** * \brief * * A / 2 * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_half52_p384, (const m512 a)) /** * \brief * * Modular inverse modulo p. * * 1/z mod p * * \param[in] z value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_aminv52_p384, (const m512 z)) /** * \brief * * (-A) mod p * * \param[in] a input value */ IPP_OWN_DECL(m512, ifma_neg52_p384, (const m512 a)) /** * \brief * * Conversion to Montgomery domain modulo p. * * a * r mod p, where r = 2^(6*52) mod p * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_tomont52_p384, (const m512 a)) /** * \brief * * Conversion from Montgomery domain modulo p. * * a mod p * * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_frommont52_p384, (const m512 a)) /* ===================================================================================== */ /** * \brief * * Convert to radix 2^52 from radix 2^64. * * \param[in] pa pointer to array of 4 64-bit chunks */ IPP_OWN_DECL(m512, convert_radix_to_52x8, (const Ipp64u *pa)) /** * \brief * * Convert to radix 2^64 from radix 2^52. * * \param[out] pr pointer to array of 4 64-bit chunks * \param[in] a array of 5 64-bit chunks */ IPP_OWN_DECL(void, convert_radix_to_64x6, (Ipp64u * rrad64, const m512 arad52)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ARITH_P384R1_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_p521.c000066400000000000000000001520321470420105600266230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p521.h" #define NORM_LO_MID_ROUND(CARRY, RLO, RHI) \ (CARRY) = m256_srai_i64((RLO), DIGIT_SIZE_52); \ (RLO) = m256_and_i64((RLO), filt_rad52); \ (CARRY) = m256_permutexvar_i8(idx8_shuffle, (CARRY)); \ (RHI) = m256_mask_add_i64((RHI), 0x1, (RHI), (CARRY)); \ (RLO) = m256_mask_add_i64((RLO), 0xE, (RLO), (CARRY)); #define NORM_HI_ROUND(CARRY, RHI) \ (CARRY) = m256_maskz_srai_i64(0x7, (RHI), DIGIT_SIZE_52); \ (CARRY) = m256_maskz_permutexvar_i8(0xFFFF00, idx8_shuffle, (CARRY)); \ (RHI) = m256_add_i64(m256_and_i64((RHI), filt_rad52), (CARRY)); IPP_OWN_DEFN(void, ifma_norm52_p521, (fe521 pr[], const fe521 a)) { const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); fe521 r; FE521_COPY(r, a); const m256i idx8_shuffle = m256_set_i8(23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24); m256i carry; /* shift low carry */ NORM_LO_MID_ROUND(carry, FE521_LO(r), FE521_MID(r)) NORM_LO_MID_ROUND(carry, FE521_LO(r), FE521_MID(r)) NORM_LO_MID_ROUND(carry, FE521_LO(r), FE521_MID(r)) NORM_LO_MID_ROUND(carry, FE521_LO(r), FE521_MID(r)) /* shift mid */ NORM_LO_MID_ROUND(carry, FE521_MID(r), FE521_HI(r)) NORM_LO_MID_ROUND(carry, FE521_MID(r), FE521_HI(r)) NORM_LO_MID_ROUND(carry, FE521_MID(r), FE521_HI(r)) NORM_LO_MID_ROUND(carry, FE521_MID(r), FE521_HI(r)) /* shift hi */ NORM_HI_ROUND(carry, FE521_HI(r)) NORM_HI_ROUND(carry, FE521_HI(r)) FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, ifma_norm52_dual_p521, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) { const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); fe521 r1, r2; FE521_COPY(r1, a1); FE521_COPY(r2, a2); const m256i idx8_shuffle = m256_set_i8(23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24); m256i carry_1; m256i carry_2; /* shift low carry */ NORM_LO_MID_ROUND(carry_1, FE521_LO(r1), FE521_MID(r1)) NORM_LO_MID_ROUND(carry_2, FE521_LO(r2), FE521_MID(r2)) NORM_LO_MID_ROUND(carry_1, FE521_LO(r1), FE521_MID(r1)) NORM_LO_MID_ROUND(carry_2, FE521_LO(r2), FE521_MID(r2)) NORM_LO_MID_ROUND(carry_1, FE521_LO(r1), FE521_MID(r1)) NORM_LO_MID_ROUND(carry_2, FE521_LO(r2), FE521_MID(r2)) NORM_LO_MID_ROUND(carry_1, FE521_LO(r1), FE521_MID(r1)) NORM_LO_MID_ROUND(carry_2, FE521_LO(r2), FE521_MID(r2)) /* shift mid */ NORM_LO_MID_ROUND(carry_1, FE521_MID(r1), FE521_HI(r1)) NORM_LO_MID_ROUND(carry_2, FE521_MID(r2), FE521_HI(r2)) NORM_LO_MID_ROUND(carry_1, FE521_MID(r1), FE521_HI(r1)) NORM_LO_MID_ROUND(carry_2, FE521_MID(r2), FE521_HI(r2)) NORM_LO_MID_ROUND(carry_1, FE521_MID(r1), FE521_HI(r1)) NORM_LO_MID_ROUND(carry_2, FE521_MID(r2), FE521_HI(r2)) NORM_LO_MID_ROUND(carry_1, FE521_MID(r1), FE521_HI(r1)) NORM_LO_MID_ROUND(carry_2, FE521_MID(r2), FE521_HI(r2)) /* shift hi */ NORM_HI_ROUND(carry_1, FE521_HI(r1)) NORM_HI_ROUND(carry_2, FE521_HI(r2)) NORM_HI_ROUND(carry_1, FE521_HI(r1)) NORM_HI_ROUND(carry_2, FE521_HI(r2)) FE521_COPY(*pr1, r1); FE521_COPY(*pr2, r2); return; } #define ROUND_LOW_MID_LNORM(RLO, RHI) \ { \ m256i carry = m256_srai_i64((RLO), DIGIT_SIZE_52); \ carry = m256_permutexvar_i8(idx8_shuffle, carry); \ (RLO) = m256_and_i64((RLO), filt_rad52); \ (RLO) = m256_mask_add_i64((RLO), 0xE, (RLO), carry); \ (RHI) = m256_mask_add_i64((RHI), 0x1, (RHI), carry); \ } #define ROUND_HI_LNORM(R) \ { \ m256i carry = m256_srai_i64((R), DIGIT_SIZE_52); \ carry = m256_permutexvar_i8(idx8_shuffle, carry); \ (R) = m256_and_i64((R), filt_rad52); \ (R) = m256_mask_add_i64((R), 0xE, (R), carry); \ } #define CREATE_MASK_ONE(OUT, R, MASK_CMP) \ { \ const int mk_lo = (int)(m256_cmp_i64_mask(filt_rad52, FE521_LO((R)), (MASK_CMP))); \ const int mk_mid = (int)(m256_cmp_i64_mask(filt_rad52, FE521_MID((R)), (MASK_CMP))); \ const int mk_hi = (int)(m256_cmp_i64_mask(filt_rad52, FE521_HI((R)), (MASK_CMP))); \ \ (OUT) = (mk_lo & 0xF) | ((mk_mid & 0xF) << 4) | ((mk_hi & 0xF) << 8); \ } #define ADD_VALUE_BY_MASK(R, MASK, VAL) \ { \ FE521_LO((R)) = m256_mask_add_i64(FE521_LO((R)), (mask8)((MASK)&0xF), FE521_LO((R)), (VAL)); \ FE521_MID((R)) = m256_mask_add_i64(FE521_MID((R)), (mask8)(((MASK) >> 4) & 0xF), FE521_MID((R)), (VAL)); \ FE521_HI((R)) = m256_mask_add_i64(FE521_HI((R)), (mask8)(((MASK) >> 8) & 0x7), FE521_HI((R)), (VAL)); \ } #define FILT_52(R) \ { \ FE521_LO((R)) = m256_and_i64(FE521_LO((R)), filt_rad52); \ FE521_MID((R)) = m256_and_i64(FE521_MID((R)), filt_rad52); \ FE521_HI((R)) = m256_and_i64(FE521_HI((R)), filt_rad52); \ } IPP_OWN_DEFN(void, ifma_lnorm52_p521, (fe521 pr[], const fe521 a)) { const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); const m256i one = m256_set1_i64(1ULL); const m256i idx8_shuffle = m256_set_i8(23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24); fe521 r; FE521_COPY(r, a); /* standard step - first round normalization */ /* low */ ROUND_LOW_MID_LNORM(FE521_LO(r), FE521_MID(r)) /* mid */ ROUND_LOW_MID_LNORM(FE521_MID(r), FE521_HI(r)) /* hi */ ROUND_HI_LNORM(FE521_HI(r)) /* create mask add ONE(1) to slot */ int k1, k2; /* create k2 (r) == 0xF(13) */ CREATE_MASK_ONE(k2, r, _MM_CMPINT_EQ) /* create k1 (r) > 0xF(13) */ CREATE_MASK_ONE(k1, r, _MM_CMPINT_LT) k1 = k2 + (k1 << 1); k1 ^= k2; ADD_VALUE_BY_MASK(r, k1, one) FILT_52(r) FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, ifma_lnorm52_dual_p521, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) { const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); const m256i one = m256_set1_i64(1ULL); const m256i idx8_shuffle = m256_set_i8(23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31, 30, 29, 28, 27, 26, 25, 24); fe521 r1, r2; FE521_COPY(r1, a1); FE521_COPY(r2, a2); /* standard step - first round normalization */ /* low */ ROUND_LOW_MID_LNORM(FE521_LO(r1), FE521_MID(r1)) ROUND_LOW_MID_LNORM(FE521_LO(r2), FE521_MID(r2)) /* mid */ ROUND_LOW_MID_LNORM(FE521_MID(r1), FE521_HI(r1)) ROUND_LOW_MID_LNORM(FE521_MID(r2), FE521_HI(r2)) /* hi */ ROUND_HI_LNORM(FE521_HI(r1)) ROUND_HI_LNORM(FE521_HI(r2)) /* create mask add ONE(1) to slot */ int k11, k21; int k12, k22; /* create k2 (r) == 0xF(13) */ CREATE_MASK_ONE(k21, r1, _MM_CMPINT_EQ) CREATE_MASK_ONE(k22, r2, _MM_CMPINT_EQ) /* create k1 (r) > 0xF(13) */ CREATE_MASK_ONE(k11, r1, _MM_CMPINT_LT) CREATE_MASK_ONE(k12, r2, _MM_CMPINT_LT) k11 = k21 + (k11 << 1); k11 ^= k21; k12 = k22 + (k12 << 1); k12 ^= k22; ADD_VALUE_BY_MASK(r1, k11, one) ADD_VALUE_BY_MASK(r2, k12, one) FILT_52(r1) FILT_52(r2) FE521_COPY(*pr1, r1); FE521_COPY(*pr2, r2); return; } #define group_madd52hi_i64(R, A, B, C) \ FE521_LO(R) = m256_madd52hi_i64(FE521_LO(A), FE521_LO(B), (C)); \ FE521_MID(R) = m256_madd52hi_i64(FE521_MID(A), FE521_MID(B), (C)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(A), FE521_HI(B), (C)) #define group_madd52lo_i64(R, A, B, C) \ FE521_LO(R) = m256_madd52lo_i64(FE521_LO(A), FE521_LO(B), (C)); \ FE521_MID(R) = m256_madd52lo_i64(FE521_MID(A), FE521_MID(B), (C)); \ FE521_HI(R) = m256_madd52lo_i64(FE521_HI(A), FE521_HI(B), (C)) #define MUL_ROUND(R, A, BI, BJ) \ FE521_SET((R)) = m256_setzero_i64(); \ group_madd52hi_i64((R), (R), (A), (BI)); \ group_madd52lo_i64((R), (R), (A), (BJ)); #define REDUCTION(R, U, REDUCT) \ (U) = m256_permutexvar_i8(idx0, FE521_LO(R)); \ /* shift */ \ FE521_LO(R) = m256_alignr_i64(FE521_MID(R), FE521_LO(R), 1); \ FE521_MID(R) = m256_alignr_i64(FE521_HI(R), FE521_MID(R), 1); \ FE521_HI(R) = m256_maskz_permutexvar_i8(mask_sr64, idx_sr64, FE521_HI(R)); \ /* carry chunk 1 */ \ FE521_LO(REDUCT) = m256_maskz_srai_i64(0x1, (U), DIGIT_SIZE_52); \ /* carry chunk 2 */ \ (U) = m256_and_i64((U), filt_rad52); \ FE521_HI(REDUCT) = m256_maskz_add_i64(0x2, (U), (U)); \ FE521_LO(R) = m256_add_i64(FE521_LO(R), FE521_LO(REDUCT)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(REDUCT)); IPP_OWN_DEFN(void, ifma_amm52_p521, (fe521 pr[], const fe521 a, const fe521 b)) { const Ipp64s *pb_lo = (const Ipp64s *)(&(FE521_LO(b))); const Ipp64s *pb_mid = (const Ipp64s *)(&(FE521_MID(b))); const Ipp64s *pb_hi = (const Ipp64s *)(&(FE521_HI(b))); const m256i b0 = m256_set1_i64(pb_lo[0]); const m256i b1 = m256_set1_i64(pb_lo[1]); const m256i b2 = m256_set1_i64(pb_lo[2]); const m256i b3 = m256_set1_i64(pb_lo[3]); const m256i b4 = m256_set1_i64(pb_mid[0]); const m256i b5 = m256_set1_i64(pb_mid[1]); const m256i b6 = m256_set1_i64(pb_mid[2]); const m256i b7 = m256_set1_i64(pb_mid[3]); const m256i b8 = m256_set1_i64(pb_hi[0]); const m256i b9 = m256_set1_i64(pb_hi[1]); const m256i b10 = m256_set1_i64(pb_hi[2]); fe521 r0; fe521 p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10; /* first */ FE521_SET(r0) = m256_setzero_i64(); group_madd52lo_i64(r0, r0, a, b0); /* last */ FE521_SET(p10) = m256_setzero_i64(); group_madd52hi_i64(p10, p10, a, b10); /* round mul */ MUL_ROUND(p0, a, b0, b1) MUL_ROUND(p1, a, b1, b2) MUL_ROUND(p2, a, b2, b3) MUL_ROUND(p3, a, b3, b4) MUL_ROUND(p4, a, b4, b5) MUL_ROUND(p5, a, b5, b6) MUL_ROUND(p6, a, b6, b7) MUL_ROUND(p7, a, b7, b8) MUL_ROUND(p8, a, b8, b9) MUL_ROUND(p9, a, b9, b10) const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); const m256i idx0 = m256_set_i8(REPL4(7, 6, 5, 4, 3, 2, 1, 0)); /* B[ 0] -> chunk1[0] */ /* chunk2 shift bit >> 64 */ const mask32 mask_sr64 = 0x00FFFFFF; const m256i idx_sr64 = m256_set_i8(0, 0, 0, 0, 0, 0, 0, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8); fe521 reduct; FE521_SET(reduct) = m256_setzero_i64(); m256i u; REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p0); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p1); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p2); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p3); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p4); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p5); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p6); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p7); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p8); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p9); REDUCTION(r0, u, reduct) fe521_add_no_red(r0, r0, p10); FE521_COPY(*pr, r0); return; } #define MUL_LO_ROUND(R, A, \ AI, MMI, MAI, \ AJ, MMJ, MAJ) \ { \ fe521 tmp; \ FE521_SET(R) = FE521_SET(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_LO(R) = m256_maskz_madd52hi_i64((MMI), FE521_LO(R), FE521_LO(A), (AI)); \ FE521_MID(R) = m256_madd52hi_i64(FE521_MID(R), FE521_MID(A), (AI)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_LO(tmp) = m256_maskz_madd52lo_i64((MMJ), FE521_LO(tmp), FE521_LO(A), (AJ)); \ FE521_MID(tmp) = m256_madd52lo_i64(FE521_MID(tmp), FE521_MID(A), (AJ)); \ FE521_HI(tmp) = m256_madd52lo_i64(FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_LO(R) = m256_mask_add_i64(FE521_LO(R), (MAI), FE521_LO(R), FE521_LO(R)); \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(R)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_LO(tmp) = m256_mask_add_i64(FE521_LO(tmp), (MAJ), FE521_LO(tmp), FE521_LO(tmp)); \ FE521_MID(tmp) = m256_add_i64(FE521_MID(tmp), FE521_MID(tmp)); \ FE521_HI(tmp) = m256_add_i64(FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_LO(R) = m256_add_i64(FE521_LO(R), FE521_LO(tmp)); \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(tmp)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define MUL_LO_LAST_ROUND(R, A, \ AI, MMI, MAI, \ AJ, MMJ) \ { \ fe521 tmp; \ FE521_SET(R) = FE521_SET(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_LO(R) = m256_maskz_madd52hi_i64((MMI), FE521_LO(R), FE521_LO(A), (AI)); \ FE521_MID(R) = m256_madd52hi_i64(FE521_MID(R), FE521_MID(A), (AI)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_LO(tmp) = m256_maskz_madd52lo_i64((MMJ), FE521_LO(tmp), FE521_LO(A), (AJ)); \ FE521_MID(tmp) = m256_madd52lo_i64(FE521_MID(tmp), FE521_MID(A), (AJ)); \ FE521_HI(tmp) = m256_madd52lo_i64(FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_LO(R) = m256_mask_add_i64(FE521_LO(R), (MAI), FE521_LO(R), FE521_LO(R)); \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(R)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_MID(tmp) = m256_add_i64(FE521_MID(tmp), FE521_MID(tmp)); \ FE521_HI(tmp) = m256_add_i64(FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_LO(R) = m256_add_i64(FE521_LO(R), FE521_LO(tmp)); \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(tmp)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define MUL_MID_FIRST_ROUND(R, A, \ AI, MMI, \ AJ, MAJ) \ { \ fe521 tmp; \ FE521_SET(R) = FE521_MID(tmp) = FE521_HI(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_LO(R) = m256_maskz_madd52hi_i64((MMI), FE521_LO(R), FE521_LO(A), (AI)); \ FE521_MID(R) = m256_madd52hi_i64(FE521_MID(R), FE521_MID(A), (AI)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_MID(tmp) = m256_madd52lo_i64(FE521_MID(tmp), FE521_MID(A), (AJ)); \ FE521_HI(tmp) = m256_madd52lo_i64(FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(R)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_MID(tmp) = m256_mask_add_i64(FE521_MID(tmp), (MAJ), FE521_MID(tmp), FE521_MID(tmp)); \ FE521_HI(tmp) = m256_add_i64(FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(tmp)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define MUL_MID_ROUND(R, A, \ AI, MMI, MAI, \ AJ, MMJ, MAJ) \ { \ fe521 tmp; \ FE521_MID(R) = FE521_HI(R) = FE521_MID(tmp) = FE521_HI(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_MID(R) = m256_maskz_madd52hi_i64((MMI), FE521_MID(R), FE521_MID(A), (AI)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_MID(tmp) = m256_maskz_madd52lo_i64((MMJ), FE521_MID(tmp), FE521_MID(A), (AJ)); \ FE521_HI(tmp) = m256_madd52lo_i64(FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_MID(R) = m256_mask_add_i64(FE521_MID(R), (MAI), FE521_MID(R), FE521_MID(R)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_MID(tmp) = m256_mask_add_i64(FE521_MID(tmp), (MAJ), FE521_MID(tmp), FE521_MID(tmp)); \ FE521_HI(tmp) = m256_add_i64(FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(tmp)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define MUL_MID_LAST_ROUND(R, A, \ AI, MMI, MAI, \ AJ, MMJ) \ { \ fe521 tmp; \ FE521_MID(R) = FE521_HI(R) = FE521_MID(tmp) = FE521_HI(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_MID(R) = m256_maskz_madd52hi_i64((MMI), FE521_MID(R), FE521_MID(A), (AI)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_MID(tmp) = m256_maskz_madd52lo_i64((MMJ), FE521_MID(tmp), FE521_MID(A), (AJ)); \ FE521_HI(tmp) = m256_madd52lo_i64(FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_MID(R) = m256_mask_add_i64(FE521_MID(R), (MAI), FE521_MID(R), FE521_MID(R)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_HI(tmp) = m256_add_i64(FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_MID(R) = m256_add_i64(FE521_MID(R), FE521_MID(tmp)); \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define MUL_HI_FIRST_ROUND(R, A, \ AI, MMI, \ AJ, MAJ) \ { \ fe521 tmp; \ FE521_MID(R) = FE521_HI(R) = FE521_HI(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_MID(R) = m256_maskz_madd52hi_i64((MMI), FE521_MID(R), FE521_MID(A), (AI)); \ FE521_HI(R) = m256_madd52hi_i64(FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_HI(tmp) = m256_madd52lo_i64(FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_HI(tmp) = m256_mask_add_i64(FE521_HI(tmp), (MAJ), FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define MUL_HI_ROUND(R, A, \ AI, MMI, MAI, \ AJ, MMJ, MAJ) \ { \ fe521 tmp; \ FE521_HI(R) = FE521_HI(tmp) = m256_setzero_i64(); \ /* high */ \ FE521_HI(R) = m256_maskz_madd52hi_i64((MMI), FE521_HI(R), FE521_HI(A), (AI)); \ /* lo */ \ FE521_HI(tmp) = m256_maskz_madd52lo_i64((MMJ), FE521_HI(tmp), FE521_HI(A), (AJ)); \ /* double hi */ \ FE521_HI(R) = m256_mask_add_i64(FE521_HI(R), (MAI), FE521_HI(R), FE521_HI(R)); \ /* double lo */ \ FE521_HI(tmp) = m256_mask_add_i64(FE521_HI(tmp), (MAJ), FE521_HI(tmp), FE521_HI(tmp)); \ /* add lo + hi */ \ FE521_HI(R) = m256_add_i64(FE521_HI(R), FE521_HI(tmp)); \ } #define ADD_LO(R, A, B) \ FE521_LO(R) = m256_add_i64(FE521_LO(A), FE521_LO(B)); \ FE521_MID(R) = m256_add_i64(FE521_MID(A), FE521_MID(B)); \ FE521_HI(R) = m256_add_i64(FE521_HI(A), FE521_HI(B)); #define ADD_MID(R, A, B) \ FE521_MID(R) = m256_add_i64(FE521_MID(A), FE521_MID(B)); \ FE521_HI(R) = m256_add_i64(FE521_HI(A), FE521_HI(B)); #define ADD_HI(R, A, B) \ FE521_HI(R) = m256_add_i64(FE521_HI(A), FE521_HI(B)); IPP_OWN_DEFN(void, ifma_ams52_p521, (fe521 pr[], const fe521 a)) { const Ipp64s *pa_lo = (const Ipp64s *)(&(FE521_LO(a))); const Ipp64s *pa_mid = (const Ipp64s *)(&(FE521_MID(a))); const Ipp64s *pa_hi = (const Ipp64s *)(&(FE521_HI(a))); const m256i a0 = m256_set1_i64(pa_lo[0]); const m256i a1 = m256_set1_i64(pa_lo[1]); const m256i a2 = m256_set1_i64(pa_lo[2]); const m256i a3 = m256_set1_i64(pa_lo[3]); const m256i a4 = m256_set1_i64(pa_mid[0]); const m256i a5 = m256_set1_i64(pa_mid[1]); const m256i a6 = m256_set1_i64(pa_mid[2]); const m256i a7 = m256_set1_i64(pa_mid[3]); const m256i a8 = m256_set1_i64(pa_hi[0]); const m256i a9 = m256_set1_i64(pa_hi[1]); const m256i a10 = m256_set1_i64(pa_hi[2]); fe521 r0, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9; /* start round */ /* r0 = r0 + a*a[0](lo) */ FE521_SET(r0) = m256_setzero_i64(); FE521_LO(r0) = m256_madd52lo_i64(FE521_LO(r0), FE521_LO(a), a0); FE521_MID(r0) = m256_madd52lo_i64(FE521_MID(r0), FE521_MID(a), a0); FE521_HI(r0) = m256_madd52lo_i64(FE521_HI(r0), FE521_HI(a), a0); /* r0 = r0 + r0 (no update r0[0]) */ FE521_LO(r0) = m256_mask_add_i64(FE521_LO(r0), 0xE, FE521_LO(r0), FE521_LO(r0)); FE521_MID(r0) = m256_add_i64(FE521_MID(r0), FE521_MID(r0)); FE521_HI(r0) = m256_add_i64(FE521_HI(r0), FE521_HI(r0)); /* * 1111 = 0xF * 1110 = 0xE * 1100 = 0xC * 1000 = 0x8 * 0000 = 0x0 */ /* lower */ /* p0 = p0 + a*a[0](hi) + a*a[1](lo) */ MUL_LO_ROUND(/* R = */ p0, /* A = */ a, /* AI = */ a0, /* MMI = */ 0xF, /* MAI = */ 0xE, /* AJ = */ a1, /* MMJ = */ 0xE, /* MAJ = */ 0xC) /* p1 = p1 + a*a[1](hi) + a*a[2](lo) */ MUL_LO_ROUND(/* R = */ p1, /* A = */ a, /* AI = */ a1, /* MMI = */ 0xE, /* MAI = */ 0xC, /* AJ = */ a2, /* MMJ = */ 0xC, /* MAJ = */ 0x8) /* p2 = p2 + a*a[2](hi) + a*a[3](lo) */ MUL_LO_LAST_ROUND(/* R = */ p2, /* A = */ a, /* AI = */ a2, /* MMI = */ 0xC, /* MAI = */ 0x8, /* AJ = */ a3, /* MMJ = */ 0x8) /* mid */ /* p3 = p3 + a*a[3](hi) + a*a[4](lo) */ MUL_MID_FIRST_ROUND(/* R = */ p3, /* A = */ a, /* AI = */ a3, /* MMI = */ 0x8, /* AJ = */ a4, /* MAJ = */ 0xE) /* p4 = p4 + a*a[4](hi) + a*a[5](lo) */ MUL_MID_ROUND(/* R = */ p4, /* A = */ a, /* AI = */ a4, /* MMI = */ 0xF, /* MAI = */ 0xE, /* AJ = */ a5, /* MMJ = */ 0xE, /* MAJ = */ 0xC) /* p5 = p5 + a*a[5](hi) + a*a[6](lo) */ MUL_MID_ROUND(/* R = */ p5, /* A = */ a, /* AI = */ a5, /* MMI = */ 0xE, /* MAI = */ 0xC, /* AJ = */ a6, /* MMJ = */ 0xC, /* MAJ = */ 0x8) /* p6 = p6 + a*a[6](hi) + a*a[7](lo) */ MUL_MID_LAST_ROUND(/* R = */ p6, /* A = */ a, /* AI = */ a6, /* MMI = */ 0xC, /* MAI = */ 0x8, /* AJ = */ a7, /* MMJ = */ 0x8) /* high */ /* p7 = p7 + a*a[7](hi) + a*a[8](lo) */ MUL_HI_FIRST_ROUND(/* R = */ p7, /* A = */ a, /* AI = */ a7, /* MMI = */ 0x8, /* AJ = */ a8, /* MAJ = */ 0xE) /* p8 = p8 + a*a[8](hi) + a*a[9](lo) */ MUL_HI_ROUND(/* R = */ p8, /* A = */ a, /* AI = */ a8, /* MMI = */ 0xF, /* MAI = */ 0xE, /* AJ = */ a9, /* MMJ = */ 0xE, /* MAJ = */ 0xC) /* p9 = p9 + a*a[9](hi) + a*a[10](lo) */ MUL_HI_ROUND(/* R = */ p9, /* A = */ a, /* AI = */ a9, /* MMI = */ 0xE, /* MAI = */ 0xC, /* AJ = */ a10, /* MMJ = */ 0xC, /* MAJ = */ 0x8) fe521 reduct; FE521_SET(reduct) = m256_setzero_i64(); m256i u; const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); const m256i idx0 = m256_set_i8(REPL4(7, 6, 5, 4, 3, 2, 1, 0)); /* B[ 0] -> chunk1[0] */ /* chunk2 shift bit >> 64 */ const mask32 mask_sr64 = 0x00FFFFFF; const m256i idx_sr64 = m256_set_i8(0, 0, 0, 0, 0, 0, 0, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8); REDUCTION(r0, u, reduct) ADD_LO(r0, r0, p0); REDUCTION(r0, u, reduct) ADD_LO(r0, r0, p1); REDUCTION(r0, u, reduct) ADD_LO(r0, r0, p2); REDUCTION(r0, u, reduct) ADD_LO(r0, r0, p3); REDUCTION(r0, u, reduct) ADD_MID(r0, r0, p4); REDUCTION(r0, u, reduct) ADD_MID(r0, r0, p5); REDUCTION(r0, u, reduct) ADD_MID(r0, r0, p6); REDUCTION(r0, u, reduct) ADD_MID(r0, r0, p7); REDUCTION(r0, u, reduct) ADD_HI(r0, r0, p8); REDUCTION(r0, u, reduct) ADD_HI(r0, r0, p9); REDUCTION(r0, u, reduct) FE521_COPY(*pr, r0); return; } IPP_OWN_DEFN(void, ifma_ams52_dual_p521, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) { ifma_amm52_dual_p521(pr1, a1, a1, pr2, a2, a2); } IPP_OWN_DEFN(void, ifma_amm52_dual_p521, (fe521 pr1[], const fe521 a1, const fe521 b1, fe521 pr2[], const fe521 a2, const fe521 b2)) { const Ipp64s *pb_lo_1 = (const Ipp64s *)(&(FE521_LO(b1))); const Ipp64s *pb_mid_1 = (const Ipp64s *)(&(FE521_MID(b1))); const Ipp64s *pb_hi_1 = (const Ipp64s *)(&(FE521_HI(b1))); const Ipp64s *pb_lo_2 = (const Ipp64s *)(&(FE521_LO(b2))); const Ipp64s *pb_mid_2 = (const Ipp64s *)(&(FE521_MID(b2))); const Ipp64s *pb_hi_2 = (const Ipp64s *)(&(FE521_HI(b2))); const m256i b0_1 = m256_set1_i64(pb_lo_1[0]); const m256i b1_1 = m256_set1_i64(pb_lo_1[1]); const m256i b2_1 = m256_set1_i64(pb_lo_1[2]); const m256i b3_1 = m256_set1_i64(pb_lo_1[3]); const m256i b4_1 = m256_set1_i64(pb_mid_1[0]); const m256i b5_1 = m256_set1_i64(pb_mid_1[1]); const m256i b6_1 = m256_set1_i64(pb_mid_1[2]); const m256i b7_1 = m256_set1_i64(pb_mid_1[3]); const m256i b8_1 = m256_set1_i64(pb_hi_1[0]); const m256i b9_1 = m256_set1_i64(pb_hi_1[1]); const m256i b10_1 = m256_set1_i64(pb_hi_1[2]); const m256i b0_2 = m256_set1_i64(pb_lo_2[0]); const m256i b1_2 = m256_set1_i64(pb_lo_2[1]); const m256i b2_2 = m256_set1_i64(pb_lo_2[2]); const m256i b3_2 = m256_set1_i64(pb_lo_2[3]); const m256i b4_2 = m256_set1_i64(pb_mid_2[0]); const m256i b5_2 = m256_set1_i64(pb_mid_2[1]); const m256i b6_2 = m256_set1_i64(pb_mid_2[2]); const m256i b7_2 = m256_set1_i64(pb_mid_2[3]); const m256i b8_2 = m256_set1_i64(pb_hi_2[0]); const m256i b9_2 = m256_set1_i64(pb_hi_2[1]); const m256i b10_2 = m256_set1_i64(pb_hi_2[2]); fe521 r0_1; fe521 p0_1, p1_1, p2_1, p3_1, p4_1, p5_1, p6_1, p7_1, p8_1, p9_1, p10_1; fe521 r0_2; fe521 p0_2, p1_2, p2_2, p3_2, p4_2, p5_2, p6_2, p7_2, p8_2, p9_2, p10_2; /* first */ FE521_SET(r0_1) = m256_setzero_i64(); group_madd52lo_i64(r0_1, r0_1, a1, b0_1); FE521_SET(r0_2) = m256_setzero_i64(); group_madd52lo_i64(r0_2, r0_2, a2, b0_2); /* last */ FE521_SET(p10_1) = m256_setzero_i64(); group_madd52hi_i64(p10_1, p10_1, a1, b10_1); FE521_SET(p10_2) = m256_setzero_i64(); group_madd52hi_i64(p10_2, p10_2, a2, b10_2); /* round mul */ MUL_ROUND(p0_1, a1, b0_1, b1_1) MUL_ROUND(p0_2, a2, b0_2, b1_2) MUL_ROUND(p1_1, a1, b1_1, b2_1) MUL_ROUND(p1_2, a2, b1_2, b2_2) MUL_ROUND(p2_1, a1, b2_1, b3_1) MUL_ROUND(p2_2, a2, b2_2, b3_2) MUL_ROUND(p3_1, a1, b3_1, b4_1) MUL_ROUND(p3_2, a2, b3_2, b4_2) MUL_ROUND(p4_1, a1, b4_1, b5_1) MUL_ROUND(p4_2, a2, b4_2, b5_2) MUL_ROUND(p5_1, a1, b5_1, b6_1) MUL_ROUND(p5_2, a2, b5_2, b6_2) MUL_ROUND(p6_1, a1, b6_1, b7_1) MUL_ROUND(p6_2, a2, b6_2, b7_2) MUL_ROUND(p7_1, a1, b7_1, b8_1) MUL_ROUND(p7_2, a2, b7_2, b8_2) MUL_ROUND(p8_1, a1, b8_1, b9_1) MUL_ROUND(p8_2, a2, b8_2, b9_2) MUL_ROUND(p9_1, a1, b9_1, b10_1) MUL_ROUND(p9_2, a2, b9_2, b10_2) const m256i filt_rad52 = m256_set1_i64(DIGIT_MASK_52); const m256i idx0 = m256_set_i8(REPL4(7, 6, 5, 4, 3, 2, 1, 0)); /* B[ 0] -> chunk1[0] */ /* chunk2 shift bit >> 64 */ const mask32 mask_sr64 = 0x00FFFFFF; const m256i idx_sr64 = m256_set_i8(0, 0, 0, 0, 0, 0, 0, 0, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8); fe521 reduct_1; FE521_SET(reduct_1) = m256_setzero_i64(); m256i u_1; fe521 reduct_2; FE521_SET(reduct_2) = m256_setzero_i64(); m256i u_2; REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p0_1); fe521_add_no_red(r0_2, r0_2, p0_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p1_1); fe521_add_no_red(r0_2, r0_2, p1_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p2_1); fe521_add_no_red(r0_2, r0_2, p2_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p3_1); fe521_add_no_red(r0_2, r0_2, p3_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p4_1); fe521_add_no_red(r0_2, r0_2, p4_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p5_1); fe521_add_no_red(r0_2, r0_2, p5_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p6_1); fe521_add_no_red(r0_2, r0_2, p6_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p7_1); fe521_add_no_red(r0_2, r0_2, p7_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p8_1); fe521_add_no_red(r0_2, r0_2, p8_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p9_1); fe521_add_no_red(r0_2, r0_2, p9_2); REDUCTION(r0_1, u_1, reduct_1) REDUCTION(r0_2, u_2, reduct_2) fe521_add_no_red(r0_1, r0_1, p10_1); fe521_add_no_red(r0_2, r0_2, p10_2); FE521_COPY(*pr1, r0_1); FE521_COPY(*pr2, r0_2); return; } #undef group_madd52hi_i64 #undef group_madd52lo_i64 IPP_OWN_DEFN(void, ifma_half52_p521, (fe521 pr[], const fe521 a)) { fe521 M; FE521_LOADU(M, p521_x1); const m256i zero = m256_setzero_i64(); const m256i one = m256_set1_i64(1LL); const mask8 mask_last_bit_one_line = m256_cmp_i64_mask(m256_and_i64(FE521_LO(a), one), zero, _MM_CMPINT_EQ); const mask8 mask_is_lb_one = (mask8)((mask_last_bit_one_line & 1) - 1); fe521 r; FE521_LO(r) = _mm256_mask_add_epi64(FE521_LO(a), mask_is_lb_one, FE521_LO(a), FE521_LO(M)); FE521_MID(r) = _mm256_mask_add_epi64(FE521_MID(a), mask_is_lb_one, FE521_MID(a), FE521_MID(M)); FE521_HI(r) = _mm256_mask_add_epi64(FE521_HI(a), mask_is_lb_one, FE521_HI(a), FE521_HI(M)); ifma_lnorm52_p521(&r, r); /* 1-bit shift right */ /* chunk2 shift bit >> 64 */ const mask32 mask_sr64 = 0xFFFF; const m256i idx_sr64 = m256_set_i8(24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8); fe521 shift_right; /* shift right */ FE521_LO(shift_right) = m256_alignr_i64(FE521_MID(r), FE521_LO(r), 1); FE521_MID(shift_right) = m256_alignr_i64(FE521_HI(r), FE521_MID(r), 1); FE521_HI(shift_right) = m256_maskz_permutexvar_i8(mask_sr64, idx_sr64, FE521_HI(r)); /* extract las bit */ FE521_LO(shift_right) = m256_and_i64(FE521_LO(shift_right), one); FE521_MID(shift_right) = m256_and_i64(FE521_MID(shift_right), one); FE521_HI(shift_right) = m256_and_i64(FE521_HI(shift_right), one); /* set last bit is first byte (52 radix) */ FE521_LO(shift_right) = m256_slli_i64(FE521_LO(shift_right), DIGIT_SIZE_52 - 1); FE521_MID(shift_right) = m256_slli_i64(FE521_MID(shift_right), DIGIT_SIZE_52 - 1); FE521_HI(shift_right) = m256_maskz_slli_i64(0x3, FE521_HI(shift_right), DIGIT_SIZE_52 - 1); /* join first new bite */ FE521_LO(r) = m256_srli_i64(FE521_LO(r), 1); FE521_MID(r) = m256_srli_i64(FE521_MID(r), 1); FE521_HI(r) = m256_maskz_srli_i64(0x7, FE521_HI(r), 1); /* join first and other bit */ FE521_LO(r) = m256_add_i64(FE521_LO(r), FE521_LO(shift_right)); FE521_MID(r) = m256_add_i64(FE521_MID(r), FE521_MID(shift_right)); FE521_HI(r) = m256_add_i64(FE521_HI(r), FE521_HI(shift_right)); FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, ifma_neg52_p521, (fe521 pr[], const fe521 a)) { fe521 M4; FE521_LOADU(M4, p521_x4); const mask8 mask_is_not_zero = (mask8)(~(FE521_IS_ZERO(a))); fe521 r; FE521_LO(r) = m256_mask_sub_i64(FE521_LO(a), mask_is_not_zero, FE521_LO(M4), FE521_LO(a)); FE521_MID(r) = m256_mask_sub_i64(FE521_MID(a), mask_is_not_zero, FE521_MID(M4), FE521_MID(a)); FE521_HI(r) = m256_mask_sub_i64(FE521_HI(a), mask_is_not_zero, FE521_HI(M4), FE521_HI(a)); ifma_norm52_p521(&r, r); FE521_COPY(*pr, r); return; } /* to Montgomery conversion constant * rr = 2^((P521_LEN52*DIGIT_SIZE)*2) mod p521 */ static const __ALIGN64 Ipp64u P521R1_RR52[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x0000000000000000, 0x0004000000000000, 0x0000000000000000, 0x0000000000000000 }, { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 } }; IPP_OWN_DEFN(void, ifma_tomont52_p521, (fe521 pr[], const fe521 a)) { fe521 RR; FE521_LOADU(RR, P521R1_RR52); ifma_amm52_p521(pr, a, RR); ifma_lnorm52_p521(pr, *pr); return; } static IPP_OWN_DEFN(void, ifma_fastred52_p521, (fe521 pr[], const fe521 a)) { fe521 M; FE521_LOADU(M, p521_x1); const m256i zero = m256_setzero_i64(); fe521 r; fe521_sub_no_red(r, a, M); ifma_norm52_p521(&r, r); const mask8 lt = m256_cmp_i64_mask(zero, m256_srli_i64(FE521_HI(r), DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 2) & 1)); /* mask != 0 ? a : r */ FE521_MASK_MOV(r, r, mask, a); FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, ifma_frommont52_p521, (fe521 pr[], const fe521 a)) { fe521 ONE; FE521_LOADU(ONE, P521R1_ONE52); ifma_amm52_p521(pr, a, ONE); ifma_lnorm52_p521(pr, *pr); ifma_fastred52_p521(pr, *pr); return; } __IPPCP_INLINE IPP_OWN_DEFN(void, ifma_amm52_p521_norm, (fe521 pr[], const fe521 a, const fe521 b)) { ifma_amm52_p521(pr, a, b); ifma_lnorm52_p521(pr, *pr); return; } __IPPCP_INLINE IPP_OWN_DEFN(void, ifma_ams52_p521_norm, (fe521 pr[], const fe521 a)) { ifma_ams52_p521(pr, a); ifma_lnorm52_p521(pr, *pr); return; } #define mul(R, A, B) ifma_amm52_p521_norm(&(R), (A), (B)) #define sqr(R, A) ifma_ams52_p521_norm(&(R), (A)) #define mul_dual(R1, A1, B1, R2, A2, B2) \ ifma_amm52_dual_p521(&(R1), (A1), (B1), &(R2), (A2), (B2)); \ ifma_lnorm52_dual_p521(&(R1), (R1), &(R2), (R2)) /* r = base^(2^n) */ __IPPCP_INLINE IPP_OWN_DEFN(void, ifma_ams52_p521_ntimes, (fe521 pr[], const fe521 a, int n)) { fe521 r; FE521_COPY(r, a); for (; n > 0; --n) sqr(r, r); FE521_COPY(*pr, r); return; } #define sqr_ntimes(R, A, N) ifma_ams52_p521_ntimes(&(R), (A), (N)) IPP_OWN_DEFN(void, ifma_aminv52_p521, (fe521 pr[], const fe521 z)) { fe521 u, v, zD, zF, z1FF; FE521_SET(u) = FE521_SET(v) = FE521_SET(zD) = FE521_SET(zF) = FE521_SET(z1FF) = m256_setzero_i64(); sqr(u, z); /* u = z^2 */ mul(v, u, z); /* v = z^2 * z = z^3 */ sqr_ntimes(zF, v, 2); /* zF= (z^3)^(2^2) = z^12 */ /**/ mul_dual(zD, zF, z, /* zD = z^12 * z = z^xD */ zF, zF, v); /* zF = z^12 * z^3 = z^xF */ /**/ sqr_ntimes(u, zF, 4); /* u = (z^xF)^(2^4) = z^xF0 */ mul_dual(zD, u, zD, /* zD = z^xF0 * z^xD = z^xFD */ zF, u, zF); /* zF = z^xF0 * z^xF = z^xFF */ /**/ sqr(z1FF, zF); /* z1FF= (zF^2) = z^x1FE */ mul(z1FF, z1FF, z); /* z1FF *= z = z^x1FF */ /**/ sqr_ntimes(u, zF, 8); /* u = (z^xFF)^(2^8) = z^xFF00 */ mul_dual(zD, u, zD, /* zD = z^xFF00 * z^xFD = z^xFFFD */ zF, u, zF); /* zF = z^xFF00 * z^xFF = z^xFFFF */ /**/ sqr_ntimes(u, zF, 16); /* u = (z^xFFFF)^(2^16) = z^xFFFF0000 */ mul_dual(zD, u, zD, /* zD = z^xFFFF0000 * z^xFFFD = z^xFFFFFFFD */ zF, u, zF); /* zF = z^xFFFF0000 * z^xFFFF = z^xFFFFFFFF */ /**/ sqr_ntimes(u, zF, 32); /* u = (z^xFFFFFFFF)^(2^32) = z^xFFFFFFFF00000000 */ mul_dual(zD, u, zD, /* zD = z^xFFFFFFFF00000000 * z^xFFFFFFFD = z^xFFFFFFFFFFFFFFFD */ zF, u, zF); /* zF = z^xFFFFFFFF00000000 * z^xFFFFFFFF = z^xFFFFFFFFFFFFFFFF */ /* v = z^x1FF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, z1FF, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFF = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF */ sqr_ntimes(v, v, 64); mul(v, v, zF); /* v = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.0000000000000000 * z^xFFFFFFFFFFFFFFFD = z^x1FF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFE.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFF.FFFFFFFFFFFFFFFD */ sqr_ntimes(v, v, 64); mul(*pr, v, zD); return; } #define ROUND_CONV_64_TO_52(R, A, MASK_LOAD, MASK_RAD52, IDX16) \ (R) = m256_maskz_loadu_i64((MASK_LOAD), (A)); \ (R) = m256_permutexvar_i16((IDX16), (R)); \ (R) = m256_srlv_i64((R), shift_right); \ (R) = m256_and_i64((MASK_RAD52), (R)); IPP_OWN_DEFN(void, convert_radix_to_52_p521, (fe521 pr[], const Ipp64u arad64[P521R1_LEN64])) { /* chunk 1 */ const m256i idx16c1 = m256_set_i16(12, 11, 10, 9, 9, 8, 7, 6, 6, 5, 4, 3, 3, 2, 1, 0); const m256i idx16c2 = m256_set_i16(13, 12, 11, 10, 10, 9, 8, 7, 7, 6, 5, 4, 4, 3, 2, 1); const m256i idx16c3 = m256_set_i16(12, 12, 12, 12, 12, 12, 12, 8, 8, 7, 6, 5, 5, 4, 3, 2); const m256i shift_right = m256_set_i64(12LL, 8LL, 4LL, 0LL); const m256i mask_rad52c12 = m256_set1_i64(DIGIT_MASK_52); const m256i mask_rad52c3 = m256_set_i64(0x0, 0x1, DIGIT_MASK_52, DIGIT_MASK_52); fe521 r; FE521_SET(r) = m256_setzero_i64(); /* chunk 1 */ ROUND_CONV_64_TO_52(FE521_LO(r), arad64, 0xF, mask_rad52c12, idx16c1) /* chunk 2 */ ROUND_CONV_64_TO_52(FE521_MID(r), arad64 + 3, 0xF, mask_rad52c12, idx16c2) /* chunk 2 */ ROUND_CONV_64_TO_52(FE521_HI(r), arad64 + 6, 0x7, mask_rad52c3, idx16c3) FE521_COPY(*pr, r); return; } IPP_OWN_DEFN(void, convert_radix_to_64_p521, (Ipp64u rrad64[P521R1_LEN64], const fe521 a)) { /* filter chunk3 */ const m256i mask_filtc3 = m256_set_i64(0x0, 0x1, DIGIT_MASK_52, DIGIT_MASK_52); const m256i shift_left = m256_set_i64(4LL, 0LL, 4LL, 0LL); /* idx create chunk1 */ const m256i idx8_upc1c1 = m256_set_i8(31, 31, 31, 31, 31, 31, 31, 31, 23, 23, 23, 23, 22, 21, 20, 19, 15, 15, 15, 14, 13, 12, 11, 10, 7, 6, 5, 4, 3, 2, 1, 0); const m256i idx8_downc1c1 = m256_set_i8(31, 31, 31, 31, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 23, 18, 17, 16, 15, 15, 15, 15, 15, 9, 8, 7, 7, 7, 7, 7, 7); const m256i idx8_upc2c1 = m256_set_i8(5, 4, 3, 2, 1, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7); /* idx create chunk 2 */ const m256i idx8_upc2c2 = m256_set_i8(31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 23, 23, 22, 21, 20, 19, 18, 17, 16, 7, 7, 7, 7, 7, 7, 6); const m256i idx8_downc2c2 = m256_set_i8(31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 30, 29, 28, 27, 26, 25, 24, 23, 23, 23, 23, 23, 15, 14, 13, 12, 11, 10, 9, 8); const m256i idx8_upc3c2 = m256_set_i8(13, 12, 11, 10, 9, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7); const m256i idx8_downc3c2 = m256_set_i8(7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 1, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7); /* idx create chunk 3 */ const m256i idx8_upc3c3 = m256_set_i8(15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 15); const m256i idx8_downc3c3 = m256_set_i8(15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14); fe521 r; /* shift left */ FE521_LO(r) = m256_sllv_i64(FE521_LO(a), shift_left); FE521_MID(r) = m256_sllv_i64(FE521_MID(a), shift_left); FE521_HI(r) = m256_and_i64(FE521_HI(a), mask_filtc3); FE521_HI(r) = m256_sllv_i64(FE521_HI(r), shift_left); m256i t1, t2, t3; /* chunk 1 */ t1 = m256_permutexvar_i8(idx8_upc1c1, FE521_LO(r)); t2 = m256_permutexvar_i8(idx8_downc1c1, FE521_LO(r)); t1 = m256_or_i64(t1, t2); t3 = m256_permutexvar_i8(idx8_upc2c1, FE521_MID(r)); FE521_LO(r) = m256_or_i64(t3, t1); /* chunk 2 */ t1 = m256_permutexvar_i8(idx8_upc2c2, FE521_MID(r)); t2 = m256_permutexvar_i8(idx8_downc2c2, FE521_MID(r)); t3 = m256_or_i64(t1, t2); t1 = m256_permutexvar_i8(idx8_upc3c2, FE521_HI(r)); t2 = m256_permutexvar_i8(idx8_downc3c2, FE521_HI(r)); FE521_MID(r) = m256_or_i64(t3, m256_or_i64(t1, t2)); /* chunk 3 */ t1 = m256_permutexvar_i8(idx8_upc3c3, FE521_HI(r)); t2 = m256_permutexvar_i8(idx8_downc3c3, FE521_HI(r)); FE521_HI(r) = m256_or_i64(t1, t2); /* store */ m256_storeu_i64(rrad64, FE521_LO(r)); m256_storeu_i64(rrad64 + 4, FE521_MID(r)); m256_mask_storeu_i64(rrad64 + 8, 0x1, FE521_HI(r)); return; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_arith_p521.h000066400000000000000000000177121470420105600266350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ARITH_P521_H #define IFMA_ARITH_P521_H #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_defs_p521.h" /* * p521 = 2^521 - 1 * in 2^52 radix */ static const __ALIGN64 Ipp64u p521_x1[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000 } }; /* 2*p */ static const __ALIGN64 Ipp64u p521_x2[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x000FFFFFFFFFFFFE, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x0000000000000003, 0x0000000000000000 } }; /* 4*p */ static const __ALIGN64 Ipp64u p521_x4[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x000FFFFFFFFFFFFC, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x0000000000000007, 0x0000000000000000 } }; /* 6*p */ static const __ALIGN64 Ipp64u p521_x6[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x000FFFFFFFFFFFFA, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000000000000000B, 0x0000000000000000 } }; /* 8*p */ static const __ALIGN64 Ipp64u p521_x8[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x000FFFFFFFFFFFF8, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000000000000000F, 0x0000000000000000 } }; /* Montgomery(1) * r = 2^(P521_LEN52*DIGIT_SIZE) mod p521 */ static const __ALIGN64 Ipp64u P521R1_R52[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x0008000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }, { 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 } }; /** * \brief * normalization input fe521 to (in radix 2^52) * \param[out] pr ptr value (in radix 2^52) * \param[in] a value (52 radix or more) */ IPP_OWN_DECL(void, ifma_norm52_p521, (fe521 pr[], const fe521 a)) /** * \brief * duplicate normalization input double fe521 to (in radix 2^52) * \param[out] pr1 ptr first value (in radix 2^52) * \param[in] a1 value first (52 radix or more) * \param[out] pr2 ptr second value (in radix 2^52) * \param[in] a2 value second (52 radix or more) */ IPP_OWN_DECL(void, ifma_norm52_dual_p521, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) /** * \brief * light (mul|add only) normalization input fe521 to (in radix 2^52) * \param[out] pr ptr value (in radix 2^52) * \param[in] a value (52 radix or more) */ IPP_OWN_DECL(void, ifma_lnorm52_p521, (fe521 pr[], const fe521 a)) /** * \brief * light (mul|add only) duplicate normalization input double fe521 to (in radix 2^52) * \param[out] pr1 ptr first value (in radix 2^52) * \param[in] a1 value first (52 radix or more) * \param[out] pr2 ptr second value (in radix 2^52) * \param[in] a2 value second (52 radix or more) */ IPP_OWN_DECL(void, ifma_lnorm52_dual_p521, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) /** * \brief * R = (A * B) - no normalization * \param[out] pr ptr value * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_amm52_p521, (fe521 pr[], const fe521 a, const fe521 b)) /** * \brief * duplicate mul (R = A * B - no normalization) input double complect * \param[out] pr1 ptr first value no normalization * \param[in] a1 value first (in radix 2^52) * \param[in] b1 value second (in radix 2^52) * \param[out] pr2 ptr second value no normalization * \param[in] a2 value first (in radix 2^52) * \param[in] b2 value second (in radix 2^52) */ IPP_OWN_DECL(void, ifma_amm52_dual_p521, (fe521 pr1[], const fe521 a1, const fe521 b1, fe521 pr2[], const fe521 a2, const fe521 b2)) /** * \brief * R = A/2 - with normalization * \param[out] pr ptr value (in radix 2^52) * \param[in] a value (52 radix or more) */ IPP_OWN_DECL(void, ifma_half52_p521, (fe521 pr[], const fe521 a)) /** * \brief * compute R = (-A) enhanced Montgomery (Gueron modification group operation) * \param[out] pr ptr value (in radix 2^52) * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_neg52_p521, (fe521 pr[], const fe521 a)) /** * \brief * to Montgomery domain (in radix 2^52) * \param[out] pr ptr value (in radix 2^52) in Montgomery domain * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_tomont52_p521, (fe521 pr[], const fe521 a)) /** * \brief * from Montgomery domain (in radix 2^52) * \param[out] pr ptr value (in radix 2^52) from Montgomery domain * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_frommont52_p521, (fe521 pr[], const fe521 a)) /** * \brief * R = 1/Z * \param[out] pr ptr value (in radix 2^52) * \param[in] z value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_aminv52_p521, (fe521 pr[], const fe521 z)) /** * \brief * convert radix 64 to (in radix 2^52) * \param[out] pr ptr value (in radix 2^52) * \param[in] arad64 ptr array size (9) - 521 bit */ IPP_OWN_DECL(void, convert_radix_to_52_p521, (fe521 pr[], const Ipp64u arad64[P521R1_LEN64])) /** * \brief * convert (in radix 2^52) to radix 64 * \param[out] rrad64 ptr array size (9) - 521 bit * \param[in] a value (in radix 2^52) */ IPP_OWN_DECL(void, convert_radix_to_64_p521, (Ipp64u rrad64[P521R1_LEN64], const fe521 a)) /** * \brief * R = (A * A) - no normalization * \param[out] pr ptr value * \param[in] a first value (in radix 2^52) */ IPP_OWN_DECL(void, ifma_ams52_p521, (fe521 pr[], const fe521 a)) /** * \brief * duplicate sqr (R = A * A - no normalization) input double complect * \param[out] pr1 ptr first value no normalization * \param[in] a1 value first (in radix 2^52) * \param[out] pr2 ptr second value no normalization * \param[in] a2 value first (in radix 2^52) */ IPP_OWN_DECL(void, ifma_ams52_dual_p521, (fe521 pr1[], const fe521 a1, fe521 pr2[], const fe521 a2)) /* R = (A + B) */ #define fe521_add_no_red(R, A, B) \ FE521_LO(R) = m256_add_i64(FE521_LO(A), FE521_LO(B)); \ FE521_MID(R) = m256_add_i64(FE521_MID(A), FE521_MID(B)); \ FE521_HI(R) = m256_add_i64(FE521_HI(A), FE521_HI(B)) /* R = (A - B) */ #define fe521_sub_no_red(R, A, B) \ FE521_LO(R) = m256_sub_i64(FE521_LO(A), FE521_LO(B)); \ FE521_MID(R) = m256_sub_i64(FE521_MID(A), FE521_MID(B)); \ FE521_HI(R) = m256_sub_i64(FE521_HI(A), FE521_HI(B)) #endif // (_IPP32E >= _IPP32E_K1) #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_defs.h000066400000000000000000000040161470420105600256710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 IFMA_DEFS_H #define IFMA_DEFS_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "ifma_alias_avx512.h" /* Internal radix definition */ #define DIGIT_SIZE (52) #define DIGIT_BASE ((Ipp64u)1 << DIGIT_SIZE) #define DIGIT_MASK ((Ipp64u)0xFFFFFFFFFFFFF) /* Number of digit in "digsize" representation of "bitsize" value */ #define NUMBER_OF_DIGITS(bitsize, digsize) (((bitsize) + (digsize)-1) / (digsize)) /* Mask of most significant digit wrt "digsize" representation */ #define MS_DIGIT_MASK(bitsize, digsize) (((int64u)1 << ((bitsize) % digsize)) - 1) #define REPL8(e) e, e, e, e, e, e, e, e /** * \brief * * Check if bit on corresponding position is 1. * Position counting starts from zero. * * \return 0xFF - if MSB = 1 * \return 0x00 - if MSB = 0 */ __IPPCP_INLINE mask8 check_bit(const mask8 a, int bit) { return (mask8)((mask8)0 - ((a >> bit) & 1u)); } /** * \brief * * Check if ZMM register contains all zeroes. * * \param[in] a value * \return 0xFF - if input value is all zeroes * \return 0x00 - if input value is not all zeroes */ __IPPCP_INLINE mask8 is_zero_i64(const m512 a) { const mask8 mask = cmp_i64_mask(a, setzero_i64(), _MM_CMPINT_NE); return check_bit((~mask & (mask - 1u)), 7); } #endif // (_IPP32E >= _IPP32E_K1) #endif // IFMA_DEFS_H cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_defs_p521.h000066400000000000000000000057621470420105600264510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_DEFS_P521_H #define IFMA_DEFS_P521_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_alias_avx512vl.h" #define DIGIT_MASK_52 (0xFFFFFFFFFFFFF) #define DIGIT_SIZE_52 (52) #define P521R1_LEN52 (11) #define P521R1_LEN64 (9) #define P521R1_LENFE521_52 (4) #define P521R1_NUM_CHUNK (3) typedef m256i fe521[P521R1_NUM_CHUNK]; #define REPL4(a1, a2, a3, a4, a5, a6, a7, a8) a1, a2, a3, a4, a5, a6, a7, a8, \ a1, a2, a3, a4, a5, a6, a7, a8, \ a1, a2, a3, a4, a5, a6, a7, a8, \ a1, a2, a3, a4, a5, a6, a7, a8 /* one */ static const __ALIGN64 Ipp64u P521R1_ONE52[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x1, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0 }, { 0x0, 0x0, 0x0, 0x0 } }; #define FE521_LO(A) (A)[0] #define FE521_MID(A) (A)[1] #define FE521_HI(A) (A)[2] #define FE521_SET(A) FE521_LO(A) = FE521_MID(A) = FE521_HI(A) #define FE521_COPY(R, A) \ FE521_LO(R) = FE521_LO(A); \ FE521_MID(R) = FE521_MID(A); \ FE521_HI(R) = FE521_HI(A) #define FE521_LOADU(R, A) \ FE521_LO(R) = m256_loadu_i64(FE521_LO(A)); \ FE521_MID(R) = m256_loadu_i64(FE521_MID(A)); \ FE521_HI(R) = m256_loadu_i64(FE521_HI(A)) __IPPCP_INLINE mask8 is_msb_m256(const mask8 a) { return ((mask8)0 - (a >> 7)); } __IPPCP_INLINE mask8 is_zero_m256(const m256i a) { const mask8 mask = _mm256_cmp_epi64_mask(a, m256_setzero_i64(), _MM_CMPINT_NE); return is_msb_m256((~mask & (mask - 1))); } #define FE521_IS_ZERO(A) (is_zero_m256(m256_or_i64(m256_or_i64(FE521_LO(A), FE521_MID(A)), FE521_HI(A)))) #define FE521_CMP_MASK(A, B, ENUM_CMP) \ (m256_cmp_i64_mask(FE521_LO(A), FE521_LO(B), (ENUM_CMP)) & m256_cmp_i64_mask(FE521_MID(A), FE521_MID(B), (ENUM_CMP)) & m256_cmp_i64_mask(FE521_HI(A), FE521_HI(B), (ENUM_CMP))) #define FE521_MASK_MOV(R, SRC, MASK, A) \ FE521_LO(R) = m256_mask_mov_i64(FE521_LO(SRC), (MASK), FE521_LO(A)); \ FE521_MID(R) = m256_mask_mov_i64(FE521_MID(SRC), (MASK), FE521_MID(A)); \ FE521_HI(R) = m256_mask_mov_i64(FE521_HI(SRC), (MASK), FE521_HI(A)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _CP_DEFINE_FE521_K1 cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_addpoint_p256.c000066400000000000000000000037371470420105600300010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_AddPoint_nistp256_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); __ALIGN64 P256_POINT_IFMA P, R; BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPool, pmeth, pME); if (pP == pQ) { ifma_ec_nistp256_dbl_point(&R, &P); } else { __ALIGN64 P256_POINT_IFMA Q; recode_point_to_mont52(&Q, ECP_POINT_DATA(pQ), pPool, pmeth, pME); ifma_ec_nistp256_add_point(&R, &P, &Q); } recode_point_to_mont64(pR, &R, pPool, pmeth, pME); cpGFpReleasePool(3, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_addpoint_p384.c000066400000000000000000000037371470420105600300030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_AddPoint_nistp384_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); __ALIGN64 P384_POINT_IFMA P, R; BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPool, pmeth, pME); if (pP == pQ) { ifma_ec_nistp384_dbl_point(&R, &P); } else { __ALIGN64 P384_POINT_IFMA Q; recode_point_to_mont52(&Q, ECP_POINT_DATA(pQ), pPool, pmeth, pME); ifma_ec_nistp384_add_point(&R, &P, &Q); } recode_point_to_mont64(pR, &R, pPool, pmeth, pME); cpGFpReleasePool(3, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_addpoint_p521.c000066400000000000000000000037561470420105600277750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_AddPoint_nistp521_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); __ALIGN64 P521_POINT_IFMA P, R; BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPool, pmeth, pME); if (pP == pQ) { ifma_ec_nistp521_dbl_point(&R, &P); } else { __ALIGN64 P521_POINT_IFMA Q; recode_point_to_mont52(&Q, ECP_POINT_DATA(pQ), pPool, pmeth, pME); ifma_ec_nistp521_add_point(&R, &P, &Q); } recode_point_to_mont64(pR, &R, pPool, pmeth, pME); cpGFpReleasePool(3, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dh_p256.c000066400000000000000000000054171470420105600265670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" #include "gfpec/ecnist/ifma_arith_method.h" IPP_OWN_DEFN(int, gfec_SharedSecretDH_nistp256_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint *pP, const BNU_CHUNK_T *pScalar, int scalarLen, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Copy scalar */ BNU_CHUNK_T *pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P256_POINT_IFMA P52, R52; BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); /* Convert point coordinates to a new Montgomery domain */ recode_point_to_mont52(&P52, ECP_POINT_DATA(pP), pPool, pmeth, pME); ifma_ec_nistp256_mul_point(&R52, &P52, (Ipp8u *)pExtendedScalar, orderBits); /* Check if the point - point to infinity */ const mask8 is_zero_z = is_zero_i64(R52.z); int finite_point = ((mask8)0xFF != is_zero_z); /* Get X affine coordinate */ ifma_ec_nistp256_get_affine_coords(&(R52.x), NULL, &R52); R52.x = p_from_mont(R52.x); from_radix52(ECP_POINT_X(pR), R52.x); cpGFpReleasePool(5, pME); return finite_point; } } #endif // IPP32E >= _IPP32E_K1 cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dh_p384.c000066400000000000000000000054171470420105600265710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" #include "gfpec/ecnist/ifma_arith_method.h" IPP_OWN_DEFN(int, gfec_SharedSecretDH_nistp384_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint *pP, const BNU_CHUNK_T *pScalar, int scalarLen, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Copy scalar */ BNU_CHUNK_T *pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P384_POINT_IFMA P52, R52; BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); /* Convert point coordinates to a new Montgomery domain */ recode_point_to_mont52(&P52, ECP_POINT_DATA(pP), pPool, pmeth, pME); ifma_ec_nistp384_mul_point(&R52, &P52, (Ipp8u *)pExtendedScalar, orderBits); /* Check if the point - point to infinity */ const mask8 is_zero_z = is_zero_i64(R52.z); int finite_point = ((mask8)0xFF != is_zero_z); /* Get X affine coordinate */ ifma_ec_nistp384_get_affine_coords(&(R52.x), NULL, &R52); R52.x = p_from_mont(R52.x); from_radix52(ECP_POINT_X(pR), R52.x); cpGFpReleasePool(5, pME); return finite_point; } } #endif // IPP32E >= _IPP32E_K1 cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dh_p521.c000066400000000000000000000053761470420105600265660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" IPP_OWN_DEFN(int, gfec_SharedSecretDH_nistp521_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint *pP, const BNU_CHUNK_T *pScalar, int scalarLen, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Copy scalar */ BNU_CHUNK_T *pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P521_POINT_IFMA P52, R52; BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); /* Convert point coordinates to a new Montgomery domain */ recode_point_to_mont52(&P52, ECP_POINT_DATA(pP), pPool, pmeth, pME); ifma_ec_nistp521_mul_point(&R52, &P52, (Ipp8u *)pExtendedScalar, orderBits); /* Check if the point - point to infinity */ const mask8 is_zero_z = FE521_IS_ZERO(R52.z); int finite_point = ((mask8)0xFF != is_zero_z); /* Get X affine coordinate */ ifma_ec_nistp521_get_affine_coords(&(R52.x), NULL, &R52); p_from_mont(&(R52.x), R52.x); from_radix52(ECP_POINT_X(pR), R52.x); cpGFpReleasePool(5, pME); return finite_point; } } #endif // IPP32E >= _IPP32E_K1 cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dsasign_p256.c000066400000000000000000000116251470420105600276220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" #include "gfpec/ecnist/ifma_arith_method.h" IPP_OWN_DEFN(IppStatus, gfec_SignDSA_nistp256_avx512, (const IppsBigNumState *pMsgDigest, const IppsBigNumState *pRegPrivate, IppsBigNumState *pEphPrivate, IppsBigNumState *pSignR, IppsBigNumState *pSignS, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppStatus sts = ippStsNoErr; gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifmaArithMethod *nmeth = (ifmaArithMethod *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_add n_add = nmeth->add; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; /* Copy scalar */ BNU_CHUNK_T *pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); __ALIGN64 P256_POINT_IFMA P; if (ECP_PREMULBP(pEC)) { ifma_ec_nistp256_mul_pointbase(&P, (Ipp8u *)pExtendedScalar, orderBits); } else { BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); /* Convert base point to a new Montgomery domain */ __ALIGN64 P256_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool, pmeth, pME); ifma_ec_nistp256_mul_point(&P, &G52, (Ipp8u *)pExtendedScalar, orderBits); cpGFpReleasePool(3, pME); } /* // signR = int(ephPublic.x) (mod order) */ /* Extract affine P.x */ ifma_ec_nistp256_get_affine_coords(&(P.x), NULL, &P); P.x = p_from_mont(P.x); P.x = n_red(P.x); /* // signS = (1/ephPrivate)*(pMsgDigest + private*signR) (mod order) */ m512 ephPrivateInv = setzero_i64(); BNU_CHUNK_T *pTmp = cpGFpGetPool(1, pME); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); ephPrivateInv = to_radix52(pTmp); ephPrivateInv = n_to_mont(ephPrivateInv); ephPrivateInv = n_inv(ephPrivateInv); /* Message */ m512 msgDigest = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); msgDigest = to_radix52(pTmp); msgDigest = n_red(msgDigest); /* reduce just in case */ msgDigest = n_to_mont(msgDigest); /* Regular private key */ m512 regPrivate = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pRegPrivate), BN_SIZE(pRegPrivate)); regPrivate = to_radix52(pTmp); regPrivate = n_to_mont(regPrivate); m512 signS; signS = n_to_mont(P.x); signS = n_mul(regPrivate, signS); signS = n_add(signS, msgDigest); signS = n_mul(signS, ephPrivateInv); signS = n_from_mont(signS); const mask8 isZero = (mask8)(is_zero_i64(signS) | is_zero_i64(P.x)); if ((mask8)0xFF == isZero) sts = ippStsEphemeralKeyErr; from_radix52((Ipp64u *)pTmp, signS); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = orderLen; ZEXPAND_COPY_BNU(BN_NUMBER(pSignS), BN_ROOM(pSignS), pTmp, orderLen); from_radix52((Ipp64u *)pTmp, P.x); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = orderLen; ZEXPAND_COPY_BNU(BN_NUMBER(pSignR), BN_ROOM(pSignR), pTmp, orderLen); /* Clear secret data */ clear_secrets(®Private, &(P.x), &signS); cpGFpReleasePool(3, pME); return sts; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dsasign_p384.c000066400000000000000000000116251470420105600276240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" #include "gfpec/ecnist/ifma_arith_method.h" IPP_OWN_DEFN(IppStatus, gfec_SignDSA_nistp384_avx512, (const IppsBigNumState *pMsgDigest, const IppsBigNumState *pRegPrivate, IppsBigNumState *pEphPrivate, IppsBigNumState *pSignR, IppsBigNumState *pSignS, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppStatus sts = ippStsNoErr; gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifmaArithMethod *nmeth = (ifmaArithMethod *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_add n_add = nmeth->add; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; /* Copy scalar */ BNU_CHUNK_T *pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); __ALIGN64 P384_POINT_IFMA P; if (ECP_PREMULBP(pEC)) { ifma_ec_nistp384_mul_pointbase(&P, (Ipp8u *)pExtendedScalar, orderBits); } else { BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); /* Convert base point to a new Montgomery domain */ __ALIGN64 P384_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool, pmeth, pME); ifma_ec_nistp384_mul_point(&P, &G52, (Ipp8u *)pExtendedScalar, orderBits); cpGFpReleasePool(3, pME); } /* // signR = int(ephPublic.x) (mod order) */ /* Extract affine P.x */ ifma_ec_nistp384_get_affine_coords(&(P.x), NULL, &P); P.x = p_from_mont(P.x); P.x = n_red(P.x); /* // signS = (1/ephPrivate)*(pMsgDigest + private*signR) (mod order) */ m512 ephPrivateInv = setzero_i64(); BNU_CHUNK_T *pTmp = cpGFpGetPool(1, pME); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); ephPrivateInv = to_radix52(pTmp); ephPrivateInv = n_to_mont(ephPrivateInv); ephPrivateInv = n_inv(ephPrivateInv); /* Message */ m512 msgDigest = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); msgDigest = to_radix52(pTmp); msgDigest = n_red(msgDigest); /* reduce just in case */ msgDigest = n_to_mont(msgDigest); /* Regular private key */ m512 regPrivate = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pRegPrivate), BN_SIZE(pRegPrivate)); regPrivate = to_radix52(pTmp); regPrivate = n_to_mont(regPrivate); m512 signS; signS = n_to_mont(P.x); signS = n_mul(regPrivate, signS); signS = n_add(signS, msgDigest); signS = n_mul(signS, ephPrivateInv); signS = n_from_mont(signS); const mask8 isZero = (mask8)(is_zero_i64(signS) | is_zero_i64(P.x)); if ((mask8)0xFF == isZero) sts = ippStsEphemeralKeyErr; from_radix52((Ipp64u *)pTmp, signS); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = orderLen; ZEXPAND_COPY_BNU(BN_NUMBER(pSignS), BN_ROOM(pSignS), pTmp, orderLen); from_radix52((Ipp64u *)pTmp, P.x); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = orderLen; ZEXPAND_COPY_BNU(BN_NUMBER(pSignR), BN_ROOM(pSignR), pTmp, orderLen); /* Clear secret data */ clear_secrets(®Private, &(P.x), &signS); cpGFpReleasePool(3, pME); return sts; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dsasign_p521.c000066400000000000000000000120511470420105600276070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_alias_avx512vl.h" IPP_OWN_DEFN(IppStatus, gfec_SignDSA_nistp521_avx512, (const IppsBigNumState *pMsgDigest, const IppsBigNumState *pRegPrivate, IppsBigNumState *pEphPrivate, IppsBigNumState *pSignR, IppsBigNumState *pSignS, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppStatus sts = ippStsNoErr; gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); ifmaArithMethod_p521 *nmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_add n_add = nmeth->add; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; /* Copy scalar */ BNU_CHUNK_T *pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); __ALIGN64 P521_POINT_IFMA P; if (ECP_PREMULBP(pEC)) { ifma_ec_nistp521_mul_pointbase(&P, (Ipp8u *)pExtendedScalar, orderBits); } else { BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); /* Convert base point to a new Montgomery domain */ __ALIGN64 P521_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool, pmeth, pME); ifma_ec_nistp521_mul_point(&P, &G52, (Ipp8u *)pExtendedScalar, orderBits); cpGFpReleasePool(3, pME); } /* // signR = int(ephPublic.x) (mod order) */ /* Extract affine P.x */ ifma_ec_nistp521_get_affine_coords(&(P.x), NULL, &P); p_from_mont(&(P.x), P.x); n_red(&(P.x), P.x); /* // signS = (1/ephPrivate)*(pMsgDigest + private*signR) (mod order) */ fe521 ephPrivateInv; FE521_SET(ephPrivateInv) = m256_setzero_i64(); BNU_CHUNK_T *pTmp = cpGFpGetPool(1, pME); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); to_radix52(&ephPrivateInv, pTmp); n_to_mont(&ephPrivateInv, ephPrivateInv); n_inv(&ephPrivateInv, ephPrivateInv); /* Message */ fe521 msgDigest; FE521_SET(msgDigest) = m256_setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); to_radix52(&msgDigest, pTmp); n_red(&msgDigest, msgDigest); /* reduce just in case */ n_to_mont(&msgDigest, msgDigest); /* Regular private key */ fe521 regPrivate; FE521_SET(regPrivate) = m256_setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pRegPrivate), BN_SIZE(pRegPrivate)); to_radix52(®Private, pTmp); n_to_mont(®Private, regPrivate); fe521 signS; n_to_mont(&signS, P.x); n_mul(&signS, regPrivate, signS); n_add(&signS, signS, msgDigest); n_mul(&signS, signS, ephPrivateInv); n_from_mont(&signS, signS); const mask8 isZero = (mask8)(FE521_IS_ZERO(signS) | FE521_IS_ZERO(P.x)); if ((mask8)0xFF == isZero) sts = ippStsEphemeralKeyErr; from_radix52((Ipp64u *)pTmp, signS); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = orderLen; ZEXPAND_COPY_BNU(BN_NUMBER(pSignS), BN_ROOM(pSignS), pTmp, orderLen); from_radix52((Ipp64u *)pTmp, P.x); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = orderLen; ZEXPAND_COPY_BNU(BN_NUMBER(pSignR), BN_ROOM(pSignR), pTmp, orderLen); /* Clear secret data */ clear_secrets(®Private, &(P.x), &signS); cpGFpReleasePool(3, pME); return sts; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dsaverify_p256.c000066400000000000000000000115721470420105600301670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" IPP_OWN_DEFN(IppECResult, gfec_VerifyDSA_nistp256_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppECResult verifyResult = ippECInvalidSignature; gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifmaArithMethod *nmeth = (ifmaArithMethod *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; /* Convert input parameters to 2^52 radix */ m512 msg, signR, signS; msg = signR = signS = setzero_i64(); const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); BNU_CHUNK_T *pBufMsg = pPool; BNU_CHUNK_T *pBufSignR = pPool + elemLen; BNU_CHUNK_T *pBufSignS = pPool + 2 * elemLen; ZEXPAND_COPY_BNU(pBufMsg, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); ZEXPAND_COPY_BNU(pBufSignR, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); ZEXPAND_COPY_BNU(pBufSignS, orderLen, BN_NUMBER(pSignS), BN_SIZE(pSignS)); msg = to_radix52((Ipp64u *)pBufMsg); msg = n_red(msg); /* reduce just in case */ signR = to_radix52((Ipp64u *)pBufSignR); signS = to_radix52((Ipp64u *)pBufSignS); /* Convert public point to proper Montgomery domain and 2^52 radix */ __ALIGN64 P256_POINT_IFMA pubKey; recode_point_to_mont52(&pubKey, ECP_POINT_DATA(pRegPublic), pPool /* 3 elem */, pmeth, pME); m512 h, h1, h2; /* h = (signS)^(-1) */ h = n_to_mont(signS); h = n_inv(h); /* h1 = msg*h, h2 = signR*h */ h1 = n_to_mont(msg); h2 = n_to_mont(signR); h1 = n_mul(h1, h); h2 = n_mul(h2, h); h1 = n_from_mont(h1); h2 = n_from_mont(h2); BNU_CHUNK_T *pExtendedH1 = cpGFpGetPool(2, pME); BNU_CHUNK_T *pExtendedH2 = cpGFpGetPool(2, pME); BNU_CHUNK_T *pH1 = cpGFpGetPool(1, pME); BNU_CHUNK_T *pH2 = cpGFpGetPool(1, pME); from_radix52((Ipp64u *)pH1, h1); from_radix52((Ipp64u *)pH2, h2); cpGFpElementCopyPad(pExtendedH1, orderLen + 1, pH1, orderLen); cpGFpElementCopyPad(pExtendedH2, orderLen + 1, pH2, orderLen); cpGFpReleasePool(2, pME); /* pH1, pH2 */ __ALIGN64 P256_POINT_IFMA P; /* P = h1*basePoint + h2*pubKey */ ifma_ec_nistp256_mul_point(&pubKey, &pubKey, (Ipp8u *)pExtendedH2, orderBits); if (ECP_PREMULBP(pEC)) { ifma_ec_nistp256_mul_pointbase(&P, (Ipp8u *)pExtendedH1, orderBits); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 P256_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool /* 3 elem */, pmeth, pME); ifma_ec_nistp256_mul_point(&P, &G52, (Ipp8u *)pExtendedH1, orderBits); } ifma_ec_nistp256_add_point(&P, &P, &pubKey); /* Get X in affine coordinates */ ifma_ec_nistp256_get_affine_coords(&(P.x), NULL, &P); P.x = p_from_mont(P.x); P.x = n_red(P.x); const mask8 mask_ok = cmp_i64_mask(P.x, signR, _MM_CMPINT_EQ); if ((mask8)0xFF == mask_ok) verifyResult = ippECValid; cpGFpReleasePool(7, pME); return verifyResult; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dsaverify_p384.c000066400000000000000000000116761470420105600301760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" IPP_OWN_DEFN(IppECResult, gfec_VerifyDSA_nistp384_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppECResult verifyResult = ippECInvalidSignature; gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifmaArithMethod *nmeth = (ifmaArithMethod *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; /* Convert input parameters to 2^52 radix */ m512 msg, signR, signS; msg = signR = signS = setzero_i64(); const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); BNU_CHUNK_T *pBufMsg = pPool; BNU_CHUNK_T *pBufSignR = pPool + elemLen; BNU_CHUNK_T *pBufSignS = pPool + 2 * elemLen; ZEXPAND_COPY_BNU(pBufMsg, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); ZEXPAND_COPY_BNU(pBufSignR, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); ZEXPAND_COPY_BNU(pBufSignS, orderLen, BN_NUMBER(pSignS), BN_SIZE(pSignS)); msg = to_radix52((Ipp64u *)pBufMsg); msg = n_red(msg); /* reduce just in case */ signR = to_radix52((Ipp64u *)pBufSignR); signS = to_radix52((Ipp64u *)pBufSignS); /* Convert public point to proper Montgomery domain and 2^52 radix */ __ALIGN64 P384_POINT_IFMA pubKey; recode_point_to_mont52(&pubKey, ECP_POINT_DATA(pRegPublic), pPool /* 3 elem */, pmeth, pME); m512 h, h1, h2; h = h1 = h2 = setzero_i64(); /* h = (signS)^(-1) */ h = n_to_mont(signS); h = n_inv(h); /* h1 = msg*h, h2 = signR*h */ h1 = n_to_mont(msg); h2 = n_to_mont(signR); h1 = n_mul(h1, h); h2 = n_mul(h2, h); h1 = n_from_mont(h1); h2 = n_from_mont(h2); BNU_CHUNK_T *pExtendedH1 = cpGFpGetPool(2, pME); BNU_CHUNK_T *pExtendedH2 = cpGFpGetPool(2, pME); BNU_CHUNK_T *pH1 = cpGFpGetPool(1, pME); BNU_CHUNK_T *pH2 = cpGFpGetPool(1, pME); from_radix52((Ipp64u *)pH1, h1); from_radix52((Ipp64u *)pH2, h2); cpGFpElementCopyPad(pExtendedH1, orderLen + 1, pH1, orderLen); cpGFpElementCopyPad(pExtendedH2, orderLen + 1, pH2, orderLen); cpGFpReleasePool(2, pME); /* pH1, pH2 */ __ALIGN64 P384_POINT_IFMA P; P.x = P.y = P.z = setzero_i64(); /* P = h1*basePoint + h2*pubKey */ ifma_ec_nistp384_mul_point(&pubKey, &pubKey, (Ipp8u *)pExtendedH2, orderBits); if (ECP_PREMULBP(pEC)) { ifma_ec_nistp384_mul_pointbase(&P, (Ipp8u *)pExtendedH1, orderBits); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 P384_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool /* 3 elem */, pmeth, pME); ifma_ec_nistp384_mul_point(&P, &G52, (Ipp8u *)pExtendedH1, orderBits); } ifma_ec_nistp384_add_point(&P, &P, &pubKey); /* Get X in affine coordinates */ ifma_ec_nistp384_get_affine_coords(&(P.x), NULL, &P); P.x = p_from_mont(P.x); P.x = n_red(P.x); const mask8 mask_ok = cmp_i64_mask(P.x, signR, _MM_CMPINT_EQ); if ((mask8)0xFF == mask_ok) verifyResult = ippECValid; cpGFpReleasePool(7, pME); return verifyResult; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_dsaverify_p521.c000066400000000000000000000121151470420105600301540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" IPP_OWN_DEFN(IppECResult, gfec_VerifyDSA_nistp521_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppECResult verifyResult = ippECInvalidSignature; gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); ifmaArithMethod_p521 *nmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; /* Convert input parameters to 2^52 radix */ fe521 msg, signR, signS; FE521_SET(msg) = FE521_SET(signR) = FE521_SET(signS) = m256_setzero_i64(); const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); BNU_CHUNK_T *pBufMsg = pPool; BNU_CHUNK_T *pBufSignR = pPool + elemLen; BNU_CHUNK_T *pBufSignS = pPool + 2 * elemLen; ZEXPAND_COPY_BNU(pBufMsg, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); ZEXPAND_COPY_BNU(pBufSignR, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); ZEXPAND_COPY_BNU(pBufSignS, orderLen, BN_NUMBER(pSignS), BN_SIZE(pSignS)); to_radix52(&msg, (Ipp64u *)pBufMsg); n_red(&msg, msg); /* reduce just in case */ to_radix52(&signR, (Ipp64u *)pBufSignR); to_radix52(&signS, (Ipp64u *)pBufSignS); /* Convert public point to proper Montgomery domain and 2^52 radix */ __ALIGN64 P521_POINT_IFMA pubKey; recode_point_to_mont52(&pubKey, ECP_POINT_DATA(pRegPublic), pPool /* 3 elem */, pmeth, pME); fe521 h, h1, h2; FE521_SET(h) = FE521_SET(h1) = FE521_SET(h2) = m256_setzero_i64(); /* h = (signS)^(-1) */ n_to_mont(&h, signS); n_inv(&h, h); /* h1 = msg*h, h2 = signR*h */ n_to_mont(&h1, msg); n_to_mont(&h2, signR); n_mul(&h1, h1, h); n_mul(&h2, h2, h); n_from_mont(&h1, h1); n_from_mont(&h2, h2); BNU_CHUNK_T *pExtendedH1 = cpGFpGetPool(2, pME); BNU_CHUNK_T *pExtendedH2 = cpGFpGetPool(2, pME); BNU_CHUNK_T *pH1 = cpGFpGetPool(1, pME); BNU_CHUNK_T *pH2 = cpGFpGetPool(1, pME); from_radix52((Ipp64u *)pH1, h1); from_radix52((Ipp64u *)pH2, h2); cpGFpElementCopyPad(pExtendedH1, orderLen + 1, pH1, orderLen); cpGFpElementCopyPad(pExtendedH2, orderLen + 1, pH2, orderLen); cpGFpReleasePool(2, pME); /* pH1, pH2 */ __ALIGN64 P521_POINT_IFMA P; FE521_SET(P.x) = FE521_SET(P.y) = FE521_SET(P.z) = m256_setzero_i64(); /* P = h1*basePoint + h2*pubKey */ ifma_ec_nistp521_mul_point(&pubKey, &pubKey, (Ipp8u *)pExtendedH2, orderBits); if (ECP_PREMULBP(pEC)) { ifma_ec_nistp521_mul_pointbase(&P, (Ipp8u *)pExtendedH1, orderBits); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 P521_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool /* 3 elem */, pmeth, pME); ifma_ec_nistp521_mul_point(&P, &G52, (Ipp8u *)pExtendedH1, orderBits); } ifma_ec_nistp521_add_point(&P, &P, &pubKey); /* Get X in affine coordinates */ ifma_ec_nistp521_get_affine_coords(&(P.x), NULL, &P); p_from_mont(&(P.x), P.x); n_red(&(P.x), P.x); const mask8 mask_ok = FE521_CMP_MASK(P.x, signR, _MM_CMPINT_EQ); if ((mask8)0xF == mask_ok) verifyResult = ippECValid; cpGFpReleasePool(7, pME); return verifyResult; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_mulpoint_p256.c000066400000000000000000000047411470420105600300420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" IPP_OWN_DEFN (IppsGFpECPoint*, gfec_MulPoint_nistp256_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(5, pME); BNU_CHUNK_T *pExtendedScalar = pPool; /* 2 pool elem to hold scalar */ BNU_CHUNK_T *pPointPool = pPool + 2 * elemLen; /* 3 pool elem to to hold 3 point coordinates */ /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P256_POINT_IFMA P, R; recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPointPool, pmeth, pME); ifma_ec_nistp256_mul_point(&R, &P, (Ipp8u*)pExtendedScalar, orderBits); recode_point_to_mont64(pR, &R, pPointPool, pmeth, pME); cpGFpReleasePool(5, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_mulpoint_p384.c000066400000000000000000000047411470420105600300440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" IPP_OWN_DEFN (IppsGFpECPoint*, gfec_MulPoint_nistp384_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(5, pME); BNU_CHUNK_T *pExtendedScalar = pPool; /* 2 pool elem to hold scalar */ BNU_CHUNK_T *pPointPool = pPool + 2 * elemLen; /* 3 pool elem to to hold 3 point coordinates */ /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P384_POINT_IFMA P, R; recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPointPool, pmeth, pME); ifma_ec_nistp384_mul_point(&R, &P, (Ipp8u*)pExtendedScalar, orderBits); recode_point_to_mont64(pR, &R, pPointPool, pmeth, pME); cpGFpReleasePool(5, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_mulpoint_p521.c000066400000000000000000000047601470420105600300360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" IPP_OWN_DEFN (IppsGFpECPoint*, gfec_MulPoint_nistp521_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(5, pME); BNU_CHUNK_T *pExtendedScalar = pPool; /* 2 pool elem to hold scalar */ BNU_CHUNK_T *pPointPool = pPool + 2 * elemLen; /* 3 pool elem to to hold 3 point coordinates */ /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P521_POINT_IFMA P, R; recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPointPool, pmeth, pME); ifma_ec_nistp521_mul_point(&R, &P, (Ipp8u*)pExtendedScalar, orderBits); recode_point_to_mont64(pR, &R, pPointPool, pmeth, pME); cpGFpReleasePool(5, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_on_curve_p256.c000066400000000000000000000030171470420105600300060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" IPP_OWN_DEFN(int, gfec_point_on_curve_nistp256_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); __ALIGN64 P256_POINT_IFMA P; recode_point_to_mont52(&P, ECP_POINT_DATA(pPoint), pPool /* 3 elem */, pmeth, pME); const int onCurve = ifma_ec_nistp256_is_on_curve(&P, /* use_jproj_coord = */ !IS_ECP_AFFINE_POINT(pPoint)); cpGFpReleasePool(3, pME); return onCurve; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_on_curve_p384.c000066400000000000000000000030171470420105600300100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" IPP_OWN_DEFN(int, gfec_point_on_curve_nistp384_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); __ALIGN64 P384_POINT_IFMA P; recode_point_to_mont52(&P, ECP_POINT_DATA(pPoint), pPool /* 3 elem */, pmeth, pME); const int onCurve = ifma_ec_nistp384_is_on_curve(&P, /* use_jproj_coord = */ !IS_ECP_AFFINE_POINT(pPoint)); cpGFpReleasePool(3, pME); return onCurve; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_on_curve_p521.c000066400000000000000000000030361470420105600300020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" IPP_OWN_DEFN(int, gfec_point_on_curve_nistp521_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); __ALIGN64 P521_POINT_IFMA P; recode_point_to_mont52(&P, ECP_POINT_DATA(pPoint), pPool /* 3 elem */, pmeth, pME); const int onCurve = ifma_ec_nistp521_is_on_curve(&P, /* use_jproj_coord = */ !IS_ECP_AFFINE_POINT(pPoint)); cpGFpReleasePool(3, pME); return onCurve; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_pubkey_p256.c000066400000000000000000000052151470420105600274670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" #include "gfpec/ecnist/ifma_arith_p256.h" #include "gfpec/ecnist/ifma_arith_method.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_PubKey_nist256_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(5, nME); BNU_CHUNK_T *pExtendedScalar = pPool; BNU_CHUNK_T *pPointPool = pExtendedScalar + 2 * GFP_FELEN(pME); /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P256_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); if (ECP_PREMULBP(pEC)) { ifma_ec_nistp256_mul_pointbase(&R, (Ipp8u *)pExtendedScalar, orderBits); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 P256_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPointPool /* 3 elem */, pmeth, pME); ifma_ec_nistp256_mul_point(&R, &G52, (Ipp8u *)pExtendedScalar, orderBits); } recode_point_to_mont64(pR, &R, pPointPool /* 3 elem */, pmeth, pME); cpGFpReleasePool(5, nME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_pubkey_p384.c000066400000000000000000000052151470420105600274710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_p384.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" #include "gfpec/ecnist/ifma_arith_method.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_PubKey_nist384_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(5, nME); BNU_CHUNK_T *pExtendedScalar = pPool; BNU_CHUNK_T *pPointPool = pExtendedScalar + 2 * GFP_FELEN(pME); /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P384_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); if (ECP_PREMULBP(pEC)) { ifma_ec_nistp384_mul_pointbase(&R, (Ipp8u *)pExtendedScalar, orderBits); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 P384_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPointPool /* 3 elem */, pmeth, pME); ifma_ec_nistp384_mul_point(&R, &G52, (Ipp8u *)pExtendedScalar, orderBits); } recode_point_to_mont64(pR, &R, pPointPool /* 3 elem */, pmeth, pME); cpGFpReleasePool(5, nME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ec_pubkey_p521.c000066400000000000000000000053021470420105600274570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" #include "gfpec/ecnist/ifma_arith_p521.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_PubKey_nist521_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod_p521 *pmeth = (ifmaArithMethod_p521 *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(5, nME); BNU_CHUNK_T *pExtendedScalar = pPool; BNU_CHUNK_T *pPointPool = pExtendedScalar + 2 * GFP_FELEN(pME); /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 P521_POINT_IFMA R; FE521_SET(R.x) = FE521_SET(R.y) = FE521_SET(R.z) = m256_setzero_i64(); if (ECP_PREMULBP(pEC)) { ifma_ec_nistp521_mul_pointbase(&R, (Ipp8u *)pExtendedScalar, orderBits); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 P521_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPointPool /* 3 elem */, pmeth, pME); ifma_ec_nistp521_mul_point(&R, &G52, (Ipp8u *)pExtendedScalar, orderBits); } recode_point_to_mont64(pR, &R, pPointPool /* 3 elem */, pmeth, pME); cpGFpReleasePool(5, nME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecpoint_p256.c000066400000000000000000000507311470420105600271650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ /* Paper referenced in this file: * * [1] "Enhanced Montgomery Multiplication" DOI:10.1155/2008/583926 * */ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_p256.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" #define LEN64 (4) #define LEN52 (5 + 3) /* 5 digits + 3 zero padding */ /* Modulus scaled: 2*p */ static const __ALIGN64 Ipp64u p256_x2[LEN52] = { 0x000ffffffffffffe, 0x00001fffffffffff, 0x0000000000000000, 0x0000002000000000, 0x0001fffffffe0000, 0x0, 0x0, 0x0 }; /* Modulus scaled: 4*p */ static const __ALIGN64 Ipp64u p256_x4[LEN52] = { 0x000ffffffffffffc, 0x00003fffffffffff, 0x0000000000000000, 0x0000004000000000, 0x0003fffffffc0000, 0x0, 0x0, 0x0 }; /* Modulus scaled: 6*p */ static const __ALIGN64 Ipp64u p256_x6[LEN52] = { 0x000ffffffffffffa, 0x00005fffffffffff, 0x0000000000000000, 0x0000006000000000, 0x0005fffffffa0000, 0x0, 0x0, 0x0 }; /* Modulus scaled: 8*p */ static const __ALIGN64 Ipp64u p256_x8[LEN52] = { 0x000ffffffffffff8, 0x00007fffffffffff, 0x0000000000000000, 0x0000008000000000, 0x0007fffffff80000, 0x0, 0x0, 0x0 }; /* Mont(a) = a*r mod p256, where r = 2^(6*52) mod p256 */ static const __ALIGN64 Ipp64u p256_a[LEN52] = { 0x000ffffffd000000, 0x000fffffffffffcf, 0x000300000002ffff, 0x0000000000000000, 0x0000000000000300, 0x0, 0x0, 0x0 }; /* Mont(b) = b*r mod p256, where r = 2^(6*52) mod p256 */ static const __ALIGN64 Ipp64u p256_b[LEN52] = { 0x000c30061de0b74e, 0x000916229c4bddfd, 0x000c9c542a72f7e5, 0x00069e0d6acf005c, 0x000051ea29688e16, 0x0, 0x0, 0x0 }; /* * r = 2^(P256_LEN52*DIGIT_SIZE) mod p256 */ static const __ALIGN64 Ipp64u p256_r[LEN52] = { 0x0000000000ffffff, 0x0000100000000010, 0x000effffffff0000, 0x0000000fffffffff, 0x0000fffffffeff00, 0x0, 0x0, 0x0 }; /* Aliases for operations */ #define add(R, A, B) (R) = add_i64((A), (B)) #define sub(R, A, B) (R) = sub_i64((A), (B)) #define mul(R, A, B) (R) = ifma_amm52_p256((A), (B)) #define sqr(R, A) (R) = ifma_ams52_p256((A)) #define div2(R, A) (R) = ifma_half52_p256((A)) #define inv(R, A) (R) = ifma_aminv52_p256((A)) #define norm(R, A) (R) = ifma_norm52((A)) #define lnorm(R, A) (R) = ifma_lnorm52((A)) #define from_mont(R, A) (R) = ifma_frommont52_p256((A)) /* Aliases for dual operations */ #define mul_dual(R1, A1, B1, R2, A2, B2) ifma_amm52_dual_p256(&(R1), (A1), (B1), &(R2), (A2), (B2)) #define sqr_dual(R1, A1, R2, A2) ifma_ams52_dual_p256(&(R1), (A1), &(R2), (A2)) #define norm_dual(R1, A1, R2, A2) ifma_norm52_dual(&(R1), (A1), &(R2), (A2)) #define lnorm_dual(R1, A1, R2, A2) ifma_lnorm52_dual(&(R1), (A1), &(R2), (A2)) /* to affine coordinate */ IPP_OWN_DEFN(void, ifma_ec_nistp256_get_affine_coords, (m512 * rx, m512 *ry, const P256_POINT_IFMA *a)) { m512 z1, z2, z3; inv(z1, a->z); /* 1/z */ sqr(z2, z1); /* (1/z)^2 */ lnorm(z2, z2); /* x = x/z^2 */ if (NULL != rx) { mul(*rx, a->x, z2); /* x = x/z^2 */ lnorm(*rx, *rx); } /* y = y/z^3 */ if (NULL != ry) { mul(z3, z1, z2); /* (1/z)^3 */ lnorm(z3, z3); mul(*ry, a->y, z3); /* y = y/z^3 */ lnorm(*ry, *ry); } } IPP_OWN_DEFN(void, ifma_ec_nistp256_dbl_point, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p)) { /* * Enhanced Montgomery group algorithm described in [1]. * * l1 = 3x^2 + a*z^4 = [a = -3]= 3*(x^2 - z^4) = 3*(x - z^2)*(x + z^2) * z2 = 2*y*z * l2 = 4*x*y^2 * x2 = l1^2 - 2*l2 * l3 = 8*y^4 * y2 = l1*(l2 - x2) - l3 * */ const m512 *x1 = &p->x; const m512 *y1 = &p->y; const m512 *z1 = &p->z; m512 x2; m512 y2; m512 z2; x2 = y2 = z2 = setzero_i64(); m512 T, U, V, A, B, H; T = U = V = A = B = H = setzero_i64(); const m512 M2 = loadu_i64(p256_x2); const m512 M4 = loadu_i64(p256_x4); const m512 M8 = loadu_i64(p256_x8); add(T, *y1, *y1); /* T = 2*y1 */ lnorm(T, T); sqr_dual(V, T, /* V = 4*y1^2 */ U, *z1); /* U = z1^2 */ sub(B, *x1, U); /* B = x1 - z1^2 */ add(B, B, M2); add(U, *x1, U); /* U = x1 + z1^2 */ lnorm_dual(V, V, U, U); norm(B, B); mul_dual(A, V, *x1, /* A = 4*x1*y1^2 */ B, B, U); /* B = (x1 - z1^2)*(x1 + z1^2) */ add(x2, A, A); /* x2 = 8*x1*y1^2 */ add(H, B, B); add(B, B, H); /* B(l1) = 3*(x1 - z1^2)*(x1 + z1^2) */ lnorm(B, B); sqr_dual(U, B, /* U = l1^2 */ y2, V); /* y2 = 16*y^2 */ sub(x2, U, x2); /* x2 = l1^2 - 2*l2 */ add(x2, x2, M4); div2(y2, y2); sub(U, A, x2); /* U = l2 - x2 */ add(U, U, M8); norm(U, U); mul_dual(z2, T, *z1, /* z2 = 2*y1*z1 */ U, U, B); /* U = B(l1)*(A(l2) - x2) */ sub(y2, U, y2); /* y2 = B(l1)*(A(l2) - x2) - y2(l3) */ add(y2, y2, M2); norm_dual(r->x, x2, r->y, y2); lnorm(r->z, z2); } IPP_OWN_DEFN(void, ifma_ec_nistp256_add_point, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p, const P256_POINT_IFMA *q)) { /* * Enhanced Montgomery group algorithm described in [1]. * * A = x1*z2^2 B = x2*z1^2 C = y1*z2^3 D = y2*z1^3 * E = B - A F = D - C * x3 = -E^3 - 2*A*E^2 + F^2 * y3 = -C*E^3 + F*(A*E^2 - x3) * z3 = z1*z2*E */ const m512 *x1 = &p->x; const m512 *y1 = &p->y; const m512 *z1 = &p->z; const mask8 p_is_inf = is_zero_i64(p->z); const m512 *x2 = &q->x; const m512 *y2 = &q->y; const m512 *z2 = &q->z; const mask8 q_is_inf = is_zero_i64(q->z); m512 x3; m512 y3; m512 z3; x3 = y3 = z3 = setzero_i64(); const m512 M2 = loadu_i64(p256_x2); const m512 M4 = loadu_i64(p256_x4); const m512 M8 = loadu_i64(p256_x8); m512 U1, U2, S1, S2, H, R; U1 = U2 = S1 = S2 = H = R = setzero_i64(); mul_dual(S1, *y1, *z2, /* s1 = y1*z2 */ U1, *z2, *z2); /* u1 = z2^2 */ lnorm_dual(S1, S1, U1, U1); mul_dual(S2, *y2, *z1, /* s2 = y2*z1 */ U2, *z1, *z1); /* u2 = z1^2 */ lnorm_dual(S2, S2, U2, U2); mul_dual(S1, S1, U1, /* s1 = y1*z2^3 (C) */ S2, S2, U2); /* s2 = y2*z1^3 (D) */ lnorm_dual(S1, S1, S2, S2); mul_dual(U1, *x1, U1, /* u1 = x1*z2^2 (A) */ U2, *x2, U2); /* u2 = x2*z1^2 (B) */ lnorm_dual(U1, U1, U2, U2); sub(R, S2, S1); /* r = D - C (F) */ sub(H, U2, U1); /* h = B - A (E) */ /* checking the equality of X and Y coordinates (D - C == 0) and (B - A == 0) */ const mask8 f_are_zero = is_zero_i64(R); const mask8 e_are_zero = is_zero_i64(H); const mask8 point_is_equal = ((e_are_zero & f_are_zero) & (~p_is_inf) & (~q_is_inf)); __ALIGN64 P256_POINT_IFMA r2; r2.x = r2.y = r2.z = setzero_i64(); if ((mask8)0xFF == point_is_equal) { ifma_ec_nistp256_dbl_point(&r2, p); } add(R, R, M2); add(H, H, M2); norm_dual(R, R, H, H); mul_dual(z3, *z1, *z2, /* z3 = z1*z2 */ U2, H, H); /* u2 = E^2 */ lnorm_dual(z3, z3, U2, U2); mul_dual(z3, z3, H, /* z3 = (z1*z2)*E */ S2, R, R); /* s2 = F^2 */ mul(H, H, U2); /* h = E^3 */ lnorm(H, H); mul(U1, U1, U2); /* u1 = A*E^2 */ sub(x3, S2, H); /* x3 = F^2 - E^3 */ add(x3, x3, M2); add(U2, U1, U1); /* u2 = 2*A*E^2 */ mul(S1, S1, H); /* s1 = C*E^3 */ sub(x3, x3, U2); /* x3 = (F^2 - E^3) -2*A*E^2 */ add(x3, x3, M4); sub(y3, U1, x3); /* y3 = A*E^2 - x3 */ add(y3, y3, M8); norm(y3, y3); mul(y3, y3, R); /* y3 = F*(A*E^2 - x3) */ sub(y3, y3, S1); /* y3 = F*(A*E^2 - x3) - C*E^3 */ add(y3, y3, M2); norm_dual(x3, x3, y3, y3); lnorm(z3, z3); /* T = p_is_inf ? q : T */ x3 = mask_mov_i64(x3, p_is_inf, *x2); y3 = mask_mov_i64(y3, p_is_inf, *y2); z3 = mask_mov_i64(z3, p_is_inf, *z2); /* T = q_is_inf ? p : T */ x3 = mask_mov_i64(x3, q_is_inf, *x1); y3 = mask_mov_i64(y3, q_is_inf, *y1); z3 = mask_mov_i64(z3, q_is_inf, *z1); /* r = point_is_equal ? r2 : T */ x3 = mask_mov_i64(x3, point_is_equal, r2.x); y3 = mask_mov_i64(y3, point_is_equal, r2.y); z3 = mask_mov_i64(z3, point_is_equal, r2.z); r->x = x3; r->y = y3; r->z = z3; } IPP_OWN_DEFN(void, ifma_ec_nistp256_add_point_affine, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p, const P256_POINT_AFFINE_IFMA *q)) { /* * Enhanced Montgomery group algorithm described in [1]. * * A = x1 B = x2*z1^2 C = y1 D = y2*z1^3 * E = B - A(x1) F = D - C(y1) * x3 = -E^3 - 2*A(x1)*E^2 + F^2 * y3 = -C(y1)*E^3 + F*(A(x1)*E^2 - x3) * z3 = z1*E */ /* Coordinates of p (jacobian projective) */ const m512 *x1 = &p->x; const m512 *y1 = &p->y; const m512 *z1 = &p->z; const mask8 p_is_inf = is_zero_i64(p->z); /* Coordinates of q (affine) */ const m512 *x2 = &q->x; const m512 *y2 = &q->y; const mask8 q_is_inf = (is_zero_i64(q->x) & is_zero_i64(q->y)); const m512 M2 = loadu_i64(p256_x2); const m512 M4 = loadu_i64(p256_x4); const m512 M8 = loadu_i64(p256_x8); m512 x3, y3, z3; x3 = y3 = z3 = setzero_i64(); m512 U2, S2, H, R; U2 = S2 = H = R = setzero_i64(); mul_dual(R, *z1, *z1, /* R = z1^2 */ S2, *y2, *z1); /* S2 = y2*z1 */ lnorm_dual(R, R, S2, S2); mul_dual(U2, *x2, R, /* U2 = x2*z1^2 (B) */ S2, S2, R); /* S2 = y2*z1^3 (D) */ sub(H, U2, *x1); /* H = B - A (E) */ add(H, H, M8); sub(R, S2, *y1); /* R = D - C (F) */ add(R, R, M4); norm_dual(H, H, R, R); mul(z3, H, *z1); /* z3 = z1*E */ sqr_dual(U2, H, /* U2 = E^2 */ S2, R); /* S2 = F^2 */ lnorm(U2, U2); mul(H, H, U2); /* H = E^3 */ lnorm(H, H); mul_dual(U2, U2, *x1, /* U2 = A*E^2 */ y3, H, *y1); /* y3 = C*E^3 */ add(x3, U2, U2); /* x2 = 2*A*E^2 */ sub(x3, S2, x3); /* x3 = F^2 - 2*A*E^2 */ add(x3, x3, M4); sub(x3, x3, H); /* x3 = F^2 - 2*A*E^2 - E^3 */ add(x3, x3, M2); sub(U2, U2, x3); /* U2 = A*E^2 - x3 */ add(U2, U2, M8); norm(U2, U2); mul(U2, U2, R); /* U2 = F*(A*E^2 - x3) */ sub(y3, U2, y3); /* y3 = F*(A*E^2 - x3) - C*E^2 */ add(y3, y3, M2); norm_dual(x3, x3, y3, y3); lnorm(z3, z3); /* T = p_is_inf ? q : T */ x3 = mask_mov_i64(x3, p_is_inf, *x2); y3 = mask_mov_i64(y3, p_is_inf, *y2); z3 = mask_mov_i64(z3, p_is_inf, loadu_i64(p256_r)); /* T = q_is_inf ? p : T */ x3 = mask_mov_i64(x3, q_is_inf, *x1); y3 = mask_mov_i64(y3, q_is_inf, *y1); z3 = mask_mov_i64(z3, q_is_inf, *z1); r->x = x3; r->y = y3; r->z = z3; } IPP_OWN_DEFN(int, ifma_ec_nistp256_is_on_curve, (const P256_POINT_IFMA *p, const int use_jproj_coords)) { /* * y^2 = x^3 + a*x + b (1) * * if input * * Jacobian projective coordinate (x,y,z) reprepresented by (x/z^2,y/z^3,1) * * Affine coordinate -> (x/z^2,y/z^3,z/z=1) * * Mult (1) by z^6 * * y^2 = x^3 + a*x*z^4 + b*z^6 */ const m512 M6 = loadu_i64(p256_x6); const m512 a = loadu_i64(p256_a); const m512 b = loadu_i64(p256_b); m512 rh, Z4, Z6, tmp; rh = Z4 = Z6 = tmp = setzero_i64(); sqr(rh, p->x); /* rh = x^2 */ /* rh = x*(x^2 + a*z^4) + b*z^6 = x*(x^2 - 3*z^4) + b*z^6 */ if (0 != use_jproj_coords) { sqr(tmp, p->z); /* tmp = z^2 */ lnorm(tmp, tmp); sqr(Z4, tmp); /* z4 = z^4 */ lnorm(Z4,Z4); /* norm */ mul(Z6, Z4, tmp); /* z6 = z^6 */ lnorm(Z6,Z6); /* norm */ add(tmp, Z4, Z4); /* tmp = 2*z^4 */ add(tmp, tmp, Z4); /* tmp = 3*z^4 */ sub(rh, rh, tmp); /* rh = x^2 - 3*z^4 */ add(rh, rh, M6); norm(rh, rh); mul_dual(rh, rh, p->x, /* rh = x*(x^2 - 3*z^4) */ tmp, Z6, b); /* tmp = b*z^6 */ add(rh, rh, tmp); /* rh = x*(x^2 - 3*z^4) + b*z^6 */ } /* rh = x*(x^2 + a) + b */ else { add(rh, rh, a); /* rh = x^2 + a */ lnorm(rh, rh); mul(rh, rh, p->x); /* rh = x*(x^2 + a) */ add(rh, rh, b); /* rh = x*(x^2 + a) + b */ } lnorm(rh, rh); /* rl = Y^2 */ sqr(tmp, p->y); /* tmp = y^2 */ lnorm(tmp, tmp); /**/ /* from mont */ from_mont(tmp, tmp); from_mont(rh, rh); const mask8 mask = cmp_i64_mask(rh, tmp, _MM_CMPINT_EQ); return (mask == 0xFF) ? 1 : 0; } #undef add #undef sub #undef mul #undef sqr #undef div2 #undef norm #undef from_mont #undef mul_dual #undef sqr_dual #undef norm_dual static __NOINLINE void clear_secret_context(Ipp16u *wval, Ipp32s *chunk_no, Ipp32s *chunk_shift, Ipp8u *sign, Ipp8u *digit, P256_POINT_IFMA *R, P256_POINT_IFMA *H, P256_POINT_AFFINE_IFMA *A) { *wval = 0; *chunk_no = 0; *chunk_shift = 0; *sign = 0; *digit = 0; if (NULL != R) (*R).x = (*R).y = (*R).z = setzero_i64(); if (NULL != H) (*H).x = (*H).y = (*H).z = setzero_i64(); if (NULL != A) (*A).x = (*A).y = setzero_i64(); } #define WIN_SIZE (5) __IPPCP_INLINE mask8 is_eq_mask(const Ipp32s a, const Ipp32s b) { const Ipp32s eq = a ^ b; const Ipp32s v = ~eq & (eq - 1); const Ipp32s msb = 0 - (v >> (sizeof(a) * 8 - 1)); return (mask8)(0 - msb); } __IPPCP_INLINE void extract_table_point(P256_POINT_IFMA *r, const Ipp32s digit, const P256_POINT_IFMA *tbl) { Ipp32s idx = digit - 1; __ALIGN64 P256_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); for (Ipp32s n = 0; n < (1 << (WIN_SIZE - 1)); ++n) { const mask8 mask = is_eq_mask(n, idx); R.x = mask_mov_i64(R.x, mask, tbl[n].x); R.y = mask_mov_i64(R.y, mask, tbl[n].y); R.z = mask_mov_i64(R.z, mask, tbl[n].z); } r->x = R.x; r->y = R.y; r->z = R.z; } #define dbl_point ifma_ec_nistp256_dbl_point #define add_point ifma_ec_nistp256_add_point #define neg_coord ifma_neg52_p256 #define add_point_affine ifma_ec_nistp256_add_point_affine /* r = n*P = (P + P + ... + P) */ IPP_OWN_DEFN(void, ifma_ec_nistp256_mul_point, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p, const Ipp8u *pExtendedScalar, const int scalarBitSize)) { /* Precompute table */ __ALIGN64 P256_POINT_IFMA tbl[(1 << (WIN_SIZE - 1))]; __ALIGN64 P256_POINT_IFMA R; __ALIGN64 P256_POINT_IFMA H; R.x = R.y = R.z = setzero_i64(); H.x = H.y = H.z = setzero_i64(); m512 negHy = setzero_i64(); /* compute tbl[] = [n]P, n = 1, ... , 2^(win_size - 1) * tbl[2*n] = tbl[2*n - 1] + p * tbl[2*n + 1] = [2]*tbl[n] */ /* tbl[0] = p */ tbl[0].x = p->x; tbl[0].y = p->y; tbl[0].z = p->z; /* tbl[1] = [2]*p */ dbl_point(/* r = */ (tbl + 1), /* a = */ p); for (int n = 1; n < ((1 << (WIN_SIZE - 1)) / 2); ++n) { add_point((tbl + 2 * n), (tbl + 2 * n - 1), p); dbl_point((tbl + 2 * n + 1), (tbl + n)); } Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (WIN_SIZE + 1)) - 1); /* mask 0b111111 */ Ipp32s bit = scalarBitSize - (scalarBitSize % WIN_SIZE); Ipp32s chunk_no = (bit - 1) / 8; Ipp32s chunk_shift = (bit - 1) % 8; if (0 != bit) { wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); } else { wval = 0; } booth_recode(&sign, &digit, (Ipp8u)wval, WIN_SIZE); extract_table_point(&R, (Ipp32s)digit, tbl); for (bit -= WIN_SIZE; bit >= WIN_SIZE; bit -= WIN_SIZE) { dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, WIN_SIZE); extract_table_point(&H, (Ipp32s)digit, tbl); negHy = neg_coord(H.y); const mask8 mask_neg = (mask8)(~(sign - 1)); H.y = mask_mov_i64(H.y, mask_neg, negHy); add_point(&R, &R, &H); } /* last window */ dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif wval = *((Ipp16u *)(pExtendedScalar + 0)); wval = (Ipp16u)((wval << 1) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, WIN_SIZE); extract_table_point(&H, (Ipp32s)digit, tbl); negHy = neg_coord(H.y); const mask8 mask_neg = (mask8)(~(sign - 1)); H.y = mask_mov_i64(H.y, mask_neg, negHy); add_point(&R, &R, &H); r->x = R.x; r->y = R.y; r->z = R.z; /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, &H, NULL); return; } /* #include "gfpec/ecnist/ifma_ecprecomp4_p256.h" */ #include "gfpec/ecnist/ifma_ecprecomp7_p256.h" /* mul point base */ #define BP_WIN_SIZE BASE_POINT_WIN_SIZE #define BP_N_ENTRY BASE_POINT_N_ENTRY __IPPCP_INLINE void extract_point_affine(P256_POINT_AFFINE_IFMA *r, const P256_POINT_AFFINE_IFMA_MEM *tbl, const Ipp32s digit) { Ipp32s idx = digit - 1; m512 x, y; x = y = setzero_i64(); for (Ipp32s n = 0; n < (1 << ((BP_WIN_SIZE)-1)); ++n, ++tbl) { const mask8 mask = is_eq_mask(n, idx); x = mask_mov_i64(x, mask, maskz_loadu_i64(0x1f, tbl->X)); y = mask_mov_i64(y, mask, maskz_loadu_i64(0x1f, tbl->Y)); } r->x = x; r->y = y; } IPP_OWN_DEFN(void, p256r1_select_ap_w7_ifma, (BNU_CHUNK_T * pAffinePoint, const BNU_CHUNK_T *pTable, int index)) { __ALIGN64 P256_POINT_AFFINE_IFMA ap; extract_point_affine(&ap, (P256_POINT_AFFINE_IFMA_MEM *)pTable, index); ap.x = ifma_frommont52_p256(ap.x); ap.y = ifma_frommont52_p256(ap.y); convert_radix_to_64x4(pAffinePoint, ap.x); convert_radix_to_64x4(pAffinePoint + LEN64, ap.y); } IPP_OWN_DEFN(void, ifma_ec_nistp256_mul_pointbase, (P256_POINT_IFMA * r, const Ipp8u *pExtendedScalar, int scalarBitSize)) { /* precompute table */ const P256_POINT_AFFINE_IFMA_MEM *tbl = &ifma_ec_nistp256r1_bp_precomp[0][0]; __ALIGN64 P256_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); __ALIGN64 P256_POINT_AFFINE_IFMA A; A.x = A.y = setzero_i64(); m512 Ty = setzero_i64(); Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (BP_WIN_SIZE + 1)) - 1); /* mask 0b11111 */ Ipp32s bit = 0; Ipp32s chunk_no, chunk_shift; wval = *((Ipp16u *)(pExtendedScalar + 0)); wval = (Ipp16u)((wval << 1) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ Ty = neg_coord(A.y); mask8 mask_neg = (mask8)(~(sign - 1)); A.y = mask_mov_i64(A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); for (bit += BP_WIN_SIZE; bit <= scalarBitSize; bit += BP_WIN_SIZE) { chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ Ty = neg_coord(A.y); mask_neg = (mask8)(~(sign - 1)); A.y = mask_mov_i64(A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); } r->x = R.x; r->y = R.y; r->z = R.z; /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, NULL, &A); return; } #undef dbl_point #undef add_point #undef neg_coord #undef add_point_affine #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecpoint_p256.h000066400000000000000000000135611470420105600271720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ /* Paper referenced in this header: * * [1] "Enhanced Montgomery Multiplication" DOI:10.1155/2008/583926 * */ #ifndef IFMA_ECPOINT_P256_H #define IFMA_ECPOINT_P256_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p256.h" #include "pcpbnuimpl.h" /* p256 point (x,y,z) */ typedef struct { m512 x; m512 y; m512 z; } P256_POINT_IFMA; /* p256 affine point(x,y) */ typedef struct { m512 x; m512 y; } P256_POINT_AFFINE_IFMA; /** * \brief * * R = [pExtendedScalar]*P = (P + P + ... + P) * * \param[out] r point in radix 2^52 * \param[in] p point in radix 2^52 * \param[in] pExtendedScalar pointer to a scalar * \param[in] scalarBitSize scalar size in bits */ IPP_OWN_DECL(void, ifma_ec_nistp256_mul_point, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p, const Ipp8u *pExtendedScalar, const int scalarBitSize)) /** * \brief * * R = [pExtendedScalar]*BasePoint * * \param[out] r point in radix 2^52 * \param[in] pExtendedScalar pointer to a scalar * \param[in] scalarBitSize scalar size in bits */ IPP_OWN_DECL(void, ifma_ec_nistp256_mul_pointbase, (P256_POINT_IFMA * r, const Ipp8u *pExtendedScalar, int scalarBitSize)) /** * \brief * * Convert point to affine coordinate * * \param[out] rx X-affine coordinate * \param[out] ry Y-affine coordinate * \param[in] a point in projective coordinates */ IPP_OWN_DECL(void, ifma_ec_nistp256_get_affine_coords, (m512 * rx, m512 *ry, const P256_POINT_IFMA *a)) /** * \brief * * Check if the point is on curve p256r1 * * \param[in] p point in radix 2^52 * \param[in] use_jproj_coords flag whether coordinates are in Projective of Affine representation * \return int 1 - true * 0 - false */ IPP_OWN_DECL(int, ifma_ec_nistp256_is_on_curve, (const P256_POINT_IFMA *p, const int use_jproj_coords)) /** * \brief * * Point doubling on p256r1 curve (Enhanced Montgomery Algorithm, see [1]) * * \param[out] r point in projective coordinates * \param[in] p point in projective coordinates */ IPP_OWN_DECL(void, ifma_ec_nistp256_dbl_point, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p)) /** * \brief * * Point addition on p256r1 curve (Enhanced Montgomery Algorithm, see [1]) * * \param[out] r result point * \param[in] p first point * \param[in] q second point */ IPP_OWN_DECL(void, ifma_ec_nistp256_add_point, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p, const P256_POINT_IFMA *q)) /** * \brief * * Point addition on p256r1 curve (Enhanced Montgomery Algorithm, see [1]) * * \param[out] r point in projective coordinates * \param[in] p point in projective coordinates * \param[in] q point in affine coordinates */ IPP_OWN_DECL(void, ifma_ec_nistp256_add_point_affine, (P256_POINT_IFMA * r, const P256_POINT_IFMA *p, const P256_POINT_AFFINE_IFMA *q)) /** * \brief * * Extracts affine point from the precomputed table. * * \param[out] pAffinePoint array of x and y coordinates of affine point in 2^64 radix * \param[in] pTable pointer to a precomputed table * \param[in] index index of desired point in the table */ IPP_OWN_DECL(void, p256r1_select_ap_w7_ifma, (BNU_CHUNK_T * pAffinePoint, const BNU_CHUNK_T *pTable, int index)) #include "gfpec/ecnist/ifma_arith_method.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" __IPPCP_INLINE void recode_point_to_mont52(P256_POINT_IFMA *pR, const BNU_CHUNK_T *pP, BNU_CHUNK_T *pPool, ifmaArithMethod *method, gsModEngine *pME) { ifma_import to_radix52 = method->import_to52; ifma_encode p_to_mont = method->encode; const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T *pX = pPool; BNU_CHUNK_T *pY = pPool + elemLen; BNU_CHUNK_T *pZ = pPool + 2 * elemLen; GFP_METHOD(pME)->decode(pX, pP, pME); GFP_METHOD(pME)->decode(pY, pP + elemLen, pME); GFP_METHOD(pME)->decode(pZ, pP + 2 * elemLen, pME); pR->x = to_radix52((Ipp64u *)pX); pR->y = to_radix52((Ipp64u *)pY); pR->z = to_radix52((Ipp64u *)pZ); pR->x = p_to_mont(pR->x); pR->y = p_to_mont(pR->y); pR->z = p_to_mont(pR->z); } __IPPCP_INLINE void recode_point_to_mont64(IppsGFpECPoint *pR, P256_POINT_IFMA *pP, BNU_CHUNK_T *pPool, ifmaArithMethod *method, gsModEngine *pME) { ifma_export to_radix64 = method->export_to64; ifma_decode p_from_mont = method->decode; const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T *pX = pPool; BNU_CHUNK_T *pY = pPool + elemLen; BNU_CHUNK_T *pZ = pPool + 2 * elemLen; pP->x = p_from_mont(pP->x); pP->y = p_from_mont(pP->y); pP->z = p_from_mont(pP->z); to_radix64((Ipp64u *)pX, pP->x); to_radix64((Ipp64u *)pY, pP->y); to_radix64((Ipp64u *)pZ, pP->z); GFP_METHOD(pME)->encode(ECP_POINT_X(pR), pX, pME); GFP_METHOD(pME)->encode(ECP_POINT_Y(pR), pY, pME); GFP_METHOD(pME)->encode(ECP_POINT_Z(pR), pZ, pME); } #endif // (_IPP32E >= _IPP32E_K1) #endif // IFMA_ECPOINT_P256_H cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecpoint_p384.c000066400000000000000000000623441470420105600271720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_arith_p384.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" #define LEN64 (6) #define LEN52 (8) /* modulus 2*p */ static const __ALIGN64 Ipp64u p384_x2[LEN52] = { 0x00000001FFFFFFFE, 0x000FE00000000000, 0x000FFFFFFDFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000001FFFFF }; /* modulus 4*p */ static const __ALIGN64 Ipp64u p384_x4[LEN52] = { 0x00000003FFFFFFFC, 0x000FC00000000000, 0x000FFFFFFBFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000003FFFFF }; /* modulus 6*p */ static const __ALIGN64 Ipp64u p384_x6[LEN52] = { 0x00000005FFFFFFFA, 0x000FA00000000000, 0x000FFFFFF9FFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000005FFFFF }; /* modulus 8*p */ static const __ALIGN64 Ipp64u p384_x8[LEN52] = { 0x00000007FFFFFFF8, 0x000F800000000000, 0x000FFFFFF7FFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000007FFFFF }; /* mont(a) */ static const __ALIGN64 Ipp64u p384_a[LEN52] = { 0x000FFFFDFFFFFFFF, 0x000FF00000002FFF, 0x000FFFFFFBFFFFFF, 0x000FFFFFFFFFFFCF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x00000000000FFFFF }; /* mont(b) */ static const __ALIGN64 Ipp64u p384_b[LEN52] = { 0x00091C81CD08114B, 0x0003708118870D03, 0x000431BF24475444, 0x000209B1920022FC, 0x000E94938AE277F2, 0x000022094E3374BE, 0x000FF9B62B21F41F, 0x00000000000604FB }; /* Montgomery(1) * r = 2^(P384_LEN52*DIGIT_SIZE) mod p384 */ static const __ALIGN64 Ipp64u p384_r[LEN52] = { 0x0000000100000000, 0x000FFFFFFFFFF000, 0x0000000000FFFFFF, 0x0000000000000010, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 }; #define add(R, A, B) (R) = add_i64((A), (B)) #define sub(R, A, B) (R) = sub_i64((A), (B)) #define mul(R, A, B) (R) = ifma_amm52_p384((A), (B)) #define sqr(R, A) (R) = ifma_ams52_p384((A)) #define div2(R, A) (R) = ifma_half52_p384((A)) #define inv(R, A) (R) = ifma_aminv52_p384((A)) #define norm(R, A) (R) = ifma_norm52((A)) #define lnorm(R, A) (R) = ifma_lnorm52((A)) #define from_mont(R, A) (R) = ifma_frommont52_p384((A)) /* Dual mult/sqr/norm */ #define mul_dual(R1, A1, B1, R2, A2, B2) ifma_amm52_dual_p384(&(R1), (A1), (B1), &(R2), (A2), (B2)) #define sqr_dual(R1, A1, R2, A2) ifma_ams52_dual_p384(&(R1), (A1), &(R2), (A2)) #define norm_dual(R1, A1, R2, A2) ifma_norm52_dual(&(R1), (A1), &(R2), (A2)) #define lnorm_dual(R1, A1, R2, A2) ifma_lnorm52_dual(&(R1), (A1), &(R2), (A2)) /* to affine coordinate */ IPP_OWN_DEFN(void, ifma_ec_nistp384_get_affine_coords, (m512 * prx, m512 *pry, const P384_POINT_IFMA *a)) { m512 z1, z2, z3; z1 = z2 = z3 = setzero_i64(); inv(z1, a->z); /* 1/z */ sqr(z2, z1); /* (1/z)^2 */ lnorm(z2, z2); /**/ /* x = x/z^2 */ if (NULL != prx) { mul(*prx, a->x, z2); /* x = x/z^2 */ lnorm(*prx, *prx); /**/ } /* y = y/z^3 */ if (NULL != pry) { mul(z3, z1, z2); /* (1/z)^3 */ lnorm(z3, z3); /**/ mul(*pry, a->y, z3); /* y = y/z^3 */ lnorm(*pry, *pry); /**/ } return; } IPP_OWN_DEFN(void, ifma_ec_nistp384_dbl_point, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * Gueron (2002). Enhanced Montgomery Multiplication. * In Cryptographic Hardware and Embedded Systems - CHES 2002, * 4th International Workshop, Redwood Shores, CA, USA, * August 13-15, 2002, Revised Papers (pp. 46-56) * [ DOI: 10.1007/3-540-36400-5_5 ] * * l1 = 3x^2 + a*z^4 = (if p384 a = -3) = 3*(x^2 - z^4) = 3*(x - z^2)*(x + z^2) * z2 = 2*y*z * l2 = 4*x*y^2 * x2 = l1^2 - 2*l2 * l3 = 8*y^4 * y2 = l1*(l2 - x2) - l3 * * sum arithmetic: 8 mul; 9 add/sub; 1 div2. */ const m512 *x1 = &p->x; const m512 *y1 = &p->y; const m512 *z1 = &p->z; m512 x2; m512 y2; m512 z2; x2 = y2 = z2 = setzero_i64(); m512 T, U, V, A, B, H; T = U = V = A = B = H = setzero_i64(); const m512 M2 = loadu_i64(p384_x2); /* 2*p */ const m512 M4 = loadu_i64(p384_x4); /* 4*p */ const m512 M8 = loadu_i64(p384_x8); /* 8*p */ add(T, *y1, *y1); /* T = 2*y1 */ lnorm(T, T); /**/ /*=====*/ sqr_dual(V, T, /* V = 4*y1^2 */ U, *z1); /* U = z1^2 */ /*=====*/ sub(B, *x1, U); /* B = x1 - z1^2 */ add(B, B, M2); /**/ add(U, *x1, U); /* U = x1 + z1^2 */ /*=====*/ /* normalization */ lnorm_dual(V, V, /**/ U, U); /**/ norm(B, B); /**/ /*=====*/ mul_dual(A, V, *x1, /* A = 4*x1*y1^2 */ B, B, U); /* B = (x1 - z1^2)*(x1 + z1^2) */ /*=====*/ add(x2, A, A); /* x2 = 8*x1*y1^2 (4p) */ add(H, B, B); /**/ add(B, B, H); /* B(l1) = 3*(x1 - z1^2)*(x1 + z1^2) */ /*=====*/ /* normalization */ lnorm(B, B); /**/ /*=====*/ sqr_dual(U, B, /* U = l1^2 */ y2, V); /* y2 = 16*y^2 */ /*=====*/ /* normalization */ /*=====*/ sub(x2, U, x2); /* x2 = l1^2 - 2*l2 */ add(x2, x2, M4); /**/ div2(y2, y2); /**/ /*=====*/ sub(U, A, x2); /* U = l2 - x2 */ add(U, U, M8); /**/ /*=====*/ /* normalization */ norm(U, U); /**/ /*=====*/ mul_dual(z2, T, *z1, /* z2 = 2*y1*z1 */ U, U, B); /* U = B(l1)*(A(l2) - x2) */ /*=====*/ sub(y2, U, y2); /* y2 = B(l1)*(A(l2) - x2) - y2(l3) */ add(y2, y2, M2); /**/ /*=====*/ /* normalization */ norm_dual(r->x, x2, /**/ r->y, y2); /**/ lnorm(r->z, z2); /**/ return; } IPP_OWN_DEFN(void, ifma_ec_nistp384_add_point, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p, const P384_POINT_IFMA *q)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * Gueron (2002). Enhanced Montgomery Multiplication. * In Cryptographic Hardware and Embedded Systems - CHES 2002, * 4th International Workshop, Redwood Shores, CA, USA, * August 13-15, 2002, Revised Papers (pp. 46-56) * [ DOI: 10.1007/3-540-36400-5_5 ] * * A = x1*z2^2 B = x2*z1^2 C = y1*z2^3 D = y2*z1^3 * E = B - A F = D - C * x3 = -E^3 - 2*A*E^2 + F^2 * y3 = -C*E^3 + F*(A*E^2 - x3) * z3 = z1*z2*E */ const m512 *x1 = &p->x; const m512 *y1 = &p->y; const m512 *z1 = &p->z; const mask8 p_is_inf = is_zero_i64(p->z); const m512 *x2 = &q->x; const m512 *y2 = &q->y; const m512 *z2 = &q->z; const mask8 q_is_inf = is_zero_i64(q->z); m512 x3; m512 y3; m512 z3; x3 = y3 = z3 = setzero_i64(); const m512 M2 = loadu_i64(p384_x2); /* 2*p */ const m512 M4 = loadu_i64(p384_x4); /* 4*p */ const m512 M8 = loadu_i64(p384_x8); /* 8*p */ m512 U1, U2, S1, S2, H, R; U1 = U2 = S1 = S2 = H = R = setzero_i64(); mul_dual(S1, *y1, *z2, /* s1 = y1*z2 */ U1, *z2, *z2); /* u1 = z2^2 */ /*=====*/ /* normalization */ lnorm_dual(S1, S1, /**/ U1, U1); /**/ /*=====*/ mul_dual(S2, *y2, *z1, /* s2 = y2*z1 */ U2, *z1, *z1); /* u2 = z1^2 */ /*=====*/ /* normalization */ lnorm_dual(S2, S2, /**/ U2, U2); /**/ /*=====*/ mul_dual(S1, S1, U1, /* s1 = y1*z2^3 (C) */ S2, S2, U2); /* s2 = y2*z1^3 (D) */ /*=====*/ /* normalization */ lnorm_dual(S1, S1, /**/ S2, S2); /* (need by correct compute F = D - C) */ /*=====*/ mul_dual(U1, *x1, U1, /* u1 = x1*z2^2 (A) */ U2, *x2, U2); /* u2 = x2*z1^2 (B) */ /*=====*/ /* normalization */ lnorm_dual(U1, U1, /**/ U2, U2); /**/ /*=====*/ sub(R, S2, S1); /* r = D - C (F) */ sub(H, U2, U1); /* h = B - A (E) */ /* checking the equality of X and Y coordinates (D - C == 0) and (B - A == 0) */ const mask8 f_are_zero = is_zero_i64(R); const mask8 e_are_zero = is_zero_i64(H); const mask8 point_is_equal = ((e_are_zero & f_are_zero) & (~p_is_inf) & (~q_is_inf)); __ALIGN64 P384_POINT_IFMA r2; r2.x = r2.y = r2.z = setzero_i64(); if ((mask8)0xFF == point_is_equal) { ifma_ec_nistp384_dbl_point(&r2, p); } add(R, R, M2); /**/ add(H, H, M2); /**/ /*=====*/ /* normalization */ norm_dual(R, R, /**/ H, H); /**/ /**/ mul_dual(z3, *z1, *z2, /* z3 = z1*z2 */ U2, H, H); /* u2 = E^2 */ /*=====*/ /* normalization */ lnorm_dual(z3, z3, /**/ U2, U2); /**/ /**/ mul_dual(z3, z3, H, /* z3 = (z1*z2)*E */ S2, R, R); /* s2 = F^2 */ mul(H, H, U2); /* h = E^3 */ /*=====*/ /* normalization */ lnorm(H, H); /**/ /*=====*/ mul(U1, U1, U2); /* u1 = A*E^2 */ sub(x3, S2, H); /* x3 = F^2 - E^3 */ add(x3, x3, M2); /**/ add(U2, U1, U1); /* u2 = 2*A*E^2 */ mul(S1, S1, H); /* s1 = C*E^3 */ sub(x3, x3, U2); /* x3 = (F^2 - E^3) -2*A*E^2 */ add(x3, x3, M4); /**/ /*=====*/ sub(y3, U1, x3); /* y3 = A*E^2 - x3 */ add(y3, y3, M8); /**/ /*=====*/ /* normalization */ norm(y3, y3); /**/ /**/ mul(y3, y3, R); /* y3 = F*(A*E^2 - x3) */ sub(y3, y3, S1); /* y3 = F*(A*E^2 - x3) - C*E^3 */ add(y3, y3, M2); /* normalization */ norm_dual(x3, x3, /**/ y3, y3); /**/ lnorm(z3, z3); /**/ /* T = p_is_inf ? q : T */ x3 = mask_mov_i64(x3, p_is_inf, *x2); y3 = mask_mov_i64(y3, p_is_inf, *y2); z3 = mask_mov_i64(z3, p_is_inf, *z2); /* T = q_is_inf ? p : T */ x3 = mask_mov_i64(x3, q_is_inf, *x1); y3 = mask_mov_i64(y3, q_is_inf, *y1); z3 = mask_mov_i64(z3, q_is_inf, *z1); /* r = point_is_equal ? r2 : T */ x3 = mask_mov_i64(x3, point_is_equal, r2.x); y3 = mask_mov_i64(y3, point_is_equal, r2.y); z3 = mask_mov_i64(z3, point_is_equal, r2.z); r->x = x3; r->y = y3; r->z = z3; return; } IPP_OWN_DEFN(void, ifma_ec_nistp384_add_point_affine, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p, const P384_POINT_AFFINE_IFMA *q)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * Gueron (2002). Enhanced Montgomery Multiplication. * In Cryptographic Hardware and Embedded Systems - CHES 2002, * 4th International Workshop, Redwood Shores, CA, USA, * August 13-15, 2002, Revised Papers (pp. 46-56) * [ DOI: 10.1007/3-540-36400-5_5 ] * * A = x1 B = x2*z1^2 C = y1 D = y2*z1^3 * E = B - A(x1) F = D - C(y1) * x3 = -E^3 - 2*A(x1)*E^2 + F^2 * y3 = -C(y1)*E^3 + F*(A(x1)*E^2 - x3) * z3 = z1*E */ /* coordinates of p (jacobian projective) */ const m512 *x1 = &p->x; const m512 *y1 = &p->y; const m512 *z1 = &p->z; const mask8 p_is_inf = is_zero_i64(p->z); /* coordinate of q (affine) */ const m512 *x2 = &q->x; const m512 *y2 = &q->y; const mask8 q_is_inf = (is_zero_i64(q->x) & is_zero_i64(q->y)); const m512 M2 = loadu_i64(p384_x2); /* 2*p */ const m512 M4 = loadu_i64(p384_x4); /* 4*p */ const m512 M8 = loadu_i64(p384_x8); /* 8*p */ m512 x3, y3, z3; x3 = y3 = z3 = setzero_i64(); m512 U2, S2, H, R; U2 = S2 = H = R = setzero_i64(); mul_dual(R, *z1, *z1, /* R = z1^2 */ S2, *y2, *z1); /* S2 = y2*z1 */ /*=====*/ lnorm_dual(R, R, /**/ S2, S2); /**/ /*=====*/ mul_dual(U2, *x2, R, /* U2 = x2*z1^2 (B) */ S2, S2, R); /* S2 = y2*z1^3 (D) */ /**/ sub(H, U2, *x1); /* H = B - A (E) */ add(H, H, M8); /**/ sub(R, S2, *y1); /* R = D - C (F) */ add(R, R, M4); /**/ /*=====*/ norm_dual(H, H, /**/ R, R); /**/ /**/ mul(z3, H, *z1); /* z3 = z1*E */ /**/ sqr_dual(U2, H, /* U2 = E^2 */ S2, R); /* S2 = F^2 */ /**/ lnorm(U2, U2); /**/ /**/ mul(H, H, U2); /* H = E^3 */ /**/ lnorm(H, H); /**/ /**/ mul_dual(U2, U2, *x1, /* U2 = A*E^2 */ y3, H, *y1); /* y3 = C*E^3 */ /**/ add(x3, U2, U2); /* x2 = 2*A*E^2 */ sub(x3, S2, x3); /* x3 = F^2 - 2*A*E^2 */ add(x3, x3, M4); /**/ sub(x3, x3, H); /* x3 = F^2 - 2*A*E^2 - E^3 */ add(x3, x3, M2); /**/ /**/ sub(U2, U2, x3); /* U2 = A*E^2 - x3 */ add(U2, U2, M8); /**/ norm(U2, U2); /**/ mul(U2, U2, R); /* U2 = F*(A*E^2 - x3) */ sub(y3, U2, y3); /* y3 = F*(A*E^2 - x3) - C*E^2 */ add(y3, y3, M2); /**/ /* normalization */ norm_dual(x3, x3, /**/ y3, y3); /**/ lnorm(z3, z3); /**/ /* T = p_is_inf ? q : T */ x3 = mask_mov_i64(x3, p_is_inf, *x2); y3 = mask_mov_i64(y3, p_is_inf, *y2); z3 = mask_mov_i64(z3, p_is_inf, loadu_i64(p384_r)); /* T = q_is_inf ? p : T */ x3 = mask_mov_i64(x3, q_is_inf, *x1); y3 = mask_mov_i64(y3, q_is_inf, *y1); z3 = mask_mov_i64(z3, q_is_inf, *z1); r->x = x3; r->y = y3; r->z = z3; return; } IPP_OWN_DEFN(int, ifma_ec_nistp384_is_on_curve, (const P384_POINT_IFMA *p, const int use_jproj_coords)) { /* * Algorithm * * Gueron (2002). Enhanced Montgomery Multiplication. * In Cryptographic Hardware and Embedded Systems - CHES 2002, * 4th International Workshop, Redwood Shores, CA, USA, * August 13-15, 2002, Revised Papers (pp. 46-56) * [ DOI: 10.1007/3-540-36400-5_5 ] * * y^2 = x^3 + a*x + b (1) * * if input * * Jacobian projection coordinate (x,y,z) - represent by (x/z^2,y/z^3,1) * * Affine coordinate (x/z^2,y/z^3,z/z=1) * * mult formala (1) by z^6 * * y^2 = x^3 + a*x*z^4 + b*z^6 */ const m512 M6 = loadu_i64(p384_x6); const m512 a = loadu_i64(p384_a); const m512 b = loadu_i64(p384_b); m512 rh, Z4, Z6, tmp; rh = Z4 = Z6 = tmp = setzero_i64(); sqr(rh, p->x); /* rh = x^2 */ /* rh = x*(x^2 + a*z^4) + b*z^6 = x*(x^2 - 3*z^4) + b*z^6 */ if (0 != use_jproj_coords) { sqr(tmp, p->z); /* tmp = z^2 */ lnorm(tmp, tmp); /**/ /**/ sqr(Z4, tmp); /* z4 = z^4 */ lnorm(Z4, Z4); /**/ mul(Z6, Z4, tmp); /* z6 = z^6 */ lnorm(Z6, Z6); /**/ /**/ add(tmp, Z4, Z4); /* tmp = 2*z^4 */ add(tmp, tmp, Z4); /* tmp = 3*z^4 */ /**/ sub(rh, rh, tmp); /* rh = x^2 - 3*z^4 */ add(rh, rh, M6); /**/ norm(rh, rh); /**/ /**/ mul_dual(rh, rh, p->x, /* rh = x*(x^2 - 3*z^4) */ tmp, Z6, b); /* tmp = b*z^6 */ /**/ add(rh, rh, tmp); /* rh = x*(x^2 - 3*z^4) + b*z^6 */ } /* rh = x*(x^2 + a) + b */ else { add(rh, rh, a); /* rh = x^2 + a */ lnorm(rh, rh); /**/ mul(rh, rh, p->x); /* rh = x*(x^2 + a) */ add(rh, rh, b); /* rh = x*(x^2 + a) + b */ } lnorm(rh, rh); /**/ /* rl = Y^2 */ sqr(tmp, p->y); /* tmp = y^2 */ lnorm(tmp, tmp); /**/ /* from mont */ from_mont(tmp, tmp); from_mont(rh, rh); const mask8 mask = cmp_i64_mask(rh, tmp, _MM_CMPINT_EQ); return (mask == 0xFF) ? 1 : 0; } #undef add #undef sub #undef mul #undef sqr #undef div2 #undef norm #undef from_mont #undef mul_dual #undef sqr_dual #undef norm_dual static __NOINLINE void clear_secret_context(Ipp16u *wval, Ipp32s *chunk_no, Ipp32s *chunk_shift, Ipp8u *sign, Ipp8u *digit, P384_POINT_IFMA *R, P384_POINT_IFMA *H, P384_POINT_AFFINE_IFMA *A) { *wval = 0; *chunk_no = 0; *chunk_shift = 0; *sign = 0; *digit = 0; if (NULL != R) (*R).x = (*R).y = (*R).z = setzero_i64(); if (NULL != H) (*H).x = (*H).y = (*H).z = setzero_i64(); if (NULL != A) (*A).x = (*A).y = setzero_i64(); } #define WIN_SIZE (5) __IPPCP_INLINE mask8 is_eq_mask(const Ipp32s a, const Ipp32s b) { const Ipp32s eq = a ^ b; const Ipp32s v = ~eq & (eq - 1); const Ipp32s msb = 0 - (v >> (sizeof(a) * 8 - 1)); return (mask8)(0 - msb); } __IPPCP_INLINE void extract_table_point(P384_POINT_IFMA *r, const Ipp32s digit, const P384_POINT_IFMA *tbl) { Ipp32s idx = digit - 1; __ALIGN64 P384_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); for (Ipp32s n = 0; n < (1 << (WIN_SIZE - 1)); ++n) { const mask8 mask = is_eq_mask(n, idx); R.x = mask_mov_i64(R.x, mask, tbl[n].x); R.y = mask_mov_i64(R.y, mask, tbl[n].y); R.z = mask_mov_i64(R.z, mask, tbl[n].z); } r->x = R.x; r->y = R.y; r->z = R.z; } #define dbl_point ifma_ec_nistp384_dbl_point #define add_point ifma_ec_nistp384_add_point #define neg_coord ifma_neg52_p384 #define add_point_affine ifma_ec_nistp384_add_point_affine /* r = n*P = (P + P + ... + P) */ IPP_OWN_DEFN(void, ifma_ec_nistp384_mul_point, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p, const Ipp8u *pExtendedScalar, const int scalarBitSize)) { /* default params */ __ALIGN64 P384_POINT_IFMA tbl[(1 << (WIN_SIZE - 1))]; __ALIGN64 P384_POINT_IFMA R; __ALIGN64 P384_POINT_IFMA H; R.x = R.y = R.z = setzero_i64(); H.x = H.y = H.z = setzero_i64(); m512 negHy = setzero_i64(); /* compute tbl[] = [n]P, n = 1, ... , 2^(win_size - 1) * tbl[2*n] = tbl[2*n - 1] + p * tbl[2*n + 1] = [2]*tbl[n] */ /* tbl[0] = p */ tbl[0].x = p->x; tbl[0].y = p->y; tbl[0].z = p->z; /* tbl[1] = [2]*p */ dbl_point(/* r = */ (tbl + 1), /* a = */ p); for (int n = 1; n < ((1 << (WIN_SIZE - 1)) / 2); ++n) { add_point(/* r = */ (tbl + 2 * n), /* a = */ (tbl + 2 * n - 1), /* b = */ p); dbl_point(/* r = */ (tbl + 2 * n + 1), /* a = */ (tbl + n)); } Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (WIN_SIZE + 1)) - 1); /* mask 0b111111 */ Ipp32s bit = scalarBitSize - (scalarBitSize % WIN_SIZE); Ipp32s chunk_no = (bit - 1) / 8; Ipp32s chunk_shift = (bit - 1) % 8; if (0 != bit) { wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); } else { wval = 0; } booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, WIN_SIZE); extract_table_point(/* r = */ &R, /* digit = */ (Ipp32s)digit, /* tbl = */ tbl); for (bit -= WIN_SIZE; bit >= WIN_SIZE; bit -= WIN_SIZE) { dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, WIN_SIZE); extract_table_point(/* r = */ &H, /* idx = */ (Ipp32s)digit, /* tbl = */ tbl); negHy = neg_coord(H.y); const mask8 mask_neg = (mask8)(~(sign - 1)); H.y = mask_mov_i64(H.y, mask_neg, negHy); add_point(/* r = */ &R, /* a = */ &R, /* b = */ &H); } /* last window */ dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif wval = *((Ipp16u *)(pExtendedScalar + 0)); wval = (Ipp16u)((wval << 1) & mask); booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, WIN_SIZE); extract_table_point(/* r = */ &H, /* idx = */ (Ipp32s)digit, /* tbl = */ tbl); negHy = neg_coord(H.y); const mask8 mask_neg = (mask8)(~(sign - 1)); H.y = mask_mov_i64(H.y, mask_neg, negHy); add_point(/* r = */ &R, /* a = */ &R, /* b = */ &H); r->x = R.x; r->y = R.y; r->z = R.z; /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, &H, NULL); return; } #include "gfpec/ecnist/ifma_ecprecomp4_p384.h" /* mul point base */ #define BP_WIN_SIZE BASE_POINT_WIN_SIZE #define BP_N_ENTRY BASE_POINT_N_ENTRY __IPPCP_INLINE void extract_point_affine(P384_POINT_AFFINE_IFMA *r, const P384_POINT_AFFINE_IFMA_MEM *tbl, const Ipp32s digit) { Ipp32s idx = digit - 1; m512 x, y; x = y = setzero_i64(); for (Ipp32s n = 0; n < (1 << ((BP_WIN_SIZE)-1)); ++n, ++tbl) { const mask8 mask = is_eq_mask(n, idx); x = mask_mov_i64(x, mask, loadu_i64(tbl->X)); y = mask_mov_i64(y, mask, loadu_i64(tbl->Y)); } r->x = x; r->y = y; } IPP_OWN_DEFN(void, p384r1_select_ap_w4_ifma, (BNU_CHUNK_T * pAffinePoint, const BNU_CHUNK_T *pTable, int index)) { __ALIGN64 P384_POINT_AFFINE_IFMA ap; extract_point_affine(&ap, (P384_POINT_AFFINE_IFMA_MEM *)pTable, index); ap.x = ifma_frommont52_p384(ap.x); ap.y = ifma_frommont52_p384(ap.y); convert_radix_to_64x6(pAffinePoint, ap.x); convert_radix_to_64x6(pAffinePoint + LEN64, ap.y); } IPP_OWN_DEFN(void, ifma_ec_nistp384_mul_pointbase, (P384_POINT_IFMA * r, const Ipp8u *pExtendedScalar, int scalarBitSize)) { /* precompute table */ const P384_POINT_AFFINE_IFMA_MEM *tbl = &ifma_ec_nistp384r1_bp_precomp[0][0]; __ALIGN64 P384_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); __ALIGN64 P384_POINT_AFFINE_IFMA A; A.x = A.y = setzero_i64(); m512 Ty = setzero_i64(); Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (BP_WIN_SIZE + 1)) - 1); /* mask 0b11111 */ Ipp32s bit = 0; Ipp32s chunk_no, chunk_shift; wval = *((Ipp16u *)(pExtendedScalar + 0)); wval = (Ipp16u)((wval << 1) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ Ty = neg_coord(A.y); mask8 mask_neg = (mask8)(~(sign - 1)); A.y = mask_mov_i64(A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); for (bit += BP_WIN_SIZE; bit <= scalarBitSize; bit += BP_WIN_SIZE) { chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ Ty = neg_coord(A.y); mask_neg = (mask8)(~(sign - 1)); A.y = mask_mov_i64(A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); } r->x = R.x; r->y = R.y; r->z = R.z; /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, NULL, &A); return; } #undef dbl_point #undef add_point #undef neg_coord #undef add_point_affine #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecpoint_p384.h000066400000000000000000000135671470420105600272020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ /* Paper referenced in this header: * * [1] "Enhanced Montgomery Multiplication" DOI:10.1155/2008/583926 * */ #ifndef IFMA_ECPOINT_P384_H #define IFMA_ECPOINT_P384_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p384.h" #include "pcpbnuimpl.h" /* p384 point (x,y,z) */ typedef struct { m512 x; m512 y; m512 z; } P384_POINT_IFMA; /* p384 affine point(x,y) */ typedef struct { m512 x; m512 y; } P384_POINT_AFFINE_IFMA; /** * \brief * * R = [pExtendedScalar]*P = (P + P + ... + P) * * \param[out] r point in radix 2^52 * \param[in] p point in radix 2^52 * \param[in] pExtendedScalar pointer to a scalar * \param[in] scalarBitSize scalar size in bits */ IPP_OWN_DECL(void, ifma_ec_nistp384_mul_point, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p, const Ipp8u *pExtendedScalar, const int scalarBitSize)) /** * \brief * * R = [pExtendedScalar]*BasePoint * * \param[out] r point in radix 2^52 * \param[in] pExtendedScalar pointer to a scalar * \param[in] scalarBitSize scalar size in bits */ IPP_OWN_DECL(void, ifma_ec_nistp384_mul_pointbase, (P384_POINT_IFMA * r, const Ipp8u *pExtendedScalar, int scalarBitSize)) /** * \brief * * Convert point to affine coordinate * * \param[out] rx X-affine coordinate * \param[out] ry Y-affine coordinate * \param[in] a point in projective coordinates */ IPP_OWN_DECL(void, ifma_ec_nistp384_get_affine_coords, (m512 * rx, m512 *ry, const P384_POINT_IFMA *a)) /** * \brief * * Check if the point is on curve p384r1 * * \param[in] p point in radix 2^52 * \param[in] use_jproj_coords flag whether coordinates are in Projective of Affine representation * \return int 1 - true * 0 - false */ IPP_OWN_DECL(int, ifma_ec_nistp384_is_on_curve, (const P384_POINT_IFMA *p, const int use_jproj_coords)) /** * \brief * * Point doubling on p384r1 curve (Enhanced Montgomery Algorithm, see [1]) * * \param[out] r point in projective coordinates * \param[in] p point in projective coordinates */ IPP_OWN_DECL(void, ifma_ec_nistp384_dbl_point, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p)) /** * \brief * * Point addition on p384r1 curve (Enhanced Montgomery Algorithm, see [1]) * * \param[out] r result point * \param[in] p first point * \param[in] q second point */ IPP_OWN_DECL(void, ifma_ec_nistp384_add_point, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p, const P384_POINT_IFMA *q)) /** * \brief * * Point addition on p384r1 curve (Enhanced Montgomery Algorithm, see [1]) * * \param[out] r point in projective coordinates * \param[in] p point in projective coordinates * \param[in] q point in affine coordinates */ IPP_OWN_DECL(void, ifma_ec_nistp384_add_point_affine, (P384_POINT_IFMA * r, const P384_POINT_IFMA *p, const P384_POINT_AFFINE_IFMA *q)) /** * \brief * * Extracts affine point from the precomputed table. * * \param[out] pAffinePoint array of x and y coordinates of affine point in 2^64 radix * \param[in] pTable pointer to a precomputed table * \param[in] index index of desired point in the table */ IPP_OWN_DECL(void, p384r1_select_ap_w4_ifma, (BNU_CHUNK_T * pAffinePoint, const BNU_CHUNK_T *pTable, int index)) #include "gfpec/ecnist/ifma_arith_method.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" __IPPCP_INLINE void recode_point_to_mont52(P384_POINT_IFMA *pR, const BNU_CHUNK_T *pP, BNU_CHUNK_T *pPool, ifmaArithMethod *method, gsModEngine *pME) { ifma_import to_radix52 = method->import_to52; ifma_encode p_to_mont = method->encode; const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T *pX = pPool; BNU_CHUNK_T *pY = pPool + elemLen; BNU_CHUNK_T *pZ = pPool + 2 * elemLen; GFP_METHOD(pME)->decode(pX, pP, pME); GFP_METHOD(pME)->decode(pY, pP + elemLen, pME); GFP_METHOD(pME)->decode(pZ, pP + 2 * elemLen, pME); pR->x = to_radix52((Ipp64u *)pX); pR->y = to_radix52((Ipp64u *)pY); pR->z = to_radix52((Ipp64u *)pZ); pR->x = p_to_mont(pR->x); pR->y = p_to_mont(pR->y); pR->z = p_to_mont(pR->z); } __IPPCP_INLINE void recode_point_to_mont64(const IppsGFpECPoint *pR, P384_POINT_IFMA *pP, BNU_CHUNK_T *pPool, ifmaArithMethod *method, gsModEngine *pME) { ifma_export to_radix64 = method->export_to64; ifma_decode p_from_mont = method->decode; const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T *pX = pPool; BNU_CHUNK_T *pY = pPool + elemLen; BNU_CHUNK_T *pZ = pPool + 2 * elemLen; pP->x = p_from_mont(pP->x); pP->y = p_from_mont(pP->y); pP->z = p_from_mont(pP->z); to_radix64((Ipp64u *)pX, pP->x); to_radix64((Ipp64u *)pY, pP->y); to_radix64((Ipp64u *)pZ, pP->z); GFP_METHOD(pME)->encode(ECP_POINT_X(pR), pX, pME); GFP_METHOD(pME)->encode(ECP_POINT_Y(pR), pY, pME); GFP_METHOD(pME)->encode(ECP_POINT_Z(pR), pZ, pME); } #endif // (_IPP32E >= _IPP32E_K1) #endif // IFMA_ECPOINT_P384_H cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecpoint_p521.c000066400000000000000000000636521470420105600271660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_arith_p521.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" #include "gfpec/pcpgfpecstuff.h" #define add(R, A, B) fe521_add_no_red((R), (A), (B)) #define sub(R, A, B) fe521_sub_no_red((R), (A), (B)) #define mul(R, A, B) ifma_amm52_p521(&(R), (A), (B)) #define sqr(R, A) ifma_ams52_p521(&(R), (A)) #define div2(R, A) ifma_half52_p521(&(R), (A)) #define norm(R, A) ifma_norm52_p521(&(R), (A)) #define lnorm(R, A) ifma_lnorm52_p521(&(R), (A)) #define inv(R, A) ifma_aminv52_p521(&(R), (A)) #define from_mont(R, A) ifma_frommont52_p521(&(R), (A)) /* duplicate mult/sqr/norm */ #define mul_dual(R1, A1, B1, R2, A2, B2) ifma_amm52_dual_p521(&(R1), (A1), (B1), &(R2), (A2), (B2)) #define sqr_dual(R1, A1, R2, A2) ifma_ams52_dual_p521(&(R1), (A1), &(R2), (A2)) #define norm_dual(R1, A1, R2, A2) ifma_norm52_dual_p521(&(R1), (A1), &(R2), (A2)) #define lnorm_dual(R1, A1, R2, A2) ifma_lnorm52_dual_p521(&(R1), (A1), &(R2), (A2)) IPP_OWN_DEFN(void, ifma_ec_nistp521_get_affine_coords, (fe521 prx[], fe521 pry[], const P521_POINT_IFMA *a)) { fe521 z1, z2, z3; FE521_SET(z1) = FE521_SET(z2) = FE521_SET(z3) = m256_setzero_i64(); inv(z1, a->z); /* 1/z */ sqr(z2, z1); /* (1/z)^2 */ lnorm(z2, z2); /**/ /* x = x/z^2 */ if (NULL != prx) { mul(*prx, a->x, z2); /* x = x/z^2 */ lnorm(*prx, *prx); /**/ } /* y = y/z^3 */ if (NULL != pry) { mul(z3, z1, z2); /* (1/z)^3 */ lnorm(z3, z3); /**/ mul(*pry, a->y, z3); /* y = y/z^3 */ lnorm(*pry, *pry); /**/ } return; } IPP_OWN_DEFN(void, ifma_ec_nistp521_dbl_point, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * l1 = 3x^2 + a*z^4 = (if p384 a = -3) = 3*(x^2 - z^4) = 3*(x - z^2)*(x + z^2) * z2 = 2*y*z * l2 = 4*x*y^2 * x2 = l1^2 - 2*l2 * l3 = 8*y^4 * y2 = l1*(l2 - x2) - l3 * * sum aripmetic: 8 mul; 9 add/sub; 1 div2. */ const fe521 *x1 = &p->x; const fe521 *y1 = &p->y; const fe521 *z1 = &p->z; fe521 x2; fe521 y2; fe521 z2; FE521_SET(x2) = FE521_SET(y2) = FE521_SET(z2) = m256_setzero_i64(); fe521 T, U, V, A, B, H; FE521_SET(T) = FE521_SET(U) = FE521_SET(V) = m256_setzero_i64(); FE521_SET(A) = FE521_SET(B) = FE521_SET(H) = m256_setzero_i64(); fe521 M2, M4, M8; FE521_LOADU(M2, p521_x2); /* 2*p */ FE521_LOADU(M4, p521_x4); /* 4*p */ FE521_LOADU(M8, p521_x8); /* 8*p */ add(T, *y1, *y1); /* T = 2*y1 */ lnorm(T, T); /**/ /*=====*/ sqr_dual(V, T, /* V = 4*y1^2 */ U, *z1); /* U = z1^2 */ /*=====*/ sub(B, *x1, U); /* B = 2*p + x1 - z1^2 */ add(B, B, M2); /**/ add(U, *x1, U); /* U = x1 + z1^2 */ /*=====*/ /* normalization */ lnorm_dual(V, V, /**/ U, U); /**/ norm(B, B); /**/ /*=====*/ mul_dual(A, V, *x1, /* A = 4*x1*y1^2 */ B, B, U); /* B = (x1 - z1^2)*(x1 + z1^2) */ /*=====*/ add(x2, A, A); /* x2 = 8*x1*y1^2 (4p) */ add(H, B, B); /**/ add(B, B, H); /* B(l1) = 3*(x1 - z1^2)*(x1 + z1^2) */ /*=====*/ /* normalization */ lnorm(B, B); /**/ /*=====*/ sqr_dual(U, B, /* U = l1^2 */ y2, V); /* y2 = 16*y^2 */ /*=====*/ sub(x2, U, x2); /* x2 = 4*p + l1^2 - 2*l2 */ add(x2, x2, M4); /**/ div2(y2, y2); /**/ /*=====*/ sub(U, A, x2); /* U = 8*p + l2 - x2 */ add(U, U, M8); /**/ /*=====*/ /* normalization */ norm(U, U); /**/ /*=====*/ mul_dual(z2, T, *z1, /* z2 = 2*y1*z1 */ U, U, B); /* U = B(l1)*(A(l2) - x2) */ /*=====*/ sub(y2, U, y2); /* y2 = 2*p + B(l1)*(A(l2) - x2) - y2(l3) */ add(y2, y2, M2); /**/ /*=====*/ /* normalization */ norm_dual(r->x, x2, /**/ r->y, y2); /**/ lnorm(r->z, z2); /**/ return; } IPP_OWN_DEFN(void, ifma_ec_nistp521_add_point, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p, const P521_POINT_IFMA *q)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * A = x1*z2^2 B = x2*z1^2 C = y1*z2^3 D = y2*z1^3 * E = B - A F = D - C * x3 = -E^3 - 2*A*E^2 + F^2 * y3 = -C*E^3 + F*(A*E^2 - x3) * z3 = z1*z2*E */ const fe521 *x1 = &p->x; const fe521 *y1 = &p->y; const fe521 *z1 = &p->z; const mask8 p_is_inf = FE521_IS_ZERO(p->z); const fe521 *x2 = &q->x; const fe521 *y2 = &q->y; const fe521 *z2 = &q->z; const mask8 q_is_inf = FE521_IS_ZERO(q->z); fe521 x3; fe521 y3; fe521 z3; FE521_SET(x3) = FE521_SET(y3) = FE521_SET(z3) = m256_setzero_i64(); fe521 M2, M4, M8; FE521_LOADU(M2, p521_x2); /* 2*p */ FE521_LOADU(M4, p521_x4); /* 4*p */ FE521_LOADU(M8, p521_x8); /* 8*p */ fe521 U1, U2, S1, S2, H, R; FE521_SET(U1) = FE521_SET(U2) = FE521_SET(S1) = m256_setzero_i64(); FE521_SET(S2) = FE521_SET(H) = FE521_SET(R) = m256_setzero_i64(); mul_dual(S1, *y1, *z2, /* s1 = y1*z2 */ U1, *z2, *z2); /* u1 = z2^2 */ /*=====*/ /* normalization */ lnorm_dual(S1, S1, /**/ U1, U1); /**/ /*=====*/ mul_dual(S2, *y2, *z1, /* s2 = y2*z1 */ U2, *z1, *z1); /* u2 = z1^2 */ /*=====*/ /* normalization */ lnorm_dual(S2, S2, /**/ U2, U2); /**/ /*=====*/ mul_dual(S1, S1, U1, /* s1 = y1*z2^3 (C) */ S2, S2, U2); /* s2 = y2*z1^3 (D) */ /*=====*/ /* normalization */ lnorm_dual(S1, S1, /**/ S2, S2); /* (need by correct compute F = D - C) */ /*=====*/ mul_dual(U1, *x1, U1, /* u1 = x1*z2^2 (A) */ U2, *x2, U2); /* u2 = x2*z1^2 (B) */ /*=====*/ /* normalization */ lnorm_dual(U1, U1, /**/ U2, U2); /**/ /*=====*/ sub(R, S2, S1); /* r = D - C (F) */ sub(H, U2, U1); /* h = B - A (E) */ /* checking the equality of X and Y coordinates (D - C == 0) and (B - A == 0) */ const mask8 f_are_zero = FE521_IS_ZERO(R); const mask8 e_are_zero = FE521_IS_ZERO(H); const mask8 point_is_equal = ((e_are_zero & f_are_zero) & (~p_is_inf) & (~q_is_inf)); __ALIGN64 P521_POINT_IFMA r2; FE521_SET(r2.x) = FE521_SET(r2.y) = FE521_SET(r2.z) = m256_setzero_i64(); if ((mask8)0xFF == point_is_equal) { ifma_ec_nistp521_dbl_point(&r2, p); } add(R, R, M2); /**/ add(H, H, M2); /**/ /*=====*/ /* normalization */ norm_dual(R, R, /**/ H, H); /**/ /**/ mul_dual(z3, *z1, *z2, /* z3 = z1*z2 */ U2, H, H); /* u2 = E^2 */ /*=====*/ /* normalization */ lnorm_dual(z3, z3, /**/ U2, U2); /**/ /**/ mul_dual(z3, z3, H, /* z3 = (z1*z2)*E */ S2, R, R); /* s2 = F^2 */ mul(H, H, U2); /* h = E^3 */ /*=====*/ /* normalization */ lnorm(H, H); /**/ /*=====*/ mul(U1, U1, U2); /* u1 = A*E^2 */ sub(x3, S2, H); /* x3 = F^2 - E^3 */ add(x3, x3, M2); /**/ add(U2, U1, U1); /* u2 = 2*A*E^2 */ mul(S1, S1, H); /* s1 = C*E^3 */ sub(x3, x3, U2); /* x3 = (F^2 - E^3) -2*A*E^2 */ add(x3, x3, M4); /**/ /*=====*/ sub(y3, U1, x3); /* y3 = A*E^2 - x3 */ add(y3, y3, M8); /**/ /*=====*/ /* normalization */ norm(y3, y3); /**/ /**/ mul(y3, y3, R); /* y3 = F*(A*E^2 - x3) */ sub(y3, y3, S1); /* y3 = F*(A*E^2 - x3) - C*E^3 */ add(y3, y3, M2); /* normalization */ norm_dual(x3, x3, /**/ y3, y3); /**/ lnorm(z3, z3); /**/ /* T = p_is_inf ? q : T */ FE521_MASK_MOV(x3, x3, p_is_inf, *x2); FE521_MASK_MOV(y3, y3, p_is_inf, *y2); FE521_MASK_MOV(z3, z3, p_is_inf, *z2); /* T = q_is_inf ? p : T */ FE521_MASK_MOV(x3, x3, q_is_inf, *x1); FE521_MASK_MOV(y3, y3, q_is_inf, *y1); FE521_MASK_MOV(z3, z3, q_is_inf, *z1); /* r = point_is_equal ? r2 : T */ FE521_MASK_MOV(x3, x3, point_is_equal, r2.x); FE521_MASK_MOV(y3, y3, point_is_equal, r2.y); FE521_MASK_MOV(z3, z3, point_is_equal, r2.z); FE521_COPY(r->x, x3); FE521_COPY(r->y, y3); FE521_COPY(r->z, z3); return; } IPP_OWN_DEFN(void, ifma_ec_nistp521_add_point_affine, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p, const P521_POINT_AFFINE_IFMA *q)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * A = x1 B = x2*z1^2 C = y1 D = y2*z1^3 * E = B - A(x1) F = D - C(y1) * x3 = -E^3 - 2*A(x1)*E^2 + F^2 * y3 = -C(y1)*E^3 + F*(A(x1)*E^2 - x3) * z3 = z1*E */ /* coordinates of p (jacobian projective) */ const fe521 *x1 = &p->x; const fe521 *y1 = &p->y; const fe521 *z1 = &p->z; const mask8 p_is_inf = FE521_IS_ZERO(p->z); /* coordinate of q (affine) */ const fe521 *x2 = &q->x; const fe521 *y2 = &q->y; const mask8 q_is_inf = (FE521_IS_ZERO(q->x) & FE521_IS_ZERO(q->y)); fe521 x3; fe521 y3; fe521 z3; FE521_SET(x3) = FE521_SET(y3) = FE521_SET(z3) = m256_setzero_i64(); fe521 M2, M4, M8; FE521_LOADU(M2, p521_x2); /* 2*p */ FE521_LOADU(M4, p521_x4); /* 4*p */ FE521_LOADU(M8, p521_x8); /* 8*p */ fe521 U2, S2, H, R; FE521_SET(U2) = FE521_SET(S2) = FE521_SET(H) = FE521_SET(R) = m256_setzero_i64(); mul_dual(R, *z1, *z1, /* R = z1^2 */ S2, *y2, *z1); /* S2 = y2*z1 */ /*=====*/ lnorm_dual(R, R, /**/ S2, S2); /**/ /*=====*/ mul_dual(U2, *x2, R, /* U2 = x2*z1^2 (B) */ S2, S2, R); /* S2 = y2*z1^3 (D) */ /**/ sub(H, U2, *x1); /* H = B - A (E) */ add(H, H, M8); /**/ sub(R, S2, *y1); /* R = D - C (F) */ add(R, R, M4); /**/ /*=====*/ norm_dual(H, H, /**/ R, R); /**/ /**/ mul(z3, H, *z1); /* z3 = z1*E */ /**/ sqr_dual(U2, H, /* U2 = E^2 */ S2, R); /* S2 = F^2 */ /**/ lnorm(U2, U2); /**/ /**/ mul(H, H, U2); /* H = E^3 */ /**/ lnorm(H, H); /**/ /**/ mul_dual(U2, U2, *x1, /* U2 = A*E^2 */ y3, H, *y1); /* y3 = C*E^3 */ /**/ add(x3, U2, U2); /* x2 = 2*A*E^2 */ sub(x3, S2, x3); /* x3 = F^2 - 2*A*E^2 */ add(x3, x3, M4); /**/ sub(x3, x3, H); /* x3 = F^2 - 2*A*E^2 - E^3 */ add(x3, x3, M2); /**/ /**/ sub(U2, U2, x3); /* U2 = A*E^2 - x3 */ add(U2, U2, M8); /**/ norm(U2, U2); /**/ mul(U2, U2, R); /* U2 = F*(A*E^2 - x3) */ sub(y3, U2, y3); /* y3 = F*(A*E^2 - x3) - C*E^2 */ add(y3, y3, M2); /**/ /* normalization */ norm_dual(x3, x3, /**/ y3, y3); /**/ lnorm(z3, z3); /**/ fe521 ONE; FE521_LOADU(ONE, P521R1_R52); /* T = p_is_inf ? q : T */ FE521_MASK_MOV(x3, x3, p_is_inf, *x2); FE521_MASK_MOV(y3, y3, p_is_inf, *y2); FE521_MASK_MOV(z3, z3, p_is_inf, ONE); /* T = q_is_inf ? p : T */ FE521_MASK_MOV(x3, x3, q_is_inf, *x1); FE521_MASK_MOV(y3, y3, q_is_inf, *y1); FE521_MASK_MOV(z3, z3, q_is_inf, *z1); FE521_COPY(r->x, x3); FE521_COPY(r->y, y3); FE521_COPY(r->z, z3); return; } /* P521 mont(a) */ const static __ALIGN64 Ipp64u p512_a[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFE, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF }, { 0x000FFFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000 } }; /* P521R1 mont(b) */ const static __ALIGN64 Ipp64u p512_b[P521R1_NUM_CHUNK][P521R1_LENFE521_52] = { { 0x00014654FAE58638, 0x00028FEA35A81F80, 0x000C41E961A78F7A, 0x000DD8DF839AB9EF }, { 0x00049BD8B29605E9, 0x0000AB0C9CA8F63F, 0x0005A44C8C77884F, 0x00092DCCD98AF9DC }, { 0x0005B42A077516D3, 0x000E4D0FC94D10D0, 0x0000000000000000, 0x0000000000000000 } }; IPP_OWN_DEFN(int, ifma_ec_nistp521_is_on_curve, (const P521_POINT_IFMA *p, const int use_jproj_coords)) { /* * Algorithm * * y^2 = x^3 + a*x + b (1) * * if input * * Jacobian projection coordinate (x,y,z) - represent by (x/z^2,y/z^3,1) * * Affine coordinate (x/z^2,y/z^3,z/z=1) * * mult formala (1) by z^6 * * y^2 = x^3 + a*x*z^4 + b*z^6 */ fe521 M6; FE521_LOADU(M6, p521_x6); fe521 a, b; FE521_LOADU(a, p512_a); FE521_LOADU(b, p512_b); fe521 rh, Z4, Z6, tmp; FE521_SET(rh) = FE521_SET(Z4) = FE521_SET(Z6) = FE521_SET(tmp) = m256_setzero_i64(); sqr(rh, p->x); /* rh = x^2 */ /* rh = x*(x^2 + a*z^4) + b*z^6 = x*(x^2 - 3*z^4) + b*z^6 */ if (0 != use_jproj_coords) { sqr(tmp, p->z); /* tmp = z^2 */ lnorm(tmp, tmp); /**/ /**/ sqr(Z4, tmp); /* z4 = z^4 */ lnorm(Z4, Z4); /**/ mul(Z6, Z4, tmp); /* z6 = z^6 */ lnorm(Z6, Z6); /**/ /**/ add(tmp, Z4, Z4); /* tmp = 2*z^4 */ add(tmp, tmp, Z4); /* tmp = 3*z^4 */ /**/ sub(rh, rh, tmp); /* rh = x^2 - 3*z^4 */ add(rh, rh, M6); /**/ norm(rh, rh); /**/ /**/ mul_dual(rh, rh, p->x, /* rh = x*(x^2 - 3*z^4) */ tmp, Z6, b); /* tmp = b*z^6 */ /**/ add(rh, rh, tmp); /* rh = x*(x^2 - 3*z^4) + b*z^6 */ } /* rh = x*(x^2 + a) + b */ else { add(rh, rh, a); /* rh = x^2 + a */ lnorm(rh, rh); /**/ mul(rh, rh, p->x); /* rh = x*(x^2 + a) */ add(rh, rh, b); /* rh = x*(x^2 + a) + b */ } lnorm(rh, rh); /**/ /* rl = Y^2 */ sqr(tmp, p->y); /* tmp = y^2 */ lnorm(tmp, tmp); /**/ /* from mont */ from_mont(tmp, tmp); from_mont(rh, rh); const mask8 mask = FE521_CMP_MASK(rh, tmp, _MM_CMPINT_EQ); return (mask == 0xF) ? 1 : 0; } #undef add #undef sub #undef mul #undef sqr #undef div2 #undef norm #undef from_mont #undef mul_dual #undef sqr_dual #undef norm_dual static __NOINLINE void clear_secret_context(Ipp16u *wval, Ipp32s *chunk_no, Ipp32s *chunk_shift, Ipp8u *sign, Ipp8u *digit, P521_POINT_IFMA *R, P521_POINT_IFMA *H, P521_POINT_AFFINE_IFMA *A) { *wval = 0; *chunk_no = 0; *chunk_shift = 0; *sign = 0; *digit = 0; if (NULL != R) FE521_SET((*R).x) = FE521_SET((*R).y) = FE521_SET((*R).z) = m256_setzero_i64(); if (NULL != H) FE521_SET((*H).x) = FE521_SET((*H).y) = FE521_SET((*H).z) = m256_setzero_i64(); if (NULL != A) FE521_SET((*A).x) = FE521_SET((*A).y) = m256_setzero_i64(); return; } #define WIN_SIZE (5) __IPPCP_INLINE mask8 is_eq_mask(const Ipp32s a, const Ipp32s b) { const Ipp32s eq = a ^ b; const Ipp32s v = ~eq & (eq - 1); const Ipp32s msb = 0 - (v >> (sizeof(a) * 8 - 1)); return (mask8)(0 - msb); } __IPPCP_INLINE void extract_table_point(P521_POINT_IFMA *r, const Ipp32s digit, const P521_POINT_IFMA tbl[]) { Ipp32s idx = digit - 1; __ALIGN64 P521_POINT_IFMA R; FE521_SET(R.x) = FE521_SET(R.y) = FE521_SET(R.z) = m256_setzero_i64(); for (Ipp32s n = 0; n < (1 << (WIN_SIZE - 1)); ++n) { const mask8 mask = is_eq_mask(n, idx); FE521_MASK_MOV(R.x, R.x, mask, tbl[n].x); FE521_MASK_MOV(R.y, R.y, mask, tbl[n].y); FE521_MASK_MOV(R.z, R.z, mask, tbl[n].z); } FE521_COPY(r->x, R.x); FE521_COPY(r->y, R.y); FE521_COPY(r->z, R.z); } #define dbl_point ifma_ec_nistp521_dbl_point #define add_point ifma_ec_nistp521_add_point #define neg_coord(R, A) ifma_neg52_p521(&(R), (A)) #define add_point_affine ifma_ec_nistp521_add_point_affine /* r = n*P = (P + P + ... + P) */ IPP_OWN_DEFN(void, ifma_ec_nistp521_mul_point, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p, const Ipp8u *pExtendedScalar, const int scalarBitSize)) { /* default params */ __ALIGN64 P521_POINT_IFMA tbl[(1 << (WIN_SIZE - 1))]; __ALIGN64 P521_POINT_IFMA R; __ALIGN64 P521_POINT_IFMA H; fe521 negHy; FE521_SET(negHy) = m256_setzero_i64(); FE521_SET(R.x) = FE521_SET(R.y) = FE521_SET(R.z) = m256_setzero_i64(); FE521_SET(H.x) = FE521_SET(H.y) = FE521_SET(H.z) = m256_setzero_i64(); /* compute tbl[] = [n]P, n = 1, ... , 2^(win_size - 1) * tbl[2*n] = tbl[2*n - 1] + p * tbl[2*n + 1] = [2]*tbl[n] */ /* tbl[0] = p */ FE521_COPY(tbl[0].x, p->x); FE521_COPY(tbl[0].y, p->y); FE521_COPY(tbl[0].z, p->z); /* tbl[1] = [2]*p */ dbl_point(/* r = */ (tbl + 1), /* a = */ p); for (int n = 1; n < ((1 << (WIN_SIZE - 1)) / 2); ++n) { add_point(/* r = */ (tbl + 2 * n), /* a = */ (tbl + 2 * n - 1), /* b = */ p); dbl_point(/* r = */ (tbl + 2 * n + 1), /* a = */ (tbl + n)); } Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (WIN_SIZE + 1)) - 1); /* mask 0b111111 */ Ipp32s bit = scalarBitSize - (scalarBitSize % WIN_SIZE); Ipp32s chunk_no = (bit - 1) / 8; Ipp32s chunk_shift = (bit - 1) % 8; if (0 != bit) { wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); } else { wval = 0; } booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, WIN_SIZE); extract_table_point(/* r = */ &R, /* digit = */ (Ipp32s)digit, /* tbl = */ tbl); for (bit -= WIN_SIZE; bit >= WIN_SIZE; bit -= WIN_SIZE) { dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, WIN_SIZE); extract_table_point(/* r = */ &H, /* idx = */ (Ipp32s)digit, /* tbl = */ tbl); neg_coord(negHy, H.y); const mask8 mask_neg = (mask8)(~(sign - 1)); FE521_MASK_MOV(H.y, H.y, mask_neg, negHy); add_point(/* r = */ &R, /* a = */ &R, /* b = */ &H); } /* last window */ dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif wval = *((Ipp16u *)(pExtendedScalar + 0)); wval = (wval << 1) & mask; booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, WIN_SIZE); extract_table_point(/* r = */ &H, /* idx = */ (Ipp32s)digit, /* tbl = */ tbl); neg_coord(negHy, H.y); const mask8 mask_neg = (mask8)(~(sign - 1)); FE521_MASK_MOV(H.y, H.y, mask_neg, negHy); add_point(/* r = */ &R, /* a = */ &R, /* b = */ &H); FE521_COPY(r->x, R.x); FE521_COPY(r->y, R.y); FE521_COPY(r->z, R.z); /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, &H, NULL); return; } #include "gfpec/ecnist/ifma_ecprecomp4_p521.h" /* affine */ #define BP_WIN_SIZE BASE_POINT_WIN_SIZE #define BP_N_ENTRY BASE_POINT_N_ENTRY __IPPCP_INLINE void extract_point_affine(P521_POINT_AFFINE_IFMA *r, const P521_POINT_AFFINE_IFMA_MEM *tbl, const Ipp32s digit) { Ipp32s idx = digit - 1; fe521 x, y; FE521_SET(x) = FE521_SET(y) = m256_setzero_i64(); for (Ipp32s n = 0; n < (1 << ((BP_WIN_SIZE)-1)); ++n, ++tbl) { const mask8 mask = is_eq_mask(n, idx); /* x */ FE521_LO(x) = m256_mask_mov_i64(FE521_LO(x), mask, m256_loadu_i64(FE521_LO(tbl->x))); FE521_MID(x) = m256_mask_mov_i64(FE521_MID(x), mask, m256_loadu_i64(FE521_MID(tbl->x))); FE521_HI(x) = m256_mask_mov_i64(FE521_HI(x), mask, m256_loadu_i64(FE521_HI(tbl->x))); /* y */ FE521_LO(y) = m256_mask_mov_i64(FE521_LO(y), mask, m256_loadu_i64(FE521_LO(tbl->y))); FE521_MID(y) = m256_mask_mov_i64(FE521_MID(y), mask, m256_loadu_i64(FE521_MID(tbl->y))); FE521_HI(y) = m256_mask_mov_i64(FE521_HI(y), mask, m256_loadu_i64(FE521_HI(tbl->y))); } FE521_COPY(r->x, x); FE521_COPY(r->y, y); } IPP_OWN_DEFN(void, ifma_ec_nistp521_mul_pointbase, (P521_POINT_IFMA * r, const Ipp8u *pExtendedScalar, int scalarBitSize)) { /* precompute table */ const P521_POINT_AFFINE_IFMA_MEM *tbl = &ifma_ec_nistp521r1_bp_precomp[0][0]; __ALIGN64 P521_POINT_IFMA R; __ALIGN64 P521_POINT_AFFINE_IFMA A; fe521 Ty; FE521_SET(R.x) = FE521_SET(R.y) = FE521_SET(R.z) = m256_setzero_i64(); FE521_SET(A.x) = FE521_SET(A.y) = m256_setzero_i64(); FE521_SET(Ty) = m256_setzero_i64(); Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (BP_WIN_SIZE + 1)) - 1); /* mask 0b11111 */ Ipp32s bit = 0; Ipp32s chunk_no, chunk_shift; wval = *((Ipp16u *)(pExtendedScalar + 0)); wval = (Ipp16u)((wval << 1) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ neg_coord(Ty, A.y); mask8 mask_neg = (mask8)(~(sign - 1)); FE521_MASK_MOV(A.y, A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); for (bit += BP_WIN_SIZE; bit <= scalarBitSize; bit += BP_WIN_SIZE) { chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u *)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ neg_coord(Ty, A.y); mask_neg = (mask8)(~(sign - 1)); FE521_MASK_MOV(A.y, A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); } FE521_COPY(r->x, R.x); FE521_COPY(r->y, R.y); FE521_COPY(r->z, R.z); /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, NULL, &A); return; } #undef dbl_point #undef add_point #undef neg_coord #undef add_point_affine #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecpoint_p521.h000066400000000000000000000122271470420105600271630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ECPOINT_P521_H #define IFMA_ECPOINT_P521_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_defs_p521.h" typedef struct P521_POINT_IFMA { fe521 x; fe521 y; fe521 z; } P521_POINT_IFMA; typedef struct P521_POINT_AFFINE_IFMA { fe521 x; fe521 y; } P521_POINT_AFFINE_IFMA; /** * \brief * compute R = [pExtendedScalar]*P = (P + P + ... + P) * \param[out] r point (in radix 2^52) * \param[in] p point (in radix 2^52) * \param[in] pExtendedScalar ptr Extended scalar * \param[in] scalarBitSize size bits scalar */ IPP_OWN_DECL(void, ifma_ec_nistp521_mul_point, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p, const Ipp8u *pExtendedScalar, const int scalarBitSize)) /** * \brief * compute [pExtendedScalar]*BP * \param[out] r point (in radix 2^52) * \param pExtendedScalar ptr scaler (length 384 bits) */ IPP_OWN_DECL(void, ifma_ec_nistp521_mul_pointbase, (P521_POINT_IFMA * r, const Ipp8u *pExtendedScalar, int scalarBitSize)) /** * \brief * convert point to affine coordinate * \param[out] prx affine X coordinate * \param[out] pry affine Y coordinate * \param[in] a point */ IPP_OWN_DECL(void, ifma_ec_nistp521_get_affine_coords, (fe521 prx[], fe521 pry[], const P521_POINT_IFMA *a)) /** * \brief * check point on curve P521R1 * \param[in] p point (in radix 2^52) * \param[in] use_jproj_coords is Jacobian Projection coordinate or Affine Coordinate * \return int 1 - is true | 0 - is false */ IPP_OWN_DECL(int, ifma_ec_nistp521_is_on_curve, (const P521_POINT_IFMA *p, const int use_jproj_coords)) /** * \brief * compute double point P521R1 Enhanced Montgomery Algorithm * \param[out] r point * \param[in] p value point (in radix 2^52) */ IPP_OWN_DECL(void, ifma_ec_nistp521_dbl_point, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p)) /** * \brief * compute add point P384R1 Enhanced Montgomery Algorithm * \param[out] r point * \param[in] p first point (in radix 2^52) * \param[in] q second point (in radix 2^52) */ IPP_OWN_DECL(void, ifma_ec_nistp521_add_point, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p, const P521_POINT_IFMA *q)) /** * \brief * compute add point affine P384R1 Enhanced Montgomery Algorithm * \param[out] r point * \param[in] p first point (in radix 2^52) * \param[in] q second affine point (in radix 2^52) */ IPP_OWN_DECL(void, ifma_ec_nistp521_add_point_affine, (P521_POINT_IFMA * r, const P521_POINT_IFMA *p, const P521_POINT_AFFINE_IFMA *q)) #include "gfpec/ecnist/ifma_arith_method_p521.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" __IPPCP_INLINE void recode_point_to_mont52(P521_POINT_IFMA *pR, const BNU_CHUNK_T *pP, BNU_CHUNK_T *pPool, ifmaArithMethod_p521 *method, gsModEngine *pME) { ifma_import to_radix52 = method->import_to52; ifma_encode p_to_mont = method->encode; const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T *pX = pPool; BNU_CHUNK_T *pY = pPool + elemLen; BNU_CHUNK_T *pZ = pPool + 2 * elemLen; GFP_METHOD(pME)->decode(pX, pP, pME); GFP_METHOD(pME)->decode(pY, pP + elemLen, pME); GFP_METHOD(pME)->decode(pZ, pP + 2 * elemLen, pME); to_radix52(&(pR->x), (Ipp64u *)pX); to_radix52(&(pR->y), (Ipp64u *)pY); to_radix52(&(pR->z), (Ipp64u *)pZ); p_to_mont(&(pR->x), pR->x); p_to_mont(&(pR->y), pR->y); p_to_mont(&(pR->z), pR->z); } __IPPCP_INLINE void recode_point_to_mont64(IppsGFpECPoint *pR, P521_POINT_IFMA *pP, BNU_CHUNK_T *pPool, ifmaArithMethod_p521 *method, gsModEngine *pME) { ifma_export to_radix64 = method->export_to64; ifma_decode p_from_mont = method->decode; const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T *pX = pPool; BNU_CHUNK_T *pY = pPool + elemLen; BNU_CHUNK_T *pZ = pPool + 2 * elemLen; p_from_mont(&(pP->x), pP->x); p_from_mont(&(pP->y), pP->y); p_from_mont(&(pP->z), pP->z); to_radix64((Ipp64u *)pX, pP->x); to_radix64((Ipp64u *)pY, pP->y); to_radix64((Ipp64u *)pZ, pP->z); GFP_METHOD(pME)->encode(ECP_POINT_X(pR), pX, pME); GFP_METHOD(pME)->encode(ECP_POINT_Y(pR), pY, pME); GFP_METHOD(pME)->encode(ECP_POINT_Z(pR), pZ, pME); } #endif // (_IPP32E >= _IPP32E_K1) #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecprecomp4_p256.h000066400000000000000000003324231470420105600275730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if 0 #ifndef IFMA_ECPRECOMP4_P256_H #define IFMA_ECPRECOMP4_P256_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/pcpgfpecstuff.h" #define BASE_POINT_WIN_SIZE (4) #define BASE_POINT_N_ENTRY (1 << ((BASE_POINT_WIN_SIZE)-1)) #define OPERAND_BITSIZE (256) #define LEN52_P256 (NUMBER_OF_DIGITS(OPERAND_BITSIZE, DIGIT_SIZE)) /* P256 affine point */ typedef struct { BNU_CHUNK_T X[LEN52_P256]; BNU_CHUNK_T Y[LEN52_P256]; } P256_POINT_AFFINE_IFMA_MEM; extern const __ALIGN64 P256_POINT_AFFINE_IFMA_MEM ifma_ec_nistp256r1_bp_precomp[64][BASE_POINT_N_ENTRY]; #if !defined(_DISABLE_ECP_256R1_HARDCODED_BP_TBL_) /* Montgomery coefficient R = 2^(6*52) mod p */ const __ALIGN64 P256_POINT_AFFINE_IFMA_MEM ifma_ec_nistp256r1_bp_precomp[][BASE_POINT_N_ENTRY] = { { /* digit=0 (1,2,..,8)*(2^{0})*G */ {{0x0008905f76bdc7b5,0x0007bd418a9143c1,0x000c475d568abc1f,0x0009a701075ba95f,0x00003d1f32c8b4b9},{0x000571ff18aafa5c,0x000f757ce95560a8,0x000434a7e54432f7,0x0002797258b4ab8e,0x00009df870e37032}}, {{0x0006bb32e5348a6d,0x000d9d410ddd64df,0x0000ad784f985075,0x0008a23d9aa6ae3c,0x00001fb0f13f1e58},{0x0008c57751832101,0x00047d361bee1a57,0x000b725df8a6ac15,0x000e32cbe152cd7c,0x00008c240484bd0e}}, {{0x0006936a3fdd92de,0x00061904eebc1272,0x0009e1ea17bc2219,0x00038de98b027f84,0x0000be1daceb9daa},{0x0005f06a2abb7836,0x000261fc983a7ebd,0x000c327193eff4d4,0x000b6b38e583e47a,0x0000315e09d4065e}}, {{0x00077362f599237a,0x0003b0d46918dcc5,0x000d6eb05e7ddb8d,0x000ec90f24650a6e,0x0000604e8ac3b74e},{0x0004b14c39d10c04,0x000ee4ce4cbaba68,0x00017625a80d5c8a,0x000d1ce2e1762847,0x00009cb7c6eea514}}, {{0x0009079606520cb9,0x000d1aec45c61f5c,0x0009cbb1bd776c0e,0x0006a090c90ec649,0x0000ce1d21d8a47e},{0x0003a076bba1725f,0x0003c4ae7ba4f107,0x000f724b117049be,0x00007c06873c568e,0x0000d1631291cbdd}}, {{0x0003074b59672881,0x000c6373e77664a1,0x000f2165a2e4d910,0x000ef22ad55ae744,0x0000cd292bcbc0f3},{0x0004c9916deed188,0x000da20d377e44ba,0x000309358347a501,0x000921711299c2b5,0x0000cd3e2ccadf00}}, {{0x0003ba5119d6cc8f,0x000a64ea0173b4f1,0x0003be81afdd3079,0x000572c082bd2021,0x00001db750e89b35},{0x000aedd9165911e1,0x000ef303f5b9d4de,0x000172b8a2c6cf35,0x000b760956742f2f,0x00007d5db743c61e}}, {{0x000763891f69c8ac,0x000a0d19499a78fb,0x0004b837ab35be28,0x00064506b462ab5c,0x00002c41f6130b86},{0x0006ec12f2cdf2f2,0x000b1a9532d49775,0x000d78b2a72327aa,0x0006dc9f021e3327,0x00006889435a91f0}}, }, { /* digit=1 (1,2,..,8)*(2^{4})*G */ {{0x0004d63c80e5d9f3,0x00018650bc6fb805,0x0004eb27f1ea9ab1,0x000aa02495882e07,0x0000a466f2e5fb46},{0x0004edf7b266ddd9,0x00042d652a23f9b6,0x0008e61d6dd58c13,0x0007a359e3670c31,0x0000d257b443894a}}, {{0x0009227077a277a3,0x00059cfc5e3a3d83,0x000c07576f48364e,0x000355e97befd904,0x00001c25c29ce15c},{0x000231d792f7c39a,0x000a46ddbef42f56,0x0003e5d8c175121e,0x000d694407e449b6,0x00003711285e87b5}}, {{0x00084039030f437c,0x000c53077adc612c,0x0008f397ca9d5bf0,0x0004489bda749652,0x0000af611eeda45e},{0x0005efc7e9c72224,0x0007b66175adff18,0x000b31e8fdcd72d3,0x0007b51e30b26d7f,0x0000abe9a851e48b}}, {{0x0005fb8394ec96bc,0x000daf305968b809,0x000272a3f024eed6,0x0002f6201380a091,0x00005bd44243eed6},{0x000967204437eb69,0x000fc1280edfe2f2,0x000966478f3e6250,0x00056e2f88f726bb,0x0000b48e94ed5c40}}, {{0x0000bfffc5132382,0x0005a0752b3e584c,0x0007f5386a673608,0x0005a637335ff9aa,0x0000ee72d7a3789f},{0x000995919cce62b7,0x0000b2a1d49c6052,0x0005898b5a5e55c7,0x000be3d281b037d7,0x0000fcf783c6d6c3}}, {{0x0001eddf7fe28eb9,0x000d42333e12b701,0x000b07ef531b9d9c,0x0002d7c4d6d490a4,0x00008ce594304c88},{0x000f2a78b36344a4,0x000df28d87fd1d83,0x000cbdd7df5fbadb,0x000e518a2fd2f4f8,0x00002427ceb81118}}, {{0x0001704d00faa90e,0x000f7760a99cbca7,0x00059333dbf16feb,0x00089ac0c94e258f,0x000067cee41b4c7d},{0x0005000c252c9746,0x000650ef88b8b706,0x000e5b0ea5e2af00,0x0009f378056feb92,0x000066ae9a8c4350}}, {{0x000d311f2cf406c5,0x00006817a2ad62aa,0x0008ff31e0276fbf,0x000a6d8b57ef2b6b,0x0000437e1f6177bf},{0x000a38d321e63954,0x0002c87c2ff3b6df,0x00023c3f61ddd141,0x0009d5d38b46feaf,0x0000a9e4aaa74b8f}}, }, { /* digit=2 (1,2,..,8)*(2^{8})*G */ {{0x000c3da1963d1b37,0x00058fa696946fc7,0x00083d8e03d70b52,0x000d8231550fbc6d,0x0000c23f1ad7a853},{0x00099d49ebcaeaa8,0x00055b03cfd5d8b3,0x00024f00b2ba1b89,0x000385daa0704b7c,0x00003f881bb6342a}}, {{0x00042370d35642b3,0x000ce10399492969,0x000aa1fa40e1eea0,0x0002bfcf55b63827,0x00006300726619ca},{0x000dc61f92142820,0x0008f2ee0d985a17,0x000af47364dbdea2,0x0003af2f8192cc64,0x00009a126d8fb59a}}, {{0x0005d5bbfc230970,0x000353eed4c37174,0x000ef73916a712cd,0x0004acaa59f8240c,0x0000b069410109c2},{0x0004d5e0fcf149d6,0x000f673137fd28e3,0x000f92655f0108ba,0x000ab48f2862ac6e,0x00009efcb3eef840}}, {{0x000da26e1aec73e6,0x0009be144cc3adda,0x0005da1c14b462fc,0x000697e72d5ffa1d,0x00007dc85a835122},{0x0001c794b1a357c1,0x000661563483caaf,0x00083d98e34b8417,0x000eead3ce6924cd,0x0000cfb7382ae666}}, {{0x000a786d62a93d0d,0x0002b5c08369a907,0x000a9e9647958a75,0x000519f802990c59,0x000076b05f00e31d},{0x000b2ce9e430d6f9,0x000b4be20ac3a8dd,0x00007f8d434c0323,0x000cdfc6531a2178,0x00009e7647365eaa}}, {{0x000f3a8f9d8cc3f9,0x00072f38bd7aff18,0x000a8e4721a92651,0x00064b0151b5ee4c,0x00003b792b15a449},{0x000255f53b1b9da9,0x00010c9a0748be7d,0x0004d6d86ce4578c,0x00072ff371d391c9,0x0000702e661ee631}}, {{0x0008c889de2e32a8,0x000b0d474a861082,0x000fc583d3b1de17,0x0003aa480f8048a8,0x00003ee931e746ba},{0x0001c240230a2d47,0x0001f2eb214a040f,0x0007461ec3244db5,0x0007f2d8ae8c48e9,0x0000149fdf2f3f76}}, {{0x000c5fe1306bd6ce,0x00056b9eb7926b83,0x0003915e73d8d154,0x00006960bbff88cb,0x000076006a867f79},{0x000daf6b21ea15f4,0x0006ef43764fb3df,0x000733a24b0b851f,0x00086f1f37b5af31,0x000030c22394a5ed}}, }, { /* digit=3 (1,2,..,8)*(2^{12})*G */ {{0x000a20ed2a8c1c6f,0x00041e5ab4b35a24,0x0001abcdbda4db56,0x0003f26801d8b600,0x000004b48afeb9ed},{0x000a24142725a709,0x00053d44fec01e63,0x000c6ddb3c8679c1,0x000868efd3ed7ddc,0x0000203192c73ce6}}, {{0x00058ae74fac8317,0x0008162d5d721d5b,0x0002a648ba32d37d,0x0001fb6a40c3357a,0x0000d41eebd7ebce},{0x0007312ec0f21311,0x00009812e6dad6be,0x00010d0c3d9a387e,0x00083b3d8de28605,0x00000e56beae8107}}, {{0x000fb3a0d6a300fe,0x0006afeaae6ee702,0x0005264f0ff2ccae,0x00093072a78f4cc1,0x000056f1807ed1cb},{0x0002f775e441af97,0x000f83bb25a43ba1,0x000106f6b36db209,0x00000ca2a30bf803,0x0000b4aeb7054ee0}}, {{0x000161957d933aea,0x00028e76e6485b37,0x000b05babd7b6596,0x0000f456d4d3e24d,0x0000ce6abd42c3d5},{0x000aefa7aee9d873,0x0009f83cdb12a6c3,0x0001f36139b52f8a,0x0008e5973bf3fa88,0x0000e7a50e16b447}}, {{0x000497cd9642f15e,0x000a28037a929a9e,0x000d3566f9270405,0x000ba2d6265601a8,0x000064b1d8ef45cf},{0x000a573239e26ada,0x0005e7f9aa5b2f93,0x000f2d605dae4d62,0x000f28430e5faa3f,0x000025c3e2fb5346}}, {{0x0009b7e2c88699d1,0x000576bd17c24093,0x0003296e6ad3635b,0x0005cb70f2c4e479,0x00000b645230e891},{0x000c2f42b8f4bf96,0x0005122d096f4a9c,0x000af2a6a3deda09,0x0006383116861aec,0x000032eb61a73777}}, {{0x000707b18213a914,0x000b751d0a917b49,0x0002b19247af2039,0x000f9e2b6c2cfa3f,0x0000392f6ab1c9d5},{0x00021fa98a0d29bf,0x000e272d5f8b10d2,0x00052db4aaa0a8d8,0x0006faa92fd30783,0x00006bd9fc3c53d0}}, {{0x0003f63771beff8f,0x0006f623b36f9fd2,0x0003d9eb684ebab1,0x00084f3ef26543b2,0x000096ae77bc2ed6},{0x000fb89d795ff65e,0x0007796b6a1142e5,0x0005d3a20e91b4d9,0x00011bfd55ea6aac,0x0000a386dea94493}}, }, { /* digit=4 (1,2,..,8)*(2^{16})*G */ {{0x000564bade8d111c,0x00049fce3779ee34,0x000d77e4a2bf81f0,0x00017327ae00e7f9,0x0000f7675150c393},{0x0007f7ccb1668c80,0x000b12ac4708e8e4,0x000b5f26ce2e2a59,0x000dbcb9f4f5725f,0x0000c707f408fcd6}}, {{0x000dbde4ac826d0d,0x0007c0361a341c13,0x000fcf3f7c95b3aa,0x000c6246c3604dc5,0x0000ce46d1be3f02},{0x000f0d1f30affc92,0x0006a5d1c7eef696,0x000562423070d98e,0x0003f8fca5889680,0x00003b45ef942f70}}, {{0x000c9a9d2168c124,0x000671dbe7a2af37,0x0008d31cad5154da,0x000c67297ec51caa,0x0000f6a5ba0129fa},{0x00003937564cf036,0x000ae4f6ef5f0145,0x000298d331a9ca83,0x00051e01e8abcf41,0x0000803532cecc34}}, {{0x000688350470c6e0,0x000970977f7195ad,0x0006d7634e8b89f8,0x00088212d8ec8616,0x000043845130a44a},{0x000f5c2ee645cfc9,0x0005bf8309004c28,0x000584a3ba78a88d,0x0005275a4a96e4b7,0x000038c353982c77}}, {{0x0006877b288e2940,0x000f33959145a65f,0x000803b8e80eaf37,0x0006112a0cd9bc36,0x0000b81a72e0ba9f},{0x00040fa5a0fd54f6,0x0008b9bf5cbdb258,0x000859f95ca88625,0x00044185f2a4fd1d,0x0000bbdb6fce4677}}, {{0x0000d8b2dae7ca94,0x000fcb36b0cf82eb,0x0005753d030cfdc3,0x000d1805a6438d24,0x0000a53ea3da217e},{0x000afa8c8dcb9f12,0x000c8dbd9184c4d2,0x0005ce430ce88936,0x000756b473dbb18d,0x000096aae294c905}}, {{0x000dfe0d903a457a,0x0001207e3533d77b,0x000970360f08ec9b,0x000e84aedd7222e6,0x00008819a858ad52},{0x000eb874ec49378f,0x0000bb61d056605f,0x000587efe032d6ae,0x000c3fe8ca9ea9df,0x0000fbcf08ae31fe}}, {{0x00022a049341c337,0x00033a9bd7638026,0x00000306390eab7d,0x00022f7c4c21486a,0x0000d141475b8b86},{0x000540cb1b1be032,0x000da9dbb7a8ee0d,0x000b96c0e3c063f7,0x000de42ecdc2ed3b,0x0000397c62c0f6ec}}, }, { /* digit=5 (1,2,..,8)*(2^{20})*G */ {{0x000e6e2135aa3e34,0x000406a584c5e205,0x00015b6e4efffd6a,0x00016589b267e4ea,0x000028a50a289a0f},{0x000fef4e6229a8b1,0x0001b6a8c8f936e6,0x000445d2f37ab589,0x000b64a868af84d0,0x00002d1d526d0d0a}}, {{0x0005c78880bdb670,0x0001f09257226088,0x000a8d556d463880,0x000fe87ac131260d,0x0000a978da1cbb3c},{0x00081d1c0fbab2fc,0x00085ffc3bdf24eb,0x000b3da6a9989162,0x0009b73405bff75c,0x0000d9387ea82fe6}}, {{0x00091ae46f2b2572,0x000703d442a8ad11,0x000ced9edcf5c7ca,0x000e533e5c3816a7,0x0000d4bbe9bb1cb0},{0x000a4a73efeed78e,0x000f18700611c5bf,0x000704c62558948e,0x00091cb5283171ed,0x00000228300708db}}, {{0x0002b79aff1b7640,0x0003cc8f43a730f8,0x000bb0f3be0fe168,0x0008ce40be89b6f3,0x0000da60e29a2a91},{0x000b662498ee8663,0x000c556962fe5de3,0x000b255f6d5a6808,0x000a245580c590ad,0x0000e4d2e7887b5b}}, {{0x00031ec55d438d92,0x000bcd082dd1b6ad,0x000794983e52056e,0x000cfd8aa5783a13,0x00009f94d2983cbc},{0x00042b80509ea4d5,0x000fe3f8e9a76414,0x000cc5621e2a00e9,0x000e39f93625453e,0x0000b6fe3802944d}}, {{0x000414582cf35827,0x000a80d6c39765a2,0x000d882871de9e8b,0x0003d1450a2db3ac,0x000046f7d2fddbd8},{0x000672303b75f511,0x0007abc60eee9a8a,0x0001cc28700717f7,0x0003de4d554c79f0,0x00009aa79fb6b0ef}}, {{0x0006940f54c45508,0x000502d3bfab839b,0x000378f6cb89828a,0x0002513c392474e0,0x0000cd44686f1550},{0x000e788bf3109a0c,0x00082f2f2759f255,0x000948a168d333d9,0x000b6b7459dd9578,0x0000c7da7b3800f6}}, {{0x0004ff052f5917b5,0x000faa8719c05631,0x000ca760c26fde52,0x0005d57d3cd8ad2d,0x0000bd74588b7072},{0x0006ad71d02a024a,0x0003acf3e2d65208,0x00078da16339cd4e,0x000f011987ebdf0f,0x0000079790c922a9}}, }, { /* digit=6 (1,2,..,8)*(2^{24})*G */ {{0x000f5d55f460757a,0x0004ec4868af75df,0x000e466b71f6795b,0x0000c72b0d7325cf,0x0000e10c5f3da26c},{0x00094ad8a7522d79,0x000cc411977a0ee8,0x0004e8d5601f6c03,0x0001e3b955085c4c,0x000028f635d618a7}}, {{0x00066010689e1641,0x000f3b22c11bb373,0x000db6ec643ab5eb,0x000afb15d2d0366d,0x0000ab615f997250},{0x000b5f7e8a49c22d,0x000402c68d7b6d44,0x0008c124aab7be0b,0x000a684eea8f74f0,0x00006ee0d7c27a2d}}, {{0x00079739f7318d32,0x00027b21994ef202,0x00093bf3a921a053,0x000dc5e102a653b6,0x0000417acbe360fd},{0x000b40cff123155f,0x000073c8b799336a,0x000c74fb67fa3a8f,0x000c69c2dfdfdf14,0x00008baaad38eb7e}}, {{0x000984d8c0756da9,0x000f60b879fbbed4,0x000691183fa97cc8,0x00008c6450ff0ae8,0x0000bc7e3aa798e1},{0x0002c0087c8490da,0x000bba6d21008f03,0x0000075a13ccfa3b,0x000db76f329bd54a,0x0000cdfd68fa494d}}, {{0x00075553bbd18331,0x0005fabfbaf50a55,0x000b10f8b3952494,0x000f37f05df55e76,0x000083667f4aec1f},{0x0001b91149c64f10,0x0006ca3553afa736,0x000beb9cb1077179,0x000ef4d35315f3ff,0x0000724cdc42e0e8}}, {{0x0009f8db144f77e9,0x000026662b5f3af3,0x0000d0c25c1ff887,0x0007b73b1cefab56,0x0000cd5a1cf3f9ca},{0x000d5a818694755a,0x000725b3c61bfd60,0x000d33c6e57d6b39,0x000d8c2c2a5a4d41,0x0000da06aa84668d}}, {{0x000633d510319630,0x0000a4956f908239,0x000fdde9a26b1a49,0x000f5c760ba0f507,0x000011a47fccb3c1},{0x00074a4f6a780782,0x0003543b8c9de617,0x0003e69cf7b58be5,0x000c69ab2b475125,0x000059a05b225efc}}, {{0x00041b32e5ee0cd0,0x000bea601799a527,0x00014451f66c2b00,0x000f25a7ca20cec4,0x00001caa549ccc91},{0x000641caaadc47ea,0x00097814eb57d471,0x0004006d25c11bc5,0x000a4cb887a2d0ed,0x000005cf797f0540}}, }, { /* digit=7 (1,2,..,8)*(2^{28})*G */ {{0x000cf9a2f2b6ddb7,0x000cb4f20151427a,0x0005e5495f13c8bb,0x000336c57206828b,0x0000deb474abe52a},{0x000c630fc54290e0,0x000e9da279153564,0x0006b3bbef1e9949,0x00021a8e27e0734b,0x0000614b2885f690}}, {{0x0004ab68d7e959ee,0x000227a1ac2703b2,0x0008471ceedd9bdd,0x00080ded1b49258d,0x0000011c8d9a06d3},{0x0000b360f8d06cf6,0x000bfd4734e59d08,0x000843e26b87ae6b,0x000b0c3b35f8740c,0x0000b6d468726158}}, {{0x000ac1e3e5d6df58,0x000075d5fa067d1d,0x000ebba6b226d7b2,0x000af82ac4134b57,0x00001bb953caf0cd},{0x000cde538c8bc9c2,0x0003669d81fbb26c,0x000be58de047db86,0x0007841e8449ed3e,0x0000d643fef5794d}}, {{0x0003331d3c69f2bc,0x0000a8da61a76fa3,0x000d96e2379febe3,0x000486b9c598b441,0x0000390a58c27d0d},{0x000cdb9daf4c5417,0x0006d8e298de399d,0x0006c4c6e1a6e0f8,0x000649470cfdb8e7,0x0000690440cf3b0b}}, {{0x000cd3d0d4027b25,0x000d3c2019f2a596,0x00035e7beba07964,0x000164eddb3ce5bb,0x00000d8037d39488},{0x0000c29968554c2a,0x0009ad6efed021c1,0x000059b49a323da0,0x0003c9c4a09a9f9b,0x0000c0cc53fbad1c}}, {{0x000c73d2287162dd,0x000c529ed6e82ef1,0x00034977dd25e6f6,0x0004a8aae16f338e,0x0000dc61c21e5eed},{0x00096fe447e4eae7,0x0006a3174a5c8c7d,0x000fa5f9c92267ca,0x0007c117e01cd296,0x000068abc8039604}}, {{0x00041d6367599350,0x000706e88fbd3813,0x00042818412bda97,0x0005e6bcd02cd4a8,0x0000b40e707676fb},{0x0006fe0a3a3a6e7f,0x000d8fbd238202b9,0x000a1286e09fb174,0x000d4efa0600b4d1,0x00005566cd140a17}}, {{0x000246780b6116f2,0x00015367f636a38c,0x00064c305dbfeb38,0x0009f998b9f943fb,0x00002a4f058aaf47},{0x000300fadd2ed37d,0x00097156d549fc2b,0x0000ad7686ed0d31,0x00005d713c2953f3,0x0000c01130ae8caa}}, }, { /* digit=8 (1,2,..,8)*(2^{32})*G */ {{0x000953c50eb5331d,0x00069024147519ad,0x000b4d5fade16af5,0x00052cec8d0981ea,0x0000f785b3ffbbf2},{0x00063ebb7f24f144,0x0001dccfd590f8f8,0x000abea80d987872,0x000fa20cf72e9626,0x0000721e8be990fd}}, {{0x0009fb18a0fee18b,0x000f1f5678a31b0f,0x000d3f9d9d7f8899,0x0002e2896d50301a,0x0000467828ca24c1},{0x000a2f2a98bf1696,0x00042ebe8758851b,0x0005a36a8fac4075,0x000e6fdb71e64e4c,0x00002450761a46be}}, {{0x000b89a4e82f20ac,0x0005be0e90fb21e5,0x0000601e57b9726e,0x000acbbb500fd2b8,0x0000def3cf863f66},{0x000f548f31add03f,0x0006e3f894407ce5,0x00040ccdd200e1b3,0x00036823ba0025b9,0x000057161113964b}}, {{0x000379ae15e41fc7,0x0000ca7c35d87949,0x00076fdd0ccf2ac7,0x000135bfd042e655,0x00007cefff827780},{0x000b09f648a49efa,0x000b462fcc9981ea,0x0000c21f3e7dc01a,0x000af6bebaed3d63,0x0000701de9b6b9b9}}, {{0x000bdcfbd504057f,0x00054d331b85f091,0x000a8cadea75bdae,0x000e6d1fd0f45354,0x00002490dea9fe2b},{0x0000ac8047450e35,0x000f366cd5225391,0x00027062fa6c9f4b,0x000f7bd93fa9d473,0x0000df0d238b6d83}}, {{0x00004675e9e96a79,0x0009c366d91cd2c0,0x000ada5d7afaf95d,0x000d7678340a2bee,0x000031e43a7d6f3a},{0x000939ae632995b9,0x000f1ff840e446e0,0x000fe0f6e10f4eb2,0x0000641d99f9f258,0x000059714d33363a}}, {{0x000dac0c56b9c972,0x00003146fc627e20,0x000583ab2dfb01e8,0x000b8d1d5a0569bc,0x0000e9531ed3477b},{0x000c960233998e0f,0x00024b5da590d5fc,0x000311eb725dffaa,0x0003166d0a806780,0x00002e32acfedeb4}}, {{0x000a823a4160c545,0x000f51222248acc7,0x000eb7e2a9255142,0x00038a9281f6ec0e,0x0000f63c9cc1c2fa},{0x000efe9ed3f2c904,0x0002604e1900a791,0x000aaaefc6a23190,0x00095a14acde09d4,0x00007b2680ab6b58}}, }, { /* digit=9 (1,2,..,8)*(2^{36})*G */ {{0x000c47940a63bdc1,0x000acbe305406dd9,0x000f4115854d7ebc,0x000bf8c8f8eb7dc7,0x0000eebcc0956bd4},{0x00040deabe2974cf,0x0008c5d99b307781,0x00065a6b4bc494d8,0x0005271e325380c5,0x00006c75941c35b1}}, {{0x0003c3a8ea6b2c0c,0x0005526c49a861ec,0x00051d8b641c7fc2,0x0006ff017024f3b6,0x00006af90c54fe5b},{0x0006848b57a6af77,0x000fe2cb103d4c8d,0x0002bb9428138d50,0x000a1d94a02bc461,0x00005196aa6193cf}}, {{0x000f0e96b0521716,0x0006bdb1782269b6,0x0008b6894ea0436c,0x000213b53ae34bf7,0x0000f89e64dfb40d},{0x000020f0e5f7aa5e,0x000a41577884456e,0x000b89101dc1c7bf,0x0005074deb3b5688,0x0000322f52afaf0d}}, {{0x00039b66645c58c8,0x0007a8dbbe5a1a9a,0x000e8d8b5703704b,0x000b790268187fd5,0x000003b8f3f8d5eb},{0x000b2f3a4a4db66a,0x00074ef2d65a8087,0x000f193430cf1f8c,0x000a6ec4c4969044,0x0000c1c8991dfd8f}}, {{0x000b8888bb33c9a0,0x00038dd0f82b2148,0x0009657b430acfe7,0x0000dfe19460c34f,0x0000b39b6f7347e5},{0x000bf0221449dce2,0x00055dcc07226779,0x0008802bed13455f,0x0001abec610d21be,0x0000f48269445497}}, {{0x000dd04b97f56424,0x0001d60b7fe7b6e0,0x000a3239f41aa1f1,0x000c4a61e7d16189,0x000064bed27452ed},{0x00079b5499dfb43f,0x000fd9b506db8cc0,0x000ec79d2cb2ca13,0x0009706e65cd47aa,0x00001dff152d73d6}}, {{0x000aa7cb935a507d,0x000551ae0ac29416,0x0004582b4da3a965,0x0007915d0279b025,0x00008622b071bf70},{0x00035a70c90666d4,0x00051800d37c7a50,0x000730d2e35953b1,0x0006c1b9213380c3,0x00008f95b8909dcf}}, {{0x0003fba6baaee763,0x000548571ba18615,0x000c7ccd5282a222,0x0004c589348b22d5,0x0000c343e640ecd7},{0x000d50cd542a5f8c,0x000f1f3e5eea7d82,0x00063b79a4045592,0x0000f8e05521c879,0x000038b6e3d1e7a4}}, }, { /* digit=10 (1,2,..,8)*(2^{40})*G */ {{0x0005910a01f9dd2f,0x0003e65533ef2177,0x00044e3924858ec2,0x0004e12677158c7e,0x0000817fb332f9e2},{0x0009f8be4c5579ed,0x000d207cf88577d2,0x0000ba656c829dbc,0x0002850852224525,0x0000a45a5a5d4127}}, {{0x0006aebf577abd9d,0x00015452133ffd9d,0x0000ac605ac980fc,0x000e4582a39a8b2f,0x00004eec5aa7265a},{0x000045d5cf88aa51,0x00029cb76ccdac60,0x000c15412957a97b,0x000342cd1af4d36e,0x0000e6170f039470}}, {{0x000f32ef99cc6085,0x000bc4351facc618,0x000d57573622f8bd,0x00097ededbaf2647,0x0000f2cc80070643},{0x00034049491087f9,0x0004f8c7593cbd4c,0x000c3f77e662b98a,0x000634616ed266c5,0x00002b5777286404}}, {{0x0008c8bf5c4dddf3,0x000e274c005979da,0x0001c17823f45915,0x00004f9f9c2072b4,0x0000aaa1baf4fa40},{0x0001cb9e28458fbd,0x0002855114df14a7,0x000d8bfa4e43521f,0x000189718d4374a4,0x0000a04910e166e7}}, {{0x000ca7b94abcb8cf,0x0009802094704963,0x000daf2a7eca4d08,0x000247498a489a5e,0x0000e144eefa19d2},{0x0008666e16797254,0x00009682ad636a41,0x0004f075f107c2c6,0x0002fc5436702702,0x0000b46d254bc836}}, {{0x0002b2a3e2819447,0x000b6350369c8e10,0x0002b729e058e5fe,0x0006e9bab9271aa6,0x00006605f347cecb},{0x000ced0cf5b648e5,0x000fe5f0e2b379be,0x000be9659e2ffbdd,0x0000d1c063d3de39,0x00006c7602acd385}}, {{0x000aa397878c7fdc,0x000d8ca2a604b3b7,0x0003bfbdcfdab93e,0x0000ba46e56f6518,0x000008070b9ee90b},{0x000ff6976d6bc06b,0x000412a0e01fabc4,0x0004d387028c757f,0x00060b4fe7c6ee8a,0x00005840dd588099}}, {{0x00032caa306d36d2,0x0007e7903605c397,0x000e2e161f3c1bd9,0x0005b6484f0843d9,0x0000c3ed7e7103a9},{0x0002e9423a811470,0x000527061160170e,0x000b6096786931d4,0x000d933acc32788c,0x000040d7f8af5425}}, }, { /* digit=11 (1,2,..,8)*(2^{44})*G */ {{0x0001682c10b4b42c,0x00049455922ac1c3,0x000c73c31352d93e,0x0002a2bc4a7b3ef5,0x00009c11c3b203bd},{0x000c092172b4577e,0x000a6f04bd55d319,0x00057bacfaff1310,0x0004d8a9db6d1c08,0x0000b14a2965910e}}, {{0x000910b95bc8d4b3,0x0009d35ea6c39976,0x000a5950529391f9,0x000ac2a3954259aa,0x0000954edcb4e373},{0x000982812f18224f,0x000a61043e09aee6,0x000f3de4d536e4c0,0x000508c61ced56c9,0x000097bf82337dc0}}, {{0x000fc9cdf0a602a7,0x0000f90768fccfce,0x000cc86be572242c,0x000fb55cef402d37,0x00007fc53399e03c},{0x00038fa2f84181fd,0x0002e72d1669a8bc,0x000b93e529c4e96f,0x000b28a0e33c536b,0x0000c1aea47311b9}}, {{0x000e413c023b543e,0x000ff931341ed7a4,0x000c597461477da5,0x0006486a44223272,0x0000e62ade1b4548},{0x00073540e59ce025,0x0006c27e17e44ceb,0x00047c7e6d15d0b9,0x000ca71caee86bf7,0x000062dc3b140088}}, {{0x000bd5ca4b43dca6,0x000b875b2c69dbcc,0x000837ee1021381f,0x000b45c713aa77a2,0x0000a05614cbf186},{0x0006c5c5b213f9f3,0x00065076db476cb9,0x0001c871dd6ccdd0,0x000210116fde15d6,0x00006771cf226ee0}}, {{0x0001dde5dfbb6e3a,0x000b56c872b4a606,0x0003e4356c3c10e2,0x000cfdbd1ab2a34a,0x0000f1935615b0dc},{0x000bfd9fd4818329,0x000cd219f2275f33,0x0006091fe9776294,0x0002d94aa0750c8b,0x000091bb35d3e4f7}}, {{0x0009529ca84f2105,0x000db2adb22b94b8,0x0009189807b37871,0x000fd1763993d8ae,0x000032507bd52b7d},{0x0006d1b1faa44f66,0x0007daae572a2530,0x0007fbd06d00887f,0x000f39d58e02b643,0x0000ff4486cf7424}}, {{0x000977faf2fd74af,0x00010abaf95894c5,0x0006cdf3274ead88,0x00068f58b7b9bdc0,0x0000d28ef6376f5e},{0x000d37fa9f638299,0x000a9ef052c4b5b7,0x0000893d97515b4d,0x0006fb5c79fe87f7,0x0000baaee7122abf}}, }, { /* digit=12 (1,2,..,8)*(2^{48})*G */ {{0x000e4daa4cf03ebf,0x000a5880a750c0f3,0x00031006e436dc3b,0x000d2500539bacfe,0x0000d4ef32a1291b},{0x000a444f665140ba,0x0002db55ffc69ff6,0x000c27c0e1c0d5f3,0x000e2259446f147b,0x0000e26f578ece85}}, {{0x000392f2ec04cd39,0x0000d5ac3f16ea83,0x000d7f5ede30754d,0x0009b6872115a461,0x00008418a223a967},{0x000fc5ff44240c84,0x00018cde526cdc7f,0x000b22632c3da39d,0x000c70d988e537fd,0x0000709b1f542582}}, {{0x0007f2ec2dc98f00,0x00016f4bdaedfbdc,0x000fbe8180bfa37c,0x000bc3e1723fd325,0x0000f58d97310235},{0x00064f972387d213,0x0001ff245104b0d2,0x000b879a945ab636,0x00029e80f5f00daf,0x0000fd8b684b4312}}, {{0x0008d2c9ae428f00,0x0004f7ea90567e6d,0x0006dddb93095522,0x00081903d513257b,0x0000d1ef01808e5c},{0x000ffa707b56bdd1,0x000c2246b29cb44f,0x000c77ce5b30e21c,0x000d3bd42b540a21,0x0000c8f28344b9aa}}, {{0x000eec41cb82328d,0x00015f3e30bc27ff,0x0009b1972345ec7f,0x000331e0ee5f0c05,0x000087d0ba66f3c7},{0x000ae59616536a6e,0x000025f99d0b09f8,0x000669480fe3c760,0x000e84b31c5d6cc5,0x0000ee121b26c778}}, {{0x000c41d1ca8f6911,0x000d2f1d4e353b7b,0x00043304ded57d7b,0x000e262fd062d8a1,0x0000c7373014e0c7},{0x000d825d0c68baec,0x000f5e76be77800a,0x000717e2f324cc7d,0x000e0471a71fe8b3,0x00007ed811a51502}}, {{0x000a2679405d4a59,0x0005c7b39f8868a8,0x0003eba5f06f98ea,0x0008af06ee27f4fd,0x0000bf77a2388b73},{0x000dcc46466ccfdf,0x000bc72fa30f349b,0x0008f8ca8aee594a,0x000b0c7d194c9d9c,0x0000db282f8561eb}}, {{0x00067b085c91370d,0x000d35b1cb76219d,0x00009adb7621c58b,0x0008dbc100ec0bf9,0x000035a1c37429d0},{0x000539991832fa6f,0x00095595e93a96a9,0x000a66a28b826cbe,0x000e29cb77526c1e,0x0000acab05a94fb9}}, }, { /* digit=13 (1,2,..,8)*(2^{52})*G */ {{0x00096e6d076e5fb1,0x000e067ceca9754a,0x0005a20acc991594,0x000e01fbf426d2cf,0x0000e8ea47274e03},{0x0003439dd70f73cd,0x000dbdd87880e616,0x000581c546fe37f4,0x0004291151554381,0x000076b608169ba2}}, {{0x000be5a560218c0f,0x0002245983c38b5e,0x000b7795172b6411,0x000736ce6b14f176,0x0000b95d3a653da9},{0x00090806472dd13c,0x000e1cd9f87dc596,0x000392d3ef194f1a,0x00019f6577c595cd,0x000044201d70daf9}}, {{0x000a4bf3535ca72f,0x000398eadd70482e,0x000990fe5b370e05,0x000e33fef708de92,0x000095e812192018},{0x0004f0f83a164ec7,0x000582c87912868c,0x00052a18313ff9b5,0x000a4bf0ab1b1be9,0x0000846b0bf28b93}}, {{0x0003043896a03a07,0x0004b381d531696e,0x000fa5c9a5d318fa,0x0004ca8c757201bf,0x00003e9b1ef0bafa},{0x0000bf7978610e72,0x0004fe18555970de,0x0008447619e614fa,0x00020318b8267dfa,0x00002d551502ded1}}, {{0x00020ab732d47663,0x000a19f16a66e918,0x0000781056db02b9,0x000d5c5eae97f282,0x000094939d8bd05b},{0x000b2c87b6265c14,0x0008af9287144234,0x000a628484fc8c50,0x0002a90cc54ecfff,0x0000ff62b0d3b8d2}}, {{0x0000f30fee8c3f0a,0x000134286d2e0f86,0x0001ad978fe6de9b,0x0004d1149e592012,0x0000ed2e1530c0e4},{0x0008c9d2519e343d,0x0007006858e6a61a,0x00069709a27ec803,0x00054a1fbce4c776,0x0000b72f3fb5dbd3}}, {{0x000c5a4b66e99b1a,0x000a6965f5206989,0x000da89d6d7224d3,0x000bf4eb9640631f,0x0000b4e03e0395b9},{0x000436d53d463c5d,0x000f7bf80b6783d1,0x000e25fb34d34e57,0x000cddcb280e701f,0x000018bf1fde0cd3}}, {{0x0008e7dd3da6ac7a,0x0007068c094dbb56,0x000e7080f6d2bb87,0x00006862db77d062,0x0000957c36387eb2},{0x000c48a3b41f412c,0x0002b40013a5e585,0x0006e05598676e41,0x000588aab2131174,0x0000a5cfa92af35d}}, }, { /* digit=14 (1,2,..,8)*(2^{56})*G */ {{0x000b63b80c17b3a5,0x0009991991724f36,0x000bce681e7aafdd,0x00021571e5eda799,0x0000608a0582bb4c},{0x0001f37958fc7a0f,0x000ed697e5fb5166,0x000a6efe500b7226,0x0002f1da5737708b,0x0000d330af0a0615}}, {{0x0001d5f271b2ffcd,0x000ce2caa6650728,0x00046dfd327de7f3,0x00027f03178322fa,0x0000216e3f0e2310},{0x00003bbfc59abb34,0x000d842f48027f5b,0x000bd4fb27522c72,0x0007b690faa40cdb,0x0000abded9d9b492}}, {{0x0002c6f30c43f226,0x0009e180d738ded3,0x0000ae17641d02b6,0x000b5f0756f1a5bb,0x0000e1022d63ad47},{0x000709b3807f334a,0x000c89dd8fffb620,0x0007ad500b84f625,0x000081d766a281b4,0x0000baefeb53ba7b}}, {{0x000e8143ae4b352e,0x0008432a3326505c,0x00021f9bfe1140f1,0x000adfcfa38d6927,0x000034810d2f90b4},{0x0000bf0d00ef8992,0x0002ffa7e6ab6665,0x000fd1695563a3a5,0x000ad66ed6cd2d22,0x0000bbe464cbfd77}}, {{0x0000824eeec7168a,0x000ce52877a21ec5,0x0006bed12ba5446b,0x000931ca2300414a,0x0000eeb5b0f5515a},{0x000322d64e381de0,0x0001cecf83cba5d5,0x000840921d7268be,0x000d46dd7f953814,0x00002b466f4b1410}}, {{0x000bd6a7d881d987,0x000ec843d9325f3b,0x0000379b23abd56a,0x00044afc5a9bef2d,0x00004a3dd4f7b324},{0x00032b0b1e2614cb,0x000de028f61bc0b8,0x000ceba5ab839425,0x00059b798f49085e,0x00003b2eafe5b888}}, {{0x00020cf3f9601768,0x0005c47f1f0ced18,0x00031285e9324320,0x0008926fa800cc79,0x000017299d89245e},{0x00019c8dbe5b7b2e,0x00054dc1c0f7d133,0x00005341590ca39e,0x0007e40e3ef92196,0x00008544b679b3ea}}, {{0x0006e673cd25c857,0x000e1717b82b99b6,0x000ce0284257ae21,0x000cd7d6675922d4,0x0000134e48cf8715},{0x00020fa3844dead5,0x00092c4b5f2b89a4,0x0005e6feb94f1d13,0x0001f55da3de9c1e,0x0000bf9802bd31e3}}, }, { /* digit=15 (1,2,..,8)*(2^{60})*G */ {{0x000a6b62d93fdd41,0x00055796424c49b9,0x0007cd56def02492,0x000194a49f888dfe,0x0000f9869f29b9e5},{0x000f96a765fed464,0x0004e6d179483cb7,0x0002157b537c82e0,0x00066411f666f963,0x00007c51bf707ed6}}, {{0x00083fd5597eef8d,0x000467c051af62b9,0x000a73b96f3d0664,0x000e60da1e9a998e,0x00006cc734074631},{0x000f6191644596a8,0x00018ca65d698049,0x000dcf446dc950da,0x00041ba3b732b22d,0x0000e67d9922451a}}, {{0x00021487098d3893,0x00021e0bdefdd4f1,0x0005e1525cf8642f,0x000032bc06995846,0x00002ad5c774a21a},{0x00067f595255747a,0x000b83318969006d,0x000e0b7efa7ee217,0x00097c961cb4d73c,0x00007cde45c8bbbd}}, {{0x00054660dbc8b1ab,0x000d6088cad38c0b,0x000fb6902a066a7d,0x000dc7ca3471b7e8,0x0000e86a1789d644},{0x00095173a8f8b220,0x000fe11a6fd8de44,0x000a5a2626461987,0x000b8a17c44dbffe,0x000097f4a165ced5}}, {{0x0008066addda0cdd,0x0005a434573eab0b,0x000b19a5f5541137,0x000d0bdfd11570df,0x00000f19e0267d6a},{0x0006506ae95d526b,0x000bfd8f8a3f0b44,0x00099a5c77b8b8a6,0x0006120809e0e489,0x00003bd4cf0ac49d}}, {{0x000426d74951de36,0x00033f78fca399da,0x00015de0e419f0bc,0x000aabf82fe9e27d,0x0000b79a1cbd8d35},{0x000f1d0d57258a2f,0x0002d02ca81c66da,0x0006f614c6cdf2df,0x0007519ba84fb8d2,0x00009db0a7aaffb9}}, {{0x000baef6bff2b941,0x0005465352c4b5c2,0x00012d5ccd22674c,0x000b65e5f4926153,0x00005b47a9bf6203},{0x000db83c64adc010,0x000ea6509ed3561b,0x0002da92e6a83a26,0x0008ccc691137023,0x00007a1159393722}}, {{0x00013e2c380a9bf2,0x000364d391c2a82a,0x00027444dcb0941f,0x00055fbcabcdd486,0x0000ff69ccdcb479},{0x00052b540c86a1b2,0x000a4f04a057a87a,0x000001893b8ba415,0x000c36a44a876550,0x00000e23c958c1e1}}, }, { /* digit=16 (1,2,..,8)*(2^{64})*G */ {{0x000f5e69622c79cf,0x00060c516a0d2bb2,0x000beb03cb372318,0x0004c5d8b0d5cc16,0x0000e18f5d34d82b},{0x000648f91783b808,0x000bf0bf5a01797f,0x000c6a4c687ad85d,0x00067d3523d20b44,0x00009192002a1f83}}, {{0x0003271e6c831d51,0x00077b8fac61d9a1,0x0002d09fe01d7f5f,0x000a2a4037d25e06,0x000064507e385362},{0x000ea6041214d255,0x00051c0232f76a55,0x000d1178f014410a,0x00037fc788957c32,0x000085a49edcb98c}}, {{0x000f3338ee1c0299,0x000f84bb5def9961,0x0003040a98f9248d,0x0003ac5761cb69c8,0x000000beb921e57f},{0x00066c038dfaec8c,0x000d10d2f5378a8d,0x00065894c993b6fc,0x000735690acf4c2c,0x00003b9318cab2f0}}, {{0x000e0341bd6ee336,0x000102bb4d8bc50a,0x0005fb1615b32bf2,0x0005df468181c0b1,0x000049acb4f25f09},{0x0002c9d27e3d254d,0x000f8cf7003e8666,0x000a275ad19d7996,0x00026d7c2f11a6de,0x0000e62e628f9c93}}, {{0x000a5ff674823c2b,0x0000030614c09004,0x000172a0cbd7525d,0x0008894a1da98d12,0x000030b72f8253fc},{0x000c72e27f2e7888,0x0000eb81d7ea1d7e,0x00029433ef893a49,0x00053356e38cf289,0x0000353f5c728ab5}}, {{0x000b6b6e1ca760d8,0x0007f19a8afd30bb,0x0007cf16ffb18b25,0x0004823e08679832,0x0000efcafa52751d},{0x0002beaaf58337ec,0x0006f11471f1ff0f,0x0008cb570ffa8731,0x0005ed83ed76c338,0x00004c92081ca03b}}, {{0x0000aaee181a2a7a,0x000ff32b88756ddc,0x000230d35049ce8e,0x000b74aa4ed4e865,0x0000261c5ca08124},{0x000d55e8ca475a13,0x000dab96c168af3a,0x000f0644ffaace6a,0x00053a1366563c7b,0x00008a47ff05a4d9}}, {{0x000f835f9d0aad8a,0x000272e523b8bf60,0x000b800dac7dffa3,0x00068eb888009eb5,0x00005af05fd9e53f},{0x00029d4c6fdd401d,0x0000c312afceb620,0x000a13ffebd0185b,0x0006be5b0c797df2,0x00003ac5e2304089}}, }, { /* digit=17 (1,2,..,8)*(2^{68})*G */ {{0x0000b1d093f471bb,0x0006510f5b343bcf,0x000a023f726a643d,0x000ed90df0f2e400,0x00003c3843aa4ab3},{0x0000bb7742e67add,0x0003e95c70816030,0x00093cfe99544825,0x000be16a6e943e4c,0x0000792d7df86acd}}, {{0x0009c15b35bafc8c,0x000bc1b7bfe71786,0x000dfb7efd32fb77,0x0008ffa7d4e1deba,0x00001f575658ec09},{0x000e07633366d529,0x000ed66368710884,0x000cc4194ecbd474,0x00068764de5e29f5,0x0000a864508101bc}}, {{0x0002009d82ccc196,0x0002d9731815e696,0x00067adc8a7f6da2,0x000f360af6df9cbd,0x0000fab708e5c748},{0x0008c7c19580ff2a,0x00056d28b898fc75,0x0009d3500789e54e,0x000af3c0972f1eed,0x00002ac6bc3c26f9}}, {{0x000ff71880242404,0x000f1c7a3e6fced0,0x0005e468a56ae92f,0x0000f9670e8cbbdd,0x0000020c88ed5eef},{0x000f9526f1333efc,0x0008b74bd70437a2,0x00018a76b379190f,0x0004cd66e5fb3289,0x0000132085c0e1be}}, {{0x000708697faad111,0x000b805a8271d7e9,0x0004c1dd178bfc81,0x000c149eb4735dfa,0x0000d2f552ec6eb2},{0x00048ef153d6518a,0x0004b40bfcc9a0be,0x000c00e5e2afad26,0x0000f1ea67b27e01,0x0000122effb0b8f9}}, {{0x000484026aa4c38f,0x0009f8c0aeaa3c09,0x000e1764589f8c76,0x000e5ee3a89f46d9,0x000024e2c82b5288},{0x000f97b2a763d952,0x0004d8a87d83b5f4,0x000662574fedee3c,0x000e6c8cfdb2220d,0x00008ad1e213c69f}}, {{0x000601630c24de4a,0x00030c2c880e5cac,0x000dc7106144a7e1,0x000995cbf8299dbe,0x00009f1a04b80eea},{0x00081b8f5e3ca421,0x00098fb79e7f8ea9,0x00075c1ae32a9ecf,0x00091361be448bba,0x0000009a3ed31173}}, {{0x000edc4d24ff34d2,0x0005e5192c4d6840,0x00056736a2a84199,0x00067dc208b04d72,0x000091aa355f1170},{0x0000b62c6dbea762,0x00084bf854279005,0x00058b53b37ca64b,0x000f4906c3de8129,0x000017420c7a1978}}, }, { /* digit=18 (1,2,..,8)*(2^{72})*G */ {{0x0004645d0c999206,0x000f55ed005832ae,0x000aac9fd1427420,0x000def2ca5f5efd3,0x0000d8417da6ba53},{0x00015bfe3a91ab48,0x000ad8bc9001d1f8,0x000bccb573cb03eb,0x000ed588452c8f0b,0x0000190d99ea9851}}, {{0x000f6928ec987520,0x0001acce548b37b2,0x0002556adc5cbc76,0x000befb4fb38e754,0x0000e6f549a164e2},{0x000cbaf6791e178f,0x000242386ce6c413,0x0004d3f2b753e67f,0x0009e6bf901be1c5,0x0000fea1ab006e2d}}, {{0x000afcbcddc5b4e3,0x0003f6ad7ab9a2d8,0x000cf2fe2c7a8c98,0x0009cf5c29c00090,0x00000a465e1b5bc1},{0x00039efc04140b7d,0x000aa29e99d043b6,0x000b4b1d9836432d,0x0007aac35ef51263,0x00007f50574f8f0c}}, {{0x0003b25760e88423,0x0009b7d341d81dcf,0x00083e622c18ffb5,0x0007e4badcddb688,0x0000becf33dd410e},{0x0009a60cc895ade5,0x000e3f6a7a73ae65,0x000e082fa7baab21,0x000f729bc83879a5,0x0000c301b48a24ab}}, {{0x000f2386acf8a72d,0x000604ac3b819900,0x00028ee94251e622,0x0000cfab91cb8372,0x000019e78eaae4da},{0x000f8063ac90f7e0,0x0006d1eb32912137,0x000dda25c7380214,0x00046a9e3a2f82b2,0x00002b889ab4a768}}, {{0x000a78b173431ac6,0x000037c593710000,0x000074fceaa51d30,0x000c0a565e1c48c7,0x0000087805015262},{0x00044c6adeb5098c,0x000f59dbcc8ad945,0x0006844fc921b6d7,0x000aaf80a70dc04f,0x00009ea6e278d5f1}}, {{0x000cf86624af5d13,0x000f4cf02ff6072b,0x0008cde126b78788,0x000985309a47d2ca,0x0000c4b1abc9fa46},{0x00028fb8b07c6947,0x000bf87aa9e5cb6d,0x000144b063bc3aa2,0x0003ccd35c98124f,0x0000562b62f1af58}}, {{0x000915ee22d46e27,0x00009b665c7322db,0x0000faabc5d86f27,0x00004cf85cf12cc0,0x00003fe2633a632d},{0x0000a1c1ed8106c2,0x0002e3ba317db248,0x000897173dd719f7,0x000cd0e5087dec65,0x0000d47fab598e63}}, }, { /* digit=19 (1,2,..,8)*(2^{76})*G */ {{0x0002aabc59c94f12,0x00095b397acf4ec2,0x00003bfdf9e674d3,0x0004780850426c40,0x0000ca04d6eb4c85},{0x0006908d03fd22f0,0x000814c5f5942bc4,0x000db3a0f5e9bc06,0x0001e62ba9a6168b,0x00006bd8a9096113}}, {{0x00009d21104a01b4,0x00024745a1251fb6,0x0008668a04b75ff4,0x000fe349e967747a,0x00006e02c0c6d4e7},{0x000084a333d89913,0x00059a82fe122271,0x0005f3a1a369f264,0x000fa053caf9b5b9,0x000022f6b350187d}}, {{0x000f36cba7ccb6b8,0x000008210395755c,0x00038f8b13d90150,0x0003ea696117ce63,0x0000c5fc7ad16c23},{0x000e0dbb58d94e9b,0x00051a9a40ebf884,0x000f65c5c2b999f2,0x0006d5effe6ec1bc,0x0000b7559295f5ad}}, {{0x00048ff65b341317,0x0008233aed1d1f71,0x00033bc63a356251,0x0001b22cf566eaff,0x00007f53d3789579},{0x00086fa303582c2a,0x0005fd4cf94cf0dc,0x0003899cb5afac02,0x00035800d319bec8,0x0000afb9e2fd22fb}}, {{0x00033425fb22b5b2,0x000c99c7ea2ee345,0x000bb698147612e7,0x00068f17a3fd0d94,0x0000828ad54f2117},{0x000657e7e87abddd,0x000bcc3810156e0e,0x00034a697c600213,0x000a648420ea020e,0x0000d279bdaf20cf}}, {{0x000f31d817bed07d,0x00055ab5c8b06d5c,0x00022f1cd42f3db3,0x0009efa79b1a785a,0x00001ca931baa4c5},{0x000b66d8a740682e,0x000d06a15d7dc85d,0x0003d89a928be329,0x000b486c72f132b0,0x0000478e55d53bd7}}, {{0x000bb6e6b0a9a305,0x000098b593d070f7,0x0005d69e7bacb02a,0x000d6fe994375751,0x00009b830bfbf6b1},{0x000cb4666d9987a2,0x0001462334c0922f,0x000e103fb50bd914,0x0006b82023df631d,0x0000f49e7f2f57df}}, {{0x000e23139482dcb9,0x0001ee1adc1696fc,0x00023caa5f3be88a,0x0003ebb3598ebe59,0x0000801aabeabc49},{0x000560a9c8a8fda0,0x00082d4db067df91,0x0005b59ef1377a4c,0x0000329c198dda09,0x00005daf596bd7b8}}, }, { /* digit=20 (1,2,..,8)*(2^{80})*G */ {{0x00064232b86345c6,0x000491cf1c367cab,0x000b12cd89c580bf,0x0005b4a329bc85a9,0x000061507757ea7e},{0x0007fbd8ddb9611c,0x00062b0167dad297,0x00011cbbb1d53bf6,0x000c8188b1604f30,0x00001f4d0fd7d22e}}, {{0x000eb572d99661c4,0x0008402fcf0a7fd8,0x0008c5d33d449b8f,0x000f0f09842fd078,0x0000da7983de9402},{0x00076f6bdb01f785,0x0001f4c4d194a88b,0x00090292128bdeab,0x0009129fcd2b63fd,0x0000ebc377dfedf6}}, {{0x0009a1904af269a5,0x000ee2c68af43eec,0x000da69b7072b08d,0x00046bcf55502468,0x0000f80ea4ac443d},{0x000a17081f1c5679,0x000da8d470c56a4f,0x000e1f2684ceb758,0x000ba15f3159abc5,0x0000964c76954003}}, {{0x000943b9b2fa6dc9,0x000e0b2b4b4b67c8,0x00005ebe4c512574,0x000128fd8c1d10df,0x00006e0e8ebb49c2},{0x000b34a5656dfc03,0x000d6143b3def048,0x0001c1b2d09a22f2,0x000c08d4085ab3aa,0x000060432732650d}}, {{0x000d702cfbe0903e,0x0006ef88e2f7d902,0x00074a4e05d17b88,0x0005b20e9fdbf33d,0x000010bd286ddbf2},{0x000dd0fd8fb34fd8,0x00013db85c88ce89,0x000b8030d8880391,0x000235bac23a3ce3,0x0000fa45c03bfea3}}, {{0x000be6868dc83e03,0x0005e0798fa7aaac,0x0004248d23c0ea74,0x00098ae9b41209ee,0x00003cedae7fcc2a},{0x0000a5ccc7b9ebec,0x0005fdc32c04dd3e,0x000def4916cf5e80,0x0009ad4cfa6c35fa,0x0000a98de7d24b36}}, {{0x000fd321053b8bde,0x00015a36fa6110cc,0x00012bc0351a15e4,0x000cb742b74fb1eb,0x0000cad7c54d4248},{0x000d56251a7ec868,0x0001ca2cc80ad571,0x00056953911caea0,0x0002c80cd7c27fc3,0x00000a95d3fdd32f}}, {{0x0003858b5c81bd3f,0x000d2a9431dd80e8,0x0009efaae17d3682,0x000f67830eb7c7cc,0x00002f1f3290cd4f},{0x000990a639034a2c,0x000a593b6251d5c7,0x000299c23319bc02,0x000b194511cca1fd,0x00006f501add6b8d}}, }, { /* digit=21 (1,2,..,8)*(2^{84})*G */ {{0x0006beb87707b7a2,0x000c72a87dec0e16,0x000d90f4e489ddf2,0x00017feb5010ded8,0x00009f1c146a514d},{0x0002ae989277487f,0x00076313476cd0e8,0x00052ddea0b6d98f,0x000ff20c6a63d0e6,0x0000d40ea3d516db}}, {{0x00019c667d0d91d1,0x000e8105ca7d8669,0x0001a93ed4b79dc6,0x00058efbc582967e,0x00007205a3aecabf},{0x000187f1f85aef05,0x00012b160f5dcd7b,0x000f2c42bbc43ffd,0x0004562f5ec697b9,0x000026b5000648eb}}, {{0x0000d41a77c52336,0x000441d214aeb181,0x000c6340187fcbdb,0x0006e6ac41506af3,0x00003b6fa4818220},{0x0006bdb65cf1fb29,0x0003ce4a84bde96b,0x00083b4cb3bfaea2,0x0008473e742f060d,0x0000fba067aea100}}, {{0x000b6c2d46254ea3,0x00039b6ec7fae9f1,0x0004d44a4114c60f,0x000f5ba52995f271,0x000066e8cbd34843},{0x00062c42a011d210,0x0000c318129d7161,0x0000f32c7f0a2090,0x000229f63b03909f,0x00009687ec5c5909}}, {{0x000507db0a04df74,0x000af43753b9371c,0x00099a17c1cd2a88,0x00066679629cab45,0x0000a296edbca1ad},{0x000519b397e39c16,0x000e052af036c326,0x00079fe7dac46a92,0x000efcd5086f0cc7,0x0000bf3f8cd63cc7}}, {{0x00042e43a80c6fad,0x000b1ef9c053df72,0x00078ed2a6c7dc5b,0x000da22fb8de25b3,0x000063c34563eabb},{0x00066648e3f185ac,0x000a5f4dd6f958ec,0x000f2dde11a9f374,0x00087dd496925a77,0x00007412068d6cf7}}, {{0x00005e399e662c0f,0x0000a57173e460c5,0x0004e0120bf24c7f,0x000f062621bbbce7,0x0000fbd676e31f74},{0x000bef99ec94a32a,0x00023cb57797ab7b,0x0009ae3d0efbd3a0,0x000900cc160ad35b,0x00000124b141f449}}, {{0x0007c8bdf49d7f19,0x0007df31711ebec8,0x000f46d03fcfcebc,0x00035281f2da40f1,0x0000aacf4dcfdeba},{0x0004907c5d800621,0x00068e3c2eef12d5,0x000ae7e3f5965a34,0x0000ca494de95bb9,0x0000c88b84c6fe58}}, }, { /* digit=22 (1,2,..,8)*(2^{88})*G */ {{0x000cadd1a806623b,0x000e2b6f79588c00,0x0009a8a99724a1aa,0x000f2088afa52fc6,0x0000f705025b0678},{0x0009b5b7e0f923c4,0x000e2b31803dd6fc,0x00048c34f654baea,0x0000a8a16488e4fa,0x000078ce7289743f}}, {{0x000c047df2f3ac76,0x000c2b67c4a658ad,0x000864e2a38fcd7a,0x000ec6e4fb3c4763,0x000051531fb65393},{0x0005e4fd59db390b,0x000c9c55e59d92d3,0x0005b30150334900,0x000919016cedca47,0x0000584c78dab3ac}}, {{0x0000d9a50b845667,0x000a70683a7337bd,0x00042f134d3dc726,0x0004c501f1e3416d,0x000077d800d0f3e2},{0x0002ade2f283b9d7,0x000aa506fe28ef7e,0x00054084698d5e5f,0x000e17b633cc5ef1,0x000066c31b2862f2}}, {{0x000fc8a61448916d,0x000c74f3a29467a3,0x0009855614595002,0x0005455f2de81e94,0x0000c7e3b2cd575d},{0x0001458e271cf38c,0x0006c8f06d0de9fa,0x00049a303fe35dec,0x000c8fbd5bbc11cf,0x0000091b6978a5de}}, {{0x000d37663e141628,0x000a0c7dacddb7dc,0x0003b0e7766eefa0,0x000f1de3392ed500,0x00000be7c32df13f},{0x000ffd3cfb24917d,0x00007c5f365b7cc3,0x000aa79e7c6214d8,0x0002056c1294e3a2,0x0000f07f35bd7c03}}, {{0x000ef267775da03f,0x00054e3abb830d13,0x00021d39eaf8a67c,0x000aae69d2ad2353,0x0000cecdaaf36b90},{0x00073f3903ddce42,0x000b5039b0d7d86e,0x000c943f361c4d2a,0x000faa09580f5af2,0x0000f9ac892638f0}}, {{0x0007e7ed58b7eafb,0x000a211399f9cf33,0x000de654563b6e7c,0x000addff178e7a48,0x0000fb88753b9155},{0x000f8b801c68011b,0x000ffd43c8aae72e,0x0004bce716798b71,0x000c168527878be9,0x00007ce2d9d5e353}}, {{0x00072002d0deafc1,0x0007568e039c2560,0x000b74f7fa8c3e04,0x000fa452b5f26fb8,0x0000d5c673e4de9a},{0x00094308345d1eb9,0x000e937e84fb7e3e,0x0000233f0b08ef7d,0x0005f8881b401d8a,0x0000861e80d65e10}}, }, { /* digit=23 (1,2,..,8)*(2^{92})*G */ {{0x00076ddafe513028,0x000b231be24319a2,0x000bb927cde9a7fd,0x00047f98503f7d28,0x0000bacef2354247},{0x000e4d52a90363e2,0x00072961d7a64eb7,0x000900d06b997d69,0x000d4f0d5e436088,0x0000deb49837ce80}}, {{0x000bb2d0d12e52d0,0x0002d9d615faa8f2,0x00006ad2841c4cc3,0x0005178828fa1eb4,0x0000037e5443ad4c},{0x00018eaef0ca0cd3,0x00057646caa6d2f2,0x000e0158862a3d51,0x0004399628eb879d,0x0000cd6553865dd0}}, {{0x0000a94af9ea7cde,0x00069d83d30a2c5c,0x000e36e136e23569,0x0009d6c9b0857f77,0x0000ee3ba9363a28},{0x00091c4d690c1482,0x000da0bdaa6ec1a9,0x0002efb68a84b025,0x0004cc597ba9fe49,0x00009c2e3b6a4baf}}, {{0x000f0606c39967da,0x0008ecee978a1d35,0x00031bb32640de50,0x0003dde62e3a68b3,0x0000e08b646ad0ee},{0x0000f5f9d3887578,0x00046276f9326f11,0x0004b608425a9f9f,0x00069fb512f521c1,0x0000178ec5cbaa24}}, {{0x00019c380abd55aa,0x000a2e43d34a2e3f,0x000dc29f25566282,0x0003bdcc7ee3759c,0x00006455153981a4},{0x000fab2b4f7c81ad,0x00074aade744b1f6,0x000ff14cda1c443c,0x000bd5111a7d222a,0x0000a28194e30835}}, {{0x000876812dab14b9,0x0007f78a4d32282f,0x000c4f8b89ba0bce,0x00094fe50e36e029,0x00004692f67fcd8c},{0x000d3eea24df7225,0x000ee8ed23a17f08,0x00006374aae9a53a,0x0006455e06d7b448,0x00001b31dbe9cf50}}, {{0x000a821ab5d22890,0x0001522b99a72cb0,0x00077cdf65604ed9,0x000cad53e06de6e6,0x000000279f3d1814},{0x000490a31fb979cc,0x000d92b7cb0b5a2b,0x000c1473e470c4c5,0x00054393aa7fb121,0x0000cf1f5b79004d}}, {{0x0007d51e7e42a51e,0x000f444c5f95cd80,0x0000ecd677766dc5,0x00040656dda8c8af,0x00007a567e594477},{0x0001a1b8848c495f,0x000ff6ac2ccbcda6,0x000f23870b5b7597,0x000568bd43bc1923,0x0000956dd9ebf318}}, }, { /* digit=24 (1,2,..,8)*(2^{96})*G */ {{0x000589fb928c5f43,0x000ab31b0e63d348,0x0002245b5418c388,0x0008872a4f460057,0x0000c3c71e7aa249},{0x000bb0696dee0485,0x00070cc6583553ae,0x0009f6a5e077bc6c,0x000ffc1520879094,0x0000bccee4609921}}, {{0x0005aaf668ac79d7,0x000433ea2dee7a63,0x000c3da02c1bc912,0x00031cfaddcde2f3,0x00001022732669a2},{0x000b89dea0558e1e,0x000e6a9e5aa049a6,0x000d25865fe4287c,0x00021cec3e74083a,0x00001aa8b5c32deb}}, {{0x00040e7bf97f20a1,0x0006d0399375235e,0x0006d582fd773a7e,0x0002e1f677614c84,0x00001999db61efd3},{0x0003489b6ccfa05d,0x000a931ee4c47744,0x0009f7bbf5dfe5c6,0x000fd75266f03847,0x00006555c655bd0c}}, {{0x000be00843e7b7e6,0x000b723fe67ba665,0x000037ef26f02671,0x0004513139145076,0x00001e80333c65b0},{0x00067e7cf2b69e56,0x000e805d53ff04d3,0x0003276aa2047eed,0x000006ba0bf7ccdc,0x00008a2d8826cd00}}, {{0x0003d241c54ab435,0x0009d27cc2338fb4,0x00094d101f8dfc4b,0x00065cb7689ff6fa,0x000074c538fab3e8},{0x00070471a2ea65d5,0x000e47dde9b62a31,0x000489a9bf481367,0x000580a7d6a06e98,0x0000679d2079dd65}}, {{0x0009f3c5562d73af,0x000f9ae3113655ef,0x000a5dc46c2ad1e7,0x0006d3bbefa2c6e2,0x0000ec4fc810c34a},{0x0006b238915ff4c1,0x000af22a42581cb1,0x00020244d851d41a,0x0003999a8e1de0bc,0x0000d237a6934d96}}, {{0x000987f8338f6cc0,0x00059e455950cc3a,0x000bad2e7384a6a9,0x0003fad84c71d665,0x000016cfe8130120},{0x000a6c81f092f72a,0x000fd727a79a6a7a,0x00073800ea330d7c,0x0001f541056e5d01,0x00003e66db6185a5}}, {{0x0009356a79debb8e,0x00065b7b0dc85957,0x000825e834b42de6,0x00021f4a727de460,0x0000c18079e2bfdc},{0x0003b0bfe5e20c23,0x0000045f5f9a0529,0x00087fe98313de54,0x000411dfc1a8b0f8,0x00004e039a515ca2}}, }, { /* digit=25 (1,2,..,8)*(2^{100})*G */ {{0x0009d20f961c2e82,0x000b85dc8de610b8,0x000ade101437f35a,0x0007eebc5e8c515f,0x00002509d1321032},{0x000842e3dac8ba0c,0x000fd66098583ce0,0x00048bafc3fcb163,0x00076414aa2eedb9,0x000007db9f48bc83}}, {{0x000595c4b3f8dbd9,0x000359d74cd06ff8,0x000f270e29f8a825,0x00087d12b9c17c7d,0x0000b2e80e811f87},{0x000db27ce43a86c1,0x0003fca990f62ccd,0x0002ec59bf016957,0x0000628f5d9bed21,0x000027d55a4ba6a5}}, {{0x000d03f718913dd5,0x000c2befc15aa1ee,0x0007c847102cc8f2,0x0005c8a1240d1254,0x0000fdffe724edc0},{0x000f68ea1cc2db7d,0x0003e6c4a02c4997,0x000d509587b544b9,0x0005f5faff725083,0x00002c702007fc4c}}, {{0x000d112927153319,0x0003f1d26ee83821,0x0005188c3a678749,0x000f5953dcf17dcc,0x00006ee6a46384a1},{0x000b8bdb94fd5a59,0x0002b7750491a746,0x00019255042413ef,0x00049dcab687fa76,0x0000d3bdf3fd8d81}}, {{0x00073eb5de6f16ea,0x000838af7f91d0f2,0x000180eba14a2d69,0x000c07d543b61b0f,0x0000a48e18374f25},{0x0002413c252f7b56,0x00055f77b4e4d538,0x000f5bfedb51fa0d,0x000d51bb3b7ce66b,0x0000bd4cf4850d41}}, {{0x0005fe87134cd0da,0x000a17e3cc8ac855,0x00078703ee282882,0x00067052f8d725f5,0x000030f3d852516a},{0x000242d3ae1ef785,0x0007fa96ab6b01c8,0x0008fa96637638d6,0x0008ee49b69a02a8,0x0000dfec375d87b0}}, {{0x000f921d710cc9ab,0x0008a269be47be0e,0x0007db96e1305cfa,0x000a2bce5323b7dd,0x0000b7178cc6492d},{0x0006c2921097b191,0x000d0fc3c4b880ea,0x000df1d178576177,0x0003f6e393f6f914,0x0000ac9a7fe9fa67}}, {{0x000bc95725aee3d5,0x0002ea553fb2b560,0x0007423c28530356,0x00000bbd96ce141e,0x00009b1c7fa39ddb},{0x0007326ca7661923,0x00044911220fd06a,0x000b99589f2eb8ac,0x000d2c8a9716e3a3,0x000016f0b4225082}}, }, { /* digit=26 (1,2,..,8)*(2^{104})*G */ {{0x000a527e6b978cee,0x000db82cf7d62d27,0x000ca96802e48946,0x000e9519e1f36e29,0x00007265e87b84fa},{0x000802786e991660,0x0003097581a85e38,0x000f541313771b92,0x00067126e1f1a520,0x0000d10aa19b0e7d}}, {{0x0006f0af00724aea,0x0002a9e36f09ab05,0x0009f3200c5b7d67,0x000971f9803f163c,0x0000abeb83ab4494},{0x000dc4a79b89e736,0x00099ec70880e0de,0x000ed078e9a3f10d,0x000e77ebd7332a66,0x0000efcf0956aef4}}, {{0x000be864b03d7cc0,0x000d4d1f4c6b6ec2,0x0006eccb68ebb96b,0x00094bfbf526b082,0x0000a5858dadf7d4},{0x00072e6a44328071,0x0001da542099b646,0x0009a026229e5471,0x000dbab9c2770b28,0x000007628b15e3f6}}, {{0x000dce3782cc4229,0x00054d0c55c44969,0x000687ed744ff73a,0x00095ca63a6a9635,0x00006189f2556fe1},{0x0005e2f1f92bf8e0,0x000c16ab2b91f71a,0x0002b5bd2443b5ec,0x000ec35ade448982,0x0000c8788b8a39ca}}, {{0x0004a1f390200e56,0x0008cc847c643671,0x000f310d5b30aabe,0x00025ae2c6a496b9,0x00007a3574996340},{0x000eafc1730bb4b0,0x000e3633ef1f5404,0x000a23f7ac20dc45,0x000363451d323b30,0x0000fabcf3b74204}}, {{0x000392b0b18c6d03,0x00098e7abded5516,0x00086524935ee7e4,0x000a3d6a903d358b,0x00006875db035981},{0x0006fc5d51954294,0x0000e980b75c904f,0x000db1fb9c1ad202,0x000ea6532c305b0a,0x00001aa27478cb82}}, {{0x00014710f8720b12,0x0004851b3e59b897,0x0004cfec90d17238,0x00000dc591361395,0x0000dc88b86a7ad2},{0x0001febd7319c15d,0x000eeced6c446c96,0x00060a4e95f5a70d,0x000a79f37e0aa7fd,0x0000ca962020a7e2}}, {{0x0008f862ec09473d,0x0000ac9d64cc78c4,0x000b52744f8f7011,0x00038e5ab6c50621,0x000008c758760cd6},{0x0006d3b2c6ac19b7,0x0007bede1603c166,0x000ef5c6e18a250d,0x0000ffdfc19a80e0,0x0000dc276b838e08}}, }, { /* digit=27 (1,2,..,8)*(2^{108})*G */ {{0x00011cac13161f9c,0x0001bbc453cadd69,0x00072aef15e577c3,0x0008c37af203900a,0x00000e41db5e3490},{0x000b87d44a487f26,0x000dc42ec965469f,0x00012e582d33e4d5,0x0001872850e9f769,0x000038b03659451d}}, {{0x000da8e4f1aff818,0x000caa2d551ee106,0x000804d524b4b06e,0x00008fc8d87a8f1d,0x0000ef431fbeb97c},{0x0000c0d9b00298e4,0x00033f0cf9a4e718,0x000fbb34f16943d4,0x000ca08c0ff50200,0x0000745ea7a228cd}}, {{0x000f1e0fa64b9ba1,0x000a4ff1d7aadabe,0x000fe6d896d5ce68,0x00034116f65d3825,0x00007bcae08c6246},{0x000ac54f612c30f9,0x000ceba33db72cdc,0x00092fb725511bb6,0x000d9573c017cbc0,0x0000a29dfebf2fc8}}, {{0x0000903c4cbe46bc,0x000c0eb1bf4581ca,0x00060c177519da3e,0x0005066ace635e18,0x00005345445cd5a7},{0x0007197ca469b8c0,0x000858948f214029,0x0004225140fdccb5,0x00087719031b49c1,0x0000a2053b8e6576}}, {{0x0002dda543915e7e,0x0005f5d4b07e2b19,0x000afac0fcdde015,0x000a72d14d144c4c,0x000034e73127607f},{0x0002db773ecd3720,0x0000fa8cf03dce66,0x0004b74758be1c61,0x0007668c48b5ea96,0x00009b6250934072}}, {{0x000d7803581ab555,0x000eab4820357c72,0x000e419c5554fe07,0x000fef5a1992039a,0x0000d9875b456d0a},{0x0000ee0ea7058063,0x0001b4dc77ad4d4a,0x000858f1411d534f,0x000f0bd5ed49a799,0x000050a8f7fd0e17}}, {{0x0003cab91b752141,0x000a5e89c92b2350,0x000e676eda85d689,0x0001c8f31a73bbd0,0x00003841c3e8d0f4},{0x000cd61ad4ee96e2,0x000a42f1db3574b2,0x000537e4eb45e77e,0x000813c06485b018,0x00002be90410b3b1}}, {{0x000add5f69c02408,0x000d61cf3480d4af,0x0006c1ad6fb043be,0x00005529cf0d8edc,0x0000e6b784db99a8},{0x0005a454130bbd68,0x0002fad96f8acb1a,0x0004c17786cf7d98,0x0001fdbf4bddd49d,0x00002c7d15e91516}}, }, { /* digit=28 (1,2,..,8)*(2^{112})*G */ {{0x0003c0440fd7f2f9,0x000bdbfc360e25a8,0x00048399d668b4f6,0x0002439f4e642519,0x000089f1fa0b9870},{0x00097b3d282ee427,0x0008cf1d720281f6,0x000e67baa329978c,0x0002104e72205910,0x000061a43a34e6ac}}, {{0x00071279a45648bd,0x000de9afb3ff9ed0,0x000b10e3d7b7d810,0x00004e74928c2e0a,0x0000f66bf52858f1},{0x000e9fccc7111eb0,0x0004f6601fbe8556,0x0007f13a84fd868d,0x0003acc0b3ee394e,0x000011bb82692f56}}, {{0x000f57841f3144bf,0x0001f9314092ebb4,0x000cf3369fecda45,0x0008e3164f17256b,0x000033b176e2d462},{0x000333e4efa6df27,0x0001d05e708d8553,0x0001d0bddee0a802,0x000f8c7d5856aae7,0x0000603c90846016}}, {{0x0007512e2eb6a7c2,0x000b8dedda492f81,0x000a60d843d6851f,0x000eb594cc11a3ae,0x0000e9fde037b87d},{0x000cf109a400a483,0x000c6f3177bf8b6c,0x00093bd6f59a5d1e,0x0006c915d232ea4b,0x000066d0031672f4}}, {{0x00008a54ec2b1382,0x000f888a1f258972,0x000f812b7fecbc4a,0x000e06b5c7ac6961,0x0000e7ee6a3486dd},{0x0003eeb9a9acb8ed,0x000811978660710a,0x00067f8f391f11c9,0x000b760a50cf70a9,0x0000a64a54a69740}}, {{0x000869d0d5ac68e0,0x0008233169bca968,0x0003a53cda259d70,0x0005a1a9404d286d,0x000088e4951616f4},{0x00052a733ab82011,0x00026e5d0150d651,0x00030ee1a18ef179,0x0006e1c49a92e250,0x0000660861970a58}}, {{0x0001843074252dfe,0x0003f588434a920a,0x0002c09cd3518f04,0x0005fc19ac0af8e9,0x000065ea1ee67b6e},{0x0000581fc169a790,0x00004aa5447ab801,0x0005b7021d9fcb63,0x000998a9ee5e5a32,0x000086ce09c0bdfe}}, {{0x000b0da855c77138,0x0004d7080eb24a90,0x000d3d8064a79971,0x000e895b87bedfb4,0x0000ff2e824b81fa},{0x000939b48c4a16ef,0x00015dbde314c709,0x000bd2f933b9e136,0x0004c0d9ecdbf1fb,0x000042e460791f67}}, }, { /* digit=29 (1,2,..,8)*(2^{116})*G */ {{0x000c8ac9b3f30faa,0x000821f711b0eb9e,0x00078b7fefa0a379,0x000f7e8dbb905f2c,0x0000d9b3674355ae},{0x000e568622b92879,0x0005fb6b40a24474,0x0001518d75018f42,0x00065c23f60121fc,0x0000b6c0f8efac61}}, {{0x0002b23a10647092,0x000b4c64a8a3d626,0x000fc1c509c1f5da,0x0008752338469c4c,0x0000592d71f92d24},{0x000e65e5e66ab21c,0x0007ab4a63d1a4c4,0x000a2eb259587d83,0x000fd941c454e7fe,0x00001e808c047aac}}, {{0x0003840fe88767bf,0x000b8176add85450,0x00066f408b7e5e73,0x000da5e771b71cb6,0x0000d35c39b650e0},{0x000174cced9e5822,0x000b8d51ec699775,0x0008df0a9a391539,0x00071f40cae243fb,0x0000e2156e1d8e4a}}, {{0x0003c2f435522de5,0x00099b6cbc613e57,0x0004d5bbb1e76fb3,0x00050f9d533131d5,0x0000500dd4c4695d},{0x0006451f5801b985,0x0009f93a4a375fa7,0x000c41eea66a4aeb,0x000b4eccf5f06787,0x0000be0cc26ec73c}}, {{0x00000b6c75700e6b,0x000408495fe1347f,0x00087f18e3c6eed8,0x00078726bab0f6c3,0x00006a00813e85d4},{0x0004f3ad785966ec,0x0000da6a78629992,0x000c99e4f0adef59,0x0001d2deb85e5a06,0x00008ebb465036e4}}, {{0x0003d92b271a34e2,0x00021fc6c68d6876,0x000cbc1727a04409,0x0009c8c7a3e732c3,0x00006da92ca67f54},{0x000e2c06175bb538,0x0004abadd44867cb,0x000e3a947ba1a418,0x000b74f85a71b4a9,0x0000e7099fa89017}}, {{0x0003b5fb75d8727b,0x000f2282bcffbc46,0x0006a334e0047ac4,0x000c33369708817a,0x000053e4b18d8ff4},{0x0005f5e93d863d2a,0x000bf53e7fe08c4a,0x00044f8de0daeb8c,0x000aaf25cb4d8bfd,0x000075bed4b944bf}}, {{0x000274dcf1b355e8,0x000d5ef694db7e04,0x0007778800d4cda3,0x00062f4e1edca878,0x000092c279274250},{0x000be2b2abb3de8a,0x000b9b86def6d1a2,0x0000bff865bb4348,0x0002de558d25b167,0x0000a14c44f5e051}}, }, { /* digit=30 (1,2,..,8)*(2^{120})*G */ {{0x000da4a7963ed790,0x000cc9dd111f8ec7,0x000d3a203fc9ff36,0x000619a51bcc33f8,0x0000c3316282fb7e},{0x00058ffec2ca8e3f,0x000cbe30bb1151be,0x00071d53238e4f7c,0x000c05f7854febac,0x00007acf3890bf9e}}, {{0x00066adbf6bb7535,0x000ff9d29c4120ba,0x000f1a65fd1f4042,0x0009b85519f94391,0x000007d911a8b098},{0x0008234499aed7de,0x000763c34bfca38e,0x000fd1be8863128c,0x00048439ce0f2755,0x000013608ea8ba39}}, {{0x000b6304a752fd49,0x0007c13516e19e45,0x00076a61d0ec2826,0x000e9d5f656e2e84,0x00006c970cc1cc09},{0x000935381bb3523e,0x00069363ab7e433f,0x0000053ef767b2e6,0x0002d839f1adea47,0x0000b39a71be38a8}}, {{0x000cb10d572b5962,0x000ed9d918e49366,0x000645a02c2b89f6,0x000f43ab965035ef,0x00005fc3fbf56b43},{0x0007c7032b9ad449,0x0000eb7a242da112,0x000d3f646f3cae05,0x0002e606b16a4d3d,0x000066b08ba950ea}}, {{0x000fa003d16724c1,0x000aa7d5846426f7,0x0008a4dd404bee11,0x0004afe48e7d09e8,0x00004e388ffd7c0c},{0x000d40da8e2b1cbb,0x000a64f17fd95965,0x0000d88abe4cfada,0x00066ec6a49e0e0a,0x000085fa4175ed03}}, {{0x00089bc84468e031,0x0005ab4a595939dd,0x00084fd839d2cf16,0x000cd45120355647,0x0000a31eb877381b},{0x00012d8643774d44,0x000965d85a9184d6,0x000b3e932a3180a6,0x0003d448e562563b,0x0000bf1cf2a46781}}, {{0x000d03d7d3318572,0x00049a354530bb24,0x00077e0492176e2e,0x000bd9f63bde3ef7,0x0000086e3e2a72d9},{0x000280da9fc53e22,0x0002d9e43b6a782b,0x0006ea07cbe66e70,0x000c1cbd9216db30,0x0000dfa49ad0403b}}, {{0x00048234a455944a,0x0003c913e538cd75,0x000c398678aeeffb,0x000c8cbffa7001f6,0x00008153cadc4269},{0x000cbd665cbd5dcd,0x000d02d3d5b40458,0x0005bdd2db3441fc,0x00002b28bb0ffeeb,0x000086864413478b}}, }, { /* digit=31 (1,2,..,8)*(2^{124})*G */ {{0x000d41f01735a335,0x00073f833f6746cb,0x00054167a0b39250,0x0003a7ba921e46f6,0x00006c09c11aae95},{0x000d59e95785f38c,0x000b834426ffb589,0x00057781d8acae7b,0x000a30f7f8055943,0x0000f1dc76c3a6d4}}, {{0x00097ba641eb7f97,0x00074a9b733aa5fc,0x000b26df4bf350af,0x0002ceba5dece47c,0x0000cc1ae7e7d3b7},{0x0007fab43b1d99a8,0x000ad0409c110608,0x0004beb49cf2a615,0x00058d94656ea2c0,0x0000cf90618174d6}}, {{0x000a41e9fa25ab62,0x000af5c775d6ece0,0x000bde7efd93c9a3,0x000b19a8169d2e3b,0x000085cb8fc6f6ee},{0x0005f7b3cfc01d0c,0x00027be909a1f0b1,0x0001f4efb7604d75,0x00015af69150a845,0x00001a9458cd6746}}, {{0x000b433b59bb0813,0x0000341d4c5105f3,0x000e323c820b4e81,0x000deaab01ae80f8,0x0000ba1d2bfa0603},{0x00002fefd81e661f,0x0004eb693e856387,0x000273b996572680,0x000f613ecf7b5925,0x00002889ae807f47}}, {{0x00070814d5389736,0x00073141339609ae,0x000d572fd5e8361d,0x000f5579c2b627de,0x0000b93bcfa4fc39},{0x000b4a9a9b91c818,0x000435717398d14c,0x0004b4b95c2dbae8,0x000ba7a759d37d25,0x0000ea36d4f85bce}}, {{0x000489527486828e,0x000dc5c97290293f,0x000bdeff5a4b77f2,0x0000edddabf04a19,0x0000608db4f55ad8},{0x0004f5d47694d29d,0x000e1c32a5923d75,0x000ba8eaeefa4a0d,0x000473bfcc7bc949,0x0000b5fd2de9fe6f}}, {{0x000e65bcd4111964,0x000a1f7d13fb27da,0x0002be0bd8ecb0f5,0x000e2f2c5c05b30d,0x0000ff05e9764421},{0x000cdc5908086e16,0x00094b8630d99eaf,0x0005e9509364c388,0x00080bcf1164be81,0x00001478d33e9527}}, {{0x000e89f3d33e658c,0x000bb5d0fefb0c3a,0x000a984dcf89f8ee,0x000d20ca4d48fb56,0x0000b9304c4e5ff7},{0x0003083bb07dcf66,0x00023c86363d14cb,0x0000b4a396cd193c,0x000063a218981752,0x00009e66befec3c7}}, }, { /* digit=32 (1,2,..,8)*(2^{128})*G */ {{0x0001d587d483a8ac,0x0001644bfe209256,0x00032e076092df00,0x0008fc46391c19ac,0x0000ca7c69ca0159},{0x000a11fe134033ed,0x00086a2a37173eaf,0x000759658d52a842,0x00086c73e2384800,0x0000d0571a330ac5}}, {{0x000617ff6bb8909f,0x000aafeb8a24a205,0x00019f14a5d36b68,0x0006aa95317ebfed,0x0000c8fde1bb5304},{0x000967ce0fa78f8e,0x000a6c5e3c99ebdb,0x000d5e1c475a7c8b,0x000cdd9dffc64242,0x000020302e081fc1}}, {{0x000418871e270c0b,0x00029a3b23358342,0x000a6cd6e14299eb,0x000d6b00d9526205,0x000018ce7f6af8dd},{0x000fdb3c22d19812,0x00064814082c1576,0x000fb9e6c451057f,0x000efd528cc914ac,0x000020534397c913}}, {{0x000e205c1544399e,0x000710441c23fa36,0x000053783e19700e,0x00068fea7b4712eb,0x0000a112e4fbfa4f},{0x000514d89ca1abfd,0x0007c57b36416860,0x000d4097b2b1ef2f,0x000a206500432691,0x0000b3a43e7e1054}}, {{0x0008a5b251a46688,0x000c41c2cf9d7c1c,0x000a25f0335a2815,0x000478f0c1320886,0x0000b3973c66051a},{0x0004dada9450a7b7,0x0005d32c11d23031,0x00020a289c0afe30,0x000abe1287da6691,0x0000967694826933}}, {{0x000ce5870a0c41fd,0x000faaaf0dcbc49e,0x000883d62d516f72,0x000eaa5e57de551f,0x0000f8ef2d69da92},{0x000ff5e2f5425d4e,0x000c0dd167d79ae1,0x0002da879bcbf034,0x000d36191039df8a,0x00004f16c971cb78}}, {{0x000aee99a83de201,0x0000551cbae2f701,0x000578bc0f4313d7,0x0003bf399efc4bc0,0x00004db1c0ede19f},{0x000c5f317b20b8d4,0x000b1b9ae8274c57,0x000500d18221751b,0x000091b816c14d44,0x0000685f584b909c}}, {{0x0003bc3770684e62,0x000ca6bc4fe3c395,0x000318bfb46f7b63,0x0001ad259ba4a815,0x00008206cce146bd},{0x000c2731bc0908f4,0x000d4ab5afc60db8,0x00049492c0e73d3c,0x00006d107aa02235,0x0000a2cf845790c5}}, }, { /* digit=33 (1,2,..,8)*(2^{132})*G */ {{0x00044ed736b966ec,0x000a5c2e48fb8898,0x0002f73bc5cfb109,0x0001bb4e226882c1,0x000063d7619b2c62},{0x0006a413e95e2beb,0x0005c6fd86e27c75,0x0009ae0bdbf2ca03,0x000edf84da04edac,0x00007492ad45d302}}, {{0x00024f4d696da3cb,0x0003b1d5a74be506,0x00047c52228c154a,0x0001bfda2e41781c,0x000096ec0545b52c},{0x00001059ae4af1e1,0x000735dbdcc9ae4f,0x0005508ac4dfef91,0x000d754392573dbb,0x000045a30ae8165b}}, {{0x000beab27c67ef12,0x0000c274d559d96d,0x0002dcf0b984d026,0x000aa0faf4f18c0d,0x0000a4d5a80a0707},{0x000bb192b84c56cb,0x000d3aa7040bf3b5,0x0004ba631dd8d7d4,0x000f4e45d39c479e,0x0000fd24341672c1}}, {{0x000c13673627c363,0x0003c973112795f7,0x00071c3b07ab4999,0x000f308cde824443,0x000024017b4422c4},{0x0007e6782a430857,0x000be955dbec38e2,0x000c10a45929115d,0x000d83e2f51c0782,0x0000d2b6c6a41083}}, {{0x000a0300c013b50b,0x000b751ec5d7f652,0x000666363fc769d4,0x000b40fb30c8f561,0x0000e14a50273cdc},{0x000989050f53d764,0x000cbadb114faf4d,0x00087892f0c26b7b,0x00024d2de328fc0b,0x00006f37a0582ce8}}, {{0x000f9b21b06e4d48,0x000483d4ed2dbc25,0x00081ca00bd2f9e2,0x000314b350eba59c,0x0000879d4fee9d2e},{0x000846aa4551a9b0,0x0002394af267bae5,0x000565e76b699192,0x000e51500aa86cc2,0x00009d486efc3818}}, {{0x0008b841146d2064,0x0005638e7e0c2780,0x000e4fd2ed5afa66,0x0003f8a3a09bf87c,0x0000a8d6a3930dd9},{0x000281d429091c44,0x000e8e029e646294,0x000f8a25ba1a0598,0x000386591adb60e8,0x00000de777e039ad}}, {{0x00023eed8fe44b7b,0x0001c40e2c2bf152,0x000587aaa9751a65,0x000b04a65627a220,0x000078ae9a0140de},{0x0008dfbb97c7d47d,0x000a883a8363b49a,0x000920e2f50e570e,0x000074b5c1a0b6cb,0x00004368ec853ac9}}, }, { /* digit=34 (1,2,..,8)*(2^{136})*G */ {{0x000c2a360971c31d,0x000066e846e364f6,0x000c727ad6974fa9,0x000639b6d7f33527,0x000015ca19ee6b97},{0x000b4ef351021aa4,0x000ba52f024e9245,0x00044265bc79a45a,0x000687390e0fa07a,0x000026bc8f7f2c64}}, {{0x0001a05fe05069b5,0x00097050f15dde91,0x0007fbbecba1b4b7,0x0007e7662a47a76a,0x0000cef9eea25012},{0x000d251439c9ff5b,0x000996e9d529b36f,0x0000927929bcb4b0,0x000321b9855ab130,0x0000e6913e2a37cf}}, {{0x000a22c213a1381c,0x0005998a9d82abfd,0x000b0c9eaee2416b,0x0002e94875f188cc,0x0000ed487d7becaf},{0x000a1bfe43d8e989,0x000d43afbddb4799,0x0003d3555d553c34,0x000ae422e4b606b8,0x0000a98941400820}}, {{0x000495775835ddea,0x00038f3dbfb894e2,0x0006a991d3c0ab53,0x0007ac0dfbe9b79f,0x0000a996ed108d94},{0x000a1485e6867237,0x000b861bb9390993,0x0009ecbcb0ad8aab,0x00089ee3b1d6a974,0x00004490d265e84d}}, {{0x0001f9addb3fd772,0x00068b61430c9ab7,0x0002b03f3bbc1b26,0x000a8d0ae0bdd41d,0x0000a6be72385501},{0x00063accbd8fe7a9,0x0001716c52dd907b,0x000c73a737c1e0a9,0x0002868a6d9bdf44,0x000035c09edac28b}}, {{0x0002ad31f429e92f,0x0007dab4baef62e3,0x000275ae5ff44e2e,0x000fc47109f5a220,0x0000f78da2e8f242},{0x00089cf1ff54aea4,0x0008ca425bcf4d6c,0x000288b364e70dd4,0x000847d56ea95059,0x0000d5e592ce8a8c}}, {{0x000e70062ee0a4a2,0x000917ac0b7eff35,0x000e6774850d2a32,0x0004c985f8552225,0x0000ed692c26dd93},{0x000068c99ecd36b0,0x000a048e7073969a,0x000922d3ea339e56,0x00093f20f392d2a2,0x0000a61b1d58dd81}}, {{0x0006e4617f3e69bc,0x000caec1ed66f181,0x000bbf3b6cc4ad74,0x000551b4d225d906,0x00003684306257aa},{0x000516497c9675a0,0x0000addb2fbc3dd3,0x000f55d795decef3,0x000598fadedb5484,0x000015e8ee776bd7}}, }, { /* digit=35 (1,2,..,8)*(2^{140})*G */ {{0x00020f2beb76812c,0x00013ecfa181e695,0x0000dec76ead7889,0x000698d5d9ea02f8,0x00000cd75bcfa2f0},{0x00017a069c2d2cc5,0x0008f0a1df843618,0x0000f08066c134ef,0x000c931ff1203772,0x00008f19ef39b4e2}}, {{0x0000aecc1c7112bc,0x00073b6b294cda6a,0x00051854d3181244,0x00049ff216ce9bf7,0x0000f5f14402d398},{0x00056e372344bdbd,0x0005f3af02909e50,0x000f436065b91304,0x0002579f8c7d59ec,0x00001766823e2146}}, {{0x00027d200e7695ba,0x000fb3189e800ca4,0x0006d1d4e8ef137a,0x0007f003750fe0c1,0x0000dad25c5ac540},{0x000807804fa82f49,0x000994fe616e2c00,0x0008e610d4715daf,0x00004e1739c25f4c,0x0000a1ed59eb55e7}}, {{0x000c966787f80791,0x000d43a4f0d56f34,0x00077d92507dca1a,0x0006bb24b961e404,0x0000a0d775222852},{0x000bb6d594089b2b,0x0004142864fee422,0x000a2f57f8c8c37e,0x000969659c1be93d,0x0000e98561f48eb8}}, {{0x0003d36eea5a411b,0x00083c9b809b7ceb,0x000b2ef3bd41c883,0x0005fa4368a41486,0x00005327a94036a4},{0x0009d81a294550be,0x000028a328cc987f,0x000b405a4a382a8d,0x000c01dba0a3bcd2,0x0000ecbc7c687492}}, {{0x000ee9ea4399d83c,0x00029ade4d559419,0x000d914e5643a410,0x000194f9bdedafa5,0x0000ab6a2f9c77b5},{0x00023fc56d6b71dc,0x000ce1637a55a4a5,0x0003af1fce4bba9d,0x0002a5998eb19a51,0x0000fb6b0a026533}}, {{0x0005384859f3a770,0x000970cb98fe684f,0x00091d11cbfe5c75,0x00014fb3fd60fbe9,0x000024a2c6896e9f},{0x000a7731d1c175f6,0x0007bf7b59e763bd,0x000880e35c8c898c,0x0002e8c923d4606a,0x00001705d921c944}}, {{0x000bd17983bec34f,0x000e79390d458714,0x000fba44f409e51f,0x000e5b503e976403,0x0000bb28b50bfeca},{0x000460fc77585d24,0x000439ed5d2c53a7,0x0008896e3f104db9,0x0000d454e5ec4bcd,0x00005c92699d9c5e}}, }, { /* digit=36 (1,2,..,8)*(2^{144})*G */ {{0x0000693a18674889,0x00096e1c63c4962c,0x0008d7b6a10d190a,0x00003a26b50541e8,0x0000e282f1e08996},{0x0001ed4e5703fca0,0x000c04e0117f203b,0x000258ac6a79aec7,0x000248c44245f196,0x0000ff00eb7253c2}}, {{0x000d0301187bc101,0x0000eb6700a1acd0,0x0003f09695693995,0x000f3e0bae823fd7,0x0000bc494f5d06f0},{0x00015737c0a7b0f1,0x000bfc989fca8cdb,0x000b4882d64acc9e,0x00080e66f970d01d,0x00002a01327ea3d1}}, {{0x0002887ba15c20fd,0x0007d9c6bdf22da8,0x000f0e54073dbcd2,0x0004f3951efbc432,0x0000469ec570ed01},{0x000deaa2e18dbfd8,0x000c5dab920ec1de,0x0002fe53ea59ef2c,0x000e8af47d0d7e8c,0x000015e430f8b3be}}, {{0x00062dbbba9d84ad,0x0008b4ece53c2d04,0x000d18184b2003a6,0x0006765b0779d897,0x000067fc9538f5d6},{0x000035f7ff931704,0x00005f2cafe37b68,0x000f6c983617d6e7,0x000df03fd273d1eb,0x0000249da2e138a9}}, {{0x000807b1c5ae6f72,0x0005a0f296c9005d,0x0009a3033a160965,0x0009f56d44b9094f,0x0000c6b826d12c11},{0x00092c2460ebcfff,0x0002ddfbe7133835,0x000e27e80740bd71,0x0003a6cdc435e063,0x00001a2aeff08bc3}}, {{0x000bb88baca8d454,0x000d95a2093c22a9,0x000139b7af41216f,0x0005e33b6ebd0bd3,0x0000663daaf350bc},{0x000c3aa8010516da,0x000ab3875c1e3b2d,0x000fedd69c7bf698,0x00045728dbd2ac94,0x0000085149b36be5}}, {{0x000d63c348e3925d,0x0000c0016e23e9d2,0x000b7a687e98afd3,0x00043c75ccb220c6,0x0000b36999ba7a86},{0x000e9f6ec46bda19,0x0002519cdc0bcb5a,0x000ee0c0acd4376d,0x000092de470f18b3,0x00002848124d0362}}, {{0x0009d1febf2de9a9,0x0008bc77e6c55202,0x000fb2e7eb995763,0x0009cbd6dc27df9e,0x0000444476cdaaa8},{0x000ba7ced0785f36,0x0004b9e93470afed,0x000906fab0ce1fe7,0x000bf2f043e6a966,0x0000d9c1876fd26a}}, }, { /* digit=37 (1,2,..,8)*(2^{148})*G */ {{0x0008d94f6be7acf2,0x0000341338d6e434,0x0002fc6886610503,0x0000f96ca56f7dd7,0x00002f54a7c972af},{0x0003e19d89ed269e,0x00005bb2ef8279cf,0x000a1736ca68762e,0x000fbb351d575465,0x000061e8deb175a7}}, {{0x0002aae2b99711c5,0x00031ce51efb3108,0x000412e3130475fc,0x00003c959cb5b2eb,0x0000efeaac806f9f},{0x0004837f98bf8cb0,0x000da39411aa636f,0x0004e03d299b3bd8,0x0006376b77152ecc,0x0000b7bc15a5f18a}}, {{0x00083eca38629302,0x000f164b71698f58,0x0002173c96261574,0x000a82abb6ba418d,0x0000a7d774e7d73d},{0x000c1dd5576a4dbc,0x000283ff3437f24a,0x0001f86ddde594be,0x000503b65e910b43,0x00004e079387d0c8}}, {{0x00039d3ee2963f2f,0x000233a626332d5d,0x000281c47c620310,0x000452fa27bc3883,0x00006bc300c4cda7},{0x0004c341a09ee9c3,0x0003ad3e7676b0dc,0x000f36ad1e76c678,0x0007b36a8620e35f,0x00009710f4c3af53}}, {{0x0000e7c2becbd6ac,0x000da1cf405ff065,0x000cf786bfcc5059,0x0009287fcebac86b,0x000006628092b297},{0x0003a21f33a3f231,0x0006f95fa90d7679,0x000b52ce8c481fe2,0x00088d46dae60eb7,0x0000dd27b34c3095}}, {{0x0007112386fc20ce,0x0005122369b87ada,0x00088beb81cf895b,0x0008f96663c00e5d,0x0000786fe6f72494},{0x0003cd4c08b1b97b,0x00066986d9bd5f51,0x000845f5fa36c27c,0x000c259b22dcc7e3,0x00003a7a6a264018}}, {{0x00014104124194f3,0x000f16022caf46b4,0x000f5955fa3d17a1,0x000fa544e6a45dd8,0x000027f7e6432277},{0x0001bcd329f0aee1,0x000ac1241de97bff,0x0000cbc3ebca8120,0x0002c1f37b8547b6,0x000028b36f4746d4}}, {{0x0004a07f82ebea7c,0x000b5769bb816483,0x00053090a14d150d,0x000e04062d69eb48,0x00003488c7727160},{0x00062b085ef31ed0,0x0002787bbfb55541,0x00004cb77b99391c,0x0007343a0b06ed4d,0x00001334165040ae}}, }, { /* digit=38 (1,2,..,8)*(2^{152})*G */ {{0x00027d09f86b87a6,0x000672f7189e71f4,0x00081c5287eec6df,0x000edd421c643874,0x0000dd3e802a5f6f},{0x0005cba1123d99ff,0x000318f38384a7a9,0x00041aa78a8746d0,0x000ea5919aac3acb,0x00001546626df6d9}}, {{0x000842e7e3646f13,0x000721aaaca5e9b7,0x0000de2e53b43348,0x0009b4ef6518aa52,0x00004c1f8413e3b0},{0x00027091000d9504,0x000ab656868a5489,0x00024df86b81806a,0x000fc7333d963bd8,0x000027dffecf8b57}}, {{0x000032dd3467eff0,0x0002e48a105fc8eb,0x00097868c757cfb0,0x0002c3180769d754,0x0000bb784982ad6d},{0x0009004e124bcf40,0x000e6db020b0aa69,0x000f6d64792a4968,0x0003db95d05137e7,0x00009c7931f4b21a}}, {{0x000de8cdd0926a17,0x000b2a7d298c241d,0x00097897af2c8ee1,0x000fad3dbe3b697b,0x000095a39dc131b2},{0x00088519ea3f0b69,0x00087a75a4d2604d,0x000e93901ec55560,0x0004fb6cc27154d7,0x00006bfc52e1469f}}, {{0x0007c1ff4bc6220d,0x000d7f796ea6ca1f,0x000927b7292549f1,0x000438045567cdc2,0x0000e37c17362496},{0x000832367b234acc,0x000ba574b6cad39a,0x000411ee7dad7e6f,0x0009c31fb3d58d63,0x0000883b19b2637f}}, {{0x000d28e06912ab7f,0x0000d9f0e4938f75,0x00097f5a913534b6,0x0006ee5cc58d47d6,0x0000cf8cceb8bae1},{0x000d0bd2f66354b5,0x000c029210466f66,0x000f599a7c02757e,0x00079b57a2af1152,0x0000cd4c1d2a65b6}}, {{0x000d0b153348f81a,0x000e92af416448df,0x000fef6bc43dd5d3,0x0001354ae4a7e8c0,0x0000c6d13c9cd270},{0x00067cecd88b842b,0x000ed48d98b5ca3e,0x000c09bcc716fe72,0x000f7af2ed01fe5f,0x000018e9887155d6}}, {{0x0002571fa1c005d3,0x0000a1a7cb1282c7,0x00064bef7798f823,0x0000303b2a08d762,0x000094b95e409f27},{0x000cc832f936b83a,0x000392ff22dfd98c,0x000633bedd944ef9,0x000cfe67a87ab01a,0x00004e149b05af22}}, }, { /* digit=39 (1,2,..,8)*(2^{156})*G */ {{0x0005d70b7657b7a1,0x0007085ca8d9d1ae,0x000cf3b0d35bf0d7,0x0000cc024adf2c77,0x000069d110cf7a09},{0x0003a7564e157769,0x0001d506260e70ff,0x000703a97ab76d5e,0x000435a6439d75ea,0x000076aec3e36360}}, {{0x0002f99d592d4607,0x0009d3e3fcd3efca,0x0004150ef1418504,0x000f73feadd26c03,0x0000c8303bb7708f},{0x00028bb4209cedef,0x000e4552f1da46cd,0x000d486f19b140bd,0x000e6167872c3f8c,0x0000b4a36e89cdf5}}, {{0x0007709b7b97f8c5,0x000cdd2e7417ce17,0x00011f9e4c798c2e,0x0006edf1eff42bc7,0x0000d3407d05f1c4},{0x000b2930ca06e395,0x000de1dbe217f2cb,0x000ca08df0ad2e70,0x0003a3b592af2a8c,0x000040a4a94b9f52}}, {{0x000cf60f96d10e48,0x00095daf176f2c08,0x0004556116c14d5c,0x00025e7fb01ca460,0x00006c4e588656b4},{0x0007fb754d3440e4,0x000851cc9071c4aa,0x00038c48b2b6677b,0x0005b2981fd58874,0x0000cc23558b384c}}, {{0x000981afc00085d1,0x000d0d5af71013f7,0x0004926c19866a71,0x000ed9fa0e68216e,0x00008c7bcfc44bd1},{0x0005694612f9623f,0x0002b679449f0e1f,0x000d14dea79b08e7,0x0009c8b2286cfc4b,0x00000d346cc223b8}}, {{0x0001287ee355832e,0x000a8715bde48f8d,0x000250613d9a672a,0x00086c08ac970387,0x0000dae19fd8bb71},{0x0005fdcbcf36d30f,0x0007974db1dbf1fd,0x000ac30ebd07464c,0x000637413ea46588,0x00007cc18fa7cb4d}}, {{0x0008561eaab750ec,0x000fd959890272db,0x0009861b1b6617ec,0x000313bb875f3432,0x0000725d0e14f52b},{0x000a16eb56377ba8,0x000efa08332aafd7,0x0004f969b00c6f26,0x000e75b6f9b0d8bb,0x0000fe905ed9a6d4}}, {{0x0009badc329d1f15,0x000798a2ac13e274,0x000f04f6cdc35ac5,0x000fff5624494f6d,0x0000234123bdb8fa},{0x0003d01cf2e4388b,0x0001a41004f7571b,0x00002b4c77fb6c86,0x000ef3131bac67d1,0x00001a55a5e1aed2}}, }, { /* digit=40 (1,2,..,8)*(2^{160})*G */ {{0x00010ee253308b7a,0x0006b0f6d3549cf8,0x000f79be840ba3a8,0x0008682b46f33696,0x0000b318d895599d},{0x000485717b66f888,0x00087e17159bb2cd,0x000da105c3fffe4c,0x000a76272f7dfbeb,0x0000bfbd7894f96f}}, {{0x0005fd5fa205d0f4,0x0004ee8ee36860ce,0x000c5b16628b839b,0x0003f4e13daf04df,0x00008b3aaf4c153e},{0x0004e879df3f3f34,0x00029941a4e0551e,0x000d33e8877228e4,0x0005911236772cfb,0x00007681b72c03ca}}, {{0x000b1aad44ef0b79,0x00091a9b898fd522,0x0007938044627d81,0x000438af82fb38a5,0x0000b4a5e385644c},{0x0005a947eeafb773,0x000c02e7cf2c0846,0x000e9dbe8a7ea8fd,0x000b6d78d1c57d96,0x0000586ca615cf4a}}, {{0x000e349a4b31aebd,0x000f2b0285b94916,0x0007b017d6137900,0x0002b0dab01a0be8,0x00008ac2977211f9},{0x0006974d05362415,0x000fd464a1c6a163,0x0005f2a0e55b98f7,0x000493f71d99e6b6,0x0000a0e9ca0b6129}}, {{0x0008c8ce34c9e3ed,0x000c916fdd5b8549,0x0007be5fa36b2b51,0x000ae2fad592549c,0x00002d134c65513c},{0x000e5adca237cbc0,0x00077e7e9090b363,0x0008cd9cdf14f0ed,0x0000cb97467fc3ab,0x0000a00ba453f572}}, {{0x000b8f7229523466,0x000e3a1cfe89d80f,0x000cdf0d11487037,0x0009c00d2b42c026,0x0000172110f51188},{0x0009ff21f71bf171,0x00008ecd850935b3,0x000c9c32bfbbecc4,0x00028143434c1a74,0x00001cad52349f90}}, {{0x000ae1d3d9866434,0x00034a7b3f85ff0f,0x000c1fa6ac6b4768,0x00077b494acd21cd,0x0000ad41f3fb547f},{0x000c5c3baf25baf6,0x000e8ce8a1c5d92d,0x0003fff5cbcfc843,0x000221dedbca01a9,0x00005c09e40eecf1}}, {{0x000d9cce837c6d61,0x0003d148f9290579,0x0006232b855bab85,0x0007c64ce7a64ae0,0x000028043d63ffdc},{0x000f181a75f69e00,0x00059796e93b7c7b,0x000172a383b1d5d0,0x0000029a0e1e4709,0x0000b9ee91160db4}}, }, { /* digit=41 (1,2,..,8)*(2^{164})*G */ {{0x00026fc9c4cd4abf,0x000e23f1402b9d0c,0x00026a0bfe9f0668,0x000417f6e573441c,0x000042560b13ff8a},{0x0003ef07f65b14ba,0x00061fd7493cea35,0x000ec7090c603bd2,0x00077a68fd05d4b3,0x00006ce1efdc940f}}, {{0x000f63cfc83f45b8,0x00011d646ac49d20,0x000b73afaae16770,0x000dca23842c77c0,0x0000cf54b1e93428},{0x0004dcfda1adde56,0x0005a1bc6441f959,0x000957b146ed74f3,0x000a15bba7d38f71,0x000080b43552bdca}}, {{0x00014e77a0de8421,0x000cc45526f09fd2,0x000c5fd9ac6926fb,0x000a7dc8de8a4f10,0x0000d25068992420},{0x000b6cda791fe0f2,0x0007b7314faa40ec,0x000b3679170d12a8,0x000c08f3e767867e,0x00000e1e221077f7}}, {{0x0000cd9c328d84f2,0x000ec10296c36eff,0x000191f73e449397,0x000f344da7ee8967,0x00003d52cf283e17},{0x000adab3ad961303,0x000c8f7e455fe908,0x000af39881456bea,0x0006ae1ec3fb53cb,0x00007d83567df6b8}}, {{0x00097128795b26d4,0x000007d53b618c0e,0x000b80b150a9c145,0x0006c0564c424f46,0x00006ae4b9ab6582},{0x0000d841a1380e4e,0x0005832f815561dd,0x000502e81430573a,0x000171a4f85f48ff,0x000063896020863d}}, {{0x000f7199dc46d818,0x000722b599ff0f94,0x00073193628eba9f,0x0009137f368a923d,0x0000ee5360c30393},{0x0004f710bd7921fc,0x00093f6e46f2a79c,0x000d25010260474b,0x00092d27c08b5dea,0x0000fab67c859c32}}, {{0x0004828817b2b97d,0x0002c0f0e0b040d2,0x0002217d0167ff6f,0x00040e422baf02d8,0x00006eb8e36ece4e},{0x0001f86203c5e993,0x0008a31113ec3567,0x000da3f78ff4f368,0x000ea84159e48861,0x0000bb7e93050f1a}}, {{0x000e3d7a82a07312,0x000248b4ed80940f,0x00057c32545a8fa1,0x00024459f67e6d05,0x0000781e5623c72a},{0x0009422f1dd9d9ed,0x00045027e096ae27,0x0006ab7164488446,0x00002f2fcb1f3e1e,0x0000a08771e4d556}}, }, { /* digit=42 (1,2,..,8)*(2^{168})*G */ {{0x000b1adfbccd5f72,0x000bafb9db3b3818,0x000e49c42a8e58da,0x000a5741f9c3a2de,0x0000e1b4d1992caf},{0x000d2ae779d25bd8,0x00001397e053a1bd,0x000689b00f8d9c66,0x000aeefabee2be5c,0x0000ed75eb0e9aae}}, {{0x00070ef12df3aecb,0x0000e7a205b9d8b0,0x0003fe5865a61087,0x00049560e6eb8f06,0x000018c288645dc3},{0x000c1f205200dec5,0x000d0053bcc876ae,0x0007bb212c914ca5,0x000c3165e12a7533,0x0000fee6eaee8fb7}}, {{0x000b625175d3e131,0x000ba79b6828f364,0x0007b65b0a28d9d9,0x000a31a0c9d7a025,0x00003f761efd974a},{0x000cea06f50c8e7a,0x00025dd9669b6210,0x0006ea0e74a30782,0x0007f7cbc88a2ca5,0x0000eefdd32a930a}}, {{0x0006927bdc72fcef,0x00092b5c4e83d33c,0x0008986accaed0f0,0x000ee5e0fd9f3587,0x00006fc2b4d5332a},{0x000bd4c284a559fb,0x00092f79f9e0f036,0x000e91031f24a068,0x000494df12868661,0x000064b67a214c5a}}, {{0x00038062d4c1e75b,0x0004591289a8619a,0x000fc2f14e9e6431,0x000a96b32ef796e5,0x0000cf84b53f10ce},{0x000e2d93f2a93799,0x000b1200573274eb,0x0003eaf97fa1c33c,0x000a47520d07b67e,0x000099241c28bfc2}}, {{0x000e16a8fa9459c5,0x00069533f36d1411,0x00042fe5fb485de4,0x000223d3ae84bb3d,0x0000362e47c092d7},{0x00051ac53cf453e0,0x00072adddd472e03,0x0006d8041bea2700,0x0004e95997d405ee,0x000072103589e10b}}, {{0x000c45b260b78e4a,0x000cab84444896b8,0x000f6cfa759ac76b,0x000f5fe7d64974d2,0x0000fc1b25688826},{0x00018f2e67924f42,0x00079c2d84634875,0x0006ee2d190516ad,0x000a501c0d1b2b3f,0x0000036290195036}}, {{0x000578dc4ce14fbe,0x000b08c06d75fc1f,0x00063cd0cc5274b3,0x000f629dd2dcf7bb,0x0000f36db3fef100},{0x000304c0d907ee38,0x0005103df2ce7a06,0x00083934eed34414,0x00075ccabaee3628,0x0000f1816df3580c}}, }, { /* digit=43 (1,2,..,8)*(2^{172})*G */ {{0x00065ca49bf70465,0x0002633070d3aab6,0x000b33d03149eda8,0x000f82c732643672,0x0000dae397b7ff25},{0x0005986e7c2b0613,0x000c759b3efb9983,0x000ccf96a4c52f87,0x000f392308a5b922,0x000053a40c602f11}}, {{0x00003172599604ef,0x000e04fda79e5acb,0x0009d5feaf05bd45,0x00080866e68b83b3,0x00000b424807d53a},{0x0005296e9538c34c,0x000381ac5ccc2c46,0x000ad873e1d42e72,0x0005408bd7d7dc96,0x00006a74e1c17bc4}}, {{0x000cfc53b4244564,0x0004fedf0290a8fd,0x0005ee4b6fd35ed5,0x00009974fcae8196,0x0000c1f220ef19f4},{0x000bedf5f9d4ef28,0x000ca3c4cb632f9e,0x0005cd318a6d91a9,0x00094f00ac42a1ad,0x0000689a17da238d}}, {{0x000fd495f78c275c,0x00068cdb30cfb3a6,0x0000fcc91ed14bb9,0x000a17ddf6d09b8c,0x0000645d0ce04a7b},{0x000dc229b0415b16,0x000009f275264daf,0x0005e7bb59b2b9b3,0x000525c2280c2b74,0x00002b3172744708}}, {{0x000e98378c350e3c,0x000c25a59b0ff628,0x0002b1fc99481f98,0x00035431d25ec81a,0x000068a37387c1fe},{0x000ebf428f4945e2,0x0009bd6f48485983,0x000f243e60db09cd,0x0002efd4687f2c5b,0x0000e57b62bb98a6}}, {{0x000fa5e9a55e99f0,0x000bc7ad0d350a3a,0x000860b4358a0879,0x0008b504684f6ebf,0x00009bc6954fb2b7},{0x000e47f1dc72cd57,0x000587c1cdd69b63,0x000020a0729886ae,0x0005a9f2a64081a3,0x0000092024e42c9f}}, {{0x0008186df8037536,0x000287fb7f01d83d,0x000a6db487d36c22,0x000fb5d0f5f1f860,0x0000704dccf6c287},{0x0004aaea176b654e,0x0000fa01720468f0,0x0000fb9b626920a1,0x0001293ca4247726,0x0000473f7f1fa757}}, {{0x000fc20755e3176b,0x000828452666a58c,0x000016e7bc6ccdba,0x00078f9084bcb6e0,0x0000554faca4c643},{0x00094e142cf0b0d6,0x00046505294dba30,0x0006822fbef1afda,0x0006df474a30ba28,0x0000e6be6e6ae1a8}}, }, { /* digit=44 (1,2,..,8)*(2^{176})*G */ {{0x000b296904664fc3,0x000b53e979f39254,0x000a642320a351cd,0x000cc34fa1efd130,0x0000a26d827b4096},{0x000df088ada01cc1,0x000d534b9db65b69,0x0001656914dd4d71,0x00018a2f335c82e3,0x000058dcd3dda1a0}}, {{0x00008fc59cde3468,0x000e7124237b64b8,0x0009635d376aaed3,0x0004ff5d8688ebe9,0x0000c1b55d497018},{0x000b143a98f532c8,0x000632ba3585862b,0x000532de58edb3d0,0x000ebfa9bb66825d,0x000060efc436424d}}, {{0x000f8f66b8a7cdf7,0x000c324f111661eb,0x0003f176844bf6c5,0x00056be78edced48,0x0000217f1b2be94c},{0x000ec85fbc8973e6,0x00067f4d7ed8216f,0x00068f645f12fdb9,0x000735154bf07f37,0x0000c3cd2d5edd0f}}, {{0x000f53916fc6beae,0x0001122765fa7d04,0x000fce16c2004cf7,0x000c22d9859805be,0x000052df10ff2d7b},{0x00099f450e1f9830,0x000c61f33ddf6269,0x000e06e68bf551b7,0x000e86ee34206238,0x00002aa249bfa9c5}}, {{0x00047aa4c7ac2b3c,0x00082731a3a93bc2,0x00057da03752d6c3,0x000d7d2fd42bbf46,0x00008348bc06dd42},{0x000825653cf027b6,0x0001032f60c77da5,0x000a69fded019b66,0x0001dc3cf6ffbc26,0x0000333cf94fd444}}, {{0x000ddab96e59ccf0,0x00077ba4a493b31c,0x0001ce1d36b7f226,0x000c8a14b54f20a5,0x00001a428916f43d},{0x00047a670dede59a,0x0002d0aed25ea138,0x000afd5154d9620d,0x0009faac5fa1d09e,0x000024f267bf7958}}, {{0x00017e76ea8b4aec,0x000d995d314e7bc2,0x000b24fa2303625b,0x000d3e9d32ee7464,0x0000fd86bbb7517e},{0x000a5817e3ed6c66,0x000681fe7cda917f,0x000a903127323a60,0x0005ae96b12d8016,0x000044afeb2ca0b2}}, {{0x000b69cbf65aaebc,0x00090c5ac751e7b7,0x000281d845c75cee,0x0002f93c693f9647,0x00005a6bb7c3dc6e},{0x000be7048732b0cf,0x0003da2f4bf94e19,0x00085541905b0af8,0x00067070b1a5325f,0x0000e3a10d49e546}}, }, { /* digit=45 (1,2,..,8)*(2^{180})*G */ {{0x0002dfa557bfa495,0x0000476e1337c262,0x000db45dc38dd4f8,0x00012d3d96faadeb,0x0000c13ada75bd32},{0x000c6ca5801dad5e,0x0007c17be93c6d61,0x000188985039af29,0x000bbefa124866c6,0x0000462261edbc6f}}, {{0x0002edf52c078d85,0x000c57dd4b79bb87,0x000adfda839ce9d2,0x000ba33e8aee806f,0x00007fc8b3dee585},{0x0003b2818874b38e,0x0001a4e2127015a3,0x000069054d6b7749,0x000ba60c89051d0c,0x0000fcc7ea0acfb4}}, {{0x0005464d0e55495d,0x00003ed9aed9f40e,0x00006de43f8b680d,0x0007a14ea70ca6ad,0x0000ab349a9bed40},{0x000e0296a877751d,0x00012dfd9e535ef8,0x00070ac681b2a37e,0x0003f0788abf57ea,0x0000a2d6ecfa6e9b}}, {{0x00063f4153af6dcd,0x000c683171b445fe,0x00029af26bf85199,0x000cbbae89bcf21e,0x0000e2560e6db219},{0x000e1d75ae224a6c,0x000f6a930add43df,0x0002cb637aac5049,0x000bc7d6862ebb14,0x00005e73664b3718}}, {{0x00093a787b955171,0x000d06e1f017d5eb,0x0005bd3a711ff605,0x000a317a03753339,0x0000d94a848d4553},{0x000d57bd8e1e0fef,0x00062a2dcc99ccc0,0x00038d4cbe8fa59c,0x000cfe9d5c134b41,0x00007c0347ff2191}}, {{0x000145c114649f08,0x000f3ccf0bcfc46a,0x000e148a3dd22dd7,0x000be895b3a822ac,0x00007ff5e819ea62},{0x0001437bd32a8c35,0x0004c538be17bcdc,0x0002e928c1bccb8e,0x0008a932f01e867c,0x000082bf7d9a8a3a}}, {{0x000d10ec409dd077,0x0005b006c19d4c7d,0x000704a0fd36352c,0x00021c0e8a0f3c43,0x0000f1b113eab5f7},{0x000cbd604ebce52c,0x0003d6cac7cd3e1f,0x000b62675f9792a4,0x000ca4b06ed3714e,0x00007ff6667d89a2}}, {{0x00080034798ca4d4,0x000f2c7af8685c8b,0x000d778ecd30d2f0,0x000cf952ad4c1c8c,0x0000e198f05db898},{0x00063d51806a84e5,0x000e1e52eca3cdb7,0x000b75c78219120a,0x000a6e0cfea1db16,0x000052a4a35bae24}}, }, { /* digit=46 (1,2,..,8)*(2^{184})*G */ {{0x0008e13092cf573a,0x0005c3f4c8303203,0x00005750d3512460,0x000db40fb842c7aa,0x0000494598d37817},{0x00077989cb6b3d8b,0x0007062757558f1a,0x000150731ef6087b,0x000f58b273cc3e83,0x0000ffa7db45a98a}}, {{0x000d84601a040653,0x000c4f4b0166f7a3,0x0007916814ccaa7c,0x00080f8fdfbd3e3f,0x0000bdc4370992dc},{0x000a6279f7786e45,0x000a95c7c1620b02,0x000d01014b0992a4,0x000fa801eba68b4d,0x000052fa0f983aed}}, {{0x000a03aee51cbd7a,0x0003eb0b796d2197,0x000eba706ef4966f,0x000307cf5c3e95f4,0x00007329daec404c},{0x000aacb62b09eeb6,0x0000d76f53a89aa8,0x000109dd72b102e5,0x0003bfa4f0d8af9b,0x0000584ec8a3c986}}, {{0x000a4c97a4abc3b1,0x000629f8f5fcda83,0x000483a1c45951ca,0x0007bee77f3e558c,0x00000e48e3d45037},{0x000f9b7025a36d96,0x000524bf6dce6a73,0x0005d44b52ac36ba,0x000ec10e9ff373d9,0x00005254e73f1733}}, {{0x000f6e149c30d036,0x000786c252bd4796,0x0009a3476ff36be0,0x000f9406305e0f88,0x0000f83a58f41674},{0x000e1a0a8596c4ab,0x000785cde601a897,0x00087559b39a4f3d,0x000826d27d17bbe9,0x00009be39f3ad611}}, {{0x000e3c3c1d7cda3d,0x00032ea87baa6279,0x000158ee6a629579,0x0004420c958c1fec,0x0000d64ac7b719e3},{0x000792f805f03b27,0x000eb7b2bcfe0b0f,0x0001327ffd07ff8c,0x0003e8c973510710,0x00002665759bab58}}, {{0x0000291d43fc236f,0x000e82235e6fc06c,0x000e4b14f6918efa,0x0006704723477728,0x0000cd51067b09ae},{0x0009f8b71be82198,0x0002467cec5a196b,0x0003a235d360dea7,0x0004c8451deeb31e,0x000071e8bcc32913}}, {{0x00005ab8b7207ede,0x000a6911a335cc88,0x0009e9fe5b2d6bb2,0x000344b19563459b,0x000063bbb632aaa7},{0x000b647545ffb149,0x000c9da8d006086c,0x0009f1914bb72b13,0x0006fefd76ca4846,0x000088e4372592ac}}, }, { /* digit=47 (1,2,..,8)*(2^{188})*G */ {{0x000cfd57c06983bb,0x00098e453544774f,0x000b3dde4afbe78c,0x0005fb6f5834d0ec,0x00007bae9c3b3751},{0x000ee4d65bdcce8d,0x000ab3dd6901b1d3,0x00047673a7680203,0x00093d2623b49fbb,0x0000be9b2e57312a}}, {{0x0009ae30f9bf470b,0x000087d0d63d1fae,0x000118fba7a5a59e,0x000fc5809658fc05,0x00005a1e22227a90},{0x00083acb655ee723,0x000edd1818baf918,0x0006032f40bacfef,0x000334844e27e9e0,0x000040f4d53495bd}}, {{0x000363b0cc192c11,0x0001d774e6daae2d,0x0002caa668f0d453,0x00082567e7b3ae0e,0x0000eb18f19fbe78},{0x000e6d2a4ad162d6,0x00046cf309ae93b1,0x00071ab3a096ecba,0x0002c0901a3f80be,0x0000db5da2662978}}, {{0x000ee84e265cd5da,0x000988dc2c6ff707,0x000f46f3d40f2a5f,0x0000c9df979d6122,0x0000ed01e35bdcbd},{0x0002d0793015eb1a,0x00095b063cd880a6,0x0005d2a436307bbd,0x000f365423f3ea7c,0x000081c0177d53ec}}, {{0x0003403ae96daf9b,0x0005aaabeccefb5d,0x000862e19cddd34e,0x00005dbc1cf56ede,0x00001050a209e4e5},{0x0009710fdf7e6a41,0x000c40de8785a64c,0x0006cd11554ee79f,0x000527d0210f3d64,0x00003c2dab8fffd1}}, {{0x00065f36c733ecb7,0x00097438a5807cef,0x0002edb163b75a2e,0x000e8e6daad28389,0x00005a009a4a047b},{0x00026231865878db,0x0006b9ea60d32b2d,0x000a6c1f604286b8,0x000e303b5ee93df4,0x0000ae2226c13edc}}, {{0x000f246cdd4e3845,0x00068e73245980e9,0x0006e1e20523881d,0x000db26e1a6f5965,0x000056940ffbe18c},{0x000cde6b503aafdb,0x0005617f961ac0ef,0x0004eefd32ca8809,0x000b960d1c8a741b,0x00006dc0bf51f631}}, {{0x000968734e4dd7f6,0x0008df9dec31a21e,0x0002817162256254,0x000a3ed65988c8b2,0x00009bb859066057},{0x000f94739f3adb65,0x000858f5da6309bd,0x0003e25d5a77565c,0x00068a42110f3a62,0x000053d37190038f}}, }, { /* digit=48 (1,2,..,8)*(2^{192})*G */ {{0x00003f3e034d81e9,0x000580ef4f8b16a8,0x000e443be8670976,0x0001a9ec197241af,0x00001dd783168b20},{0x000097440f10fef1,0x00018a804dbec69c,0x00067b238c506e04,0x0008f287fa83b85f,0x0000d016711f649c}}, {{0x000a1a96613ebed5,0x000aaa0b311898c7,0x000452f4160400b5,0x00055fbbce2a272e,0x000044105e96f0ba},{0x0002280dcf97d62e,0x00039cea1c8cde9a,0x0008d0499e144dcd,0x0003fe7cd9d958ba,0x00007fe9ad9ee6a5}}, {{0x000320c5cb34fa83,0x000c1a43794f8dcb,0x0009951b966af168,0x000a28da0dcca923,0x0000bdaf4528f40a},{0x00083be9a0dbe4b2,0x00076ff47b50a951,0x0001b6b449d08629,0x0002b4f53933e3b0,0x000077b42a87e4bd}}, {{0x0000a02b0eaceafd,0x00088c341dca5663,0x000aa7c1ff9509d6,0x0003070fb7de7fed,0x00009716331f83e3},{0x0005f449ec69c78b,0x00092aa2fd3cf36d,0x000709959bb35e00,0x00081dc33d131954,0x0000174691c29863}}, {{0x0006166b44b3b527,0x000e8abe085116b3,0x00055111e7cb7191,0x0000aae2f04a4337,0x0000b8cbd7d43a2f},{0x000af71e91ff6ddc,0x000673cfd4b322cf,0x0006bf828cbf933f,0x0006d39eb726aa81,0x0000f4fde56a46c2}}, {{0x00081dcee597d414,0x00087dac97e65165,0x00006a1325b93f7a,0x000a0d6498877936,0x000087e6a262fd86},{0x0009a34fc66e7cce,0x00055918f483f148,0x000c479481754c72,0x000f76c426d2dddf,0x00002d39a7634863}}, {{0x000cca31c7a57625,0x000ade949dee1686,0x0002d160c071cd59,0x0001de16a1ae0522,0x0000da394a68f678},{0x0007da93fd13da3f,0x000971d9bc499082,0x000cce082821a131,0x0009544ac4a9b4a8,0x000025d76c70fa80}}, {{0x000e658aedcda8bb,0x00031644cd8f64c3,0x000fe937f063f6ea,0x0001e975658a2d78,0x0000049c304fd752},{0x000473ffef5b241b,0x000792e05da59eb6,0x0002a9683732b03d,0x0000a6487ba3d60a,0x00005d72e137e219}}, }, { /* digit=49 (1,2,..,8)*(2^{196})*G */ {{0x00099ee566eb922a,0x000364f692ac542f,0x000028dcac6c9771,0x00018cfbdf079ffe,0x0000610be982fc2a},{0x00013889ee80e815,0x000511fd62191997,0x000663545a2e0935,0x0008cc4048c883bc,0x00000920149ca0bb}}, {{0x000eee0c0ea6e1a4,0x0009b8f81a1b3bed,0x0004ef395891f049,0x000e351f74f3ce14,0x000069aac489bd81},{0x00027729a694a1ff,0x000aec0d39e25c35,0x000071f076d9e952,0x0002d5b584061982,0x0000a6863991eccd}}, {{0x0001ad919aac7231,0x000d837b1b76ba6f,0x00045b7295421df9,0x000677d0a1a2eab8,0x0000c06c35fd7a6d},{0x000314874f18d1ae,0x00031b807ea7b0ef,0x000e4bc5643a1ce2,0x0009b5aabedf5496,0x00007faef00cb014}}, {{0x000747ea0bede08a,0x000e0753f73f449b,0x0007d5fd126e01d1,0x000e0524d1d1c94f,0x0000db80899bb94d},{0x000c10697e01e74f,0x00074fe228d291e6,0x0004d7b0c0585031,0x000c5761635b804b,0x0000e6909f3f3acf}}, {{0x000a8f2439972c6b,0x000d88f0876fd4e6,0x00071943cf4a2c61,0x000dcc9cb45f0c30,0x0000274cda09b319},{0x0004426efde75793,0x000b01b65ccde7b6,0x0007c3a4fb720a13,0x000dcf1d741e2cd1,0x0000483cddf39166}}, {{0x000d32fba5127c0b,0x0008344fc94dea3f,0x000edda3a50b098e,0x0009531ef34c8cdb,0x00009ea6e5479af1},{0x0003173f9743bb5a,0x00036f6795dcfb75,0x000330414c181516,0x0006467c0fef01b0,0x0000608f1137cc86}}, {{0x000731021c804f19,0x000272aba16f73bc,0x0003c5c8b7dfaace,0x0001fdebf2fb3101,0x000060e66ffcf1c4},{0x00051f55a60c6b7d,0x000ca244fee99d47,0x000685a66c4490cf,0x0007f1df74bca48b,0x0000e008421c6eaf}}, {{0x0008949a50ad4589,0x0009c1acb452fdbb,0x0004985e6bffc0ea,0x000efbfd931ee696,0x0000aba564d3b7e5},{0x0007a12f75fecfe0,0x000a3263c88f3bd1,0x0000c37c6a1321bb,0x00004ff03ab147c3,0x00003bd493c68746}}, }, { /* digit=50 (1,2,..,8)*(2^{200})*G */ {{0x00032811a7abd874,0x000db7881fdad909,0x00057a04e50379b8,0x0002cd9e5cf638f5,0x0000f7d1bc229820},{0x000dd099becd5a2a,0x00089309bbd11ff0,0x000fa633afb561a6,0x000f7a86676108a6,0x0000803fa54a21da}}, {{0x0002ede0e2398f58,0x000858a58d6cd461,0x00057b7853efdb37,0x0008c6b289cb633b,0x0000c7e7d1c765be},{0x0009e66e59813ff9,0x000d162065a6f4f9,0x000ccdd7da21b1ec,0x00007f41cc3a47ec,0x00006d5b783c2d8e}}, {{0x000e4bf888b90c57,0x0004f777b0ac93d1,0x000d5aa9e84f32ca,0x000e8f22ba6e37b0,0x0000c2bfd71f0dbd},{0x00029438c4942ce8,0x00044e04df0ba2b4,0x000d0dcdfb573987,0x0007fc420935d5cf,0x0000d2dbc8e26eee}}, {{0x000aebfa4044443e,0x000fabe67e573e06,0x0008d598ca0bb6e3,0x0007d84c505891db,0x00008b6a89573352},{0x000fd835db9f7005,0x000d7e9e56e55c19,0x00028cd210f50d2c,0x000afe3eb7148ced,0x0000282da8971416}}, {{0x000d8c8bc0a17b96,0x000d956c17706169,0x000d6c4e0e6ccae6,0x000f778455351909,0x000039e97d726501},{0x000386493c5aa83e,0x0003ab6056becfd1,0x00038d0a6a30f997,0x0009bf4f933f1325,0x00003ec9cf3e5b1e}}, {{0x000af546c8a478e5,0x00009fa5abea82a6,0x000929091c0b931c,0x000a611068dc611b,0x000031a3754d6e83},{0x000243fc70d1d9f1,0x00087c7c977ec238,0x000c3b180905907b,0x000f7b3c0a8de294,0x0000453273a39eaa}}, {{0x000f989c69b6cdd9,0x0001b00b008733a5,0x000cf19582ee2e99,0x00082c3d0cba0697,0x0000f5ec6cff4889},{0x0003404faefb719d,0x0002c724c3c2b2fb,0x00084bc2cff9824d,0x00064341f90e02fa,0x0000ab3d02a9a4d4}}, {{0x0009d7b51caacc1c,0x0008509081e9387c,0x0006c2bba30bf8a1,0x000749415fb9780d,0x000016b6886a163a},{0x0009d9971a12e8dd,0x000f041d6d9f6711,0x000897c914fde7c4,0x00037415fba6c1e2,0x000044ff79be19da}}, }, { /* digit=51 (1,2,..,8)*(2^{204})*G */ {{0x000a38783edbf56a,0x0008a62060b5f619,0x0003e197df84183c,0x000ec5565a56f46b,0x00003d764abc2d6b},{0x000a0edc3fc096b3,0x00080a9da710718f,0x000633fc0eb6b9c6,0x000931e875a77998,0x000072910f080d6c}}, {{0x000c351b873ccd50,0x000f849cb198ac73,0x000cd2f12adddfbb,0x00052b678a884a93,0x00006d2e4199685e},{0x000ba6f9e2ce488e,0x000619fe2c4b44b8,0x0006a77f7f29e16a,0x000b9984a580f6c4,0x0000c4fae9993e3c}}, {{0x00043775095179f6,0x00074b65eb03c0ee,0x00038e84cad4f821,0x000c08ad2f19b795,0x0000a815addc931c},{0x000a6a2475d15354,0x000e250bb3ee8a3e,0x000bc6c7e2e9f012,0x00084e0f675eb14f,0x0000728fb5f890a9}}, {{0x00079fb23be5ff7d,0x000b7abd3c095f18,0x000e5d17bb3553d9,0x0003eec8404b261b,0x00004c7b8e343501},{0x000f0ac52ff88cf7,0x0007572dfd754907,0x0004e2b22c9118c3,0x000d179073a97d08,0x0000d6bca24f52c6}}, {{0x00062d8c5230f8f7,0x00029ee4b049136e,0x00014f3cb9c19a54,0x000e78a288b63bf1,0x0000675ced19a43f},{0x0004ac0245017d70,0x000da67379e7896c,0x000206517d607078,0x000c44a6ab25237a,0x0000c32d492b5336}}, {{0x000e008c5bcdd3fe,0x00003fb319d76820,0x0008fc97a392e47d,0x0008db544b029312,0x00005611953b5d34},{0x000d3a1aadc08c32,0x000ab1c0278ca331,0x0006c870390417da,0x0008770cf666f76a,0x0000e48921cecb9f}}, {{0x0000ffc1739db82e,0x000d6ff50f75f9cd,0x0002ad7569ae9e9d,0x000e1e3181d8eddf,0x0000eddba8e1699e},{0x00002aac66c37326,0x000c6e3037d90f29,0x0005d02ad905e85e,0x000d947afe3f307d,0x00000675780cc1ba}}, {{0x000709def8c8c5c7,0x0004c1a567193ec5,0x000a8eed0812adee,0x0005924ddaf3c305,0x00002a0743a5403a},{0x000f431d23ed5fa0,0x000f9830eb2b6692,0x000b5818530569a5,0x000050c164d80ce1,0x0000cf41a7008416}}, }, { /* digit=52 (1,2,..,8)*(2^{208})*G */ {{0x00037dccb38225c9,0x000f315adf7cccff,0x0005ec2414fcf3b3,0x00075f87e81a3e5d,0x0000f61ae1e090a2},{0x00009fa4f71b333a,0x0000e73907fba12d,0x00097997840dbf32,0x000506cc535daa6d,0x0000b54ff864cf47}}, {{0x0008797e91aea7cc,0x000a480eb6b242d6,0x0002d2f863b4d485,0x00089479dd30bd02,0x0000e4b655e68a0f},{0x000d53005ec1aeb9,0x000290a6b4e185ab,0x000d8586b6a88091,0x00048c81b82f2c67,0x0000bb2a23d0098b}}, {{0x000933d489d97ae7,0x000bb9e5cfe5c487,0x000e082b0c0ceb9f,0x000cebf8a82c020a,0x0000ded88fbff89b},{0x0000c73ff49bb729,0x000642e67c51e574,0x000a98cd0b0768e2,0x00043b1c60f64020,0x000020d51988ed0c}}, {{0x0002f4209bf9bcf0,0x00059be9d8e68fd9,0x000288102284ec39,0x000064398db0f053,0x00004a5dc6b917e7},{0x000420b560d4b030,0x0007fcc1a739d4b6,0x000f3e6a037e1521,0x00016c1d009aea75,0x00000584c6da5516}}, {{0x0005c25bb9b62679,0x00086c75488771a4,0x0001396cc5d8091e,0x000d1f142cb76e3f,0x000053b1fbdb29de},{0x00090a8fd649ba14,0x0008a31f88ce6dce,0x000c62ad1ca78ee8,0x000acf8c7be2becf,0x00000873b8c63e6b}}, {{0x0003c778da9603b1,0x0004c5696f37750f,0x00069d8907179717,0x0006192ed25dda55,0x0000eacdd235716a},{0x000ba0f75d54c23c,0x000b8463b04938d5,0x0006234e9d1e300a,0x00020e9b53d9dded,0x0000bab7f97bd886}}, {{0x000760871c2b484f,0x0004c8b4ebd3f02d,0x000caf56e9cde387,0x00059c4cea47acd9,0x0000eae7a0124e02},{0x00098b00ed0b01b8,0x000a0e536e530d74,0x0004cf87ac646f5d,0x0009e6d2a7abc52a,0x00002f3c4af4c323}}, {{0x00082b921a859ae8,0x000619c6254dc41f,0x00038257ec641913,0x0006a3ca77e29392,0x00000c021e167183},{0x000a3d8c1544aca0,0x000f62e1402cec5e,0x00070ff1a4d2048f,0x0000bd9cb9f17ca1,0x000074174697d3a5}}, }, { /* digit=53 (1,2,..,8)*(2^{212})*G */ {{0x000e0ace9790f135,0x00011e60ebcf7262,0x0001342678767f4b,0x0008aec094482b83,0x000086d2546132b7},{0x000cf8daedabfb38,0x00071d31f8d1f420,0x00014a5069e4864b,0x00083fb4b1b1e83f,0x00006eb2e2034cf9}}, {{0x0004d5ef9bcae914,0x0000b0d1e935abb5,0x0003c077f3debaf5,0x000b3d7b5defd10b,0x00005a2eed07f66b},{0x000687601569519a,0x000a7ba74f17e266,0x0008123a7dcee411,0x000877efdc0a0e3c,0x000028a9a1af6c1e}}, {{0x0009432af25a44dc,0x0003c0c207674f17,0x0006ba6b64e961d4,0x00069db1e112e09a,0x0000b97a68266210},{0x00016fbbff8bf955,0x000008fde2ddec64,0x000f11e7b94049f2,0x000e7c08a81392d1,0x000090f2310497ae}}, {{0x000a995e5dfbc6e3,0x0004fc7904fc3fa4,0x00057d4a050cf2ac,0x000caf6aa14a23f4,0x00009e74b3de65f4},{0x00016c563b4a41b8,0x00083ecf3a5598a7,0x0007407e5359d663,0x000c3283c56534b1,0x0000a377a93e6974}}, {{0x00064110e3d7be93,0x000db892f3b26e7d,0x00000446416395d6,0x000c44aa3f470986,0x0000d33c4ed3954c},{0x0002e3c7706265bd,0x000d02cfad414e41,0x00081bec63b3b22c,0x0001c5ef12b155f5,0x00004a979c09ab69}}, {{0x000e709afd4ebe8c,0x000b8ea308780f21,0x000119d55ae78e9a,0x000664ba3dc8de76,0x00001b9c38ab8027},{0x000526074ae5ec7c,0x000c776021704560,0x000ac3d34419af49,0x000944e68bf204b3,0x0000bf2f1a243170}}, {{0x000a45755beb5e5a,0x0004c3e7882f14f1,0x0004ed815580f741,0x0002464d0c9f6dc3,0x000088180b1213cd},{0x000ca2ca9f747a28,0x00054277c4608cf7,0x0001d9dd48232ab2,0x000f8730e7ccbdf3,0x00005ef4880c3dec}}, {{0x0006539c7de5db9b,0x00043a7e0f222c2d,0x000b9c92b4c46a68,0x0003b3230309d42a,0x000069a4869c5fac},{0x000331fb46a1f47e,0x000277c432ac7d72,0x00000f4ddec961d1,0x000121ade72692cf,0x0000f86aeb4b1886}}, }, { /* digit=54 (1,2,..,8)*(2^{216})*G */ {{0x000ffdfc7e7c2a09,0x00085eae457a4773,0x000bae6fdf8723eb,0x0009a0d71d19857d,0x0000d6ef525ea59c},{0x000d15002a515a26,0x0002c5426ee7cda3,0x0009a1edc37de8e0,0x000e199c8341b086,0x0000bbb468e51820}}, {{0x000f6927b0d79bd1,0x000614c85edfa308,0x0003f86bcc29875b,0x000193b862597655,0x00001c7d62051005},{0x000d0721ecd294e3,0x000feba55f2f94c5,0x0008d744240dfdf9,0x00015625d6a996f9,0x0000e456c18ca0d6}}, {{0x000072c30c9a3e3f,0x000a8e9262a35393,0x000d35fe1292598c,0x00087a2b978a49d1,0x000028a1a98b5727},{0x000912e3eefde708,0x000825277c850e61,0x000f065759f71f40,0x000459fad84f15f8,0x0000a72b7cdf565b}}, {{0x0004cae01e64c20e,0x0009b2079e5fb67e,0x000a8bdf924006e5,0x00033ca37e1331fe,0x00003ed077fad719},{0x000c957822ca746f,0x000cfe60412a77db,0x000c22af18030eaf,0x0007aeb3106ff7ca,0x0000cacc54eeaa59}}, {{0x000cfcde2a6c31ad,0x000d386365e668b9,0x000a0dc0c7d17066,0x0002d72beada8dcd,0x0000ed8b493a21b9},{0x000d65adf799777f,0x000c63e7e85d1e48,0x00096bbdaabe1343,0x00090a4ff9ca0967,0x000015220dfe9e8a}}, {{0x0007e0aa7adc7a48,0x000db0cb0ce1c552,0x0004e3df0b8cb07c,0x0009bee3b5b534d0,0x0000fda2b88e9831},{0x000f7d9eeff2ac2e,0x0007e2d79362c410,0x0000823dcdc0db71,0x00077b12467920c9,0x00001801931c732f}}, {{0x0001ff32eab51c2a,0x0002df10296f4fd3,0x0003b852814bc239,0x00078de051dca76a,0x0000dc7706867646},{0x000c2397edc895b3,0x000c8f18d2c714bf,0x0008327992dc9ba8,0x000467a2364b5c33,0x000088766fb7dea2}}, {{0x000f5fa5904e2bd3,0x000209afa8338349,0x000206d2dfd21b18,0x0004529102295172,0x0000fd30a26b44f3},{0x000137b286ed0846,0x0004125e77d9a3b0,0x000a624d3959c964,0x0003d9c4a11235ce,0x000037f27954916b}}, }, { /* digit=55 (1,2,..,8)*(2^{220})*G */ {{0x00061bbb05f9956d,0x000106ac42bd6d29,0x00082503dba8e1c1,0x000ae458e6df8646,0x00004572780d144e},{0x00004d881133b185,0x00070f070a6a26b8,0x000cb240e6288319,0x000ae43d370686c0,0x0000da343e03be55}}, {{0x0001567f755e516f,0x0002de74462007dd,0x00047b5f76420568,0x0000d6ee7b8ab48a,0x00004f2bc1635d97},{0x000931de26c2af42,0x000d96b0887bcec5,0x000e8847159b8388,0x000b324cb694497c,0x000039c7e289bc5b}}, {{0x000b15d6243f1091,0x0000ca11f17a34c7,0x0008a8443e31d5d4,0x0003fa53b5420ab3,0x0000927b5e2d1cf0},{0x000424051138a243,0x000fdb1e274e49c4,0x0004528d80f9684c,0x0000da2a45cf5074,0x0000abcad67dae2e}}, {{0x00084e81ad96c3d5,0x00080021a93507a4,0x000744ed85217d67,0x000286a40b4cd118,0x0000702de63abcfb},{0x00077e27e30a727b,0x0000cb5272e9d6ec,0x0004ff812967789d,0x000a6af8eea1c93e,0x00003caac07df9b9}}, {{0x000098baf9cb4cd3,0x000b81e48ac28403,0x0004bc21d97de9e8,0x0004798431831129,0x000013750d1196db},{0x000ae9e34b83b95b,0x00066584198da522,0x000be98219cfe30b,0x0007d4e08ab4fc17,0x00008387d9c3f13b}}, {{0x0009f80d55b0c703,0x0003dec0ccced589,0x000b73ac42429524,0x000510fc625cd4b9,0x0000a65aaf5a02d6},{0x000f34bb38b3eac6,0x0007ac9ce6dc1532,0x0007a93199e8a328,0x0001c3b4d138d511,0x0000ca319150839a}}, {{0x00061e15b0193f73,0x00026e84a34f239b,0x000c02e5ed252835,0x000fb353215fdb83,0x0000611a80a40f29},{0x00053277336c58d7,0x00082d4a127f89a5,0x000bb2b59fa73e65,0x000bfdf925d541e0,0x000059c1e0662639}}, {{0x000f9b71b8c0f425,0x00077f2d0c051995,0x00029b4c129bcbe6,0x0007e7c82502fbc2,0x00002b22165d2734},{0x000b6e3e8373047f,0x000bb592b82dd077,0x000519b4c4ab6dee,0x0004bdb327630273,0x0000227777e79e51}}, }, { /* digit=56 (1,2,..,8)*(2^{224})*G */ {{0x000c41114d0d0f0a,0x00071c035d0b34a2,0x000b56e6af5ad632,0x000f458d1440b386,0x00009070851ee09e},{0x0000477abf63470d,0x000c1f1ad95a0b12,0x0008478dc8a2c85e,0x0009d79c9c09b37a,0x00005669d660129e}}, {{0x000a68df70882277,0x00065b3292a92874,0x00062d47b35717e2,0x000498f05ddc15cf,0x00002045f41bf3f8},{0x000a8b9343580755,0x000f94505bf7dd0a,0x0008e243ec49440b,0x000aea3afa4e63d3,0x00000f5462133be9}}, {{0x0006113c503cd9d4,0x00061b51e706ad97,0x00044d98af8ed595,0x00086b990b99cebb,0x0000a86e1c215f82},{0x0003cbb144e6b9aa,0x000e4b097e2b5aa3,0x000c2fed61bf9a24,0x000125c6c7e1022c,0x000044eec8aec086}}, {{0x0004e7b4f75c69c7,0x0009d717af715d2e,0x0003eb2b959f67ad,0x000b50256e2f7f59,0x0000faa39a85f847},{0x000657624d4d6888,0x000779788d5374a6,0x00031a2adb0e9860,0x0008607e22b915e6,0x00009ed17ced0865}}, {{0x0007e49f538144e9,0x0000801dace5aca9,0x000179c203139436,0x000579d09c4fdbcf,0x0000b8c43e3ced43},{0x000f036040802177,0x0007090937e2ad5c,0x0007636ab7b11bc7,0x0009a49dc846e250,0x000015f05617398b}}, {{0x000858e1e42fa26a,0x00096e07442f1d58,0x0000de8801c7a755,0x00023d647475607d,0x00002129ca073288},{0x0007cdea3e2c120d,0x000050b8231ee10a,0x000abbbc34902c47,0x0009866a41b80e7e,0x0000ea4fb6751c9a}}, {{0x0005b9d57b4ca325,0x0009b07f8ae7c38d,0x000b67ba2c17122d,0x0004048b36db07a5,0x0000c13547ebaf13},{0x000fe5a101822457,0x000dbe78eba20f2f,0x000e71d40250d287,0x000744f58ef11ca8,0x000067b29ced3d7d}}, {{0x000af127793627f3,0x0008811e51732d26,0x0007ba47d495211f,0x00011fbc5dfd6eb2,0x0000d0277a7c5305},{0x00059aba7caa2e14,0x000712d06c425aef,0x000b6687611ec682,0x00054599c6df92f8,0x00003f2120a92224}}, }, { /* digit=57 (1,2,..,8)*(2^{228})*G */ {{0x0006605ecd65db55,0x000d72e421d3aa42,0x000cc1ef49735da2,0x000798f1cf926407,0x0000115826b66fae},{0x000b337ce7ef919a,0x000a7a6d6a5eabf5,0x0003c637e9a63491,0x0006f67021edb84f,0x0000746c950ad014}}, {{0x000add3db7ec68b8,0x000b386d23ddc820,0x000c732406385f9e,0x000123ac503fd344,0x0000078adedd4745},{0x000755e7ed4c6729,0x000153f8260e01bc,0x00048d4be4a45000,0x0008bbb33fbeb49e,0x0000d816465d0546}}, {{0x00074a9e86f273ac,0x0003768da9f3804c,0x000dda1996154227,0x000ef0ea5470f07f,0x00007a00585a4292},{0x000a3d7f108e6847,0x000633543471a24c,0x000deddbc6014539,0x000748d4d239446b,0x00003d82eda4eff3}}, {{0x000157c30c88e767,0x0007447f23206d55,0x000fcbce3e45a30e,0x000a8919a2f6d341,0x0000644f481a46b6},{0x000508455987e93f,0x00086c52d4fb936f,0x000bf1494782ed2e,0x0009b3b64ef22f7a,0x0000e271957d8d37}}, {{0x000051f896c2e8eb,0x000d7a69b583160e,0x0003d49398fdf12f,0x0009af8ffbe74fcd,0x000031d40fe11379},{0x0003fa86ded14ca8,0x000aa3806ceb84af,0x000ded17778cfed6,0x000b7ad455ace48c,0x0000241e365b6a4a}}, {{0x000cdf92ebb9f2d2,0x00044fa908ec5b55,0x000d433b1e41dba3,0x0008fdc8a882d661,0x00004a21b29f9689},{0x000b80cdc8345f8c,0x00040425ef6c9c1e,0x00017accb726646f,0x000c62cc4b52d668,0x00004fe7071d103a}}, {{0x000fc5b114eed902,0x00092c1ec222ba0e,0x000e6278ac333ebe,0x0000b826bc3dff42,0x0000884990265b21},{0x000e3baff2f463ac,0x000065bc6b05e85d,0x00088711208431cd,0x000750c9d0a6d302,0x000019cb19f15c3e}}, {{0x000595cd1fa2a781,0x000d8d8df7304d44,0x000bb98b416f08ee,0x000983c60b71bcf1,0x0000fe06b3f76c34},{0x0009429622589d67,0x000cb9a4835859dc,0x000cb478d834436f,0x000f5234e4a0f0d2,0x000076555e5f3c86}}, }, { /* digit=58 (1,2,..,8)*(2^{232})*G */ {{0x0004c9b20d431706,0x0002e62f23f2d925,0x000d0bef8e6b4e0a,0x00055d8206cab71b,0x0000c95a2a5e55d4},{0x00031469c615f1a7,0x00031aa9f2ac02f8,0x00069d5a83ea26e1,0x00016bd3403f8e61,0x00007f5ad3cb507d}}, {{0x0008b75007f2d3e8,0x000b9583ae9c1bde,0x0007fac5923887d3,0x000d750b4e0af6d9,0x0000d1ef5fdad135},{0x0004069ea597b54b,0x0003bafe02358f2b,0x0006368b73835819,0x000671cfc31b8b85,0x0000fde8d8c56c72}}, {{0x00028ad2a84e6c41,0x0004fcde36d07576,0x00017717c0d9fc24,0x000484cdff722d7b,0x0000ebe7611ea3b6},{0x000c336b09195735,0x0008ab520226040e,0x000064d14bbbb3e8,0x000ac8c886c34ecb,0x0000b85de43f45af}}, {{0x000dcefcddd2868c,0x000b79e558df0194,0x000a5ea22e49ccca,0x00091ce24230da4b,0x00002dd640a90582},{0x00072d824d931811,0x000feb2a47d4c5ab,0x000efbe07e5114c0,0x000d6c17355ac9ab,0x0000fcd91a520be1}}, {{0x000b8b3bb657e0d1,0x0002823cbb13d1b0,0x0002507060487a33,0x0003073a998799f4,0x0000a4673e731318},{0x00071b9484805f36,0x000b92e3ecebb211,0x000b1f5665228e4a,0x0000fe71f17cb6c4,0x0000fab132e7caf2}}, {{0x000e8ef838c9fbc1,0x000c452de7e5c194,0x000973312d33ad9f,0x000d8b33dfab2860,0x000073e06257b5e1},{0x000ec0507e35022e,0x000df264cb1bf3d1,0x0009551e8ee3b962,0x000b4deed4c1f9d0,0x00009cc539a7598a}}, {{0x00094abebcf27683,0x0008e09a607419d5,0x000262210bc3d71d,0x0004daef3faa71e6,0x000036cd41505615},{0x000a29a36702adec,0x000ba91eb78399f1,0x00052519283d6b50,0x000ce18f048aafb3,0x000081d651ae4804}}, {{0x000a55b52ea9cdb8,0x000fab5ef7d92893,0x0007df294c2baacf,0x00036dbb62480d4a,0x00005fd14d5bdd1a},{0x000d5e9d7d31477a,0x0000715309eadb09,0x0009f58728a80fa4,0x00022c35adea7de5,0x0000ddf8bf0e739b}}, }, { /* digit=59 (1,2,..,8)*(2^{236})*G */ {{0x0008d2fe5724a2d6,0x0008a411e84e0e5b,0x0002f5d04e3bf4c5,0x000d0d132a5db84d,0x00001765a592c24b},{0x0008b4a422ebc11c,0x0004336f3eb82fab,0x000c454ae73559b6,0x000b3a5108cb20cc,0x0000bc49662e3c97}}, {{0x000dc9d1ec6f170f,0x000bea3af2ebc2fd,0x000ced852c3855dd,0x000b601b1a0af843,0x0000efe50594d52d},{0x000740f316de5b77,0x00051bb62771deb1,0x000a7a84b76a9d83,0x000c81aae829277a,0x0000e1420c11bfa4}}, {{0x000d60f8e1cfb95a,0x000af10cab91f1eb,0x00038fbbd9345d96,0x00016c852bedd9e4,0x00005be88d186e1e},{0x000701924533f212,0x000417b9e05614a8,0x000660adcd80a4d5,0x00039c726fd26c76,0x00000cb351353c24}}, {{0x000fcf57c64d0fe1,0x000089aeeaf8c495,0x000d0e557f623c19,0x0001b346cee7aa73,0x0000e3399090fc9a},{0x0006eb38aad81cf7,0x000a739b6057604e,0x0000db9b5314c754,0x000f3472d7d343c0,0x00004c1dfbe3a0a5}}, {{0x000701a7d15ac5c0,0x00023520a981b0d0,0x0003b61899d2b0df,0x000d9eb9c1c354cb,0x0000a66e6fc26984},{0x00090a54c87214b2,0x000caefdcf2b9218,0x000333ea2b996b05,0x000111ae66ceef0b,0x0000fbf98e12d06c}}, {{0x0002d09a5a1d9cdf,0x00039db4f6d01b11,0x00027c414e4622ba,0x000bc3b3be73c6bc,0x00008bb6de003282},{0x000e59669367bb32,0x00042eee7de13f4c,0x000535f66fef6436,0x0008d7d70177e2be,0x00000eff574037b4}}, {{0x000291aba861ed06,0x000e76c048752a14,0x000e5d81960c63b1,0x000d9aa9241f2702,0x0000cb8d90ea933b},{0x00055408ef3f36fd,0x000ad70a653d61da,0x0003a9daac2f423c,0x00082428fd1b648d,0x0000eccb9ac2171b}}, {{0x000848949c160154,0x0000e4f8be762b49,0x00006d459f779d3d,0x000d6b1fa2a9ee4d,0x000073144722cd51},{0x000631594e5d8939,0x0009ee5d23a84178,0x000d6db14456f57f,0x000650e1f892f3b1,0x0000d7a0b3f34fe0}}, }, { /* digit=60 (1,2,..,8)*(2^{240})*G */ {{0x000585113ba8dd62,0x00080ea1f095615b,0x00065f617af767a6,0x000aab6be0a28ad7,0x0000085f54531694},{0x00033ed1deec48b1,0x000ae0b30df8aa1c,0x000b877911cd914a,0x000e64fcbaddda07,0x00004abbcd21ba68}}, {{0x00032b33d4f558d6,0x00037483e07113c9,0x0008ea602fd9386b,0x0000f762b6e4a5d3,0x000040b7b04b7684},{0x000f178169d618d6,0x00020510dbbf08dd,0x000885aab8e91f1c,0x00043069b211d07c,0x0000c105f022a618}}, {{0x000568d0917c4acb,0x000c55a83cdd60ed,0x0004cbae30f32f9c,0x000d8992a50602fb,0x0000910f7a813c33},{0x000ec2057b354ced,0x00035c70259217fd,0x0008e56f3c6925cc,0x000490b6e93831cd,0x0000a336551d0bd7}}, {{0x0008835dedbc740c,0x0007d25913cc16df,0x000ce91f116c9a1b,0x000808dae18bc5b6,0x000071a394c1d139},{0x000ce433b9ac0821,0x000ead865a40ab05,0x0008bc6703c50add,0x0000029696559643,0x00009a0bfc436be6}}, {{0x00066dd6d2079f06,0x0004c3d42e06189e,0x000067cd28417e6e,0x000130050bf07794,0x0000de2c929cf8ba},{0x000333b1e86df344,0x000b967ff99abde3,0x00009477132566ad,0x000536ed7c990355,0x0000973cee61a30e}}, {{0x0000428dffccb096,0x000cfe784d6365d8,0x000f0f3311b8f429,0x000378330bcb7443,0x0000aa82351ab1ae},{0x00058c1fb6bdb9c6,0x000e9efa4faf8433,0x000dca1d65a933e3,0x0008101ceced8538,0x0000d4a8d9e6e600}}, {{0x000e6c984782812a,0x000b4f7be42a5821,0x00004697d39f6d6b,0x00067b1a9d3fc608,0x0000472dc3a58087},{0x0006fec314288ecc,0x0007d25d30c31f70,0x000aa52b5e0e12c8,0x000798de7b7eb72b,0x00005698fa1698c6}}, {{0x0009650f1aafc77c,0x00018b07e50122b3,0x000b118b6d8a8280,0x000784d7bdd744f8,0x0000b7a7039bee26},{0x0003cde18959c8fa,0x0004df71fa38477c,0x0009110e30c5b652,0x000a5bb8a3d815f1,0x00000fab64c70c58}}, }, { /* digit=61 (1,2,..,8)*(2^{244})*G */ {{0x0009c02205f112dc,0x0009e952f41deff1,0x000acc7b67b111a0,0x0002d1d510e44a59,0x0000fa3e8511d623},{0x00051ff946f13b54,0x000dc69c4b7d692e,0x000317f509655586,0x000e6b4462e6392c,0x0000a96c730c5b29}}, {{0x0000a3933301eb25,0x000a651566c5c43e,0x000854f45d136c9a,0x000a9b44acff9c91,0x0000afb49c7ad947},{0x000a2e067e61d8ad,0x0004dc10dc1eb2bf,0x000135c5137c224f,0x000bda57488cfd8c,0x0000c44a7f8d059f}}, {{0x00052723d33fd8ae,0x000d77c5b0f7bd45,0x0008bb677dfa7a03,0x000ac19a96990c2c,0x00004b6f2495b079},{0x000fb6607adecf05,0x000bde2919ba0f93,0x00090c3da815b883,0x0000a7d12075a3bd,0x00004310fdce89c8}}, {{0x0006c13cc1c1b2ba,0x000707f3e5f9f11f,0x0009e009feccf526,0x0004546bd9afe153,0x0000da180beb161c},{0x000f8417a1d44bc5,0x000008e325fc3ee3,0x00006399ac1041ab,0x000580ee77109540,0x0000ceab562965db}}, {{0x0001872bafa156fb,0x0007a216ce400bb1,0x0007b96951ea5324,0x0007767e0f72919f,0x0000be25883d565f},{0x000a586c9ea652aa,0x00077eb211f7dc69,0x0005ba936a575e48,0x000dacedab8900e5,0x00003e88330c056f}}, {{0x000fab17514db1c6,0x0008172813b230d7,0x000e97892cd69e71,0x000cdff6a634d0f5,0x0000c7df5b396089},{0x000b9815a106666f,0x000a1a74f7c4f830,0x000416725238afc5,0x000ab9aa0a7d2edc,0x000091170e9acf8b}}, {{0x000a68529f79ae19,0x0006ae151c3ebe53,0x000797f52949338a,0x000e08fc9db14d5c,0x00004a632a0f71db},{0x0004b14f4695b847,0x0005adc149f75b88,0x000082eb2d6c5560,0x0009f624e9b8946a,0x0000a038b421d27b}}, {{0x000db6d961011f15,0x000439b319540c33,0x000964ccfd972723,0x0008f8acb18490f5,0x00000165db5b23d9},{0x0003f6e09555115e,0x00005bb146110697,0x000e9391de70734b,0x0006302d2b19436a,0x000046716ed749df}}, }, { /* digit=62 (1,2,..,8)*(2^{248})*G */ {{0x000b8a4cbe978aa8,0x000fbc8ee3c76cb3,0x0003979fd2b05b7b,0x000d941563cf1162,0x0000e542d606a5d0},{0x0005e56df6f115ed,0x0003ca59ce6bb278,0x00017eef4378ebbf,0x0000d8c8dc4afaa5,0x0000a21b92c92f88}}, {{0x00035dc5396eb247,0x000c8ef4e4ca4631,0x00072209072a4380,0x000c5c200bcef728,0x0000b72cb6549160},{0x000b0c5738b12183,0x000822e27bf1bc68,0x000f7cd34933b26d,0x000119eda10a224e,0x0000c80f888434bc}}, {{0x000e0efb3b8b1b5d,0x00038959884aaf7a,0x000259a44d6afe4d,0x000f91f87b1959be,0x0000337331701bb0},{0x000b01a0216bb368,0x0000c5eca8c325e7,0x000671fd9f4f814d,0x000e76c1d3c91169,0x000010645e8443c5}}, {{0x0005b4488b3fb1e8,0x000d26b23a5d8961,0x00056a2fedc3595e,0x00081de771fe19e3,0x00005b981b48385a},{0x0002c4f79da9b17b,0x00017541a1f22bff,0x000fb8bc6c4a7592,0x00033ea8e920a8a6,0x000037f6be35ab5e}}, {{0x0006210d9e58a61a,0x00029b5224c08dca,0x0003db93fef2cd7b,0x00002ae4f2bbb09b,0x00004673f3e36b54},{0x000acede4893a3e0,0x000167a09cb54d69,0x000fb53a3b5bd9ea,0x0006f485791eef6d,0x0000d389cb15387b}}, {{0x00078c2ec1e3ed4f,0x00051691416a6a5e,0x00085c63595aa0e1,0x000163b5d8f860c7,0x0000283d923fc854},{0x0005beef7ad3f5b3,0x0007b815ad735813,0x000023a1511c7557,0x0006b79bab4cc9e0,0x0000199d8c4e721f}}, {{0x000e42f66dd9a70c,0x0000846de6736294,0x000e21f936b36c3b,0x000215cc757f7aa1,0x0000e42c4db111bf},{0x000f78959874b51d,0x00067dc910778965,0x000f6350f2c2eb73,0x000e53487a0d690c,0x00008713f1619ac6}}, {{0x000bdec2116e9b29,0x000389c76497ee80,0x0006bb3874fd1cc1,0x000343fe15d2b0ac,0x0000a3fadcb3a4e1},{0x00037248e9d64745,0x00087efa63b10110,0x0007dd6bd1db932c,0x000c6c78bf9e3fa9,0x00009e31d0655466}}, }, { /* digit=63 (1,2,..,8)*(2^{252})*G */ {{0x000be5ed0e405bae,0x0007fc91ec34f9e7,0x0004b79b18f54024,0x000b106f3d8772d3,0x000037037c975e12},{0x000aec44147d71ff,0x0003d1931e82b100,0x0007bf1327384e2c,0x0002fb55ec63d285,0x0000df2ba6d3b215}}, {{0x0007a23f356e3059,0x00041e71e29a3efb,0x000f94f0f0f98de8,0x0007a880ecbe906e,0x00002d869e92df60},{0x000cf0bbf87a34ec,0x00089c2efd2119d3,0x000ebfbd0dd06fa3,0x0006c851303198c6,0x000030a29d4bfdd3}}, {{0x00089caef387625f,0x000fcb72b7247593,0x00017a38174726e5,0x0001b102c945353e,0x0000fcd0db4d1457},{0x0003429bba3484a4,0x0001753db65ef147,0x000e6a574289160a,0x0006d9c5f2dc2cb7,0x00005d42b1ac334f}}, {{0x00012c9e1ee0d0a1,0x0003490b01e6e274,0x000da05414bdd548,0x000de03a9047e2cc,0x0000c371569c9623},{0x00078851bc8c9a7d,0x0000d36794075521,0x0006dbaa6726fc38,0x000ce611949c5013,0x000053af2d9b1059}}, {{0x00035aa24062df0d,0x0002a52fb85fa4ca,0x000d94e1eaa94f02,0x0001840aed61257c,0x0000fb93c2113070},{0x0000d05aabec972c,0x000f75d4421fc835,0x00007292ec8f71dc,0x000b37558f6df8ee,0x0000d9d09ec67e4f}}, {{0x0000235a102cb4ec,0x000fb35a64785f45,0x000b0f0672f75fa1,0x0002e6467bc56637,0x00008030444d7012},{0x000881065be741fe,0x000b8d8f2c4aa658,0x0000fb14fbdf31d8,0x000b607bac347583,0x00006adf01034a09}}, {{0x000f12502f6f25d9,0x0000c22cc1b5e838,0x0000f6f93bcc544b,0x0008c7ddfde2d4ad,0x0000c68d49d6c0f8},{0x0003511dcdcef6f9,0x000a7dc7783920a0,0x000dbd6b689c8148,0x0000f52a6e80014a,0x0000730b2f927704}}, {{0x000211e48a709134,0x000a06d95a7b1a29,0x0005aa515d70a8ec,0x000baface9c4e7ad,0x00001420ee199ed7},{0x0005f92e47355a0e,0x000716ec78ef1f42,0x000fe05e173edf3f,0x000e4dfe82b2c090,0x00005f26894a26e6}}, }, { /* digit=64 (1,2,..,8)*(2^{256})*G */ {{0x0008910bd3c74498,0x000d8af3aeac968f,0x0008cc252692ed9e,0x00067be64e4f7fee,0x000092836060ef1c},{0x000890896b28139e,0x000470cc9c0726e3,0x0009a0eab753f427,0x00046bc1b1530956,0x000038600b6014d5}}, {{0x000cd15a3cc6fb9b,0x000a19f82e4c6346,0x0003cd730abb95f1,0x000222f258efb831,0x000068413078deb3},{0x0001e7c1ed462bd3,0x000d5fdbfcd8fb51,0x000f5c6d0b354d1b,0x000acc02f31db2ee,0x00009cf8f2c231b2}}, {{0x000ee3e9bd875a0b,0x00079f5903fa2711,0x00029af6a861120e,0x000561354e6da0fd,0x00000c0f6913abd6},{0x000948148819fd8a,0x0008e1ce27a94979,0x0003f4d9497c8870,0x0002f21ca36d254e,0x00009bc3a89fe40b}}, {{0x0004af860fe1d658,0x0005c3a43228d831,0x00003626b989c96b,0x000ceba2924ae1c3,0x0000c45b79310a64},{0x0002ceb1de0d0667,0x00088613f714aa18,0x000d68a9c780c9b4,0x000a36f94f51865a,0x0000055e19d4f0d9}}, {{0x00014fc2a4b59f10,0x0004bfd2f9fd51a3,0x000216cbd55294c7,0x00097be507f2f1fe,0x0000924f1faac4f7},{0x0003541b7a3d4f01,0x0003c8cb55fc5c6d,0x0007ec5dc6c3980a,0x000f63bcee3510ce,0x0000ab63b2a3eef9}}, {{0x000560910cddf7bd,0x000a825eca445df4,0x0001e77f13b9bb31,0x000af16bcf1af24f,0x0000d48e4c17550d},{0x0005fc863ac98830,0x000ec32093eaa327,0x0009073fe1808aec,0x000fee1100183134,0x0000b88f64b6ab63}}, {{0x00017535ffca9e3e,0x0004c4176a9f05d0,0x000b8e9c9e88a67d,0x000aa685e06ca4e4,0x0000941d64ce2bd7},{0x0004eb4d5b7fac46,0x0003ece406851d75,0x000f3bfe1359045f,0x0007cb734afa3acd,0x000087d6f48d53f1}}, {{0x0004ef0fb7992ec5,0x000237355dbd4b3d,0x0007914aabfa41db,0x0003654621f87992,0x00002b7c7dfd2d83},{0x000c21100586c6db,0x000ded8f1bfb12a4,0x0008223d7b6ca10c,0x000b4b5146ab877e,0x000069c991a7978e}}, } }; #endif /* #if !defined(_DISABLE_ECP_256R1_HARDCODED_BP_TBL_) */ IPP_OWN_DEFN(const cpPrecompAP *, gfpec_precom_nistP256r1_radix52_fun, (void)) { static cpPrecompAP t = { /* w */ 4, /* select function */ p256r1_select_ap_w4_ifma, /* precomputed data */ (BNU_CHUNK_T *)ifma_ec_nistp256r1_bp_precomp }; return &t; } #endif // (_IPP32E >= _IPP32E_K1) #endif /* #ifndef IFMA_ECPRECOMP4_P256_H */ #endif /* #if 0 */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecprecomp4_p384.h000066400000000000000000010117501470420105600275730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ECPRECOMP4_P384_H #define IFMA_ECPRECOMP4_P384_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p384.h" #define BASE_POINT_WIN_SIZE (4) #define BASE_POINT_N_ENTRY (1 << ((BASE_POINT_WIN_SIZE)-1)) #define OPERAND_BITSIZE (384) #define LEN52_P384 (NUMBER_OF_DIGITS(OPERAND_BITSIZE, DIGIT_SIZE)) /* P384 affine point */ typedef struct { BNU_CHUNK_T X[LEN52_P384]; BNU_CHUNK_T Y[LEN52_P384]; } P384_POINT_AFFINE_IFMA_MEM; extern const __ALIGN64 P384_POINT_AFFINE_IFMA_MEM ifma_ec_nistp384r1_bp_precomp[97][BASE_POINT_N_ENTRY]; #if !defined(_DISABLE_ECP_384R1_HARDCODED_BP_TBL_) const __ALIGN64 P384_POINT_AFFINE_IFMA_MEM ifma_ec_nistp384r1_bp_precomp[][BASE_POINT_N_ENTRY] = { { /* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x000607664d3aadc2, 0x000fa3dd07565fc8, 0x000e1e26a4ee117b, 0x0003afc541b4d6e6, 0x000459a30eff879c, 0x0004ede2b6454868, 0x000513812ff72361, 0x00000000000299e1}, {0x000af93c2b78abc2, 0x0006e23043dad1f8, 0x000d385481a72d55, 0x000e7562e83b050c, 0x000968f4ffd98bad, 0x00069a840c6c3521, 0x0005e9dd80022639, 0x000000000005a15c}}, {{0x000a271bdb93b776, 0x00066c8229e549ca, 0x000a0046a4ddbf0b, 0x000e6f0ff9d48a26, 0x0005f0687f503504, 0x000e4b506da82149, 0x0000c39c90a4fd2d, 0x0000000000042746}, {0x000777e3e34947f7, 0x000cf42ea84624df, 0x000c322ca0a5f414, 0x000f18bdc588259c, 0x00015172bad915e4, 0x000b0e68409f1fe4, 0x0000c2070d430900, 0x00000000000123df}}, {{0x0008420bd283fe68, 0x0000405e4dbe5ef5, 0x0007d2a868c2d376, 0x00034e9a170ccf19, 0x0002d51c6c3e6b20, 0x0003aa4703a48d73, 0x0003ace36f7e2d26, 0x00000000000e7c1c}, {0x000a7b5b465465fc, 0x000697e28482179f, 0x00092befa3c13549, 0x00063c04ef67446d, 0x000ad2e1d0b41326, 0x00002b33968012d5, 0x0002aff6db68b151, 0x0000000000098329}}, {{0x0007a84fcfeee6dd, 0x000c00aae84771bc, 0x00004833a9bdf308, 0x000153b0aecac470, 0x0004736400ad2e4f, 0x00085d979078358d, 0x000228fb40f647d6, 0x0000000000034179}, {0x00059b3d50946875, 0x000f354f3e8e74aa, 0x0007e02066cc9331, 0x00061a34c542ad23, 0x00030418c6938e3e, 0x00020017d147162d, 0x000319e607b9e338, 0x00000000000303df}}, {{0x0006ca2ee1bb26b1, 0x00017bb595eb9873, 0x000340e77dae425b, 0x000b1b5293c703ca, 0x0005aacc05e67f1e, 0x000e8e4c660db2cf, 0x000ffbc676b987e2, 0x000000000001d178}, {0x0002304b4db1c9d6, 0x0003c2b694ba022c, 0x0000733804c0a50f, 0x0001b3101c35b997, 0x000f982c041180b6, 0x000de236d4b237fa, 0x0004a3e6c5944024, 0x00000000000e209e}}, {{0x0003f94fc482e189, 0x000c37eb5c930b8d, 0x000fa7363cfe5622, 0x000930f580d57f38, 0x00061bdf6015ec52, 0x00002d33b2a33f66, 0x000c404f0f6a962b, 0x00000000000f0430}, {0x000a60b1c9962152, 0x000203f62b16dde1, 0x000d30e7f024d36f, 0x000bffcb79e33b13, 0x00061b546f058bd4, 0x00021559a93c9e5f, 0x000eba586d8ededf, 0x00000000000af2a9}}, {{0x000c82aa932c9f81, 0x00032df13b9d0ea3, 0x000012e0e11a7414, 0x000dcf8211faa95e, 0x0001659753ed731e, 0x000b2df555f4215d, 0x00025bf893db589d, 0x000000000001c890}, {0x000c8f68d90a16b6, 0x0002f0996b21f9df, 0x000c5d608c816e33, 0x000d76f50130844e, 0x000401fff78065aa, 0x0003b07060ff37c0, 0x000b3ef57f238e69, 0x00000000000af6c9}}, {{0x0006da365db4f184, 0x000fe23f60a057fe, 0x000be85f6a0c5049, 0x0002e7193d7e30ff, 0x00064f3ddb371c5c, 0x000b664231d9aebd, 0x0009b11c7b5fe116, 0x00000000000349cd}, {0x0008ec6d3c0c6dd7, 0x0005e0d2cfe83aa5, 0x000f7a290df3f1cc, 0x00054bf7d8686e4b, 0x0003a42dbba27017, 0x0008ecf0ee992326, 0x000f617008d943c4, 0x000000000000d27e}}, }, { /* digit=1 [{1,2,3,..,}]*([2^4]*G) */ {{0x000b56e7a10896aa, 0x00082da6e8a7edb2, 0x000a339205afd669, 0x00065517917652b3, 0x000a2887d5ff37cf, 0x000bdc3fa317b63e, 0x000aa137065f5313, 0x00000000000435ab}, {0x000e15a5659db481, 0x0008e9b21615f8a0, 0x0000a5926b88aaa4, 0x00071dc154d41105, 0x000bc88ee1489148, 0x0002d1967b333bdf, 0x00051351c305c6a7, 0x0000000000081ef2}}, {{0x0007c0045dd2a4a0, 0x00075ad852b872e3, 0x000b4af19266ca1e, 0x000b9fcc651b1dd6, 0x000612e8dc871896, 0x00031cfb0ba8953d, 0x000d793a9865baa6, 0x00000000000626b3}, {0x000b7328c510ad93, 0x000901148bc71a36, 0x0008838d56b7b5d9, 0x0005f9e9448fd096, 0x00000a2377b67731, 0x0005b4ff04bcb06f, 0x00099f73b42725b3, 0x00000000000aabca}}, {{0x00077d8466e4794b, 0x000763ccf806a4c7, 0x00041b06944ed785, 0x0004e06ea52bef99, 0x00053a7d2f3c4f50, 0x0003a1bc940d01ff, 0x00040062e5c5d3e7, 0x00000000000ae7d7}, {0x0000b071271e42a1, 0x000923d30625e38e, 0x000c9ea33ece8520, 0x000a10d04bab9856, 0x00009da2a2ca5c3c, 0x000c9462c2605ca0, 0x00058348eab00eb5, 0x000000000002624a}}, {{0x000c57a24f5d5ab6, 0x000eded4de4f83f2, 0x0004d9f2c578d7f4, 0x0003d30f8a0580de, 0x000dca57b7bde04b, 0x000e44d56a309199, 0x000e5cfc8e87cf3b, 0x00000000000d1b30}, {0x000dc1d0888b708b, 0x0008cb213c69fa81, 0x00085d35b9791d2c, 0x000bbbf1090fede9, 0x000c301fe259fe51, 0x000cd3fe86d97cab, 0x000a513ee127895e, 0x000000000009404c}}, {{0x0004d8911e8568cc, 0x000c5194924b48e8, 0x00026b2f852cc83a, 0x0006428b12136094, 0x000351fea1dc4906, 0x00015ace6dd2ec6d, 0x00024620fe8c27a7, 0x00000000000a4463}, {0x0003c328530abb42, 0x000b900c213bba9c, 0x000bf43a5f2c2e1e, 0x000903c6484641de, 0x000a1378e68fbc7a, 0x000cd8ae42413063, 0x0006f9b960b5efee, 0x000000000000614a}}, {{0x0001dedb8bf3dccc, 0x000a0dc529384912, 0x000bc9fafda07c1d, 0x000597e52ce08f71, 0x000581998af2ee21, 0x00041eb4226de4c6, 0x000b96cb4aa43c97, 0x0000000000039c18}, {0x000a9ce2b257fb6c, 0x000a566e1d5da261, 0x0002d61f72303077, 0x000396f305ee4f10, 0x0000c831254b8545, 0x0005680b8f9d19ea, 0x0004a4cee0842f5d, 0x000000000005a443}}, {{0x00007168b4a67147, 0x000a12e206547853, 0x0001c6a852120cb6, 0x00009d5504c8129c, 0x000c9710b70b2b56, 0x000296a52fb25e37, 0x000dce83f2fd2cd8, 0x0000000000062f45}, {0x0000b128f82bb944, 0x000a8a818b9bda93, 0x000ed2d611039805, 0x000e43a2ec76a180, 0x0007caa846883e7e, 0x000182141473e687, 0x00004db9a19eb57c, 0x0000000000045ed2}}, {{0x0001e64ba6661cc4, 0x000cee484fd9edbf, 0x0005b5c2b4988114, 0x000449e7c1c3984b, 0x000118eb5195c0dd, 0x0007a16d2f313389, 0x00020a0336aab877, 0x00000000000c2417}, {0x0001e21e239dcab2, 0x00034678db970845, 0x000627331787ffae, 0x000a0e4a022c7a44, 0x000434a02a6b5d85, 0x000791ce3b01f1e0, 0x000c5b2657eedda5, 0x00000000000a277a}}, }, { /* digit=2 [{1,2,3,..,}]*([2^8]*G) */ {{0x000fa21fa335ab82, 0x000a49a7a5b41c7a, 0x000300862e13765b, 0x000438e3d9f0e627, 0x0009e328c2e27539, 0x000cbf891013c671, 0x000d287f4a706ccc, 0x00000000000735a2}, {0x000a7119424dd00b, 0x0004246694eeffb4, 0x000059afb703b483, 0x000ed8b423d47e45, 0x000bf44c91809d54, 0x000e9b3848075a8c, 0x000c75d4f5b184ab, 0x0000000000041abd}}, {{0x00093e732cc6e06c, 0x000c65e2cb07faab, 0x0006c10c7767a2e6, 0x000c53fd4de1f262, 0x000c838f7169a296, 0x0008a6ce7d408060, 0x00067168e19d7b2e, 0x0000000000094b58}, {0x000136755dca2adc, 0x0000293d02a07640, 0x000ed9dfab92ca5c, 0x00069f51aa3bc4ef, 0x0000dd09b1426aa0, 0x0002e59450e44fbf, 0x0006ace264f34383, 0x000000000001fc16}}, {{0x0001b41eba2511e6, 0x0003e9ee4f521f6d, 0x0005af7a840c9880, 0x000396db7edb07d1, 0x000c2e8290630d5f, 0x0003495da09b3457, 0x0009b8f1d28188f8, 0x00000000000cce55}, {0x000f6b035c499b66, 0x0005617cbaf577ca, 0x0007eb3582ad9848, 0x00008995145b8fd9, 0x00081a33b1a72982, 0x0005149e992cb5da, 0x0004c0ca49fe334c, 0x000000000001772b}}, {{0x000b80038e0f9767, 0x0006756ad758212d, 0x00066af19dfc2941, 0x000c6ffe2c8b0369, 0x0007fcd7336b85f2, 0x000a46acd55c6d35, 0x000ac7b1ecc56d22, 0x0000000000036277}, {0x000330b02f145871, 0x000c1a4ed11e8d27, 0x000297add7ae640e, 0x000ba45266158ab0, 0x000d89e0dff05fda, 0x0006b02d06f0b27f, 0x0006e132ef7ae2eb, 0x00000000000cc1b4}}, {{0x0008162061985fbc, 0x00005c112733b3ba, 0x00062ae17de90bd5, 0x0008e01810097859, 0x0002bfe16c4fbb7d, 0x000d9f8107640a3e, 0x0005d74e34813ec1, 0x000000000008d260}, {0x00078cdfc58ed763, 0x000f72a544cd81e6, 0x000e167259300b75, 0x00057bacec18a7f0, 0x000511b882d69e61, 0x000f86563a555fc9, 0x00096e4305a4dd04, 0x000000000001d0fd}}, {{0x00008da90a96090a, 0x00032f04145e8229, 0x000a916fb6ff9132, 0x000ba4e12aa299fb, 0x000991b3b5179ffc, 0x00081c747cc5ec24, 0x0003eb9edcd4616f, 0x0000000000077a88}, {0x000a4909883002a4, 0x0008b9b0bab581a7, 0x000e659d0317cb87, 0x000d81e438a9d43f, 0x000e25ca8b3cfe8c, 0x000bc720cf40e2b5, 0x0006a34254030067, 0x000000000006b244}}, {{0x00099b58a43c6d42, 0x0005180e1cd16205, 0x000e96620312fe6d, 0x00019d509ddce071, 0x000e70c4b03267a0, 0x0003ba57e52573e3, 0x0004f716d253e14d, 0x0000000000016250}, {0x0003e944594baca0, 0x00013a237bbf8f9b, 0x000a642b05f4171f, 0x000531a1f384daed, 0x0003981251654b13, 0x0002dccc139067f3, 0x0007b5e98fb14167, 0x00000000000a75e2}}, {{0x0009f542630002ea, 0x00044e65245ce93e, 0x00012350ea59da7e, 0x000c121bad2c8070, 0x0002060fcf245677, 0x00078cccac52dec3, 0x0006fb78d070675d, 0x000000000001bc8b}, {0x000ac9684403d046, 0x000b5c5cb86bea72, 0x00053d522dc955a1, 0x000cdf2c92a70d83, 0x0001f53cd2a1fbb7, 0x0004f11395a9ff1f, 0x0009f1fdbe6b7a98, 0x00000000000a470a}}, }, { /* digit=3 [{1,2,3,..,}]*([2^12]*G) */ {{0x0006766eb19e084c, 0x00028eb06571b5db, 0x000430cbda13e4c9, 0x000966726eed225a, 0x00046100e387a185, 0x0006298d18d9e56e, 0x000ad0470506b9dc, 0x00000000000f3350}, {0x0009595e79f27f3a, 0x0006683eb62a798b, 0x000ae3d2069c14b3, 0x000e880e1bd4a82e, 0x000fcaf3b3fcb089, 0x000ffd65cd4d1e70, 0x000ebbd0b1ec6395, 0x000000000009b184}}, {{0x000d72326a677bdc, 0x0001bd4277730e1a, 0x0004e8c2adc8ef98, 0x00046b099f1867d4, 0x0002602dd4cc6b07, 0x0000811201ec73d7, 0x000f2d27fae51538, 0x000000000002f8b2}, {0x000e28e4b1971c05, 0x0001bb924af64246, 0x0005d0fd898e9387, 0x000e9ae068565acc, 0x0005a9a4f1464e88, 0x00093f7348a3dbd2, 0x0003bcdb4a3e483f, 0x000000000008f1d3}}, {{0x000da9f02128c46a, 0x00049d1de964bafd, 0x0007f571d595c1ce, 0x00055af0de9eb074, 0x0005a60289bfbc4b, 0x000392c619f11b99, 0x0004fc3e59000c52, 0x000000000005ccff}, {0x000c017748720be7, 0x00064b28b306ba1a, 0x0007e101bd3e41b0, 0x000542ce3f824faa, 0x00022f52b71c59b0, 0x000c6d26370f097b, 0x000e5b4483b72604, 0x0000000000034d93}}, {{0x000b2e0b9f0415b8, 0x000c7721bb8359b7, 0x000a5f46c16031df, 0x000a789348538714, 0x0007af598c4f9cc9, 0x0006f27c878b604a, 0x000ba5d370375e47, 0x000000000000b15c}, {0x00021b9613cec089, 0x000662bcfd9a4c03, 0x000e3ea0c45f94ee, 0x0006464a211b19f3, 0x00019990b504b05a, 0x0004951d3ce059d4, 0x0007b0011c5f87d9, 0x0000000000000d9c}}, {{0x0002533a1c8fbed1, 0x000ce64e84c28804, 0x000338cbe4f167c9, 0x000d9ed9fbf23cc9, 0x000f5b93118bb77e, 0x0006255cf155fd45, 0x0008941e9f6d7d9c, 0x00000000000c4f64}, {0x00008205c725e2b1, 0x000154bc3a502a87, 0x00030c3fbf39b6ac, 0x0005548d3c862428, 0x0004030f713cc7df, 0x000785cbf9dbfc08, 0x000637f3623326ad, 0x00000000000dd3ad}}, {{0x00053a3eba12bfa4, 0x000ced8b8b37a274, 0x000ff25533a7ef36, 0x000684bd17d58a93, 0x0002032fda408ac7, 0x0004b49645f9557e, 0x0001097fe128e6ed, 0x00000000000ed02e}, {0x000f765f56c35dab, 0x0008c0052d88eb68, 0x000256931b154329, 0x00010798446a4f6a, 0x0007c99ad35fbf46, 0x0000906073bc4391, 0x0008aada18234dda, 0x000000000005164f}}, {{0x000f715095892612, 0x0004e02c16c7865e, 0x0009e82bb73222b5, 0x000bbc0795486af0, 0x00070427332d3abe, 0x0005d3cabad858cc, 0x00019c9a1d4b6aa3, 0x00000000000e208c}, {0x000d5b54420318c5, 0x0000afcc14276eea, 0x0008e6c4a86b5358, 0x0007cb4e7706b5bf, 0x000e479e2c750027, 0x0007ad688c01ed42, 0x000626ff1759604d, 0x00000000000c045f}}, {{0x000e0b227c3a04b7, 0x00029f365419f1ee, 0x00001db5dec2705b, 0x000c165c41880aa9, 0x0007f9712fbd8a91, 0x000c556783eb27a9, 0x0009cfa6587aec76, 0x0000000000002cd7}, {0x000e78bc85d2b5fc, 0x000fefc878f9c549, 0x000d411713959cf3, 0x00084d8caf6df5e8, 0x0002aabcde7509a1, 0x000de597ad32bf23, 0x000858f601d0de03, 0x00000000000c5da2}}, }, { /* digit=4 [{1,2,3,..,}]*([2^16]*G) */ {{0x000f068a28ea9470, 0x0008bb6029961859, 0x0007d86ade910602, 0x000693b4df3e5b1b, 0x0008a0c3e35782db, 0x000b2f577b513148, 0x000cc3bfb01ff3cc, 0x0000000000027a72}, {0x0000fdf0e7cd346e, 0x000f626170927fbd, 0x000aa1bbda6cc535, 0x0006a634c872d772, 0x0000b14d9c9f0bec, 0x0006c7778a0a7cc9, 0x000a4c8a32d2c44f, 0x000000000003b889}}, {{0x000f462aea173d82, 0x000a4860ef793767, 0x000a7a5856850902, 0x00083662ee7f523d, 0x000f54122af0322c, 0x000bb2d8058ccd95, 0x0005777454880c2b, 0x0000000000086d8d}, {0x000038487c4c8fb9, 0x00042d5a3057c6dd, 0x000955643c37ff31, 0x000c99ec3c512f97, 0x0006556d891e26aa, 0x0009f6112c3eac03, 0x0007e9866c3aa7bf, 0x00000000000c144f}}, {{0x00000b161de71555, 0x000aead0d24c7983, 0x0006a55d94bbb854, 0x00034ff7655aa29d, 0x00057a5e217ea551, 0x00021b295a3d1038, 0x00036dfbb9eeb53a, 0x00000000000c84a1}, {0x000aac3258d9db81, 0x000087579398db29, 0x000fa470f6fa27aa, 0x0002e1e464522581, 0x0005479d8f2c99b3, 0x0000b80ef99d5495, 0x00050bc2a8a6a193, 0x00000000000656c8}}, {{0x000f81f2532800c4, 0x00045171898aa3c4, 0x000ea2712f9cc33b, 0x000835ffdb2c1bad, 0x0001591f5aafbc0e, 0x000272c6a4ee3028, 0x00068afd71de3bcc, 0x000000000006e93f}, {0x000145dbf5847f9b, 0x000bc35ee08038de, 0x0001b04c30c2d081, 0x0007ff5957b2ff76, 0x000e5ec029c049f3, 0x000324c12315d8e7, 0x00057833230602ef, 0x00000000000966b2}}, {{0x0003e43e11c6c113, 0x0002e86283e21e81, 0x0009c3e50b313030, 0x0009b1bb9784a9a5, 0x000ea0c0acb57d02, 0x0007c682b7c7798b, 0x0002b041241c716d, 0x000000000001d33c}, {0x00079a15b39e351d, 0x000dc5d469ca181c, 0x000ce825406e72f2, 0x0004cc2a13cf4ce5, 0x00069e3ce2793d05, 0x0004beafc13bd216, 0x00087e01bc70e68a, 0x000000000008aba0}}, {{0x0009cf16a3c4418b, 0x0005884aa863e012, 0x00089c47322b55de, 0x0003206b5c399b2c, 0x00073cc109bd553f, 0x000384088775b921, 0x0003cf25c01263fe, 0x00000000000d5f74}, {0x00057c2efedc75c2, 0x000933d69705ce0b, 0x000359bbe99d9a50, 0x000ab1a2626cebe5, 0x000285b1afe80198, 0x0007e6efdaf8320f, 0x000bb6b9c0968ce1, 0x0000000000090215}}, {{0x00066543cf4fd691, 0x0000d3ee52d8e909, 0x00094816ee49cd7e, 0x00095c61881a757d, 0x0009c13e370735ce, 0x000d2d3f60a8cf9d, 0x000c0de71258d548, 0x000000000000bbe7}, {0x000476d4cb00031d, 0x000bfbd6496e1309, 0x000c1c69b8768cb6, 0x000501358cfdfb53, 0x000b59275b4acbe8, 0x000f722ba655c902, 0x000aad7e0ff05b20, 0x0000000000042b17}}, {{0x000b76411fcb09e7, 0x00066da643272cd3, 0x0006802b1cc8eac2, 0x0005a7c35b43943a, 0x00084606bbf22386, 0x00059fb9a6ac0158, 0x0001a59660ab7215, 0x000000000003ce2f}, {0x00083d9ad8b4f172, 0x0006e62af29aaa08, 0x00060fa06813a370, 0x00029b744c110388, 0x0001d36c2571ee9f, 0x000b552b7b2a19cf, 0x0003d4b87d88e265, 0x00000000000beb25}}, }, { /* digit=5 [{1,2,3,..,}]*([2^20]*G) */ {{0x0002b4a5d3a4b643, 0x0000231bdb4829ee, 0x0006d713dc69c388, 0x00042469b6fc64eb, 0x000a15786b8c18c0, 0x00063da4a0dcc15f, 0x0000fb81acdb068e, 0x00000000000dada7}, {0x0008c1ca45ab6321, 0x0009146361afe98f, 0x0001d88fcfcf648c, 0x000b61b615694e72, 0x0001872951d2f389, 0x0003badc77036def, 0x0008d340fd3bdad9, 0x00000000000380a6}}, {{0x000d66b2c4fdf4c0, 0x0007ac5cf8997090, 0x000a08d2a2626f49, 0x000681e307b254af, 0x000775cd94d78139, 0x000684954cc87fb5, 0x00099190e7027478, 0x0000000000095ceb}, {0x0004649153ee63bb, 0x0006891bbc0ab337, 0x0001f845e221f84c, 0x0003d704b93d45fb, 0x0004f541da1f1cb8, 0x0007ffd10e229902, 0x000b9a3eef7ce14b, 0x00000000000b3fc1}}, {{0x00067cf1182bf349, 0x0007f23c1f744697, 0x000288faa5d1b184, 0x0002c9d5afd1bfd3, 0x0004f89d76fea4f8, 0x000702f80a3d1e9a, 0x00089d964f705075, 0x00000000000f56c0}, {0x000478c2e0092e1f, 0x00012e205fa8ede0, 0x0002998cd8ea4a27, 0x0001004356d43961, 0x0001fdbbdfde331a, 0x000a00e7158b7890, 0x000a30a52a15979b, 0x0000000000055497}}, {{0x000d05d101bb2988, 0x00097e5004e8001a, 0x000e96c63ff7fdd5, 0x00050d1bd869f77c, 0x000de7ebea2c405f, 0x0007620baecffa54, 0x000ff43354dc22d8, 0x00000000000b1c01}, {0x000d9286dd26e577, 0x000c2d9370076043, 0x00025722a20b989f, 0x00076273291e5c62, 0x0007f0a7ca55c0de, 0x000592a305cfebd8, 0x000ce4de1162809e, 0x00000000000a78eb}}, {{0x000153343d6d3c05, 0x000a15562a856338, 0x00041dfd1ca25266, 0x000317409c75b8cc, 0x000124923f80c19f, 0x0005b291e21c7cc3, 0x000b05e63fe47f8f, 0x000000000000dc08}, {0x000a81ce4831b7d3, 0x0001558ae455ea5d, 0x0000f05c04530b31, 0x000c97f3ee3989cc, 0x0005f38759ae42c7, 0x000f46899c1b03af, 0x000c7d1a673c75bc, 0x000000000008d508}}, {{0x000fc69642676f12, 0x0008d1e9b23b9bca, 0x000626ac6d6d75ba, 0x00000fe59b7721d0, 0x000c9e2f4cebd4cc, 0x0000af70ed5c36f9, 0x000799deca06bac9, 0x00000000000416ee}, {0x000affe525098c8a, 0x000df0d7afe1b4a6, 0x000083fa6f5ecd29, 0x0003d6ee6eaed183, 0x0002496087e011e4, 0x000a3a66e5baf860, 0x000677f833634fb1, 0x0000000000079398}}, {{0x000c39f67e66a95e, 0x0005b76512d1b46e, 0x0009e5603da596ca, 0x0003aa8025a5f25a, 0x00095cbd2a40d1c7, 0x0008d61c62aba192, 0x0000f3b53cadc3c8, 0x0000000000009829}, {0x000894e8b1d3bb8b, 0x0003a72800ecafd7, 0x0003c62dea4f99fb, 0x00092a7282ba9d23, 0x0002bd5f1bb214bf, 0x0007c6c969062967, 0x000601362f68eba9, 0x000000000007ea9d}}, {{0x0004d04ff62d3721, 0x00071e141e762de4, 0x000fa0d592d3e0eb, 0x000cde496131447a, 0x0005cb6c2ef746e6, 0x0002f9fd80458a5d, 0x000457b774763453, 0x0000000000016544}, {0x000adb5cae252cf8, 0x0005abfacb4de24e, 0x000e9db72a61c26c, 0x0003220f22d92e51, 0x0006557232589b54, 0x000ddb8bcaa4590f, 0x0007bdc7b6730e01, 0x0000000000069e1e}}, }, { /* digit=6 [{1,2,3,..,}]*([2^24]*G) */ {{0x000e98d9a0583230, 0x000f77d27d71f312, 0x000823b17edc1a45, 0x000afeb6075b2d00, 0x0006d93a06f7418c, 0x000d001b9c0d691e, 0x0007b9c16a95259d, 0x00000000000026f1}, {0x000b72219cfa1dea, 0x000984c1041afdb4, 0x00056e257be49c48, 0x000efd62c1758e9c, 0x0007e6c3229a8d08, 0x0002d89249cc6f20, 0x000fe7ec69e90208, 0x00000000000f331d}}, {{0x00061c722c01a99c, 0x000518ec4335f7fe, 0x000df3425d366c49, 0x0006de001141ab62, 0x000c2eca98a13ff9, 0x000fdf648b21acc2, 0x000e8b6154849010, 0x00000000000d1403}, {0x00097be7041b8df0, 0x0008ff1a35f306b8, 0x000b8cedd3e80c1c, 0x0006c077fc9a752f, 0x000e420d48a089c2, 0x000fe2e738d2535f, 0x000f3980ec5ddd52, 0x0000000000071704}}, {{0x000259172095dfcf, 0x000a020aa15d95a2, 0x000d85bd292d185e, 0x00005caef579e8f8, 0x000b325981bfe2f2, 0x000438be8ad27e38, 0x0000d9087b8284c3, 0x0000000000042236}, {0x00091bc7ac277af8, 0x000bb87cdf5accaa, 0x000de0f7da8c4a28, 0x00040c1891046669, 0x000c9c1578e8a712, 0x00050ffa2eb5a175, 0x000a28bd66910ad1, 0x0000000000011459}}, {{0x000f920077501dce, 0x00091498808ed4f0, 0x000dc6c59ac5d089, 0x00025f176c6b964a, 0x000bac474261796e, 0x000a460c11aced64, 0x000e48a62470fc29, 0x000000000005e751}, {0x000842d2c145f36f, 0x0007acc00053aac5, 0x000ca1b81e5b854d, 0x000cc2e3f9ca178e, 0x000a0b80d1b0ddac, 0x000642225ad33f34, 0x00061b6a76df9364, 0x00000000000778e7}}, {{0x0009eb69fa5f1bc6, 0x0008ed30302342c1, 0x000e3ef7d69039f0, 0x0009b575c4630f26, 0x00008d098d745364, 0x0007f5cbc60197fc, 0x000efc9c295d5464, 0x00000000000c0813}, {0x0001c5999be2ce7e, 0x000e7f6e08007370, 0x000b6019bc473a63, 0x000e08e11d9b388e, 0x000a5db61c657af3, 0x000b4dc4d073ec38, 0x00082a9b480cb89d, 0x00000000000372fa}}, {{0x0003179049382c1e, 0x00069dffb03ae77d, 0x0002e9528cdd6bd1, 0x0002521b19fe0db8, 0x000f3d5c7fee4c26, 0x000e68e1e0ec1e54, 0x0008a62856510b05, 0x00000000000dc80b}, {0x000ac17897e6fc5d, 0x0000680a509308c8, 0x0000b4dde3197e47, 0x00012ee28235c538, 0x0008301f9653ca61, 0x0001fcdf8d28a0eb, 0x0005f322b11e26e1, 0x00000000000e4d73}}, {{0x0002a6a91ebadb85, 0x0006346a2a08bc3b, 0x00020e574ba891b2, 0x00056a2b3df9fbc8, 0x000eb121d51228c5, 0x0003bc86c81d3161, 0x0000d14e27ce0b12, 0x00000000000bfb24}, {0x00072db1b86f039c, 0x0005986edb71958e, 0x00011b5a99c9a865, 0x000c6d8067f5870b, 0x00033fe8e5322f6b, 0x000a7997ff558b88, 0x000b9be9433e2321, 0x0000000000087e53}}, {{0x00084d7bdfada95f, 0x0008b9c66a32b0d1, 0x0004ace9a2f6c763, 0x000fab721e716f0c, 0x000b96ed74e68c6c, 0x000110c8332c8fcc, 0x000efe475890dd0b, 0x000000000005cb4e}, {0x0003947e05207b63, 0x000d29d7b89a68e0, 0x00001e2e33262bf2, 0x000b55bca7a7d527, 0x000655d04585c3f0, 0x00057acc5a6e56a0, 0x00039e818e221c42, 0x00000000000fcb8d}}, }, { /* digit=7 [{1,2,3,..,}]*([2^28]*G) */ {{0x0007398749666d45, 0x0009c0a74da828f4, 0x00001ff782080bc1, 0x00026bb57c2f5ad1, 0x0002845d45e4896c, 0x0009a7d36981e2f7, 0x000e8fca152b877e, 0x000000000007b582}, {0x000b1649b1810a70, 0x000c3ea3b9bd9987, 0x000d4cd2bb2df2fb, 0x000fc5d5748a6550, 0x0007622665eed346, 0x000f16e277ac2f21, 0x000dc8bb5efe7fb6, 0x00000000000644c9}}, {{0x000db9a336c7d7d8, 0x0003598d0898164f, 0x00065860354f4784, 0x00018287cfc13dbd, 0x000c8655a658651b, 0x000c91b712d606e4, 0x000090ba64d3c563, 0x00000000000b82a5}, {0x000726397fcaaf5f, 0x0006c2d1dff024ae, 0x00092238373e43a8, 0x000ee6b0ea1fe022, 0x000cd5c1273c1ac2, 0x000e603e7c100b60, 0x000dfb4496084cea, 0x0000000000077c2f}}, {{0x00064d07c56a20fe, 0x00000a93fec079c4, 0x000155e36a436889, 0x00045a5cce5662fd, 0x000f83a9a4a9c00b, 0x000bbeb632e8a0a7, 0x00080f6e0cdebbc0, 0x0000000000063ccd}, {0x0008f36be2f62c1e, 0x00061fc10fa07d22, 0x000b3e653f03a3be, 0x0009cc66bf53af92, 0x0000f10bb6c9fda6, 0x0007625e1474b744, 0x0003cbcda9db3b1e, 0x000000000001dc7f}}, {{0x0006fec7b896d97b, 0x0007de8e32259b22, 0x00051ccb0af3cd54, 0x000a4219f42edba4, 0x000d0d411d4df147, 0x000014bb46d4bc00, 0x00066fa1a13a2770, 0x00000000000fa101}, {0x000b6039e0c4cc34, 0x000d8b2a1dfa62b6, 0x000ae98992614f2f, 0x000a3a2f88c7359e, 0x0008347726a08409, 0x000507bb9071f383, 0x000167d18a551c27, 0x00000000000b359b}}, {{0x000fae4c55d4b2c3, 0x0000aeaaaf45fd46, 0x000aa7e37459675f, 0x0009b673fe123f1e, 0x000dd8fd0129989b, 0x0004982a4e2ca56d, 0x000ec777d6d0cd62, 0x0000000000071e1f}, {0x0001c6bdd9bc3a7f, 0x000043e9a049f5c5, 0x0006deb929a38a20, 0x00008e24fed8f86f, 0x000ce199e8dbac2b, 0x0009cc964a1d1357, 0x00063b7cf06ec8e9, 0x00000000000d85ec}}, {{0x000ba68a3fc0bcb2, 0x0004e7d111c66c1b, 0x000d9aa66fbcd347, 0x000730c6db857e9e, 0x0009f4b46d124cd8, 0x0008472dc3c9c03e, 0x0001bbd42f0242a7, 0x0000000000026084}, {0x000aac1b65a94c0d, 0x000ea6332b11a21d, 0x000acbe9385d6783, 0x00028eee7e8944ac, 0x00005ab28372402f, 0x0005e1ff33d1bab5, 0x0007296944e82cad, 0x00000000000e8c75}}, {{0x00058e168fe9a81d, 0x00043a151dcbb9f9, 0x0002eed94828803a, 0x000fc00604d46e1d, 0x000572f3e28c947a, 0x000b1cd1dc3c9d57, 0x000a45ce4c1cbd14, 0x00000000000f80de}, {0x000d8f65d998669e, 0x0003c50920f39bce, 0x000b6be78ee5193f, 0x0008ba13f798e332, 0x0006c5edde471997, 0x000714a1e1294aaa, 0x00003c280002c2be, 0x00000000000f2126}}, {{0x000493dde1b54616, 0x0002ea44f6ef79f3, 0x000c2b67fffeca1c, 0x0004ed80eaf66728, 0x0008181514a2cb0e, 0x0002927ea2bf485f, 0x00064574670e180a, 0x0000000000012c14}, {0x000339b9a314b3a8, 0x000724068c073875, 0x0004212e0016a517, 0x000651d698b28177, 0x00096da14fa8391b, 0x000a578b1f310d16, 0x000ad7a089be6bd8, 0x0000000000044389}}, }, { /* digit=8 [{1,2,3,..,}]*([2^32]*G) */ {{0x00024e7304503422, 0x000f0ba86aec16bc, 0x0007f0cf87c57f69, 0x000ff0789df2f808, 0x000d97a773d58978, 0x0003f35f685750cf, 0x0008c9806bb730fc, 0x00000000000fed86}, {0x0006b0ff06192aaf, 0x000eadc0fcde080e, 0x00055bc2901e7a1e, 0x0007d028d3ad6cd9, 0x000997293550fefb, 0x0005cfbba5c652b5, 0x000d2232e12942ed, 0x0000000000098800}}, {{0x000418b23a7be4e3, 0x000cb162cdf33f48, 0x000c8d04be100c6b, 0x000d114454eb977c, 0x0008dea38a674478, 0x00035728a8ce403d, 0x000504d459633b74, 0x00000000000a63b0}, {0x00010a5f9fdcafdf, 0x000c40c74066a938, 0x000e6c61b766c71e, 0x000b588a99690ede, 0x000c3ad775623398, 0x000bb60ee4949517, 0x000becf9824f09cb, 0x0000000000085660}}, {{0x00083bb80ede991f, 0x000a02daddb11952, 0x000f09f6c4b181d6, 0x000e82721a6aa89b, 0x0007467506deb73c, 0x0008d8daa1091958, 0x000dfd0927724c42, 0x000000000007c17a}, {0x0009a9bb30e43182, 0x0003a8518dab18e9, 0x000594c3465b3913, 0x000c37f89e7a3983, 0x0008e273f6f35943, 0x000143d228e63f5e, 0x00028ec6d0352b83, 0x00000000000ebd16}}, {{0x000731dadf48f7e1, 0x000a14074ee26b83, 0x00088243bc9a29c8, 0x000d53972cecb4c8, 0x00079a7dd9c4aa01, 0x000c787cf4b0cf12, 0x00053f3e3e3f165b, 0x00000000000942de}, {0x000bfa5d149fa2b1, 0x000010cc6971941d, 0x0007bdd5c6a1acca, 0x000c1e292314a097, 0x000614a1adcb9fed, 0x00062b86a7547d22, 0x000b7d405561a486, 0x00000000000f5480}}, {{0x000be69f3af05d97, 0x00082c4e59f2ff48, 0x000865d4a01ec6bd, 0x0000d824464bbbbd, 0x000016f9540dfbc8, 0x000595b5d3bacfa2, 0x00080d1954efb613, 0x000000000007a5cd}, {0x0009c6dbd9d7e6b6, 0x000ac926a54cf784, 0x000f3366624e7b07, 0x000167ccb5c8d4c7, 0x000ff9a21ce20677, 0x0002df8cdc994d22, 0x0009083a25ff6b42, 0x00000000000f68e9}}, {{0x000a093607905265, 0x000ede544b89ab7b, 0x00017731e314dedd, 0x0000da69a73104b6, 0x00067274b105a6a9, 0x000c61bb65c26021, 0x0005068f9705cf60, 0x000000000003c4d1}, {0x000ed5677f9dc5c6, 0x00020ab5a27accb8, 0x000e0bb2ed27cc25, 0x00036d15a36afae3, 0x00095c455916e68f, 0x000b5d1fa79004b1, 0x00048916ffe6249b, 0x0000000000049338}}, {{0x000a7603914a9a59, 0x0000b941be86e102, 0x0001a6f35b551149, 0x00095b469d75ec8a, 0x0003db0d4374658f, 0x000fc77053fa79d5, 0x00012885da635c6a, 0x000000000008e7e8}, {0x000f4285c3e56baf, 0x00002558cfa8eed1, 0x0000effdf411ca89, 0x00098b96a32e8849, 0x000e3c45ce1a104f, 0x00085de0268237ef, 0x000de35c820dc22d, 0x000000000007459e}}, {{0x000a78ec870a31bb, 0x00036923d0b44369, 0x0005db7ea085ecd1, 0x000be009cf5b87e5, 0x000d1d61103d1656, 0x00065239313a37d0, 0x000ed81d705880fb, 0x00000000000ed712}, {0x000ff1a5976c303e, 0x0006f15ad02e6160, 0x00077114865ad858, 0x000376cba2b3ffe8, 0x000f9745443c56aa, 0x000903660c3be2b2, 0x00092d47c8a870eb, 0x000000000006c6c1}}, }, { /* digit=9 [{1,2,3,..,}]*([2^36]*G) */ {{0x000b550138d02bd3, 0x00038148bd39cbc2, 0x000f6b4c6038c07a, 0x000fbe2ce5484157, 0x000c87fdde9ff397, 0x000e9c179441e5c2, 0x000c716366b49ffe, 0x000000000002938d}, {0x0008a64bcbf3adf9, 0x000d026d450f9f8a, 0x00015da756f71781, 0x000bf4d298fd8771, 0x0007544768b65f68, 0x000491267e86df04, 0x00071a40b69a32f8, 0x00000000000f917c}}, {{0x0007f3a58f523dab, 0x000a7a66c70349a5, 0x000f8ae356d6f09f, 0x0003e96b5ab54115, 0x000c7c57d123dee3, 0x000d6ad37d068929, 0x0001780839a208f1, 0x00000000000123f8}, {0x000f3c2b5c9dfc15, 0x000f4b3e5e52449d, 0x00055ba373af8955, 0x0000ab7389f2dd3e, 0x0005890bba6f513a, 0x00066bf093197a14, 0x00072261add75b6f, 0x000000000004eef1}}, {{0x000fbdf154b15bac, 0x00063810b6ab3193, 0x0006da8c3809a3ef, 0x00038dd898977511, 0x000e7a336c9a3cf8, 0x0006f89c03e391e4, 0x000e227014833717, 0x00000000000bc4f1}, {0x000e7d4400e0ab41, 0x0006b32b104f92b2, 0x000d1a7a3b67e3fa, 0x0000437bf178ac12, 0x0005c99370d5b831, 0x0002b93a8722299f, 0x0007190a493cf033, 0x00000000000a420f}}, {{0x00046acf9a0ee15c, 0x0006a21feb7fb87b, 0x000579369777bef5, 0x000557624b04e704, 0x0006342cb0ad03a6, 0x0004f64262531f18, 0x0003ea088c4d54a2, 0x0000000000006a87}, {0x000f1f11e0fca837, 0x000d5dbe0253ef23, 0x000bcfdbd73eb554, 0x000368173e65902b, 0x0002ccbfa504eaaf, 0x0000e163e71f1fab, 0x000f3bb7b845224b, 0x000000000003c779}}, {{0x000cf36036019ecd, 0x00029cd7b3c4286b, 0x0005e1ca08cbdeb9, 0x000bcbd24ef5c386, 0x000ce579c309eb66, 0x000f6c9007edcc21, 0x000c2c7b19d49116, 0x00000000000b6317}, {0x000aad793c4e52a3, 0x000e7554ba553558, 0x0002315e3b514170, 0x000e33bffda4032e, 0x00082306675c3d1f, 0x0000c91e75dfec47, 0x000879be59305e00, 0x0000000000025a6b}}, {{0x0002c6fd041a12fc, 0x0006aa35802f5d21, 0x0000c3d459456256, 0x000991d472b9d211, 0x0006a2f8e875261a, 0x0009b6d63d81a1ed, 0x000758942f213a69, 0x000000000000ae57}, {0x00067bfe08ea2ebd, 0x0007061191c82b48, 0x0000611a48f73652, 0x0003e86525112224, 0x000d30dabb91abe2, 0x000d2742466dd967, 0x00005077650c597e, 0x00000000000ab25a}}, {{0x000abb01ee5e0194, 0x000bca624ab366b4, 0x0009dc413b0af513, 0x0009c4273aa694c3, 0x0009779288abe822, 0x000575e0e0cc3102, 0x00003ef8eff30f57, 0x000000000007d528}, {0x00093a51fb5fbbe1, 0x0002f32d87e548f1, 0x0004001c13dfb44c, 0x000b8dd16c6e6274, 0x000c2c140452aa2c, 0x0003031b1add098a, 0x000543d25f285d2d, 0x0000000000075b59}}, {{0x00032a5061a42b94, 0x000dc520b0bb8a42, 0x000466f1305a432b, 0x000c73a73c239760, 0x0009783aabba85c1, 0x0004631556e4dec4, 0x00017b69f0c69bb0, 0x000000000009c97b}, {0x000fbbef3e8375b4, 0x000b155af24a9074, 0x000991d9ad3481f7, 0x000283d708671c48, 0x00035fd9001a4034, 0x0002eaf3b200ddab, 0x0006c4e45f28e434, 0x000000000001ba93}}, }, { /* digit=10 [{1,2,3,..,}]*([2^40]*G) */ {{0x000e8393cd68c757, 0x000b2b083ba6a1e9, 0x0004638d474c7417, 0x0007a21fc82dc041, 0x000a9d3679d89536, 0x0009724c0227be26, 0x000c0fc70f6d6c7e, 0x00000000000f9ebe}, {0x00075bdec21bc5d4, 0x000b029dde03dcdd, 0x000a669d8fc534ff, 0x00090c90f602f4cb, 0x000849722bc4daf5, 0x0009b22b617c5288, 0x000b90a8df99f008, 0x00000000000e59b9}}, {{0x00015e6442d15d01, 0x000dc6f5775290ef, 0x000cdd79298e58a8, 0x000842778b96c6d8, 0x00022f59350519a1, 0x0007209d6a674f99, 0x000fff5abeeec46b, 0x0000000000047cf5}, {0x0009d3497d146805, 0x000ede24509b7378, 0x000ed2fba1e0b34e, 0x000af595761e8e3f, 0x0008d420a2887f7d, 0x0000ff696ed5cfcb, 0x000c8f365b29eb7a, 0x0000000000099a1a}}, {{0x000785db50fa1164, 0x000694936c6a0393, 0x0005ce545ed4b2d3, 0x000e8b45714f2c6a, 0x00023f5ac25a03ae, 0x000b33794139bd69, 0x000ba96a2e42bab5, 0x000000000003ff7b}, {0x00034248c56f7e51, 0x00088b61d8643327, 0x0008d647e582cbe4, 0x0000e1472eb77fae, 0x00013b99c6356211, 0x00074c9f23d5b96f, 0x000250956ecf64f6, 0x00000000000ef2ba}}, {{0x000a8baf84131eb9, 0x000019ee1ec3a29b, 0x000d9f684960ce84, 0x000737588102ac15, 0x0009c08527f432b9, 0x000e3dfbedd296cf, 0x000c4fb74f8145fa, 0x000000000006cd7c}, {0x000debad8e4205ae, 0x00062a0f2fe7a043, 0x00094ce3fc7d23aa, 0x000f2d40eeb90a7f, 0x0000be4de6846e7d, 0x000dd06bce2f46e2, 0x0009f6cd28feba3f, 0x00000000000e6d6d}}, {{0x0002283f4c1e03dc, 0x000bc246ffcb6b34, 0x000a382150ba305c, 0x0003ae2250e66766, 0x0000924ce5fab4b4, 0x000d8c77695c1b5f, 0x0009d02555795beb, 0x00000000000acd9d}, {0x000cf0d26acc1b8f, 0x00088e1d74aa6321, 0x00035822f91490d5, 0x000df2795af56df1, 0x000fb331b6f4df74, 0x00059e13724b10c5, 0x0007f2b0a6df9a65, 0x00000000000c0663}}, {{0x000c55f77d493f59, 0x000089ad73168775, 0x000791ccc3015317, 0x0006c2d30b3a5f4a, 0x0007c89723d59e94, 0x00031f6077bc4ced, 0x00034179f514a1bd, 0x000000000003a274}, {0x0007950f4645c0c2, 0x000e07eb010278e1, 0x000a3d29cb5ab91d, 0x000760f35be21cba, 0x000b7c793331718d, 0x00030d29eba58160, 0x00003afbc0ce1f8d, 0x00000000000c6f4b}}, {{0x000986e6462b5c9b, 0x0000cbd8c0867ee8, 0x000db80962770b4f, 0x00012de024593896, 0x000fdef840b687ed, 0x0000b56e13f7d98f, 0x000e8771eee0cb5f, 0x00000000000d8d9b}, {0x000f5c1c38b9eff3, 0x000c1e6b50b5a5f4, 0x000fada267894657, 0x0001bd17cb1f9925, 0x000d4ff11827418b, 0x000042c63607818e, 0x000ae3e630d93a9b, 0x000000000008c779}}, {{0x0000de60ecec558f, 0x000bb35d474260aa, 0x0007deb342712d19, 0x00015e22e91bf5f3, 0x000cc08b6b1abd6a, 0x000b97de8e366a84, 0x000f29759c122f55, 0x0000000000008a03}, {0x0005b54173576b1f, 0x00000dcc9fca2774, 0x00073c06ae128d8b, 0x00039029b59cd052, 0x00006f5e5bd4deae, 0x000099f4df532ede, 0x00005284fbeeb936, 0x00000000000088d2}}, }, { /* digit=11 [{1,2,3,..,}]*([2^44]*G) */ {{0x000b3d633d0721cb, 0x000732ba8c78fe5a, 0x00016e2c1c57f816, 0x000f36a2fc2451f3, 0x0008bb91e1e36842, 0x000ead762fc5c955, 0x000556035d1dfcc3, 0x00000000000031e5}, {0x000b4359fe8646d5, 0x000383af0cc803c6, 0x00070f15b8bb97ea, 0x000de0a6ade1d137, 0x000d93b2dcb580c3, 0x000a2214de8c3a5b, 0x00048de3adbd7c90, 0x0000000000011929}}, {{0x000e8783f9b6f97e, 0x0009b65026296c0d, 0x00086ba77888a60e, 0x00063a460c8bbf8b, 0x00078b2a71206237, 0x0005497e7fa8f5ad, 0x000618fd744bdf08, 0x000000000002ba35}, {0x0004df87b45c7eff, 0x000870cebfe9d444, 0x000c034f12ddb3df, 0x00017a3fcf19627f, 0x0007c2f112616558, 0x000f2c85030ab44f, 0x0000c3bb001c9ddd, 0x0000000000007326}}, {{0x000e365e9f55b0a4, 0x000aeb08fb116bd9, 0x0002cf623c1f798f, 0x000fc7b6f9549671, 0x000f76bd243c73ae, 0x00009d5a8c0fb886, 0x000049871eacc5ce, 0x00000000000e773f}, {0x0001eb3732cb8726, 0x000aa92945c840e9, 0x000022c04533de34, 0x000bc1d0509d7400, 0x00010f1af1754762, 0x0008c160f15cf97f, 0x000f0c1f85569532, 0x000000000003b439}}, {{0x0004f7c9bedca76f, 0x0006dfa7d1236235, 0x000a7e4930642e7b, 0x0007288beb1282c5, 0x000a07fee8a99ea2, 0x00070fee91c069ef, 0x0006fa5749c7b558, 0x00000000000afcec}, {0x00048441716f41a1, 0x00064a3f8f1b0daf, 0x000b8af2f805e4cc, 0x00029a9b59dc06f1, 0x000b98a92c387533, 0x0002b4662fa8e5f5, 0x0006c66b6f46fd3c, 0x00000000000ec04c}}, {{0x00054b9f6efe8494, 0x0005eaa16c27a15a, 0x000106292d7b104e, 0x000d193aae87c9d3, 0x0009916d634e7ae2, 0x000a65b4b125ab45, 0x000e2202ded714cf, 0x000000000004e212}, {0x0009494225bd1826, 0x000c097c48a1862b, 0x000bf9e4c3ff8573, 0x000b77b2652f5018, 0x000d078efd386fe8, 0x000cb82991daa602, 0x00062635885364db, 0x00000000000b8240}}, {{0x000f5a3697f1c244, 0x0000e0430af76c1b, 0x000f0e87f66ce63d, 0x000905f12e919108, 0x000012db9e14e1a7, 0x000baeeac1c689b7, 0x0003196bdd3dc90a, 0x00000000000504f0}, {0x000e18cdf6373284, 0x0003c874afd60b16, 0x000a978150da10ac, 0x000eee1ebf4aab2c, 0x000c1aa49fe60d33, 0x000217cfda3631ca, 0x000e770d8340fbf2, 0x00000000000423b7}}, {{0x000b3813851ecc4b, 0x0001df8c07372826, 0x000ea9f99e2d35f1, 0x000faf1a6305a291, 0x0007f3e0f93d2b97, 0x000aeb8c15bc61f6, 0x00024b7238583cd7, 0x0000000000039f5f}, {0x0002b746db300ac6, 0x000a11cc8b467be6, 0x000e46954d17b55e, 0x0005f95ba2641ae4, 0x0002ce9d565b1b9a, 0x000eedc6287a0c36, 0x00003d07fb51b2e1, 0x00000000000a9739}}, {{0x000d77fe5e566bbd, 0x0001978a53b5a370, 0x00081dca6fe505a1, 0x000f427019a6f8e7, 0x0006dc3ad0ba3520, 0x000745b7cde6fcad, 0x0002dcfec96e4f79, 0x00000000000b133f}, {0x000924a225ecf745, 0x0000c50088a2b006, 0x000c145291ebead7, 0x00032ff23ae4b9d3, 0x000e85246712f213, 0x0000b515e8cbc659, 0x0008b727fa9c8df5, 0x00000000000494ac}}, }, { /* digit=12 [{1,2,3,..,}]*([2^48]*G) */ {{0x000ff6bf222c5c9c, 0x000322986475308d, 0x000309c5ef927cbf, 0x000d6b4216ab9acb, 0x0007be12d76a038c, 0x000347bdb3df9b7b, 0x00048913f4d9785f, 0x0000000000013e94}, {0x000466717b5c75f3, 0x0000a5f8e796eab2, 0x000d6af2aad3919a, 0x0005d8ad10740b88, 0x000b5337dee6254b, 0x000f02247c38b8ef, 0x000c4cf688c2e194, 0x000000000006c25b}}, {{0x000272cd3b35df41, 0x000d936c9dbbec27, 0x00026ae70fa619c9, 0x0008db696a8f9f19, 0x00056b01e6bc1ab3, 0x000fc4adae031d23, 0x0004e410466ae68a, 0x00000000000ed9c4}, {0x0005ea962547af52, 0x000cb61272c12a27, 0x000f929706a5a2ac, 0x0007a910ecc49eb8, 0x000ccbe84d5cf4c4, 0x000e497d7eb95dfe, 0x000ce443f3b71c8e, 0x000000000004c6fe}}, {{0x0002d9d94d551889, 0x0006182e5d818574, 0x000101531df0c231, 0x00044261daa2e22b, 0x0000e46f32576b02, 0x00069db38b86a358, 0x00027eacf145bd76, 0x000000000004df27}, {0x000d2ba752047cd9, 0x000c203d9391e25b, 0x0007c9592434b2d4, 0x0007845ec38fa9ac, 0x000a265ad6bbefb7, 0x00054a1b2dd40660, 0x000499a22d988618, 0x00000000000737ea}}, {{0x000ef1248ca55f15, 0x00028e323ed0c422, 0x0001736a7d35b006, 0x0002f06e8d68e4e9, 0x000ad0742e5d9c09, 0x000d3df92d8f5555, 0x000eabe2d175bf00, 0x000000000004f71a}, {0x000a6a143a42cf09, 0x000c6d1762d7229e, 0x000840a2cbe90735, 0x000cb4c6281f2a74, 0x00003603e53a2caa, 0x000fecf29635ba47, 0x00036194a9811d49, 0x00000000000466bf}}, {{0x0009fc85048451fa, 0x000fd4737236d065, 0x0005b89cfa755eca, 0x00070306da6e06f0, 0x0006f3838f569da9, 0x00043188730279bd, 0x0005d0fb328c8b94, 0x00000000000be90e}, {0x000859016f87df1b, 0x000843334a6711d3, 0x00078d74e5890358, 0x0007b6e38904b738, 0x000296b588a53493, 0x000577ae391e227c, 0x000c7da599b21544, 0x00000000000214a0}}, {{0x000fcc62fe159c27, 0x000c9e63fbb0fb71, 0x0007ab3cd12c8947, 0x00030677afd4bf85, 0x000dfd37120d5cea, 0x000d718a74494e39, 0x0005fb8c572c7249, 0x000000000005fa30}, {0x0005abf2e0c1181d, 0x00074751c217ee1b, 0x0005917c5a26a520, 0x0006e6efe7a64872, 0x0000f53b0e479a99, 0x0005fd5931a4f6d1, 0x0009ee651390ecd1, 0x00000000000739ee}}, {{0x000e27c9677a2151, 0x000ef0b6d37446aa, 0x0007f13e8f2bd87e, 0x000c94fa109847d5, 0x000044944c7712bb, 0x0005a31b874c0d53, 0x0005920d280b18eb, 0x000000000007ef42}, {0x000c07ddca373d80, 0x0004ef11030c77be, 0x000075bee798eeea, 0x0002d013d22f1b04, 0x000cd93ee54dd5e0, 0x00041d4b1b6d66c9, 0x0006ed80b4154faa, 0x00000000000acf8f}}, {{0x0004ca485f1804e7, 0x000ad0f05710ab2a, 0x00002b0d41da0420, 0x000a67a46b8d0e2d, 0x000c698b78cc137d, 0x0008a9393454b89f, 0x000e69f2a6e1de25, 0x0000000000016488}, {0x000b96b954a8287c, 0x0003d7c6c5501c10, 0x000fb63222050457, 0x000e30e92f152478, 0x000327e70a0a4b9d, 0x00014936309d4ca9, 0x0001379c8b16340d, 0x00000000000ce642}}, }, { /* digit=13 [{1,2,3,..,}]*([2^52]*G) */ {{0x0003c432161be476, 0x000c0f8a8499b505, 0x000715248b87d78c, 0x0001b1d515e1328e, 0x000ba941e788b85e, 0x0005dd8d888a2636, 0x000350a045241d2b, 0x00000000000332f0}, {0x0008eeabc026bdc0, 0x000f796c4b204e16, 0x000ce54b1f342310, 0x0003fc6d00b602a1, 0x000e89aa3b796fc3, 0x000d4dd0007a914e, 0x00095635353eb7a4, 0x00000000000673e8}}, {{0x00027e0f6ecb7465, 0x00040f36e83987c1, 0x0002e0c806d929c2, 0x00007464efc5b0d5, 0x000ad316c43436ab, 0x000ccf839b211e59, 0x000a072515ec9f16, 0x0000000000003dc6}, {0x000ec4a69e8d5661, 0x00017842b727527c, 0x00065c4526d40261, 0x000711ccef5255e9, 0x00075108cb92967d, 0x0001b9740cd3bfb0, 0x000308e50c0d8aec, 0x000000000001a9e6}}, {{0x0002078cea733c1a, 0x0005b283eec25eca, 0x00036d44d991d5b4, 0x00083b827ad302e8, 0x0002bde3fdd0269a, 0x00030b3a6225f2f1, 0x000043046fcf3801, 0x00000000000c3ed9}, {0x00066dedc2439ae4, 0x000eff870f14cae6, 0x000680b39cf67cb8, 0x000d5f4847be7732, 0x0003d0ed73a0f3e1, 0x000b3babba949822, 0x000f706933ccf014, 0x0000000000037f08}}, {{0x000ba839c8cf3524, 0x000ed1afa6aa5579, 0x000f9ef0d2ddddd9, 0x000920b5d36da502, 0x0009291e774f07fb, 0x0000d87a8144d51f, 0x0001a026c2c134f4, 0x00000000000a932f}, {0x0003544f31a7b78f, 0x0009935bb2a42294, 0x000ea47969f6664d, 0x000cabfaa1838ed8, 0x000fe2855f1f5c40, 0x000525934ea0c05f, 0x000fd4931ebb02fd, 0x0000000000016246}}, {{0x000bd623cb7fe067, 0x00038ecfabd26775, 0x0008c3832c0a3527, 0x00064ccfe2691ca7, 0x00058347566acf4e, 0x000b8c733e3889e2, 0x000f5748da354885, 0x000000000009d9c9}, {0x000592cc5e5c9fb4, 0x0000e8c26a8d609c, 0x0000459f168ec210, 0x000a70a3f8db9f92, 0x0000e758213e181c, 0x000b2653e25aa645, 0x00003aa4898f9169, 0x00000000000ccd83}}, {{0x000fac468f3d59db, 0x00099517d13b0e90, 0x000cf2490366b8de, 0x00026866d752aaab, 0x0001cab026676e2e, 0x0003163c395da9fa, 0x0003c9be8d91ad42, 0x00000000000a6995}, {0x0007a57ea4ee9030, 0x0006ef728b1d231f, 0x00013aa7ae93d8f6, 0x00000a82e75d9c30, 0x000e3ad09def97a9, 0x0008a2be8136c6b1, 0x0004474bab14a6dd, 0x0000000000025cf1}}, {{0x000e1d30e97eb41c, 0x000b411b59f3da92, 0x00020acfcec12d54, 0x000f0a1936595900, 0x000cca0b1b0e5cad, 0x000274a5e8fef04f, 0x00027ebcb4d9fb0c, 0x00000000000ba784}, {0x0008e71ae4477c5e, 0x000fbc49f0bc478a, 0x000ac96d890c62e2, 0x0009e583f796b820, 0x000b17964262200e, 0x000db00395bbea92, 0x0002ba86b3c15756, 0x00000000000ead48}}, {{0x0007642e08638534, 0x000b5cd92906c650, 0x000ae6db49a06b5d, 0x00029781fdc19156, 0x000c269d611e0d69, 0x00065b00a45d01a8, 0x000388e7bd1e7096, 0x000000000009bcaa}, {0x0007591cdd6ae97d, 0x000ed8f189e87506, 0x000ccf1d10959a9b, 0x000bf16c633b1123, 0x0009d6f1dac8ca65, 0x000c3381dc6adc9c, 0x000d120df2c293a3, 0x000000000008388c}}, }, { /* digit=14 [{1,2,3,..,}]*([2^56]*G) */ {{0x000653d60a9d872c, 0x0003bffdbd0eb2dc, 0x00061fddaf39f568, 0x000cead35e7a3a29, 0x000c67833028c11a, 0x0004c79764998cf8, 0x000a1c8f3a346b84, 0x00000000000db9b1}, {0x000642a471b701b9, 0x000628735dabc47d, 0x0005300f39a216a2, 0x000dd49d267a01b0, 0x0003ffa20d117c0a, 0x000ab2d4a2b46c91, 0x000080f2acef26d8, 0x000000000003d926}}, {{0x000ba70a22083784, 0x00084e9d2a98a2f2, 0x00091072e4da23c2, 0x000325dceaf86ae5, 0x00088f161525f399, 0x000211b9d03b17c8, 0x000a48d8ac35c984, 0x000000000009050c}, {0x000bbfa19d5ef891, 0x0006ba818c44b2c9, 0x0005e1b560830da0, 0x000af35f8715b052, 0x00099d8829a9633a, 0x000a820f15463e1b, 0x00075db18df52d84, 0x00000000000d0966}}, {{0x000ae853a945611a, 0x000bed54e2c7c031, 0x0009b2bf77ae12b1, 0x00005e8e60f7f5a6, 0x0008427483adcb41, 0x000bff383705db30, 0x0006e9f73ba98bf2, 0x000000000000220e}, {0x000231b48f25af77, 0x000e8c01c46b84a3, 0x0004ae472f3bd7a2, 0x000dc0bfa3403e6d, 0x0007d2202896f738, 0x000882e5e098bc68, 0x000b13ec0c217a5f, 0x00000000000a1f4e}}, {{0x0009208204f520a2, 0x000ed2615c78254f, 0x0002b7a2ee7b484b, 0x0001d771c84a04b5, 0x000fcb9f9e349c3b, 0x0004f7846b6fc203, 0x000248bed65464c6, 0x00000000000eb004}, {0x00040455a574f8cd, 0x0003f5c017726a4e, 0x000b0a7d5066828d, 0x0006666aceb0e3ac, 0x0008fc046f0ab78c, 0x000aa959518d3c18, 0x0004e87f3e2f301b, 0x000000000008a284}}, {{0x0008a96d207a2eb2, 0x000e3c899eba3614, 0x0002ec9689146ad2, 0x0008629da55568ed, 0x00082b1dc1d9607c, 0x000c001ff6b54722, 0x000b8523232311c9, 0x00000000000488f8}, {0x0000aca655c2cd82, 0x000723867ac9a850, 0x00092fe2557b4773, 0x000c647a74488fff, 0x000fbe0876407398, 0x00019a571f6ed920, 0x000aeb72beddc763, 0x000000000006a244}}, {{0x0006fe658431a6d6, 0x00064b7da79c5a1c, 0x000fc6b2b6576354, 0x000b7b54aa36d18e, 0x0008ed0e30913481, 0x00093074c6efeaf8, 0x000654eb017bddc9, 0x00000000000529dd}, {0x00089f1ff5fdf666, 0x000fcf5177230c70, 0x000373317732e646, 0x00082d34ca267426, 0x0005adcd1650194d, 0x0007758b7eaeffe1, 0x0008194dcec3d9af, 0x000000000004cc2c}}, {{0x0003e55601cd21ee, 0x0004794bdc7f4a7b, 0x00080eb7c8f212fa, 0x000dab0d654cb574, 0x00037a49195627e2, 0x000d5d0991d4e1e5, 0x000de7a1ef570c31, 0x00000000000295f3}, {0x000c78902e5817a8, 0x000198681b00d89c, 0x00061b3376c1d033, 0x000e90c6a1b57484, 0x000c1222e5544324, 0x000d53dd044f9324, 0x000ef0e30ba10fff, 0x00000000000b48ee}}, {{0x0004a14fee68295a, 0x00041a349bb65da9, 0x0006f09eba200d68, 0x000d891c18d37516, 0x000dae8d2bfba6e1, 0x000b330789985aa4, 0x000e948baec9ae31, 0x0000000000098750}, {0x000e6cd5311f8630, 0x0009c0d834bf8a5b, 0x000c536623c88198, 0x000faaa0c51d098d, 0x0002b887a10f0c22, 0x0008bed323240404, 0x00066231f6a61424, 0x000000000001ce0d}}, }, { /* digit=15 [{1,2,3,..,}]*([2^60]*G) */ {{0x000c2532e44da930, 0x0009eac6dbdf6097, 0x0009dd0474f3e9a9, 0x0004de3dc28e1b18, 0x0002a66477111669, 0x000b08b4b2d039cf, 0x0008cea13bbe6fc5, 0x0000000000010ebd}, {0x0006e345ee3db6d1, 0x000c2cd4720862b2, 0x000fcd0516567c14, 0x0006303929bfa29c, 0x0003818249bfb3f6, 0x0007f7cd97c378e4, 0x000a1676068c8084, 0x00000000000987eb}}, {{0x000e55f593b72e2d, 0x0008c1238e0971aa, 0x00081a4c08ea4523, 0x00054e7f74c5c514, 0x00028805813b4512, 0x0005e7a6e238b16d, 0x0000bc23987b2892, 0x000000000002a1a1}, {0x000c0e8fa1a83cf0, 0x00010944c784c643, 0x000f1939fa2e366e, 0x000ab2aead457171, 0x000631c042056bf1, 0x0000b8881d5f8f0e, 0x0005a8ac062526a1, 0x00000000000fe550}}, {{0x000d9597e54c99bb, 0x00076cbbd8575ded, 0x000019092c8277a0, 0x00056202e6b72a58, 0x000e7c024443e5cb, 0x0005368f35738ea0, 0x00044f8ed06170b5, 0x000000000001aeed}, {0x0001a7ce730f30e4, 0x0003a3d90a6b26fd, 0x000480ba5c428a59, 0x00093dcc5612aec9, 0x000f99c1bacc0890, 0x00043eaadc272ef6, 0x00089147db3b43dc, 0x000000000000832d}}, {{0x0001abaa498687bf, 0x0001bac92ee14ee5, 0x0002ef494748554e, 0x000ca876e7a32661, 0x000a8456c9af29a7, 0x00054326f0f2b7e7, 0x000ec87471824e97, 0x00000000000364d2}, {0x0007a1e32547416e, 0x000f386d8aacd172, 0x000735a9921c3b5f, 0x000fc881d79f7eb2, 0x00040040547d9805, 0x000b4e90b377ac3a, 0x00081bd39215d461, 0x000000000004c5fd}}, {{0x000bf8e11ac3f3fa, 0x000df9ffe5562f1b, 0x0000905bb11344f5, 0x000f981cbefa3c77, 0x0003667bfd643039, 0x00040e3df2ab0688, 0x0009ca9007a25743, 0x000000000005a3a4}, {0x000a64031de3bcfa, 0x000fd9c7be629ab9, 0x0003fbe0cdc1be9c, 0x000ff39e7380dbb1, 0x00059facc3b8ffe7, 0x000ae422c620bb9b, 0x000c432ddcb8cd31, 0x00000000000d12c3}}, {{0x00072db65199d9d3, 0x000d703621d34a54, 0x0008bb1d8b92a619, 0x00000f66ca2933b1, 0x0002de1494a2886d, 0x000dcdf82d0a2238, 0x000832b8656c4d0b, 0x00000000000c4a58}, {0x0005f2f5aceb0154, 0x0002fa982c1aa34d, 0x0006b9fce5077d2d, 0x0008de431390c6e9, 0x00018c4fe595fc26, 0x00090d82fea4160e, 0x0009076c427a6367, 0x00000000000fc519}}, {{0x000775c688e983e3, 0x0003e8c0749464df, 0x000f192d78daad34, 0x000e96904bb2048e, 0x0004d6dc8b606cda, 0x000438bbc6dec959, 0x0005a58d26586954, 0x000000000001b0e9}, {0x0001e04544fa17f3, 0x0005e8189f1141bd, 0x000c131e8abc17dc, 0x00075a227f8ec1ab, 0x0000607e37397757, 0x000793e4e7a12524, 0x000af4afae84e74f, 0x000000000005bf5b}}, {{0x00039549b6d366af, 0x0000aa10292b850d, 0x000fff80cff6798a, 0x000f18f73ad7a1fd, 0x000c5897b11f7a36, 0x000664c618b2c7b0, 0x00022cf7b9a272cb, 0x000000000008f81e}, {0x000e957ffad5963b, 0x000663b99b210935, 0x000ea3abc7ab4283, 0x000175d001db74bf, 0x00067159cb8a3af1, 0x000de4601526f084, 0x000eac6a3c6e1feb, 0x000000000008c232}}, }, { /* digit=16 [{1,2,3,..,}]*([2^64]*G) */ {{0x0004c667c92f7888, 0x000aaa54768d9e88, 0x000d1397d0aa7f52, 0x000f203faef6863d, 0x0004bd7471b3774d, 0x0007de2e9f795a03, 0x000cfff0958718b4, 0x00000000000e1160}, {0x0005c7ba07a0ffd6, 0x0005186ded97af9a, 0x0008fa18cb4fab4b, 0x0008920424e84590, 0x0004eecf8b2b0558, 0x00068a6fa3745591, 0x00019fe7d3df1fb9, 0x00000000000bad07}}, {{0x000b4e8b4136f0e4, 0x000ae2566021f579, 0x000cbf2ef6760188, 0x00047a5d9f51b6a3, 0x000df8efa64634e0, 0x0001f584f0b50d91, 0x00091cc2bbcbb297, 0x000000000000907c}, {0x000fd43610d5f812, 0x0000ca7ebeb0dd65, 0x0008a7b6eef1e9c1, 0x0009a073f5c962ab, 0x00053ff74a2fc04d, 0x000f0749d95c155e, 0x0005d0923c65a53d, 0x0000000000027ae3}}, {{0x000cd3b33afd62e7, 0x0003c4d37c266037, 0x00042b261375e38f, 0x000a2e928ca9d674, 0x000a79beb236566d, 0x000f801e7a9771c1, 0x000358af6b97a976, 0x0000000000071259}, {0x00004ab4fe03d3c3, 0x000bcc23a5e31cf5, 0x000c506466ff69e3, 0x000233b1911ccf3a, 0x000cfa3b3ace3f3a, 0x0004c5f5c93e4664, 0x0003c04bdc14832d, 0x000000000006abf1}}, {{0x000832aefb763bd9, 0x000f0d5469c7af17, 0x0000d7bc962f1b04, 0x000ca21a16caa7b0, 0x0002e6cc7f39f881, 0x000378723221de18, 0x00066010d61ab531, 0x00000000000520c9}, {0x000ed27c50cc42c5, 0x000ac145214ccbc9, 0x000ac441f327ce66, 0x00059e30cb1fe6a2, 0x000a3e299fe79fce, 0x000af78cf2e6e77f, 0x0001593a0cf652d5, 0x000000000003e852}}, {{0x00087e649fa97c56, 0x00029ebbe18b74d8, 0x000417a0e476f2ee, 0x0005a2a0b24f97ba, 0x000262fc61243ddf, 0x00003b73af9a400c, 0x000fde9ad9b0bc6b, 0x00000000000153c8}, {0x0006f3a6ac904b01, 0x000f41b6477d9542, 0x0008ea414bce433e, 0x0007128953069569, 0x000db9e775794428, 0x00005e0d14b5db01, 0x0002f5237edf0bde, 0x0000000000085533}}, {{0x000e220415482512, 0x000190791dfa1ca2, 0x0007078d88a1aeff, 0x0005b77ccedf4f34, 0x000d5d965c0549f2, 0x0009e672705170cc, 0x00017637d9521bd4, 0x0000000000086a00}, {0x000e53f005b29758, 0x000b5dab44493664, 0x0005df02ede5bef3, 0x0000c3e4c2506ba1, 0x00065ec6f1324366, 0x000ac7691b2fb261, 0x000eb5ccc4221a99, 0x00000000000a576d}}, {{0x0006b1405a6d6a62, 0x0001e3a17f86cedc, 0x000ffc614b14d0e0, 0x000a3f0927935e2a, 0x000ac04d4fb0a86e, 0x0007694212f43742, 0x00012f32a30bce38, 0x00000000000d8d39}, {0x00091bf3c81523e6, 0x000ed34154b18f9f, 0x0001725c2ac49b1c, 0x000be0f9f7a13c1b, 0x000a531736e526cf, 0x000cfa2c250d50b3, 0x000e5f81849773b2, 0x000000000003ba8a}}, {{0x0003089126b94126, 0x000854a87307686d, 0x000fced9f497ff98, 0x000042f427ea198a, 0x0001ed259219c1d3, 0x0004850cadc59211, 0x000e8d0abdbd1623, 0x0000000000043b6f}, {0x0004352ff19d9aba, 0x00069d3c79d16450, 0x00090120dc8bc8d6, 0x000535d5a98bf664, 0x000dab2cdb2ba736, 0x000af89eeacb3b7d, 0x00053237d3743ada, 0x000000000000b348}}, }, { /* digit=17 [{1,2,3,..,}]*([2^68]*G) */ {{0x0006e0a86f5827e3, 0x000e1a68295d9bd5, 0x00032e6b7dcbdf31, 0x000a0cffe0c3df09, 0x000b3cd00a1a8deb, 0x0000f90885b4d037, 0x000ef7e9edc429aa, 0x000000000005847d}, {0x00025d7642f87bf0, 0x000f49739d03ced7, 0x000f63949ff1cd98, 0x00034ff1759060ab, 0x0009a7e94dbbdc3d, 0x000e8b7f3029e9aa, 0x0006f42a3cdfa0f7, 0x00000000000bbd8f}}, {{0x000178a4d4ad7d87, 0x00040cd8c2ec862e, 0x0003f7b9dc665542, 0x00086d4db83e1ac5, 0x0002bb549bb5e123, 0x00007c0f19a79203, 0x00008eaf81cba628, 0x00000000000abf20}, {0x000001ed540ad4e0, 0x0000a9d7a72302a9, 0x0007110b90df5c50, 0x00024daec9005170, 0x00037193eb3047c3, 0x00015c655408cd0d, 0x000c228f0bcce2d3, 0x00000000000869d6}}, {{0x000e5354c88a38dc, 0x000717192a26df13, 0x00059c532d5dc6ab, 0x000195620aeab120, 0x00057c2328498938, 0x00079bc39ebe39dd, 0x0000925787970e4f, 0x00000000000143e4}, {0x0006e01b286241f3, 0x0001e5f60303562b, 0x000cf202635ec6b7, 0x000b3a2f1856e619, 0x000bbf77d65c7ec4, 0x00011058fbef7dc4, 0x000945b444d50670, 0x00000000000c33cb}}, {{0x0000e30b66c01c80, 0x000354b5e753d742, 0x000c1ca06540fdb4, 0x000d75f42fa905c4, 0x000ac33e462b4034, 0x0008de3bb89b85ed, 0x00039131f413c305, 0x000000000006ba75}, {0x00046bc0a659bd1e, 0x000573f50020190e, 0x0006ea7059f1f5a4, 0x000aa10efa2adddf, 0x000e1a6566aa7297, 0x000b4f2143e8ccdb, 0x000ae74dfda07fd7, 0x000000000007cb1c}}, {{0x0008cb34259001d3, 0x0001d49d1cfcc46a, 0x0008f80188e0d2b9, 0x000d285d2ab0a996, 0x00071df5b6cb8cd5, 0x00003fadd9c5cff6, 0x000c0019f4095a30, 0x00000000000aa463}, {0x0002c2d4a3652c8f, 0x00087f86673b013d, 0x000814cd905b85f4, 0x00075b44cc2cd5ed, 0x0000b0342517b376, 0x000817cd771d5262, 0x0006183af1f31657, 0x0000000000079199}}, {{0x000066ce8afe9a22, 0x000815600fedffd0, 0x000fa276d4e1e61e, 0x00062674cb08e4e2, 0x00052e9ab52d8f12, 0x0005686adfab0c1f, 0x000e4e090b1ac94c, 0x00000000000bb10d}, {0x000c301d650cbaa8, 0x0003b3383f48546f, 0x00045006d2b6b386, 0x00092fe500058f01, 0x0007f4ce508ac5ab, 0x0007a5166f03c7c9, 0x000d66525ac2cea7, 0x00000000000996ef}}, {{0x0002ee0f55870dbe, 0x000f522daed9eb3c, 0x0008bd7a619de4ba, 0x0007daa46ec27562, 0x0004df0f7a076593, 0x0006036c14c58eeb, 0x000aa5eb972393fa, 0x000000000004d17f}, {0x0005a44cb91701e0, 0x000a3de29c31e831, 0x0004699fe7072908, 0x000952e2c563ddbf, 0x000e5d6b0b57ac00, 0x000c4728203a767f, 0x000d56e858fdf3a6, 0x00000000000a5213}}, {{0x000b5ed7b705b7ba, 0x0002631796c22d0c, 0x00099ed65d60e408, 0x000cb716cb0c301b, 0x0007d1702ca94ff0, 0x000a02a90dd0cdbd, 0x000625470a26c8e1, 0x00000000000d7054}, {0x000218ab60af89bd, 0x000e0fadc2e8673f, 0x0000890003c99982, 0x0005ebb2951a8fe7, 0x000364197a76042b, 0x0009c1b5de4af9d0, 0x0002b1dd2c6bb324, 0x00000000000f0193}}, }, { /* digit=18 [{1,2,3,..,}]*([2^72]*G) */ {{0x0004ea16a709d85d, 0x000329ded9b0ccd4, 0x0002e9bda4d583bd, 0x000aaf5393937290, 0x0002a438413e94f3, 0x0003c7de32213686, 0x000540449286da37, 0x0000000000029aa1}, {0x0001d592acb2cf64, 0x000ef1bd13e4055d, 0x0004681cce9d2c6b, 0x000558f6bcd0cb2e, 0x000e9e610369d43b, 0x0006e0651f5757c0, 0x0000aa15c80b23c1, 0x0000000000000182}}, {{0x0004d40f93bd737d, 0x0008c10a8aabc8f9, 0x000d5b1177a72237, 0x000df1a076945a2e, 0x000c03861f02a009, 0x000866a3cf869152, 0x000cbbc405226e9f, 0x000000000008b41e}, {0x000cb1b314f36d3a, 0x000bab5c9ed101e9, 0x0005d83bc9ae2498, 0x000f22e57589279a, 0x000d7fe2d6aa1a9e, 0x00073dbfa83ef607, 0x000066f2da845434, 0x0000000000057879}}, {{0x000f91047abd3166, 0x000593df98ea92d5, 0x0002ec06cefe6ff8, 0x000d1b5ea6d69771, 0x00097e25ffbcc9cb, 0x000a6280e3f9f231, 0x000713bca8e0567d, 0x0000000000035cda}, {0x000fe70b79caf906, 0x0003946ef321cfa3, 0x000b4a657c54ec43, 0x0003b4b51de40452, 0x000cccd9ba8d37b7, 0x000f7045b5bccf3c, 0x000dcca2ca080dd0, 0x0000000000068cf4}}, {{0x000d265e2cd7626e, 0x0007e3499b44b9a9, 0x000ad7706fd7669e, 0x0000406c1f517d80, 0x000b82a174e83014, 0x0002c9b3ad4b3c8e, 0x0006f4c8835b13af, 0x0000000000044371}, {0x000fa90f05b33562, 0x000c2336c4f4b966, 0x000385e7d9f805d4, 0x000a2dc828c34d3a, 0x000c34d0d1f76ffb, 0x000a4fbce257a345, 0x00049fbc1eff056c, 0x0000000000007683}}, {{0x000db1540add72ad, 0x0009e5ebdc79cc93, 0x000baaf845cf7653, 0x000efe79c8b7f7df, 0x000ac469aa5793f6, 0x00033c455b2f1e40, 0x00012a882f0e9434, 0x00000000000aea07}, {0x00030f4a7dec8786, 0x000e9b13578c31bc, 0x0001af154c9f03fd, 0x000a2d854e09133c, 0x000cc6ad853283ac, 0x00004f75cae03943, 0x000c37ce0a619171, 0x00000000000f9838}}, {{0x0004bc7eb2d5ec5c, 0x0007e9db114e2be8, 0x000c421a1f0f05da, 0x000016bd2f3080f0, 0x000fb9b7203704df, 0x0004fe2ab0cb3f7c, 0x000ec1adb877c781, 0x0000000000037761}, {0x00081bf9c70c3c38, 0x0003cb5d6068d8ec, 0x0006b75a387ed168, 0x000aa5457d36d422, 0x0007423cc8cb39b4, 0x000a6566dec1de46, 0x000f55280e02dafd, 0x000000000003ca55}}, {{0x000e1cebdad8aedb, 0x0006b340d77c218d, 0x000b7391085bcda5, 0x0005b028b74d32db, 0x000a3cc1117e3e91, 0x0006c5939ae7101c, 0x000caa3c36152b52, 0x00000000000d3ec0}, {0x0001039f162ada74, 0x0004534de058e1ef, 0x0005d23a486e5201, 0x00030efc214ac0e4, 0x000cc7100acb27c0, 0x0009097b72a216d1, 0x000aaf3b73004330, 0x000000000007afd8}}, {{0x000af1b588df6219, 0x0003a5d7afe99881, 0x000b20bd69a8d3f2, 0x000067dc65234936, 0x000527557f5de39a, 0x0000e9f9d3458527, 0x0002d8756b8d8693, 0x00000000000040d5}, {0x0003845ac0bf2beb, 0x000a9606eb60a92a, 0x000238ad785ef768, 0x0005748e068d2949, 0x00022fce158da621, 0x000183c8f73fbdca, 0x000c989cfee07dcb, 0x00000000000a5e03}}, }, { /* digit=19 [{1,2,3,..,}]*([2^76]*G) */ {{0x0000e52cf2e9b4ad, 0x0003f86230933fe6, 0x000fe37b1c8aab75, 0x00086ba6f595ed40, 0x000de2284a5801e1, 0x0009e5e25d3291c3, 0x000f5303dee2311b, 0x0000000000015cc9}, {0x000f15883981ad15, 0x000444fba15675de, 0x0008ff144b8a465b, 0x0001eb92532d015f, 0x00084e7455de8690, 0x000f811c94396fd7, 0x000b372fbcea8fbc, 0x00000000000ae952}}, {{0x0007195bc501819f, 0x000f06bd2c54c87b, 0x000c8e0d99fb53f8, 0x0002654e3eee748a, 0x00039598d90727f5, 0x000cb371256f2058, 0x000c5b5f91c2d027, 0x00000000000a3e33}, {0x0002b15fc69c25d9, 0x0003e248490a9884, 0x000516ef1dee14b6, 0x0008b3d74f7d38ca, 0x00002fb602142013, 0x000033d4eae791f6, 0x000f176b4fb300bd, 0x00000000000bdfd1}}, {{0x000558e7c27dd125, 0x0004d9bd2b68cfc0, 0x0001783c86b4626f, 0x000f35989586da1d, 0x000afd0944ca67e7, 0x000569b5abc04c8a, 0x00046eb8db5424f0, 0x000000000000cc55}, {0x0008ec9be17ec8dc, 0x0009e8f0ef9decbe, 0x000cdc094579a394, 0x000eb644e7329b8f, 0x0007e6896b042ec1, 0x00018b6bf3e0e7f3, 0x000fa6ad2bff11c1, 0x0000000000040f93}}, {{0x000fa586c442030a, 0x000a30c3d2055f9d, 0x000061ff065411bd, 0x000a98b1fbf56cae, 0x000f396e31cd1b68, 0x00082c03b56fd85f, 0x000917d2ca584443, 0x000000000007d3ef}, {0x000572f96fe58801, 0x000c74129a730d28, 0x000ce4a000ce9071, 0x0004180653f3b241, 0x00049ee066bd9e85, 0x0002ea5fee65a1a1, 0x000e2e3420084e36, 0x00000000000c7911}}, {{0x00079bb68a21bf45, 0x000b04c3f4f487b8, 0x000f5bdc807ffd5c, 0x0009bad1844be875, 0x000e272afc140fbd, 0x00040a7386b3b80e, 0x000a37d727b0b6aa, 0x000000000004d809}, {0x0001886f07e4e9c3, 0x0004c09fb0640689, 0x000e568c8f4da447, 0x000ff8ad73a211ba, 0x0001d9a6b97da7e5, 0x0009e8f56ccdbf62, 0x000a0938448e2cc8, 0x000000000002126d}}, {{0x000bfb3f1befeb61, 0x0004c43f0ae67505, 0x0007b68cdb6c3beb, 0x0006c25dbb4492ec, 0x000884bff97fd5be, 0x0002da2e27efc9ee, 0x000c3254fbd9d706, 0x00000000000c6d2a}, {0x000d04af3852eaac, 0x0003e14cf6dc0935, 0x0006b6f8f3aa240c, 0x0006543d9a16800c, 0x0009beb1e28dd056, 0x000e658339cc2ade, 0x000cb2cbfeb45038, 0x00000000000d0f5a}}, {{0x00014927529fad7a, 0x000714f10299a19b, 0x0007bc14eebc4178, 0x00018bc0cbede41f, 0x000e6b03ac7d024b, 0x0005213be7883c01, 0x000540a7b99e741c, 0x0000000000085a97}, {0x0007979358dabc76, 0x000060b6fe59caa3, 0x000a32d2efcf0218, 0x000969d6ad1891a4, 0x0003ee7761dccaa0, 0x000b12539c47afe1, 0x0005f4cae681fcdf, 0x0000000000002ea6}}, {{0x00033b53cfd1d032, 0x000865e930d64f49, 0x000e6882e13322aa, 0x0004f7efa08bd4a8, 0x0006a6e10f64cfac, 0x0007ac162277e845, 0x00068b41be306740, 0x0000000000052a9b}, {0x000cf81e872685ed, 0x000e28d8d216a150, 0x000406cac9d54222, 0x0004102c60d54c43, 0x000028815187ad9a, 0x0003b8e59b09420f, 0x000ba1881179c60b, 0x000000000005b09a}}, }, { /* digit=20 [{1,2,3,..,}]*([2^80]*G) */ {{0x0002bb0ebd1ffa8d, 0x0000c22313ded9b3, 0x000c76c37673c0ae, 0x000eeaea76ec3812, 0x00060275ad3643d6, 0x000095bdaa165513, 0x0004b0e5c1b65adf, 0x00000000000367c4}, {0x000f3876ae1976b5, 0x0007de2b419c1bd2, 0x0005d5344cebbb0b, 0x000e51fa2baff060, 0x00006269b5d0b5fb, 0x000e8d667a0594d7, 0x0006e70b07b70523, 0x0000000000063e01}}, {{0x00082243f0134f99, 0x000d9022aa09c335, 0x0001e1b9a8966dc5, 0x00044c5b38b417ba, 0x000b436451ec3173, 0x000b1c87629a74cd, 0x000ffdd898eb6ca8, 0x00000000000b74ee}, {0x000187e3675bea14, 0x000410d9eab63bb0, 0x000dd59e68360fb6, 0x00094ce14dbff2ff, 0x00092706528037c8, 0x00029a0cd3704d34, 0x000c4f9ee435d8ba, 0x0000000000009c11}}, {{0x000414827bc8962c, 0x000552fde4893802, 0x00000bdd0aabfbb8, 0x0008a5b09456ed5c, 0x000925797c6c157b, 0x000c14c0673606a7, 0x0001caa9d0f47c33, 0x00000000000faf97}, {0x00082453cb3879aa, 0x000ec6e763c509a5, 0x0006f45dc5dfe238, 0x0007ecbc49e9efce, 0x0007b38f2b59d95b, 0x000c397db0c31792, 0x000bc797912b53b3, 0x0000000000045c7a}}, {{0x0002600fe807b0d9, 0x000578b3269a1894, 0x000cd6a11a8caa23, 0x000c714e428865d4, 0x000ffdaba094bc5a, 0x000d657f2531dd17, 0x000bbf86d2405718, 0x000000000002f99d}, {0x00063a9cad22b4ec, 0x000d1c428a80ebb2, 0x000111bbf67dd9f1, 0x000691922a5d2566, 0x000318a18586a752, 0x000f633b3bfe6392, 0x00029828a0c772fc, 0x000000000003f3c5}}, {{0x000cdc4baa08bf36, 0x00052cd81bdce7a2, 0x0009dbe6198554f1, 0x000228bf8ebe39d1, 0x000eb2cdd8524cb0, 0x000e9b3af496a9dc, 0x000f8a0f115a1ad0, 0x00000000000d8eee}, {0x000de9efc567fd4a, 0x0009b5232a514417, 0x000762e720496fa2, 0x00018b08994b4e8e, 0x000809097a52289d, 0x0004621d0b4e346a, 0x000ab8c641510f32, 0x0000000000095a41}}, {{0x000c5913c30a847d, 0x00004c8c9b0adae6, 0x000c6088d1ec2259, 0x0007946e62c508f6, 0x0006e9fe2321b03b, 0x000c1d1366042592, 0x000c9c73b10bba80, 0x000000000009d218}, {0x000e72b1483512ee, 0x0006d6ed0c8eed83, 0x0009abfdad8b62ec, 0x000096ab9e96167e, 0x000cc473e3773078, 0x0003a3bc8b28f0e6, 0x000796b44e499568, 0x00000000000d3523}}, {{0x000ec81c53fdc5cd, 0x00095261578c7817, 0x000dba0eec8c348b, 0x00066b414c803900, 0x0005faa7cc399932, 0x0009b7e27bacad75, 0x000533418c4defd6, 0x00000000000ae751}, {0x000b26e534337f55, 0x000f36f3bd3298fb, 0x000bd59fe7197151, 0x0004f73dc4c54ecd, 0x000d44d3d74eb716, 0x0009ea511ca66290, 0x000c49f77c62424c, 0x000000000001f714}}, {{0x000343bd88e025df, 0x000b893a62e7c716, 0x0003b75e6fa4a448, 0x0003cbb10cc95456, 0x00062f37154c265e, 0x000f2e08b28cceb0, 0x0000916b79b0713b, 0x000000000003ab39}, {0x00046ae52480b7d8, 0x000a750a8d04cede, 0x000f3c798fdbfa72, 0x000336ac21cc62f0, 0x00036fc004503db4, 0x0004b2d954747f0a, 0x0007a7067cbf1c54, 0x00000000000fd2be}}, }, { /* digit=21 [{1,2,3,..,}]*([2^84]*G) */ {{0x000f8f632d3f21bf, 0x000880233e423a7e, 0x000fc3a5113e93d2, 0x0009cef6349e35be, 0x0003ded2ec542ca0, 0x000dded3d3b70afc, 0x000ee0c813474d52, 0x0000000000012f00}, {0x0002c304534f52c2, 0x00002a0908f763fa, 0x000cccb3aba1eb57, 0x00010c134b6a8e10, 0x00056e7c163e84ad, 0x00057e0c36f37fd9, 0x0001a27caae8c8d0, 0x0000000000055372}}, {{0x00086fa76217d20b, 0x00015a354c1de108, 0x000a55c4648be905, 0x00010999d532bbe4, 0x000f520117516766, 0x00059e35eb7c2f4c, 0x000b7b6945d34ff6, 0x00000000000a1303}, {0x000495f21c8085bb, 0x00028a200ddba08f, 0x0003caf84b1e53dc, 0x000445faa82b46fc, 0x000cfccedc1b3018, 0x00053e29fc3e6a3a, 0x000547e86ae87033, 0x00000000000fd7e8}}, {{0x000683184a93e477, 0x000a4728c8e14128, 0x0003d8bece755c7e, 0x000c2da4796df734, 0x000e00a55efc3016, 0x0006b1cb8f6d79e4, 0x0005a94fced26952, 0x0000000000091f16}, {0x00031165825c7f6e, 0x000cf528b857275f, 0x000d8cb6dce0ced4, 0x0003520e07bb990b, 0x000f4ea8ae6b4f90, 0x000b735bb07ddb97, 0x000d4a29c01e70b3, 0x000000000005000d}}, {{0x000f814f4e7d6929, 0x0005e306b63e3665, 0x00098d89bb61e0d2, 0x00068898bdeddea9, 0x000d67a329ac36bb, 0x00092ccce9331655, 0x0009b414c7fe26ba, 0x00000000000be051}, {0x00042824d37928be, 0x000830dc39dbc42d, 0x00083d595f84e0c5, 0x0008818fa8682bba, 0x000db60aad97c7f7, 0x0002c64cc43396ea, 0x00043e751784d7ff, 0x00000000000866af}}, {{0x0007b94e1c1e3bf9, 0x000a53742b61de85, 0x0004d0debb63955e, 0x0006787abce34016, 0x000ea4cb41b4f52c, 0x000ca817e4749711, 0x0000487ce0dfb03f, 0x0000000000096e85}, {0x000c4c6d7efe5c7c, 0x000b6cd65250dc1f, 0x0007ec2aec96d815, 0x0003cb2b4dd561a2, 0x000abb5379f57352, 0x000a847ba15ba773, 0x0002decc5e62d6c0, 0x0000000000004d85}}, {{0x0003450b4a8e849f, 0x00036f0a69e68100, 0x000d9356a0504fb6, 0x0003ab7cd14af1d4, 0x000d558d555d773a, 0x000e63dd6c0b88ed, 0x000db3eb12d197d2, 0x00000000000bcd9c}, {0x000ed15d1fefd8b7, 0x000fa06432985766, 0x00052d6c3d3a4a47, 0x000f6164171b9bc6, 0x0009bbfcf90abd28, 0x00036084d3778163, 0x000a751f93898f3a, 0x00000000000dd00c}}, {{0x0000e82da9d478f7, 0x000ae3b8d8e48b47, 0x0000534e09405090, 0x000430c2aad8c684, 0x0006b82c16731d72, 0x0000fb41de8c5d50, 0x00034f989978868a, 0x000000000000f812}, {0x000d9518cbfe70fc, 0x000f1a0c941ce78c, 0x000c323a8cf0aba1, 0x000e296101f89af8, 0x0003ca6a3227aa7d, 0x00064ec0c4cadd8e, 0x000db43b4db51f27, 0x0000000000009256}}, {{0x000e28a122d0f32b, 0x00022b9207dbc085, 0x000dce5b9cc6b932, 0x0004e5534ba150b8, 0x0001dfec99724992, 0x0006f870d2935ebf, 0x00085c34bf5e94b7, 0x000000000004c203}, {0x000bdbb9ed40b2b9, 0x000c3c78ac1719f8, 0x0008866adbfa0f7d, 0x0007ee4cfb4b8bb6, 0x0002cd8724b676c6, 0x0000bc1efecfaefb, 0x0001b5e9bc3d6734, 0x00000000000ca554}}, }, { /* digit=22 [{1,2,3,..,}]*([2^88]*G) */ {{0x0004ccdc054842bd, 0x000704f293478100, 0x0000ca74cad5c267, 0x000c94f64d55f6f2, 0x000d725c51251bf7, 0x000b6a0914489b57, 0x0000fa3aa4d43ab1, 0x00000000000cf7a6}, {0x0007fef943134dbd, 0x00038aa918a4ce7d, 0x000eee4d56ef907f, 0x00000a16812a03d0, 0x00070b0a1e4bed0e, 0x00028386bb09acf2, 0x000321c73a41f7ac, 0x00000000000f4cd1}}, {{0x000b2804db21ede5, 0x000fd10a53b8f9a2, 0x00080087f23a6e5f, 0x000513fabef2b974, 0x000cd3f802fd740d, 0x0000627afff6cc47, 0x0002dc1be6825beb, 0x000000000005886c}, {0x0002ebc44567c313, 0x000afb6cfb2c6b07, 0x000e1dddbc404a5d, 0x00016f53a5a485ba, 0x0002e7b2223e7a1e, 0x000a13a9b16b60b9, 0x0001a2332f33d836, 0x00000000000876cd}}, {{0x000bcac1cf1b2eda, 0x00095802f495c1f2, 0x000e55ffc912d44b, 0x000b294e9b3f0f6d, 0x000033cbdcd1eaf3, 0x00083fce582cc760, 0x0004cc1a5642278e, 0x00000000000ffa0e}, {0x000dada72c71a95f, 0x000ed7d93e9766ea, 0x00015d2d9c24e57f, 0x000dd79eafe5f361, 0x0000fcaafabbcb53, 0x000053efecbbed8f, 0x000b7a570472705f, 0x000000000001ebfe}}, {{0x0005f3669cd44c3c, 0x00025a896d28dae1, 0x0002e7c6820a84bb, 0x000fe8c06fb15cd6, 0x00061cdffdad1bba, 0x000119b3a2daab29, 0x0005a3984defc8e1, 0x00000000000de2a2}, {0x0000f914a19c745f, 0x000b3a7f54ecdb35, 0x00041f75def22ce4, 0x0000efc6a3b94437, 0x00076785163b6913, 0x0002b1d0a5d17f12, 0x00093cc019911b17, 0x000000000007e3e0}}, {{0x00049fc81e69d5e0, 0x00085d307d4279b4, 0x00039a33441f2443, 0x00078371531d6263, 0x0008b42639ecfff7, 0x00099fb76fdd61b0, 0x000f0eca9462e7be, 0x000000000007c3f2}, {0x0008f656f3641bfa, 0x000f85c07066bcc1, 0x0008bd883c4e6617, 0x0001387d93ff4937, 0x000b864eed19b6d3, 0x000fad6382fd7d67, 0x000fe667b707ff5a, 0x00000000000d0206}}, {{0x000bb568a2a2f3e3, 0x000a9235455295a9, 0x0008072539522964, 0x0006d10c75720aab, 0x0009f6a0df88ac83, 0x0005a9c96ea2c538, 0x0007bedfbf31519e, 0x000000000008cad4}, {0x000d6b001091ce3f, 0x00036dbd5de982e7, 0x000e935fa43e76d4, 0x000fef6324ba9235, 0x000e8f14a2f5a2bd, 0x000880ade8b0f981, 0x000d4a590de1c45f, 0x00000000000107f3}}, {{0x00091e8b5ebad75d, 0x00009b03d47621b9, 0x000da50c79b05bb6, 0x000ca72548723c56, 0x0007c944e3849da9, 0x000947973a12e40d, 0x0001ea403dbcf2cc, 0x00000000000c6ef4}, {0x000f1cf0966fef48, 0x000d74ccc2856b9a, 0x00011bbeae1e30d2, 0x0007f7e43ee1576e, 0x000a0a894961701a, 0x000396f6e7f061c1, 0x000ca956059fb88f, 0x000000000001a91f}}, {{0x0000a27b9e3336b7, 0x0000be185bdc20d5, 0x0008a8bb1575f81e, 0x0003397c3fe5695a, 0x000f61f6a04f1f6f, 0x00090a92b6c9f3a5, 0x0004543c0f9d4bb3, 0x000000000004793b}, {0x00055e696b3d9202, 0x000d991ad0c33a93, 0x000c4d967cf46a4f, 0x000d90565d53c83a, 0x00034176007dfa24, 0x000d1623cd63e583, 0x000345741089fd2c, 0x000000000002685d}}, }, { /* digit=23 [{1,2,3,..,}]*([2^92]*G) */ {{0x000883b867d2fbb5, 0x000271d51015761f, 0x000afd0328ae7e6f, 0x0007e2fc6dde9e2b, 0x000937d5bb1f2ea0, 0x000cc6e28ceed9ad, 0x000fc43121994b98, 0x0000000000067ad8}, {0x000d53a60b81c5b7, 0x000ca34707fb3d11, 0x0005e1e4ff2b5765, 0x0009b8d81ef6cb57, 0x000b1223a9a1fe93, 0x00074cf375c51e8a, 0x0008e18f6d7993db, 0x0000000000097280}}, {{0x00067952d0358e02, 0x0005b0db3322730d, 0x000098edfd5f000a, 0x00085380e8a38fae, 0x0005769360d86efd, 0x000f27ef5c1812ea, 0x0002e8505723dc76, 0x00000000000f35af}, {0x000764970d5cb557, 0x000849f7bb7fecc3, 0x00052323da5066c3, 0x0007549773eaf7f9, 0x000489d51bda0118, 0x0000ccde605bbbba, 0x00087d52cabb0664, 0x00000000000e7ff3}}, {{0x000fa071b96c7c7e, 0x0009c70187dfb0a2, 0x0000f19decc5bd43, 0x0008b816a6c0d616, 0x000d6a27e97b3018, 0x000a389aaeaeda67, 0x0002734a5192826b, 0x00000000000a2bf1}, {0x000832bf68c7b455, 0x0000c8ff10656bdb, 0x0008bc56c7023546, 0x000a3e11dc7aed54, 0x000b38853d61e34b, 0x000cbf658c457048, 0x000edde89825db1c, 0x000000000006b255}}, {{0x00067336ad6a8789, 0x000d0c377b3730db, 0x00063e31dca6f13f, 0x000f2adf39b68951, 0x0006bd6da22ed9c2, 0x00009678e1bbff10, 0x000e783f7e5b8e7e, 0x000000000007ed3e}, {0x000a0e3ab40df97f, 0x00071689e6b30fb8, 0x0000b670f8712d68, 0x000277edda78c55a, 0x000cefb65cb717d3, 0x000a30f0ce686cac, 0x00071e758aa1ab19, 0x00000000000b11f0}}, {{0x0007d3d2024290f7, 0x0000c0bef2d25159, 0x000b908d7c494e4d, 0x00017cedd4af7aeb, 0x000bc8e88ca42c24, 0x00020d15452b5b3b, 0x000d4bc00328c44f, 0x0000000000030af5}, {0x00053687c2073cc9, 0x000dee8bacbeb2cf, 0x000bf613b57931f9, 0x0001da61d9e70314, 0x000c0e70a331b67d, 0x000e325772ddefcb, 0x0009797d09bc6d61, 0x000000000005b52e}}, {{0x0000d7a5438e4dd1, 0x000b5d40f36e5e3e, 0x000702a395a7941d, 0x00094d7cc51dbaf1, 0x000f0edf8bf9e340, 0x000b5e16520f93f0, 0x0003a8534b75aa23, 0x00000000000dc1b7}, {0x000196b771cc1d7e, 0x000b09dd48c40ca1, 0x000664851f0b3766, 0x000f8a2a9ffa0db3, 0x0004d94ed9bd4212, 0x00069cb198d5236c, 0x000dfc81bec489f1, 0x000000000006104e}}, {{0x00076550d0174653, 0x0008d9cb21b56311, 0x000fe59ad5e35eee, 0x000a67100d7b34c9, 0x0001a6c1b0c3e3f3, 0x0003c3e31d4bcb3d, 0x000be86ebd26fb9f, 0x000000000002dc79}, {0x000582f4b4dfea09, 0x0002ae7cf9a0a1f3, 0x000c37b50dcbdab8, 0x000320e69e1f08bd, 0x000b946f83d78b0e, 0x000a399ad2a8caf9, 0x0000866daff0ba98, 0x0000000000038ed6}}, {{0x000af81ab2009a09, 0x000fc16f3708ae33, 0x000f381b02290f16, 0x00015b227bb71a8b, 0x0004162f8b5597a6, 0x0001e3fb9a8b9a86, 0x000ff680ee8362d9, 0x00000000000f83a4}, {0x0005ffc830c362b9, 0x0009507a7873a90a, 0x0008c2637b53ccc0, 0x000683d860d60ba4, 0x00071f87d32a427f, 0x00050319dea99592, 0x0009ceb2ac69faa0, 0x00000000000d2d0b}}, }, { /* digit=24 [{1,2,3,..,}]*([2^96]*G) */ {{0x000fbfb66a502f43, 0x0008324480c57881, 0x000d6a55d7a45e41, 0x00002c3273e2bc82, 0x00053ef1ed4c7350, 0x0004948e88c42e9c, 0x000632028babf67f, 0x000000000008a978}, {0x0008edce917c4930, 0x0001bf5f13a4625c, 0x000e9dd4dc6a263a, 0x0006bcc37232768a, 0x0001576e8c1830f3, 0x000bcb766c5317b3, 0x0004dcef1d57a69b, 0x00000000000b3e3d}}, {{0x000aa97e11eb2f75, 0x0004f53ebbaaea28, 0x000f59d2921161ee, 0x000f25d340986b44, 0x000e3365312a3c15, 0x000641f96c5925d2, 0x0008e4c35d3ee251, 0x0000000000098412}, {0x00032040e2f19c59, 0x00029b41a21a75a1, 0x0005c4225a472860, 0x000f4c0faf5663dd, 0x000a0a62c9dc4ffc, 0x0002d60c5889d285, 0x000be50908665acb, 0x000000000000a131}}, {{0x0006f87a21caa381, 0x000a6318feb4c006, 0x000ed4b6b2c3b939, 0x000786d5b2386621, 0x0005a722c5911e4a, 0x00006cb0188e0430, 0x00036438eb062af4, 0x00000000000e7216}, {0x0003e9f2fb9e0c73, 0x00093450c1d28f54, 0x00023904331c181f, 0x000a53a6f6c06813, 0x000a25eac032fe46, 0x000c497224553199, 0x000a2941fa659aff, 0x00000000000bbcb7}}, {{0x000a3dcccc791733, 0x000a8c0de60f43c9, 0x0004454fef6e3630, 0x0002aa8e734e2e0a, 0x0003ef773db6f412, 0x0002d71c508f40f6, 0x0008250a7e9484ce, 0x0000000000078a3f}, {0x0005a99063a64539, 0x000ef0cac7a5b50d, 0x000064e61e079dfa, 0x0009a90d3e181458, 0x000a0aadf689ecf1, 0x000f0acf70d1b062, 0x0002b942299f1ff3, 0x000000000005ac25}}, {{0x000b4c356075ce0d, 0x000a8a4bfe150fb5, 0x000907dbaf6f1c40, 0x0008260a0ee708f9, 0x0004abc9d5f541e2, 0x000aae99eff4fdff, 0x0004d96ed92241ff, 0x00000000000c04fe}, {0x000731763369357f, 0x000a8f10a173e2a4, 0x00065723921ac826, 0x000823f8ed02e85d, 0x00042e522dc1d2a0, 0x000c939fdffa78cf, 0x000bba07041e4600, 0x000000000003a9a8}}, {{0x0008012ba5de4e7d, 0x000c7a1fc20f7144, 0x000540a292e6e434, 0x00081c28e2e8e16b, 0x000a4c4562342e55, 0x000e31ad4912c80f, 0x0008117fd61fb9e9, 0x000000000001c19e}, {0x000de815bbe3ce38, 0x0003b6a7ab2cb6d7, 0x000aeaa95e1796a8, 0x0006a85ab06af4e7, 0x00044866378d33f7, 0x000826f8cda387e5, 0x000cb6bb71deb856, 0x00000000000eb64e}}, {{0x000d7e72d8af89da, 0x000ba0e93593424a, 0x000584230569d130, 0x0003dba8e15d8645, 0x0001cab64644ab77, 0x000fff0619cea4a5, 0x0006a4516754d72e, 0x00000000000cd3a3}, {0x000ee6af7eb6909f, 0x000c6c7d352abc75, 0x00007221eaa0649d, 0x000ed979199938f5, 0x000acd6f34958a8a, 0x0005f93eeeb06789, 0x000851c51d776677, 0x000000000000a8af}}, {{0x000b089742823cef, 0x000c544bfd166199, 0x0008c58b08cf9fc3, 0x000cf81c39366838, 0x00068b08680fe50f, 0x00032aab0c9b4eb0, 0x000ddaf90882c528, 0x00000000000ecbf5}, {0x0004bc1447794cdc, 0x000f8fd4d51c6fd3, 0x000cc355ce034b68, 0x00053dbfb187c34f, 0x0006f8ed037fb729, 0x0007bad45166f7f2, 0x000808d2b1077a09, 0x00000000000790dd}}, }, { /* digit=25 [{1,2,3,..,}]*([2^100]*G) */ {{0x000273ed4a6f3c1a, 0x00092a05c751c876, 0x000bdb5d554c8320, 0x000e26cf4c98fee4, 0x0009e7b3a7c79c56, 0x000cc16466084f8b, 0x0000bca0b042f6de, 0x00000000000fbf3a}, {0x000078eb34f9801e, 0x0006694524c2c1cd, 0x0008ad2d5e6f66b7, 0x0002d6e7ce1f9f62, 0x0007fc0c34fa1879, 0x0000a16938ebc2fd, 0x000019032a9f4178, 0x0000000000056a60}}, {{0x00009be19d72cca6, 0x0009ea4b957d1c55, 0x000c88712c99979c, 0x0005e80a271d9e14, 0x00044b9367e51157, 0x00079779f0fff68d, 0x000f68f55ba67322, 0x00000000000d4d68}, {0x000ebae305d14369, 0x000b401474ab1533, 0x0007e0884a0d1ea6, 0x0003a8336111d25d, 0x000fab531cef6390, 0x0002ed86737342a5, 0x0007e1d3c93fe770, 0x000000000006279f}}, {{0x000ed609fa3c6148, 0x000beb398290bf69, 0x000b5366c9b47f2a, 0x000aa2956560b89f, 0x000c50e6647b3e71, 0x000be42da80817aa, 0x000a4e35c833ada0, 0x00000000000f1bab}, {0x000a4dc6e615148d, 0x0009ac57be644e77, 0x000de3f8f9ac6cc1, 0x00077310defd9095, 0x000e899cba568300, 0x000effb5a92fe9bc, 0x0004bf48450ec4bc, 0x00000000000f2f5f}}, {{0x000e1a6a67c12c1b, 0x000e7dccf68bc63e, 0x000af5107f8ecb57, 0x000e199254dd3e41, 0x0006ddce5c84e43a, 0x0000b4258e8526e2, 0x0004c452bad815ea, 0x0000000000009457}, {0x000fc838b5157d7f, 0x000e1a5362fcad0f, 0x0003a5c9b577c868, 0x00012b5eeffc2cdf, 0x000b14de4e5b0f93, 0x000233fa55475657, 0x000ec2746e67d4f0, 0x0000000000035471}}, {{0x000afd6c233d63fa, 0x0009cf55edabb6d7, 0x000b353b7e2a9194, 0x000822b9bf171614, 0x0003afe808dcf53e, 0x000272f554a5b3b9, 0x0009a1590bbbded7, 0x00000000000eaea7}, {0x000101d093edb837, 0x000b5d7042bea6a3, 0x0006a766d7a462c5, 0x000e69031078aa66, 0x00087e37bc8bd8d1, 0x0000089759e837f1, 0x0008679558ff4f85, 0x00000000000421fe}}, {{0x00076617121c3ac1, 0x000a13503d9370d0, 0x0006e1d369d53e18, 0x00001ef5b52e0f07, 0x0002f955b5fa67f1, 0x0000e0569b6b5b4c, 0x0003efb5f03d5388, 0x00000000000c9939}, {0x000c81fd72768469, 0x000a690755bd5e4b, 0x000324dbfd474da1, 0x000fd519e9ce792e, 0x000396ccfa14326f, 0x0004a22de1b772d7, 0x000342652710f487, 0x00000000000db210}}, {{0x0008597293bd01e8, 0x000dfaa6489def01, 0x000dc630321a7c29, 0x00043a95fa2efed7, 0x0003720e1a8c4d89, 0x000a4f8a3c9baae5, 0x00006bc055444b95, 0x00000000000a7c12}, {0x00017016dee8b7c9, 0x000dfd97765b5926, 0x00050b911df827d2, 0x000c35af1503b16b, 0x000fa9fa21f8115c, 0x000fed1f11dd5359, 0x000679197c32996d, 0x00000000000f77f2}}, {{0x0004d7575fc73ce2, 0x000ce58d6998db75, 0x000d11d5d661c62a, 0x0002a0165739fcf5, 0x000822f7a073420b, 0x000042f005c5db30, 0x0003d9016c547805, 0x00000000000a1241}, {0x0008aac8eaa9ff4f, 0x000fe8ceb2d6ffe8, 0x000f806ab6efe1ae, 0x000d012339c146c9, 0x000628ac05552638, 0x000d46e6302fbb7b, 0x00088e7fcb0c8162, 0x00000000000066d0}}, }, { /* digit=26 [{1,2,3,..,}]*([2^104]*G) */ {{0x00029831f2b8ed10, 0x0004917e3d0b77e8, 0x00062b9d59b96ed5, 0x0000261d0bb1849e, 0x000ec71a3bbef8ef, 0x0002a88ae9b804ce, 0x000b9e00b7d17154, 0x00000000000e9097}, {0x0001f74d24b8094d, 0x0000cdbad9f12075, 0x000917cb364517bb, 0x000834fb83debf54, 0x000d637e449ba8a4, 0x000b82664c3ee226, 0x0000e8e3070d93ca, 0x00000000000b3732}}, {{0x000cd133b578c566, 0x0004bb506b7b86f8, 0x000a189da5b723c8, 0x00029ad3789281ee, 0x0001f9af456164b7, 0x000f9186069ae8f8, 0x0000fb007befe156, 0x00000000000edc25}, {0x0003b5e8dc3a9219, 0x000ab1c16d7598b7, 0x0000fdec987e0e87, 0x0007da936881f89e, 0x000103a5b1ea5dc9, 0x000153a0faddb603, 0x000ee27eb515b13e, 0x000000000002b4a1}}, {{0x000bcceb06f924be, 0x000d4e6b739c7071, 0x0004a4fc7ff778b8, 0x0003acc1b4b45493, 0x0008f6bad44a14e3, 0x000020972d6704b2, 0x00033543cd7e5ddf, 0x00000000000e0d6c}, {0x0008ad0a64850139, 0x000b67d395c3ef6a, 0x00040e40560ce9c8, 0x0009f21efe4a5757, 0x0004f55ea727b626, 0x000450c823f97b37, 0x0005d5b689b4de42, 0x000000000004f5ae}}, {{0x000bd2a72ae0f683, 0x000d7e7365f9e264, 0x0009dec60e7c539c, 0x00089ac8e611fc3c, 0x0005699c227dbfb3, 0x000f2ef17ce778fd, 0x000ed4dc1f47b63f, 0x0000000000002672}, {0x00013b4caed73e7f, 0x000a551c63805fa1, 0x0002b72b6fe7e133, 0x0003d13e00e12a38, 0x0000bf8df325375b, 0x000f5f21a91f9f75, 0x000584f1ea0e421d, 0x0000000000032c60}}, {{0x000c6a3d385d54a6, 0x000a26d720050d7c, 0x00008151ff431078, 0x000aee6f1c89ce3d, 0x000b57b2b79d5d1d, 0x000c7ce823f7644b, 0x000b0bb1063f92fc, 0x00000000000c15a9}, {0x0004b892e4ed0e8c, 0x0007865661a5290d, 0x000a266171fca5c3, 0x000dc5d42ecede66, 0x000c8eb0689e0661, 0x000d7ff77be586ca, 0x000c3bc86641a02d, 0x00000000000b9ef4}}, {{0x0006b862a25bd60b, 0x0005903b07fb53e1, 0x0000603f2bb26df9, 0x0006449356376454, 0x0002a55bcadf272e, 0x00071c6af2b6ad1c, 0x00080686c527765c, 0x00000000000c1678}, {0x000fb64422cb7cb4, 0x000660cae829453e, 0x000b68619a56abb9, 0x000f8337513dfb65, 0x000e1b351dda504d, 0x000af7cd04260ee8, 0x0000fda473c5d9db, 0x0000000000071e39}}, {{0x000c98e3f8d5e928, 0x000c217544e9789d, 0x00047053e368c072, 0x0000e3937af8cf8c, 0x0009a2f308e2e146, 0x0005060e98b4aa2f, 0x000a7dafa2bdbc3a, 0x00000000000f84dd}, {0x0004961384232a8d, 0x000d53b256b55aeb, 0x00063be03fa9b44c, 0x00010d13c8e52f06, 0x000b38865772c405, 0x000416f1062c1542, 0x000eb54755de7ebf, 0x0000000000097aa2}}, {{0x0009115b2961da7d, 0x000f01d9aa9f9fd6, 0x0004c642e6501980, 0x000d6a17f167b479, 0x00085bd9153d7ebe, 0x000682ba6324c13f, 0x0006e2e9ea5b734c, 0x000000000007e3ff}, {0x000ac4814edd792c, 0x000361ed2b04fb2c, 0x0001100e4a13806f, 0x000a5d3d68b8ec70, 0x000d1c6ce0d2afce, 0x00019410c21dc058, 0x0005340043de75e7, 0x00000000000e15cf}}, }, { /* digit=27 [{1,2,3,..,}]*([2^108]*G) */ {{0x000e0e09fdbcad95, 0x0004ef7aaa73197d, 0x000fdf5aa02c7c2e, 0x00017372e0c286f0, 0x00025da3472da1a4, 0x00076f2a23b66850, 0x0007d4bc0d116b75, 0x00000000000a36a2}, {0x000b11735059e67b, 0x0001ecdb3f4744cf, 0x00033adc74dab02a, 0x00011b969d4f1723, 0x00066cca4ef7c70d, 0x000c6afdfdf96d13, 0x0004da570693db2f, 0x0000000000056750}}, {{0x00080567673bd755, 0x000df02c6b607d3c, 0x00025bebf3a2d95d, 0x000b01d4f57eb0c9, 0x0004d750e515af5a, 0x00089ad6859935b9, 0x000eff32721b408f, 0x00000000000a7e3c}, {0x0009a7a317218bf0, 0x00010bd462fd8d81, 0x000035ae54257b2d, 0x000da619263fa61b, 0x000eb6488eb34162, 0x0005680c42ed1f2d, 0x0007b0b0bd37a872, 0x0000000000029ec2}}, {{0x000d73368a1e2f2d, 0x00047170f8a745d8, 0x00056c4ca9228944, 0x000bd224b08921af, 0x000de6caca3a5f65, 0x000cb9d5b1017ae3, 0x00099b613f36b626, 0x00000000000ed19d}, {0x00092b03ebebeebf, 0x000c752c915a4d7d, 0x00088621f044eee8, 0x000f7c206a51a132, 0x00066e0197ce2cd7, 0x00071b04cfed60db, 0x000b134e5b2bb7d9, 0x000000000002f45a}}, {{0x0009fb6e89b64981, 0x00034fb09e755c21, 0x0005804661454c99, 0x0005b01cdb1f4f66, 0x0008f1dd1cf0451c, 0x000687e41b02f906, 0x000bd3d4765e7c0c, 0x00000000000d1967}, {0x000f135de5248a08, 0x000f406a0e4ec0b1, 0x000b70c2868ad046, 0x000d01ac651d8073, 0x00030618a96cc1e9, 0x0004ad8ce5e6ebd8, 0x00090f9ce1aacec5, 0x000000000009953f}}, {{0x000f6e431dc5b814, 0x00044fa4b66978a6, 0x00032f1c66e89ca4, 0x000ba60986c85001, 0x0004dae014e110aa, 0x000bc0e4649bdfff, 0x000d5fe2a810bd0a, 0x0000000000062d1d}, {0x0007dc411c936920, 0x0002c15d2f2c7072, 0x00075b1f6234ac4c, 0x000b6f94c545f5b7, 0x0002f99241e840c6, 0x0007082935875b6b, 0x000344fa3e88a9d6, 0x00000000000ad6d9}}, {{0x000edb2b4857e570, 0x000fba8d7901c33b, 0x000ae7d92e8b3979, 0x000d7c504e4bce1a, 0x000e5ab0696fb905, 0x000db9cd5dfbf9c4, 0x0000fe0f4e6e2ab6, 0x00000000000482e4}, {0x000aa1f98e714cdb, 0x000225ccd9b418dc, 0x00058c553b3cc2f6, 0x0000dbe59065754a, 0x000a461c1620cebe, 0x000e541a74d052d3, 0x0002d8396bac422f, 0x0000000000070bf3}}, {{0x000a0c1fea68e228, 0x0005003c88a847c6, 0x0008f73e5d2fc7c6, 0x0003d393870d90fd, 0x0004f2fdb976d90a, 0x000312a302fd78d1, 0x000f2f9472a6066a, 0x000000000003484a}, {0x000f5efbe46efdf7, 0x0008c7cf25950c82, 0x0006be05e61c118c, 0x0009379e563a2bde, 0x0004b46e93d85d47, 0x00037285ce87b50a, 0x0007e69128fc11f1, 0x000000000007c67d}}, {{0x0006a0e99182cb3e, 0x00059da2b072529a, 0x0000a5cae364c3e2, 0x000e35a5b132756b, 0x0004fadb6907c721, 0x00083f546e5695e8, 0x0008aebc5a3bf4c2, 0x00000000000dde12}, {0x000842d7630a9d87, 0x0000d179c7fa6028, 0x00016ae518569923, 0x00083bea16bad558, 0x000e9137ecd8af7e, 0x00030d1ab6f41231, 0x000ee8ac87543d8f, 0x00000000000b1ee0}}, }, { /* digit=28 [{1,2,3,..,}]*([2^112]*G) */ {{0x00021880433d0094, 0x000fe359cbfa01b1, 0x000ccfcddd1c5f17, 0x000e90f630cbcb5a, 0x00006ddbf2382fd5, 0x000f753e62b0f613, 0x0000165070970a3a, 0x0000000000041727}, {0x000724192d1373c9, 0x0003e2eb15b3b70b, 0x000786ed962decdc, 0x00074aee930a75c6, 0x0006849e77270d43, 0x0006a19ff3cd3604, 0x000c049ac3117e33, 0x00000000000433dd}}, {{0x000b49aee05ae3b9, 0x0005d985dcb4303d, 0x000d13447c8994a2, 0x0007f3055fbf1d6c, 0x000f43fcd98a4059, 0x000ec99cab6d166b, 0x0003705932570915, 0x00000000000c5bdd}, {0x00050b2df8b6890e, 0x000dac18f782613c, 0x000d7472d5468bfb, 0x000a89df478e56c7, 0x000864d290535d50, 0x000cf7e0e242c2f4, 0x000d40cda12c6161, 0x00000000000ac8d1}}, {{0x0001c7858f5f5373, 0x000027a9a9dd7275, 0x000baba450a60383, 0x000267b6726c3253, 0x000d7f841afb1550, 0x00004643012cfb2f, 0x0006cba41b19052f, 0x00000000000b7d78}, {0x0007d7e12176321a, 0x000667b61b39c512, 0x00091b7379479d0c, 0x000efb84a3489052, 0x000cf2e864b965d6, 0x00096cdb2f377862, 0x0000f63c94000dab, 0x000000000008efef}}, {{0x0001ea0f696fd259, 0x000ff8c558000585, 0x0007b878d3ed6d3e, 0x000d75ceb7a35cc0, 0x000cf0a93110acf0, 0x000c50c850fbdce4, 0x000d6f82b2d13a9c, 0x00000000000cef70}, {0x000ce46086dea462, 0x0001e1cc9be2dbe9, 0x00043757ada5e365, 0x000479f195a532b9, 0x000a1ab3605c52bd, 0x00024c1e0769fe6c, 0x000d7aba6a63e48a, 0x0000000000099da5}}, {{0x000ad5fa3c1cbaf9, 0x00066df2a6cec962, 0x0003dc76a0f4995b, 0x0007e4c0de8a6aa7, 0x0004be7b8f5d7c8a, 0x000da3e7e5c806b9, 0x0008e5ccca1c714f, 0x00000000000cff78}, {0x00056778e2279cec, 0x0006e17a081a8743, 0x0007133643f614b8, 0x00090549e4cfac8a, 0x00029d53a2000d7c, 0x000977a8b6fb74c6, 0x0007c465b9ed6d5f, 0x000000000000ba2e}}, {{0x000a6aa57649a837, 0x0000f8435e295b6f, 0x0009b668270d6cf9, 0x0006e6fece5cb161, 0x00095336f7ffe2fe, 0x0008ee2676f249b0, 0x00017b5801feb990, 0x00000000000fc8f2}, {0x00006b2a4f1b5cde, 0x00053fc1adc3e51d, 0x000e0bc8cae40bdd, 0x0005404cc1d9b726, 0x0001a1f2c5a44afb, 0x00008f19575cabd6, 0x000f492bd797e1cd, 0x00000000000cbea0}}, {{0x0008ce5f4471b983, 0x000d8e9759aa9a33, 0x0001c65f7f2a0258, 0x00059aa2c80bb617, 0x000230c9b328e49a, 0x0004ebffcdb89e21, 0x0008e4f42b9adb00, 0x0000000000047967}, {0x000c42c02e645b6d, 0x000f20dde5b0e690, 0x000d9a21c0cf9036, 0x0007a5cd8c8285c5, 0x00071d1562069f8d, 0x000e126bcd7cde59, 0x00060bdbe765d7a8, 0x00000000000e3f4e}}, {{0x000bcd16afac5b0a, 0x00041509abccab5b, 0x000ba67813ffa4bc, 0x00071bd640bc2f7a, 0x00078f546c681ae3, 0x0008b8cbfa155c29, 0x00048b8858cadcc0, 0x000000000001d969}, {0x000da5c95714aa4d, 0x00010919cb2262bc, 0x00085c89980779aa, 0x0000f1ab4abe5612, 0x00069cb75bd125dd, 0x000a778e4c6bbe63, 0x0004b3bb367cf947, 0x00000000000bde52}}, }, { /* digit=29 [{1,2,3,..,}]*([2^116]*G) */ {{0x000545d771f3d008, 0x00076c6307398a47, 0x00054915c4cf9c72, 0x00026aae3a993222, 0x0006da9308d18e01, 0x00068e5050fbfdf7, 0x0008bd2163ed6b61, 0x000000000007500d}, {0x000f06ed5b023878, 0x000d3f571595fffb, 0x000ccfd2dfb01965, 0x0005f7e53d84c661, 0x0009025029da6b22, 0x000d89aed9c03126, 0x00015054c1edfa17, 0x000000000006b435}}, {{0x0007c3fb4d5bcba6, 0x0005b009ef80a60c, 0x00017966ca95c6c2, 0x00055ed685add960, 0x000672c7dac8ab44, 0x00072f16818f323f, 0x000a99e7009790e3, 0x00000000000067be}, {0x000c5bcf19664dda, 0x00043f15bdbcc383, 0x0007e49d4e4912df, 0x0002c304bdbec36f, 0x000d1b3ac6c72fd6, 0x0002938898b3ea93, 0x000f8bce1c8e5c9c, 0x0000000000011564}}, {{0x00098a86761cd6cf, 0x0008477faac22471, 0x0009e917079e4be8, 0x0001dd45fbd35ab8, 0x000a45d6d40e31ad, 0x000749ef67e0de9d, 0x000cf2a16c5f1939, 0x0000000000085691}, {0x00046f38fcf548ca, 0x000e7156536ac506, 0x000b8e250c84b9f9, 0x0001eacd35088fde, 0x000538fb995c165a, 0x00093b3a5ce8a733, 0x000e7934d0d33132, 0x000000000008b570}}, {{0x0002b3fc481df360, 0x0006d6a3a232752d, 0x0000509b75e73d18, 0x0000c3322a82d404, 0x000a14cbc8351703, 0x000da272724bf18e, 0x000d4a319dc4cab2, 0x000000000006d020}, {0x000398eafd6e92bb, 0x00066aeebdd89825, 0x000a73a882a68cbb, 0x0002978595f361eb, 0x000c1ae8fa3cfc8a, 0x000341575e60dd96, 0x000e4819c2109aa5, 0x0000000000006a0e}}, {{0x000065dd44a81443, 0x00083443deaaabf2, 0x000c83e66800298b, 0x00018ded51d6acd9, 0x00017d4ec9bef889, 0x000c48a6948c9b2f, 0x000f5478b41104df, 0x0000000000078827}, {0x0003f535562e2f60, 0x0004674ed7948c07, 0x0001ccc08940c103, 0x000449b0d9fe252c, 0x0006c14e825a6fe6, 0x000690f0031743d0, 0x000748d9d4ad8c08, 0x000000000000e65f}}, {{0x000eaf196980dd99, 0x0009692501ff821f, 0x00072b4a2cc10b2a, 0x0009a05e53038473, 0x000c2543d1a995b9, 0x00080877130a72fd, 0x0001456648126b11, 0x00000000000eefb8}, {0x00041f6a86207b43, 0x000d8d9a87f836b7, 0x00016f9bd17dd926, 0x000e118c40122e4c, 0x000f853b291e3341, 0x000565bade513567, 0x000f77d4f1bbb73b, 0x00000000000a7658}}, {{0x0007b4a08d152bb9, 0x0007cbab37a630ed, 0x00077618410cb7bb, 0x000086c1d4a8f5be, 0x00046581428269e1, 0x00076cc7d3a87384, 0x0003a0b642dc1626, 0x0000000000097e42}, {0x0008ca2aba5729e1, 0x0005b66ac1b365bb, 0x000e67e449b0ae7e, 0x000debbadcc68242, 0x0004b1536fa18f47, 0x0009e546144e9bf6, 0x000b901cfdd50493, 0x0000000000043bb3}}, {{0x0005a0a5974046e0, 0x000112e32f89636a, 0x000495f55b511bd6, 0x000b1ad8f8328866, 0x0008adcbd933278d, 0x00064f863271d907, 0x0003652208fae34a, 0x0000000000039c89}, {0x0000e167567c2b6c, 0x00048cb46f2725d5, 0x00086f7986cb61ca, 0x000d316edd504188, 0x0004cabe36ed3421, 0x0002efcdab1d8a06, 0x0003eedb13e56036, 0x00000000000c71eb}}, }, { /* digit=30 [{1,2,3,..,}]*([2^120]*G) */ {{0x0000e8a3d453ef19, 0x000752af8ed809c8, 0x000017d0798a8632, 0x000726f782193578, 0x0001b87254c44c0e, 0x000e7691a8c1962a, 0x0002ee30796a71c9, 0x00000000000a75a1}, {0x000c339094f215d4, 0x0003e535f42c17eb, 0x000b753210a29b6e, 0x000ef35e39a7a591, 0x0002d459b91ab7f1, 0x000fd429da2789ae, 0x000f57eadbca7f02, 0x0000000000065290}}, {{0x000ffd02d3a50b87, 0x00027c085500177e, 0x00023ee786608759, 0x0001d964318e861c, 0x000604fe9b85dda7, 0x0005e7e2001d3d39, 0x00081cda4bc065e2, 0x00000000000e076c}, {0x000171ac92e482e8, 0x000095b9f82189f0, 0x000cf8881039863b, 0x00083e4d8dd159bf, 0x000720b18043f526, 0x000a0d8f5ca9c888, 0x0005c473c040fa08, 0x0000000000017952}}, {{0x00023e634e793b49, 0x0000c37ed2be4ce8, 0x000e92823d3628c0, 0x000ad8ae77c2f00c, 0x000a44de16a8b061, 0x000e490ffe87e1a9, 0x0003eddf4f57c87e, 0x0000000000000599}, {0x00036b9f1b67eda0, 0x00020e1036387a16, 0x000cdc81b1b14889, 0x00020d15ab42f920, 0x000dac0ff03359cb, 0x000c1e7f4a738a18, 0x0006e0da501a2e2a, 0x0000000000084d8a}}, {{0x0000efaf35b1418f, 0x000173a8289046f2, 0x0004fa8840c897aa, 0x000898ae5fa19d2f, 0x00065e1c5fa4c574, 0x000390fc20b13dbb, 0x000187f11343ba7c, 0x00000000000d7d32}, {0x000b8b2ed2cc734d, 0x00011c92cb1bab11, 0x000e6307a3aa4fd9, 0x000dfe5672f2af7d, 0x000430932441da69, 0x000af02d69c62d7b, 0x000c22165672ad94, 0x00000000000cde81}}, {{0x0006bff8295a2913, 0x000d91d27efcde72, 0x000bdb7b59692a46, 0x000fb83caa26d18c, 0x0003b82babbe99a3, 0x00083dd60d27e613, 0x000cb861030dfdd7, 0x0000000000073c78}, {0x000a3caf05842de3, 0x0002d8707a2cf633, 0x000f47297bf43775, 0x000d412a2b176b8c, 0x000fc72021017c3f, 0x000a6d536d5b52e2, 0x000ec024a63030f0, 0x0000000000004648}}, {{0x00024dd131928645, 0x00063d45e3501026, 0x000cd2a97f7d8b99, 0x000a088e302483ae, 0x00082c2485c01532, 0x0009cdbe63475e8b, 0x00073808f9ea5696, 0x00000000000253cd}, {0x0002a544f2d5917a, 0x000581cf323a3b9c, 0x00023a0e49f58c76, 0x000e84fc06f3d0ad, 0x000e39efe6d99a31, 0x000ac4decd326b86, 0x00058277e3e1df14, 0x00000000000f3e0c}}, {{0x000611e8121168e1, 0x0008967477cdc1e4, 0x0003ef00563660fb, 0x00060b9917eec666, 0x0004d66c5c1d31fd, 0x0009508baacd95bd, 0x0002432e0551f3bf, 0x00000000000688cb}, {0x000033e51fe09e4b, 0x000448c039740256, 0x0004cddb41207f6c, 0x00025e144db62afe, 0x000bc4a030da1918, 0x0000815043ee8aca, 0x000cd08ab154a894, 0x00000000000486c9}}, {{0x0009bbd8fc757c25, 0x00003e92b56bf065, 0x0003d138d6f390b1, 0x000d0ef50f5c483a, 0x000611fa89fe7754, 0x0004ea7d8850a9ef, 0x000a2e97d74b1bba, 0x00000000000aab7b}, {0x00042e268ab251b7, 0x000af06f30ab067f, 0x000bbd0bcb9d997c, 0x0000bca7a2e053e3, 0x0008dcf0e14c4758, 0x000f553108579559, 0x000e18c3596781d6, 0x000000000004c9b7}}, }, { /* digit=31 [{1,2,3,..,}]*([2^124]*G) */ {{0x00056db726934b05, 0x000d28db8b78ca20, 0x000efbe1df76bc8b, 0x0000f022dde2e3c8, 0x00038cbf406c67e5, 0x000f7ff602e2461f, 0x00068832182781e1, 0x00000000000e30e2}, {0x00008c8748c4086f, 0x0000895adc204b38, 0x00054339345edf7d, 0x000f060b73417379, 0x000fd128d46cd5ca, 0x000fc1e04ed93187, 0x0000a13f2819cb20, 0x000000000002b7f7}}, {{0x000424a4cdc9ef0a, 0x0009fd74d09c0410, 0x000c23c8eb2570ac, 0x000cfdce132b9412, 0x000c843d3c66db1c, 0x000cb3ef4a0e5309, 0x0001771fbd03a5f9, 0x0000000000000ea5}, {0x0001bb0b6df68f60, 0x000fa1ebf5a155d8, 0x00046a120ff8039f, 0x000c37aa0d34d161, 0x00050fca43af3256, 0x000841bdeee40efa, 0x000a0bc299bbd4b9, 0x000000000003bef4}}, {{0x0001fdb0e87d4c69, 0x0008f5bbf8bfdcec, 0x0002c8b1b68f641d, 0x000718bfd3fb74be, 0x00015a085196abd2, 0x000dba2ea03c0150, 0x0008bc147474dc4d, 0x00000000000eaa2c}, {0x000a67e6cbd2f408, 0x000e9bc3dc5c2f94, 0x00045e933f00eed5, 0x000e98325d341410, 0x000406fcbc8e0276, 0x00024ebab9372694, 0x00050b8c4b7f2ca3, 0x000000000007dc3a}}, {{0x000547a274927d68, 0x00075e01295fd654, 0x0003c43252dc8b6c, 0x000689f9eaf8eb82, 0x0005c622acc52ec9, 0x000757f2a327b96c, 0x00006eae918f81b2, 0x000000000004fd66}, {0x000f52e65907ef2f, 0x000a109bb7fcdbf4, 0x0007ab72ec41ee7a, 0x0006f125fb475125, 0x00018e399520df2a, 0x000b1c3a2be88faa, 0x00081f0166d57e3f, 0x00000000000e525f}}, {{0x0005132af5b85725, 0x0006e0c64cec623a, 0x000d73b377e49971, 0x00043ae5a8027b17, 0x0007d0a7406ac27a, 0x0002bfeed1c5729c, 0x000357445fc7d34e, 0x00000000000809bc}, {0x000fe2c3577b04e1, 0x000a30598626b6a7, 0x00059236250da683, 0x0009b314294839a7, 0x00093ab9bc662151, 0x000ab597466282da, 0x00012e84c422c25c, 0x0000000000071c0f}}, {{0x00044dd5af953087, 0x000b3f24fab9aa7e, 0x0007e53a0eea7298, 0x00070e733ac4fb68, 0x0002c8a6976575e3, 0x00030aa0ed8d6164, 0x000637f057f10a5e, 0x000000000004f1e8}, {0x000514c4bb67bcdc, 0x0005e887f06b2b4b, 0x00032e66a34587bd, 0x000f7eb6e6483a19, 0x000f475d4bfd4319, 0x000811fc744f1aaf, 0x000f8ba8ee73b50f, 0x0000000000082916}}, {{0x000b0ecbb3371c13, 0x0009596495c1e57a, 0x0002216cb93b15bb, 0x000c858fe6e84ffb, 0x000b0b189be26806, 0x00058a7685c215e8, 0x000202ac61577e80, 0x0000000000088e0d}, {0x0004f2a99a53c49a, 0x000de70322e164ce, 0x000973bc42c42efc, 0x0001f014d701ab8e, 0x0004a61df25f8863, 0x000f6dbeb889f10d, 0x000168affec5a9bb, 0x00000000000934ee}}, {{0x0006f789ccd0fed7, 0x0003cdefe3a7abd6, 0x000569da64526056, 0x000c26a73d1f9b54, 0x0008237ae8b77366, 0x00047825935d5d71, 0x000ee33efb20feb4, 0x00000000000aa545}, {0x000d70972e2560bb, 0x00081750edd05bef, 0x000da581b51c4635, 0x0000f370a9e29dc7, 0x0006bfbec7f616e6, 0x00047e1439cf0a13, 0x0001a9b430a34b2e, 0x00000000000c6cdd}}, }, { /* digit=32 [{1,2,3,..,}]*([2^128]*G) */ {{0x00056f0266d7e788, 0x00065f186d6bc61b, 0x000e03ac4fb95d1d, 0x000432edfe64dc3e, 0x0002d795ea57c9e7, 0x00045af2bd9fc483, 0x000517f4ffdb81c8, 0x000000000002b670}, {0x0004d8950582c931, 0x0007aa7c1be04d23, 0x00045b4daadb356b, 0x0008aba03f2ef6dc, 0x000420dc701d62ff, 0x000f1011960ecaac, 0x000fd09f4b559f4f, 0x000000000003cd54}}, {{0x000973c51356e0d2, 0x000aa31954a56667, 0x00047c018911cdb5, 0x0003ec5e37ef1d2d, 0x000575bc3b668c43, 0x0009cd98bcd0f203, 0x0002a33723f14524, 0x00000000000ea3b4}, {0x000998df93db2ed6, 0x0000ff607fee05d9, 0x0005662b349502ed, 0x0005d74cea5417fc, 0x000a10fca22bd47b, 0x000635e8b6891940, 0x000fef5cea41332b, 0x00000000000b5934}}, {{0x0000bd5aa7cff3d9, 0x0003c365a4a426e6, 0x00069eea0aae5d6c, 0x000c8b4b7205a704, 0x000357df815ca330, 0x000a926744858eab, 0x0005d76e522afaf1, 0x00000000000f4136}, {0x0001a59021cca096, 0x0002a00dd3461384, 0x0008629f956ac671, 0x000103f7c082301c, 0x00076b092b71f427, 0x000037a3314a2a18, 0x000e14210f632130, 0x0000000000039340}}, {{0x00025fc00f86f9f5, 0x000b5b1f4fead323, 0x000e624d9ef69f8a, 0x0007efe2e28aa2a7, 0x0009b3151d6748b4, 0x0006a346070dad2e, 0x000af787a8178b43, 0x00000000000801f7}, {0x000701583b4bfabc, 0x00034fab462e36e3, 0x000ddd2177064fe4, 0x0006b3fe66812831, 0x000a6a3fdc1db469, 0x000e37dac3bd9910, 0x000fb34409128449, 0x00000000000cf605}}, {{0x00081f556f82acd9, 0x0006f59470e4953f, 0x000963a40f813b02, 0x0003c1e0fb30ecd3, 0x0003b62892f14761, 0x000eefa161fbeffa, 0x000719ddfeef49f8, 0x00000000000daeff}, {0x0004929822ef7d6f, 0x000dcff1872cd89c, 0x0009edd2dba5c5c9, 0x0003a387695218a2, 0x000720802b8852a6, 0x000f4a473a0d413a, 0x000a4a233f1f3118, 0x00000000000c9d7d}}, {{0x0006ae71b9b2b784, 0x000ca86737912907, 0x000e250552a02dec, 0x000185ee92c712de, 0x0006c201e3272efe, 0x000f6b0788b908f8, 0x000bf33ab5528894, 0x00000000000ce0a5}, {0x000abf1c0844ab25, 0x000185eab37ac7f5, 0x000c6bca8c37680c, 0x000edff304f1cf97, 0x0008f6fd3e90f3a3, 0x00016e5ed8992ecd, 0x0005c4ff24d7c69f, 0x00000000000def9a}}, {{0x00054a31e739d50e, 0x0001e2edaaaa9c57, 0x000574cc3b6825a1, 0x000fc42bcb161908, 0x00046709d8513542, 0x000af4ce06c04ec2, 0x000e2e5fe9768ea9, 0x00000000000eb6eb}, {0x0005126ebc807472, 0x000c87b7da4abcae, 0x000d07139021766d, 0x0001c51fd563c816, 0x000926c775e17f69, 0x000b58889ea990d6, 0x000c2c2cd96f1321, 0x000000000000f1aa}}, {{0x000e697116bc35a7, 0x0002057edf71ec8d, 0x00063f77e7793641, 0x000ba1aa6934160d, 0x000c5e639a54b37a, 0x000bce957d45b3d2, 0x0007f362c6b9ad70, 0x000000000005d7e8}, {0x000a8127f71a285b, 0x00017b02169816f9, 0x000c7a7939056bf2, 0x000692b478e4b92a, 0x0009be3fe25a15aa, 0x000bdd4a8dd67cf2, 0x00027af1ef75b006, 0x0000000000041df6}}, }, { /* digit=33 [{1,2,3,..,}]*([2^132]*G) */ {{0x000455d88f7fc60e, 0x00091a58a27c4fad, 0x000ee65aa7e47d3c, 0x000826600079a263, 0x000f2606caf52431, 0x000cb28c8113f6fc, 0x000aa6f6ff2be316, 0x000000000003c17c}, {0x000c05f668a9dc76, 0x000798ea577e0148, 0x000c912137590c65, 0x000eff4592a57ef2, 0x000c5e3f67b24b28, 0x00000890276e1f87, 0x000b7e40d7a676fb, 0x000000000004b6e6}}, {{0x0007f95d338f5fb6, 0x0000076e27519dec, 0x000fefb9477deeec, 0x0002dfb71fba6625, 0x00085e0886af5832, 0x000ee544c228aec0, 0x0006398d83b6276a, 0x00000000000e29f9}, {0x0004808391599977, 0x0006d1ba4cfe02e0, 0x0000441e3d4b3e92, 0x000ed58cee95d92c, 0x000abe5355407e0e, 0x000a9a1f42d29282, 0x000c82866638b607, 0x000000000006ab8d}}, {{0x000c43ee7094e067, 0x0000b599ece9688c, 0x00025bcbe937baac, 0x0005ba86373ccef5, 0x0003c64f72612afc, 0x0004ce1abe455683, 0x000a77f29ad54041, 0x000000000003ee82}, {0x000e0b1548890be5, 0x00094fa26eaa0940, 0x000c96b0a3e57442, 0x000ade54e1c94bd7, 0x000e20b0ddbe9570, 0x0006eff6ff4a86d8, 0x0007a4967ab653dc, 0x00000000000e8bab}}, {{0x000de87dcf2f3d8e, 0x00056a16c79cee01, 0x000db47cfbc9e301, 0x0006aa0c2f47e69c, 0x000f2c9b4914b8bd, 0x0007242a8277d590, 0x000512b6d1c81009, 0x0000000000045f75}, {0x00044d25d22dbf16, 0x000f02176162aa27, 0x0001167bcefd598c, 0x000c0d1a503aee8c, 0x00057af4dd78fcf8, 0x000b43be45d1f94a, 0x00071b8f0bc1a62a, 0x00000000000ba9e0}}, {{0x000adf4d6bef5a3d, 0x000a19a2dc376622, 0x000b08bb2e394780, 0x000e5cf7c0765207, 0x000c4063c3538e70, 0x000baec46c0dbb4a, 0x0001ad3f4550566a, 0x00000000000f9356}, {0x000e15a92e3f32ae, 0x00055d0bc6d91fc6, 0x00092d1d7bd54520, 0x00033424b80c021f, 0x0007af5e458c62a7, 0x000bfde586e1d546, 0x00052c6922574f70, 0x00000000000d19f0}}, {{0x00077ca19b6937db, 0x000c3bf87f30d9c2, 0x000f3d29bdf61e62, 0x00032bd50ec0ba46, 0x000ae60d1e72d5fd, 0x0004ff2d37de8fe0, 0x0007e452d77fe0e1, 0x0000000000055ca4}, {0x000fd784e6c9781f, 0x0000339e3d19e6d1, 0x00045fa26fa441a0, 0x0000c7afe92c6d07, 0x000869a829043bd7, 0x0006d1d9ea3fbc06, 0x00024be263f00ed9, 0x0000000000075c0c}}, {{0x0002619f4e7dcc16, 0x00090a1d1a8f0893, 0x000f4151f0e91898, 0x000c39b84ee41fc5, 0x0002e4a019099db2, 0x000a66c12ad292a0, 0x0000f6ee6b26ddfc, 0x00000000000f04f7}, {0x000e18e3a8161ac5, 0x0007f01e66788b92, 0x00099db080ad62ab, 0x000e4542595d5a6c, 0x000bdce965cc3e7c, 0x000ec7931f894a64, 0x0005be12e46952d9, 0x00000000000fb65b}}, {{0x000d91fc53fa82b7, 0x0007d705bfe3760e, 0x0006eb6118c41a96, 0x00077a9bc4567977, 0x000617081a2f811e, 0x000e1640e4f52c4e, 0x0001d787405d819f, 0x0000000000070771}, {0x00085581b6dc5925, 0x00062dc6fff82580, 0x000af03b55b43c90, 0x00066bea9cf3eae3, 0x000e87139b8b0ecb, 0x00042b4d77418372, 0x00032e6aaccf295e, 0x0000000000031fc9}}, }, { /* digit=34 [{1,2,3,..,}]*([2^136]*G) */ {{0x000f65dda78f831c, 0x00073fa3b4c8e10f, 0x0006b8117d5cb12e, 0x00039562e8c4d8cc, 0x0005cf89935b06aa, 0x000fa071e4981c3e, 0x0003bebdbd0c4745, 0x0000000000049607}, {0x00004bb91c157448, 0x0007009a7298688d, 0x000867eb798cb22b, 0x000b5b3988f2781c, 0x000d73b1719d9a64, 0x000d2e8076ac9440, 0x00042b58ad54c7e3, 0x000000000008f067}}, {{0x000489635dd868b5, 0x000ef339521774bb, 0x0001f606d4b5774d, 0x000d61e0a285bd5e, 0x000e71171b1c1084, 0x0009b29f93935a84, 0x0009bd8ac2433cf2, 0x000000000006dd1e}, {0x000f576ac5f0cc26, 0x000f788da0477c71, 0x0007313f812b64cc, 0x000a25f9d5b19e1d, 0x000b6a27fa79a792, 0x000a16a8e9ee015c, 0x000e67ea3bf8b57b, 0x00000000000c15fd}}, {{0x000f3b091fcd53e3, 0x000c537f50e43695, 0x00003782e79d52fb, 0x000af85e1d111511, 0x000f6785ae1c3916, 0x0006ada8cf56e852, 0x0005b2bf8c72adae, 0x00000000000e1328}, {0x000cbe0d0bda153b, 0x000e35327920cb17, 0x000e7daa3650306d, 0x00028573caf37928, 0x000b550ffe1ca713, 0x0005d4e4fb15ab34, 0x000f9d818980666a, 0x000000000002f854}}, {{0x0005d9265089916f, 0x000013b623150146, 0x0007ede4f0fb2f49, 0x000c31c56471100e, 0x000b1bae8d2a4bc2, 0x000f1f76a4a0e73b, 0x0006cabfc0770a8d, 0x00000000000a7bb1}, {0x00039cb13d9c4b7d, 0x000f42afe5b1cb58, 0x0008a2ce9b2dade4, 0x000a333a1af2a824, 0x0005dafed6cd97ca, 0x000c3b2e393cb92c, 0x00095609553e7e92, 0x0000000000061af2}}, {{0x000ea55edca2a058, 0x0003f5559dd3109c, 0x000f7ba60d37c6c8, 0x0000fabcaf57d0dc, 0x000578742ab60d84, 0x0009c1c8e9625866, 0x000167c85482ad40, 0x00000000000adaa6}, {0x000208d39ae67d2a, 0x000dcec26ad9971a, 0x00067a35ccc54689, 0x000a7fc2539986bb, 0x0006a23dee41340a, 0x0001a9837d767487, 0x000da9a948a9292e, 0x0000000000071438}}, {{0x000778a60c6bd7ad, 0x0007f39038863eb8, 0x000e85efa03ef35f, 0x000682ef3d8310f4, 0x0008f412315338aa, 0x00026310bb52d41e, 0x0006924fbef3dd70, 0x00000000000f6ff5}, {0x000ba50eddf2b7fe, 0x000b63831c6b1cbc, 0x0003bc6684c6c5e0, 0x0006abc6516bba59, 0x0005446d35a876d2, 0x00012a8d0c237f9a, 0x00015bb2b16c0ff0, 0x000000000000ee03}}, {{0x00014182dba86bd2, 0x0009c817d77b02b0, 0x0006420950654aca, 0x0004107da68b7691, 0x000dbebc4c4dd3ac, 0x0003d39e96904bcd, 0x000950b0d2103ca5, 0x0000000000030a5e}, {0x00028ff31a9f909b, 0x000c7b092568034b, 0x000262a60542e8eb, 0x000ab34c15855ae5, 0x00063017194f2389, 0x00046b838c14dfd9, 0x0006fc420e071911, 0x000000000008fb4b}}, {{0x0009c78614d38ab4, 0x000d813722ab0651, 0x00088626a03970e0, 0x000f467f76fdaf74, 0x000912ddfd9ad3d0, 0x000bdefd37ce072f, 0x000315ce918a5747, 0x00000000000750e5}, {0x000fa00e65975639, 0x000cd08bbb20dcda, 0x000822e7b86b49be, 0x0005c21ca865ba6a, 0x00002e6e8e6fc8fb, 0x000608b60ee6e41e, 0x0005cdd00ae6214c, 0x000000000006ff68}}, }, { /* digit=35 [{1,2,3,..,}]*([2^140]*G) */ {{0x000cd00e20fc1fe8, 0x0002bbbccce39826, 0x0009c6cbc7ade77c, 0x00035a5d2252fdaf, 0x000954e7dd499eae, 0x0005100fda8f4f20, 0x000727a56d72a629, 0x0000000000056767}, {0x000898f026420cbb, 0x000adbf60b247e57, 0x000b35db15577b1e, 0x0007ad4b93dab9cc, 0x000022d71f39c2a6, 0x000304db218cd0ed, 0x00082104380c425f, 0x000000000006729c}}, {{0x0000345995afd46f, 0x0009dca07923b790, 0x000129149d2f3565, 0x00079e83cb025114, 0x0005beb383ef41e3, 0x00076dd0dfabac00, 0x00012724d12d9a10, 0x00000000000b208f}, {0x000d58cd6475c579, 0x000359cc38a604c8, 0x000857e410d47fbc, 0x00060d98ac219eff, 0x000faf284c806f63, 0x0009e366a1edaab3, 0x0007269c3b528101, 0x00000000000bc9e9}}, {{0x000a386526319283, 0x0008d26bd07d697c, 0x0006e6a9c305333a, 0x000c5466798b96c3, 0x00081d3f3859d831, 0x0001b9ec71d6b410, 0x0001a9501d38ec99, 0x00000000000d7843}, {0x0008f62f7d623e0d, 0x000dd8b85baf6942, 0x0003f90bead64135, 0x000c1107acdcf58c, 0x000c848d5842efc7, 0x000c7fdacd9af415, 0x00019b6b5a06bc0a, 0x00000000000a3443}}, {{0x000517cc17c08a8e, 0x000a28410d82975c, 0x0000ae8bc362b8a4, 0x0000d0d18c253486, 0x00007eb035a3ae46, 0x0001144145d0279a, 0x000f7987e7c1289a, 0x00000000000c0744}, {0x000ccad1ad801112, 0x00072b7b2b4f054d, 0x0007f502703051c0, 0x0007395b51ee6864, 0x000bf6122422124a, 0x000f1a7fff2937c4, 0x00032eb4ec133207, 0x00000000000f8860}}, {{0x000daf15d19f8632, 0x000794c0d78053af, 0x000ade8ac0a0ca73, 0x000c453e4b57e236, 0x0005f4172b285217, 0x000f999f8b4669e3, 0x000d41509a3cd049, 0x0000000000087c69}, {0x000ec5ba18211916, 0x00032e14d01e8346, 0x000c499a14031eb7, 0x000bff270dc2bf04, 0x000bc01864000e17, 0x000a4dd3446560b7, 0x000d06e28c7b9c49, 0x000000000000f325}}, {{0x000161555383d319, 0x000d0dd4eb3d0283, 0x000dca801a8bb250, 0x000285ddc1973c7e, 0x000aa0046b981200, 0x00019a7fcfd342be, 0x000fe5d191734912, 0x00000000000b7caf}, {0x000a5ee9f805422f, 0x00057ea5a0c4d360, 0x0004c8206c9d4abd, 0x00016dc6046eeeb1, 0x000ecc8e64b15b2a, 0x0007fadda1755e1f, 0x000ec251e4946e9e, 0x00000000000fcbf4}}, {{0x00024bd4d62de244, 0x0001d46d7088801b, 0x0002ae4b99b01f02, 0x0008fca4fbea2725, 0x0005bd80a9dfe494, 0x000871c717d6c776, 0x0005701b470ea6f3, 0x000000000008330a}, {0x0004db08d904e89f, 0x0009bdaecddc0ed5, 0x000f26cdb2e08463, 0x000cd84caeeef145, 0x000fc685a35656c7, 0x000d93ddcc60c910, 0x000895e68bc5c59d, 0x00000000000feb64}}, {{0x0001bb5474d7445b, 0x0008af877e8c6483, 0x000948d44b23fa45, 0x000269f2b004cfe9, 0x000795450f8b19ff, 0x000a7d4588adc5d7, 0x000fdc688ce8bce2, 0x0000000000097bd7}, {0x00043a2684d27187, 0x0007c1b9f4ad5bd1, 0x000b255e8d74e0bd, 0x0001f7e71d83d86e, 0x000d25ffc219abee, 0x00073f553e693c76, 0x000a551c9a84afc8, 0x0000000000066d77}}, }, { /* digit=36 [{1,2,3,..,}]*([2^144]*G) */ {{0x000e4a9a609d4f93, 0x000f05584cbb3289, 0x0002a9b59e61225b, 0x000d8267df2d43de, 0x00000109e8014126, 0x000172f1cdd5bbbf, 0x0000d985b92ee338, 0x00000000000f3143}, {0x000ac2d50dd03701, 0x000b11e059a07dd0, 0x000eb68a6d1ce296, 0x0000751560f20e77, 0x000e7aaf3a9ad622, 0x000bae14ea59489a, 0x0002497b70e2f664, 0x0000000000076d08}}, {{0x0001e7720f69ad57, 0x0004baff47822226, 0x00011f4e0e8fa5c8, 0x0005f8d2ef696aa0, 0x000b4fa94fcabeb8, 0x000d41a438ce5baa, 0x0007720a32f96200, 0x0000000000074f6e}, {0x0005b3ae79f59da9, 0x000a8be0221aef2d, 0x0005793443a4452f, 0x00085d6a7e49f3a4, 0x0009cb5d3c6378ff, 0x000eb65f56300658, 0x000bdfe8e4383596, 0x00000000000ff8ad}}, {{0x000ec83ab52a5d83, 0x0006cf6fd26cb934, 0x000ee1af72ab19a2, 0x000788be372817f8, 0x000ae8c90c31694a, 0x000aa0ce585f3dc1, 0x0002238c90c6bf15, 0x00000000000f01bb}, {0x00043ef688d7f41f, 0x00075bdae01dd56c, 0x000cf79ad5ecb5f0, 0x000ff4ec2548f251, 0x0008d12802a750dd, 0x0004d924054a4986, 0x000d1acd922fb640, 0x00000000000957f6}}, {{0x0006a17488184bb0, 0x0004d082ea61c88d, 0x0004b5a68e9c5821, 0x000df962e54f5d00, 0x0006e39dc6ab7d33, 0x000179b13340b0d3, 0x00088cd97a8b848d, 0x00000000000288d3}, {0x000bcf17110adf56, 0x000462237e507d00, 0x000fa28fb932260c, 0x0008bcb42be74594, 0x0004de2176b6645f, 0x000e2f09cce2b0f5, 0x000001af570a09d1, 0x0000000000057fdc}}, {{0x00009414087acee6, 0x000fc7dd81467f3f, 0x0007997c546fe735, 0x0004e832d2e9fbfb, 0x00061c9d9c7ca2ae, 0x000f27f140f127f6, 0x00029ef06c5a57e6, 0x000000000001f303}, {0x000b431a1206d910, 0x00037a1b2b82f82b, 0x0007312610c2e220, 0x000cb8b039f12bbb, 0x000902b92d6b1cf0, 0x000f649e606ce433, 0x0006eccb5e826869, 0x00000000000e9309}}, {{0x000f672480aedb22, 0x000c79d21c740037, 0x0001a34fe6cb5f73, 0x000b1a3aae5d701b, 0x000891978d1557f8, 0x000b85b1e477e4f8, 0x000fb42913ffb40f, 0x0000000000058489}, {0x00047efe2cde596c, 0x000a60e1ab266dc3, 0x00073cc3adaf7198, 0x000ccb657ab8d871, 0x0006547f64bdf578, 0x0003e497e339fd79, 0x000706904693943f, 0x000000000001d864}}, {{0x0009da8454e1979d, 0x00030da92e482d7a, 0x000b666249139a91, 0x000ebb3639c78714, 0x0009d77aac3c8763, 0x0002769a43bf7177, 0x000eda92a5420d3f, 0x00000000000d092e}, {0x000352bd3a0254a9, 0x000b5d7bd8d8f8e8, 0x0009446f6266c164, 0x000fa3ed6b0cf872, 0x00040490a771a5ea, 0x000ff37225255afc, 0x000cdbd40bb0fd15, 0x0000000000079294}}, {{0x0005908307814aa6, 0x00009158bfe27b53, 0x000df35ce707d624, 0x000153b8e71aca19, 0x000171b11643f07b, 0x0004e2f905e67698, 0x00010977b7dd7dd0, 0x00000000000f0dcf}, {0x000bd23edf0138e0, 0x00071d3bab2a41f1, 0x000facf3129d6b1f, 0x00099afc6f53cda2, 0x000f628039e454fe, 0x00083aa16071f2a4, 0x0006f9f1f44181b1, 0x000000000005010f}}, }, { /* digit=37 [{1,2,3,..,}]*([2^148]*G) */ {{0x000b28d4d03ca18c, 0x000a0b1e36500cc3, 0x000e44ebafd13e2f, 0x0001d2ca4bfdcedc, 0x000fb29cdcfebf45, 0x000514871d210892, 0x0001e35b12bcd894, 0x000000000001809b}, {0x000c86d0fbcc5e1a, 0x000ce09b243105c8, 0x00037f6b6be14182, 0x000a16b5de334b63, 0x00020b116076cef0, 0x000ae2bf4fe0bd1e, 0x00093754e4b48289, 0x0000000000068c8a}}, {{0x0007e2c503fdc14e, 0x00049309b1eb33af, 0x000b5e3acfac1d05, 0x000b81ebf8a894ca, 0x000e0d29329387c2, 0x000bf371427a40bc, 0x0008957f4c315be4, 0x0000000000001236}, {0x0002d22bfd1d81d3, 0x000f4319c88f7e2d, 0x000189361ce75d22, 0x000a05df0dd13811, 0x00024acba9fafcc2, 0x00027313ec8d55b0, 0x00094a871358de59, 0x0000000000017ce2}}, {{0x0002c99cf8ff48b8, 0x0002410777188c8a, 0x00068c821fc35883, 0x000b515120380e77, 0x000fe13577d1261a, 0x000862db1453c858, 0x000e1cb1f6bb58f3, 0x00000000000b9529}, {0x000338bb0bed7b45, 0x0008003f63a416f7, 0x00081208dbc793e6, 0x000048b756e5af2e, 0x00031c984bef8423, 0x000a00f3e4d978ed, 0x0009e7a06242995b, 0x000000000004f4d1}}, {{0x000e08308825a639, 0x000e8d3797831773, 0x000f79843c567224, 0x000a6a611a4e33a2, 0x00005328043a2ff7, 0x000e9f7dd904f86f, 0x000904e29d31c012, 0x00000000000c0a51}, {0x0002dae695c951e1, 0x00024070c2696563, 0x00060638255bc0fb, 0x0000d0c12c8a1f65, 0x0001ab352a835b97, 0x0005eb0c7572aaaa, 0x00059963df45a90c, 0x00000000000d4977}}, {{0x000fe53cf0bc7d5d, 0x00073e35daffd3d8, 0x00005ab0f149d24a, 0x0005a40f009a48b1, 0x000d308a81c693f0, 0x000885426a4a801f, 0x000f0575e5dc467e, 0x000000000004629f}, {0x000c6c457ceba67d, 0x000c6356b879b5ee, 0x00084a5c7d7e4e3e, 0x000856eec2dd55b5, 0x000880f0c80411c9, 0x00001b21720f0443, 0x0007b8c0b5e3e218, 0x000000000006ea09}}, {{0x00042a359a9c02d9, 0x0006601c2df8ca11, 0x0001ea46897d0b3b, 0x000341c8360fa6b2, 0x0002c52bb2d6e198, 0x0002efba5e67f809, 0x00032af944dc63a0, 0x000000000002c123}, {0x000d5d58228e0e7d, 0x000b239684f6c863, 0x000f4f910b494aa3, 0x0008eb646594725d, 0x0005793c32ddb7fb, 0x000f94b55bb4f5f0, 0x0002773ef3c33845, 0x0000000000009eac}}, {{0x000bc0df5aa0ebff, 0x00046efd26dca17d, 0x000d31eadaba6e9d, 0x0008a89e1830a96b, 0x00013e039a029f10, 0x0006fbb3b7e8e368, 0x0002f11747b3e925, 0x00000000000abb3b}, {0x00023cb577b95e94, 0x000e2cac5818c280, 0x000b36c4a5c24e15, 0x000fd4d7a5485367, 0x0009aa3645074081, 0x0001a5f81fe2d8e7, 0x000db4e86ce00ea8, 0x0000000000077a9b}}, {{0x000a3bf39d563e4f, 0x000f02c5b0e421f4, 0x000bae31a917643d, 0x00085959aa907285, 0x000af658699bace4, 0x0003b18e632be886, 0x000667ce75d6c6da, 0x0000000000069caf}, {0x000af371b713c401, 0x000f0c17c66ce4f4, 0x0002f4e783050dba, 0x0000041623db4f0b, 0x0002c74762e1ceb8, 0x00071c52fe75615b, 0x0002ecade8a54386, 0x00000000000cacaf}}, }, { /* digit=38 [{1,2,3,..,}]*([2^152]*G) */ {{0x000ea5d38989c046, 0x000c5a933aaf71af, 0x00084b51a5d47afc, 0x000dff8854de4972, 0x000b247bec1525a9, 0x00061e58da8b31d9, 0x000707468a25c846, 0x00000000000786a0}, {0x000d126f8d197fbf, 0x000be282db8ca2e4, 0x0000d8a3ccd2e3a9, 0x0000faaeaeda06f0, 0x0009add94b47a2c4, 0x0000690766963292, 0x00092cc72354f6b0, 0x000000000007878e}}, {{0x000456ff7fbc201b, 0x00083854b0583e19, 0x0005b9f9d05986b8, 0x00093894c32fc71b, 0x000c9ec8f90dec82, 0x000c7b9c0882fad4, 0x0005e52d39990dc6, 0x00000000000d71a2}, {0x0003262dabc3b450, 0x000866b852e64a5a, 0x000281968ae95022, 0x00011545857f0497, 0x000c1ccb9bc83700, 0x0002bb853746621f, 0x0004ed97e44e6361, 0x00000000000758da}}, {{0x000e66dca895aedb, 0x0007e58775856e71, 0x0003edbdf1471e8b, 0x0002e3da62265d35, 0x000672d98b0886a1, 0x0001e9c858ec4278, 0x0004ceb9da8016f6, 0x0000000000080099}, {0x0007a34c46f751da, 0x0004f63d0878c9c9, 0x00077928ee65f2b7, 0x0009e126a1c1efae, 0x000eebd0497a780b, 0x00065231eeed68d0, 0x000127bfeee3d292, 0x0000000000080e03}}, {{0x000369b381ff008e, 0x00068d25f6507829, 0x000435b503d33f46, 0x000031108b9b08bf, 0x000f3fe92e910b36, 0x000189ddc16477af, 0x00038f6e5f6cb103, 0x00000000000c698a}, {0x000953f049518733, 0x000e102a092187fe, 0x000b4e74068daf16, 0x0005eac8fd6b76cb, 0x000611ef96b455a1, 0x000e433b51e37ec3, 0x0004c3d1b3b3fc30, 0x0000000000051d17}}, {{0x000c3efd55e9f108, 0x0004ee67813dd55d, 0x000e8b95d557829a, 0x0007b634c8cf1647, 0x000fa3556b4674ea, 0x000db03dff1bde0b, 0x0006b45343f260c1, 0x00000000000e0a1d}, {0x000557bdaa85b25c, 0x000b5af56bed0543, 0x0009694c640e2d2a, 0x000c5892c72fa801, 0x0006a49486e504e0, 0x000f78943812e259, 0x000431d5e0bddb2e, 0x00000000000acdba}}, {{0x0005b2c1b41a7e30, 0x000e8b6e95494a98, 0x000e156b8fa7f1c3, 0x00012ee2183ce113, 0x0000cc01d1434741, 0x000d0d25f4180ec4, 0x00016ddc5f8f7b8d, 0x00000000000974a6}, {0x00054a8b6ee62d01, 0x00072b9a7f0a96a9, 0x0007a0f1f81abc8f, 0x0000b82bc5671a8c, 0x00000466ffaf50eb, 0x000fdc348fa58667, 0x000299a75ff5aab9, 0x000000000007f784}}, {{0x00064348b9a55592, 0x0008f24b18ccf351, 0x00046d73b67eefc8, 0x000977c532d340c4, 0x000191002448043a, 0x000960397a2de526, 0x00034e1e11027870, 0x000000000000164e}, {0x00056330f30da4d6, 0x00014cc5f57288f2, 0x000974f0c19f8ace, 0x00020963266aaedd, 0x0002c3ccd59f3b15, 0x000a6dd5dfaea30f, 0x00035a1da2e1fbc9, 0x00000000000ceda8}}, {{0x0007996f48325ebf, 0x0004f7914213d709, 0x000270acf84435ed, 0x000e5a126a34238c, 0x0000701ce8c76eda, 0x000656e02e566bf5, 0x000fbf3562e87555, 0x00000000000b4e8e}, {0x0008d6657de7885e, 0x0004a5f10a503e86, 0x0006a10baa0b8f13, 0x000fc25cc2f2e415, 0x000caf5718c149d1, 0x000d6b890e973bb1, 0x000f129b8825dad2, 0x00000000000e2f00}}, }, { /* digit=39 [{1,2,3,..,}]*([2^156]*G) */ {{0x0009cd8cd3edcb0c, 0x00022e37211bdab0, 0x000bfe0383f52218, 0x0007e26a1b9f8b57, 0x000d7d7f72d5fdcd, 0x00049c9205641e45, 0x0002a15377c1bec4, 0x00000000000efc7b}, {0x0007344da1d40eaf, 0x000b6c657a9ff3f7, 0x000acc6777a25729, 0x000d1bcd020eaa96, 0x000a3f6860c76bfc, 0x000c7c80617534b0, 0x00056b8ce5722284, 0x000000000002bd74}}, {{0x00070f4fca1b2907, 0x000d2aed02b6a844, 0x00048854f708389d, 0x0006ec4654e7c314, 0x0003e7034bfd8222, 0x000d6b555008ac00, 0x000d44e343c5407f, 0x000000000001b429}, {0x0003fda90bb8f0f9, 0x000bce0702a33908, 0x0003c08ba27edf85, 0x00072f6d46524015, 0x000d35f600437e6d, 0x0003e8cc4d92655e, 0x000b40a0dbaac627, 0x000000000003c3ff}}, {{0x00098d832fcb2cab, 0x00078bc06ecab0e1, 0x0004e7cd0ece1448, 0x0006fa0453c94bf2, 0x0003ed1a6731a6fc, 0x000c3f1fb5460f94, 0x000d4eeb11656a4e, 0x00000000000ff1e7}, {0x000efd2eb43b2558, 0x0009059526466dba, 0x0007bc3cfc024713, 0x000588824fd2ce63, 0x00039f2c29257bdf, 0x000e97f3013df0c8, 0x0006411bf621e6de, 0x00000000000ebea6}}, {{0x0003b015d907e90a, 0x0004e5906a35b43f, 0x000f32388b4d1260, 0x000ac9136f847648, 0x000bbe0f1dd365c8, 0x000d26c21f73b3de, 0x000ae740358868a2, 0x0000000000076792}, {0x000fc16ec80c7bf1, 0x0008d3ecea1669e7, 0x000b1ce4e42f6130, 0x00091090e0062443, 0x0006dd94681b6db8, 0x0005a3de2d29106e, 0x0006ccb40b8694a8, 0x00000000000936b8}}, {{0x000fa93eb46c6ed1, 0x0009f28d33e792c1, 0x000af8e666ab1b38, 0x0009f3bce683c5c2, 0x00098371fe755a74, 0x000712c1d717629d, 0x0001aa5e828fc057, 0x000000000007e4c6}, {0x00082c4505e4cd17, 0x000035d927bad55e, 0x000bbbc997dd1436, 0x00099a398591dc25, 0x000a4836664c560a, 0x000d79298c885fe8, 0x0001d7d18acd4226, 0x00000000000185df}}, {{0x000755a507c76d63, 0x000c69d8a925b591, 0x000ef5ac5d730610, 0x000ca6ddfb534b8b, 0x000c6dd78a324f53, 0x000a146d54e64874, 0x000201336e5b46c2, 0x0000000000098395}, {0x0001a5ef82624226, 0x0004ca4c095220d8, 0x000ae0a7c3b4840e, 0x0002f64c36286ed0, 0x0003c3ebb08c0ff9, 0x000f00c3057b1b90, 0x00036ec6bdc9b665, 0x000000000009a46d}}, {{0x000c3639d049078f, 0x00048d67dc92ab51, 0x000e52783edc1242, 0x0009baa8b87c0b05, 0x000052760ef4b6f0, 0x00047bf855a8a903, 0x000e742e2ae75610, 0x0000000000085bd4}, {0x00097e1bd11078ed, 0x00093ced11ff7661, 0x000e3244d9aa20e1, 0x00088ff24b3e912a, 0x000a1afd219683d4, 0x0000d21286e166fd, 0x00039c66a912114f, 0x0000000000005c9f}}, {{0x00070dd4c4f3a35e, 0x0006d913f92069a9, 0x000aaa1c8b2107ab, 0x0004e2c787c35959, 0x000fe7b7b7ddefab, 0x000e28e6aa55d465, 0x0007bc921aaad834, 0x0000000000012d6a}, {0x000d81dd493823d1, 0x00072109803c417d, 0x00095b2d5e30421d, 0x0008bdb99c5bb670, 0x0006bc7c2da71a8c, 0x000927eef1cd1c2b, 0x00041050189c975f, 0x00000000000229f9}}, }, { /* digit=40 [{1,2,3,..,}]*([2^160]*G) */ {{0x00086c2a1c05c1ca, 0x000a911a8fde5d4c, 0x0008768c091692e8, 0x000c275c74dfe82d, 0x000c38373a506818, 0x000e5f88f2b0294a, 0x00083a584c4061e8, 0x0000000000073423}, {0x0003f61270e03ada, 0x0002d263895b3203, 0x00007b3b0d15f74f, 0x00059da84da7f0d6, 0x000a924a09f21443, 0x0009ad83576e3095, 0x0002af612986e3d6, 0x0000000000039212}}, {{0x000c342a3198c068, 0x0005d3ee0a31c35b, 0x0003fc2cd3c80f60, 0x0004f4ff0fbfa963, 0x000efafea65a90a6, 0x000f4b9f9513f054, 0x000590796ba7479c, 0x00000000000932a9}, {0x00037547e06b6b4e, 0x0005d93af8a64743, 0x000922627b827de1, 0x00071e9c1a46c909, 0x000f4c9bca7223bc, 0x0008cea30000643a, 0x000ec2b6d967c784, 0x0000000000073312}}, {{0x000ecb2626cc0655, 0x000eafeb707ee40d, 0x0001edb8dca9d02f, 0x00016459a0d32bae, 0x000a1ffb926626de, 0x000578b4a9a2ff38, 0x0004434e5ad96d8f, 0x00000000000883e7}, {0x00041045bc252635, 0x0002d1d8eecaa72c, 0x000edd696d444309, 0x0002faed758ae41f, 0x00004a85d867e49b, 0x0008cba866a9a229, 0x0009822fb89dcee6, 0x000000000007f09a}}, {{0x0009f15eb1bbb5c7, 0x000d952ec99556bc, 0x00015795c8a4dc35, 0x000337c6dcc7816c, 0x0009791f7cf1e881, 0x000885a42e4e7b6d, 0x000e41faa717aa59, 0x00000000000f9c01}, {0x000171c4ffe4a6bc, 0x0000ccf208d57a05, 0x00042714fd20944a, 0x000871b264ce04b2, 0x0006cd42026a7261, 0x0009f99fe66be4a8, 0x000e2bc5397b7782, 0x0000000000024578}}, {{0x000b87e03bf622cc, 0x0002fadc79436506, 0x0000be1fdf9a8888, 0x000aaa40406c1296, 0x000c8b658d3cef9f, 0x000435baff4e6388, 0x000c997262beb41e, 0x00000000000fdaea}, {0x000ba84e0b8f458e, 0x00045d359f7d8428, 0x00016b951ae31b5d, 0x000f03229498ba51, 0x000a85bf35adb18c, 0x000aa4bc8c67388c, 0x00027a8a7a6aa262, 0x0000000000072f46}}, {{0x0001e4a772f0f152, 0x000520733667a853, 0x000ae90cf08b2488, 0x0009b27a7bc26604, 0x0008eb4f0c7a7ca2, 0x000f276309fefa69, 0x0001337b6f351301, 0x00000000000fcfb1}, {0x00022648d86fc4cc, 0x000979928d9cf841, 0x0009da8838c5ffbb, 0x0001acbe041bef47, 0x000af8d998547fbd, 0x0005a0dc57d25159, 0x0009332ec3a7d8db, 0x0000000000087e3e}}, {{0x00088fc716a5b4c1, 0x000423fb812eeafe, 0x000a6b9f65779527, 0x00041838fbefbe46, 0x0004a4b24a05e572, 0x0000c0a432b7d49f, 0x0001db23b138d071, 0x00000000000a85ec}, {0x00095de9d8768d19, 0x0006d7cc1f3d657e, 0x000b6e219733e2a8, 0x00023128f56981d2, 0x000eb4080a011bda, 0x000999b7f68663ea, 0x00080c8dd7ba7e9f, 0x00000000000b6865}}, {{0x000b2ea58bc5b2ba, 0x00008ba8418f2c05, 0x000ab2d74f8719f3, 0x00038d7bce1e82e0, 0x000eb397915b4e64, 0x0004cf6599e489b3, 0x000affa9baea9ffb, 0x0000000000042ef4}, {0x0001f2cfd470aeb9, 0x000eeae3fb532a9f, 0x0001d5334d1ddf3c, 0x0008e28defe047ca, 0x0009d24e60fe8972, 0x0000f710c63a8c67, 0x000d3cadacbf9247, 0x000000000005e198}}, }, { /* digit=41 [{1,2,3,..,}]*([2^164]*G) */ {{0x0008597cdef10944, 0x000f4294d29542ec, 0x00058a58394c4343, 0x0007f9158f95038b, 0x000164420c94fa1a, 0x0003caea8b137981, 0x0003402b686e1e09, 0x00000000000f9e1c}, {0x00006da6276d2e4f, 0x000cacd1beecf39b, 0x000bd69a9fc92254, 0x000c7192dfc2b165, 0x000dcee7e854cecb, 0x000635cc82cdb955, 0x0007d39fefc321f2, 0x000000000002936f}}, {{0x000f165eb19500c6, 0x000f54962c020b57, 0x000116eb855d7c76, 0x0009a79dd189c401, 0x000d6ce517a77854, 0x000d6bb9747675cd, 0x0000295102294e32, 0x000000000006ed1a}, {0x000926ef8530f97d, 0x000353efb54e82c3, 0x0002eec5a292f22f, 0x000c2948967fb050, 0x0009be04e909955b, 0x0001efad6373615c, 0x00097af1fcf82011, 0x000000000006fd2e}}, {{0x000445389cf3da63, 0x0002b85e1e4ab383, 0x0004d8f24163478b, 0x0004da1a717e0356, 0x00080f1bf3dfc0b8, 0x000a6fd41f1a63b2, 0x000cab47b74201ab, 0x000000000003518f}, {0x000a17bf41f156b8, 0x00031e12511fae1c, 0x0005a421fc7a58f4, 0x000fb10db5665c05, 0x0003b99f4d5a20e0, 0x000b7dbceb5448a3, 0x000b87cb1847ad46, 0x00000000000fdcad}}, {{0x00040c75d27c479b, 0x000823f2b5bd3e20, 0x000298ef45cbe8a6, 0x000f2db94256fe1f, 0x0009318ddb03532e, 0x00024c8e1acbfc45, 0x0003db2375f9fd5f, 0x0000000000037078}, {0x0002335b7531e78b, 0x000251bd461e7e12, 0x000e223c32f4b08c, 0x000777d8845f315e, 0x000697fc92c7c9f8, 0x00092954081aed29, 0x000fe09f2f8d7949, 0x00000000000ff5eb}}, {{0x0004fbb34790cc07, 0x000a4397049f47ff, 0x00000e7e84e96f9b, 0x0005ec1e7862c0cf, 0x000834350bf1ce6d, 0x000ec8d7417a98db, 0x000aa86ceccd8030, 0x00000000000bcab4}, {0x00032ba3b5c44605, 0x000c04378b1fdff3, 0x0002189e90f61242, 0x0000faa8d60f86df, 0x000a3573271abddf, 0x0008f8032987583d, 0x0003f6b0afe4ec4b, 0x00000000000b69d0}}, {{0x000f8df0532bb051, 0x000c5bd9a66d6010, 0x000c7470f77e12e7, 0x00051dfef38e9b37, 0x0005754fb3fba751, 0x000069b72a3348ae, 0x000faf1218fa8f13, 0x000000000000835d}, {0x0007a4c220543f04, 0x000c02121a98ebed, 0x0005ec4ceabea5d8, 0x000a4be1a1eb6eea, 0x0002adeb3ae51b23, 0x000ea2b45b5c48b9, 0x0008eaeebd305ded, 0x00000000000c3719}}, {{0x00055d2a529f419b, 0x00062f73471b59c9, 0x0003ecf010a8f9e8, 0x000497dae082cef5, 0x0005c3e563bc57cb, 0x000125f95dfcbf2b, 0x00001922149c0fd1, 0x00000000000425bc}, {0x000c9ac134356e8b, 0x0000e049476de7aa, 0x0008c62ed440f124, 0x000c62d1256424f6, 0x000541bc66fa56c5, 0x0006ada140a118ee, 0x0008c50d8e9ff829, 0x000000000000134f}}, {{0x000b2c8bea306a01, 0x000b1d0960bd7257, 0x0002ca4efc9832f7, 0x000cc77a98509175, 0x0001e5f81554975c, 0x000cff2c8b41bd53, 0x000be3bdf8ab57c8, 0x00000000000f5822}, {0x000ad597c5610627, 0x000ae1f0ac0e6f99, 0x000855b71125b2a5, 0x0008b82e3cc86ac3, 0x000d2b2beaee22bd, 0x0002617ffc43bde8, 0x0000968168781e41, 0x00000000000b7ee7}}, }, { /* digit=42 [{1,2,3,..,}]*([2^168]*G) */ {{0x000956a7f54f949d, 0x00074086945790c5, 0x000771ce236fcb82, 0x000b0c6000575064, 0x00080b09adeb2c04, 0x00081474f468be6e, 0x000cce2f3bf32b6f, 0x00000000000a712c}, {0x000c24bf8b416a6b, 0x0004c292cee41c19, 0x0008e149d7276386, 0x000a66156f47b2ac, 0x0005840b5d1be54d, 0x0006e8cf62ca7683, 0x00053eb52adb6a8a, 0x00000000000dade1}}, {{0x00026c98ae834331, 0x000b365f7d2c0d6e, 0x0004cfcca31f7dbe, 0x000634c986436f32, 0x000133356165e268, 0x000c7957d6334d8d, 0x000983f17164269e, 0x00000000000b8093}, {0x0008676a1037657d, 0x000d9edb1fe5cc2a, 0x0001cd1de0787da3, 0x0005f4da691b6657, 0x0001e1e2727e746e, 0x00027b0296117129, 0x000197bb4aa8f16f, 0x000000000007f42c}}, {{0x000a6e4b3ca52862, 0x000cf2af8bdfa5a6, 0x000675c2d00d6d96, 0x000d5ced7046d2e5, 0x0007d545fd33d57f, 0x00061ffd75ea025f, 0x000242e2ccb6f431, 0x0000000000009406}, {0x000194e235777423, 0x00019f3536d60805, 0x0005fe57dd0b2a05, 0x000b06a5cc554450, 0x000f9a9e2a66fd15, 0x0003dfd0261b0feb, 0x00051fdc3c057665, 0x000000000000a8ab}}, {{0x00014e15511a3745, 0x00067fe19901abc4, 0x0000c6f09a808e87, 0x000012556c4ce5cb, 0x0005938c89ab92fd, 0x000a587b123172d6, 0x000c50a71f8a33aa, 0x00000000000b55c9}, {0x0009dec34d6b29ab, 0x00056ec005f6a241, 0x000b67510d45fff0, 0x000d67f9e26361fb, 0x000321389c2598a4, 0x000ffbcee7f0a2b2, 0x000888d158820795, 0x000000000009f36a}}, {{0x00065f3227de5d3c, 0x0001e5ffec1d7642, 0x000dceb00d947f3b, 0x000844c649c850b5, 0x000610fa337dfbe3, 0x00080773d450263e, 0x00066c44f7c8f402, 0x00000000000e8969}, {0x0009e0325576575b, 0x000a42587f475435, 0x0002c020daa3c5c5, 0x0002f667071543b1, 0x000e06577b749e90, 0x0000bee1303398aa, 0x000cec030926d691, 0x00000000000ffa92}}, {{0x000298023770357c, 0x000dae4ee3345cdf, 0x000943bb20278bd9, 0x000ca667ce118490, 0x000dcb69c7ead817, 0x000680afeda222cd, 0x000ca874ac74709d, 0x00000000000d9596}, {0x0002187a0dd3835c, 0x00082dff57da7e9a, 0x0006d7aa1a2ea94a, 0x000ba28b7fbc1b01, 0x000c13d4ed0f71c0, 0x0003a2ef260faab1, 0x000dff6fbe3567ea, 0x000000000004e577}}, {{0x000b9f236346df15, 0x000f89b758b50c99, 0x00075b638b06df34, 0x000b3c39ee88a784, 0x0001105e1ec04669, 0x00088ea133f36a67, 0x000aadd0f30e5d9e, 0x00000000000baecb}, {0x000d89dcc4fedb34, 0x000d3ec65be650a4, 0x00093dd7d659e073, 0x0005d29942ce52c4, 0x0007d3ce28d4f719, 0x0007fc9041220187, 0x00055e9c962aa1a9, 0x0000000000065c5a}}, {{0x00095e9750ada30e, 0x00094eccb421e7ff, 0x000dfa5cb406ba75, 0x000da9e05a53972f, 0x00007bc99fead344, 0x000f77bf53a8035e, 0x00078ae0214485c0, 0x00000000000e54df}, {0x00053ac771ed9aaf, 0x00027def45af5dcd, 0x00024afc33d18821, 0x0007db1c337e0181, 0x0006b84671d5a9b1, 0x0007d696d026a4f6, 0x00022a606142343b, 0x0000000000081cfd}}, }, { /* digit=43 [{1,2,3,..,}]*([2^172]*G) */ {{0x000d2a53b2756567, 0x000f3feb984b33c0, 0x0004e95d9895327d, 0x000f97e3ca0a9a03, 0x000dacc000ac177e, 0x00040f51a76d4796, 0x000810bad0fa6eb1, 0x0000000000006ebc}, {0x000c76db6b103c54, 0x00004f89eb78f367, 0x000ad3bb031162c2, 0x0009cfbb25e9d1c3, 0x000fb4e7aef3e2b2, 0x00067e8459388ea8, 0x0006d7ee606c12e2, 0x000000000009f580}}, {{0x0008f59540514451, 0x00028cf947c06046, 0x00062665be2e4fbd, 0x00015c05f1835ca3, 0x0002d8c79d90d001, 0x000b5f791df08415, 0x0008cdc0c3a6846d, 0x00000000000749b1}, {0x0000ce2ed12d25c3, 0x000d8d314b7d4a22, 0x000dfaf9b4508139, 0x0005af06855a9438, 0x000ee9d02ab997ed, 0x00038a5d0ea84ae9, 0x000eabb87e903432, 0x00000000000650a0}}, {{0x000c8f034ea36274, 0x00088357540ab419, 0x0000f5e32c760e57, 0x00073ac14d7fed37, 0x000fd186ee3d33d2, 0x000a7b1d9fef6b9f, 0x000bc2a94c207101, 0x0000000000050bc8}, {0x00013f9560f76983, 0x000e5c68959c999a, 0x000056367228b52b, 0x000a4fce6861310f, 0x0000c828330f7a73, 0x000f74fdb19bcac9, 0x0002f473e3b66f7e, 0x0000000000052d8f}}, {{0x0008b2d06a3248b0, 0x0008e58225208828, 0x00095368e614a61f, 0x000e45562fe86dbb, 0x00082dc5b2f11224, 0x000096555a8c8a47, 0x0004528a957b8dc3, 0x00000000000b1591}, {0x00063a60dfca11b8, 0x000161e563c57eb9, 0x00024a9e6e7bbb16, 0x0002de99462e7a31, 0x0001c2489214f8f6, 0x00074639c6b3dfe9, 0x0004b56c1d8fc421, 0x00000000000ef88d}}, {{0x00071f1bee09bff3, 0x0004a6eda384edeb, 0x0001d457a27a9c42, 0x000e6af10e01b58c, 0x000ae1175185c441, 0x0000dfcc6ac962bc, 0x0001b472d34d676f, 0x00000000000a9412}, {0x000f38c043747e7d, 0x000ad77dea14649d, 0x00065b52576e79ef, 0x000c09dd5d17db20, 0x000db45a6e94625a, 0x0001f8caf579edea, 0x000b8ea659282a84, 0x00000000000c11a7}}, {{0x000f9bf364d3e9eb, 0x000407d0850b3dae, 0x000e31cf311bd53b, 0x000f1f891cb75575, 0x00089d3b6afe68ce, 0x0003b46e427a6ba7, 0x000059f220f9c1f8, 0x00000000000f526e}, {0x0007512e159b9fa5, 0x00094edf3cccac66, 0x0003e3258b2c0e34, 0x000d9e98cc78d3e7, 0x000b5fa48469cc09, 0x000686001391bc40, 0x00073a22bcdcd522, 0x000000000007c599}}, {{0x0002ae0971dbb084, 0x000bd9de8555bad1, 0x000c9834d42cb891, 0x0000285de654b80c, 0x0008802be80bf17f, 0x000d823bf33998d8, 0x0006b64095923d5a, 0x00000000000e848f}, {0x000fcca2a1ce91f8, 0x00015c6e95017db4, 0x00048a3538b7e8ae, 0x0001be7a70558759, 0x0008441da4770c3f, 0x00048d4c2b652671, 0x0008deaba3b06f9c, 0x00000000000086f1}}, {{0x000d473962fbc397, 0x000b15a4a5ce3b56, 0x0003f34c786123b8, 0x000388e4efe9a313, 0x000aef9d074bd459, 0x000ab9cb03a45c11, 0x000566f68ab50b93, 0x00000000000ecd9a}, {0x0008303c4d104a42, 0x000f0bfb79b7f7f4, 0x000a0520b1df9755, 0x000aa21877390f14, 0x0005e314cfb54f31, 0x0008eab122de0c64, 0x0004f656d904f623, 0x00000000000ccb4d}}, }, { /* digit=44 [{1,2,3,..,}]*([2^176]*G) */ {{0x0007aa3a213de299, 0x000c93eb83a8707f, 0x000eb1f52edb04b6, 0x000c77a53abe4e9c, 0x000ebb9feb8257b8, 0x0006f922e0a14673, 0x00026cc0a6cbf7f2, 0x00000000000a32e5}, {0x000ec20f9c4de649, 0x00049ca417e66df1, 0x0009b8c741987bef, 0x0000e7a62e135de2, 0x000ea7ee82c72bae, 0x000776c74962bdca, 0x000feb573d7f6ae5, 0x000000000006ffbe}}, {{0x000a70e677b6f831, 0x000b9cbc0bb18f0d, 0x00037297c3884bb7, 0x000b350d38064428, 0x000c397a7602f62c, 0x000987d82e4d2f1c, 0x0009faa54bd48e43, 0x000000000004f0a1}, {0x000a1b4997cc48fa, 0x00005fa0c9a44d6a, 0x00012729fa8ce7f0, 0x0002c5b9cbd8d343, 0x000813d979568e24, 0x000da55fa1671eb0, 0x000ce5ccae388f40, 0x00000000000f376d}}, {{0x000f917fe9a26ae0, 0x0003ae54d92cd055, 0x000e0e9599c7454d, 0x0007fd2849f6143a, 0x000dacd0202d7c90, 0x00092d19abb11dd2, 0x000677a4913a701d, 0x00000000000cf610}, {0x000f3626f0aa0d9f, 0x000a3fff1e1d462d, 0x0009edea6495252f, 0x000f33a92cabf724, 0x000ce329d1adcafc, 0x0009a0e4cd571e13, 0x000f867626ad237a, 0x00000000000130d7}}, {{0x000f8196d845d3e6, 0x0002f8a89daef137, 0x0004ece7e9ffa3ea, 0x00023775b80bb4b5, 0x0002a45b362648d9, 0x0005bfe910a587c5, 0x0007d7daff503cc7, 0x00000000000116d0}, {0x000600a28d48ec00, 0x000916b5a471517d, 0x0001f4eebe019105, 0x0006cfc595abf8dc, 0x0009ed0391ce8f07, 0x000fcabd3c9de4ce, 0x0009edaaaad03ae1, 0x0000000000087b19}}, {{0x000b51557a9fd4ff, 0x00034b0641d0941f, 0x00049c97e60548cf, 0x0005b4b00d5ec6f7, 0x00015569d89ad12a, 0x000ac72089be1a11, 0x000df19c0566deff, 0x000000000007034e}, {0x00000817b5f1bb5e, 0x000e5636aeb6adf8, 0x0006c2164b0bbfac, 0x000f898734e9d301, 0x00095ccdc6bcf4e2, 0x0008a4f28daf7421, 0x0002c39d39249f60, 0x000000000008820e}}, {{0x000d9387d2303055, 0x000ac620248118e0, 0x00080c838dc206ab, 0x000eb38d7f033fdf, 0x000232646d6f86b3, 0x000dae596ee3226b, 0x0008e58c4825f6f1, 0x00000000000a5bcb}, {0x0000edaef1eabcc8, 0x0006f904a53484a2, 0x0007fa1deed27103, 0x000329f21d45f8ad, 0x000a06605546af6a, 0x000a93d14f20ad88, 0x000174cf7a0e9619, 0x0000000000091c97}}, {{0x000ae272638371ad, 0x0005559edd263abb, 0x000509e662e63add, 0x0000d304e7f07169, 0x000119b88200bf4a, 0x000da801e36fc0e4, 0x0002c791db560240, 0x000000000002c72c}, {0x0006387b3ebbf52c, 0x0000dfe960c2596c, 0x00093166fd89300b, 0x00080febccc1576b, 0x0005c3c88f475a64, 0x0007bd8ec72f4e5e, 0x00055e224e7e749a, 0x0000000000076314}}, {{0x00073d61157ae785, 0x000ab42c9fad4fc2, 0x0000e5d3107f2d93, 0x000c7fdb149854b8, 0x00002fc359eb0cf4, 0x000ec86034a7d900, 0x000e149ff0c3ea29, 0x000000000009b24e}, {0x000512a0eb94d71b, 0x000e0638c80999de, 0x000012d24a63feaf, 0x000e0f8a07ea5482, 0x0002aecdec3f2fb1, 0x00074025b1e580d3, 0x000164bbf895730f, 0x00000000000dd529}}, }, { /* digit=45 [{1,2,3,..,}]*([2^180]*G) */ {{0x00051b4cfaf372e5, 0x000b9fa2db519927, 0x000d4edc529b8ffb, 0x000af1d605917201, 0x000e782a09939f88, 0x000c710d31c5fea5, 0x000365e0fb15884e, 0x00000000000d32ce}, {0x00054592dfab29b3, 0x000d7d9f896aa46a, 0x000ce02cec631ef0, 0x000992dca6e73436, 0x000a6fd0c08b1b76, 0x0000f5c2376338fc, 0x00035bc3ea4c65a0, 0x00000000000b316b}}, {{0x0001e6b975664a84, 0x000aa14f962e38f4, 0x000c4a3248d485a4, 0x00011c079e777bf3, 0x000b4657c31b2c0e, 0x000494de3a1705ef, 0x00071802688fd23c, 0x00000000000412a8}, {0x000b58909626d6fa, 0x00004878fc7ace41, 0x000bfc58da0a4094, 0x0003c4c704b70c17, 0x00087323c0087c81, 0x000089f1a98553da, 0x0002914f63cec663, 0x000000000009655d}}, {{0x000f1be887dbd011, 0x0008384e5541ec05, 0x0002bbc7edd0f227, 0x0003ad69beaad3d1, 0x0000f51c2714e0a4, 0x000ea5b0c97dd182, 0x0007caac2b4cb457, 0x00000000000d1176}, {0x000327be0b446dbc, 0x000e318ccf36cb48, 0x000fe4f5fd270bff, 0x000ce43d8d292a8d, 0x0008d58c4ee79811, 0x0005c65a772c5fc6, 0x0006695bc0f0bed3, 0x00000000000cbbf9}}, {{0x00002ac6c24f6061, 0x0003810586ea68e3, 0x0007603f1b64b158, 0x000c4d7dfbfa352d, 0x00021e1c2291a42f, 0x00011760abf38c38, 0x0004d746e40ef60e, 0x00000000000dcb97}, {0x000c4f8f01f54098, 0x000f1755b105ba56, 0x0001f9ffa1baf4e7, 0x000d0b00945db608, 0x000cf2809e1ca630, 0x0006c95c5a160ac9, 0x00074f38fc1113dc, 0x000000000005d525}}, {{0x0001da84872cc14a, 0x0009a7eba3da615c, 0x000558d3935c6438, 0x0007d982b93d8b2c, 0x000c7cad1f758c91, 0x000ff150aca8fc6a, 0x0007fa5f581f19a0, 0x00000000000e0832}, {0x0005d538d28d5c50, 0x00038c774f18716a, 0x00051c30fd1c0854, 0x0006e9b8ad72b112, 0x000b917986cfce03, 0x00025cf9b463f9eb, 0x000feabe51632813, 0x00000000000dd7e5}}, {{0x000710a35bbc6ad8, 0x00005a4e9f29eaf6, 0x000a92c5e19e2d59, 0x00084e42993359de, 0x000f224d5aa30e21, 0x000132c484f96ce7, 0x000f5f0862e2003a, 0x000000000000f015}, {0x00066db2ab4fc1aa, 0x0007cab9d51492bc, 0x0009b538d3bdb7a7, 0x000e671c1fd96e3a, 0x000e71a703b24865, 0x0002add107baf4db, 0x000d3083dd6cf914, 0x0000000000098461}}, {{0x000b2da1393d8e42, 0x00051714c1d1ba41, 0x000ef78ff03cd88b, 0x000ea3a6951ac80b, 0x0000ac00c8377f23, 0x00024cc1b5c59929, 0x00062bf6efa2b3bf, 0x000000000001e844}, {0x0006a668e721edeb, 0x000069bda627d119, 0x000d91ed1a995ffb, 0x0007089c3b94ec3c, 0x000e3031699ad1ee, 0x0002b2453f75dba6, 0x000ed48ff75f7924, 0x00000000000289bf}}, {{0x000ac44be8741dd1, 0x0002fcda68a7d811, 0x000fb56aeb52d290, 0x000e2dadce20b92a, 0x000cfc69dca6483b, 0x0004f98917de1601, 0x000a564bec17aaac, 0x000000000008d479}, {0x0009255137ea7d35, 0x00025c623cb8d743, 0x0009f513ea4e4bb1, 0x000b7c030dcde621, 0x00073a1733fdda9b, 0x0002fac31f84ea32, 0x000449d7afb6c3e8, 0x00000000000d3897}}, }, { /* digit=46 [{1,2,3,..,}]*([2^184]*G) */ {{0x0006c80cb0000ec5, 0x0007da189f30f16a, 0x000d675bfc196669, 0x0009ec37d8da76e8, 0x0006c1ea7c10307c, 0x0008c62d4b3e1d00, 0x000b3ac15e20b3b8, 0x000000000000bff3}, {0x000b01f1748ea86b, 0x000e29e330eb12b6, 0x000af2a26953e630, 0x0003cb002e1eb2af, 0x000bf525e4d4157d, 0x000a3dff1638f297, 0x000051a20f833234, 0x0000000000045a9c}}, {{0x000b35a3033b3940, 0x00007fe9fdde8b8e, 0x0004a1bfc8bd5420, 0x00049acddde6f6e9, 0x00097e54356ca653, 0x00009f73cc53c29c, 0x000277ee15ad9457, 0x00000000000e5429}, {0x000bdd741f2769e6, 0x000d6f52035cdb19, 0x000b835933b3195b, 0x000b0ceca319bd4b, 0x000b6951fd8d26e0, 0x000c34d6f4e7eb67, 0x000b59ac3a6f4395, 0x0000000000000f60}}, {{0x000d7763c7959780, 0x000c02c47010c514, 0x000f6a495cc56b87, 0x000be509d930f6e7, 0x000d5f56cf045c8a, 0x0002f1fc16bcf875, 0x0007101f6456c006, 0x000000000005304d}, {0x0001668b6ef47661, 0x0006dd76452e46c9, 0x0004266da10fc06f, 0x0009fc89021bde74, 0x000f4babfae0b5ae, 0x000a61fd6505c6b9, 0x00025a99d943c17e, 0x0000000000059bf1}}, {{0x0003de8a392493e6, 0x0009cbd10b8bfc25, 0x00082fa94d1d5f3e, 0x000be5ec0c907818, 0x00071ad167ce9a18, 0x0008c1c563677f4c, 0x000275ccb254e2a6, 0x00000000000e2c4d}, {0x000250541623e5c3, 0x0003f44958cb1bf9, 0x000db2f9dd62ce34, 0x000a767a2ffdbd52, 0x0009b0b6c22d7445, 0x000c92b2e0e789c9, 0x0007823ff8b6565d, 0x00000000000eca98}}, {{0x0000ad4fec1eb621, 0x000c36618fcad673, 0x0002540e2f8dc71a, 0x00039947d7ce5530, 0x00095257f24b90ad, 0x00098768cbf8c458, 0x0008305a94992020, 0x00000000000bb6d8}, {0x0007503283325be4, 0x0007dfae8f1616ec, 0x000fc3e0aeb8a2a8, 0x0001ea9139ea0507, 0x00012e39e1d8a72b, 0x0009c7bc282229a9, 0x0008254153bf3e47, 0x00000000000c5541}}, {{0x000605d76cba7718, 0x000a6fadf9be90b6, 0x000490316f096fe8, 0x00024ec2f9953940, 0x000861203303cbad, 0x00089a4be6236a26, 0x000a82e4bafc3365, 0x000000000005e23f}, {0x000642137e1da447, 0x0005c8ccbc576c76, 0x0003f63011c9e098, 0x0002d5841df8dd26, 0x000914d31fcde6bc, 0x00026010bec24e1d, 0x0002f3acaaf13efc, 0x00000000000e01b9}}, {{0x0005639fc34e5a27, 0x000c7c52789bb2f8, 0x0006d4ce23fe7231, 0x000f95aacafbbfb9, 0x000dc7f6eb6d8b6d, 0x000b4c9d737afdcb, 0x00045357775bdd6c, 0x0000000000011007}, {0x000bddf07c5f1b9e, 0x000e3903e5ba1399, 0x000d7d2fc919a9a5, 0x00018932d7ac9e4f, 0x000543ce66a8046d, 0x000956410e2fe9d1, 0x000f7244b5beb4d4, 0x00000000000bb147}}, {{0x0006e03c443812f7, 0x0005c6f6a6104456, 0x00098182647d3e84, 0x0009a6ab51989e5d, 0x000f68f5b16842fd, 0x000f7fe671b60ce0, 0x0005a897324d8756, 0x0000000000067681}, {0x00061f269664533a, 0x0002a265ee993d1f, 0x000a90ce6a02c969, 0x000232334b4adb0c, 0x000e1e5a8d18e909, 0x0004f6456ddcd233, 0x000d9b3dc5b27c5f, 0x000000000007f421}}, }, { /* digit=47 [{1,2,3,..,}]*([2^188]*G) */ {{0x000b170252588bc8, 0x00099bfc40c30a63, 0x0001ef23d6587c46, 0x000b54dc027511d3, 0x0004cf3484ce4fd7, 0x0009beea5f479928, 0x000280655ab81106, 0x000000000007392e}, {0x000148f913baced2, 0x00084522e7b403b5, 0x000493599cdac0b8, 0x000b95877f3913fd, 0x00067dd525149cf1, 0x00008cbca3e06b92, 0x000529992e920e29, 0x000000000006d6ed}}, {{0x00097dff92ad4838, 0x0001e8a46c9112d1, 0x0000711ed277a798, 0x00064f15cf8e4ca2, 0x000a01cb3488d4ba, 0x000bd7ded01b3908, 0x000ae169b1fa5d38, 0x0000000000018b2e}, {0x000f3694f52a1f22, 0x00019619324bdbe0, 0x000d1d925851b48d, 0x000f42e925b3f6ab, 0x00095f7e4d11a397, 0x0000d9f0132169a4, 0x0002e5c0fa9a548d, 0x0000000000089d8f}}, {{0x0000115baf0f7c2d, 0x00040240239ae483, 0x000c7482d351827f, 0x0007151f58ec53e4, 0x000cc080d59ff9ab, 0x000f782f4d397862, 0x000d5873eee88536, 0x000000000006c1d8}, {0x000c16042c611b2f, 0x000f258bed3e5b15, 0x00036e097964eba0, 0x000c8ab8a482af89, 0x0009e746a8549044, 0x000a0548e0065858, 0x000a492538d1b926, 0x0000000000007cdd}}, {{0x000178ddffec9175, 0x0004c9c0d5230baa, 0x0004bce21493d0f7, 0x00090dd985154559, 0x000c8dbfb46a67df, 0x000757ce3223e8b9, 0x000296f39529a36d, 0x00000000000b4648}, {0x00000562605aa919, 0x000dc330749e8973, 0x000a3ffdafa653e5, 0x0000b3494083aa87, 0x000321e321c68c32, 0x0003e78921161f5a, 0x000ccc0980deedde, 0x000000000006ad76}}, {{0x0003725fda5a777d, 0x00086af9a69e965a, 0x000a3534516a8b8a, 0x000a77f3e52375ce, 0x0009a019a5932dff, 0x000238091ac65569, 0x000085d402f5c4df, 0x00000000000d3518}, {0x0004a37271e8fafd, 0x00007dcee2db4b54, 0x0006c1d813edf12e, 0x0005b6121bc49990, 0x000e68b9808d9cb1, 0x000d6ac5b40b34f9, 0x000b8a98de63590b, 0x0000000000039766}}, {{0x00069c8c3d7c7657, 0x0005171191261c8a, 0x000244a0eba69bbd, 0x000344bdda57f44c, 0x000ac4f0cfd2ad4b, 0x000543efd674b758, 0x000d063bc058a077, 0x0000000000056618}, {0x000a82ca14a01b7a, 0x0009d95107c74391, 0x000a3c4cfae47f34, 0x000af35e3f1d63cf, 0x000643ab87265dbe, 0x00056c6fd012029c, 0x000e304f588a4ea2, 0x000000000003e5d2}}, {{0x00081d2046b48f0f, 0x00043847622b5217, 0x000c2a7014a5d0be, 0x0009da7b82c435cd, 0x00025b73e01114da, 0x0008b37b399c8c43, 0x000ddab978fe55ec, 0x00000000000337d6}, {0x00034bf111412925, 0x00071e0d4ffda16d, 0x0003fc3275d2e3f4, 0x00062872913cddbb, 0x0004f67405be2a7d, 0x000a31060229afd0, 0x0009d6e372202e49, 0x000000000009fc21}}, {{0x0001a0d511e4c022, 0x0009173fa3508062, 0x000e92c1603f0953, 0x000549f58493d985, 0x000adc79f602f64a, 0x000512b84d9ceae0, 0x0001516569e37bd1, 0x00000000000151c9}, {0x000c6addaeefed36, 0x0004c075678c2066, 0x00015cc88eb8c3b8, 0x000dca3a57fb96a6, 0x0000223dc3ce6334, 0x00011e2770ed9082, 0x0008e274f9c3aebd, 0x0000000000079c0b}}, }, { /* digit=48 [{1,2,3,..,}]*([2^192]*G) */ {{0x000688b6fc0935b1, 0x000f5378205dd339, 0x0000b901357b7bc3, 0x000c06c682e00f2c, 0x0003114d5423dbce, 0x00052463ef2a145c, 0x000b0aa01d98747a, 0x000000000007d717}, {0x000d2bf78a72f39e, 0x000d29653bc4f4a5, 0x00051b32471fd3a0, 0x00043dcaf8e3f402, 0x0000e86fe16ef779, 0x0009ffdcf70774a1, 0x0005c96b62e6f1bf, 0x0000000000058874}}, {{0x000b3ac410563249, 0x000bc2a5f8ecef60, 0x000af14f01d834e5, 0x0001cedc59c4301d, 0x00010111d9989de3, 0x0000d5b951e0f40b, 0x000ab8d29d229f96, 0x00000000000d1dab}, {0x00033bacd39b8f1d, 0x000bd7b225cc8ccc, 0x0003c9f7b44c8f47, 0x00052a1f5fb06b38, 0x000f842b9081009b, 0x0002725128a575d3, 0x000cb7fddb48afe9, 0x000000000000b452}}, {{0x000dcfd459bff4dd, 0x00050ae10069e26c, 0x000e9f25bee973af, 0x000caf27ebaad0bb, 0x00073dd6119cbbe4, 0x000fceefe5907bf3, 0x000c7e0a723dff9d, 0x00000000000f7cff}, {0x0002a3a44c0ca01e, 0x000d17bc95fa21e6, 0x000c0e71f388ad82, 0x0007ecd27b3335bd, 0x00027b8d7d49316a, 0x00019058fbf08e67, 0x0009ea4b209f93c6, 0x0000000000059d8f}}, {{0x000cfbdc0726f5f2, 0x000ba167ec88a4a8, 0x00009c64d249271a, 0x000e2443877e6342, 0x000603462cb310f2, 0x0003afcee6321bf2, 0x000dcd1dbd10ee9d, 0x000000000002ca17}, {0x000667ac9826886c, 0x000d509465265738, 0x000151279a7a2541, 0x000b0f95e1c59136, 0x0001757d3a630043, 0x000def1e0a09b94d, 0x000d41533956529f, 0x00000000000d4fed}}, {{0x000c29ae93761a8a, 0x0008a3459097559c, 0x000f79e8fee087bc, 0x0009a286ec406ef0, 0x0006fee5454dcc93, 0x000257f708d21427, 0x00085e66a0e1a56b, 0x00000000000006fb}, {0x0006c4387ea9f222, 0x0000ac44f9df22bc, 0x000c5644721083d5, 0x000a8224fca1a819, 0x0008f3ed85bf5894, 0x000899b5b8586e41, 0x000371d494dfb202, 0x00000000000ecb8e}}, {{0x00094e8a6ed08358, 0x000cf690c0cfe457, 0x00092e98638a5e98, 0x0008042204d98a6b, 0x0005bad2eb082250, 0x0005823eec87a97f, 0x0003f6d307c59ed2, 0x000000000000df8b}, {0x0002a9b6fd1bc660, 0x000e9280ae343343, 0x00077184e86c10ae, 0x0000e5a24d04e396, 0x0007309830fcea93, 0x000afeebc0269d9a, 0x00002d41dc8f0ae4, 0x00000000000f14ee}}, {{0x000ef795d8c64486, 0x00026efca7f7acdf, 0x000411f7c32b0a9c, 0x000b87fe57d08e0a, 0x000a7d9a1967c9ea, 0x000c2749248c01c2, 0x00063911c97ed97d, 0x000000000001cf1f}, {0x000b6334379af438, 0x000d1541f8c0d49b, 0x0006f782375b1fd6, 0x000935ba6be190e1, 0x000764494b4e9806, 0x0003c00b6ec6c5de, 0x000f15f04e2d4cb8, 0x00000000000c0b84}}, {{0x000c9d81a70917bd, 0x000702e75a26e455, 0x0005bf4870175e47, 0x000d057ee7d8e4ba, 0x000d8994f44953df, 0x000538367b959110, 0x00029cb4a16596bb, 0x00000000000ef82f}, {0x000ea0c85d7d05e6, 0x000305a7642ffe63, 0x000b9d7a5d2d391f, 0x000b23803a4184c4, 0x00020f7fcd62c7ea, 0x000a8a0c660c67ef, 0x0002b041e05799df, 0x0000000000004d35}}, }, { /* digit=49 [{1,2,3,..,}]*([2^196]*G) */ {{0x000ffb708a3b5e85, 0x00030c97c01eab92, 0x0007510b2d7953a7, 0x000ce807fa7d3c2a, 0x000e81060874dba1, 0x0007eeead69e6f96, 0x000f3d6e3e0df74d, 0x00000000000b0c87}, {0x000317c5146f214f, 0x00028c55ae3dbb43, 0x00014b4be1d3dc49, 0x0008c591de7860a7, 0x00066e546731a600, 0x0001e45d48202f8b, 0x00015a652f2d07aa, 0x000000000006df54}}, {{0x0007d6371007dea2, 0x00049041c706cbe5, 0x000dcf6b55c23258, 0x000cd27839e9d5ae, 0x0003bf3c4c067dc4, 0x000b7bd22dfc9db8, 0x0002da85b8094138, 0x00000000000d0f4c}, {0x0000b16d9a334a33, 0x00092d7b340062c0, 0x0002bb5502deaa2f, 0x000b2c2752366864, 0x00010113a85fa340, 0x000b327045ddd055, 0x0002ff7dfc7ab29c, 0x00000000000dabf2}}, {{0x000a8373e5c690f8, 0x000ca2fbce9bdf20, 0x00049076d1995e9c, 0x00045939f4cbaf1b, 0x00092574a3bd48ea, 0x00092c39a56c5400, 0x00034384a39630e7, 0x00000000000eef81}, {0x000361503c11fa79, 0x00095f996760edb5, 0x000c1bbc8ea81e13, 0x00012e6966d70279, 0x00052e6f7c63a0ca, 0x000d13ead92a6d5d, 0x00068146809d269b, 0x0000000000067aac}}, {{0x000cf4e4cd35d7a3, 0x000a13fc9b3cedea, 0x000ac33c871e844f, 0x000a58afe1ad536c, 0x0008cb39149f2003, 0x000edf470cec4be3, 0x0005194d578c99bd, 0x000000000003a356}, {0x0001980c5865f55f, 0x000607a762f2732a, 0x0003ce874c8a141c, 0x000817f270c508e9, 0x00049fdb29c8dc0e, 0x0002711d35a7be20, 0x0000c2fa1a0be3cb, 0x000000000003786a}}, {{0x00065cdb1cddc024, 0x000c41d0af6b5128, 0x0006106e0f532684, 0x0001951b1ea8fc4c, 0x0004b1fae4826764, 0x00023477bc0b9006, 0x0009ce7012642f66, 0x000000000005bf01}, {0x00001d44438309f3, 0x0007fca1f46757f4, 0x0004d56451db59bb, 0x0004ef2d3868de95, 0x0001044e0c189c03, 0x0005e38c30533d92, 0x000053ba6cf14ecb, 0x00000000000509d7}}, {{0x000af6aee4d4a85d, 0x000c0e164268de02, 0x0001633ba7cb9816, 0x000979478ab17f45, 0x000e0179ed0e734f, 0x000a2686746d468d, 0x00085d7e68f006df, 0x00000000000e3d04}, {0x00073699ad94d8f6, 0x000c30913a1d74ab, 0x000e2aa1b6d33ea2, 0x000a79e49eadd08e, 0x00017dd8f954eeb1, 0x000bb26d0433f5e4, 0x000e2970a6281430, 0x00000000000ff5e8}}, {{0x000235f9cfa08aab, 0x000eb6a352b56ce9, 0x0002152b2e478d04, 0x0007c7a240e6dc62, 0x0002d313b4a9ee1f, 0x00001a40585d5be6, 0x000d5a1522c5d25c, 0x00000000000960af}, {0x000459bf66d63a1d, 0x000e4a3cb77f327b, 0x0001a15093d3f2d2, 0x0000c7d3b93fa9e1, 0x00013c0383ad8409, 0x000f7a220c77f1ee, 0x000bfc461c93b776, 0x0000000000004ac0}}, {{0x000fd3f75cd14c88, 0x0002a3c7d6b63ea7, 0x0002b345f341120e, 0x0005d20aa0eaa1ec, 0x000fc0eab4908ed1, 0x000d9f260e944ad2, 0x000ba371525aa1f6, 0x0000000000016146}, {0x000bd29ab6e83fdb, 0x00068f94019075db, 0x0002a02a4fd970a1, 0x0001c37cab1060af, 0x0000c8cac96f6a4e, 0x0002466ec357fe4d, 0x000e7097a8b8ab6a, 0x000000000009c01b}}, }, { /* digit=50 [{1,2,3,..,}]*([2^200]*G) */ {{0x0007eae876f30205, 0x000645b0b5d68b38, 0x0002f6471178cf56, 0x0000a4a404a3458c, 0x00059f467b6072ad, 0x0006348091de8e25, 0x000178a4b3570590, 0x00000000000706f0}, {0x0007cba07f8d2545, 0x0006d588d21aac4c, 0x0001bb1a8ee3a06e, 0x000e73d241bcd915, 0x00022facc7ccf4e7, 0x00025d2a0b8d8a1d, 0x000608483c35a71d, 0x000000000001ef9f}}, {{0x0009cd91f152b14c, 0x00034a704015f319, 0x000a64fabfbdef40, 0x000301f2ccb94180, 0x00046f00d8aa697f, 0x00038a0173ee8776, 0x0005432b5afaf881, 0x00000000000832d7}, {0x0002183eafee3abb, 0x000d627c27ce1884, 0x000735007191c91b, 0x0005ac75b752008f, 0x0001e84fe5f192dc, 0x0005929cecf382e0, 0x000ffa90e034197d, 0x0000000000015ca3}}, {{0x000596896506329d, 0x00058cb51f038efe, 0x00073c05f41ddada, 0x000fafab41fe1a74, 0x000da719f25493c8, 0x0004f5cde6297701, 0x0005426e9165bc64, 0x000000000000c11c}, {0x000368f61fe7d95a, 0x00098a2564809894, 0x000e829acda88407, 0x000592622b1d1be2, 0x00026ecdd041286a, 0x0009f952486a3d75, 0x000b0f4b867e0a64, 0x000000000000629c}}, {{0x000259f3facaa9bd, 0x0001d11dd860d21a, 0x000b8c19c604b970, 0x000aff635c019302, 0x0001e3a4a900d4f8, 0x00078c8ba96a727b, 0x0007c41426daffde, 0x000000000008d152}, {0x0001e6f4fd354295, 0x0004a0c0d5233cfd, 0x00066c04a38eba93, 0x000bee43d914fb41, 0x0008f3ba26a64828, 0x0004eb26f8324ea3, 0x0007bf027590f3a9, 0x00000000000acd95}}, {{0x000a71b96f713d9b, 0x00013f4f668435ae, 0x0008fef0f35f5919, 0x000e86e7365712f9, 0x00088a822bc0f607, 0x0001299b3d588229, 0x000b1a2cfbd63ac6, 0x0000000000067167}, {0x0006f5a47be411d6, 0x000b0750f673f622, 0x00032c38df6a058a, 0x0005bd169123c758, 0x0006eab99b375e6d, 0x000aec6a36a93d1b, 0x0008186ef4f7e68c, 0x00000000000cf3ed}}, {{0x0006410726f50135, 0x000fd959353be170, 0x000b4de98d5dc91d, 0x00026f799d7a4f4a, 0x000e52fe4b656a48, 0x000038573ab146ec, 0x000e8494fc21d735, 0x00000000000f4d56}, {0x0006901ebf8c490f, 0x00093e15ca04c71d, 0x000ef178dcf47997, 0x00079244f21a9114, 0x0009dcc76132ef7e, 0x000e890482eecb7e, 0x0002c55b484745db, 0x000000000006e43a}}, {{0x000b8d876ab51a4b, 0x0001af92b3072f8e, 0x000d8f5d67f2d2e3, 0x000d5edc578e3a39, 0x00029587fa22e51b, 0x0002eba85efda70d, 0x000530cfec17089b, 0x00000000000af7ba}, {0x0004893a5eb2bed8, 0x000bb5ac155ae396, 0x0009a3394a2b6335, 0x00086c2c38718a82, 0x0003d63745b7280e, 0x0008a79aa9d12de7, 0x000bf70e8ea855bf, 0x00000000000bd705}}, {{0x000260c123f30563, 0x000c53ede2484b68, 0x000620a80e97a435, 0x0009e93962a667bd, 0x000b130f2cea5606, 0x000366a66c931266, 0x0003b14bd6a6fca7, 0x00000000000aa5ac}, {0x0004e3f2adddce7d, 0x00044a025d0ef29e, 0x00075ab6560ff06a, 0x000927f2b3057f30, 0x000a1499f8844809, 0x000b9a653b001c10, 0x000d05309d141c30, 0x00000000000bf659}}, }, { /* digit=51 [{1,2,3,..,}]*([2^204]*G) */ {{0x000d68f9d41abcc8, 0x00016a6c328ffdb0, 0x000797038aa63e5d, 0x0007d39063de7eb8, 0x000710daf9bd691e, 0x0008b5d7a998df4e, 0x0004b8c7085b9e71, 0x0000000000016b3d}, {0x00019da01ecaa2a1, 0x000494dfce693daf, 0x0007011a8e84696a, 0x00004bf4491fb345, 0x00014552451c2c19, 0x0005e5e407c1bf11, 0x0003726562cc2c3c, 0x00000000000fe0e4}}, {{0x00073ecab0b13cfe, 0x0002484c3630b425, 0x0005d7cee5256fab, 0x000125ff61af001c, 0x000fbfea35255abd, 0x000e0cb6e69bca56, 0x0005a6384af19900, 0x00000000000d0047}, {0x0001438f80a7fcba, 0x00090edafde48dd9, 0x000a30b2135b9aaa, 0x000f97a6c8ffcca5, 0x0003e5a9cc5cf14c, 0x000104e054d6cec2, 0x0007c1b0d678f88a, 0x000000000009fb52}}, {{0x000cf7bdfab400e3, 0x0009e8618ffa6a37, 0x00041539f0cbda9a, 0x0000d744f61edff9, 0x0009eb7a476f5b1b, 0x0002ee99b33df67d, 0x0002cc7f1a767ea9, 0x000000000002223a}, {0x0004324c9cd0a9f1, 0x000f616f376f2586, 0x000c0794e16b9222, 0x000516ca58765df0, 0x00062260ed6b8dc1, 0x0004b29ba8934082, 0x000bba060eb0afcf, 0x000000000001d252}}, {{0x000bb25431b5857e, 0x000160d6cadbf906, 0x000790df51943fb8, 0x0003c734ab19507e, 0x0005660086b33b43, 0x000eb0f434fc5340, 0x00058d770ae903a1, 0x00000000000f6b5b}, {0x000dc8bc8bb4bdd2, 0x000d6e206e14147d, 0x00079b5341d6e69b, 0x000ca2f47449e081, 0x000639fef8e1cfbf, 0x0006fc80cebaef25, 0x00061b959e37b8c1, 0x00000000000e911d}}, {{0x0006b0541df5b61f, 0x000b0014a0907c72, 0x00060742ec5c6420, 0x0007c4dc999acc04, 0x00075e7ab1e3dbbb, 0x0008fb11e01b7710, 0x0005c2a33fefbfcd, 0x00000000000c0b8a}, {0x0004467ba7747f4b, 0x000ec774dc2669d0, 0x0007562d1fca7010, 0x000dc694d9c84626, 0x000a1e772c5f5ac4, 0x00083fe91bf6e002, 0x000dce4922120e0b, 0x000000000003efba}}, {{0x000263fbc0d157fd, 0x0005bc483d4b1827, 0x00037dfadf4ae121, 0x000df6fcbab1fb10, 0x0000f6cdfc0c5165, 0x0004320fceb28437, 0x000e80ab565c0099, 0x0000000000062133}, {0x0007401414422436, 0x000ee7850cda5472, 0x0007bd0ba094b0ec, 0x000805cc2c82eddf, 0x0006cf244539d14b, 0x000dbe92dcb5468b, 0x000f1e97d43ee825, 0x0000000000089fb8}}, {{0x000a494639f26e1a, 0x000b5421afbe0092, 0x0004dc6db28bf654, 0x000cf4db1a2705ad, 0x0006d128bcd556ca, 0x000191ad86a3a413, 0x000d242411c4b866, 0x0000000000015b45}, {0x000845fec1268b55, 0x000a74cc82459052, 0x000da0992b42bc3f, 0x000bb1c69f6298e1, 0x00031933fdb59c88, 0x0001308c3fe567b0, 0x000dfa8a6aea7188, 0x00000000000a2f0a}}, {{0x0006a4d1fcc1ad65, 0x000d2d7bf2ac5a3e, 0x0005e362c26e5671, 0x000abaa9afa97632, 0x0004b62b36ab162f, 0x0006a84e97b7f166, 0x00043d77b9f79729, 0x000000000007dbd8}, {0x000519c3add29e33, 0x000fcc6e9c1e11fa, 0x000ac380a63f4305, 0x000a93d3bfa90c04, 0x0009d050e46afa7f, 0x000c5625655846fe, 0x000a65473b9a0d35, 0x000000000002b656}}, }, { /* digit=52 [{1,2,3,..,}]*([2^208]*G) */ {{0x000f0e1b25d4e4dc, 0x000a6372798f002b, 0x000537a488c42515, 0x000f9a98a1e25677, 0x000ce70391c85e64, 0x000f024585870254, 0x000bed2def81a341, 0x000000000001d087}, {0x0002a1629bafa8b1, 0x0006d3557d07cb43, 0x0009543a3877e0bb, 0x000c5675f73ba510, 0x000b9c7c670608c8, 0x0009850725309050, 0x000e962ab67da3bd, 0x00000000000e5df4}}, {{0x00057ab93a62b1b3, 0x0004b7be81fb0ec2, 0x000d385405273506, 0x00040e27a8d16791, 0x000ad520811ebb3d, 0x000f65d231806c67, 0x0003d7add4bb6686, 0x00000000000e20e2}, {0x0008a96c64700a7f, 0x00088208b470000d, 0x000907fb1a1c5c32, 0x00064f8121c37e26, 0x0001a598efbbbd39, 0x000eef966d35ef30, 0x000e46bd76a276c5, 0x000000000000af64}}, {{0x0007b8ba2901e630, 0x000573f40494a69d, 0x0001d7e86c246f17, 0x0003360c9e634b1f, 0x00096ab166bbacc3, 0x000fdb67e6cf72ff, 0x000736477d8f2db9, 0x00000000000cb644}, {0x0000821b2e82caf8, 0x0007549454e1ad4f, 0x000486f6c48cff7d, 0x0005f0be8e7b06ec, 0x00047dc40b498042, 0x000ed620b862df52, 0x000a648ca7d7c812, 0x000000000003c45b}}, {{0x000d7620f273aa67, 0x000e1169474a1e10, 0x000056ab42590c74, 0x000de922ede425c9, 0x000a6df8a8908589, 0x000a8b8e350e03fe, 0x00091a0d8a5c1c4b, 0x000000000003fffb}, {0x00026981fafa18b5, 0x000f721cf05437b0, 0x0007e513859293da, 0x0007eaed0962c826, 0x0004213f6004c323, 0x000148b6b43d6ac3, 0x00080a45e619b2d4, 0x00000000000ea5fb}}, {{0x00014768f5f99aa5, 0x00067314ea217285, 0x000017c8fd29a716, 0x000fb46a63ea8fc5, 0x000890d84e5b0902, 0x000e49b8a925a6dc, 0x000be5e2e74f9c14, 0x0000000000007d45}, {0x000cae18673b6270, 0x000667b768d075ba, 0x00089b2a5deeff6b, 0x000223360d5b216a, 0x00080a7386f475db, 0x000c47746b132b67, 0x00031d7f933fd580, 0x00000000000fbaa6}}, {{0x000ee5b308cc45e3, 0x0002faba967ac481, 0x000d29b2fe96bd68, 0x000c601ef5f681db, 0x000ffddc580fe033, 0x0007572d85c34f77, 0x0004d0d30f5b66f3, 0x00000000000da20d}, {0x000030e8bcc549d9, 0x0002cdb2310273e6, 0x000ec784d2efa81a, 0x000a33f7899cd7f5, 0x000fda29c3821cce, 0x000e14ecf0f4e0a7, 0x000839c6d7c5f32b, 0x00000000000d9caa}}, {{0x0003fe55b28c2fec, 0x0007ba884edf1601, 0x000775572e4af6c1, 0x00004152d7852a27, 0x0007f26efb4c66d0, 0x00022f8cb34732d7, 0x000ff518b3ef8e29, 0x0000000000018bcc}, {0x000ec4cab3e21461, 0x00004a219cb1deb6, 0x000868a49e96a154, 0x00099e1d90760ec0, 0x00078a94df2ef0af, 0x000058f89e6fe194, 0x000d9764b5dfcd04, 0x0000000000023d21}}, {{0x000d7944d758c20d, 0x000209a8580a957a, 0x000f955204f37a28, 0x0000970be07f7827, 0x0000712f7b7cb4da, 0x0006a7b970ac2a26, 0x000f62c9b8ee8443, 0x0000000000011fb2}, {0x000ff5f68230c1a3, 0x0002a5daabed96f3, 0x0003bdf181469c85, 0x000b5b7d96cfb8e8, 0x000344d9e84382d6, 0x000e7da3c4d7d0d9, 0x000253fa2a9ea991, 0x00000000000d531b}}, }, { /* digit=53 [{1,2,3,..,}]*([2^212]*G) */ {{0x0003b2a8a65e5b7e, 0x000424cc41f278dc, 0x000bf1d7ec4af5a5, 0x00066640fa1ca255, 0x000b91e5edaf7053, 0x000d3de14eeb40f3, 0x000c43cdf98235f1, 0x00000000000ff018}, {0x000927ebce051283, 0x00074aa3228e6dee, 0x00043f750dae9462, 0x0000425650b2dab8, 0x00026d875f1790e9, 0x000e8a46ee4a8cad, 0x000fb5c212029c9c, 0x000000000005ed7c}}, {{0x0007539a8f390740, 0x0008eadb5966f40b, 0x000e0b7342eb902f, 0x00073e244693a961, 0x00055982bbd3a76e, 0x0002ca13214da743, 0x000e7646e982cd5d, 0x0000000000024938}, {0x000cf856b36cb844, 0x00029749206b2571, 0x0006030c0c47215a, 0x000d1567025bb7cf, 0x000e19555c9ebee3, 0x0001639bae23f0e1, 0x000bd00dec383775, 0x0000000000005d43}}, {{0x0002c235491635a5, 0x000e4e4e52e86121, 0x000459dc25e36e9d, 0x00051bfb49f2b393, 0x000b3f8097cf73b9, 0x0008fbf057b6cb7d, 0x0002119dfb8d0b32, 0x00000000000ebce6}, {0x000c890c36814c6b, 0x00007a31a15235a7, 0x0009c26d4a535440, 0x000834e6b5638766, 0x000d10ee5a281d22, 0x000aee4eafd91b30, 0x000a763d7a282d59, 0x0000000000073300}}, {{0x000f6efbfb5bea3a, 0x000f878b5c14b0f6, 0x0005485b973e6dbd, 0x0002ab209e1759fd, 0x000db4b2f68cffa2, 0x0005be7f45a86263, 0x000f6d71e77c516b, 0x0000000000019844}, {0x000dc7fe7c7337ad, 0x0009d2519d0058c1, 0x000edd3b9e6ca5d6, 0x00074a685b3c2a9b, 0x000fc294f4492c6d, 0x00069fb469306f68, 0x000886552e77c22c, 0x0000000000010bb9}}, {{0x0001ae09a4f32c66, 0x0007beba7daac862, 0x000767fe0f73dc31, 0x00018f885bdbc832, 0x000094d43909985c, 0x0009e108b86555ff, 0x000313b0b1b2b653, 0x00000000000c0bf1}, {0x0003b62754d457e4, 0x00021bd4777c10d3, 0x0007d7f58d2fb40a, 0x00057374a27f1ddc, 0x000eeaaa58ab85bc, 0x00076fac29a8ae24, 0x000377161cb2f5e8, 0x000000000006636e}}, {{0x0001f89428b5c457, 0x0007f1674b959a73, 0x000b96ebf7106c2e, 0x000a32dc67c36488, 0x000368d720a63962, 0x00057a5b24949617, 0x000c0f4e81df85a9, 0x0000000000053123}, {0x0003624d70103a1a, 0x0003f5091dd340e1, 0x0000c9fe10861f33, 0x00020f52c119dbe8, 0x0006c94d609a5e77, 0x000dccd1fd584ae7, 0x000c6e476c63ba86, 0x0000000000032508}}, {{0x000df9bca60288d5, 0x000016bbf77cab44, 0x0000fa9d18796041, 0x000eb1a2b9febf8d, 0x0001a25330ce357f, 0x00091799874240a8, 0x000f5c7a9ab575b4, 0x00000000000eda3e}, {0x000c7149276e2420, 0x00036360410d2e37, 0x0006d4d0d5e12db0, 0x000b466cc381b581, 0x0008247a49047bae, 0x000c58130024a98b, 0x0006d26e70b4c3e3, 0x00000000000ae8a5}}, {{0x000d9a7dd453995c, 0x000393313a9d4705, 0x000fd95bba01fcaa, 0x000ef915e4dd5cea, 0x0003c565dd67c0fd, 0x000ed05ac902a2a9, 0x000ae9d8eba4dc7f, 0x00000000000e157d}, {0x00019071237f3ae4, 0x00006d655d0b3ced, 0x000513db82a990cd, 0x000525a0652872b6, 0x000fe68c0ddb5b7e, 0x0001cb31caf7968e, 0x00071e2ec02930f5, 0x00000000000f2be0}}, }, { /* digit=54 [{1,2,3,..,}]*([2^216]*G) */ {{0x0003b3ac56ccd2a3, 0x000649b23ab4e3e0, 0x000d023509576972, 0x0009e51e798edf99, 0x0009307675c7dbe9, 0x0008c0fb63854744, 0x00037223ffaf5562, 0x000000000001698c}, {0x000420dd9073adb8, 0x000d039f45a56f2d, 0x00011e9a2cdfa00e, 0x000079e4af138fd7, 0x000a2ee4ecc02a89, 0x000bbf92fb86371e, 0x000c51076d256a06, 0x00000000000ae3c4}}, {{0x000340cb6908d50e, 0x00092ba2e95430b3, 0x000660e7e985a29e, 0x000b95145bdc19ee, 0x000e382e77bdf94d, 0x00020b29a951d00a, 0x0001f19940a5fbb2, 0x0000000000058fc9}, {0x000d804932dbc0b5, 0x000be682e42eaaa2, 0x000400a2efd4aee0, 0x000810016294d055, 0x00032e326d68be15, 0x000e64fceaea13fe, 0x000a8ac0dfe1ef15, 0x00000000000b8237}}, {{0x0004480f8fce3f16, 0x000a7e59b80017bf, 0x0006c7396aa46dc8, 0x000172a5af5b47f5, 0x0000160d7e8d8799, 0x000f9a549f72c978, 0x00044a1d1ce972b2, 0x000000000004857b}, {0x000d15fb2758caea, 0x000542545bdd6f77, 0x000984fe91e9b1e2, 0x000343a4e23c0644, 0x00091d1fd9cd5a60, 0x00070b5b3986779f, 0x0005a35bd5611b35, 0x00000000000f9d76}}, {{0x000b72123cb1cd13, 0x000e76ee65a0886b, 0x00081e4e332045b1, 0x000cc382876e523b, 0x0006d3bf53aac4a2, 0x0007f290cab7aba2, 0x0005bd5bf00871db, 0x000000000001ee6d}, {0x000bcea869ddbc32, 0x000334cafb21874b, 0x000bcaaf9d600f4d, 0x000785520b281cd0, 0x000e64d9c65ea1fe, 0x000a0e67be457198, 0x00068aa3d1a6d0c5, 0x0000000000090cc4}}, {{0x000450a44e08b4d9, 0x00014cb0a365753f, 0x000b82633a02b2b6, 0x000210997ed887af, 0x000f30d9b2970b85, 0x000fb9c745fec3e1, 0x0007854ce4149f10, 0x000000000008cbff}, {0x000dc4bd785a06f1, 0x0009f81b0d7b3b6a, 0x000116390fc1ac37, 0x00021de2b841eb88, 0x000ad83c22e6aec2, 0x000affe9162c7d86, 0x00081d5504dcf885, 0x00000000000f4454}}, {{0x000578651af84c0a, 0x000e0d4ee3f7f52b, 0x000cec289c787837, 0x000ee1363ebab5bb, 0x0007005ec2374c0b, 0x0002fb00670e32d7, 0x000899302fc73dc5, 0x000000000008f159}, {0x000ba114d96a8216, 0x0009d42a5478e2d1, 0x000e66d84b639b08, 0x0004970c8378f0e8, 0x00058e2c86c5042c, 0x000c7c76770c1957, 0x0003a861a95e6884, 0x00000000000d6fb4}}, {{0x0000a2299e18ff96, 0x0001ceaf237a8503, 0x0006d80455ecbada, 0x000fa473f251ad61, 0x0006d828578e5fbf, 0x000e118adc40570f, 0x0005485cc65c0dd4, 0x000000000005da48}, {0x00073e60bf0732eb, 0x0000fe27fc2e7307, 0x0009067267d2e6a8, 0x0002fa55e27fb12d, 0x000810003fae35a3, 0x0009800c17fcfd72, 0x0002e6c74b50a3f4, 0x00000000000dbafb}}, {{0x0002a6bfc8996b96, 0x000bd0c62fd2c8ba, 0x000a840806b7cf85, 0x000933dcef3f9e43, 0x000d9889ffa276b0, 0x0003c88d251b1ec2, 0x00052f9e84b2ba9a, 0x000000000001913e}, {0x000a4507b899f92f, 0x000e6bafc5e94164, 0x0002238654296051, 0x000cc41bed171099, 0x00036c7a41c84e9b, 0x0005369cd0db5b73, 0x000934d4be07a779, 0x000000000007bd3a}}, }, { /* digit=55 [{1,2,3,..,}]*([2^220]*G) */ {{0x0006d08f59277dc6, 0x0008a3f2eff5384f, 0x00049c170a3dfb6a, 0x000b18a0dde190dc, 0x000da26b0409af10, 0x000b1d944f491b98, 0x00054166080782a2, 0x0000000000097e8c}, {0x000baebab71369f0, 0x000d1fdbfc5f5495, 0x000a70804cb1f0f5, 0x000263857645ef4f, 0x0006a02583638e5d, 0x0005d250331bcfda, 0x000285f5330ab8d3, 0x00000000000c7cab}}, {{0x0004a7ee3780eead, 0x0001ef16938f4dd4, 0x0005af2b9dcbcc11, 0x00095530b6490d71, 0x0001a28a296a2d50, 0x00026415c8432fef, 0x0008656f254dd08d, 0x00000000000d50c2}, {0x0005457026e64224, 0x0003c4f5bc4553f7, 0x0006183dc27db1b2, 0x000dd6e65e593411, 0x0002a56dc2eabab8, 0x000a90e05676baca, 0x000da038eea06bea, 0x00000000000174ba}}, {{0x00021d43da6aa865, 0x0005de6a19dcb664, 0x0006a4c857b63184, 0x0009b9fc6455613f, 0x0004a7390d0eb4d8, 0x000ea135a6cb0fe4, 0x000982ade197a459, 0x0000000000020680}, {0x000776554c3cb5c6, 0x000b803db9be90e0, 0x000e56e339783849, 0x000e8d4753c196c6, 0x00000b7c6ff544de, 0x000a1b14259adcc7, 0x0004f2c6260ec24c, 0x0000000000046cbd}}, {{0x000c69e90d279f7b, 0x00051a35e411c1f8, 0x000aa4eec7d05943, 0x000859e89a66f2be, 0x000e0def8ecd7c7c, 0x0004947b79908c37, 0x000ce88274124e34, 0x00000000000568b0}, {0x000eb0436a41e1a9, 0x00070e52919611c1, 0x000a98c568a44a8e, 0x00039e156bd3a7e1, 0x0006268f856260fb, 0x000fd8293e56a34d, 0x000fcbb3a1fe1613, 0x0000000000067537}}, {{0x000d9811d879790e, 0x000da8a15d6fdcb9, 0x0006c38fcc4a52b8, 0x000e38c55bbe733d, 0x00051ff94a9d7a7e, 0x000585ab5eff146a, 0x000a5de572d13edd, 0x0000000000006491}, {0x000a7bbc541e4f72, 0x000a29c84e1c4d63, 0x000bbb62e6c0b1d5, 0x000cd9b385f06c82, 0x00077a7759c3db12, 0x0003bd7060c93eb9, 0x000d50f1f5b0fe68, 0x0000000000085ec3}}, {{0x000e87011f7cd75e, 0x0006e89e48d8ba73, 0x0007fdc53e3e2631, 0x00033d7302c0daa2, 0x000a048eefe360f0, 0x000a7224415e4578, 0x0009cdfd6dec89b0, 0x0000000000030948}, {0x0003345fd128739e, 0x000ad7cdcc2a0188, 0x0002b63966c3b413, 0x0000a455812b560a, 0x00052ca31d8ca630, 0x0003a5b5a8fa5c41, 0x0004e036aa3c234f, 0x00000000000c86cf}}, {{0x0004ff5664ce36b2, 0x0005e9a0e15351cb, 0x00019cbdd0d2f66a, 0x00059eafb29777cc, 0x000ae354cafdc170, 0x00007c3717e40e5f, 0x0009459cf594054d, 0x00000000000a71c3}, {0x0007429ea783b1e9, 0x0003469309e95af4, 0x0004f55088c266f7, 0x0004070e25823b6e, 0x000d0bc27359f216, 0x000925094ead851b, 0x000f4e3d21bfe8b0, 0x0000000000034a97}}, {{0x000a4c18541d03ec, 0x0004ad927282fbf3, 0x0005c034c274cf2b, 0x000207f450db7135, 0x000423e16d9558b9, 0x0000e349cae95338, 0x0002bc4f10c6d4e6, 0x00000000000feb12}, {0x000eced76985b33a, 0x0002f22548cd1c2d, 0x0005b37b87399908, 0x000f912b6167b3cc, 0x00027902d2baa1c6, 0x000de34ba6967bab, 0x00025eebbe0b0836, 0x000000000004b796}}, }, { /* digit=56 [{1,2,3,..,}]*([2^224]*G) */ {{0x000e99ecf706c6bf, 0x0005c9e857f32800, 0x0001e880e21c15d7, 0x0008d68ff4f65674, 0x0005ac339148f853, 0x000dfc12f35380f1, 0x00093efef0bfdd5d, 0x000000000001387d}, {0x0009274bbe5eb9e6, 0x000aa618ce77c94f, 0x000ef0d12ae1c332, 0x000f06e00dc0da6a, 0x000e07603cc724ea, 0x0006963c7049113b, 0x0003005cf489088f, 0x00000000000ede4a}}, {{0x000abae3c29bb132, 0x000af77e486f79a6, 0x000ea167f51170e1, 0x00028ab7df36628c, 0x00016704dcd6322b, 0x0009a35672d14d13, 0x0003b6d359977af2, 0x00000000000ec96d}, {0x00053212afaa74ef, 0x000f0fd6e400a371, 0x0003860e13fc28c5, 0x0001c7d9b8533afb, 0x00028de66eb862d8, 0x0006784eeefa638c, 0x0002237405a9d7e8, 0x00000000000a6c22}}, {{0x000fc1e6b9032350, 0x000a46909994e4c6, 0x0006261c6638f0ac, 0x000ca05884aacaa5, 0x000996995a981505, 0x0002c000ee4b6530, 0x000b0930e00a5ed0, 0x00000000000236e7}, {0x0005ec99c1d0db26, 0x0002ce696f09d532, 0x0002f7914e3f9268, 0x000a7b401e1e2a4e, 0x00069d2d025aa9ad, 0x0004ffeb19630acb, 0x0004f69fab2c6ed8, 0x00000000000ab758}}, {{0x000c87e27d06e6af, 0x00073f9b2dba43cc, 0x000cbbdd7e7ab099, 0x000a4f33b8104eed, 0x0000e4e1896e7692, 0x000d2aa365da885b, 0x000bcac2a30fec73, 0x0000000000086f60}, {0x000adfed330d989a, 0x00086bc8bf16d541, 0x000f4b7104707db4, 0x000e2f37e35610a9, 0x000482f9d71c8e79, 0x000e62733981139f, 0x000061f8997ec424, 0x00000000000a3518}}, {{0x000efb4736bf4182, 0x0003f6cf0e6ef64b, 0x000b24ffed39dfee, 0x0007783856111dce, 0x0000c0e9f2b00277, 0x0007fe5073a1d36f, 0x0008f1fcf4f6365e, 0x000000000007fa7c}, {0x000ce2543c17ec02, 0x0005509a02de874d, 0x000cd3e25ee5e59f, 0x000a9654b7f4e35d, 0x0009805b58bd7211, 0x00057860ca6b2ba7, 0x000d58418302c209, 0x00000000000f99f9}}, {{0x000634f7fb73c6b6, 0x0002e4e6ef40fcf1, 0x000c701a714f0702, 0x0003403fd41d144d, 0x0007e0774c37a4f0, 0x000c7484a3a50717, 0x00066b078e8c568e, 0x00000000000fbb3f}, {0x0000fb0d6daae4e9, 0x0002c169c9474ce5, 0x00027d6aef77ce07, 0x000968508303114b, 0x0008fad0def23e8e, 0x000c1c8da7a9797b, 0x0007210ad14404ef, 0x0000000000021ced}}, {{0x000169a6e51baf05, 0x00088fde0d1b3e6e, 0x0008e5407b7aa0be, 0x000ad79c9eb9de48, 0x000b0ffbcdac16d3, 0x00020287c2707ec8, 0x00055ad7e6750fa2, 0x000000000009c2e1}, {0x000dcbd856a04522, 0x000e43018c309307, 0x000def4e0648d266, 0x00023aecf15a4af5, 0x000cc1b8cca01aa3, 0x00043a969f085d69, 0x00043047a3eaccb1, 0x00000000000f3a98}}, {{0x000270a279eabd20, 0x000d5c7e9ddef0ef, 0x00060c66b8938b7d, 0x000746db239bb82a, 0x000b28ea13416bc0, 0x0001309b0c811a8e, 0x000b345f714ca71d, 0x00000000000d4eb9}, {0x000f50441ed062cb, 0x00091e0e5afdcc03, 0x0009d20438aad877, 0x0001e7b843343663, 0x000a0eed1116670e, 0x0009bbd50c8c38f9, 0x00095af914fae261, 0x0000000000051c19}}, }, { /* digit=57 [{1,2,3,..,}]*([2^228]*G) */ {{0x0001b38ab493e121, 0x0005bde849cd1240, 0x000576b3d2c358dc, 0x0009e3dabe92fbab, 0x00043324900a3fbd, 0x00020904e785414d, 0x000ba8daead1abde, 0x00000000000aa5f1}, {0x0002d0438c4bd099, 0x0002fd60a4f2ce26, 0x000593174efc1656, 0x000c78934efa243c, 0x000f216a8d8c163d, 0x00001617b3067dcc, 0x00051e116b6534a9, 0x00000000000bbabe}}, {{0x0004b6e85f0076cc, 0x000c1929454f6549, 0x000021b9b8ac3fe0, 0x000a7c5ee25c0b0a, 0x000f2e752295f5b0, 0x000acac687d3372f, 0x000e3cd6dadc7d6e, 0x00000000000a96a8}, {0x0006465e062c14dc, 0x00030ea831db66b4, 0x0000548165c8c6c9, 0x00017e572e3c00c5, 0x000d2a5fb6ba5ff8, 0x000392476b022e25, 0x0005a0b611c5bcbb, 0x0000000000019048}}, {{0x0000dddcc280d252, 0x000d5efda99d90b9, 0x0002988f9d0202d2, 0x0006cd1ad14ac705, 0x00031f4138808b9e, 0x000dd7fb91239ee3, 0x000b12d98e93d993, 0x00000000000894fc}, {0x000d9440883321ae, 0x000d433a92019c9f, 0x000ee20fd3f674ff, 0x00051280d0a320b4, 0x000b4b607b538450, 0x000228c2ec20551d, 0x00025c6e63c766ea, 0x00000000000ac48f}}, {{0x000ea4ad3f5b0bfd, 0x000140372678d84b, 0x0008ab3dd6009aeb, 0x000bca4b79594c43, 0x000baf3b75cfebae, 0x0001e09c6e587850, 0x0004cd534183ac2c, 0x00000000000c0820}, {0x00012c542116a023, 0x000a7dac2cf06c18, 0x000f5e79e9f15f10, 0x00009f490b0f6c27, 0x0006c2c62207f6f5, 0x000ff18873ffc3cd, 0x000c6fbb21eb1132, 0x00000000000e62cc}}, {{0x000a11bec64a35cd, 0x0004f1ca74a30c77, 0x000de3a654c55d5a, 0x00049038d6b4b005, 0x00002f7906ee3709, 0x000452bbb12ba86e, 0x000039aa76f77adc, 0x00000000000f9837}, {0x0000782bfd430ed7, 0x0001841fe306f87d, 0x000ce68ff3cdd73a, 0x00024ccaa7d44b2c, 0x0005d86900f9cffa, 0x0003ecfa022bae39, 0x000980e7a138782e, 0x0000000000086d28}}, {{0x000489915b0c1e42, 0x0000991b8b685879, 0x0005ba3b38e17597, 0x000d69ea7d9931a2, 0x000c7632a26bcdb0, 0x000ba170f3c8441d, 0x0008adf11a365c62, 0x0000000000034e74}, {0x000d3f6d2f87f536, 0x0009d523ca2d7db2, 0x000b5fe1b40ff204, 0x000c7771d07308bd, 0x0007c291c2ef71af, 0x000b40d1773588d7, 0x00015629baa3b0aa, 0x00000000000eea9f}}, {{0x000a95a8a249bd36, 0x000f90ae9143a26d, 0x000709bd167b8510, 0x000f7a7f3b4b882d, 0x000de22d9b9923df, 0x0004f02b1b178e73, 0x000c2fa83861afaa, 0x00000000000b9064}, {0x000de7d4573c6d34, 0x00022142eb294574, 0x0006f55c30205aad, 0x000717fe649a8b70, 0x000cad53c9bbd589, 0x000ecd8f7a925c47, 0x000142c339b11a09, 0x000000000001bbf1}}, {{0x000abd60f6eb49c8, 0x0008c406a7e201fa, 0x0007246dc14c8322, 0x0002eff020748efc, 0x000af39b58dbd440, 0x0008cfb047827442, 0x00078f77e3f2768d, 0x00000000000e45a9}, {0x000ab42dc779cb3d, 0x000229db0829881a, 0x0005eb7284cde06b, 0x000ce47b82775f69, 0x000f63910016e434, 0x00047792fe84995e, 0x000eb9a35e8b971e, 0x000000000007c6aa}}, }, { /* digit=58 [{1,2,3,..,}]*([2^232]*G) */ {{0x00097b7667d86ea7, 0x0001b1fa064cf475, 0x00026db64fb0c148, 0x00002a1fa9d94539, 0x000bdc6bd7eada81, 0x0002f6044786aeca, 0x000208caf91e3bca, 0x000000000008573f}, {0x00036746e95246de, 0x0006cd309fce8dbb, 0x0001300c9068d932, 0x0001ae0f3d530575, 0x00000d1fd61e5779, 0x0005ebfa626b053f, 0x00097991c962c004, 0x00000000000076ed}}, {{0x000013c3d6e02921, 0x000c449f2499410e, 0x000e2ab53501cdc4, 0x0009103d5e91bc0f, 0x000bcb404f68897b, 0x000f7fc0263db1ef, 0x0000af70efd9d842, 0x00000000000c6a23}, {0x000a0390300406c6, 0x000308d5b199ee1a, 0x0009868ea4fe37e1, 0x0003d34504dd889f, 0x0001f823686fde58, 0x000fc73dc0375600, 0x000f42f19ab86f95, 0x0000000000093f12}}, {{0x000b8a18e1e24b49, 0x000143f896ca9186, 0x000d7ce3f5b4c07a, 0x0001632600e4e2b2, 0x000f69e702d5d074, 0x000e0df2b87c7db5, 0x000fba1f5a3b8053, 0x00000000000f443d}, {0x0005af3bc7c98ae2, 0x000deeb90e22f972, 0x00070953899b58fe, 0x0008299a5aa335b5, 0x000d4197b32afb1e, 0x00055918ed78504c, 0x000c720e7a79cc67, 0x00000000000883b1}}, {{0x0004af5925d66db3, 0x0008dbf66baa58e7, 0x0001c386a0ca25fc, 0x00032abeaaa466ce, 0x0007e5f2733b80bc, 0x000531afa605b789, 0x000369e9e7e3a1a2, 0x000000000003deb8}, {0x000174c1d570e84f, 0x0008d36212ea2dd8, 0x0008479c4475fe18, 0x0004b31444e9ea02, 0x000169530c1befa5, 0x00079bdd19c2229a, 0x000cc368feb9854b, 0x000000000008b984}}, {{0x000682b315cae64a, 0x000981df8d98c41e, 0x0009fabd7bca288f, 0x00064f91703e1431, 0x000e9de0ab4ca54d, 0x000dc4e0fa12198b, 0x00091f160e06241d, 0x0000000000066958}, {0x000b5c1e9cafc463, 0x0006f808565e66f7, 0x000a9467f76914c8, 0x000cd934bac17690, 0x000ca5be965f6682, 0x000a38e9062e7ac2, 0x00016ed33f6f8ad7, 0x000000000005b8b5}}, {{0x000509d8741fea0a, 0x000c1f041e421362, 0x000c0d8899228fbc, 0x00093751128ed62b, 0x000acec6eae64fea, 0x000a65dae041a1c1, 0x0008e81f32359415, 0x000000000000154e}, {0x000a9eb331e84371, 0x000ec309e9f286a4, 0x000765936bc21528, 0x0004dd5692420c27, 0x000ec4fa1a6a7bb5, 0x000779e77193a41a, 0x000b8c35f5f3b43d, 0x00000000000046eb}}, {{0x000b5769d7b9ec0d, 0x000aa3a5a366dc99, 0x0005d073ce2a60d9, 0x000e4aafe5355bee, 0x0003ced676663e16, 0x0003440036d8bac0, 0x00020c403eb33ed9, 0x00000000000333ab}, {0x00094bfc36e2db30, 0x000739fce19869f6, 0x000435b17be8c513, 0x0009611921a58e5d, 0x000620d5c61a8e68, 0x000c81b4e8f5f115, 0x000779b17f612fad, 0x00000000000e562f}}, {{0x000d75f385d1b0f1, 0x000f0d6a4d25bfe8, 0x0007b705bfa0d54e, 0x00059731cdedfc0f, 0x000603d6502f9420, 0x0005ce8c80c4e385, 0x0000b7981a4fc5e1, 0x000000000007aca3}, {0x000ea22cf2bcfc17, 0x0009ef2037ef684f, 0x0007e5010cdb37dd, 0x000a23c71f3e4e4b, 0x0009f47b504b9c98, 0x0003233aaa73c8b8, 0x000f68b9e33f5402, 0x00000000000f92c9}}, }, { /* digit=59 [{1,2,3,..,}]*([2^236]*G) */ {{0x000a9e3a73909533, 0x00090ba03ba3b07a, 0x00090d7a3c9c5a5a, 0x0008cfe4f0f60b35, 0x000e6fcccd96f96b, 0x0009dd17ab908d77, 0x0000487208ef7de7, 0x000000000003ec3d}, {0x0006af6a704d4f0e, 0x000d09c5ad2d9a11, 0x000e77d5943d9764, 0x0009449470eb938b, 0x000bee7d772fac99, 0x000b7ad09faaf27f, 0x0000a9fbe402abd0, 0x0000000000057db0}}, {{0x000ca62ea2a4a457, 0x0001b10c082a59d1, 0x000bdd4313beafb9, 0x000935b4cb291a7f, 0x000313e9ce08785d, 0x000f6f1c4fc2ae15, 0x00024c3146fabf4d, 0x00000000000c87dd}, {0x000f74ecc24bd4cf, 0x0000385fdd8765b9, 0x000dc418405d512e, 0x00005013e7e0297e, 0x000fb92df904c81d, 0x0005ddccbb56ddd1, 0x000f1d4612df9f29, 0x000000000000e27c}}, {{0x0002069dae7548ac, 0x0002986d9b05f69f, 0x000025ad33463063, 0x0008e7c27d9d64d3, 0x000aba04e6ad9b6e, 0x0008abbbe79bd66b, 0x000d0477e4d0b082, 0x00000000000cc540}, {0x000bdbdb8d90e2e4, 0x00067f5d8a46ef90, 0x00078bfd47c637af, 0x000b852563fe6b52, 0x000997cdd04fb93b, 0x0007de47d06bb3ae, 0x00061c07f011d48b, 0x00000000000de78f}}, {{0x000eb7904785958b, 0x0007d7830460f8a0, 0x000cf49e72cbbaa0, 0x000e2aa307d9c790, 0x000b5aad8b6c73be, 0x000848db51b02af1, 0x0004765e31882703, 0x00000000000f230f}, {0x000b79128735694b, 0x000bd4ea6535cc84, 0x00008e33135971e8, 0x0007b332fd33cac2, 0x0001c566914f4c19, 0x000952d3b24c7b0b, 0x0005f2956ce3c371, 0x00000000000fabae}}, {{0x0004121555388dc8, 0x0008b8a95e5c1a8a, 0x000cd5dbd7b0133e, 0x000df6acda40bc0b, 0x00058234471d1859, 0x0003c0100f9097aa, 0x00067caddc0c9b78, 0x00000000000feb70}, {0x000ce59ade26052d, 0x000a6e3805fd0a27, 0x000626ac8acaae6d, 0x00099921943a0a1d, 0x00091dfe627ea459, 0x00006515fb47f061, 0x00073e313d4f09da, 0x000000000001f54a}}, {{0x000f6dd7137bd615, 0x0007e0db87bc3c53, 0x0002eda89127238c, 0x000e9c4a3fd2a60d, 0x0001c9f017e5ea81, 0x000c75768190c9c7, 0x000de621864180bc, 0x0000000000043dbc}, {0x000fb5dd8276da18, 0x000de5b090c70dac, 0x000cd9057894e345, 0x000d268a918bf24b, 0x0008ae204f49fef3, 0x000d7c356e10c52c, 0x000a17f4be898d86, 0x000000000002fdb5}}, {{0x0009bfc4aad5cc44, 0x000a20079c69c96d, 0x0008a5713957941d, 0x00086660139685a2, 0x0004946fbeddb8d1, 0x0001aace408590ca, 0x0001b67fecd9b964, 0x000000000002936a}, {0x000267114a49f247, 0x00065925b6235aee, 0x00055e3538cd2015, 0x000663d8c6fb34ac, 0x000c2fc1c10d971e, 0x00042b822543146d, 0x00024d6e4053c706, 0x00000000000492e5}}, {{0x000d356fb82e9b9f, 0x000beca9872e0a14, 0x000f54683a031c30, 0x0007cb84e05b2811, 0x0006fa234d4596b1, 0x00035a7d89798714, 0x000384ba78949ebb, 0x000000000006fc59}, {0x0001361f78e02fa8, 0x00081a303e549f81, 0x00064be08532a2fa, 0x0002de8ee7220467, 0x000563e27035e57e, 0x000d2fe6fa05c106, 0x000aadaa38e86602, 0x00000000000ee2f6}}, }, { /* digit=60 [{1,2,3,..,}]*([2^240]*G) */ {{0x00044971cf281b0a, 0x00052c0426b768f1, 0x000ef3f4445c186e, 0x00012e3172c0d3e8, 0x0006ee75473731d3, 0x000a7ee615f49fde, 0x0005fb895530f06d, 0x00000000000e8b3a}, {0x0006345afdc270e9, 0x00019fd14973443f, 0x000f6896912e434e, 0x000ae07653908d03, 0x0006ba02a278e2ba, 0x00021b8f8c3d0143, 0x000297a0d0222e7b, 0x00000000000d7ec1}}, {{0x000653659b1a252c, 0x000514f120aa7478, 0x000c72dfe03d7757, 0x000ac5ecfe5f7a92, 0x0009bbf3cec6c96b, 0x000361cd5d4e73d5, 0x00044ced8d233560, 0x00000000000562f4}, {0x00045d3e2b7ac684, 0x00022bd37d3cf9b9, 0x000cb601f2d0a968, 0x000535a3d2f41ee1, 0x000ee8b1743e7e35, 0x0005a27650353b52, 0x0008b831d89dfd7b, 0x000000000008d9ea}}, {{0x000718fb55d90569, 0x000b306a67bd2493, 0x0001471031374c3f, 0x0005d5197bc62d32, 0x000924c51874ee0b, 0x000a1a0d552b1703, 0x0000acfed1f42382, 0x00000000000db627}, {0x0006189cf7edbc97, 0x0006c36be4a9b658, 0x000680236e8f5c91, 0x00036d3b8f8074cb, 0x0009718545c6c174, 0x000757d213bb4d39, 0x0003668e1ea3555c, 0x000000000008c474}}, {{0x00063be615177c6f, 0x0002773457010af5, 0x0001ce08b2f26f1c, 0x0000e8c9c25fe5be, 0x000182dd0485705b, 0x000ac280540f36ea, 0x000b923d55bc8527, 0x00000000000ad921}, {0x000b6da293461f09, 0x0009551586cd4c76, 0x00086171a05efa67, 0x000605e84f0abcb8, 0x0003772dd0dabb4e, 0x0004e1d41354ef8e, 0x0004917f1a8f795e, 0x00000000000de5d8}}, {{0x000beb4ebddc46f4, 0x00073ec72c64fb0c, 0x0005bac2d9d9096a, 0x00022001819efb1b, 0x00068cdde8703c5e, 0x000a87aeedf5ab6d, 0x000f1975a44e9d92, 0x00000000000bcf77}, {0x0009407ed3c226cf, 0x0005e8191efbc92d, 0x00064a74c9c1339d, 0x000e58265cf242d2, 0x000180b1d17be62b, 0x000de59a9ae99a3b, 0x000ce248cbb44692, 0x000000000002dcb3}}, {{0x000a48783de6cfb4, 0x0006bf3899558552, 0x0009d51bfff43e77, 0x0004fd32df8d1a75, 0x000376d3fbbf0b1c, 0x000fd52bcf16bcc2, 0x0001f0d5888916f4, 0x00000000000d5cde}, {0x000f03d1ac917a2c, 0x000ae764ffffd280, 0x000af8be538ef59b, 0x0004762ccd57b860, 0x00032935106234f6, 0x000c642f32233a4c, 0x000f34df076095d9, 0x0000000000059f0d}}, {{0x00010c66eff8425e, 0x000379580cdfaafe, 0x000d1f7ccb185b5d, 0x0005f77c327f3e8d, 0x000c35353c5f5d3d, 0x000258eb105d5339, 0x000f79c56fb5fe5c, 0x00000000000edce1}, {0x0005bd6f7b6e122d, 0x0007cab7aa141541, 0x0008987b379beb7f, 0x0001491458d9e533, 0x000caa7f0f31e124, 0x000fda7abdd2448c, 0x000a4dec58d3c7f0, 0x00000000000c91bb}}, {{0x0002f037fabc6138, 0x000b73bd258d77ca, 0x0006aa4d0ec1d1f3, 0x0002512e3f966a14, 0x0007709d0c2d5b43, 0x000658259338bfca, 0x000023d142cc1049, 0x00000000000636b8}, {0x0007458ca547abc1, 0x000cda9ef9400a80, 0x000ad926836a9402, 0x00063c55cb644887, 0x00011cea475bfd2f, 0x00067a25fbae949b, 0x000a6aa45446031e, 0x00000000000dc6a7}}, }, { /* digit=61 [{1,2,3,..,}]*([2^244]*G) */ {{0x00085fa16820f665, 0x0009fd699ea2d24e, 0x0004f1772a862ed3, 0x0004bad66a8b35ba, 0x00024233fccb4660, 0x000d3cf0c0c779b6, 0x0007af578458acbf, 0x0000000000096bf5}, {0x0008a325d9d68d07, 0x00045a9724244e54, 0x0005b4b1e20150f9, 0x000a5b8c6be8c159, 0x000c774d62c40980, 0x000bde24b6230e3e, 0x000204da1467d84f, 0x00000000000cc862}}, {{0x000b4d1a75edabf3, 0x0007567c51633fd8, 0x00020dc66cdc521c, 0x000c8dc9ee450d03, 0x0008b41a3e2f77fc, 0x000bf06898dd2b31, 0x000464df6a935e93, 0x00000000000a92e5}, {0x0001e3ee6beb3c9c, 0x000e449afcd9ef46, 0x00031a4b44405106, 0x0008ad2c7ea7810a, 0x000e550822b2cdbd, 0x000606adcfe61571, 0x000110744a4f9386, 0x00000000000d9d4e}}, {{0x00006ff4ac15d783, 0x0007ef1084276ccf, 0x0009d3b1212d957e, 0x000dcf5bfb4283a4, 0x000db74017eb3752, 0x00078fcf8f6b2214, 0x00039afc1cdf7245, 0x0000000000012265}, {0x000c5dc1b7858cd2, 0x000cdcc0796680d4, 0x000e05b222bc5975, 0x0003a9a504cf7d65, 0x0003c93ed5932027, 0x000303f1b0c7b7e5, 0x0006a4aaf9c36866, 0x00000000000cb013}}, {{0x000bfa5cdf24bf96, 0x000411fef389c07d, 0x00022753fd218088, 0x0000a1437f04a344, 0x0009d0169369bd77, 0x000377cc3c7438e2, 0x000a4f6b265742e2, 0x00000000000c369f}, {0x000bb384dc3d9a84, 0x00060dfdbcf462e9, 0x000d3f52e65bb342, 0x000a0b82a9c483da, 0x00042de432285574, 0x000d1fabe0563fe9, 0x00096658ca0e8aea, 0x0000000000066023}}, {{0x000afbbacd3ede36, 0x00007746325d090f, 0x00094f8b4a38ccef, 0x0001c2866c3931a7, 0x000a783a73e7d9f2, 0x000d82d13c12880e, 0x00010e382e1ce28b, 0x00000000000ac023}, {0x000fda6b09a40144, 0x000b69802d06233d, 0x000de8140422422b, 0x000367efd4cf75a0, 0x0000e8f2f6ed38b4, 0x000e72ff4765cdee, 0x00070ae0b4d72b35, 0x00000000000947d4}}, {{0x000a35bb9d72eb2a, 0x000c5383bda07268, 0x00038c9d09f99c2f, 0x000717d369f39c03, 0x00011a5a39006f3c, 0x000ec6c2b1bb593d, 0x000202d0f07ecc2a, 0x000000000004240b}, {0x00083c5449860db8, 0x0001935342f6c7b8, 0x0009a1541ab519cd, 0x000eb09ccb6a888b, 0x000785aa42c5fcd6, 0x0004e5895abb7a6f, 0x000582952f8824aa, 0x000000000005c406}}, {{0x0001d7b0f8433a5d, 0x0004359d6e052cda, 0x000fea341e325461, 0x000d07d7907cc890, 0x000dc4ce5d800459, 0x00004f40267d720d, 0x0002a83262028eed, 0x00000000000d7881}, {0x00055f59d844fe29, 0x000fcf735fd6cf7f, 0x0001c0c0179cc733, 0x00006e8e19a43f29, 0x000f19592b76328c, 0x000b836f7b97ef65, 0x000a9981325f3db8, 0x00000000000d6e6c}}, {{0x000a67318a4b19fa, 0x000a63667a71faf0, 0x0007be6235b29837, 0x000535efc62f7919, 0x000b389faf7fe084, 0x00071b7f65bc1652, 0x00070340cf51683a, 0x00000000000d4f39}, {0x0002b576e30c499d, 0x00099823e7549478, 0x00032769bfa306a4, 0x000ee027225b31ad, 0x0006fc282f165639, 0x0009f61ae7533bc8, 0x000803710009d2c6, 0x00000000000bf65e}}, }, { /* digit=62 [{1,2,3,..,}]*([2^248]*G) */ {{0x0006c5f4c042c4cd, 0x0001ceb29e44bf59, 0x0004c11cc5ce653f, 0x00004943d2bf689a, 0x000a47428dd2d09c, 0x000aafac83ab7799, 0x0006e0dc558d6be9, 0x0000000000087f9f}, {0x00056bc34f65dad0, 0x000c793842bcd3a9, 0x000241a2ffbfced6, 0x00052687e6d47b5b, 0x000a4c37eeee1645, 0x000c412ceab304b7, 0x0002c8dbb3d4e13f, 0x00000000000a726a}}, {{0x00059e97675084b3, 0x0008d79d88dffddc, 0x00002dc16c994a53, 0x000000fce7d606f0, 0x000e2fa27fd3b528, 0x0009436afc773557, 0x0004c755b53dd3e1, 0x00000000000e10b6}, {0x00077a15a41de95f, 0x000bfe5832664b2b, 0x000d15e689d49c17, 0x000bf537af3e3dd9, 0x000cf47d298c7b93, 0x00012136994fafa2, 0x000ff694c2ff9a21, 0x0000000000033468}}, {{0x0001b740495480b0, 0x0003f91e8c991baf, 0x000b4c043871430f, 0x0003f6dd095f5b94, 0x000cddf3cad27c5e, 0x00057aacfed7522f, 0x000f5180bb87056c, 0x000000000000cc5f}, {0x0006cac5a2f35aa0, 0x000e0964def7e61e, 0x000e006a84529a7b, 0x000192584de66a22, 0x000e075f07c5cc75, 0x000eade939acaf7f, 0x00058f6505c2f81e, 0x000000000000e3cf}}, {{0x0001fb7f00850a1a, 0x0001dbe45d81a1aa, 0x0000ee7897985bd0, 0x000a516b078ea895, 0x0001b446476463c5, 0x0001e52329f3efe4, 0x00022084580e2410, 0x00000000000c8ae8}, {0x000539dde4d08a27, 0x00077bff4077d088, 0x000c1e715cd7b849, 0x000eef207e1c03eb, 0x00096e654d584df4, 0x0006f15964ab3d03, 0x000cd5b20056cd08, 0x000000000008acd7}}, {{0x0008f4a5a8f26e12, 0x000538caa623c979, 0x000e7d0ec3691999, 0x000f856ee285bfe4, 0x0006d0674ecd089a, 0x0006f661277b461f, 0x0009f8baa9d9b38d, 0x0000000000059066}, {0x000460fe25d6fd2a, 0x000d2b164340c38e, 0x0003981c9e27c186, 0x0003b9176e4346f2, 0x00017caad5fc73c0, 0x00087803d6a678eb, 0x000a94103ff0790a, 0x00000000000f7430}}, {{0x000dd3174fcc39a0, 0x00094517075af0fd, 0x000fd65c623f7ba2, 0x000e9493b86f6398, 0x00017f296bf4320c, 0x0001082765115657, 0x0009000919607a96, 0x000000000002f035}, {0x0004b29394d28cac, 0x0008f5d13de7c5ae, 0x000ea9b2719ceec5, 0x0008089c0f58697a, 0x00030ca7ca20f1b2, 0x0001e1be52adcd1a, 0x000ba096c07f42c2, 0x00000000000baa0a}}, {{0x000dc0265a01c54c, 0x000233027c169336, 0x0003342d9c6b202a, 0x0006cd31b8b0179e, 0x000a6dd5a4a7e6eb, 0x000c82f110d2d27e, 0x00002241682c0007, 0x0000000000081075}, {0x000f1169b3430f67, 0x00019f3903f514b2, 0x00091dfa21d2d176, 0x0005eed470bd3b32, 0x0007e85a62931b62, 0x0005ad640a46398a, 0x0003a58ff6ef8c80, 0x0000000000095bfa}}, {{0x0006e424a5742fd1, 0x0003a8cd6c9f7239, 0x000180484ef81e04, 0x000b0f589b8ad2c9, 0x00070d9c999d9c0d, 0x000f84ab4692a8db, 0x00006ca407fd03c9, 0x00000000000cc9a9}, {0x000b5d757bfbcaf2, 0x000014813a7654ce, 0x0008615f305ee56c, 0x000f2934fa0a23f1, 0x0007cb1f8d7aca6b, 0x000d10c531dfa3af, 0x000c1328036f5498, 0x000000000000e012}}, }, { /* digit=63 [{1,2,3,..,}]*([2^252]*G) */ {{0x00034e0d2aae29e9, 0x00091a53f1a10241, 0x0004dd23936a5886, 0x000ed8532976d137, 0x00065ee692d130ef, 0x0009e7cc1cf5ada1, 0x0004723ceda69d25, 0x000000000009baab}, {0x00095b8627836d36, 0x000237ee5baef4bf, 0x000e9b1caaa769fb, 0x0008ddacfdaff633, 0x0009cec076939e5c, 0x000fb509d575c8db, 0x0006979afc8ae0fd, 0x0000000000085651}}, {{0x0000da11d13ab853, 0x00042a7342f9446b, 0x00039f5ef3dbc527, 0x0008bf07471c3856, 0x000130827f3450e4, 0x000779c23729e5ab, 0x000d5817199191ea, 0x000000000009fa9f}, {0x00077a9b9dc5fca3, 0x000827d5799369d5, 0x0003bee46a6f5cc0, 0x0007d51e85417260, 0x000dec720355253f, 0x000a16268107a793, 0x00031b1c14d0566a, 0x000000000008bbb2}}, {{0x00016132445f3e21, 0x0009ef5689c5dce5, 0x0006397102e2e73d, 0x00079d012eaa5340, 0x0006d9271e941af8, 0x000e63c34dba775e, 0x00024b60f8507310, 0x00000000000a686a}, {0x0006624c82f5c532, 0x000dded5ca8f992c, 0x000b2edebcb9407c, 0x00039426d90a7d51, 0x000bccd37e76e2ee, 0x000412e0fe5b3e4c, 0x0000489013bd08f1, 0x00000000000ce999}}, {{0x00009cf56d1d974c, 0x0005561d0e01b86e, 0x00046be97f98120d, 0x000e224b362902dd, 0x00029e0a5d16d4a4, 0x000e580e945923c1, 0x0009544fc2bdd495, 0x00000000000a8c3d}, {0x0004daa7a4671003, 0x000a1aeff11352c5, 0x0005a1c5b6c0120c, 0x0007d3eab8f9f31a, 0x00066d566c158090, 0x0002e6fa7af2c121, 0x00003a0082daba95, 0x000000000002df9e}}, {{0x000fc79dfc540dc4, 0x0004091b379c535c, 0x00090bc691de574f, 0x0004208176b3b828, 0x0008aaba5cd3d0f4, 0x000794f9fd18c211, 0x0008944aed5c9770, 0x00000000000f4c33}, {0x000946afeb1a61f9, 0x000b9b8e67989163, 0x0000523ed92edf12, 0x000ef39ab5573985, 0x0004b71031051b7e, 0x000ac89e4175e393, 0x000db8943abf4a82, 0x0000000000057ffc}}, {{0x00066f02c7c0f325, 0x000f899c2b4cc9e8, 0x000f2b3e2c2a45ff, 0x000b66b5a352b7b1, 0x00043ec757ed067b, 0x000d36adc3c7d6fc, 0x0003a42f69291cb9, 0x000000000007c914}, {0x0004d853fbc3268f, 0x00006768c3c3f0a6, 0x000dd7feada4c10c, 0x0004b025299ea1bb, 0x00091a2d4005d86e, 0x00017fa60be46b7e, 0x000fbeaf865a1693, 0x00000000000cdce2}}, {{0x000297083b5951f8, 0x0002b66fcba529da, 0x000a6f9544c17490, 0x000b97241b4305fd, 0x000e25b6af89a371, 0x0005f9e8cb2d858c, 0x000ef8bab07d5327, 0x00000000000d525b}, {0x00073848e93e22c2, 0x00084ebf79e3bb83, 0x0007a079aa9da5d4, 0x0008b66cba1a65a3, 0x00038b1eb8b67dbd, 0x000a6436a88ea401, 0x000e33210ac1b38f, 0x000000000003df40}}, {{0x0000b48bcae58bd8, 0x000c45f79f0de54f, 0x000db929ac4cc6a4, 0x000a68e11571c5c9, 0x000e2474faf7d631, 0x0002a924a6d072b4, 0x000d7a5e043a6d86, 0x00000000000b0fc8}, {0x000fb0fbc0056e2d, 0x0008bf54bb7f2f12, 0x00058e2455c41895, 0x0009f4c5909ec050, 0x0005abd164608145, 0x000b1c69ed28cda2, 0x0006f4bb676d018d, 0x00000000000ac503}}, }, { /* digit=64 [{1,2,3,..,}]*([2^256]*G) */ {{0x0005d534448865a4, 0x00079dbe04c30004, 0x000de820bf917110, 0x000b54670911457d, 0x000b3f7a1757dbf8, 0x0007bd62c9e683b5, 0x00097e7b89a08a9c, 0x000000000000b3fc}, {0x000ba720a0047774, 0x000980ac9abfb9ba, 0x00007bd7b6be79d8, 0x000c335d9deed984, 0x000f72603e080aa6, 0x000783bb2e270580, 0x0009ae70857a946c, 0x00000000000caa92}}, {{0x00008763d38fe0f6, 0x00001f071c986bc1, 0x000413c627ede21a, 0x000b12a61483bc2d, 0x00001caf6dd6845e, 0x000c21b9217471d8, 0x00036d7b603616dd, 0x00000000000b9925}, {0x000a996617818c3e, 0x0007f433f065211f, 0x000b56653ac9464b, 0x0007386a9adf49b1, 0x00092cb2944fdf61, 0x000d9c0764bfeb39, 0x000576bf288427b3, 0x00000000000965b4}}, {{0x000b333ccbe322d0, 0x000fbce23a199d59, 0x000074dc302e3830, 0x00000121d15a0063, 0x0005f4355a1fc720, 0x0007f780715fde73, 0x0006913849761f60, 0x0000000000018204}, {0x00074bfa03274297, 0x0002575756e4ea63, 0x0009809c9584a1de, 0x00032763d4ce3dc3, 0x000ef1d66e006312, 0x0008829e6a769d2f, 0x0006ef8624ddbac2, 0x00000000000d2df0}}, {{0x000f606b2db32f32, 0x000b59ec11596f9e, 0x0004a5f37de5fafc, 0x00094e131fca111c, 0x000896076f45acf7, 0x000732588438b917, 0x0000daad71035b51, 0x00000000000a5d91}, {0x000d85cad07f3bba, 0x000a7efaad0e82d9, 0x000f829c6ffe7ff7, 0x0002426474ce3273, 0x000a2aa270da9940, 0x0008fa6ebd53b687, 0x00041196c8bb78d7, 0x000000000006e699}}, {{0x00044c83de3d28f8, 0x0008b2dfc39e611a, 0x00099024ec940ff4, 0x0002123313aa4788, 0x000b9c6acbd11cf1, 0x000d54177785b025, 0x0001eab4aeb5b8e4, 0x00000000000d943c}, {0x00041945f056ffdc, 0x000097892db846ab, 0x0000f6f8e04921ff, 0x00013c61cbd3232b, 0x000700b6c34ebdee, 0x0003de32b873e0a7, 0x000302b279505ae2, 0x00000000000c5a03}}, {{0x000395d621a49e0a, 0x000c7430b669fc05, 0x00093c4a448f25c5, 0x000730c4c33493e3, 0x000fca00ed3901ad, 0x0004a55168c882c1, 0x00027dab2e9c89d2, 0x00000000000f5d03}, {0x00020231a1107ea0, 0x000f946488bd7b79, 0x000d5a9d2b183f55, 0x0000e90aecfac7d9, 0x000fac6a9e8cf9f6, 0x0008bcda84afd1f5, 0x00099857a20bf8c9, 0x000000000008b46b}}, {{0x0005f4b3119ad50d, 0x0006c1f2f6c1efc1, 0x000be8ee71be11e0, 0x000e4a6569c090bd, 0x000adb3986d020dc, 0x000f553eae4f7401, 0x000bff1389799485, 0x0000000000009026}, {0x0003665df6023a4c, 0x000b388067aa6ec6, 0x00069e9d017576cb, 0x0005019459bf26a1, 0x00058b6e76f68416, 0x0000d2434ec125bd, 0x0000b0d636f9321f, 0x000000000008e05e}}, {{0x00021074c1c07346, 0x00068fe1f11ac76d, 0x000a3e93fcce998e, 0x000015a3c5babf98, 0x000d5929ea0a99d0, 0x000fb7b7e7e795b4, 0x0002e8c9cf68331d, 0x00000000000a6499}, {0x000716aaedb25dc3, 0x0000d0b7e0dd7aad, 0x00064fd90a09f648, 0x0003cf034f02b979, 0x000a5662f0c86402, 0x000058ccaf7dd410, 0x0001eda3bb6088a1, 0x000000000004e780}}, }, { /* digit=65 [{1,2,3,..,}]*([2^260]*G) */ {{0x0006b5199cfd1ff1, 0x0009d140a0f9f409, 0x0004971fd020b4cb, 0x0007c2304a1f742e, 0x0001195ba34e78ff, 0x0007f78b4c0568f5, 0x000a53e97183603b, 0x00000000000f9efa}, {0x0009e6e1cb2c1b4d, 0x000bae924d2c4efd, 0x0004b415d4c5ceca, 0x000e73f6ee37e106, 0x000a5e5a1dde4b12, 0x000cd64161836fdf, 0x0004d87f1b92259d, 0x0000000000067754}}, {{0x000befa999003a02, 0x0000e279fd119411, 0x000606c204c4310e, 0x0007da4da44105e5, 0x000a28223fe1d8f5, 0x0006f2d2eb1814b7, 0x000e06cf2fd241e0, 0x0000000000001dfd}, {0x0001563b8cdc2810, 0x000a4876a31af711, 0x000bd72037bc4e78, 0x000d608493a6a0aa, 0x0008a88c03e75117, 0x000916897dcec808, 0x000c57eae1d352ea, 0x000000000006e8b2}}, {{0x0001a9c4fdcf93d1, 0x000650254486c9e5, 0x0006796f28c8ff02, 0x00058ba000f54926, 0x000934009fb6fb58, 0x0002bde301315bdd, 0x000358b18a8e0ac4, 0x00000000000f1070}, {0x000b8de4d767059a, 0x0004ebeb1db7458b, 0x000305d015a22913, 0x00014d4e4122b217, 0x0002aabccc7b1522, 0x000d07571d3e673f, 0x000f1794c50f64ae, 0x00000000000e66b4}}, {{0x0004bef0d3847d2e, 0x000aa09f8bb05816, 0x000388d5b381065f, 0x000c7b6076e13ec8, 0x00035d5ac07f26eb, 0x000ab69e6bda0b55, 0x0001fabcb8132248, 0x000000000001c0f2}, {0x0006ceb771ee0889, 0x0007b7a466528564, 0x000e55b024527048, 0x00011864c1d7cb8d, 0x000f2d08130185dd, 0x0005ea0f0096f849, 0x0009b2b4f503dd8a, 0x00000000000d1bf6}}, {{0x000f0c6218b7c4e9, 0x0008540336b12c41, 0x000f74c446fc6c56, 0x000048d9c841f0d0, 0x00051d617f50c337, 0x00017d3794ce6d02, 0x00024300fef21981, 0x00000000000f95be}, {0x000f7d33fe9f8bcc, 0x000ec98de119d3a3, 0x000e778f8a8c16b8, 0x0005b720f9678bed, 0x000d334ace309412, 0x000e86e04fc5b57c, 0x00003909486527b7, 0x000000000006e552}}, {{0x0001aa0f2e0127d7, 0x0007b4ab7a22bd4a, 0x00047f417a4172fd, 0x0009f95078de336c, 0x0006f786924520f5, 0x000f1d96ffd28fa3, 0x000f0f1de42581cb, 0x00000000000366e1}, {0x000e183b180aaf06, 0x000febc65fa9d0a4, 0x000739e25cf57814, 0x0004f3a4a0822a93, 0x000bfd05a0aa0638, 0x0005ee3ce1c81332, 0x000d00bfb12361d9, 0x0000000000042016}}, {{0x000f0b32c63695dc, 0x000143b75c45b10b, 0x00037d16d187f9f5, 0x000227df8e0a114c, 0x000e73ddba245450, 0x000f246455e69f1a, 0x0007412007b80e57, 0x000000000003d159}, {0x0007528fbc79a394, 0x000ffcbe54d2888b, 0x0004e47907e4e2fb, 0x00070594cc39f745, 0x00032b1b8da9e19f, 0x000f68d2680f00ab, 0x000829b765aaf973, 0x00000000000e993f}}, {{0x0000b5faa7527283, 0x000530a159f61ee6, 0x0008e1f9dcf0213d, 0x000b8ee1661a2405, 0x000ec95c41b36d1a, 0x00051eb56cae7f40, 0x000250bc3d20407c, 0x00000000000e8754}, {0x000ae69a0a837ff0, 0x0000281561056151, 0x00032df2869a92d9, 0x000c1bf6af2a00cc, 0x00042d0a56c0abdb, 0x000c8959ee9a9425, 0x0002f34774a7b77b, 0x0000000000019cef}}, }, { /* digit=66 [{1,2,3,..,}]*([2^264]*G) */ {{0x00035e2ab65ec55c, 0x000b3114a25c78e3, 0x00036712a123ad50, 0x00068411e7bd7df9, 0x000ad6da54dbc49b, 0x0000da3215b0359f, 0x00087ea6e6e5f93f, 0x00000000000d640a}, {0x0003244eb630ddc0, 0x000f7c1a4f6cdf83, 0x0008137a92bebef0, 0x000eb8e3c0a631d4, 0x000db756445ff44c, 0x000c8880e0205b11, 0x0000d304844e845b, 0x00000000000b85e0}}, {{0x0005c0fc3837219a, 0x000cee76894c3764, 0x000faaa07cdf021d, 0x000fcfbe55cd1e6b, 0x00023a7ad5b9566d, 0x00087a4ef5421a9f, 0x000423a005838a46, 0x0000000000023a2c}, {0x000326b6922fa665, 0x000ed4b780011f85, 0x00024bae2459585b, 0x00069e937ced8f3d, 0x000d8c1e1eaa2b5f, 0x00089cc4d306b621, 0x0007748acbbe71d3, 0x00000000000f4ab7}}, {{0x000e8b5d217d418f, 0x0002ee557e7c707f, 0x000dffc8ed3b58d7, 0x000efa4b42b3ab4b, 0x000d8e53b32db9b0, 0x000b1bfbd9d71dc4, 0x000d3fe3a93e4e11, 0x000000000009901b}, {0x0009bf805b79f71c, 0x000b35f3a5304e02, 0x0007d4e3dff75554, 0x0007a7bef469e919, 0x000278f160dcf415, 0x0009189a9f03282f, 0x000f2197e4b7f4c8, 0x00000000000a967e}}, {{0x00083fb3cef3edcd, 0x000642df6f242046, 0x00054e87770387bc, 0x000232b372bcc88c, 0x00086e428cc59e80, 0x000a1b76326ba13b, 0x0005f32526ef1f13, 0x00000000000dc97c}, {0x0007320a0cda3969, 0x000344954867fb10, 0x0004f1baa6436a30, 0x000fa69be143027a, 0x0003cf54f28b7e39, 0x00097c2da1232946, 0x000099cf0991dc75, 0x0000000000052e07}}, {{0x0004ba256e3a80b8, 0x0005fbdfea74874f, 0x00090a65af244c4b, 0x0005675aaba39901, 0x0006a12be348d5a6, 0x00018ac5d2250648, 0x0006f9766dd428e8, 0x00000000000fff9b}, {0x000ff89f1b07248b, 0x000174b3b10f3ab0, 0x000ac70bef37c1ca, 0x00011ed5c9e36bef, 0x000364cdfcdd2a61, 0x000462f54a99a302, 0x000b5fdbfbbe7a59, 0x00000000000cc266}}, {{0x00081f8725c117c2, 0x00037dc9daeefc8d, 0x0009cda216a5b4ef, 0x0002271ca53d53df, 0x00054d1aa50b206d, 0x000001e99b054633, 0x000aa452bca91088, 0x0000000000017fb7}, {0x0007b7c6cf80a17f, 0x0007afff3af9472e, 0x0007c0765e5ecd82, 0x00004be24753989d, 0x0006e90950c6aac0, 0x0008efe5b4a5de2b, 0x0009f9b46af0ab73, 0x00000000000db445}}, {{0x000c5196b2aa222f, 0x000d15bdb6d3f8f0, 0x000389884e011601, 0x00008a96ddd9e23e, 0x0008467e7577ab50, 0x0007555edac1e974, 0x000d57e74e35b601, 0x000000000009d04f}, {0x00080785cb147efa, 0x000908585c6fc59b, 0x00035ae9e9b63afd, 0x000d1e80b684dd21, 0x0009edbaddcc2739, 0x000c57660e1ba788, 0x00089a464f42059d, 0x00000000000a7cf2}}, {{0x0002dd131270b84a, 0x000dd412f64a3e09, 0x000b9c94f3cfd9dd, 0x000cdc2c2e964e0f, 0x000d0011cb01fbe6, 0x000228f23e9a3b1f, 0x0009a16c30762dcf, 0x00000000000be919}, {0x000e7d10046b4ea1, 0x000b4732711dfdf5, 0x0008160cd8dd88e3, 0x0008ba0c6eceba7a, 0x0001f3c3d31d8ee0, 0x000716948b171153, 0x000add65060b633c, 0x000000000002ff2c}}, }, { /* digit=67 [{1,2,3,..,}]*([2^268]*G) */ {{0x00000725d23401df, 0x000096f178dbeb92, 0x000498bead595449, 0x000b4b459b46611d, 0x0007c72b4a58a6e8, 0x0005985adafce826, 0x00073321142175a4, 0x00000000000e649d}, {0x000052db6dbc2445, 0x0003a6bf42fe0182, 0x000384cfd9aea017, 0x000a58acd0291983, 0x0009215492e1b0c8, 0x000b5a5f0a73ff32, 0x00049b895c545eb1, 0x000000000006fcaf}}, {{0x000a5a0bc1e856f0, 0x000f28baef5de481, 0x000a8b075c84a181, 0x00058d754c8267b1, 0x0005ccf703932685, 0x0008ee021f924f79, 0x000a4be3763f30f6, 0x000000000005c01b}, {0x0006ee7749647d88, 0x0008acc01a3e928c, 0x000c22c3ac36bfb8, 0x000512e6c45e3401, 0x00084ef433f61ab3, 0x00021f5afa978fe4, 0x000a4023e2ea018e, 0x0000000000011524}}, {{0x000ecc04426e192d, 0x000c692a7fbcd69c, 0x000df4111d9bb7a6, 0x000db2d02a8feb62, 0x0002728cecbe8e45, 0x000837662176c0cb, 0x00082c33fcfbb0d1, 0x00000000000d6f28}, {0x000d967a59df021f, 0x000bc75a0f344b04, 0x0001f4de7fbff391, 0x00090cefa0453b03, 0x000ff54c96fbf4ea, 0x000f77afc5108858, 0x0002fc86b46b5731, 0x000000000006bf7e}}, {{0x000215c3f055a1c5, 0x0002fe1d42d93e03, 0x000c50c3e0aa63b9, 0x00098e783686967e, 0x000474a30dbf5f66, 0x000d20230bb5e159, 0x000f8bef86bb5bcf, 0x00000000000403b8}, {0x0001c2443b169c63, 0x000fbf249aac89ec, 0x000e2f941f78369d, 0x000960cefca9a90a, 0x00088f449c4b3b80, 0x000cfe09ef28e338, 0x000d260cdfc61bf0, 0x000000000008b22c}}, {{0x0001733d4c0dd30d, 0x000af7013d596371, 0x00017f590b1fdd3f, 0x000898e35915f523, 0x00039fd967d4bba7, 0x00073558f9fbe5f1, 0x000bea0aba8344d1, 0x00000000000ffeb6}, {0x0009792191976aee, 0x0004e928f68cbbf7, 0x0007210e163722d8, 0x000c4e06abb0ac9a, 0x000a6895762709b5, 0x0004045a401ef3f8, 0x000ac355dbe9f79f, 0x00000000000ef178}}, {{0x00094c375a95d7b3, 0x000dd7f89c2c3b20, 0x000a45fd88318202, 0x000e48b12d9f811e, 0x000dc7a43dd0be70, 0x00018ca3a703ac1b, 0x000012a4309a2c21, 0x0000000000001943}, {0x0009ce1f49259e54, 0x000e6d9597d8737f, 0x0001541e69df2d37, 0x000760df1561aaa4, 0x000e2d91ee39fcf8, 0x000bbcb6de1e0306, 0x00074699979031e0, 0x00000000000cfcc8}}, {{0x0005490cc3cc0b27, 0x0002a4073f24615c, 0x0003e0a87e36ac6d, 0x00006c18fcec6a28, 0x0005d75a73f10abb, 0x0008c94883a7d129, 0x00074165fd8700f1, 0x00000000000732f7}, {0x00049117079dd0b3, 0x00098d15d8c801e0, 0x0009200404155fcf, 0x00007c7120e12665, 0x0001f42cc9fd9816, 0x000a888cf0e486b1, 0x000249e606c16c01, 0x000000000001ea23}}, {{0x00014f7d981a63eb, 0x000cb923e948b882, 0x0000fdde16bb34e4, 0x000011a6df27debf, 0x0001d57f4ca2345a, 0x0004196e9ba6784c, 0x00026df01b370311, 0x000000000001aab4}, {0x000a2240acace9dc, 0x000d82ffdc977a4c, 0x000a7e87839c540c, 0x000c01216f09c1f8, 0x000e5b9cc0b65ca1, 0x000150569612021d, 0x0003ea910e10e95e, 0x00000000000e2ab9}}, }, { /* digit=68 [{1,2,3,..,}]*([2^272]*G) */ {{0x0008093fcd51c0da, 0x000aaac58c9dfd06, 0x00005aab38065215, 0x0004afc2cc4252aa, 0x000397c2bdf932ef, 0x00049e19a08bd48b, 0x000496ac8a7803a8, 0x0000000000075c31}, {0x000fef0d3072e592, 0x00057733dc7dec06, 0x000d0f9063e4be72, 0x0005b0847be21a8a, 0x00055ebf426f6d9c, 0x0004e9e5bfab0fdc, 0x000089d60748caf9, 0x0000000000069366}}, {{0x0000e5d6509e91ef, 0x00048b06c17a3a05, 0x0001e37973be9551, 0x000ae990038aeb31, 0x000b58b402ca2440, 0x00077732a83bf711, 0x000932b8763e00b5, 0x00000000000f651a}, {0x000cf91f09ef177f, 0x00070be02ab9cf6b, 0x0005ba59eb97ec90, 0x00072f64283f8100, 0x00072365da5e7ed2, 0x000dc6beb098cf05, 0x000d72d90e6f1805, 0x00000000000cf7b9}}, {{0x000bed14c2e5c1d5, 0x0009f89b2edba20f, 0x000638f30da8440c, 0x000d9ce8943fce4f, 0x00045a2ff9961dde, 0x0006e87feaaf07ff, 0x00008c69e60f92c9, 0x00000000000b9ee8}, {0x000d99ec41a8cc2a, 0x0005279d6d8c67c9, 0x000b28385a21a71a, 0x0005267350b7fc9c, 0x000d8a2abab0c8a6, 0x0004faf7ce9fcb46, 0x000c8a57c3bfc62c, 0x00000000000a8207}}, {{0x000f000e371891b6, 0x000b56f101762b79, 0x0004acb33b163eb0, 0x000e2aaac1dc8274, 0x0009f835a1b62c58, 0x0009915a451410e8, 0x00048d981333a762, 0x000000000000c141}, {0x0009810640a6c340, 0x000184d20b3d37fe, 0x000e4eb008d53e3a, 0x000b68c2a2645f81, 0x0007add082eaa664, 0x0005ff2067a6bc85, 0x000fcce7467dc63e, 0x0000000000004e2d}}, {{0x0000cfcf5d6b5960, 0x000cc57fe04dac14, 0x000998e82d998b8f, 0x000bd40e0a341ea4, 0x000b9c24fdba5128, 0x000c1dea81adf3cb, 0x000ef2b1ce8520f4, 0x00000000000db22e}, {0x000911256ee6f617, 0x000b2e9f05f28713, 0x0000043d1376f349, 0x00052d3f63bfade4, 0x00006cbcc395a2ad, 0x000714bd81b43575, 0x000ca6fd1d7e0666, 0x00000000000a40ea}}, {{0x0004ca398c06d768, 0x000c23d0efae2846, 0x000878540a1ede95, 0x0005a253f00eeef2, 0x000cd86161cea5cb, 0x0004a389ac2f9258, 0x000159d2b0865f5c, 0x000000000009b1f2}, {0x0008e174cdba2f0b, 0x000245a758a60599, 0x00087073a8d80dcb, 0x0005a4949d301c92, 0x00061c4bb89b8865, 0x00060259c129647e, 0x0007d106f0665ec3, 0x0000000000006619}}, {{0x000cae6e407127c8, 0x000070262c90bff7, 0x000ca8e9829543e7, 0x000f8fb1577634a8, 0x0004597668ad6514, 0x000ff6ecf4678d63, 0x000dfc90213b637c, 0x000000000007518c}, {0x0005a2999ad1c0e5, 0x00071d006db8f897, 0x0004562511312669, 0x0003aeadf6356731, 0x000f1a366456acc7, 0x000e73aeaaeaa4fa, 0x000a480df51aea1c, 0x000000000009a8e4}}, {{0x0001074c67a33fda, 0x00086a23545689bd, 0x0009b9de484075b5, 0x000247b132c568a3, 0x000dcc4760bbab0c, 0x000ae821b129a5c9, 0x000f8303eba46726, 0x000000000003df1c}, {0x000f0c5101b30f29, 0x0009f010813cfb68, 0x000cc25f999a807c, 0x00020b31fe4b6007, 0x000398dd32399073, 0x000abb34cda3bfeb, 0x0005f123f1ed1641, 0x00000000000946f8}}, }, { /* digit=69 [{1,2,3,..,}]*([2^276]*G) */ {{0x000261be9524972c, 0x0005728524830014, 0x000a9e4b0c851ae7, 0x000fa9900e4f78b6, 0x000b54a3f7a33a66, 0x00065a79afd8a65b, 0x00069a505d3f6319, 0x0000000000018914}, {0x000675265cae6514, 0x0008278367cbbd6a, 0x000c906352414281, 0x000b3f6f5af173f1, 0x000a5ca36597e41b, 0x00099f79557cb03c, 0x000ef127f86cb87b, 0x00000000000ad4dc}}, {{0x00092527cce78878, 0x000b138a49bf4890, 0x00076c4f31c0490e, 0x0009eca01b2f7c2e, 0x00005be8359f5f70, 0x000646b3fc479a65, 0x00011b6b6a22bfd6, 0x00000000000cc5b7}, {0x000c9aa1253a31c2, 0x000d18e7dbc638f0, 0x00085601e946c9b1, 0x0007e04030271eb4, 0x0008e22fb3c72d3a, 0x000e0d46cb08b597, 0x000915860d62789b, 0x000000000001d49a}}, {{0x000e171e53bdf97e, 0x0008556d65155b11, 0x00013206465d7fcc, 0x000049f10dfaeae2, 0x000ae30b70b8ef9e, 0x000c6a56219750b3, 0x00002611ed860015, 0x0000000000012097}, {0x000714d4a4467bbb, 0x000e279559d04c7c, 0x000363f176594d50, 0x0007323ae8fb3c53, 0x0009a4111f88d6fd, 0x00010a683834639c, 0x000e9afc69a029a3, 0x00000000000255f2}}, {{0x0006e6e51e1dd6f5, 0x0009766797f569dc, 0x0007480d93f86f88, 0x000f4a531adb034d, 0x000e5d185cfc18ee, 0x00053c27bcf1cb5e, 0x000569f596a59bbd, 0x0000000000069002}, {0x000a4105949da385, 0x00053d9433e78e1e, 0x00022ac847a15a5d, 0x000d7ed65d68ece1, 0x0009fb2aded8233c, 0x0009b750e201bbe0, 0x000f25987f4975ac, 0x00000000000337f7}}, {{0x0009f8de8126d12d, 0x000626fb6b7bb82e, 0x000f3dc00034e80a, 0x00089d8316ff5318, 0x00079894d65f98ad, 0x0002801704800ee1, 0x000537034ea3c448, 0x00000000000c30be}, {0x00066423e58a8102, 0x0009243c2d27d6b9, 0x000c30559bd3f060, 0x00040105eaef29b7, 0x00017b678fc76545, 0x0003012701d8f07a, 0x00036554bc6f737b, 0x00000000000e9473}}, {{0x0005ee6b65e3f046, 0x0002a3561b3fe3d4, 0x0003adfe7b57a7b4, 0x000831347fb79d76, 0x0001c48002ed4374, 0x00044dcb0a7f497e, 0x000e0686221cce2c, 0x0000000000043785}, {0x000bdab4ad1119ad, 0x000279ee9061f323, 0x000458b83a9d33ec, 0x000e85b76f7f52c7, 0x00090fd6c65f1d8d, 0x0001f8a3939a713c, 0x00040af74ca06771, 0x000000000008ebc6}}, {{0x000c37bd5d97c8e0, 0x000841942c2ff6fd, 0x000f5c9ed6475a4f, 0x00052b5771a5972c, 0x0004363c2048f3c1, 0x000db8da24cfb1e7, 0x00043dcd2ce8249d, 0x00000000000a5ee4}, {0x00044b387eb3689d, 0x000606fa84b3cea2, 0x00069e100b1b94b7, 0x00071368e13869e1, 0x000c96f0f8a12e45, 0x000d93dc039ac6a0, 0x000ec9e24458ac42, 0x000000000005f60b}}, {{0x0001937d698b9991, 0x000c7514cc1dc470, 0x0007f6d12f9a74ce, 0x00022ac2fc9230fb, 0x000d92e23e21f0e4, 0x0006d1ac0aa50a1a, 0x00049370ac46d867, 0x00000000000f9f54}, {0x0006e32302426e7c, 0x0002059a6b86a840, 0x0004338952e5938c, 0x000cff13192968cc, 0x00040b342dd8d3d9, 0x0001da44113e700b, 0x000760fd5dc7bb3b, 0x000000000002c883}}, }, { /* digit=70 [{1,2,3,..,}]*([2^280]*G) */ {{0x00067944f366244c, 0x000d59e9af31428e, 0x0009cbe9f6c4942e, 0x000bd92582864947, 0x0009b2e09205204a, 0x00056b1017995988, 0x000f260c727a3dfe, 0x000000000008b657}, {0x000fac647b56af7e, 0x0004cde35d954514, 0x000e44c1af2c53f1, 0x000261f36019feec, 0x000966511d8ffa03, 0x0001148b9afda42d, 0x0003e1f63211dd82, 0x000000000006f13a}}, {{0x000fe40d0b19b4c9, 0x0006a3997900ec16, 0x000abf1980c5bfc2, 0x0005b0a661f3c579, 0x0008aab1292b71bf, 0x000d993f244b1338, 0x000966cbe80cb9d4, 0x000000000002203f}, {0x000fa9a95e9148b0, 0x00053bc82a651a1e, 0x0005a004b90c2827, 0x000c7e7502f0003e, 0x000056a38f73a388, 0x00087d9b09c704ef, 0x0001f393cde8a734, 0x00000000000ec11a}}, {{0x0004e6a4ec3efae0, 0x000e047fe47986cd, 0x0007fd532d6e5353, 0x000fa8b9a8671744, 0x0000514bf471b76c, 0x000dcf1fc9bc87bf, 0x000fa837392dce71, 0x000000000003ad1e}, {0x0001e59290757ebf, 0x000cebbea5a33841, 0x00075b7402f28c87, 0x0004ecd9b1665aa2, 0x0006e329df225b3d, 0x000aa808de7b0df2, 0x000faf18fb438e0b, 0x00000000000dd516}}, {{0x000d8d8f4a6b2b66, 0x0002a63f27a255cd, 0x0003341f52773d72, 0x0007cd965f9ce38b, 0x0000635ba3005d31, 0x000343662162c92e, 0x000ac85259f64ffe, 0x000000000008e614}, {0x000a1c59580d5fe2, 0x000e397fb55baa90, 0x000365cc03ff132a, 0x0007325780618255, 0x00086c1e6306a57e, 0x00067b14c892f6b3, 0x0008c5f12e4c0723, 0x00000000000c83a4}}, {{0x00040eada4657ebb, 0x000e31e6f9a95314, 0x000a04269b290326, 0x00056256e8b41991, 0x000b7a4a53f9365d, 0x0002b9b16e1b9c53, 0x00070155dc1d50e3, 0x00000000000bb6d5}, {0x000b5b1121311bd1, 0x000984c270249c99, 0x000f7b0846375c38, 0x0005b610689902bd, 0x000fa4cfc5a819a9, 0x000e5b424dd5706b, 0x000a87d33bdb7314, 0x00000000000e69eb}}, {{0x000fd0482abbdf6b, 0x0004f6897401cbf6, 0x000652cc2d40814f, 0x000b32939e2b43ba, 0x0001bf809331e511, 0x00058f8f43952286, 0x000727815f6c1dc9, 0x00000000000c213e}, {0x0009a038bd421fe7, 0x0008ceb09ae59065, 0x000d25d81924ad76, 0x00015a2a20f86c7b, 0x00069aa308078f48, 0x000758878748a176, 0x0003d7f1f46a211b, 0x000000000006f6fc}}, {{0x0005626ca6bcb860, 0x000ac75ba2f9acbe, 0x000c234135494b93, 0x0009e0b610d080fd, 0x000333a99c2f3c33, 0x000580aff614ac29, 0x000a3aa5e23af2aa, 0x00000000000e1fdb}, {0x000ca5f5b322ee30, 0x00065aa603365011, 0x0001b05f57ab1134, 0x000524456330a336, 0x000b9e025aa3a2b2, 0x000a0d5cfc396b5b, 0x00083babbf77faf8, 0x00000000000ea31c}}, {{0x00047a49edb97340, 0x0002d300b04831fb, 0x0008ca060cb164c9, 0x000c5420cc10a74f, 0x0004eff9d01017d9, 0x000aa12857f637e8, 0x000114d732aa1e27, 0x00000000000e2a77}, {0x0008fc5f031be351, 0x000d262acf1585bd, 0x0001b0dfbfbd395e, 0x000c5d22e6eb2db2, 0x00028d18263d88be, 0x000bbd6acaec2720, 0x0004c04b687353e4, 0x000000000000ff7e}}, }, { /* digit=71 [{1,2,3,..,}]*([2^284]*G) */ {{0x0006ecc79d0fef75, 0x000dfa6e19d09c24, 0x000097d1dea89821, 0x00080950ee527a58, 0x000b7c4278a6ef73, 0x0000798ff78b7174, 0x0000cac133d867e7, 0x000000000009e923}, {0x000f7954ffb5e165, 0x000877431eeef1ad, 0x000728c869881eba, 0x000306a8d6af3f83, 0x0000bbec076af7a4, 0x000257ca3633bb5a, 0x0006636d07623e7a, 0x0000000000021c00}}, {{0x000f8db3d9e25bfd, 0x000ed35ae891ae18, 0x00094f42c82c0dd3, 0x000b3cae63745c4f, 0x0005f218d139c2da, 0x000f3b0e255b8c18, 0x0003fa6ab039c889, 0x00000000000c644c}, {0x0008fe1e4d75d65d, 0x000d9c8496f1ff0b, 0x00010bc25fdaddb7, 0x0008392921149191, 0x000fef73f3455c67, 0x000fcfb22e962e52, 0x0009113818baf354, 0x000000000009d4bc}}, {{0x000af695e08e48a8, 0x000683a35938698b, 0x0003114a51ff94f2, 0x0000f82899d204cf, 0x0009158780b5fcce, 0x0004edd4f4ca4158, 0x000c34c28f1bb73c, 0x000000000007a6ae}, {0x000b281e555c9d40, 0x000676d4783df7ee, 0x000d1f8a08acdccd, 0x000c2bcdf6d7f923, 0x00000f356ca3b7b8, 0x000b8e964f0a8d47, 0x0000e1229894bfde, 0x00000000000d3aa7}}, {{0x000d000279a1a838, 0x000b77f1f985b888, 0x000a43ce9b20f9f6, 0x000930a5188fcf70, 0x000ba3a82904b40a, 0x0001510273fad79a, 0x00017b7bee8d22f3, 0x00000000000c2c3e}, {0x0003fdcf0848373a, 0x000041fbe06e92b8, 0x000ae48de4a30594, 0x00090ec2d9cf7a56, 0x000a9bd062c5fff2, 0x000d353815d0deda, 0x000eda080344abd7, 0x00000000000f5cf9}}, {{0x00012d81fb28e752, 0x00018093526223ac, 0x000d23e13369699e, 0x000d26ee94c9abed, 0x0003a20b52679a62, 0x0003d5fa4425b86b, 0x000fc68164f9c8e7, 0x000000000003b12c}, {0x0006c5fe565db2c2, 0x000be6cc34bad21b, 0x0002901d6245306f, 0x000f50970e4963cb, 0x000cf0813b31f80f, 0x000f1ab8ee403ccc, 0x000b92a72ab5f584, 0x0000000000070f15}}, {{0x000e213ed814f6f4, 0x00034170098ddc99, 0x000e9c62ee04edbc, 0x000b04b8660d7749, 0x000b5152ad1e35b1, 0x0008e92aa8b4b6c4, 0x000f4e0b0bd1c24a, 0x0000000000088172}, {0x0007445379f53f7e, 0x000d513a76898c7b, 0x000f4e73336bcd42, 0x0004f973dc17e72a, 0x00060a7124b24b39, 0x0008a372c1b0cd16, 0x00003b7549880cce, 0x00000000000e7126}}, {{0x00055aa45f74a004, 0x0008dc14a3abb979, 0x0004a411c66e9f88, 0x000f1828a4be08cc, 0x0009deca5a89e49b, 0x000fbb36be6e7bf8, 0x000e57a7326cf88e, 0x00000000000c7f6a}, {0x000da2212d19f21a, 0x0005dceced37b724, 0x00062d313930a591, 0x0005b3fb62a62e4c, 0x000793e5c0e1a7e6, 0x000b8d77382cb79a, 0x0002f014c9a99461, 0x000000000000b05f}}, {{0x000a2dd7deb1dde9, 0x000a831d31f799b5, 0x0008e986349103b0, 0x000362e52f04d685, 0x000921c7b6511793, 0x0006f47f65808e70, 0x00040533fe9123ed, 0x0000000000058f71}, {0x000d5dbe8f1956b4, 0x00061821d30451f3, 0x000e7b4e166f399a, 0x000db145b2048aa2, 0x000ed7811330932d, 0x0008fd85f17d989f, 0x000434032ae4cb12, 0x000000000007d1ef}}, }, { /* digit=72 [{1,2,3,..,}]*([2^288]*G) */ {{0x000acb4203cc71b2, 0x000a9070d34e112c, 0x00047b523d821ba6, 0x000f9b95eb8ad292, 0x0006a6a45dda269a, 0x000df41e0dde0a03, 0x000f2aa18b528e63, 0x00000000000a260d}, {0x000c22d6a6aefb01, 0x000d424a67709f9b, 0x0002a9971343d570, 0x000e2a1968444330, 0x000d131a6cf073c1, 0x000e794543660558, 0x000dcdb0289c832e, 0x00000000000c6d8d}}, {{0x000d86ee6f475d5b, 0x000d30ed1082f1a9, 0x000a6711ccf28680, 0x000ef0eece773534, 0x00064bf0c426a35f, 0x00011b2fb76adaa4, 0x0004d3fbab929aa0, 0x000000000009d8cc}, {0x000bb954fd395b2c, 0x000dabe6d7f2076f, 0x000a4cbdfe911e02, 0x000cba5106ceaac2, 0x000a45258697c7e2, 0x0005945b0fe94528, 0x000f7a7109b17d07, 0x00000000000cae17}}, {{0x000ce6be22a12c0b, 0x0008a6855029961b, 0x000a3c801158be2e, 0x000d2b4a8e92e70b, 0x000f0cc9fca9f601, 0x000bc2e96fd02799, 0x0009b889f99ca013, 0x00000000000ff9db}, {0x0006b1bd37f91ceb, 0x000616ae70849faf, 0x0005d65bd4da44b0, 0x00092a4e0945e8f9, 0x0002ecea36f6394d, 0x00018a069ddab675, 0x000860650b74d60d, 0x00000000000ad650}}, {{0x000bf5b4a4380ef4, 0x0001cfc1faedb8cc, 0x000e6ba03d77f4c0, 0x00085456416defe8, 0x0000c58653e7f004, 0x000f6f99e75de777, 0x000c07dd2dcbebe2, 0x00000000000d159a}, {0x000c9af1998a9b17, 0x000a045dd713c4a8, 0x000e1c3678ddf502, 0x000756b6b962b38d, 0x000bbffd3f0c3f73, 0x00008ebae3cb9f53, 0x000dbad723c40b7f, 0x000000000000c3cd}}, {{0x00003107748ef382, 0x00058a804b2f0156, 0x000b319b886fb1eb, 0x000f4fd353970be7, 0x000712854a9131ba, 0x0009713983481c8b, 0x00094ab0424eecf3, 0x000000000000f4ed}, {0x000648ea129bd87a, 0x000a992b74ad013d, 0x000692f5d2444d08, 0x000b28070a5f0c93, 0x000b9f5101ca6741, 0x000d0f81e46c12cf, 0x000288e7014d7901, 0x00000000000d758c}}, {{0x0000c39f81600214, 0x000686a565269228, 0x000c17ee858626b0, 0x00011a7d8c6ddb92, 0x000b2332347b0bda, 0x0009dff48b7ebfaf, 0x000c83cf791881e9, 0x00000000000dc357}, {0x00082704ffef2257, 0x000fe2a264f8831e, 0x000c9352584eb7a7, 0x0008260bb47d4188, 0x000c3d8170326d47, 0x00005f901544de4e, 0x00063cac7150a9dc, 0x0000000000075c09}}, {{0x000bcfd07a0f22c4, 0x0007c58805ca858d, 0x000b1c2b2351e4ce, 0x000c9a1349cfed00, 0x00017800a980f9cb, 0x000847e9d67bc7b4, 0x000c48e7e6dbc0f6, 0x00000000000af379}, {0x00047d63263e04cc, 0x0003c80b6fc048b9, 0x000808eb22fe8f7f, 0x0001ed14e9dc24bc, 0x00073fab87e6d2d1, 0x000c630ae48d74f1, 0x00020a1feca5af50, 0x0000000000062d06}}, {{0x000e56ad2bfbbdbc, 0x0008ff6377e3bcab, 0x000f30b92835c3f0, 0x000ac42c21c0cf1e, 0x0009857d8edb7f85, 0x000b77ed67a3e31c, 0x00010b2eb1076327, 0x0000000000038dae}, {0x00026ce2d0dbce6d, 0x000dced7c6fb0aad, 0x00066cec0d07ac1c, 0x00035504569e7309, 0x0007bedae3ab4dc4, 0x00027e463aa82fb9, 0x000a1106d37bef4f, 0x00000000000f0c35}}, }, { /* digit=73 [{1,2,3,..,}]*([2^292]*G) */ {{0x00011f784b3a0046, 0x000066edf5561b45, 0x000c8578d54224c1, 0x000ae56d8d66d29a, 0x000ae9d58eb27699, 0x000f9176d5f81602, 0x0003b1d0c04874fa, 0x0000000000052315}, {0x00067980492adf03, 0x000309690930fad0, 0x000146ea47ef3788, 0x000725873bcba90f, 0x000de902e3292d0e, 0x000bc27b957efe72, 0x000c093fcd598676, 0x0000000000093940}}, {{0x000cdd973668c530, 0x00077c68b641e912, 0x00064e1ee190b62b, 0x0008cbad89ce6688, 0x00006c269d8eeda9, 0x000f3402315f84dc, 0x00034af0eb685ecb, 0x00000000000c0326}, {0x000bc909db075650, 0x000562e3d7fff094, 0x00012e59576050a3, 0x000abcfa3e050e0c, 0x0007c001dcd9f02c, 0x0006d2d52ccd2da6, 0x00041f50aa372306, 0x000000000007224a}}, {{0x000ec1f1185b9762, 0x0007e4b1f8698c94, 0x000d0af36ed765ea, 0x00049f56536e156a, 0x000109c95a75ba1c, 0x0006d9af131c3163, 0x0008b7268a308f0a, 0x00000000000fa9ca}, {0x000f13b9ac944487, 0x000b1c3b1cbccb86, 0x000446bb4e60be0c, 0x000c7b334396850c, 0x000a048a69431b4e, 0x0005820bf42f21d5, 0x000a580bf948f55b, 0x00000000000b48dc}}, {{0x000b86ea9a29c966, 0x000cd04418b58cb8, 0x0002d1612a6d4e73, 0x000e22c7c65a6da4, 0x00051dbeffe45f87, 0x0003cc05caac7106, 0x0002c4ff619d64bd, 0x00000000000e65c9}, {0x0002126bd4b5ea52, 0x000d123af2b21062, 0x000e0691b9e9f16b, 0x0007efac6478c561, 0x000af6cd140ec34a, 0x000a0db2e57cde95, 0x000b7664b74575f5, 0x0000000000075d7f}}, {{0x00078c972345257c, 0x00058a9532cb266c, 0x0002b89ba64976de, 0x000067545b1733a4, 0x0004cc6e65dd74ea, 0x0006ff2aa7f37f02, 0x00079e6612b1425c, 0x0000000000030374}, {0x000f1ac7f7aa2f0c, 0x00097e512bca4fe9, 0x0003049963042b95, 0x000bd29a259d6515, 0x00077373034f5b97, 0x0005aa640215eb65, 0x0008b779da0fc488, 0x000000000007e435}}, {{0x00041294c6ef7a53, 0x00023ce3cc51372d, 0x0009af7f675a386a, 0x000d981efc9f71b0, 0x000a20bea9baa9e6, 0x000ef7c1fc01ded6, 0x000a5cc4b7e6424f, 0x00000000000f9dec}, {0x000954a122b474b3, 0x0002aa0a43d0a3de, 0x000a0d55c109a592, 0x000a173b5d57bbf3, 0x00056299978197ce, 0x000ca2bb13c3f30f, 0x0002e069a7820a8e, 0x000000000000ff69}}, {{0x000deeb8201c384c, 0x00029aca3f998176, 0x0001642e9c9fe922, 0x000dbd63d82750be, 0x0002faa3400be031, 0x0005fd54bfb2552a, 0x00030374e9b5d365, 0x0000000000035894}, {0x000839a12661f3f2, 0x000a15a575a4221a, 0x00056e3aabcc078b, 0x000ada596e1e1175, 0x000d0f305dc3ca6f, 0x0008d7af5126e9af, 0x00069391da8d7305, 0x00000000000d8353}}, {{0x000cb9cfccb5f12c, 0x0002c28405061c1b, 0x000211e4805b5eb0, 0x000944405547f7c3, 0x000d3441e472789d, 0x00044ce877fa445e, 0x000d14feb198254a, 0x00000000000129ae}, {0x00073247d16dc8ed, 0x0008622b05de2de2, 0x000590692ea55dfa, 0x00052caa83f7f094, 0x0006cefaa757fba2, 0x00017d8060f6ad6e, 0x0007ade1ad187165, 0x000000000008e9d9}}, }, { /* digit=74 [{1,2,3,..,}]*([2^296]*G) */ {{0x000c5ac4350713f2, 0x00062cbb991946e6, 0x00025875bf6be408, 0x00024aab6ab6c041, 0x0000bc41f4b7d50b, 0x0005496cf419d281, 0x000ac0e2e88d7a29, 0x00000000000f2457}, {0x000a357ad05dad34, 0x0008e838e4a3533c, 0x00068ef45f1df4fb, 0x000ab1c7a5c5fdd4, 0x000dde34cb8d9fa3, 0x0009105fe324798c, 0x000249bfa5a9d088, 0x00000000000fd0df}}, {{0x000b286ea52474ce, 0x000419974759bb2f, 0x00039b1e3f8aef8e, 0x000c58ec64941cb4, 0x000a01d055758afe, 0x000448db52d7c57f, 0x000440c07c74cc5c, 0x0000000000001bb1}, {0x0007977c86a9c43f, 0x0003893162d96796, 0x000ee52587841e45, 0x000c57e6af18dedc, 0x000f174a30894f28, 0x000dd626536faed8, 0x000d7b702dbd64a3, 0x000000000006adc0}}, {{0x0002a70e7d991630, 0x000854981be688ec, 0x000de0f53a95f8f1, 0x000e05074cff00d2, 0x0001b52c7f9c3168, 0x0001c7986111150a, 0x0002ad0db2ed84a5, 0x00000000000e6127}, {0x000c16b3e4d1fe2a, 0x000897443d935440, 0x0002c51d6c8aaceb, 0x000ef4e866b5e41e, 0x0005b965a67071e0, 0x000e1aa7705c57a4, 0x000e3285bdb58c70, 0x000000000009df3c}}, {{0x0009a11de31a0e3c, 0x000c6c41e4aed12a, 0x000342590d5103b5, 0x000ab7b8ed812d38, 0x00081afb58b8f5ea, 0x000efcc3a7801fbb, 0x000b91be5cdba671, 0x00000000000cd10c}, {0x000761b96524aa0d, 0x00013882e821e20b, 0x0008d1b11d20578f, 0x000de2bd8a0f0393, 0x000c857fd3a03afe, 0x00060f767e20a117, 0x000da1ebaa2aa430, 0x000000000002b9d1}}, {{0x000d9fea4e493f3b, 0x000e070e478fb44f, 0x0000254b6a02edec, 0x0002b005be36ea75, 0x000f6717e06aaec8, 0x0008f197782618b8, 0x0000d12db1f6d400, 0x0000000000016b39}, {0x000ddfa794ec9644, 0x000bafe86fd4d041, 0x0006bc15de0d2bf6, 0x00023e70c0491593, 0x0005ed4562356cbb, 0x000d836efd05be7e, 0x000604601374069b, 0x0000000000032e5f}}, {{0x0001ebab46405b61, 0x000f009db138cd2b, 0x0009fd7df23c53c0, 0x00047794feebab9a, 0x00017fdb1e710bb6, 0x000f1f65dfce4aee, 0x0006cd7d5c0c61a7, 0x000000000008d02d}, {0x000621234d968fad, 0x0005c7cac0485224, 0x0002b8dbf87d2555, 0x0009a59db0aa864d, 0x0008ff94f8b5b587, 0x000c97f8e75f391b, 0x000232a6c994ae49, 0x00000000000d690b}}, {{0x000e6486f79bfa96, 0x000e507c60c742b4, 0x000d5aa8cb9b07e8, 0x0000a09dcba89982, 0x000a802ce50ca8b0, 0x0002144b0a77f1f3, 0x0000db6c4050df2a, 0x00000000000ab1b1}, {0x000a93fc6ce00720, 0x000e89025d46fd65, 0x000c1e4037fdb9f5, 0x0002d629ae2d5361, 0x0009eff0f6a9bcad, 0x0005fa5a07a15282, 0x00039ce87345cd92, 0x000000000000e840}}, {{0x000cab548e246919, 0x000d15017e1454d5, 0x0005f67186d3e9b6, 0x000059dfa98234b5, 0x00099985af982541, 0x0005b7b1c4bf344d, 0x0001ad39737ed67b, 0x0000000000087c41}, {0x00069e3ff4c10920, 0x000022fad8cecc3b, 0x0008e45c000ca718, 0x000d856404043f8d, 0x0005863927a11a53, 0x0008921216c1f07a, 0x000c8f38d3a4f4b6, 0x0000000000001976}}, }, { /* digit=75 [{1,2,3,..,}]*([2^300]*G) */ {{0x000dd4906efe62a1, 0x00063bcc8842253e, 0x0007a247757fdab1, 0x000a1ef2571d6b1e, 0x0001739a956e745d, 0x000bffc16f01c292, 0x00072ceffd8065e4, 0x00000000000f36fe}, {0x000478592361b14b, 0x0003ff49e90d1ebe, 0x0001338e12b047f8, 0x000b583b7240d91d, 0x000c03f8387fcb78, 0x00000f2d92e1a7c3, 0x000a8416566c2232, 0x00000000000aaf80}}, {{0x000f32d335de93bd, 0x0002d7a1a522aee8, 0x000b425f9e81403f, 0x0004abe3d4ac4abe, 0x000337f996e841bb, 0x000727761c52950b, 0x0007d201d991e679, 0x00000000000978fd}, {0x0006e2e2907ff054, 0x0007486bad5e5c68, 0x00010431aa78725c, 0x000eb7705757453a, 0x00093939df7758ff, 0x00078ea0fbb18612, 0x0001d3bfdd394a6a, 0x000000000006e33e}}, {{0x000c3ccc7d56f63d, 0x00076db1cffd2381, 0x0002131b488cf4cf, 0x0001e5aa3c1db85a, 0x0001ac55d391a418, 0x000d270d0e5183e5, 0x0005462793d5efef, 0x00000000000c0631}, {0x000c80c1d49264dc, 0x00008ecb40a58378, 0x000aa60ec18fee5f, 0x00014ab6c5830fab, 0x000ca03f201ea89b, 0x0008c54f64dc477d, 0x00066e5604f5dac8, 0x000000000002acfc}}, {{0x0003e9c742a5516d, 0x0009da7f29531cb5, 0x0007fe865f9eba30, 0x0004ce9efae348cc, 0x000cac52758dd2f5, 0x0002961a45acb931, 0x000fe1287b3e18d2, 0x00000000000748f8}, {0x000f0554bb131f76, 0x0001d1b62b340cc5, 0x000b08ad2a8e1d6a, 0x0008dadbe8da8486, 0x000954f18276bad7, 0x0004bfdad85fa710, 0x000237e2cc9d287c, 0x000000000002c75f}}, {{0x0004d2c2f1f927d3, 0x00033283dd7ef2a5, 0x000a91f40054b9d9, 0x000c095870282aba, 0x0008f4e36324ba08, 0x0004cecf2b02b00d, 0x00024e53aaddc060, 0x0000000000084ddd}, {0x000a889fa3214142, 0x000ca34bc00a03f8, 0x0000c263c00349e0, 0x000eaaacef68f74d, 0x00023c0293515228, 0x00042e3b740a790d, 0x0001e0e0e9af5c84, 0x00000000000a9f14}}, {{0x00087ba6916bcaca, 0x0005bcdcdd7d6721, 0x000b58247a460e0a, 0x000c569c00ce5c40, 0x000fc589d0c75923, 0x000fa6fe6099c17f, 0x0008c40335eeea89, 0x00000000000a4e86}, {0x000a7415516e07c0, 0x00024b7037325a9f, 0x000944c467e9c1bd, 0x00032efd5e26d28a, 0x0008de919cbedf31, 0x000bbb18d7ed994b, 0x00050812df67cd6f, 0x000000000006baff}}, {{0x000c3f58ee594ee5, 0x0008b72f4949e0b4, 0x0001e5bef192dfaf, 0x0004726092a58066, 0x00010f5cdb7271b0, 0x0004bfc49ad5c3c1, 0x000be7d4951f9e55, 0x000000000006131e}, {0x0009f77a3840f92f, 0x0009237da59f303d, 0x000ff0c06b034503, 0x000962a4d89fa660, 0x000e71d824f5d020, 0x000050e312610c61, 0x000bfb9c917da73c, 0x00000000000e6e7e}}, {{0x0003a9eb85c489f9, 0x0003af2ec9ef5122, 0x000d827990bab108, 0x000b2387d2ac6e41, 0x00020318a3b790e2, 0x00084a7a0cf682b1, 0x000d057fe76089ea, 0x0000000000016546}, {0x000bc6c0a0421345, 0x00041f987118eca7, 0x00079f0cde4a8da9, 0x0007774888a7e8d0, 0x000a63ec5831544c, 0x0002fe985bd2647b, 0x0003e8b479cea3fd, 0x0000000000028d16}}, }, { /* digit=76 [{1,2,3,..,}]*([2^304]*G) */ {{0x0005b08a8a2a82b4, 0x000fa04baa17598e, 0x0006a0661405c62f, 0x000031dc6cd61096, 0x000030bf87a5c4a6, 0x000e497ccba2534d, 0x0006657ebc6e2131, 0x00000000000851fd}, {0x00018d257f3e221b, 0x000e69ecae010ee2, 0x0009788f9b15d390, 0x000a9c22fa527837, 0x0001236d442e39e8, 0x000c289ce74c9380, 0x0009cf8b21ba23b1, 0x0000000000025c76}}, {{0x000aafc618669c84, 0x00037761e10e2b1a, 0x000c03aea1a1a99e, 0x0000ff43dbc6fcaf, 0x0006cbe0ba8aa087, 0x000f1ff6a9765128, 0x0005b647d46075c0, 0x000000000003abeb}, {0x000f7f59840e13b0, 0x000af1234c80e297, 0x0000d9f885a37dab, 0x0002d41d82ab780a, 0x000fde426e50399a, 0x0006dde778a03afa, 0x0005eca2bcb109ca, 0x000000000000618f}}, {{0x000adbd12143606f, 0x0003e0d27500f7d7, 0x000cde21714cb370, 0x00078f8610763e40, 0x000f47ef08feee75, 0x0007d04c06e56078, 0x000aa3a8d03a7f04, 0x0000000000027cc8}, {0x000677d27af9cf4f, 0x000056b08eb37c00, 0x000a4a2b5d3fdd3b, 0x000869ae3f10ba99, 0x0003e500e8466f9b, 0x000171b1a3bfb983, 0x0000456d975557b9, 0x0000000000018fa0}}, {{0x000e348941e625d9, 0x000fc15d47e52aa7, 0x000dc7038ccf5369, 0x0006a3070cddb11e, 0x00032b5a8db75122, 0x000f37d6563a253d, 0x000b91e8be4d1fbe, 0x00000000000c0920}, {0x00045423a83becc9, 0x0008308b713a8319, 0x000ebb9d576c8cba, 0x0005877917ee393e, 0x00091528cd12a897, 0x000daf6aa294792e, 0x0009b94512dc8c37, 0x00000000000197a9}}, {{0x000e5d8cfc9c3b49, 0x000e0cfebe026cd6, 0x00010748e4a52d81, 0x0009d16725ebd099, 0x00007a584e8d00f8, 0x0001cab5894c6f2b, 0x0003c8095ac9cc91, 0x000000000009c407}, {0x000462695d0ed83f, 0x00056265919b06a1, 0x0003cfa033d1cd2a, 0x00097f1815a70aa4, 0x00001c5fd35a6db5, 0x000d52a8bdd9e4a1, 0x000fab38b8e35112, 0x000000000002ef20}}, {{0x000003aa77fd8f2e, 0x000b43b21dc1edb9, 0x000008b1e2380339, 0x000e5d30da87d664, 0x000f0cd999a0f536, 0x000e08f5d4ce10ed, 0x0007e68949181450, 0x0000000000052664}, {0x000bcdd23ee4cc2b, 0x000a3cb207ee8e61, 0x0002ac9dd73c4f6c, 0x00040d225e0cf154, 0x0001067fa0527d49, 0x0008b2e21b688b31, 0x000eab89308326a9, 0x0000000000072311}}, {{0x000c6c4de58ef59c, 0x000db2a6280408d6, 0x000f4e9cd796cbfa, 0x000daa3c647fcba8, 0x000f4952d3a44a2c, 0x000e2e2c3e1a9e91, 0x00040ebc1b3d8011, 0x0000000000018e43}, {0x00017ee00926dad8, 0x000cceb8696ff13d, 0x000436379cf7b867, 0x000d6ce6c1e905c6, 0x00091ed2e8cba471, 0x0007c8c914e13d60, 0x00084e52951509c7, 0x00000000000e2348}}, {{0x000a3b1514eda4ba, 0x000ac37be5d3f53e, 0x000cab6203ce338b, 0x00024b59d1569e7a, 0x0009b4e293ab165a, 0x000b7c0a4254aaf5, 0x000b183c751fbd6f, 0x000000000005018c}, {0x0000fe7bbd1e6c72, 0x000eaacb3b8965e4, 0x000a2f2ab6db69d7, 0x0007258621df6d82, 0x0003185f0e2a245d, 0x000ddbd812af0e28, 0x00002a1e7edc818f, 0x00000000000c538d}}, }, { /* digit=77 [{1,2,3,..,}]*([2^308]*G) */ {{0x00042da90721f8f9, 0x0009f6858b6747d2, 0x00082ecd0813dd9f, 0x000674e29d9194d6, 0x0006dcb30a51324e, 0x0008aa5492dc6fdf, 0x000a923f3ecb7752, 0x0000000000023ffa}, {0x000c7344981b01f4, 0x00090d8efcbd58f8, 0x000d0144b46e312e, 0x000b0b74cf4a1708, 0x000fbbf335fd04f2, 0x000928c36bc0bb49, 0x000d45c6b6e5bd5a, 0x00000000000d893d}}, {{0x00016a2799bedc34, 0x00022fb083c2a5e5, 0x0000296a1d9c8cea, 0x00030e747a81b965, 0x000658a987376e41, 0x0002829c9cd704dc, 0x000d63842ae32959, 0x00000000000be20d}, {0x000f531daa9bdad7, 0x00053abee8e552a9, 0x00078232300aac8e, 0x00039b2467112ba1, 0x000fbe341038781f, 0x000a2f8be6f06058, 0x00066e5effdca512, 0x00000000000af344}}, {{0x000afa3ee32c886c, 0x0006d3933b4c0742, 0x000439c40f3f936d, 0x0003c0f0b7e019e4, 0x000fa48715d652fd, 0x00039be537f8e5dd, 0x000cdc0879c5defa, 0x0000000000056f01}, {0x0005bfa2d160b7fa, 0x0004671b2dcba45c, 0x000e0bb6fffdcb60, 0x0004846640b2d753, 0x0000049a2cbe6af9, 0x0002ab0f178a1071, 0x00043841a1ce67ac, 0x00000000000a76d8}}, {{0x000a317691072fc1, 0x00025ab86639e0b1, 0x0006a85f7a13b8bd, 0x0004418d763f0bbd, 0x000211a9802cb573, 0x000269b8ad2cc332, 0x000355e41d7db881, 0x000000000002ecfa}, {0x0004e57bc1e94af4, 0x0006159d6912442e, 0x000356e842631b03, 0x0008b6b8a7397395, 0x00091cc83ae38447, 0x0007ccd97e86ad7d, 0x0004c6bc9b208479, 0x0000000000069494}}, {{0x0006d3d1d84bf486, 0x000a4bbb6725a843, 0x000b1260c5ec574a, 0x000dd0664bcb2d64, 0x000a780d5c1bab65, 0x000a61e6e755e848, 0x000b4b84e6f686a3, 0x00000000000bd100}, {0x000cfe4a11d7ea4f, 0x000a3b34fdf84517, 0x000d9afd2967c440, 0x000c881f9a125f0d, 0x00064aeadf8e3c2c, 0x0006bf0c2b1fcce5, 0x0001bebdfc54c0c4, 0x0000000000009d28}}, {{0x000af84d84069bc1, 0x00010e1aa844a91f, 0x000628bd439b9e84, 0x000aba65ddcb5d25, 0x000a38009c6a3025, 0x000261ee5ac8cdab, 0x000430b9ee07b46e, 0x0000000000006ab8}, {0x0003196ba81697a7, 0x000207a36b461d0a, 0x0005a884d3b0fe10, 0x000f469341275a1d, 0x000f1c7cf858ae4e, 0x00092af3df7cb393, 0x00017683c00eafd1, 0x00000000000a1e15}}, {{0x000475d9329b61bc, 0x00078687d0980c72, 0x000d109af3ad73e4, 0x00007fabbcde5b3c, 0x00016ed103a56414, 0x000a6ee2212ec9d2, 0x000c11f858c7851f, 0x00000000000818f2}, {0x000247f6c002433a, 0x000a04720d42a19d, 0x000f64099b42a8aa, 0x000f25533723e4ef, 0x0003d3260b6299af, 0x000391c33d6c67ce, 0x00038163a6fc9d86, 0x0000000000031de2}}, {{0x00092324c0c2dff4, 0x0004f585edee2c89, 0x000820f42406ab00, 0x000924fd85ad3203, 0x00019124bffa3bd7, 0x000c628682e7d8f9, 0x000f5d885397c044, 0x000000000007fda9}, {0x00035c11900b0d2c, 0x000e6d302582e314, 0x0003e1f066fcf73e, 0x0006b5b63653c06e, 0x000d9c70dad4b021, 0x000bba93d8f08a1a, 0x0002b7ccf014aaff, 0x00000000000a33f1}}, }, { /* digit=78 [{1,2,3,..,}]*([2^312]*G) */ {{0x000cb198f774dfa5, 0x000dd1e347819af2, 0x00020411ce747fbb, 0x0005ccc28af85bb9, 0x000b3ae9ba11fc18, 0x000bdb313c923d78, 0x000b877d494d7ea7, 0x00000000000af8f8}, {0x0004fe8c8323652c, 0x000bdc178ccc093c, 0x00006a94572bacfb, 0x00047cc80a50372b, 0x0000e6f901976087, 0x000c2f2168147aa9, 0x000b514683d4c978, 0x00000000000552f3}}, {{0x000f8017d10c6b96, 0x0002229d81537326, 0x0007f1980aaaed23, 0x000ce6e8783d1fe4, 0x000df0e3c126aa4a, 0x000ca4b719c14ebd, 0x000f350eb1c08d6e, 0x000000000001c91d}, {0x00013bd5d85a7c75, 0x00064db8119bb0fc, 0x000fdf5036f03e4b, 0x000916835436f82c, 0x000b9b18d212053c, 0x000bc3497eb41ccb, 0x000d8193b3fb43b1, 0x000000000008c1ce}}, {{0x0007ad7a8ff88fe5, 0x00031521f4af6aed, 0x00033eaf4c7af196, 0x0009ab7ae0377807, 0x000db65f73ffad09, 0x0006059b9541cadc, 0x000f8253430463a8, 0x00000000000043e9}, {0x00061f938516beb2, 0x0001bd515f4c75f1, 0x000d0a9d767932f1, 0x00053567ef1b9007, 0x000f1295b5fe7bed, 0x0009176278782b45, 0x000d9fab54ebaa03, 0x000000000008787e}}, {{0x0006f626b572390e, 0x000905255508b5c5, 0x000fa6a60258070c, 0x0005eea3095205c4, 0x00002c470ef7d976, 0x00040bf0afea2ed7, 0x000a16f5e8a0fc9c, 0x00000000000e4137}, {0x00055209e40da33c, 0x00003b917537047e, 0x00003ab2893cdb40, 0x000bce9023854871, 0x0008a8bc3a94bea6, 0x000c450444620840, 0x00015164a87a2a3a, 0x000000000007df70}}, {{0x000cf2f10b0520cd, 0x00004c38d07270c5, 0x000e4dc64fc6cd1a, 0x0001d8f300e953df, 0x00040a7dce63abde, 0x000425847b98b23d, 0x00061b63e51543fc, 0x0000000000043a21}, {0x000d54e8ecf42bd9, 0x000ee2650a1d5920, 0x00086c043a07e5a3, 0x000b7048bd9bd78b, 0x000df89e86bdc15d, 0x000579426bad1dba, 0x0005f8d7d4845024, 0x00000000000287bf}}, {{0x0006ca98107f85ef, 0x000615fb05303f18, 0x00091aa7ab0bf32f, 0x0000fa47d92132d0, 0x0008994564bf7a0a, 0x00029e066e993faf, 0x000574bf30252517, 0x00000000000d4260}, {0x000990cf5caa4f19, 0x00009f1eecc3d948, 0x000f8dbc962efd6e, 0x0001cf1d1dd88736, 0x0003b6f1aae115fd, 0x0009344b97ce882a, 0x0009ca7efb7ec6da, 0x00000000000cc5b5}}, {{0x0003c28364de2038, 0x000c48bcbf6cdce6, 0x000e355114722287, 0x000febf92ebe1bcf, 0x00019af24c2e4ee8, 0x000a861d57847829, 0x0007ec618760b094, 0x000000000006bae2}, {0x000de113e64c1ae9, 0x000fc77c174b9e18, 0x00055d1ba670f4b5, 0x0004f6a58a0062c2, 0x00047781acd1db9e, 0x0006d86b03480c9b, 0x000ef52d7c628ef5, 0x00000000000b3e2e}}, {{0x000ade0c1eab3d7e, 0x0000fee9e25d91a6, 0x00060f30210199eb, 0x0001157d2d91300a, 0x000fffcbe50fd2fc, 0x0001d376ee7597e2, 0x0005624be3814fe1, 0x00000000000dbf14}, {0x000860a341c4b797, 0x0005638a107c07ee, 0x00045c1dbdbe39f3, 0x0004e09caebd481c, 0x000bf9ace60d1801, 0x0001cb8e7b28c331, 0x00065ee8fba04f21, 0x00000000000e42dc}}, }, { /* digit=79 [{1,2,3,..,}]*([2^316]*G) */ {{0x00060f98795275e8, 0x0009d009dc2f44a9, 0x000392d1d1132d95, 0x000faa2ec5d91fec, 0x0000f160afcbc89b, 0x0007566b5461be9a, 0x0009a2fdd084bb7d, 0x00000000000e4809}, {0x000f69da99c8ac01, 0x000bd1b461fc964c, 0x00012ac0cf0d2b27, 0x000332d9f09a206f, 0x00036941d6ef3246, 0x00087f5f6bde4c0c, 0x00040044ef03fdf3, 0x0000000000057b63}}, {{0x000b480bf51dac8f, 0x000ea7e485158a07, 0x0002c9e9ee8b46dc, 0x0000dafa6fbabfcb, 0x00038f09fff720de, 0x00006994f04f0158, 0x000d335a0562976a, 0x000000000006e3cc}, {0x000d89d62ca77de2, 0x00045c087ef9c0e4, 0x000f0235509703e4, 0x0004814d916ee937, 0x0008d23d140b4fc0, 0x00062028f3369c97, 0x000adbb0fcd70f16, 0x00000000000e1e28}}, {{0x0003a6684cfed7ee, 0x00094e3ccfe8dea6, 0x000d721274c869f9, 0x000e2cbb605c4274, 0x0005b0d809923f13, 0x0009913815ee1239, 0x000b6e4dcaea94b9, 0x000000000008c4c4}, {0x000ec88cc6307d53, 0x0004bd7aad54ab94, 0x000859bdd379b119, 0x0001eee68048fd9e, 0x000fd57225fc6eb3, 0x0008dfd3f693842d, 0x000cf13e62cd85a8, 0x00000000000d5462}}, {{0x000df1c3e7de2ba1, 0x000ff99b5f14f615, 0x000c00e1f8e35232, 0x0003900ff19bf251, 0x0000260925ede749, 0x000ea1eafc82e5b8, 0x00021e3398d340c0, 0x0000000000012871}, {0x000896ddafdbd954, 0x00046ea6dfb0ad7a, 0x00039aa9f60646cc, 0x00078bf1201299a2, 0x000d32e5cebce266, 0x000181e32b5369e4, 0x000add2304eac86d, 0x000000000003d364}}, {{0x000f357cfbf02e91, 0x000a2f55f868d743, 0x000049d92d19de08, 0x000ff9bbb5ba194e, 0x000957724703bec0, 0x000e0e4fbf7325c4, 0x000d7c5ab8f06323, 0x00000000000ecb0f}, {0x000a0f97049bea9a, 0x00069cc72e8da9e4, 0x000c7a0fc237673e, 0x00046e64252763c4, 0x000eb8d81de3bfa6, 0x000772f007a769ef, 0x000a5ef5ec70031e, 0x000000000002729a}}, {{0x000cc742f063ab99, 0x0003b51f19bb30d3, 0x000878f139d45b8c, 0x000de2f987112cb9, 0x0008759de2cb5f7c, 0x00049bd98dc51d94, 0x0001fd9d05c410ed, 0x0000000000036434}, {0x00020d69ae77fca8, 0x000a9d7869d68233, 0x00007a8daf0bfe29, 0x0008180c25910747, 0x000a6ebc4ebc7f25, 0x000da1d687b90fc7, 0x0004935565390f3d, 0x00000000000a44e4}}, {{0x000116432be8131b, 0x000ebb4a2742da3f, 0x0008bb7a8fda7aaf, 0x000adccdd7fcf4fc, 0x000337d4fcc6b15f, 0x0001c7ab70b1fa2b, 0x000cc9242c7b26f0, 0x0000000000050574}, {0x000069eaa2593652, 0x000b76ee50f421b3, 0x000a5035e1a2b7ad, 0x0003af18420501c6, 0x000b1b6e7d2a04d1, 0x000516f80c22e092, 0x0005b5a393be7ee9, 0x00000000000b80bb}}, {{0x0003f2ad59508de2, 0x000bd9e41b9b6b62, 0x0006d3eb906556a9, 0x0000c8cf272346c8, 0x0005def5749367e5, 0x0002676fcc98a5ef, 0x000659c2dea8afa0, 0x000000000006ace4}, {0x000f1f5cd12db7d7, 0x00090c2b707aa093, 0x000d4cda421d1577, 0x0000fa2a778c20c3, 0x000d57af166b5b58, 0x00078ce62272c3a1, 0x000087e47a64a9ca, 0x0000000000071d35}}, }, { /* digit=80 [{1,2,3,..,}]*([2^320]*G) */ {{0x000e3ee1ae74a706, 0x00069c20fb9106bc, 0x0005cf0e923045cf, 0x000bc6a5cc0aa89b, 0x000b4fb9f01e12bc, 0x000ae1b895279c6a, 0x00003cbc8e178911, 0x00000000000c2900}, {0x0006736dff18cbd8, 0x000579949d6eb7ac, 0x000931ae3b95e19f, 0x0006ee2dd2275c0b, 0x0008c419f1d568de, 0x0002b5a40a9e4fff, 0x00096dbc759ca4a5, 0x0000000000063b09}}, {{0x000eafd50b503ff0, 0x00058f682715078f, 0x000b7ec2b450662f, 0x0008f55c51916c40, 0x000b61ee081fa46c, 0x00064872a98c3524, 0x000faa5ab7f2c2ad, 0x000000000007e555}, {0x000425ebf2c1673e, 0x0003c802e0d22c20, 0x0004e9f77f229a7f, 0x00019087af20d270, 0x00016be50784b56d, 0x00072b8518d619e2, 0x00076e10fdbb7213, 0x0000000000049355}}, {{0x000df2627e9f5583, 0x000e073c57fde593, 0x000f9da9fd5339d4, 0x00071f1cfb9821f2, 0x0009cf6a1d68d25c, 0x000d24e649427e20, 0x0008b5bf3c3916ac, 0x00000000000bda7b}, {0x0001a88dfb057584, 0x000e2e7c5f7c7d49, 0x00071c4b5c378478, 0x000c472e66b277de, 0x0007b2816f1e818d, 0x000383c6d4413fd4, 0x00053740f262af48, 0x000000000004f190}}, {{0x000aa901e2868cf5, 0x00009d97a9b136f1, 0x000f9d37eb7a3b6c, 0x00060c2548188194, 0x00061d59be44c571, 0x000f2b2474dbdeab, 0x000b33b93a9dad81, 0x00000000000ecbca}, {0x000a766b5fedf0a6, 0x000ce5e1ce82823b, 0x000997bad589b344, 0x000273a2d82b0df8, 0x0006ac8ff52fe716, 0x000ea7ccdb017f5f, 0x00074b7563e79970, 0x000000000003f0e6}}, {{0x000fda8d824654de, 0x00033487edc06864, 0x00024946c59b50d3, 0x0002bea10fdba0ce, 0x00052c3dbf337fc6, 0x0007d2a46c836bbc, 0x000f714fdfb5c34f, 0x00000000000dca0d}, {0x00024bebc7614440, 0x0007730a0767544c, 0x00067fffd43f5d03, 0x000d49dfacc13dc4, 0x000aae1a261ad307, 0x000d98650148d673, 0x000fdee008f95b52, 0x000000000009f558}}, {{0x000015df21e067c3, 0x0003dd084564b8db, 0x000d0b4c4a73b501, 0x0004bf63bc7206d7, 0x000ffc3d577224bd, 0x000c4924fdd37b4e, 0x00096e8156d6f635, 0x000000000001d1d3}, {0x000ca9d7511fd3e1, 0x0009d977b3b3982e, 0x000fc4c09646cd37, 0x000f9c4ae811d70c, 0x000ca06c7f0de581, 0x00049d87fe5441d5, 0x0009bb0275c92b19, 0x0000000000078046}}, {{0x000cdb7d87948ad3, 0x0009117cd6af6151, 0x000e60b294f18979, 0x0005b1d788224330, 0x00031b9745257e49, 0x000f3ce21fed338e, 0x000896527743d386, 0x00000000000b515c}, {0x000e2d7dc921023b, 0x000d19fde7038e85, 0x000c1b9c9ba2d99f, 0x000600b36ff74dd6, 0x00048302c3c95d46, 0x00044b5eb8ea74b0, 0x000402d560f570f7, 0x00000000000fe762}}, {{0x000cf97b63daba80, 0x000eea7f8501424f, 0x000f397f945052f2, 0x0006b8a2ad5053d9, 0x0003fbcebe43c658, 0x000054f1688c09a4, 0x00047fde7f2a4a20, 0x00000000000bbbb1}, {0x00041659e06114fc, 0x00075087e48f29cd, 0x0009df479d6378c0, 0x00002ff7f27cac87, 0x000c37b1f6e18ae8, 0x0006d1deab01a131, 0x000f803f0d4c2e9a, 0x00000000000e7cee}}, }, { /* digit=81 [{1,2,3,..,}]*([2^324]*G) */ {{0x000643c3f46ade04, 0x0007aaa03b473d97, 0x00091126d04a500a, 0x000ef86f37b57bd6, 0x000b2a6371d2b286, 0x00077ccbd95b797e, 0x000a6da489ef8940, 0x000000000008e99c}, {0x0007980fdcec94f4, 0x000845cf9e236463, 0x0000b4681fa85d18, 0x00023b6ba7ba4781, 0x000757de30bf3295, 0x00036ca01d406ab8, 0x000ac5aa10e4a215, 0x00000000000dfa7a}}, {{0x000146df48d94f2a, 0x000a9762a5eebd68, 0x000728ae94bf3482, 0x00034aeaa4f964b4, 0x000ed6526f010fd5, 0x000d71d72cf46648, 0x0008eabc62a54a18, 0x000000000004f848}, {0x000d9dd392598cb3, 0x000a262c40de70e6, 0x00099451ce04b75f, 0x000d7466ab190976, 0x000b2dd1ad3d3a51, 0x000f88078f07bea4, 0x00035d2a0ec4672e, 0x00000000000664e4}}, {{0x0002f7cfce391389, 0x000d017c563bd4e7, 0x0006d61076868226, 0x00049ac4cd1bfc15, 0x0000d4e53d3b591d, 0x000079a6ed446551, 0x000eb4ca95ccf6ad, 0x00000000000b5ea6}, {0x00099522fba1cf25, 0x000cd600ccc9ba8e, 0x000c729701bdaf25, 0x000edc569c6c6e81, 0x000a586abcdc5f27, 0x000dbc5b6b3fc0f4, 0x000fe0dbfdf3f985, 0x000000000004ea80}}, {{0x000e7847d76787ae, 0x00083ee6e7005dda, 0x000646f5e7ea8d16, 0x000df7dfc45111c8, 0x0001875c23c8373a, 0x000039d490c7535b, 0x000a062a7e04f897, 0x000000000009afd1}, {0x000cbb06099a2183, 0x000fb049dd385881, 0x0008a6ac539cc7cc, 0x00057b9925498c29, 0x0002da25daa3dce0, 0x000decb7d7b9c9bd, 0x0006ef6d0b70a3d4, 0x0000000000003df7}}, {{0x000405f3ffe95388, 0x0004eff54e8bb8ae, 0x000ad0d572466c0c, 0x0005bc4ed1fae2ed, 0x0009ea983db1b226, 0x000851454a5e23c2, 0x0005064af5f55909, 0x0000000000036eb4}, {0x00062710e23e547f, 0x000844c72b2d0dfe, 0x0003b7abb313e4c9, 0x0008ad4e19c9c269, 0x00053e8b8004b1aa, 0x000c747fdb9cfea9, 0x000e4107782d788a, 0x00000000000ce9d9}}, {{0x000aeca3f9d9a2f2, 0x000f8779905b5deb, 0x00064a28a88ba6a4, 0x000f0aa679096dc3, 0x0000f558913cce9a, 0x00024a2e2fdf04f1, 0x000b3505300cb06f, 0x000000000005d581}, {0x000679a2a74abdaf, 0x000aa855c8de8c32, 0x0000f6e26bb556cb, 0x0002a4197740d667, 0x000744c9360d6761, 0x0005cc8807588a52, 0x000188928ac91032, 0x00000000000acdd3}}, {{0x000ac6fa45a00390, 0x000933774af3674c, 0x000bcfd34179ae6d, 0x000205ec11875399, 0x00018799c22ede45, 0x000b0842ef3b1144, 0x000d64fd53f681e8, 0x0000000000066d36}, {0x0007de25fd86d3c2, 0x0009ca2c3391c37b, 0x000760d08855c7c1, 0x000fa4a6ab8ab4bf, 0x000bd841a6234df1, 0x0000b189a2b0cd34, 0x000da752441d79b1, 0x00000000000fa025}}, {{0x0009e3af5a1f4313, 0x0000c3c6c56185fb, 0x00083406c1a4afdd, 0x0009c90ae2fb830d, 0x0003ec31a504b325, 0x0006230bdf7cc6e4, 0x000e3a83bb13c612, 0x00000000000ff1da}, {0x000c261cfaa4903f, 0x000010cc6c1a44f0, 0x00029f13aa21ef15, 0x000c75fe604a58e6, 0x00012491f872d454, 0x000e116a5ceadfd9, 0x0004816c5575da9c, 0x00000000000b24a4}}, }, { /* digit=82 [{1,2,3,..,}]*([2^328]*G) */ {{0x00087efd2e620105, 0x00045c5ad791e85f, 0x000885fe6de88f7b, 0x0009e4998544bc47, 0x0005d273c360673b, 0x000a75a8c934d8f5, 0x000c977fb48d0768, 0x000000000005e0fa}, {0x000ee7923fcfedee, 0x0000dbe01655fb13, 0x0001ed409cde6661, 0x00030de533251391, 0x0001de9f3fc574f8, 0x000e01fa5a724033, 0x0004b496b25206a7, 0x0000000000007eda}}, {{0x000a5e409b41a55f, 0x000283e6e9380f21, 0x000bd6398225ced2, 0x000c8b4b843ec071, 0x0002af8a23f1f2d7, 0x0007923350055d88, 0x000e74e848010ed3, 0x0000000000055e08}, {0x000839aa213ff6af, 0x0003d956ea8e93ca, 0x000299a04653a35e, 0x0009271cca1b5491, 0x0001f1d0b7f15f7b, 0x0009963fbd41d228, 0x000cd8b187047b5c, 0x0000000000002536}}, {{0x000a16fe10008718, 0x000fd7138a03f4b5, 0x0008b9afc3d67514, 0x00041fd2a7cbcc17, 0x0005f6073ecba29c, 0x00004fa086014349, 0x00053298b46d3805, 0x00000000000401f9}, {0x000b314f178aa1e6, 0x0009808cc4abc63d, 0x0005190f1545e910, 0x000c8faa75d9af1b, 0x000fc2e5592d6eb2, 0x000468e666f50198, 0x000fc3773b9d55c0, 0x000000000001a2a9}}, {{0x0004cdf21adad97a, 0x00008e51a956ff23, 0x0002a26288680976, 0x0000fa2f974d2cb8, 0x00074c6a78dec616, 0x000c89d11e00474f, 0x000133ee916e510a, 0x00000000000f826f}, {0x0002a0e3be0ad710, 0x000103fc65d3ecf2, 0x00089ef785c9b19a, 0x000a82e0b9196b29, 0x0000a572b6f55237, 0x000bed2bc4975e68, 0x00025e41ea8b92b9, 0x0000000000098268}}, {{0x000bc901bf39d0d3, 0x000fae352fb9c164, 0x0000b33959aa5988, 0x000ce6fafcb7de1c, 0x0004f694cad0f9ff, 0x00061d6110e574cf, 0x0005d8adb4671cb7, 0x00000000000c8aa0}, {0x000b2a78a9127846, 0x000a987cd7872df6, 0x00010a813ed5d7a6, 0x000531ec2cb43e23, 0x0004b9e6b89f1c41, 0x000e5d4d262fc310, 0x0001dd7f406a0dc4, 0x00000000000df3f6}}, {{0x0005300bc3a99814, 0x0008c06f721d246f, 0x0003df2a36c6f8d6, 0x0006b7a5a44ffdab, 0x000915764390c5ca, 0x000747d7dc53e328, 0x0001227f16917459, 0x0000000000061f79}, {0x000965ef8eb0e108, 0x000ae099f4e3a08f, 0x0009b651d265b539, 0x00043576b72f3285, 0x000cc33695bd270a, 0x0002249029d6bb26, 0x00051f60f9202126, 0x00000000000e1b0a}}, {{0x000bf8353cd33783, 0x00086265d4eff002, 0x00010092c6e845e0, 0x0005c996be6ce254, 0x00096b6056eec399, 0x000a007266fd43e5, 0x000fb1d328c28f28, 0x00000000000f719a}, {0x000f1e2a3462b4c4, 0x000fb75dcabd2f96, 0x0006c939c482a7c5, 0x000a522d764ab7e8, 0x000dcf8a487267c6, 0x000810a449458c96, 0x000786af1af61b78, 0x0000000000073902}}, {{0x000b7c441c7f3df5, 0x000a88a390dca834, 0x0004f92ea9440c60, 0x000ea69bc5e82f15, 0x000d4628d6f177bb, 0x00068e24071f02e2, 0x0000ee6260790cf9, 0x0000000000066527}, {0x0001df8e5c25d23a, 0x000f233639544be6, 0x000c37cf5bac2371, 0x0000f867807ed557, 0x00019dfa452c6906, 0x000d27c0d1b0ac01, 0x00090cbbdb25fe06, 0x00000000000a60ef}}, }, { /* digit=83 [{1,2,3,..,}]*([2^332]*G) */ {{0x000957058557b81a, 0x000dc1877dfd042b, 0x000fe0adb79e32df, 0x0009536c78e295f6, 0x000374a04cc59d08, 0x0007f75edcbb5d55, 0x00078ce366600682, 0x0000000000061e73}, {0x000dd46741146ae1, 0x0000a74170170ac0, 0x00052de550198353, 0x00030f8ac1c4a0fc, 0x000d3cd92824d75a, 0x0005e86d4d7e7be0, 0x0005ef5ea0abdb1b, 0x00000000000b3b61}}, {{0x0003f4e13d621f8b, 0x0005a618ca06b4bf, 0x0002813dfa928efe, 0x00072cca3b6ce7e1, 0x000e5f14bb579813, 0x00073abbbb44a68e, 0x000c0afc1167e963, 0x00000000000767d4}, {0x000277deb88a4f9a, 0x00077c6dcdfeb3e6, 0x000664e1fd3b5c4b, 0x00001aabfcbf2f89, 0x000a67aa82774775, 0x000aab9cd0be7228, 0x000b4a5de7b8331d, 0x00000000000262fe}}, {{0x000cce85ebd04b7f, 0x0007f7a9623b5682, 0x000f8d813f260bd0, 0x000dec9e0f8e530f, 0x00091d65dcd4f8a5, 0x00039541c88bcbe2, 0x00097a09fe380367, 0x00000000000e716a}, {0x000184fc8c1d72cf, 0x0003bbd8e34de924, 0x000a19b51363e270, 0x000d905351941206, 0x0006f7a3c4830183, 0x0003557396345099, 0x0002f718283cea01, 0x000000000009aaa7}}, {{0x000a56eb624d0cf2, 0x0006a7b7da0287f4, 0x00087c61d1ede60c, 0x000d83c51f3dbd9c, 0x000fa91d085ac056, 0x00035262de2f4d46, 0x00029e31759c9ceb, 0x000000000000c9dd}, {0x0009a41b82bb0c12, 0x000e8108cf9ba936, 0x0004fc5060b7103d, 0x00016b273d372b32, 0x0007d5415e53f698, 0x0006b8b0e126575a, 0x000a5e546bb4c130, 0x000000000004d54e}}, {{0x0002c932a7c5abec, 0x000a881dd074d9bd, 0x000f76c734b204ea, 0x000e1f0352b58f62, 0x00029c390eefb5af, 0x0006a8d236d2d948, 0x000be5d073f9a0f3, 0x00000000000466eb}, {0x000118cb3dd8d87a, 0x0004d968c04a5c76, 0x00007c8586d1cdac, 0x00096bb15c0970b9, 0x000370ab8dda98e1, 0x000039fa92af28ea, 0x000ff6b912fbda7a, 0x00000000000cbd02}}, {{0x000e45ea08b7c4d8, 0x0001d5bcf28785c2, 0x000fc63d7c5e8cf8, 0x0005de6707a7138f, 0x000cfb2041a48868, 0x000db3060a77646d, 0x0006908608695289, 0x00000000000e27a1}, {0x0000f0b051870cd1, 0x000794148d936eb2, 0x000a4e50dd50fda5, 0x0002d4db0391d14a, 0x000462b0373f9d72, 0x000a9992c5683112, 0x000b8487b0363be9, 0x000000000008853d}}, {{0x0002c578f8f683b4, 0x000576c8e5a2524a, 0x0007522f4370ef9a, 0x0004aad50ad6f3a6, 0x00051f107e269b01, 0x00051bf732a3933c, 0x0006df4b04395cc9, 0x00000000000b0ef5}, {0x00017d2e75e44b21, 0x000cd28c9fcdca32, 0x00061a5012b72649, 0x000f58e53ace23e2, 0x000efe688f02b546, 0x00091406dee5fec4, 0x0004d9d8b43f6d2e, 0x0000000000026176}}, {{0x0002d2ad73a4790a, 0x00034daa7fcc985a, 0x0000276056234a54, 0x00018c59894edceb, 0x000da9ac29a7fbf9, 0x000372f2c470c45e, 0x000d3fdfd44f6fbc, 0x00000000000a1e38}, {0x00009dd8fe96aa5f, 0x0003923d2400aaad, 0x000c441c1c12013d, 0x000488148baa4ac3, 0x000ebc26e6b0c76a, 0x000ef566273227e4, 0x0002bbe732edcfe8, 0x000000000000c566}}, }, { /* digit=84 [{1,2,3,..,}]*([2^336]*G) */ {{0x000d5d97020dd4a2, 0x0005087c7dd7d118, 0x000d6556f04f9110, 0x00048789fff00158, 0x000b909eaf1abcbc, 0x000443a788ffcef8, 0x000fed9905f4eef1, 0x00000000000e15cb}, {0x000831894b4ea50c, 0x0006cca2969ec57b, 0x000ae2b1ba048b54, 0x000fab787ea6e3a2, 0x000ff98c4fe567f7, 0x0009cb91e0d0ee10, 0x000ab4c646879ac1, 0x000000000007d1d7}}, {{0x00092725c84d0435, 0x00013cfbcbc49b56, 0x000166c387130162, 0x000e05622322f91f, 0x000a7662ae23735d, 0x0002be7a6d2590bd, 0x00017263d468fed8, 0x00000000000695ea}, {0x0005986e2611645f, 0x00050c50f4940fa9, 0x0003729def8820a9, 0x000cd041fd257785, 0x00044a3d0808680c, 0x000684cba25ddac4, 0x00088841d8b738c4, 0x0000000000053963}}, {{0x0003a8028963f3e3, 0x00076b05cb83426c, 0x00074bc4cf79f053, 0x000b5aaefa9e4f0b, 0x000d9bd075ecf023, 0x000a41bfbb8061e5, 0x000d967d2ba50f1a, 0x0000000000090865}, {0x0004ae64b7cf3e16, 0x000d97f221a788f4, 0x00000b032e3ccff2, 0x000eb6af6ab15418, 0x0004dc87cd93085f, 0x00039dbf6fd14102, 0x0003643e196fdb32, 0x00000000000dbcd5}}, {{0x000d4ecde2fce0e7, 0x000891466c9f4fd3, 0x000b63a0ee692739, 0x0008c75b58655519, 0x0004e65862cc291e, 0x0009971671ddb715, 0x000c19285153bc2b, 0x00000000000954b6}, {0x00039e1aad688b1d, 0x000e0985d4505697, 0x000559cd349baa64, 0x00098dafa5fe5e6a, 0x0006f90f231d39e0, 0x000afd0b53fc2604, 0x000c18de5d5ced32, 0x0000000000060c09}}, {{0x000b1d0586854e54, 0x000cf3720b17188f, 0x0005eebb9c78a9a7, 0x0006e315b54eefca, 0x000472b0edaa03c4, 0x00077476e387e466, 0x000259fc59b03dee, 0x00000000000607a7}, {0x000e6b356394b5a7, 0x0008b1478bceddaf, 0x000e3cdb4ff0323d, 0x0002f72cf272ee0a, 0x00038bd885cd7127, 0x0006ba31c19e3a4a, 0x000b369af6415b37, 0x00000000000807b2}}, {{0x0008b39051ba2cdd, 0x00030dbfcfa7593b, 0x00015a46addd3783, 0x000851d67a19b610, 0x000431ae1a67cc6c, 0x000d1e135ace88bf, 0x00090a74554a6193, 0x0000000000042118}, {0x000bd87496a1468e, 0x000277cb3268907e, 0x000047feb42207f2, 0x0002c21766e72f3c, 0x000a880642e30a67, 0x0004d2b3624bb718, 0x0004ab425dc41d18, 0x0000000000089102}}, {{0x000caa1ac9c2c636, 0x000673180789b5d1, 0x000d386a756090c3, 0x000b895e99e922ea, 0x00003d0bbe807951, 0x000fe79c0987ea25, 0x000d2a6d2f49f0e2, 0x00000000000c2b18}, {0x000ed8226be989ea, 0x000d8707798f36cd, 0x000ebf8dc541b02a, 0x0001e32bc4479412, 0x000938a845f346cf, 0x0005e5d924dfc145, 0x000c3f210083fe45, 0x00000000000a1fed}}, {{0x000faea0d2bc54ec, 0x000a972fc8198080, 0x00029736c6c3c3d0, 0x00098bbd99e30373, 0x000a0efddfca3691, 0x0009147416b68390, 0x0008078c35f3e4f0, 0x00000000000ca7d7}, {0x0005a76575b0ee6c, 0x000e9564d991dc4d, 0x0003cf033490be81, 0x0000dab5d635893d, 0x0006f944e49a51f3, 0x000233bc00427e34, 0x00093e1e0bf1b56a, 0x00000000000617bf}}, }, { /* digit=85 [{1,2,3,..,}]*([2^340]*G) */ {{0x000129009060318c, 0x00056d23658c8428, 0x0004596f83a71a5a, 0x00010ec082210f1b, 0x0001bfc364906dab, 0x0004f2d14fb1add9, 0x000443eda8b02f9a, 0x0000000000056560}, {0x0004169ffc0d0413, 0x000986c01479d686, 0x000d5173dbdf44ef, 0x0003c1d718883983, 0x000e13c34fd24dcf, 0x0000c15ac87a9c04, 0x0005d2fe0e08ec51, 0x00000000000c0f49}}, {{0x00099e97b82e73d1, 0x0005db097b2c50cb, 0x00071fe923d57f3e, 0x00066e9420996453, 0x000eff7290736382, 0x0008c394043d059d, 0x000925eebb5fe114, 0x00000000000daa8e}, {0x000995963e49eb67, 0x00007f43c78d7e6f, 0x000a34a7c03b2d6b, 0x000a7d66b6363576, 0x000be096a954cdd5, 0x000afa2fc8b70a2e, 0x00095a011d5419d0, 0x0000000000004fb0}}, {{0x00033bb61172fb0c, 0x00008eb05c51603f, 0x0000d435c61a818f, 0x00073cd489576f54, 0x0000535a8d57cfd5, 0x0001436c4e653538, 0x00022d1394731467, 0x000000000005f0a1}, {0x0007992fb047bfc7, 0x00099aecc7ec110e, 0x000e8ab91f3e896f, 0x000f6523d4221aba, 0x000f2851996bdf96, 0x000cfb67efef5649, 0x00005246fb9f26d5, 0x00000000000ef5c4}}, {{0x00016ebee78befa2, 0x0003188e7ac8d2f0, 0x000b37c50c491499, 0x000d52918be419b3, 0x0004c057621c3b96, 0x000e57e597e75e35, 0x000463cb1b709f5c, 0x00000000000844f2}, {0x00053157dde1a349, 0x0006d53608198549, 0x0000450e27f360c3, 0x000d348e04114157, 0x00004d73eeae6dd0, 0x0000ed85e5b28e95, 0x000b580843923269, 0x000000000006da14}}, {{0x000ce0f0a89b6284, 0x000735cbdc4424ba, 0x0003b0cbdca1bfb5, 0x0006886c118d02b1, 0x000675aaf27658a2, 0x0005f6ec187ff74e, 0x000d32b133be95f6, 0x000000000004b1b8}, {0x000fda7aaf38358a, 0x0001bdd8a8ef25a8, 0x000eba5b65bc2a4f, 0x000a6db26623fb02, 0x0000bae15453d525, 0x000f89fc9f2368d4, 0x000a3e55d6a84d84, 0x0000000000086021}}, {{0x0009f5565cd739fd, 0x000f210520b26d6e, 0x0004ac2940ef5ddb, 0x0008ef88948f78bf, 0x000550ad452e1246, 0x000c4847040a9d27, 0x000ace5e382347c1, 0x0000000000033e73}, {0x000c8b4278956db1, 0x000437d83d02e97a, 0x000af99c625baa1b, 0x000d448885679e6a, 0x0005fc95919c6716, 0x000c2194a0e12bdd, 0x000d2d7da4420492, 0x0000000000015ffc}}, {{0x000c11f07976d090, 0x00025bd048bdc85d, 0x0003c8a142cbe0e8, 0x000a758a985ac100, 0x000cf2c7ace940aa, 0x000ec347d6039bcd, 0x000ab7712092cc6a, 0x000000000006b5ac}, {0x0003db66ec59bab1, 0x000551ebcf80c829, 0x000fffebfb9d4dbf, 0x0003d1ad0b610f09, 0x000498c28ac73fdd, 0x00059750fdd3f6f9, 0x0001ac650b77943a, 0x000000000002d399}}, {{0x0001cfefd0dbceda, 0x000826cbd2756691, 0x000e925943cf3919, 0x000aa0be4c58c7c2, 0x000f0e488784177e, 0x000916b0f603551e, 0x0002e2c8eba131df, 0x0000000000015973}, {0x00008eec1292bc0e, 0x0000355acca849df, 0x000e7c404ec832b8, 0x0002c703bd3b202e, 0x00056ddd8eba162a, 0x000b1d93d4c5e5d2, 0x000dcf66e7844a77, 0x00000000000110b9}}, }, { /* digit=86 [{1,2,3,..,}]*([2^344]*G) */ {{0x0003ab751954f075, 0x000f91b66faabe09, 0x0001714e51539902, 0x000f3a0a675f7c8e, 0x000f30313a711a82, 0x000aea9e682884a2, 0x00005d7ac5d7b058, 0x00000000000cd5ff}, {0x000d5d715b7b74ff, 0x000287c29638d05f, 0x0006736db974b38e, 0x0003c47a17ae3a7c, 0x00077009e38ae85e, 0x000f9c52e91b107c, 0x0008a0f3b777d8f1, 0x0000000000011b68}}, {{0x00072d048b012b70, 0x0009a4ae3d232353, 0x000ebed55756fa98, 0x000c769ec62fd6b0, 0x000f62a4720cba73, 0x000c1f491d586ba7, 0x0005716497cd140c, 0x000000000007b2ac}, {0x0007af894008277c, 0x000b9a65eabb5e68, 0x000cb737865439ae, 0x0001b84231457d7c, 0x0005901645c525b3, 0x000f7b656cab62f7, 0x00095c2377d74db2, 0x000000000002d33c}}, {{0x000e54e4ebfecf4f, 0x000b310105dfc241, 0x0000ded90576b5a5, 0x00068324e80fc085, 0x000287dc7da6122e, 0x0004728cf3b26e76, 0x0001297bc183de6d, 0x000000000008bcdc}, {0x000bafda0190b71b, 0x0005d8b995cec24c, 0x00099629f2c641a0, 0x0009e6b4da5b77d0, 0x00096caf9161612e, 0x000f45eb68ec048a, 0x0000e9e3628ee2c7, 0x00000000000d8565}}, {{0x000dc37cf3c258c7, 0x0005aaae2f447f93, 0x000c6f7663c30e3d, 0x000b2f482c1f372f, 0x000d351a5f7f3262, 0x0006c75a85521feb, 0x000fb8f8ec919091, 0x000000000002728d}, {0x000f483180d24d43, 0x0005f5dd4ff4f0a1, 0x0000b042bcddd9b8, 0x0005b98ba8b777b7, 0x0006fb7f8409318b, 0x000fd31dbd971d42, 0x000347ed1465e8b0, 0x0000000000000f66}}, {{0x000f5311360afd40, 0x000bacea0374a33b, 0x000feb5ded889fab, 0x00002361bb01f474, 0x000a8c328b8bf6ce, 0x00053d6302a5b28b, 0x0005d86991b1d8b2, 0x0000000000085945}, {0x0008eeb3e3866a93, 0x00024f5c6e141989, 0x000231ed9c304f2e, 0x000032f67e76ece0, 0x0002338980594eb4, 0x000001b765bf14aa, 0x0001340804a7c00e, 0x00000000000734cd}}, {{0x00036d45a9f2195d, 0x0007e5ba5288b70f, 0x000e413923c56371, 0x000a997602f3c65a, 0x000fe08c0223c1a9, 0x0007e6f1dc5c7512, 0x00059748a19c3c36, 0x00000000000fb241}, {0x0001d161a9f86145, 0x000879f674a5f0bc, 0x0001526754b42988, 0x0008c4303d6f13ed, 0x000d917433fb5aeb, 0x000f534900fed575, 0x000616e4a5ef9a59, 0x00000000000f315e}}, {{0x0008596b7b07e015, 0x0009c7059c585ee9, 0x000cfabffa6395f2, 0x000d9318d9633cd0, 0x000f37bda14896dc, 0x0008964dcb2abc44, 0x00076ce31adb3feb, 0x00000000000e3168}, {0x000ed4ab82ecfd95, 0x000363173288028b, 0x000f24a3fd6c4552, 0x00034c91d6f69add, 0x00022c34e118b5b3, 0x0005984ede613e56, 0x0003a18bbdbf5c5f, 0x00000000000cf4f6}}, {{0x0008f4401a1165b4, 0x000b4315ad7a4644, 0x000672c1b06e4df0, 0x00097a8baa564733, 0x000446edcfcbe12f, 0x0001a968ef263db4, 0x00087547cf91d53c, 0x00000000000c15db}, {0x0007f5c515f16ba5, 0x000345d35e53a1e8, 0x000a90f359724b01, 0x00011ea246da3d37, 0x000653f068205d3d, 0x00010c00fc1ddfcc, 0x0008c78169d71166, 0x000000000004bddc}}, }, { /* digit=87 [{1,2,3,..,}]*([2^348]*G) */ {{0x0005418902e018d8, 0x000328002f4583b6, 0x00029b160f5eca39, 0x000d112fb93f735b, 0x0002196e3084a8ce, 0x000e8c74427cb629, 0x0005ff72395bdd77, 0x00000000000ee71f}, {0x00030cc165e06d5c, 0x000ca7cfc14d95b5, 0x000ac1b9673d9545, 0x0000129d213738ef, 0x0001bc0b5ea366e5, 0x000a067007a905d9, 0x00082192cb630afc, 0x00000000000bf3a0}}, {{0x0009c76f27cbedd6, 0x00086e96c4aebbe2, 0x00087447d6551831, 0x000d2f632f9151d3, 0x0004302b99e2f86a, 0x000fd317105daf87, 0x000c624299dbfa14, 0x00000000000812cf}, {0x000ccd383b8a542c, 0x0001b42e615367ce, 0x000e792323a5de78, 0x0006c70548fffa38, 0x00077b6db825c34c, 0x000f2989e1fbed77, 0x0003ee850bded44e, 0x0000000000081546}}, {{0x0008bd3d7d2dac19, 0x000ce352e14371a1, 0x000574a96d5757aa, 0x000d9395a7b7719e, 0x000b8544328b64d5, 0x000f9c5934d5197b, 0x00045e5220626522, 0x0000000000074d6a}, {0x000ed277c567a2e7, 0x00003f52c9eeb86b, 0x00037cef0ab9cbea, 0x000b3bfc9ed39349, 0x0007a14c3d70e606, 0x000db5876fc5046d, 0x0007a181cd053e5e, 0x00000000000a3034}}, {{0x00026a12e217941d, 0x0008a9decf2164e6, 0x000546598e5e9913, 0x0009ce8aeb36b93a, 0x000158fb4dc8d564, 0x0002d60cfab9f77d, 0x00061966b11fb6b5, 0x00000000000eaaa4}, {0x00098700891e3d12, 0x000dbf3522a998ce, 0x00034cf7624bc215, 0x00097c625e387237, 0x00072d4595ee2679, 0x000e5456ced5047b, 0x0006feaaa41e5f55, 0x0000000000078cfc}}, {{0x000abf51b7538110, 0x000353fd75579f7b, 0x000019e5c13ce4a6, 0x00076854d208bb77, 0x000ac1c9512f4c82, 0x00081e9f3941aeb9, 0x0003396ce0bed5a1, 0x000000000003744a}, {0x000bd7c923f4230a, 0x0006180eaff7a041, 0x000dbb73984381c7, 0x0007c1b0f8e7fd8b, 0x000aaf499630f16e, 0x00080a16856bdddd, 0x00012be8c112df11, 0x000000000002987f}}, {{0x000b02027989cfc0, 0x000a60ce9ab12f61, 0x000973d1a5ee6cd8, 0x000b3b69a1753a9f, 0x00002bae5685f031, 0x000d3c06632160ba, 0x000f5cdfde9ae80c, 0x00000000000a180c}, {0x000f0a3aff152330, 0x00023e2c194158b5, 0x000e1481b10c0c49, 0x000e7d12ea20322e, 0x00007968c7ff67ea, 0x00027bab93eb507b, 0x0006eaeb300ff9ce, 0x0000000000097575}}, {{0x000b71b2ec924484, 0x00007325de655ef5, 0x00027d8f4ae5da5e, 0x00026ad89e4c34bb, 0x0000ec5a615fa909, 0x000c770ac8e61adb, 0x000f8a5a2233d43f, 0x00000000000cbb23}, {0x0003b01804f61225, 0x000a4a7e6c5861cf, 0x0004fcae81492249, 0x00040be697e7dc09, 0x000eb6f29135b0f3, 0x000e89899783a7d0, 0x000f55412469b007, 0x000000000001bfaa}}, {{0x0003c3de6d71b673, 0x000cca438634e69c, 0x000f00cb40863203, 0x000dedfac40dd56f, 0x000e4956a5de2ab4, 0x00013f84d758e95e, 0x00016cfc11e39451, 0x000000000006059f}, {0x0008f87a862c83c5, 0x00038fd8e2236750, 0x000df4ebd7b9092c, 0x000b1538ea13b455, 0x0003013d382702ae, 0x0009ca201de1275d, 0x000351470a7b7e65, 0x000000000005c77b}}, }, { /* digit=88 [{1,2,3,..,}]*([2^352]*G) */ {{0x000bd58c2fd385c4, 0x000d8281f6e58982, 0x000c3afee2ff7056, 0x000a41afd89abd8e, 0x00007984feefe29f, 0x000d20a64fcb0b0b, 0x000cd50b0928a6d9, 0x000000000006979c}, {0x0008ab27cda5c7bd, 0x0001cce9c34c7521, 0x0006dc0b027875db, 0x000635250946a5c3, 0x0006f39f53b9d464, 0x000bc8b64b09a97c, 0x0000d61d47bc20dc, 0x00000000000d458b}}, {{0x0004b16a9cc79c48, 0x00075763e36638c9, 0x000ff772bf788245, 0x00011a8c66b40e9f, 0x0008f384b70862ab, 0x0001978760624469, 0x000837e7cdf3bd69, 0x00000000000064f8}, {0x000fbc5f9be69c3f, 0x0007895900a21f89, 0x00053a9326cbd6b2, 0x000fbbddd3e6e471, 0x0006baa2e2a03f65, 0x00085282484f52e0, 0x00032c1dc462a8e3, 0x000000000007e4c0}}, {{0x0008c150b5ec2626, 0x00094cc580ea6853, 0x000526b13f535e43, 0x000604fb23480cfc, 0x000a344146898665, 0x00010a94595787cb, 0x000c78425d7c6f4d, 0x00000000000b2f1c}, {0x000940b59f5f9db6, 0x000f455da8884e6f, 0x000468b788890b3d, 0x00081d7d99e417f5, 0x000abf28fba2c648, 0x0004eff801eeba5a, 0x000fb720feb7b350, 0x0000000000050deb}}, {{0x0002dafb4e000df5, 0x0009720ebf79c9aa, 0x000a041b02faa426, 0x00007e78d630d2b3, 0x0007fa605dcb016c, 0x000d0470520021d5, 0x0007e66190f3e942, 0x000000000008974b}, {0x000bb7ed0e0135bf, 0x0003b6710da6c4cb, 0x00011bda556d9709, 0x0004b8ba583089a0, 0x0004ea7dbcdd192c, 0x000df1097171ab8c, 0x0000ed715f60818c, 0x00000000000205d1}}, {{0x000c0f09863d151a, 0x0004b4a6226f970c, 0x0004a88f8872d167, 0x0002e60a1193cac8, 0x000543dda270b44e, 0x000d647382ce6393, 0x0006751a9e8a2138, 0x000000000009d843}, {0x000abb28a3b6891b, 0x0008a98a1222e3ef, 0x000341bb8ccbdd0d, 0x0005be5555088026, 0x00017b38f0648047, 0x000e249f5c39ccd9, 0x000b74ea31304de8, 0x000000000004d42d}}, {{0x000330dc4e7217de, 0x0009c39a689bbd9a, 0x00001ce7a86200c3, 0x000108a8d29457b6, 0x000014ed4b4dcf33, 0x00015625f312612e, 0x00063bcbb21f3451, 0x00000000000303a3}, {0x0009f7756d9dff06, 0x00004aeb0c8c0639, 0x000d964999e9958d, 0x0002604683b37dcb, 0x0007862b08477a02, 0x000d69390fa4ced7, 0x0003145a49bdc136, 0x00000000000c0215}}, {{0x000155abc265f191, 0x000f0544874b6521, 0x0007a036ebfb6d29, 0x000afd631411ba1e, 0x0000466d6415b303, 0x000d4c2de30047aa, 0x0007b13a1b676594, 0x000000000002860c}, {0x0008a20d9745d768, 0x00046fe140a72d14, 0x0007d03c948ac2bf, 0x0006df9f46f144f8, 0x000bc0defbc46c9f, 0x00024c075f7e7b95, 0x000c39fbc9a96978, 0x00000000000d7773}}, {{0x000f0ec4d363b0b7, 0x000bdd2db4d34f56, 0x0005740dc154bacd, 0x00065cc723a57c02, 0x0007d8ded62c4475, 0x0002f1a9ed98c359, 0x0003b20aeac6d9de, 0x000000000000a98d}, {0x0004a99c9e88ef97, 0x00034d9708f06642, 0x0001bd570d037e70, 0x00032cf49cda0113, 0x000a858467e24993, 0x000748e8e546df74, 0x0000738b84a55093, 0x0000000000006f09}}, }, { /* digit=89 [{1,2,3,..,}]*([2^356]*G) */ {{0x000f37fe6b03f897, 0x00052c0a40cabe70, 0x00091f1b94fec55b, 0x000898c340187426, 0x000636d9e57a8625, 0x0008aa21169c9f3f, 0x00016869d9d7f337, 0x00000000000e7dca}, {0x000214154225907a, 0x000ba24d49aebb77, 0x000fbddce2036f3c, 0x0001d01576f533f5, 0x00099ef82ece667c, 0x00007c14d372eee1, 0x0007f6577723c0c2, 0x000000000000eed3}}, {{0x000850ebff25b818, 0x00013c61db976bce, 0x000a1c9cf36381eb, 0x000b8ca060b1adcb, 0x000188e2c178ce89, 0x0003bdd3c41db448, 0x00042cba6339f392, 0x00000000000d29db}, {0x000bbd1437baf649, 0x000f53521116eaf1, 0x0005d6c8cce9ea0c, 0x000c984bd79fe5d8, 0x000e9d45eee49357, 0x00088e01f2eda73b, 0x0008731a50c59f62, 0x0000000000075018}}, {{0x00038b1bc1ced6c1, 0x0004df323953ab33, 0x000a2512b2fa2401, 0x000dfd9bd32cb8d7, 0x00037ecf35382937, 0x00039941507c4e56, 0x000a06b573960eb6, 0x00000000000dd1a4}, {0x000a33b92253abc1, 0x00050c625f400562, 0x000bec6e4c3f3a23, 0x0001e5b6220f24df, 0x000827d01c6f66c5, 0x00012372d9f97d75, 0x00004860b1572404, 0x0000000000004d55}}, {{0x000a3b570044f6d8, 0x0005fc552c6c6093, 0x000f9e99da8c0559, 0x000375c19610b0cd, 0x000bb051dad5c9ed, 0x000556643f0e7b4e, 0x0001d87267a304c6, 0x00000000000c96dc}, {0x000cd649696f60dc, 0x000dbf0ed5f9a8b8, 0x00051f0009075842, 0x00066f4af5a4b4c2, 0x000d20644cf2ef5d, 0x000ae23c00b5bed3, 0x000b66f7e4543a75, 0x0000000000041325}}, {{0x0006798502ee1353, 0x0006c04ef7ad5a7b, 0x000c6878548d78d6, 0x0008a6a47591d88b, 0x00046902edb49ae3, 0x0002b143a27d9125, 0x000df65dae3d8381, 0x0000000000093a2f}, {0x00091ef1ecb7e486, 0x0000807a00388858, 0x000fb3b7ca4398f1, 0x000c17172b1bcba8, 0x00032d0033c73fd6, 0x00016c28aa8d70f9, 0x000ad79ea9eea329, 0x00000000000423ed}}, {{0x000a6b031af68d65, 0x000b59949b33d112, 0x00063134f5d066ef, 0x00071e788e17f2bf, 0x0002da9c088188ce, 0x000d8c9e9d851baf, 0x0005b6e869c5ba86, 0x00000000000a0142}, {0x0009ab9cc7c38dc7, 0x000eceae8b1c5d3f, 0x000b0c8e79b3cc01, 0x0002910c374bb97b, 0x0007054874831494, 0x000bc6ee13e13c45, 0x00047be0e6fad435, 0x00000000000b54d2}}, {{0x000e68e47f9ea217, 0x0003c9c85e50a3a1, 0x000b0543d8520966, 0x000ce81807f33dba, 0x000a3db81e06cb78, 0x000638d709d337d8, 0x000babe223eae472, 0x000000000006bf2e}, {0x0006763908bcca20, 0x000662804b59c92a, 0x000900c614fc9957, 0x000ca1e7bc6949c1, 0x00008f051155321e, 0x000539f40bf2906c, 0x000808b802a3289c, 0x00000000000073cd}}, {{0x000fc3dc90267bca, 0x000956d34bdf61b1, 0x000bd7a38090ba35, 0x00051135a3bfdd10, 0x0005f1296bdd61d0, 0x0002e9a7c4abab57, 0x00003d72da68494d, 0x000000000008d11f}, {0x000319b6e5281755, 0x0002247811121597, 0x000526a929004138, 0x0003ec67521898f7, 0x000996c1da75ec29, 0x000f2c7b3f0cf026, 0x000af8b0dbd4c380, 0x0000000000034e4b}}, }, { /* digit=90 [{1,2,3,..,}]*([2^360]*G) */ {{0x000c4e9ab57885e4, 0x000f3c32730e8279, 0x00033a83277668a3, 0x000fdbf3f5cd8478, 0x00067272d4dd2bac, 0x000b7577645f3641, 0x000be2dd813a795e, 0x0000000000050997}, {0x0005df7d4526b8ac, 0x00040da054e2b966, 0x00068890ccefdc5e, 0x0008f31026116a38, 0x0000dcd85e914c42, 0x0003adc2d372af9a, 0x0009e6fda6e90367, 0x00000000000a8db5}}, {{0x00029349f348fe26, 0x0004251a033a4db8, 0x000e0f2d8a80c6e4, 0x000ce49a42a266f1, 0x000b82c4d11e92ee, 0x000bae08a87e037d, 0x00078c875be1416f, 0x00000000000c5394}, {0x000064a55c345b79, 0x0001651f8b907a36, 0x0000a11c59759db6, 0x000bd666c51b9c32, 0x0004ee565de82c74, 0x00082c8c3635d3d2, 0x00093c6bd6566389, 0x00000000000daf6a}}, {{0x0007ac96ab52d7dc, 0x000dd68fe359d36e, 0x000f3dea99f83698, 0x00052c3fc704935e, 0x000952e4e22d0ec6, 0x0003e3ada1eeff1f, 0x000871ba6777cb08, 0x000000000008befc}, {0x0007324fc4458b0a, 0x000e34ede689e853, 0x000cf3cdc3eb9d08, 0x00080517ab83c288, 0x00052c8c1f48e0f0, 0x000241aac1f3d5f2, 0x0007e057991607af, 0x00000000000b8a33}}, {{0x000ca2047d1f8f40, 0x00004179c59cea3e, 0x000880cb97b10e4b, 0x0005cfdba0cf3857, 0x000b3a8fbafadda7, 0x000384e0b94081a5, 0x000a45b91de90a33, 0x0000000000027aa2}, {0x00058a31cd3d8717, 0x000220747bcc094c, 0x0000191551c0619d, 0x000e3e9722484f1a, 0x000da62d1dda9c1c, 0x000963bce13a7ee5, 0x00021b77fd79343a, 0x0000000000083d2f}}, {{0x0009d92935034280, 0x0008b3dbb3fa61cd, 0x000a3f5ecd8961d8, 0x0006574793ce8041, 0x000783dbce4f35ac, 0x0003cf6b0b2697dc, 0x000164e35c5bf2e1, 0x00000000000b0c4a}, {0x0008df1996e7f4a8, 0x00038aa49090842d, 0x0003b655f6623523, 0x000e96c54d504e4c, 0x0001b73310a3f646, 0x000bde5dad74e754, 0x000ef7ead7159618, 0x00000000000aa09a}}, {{0x0005ac9c05f620d2, 0x000df609deb16279, 0x000a25447b2b8795, 0x0003132b378305ce, 0x000869275f5e4a9f, 0x000b089b5f101799, 0x0000c514be746761, 0x000000000000c81b}, {0x000e2dd3d7fa135b, 0x00030ca90a9bf94b, 0x0006097de4edabc4, 0x000ac9620c71989d, 0x000a390aedd01b25, 0x000d8cd39b971b61, 0x00011a995214d779, 0x0000000000065c6e}}, {{0x0003855cea5ad9ec, 0x000d4a8393a23731, 0x0006e8588fe37236, 0x0004e0255a202691, 0x0002a446bcc6d882, 0x00051499b9dd9a27, 0x000535c929cded53, 0x00000000000cfe76}, {0x000bc0f428a70f0d, 0x0009626f3d7d9b38, 0x000a6acd906c92a5, 0x000cc06759e6ddb7, 0x0004e302b89191fd, 0x00007e1f7ac2e190, 0x000b4aad25c645c2, 0x00000000000ab3de}}, {{0x000338669b2cb8c7, 0x00071a13f19b3741, 0x00031ac1789cc21d, 0x0000c997044a6f4f, 0x0008dca1075c00ec, 0x00020ab0caf5665f, 0x000effded5ca3f06, 0x00000000000a896d}, {0x000378285debab1d, 0x000a5032ab2b2a9f, 0x000438bbbc4fc5ea, 0x000b6f725133304f, 0x0001977a45672286, 0x000abae4f0d16d53, 0x00003b00a66036f1, 0x0000000000095f01}}, }, { /* digit=91 [{1,2,3,..,}]*([2^364]*G) */ {{0x000925dc8a89e47c, 0x00066f2cdae310b9, 0x0002591b317d8ec6, 0x000f25ad750b29bd, 0x0005dba15f3e9d14, 0x0009fe2dd931b9c6, 0x00043334db169ebf, 0x0000000000052663}, {0x000c577396a26bac, 0x000968859a4f76bc, 0x0005596f973fb63a, 0x0008d6a67ac4db88, 0x0002be25d7557463, 0x000db10ee5c8ea7b, 0x000cd38a0f0a8738, 0x00000000000e890b}}, {{0x000bf56a7de9f2ff, 0x00022883533aee6b, 0x0008916bc1e75ddf, 0x0005fb546d0fcf42, 0x000a4ab05da78f0b, 0x0007b66147e6b0a0, 0x000cf2cd91a869c6, 0x000000000006c6f7}, {0x000593da575680e9, 0x000d7c072a1067a9, 0x0006a216ef99f7a9, 0x000192c8f0ce9469, 0x000fd11494417378, 0x000ccf45adf2e7b9, 0x0005684fa17cb614, 0x0000000000045f03}}, {{0x000725d8721dd338, 0x000930f4ca77fc15, 0x000b6681d170fa2e, 0x000625b4ef805afc, 0x000fc015c5864873, 0x0001a8c93bddba22, 0x000f427091b50aa4, 0x000000000004c005}, {0x00044f31df11a4ec, 0x0009ff43d3745415, 0x00007d532af636b7, 0x000a10c82770690b, 0x000b77513f003efc, 0x000c3af9bd0c25d7, 0x000adac0015cc12d, 0x0000000000094c6c}}, {{0x000e8ca221c6ffc6, 0x0008d8b70e94f6d7, 0x000aee261a6327ec, 0x00019ba4d3ef22f4, 0x000a1999f948e222, 0x000fe73027f8a712, 0x000af025575e96ab, 0x00000000000564a1}, {0x000b25cff3d9db0b, 0x000b1045e9c658aa, 0x0003561802f8c969, 0x000b825c3db161be, 0x000aba33a906dd23, 0x0000e41f205fb173, 0x000d1d9a8b5ecb87, 0x00000000000ccc30}}, {{0x0002aea737bc7de5, 0x000c2bed7d94c6a0, 0x00033bc161f07397, 0x0006af6106834bff, 0x00044c4f74486541, 0x0001dfc06dade8a1, 0x0007bc62227a1d88, 0x000000000008dc2b}, {0x000d41c50320c146, 0x0001c4f1154170fa, 0x0005645ed0c5caa2, 0x00053aba0f1b9617, 0x000d48b0ec8e98cc, 0x00072d0342f68011, 0x000e384bbc34679c, 0x000000000009c576}}, {{0x000919b377dae55c, 0x000a5d9243926709, 0x000605401369e5f3, 0x000feee0e35f201a, 0x0003196f23f3a1bc, 0x000c1d068d25be5f, 0x00050b298c67f2ff, 0x000000000000c3d9}, {0x000d303412559962, 0x000fa5e15ab9975c, 0x000533c7cf964ba3, 0x0002ec947a7e2696, 0x00022ac22e49a9f8, 0x00006f090f02af9a, 0x000cb0dfb3103fa7, 0x000000000003cf8d}}, {{0x000298e2791b8ead, 0x000259f5f44f9ed5, 0x000ce416b16e73bb, 0x000f258f9627f9cc, 0x000938fd51bdd7e8, 0x0006a4a7922499dc, 0x000250a9d7497c84, 0x00000000000026ae}, {0x000e3b88b9c7c3db, 0x0009084d47d19214, 0x000f52469be04308, 0x000138806a52e316, 0x00027f08953f9b2f, 0x000fcac083fc8da0, 0x0003fc22d074d292, 0x00000000000701d7}}, {{0x000b913b1d418177, 0x000cbb7b856256b6, 0x000f3717023b8633, 0x000ddd5c91b8ffd9, 0x000155d38511b4eb, 0x0000da525ef815ae, 0x000bbd98587d551b, 0x0000000000034a9e}, {0x0005ef8ce15a684b, 0x000b8844811fa3d0, 0x000d70ffbd583fff, 0x0008bb4f623789be, 0x000e404980584b26, 0x0002b435ab26ae5b, 0x000eb3b47a5ded3c, 0x000000000008fcec}}, }, { /* digit=92 [{1,2,3,..,}]*([2^368]*G) */ {{0x00069e40601a7dfa, 0x000cb70765682efa, 0x0003c3be2bc6c542, 0x0005ef0a6db6169b, 0x00012032d5992a93, 0x0006f13160029276, 0x000f51b5babb2d3a, 0x00000000000db26a}, {0x00039e460e4f3b3d, 0x0000200c3401304d, 0x0003ff9e293a0443, 0x000e2ed0f9b36565, 0x000934031d18a1bb, 0x000fe1224e17a5d4, 0x000cf5e3661047f8, 0x00000000000623c6}}, {{0x000ad46943acea12, 0x000a859367582797, 0x00066c45ce5e5faf, 0x000351af6a27741d, 0x00087f929e0d5d96, 0x0003f1afbeab94db, 0x0001dd865ba01104, 0x000000000005fb63}, {0x00040d1f1e090717, 0x00038192e065294f, 0x0002fb37089941d8, 0x000228db7cae5f66, 0x000d6a828b037bcc, 0x000f301aa02eaecc, 0x000a077c48a2ea91, 0x00000000000f5eb1}}, {{0x0000bb651b864105, 0x000154dd3bd8408c, 0x0001daf9340de0f6, 0x0006998ba0668966, 0x000cad713bbd1ad4, 0x000ca4fa5b7c679a, 0x000a1cef9389aff7, 0x00000000000d68b6}, {0x0009051030865994, 0x000093acfff601ae, 0x000275b28bea6bfe, 0x0006441c66ad734b, 0x00042fd3eb165e2f, 0x0004e211749f144c, 0x0001a3bd7f22082e, 0x0000000000041791}}, {{0x0002b76266c69181, 0x0004edf0ae8df2d5, 0x000906801183c79d, 0x00017ca1dd286917, 0x0009709b678ede37, 0x0000acdc60c1db87, 0x00003a0288959a40, 0x000000000005ca2d}, {0x000fd72975fb9eb5, 0x00084e52534b365b, 0x000f103241b3e4c6, 0x00034f873eece315, 0x000d642a67991a9a, 0x000a7e8a80fb0c7b, 0x000238375cc0cfea, 0x00000000000d00ec}}, {{0x0005a38c81bac32b, 0x000bdb67d88fb498, 0x000506df3f19aea7, 0x000433ede7910791, 0x000a20ec085cc26e, 0x0000eefb30ed8fc0, 0x0008c22684a901b3, 0x00000000000e855e}, {0x0003801582a535c0, 0x000a23d31d6c91c3, 0x00014e8637446682, 0x000380e755f1af17, 0x000a6c985ecfd938, 0x00065084e6a8e434, 0x000ec653bec9c1cb, 0x0000000000070309}}, {{0x000a18c1c3a6f1f6, 0x000f49a2461c2364, 0x0005b210149e5bc7, 0x000bfea0ae15fd0a, 0x00027ac4d98f2265, 0x000831902d817b35, 0x0001fe9788aa4511, 0x00000000000d4616}, {0x0004b65395df8642, 0x0003d2a7cac2f471, 0x0003af0e90c12844, 0x00048d211070e2f3, 0x000ab769926571a6, 0x000aea1556050d8b, 0x000411cf8f24a040, 0x000000000003522b}}, {{0x000a6d728de1a709, 0x0002e45d4ed63b83, 0x000803bc165cd24c, 0x00029022b267f598, 0x000fc8446afe76be, 0x0004d6f50791c22a, 0x00077ed6ce8b8859, 0x00000000000e3f1f}, {0x0000a258fb32c514, 0x0006d1a72b16f0c7, 0x0009dc6ac4083dba, 0x000743e1cad2e785, 0x00041e0e640d6a1c, 0x00074648529ff0a5, 0x0001fb4cd519be4b, 0x000000000004584f}}, {{0x00051eecfb6439ff, 0x000619ca8cc9cbbc, 0x0007f10adb0b792f, 0x0005d53059b2bbb3, 0x0000730e5dc37211, 0x0001d89988fe7ac3, 0x0007a54e67ef6984, 0x00000000000c8ed3}, {0x00004a045edf3ac0, 0x0005e48164b3dc80, 0x0006b3cd6d953b04, 0x0004643beed38ce9, 0x000fa3e30b3db7fd, 0x000ddd484993cfa9, 0x00075ddcc5e7af01, 0x0000000000068401}}, }, { /* digit=93 [{1,2,3,..,}]*([2^372]*G) */ {{0x0007c9efed4b7222, 0x000ab79768e9e648, 0x000c0eb72891fdba, 0x000821bbe0c67d8d, 0x000a6909fdfcc194, 0x000ccdda7537a6a4, 0x00026cae6d705195, 0x0000000000092b39}, {0x0004e2be194fc116, 0x000ab2c5dd6af51d, 0x000bd2ad4ffd8821, 0x0007388397a3bd3a, 0x000a8baf59c2dd3c, 0x0000ec9589d176c6, 0x000315d5c6219e38, 0x0000000000054e8e}}, {{0x00045f27ccc6232a, 0x000560683349d797, 0x0004a272721dca0a, 0x000181050663b9f6, 0x00099733dac647c7, 0x0002137c5f327d14, 0x0001c703f55e4a29, 0x00000000000da59e}, {0x000b58d5c8ca43e3, 0x000c7baa8b4dce4f, 0x000e015119c73eca, 0x0008c1db0322dfa0, 0x0007fd69954f99a8, 0x000a29889394440a, 0x00064a9060473da5, 0x000000000002f048}}, {{0x000df3b38c2a0a79, 0x0000190762c1ecbf, 0x000c4019f47729e5, 0x000849f5c47c645a, 0x00056d72e7487420, 0x000e11773b082319, 0x00050eaeac683b8e, 0x00000000000fb5c5}, {0x000722990680a985, 0x0003e6d986d69658, 0x000da73ac5c10442, 0x000136fd94d52235, 0x0009ed5b01c6d13e, 0x0008fcdcc1aa7541, 0x0005ee7c2014b140, 0x00000000000cffde}}, {{0x0009c28bf944531a, 0x000bbc7d0abb1f4a, 0x000c2054201bd117, 0x000defca80767df6, 0x000871820908eb67, 0x00074d19a6fa174d, 0x00081a3215df4856, 0x00000000000960a0}, {0x000602066fc6cc5c, 0x0006993ed71807f6, 0x0002dfba1c3883c8, 0x000d56efe787e592, 0x00098fe8b96f0909, 0x000ab68115ae74fc, 0x000e0c8fc342c435, 0x000000000000b991}}, {{0x00047f2399bf97b6, 0x00021c600dd569b8, 0x000917d84fb94235, 0x0000a27de43c1d70, 0x000e616bdb162d7b, 0x00029795321bf3a9, 0x0008b233ce767c96, 0x000000000009e439}, {0x000800714c3c1216, 0x000934069cced410, 0x000f1cffed0b3d13, 0x000bf89c53942369, 0x0009acb24e389981, 0x000da473507d9c07, 0x000cd9d2e5e904a2, 0x000000000002f1b6}}, {{0x000ee38595e6d6e3, 0x0003bfeecc6e7a5f, 0x00087ab2bdd62b28, 0x0004e20e81879cac, 0x00089c4a27124845, 0x0000749c3d0ea9cb, 0x000f93ba8b6f3354, 0x00000000000e971d}, {0x0002b66fa9a77846, 0x000b64c2a1b129de, 0x0005071339da6099, 0x0000b53435739873, 0x000a57040c00e6c6, 0x00091a7b4b9f56a6, 0x0002466de6489f62, 0x0000000000053bc3}}, {{0x000554330abff5cf, 0x000ae828a9dbe5c5, 0x000263a5672326a0, 0x000428089faa5816, 0x00002dba2a1d1558, 0x000197ae62da0922, 0x000abba225f631df, 0x000000000008f4eb}, {0x0005dcc2ee38818c, 0x0001bbbadc9b2cb5, 0x000ab544fb33427b, 0x0006cc2759413f76, 0x000121dd1222072a, 0x000ac2c737b39ea4, 0x000296d6baf9e196, 0x0000000000075d46}}, {{0x000b2448cce42a48, 0x0001555671128874, 0x0000a30717d307ff, 0x000207ce99ca16c1, 0x00057c7a26b97e21, 0x000c3ab00785fa10, 0x00059f33c28658c2, 0x00000000000d79cd}, {0x0004e804722ed471, 0x0006f9a674db4469, 0x000c9ef186db33b8, 0x000722166bf2c6d5, 0x000abd4c3791990e, 0x000696ee1ba29aff, 0x0006a5d98510cf20, 0x00000000000f93d2}}, }, { /* digit=94 [{1,2,3,..,}]*([2^376]*G) */ {{0x000bbb4af21bdc49, 0x00065e7cf5babca3, 0x0003f75a29c95b64, 0x000531d04fa84740, 0x00045780efda9c1a, 0x00062cb5a399e848, 0x000f3b6e9c12be4f, 0x0000000000094a5d}, {0x000aeeb34b3f3b9c, 0x0006d3c15fe11c69, 0x0009e05f576f256d, 0x0006da4be294c912, 0x000aa99b83983ef7, 0x0001b9f6a5cf21d5, 0x0007bf50679cf875, 0x0000000000054d0b}}, {{0x0009b2dd4ee443f9, 0x000fcc84f9171b4d, 0x000ea8b580b8da51, 0x000753ba05068eb1, 0x0004077777efcdc4, 0x0004cf44aa177ad1, 0x00044e0b7f54eb7e, 0x0000000000018601}, {0x000becbcecff7dd7, 0x0002b1279ed4c55b, 0x000e10b5af306b99, 0x00058fab8cdb6cf3, 0x0004a0c7614aebc9, 0x0002c6d8ebc4f93f, 0x00038ac5bd6cde7b, 0x000000000008d65f}}, {{0x0000f0922779f009, 0x000bb4da7d63a943, 0x00025a4f402efdea, 0x000001668841d1ef, 0x0005b10366f61e8c, 0x000b121e90688f48, 0x000c1e38ee34b005, 0x0000000000014e0d}, {0x000a8eaa6c54d224, 0x000e683c1d44e6fa, 0x000050a1a6ad5a9a, 0x000274453715349d, 0x000dc5ca18f66b73, 0x000ef86e35065bdc, 0x000f5d677313cf2d, 0x0000000000033ebf}}, {{0x000a3669bab3aa8c, 0x0001fffec66743ba, 0x000af6b2298cee7c, 0x0001365ee61bc95f, 0x000e8948b6e23181, 0x0001644be358bbd6, 0x0007a71cd9c342e3, 0x0000000000060a8a}, {0x000569b8813054fe, 0x0000ae065519f224, 0x000901053fc569ee, 0x000c03b8517ae8b7, 0x000173750d6e8957, 0x000aee6d7c96a040, 0x0001144eb2e364b2, 0x00000000000ed099}}, {{0x0006635997173f0f, 0x0003b71714896339, 0x00025444ec94256f, 0x0005f33fe56d0905, 0x000638a1b2efb078, 0x0000fc15add43e0f, 0x000d362df35cfb36, 0x0000000000090b3e}, {0x000659873829fac7, 0x0000bd4970bdd7ef, 0x000e315a3dccca14, 0x0008a3e4a43c4f3e, 0x000fd9cb4808c99e, 0x000c3d0948013609, 0x000223f3fef0eaec, 0x000000000008642d}}, {{0x0005a811304eaea0, 0x00018ffe3104b37f, 0x000808bc57214341, 0x000ed42cca2f1506, 0x0002c421c69415aa, 0x000b87b368618aa0, 0x000d5f4d6a091dfa, 0x000000000000e786}, {0x0009341357580c61, 0x000ee0be97746d4b, 0x000cd6467b049086, 0x000823b7a70d4224, 0x000809de860f6094, 0x000cf60205928791, 0x00086e7f7fca496d, 0x000000000005f460}}, {{0x0007768861c39ce8, 0x00007b509f7028f0, 0x000fc09189281be1, 0x000832a7f07f3291, 0x000d8fbdcb83853d, 0x000a4650d074fdec, 0x00072080ed8de9d6, 0x00000000000a5d68}, {0x00079ea50cb0600f, 0x0009ae66666d224c, 0x0008a45c66bc5d53, 0x00099510da620fbe, 0x000fdf866f777e2d, 0x000045beb901145f, 0x000008442a37e5db, 0x00000000000beb1b}}, {{0x00048a2dbd606668, 0x000c9bb39a179bed, 0x0009439710e05c24, 0x000abe3b91f14833, 0x000fbd39a2bc6be6, 0x0001d813ef972804, 0x000d4a06737e54f9, 0x000000000001a87c}, {0x000d0c4b5d0bc923, 0x000b2bf88b2e5982, 0x00052c33a491bb9f, 0x000aedfa58af0431, 0x0006ac0511b07a93, 0x0007e2c198853cdf, 0x000d8a9d7f416d06, 0x00000000000f9671}}, }, { /* digit=95 [{1,2,3,..,}]*([2^380]*G) */ {{0x000f6957a24c76d1, 0x000222e7d0a157df, 0x0001697f0073308f, 0x000ddc63eb317f9f, 0x00015adf71d715f1, 0x000858bc3f027507, 0x00071a2ce33c2eee, 0x00000000000da73b}, {0x00035cb76cad67cc, 0x000de9ef6a709ffc, 0x000c7c7ed1727cfd, 0x000f5a67502de655, 0x0001a47019739f5b, 0x000ea7b24d11122a, 0x0002e182cfaac2a2, 0x000000000000a458}}, {{0x0007ab134ebd334b, 0x0005196a1e74f032, 0x00014e69e2323c83, 0x0009c4fbe35109cc, 0x00004521d7e61244, 0x000d002931fad8b3, 0x000229c85eb23d57, 0x0000000000035f68}, {0x0000d113aed4dbde, 0x0000c7c5b86677f2, 0x000189b64d0338ba, 0x0000456757cd5717, 0x000e3a1c866b067b, 0x000ba88c0eaab81b, 0x0007dc72a6af75bb, 0x000000000000ef56}}, {{0x000ac045af51c5bb, 0x00010597a26ff058, 0x00059bcfafa87a4b, 0x000aff65c27f5f6d, 0x0005d8d544e60b06, 0x000275c32ce5ab66, 0x000e7c92f031be99, 0x00000000000f42e0}, {0x000c8a905adb28dd, 0x000175bb28b05c35, 0x00031ae347df4e7d, 0x000d299f93fb7dcb, 0x00086e2ccad9e73f, 0x0004d4f57fcd999a, 0x000c9bb8c8a6df33, 0x000000000009a2ac}}, {{0x00030bea7fcf0ecc, 0x0006a3afdee26fd5, 0x000cc01988c78a70, 0x0008ee3ba4a33026, 0x000a2a883b7f340c, 0x000d7412b1a6ea51, 0x000b6e64f27976d5, 0x0000000000091251}, {0x0008bb3d89325d7a, 0x000d25f3f8f40ad2, 0x000216e9116c139b, 0x00073d6ad61b2cbc, 0x0005d542676dde3b, 0x0007d712bf08398d, 0x000023d373931e8e, 0x000000000007f96e}}, {{0x0004e4e1b942add8, 0x000e15adf3d9957d, 0x0005ba50de0860ba, 0x000ce33a82d3736d, 0x000e718c8aa3f9fb, 0x0006ccf69f307823, 0x00065b860578cf41, 0x000000000001ef84}, {0x0009d5f6cc7a9ceb, 0x000939ee0cf97011, 0x0002f3cbdb7c8fc5, 0x0009a8dc09da90cb, 0x000dcbf3ccb8f99b, 0x000a626321f521c2, 0x0009da6bf6694891, 0x00000000000854fe}}, {{0x0000917c5016c853, 0x00049e44e3f85fb2, 0x0000e1793eed8bac, 0x000254501c4e171e, 0x000cce52defb1004, 0x00063100ac12df68, 0x00035fb1fae2fbf3, 0x0000000000035732}, {0x0007edc8c1da40d3, 0x000c58d4deb655bb, 0x000bfb14f6d9d28f, 0x00085835a4e118f4, 0x0001308772e93249, 0x0004e48765abfa96, 0x0007b241c7611ff5, 0x000000000001f586}}, {{0x000782cfada548c3, 0x0001e463031709b7, 0x0005afd4d0d5166c, 0x00097fff172c7d05, 0x000735b193cfd8e4, 0x0009df4bc7f7009d, 0x000e376b9fd3f7f1, 0x00000000000b46f1}, {0x0004c800fedd3a70, 0x0000987c6eaa8c8c, 0x000dff8047ad562a, 0x0001042539eab96e, 0x000779b8f5cc2a12, 0x0007840dc29a6d5d, 0x00030f33803a10b7, 0x0000000000011a6a}}, {{0x0000457a60ad991e, 0x0005e3c90a59f250, 0x0005eeda9345d42a, 0x000885c1a0d58e29, 0x000d6816b0099aca, 0x000e4718f77b9b6d, 0x000c458e5c12139e, 0x000000000004e4ea}, {0x0005f9c85e9bfc5c, 0x00086c00c3568eed, 0x000b5b4b0eba61f9, 0x000ffc75eaf3eab0, 0x000d42a87e32cba1, 0x0007a882f5f99092, 0x0005122e7b49c76f, 0x0000000000029040}}, }, { /* digit=96 [{1,2,3,..,}]*([2^384]*G) */ {{0x000dbfc10083fe9c, 0x000bfcf17f9dc084, 0x0005e1e364b063e9, 0x00054ffe437b29cb, 0x0009e27ee9e2a694, 0x0003af03b6628d78, 0x000d6256e3b975ee, 0x000000000002f532}, {0x000e1d6aa4b057a7, 0x00043cae15213418, 0x000003dc9b2b9ddc, 0x000a959fa4d82608, 0x00055ae17566902b, 0x000c82eb4bad700d, 0x000ea716b2c5dc14, 0x0000000000036708}}, {{0x000e41b4a9c3409a, 0x000849cbd62cd8bb, 0x00047e8c2d4de38c, 0x000bbe98f886eca3, 0x00049b432990b7f3, 0x00030035684860e8, 0x00029ed19a3bafa4, 0x000000000000e209}, {0x000ed539231869f6, 0x00098f15ff660294, 0x00050e66a84ebdc7, 0x000de8d2955612f1, 0x0006ec97a4a53ec6, 0x0000d15fe2d95b4e, 0x00024d868731f0f9, 0x00000000000aefae}}, {{0x000253f48e5fab58, 0x0006889f97859df6, 0x000dee3f7bba228a, 0x0001d4ea62a5c827, 0x000ea3045da6826e, 0x000d3d237ecba3e4, 0x000358beed1da058, 0x00000000000b8b41}, {0x000293271a9d4293, 0x000d2730e7ac94c3, 0x000f438703e7096b, 0x0004cace8c1c6462, 0x0001055d39de9ba9, 0x000b71db3ec7c382, 0x000a11c89705a82f, 0x00000000000781b6}}, {{0x000606caa5686427, 0x000cdc1951fb0886, 0x0000daff401d6319, 0x00009bb2754f1d38, 0x000e0e0e2bf19831, 0x0005a3da40f7db33, 0x000197348c4e1937, 0x00000000000840a6}, {0x0008d7f45b2f9769, 0x000d11687a735d22, 0x000434d1e1dee1ff, 0x000773c0aa9e79d1, 0x0009f56de9654a25, 0x000dda7af656f6e2, 0x00063fdf84666df0, 0x000000000003f9e4}}, {{0x000a9c9951735edd, 0x0006afe9f90d3ad9, 0x000f97a0b45a07d7, 0x0007d6ec36e3b706, 0x000f580c8e6dd513, 0x000bab45c3ea55f4, 0x000d5819398b33e1, 0x00000000000aee76}, {0x000d9c115c469d59, 0x00071e72c8214ce4, 0x0006b3ef7ac6abe3, 0x0001ac198f9553cb, 0x000a1c98ad467fa5, 0x0000ebbb2019ac4e, 0x0000a68942e16e01, 0x00000000000bed3c}}, {{0x000f13cdd62e69a0, 0x000461a814bf695a, 0x000e4323f4986584, 0x0001bfa2a4dd16f8, 0x000a76fb9f2b33c9, 0x000b1f1114af4d9c, 0x000b45a23635ef75, 0x00000000000a0891}, {0x000bef0dcdd6b903, 0x0005f5d1b87ba5f6, 0x0005d7ac1d6bdae8, 0x000cb4543d4ef435, 0x00064aa784ea70bd, 0x00070e4220ed12d3, 0x000483009cd34901, 0x00000000000280cf}}, {{0x000bddf9aa596a1d, 0x0008952c04b79c0e, 0x00099a2770f3fa4a, 0x00044bf1911b3184, 0x0006bb897d318407, 0x000e9de5dd13f080, 0x00052b376dc8b81d, 0x00000000000c996b}, {0x00047f465159b51f, 0x00041d91e47b224a, 0x0009b71ad19e642b, 0x000c167eface7572, 0x0001d4805ed6a441, 0x0003fd6654eb9588, 0x0005778fc93daf3f, 0x00000000000cc570}}, {{0x0000b16f46a35f8c, 0x00065a630c20c4e5, 0x0001f4362772ed03, 0x000aca10c0dec6cd, 0x000ba9e2f55428c8, 0x000bbb1705d34bb5, 0x000f6e8e81b4f732, 0x000000000008363b}, {0x000ca7950547e910, 0x000969603fe028be, 0x00047954fea1ddef, 0x000bb8efc191d12e, 0x0005dba97347c0da, 0x000656aaaf0e463b, 0x000cf0b7f7c207a8, 0x000000000003f08d}}, }}; #endif /* #if !defined(_DISABLE_ECP_384R1_HARDCODED_BP_TBL_) */ IPP_OWN_DEFN(const cpPrecompAP *, gfpec_precom_nistP384r1_radix52_fun, (void)) { static cpPrecompAP t = { /* w */ 4, /* select function */ p384r1_select_ap_w4_ifma, /* precomputed data */ (BNU_CHUNK_T *)ifma_ec_nistp384r1_bp_precomp }; return &t; } #endif // (_IPP32E >= _IPP32E_K1) #endif /* #ifndef IFMA_ECPRECOMP4_P384_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecprecomp4_p521.h000066400000000000000000017702761470420105600276030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ECPRECOMP4_P521_H #define IFMA_ECPRECOMP4_P521_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_defs_p521.h" #include "gfpec/ecnist/ifma_ecpoint_p521.h" #define BASE_POINT_WIN_SIZE (4) #define BASE_POINT_N_ENTRY (1 << ((BASE_POINT_WIN_SIZE)-1)) #define OPERAND_BITSIZE (521) #define LEN52_P521 (NUMBER_OF_DIGITS(OPERAND_BITSIZE, DIGIT_SIZE)) /* P521 affine point */ typedef struct { BNU_CHUNK_T x[P521R1_NUM_CHUNK][P521R1_LENFE521_52]; BNU_CHUNK_T y[P521R1_NUM_CHUNK][P521R1_LENFE521_52]; } P521_POINT_AFFINE_IFMA_MEM; extern const __ALIGN64 P521_POINT_AFFINE_IFMA_MEM ifma_ec_nistp521r1_bp_precomp[131][BASE_POINT_N_ENTRY]; #if !defined(_DISABLE_ECP_521R1_HARDCODED_BP_TBL_) const __ALIGN64 P521_POINT_AFFINE_IFMA_MEM ifma_ec_nistp521r1_bp_precomp[][BASE_POINT_N_ENTRY] = { {/* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{{0x00031a16381adc10,0x000f3f18e172deb3,0x000e0c2b5214dfcb,0x00017fd46f19a459}, {0x000ac947f0ee093d,0x000d50a5af3bf7f3,0x0001457b035a69ed,0x00009c829fda90fc}, {0x00011cada214e324,0x000274e6cf1f65b3,0x0000000000000000,0x0000000000000000}}, {{0x000460e4a5a9e268,0x000f4a3b4fe8b328,0x0004351396120445,0x000fd683b09a9e38}, {0x000132062a85c809,0x00064bf7394caf7a,0x000d7de8b939f331,0x000224abcda2340b}, {0x000163e8deccc7aa,0x000de0022e452fda,0x0000000000000001,0x0000000000000000}}}, {{{0x00090cf08640909d,0x000f1c99dd36bc1e,0x000b26b07ecb3fa1,0x000ae2d7a0e797d1}, {0x000aa83d508251d1,0x000bd9d9026d377a,0x000372a82ebb4df4,0x0003cd8e66031a96}, {0x000a461413a3a019,0x000f3f3417e59440,0x0000000000000001,0x0000000000000000}}, {{0x0003d2ee331fe1b6,0x0001ab6b30fa0d81,0x0004af6e07a7b8df,0x000d19247a757e5f}, {0x0008fb5c9c9bfd4c,0x000dd9f1bbef4f92,0x00090d14c836216d,0x00083e26d4bba055}, {0x0007769f85ae35a8,0x0009338053f9f677,0x0000000000000001,0x0000000000000000}}}, {{{0x000e9cf4d4910f78,0x0008ce976f1bd6be,0x0004316197502d2c,0x000acff10dd75a48}, {0x00019028ed35e8b5,0x0008d69f8b251d24,0x000d6bd0896bd46e,0x00072d891ecd5cf2}, {0x0005acaca3cda953,0x00048caeec8eb532,0x0000000000000001,0x0000000000000000}}, {{0x000cfa6c0ee5f7e9,0x000c4650f7436072,0x000de49d2c8212fa,0x000f61e3867882e4}, {0x000bad816ad6768e,0x00061716ea67c6e2,0x0007c558fd1aae77,0x000fd4154e818be9}, {0x000655c0a7978aab,0x00016eeccbcfc363,0x0000000000000001,0x0000000000000000}}}, {{{0x0008d6d77d92b8ab,0x00043a09438c8179,0x0002d8472d2f17de,0x0003c5783350ea81}, {0x00083a8745c474f8,0x0006432cf1257f1e,0x00062eaaaa0e9e75,0x00048e2ff9cd7e03}, {0x0003e483866e30e4,0x00010261aa5a41a4,0x0000000000000000,0x0000000000000000}}, {{0x000a0825be109849,0x000fa3fe1a372686,0x00078234ce8ecf10,0x0004adc2f75dbfd7}, {0x000c2a029127ba85,0x00093cf941f2a5d1,0x000731ff178cc83f,0x00077b7371970dad}, {0x000585a55db2a90d,0x000ce95b39f00bc7,0x0000000000000001,0x0000000000000000}}}, {{{0x000194afcf14a49e,0x0005a84b7647983c,0x000f36c498b9c6ad,0x0009bf3cd194ebf0}, {0x0000a11b8897f578,0x00021c1e0636af18,0x00081ed5c78bbd67,0x00077eda9f869267}, {0x000e027585fbd2cb,0x000219639ede19c8,0x0000000000000001,0x0000000000000000}}, {{0x000d6f9bbc6f7598,0x000e61f46f584865,0x00092b9aa7bfc0b9,0x000e7affbce8f803}, {0x00079ba188aa0108,0x0003ddb44be48396,0x000ec0be4d01a384,0x000f4743970028f6}, {0x000a54089488e6c7,0x0000eb764515b988,0x0000000000000000,0x0000000000000000}}}, {{{0x000fb915a75b36d6,0x00098df6fbc9035c,0x000ab2bf9c05711b,0x000a98df4617b374}, {0x000b9ca70393d11c,0x00092fde650b0a9f,0x0000a8356f25580a,0x00084bbfeb8e79cc}, {0x000a24068cab11e9,0x00090ca9977f9a7c,0x0000000000000000,0x0000000000000000}}, {{0x000f780956b43319,0x000666bc2c6a278b,0x0005aae506d6f0f5,0x00013a79101ee3dc}, {0x000464efcb64c26f,0x000b655b96872b32,0x000205493100d454,0x000db9ed2d404739}, {0x000a371d8889555d,0x0007ac35716e9382,0x0000000000000000,0x0000000000000000}}}, {{{0x00015b574766756d,0x000756c4140b766a,0x000a87ee130cd00e,0x000e71dde237ca9f}, {0x0004c6c64d36f986,0x000ec61846855fe3,0x0000c69617b88a62,0x0000747aa4191478}, {0x00005839d062f917,0x000fb1a3775b2fed,0x0000000000000001,0x0000000000000000}}, {{0x0008f4b46df66eaa,0x0005c5e48292928d,0x000952eef7e3dae3,0x0008e70d2fcf3b38}, {0x0004f15ca91d1a2c,0x000ab5e87949e6f6,0x000edecc51365ef2,0x0001681412786eb8}, {0x0001ceb423c5ae2c,0x0001508868ec18bd,0x0000000000000001,0x0000000000000000}}}, {{{0x0000208b103ed8c0,0x000cf52a553c6734,0x000dad37a0202c37,0x00046bcf0d5ab144}, {0x000a4f845acc60de,0x0007adff52dc2bcf,0x000c51d82fc1314c,0x000ec54d801f0545}, {0x0005808712dea714,0x000fb931541a41cb,0x0000000000000000,0x0000000000000000}}, {{0x00058cc64475550b,0x000b21788f8bc00e,0x000a004a389a9c56,0x0002e2bc34cf9dd4}, {0x000da5ff85d06f83,0x0008c4f4e0552c88,0x00041ef30833bd47,0x0006f4f16038ada8}, {0x0003c429dcd227c7,0x000e2410247ed5b7,0x0000000000000001,0x0000000000000000}}} }, {/* digit=1 [{1,2,3,..,}]*([2^4]*G) */ {{{0x000f45f44362a272,0x00062847c0d42017,0x0004003ee6e299d3,0x000c2b186f86dfae}, {0x000005072cb2ed3c,0x00094a1ff8c430e5,0x000197c69058c452,0x000b30c97e9f9eeb}, {0x000563a1d859543f,0x0005682eed4bed13,0x0000000000000000,0x0000000000000000}}, {{0x0001e8dcd0f160b5,0x0001397c4de39d5f,0x00069468c3199a97,0x000eccc4294f1802}, {0x000a3d505983ad64,0x0000e0c1709cc6da,0x000e51864a5b5c16,0x000261dc006a8763}, {0x0009e9f34b9099af,0x000b800fe38a58c6,0x0000000000000001,0x0000000000000000}}}, {{{0x00059ae8d65b4828,0x0008ad5c3b72b54f,0x000ae6b62e3c123c,0x000d2e8fca4e7ba3}, {0x000cb7633eb4deb5,0x000b750251aee39a,0x000d3f677dcf2f5e,0x000b32a703401c6d}, {0x000a5d0ad9a1f1f0,0x000d234a21b83d7c,0x0000000000000001,0x0000000000000000}}, {{0x00011dec3fd34650,0x00054d4c8a50ab55,0x000b2d5cb0b1b4ae,0x0005079b6fe6cc64}, {0x000eb5cdba6f0e3f,0x000ef10266dc0c66,0x000ef80e32e16ebb,0x000c5faff80cb3e0}, {0x000f9f041347fbde,0x00055c088b1af3af,0x0000000000000000,0x0000000000000000}}}, {{{0x000fecd778ec8555,0x00013eb0956c3cd6,0x0005e90a57516438,0x0007f84773320ba9}, {0x000dfd66f6e10d88,0x000a16d04c079fb7,0x0009e6452c01f397,0x0006b339081619a5}, {0x00076316466573eb,0x000a315640ac72e5,0x0000000000000001,0x0000000000000000}}, {{0x000e34d296b0561e,0x000ac0c9e92b6a35,0x000402420e573d8c,0x000d871e142cb792}, {0x000bf1bdbe0a1707,0x000d7310a6b250ec,0x000894a7b366170d,0x000fe4a684f16643}, {0x00025d9fae0bb793,0x000c96f6d42adcf6,0x0000000000000000,0x0000000000000000}}}, {{{0x0006ae6a85f73844,0x000ee1c671907ba1,0x000014d027ea0da9,0x0001f3800efad55c}, {0x0001bb9d3e0160b0,0x00038df5e9e2f7ed,0x0000a5ce67c43969,0x000dd40c305dd65b}, {0x000c97f61533f5ed,0x00097668a79ebe01,0x0000000000000000,0x0000000000000000}}, {{0x0009d235c3ae123a,0x0008b82c52fc6fad,0x000edd0329eea2d7,0x0007cac021e0e0d2}, {0x000a5887a53dcf1d,0x0005d60b2dd0a846,0x00031dd1b4f43d5c,0x00064597d8ee0e86}, {0x0002bdcac36cdd8e,0x000902b9d50810be,0x0000000000000000,0x0000000000000000}}}, {{{0x0002ff15cc9efbda,0x000d0adea1bf15e4,0x000712003c28f70c,0x0009acbb183fe29d}, {0x000e35ff46058b74,0x0000e6fbe9505c1f,0x000949d4ed7c586f,0x0006bc96db22c518}, {0x000e9fa6b4caa767,0x0006b3b723ba4dae,0x0000000000000000,0x0000000000000000}}, {{0x000d4a1dbb01ce30,0x0002733373d1589b,0x000695b9bd79abea,0x00024c417444789b}, {0x000a3e366b3687f5,0x00018eccb8e87edb,0x0007fa4355949d4f,0x0003b1b5225855c5}, {0x00040d600e111ea7,0x0002ca9912224327,0x0000000000000000,0x0000000000000000}}}, {{{0x0001ccaa77955b13,0x000980cc45066e57,0x00005f6f02b3f9b1,0x000f381f6757639e}, {0x000d14e03775ce84,0x000770c3535ef348,0x0000c573845ff7f4,0x0007edbd50365fb5}, {0x000ae96135b16a31,0x000b1cbda8a1cae0,0x0000000000000000,0x0000000000000000}}, {{0x000fb5af8ac6debc,0x000ccace499e422e,0x000f85f9a34dea5d,0x00099ffe8fc76f8d}, {0x000700f62f621078,0x00048a20afbdb94b,0x000353ffe99ecf56,0x0009d5421253436c}, {0x000d53ffd3fcac92,0x000092a9413337e3,0x0000000000000000,0x0000000000000000}}}, {{{0x000cc6739bc22034,0x0002d46c578a3cfb,0x00074dd1918f2158,0x000820e4ee32d9c8}, {0x000ee4769c451119,0x000a52dc0b788cd9,0x000ea08ad1dce239,0x000e6c51ce30fbf6}, {0x000c6808b739646f,0x00014612aa8ed807,0x0000000000000000,0x0000000000000000}}, {{0x00084f57ce386096,0x00001bd8dd33a19d,0x0006d6cf7616b3bf,0x000aa0ec8a31fd3f}, {0x0000f33cd7d20cf3,0x000d8c7b490a7ae4,0x0003afd25187398f,0x0001d4b82d520c24}, {0x00008bc63a1c99f6,0x000da20702f937af,0x0000000000000000,0x0000000000000000}}}, {{{0x0005f3504967c9f8,0x00081372b9b7d4f0,0x00090711a09dabb5,0x00052fc0a79713f3}, {0x0008ebea8efb840b,0x000ba724a4b43b13,0x00089257bae703ec,0x000c5de16b6e9669}, {0x000a9811fd41e4b4,0x000c0fc1b18e0380,0x0000000000000001,0x0000000000000000}}, {{0x0009bdb977d41aa0,0x00084a0964efd898,0x000049a3954725e1,0x0002567309871a1a}, {0x000d6462734e1923,0x0004d24ffa586e4c,0x000a7d5e1d8d7ce5,0x000f69f3efbcb30d}, {0x0007de3d3416e700,0x00041ee729987fef,0x0000000000000001,0x0000000000000000}}} }, {/* digit=2 [{1,2,3,..,}]*([2^8]*G) */ {{{0x000757d0283c0ad6,0x000745c834df0056,0x000e5caf285c0d9c,0x000faea391f23599}, {0x000232d4e48a9620,0x0009bdc7a7b74615,0x0002fd4f47934e59,0x000c4f65ada3d4dc}, {0x0000798974c81e39,0x00061064a2c57e3c,0x0000000000000001,0x0000000000000000}}, {{0x000a38d40ea9cd04,0x00060922a435ef3f,0x000a826a53bc247d,0x000e94d33d8a1866}, {0x000de75ac695cced,0x000bcb2e7b2b9c71,0x00016e1d52b9aa78,0x000540f2da2b1a83}, {0x000881db4e2a0769,0x000e217e4c0ddd49,0x0000000000000001,0x0000000000000000}}}, {{{0x0008396a04a1a9b5,0x00071e1d4dea3fc9,0x000f1b1b60428524,0x000875279e270a42}, {0x00031e46c1327bff,0x000c05c823fe0222,0x0001988e4c1b07ef,0x000346e86dbfa458}, {0x000ea14d7c3803e0,0x0002698c2f4163f3,0x0000000000000001,0x0000000000000000}}, {{0x0004df73f1c64b3b,0x000bae3f77cba047,0x0009fac52f482f0e,0x00046303eabe2a5c}, {0x000605a86c7774d0,0x0006157561d8716f,0x0006dae76cfe4cf1,0x0006f10528e0564b}, {0x0008d8ad69113bb2,0x000c2f933ccc8b87,0x0000000000000000,0x0000000000000000}}}, {{{0x000963cd234bdeab,0x0005b961fb152043,0x000192d80595fa4f,0x00021e095276439a}, {0x000ab3cdd8200acb,0x000b977cb97a7564,0x000f1ac5e95df534,0x000082ed91f8da63}, {0x0005eeb0ff149253,0x000e11676ac3e35f,0x0000000000000001,0x0000000000000000}}, {{0x0001cccbb8a0782c,0x0008ef764987a4d5,0x000621e7649cd3df,0x0006ca705ffe9912}, {0x000d887d63f6769b,0x000a2f7ad40e5963,0x00074e3b9fc2e426,0x000bd597aa3dacd3}, {0x0000fea916df09cd,0x000c4db4a1b5ffeb,0x0000000000000000,0x0000000000000000}}}, {{{0x0006312ffff6fab5,0x0006b5b394c36d7c,0x000ae9f8123d8c52,0x0007a4616b7fb3e1}, {0x000a92d9f22f9728,0x00095d4a0fd21b31,0x0002d23d7cbfded8,0x000b5c10574881ff}, {0x000e2bd04e830bd0,0x000fd69dfeb7774f,0x0000000000000000,0x0000000000000000}}, {{0x000b243fcf68f023,0x00066b7e7441cd83,0x0005c91b009a23e1,0x000f85c785f70865}, {0x0002122e7768c122,0x000fb751856db403,0x0001836d6df94b82,0x000098df3edc80b3}, {0x000298e9aeea7ce8,0x0006e6048ecb9605,0x0000000000000001,0x0000000000000000}}}, {{{0x000cad0b80b053c4,0x000883158e365644,0x0001acd6f66175a4,0x00078eba00f9062c}, {0x0000f302446bdc8b,0x0004ffcc5c874a3b,0x0001cc9e542baabd,0x000ca8d66f56fe73}, {0x000fec6e656e27fc,0x0000e12576ad29e3,0x0000000000000000,0x0000000000000000}}, {{0x000f2114ad6a5008,0x000ff37b5e9ff077,0x000fe609c9e85ddc,0x000612f68cb97937}, {0x00035cc97418d8cb,0x000e6da8506bf5e6,0x0001561e4122e23c,0x00026ba1b08bd010}, {0x0007eb4a708cbd94,0x0000c9d309deaf41,0x0000000000000001,0x0000000000000000}}}, {{{0x0001bba765fa9bcf,0x0003babdc21b3ff6,0x00025b55117dbb2e,0x000cd85081bffb4d}, {0x00081cb8cbfa61b2,0x000244b920db891a,0x000db06e819df932,0x000532ca257bcc77}, {0x000ade96bb81f698,0x000552846b3d2e5e,0x0000000000000000,0x0000000000000000}}, {{0x000cc4965acbbc52,0x00019fc3317e41d4,0x000a394d289bf4a3,0x000dfcc926b6b451}, {0x00099fdc4795a3bb,0x000fbdeb87e6005a,0x000e9db4adbdc0b3,0x00050e680b14c0a6}, {0x000a1f2811642efe,0x000396ef97cb540f,0x0000000000000000,0x0000000000000000}}}, {{{0x0005f3ef0a7bd1f0,0x000acae8e898fb4a,0x000ba953fee10eac,0x000ac34b13e74541}, {0x000d80a4f317458b,0x000699b6bc22b700,0x0009d659b3752d47,0x000972beec5644da}, {0x00015e14a99a228f,0x0008731fa64678ce,0x0000000000000000,0x0000000000000000}}, {{0x00076f9ee24a5ff4,0x0001761a3d49abfd,0x000099dc50257cde,0x000182905bef244d}, {0x000f586d9a90e6d1,0x0007ebb4cb4857b6,0x00070d79d0a32ad0,0x0004bfe6c4dca5d6}, {0x0009e03cd5b7b143,0x00028c04a0538f51,0x0000000000000001,0x0000000000000000}}}, {{{0x000c6fc14a74584c,0x000402292021e48e,0x0009500ecd0a9680,0x00002339ed719b16}, {0x000ebb81e8a19412,0x00040e8e4db85440,0x0002a313f6a53c2d,0x00082796c5c684a1}, {0x000636765497c008,0x00020c751837b791,0x0000000000000000,0x0000000000000000}}, {{0x000740897b89a933,0x000f39feb6c7cfd4,0x0006675504305fd0,0x000708d724da0165}, {0x0003fcde5846c915,0x000cbcc847c7bb1c,0x00035875d5c58a40,0x000f531dd999d009}, {0x000ff3f98178ab52,0x000a7c4485d31888,0x0000000000000000,0x0000000000000000}}} }, {/* digit=3 [{1,2,3,..,}]*([2^12]*G) */ {{{0x000bc092fe2354e8,0x000850a2f27fd64d,0x0002ad51407fff03,0x000808402ffc14aa}, {0x0007fbe516b67c4b,0x000f027098449910,0x0009af3715688b40,0x000dbddce7795e2c}, {0x0008a5dc626ec8f7,0x00032acc9e1305cc,0x0000000000000001,0x0000000000000000}}, {{0x00014a5956e30ed0,0x000921ce664e13cd,0x000b7485d5a678ff,0x0001d65fed6fe685}, {0x000152b7d0453dd6,0x0001e48dc7a066d9,0x00012560c3395f08,0x000d6053e587c1cb}, {0x00076afca630f2cd,0x000814f0d70553c7,0x0000000000000001,0x0000000000000000}}}, {{{0x000a19c3686b1f78,0x0009545540d3da61,0x000fed5fc9dde90b,0x0009be8908cbe546}, {0x0002b931292ec657,0x000e0b221531c8bf,0x0003dcf64709233d,0x0006a91e2913f0e3}, {0x0003880d89929920,0x000d07ab37b02493,0x0000000000000000,0x0000000000000000}}, {{0x000b1d587081c0df,0x00062b5f29f3ee6e,0x00013755e246f468,0x000c2e51e2652ae3}, {0x00046ba6a65e2952,0x000fd1b792013b94,0x00049175e7bffb43,0x000166af7dd896a1}, {0x0003d0d5f68a4101,0x0003a34ff29cf955,0x0000000000000000,0x0000000000000000}}}, {{{0x000b9e5f2e5de279,0x0006be9e4c557ee8,0x000c510883da6331,0x00016eedfba63955}, {0x000b55eba66cb586,0x000d93dd071f901b,0x0000d11e4c33f467,0x00029c2288bdd752}, {0x000f22d4f3c9b728,0x000416f979cce9a3,0x0000000000000000,0x0000000000000000}}, {{0x000f91fa66b3408c,0x0009041780ab3969,0x0001e17f9e99f2b3,0x0002825a0408a22e}, {0x00013e814b39af10,0x00017c70c14077db,0x000fd91116e8d047,0x00025157bba11642}, {0x0003d53fd072760c,0x000130f596860d22,0x0000000000000001,0x0000000000000000}}}, {{{0x000ddddf5d1e5c64,0x000b39631d236577,0x0005fc5e812c4b6d,0x000ec807d1cccab0}, {0x0002c8729f1a1c38,0x000999e4061629e9,0x00088f56b4c00d1c,0x000c3cac8f29781d}, {0x000b02141cce3380,0x000920c7e0e0cc16,0x0000000000000001,0x0000000000000000}}, {{0x000234580d88382b,0x000b0ad02da7d076,0x000cc82cf5ae2d27,0x0008a15c3adad7f2}, {0x0004d7009305d2c0,0x000e9e632a55fa7b,0x00011560b55b693d,0x0008b565732e2a82}, {0x000f0adb63788cf9,0x00038e2d1f605489,0x0000000000000001,0x0000000000000000}}}, {{{0x00007e33611831c8,0x00062ce163c826e6,0x0001c1873d3e07b5,0x000df7813a79a532}, {0x0007451a6bebf65d,0x000789f014abc3f1,0x000cc2aa01512853,0x000bc25e7cee2985}, {0x000dd32f61a13543,0x000f9b061a57a2a5,0x0000000000000000,0x0000000000000000}}, {{0x0003734e520ae3c4,0x00041544fe045295,0x000321b2f9da98d0,0x0004ac066f5c4118}, {0x0004f9ed8d4d338c,0x000c2ea3577c3f4a,0x000a775eee973782,0x000efa3a3176188c}, {0x000aa0ec53f7823f,0x0009b227eec20996,0x0000000000000000,0x0000000000000000}}}, {{{0x000cab486125bb6b,0x000ce02028378ff0,0x0005e625f7d1c380,0x000dc7cec93bc7c0}, {0x000d0c3b6e1a5a67,0x0001da033baa95ac,0x000e0b126ba3c688,0x0005b900f71e6919}, {0x000cfb69d4bcab68,0x00090d9f859cecf3,0x0000000000000001,0x0000000000000000}}, {{0x00030307c7f8906c,0x0006bf1f14afae02,0x00001d0c8e70d7c3,0x00031fcdd396a945}, {0x00035972de152221,0x0001149c59aa6c9c,0x000e743c53f3251e,0x00072a17186bca64}, {0x000bae52281f6178,0x000c98982b2d35fe,0x0000000000000001,0x0000000000000000}}}, {{{0x000abaada33bf5eb,0x000334cbe9475074,0x000503921efaf87b,0x0001a3119b05ca55}, {0x000a4fa919940136,0x000a8bd8f158f3c3,0x0002e855587cab4c,0x000fd133003309bc}, {0x000a468f055eab49,0x0008de65f435935f,0x0000000000000001,0x0000000000000000}}, {{0x0005a479ed62ca37,0x00046fb6c0237009,0x000c6558be89daa3,0x000e86cd9c606b6e}, {0x000dcb5426f2b48f,0x0002744bfa702fd9,0x000e9ceab7372571,0x000cd8bef4768a91}, {0x000d361ea2d4f5d1,0x0000ca847b5f94d5,0x0000000000000001,0x0000000000000000}}}, {{{0x000c6a7b65b21bde,0x000fc723a29c73b0,0x000392643c39c3ea,0x0000b213f81be3c4}, {0x000e3ec734fa388c,0x000b26d37a33b98a,0x000332e230742689,0x000e28354ec1687a}, {0x0000d4b7e6935b64,0x000ba79d55aecff6,0x0000000000000000,0x0000000000000000}}, {{0x000073362910afa1,0x0007fb8bcd336bd6,0x000b6c7a7845b5f6,0x000017305633e845}, {0x00076a907be72df6,0x000e65734d2814a5,0x000f113c7084b86f,0x000cd7bad9f20758}, {0x000f6af2a5030c22,0x0001647ff1cabc3e,0x0000000000000001,0x0000000000000000}}} }, {/* digit=4 [{1,2,3,..,}]*([2^16]*G) */ {{{0x00084cce9eb37269,0x000406ac65525f61,0x000c9acc4f25051a,0x0007bdd2651c4a44}, {0x00059571fa6bdb63,0x000cf1489d2ae9ce,0x000a821f56bdf324,0x0000e5fa827f61b0}, {0x00046a2449dcea62,0x000c947027c9ed4b,0x0000000000000001,0x0000000000000000}}, {{0x00095f1c50d4d450,0x0002c227a410cd04,0x000bc9ba135ee643,0x0004257073536858}, {0x0000b7e39c350531,0x00016eeb65d0616e,0x000e949a694a0693,0x00069aba0dc455bb}, {0x000d36d721f9d7b7,0x000a041dcb7a1d32,0x0000000000000000,0x0000000000000000}}}, {{{0x00030d330fc15e51,0x0006a88312448f9b,0x00027c12fd1499ca,0x000b765eaf5a132e}, {0x0008d01b2d2a5c3f,0x000e3517c807951a,0x000936a97c68ed6c,0x000f8cdd161ce67d}, {0x0005d9876ad5eb28,0x0009976496ac4a79,0x0000000000000001,0x0000000000000000}}, {{0x000d912524de7c0e,0x0001e66e4dff627f,0x000a96a9194e4460,0x000ccae884a673b1}, {0x0005d06054966f81,0x00032269452eba8c,0x000ba7677e70b535,0x000298891e5c17de}, {0x000f9a70e2fe55a9,0x0004d48b39032dcc,0x0000000000000001,0x0000000000000000}}}, {{{0x0009dc9a72f4ff50,0x000df54e86b3f74b,0x000b7fc672cd56a4,0x000ac313c91daa4c}, {0x00053d8b04fac047,0x000047ffb771df8b,0x000a8ad48cf7c44d,0x0008bf663542e196}, {0x000aa68b0ea4fed6,0x000483dbd49e0b45,0x0000000000000001,0x0000000000000000}}, {{0x0007d603e389e5cb,0x000ee233664de2d7,0x000994f96855ef7d,0x000c5bf8c8ab10b1}, {0x000c2f5ab3d235e3,0x000bff37afff2ae5,0x00050de9d0fd0f4d,0x000ca6d91d5250db}, {0x00042da0be2c950f,0x0001c70ec3836fa7,0x0000000000000000,0x0000000000000000}}}, {{{0x0009b222a53c1578,0x000733b1bb114a22,0x000887f6c13ff59f,0x000d5dfb2679cded}, {0x0001fd35dec8bbba,0x0000930770ea94d4,0x0007da8d4f0a6019,0x000d2142901c2ad0}, {0x0002aaa8648f142e,0x000f42252e455969,0x0000000000000001,0x0000000000000000}}, {{0x0004f335e4753950,0x00010578c42f0d9b,0x000fda89975c2716,0x000761372c49b195}, {0x000583ac76051357,0x000cd0c4d54de0d0,0x000c35f47ffa549f,0x000731f21817e11b}, {0x000ac2b103f57a56,0x000284cde0cd7146,0x0000000000000001,0x0000000000000000}}}, {{{0x000bb2a3bcba0504,0x00052359d22ba169,0x000ee4d727c18bc1,0x000338aababfd9ca}, {0x000cae35505124c8,0x000599b6e8a9cc3c,0x0003c6415386807e,0x00043919da2fc5ab}, {0x0001a4c6fd2ee43d,0x0007be38ead93480,0x0000000000000000,0x0000000000000000}}, {{0x0008c66b564a97d4,0x0002177834d44e8b,0x000690ef30774807,0x0007151d926feb1c}, {0x0003fbe2f1f3454c,0x00048ce8e6456bd0,0x000270c04a6964dc,0x000fe8febbc7afec}, {0x0000f159a483b3a5,0x000aca96cb139ad3,0x0000000000000001,0x0000000000000000}}}, {{{0x000c0e9763d8a013,0x000baa65d7b1d37f,0x000608a4b87c8c06,0x0008c2592e527b8c}, {0x000aacc19bb3aa2d,0x000ce5b0adb09308,0x000e0f42458761d4,0x0002d73d4f707a6e}, {0x0003867f8d791c44,0x000c943ba7a1a60d,0x0000000000000001,0x0000000000000000}}, {{0x0007ffca3e51b076,0x000d23467af3d90e,0x0009427b9fa60c44,0x00054ce0e4a16358}, {0x0001655e4129aaff,0x000befd5ea275c28,0x0000ce27c03c7fcc,0x0000c97ca421b716}, {0x00069ee6f84bb35f,0x0007ec35e0436eea,0x0000000000000000,0x0000000000000000}}}, {{{0x00033b8c99430421,0x000e3aa65723117d,0x0001482e2ca3fcee,0x0006dfdb52560262}, {0x00036a105a9eb6d9,0x000c0fd8b7bdc41e,0x000c58ba2f2edd58,0x000c050043d8b271}, {0x0009966a34a51907,0x000aee0fa52e13a7,0x0000000000000000,0x0000000000000000}}, {{0x000c2d7066d5fc91,0x0000d462accbe2da,0x0008397028d0b78e,0x000b525e2c9d107f}, {0x0003dfedd5666711,0x00083957250c9620,0x0006d0f2be094638,0x00026dd96c8ff985}, {0x00098fe829c7a670,0x000dacfc430b6d43,0x0000000000000000,0x0000000000000000}}}, {{{0x000aba8bae3f0048,0x0006fc5f421abd9f,0x00094ac402ce8227,0x0005bead91f2efc8}, {0x000d28241f32e7d5,0x0008bce170cc1090,0x00050cb19f59df3e,0x00034ac35c2de273}, {0x0003cf90c3e6cfc4,0x0002a784bc2847d1,0x0000000000000001,0x0000000000000000}}, {{0x0003f87f754f1aa3,0x0003382713cbe9fd,0x00034163c334fd8d,0x0004cbe346cada61}, {0x000dd6aa94a54721,0x0007b9235830a042,0x000500be120acf2f,0x000d30c3e8d009be}, {0x000225e2751dc7f0,0x000714b7edd06e6f,0x0000000000000000,0x0000000000000000}}} }, {/* digit=5 [{1,2,3,..,}]*([2^20]*G) */ {{{0x000c1256fe47d13c,0x0007012fd1181020,0x000c4a469315aa78,0x000b1163ea26a86c}, {0x000e4be00b905056,0x0002f1dad4a0ac68,0x000e2d8c19c57695,0x0000bbc11daec6fd}, {0x0003baf9c6293f81,0x000d375056fba03a,0x0000000000000000,0x0000000000000000}}, {{0x00073f08bbfc9af7,0x0006c14cc716b559,0x000b5b613b18efce,0x000f005d64d3ad94}, {0x00034ba83b800248,0x0009ee4cf2a375eb,0x0007d29413af2a4c,0x000525ea872268a2}, {0x000c082bd8d12fde,0x0006fa2d233189c9,0x0000000000000000,0x0000000000000000}}}, {{{0x000f1bef2c1b123b,0x000c9ca73fb5cd85,0x0001a80d76a111a8,0x00025f888d3b7461}, {0x0003f7765b87f2e3,0x0002e36012c8ad9e,0x0009dc42c7cf6c49,0x000d7d5db366bf5a}, {0x0005359f96228a81,0x000772725123cd91,0x0000000000000001,0x0000000000000000}}, {{0x0006c7a0e2cfcba5,0x00097fa38cc5da8b,0x000b43bb38eee14f,0x000f15c0770c4afd}, {0x00093138850f3aa0,0x000658cf7e3953b9,0x0007c8bb70f07792,0x0000d78fd38c1d44}, {0x00023ebe4681177a,0x000c9d704ca7518e,0x0000000000000001,0x0000000000000000}}}, {{{0x0008fa7e4527a9d3,0x0004db4e9fda74ba,0x000404855f433494,0x000f130f65201753}, {0x000d719a9846d31d,0x000c651ab9661cb9,0x000b653c04c2995b,0x00031b2c3fb591c2}, {0x0000b91d21b65fb3,0x000c1f9233b624c9,0x0000000000000001,0x0000000000000000}}, {{0x000eac108061f9eb,0x000a2e86d9cc5afc,0x0000e2ec8f94cdd0,0x00040675309b7d38}, {0x000320d2223f6f2c,0x0003be480dc1e34e,0x0007b72b364f62ba,0x00063595753dec52}, {0x000283d90f6639f0,0x0001d567ed0c354e,0x0000000000000001,0x0000000000000000}}}, {{{0x00067e2e3d478324,0x000b9d2b33e93756,0x0005cc9c7d0711cf,0x000aa7c2edf0adb9}, {0x000b6610b704fc5a,0x000107368e770150,0x000cc4ef9af2a471,0x000afe1e566d06e6}, {0x000a67146814dd0c,0x000fd36c67f6637c,0x0000000000000000,0x0000000000000000}}, {{0x000b744b33ca6a46,0x000a2ad960d19dec,0x00099ff41dbc0bcf,0x000977ca933b28a6}, {0x000a7951faf63b97,0x0005168f23ca3752,0x00097d901e0f16b1,0x000105f55f964ea3}, {0x0003c0d403b374a5,0x000d43e408ed3a81,0x0000000000000001,0x0000000000000000}}}, {{{0x0007586c50a55f86,0x00026583c230d093,0x0009c8f1eaf61062,0x0009876910419f67}, {0x0006e8d67dbad2c6,0x000c3c184d440783,0x000753899fd2f814,0x00037825fefa52a3}, {0x000f0758545a721e,0x000498a4b823d5ff,0x0000000000000000,0x0000000000000000}}, {{0x000e376ebd4ed258,0x00004d6a23fbe496,0x000b69ec3505f765,0x0008fe6b545afc26}, {0x0000e87ed2073fb2,0x0006145047af95f2,0x00053f84d27cd1ba,0x000fa35d865dc4cc}, {0x0007b711a9ee96b7,0x0008ec430aefdeb0,0x0000000000000000,0x0000000000000000}}}, {{{0x000354ba169146af,0x0008c79fdb88cac7,0x0009f85e2efdc64a,0x0001012d7f3a69d0}, {0x00017d2bed232563,0x0004dfd89cfd4d1f,0x0008288e64d46be0,0x00089f8bf20fd559}, {0x0001d08641f269d1,0x0009fc333e29ffc1,0x0000000000000001,0x0000000000000000}}, {{0x000c7dab1b832059,0x000223bbef8e949c,0x0007f10fed75c714,0x000647b0bb61d266}, {0x000b8e823dbf309c,0x000601c5a1f58db2,0x0009c023a71fa3e4,0x000a0b5cbdd6344f}, {0x000df6a6577b11f1,0x00027e6eb12db5f8,0x0000000000000001,0x0000000000000000}}}, {{{0x000b94e9f2c64c2a,0x000dff9c4cc3460d,0x000339e03c0646b9,0x000ca76c7ae26f18}, {0x000612ba1712f64d,0x0006950e5f2c8040,0x000569eb5bf0fae1,0x0006185858b613d1}, {0x00080b1245b35ba8,0x000d9a3c93740668,0x0000000000000000,0x0000000000000000}}, {{0x0005f1c44e1c9646,0x00061096f83044ee,0x000e69176fe10924,0x000a78875cfb2614}, {0x00007825516a8324,0x000065d69cfbad90,0x0001f873d71727bc,0x000185c81c530662}, {0x000c1471ae21856f,0x00047e68582e4e3a,0x0000000000000001,0x0000000000000000}}}, {{{0x000ce1c67b68f07c,0x000dfa5469124c9a,0x000ccd6db2024f3d,0x0002fc6faadd52b4}, {0x0005124af076574a,0x000510591517b271,0x0000081118a106bb,0x0007cffda2d67e24}, {0x000b3b39fc6925ec,0x00012037b374e288,0x0000000000000000,0x0000000000000000}}, {{0x000d91b81541ec51,0x000c413a683e17ef,0x000952a60eda72b7,0x000b61d80495c130}, {0x000f6bf06a5749c4,0x000c7cbd39872c4b,0x0001a82e01cb7ce0,0x0001726d7547989f}, {0x000742de944906b4,0x00009f2e02ff3752,0x0000000000000001,0x0000000000000000}}} }, {/* digit=6 [{1,2,3,..,}]*([2^24]*G) */ {{{0x0000872f1cba7983,0x000a9c28a369cd44,0x00007ce63b6f5daf,0x0009c12dc12c54cd}, {0x000a00a67eec84f7,0x000bc7a4edee7a34,0x000ea82ff4e7f63d,0x000950ab492940f7}, {0x000953027dc3353f,0x000be21b37a3c6cd,0x0000000000000001,0x0000000000000000}}, {{0x0005f758ab77d6e7,0x000bab416ce18f4c,0x000b9e45e70a1adf,0x00038074a53a6ae6}, {0x0005919bbc5eaf8e,0x0006580a40639d33,0x00033f83c3446f86,0x0009f20b5de7abe3}, {0x000a42c48703c063,0x000ed659dbbfadd4,0x0000000000000000,0x0000000000000000}}}, {{{0x00025b49cc7d0744,0x000d5ca66a4107d0,0x00009a278704a0b9,0x00027e26383562d7}, {0x000c28bfb3e1fb8b,0x0006132452cd156b,0x000d9a249ca82ac0,0x0005a22d3a0e92d3}, {0x000b19aafd34655b,0x00048d36ff20dea2,0x0000000000000000,0x0000000000000000}}, {{0x000f6b3025835a5b,0x0008531143727c86,0x000c5c003858192a,0x0001da9352b2fd4b}, {0x000d25e79d62bdaf,0x0003c74903de7c27,0x000ad4718fc47302,0x00063e48286ed6b3}, {0x0005e2dbee1fb246,0x000857558feb16de,0x0000000000000001,0x0000000000000000}}}, {{{0x0009f56e96a543bc,0x000d31c6bb399ae7,0x00031b99e11a37bd,0x0006c0e42fdb7dca}, {0x00074aad0723ad0f,0x000aae97e4f8e5ac,0x0000fdee33ad0efe,0x000675078a78e14a}, {0x000909b38b03996b,0x0007469ca609f2ac,0x0000000000000000,0x0000000000000000}}, {{0x000466dcc50132b4,0x000eddd95df5a1fb,0x000a8d9a82cb91aa,0x000178685d056d78}, {0x000f44580cbb5024,0x000b8404125b7ea5,0x000c959397a21279,0x000b3c397b77ec41}, {0x00050358651ee34e,0x000febe48525c5d2,0x0000000000000001,0x0000000000000000}}}, {{{0x0003aa997f7f37af,0x000bd0399f83a0f3,0x000f152344eac6ee,0x0003cc5d1e36ba58}, {0x00058bcb7b01bb23,0x000e6e01c3b95ccb,0x0003f3cbd70b3470,0x0005471f142928b7}, {0x000f33fe8192a8fa,0x00067751b82a4272,0x0000000000000000,0x0000000000000000}}, {{0x000ea1f801a1be23,0x0000e029d67e2091,0x000355df0fe9219d,0x000069ec86128187}, {0x000e9196ceb57b88,0x000b831fc0c5d6f3,0x000b18561a90e72c,0x0006875cf51476cc}, {0x0009d0fdc775daca,0x000556f11fb0d65e,0x0000000000000000,0x0000000000000000}}}, {{{0x000d755a99415514,0x00085952e4dc0b72,0x000ddaa98f7198b9,0x0002cf0597f96150}, {0x000e7060ed10994b,0x0005df6128c96445,0x000ea5cf35637a95,0x000b47cf25cfbeee}, {0x0003e924da7f8ade,0x000d5d59754f0973,0x0000000000000000,0x0000000000000000}}, {{0x0007794536974a33,0x000bee39625b4887,0x000c916eff917626,0x000c143d7b2fe99a}, {0x0002b42a1f214f15,0x000a92c52323d0ac,0x000fb97a09db1674,0x00097d2bc99da798}, {0x000062e5a6c7b18b,0x000498e32a3a4e9d,0x0000000000000000,0x0000000000000000}}}, {{{0x0006f0528c6a99de,0x0005f78365a5404f,0x000a6130da7d607f,0x000ce8f385d457a1}, {0x000127a71db8c282,0x00075b1780f22e8e,0x0005f271ed981d16,0x0000879b71615445}, {0x0003f2395d4c8d2d,0x00002ffbb885eae5,0x0000000000000001,0x0000000000000000}}, {{0x0004e8a699830814,0x000f60c1a29f03dd,0x000620f1843d15d6,0x0005370351aa6497}, {0x0003f3bdc3d85b92,0x0005713630b15aa8,0x000b25038bafd76d,0x000aa324c45046f5}, {0x0008ff854c7ef0e3,0x000f873074cd9a42,0x0000000000000001,0x0000000000000000}}}, {{{0x000a5c1655f0c965,0x000ad8760b75d0c0,0x0002d3b7a7dc8ea4,0x000d9d864941a528}, {0x000eb47e8ca867c6,0x0001a8847066dfb5,0x000249722cfbbbd6,0x000d270c27ad4dec}, {0x000e74307c896550,0x000812fcfddc8f52,0x0000000000000001,0x0000000000000000}}, {{0x0009df50d9240b18,0x000a5431583e94ff,0x00044e5e649470bb,0x000156c0cde5a76d}, {0x000ad9f50c93b508,0x00099e86567b7ad7,0x000e7618f9dede32,0x000b84978d6f1f46}, {0x000aba70858d56a1,0x000626f5aa274be1,0x0000000000000001,0x0000000000000000}}}, {{{0x00038150eda6a189,0x000d5498edde21db,0x00010e8c4a802c3e,0x000d570892441512}, {0x000a6f9b009f95d3,0x000c80e954785d69,0x0008dbfa197859ea,0x000f9a954ad6166d}, {0x0005360545cac81c,0x00042d01aaa83bd5,0x0000000000000001,0x0000000000000000}}, {{0x0008a0342c362ba4,0x0008202cf6246957,0x0008c4987d0b8dd8,0x000becfec2b48e0f}, {0x000a0d5c621a63b1,0x000668f2b6a90343,0x0008bd4fe098700f,0x0008bd8fa8829c08}, {0x0007948513f0936a,0x000733ae92e72067,0x0000000000000000,0x0000000000000000}}} }, {/* digit=7 [{1,2,3,..,}]*([2^28]*G) */ {{{0x000f8517a4c96e5e,0x000b0e039e54c124,0x0001ec83d522549e,0x0008ead8eb02627a}, {0x000ef95771e9618a,0x0004f3a6b4497c2c,0x00055a41c4917c7d,0x000be8babd80080b}, {0x000548c7990585b7,0x000c64dabe54a06c,0x0000000000000001,0x0000000000000000}}, {{0x000269bac978d382,0x000c6bdf9b98b02b,0x0000247e075c4ed8,0x00030716d8e1a299}, {0x0003a019c94edbc8,0x000c1665fb3458f3,0x000e700cd4d82fa9,0x000a2326e507ff63}, {0x000452b8341c9bbf,0x0000dfc9214a3f5b,0x0000000000000001,0x0000000000000000}}}, {{{0x0001109faf34910d,0x00006e16fb098733,0x000f23db2247dc5b,0x000f53ef62c76a0d}, {0x00018f68431633f2,0x0003cbe6a9413972,0x000253b6d05ffc26,0x00047ed103a8b14a}, {0x00089d6938ee0b45,0x000f4f3310d7c6f3,0x0000000000000001,0x0000000000000000}}, {{0x000ae5ea5e61f0fe,0x000803eba63d9ee3,0x000ff5d7d44281cc,0x0006da525a289454}, {0x000688b5bf3e7fa2,0x0006c91ab88b9a08,0x0009907565a2877f,0x0001737c021210a3}, {0x00031db551223d6a,0x00041419f277aae1,0x0000000000000000,0x0000000000000000}}}, {{{0x000ab41a098c92a7,0x00072fa6811333e6,0x000851f03fd8fe3b,0x0008e34493163c43}, {0x00028174f0009cb6,0x000db83d4e177695,0x0004d1bfc734499f,0x000c56272647cc55}, {0x000d38b2b770d722,0x000fcea5c023f6ae,0x0000000000000000,0x0000000000000000}}, {{0x000d52df57e5ca52,0x00065ec98ce0bb77,0x0002140495f37162,0x000d03a5ffc6d632}, {0x000f0d0061a4f743,0x000af61ada3e0094,0x0004b70091a92992,0x0003fe83591d84a0}, {0x0008b7e8b2e59f37,0x0006892e459b7561,0x0000000000000001,0x0000000000000000}}}, {{{0x0005e28d077485e2,0x00020e97a1a0b220,0x0006679b5d8662c1,0x0000da8bd256806d}, {0x000925177882d56f,0x000fd447d9b3a0c2,0x000077e15eb4fc81,0x0000f15d98b7d44b}, {0x00021ac9944ac5bb,0x00096438b1a53927,0x0000000000000001,0x0000000000000000}}, {{0x00015ec8db3161c2,0x000f397c19309926,0x000de0771a46014e,0x00075e027929bb3e}, {0x0009dcd3fad002d9,0x0008c634c3d387bd,0x0009c3f4ebf24793,0x000a2c2da2b50807}, {0x000e85151e2b2209,0x0005f4bb80ad2ed2,0x0000000000000000,0x0000000000000000}}}, {{{0x000d84a6577d1d88,0x000209b195d9875f,0x0007dc25315ab09e,0x00041e59650e28f1}, {0x000f81b07fd77f04,0x000191d3288a8ccb,0x0001838964e3273f,0x00014aa2bd5786f8}, {0x000d924c29c83190,0x000d240eca2dec17,0x0000000000000001,0x0000000000000000}}, {{0x000c94cf500620a8,0x00017a01ff5bfc59,0x0001d4396ff8b7cb,0x0004fb6ee69226c5}, {0x000565facfed55e4,0x000fa0b30de43edc,0x000b20ea8612b643,0x00056d93e66dab8d}, {0x00098f9a9e46bfc5,0x000537cf26d7b09b,0x0000000000000001,0x0000000000000000}}}, {{{0x000ab3bbacf312ed,0x00003114377687ca,0x000ecbe360e1fdea,0x0000336e644349d4}, {0x000ce9701c97498e,0x000b970f76e36640,0x000d18aeb034f110,0x000d8c04737b96e3}, {0x000b828ff89d3a4a,0x000ceb091b279c08,0x0000000000000000,0x0000000000000000}}, {{0x00002832632c0b79,0x000f06083c30b6b6,0x000d6d46a5784fec,0x00018a1a822c2ef2}, {0x000ffd16846c810e,0x000859c7f32abfb3,0x000410206687e5a6,0x0001a4731948bcab}, {0x0009310e425eab64,0x0006640ebb114d39,0x0000000000000000,0x0000000000000000}}}, {{{0x000759039c7a9d17,0x000c2d4dd47b8758,0x000c1f2cd883e5fd,0x0007f9cf12cfd22e}, {0x000b330c8103c8b6,0x000fef902907b0c0,0x0008540db26c476e,0x000e726a64472792}, {0x000b090ef761ac1d,0x000f96107e57dd18,0x0000000000000001,0x0000000000000000}}, {{0x0004650aeff40f19,0x000f9022a822976b,0x000a5007e542efc8,0x0007e6336d263df3}, {0x000d3e6b563a86e0,0x000fc14e677c3dd9,0x0001920cf4b81cd1,0x0001cedaf8056af9}, {0x0006ebfcbc28b238,0x000af30ce3975f89,0x0000000000000001,0x0000000000000000}}}, {{{0x00090c95c3d0b9c7,0x000844b8f686b48f,0x000a746779417d91,0x000bd2f6b498e1e2}, {0x0002adf2e61e9354,0x0000db08d1aea1ed,0x000a497f347f08db,0x000c7871378402cb}, {0x000753c735de0850,0x0001f9ed5b707951,0x0000000000000000,0x0000000000000000}}, {{0x000d045e45f819b7,0x00024591e83186d4,0x0002f07b1add4180,0x00067074059bab68}, {0x000ea2b0f371c1d4,0x0000e5f219b0e391,0x000f844f22e68c28,0x000679b7f960b058}, {0x0002502036ca9899,0x00028a1f63acdbd1,0x0000000000000000,0x0000000000000000}}} }, {/* digit=8 [{1,2,3,..,}]*([2^32]*G) */ {{{0x00023b6569acb75b,0x0008bff580463d22,0x000bd3d896f7a55f,0x000bc35819d6f3c8}, {0x000fcf8dfdd32dc1,0x0007477a57a2786c,0x000a3b0ae5589b65,0x000806de5eae9f47}, {0x000782fcd93f2178,0x00096dd9479ee32c,0x0000000000000001,0x0000000000000000}}, {{0x00029435cbeebc5d,0x000d8352a35de209,0x0004ce809af5b11d,0x000a76cf080ab8c3}, {0x0002250478b1ce25,0x00003b3ff7216bfb,0x0004133d87f47621,0x000a4132748099b3}, {0x00029b68995f627a,0x0006fb62b3cf30a7,0x0000000000000000,0x0000000000000000}}}, {{{0x0009267d43d108b4,0x000b5b0396f4d947,0x000b1e5f7f088692,0x0009c3c1fd9437e3}, {0x0006cb9b9b7fa950,0x000a37b6c115a75e,0x00062d05b42f650b,0x000d5b3cf510dbbc}, {0x000a49bf06d5fe62,0x000049824e6593c6,0x0000000000000000,0x0000000000000000}}, {{0x0007f70f36b1fb53,0x0004a3eb94fc53cc,0x00082c0e60f6a2b3,0x0002888aea4bc9d4}, {0x000d37ab9ed318f4,0x000a505ae0c0fe3e,0x00082c9e94fad3b1,0x000efa0f31285453}, {0x000bd4be69ae4fb8,0x000003a516fe8844,0x0000000000000001,0x0000000000000000}}}, {{{0x0005e8088591d8c2,0x000c6e24bb4a7ab3,0x000968fd3709e47e,0x000d55e3e7d95582}, {0x000f8783f2538474,0x0003b454e19d35c0,0x000724c4578fbe58,0x000b98f51326114b}, {0x00090d99b97ee546,0x000691801229b8f1,0x0000000000000000,0x0000000000000000}}, {{0x000e4a0a2aa86765,0x000aa08b19b4b67e,0x000c220cb11d4f5f,0x000c7d426ad0862b}, {0x0002dd7a63508ce1,0x000aae47773236a7,0x000cce936cda4ace,0x0000808ba7a0be3f}, {0x000c14a5b972c384,0x000887cda4655c79,0x0000000000000001,0x0000000000000000}}}, {{{0x0007786aa39096d4,0x000a4070017bccec,0x000926b1ae026576,0x000026855e810d17}, {0x00039def24d306c0,0x0008ac55c7d826c4,0x000b521e40f66cc7,0x000ae26697c9fbf9}, {0x000a75caf01aaaf8,0x0002a9d094aec346,0x0000000000000000,0x0000000000000000}}, {{0x000a161f4c1b67b7,0x000e72cc3c7e5f99,0x000fefa749b88977,0x00063737d6e24cf4}, {0x000ed4607a910568,0x00017686854dcfe4,0x00011acac7bc09c0,0x000cc731394d9ec2}, {0x0009e4dd8ac76909,0x000bc7246fb612d5,0x0000000000000000,0x0000000000000000}}}, {{{0x000d5c2ad970ea88,0x0000eb7dbc22b4be,0x00070d534e1a9e33,0x0004b0eab21921c0}, {0x00071b3a90f4b6c3,0x00015ce8387fd7ac,0x000ec28efad61dad,0x000f792985d577d5}, {0x0009ac313d175e05,0x0002d86582a5f995,0x0000000000000000,0x0000000000000000}}, {{0x000258f797f0af53,0x0006198f53a67607,0x0008e97661c802c3,0x000001f410140442}, {0x0003c270534a9c94,0x000a5333d3d840fe,0x00076ed16f99ddeb,0x00021b94ff80e532}, {0x0002761460189f70,0x00007bce48c909c6,0x0000000000000001,0x0000000000000000}}}, {{{0x00018e1640843ac0,0x000d435c11720f14,0x00057cebd3881c75,0x00023104876137be}, {0x000da25ae87bc97f,0x000052fc640f68c5,0x00027372b9f14882,0x000b4e854fcb3017}, {0x0009d3406b0f1a39,0x000e653db1df6886,0x0000000000000001,0x0000000000000000}}, {{0x000c416fe50a1e7a,0x000c29b7a99148a5,0x000d660bcfe2e7c6,0x000630309213716a}, {0x0004b63e38c0d1fe,0x00033bb86d3923a4,0x00056213e592fda9,0x00080b360f884315}, {0x000db3b21dcd9fe7,0x000617bc0a7836eb,0x0000000000000000,0x0000000000000000}}}, {{{0x00035cd63c7c9de3,0x000a91ffca828c02,0x000b3e377bfdd504,0x000496682e625999}, {0x000b8af1c462d519,0x0009570d96676ec9,0x000bf815f3869cb1,0x000b476a8b4fba76}, {0x00057597ce654eda,0x000e2235375a2127,0x0000000000000001,0x0000000000000000}}, {{0x000e9252adfeeb9b,0x000707b233b4a650,0x000ab158faa771d2,0x000df78fbc7a8536}, {0x000be88e5009a864,0x000abbc52635e311,0x0008769bd53cfa60,0x000305e36a566f93}, {0x0000e758e66271c0,0x000b10e12e9cdd0e,0x0000000000000000,0x0000000000000000}}}, {{{0x00092f38031c9da3,0x000f6f0dd54d0455,0x000298fe24144d05,0x0006274ae2d191b2}, {0x000909113fc1ead4,0x000dea702ccc54c5,0x00008c5763ea8c10,0x000635441e7274f2}, {0x00006b2f2578c573,0x000c3b8134369537,0x0000000000000000,0x0000000000000000}}, {{0x000ada464a85cfcd,0x0006064c2605a588,0x000004bbf31d5464,0x00010805ca04e18d}, {0x00067998cccf9032,0x0008398a6f896278,0x000dacf8d2faed14,0x0002de01ea7eca85}, {0x000eb7d829278474,0x000eb89fe5859b0f,0x0000000000000000,0x0000000000000000}}} }, {/* digit=9 [{1,2,3,..,}]*([2^36]*G) */ {{{0x000a73aaf5f01aa9,0x0009abe5e08d9505,0x0009fd8bcd318e91,0x000915895b386f06}, {0x0004a0b5abd07d68,0x00039901b007bc24,0x000ff05c36936913,0x0003179dcef7684c}, {0x000125196e69b799,0x000a2823db7308b0,0x0000000000000001,0x0000000000000000}}, {{0x0008e83616d0d063,0x0003bf0c66e267f8,0x0006d375b822f9f9,0x000dc02109656c0d}, {0x000530c1fc16b6d5,0x0006bf6541ba81db,0x000443cb4caf94b8,0x000a87f59d3c1a6d}, {0x0002afcd60e10fe1,0x000a088d7e1995b7,0x0000000000000000,0x0000000000000000}}}, {{{0x0005b8daa50517e7,0x000dbed46676160a,0x00016e7a7e78dcdb,0x0008e1fc1b0f5e9c}, {0x000933cb9503e917,0x0006f78b36f2294c,0x0006ec3420442aae,0x000c01e17c7ffb2d}, {0x0007293b87d30fdd,0x00092836bed4739c,0x0000000000000001,0x0000000000000000}}, {{0x00075943e2ebfd04,0x0007b784cf37b849,0x000645eaa02ab285,0x0000b0ace12a0d65}, {0x000ff267c93aa3d3,0x000fa6954230be3e,0x00001e1903aa7ed6,0x000c311ae0c82cdb}, {0x0005f0bd3c5056d4,0x00022094d54a9827,0x0000000000000001,0x0000000000000000}}}, {{{0x0001c0660a4f2bbd,0x000c3d2fe061f455,0x000a2b6dd7091d40,0x000bf7437cc4883d}, {0x000f258011ddabd2,0x0001bdaba7aee852,0x000195b39f463ce7,0x000efb33b881bd7c}, {0x0007d695aede085f,0x000380f8fa2471bf,0x0000000000000001,0x0000000000000000}}, {{0x0006eeab983554b4,0x000f138a6f5a6dc9,0x000b29f154f07f71,0x0007d1c7242d7a9e}, {0x00042f3c7f1afb70,0x000af2896b44aee8,0x000b55601f569990,0x00061e36ed07c5c5}, {0x0005430facca2678,0x00016ea78eb21424,0x0000000000000000,0x0000000000000000}}}, {{{0x000aeaaabe68e207,0x00098b6eaee3177d,0x000f5c1267a6e353,0x00092ae2d01bbbbb}, {0x000bf3af1a4f4a2b,0x000532088e5cdfa4,0x000c8ee638a58f55,0x000bbce5e7aa2a0e}, {0x000a1644879c3f50,0x00025e378387c246,0x0000000000000001,0x0000000000000000}}, {{0x00069ee8884e88e1,0x00090f8ec2984b67,0x0001f9e47bd62fea,0x000f9867e7522665}, {0x000cb916cb0493d9,0x000106987f5be2cc,0x000869c71156e1c1,0x0005011576bd7bad}, {0x000b76a6e945007a,0x0000aec18de41f38,0x0000000000000001,0x0000000000000000}}}, {{{0x0007c59949c6f67a,0x000c897a229d2368,0x000118e3e788aa53,0x000794e3080e973b}, {0x000815a91046f15c,0x000ac04ed530c0f2,0x00078a4fe35eb925,0x0001fe18e7070c54}, {0x000f409ce7d9c57a,0x0008aafcd17edd4b,0x0000000000000001,0x0000000000000000}}, {{0x0002850fe8174557,0x00037e234694753d,0x000c528ec7d2c45c,0x000bdd41f346792a}, {0x00032ca964be2a36,0x000fef3e7911d679,0x0000101c72673a03,0x000653d6358ef0bc}, {0x000f874e2b9caaba,0x00045ebbcc31882b,0x0000000000000001,0x0000000000000000}}}, {{{0x00090baa505384e0,0x000993148d7d8454,0x000d948464cae379,0x000f46feac4f8ace}, {0x0007268d1b7c8dda,0x0000d4770e6c39b6,0x000c1955967ac571,0x00052098b74830a2}, {0x0008d17fe1904773,0x000191e5071ced85,0x0000000000000000,0x0000000000000000}}, {{0x000b4f003b56551f,0x0000872a7e419344,0x0001262c90a767f8,0x00015a9791770fa4}, {0x0001a4bc5606e253,0x000a665041696dd3,0x000da6d7ec137466,0x000cac07c562bd01}, {0x000c4a92e59de1e2,0x0007068f7d29994b,0x0000000000000000,0x0000000000000000}}}, {{{0x000172698b05a9bf,0x0000570dde3c4b9d,0x0004dad7e2ab8a86,0x000cc4fe376d08bb}, {0x000df2d396e50709,0x0008138716b38f91,0x0004e9a6a45d9577,0x000feda477817a06}, {0x0007062a4f79bf83,0x000ca12aff8e0103,0x0000000000000000,0x0000000000000000}}, {{0x000748577bd0ea3b,0x00068ca23c2d1e49,0x00079fc968bdb9b4,0x000359089d5d5807}, {0x00037ae7478afb4f,0x000f6ac1a17ffb5a,0x00076fb0ad6d0956,0x0003cc73da4935d0}, {0x000b38ddd4e896c8,0x00091fcd942654f0,0x0000000000000000,0x0000000000000000}}}, {{{0x000d06bf88e947b1,0x000a0ca717a0accc,0x000b428946c6ceb8,0x000992652bd2594e}, {0x00041806882365c1,0x0004f2f3523a8241,0x0002e27b634a60c7,0x0006f4680f2b83ce}, {0x0005e159f3342680,0x00053718c76ca148,0x0000000000000001,0x0000000000000000}}, {{0x00063dec4e0c9dd7,0x000cb7d74bb74e1f,0x0004a5f09446f95c,0x000f4555c75d0662}, {0x00028d6e7583fd36,0x00083fa30323cc2b,0x00010012c0c49bb7,0x0009907cd3d64f77}, {0x000c79e69ac90f89,0x0006c12cb352bde2,0x0000000000000001,0x0000000000000000}}} }, {/* digit=10 [{1,2,3,..,}]*([2^40]*G) */ {{{0x000bc2a7fe05ab80,0x0001a246f49f7a93,0x00091072db7cc0b4,0x00011f97d30ac7ec}, {0x000169de685e7537,0x0008a2ae9aef0acc,0x000e3c46bded4c6b,0x000604789cdc4497}, {0x000a082feb2b2ea2,0x00078fe890cba4fe,0x0000000000000001,0x0000000000000000}}, {{0x000edbc5c5076824,0x000298a472aca466,0x000a80660505ad15,0x0000c1cc1b16ca97}, {0x000dda2937bbf38b,0x0002545fac4d56c3,0x00090f07e35494b7,0x0000903e9ca74b57}, {0x000b43111b0c8bc4,0x0005465923f9e9c4,0x0000000000000000,0x0000000000000000}}}, {{{0x0008b52bfb73ff4e,0x000a4d6410d489c1,0x000ae318bb528530,0x0004b71f3f7d7028}, {0x000970b21b686b53,0x00001ea2751f5995,0x0001322663379ddf,0x000e77c11915800a}, {0x000261c476db4bea,0x000ae8e89c22a1e3,0x0000000000000000,0x0000000000000000}}, {{0x000e16965a7b1dfa,0x0009afd6426762fc,0x000532ec13f2e53d,0x000fe4131e801ed5}, {0x000c86963e2f9e9e,0x000f46e5098aecc3,0x000faa2b47801a35,0x00043b6f3406c3d8}, {0x000b57971349f37b,0x0007d749ef39f4ad,0x0000000000000000,0x0000000000000000}}}, {{{0x000dcaceb126ca58,0x00046c5a73dec3f9,0x0000e0ffb30d8879,0x00026935e7e62831}, {0x000f5e074c83b841,0x0008b04291158a7d,0x000f72a08eaada21,0x000a40d05438fa20}, {0x00005e6ac9aa8c4a,0x000b92b755928484,0x0000000000000000,0x0000000000000000}}, {{0x00081326c74e90da,0x000cdbf1a037a879,0x0009887e29013ab2,0x000ffd6598bd3d86}, {0x0003b3c803a95fec,0x000e4c50722fd839,0x0004e70129b699c3,0x0000fa72cdd65e3c}, {0x0000ccbba65f24da,0x0008975325682f6c,0x0000000000000001,0x0000000000000000}}}, {{{0x0008d8231d21b98b,0x000f46eede07ff72,0x000c57dc8bc52ba3,0x00096a93bbd28782}, {0x000609e0a7a0e49d,0x0009fbe4aa495765,0x0004c5f79dbfb8ae,0x0005e1789960cccb}, {0x000b74da3d25ebfd,0x000c2e56df642b09,0x0000000000000001,0x0000000000000000}}, {{0x0007057a2be83a30,0x00026ba759ce4dd1,0x00057744ef0ab9d2,0x000c9ee2b7115a63}, {0x00000d77f24c2ddd,0x000142ea1adfee89,0x0000f3fa9d5346a2,0x0007a84ecd7e6d50}, {0x00035caeb7a1527e,0x000c8110e6262dae,0x0000000000000001,0x0000000000000000}}}, {{{0x000457989aea7c3e,0x000a16bd6196a6cd,0x0006f76c2cbdd85c,0x0005840dcfd847e9}, {0x000ec8ea001b3aa2,0x000898be24444e27,0x000397d8a0c53dda,0x0003fa5f98a5b3e4}, {0x0008e197364ea986,0x000bbd922c6bbfbe,0x0000000000000000,0x0000000000000000}}, {{0x00064b7db5084e37,0x0008c954735a1906,0x0007371d65a99056,0x000bdaf052b4c902}, {0x0009ec2cc9668600,0x000adac668469729,0x0002f7ceb4949cfb,0x0001eda14ca03327}, {0x0009270923989fbe,0x0002a80f1714c9d9,0x0000000000000001,0x0000000000000000}}}, {{{0x000da9fadd2d2e35,0x000ebe39d9c06e00,0x0007878b1c269b9b,0x00045c0350e16aa4}, {0x000d604f7fb31a05,0x000233dc435d57a4,0x0004a59629977c5d,0x000caa747e5387e5}, {0x0006980680cca577,0x000c7f3aa2473480,0x0000000000000000,0x0000000000000000}}, {{0x0006ecf72ff177c1,0x000ea087d84398f4,0x000f8e3dbad5b5e3,0x000793b7c29bdf29}, {0x000d48b4ad4a2c86,0x0004cf9d25337e0d,0x000be01c858ea723,0x000fe90a676bb282}, {0x000306f507590c7b,0x000915155053c47d,0x0000000000000001,0x0000000000000000}}}, {{{0x000311b42bb970cd,0x00056fa08e6727fa,0x0006285b2f7609fc,0x000807c307ce1a3e}, {0x000d8c9c1df6de94,0x00070b979619a317,0x000fdde052a3379d,0x000baa7d20b3870e}, {0x0006e443d8f7406d,0x000355511beafebb,0x0000000000000000,0x0000000000000000}}, {{0x0002e82c90634dd6,0x0002249d51e499d6,0x000615ca9d89995a,0x00097ac7d99162d9}, {0x0009551034000ab8,0x00070ca9d924f35e,0x000b526853be7dfb,0x000638dc8c8aff11}, {0x00031fb01463b8a6,0x0004e7b55e740433,0x0000000000000000,0x0000000000000000}}}, {{{0x0008d4f13a03485a,0x0004c5dd3ccf1850,0x000d8ab1776f2552,0x000a54a5e0bf0c9e}, {0x000e81226e24a017,0x0000e5b1ecb9626b,0x0006acb8b7b3bc5b,0x000414da0130f24c}, {0x000b2f1d94673605,0x0003ae73af8b9c7d,0x0000000000000001,0x0000000000000000}}, {{0x0001a4baf806025a,0x00068cf7b99ef6b1,0x000b70549901e9bb,0x000cc5d4a5ca0071}, {0x000b555009f7be57,0x0008dbaab6501aba,0x0005c582d17b21b0,0x000d9921c7bacde3}, {0x00013fb4b9991c48,0x000d72c6f664c93f,0x0000000000000000,0x0000000000000000}}} }, {/* digit=11 [{1,2,3,..,}]*([2^44]*G) */ {{{0x00000e09c15f3e5c,0x000f97f45b409fb9,0x000ff4a01087837b,0x000d204b2bcafcbc}, {0x0000a0da165ec6b8,0x00011716978423a6,0x000f2f7f8295351b,0x00081f58e2d13eb1}, {0x000ed84592b66922,0x00025f5f9819aebb,0x0000000000000001,0x0000000000000000}}, {{0x0007ea077d668278,0x000b9653ee2ff77b,0x00098e8334b5b359,0x0005210487baabe1}, {0x0001a95a5886c85a,0x00009649f4c23788,0x00056127f95c6f68,0x000aed6c6419d339}, {0x000be49aa657d29f,0x000da67ae0b376a5,0x0000000000000001,0x0000000000000000}}}, {{{0x000fb32bacbbde73,0x0004f08a721e3545,0x000584020b45c467,0x000fd3a284a774fc}, {0x00004477afffeada,0x0006a2c4ec266e10,0x00066dc326c6652d,0x00070b3a65b94280}, {0x00055b8104c7d5c7,0x000d8c4b6af237e3,0x0000000000000000,0x0000000000000000}}, {{0x0000b97b7ca1cffd,0x000435de1358221c,0x000876cab38cc7ac,0x00054cdc8f30b09e}, {0x0000ccb3a4f5aec6,0x0002ac30ca26a9da,0x00011038e2a6fa3b,0x0004545c20a577ee}, {0x000bff8e2f50fb14,0x00093158359a6d97,0x0000000000000000,0x0000000000000000}}}, {{{0x000b8fa7bdc8384d,0x000f2859e636e718,0x000ed301cc9c465c,0x000006a5b105b2b7}, {0x0007075698827d1b,0x000fbe7e34565b30,0x0006110c56ecfa0a,0x000be3136324ecec}, {0x000a684fbfe59f06,0x00056bc39bf313cf,0x0000000000000001,0x0000000000000000}}, {{0x0008543e894e8a16,0x0006d339681c386b,0x0001fc0aac97005d,0x000c6eaa38aa9f79}, {0x000a90d6089956c5,0x0005ec33374fdc05,0x0007a4eaa1631484,0x0008df64f8ad9e1c}, {0x0007f44336b984af,0x000859e7ad53b8dd,0x0000000000000000,0x0000000000000000}}}, {{{0x000c8ba9ccf89d24,0x000874ddf8d1b9b2,0x00027291ffd7f24e,0x0008bd9d563287c7}, {0x00065d01bdb48d02,0x0001b99b973b0c12,0x000050d618319b97,0x00038420d531f686}, {0x000d7c201c411c3a,0x000d97468eb84cae,0x0000000000000000,0x0000000000000000}}, {{0x000eb2fc05bf609a,0x00073e1dab9da1f6,0x00049847c3ac275b,0x0007880554d322f9}, {0x000fedd0cd2b7f05,0x00085bb3e74958ea,0x000fcd8d9061a481,0x0006f9ac370d5c6d}, {0x0004cb188a021786,0x00057aa132c3b5f5,0x0000000000000000,0x0000000000000000}}}, {{{0x000a082d83368da6,0x0009c04ba3a92f9d,0x00018e366fb4a189,0x000dca28f8a4aa8f}, {0x0008c98efdf41b12,0x000e7f6ce11df724,0x0003850179926b22,0x000c0fa0bae8aa29}, {0x0007fa3acc87191b,0x0008222f18a88f29,0x0000000000000001,0x0000000000000000}}, {{0x0009dda00370c8d5,0x000720c0497d2a02,0x000cdb5a6b3dc411,0x00032f0daa73c7c9}, {0x000505d3784e14b1,0x000d7b77b06edb5d,0x000c1f94b45f2c9d,0x0003193f38ea4c8e}, {0x0001706f6af3bbf0,0x000f0df22ed99a0b,0x0000000000000001,0x0000000000000000}}}, {{{0x00097825d9e0b2bb,0x00096d1340276af1,0x000d82fe6324bbcc,0x0000475ecad6233b}, {0x0009a0cd8d04ac29,0x000e8e067d738cce,0x0004317aa038ad08,0x0009a7ce55aad83e}, {0x0006a1887d5e91f4,0x000a135efeae9285,0x0000000000000001,0x0000000000000000}}, {{0x000fa0b6a035b085,0x0005853d153ead9b,0x000ca7f6fb4ef7bc,0x000bfbb30b798e2a}, {0x0006653595cf1f8a,0x000774e7d1791820,0x00048df862d39281,0x0002db1e40868b45}, {0x000153b336e38fc5,0x00052ce2e4b80e72,0x0000000000000001,0x0000000000000000}}}, {{{0x000306c918831eac,0x000de7b8556b1913,0x000c579621fb2237,0x0001fa1088e011f5}, {0x0007511558db4265,0x000c63131310e896,0x00029cec356a91fc,0x0004b85a2f85b7d1}, {0x0006bc4404e3b5cc,0x000ac5c4fcc3a6fc,0x0000000000000001,0x0000000000000000}}, {{0x000498b1e054105b,0x000818b7c971dcbb,0x0006cf66f8ee2eea,0x000fa05b49db517f}, {0x00012073a35daeb3,0x000d5bb674f202b9,0x00032d411842792d,0x00076cdcc487632e}, {0x0006568c96ca8dd3,0x000ecdfe1c986f51,0x0000000000000000,0x0000000000000000}}}, {{{0x000595043dc23233,0x0008d9e1b752f3f5,0x000f6e2b3641b931,0x00064e0f5c02bb70}, {0x000169d8f287038d,0x00062f3a1b075424,0x00001bf3b8c6755a,0x000a2b642127d597}, {0x000c17f0c20fbe8b,0x0005263410177dfa,0x0000000000000000,0x0000000000000000}}, {{0x00008cc560c65efb,0x000ef6706807502b,0x0007a1e8980e532c,0x0007963729a4a8b8}, {0x0007ccb3a4f193b6,0x0002e07ae80043db,0x0005be0346fea839,0x0009ef33f7a00da3}, {0x0001ea778cb41f4e,0x00096ebb760e7727,0x0000000000000001,0x0000000000000000}}} }, {/* digit=12 [{1,2,3,..,}]*([2^48]*G) */ {{{0x0009ba658c1f9460,0x000b18b48e1df3f7,0x0005fc03a103eb15,0x0001ad263bed592a}, {0x0000a127b78a3359,0x0000337c7b07e9d8,0x000d2a0349dd74fc,0x0003b1a807c5364e}, {0x000d92cca588d420,0x000d9e772a1716ec,0x0000000000000001,0x0000000000000000}}, {{0x000fc1df3f66f295,0x00015742d25980f6,0x00036f0fdb08922f,0x0001fe47a583206a}, {0x00001c73f88168cc,0x0001b777671d2798,0x00068317ac8979ce,0x0002a98b48363dba}, {0x000f36b7460d4015,0x000da1c3d46c62c7,0x0000000000000001,0x0000000000000000}}}, {{{0x0001fb046e7fab2a,0x0000e190213473d6,0x000cbb6e9b84f9db,0x0008fb8a36fcff78}, {0x000c47cd5e9d16aa,0x000c2601e9337a00,0x000713efe8445d72,0x00030681fd15bbab}, {0x00051cff90b2dd23,0x00024900ab444b21,0x0000000000000000,0x0000000000000000}}, {{0x000de9a880ca8289,0x000e3bcb8ede5206,0x000e1369e32209ab,0x00036516b711e224}, {0x00025533569db531,0x000419656e59d965,0x000ee21f2d680255,0x0001d59bb004326e}, {0x000bb722c073cca7,0x000866aa784f931c,0x0000000000000001,0x0000000000000000}}}, {{{0x000d262bb3ca8da3,0x00045288c7563397,0x000d10c59451797d,0x0004e594575ac7f4}, {0x000311006db0bd6b,0x0004d6485bec56e6,0x00089e23442953a9,0x000610efbe7ae598}, {0x000f1a0f166d5639,0x0004e5f91e0ed7d5,0x0000000000000001,0x0000000000000000}}, {{0x000aca95d51d383f,0x0000d23ae1d67e17,0x0001b867b62738a3,0x000907e6a529f72f}, {0x00059335e44e6986,0x0001d5fbd59c1e58,0x00018393e6789776,0x000e5bc878acd1b0}, {0x00059b26328cd9f3,0x000f3d83306eef44,0x0000000000000000,0x0000000000000000}}}, {{{0x0009313593b1d240,0x0003b3672b4b0a51,0x00078ea42e614acc,0x000784cd22fe0a9a}, {0x000a6c20faf43e72,0x000e49f3038f9c3e,0x000fb914c50987c5,0x00000c76e9b912d1}, {0x000dc2b7b96a89b9,0x0008de238b29a074,0x0000000000000000,0x0000000000000000}}, {{0x00068ea377031f72,0x000e9606adb168ca,0x000e58dde885ecba,0x000177424d422e92}, {0x0008aa609937ceba,0x000f30fc81145199,0x000c9f99eba807b8,0x000e200db6e7a724}, {0x000db2dc7651c126,0x00009cb58e38f0c9,0x0000000000000001,0x0000000000000000}}}, {{{0x0002dda36b654cc9,0x0008acdfcec83248,0x000164e7c3c6f06e,0x000ff27341f98b3f}, {0x000b145595e7208c,0x000f8fbf6e4d7416,0x000a519d6e691f26,0x00082c10e5fd7be7}, {0x000b1af42c760524,0x000f36238c97dbcb,0x0000000000000000,0x0000000000000000}}, {{0x000a3b8e5e8a7251,0x0006fabc0a713664,0x0004fe41fe20cb31,0x0004067dc2b00d32}, {0x0004fa30d7f12a4e,0x0003f79c759905ca,0x000ef9b323da1724,0x000357ea84efa0af}, {0x00083350488b839e,0x000408f03e5cf22c,0x0000000000000001,0x0000000000000000}}}, {{{0x000e616991835801,0x00028f75d4e1a857,0x00031b04bb8869ad,0x000fb7737091410d}, {0x000cdd4fad2e164a,0x0004c7cf900934ac,0x0009b433f8948c75,0x00028687541974f6}, {0x0008f0af013f8d2a,0x0000b59eac62d398,0x0000000000000000,0x0000000000000000}}, {{0x0000c23b25d034e1,0x0007d927e7c611fb,0x0007596a05e54d05,0x000f8995596eb4b3}, {0x0005b26be4690555,0x000ae1277dbebe99,0x0006bc99c064aa3f,0x0001128fda3fad13}, {0x000cd244392bf3eb,0x000a481bf8fac406,0x0000000000000001,0x0000000000000000}}}, {{{0x000d8f6c1e9aa431,0x000e3d32dbe1679d,0x0006391e1828c205,0x00026f450a2821e3}, {0x000a00cf3fc9e32a,0x000a2fc5a7a744f6,0x0006b70facb792c6,0x000e8edf92ab0b29}, {0x000d53faf8f11ba4,0x000b1e87f01ff5b4,0x0000000000000000,0x0000000000000000}}, {{0x000e6fdf30e29338,0x00014840cefab311,0x000c4e092d034ea0,0x000be36bee8c5b8d}, {0x0001f39e2788cf85,0x0008f32c467a702e,0x0005e353cc3b7917,0x000f137377576e06}, {0x0000db55d1c5fcce,0x000d16e9cd523a0e,0x0000000000000001,0x0000000000000000}}}, {{{0x000e8870b81dfb8c,0x0006908ea654a671,0x000c3eb3660a23dd,0x000daf70673dbdf6}, {0x000c19bbf5d38a5d,0x000fe1371d1e7af5,0x000e30bcc1eff610,0x000f1308bdd31572}, {0x0000db70b20ce33c,0x000e036ab6b3edc6,0x0000000000000000,0x0000000000000000}}, {{0x000357b86d4f22a6,0x000b893ce6e16bae,0x000a3849b8d94e06,0x000e1675b6058ad8}, {0x000ed6add0f99ace,0x0003cd380c39df12,0x000e2335c645ff14,0x000994a0f6180481}, {0x0005a52a4c84b4bf,0x000e9849a710f480,0x0000000000000000,0x0000000000000000}}} }, {/* digit=13 [{1,2,3,..,}]*([2^52]*G) */ {{{0x0002ea2996fba378,0x000cf933ae1a32c4,0x000b43b79b9d0dda,0x0002636c30561bd9}, {0x000f9122413700ad,0x0005a779a0d830de,0x000580fda5f65618,0x00067e785d8628b8}, {0x000ce8b188bafa8c,0x0006d2c75df63d48,0x0000000000000001,0x0000000000000000}}, {{0x00090afd2d7e01b7,0x000e57c72b304c5a,0x00040d7dec21b4b2,0x00094cfde0f45d07}, {0x00010aabbfa713eb,0x0007fa8b4fae1b3f,0x00047d2b080d24d3,0x0001142abdb36f64}, {0x000470df72045350,0x00047e76e433f8fd,0x0000000000000001,0x0000000000000000}}}, {{{0x000081cbd682dd91,0x000d2c1433b543ad,0x00094641d2488d8c,0x00036e702da0394f}, {0x0008248288ca4d8e,0x000112c8a6461fe7,0x0004a486f063613a,0x000f77efb66bb862}, {0x0006e8d41511d90f,0x0009a1ce80969401,0x0000000000000000,0x0000000000000000}}, {{0x000feced91fc3935,0x0002e83ecdac7136,0x000ee8e2857921f4,0x000ef9bbe82b293d}, {0x000bd182b25ab2c3,0x00097ad819ac32f4,0x000916b74b598de2,0x0004d5e666a5dd15}, {0x0007be0b151456a2,0x000b794dc25c5c44,0x0000000000000000,0x0000000000000000}}}, {{{0x00087c377c23c5aa,0x000d33ca314119f6,0x0002512d0943eacf,0x000f9fd69c0e1850}, {0x000b7c3c6ea7ee55,0x0006291556c20685,0x00053374868b07c6,0x0009f9f339d7b589}, {0x000d6855b9238a10,0x000491ac6af37f75,0x0000000000000000,0x0000000000000000}}, {{0x000b5d5b2f49812c,0x000855e7603bff6e,0x0008f73b087f7552,0x0005c0adc19b7320}, {0x000d355df5442e8f,0x000a4b8876b6aeab,0x000a7378dc2b22b3,0x000c26f89265f8bc}, {0x0006645f23dbb040,0x000f38b09ab1bbfb,0x0000000000000001,0x0000000000000000}}}, {{{0x00011ca0d8fcc245,0x0008ea92267e1494,0x000bbfcc2abb385c,0x00029656bfd56d29}, {0x000075f2180a734b,0x000dc3400006f728,0x000f754023104376,0x00021bae73e6854a}, {0x000a8d2ddbc75324,0x0003d711770a3406,0x0000000000000001,0x0000000000000000}}, {{0x000476594b8d6365,0x000aedeb8cb49714,0x000c86324ad6ba99,0x00016428c49863ca}, {0x0002a2e5cfc3d8a3,0x0009adc3e0cb62d8,0x000eff79e5f3fda7,0x000eb4f990b6cadd}, {0x000b0e410ae15a98,0x00000aedf394c7b9,0x0000000000000001,0x0000000000000000}}}, {{{0x00021de1984e2e65,0x000603254887ed1d,0x00087e7535512fa1,0x0006f4ddde7dd7d2}, {0x000fd9cd7f2faac0,0x00009274ea570744,0x000b8cb9c92e3b10,0x000294aa3ad7752d}, {0x0001e25f444d43f5,0x000d6a378f2a4af0,0x0000000000000000,0x0000000000000000}}, {{0x00007294901179cf,0x000fc01f2357da9c,0x0003c6543ad3aafc,0x0004db8aa97c6078}, {0x000dd86b1f882854,0x000e842c5d55c6a1,0x000e30c9aff1c67b,0x000d71107c0af546}, {0x00097038444a87de,0x000d8c2bb6354272,0x0000000000000001,0x0000000000000000}}}, {{{0x00086f90f323a729,0x00082963dacbf625,0x0004056ab9d5b07c,0x0001d30212e37a0e}, {0x00065da9a3d1070f,0x000445a33677e429,0x000c39a6aee3c700,0x0006b968d6cd0279}, {0x00098776415f9a3e,0x0007bd59dc1684b7,0x0000000000000000,0x0000000000000000}}, {{0x0005cafc1fb833a8,0x000b18657b2cb0ad,0x000af58b0bf123c6,0x000acc1e7ceb4334}, {0x000e5575f0e10ca6,0x000d22916c7bc194,0x00097f735880fd80,0x000604a86980d5b3}, {0x0002f218f0f8d8fa,0x0000806dbeec3ed6,0x0000000000000000,0x0000000000000000}}}, {{{0x000b6c1669c31b94,0x000b37bb5eb33b20,0x000f2f86abcd3194,0x000093b3893ef395}, {0x000d0b48537fd7dc,0x0006863b5109af48,0x000cb076c2fca9e7,0x000fc785f088e6f5}, {0x000c88facfd552fb,0x0001054316685a3b,0x0000000000000001,0x0000000000000000}}, {{0x000b6af5d1972479,0x000ccf45d30e213b,0x000db2b3881288b7,0x0008f7bff9008ba2}, {0x000607009e5be8cf,0x000e10b176da0a78,0x000522cf433a33d0,0x000090924737e4d8}, {0x000cc0a11c296771,0x0001fd3715d11b75,0x0000000000000001,0x0000000000000000}}}, {{{0x000c391c2f2938b1,0x0006b396d1c5f420,0x0006bb17f5eeaef7,0x0006a57b7feb16a1}, {0x00026cc8015523f1,0x000ded6e6d4aadf1,0x000f602e23393c9c,0x000e2c8dbcb36848}, {0x00011e23c49f3a9a,0x000730c0c1ebfaf8,0x0000000000000000,0x0000000000000000}}, {{0x0001b88cdd5da561,0x0002fcb4c22029af,0x0009624d6d5aa7f2,0x000db935bb120735}, {0x00019a8308449416,0x000467f9f185fd32,0x00057d8b4d3e00fc,0x000e187052a8a69d}, {0x0009e66380528c91,0x0007a42a603bc9b7,0x0000000000000001,0x0000000000000000}}} }, {/* digit=14 [{1,2,3,..,}]*([2^56]*G) */ {{{0x00026efe1474fe09,0x00029da3ad38a0ca,0x000ec34abeaf5cd5,0x000847ac94808b1e}, {0x0001587ade96127c,0x000a43fa8cfa6df2,0x000bb39bcfdb5ad6,0x0005dd4d0c9f947f}, {0x000772a4ebca687c,0x0009227d79e215e8,0x0000000000000000,0x0000000000000000}}, {{0x000926e1c81cb032,0x000ffdb04fbc5abf,0x00034707ba5b9c12,0x000a347c4ee8c89b}, {0x00072367a152d81a,0x0004511a3a4cd565,0x000b8f1a66429397,0x000260ea13e9d0e3}, {0x000a19a28ee14ab4,0x000d5dea76ba4c81,0x0000000000000001,0x0000000000000000}}}, {{{0x000f1e1b3fe2f1a3,0x0006da87421ab9af,0x000a3305ebdbbfcc,0x000cb7784b75a8e1}, {0x0006a4410056f8f4,0x000ff65612b5abdc,0x0004b1cd83f32f54,0x000fb989d25121c4}, {0x00014abed80a7bb1,0x0005ba8f200e1152,0x0000000000000001,0x0000000000000000}}, {{0x000fb8525d63a07f,0x0002a4f5f23c02f4,0x000405911d9aa8e0,0x000dae0345abb8b1}, {0x0007b4834d14e7a6,0x000b31fdc5462195,0x0005dca7cbf9b75e,0x0001ee84304e26ee}, {0x0006a2c7d37349cc,0x000fc85a34c3afcc,0x0000000000000001,0x0000000000000000}}}, {{{0x000cefac8c58a5d9,0x000939b188506808,0x0005985dd6ee8422,0x00094a64ab14cf0e}, {0x0001ac27af983cda,0x00024f6eafd12785,0x00025d8bab20f8ff,0x0004a549d9c6da3b}, {0x000f18f37ed810bd,0x000655f630e4c95b,0x0000000000000000,0x0000000000000000}}, {{0x00018594e51ad76d,0x000d8952697460ae,0x000aec56660f8de9,0x00093a39294777cd}, {0x000bdf7dc98fde3a,0x0000c53dc363fcc0,0x00091985d2c2708c,0x00093692d05055da}, {0x000c4d312ebcde24,0x0000c18d0017f5cd,0x0000000000000000,0x0000000000000000}}}, {{{0x000a3f86e5f8496f,0x0007f32df7ec8ea1,0x000d8551991f1f8f,0x0000f4eeb16ec397}, {0x000f5ebe5be1abc8,0x000f8233b8a1e6cb,0x00037675c403702a,0x000cbf97ecb04148}, {0x0006555682899a5c,0x0000280720d39958,0x0000000000000000,0x0000000000000000}}, {{0x000312054dc27af9,0x00074dd550df7288,0x000193eb1e2f87e2,0x00073656a715c43f}, {0x0006ecb67dce2977,0x000aacb5db8a585c,0x000d92a6332fcd10,0x000cdeebccba4f16}, {0x00036c8da2b8001a,0x0007817b62765789,0x0000000000000000,0x0000000000000000}}}, {{{0x0002d6d084e03d59,0x000c244d84ecf179,0x000c93fa7f1e0110,0x000f695cc72b1bb4}, {0x000921730f1b2908,0x000b0b36b38d0bc6,0x00029c0e4bf469cd,0x000c1d41428da1db}, {0x000d1253d7a577f2,0x00006a23b655222c,0x0000000000000000,0x0000000000000000}}, {{0x000ba5fbd7ebe31e,0x0005209808ec8aa4,0x00049718327a5383,0x000bb2492c210a5f}, {0x0002eef53e1dbdc5,0x0009d3c1717e38e0,0x000d4877b41e983c,0x00012d8aedea3a07}, {0x0007e058b6c0e3ba,0x000fd022c8be6da1,0x0000000000000001,0x0000000000000000}}}, {{{0x000870ab98aeb123,0x000044a353002cf5,0x0006150f34fa12da,0x0006eea20086b83e}, {0x000a0a2cdf13169e,0x00028616b25e80e0,0x000c5982d13e0cc5,0x00019702e01a4a67}, {0x000b60ef183d6e66,0x000a1f6f9172f815,0x0000000000000001,0x0000000000000000}}, {{0x0002b57766386476,0x0001a0e6acc5477b,0x000ba422b2405581,0x00090991a9873020}, {0x00045310acf2c8c9,0x0008701ea796459d,0x0008c83917c30ec7,0x0009db51be44d168}, {0x000514c3bb42ce9e,0x00048d0b03fd870b,0x0000000000000001,0x0000000000000000}}}, {{{0x0007edbd640c9bb6,0x0001c6f483d72a01,0x00058a225c5b0849,0x000e8697568a7e71}, {0x00022821bf73d7fd,0x000c765e3aef4bc0,0x0001d2e8d1daf2fe,0x000772d486e7b59a}, {0x000595f951edfc03,0x000ffff1683f882a,0x0000000000000000,0x0000000000000000}}, {{0x000fc53814c4cc13,0x00014196f30cc555,0x00076a3af64c6ce2,0x0009bfff339f5668}, {0x000ffe438adb5544,0x000aa59ae8f3c48d,0x0006c57ce59b5441,0x000eb7bdc7b7c0fd}, {0x0003b8e1d8e51d10,0x000d6a6427d57897,0x0000000000000001,0x0000000000000000}}}, {{{0x00005519264c8b35,0x00066ff272a08c1d,0x000142d545c343f7,0x000ef117b8bd86e9}, {0x0001c60c69c66860,0x000b54e53cb6de93,0x0000c9b9924f2f51,0x00030b949095878c}, {0x00016f5f1fba7e2a,0x0005817da79c3a69,0x0000000000000000,0x0000000000000000}}, {{0x0006ad6babd55997,0x000be6d551de11e0,0x0006c45d4c33b3cb,0x0009e3dfcc4aa553}, {0x000821bb5c238e3c,0x000dfc012d05a1e3,0x000650684d8d4638,0x000805b7e2413b85}, {0x000718949cdcfd8e,0x0002efc1a85e6627,0x0000000000000001,0x0000000000000000}}} }, {/* digit=15 [{1,2,3,..,}]*([2^60]*G) */ {{{0x000f6a9bd09d8e58,0x00004bdca0a6cc0a,0x000d9e6d336fe5f9,0x000c9d8bd87d0339}, {0x0003f4d463bab3b8,0x000203e46dfb629c,0x0000ef34ea62ed4c,0x000564035458998a}, {0x00069592c6278328,0x00081b3c56ebb377,0x0000000000000001,0x0000000000000000}}, {{0x0009a17aab96cc87,0x000f8ed51ce44125,0x000c62b1c658666d,0x000b6999437c7966}, {0x0008f0fecb36474d,0x000f725b1f7c6099,0x000396c71fdafc21,0x0006a547fb5a5b56}, {0x000566ae79d88868,0x0000f4130033ff0f,0x0000000000000000,0x0000000000000000}}}, {{{0x000a6c73f41a4fd1,0x000bf46616431912,0x0009c6ffbd2fe4c8,0x0009e4fd42f313ec}, {0x000b9f8b100ba286,0x000e18229bbae712,0x000550161a1f1da0,0x0000032c80f2ffe5}, {0x000f0b1d53bfaa0e,0x00035fb83c760748,0x0000000000000000,0x0000000000000000}}, {{0x000ed33353cf7a1f,0x00075b8b3c031fa0,0x00053c30e33c1415,0x000945a8fa62217c}, {0x000aa8b667de4f9f,0x000c4952fb889399,0x000b6e3b711abc77,0x000959e7e12fabed}, {0x00057ebfe5a1b2cb,0x0005344206e24318,0x0000000000000001,0x0000000000000000}}}, {{{0x0005f9c5a301de7d,0x000b800d937115a9,0x0004b1412c82ee0e,0x00039cf3df5a5904}, {0x00016cd50327ee6f,0x000841dfd19a796b,0x0005d79c493ac5c0,0x00097275eb2319d1}, {0x0003b6feb4b9d447,0x000542e1eb10df1a,0x0000000000000000,0x0000000000000000}}, {{0x00051bac56d17f38,0x0007837a907c7875,0x00082e7d67e232dc,0x000c3c225acaf222}, {0x00056e17100c95eb,0x000198b234622502,0x0006b8a4beb3ba23,0x0005492d30351698}, {0x000c0dd28973e413,0x00031b2e1155d6fc,0x0000000000000001,0x0000000000000000}}}, {{{0x00014d7bc4df6981,0x000c45e951da151f,0x0003964143f3d397,0x00056c9c24be6549}, {0x0000ae1293e252e5,0x000bfda40e3aed33,0x000e72cdf82159a4,0x000f514f7b173b13}, {0x0000684bfa5b859f,0x000fce90812f67e2,0x0000000000000001,0x0000000000000000}}, {{0x000a9abf7e9a0c25,0x000a823b0b3a0fbc,0x00011d2709072194,0x000b7a7f17f5564f}, {0x0007987f0af999bb,0x0009d6201796c014,0x000d35c45cce25a6,0x0009265843370c43}, {0x000a55401cbff6e8,0x0000eab503e2ea19,0x0000000000000001,0x0000000000000000}}}, {{{0x000caabc4b5cd512,0x00034cdeccde50ae,0x000395d24049ffdf,0x0005918925068e1b}, {0x0003f93fb9ea4405,0x000a60ba95d141ad,0x0005981c42f76f02,0x0005946bf800414a}, {0x000435023138c47b,0x000f3cf314147e38,0x0000000000000001,0x0000000000000000}}, {{0x0008bdcc69ae19e3,0x000ac73cebd917e3,0x000c35337880966b,0x000e6ede2718c3e8}, {0x000fd10236ae833e,0x0004797bb14f5b88,0x0001296485e76bd4,0x000a68194c12b2b3}, {0x000b75dc1e45112b,0x000dd88574000b0c,0x0000000000000001,0x0000000000000000}}}, {{{0x00037d315eea24bc,0x000160f77a65b38f,0x000de27962237731,0x000bd3346f06ae65}, {0x0007a25b38b1587e,0x00055c6b9f2a1d2c,0x0002f34b1687394a,0x00054f27c66a0ccf}, {0x000866c84ecf3de7,0x000b4da4a0f4aaa9,0x0000000000000001,0x0000000000000000}}, {{0x00066dd8b8dffeb8,0x000121bfeaeff003,0x000a80b5c3bfe941,0x0005b6a4c3fed2fa}, {0x000c623dfdf4718a,0x000b0791d22ef007,0x000949ccec61c6bd,0x0006e328d9cc6d79}, {0x00014a1530d03e69,0x000d45fdb36710aa,0x0000000000000000,0x0000000000000000}}}, {{{0x0006dcfa61a8d3cd,0x000ff977e2649373,0x000089ee4ac6af49,0x000b86d61720bd71}, {0x0007848d2c5df2f3,0x00078e07afbcc66a,0x0007ceb1f230a9ed,0x0000d2f61bf5077a}, {0x000770c3ffbf99e7,0x0001487ae5f08492,0x0000000000000000,0x0000000000000000}}, {{0x000ee44c464c2996,0x000d8f990f4f03a6,0x000453774274aacb,0x0005c8730ef447b6}, {0x000e5e02e661f55b,0x0009f13f1011e65a,0x000f4c8fe17d3ed9,0x0000dbeb35dd393c}, {0x000a7d1cd2327711,0x0003fb444802cd65,0x0000000000000000,0x0000000000000000}}}, {{{0x00071a842f621fd7,0x0008594c057a1dea,0x000e1689c80fc8fb,0x00022f52adc9a8e1}, {0x00099c47b816309c,0x0000c495f00a960c,0x0002e200a0f356d9,0x000a87494b798824}, {0x000dcd587b7f9ca6,0x0009c4d76d2c396f,0x0000000000000000,0x0000000000000000}}, {{0x00035970dd6ecf15,0x000449aee47a261e,0x000adfd394c8df13,0x000dfbec67553f2c}, {0x000aca43c615471c,0x000606556ef09db2,0x000a225f2e040114,0x00099dfb28da12ec}, {0x000812bc587a4c83,0x0001ab8cba898428,0x0000000000000001,0x0000000000000000}}} }, {/* digit=16 [{1,2,3,..,}]*([2^64]*G) */ {{{0x0006146954276a1b,0x0000c171344edf1e,0x000b30130812b4a5,0x000314a14896c770}, {0x000e796a686592cf,0x00079226d890053f,0x000869a5847ac79d,0x000cf60993a83ada}, {0x000e4b5fe7d156a5,0x000add7850cdf667,0x0000000000000001,0x0000000000000000}}, {{0x0005bcbb35fb3dea,0x0000a34e2d6021f3,0x00090be93989877f,0x000303404d6435bb}, {0x00007e5919257861,0x000c99d1992710c0,0x0001c7987d3586cc,0x0008e8681c58c145}, {0x00059a487fa896da,0x0009a8b1a9e54366,0x0000000000000000,0x0000000000000000}}}, {{{0x00029533273f3ddc,0x0009580b259ba7fa,0x000a4092fea94f8c,0x000efd38be9d56f6}, {0x000720f2ba425622,0x0007c0adb2a4d25a,0x00018752498a9ea5,0x000d893bbb4d11f1}, {0x00056b02f195ec41,0x000bca2ad72c4b2f,0x0000000000000000,0x0000000000000000}}, {{0x000a4013f1ab7060,0x000f17521f983a0f,0x0005292b2f1ebae7,0x00075002debce289}, {0x00003b6cd203ad6d,0x000c3592c993bfe5,0x0005400a40b351b3,0x000e9b6bafed180f}, {0x000d6a9f0291283a,0x000563036cf95dd4,0x0000000000000001,0x0000000000000000}}}, {{{0x000efa3e474a5b75,0x000e5a6d55141813,0x00008a31bd3435d9,0x0006a68b3c599425}, {0x000252817b3af9bc,0x0006a695a37f35e7,0x000f06836ac1d6b0,0x000b19a92f525bb2}, {0x000215d9b8e544be,0x00080723f1554fe6,0x0000000000000000,0x0000000000000000}}, {{0x000e709e6109d280,0x000e367fd7bcb2f8,0x000be531b1c6fe21,0x0002d1fc5388b64a}, {0x000c169c0609b0df,0x000cd0fc3d5f664a,0x0003de00815f78ff,0x00049af9ff38956a}, {0x000e62c250aedb30,0x000af977c662b6e7,0x0000000000000001,0x0000000000000000}}}, {{{0x000cfa5a95db7680,0x000cc333878665a8,0x000809b2a4ba5401,0x0009594f6cdc3f0e}, {0x000e99bbfac6790d,0x000d836074d551d6,0x0009d9ae874e847f,0x000a264b3b0b13f8}, {0x0003ac51f7a6ec5f,0x00021d6dd250c60a,0x0000000000000000,0x0000000000000000}}, {{0x000e14abaa7747bd,0x000f127c3196cad1,0x00078a629241495e,0x000ded5d0cbcf8af}, {0x0005b83d56ec31f4,0x000c6ef029fa54b1,0x000cc516f0a12c6c,0x0000ce830e11ae62}, {0x000747fe9964fd2d,0x000c6756076a3288,0x0000000000000001,0x0000000000000000}}}, {{{0x000b9a69b333564c,0x000cec5ad994fbe9,0x00091ab4f5d4d95d,0x0004dbde503f2b0d}, {0x0003c8b32fed7498,0x0009fa10339bf799,0x000b1e6b4c7bd908,0x0001c54e64a99794}, {0x000598ef7979d915,0x000f29a322ae1bc8,0x0000000000000000,0x0000000000000000}}, {{0x00042520c237fcf4,0x000303a14c0e24d4,0x000f7ed62c67df4c,0x000ee5dfd3635dff}, {0x00097bcf94654c63,0x000eb529e2ea1f28,0x000969c7cff702bb,0x0003bf0591306903}, {0x000474be25c3afe3,0x000d8f2570e7350c,0x0000000000000001,0x0000000000000000}}}, {{{0x0003d3d928f89c37,0x0004d9c668cfa4b7,0x00097ee2907da69c,0x000fb743bf4c3402}, {0x000cd4034c59cbf5,0x0009bc4b73d60ae9,0x0007664da82be729,0x0007e3800a84da1f}, {0x000700f12fb007b6,0x000882b546161eb7,0x0000000000000000,0x0000000000000000}}, {{0x000e150bbd0f66b9,0x000122fc5d0def4b,0x0001ba0f43d660c9,0x0004e9263a5b4550}, {0x000ef33c24e5b722,0x000249e1b7ba92b4,0x000aa152b1856c8d,0x00095fe68108b2c9}, {0x000e766ae6e54017,0x000903a379f58c2f,0x0000000000000000,0x0000000000000000}}}, {{{0x000980153e2aed11,0x000ca0053853a90a,0x00003bf5f23c9661,0x0009061283e91bda}, {0x0006236d967ae1de,0x0004f3d80708ed52,0x000bb014e9c6763d,0x0002f3d82f09bad2}, {0x000f8d828de34c80,0x000187805c46ac1b,0x0000000000000001,0x0000000000000000}}, {{0x00086a0c8fd9feb0,0x000d468bed15d861,0x00036573dedab729,0x000d88e4dce7ee93}, {0x000d9e86caa8e75e,0x000c0d08d6110fe2,0x00082b709f0b0d08,0x000ab3fbb5af39b1}, {0x000c1b7910befecc,0x00062bf43fafb941,0x0000000000000000,0x0000000000000000}}}, {{{0x0005341f232f3278,0x000c66dff5ad0b4d,0x0006270a82ebb141,0x0002897d7912e413}, {0x0006b6b16ad87fc6,0x000fe7c18f348f2e,0x000a03bae57af6d0,0x000a6d2d6ab02f22}, {0x00017c3e7efa7a28,0x0009c673423958d7,0x0000000000000001,0x0000000000000000}}, {{0x0004f0f2ce49ed5e,0x00055b8c6c92190b,0x000aff1be7fa884b,0x0002c375de74b331}, {0x000f37a676c7d888,0x0001190b6b57c355,0x0009c95180dbbfa7,0x0001d7dc77b1599b}, {0x0007eba118f76648,0x0004aa840229ee22,0x0000000000000000,0x0000000000000000}}} }, {/* digit=17 [{1,2,3,..,}]*([2^68]*G) */ {{{0x000507b4b3de6fe0,0x0009064574b533f1,0x00076eaa707b56c3,0x0005e98aa9532376}, {0x00034611c9b6716e,0x000eb6a26112d9a9,0x0006e068430b4789,0x000e50fd96103fab}, {0x000509b62d215cdd,0x0000b7c4da786d1d,0x0000000000000001,0x0000000000000000}}, {{0x0002a0af86e4be0a,0x0008383ebf635e75,0x0009175f3f7680f5,0x000b999d9f1a0d87}, {0x0001f04cce1e2861,0x00086e6afd75ef23,0x0004476af7240e6e,0x0005e887f56c0473}, {0x00094ba352837e09,0x000f469e3dc524c1,0x0000000000000000,0x0000000000000000}}}, {{{0x000726e7d4a98265,0x000a397d1e874b3c,0x0008c78c755a513d,0x000fef1392677915}, {0x000e1e9e24f3ae62,0x00096cf6213d1cf9,0x00004b1f503d4fcd,0x0000f07e39bb0e12}, {0x000406c607195818,0x00046d3b7b9a617a,0x0000000000000000,0x0000000000000000}}, {{0x000b43a8c35ac9c8,0x000a92f37f3857cd,0x0008ae49b6bed377,0x0000e3380827d789}, {0x000e2deff6865bd5,0x000758e466fdb287,0x0001f3ba0c560a0e,0x000db418a2645432}, {0x000aa26f5d44767f,0x000d36cc7b7f8bfa,0x0000000000000000,0x0000000000000000}}}, {{{0x000020f87c5aeb2e,0x00035693c551e0d7,0x0004a7f0938f3f98,0x0008d4d829ae419e}, {0x000d8e42f19ee358,0x0004d94560e54e60,0x000ddb20bc96b546,0x00014bfcf64c2c92}, {0x000518fec9517e43,0x000a92773a95b0b8,0x0000000000000001,0x0000000000000000}}, {{0x000c159b5e61b250,0x00070c6538519060,0x000d0372c4dd1c2d,0x000fd8998866b5fd}, {0x000ceccabb79115b,0x0000eee1fb689260,0x000b839fc8378f05,0x000677dee33a7134}, {0x000b9326b080c62a,0x0003ae07e602129a,0x0000000000000001,0x0000000000000000}}}, {{{0x0000dde02f16a4fb,0x0001ca814d149b58,0x0003cc8c599eaa3b,0x000d833d43a45440}, {0x000afdba29de3c98,0x000b2ff2056e31f2,0x000ab3bf81e95cba,0x000649419f19b530}, {0x000585b648a6e1bb,0x000ff11dfbba1ed0,0x0000000000000001,0x0000000000000000}}, {{0x0004734696bc60cf,0x000199c0250d4a2b,0x000d4759758b9f4e,0x000f68bc326d4e2a}, {0x000cea78113abc32,0x000d248f92840b01,0x000d61ebd87644ac,0x000ae9a32d38a8d8}, {0x0000c706b58a69c2,0x000561f4b942e16a,0x0000000000000001,0x0000000000000000}}}, {{{0x0002fe7e20769488,0x000a1c068b87a199,0x00032a3459c496fa,0x000e96c391b8839f}, {0x0007f4914cec7211,0x00039756176c58a1,0x000aa63441905f9c,0x0008ea16377fb867}, {0x00042578ce2a2865,0x000cd140c73dd697,0x0000000000000001,0x0000000000000000}}, {{0x00074ef7ab059a14,0x00031e0f7d0f636a,0x000fea67e10b4430,0x0006ef5711a15a06}, {0x000f717856862153,0x0002513381cfd3a9,0x000a8b9906086974,0x000a08521bae079c}, {0x00052ef6a1d4b90c,0x0004f5ad24ad39a3,0x0000000000000001,0x0000000000000000}}}, {{{0x000c2d28a3a30e7c,0x000933949c694069,0x000d1f2a5ed527fa,0x000e2b5573d97d5c}, {0x0006aa892b500798,0x0008ac4418f1419e,0x0007bf2d1e227f12,0x000bc2143f4c8a62}, {0x000ae6ef99da3403,0x000679827f46143c,0x0000000000000001,0x0000000000000000}}, {{0x000a8cba49268935,0x00038ccee58ce9de,0x00061df0ac493218,0x00075eb49225f314}, {0x000073000d3eb206,0x000145d79e65edfa,0x00007b1990aba7cc,0x000c916353a37685}, {0x000854a40d94fba3,0x000cb2e109e1b50c,0x0000000000000001,0x0000000000000000}}}, {{{0x0000c263771f69c1,0x000d1595543d358f,0x000ef2e3d8a56184,0x0005866bc8c3965a}, {0x00021c100a7748c1,0x00029b46541a4ddf,0x000c5cb49ea744d6,0x0007a3a96b8b1fb0}, {0x0005aa7e85061bd2,0x000163e83c339e28,0x0000000000000000,0x0000000000000000}}, {{0x000102ac6923a672,0x0004153c3e1bd59a,0x0003473bcdaf9384,0x000f589da2a6c958}, {0x0003af0eb1a0311a,0x00041f50baac8d3b,0x000bd2c8728d9afa,0x000fc24b4e16e953}, {0x0003e6d4570ad37f,0x000aac57efaaa8de,0x0000000000000000,0x0000000000000000}}}, {{{0x0008c7fccb0a85bf,0x0003bdff198eec53,0x00029ee8af84ec04,0x000572ea125b846f}, {0x00025280cfc9ed01,0x000f73f2654ba803,0x000ffbf57e3b7be3,0x0004f83701a26bca}, {0x000d20a251a2d372,0x0003ec410f80b319,0x0000000000000001,0x0000000000000000}}, {{0x000961197dc0e519,0x0003d8c136f93b3b,0x000000ba8d6c2646,0x00084f848d99824e}, {0x0003fcfbb42b20e0,0x00038715f781fef3,0x000bdd048ed10781,0x000042869724ca7d}, {0x000de2c203c66b90,0x00090489fab2c4cf,0x0000000000000000,0x0000000000000000}}} }, {/* digit=18 [{1,2,3,..,}]*([2^72]*G) */ {{{0x00038bb0c7aa46ca,0x000d2cad2e37a158,0x00054d33ad65a28c,0x00004b20d4f1caa9}, {0x000b180e4c9d244b,0x00070a13f58c65ce,0x0008816ecff016c3,0x00016ad260aeee75}, {0x000dbb7b595c36fe,0x0002944d06dfe8bb,0x0000000000000000,0x0000000000000000}}, {{0x000c325d67839921,0x0006a5955c2a22f5,0x0001664092579a37,0x0003aac4f8e9390b}, {0x000722a8dbf2236b,0x0007b02d94034f2b,0x000fcd8d5de86b97,0x000fa8bc9f80729c}, {0x000bcbc03be296bc,0x000364ec1469f11d,0x0000000000000001,0x0000000000000000}}}, {{{0x00048e2fcaa83f58,0x000495fafcc6105f,0x000d34073fc2c5d9,0x00042510321d1a08}, {0x000d83427742e304,0x000ec5f97b8068ff,0x000530da7faa8a52,0x00005d010e52ac14}, {0x000df5701f277a14,0x0000eacdd532283e,0x0000000000000000,0x0000000000000000}}, {{0x000f566cbb172daf,0x00050c51771845f8,0x00066aafeeea7b0e,0x0005258081cf4ee6}, {0x000c71bc2c6ec8fd,0x000790d250232a19,0x00011bed4c06ab26,0x0000acd06e0bdc44}, {0x000734273e0fd2a2,0x0005c1c9fb738a19,0x0000000000000000,0x0000000000000000}}}, {{{0x000b6ef22ab96e69,0x00026b8cd18dc5dc,0x000563a07bc4111e,0x000f73913482455e}, {0x000edcb5ec4ad0e2,0x0000caacaf21483b,0x0000f16a5a48441c,0x0005bffbf280c9e8}, {0x000f37a7690242b8,0x0002eed954418691,0x0000000000000000,0x0000000000000000}}, {{0x00066d6e31428479,0x000f47fc4b8794a7,0x000a81360ec38293,0x0004d77d31e9f867}, {0x00042db92af31be3,0x000d799976882df8,0x00005ddd34a906cc,0x000b961ddfb3abb5}, {0x000bbb326a3a37b0,0x0005d4f7af85a74f,0x0000000000000001,0x0000000000000000}}}, {{{0x0006d183b4b1bfc3,0x000143cdd1f50d0b,0x000721cf9d088770,0x000338fad247118a}, {0x0004efa498ee55a8,0x0008d9808733ff45,0x000faa72107a954a,0x000a392986064eae}, {0x0000c503bc385af5,0x00095cfc7e0cec3e,0x0000000000000001,0x0000000000000000}}, {{0x000f6c1133ea5097,0x000685bf161ebfa2,0x000bb087e9c48b5f,0x000987c958eb481e}, {0x0001ea465a54c3b7,0x00081943446e92e0,0x000a8941e66d88ba,0x000d40dc6c71b0c7}, {0x0007f59a3690cafa,0x000130f02679ac05,0x0000000000000000,0x0000000000000000}}}, {{{0x000c5b4b93b19e8d,0x0001b316df16919e,0x000549bdce1a1a0a,0x0001cc00d06d528f}, {0x000cf17722a1d1b7,0x0009c7821f1ae098,0x00007c6fc2825a3d,0x000f796a6b06d5bd}, {0x0004ca4366a06040,0x00072103b88040d4,0x0000000000000001,0x0000000000000000}}, {{0x00038b6ea0266cec,0x0003d4ff03eab713,0x0008f81bfb033aae,0x0004b58cdd700e03}, {0x0002486b62595d6a,0x00027288e5a75ffb,0x000043649c2c3428,0x00056516d9dc3a87}, {0x000145473b4564bc,0x000f9a0961272b27,0x0000000000000000,0x0000000000000000}}}, {{{0x0006ad885aea13aa,0x00022fbb0e237052,0x000115fb0a1aa034,0x000ccb8ce398278d}, {0x0004178f8f78a3bc,0x000403be5854a510,0x0006bcde0e2e720a,0x000edf5f632b7fc4}, {0x00038eed71d606d0,0x000d21f92dbc6d75,0x0000000000000000,0x0000000000000000}}, {{0x000631ff7cd8f78c,0x000698475f524849,0x0005eafa796bd6f5,0x000fa7a4ee42bd53}, {0x000b8f8540687776,0x000540f9fdea3095,0x000f5bf17004e5b9,0x000834c440599d47}, {0x00063874f7c8a4ef,0x0006bec9a4f28185,0x0000000000000001,0x0000000000000000}}}, {{{0x000c12a0297bd390,0x00020c5821857743,0x000e07f2b528d6e4,0x000318df51deafc4}, {0x0009c03086d94e26,0x0004d01fde5e064b,0x00071c1d5855c1d9,0x000cdd2d762cca56}, {0x00022e583500cf8e,0x0003f52279b68b61,0x0000000000000001,0x0000000000000000}}, {{0x000b572837258eb6,0x000b88af33e25ea0,0x000ba976e7082c63,0x0000d0abef5e06ce}, {0x0005c8fda6ac69af,0x000f82b26435f42d,0x0005ef9369e629b7,0x00029491bb2be768}, {0x000ae13ca4da59b7,0x0000f00ce8846bfb,0x0000000000000000,0x0000000000000000}}}, {{{0x0000079959682d5c,0x00076719e3233b3a,0x000c78c2194cd545,0x000e51d3c744ff86}, {0x00053afacd6dd789,0x00098cb1ba7a5cd2,0x0004fb918b560853,0x0009ff1bce38273c}, {0x000a7efa90ba240c,0x000ba73bb2e372bc,0x0000000000000000,0x0000000000000000}}, {{0x0003a114b353d398,0x000d2df4adbd1d56,0x000e9ad940e90284,0x000fca7fe3af63ef}, {0x000de96feaa4e61f,0x000bf94ff4ba0669,0x0005279d7b8471ad,0x00071dda976e696c}, {0x00066b8800a22911,0x000f5fba44b58815,0x0000000000000001,0x0000000000000000}}} }, {/* digit=19 [{1,2,3,..,}]*([2^76]*G) */ {{{0x000b896b5317311c,0x000ccb025efc3b29,0x000bcd9f85c60e34,0x0005f821ae29c1d9}, {0x000293dcc63561e8,0x000f95824c27219e,0x000843c9e01039f3,0x00048ef0f79fd3a9}, {0x000ddb5a3bba44b8,0x000011f0a7f5379c,0x0000000000000001,0x0000000000000000}}, {{0x0000be31597dedd3,0x000aaa0d73669dd4,0x00090c605d60706d,0x0007d62f262a826a}, {0x0005e90997b0e2e6,0x0004dc73225ac29c,0x0008be39728fe4ca,0x00038656b7a746c2}, {0x0008bd5a3cf46a3d,0x00080a0c58ac7031,0x0000000000000001,0x0000000000000000}}}, {{{0x00070e2b4e96cd1b,0x00023ea39d68ac53,0x000f98a99040b26e,0x000362a9be557ba1}, {0x0003c202765cccef,0x000726d7b5a7731e,0x000faf8cd815e2ba,0x000ba6579cd91c25}, {0x000ec8fb3dafb2e8,0x000af4648049fac5,0x0000000000000000,0x0000000000000000}}, {{0x0004b6251452046e,0x000cb296110b89a0,0x000551f88c9d1ddc,0x000bbb0b0f26d015}, {0x000c2b5bd39d39b8,0x000dc18ef79d52ff,0x000b527ab6d006e2,0x000a804f61d0142f}, {0x000be5992391511f,0x000815a3e717ea9d,0x0000000000000001,0x0000000000000000}}}, {{{0x00029eaddc553333,0x000212246b16c20f,0x0009da31a639b833,0x0005a63d297cf150}, {0x0003190a2a3a8499,0x0002ca8af6260545,0x00018490cdf918d2,0x0005a5ed4b646253}, {0x0004fec387ca9de6,0x00010b72b35acffa,0x0000000000000000,0x0000000000000000}}, {{0x0006d539b23d78ec,0x000a4b221e3646f9,0x000b6bf83af256f3,0x000d62f0c408a90f}, {0x000fdaefff14a7ab,0x000e41ce0c4069cd,0x0001cba29824953a,0x0007a382ab7eb47d}, {0x0007f64599eb440b,0x00074a4c148b6095,0x0000000000000001,0x0000000000000000}}}, {{{0x0005a160c85caa71,0x000f0e79edff6be6,0x0007704970c1ae3a,0x000a395f8b957c42}, {0x000c85f0f181eb8a,0x0007d8f529bdf3d6,0x000d3534e626c58e,0x000c770dabfad83f}, {0x0003e65d7e5ada98,0x0005676430730bac,0x0000000000000000,0x0000000000000000}}, {{0x000d0476d73fcec9,0x000d714dcf97c309,0x000a56a3252ab9b5,0x00097fc79648c08c}, {0x0006b897ba609ff2,0x000c446a06ff8430,0x0002d01ddb643744,0x000f97ee1218bc20}, {0x00048db33f9b0f80,0x0005e8b5f54bb8f0,0x0000000000000001,0x0000000000000000}}}, {{{0x000851bfcfbb80d1,0x00082b51c40077e9,0x00087cd565dbfe09,0x000954bdd372a1cb}, {0x000f6bbff7b4dccd,0x000237c51d294b36,0x00003d64ce0f8798,0x0000569d6e3c2614}, {0x000a6224fb79e0e6,0x0004d7c33dd3b5eb,0x0000000000000001,0x0000000000000000}}, {{0x000f054ad5a9cfa1,0x000bee5f93daceaa,0x0008aa260aa160bb,0x0005025da9f4b722}, {0x00004817d1e67b1b,0x000e00279781308a,0x000c2084afd2f00f,0x000c154f68e6680c}, {0x000c6b0f1d4b7ecc,0x000fe2b89761184c,0x0000000000000000,0x0000000000000000}}}, {{{0x0007fbeff2b9ea68,0x00035c954c6cefab,0x000062277d67291b,0x000820637553137c}, {0x000e8b75730d8af4,0x00068d2250710c68,0x0007a2fbae3e7c1b,0x000f6b643e1aff63}, {0x000dc46991ef002b,0x00096e38ab4582dc,0x0000000000000000,0x0000000000000000}}, {{0x000bea0d80f3758d,0x0001d6899ee62692,0x000cdd2a79a4d763,0x0002f50f2ee3aea9}, {0x000fb1476eea0816,0x0007c81475c4d433,0x0009d9fe82142372,0x000756c76934dc96}, {0x00033eb086d918c8,0x000e3056d2a89175,0x0000000000000001,0x0000000000000000}}}, {{{0x000ef0de9496fb55,0x00076806fa762c50,0x000770bcaf6f226f,0x000a0d3e47cff6b0}, {0x0004eb780ef8cec1,0x00034df87449872a,0x000896382a505c84,0x00046b56a94dfc29}, {0x00021c7a5c037f2d,0x000659ef98ff9417,0x0000000000000000,0x0000000000000000}}, {{0x000001c935289072,0x000f4a229e4010ce,0x000b1be023ab7710,0x00073fb44f780b68}, {0x0002944ddc611373,0x000ba09ab8b61290,0x000be003d4bb157e,0x000f7557730f52d1}, {0x000506c275d184bf,0x000c57abea8b4979,0x0000000000000001,0x0000000000000000}}}, {{{0x000004498fadaa48,0x0009d0bea3c3894e,0x000a8f46458aa39f,0x0000008b0b3654a0}, {0x000ca4cd7392bf83,0x00012eb97aa46a22,0x000b9cb80e1d7afb,0x000cf74c8adcd888}, {0x000b51d04bb6e179,0x000b50968eb22473,0x0000000000000000,0x0000000000000000}}, {{0x000f96d03d831756,0x0007499de9e10051,0x000ecddcd4ffade3,0x0009dbdffc72771e}, {0x0006b5e1bb9647aa,0x000addb508dc2415,0x000ddf40de78eeab,0x000ab1c488946fac}, {0x000c823824a964d6,0x0003b16f258c8749,0x0000000000000000,0x0000000000000000}}} }, {/* digit=20 [{1,2,3,..,}]*([2^80]*G) */ {{{0x000cc508d53fa611,0x00057fcd40894532,0x000f3eb54e960b10,0x000ea40877d231ff}, {0x00043e5110313bd6,0x0005209f6eb9ee83,0x000589764924e778,0x000332e258b2e7fa}, {0x000e2e038618a6eb,0x000aaf96067c3511,0x0000000000000001,0x0000000000000000}}, {{0x00022156015c8ff4,0x0003a0ef974e440f,0x0008ea1f931a1b7a,0x000e417472932b48}, {0x00003bb75d745720,0x00096758e51bf9c8,0x000f97c7f0b39099,0x000b39d56a488d83}, {0x000fe1ded1fac932,0x000399aaf43ccf55,0x0000000000000000,0x0000000000000000}}}, {{{0x000fb78344f73774,0x000a49ad3e73876f,0x0008771e37ad3158,0x00003f2cb98ec469}, {0x000f31bd531106f1,0x000434959ff8325a,0x00064eee47f875ba,0x0001cf224bc0a102}, {0x0007d33a19ccf2f6,0x000f2186ce603133,0x0000000000000001,0x0000000000000000}}, {{0x00006e91f2869773,0x0000239179c5ea67,0x0009aa4ed3879ba3,0x0003eb977e239f26}, {0x00090ef091443aa8,0x00036fc4d282853a,0x000a0bb2b260d343,0x0008119fbd0756b3}, {0x00053a3a6e0f1619,0x000016a2af080234,0x0000000000000000,0x0000000000000000}}}, {{{0x00000185bd1fcc92,0x000a0002ebe1f280,0x00030d3e5f23ebcd,0x0009d40f75cccaba}, {0x00063108edd488ea,0x000028024e152a65,0x0008296732e422c6,0x0006142e6cc11761}, {0x0004e44889dea726,0x0004d1b05325e95d,0x0000000000000001,0x0000000000000000}}, {{0x000270a2e4063870,0x0004d9c29b5dcaf3,0x000d2f759d7bad98,0x000ff7c2ad7bc046}, {0x0000fa4e4f59d347,0x000a06be29c16d4c,0x000bb31872d14ff0,0x0002b7a5b6ec2390}, {0x0008ae4cc66be2ce,0x0007006b9b1fe040,0x0000000000000000,0x0000000000000000}}}, {{{0x000c4cee52cfafd0,0x000916a99628d59c,0x0004417813a4764e,0x0003f0c49a05da16}, {0x000992babb644e42,0x000179a66e24dca8,0x000cbef894f6883d,0x0001ed7756c7c157}, {0x000ff08e144c3013,0x0008ac78b0a3e9cd,0x0000000000000000,0x0000000000000000}}, {{0x000dabd753963ba6,0x000426be7ba3ec43,0x000d17b8f8b93626,0x000d7ac0bfcd2a78}, {0x000c2aeda53c9486,0x000c99eeaefc3c49,0x0003d0949fb4a9cb,0x0005db07562812ab}, {0x0005da4c6c0f863b,0x0009e08ec31fe43d,0x0000000000000001,0x0000000000000000}}}, {{{0x0008d00b0f45825d,0x00075f4acb7a9109,0x000fe317cf8f4f81,0x0009a77cf8155d16}, {0x000d7ac3ddeef2bc,0x000aeae3c417520b,0x000e6ff44ee6fbc0,0x0008d8c238521aaa}, {0x0003f42c9f47bc82,0x000d2fc09b26d055,0x0000000000000000,0x0000000000000000}}, {{0x00032ac7c6897ed6,0x000498c1e669bb9a,0x000697322f4c8aca,0x000625a543042d46}, {0x0003cdf16aa69334,0x000b4b67c267bda0,0x0005d6f205d341fa,0x000005daa2bd83a5}, {0x000c9573fcdfd94e,0x0004e81cb76afe9a,0x0000000000000001,0x0000000000000000}}}, {{{0x00074fcede51930f,0x0001c997863b91f0,0x00092d449a3c4328,0x000c91197a68c2d7}, {0x0006a3b2de0b3063,0x0003e7d82555e166,0x000f427f70b4227f,0x00066c04e18d6aac}, {0x0004c82c2c2b9b61,0x00095a376fa210aa,0x0000000000000001,0x0000000000000000}}, {{0x000de0f4a3a29f55,0x00023263844f1727,0x000fd0bec7770941,0x000e79f43b5f4e85}, {0x000035cbc9a5768f,0x0005bb2328826a73,0x0008a77da7d22096,0x00096978fe424078}, {0x000ae1a0514c7cf9,0x00085e77943ce3c2,0x0000000000000001,0x0000000000000000}}}, {{{0x0000d1b4594afc85,0x0006a925e9937fdb,0x000d1cf398814c56,0x00000694cd250848}, {0x0005fbfd82b6ccc3,0x00047db4ae135bc7,0x000c1f18639e63fa,0x000730a5e5b32295}, {0x00041bb1c61f91b2,0x0009451335383b28,0x0000000000000000,0x0000000000000000}}, {{0x000df27e3f2dca32,0x000ee40fb695c7e1,0x000c8c313d1721a9,0x0008bc93267e9801}, {0x0006a9aafbe12b28,0x000e34c2b180d7a3,0x000e6b65e8b79ae5,0x00047da7f03b22ef}, {0x00094e563552e913,0x000f4aab16538cee,0x0000000000000001,0x0000000000000000}}}, {{{0x0006db42e9e50fad,0x00042149f7546b33,0x00057093c06f6900,0x000dbce88e00d7d3}, {0x0004ad9ede7428d2,0x0001940521d004dc,0x000e4970d3be2ce0,0x00031bb5cf60dc4a}, {0x0003df5670a6ccb0,0x000b64df04605d80,0x0000000000000001,0x0000000000000000}}, {{0x0005f0fb0c7d8a77,0x0006951f8ad28aa0,0x000e5b908dd39d0a,0x0005f76fd67e92ff}, {0x00080f281077f416,0x0009ee2db2c8d529,0x000e9a09ff0b841c,0x000f9a5850f2e792}, {0x000e9887cd74d1ff,0x0009aa468c4978db,0x0000000000000001,0x0000000000000000}}} }, {/* digit=21 [{1,2,3,..,}]*([2^84]*G) */ {{{0x00045bc39568d9b4,0x000deebca99c74cf,0x000ae132b3816aa0,0x0003fb57b713a9d8}, {0x000e4139b0131f8d,0x00042164bbc38156,0x0005a533293d5ffc,0x000f28a54d0e74da}, {0x000246758970fcef,0x0005cb3ef8fd2b56,0x0000000000000000,0x0000000000000000}}, {{0x000e59886b3941bc,0x0009ade1a4b217a0,0x00023117719aa3f6,0x000c88c1b7b4e45e}, {0x000c3f1294233118,0x0001ed8c9dd7dfa5,0x0003ffafa2104f8f,0x000e89ed71382221}, {0x000d0f8573ea0a97,0x000a81f09db9f82c,0x0000000000000000,0x0000000000000000}}}, {{{0x00077d542b1d8c85,0x0009eb6c76648a7d,0x000ae9936fca1675,0x000c8db3d9556eeb}, {0x0008f1fc23af7239,0x000956a6643df02c,0x0005264fec894e1d,0x0000aaa92f802a0d}, {0x000d756f014a90b9,0x000e0753d197ff93,0x0000000000000001,0x0000000000000000}}, {{0x000dc80b7f62d4df,0x0005de026f897406,0x000bf46ad6add1ea,0x000f1c5d1c416858}, {0x0004d6b3d82ce8f0,0x000459159df587ce,0x000ca473b92c19aa,0x0006da5bec10b6ba}, {0x000e0b4be600af3c,0x000cf6c81e2b9b40,0x0000000000000001,0x0000000000000000}}}, {{{0x000c67c15f2b99a5,0x0002e78f41b12d02,0x000f7e85b9e3bb96,0x000e6c293dd82110}, {0x000a0b7296f35eee,0x0008b9f01a446a48,0x000f7d8d89873daa,0x000d90409d0bfd67}, {0x000b42d1c91c3962,0x00005e6c3afa1fdc,0x0000000000000001,0x0000000000000000}}, {{0x000607a511880114,0x00046b3caa5f65bf,0x000ed1d7edcb6427,0x000223b76ca3eaf2}, {0x000c254785aeacd8,0x0003d96bed772614,0x000fe17074c3138f,0x000fc4599803c303}, {0x00029d4441854c4a,0x00068d2f47c7e6ad,0x0000000000000001,0x0000000000000000}}}, {{{0x00027dadf66942d9,0x0002d934d4f0887d,0x00024ab4a3b4ff58,0x0008094d151ee4b7}, {0x00059df116aee58c,0x000c8ad8141ceee5,0x000c277f6cc0cd16,0x000b9d41dd2c3d13}, {0x00018d63c75e0cd1,0x000c06bb0767f3f3,0x0000000000000000,0x0000000000000000}}, {{0x0003f3f369ef6b69,0x0007808f1170f91f,0x0006338ef6344906,0x000cb4597495e6b8}, {0x000283f524ab766d,0x000d7731127ec634,0x00075be86373e0af,0x0008d2af0e3a5495}, {0x00014c6819dfc2be,0x000f7affa7af5c63,0x0000000000000001,0x0000000000000000}}}, {{{0x000892c7124cd33e,0x000b92182e71043c,0x000db014cae4df90,0x0009ceb0a4ea4119}, {0x000ef942ed19b706,0x0000628b68098d1b,0x00084c6cb159ff0e,0x0004d4b5184cdc53}, {0x000190191d032e77,0x0006b2ec68efce97,0x0000000000000001,0x0000000000000000}}, {{0x0003436236c90d20,0x000e12c74816ecfc,0x0003e074e74849dd,0x0007be255b09c30d}, {0x000526507824bfa8,0x000ef7cb512aeee2,0x0002afeb20a50c2e,0x0008aa489a2c4123}, {0x000334adba554c1c,0x000ed1b94b601c93,0x0000000000000000,0x0000000000000000}}}, {{{0x0001c752e894f83b,0x0001102db47294b0,0x000efd031528755f,0x0008e7a5233b9d7e}, {0x000dc69c62c7500f,0x00051f44711ee3b5,0x0009d94a5e280f05,0x000b11042cd8c7dd}, {0x0008b14370c2167e,0x0007807f4636e4af,0x0000000000000000,0x0000000000000000}}, {{0x000598691d482817,0x000b8412f599a077,0x0000459d6b4cf61c,0x000405e26f27cc0b}, {0x000ddbc7fdaf5126,0x000cdbba7c4a3026,0x000b262658e4a3b0,0x0000f2e795bb25d0}, {0x000766509eec95e9,0x0005a452259c52c8,0x0000000000000000,0x0000000000000000}}}, {{{0x0005f6dc2c523bd7,0x000003d082f18f83,0x000ef7ee57fec42f,0x000f2558c3c5a1e3}, {0x00038f0a9e89f93b,0x000efbe9151ca6a7,0x000ed767c4685458,0x00079d486204e6f8}, {0x000a36a1a4b728f1,0x00043b885c25b705,0x0000000000000001,0x0000000000000000}}, {{0x000eabc2b52d4646,0x0006c95bf22f084b,0x000314aed2f78fee,0x000dd61877362fd0}, {0x0009044697d005db,0x0001d56d41727a4e,0x000627e07ab413dd,0x0000b5903e3cd67c}, {0x0009c224e9a02779,0x000806739d1d3428,0x0000000000000000,0x0000000000000000}}}, {{{0x0004109673b0becb,0x00029788f9eb9435,0x000ae5dfb3d20da6,0x00057d88527623e5}, {0x00015c844e99c175,0x0006a57ec3b40311,0x0000b594aff5aa0b,0x000cea2e84adbe7d}, {0x0007fcbaf1e84a37,0x0008e3048c293594,0x0000000000000001,0x0000000000000000}}, {{0x000f58bede275de5,0x000b21503171b093,0x0007b8e1c737aaa2,0x000dfceb6261f263}, {0x000d21e8e8701620,0x000e453d37db241d,0x000825774e79c85c,0x00066f92bc717db8}, {0x000b9d9ff5a2566e,0x000bfd4ae0bd7b6f,0x0000000000000001,0x0000000000000000}}} }, {/* digit=22 [{1,2,3,..,}]*([2^88]*G) */ {{{0x000cd0f9ef7a9efa,0x0001757bbdb01042,0x0001996a380a3fbb,0x0009e651f39db731}, {0x000cdf3f08146bb6,0x000679b0b6ec6679,0x000ae26608474788,0x000d883e5a5990d1}, {0x00061924fa5e209e,0x0001de3c755c0bba,0x0000000000000000,0x0000000000000000}}, {{0x0007c1f82ebae92f,0x000ccf8ace9c6a84,0x000857d9026a1434,0x0005b0b7ad864d4c}, {0x00018f613e2210ee,0x0001165b2c86a357,0x00019fb55984d679,0x000f15401901080d}, {0x0009a0e8b3389ecc,0x000e608b509b98d9,0x0000000000000001,0x0000000000000000}}}, {{{0x000a526cf604c662,0x0003afa9ed0f7a0c,0x0001dd685ac125b3,0x0007ff8f516f5290}, {0x000ad927c416e17e,0x000fc77cc9720475,0x000071767e1e9190,0x000f6652fcb33aec}, {0x0000f0d48cb2653d,0x00086c8bf16720d8,0x0000000000000000,0x0000000000000000}}, {{0x000404c440590fcd,0x0003377f43e4e408,0x000defb22729c42e,0x000241aec3b37e10}, {0x00092c795c866daf,0x000f4d30790a07c8,0x000075bb2425f5fb,0x0001b7cb5830a5db}, {0x000c950890875f16,0x000e6591cad66493,0x0000000000000000,0x0000000000000000}}}, {{{0x0003de8c91c31e47,0x000a2de46bc7eb7b,0x000f3de301a0b479,0x00094aa7479aa235}, {0x000be5191502fe1c,0x000266a8b4adef28,0x0002961e0e185a17,0x000f211c2c23ddea}, {0x0007d3314a5b8f85,0x0007d3d59f2b026d,0x0000000000000001,0x0000000000000000}}, {{0x00032b1fd4f159bf,0x0003721f923e006e,0x00024a7d38b715f2,0x0000994620d23277}, {0x000ab6678b2917d4,0x000fa4a8245b0c3a,0x000912038e0b4172,0x000f6fdcf8c4b1b8}, {0x000ccd3b3eaaf19e,0x000d40f97e7249e4,0x0000000000000001,0x0000000000000000}}}, {{{0x0007975597dddacd,0x0009d9266f6975c3,0x000599f544c22dfb,0x000c2be6db081480}, {0x0002aeb8ec462839,0x0009d49cd3b5cdf1,0x0006a8ba917fb29d,0x0008233b216f9614}, {0x000abf1a9d936c0b,0x0007878c8a45a2f0,0x0000000000000000,0x0000000000000000}}, {{0x0005dd64a0356029,0x0008c2d1625aef0f,0x0005ff56fc705652,0x000323cb9b293d67}, {0x000bd02b295cca5c,0x000c7129104d697c,0x000d83fe4eb4b02b,0x0004a4e9327cc1e4}, {0x000f46cdc9c23cdd,0x00053f946406995a,0x0000000000000001,0x0000000000000000}}}, {{{0x000d1e43a1e16a36,0x000514cd5be788b6,0x000f3827d2f55b7d,0x0000a3f8f594d05c}, {0x0006accb980d1448,0x0004ad1e4f1f6b59,0x000e7dd3016801fc,0x0007c435098ccf31}, {0x000c6bc2e61b9059,0x000588b12be241e3,0x0000000000000001,0x0000000000000000}}, {{0x0000b8e2e65481b3,0x000aef410135fbc4,0x000c7a2e23221960,0x000fd4a513faa141}, {0x000a0357c6f569e3,0x000f4ac3eadff143,0x000f6174146f64bf,0x000c13f9a5506c59}, {0x0005ed7b5be845e0,0x000d0deb4721eef8,0x0000000000000001,0x0000000000000000}}}, {{{0x000e8dfde28d4a2d,0x0001761a2d5208a2,0x00005b6ff5ebb541,0x000b58d09bebbafe}, {0x000a9eccec1be769,0x0004b3933ce41d83,0x000e22e31e1a1a39,0x00081430e109c5df}, {0x0005c36dffc66dc3,0x0006a93ad68549c2,0x0000000000000001,0x0000000000000000}}, {{0x000135d5a197f614,0x000b4beb4875f558,0x000374737f60f213,0x000b3391150b17e2}, {0x000fd51cce3f02fd,0x00090f492191217f,0x000bccbadc4f8a8a,0x0005d89eef2479ce}, {0x000b7145781a1c26,0x000e4d791a7d8953,0x0000000000000001,0x0000000000000000}}}, {{{0x0006a3d38b806bee,0x0002ffcbc7fbb018,0x0004904b1192a4cb,0x00039b7f571c01df}, {0x00040717c8035f6f,0x000f75f4a725c0f7,0x0003575b1f8427ca,0x000cefd7922924c3}, {0x000c3f91c6705a27,0x000f14804d6b5694,0x0000000000000001,0x0000000000000000}}, {{0x000d6688c387623f,0x000533d1b2b7249a,0x0006a96c61952611,0x0009fa8adb7cd547}, {0x0006614cc5f19687,0x0000dc38a5b55739,0x000b43a1185de8e8,0x000489b0890de38d}, {0x000cfe16e6aaab3a,0x0009a02c0ab01066,0x0000000000000000,0x0000000000000000}}}, {{{0x00047414fc9de104,0x000b82aed9435d61,0x00062ff16a9bd16d,0x000caf4a3b07e71a}, {0x0003ff9456ee752d,0x000d78dd65ea0d3e,0x0005bf864901fef1,0x0007bc9f42253114}, {0x000cb13ee366fd36,0x000fe6290083f481,0x0000000000000001,0x0000000000000000}}, {{0x00032088e6e77ebe,0x000f38c5e887c852,0x000f005e149cc7b3,0x00089874e1bede78}, {0x000c72dfeaf32e8c,0x000cb0a4d9cb4e28,0x000aba5da48c7113,0x000b1fe289a0af7d}, {0x0005d0dc00d3633a,0x000801c0b05c86bd,0x0000000000000000,0x0000000000000000}}} }, {/* digit=23 [{1,2,3,..,}]*([2^92]*G) */ {{{0x000567a7a06de008,0x0007cf045155d807,0x000ce8bb24635169,0x000c2900cba64633}, {0x000c724297174dd5,0x000c3a3851e7f044,0x000f59548c830bf0,0x0003817a26f0d35f}, {0x0003d8b027d923f5,0x00062c2b3dd7cad9,0x0000000000000000,0x0000000000000000}}, {{0x00094cbf6924bf9f,0x000c09986d299bcc,0x000f89ccb5adf6f5,0x00099f825aee26f4}, {0x00056c1b545bb186,0x0000d22aa56595e6,0x000ba5ea3953faeb,0x0003a9580b4b6abc}, {0x000465246d4e240d,0x000d8613b6fdf7ef,0x0000000000000000,0x0000000000000000}}}, {{{0x0008a64cd725af51,0x000d6dda66823389,0x0001f40d7d1c8516,0x000115e05fb1f564}, {0x000ad7906c2d8d5a,0x000f4efe00496ac4,0x0002d973643f7076,0x0004414f58386c89}, {0x0002d83c2e34b14c,0x000437c00d08bc7c,0x0000000000000000,0x0000000000000000}}, {{0x0004451656bebe71,0x0003f2219e2e5bca,0x000118227eacbf3a,0x0007e2cef1a84019}, {0x0002d58a5f9de601,0x0001ecfa6e192212,0x0006fb198696eb0f,0x000854826be2d3df}, {0x000dea0068fefc08,0x00074e77c2979102,0x0000000000000001,0x0000000000000000}}}, {{{0x00048eb205a5b22a,0x0007d680f21ad148,0x0008e50bcbdde0fb,0x0006f6074c1119fd}, {0x00079f9f2e43583d,0x00065361f1d9961c,0x000463e625f26bb7,0x000f2b47c8db008a}, {0x0008c397787cd134,0x00029b36eea7ef32,0x0000000000000001,0x0000000000000000}}, {{0x0006647223894ce2,0x00087adfe036fb3d,0x00067daf1eb206e8,0x000b19b372f017c4}, {0x000a8ad33a99ef7d,0x00055c0da806ea7b,0x000c02414bd637ef,0x000b598649739b12}, {0x000feed3dd282f3b,0x0003ecce69b37255,0x0000000000000001,0x0000000000000000}}}, {{{0x000e5f81ac137092,0x0000518f81e9a3bd,0x0009720014a7f4da,0x0001f457a02bf073}, {0x0006be074553e9ff,0x0004351eaa3a46ea,0x00022b27e32f0dd6,0x0003b488462fd22b}, {0x0006ddddacafc2c2,0x00035bfb75908f56,0x0000000000000001,0x0000000000000000}}, {{0x000987332b5b9a11,0x00044ffe94dfd9e8,0x000f9b91bc64f63b,0x00077f430dbd772b}, {0x000dfd580392aecb,0x000ddc69fb2fb67d,0x000314d2fdb69c91,0x000e754b9b9f9ea2}, {0x000f2e9c2e624f23,0x0000a3c6e677e1f3,0x0000000000000001,0x0000000000000000}}}, {{{0x000e37a930c3bc57,0x00006f969b4cf1af,0x000df3ff74237c4c,0x000d1ea35c488b6e}, {0x000e084f47372a77,0x00065b61ccb75b2d,0x000a4e47577fd773,0x000dbd98a086f5f2}, {0x000533002b74aa9d,0x000bedfb9c8068e6,0x0000000000000001,0x0000000000000000}}, {{0x000b7aec02da823b,0x0009baf08dcbb7e2,0x000400bf0e5f485f,0x0003a3c7f9dfd4e3}, {0x0007472ece43050d,0x00091a092b1134f2,0x0004c1a0e70ff8a8,0x00037f3b75a31807}, {0x0000f51f254e9906,0x000c2183d0367614,0x0000000000000001,0x0000000000000000}}}, {{{0x000a39c0dd80f6fe,0x000a13cb07adfd25,0x000ee3ca4d8c1a3a,0x0007a28212986a18}, {0x000c5167c4c47943,0x000beb7b7306e9bb,0x00038cfc9b26c1f3,0x000b68e5bc206604}, {0x0003bd9665b63ba8,0x000661b9d7de6c40,0x0000000000000001,0x0000000000000000}}, {{0x000c9e6e7c3229ea,0x000fb93cb721672d,0x0002429ae120fbe8,0x0007d3de1f64e3d5}, {0x000492888bee099a,0x0009c2f4894dc1d6,0x00011bda9ef3c7dd,0x000289559ae47758}, {0x0008fcbb34df4ae3,0x0005c440c5d0ce22,0x0000000000000001,0x0000000000000000}}}, {{{0x000fc1fd2377e231,0x000257cc9235e4c6,0x000a8f0482692e0c,0x00027d24355728b1}, {0x00087856d3663645,0x000dfe4f7c7f19ee,0x000c0f9ccd7eb847,0x0001019511788244}, {0x000c4838c54b2a98,0x0008b89d2d46944a,0x0000000000000001,0x0000000000000000}}, {{0x000e02a1a1d2a70d,0x000b7d63b4d27dff,0x000ab61d5fa9a970,0x000d7730420f7a7f}, {0x00079f4479996041,0x0001189500cc1597,0x000981b342dd1a18,0x000b0c87b154435a}, {0x000fe5a645fb9438,0x000a1ab34fb7fc43,0x0000000000000001,0x0000000000000000}}}, {{{0x000f438f4b100160,0x000f22d13ff0c314,0x000d55796ecb8e45,0x0000ab873dd2e2bb}, {0x000789eb71d33f83,0x0003167e0b14a364,0x00002c246513aa48,0x000b03e86d3a7935}, {0x000b2db2bb0fe98c,0x0000d70404a0ec4e,0x0000000000000001,0x0000000000000000}}, {{0x0004384c5c6b60bc,0x0002570cd19a5c8f,0x0001c33b468c19b3,0x000cbac39210942f}, {0x0007d36048a2a29c,0x000f69ef5fd4ffa9,0x000ece5cd6b0a674,0x000b1322973982d0}, {0x0001493bd4bce1b8,0x00083d4d6596bf49,0x0000000000000001,0x0000000000000000}}} }, {/* digit=24 [{1,2,3,..,}]*([2^96]*G) */ {{{0x0000db5e813acae0,0x0005831117f6d456,0x0001106059c8e19b,0x000f908ce8232c57}, {0x00092d0f09782c78,0x000bd0fcb64a24aa,0x00077e3d766becf8,0x000f155f53d2f599}, {0x000389ae2fa9a727,0x000920ff877e9249,0x0000000000000001,0x0000000000000000}}, {{0x00085d510d2d4458,0x000dc73b4e520499,0x000aa68342be4788,0x0004f89c8a0ca8e6}, {0x000e8668748927b1,0x00017375ddf19eb3,0x00041d15e5f8b7ce,0x00052912af54652a}, {0x000b9a777a86a727,0x00003bbaf706d85a,0x0000000000000001,0x0000000000000000}}}, {{{0x00017d39542a7b35,0x000d6953d2cbb145,0x00044a3ef5b5b733,0x00076565472126ff}, {0x000b2a4a1334dee0,0x0002573d17b26c37,0x0002c7ab5b295171,0x0008d328148c129c}, {0x000907f5aa2c72b0,0x00018b1d10e10308,0x0000000000000001,0x0000000000000000}}, {{0x000159666154b57d,0x0005dd9359d8885e,0x0000281b6f14827d,0x0009bc4ba475f3a4}, {0x000c32eef44696b1,0x00082b50dbdc6dfb,0x000236a9ef4383e7,0x000fd73208450583}, {0x000d190b07767db3,0x0003153c0278a00d,0x0000000000000000,0x0000000000000000}}}, {{{0x000ba905f5456251,0x0008ee5b3d8d39c0,0x000ea2a0a4462a26,0x000032f3094457cb}, {0x0009bab36ceff80f,0x0001b0fdf3879073,0x0009dc840209bce2,0x000df0c1c8e03824}, {0x000c51d81213ecb4,0x00063c2b025e0d70,0x0000000000000001,0x0000000000000000}}, {{0x0003bb32c4b899f8,0x000ccb798bfbf249,0x00028838277f622f,0x000e5b67c2594827}, {0x0003c2c07c4dd5cb,0x000c19526a2c4c70,0x0000177dcd0df4c1,0x000457a743a1ed39}, {0x00032bea63a4c527,0x00075d1c302e78ac,0x0000000000000000,0x0000000000000000}}}, {{{0x000fc5003828ff0b,0x000436a9841f4323,0x000c6f35f8a62407,0x0009286efc260a1f}, {0x000fbe74c4b2df5e,0x000cb3568b504bfa,0x000dbcf3548e5047,0x0005d92aaad71af9}, {0x00018241085e423c,0x0004f894d1d8842d,0x0000000000000001,0x0000000000000000}}, {{0x00075b2a3f29b75d,0x000ec555f7834899,0x00092b31a410939e,0x000b7bc223255263}, {0x000db65a25c264a1,0x0008fc1aed283464,0x0005c70ecd1a9b70,0x000d90a7a2a0ea33}, {0x000d21f2e9f14ffd,0x000fb49566dadd7f,0x0000000000000000,0x0000000000000000}}}, {{{0x000fa5757545376f,0x000ae164cbfd55ff,0x0008a8545451f1c3,0x0002e007d0be9705}, {0x000ed2a8f4c49727,0x00097ed736254138,0x000516215e864c7c,0x000bb624fc1b83df}, {0x0000313aaf4114fd,0x000a7a8c7f0423cc,0x0000000000000000,0x0000000000000000}}, {{0x000ed76abc8d276d,0x000bfe3e74f599a4,0x00025d1f92d8b381,0x0005a3599e406956}, {0x00071869bdf5e06a,0x000ec86f625afaf6,0x000d724bbcc12cda,0x0003da7516890dd1}, {0x0009b69252163060,0x0002541f15a18b40,0x0000000000000001,0x0000000000000000}}}, {{{0x000e1c4e632e5d61,0x0002987ad659b7d5,0x0003f7f338de2f2a,0x000b55a5aaeb06f1}, {0x000b9a60e84f26d9,0x000d10563130c6f8,0x000e760d017d58e9,0x00039e20b973fa41}, {0x0000eaafdb2f4acf,0x000501ec9c6ab584,0x0000000000000000,0x0000000000000000}}, {{0x000f4549ba5a6302,0x000a98b140b89722,0x0003e099225c2510,0x000f31b19117bbe6}, {0x00046ba7147bd18a,0x0000f540e368bb5c,0x000eacf29d33114f,0x0007e59588a01c9a}, {0x000ef0e25eb2d0e6,0x00058e4bb1b8d029,0x0000000000000001,0x0000000000000000}}}, {{{0x00057915cb5440b5,0x00088e89a3e1eb04,0x000ed12c670e08cc,0x000eab1d89133ab9}, {0x000f615d9bc0c1fa,0x00081504d63c4250,0x00062cd084c8e8f8,0x000aaf76dbe53ead}, {0x000bf1dcc49cfac6,0x000fc7007ea0b885,0x0000000000000001,0x0000000000000000}}, {{0x000472352fc50515,0x000fa2123835c747,0x00067bab29e80692,0x000cca008379c2a8}, {0x000799065aafbc2e,0x000a605d2e32da97,0x0002283421bbbfbd,0x000dbdc2e1151243}, {0x0007a9d899c126b9,0x0007467ce3f8d643,0x0000000000000000,0x0000000000000000}}}, {{{0x00000c97f4a1ee70,0x0000a55fa6cdb3e0,0x000fd5fcd60595ed,0x000522bda02a23c6}, {0x0000361844a1d76e,0x000c6c179ebaf8c0,0x000a6ccd0a47af40,0x000071e2a1156aa1}, {0x000a1b0fc4eb0062,0x000bb4c1c5314a2c,0x0000000000000000,0x0000000000000000}}, {{0x000c048376702b16,0x0002ef5b4e8123cd,0x000a7d67834242a3,0x0003bc3accb0fead}, {0x00007e65ed32fc2a,0x000b8b44e6e71194,0x00077e9aeb1712aa,0x000039ce4f895a59}, {0x0009d43ed708cfeb,0x0004254957cd1ca1,0x0000000000000001,0x0000000000000000}}} }, {/* digit=25 [{1,2,3,..,}]*([2^100]*G) */ {{{0x0009a3fb62f03e91,0x000fc3cfe3b9a1c2,0x0008c5a528bca033,0x00096cd7b4bc3e3f}, {0x0008c4bd134e2233,0x00065224c739c3eb,0x00071ec25548c0a5,0x0007b0fb17f6f014}, {0x000aee1015fc6579,0x000448c4d69b6d18,0x0000000000000001,0x0000000000000000}}, {{0x00074be708f600f9,0x000042a14b550a00,0x000f8e6b95a52425,0x0004e9813f438c42}, {0x0005181004aa1017,0x00010cd9a834ae43,0x0002105b1b67e295,0x000141438bad8cdf}, {0x0004d11308ec5ba9,0x00034300e8c08dc6,0x0000000000000000,0x0000000000000000}}}, {{{0x000625d111480c24,0x00034cdcf3505fb2,0x000c306874b99629,0x00004410981e8fcd}, {0x000492bd0a650027,0x000a534a84249eb3,0x000e1326b6bb40b6,0x000ebe5d29140c32}, {0x0009956b2cb2ca52,0x000b8c77c7225102,0x0000000000000001,0x0000000000000000}}, {{0x0002b4e077c5c4dd,0x0008846314442efe,0x00066618e794431d,0x000a933fcd3eeea2}, {0x00006644159656a5,0x00022dc52fbda24f,0x000542f82f45dda5,0x000e0e5075c9d412}, {0x0002aba0fff34a66,0x000d69512c4a1d9a,0x0000000000000001,0x0000000000000000}}}, {{{0x000dc5b949f6aa55,0x000cb79872016ba3,0x0001df5e18d2889c,0x000aebf5e0129254}, {0x0003a4cd20b4cdbc,0x000f30108963d6c3,0x000c0dbc46a1dad1,0x00042c0e39b6755f}, {0x00007fa126ef9e69,0x000805d500d36fac,0x0000000000000000,0x0000000000000000}}, {{0x0000b5e7bd19e5fb,0x000b3765e8dbbff9,0x000e491cc2deb8ec,0x000ab995d314c068}, {0x000b4e810513ad31,0x000b50dc0fcca181,0x00029580c1e05269,0x0006b6453c858930}, {0x0009a98b2de5a7d2,0x000b386f7a77183c,0x0000000000000000,0x0000000000000000}}}, {{{0x000d861fc542368a,0x000a737b3c184cd7,0x00014a6e3b95c425,0x000f514e85d4a651}, {0x00098b665bb45532,0x00066a39b08b87e5,0x00008dbdbcbbabba,0x000ba64b561fa462}, {0x0005692509520864,0x000281de8b31e205,0x0000000000000001,0x0000000000000000}}, {{0x0001bb6a74473c21,0x000932e76a8c5ddd,0x000c6ee633cc0f66,0x000f68d0c546bb80}, {0x00006828f4e0c911,0x000b2a4276c213a2,0x0008cb204a16b2ce,0x000d38c09aa1cbe9}, {0x000f3ebeebcc1671,0x00032c7a684ba9a6,0x0000000000000000,0x0000000000000000}}}, {{{0x000a3463989cd762,0x00035114b160b22c,0x00057f2d520e3cc4,0x0000ff788707011b}, {0x00068b1a346a61d3,0x00084618b8d69eda,0x00020c04008115fa,0x000dfeeecaa806f5}, {0x0007e08436a14e30,0x00005f68bc839ccc,0x0000000000000000,0x0000000000000000}}, {{0x000ae58e3c998f3f,0x000951d35d5af6b3,0x00038625415f29bb,0x000fd087552cd755}, {0x0002087ef7e8ab49,0x0006b067b5de9ebd,0x0001e74110309c17,0x0007b224505a1ece}, {0x000ba962991a5a2d,0x000b8879263dad03,0x0000000000000000,0x0000000000000000}}}, {{{0x0001b7e0189fcda6,0x0008775ba885f2a7,0x000b98305b9915b6,0x00019b2753769a90}, {0x000638d87ac0d10c,0x00083c77c18f7acf,0x000d23964d02af25,0x000de5be92026e04}, {0x0005a30998f85294,0x0002d2bb22f8803a,0x0000000000000001,0x0000000000000000}}, {{0x0000daae09876e93,0x0007b9f1b9b10415,0x000e48eb13c50096,0x000cf9ccec3e5c4d}, {0x000f7b6158629895,0x000aa201ea7d90f3,0x0006e88c0cda29f8,0x000f4c0d70150c9a}, {0x000ee70bc97d1c62,0x000b8e4fd0f68d56,0x0000000000000000,0x0000000000000000}}}, {{{0x0003edbb844d6c8a,0x00076a792ccd3b41,0x00072527a7c1564f,0x00055b682778d6f2}, {0x0002167ba3cee45b,0x000d96d43a6e138f,0x000806538c932f15,0x000d4892afee6363}, {0x0002b82f06ed7c45,0x000fee287b4614b8,0x0000000000000000,0x0000000000000000}}, {{0x000953f4fc1bb9d4,0x000e995150d18cb0,0x00067e23c2e107a5,0x000bfba071a733f6}, {0x00008ca46066c2e8,0x000cfb49871d6c61,0x0004ece39bb5a648,0x00040cf34f514816}, {0x0009b9250336996f,0x000c69d6e08146e9,0x0000000000000001,0x0000000000000000}}}, {{{0x00008e517921a752,0x000ab87a6c13d140,0x000c4597b07c5d69,0x00074a68c66db12e}, {0x00019ca40dec9dbd,0x000a617fff4579d7,0x0005876131725395,0x000d09e3b946e383}, {0x000d20c852478942,0x00087982ecbef742,0x0000000000000001,0x0000000000000000}}, {{0x000589886da1602b,0x000c3fc9ae2bbd5f,0x0002126ee978ba22,0x00075595e212b5ab}, {0x000a2389b739eff8,0x00063595af9d6707,0x0000f9787d12dd72,0x0003b014c3309267}, {0x0002f506a0067880,0x000f67060764da69,0x0000000000000000,0x0000000000000000}}} }, {/* digit=26 [{1,2,3,..,}]*([2^104]*G) */ {{{0x000365108b90f9d0,0x000f80765f67fb1e,0x000b1b38d141aae9,0x00024d697a9407e4}, {0x0003f9693e7ccc84,0x000a50e7d291d93e,0x000cd34385c13c5b,0x00066fcf73c9d94e}, {0x000598f4a80eb0bb,0x000b721c4d4c290d,0x0000000000000001,0x0000000000000000}}, {{0x0000fb9a3bbeb3c7,0x0007ba326d546e3b,0x000a848cf094c6d2,0x0000e41609d2dc18}, {0x000266f0069ca46c,0x000c4aef799231b9,0x000abacbdbead081,0x000b272ba1959d4d}, {0x00049b7208e216ce,0x0002ba83cc03eccc,0x0000000000000001,0x0000000000000000}}}, {{{0x0004c0998b5250d8,0x000c867c43b599d6,0x0004c9f6ac785a2e,0x0004ec8b59f29f0d}, {0x0004df16ae8c0faa,0x000b8d8f78201760,0x000bc38bb59089da,0x0007384039822772}, {0x000d1571c6e88e81,0x000a7b7d4e8e0cf3,0x0000000000000001,0x0000000000000000}}, {{0x0007bc572ea0f919,0x00064539b5eb1047,0x00077d71bc88d22a,0x0004dc62d769223e}, {0x000adfe2b562c973,0x000173fab241cdb0,0x000603370ddf3ff3,0x000f70dbbbbd997d}, {0x0008a88a56d59561,0x0004be64aafc3299,0x0000000000000000,0x0000000000000000}}}, {{{0x00045d30a00d827f,0x0006bbe20955e997,0x000cead0ee1643eb,0x000fce2db7c5ac6f}, {0x000ad1d2efb30bc2,0x000d9fbc667affb8,0x000bb6fb3983d3ef,0x000f70a834538091}, {0x0008384fd172dade,0x0003f32390fa3030,0x0000000000000000,0x0000000000000000}}, {{0x00022aae53d2000c,0x000caf0273baad84,0x0004a6a878c712a8,0x00002615beecdb4d}, {0x000b0e868dba85ad,0x000964d03b5c6537,0x000cbcf8b6d0fd98,0x0006a16ca9f74a32}, {0x000552ffb8c5dbeb,0x000bf0f20d682f2c,0x0000000000000000,0x0000000000000000}}}, {{{0x0009a64c8deb9f4b,0x000532674c0fe944,0x00001e88fe681603,0x000b8697595c6e13}, {0x0008cf6f513d4913,0x0008c1e3203b6d47,0x000b68db28573518,0x000bdfb9fd4390cf}, {0x0006601496c4bb93,0x0000633f388af7cc,0x0000000000000001,0x0000000000000000}}, {{0x0005258fb2317523,0x00040dacae0a8b9a,0x000ba0560abb741a,0x0008bc6a795d005e}, {0x00096caa47999397,0x000ff04fef1c0b24,0x000b0926ddcefe71,0x0008f281ff3947c3}, {0x000027cc7cc93f3d,0x000e78773c9a3f23,0x0000000000000000,0x0000000000000000}}}, {{{0x0001c60cc85e7257,0x00011fa52f42f768,0x0002f380ec8fe41b,0x0004893bc07fb9d3}, {0x00034451f49fbf7a,0x000388023d1b4705,0x00079c42053de8b9,0x000cf909c04d42cb}, {0x000eca57f6797b3a,0x000cf34d35027c43,0x0000000000000001,0x0000000000000000}}, {{0x00086008351763ff,0x000f9e1103300427,0x000991707dcb32e9,0x000efb21a41fbb4f}, {0x000b5649d55978db,0x00004e4d7b3fa6d3,0x00012196968dee3a,0x0003561c60989b74}, {0x0009c91c53ee540c,0x000b9823a2ee0db7,0x0000000000000000,0x0000000000000000}}}, {{{0x000f6a15601d1f8d,0x000406c4591dc921,0x000b36c8aaaf7c15,0x000834fd3b0d0813}, {0x000e544ef9e76287,0x0002fb609294a18c,0x00008d9bd0198775,0x000cd4816092b24d}, {0x0008b097d39d2d32,0x000b3a5b9f00f218,0x0000000000000000,0x0000000000000000}}, {{0x000da9d6f0979e9d,0x00080741dad104cc,0x0004ee619b7637d2,0x000d71560f5a9cc8}, {0x000b897bb554b4f3,0x000890a210367054,0x000aff63f1f61c3e,0x000cb92963c20784}, {0x0009317afc9acc43,0x0005c1dadb0d3e30,0x0000000000000001,0x0000000000000000}}}, {{{0x0004debc7af95096,0x0002bf8bc26e7cbc,0x000070bd1c43e146,0x00017181a62e8acb}, {0x0001c46b5339f3b4,0x000a2c14c9b646ef,0x0005de576b9f4c81,0x0004f9a155e97645}, {0x0003cfbba219f7e3,0x0009fb1fd4f92031,0x0000000000000001,0x0000000000000000}}, {{0x000bcf11449769d9,0x000ea5acc7cb996d,0x0006bdb653213f43,0x0003a2cf9c396c5f}, {0x000777fb3075bc28,0x0009fab46fa97f51,0x000d80cd600dc1e5,0x0008ba6a57a9d490}, {0x000c9975b8111175,0x00067a2ad8270658,0x0000000000000000,0x0000000000000000}}}, {{{0x0005e67b8d52ab83,0x000eb2049665d86d,0x000b56e1ced19993,0x0009c1fc7a62ba87}, {0x000276fc5cf75dfb,0x00054f5dad4712b6,0x00089fbe0548bd15,0x000d1ee24125ecba}, {0x000176a53fa18f5a,0x0004e18796b5267e,0x0000000000000000,0x0000000000000000}}, {{0x000a0f1a17a9eb45,0x000584e4e5f968ad,0x0008e12a3e089107,0x0009c73cd6a2ba69}, {0x00002e23b2a1f1ee,0x00028e9adc43a76e,0x00062c6e3d7526f4,0x000d0557ab8af09d}, {0x00058b1d337cd537,0x000000e54434b827,0x0000000000000000,0x0000000000000000}}} }, {/* digit=27 [{1,2,3,..,}]*([2^108]*G) */ {{{0x00036c3a6abc7042,0x00004a11953f80fe,0x0000b4cc57cd15f7,0x000df44d3d3a8bb5}, {0x00015b5099398347,0x00081f3a553789e2,0x000d0115f2bce30d,0x00090b7f91f0853e}, {0x0007ec29320d53ac,0x00085b63e7bfbe8d,0x0000000000000000,0x0000000000000000}}, {{0x000cdcd80232c6da,0x000d8fc636cf5e56,0x0006e4c3d9621241,0x000b84a86812f9d5}, {0x000287741d3de81f,0x000ab3d77eb50a79,0x00048627cc80386b,0x000a1901afee8f37}, {0x00095591fbf5ceb2,0x00080aed0c8140dd,0x0000000000000000,0x0000000000000000}}}, {{{0x0002fcdd07efc38c,0x000c9ad8b1dbd166,0x000af6b6e1566c06,0x0005c4ad28998a9b}, {0x000b12d2005dbca4,0x00009acb17fcd947,0x000af2e6bf7b35f6,0x0000b8a8aba325eb}, {0x000302e3f599df52,0x00080d2bf9b973e4,0x0000000000000001,0x0000000000000000}}, {{0x000aebd112a3c0c1,0x000c408868630c25,0x000af7c4f6ba5529,0x000d49e0f5657b1a}, {0x000da3fa70b84c0f,0x0009f530044d86ec,0x0003f7ec59dce6d3,0x0004bdaf73433951}, {0x00022dd61822c292,0x000466acb0786ece,0x0000000000000000,0x0000000000000000}}}, {{{0x000bab3d6168fc90,0x0007cbb6b2be9857,0x0001cf2ccb017656,0x0001630304c6ccfa}, {0x000ab9344dbdd28a,0x00075f0fec3093b4,0x000ff2494e7a4029,0x000ca3bad1c9c568}, {0x000b17aa4b7bc2e4,0x0001be8844e06c12,0x0000000000000001,0x0000000000000000}}, {{0x000748f359f51efa,0x0006b016fa4643bf,0x000de784a5c3f1e9,0x0006412db1ab3996}, {0x0002a042b01eeae2,0x0005a0d3a2a424ea,0x0009b9a7aeefe348,0x000b209614c9d52b}, {0x000556ff1e6afd00,0x0001e2290dec8fe5,0x0000000000000000,0x0000000000000000}}}, {{{0x000dedb27f20e8c4,0x000f535a0fc33855,0x000788ccd8803e8a,0x0001f7d6e10cabd0}, {0x000355f889d7fa1f,0x000583e3030487ee,0x000f3dd1885d800a,0x000f09ae9a4a2fc9}, {0x00054fc302887b5b,0x000678d91181d3a5,0x0000000000000001,0x0000000000000000}}, {{0x000b146d6cdca631,0x00046652f280d553,0x000e0b73d63dfaac,0x000399cd0d77869d}, {0x00057ba5ffe6aa8a,0x000ffc1da65c61b7,0x000738771cf6c9ea,0x000620ae124834d2}, {0x0006504def184b95,0x000d761c974cb47f,0x0000000000000000,0x0000000000000000}}}, {{{0x000b12824a32cfa1,0x0009c552049f6e5b,0x0002cf47aab27c7f,0x000c49affe61e35a}, {0x0002247309f28abd,0x000d8f5d3d157087,0x000c6b864fe18c22,0x000addbbfad216e7}, {0x0006e83c0b6f0f26,0x000fd5df730de2cf,0x0000000000000000,0x0000000000000000}}, {{0x000d5ed49aa6d720,0x0003b8bf56601c9e,0x000932a05f265897,0x000b6e7997e501b5}, {0x000a12ea7ac82871,0x0009ee973ffc91a5,0x0008bc4a89b5c6c1,0x0003ff7cc4ea3cde}, {0x000dd04f7b689969,0x000d1dbe61024f53,0x0000000000000001,0x0000000000000000}}}, {{{0x0009c8cbe80fbbcf,0x0001820704f59919,0x000a2837d2432345,0x0001d7c57c052221}, {0x0004dd7abcf6f7fc,0x000ceb0c9ac384fa,0x000cbcbae19fcf70,0x00044465c2e5cd22}, {0x000a11ffc8ca98c5,0x0007b72231b3018f,0x0000000000000001,0x0000000000000000}}, {{0x0005516f6500002e,0x00015b8dc7f05ee2,0x000111229aa6356e,0x0006bd0e54525c30}, {0x000dcfc5ecb4c0df,0x000355785f844693,0x000ab74792af79c9,0x0007357c34213765}, {0x00008a7b5867734f,0x00069a6d820a3083,0x0000000000000000,0x0000000000000000}}}, {{{0x000b3a34b0a583e8,0x0004109d1c2a05b3,0x00056d185c8227f4,0x000c30eb0f8b309e}, {0x000e5f0d836e7213,0x0002fdae4ffef15c,0x000257bcdd2d7309,0x000dad1ff9a8d757}, {0x00098efcc192b734,0x000fe0e5b46f1d9f,0x0000000000000001,0x0000000000000000}}, {{0x000ec3057c0b1268,0x000e1eea4fea07c8,0x000ac5ab201c4cbc,0x0001b75086654bcd}, {0x000e612c2aee9474,0x00065fa077070bf8,0x00015dd97afeaab6,0x00088802f9979ef0}, {0x000c9b3109eb556d,0x000e513d135fae08,0x0000000000000000,0x0000000000000000}}}, {{{0x0009b9b53c1efab4,0x000babd37156ff65,0x000a115d2c7f8338,0x0007371c9d1175b5}, {0x000a353c22d6aa92,0x00079ee37be5b07d,0x00020293585421cb,0x000abe2b0a938ac9}, {0x0003622f3d489e47,0x000ac9ccd5811b36,0x0000000000000000,0x0000000000000000}}, {{0x000cb54f0f506ac3,0x000feebf83fb7441,0x0007d9fa2d5527b4,0x000b40376d4a3597}, {0x00045e4619c87f8a,0x000b913b27d590e9,0x0001da0e8861075a,0x000dd8fb707f389b}, {0x000140b6fe0beb49,0x000bf7392dd17235,0x0000000000000001,0x0000000000000000}}} }, {/* digit=28 [{1,2,3,..,}]*([2^112]*G) */ {{{0x00082a01cdf12457,0x000bf550e3442670,0x00027cfd7b191616,0x0009bf54426bd9ae}, {0x000375f468d0ec29,0x00095e63540487ca,0x000f558b93aa7dc6,0x00028f48edec9322}, {0x0007ee742818f059,0x000d23aca5b08895,0x0000000000000001,0x0000000000000000}}, {{0x00018972085008e4,0x0009e445a0130711,0x0005bf246e5348cb,0x0008ccf1f5c183c6}, {0x000f2e9a40aeb3fd,0x00087abdef0fbda6,0x00050f5daf09cee0,0x0003e33344ee90c4}, {0x0004044243abe107,0x000b8f02a065d1a3,0x0000000000000000,0x0000000000000000}}}, {{{0x000b66d418145236,0x0007896ea70c3fff,0x000cb17d54fc5491,0x00042a641eaf6e4d}, {0x00096b15be10c7c6,0x00011efe5f993282,0x000c04930829e9c6,0x000a5f18e8613cde}, {0x0007985a51a7c38d,0x000b8f3536d908ab,0x0000000000000001,0x0000000000000000}}, {{0x000ce50b447f989e,0x0006725435f6e48e,0x00060505d7413d04,0x00051fa907efc4e5}, {0x00091cc601ad28a5,0x000eeaf4b18fed33,0x0002e1a4338a8549,0x000b61868d3372c5}, {0x0003a511bce70bb6,0x000e1f5c8d75eb9c,0x0000000000000000,0x0000000000000000}}}, {{{0x000d68d2a3e7e05d,0x0009bf6f65a63322,0x000368db479d7794,0x000e22f5738f46ed}, {0x000947212d465e52,0x000bb783e24758d1,0x0009d33d677a59c8,0x0005609046041b23}, {0x000f6497a9c2f277,0x000e7a9be5339a8d,0x0000000000000001,0x0000000000000000}}, {{0x000804d780847503,0x000fb6bd5cd190b5,0x000d58769b6bfbeb,0x000a5b2366d25685}, {0x00084206ac283f9e,0x00045e93a909d14a,0x0007818e03b612f8,0x0005061fa312c680}, {0x000501efdeb98070,0x00043cfa3670b66b,0x0000000000000000,0x0000000000000000}}}, {{{0x0008296f30c9bed5,0x00099a4bb11c1f32,0x00015b4084960501,0x000c50ce53a7ca7c}, {0x000f50a2c1da281b,0x0002c0e34f682873,0x000f21f441021705,0x000e9f354fbc9c5e}, {0x000d7990a0bba954,0x000ca402432a326c,0x0000000000000001,0x0000000000000000}}, {{0x000e6dddd976d76d,0x000a57e55cac7b2b,0x000da37392c8a3b8,0x000fecd4ec1dc93e}, {0x00009cf4f78c92e3,0x000ff689fefedf3f,0x000abd5033740521,0x0000df4087ca092d}, {0x00002763eb9e4e11,0x000689f3f329b79d,0x0000000000000000,0x0000000000000000}}}, {{{0x000d09236f94e981,0x000f3b87c2492089,0x000090559806590f,0x0006b638cb962e83}, {0x00043caf0b4cf40f,0x00066f61c7a2faca,0x000edaa5c1d246d3,0x000b19d9f9d7b0bc}, {0x000d3b97c04cafce,0x000f23bf9f27399e,0x0000000000000000,0x0000000000000000}}, {{0x000b2a804eb31689,0x0009a2a7437938a7,0x000f3c9cd990c2d5,0x000b68b7f843ec1e}, {0x0005141dcc07de04,0x000fdd1e7d56eecb,0x000a099220b61db4,0x0004184b463b9f76}, {0x00076a6a6fd2bcb4,0x00067d87f98ad9c6,0x0000000000000000,0x0000000000000000}}}, {{{0x00025736286ff497,0x0002401f1271e328,0x000981dcd7607683,0x000cfb7ab6548084}, {0x000df4da03d9c990,0x000d822ebf4ae8a1,0x00099db5f23d4a99,0x000f6315e3fb9894}, {0x000021f262e80d80,0x00027457b91d5ecd,0x0000000000000000,0x0000000000000000}}, {{0x0007a0ed90d98205,0x000cf6f6b6c517c8,0x00057c5ae11bc6b8,0x00000efaef845be3}, {0x0005e74813e365be,0x000c8e0106700aae,0x000d776c99ef5ca6,0x0001e3d37bff71e1}, {0x0003a89779b96572,0x000c15ea2a31bd25,0x0000000000000000,0x0000000000000000}}}, {{{0x0000092959940ede,0x000bb4c7bf2ceef4,0x000d604555c30636,0x0003fe5635d8d5c1}, {0x0008cdef0cb902ce,0x000b6f22235732b0,0x000fddf6f7cfc6cb,0x000369004df1a446}, {0x0004ba65bcff1dc7,0x00020adfd4756b77,0x0000000000000001,0x0000000000000000}}, {{0x000afeaa9dfdfa89,0x0000b80d92606c1c,0x0006888e19c65eb3,0x000bf9bb4db51900}, {0x0008e84280b5d191,0x00077a1cb4c3d007,0x00055fc83156ea4d,0x0009f40279edea0b}, {0x000aa5223480bee2,0x000f264b4f70afa9,0x0000000000000001,0x0000000000000000}}}, {{{0x00054382d016c8d9,0x000ec7826f7b17bd,0x000dce64f2832c36,0x000193ae22a16680}, {0x0000aaf6a85c2ab2,0x000f20270252cc0a,0x000f317cc1335b32,0x00003743776e2afb}, {0x000a199000deb474,0x0006bc61591f25f9,0x0000000000000001,0x0000000000000000}}, {{0x00084eebf2800729,0x000608b06a4eb61d,0x000b23e73968bb72,0x000a3ae82e886104}, {0x000d27c8605d2992,0x00033bec6e418a91,0x00029d45f2b49e6e,0x000bd1f4a3f4a9d8}, {0x000bc4ceaeb2f044,0x000c63b1ef09fa28,0x0000000000000001,0x0000000000000000}}} }, {/* digit=29 [{1,2,3,..,}]*([2^116]*G) */ {{{0x000826845611f97e,0x00015b6b1ee54a04,0x000608b1dc092400,0x0009050925698b8a}, {0x00031b5e532ada13,0x0000c41c46df4acb,0x00090c116e05bee3,0x0009642c127307d1}, {0x000365a48b566eca,0x00046d5c3cffa21b,0x0000000000000000,0x0000000000000000}}, {{0x000b8836b9754189,0x00079ea005768621,0x0007bf51510520f5,0x000bbc0ca43d38cb}, {0x000c9fe21891a0a4,0x000242b093687446,0x0006d618feab8811,0x00047a921f31cacb}, {0x000cb09d3cf611aa,0x0007d8fef9a8efc5,0x0000000000000001,0x0000000000000000}}}, {{{0x00042c81af50749b,0x00081540e019366d,0x000d6072e7b7487e,0x0004156c32da913c}, {0x0003df1e87478e7b,0x000880f5ccb21742,0x0002347ca344dd54,0x000d15da2c269018}, {0x000993e2887d2337,0x000379604cc23f8d,0x0000000000000001,0x0000000000000000}}, {{0x000778d40c2ec9c0,0x00027ec9dd1808f9,0x000dcd7b63f43450,0x000cf65f198a63ab}, {0x000d3a7a4c38803b,0x000476f99f1130c2,0x000d6b9c1ea5019b,0x00034f67377e991a}, {0x0009047dfa9f5ad1,0x0005dc80641e2fd9,0x0000000000000001,0x0000000000000000}}}, {{{0x000de0d9dfa7af75,0x000eba7ea5710283,0x000dd5435234652c,0x0006f821b8a36856}, {0x000c319e00261b58,0x000ed079e56ce309,0x0001099e0f75ac31,0x000e2442020d51ff}, {0x0008b83fa0c077ae,0x000e6fc85e1f8724,0x0000000000000001,0x0000000000000000}}, {{0x000872b798445d10,0x00032b311d3108af,0x0005040c97d2ca2a,0x0005703d4fa4c2f0}, {0x0006980d5eb27761,0x0005f074a536c8c1,0x000181395daa1e3b,0x000b672dad89bda9}, {0x0001f3d94395bd4f,0x0004b4c4a2c81ef6,0x0000000000000001,0x0000000000000000}}}, {{{0x000924e7856ff846,0x000ee4f61f664ccb,0x0005ac67cb02e404,0x00050da76b002de5}, {0x000c4537e3c3c875,0x000c36c052b6b43f,0x000b204b2d5ce01c,0x00088e7f6d0e0c5b}, {0x000c188bbf930fde,0x000168056f87d909,0x0000000000000001,0x0000000000000000}}, {{0x0001106b668bd3a0,0x0008dce76203aabd,0x00002fff3110182e,0x000f7d1e1307d3fa}, {0x000347101339296b,0x0004a22e456ed2ca,0x0002d011b668eed2,0x000b79cf95e5e410}, {0x0006693b0681d10c,0x000355f94e08ac6c,0x0000000000000000,0x0000000000000000}}}, {{{0x000323242b9413a5,0x000d8925b57cdbcc,0x0004d31e6960afac,0x000cc1c8075e88b1}, {0x0003a4d853d5880e,0x000c2d17b4e21339,0x000c35a1d02b3405,0x000f7f4eb22a29f6}, {0x0001b6570763f945,0x00008a38d9e91699,0x0000000000000000,0x0000000000000000}}, {{0x0009e262a8faf74b,0x000d89cdb707d091,0x000c28362e27b3cc,0x0000a8d2e31adec3}, {0x0004f2e5340b0d97,0x00076d44ac11f1ff,0x000ddee42bd388ab,0x00052165e718528c}, {0x000c2384a7cb055f,0x000e3bd81cae87a8,0x0000000000000000,0x0000000000000000}}}, {{{0x000e0ef29067ec5b,0x000b3efb1759268e,0x00093d33d241c82d,0x0005ebc6b912da50}, {0x00004cea7d557bb1,0x000a95c0c2531329,0x000338d1728bce52,0x00023e934774d703}, {0x000bdaa179ff6232,0x0009c05a25267ea4,0x0000000000000000,0x0000000000000000}}, {{0x000b3f1bf490cbf7,0x000ec049cf21d24d,0x0001567c730a18c0,0x0008c3e0f359d391}, {0x0004ea1bf7eca8f7,0x000252d4d89f9aa6,0x0007a2e5b2ffd6d4,0x000e70d5197d3cf7}, {0x000ac046e420f1fd,0x000f82fbaabfd6c4,0x0000000000000000,0x0000000000000000}}}, {{{0x00023d833bf81b28,0x000064787960d20f,0x0001e23da2c1a82d,0x000fca0df31fd1ab}, {0x0000d67beaa32632,0x0009e45d2648f548,0x000d563bb162f9bb,0x000110e02089d434}, {0x0007082d3a10eef0,0x000cb7b7735d1d64,0x0000000000000000,0x0000000000000000}}, {{0x000d95b89701e6ec,0x0003bbe61d29d940,0x0001c7d5b4e68b4d,0x00012a5ad78df4bc}, {0x00047d83302cabd6,0x00011140b2809827,0x000211a754f62795,0x00041d43610e16e7}, {0x00099e665f0dec95,0x000ee6baca9f0f39,0x0000000000000001,0x0000000000000000}}}, {{{0x000657257b2d9252,0x000915208861aaee,0x0008adfc02b5d4bf,0x000f78398b2a8792}, {0x0002cd1929e3951b,0x0001878fc66ac2d8,0x000a1972453f26a5,0x000c0ebd963c67c6}, {0x0006feb8829e6f9c,0x000c986a8aecc7ab,0x0000000000000000,0x0000000000000000}}, {{0x00030636d8df74f1,0x00011de6a5beb09f,0x000247b37675f6af,0x0003d122a04301fc}, {0x0003f577167d7789,0x000a69addd4d974f,0x000f8be983fc60de,0x0003627055a8d35b}, {0x000c83aaf95c80a8,0x000a9aa21f06b151,0x0000000000000000,0x0000000000000000}}} }, {/* digit=30 [{1,2,3,..,}]*([2^120]*G) */ {{{0x000c1e136664d27c,0x000e853cf04eac1d,0x000599f98901c4f5,0x000f0e3ecbc44867}, {0x000ee5a12a7f834f,0x000066c152851c12,0x0002df97ca61be6f,0x00027153da2c7383}, {0x0003e882e14acdbe,0x00030b87567338b7,0x0000000000000001,0x0000000000000000}}, {{0x000fe8148de5b00a,0x0003a405fd56d3d1,0x000e986a7db49ee5,0x000cf7bc11101981}, {0x000a9750760e2695,0x000815cb90b6aca2,0x0009f299f5ace2a4,0x000d6b06b61bc3dc}, {0x0002e5c223b28698,0x000c0b5687880a6b,0x0000000000000001,0x0000000000000000}}}, {{{0x000f552c0e5d59cd,0x00029aaaadcddf1a,0x000f071e91a160c3,0x000bbaf777f33e93}, {0x000696e836178f9c,0x00030ecc6d74f3bc,0x0002571349ec6474,0x000dbbec63ff9e68}, {0x000eff8b43f624e0,0x0008000d19e23a64,0x0000000000000000,0x0000000000000000}}, {{0x00060d53484cb54f,0x0000d83eff3832ce,0x00012f600dae89d0,0x00089d2df8745dbd}, {0x0008a48217cd83eb,0x0005ce0f8ae79b86,0x0004021c2c4ae44c,0x000ea980ca2b0fe9}, {0x0004146745ab9482,0x0001c2cffa33fcf0,0x0000000000000001,0x0000000000000000}}}, {{{0x00076fd51fd99bf9,0x0007e3a2b01fa7b1,0x0001a17875cbebf2,0x0008df20ca98073a}, {0x0001c738732531a0,0x000c360b05cea958,0x0008986bad316bfd,0x00009591db5fb8a6}, {0x0008ce8516941db2,0x000cd50df495ad83,0x0000000000000001,0x0000000000000000}}, {{0x000d46b24a5b2933,0x000a4af0d09b27b5,0x000e34ef392f2b04,0x00028d0cc4e0cb50}, {0x0005bbe1270619c0,0x00002d927660b899,0x000c444a9beaf922,0x0003686effea3a61}, {0x000321e427cc238c,0x000fe609075147ce,0x0000000000000000,0x0000000000000000}}}, {{{0x000e9dd164c62b53,0x0001878a3599a216,0x0000821091d05317,0x0002cda324ef2697}, {0x000e94950f2f16ed,0x000815b553eaefd2,0x000f8019f00612dc,0x0001930eacc547c1}, {0x0006fc4a1fd1730a,0x000db88252d52d13,0x0000000000000001,0x0000000000000000}}, {{0x00077522a6c4bee6,0x0006b12deb38426b,0x000ca869197aea9f,0x000c43193823d16a}, {0x00028f12c9d38187,0x00031f43dad5cc98,0x000728a436529c3e,0x000863d40c6f0781}, {0x000da1798bfbb097,0x0001e17a19693394,0x0000000000000001,0x0000000000000000}}}, {{{0x000a20633820f8b6,0x0008884ce6057395,0x000b9e9ac4298b05,0x000f80c79f28e7bc}, {0x00012abb15751770,0x000ce75763d01472,0x000afbe67296f82c,0x0002a2950d9f8034}, {0x00031ca6f1179141,0x0008bb87c616f997,0x0000000000000001,0x0000000000000000}}, {{0x000f27dc8004bd5d,0x0004fc5fa5d017c7,0x0009fdb4deb95bcc,0x00051c1e39917e40}, {0x000cfbefa777d300,0x0006ebd51f3f36df,0x000089ed9696a852,0x000c58a6c0bc16cc}, {0x00093efb56723f03,0x000f77e4f7a67531,0x0000000000000001,0x0000000000000000}}}, {{{0x00082edbf63cd0fa,0x000fb67ff0d41a00,0x00076aa53cf1522f,0x00099dda453dcda7}, {0x000bf634bcd8a3ac,0x000f09af12ca31a6,0x00045d3da6aee65d,0x0000b2e1c131b960}, {0x0001888166f3c7e7,0x000d21cb58f8b972,0x0000000000000001,0x0000000000000000}}, {{0x000f3e0321dcdf91,0x0009a8d4da7b1151,0x000e3a95788cafbe,0x0007071e39c010af}, {0x0004b05cb3faf8c8,0x0008a702fbafcfc0,0x000618742c775b70,0x00068aab53d65b3b}, {0x000b27ffbb84f938,0x000a7508491b708b,0x0000000000000001,0x0000000000000000}}}, {{{0x00020328d4b15dd1,0x000274b581eaa62f,0x0008fb2a285d269e,0x0006ea89604b1779}, {0x000933aa53ad75b2,0x000fa62691d5119e,0x00067e03e002a949,0x0000629215018ba1}, {0x000ae2796195dffb,0x000282dc1f93eae4,0x0000000000000001,0x0000000000000000}}, {{0x0000977c61f7743f,0x0008f7654950f798,0x0009f0fcf77422ba,0x00070562b7dc1d4c}, {0x0008f0b2f76176b9,0x00094ad6c12de606,0x000d53dd34579508,0x0001fc63f78fe569}, {0x000a90b5214981ae,0x0005ab902dadf9f2,0x0000000000000000,0x0000000000000000}}}, {{{0x00006fc86d7474a9,0x000491c759885f54,0x0002d4cddc55bd2a,0x00061045c35aa122}, {0x0007a2154985eb54,0x000f0dcbe4188b45,0x0006a7e235148dff,0x0006a2535a30d70c}, {0x000e2be337d8e901,0x000cf899a19ee96b,0x0000000000000001,0x0000000000000000}}, {{0x000dc1860747030f,0x000a1d519771baa1,0x000e6bf7f8dea4c9,0x000b88d5c44825c6}, {0x0001648270d80fd4,0x000d7c088d619d7b,0x000e67f50ac4887c,0x0009d1ac72f9cc2c}, {0x000dce091aafa6b8,0x000ac9b9365de8af,0x0000000000000001,0x0000000000000000}}} }, {/* digit=31 [{1,2,3,..,}]*([2^124]*G) */ {{{0x000c9884018b1bd5,0x00017e335350476d,0x000f240ea34a105e,0x0007225c0ca7c1ed}, {0x0002e60ee9bcde0a,0x0001b7a04f8d5abc,0x000d636ed201196d,0x000fee08dcde421f}, {0x000648f1c3a41da5,0x00014b37a2b18a4d,0x0000000000000001,0x0000000000000000}}, {{0x000574ca3d13216a,0x00000c8f4aa46ce2,0x0005e6cb8b142b50,0x000aeecc2cc007b3}, {0x0008b139d4602d18,0x000857b6e6fad62b,0x000703a0b8035154,0x00047dfe5be4aaf5}, {0x000e255f15b88d9b,0x000ceeb42f23b0c7,0x0000000000000001,0x0000000000000000}}}, {{{0x00027bf41035c3be,0x000003d6c228d698,0x000ac8482db53bd6,0x000f6c6cedd6d84e}, {0x00055554b59c1199,0x000b3dd0d5c80a25,0x00098fd9a255d70b,0x00088ce8ece5b616}, {0x00010e4ff0160238,0x000e8b21f2b5b409,0x0000000000000001,0x0000000000000000}}, {{0x0009be6e93956f12,0x00028be014bad7ba,0x0007941a6f1d6c8e,0x000374aa983d3be4}, {0x0001ab03efe8a93e,0x000ecc1517778750,0x000a07f3863f0102,0x00022339ade08ce1}, {0x0002e138fb118165,0x00037ded66083914,0x0000000000000000,0x0000000000000000}}}, {{{0x000be450955d0f49,0x000350db3612b4e4,0x0008b05c6937d0f5,0x00091d0bc00589e9}, {0x000f08134602fbb3,0x00072898cb46a43b,0x0000c3f425983612,0x00092a9319d102b7}, {0x0002adb9889640c9,0x000f69984da61b9f,0x0000000000000000,0x0000000000000000}}, {{0x000925b413e1ae3e,0x00046d808d55308e,0x0001e8e95f85495a,0x0001aa328926b87f}, {0x000e6f7c0b2cf48a,0x00097c234327b453,0x000bc1b584c452ac,0x000ac04a1db1b2a7}, {0x0002c2df96a4716f,0x0008b35f6c998afc,0x0000000000000001,0x0000000000000000}}}, {{{0x000c246de542c405,0x00006abed2f33bb7,0x000d46decdec7b50,0x000afeed50c509c6}, {0x0007109502cf683e,0x000fa7b0916c8d21,0x000971ce284eb826,0x000b5478a9a06ef3}, {0x000dbb05d7e812b4,0x000fa9bdf3afd0be,0x0000000000000001,0x0000000000000000}}, {{0x000c0e4a6519aab5,0x000d79de9fb97617,0x0002d46f889510f0,0x00025cb75085caf9}, {0x000f963379f4c576,0x00002dc4877679ee,0x000748161e8da062,0x0007933c7094d95a}, {0x000527ab96f198e7,0x0000a23cef9bb67e,0x0000000000000000,0x0000000000000000}}}, {{{0x000254c4bef57a31,0x000f8fe05ebbca4c,0x000036d19011dab0,0x00092f09f97449f1}, {0x000feb784d8ec601,0x000551e5955591a4,0x00088c74b266204b,0x000fefa58c8cd4d4}, {0x000954c3d29f9c68,0x000262f04bf8acfc,0x0000000000000000,0x0000000000000000}}, {{0x0005e5c9d99f906b,0x0005ebe8f2ee55b8,0x000f127eee6b4d59,0x0005b10ba97a057a}, {0x000c7680e692309f,0x0007c47d151a8543,0x000975bcc38cb298,0x00056b40037e7ed1}, {0x00069095953732ea,0x000e079710f9d766,0x0000000000000000,0x0000000000000000}}}, {{{0x0007ef5561843b50,0x000725adb4b17e58,0x000223554b9e6db7,0x00040d6a298840a9}, {0x00089b9987d3e8ea,0x000c544359088f19,0x000712498c4e6798,0x0009d49555742687}, {0x000531911aeb4757,0x000c25edd6bd8c42,0x0000000000000000,0x0000000000000000}}, {{0x000da2be384ee90b,0x000ed1578452ef17,0x00026ec7e64f3506,0x000d93fd400c530b}, {0x0006442c14bcb0a9,0x000bc44330eec280,0x000b7a321d894abd,0x000383284ca21784}, {0x000aabf2cbd2fe67,0x000a0b333a314bbd,0x0000000000000001,0x0000000000000000}}}, {{{0x000deccb4cc0fcd3,0x0002b5d6f0d87e14,0x00022447f7757c4f,0x000f03b5e4d05426}, {0x0003dcf9d56f98d5,0x0001c6d571746b68,0x000648164a40c197,0x00086a775d32054f}, {0x000bbccdf9c7e93f,0x000ab95b370c616c,0x0000000000000000,0x0000000000000000}}, {{0x000ad22f9be04193,0x00049e68cea75e3b,0x0004683245da929e,0x000316e38a93792f}, {0x000965e00dbe19e7,0x000e9c59fb61ef64,0x00094c5036fbab0d,0x0009e4c2c8f5993c}, {0x000c76d4a049b3bd,0x000c781dc2d523d7,0x0000000000000000,0x0000000000000000}}}, {{{0x00010cba8003a62b,0x0002963dead37561,0x00024e572ee261b1,0x000924c14f710c53}, {0x0003a3234879da4d,0x0000242c6b2bb72d,0x00025965319d73bf,0x000c5d438ac356b7}, {0x000eb1ea69c1467e,0x0006ea40556d55e4,0x0000000000000000,0x0000000000000000}}, {{0x0003bb0cfbfbdc6b,0x000292f755482f11,0x000b750229b1fdd8,0x0006dd9d36eb56b3}, {0x0009fd65055f0875,0x00005fbea1ad24bc,0x000b5ba29626eb13,0x0004c9855409fcec}, {0x000000d0af627326,0x000b249d561b2281,0x0000000000000001,0x0000000000000000}}} }, {/* digit=32 [{1,2,3,..,}]*([2^128]*G) */ {{{0x00097f8c2da756c3,0x00065716b51e78af,0x0004d4e4ac9bb4d7,0x000be63f12ece85a}, {0x0007f2c2556ca2a2,0x0002341b0c191c3b,0x00063796c15ecee1,0x00092e302dd7df66}, {0x000d162a4ce9cb82,0x0003dfa7f8ba9276,0x0000000000000000,0x0000000000000000}}, {{0x000403973587aa55,0x000a9956dae839d8,0x000d9da7dcbd9d38,0x000d0fffb69b8acf}, {0x000544e0adb2ad93,0x000b2ad644f74f04,0x000e7d5b5de013bb,0x000f944ef674d489}, {0x000e01d0ea2d2bd3,0x0008aedd32d1ec0a,0x0000000000000000,0x0000000000000000}}}, {{{0x0003c3743a6b3bf8,0x00083b2cea274d8e,0x000f6accb4a79b20,0x000ac9cff7eff159}, {0x000c5bd1a458b1a2,0x000af5afd8c30597,0x000e95f67ad0a34d,0x000ffcb5f547ad0c}, {0x0002c927ef492633,0x000118d70d201bd4,0x0000000000000000,0x0000000000000000}}, {{0x00025271d14dfd7c,0x000f83511be77473,0x000e33f2540532d9,0x0002d9c50e1e6624}, {0x000b9f8f4394e620,0x00085289919c8fa1,0x000d6412359d3b9f,0x000a4c00c9ead88e}, {0x000626daa054c125,0x000853e0db1f33bd,0x0000000000000000,0x0000000000000000}}}, {{{0x000ad013227cbee4,0x0005d963a674d5e9,0x0002422839e1c90e,0x0006f11c073f8abd}, {0x00051cbde443fb90,0x000f94add68e37cb,0x000d9cdf247fb6d7,0x0003b3ec024c71cd}, {0x000015c9b5032da9,0x0007607e0d83a94a,0x0000000000000000,0x0000000000000000}}, {{0x000d4287c9083b11,0x000b167379dfa59e,0x00092871f05ea23f,0x0000a530c1fbcc90}, {0x000c9b670aaadfc5,0x000840b4f012b3f9,0x0006d74574236725,0x0005827f0582ac31}, {0x00047f13870e7720,0x0006f314a9061f10,0x0000000000000000,0x0000000000000000}}}, {{{0x0003be466658f617,0x0009fd565e43add7,0x0004a046e438ce3b,0x0007e9edef2d69e6}, {0x0006c7f11d4e7b33,0x0009fce23db4d264,0x0007ee69cfe36cf0,0x0009d497797ff857}, {0x0000fa9f71e1b23f,0x0002d2813fdfceba,0x0000000000000001,0x0000000000000000}}, {{0x0005801d34f0db76,0x0008b9ba1d6ad8bc,0x00038f8437efa8c8,0x000755dc58d2c493}, {0x0008ea5d4147adf5,0x000454e0d19f3138,0x0005174d880f0ef2,0x0006f4ab4400ed7c}, {0x0002f97c02972f59,0x000bb7fd1f05bd42,0x0000000000000001,0x0000000000000000}}}, {{{0x000f26521378e02f,0x0002d730a6852468,0x000763f810a221e5,0x000f48636e9cb246}, {0x0004c1b9e4959290,0x00093bb4ca5e4a52,0x000f2a6103eedfad,0x0009e3ea2bb0a0a9}, {0x00013663d597d7ac,0x000a98c50bf00061,0x0000000000000001,0x0000000000000000}}, {{0x00050b19a3ef90bc,0x0000ea69cbaa303c,0x00074f8f2fe993d5,0x000223c8be835b07}, {0x000f455e7085ef84,0x0002207ec6b0871e,0x000e48bd79a714e6,0x000daa1613ef3b51}, {0x00098f36229d3dd8,0x000c2d9134c94bcc,0x0000000000000000,0x0000000000000000}}}, {{{0x00050a19f5342c54,0x000dc653d78301f8,0x0006bbf10f389ca9,0x0004326e54a5af67}, {0x000fdd8a13b29709,0x0008aa3fafda8b65,0x0006c2e3f7baf8bf,0x000bca4111083f35}, {0x000cdf78842a34d7,0x0002a973106a6473,0x0000000000000001,0x0000000000000000}}, {{0x000155f05f4ec88f,0x000ffd8679f932ba,0x000e00ae69c605da,0x000b7c72ba823e0d}, {0x0009e0bbb62edf8b,0x000f7bf5bd871069,0x0004e610f36c3cf4,0x000e41a06519118f}, {0x00014868b2ff5976,0x0000f7b8d8554854,0x0000000000000000,0x0000000000000000}}}, {{{0x0003e5d502754293,0x000e9ee9e0f2543e,0x000a3731f423dc07,0x0003b8bc5bf91184}, {0x000726f4ea8f1d1a,0x0008035844d23059,0x000c7266e29e66af,0x00082574f0c5767c}, {0x0001a6dd0e57d5d2,0x0004e537115bccdf,0x0000000000000000,0x0000000000000000}}, {{0x0009f7ce1bfb6728,0x0000ccb130bc8170,0x00039a62c614cf63,0x00068e187476935f}, {0x00034de841f4a723,0x00011647b88ac5f1,0x000e09f54f07f6bb,0x000f505a8bf2adfb}, {0x000d75a5f605b64d,0x0000df9bbeb2b499,0x0000000000000000,0x0000000000000000}}}, {{{0x000308733efc5f8c,0x000b75cdb37e83e5,0x00060b5bfda48081,0x0009f06138365296}, {0x0009688a8974b9f6,0x0005444cc05fb9ec,0x0005a67f252002f7,0x0009664675a1899c}, {0x000b6d7be11db7cc,0x000549e5e85617c6,0x0000000000000001,0x0000000000000000}}, {{0x0000536e04ec0d89,0x000ceb7897a84665,0x000b8acad3957bde,0x000ba89439f416b8}, {0x000cfde12e814bb4,0x000a77e0ef45c679,0x000f35bbfcd091bf,0x0009f3ea6cc5ae92}, {0x000f66583ff4f9db,0x0009a867f0fed315,0x0000000000000000,0x0000000000000000}}} }, {/* digit=33 [{1,2,3,..,}]*([2^132]*G) */ {{{0x000487d30649cced,0x000796a5efc98a70,0x00086f3d00556482,0x000c177d81ed5742}, {0x000f3693c918841a,0x00044078e141f63f,0x000ad9ccb0cceba5,0x0005cd9ca803f396}, {0x000a3b9f81f2f890,0x000c5b4318691bb9,0x0000000000000001,0x0000000000000000}}, {{0x00076e3095e41a52,0x0001ffb6fd45a8f8,0x000a8a0715ef8788,0x000192a0b8d73d7d}, {0x00086ca88981c074,0x0000f41a80dc66d0,0x0002bbb8f279d460,0x000cb55640383488}, {0x00052b11c10c7a90,0x000053f89b04d855,0x0000000000000001,0x0000000000000000}}}, {{{0x0002e1e8d88792dc,0x00022e3ae581427b,0x00090f869db2e712,0x000e06689d393376}, {0x000702d537bfdb1c,0x0007346bbf1a9bff,0x00090f54aeeb8464,0x000273c9dd468a0e}, {0x000c871a654e3afa,0x0007465945d8c3b6,0x0000000000000000,0x0000000000000000}}, {{0x0000e770af4a5960,0x000be4ac70e87a10,0x000797d6d911c87d,0x000533fb961a5c5e}, {0x000b8548c0001c5b,0x0009d47191b560cf,0x0009eeca65c8463a,0x000ecad37d2137d3}, {0x0000514ad716bab4,0x000f8789ad5bc27b,0x0000000000000001,0x0000000000000000}}}, {{{0x000dbc583693bf30,0x000ef8d24b6766c6,0x00095890706d31b0,0x000c51cce3a35296}, {0x00080b8ed7618c90,0x000973ebf17cff3a,0x0009c68d473b1c44,0x0001098525e43a12}, {0x00074031f5036c9f,0x0001d33955ea92c3,0x0000000000000001,0x0000000000000000}}, {{0x0006f1c314ce3a37,0x000a4064ddf24cf4,0x00070db52569e1fd,0x000405305ea2c55e}, {0x000d5f14297acf89,0x00046ea96e034f59,0x000622a42888331a,0x000a102ad1347dc4}, {0x00088a514e007741,0x0000461db8ec7cfe,0x0000000000000000,0x0000000000000000}}}, {{{0x00023847d8cf0718,0x00021ccb2c301d0f,0x00024b1883c46a31,0x00063cce64fb5faa}, {0x0003cc10bc090432,0x000510506a731fce,0x0009a05134986c0e,0x0003aa30a907d289}, {0x00071f165d859243,0x000eeaa5074a4066,0x0000000000000000,0x0000000000000000}}, {{0x000b1d8c9f3b369e,0x0008874f03f7bd39,0x0004a870054ed9a2,0x000756adbd121753}, {0x0001a9a0d0a37510,0x000529605385faa5,0x000c2eddf5c089f3,0x000a130a237e15a5}, {0x00074ff2cbd316fb,0x0007ee2c9d3ce137,0x0000000000000001,0x0000000000000000}}}, {{{0x0009dbdc68f3280d,0x000657e090c25dbe,0x00024c6421981e70,0x00037a5a5d0a99ac}, {0x00037fc8c760c5df,0x00044d1a53e37845,0x000ff43dddfe06f5,0x000e4ab44983d93f}, {0x000c0915a82bb80c,0x000646c74033c3a1,0x0000000000000000,0x0000000000000000}}, {{0x00004b5d5c7ce211,0x0001372b933ba5de,0x000ea64d116a103a,0x0006df2d3d823414}, {0x000619b7a1bf8333,0x0006eac1655d2034,0x0009aeedd521f9b1,0x0006d98d98725948}, {0x000610e8ae934636,0x000efd7b215cbea4,0x0000000000000000,0x0000000000000000}}}, {{{0x0005d0308e1127f5,0x000cf03c8e2019c4,0x000aa0237cf6545f,0x000764372510cd18}, {0x00097139d47739de,0x000a85188927140f,0x00037dc9b8b5e192,0x000b2545731c10b5}, {0x000991ea59d03831,0x00067dea66743632,0x0000000000000001,0x0000000000000000}}, {{0x000cc6866cf98c39,0x0009016f3fd54524,0x000592bcebafd818,0x0002f06cc34bdbb8}, {0x000b6cb2e7a209f5,0x0005749dab7ee649,0x00076406958e2abb,0x0009516d049dfaf2}, {0x000de5f7e8adfc4b,0x0007ce97062d4c5e,0x0000000000000001,0x0000000000000000}}}, {{{0x0007da121df0699c,0x000ad3597a95de87,0x000181d213d52a92,0x00002da71c92de4d}, {0x000dd3803396793e,0x000c8761f332f0e0,0x0005c1e0d83b70eb,0x00048cf70527f5a7}, {0x000ceb82fe3e31cf,0x00029a56f1047f6a,0x0000000000000001,0x0000000000000000}}, {{0x000ae721531eb7f3,0x000c70c79169f267,0x000d345b58d29bb0,0x0006c1daec3533a3}, {0x000115913b369665,0x00099820ca585f3e,0x000623473863b5d7,0x0003e2b952a9549d}, {0x00011f22279d7812,0x0007e6cad8cfd481,0x0000000000000001,0x0000000000000000}}}, {{{0x000c384b610f9960,0x0009e42d4100e245,0x000c5264e577187b,0x0000ec202477a817}, {0x0009dc146fbb4cb2,0x000c49fc51a5dd07,0x000dd34b66b540f6,0x000418cb3114a207}, {0x000042a4afc85f36,0x000592a886f4d479,0x0000000000000000,0x0000000000000000}}, {{0x00062b5959d642be,0x000c107df28ef33c,0x000c98bc18d09a83,0x000908cb61720266}, {0x00034bfa40c64e8b,0x0005f7d00d3266ed,0x0006699785d5c5ac,0x00070fda50cded6e}, {0x000a7129a0528d63,0x000df6226a01349f,0x0000000000000001,0x0000000000000000}}} }, {/* digit=34 [{1,2,3,..,}]*([2^136]*G) */ {{{0x0004a83b5020b6b5,0x00064ea6b7250085,0x000f5cc5dee82b8a,0x0007e307a44f4310}, {0x00061a979f99982f,0x0006271c95260383,0x00087bd9d4a6e7e3,0x000183121a682c2e}, {0x000a0c42c801461a,0x0009efc46dd1bbdd,0x0000000000000001,0x0000000000000000}}, {{0x000ff9d53c8adce8,0x0004cbac7e6d6ff5,0x0008a2a18c9ba604,0x000457234e0b1c61}, {0x0001b538c1881476,0x000d20849fff1d07,0x000e3333d9430380,0x0001d1326f05033a}, {0x0004a49c4e89c642,0x000e640c63716450,0x0000000000000000,0x0000000000000000}}}, {{{0x000a7c6657e0c514,0x00010e4ba5060489,0x00003183bcaf92c4,0x00051063325bb838}, {0x000624a227afade7,0x000d611fad61ce2f,0x0001f27e1c057fe8,0x000426a808156374}, {0x00051e188cc3f494,0x000e601fb19202dc,0x0000000000000001,0x0000000000000000}}, {{0x000f5c4ba35ecd6e,0x000c838b90f28423,0x000ecc8f9f7eac00,0x0004ae3bc63ca5b1}, {0x0000a61f4eb49abd,0x000e5e94c7586825,0x00050828aa62e59d,0x000ca27ce17d2e20}, {0x000f7dcd24d94b7e,0x0004ed84ff72ff3c,0x0000000000000001,0x0000000000000000}}}, {{{0x000dae22413fe9d4,0x000881c93ceb2c9e,0x000376b68f1c40b8,0x0004d107493ec443}, {0x000de2613f0552fe,0x000264177a2adbc0,0x00044456850f4d4c,0x000c024b1759999b}, {0x00032c490b5528e8,0x0004e4fe9cb25fa5,0x0000000000000001,0x0000000000000000}}, {{0x0002401de7dabddf,0x00056529f2c840ea,0x0006004e218ae4f0,0x00026d7d9745c833}, {0x000bc1aa8e8c745a,0x000254366c2e1e3a,0x0009a65d176c592f,0x000575f2ce2f5dba}, {0x000390121cb70eda,0x000ad4df3bd7c9ef,0x0000000000000001,0x0000000000000000}}}, {{{0x00052f406338228b,0x00000044f05c5be3,0x0003a7061d336069,0x000371f2e7fd3e15}, {0x000ddb123a32ed82,0x000a15e8eec0c29b,0x00046b80938b2d11,0x000ba2ae38c19bba}, {0x0000c4e7466a69b9,0x000ba8e7a0607a47,0x0000000000000001,0x0000000000000000}}, {{0x000e250e34d513c2,0x0009900d3d611604,0x0002850e69a99aa8,0x000ea018e87aacf0}, {0x0008ea9b70f5d0f5,0x0009dfec50e62995,0x000ef7267ad0ad8c,0x0009fbbc4dd8a19f}, {0x000ef73af4e91334,0x000d0636506a6e44,0x0000000000000000,0x0000000000000000}}}, {{{0x000533f2ba0eb14a,0x000b9fc6b2073504,0x00059889c71f37ca,0x000d3e3b2957243a}, {0x00033cd4ef031ee6,0x000e1fa792c82e2f,0x000936a9431aaa2b,0x00075897dee2d5df}, {0x0005c1a2769038db,0x0004c149337ba93c,0x0000000000000000,0x0000000000000000}}, {{0x000ff077c9595fa2,0x000b4e92632965da,0x00073090129d489d,0x00024c2f940397cb}, {0x0000f08747c463ab,0x000063f57ea7844d,0x000a687de4ab15b4,0x000d7bdc8db9dfb6}, {0x0000393c5c4b7272,0x0002b3cc129fac67,0x0000000000000001,0x0000000000000000}}}, {{{0x000d85352986f86b,0x000b3bb5e1a9d134,0x00096ed674c04b6f,0x0001eaebc5869197}, {0x0001ec13b24f0220,0x0005acb88043fe14,0x0006b2f77717702d,0x0001f913c28eb4c3}, {0x0008bc0cbbd9e8fe,0x000014871dc376bb,0x0000000000000000,0x0000000000000000}}, {{0x000b182392919d22,0x0005619062a004b3,0x00084b9c0aa0d96f,0x000e6a14d38134a4}, {0x000b962e9b9dd384,0x000d2a3f87434945,0x000e17c26111d5b0,0x000cca088afb0558}, {0x0004109b67e83601,0x000ebef3372d865f,0x0000000000000000,0x0000000000000000}}}, {{{0x000c5a0356b17ac7,0x000f616fb80668c9,0x000f7001431d3037,0x0006786061783bd7}, {0x000e2a8db044a7eb,0x000d63e80e687c5b,0x0006dba72619e19b,0x000b3f54433d79bd}, {0x000179eabd3da5ab,0x000fcebeded88553,0x0000000000000001,0x0000000000000000}}, {{0x0001156c4d223604,0x0006fa0e48c3398c,0x000d70c895f6a870,0x0000aa32def1e5d8}, {0x000a3628036e774e,0x0006fa3b42b31a93,0x0003f15e7bb3f2aa,0x000fd667e0a491ab}, {0x0002f04b61d5276e,0x0001fdac2e330e17,0x0000000000000001,0x0000000000000000}}}, {{{0x000760d231c36820,0x0008bd2a50426c8d,0x000d4451d722fd74,0x0001877484a5084a}, {0x00019395bd1ac7d5,0x000dc03d6541ad77,0x00068a254b40eaa5,0x000dc699a962f42c}, {0x000f2ecdd481b2b4,0x000345d9badbf178,0x0000000000000000,0x0000000000000000}}, {{0x00090c94035684fe,0x000e517a9849bb68,0x0005822be91e8615,0x00067ca7e3c3e516}, {0x0004c5ebee67a9ed,0x000f03236f5438f4,0x000029ef9e45ec0b,0x0003412d001129c5}, {0x000bad0b64fd4f4e,0x0000e15f591e3c09,0x0000000000000000,0x0000000000000000}}} }, {/* digit=35 [{1,2,3,..,}]*([2^140]*G) */ {{{0x00067ca62dd9afd4,0x000678b2e8cc8368,0x000d7d6c96a2abfd,0x00075f62bb6c702c}, {0x000988eb9ab34b7b,0x0007b382272a8eb6,0x0005e40ee1d17286,0x000b6f600751bff1}, {0x000ff996b4ec3001,0x00015d7fb8efdf30,0x0000000000000000,0x0000000000000000}}, {{0x00062d76a29a2746,0x000f091c80dd81fc,0x000c1a9825d4a2f2,0x000a4fb54ae9b61a}, {0x000db71a812fcb05,0x000bb96eaaa7baf2,0x000dfd9cc434e4e8,0x000b8fce567253c2}, {0x000b948eeceeb8e7,0x000abac787b7e9d6,0x0000000000000001,0x0000000000000000}}}, {{{0x000566d2087a8f7e,0x000f8d816dab3c44,0x00068ad0a5ea555e,0x000ab76093fa3eae}, {0x000bcad51a41fb45,0x000c784a1114a732,0x0002d99cd96f3573,0x000f7808bc957e91}, {0x00022a461547dff3,0x000e9dd3f93d98d0,0x0000000000000001,0x0000000000000000}}, {{0x000f5792b3bed20d,0x0003199e50e443dc,0x000ab35921f1c5d0,0x000cb763ce7e3777}, {0x0009ec69a2c8061a,0x0004921d8bd5a1f1,0x000d3f186d49b86d,0x0003d287849a3eff}, {0x00019a1d3969ee2c,0x00097e7987e8d923,0x0000000000000001,0x0000000000000000}}}, {{{0x000e6b3554a3f3c4,0x000c8b48d7c64666,0x0004319bb26494ce,0x00023bd53c15f132}, {0x000a4b25b7340a49,0x0002c82187e36296,0x00076cb62a70b23d,0x00013ce0a44b3a26}, {0x000e1376215ada95,0x0004bdcdd5bfa093,0x0000000000000000,0x0000000000000000}}, {{0x0006f0577c34a522,0x0002d6eb1d23f2e1,0x00074b1ae5a563bc,0x00076c1922ce417d}, {0x0008d8b56e586f06,0x0003d2111864665c,0x0007a1f4a9d1f08d,0x00009ad18a2eb5b5}, {0x000f16f69121b144,0x00055ad3dba51f31,0x0000000000000001,0x0000000000000000}}}, {{{0x000a0990f6c14c34,0x0002ae1571f4bd14,0x000a7e981428a12a,0x0008a57064ea4bd5}, {0x0005ec2f56d89f54,0x0004fcfb513a99f0,0x00081deb029c28b2,0x000c16eb364a4688}, {0x000f6df6754a22d8,0x00039a8e7ba7c29d,0x0000000000000001,0x0000000000000000}}, {{0x000585b840875f9d,0x0006688b87eab66d,0x00061b8a4aef8f2e,0x000968d01b210ab1}, {0x0007a38c32d9fcd5,0x000170203f9469f2,0x00027ba7e65bf262,0x0003268e8f3ddf53}, {0x000d5d6a50d743f2,0x0006f76866dcf3bb,0x0000000000000001,0x0000000000000000}}}, {{{0x00075ceb39ee406f,0x000fddc2dbf93cfe,0x00005aa3d0f7d044,0x000c04043459ab15}, {0x000bfbea051fd1e4,0x0005c86723eeca2c,0x000dd90428637a5a,0x0006d3aca9d581d9}, {0x000277709f646127,0x000d9e5fdc588878,0x0000000000000000,0x0000000000000000}}, {{0x0005fdeadee7c5a7,0x000b59b799ae3c10,0x0005e3595acc919d,0x000b6f6b2aa1f7f7}, {0x000cc519dab324e9,0x00070aa0c81054ee,0x0006840dab1fa02d,0x000ce8162c464504}, {0x0007fc117382d8fa,0x00079cc63a2e343f,0x0000000000000001,0x0000000000000000}}}, {{{0x000f45643ca65cbd,0x0007305e42072e40,0x0006980bc47b22b4,0x00091f480c0959ae}, {0x000df17382117d00,0x000fb6755fe76ce6,0x0008195083b13716,0x00053ce928778e33}, {0x000eadd235784446,0x0005f288650fd122,0x0000000000000001,0x0000000000000000}}, {{0x00032d4f966b7e9c,0x0006ec40795011b8,0x00056106a162f5eb,0x00060472439d72fa}, {0x000ed9a6959807a3,0x000d3315f177c4b5,0x000b196cd83808fb,0x000c21f3f41dc773}, {0x000518607dcca40d,0x000920d975bf1042,0x0000000000000000,0x0000000000000000}}}, {{{0x00043d0a4a0b7f26,0x000c9bca61488d76,0x00078d40864c9a4e,0x0009191208ac32aa}, {0x00065e2c33dbbd1f,0x0006b041d84ce172,0x00022f6c73e5e84a,0x0000caf07f551302}, {0x000e0bc76bc20bdd,0x000a43482195b22f,0x0000000000000000,0x0000000000000000}}, {{0x000f04c8745c6a12,0x0002b2bdd6ee1437,0x000b9431fd260182,0x000e54b7f10879b1}, {0x000a6b8d5c027ebe,0x0002358509530c61,0x00071ee3b953e075,0x0001d055e247c05d}, {0x000f78c21fc120f3,0x000c40b71a77f551,0x0000000000000000,0x0000000000000000}}}, {{{0x000ca1655dd01fc4,0x00023cfcdcd83fdc,0x0006fe01dad6f137,0x000a92f448fc724e}, {0x00071e9506b3510e,0x0002c50316bacd31,0x000812e5b9c38263,0x0005b06a2041b525}, {0x000d1e51d6095bd3,0x00018f8c9f2aff29,0x0000000000000000,0x0000000000000000}}, {{0x000e8440d9f6b1c5,0x000d8f5815a76ff5,0x0000ba6e7eb4652d,0x0000cfa7a2d772d1}, {0x000e12c2c10a367d,0x000122408a9134fb,0x0006be74d3fc999e,0x0007f158ed729839}, {0x000445a86f173644,0x0008103589b3e72e,0x0000000000000000,0x0000000000000000}}} }, {/* digit=36 [{1,2,3,..,}]*([2^144]*G) */ {{{0x00002ef5664a50e9,0x000569e6626b5584,0x000bb9dc4c85c34e,0x0006cac4009d6dab}, {0x00047cf68656c674,0x000e65ab973336b9,0x000ecf3e266a898f,0x000b5830a2ee0371}, {0x0007109821d57e75,0x0002643e097669c9,0x0000000000000001,0x0000000000000000}}, {{0x000e2ad77fec8187,0x0001deddfb754e78,0x0004aaa3d5328431,0x000f5938ac9d56ca}, {0x0000419e9ec29fe5,0x00089e92d324185a,0x00068c4746f628de,0x00086959a461fd09}, {0x00039e1752cc1b19,0x000f685c4efa867f,0x0000000000000000,0x0000000000000000}}}, {{{0x000578941d3daa6e,0x0001e81a86314a15,0x000e2ec49066a742,0x00085f37e975bc97}, {0x000abd59fd20aa74,0x000b001318e5e712,0x000bdca951133a15,0x0006057f57ee1259}, {0x000dad04acbd3b2c,0x0009e7ef3153ef33,0x0000000000000001,0x0000000000000000}}, {{0x000d37d508c6263d,0x000d87a4e81e7b2e,0x0005a01a3eff8f36,0x000726730288c3e4}, {0x0009b846f52088b3,0x000f560651a99118,0x000aeef71db52e56,0x000e58e36c06431c}, {0x000d03f83a3f98d5,0x000adc020099b8d8,0x0000000000000000,0x0000000000000000}}}, {{{0x000d0b7b6a8a3320,0x0007c1820c541666,0x000008d89959635c,0x0006f6b2d261e2b0}, {0x000b20857dc9286c,0x0008490da31aca2d,0x00001835ecf8b430,0x000769b376d5c408}, {0x0006c3593326d702,0x000ae359276d5c27,0x0000000000000000,0x0000000000000000}}, {{0x000052b955ccca9f,0x000132f8bdb8b0e1,0x0001fc788aac66dc,0x0007aff377f81134}, {0x0005f3f5c42cf8fe,0x00063a0cd5ec56c8,0x00044e19f92551b9,0x0005a03e4e9df2c1}, {0x0005981a18a9c38e,0x00038410aaa01483,0x0000000000000001,0x0000000000000000}}}, {{{0x000ab1b79d73f8b8,0x0002c67e2040bd52,0x00089ab066095a12,0x00020058f1cb78af}, {0x00035c77cb75101a,0x000e13361531375e,0x00075eaea159ba65,0x000a7ecbfca3524c}, {0x00019d039ab8ae0f,0x00099c623ac91c57,0x0000000000000001,0x0000000000000000}}, {{0x0001430a249d36df,0x000efe8450eb5d6b,0x000afb92b30c47b9,0x00024beea9991147}, {0x00039e1752c3ff68,0x000fd6a6252b160b,0x00046e76256f4b47,0x0009076f7bff5746}, {0x0003f350ce5bbdfa,0x000da84642b5dbcc,0x0000000000000001,0x0000000000000000}}}, {{{0x000f59f034423df4,0x0000c74c6502a253,0x00051f6b04936dd5,0x000ac1dfa20fd420}, {0x000a26ee480942df,0x000b8f32c2aa1793,0x0008f9fd5819aba5,0x000593ae9a68c3be}, {0x000809f95c514dfc,0x0005832a0100c51d,0x0000000000000000,0x0000000000000000}}, {{0x00084df91d0b9d7b,0x00019af96dda8b28,0x0009e06515fe82b7,0x0004e7882cd87d52}, {0x000d3f4a8cd84bcd,0x0005a839e5e4c173,0x000eace8b4e2b402,0x00009c378fed4c2c}, {0x000b8a183c245522,0x00026032daca8b53,0x0000000000000001,0x0000000000000000}}}, {{{0x00021d74b7f15174,0x000b1737719209fa,0x00000c8bba28cfe5,0x0000523f1c2878b2}, {0x000c0170331c9a62,0x000cd83b50a5843a,0x000131d0381135b8,0x0003a643b75eb047}, {0x000ef1464d2ab54c,0x0007f362ed0e42c5,0x0000000000000000,0x0000000000000000}}, {{0x000bb20fbad15614,0x00040a78f8613291,0x000895f7e0d7805c,0x0004b54ca2a8624a}, {0x0000e6579a8713ce,0x000626e2cc1b0cde,0x00093c66377df41d,0x0009cd6454de0451}, {0x00009db1f1c3ca34,0x000d91b047b0a149,0x0000000000000001,0x0000000000000000}}}, {{{0x0006148c3607c309,0x00072dd5c6a1cd15,0x0004ea2e6d51f4ab,0x000bb9012a38398f}, {0x00025cc1f09df84a,0x0009c3bace064bf4,0x000f3b1a1aeaac49,0x0008ba0e470586b9}, {0x00026aca2a7b1cc0,0x00037064de7e58e0,0x0000000000000001,0x0000000000000000}}, {{0x000f70f6864c071b,0x000cebbcde808997,0x00042d9268c9d10f,0x0001f3646bf97f61}, {0x00099c6124289f61,0x000f65308f5fa877,0x0003b1cbe10f2164,0x000db1cfb717f6c1}, {0x0002178fd0705446,0x00053784aa2a3cca,0x0000000000000000,0x0000000000000000}}}, {{{0x00032b93eb6bf0f8,0x0008d44a6f35d7f4,0x00062f74f5a61124,0x0008d968ff45509d}, {0x00090f78b11dcef9,0x000e0fdb4e540d2d,0x000178df19486918,0x000b775c9c48f839}, {0x000a4516e1546952,0x000548b05a9a422d,0x0000000000000001,0x0000000000000000}}, {{0x0000e6542e705240,0x000ea85c40801a5a,0x0008cf4381fc9bfc,0x00026551ecff5ed1}, {0x00006e3765708042,0x000f10bb393addaf,0x0004c0be6d6327db,0x000ade98dcbda7a9}, {0x00045d1d2c9cc265,0x0001d23919800694,0x0000000000000000,0x0000000000000000}}} }, {/* digit=37 [{1,2,3,..,}]*([2^148]*G) */ {{{0x000136d3adf7c0d8,0x000a615150ed1e22,0x00048b602d1f12f4,0x000a438f58c86ca8}, {0x0006c2ad94dbc8f3,0x0001741520fd2861,0x0006926fc8f344fa,0x000aa2867b7697e9}, {0x00063769f3f74f49,0x0003389eafe4ecc9,0x0000000000000000,0x0000000000000000}}, {{0x0003271ab880c04c,0x0007eceb904c8b8d,0x000cf0e8b6b36124,0x000b8dfe9dc846a9}, {0x000c71bd5a3dcf58,0x000bb872ef46766e,0x000ea257028f76aa,0x00037d56cad75976}, {0x000e6e410a7a4c1e,0x000aa4d9ef6dff50,0x0000000000000000,0x0000000000000000}}}, {{{0x0003f21a068b1990,0x00028b83926d837e,0x00046424f5058ff9,0x000540b150a21088}, {0x0007bd69839e2656,0x000836bb43217215,0x0008f5d34535e3bc,0x000a61ec6b271f81}, {0x00014bd57f4cd40a,0x0009c8fdb8302a87,0x0000000000000000,0x0000000000000000}}, {{0x0006b22f2553a3a3,0x0003b58b7033af0a,0x000213a07cddbf4f,0x000434d1d71e271e}, {0x0003ac069f3affa9,0x0004ccd448d5d23e,0x0005a3de785990cc,0x0009500536e9dd21}, {0x0005a1f484316890,0x0008d39f92d8e2e4,0x0000000000000000,0x0000000000000000}}}, {{{0x000e463b75bb6ea5,0x000ed0a11789a549,0x000dd32eea4152e4,0x000b779f3244c612}, {0x000a765d467497f7,0x0001f2317d762ed2,0x000fb479fdc0f1f6,0x0005b625c778a26f}, {0x00086e4279e293c7,0x000778007cc51b6a,0x0000000000000000,0x0000000000000000}}, {{0x0008d10c9ca3a103,0x000303626747aa01,0x0009d0d1059a4b9c,0x00047b992888178d}, {0x0005dee73f8df999,0x0003009b79f58ee6,0x00095bbb19efb6cd,0x000ee364f704fdad}, {0x00075210ba101581,0x0009e1f5ffb0008b,0x0000000000000000,0x0000000000000000}}}, {{{0x00061dbbf0d6ad65,0x00037943121ba6f6,0x000176edfca2325e,0x00061e28f0cef68c}, {0x00084617ac6eda38,0x0007535e8ca77e7f,0x00023d1d31f498d5,0x0000546d78b2f36e}, {0x000c7d55e2c3f881,0x000891156a1cb9cf,0x0000000000000000,0x0000000000000000}}, {{0x0004ce76bf8c0b46,0x000f73894a4c0a97,0x000e4d65f8fc178a,0x000cb9405d4f42d7}, {0x00089f73dac29f71,0x00028141921d35c6,0x00055dee3cb66f43,0x0003af9effca7532}, {0x0004e3d9ea981425,0x00042022e23b71d3,0x0000000000000000,0x0000000000000000}}}, {{{0x000d0b7e99b465d6,0x000dcdbbc6a7f631,0x000fdb4862b8d0eb,0x0002d00e72a3f599}, {0x0003fff9e95d96f0,0x00098b66f4cdbc62,0x000ac921634cb2b5,0x000ec0deea0b5c81}, {0x0005b0a27a76f063,0x0001e02d30431834,0x0000000000000000,0x0000000000000000}}, {{0x000c98aa1c9ac7a1,0x0007c5a7466568e8,0x000fb66755607c49,0x000ef99d83842e7b}, {0x0003f63d03b04212,0x000eea39bde1d43a,0x000c0a3d0947a656,0x000da642406f1e3f}, {0x000c396f50ca4ece,0x00002261add500ea,0x0000000000000000,0x0000000000000000}}}, {{{0x000faccc08dd24e3,0x0002a75b2039c36b,0x0007b00e10c370cd,0x000decd44a6f8b5d}, {0x0005623fd6ab9f44,0x00019a1ddd85e65f,0x0007f5f2f27bfaa2,0x000934e1d6c8baa2}, {0x0002398cf5bc3e40,0x000936e76ebca08a,0x0000000000000001,0x0000000000000000}}, {{0x000b72cc3defb1bf,0x0007c48e0f8a00ef,0x000b50a281abffca,0x000290112a957074}, {0x000c6cc0bcd2913c,0x00080828c73f9cbe,0x0002b7332c142bad,0x000b82fd75dcc17d}, {0x00071d9dc563b115,0x000fa46eb1fc833d,0x0000000000000000,0x0000000000000000}}}, {{{0x000293af2196db74,0x000aa8f516dffa78,0x000ab476917c3f2d,0x000a17a44ba1c0ca}, {0x000771d0d213b4e6,0x000872d37a8c50d3,0x000a9d4f31d594dc,0x00020ae17df8f34d}, {0x00012ccecab30c4d,0x000fa5e5b7722b87,0x0000000000000000,0x0000000000000000}}, {{0x000e6e4b1df4a900,0x0005d66c421f23c8,0x000473d466e42335,0x000dad17c61ddae2}, {0x000ed279fa7168cb,0x000addca2ea2657f,0x0004d479a5bdfda6,0x0009ec1a80eb84e8}, {0x0001a95ca1a89847,0x000f2ca605fdb8f2,0x0000000000000001,0x0000000000000000}}}, {{{0x0000bda5161e9684,0x00055c62c59939aa,0x0001e39fae89d4f2,0x00072aef74c49bbe}, {0x00060180fc9e6093,0x00063da12ade7248,0x00028defa823f501,0x000a965a30e8a72a}, {0x0005cf1083c600ec,0x0004af9f8b968790,0x0000000000000001,0x0000000000000000}}, {{0x000afd7d7d936a7a,0x00003b13810cfd26,0x00037d1ddbf986aa,0x0005d035eede05c2}, {0x00071b7ae0b88271,0x000812487895ef9e,0x000f170e50423460,0x00003054f1639f87}, {0x0002e674eebc0936,0x000654593b42f2ce,0x0000000000000000,0x0000000000000000}}} }, {/* digit=38 [{1,2,3,..,}]*([2^152]*G) */ {{{0x000a2f3a1cbc282c,0x000e19a09feeb1c6,0x000c54628c6180b5,0x000cefbae8c61be2}, {0x00031054eeedc773,0x000005e41190648d,0x0004925364893510,0x000a54e9064644b7}, {0x00026639e573a22c,0x0003b5a6074dacd6,0x0000000000000001,0x0000000000000000}}, {{0x0002e1f28cb4398c,0x000fba11161ac99e,0x000aaf012b04f328,0x00060a6cb74a91c1}, {0x000690cf3c48dadb,0x0007c4e07d1b8182,0x000bed19eb0dacbf,0x0001aba090482e6f}, {0x000b8c6fb9ea1ef8,0x000d6d4b567809aa,0x0000000000000000,0x0000000000000000}}}, {{{0x0006de757b8ee9dd,0x0004f4a9eb572b8b,0x000650813f9e5a92,0x000081024cddfbbc}, {0x0003e750529ae0f8,0x000c407a678dbdc2,0x0005c643db36c6df,0x0009adee9ab1549e}, {0x000add1f855d46bd,0x000aedf68182d8ac,0x0000000000000001,0x0000000000000000}}, {{0x000e2fb66eef3f12,0x00004b24a7282866,0x00050b3c877e75f1,0x000590fae38bb301}, {0x00008b7b5535d2f8,0x0001b50eaef87c62,0x0000c4541ba355de,0x00098bfe96023f0d}, {0x000dcf2eadc15969,0x000f41ab8c033f3c,0x0000000000000001,0x0000000000000000}}}, {{{0x0001bfbe835763b7,0x000da08736745919,0x000d000c52158859,0x000dbafd4373d9cc}, {0x0003efeee235e560,0x000fe980f98d303a,0x0004f012a6082ad1,0x000e567ed43eb524}, {0x000eddca68306748,0x000f954e531e38a7,0x0000000000000000,0x0000000000000000}}, {{0x0000101b465ee778,0x000f8f4e95956310,0x000bcb6c6057ab1d,0x00052b140218cd6f}, {0x0000a217b7b093a1,0x000924c99c9b3267,0x0000b388550cfd67,0x000eda396f8cf9af}, {0x00035154327557bf,0x00098cf74a0d9f01,0x0000000000000000,0x0000000000000000}}}, {{{0x000cd9335dea0190,0x00015fcbf855836a,0x0007808f96352fb5,0x0005c5cb374fc6d2}, {0x0001eebbbb50f586,0x0007f3a5b9a4d0c8,0x000bc6329ed702e4,0x000264f0fada97b4}, {0x0005e3bbcf73be9b,0x000dd442f9f14de6,0x0000000000000000,0x0000000000000000}}, {{0x00029cdbcd6414f5,0x000db247ce590b47,0x0005be836ddf363c,0x00032e4b6a8da968}, {0x000c049bdb9815fd,0x000d8f7528076e41,0x000d50b097db4cb8,0x0007f829470b7fc1}, {0x000b6caef75b1cc6,0x000ed3d55324b1d2,0x0000000000000001,0x0000000000000000}}}, {{{0x0002ed4b0886efde,0x0002e69216f70caa,0x000a19fc084c43fa,0x000bf1fcd447360e}, {0x00088b44bef17255,0x000c941e542e92c6,0x000c9462ab05687b,0x000f4a55ed27b06d}, {0x00006c4879438508,0x000b3f5a16cdbf59,0x0000000000000001,0x0000000000000000}}, {{0x00090da308f335bb,0x0002c62f75607156,0x000ac3878c204f5d,0x00019a70e1d9ebee}, {0x00065ce18d8dd345,0x00053d4a7a6a59b3,0x000ab840d7a66249,0x000e9f8efc3edfda}, {0x0006a32d022f5317,0x00072a29be1120dd,0x0000000000000001,0x0000000000000000}}}, {{{0x000bdbfdee3c7792,0x000b747684a7e37c,0x0006fd64e032b7ae,0x00031287b0371790}, {0x0003245ed96aa7b2,0x000bcb2d9689dd51,0x0009eceb1d9918cd,0x00053e6e8dbeb445}, {0x0003cd8435c2226c,0x000a212888b11938,0x0000000000000000,0x0000000000000000}}, {{0x0001020457ce98be,0x0009fbe80ddb3555,0x000e385ff7a0d009,0x000821584b1de3c2}, {0x000f36cd64d47bdf,0x000d2c6d2f0d97c5,0x000126f061319f64,0x00050f118e4e9aeb}, {0x000dd0fd66a1918b,0x0008c9bb60247ff9,0x0000000000000000,0x0000000000000000}}}, {{{0x00006452a69b40ef,0x000a58916404d8d3,0x000489351fe54188,0x00083228fc171eb7}, {0x000410e07508f15f,0x000b2d0bdc317f64,0x00075755181b0c85,0x000c4ca35cc09ad3}, {0x000bdec4e4688b7b,0x000ec2f6e18ec10c,0x0000000000000000,0x0000000000000000}}, {{0x0000b91ff7109c43,0x0001353357108dc1,0x0006db397b6c17eb,0x00038d3f418ed53c}, {0x000a1a7d0d6f5104,0x000558963fe8aa2f,0x000629ed52f70d0f,0x00070987dde60b3f}, {0x000b95a72bb4ccee,0x000aae64e168b593,0x0000000000000000,0x0000000000000000}}}, {{{0x0009ff50fcb47b0c,0x000001fc1e2456f6,0x0001c124be702b84,0x0007f671a6c9b545}, {0x0000e07337c72285,0x000d3661d0b0a89f,0x0007db2af0223087,0x0001d9b173b261f1}, {0x000c65404d0457b5,0x00086eefc1cd30f8,0x0000000000000001,0x0000000000000000}}, {{0x000fafb34fbb3972,0x000db4c5bd6770ff,0x0000de59815fc7a7,0x000b5602342e8ca8}, {0x000220e1c9e4f843,0x000b0b7c5b3bfe91,0x000b313a1e2826c8,0x000988ce465ce442}, {0x000217ce5f2ef9e9,0x000682a10ff59077,0x0000000000000001,0x0000000000000000}}} }, {/* digit=39 [{1,2,3,..,}]*([2^156]*G) */ {{{0x00041390c3361b6e,0x000b58054f802294,0x0009b74e1597143a,0x000652a48a901ba0}, {0x0004b9b4f3635116,0x0005e2ee300afb31,0x00079f7d46228864,0x0001b66e61674d2f}, {0x00005aad2298ff3c,0x000bd327d6400925,0x0000000000000001,0x0000000000000000}}, {{0x000b20dd543f093d,0x000dac4b51c2ba0e,0x000bf1d364874c9c,0x0002601310d4063e}, {0x000c6c8c6fbaa6b7,0x000ce6639ff8b94a,0x000066c91f488ec6,0x000524c600b8f454}, {0x000ff656ef37706e,0x0008a0434286c21c,0x0000000000000001,0x0000000000000000}}}, {{{0x00077e284b1fd44f,0x0001dc37f60445d8,0x00069f0b4dfca419,0x000aa285358c7759}, {0x0003172cf55e112a,0x000ffea4f47f71ae,0x000412afc352eb30,0x000bc7ffc3d95b8d}, {0x0009ccbacabdbf74,0x00030dd4b6acd123,0x0000000000000001,0x0000000000000000}}, {{0x000870d6326f819d,0x0001f9d1598751a6,0x000c925f0b6c6b0d,0x000c309ba890fd44}, {0x000f1cedd20fe106,0x000408588dc46673,0x00053cbebfbcf6f2,0x000da52fed53b541}, {0x0002bbf3f7b4aace,0x0008d484a22a2167,0x0000000000000000,0x0000000000000000}}}, {{{0x000d633fc6b2523f,0x0003c8573eaf11ae,0x0005f254d2bc0511,0x0001c7fd283764aa}, {0x000f770135776ee7,0x0003df5ba988759f,0x00065da842051883,0x000b809c0705d522}, {0x0001067f4912507f,0x000fb628d91a9464,0x0000000000000000,0x0000000000000000}}, {{0x000e6e2ac33e3aac,0x00065c0000ebfac5,0x000ced796bda6c05,0x000a32836c90c0d4}, {0x000d2ee187fc8100,0x000d7848e982bcb3,0x000be08290e6b628,0x00085ab586db4a59}, {0x000b07e2fb9a0080,0x000d56210d8de2f4,0x0000000000000001,0x0000000000000000}}}, {{{0x0000ac7a2fd05258,0x00034c744e57f4bf,0x0002edb448a88343,0x0004d56a4c1f9523}, {0x0003b85d4cde6c8e,0x0003063d710bd23e,0x000833d45b52f378,0x000d2012d08a14ca}, {0x000ccbe55ff85aae,0x000e919fa9b95c02,0x0000000000000001,0x0000000000000000}}, {{0x000999b76646e255,0x0001f5f355b09a04,0x00000d64b669309a,0x00089605b2bd55ad}, {0x000656b121bac578,0x000d693b7220d91b,0x00053ea1faab888e,0x000745d07a303444}, {0x000e7a52e75e36d6,0x000a7986433618f7,0x0000000000000000,0x0000000000000000}}}, {{{0x0002484fcef15b60,0x000485fc2dc91c4b,0x000d7e9f8403b5be,0x0005ec8542217cb5}, {0x0003f3deede9d858,0x0008c56ddda1f005,0x0009028845902ce4,0x000cdbb111feb2e9}, {0x000537c2b8f6659b,0x00075d89960f5bf1,0x0000000000000000,0x0000000000000000}}, {{0x000a9e85b9799e89,0x0001de39c6986f88,0x0000fa555ee69af1,0x000f3b270c555b9d}, {0x0004c62266b30411,0x00084a11940b0e86,0x0005b26112da8247,0x000fc56950bfb7ec}, {0x00066d81f8a57ba0,0x0003b772e0aa0038,0x0000000000000000,0x0000000000000000}}}, {{{0x000710f55ddf9e13,0x00018f67ff0e8dc1,0x000601481b67ef67,0x00009ffab39b462d}, {0x000b5ad90ba1057d,0x00018d94f2f83bbb,0x0008d2eed4c7a169,0x00019ddb61a12bee}, {0x00096ab74dadd029,0x0003902e5753e9de,0x0000000000000001,0x0000000000000000}}, {{0x000926dcd7de034d,0x000eab5af3e375a3,0x000eb250dce827a6,0x00008bd108623cdc}, {0x000d49a7d0e9c524,0x00066e3019236fda,0x00040ab55ed033af,0x000667077bc755cf}, {0x0006972e633b49be,0x00095334396ea43d,0x0000000000000001,0x0000000000000000}}}, {{{0x000671c0c20009e5,0x000956db94fffef7,0x000bca8fdc30361d,0x000ebfa5860aa7a6}, {0x000feca2b724bff4,0x000572f34fd506fb,0x00048ff2e88a7d1e,0x000874822e19430c}, {0x0003c0129eb20b17,0x0003db07cc6f0162,0x0000000000000000,0x0000000000000000}}, {{0x000244f5da60b490,0x000fbd8954a885e9,0x000f39699542bf3b,0x000c93a6a7e331fd}, {0x0009816b29c5180d,0x000ad960c8e85d80,0x0003a3a7931b35df,0x00092e570f2974ab}, {0x000904daaf442234,0x000cf25e1f700754,0x0000000000000000,0x0000000000000000}}}, {{{0x00056e1b7ae8ee13,0x0009b65f8128c4ea,0x000e5e0d92d02840,0x00074f688ed0e1c4}, {0x000f9c55f66d6f3b,0x000eb2ab8035d3f9,0x0006b643bde4296d,0x000f25e29f7ea7cb}, {0x0007f5f239b9d057,0x0001af17e3fac208,0x0000000000000001,0x0000000000000000}}, {{0x00063cbb323c7d21,0x0002b6d926fd3ed4,0x000ab9ee679014b1,0x0007e6093a1bcb9a}, {0x000dc171705931f4,0x000b0a4387f44f73,0x000c7cdd2a12e513,0x000a473ec3b73ce5}, {0x000ef17967f341e3,0x000a3809a474c86a,0x0000000000000000,0x0000000000000000}}} }, {/* digit=40 [{1,2,3,..,}]*([2^160]*G) */ {{{0x000dc98081f0b504,0x0002377f1bc655c2,0x00067de245fb688a,0x000260cdd7a61e34}, {0x000d89aaf28a330b,0x0004e078039aeae5,0x000a42253d349d8d,0x000438cabcfed7ae}, {0x000a9960f3728bd2,0x000af658af568325,0x0000000000000001,0x0000000000000000}}, {{0x0006e52ab17d640b,0x00019d1bc21ee481,0x00026613d4c31a58,0x000c14072a5969b3}, {0x0005babfa75ee1a8,0x000c563bc4d35701,0x0000425d2086ecb7,0x000c9b8fafb1a4a8}, {0x0007ef737c2661a2,0x000c20e7afb2d654,0x0000000000000000,0x0000000000000000}}}, {{{0x000726f329838a5e,0x000204b7a9942b65,0x0004a26b80fa33e2,0x0006f40abbf82a56}, {0x00026970dfcc973c,0x0001c38e96f95485,0x00019abd2bbae55f,0x000c1edd71d62ecb}, {0x00020adf26d97496,0x0000d917e1cf322e,0x0000000000000000,0x0000000000000000}}, {{0x000aaf44ac399116,0x00067bb67e29ba76,0x0003d1213c21031c,0x0003b345e37fdfde}, {0x000dab46f2bbeb4f,0x0003442227ef5d5b,0x0005c11bdace9105,0x00060e12dac175a6}, {0x000cdb1cf99010c3,0x00087106f2502658,0x0000000000000000,0x0000000000000000}}}, {{{0x00044188249a4961,0x000eb8deb1c61cee,0x0006080b71cf8ff5,0x000b75b57b2ccc29}, {0x000b9ffb3c6aa214,0x0000a50e70e80f53,0x000fd2ffeb156be9,0x0005a94620e80211}, {0x0005db41e15422e5,0x00055d2030526508,0x0000000000000001,0x0000000000000000}}, {{0x0009e1933e619307,0x00086b5084131313,0x000b6d55898976e9,0x0003f79536a0866b}, {0x000b8e06bc0b2a44,0x00034e542863ba00,0x00040e4dd7a73a37,0x0008b2efa3822134}, {0x0005312ecb0905af,0x0008efb084f884e9,0x0000000000000000,0x0000000000000000}}}, {{{0x000172c5ec6e6f32,0x000784d8ddaafa3f,0x000785f2ae4eb6e8,0x000db162f77d65ef}, {0x00085dec5c58d4e5,0x000a30bffa2375c7,0x0000bb7c92e0f7f4,0x0002294b17a00c92}, {0x0009107e026f93d7,0x000911ce9dc0950a,0x0000000000000000,0x0000000000000000}}, {{0x000841c6766f1f49,0x000079724523292b,0x0000e7ddb4cb0490,0x000d47f955646515}, {0x000b44b2a0877c3a,0x0004c3de4bd8708d,0x0009d24b4a9131fa,0x000585e650ae938e}, {0x000bb2e4980176c4,0x0001820248559a60,0x0000000000000001,0x0000000000000000}}}, {{{0x000cef71c9a9281b,0x00078b2e3e260928,0x000b15a4e8453115,0x000c76cc66031c77}, {0x000e2f2c06ffcc30,0x000a471db8c352a0,0x000184b9a687b94e,0x0009b19798642e1e}, {0x0001d84cf08e1a1c,0x000462a36c823a7d,0x0000000000000000,0x0000000000000000}}, {{0x000b775551fedfb4,0x000c921b0d298e47,0x000071e1319e7833,0x000e6f4ce5e5ae43}, {0x0001348ff7cbdbf6,0x000c042f31447260,0x00061f1861a992ae,0x00020e5f80d48204}, {0x0008846b75b72853,0x0005ef4edf14c058,0x0000000000000001,0x0000000000000000}}}, {{{0x00051608c9277436,0x00036641c6cf4e0f,0x000263e7b7515b1b,0x000a50636eb6d459}, {0x000df53679a56041,0x000b4abcaa6ef1d0,0x0005077b47a03019,0x0009d2d427efae97}, {0x0003dfa9162f30c4,0x000f8bc801e5655a,0x0000000000000001,0x0000000000000000}}, {{0x000202783ac347e0,0x00001a26d59f4868,0x0003895e6664e175,0x000031f4202e3866}, {0x00069d2af7613aa8,0x00021cc1e58ddf28,0x000159ee13d84ffa,0x000c8f6eb59a5da3}, {0x0005df9b7b87bbc9,0x000771b8b6006cdc,0x0000000000000001,0x0000000000000000}}}, {{{0x0006aa5bb86ea29f,0x0000e29e7a21c03e,0x0009e430844ee3c4,0x000584b091ca8307}, {0x0006afb05a033420,0x00015d7ef65dc354,0x000acb0dfae44d05,0x000bad35608c8e97}, {0x000a78e5d1c181a0,0x0007cad8ba90d885,0x0000000000000000,0x0000000000000000}}, {{0x0001cba5026e7f38,0x0009593d89eff94b,0x000b88834191828d,0x000881379cd1acbe}, {0x000c4d9c16250e77,0x000f4d66dbf51b1f,0x000703cbf985d682,0x000998e4fae0e78a}, {0x000e124668125e5c,0x00095c7096d1799f,0x0000000000000001,0x0000000000000000}}}, {{{0x000c267dbe90f79a,0x000a682de8af3a96,0x000fc2373c7d7a0d,0x00046c045ae71058}, {0x00067b05a94e6008,0x0009ec9a78879108,0x000973f0df20f654,0x0003d4a6c168aecf}, {0x00050f6bc30604ed,0x000f342722d4210b,0x0000000000000001,0x0000000000000000}}, {{0x00089badc8348ffd,0x0005ea32767a9d3c,0x000dc1a4baa76ac9,0x000219cd3eced60d}, {0x0007d2d3cddf3114,0x000c14e1ea557cfa,0x000c466d40b6e234,0x000224ae183077a3}, {0x000e59e159bfca75,0x0004c30d62fa0c8e,0x0000000000000001,0x0000000000000000}}} }, {/* digit=41 [{1,2,3,..,}]*([2^164]*G) */ {{{0x000acef3fd9ab352,0x000a04dda16fb097,0x000e90de3351fbdc,0x0001f9baff197a3e}, {0x0003610909fc0701,0x0003d538e2bf8355,0x000fbd9d3c214c4a,0x00064b2db047d1ad}, {0x0000b9e3fa7800e1,0x0001033ba0bb0ce3,0x0000000000000001,0x0000000000000000}}, {{0x000cb2552f015a84,0x000cdab20301de3c,0x000af7c3af2c8c0d,0x000fe99606c79c8a}, {0x000d638fb52847ee,0x0009bf56737cb586,0x00000b1ec4f260f5,0x000362ff887d36f2}, {0x000ed3b693913291,0x0006e3c40f0d7ae5,0x0000000000000000,0x0000000000000000}}}, {{{0x0008a516e5648dad,0x00047202a3fb8a9d,0x000ecb3edff5fedd,0x000220d17fb9838f}, {0x000dc8b9ac40f762,0x0009a8311e23ad98,0x00084edfb615d6c5,0x0004e6c85dc486c7}, {0x000bf81a7ee5f8f8,0x000ecc58d5bb866b,0x0000000000000001,0x0000000000000000}}, {{0x000d41ef176fcfa3,0x00078f007acce1a1,0x000d8b8126b20e97,0x000a71b3438944de}, {0x000134e76c73c437,0x0004a56abd9a1b4b,0x000de8db7385f9b1,0x00043115d58229b4}, {0x00034725891b4078,0x000c55ba8c32f815,0x0000000000000000,0x0000000000000000}}}, {{{0x0008e051939a3b7d,0x00010361ba38d482,0x0009c9a686091017,0x00050f6456db6700}, {0x00031ba66d450ac6,0x000e0bdd4225b759,0x0006e52d315738bc,0x000d21403d74797c}, {0x000a041eb53ed58e,0x0002f948ee60c564,0x0000000000000001,0x0000000000000000}}, {{0x00014e408d1cd601,0x000cfebde9152461,0x0004123bd5f4532c,0x00083ab7b9fe9b7a}, {0x0009704a01b31e49,0x00040d9c79a4402d,0x0009ff5b8e0a168a,0x00048d442aea1790}, {0x0001410d782cc3c0,0x0002bf2d98ba10cb,0x0000000000000000,0x0000000000000000}}}, {{{0x000943818d1af858,0x0005d42684f68399,0x00068a5f9139d27b,0x000d03a1a3ed9c84}, {0x00024e699de7f9f9,0x000ddd7e41e31174,0x00089cc967769d86,0x000a0e9e00b5f6fd}, {0x0007b63934a6926e,0x00011c5b068a8b3d,0x0000000000000001,0x0000000000000000}}, {{0x0007d21cfa86aa41,0x000f529a2aecb429,0x000251f8677cf147,0x000bad3bd2a35774}, {0x00090bedc57bbf0b,0x000a31f1dbfe5b37,0x0001e75b3cb7422a,0x0006476bcd9901bb}, {0x000278bd8b31cdbf,0x00082a6fb171258c,0x0000000000000000,0x0000000000000000}}}, {{{0x0009d9b88bd44811,0x00086c7bafe985de,0x000eb018e7fc2f20,0x00037a5b53cb3738}, {0x0000a097f28e364d,0x0000b5541e546ab4,0x000530e972bd2ec0,0x000b65a95e020994}, {0x000221ddc10db4cf,0x000295000b94fc68,0x0000000000000000,0x0000000000000000}}, {{0x0006ace5e2ed6000,0x0008ffd606613047,0x0002a24af3b853da,0x000aba583e1b87cd}, {0x0004618719533717,0x000d61f56ae2be40,0x00025ef5e9069ea8,0x000f94027fe98e78}, {0x000db6fc7d9c1583,0x00075271696c0d71,0x0000000000000001,0x0000000000000000}}}, {{{0x000f12734c3ec92d,0x0002bb3d48fbed19,0x00049bdd26ff69ad,0x000fbf26985b989b}, {0x000ad451c21eb61b,0x000237a30e35f12c,0x000a3b3680a082df,0x000188ebe4c92751}, {0x00087a8fbc731694,0x000b03a8bdfe9408,0x0000000000000001,0x0000000000000000}}, {{0x0006f89f4e0d5883,0x000d80de19c8b935,0x00077afef27eab9c,0x000538f8f941390d}, {0x0002b8c79f62a16f,0x0004a907ee9a2c1a,0x000951eb7aa5d968,0x0001fe7d75aa9877}, {0x0007b983b59fbafe,0x0002bab437db42c1,0x0000000000000001,0x0000000000000000}}}, {{{0x000bf512d363aeb8,0x000e0db50c6d9411,0x0000e1101f753fc2,0x0006d62a0ded1b7d}, {0x0004a1ec0fcb3b8e,0x0000a9719f9cb02e,0x000fa60331be1189,0x000525c569643656}, {0x00081aa5691f4f2d,0x000a963a9ea530b1,0x0000000000000000,0x0000000000000000}}, {{0x000098b88fd83f01,0x0009e9aed5969329,0x000769c1597dbeae,0x0003f34dc1aadb7c}, {0x0006d041d0f773cd,0x000dcc7a18555ae3,0x00057b66cab6672b,0x000c3dbd797513fa}, {0x000ec420f27eb3f3,0x0003c62ce13b7853,0x0000000000000000,0x0000000000000000}}}, {{{0x00057f7ec577ceaf,0x0009584ce56b583a,0x000ce15377e1306d,0x0005b26b1e23a49b}, {0x000f42d98c317bad,0x000c523283ae8b11,0x00081ddf50073f0d,0x0004ab516099e7af}, {0x00029299e519277c,0x000c0d8cb7cfdd6a,0x0000000000000001,0x0000000000000000}}, {{0x00029a85f4a1c822,0x000b7e9213cb42ad,0x000364e5e4a37030,0x000a3941f8a54d03}, {0x00050b7d507ec771,0x000db1def4d6f8ad,0x000eab3bd493bf4d,0x0009716822a9c65e}, {0x0005d463b7e2f601,0x000728062fa75d1d,0x0000000000000000,0x0000000000000000}}} }, {/* digit=42 [{1,2,3,..,}]*([2^168]*G) */ {{{0x0002ee214ad0e3d6,0x000d51de6a66c4a4,0x000c1ce94446c6c7,0x000c0d5dd2eee21b}, {0x000e88f8f4a8deaa,0x00055296fd5914a3,0x000dd876c3945207,0x00083798ebb4e647}, {0x000fd6484696a7a6,0x0001d866ec9d8ec9,0x0000000000000001,0x0000000000000000}}, {{0x000ca34e120495f9,0x00050701e46446f4,0x0004431e6d90fc27,0x0006b7610b310d40}, {0x00086e5199614976,0x000e7e80f704e266,0x000aa764f7efe74a,0x0003d9535c6d9829}, {0x0005a23c25702e18,0x0000a0457bd92a75,0x0000000000000001,0x0000000000000000}}}, {{{0x0009cf085024c2f1,0x000c0aff178cc9fb,0x000cd1f6670717cd,0x000588548870fa8c}, {0x0001a99c44c6bc4d,0x0007a4c31ed62743,0x000f88c552f232dd,0x0008940140f085da}, {0x000a8211a1d88681,0x00041216e4c1b09a,0x0000000000000001,0x0000000000000000}}, {{0x0006cac59e6c3159,0x0000ba3374279c4b,0x0008991eda2c878a,0x0003b4cf84ea0b3f}, {0x000025e729a3932e,0x00047222c0cc5f31,0x000ba94b4346c5bd,0x000e2995032ec5c9}, {0x000db493f41a4bab,0x00024e7b6e042b7d,0x0000000000000000,0x0000000000000000}}}, {{{0x000aefc5789d3eda,0x000070117b5af24b,0x000a5c6b9c3050d4,0x000dbfc9621085b7}, {0x0006f4c0b7973deb,0x00006f6cf4b4e834,0x000082f092a35673,0x0002d877db7b37b4}, {0x000c2eac8682b506,0x000eac10f86afedc,0x0000000000000000,0x0000000000000000}}, {{0x0002caf651b8b0a4,0x0008310eef2a1934,0x00026025b8808ec6,0x000dcff1e64f055a}, {0x000a67192e09ae5e,0x000d785482258125,0x0007daa7d24e92c4,0x000a9c45e5162876}, {0x000fc7c72fb7aba4,0x000522976bb5f88c,0x0000000000000001,0x0000000000000000}}}, {{{0x000921c0f982798b,0x0001a2079475b7fe,0x000ea0fd52e410ea,0x000e44af77d4bbcb}, {0x0001f260a54b0212,0x000269af2ec66a7d,0x00034794993bda84,0x00050b15e358d04f}, {0x00067a4d30bdfadc,0x000e912250ea3d1c,0x0000000000000001,0x0000000000000000}}, {{0x00083de4fe7bebfa,0x0004fdfb63579e27,0x0001abe0cbad5ac8,0x000820014b8a145c}, {0x000a85d987c51840,0x0009eba9aacfadab,0x000291af5fccfd5d,0x000785e551a982de}, {0x0002bcee4372c455,0x00049c9d89842d5e,0x0000000000000001,0x0000000000000000}}}, {{{0x0000817678d00826,0x0003072fc12b3906,0x000fabe24fd4868f,0x000b2a4f9e0b8813}, {0x000ccd87b27441cf,0x000e7fd0a48234db,0x000ea747d9a2a9fe,0x000c91ba0d4add56}, {0x000c9d0dd2d3e7c8,0x00005660e4fd17f4,0x0000000000000000,0x0000000000000000}}, {{0x000a904f88c1be1b,0x000e5cce4c6964ff,0x0005fb6194a74952,0x0000f033d222444b}, {0x0008c26fbb11965c,0x00055ed1ac1d1bab,0x00020c09d970630d,0x00075b608324cefd}, {0x00050cf259835d15,0x000462cd49bc1143,0x0000000000000001,0x0000000000000000}}}, {{{0x000b46239d54de36,0x00013af2871bf6df,0x000bb6d9f31a1b7c,0x000528b0f5b2569d}, {0x0006b9497778a81b,0x000c963043af6788,0x0003bf9954a12672,0x00059feeec8df36a}, {0x000d60c22b5fdead,0x00060d265f0f8b6f,0x0000000000000001,0x0000000000000000}}, {{0x00050d0b6534b1ea,0x000703b71e08797c,0x000d2bd35e284a7c,0x000105aa68827a45}, {0x000902245c12e4ca,0x000f1afdb8eeeba0,0x000caa7693b8db6c,0x000824a39f45018e}, {0x000945d0c9d12756,0x00055f86289ff82e,0x0000000000000000,0x0000000000000000}}}, {{{0x000f246813a5e2f3,0x0004d2dd1bc96870,0x0005743352958a8b,0x00007a9386d4a79c}, {0x0008b4a29091d043,0x00059ba9e47bd2da,0x000478de8a606e11,0x0008c9f2a8c27ae1}, {0x0002946224c1c93c,0x0003ef3adcff2ded,0x0000000000000001,0x0000000000000000}}, {{0x0005100b79546483,0x000ac268f6c48348,0x000e4b2ec17a54ad,0x000f85818d6815bf}, {0x0004f425318546e1,0x00013cbacecaadf3,0x0006d908fa2a9c92,0x000e8808196d6c46}, {0x000ad801f4a291fd,0x000b7ecba0623fa6,0x0000000000000000,0x0000000000000000}}}, {{{0x0007b0f39088ef39,0x000a435ae74e03d1,0x000fbdcdaf3b17b1,0x00090868e5084910}, {0x000019102285b63c,0x0005454d88d8e63c,0x0009e2380d185fed,0x000af9e19dfe50f9}, {0x0008e09d7ce8d3eb,0x0000155127749872,0x0000000000000000,0x0000000000000000}}, {{0x0007fda1b031ef4b,0x000dfd7188feeb77,0x0006801e0f6f597f,0x000e9d1729652f82}, {0x0009d58dec034252,0x0003cc68d0c6aa0c,0x000a4e76779b37e4,0x00008d509f569c62}, {0x0000c41330558ca7,0x00056956b5657bd9,0x0000000000000000,0x0000000000000000}}} }, {/* digit=43 [{1,2,3,..,}]*([2^172]*G) */ {{{0x0009008a556937c2,0x000f76241f10378e,0x0004e7ecf0092193,0x00097f48f8905d70}, {0x000c86b4870ad280,0x000f86eb6f389aca,0x0003ffbc3b9a3132,0x000a9c6b9598fe5a}, {0x000429f1014fb463,0x000e06408908552f,0x0000000000000000,0x0000000000000000}}, {{0x0000c94ae41024de,0x000a6dd0399afa53,0x0007da5ef17ac70c,0x00080b49854eb299}, {0x000104afd62b1e2c,0x0000b1375777d7cf,0x000794db8dbecfef,0x000ff21b1b05dfbd}, {0x000f1e68e47404db,0x00080928abdaf296,0x0000000000000001,0x0000000000000000}}}, {{{0x0001636898bf4d11,0x000fb75ab01bffaa,0x000ba4b1f3e58bf7,0x00059cab50bc67e3}, {0x0008acea4689ce8b,0x000f1932a30d30cf,0x0006e5cb3d1d8eda,0x0005fa7949e492c0}, {0x00041db2db16d8b2,0x000b0610d851b96f,0x0000000000000001,0x0000000000000000}}, {{0x00054a2b36667691,0x000ca196d36fe2b1,0x000766e2a6109d47,0x000f9263f1863dba}, {0x0003be92b5a5ba8e,0x000aad9918a5da16,0x0009189520c8298c,0x00010a27963af5e7}, {0x000b8c3b84ab05f9,0x0007bafd0103c420,0x0000000000000000,0x0000000000000000}}}, {{{0x000e3e45f8d73683,0x000eb8ebb6d11caa,0x0000f274ee508fde,0x00020c83562c576b}, {0x0008510e47baeee6,0x00079b810588c571,0x000894a919ff42e2,0x00007edf259b927c}, {0x0009d16a223100a0,0x000a5b2acb9ccb16,0x0000000000000001,0x0000000000000000}}, {{0x000e8415a9179d06,0x0004b594d74f07fe,0x0004fb6e0e5cacca,0x000788b708cc549b}, {0x000c0c62edae508e,0x000b9ef886c2847d,0x000e40664c8eee69,0x0003ed24b57a9dee}, {0x0002b9d44a547432,0x000a6f16f12261ca,0x0000000000000001,0x0000000000000000}}}, {{{0x0005496bc42e6e51,0x000d33d320585033,0x000cf402bd388067,0x0003e6730074be0b}, {0x00043e8db4e94291,0x000f7beef462a0cb,0x000e58a8c2ead81c,0x000b97eccd5df06d}, {0x0005954e3501f23b,0x0004b4a8b8e4e11d,0x0000000000000000,0x0000000000000000}}, {{0x000598c1e025da1b,0x000b09bf9648fc1d,0x000d224f8ad9987c,0x00065a60d88fba1f}, {0x00054d86a1d9f606,0x0006c4ad1df1e7f7,0x000e1da4acf77f72,0x0000938971a27713}, {0x0007fc94e0f78da1,0x00083992811d7d3b,0x0000000000000000,0x0000000000000000}}}, {{{0x000c9cc6dd4a5914,0x000862d80be96443,0x00008c7a249fd0f7,0x0001ea54a0d2c9f8}, {0x00048d9e55013f6b,0x0007ab76e8d002ac,0x000cbf4462d73cac,0x000faf5cdb58c492}, {0x000ca322b819e5c1,0x000b840745406425,0x0000000000000001,0x0000000000000000}}, {{0x0005f739a14940b4,0x00097d20ee2a886c,0x00035ab04c341a53,0x000f7a9d2904ba7b}, {0x000d9cae762f47f9,0x00007d2eaeeeb5be,0x00070ab079042e0b,0x00060a339ed63e5f}, {0x000c7b9658ba8e43,0x0002d18d85499745,0x0000000000000001,0x0000000000000000}}}, {{{0x000b401e3813737f,0x000ff61118cf0239,0x000909b65cbad1c8,0x000da081fe099573}, {0x00028cfc70caa9fc,0x0002bfc31062db69,0x000e85af4aac9c83,0x000ba3d1d4e51a7e}, {0x000363dd1405fca7,0x0009117097ec2370,0x0000000000000001,0x0000000000000000}}, {{0x00065c78edf4f376,0x000f36321b45daed,0x0003283085bc71ee,0x00018a85f5b5aa08}, {0x00055758f2c2f181,0x0001623497212c90,0x0006ecdfee014f92,0x0000a48aadb790d1}, {0x000881e12f4528d4,0x0004482acaa286a1,0x0000000000000000,0x0000000000000000}}}, {{{0x00050bbeb7940a25,0x000eb62b0dec1d2e,0x000f7146dd0fa42c,0x00051beef911c829}, {0x0009947cccb28e02,0x0009505362c5e903,0x000767ef06d55451,0x0003dcda2ee6b16e}, {0x000b2373652d7be8,0x000cb5af116c86d2,0x0000000000000001,0x0000000000000000}}, {{0x000d36b874b6449e,0x0002d7bb963c1def,0x000de8609229e57d,0x000375fd0ce127b2}, {0x000b5890dc213b70,0x000a1d88db3c82d4,0x0007b583b09ebdc9,0x000cc6b137b10089}, {0x000cf29a5fc13efd,0x0001907605ca17a3,0x0000000000000001,0x0000000000000000}}}, {{{0x000665e2bbfdb04a,0x00017e4232c5cb5c,0x00026232f5f9a245,0x0007a0275981cd79}, {0x0005ae253d4d80a2,0x0006c00bb7783b1d,0x0004c2589b5ab0bd,0x000f6c48caf740ea}, {0x00082e177fc5351c,0x0000fd2b0e714ba4,0x0000000000000000,0x0000000000000000}}, {{0x00052b5ad6ac73dd,0x0007a311881ba785,0x0004ccac10cfb206,0x0003dcbe5d449097}, {0x0008b8873accd901,0x00080d70e5b2cf2a,0x000440b2c2817333,0x00067c3b711d4631}, {0x000b996623747bc6,0x000383423c70b2d6,0x0000000000000001,0x0000000000000000}}} }, {/* digit=44 [{1,2,3,..,}]*([2^176]*G) */ {{{0x000b11d1789dc869,0x00016c2eed227fa8,0x000916842cb7fd9a,0x0008564ce12a5d02}, {0x000bee59ed474675,0x000e675f354b48f9,0x0005d69ece126be8,0x00018ce3aca2f7c7}, {0x000768d6000f88d2,0x00090f26ea6ff29a,0x0000000000000000,0x0000000000000000}}, {{0x00096ef4ce69e270,0x000f2da0efb2f05d,0x000a99dc276ac3a2,0x000e0342757c443d}, {0x0003b390d2a5e23c,0x000e7ea78e9b674e,0x00085e132e72b987,0x0006b6c21856dca4}, {0x0005bed8cda17d0d,0x000237220788bdee,0x0000000000000001,0x0000000000000000}}}, {{{0x0002364996ca25a6,0x0007ec8d70cd440e,0x000d8467c5161afc,0x000408724c9aa882}, {0x000b962a215cbbc1,0x000c4986c1ad6d3c,0x0001332912aaf7a6,0x000d6db2702d8369}, {0x000a17e017d4a1ec,0x000f2dbf2405e93f,0x0000000000000000,0x0000000000000000}}, {{0x0000641168090c5e,0x0006fce42ae3e68a,0x00039938713395b0,0x000394a15bb1098f}, {0x000db97734c1bca3,0x000edfc62ae8c0be,0x000bc2f9b0452cb1,0x000304c79c90c661}, {0x0000dada4e625332,0x0006fc2e4ae4342a,0x0000000000000000,0x0000000000000000}}}, {{{0x0001bd7fc156252b,0x0000ddb25b337fb0,0x000ac5d025ae1e66,0x000c26056a73c379}, {0x00095dede6af2b69,0x0001ae9121b7e81b,0x000754f6cd030d2a,0x0008b47d1e9a5f7f}, {0x00025d238c9b7c0f,0x000d32d6fa902ce9,0x0000000000000000,0x0000000000000000}}, {{0x0005ace423d94184,0x00056f6ab6a655f9,0x0008fa78d47709a3,0x0003f5d39d32f258}, {0x000beab0a90b8c58,0x000bc517995d68b6,0x000ea4acae9d65d8,0x000fd569fb104a80}, {0x000b09db02cb3b12,0x000c624b3e1e5f67,0x0000000000000000,0x0000000000000000}}}, {{{0x00093cbca6dca0b6,0x0004a2146559221e,0x0006c357ebc20032,0x000e73dafbe29569}, {0x00073f1c77b70537,0x0002b0a8e959d415,0x00055d9c50a71dc1,0x00037c9b3656d184}, {0x000283b617fcbc17,0x0000976acf8093d9,0x0000000000000000,0x0000000000000000}}, {{0x0008b573715b4734,0x000173f0027024fa,0x000386bfccf3b38a,0x00095480bbc99c54}, {0x000668bfbf241bdb,0x000353dffbcc88d5,0x000216b7968e8858,0x000de22f661faa2a}, {0x000189437f0cc373,0x000c1f5601679c0c,0x0000000000000001,0x0000000000000000}}}, {{{0x000a86967182c501,0x0001f634e40148fc,0x0001c864ffbfa398,0x0009d6d142879632}, {0x000443e4b6047507,0x000e1e5a879eef57,0x000d2b8fd7f7f136,0x000d19b6378838d5}, {0x0007815ed1c2726d,0x00042ef17abcb4c1,0x0000000000000000,0x0000000000000000}}, {{0x000b9a5999895b25,0x000be140e558227b,0x0007f28ae923d146,0x000d00a58852f582}, {0x0000e60ada16c8cd,0x000158a85a7def11,0x000e5c61d1152d28,0x000d4be61bf1a55a}, {0x000cf413c0a31606,0x000b3cd625cdfd8f,0x0000000000000001,0x0000000000000000}}}, {{{0x0003f2f8ccce2027,0x000fd5cd45c4a564,0x000a6b2411224a0a,0x0007a5ca2258c4c8}, {0x000678f855fedfa8,0x00055199f43975cb,0x000e9a39edc6298c,0x00007312684e5a48}, {0x000adaeb9f55daba,0x000b39c9f5f377bf,0x0000000000000001,0x0000000000000000}}, {{0x0003e0968382a7ce,0x000869c70ffd115a,0x000ba001f2afcccb,0x000107bdfe8068fd}, {0x0000206868f7c124,0x000821a90928b9fe,0x000afc533728dac3,0x000b3e9edff0ac94}, {0x000d10c697f67565,0x000bea250773ba0b,0x0000000000000001,0x0000000000000000}}}, {{{0x000275a2c8f91400,0x000bb4c241f78224,0x000c4fd93b4ba60f,0x0002941b616268c1}, {0x00020107f7964087,0x00031b438825e04f,0x00019247786625f8,0x00028de20083c5f6}, {0x000abde39791c6d5,0x000b3b75c25ecfb0,0x0000000000000001,0x0000000000000000}}, {{0x0008e09f47b9d8c3,0x0009374c6bc5ceb5,0x00038e27941b3112,0x000e3235cee2666e}, {0x000ea8dbee896ca0,0x00030660009b498d,0x0005f8f0f2897645,0x0000fb5ee44458ff}, {0x000fb559aa7b5e14,0x000272ac85e138f9,0x0000000000000000,0x0000000000000000}}}, {{{0x0009f0c6193905a5,0x00013e99256667bb,0x00027fdbbfc34892,0x0000d2c71218ca33}, {0x000915a83f00e563,0x000d628331bdc8df,0x0003e8128ee96b80,0x00016a5f7e06bfe7}, {0x00016364a2a7cd33,0x000c748cd2a08bdd,0x0000000000000001,0x0000000000000000}}, {{0x0001d90fa51d3800,0x00020c814ecb8822,0x00000fc79208b5df,0x000f252076343a10}, {0x0008a14b68032c99,0x00054fe0dc71413b,0x000d97c9a173cb46,0x000c85a386e9a9ac}, {0x000bf160a14a40bf,0x000032849e997087,0x0000000000000001,0x0000000000000000}}} }, {/* digit=45 [{1,2,3,..,}]*([2^180]*G) */ {{{0x000384b0dc2ffbb2,0x000e0c16c289b477,0x0009eabe48cf9601,0x000199d671ddca51}, {0x0006f3fce7863b3f,0x000e01be3ea3ecba,0x000b70167c58c7d2,0x000f4893679afbf4}, {0x00019a4362cb78d1,0x00061515a3d7fee0,0x0000000000000000,0x0000000000000000}}, {{0x000f2840f746e722,0x0002ef160c51fc25,0x00097156a16516e7,0x000e8398d9625db3}, {0x000d63f5b2c0ebf6,0x000c5b6523651404,0x000476dd10c4d87f,0x0001f40ffa318eef}, {0x000788025e5d3977,0x0003c298fa2547e3,0x0000000000000000,0x0000000000000000}}}, {{{0x000523e81658a625,0x000aef8e050759b2,0x000b0377d5042659,0x000b9ae72b36823c}, {0x0007eff957169419,0x0009705cebf46fc1,0x000bd18b61ce7ad5,0x0007a7135b602fff}, {0x000f2e092fe9192a,0x00074d30a3a8e596,0x0000000000000000,0x0000000000000000}}, {{0x0007c895ead96751,0x0006523da4889766,0x000467afe86eb732,0x000a5ee25b7a7cf8}, {0x00000f2568e46393,0x00079a3304b15dd0,0x00036bd203f1569b,0x0009a5e938c0d91a}, {0x0001da1271a34645,0x0004c688c575bf52,0x0000000000000000,0x0000000000000000}}}, {{{0x000c62a6b633bf04,0x0003c0eaef0121c8,0x00058d7354098cc5,0x000448cc925273a9}, {0x0006f73c56bf4c04,0x00042b800bc52be4,0x0008d6b39147d475,0x000444cb5cfe3029}, {0x000d4247fb2312e0,0x0007054c4d89dd9e,0x0000000000000001,0x0000000000000000}}, {{0x0000edd6a97a9163,0x000582ed4f4d5b46,0x000b9ca61309206a,0x000fafa93e18c6dd}, {0x000bda68f9bb8a3e,0x00070a52c8b2d783,0x0007728c0dda564b,0x000c0dc789e7dbe4}, {0x000119aa3e8a6481,0x000bed27f421a4e4,0x0000000000000001,0x0000000000000000}}}, {{{0x00001ee133405081,0x000b94055dadf3f3,0x0008803374bd3d6a,0x0000e431a078817f}, {0x0000ae1298465c73,0x000a08da98aae817,0x00076bc8b779119b,0x000c1b8f7410f128}, {0x000bc98dcbe46247,0x0001761805980867,0x0000000000000001,0x0000000000000000}}, {{0x0009de67dab5cae2,0x0003d2d0125b70f5,0x0008c5ad3a01682d,0x000cf59a9c7c1b26}, {0x000ada095cf6362f,0x000b79b1ed6482c8,0x0002b3bc253c84e5,0x000756917d1dd695}, {0x0008f439fdfad9c3,0x000651a63232aa5c,0x0000000000000000,0x0000000000000000}}}, {{{0x0003a055275e1f13,0x000bce620ca4b51f,0x000765c9fcc48133,0x000387e5710e23a7}, {0x00041d9c294797a6,0x000fe4eedda6621b,0x0009f733bf9d9ac9,0x000e4cb8a3045df1}, {0x000d5c96c4f51d70,0x00041a25c50ad245,0x0000000000000000,0x0000000000000000}}, {{0x000acd86687a04f6,0x0009bc4b6a5c45b3,0x0003f85a2b09f7d1,0x000f69420758494b}, {0x0007e554c9337d50,0x000ccb9c2f40c240,0x000e482c5dfc1a60,0x00016ad44e8b11e7}, {0x000d080e60fea531,0x0001889fd549f4ed,0x0000000000000001,0x0000000000000000}}}, {{{0x0007e29c5ef5cdd9,0x00046b2b2e558b7e,0x0004702314f3e6bc,0x00026fae56eeaa30}, {0x000145ca44a1b067,0x000ea8da792ee6f2,0x0007e4c829cf9680,0x000d723cb279141e}, {0x000c514c645b326c,0x000b3d5e8e8931da,0x0000000000000001,0x0000000000000000}}, {{0x000e5ed0862bd48f,0x0009404a34e74e61,0x000e1d4a98483644,0x000f45001f65c56b}, {0x0008e062ee7183e5,0x000a39ef75aa764b,0x000f4509012ed646,0x000742837f0ebdde}, {0x0009ab588faa786a,0x0008d7474accf0f8,0x0000000000000001,0x0000000000000000}}}, {{{0x000f31aa7add26e0,0x000b5f70683b341e,0x0002190eb5f5ed33,0x000e3b2bf3278604}, {0x0002cdb29e4008f6,0x00042f0700c911a6,0x000f5e3688f5189d,0x0007c2de5c257eff}, {0x00089c193e2d4667,0x000cca5de47c9861,0x0000000000000001,0x0000000000000000}}, {{0x000dddac10383cca,0x000803caddccaca7,0x0000778df17cf555,0x0009278c5faf93e7}, {0x0000e7cfbb523b02,0x0003ef004ba7546c,0x0007290d52d052d3,0x000f54a34c36c895}, {0x000e1b89dcc555fa,0x00058777136cbca3,0x0000000000000001,0x0000000000000000}}}, {{{0x00060b5ef6c20e82,0x000bf430fe1ead47,0x0003a480e70d1479,0x00097c0aba684ec7}, {0x000549990971954c,0x000a1c5645d306cb,0x000cc85cc5c264ce,0x000739efac323d9e}, {0x0003b20c4465cbfa,0x000b4ee9cad749e6,0x0000000000000000,0x0000000000000000}}, {{0x000242934808827e,0x0008a9860bc18213,0x0007a452bdb41b29,0x0006c3f651ceda44}, {0x000f153ca2965078,0x000e0cd8cc7845a5,0x000c9cd5913baf87,0x00050312de2e060b}, {0x000a1444279bfb31,0x000ff8a16f8265f7,0x0000000000000000,0x0000000000000000}}} }, {/* digit=46 [{1,2,3,..,}]*([2^184]*G) */ {{{0x00033bcc8924eb55,0x0002e9d518ffb740,0x0001ae0cd732da2c,0x000cfbc19a4290d6}, {0x000d8784c1f06357,0x000fe209893ca1ae,0x000969a85a8dedb3,0x0009c8eb2e932f87}, {0x000bcc740550ff52,0x0004f554bf85aafb,0x0000000000000000,0x0000000000000000}}, {{0x000bc6372d7f8438,0x000dc0557f4f2ed5,0x0009d0c30f3c2efb,0x000ddabb262ac2fc}, {0x000f7a05b87d4d5d,0x000c91e745769d1c,0x0008c994d0a4907f,0x000889250072dcd3}, {0x000ffae1ac453a28,0x0002a8e72458000d,0x0000000000000000,0x0000000000000000}}}, {{{0x000d9177fbc76a5c,0x0003975e3cbf7406,0x0002f09def039ed5,0x00034da80caf736f}, {0x0008efcc790febc5,0x0000ad47e746448c,0x0001ca336b92fa7b,0x000b90e92c64c767}, {0x000dfd8d6637080a,0x00032f5711517b52,0x0000000000000001,0x0000000000000000}}, {{0x000a0257ff4a1581,0x000bc02441238656,0x000364971ed77234,0x0008b1d09b2d316f}, {0x000bfdf4ae5e00cc,0x000468fa8d307856,0x000805be3791c041,0x0003fa589236fc69}, {0x000a337620c1fe73,0x0001e737b5760989,0x0000000000000001,0x0000000000000000}}}, {{{0x000e1990ae2c44bd,0x00083ee2175b6a29,0x00005d1fb5989698,0x0001375eaf1c4bd3}, {0x0009f54aec5725cd,0x00017c1f0f7d222f,0x000f9f96b74e2d73,0x00053fff253f88e6}, {0x000b31a11aea1b12,0x000aa32748b4a307,0x0000000000000001,0x0000000000000000}}, {{0x00007b074c7b461c,0x000258e6e4224b52,0x000162fc7af983c9,0x0004966825052f5a}, {0x000f9138a0346a4a,0x000a7041242b7952,0x0000a366f5699476,0x000460c88c7d5eb7}, {0x0003f2b3125e31d3,0x0002a892d14ada09,0x0000000000000000,0x0000000000000000}}}, {{{0x00001e6a21a7b432,0x000c3971b4886b8a,0x000dae7cb7883120,0x00059d28f3efe6ce}, {0x00028e1699713fd6,0x000252af65756250,0x0002a3acd7c4a210,0x000f7efc9c5a81fe}, {0x000e2a5f82fab4ec,0x0005c0924441558a,0x0000000000000001,0x0000000000000000}}, {{0x000495dd493563c9,0x000ccadf9b0e7295,0x000ab5a8f70bb0fa,0x0005b32501ed29d2}, {0x00036f439adfe6b6,0x0000a6c7202e9c24,0x0006531bcd403e24,0x00064526a2b69777}, {0x0001dc2d590cd125,0x000b64170acdcfa6,0x0000000000000000,0x0000000000000000}}}, {{{0x000b0bb5e03ac48f,0x0009bb5837030273,0x000a05cded5e6ec1,0x0008034dce79ed12}, {0x0000fc54532094d5,0x0008fcc6c534a769,0x000bca87d8be0fee,0x00041150d981f9e6}, {0x000222345254c456,0x000b2aa496b6e112,0x0000000000000001,0x0000000000000000}}, {{0x000d2c8de5bb7e5b,0x000278f0be2794e5,0x0001b31bbb57b1c7,0x00001958330187ab}, {0x000f5dd751abf9bc,0x0002de4b57d090a0,0x0009cb74fbe565f2,0x000f83e310b95170}, {0x000d1301cd0ee2f4,0x00049fd2006501c7,0x0000000000000000,0x0000000000000000}}}, {{{0x000e8d883bcef9f8,0x000be3770de7cc8b,0x00007c65e3e95107,0x000ac96f780e3eca}, {0x000413d615089cf6,0x000585b5b22549b6,0x0008b5facd5da79f,0x000f3c8b5c5a4c0d}, {0x000d6dfaa970b49f,0x00065cc025c0e7ad,0x0000000000000000,0x0000000000000000}}, {{0x0003c64dd34154da,0x000343c797b7cd0b,0x0001f367813bc308,0x000fbf3f138ae118}, {0x0006f1f8c6302e7b,0x000f35ea2ee3cc54,0x0003a0b904ac34ee,0x00052596f106852c}, {0x0006e533ab1310ec,0x000abf763b19381e,0x0000000000000000,0x0000000000000000}}}, {{{0x000d9a73e24c887c,0x000707461d095f01,0x0005d3ad552ce968,0x000f402b6c527f5f}, {0x000818672d6016b3,0x000279bc4633dd66,0x0000c571c90fed28,0x000cee78b5512020}, {0x00048d6ae97b4812,0x00055292fa8b91d9,0x0000000000000000,0x0000000000000000}}, {{0x0004608b8c1577cc,0x00058615049c4716,0x00077fa05c3b187a,0x0000d33110dc1846}, {0x000554a923122c03,0x00015b3d3cf40b2d,0x0005e05a3843c4de,0x0006438408a6964a}, {0x0005f646af7c591a,0x000ae89a0f7132ab,0x0000000000000000,0x0000000000000000}}}, {{{0x000b5e462dd556b6,0x000f3aab5e9c2f29,0x00040c3ae00c87a1,0x000aade98fdfc7cb}, {0x000f2f671ec86f72,0x00069dd7b2aa376f,0x000b6f90c4b07483,0x000ae5c39e831a9e}, {0x000ef6929b8bdb31,0x0007125a4c5224c9,0x0000000000000000,0x0000000000000000}}, {{0x00080ab908d10b8d,0x000b7c8a32a9943d,0x00051b7d4fd0edbb,0x0008eaa89eb83ad0}, {0x000fb343de0ebbe0,0x000d3c4d0cc33cc9,0x000b15124b0953fa,0x0007582773fc9c30}, {0x000ab2c193a021a4,0x000b73ddfb881675,0x0000000000000000,0x0000000000000000}}} }, {/* digit=47 [{1,2,3,..,}]*([2^188]*G) */ {{{0x000f014ad29ca649,0x00075a10e7e9c3d6,0x000042dda6a91edf,0x00069276fbe9047f}, {0x0005a497f91416df,0x000b982ab7fce403,0x000b8b61e6adadfa,0x000d218a9fd9d973}, {0x0001c8c04e2c23f1,0x000cb12274d47d9e,0x0000000000000000,0x0000000000000000}}, {{0x0000ec3de397b98a,0x000d9a272cecd709,0x00050e492db6d724,0x00082a50e32d2f19}, {0x000db6bf40e9c68f,0x000b25727f0678af,0x0007a36e6ae78194,0x000cbb096d1806b7}, {0x0001afd3feedfa35,0x000e57c17d9b9ff4,0x0000000000000001,0x0000000000000000}}}, {{{0x00078e57ab05c549,0x00081a123d2b219f,0x000ecb0183ca3cf9,0x0008ed9f1eddfd07}, {0x0002f8f90e3c6699,0x000ad41bb20e0515,0x00019c77dab5c5ef,0x0002ca7830069394}, {0x000ae5cd1de605b3,0x0003933d6039cc98,0x0000000000000001,0x0000000000000000}}, {{0x0000ae5b05bb2b74,0x00071168c4bf8259,0x00001a66f3efdf4f,0x000e1da4a65b0015}, {0x000ba0665dbdf241,0x00015f360d4c3387,0x0004e85c88fe301f,0x000c061a8e048acf}, {0x000bcc0119ca9957,0x0009ea8585dfcf51,0x0000000000000001,0x0000000000000000}}}, {{{0x000c2a4869f8ca68,0x0005748af64adfdd,0x00044c661ce61bf4,0x000fa33532bda5e6}, {0x0004409ebd1c4df9,0x00063b107af0f45d,0x00013ef2dc8804b9,0x000a186c6c3f3d75}, {0x0005a7ed73f6b67c,0x0000b525bc5b72fc,0x0000000000000001,0x0000000000000000}}, {{0x00008fa0f93430b8,0x000bf3cdf63616c2,0x000a2ed8b79415ed,0x00008df169f3be1c}, {0x00006a9b7669442a,0x000be581a2acda6a,0x00093d2dae365779,0x0006ea987608134d}, {0x00059b31b3052589,0x000d8078ebfe0716,0x0000000000000000,0x0000000000000000}}}, {{{0x000a0e4faa59f069,0x000d33d96e52e437,0x00029f2632f3aebd,0x0000c85e4fd15682}, {0x000de4f3be7892c7,0x0007d9fb180a1634,0x000b175638b44c2c,0x0002e33499b53e6c}, {0x000cdad290b60dc3,0x0009d1cf1fcbab2e,0x0000000000000001,0x0000000000000000}}, {{0x0001854cefb1da9f,0x000257b5b7539f5d,0x00096df1240b9d47,0x000f9e9a561ffc72}, {0x0000d6d9452715e9,0x0005aea9109f0df3,0x0005d521e814b452,0x000c7037d6e74c47}, {0x00060afbb2239aca,0x000dfe3a178a1e6b,0x0000000000000001,0x0000000000000000}}}, {{{0x00085fac7aac5d24,0x000e6efcd816f4de,0x00001aa65b85ec90,0x00042ef288a94272}, {0x000527aa3e5baff2,0x0002c225dbf973aa,0x00073237d80e262e,0x000ac84d268b446c}, {0x0000056980d17882,0x000089041c6047c7,0x0000000000000001,0x0000000000000000}}, {{0x000f5b36106ae92d,0x000b658d82ab92e5,0x00036754a0792779,0x00032fae5cee6721}, {0x000bd0394c90fe6b,0x0001825f86d43336,0x000fa2e7d57eb880,0x00022294f3c7cd21}, {0x00070bb4a5b81f76,0x000e5c797152fbf7,0x0000000000000001,0x0000000000000000}}}, {{{0x000d4560b8c46ee0,0x000b73ca40a188f7,0x000b593661397fde,0x00026cffd18ba8cc}, {0x000c47a735170abd,0x0002887e49a94d3e,0x0002a2ec01caeb9b,0x0007426e36269901}, {0x000522aa9c52b5bf,0x00066af9e1ef518f,0x0000000000000001,0x0000000000000000}}, {{0x000d742afa309fe0,0x0006f810d9df60b6,0x000084e739c300f5,0x00056da63d1a036a}, {0x000cd4f33c2df42f,0x0000b456fee1f0f2,0x0008f569e5589fab,0x00062492c9b09b89}, {0x000079adb7885960,0x000cf412b618c75e,0x0000000000000000,0x0000000000000000}}}, {{{0x000e60d6e9faeb2f,0x000298054778495c,0x0000f99d00d5919a,0x00052dad049c1204}, {0x000e8b4f342e902f,0x000c225bd4b3fa2a,0x0004f48aaba21576,0x0009d33ad4b48b96}, {0x000a24fa9d5b26df,0x000f2799a4fd763d,0x0000000000000001,0x0000000000000000}}, {{0x00017650a566263d,0x000e25ee8cfe1893,0x000763623662e408,0x000a4360ad7e6d05}, {0x0000ba65a8e233ee,0x000338261baaa5ea,0x000af51b8dde194d,0x000003aaa23ac37d}, {0x000ab55391298a43,0x0008f52d2a4172a8,0x0000000000000000,0x0000000000000000}}}, {{{0x000760e887bee904,0x0009f91c8cff613a,0x0003af1d33766225,0x0002f55a798ee44c}, {0x0002c7171b76304c,0x00051b89de6b4202,0x000754ce995dc454,0x000a5d7e90f40166}, {0x00037fe2c45f5e9e,0x000d835f81a1be14,0x0000000000000001,0x0000000000000000}}, {{0x000c04a7dafbcd8e,0x0007d22e0b1aaf34,0x000ad92815662ecd,0x000b88ed3ef4d947}, {0x0000190778cccdc8,0x000ea32bf7d0a755,0x00094ed615d6df41,0x00066cdce7de3703}, {0x0005d94b6a5a2d85,0x000869b1500a755b,0x0000000000000001,0x0000000000000000}}} }, {/* digit=48 [{1,2,3,..,}]*([2^192]*G) */ {{{0x000556d5fcb0ca3e,0x000bb40eb6f5de7b,0x00092b00751e1fef,0x000d985badf10d77}, {0x000bda78c0fd8245,0x00097cec621ec6c5,0x0009de36f6534761,0x000929578b20f59e}, {0x00008129148b6a34,0x000260858df1e4dd,0x0000000000000001,0x0000000000000000}}, {{0x0002df7b80140bb6,0x000f0872cf54b64a,0x0005ba02c9e702cc,0x0006a4694fa2136f}, {0x000ae62ca46c9431,0x000a69d6c72a601f,0x000ff0af210ce686,0x000a108647e23ca9}, {0x00072d54b7301dc8,0x000b4fc0d011e4bc,0x0000000000000001,0x0000000000000000}}}, {{{0x000c2c9272139ecb,0x0008248890056b04,0x000319a82e4c5944,0x000bd6a55d37d95b}, {0x00074d80dfb735a8,0x000b368732a7edec,0x000dbb960fac47dd,0x0009b7d149244f46}, {0x0005c8153e4ae15b,0x000dd7d6f5637025,0x0000000000000000,0x0000000000000000}}, {{0x00023077c37f59fa,0x000e01c814ef1183,0x000d2dfe1b52b965,0x000d66c5cad600e8}, {0x00064cd44f8d02cd,0x000b170f04ad1f49,0x000b95d6b03da74b,0x0009721ac42809f8}, {0x0003fd08dc3ee705,0x0005bd69cd062aab,0x0000000000000001,0x0000000000000000}}}, {{{0x000b883d845a0ae0,0x000afbae353f2a2f,0x000473d0adeb61aa,0x00037ae3890f51bd}, {0x000480f0c4103d1b,0x000087e22deca493,0x000ae96c669a58f0,0x0000d7ec27b93462}, {0x0005f63a771fe3af,0x0004035d6f692734,0x0000000000000001,0x0000000000000000}}, {{0x00047ce82b6063a3,0x000a032d78ca1a20,0x000ffe80d92bf2a2,0x000357128144148d}, {0x00065f437565141e,0x000044794e70453a,0x000ed9d74d6e72f4,0x0002c9dec888c3b6}, {0x000d35b1703c9efa,0x0005564a8b5ee101,0x0000000000000001,0x0000000000000000}}}, {{{0x000408c0ef420ccb,0x0003751466bdddb5,0x000686318317d090,0x000f5c351d77faab}, {0x000e6e1c56990fd6,0x00044f54fded7bc7,0x0007a03658746405,0x000acb87ac9e9b1f}, {0x000e1a951d060b45,0x0002d4d46b22b133,0x0000000000000000,0x0000000000000000}}, {{0x000b308639e1f9dd,0x00088fb9f340687c,0x000545e0d0da3dfc,0x0007c0127b5897e6}, {0x000708cdc1322bbf,0x0003ce8bdc5bfb35,0x0009aefe13ad9991,0x0006b6cb7333e158}, {0x0005d1b9d92265f8,0x00065e9dfffba15f,0x0000000000000001,0x0000000000000000}}}, {{{0x000dfc8b990a47ce,0x00010afcf7dc8ef3,0x000e84517ba6c8fc,0x0002906aab79d6ea}, {0x000563aab2198045,0x00005b6fc1e2c314,0x000e1c75139c8775,0x000f87b03c5339f9}, {0x00013db5c7dd8d56,0x000be729d4f04194,0x0000000000000001,0x0000000000000000}}, {{0x0003ca2969a49a45,0x0003d7263734a805,0x000a96220f01659f,0x000a81ea503a05cb}, {0x0009a4b1e826b6e7,0x000b9124852cc317,0x000a53155592390b,0x000adcbcb9064287}, {0x000f6cda7ecb3423,0x000745fa7b75f585,0x0000000000000000,0x0000000000000000}}}, {{{0x000020f9870c5652,0x0008ed2cf4bf5440,0x00043a293130a211,0x000b5775772ea602}, {0x00033659b8c321b9,0x000b8b914e8eddd5,0x00016d7acd2ea084,0x000600a84078289a}, {0x000073293df2fe16,0x000f1b7632be02d1,0x0000000000000000,0x0000000000000000}}, {{0x000ae60c00fc41df,0x000dee1aec5298cf,0x000dc3a384668cb0,0x00039330262dc7a6}, {0x0008200480e942b2,0x0007f1ad6908e660,0x0004d8902ca00250,0x0009dfae47555ead}, {0x000dd7fb7e96dfa4,0x0004d09336664145,0x0000000000000001,0x0000000000000000}}}, {{{0x000d1eaa79614564,0x0008f53026152677,0x0004e1ef41c569ec,0x0009c61bebc6f47b}, {0x0005a764d392b91a,0x00081c91fd03bca4,0x000d12e91e91f33f,0x000ceb9cb7de2868}, {0x0000e9b7cc6516bd,0x000c8bcc47c28272,0x0000000000000000,0x0000000000000000}}, {{0x0007539aee683a33,0x000df86171edb94b,0x000cb40fe4798476,0x000b93f35533bd14}, {0x0009da702f13dc6d,0x000ba7ad4d348188,0x000a392741f6a108,0x000c52b97e5c2cce}, {0x000568205c383605,0x000d4f58766e7a6c,0x0000000000000000,0x0000000000000000}}}, {{{0x000d3d9203521aef,0x0003dde5091b5f60,0x000ec304735ae314,0x000afe69e360b755}, {0x000f3119298c9f78,0x000c6a7738e3ed2f,0x000298a24d640365,0x00078b486bf006b1}, {0x000e9050b3448a96,0x000ac46d50f02b81,0x0000000000000001,0x0000000000000000}}, {{0x000b1ce68a1d8699,0x000b8559ff13a9f1,0x00023011f5efc1bf,0x0004e57b1d2b17a5}, {0x0008efdcb9ac6bec,0x00009c3a1153d5a5,0x0006b2a4b16461a1,0x0005a5edc709e6c0}, {0x000d62c80c93e99c,0x000b0218529aa94e,0x0000000000000001,0x0000000000000000}}} }, {/* digit=49 [{1,2,3,..,}]*([2^196]*G) */ {{{0x000e7cc655ddb9f3,0x00013549c78f7abc,0x0006489c7f6e90f1,0x000e52627145775f}, {0x00027c353f1cebe8,0x000a2f29fc36a4b9,0x0000acc3ef5baced,0x000fb8074e6a3d4c}, {0x0008d3fd643a9c64,0x0004c070fffe4c63,0x0000000000000001,0x0000000000000000}}, {{0x000fbd2cdf57826f,0x0005bd9bf19e6e5e,0x0007942ab0ce8665,0x0000c790e82b0e8c}, {0x0001e2f2b552cb1c,0x00090a098c9dab8e,0x0009810a67eba463,0x000c6a4756fc9b4d}, {0x000e8cb25c97785e,0x000215f5f5b6c18f,0x0000000000000000,0x0000000000000000}}}, {{{0x0002bf06c6b067f9,0x000a2b3dcbcaa8f7,0x000559f9fa4cedc2,0x00001ff4707cbdc6}, {0x0005eb59f1a1d653,0x000b9620b3fc409d,0x00091f76c53a5feb,0x000e766a3eea48b5}, {0x00013597ec3fc458,0x000a5eb4cf309e19,0x0000000000000000,0x0000000000000000}}, {{0x000b24162ae5ce89,0x000e57dda1da6f8b,0x00092393366cd895,0x000d0cbc02de8414}, {0x0007365ce8f0759a,0x000cfa2564893b65,0x000a74873186b40b,0x0004d0156cb04fbe}, {0x000490f66512a03d,0x00036b328165e70e,0x0000000000000000,0x0000000000000000}}}, {{{0x000d63dbde7982b9,0x000c29e4cd39f5d1,0x000aa87372309f98,0x000951ea561fec44}, {0x0001afd07b42ddc9,0x00045755866c4665,0x000b2e07bf78c6a3,0x000e9284f87ca447}, {0x00035d4199cdea2e,0x00049a677e175372,0x0000000000000001,0x0000000000000000}}, {{0x000229ff95010f5f,0x0003cbc8f306c814,0x0001a7861e7a79e9,0x0002d63c05616521}, {0x000d995f90f64784,0x0000e16cd8cf737e,0x0001408ff0413e3c,0x0009c3a4f30dedcf}, {0x000a0a6b443a170a,0x0006e0cc49b5c711,0x0000000000000001,0x0000000000000000}}}, {{{0x000ac308c74d834c,0x000a8dd825f7406b,0x0000fbb496f34b0d,0x000075e1de870fb5}, {0x000227841bcf2365,0x000b8e05ffd3c983,0x000e33dc39c86d83,0x0009f0fd6d0e74cb}, {0x000d62a5a8904ae1,0x0008c32b1e28056e,0x0000000000000000,0x0000000000000000}}, {{0x000d2a2671b67c79,0x0004494c1cde5597,0x000c0326e9105031,0x000b1ee150606033}, {0x00061f18317b0423,0x000cc474ed398c9c,0x000df4796a972375,0x000696b52ef07eb4}, {0x000ed96071372ae4,0x0005ffabf9d1feb1,0x0000000000000000,0x0000000000000000}}}, {{{0x00045b8e28f19059,0x000286054435bd90,0x00012ddcca1e377c,0x0009f510d747b1a8}, {0x000d3775c0ea63eb,0x000865c7834fcce9,0x0007bbad37d19f75,0x0007bbc7cb402eb6}, {0x000530a0f5327111,0x000908600a1a8bd5,0x0000000000000001,0x0000000000000000}}, {{0x000abbe5e02132c6,0x000b17b10fe3c6dd,0x00011b655993587d,0x0008aa4f1c163208}, {0x00092e7539751ad7,0x000229bfb751c187,0x00003ce5719f77dc,0x0009dd5c3eedf84f}, {0x000b8c257bb9c60b,0x000345e60da1b9c4,0x0000000000000000,0x0000000000000000}}}, {{{0x000e7d40935779ea,0x0002b583ea2a70e6,0x000137328e54c9ba,0x000501ecd4654390}, {0x000e5d733683ab93,0x0009f374dd118e98,0x000b90700d407bd8,0x000c13b0afb65295}, {0x00048095857db6bf,0x00070895fc47c66b,0x0000000000000000,0x0000000000000000}}, {{0x00037df304273762,0x00053684543a49aa,0x000af1483095c127,0x000176dbbf08a1c2}, {0x000fbbab267dccb7,0x000bd6efdfa7bbd2,0x000abfc8aeeb27ea,0x0008c902ad03e86e}, {0x0009e682a4e44e71,0x000fe0064991f1f0,0x0000000000000000,0x0000000000000000}}}, {{{0x000aed77f4d8e151,0x000d64f6fa111299,0x000d4feb2e79c04e,0x0007b4f97a120999}, {0x000d370550af65d5,0x0001340660d07357,0x000084ce4afb7c64,0x00040826e57205ac}, {0x000a7fc0bae197ca,0x0008238f07d6803e,0x0000000000000000,0x0000000000000000}}, {{0x000454a02cb353a2,0x0000deb5cdf6d6af,0x000f3bb89c8b32bd,0x000b355a1bd8c3f6}, {0x000e63db355ab5de,0x0005c6b3982f043a,0x000910f0e90987dd,0x0001380521adabe8}, {0x000fa044a4bf6a24,0x000fd8fb752ed23d,0x0000000000000001,0x0000000000000000}}}, {{{0x000fdd1be70b4926,0x0009a826f6dba658,0x000cb4e95121bc79,0x000f676af00f6eae}, {0x000cee75a521d56d,0x000eca7d7729d333,0x0002e5027fb68ac4,0x0004a49aec5f206d}, {0x0006a988faa272aa,0x00047f341efc691b,0x0000000000000000,0x0000000000000000}}, {{0x000df0f078415461,0x0006ca3afd9193e6,0x000e7785c7d78268,0x00030f1e3c2a9148}, {0x000aaa49f1fa54c3,0x000e96229782ded4,0x00093b6b845da08d,0x00020729c99179a9}, {0x000904b0df8fef02,0x0009cee6016c6aad,0x0000000000000001,0x0000000000000000}}} }, {/* digit=50 [{1,2,3,..,}]*([2^200]*G) */ {{{0x0008c22f80cbfbe4,0x000130943a347193,0x000e2773aac837e8,0x000010c64a3c4f46}, {0x000be2b750229f24,0x00007131ff138446,0x0000ce7731813b90,0x0000e94672d6c2c9}, {0x000dcb075dd149a0,0x0006d07531381b69,0x0000000000000001,0x0000000000000000}}, {{0x000b38c7be8e6de0,0x000a9739ced7c6b6,0x000a61fbc4fb63d5,0x000fe4d18f6b6bae}, {0x000bd6ae1dbab075,0x0002c3dbf8c1ebed,0x000b0516dce109a1,0x000e4a2962c4c087}, {0x0000db685a1e1733,0x0001ad9f800e79f4,0x0000000000000001,0x0000000000000000}}}, {{{0x0003feea78bb9ff0,0x00046e4fde5cbe66,0x0003f440437dd027,0x0002a08933232942}, {0x000e421f2f6038cb,0x0008d7b95a50b4f0,0x00073ae18c0b0f4a,0x000bc9451cc035a4}, {0x0005154ba8955b22,0x000d349d1fd0859c,0x0000000000000001,0x0000000000000000}}, {{0x000f04652c1a8bcf,0x000b73e19db868af,0x000eea574f2961dc,0x00027664f8c3e1f9}, {0x000839b512b73f43,0x00002a0ec5b683e4,0x000b38a0fb615a0b,0x0001b1e55bb87991}, {0x0003094173f71955,0x000d3c0ba8f16419,0x0000000000000001,0x0000000000000000}}}, {{{0x000ed0fcb63247bd,0x000c61e26950f920,0x0008ac76960a5916,0x00049cfc2ae5b02a}, {0x0008cda5eb1a5171,0x000118595b5c8f4a,0x000c88e0004518e9,0x00089dcbce699e0c}, {0x000dca7cdb0b0583,0x0009678f7a0d455e,0x0000000000000001,0x0000000000000000}}, {{0x0003e3080d452c74,0x00067cd9ebc5ab77,0x00092748ad132f85,0x0000eb812f890896}, {0x0009083d0c649d6e,0x000d13cd26dc1732,0x000539d6815ffdae,0x0007727168b4775e}, {0x000ad256509166ff,0x0001747a36c1d3bf,0x0000000000000001,0x0000000000000000}}}, {{{0x000e6e936a559258,0x000787f262712646,0x0007ee8f55296d6c,0x000b44326540e78b}, {0x000ef2fb8850453e,0x000e4739b6073a9c,0x00032c19bbfb39a0,0x0005bec805ba5b65}, {0x000b74df44331c49,0x0009d3002e8ec8ed,0x0000000000000001,0x0000000000000000}}, {{0x000d7ba6c48685b3,0x00073d4bae18cecb,0x000a9e818b43a66d,0x000e109d5a439da7}, {0x00084e2bd60c3422,0x00082785ad715748,0x0009a5bf6bd330b4,0x00066c8383da8c0c}, {0x0009a00bf0007cc5,0x000256a489783e2a,0x0000000000000001,0x0000000000000000}}}, {{{0x0004a8e407a2ccd9,0x00086ad221fba29d,0x000fddda1e9d46ad,0x0008643114fcb5bf}, {0x0005a60db0e24f96,0x000659be98b0468c,0x0000c785c91bca8a,0x000b1e072204cabd}, {0x000ebbe04d9453df,0x0007688aef77cf50,0x0000000000000000,0x0000000000000000}}, {{0x000b62e349b426c5,0x0004467872d194b8,0x000ddbd4e1c43334,0x00024117aad0f260}, {0x000ea7d8cfb9c423,0x00083e18f4bd6c92,0x0008dd5687682258,0x000359ac483a7289}, {0x000ec708225923bd,0x00062148de2e57ff,0x0000000000000000,0x0000000000000000}}}, {{{0x0004d07f78796d38,0x000a0307a33d42f6,0x0008948a2a44d434,0x000f90db03ccc6f0}, {0x000696ff7592ebb8,0x0007ff2ae969af49,0x00014fcec7fca3c8,0x0000d6cec6f56874}, {0x0009ae9c6b325541,0x0003ea961c98239a,0x0000000000000001,0x0000000000000000}}, {{0x00084bbf91f7e4e9,0x0009ac472d023742,0x000d63ca5a686ea8,0x000614346cd552ac}, {0x000072fb24ab8e61,0x00080d3677dc07d1,0x000c8c0d1833f7c8,0x000717c50635d225}, {0x000f8a2192bf84ae,0x00027f2e83c678c1,0x0000000000000001,0x0000000000000000}}}, {{{0x0007ea965c0d1be3,0x000dffe0762dd1bf,0x000d60aa7917e003,0x0002fc7262c54da8}, {0x0004421eaa7edfa9,0x0002c86ea7ff6dc2,0x000473729f82d5e6,0x000d535c6df46821}, {0x0004bda6bb69bc00,0x000b33f34e260149,0x0000000000000001,0x0000000000000000}}, {{0x00096ecec3563dba,0x0004fd12da169210,0x0002f945903cc5db,0x00014cb4c4f95586}, {0x0007af70f6fbb150,0x000a6967e23d80e4,0x0003ebeadb489f20,0x0006a009490665a1}, {0x000afaa96a28958e,0x000a31da82221f9f,0x0000000000000001,0x0000000000000000}}}, {{{0x000b5dfd8f4cc713,0x0009de59f2c453ba,0x0000c9b2cc1e3fa6,0x00033c17b6318b0b}, {0x000e92d5d399a56b,0x00008f8a6f6dc3c1,0x000b7f39e28633ff,0x000ff1fbcd4351ff}, {0x000013e8c77388ee,0x00066a953e5ebf9d,0x0000000000000001,0x0000000000000000}}, {{0x000bfd2f419a3879,0x0001d195e5a481bd,0x0001ef3e1ae017a3,0x0008b706b5b37267}, {0x0003f748e8ba9898,0x000e9de7d3391698,0x0007cde6e3e3c930,0x0009ee4ca324e7e3}, {0x000b6a772ae3cdd9,0x0004235fda48d82f,0x0000000000000001,0x0000000000000000}}} }, {/* digit=51 [{1,2,3,..,}]*([2^204]*G) */ {{{0x000ce56e11c7765f,0x000fe4cfdef6377d,0x00035b399363df3d,0x000ca630a715e9e9}, {0x000a21011f820ffa,0x00022d3bc633f64d,0x000dab0c59875522,0x000dc95736a8523a}, {0x0008fef5b787c715,0x00032a66393c6305,0x0000000000000000,0x0000000000000000}}, {{0x00034ecf897f6f48,0x000d40891f4ace54,0x00051c5f6bf7708a,0x0007ca62fe89ee25}, {0x000eae6011a07c37,0x000028c949d24cd2,0x000ab99c094a1a4d,0x00031fed19d9cf84}, {0x00051c154036f7f0,0x0003d437b50c3205,0x0000000000000001,0x0000000000000000}}}, {{{0x00036aa0bf5fef4c,0x000b4bb069d26c89,0x0002e3dd1d0d3718,0x000bf3daeaaab400}, {0x00076315a34c426e,0x000eb5f38604c676,0x000805197e2eb1b1,0x00037226db1abc31}, {0x0009ad73df5e17eb,0x000d3797d098f510,0x0000000000000000,0x0000000000000000}}, {{0x00082cf0882acea0,0x00006b48806f5a59,0x000abd275055f094,0x00049a504db94328}, {0x000ec38e43c40b3c,0x00082b99e608d386,0x000cf443b07fe475,0x000b7186cac29089}, {0x000d982cfac474a1,0x0009aa7b0368d422,0x0000000000000000,0x0000000000000000}}}, {{{0x0006f1287e600c1a,0x000cffcc5624ecb0,0x0002d1ca07fb78a4,0x000a1f9666cc7bc9}, {0x0008539fb634b6eb,0x000c73e361397798,0x00014a496c8d68c2,0x000d7ca4181be620}, {0x00069a299a451732,0x0001c06004061fe8,0x0000000000000000,0x0000000000000000}}, {{0x00029e4b308242d0,0x000a13eeecee128a,0x000f659548ea451c,0x000490cf14707b99}, {0x000362f80a26ba79,0x000292eee64971fe,0x000871b89c8fc38f,0x000d6dc0d122e55c}, {0x000979f11919fbb1,0x000f85c98fe350a4,0x0000000000000000,0x0000000000000000}}}, {{{0x0006cb60e51b31a9,0x0009c2f6d82cb3ba,0x000f86e04fd98949,0x00087bb6cb66fb0c}, {0x000cb7e6257cf354,0x000caa5a38dbe642,0x0007ff70132dd977,0x000a9fe7cec8cf0c}, {0x000f2a9f98b24a15,0x000c7552eb7ce954,0x0000000000000000,0x0000000000000000}}, {{0x000aec9e842f8ae5,0x00096d766fc55447,0x00099065768ced0e,0x000adad9493166bd}, {0x000c328be045e2b9,0x000e70d305222a08,0x000ec1d4f554727a,0x0002fed1873d61d8}, {0x0001c46d541e23d8,0x00042ef348b3f19f,0x0000000000000001,0x0000000000000000}}}, {{{0x000ccf976377d19f,0x000f1cf68ff2fc1a,0x000d98b274ba0faf,0x000788c074f0bd37}, {0x000a798f5cd04250,0x0003cafaaeab508b,0x0009fd1e881c2856,0x000dd63706ee8361}, {0x0001b79794f0ad14,0x0006f33d5c0505bc,0x0000000000000000,0x0000000000000000}}, {{0x000090b50612a9e3,0x0003e3a662f706ea,0x000cdebf25eed8bb,0x000d3a7d888eb094}, {0x000fdc87a6c4d17f,0x000574531e25001b,0x0007e6d823c00762,0x00014c6a486f9d98}, {0x0006d2d6573a4d0f,0x00074c191e9a8851,0x0000000000000000,0x0000000000000000}}}, {{{0x000d58220482e6f9,0x000c77488e8bdb82,0x000ba1084c7aabd7,0x000ae76567c7272c}, {0x00079ab82a151ca6,0x000826c75c1ca84a,0x000434806316ad0a,0x00040dd7f329f3c6}, {0x00033bd2dde3d6a0,0x000c43689c3e453f,0x0000000000000001,0x0000000000000000}}, {{0x00061be6ee98af37,0x000291b8361cc48c,0x000b8a7b622624c3,0x0000547d4c3e4e24}, {0x000c937a21d5f3c1,0x00007a153ffa09bf,0x000a63d54fa325a4,0x00048d13bea75c7f}, {0x000e1e55bfb7c45a,0x00055a1a8b85312f,0x0000000000000000,0x0000000000000000}}}, {{{0x000094bb55dffec6,0x000b1ee483a0b1a7,0x000e63531718eed4,0x0009354c0be15b59}, {0x00029a3b937fed84,0x000295e4506353d0,0x000205f7b6d68fbd,0x000e59b3375fdbda}, {0x000b4aaddd0cb573,0x000348c879da0f51,0x0000000000000000,0x0000000000000000}}, {{0x000afd066ea2106e,0x000ee293d8c45af2,0x000bc67374a1f66a,0x00016d7c0fd1fd2b}, {0x0002493231dcd541,0x00019502a277efda,0x0003c7872e2fab64,0x000a95c3d06567be}, {0x000fa48d7ff41d2a,0x0001cc69c52d2e6d,0x0000000000000000,0x0000000000000000}}}, {{{0x00046d25ca0b12ed,0x0003e7af11f36102,0x000d246f5c00ca56,0x0005f2713dbda22c}, {0x000571517fe92c1f,0x000e558aff5b82f3,0x000852ec7e4811aa,0x000a0a7d7a0cfe93}, {0x0009a571e80c69ef,0x000d5ecf0c8dc85a,0x0000000000000000,0x0000000000000000}}, {{0x000629e0362ea61b,0x00019570463933fa,0x0004d8bdb2997e91,0x0008d16c1670ff63}, {0x00042ac0e352c375,0x000bf5c218c31489,0x0009269789d4077e,0x000eedd9111468df}, {0x0009e59bdc949bb1,0x000694a97ced001c,0x0000000000000000,0x0000000000000000}}} }, {/* digit=52 [{1,2,3,..,}]*([2^208]*G) */ {{{0x0000e658f63653aa,0x000362a4e263b15e,0x000f1a72f5cb787e,0x0008dd85ade21c8a}, {0x0009351d6c477346,0x000ea4254fd69f8f,0x000c982ae15e0af4,0x0005dd836935db86}, {0x00023278398d3a2d,0x00082c5ffb0769dc,0x0000000000000000,0x0000000000000000}}, {{0x0002ae6ecd27779d,0x000456043db3d94c,0x00073642e7c09230,0x000692df6f9dd795}, {0x000422cd985762a8,0x0006ac0a49a83e72,0x00059cfa2e9e20f1,0x0000d0093708d3fe}, {0x000c84d0b10a4692,0x00035fa5bda12a10,0x0000000000000000,0x0000000000000000}}}, {{{0x0009924edfb9aeab,0x00028a46d2968a10,0x000fe84ed7a9147a,0x000478aa49744c91}, {0x00030fd88965188e,0x000dc8d99e65a34f,0x00006f221fd955c8,0x00027ea7cd997402}, {0x000f83ab9dedce89,0x0006e8a7c26d23d4,0x0000000000000000,0x0000000000000000}}, {{0x000728e182c8cb8b,0x00078b0fa5f32091,0x000760a4e2a3ad9d,0x0002b50f65aca369}, {0x0003d46ee027e681,0x0005a7e2b8db993f,0x00003752acac076e,0x0003a179054a6029}, {0x0007bff0fddbfa0d,0x0008feee0dfeeff8,0x0000000000000001,0x0000000000000000}}}, {{{0x000e1e66266af2df,0x0002e36c081c96d8,0x0002c3c896d714ef,0x0002acfe977ac59e}, {0x0001a95d1b3f90be,0x00003c79555da335,0x000ac68d1f4138b3,0x000d2dc5e8301aff}, {0x0007f5144ad06837,0x0000d0ff81349a59,0x0000000000000001,0x0000000000000000}}, {{0x0003ebad0af48caf,0x0005e5d9aadd9976,0x00026bfaeb96c7e8,0x000c9ceb03564b50}, {0x000254586ab1371e,0x00038a2ddf7b0228,0x000ca35a77209961,0x0003fd9f60e7f5a6}, {0x000f0eb7073273c4,0x000a1bce76f5e62d,0x0000000000000001,0x0000000000000000}}}, {{{0x000a60a63bd16196,0x00077f090aae19bd,0x000e7638c32cb3f5,0x0002a6ddf59abf93}, {0x0001d3548613634b,0x0001b5e6513c50db,0x000b5bd49476ec89,0x000a83b636d2f4bb}, {0x000071e3a3dd95f7,0x000ef977c02f69d5,0x0000000000000000,0x0000000000000000}}, {{0x0008603799531d83,0x000ec49c9ad3cfc6,0x0004e50cb9635f1e,0x0003ca9d26b39588}, {0x0006f3bd6a0e5d70,0x0008ef03a93fe903,0x000aad2605b0ecc0,0x000b6abd3a9b070f}, {0x000a81977f3494ea,0x000831164f95f67f,0x0000000000000001,0x0000000000000000}}}, {{{0x000d576c129bba19,0x000dc781b1958f67,0x0004c725830444b8,0x000d772989a02957}, {0x0003160191e1f14a,0x000b3aba62ef31af,0x000a9c026782cae3,0x0005e2df9de1d797}, {0x0007d5d393897669,0x000e09de2e3f7f60,0x0000000000000001,0x0000000000000000}}, {{0x0002f590d9230f6d,0x0008e59ce71ff8f2,0x00065bfab0b97ecb,0x0005b773840ae894}, {0x0005df550efa55da,0x000a03525e361e4f,0x00032a275d9fd4c6,0x000f30d16226c4bb}, {0x000512eb88ebc1cc,0x000a048dd37790a6,0x0000000000000000,0x0000000000000000}}}, {{{0x0005c82e7c82fe0b,0x000b6b153f48688a,0x00079cad28ce32c1,0x0004dd65d7330f19}, {0x0005fd6ce0841643,0x0004ad25ddac7886,0x0007705833e0df48,0x0008294753bb4502}, {0x000ad8dbbbf63937,0x00019b436c10a463,0x0000000000000001,0x0000000000000000}}, {{0x0005b7516a304d40,0x0008185865f25816,0x000cfc1c163a4965,0x000ed7eed35d77f6}, {0x0002d2246fce8e80,0x00064fa59660ff02,0x000081304ce77dc8,0x000c6fc813dd85ee}, {0x000db13057fabb84,0x0008d66a509ef64a,0x0000000000000000,0x0000000000000000}}}, {{{0x000ae85bb3c1e90e,0x0001923787b4a031,0x0009e575e9892a6e,0x00074c2ebb769eea}, {0x00063064d9df4bf8,0x000e1bf584f54d2f,0x0007ecc49f863e83,0x0003213fe023848a}, {0x000c07e3d527042f,0x000c51626ab6da53,0x0000000000000000,0x0000000000000000}}, {{0x000783a377f5ac26,0x00010cfafa402a74,0x000f762b70abfb39,0x000eac42e208b3a1}, {0x000497274db0b567,0x000b54ede1f18ddf,0x0001de4808fda6ea,0x0002ceac81237a87}, {0x0007edd6e7428e9d,0x0000cb9fb5801abb,0x0000000000000001,0x0000000000000000}}}, {{{0x000205d81676b493,0x0001cfe8f546e257,0x00087afe8b644287,0x000676bad5e346c5}, {0x000f4a964afa3748,0x0001422f71ca39ba,0x000328b0e9e0a58e,0x0001d31cca18d62c}, {0x000787f6507714d7,0x0009ad810168e375,0x0000000000000001,0x0000000000000000}}, {{0x00030f78aa1440c8,0x000f7e509d6354b7,0x000beae80e0ec14f,0x000f7cc09793053f}, {0x00025b6b1fd1b019,0x0004558d48e4fca0,0x0002aae7ed4a0374,0x00070e2db1c48699}, {0x0007f4b02f033375,0x000af43011764955,0x0000000000000001,0x0000000000000000}}} }, {/* digit=53 [{1,2,3,..,}]*([2^212]*G) */ {{{0x00015e37a2d438c7,0x0006bb436c808cd7,0x000782325918615d,0x000d68ce58c6e6b2}, {0x00075a40e8f75ca6,0x00001da381c4c378,0x00055d9be962879c,0x00075dd3d4cf58a1}, {0x00099fd85847d5de,0x000e158f7f76b4ee,0x0000000000000000,0x0000000000000000}}, {{0x000c9f66a4cec18d,0x0006e45302a76bd4,0x0001b679cdf64708,0x0002c24293b84a7e}, {0x000a092243bc4d41,0x0005c3c375519ccb,0x000d06b585371f2d,0x000590f4c0f28ba3}, {0x00073b4091daa768,0x00073c6342e78bf5,0x0000000000000001,0x0000000000000000}}}, {{{0x000dcb7fa9fca3c3,0x00047144679a2a9d,0x0003be369b38069c,0x000a82620de84dbc}, {0x00098d5e1f28d82c,0x000205de8989e877,0x000abac84051f10a,0x000ac26a5b9c5c22}, {0x00074ecbb99bba5f,0x000253359fa6c2dd,0x0000000000000001,0x0000000000000000}}, {{0x0002ac09a82c210a,0x000b422ac08c572e,0x000c5c720e071535,0x00095966a7bd1c3d}, {0x0003a0a4b0c9e18f,0x000faa6c6449a62e,0x000bdd44f85595c2,0x00047bb9f75f529c}, {0x000f46a6493955cf,0x000622defa5af650,0x0000000000000001,0x0000000000000000}}}, {{{0x0006df335e8acd01,0x0009b6996f91a727,0x0008be8a5f6bba5b,0x0006ef24a13311be}, {0x000b7fe2a95d51f2,0x00084a38b4ee11ba,0x000caf93233a4f76,0x00073771e4762ff2}, {0x00024adb050176c1,0x000a9e7e6a96ea5e,0x0000000000000000,0x0000000000000000}}, {{0x000540fbecee1541,0x0003f39f444fded1,0x0006ce01534c5cef,0x000a886125f5b460}, {0x000b437e2199b1d8,0x000a994fb5a77157,0x000fcae599e6b65e,0x0002599cf24da91d}, {0x0009f0d7248964c9,0x0007ac171d21915d,0x0000000000000000,0x0000000000000000}}}, {{{0x000ca4b8955dde0b,0x000f850c9b5cc251,0x000b99572d6cb500,0x000f8952b82356c8}, {0x00088575ebe209ee,0x00089253a4607df2,0x000ff9ba421a6b33,0x000799f0eb4dd513}, {0x0003ed789c84b56b,0x000293e6a5c4d425,0x0000000000000001,0x0000000000000000}}, {{0x000ff217c0f18530,0x0008986930ae0198,0x00012fd1e778abc5,0x000f509594fad4d8}, {0x000656733dccef2f,0x0006afad83f10fab,0x00078f717d75c593,0x00018a1a313cd995}, {0x000cd73871602741,0x000f5446078ec40b,0x0000000000000001,0x0000000000000000}}}, {{{0x00034871165b0407,0x00041aa1bdd6d509,0x000fcc9e894c7b1e,0x000369e1389494fd}, {0x00087f5116c5472d,0x0000a1b0d04b3663,0x0000b4c49058303b,0x0002bdbdc1d8cd26}, {0x000ae8f01c121d9d,0x000dc1d8c7270b76,0x0000000000000001,0x0000000000000000}}, {{0x000d922f0e06b7cb,0x000f07bd16843c5d,0x000c01dd32245ab8,0x000fa9f6081477df}, {0x000c2db624f56ea9,0x000b2fb3e2bccdb5,0x000cb3b768793cb3,0x000c8d894f04384c}, {0x00010a3af20b15d0,0x00045ab5af8411db,0x0000000000000000,0x0000000000000000}}}, {{{0x0006b9ed8590e4a5,0x0008a58a2974d283,0x0001c7668bc64c35,0x000acc81cd837cfc}, {0x000fc7b9eb02f729,0x000fee9d6ad1171e,0x000a8d7ca7eeb433,0x000a79ea2e79ed5e}, {0x0001fb8522e38381,0x000cc8162a76e7a5,0x0000000000000001,0x0000000000000000}}, {{0x000c67543c98a4ea,0x0001f713941c4de6,0x00081dc75d38a3eb,0x000374ce9c459cdd}, {0x000bdd7ff2d1d555,0x0000d7b03a560a54,0x000ad6193d7f976c,0x000099ff27e977d0}, {0x000749edcba5d394,0x0002c6804ed826ed,0x0000000000000000,0x0000000000000000}}}, {{{0x0003e3bd3291cd15,0x0006a26271a72635,0x0001ef4581082f50,0x000cb6109637a812}, {0x00043e376f158b63,0x000e1fb8b4f92150,0x000fd4238523b166,0x000edb09ffe09019}, {0x000a7d8e27b82fb2,0x0001989a4df94f9f,0x0000000000000000,0x0000000000000000}}, {{0x000410feb007ca74,0x000ed314198cb45e,0x000e234a35b4b72c,0x000c1779579fdfb5}, {0x000da54f63558ebf,0x000b68211f279305,0x000b7f7a88ea265f,0x0000914728cae4ca}, {0x0002ed65205137c3,0x00045ed6df45a086,0x0000000000000000,0x0000000000000000}}}, {{{0x0001cfb71cb23bf8,0x00067b25479ac001,0x0002f48bcdb785ff,0x000da267c454fd25}, {0x000154e460f65f62,0x0006fa21e0ac759a,0x000770bdb56d239e,0x000db91d7ccefa07}, {0x000f07f46fe275a8,0x000527a152927368,0x0000000000000001,0x0000000000000000}}, {{0x000969a0d74d64a1,0x00059c36f066b2d7,0x0003a664061d81a7,0x0008c41d929c3e1c}, {0x000a4033ad63b5ba,0x000387b665fdb5a8,0x0002e2c2b433c84f,0x000e4f2d4d931e74}, {0x000631141b030d2d,0x00086de3845c248d,0x0000000000000000,0x0000000000000000}}} }, {/* digit=54 [{1,2,3,..,}]*([2^216]*G) */ {{{0x0000c039d020c1dd,0x000d44ab7b690765,0x00026b42700b4f64,0x0002c1e20576d051}, {0x0009e70d2ad712c7,0x00015f46314322ae,0x000dfb189904b573,0x000124905a45ef02}, {0x00026cce68a7b470,0x0004ac5f0db2cade,0x0000000000000000,0x0000000000000000}}, {{0x00042cd205524778,0x0000d86fcfeb993a,0x0001cc7f2d2ee992,0x000c209546bdb299}, {0x000531516a6eab71,0x0005f1492f99e62c,0x0002cf5197ae7709,0x0002013e12e8e95c}, {0x000b78cb72aad7be,0x0000320e70b96760,0x0000000000000000,0x0000000000000000}}}, {{{0x00011fae297851e8,0x0004f69afd113575,0x000ab322fa242843,0x000f361ecbe5e3de}, {0x000b7c1b08880d89,0x000a50aa80c1fbd2,0x000104d9e40537e6,0x000ed4f51df57fdf}, {0x0008a6cfbe707164,0x000f36d887e3d0b7,0x0000000000000000,0x0000000000000000}}, {{0x000365e7f9a5983b,0x0003c6129d87d996,0x0002952186a64aad,0x00009284f8224d3c}, {0x0007bc689c1d4452,0x0003f44aec2c194d,0x00057e00e7c6b2d0,0x000de28c9eb3f18a}, {0x0008b7de6fac4981,0x000009552159064b,0x0000000000000001,0x0000000000000000}}}, {{{0x000147285c5f1e84,0x00054bbe273f4c79,0x000ec66bd4d71c06,0x000771b4dd0505e9}, {0x0002d4c891619ed4,0x00021a0542316ff1,0x000ffae0c65ede48,0x000db678c0c5a23c}, {0x000bbf48abf05e02,0x00032691ff4f9e32,0x0000000000000000,0x0000000000000000}}, {{0x0004ec586f495f39,0x0007665c351b2d94,0x0003939c0c800e74,0x0000a9b2fe310474}, {0x000c05e63ba55b78,0x00011119c911cfce,0x0000043322972c9c,0x000235f5ba3b0c8e}, {0x0002b78daa0946bc,0x000a82622257dc22,0x0000000000000001,0x0000000000000000}}}, {{{0x00053147b3b22c3b,0x00004897a83e73cf,0x000d11d0f510fba4,0x000de4abfcf9128e}, {0x00047095c92d56df,0x000f3cd334bcfa2a,0x0000038a5b6f4d4f,0x00095df73169a249}, {0x000aba80e663bcbc,0x000c64a47769e841,0x0000000000000001,0x0000000000000000}}, {{0x00004365a62c4cf6,0x000531a582938f21,0x00043321e6dc439a,0x00061253f7387146}, {0x0008352424fe3ee8,0x000a676302135902,0x000702fe71ab2ae0,0x0005f460396ca837}, {0x000882e04f7bce51,0x000f93d936239901,0x0000000000000001,0x0000000000000000}}}, {{{0x000dc17de84a8cec,0x0000802c374c6c6c,0x000bd6a5b20e3454,0x00046c40337b0f58}, {0x0003431d7aff9402,0x0001dba6a849292d,0x000f90b37486a260,0x000c12d61cbe41a0}, {0x00033f828782067d,0x000486ebc39fcd30,0x0000000000000001,0x0000000000000000}}, {{0x0006818da93cb68a,0x00039ef42673be02,0x00040e906d3f2e27,0x0000e1f1d8ecf6f0}, {0x000655c024d3837b,0x000417cf596708c0,0x0000946c57882083,0x00058942a1031702}, {0x0009752bc7086a40,0x000474bd8d65b027,0x0000000000000001,0x0000000000000000}}}, {{{0x00057bccc2137aff,0x0003cdce9d3ef437,0x000021aa7d7b10a8,0x00014071804bf03e}, {0x0005009822fa479a,0x000c4d2fe91adecf,0x000bad18fc3b061e,0x0002ffe82ea4479f}, {0x000b0bed7b70c576,0x000d5c8a667da425,0x0000000000000001,0x0000000000000000}}, {{0x00036c22b574750b,0x0001a79beeade4d8,0x000d7c41634d28e0,0x00030d7e124715f6}, {0x000b28e33c4f983d,0x000442a0682ee2bd,0x0000a48a18cfc1f5,0x0009a6cb16376839}, {0x000ecc58844abd78,0x000383bd6682cba8,0x0000000000000001,0x0000000000000000}}}, {{{0x000c36944a224339,0x0002221a86a3568f,0x000a933230388a55,0x0002ca0cfc1f186c}, {0x000051f24d4d5f8c,0x00053ac024a82a69,0x000e4e0b6761f2a7,0x0006b4a03fa98a0f}, {0x000862d5fd1d2058,0x0006922bcb9949cb,0x0000000000000001,0x0000000000000000}}, {{0x00085574f50da47c,0x000f8cb1192295a2,0x0002436f1d423eb5,0x000f6ae23f4febd2}, {0x000640f1f266f842,0x000e94d3498091b2,0x00016f1f4561f25e,0x000c6e303b526f4a}, {0x000bbc14e80ed7ff,0x0009ac6f957c1908,0x0000000000000001,0x0000000000000000}}}, {{{0x00089a398d206da8,0x000e6a92326c61c3,0x0000b658149c80b1,0x000f4f6423067f4a}, {0x00022c96735aed5c,0x0003cb53c31cf4dd,0x000c7214b478ba14,0x000d3b1bbb1eb353}, {0x0005aa79b46f2e84,0x0007d44a4fa3d67b,0x0000000000000000,0x0000000000000000}}, {{0x000d31f07cf711e2,0x00031e5402e45d5a,0x0005565057819f0b,0x00050ebe214cdf81}, {0x000e63efd8e063fd,0x000c82d63ad808de,0x000d0ee39ccec300,0x00085249be7d39df}, {0x000e9271ab6c788e,0x000a727ffa3cadeb,0x0000000000000001,0x0000000000000000}}} }, {/* digit=55 [{1,2,3,..,}]*([2^220]*G) */ {{{0x00061361be3ee97b,0x0006e1f3125658fd,0x00096b636a1d69b6,0x000b9e470c7ac9e9}, {0x0005bf9bb3617e69,0x0002050a8c1b1e89,0x0002213fa5a11a51,0x000bc2919affa249}, {0x000be1b1008d55c3,0x0003926dcf2c08c4,0x0000000000000001,0x0000000000000000}}, {{0x000fb57fda93efc6,0x0008276ce4aac2b4,0x0009277cab16292f,0x000e677dc90518a9}, {0x000ab0432d015144,0x0005d9214eea4408,0x000b8a649b20eb23,0x000b48a45d8a2560}, {0x000cf7d1d37dd269,0x00049d71a47616ce,0x0000000000000001,0x0000000000000000}}}, {{{0x00034d86d189072b,0x0000b9475ac257a7,0x0003a9d12f132433,0x000adf08cecaa5dc}, {0x000dc33641cc3048,0x00040352a6bfcc4f,0x000dac876f01bade,0x00035bd7dfb06e93}, {0x0001d4494c0e1ca5,0x000219b51965b8b2,0x0000000000000001,0x0000000000000000}}, {{0x000f90e9be7f6998,0x00040776cb857a46,0x00031907caf1b517,0x0007040038843e17}, {0x00014b3c14ab5377,0x0008c99d12b47cfe,0x0001590d18daa185,0x000f84db2817d455}, {0x0008544bbc4d8f7e,0x000ee1752b595c5a,0x0000000000000001,0x0000000000000000}}}, {{{0x000718c9c3382876,0x000798d016412ea8,0x000c7059eeb3d459,0x000e910707afd251}, {0x000366ae603f57f6,0x000f1d424b7c29b3,0x000f4591f08b6d11,0x0004fa0b188406f8}, {0x000a09ce46dfa46f,0x000f3e1ee6193a22,0x0000000000000001,0x0000000000000000}}, {{0x000ef37aacfd9628,0x00044abc282a7b59,0x00016eca5fb04908,0x0002a4a0fa414af6}, {0x00010748c915edd4,0x0003d4af5a6f1ab8,0x000aff331ef86bba,0x0006d8ffc35ce768}, {0x000278d36b6c4e53,0x0006238f61ddd56e,0x0000000000000000,0x0000000000000000}}}, {{{0x0008204ec1fe994f,0x000a401febacf810,0x000a1fbe66e0a0c3,0x000654b72570b727}, {0x0007b5299d8ae343,0x00058b323a83e064,0x00034d13d86ee0d1,0x000be946224b7585}, {0x000a38321cb77d0e,0x000ea9b845ec39e9,0x0000000000000000,0x0000000000000000}}, {{0x00021327ccd07b3e,0x000b9c13edfc5044,0x000efee69b80c4b9,0x000b9736ce07a452}, {0x000de2779de28110,0x0009cb506b810433,0x00009831468d2371,0x000fb54615eed293}, {0x000a72f30895d360,0x0000822a939f9fa6,0x0000000000000000,0x0000000000000000}}}, {{{0x0003613a0bad2c78,0x000a2841479bab61,0x000ae853dfe64b3b,0x000c5d69d7d5f8f3}, {0x000913c023c98edd,0x000e51c064c2af1c,0x000caf23e811beb5,0x000a297f73a13e28}, {0x0002c2db1b2c63f7,0x000869272783c6e9,0x0000000000000000,0x0000000000000000}}, {{0x0009e33e7c2b0e8b,0x000a6e2930859a4d,0x00021c82319f96d2,0x00062855234b3a37}, {0x000cfe1e952c7999,0x0009fff526834c3f,0x00082932d66290aa,0x000ed0618b6fc1aa}, {0x000f51b1765d795b,0x0000fa7ad3a784d8,0x0000000000000001,0x0000000000000000}}}, {{{0x000b99ec5345605e,0x000d705b03ab3b6f,0x000d514df02df673,0x000d979497926d51}, {0x000327f3cad9968b,0x00007b8edfa7bbd7,0x000fc5c1dee65278,0x00036db8f1709072}, {0x000d430f38a088d0,0x000f9df3373c9bfa,0x0000000000000001,0x0000000000000000}}, {{0x0002932b26523f7a,0x000a4698ce826d56,0x000d64992b915d43,0x000f137e0e1471fe}, {0x0006811a1c25612c,0x0007e5e74619907c,0x0000f455dcff6a59,0x0006fe503afcb4d1}, {0x000af47382daf8e9,0x00085e51a1e9e2bf,0x0000000000000001,0x0000000000000000}}}, {{{0x000c899ed52c7ebf,0x000805309ddc9f57,0x000f9ec0561000b8,0x0005599061be65ad}, {0x000c7c6ac2e8bdb7,0x000546a9f7f8f392,0x000b38f709f90fbc,0x0005b81ee256aa4e}, {0x0000cd9ffe3bb73d,0x000ad1e54f791392,0x0000000000000000,0x0000000000000000}}, {{0x000e432eaecfeb4f,0x000efd7d99d4376f,0x000ecbf257042314,0x0006524d0d11bf19}, {0x00070c070e8811a2,0x0009bb46ac80db71,0x0005deced6976256,0x0001f5d4f1996e7f}, {0x000c6d1bc35c855b,0x000b7fcfaf131b63,0x0000000000000001,0x0000000000000000}}}, {{{0x0007faf89dff5e6d,0x000701e289504c4c,0x000c21c143d7c67c,0x000b8b1051104808}, {0x0001a8547ea3f429,0x00042d1597643f8b,0x000c20d8e30463a4,0x00019700b9ca1322}, {0x000c7c74112313e3,0x00021d429e582d53,0x0000000000000001,0x0000000000000000}}, {{0x000df174dc25e320,0x000421f30a9c65a6,0x000cca7bd70734a8,0x000970e912f441c1}, {0x000b0da35c85642e,0x000fbc6108990f29,0x00004f9201a5ca87,0x0000b4ba5b8a0067}, {0x00032f15dd79c420,0x0001dcaa2c572053,0x0000000000000001,0x0000000000000000}}} }, {/* digit=56 [{1,2,3,..,}]*([2^224]*G) */ {{{0x0009f88e8ef42daf,0x000fa3828b99d9e1,0x00051fa512ec2bee,0x0004d684d33e3c3c}, {0x000ae34a6c37abe1,0x0009d4bea55b5936,0x000e6492802583c8,0x000098da605bd938}, {0x000288cfc1f04542,0x000ed0659c47e455,0x0000000000000001,0x0000000000000000}}, {{0x000ddaea5046a68e,0x0003e422472a49b9,0x000c2da95690aefe,0x000dcef36e21cee3}, {0x000eab14f0abf0c7,0x00064941e198c3c9,0x000fcf64819eee0b,0x000dbfe77fa8433c}, {0x000c3b28a2f7686d,0x0009c3dbfd233403,0x0000000000000001,0x0000000000000000}}}, {{{0x000b7107c522fbbd,0x000c42e8887082c3,0x000cd304c29d218c,0x0004d8477a96d44b}, {0x000ecee7f483ff1c,0x000951d19c530d4b,0x000d68d4d6bf1fdc,0x000fe03d009b71d2}, {0x0005537694d3bd1d,0x0003c3db4cb1a2c4,0x0000000000000000,0x0000000000000000}}, {{0x00086f0e3fa15f33,0x000388caf5fb4c5e,0x000b2f14ba7715c3,0x0002610381191db4}, {0x000e0f68a08e3384,0x000342059cb75d25,0x0002bd292f767fcd,0x000a7a696b414dec}, {0x000dfb67016057d6,0x00035999c277b18a,0x0000000000000000,0x0000000000000000}}}, {{{0x0008ba73e1f475e0,0x000dd3f1b783f77c,0x0007375b491b116c,0x0007d166e4a377a6}, {0x00011bc5434f7131,0x000a2dbe9d40b215,0x0001220856a6b5e6,0x0007b890e757f7e0}, {0x000f02578a944660,0x0004883ff77008f5,0x0000000000000001,0x0000000000000000}}, {{0x000a3e2632a212b7,0x000302b8f038a3d8,0x000a306506181a49,0x000301702b3192c1}, {0x0002c30f8e6d2d73,0x0002a0c5b0c340d2,0x000f8bfe6e8c90fd,0x000e8d703d0478e5}, {0x0005135b5979aaf2,0x00034da81fa7add8,0x0000000000000001,0x0000000000000000}}}, {{{0x000f16b10733860a,0x00007e088e20bfd6,0x000859fdd39b30d0,0x00096072d4c40b6e}, {0x0007d0a59d2a4c91,0x000f5b531a3c4f60,0x00005885c546c30a,0x000ddc1d5df2fdc4}, {0x00026f4df2971b1a,0x000bb67cb15104fb,0x0000000000000001,0x0000000000000000}}, {{0x000f74646d17eec9,0x000e3de3bee8f39f,0x000560fc63e96143,0x000d7aab2e0395d9}, {0x0003f099cc808fd9,0x000e3c3dca422f15,0x0002c61efabb0d74,0x0008d736943aed2c}, {0x000d74e4178f87c1,0x0003d1b76afadf96,0x0000000000000000,0x0000000000000000}}}, {{{0x0009583eea912fe1,0x0006a5587f3b9010,0x0002a020829ea8e9,0x000b82ec346b73a8}, {0x0001f44eda406972,0x00067b4504fbb553,0x000e7a6189bcd268,0x00039bdb40c39e05}, {0x0005c436a03e5e06,0x0007019eedb498d3,0x0000000000000000,0x0000000000000000}}, {{0x000662e3f77764f2,0x000cda79a7c8507e,0x00040c75e0594299,0x000bed938a93a1fb}, {0x000829d1bab3f2df,0x000df99ce48d52d8,0x00032fb8c4092f5f,0x000036b5fa768aef}, {0x000201a9ee7997be,0x000ca0344038e8d5,0x0000000000000000,0x0000000000000000}}}, {{{0x0004ae17c6c4ef83,0x000409ab5b4b2b20,0x000c4c863d0780e0,0x0003a003f73d00d9}, {0x000f7d17b97edd24,0x000335ec2eca6e6e,0x0007def3f246d97d,0x000f0e2518ced6c0}, {0x000f728fdb8b0595,0x0006dcc1ccb10bfd,0x0000000000000001,0x0000000000000000}}, {{0x0009f012dd02f504,0x0009d50a767d8e86,0x0001bbb0510be6fa,0x000cdab7deeebbfe}, {0x000f08332cdf98f4,0x000468782175d651,0x000610add0fc83f5,0x0004965277afa428}, {0x000ff5c3438635dc,0x0001fc0961df5b9d,0x0000000000000001,0x0000000000000000}}}, {{{0x00069bd3ef1fabd9,0x00064fe7b00b747c,0x000195c6097cd6a8,0x000470709e13f896}, {0x0002cf79709fe958,0x000b72450de744f3,0x000df3f80fb1524e,0x000527ea0bf24b8d}, {0x0001b2774e7c3f06,0x00031ad38e7aad24,0x0000000000000001,0x0000000000000000}}, {{0x000b784c1f4489c7,0x000f2a889f589505,0x000a5a3175ee6df1,0x00047a68c157fe56}, {0x000497f7b784bd67,0x0005ed8ff0792025,0x0001528aca7e0427,0x000d473d7c41594f}, {0x000cb017e35b5669,0x000f1ce78bb2a52b,0x0000000000000000,0x0000000000000000}}}, {{{0x000290556eb6cb2d,0x0005feea12a072e4,0x000d082bac976238,0x0007c4331be16424}, {0x00021f06c7a59869,0x000de72b68a812dd,0x000652502f900697,0x000d9acaec02a2e5}, {0x0009120c4a89c7ef,0x000a1bdf713a324f,0x0000000000000001,0x0000000000000000}}, {{0x00067220e1027a34,0x000cabc964145333,0x00029a9fac99b048,0x0001c2850e9e757a}, {0x00057de9cc170cb2,0x000d017c03bef969,0x0008cbf0f3534a37,0x00085a627fd6a9c1}, {0x000c29da8ed78ac5,0x000ae4ef092acab9,0x0000000000000001,0x0000000000000000}}} }, {/* digit=57 [{1,2,3,..,}]*([2^228]*G) */ {{{0x00060edf11bb374f,0x00007883a0baf3f0,0x000eb8cb2a326de7,0x00095554f5a8d631}, {0x000236ba14fb5cfa,0x00053769e29d950c,0x00043eac3b6e6d4c,0x000400e396b6857d}, {0x000b3b40a28cc2c6,0x000f0142ca52de79,0x0000000000000000,0x0000000000000000}}, {{0x000536d43744d95a,0x00080dbb696fec4e,0x00086879c7360fe9,0x0006d4736a564e15}, {0x0001262e7ce9d679,0x0004cced89ee75c8,0x0005fe2dd4f732cd,0x00004a4d97d2a3a7}, {0x000e046cc62def6c,0x000c590bfe781afc,0x0000000000000001,0x0000000000000000}}}, {{{0x0001e39da3d53729,0x000c68258dcf68b5,0x000b1289a021c50c,0x00028ef654112229}, {0x000f4c73b83c7489,0x000a0ebdbdf0df33,0x00033245f1663936,0x0006bdfac3bf0988}, {0x0001bcc9c21bceec,0x000bcb64a15de987,0x0000000000000001,0x0000000000000000}}, {{0x000fb2f27cba002c,0x0002f0ce8d66f97e,0x000c4f49e106a48e,0x000720d60d05177f}, {0x0001b9e35427304e,0x00008c355b746f84,0x00061577b7b7cd5e,0x0008586eb9a88122}, {0x00003b21c38ce383,0x000aec02872c5a8c,0x0000000000000000,0x0000000000000000}}}, {{{0x0003ee736c032ac5,0x000efdfdb4c3d4de,0x0006ff01d94dbf41,0x000a0bb5ee1889b9}, {0x0009e7a8dc456a87,0x000c2bb8ca379bb9,0x0000100b2eae0668,0x000d2063b0184325}, {0x0006daafabf5c71a,0x000da2051e835c68,0x0000000000000001,0x0000000000000000}}, {{0x000eaacab83acf78,0x000761a09a5ec30c,0x000838055c361c20,0x0002e34e4fa05860}, {0x0001b9a7a3c102c4,0x000f91746c97086b,0x000c731ba10529e6,0x000e8a7f6450292d}, {0x00076f3144af4061,0x00077cacdce041a7,0x0000000000000001,0x0000000000000000}}}, {{{0x0004b67237f032bd,0x0003fda08c68528a,0x000c719571479a5b,0x00011c75d8054fed}, {0x000bf503c35807c6,0x00037b9ea9e88e5d,0x000c9422b4c4521b,0x0002950eb17e75f1}, {0x0008eca427950847,0x000c0f845c91f923,0x0000000000000001,0x0000000000000000}}, {{0x000c1e80ea8c1010,0x0002e1978ae396a0,0x0002c0d00f914b24,0x0004e43fb47bf7bf}, {0x00034b416e50ae94,0x0007c8d114906c36,0x0000ad0347f03a3e,0x0006a6eba25165b0}, {0x00021e9dc53a14e2,0x00076911eb83f4f5,0x0000000000000000,0x0000000000000000}}}, {{{0x000bb95adc5ef776,0x0008da0ab8c5f233,0x000a4ab915fb3034,0x000423a63a5dffb8}, {0x00063715aa2304a4,0x000018304840df01,0x00037b80028296bc,0x000854f7402fb23a}, {0x0006ebdeaf3e5fac,0x00005463cd3d8406,0x0000000000000000,0x0000000000000000}}, {{0x000c9468fa481453,0x0003a0abd61a0348,0x00047c025f468b21,0x00090d7078cd984d}, {0x0005284e72a10788,0x000156fa2b542f64,0x0003b3c956017512,0x000991f2c57b982f}, {0x000989b3c05c1c45,0x0001ce6eb96dccdb,0x0000000000000001,0x0000000000000000}}}, {{{0x000c0c76c91a3d86,0x00001a3cab8eb5fd,0x000752ec9cff796c,0x0003f81d37bdda1a}, {0x000e12c746df5d95,0x00027c38d512fd50,0x0004e23ce093d983,0x0004adeb3545f200}, {0x0008acce0db1764a,0x0004097d3ea0eee0,0x0000000000000000,0x0000000000000000}}, {{0x00057c8acd0df62f,0x000a235a3f7e354d,0x00043547a0eeee98,0x000831405ee1adbc}, {0x0006a916c043f6f0,0x000e4844ab1da766,0x0000728cc7b74a71,0x0007192544b4fdc6}, {0x0009d41decd4aad8,0x000497605d2bc303,0x0000000000000000,0x0000000000000000}}}, {{{0x000c16253894ed63,0x00072cd0f6a2350d,0x000412983f7baee8,0x00009f78d054975c}, {0x000d7bad42e9614f,0x0005f2ac60d67eaa,0x000622d671f099d8,0x00021f07bed1e830}, {0x00081424aeea7845,0x000f7592014c5f2e,0x0000000000000001,0x0000000000000000}}, {{0x000619d3fbb4d7a6,0x000a9269d1beee9e,0x0002e4ef27debfd4,0x00069156fc40ac5c}, {0x000b31c86af27730,0x000f4aa3fc30b8ff,0x000bfd86f500b895,0x000c9dccb88b68a2}, {0x0003b7832b9f66f8,0x000853497ba1895e,0x0000000000000000,0x0000000000000000}}}, {{{0x0000b0ab29d3bde4,0x0009c71ea0d8e5cf,0x0004b6204df30d49,0x000d3f548f748b9e}, {0x0006eba95c754c4d,0x0007ad6cc9c44387,0x0009e2d08e10896d,0x000ea9428b4a544e}, {0x000fe71891a2d3e1,0x0006b905c7660eb6,0x0000000000000000,0x0000000000000000}}, {{0x00066e6414125179,0x000e2877106f8fb3,0x0002d9d82f542b36,0x000b4eca63743c2e}, {0x000cfc887146aaf2,0x000ed669e0b28d08,0x000c885c73913714,0x000914ee1f56da28}, {0x000d4479d84424da,0x00015e3364622742,0x0000000000000000,0x0000000000000000}}} }, {/* digit=58 [{1,2,3,..,}]*([2^232]*G) */ {{{0x000bd25b5edea690,0x000347c3abc5bd1f,0x00078a11d29a3138,0x000c6d62f2283223}, {0x0007b4af4ece3ada,0x0001c75e4372b0dc,0x0009560a7308e28f,0x000d0ea7127d9913}, {0x0000172da9cb3c31,0x000c36c69386a7ee,0x0000000000000000,0x0000000000000000}}, {{0x0003be2a2cae0b56,0x0000778293313929,0x00041cdee07af8d3,0x0000895f4118b415}, {0x000b9b3a9502ad6d,0x00004e1d44242767,0x0001a843924f3834,0x000a3c5c40dce7a9}, {0x000443e9e0f30db5,0x000c5338df60b62d,0x0000000000000000,0x0000000000000000}}}, {{{0x000d88264070b39a,0x00060f5a265bdb95,0x000717063ef771ed,0x0004ca000dd813de}, {0x0005a4d348196d97,0x000def16129d2691,0x000bcbbfcdfb3523,0x00057290d6981eca}, {0x0000c5d2444e08c7,0x00091c65a063c65c,0x0000000000000000,0x0000000000000000}}, {{0x0001941d0c9b7cd3,0x000cc0a5845e0e75,0x000c51c09cc90c04,0x000ce8aff11f3a2b}, {0x000303944ca09536,0x0005cb9d10d614a2,0x00062674cf73a00e,0x000639b5262911f3}, {0x000379f49e681d43,0x000ea07634bb0927,0x0000000000000000,0x0000000000000000}}}, {{{0x000aea3b47740815,0x000ede22e76e20e2,0x0007e03afde6eca1,0x000f70d608d1c44e}, {0x0000b88d585444ed,0x00074d298cd8ec39,0x0001146c4c3f6754,0x00073274110e9ce2}, {0x0009cf1f4b12ae7e,0x0004fa67e9f4b4ce,0x0000000000000000,0x0000000000000000}}, {{0x0002ef9318bf7948,0x0004cb3efdaff610,0x00059bd31047a8b9,0x000fad7c4b8b1235}, {0x000a02488482725a,0x0003b462badd939d,0x0009f8945cb99ab4,0x000c0f6b65c66a4b}, {0x000e97dd0bddb4b1,0x0009d75a1f797639,0x0000000000000001,0x0000000000000000}}}, {{{0x0000ec0aca9d0f94,0x0002fb13ee984570,0x000e5ad047be55b4,0x00073a0845bc6993}, {0x000ffee41f2aee8f,0x0003c832041ac680,0x000bb4a740b12fcd,0x000521ebc1645e36}, {0x000dfcc7735a45c9,0x0008ef92b0fbdab8,0x0000000000000000,0x0000000000000000}}, {{0x000805ed4e45e0eb,0x000584829d754db5,0x00036cc488a6c810,0x00060f1ec9632468}, {0x000c0f2ebc30d39f,0x000e960758390502,0x000f4626d1feec9d,0x0004f944bca363ad}, {0x000375dbfdeea282,0x00050ba887d0959c,0x0000000000000000,0x0000000000000000}}}, {{{0x000857ce82a61386,0x000fab480b18fa40,0x000223002b9297b0,0x000f9b41f698e6a5}, {0x0005eb688e33b253,0x000cc09f30bec2ad,0x000eeb6333a5ffe4,0x000bc81e94524303}, {0x000091b660b277fb,0x0008fd03ed404dad,0x0000000000000001,0x0000000000000000}}, {{0x0005dd59faaf5be9,0x000abe017edd5410,0x000aaa4856720e0a,0x000d987f4b1178d8}, {0x000fe5e556ef405d,0x00081f659d8f4002,0x000f7836cb450ed9,0x000350d35c2f69df}, {0x00095c15741d4705,0x0004c982d30172da,0x0000000000000001,0x0000000000000000}}}, {{{0x000f854cfa0f1b9c,0x00036c27f5709e7d,0x0002fcca4c8efcec,0x000a965fa53691ad}, {0x000f70705ad9f4c9,0x0006ca89080d5043,0x0005cff60c807ea8,0x000ff2e47ec8fa95}, {0x000846288bda4094,0x00003dd7b4f68fa6,0x0000000000000000,0x0000000000000000}}, {{0x000c953f0c60b7aa,0x000060469787d616,0x0009579f0ed52085,0x000faf3c529ad3be}, {0x0006f18223d47482,0x000c07ac1ad869d6,0x000437b5cb0dcd56,0x0004dc765feb592a}, {0x00004a294944df05,0x000184cb4ad2de82,0x0000000000000000,0x0000000000000000}}}, {{{0x00003d153000960d,0x0008f85dc5ffb696,0x00009b3d9302c4f3,0x000fd9668bf9ae36}, {0x000a25bdc3c8ecf4,0x0005c1a7bbfdb2a9,0x000393a4a4463083,0x000a4d41df85c97b}, {0x000d92cc6610ea8e,0x000bee7a14446540,0x0000000000000001,0x0000000000000000}}, {{0x000fe7092ab307cd,0x00055b75f48236e0,0x0009f206af987311,0x000191b95f1aca72}, {0x000b01a57a7e9b13,0x000784300caa5513,0x0001b4e8ad08534f,0x000e7a92df980dd1}, {0x000edd78871ce4ff,0x000f2fbe3e6a8b6a,0x0000000000000000,0x0000000000000000}}}, {{{0x000cf8b0ae3366de,0x000c06074154422f,0x00007a17d21e5dad,0x00001e78c237ee85}, {0x000d108f5fd2183c,0x00098eec2dada49a,0x0001c303e35f7659,0x00091f2075445a12}, {0x0007426d8f5fdddb,0x0006af1dd7a92c53,0x0000000000000001,0x0000000000000000}}, {{0x000c31da2f658936,0x000e72228504949a,0x0007646877ed3189,0x000cbac9e04fe426}, {0x00093f8802494ee0,0x000975ea85d9fdf7,0x00038fb0c9c6045a,0x000802b88cb118cf}, {0x00057e39ea12c877,0x0002548e571e0697,0x0000000000000001,0x0000000000000000}}} }, {/* digit=59 [{1,2,3,..,}]*([2^236]*G) */ {{{0x0001f89eed993384,0x000860d77e7f7ed9,0x000e9a249862cf0f,0x00026963705ade19}, {0x0005d0f929eafa4b,0x000a12f7eef6f18b,0x0009d590ff1861d1,0x000d6b67d2954ef5}, {0x000540dd418bcbd0,0x00096e83b51e5170,0x0000000000000000,0x0000000000000000}}, {{0x0000a67de6f33ef5,0x000d0f090cb0d50b,0x000b8b3eeba89c8f,0x00026dc5289c0d96}, {0x000e0e6dd7431a8a,0x0000a660c8afde18,0x000cfa02cc76374f,0x000b7654494d397b}, {0x000476b8fd958a15,0x00097d53a314e324,0x0000000000000000,0x0000000000000000}}}, {{{0x0005d2d913938d7d,0x0006d9d471ad5a92,0x00018a88bdce6ad3,0x000b90be599734aa}, {0x00099aa6c0fb7b20,0x000eda14b233c887,0x00024ee7dad41f1c,0x000cb7c643d13bb9}, {0x000e7d84ea63db6f,0x0003a846de4666cf,0x0000000000000001,0x0000000000000000}}, {{0x000e6128e81e8c45,0x0001464a9235f4eb,0x0002db34ea2780d1,0x000ad3e8b3ecdbc0}, {0x000f8cdbe120731f,0x000f4318097ab5eb,0x00079ebbf1d4990d,0x0007e93c15830f8e}, {0x000c40a1cfba03ee,0x00068df76de664ef,0x0000000000000001,0x0000000000000000}}}, {{{0x000267eeb458a4eb,0x000e492a1279f17f,0x000c76f729af11c0,0x0007339e92b8f2a3}, {0x00014e00c8ca3543,0x000dbcc01641f96b,0x000755e449dde571,0x000a0a0df11e5fa3}, {0x00031770742dc646,0x0006f53610d1c65d,0x0000000000000001,0x0000000000000000}}, {{0x000e5b808553c438,0x000499c99fe83176,0x00019eef1a061f75,0x0007deb8d4c21a60}, {0x00033192fdd7ecc6,0x0003250ef2ec37ce,0x000aff8f6ed93441,0x00058d1e9777ac4b}, {0x00083407f0d67d5c,0x00079fd1b5287171,0x0000000000000000,0x0000000000000000}}}, {{{0x0009d6152b9c90b3,0x000aff28f438100d,0x0000a2146e64ecd5,0x0009ad5b7e0c0df1}, {0x0003f6775181b0d1,0x0003c7a1b8151d7c,0x00035c338a3ef9f4,0x000e1fdd81712dd2}, {0x00034726a1f2597e,0x000cb3083971de47,0x0000000000000001,0x0000000000000000}}, {{0x000c041200d9bef5,0x00067c85ff590dfa,0x0008b72aaea952b7,0x000265e7843ae9c1}, {0x00032307d7542004,0x0002dea503395a89,0x000e1eec7f73a8fc,0x0004b86c7eb53399}, {0x00021cf862926b2c,0x00019347a4f0820d,0x0000000000000001,0x0000000000000000}}}, {{{0x0004f7b384cd7297,0x000acc1a4787e2cb,0x000a5590739ea069,0x000be73fa99d3f7a}, {0x000e7cf6cca23601,0x000960cc53aa83e6,0x000b86b5920b1173,0x000fa7ac9dbe20e0}, {0x00068bb6f6b3ef99,0x00064060ac6c56f4,0x0000000000000001,0x0000000000000000}}, {{0x000626c189f97eeb,0x00092eb7dd82a1dc,0x000142f8425008f8,0x0004b241705cbf37}, {0x000c04c8483d101a,0x0002075cfd275951,0x000f282a7dae45a8,0x000263c98e81a9d9}, {0x000c331b130bf290,0x000c95c5f55addef,0x0000000000000000,0x0000000000000000}}}, {{{0x000ac9a1c36e3c24,0x0008e09fb461cd04,0x0007bca251b2abd0,0x00098ad8fa6e8384}, {0x000087e953f04f5d,0x000d9f6c57ca3dcc,0x000f179679c5992f,0x000cc9cf93cdfac8}, {0x0000d1a320e29622,0x000580703c650a05,0x0000000000000000,0x0000000000000000}}, {{0x000188e58d397fdc,0x00021860a160b5c1,0x000be9a3f426d729,0x000f8747311911d3}, {0x000b78a79eb1a864,0x0006b881dee2ff5e,0x000fc87ef83107b6,0x000ed139997a8784}, {0x00080e84fd894e5e,0x0003aa1a2f41979a,0x0000000000000000,0x0000000000000000}}}, {{{0x00031707560bd53c,0x000c9501712fc58e,0x00010e30ced00607,0x000465e677b023a2}, {0x00067620a31c653b,0x0008ea62e5b10af4,0x000d99048d08ca5a,0x000d65af877831dd}, {0x00029f5ab5be8899,0x00028321d38a082b,0x0000000000000001,0x0000000000000000}}, {{0x0006bb42378c6e38,0x000fb8ba4bc4d5d5,0x000a4ef2e4b28b7a,0x000b41f7c314822c}, {0x000a2882d9a51ae9,0x000e6c2280f2b327,0x00019697ce965ab1,0x00075708dae4a49d}, {0x000f1175eea346d9,0x0000e9572d2fbccf,0x0000000000000000,0x0000000000000000}}}, {{{0x0007d4bad9839247,0x0002744af0bab5bd,0x000cd1e04b0ade61,0x00080a7fe21c3a53}, {0x000864b9871244ec,0x0003f6fd1428f483,0x000889d63b180bf2,0x0006acf748b0e2b4}, {0x000a061072996dea,0x0006607cdec9d5f3,0x0000000000000000,0x0000000000000000}}, {{0x000a9858e242fc0a,0x0001fa2d38ce4fc2,0x00087521e69c709b,0x0005bae8f5996fd9}, {0x0005e131ac99f4d0,0x0002578fe3c3bad7,0x0002279c9d139206,0x0004b6fbac903ada}, {0x000292885696da36,0x000ddbd02ce1356c,0x0000000000000000,0x0000000000000000}}} }, {/* digit=60 [{1,2,3,..,}]*([2^240]*G) */ {{{0x0001074e0ee1b4c2,0x0001a0ff10eeb73d,0x000c77549f2e087c,0x0006808a5e2e0837}, {0x000e948c7156c74d,0x000c13bf7c11f82c,0x000a51472ee287eb,0x000b28c4e6f906f6}, {0x0000fef0b165038c,0x0002d8b6f1c9d932,0x0000000000000001,0x0000000000000000}}, {{0x000d310ce2cf5a19,0x000c08add6b6df57,0x000dcd4cb28cd825,0x000e1cbe48bebf85}, {0x00051f1d5aa6a644,0x00008ba85cbebbd3,0x0001bc84d8a2aa19,0x000d343d2d77518b}, {0x000a9098229b988e,0x000a9f940fc8d07e,0x0000000000000001,0x0000000000000000}}}, {{{0x00096ebc173a5d8b,0x0000ed54a67c958f,0x000ef67809a984cd,0x000abb728dd8453d}, {0x0009f4fe5f363de0,0x000e4fc4614b7360,0x000fee4aab1b83c8,0x000606d2158cb989}, {0x000096597fe56f7d,0x00057270734a0c52,0x0000000000000001,0x0000000000000000}}, {{0x0004ef503a18dccd,0x0009b732b2f44d09,0x0002c29898debd6d,0x0005ffd4e0ef3ff7}, {0x0003830b99ae2e5d,0x000dd5fca5e1c94a,0x000e97015b084de2,0x0000e94504be6d08}, {0x00079eaed90fe0fe,0x00051eafa2897ddb,0x0000000000000001,0x0000000000000000}}}, {{{0x000dd470cee4255c,0x0008ea907208e445,0x0001157ba3e551b3,0x000f94c51b72b693}, {0x000b183c616c9cf9,0x000fe84fcaaf1c59,0x00077c97ed67f1d2,0x000a1d1e1a09f1bd}, {0x000c2f47751550da,0x00038d58d345e7ba,0x0000000000000001,0x0000000000000000}}, {{0x000d95b5f854d3f8,0x0004daa404c99ba5,0x0005a1bac7d29f41,0x000da46981c9d673}, {0x000652c1bc49956f,0x000e505f2a66bdcd,0x00081069783eab5f,0x00036f9996ab9237}, {0x000238170a7330e6,0x000670fa70e33da6,0x0000000000000000,0x0000000000000000}}}, {{{0x000e86a58386cf1e,0x000572f15be04bfe,0x000e35f663e32b87,0x000f5c5294b48632}, {0x0001362fb4267165,0x00007dadeb7d3b94,0x000012e189d86c34,0x000d63e5f7805689}, {0x000b7e33561c7907,0x0003c0c0dc085fa2,0x0000000000000000,0x0000000000000000}}, {{0x000cbe4f2b4f6916,0x0002f30cfb081da9,0x00011fe0a525ac2d,0x000bbd4632662679}, {0x000223e344c2d8fc,0x0000a08757b1ff41,0x00001c0a48229e9a,0x000456b8c92c6f71}, {0x0009a086c4af0e80,0x000d74c21360d8bb,0x0000000000000001,0x0000000000000000}}}, {{{0x00000ce7164d30ca,0x000fedb34ef3a45a,0x000800620f8ac5c1,0x000c7c79ba6237c0}, {0x00088ff56f44997d,0x0008ab94745563d5,0x000df21b2b00a9ae,0x00086a286295b8d1}, {0x000426dbb4cf9b37,0x000ec830b7004300,0x0000000000000001,0x0000000000000000}}, {{0x000a97f98f792db1,0x000f9d5a4e4b251f,0x00061b4d385d3a62,0x000b4cdaad987701}, {0x0002341727a73b90,0x000c4abf7e84f908,0x000f0ded814c4a3e,0x0002c453671bed3d}, {0x000a888690c8945f,0x00019a94087855dd,0x0000000000000000,0x0000000000000000}}}, {{{0x000e5f28e7fb0752,0x0005ca705e5e780c,0x00093ca952d3af74,0x000eccdc7351cb28}, {0x000bfc12e9837fed,0x00014b93567e7bfb,0x000546247999f34d,0x000a3f729887c629}, {0x0006edd285692b0d,0x000fc9812e383cc9,0x0000000000000000,0x0000000000000000}}, {{0x0001bc941d72f110,0x0009ba70199860ef,0x0002d090c33493b9,0x000503ff279e0c37}, {0x0005c3fbe286bbe1,0x0006d81c3e80f646,0x0008d3a0a9257bf0,0x000e402ee72a2a44}, {0x00092b91c6a5669f,0x000ad95315497ce5,0x0000000000000000,0x0000000000000000}}}, {{{0x000b397c9c0b3f5e,0x0008573318572b93,0x0000e667f17a3327,0x0000b9137af5bff7}, {0x00017fb65a96b2e6,0x000188dfee9e25ef,0x0002c9edd117ab29,0x00015472d03d830a}, {0x000512ca1063aa4e,0x000adf9593f42bd8,0x0000000000000000,0x0000000000000000}}, {{0x00043be475ba796e,0x00023dbbccf7b7a1,0x00080d4a4b140a81,0x000247748562ea6a}, {0x0002f53e144c7e84,0x0009ac8b6fa39d88,0x000b1eab451fe154,0x000ec4538f34ffe4}, {0x00076cc290527aed,0x000d83bcd8efdc10,0x0000000000000001,0x0000000000000000}}}, {{{0x0000c5c5bcdaef57,0x000720046d980167,0x0000601ff33f7b5e,0x000e6b0aa07084cc}, {0x00007791af83b900,0x000dd856fdd2391e,0x0008d880430654d2,0x000f826068896340}, {0x000a4b443c176e8b,0x000c4e18c663e62f,0x0000000000000001,0x0000000000000000}}, {{0x000d8ae0441a598d,0x00065c950e8cec48,0x0001316d53d11b80,0x000cd6863a5ccc8c}, {0x0008ced41a668fee,0x00076ba771bb4164,0x000b49a9a4bb4b6f,0x000e370974d5a9b2}, {0x0000485def9f130a,0x0001b84c25f49d20,0x0000000000000000,0x0000000000000000}}} }, {/* digit=61 [{1,2,3,..,}]*([2^244]*G) */ {{{0x000f43bc2dfb404c,0x0008b314169ebb20,0x0004d9ce016776ec,0x000b6f3c40cc814f}, {0x00075de6701fd64d,0x000be16687bc27b3,0x000c8ca41b2641f1,0x000e5c7ebdd8aaf1}, {0x00021918a667e429,0x000d9384d2d4cd92,0x0000000000000001,0x0000000000000000}}, {{0x0009667398bc8b35,0x00026c502a6f1f65,0x000612fc65ae7726,0x00047588d1717c45}, {0x000b0cd0bd27306b,0x0007b68702fd9dbc,0x000a43a5beaed3af,0x0008d9e3bfb560d2}, {0x000c14b9b618c615,0x0002421dad1537ee,0x0000000000000000,0x0000000000000000}}}, {{{0x0009e7889bf8b6ea,0x000292e957ebe27b,0x0002bd715ca3ae1f,0x000ea4756ae08fea}, {0x000f5cab67aaf3b2,0x00047caa37f247c9,0x0001b8953af0925d,0x000557e7bd1f409f}, {0x000979eb14ee5b8e,0x0008bb0e2890300b,0x0000000000000001,0x0000000000000000}}, {{0x00078d6b71ea9467,0x0000c63dfcb1d01d,0x0008e6aaf05595db,0x00006ff49217ec90}, {0x000b8ab12df36451,0x0004207aff8489ad,0x000b85d257b835bc,0x0003706e08a1abbb}, {0x0002a5b7d71ad10a,0x00056ae224792f6d,0x0000000000000001,0x0000000000000000}}}, {{{0x00028daca765356a,0x0000ee74680323bf,0x00005f51f95b6f29,0x000c6656c3eab37e}, {0x00038ce239752348,0x000cf8aff4ec8ff2,0x0003adc6745b80af,0x000e56c344a76be9}, {0x0006011d48a9f827,0x000ed4a3e016c1c3,0x0000000000000001,0x0000000000000000}}, {{0x00096e22c7a80fb0,0x000891624b09ab2c,0x00049f6d4616a383,0x000b275d1cd7006e}, {0x000adb9075332618,0x000586e58c4079b5,0x000645e2b19bf36f,0x000f76906dc5820f}, {0x000f6bdd7a51a11b,0x000b67dd8137d034,0x0000000000000000,0x0000000000000000}}}, {{{0x00095b8b650fd71f,0x00014965b39aaa82,0x0001270c9510690f,0x000b3a9f763e6fce}, {0x000be3f839143baf,0x000866c1890dc990,0x00074c8a0d6a0e73,0x0004b520d476087b}, {0x00081006ed8910a1,0x00052b16e6fb91bd,0x0000000000000000,0x0000000000000000}}, {{0x00057756a63f7354,0x000a1ebe4b13d097,0x0003f1884cec54fb,0x000503924519ff97}, {0x00059fb9e4f42689,0x0002ce5e202d309b,0x00098e0004b85f0f,0x000b05c20b1735d8}, {0x000add1fbd4f54e0,0x000dcb178e2a7f34,0x0000000000000000,0x0000000000000000}}}, {{{0x000b4ec871f1c2e0,0x0003b5de22756058,0x0000837f536100e3,0x0000c16f1ccaf424}, {0x00056dcf857da01f,0x00038c07ebb5fb6d,0x00096a096d6242a9,0x0003055c2b2c30cf}, {0x000a782e55f66ac8,0x0004f012cc9c2c3a,0x0000000000000001,0x0000000000000000}}, {{0x000506352d9bc635,0x000b06aeaaa56b9a,0x000095186c35174d,0x0002167f537385d7}, {0x000cf421a089f0ea,0x00022c37dc99678c,0x000356bf33a69466,0x0003e97eafc66d63}, {0x000e3c0197b16669,0x000d912a0fa3fee5,0x0000000000000000,0x0000000000000000}}}, {{{0x000a52c892d50f2a,0x000dfd8fc48ea89f,0x0004b09bae86a680,0x000a1e1278d67917}, {0x000370f37ae3b7ce,0x000f51107a8383d3,0x0005c8e157913dc9,0x0004c347e479bbd0}, {0x0007dfb63e7f7f02,0x000ac4a32c2410c2,0x0000000000000001,0x0000000000000000}}, {{0x000c5983d275b47a,0x000f3ebc8a42a9a0,0x000db0533ac31f03,0x000cb9b707b4440f}, {0x00064522041e91b5,0x000076367218816d,0x00023be78c44489a,0x00060289668fa7d8}, {0x000b7bda9a033e06,0x000c041bf9880e14,0x0000000000000000,0x0000000000000000}}}, {{{0x000df487e3ac46f1,0x00026f6aeda132f0,0x000f9138020c745f,0x000a8841334fb2d5}, {0x000c66722bd6a712,0x0005a1ea4533d309,0x000636323c57e66d,0x00008eb26f26bbe3}, {0x000fa479b5dc3fac,0x0008f02e50177e02,0x0000000000000000,0x0000000000000000}}, {{0x000c92b56635aa25,0x0007f4d610ada23b,0x00010104e5566f0f,0x0004f4b30ea26b57}, {0x0004efd9675fd322,0x0001af8f50ca2f0b,0x000382d177aefb1d,0x000538151171ef73}, {0x0003347891a319cf,0x000711dcdab779a2,0x0000000000000001,0x0000000000000000}}}, {{{0x0002b024db8d3d78,0x000aa5cc47fd4499,0x0004ca3c2ae301e6,0x000f6635a239d460}, {0x0001e72a93968b59,0x000f3e7cb493da74,0x00057a0e451c8476,0x00090539a4ae9584}, {0x000df123a0ccc6f4,0x000f3e4b36ee4a70,0x0000000000000001,0x0000000000000000}}, {{0x000bf5964aec0226,0x0008d0d54e934ea5,0x000838881f3a4f9d,0x0001904c5759057f}, {0x00054f74d21e3d23,0x0009110e0965fa28,0x00025473e3fbb9d0,0x00066659568773f8}, {0x000e05953c3213d4,0x000de0c6c9fbf74e,0x0000000000000001,0x0000000000000000}}} }, {/* digit=62 [{1,2,3,..,}]*([2^248]*G) */ {{{0x00023dd4a823eac8,0x000e2984db5faf62,0x000d39d495d0b0f5,0x000841ce0a14e52d}, {0x000cb365ed8de723,0x000bcb1fe9b4ef0f,0x00047ee3aa7d5d2d,0x00032d33c7e0b190}, {0x000d3b9dde2978f5,0x0005329dbc97d12a,0x0000000000000001,0x0000000000000000}}, {{0x000d165556c00ac2,0x00057fb3172c7a02,0x000beeb32c48804b,0x00099dadad774958}, {0x0007934b2bc9659e,0x0003fd281f90ab3c,0x00013abe477effe3,0x000378b329a3faa7}, {0x00036cbb9f3df235,0x00014562e824d0ac,0x0000000000000001,0x0000000000000000}}}, {{{0x00078de5aeb19662,0x000d1f458b071bd2,0x0000313ed9b5b584,0x000ce5fe5f476cd6}, {0x00077007678c1c54,0x000258964a6d145a,0x000420c0c62f8fee,0x0008595f7056fa68}, {0x00089119263621f2,0x00019c5d8cf9f82d,0x0000000000000000,0x0000000000000000}}, {{0x0000243d2e6cb7a7,0x0008d78d5a87bb13,0x000c4e517b3bcf90,0x0000f65dd0ef67bc}, {0x000d930e5dd35ba7,0x000eb9fb0741af2f,0x00075eb448314eea,0x00003702fdd3f71f}, {0x0002c0a91bac4835,0x0008e91ebd11ec1d,0x0000000000000001,0x0000000000000000}}}, {{{0x000160f761d5cda1,0x000d737ebbdcd5d3,0x000d7809f98ac1a9,0x000dcdbd555d558c}, {0x000fa398a682b263,0x0004f2c8dcb516cf,0x0003f1fdc39fa308,0x000c8f35f0892119}, {0x000b1a2e7b6b0e00,0x00060305cb4b78de,0x0000000000000000,0x0000000000000000}}, {{0x0005dc3804225ef5,0x000a4dd0142d36ef,0x0006183af50e0ed5,0x0006c670fcbeb371}, {0x0008629b90cb9a81,0x0002af3261b35739,0x0008aa6b6e9823af,0x000fbd19a0ec458b}, {0x000311a98270a0a9,0x000299fe388efd5b,0x0000000000000000,0x0000000000000000}}}, {{{0x000bf04df8057734,0x000b1031cb2cfcf4,0x00013e25b6e0c3ad,0x000fa4cf3dd2ab40}, {0x00007758e2edfff8,0x00031ad907feffd3,0x000b4564baf111bf,0x00073c4f6a12eba1}, {0x000fad75513a8160,0x00074de7fc43bd94,0x0000000000000001,0x0000000000000000}}, {{0x000d44eee593810b,0x000f1e369ffff5b8,0x00064f19da65334d,0x00021d0f5c2b9ceb}, {0x00091c5ca3390013,0x0005689acf02b87e,0x000bf7c3a49c8b54,0x000093f7ed7c049d}, {0x000a0a1d58d27784,0x0003d7726f20ba73,0x0000000000000001,0x0000000000000000}}}, {{{0x000ec366cfe8b8dc,0x0005109510bbe0e0,0x000aea6451541d52,0x0007f0a613f8478f}, {0x0000f85f758544a0,0x000f2b250e479f86,0x000b98246494bdaa,0x000483bd40872db5}, {0x0001ef43cbf9eee7,0x000bc8abec7ccf7e,0x0000000000000001,0x0000000000000000}}, {{0x0005c21b7bfcf30c,0x0003ee117f493af1,0x000fdb4b0534832d,0x0001fa1bf55f45c9}, {0x00078f7e3c1efc43,0x0008a7de78a32d11,0x000dc3559e7ee791,0x0004e7a865c863d0}, {0x0007e1e671e05898,0x0005634bd3bf85ef,0x0000000000000000,0x0000000000000000}}}, {{{0x000d81691c2ab48f,0x0002541bcc0607cd,0x000da791a7f87cac,0x0008347771261610}, {0x0008e3bac250c120,0x000659e04001e2db,0x00052cf1b9282899,0x0009b392289990cc}, {0x000164d7d417f75a,0x000945df41fb11a9,0x0000000000000000,0x0000000000000000}}, {{0x0009c07103c6ae84,0x000480fee72710d4,0x000b8360a2b9d155,0x0000e0d3d7e07da2}, {0x000d149f0388daf1,0x0002f71dfdfd1523,0x000418130ff86f14,0x0009f7346c3e8b09}, {0x000b2e35c5e699a7,0x00052b1c1fdc6ba3,0x0000000000000001,0x0000000000000000}}}, {{{0x0003345adc3b52d1,0x00068ceb5ac071d1,0x000e11041a7e60d2,0x00074a2a70677323}, {0x00040734a03353e1,0x00041105a4c9d8da,0x00044e1f19873918,0x00091f314a743285}, {0x000322e1b26f9179,0x000d3d1613ed69ba,0x0000000000000001,0x0000000000000000}}, {{0x0004543cf00ed5fb,0x00053fab663cf4cd,0x000be8cc8843f104,0x000f74fe45dc2276}, {0x0004319b78ce0e03,0x000389520a05dc90,0x000cbb592960d2ca,0x00026ed0dfe3e1c7}, {0x0009036fca8841aa,0x000549d9ea193025,0x0000000000000000,0x0000000000000000}}}, {{{0x000d95d4b57fe6e7,0x000237e45eed99e3,0x000ddc0cb978fe19,0x00073f687eb46e14}, {0x0006f57bdaf6e4df,0x00047741a18670ac,0x0004925a46fbe2b8,0x000282f9632d0245}, {0x0002e144fc15a10d,0x000815c55aed10af,0x0000000000000000,0x0000000000000000}}, {{0x0004dce0659c9bac,0x000b25a506cebbc4,0x00048b6559b03aaa,0x0008048a933863a2}, {0x00020d37a9de4c34,0x00020f440226cd5e,0x00074e9ee95db69c,0x00082f425e1eff1c}, {0x00033a6f8d820bb8,0x000ef06f95cad219,0x0000000000000000,0x0000000000000000}}} }, {/* digit=63 [{1,2,3,..,}]*([2^252]*G) */ {{{0x000e4e5c561d5097,0x000b584aedde8b8f,0x000aba27830c0d36,0x000c7d59c0f869dc}, {0x000b714a35cbc32b,0x0004bed4bc22d71a,0x000061f00680d9e0,0x00033bf0836adf25}, {0x0000d7fedb3d768c,0x00095c616b984e3b,0x0000000000000001,0x0000000000000000}}, {{0x0008c5d5c16b3659,0x0009b2bd923c283c,0x000fbaf03219a32e,0x0005bdb0f0d8e95a}, {0x00027d3039b5fed1,0x000c59ce26d89427,0x000676fa1dec9a4c,0x000121992696f0b3}, {0x000260c98b8c7cfb,0x000541c1c9792927,0x0000000000000000,0x0000000000000000}}}, {{{0x0002f821dc52854f,0x00009f01e839c81b,0x000f9520b0acb7e7,0x0005ef6ec4857ab9}, {0x0007209f9eda63a8,0x0006daca6651f475,0x000d6976e7173379,0x000240b37bfaccec}, {0x000b4437229f4ce0,0x0001910fe8a0ffcb,0x0000000000000001,0x0000000000000000}}, {{0x0007819702adce4e,0x000559cf2ed75ea3,0x000524a7d80f948f,0x000a15733e1fceef}, {0x0008e25fd5510058,0x0004c29ed3586531,0x0004e51cb7d9fa11,0x0006f171b487caa6}, {0x0006163b82558054,0x000686de74000000,0x0000000000000001,0x0000000000000000}}}, {{{0x000b150deff72861,0x0006369a87c08222,0x000222ff210ad76f,0x000b4d66f2177234}, {0x0006ffb6d673f874,0x00059b847a7a63aa,0x00088181fb601b85,0x00061d5a56e17f52}, {0x0009cad3b2dceae5,0x000b7064799ea515,0x0000000000000000,0x0000000000000000}}, {{0x00071777678fbf96,0x000ee3fb840953c6,0x0006c82ee1fe6943,0x0000476345986586}, {0x00027b2c01a1da88,0x0001dd9ed1d2e620,0x00093b57ac9ecf98,0x000aea3ed52ca86a}, {0x00083c732ab42d43,0x0005274badd57297,0x0000000000000000,0x0000000000000000}}}, {{{0x000860f86c3463c3,0x000fa451b92975d3,0x000e9c89aced751f,0x00082df00fff3b8f}, {0x0004d44ceed1d22e,0x00022e7d389ef4bd,0x000e91dec43e5b63,0x00003ac6cd725daf}, {0x0003c7139385f22e,0x000deeecc87ca1c2,0x0000000000000000,0x0000000000000000}}, {{0x00051580221e0fc8,0x000941fbf97dbfd6,0x000689ac9e872372,0x000740f84611974e}, {0x00046e04ba0c6ce7,0x000419caa07a8f97,0x000565905b0cdaf7,0x0003cd2570033075}, {0x0003b2c015af7e40,0x0003287d54b47d8e,0x0000000000000000,0x0000000000000000}}}, {{{0x000087653c1971e3,0x00077f0a153e5f28,0x0003ed97c2828991,0x000095935157a12d}, {0x0003722663e4ec8c,0x0008ec4fe824b403,0x000dd44aff641d97,0x0006da087485323c}, {0x00044e2cb2c2b861,0x0006eba170078d74,0x0000000000000001,0x0000000000000000}}, {{0x000b5b83303bc746,0x00013dec62dad85e,0x000eb52890ef39fd,0x0007414a67a192cc}, {0x000ca32294492ed1,0x000e1460a8a16787,0x00024c190537d3f9,0x0004d8dd49fa5c1c}, {0x00025dcc6564966f,0x000872ce77f122af,0x0000000000000001,0x0000000000000000}}}, {{{0x000f907cb543fab3,0x000c69a83a50077e,0x000cb4bde1d63e29,0x000c33fc44a3bb56}, {0x000f82a91020da98,0x00021551aca18ce5,0x0000524e8061c783,0x00030bbde84c8ff8}, {0x00080aaffd7e7a07,0x00025503d2cefb4d,0x0000000000000001,0x0000000000000000}}, {{0x000d489c09cd7406,0x0003bbf72e670d86,0x000584e3d6cd578d,0x000c5357fb7dc505}, {0x00078eb6069dbc02,0x0003d4fa59d19b85,0x0000398d29e9ce8a,0x000efb99649fd29d}, {0x000ce49c616fbd54,0x000860686cd02ccf,0x0000000000000001,0x0000000000000000}}}, {{{0x000b5280bf38c012,0x000b16e5d0e927a5,0x000e0fabbb77cb27,0x0009a5fc1a89a6d3}, {0x000a92cdb34cf1fa,0x000464dc9a9cf793,0x000eb464387be7aa,0x0007fbfde96cd4d4}, {0x000232f3e162772a,0x000656aee57c0a02,0x0000000000000000,0x0000000000000000}}, {{0x000a4f88de057838,0x00017126373b6048,0x000e4a0f6263ace7,0x0001d00ce841a9eb}, {0x0004964f3fadfdda,0x00053a6795df2847,0x0007970db46fe5d6,0x000fc5cc5ee32eac}, {0x000634cedbf5f3ce,0x000fca10e755fd0e,0x0000000000000001,0x0000000000000000}}}, {{{0x000aeb844e0e5a47,0x000278171b725206,0x0003ef95a8f2f67f,0x0001fdfb411d7c3d}, {0x0002cbc9db5d5134,0x0004cd3d499c831f,0x00090a75fa0db406,0x00072c8d72cfb8bb}, {0x00070a986050fdef,0x000f2a584d26e897,0x0000000000000001,0x0000000000000000}}, {{0x000357b6cd8cc5f7,0x0006b375fe114c8a,0x000aa2296d0e1fc2,0x0007cba1e2fe623c}, {0x000b8ca73315ce03,0x0007e86db236843e,0x0005e04b5b70ddfb,0x000420198f9d4b15}, {0x000535cfa0692139,0x0005a2aa06d43751,0x0000000000000000,0x0000000000000000}}} }, {/* digit=64 [{1,2,3,..,}]*([2^256]*G) */ {{{0x000cc45663bc9f5b,0x000b2868f57feb89,0x0004bd3cbd6a2543,0x000a5e560bf63c0e}, {0x0000e648f4a5666d,0x000591427cb7d9cc,0x0005977ab848b1a7,0x000af4656829e85c}, {0x000ae8f7a4025667,0x0003b4ab876527cd,0x0000000000000001,0x0000000000000000}}, {{0x0004ed81840ffbcd,0x000e4830db96c420,0x00026c352dd1b3e5,0x00003369497308c9}, {0x000023370174e547,0x000c6d8497a95345,0x000ecbfae86058c7,0x0008a32e4cdcae7a}, {0x0004e9eb567daf0b,0x00085eaf8dd7df3a,0x0000000000000001,0x0000000000000000}}}, {{{0x000deae24e7511a4,0x000762cb23734ed7,0x00066bcd84d23939,0x000c037c989a46bd}, {0x000c06543988385e,0x0003f08c8acc808e,0x00000e7680dc66ca,0x000e4c3c5332a768}, {0x00063204acc98ee9,0x000db0a0ef46de86,0x0000000000000000,0x0000000000000000}}, {{0x000b4a4e27fff289,0x0007eeb14e22b305,0x000e9d3141e930a3,0x0004f15435f5cd09}, {0x00052f55ccf3f336,0x0006c9377055f313,0x0000f610c74549ef,0x000c8d0207da4bf8}, {0x000b6ee97b1c2b15,0x0000920992fd2caf,0x0000000000000001,0x0000000000000000}}}, {{{0x00043f2525d2ebb4,0x000811edb2cca106,0x000c996f27900e32,0x00092edb6f6af92c}, {0x0002dbdef8275bf9,0x0004dd3d26338446,0x0004401818a7ff9a,0x000d60e7694d8e21}, {0x00054e87fa7aec62,0x000f988bdd22449d,0x0000000000000001,0x0000000000000000}}, {{0x00063c9fbe4e6775,0x00026d7e7ff11afb,0x000c6b3e18f7eec0,0x0005c983e08b80f1}, {0x000b75d6b5a4c84b,0x0005f99e3a4b0fd4,0x0005a7cfc4904ce8,0x0006c336a99a7afd}, {0x000e4a736ba1e62f,0x000595be20ba2924,0x0000000000000000,0x0000000000000000}}}, {{{0x0008c92f010fc781,0x0002463423f6e871,0x0005f129e35dae8d,0x000d59f4aeff7db0}, {0x0000c963932f5dba,0x0005e468db3cf82c,0x000e23c6b7d10e1f,0x00006e08595910e6}, {0x0008880e8c76fb1b,0x000134e8c1259453,0x0000000000000000,0x0000000000000000}}, {{0x000506649d87b671,0x00014c272ea4f089,0x000aa2740669dd1a,0x000622f8a6cc0d62}, {0x000e392244f6f191,0x0003dcbd9dd28338,0x0000c61a8dd7166c,0x000e4930a90ca39c}, {0x000d41296b979b8c,0x000037aa5c88b76c,0x0000000000000000,0x0000000000000000}}}, {{{0x00051d16f31cd955,0x0003fd720fff5e54,0x0006c62e42ceacd9,0x000b72856f74fc83}, {0x0002b8a51db93ff9,0x0006ca983e7b6bb4,0x000e06f8fd893a36,0x0002491c6c8908ee}, {0x0008e9f64e123094,0x0005764984e58063,0x0000000000000001,0x0000000000000000}}, {{0x000ad9aba979f347,0x0005557b9d835c0b,0x00089b7877984846,0x000ce8c3c6bb325d}, {0x0002e0fb571c388f,0x0007185f17237c5f,0x000ac5737bcf4832,0x0005f037df6f53b0}, {0x000b6f7ae34a972e,0x000821f685c7b273,0x0000000000000001,0x0000000000000000}}}, {{{0x000e5575bc0dd4ad,0x00028eabf66053ac,0x00054861cbd6dc53,0x0005b123ea9fdaff}, {0x000c00ecf823c855,0x0005d8934d09e411,0x000eb090ae97a01a,0x000591dabc9c170c}, {0x000f751f273c40a7,0x000f0f52861011d8,0x0000000000000000,0x0000000000000000}}, {{0x0002bc9a33075cd8,0x000bb779de4fde35,0x0002eb1b199f0130,0x000e29003c4457b6}, {0x0009ff04878d3a95,0x00004ebfeec1a9dc,0x0007d0d097a6545e,0x0008673c7b41f5aa}, {0x0007894e63c5c4ce,0x00005b385d1700a6,0x0000000000000001,0x0000000000000000}}}, {{{0x00046d7efcbdeae0,0x000fbb2f349cfbe6,0x00022f14a9cfd187,0x000ef46f7fb5a2ff}, {0x000d8084df701781,0x000b2e7da6ada115,0x000273537b36285a,0x000d779e5cbe2143}, {0x0007b1bb342159b5,0x000321182d17ef98,0x0000000000000000,0x0000000000000000}}, {{0x000974b9395d5c1b,0x000a203e9046670c,0x000c9fa51be4f31c,0x0000167fed87df23}, {0x0006d7ab1aee3553,0x0006c8a7b334d671,0x00037b8b3f821601,0x000677ee013df3eb}, {0x0007a3a1013ff132,0x000a7ed7d1a2e9a5,0x0000000000000001,0x0000000000000000}}}, {{{0x000b3fd002806466,0x000fd4605cfac818,0x00085d2f0b811efd,0x000167145bb41efb}, {0x0006e3c03cac7ee2,0x00085c4b2dade36a,0x000220dcd3725a14,0x00032cf525a550bc}, {0x00014db66b11c84f,0x000013664e47ace3,0x0000000000000001,0x0000000000000000}}, {{0x000a48858e7d464c,0x0002276f7bbfd1a7,0x000e24ada567d04c,0x0006a941adced466}, {0x000c270addbb103a,0x000761ca82f14e02,0x0004d0794b62798c,0x0007a0bec3f90326}, {0x000caf618966e8d4,0x00021a1f211c02e6,0x0000000000000000,0x0000000000000000}}} }, {/* digit=65 [{1,2,3,..,}]*([2^260]*G) */ {{{0x000c24408b5b4bc1,0x000d861e48c2aa26,0x0008746f93b2fb6c,0x0005f018515690c4}, {0x0008d76a3c1b771e,0x00093035c899fbb2,0x000d18ac338e0049,0x0001b4e7f02fa3d8}, {0x000fabf9b804c035,0x0002f83e6175e309,0x0000000000000001,0x0000000000000000}}, {{0x000830680485a054,0x000962c1a8a622f6,0x000f94a3f3450d94,0x0007a83e0a44d62d}, {0x0000105319e21805,0x000a4a1ebdd2bed2,0x000f4863d6076c13,0x00034672ca137368}, {0x0006135e4ef4b1a4,0x00020b6692537ff9,0x0000000000000001,0x0000000000000000}}}, {{{0x0001b7a5e08fe30e,0x00029eb048815ab8,0x0002e0a161f11e12,0x0001801becb84207}, {0x000ad5b394a58f8e,0x0007512807890edf,0x000f675b3e4e4773,0x0008c99841055d81}, {0x0003ed35c1050ce1,0x0006c217bd56acf4,0x0000000000000000,0x0000000000000000}}, {{0x0000d6c8c5a1e005,0x000ddbaf53db5dcf,0x000c6ab4e4f6ee72,0x000e686032c8481a}, {0x000415c545af61b4,0x0003595ad60e7c0e,0x000f59b261ffe75c,0x000cf66fa7cfbf47}, {0x0002e7097fa1aaf6,0x000a8386b7977f21,0x0000000000000000,0x0000000000000000}}}, {{{0x0000029a7619e46f,0x000f29f5c333074b,0x0009e45f3bb1eec5,0x00035aadf8396133}, {0x0000825d3e2a3176,0x00034ef799bdaba5,0x0007f38574f4d09c,0x0009085e808678d4}, {0x0004a57483db0387,0x00054465ae9f6d1c,0x0000000000000001,0x0000000000000000}}, {{0x0002fb74fcaebc4b,0x000ef4b901e46eb5,0x00068ec4a861868e,0x000f51a07bab1199}, {0x000748f19df109f2,0x000d75da4f6a75a0,0x000f255613859652,0x000e60c8067759f7}, {0x000b663826b7b569,0x000f450533f4d440,0x0000000000000001,0x0000000000000000}}}, {{{0x0008e66704c4911e,0x000b5ad20de07d3b,0x000dab27e9b7aafa,0x00052dbe3fb66eb5}, {0x000cf7ce856345ac,0x000025496cdf84c8,0x00082f095b8e1e29,0x000e8e6db4cd7761}, {0x000b0faa321aaa54,0x00088ae73fef003b,0x0000000000000000,0x0000000000000000}}, {{0x000d643fd4fac454,0x000c4870e138d616,0x00069ca59b85612f,0x000a26a00889a9e6}, {0x000c093e3dad6fb3,0x0006ce66bb43df1b,0x000244dae036271e,0x000c05182a82fcd4}, {0x0002559d8958ca2a,0x000a7526838c8510,0x0000000000000001,0x0000000000000000}}}, {{{0x00084b954cc2f383,0x000a776cd88b3801,0x00070c99422dcf3b,0x000bd45086f66f43}, {0x0005f7b81c0e8bc4,0x00004cad2493575c,0x00070ce4091825d7,0x0004f1ff4bbf4b9f}, {0x000d28bd9ac2a0a2,0x000c23e5ebf7a3b5,0x0000000000000000,0x0000000000000000}}, {{0x000270e7ebdf9c15,0x000050eb783548eb,0x00081562bc5fd0b1,0x0005f68896b8a59a}, {0x00073bc130375edb,0x0001c5bd938ab1fc,0x000c19c89b28feaa,0x000f8d6e4b1c7f18}, {0x0009f7384e98a494,0x000a3f55131bf640,0x0000000000000000,0x0000000000000000}}}, {{{0x000a27923d9331dc,0x000f04ffb6351b25,0x0007f29f1e1c9bc2,0x00069b7d91e80528}, {0x000d48a56cb26370,0x000d9a9a20ff75d6,0x0000b393f52dd397,0x0003703dee3c5227}, {0x000f9c1c267288a6,0x00083849651d4713,0x0000000000000001,0x0000000000000000}}, {{0x000d56c853c2dd2e,0x000a93bc1a8d521c,0x0008735173646598,0x000967ee4685de4b}, {0x0004cf35701ef418,0x00080b116b6dbbce,0x0006b03c5acf7cf3,0x000fe839b4243541}, {0x000841fbd8d1a9cf,0x0003a6e1730d1f15,0x0000000000000000,0x0000000000000000}}}, {{{0x000fdbea99958b96,0x000e01f76bf65ac0,0x0000c6778adf573b,0x000d0f51ffd85a6f}, {0x0004afe98c72d927,0x00087e8ec8173887,0x000d76d032ae57d1,0x0004df95e88800c6}, {0x000ec4042dee55d1,0x0008e8cd5760c30d,0x0000000000000000,0x0000000000000000}}, {{0x000eac1084c10f00,0x0001c37bdb463a14,0x00076281603cbf77,0x00034037d48543b5}, {0x000f3b965ac3efc6,0x0009a7be5b6e5426,0x0003d0f87fba3664,0x0004ddb5ca9f2e20}, {0x000052649abbc317,0x0004b72eb6083655,0x0000000000000000,0x0000000000000000}}}, {{{0x0001bc4f61438294,0x00002964a43b5d5c,0x0005d7c26171c634,0x000967cc93c0fb82}, {0x0004b96145dca1b7,0x000b5c4ddfd06836,0x0007f0eec5bd3c73,0x00082d7bf8f0d500}, {0x0005b93c7771d6fd,0x000475f222990f21,0x0000000000000001,0x0000000000000000}}, {{0x00026e01b4722367,0x000926340c9a0a1d,0x0007edb2bec04b5b,0x0005d17d0417ca25}, {0x00072b41c7280efd,0x0003c942f670df33,0x0007910fbfcef999,0x000437ef3a577e3d}, {0x0004d4c9039005c5,0x000edddb0ceb3a8c,0x0000000000000000,0x0000000000000000}}} }, {/* digit=66 [{1,2,3,..,}]*([2^264]*G) */ {{{0x000a3a0634a3ce07,0x0008f38d14324956,0x0002232fc3562771,0x000d389e5a0479ef}, {0x000b882744b806a6,0x0000bd687af4d435,0x000d3172792b960b,0x0001f792e60e4cec}, {0x0009dcb17063be91,0x000c5902f6ffb4b0,0x0000000000000000,0x0000000000000000}}, {{0x0004fbf6f215ba3d,0x000918e7c66f8fb0,0x00095b38bbb07b90,0x000022d201c5b207}, {0x000344fdf3937c67,0x0005a11142ee01b8,0x000cb5fc7b97506e,0x000c2ae4043311b8}, {0x000e1937f2450b7b,0x00045fa26a70cfe3,0x0000000000000001,0x0000000000000000}}}, {{{0x000fdc4396bfa539,0x00092b7edbcb88f2,0x00019d35421db912,0x0000a538d5dee79a}, {0x0003b035e9ea2a42,0x00021709fe9cf14f,0x000a5b749703f94e,0x0002495b47e8690c}, {0x0002ef0574deb7af,0x000dd4b09d6324cc,0x0000000000000000,0x0000000000000000}}, {{0x000f7df3b9fe6e0b,0x000f9e25c764e67f,0x000b9153d851593e,0x000822d7ef6d9489}, {0x000c9238e5449117,0x000bd3333b1e34e4,0x0006cfb58cc8198b,0x000b7b487650416c}, {0x000068c07a8085b4,0x000b7b5e20cc8eb3,0x0000000000000000,0x0000000000000000}}}, {{{0x000af6a4691425a8,0x000eb7a958bb9efe,0x00085a7002151b0a,0x0006a8775208123e}, {0x000055575f5446b3,0x000528fdeea0c896,0x000a43b1b4d824bd,0x00096f550c5c7315}, {0x00050cdbb6610168,0x000b9c3638cd4a93,0x0000000000000001,0x0000000000000000}}, {{0x00039bfed8d0ec30,0x000230c0cb3e1745,0x0004b3cb7f69dddc,0x000a60a97d0d2a3a}, {0x000c6d61d74827e9,0x00048c2e237c10e2,0x000c78dae64ccf95,0x00031e036445ee96}, {0x000bee13f244e4cb,0x00012ec220b81c78,0x0000000000000000,0x0000000000000000}}}, {{{0x0008b837d4bef687,0x000919e15922b2f9,0x000c8afde9c62c29,0x0009534c95a1a3c5}, {0x0008f604b1043ffe,0x0007a01a13fa2f63,0x000393b04cd8a8d2,0x0006e26fd0c22660}, {0x0000808a072545d9,0x0003871dd10699cf,0x0000000000000000,0x0000000000000000}}, {{0x0007dfe3a4ea56b7,0x000094c38223ef03,0x000e8b66c87d36e2,0x0002766ee28405ae}, {0x000f0a065b535e3e,0x00084a317ded4b87,0x000866d3f53ac0b0,0x0007a0ee55860ca5}, {0x000a7080382b21bd,0x0002f3ff1d58cf1f,0x0000000000000000,0x0000000000000000}}}, {{{0x000760a0d077a674,0x000256d1eb02b933,0x000a86e63e76464f,0x000e22b473632441}, {0x000db481034e4b15,0x000914ef870834a6,0x0004c2dffa8bbf34,0x000d9d0466943feb}, {0x00031a2dbf893cc1,0x000615fa26911a87,0x0000000000000000,0x0000000000000000}}, {{0x0002f76d13211f86,0x000b53e5f9871239,0x000bd8e3f6da4b87,0x000367de3555d6f5}, {0x00095ebc54c2b323,0x000413dbb2bd8e48,0x000ddef4e974c105,0x000de08da1d15f48}, {0x000eb47f901deb65,0x0004f245e4c32880,0x0000000000000001,0x0000000000000000}}}, {{{0x0005b2c93a39a68f,0x00012def13c9b690,0x000a5eaf60ed34ff,0x000eed4546115d13}, {0x000acc0704820ad4,0x0000c499c60761b0,0x00013af5dd51e45f,0x0007a978e5524abd}, {0x0009f811db1ec09b,0x0005900dab7d3aa7,0x0000000000000001,0x0000000000000000}}, {{0x0005f21e6490481e,0x0009c0ea3d3b19a7,0x00068df5edf0364a,0x000c93c95e1d6b4a}, {0x0008333e2dcc0b44,0x000a8fc7be078322,0x000350437cb9512e,0x0005c965c20fe9e1}, {0x000d3176a887068c,0x000004e870a54162,0x0000000000000001,0x0000000000000000}}}, {{{0x00005c3b211947b8,0x00027fda98024305,0x000832a6aa27a459,0x00057be3feea006c}, {0x000ba0bb599ef407,0x0009c187eff74059,0x00032aa4ef6180b7,0x00072b398f55afe2}, {0x000cc5ddc46af4a2,0x000e611d5ea71271,0x0000000000000001,0x0000000000000000}}, {{0x00085981da5484c4,0x0002661fa0fa34a4,0x00025e8fb282c8f6,0x00009d9542344d00}, {0x0005e720cc73e773,0x00081ad0388c6b65,0x00097a5b5f85f411,0x0006173a273c5fde}, {0x0000126c0a036ea1,0x00030085c778a65a,0x0000000000000001,0x0000000000000000}}}, {{{0x000dd3a67c2984a5,0x00072c7824703af1,0x000bf0c69c5b39c7,0x0000901a46f942bc}, {0x000f89e0174be31d,0x000b6326f7d38bdf,0x000eadb91bfcc1ea,0x0002541868bb8787}, {0x000a48a8ba038566,0x0004606d8787616b,0x0000000000000001,0x0000000000000000}}, {{0x000e290f5d5f8e88,0x000eb41d33d54569,0x000662b634f1ba52,0x000fc5049dfd1d1b}, {0x00059be51c909876,0x000b7406ba93e420,0x000475a49355b9dc,0x00048963ea182651}, {0x000985ceebcf7670,0x00062eaa85c80508,0x0000000000000000,0x0000000000000000}}} }, {/* digit=67 [{1,2,3,..,}]*([2^268]*G) */ {{{0x000b5648e1eb2291,0x000ba734c2f6e413,0x0008535398b202b7,0x000a8b23ebd7f177}, {0x0009fd3b0fc5e7ee,0x0003df55ddc7a0f1,0x000261d577641e2a,0x0008f496646ecb9f}, {0x000f2be9c112454e,0x000e02c23da6a9da,0x0000000000000000,0x0000000000000000}}, {{0x0009d35c52fed679,0x0007671efd66d8e5,0x000904f29b91b401,0x000c352b084f27ae}, {0x0000123e88566129,0x000229faaea32636,0x00087f4c04620cfd,0x0005535f695ec91c}, {0x000fc2a2127c5854,0x000fa1c94873fa3c,0x0000000000000001,0x0000000000000000}}}, {{{0x0004b028b8f44cc5,0x000fa18c73e470d1,0x00046af781c684d5,0x000aadf0eb44feae}, {0x000604610320e3e3,0x0008fffa44fd9c59,0x000908270d9d9d3d,0x00088a6283f3ebbc}, {0x00060d649fcec534,0x000e1d44a603fadd,0x0000000000000000,0x0000000000000000}}, {{0x000740ae33023df3,0x0000135f6a91ebce,0x0003780772b2000b,0x0004747ae7ea71ec}, {0x0007f6f03b13d0e5,0x0006603e33fc299d,0x0000d28b6e9df68d,0x000a2043747f8604}, {0x0006089683aeee37,0x00024e9926fb8de4,0x0000000000000000,0x0000000000000000}}}, {{{0x0006c9f15018542e,0x00079fb1f6fe5f6f,0x0005889ab7c13ba5,0x000129b7c5358418}, {0x000a9ac0306d8ad0,0x00008b37c84cfb84,0x000acf7da701dcb0,0x00014bb42427b3eb}, {0x0006e318d3d02d27,0x000958db234da419,0x0000000000000001,0x0000000000000000}}, {{0x00031a9f2e6d1d68,0x0000ba7009240e02,0x00063eb8c05422c8,0x00081b3a6ec6a77b}, {0x000bc58689a5aa19,0x0006306dfb930061,0x00007013549ec203,0x0005410416293e63}, {0x0001a4d303fabd7a,0x000ac172f1e81c7f,0x0000000000000001,0x0000000000000000}}}, {{{0x000b9ad3970b9e18,0x0000bf6af8e430ab,0x000f59d55e652348,0x0002bd614bc56b8b}, {0x000183df0a6ecc07,0x000ee1786d25c98f,0x0003feabcc84059b,0x0007b20a09a6f26f}, {0x000d600ce79a2dfb,0x000f39cf2e6f0393,0x0000000000000001,0x0000000000000000}}, {{0x00072a39f3507cb8,0x0007042b1470af9b,0x0007da313b04804a,0x0000e590e67c9622}, {0x000cabec90cccc29,0x0005e76e6a796f29,0x0001637cadb620bf,0x000d15b03af38ec0}, {0x000dcf7634087520,0x0001906c0ca6b7d8,0x0000000000000000,0x0000000000000000}}}, {{{0x0007eccab473c8b5,0x000354c80ff211e0,0x00045d2bf3c3aaa3,0x0005bdea352cfb52}, {0x00016f804d4fc256,0x000e5ad706ca34f0,0x0006619c96cff608,0x000490525e689857}, {0x0004163c78de4a6f,0x0007e4b87dad9b7c,0x0000000000000000,0x0000000000000000}}, {{0x00035a48ce31e1e3,0x000c4a6aef85129a,0x0002e4b9afe02466,0x000a8b4fb7e5c1b3}, {0x000e4ea65ec8abb1,0x0009979db25393ba,0x00064b047eeb2086,0x000d6e5e56906ac0}, {0x0008d958b203281d,0x000de4155ed9842b,0x0000000000000001,0x0000000000000000}}}, {{{0x00019bc174c6d988,0x000cf4d9f702e572,0x000883fd073431fc,0x000f7c52e0996638}, {0x000331a7f7f18050,0x000e9196a2374342,0x00087a7400e71f3a,0x0003791b5d724c12}, {0x000499ca89fe518a,0x000e565820d945a9,0x0000000000000001,0x0000000000000000}}, {{0x00035b7cb9fac00e,0x000a632b3417a9e4,0x000077b9768bc095,0x000afb46dde432fd}, {0x00032553ea0ffde2,0x0000725529dbe056,0x00071cbdddb8ca1c,0x000edb41a198fcb3}, {0x000f5060041dd314,0x0009a1fe368a743c,0x0000000000000000,0x0000000000000000}}}, {{{0x00059195e6de2d3f,0x00030ea9f4518076,0x000e3f066c30b9f7,0x0003bd981db2f294}, {0x00046e95c601e580,0x000782f5d49b6ae4,0x000f2a24bea15da5,0x000d57d82c482be0}, {0x000747b852b55a3b,0x000400c12ad66ee4,0x0000000000000000,0x0000000000000000}}, {{0x000106fc9ab22be0,0x000f3ff85e4be397,0x00064c04ee049a9a,0x00068c1771b2f4aa}, {0x0009c56a4f6e25c6,0x0006c0243a7cc3be,0x000082558b6f8b1c,0x000d25ba47737910}, {0x0009a82551abc22c,0x00044f195c4a902e,0x0000000000000000,0x0000000000000000}}}, {{{0x00037e57ac34630d,0x000fc2c030f2d54f,0x000b84aa880649ef,0x000b55a13ad19d77}, {0x0002091bd296d1ca,0x0008f7f0b28c0816,0x000d7580c469726c,0x00021840b8cfb847}, {0x000fd3c1cc59a8b1,0x0008b90e2778fdc8,0x0000000000000000,0x0000000000000000}}, {{0x0006cc1f42f98900,0x00026c3bf2f82644,0x0008d5f8bb74fc86,0x00077c747df08423}, {0x0005d41c77ea13a8,0x000556d8fe471d93,0x0008287e98cde5b5,0x000c068f4d40279a}, {0x000305a88e400538,0x000e77c091d74bdb,0x0000000000000001,0x0000000000000000}}} }, {/* digit=68 [{1,2,3,..,}]*([2^272]*G) */ {{{0x000190a6f12cf864,0x0009e0eee766f86e,0x0005b775cd536070,0x00057c69d4566a98}, {0x0005745df1e07e40,0x00047733f9c06722,0x0006e2b1b1c2a5a9,0x000fc80987a24bcd}, {0x000f4061ae7293fb,0x0007d711f7042b89,0x0000000000000000,0x0000000000000000}}, {{0x0003c1b0341e791c,0x000537daedd9c1c5,0x000495a12d7c48bf,0x0002d4a32c8c9765}, {0x0005a662fe9dfe7c,0x0007c6bad9faed52,0x000660c5c4df70a2,0x000bba7fb07624dd}, {0x00091b1d621abac8,0x000771b618ce5d4a,0x0000000000000001,0x0000000000000000}}}, {{{0x000c915030a7a399,0x00068b673999f751,0x00008c22b2afe146,0x000bf6a5fc300d5b}, {0x000b3e178c0bceca,0x0009d38258020b90,0x000176381c171fe7,0x000e86f32623a2f1}, {0x000f64b9bf3a66cd,0x0002c55668f5ac6f,0x0000000000000001,0x0000000000000000}}, {{0x0001812516e735d9,0x000aea3ea58c5dac,0x000356a5f10de279,0x000295b07e9f7153}, {0x000f586ce9eb4d08,0x000daab1a3f7c783,0x00000a0030b2d7c4,0x000c2198f3166033}, {0x000184aa9d0c0475,0x000b11a6fe88caba,0x0000000000000000,0x0000000000000000}}}, {{{0x000ba5c8d0193b1f,0x0007644c52e9d2ec,0x000084d971b1a2c0,0x0000ba2904071452}, {0x00016420810c95b0,0x000726c12ee37ace,0x0005cdbfb3b34658,0x0001ddb8f12176e9}, {0x0002665465a782ea,0x0005989e91fb9ee1,0x0000000000000000,0x0000000000000000}}, {{0x0000c16d55245f9b,0x000a5ab01d1b1ade,0x000186cc016cdfa5,0x000f20c1907f643d}, {0x000b819ce2692951,0x0001e463db499758,0x000551bae173a15a,0x000c9960164a1a60}, {0x0005b509da7db4de,0x000254d9cec8875c,0x0000000000000000,0x0000000000000000}}}, {{{0x000b44e11c323d06,0x000fd5d6d986113f,0x000894e506cf902d,0x00052247fd0b1d00}, {0x000a2782247b185a,0x0003bd1827ee7a96,0x00075cc817a81ab7,0x000d58e21da1b5a6}, {0x0006b1f8c96f3b0a,0x0005eb0b4feab1ba,0x0000000000000000,0x0000000000000000}}, {{0x000e1e70f2721b75,0x000160a2caaa6a94,0x000c595ff3de4a5a,0x000a75c84e2aab67}, {0x000e555f145b7c4c,0x000c6003a47731be,0x0008f07e7fe03b5f,0x0007c95ac06b0bfb}, {0x0000ec8f9062bb21,0x000d58a73aafef97,0x0000000000000000,0x0000000000000000}}}, {{{0x000123c6709431e0,0x00010ae6e4e2793d,0x00084b28d12b01b7,0x0007bca51962e973}, {0x000f98e6a52dea7f,0x0002d8bb8dd35519,0x00063c8d202bed1f,0x00009ec87640cd7a}, {0x000e8802cf11aa3f,0x0002789d1734b8f7,0x0000000000000000,0x0000000000000000}}, {{0x00015a8a3e8d859e,0x000534ae889a29d5,0x000da86637742cb4,0x0005ee22c15c8252}, {0x000ad4f9397a87f5,0x00093d8a684e2ab5,0x0006af7ba63ff2ec,0x0004f0fe6a52e297}, {0x000effff8321e195,0x000d2957562f8dbd,0x0000000000000001,0x0000000000000000}}}, {{{0x00023e7069e42e0e,0x000d2239c3ca8089,0x00005746ae0d546f,0x0009bcbb8ee8194a}, {0x0005279f5c84f339,0x000373c06a06d19b,0x000c70d34e701108,0x0008ba438171e418}, {0x0007c7306769b5b5,0x000064bf193f46da,0x0000000000000000,0x0000000000000000}}, {{0x0005544b033a42d2,0x00061e556329a54d,0x0006aab67ee7a477,0x000c61bcc63287d0}, {0x00034397f22f1672,0x00021907d612d307,0x000ccf64c77cc188,0x000f80df2be0b759}, {0x0001db9d853899e4,0x0007cb0c4b9b73aa,0x0000000000000000,0x0000000000000000}}}, {{{0x000ff9f36c3349d4,0x000c3db537864c16,0x000d990835ee2990,0x0003c5fb1d408a12}, {0x0004b5ff931b6504,0x000452158a1b1e0b,0x000db8a2c29f72a6,0x0009d61be31c5985}, {0x0007a2320489621d,0x000480174d202617,0x0000000000000000,0x0000000000000000}}, {{0x000294c195148880,0x0009ed88751bd34b,0x000f46ac8a70ae99,0x000917e5c0560f97}, {0x0002525c8ba24922,0x00048c3502a88bf3,0x000ee6a458ba7134,0x0003f607a14e42a8}, {0x000dd29054842573,0x0009c1acd66ae0e2,0x0000000000000000,0x0000000000000000}}}, {{{0x000edee700e2b9a1,0x000ca05fd3e47e10,0x000775354363597f,0x000b8ab9d14d9e5f}, {0x0009809ae6cb63e8,0x0008a4dd84740965,0x000dd249f1a5c96c,0x0004d2f79af0cb6e}, {0x000166e5361d2b7a,0x000692fe3d22a60e,0x0000000000000000,0x0000000000000000}}, {{0x0002fa6f8995a329,0x0006e396d7a363f7,0x000d92f57cc488ad,0x0009d1958510a286}, {0x000c0b888aa8bf0a,0x00042decec317136,0x0008b9bdf9fc71bf,0x000ac0298d41b6cc}, {0x0009ecbb249e5d99,0x0004db314b57f810,0x0000000000000001,0x0000000000000000}}} }, {/* digit=69 [{1,2,3,..,}]*([2^276]*G) */ {{{0x000d708c668b7357,0x000d96ce839038b2,0x00020e1ea62ce28e,0x000713c58763eab5}, {0x000e2c4523fd6ed2,0x000eae1cb271027f,0x0005e4f9c4b8cf67,0x0009601ad02024a9}, {0x0007d73ac0716494,0x00064337442ffcdd,0x0000000000000000,0x0000000000000000}}, {{0x0007851b23ec84bf,0x000beedb8574d7b7,0x000286ebfe9b645b,0x000e45ce0c8710d8}, {0x00056a79aecb4766,0x000f379f83c2d312,0x000bbc5340ea164b,0x000df851521a164b}, {0x0009d5d5e1ac3081,0x000081b205779b7e,0x0000000000000001,0x0000000000000000}}}, {{{0x0003e4b56c489ffe,0x0000450823173431,0x000479ae5276717f,0x000cb05ce3d436d8}, {0x000ddf2257834d02,0x0007cf804300a63f,0x00048d555acde6aa,0x000b3233d0de457f}, {0x000aa55b4de5db66,0x0008a60379d9ac81,0x0000000000000000,0x0000000000000000}}, {{0x000e90717067058f,0x000132c47bead613,0x00090e8a449f2111,0x0001c278b92dfa6c}, {0x000a20e5052e4286,0x000d62ef7fbb21a8,0x0005d03da29cea2d,0x0002b105405706ce}, {0x000dda27b321921a,0x000d13a8070a212b,0x0000000000000000,0x0000000000000000}}}, {{{0x000d23cf55c45926,0x0005b98778f5f299,0x0001705a5c8c8b02,0x000b88f43919b71b}, {0x0001fcb92372e0d5,0x00043296e160fa37,0x000a4970a89cc719,0x000334a3ae695fe1}, {0x00051e4b95dec2f9,0x0004d6275a594212,0x0000000000000001,0x0000000000000000}}, {{0x00047e08dd859c11,0x000f2faa12f1b2ff,0x000ffb55ea0ad152,0x0005927a2d49016e}, {0x00063e898a743956,0x0007e768ee6cdbde,0x0009ce79201bbe74,0x000b64e8832a0a06}, {0x000cff0774d3af5c,0x00081d58cc25a522,0x0000000000000001,0x0000000000000000}}}, {{{0x00027f0e1b46fd00,0x0003f1c1b9a1af5b,0x0003c2c754fc491a,0x0007d3165cbaab1f}, {0x000360310665c2a7,0x000a6d64bd760e64,0x0004ce1abfa1968d,0x000d2b0e1701fb5f}, {0x000d3c4d7b466c4e,0x000f912ebf21257e,0x0000000000000000,0x0000000000000000}}, {{0x000f6e44d2ef47a9,0x000cdeddd0d09650,0x000acd3234c8ca37,0x000cba5fb7244def}, {0x000f3acca56c2d39,0x0004d3ff0e42e4fe,0x0003498d03959e10,0x000b101ed923e651}, {0x0000842e240deada,0x00047140cf65c53a,0x0000000000000000,0x0000000000000000}}}, {{{0x000420de7a3cca92,0x00078c40b5d961dc,0x0000669c0650c56a,0x0006512b20ea2fcd}, {0x000c80cfdc1ced7d,0x0002dc4c42793f28,0x00014af2a2c66b61,0x00038712d0f465ef}, {0x000a3e10f498de28,0x000eefd43378b1ab,0x0000000000000001,0x0000000000000000}}, {{0x000182339af2de22,0x0000f52743e62529,0x0007cb967f975c8a,0x000a495f3b942e5d}, {0x000442c93c4c7a6f,0x0005ea4e81af911e,0x0001c3361393032e,0x00046ad975cf453b}, {0x0008fb85fbd84437,0x000e9f19bef58359,0x0000000000000000,0x0000000000000000}}}, {{{0x0001c8a03a758373,0x0002ff5d3c5d987b,0x0008d28755f9b053,0x000696c9a6811aec}, {0x000671a05c762526,0x000b50917885c6fe,0x000e435b1cd97329,0x0007d6424b129ce1}, {0x000fb69b5d25c001,0x0005bf8fd3449e7d,0x0000000000000000,0x0000000000000000}}, {{0x0003b3b4745aa0fc,0x000a304f13caa8db,0x000c42581d38c65d,0x000a26e3f1637449}, {0x00075086fb17831b,0x00070bccf51f20a3,0x000ec67794f66bbe,0x00008759114e8fb9}, {0x000e55fefba15c3e,0x0006b06274e840ba,0x0000000000000000,0x0000000000000000}}}, {{{0x0001392a85eee65b,0x00037ebdba8a73a9,0x00057c70feb31623,0x000f9841fe6064d0}, {0x000abb8ea58571cb,0x000f4d78e10f9265,0x00010194ea34ee68,0x000ee932bccc86c6}, {0x00018b05ba4d88af,0x000c7f1b666c9e95,0x0000000000000001,0x0000000000000000}}, {{0x000bfc49e59e8fd1,0x000ae405208c75f8,0x000d373c5a99df54,0x000a977279933e71}, {0x000da64aa0b3f5b8,0x00036d2c0da96b6a,0x0002eed5227ca046,0x000b6e0ffb64c414}, {0x000baa05111d0f26,0x0006496cce8a3203,0x0000000000000001,0x0000000000000000}}}, {{{0x000c440343aef952,0x00019eda15115cbf,0x0004c0ca17c7be65,0x000b899e1e404697}, {0x0006bd56cb968d39,0x00077f25afafaffc,0x000e8460c48baa89,0x000cb8ddcae733c5}, {0x0004e7b4d8db3dd6,0x000d4730c42ef0ea,0x0000000000000001,0x0000000000000000}}, {{0x000ded4336e0e996,0x0007761c36485b3b,0x0003a9ef9b460a85,0x000ea119c163b2e2}, {0x000f8699c32d39ca,0x0009afc21d6fbf2a,0x0006105b2f30acbc,0x000d2782e1795cd4}, {0x000bd0296c5de1eb,0x0003f540db331e94,0x0000000000000001,0x0000000000000000}}} }, {/* digit=70 [{1,2,3,..,}]*([2^280]*G) */ {{{0x000566c4dd75c1b4,0x000a0570856265b3,0x000cbace31affa63,0x0002b4ed64645336}, {0x0006de49945b2d79,0x000ffedb2ccdc41c,0x0001239fc3fec1e4,0x00056c094341fb38}, {0x00028185bb5868f9,0x000adaf680572da8,0x0000000000000000,0x0000000000000000}}, {{0x000e0585aa2d876a,0x000b95480f8f0fbf,0x0005be334d530bd3,0x0002f278c2d3c86e}, {0x0006b676d6c82d76,0x00039dec8e1488b5,0x0003e4b756194ec5,0x00094e5ad8a2c0fc}, {0x0001d4129e01cce4,0x000c459cb7e94c1e,0x0000000000000000,0x0000000000000000}}}, {{{0x000e172f71314c57,0x00073776d707122e,0x00007937b43cc86b,0x0005775ac42e1bf4}, {0x00055e0abab130a1,0x000a4930e58a6f41,0x0005a237af5f75c8,0x0004f7ffdb8ee4d2}, {0x0008fe7af47745ba,0x000467da1f09c11c,0x0000000000000000,0x0000000000000000}}, {{0x000ab833ab90a6b8,0x000669bed4019358,0x00007b7fe4d74f45,0x000d834f00a5516c}, {0x000f035a36d318fe,0x000f8a31bb46f3d5,0x000972946e1df3bc,0x0001ef24a7e886c9}, {0x00085864c383ab5e,0x000a5b85a50c0d32,0x0000000000000001,0x0000000000000000}}}, {{{0x000d65b66d82688c,0x0003872c2925e382,0x00080fde81ac79d0,0x000a2b38a2432027}, {0x0005fa34422b6bc3,0x000948d55e24a659,0x0004efa7ed8f149b,0x00071011867cfac1}, {0x000bd1e94e578bbe,0x000803efa0276501,0x0000000000000000,0x0000000000000000}}, {{0x000f7389f88ed003,0x00099b4f58dfa2c9,0x00027af2024d3bff,0x000a0ca5e0ca7fb1}, {0x00083782dbf7ba09,0x0009fa5d6101098d,0x0005231abdbaa4b1,0x0009c03b0d70ddb8}, {0x000cba60cbb85949,0x0003ba8d596ce326,0x0000000000000001,0x0000000000000000}}}, {{{0x000ec042211830fd,0x000f78b67d56f78a,0x000d0dd5f0085f0a,0x00077ef6d1879493}, {0x00009d412929cede,0x000f8f47fc6254c3,0x00038136cfbb6a12,0x00090a561c304af6}, {0x00064012770283e0,0x0006e8c77dd363b1,0x0000000000000000,0x0000000000000000}}, {{0x0009730231689c1a,0x00078a2910104065,0x0006adb22ec70366,0x00007eaa5919dc9a}, {0x0000eff75ea6bb96,0x0001b154022f103f,0x0002e9dc4300dcfa,0x00023ebbf1abfdcf}, {0x000c7610a1be47bf,0x000ee8e48e43b23b,0x0000000000000000,0x0000000000000000}}}, {{{0x000366222079ff20,0x000dd6c255282fb1,0x000e5f65eafcf45b,0x0009b30515c02959}, {0x000efd5074c2f0d5,0x000460bf3169d34d,0x000d88198c4daf0f,0x00042d35aae9cd4d}, {0x0006f8fb3a3e2b92,0x000e5b7ee19179cd,0x0000000000000000,0x0000000000000000}}, {{0x00015c0c8bdd26b4,0x0009fc2499885330,0x000c27ee4ed9b18e,0x000e30d901ee8c44}, {0x000a438c4d057961,0x0007a847d74e4722,0x0005e9ebd34c3ce2,0x00049ec1f371fc17}, {0x00062cfa628ad626,0x0000258cb8ba2199,0x0000000000000001,0x0000000000000000}}}, {{{0x000414eef61746f8,0x0002f44b16d63548,0x00091c53690466a2,0x000700b4b9b4826e}, {0x00069ba41d6fddfa,0x000f48b184a9d1c2,0x000af1a9a1ae5623,0x000688445e2f1d66}, {0x00028a0ef16e7621,0x000ea0a509e87455,0x0000000000000000,0x0000000000000000}}, {{0x00016c4ebf9d1f30,0x000002405c88d64d,0x00021995ea2cb159,0x000476f59206340d}, {0x0007fbdb47138c1b,0x0001fc51a673c4a8,0x000c132d81d7d81f,0x00033035e2c568d2}, {0x0001981e0c2e86c3,0x000c9f25fcaa15dd,0x0000000000000001,0x0000000000000000}}}, {{{0x000b2a49ca5dfb81,0x0008d370aadb7c4a,0x0009f4ebf1398343,0x0004d610d25c9ac8}, {0x000b49c7f0f75d8d,0x000cfed5c3ca14e0,0x000cd7f4d6f7590d,0x0007d93cbfaa36f5}, {0x000dce79a65cb3d1,0x0004b4bd97f1011d,0x0000000000000000,0x0000000000000000}}, {{0x00001207087dd6cd,0x00049477a85a518b,0x0007671964d279a4,0x0001d11aff88af2c}, {0x000a1dbb6c2c5f27,0x0005ba326b82395c,0x0003c2898f431018,0x000463dc513c0cb7}, {0x00069f2786b20305,0x00061fc5c18db944,0x0000000000000001,0x0000000000000000}}}, {{{0x00080adc636061c1,0x0006244e403a263d,0x000ad04e1deab320,0x00059720dcbb6130}, {0x000d66e8505322a2,0x00060fb3f5231b1a,0x00049e1cd79b6e2a,0x0006179c366e663d}, {0x000c6ea0d01277eb,0x000473883c4ffde6,0x0000000000000001,0x0000000000000000}}, {{0x00040167fca5210d,0x000d95aec71f687e,0x0001c63bde59a231,0x00074dfa4af79a44}, {0x00060fd79e68ddec,0x000b613ae2a19527,0x000036b08e61ca70,0x0003e30d2b549e73}, {0x0008fb383d922e0f,0x000aa028c146216d,0x0000000000000001,0x0000000000000000}}} }, {/* digit=71 [{1,2,3,..,}]*([2^284]*G) */ {{{0x000090e2290855e3,0x000c63856faf70c3,0x000a537fff7cf9c3,0x00002007d0317a7a}, {0x00010dc853b3261c,0x0006ccdf2c616875,0x000385cd6f188d53,0x000a2955fa1d26fd}, {0x00087bdaef2d7d6e,0x000b0f3173148e30,0x0000000000000000,0x0000000000000000}}, {{0x00084c9a254216ed,0x00047cc0770de6d7,0x00035e4c8fa4bf8c,0x0000f637aece660d}, {0x000adedb7b99e891,0x00082ce72b5ced4f,0x0001d4d0fa07446a,0x000194600c851570}, {0x0004ffcea4152f30,0x000c96f31c15edf3,0x0000000000000001,0x0000000000000000}}}, {{{0x0005b1c7831bdcc8,0x000d027bafc7d23f,0x00050c19efdbe5d1,0x0007a7533cdce225}, {0x000573af279d2535,0x0006015a5e144120,0x000803b571412097,0x000eb203384ac91c}, {0x000edd68012ba72d,0x00091d825c3d8d2b,0x0000000000000000,0x0000000000000000}}, {{0x00023553a39f8385,0x0005b8eaf27fe164,0x000c4539fb7ef933,0x000adc9ffa5830e5}, {0x000950a5e503466b,0x0003a2a96a1dcbb8,0x0001a89a62dca0dd,0x0001d5f98db48a88}, {0x000554b9506e0a31,0x000dcd69efeec8e2,0x0000000000000001,0x0000000000000000}}}, {{{0x000b8cbe4b97fc6c,0x000e5a71915ba245,0x00044263935f5290,0x000ce189775a8de5}, {0x000cd0549c8def51,0x00027c89477b9645,0x00047cfbc54728e8,0x0000c7cb6412bf4c}, {0x00016bf97806ea22,0x000feea61b447d92,0x0000000000000000,0x0000000000000000}}, {{0x000a3fafee06d0a1,0x00032a2cf4c624fa,0x000baceff4ee9dd4,0x0007411d429aa2e7}, {0x000d154759f7bffe,0x00091cde409d4d9c,0x000a9a31ac9508e0,0x000deb0f736891db}, {0x000c17f78c058b52,0x000b43e218c9736e,0x0000000000000001,0x0000000000000000}}}, {{{0x0000f4f238352945,0x000f07d445a023b0,0x000551441addd54c,0x00008f85e62fb5bf}, {0x000ffd275f3aa334,0x00001eb4ed1f4e87,0x0000af1b08c2f8d7,0x00093b5987facbec}, {0x000542336f0bc311,0x000587219a8c1237,0x0000000000000001,0x0000000000000000}}, {{0x00052f04dae724bc,0x000e221a68b0a55d,0x0005bdff6f9d5fa5,0x0007e3f2da24e831}, {0x000628b43c649948,0x000a393f548cc549,0x000acee934d621cc,0x000e0ce12d1b52e8}, {0x0000b93c4f0e6025,0x00077116663ffdcb,0x0000000000000001,0x0000000000000000}}}, {{{0x000b53f717a44956,0x0002c65fee76e1bb,0x000ae70d2da363ec,0x000cd6887a61f9c3}, {0x0002283a4e23325b,0x000ae6d909c60aab,0x000702a1dcca3dd1,0x000938d6a31c5517}, {0x0003e01f167bc2d3,0x00067596be65d549,0x0000000000000000,0x0000000000000000}}, {{0x0007978a4e132cb0,0x0005df10adf1702e,0x000364f7e05324c1,0x000693e3866569f8}, {0x00082e303b6c9df3,0x000298933d134854,0x0003d7696e64c215,0x0000f465322046cb}, {0x000e839e686c1c09,0x000b7f8ac2e6f682,0x0000000000000001,0x0000000000000000}}}, {{{0x000e71627b708629,0x00012bf54385d85d,0x0007bb4ab478b057,0x000a3b2ccc6b5489}, {0x000f67fa6f6a05a9,0x00073cd5233bfef8,0x000c4c4f505a80c7,0x0006a3fe8c185c9c}, {0x00059e110f37ae33,0x00054cb440dc7a62,0x0000000000000000,0x0000000000000000}}, {{0x00050c98bc7b0e1e,0x0005a04b3793331e,0x0003b8d31034a8aa,0x000c95dac900df01}, {0x000fd52027ee1c99,0x000b5be3aeb891a1,0x00042f3b68574224,0x000ae00bb37d5ba8}, {0x000a7f31f3f36375,0x0008c304743a2813,0x0000000000000001,0x0000000000000000}}}, {{{0x000c7e03b7aa645a,0x00091f7e39a28977,0x000995d7d443d68e,0x0009f39216c442e1}, {0x000b376cc21c4025,0x000705644f75967c,0x000592e3b90bca20,0x00056be0ef613507}, {0x00097f2f7456e836,0x0004b46438409baf,0x0000000000000001,0x0000000000000000}}, {{0x0005a21df85e1c6c,0x000b0ab454500393,0x0004c5912b476c6d,0x00065a0d1aa49d94}, {0x00059cdd7e7069d5,0x00090a402b7eeef8,0x000283db40b228bb,0x0005dcdf2c268733}, {0x0005a42d37d44810,0x000b80e5d1af0360,0x0000000000000000,0x0000000000000000}}}, {{{0x000c14cb537e819c,0x0005f2b3bf6b7569,0x000cc275187a0bac,0x000925ef6c2d559b}, {0x00025a54533380eb,0x00019f0d6cd0382a,0x0001433bbf74a021,0x000bbd994d4caf68}, {0x00027772c53999a9,0x0003af249226a38d,0x0000000000000001,0x0000000000000000}}, {{0x0006a46b5b493127,0x000bee887c8f7779,0x00045dd063eabbf7,0x00029199a0a8e117}, {0x000918d22e28aea4,0x0000ecebe77e69a9,0x0007cecb0ed2deab,0x000637aa98d20edf}, {0x000a194790e52888,0x00060c73078fbd0c,0x0000000000000001,0x0000000000000000}}} }, {/* digit=72 [{1,2,3,..,}]*([2^288]*G) */ {{{0x0009af391a8697ed,0x0007fe5bb7320546,0x00080d05ad03f5f9,0x000f9b7973b1a3ca}, {0x00033b52add9800a,0x0003cc487ccc82c5,0x000f71a0da2ae069,0x000c060c7047e46c}, {0x000a21503aeb64ab,0x0004ed0075b1d33a,0x0000000000000001,0x0000000000000000}}, {{0x000a2bed91298551,0x0000c49a79f6b129,0x00022374a19da463,0x0001305962f001a1}, {0x000a3a3cc4dcc90a,0x000188b4cc026cef,0x0002ff30fbb1d3fb,0x000c36e3761cad09}, {0x000dbdbdc6354b93,0x000b2ab73317cff3,0x0000000000000000,0x0000000000000000}}}, {{{0x00003f3665635e4e,0x0004e17fd85da26c,0x00052fd006ed5f69,0x00032d252f043a61}, {0x0005c8bc9cc74510,0x000f5370ca9348d5,0x000540b56333c4c6,0x000bc9a5ca533610}, {0x000d8071b716d25c,0x0002367337f70a39,0x0000000000000001,0x0000000000000000}}, {{0x000db6fc5387c11b,0x000cfd3251b14397,0x000d84aa2bfdb755,0x000e38100cc3e62a}, {0x000046071f1f89e9,0x000e7012d9e47fb1,0x000e6ad97ec5c7c3,0x000698bc4de4f6c7}, {0x0000c6a07a4e7cef,0x000198a03a3a1224,0x0000000000000000,0x0000000000000000}}}, {{{0x0003b8713123ec24,0x0000419a51d2d151,0x000c8ee7e2c9c855,0x00039f110d3d8f17}, {0x0008ce870e320ac3,0x0000d4e71030e599,0x000ace1a5cbbd4da,0x0007c15bfcfe41d9}, {0x000408b36096093d,0x0006b26a0c56d39a,0x0000000000000001,0x0000000000000000}}, {{0x00035ac9181317f5,0x0008d46d26280ae2,0x0003c29370c4bff6,0x000addee48f7eaa2}, {0x00030f605627b203,0x0003e03ba6674883,0x000cdd81ae186660,0x000d8bc04a9667b4}, {0x000cbc45ee0c1b5b,0x0003d34e81dc5ff7,0x0000000000000000,0x0000000000000000}}}, {{{0x00063b161dddd94b,0x0003d7c93f0cc576,0x00022d6ac11071af,0x00012d84b9149bdc}, {0x00088e44e4632e63,0x000448cc8ec50d4c,0x000f89a6c85277ac,0x000e128700eabfe4}, {0x00042928ea38e5f2,0x000e293e261880b7,0x0000000000000000,0x0000000000000000}}, {{0x00051028cc113b68,0x0001919b6a14e2fa,0x00082dfd5da09549,0x000ca662e13022a3}, {0x0002996fafc24233,0x00018dea4f505fe4,0x0005a2d96182166a,0x0000199ba55815ea}, {0x00077232622a4ac8,0x000311b13c3b8133,0x0000000000000001,0x0000000000000000}}}, {{{0x0008673adf41d204,0x000e2a0a390575d9,0x000dcb844f35fe0b,0x000b6f4f917550d3}, {0x000fc6ecf7285d09,0x000925f580342d9d,0x0008746022d9fb4c,0x0001b6b73d4bc619}, {0x0004aa1c30d7a3bb,0x00003bf32bccb3c5,0x0000000000000000,0x0000000000000000}}, {{0x000783e73d6e9052,0x00006db6e57f7b8e,0x0005d1afd274f869,0x000318770758e016}, {0x000290175b314342,0x000e6d25df464413,0x000da9ee1f0d5093,0x000297855e553138}, {0x0007c7b64937a717,0x00057ccbf262664b,0x0000000000000001,0x0000000000000000}}}, {{{0x000d9056eeba30b5,0x000355a8c404c7b9,0x00039ffec5e11fca,0x000c3ac7b4f4c637}, {0x0001ace1869851e4,0x000e1816afc7de47,0x000d517fb7e6978f,0x00040e256f62bd56}, {0x0004bb4c53034a6f,0x000aa98eb4b9ad2d,0x0000000000000000,0x0000000000000000}}, {{0x000fd2909662ab1d,0x000c55f8463596cd,0x000074f62f74b11c,0x0004dfc43f12c5ee}, {0x000ad69405653ae5,0x00089f1d6e4668a4,0x000187ca431697ab,0x000831cc4eed080d}, {0x0003a69f7d775edf,0x0004e434435eef6f,0x0000000000000000,0x0000000000000000}}}, {{{0x000a1403851eb93a,0x00085c9ae49b53f2,0x000926a512455b57,0x000ca729dbef4a6b}, {0x000b8440248e399a,0x000191c77a9a0e66,0x000873c8f27a8296,0x0005408861a08ed7}, {0x0002bbe9c5e3865f,0x0003549235be42ba,0x0000000000000001,0x0000000000000000}}, {{0x000a46fbe3334020,0x000abf1524bdbc9e,0x000b376fa382ce55,0x00075b35cc1fb214}, {0x0000910d13b19369,0x000cf5d3212ad3b7,0x000c7e93b691b3bd,0x0001ba22d0312eb4}, {0x000285b3975e5da3,0x000c999e2ec96eee,0x0000000000000001,0x0000000000000000}}}, {{{0x0005bf15f46be575,0x000a1061cb09c821,0x000ae2de789e5912,0x000cecccd84851c6}, {0x00001b95ccd21d74,0x00032dddf26a2851,0x00049210122d3f6d,0x000f02c5d952db55}, {0x0004be99796a4aa1,0x0004078cde88aab2,0x0000000000000001,0x0000000000000000}}, {{0x000d753b80855f9f,0x00078288aff9b92c,0x000f7cdce61cc49d,0x00048cc3dac4e445}, {0x000cb0ac2a937fad,0x0008c5bdda956fdf,0x000bb3e81841ce29,0x0005170e6c819f12}, {0x000efd73ecab58ad,0x0000f476a3a48130,0x0000000000000001,0x0000000000000000}}} }, {/* digit=73 [{1,2,3,..,}]*([2^292]*G) */ {{{0x0004f332dc67a3c5,0x0003213d82a4383a,0x0000fc0621356af6,0x0004ca32ca05acfd}, {0x000c1e80103ea886,0x0009dd0ff4c2e9c7,0x0009d764c64b7589,0x000680c128a8c988}, {0x000fdb7cd881a125,0x000ec5f09f58ad77,0x0000000000000000,0x0000000000000000}}, {{0x000ecd4f9cda86d6,0x000c4c41a633a8c6,0x000847c2f58ecb1f,0x0007b29592dae51a}, {0x0006e268f50e3a7d,0x000a27de2a3b5eef,0x0006d540d7a599e3,0x0000d01f9b571491}, {0x0005e52e5204fbca,0x0003d9eb48615c67,0x0000000000000000,0x0000000000000000}}}, {{{0x000d9eaa867420c4,0x0002f7f5caa2ddb0,0x000c31038c0ddc32,0x0001596a08fb4b57}, {0x000a6d9ca6980a65,0x00095c78a8ab32e2,0x000ba78e5808eeac,0x0004f5f9923d5a32}, {0x000ad1c8d3bbece3,0x0007098f8b845926,0x0000000000000001,0x0000000000000000}}, {{0x000843645beef787,0x000fa28875d75316,0x000e13608c5a90e9,0x0005556eaf90c364}, {0x000dacc40e05857e,0x000c5012b59e332d,0x000230b2b76768f9,0x00032932d53c8a76}, {0x000999fbd573bdff,0x000840eee9300114,0x0000000000000001,0x0000000000000000}}}, {{{0x0002362363f6901a,0x000be66748446167,0x0005f5c47c0db36f,0x0002fbb39fb54024}, {0x000e344525a7871f,0x00071375bdbedf63,0x0000bd89f085fb8e,0x00001c59b6e647d5}, {0x0008031fa2f2ea43,0x000d9b58012b6657,0x0000000000000000,0x0000000000000000}}, {{0x0003015fd48eca8d,0x00082cfde2151d47,0x000e4d908c99616e,0x00004977d4ec3b2f}, {0x000f513df9ad204a,0x000b66641e3ee923,0x0009df2175bb5d92,0x0004cdb5c3c90fcd}, {0x000de8809fac5725,0x000985c6981a627f,0x0000000000000001,0x0000000000000000}}}, {{{0x0001a0d912586411,0x0001b0d49fbe5702,0x000bb57b277de5b2,0x000a4b2d7291e7e7}, {0x0008c16da29ce1e6,0x0008f8b71f4426f8,0x000fbf76a6ebaff6,0x000cab510adb9995}, {0x0004b996a6ec18d2,0x0003bc3ce11f1f8d,0x0000000000000001,0x0000000000000000}}, {{0x00004c4051321f3c,0x0003af34703d798e,0x000dd55e68b6b0a3,0x0007f09cb14161e8}, {0x0005357558d9c473,0x000d9a485a90c00b,0x000dac2508e73fc9,0x000ed252e5f5bb09}, {0x000b1efcb4ba2132,0x000593c58bf23933,0x0000000000000001,0x0000000000000000}}}, {{{0x000d1217cba9c6d8,0x00087cb7a562f7c7,0x00004fa0d0ea0e23,0x000c05e3acd8379e}, {0x0006d159e80cdee0,0x000029ffd63834d6,0x000500f3ee777b61,0x0007b75be130d659}, {0x0003756de768a261,0x000a541b809584c6,0x0000000000000001,0x0000000000000000}}, {{0x000af54a67204972,0x00085857b547d484,0x000954a25746036a,0x000bc1881e0295bb}, {0x000d3d231831b4de,0x00002708fd517190,0x000b1e9571812770,0x000c3e25dfa6c88c}, {0x000fb3c57a9f5467,0x0001d404949d8103,0x0000000000000001,0x0000000000000000}}}, {{{0x000a34fad1eabbbf,0x000de71fa7ad8210,0x000d67acfecf1047,0x0005ec7ec527279f}, {0x0007906ba2abc3a7,0x00066a25ce54f7d9,0x0001e7d558ddfb44,0x000ba77bccd91efa}, {0x0005405027796dc3,0x00072f9ae8e511f6,0x0000000000000000,0x0000000000000000}}, {{0x000feaa4cfcc2a79,0x000d60cf749b854d,0x000ac1632a7218b2,0x000a7ce21f4e0ce3}, {0x000550325628caf5,0x0006b7d84c8e6b8a,0x00081d8e5bd9a461,0x000bb7affd9d5730}, {0x000dca775afff520,0x0006a52e629d73fb,0x0000000000000000,0x0000000000000000}}}, {{{0x0008f6b8297fa26e,0x000d76f386ac99ac,0x000ce235f3a2acb0,0x000620801a076df3}, {0x000c62031f455ef8,0x000d6e488b1627c3,0x0008ebc5bf3c9afb,0x000c4512c254ea59}, {0x000abb87bcef237d,0x000cb4dcacb5a5ed,0x0000000000000001,0x0000000000000000}}, {{0x0008e7718ef189e7,0x0004207cf70cc015,0x000e9a66810fd747,0x000d69bb7c99d1b5}, {0x000454409a3962cd,0x00014e1d3b541825,0x0008bec33aca5afe,0x000a9c5e4a92268e}, {0x000bf2e95060a307,0x00093a289c336375,0x0000000000000001,0x0000000000000000}}}, {{{0x000781a84aba36d2,0x000ad7584291d55b,0x000992c0a266ea73,0x000e02af20e9954c}, {0x000ca4d73d175169,0x0001612ee12718e0,0x000cf1ded50926de,0x0008c1060d91c638}, {0x0007dc332b5998df,0x0002624eb7dc884b,0x0000000000000000,0x0000000000000000}}, {{0x0008eae21aadf4bc,0x0005c2a9f4bf2cd7,0x00086c74c6b37272,0x000a4de4b5b5158f}, {0x00093ba4800d6736,0x000138590e451f46,0x000263ed2239cb95,0x000545bdc4c56f5d}, {0x0006676d4c0f8acf,0x0004038bbd0743d0,0x0000000000000001,0x0000000000000000}}} }, {/* digit=74 [{1,2,3,..,}]*([2^296]*G) */ {{{0x0004fe80d04c169d,0x0001452da244cb71,0x000cda8b72206f04,0x0005887084ee9fa6}, {0x000920e111da7c3d,0x0003bb35ef1c2673,0x0008e61906e57c45,0x00073eebaa206a85}, {0x000dd3b5bf458238,0x00015dcf71c4a720,0x0000000000000001,0x0000000000000000}}, {{0x000605cdd81e2955,0x000ac0e98756fb91,0x000f0286c4ccda7a,0x00017819b4372718}, {0x00031dae0a5d8a40,0x000720f8cb219351,0x0003217261dafa40,0x00006fb18c8c40e0}, {0x0003c7d483485194,0x000d46e02770cacd,0x0000000000000001,0x0000000000000000}}}, {{{0x000b16ebe5676f0c,0x0006e7f47e5b4652,0x00071c81701e6ae3,0x0007f8d6e3a4cc33}, {0x00067b29431c31ae,0x000869125faeb29c,0x000fd62e16be2afb,0x0004934ce6d0052c}, {0x000cd74901063882,0x0002e62b021800e1,0x0000000000000001,0x0000000000000000}}, {{0x000a39e3523a9de5,0x00076121f34b3253,0x000d9c36b4aaa3b5,0x000b23992e0442ed}, {0x00023d2725144419,0x000ced8d6e4d3747,0x00011186d58a7080,0x00050cd63ed11b1f}, {0x000c6faa6d7a4d0b,0x0002559c897561f4,0x0000000000000001,0x0000000000000000}}}, {{{0x000657d806465325,0x00095fd29c362706,0x000e70b9e028365a,0x000fa40d084d6b18}, {0x0009d80bbbcfec68,0x000a06728aae56df,0x000361eb62533738,0x000dc77e1c92bd4a}, {0x0004fbeefd3c11b1,0x000cfba52dffafa9,0x0000000000000000,0x0000000000000000}}, {{0x0009acb1f00a47f4,0x000024e668d3f2f1,0x000095d2d5d23cbf,0x00076b697f105b84}, {0x000da5b550d7489f,0x000c9d3a15e73345,0x00093e0d2b26a8fb,0x0001e4494adfd6a2}, {0x0008e6417e038745,0x000fb0b051833181,0x0000000000000001,0x0000000000000000}}}, {{{0x00013685fee3f167,0x00059193a123f397,0x000f28bae616ef5a,0x000d2c6567b33050}, {0x0004dae5b6596da7,0x000481adbd59fc9e,0x0002c1618dde4a40,0x0001f2a194682fe9}, {0x000c05bc15adc043,0x00013edb30fcceea,0x0000000000000001,0x0000000000000000}}, {{0x00047d7a2900c6ea,0x000e954cf35b8dee,0x00074908606c425e,0x00094a88cdac359e}, {0x000fbef2c858622c,0x000d0f745810d20b,0x00041d71ca77f658,0x000782f59f1e4267}, {0x0004af36c640314c,0x000e35ec0709c829,0x0000000000000001,0x0000000000000000}}}, {{{0x000c5c739f094c18,0x000b75fcd89a8d55,0x00071a4d047c0dcd,0x000ef9a3d498ccfb}, {0x0008f669e7edb8ba,0x0008d6b13c20d8ae,0x000a564d16a48c79,0x000250d241703f4c}, {0x000680ef9509f9dc,0x000970b2c17a388c,0x0000000000000000,0x0000000000000000}}, {{0x000778808942861e,0x0009abe8d8d33c23,0x0009bd2fb189dd26,0x000112581e8769b1}, {0x0009d657bacd662b,0x00084fbcaa8521c1,0x00091c546adc05d5,0x000c68fad3f4e938}, {0x00057bce78617aeb,0x000701e39a422608,0x0000000000000000,0x0000000000000000}}}, {{{0x000d79f624f8eb1a,0x0008e9c5d103b9cf,0x00071b65a5829554,0x00034991b8462f3d}, {0x000b51453c2b2409,0x000cf62fb341c087,0x0006cdb37eea50d1,0x00027ada571b02ab}, {0x0009e677d1b49b69,0x000004b52dc4d6da,0x0000000000000001,0x0000000000000000}}, {{0x00042f171b839d5a,0x000765b6cceda32e,0x00009960889dbcc6,0x00040e8e2e336d9f}, {0x0001f34cefd7de54,0x0008bc6b5ab410a8,0x0000cbb91782d60d,0x000a95e22f3046d8}, {0x000775cf7c99291e,0x000282ca473be09e,0x0000000000000001,0x0000000000000000}}}, {{{0x000b6a03ba3e1ec6,0x0006b7fefa851ec2,0x0003a92f6680a7bf,0x00075deabf4905c0}, {0x00096ff483a6ae8a,0x000c163b2b784673,0x000be098999b6fbd,0x0009c4a535388968}, {0x000b8e919419a12c,0x000b0bd87c889640,0x0000000000000000,0x0000000000000000}}, {{0x000f69e3681b9e47,0x0008fc5971b3c868,0x000bd601db453ea0,0x000aee960ff01a96}, {0x000a0347158b6a72,0x0008994151ef1dc3,0x0007de4b70d9ea4c,0x0005a29068423993}, {0x000e4276c73a1788,0x0008a834f8bee71a,0x0000000000000001,0x0000000000000000}}}, {{{0x00059366b70a0b8b,0x000d60abadb72457,0x00087caf5b975b84,0x000cc3f1983f793d}, {0x0002e94d8de541ce,0x00090b687cd8885c,0x0006b6cd952f2acf,0x000016cc05b6d504}, {0x000f97cdb266e5bb,0x0007c95959c78452,0x0000000000000000,0x0000000000000000}}, {{0x0001e70e0efd1f63,0x000528c8989bfc93,0x000c244410e36663,0x000645d5f14f2667}, {0x0008cf8059cc8bca,0x000d2134f71c94e0,0x000ba7b1d1a84e91,0x000e21c35b983489}, {0x00003bfc5dddbab1,0x00099886156a8fa3,0x0000000000000000,0x0000000000000000}}} }, {/* digit=75 [{1,2,3,..,}]*([2^300]*G) */ {{{0x00083fd796b1a72b,0x000c549640b910ec,0x0001f3c076c5166d,0x000b7e4e553ff932}, {0x000e97e2f7e676d2,0x000a2cdad5097c11,0x0004bc0c5cedff5a,0x000757d09eef397f}, {0x0007434958d95f66,0x0004eee32eada9e7,0x0000000000000001,0x0000000000000000}}, {{0x00041f85b3f06836,0x0003aba0e3496ce6,0x0007931548ea6b77,0x000149273aecbf5b}, {0x0001858c42c5d2ef,0x000ddc70d91528b8,0x0008d341c157c1ef,0x000a690e10df0a32}, {0x00064f5d30760fd8,0x0000d14ec3b44ea3,0x0000000000000001,0x0000000000000000}}}, {{{0x00087f011572bb6c,0x0000d126f1e48db1,0x0000d05c4b7b6201,0x000a2ba1e0fbe5e8}, {0x0000224d802f13f0,0x000e0b8698189e96,0x0001b4bc0b8af43d,0x000c706b742b2859}, {0x000d9196336bf7ae,0x00007fec0d2fd363,0x0000000000000001,0x0000000000000000}}, {{0x0000b0b6ce7179b1,0x0007cde982e3e244,0x000d814a6fad99d6,0x0007d3497edfbb4d}, {0x0007a46c6afc84ac,0x0004cd907a63bbd7,0x000909a18bcc3d68,0x000d756b5193f098}, {0x000f37ab5d6e0581,0x000ffb06adf4d102,0x0000000000000001,0x0000000000000000}}}, {{{0x0000415e4f4b1ce2,0x0002f16bd8544ce9,0x0003e7600d6c664d,0x000d9aa401912f05}, {0x000dd3e0c268e1e8,0x000f14013443dcda,0x000f59cbf936e212,0x0004b8aaec39252c}, {0x000d652c200b8cef,0x0000aac64c11e47e,0x0000000000000001,0x0000000000000000}}, {{0x000c08e2e7a2dfe0,0x00048459176893a7,0x000c7c5a8f0afe8a,0x000e999b6f043d0d}, {0x00000b3c3cfd6e33,0x000b4fbc5e2a496c,0x000f5eee2690de5c,0x00073d2db4511dfa}, {0x000fecdd2743e927,0x0004f4ade6a1948b,0x0000000000000001,0x0000000000000000}}}, {{{0x000039609cadf211,0x000339488fdf258d,0x0000e39945a1e037,0x0009a8444d16fa60}, {0x000c454408c23f53,0x000ef729fbf7f8cc,0x0001fe369b8abc6b,0x00053dbd87a47666}, {0x0000f6266a890341,0x000de3c7b4bcd279,0x0000000000000000,0x0000000000000000}}, {{0x00006e205ec9aa47,0x00063cce1af477a4,0x000f7fcf64572e77,0x000c931743d00999}, {0x0003902adccdc1f7,0x00041be26f8b87a1,0x00006779ffcb96f5,0x0001c0636264bb59}, {0x000484331c0db1d6,0x00076e5585c8ae19,0x0000000000000001,0x0000000000000000}}}, {{{0x0005899b377cc15c,0x000f315fff92e2e8,0x000a8cf599eb4a44,0x0002e4cfca1a3e87}, {0x0003f205f34e217a,0x0009eb1362e4f28f,0x00061c84aa7c205e,0x0006fa76515b6ace}, {0x00083aca37e55058,0x00030435e870f8ec,0x0000000000000000,0x0000000000000000}}, {{0x00002203ed113de7,0x000655318327d42e,0x0005d903904004d9,0x00094adb7cd1d2f1}, {0x000ebca1242c89d2,0x000af2a1423b5bb4,0x00066f393818e824,0x00079a30444115e3}, {0x000183b2cd6a53de,0x00047bfd324d8249,0x0000000000000001,0x0000000000000000}}}, {{{0x0001ee196db2cf29,0x000718a1d049034d,0x000acaf386ae53d6,0x00006d746605e4e6}, {0x000c4458e136fcc3,0x000b7a1ac677dc40,0x0006ee4bb331955a,0x0007b95c386ed47f}, {0x0006640fb4384103,0x00081000a37bb752,0x0000000000000001,0x0000000000000000}}, {{0x0008cc55b8f1bcdb,0x00025171d84cd78b,0x0001b8eb12ee7e03,0x000bd8c564c45f59}, {0x00076c2283df12d7,0x0008a36461b03bfc,0x0000c8cafd6fc812,0x000ae72b6275a058}, {0x000438282511c376,0x0008780ca3213fce,0x0000000000000000,0x0000000000000000}}}, {{{0x0002c0f6f353cadb,0x00056c17179cb81e,0x000af140db008101,0x0001bb5e63cd1fa8}, {0x000b0729533d8217,0x0006676827544c77,0x000fe1b0143af56f,0x00045a759df2599e}, {0x000962b593accffd,0x0007a3c61321e555,0x0000000000000001,0x0000000000000000}}, {{0x000e58a6aa5358dc,0x000739bb4d42d566,0x000e6ef3760e0cfd,0x0004fb370620ef46}, {0x000c2253e0f9e680,0x000b5c8c64f4e9cd,0x00008daec6f6658c,0x000504153037a80d}, {0x000215b47cc959be,0x000e4e7aaaa8653d,0x0000000000000000,0x0000000000000000}}}, {{{0x0002bc233166381e,0x0000199700029af5,0x0003201dddf2a837,0x00085cdad02e2c74}, {0x0006daea6cd36d88,0x000c3f784e7e3512,0x000e882fa40cea6b,0x0001eec16a3a5130}, {0x000c43706ace2f12,0x0009ccf3c3a16a13,0x0000000000000000,0x0000000000000000}}, {{0x00064823f9e7a6c2,0x0007bae8e4729ac9,0x0003fe54edfeed8d,0x000a4e7bcfba42bd}, {0x00039e917bf88ec6,0x00004163c606be20,0x00009b017d5a63a6,0x000c276869bd6bdf}, {0x00094144ff021410,0x000a13f038cdd94b,0x0000000000000000,0x0000000000000000}}} }, {/* digit=76 [{1,2,3,..,}]*([2^304]*G) */ {{{0x0002f8bd1741a941,0x000d4f3177637189,0x00060a2c8b16c0b1,0x00012ea49a688a19}, {0x0004556eef3eca0d,0x0000c833814746c3,0x0008d8b842db71e9,0x000b1bf4ae9e3fdb}, {0x0000ee706bc576b9,0x00054e85a8de649e,0x0000000000000000,0x0000000000000000}}, {{0x00032799b9f19edf,0x000975259805923c,0x00076f95241c4760,0x000d3b18d6c8d637}, {0x000fa677dee0ddd3,0x0002ad9334e5bcea,0x000ceb27ca464781,0x000594d56dac3990}, {0x000338deb39d6e55,0x00096c7a9d83d78e,0x0000000000000001,0x0000000000000000}}}, {{{0x000d7b49014b2147,0x000f134215e0ae52,0x00084df8cb33a781,0x000b10bfaf858985}, {0x00065449e13a9c3a,0x000859368bea1a4d,0x000d78c2c8134dfb,0x000ba7d94439b51f}, {0x0003f1c754b1e6f5,0x000d464cf5d47b00,0x0000000000000000,0x0000000000000000}}, {{0x000c286403cdb3ba,0x000c15d6597a8e6d,0x000e5e853fbe3d2a,0x0004c9898bd192da}, {0x0003c76032d13f80,0x00038d5e8bdb66ee,0x0007ea1349bcb167,0x0001e4001679e16c}, {0x000f1f584d22ec20,0x0007b7d9f317a982,0x0000000000000001,0x0000000000000000}}}, {{{0x000196d862941c7f,0x00015fd4c9380d4d,0x0000a23a9cf4968a,0x00039223ad85ace8}, {0x000b20fbe77f6374,0x0003ae3be886de7e,0x000a36dd5eea175a,0x00061d0a78e19da4}, {0x000a64f9638a5733,0x00007bdb82dd1f3a,0x0000000000000000,0x0000000000000000}}, {{0x0007fe74ebe49201,0x000a7702be0b4d0b,0x0000cad19bf2f6ec,0x000d6c0b5b514f13}, {0x000c08518708375c,0x00035c8f337b8d0b,0x00055fc06adb3974,0x00083bfc4b137fa3}, {0x00045b3d91207a07,0x0009d53cd23a6fdf,0x0000000000000000,0x0000000000000000}}}, {{{0x0000a67f092fe026,0x000e142efbca10ec,0x000cc433a343767e,0x000f6b9e68131944}, {0x000e836fcc884370,0x0005328231b4d1b5,0x000895d85b956e68,0x000117afd7ce3e4b}, {0x00028a48e23cd96a,0x0007756cbf1cc4fc,0x0000000000000001,0x0000000000000000}}, {{0x000c45bb98d0ddee,0x0002774201b8565c,0x000b4f52020bec2c,0x000bda65cd76ab62}, {0x000ae2fb221ac3aa,0x0007ba962fd348e9,0x000e7c381d5e875b,0x00068ae119edacdd}, {0x000b495d57186eb9,0x00056fdf795bd0d5,0x0000000000000001,0x0000000000000000}}}, {{{0x0003ca5ab59ddb41,0x000f7f1ebc9c6cc7,0x000f57e85f634cbe,0x0005a16eddf122c7}, {0x000c8a63efc695ac,0x0003541555a07f9c,0x0002a4d80e98783f,0x0006230998aabf3c}, {0x0008cb24667129fc,0x0002de1b3b8ba86c,0x0000000000000000,0x0000000000000000}}, {{0x00062aec0af56692,0x0007719a7045c1fc,0x0005b9718436f251,0x000c9b5d581f4e26}, {0x00069b5489f5725c,0x00051e7c1aa8e91e,0x00028ec256fe93ea,0x000487a680376ebe}, {0x00030e63df392cad,0x0009887cd96ae342,0x0000000000000001,0x0000000000000000}}}, {{{0x000e42367a9d725f,0x00039383477d80ab,0x0009bf84781ae655,0x000527eaf1389d3f}, {0x0004102ffac6350d,0x000a3b0583300052,0x0001cf3332af83e5,0x0006d633aac030a5}, {0x00033508c7e87b5f,0x00094e54cf554461,0x0000000000000000,0x0000000000000000}}, {{0x000f352ebddfa61b,0x00025e3d5e304a79,0x000673478bec8a85,0x00072acfcd082890}, {0x000446528a7ef652,0x000120a7a607746b,0x000c8aaaa126f2d6,0x000e0714c411ed8d}, {0x000219322242ecc1,0x00076f4dd29b9909,0x0000000000000001,0x0000000000000000}}}, {{{0x000c19050d8003bd,0x0000966c18887790,0x000653ed598ed239,0x000bbd18179a89ab}, {0x00050e32e18d6ebb,0x0003a242275a6e33,0x000cf9fda141c240,0x000cba7fbc6f732a}, {0x0007d9042bdcaed5,0x0004cddd17f09749,0x0000000000000000,0x0000000000000000}}, {{0x000dc494bed8e1aa,0x00072f9b4efbdcb4,0x000846e40ceacaf0,0x0008e7a08c964b79}, {0x000b697992c6dba0,0x000a31236d2a3b33,0x000f13c67e503cfa,0x000758371b2297ad}, {0x000a30fe4d1b0d5b,0x000937f2f3ba13a0,0x0000000000000000,0x0000000000000000}}}, {{{0x0001e3e792f54f5e,0x0002d66e1c349e9d,0x000411c782a7cb86,0x0004b067774f6f73}, {0x000f3d88b7029f91,0x0008ac9342be145f,0x000fba10730a2fc6,0x00017ace014c77dc}, {0x0006ebecfe34f062,0x000f04b7a85b9087,0x0000000000000001,0x0000000000000000}}, {{0x000e45d39d99da4a,0x0006122af68cfe2b,0x000beab553aeda14,0x000338ecc8cf47bb}, {0x0007a9f26575d185,0x000dafc93ebcf570,0x0006b569b4f26152,0x000a1c5170968500}, {0x00059575a58e4408,0x000d43a451b6b327,0x0000000000000000,0x0000000000000000}}} }, {/* digit=77 [{1,2,3,..,}]*([2^308]*G) */ {{{0x00031eea8652aa77,0x00075a9b33eda2b8,0x000ccb42fd2dd1ac,0x0005ab8fe55769fc}, {0x000ee2ea2c9e4a86,0x0008effb93c60208,0x0001522321dff3f2,0x000e5124fb782d6b}, {0x000f961e96e29dc3,0x000a6d2f39193c4c,0x0000000000000001,0x0000000000000000}}, {{0x0005e63b7e317479,0x0009d667da851f03,0x0007183aa797e9f3,0x00059f9fe886c75f}, {0x000d96d9e68574aa,0x000ee25277706045,0x000aa94b18ceb8f2,0x000d5bc3971ae4bc}, {0x0007b608157fc8f0,0x000150dd6428487b,0x0000000000000000,0x0000000000000000}}}, {{{0x0003f45b89aa7776,0x00091f2af99e2d25,0x00076414d1e112b4,0x000800014a8e2b12}, {0x000ffa17691a71c3,0x000bd4233ab0f6f9,0x000bd49cf4e764a4,0x0004012735f0ccb8}, {0x000037d3dc7fc071,0x000ae03da811ddf6,0x0000000000000000,0x0000000000000000}}, {{0x0004a8fb960d3228,0x00048eb39e1a42f2,0x00007ea05b5a3c40,0x000b7bd9d581bb93}, {0x0008feeb6ce36fa0,0x0000329bb28b7b8d,0x000e608fcc8cab6a,0x000504c03b085c44}, {0x000593cce3f2c4c9,0x00093bb2ef5a3d51,0x0000000000000001,0x0000000000000000}}}, {{{0x0005eee4a29b9e00,0x000dc20740482d3d,0x000e9ca5a465e210,0x000dbcf9b04be3f8}, {0x000cf79a10d11c21,0x00098890d16c757a,0x000df4eccacfdb2e,0x000f11b8ece9836e}, {0x000bc4d7a9a35695,0x0009ee2c9b7d003b,0x0000000000000000,0x0000000000000000}}, {{0x000e2dd26ff13203,0x000133cc51c6bc72,0x0009ca679c2a2da6,0x000951011dc4426e}, {0x00093bedba6ea308,0x00088d9217c2a099,0x0000e9979694eb83,0x000d521e97150620}, {0x000035d356c66be4,0x000161e2cef90abf,0x0000000000000001,0x0000000000000000}}}, {{{0x0002a5d7a2fe5424,0x000c5abd77fdcc05,0x0007ae8084591e67,0x0006481030c17511}, {0x0001f92e55b534fb,0x0006bd1eba6c21b3,0x00096514d056aef9,0x000df597cfd93bd8}, {0x000c4de2939ce9f5,0x0004ef6737cbaf10,0x0000000000000001,0x0000000000000000}}, {{0x0006ccf17f5b4aa6,0x00049ba070d7b272,0x00033084cb0ef8a2,0x00018fa7fece71d7}, {0x000e7f11b328ddbf,0x000b8c5b898e7f8f,0x000699bc5842d33d,0x000944b7141938ef}, {0x00039a13d619477d,0x000d5228db36f5cd,0x0000000000000001,0x0000000000000000}}}, {{{0x000b8747f420dd4b,0x000fb52bb177eca6,0x000f43dcaa9b6760,0x0007a3f15a0ec05a}, {0x000736800fc5d305,0x000bb74572a151d8,0x00065a96cf22ff7d,0x00019519394cd42f}, {0x0008227699f90840,0x00068419e24fe2e2,0x0000000000000000,0x0000000000000000}}, {{0x00025578363927ed,0x000574db66d688d6,0x000d409ddc1459fb,0x0007f82b70d69f87}, {0x000cb67c0931340b,0x000a17e9ba495398,0x00095f5bb6fc86af,0x000372330a201b0b}, {0x0002bfb684331f96,0x000759b31f0fa4ba,0x0000000000000001,0x0000000000000000}}}, {{{0x0008a9686e50ea9a,0x000fa53caf16bb29,0x0001e6775d854b08,0x00037450aecb3742}, {0x000a7e3971ac67a8,0x000916720ee3a053,0x0007ef527af5a2ad,0x0008c78907d26a51}, {0x0000187ff88dddeb,0x000580501085ffc1,0x0000000000000000,0x0000000000000000}}, {{0x000bd54c631b5ef7,0x0000a533ff81bdf1,0x0000234fa962cf5c,0x000a7f99121d8411}, {0x0004d769fb90a1f3,0x0005f3f42e621b7c,0x0007e5f02655798a,0x000d995fc9fe9a95}, {0x000560ed712fc645,0x00059000f20fc194,0x0000000000000001,0x0000000000000000}}}, {{{0x000ca8aff309b100,0x0000c85dcacc4c44,0x000282732cee9318,0x000efc73a9f020ed}, {0x00070ac2ec46ccda,0x0004edd612a22d61,0x000fb7673b4cf6d2,0x0000510828deb00f}, {0x000a061d4c49e843,0x00016c8aea6c342b,0x0000000000000000,0x0000000000000000}}, {{0x000ffaa28b87e79b,0x0001bb9617a5663f,0x00097f1ba9e99062,0x0002ee20742a4b1f}, {0x0000500e34cdf43b,0x0002b6de4ad6c0ab,0x00002eba08ef6f81,0x0004e0bbfd3a6364}, {0x00094460899a3582,0x0008335d3e07b17d,0x0000000000000001,0x0000000000000000}}}, {{{0x0005a71e395d239e,0x00026a160db974ae,0x0004df55ba5b2671,0x00091fe0f2bfd214}, {0x00027e4215d39cf2,0x000849498b3dc0a6,0x0000c7dfec311ed8,0x00029fbb50995b22}, {0x0005f9ca4a3d83cc,0x00085332f62dd6c5,0x0000000000000001,0x0000000000000000}}, {{0x0003278db69ec48f,0x000c56caebf5d4e7,0x000e4ab979b38b01,0x00005e1e7e210f66}, {0x000e800e35bf7fe3,0x00041625bdbbd247,0x000140764eabbcaf,0x000ae49d3fb6b3c0}, {0x000bed09dc31a840,0x00044a6c67185e6e,0x0000000000000000,0x0000000000000000}}} }, {/* digit=78 [{1,2,3,..,}]*([2^312]*G) */ {{{0x000976185cedb78e,0x00000d5ac29ab973,0x0005376ef5010492,0x000fcfdeb7cabe96}, {0x000e82ebeaa6eb29,0x000856863e849702,0x0002b7dd5820c1d9,0x00080b85b8b6adb3}, {0x000cc2bebcb2a1da,0x0001cb911240a24e,0x0000000000000001,0x0000000000000000}}, {{0x0009339d66471f42,0x00086865738f288e,0x000ec9ab31ac9389,0x0006dfc0b78b477c}, {0x000d22531d4c9b75,0x000957b1f72bea7b,0x000f90819668750a,0x000023544082b7ac}, {0x00010dd35fa97aa9,0x0000657c9376d4d3,0x0000000000000001,0x0000000000000000}}}, {{{0x000d393a7e12c9a1,0x00087315af1e7695,0x0005dad48c909f6c,0x00065a7e168b010a}, {0x00026d86fdc5603c,0x0008f52d5373f51c,0x000a497697c8b7d8,0x0006670982debc64}, {0x0009f942aaf7a067,0x0000beb15cc57a80,0x0000000000000000,0x0000000000000000}}, {{0x000728397fd456a4,0x000c8ff5563ef971,0x0004e73a2dd305f3,0x000cc516a80ae4a1}, {0x000352258160b828,0x00008533e6e74db7,0x000028314ad68011,0x0007541598a03b32}, {0x000c3d815763ab10,0x000089f632644f56,0x0000000000000001,0x0000000000000000}}}, {{{0x00096953520ee092,0x000306d200f67521,0x0008a20dfb41aa95,0x000ecbdc450070d5}, {0x00044a73c2aa2e56,0x000cf15e09936979,0x00039822bf1cc5f8,0x000ba98dee98b81e}, {0x00049763f39d2614,0x000dce88bf80d042,0x0000000000000001,0x0000000000000000}}, {{0x00090be494194f3d,0x00009eeb5f7526ea,0x00042892f629d76e,0x000de6b9665e7661}, {0x000e4db45bef0dd2,0x000f0c29ede66edd,0x000cdcbd947a3fe0,0x0009dc0bb66739bc}, {0x000aa185f9760092,0x000d98f355b62fee,0x0000000000000000,0x0000000000000000}}}, {{{0x00095d178d8fc8db,0x00088ab909e6143a,0x00089b7600c18603,0x0000f4aa942112c1}, {0x0008b5a1967f7a08,0x0003543a0e5057c0,0x000cafbf9ac78fd1,0x00049408a20a1598}, {0x000b58bcdfa7974b,0x00036217ad4e198f,0x0000000000000000,0x0000000000000000}}, {{0x000138c5bd603cb6,0x00072af896026457,0x000ea9d78b2185f1,0x000482318652917b}, {0x0008b9b757159621,0x000f2c7ae3b7470a,0x000d10f532d77474,0x000d6b40b8bfc96f}, {0x0004da23277081db,0x0005192cd44f13a5,0x0000000000000001,0x0000000000000000}}}, {{{0x000210b018203491,0x00081f7f56d37ef1,0x0003499eb28c2bde,0x000d16d800ddf3bd}, {0x0001a8ad11d2638e,0x00081f6ac5a19953,0x00073cbdac06d819,0x00089e5df343701d}, {0x00080e56132b9d88,0x0008f82b847a3187,0x0000000000000001,0x0000000000000000}}, {{0x000ae2fb5a3b782f,0x000dfec66b9766a4,0x0003802b7f84c2ba,0x0002adc75633f423}, {0x0009ba300fd1c729,0x000a85bdc16e7491,0x000bea7ecdc049f9,0x0008cba7fd0e8182}, {0x000a5a9aa8bce3aa,0x00008a0977d90d48,0x0000000000000000,0x0000000000000000}}}, {{{0x000ee51072d71e54,0x000e9e2a68ca9bef,0x000a9707bfc11ef4,0x000ae91635e6d8f0}, {0x000dd87435cc0e00,0x0002d6a89b217b9e,0x000c5bada1452b8b,0x000d602de29b175c}, {0x0003f43b9bd73fb3,0x0000724373642133,0x0000000000000000,0x0000000000000000}}, {{0x0002c3dc04031002,0x000c73ba54808162,0x00084fe7d46fa018,0x000e61eb44ff91a6}, {0x000448f89778fb3a,0x000d0dc5c96379eb,0x000f26ee0588d9eb,0x000aafd623f750bb}, {0x000b6e0aafb4a855,0x000ab06c0e1eab53,0x0000000000000001,0x0000000000000000}}}, {{{0x0001292993c3f0c9,0x0009243ce8e0477f,0x00002cd6d125a6a7,0x000424b8f8d2f4dd}, {0x0000e036966f98b0,0x000b28d9609c6ed4,0x0006f54dde908ae8,0x0001261395876628}, {0x0001a89f477ea392,0x000b89a6253dab22,0x0000000000000001,0x0000000000000000}}, {{0x0000776cda9e2906,0x0004dd51a83a13fd,0x00024cb69c0833d7,0x000afa9f2d0d7515}, {0x000d5068104d274c,0x000b1536c256cfc3,0x00005c2c5a3bb4ea,0x000e695b252297e0}, {0x000674ad5032178b,0x0007afaaac5118a0,0x0000000000000000,0x0000000000000000}}}, {{{0x000b5f87444140a9,0x00070937761e89c1,0x000052402d8c768e,0x000e0d8fa7063fcc}, {0x000065032ca28437,0x0000560b81d70497,0x000a63bfcc5af72e,0x0007abb68cfddac1}, {0x0007b3b85e89f391,0x000e3880d7454a25,0x0000000000000001,0x0000000000000000}}, {{0x0001d4cbebc9cca5,0x00014fe965181800,0x00064d65a9766b10,0x000646ec511b3639}, {0x000cc26e7c4e0d56,0x00094ae11adfae8d,0x0001a6886e8d406a,0x000547bbf4ad6e9a}, {0x000e8901b3004a68,0x000c8d5981c48013,0x0000000000000001,0x0000000000000000}}} }, {/* digit=79 [{1,2,3,..,}]*([2^316]*G) */ {{{0x0003223ffb7f0034,0x00056eeed01f7ec6,0x000a95759d3b10c6,0x0008fe9fc8ceacdd}, {0x00036b6ab8ec35f6,0x0008c0b21550e979,0x0008e1de4ccc3b92,0x0007fc6be17e92be}, {0x0001bdb6320828c7,0x0009d213352a78b8,0x0000000000000001,0x0000000000000000}}, {{0x0009b3c1ecfa9e13,0x000b3a0b5daa423d,0x0006bf95aa594567,0x000fbfb5a3d149d4}, {0x0003d4e9979588d0,0x0001e08ca45e636b,0x0005c358fa3b11bc,0x0003552e11b17364}, {0x000b67bc8931ab99,0x0002d3ce614c5f0d,0x0000000000000000,0x0000000000000000}}}, {{{0x000ed714844f3544,0x000cc4bb9010843a,0x000996ac0026321b,0x0003453553c74ad5}, {0x00041741982c7cb6,0x000196d8fedc48a0,0x00020d244c9f0921,0x00070a8fce97fabc}, {0x000a6d44732828d2,0x00060bcab0c77562,0x0000000000000001,0x0000000000000000}}, {{0x00061da3943969d2,0x000d674b749d7b3a,0x0009df6dae1fb5b6,0x00005c30ec275083}, {0x000ae7da1a9284fd,0x000c82a28eb7bd6d,0x000a71d66cd19bae,0x0002d599b2c6a08c}, {0x000faa1546c312c5,0x0007f06795e3065b,0x0000000000000001,0x0000000000000000}}}, {{{0x000fff9188aa7d8c,0x000deb80ad064a0a,0x0007114ab9689af5,0x000fad0b4dbde778}, {0x00055fd29cd3c099,0x000d379d42525d60,0x00016d04df50e85b,0x00053602e006dfc1}, {0x000e6c63f374d96b,0x0000f26509a7f32e,0x0000000000000000,0x0000000000000000}}, {{0x000822c176aa9790,0x000f58fc039cb1ee,0x0005872cad56c2fd,0x000e8ae0ea665324}, {0x0004daf2e64bf3b9,0x0008f96bb4b8314c,0x00090e063c57f41a,0x000d5149d3063df9}, {0x000ba61281d5f9b0,0x0004ba3d6cc9c608,0x0000000000000000,0x0000000000000000}}}, {{{0x0005d4a76da49005,0x000c3b224e91125c,0x00062ab184a74621,0x000b682a17406495}, {0x00053c3f7c8cdedf,0x0008e38d4416ae20,0x0009c28df044060d,0x000f86143e5739ed}, {0x00095f9f7f327b97,0x000872538531478b,0x0000000000000000,0x0000000000000000}}, {{0x000b98e468155010,0x0001fc05661b3943,0x0009ee23198c1bcc,0x000744fc64ff1647}, {0x000560f20d871115,0x0002c9feeacdf5ac,0x00070b263cba9c39,0x000badbac8fda72f}, {0x0001aad35365c71d,0x0002f99d51687d17,0x0000000000000000,0x0000000000000000}}}, {{{0x000acd4ec9302acf,0x00046876812a6969,0x00062f921abd47ef,0x00030834c8ee3434}, {0x00087c08c033bb79,0x000e51d0a2369c3e,0x000c1fbd98cac8fe,0x0006a309b704c675}, {0x000a173a43fcbb3c,0x00009432c4949569,0x0000000000000000,0x0000000000000000}}, {{0x0005e781f2ef36de,0x000e3479bd3a702b,0x000d74e86eb68837,0x0003849622881aa5}, {0x000ba91b89a84ecb,0x000caeee87dd2964,0x0000f40b0230b757,0x000e7853cadc83a1}, {0x0005f5ad1465657a,0x000e75100e5033e4,0x0000000000000000,0x0000000000000000}}}, {{{0x000e44f3911651e4,0x00088f7f22b492d2,0x00072f850dbf1662,0x0003ab2a45a14853}, {0x000e1480b82ee674,0x000ca609c8235a84,0x00085d8422668b9b,0x000a5d6f0bf02f4e}, {0x000afb880792321d,0x000cb82c095f0261,0x0000000000000000,0x0000000000000000}}, {{0x000bc2f5725cea9c,0x000e1f43f99381e6,0x000e6089c844a832,0x00000aa951ad7011}, {0x000282a695207656,0x00007e689c114477,0x0000e537bb9a4c6a,0x0009df06eaf0cd7b}, {0x0007c474d7895232,0x000f0710d2b00b77,0x0000000000000001,0x0000000000000000}}}, {{{0x00093c8e0aebae92,0x0001a4248ef98180,0x0005353d71384b97,0x000564228ab8dd10}, {0x000ee9e95615cf3f,0x000dbed91f163427,0x000ff8c7cd8d83e1,0x00002a117b26a05b}, {0x000d651309094b7c,0x0005fa8d73f3a728,0x0000000000000001,0x0000000000000000}}, {{0x00045cf4f3fc6c29,0x00069a5dd01b3bfb,0x000e3b24278a983b,0x000ba6e8dda15e64}, {0x0007ceabdafeb0be,0x00028dd1f4ce3cbe,0x00083c003c3a01ee,0x0004286b68f03154}, {0x0003661bd44cc13c,0x0006d7a5a2b18a65,0x0000000000000001,0x0000000000000000}}}, {{{0x000f4f2d2f859a83,0x000584cf466ff03e,0x00078dc82b847044,0x000110dcb52d320e}, {0x0007adfe140d78b5,0x000b45fd46e07b11,0x000943939af65810,0x000f26b6d5c5bda1}, {0x00091095a8309f53,0x0000d4aad23c7d80,0x0000000000000000,0x0000000000000000}}, {{0x000dd82bca9e7ca1,0x0001551ee78b6090,0x000453fc776839c5,0x0001d0262966b875}, {0x000729e2a29966bf,0x0008c49cfc825d3c,0x00009961345ab1d4,0x00007e6049f3ad60}, {0x000007da4f1b3985,0x000c382c8f36cb0b,0x0000000000000000,0x0000000000000000}}} }, {/* digit=80 [{1,2,3,..,}]*([2^320]*G) */ {{{0x000a284c690646dd,0x0003eedcd5cc91eb,0x000ea471fd6292fa,0x00023a125841cc32}, {0x0002e35810a749fb,0x00061336484e18eb,0x000b6f65228a2bfd,0x000207542e7452ca}, {0x000526cd940c7469,0x000d2936b9b32962,0x0000000000000001,0x0000000000000000}}, {{0x000573e4f063ef2a,0x000418ca996c2a17,0x00033e1f9c1c3d42,0x000b3cbf970fbd47}, {0x000088c0b1561246,0x0006e93234f08535,0x0009d7f8ff901881,0x0000aa556f8574d9}, {0x000a5d989d3b1d29,0x000ed0ab78218edd,0x0000000000000000,0x0000000000000000}}}, {{{0x000233d6557077d6,0x000f2b32cea9ff87,0x0006963e65db1454,0x000b05b7d5f2627e}, {0x0005a68cad15bd15,0x0009679cfef2c921,0x000cc1f982da4ecf,0x000673910763dd21}, {0x000110fdc3925aff,0x000a3cad0858b1ce,0x0000000000000000,0x0000000000000000}}, {{0x0000c51bfdb7b566,0x000e8b88f58f7516,0x000713a7cf39e39e,0x0004ac365af813ed}, {0x00040a788e43e8ac,0x00010b5e01e789c0,0x000ddf33d0cb49ec,0x000a3f2d9bd726fd}, {0x0006e3c30504e525,0x000e51a456acdf77,0x0000000000000000,0x0000000000000000}}}, {{{0x000707d7da6499d4,0x000c004b6d85bc23,0x0004b483dd72372e,0x000b15c9838f63c9}, {0x000dd40b6584e869,0x0005bb5ad6291644,0x00069be693ec1c90,0x0007b5c6018dc109}, {0x000c9c113b81150c,0x00040bbd460de804,0x0000000000000001,0x0000000000000000}}, {{0x000d558a1b81757d,0x00046da356589b5a,0x000f093ea9cf88e0,0x000cd54eede9de0f}, {0x0001f19ec3f8839a,0x0004ec243ffcbf45,0x000d0d1f8b02c0e4,0x000a42d2cc07981f}, {0x000363b43f4701bc,0x0007f930f2e9e43f,0x0000000000000001,0x0000000000000000}}}, {{{0x0006b0772d9f5845,0x000f28a8c7c3d700,0x000c1d96b231ba3f,0x0000f432c17a4f5f}, {0x00014ca88f653da5,0x0001ac5da9fce5ef,0x000105dd10257bb3,0x000206b910de18d3}, {0x000d121d64f95008,0x000e83748b9a298e,0x0000000000000001,0x0000000000000000}}, {{0x000dc94560ad3e4a,0x000b34cda193affe,0x000f39dff5030add,0x000d72c1a3a58a0d}, {0x0001ad7c02e84586,0x0006dddddd7190f7,0x000431dd7f7815ab,0x0001b059af2893fd}, {0x0006d66ebdb90a30,0x000ac5b55b254562,0x0000000000000001,0x0000000000000000}}}, {{{0x000a7032755a2cc5,0x00087b60173b4c02,0x000853a0c8b700e1,0x000d3fcbebfa5d41}, {0x000106636a248a74,0x000d439df17f1529,0x0001a48433bf866c,0x000ed52b92a93d36}, {0x000de5dbf96508fc,0x00064c08fb48dbcd,0x0000000000000001,0x0000000000000000}}, {{0x000e6d70757d607d,0x00099aa287bad741,0x000aca83d8bc1d01,0x000a6deb3248272c}, {0x0006281490886dee,0x00003b3e7ed5830e,0x000b8f50b5515018,0x000ee61ae410329b}, {0x000dd209b1b1ec67,0x0009f79d8f057d2a,0x0000000000000001,0x0000000000000000}}}, {{{0x0009240ac4aeeb4f,0x0009de701cba0d15,0x0001e2030d5be49e,0x000f5b9fa8d80ea6}, {0x0009e389aa0a7891,0x000f08f46a281d5c,0x0003d8942c2a6a9b,0x000dcae5c6263013}, {0x0006ed6f226d80fb,0x000e7cd744527397,0x0000000000000000,0x0000000000000000}}, {{0x00064112eebe5a16,0x0005561ba10f054b,0x000076de3983c715,0x000338a0051c721c}, {0x00017ed93ec2b1b6,0x00040d08e30b18e6,0x00086d02546a805e,0x000b289546bf39d9}, {0x00029a40d87fe36c,0x00003828ca6d96cb,0x0000000000000000,0x0000000000000000}}}, {{{0x000888aaaf08b61b,0x0004baeb89b8a3b8,0x00013c31ce0504b2,0x000084891577d88f}, {0x0001501541da01d3,0x000be18906c31edb,0x000cf8acb88a0c0f,0x000de0a54814b123}, {0x000d30b10ce17eb8,0x0003c65435ad1112,0x0000000000000001,0x0000000000000000}}, {{0x0003c3081d6e0b2e,0x000bd1198cbd6e7a,0x0009feff60218481,0x0009559a8a4e33b7}, {0x000ae242155d34dc,0x000458dbdb49b265,0x0003688660033750,0x000853753ede19c3}, {0x000b6969aac09e0c,0x000a5225b275670e,0x0000000000000001,0x0000000000000000}}}, {{{0x0004c030e13db910,0x000b8e4bb182d8fd,0x00024d5733c45ba7,0x000e09929bbae322}, {0x000c5e18395c5857,0x000beb34317a4b7e,0x00065979d2ffacfb,0x00000dac7ff47099}, {0x0002ac181634b33c,0x000b325a113dabd2,0x0000000000000000,0x0000000000000000}}, {{0x000f6d0b44a18451,0x000ebd4b60b5e31a,0x0007c6c236a60067,0x000b1be8ccf47b3d}, {0x000a21dbd1cc7199,0x0004932466e888eb,0x0001dee034c21f8b,0x000ff9da169619ff}, {0x0007e95c7e040c95,0x000b5a9dbe56efee,0x0000000000000000,0x0000000000000000}}} }, {/* digit=81 [{1,2,3,..,}]*([2^324]*G) */ {{{0x0008f08161486b22,0x000be755ab4efe68,0x00048d9609c012b1,0x00098843db068e78}, {0x0002d958488ad0fb,0x0003f6d23cff5eda,0x000c41d3ec7372a8,0x00035d185ec0b176}, {0x0006314a5925e490,0x000a3de4ff957947,0x0000000000000000,0x0000000000000000}}, {{0x00029cc94c1b43aa,0x000d43d2ad417dd5,0x000360ab4fa2dfe7,0x000e9eb552cc454d}, {0x00035a4732c24fb2,0x0008d1e843cf82a2,0x000ab8e67bb7a406,0x000191877eafbca2}, {0x000574ab099566cd,0x0009f922f9872f62,0x0000000000000000,0x0000000000000000}}}, {{{0x00085f8208bbe4fe,0x000ecc287db7bb2d,0x000e568667e702fb,0x000cbeb7a157f36d}, {0x000bf484f3352f4e,0x00058da014941bbf,0x000586c3d5fe38d5,0x000a8a8ef1b37b22}, {0x0005949627a9e7fe,0x0004740c422ebeba,0x0000000000000000,0x0000000000000000}}, {{0x000c2ec0fe63724c,0x000be0eb88269034,0x00016f607ed8c7ff,0x000b235b0a729f09}, {0x000b2fb783d219ca,0x000a1f91a0e85a3b,0x000f36eaf1659ef7,0x00023c3d4be9067e}, {0x0005e5bd92b43e99,0x0001e3e81391aa3b,0x0000000000000000,0x0000000000000000}}}, {{{0x000cdab06c0f497a,0x000ba682d62fd58a,0x000624d8816a960e,0x0006c48669b75099}, {0x0001fb169d6d2670,0x0009d5b924784941,0x000361b9811c3888,0x00005ccc21278392}, {0x000173173a0f5de5,0x000862da0030f596,0x0000000000000000,0x0000000000000000}}, {{0x000580503b5bd1a6,0x000460a53f77d734,0x0009ac0fc516703a,0x000cc1b1f0c1292d}, {0x000599d98d3204b9,0x000365fabf012bdb,0x0001f82c240390bf,0x0007f3c05cb807a9}, {0x0001aacb4486b03f,0x0002d4bf3cd7e64a,0x0000000000000000,0x0000000000000000}}}, {{{0x000cf4fb66902a59,0x0006522d970cf058,0x0008db985646108b,0x0005bd091c524ec7}, {0x0001c8ded01bac37,0x000a7571d5eaf41a,0x0003ae41513bf75c,0x0000831a58ce8343}, {0x000b5c1d0b1cbad6,0x000a127e3558b4d4,0x0000000000000001,0x0000000000000000}}, {{0x000c5bcaa2423577,0x000e95cd90416c5f,0x000f9cd3e851fd11,0x00043cec77429d71}, {0x00033818263e74b1,0x000b0bed2ab694e3,0x0009d3b078fef207,0x000322c62d90900d}, {0x00013057fb2dcc39,0x000b0aee2cd8c7f7,0x0000000000000001,0x0000000000000000}}}, {{{0x000ca837cf1af373,0x0003ae0bc7638546,0x0005fbd88b9c057e,0x0000f14623993437}, {0x000d8418b02866d1,0x000938602b2a7398,0x000d172bab8e8fb6,0x00001960cc17eb57}, {0x0000f437b4d86f8d,0x0000c3266073d8a3,0x0000000000000001,0x0000000000000000}}, {{0x000b4a64de3a3170,0x000d07d300586858,0x000590b48d2c8237,0x00064608c48f8521}, {0x00055a4fad372745,0x000ad1664c3cb9d0,0x0000e5148678bfbc,0x000ce1f67995bdb9}, {0x0000ce6b82ba0137,0x000865e65d5e9060,0x0000000000000001,0x0000000000000000}}}, {{{0x000a3697b62e274a,0x0004f036666b6cc6,0x0004615de0a77111,0x000d1a544656bc00}, {0x0004cfe1b0ffd27e,0x0007b011fe7a367a,0x000028f9395287ba,0x0000e474d2cd1539}, {0x000df81c967ab663,0x000809d416f7d850,0x0000000000000000,0x0000000000000000}}, {{0x0004ff0171522411,0x000cb614e9eb99cd,0x000efe5013168ce9,0x00000068878690dc}, {0x0003ea58b25b4f05,0x000697bfbefe708a,0x00061484cbc18871,0x000fd61b572d109e}, {0x000507a67ea6e538,0x000c108cf0642bcd,0x0000000000000000,0x0000000000000000}}}, {{{0x00073712d28f1037,0x000dcbb85bee07b2,0x0002d427b383b0b0,0x000886a4c921569c}, {0x000a22bb54a08b63,0x00016efd18019f62,0x000be30e896a901a,0x000b1c79b63790d0}, {0x0007550d4ad3f339,0x000c014ebb2a7324,0x0000000000000000,0x0000000000000000}}, {{0x0000eb80b7360646,0x0004292a8064819e,0x0001aa8d66966eba,0x000cb5433c6786ce}, {0x000c176010116f6a,0x00042b7f40b26c85,0x000bb51bb431c00e,0x00079fd699bb4a71}, {0x00083711f2c2acd8,0x0008a64b1e3905a7,0x0000000000000000,0x0000000000000000}}}, {{{0x0004f281744c4f31,0x000fb974f0427525,0x00022ee390de534c,0x000caed9f368e25e}, {0x000470d3f5a1ebc4,0x0006bb7427d70104,0x000830891f024042,0x0006993cd5f37f0d}, {0x000a9d89f4ebe578,0x000c7b2549a02c1b,0x0000000000000000,0x0000000000000000}}, {{0x0005527d2ef3c160,0x000aa733afd2d857,0x000200435a36240e,0x000dbed50df72a8e}, {0x00064e9f3dcc7104,0x00084041401f5c34,0x000b281791b398c9,0x000ad77cd49e1581}, {0x00029530ca203aa2,0x00024a7004073823,0x0000000000000000,0x0000000000000000}}} }, {/* digit=82 [{1,2,3,..,}]*([2^328]*G) */ {{{0x0004b896de83f7b2,0x000dd1b2e000727a,0x000d43d965547a68,0x000c1f1e1ce79a50}, {0x000e5ec87252c6ab,0x00060d6a5ae7160f,0x000985fdcf45caab,0x00091b3180d9d235}, {0x000646ab8f898256,0x0009f0446d6798dc,0x0000000000000000,0x0000000000000000}}, {{0x000ec719b8387586,0x0001de5f9db6636e,0x00038f4a187cc943,0x000ac366ef383b03}, {0x000022fa366743db,0x000760fac1cc0b0d,0x000265067948b1b5,0x000693934495e8d4}, {0x000c64b8f4f88921,0x0005281cd8ec2ed3,0x0000000000000001,0x0000000000000000}}}, {{{0x0008479d81fdc38a,0x00096a893e0d1c8a,0x000972cecee045ea,0x0000ed0b37445b26}, {0x000bf1c0a16a9b25,0x000509c76808e477,0x00070c4c826b6837,0x0008008a3f9fb748}, {0x00088d0f74d58040,0x00063d18d474fc4b,0x0000000000000000,0x0000000000000000}}, {{0x000a143fb2178ecd,0x000ee2726dcabd2f,0x000e017d3cb36d39,0x000d77e2d8d9e011}, {0x00069332c865043b,0x000231a13fc89650,0x000e078f7a775c43,0x0002e93c91cf1e3d}, {0x000d48604e0f7c89,0x00031d2709749250,0x0000000000000001,0x0000000000000000}}}, {{{0x0006fca2f24da625,0x000adeacc535625c,0x00020bfcd99308f2,0x000732872a2697fb}, {0x0007578b9abdd39d,0x000d7e3c3e30d29a,0x000dc63c314955de,0x0002de0cf2a14e6d}, {0x0002e4f4d6b0bbff,0x0008423dc75d4cf8,0x0000000000000001,0x0000000000000000}}, {{0x000dc6563086abd4,0x0007f2e300951d8c,0x000a989054197751,0x000a88edbb68daee}, {0x000ee17db6bcc0fa,0x000d996d71fcc36f,0x00038a1dafea4a84,0x000fc8d72ef68c32}, {0x000c6b07cf974baf,0x000b2a140ef1e1e5,0x0000000000000001,0x0000000000000000}}}, {{{0x0006034713a3e42b,0x00008cfb50e4479e,0x000f617634a25363,0x000ba17f9549272f}, {0x000163e264556302,0x000db056ef0f6ed9,0x0009449c67d2e92d,0x00027bf608bef04b}, {0x000a41494e0fd2d6,0x000ecafaa0f9ad5b,0x0000000000000001,0x0000000000000000}}, {{0x0000394a908a0374,0x0002739ed3e6c1ac,0x0002bf950e49017e,0x0006ca69441c9b0d}, {0x0003c717b7978985,0x0006f1bf123315b5,0x000d5ffc5bce1316,0x0000f7b0dacbdc85}, {0x0005306a73236570,0x0000fc22ce0f19f8,0x0000000000000000,0x0000000000000000}}}, {{{0x000a6e6af09b8eae,0x000343b43c513568,0x0003425270500040,0x000fb4508580e8a3}, {0x000b307fa3d1f99e,0x000113638a6f65cd,0x000be36db7f5ca63,0x000ede447eb7ec8b}, {0x00022e6ed48cec2c,0x0007bb1afd7c927f,0x0000000000000000,0x0000000000000000}}, {{0x000c11f9a334fdc7,0x00026ae8011e9b06,0x000ba4fc7ee152d9,0x0005ebe2d92b45f4}, {0x000643466d3d6908,0x000a09e637a743ca,0x000aba719664e4ce,0x0003162cc6d5e41c}, {0x00060cdf202e7dd3,0x000c307d09d0c5c7,0x0000000000000001,0x0000000000000000}}}, {{{0x000b621fceac0c99,0x000cd9f0c6398393,0x000246af19db94f8,0x000def03f4511189}, {0x0007e278282d9eea,0x0005d51872d67451,0x00069251c97cb275,0x000152306520f8d9}, {0x000f0746e9696ce9,0x0009ec26638c1b12,0x0000000000000000,0x0000000000000000}}, {{0x0006fbb28d6db318,0x000282f1e3fd8169,0x0001638aa745ba97,0x000741cbd6f6afe6}, {0x000674be06f9a37c,0x000f0e4d5ef37aa1,0x000c66c847151102,0x00086ff305cd0c0a}, {0x000dec0bec87dfaa,0x0006e29a33525521,0x0000000000000000,0x0000000000000000}}}, {{{0x0009e94294764d17,0x0002085b396e5ed1,0x000a114f1c4a72c2,0x0007528c8545f538}, {0x000963b0d0aaa085,0x0000ee6c82fe930c,0x0009cc321991f876,0x000bfd79b22e04e6}, {0x000e404e5103af68,0x0009a8126bf818d5,0x0000000000000000,0x0000000000000000}}, {{0x0006f18c56b9245c,0x000be8cf2d749759,0x000d0534792607af,0x000737082c9ac67b}, {0x000b81d246c242f3,0x0004a1675a873285,0x000b8be65c0f0c83,0x00031f4367aaf8a7}, {0x000eeb7fdd2c4760,0x000b71b7bc940b35,0x0000000000000000,0x0000000000000000}}}, {{{0x000e474b29bda866,0x000e2b3a2640ed4a,0x00021f91da93684d,0x0005df67424bab62}, {0x000b550d60209995,0x00096c99d55193b4,0x0003c748e9f27481,0x000631e6b3fe7e7f}, {0x000f47f4e257248f,0x000f8f56db9ba373,0x0000000000000000,0x0000000000000000}}, {{0x000bc357ebc4dd12,0x0003a33556892c48,0x000b72124cffa435,0x000e35056ea40bee}, {0x000a1b37aa3c71db,0x000ddc96c72e951c,0x000291c71de6fcaa,0x000ff88244eb58ae}, {0x00089a7bf96fd42a,0x000eb41c5d8ae97e,0x0000000000000001,0x0000000000000000}}} }, {/* digit=83 [{1,2,3,..,}]*([2^332]*G) */ {{{0x0008ac7511fc1235,0x0005af51e9a589c7,0x000c09d63e56a5f8,0x00055b518ce24a89}, {0x000a75441652a9b6,0x0004ffab489b445d,0x00071289523b0e9f,0x000290aaf7cb23e7}, {0x000c9bc7899234af,0x0001dda65dc198b5,0x0000000000000000,0x0000000000000000}}, {{0x000eeaccabd5a6f7,0x000d5900e72c44fa,0x00047a63782a2bbb,0x000393bbf531aecb}, {0x00009c7dda45067c,0x000719fa6f31630b,0x000f3a0c95e46b2e,0x0004deaf5d70f849}, {0x0007dd5d46829965,0x00096c286bc1f082,0x0000000000000001,0x0000000000000000}}}, {{{0x00012d5838ca6af1,0x000964e9241a8a04,0x00024077ab2ac6aa,0x00089da3e1536c1d}, {0x00001df56af4aad1,0x0006ef9e57fbfb6e,0x000b17f8ca8e6244,0x0009cbcb351a7c9e}, {0x00085fb54f3eda4f,0x000c296970873909,0x0000000000000000,0x0000000000000000}}, {{0x00056d8d32e5fdd1,0x0006814d7980be46,0x00065dbc6a68d7ed,0x000cebebe9b6528d}, {0x000269dfcc27d433,0x00073aec8225c88d,0x000d90643f7caaf2,0x00041c78327e8662}, {0x000763fdae4a09eb,0x000b0ead9bd2f604,0x0000000000000000,0x0000000000000000}}}, {{{0x0008f42a8c29bd6f,0x0001879cf21db610,0x000555cfe2bddcfd,0x0004d452af269c11}, {0x000fcc4011856e7b,0x000e6e45593cb7c3,0x000b215415957c0f,0x000d3b983b2c8996}, {0x00012f953be5cf31,0x000f7078abc3a003,0x0000000000000001,0x0000000000000000}}, {{0x0002c0d6b39b80ab,0x0007b2847e724ed5,0x000cfdfc83942bcb,0x000c1c0a2ddac314}, {0x0001da690e67e2aa,0x000310507c60736a,0x0008b8515f2f407e,0x000203447dd4a30b}, {0x000208fe5f3ddc7c,0x000470482e113587,0x0000000000000001,0x0000000000000000}}}, {{{0x000d7682eb5538d3,0x00058bd8734ac8b7,0x00075fcdec6d3223,0x000ffc3556d9d86e}, {0x0003a6c363b61e72,0x000d03c2ead1066f,0x00074fd7095dbd73,0x0002b42f9972cd16}, {0x00070acc2acc3e68,0x0006fd80c7114993,0x0000000000000001,0x0000000000000000}}, {{0x00049c09589c235f,0x000294e10709485a,0x000e55bcaedd0d2a,0x00084da3a073e38c}, {0x0004725346561d28,0x000ed8195e95d347,0x00001ec990b2c19b,0x000817664aecefe7}, {0x0005f12464c59ce8,0x000f85a23cc1c6cb,0x0000000000000000,0x0000000000000000}}}, {{{0x000fb48cd5b9dd85,0x000ea5640b16ec8e,0x0004991733d00d1c,0x000e2230142b823b}, {0x000d1646ff2bfccb,0x000e87a4efbbe898,0x0007933417bfbbcd,0x0002ac0c744278e4}, {0x00079c8483d8b4b3,0x000fafae62ecea8b,0x0000000000000001,0x0000000000000000}}, {{0x00063d47c065003b,0x0004185cb3cef55d,0x000bfcfe8d3872f3,0x0009112c490c5e61}, {0x0003b1e7d4274313,0x000517366c9c6308,0x000bc9bb53389bc7,0x00025afa81750fe0}, {0x000afda6e1b71dc2,0x000c6a9aba51c85b,0x0000000000000000,0x0000000000000000}}}, {{{0x00000e070af57b1c,0x000441246548fb7a,0x000c563ead66464d,0x0007508f0851b47e}, {0x000f31999ecfeae6,0x000f85797a3840b6,0x000c74080d60c378,0x000f3eaf1e242bf3}, {0x00003ca35d886cbe,0x00022754c9a357ba,0x0000000000000000,0x0000000000000000}}, {{0x000982d0aaae9f75,0x000176d1b4b6ca3d,0x0007980f7d421826,0x000979133a61fcc4}, {0x000cb63f41cac3bc,0x00079bb4b9516419,0x00033cd18a279569,0x00075e18895b57d5}, {0x00063599127b0d23,0x00063dbbded01670,0x0000000000000000,0x0000000000000000}}}, {{{0x000342ad817f361c,0x000cb1bd9eb81b06,0x000c7b97a0843c43,0x00083f804f029e13}, {0x000b3486644af0ff,0x0002a64dc632346d,0x0002a39cc0dcbed6,0x00056457b2ff9c5a}, {0x0000fe8536001cce,0x000def7d14af048a,0x0000000000000000,0x0000000000000000}}, {{0x0006c4115861eef1,0x0006a14bad6b1ac1,0x0005dee3e9d201f9,0x0002b396cf147ed1}, {0x000f4643f8a21b3b,0x0004c9915584149b,0x000a893cfd7ba449,0x00027a8a4eb7aef9}, {0x000cc4fa992b1d31,0x000eec6c99a8fa7f,0x0000000000000001,0x0000000000000000}}}, {{{0x000a8d985f7ab9a0,0x000b7d39a70c2f72,0x000f6f8acabea7d5,0x00095d0273f642dc}, {0x0007d8a54bc56deb,0x000a63f1883f3cc3,0x0004b831ef1bba05,0x0008e112f14c8c07}, {0x00089737917f937a,0x0004874d335ca229,0x0000000000000000,0x0000000000000000}}, {{0x0008374f770af11f,0x000cad8ee96d7e99,0x000bff9e11a7d432,0x00056384e6665366}, {0x0004a9b692423f6d,0x00075f044efc7e34,0x000ee60ee1b3dddf,0x00039cd00df7a827}, {0x000529eb5b2612c9,0x000cd7c4ffa6a13d,0x0000000000000000,0x0000000000000000}}} }, {/* digit=84 [{1,2,3,..,}]*([2^336]*G) */ {{{0x000c16671a6774f1,0x000af03753ce5839,0x00054c5f8c07356f,0x0001afc71165a356}, {0x000f9d6adf86cf5c,0x000a6b4966903b89,0x0009f4ebff86c3fb,0x0004a87b0151b151}, {0x000efd27bbe4f95b,0x000b040513d26385,0x0000000000000000,0x0000000000000000}}, {{0x000622a63fa5d90d,0x0008d92aca99c7d4,0x0001d6acf3aa6efd,0x0001b7387e55d6dd}, {0x00010db119c2295a,0x00011a67dad9703d,0x000eedb427c0f52d,0x0001e055192fe412}, {0x0004a5758174c7a3,0x00055cfd4b1dde40,0x0000000000000000,0x0000000000000000}}}, {{{0x0000d119f7fe9853,0x000fe49990254b37,0x0008a86cb40764d3,0x000820af39be0e2c}, {0x00027458321b04b9,0x000c2ba583294752,0x000ae89a07a5c7f2,0x0008fa6d520652e9}, {0x0005604c9bdc0eee,0x0000c06f2e484243,0x0000000000000000,0x0000000000000000}}, {{0x00014a30a2bfa81c,0x000cbd6640003017,0x000ab87a938a3f37,0x000e1c91f3132874}, {0x000e57e9d7ac6ecb,0x000e33fb881734fa,0x000073b600765b07,0x0009428cbfb5edfc}, {0x00029028585e9a20,0x0001e077ef7692bd,0x0000000000000000,0x0000000000000000}}}, {{{0x000cf34a0d6f6ffe,0x000370c22b280291,0x000e87a26b1fd975,0x0008088a662b3666}, {0x000eea746601046d,0x0008edbdfb0988f2,0x000f2131f7fc1ebd,0x0009266b6d41f4b2}, {0x0003c1c020089694,0x000be27c849de8c8,0x0000000000000000,0x0000000000000000}}, {{0x000bcda37f3a594e,0x000726480ec74a90,0x00026216e2ddde9d,0x00064b02bef16495}, {0x000aafba3c749a5c,0x000a872930c3f630,0x000654a8695df3be,0x000cb5372491b21d}, {0x00017f3b3a2f3f6f,0x00094613fe01cfe9,0x0000000000000000,0x0000000000000000}}}, {{{0x0008937b47b39090,0x000415bb7112fdec,0x00066e9e19d3ed5a,0x0006597801eab0fa}, {0x0005e740c409bbbe,0x000050b19bba9267,0x000df2c3e8b56daa,0x00012fbcf099e6ee}, {0x000195262a55e069,0x000ee2f2c7d1e980,0x0000000000000001,0x0000000000000000}}, {{0x000c1384c013e53c,0x00074951ffea5bee,0x000d0ad477deaca6,0x0004ee3245756473}, {0x00030808642161fd,0x00050c8b97a30694,0x000340f405f653b8,0x000d5a543cae9de4}, {0x00031ca24347d550,0x00092a75f4312ea3,0x0000000000000001,0x0000000000000000}}}, {{{0x000c8162c746ef6f,0x000f6715dbf9ea58,0x0005523d8217dd87,0x0000b2c52bc5b0b4}, {0x0005db8903ecd878,0x0004296f75f92e78,0x0003c6e6397e4045,0x000e84bad1cccce3}, {0x000b82162d3c5f54,0x00009333f935ae95,0x0000000000000001,0x0000000000000000}}, {{0x0004ff1c33e26a2e,0x000785b4ec10e1f5,0x000a1634274c2886,0x000b5d5ee5822d49}, {0x0002fbe9122e0bfa,0x00003c2cc2955a06,0x000e08e579ad9b7f,0x0001dd6ee255f2e5}, {0x0004f08f71b65e70,0x000c9dcd7d23cb93,0x0000000000000000,0x0000000000000000}}}, {{{0x000927819d85c389,0x00088dd986cf5001,0x000eb6ebdddab174,0x000a1e388628281f}, {0x000014511bc0392f,0x000b79c2a5e1691b,0x000d866b842f8440,0x0000343c71a48805}, {0x0002ac5c5d5d795d,0x0004aaedd8558804,0x0000000000000000,0x0000000000000000}}, {{0x000896067875f110,0x00080b0d43dab8fa,0x0009a3104ecd6f15,0x00017c31840b3b59}, {0x0007841201091767,0x0008de871b2243eb,0x0003f7be2323a388,0x000f764799c353ac}, {0x0009d244edaf476f,0x000513c595b87c99,0x0000000000000001,0x0000000000000000}}}, {{{0x000800832e6fdb7c,0x000df2ceb7712003,0x000625cbf7ec3398,0x0007b9eb4c74b442}, {0x00090424f2515df6,0x000abc10516b9778,0x0005df82462b4902,0x000a6d60d9807c8f}, {0x000606aee1bb838c,0x00030e1e7a2ff1ff,0x0000000000000000,0x0000000000000000}}, {{0x0008fce9b8ce853f,0x000b7049a4c20923,0x000ae2b39f773f7b,0x0002f55bcfbf4b1e}, {0x000b07309ae9653e,0x000cf869d6026775,0x00099fe1b0e83daf,0x000202f8a21d72ed}, {0x00037619de81bf7a,0x000b7b2bf238b7d7,0x0000000000000000,0x0000000000000000}}}, {{{0x0008ca9dd54298a1,0x0000e1308270c47f,0x0002be3ff9743378,0x000471b0b186cdf8}, {0x000b1747ce696eb6,0x00015fe31005f60a,0x000ac1b5a457da88,0x000f4901af0f6bb9}, {0x0002f972c925bd14,0x000186acd8b58a65,0x0000000000000001,0x0000000000000000}}, {{0x0000f355372184c6,0x0005e1f7ba0c693e,0x0005b11db3d6dbda,0x00051b89e46fae1c}, {0x000c97c0b46b0f1f,0x000cc037caa48d5e,0x0000355bdcc75991,0x000f28784dc0e5f4}, {0x000837eadd1a3fa4,0x0009eeb5a1926d0b,0x0000000000000000,0x0000000000000000}}} }, {/* digit=85 [{1,2,3,..,}]*([2^340]*G) */ {{{0x000847fc397e26dd,0x000de02cc0ff17de,0x00063e6fe388ee8b,0x0001e73a774123d0}, {0x000daf8cb9f5597b,0x000b938535ee20c8,0x0000d7da8b1bfac8,0x0008e2a819363df1}, {0x00079861ae7d4273,0x00003eaf0a677999,0x0000000000000000,0x0000000000000000}}, {{0x000611141de00c8a,0x0001d2aefc5b58bb,0x00033633ce29b3d9,0x0004bfef0d5e3306}, {0x000d78956c10a254,0x000fa84101beaa2d,0x000f9588ba22402c,0x000e0df8f46296a5}, {0x000c7018734ace12,0x000ca8e0e00d25c6,0x0000000000000000,0x0000000000000000}}}, {{{0x000c26d9a28cda66,0x000ac34788e2808c,0x000a2e3c895ddb52,0x00092cc3305bc55d}, {0x00086ee8076376e7,0x000da2d9cb5f9d99,0x000f0d8aea185a30,0x00068ef462b956f8}, {0x0000f61c2096bebd,0x00044e7be11b5930,0x0000000000000000,0x0000000000000000}}, {{0x000ea58bb15fdd13,0x000d5b2585fb779d,0x000d75c3d978271c,0x000e827a5ac1a4b5}, {0x0006c6fe4d4804ee,0x000f66c09f0147df,0x000b3203f6a4c217,0x00081eeb950292c3}, {0x000da3f441776841,0x00071712f688beeb,0x0000000000000000,0x0000000000000000}}}, {{{0x0004586de8027c8d,0x0003b7dc25b073ea,0x00049b36fccf2477,0x000032458466e794}, {0x0006f36f854043cc,0x00051e24c902d71d,0x000ec681a81ea4c2,0x00060e710d119e39}, {0x000dfa8e50e27e69,0x000bc96885ae0f44,0x0000000000000001,0x0000000000000000}}, {{0x00072cc7ee3e54e0,0x000e54b8224b0f78,0x000e5d4bd3db5696,0x000d27cc64ead37d}, {0x0009b5b2f36d2cba,0x00021210e2a45e52,0x0002c8d788fbf745,0x000440c5440be1bd}, {0x000157b392b99018,0x00045deeecc510bc,0x0000000000000001,0x0000000000000000}}}, {{{0x0001f34441941c1e,0x000786af242ed224,0x00082ffb7bd73f71,0x00040040ee8f684b}, {0x0000b0e0a77660b9,0x00055090773cb918,0x0003b4341ff934d0,0x000efe154397d7e6}, {0x000566086597b1f2,0x00038e115dad8d73,0x0000000000000001,0x0000000000000000}}, {{0x000320279e97eed7,0x00092b44ad3c59a0,0x0009546c02d95d0b,0x000317d617644016}, {0x000b3b1278de80cf,0x000150eec20cc035,0x0004047a454911ca,0x000eb15350f140f3}, {0x000297dd664a854c,0x000c1545fd389a24,0x0000000000000000,0x0000000000000000}}}, {{{0x00054c6d42f4ddeb,0x0001a5d46442b31b,0x0008eb97dd3c9497,0x000f35259e3e1ff6}, {0x00049058db0b2e2d,0x0006968077e0b694,0x000456e4ea6ec9f4,0x00098457796aba76}, {0x0005412cc7718336,0x000c5eb4e4306f25,0x0000000000000000,0x0000000000000000}}, {{0x000f4a91bf2060dc,0x000e9a57dadc33ce,0x00051f56adeb934d,0x000b29d22e8fe341}, {0x0000f85723b5e49a,0x000ee66b41fabf52,0x0005253bffe67611,0x000c50202f550a60}, {0x0006d250b9e49468,0x0001a2956ea13fef,0x0000000000000000,0x0000000000000000}}}, {{{0x0000dc097ea2b524,0x000c5eb5323240e3,0x000082d33c53dd49,0x000c5d6917c692b6}, {0x000337e9d695a12b,0x00078372d602c7fd,0x000ef2985e92117b,0x0008ceacebcbefa0}, {0x00068cc3e9b4e8e1,0x000db3e3e50ee13d,0x0000000000000000,0x0000000000000000}}, {{0x000980bec0d2f5e3,0x000eaa9b062f585f,0x00083ee3b5103eda,0x000605534f1f8028}, {0x000add292d29ee4a,0x000f9ba28df95f8d,0x000d134fb5785f57,0x000f0fe162fe54b8}, {0x00047f0902bd8287,0x000de3769ce1a122,0x0000000000000000,0x0000000000000000}}}, {{{0x0006e3d538c32c91,0x000eb774341e7141,0x0009e6b225ba2b4e,0x000824dcff742236}, {0x0004d5e3b9c67d3c,0x0006e4276dd54722,0x0001d2dcc105d46c,0x000392da4b3a8a00}, {0x000e2f3953b25248,0x0002fecbb5174b67,0x0000000000000000,0x0000000000000000}}, {{0x00008d720508826b,0x000b9b4e2e807123,0x0001bf6b1169562d,0x0006d2acb14e6841}, {0x0008cbfd3257245f,0x000189ac1c8cdf45,0x000ee493f894fd3e,0x000fa59cbf0ab5d6}, {0x000476d8e672a0c8,0x000ed9fbb78753d8,0x0000000000000000,0x0000000000000000}}}, {{{0x00039334c1cd9788,0x0008ab0560e3e74e,0x000fa2ff6e2c62b5,0x000acd7d25b0cfee}, {0x000c456f469aee3d,0x000a862fad6476d0,0x000688f0d8d2340a,0x000b648a9494468a}, {0x000f4ed209d4d2fe,0x0008a93e7c5890e9,0x0000000000000001,0x0000000000000000}}, {{0x000cdd07e3f60721,0x0002466078437612,0x000ea1835868d6d1,0x0005ba6a85400753}, {0x000f7f252808d5c3,0x0007b45d6857ba4d,0x000d683048ddde70,0x000c759393e38c60}, {0x0000c630e919b183,0x0007209017172576,0x0000000000000000,0x0000000000000000}}} }, {/* digit=86 [{1,2,3,..,}]*([2^344]*G) */ {{{0x00060ead50b81885,0x000bcef73cb6f0c1,0x00053fb7eb3e2cd2,0x00062b319bb7bc05}, {0x000a38a471706b6b,0x00046c6b42daf298,0x00005e59d404cf98,0x00048fac2e73085e}, {0x000ff0af6c53893b,0x000de9e3d8eea7a8,0x0000000000000001,0x0000000000000000}}, {{0x00034470acd5b055,0x0000c4c1af94ede9,0x0004fba6b3889b3f,0x00023ee49af80496}, {0x000f0d89fd53a3e4,0x00053cc302793fad,0x000b36dcd463b613,0x0003782e102e51fb}, {0x000c63732d6d1c6c,0x00059dc97f604bbb,0x0000000000000001,0x0000000000000000}}}, {{{0x000db31484a7e177,0x0001740a1bc3a05f,0x000c265e95ebda07,0x000546d643b1d3c4}, {0x000c2611b9709edc,0x00015784fc807b04,0x000e5bd473ceec4e,0x0003c97fb33e58af}, {0x000d6d5327b94dc5,0x00062a914fc6dc39,0x0000000000000000,0x0000000000000000}}, {{0x000cbcf73d880ddb,0x000029df80627a67,0x00091ccf95a67d3e,0x000ec7aefd91b52d}, {0x0003aa855273ca53,0x0007213a95113157,0x000b98a49db550c0,0x000b470643affa5f}, {0x000f0628a0fa67f5,0x000d2cf906186e6b,0x0000000000000000,0x0000000000000000}}}, {{{0x00039cff07a9f5bc,0x000b27814ba6cdbc,0x0008da0e67469efd,0x0004ccf0a198fcd4}, {0x000cbf71a6e5b71a,0x000500eabe51b9c8,0x0007908463c5cf80,0x0004962539aa0260}, {0x0001de61db956e33,0x0004f9e2c1ac338f,0x0000000000000000,0x0000000000000000}}, {{0x0005f37dc080da53,0x000c1c2a74369386,0x000025722593f4e4,0x000a4e09b626a8d5}, {0x0004b1e7f8c96db6,0x0002c5a75c187079,0x000cb91e644a3045,0x00024e7eb18af641}, {0x000fb48086d9cefa,0x000b4dd6532fa3f7,0x0000000000000001,0x0000000000000000}}}, {{{0x0001be067e3e2f37,0x0007737f152d2c7f,0x000242f8dec8659f,0x000c7d958df47d63}, {0x0001b91c63b0acba,0x000c2c6ad3f62088,0x00099adda54c0028,0x000a3012f6937019}, {0x00014f4c499516f6,0x000da068d44cb73c,0x0000000000000001,0x0000000000000000}}, {{0x000209ec58d1b414,0x0008e876dcc7401d,0x0009323106751dc5,0x000f75f24e14fe98}, {0x000ac88f5086e5a4,0x000294dbdb4ccd6a,0x000be99edf86543f,0x0003767f48ab30e3}, {0x0007667c622dcd0b,0x000d7fd6615681d8,0x0000000000000001,0x0000000000000000}}}, {{{0x0008c453ac10be58,0x0006d75a48dfcf2c,0x000c4944bc5042f3,0x000e7ad5c9cee1eb}, {0x000996c45d109bc9,0x000689f02d424fbf,0x00023528e926c326,0x000e84ac793d58e5}, {0x0008eeaddb5a4ed0,0x0005d31f9ea2560c,0x0000000000000000,0x0000000000000000}}, {{0x0007ba171a6ebc35,0x000d39e242ba28da,0x0000694f0cc97464,0x000d7fb496b0d2fb}, {0x000d7e1b5b66b3d8,0x00001db81788dc1a,0x0003854dd5fe4e9e,0x000f9965063e6021}, {0x0003751c74ab4631,0x00006945420e7941,0x0000000000000001,0x0000000000000000}}}, {{{0x0005b110bb6dcc9c,0x000e9d1e6c13e60d,0x00058585159a0842,0x000b46fe443356f4}, {0x000853b25c086265,0x000ebbff20877291,0x000136ec71c4d1d0,0x00003ebeca5e79c2}, {0x000a0af3b3a96ed2,0x000f93012e330a32,0x0000000000000001,0x0000000000000000}}, {{0x00017ed67dacd4b6,0x000ceade583a567d,0x000316840b4e5703,0x000c414303d396ce}, {0x000ed6970ea480cf,0x00063761b9b1974c,0x000788f3de4383da,0x000ad07d6726e400}, {0x0003056bda545993,0x000385d3fe822ea3,0x0000000000000000,0x0000000000000000}}}, {{{0x000285c58225166f,0x00072d2451ec99f6,0x0005efbddf5101b0,0x000dbc066e055890}, {0x0002c29985ac7cd6,0x000f1839b6caca94,0x00093cafd8d9c1ce,0x000b177ba7911d6a}, {0x00098fc762e30d5d,0x00067686b89a78b5,0x0000000000000001,0x0000000000000000}}, {{0x000dff4557a32b93,0x00037e16c6af191e,0x0007ad7362550f1a,0x000983cb772b5537}, {0x000b0746f50f2068,0x000dbb42f7ee6b8c,0x000f0cdda882070d,0x000a732384a13e83}, {0x00055b3be67dc4f2,0x0003cf20d84f4cbc,0x0000000000000001,0x0000000000000000}}}, {{{0x00007348004e40c0,0x000448f78fb0602f,0x000c2ac8aebb2604,0x00064b78277ca03f}, {0x000eb2c6f473d278,0x000cb793a9eb1664,0x000e2b358eee9a37,0x000194f18cbc9c2c}, {0x000f6078bc87a3dc,0x0006220e93cd112d,0x0000000000000001,0x0000000000000000}}, {{0x000d1ed5d96d6d2f,0x000b72be10752f3f,0x000d1e476660c38f,0x000b1d6d9b093c35}, {0x00026d898dff773a,0x0004b445df00e4cf,0x000d1ce422c1136c,0x000db6e821b59ee0}, {0x000de6252e82511e,0x0002f481c804e41a,0x0000000000000000,0x0000000000000000}}} }, {/* digit=87 [{1,2,3,..,}]*([2^348]*G) */ {{{0x000d7989af2b44ed,0x0006f91b1a9086f8,0x0002b4d5672b30f1,0x00072009919c3dae}, {0x000003b6ec0a964f,0x00012b7f4f64ce56,0x00076bfe0f0d4fbc,0x00043eb40f821444}, {0x000cbb4480332a8a,0x000f3ff375566080,0x0000000000000001,0x0000000000000000}}, {{0x00018caf35e5d712,0x0009aba53d6591e5,0x0004f1b1b50e170d,0x000f9eca3e56ed3e}, {0x000288dfe4cc67c4,0x00059c7726fa0dd0,0x000a0660a01f234a,0x000a704007db6c8f}, {0x00070b32e8366767,0x00096994810fb845,0x0000000000000000,0x0000000000000000}}}, {{{0x00092a1897b4c0b5,0x0009027fe35612df,0x000a5105c7f9f97d,0x00021853ba021326}, {0x0005dd2cadb219c5,0x0003ab9d259b3ed4,0x000857fddadc1ebb,0x0004addab0607b4a}, {0x000ff916fbbc92a3,0x000721ee7e6c527d,0x0000000000000001,0x0000000000000000}}, {{0x000ba1dabc6f5958,0x0000087b0e564aa3,0x000b9c963dd27f6c,0x00028eca3c030970}, {0x000c23cd7a457768,0x00017b833d0834d3,0x000be25f44c50d54,0x000a153d4a6bf0d8}, {0x000e9c71da49590e,0x000d43f3a30dc247,0x0000000000000001,0x0000000000000000}}}, {{{0x0009bd585a57c01e,0x000ee844d7078c7b,0x0006c16cb258be3e,0x000a3282f9caf55b}, {0x000e08d004fc2ebd,0x0009db3ca2d054d0,0x000ff89010ddde2b,0x0006615b9b156d6c}, {0x00000ee87cbb5e96,0x0000965826673f04,0x0000000000000000,0x0000000000000000}}, {{0x0005c973c58e4e2f,0x000bfed17990af45,0x000982806a235d03,0x0003a7e6203578b6}, {0x0002679d20d4837e,0x000fa09a67212915,0x0001e993e548aecf,0x000034e7752d33de}, {0x0008c0133b8d99be,0x0005d644443ed88b,0x0000000000000001,0x0000000000000000}}}, {{{0x0005d09795891669,0x00055ce0c6b8f799,0x000cdfa7a67baad2,0x0009a5462a84102f}, {0x000ca5fff322b2ed,0x00016895f0238b4c,0x000e1fc27a1fc8f3,0x0007399300db4369}, {0x00016f718708ed71,0x000aa4931503fe5f,0x0000000000000001,0x0000000000000000}}, {{0x00040da9e1ff0c6b,0x00022af9967269a0,0x0005871908b86944,0x000801c88350fa73}, {0x000f680cd1b5d61c,0x000f0b415826cc63,0x0008b363474f5f7a,0x00027800e5401e93}, {0x0002305262f20f7f,0x0005e6d27bb44c56,0x0000000000000000,0x0000000000000000}}}, {{{0x000dab714dbca0be,0x000450d634bc786d,0x000d2802c42f3afb,0x000ef6e542d9994d}, {0x000946669336b0ea,0x0006a8fe65059b68,0x000f702cce1812e5,0x00030e3c70e359c5}, {0x0009fd5b9f2069d5,0x000093f3f0186d75,0x0000000000000001,0x0000000000000000}}, {{0x0006d10e2b40858b,0x000a417e22a4fbc2,0x00013ba0de831401,0x000d41a31a86b763}, {0x000893ad0b78b7c2,0x000aacf20f1564cd,0x000bac0041297947,0x0004ac69dc2da24d}, {0x000ba071987933c2,0x0007176068dfbd75,0x0000000000000000,0x0000000000000000}}}, {{{0x000c8b4eb4601064,0x00099a991f16e053,0x0005bcf58e425bfa,0x000b1e6fefc21bff}, {0x0005da04d7e97cf6,0x0003f93bddaedacc,0x000336130ff2741f,0x00028f428d033ae2}, {0x000b98d58f0cc054,0x000281be6796c6ea,0x0000000000000001,0x0000000000000000}}, {{0x000562d3cd261bc6,0x000c4e652831be2e,0x0007f84fc06f2ac2,0x000b078d9ca13774}, {0x000d2b248e882f5c,0x0006981dfa0231e8,0x0005f7dcfabfd673,0x000f3658f51759de}, {0x000d6a68de41452d,0x00038358c049f993,0x0000000000000000,0x0000000000000000}}}, {{{0x000dba36a11f468b,0x000ddefecb4596c7,0x00004044ba328343,0x000e3d89658e943c}, {0x000955f5e1aeb372,0x00008650d658c0f4,0x0004309aed6ff5c1,0x0000ad875f7bb480}, {0x000c35156e670707,0x00066875cf1c6033,0x0000000000000000,0x0000000000000000}}, {{0x000bceb289713705,0x000a8a9a03fa8061,0x000cac052e91978c,0x000b61eb6bb99c20}, {0x000e50fb8f33460f,0x000ec61a887398ae,0x0007437f45e3c633,0x000fcf4c74c22971}, {0x0004691a2d9b4866,0x0009004647f4a64b,0x0000000000000000,0x0000000000000000}}}, {{{0x0004f3cfa7e54e73,0x00076a7075c33047,0x000b446bdd4b3ee5,0x0003371a1b7efe90}, {0x00013826a3c98a14,0x000412cdba45fcf1,0x00048a44b5601caa,0x000206ebe3f76143}, {0x00050e4439f111b6,0x0008451f6bb4a9d7,0x0000000000000000,0x0000000000000000}}, {{0x000c0d59b5f2d48b,0x00029bcb29ae2863,0x0003a9a3c78e216b,0x0007856c2465c5b5}, {0x0004736d155fd956,0x0001ce6b07dfbfe0,0x0008361c3a4fa43a,0x000d0e9f03c0f19b}, {0x000e803f9b21f548,0x0002f885460ccb9d,0x0000000000000001,0x0000000000000000}}} }, {/* digit=88 [{1,2,3,..,}]*([2^352]*G) */ {{{0x0006b287cbed671f,0x00071c978130d6d2,0x0007aadd881d433a,0x0004f45fb4ad7bb1}, {0x000d7b1940d6b52e,0x0002d44569722e2b,0x000de70f91dc84e7,0x000ed42546436d3f}, {0x00047e41abd1bc41,0x00010f544a7be2b8,0x0000000000000000,0x0000000000000000}}, {{0x000e82545325818a,0x0003cf3d8e5d2be2,0x0005f30317d1c986,0x00015ce098fb8ec2}, {0x000158947db8581f,0x00055d8793f3e6c3,0x000f50843a7feb50,0x0008ac153d3d8417}, {0x0004329e7248bbc3,0x000d2ffcfbcb0366,0x0000000000000000,0x0000000000000000}}}, {{{0x000b91e88872c802,0x0009859329a6f390,0x000332091e85e0fd,0x000d0a1fc7233994}, {0x000c07172741e069,0x000870fafc953488,0x000d8073b040fb91,0x00089e841e1bbb2f}, {0x000f582161687272,0x0007bfa72dc0f548,0x0000000000000001,0x0000000000000000}}, {{0x000c2f4044695d52,0x000e9fc898f3ae4e,0x000d6d16346893df,0x000cc356cfc2a2d6}, {0x0008f9780e14adcf,0x00040c34a952a0f5,0x000bf1f1f74017fe,0x000ae85cc7e49637}, {0x0002400547db8273,0x000eafd4e119d7f7,0x0000000000000000,0x0000000000000000}}}, {{{0x000a5355afe08a2e,0x000687a2f29baf29,0x000653058a23e11c,0x000110b2ab5abb63}, {0x000e4ead1d1b9533,0x0005d1b7b6254324,0x00074059ad5a8616,0x00090712ab62d100}, {0x000e9d5016f88f2a,0x000afeefd62c6b78,0x0000000000000000,0x0000000000000000}}, {{0x000d2d42ce0d173b,0x0009198d15289e62,0x0004baf7b535d68b,0x0008566e4a9af773}, {0x000402c278158bfd,0x000603f6310f0f5b,0x000331a366d639ea,0x0007457655beed79}, {0x0004b46175b5f4bc,0x00048f6ced012274,0x0000000000000001,0x0000000000000000}}}, {{{0x000b20efdb706d0d,0x000c40117c40b081,0x0000a6d9c2aec008,0x0004d3e0693270e3}, {0x000674266a5ea611,0x0001ebf62144a6af,0x0003d45ee3917e38,0x0008c35ff5d67fca}, {0x0006e79dba352604,0x00081a7e7bfed40f,0x0000000000000000,0x0000000000000000}}, {{0x00006eb8dc692380,0x000fe33343c5a20c,0x0003e67d0a53418c,0x0008959e15eb001a}, {0x000ac0ead5e7c7e4,0x0002e4162f0962e6,0x00017bb3e28513c3,0x0004317568fafb81}, {0x000912ceb3a2e303,0x000102559381740c,0x0000000000000001,0x0000000000000000}}}, {{{0x0005f372c77f1047,0x000b3d958eb7b744,0x00069ac2a8ab1157,0x00057d2ec5015809}, {0x0007f4db5c158ff6,0x000e3fc15a71737f,0x00048e949735c5de,0x0003845758233ed6}, {0x000e91137608f198,0x000720cc72b9199c,0x0000000000000000,0x0000000000000000}}, {{0x000b050528cb006d,0x000ac29d53a71cfd,0x0009a1f2ad6eb262,0x0006c829676f56dc}, {0x0003dd6ddbfb591a,0x000c61cac801979f,0x00031b13cd6cc83a,0x0003cf1a5e5c85bc}, {0x0007cff1f95623b3,0x0004f7b2cd595d6e,0x0000000000000001,0x0000000000000000}}}, {{{0x000699fc8b3dab7b,0x000229f393f97b3f,0x000012376dbad08a,0x00038a797638cccb}, {0x0006110a40e7e328,0x000e3d1acf08dea4,0x00003f85adfc07de,0x000fffa8d9d37eb4}, {0x000db3ca114eff2b,0x000b41dd72c79e23,0x0000000000000001,0x0000000000000000}}, {{0x000822fbbe3ad3af,0x000ddd71461cfcd7,0x000d3d8f03aedaa8,0x000f069c35282be1}, {0x0009283f776eb004,0x000746b05b9838ad,0x0002fcc85c205f31,0x000bd9143e61b0eb}, {0x0004e7f4435b3321,0x000a673088e100ce,0x0000000000000001,0x0000000000000000}}}, {{{0x00052e132b686982,0x000419eaf166734f,0x000edb4ffc59ba11,0x0004fda13f9e0e45}, {0x0000c12226a0efde,0x00070adf716ee2a5,0x000402012f467257,0x000f2ecf2b32d94e}, {0x000205b1386ade63,0x000b3bc779c31b50,0x0000000000000001,0x0000000000000000}}, {{0x000cbbdbe0875f47,0x000a208dcda3e65d,0x00048b61b40cb945,0x0002b16480725e0f}, {0x000aa186079b7359,0x0007e306ab144462,0x0004b09effdc0e10,0x000a76ab4395ae17}, {0x0008c3ddeeefeec9,0x000216cdb5d669d6,0x0000000000000001,0x0000000000000000}}}, {{{0x000c70f6d4b2fef7,0x000c0c92ef06acfe,0x000790f3344c38aa,0x0000fed753c30edf}, {0x0003dfc8006501b4,0x000df722f2f6da80,0x000c340284a42e2f,0x0002a0f154005cec}, {0x00082f0dfb36ac65,0x0007bed1506b21ef,0x0000000000000000,0x0000000000000000}}, {{0x000d76b785906061,0x000edca1c3d7b884,0x000307e9a89c6050,0x000e0ccc1519baa6}, {0x000663495eff88c7,0x000a17475b22e916,0x000c39e69639f1ce,0x000b1f0e827f8c53}, {0x000066355ede8121,0x000d5b91249281eb,0x0000000000000000,0x0000000000000000}}} }, {/* digit=89 [{1,2,3,..,}]*([2^356]*G) */ {{{0x000ccccf35a37229,0x000465167517203a,0x0001bf938eaa2ac7,0x000d73d683a983dd}, {0x0007f598a6f1db73,0x000235f9ed630b4f,0x000f332db784cb56,0x0003b330540f52bd}, {0x0005843b0221e5e8,0x00044a09499b4ec2,0x0000000000000000,0x0000000000000000}}, {{0x0000fb3cab0a1b02,0x0008968b6e52dc01,0x00022c046dc60a24,0x000695beae1e187a}, {0x000d3006acf49482,0x000960f10535934b,0x000df011e1d0143b,0x00085de371d84cfd}, {0x00082841456c439e,0x000585582ff3b564,0x0000000000000001,0x0000000000000000}}}, {{{0x000e94ac6fbf17fb,0x00044289803b61bc,0x0002e798f31e8afe,0x0005e43d9a42f37b}, {0x000f377aef7a7947,0x00003a6947a8f685,0x000c1b4969c3b8c2,0x000b9c542cdbdf0d}, {0x000501682c76bc8f,0x0006972a768660ff,0x0000000000000000,0x0000000000000000}}, {{0x000f9daec5f3009b,0x000325c4a46652c8,0x000b09499ac89b1c,0x0003ccd5721c0cae}, {0x00098da46e3445e6,0x0002db691caca0b9,0x000845a793a1fc73,0x000ad927f614049e}, {0x000024bf07aea310,0x0007245359be8b80,0x0000000000000001,0x0000000000000000}}}, {{{0x0000db1596cc9e80,0x0009a231d0f49f13,0x000f1d499d6bd9c7,0x000757ac7ea9b7cf}, {0x0005305a4d545367,0x000f2c85480a42a4,0x00029efd461a5b51,0x000fe691c9e6b8ed}, {0x00090ea1ca549541,0x00058f09c0153e64,0x0000000000000000,0x0000000000000000}}, {{0x000525f593f9a0ed,0x000edbc140a1f67f,0x000f5bef166a98aa,0x0007a559750be5c2}, {0x000fb8cba58b2d45,0x00014d93d0c5d96c,0x000723470bfa2f95,0x0004f6b79058b86d}, {0x000d58f11a8a7858,0x000fe32b2d0ad418,0x0000000000000001,0x0000000000000000}}}, {{{0x00016f6d1a0d42ca,0x0000a7c2c062afb4,0x0001630676c3dacb,0x000c297ad74ee6b3}, {0x000d18f736e4995f,0x00064edc2548a7a2,0x00031596b5d5f53d,0x00040e945b2c8330}, {0x000587c06dfaa52c,0x00037c462a8f05b0,0x0000000000000000,0x0000000000000000}}, {{0x000cd636b4f0d870,0x000b2b0835ddc02f,0x000d233347086482,0x000bf92bc7f1c7b2}, {0x00050d5f30c92b32,0x000ce136c0491539,0x000254d29288cec9,0x000c34eb38494ac8}, {0x000ba2a1b0b3117a,0x000c473a85376a14,0x0000000000000001,0x0000000000000000}}}, {{{0x0002a61629b67537,0x000edcfef26d3aba,0x0004bac42f2af22b,0x0004da8b32bd0514}, {0x000be474d59e6af5,0x000c190f17846ca3,0x000f3e17e7c79bfa,0x000a13543ecbaea0}, {0x000e74acd0ff996b,0x000cbde27a5f5aab,0x0000000000000000,0x0000000000000000}}, {{0x000ccc73ffeccff0,0x00082b1e746179a8,0x000b19b717d62af8,0x0005045a4e0895be}, {0x0006b8f194a8bb25,0x00089f1cd50b3736,0x000f2a57b3da3e10,0x000691e4f67468b1}, {0x0008976ca9c4602f,0x0005e53ed98ad969,0x0000000000000000,0x0000000000000000}}}, {{{0x000f79bf523ecdd9,0x00097ebf36d74486,0x0000fe48147bf45f,0x000868d46235b3ae}, {0x00073a9b13d93d40,0x0004e9264c45fa91,0x0008c79b5705f4c3,0x0000fd4b166fd0d5}, {0x000aca2edaf4ff87,0x000955b68a488f7a,0x0000000000000000,0x0000000000000000}}, {{0x000f3e0b19951fb2,0x000c26747dd972f5,0x00092d84bc8f6fc0,0x000255f7088102b5}, {0x000c984970893201,0x000a6791707f6288,0x00072769309b54e6,0x0006389f4da5d532}, {0x000c1eb23c48b5de,0x000d1bac794b858f,0x0000000000000000,0x0000000000000000}}}, {{{0x000e2d8dfd2d5a87,0x000e5a708c918328,0x0009b9fb00f1dbe8,0x000fe9c7a3695cb8}, {0x000749205b4caaea,0x00056f204bd6ec0b,0x0001a73a9e0254c7,0x0004152441cfd51d}, {0x0000d2b8b0ca9156,0x0004dee3cdd9e937,0x0000000000000001,0x0000000000000000}}, {{0x000ab13754dec146,0x000b5d5322d78e9d,0x0000adbfc5578b8a,0x0000ce27a2b97f9c}, {0x000b49cd573f2d5d,0x0006ee23d2e94e39,0x00061ea213bd15a0,0x000e561b9d34708d}, {0x000fb576c6271f59,0x0001669ae9450741,0x0000000000000001,0x0000000000000000}}}, {{{0x0001a66376c54f37,0x000a06b888102e23,0x000430b0efaaecdf,0x0003b1e3d888793c}, {0x0004f8beed2dbb12,0x000ea5e72a8887df,0x000d4aa2425e9853,0x0009d98e93f3ccc7}, {0x000cba97fe918171,0x0006b08ea6eef307,0x0000000000000001,0x0000000000000000}}, {{0x00019b171f51c344,0x000d5e5d9f40be57,0x000fea96313e16ec,0x0001461efe1e359f}, {0x00043de9904f3d9f,0x00081bb7a038f6d9,0x000ed552c5787d58,0x000a67fc2cd9a74e}, {0x000643f377ccb483,0x0009db7070b5762c,0x0000000000000000,0x0000000000000000}}} }, {/* digit=90 [{1,2,3,..,}]*([2^360]*G) */ {{{0x000188556b53942b,0x000736bd7c7672ca,0x000a466705820ced,0x00039ba4b83d6897}, {0x000af174ecbf7e3f,0x00003dc58b34188f,0x000b453db5dba0b2,0x000ef54df32d5206}, {0x000d08e3c52fcf51,0x0003732f551f3408,0x0000000000000000,0x0000000000000000}}, {{0x000937ade92603b2,0x000b6a7f7f5dfd6b,0x0003151876b632c9,0x0009040d3ee4a789}, {0x0007441b009fd7a5,0x0008b427fedfc2d2,0x0007f921c0ceded6,0x0002220fc8f207d5}, {0x0000f675383c79a4,0x000d6f410a2e837b,0x0000000000000001,0x0000000000000000}}}, {{{0x000fb8b792ff9c0f,0x00062d82addc4301,0x000b9cdf1d9fdb00,0x00042255b1cf25ad}, {0x0009daaea42ebb5a,0x000dffd105199066,0x00001d688f207641,0x0001da7769bd6130}, {0x0004ea507a275aa1,0x000073ea612e43e0,0x0000000000000000,0x0000000000000000}}, {{0x000f18b4b24386fb,0x000f72268a5e0821,0x000ad126436a7554,0x000ba02f714fe1c3}, {0x00019b7c7cde45b5,0x000c576f09f2da35,0x000aef34fb328e0f,0x0001a0386e0f185f}, {0x0007a6bb32adc73d,0x000733da21be9ac9,0x0000000000000001,0x0000000000000000}}}, {{{0x00023d540d542b80,0x0004cc500040b26a,0x000e6a09fa7f8755,0x00027fbb548aea96}, {0x00065fa1d8c060cf,0x000943cfee1a6187,0x00061bce6a8c7ea1,0x000d99730b0b20bf}, {0x000eac170744528d,0x000423d049742c42,0x0000000000000000,0x0000000000000000}}, {{0x0002bba636da345a,0x000a62e601cd801e,0x000c9e240a6cbeef,0x000103af8106469f}, {0x00007c7109e54da8,0x000b9a3ec3dcc449,0x0007788e44b6df8d,0x000d0e67c93ee34b}, {0x000e8347b4a58495,0x00037223b5096e63,0x0000000000000001,0x0000000000000000}}}, {{{0x000417e035b970b5,0x000ca1b60364c1bf,0x000ea847f52dda37,0x000517fb28527f5c}, {0x00007a1e399f798d,0x000452c79fff102f,0x000688a87dfab3cc,0x0006490b0295c5aa}, {0x000d17acd0dbc605,0x0005acb4f6972c3d,0x0000000000000001,0x0000000000000000}}, {{0x000fa35559042635,0x0004e33a903ffa23,0x000c46f6e3526281,0x0007bc6b1cec4214}, {0x0004bca2e1dc8726,0x000b50045720b747,0x000c697f394811de,0x000ba5001f3d4304}, {0x0009ea7fd0f7a5e2,0x00090dead3d0124c,0x0000000000000000,0x0000000000000000}}}, {{{0x000e47c23d19de00,0x0009afd475bc3cb7,0x0001acc6490ff459,0x0009f5dc39b1950f}, {0x00064d14540f1ee0,0x0001b75050e51c95,0x0005647bebd088ff,0x000f240dba4c1789}, {0x0009b95e8097400c,0x00085b5d4b842055,0x0000000000000001,0x0000000000000000}}, {{0x000986a76d06fbfb,0x000d7fc2ffb65385,0x00018e264c5a478e,0x0005a2784841d184}, {0x000fe21d9e8a017a,0x000bf52154297fe2,0x0007dad072d6d911,0x000eae77c8ea8832}, {0x000786b6a02d1fcb,0x000e682555450013,0x0000000000000000,0x0000000000000000}}}, {{{0x000de731f9f48a0a,0x000a357753cff617,0x00073655403972b7,0x0000484d28d73a10}, {0x000c846d46c140c7,0x00055b7ef1516a9d,0x00014890b5525944,0x0005f418ade1b816}, {0x000a465f264a9164,0x000ed37693e9a176,0x0000000000000001,0x0000000000000000}}, {{0x000e5c3bfdcbca2f,0x000121dc135bc4e5,0x0003d39b5c7ca946,0x000be46855877498}, {0x000879fb5d801318,0x000afd92b1e5cb62,0x00024aecd7f80343,0x0004a3835c8434ed}, {0x00025764c6aa7d95,0x000a0241780668d3,0x0000000000000000,0x0000000000000000}}}, {{{0x000c0928cf2280c1,0x000f2c37933b1734,0x0006bae2a2974a56,0x0001e8bdb1d26ac8}, {0x0009c84c336cb6bd,0x000ca41014cdaa1b,0x00024b87838c44fa,0x000f525239cae2ce}, {0x000cb0507515f204,0x000993dbd0e0a58b,0x0000000000000001,0x0000000000000000}}, {{0x0001411bdc3926ce,0x00087f3e15aa5363,0x000ade47bf68672c,0x000028e493da50d5}, {0x000120048f8cd148,0x0005ecfaeb03c756,0x000e1347b7867aab,0x000ba0208953afcd}, {0x000be9b23e2411e3,0x000a2e848d40b424,0x0000000000000001,0x0000000000000000}}}, {{{0x000583ec08d4ad28,0x0007687b7ba7d916,0x0002b3f0b4e2bbb4,0x0002caace0e4b3fb}, {0x000b0e6fb63a6917,0x00000520c822aab4,0x000f41f7930e37aa,0x00046bfa91da4dcb}, {0x0008bd604f521a69,0x00040fa707c1f0b8,0x0000000000000001,0x0000000000000000}}, {{0x000520b880d23952,0x000bb822333018d8,0x000aa6a00bca6bc2,0x000f3469011553af}, {0x000c20ed5fc0a5de,0x000ee0e8c5bcfec7,0x000476e2f464224d,0x0002d844542e8adb}, {0x00009924fd3c1bdb,0x000f2fac98d161a7,0x0000000000000001,0x0000000000000000}}} }, {/* digit=91 [{1,2,3,..,}]*([2^364]*G) */ {{{0x000c9a655367407c,0x00001acf48b04d30,0x00004344830b68ea,0x00058a53174d6fa7}, {0x000f59044eeb31ac,0x00087d51a60524d6,0x000a344fb882d4df,0x000d1ed41d08aa0b}, {0x00086b6aea85fb93,0x0007f27fa57f4860,0x0000000000000001,0x0000000000000000}}, {{0x0006f6fa7b7febd7,0x000ef92aae956259,0x000abc183c404813,0x00011be4ded30d2a}, {0x000e220b7ae966a0,0x000c3e6cfc88e77b,0x000a92b77d5e0cab,0x0003d7f99c6dac06}, {0x0000a6be4c76c302,0x00032d1d55150da8,0x0000000000000001,0x0000000000000000}}}, {{{0x0000d37f0300cf42,0x000564d1a1ebfaea,0x000bce4cf04b07ea,0x00084f2b4677d784}, {0x000db14a4f867741,0x0000b95ce93b8741,0x000a31735b5960b0,0x0003d2c80a76fae4}, {0x00022c4d123107ec,0x0006cd8678a9d705,0x0000000000000001,0x0000000000000000}}, {{0x0004b58dcaec13d9,0x00067d88c3d5f230,0x000f847248f45f52,0x0003da2628ef4e85}, {0x000e37945a7b9c0f,0x000a2da387ea2c17,0x0008e98e84de9888,0x00038290c88f211a}, {0x0004ce3667557434,0x000040ca4612f56b,0x0000000000000000,0x0000000000000000}}}, {{{0x0009e872c584974d,0x0006ca75132450c3,0x0006c420ca2dafbb,0x00069da0e632e68f}, {0x00018e1d45c5a963,0x0000394fa7a8601f,0x00098adcea6c9852,0x0001b23e3c6dad95}, {0x000f0655b2b99628,0x0001992529d81db4,0x0000000000000000,0x0000000000000000}}, {{0x00000b6625e14e8c,0x0006611065dd0a46,0x0000a833140f2868,0x000735d82490f09d}, {0x000326d182482735,0x00074f69a678ac02,0x000e336a3425366d,0x0000093a8f215358}, {0x000644f6ddf3569b,0x000d19beff776a6e,0x0000000000000000,0x0000000000000000}}}, {{{0x0007a73bd7975b73,0x0004ba1e3ef4b56c,0x000835871e0104fc,0x000ed4624759b57a}, {0x000eed3c95d4d9b4,0x00029d8353648a71,0x0006bedece81ad28,0x0001452c12f2b2a5}, {0x000ab19b8b67ec3e,0x000ccd3f8f88bf35,0x0000000000000000,0x0000000000000000}}, {{0x000062e0d5c7f0b6,0x000dd34abff69676,0x0009b89962a6641c,0x0002be1c0add12e1}, {0x00014a078191a9f4,0x000c488cf972d9da,0x00090e9607f65fc7,0x000d5cdadd7da7e7}, {0x0001ca37f83b3584,0x000dd43c6df02d38,0x0000000000000000,0x0000000000000000}}}, {{{0x0003f8ca58799292,0x000601d1cbef0700,0x000f41308b0cefb1,0x00090de4387a468e}, {0x00035f90ae8d18bb,0x000b356306c0a768,0x0005e167044866de,0x000114237a5a47dc}, {0x000143e3b4bbc084,0x000c1c6d0277c186,0x0000000000000000,0x0000000000000000}}, {{0x000c81887bc12544,0x0006af4b6c2a8e8c,0x000ba5958fe82cbe,0x00067cd479340299}, {0x000d360f1809e7e6,0x000de77ee94fcc0f,0x0009d25d201341ff,0x000fac2af6e20977}, {0x000dfea19f8974a2,0x000fba7a5252c712,0x0000000000000001,0x0000000000000000}}}, {{{0x0001e6367ded4905,0x000fd6fd8b41173a,0x0000c717ef3cdcf0,0x000608fdb3300d01}, {0x0000d527d7c8e07e,0x00039cd9ece69c0a,0x000677211bdaf48d,0x000b5d520c7fa557}, {0x000bf842692f3c61,0x000055814bffe31f,0x0000000000000001,0x0000000000000000}}, {{0x000c94502a0e0f49,0x0000528193bb953d,0x000d7bdda5ab1a23,0x0007c4a219650b25}, {0x0000f78abb7ba4c6,0x000eb157bdb9dbe1,0x000ace6b3d0ff943,0x00048180c4dc1a32}, {0x0000124b69e9b36a,0x000da7fee72796eb,0x0000000000000001,0x0000000000000000}}}, {{{0x000530dbdddc111e,0x0004131a0423e417,0x0002a2fcd4c890b5,0x000685a6ffdb8021}, {0x0001c68bcc7cf314,0x000fb29a153281e3,0x00090775f2e2a729,0x000fe4fc20716627}, {0x0005fa8915460a5d,0x000b7744dbded762,0x0000000000000001,0x0000000000000000}}, {{0x00058330ded93a3e,0x0002ad9ca2943c52,0x00031d21ab8030d0,0x000fe30e76f64897}, {0x0002b30fd418c647,0x000815868a20f82e,0x00098d35bf8cbd5b,0x000facccde412b85}, {0x000358ff02bb4ec8,0x000fa54fb1673bc1,0x0000000000000001,0x0000000000000000}}}, {{{0x000aed08c7bd3b0c,0x0004e546195fa3ed,0x000c31c13efbcb9e,0x000f2eaeb2cc8a6a}, {0x000a1912ca200483,0x000f0ff27a5ee60f,0x0000a7b9e9c56cff,0x00044977503cdac7}, {0x00064deabbda5a3e,0x00038efe3a9fcba5,0x0000000000000001,0x0000000000000000}}, {{0x000821113784eeb7,0x000a12560a5e577e,0x000ae4b9aaf4ec38,0x0005c9a38358d926}, {0x000497b69c24b1cb,0x00007485410e5464,0x00026fb660a2d50c,0x000987263ee5a4c4}, {0x000b3ba20c286e0b,0x000ae54bed6c50f7,0x0000000000000000,0x0000000000000000}}} }, {/* digit=92 [{1,2,3,..,}]*([2^368]*G) */ {{{0x000e2418ebe8f2ee,0x000f4560bac026d4,0x00008c6a85ee3153,0x000c7d7d8e05a0fb}, {0x000d35867d053abe,0x000ebaaa06ca6918,0x00022207d8627f01,0x000fdfe74b9c6ea9}, {0x000478deb27dc332,0x0006b633ddba7b54,0x0000000000000000,0x0000000000000000}}, {{0x000eb3b84da8ae44,0x000dced254321c2f,0x000ae0be12cbd92c,0x000b5fae91edd7e2}, {0x000adacef448565a,0x0003f288c1607c22,0x000ea8d01e22b70e,0x0004e3598c73a3ba}, {0x0009cd9f6c24e3c9,0x0007a5595791d3f8,0x0000000000000000,0x0000000000000000}}}, {{{0x000cd049d3a9026e,0x000dbe859af0b3a1,0x000d9aa6b9632b70,0x00029dc483656cba}, {0x0007d02bc7ba1a52,0x000fc68a06574b48,0x000470a9518ff35f,0x000aaf20c720ad36}, {0x0003bb49ecf8b908,0x000f66f8b9d88aee,0x0000000000000001,0x0000000000000000}}, {{0x0004ae92aaca41ff,0x0009e2ff799aa5c0,0x00048de6d0a352ca,0x0008f5f2eb0f3051}, {0x000fea98f1062e2b,0x000285eca4dfe726,0x00044d322419400c,0x0001441ba1f95272}, {0x000c0f6113ec0c84,0x000b67f7b093769a,0x0000000000000001,0x0000000000000000}}}, {{{0x00010c16516e4d3c,0x000611e277c39f9f,0x00040673dd719aec,0x000e007e471514eb}, {0x0006cb0a884f04c5,0x0007cdfc977e1e7d,0x00096fd19b101b5e,0x0008b661589b4413}, {0x0006ee58455ad5da,0x00030384dfd6a666,0x0000000000000001,0x0000000000000000}}, {{0x000dcee7cc09a195,0x000f049d8452fc3f,0x000453637f0d8b3f,0x0001dc43d12fc712}, {0x000f4b97aa7b885d,0x00030970db43c87b,0x000015eb8214e6b6,0x0006a5744b5ac5b8}, {0x0008d3fab8987808,0x0008438a227d82a5,0x0000000000000000,0x0000000000000000}}}, {{{0x0002d58e6de7c70e,0x000a184fd2b399ce,0x000d46ffafde56a0,0x0003266443a772e3}, {0x0009e5e99ec73618,0x00068acc975a652a,0x000b99dda22ced10,0x000f17534159829e}, {0x000ab0176c94c616,0x000fbda334609df6,0x0000000000000001,0x0000000000000000}}, {{0x000e586ebac6018e,0x000f2f03144a03f0,0x00070d82d13df49e,0x000fad35f054795a}, {0x000bfca4e83c93d4,0x000ccd2e817178dc,0x00006d906f96d5dd,0x000999860a4c0599}, {0x0007c4473b0cc898,0x0002a9c7a2422f0b,0x0000000000000001,0x0000000000000000}}}, {{{0x0002b09542f251bc,0x000e9c6a4a88693c,0x000ca160d5142fa0,0x000a8912377d1615}, {0x000e8a6efbddaae6,0x000a4c058235658a,0x000f27a6a6dd7c56,0x00070769ea7bd61f}, {0x0006f5dde4e365fe,0x000d56d5c0ff87a3,0x0000000000000000,0x0000000000000000}}, {{0x000ceae2e0074d51,0x0000c081ba44424f,0x000d9e0eec434166,0x000bbc85793c6ecf}, {0x0000cfdda19dc769,0x0009ff9b44e244b1,0x00055190f00a8e3e,0x000a30e6f1e94105}, {0x0002df24f630f9cd,0x000164028859bc1d,0x0000000000000001,0x0000000000000000}}}, {{{0x00091d8b229586b3,0x00062d4212a9d0d7,0x000a44dcf82dea37,0x000886a8066a0e31}, {0x000c8d5c7f9428cd,0x000e7fa7c681f5e4,0x000db54aa6ccbecd,0x000e8442c468c6ab}, {0x000eb0d35eb4fd66,0x000ecc62bfda1f45,0x0000000000000000,0x0000000000000000}}, {{0x00043fbb4e2cb5f4,0x000b78f0a96488d5,0x0000f4585ef033e7,0x000ccf9f3f7c9386}, {0x0002c56f736843a4,0x0003c2a98300d2f8,0x000d0e9651445c74,0x0006ad9774234178}, {0x000b0d7d2ff89fee,0x0002dc8f018f3a2c,0x0000000000000001,0x0000000000000000}}}, {{{0x000a0b1e42fb1d75,0x0005875ba8ec633c,0x0009652adf59ccbb,0x000c9a8c4da98461}, {0x000058421fa35715,0x000861494cf70c21,0x0001a367a4a6e22b,0x000f1f29e364cf7f}, {0x0002eb8412063103,0x000046241f101761,0x0000000000000001,0x0000000000000000}}, {{0x00035295fd113dfe,0x00087ca26d83dc56,0x00009b60485e1379,0x0006992ee53da791}, {0x0003f63e81d304b9,0x0005e83c82169ed5,0x000cdfc2181cd77e,0x0002864256eb4e4a}, {0x000dd24e836cab6d,0x0000560017a3ed5b,0x0000000000000000,0x0000000000000000}}}, {{{0x0000d40ea7dbd218,0x0000bffd292d5f99,0x0000b3c033efe2aa,0x0003caf5350ffa07}, {0x00062cba18d05709,0x000de1ef348e77aa,0x00050628dcafce95,0x000654c13b978d30}, {0x0004b7581a218420,0x000aebc1eed7a302,0x0000000000000000,0x0000000000000000}}, {{0x000467c3cff7787c,0x000cc65919f6e7d2,0x000e4ef4ee66f3a2,0x0005339dd95dc335}, {0x00083538624188b1,0x000c9f6ee9c47f71,0x000c2d00164075ad,0x0000fb8c9b9b8fc3}, {0x000ab425082f15ec,0x0003706da80b242c,0x0000000000000001,0x0000000000000000}}} }, {/* digit=93 [{1,2,3,..,}]*([2^372]*G) */ {{{0x000981c54aaf54da,0x000345cebb5e6933,0x000544b1b1632546,0x0001b01f84cafbc6}, {0x000115cddc181798,0x000378ad86aa1393,0x00075fe68cbb4941,0x0009588ce3ac7e26}, {0x000708d627f2694e,0x000a9deda381ddab,0x0000000000000001,0x0000000000000000}}, {{0x000d5f56fe3c020f,0x00064c1a13df6f31,0x00002f2a54ccdb45,0x00018f47586ae362}, {0x000f6db9ebb1f191,0x000b71b6517fa3e3,0x000f8c282c695b00,0x000758306aa882ec}, {0x000bb71fac8a72bb,0x0005351671f4f924,0x0000000000000001,0x0000000000000000}}}, {{{0x0008318350691a0c,0x000b269d0103c9cb,0x000bca486ca47a18,0x0001af062d151fe9}, {0x000e7c2bcd6c38a3,0x000a2dd4944c38da,0x000d5e2d0cab5f56,0x0001aaffb6b80e8d}, {0x000b4ab87f1aa045,0x000baad7ec926bd1,0x0000000000000000,0x0000000000000000}}, {{0x0001499620b24214,0x0007f0d276179361,0x0005f42f5e14dbe6,0x000a3745bdaa4d19}, {0x000b02770c1ff9ae,0x00030746fe336a10,0x0005a19965986ef7,0x000598b61ae7500d}, {0x000c2b7c92c56a5b,0x0007c0f20ece26fb,0x0000000000000000,0x0000000000000000}}}, {{{0x00087e69d72ded5b,0x000cbed0493c7849,0x00059557a83ba0a5,0x000cabc475bbdb17}, {0x0003d65e4a623f2a,0x00071fb7df8bf3c5,0x000f576c8eb2466d,0x0003c6d8140f7545}, {0x00002bd4e620a012,0x000cb967837a469f,0x0000000000000001,0x0000000000000000}}, {{0x000871f9216cfc43,0x000a4dc25382488b,0x000ef93af7d4b3a3,0x0003ed77dbf730c3}, {0x000a6f764526ebfd,0x000b6152b407f935,0x00025711c016476c,0x0003dee3ad5a2bf3}, {0x00009ed5688aaec7,0x0007cb5a614fc9fb,0x0000000000000001,0x0000000000000000}}}, {{{0x000d2983eb57fb01,0x0006f8090fc8d49a,0x00055cd8ed43313e,0x000063128651d168}, {0x0009d55315e356a9,0x0003731bdb591a91,0x00090f35172884d8,0x000ce2ac6b9b209c}, {0x000e9deccfbd125c,0x0004c67d19839d92,0x0000000000000000,0x0000000000000000}}, {{0x0007835fb081749a,0x00038c29318405ed,0x000c88969fe7858c,0x000d9e6b39c13839}, {0x0001a193b85889e3,0x0000167b73a0e542,0x000e3a6c6ebad78e,0x000fea5061213cbb}, {0x000f99af7a8cbcf0,0x000934dbdf82d320,0x0000000000000001,0x0000000000000000}}}, {{{0x000dd97cee516977,0x000fc49266fa93ba,0x000b3371de037896,0x000f3467c9ec4ba4}, {0x000bff13f9988671,0x000c0500963fcb88,0x0009447add0b56dd,0x0005dc495e382a32}, {0x000c531e8e3d8f13,0x0003f8ab53419d64,0x0000000000000001,0x0000000000000000}}, {{0x0005999b06e01bce,0x0004ac4c86e9d1b3,0x0001acac55379f5c,0x000ed5f60cf793db}, {0x000deecc778efaf8,0x0005438ff64587a9,0x000da09df4f7f063,0x00095b550b56ea7d}, {0x000d4a2f2118371b,0x000897f5ee846337,0x0000000000000001,0x0000000000000000}}}, {{{0x000e73c876ead4f8,0x000074f77e1ef006,0x00068e9d113a8d10,0x00068c4c79701512}, {0x000c8af63c9e4975,0x0001a355ba1ddb87,0x000a7f69e6cd38b6,0x0001a9ae068bd113}, {0x000bc3a633214952,0x000e40b4f3b0cfc9,0x0000000000000001,0x0000000000000000}}, {{0x000dc3573f4bb5e4,0x000ce2ef087b7068,0x000ffeeffd386368,0x000053bd77e46931}, {0x0008c8fd63c43732,0x0009915ece7b6a54,0x0009d1980b122996,0x0000807d3a509f62}, {0x000abb80ee8c76fd,0x000ea6d20af82699,0x0000000000000001,0x0000000000000000}}}, {{{0x00023cc70a1b7646,0x000fb2fea8f69076,0x00051b6f61d27313,0x00053b59960e18ea}, {0x0003b52c79117607,0x0003c4870ae1dead,0x000b0ba34bd1f16b,0x000eb6ec0bc7a291}, {0x000e48716fbdf694,0x000f3b9ceb0fbb83,0x0000000000000001,0x0000000000000000}}, {{0x000f4df150c14682,0x0004d73e71ecfad2,0x0001f4eed11e2bf5,0x000e8f7ba0e6130a}, {0x000d0ee611881177,0x0004b3748fb1ee0f,0x00018bc0f1b2681f,0x000d95b14d7b81f4}, {0x0005715bb9df9123,0x00010458047bf5c1,0x0000000000000001,0x0000000000000000}}}, {{{0x0007c0378bc40ed7,0x000325851811caa9,0x0000425fd5a042ad,0x00083181ae223e37}, {0x000dcf721e5a193b,0x000e3457f090e949,0x000bab83df6a8520,0x00045f22447cb654}, {0x0000dfbcc720ad35,0x00030064eddb51ec,0x0000000000000001,0x0000000000000000}}, {{0x0007e2d48a4ebf78,0x00086d5a22dda9a9,0x0004ad7ed63a6603,0x000bdfd6f4eac86c}, {0x0006ea0b3cfe90e9,0x0009746e43f3d057,0x000247c38598edeb,0x00066c63f53c5a4f}, {0x0007de7ce9110d7d,0x000580edc5628f93,0x0000000000000001,0x0000000000000000}}} }, {/* digit=94 [{1,2,3,..,}]*([2^376]*G) */ {{{0x000ceb75a39240f6,0x000cd422d17ed307,0x000816d46db1d003,0x0000a452acb6fef8}, {0x000cb9bbe93acb00,0x000e7044e1a33425,0x000fc32d94105ed8,0x00077b448d72bf04}, {0x000527b278a8006d,0x0003f3ce1c27af77,0x0000000000000001,0x0000000000000000}}, {{0x000e21a0404fea41,0x000ba2bea8a562ed,0x0007dcaa390fe905,0x000e3be58bd01814}, {0x00024ad37906a8c2,0x0004147c934bd6ba,0x0008700ab35993ee,0x0003eb32c19654b1}, {0x000e9fb6dc4b6283,0x000fffefce4982fd,0x0000000000000000,0x0000000000000000}}}, {{{0x0008ddce89d919a0,0x000c8653953842cb,0x000510be22ec94ea,0x0004fc6818af52b2}, {0x000d36cd384c6520,0x0000918e38b08bd4,0x0008cd3bbca8f664,0x000f9b3d5866c2ac}, {0x00015b5a22e4fdae,0x00028fcebfa696bd,0x0000000000000001,0x0000000000000000}}, {{0x00086becff5dbeff,0x0002b0a9f4f0a089,0x0002781857ab5bde,0x000f7d34f623a384}, {0x000ab2fc32d5df48,0x000357b29a5aed2e,0x0002a4f85d8000c3,0x000a47c091a8d7a0}, {0x0008c875883e2289,0x00004c78f3991d74,0x0000000000000000,0x0000000000000000}}}, {{{0x0006929bd70c6394,0x00085f2018c22473,0x0004be72094183d0,0x00086c43b8504d5a}, {0x00086b6f18e21a1b,0x000ad297dd4ff469,0x0000f368a9142ac6,0x000e09fe86beaf09}, {0x0008c552b3b6921a,0x000bce953006e93c,0x0000000000000000,0x0000000000000000}}, {{0x00072ac6e0006309,0x00015780956c6baf,0x000c4c2c5f7fa741,0x0001eba55e9870c9}, {0x00060f57cfca17ec,0x0006e490ccc10b4b,0x0008a9db0618cc6a,0x000131fe5f0039e9}, {0x000970dbcf0f5361,0x000700a442baa6b1,0x0000000000000001,0x0000000000000000}}}, {{{0x0003ec842981eb23,0x0008fb16678799e5,0x000db8c26f2eb3f7,0x000307e41091298b}, {0x000c2265d3b22e09,0x000829161a79682b,0x00094108a62536ff,0x0002002fb6dedea9}, {0x00079fdbc3d369ec,0x0002baf58b2f20ca,0x0000000000000000,0x0000000000000000}}, {{0x00056d9fea698757,0x00041a61419646f7,0x000308b017c99346,0x0002b76a5de627fc}, {0x000cb23ee7d29bea,0x000ab47900ba8603,0x00096bb85c794766,0x000df41684cc004b}, {0x0007656ed94d547e,0x000e302003142b8b,0x0000000000000000,0x0000000000000000}}}, {{{0x0005cdf0222a69bc,0x0005e1e346fabbc8,0x000e07629de2b094,0x0005724f76a1e2b5}, {0x0006b43bc885c45e,0x000d1f53506f8c50,0x000458ec4a247aeb,0x000ee8c49a8e9759}, {0x000961f24ad9f81f,0x000c780789ce81ef,0x0000000000000000,0x0000000000000000}}, {{0x000ac3a5a536c8ac,0x000fe30d120ebbbd,0x00029a29c912f38c,0x000d27e5470f8673}, {0x000f785f54b6aa93,0x00069bc2c6347ce7,0x00091c1681c6e838,0x00015f8951322402}, {0x00054c132d778a68,0x0009133565718293,0x0000000000000001,0x0000000000000000}}}, {{{0x000f8e71a3d24acd,0x000de7f8ccaa4039,0x0004a565eb389f9f,0x0001445b3a88c7c8}, {0x000b1b88e20b6224,0x00022d8db00479b1,0x000369096695cdce,0x000d48a7013202fe}, {0x000e3713baba6a66,0x0009b65be868e0af,0x0000000000000000,0x0000000000000000}}, {{0x00018718a6375d71,0x0003fe3e38b8c6c5,0x000ee16d3bd00a61,0x0001a73a8bab2dac}, {0x0001decd0dde75f5,0x0009a19d5d5d598b,0x0002f5dcc2ed8e1f,0x0007b66c768674ed}, {0x000717b781a03645,0x000cd5eb14d9fd45,0x0000000000000001,0x0000000000000000}}}, {{{0x0009a4c40a33f00c,0x000d2d3bef2c63e1,0x000922215ae57c68,0x000763ee03e85348}, {0x000337a4a0d2cb54,0x00047d23204381fb,0x000be443d9712227,0x0007d96627f6c828}, {0x000fb6b5f6d1199b,0x000a433d2170b3ab,0x0000000000000001,0x0000000000000000}}, {{0x0001d3366971bb69,0x0007a38c946a2ebb,0x000b29fb103a111d,0x00047d3675997def}, {0x000fd82824e10a96,0x00029d6d05a45fde,0x000500fa9b94f37f,0x0002317e08c1e35c}, {0x0006ed9214c60102,0x000ee0a2afcd4a2a,0x0000000000000001,0x0000000000000000}}}, {{{0x0003291f02ce62ff,0x0005b8a731176ae1,0x00053e5b4c8c2f09,0x000d5a2322d8f01b}, {0x00092f09c90539b8,0x000c4c22646cfad1,0x0008df5016016f3a,0x0002500c56f4c2d4}, {0x0006618c9bed5731,0x000f52249d380720,0x0000000000000000,0x0000000000000000}}, {{0x00052bb2164b93c6,0x00009ba854f0dba7,0x0002bd9fbffad821,0x0002cee339d0e928}, {0x000515cfc63fee61,0x0008541bf33aca9e,0x0001f0f0fd5f8231,0x0008dccc44f51df1}, {0x000e26d92e5d7f0f,0x000334dc204c43c8,0x0000000000000000,0x0000000000000000}}} }, {/* digit=95 [{1,2,3,..,}]*([2^380]*G) */ {{{0x000df775a4cea698,0x00057fa877dfb590,0x000f628f95d0e8c6,0x0004b622c58775b2}, {0x000e755966c521f9,0x000b826bcad94ba3,0x000585e536e18362,0x00056a8bf64e1429}, {0x000c0d065ab9cff4,0x000c6b7ad254f1fd,0x0000000000000001,0x0000000000000000}}, {{0x000be22413e6824f,0x0009f5a869cd6010,0x000399cde94b5cc4,0x000c96f6029dfb84}, {0x00068c7d0822053b,0x0006cb5f4bf3d33d,0x00090bad70bd72fb,0x000c5f85b78281e7}, {0x000fbd3aad6b87dd,0x00067e9bddab2fd6,0x0000000000000000,0x0000000000000000}}}, {{{0x000f0963f658551e,0x0002ea1215b91acf,0x000276c4b8c7ce3e,0x0002c599ae4d76fd}, {0x00006cf3a3b9f27c,0x00006667b3985a81,0x00095ab3dd5545f7,0x000e9ae8ea63e5bf}, {0x0008eb3015a494d9,0x00014b36df8e2aac,0x0000000000000000,0x0000000000000000}}, {{0x0001e0605f96eb43,0x000d54ec384ae024,0x000bfb3e2ee19fc3,0x000c041bce0a2d7c}, {0x000b57e0aa0d1a5a,0x000f6adf1022b978,0x000452550508726c,0x000b77d6d81e1380}, {0x000536c9802fbac9,0x0007d16666d2c234,0x0000000000000000,0x0000000000000000}}}, {{{0x000d75964c31ca58,0x0004e22c167fba0f,0x0006865896879fb3,0x00085f113d2ac14b}, {0x000fcf92650326bb,0x0009815c6ae567c4,0x000703330478f2d0,0x000c2d4e045bb2da}, {0x0004917027450186,0x0001cb3d6ff5bbeb,0x0000000000000000,0x0000000000000000}}, {{0x0006aee5ed6230d6,0x0006f57fa7f974a9,0x000d445b19954b86,0x000cc41b7edd540d}, {0x0002f6672b9eada3,0x0005adb45c3c302e,0x00085355ea3de1bf,0x000a70efd3fa201f}, {0x0002e28049bc11d2,0x000a9e4d97e0553d,0x0000000000000000,0x0000000000000000}}}, {{{0x0005aaa83e0b7193,0x000ef4020dd38cdb,0x0000a2db89cf16c4,0x0008b727a5cd426b}, {0x000baf5617c8e43e,0x00043d6e5823ddc0,0x000180e259e17f2b,0x000506737413c826}, {0x0004e741255f63ef,0x00009623e6163c43,0x0000000000000001,0x0000000000000000}}, {{0x00095e5ae0c64c88,0x0006e547505a1996,0x00074ec16e26e1e3,0x0001814a43d8b0e2}, {0x0004c037ed439483,0x00075672e85b1a10,0x00064a05bc4b4563,0x0004f4e8604b9fdc}, {0x000d8d54cdb5b099,0x0008d7035e5850a1,0x0000000000000000,0x0000000000000000}}}, {{{0x0006358cac1e1dd9,0x000326ae97ec9d6b,0x00096931bf3f89cd,0x0008a8a20db33ff8}, {0x000f15df6988b172,0x0009cd5efc8b413b,0x000bb187876052fc,0x0004662d8014980d}, {0x000d9235f7d44d41,0x000edff0c8921456,0x0000000000000000,0x0000000000000000}}, {{0x0002553d46a6bdb6,0x000a25d43349dd7d,0x00098c5095dc275f,0x000e81697e9d6a23}, {0x00021486070955da,0x000de66e5e004d62,0x00061fc887538530,0x000b0cbeddeb407e}, {0x000968acbb1e576a,0x000ee36df6504685,0x0000000000000000,0x0000000000000000}}}, {{{0x0001376b4df2834d,0x0009122c927fc01d,0x000cb3e3200f4b1b,0x00077db8d6a633a1}, {0x000324c991410544,0x0009a4d4ddbf0c1c,0x0004f89da008df0a,0x000df68e550730c0}, {0x000e5c51e1a10f51,0x0008da410315475c,0x0000000000000001,0x0000000000000000}}, {{0x000c76b031581137,0x000f3f4ca12b9bde,0x0004e3a329753a8b,0x000499c86ef86a89}, {0x000c838a372fcc5a,0x000ec44e4a97d666,0x0000ea241b991236,0x0001650c8dbf9560}, {0x0007627fd4eb71cc,0x00078654f79c844c,0x0000000000000000,0x0000000000000000}}}, {{{0x000ce7225c38fca0,0x000cf6f1a6e96969,0x0009cc6268e77785,0x000308efc7d8303c}, {0x0008a6b0e52762b8,0x0004bf9968cba9dc,0x000db7c416fd26fa,0x0000e7d932fa8c4c}, {0x0002063b5de7df0b,0x000a1bd8e36d9447,0x0000000000000000,0x0000000000000000}}, {{0x0002f11b9d88f945,0x000b6a528d0c6d85,0x0000491c222e34eb,0x0005246f572cf3b4}, {0x000826a507a97323,0x00051b49545419c4,0x000f246a45d14681,0x0008555cac591e9f}, {0x00067c66c74cf909,0x000c814d10852a3f,0x0000000000000001,0x0000000000000000}}}, {{{0x0004d6495109aae5,0x000c4b86a81e7f4d,0x0004316eb1054df2,0x0006877c19b90005}, {0x0007963ac12d941b,0x000bdc46a9dbe383,0x000befbe68280f87,0x00071d97d1dc04af}, {0x000aabbcc64f8fe9,0x0008543ef9d7ecfd,0x0000000000000001,0x0000000000000000}}, {{0x00056ebb21998e32,0x000ab05f744a3f42,0x000c6587a4d462bb,0x000c14a18de305cc}, {0x00056d2c0e8c5f7c,0x0007f552fd1c2fa4,0x000165b93096db0d,0x0003eef9e935df5d}, {0x00013440e0a7d4ef,0x00020c2ecbc3b683,0x0000000000000000,0x0000000000000000}}} }, {/* digit=96 [{1,2,3,..,}]*([2^384]*G) */ {{{0x0003ac5243ed86b5,0x00075f9805e79dc4,0x0002bee2dfe95a21,0x000284b06125c31c}, {0x000a0103195082b6,0x000cedfa4a2264eb,0x000afa325bc143e8,0x000ae3ae24853199}, {0x000ebe96963067c6,0x00096c54a7cecdeb,0x0000000000000000,0x0000000000000000}}, {{0x000e3a5229434e36,0x00055f3a1a50446d,0x000644f2db4f7215,0x000ad43f6dc38924}, {0x0002239beb126b72,0x000840de05e7dd77,0x0002862d6caacd0d,0x000bce6fa639c67a}, {0x000087602ba53021,0x000679ec9b598271,0x0000000000000000,0x0000000000000000}}}, {{{0x0005ed4dab9a7e9f,0x0006797aaab2f5b7,0x000301593051ee37,0x000962a30b02f44a}, {0x000a1d622cf13021,0x000a7dfa0555a3ee,0x0006aca4fcd685c9,0x000ad2e750777a2a}, {0x0006aa905bd4c914,0x0008ffeec52d7b1e,0x0000000000000001,0x0000000000000000}}, {{0x00095204a3f6fa1e,0x000c34539f85e4fa,0x000e8ddc16e36eee,0x00044a9e74599d1c}, {0x0007ab343c6c5502,0x00007951ae714c01,0x0005c8c4503f92db,0x0006830499e544d1}, {0x000188a7b94680ff,0x000147d6c4809fe7,0x0000000000000000,0x0000000000000000}}}, {{{0x000e6ff25ab97af1,0x000ec754ac7f57b5,0x000607a92403e802,0x0000eca9aece9592}, {0x00080834b57b8bd9,0x000e2fcd37a127de,0x000ed63155d3ec1e,0x000f99b11a3b9b54}, {0x000db302a147172f,0x0005d9290b10d36a,0x0000000000000000,0x0000000000000000}}, {{0x000eee6089f16e1a,0x000772f210e83cea,0x0002496230bbfc3c,0x000c1fbbcea01caa}, {0x00032cc99a5937d0,0x00074603f91be511,0x0003cfecb00c641e,0x000ef833255bc0f0}, {0x00085cab2f6311c8,0x000c7fcc61e9c871,0x0000000000000000,0x0000000000000000}}}, {{{0x000f147189a2546b,0x00070bf89fcfd41b,0x000a403ed89c0790,0x0003f861a107b324}, {0x0009b4dade6e318c,0x00032b6327665e9f,0x00016ecb408e3b33,0x000c11ee2181f62f}, {0x000ba590467bbd1b,0x000a0f4b5440b9d0,0x0000000000000001,0x0000000000000000}}, {{0x000b1aa7ade86660,0x000d1a8a32a33d9c,0x0009ae722d5edb96,0x0004c7770654bd1b}, {0x0001d03d0e5a5166,0x000b01ee816a4a63,0x00015843d1d9344f,0x000c1e1821b3c769}, {0x000c22520be2d285,0x000fe7e0834d6faf,0x0000000000000001,0x0000000000000000}}}, {{{0x000a30d8168852db,0x0007853d06621fd0,0x0000e561a31ba03d,0x000e2351f7abbee6}, {0x000bfa802185d2d6,0x000a8cb11d19a8eb,0x000b4f2b7623f602,0x000f149b3db4a55d}, {0x000399a66e1d6eee,0x000dded7de613b1a,0x0000000000000000,0x0000000000000000}}, {{0x000694da4aed0861,0x00013409999d11ea,0x00021cefe8e175cf,0x000ca47b4e5a0420}, {0x0008274d934ac552,0x000e270720e741b5,0x0003c0a8bd69787c,0x000e75f9cc756f74}, {0x0003e654e1ea2208,0x00040979701ca5a9,0x0000000000000000,0x0000000000000000}}}, {{{0x000d12f4d256a679,0x000fb6f240706408,0x0001c6799f2d7255,0x0002b1c7ad7d86d9}, {0x000c6259fb2898c3,0x000dc9f2eb172083,0x000f61ec85a5a26c,0x0002303eee79dca9}, {0x0003cc24582cff2b,0x000018aea38a1c28,0x0000000000000001,0x0000000000000000}}, {{0x000fee514ac3447b,0x00004db0b385f6f7,0x000785b0f880a482,0x0006256aaff858dd}, {0x0005224f69e65ae6,0x00099c8d9092f5e3,0x000a4d5b2e1cceee,0x00065201f6ee40cf}, {0x000abc908fefbb83,0x000f4461f21689bc,0x0000000000000000,0x0000000000000000}}}, {{{0x0006ba04a3b21865,0x000b257a4daf424e,0x000a3bec5e4ad4b6,0x0001bf9b577cca5f}, {0x000e764bad272e02,0x0003f73ae3883e3d,0x00078df5e21be44c,0x00046e6d9107b020}, {0x00009a9e8ecf5414,0x00062dbf7ce0cbdd,0x0000000000000001,0x0000000000000000}}, {{0x000ed268a93dd876,0x0001345efa0e6741,0x000a124edec5cb04,0x0002301ceb5830ec}, {0x000c074b8d138854,0x0003717a195a4b92,0x00078d388cdf3e4c,0x000aa6e0172f6f1a}, {0x000474fe593756f7,0x00063e14f10ad2f4,0x0000000000000000,0x0000000000000000}}}, {{{0x00056d8ef5183d33,0x0006d4aef07505d7,0x000fd1d5c09dd4c2,0x00026645b43bb4e7}, {0x000876a817eb253c,0x000209c32af92f54,0x00083a63e205a086,0x000d802502f8b9b8}, {0x00069b5a7a6f9cb8,0x000e8d87089ec121,0x0000000000000000,0x0000000000000000}}, {{0x000c2981d5c3f78b,0x000fd7c0b6dcff4c,0x000e2051e1d39135,0x00056f990f800ca1}, {0x000bbae12c766764,0x000fc5fcbf987a86,0x000db02cbf344cfd,0x000965a4f55ea853}, {0x000d8cf4b24b115f,0x000ddb28cffa2bf4,0x0000000000000000,0x0000000000000000}}} }, {/* digit=97 [{1,2,3,..,}]*([2^388]*G) */ {{{0x0004c9f1b01bbcb1,0x0008c564ba5d43cd,0x000b6d345ac26289,0x000156220f11b91d}, {0x000dcfa53c395f80,0x000e8f0647eb32e3,0x00071de125c49a24,0x00035c7837015374}, {0x000bc6a877a9741e,0x000a3e1c5d3aa600,0x0000000000000000,0x0000000000000000}}, {{0x000eae31d5cbf2fb,0x000ff21336f73218,0x00063097ec47555d,0x000e41ac8f16a8d5}, {0x00010c063790a928,0x000842e2a872cf72,0x000d214bed4668e2,0x000e7b5aab91e7f0}, {0x0002089cbbd94783,0x000d7755df6f3c47,0x0000000000000000,0x0000000000000000}}}, {{{0x000c45be80c5ceff,0x0008b5f3a736f81d,0x000f684853db7b94,0x0007af37a1d8a120}, {0x000c1e37602997de,0x0001ba866cadb401,0x000496a24e3e6caa,0x0002c3eae9d6cd94}, {0x00074e14e06f82a8,0x000343069d99834a,0x0000000000000001,0x0000000000000000}}, {{0x00060baf525e3e5c,0x000adc3855bae42a,0x00020017824fbb6a,0x000d2439950ab7cd}, {0x0001396b971049df,0x000925d16b65cd1e,0x0000815f2ec4dd14,0x00099059e2e1d82c}, {0x0007231633ba03a7,0x000c17f35a3c602f,0x0000000000000000,0x0000000000000000}}}, {{{0x0005cd392892c72b,0x000067c79588a466,0x0003e61043554996,0x000e4fea3dc40ec6}, {0x0006245b592ed7ab,0x000d5fddb91366af,0x0005bcef5cf9183d,0x0006f2afe7d93c79}, {0x00038f789bd81e98,0x000a24ae25969d23,0x0000000000000000,0x0000000000000000}}, {{0x00015df628bff28b,0x0008b0238f67e086,0x000debae13d569b1,0x000537b081c52561}, {0x000e3e637e8d5f7e,0x0000b558a9b4dba0,0x00092e9e6c338cb1,0x00054c7742924ded}, {0x0001b877e357069a,0x00077dfb12df7675,0x0000000000000000,0x0000000000000000}}}, {{{0x000eac10daa6fc06,0x000a451d0d93fa05,0x00030dbe3663fb80,0x0003df5569a67246}, {0x000583a7b7740137,0x000a1bf5763b688d,0x00007976f4ce0d19,0x000972348a80c203}, {0x000296b9dd874e74,0x000ad726fc872424,0x0000000000000001,0x0000000000000000}}, {{0x000626a33acca649,0x00019c0b206a34a4,0x000597e1cfe661fc,0x000915e61f98c11b}, {0x0006400c41adb010,0x000ed21859bdcb2d,0x000247507de82c2f,0x0007ba1295daeffa}, {0x0000842d673a4f29,0x0001721fc083b457,0x0000000000000000,0x0000000000000000}}}, {{{0x00034490e59e8714,0x0004db94a827c594,0x000be5c43f7b8f49,0x0005c1ed99f38332}, {0x000c89e5a5eae6d0,0x0007a328c3f873b0,0x000b195eb0205cc5,0x000957c8e1b9bcde}, {0x000a9c05764ec15f,0x0003785ee6082c58,0x0000000000000000,0x0000000000000000}}, {{0x0006efc5f7d22a96,0x000c221343eb9e1a,0x000752365f225594,0x00006ed92aaffd4a}, {0x00047b4ac0a51a79,0x00034752a1b444db,0x0000b01d86935b36,0x000ff91905b43171}, {0x000a16a9f33a34ae,0x00098febd2ea9993,0x0000000000000000,0x0000000000000000}}}, {{{0x0009425bd3be24b1,0x000ddf604bb70186,0x00004732993f7d31,0x0003e481243d40e7}, {0x000cdd085631cbfd,0x00020a779443a447,0x0005a3d17a4bd6e9,0x000c2ba013a6f159}, {0x000091ba40454351,0x000bd45892d66dc6,0x0000000000000000,0x0000000000000000}}, {{0x000413e025588ac6,0x0006b5fdc28cccb3,0x0001b7df9aa499d4,0x000dec43b5bc5fae}, {0x00066d0478edbc5a,0x000c5c7523db595f,0x000f66c3689cc921,0x000369286e3460ae}, {0x0009f5650aae055f,0x000ecf05c2d82ed3,0x0000000000000001,0x0000000000000000}}}, {{{0x0002dc4c335595b5,0x00087d3146806d12,0x000280502c85e0da,0x0006080ca34c63d6}, {0x00057bee19e4fbfb,0x000b329c24618627,0x00059c63cee44932,0x000729a1018b673d}, {0x00038096ab196705,0x0008deabcefcd004,0x0000000000000000,0x0000000000000000}}, {{0x0008d702c45db29c,0x000164a83c7ff2f7,0x00004bdcc8d9c10d,0x0006a51badde1985}, {0x0007b3d628a8f0d9,0x000238514e884060,0x0003ad2af9123d94,0x0001c02c79997897}, {0x000547f0e64e4ad3,0x0009546706bd2921,0x0000000000000000,0x0000000000000000}}}, {{{0x000474c793f4e626,0x0001b9f27eccc505,0x0004061bf3c9bbd8,0x000776661385eed6}, {0x000ca2d5cbcfee54,0x000b0a8618a0f415,0x000c45418675f88a,0x000e0d5df7ae47e7}, {0x000f8808275324e3,0x0005bfe818ccf0e2,0x0000000000000000,0x0000000000000000}}, {{0x000d8f452acbfbda,0x000031ef224de6c2,0x00070dcb7f79ce12,0x00097b18d958660b}, {0x000224dfd1c89c45,0x000d69ce10da0fa5,0x0001b65989afa822,0x00094e1b3fa146e8}, {0x0002ae217dcac503,0x0006327d3eef4183,0x0000000000000000,0x0000000000000000}}} }, {/* digit=98 [{1,2,3,..,}]*([2^392]*G) */ {{{0x000f424e1d9c6487,0x0001fab2d1847091,0x000c18abe11482b3,0x00002a204548d244}, {0x000d2901117bfc9e,0x00086c34a4b1dc1c,0x00025a48ee98a6d2,0x000cb76b3ae604c3}, {0x0001c8298db518ae,0x00008fb7194b2498,0x0000000000000001,0x0000000000000000}}, {{0x000055d976a5cca1,0x000a2cc7061a3bfd,0x0005a667bf88a107,0x00028dc3af0a63ac}, {0x000873e8641fb210,0x00040a558da80d94,0x000fc0963f8d8c7d,0x0009ccc465473acc}, {0x0005ce362fbd5307,0x00081d15006f15e8,0x0000000000000001,0x0000000000000000}}}, {{{0x00022141cc3287fc,0x00038266149a76c1,0x000fdcc4f6ec602d,0x000673e316b23844}, {0x0002f7ff0591cea0,0x000226449753082d,0x0008c9cafeaf6b58,0x000801a84f6bca52}, {0x000738672e240363,0x0000fb54c4174c43,0x0000000000000000,0x0000000000000000}}, {{0x00005f340ab8f558,0x0003c50b6de62a42,0x000c67ea2a5a8485,0x000584f292e0d583}, {0x000976bb7a441296,0x000e6eb31fa9f0cd,0x0005886d0d33dfac,0x0005ca9b5dbb850b}, {0x0003bbd95e75a3fb,0x000aa9fc35ee4214,0x0000000000000000,0x0000000000000000}}}, {{{0x00048296df946f82,0x000d1ae0f7178948,0x0009fea01e8f3835,0x00032c83af761a04}, {0x000c81060dc76c7d,0x00037519156c5ff4,0x000bd4aec6a8a45c,0x000cdf6166cd6f1d}, {0x00042edd4a64bcec,0x00087353c4d352a9,0x0000000000000000,0x0000000000000000}}, {{0x0007c5d100fac674,0x000db9e757c12a95,0x0005aae530260819,0x00099d6efbc64c70}, {0x00069b00bbd4972a,0x0000b755c13bf68d,0x000c9bf125fdc71f,0x0002e7e830894502}, {0x000fe09937e20c9f,0x00002b5fa7bc0dae,0x0000000000000000,0x0000000000000000}}}, {{{0x0006f3e4a3b653b6,0x000d1a688f6e0a4c,0x0009e0c6a622a9b6,0x00092759febdd4b3}, {0x0007de14d66ca7fb,0x000a2edb8e3d698e,0x0001ab808ea4d110,0x00080f85570610b2}, {0x0004c29e8f8405b0,0x00027dadf7ff6310,0x0000000000000001,0x0000000000000000}}, {{0x00057c2f52f741db,0x0008e2e671ed8847,0x000d5288875b3801,0x000d96a8629331d9}, {0x0005a7e602196279,0x0001f2dc09559eca,0x0008fe5f274c1468,0x0006483d04249681}, {0x000f5286b1c8246f,0x00077944ba105276,0x0000000000000001,0x0000000000000000}}}, {{{0x00065afeabf73b11,0x0008c74def9ab376,0x00022e8ebbf2f73b,0x000cbc3cc29566a6}, {0x000e491e3c34a56e,0x0005e3e30062fb22,0x0008f34bd61c9faa,0x0006ad9002a6b766}, {0x0001e57f55fbc947,0x00052212e9e41cf0,0x0000000000000001,0x0000000000000000}}, {{0x0000895f7a4eff76,0x00077650f0c0269a,0x000b638552f2435d,0x000cabbe1734cb6d}, {0x000ac1912708cc1d,0x00051cb37cd08219,0x0002a65eea8444e1,0x000bbf996f86f52b}, {0x000fc6bb767f7430,0x000d61b13f4e2c8e,0x0000000000000001,0x0000000000000000}}}, {{{0x000d5ccc9d50240d,0x00084d2e5496b2b0,0x000f884405e473c3,0x00057903c51b5ae8}, {0x000d55afcc0675e0,0x000125af4b250a76,0x000937bc2b1d7e99,0x000a633470b9206a}, {0x0000cfe28137ad4e,0x0002cd8906210714,0x0000000000000000,0x0000000000000000}}, {{0x000877153680ec3c,0x00019913626b5dae,0x000bd89f532b2d72,0x000d578470af1c82}, {0x000b3f975bb94d7b,0x000f53a6076b8092,0x000db22bb5b744d5,0x000f43f924c34cb2}, {0x0006114e078b5812,0x000fb3e3de49501e,0x0000000000000000,0x0000000000000000}}}, {{{0x00028536905d5e34,0x00092fdd83e93bc7,0x0001a64b28a1f75a,0x000a170fe5a66cb3}, {0x0001e6a59754016b,0x000c5178f6263ade,0x000bc78f0892f5d7,0x0002723285c0f5f3}, {0x000ce420f8de3807,0x0004c264b36ac9d2,0x0000000000000001,0x0000000000000000}}, {{0x000334fb73061393,0x000f6bbeabea50b7,0x000a60e0b4b57374,0x000565e15377dc7c}, {0x000ef0ff94b0e964,0x000e47e49a96f0ea,0x00030ac68d3dc2bc,0x0009347ee5d6453c}, {0x000eac1f6901d599,0x000086abf91bda19,0x0000000000000000,0x0000000000000000}}}, {{{0x000d441660f7e89b,0x0004d20a8f4b5442,0x000f7bf31e592476,0x0002835026e4af60}, {0x000359fc53bdf7be,0x00012726ea080568,0x00075b1726e147ea,0x0001ca2a0207d5e1}, {0x000322cae833e591,0x000e936cba51a14d,0x0000000000000001,0x0000000000000000}}, {{0x000a1d6534e7b937,0x00065ce0948dd2da,0x0002f88e2acca2b5,0x00091e6c94ccb3a4}, {0x000c7d8fe477585d,0x000807f46db59ceb,0x000b940f42378210,0x000e402ecff0fc9e}, {0x0007bc598d173f94,0x000f16af975145bf,0x0000000000000001,0x0000000000000000}}} }, {/* digit=99 [{1,2,3,..,}]*([2^396]*G) */ {{{0x000942a4c75e9fe7,0x000c673dad29e115,0x000e6be55a2350de,0x00045659ca3c399f}, {0x0003c87e22652712,0x000bd4c4458f51c6,0x00057db758ae1a11,0x000c547db810319b}, {0x000c8ba847d5c89d,0x000239959a5bbe62,0x0000000000000001,0x0000000000000000}}, {{0x0003d490f3876f02,0x000521482b690e8c,0x00083aada0850d48,0x0004a53582c13331}, {0x0007bae5a342545c,0x0001c50d6f31c146,0x000d97c2d093b815,0x000e82d6fbdb84a7}, {0x00053468edb41ffb,0x0009e6ae0e9fad49,0x0000000000000000,0x0000000000000000}}}, {{{0x00060773f6c223a7,0x000ee1e8255739aa,0x000672547b158459,0x0000639d3f4e65fb}, {0x000635059b89e003,0x000ffb7b9ac29a4f,0x000cad3267e18233,0x000a7f7d6bbb6854}, {0x000d91b6e79c3b99,0x00065ebec22c4720,0x0000000000000000,0x0000000000000000}}, {{0x0002fbb0f6be8071,0x0006dc307d9b73d7,0x000c6fa2f527f8c4,0x000e537cfbf3d06f}, {0x00018d7888122d62,0x0001ea61a84ebd38,0x0005532479a6f831,0x0004a4bf3325eafa}, {0x000717809c7a3155,0x0000399520a8095a,0x0000000000000001,0x0000000000000000}}}, {{{0x000b807898f2ae67,0x000d7e4f60fc8927,0x000bd2ecac1c97bb,0x00075b365b008578}, {0x000f53b54d53eaaf,0x000e5a0ab86540b6,0x00009c6ac54c1d9c,0x000267e6b65d52d9}, {0x000a061126607ea0,0x00011c0a94e0f97e,0x0000000000000000,0x0000000000000000}}, {{0x000dd52c7077ac64,0x000e6849bb24e97f,0x000e60101c7fc9b8,0x000e52f0dcbe3ce9}, {0x000023c779930c2a,0x00050df58185f016,0x000a6864a7c2cfea,0x000d52f720dc8c89}, {0x0006aecf1e2d3b3f,0x000fe51ac6cabd56,0x0000000000000000,0x0000000000000000}}}, {{{0x0002f47341f417ba,0x000cd8bb740324e4,0x000e45bfed89909b,0x00089a7fe9550616}, {0x000b7861f9828778,0x0008946a71446a53,0x0006502fbe6cdbfc,0x000f70373dcf7291}, {0x000b59a0e59c8ba5,0x0004ed07606ee31a,0x0000000000000001,0x0000000000000000}}, {{0x0003f237a7cf7e71,0x000f61b5ddd50efa,0x00056f3a63a0f211,0x0004dae68319e664}, {0x00090e5acc6a3312,0x000d6c5fe3f2c7d0,0x0005f435cc8df625,0x000420f4229fa016}, {0x0009c92c95adf8ff,0x000c03d951affc2e,0x0000000000000000,0x0000000000000000}}}, {{{0x0008e856f1a63237,0x000c38cfb4864e09,0x000a9b6c8ef2a48d,0x000565ee070c9954}, {0x000b247d25c31c3e,0x000d383653eec5d7,0x00033815ac0ce45d,0x0001d40035f31f5f}, {0x00016fd77486c728,0x0002145bbe546eb5,0x0000000000000000,0x0000000000000000}}, {{0x000f8a00f9535f58,0x0006793f432f2f0d,0x000a22b5ed0740ff,0x00046e71ff907935}, {0x0006ed013a6683d4,0x0006c4dc5feeee1f,0x000e49d371167831,0x000c07fabe848ed6}, {0x000dbccd8d710493,0x0003939263e99e29,0x0000000000000001,0x0000000000000000}}}, {{{0x0009123d0b7caf2a,0x00010c9813e058eb,0x000b14ecd8d170c4,0x000aafb543a445ef}, {0x00066b13251ba12c,0x000a58ee44692c76,0x0009f4193734f736,0x000a0ff39b6d1ecf}, {0x00049d16c582e2c3,0x000a54bc874e11dd,0x0000000000000000,0x0000000000000000}}, {{0x00086c1422f1debe,0x000be6be161bed99,0x00094c11992adb85,0x0007d02a974392b1}, {0x000dc1355dd0b472,0x00001779ff9ef84f,0x0008dc1dbbcd1c30,0x0007615360f70921}, {0x000cd90cece2bff5,0x000a085b2b4772a1,0x0000000000000000,0x0000000000000000}}}, {{{0x000bac8ffc9b1cbb,0x00041fbeb1c7a5f9,0x00032bb744d70f6e,0x0006377a1f50a7aa}, {0x00008611c61b42a6,0x000ce936f3324a60,0x000a084c3dc201c1,0x0002b70db700c5bc}, {0x000f0caf347988c8,0x00025e2dfe3675fe,0x0000000000000001,0x0000000000000000}}, {{0x000fee427e9f9424,0x00069a165d8d1c76,0x000dc1fbe1e937f2,0x000db180dfee35cc}, {0x000b55475d4c9745,0x00036d0a2fefc6cd,0x000476726ccd4e8b,0x000f3783e580f7ab}, {0x0005d079b31ff3c1,0x00009ced18ab19ce,0x0000000000000001,0x0000000000000000}}}, {{{0x0000806a0ffa1183,0x000b368c8ad93735,0x00045322006bc207,0x000356cef3feb2a7}, {0x0000d9772041b29b,0x00015326534db436,0x000c3a4ffd400337,0x0004525bb0cb62b4}, {0x0003dfc1aef8cba9,0x00023c5f95e7e7b2,0x0000000000000001,0x0000000000000000}}, {{0x0009f0d5faafe7a7,0x00079f056236883a,0x000e0f2e02fe7ca4,0x00020a75821e669e}, {0x000fc3208dc12d93,0x000c95bd4d2a90f1,0x000127ab836d5d0a,0x0006a56f1f5b0f15}, {0x00053533b35a8c80,0x000e1db5d6ee484b,0x0000000000000000,0x0000000000000000}}} }, {/* digit=100 [{1,2,3,..,}]*([2^400]*G) */ {{{0x000b291af321cc48,0x0000d263480c29b1,0x000ec9060276afae,0x000489d0d90afac7}, {0x000ec62d3da37067,0x00088f38b3e31b78,0x0007f35ff5fafe7d,0x0007885361013dfa}, {0x000270f897a6237d,0x000c2a42a2eac980,0x0000000000000000,0x0000000000000000}}, {{0x000b6527c69198d0,0x0008c038b2196095,0x00056c8573aab3e2,0x000c299349dbf002}, {0x0009c016fc238b06,0x000c26c63dc550c5,0x000712822cb43957,0x00044a5765b7d6c8}, {0x0000be87f42f34ea,0x00061a9436ed5036,0x0000000000000000,0x0000000000000000}}}, {{{0x0006c0f3c9200410,0x000c1523b6d0c7cf,0x000b2a524b701323,0x00080e1d445c4f05}, {0x000cfb721bd24fb2,0x0004d74f5043a450,0x000c3ca459a36903,0x0001f8a997769ed3}, {0x0004569349bd35cd,0x000fa7a1b94559af,0x0000000000000000,0x0000000000000000}}, {{0x000479e9fda50d86,0x00039193e5dd5ac7,0x000fcfc382ffdaf1,0x0006e937727251e2}, {0x000819f976e0e477,0x000e0dea37faf936,0x0002b3218ec38c97,0x00020308bb264566}, {0x000441534d581e3f,0x000046c275dc071a,0x0000000000000001,0x0000000000000000}}}, {{{0x000cb5968e20ed2c,0x000a52702c5bb89b,0x00033f897addfb47,0x000f030ce16c51a7}, {0x000945e8bc092078,0x0000a224a9b9a4c1,0x00074fb0d2a2dbea,0x000a00b01506244c}, {0x000403180ef3b3ed,0x0000d544f09c72f4,0x0000000000000001,0x0000000000000000}}, {{0x0007f0289c261b7e,0x000d803c0211ff4a,0x0001ffe93b188323,0x000b503181a127a4}, {0x000960bd651117de,0x000f238b1565ffd2,0x000706280cef133f,0x0004ddb33d18643d}, {0x00057a46393ccc6e,0x00011d1fcc4678c9,0x0000000000000001,0x0000000000000000}}}, {{{0x000cb18067eb6c9c,0x000904e0e232321c,0x000c2c362eb5eae4,0x0004f20ada675b34}, {0x0009513d2fa912c1,0x000c8c7ff960f4ae,0x000ea3278df20646,0x0004b702cc146790}, {0x000b87bb57608da3,0x000f1fadae0fb9e2,0x0000000000000001,0x0000000000000000}}, {{0x0006a843b0ca7a84,0x000ffac89f77d5a2,0x000265d14c35a368,0x000486e7957c89a9}, {0x000f9514b7e05bd1,0x00037cf3d5a9030e,0x0002008b9ea39985,0x00050c45cfba4fb3}, {0x0008d5a1561ff956,0x000bc01cc6a56407,0x0000000000000001,0x0000000000000000}}}, {{{0x0005bb52ea9ac7ec,0x000e28f7ce0ec366,0x0004c059fd569d2f,0x0000e89276b354dc}, {0x00013674b639e129,0x00051c92206d8283,0x0005fd8d62852509,0x00083a0ba16eee81}, {0x00023ff408ee3851,0x000e736678fced53,0x0000000000000001,0x0000000000000000}}, {{0x000a8b28dba67d24,0x000216ba84ecb673,0x00034998afbbd048,0x0004e06cfb264967}, {0x00064c024c958fcd,0x000c3e07fdd668c7,0x000e902ee5004559,0x000c7be484240ea9}, {0x00085d1cbdf78504,0x00001fc315ffe9b1,0x0000000000000000,0x0000000000000000}}}, {{{0x0003f67e6d554604,0x000a7edbdf25d6db,0x0004a86faf823503,0x000561d458cbd82a}, {0x000fd50ad1fb2727,0x000d57e2f00994b8,0x0006a571b2b47251,0x00025dcba3cd1573}, {0x0003351634df5819,0x000f90f716e579ec,0x0000000000000001,0x0000000000000000}}, {{0x00015c741fd15e62,0x000782e4509eb436,0x000bb1dede8ef754,0x000e32d87a793f6d}, {0x000cb27d972fea02,0x0000af4ace00b65e,0x000665980ede0c9d,0x000f6c809dcb9681}, {0x0003f6f1f979a653,0x000fa70638c8e694,0x0000000000000001,0x0000000000000000}}}, {{{0x00069573569a82f9,0x00074c79907894c3,0x000923a4f546a942,0x0003c148a698895f}, {0x000c357afe3d1621,0x0000597be114eca3,0x0008bde57638ac14,0x000ab1f30c4d2325}, {0x000c1e648b9d09ce,0x000b5b544e3974e2,0x0000000000000000,0x0000000000000000}}, {{0x000a45f392d296b8,0x0008740111ad4028,0x000c3e262fdbe28f,0x000c3453830a9ee4}, {0x000ae0fdaa4f4e3c,0x000db8b9c8044def,0x000827b06665f64c,0x0004b0bfa5e94a06}, {0x000288ab3926f336,0x00095cd9d3c3ecaf,0x0000000000000000,0x0000000000000000}}}, {{{0x000b181f2f210670,0x0009ac047db30c5e,0x000f0b9977abb73f,0x000685fec5355db3}, {0x000cba356655da26,0x00050bb7fd48c1a2,0x000094ac2c2dc459,0x0002437ff8a8e766}, {0x00026425d80146ca,0x000d215b7aafe50b,0x0000000000000001,0x0000000000000000}}, {{0x0008a54b77260e44,0x000200683c3c461c,0x000806c758fee244,0x000ee02fb90af5d8}, {0x0005167ac6f6571d,0x000f1dfed253aeab,0x00051fc762d73380,0x000f059d556559bf}, {0x0001430491432973,0x00077ebf133e93a9,0x0000000000000001,0x0000000000000000}}} }, {/* digit=101 [{1,2,3,..,}]*([2^404]*G) */ {{{0x0002ff226442343f,0x000cd833f176501e,0x00095759918597f6,0x0008de415f1a7fb7}, {0x000e4316d41dcb51,0x00029d89c6966644,0x000513d7775eaca8,0x000a9d45da4eed7a}, {0x0002852aadd14ef8,0x00062ec016fff623,0x0000000000000001,0x0000000000000000}}, {{0x00091f95c7b230dd,0x000a732cc46d0d07,0x00004775f23d4641,0x000d9d15b9dcdfdd}, {0x0007a727ace99c9b,0x00077fe3e5aec6f6,0x00023beeac1ee2fa,0x00008f21d63275b9}, {0x00065885355852cf,0x000ce1be6d4550b6,0x0000000000000000,0x0000000000000000}}}, {{{0x0006e321251c61dc,0x0002560a1fff242c,0x000a45d55894b5a6,0x000bc8f1bc1ece0d}, {0x00099655945af852,0x00081d51a6f4152e,0x00048184573b7d9f,0x000f69e42e8015c7}, {0x000b2c20669dba53,0x000e9f9624512355,0x0000000000000000,0x0000000000000000}}, {{0x000c96019553b866,0x000abe8a5146d011,0x0006c8e83c7c8d9f,0x000d33f93fede45c}, {0x0006fb87d2fad3d5,0x0007a48456e1fe30,0x000e6e9f030c2436,0x000ab8f59e2c2aa7}, {0x000e2ecee8097392,0x000ce7dbed7e8f7a,0x0000000000000001,0x0000000000000000}}}, {{{0x0009869c0eb3066b,0x000607798fe984da,0x000507796822415b,0x000b35e4cf4e7bb0}, {0x00043514e2eac3dd,0x0006f5f2ec73d5e0,0x00073c55dac4fc5a,0x00009ae9d9b66b29}, {0x000e7849157dbfd1,0x000a5482a9437d4b,0x0000000000000001,0x0000000000000000}}, {{0x000c4e943ae95512,0x0006cf652253cdb5,0x000d6ec12d70a741,0x000569eacfb8355d}, {0x000eedc557ace0f2,0x00079ed65a726737,0x000cbaa427929f79,0x000f9f7b12d69985}, {0x000f61768135719d,0x000ae5a402492b60,0x0000000000000001,0x0000000000000000}}}, {{{0x000feaf2d1e3892c,0x000ab68c7ed96e8e,0x0003cb959b9f3e2f,0x000c2e34fe65989c}, {0x00089b397dfd24ce,0x0005a4f7a72a8210,0x0003d4d194fcfc29,0x0004009eac36cd18}, {0x0004df54ac2005f3,0x00037ac4355ce338,0x0000000000000000,0x0000000000000000}}, {{0x00018f15a5288002,0x00084aab158f0c62,0x000919d3c1cc9db6,0x000c654f22157c5c}, {0x00061a5d7e7c5733,0x000dc89cd41bb67f,0x00046690cac1f786,0x000f2b55f183f6e7}, {0x000f41e4cb445fa4,0x0005a969c4dd429d,0x0000000000000000,0x0000000000000000}}}, {{{0x000f3df64800b6f3,0x000d7480b73133bc,0x000b600425660d57,0x000b837e3aef4df6}, {0x0005fb5d2c2dd02d,0x00011fe018b03d5a,0x000c71322317085a,0x000d374ad3a452d3}, {0x000a4d81aa830346,0x0004a3299709ce7b,0x0000000000000001,0x0000000000000000}}, {{0x00016776ed8701be,0x0009a6af0a211f00,0x000ee5799e2d0b99,0x0004ffaa89dc73ac}, {0x0005974371ca9e1e,0x000e0cc77bcb98c1,0x000c6b4ceea4b327,0x000a8308bd6b7617}, {0x000c8a4f2fabfb14,0x0006930491f45b7a,0x0000000000000000,0x0000000000000000}}}, {{{0x000d9bdcbcf79471,0x00074d3dd4ca53d8,0x0001af7d8d51306c,0x000b82f03e680d58}, {0x000a7884ca0be9c6,0x000c62e3720aacdb,0x000ad9ad633f5955,0x0000c84d067a1c4c}, {0x000e24eee54e3c55,0x00019dbe3f67b54f,0x0000000000000001,0x0000000000000000}}, {{0x00099b839c026b9e,0x000bc7d75cb7b6b9,0x0005e6b4aa8a5275,0x000156cdfaa9f40a}, {0x0004a1992d1c2e6b,0x000b18092816e51f,0x00027a900c94afd0,0x00010f9d0fb16b34}, {0x0008f98b409eefa5,0x000aaed3cae46309,0x0000000000000001,0x0000000000000000}}}, {{{0x00060d5e996dc11b,0x000619082845b56f,0x0006ef36f7ab0ecb,0x000d028f81fdfa6c}, {0x000060da295844af,0x0009596e31cc9ebb,0x000308c32eb79211,0x0001ea951754105b}, {0x00008750f063690e,0x00083b8a021ee964,0x0000000000000001,0x0000000000000000}}, {{0x000d813e43ebc1f3,0x000af78ecca7ac06,0x000d8eb52a4c2d59,0x00067d3099d75877}, {0x0005b00d48668cb3,0x0002755481aaf570,0x0000b8ddd277a751,0x000dd4573c6cfa3c}, {0x00075e83624bf68a,0x000ee89ee03e9ce2,0x0000000000000001,0x0000000000000000}}}, {{{0x0001adc31d17fe65,0x000ba5bb3a93b688,0x000b603dd9e8ce1c,0x0008b0cf4f5b70c1}, {0x000175f958dd3aed,0x00070f44e15eae25,0x000177aa5b942f5b,0x000302efb949c526}, {0x0002ba3a2c8dd115,0x000b89f9288a9513,0x0000000000000001,0x0000000000000000}}, {{0x0005972ebede20db,0x0005b1bc841aedc4,0x000933a99b87853d,0x000597276e1536aa}, {0x000a0238abf3c852,0x000485ab1105488f,0x0006d521debe07d8,0x0002f1ad18f16d6f}, {0x000d3c55a54637f9,0x000804a2b58773df,0x0000000000000000,0x0000000000000000}}} }, {/* digit=102 [{1,2,3,..,}]*([2^408]*G) */ {{{0x00085142795b0fc9,0x00032b75a8973a1f,0x000125d27c2f65e5,0x000245efb7e6ca7e}, {0x000a3d37a1c1d680,0x0008ed8871c0ac3f,0x000f92273ed1f61c,0x000f1c0619b125a3}, {0x000c151e1baaf99b,0x000b5fb9c92ca12f,0x0000000000000001,0x0000000000000000}}, {{0x000d45f1302c2800,0x00028a46eca65c4c,0x000181d940c2f16b,0x00008156dae561c3}, {0x000ffdb51b5dbdef,0x0007d0f3f05aff9f,0x000216756731470d,0x000d3e4323b09f64}, {0x000c256f1c5c736f,0x000c46af757ebac2,0x0000000000000000,0x0000000000000000}}}, {{{0x0008b99d3a5cf086,0x000a6f7dad9f189d,0x0009613956296f2e,0x00029ebaf5d410b4}, {0x000d4c6b1f46d86c,0x0001709ad92dbba6,0x0000cc09de07504b,0x0006c7c9ec95eea8}, {0x00007648647d01eb,0x000b3919b1d6cd99,0x0000000000000000,0x0000000000000000}}, {{0x0005f9f34e61ba7e,0x000eff53cc24a00a,0x000672781ea5e367,0x0005266f275cfce0}, {0x0009992d98139edc,0x0002c0efd50d9e20,0x000de18f3d9cb26c,0x000b647d23fe687b}, {0x00054a71ad97b9cc,0x00027a258eaff20c,0x0000000000000001,0x0000000000000000}}}, {{{0x0008f39dfcb8ed4b,0x000811922f1fcd37,0x000a2846f7edab95,0x000566857a64449b}, {0x0005d6755b91a9b1,0x00033e748b542e81,0x00055f4eecb18a57,0x0006c4663a3a4f59}, {0x00052acaf4bb5b32,0x00079a0d2cfa0bdf,0x0000000000000001,0x0000000000000000}}, {{0x000a0b89e0ca131f,0x000be75df1d52db6,0x000534480e6cb8fa,0x000be7af1d438291}, {0x000ad1a493673eca,0x000a16c7e34998f0,0x000d3ab56804db13,0x000479fc142bd461}, {0x000daa988aca4c3a,0x0001acd3bd93e84a,0x0000000000000001,0x0000000000000000}}}, {{{0x000cbad8f99ea394,0x000cf3fa23022a30,0x0009f3a186b0f3c6,0x000e922b33420e3c}, {0x000c1bffbbdb1dc6,0x000aa59cdeeac227,0x0003dd943d5b8787,0x0005513a5be5e367}, {0x0004c0fefae77a5b,0x0003518e4c10fcbc,0x0000000000000000,0x0000000000000000}}, {{0x00024505728229a8,0x00014b020fe0ed2a,0x00039e8625b5e8e9,0x000ac893dbd2dbf4}, {0x0002a5bf5b95c3df,0x0009c6d879c2cfde,0x000a75fca30a3152,0x000f3ac05ce905a9}, {0x000445553894b84c,0x000dc2eb87696cb5,0x0000000000000000,0x0000000000000000}}}, {{{0x000c1e6489e4e3ff,0x000e40fadb280ee1,0x0009bea8383ad81c,0x000e1b3d235f576b}, {0x000a3198405d1a52,0x00058352c1e2f66a,0x0004288cd9077fa6,0x000dbd50c9d00a90}, {0x0009bd9a7d893793,0x000b363fd16ecce4,0x0000000000000001,0x0000000000000000}}, {{0x00020eac52973702,0x0003e0c70e76207c,0x00006b2a996d0f74,0x000f4f6a44bb0744}, {0x000df28bc6807b4d,0x00017b088a4a4664,0x000ec1355d57eb8f,0x000182cf9ce6cfbc}, {0x000610a314e418de,0x00010173ffff5e3f,0x0000000000000001,0x0000000000000000}}}, {{{0x000165051d386e1e,0x000bd47b826f3a9b,0x000a1c2b86d2360d,0x0009b8835ea5cf34}, {0x0009783bb9260611,0x0002b789b3e982a5,0x000e987100210011,0x00097fc2b9ab3e6b}, {0x000ba0e81d76b916,0x0007fbcd1d8d4518,0x0000000000000000,0x0000000000000000}}, {{0x00091e776c559b38,0x0004c1e4fe7c517d,0x0006b3ca068cf1e7,0x0001a6fbc371e38f}, {0x0003b1539a3d7c5a,0x000cd0c3d50e8468,0x000c7e40ea4660b7,0x00012b9d873faeb0}, {0x0007f3ea3f2ff663,0x000c8c52e58fcf13,0x0000000000000001,0x0000000000000000}}}, {{{0x000e0d1c0e7b0a6e,0x000182d5a79223c1,0x0002d07160d41c08,0x000de95d46cca38e}, {0x0004d00dd9df759c,0x0001f3ff3dc94e0c,0x000ad18e4b33fc34,0x000d2cfdbdfdd807}, {0x000c70a120714770,0x0005cb86265c3704,0x0000000000000001,0x0000000000000000}}, {{0x0002e095e7588e93,0x000bb0fc7a7538c8,0x00049b1bf8ce184d,0x0006eac46bad884f}, {0x000da577205521af,0x00073592b9bc40d1,0x000dae6302c8fae5,0x000e9a408dc07f7a}, {0x000d86c203a973c3,0x000db4c1145f0edb,0x0000000000000000,0x0000000000000000}}}, {{{0x000b134fd6bc3c71,0x00030305a92256f9,0x0007ccfce0b23245,0x000ca36a6d8cb621}, {0x000236d0ef54fd61,0x000a182b1b210c1e,0x000e2c48ae4f2531,0x000aa16671b7b1f2}, {0x0001cf556d29f38d,0x0001c83fa6c8eaae,0x0000000000000000,0x0000000000000000}}, {{0x000a18df67396e49,0x000978a098406db9,0x000d15a5ed3d588a,0x0008786d781ea818}, {0x000c4ad06fce15e6,0x0006d7a550f98680,0x0004140981589bd6,0x000f7ff83976d3ff}, {0x00088eabc6ffe6df,0x00031647479f189c,0x0000000000000001,0x0000000000000000}}} }, {/* digit=103 [{1,2,3,..,}]*([2^412]*G) */ {{{0x0000d7e3378fb507,0x000c9bb0731c42eb,0x0005dc372a3657ba,0x00074ab3d967282a}, {0x00057f9ac8856a93,0x000b740967bdf210,0x0003024fec8274b3,0x00015596459a5693}, {0x000d21c1794a1687,0x000a98ef7bcfc7c8,0x0000000000000000,0x0000000000000000}}, {{0x000af7b9ab0a89f0,0x000a24bfd8b660f9,0x0009cb13ed97b728,0x0000fd15ee5e0227}, {0x000febd3b7d28a45,0x000367bf5b972ff1,0x00091b608f71ea2f,0x000f496276edaa41}, {0x000a6a4c152d016b,0x0000bf52e7daddc4,0x0000000000000001,0x0000000000000000}}}, {{{0x000ed176dc4c781a,0x000f2149979e6d8c,0x000b3c390a71d8f2,0x0009ec42d1cc9018}, {0x00013805d407dff4,0x00092c79f656592d,0x000250a69b4fae8b,0x0009ea40b75d7816}, {0x000e49fbb9c23c18,0x000630012080c698,0x0000000000000001,0x0000000000000000}}, {{0x000297ec2f3d27ef,0x0009b4394adc76de,0x000084a2dca39d2e,0x0004162fa4a3c98c}, {0x000de4df52d9fff5,0x0006af6c27847a48,0x00049729a4d9dcca,0x000b96ed3609128a}, {0x0002001168323c41,0x00051e81fed2290a,0x0000000000000000,0x0000000000000000}}}, {{{0x00023ceeaf6fda5e,0x000fb751aba8d27a,0x00058878762241c7,0x0009d28160069d96}, {0x0001830ade2dd51c,0x0001c3eb509b6317,0x000cb86f909879a9,0x000dee7eb48aca8d}, {0x00028bf799244bc3,0x0009202a06470538,0x0000000000000000,0x0000000000000000}}, {{0x00015f7fc2843df9,0x0002f53ba48f85a0,0x00095ae129c2b6a1,0x000ddb2a444e10a6}, {0x0006aecfba54d8ae,0x0007c39b4f0e8bdf,0x000e6010a72c4d1c,0x000d5cdfd0f373b3}, {0x00068c9e099b50a0,0x0001c8bed1929d51,0x0000000000000001,0x0000000000000000}}}, {{{0x000c2c46683ba5b5,0x00057c57128a2090,0x000dbf610a813452,0x000009fdd16c4a33}, {0x000c78f1d5b65bff,0x000560ad02b49af8,0x000ea450eb8499df,0x0003a52dc630fb45}, {0x000da8ac57e35202,0x000fb72fd6cb3d8a,0x0000000000000001,0x0000000000000000}}, {{0x0006d77839d10202,0x000f1f4a52a42a8f,0x0004175b2fd3f44a,0x000ac14905fe7f14}, {0x000701757d0c0079,0x0008ae6d1c475fac,0x000d56b7bfd93878,0x0001b7dbf13b33f3}, {0x000d1df20cacad13,0x0006098aef62c8eb,0x0000000000000000,0x0000000000000000}}}, {{{0x000224c02776a096,0x000fdf0428bd2668,0x000824486a9c4320,0x0009f3de8bb8cb98}, {0x00008a99c85515ad,0x00087cd9c5ea0fc3,0x00030bd0c213cb33,0x00075f7ddf36e0e9}, {0x0008b09a16a3e9e2,0x000ff92ba0c69ed0,0x0000000000000001,0x0000000000000000}}, {{0x000dd8b8dacd787a,0x00044526b1b4ed23,0x000c4fcde2872824,0x000a0aecc5884baf}, {0x0000edf7e8ded34b,0x000a4bc010f4ef7d,0x0007a006485cbfe6,0x000ba70311a2f225}, {0x00032199cd733758,0x000ee0992d474968,0x0000000000000001,0x0000000000000000}}}, {{{0x000d4dc4b29d1e7e,0x000ced039d3b8a01,0x000815590ff2c2bd,0x00021d5655ef3773}, {0x0006fddb06996f34,0x0006f2915cab4832,0x0005a14903f506e5,0x0004bd51fa3522da}, {0x0009df3d4ada1113,0x00041c2c8aabe985,0x0000000000000001,0x0000000000000000}}, {{0x000708b80fba1a02,0x00028b6a0afd8d60,0x00058773df43d0b1,0x000ecec358a258ce}, {0x0008b0ae7440af59,0x0000e74789fcab99,0x0007429cf7b8fd56,0x000584c72e545e3c}, {0x0001897264b148aa,0x000a07b9a2d9b131,0x0000000000000000,0x0000000000000000}}}, {{{0x000edce9ca1286ed,0x000ff3a46b7fad16,0x000535c9d7d2b840,0x0003708d5ca958c2}, {0x0005420c1e063332,0x000713a6fa0fa9a8,0x000918405a51ff70,0x000da85f855da776}, {0x000d1bea73da5e0f,0x00064183a6508fa4,0x0000000000000001,0x0000000000000000}}, {{0x00083d4f23ca730b,0x000725501529af4b,0x0008000d1b6d21a0,0x000a7b3eee3507cb}, {0x00022a88a07a33b4,0x000540f9d09c28e9,0x0004983b28faa40e,0x000f54edb432d0fc}, {0x000ce23569311803,0x000d266759b9bb64,0x0000000000000001,0x0000000000000000}}}, {{{0x000fd03e2a0c4500,0x000d5cf3f782f796,0x0003ffeae620bf4a,0x000ca0158514f603}, {0x000545633e085e39,0x0004884fbea88f4e,0x000882a85fc77f29,0x00012678c646f605}, {0x0009ba323a505f9b,0x00029223217b4379,0x0000000000000000,0x0000000000000000}}, {{0x0002e8744f4170bf,0x00081a29194f6c03,0x000a932a7916cab1,0x000fb0f9f60ec063}, {0x000ff217a0ff0b94,0x00003ea56b8f066a,0x000ed4a56ee8b26d,0x0005efbf8ce2c1ff}, {0x0002eb114ed13051,0x00043d7447433992,0x0000000000000000,0x0000000000000000}}} }, {/* digit=104 [{1,2,3,..,}]*([2^416]*G) */ {{{0x000affb50d183763,0x000c1c5fc7f37a88,0x000a1f73a2f170a0,0x0001192983474ff9}, {0x0006b4738ed4fea8,0x0004d293dcdd7868,0x0000cd916188a232,0x000bc585fd523667}, {0x000b67188a2e54db,0x0008ed10b37344d3,0x0000000000000000,0x0000000000000000}}, {{0x000548b086336003,0x000991fbe0b348b4,0x000ef3cdca5ad120,0x000cfcd2034c9a59}, {0x0004f56699960d16,0x0006df1f5f10f252,0x00000324733c5f1f,0x000a757f84ed98a5}, {0x0002f7eec2ce4fa9,0x000ae3d296f3ba03,0x0000000000000001,0x0000000000000000}}}, {{{0x0004e9382b32007c,0x000d81cd77eae7c3,0x00013604a2dad7f0,0x00043d13d0e3fde5}, {0x0004c6cb59871704,0x000a8441d1c5f3e6,0x0002361adfd909c7,0x0004efba78610053}, {0x0001559070eb9abb,0x000708ee4fe6fb05,0x0000000000000001,0x0000000000000000}}, {{0x00079200ca4f6cc8,0x000579128ad5ec75,0x000c265973749006,0x000f0a7f8cf2fa39}, {0x0002ddb548c37c9d,0x000da31069648b65,0x0006a7e075eeef13,0x000504d0e4093491}, {0x000fd613bea6b782,0x00055bba92eb2c08,0x0000000000000001,0x0000000000000000}}}, {{{0x0005ab4da4a4107d,0x000f0dbf85411a8b,0x000a933992a7b991,0x0000accdce47a748}, {0x000c5662f2eb8c82,0x00064b5fdd12508c,0x000db73adddfe6b9,0x000af97a44a31358}, {0x00044c5ddfefeaca,0x0003403a084f6ff5,0x0000000000000000,0x0000000000000000}}, {{0x000ad406fec21428,0x000e8954cddbeba4,0x00092a7fe19ec844,0x00084bffa4c49f5f}, {0x000ec8eb76b96304,0x00014948f0f75a70,0x000dff2c139503c4,0x00032fdf031b7606}, {0x000fa11a5ead6208,0x00047ef7a1eba7c5,0x0000000000000001,0x0000000000000000}}}, {{{0x00073a3dabdb3534,0x0006dd5d8f611c69,0x000799bf33f3f4e8,0x00026f63749fb625}, {0x00092667bd3584a3,0x00060fa9fea81613,0x000999ea3a8de550,0x0004dd75d71ac4af}, {0x00078319418b1e64,0x000c67e995c857c8,0x0000000000000000,0x0000000000000000}}, {{0x000c7afa552eb541,0x000a7222bb4a0732,0x000c7e0e1a608c59,0x00009057e1132506}, {0x0009c5c6a19981fa,0x00019205096b7bf3,0x000a7d38ab7490c4,0x00099e016ba7462b}, {0x00007f474dc3595d,0x0006636a3d8c9f12,0x0000000000000001,0x0000000000000000}}}, {{{0x000058d88f35f241,0x000a59b2e8d2532f,0x00015502597aca02,0x000fb1e8bd7d1caf}, {0x00055680e361da0d,0x000ed31cfd9355f1,0x00047c0b0064d2b2,0x0004f348830f3080}, {0x000b7440fbffaf7d,0x000a5a553b98e17b,0x0000000000000001,0x0000000000000000}}, {{0x0000f6eacb637570,0x000d4925881bc39f,0x000d655e7e9a7105,0x0002f09a033db883}, {0x000e97d5a4975dc8,0x000036e619a17847,0x00079d0e9b209304,0x000434fdadf80484}, {0x000412216e6c7daa,0x0000eb152f330b19,0x0000000000000001,0x0000000000000000}}}, {{{0x000362cca8e2db27,0x000b58fb4260cc2d,0x000e2d527b899614,0x0001f0b467cb8aa3}, {0x000d1ef71b82f08c,0x000dc68072c4649a,0x00098aa11a9313c4,0x000165002fbe1ac2}, {0x0000bf5399f23796,0x00024b537dfdd6e9,0x0000000000000001,0x0000000000000000}}, {{0x000f6c830ade2b53,0x00074af2e76469fc,0x00051f1bc5f4ed41,0x0000406c3a450f7e}, {0x00002b53708a683c,0x000428a6e3aa7dce,0x000c0df44b377b62,0x000e9c1a58f5f1ab}, {0x000c5458b0f02c35,0x000b16ea8718da27,0x0000000000000000,0x0000000000000000}}}, {{{0x000134d37c05c59c,0x0007233d57586878,0x0006cf5af7409f53,0x0008ae6dfc4fd018}, {0x000e8b54df4cc39a,0x0005f3046db1d402,0x000312aeece717b2,0x000da13a0c5d98af}, {0x00073d6305f96c47,0x000587c80a3e3a7f,0x0000000000000001,0x0000000000000000}}, {{0x00027d5a2516f5d0,0x000f9338bbf8fa7f,0x0002109c7d0c4360,0x0006004be57b26a1}, {0x000da32aad5aeeea,0x00041aa5daf9dede,0x000b0a16abc83073,0x000088080bdafdd6}, {0x0004fa8814cecd6e,0x000f5f24b2b7fe1d,0x0000000000000000,0x0000000000000000}}}, {{{0x000cc19d6d74494a,0x0009296d31ebaa05,0x0003edd43b02f30e,0x000c79aac72cbbb4}, {0x000d57829df3e827,0x0008bb62624e4cf8,0x0004f05ffe745fb9,0x000950b350aaad89}, {0x000ea5e2db566ef1,0x000e1e37f6dcf4f2,0x0000000000000001,0x0000000000000000}}, {{0x00034202ee7f3c59,0x000ed5d748da48fa,0x000e1cf505b68fd9,0x00031b86c7778cb3}, {0x000dbdadb45073af,0x0004b6e80bfe717f,0x0001ee413036b30b,0x0003482b138b2c3f}, {0x000e1ed1e4fc0159,0x000e84d788bd2771,0x0000000000000001,0x0000000000000000}}} }, {/* digit=105 [{1,2,3,..,}]*([2^420]*G) */ {{{0x0009afb73836ce2c,0x00035d1c0854627d,0x000acf6649f2eb9d,0x000acf4c38a8a9ec}, {0x0002178be52c0095,0x0008f6e06df7d7ea,0x0008285115ce7bb4,0x000b7f232680bedc}, {0x0004103a6e51e8f4,0x000aaa09aa0bc0d2,0x0000000000000001,0x0000000000000000}}, {{0x0001c4bc539f42b1,0x0009f1f757159ce1,0x0000e9e10c0bc8d0,0x0007345be3621884}, {0x000d1822e5e0a60d,0x000ae792acddc802,0x0006be0f49763d76,0x000dff0f1717868a}, {0x0004437867cae1bc,0x00070e8bfe19f269,0x0000000000000000,0x0000000000000000}}}, {{{0x0001b8994b02326b,0x00031ce496416ae0,0x000dc0825cea213f,0x00050bdf0281aa93}, {0x00059236853f9e44,0x00041e294dc8c09e,0x000b03a595c72a58,0x000c2bc6e5381e14}, {0x00020b03546b3008,0x0008eca57d1874ef,0x0000000000000000,0x0000000000000000}}, {{0x00051a61ce5948af,0x000925d36a169359,0x0001712f7655b84b,0x0002f3fdc1e05016}, {0x0009aa758020ba42,0x0006927405b02281,0x0009822fced2aa8b,0x00019ae63d9313a7}, {0x000d9c07887cbebb,0x00065e13e45febcd,0x0000000000000001,0x0000000000000000}}}, {{{0x00034f1f7e499842,0x000a48878049fec4,0x000692a3fe1f0c9c,0x00048261277fbbb0}, {0x00032263dc0fe7ad,0x000e09052ac6fec0,0x000683804d38aeb7,0x000d6c55fb1237fd}, {0x000bce4b453925e9,0x00056ac33e2d8263,0x0000000000000000,0x0000000000000000}}, {{0x000a764c5c6d3730,0x000ed9705b2adb70,0x0003bab4631b9f1b,0x00014535b4850149}, {0x0009c2385e82937a,0x0007aa5ebdcd9ea7,0x000656517e5b5eb0,0x00078fb6885fd321}, {0x00087f791c6b2bd8,0x000bcad44bfcfcce,0x0000000000000001,0x0000000000000000}}}, {{{0x000a7c1bbda99502,0x000d13ad86ee95d4,0x0001edd6edef741f,0x0001221485b8fada}, {0x00062b65b3c0a089,0x000583aac0300922,0x000ec2e6716727e3,0x0006d6729d8a817e}, {0x0002ad34233bfe29,0x000806779921dca9,0x0000000000000000,0x0000000000000000}}, {{0x000373f0b0bc37c3,0x0006835632a2bfc1,0x000a8cd4f472c2b1,0x0004b6c9a4cedeb1}, {0x00076180690c132a,0x000eca05f9fa510c,0x0004e0551eb02c41,0x000e63213fc52e0f}, {0x0001b429bb6165cd,0x0002bc1fdd188cd9,0x0000000000000000,0x0000000000000000}}}, {{{0x000629f7658d599b,0x000b1e87d39d0d52,0x000caaa997607dbd,0x000fcf23eb7d6dd2}, {0x000857e0cd30a02f,0x0003ecd22778d510,0x0005c5e961e1f158,0x00068aa70a145465}, {0x000c8fb1ff96ec7c,0x0009b464d2f55e62,0x0000000000000001,0x0000000000000000}}, {{0x000e904d20ac7941,0x000e4f0bec2602b6,0x00080f6effaef59a,0x00060688330793e6}, {0x000db2442ae08549,0x0005e3d773ff5a5f,0x000cecbc6ac0199c,0x00012fa7a795cacf}, {0x000d6f9bfc57e52d,0x000ce32e4eaeafdf,0x0000000000000000,0x0000000000000000}}}, {{{0x000eeeccbba2a7d7,0x000ad1d77ed0ffef,0x0005e752d769db74,0x00015b240b6200a7}, {0x000597b48ab8cfc3,0x000f97504538ef48,0x0005a2e980da41b6,0x000c0010c2010969}, {0x0007fe53f0d2b23a,0x000a1efe8b48887b,0x0000000000000001,0x0000000000000000}}, {{0x0007b952e8dd021c,0x00026e6b8cb163c9,0x000d62feeed16bdd,0x0007e3db6129cfd5}, {0x0009dcfa4489e9be,0x000f551707d804ec,0x00012a2adb1fbcf8,0x000c05be22830553}, {0x000c9f74b7d87937,0x0008d7e5edd3be33,0x0000000000000000,0x0000000000000000}}}, {{{0x0004b2f4546a8f7e,0x000d2a223a807885,0x000155358a6954ae,0x00086e4b30349ae5}, {0x000a5982c7a2aae1,0x0006ca4f6415564a,0x000013abb73fd2e2,0x00092d10cb063fca}, {0x0006104963b01aea,0x000bbcd0f1f68f33,0x0000000000000000,0x0000000000000000}}, {{0x00069aedbf43f1a2,0x000ebe1ef2c9b47f,0x0003246ee727e6d3,0x0003f5bd1a5a6120}, {0x000987e829b05fc2,0x000b70444c023806,0x000f0d6e903fa23f,0x000baba52743b14c}, {0x0009994d97e9872d,0x000a52cbf74f834a,0x0000000000000000,0x0000000000000000}}}, {{{0x0007ea3240feb8cc,0x000792ae77094407,0x0001201418e13db8,0x0003920cbc07e7f8}, {0x000aed56c93837f4,0x00013ae3d2a87da3,0x00044b8ddc44f1df,0x00069328fcaa2209}, {0x000b928d8e381964,0x0007313e55f26bee,0x0000000000000001,0x0000000000000000}}, {{0x000ec4f451bd8008,0x0007bdfe195b7e42,0x000e12b70e68b680,0x000159222b99f5fa}, {0x0000c4e0659127ea,0x000efe86909b5076,0x0008c58b9b667112,0x00047b7026cf16a3}, {0x0007373740ea01a9,0x0000153963989580,0x0000000000000001,0x0000000000000000}}} }, {/* digit=106 [{1,2,3,..,}]*([2^424]*G) */ {{{0x000546c7f70bcb2f,0x0007212027084052,0x00013f0d6d83c3eb,0x000eaca7142e7b62}, {0x00029f973a763019,0x000be00c2a025efc,0x0003eca6f6199ab8,0x0002b5618bcc0394}, {0x000b02749fbfb9ab,0x00013c0ae9ab795f,0x0000000000000001,0x0000000000000000}}, {{0x000f295b93c3d712,0x000bf1ab6d0e9f50,0x000bf53d7cb083d8,0x000d744e07076abe}, {0x0005a51a53561f29,0x000d647b915c2fc1,0x0009ead253f84287,0x000e91bd9d6251a2}, {0x00006dd74006b7bc,0x000c92c770e4efe1,0x0000000000000001,0x0000000000000000}}}, {{{0x0002703ae4d5c812,0x000427e95afaa341,0x000271961d1eb61e,0x0000fb71509a4412}, {0x0007bef04644ecf6,0x00044d4556d64abf,0x0002a7bfd03e651f,0x00094add4bdd9b05}, {0x000438d74bb2156b,0x000fa36c6c16572a,0x0000000000000001,0x0000000000000000}}, {{0x000ae16f96be2911,0x000d52afa2d73a0e,0x0005bc81a5a44951,0x0000fc89324d90b4}, {0x00018cab36337849,0x000cb411d87db838,0x00021f7d6cb710ad,0x0006ad26521480af}, {0x00094a666f370ca0,0x000375d8bc966e31,0x0000000000000000,0x0000000000000000}}}, {{{0x00082baa7d62ed15,0x000a2a0c35293a3e,0x00068a91eba6b63e,0x000715c2cd81a65b}, {0x000ed39839d20270,0x0001cd1c736c49a2,0x00023b8eae3fee67,0x000006012e0a11a6}, {0x0006b901f0657746,0x0003944e0864a739,0x0000000000000000,0x0000000000000000}}, {{0x00089e4689d04d8a,0x00060efa98dca953,0x000708ea3f1bf018,0x000f379e0740bbd3}, {0x000ab07cf1111586,0x00040f6bae4389cc,0x000c0c62ec14d78f,0x000a8ca2edc050cd}, {0x000eb9e22353ae3b,0x000221497d609a22,0x0000000000000000,0x0000000000000000}}}, {{{0x000dc15d0ed0cc63,0x0001ce35b540e1bb,0x000973de7aa979e9,0x0005e965745fa684}, {0x0008a999e957c84d,0x00071ead702675f7,0x0002beeec63eb2b6,0x00062262a9349f4e}, {0x0005b027fa151a2d,0x0005b45a63374388,0x0000000000000000,0x0000000000000000}}, {{0x000ade9fdcbfe121,0x00019964a13f4063,0x000ea6e576b23957,0x0009fa2021e1e294}, {0x000f93e8e8d0c1a3,0x000627a8aaeb1db8,0x0001c83a239f73f2,0x0009dc2704f34ba1}, {0x00053062be1591a1,0x0004c975cd21326d,0x0000000000000001,0x0000000000000000}}}, {{{0x0006b8fb25e6414b,0x0003f3c35210ef6c,0x000fcf4305218c66,0x00044c1aba52d092}, {0x000ad9ddbd46b892,0x000a630015bf7459,0x000b32b246737751,0x000ced081a65d447}, {0x0002e2e5f643a94b,0x00044927f131866d,0x0000000000000001,0x0000000000000000}}, {{0x0004645014a53592,0x0009ee4e5661d1ca,0x0009024d9b573293,0x000159f5f55c84df}, {0x000a0100b8c24f2c,0x0002de6a0aef0178,0x0009e7eedb7e96ff,0x0002067fc1f195df}, {0x000897eb377d8a42,0x000f1229a3daed81,0x0000000000000000,0x0000000000000000}}}, {{{0x0005287cf2f5961b,0x000cef9beb6f8461,0x000a7eaedc75201f,0x000d39dfabd8969f}, {0x0004252116284485,0x0002945b419a298f,0x0000f03b98d985bc,0x0007be292f990254}, {0x0007d1f59fb5c829,0x00002d379bfc2592,0x0000000000000000,0x0000000000000000}}, {{0x0001179af2527211,0x000f2724128932bd,0x000920719e949c7f,0x000f184c1ce441c4}, {0x00091d4d77a7c7bd,0x00086d6826d00ec0,0x000125b3901be8d2,0x000c6d7da5fd8de5}, {0x00084f0587b71c09,0x000ecbd13d8a200a,0x0000000000000001,0x0000000000000000}}}, {{{0x00034258888b309d,0x000da5700df117ec,0x000eecc1e03d3856,0x000d69afef5df311}, {0x000ced3bd1e65823,0x0009ca00a3d94409,0x00053de41e7eb569,0x00002f1291722236}, {0x000dbd2ee0ded7b4,0x000a909f40f6e980,0x0000000000000001,0x0000000000000000}}, {{0x00082d95c76e2f3a,0x0006d18779f8f974,0x000021eeb4e7e5b3,0x00070089298e7654}, {0x00003aa90b7f11d4,0x00020fd2c120d0de,0x000ddfdcf3b2e6f9,0x000134293b957e6e}, {0x000d5361a94456e0,0x0004bc62d97be2a1,0x0000000000000000,0x0000000000000000}}}, {{{0x00047691dfe1ac32,0x00095bb25141cf40,0x000cb8b02c59109a,0x000eb57046b0d286}, {0x000a8b7de816343c,0x000109a4f745b33c,0x000bf34e4de2617d,0x000950869270fe1e}, {0x000a3a1b01ca6170,0x00012e38634a9ad0,0x0000000000000001,0x0000000000000000}}, {{0x000f079109fbe1e8,0x00071bce15260c38,0x00059aca1efc1bab,0x0006c7ad5da68584}, {0x000030bec54d9816,0x0009a9c32e8f4612,0x0001154d88a51704,0x000ebe8180a7efea}, {0x00008abc6ec5ede1,0x000d7de0d26459ad,0x0000000000000001,0x0000000000000000}}} }, {/* digit=107 [{1,2,3,..,}]*([2^428]*G) */ {{{0x000019394140932c,0x0009a362bec3a200,0x0005ab884c7a2c57,0x000cab2ba06cf4c6}, {0x0003ee7eda004083,0x000107bb12f5f6cd,0x0008a0ae8649e92a,0x000a5a344683492e}, {0x000cfb24291fc3fb,0x000c3894cfd1718d,0x0000000000000001,0x0000000000000000}}, {{0x000751b1b1d1f30f,0x00043fce22373903,0x00023da45dac2f10,0x0000105df9307b4a}, {0x000892b6d1b2c311,0x000f645131b39e6a,0x0006331d8e317be2,0x0000b2f395de9046}, {0x000d56345f1e436a,0x0001b0547fe7481c,0x0000000000000000,0x0000000000000000}}}, {{{0x00078f4b7084325f,0x000727f8bc0fa450,0x0001eb36b7bf5948,0x0004268cea0106cf}, {0x000e8c80e06d4c70,0x000c216323300186,0x000b3016e94d5075,0x000d882e86c372cc}, {0x00048a28a053b8cf,0x000343d171001931,0x0000000000000001,0x0000000000000000}}, {{0x000c0287664ae003,0x0002766d8c63b224,0x000b8220989c0738,0x000b967cd418521b}, {0x0004152d761e7a59,0x000fa019e4601efc,0x000f11b41cb4d7c0,0x000dcac0131d9d52}, {0x000c991e4e27a162,0x000789975ffa76aa,0x0000000000000001,0x0000000000000000}}}, {{{0x000adcdaf64c0019,0x0002a5ef0c2175ba,0x0001cfec89a01d6c,0x000b25fa94296a25}, {0x00089c7ef16afeec,0x000c007e24585f16,0x000bbbc143cb4742,0x000531bcdafbbc24}, {0x000013773a99937c,0x000e19b7d849db6c,0x0000000000000001,0x0000000000000000}}, {{0x000e83417610eec6,0x000e934e9e9d81b9,0x000af4480e73d7b1,0x00086003aa3fea2a}, {0x00079c57f5c52d5f,0x000495c2aa9268f2,0x000922e4d082c9f5,0x000448a981d714f5}, {0x000bdf27622c6821,0x0001ae01e6436230,0x0000000000000001,0x0000000000000000}}}, {{{0x0007602120347ad3,0x000dd3e9ad407753,0x0002f89c76c52251,0x00044aaf5957d5e2}, {0x0006157c28051b58,0x00069eb597630bd3,0x000a387acac6af33,0x0002aad0ef875611}, {0x000ccba64de2edc3,0x000ff1731d170b0b,0x0000000000000000,0x0000000000000000}}, {{0x000557f665f21957,0x00064548e1ee52c2,0x0000cf955615f44f,0x0002bf2c64b6036a}, {0x0008d89213e751e5,0x0005aa570d34bd85,0x0005ae3bf1cb2e71,0x0003f29e703acc20}, {0x000a34a47fb1911e,0x00089578616fc498,0x0000000000000000,0x0000000000000000}}}, {{{0x000dc828f86252e4,0x000d09ec8dfb2555,0x0005077092f2430a,0x00078d5b0c56862b}, {0x0002f9b2b116f869,0x0007b998e4dcbf23,0x000fbcf91af3491c,0x00056f1110038af4}, {0x000e0888ba8f38ec,0x00043daf07963a9c,0x0000000000000001,0x0000000000000000}}, {{0x0008da925a008487,0x0004f369188e0311,0x000ec8e641278107,0x000a270db9969754}, {0x00072aaa78c429c9,0x0001a344c1da5196,0x0003087bd58c2f7e,0x00088aeffcfb4dad}, {0x000fbcec5f2532f6,0x000a809230f905b4,0x0000000000000000,0x0000000000000000}}}, {{{0x0000b4a0ddb8dfab,0x0009deda0e27481d,0x000949ab745b2f9c,0x000dc2842dbe3df2}, {0x00059b98be5c35da,0x0002ed3249c0c912,0x000dc475c0841958,0x0005a3cc60128529}, {0x000078110f67e016,0x00017fe4fa3624ca,0x0000000000000000,0x0000000000000000}}, {{0x0006abd2bfebf71d,0x000617fcd7e4413e,0x000ac8bf7c39197b,0x00022ac8be897f87}, {0x000878bd60d51691,0x000ed69bb2587c48,0x000a51aae1defc49,0x0003d1f77705c7ae}, {0x00021ab01c739c3e,0x000801dacd9f17c4,0x0000000000000000,0x0000000000000000}}}, {{{0x0002a912967cbb3e,0x000f46687e4df221,0x00007e4eef350ebe,0x000e38a4de052972}, {0x0009d5282d27fb20,0x0006e64b3686af97,0x00067350cb71692e,0x0008437b220d3baf}, {0x00042c826bce6850,0x000642d60e139b00,0x0000000000000000,0x0000000000000000}}, {{0x0004eb43ead3cd1c,0x0007d1cbedb5fe6f,0x0001b45fb1ca7933,0x000a503cea7b46bd}, {0x000fef3868c8b110,0x000f9fe2cde99fc9,0x0006dd89f348e20b,0x00022d25b6cd54cf}, {0x00051adcb2128528,0x000ea79e7afb9c6c,0x0000000000000000,0x0000000000000000}}}, {{{0x0001fc12e7ca5055,0x00025e91d6adbf30,0x000587a0d31dc42e,0x000cc8a9cecd10d8}, {0x0009d8d1b41ccf88,0x0003b3f96490bd95,0x000e028999c5a513,0x0004c3a0882547be}, {0x000fc3438b39f5f7,0x000fa75af39ed4d4,0x0000000000000000,0x0000000000000000}}, {{0x00002b54c1f9ad9d,0x000dbd0a29ee5fbf,0x00057045bbc4f0d6,0x0000fce2e6fde293}, {0x00033040027dfc7d,0x0003be51ffcda45a,0x00054869841c14d2,0x000156ff1e336d04}, {0x000a634d9fdc8522,0x0003ae619b696b5e,0x0000000000000001,0x0000000000000000}}} }, {/* digit=108 [{1,2,3,..,}]*([2^432]*G) */ {{{0x000019f2fc6beb7f,0x000666646b70deb9,0x00090a5717d2e533,0x0006810fd38f5274}, {0x000233bb33bad791,0x0009b6b88efd9526,0x000d5745dad71c05,0x0004ca300788fe6e}, {0x000ed4a6a21a98ac,0x000e10eeff58916d,0x0000000000000001,0x0000000000000000}}, {{0x000da52e803a67cf,0x0007d398c1a5fc48,0x00042b185c01901e,0x0004eda6cb2700b0}, {0x0004eeec867cdaca,0x000dcb7e930a19ae,0x00010a288471dcc7,0x0003198ed17517e0}, {0x0004e8756bb36f68,0x00027df915ed36bb,0x0000000000000001,0x0000000000000000}}}, {{{0x0009d95ae2bd1168,0x000fb9d6f73873c0,0x00027b3bc9e7cafd,0x00005fa81f14d40f}, {0x000ed4eebf4e66fc,0x000bb6036a4e6b76,0x0009e3f736cb7387,0x000b2277b08a58e1}, {0x00055c0d7a4986be,0x0004d18f830adabb,0x0000000000000000,0x0000000000000000}}, {{0x0005e59f982356bc,0x0000599a3ae563b2,0x000d06e16bf18997,0x00088dac7505891e}, {0x0004c76b3eb973d6,0x0006498b2d10cb08,0x00074af2d6e8e95c,0x000a503f71b8afa5}, {0x00066999bc16133c,0x000bd76f3443fa99,0x0000000000000001,0x0000000000000000}}}, {{{0x0009cc5a1fdf300d,0x0000ede5aa101a8c,0x00053342a7d32907,0x000bb4fe852398fa}, {0x00036673ceb9c007,0x000c9247b3a94312,0x0001ee51cb682683,0x00075c07f2ef115b}, {0x00083b0143f6486b,0x000d101585ec3771,0x0000000000000000,0x0000000000000000}}, {{0x00080da54d84cedc,0x000e569a2e8c0006,0x000e94c0472e41a7,0x000a41c1b7c713ec}, {0x000e5742d18ccf2a,0x000df3c3763e3162,0x0006b9977417a84e,0x000f165b44c75791}, {0x00045d988246f2e2,0x00095c8287828d1c,0x0000000000000001,0x0000000000000000}}}, {{{0x000f9c015fdb1c06,0x00099f25767d4418,0x00077c536b749d61,0x00054bfdb54e847b}, {0x000237979776c1af,0x0001eefa220b8386,0x00018acdf9bb4a75,0x0008ce45beb5028f}, {0x00030f98a7dd8621,0x0003023f055e3ab9,0x0000000000000001,0x0000000000000000}}, {{0x000f321b72c7f6a2,0x000659eeb57c141d,0x0000b2255cf53902,0x0009dbecf2a776fd}, {0x000e6453cf8ab4cc,0x0002d5647863e94e,0x00049fe93a4007af,0x00039cf116d00271}, {0x000dc8184a637605,0x00061de7465f7317,0x0000000000000000,0x0000000000000000}}}, {{{0x000dae8508371ab1,0x0009f5759cf42671,0x0001705cf63d991b,0x000e90ca5edd0265}, {0x000af5c715a86e95,0x00096331dd94a89f,0x0005808565c73b46,0x0004c9ca8a595723}, {0x000561170be646eb,0x000a57b5fc879ce5,0x0000000000000000,0x0000000000000000}}, {{0x00080540adb44437,0x000abb97c57c16dd,0x000be7baf4488307,0x00019e753dbf21d2}, {0x000ac5be29dc51e1,0x000df21c9ad3cc57,0x000a9aa74fbb9193,0x000a11ec7b8e665f}, {0x000c01bfce350115,0x0009909f2c73b53a,0x0000000000000000,0x0000000000000000}}}, {{{0x000744ab95b71183,0x0005aa6c81566c3d,0x00033310fbbacd74,0x00006a2dd55a7d6d}, {0x0002db05de914221,0x0001ffd4282301fd,0x0008cf7489b2de85,0x000c6f0a02baf309}, {0x0002ce9af0a85604,0x000261197b0884c2,0x0000000000000000,0x0000000000000000}}, {{0x000e2c60da7deb89,0x0008d4b2f2e54489,0x0002e5dee75d5785,0x0005e0e953899934}, {0x000ecd968f2eb742,0x000229cbd8cbbbd2,0x0008dcc6b871d5e3,0x000490c7582e68a9}, {0x000cde3999720429,0x0005eaec58ffb639,0x0000000000000001,0x0000000000000000}}}, {{{0x00028ab59549216b,0x00005d61d82596b8,0x0009fa679fcfc930,0x000ccf438ed2cad9}, {0x000a40190b3069f6,0x0007f5af4bb6d49c,0x00002f9e7c50f6a7,0x00019940efdd8671}, {0x00002add96c554a6,0x000e007d80786684,0x0000000000000001,0x0000000000000000}}, {{0x000ad0fb54ef0a37,0x00046af5d15fc57d,0x000b825452e8ccd9,0x00044232c710cb6b}, {0x000cf88855ecdc6f,0x0001d6d2b8f40b3c,0x000436e2bc3e510d,0x00007b1ff42aeddf}, {0x0000ed88484552b4,0x00075c1505c18430,0x0000000000000000,0x0000000000000000}}}, {{{0x000a55f734e8c16e,0x00026ef042fa2f6e,0x000b24c1848ab1d2,0x000acbe86862a1dd}, {0x000651f4168e7413,0x000d596e07914083,0x00079ca23961d189,0x000e6d53679701b3}, {0x000cf35fa05ec7b7,0x000d20d7f6b70713,0x0000000000000000,0x0000000000000000}}, {{0x00018785b4c707b1,0x00038676095f2dbc,0x000e28a0370a0054,0x000af09e50c89610}, {0x0000f144bba0bfee,0x0004cf6dd7455cf1,0x000e722f509d9783,0x000b05c279e5f94f}, {0x0001244fe8092deb,0x000153b314f061e7,0x0000000000000001,0x0000000000000000}}} }, {/* digit=109 [{1,2,3,..,}]*([2^436]*G) */ {{{0x000803868bfafe94,0x0002ddeb7719717f,0x000911e1ad005b4c,0x00076f1e0df34f87}, {0x000b29958d5da570,0x0005d1ebf66f49ec,0x000f5712ca7b49e5,0x0005b2ff1b32fcb4}, {0x000f97d3d42a971c,0x000804838bb32749,0x0000000000000001,0x0000000000000000}}, {{0x0002e7908789eb65,0x000af786529c3ba5,0x000e71594737ddd9,0x0005400f6dd64d51}, {0x00039922bf016830,0x000db4bbaa21ca42,0x000935d8c94ee851,0x000c80623440afda}, {0x000110efc0a576c9,0x000396d79f58dcd9,0x0000000000000000,0x0000000000000000}}}, {{{0x000b38ccc9df95f7,0x000d1849ee6062ae,0x000164333dec1411,0x000e81b4a4a4727a}, {0x0009c74b241dc566,0x0005069fb7290aa5,0x0009d322865cb6d8,0x000ecbd648392838}, {0x000909864ce3c8f7,0x000ac9fef248d28c,0x0000000000000001,0x0000000000000000}}, {{0x00061d435126259d,0x0005a6b96bec8542,0x0001f509bbc62a6f,0x000ddbc8b43f9c90}, {0x0005e94118466c53,0x0002a386779ad388,0x000db58d109dd2e2,0x000aeef4f2af60b6}, {0x000bc0cd7adf1adc,0x0008220fb47811d5,0x0000000000000001,0x0000000000000000}}}, {{{0x000f1b4d9b2b9d58,0x000635d4601e4549,0x0005712ad28d37e9,0x000e19b42c3143dd}, {0x000fdc6366f04af7,0x0004b34637aa565a,0x0005b2ac12b452bc,0x000277fe7f5bdd13}, {0x000c6ff31feea8b4,0x0000c45cdaec8e9e,0x0000000000000000,0x0000000000000000}}, {{0x0007813178366af1,0x000e83664c221b3f,0x000afac4ecd652c3,0x0007c4666da93d03}, {0x000652ceac0d6cfa,0x000b1a4cf4039d2b,0x0005c58a6eb1946c,0x0007422c9b53a228}, {0x0007349ed1b4d836,0x000afa4c55a379cc,0x0000000000000000,0x0000000000000000}}}, {{{0x0009ee173ac4010e,0x000fb942f467a4b5,0x0005770a30141b66,0x0004198802513df6}, {0x0002c7e0148f2f1d,0x0009a1b6c6f54abf,0x00056f2bb47b51bd,0x0004f5846505fba9}, {0x0002a3ddcb02618f,0x000a7b69ec8c6450,0x0000000000000000,0x0000000000000000}}, {{0x0004b69533aa9231,0x000b0804316d8f19,0x000006107c58f7bc,0x000310f29f43afd0}, {0x000e7a15ea5dc32f,0x000849a363e2b91a,0x00074452b4966c63,0x00071d63455b6a45}, {0x00039b535b8835c1,0x0005091ae86f54cd,0x0000000000000001,0x0000000000000000}}}, {{{0x000de1ec8614daa5,0x000f0834c4db4a7b,0x00048a29f6ba70a6,0x000be231587d1015}, {0x000bb998c9a2049d,0x0005eedcf88aceaf,0x0008878e6b738f7e,0x00019b693ecfcab0}, {0x0008dd1ddb374ede,0x0003be7a6cd94f00,0x0000000000000001,0x0000000000000000}}, {{0x000bd130c16a2f12,0x000343c20757ed83,0x000228e06b217bff,0x000046a91bef19ad}, {0x000400e88da5cc51,0x0000a9f961011b58,0x0003f9049ae6f047,0x000e9d079a03c6f8}, {0x000401435912f072,0x0007490b78fe3f9a,0x0000000000000000,0x0000000000000000}}}, {{{0x00081fdfff4245fc,0x00050168c14a6614,0x000764d4d2b84edc,0x000aaa60be356501}, {0x00030e6771588736,0x000714d50c0c40e3,0x00029157b8fe8875,0x000a9215aac4fbdf}, {0x000b4091b549e25d,0x0001ad442d2b0058,0x0000000000000001,0x0000000000000000}}, {{0x000ee6a91c584138,0x000d84934568ba88,0x00010dd1585307ef,0x0009b046cb644b24}, {0x000dc2bd376e1321,0x000cecc49bef0c68,0x000f76556c2d2d1d,0x000d810f8810c907}, {0x000a20da5052b3dd,0x00079ec3448a3c1b,0x0000000000000000,0x0000000000000000}}}, {{{0x000084366f4dadcf,0x00087f5cc0a55e0e,0x000a139c3fe7ef01,0x0003f2e749d53f7b}, {0x000ffd809a727542,0x0002e74f9e5a94a4,0x0001929541f08d0e,0x000114dd07932254}, {0x000f53ad14915984,0x00078a408f5bb7db,0x0000000000000000,0x0000000000000000}}, {{0x000b74adedde4d64,0x000eeb46e287111d,0x0001ad3605f3b22d,0x000070fc8863541b}, {0x00093fdd530f51fe,0x000f3d69c04af47e,0x000f551d93cb6477,0x0002bc684cde6d16}, {0x000154a9f50cd685,0x000e9f16ac0cc2b5,0x0000000000000001,0x0000000000000000}}}, {{{0x0006190bccf09089,0x000de2a4a386bf1b,0x00095703cbb17c47,0x00013d223bf84891}, {0x0007a124742673f0,0x000290f2b86fdb82,0x000f44e50e9b7e10,0x000ecc65826079a8}, {0x0004d12b589a9228,0x0001b683a119d1ab,0x0000000000000001,0x0000000000000000}}, {{0x00025950f93cc637,0x000b7a6b02229a2d,0x000fb0617d538c46,0x0001dd7b6bc581dc}, {0x0005b6b522d590ce,0x000133e3f5d0dcdf,0x0005bdf5cce47e79,0x000e21b8ecd0d71f}, {0x000ac21b717d9aef,0x000b887b6090257a,0x0000000000000000,0x0000000000000000}}} }, {/* digit=110 [{1,2,3,..,}]*([2^440]*G) */ {{{0x0009fcba235d8a1e,0x000ca359a63f98f8,0x000f60025c086d07,0x00018d4e590915cb}, {0x000c915cc7c3b68c,0x000933480185575e,0x000511ae8d10d820,0x000082704b904789}, {0x000a4e997db2e76c,0x0008c3f5824d99f6,0x0000000000000001,0x0000000000000000}}, {{0x00053628d8f32dc9,0x00000ea757555069,0x0008537e14185044,0x0007f7a0609d8295}, {0x000c55da70118c7b,0x0009ad1223c50379,0x0008629c936f6ea7,0x00054f7f839cbde4}, {0x000f8def61ba0172,0x000f5c1bef09ebdf,0x0000000000000001,0x0000000000000000}}}, {{{0x0002eeedc5fe3f41,0x0004f9330d665ae8,0x0003f5e64a30753a,0x000e92f39e477096}, {0x000aa07f9d297ef9,0x00048c3ddf388062,0x000e61e60ab0df5c,0x00095a47567e55e6}, {0x00066d0129872a6f,0x000953425f368c3a,0x0000000000000001,0x0000000000000000}}, {{0x000b7cc7bf66ffa4,0x000f16b2825eba03,0x00090e67535ba3ce,0x0004aef14aec5704}, {0x00001511ac67bcc3,0x0001002739d95c0e,0x00029220f4f36575,0x0001465557ab45e9}, {0x0009abecf1baabf9,0x000fe98337c9760e,0x0000000000000000,0x0000000000000000}}}, {{{0x000025751d2b325a,0x000cde6a01039da1,0x0005ba8462228499,0x0003490747232500}, {0x0001a523417ab4da,0x0003451baf54b07c,0x000516f3fa7e4ffd,0x00042fbff2147ce5}, {0x0003f1b0afc522cc,0x000cb395c7010ca3,0x0000000000000001,0x0000000000000000}}, {{0x0005ed5f55af51c6,0x00015b980e568466,0x000a5a1b30bd5964,0x000bb04e8834a37b}, {0x000becf282494fee,0x00040dc6ceb29d17,0x0004a868d5399a53,0x000276012bcea50f}, {0x000c769aa83faa31,0x000d8e6550a0654b,0x0000000000000000,0x0000000000000000}}}, {{{0x00066fa0ef4dbc14,0x00071d134a53f7ec,0x0001ee39cdaa7b28,0x0009b3f183070c04}, {0x000c76da77991974,0x000916f1eb867841,0x000b27421e5438ae,0x00051b0e12d8e409}, {0x0005e08b83842a6e,0x00094374b9e008de,0x0000000000000000,0x0000000000000000}}, {{0x000a4cba763a6340,0x00013308e07acdfe,0x000db2143a906789,0x000fe6dd815c887a}, {0x000e2a9d2043c85f,0x0003ceab79a68d05,0x000986393674d33d,0x000d12ee73ca7a8a}, {0x00003b9bbd54b7af,0x000b702eead11264,0x0000000000000000,0x0000000000000000}}}, {{{0x0000b987f57f80d5,0x000d4367c06145fa,0x00034438e79fd55d,0x0000f9f8e8ca9c52}, {0x00036810f12c2fad,0x0003ec5af1a97a71,0x00085613d0eababb,0x000aecb3da01b7b5}, {0x0000150798aadf26,0x0008029cce9cadbb,0x0000000000000000,0x0000000000000000}}, {{0x0005a72e54383960,0x000decd025e95126,0x0005b2c914390e3d,0x000864784955e972}, {0x0008cdae63ed0053,0x000aa5ded860c28f,0x0001dd80fb99e774,0x00020f07854bb74c}, {0x00091581c2caae0f,0x000d48069f6ba766,0x0000000000000000,0x0000000000000000}}}, {{{0x000f135836126647,0x0004208b738df6f5,0x000786c7341e91f4,0x00084ed91ae2188a}, {0x0000b08e3293bda3,0x000e09af3119b1a0,0x0003662652676669,0x000fd07b9f37322f}, {0x000ae129d764ea40,0x000b85c16a911b11,0x0000000000000001,0x0000000000000000}}, {{0x000021aec95ad18b,0x00080eeb3197c759,0x000dfd4a4334daed,0x000ff78d606234ad}, {0x0003ff98a1d73ab3,0x000c9cac669f90a4,0x00063cf99bed1762,0x00028f03fcd45e80}, {0x000b17bf750672a2,0x000879027e080bfd,0x0000000000000001,0x0000000000000000}}}, {{{0x0006a647cfcf8e23,0x000d745dafe04723,0x000c3212b4d30081,0x000945780f548f13}, {0x000a0d885e14f51f,0x0006ed3092941059,0x000651e189c478f0,0x00007a26e8c75042}, {0x000a14b52f36b6ee,0x0001a032dfdec009,0x0000000000000000,0x0000000000000000}}, {{0x0008ca67379eb582,0x000b6f527f0a50be,0x000adaba76e4c6be,0x0009b987fc7fd1fd}, {0x000a047c90091990,0x0006d6f45b992155,0x000e37e2da697e00,0x00011a38bcd1740d}, {0x0009b93e8ce3867f,0x000b60503be8b250,0x0000000000000001,0x0000000000000000}}}, {{{0x000c16ca71ab9de2,0x000d4b4d3bbd16e8,0x00053785c45519f4,0x000fab776454947e}, {0x00019d9b9416f1aa,0x000337e34e6883b4,0x00041570208ba8ab,0x000cab67774a7e58}, {0x0008ac5165a84d18,0x0003a977b69d3110,0x0000000000000000,0x0000000000000000}}, {{0x000e5bcfd652943f,0x000743cd5e892a91,0x000502744c85aa27,0x000bb91ba0414bf5}, {0x000f8bc4ef773e26,0x000f9e301b8bcd45,0x00028983589038c8,0x00019a5f5e5a30d4}, {0x0005c6671a609f77,0x000a3aade09eb4af,0x0000000000000001,0x0000000000000000}}} }, {/* digit=111 [{1,2,3,..,}]*([2^444]*G) */ {{{0x0008fa162e0dbf60,0x0003f486c08a442e,0x000d94f9cd2b15f8,0x000f2a2350bb6a89}, {0x0005b606cc5727bb,0x00003f198a74b132,0x0001a6f73b79d3ab,0x0001c95046a9cf73}, {0x0005ed71e298efd1,0x000274d622bb2409,0x0000000000000001,0x0000000000000000}}, {{0x000c383b3b59eae1,0x000e81b2f1927508,0x0000d888be6e14de,0x000fb612ce4b12e8}, {0x0001378248f53213,0x000330dbca43092c,0x0009ef5e40c52b24,0x000e9d869889952b}, {0x000c05f4131f1126,0x000503fd03ae1dfb,0x0000000000000000,0x0000000000000000}}}, {{{0x000868b8bbdfd1e3,0x00069e244e266c6e,0x0007c7bf40b05a43,0x0003b7e1e296776b}, {0x000e22cfd9c18aed,0x000ea90d63ddbc31,0x000929198abb7bc1,0x0005791f36a5e50b}, {0x000737c71c2f87e5,0x00024f75c6d8e7fe,0x0000000000000000,0x0000000000000000}}, {{0x0004c9eb7d596ad7,0x0001e1a0fb486ad5,0x000d820f02c91d1e,0x000160179160a67f}, {0x00057f1163f25e5d,0x000cbc9a928b61c5,0x000df9b84ed79f2f,0x000854ba69556a33}, {0x000c5cb8ac8febe1,0x0009a7ec5a344343,0x0000000000000001,0x0000000000000000}}}, {{{0x000a1f2d5d90dce2,0x00048086d7fdecb8,0x00005e3d618ccc17,0x00081c1e93d5b7f5}, {0x000a9cc469c44a02,0x000561bd59d9df3b,0x000788578aa5fba5,0x000f6a295757cdc7}, {0x000387a16bd50e1c,0x00029d1a6695b773,0x0000000000000001,0x0000000000000000}}, {{0x000b40770bcc13d9,0x000a0b4cb7c0701f,0x00058a0433c71ad0,0x000e93cd5406bd3d}, {0x00098c999eda26c3,0x000092f416481951,0x00047a1b9bfd4b10,0x000f450e0ae46263}, {0x000aa14d201a717d,0x000a1f0cadae7402,0x0000000000000000,0x0000000000000000}}}, {{{0x00025a8ecef36f15,0x0000495828c615a7,0x000ac113424f603a,0x00042c1687a77e81}, {0x00098761c2762346,0x0009b1a4749d0db2,0x00097828ac3391f2,0x0005050c5b69143a}, {0x00078b0a25ae0092,0x000d6c144730edc5,0x0000000000000001,0x0000000000000000}}, {{0x000bfa3844e6437c,0x000f55606aeb933b,0x00097e413566e3da,0x0001c1ae4263527e}, {0x000823a0378934ac,0x0002143f588c3363,0x00027262bb7d997b,0x00082419935b6941}, {0x0004eeef99cb555c,0x0009b82ef7f7cb72,0x0000000000000000,0x0000000000000000}}}, {{{0x000f0062dfac9c48,0x00002d81a18ce131,0x000ddcf23a0713ab,0x000a1fcdc4c43fef}, {0x0007bce6f244518e,0x000ad87348b34742,0x0006967b2b850180,0x00045248a8e5aac5}, {0x000029c18af90606,0x000027d44e26ac08,0x0000000000000001,0x0000000000000000}}, {{0x000cb47b7d6fa01c,0x0000fa06669eb12a,0x000ba3426d87d938,0x000cc362d25b1811}, {0x0005c938c9a5e9c2,0x000513be5311d61f,0x000c741f99e49306,0x000858e6ea44630f}, {0x00001034df68ea15,0x0009fda601eea831,0x0000000000000000,0x0000000000000000}}}, {{{0x0001335ca463c947,0x000056d6526151f8,0x0003c494f0f999ff,0x00082dc10a7433ca}, {0x000067fa3bcdc41b,0x000c803bb39af11e,0x00031fc0ac7bb35e,0x0005b5e185aa457b}, {0x0006ab2cbed55591,0x000c973304481958,0x0000000000000000,0x0000000000000000}}, {{0x000c07b3b2112108,0x00057bae813666bf,0x0008eee1f424f0a9,0x0002122582cf0958}, {0x000314daeb7bdc33,0x0004de4e23458ec0,0x000a768d0f97884e,0x000a1655c201fc50}, {0x000f1a537b424f36,0x000a6c0cdff48114,0x0000000000000001,0x0000000000000000}}}, {{{0x0007e2caf6bd29ac,0x0003376357d313a7,0x0007372bec99c462,0x000dae50c449ad64}, {0x000a9851fff00473,0x00047fec5d20efdd,0x000826de033e859f,0x000f46311785804a}, {0x000104e3184caf5e,0x0001ecedcc25e31e,0x0000000000000001,0x0000000000000000}}, {{0x000e47c0beec6da0,0x0001b1920715db74,0x000ae32e6188b124,0x000b5dfc6ee77c87}, {0x0006b132638e4040,0x000b86b665e1c6f4,0x00028fe14b060006,0x000b71efffb869b7}, {0x0006eab86370f188,0x0003e80379ec88c1,0x0000000000000001,0x0000000000000000}}}, {{{0x000f8cb24f3b637b,0x00076af131c20322,0x000815ccfff0c2b0,0x000fbdbff056364e}, {0x00060c8028853dbd,0x000af0ee0841ab57,0x000da56ca93ac088,0x000d301350923094}, {0x000228a255054010,0x000a058e7dde6774,0x0000000000000000,0x0000000000000000}}, {{0x0005176aa5c512c3,0x00020d3779fd868a,0x0007658fb3dbe164,0x000cf13041f45c5c}, {0x0005049dea64d110,0x0003f6746e19e0e3,0x000a39087ca45757,0x0008108ab4e2fe7d}, {0x0009cce4e874c545,0x000b791d64965ce3,0x0000000000000001,0x0000000000000000}}} }, {/* digit=112 [{1,2,3,..,}]*([2^448]*G) */ {{{0x0001f7c72b336855,0x000f76e247b483cf,0x000202781dc97b6b,0x0005bb58c0f81747}, {0x0000c92efba888b6,0x0009612af59611a6,0x000ccbeaf54a57cd,0x000ef8689ba520d7}, {0x00091cc366d3cbf9,0x000056dc1abfe905,0x0000000000000000,0x0000000000000000}}, {{0x000a04beccd53894,0x00021b1e600b02d4,0x0006c3ebe8f2a150,0x00007cfe9586be60}, {0x00062f4028af5b85,0x000d392e8954dda7,0x000dadc519d37584,0x000b58c3813ebde8}, {0x000557ce681db641,0x00006323fa3b9991,0x0000000000000000,0x0000000000000000}}}, {{{0x000327209a17e11d,0x000d294da0ba85ba,0x0002e3b7145fac1e,0x000fef1248cf218d}, {0x00034de112f175cb,0x00094a8f1676f3e2,0x000f9c2657870861,0x000518958d56de1a}, {0x0003dbcba495c76a,0x000cbfa5e9c9c9dd,0x0000000000000000,0x0000000000000000}}, {{0x000fcebaff9f1e95,0x00070930a1b712b1,0x0008296f1f273d82,0x00071eddfa6e1f41}, {0x000af7dd190815ef,0x000f6fda9bc4a2f8,0x000482585b1234b2,0x000e23556036541a}, {0x0001ac1cc79e6b22,0x00079988ea71f991,0x0000000000000000,0x0000000000000000}}}, {{{0x000a9c0f0a888100,0x0007d24e7957d723,0x000347cf9592bff9,0x000365bb77516430}, {0x000532639eeab522,0x00075ffdcf80bee0,0x000715b06a25a527,0x000f841be2cacf87}, {0x000bc301ef1a4c9c,0x000be09159817e68,0x0000000000000000,0x0000000000000000}}, {{0x000ae077a00f18c6,0x00066d4baba09883,0x00026a600e57c245,0x000d614baadec7ac}, {0x000df9f1c7a24538,0x0006e61c4241b694,0x000e25d7cba200ff,0x0002e6c811de028a}, {0x000a7a2ca09bc137,0x0004b214e3d38684,0x0000000000000000,0x0000000000000000}}}, {{{0x0002cc5d8d86efa4,0x00086c8ee779a0a2,0x000fd2159545dd5d,0x000c7262fd5e2c81}, {0x0008275f13cf7ab1,0x000759a0b74f36ad,0x0003c0c8c3ddc91e,0x000d10948a51d222}, {0x0007160cf9b2c7f7,0x00060f285822b597,0x0000000000000001,0x0000000000000000}}, {{0x0001e962392851c3,0x000b50d7c127ef1a,0x000d984c5287e5e2,0x0005ce7d3999dfdf}, {0x0006fd1373907aad,0x0007f8f0825c8472,0x000b5c55ebbc32d9,0x0002bd51b3a068dc}, {0x000935287a1b4f59,0x0006c8f3eb9dca36,0x0000000000000000,0x0000000000000000}}}, {{{0x000e20e45266c880,0x000d20d089ee45a2,0x000924531cdc6e8e,0x000f7ce2e1fa4436}, {0x0002517f9a18e676,0x000d570398bec610,0x000dea4d0f9eb1c1,0x000c9914ddf30f65}, {0x000cb21d0d421e9a,0x0002d38fb5fd0304,0x0000000000000000,0x0000000000000000}}, {{0x000db46cd0b507ab,0x000ba53f3ce83b8d,0x000a8aca81c50a03,0x000245a83198cc38}, {0x0008bb4ffb6faabe,0x000c93601934e1ba,0x000061b676968674,0x000710e9ebcf5033}, {0x000185f4475389bc,0x000687b9bd9763f5,0x0000000000000001,0x0000000000000000}}}, {{{0x00029514447f1de3,0x000d950771604321,0x0003a8cfdfffb078,0x00022ba412e08811}, {0x00097ef9f248a108,0x000b82c1196accaa,0x0001f8d1787041bc,0x000ec8430565e6d4}, {0x000eacea7ff3e1c3,0x000896b9bec2206b,0x0000000000000001,0x0000000000000000}}, {{0x000508946b504e8a,0x00067cc71474da28,0x0009ad4094d373bd,0x00068f87798411db}, {0x000b0b90d5d507cc,0x0000617d88846f61,0x000a437ea42aac2f,0x00012a4ea205a926}, {0x000adcb25d613e80,0x000fb7ef615aab09,0x0000000000000000,0x0000000000000000}}}, {{{0x000127afd82f8260,0x000f4ea3f09c69bf,0x000b49f3f0e43a3e,0x00052457b8b9c3f9}, {0x0004fe6ce00409f0,0x00044efa3e31f441,0x000e3e0240cf1253,0x0001f0b4a170983e}, {0x000d166b0cc9e8c1,0x000b455417a2207f,0x0000000000000000,0x0000000000000000}}, {{0x0000fd522cdf167d,0x000b48039daf9a36,0x0007cdbcd7341cc4,0x000c7db3b7805076}, {0x000641b0db786edf,0x0006ea9b69b8bccc,0x000eded2a4e25e3e,0x000651b8f0911cf0}, {0x000614b601e95ba9,0x0005000aeb19e877,0x0000000000000001,0x0000000000000000}}}, {{{0x000c0c51d56f967b,0x0008dddbb7684495,0x00035dbc45f7bb76,0x000f9e6deda49098}, {0x000e73639006a39d,0x000878e5a247f77e,0x000cd83d141b2c8d,0x000804a47e332c8c}, {0x0009dc7a02d4027f,0x000b1b9934bb002c,0x0000000000000001,0x0000000000000000}}, {{0x000777a838efe004,0x000368d9919c1d8d,0x0009dd721650f685,0x0002b1de892863f1}, {0x000d78f2b25a32a9,0x0002a4320690ff3d,0x00005a4af7bb8bc1,0x000cd763efcfe035}, {0x000701c70cf4f256,0x000443ef26775353,0x0000000000000000,0x0000000000000000}}} }, {/* digit=113 [{1,2,3,..,}]*([2^452]*G) */ {{{0x000e0800cd422057,0x000077d1b7504d49,0x00004fd80e159ebe,0x000a18a8714afb4f}, {0x000de28810d8b90e,0x00019cff83f02c3c,0x000eb9e19367a867,0x0009952bac438786}, {0x0000e0748ecceb4e,0x000faa55aefa6646,0x0000000000000000,0x0000000000000000}}, {{0x000aa315b1f2623e,0x0002b544f96e097a,0x0005dae237e7a5db,0x000873d0a9362519}, {0x0005569799223163,0x0001a58ea84d0fbf,0x000d43fd3bb728ac,0x000f100cfe43661e}, {0x0004f55c6f1cd21a,0x00091825dcbe9fa2,0x0000000000000000,0x0000000000000000}}}, {{{0x000fc794a5858d75,0x000a4affcd84d641,0x0005082ece4f5985,0x000b4853cf3bb3f4}, {0x0000bb1d8af65850,0x000953dc3e670d98,0x000424ef579458a6,0x0008ac2f2e4a7963}, {0x0000d771e540b685,0x0009be1f5fed2292,0x0000000000000001,0x0000000000000000}}, {{0x0001be223c4864af,0x000fbb662c4dc573,0x000a57017521419c,0x000c0240d65099ca}, {0x000b13af88f3bfbc,0x000bc4861e1643ac,0x00067ed67405bcdf,0x000d9351f1c835f0}, {0x000d0e188cb8018e,0x0001f8d276f971ee,0x0000000000000000,0x0000000000000000}}}, {{{0x0006a9e449621f3d,0x00052e91ee418d60,0x0007e5ea0e7d2dd0,0x0006f73c92e787f3}, {0x000cc4508ea4869d,0x0002d461acfe248e,0x000bd24529ffcc1a,0x0002f90dc5dc22dc}, {0x0002f8abba336456,0x00056cd254e4f954,0x0000000000000001,0x0000000000000000}}, {{0x0000aa036c0262fa,0x0002edc4f4234a99,0x0001031cef9b59ee,0x000145d5d5d4b081}, {0x00087df2c037b984,0x000a2d6af2c7b077,0x0006ff431d568532,0x000e309a7c9b6d5e}, {0x0006a3ee9bb40c66,0x000c81af9db41cda,0x0000000000000000,0x0000000000000000}}}, {{{0x0000f6f067a194c8,0x00066d7ad7abcf3a,0x00041cf832b531ca,0x000f470a4ac4965a}, {0x000cbe00766a00f9,0x000432af80a92657,0x0008968ac40c892b,0x000cbd44ededa94b}, {0x0008d46204be8b74,0x0005dd98f760bd2a,0x0000000000000001,0x0000000000000000}}, {{0x0007f464f2479db1,0x000c0fdb3e7dcb2a,0x0001a96b28900b58,0x0000a2993c1d7ee5}, {0x00057bf0ce9357a3,0x0001f5d39eb49f5f,0x000fb8b8f0c1970f,0x00060718d4faac9c}, {0x000ec4ed9e1c25a3,0x00004bb0d7504b66,0x0000000000000000,0x0000000000000000}}}, {{{0x000c9e1b2fe9b1f5,0x0008d34221feb754,0x00042a589958e706,0x00008c19119e3c31}, {0x00021ac738645a87,0x0004d7be72a33383,0x000a72a39907dc71,0x000beb5759bb91f8}, {0x0009abd4b13e9374,0x000b96398db67d76,0x0000000000000000,0x0000000000000000}}, {{0x0000945a75d3799d,0x00031dd530ad32ad,0x0000c605c645aa0c,0x000c247141d0f230}, {0x000876cc8fca8350,0x000943188b899279,0x0001484afb9ffa8c,0x000536d0aa571f07}, {0x0002b7a0c7fbe8ba,0x000c736f36c17e51,0x0000000000000000,0x0000000000000000}}}, {{{0x000618a7bb29e0e4,0x000c09c2bff10aed,0x000781dbe57f3993,0x000965b0e2b9baeb}, {0x00005cf5dc5bd4b3,0x000ce5975c6e0f92,0x000471ab0fcf2bf8,0x0002a2d43bae9f5d}, {0x000bcafa18f22cc7,0x0005911e3b357902,0x0000000000000001,0x0000000000000000}}, {{0x00057df200a9fe3a,0x000b50d956c845fd,0x0007f211bf361887,0x0009b4007c382ac0}, {0x000ee4f517e7f4f0,0x0008256df5e905bd,0x000fa86a9368d1c3,0x000a7df56d37c426}, {0x000efab6ec26a5b8,0x0005cdfe9cfac9c1,0x0000000000000001,0x0000000000000000}}}, {{{0x00082202f99826cc,0x0004867eca10dd40,0x00071f5c4e281cfc,0x0007b5da880b8221}, {0x000325e5cd3e67f8,0x000671c0e0906564,0x000df4bd6ef65d7c,0x000c8a693695da96}, {0x00076e79dcdb1aea,0x0005bd96f080eaaf,0x0000000000000000,0x0000000000000000}}, {{0x000240c6e69e5a49,0x00080c138884ae0a,0x0002f7e55e87844e,0x000a57d17ee0d45e}, {0x00033a1990475a82,0x0004fc5139e3efb1,0x000093a8d1fcb820,0x0007e2fdf23f8eaf}, {0x000aec2eac127538,0x000a0742581e77ed,0x0000000000000001,0x0000000000000000}}}, {{{0x000de604b9db6d8d,0x000262da62b65572,0x0009db8d0d3fb7d9,0x00067b7f8e9c2aa3}, {0x00074f2912d3c9b8,0x00079e6d831a5ad6,0x0006f3cc6935b1c2,0x00009a75e08b8223}, {0x000aaa28cfcf8f6f,0x0004f75ff407271b,0x0000000000000000,0x0000000000000000}}, {{0x00024706c120a90c,0x000b4f991d9aa4ab,0x000767e06952ed85,0x00006ffc0793e3c1}, {0x0003d6115d975f7d,0x000c57472c131644,0x00024430b8651df9,0x000bda1a64f28b97}, {0x0006db846f1bbd8d,0x0002f562aea1650c,0x0000000000000000,0x0000000000000000}}} }, {/* digit=114 [{1,2,3,..,}]*([2^456]*G) */ {{{0x000d810c86eab937,0x0008e6e6eb51bdd5,0x0009bc2e3a0e4219,0x0007e391c4b3dc48}, {0x000736ed77fe5eda,0x0005e60972cd0e3d,0x0001aaa05f70f41c,0x000db07669f426a5}, {0x0005914839830a47,0x00029045b98cf434,0x0000000000000001,0x0000000000000000}}, {{0x0009d9c576932524,0x000409f4c3b8bddc,0x000d467dc9295086,0x000bdef23e6cf0fa}, {0x000729684c1e0fbe,0x000c3a23011daa3a,0x0008c4ef40ca0da8,0x00034dda12c0850f}, {0x0002c5e51990ccbe,0x000494c2f0adaf8f,0x0000000000000000,0x0000000000000000}}}, {{{0x00087b36a390065e,0x000c93a9bb0064f8,0x0004572329d651f2,0x00010e01d988aed3}, {0x000be48541e9e6f5,0x0000ac10a8abc023,0x000b700a8621efc9,0x0003eb208400f943}, {0x000d85b1c768bb3b,0x000f42634af0db64,0x0000000000000000,0x0000000000000000}}, {{0x000e0a10a250b4be,0x0000634e42e593a7,0x000adef0026acaa8,0x000002da6f2f96cb}, {0x0008dca66aa2e955,0x0005a69e8157271d,0x000f32666dc76291,0x000c378977ddcf29}, {0x0000e5eaa07d6619,0x0002a548e47a94e1,0x0000000000000000,0x0000000000000000}}}, {{{0x000cd510985c6ead,0x000d1cc399a1876d,0x000fc77243f5c966,0x000c3b2c4abf82c9}, {0x0001efaf22c713ae,0x000a22e1704988df,0x0002a2d8f28a287a,0x0000f724ea967d19}, {0x000ed48e76179ade,0x000ff318acdc5b8c,0x0000000000000001,0x0000000000000000}}, {{0x00063196ac8ad685,0x0002708e70052b0c,0x000d8ff45f4a08be,0x00064862e9bd37fa}, {0x000efcc39748e461,0x000dcfa2843cc067,0x0006ae8688367317,0x000b8aabfd38c458}, {0x0005642ea85ecef5,0x000873af78e84b81,0x0000000000000001,0x0000000000000000}}}, {{{0x000b763fd4a23b33,0x00004ce905f61100,0x000ad5b3ffa31c96,0x000817bf059b27d0}, {0x0004f957d997fe85,0x0008adabfcc9cea6,0x0002fa1bf24cb58a,0x000afe218a3174dd}, {0x000ee69ca08cb0de,0x000fdf310fed00cf,0x0000000000000000,0x0000000000000000}}, {{0x0006e131eb000160,0x000a4d18c779a4d6,0x00013180dd747a1f,0x0009340c23f27ad3}, {0x00004df4a2f35316,0x000ec77b35a8c2be,0x0007fb23a1f8aa1a,0x0009e69edc272eed}, {0x000d58ddb6110abc,0x00042ae7590226a5,0x0000000000000000,0x0000000000000000}}}, {{{0x000f3cc8ae818a77,0x000f54ede150dbf6,0x000c2f06bc371295,0x0006ab2d173c2266}, {0x0007fda0b8b46bd2,0x00070909e3958aad,0x0005242beb035184,0x00006b5aad800c13}, {0x0003a70dce6b782b,0x0007761ebe42a4f4,0x0000000000000001,0x0000000000000000}}, {{0x000ee87f40792877,0x00080b5c7acfe8e9,0x0007c5775efcb053,0x0007bf0a2d540e71}, {0x0008c839d644d450,0x000d1ff451c6b81a,0x0001b7ea45f8834b,0x000306bfc9c3c653}, {0x000cabe92f1a607c,0x000c13152a3731fa,0x0000000000000001,0x0000000000000000}}}, {{{0x000ad1ff805361f9,0x0003b3536327ce4d,0x0005b0b62672d1bf,0x000ddf3847367af0}, {0x000278798d158f13,0x0004fbc252a948f1,0x0006fc03d0fe92b8,0x000c0138676b978e}, {0x000ea4ba8ef9334e,0x000f98b13cf22496,0x0000000000000001,0x0000000000000000}}, {{0x000ac5c627d693fd,0x00015f19d6d21fa8,0x000b4a2fb70b6705,0x0002c39928de441a}, {0x000db0fd9e912476,0x00096888c13371fc,0x00013f185fb68ee8,0x00092d86c189d0e2}, {0x0001cf6facea1f84,0x0005b949b94eff15,0x0000000000000000,0x0000000000000000}}}, {{{0x0003e85508c930d5,0x00050167c798885c,0x00018ef2850f4f27,0x000547f00d7f6b01}, {0x000899cb15ed2f40,0x000bc417a989d6f1,0x00008165c9378941,0x000bb0e0c28f2218}, {0x000839d9572ddfe6,0x000d6ab0b70e2e95,0x0000000000000001,0x0000000000000000}}, {{0x00092c31b5a755fc,0x0005623261be8d00,0x0002ed776ec81547,0x000ed7b92bc72da3}, {0x0006d943fbdb47af,0x00096c45167b5a5d,0x0006fef44f208158,0x000d5bd5c28e23f0}, {0x000da432e8f4f6c6,0x0007b3355da25eae,0x0000000000000001,0x0000000000000000}}}, {{{0x00076c8ab8c349a0,0x000850693d15749f,0x000d18a6991254fd,0x000f60f54944e4ef}, {0x000febc73879cf78,0x0004c63e00125696,0x00042f68e1e2dbe0,0x000b688fd93a88e1}, {0x000f1e83abbe7321,0x0003aaa7b2fa13d6,0x0000000000000001,0x0000000000000000}}, {{0x000caa293a9d97c5,0x00059519ff3b97cb,0x000cedb5893b39ad,0x00064ed07e59369f}, {0x0003315852af3473,0x000d5a40d47c32e9,0x000386582768fe34,0x000453f8e4c60653}, {0x0004a96dcf43bf2b,0x000e332542e1828b,0x0000000000000000,0x0000000000000000}}} }, {/* digit=115 [{1,2,3,..,}]*([2^460]*G) */ {{{0x00011a7aae3fec0f,0x00081883626ec806,0x000aebe504491b56,0x00031dd2ecc113fd}, {0x0001068171e0f3fc,0x000d2fbb6b5fdadf,0x0000ee0e94a492b4,0x00090723f06e06c2}, {0x00016b906e2fed2d,0x00033b2f32d5d083,0x0000000000000001,0x0000000000000000}}, {{0x000731c43f27e685,0x000c912924bed063,0x00058df5bd8f8996,0x00080e3a04d16a64}, {0x000303ff6f14cb47,0x000f56c8175aed03,0x0003011b62e0f3ec,0x000eee8bd1d8f816}, {0x000a055be5c28fa8,0x0005635edb8d9c9f,0x0000000000000001,0x0000000000000000}}}, {{{0x000eb4c2e9d6a36d,0x000f1c0e66e6ba0d,0x000058a747cb2451,0x0004b10a20962d66}, {0x000e1da104e82021,0x0004693d32e594ca,0x0003bb7f837609cb,0x000e53eda7c5059d}, {0x000b602751dd16ca,0x00007ac67ede2a3e,0x0000000000000000,0x0000000000000000}}, {{0x00038202cc49b145,0x00003535c208aec8,0x00056079145b2fb2,0x000814d455be9713}, {0x00082fd8f0bb395c,0x000c755426c09f67,0x0000b748edafadbc,0x000deaf4bc3a4ecf}, {0x000bff049553943e,0x00057ee542c407a2,0x0000000000000000,0x0000000000000000}}}, {{{0x00058193376e77cb,0x000e72c0bba4380d,0x000bc54c3a89ddc3,0x000dd63a1bbc6d0f}, {0x000bf1518f660f2c,0x0007e5bf5faf2f62,0x0004682bfe7727a2,0x000da33defeb7b16}, {0x00032b5ef40ec257,0x000a0e902b2e8961,0x0000000000000000,0x0000000000000000}}, {{0x000ab468387524e3,0x00024e69a88271e3,0x0004545479e82998,0x000121a7373761e0}, {0x00093e3b1f753397,0x000463acb40aaebe,0x000cb721af707dad,0x000c14e152331d6d}, {0x00065553048e5280,0x000612aaad009d91,0x0000000000000001,0x0000000000000000}}}, {{{0x00092b39f964e28f,0x000fa7cfd7976897,0x000f279c07ec556d,0x0001cf40d7670e8c}, {0x0007b5e04abdedad,0x0006fcc19990b137,0x0008572f5067ad94,0x000a28101c966a08}, {0x000b5e33c2ad58ac,0x000eb0e333e24c43,0x0000000000000001,0x0000000000000000}}, {{0x000f0361a475ac89,0x0002dcf79463ef54,0x000dd053538c22ce,0x0001013b4e6817ca}, {0x000b44b01a6e12bc,0x000d109d85844a6e,0x000b985bfdaef54a,0x000f6830be544481}, {0x000fd8dd0297f121,0x0007cb6d0b67a68b,0x0000000000000001,0x0000000000000000}}}, {{{0x000ba65ede23b338,0x00026845dcbcdc45,0x0000a0b1cdddd83e,0x000092ea63968b4f}, {0x0004b71e6e72d35e,0x00046c5ed03f1ddc,0x0006efc5a166bbfa,0x00090de0b5f6b7c7}, {0x000445136c1387b7,0x000ba78923450ab6,0x0000000000000000,0x0000000000000000}}, {{0x000a850194005e74,0x0009c00cae44ea99,0x000e5e17b631e4af,0x0001c80d51c0dae8}, {0x000120c3cbe08ee9,0x00023c8041a40936,0x000ada73446b0eda,0x000643d14026f215}, {0x0006fbac37813fb6,0x000fc70031b68bb2,0x0000000000000000,0x0000000000000000}}}, {{{0x00075ab901660b40,0x0001e645ee7e0ee2,0x00037b06a37399f2,0x00080496e9bd12b1}, {0x00026a5d50d58960,0x000c1e3f3705ba3f,0x000274a1d4a00817,0x000d2d00866a4d39}, {0x000f146bf0317c40,0x00024e2ec71ea064,0x0000000000000001,0x0000000000000000}}, {{0x0003c199f5c7f563,0x00062e4f78f16893,0x000a194ad2a3fb13,0x000080225259655c}, {0x000bc5898f9da5f4,0x000553edffd8a6c1,0x000e20b2793c4797,0x00041ea73083e26d}, {0x000a2971a533d937,0x0000e54fd22035b2,0x0000000000000000,0x0000000000000000}}}, {{{0x000f9d4de9a27585,0x000400debb5987f8,0x000d526ec09e3156,0x0008bd03e0023f66}, {0x000aed7d715cc557,0x00058cc9c03099f2,0x000506b4417ca0c8,0x000d23b4df572ea5}, {0x000c5dc147420ffb,0x00032899652bdfe0,0x0000000000000000,0x0000000000000000}}, {{0x00031987cf8e9148,0x000b259461ad7d0d,0x000c859a4a7e6bba,0x00030e2b3d2a289c}, {0x000e9be629139087,0x0003904cf1cf6e14,0x000cca9dab045a7c,0x00082a43de3eacb2}, {0x000d82c3afa439f6,0x000decd187ae70d4,0x0000000000000001,0x0000000000000000}}}, {{{0x00087b4497808581,0x00012be293d33455,0x0004ce4906c6f8ad,0x000a66938d521bfa}, {0x00046a914bdb3b26,0x000ae5f6e99dc3e7,0x00059dbb0881c2e3,0x00009191a1b5ac25}, {0x000c6a97a72e5343,0x000ddd07226ad4a6,0x0000000000000000,0x0000000000000000}}, {{0x00039e249234483b,0x000669419af2063a,0x00042122752c72bc,0x000aa7e19a44c7a3}, {0x00011188ac573c28,0x0009a3360e14ec6b,0x000bc0bc86245880,0x000741e192993af7}, {0x000d8d75742bd481,0x0006cd8768555ba8,0x0000000000000000,0x0000000000000000}}} }, {/* digit=116 [{1,2,3,..,}]*([2^464]*G) */ {{{0x000ebaeb9266fcb3,0x0006c49166afc8c7,0x000b1a4fb9f8df09,0x0003a2759ef63e0b}, {0x000ded0e62d1d0a6,0x000215cb79a13c16,0x000942482d5b46ef,0x000a5cf390334543}, {0x00039ce21c9b239a,0x0000a2fcf03ed34a,0x0000000000000000,0x0000000000000000}}, {{0x000466a8adf517f0,0x000775523be0b6d8,0x00074759167493a7,0x000284c64894bb12}, {0x000e2864e9ca25e2,0x0008b7f98fd07d26,0x0003fdb6d6620610,0x000ef64b5a668e1e}, {0x000d31c44a0ba6ca,0x000891dac14a11ed,0x0000000000000001,0x0000000000000000}}}, {{{0x0007e005c5b2f805,0x00010b6d99c24dd3,0x000813da1409fa02,0x0008bf13d53cbcd5}, {0x0005bb6d8655f948,0x00021f224e5b2d05,0x00077dd3ba305b4b,0x00005337f568059a}, {0x0008b4b1e783aa9f,0x000d6ce8c56442b8,0x0000000000000001,0x0000000000000000}}, {{0x0007e0acb71f23b1,0x0007f2e0e90fde9b,0x000336f8ff1da186,0x0004751614e3d072}, {0x0003187e51c7e8e6,0x0007ef17101ca72a,0x0008a9761c42d892,0x000ebb69cc0c641d}, {0x0002903e96138250,0x0006b8d2873a54c1,0x0000000000000000,0x0000000000000000}}}, {{{0x0007b97b6b68155f,0x000799e78b707b09,0x000e1f75bd19e80f,0x00035096285e6628}, {0x000d9b8661ae0f1a,0x000fe90a8911dc8a,0x00018180a1d7fb12,0x000733dbb76ae258}, {0x000085cc47bdbf1a,0x0008c417eada4711,0x0000000000000001,0x0000000000000000}}, {{0x0006498715c0f18b,0x0008cd3093549e44,0x0007888a48d3a384,0x000a0d971c9394dd}, {0x000f79cc4aa385aa,0x000d44729501e42f,0x0002ea4042d9ad6a,0x000c1e43ab081b30}, {0x0002a374ef11901b,0x0009de3ad60e42b4,0x0000000000000000,0x0000000000000000}}}, {{{0x00023f47f06415e1,0x000ec51fe7219c05,0x000bd8a88f411a49,0x000308976713e8b2}, {0x0006ee0f84892d3f,0x000957e9fa410c61,0x000903d60b015584,0x000f41fc07f1fce0}, {0x000fa3ce182117ef,0x000654b039b5693f,0x0000000000000000,0x0000000000000000}}, {{0x000f700d59c0d688,0x000bcc693fd9aa04,0x000b8b0e7fea0743,0x000182c181c35812}, {0x0008864896cc8fcb,0x000c77cf499f019f,0x00010bba6594c508,0x000e88406e142c41}, {0x000b45fd50fcaee7,0x0009894dc1ba3eb8,0x0000000000000000,0x0000000000000000}}}, {{{0x0007488ba3fe2367,0x000752106ad62ea4,0x000980bc62d3b8ad,0x000328ef733708df}, {0x000d47b00f88c069,0x000f6bb0176a2cf3,0x0009f6480ef1ba36,0x000ac0712001822e}, {0x00032f8aac418a68,0x000ff326047c12c9,0x0000000000000001,0x0000000000000000}}, {{0x00039bbf3cc8d8c5,0x00091d5e4cf0789b,0x00042078d73c679f,0x000b71a650f7aeca}, {0x00082a530b74abff,0x000a71711bd8405b,0x000c3bb0ac95d510,0x00094cee94894b3c}, {0x000906c5e7b66990,0x00030a027cdba56d,0x0000000000000001,0x0000000000000000}}}, {{{0x000c446c47eef0c8,0x00044a0878421c07,0x0008722c55cf2755,0x000ec763424a48fb}, {0x000f4f6b5b3b9028,0x00078d4fe3ca8f7b,0x0003f4277d82e20f,0x000fbc6300a704e2}, {0x000a908b8f5f71bb,0x000b090bc8e8a53a,0x0000000000000001,0x0000000000000000}}, {{0x000dcad6549fc8da,0x0004e635d31de3d0,0x0009ac9c9dae5fbc,0x0005d812525deba7}, {0x00028465a1ffb0b8,0x000039c002085422,0x000d1431962a343c,0x0001729577d460c9}, {0x000befcdb0fe4b63,0x000f982552806705,0x0000000000000000,0x0000000000000000}}}, {{{0x000c16470afeefa0,0x000c0df482969752,0x000988294a6b7345,0x000192c323f56fda}, {0x000ece866a0fbb9d,0x0003fb58e433eb87,0x00044e600bdf291f,0x000bc9a43f5fab4d}, {0x00060683951124ce,0x00065a7c641677f4,0x0000000000000001,0x0000000000000000}}, {{0x000ce490f8bb04ea,0x0002e7ad3382ee72,0x000272231533e6b8,0x000186b13ffe5f10}, {0x000cc8faf0cc5e1a,0x000c709ed2b173b2,0x00067e514381962f,0x000cd58bc198455b}, {0x0006402864604346,0x0009d46f62db1463,0x0000000000000000,0x0000000000000000}}}, {{{0x0007bb607e896c28,0x000e0a894887a4bc,0x0006eb1e97614230,0x00003e71e2c653f8}, {0x00096dded494be93,0x0008ac95d09fc0dd,0x000bea563fba0619,0x0008f3c1624d738a}, {0x0009df64d4a0ea98,0x0001d5c6ae182338,0x0000000000000001,0x0000000000000000}}, {{0x000eeeb900454516,0x0006377d7a8b0a7f,0x000a9c345a7de36c,0x000100d5611067e9}, {0x000806bcdcedd0a9,0x0002b5dec6f6c68c,0x00051f38d7d4a349,0x00022d5061b9ad36}, {0x0005c9ea7f739c0f,0x000ee734e6cedbd1,0x0000000000000001,0x0000000000000000}}} }, {/* digit=117 [{1,2,3,..,}]*([2^468]*G) */ {{{0x000eb05013cb5aab,0x0009afca55bd420f,0x0009c3c71fd8695f,0x00000cafcc6e5ed1}, {0x000728edc89ca3d5,0x00076471854e21b8,0x000201f0ff872ac7,0x0003e23036d8ee45}, {0x0002c13f7c8bee8b,0x000707a1d51a1e5f,0x0000000000000000,0x0000000000000000}}, {{0x00022b011bf68532,0x0000cf529ed8e280,0x000b8a477a52b6ff,0x000cd2f63b6e8238}, {0x0007c291c55c9cf5,0x000f4796ab42ab24,0x000c0989f93937b3,0x000bca7b47aa5dbf}, {0x0006f0a6b7620e79,0x000f58dd4ea00729,0x0000000000000000,0x0000000000000000}}}, {{{0x0004f87aac9cea1d,0x000fabffc3ba2342,0x000a3b2b167162b1,0x00073da5b86c7978}, {0x000769b5f991d83e,0x000cb3d9088d484c,0x0004542e085b4392,0x0004eba2ea8f2806}, {0x000c46cb82b91d2b,0x0008c0e83321f8cd,0x0000000000000000,0x0000000000000000}}, {{0x00097601a9d31426,0x0009ef4a0c50dffd,0x000fc4b8056305e9,0x0000c1c8a29f6e86}, {0x000d4be1babedf5b,0x0005e98d4d558d2c,0x0007fd7d17d7bc87,0x00009a0a33b745e5}, {0x0008c2a2bc3cf9b6,0x0006235277b76d2d,0x0000000000000001,0x0000000000000000}}}, {{{0x000ad9eb395de05c,0x00050bddffa75224,0x0008d48f88a50e57,0x0005bffe3c2175d5}, {0x000aded74a44ab8f,0x000f36097483dc36,0x00041e5290fdaaf9,0x00051f0f28ee6aea}, {0x00006d6a082ff0ae,0x000068e3568c35a6,0x0000000000000000,0x0000000000000000}}, {{0x00052b137174e56f,0x000a242808c3c521,0x000cee713ccf3a0d,0x0007f4523126e210}, {0x0009790a26049fad,0x000293cb237c8c65,0x000391754b82c700,0x0005060129b75ceb}, {0x000ad78c9cbc1be8,0x000452fab6d7a60a,0x0000000000000000,0x0000000000000000}}}, {{{0x000614e7a62b479f,0x00091b1806f1503e,0x000c937295d07735,0x000468f3b432690c}, {0x000027af2bc376d3,0x0001568b1fc765b5,0x00004c84508081cf,0x00093b08d2fa4f2d}, {0x000aa23530d43841,0x000eddd4118eb0fd,0x0000000000000000,0x0000000000000000}}, {{0x00095d916a74bf7e,0x00052f879c30fb73,0x00033e906c3732a6,0x0009ecd6d707078b}, {0x000764fe7914feb0,0x000164429576e244,0x00070601ef70830f,0x00038d1a94c290ff}, {0x0007e067e8e38b39,0x00004d7b7a7e7934,0x0000000000000000,0x0000000000000000}}}, {{{0x00092dd8b3c6e87d,0x0006c49275954a31,0x00016b291ceab935,0x0002ae4fca80283b}, {0x0002ae3f769e974a,0x00047d8e3a1a96a2,0x000875bc17f080fc,0x000a5eabb84f45c1}, {0x000e2f2661df31c8,0x000663147f43e69b,0x0000000000000000,0x0000000000000000}}, {{0x0002716571c12164,0x000b5580b0b11754,0x000bedf056c51a6e,0x00019d3572bd29fd}, {0x0006ce46ac6d5756,0x000d711d909ced7c,0x00056c0ec115b51f,0x0005ebe8c1ea4d63}, {0x0005d77cf7a0032e,0x000ddbec9919b1e6,0x0000000000000000,0x0000000000000000}}}, {{{0x0002437a972f2c78,0x00015b5e5010e549,0x000fb968e48079c6,0x000ee7041338af95}, {0x0007cad3cea2147a,0x00063a330c01aad8,0x000ecdd3002cfb58,0x000bf58e568343ac}, {0x0007567e97251d0a,0x000b568be5a71fbd,0x0000000000000001,0x0000000000000000}}, {{0x0003982ec0a47e47,0x000862df20207b07,0x0002c656e08dda4d,0x0005ad59afe9aa6b}, {0x000ee04d8bf8d524,0x000d84cab42cc2b5,0x000ee837ff8c6d4a,0x0008b691af448525}, {0x0003b100c345fb36,0x0000d061abec1e80,0x0000000000000001,0x0000000000000000}}}, {{{0x000c9cc4477a0393,0x0002f0a9ecb165af,0x0008a80444bd4fb6,0x000a9d4dd001619b}, {0x0000b10c19a21051,0x000801b4ef3f9384,0x00076219bc4d71f3,0x000ea7190314526d}, {0x000da93e188e8697,0x0000967b67776acf,0x0000000000000000,0x0000000000000000}}, {{0x0006ab2717f542c5,0x000ae82426abc0aa,0x000641af35023777,0x0005dcf6c7153a96}, {0x000977e0ee60ca55,0x000c371732ddcc64,0x000063579dd744f3,0x0004f34c496af4bc}, {0x00000f9df0536028,0x000b1c2a26167cf5,0x0000000000000000,0x0000000000000000}}}, {{{0x00061fdc0b1fc134,0x00059fe59da03f7e,0x00051831e7698bd3,0x0009f81df982fb68}, {0x0001c64253ce4407,0x00084a0c0fffbd0a,0x000fd2724ab08376,0x000aaefd7b900fa3}, {0x000017be08cd54b9,0x000359398932034f,0x0000000000000000,0x0000000000000000}}, {{0x0008bfed571b358d,0x0006e5bd73f12c5f,0x0007574722cbd9b4,0x000789de672fc532}, {0x000cf9d4c5de795b,0x0008e00647313e84,0x00001e2002f19344,0x0007649a15d6dda4}, {0x000a4f04c96114ef,0x000ac34a9dc08537,0x0000000000000001,0x0000000000000000}}} }, {/* digit=118 [{1,2,3,..,}]*([2^472]*G) */ {{{0x0005e5ed4ea72f88,0x000dc27eafbd5d75,0x0008274c8f222817,0x000e4b956ed11c56}, {0x0002ac506cd96a0b,0x000c56121cfca3c6,0x000e3c5160f64376,0x0001cd969d9794e1}, {0x0002818ba2a1b9ac,0x000bbd5d12cb946a,0x0000000000000001,0x0000000000000000}}, {{0x000065269838f81f,0x000a256eaf242367,0x000743908912f4af,0x00048d332342e954}, {0x000f75565f855ec0,0x000e4ec59a3a8816,0x000505255b015d48,0x0006bf898ef06a71}, {0x000af90ae385313b,0x0001d5415dc8688b,0x0000000000000001,0x0000000000000000}}}, {{{0x000115486df6f2ba,0x000803b08c738eec,0x0002302443593e59,0x000e60eb4f00e934}, {0x000e57c91438ebdb,0x00080e89c523e859,0x000d75cba0053e05,0x0000d11317c9b329}, {0x00035e5703d38955,0x0003845aac6426d2,0x0000000000000000,0x0000000000000000}}, {{0x000349105fa06b94,0x000e9b21c69e6c42,0x000f70eb1519a81d,0x000827ae2990539b}, {0x00048fe9bf0bbafc,0x0008dbb3c1ee9dd5,0x0002a908c4d4274b,0x000cb7224476f3be}, {0x00028346b6e6842b,0x0003ad39da0c7384,0x0000000000000001,0x0000000000000000}}}, {{{0x000a9a342fa007b1,0x00065415bb7a90ea,0x000dcc6aa0c26771,0x000a1f0bc720264a}, {0x000b5e93f7bc1986,0x000bf6b3fca182f9,0x0009a7b5c22f84c1,0x00087bdec7ad14eb}, {0x0008902c942c3b07,0x000a69d7973e7810,0x0000000000000000,0x0000000000000000}}, {{0x000230ff44676602,0x000d3064b8821220,0x000d730a5228928d,0x000ea087c0f54e1a}, {0x0000abe8035de528,0x000d9e98d62188b8,0x000d85f12fe3f391,0x00095d1c13b3c4b4}, {0x000c9a4940436d0a,0x0007d2cc5f243602,0x0000000000000001,0x0000000000000000}}}, {{{0x000c484e2708d61a,0x000e14446b62d85c,0x0009c0fff451d84c,0x000a49ca08f1ae70}, {0x0003d71899e1ae53,0x000709a90d9917f9,0x000f39b12fbb0503,0x000038af72a2045e}, {0x000817cd90b8cc9a,0x0002f352b4ed83f0,0x0000000000000001,0x0000000000000000}}, {{0x000a71d48ae023ef,0x000d8744e50d53a7,0x000192ec22667e7a,0x0002e19437867d3b}, {0x0007124825f0cce3,0x000aa41f07fce902,0x000fc674b8262125,0x000d1f602e03c9ce}, {0x000f93cc0c071ae6,0x0003fae4c52caef9,0x0000000000000001,0x0000000000000000}}}, {{{0x000d102ba58b5201,0x000cb021f49742da,0x00078984de6430a2,0x0005002098f1e552}, {0x000c9b804a37766b,0x00095479cd052eaa,0x00083f87dcee9cc2,0x000ce159b125b614}, {0x00001a384dc69331,0x0002e4ec5a2f8699,0x0000000000000001,0x0000000000000000}}, {{0x00049fffc681e26f,0x00001b52ea90f687,0x00080117445f69ef,0x00093fb5f32e704c}, {0x000d36110b81abea,0x000a3e64f4ffada3,0x0000ff99dcba475c,0x0000eb1b968c2040}, {0x000ded29d4be59cb,0x000ba78061ed859d,0x0000000000000000,0x0000000000000000}}}, {{{0x0004949755c59603,0x000c796691a84904,0x000a8445d0aabdba,0x0002396cff6a7bd7}, {0x000562547f935def,0x0009038b91c344b0,0x0001f20274812ef2,0x000e1fe565e5087b}, {0x00074866fd902829,0x00032844aad6b8f8,0x0000000000000001,0x0000000000000000}}, {{0x00092e9251d05a0d,0x000328420cd4a328,0x000e00dfce4ccaef,0x000beca3a94d516d}, {0x0000fce64bd11bb9,0x00054cb1e99e5269,0x000cfc1bfec9624a,0x0004e634fe2023b3}, {0x000e53481128c3b5,0x000cd2258147276f,0x0000000000000000,0x0000000000000000}}}, {{{0x000e9ad8d783865a,0x0008e5a58d54402a,0x000e236d64e3be62,0x000daf46f4aae16f}, {0x000049ba7000cd7f,0x000deb437c36e86b,0x00025e5a9179d63e,0x000fb30e5ec5adff}, {0x000fc4d691408156,0x000d8b4dff418608,0x0000000000000000,0x0000000000000000}}, {{0x000c4eed479219ce,0x0008e4d5ead8e114,0x0005f4f71316535a,0x0001c636b70e9489}, {0x0008aa2310479eec,0x0004e1dcd4f2eb70,0x000474c99b5134b7,0x000ce4754e99035c}, {0x000218919b4c0dad,0x000e1d1dd3f97981,0x0000000000000001,0x0000000000000000}}}, {{{0x000cc18c358773b9,0x00036bf6385f12eb,0x0008a0c24ba8caf5,0x0003093cd83891ca}, {0x000f5b8c3762108b,0x00041e3399b26a0e,0x000fadfca8c426db,0x0004173bf6760263}, {0x000a6677ad40bf58,0x0004eca4760acdd8,0x0000000000000001,0x0000000000000000}}, {{0x000c42b8b4207fa1,0x0006dc5a60d34efb,0x000a367e08d67868,0x0008cead3e942c85}, {0x000409d289bdc2dd,0x0004b034c3a6d1bb,0x000889304955940a,0x00080034f3684e43}, {0x000808a7cddeee0c,0x0001148f3d9aa263,0x0000000000000000,0x0000000000000000}}} }, {/* digit=119 [{1,2,3,..,}]*([2^476]*G) */ {{{0x000df4a3fd3e1bab,0x0006287d84daca3d,0x000d7eaf57017e3e,0x000d1a4e4870b354}, {0x0004c26a3e3ca9fe,0x000ce1ea5e5710e0,0x000709e17a2ff920,0x0000f8a3bc06ee67}, {0x000788ab8c019a66,0x0006f43d909c0fdb,0x0000000000000001,0x0000000000000000}}, {{0x000c0c61eebda5c3,0x000395c130704b51,0x000762ffbcb5d086,0x000f660bf6639983}, {0x0001646d9fb03337,0x00065cf06a8fa37c,0x0005f2e3f14b6d28,0x00088227d360e736}, {0x000a48fcdc5c3e58,0x00059e8c2eaf07b6,0x0000000000000001,0x0000000000000000}}}, {{{0x0001ce2b5f2dc50d,0x0007e39f8c4d01b0,0x00078d34284f417d,0x000d157acbf04214}, {0x000c0c4238071f59,0x000b0a1e05f8a594,0x000d81bbaf85cdc7,0x000d1d1329e8c9cf}, {0x00068fc55c9be4f2,0x00029b5c20884e31,0x0000000000000000,0x0000000000000000}}, {{0x0009fd4109cb4727,0x00021d96d542276e,0x000d61e57db16c16,0x00052da58656adf3}, {0x00089d546ecce2da,0x00041508ee2098e0,0x00011997499c874b,0x0006f525839d9cf3}, {0x000de08e59654896,0x000e511cdd85c0a0,0x0000000000000000,0x0000000000000000}}}, {{{0x000db13610c4d993,0x000192018344e51f,0x000cb8a7e81016f0,0x000425ff1ca2c27e}, {0x00047a8df5318c36,0x0004872bcd56d5d2,0x000d142a2e0d2618,0x000a83feb22e4866}, {0x00013dac70999b14,0x000ed007863be6ab,0x0000000000000000,0x0000000000000000}}, {{0x000023bbbd62b467,0x000e6ef8f48d21ce,0x000ea9c5f9c35940,0x0009af532bd76e0a}, {0x0000f8ff97911a1f,0x000efcff41750c50,0x0007cfa3985ad13d,0x000136812ef99c02}, {0x000319ee534694b3,0x000b9d9722dca85d,0x0000000000000001,0x0000000000000000}}}, {{{0x00040d25bac4c923,0x0005026132b9fa82,0x000ddc2ef3e74ec9,0x000151b0a9db4e16}, {0x000ff5ad95c1429d,0x0008144cde9bb57b,0x0000c02f2a19e480,0x0005655b0b6aef98}, {0x00038725b1f2df6c,0x000672346457ed21,0x0000000000000000,0x0000000000000000}}, {{0x0003077ffe12bd18,0x000e682804b9bb8e,0x000b8a3a7328db75,0x0007b6f50cb1bbec}, {0x0007a823e8549b58,0x000d7be7a7e70575,0x0007103b60b8617d,0x0004131d7bc32367}, {0x000713f91128ac22,0x0000deadb3b9bf03,0x0000000000000000,0x0000000000000000}}}, {{{0x000b46eea58e4f6c,0x000e8500cef9c4a5,0x000e36179b50381a,0x000498cb317e7dbb}, {0x000df2d824ab9ac6,0x000aa97d96328707,0x00068fd80e79f5f6,0x000ee03799c5c193}, {0x000688d4b109d20b,0x000fae5dfd91a5a4,0x0000000000000001,0x0000000000000000}}, {{0x000e4aa8649aaa1b,0x000caf8a4a894ffc,0x000f0a6af855f3c5,0x000fa6ef0a082826}, {0x000564cf46392869,0x000d9060255a7500,0x0007688b437590a1,0x0005fa2a21425afd}, {0x000dd69d65b91f19,0x0008045302895146,0x0000000000000000,0x0000000000000000}}}, {{{0x0009a872aecfc094,0x000c8cde3af050fb,0x000ebe6b500bec0f,0x0004d4b7e7c4ef2e}, {0x00094b38a6c4228e,0x0004f9fb0e82362d,0x0000dbf4e229d20c,0x0003a6e45bdfa369}, {0x000b1c90f730c74e,0x000306f2fc481fa7,0x0000000000000000,0x0000000000000000}}, {{0x000e496c4b887a36,0x000e6ae46148f8e5,0x0004268188f16f8a,0x000cf1b360936452}, {0x000ea828f2ec9dce,0x000a581be5eec097,0x0000a093e062b3a8,0x000e4da12b498543}, {0x000b50541562092d,0x000eae33c27b17cb,0x0000000000000001,0x0000000000000000}}}, {{{0x000bed4ffad0684c,0x000bb264e57bfffb,0x0009eb6b035825f2,0x00013466fd8b6643}, {0x000ab9c3537903c2,0x000b0366be7313de,0x00096ae2121723c9,0x0005953e87c3ac29}, {0x000b6974bbd38278,0x0003e43a30236cf9,0x0000000000000001,0x0000000000000000}}, {{0x0003b2707ffdea7f,0x0002da68809f795f,0x000374c5228ca4a1,0x000ef9a132cc5a86}, {0x0002bae5f8c0d15c,0x00061ce20672616f,0x000abed75c41da6e,0x0006a5fc5af7de33}, {0x00076a4d15065912,0x000ed44c16e78857,0x0000000000000001,0x0000000000000000}}}, {{{0x0003498018e534a0,0x00031b029f064c8f,0x000b893aedc07be9,0x000b0eea14f71f6a}, {0x000eee179067b242,0x0009f6bf528af895,0x00020985e852a279,0x000b94bc19691d5c}, {0x00005deba296ab7d,0x0000b231b9475f76,0x0000000000000001,0x0000000000000000}}, {{0x000c45d63f8d3bc5,0x000aab0d9145a0f8,0x000bc0cd8bbb3a1d,0x0001299d614875d3}, {0x0008bad650d624f5,0x000b91d8407baf74,0x00054a383b9d385d,0x0006840ae765f5cc}, {0x0005a54bdbe2653a,0x0002865728a0edab,0x0000000000000000,0x0000000000000000}}} }, {/* digit=120 [{1,2,3,..,}]*([2^480]*G) */ {{{0x000e419064732d33,0x0000fb9f1fdd6e2b,0x000b458dd169ab15,0x000b79def3f55fa5}, {0x0001fd9b88ebfb1b,0x000b8b17a8c1d98e,0x000e6b37f6beb8b7,0x000dbc72340b6c86}, {0x0007c19d37bb70ed,0x000f6867a99418dc,0x0000000000000001,0x0000000000000000}}, {{0x000a4a09f22c0fb3,0x000bb19cb6bc1256,0x00077d8b51c8ded9,0x000574809f35ca45}, {0x000bef1168ba7eb2,0x0002cdae11770b52,0x000ff68ed4f42bd1,0x0003d326b225de9d}, {0x00037f1445631a8c,0x00012cb14a3c371d,0x0000000000000001,0x0000000000000000}}}, {{{0x000b0b95f0603f03,0x000fa7f969adad66,0x0001acf774657813,0x000a2615220707f6}, {0x0002f71d4cd53712,0x000f82a44a2fd4ef,0x000773fd9e262931,0x0002f763ad200681}, {0x0009b206fe31fd70,0x000765c3a8767fa9,0x0000000000000000,0x0000000000000000}}, {{0x000a7f8ce84569e5,0x0009a821c3dd4741,0x000e90e3290cc915,0x000cf99306b623fa}, {0x000d7531760ae9e8,0x0009e7cf282874af,0x0006e1ae6527ae8c,0x0008f99eef73293d}, {0x00037109e03d3d87,0x00036ee1efdba892,0x0000000000000000,0x0000000000000000}}}, {{{0x00051928ed074ce9,0x000b292af7a58dcc,0x0005ec5d4bdfb374,0x000cdd85d01fb1db}, {0x0006e626365656d8,0x00074fc478641e47,0x00016a5e28d244d6,0x000adbaa94ddb39d}, {0x0007fdde95fd5183,0x000b47ea66d8626b,0x0000000000000000,0x0000000000000000}}, {{0x0004c9d4962ab02a,0x00021388f7fd2b57,0x0006c23d66031232,0x000a1a6ab2ca0c2c}, {0x00017664a406bce3,0x000f5497442ca199,0x000866b6f2fc1498,0x000a41cbc3b0ab32}, {0x000557ca37a277ae,0x000af01602653825,0x0000000000000000,0x0000000000000000}}}, {{{0x000db75622a8dfc2,0x0005479be9e5c74f,0x000548d39ec29bd5,0x0007942d29c79da4}, {0x00079c4bc1f5df3f,0x0004a7cecb948e1f,0x0008793b63229ed3,0x000939c1a7d67689}, {0x00057ad78be3b341,0x00052f2801351b91,0x0000000000000000,0x0000000000000000}}, {{0x000cbeae6fece889,0x000b3085ddee3b59,0x000eeab1d348140d,0x0006bba941a033c2}, {0x000b685703aafb67,0x0005046b6423a9d8,0x00075dab832a7c83,0x00015b8c259b9e24}, {0x00018a6bbb51f863,0x0003a253eb5dc8db,0x0000000000000000,0x0000000000000000}}}, {{{0x000cca37a85cafbb,0x000b3657f26e3623,0x000787ec793c4d2a,0x000337f7520b9137}, {0x0000dbcfb7906436,0x00018cfaf22caa7a,0x00044625a502d754,0x0000066c6a130ba1}, {0x0001212f51d083e4,0x0004ebb9541e99d2,0x0000000000000000,0x0000000000000000}}, {{0x0009384f4e2ab22a,0x000ff707cf7953a3,0x000aa5f9b05bdfba,0x000626e81b083e95}, {0x000defb350599782,0x00092399d206f421,0x0008bd9415729d3e,0x0008cf10387904ad}, {0x0006e0bc19370ad7,0x000b48f2c002a076,0x0000000000000000,0x0000000000000000}}}, {{{0x000b8bb85d8adb3e,0x00067b9a142f9bd6,0x000fc51be0f979dc,0x000cb118f84e32d8}, {0x000a7f5b6ca36f9c,0x000a900f565e79ab,0x0003143fcfd2df63,0x000122db9b751516}, {0x00086015e5f85f9f,0x000bf0e7c48af6d8,0x0000000000000001,0x0000000000000000}}, {{0x000cbc466d0dec7f,0x000fcfc13f4daf5d,0x000613ac2b0043ae,0x0007d2ec60909041}, {0x000eff4b79cb6956,0x000e04188e57b5e5,0x00045aa9dd05dcf8,0x0007cd8106c6759c}, {0x0004b84b0c6c633a,0x00041ee796334569,0x0000000000000001,0x0000000000000000}}}, {{{0x0008ed21f68b4a3f,0x0009e0f39b982afe,0x000ef033664df945,0x0006109c1245ad2f}, {0x0004d6578f9c34c2,0x0008e9fc097b7383,0x0007b3121a085c72,0x000365666df584bd}, {0x0007af58ed558596,0x0007e9fd1e18ec9d,0x0000000000000000,0x0000000000000000}}, {{0x00017df29af6bc16,0x000dbbf468848de7,0x000d747cd3b7c888,0x000801a051097e9d}, {0x000f68bb9b824e70,0x00027a8a5f172bbf,0x00074f9f45d5351c,0x00080ba6fcc24020}, {0x000d4e050d7e5a57,0x000cebcb9d2f1cc1,0x0000000000000001,0x0000000000000000}}}, {{{0x000b990fe3b9d773,0x000eb81096bf3df2,0x000eb580e653b2d5,0x000cfd31a2ad7396}, {0x00065cddd150bca4,0x000cde916b4cdae8,0x00019b56ffe74e35,0x00021e7dc0b21b6f}, {0x00099d8bf333016e,0x000eb146cec318c7,0x0000000000000000,0x0000000000000000}}, {{0x00030acdbab36d51,0x00089ddd1e911c98,0x000891db5801a0df,0x000f1a5d646bbddd}, {0x0000ac4d27510e25,0x00044af2f910d55b,0x00024a75bcea08e1,0x00037ae5f37d50da}, {0x000d372739ad211e,0x0002a2d9d5c41773,0x0000000000000001,0x0000000000000000}}} }, {/* digit=121 [{1,2,3,..,}]*([2^484]*G) */ {{{0x000ce74763660052,0x000da3e409da1731,0x000098b5f715b328,0x0003538d607382a2}, {0x0007bc3ee7b0651c,0x0006d5eed9abf1dd,0x000eb18e8c0d16d9,0x000e3fe464dc1a4c}, {0x00030d6fa6b9f8f1,0x000cfa359d987d0c,0x0000000000000001,0x0000000000000000}}, {{0x00047d09810803ed,0x0007b5b97b578929,0x000cc27fc5005d73,0x00040feb2087e2c1}, {0x000b7dd0d960662d,0x00025ee555f37345,0x000d7c17f3858a72,0x000a0cf2ae739ae8}, {0x00000ee77dcf4e1a,0x000c12649e41ecee,0x0000000000000000,0x0000000000000000}}}, {{{0x0008de672d619b61,0x0000ea8326922a80,0x0001a0841b015626,0x0000f8a963e3e317}, {0x00037806aeb44acb,0x000d9d8a14334837,0x00026bd761a3419a,0x000d2e7a343fbffd}, {0x00086e32c6d361b6,0x00023ef433219c4d,0x0000000000000000,0x0000000000000000}}, {{0x00025620f22d4f25,0x00067dd5c03d381f,0x00080f734643a87f,0x00006c5ee876505e}, {0x0002b491baac4e49,0x0003e07deb178a01,0x000ad060f735b869,0x000576ce5dd8d75f}, {0x000dd4cd9c97cb18,0x000cbc634bbb55f5,0x0000000000000001,0x0000000000000000}}}, {{{0x000b9733710e8e01,0x000e73a5711788b8,0x000bf8afcacf73a9,0x000d6725ee57149b}, {0x000e7fe486c64e2e,0x000322f9087bd5a6,0x00009af08709418b,0x000084990390cb99}, {0x000a6bb3ab911d03,0x000d2868a69e665b,0x0000000000000001,0x0000000000000000}}, {{0x0005e749b382f6d2,0x000a9a1034406b89,0x000826ec06265b52,0x000e64e9aec95b07}, {0x0003982f9a9c5d16,0x0000698b37d7e83c,0x00050d8bbdbeb42b,0x0007c82f4fbc8ae9}, {0x000adc1e63d423d5,0x000b249310802372,0x0000000000000000,0x0000000000000000}}}, {{{0x0007033614a6d5dd,0x000fddc5f2fac137,0x000e014aa4b4dee5,0x0004a9b72218fde8}, {0x000c10e229612a68,0x000cb5b99f1d9b66,0x000eff01796c1307,0x000ec087152271c7}, {0x0009f171d27930b1,0x000dd53091f21ad1,0x0000000000000001,0x0000000000000000}}, {{0x0004c873e4172f54,0x0006ecbd512368a7,0x000d3ea21d4bc31a,0x0003a95f62eff689}, {0x0007c73a33474bd4,0x00088fa97a141350,0x000b4d3b01846eff,0x0005fbac8f6a8f06}, {0x0009ddd58dc2a301,0x00001f7b911f1a15,0x0000000000000000,0x0000000000000000}}}, {{{0x0002e681058bcd0b,0x000ecb766f6bc98d,0x000866fedccaaef5,0x000b2e2473204d11}, {0x000f6e18757016ad,0x00011d59effc1a8a,0x0002050629e88cfc,0x00093c7bdc024782}, {0x000a9b2aeb9bb00e,0x000336991f06d2c0,0x0000000000000000,0x0000000000000000}}, {{0x0001568955531744,0x0008281170681859,0x00050d7be99cf6e1,0x0008cb9d185c0963}, {0x000f49cfc22a2afc,0x000f9d20626a2a56,0x000ad87b48f04b95,0x000bd1441cc30d3e}, {0x0003e9b72d43f56f,0x000e3b3843d17383,0x0000000000000001,0x0000000000000000}}}, {{{0x000e873b05f77e97,0x00071d5ebf3c8d2f,0x0005b9ca7cc32fe3,0x0008798cc245b054}, {0x000e6eaf83f8b265,0x00061d87bdf09afd,0x00048a529e1b9707,0x00001501c97ba4fd}, {0x000ca96655ab0a10,0x00042f0ec7beee1d,0x0000000000000001,0x0000000000000000}}, {{0x000296b82c7a9289,0x00070c171dfdb228,0x0001dac3a3a171bb,0x000b7ea6ad9a13af}, {0x000251fe361dde21,0x000cea9acd2f8b81,0x0008480e8df3c1ec,0x00038a5f495ca4b4}, {0x000fd225cb8ecc78,0x000454bc6bffc707,0x0000000000000000,0x0000000000000000}}}, {{{0x000af33412f12687,0x00015e41163cf0f3,0x000967fdc5a6a476,0x0004235cf9f62e34}, {0x000b314d06a6a848,0x000820f5665619a2,0x000f11a14ea427a8,0x000ce9a80c44b6a1}, {0x000f92bed7985fca,0x000dc713540bdff6,0x0000000000000001,0x0000000000000000}}, {{0x00065826c0cb51e6,0x00030220ec95e76a,0x00064aea77a786d0,0x000cb5ba9e93c602}, {0x000f020c5b781189,0x000e7b4655282299,0x000e97af8ea95e4d,0x000a8a80a0f194a4}, {0x0006433581c41d62,0x00066e34a29ca8e3,0x0000000000000001,0x0000000000000000}}}, {{{0x000cef36ab807b63,0x000040cdf4c99984,0x000c211953a5f8d7,0x000ab4c0faefc5ed}, {0x0005ca17066a1563,0x000fb2c0940c339a,0x000b1e8517a5667a,0x000c3d2a94a0b135}, {0x000185e4d4526e2e,0x0001b53c05d493d9,0x0000000000000001,0x0000000000000000}}, {{0x000c5ced3676f843,0x000195ff470fab2f,0x000ed29f4a221ddb,0x0000868b2d94f5fe}, {0x0003caf8fcc5069f,0x000dcfc1418631be,0x000998943a070623,0x0009bafa5f731c9d}, {0x000c5c56c1cc4a06,0x000a82f502e626e1,0x0000000000000000,0x0000000000000000}}} }, {/* digit=122 [{1,2,3,..,}]*([2^488]*G) */ {{{0x0009edf282d019ec,0x00099e8e335e18d2,0x0004ace8ce0e046e,0x00001d0f72c0503a}, {0x0007e9c6d09e242f,0x000998b6c2fcb456,0x0000be40686ceb13,0x000db8fca6af9143}, {0x000c77e852236ef5,0x000ba3718e1a2901,0x0000000000000001,0x0000000000000000}}, {{0x0005ae430ab427d9,0x0003d8a843a1b6ab,0x000c9500fb6025f6,0x000b9cb8d803e788}, {0x000fcea023d9bfb7,0x00003f3ec5cdad70,0x000188da7e50d4c8,0x000f9eb540fd9c07}, {0x00014ab57822ee2a,0x000574aff12ba00d,0x0000000000000001,0x0000000000000000}}}, {{{0x0003c20dbe0952a3,0x000480b6013f7fd5,0x000447348d109d4a,0x000fe6fecb6a7da1}, {0x0006564e8c529d8b,0x000034045fa60672,0x0003ee2a8df68fa9,0x00021796dbc7ff3f}, {0x000a130fededc279,0x000fe24c3f368ae9,0x0000000000000001,0x0000000000000000}}, {{0x0002961eb9eed66d,0x000919ed55f27279,0x0000068193a9b014,0x000f317444cb0bf8}, {0x00096e22227ee32e,0x00047c8b854cb4a8,0x000bf6dc6a73b281,0x000d6804296e2ed1}, {0x0003e6f8a77be001,0x00084c89b143ab22,0x0000000000000000,0x0000000000000000}}}, {{{0x0008d791f2d40215,0x00003b05d1fd525c,0x00037b16b3ca30ae,0x00070792a856131f}, {0x000b7639faf0f678,0x00006b7cf12eff42,0x00098ab7a44f2173,0x0006714e846ec06d}, {0x000eac350874a266,0x000b56e5920dc3ae,0x0000000000000000,0x0000000000000000}}, {{0x000d703e34853d1e,0x0002cd53a7cce717,0x000410bff4f394e1,0x00074ecb0bba0cc1}, {0x000de8fa9da2c436,0x000f5e3f74e2caa0,0x000cc28b148d1eb1,0x0009fc1ac5bad585}, {0x0001220666fb73af,0x0000c3241a57ee07,0x0000000000000001,0x0000000000000000}}}, {{{0x0000e99218ea1f1f,0x000ccf21044500ec,0x0000c873630cba88,0x00064f806fd4e4b8}, {0x000a7056645dd457,0x0002ed87394551a9,0x0008987025ba6b17,0x0005dd01b45fa9a7}, {0x000ccea3a1f9f135,0x000592807cbab8d2,0x0000000000000001,0x0000000000000000}}, {{0x0006c96e8e24e119,0x000d921a51e8134c,0x0002ab9759957065,0x0004035ca89e1baa}, {0x000df057c2aafabc,0x000c0890aa1a6716,0x0006bd3f802387d9,0x0006a39383e5c778}, {0x000601e4e1f62705,0x000096f226577900,0x0000000000000001,0x0000000000000000}}}, {{{0x0001d3b5076ee66b,0x000068e996c31106,0x00063f8bf5d922ca,0x00008ed44203a2fa}, {0x0001df0821d991eb,0x00019d54e602f04f,0x000bf35cd4ee7bb8,0x00015f2609e3729a}, {0x0009e8e65b2fcd60,0x0001df9e9c109298,0x0000000000000001,0x0000000000000000}}, {{0x00058eae5edc3042,0x000fe31ba09cdc97,0x0006f52853b56fdb,0x0003df0f5ca36adc}, {0x0000a54940d61878,0x000902cef58665ba,0x0004efbb68e67641,0x00036806e0aaf0f5}, {0x000194a89e785e8c,0x0008883379ceb241,0x0000000000000000,0x0000000000000000}}}, {{{0x0001a19f7b341ee3,0x000076e0e5354bd1,0x0001806a485286dc,0x000d2bf681431840}, {0x0002c82334b1343e,0x000b6908add258b2,0x000737bf47a5dbe4,0x0007303c531a0b11}, {0x0003a29d6501615d,0x0009313aaea01e10,0x0000000000000000,0x0000000000000000}}, {{0x0007b22b906a725c,0x00024ad4ce011033,0x000bf242639d28fc,0x000fa39cd38de6c9}, {0x000a72beeb0f8fd8,0x0009a0ad9b93380e,0x000c8221fc799b7c,0x000be51116d9d8de}, {0x000a10526402ca53,0x000777aa2c9ac3b1,0x0000000000000001,0x0000000000000000}}}, {{{0x0001a723455b8da2,0x0001d0c7c777796b,0x000fb41cc9b1644a,0x0000ef5ce0972939}, {0x000637a26ddcdf7a,0x0008cf1a639f0844,0x000023a3ce642ca3,0x00098f7db827cdb3}, {0x0005279eee7f6f0d,0x000565523e47e762,0x0000000000000001,0x0000000000000000}}, {{0x000fd1b034828d4a,0x0000721a61eafcaf,0x0001ce95f4ec0ae3,0x0003ba2db4a66fba}, {0x0006525e6f06fee9,0x000817b26fcb0ef3,0x0000265db68ac06f,0x000f74e811cb24b3}, {0x0006550f9c2bf885,0x0003940f2d2fcd83,0x0000000000000000,0x0000000000000000}}}, {{{0x000e8955d1b109b2,0x000e1de1d0f381d4,0x0006407a6cf45a79,0x000f2393e689a76d}, {0x000d3d92aed2a407,0x0005547cc6ac261b,0x0005e0b9e62fcac9,0x00081e2910774983}, {0x0003d6780dde8f90,0x0003c5c4cab77f7b,0x0000000000000000,0x0000000000000000}}, {{0x000e052d3f3dc82c,0x00039caa1aeecdbd,0x00024153092958c9,0x000c11b7ca5c0f7b}, {0x00027c92847965c0,0x000732af643698d8,0x0000367351c0ba1d,0x000f1b1bf491a3ee}, {0x000df3514ec2302c,0x000b4c4436d640af,0x0000000000000001,0x0000000000000000}}} }, {/* digit=123 [{1,2,3,..,}]*([2^492]*G) */ {{{0x0004265bd7179d88,0x00032014b97128c5,0x000fd3dafdfe0b08,0x000b1956b3fd6699}, {0x00091416a87bbb8b,0x0001dd4344038f86,0x000566c88826c840,0x000f07a8a4b77456}, {0x0007671e1b2fca59,0x000200797dc52a03,0x0000000000000000,0x0000000000000000}}, {{0x0007843bbe8d7f70,0x0004f9ee9b4c465d,0x000303b1652fa39c,0x000ae7c4c4a55ae2}, {0x000263ccdcb67c15,0x000a17fd06da8ac5,0x000c10d8d1d1e927,0x000e5bfc6232685a}, {0x0003162cd048bbb8,0x000b11c2cffebb23,0x0000000000000000,0x0000000000000000}}}, {{{0x0002cb202ec3c178,0x000285de81ad92d1,0x000b71b77497dfd0,0x0007a8a10c150a03}, {0x000bbe99f4ad3f59,0x000f4533b0aef51d,0x0003b27838ed4931,0x0008ffc95a8ebcf1}, {0x0002cefcf5623ddf,0x00010737c166832b,0x0000000000000000,0x0000000000000000}}, {{0x000e740d8da2ff7e,0x000624f3d3ab048c,0x000376415ced03ed,0x000fbe5676391c7d}, {0x00081671ffe7b22f,0x0000390438cc5f49,0x00084a5ae289dd49,0x0008f9a1f5bbef09}, {0x000b05c4941c6652,0x00083aef77ff073e,0x0000000000000000,0x0000000000000000}}}, {{{0x000604a9bc6900b6,0x000878e5f51ce9df,0x000b763f98cad97f,0x000f5a1389d3ab54}, {0x000ab3d0efdef6fe,0x0009be5cf0df2543,0x0002a0d518696763,0x000134850193d832}, {0x000860abf9047761,0x0004b4f04b3d8de0,0x0000000000000000,0x0000000000000000}}, {{0x000e57c44a551894,0x000a3fa66238e065,0x000d140af7878a12,0x000de14d55dcc858}, {0x00061c7b391cc65f,0x000d7dbf324d8825,0x0005d09aa74e78f2,0x0008ed166a4503f8}, {0x000da0c2a7ad860c,0x0002048d8fe387e6,0x0000000000000000,0x0000000000000000}}}, {{{0x000505ddc7162a8e,0x0001fb5ed0deab66,0x0005e972cc689dc5,0x000e495fb69dc78b}, {0x000ca3f1826690c6,0x0005f6186896d605,0x000fd32f66789288,0x0008863f96f8edfb}, {0x000e644e5dece22e,0x0009b7f857a4d564,0x0000000000000000,0x0000000000000000}}, {{0x000691ddbeebfc5d,0x0005901566a70055,0x000e1f4e6067fa43,0x00086e62796a672c}, {0x000b4e5ee14cf308,0x000b327c1a40aaca,0x0002fed3294bd689,0x0009103e56992c00}, {0x000b1323df8494f5,0x000d7b51fec2bb9e,0x0000000000000001,0x0000000000000000}}}, {{{0x0009f1b91641749a,0x000415c17bca5ff6,0x000c6d3a845d2248,0x0005f9b6f404856a}, {0x000cbf400b63630d,0x0003b4ba273b60be,0x0005d238fa843e67,0x00015df9fe916d32}, {0x000747b338f22dd6,0x000213df0dde0478,0x0000000000000000,0x0000000000000000}}, {{0x0000235c1fe8e923,0x0003196a6c0855b8,0x0009e7caa33347ee,0x000bc0a45596b47b}, {0x00011e3fa8377c58,0x000acaedbc6f8b16,0x000fc365c99edd72,0x0002dbbec0f6e0a6}, {0x0002b70a4b7723c1,0x000a4bf65f3c20c8,0x0000000000000001,0x0000000000000000}}}, {{{0x0004bf14c1a4d603,0x00062d773ba946d2,0x000a858973ed2e17,0x000af47e821e4637}, {0x000c4e2f1b685a3b,0x000a24d7fe743f00,0x00011c916f0b3711,0x00019d3f29631796}, {0x000070eeb3ea27a8,0x000fcf9d0e9d8d24,0x0000000000000001,0x0000000000000000}}, {{0x000a9e0cc6d6de0a,0x0007d8c5fca34ad4,0x000c81d46494c7d6,0x0008c618856d1751}, {0x000ea22fc514e835,0x000e085f741c8235,0x000c321d004a049d,0x000bcb516087e553}, {0x0002d6363ccbbe68,0x00083e572fe7f6b5,0x0000000000000000,0x0000000000000000}}}, {{{0x000e20ba96faf5c5,0x000e8d8c8a0cc4ab,0x0009b5c593a344d4,0x000c6c34af049395}, {0x0005aa8d456d94a3,0x000ed953bf7c9473,0x000962cd0b8cc1dd,0x0000c01bb3088b5c}, {0x000c82c42c7d7139,0x0005bd26c576d9ee,0x0000000000000001,0x0000000000000000}}, {{0x000ee2f364e79144,0x000e681f5a9a561f,0x00014c6812d4021d,0x000e552f50051d32}, {0x000f6a99f35033a6,0x000e505a2349153d,0x0001622a1be8e97e,0x00067971f625164b}, {0x000d441d9fc2328e,0x000d2eb0550478b4,0x0000000000000001,0x0000000000000000}}}, {{{0x000769c73aea3c08,0x000df9a9593240cb,0x0004e8217f3b057c,0x000ceca2220054ab}, {0x000c95ba1c2a734d,0x0006500d1322b719,0x000ec571b4360381,0x0006f76e87cb0ba1}, {0x000c5938559db2c7,0x000397be033b5877,0x0000000000000000,0x0000000000000000}}, {{0x000b6a77feb075ca,0x000d9cc6a6cde3dd,0x000e49872538f578,0x000e469feaf37819}, {0x0002ddc9c48cda10,0x0001a6e5450f9883,0x0002d31bf05ea5f5,0x000375cd216a195d}, {0x0008007e689987c4,0x000cbc358f3e07d1,0x0000000000000000,0x0000000000000000}}} }, {/* digit=124 [{1,2,3,..,}]*([2^496]*G) */ {{{0x0006a73f6f2770c4,0x0000f968ca281cd6,0x000827efca6a0867,0x0003a96b180e8f32}, {0x000809979b757eac,0x000d9223bfbff7df,0x00047dd166015fc2,0x00065475a88730d7}, {0x000ce16229ea9d12,0x00076d23756de3fb,0x0000000000000000,0x0000000000000000}}, {{0x000ed537bee27c6e,0x000943e46c7c15a8,0x0004b3f87656d7df,0x000a9213335be530}, {0x00076cb0ee208db8,0x0004f5fc16b61ee3,0x000c1114ee85495a,0x000253ced62c2d47}, {0x000641c92453ad35,0x0003e4e1a21d73af,0x0000000000000001,0x0000000000000000}}}, {{{0x000483ff2c9de102,0x00017f0cb9492bab,0x0001999673c19107,0x0005c7a75ba40ad7}, {0x00022ec8c1ec861f,0x00078704457a9540,0x0001194ab6d023c8,0x0000daf5008c607c}, {0x000d394925361233,0x0005ab5bf20a934a,0x0000000000000001,0x0000000000000000}}, {{0x0008ed3301b16277,0x000b31045574d7ab,0x000ed11cb44f38e3,0x0001af67ab10bb4e}, {0x000d033cee10ca51,0x000549874c9fe7c1,0x000392d6999489f1,0x000ffcfe4a15a85b}, {0x000b006a13684dec,0x0007b8baefda3eb3,0x0000000000000001,0x0000000000000000}}}, {{{0x000e82cbfe7306a8,0x00002e52832eb494,0x000b381c8b461b41,0x000a6e877f0afbca}, {0x0006b8482ae88f1b,0x000709eb28c8cc07,0x0000cd45fc8e5ced,0x000b1363d1cf0c64}, {0x00093a63d6be8f78,0x0001407a8e7f6a49,0x0000000000000000,0x0000000000000000}}, {{0x000fd703c088bf64,0x000708b3415df01b,0x000f82eeb2c8b57f,0x0003ed35407aa69d}, {0x000449767c6b4a72,0x0002e1a8184dbc3f,0x000d25edffc3e965,0x0003e8855e29ad89}, {0x000c695a889f2e49,0x00025dae2a995ab2,0x0000000000000000,0x0000000000000000}}}, {{{0x000c300d63dacf22,0x000f84149cc93249,0x0004f71e87a984e1,0x000ebeada635f884}, {0x000cac51f48942eb,0x00076c6b878d815d,0x000587460dede95b,0x000883c91cf8c3f2}, {0x00013e9be5375387,0x00076d4ce987a56d,0x0000000000000000,0x0000000000000000}}, {{0x000fb20151675f42,0x000bf54bf1c2d622,0x00022da7f9e8bc4a,0x000051b0e7b83f3a}, {0x00073eda536a6e42,0x000ce8431a9d89d5,0x0002b7a64d23c5a3,0x000007a6be7b3eec}, {0x000672919b5fb43a,0x000c454a7d18005b,0x0000000000000001,0x0000000000000000}}}, {{{0x0009f484a29e97a0,0x0005e90aa411ba92,0x00016fc135a72a99,0x0006cfa3c8dd8a3a}, {0x00066efeed6df222,0x000e66eb40ebb1a2,0x0000f8ad15ad7b0b,0x000e0c3a19929e39}, {0x00051e3404d13a05,0x000175cf393bacd1,0x0000000000000000,0x0000000000000000}}, {{0x0006cdbeb4d89814,0x000b884f6ce10295,0x0003138d1321a20d,0x0006528c4bd065b9}, {0x0003d082878ee395,0x00029465651ab383,0x000cb4e49e6b0dcc,0x000710248d30e955}, {0x0006e01a51ae9cc3,0x0002fc5567eab89e,0x0000000000000001,0x0000000000000000}}}, {{{0x000c59218072f54a,0x000195bad5f014fe,0x000deabd55429cb3,0x000b2ab5fb9c1406}, {0x0006cf39524ff8ca,0x000fbb57c01480bd,0x00018cbc932f5376,0x000c9e4e5da034f1}, {0x000fb16c36eb8d83,0x000048c80fc4eaa6,0x0000000000000000,0x0000000000000000}}, {{0x000668aa11e1cfe6,0x000d4f614afa98be,0x0004cadab479a412,0x000864b0b94d7822}, {0x0002651053a74933,0x000dd43fe6424e5f,0x0004f2c600bdaac3,0x000ec0b432ccf8a0}, {0x0004d82574257110,0x00024e58edc3e12f,0x0000000000000001,0x0000000000000000}}}, {{{0x000d5163c2f29845,0x000271b8856ff717,0x000a79d0557c5c08,0x0001484032810d21}, {0x000a5a6e95174165,0x00093b8782ce8f06,0x000a6f7f14b15d03,0x000ca398eeacdf3d}, {0x000eb31c7c040c1a,0x0003ace9ed34f4d2,0x0000000000000000,0x0000000000000000}}, {{0x00086bac2cc4ff50,0x0008d5294f7bd063,0x000ec0b7a55f986d,0x0006868155592285}, {0x000e215833824965,0x0003366d9a307162,0x0001de9196efa150,0x00076afbb75f7833}, {0x00046ce65ce11aa8,0x0002f7a207e31942,0x0000000000000001,0x0000000000000000}}}, {{{0x000d6129f7d0fa54,0x000150bddf5a7cf8,0x000b4988625b2f43,0x0009bbfb3c2f3809}, {0x000f5b080f7b3129,0x0000ab0abb84ed45,0x000510d824f7bed2,0x0006d6447243533e}, {0x000c576b7b64fbbb,0x000e16caa9ee8267,0x0000000000000001,0x0000000000000000}}, {{0x00053a269ea0b07f,0x000e06f68fe62242,0x000a777b6874572d,0x000d5f86cf599bf5}, {0x000fe2a811045a16,0x000873264294a33d,0x0007a04ac970a0c0,0x000ceb2b7d05d686}, {0x00029a28a0e51a57,0x000bacbf79a38ead,0x0000000000000001,0x0000000000000000}}} }, {/* digit=125 [{1,2,3,..,}]*([2^500]*G) */ {{{0x0003efe866dc2f62,0x000853cb9e407c10,0x0000e6c71edaaa13,0x00018f751b70a2af}, {0x000b0cf7e3e825ae,0x0005c36a5a1ec11b,0x000487f56ab4b564,0x000a86df052ea4e5}, {0x000d750313868ef9,0x000e60ee422740c7,0x0000000000000000,0x0000000000000000}}, {{0x000ee652bd47edd5,0x000397faa97f40b7,0x000294d2d1ba3dd7,0x000344d3453daecf}, {0x000d324bd3f56e65,0x00078c6f611c9985,0x000e24f2675985ec,0x00038b4060d38ad7}, {0x000dfb7496c92821,0x000be627a6ad57ff,0x0000000000000001,0x0000000000000000}}}, {{{0x0009be6a7e5a166a,0x000d06313031bd58,0x000704962d984289,0x0002ec5b522512df}, {0x000386a669eef493,0x000fe747674db075,0x0004dbaabd7aebbc,0x0004d27fb22ce794}, {0x000e70494458ef81,0x000fadc96805636a,0x0000000000000000,0x0000000000000000}}, {{0x0005b60c511b3ff8,0x000584915adb1e6c,0x000f8937e8e108c6,0x0008406d64ea3a9f}, {0x0004461d268f9ab8,0x000e3ff279d6126f,0x000d3b3ed1f3032a,0x00023a1b63af22a5}, {0x000caf9282fd7a53,0x000d99f7a42a7590,0x0000000000000001,0x0000000000000000}}}, {{{0x000dfb005014a6bc,0x000d36179f05f79f,0x0001f0a00c591c70,0x00009f861bdb8aa0}, {0x000851877e4cc13b,0x00004921bdab098b,0x000265f47ca34718,0x000478a5d59cb874}, {0x0008aac74eb734d8,0x0002f6a87e5bc7bb,0x0000000000000001,0x0000000000000000}}, {{0x0005dd559082ec4f,0x000fd3340b409a63,0x000e395e6174cff9,0x00035fdf83237476}, {0x0006e995df5d90e4,0x000535beb0acf902,0x000ddc2f60fe3f20,0x000821d68a60c3ba}, {0x0008005435d079f0,0x00084ef7a20c388b,0x0000000000000000,0x0000000000000000}}}, {{{0x0001ce9624902c85,0x000dacee54d7fc06,0x0008e982883e676d,0x000cea68fc5997cf}, {0x000b94f3d06f1e8c,0x0007b80d8242831b,0x000ec2e625c36045,0x00015466a1d87389}, {0x000c5009313ff25b,0x00045efb5d45d1f9,0x0000000000000001,0x0000000000000000}}, {{0x0004e32c6f246301,0x00064608ec78b5ab,0x00053a9c0b324014,0x0004ddead5ffb795}, {0x0008bf933bdcc559,0x0005249289dc110f,0x00047d25d52f652d,0x000d95ab06c0cb41}, {0x000bbff17968adb2,0x0002664039be6fa1,0x0000000000000000,0x0000000000000000}}}, {{{0x0006c159dee64527,0x000d486c1da85118,0x0002ffecac887f87,0x000401c5326e8ac4}, {0x000fe68a082d270a,0x000b17b4ec0bd703,0x0009b1a9fe82427b,0x0008f75c6b25d502}, {0x000ac56e28859df5,0x000bc70f97f9bffa,0x0000000000000001,0x0000000000000000}}, {{0x00073b932e4e3e21,0x0005f8e721dc13af,0x000825bde1498f11,0x00080fd3102f60c7}, {0x000f292e5a9e9f07,0x0006a4edbc9fcac3,0x0008f2651ae44279,0x0002622ca1bb123f}, {0x000a4ca103d2d6a7,0x000ca577d0f1994f,0x0000000000000000,0x0000000000000000}}}, {{{0x000e577af10e1302,0x000156bf557eaa33,0x000ca7cba0f98005,0x0001e9d6e3d41486}, {0x000ad3a30b9f973d,0x0009856b55aa3443,0x000724f819219409,0x0008250cf13f0ca4}, {0x0006f0f69ba1696b,0x00063bba1deb1e9b,0x0000000000000001,0x0000000000000000}}, {{0x00037cb6672f9435,0x000d7e7437eb08a0,0x000579149c6faf55,0x000e4c6943f7c61c}, {0x00026eba03e36921,0x000a3ade34c342ab,0x000052386264eb60,0x0000ffc57653cf12}, {0x00070eec7914e6e2,0x0004912d67845657,0x0000000000000001,0x0000000000000000}}}, {{{0x00006fc3e072e1bd,0x00066e9739a62b31,0x0006ea97e6ad1669,0x0002aa2bbc843284}, {0x000871768bc4f0fb,0x000a51f2d1bd1f5f,0x000245a8890f99b0,0x000b6a0000aa5f53}, {0x000547c1538e0dc0,0x0001c33dbece2149,0x0000000000000000,0x0000000000000000}}, {{0x000b56de17b97c51,0x0000fccb15a8e3ea,0x000c00352a78e0ff,0x000e7d480dae3bf3}, {0x00092273cee30716,0x0000962a4283dde8,0x000e674e18ae53b0,0x0002b8c78835cb2c}, {0x000faee271217641,0x00046294e0f5e7c6,0x0000000000000000,0x0000000000000000}}}, {{{0x0005697612d854d6,0x000590266d871a78,0x000015aa94be7df9,0x000482ac4e8bbf72}, {0x0007c12880439150,0x0003495f23aa4b2f,0x00074815ef777bb5,0x000838a798c004a6}, {0x0008a425cc7aadc8,0x000c432ccb5f5730,0x0000000000000001,0x0000000000000000}}, {{0x00006af85640f288,0x0003a6718ebc6cb5,0x0002c50bba9dd21e,0x000e3c4d56098fde}, {0x000a4a8a721857b6,0x000218f9c402f4d7,0x000a6f255530e5d9,0x0000bf7b3c63a541}, {0x000f0181b97421bb,0x00023de7a08f2804,0x0000000000000000,0x0000000000000000}}} }, {/* digit=126 [{1,2,3,..,}]*([2^504]*G) */ {{{0x00061ebad9ee2c24,0x000dd46aced3ddaa,0x0000bd3e3fde5fe2,0x00020569fe14f9f4}, {0x00088d818d1a2095,0x0002f0bdc9b4968b,0x000e3de0b8b77328,0x0007fe9e8edc6520}, {0x000017cf0272ff76,0x000eda0f65dc99bc,0x0000000000000000,0x0000000000000000}}, {{0x0009b50b03dc034f,0x000ff04ea634ab0a,0x0007b191db6e6308,0x000a9de7ee04399a}, {0x000e6da7bdea8dde,0x00054c55ae492d45,0x000f4e939e666b7b,0x00090c925a51f573}, {0x000f916220292c15,0x0002d380fc7f5071,0x0000000000000001,0x0000000000000000}}}, {{{0x000639a92b83d191,0x000b3a1ce7b1b453,0x0000d260e431474f,0x00032954aefab808}, {0x0006dfaf9e670c4e,0x000e42d0d7b5bae7,0x000bfa89eb4687fd,0x000c7d89b1ca5f45}, {0x000ecce4fba638bb,0x0008a21de873fcc0,0x0000000000000001,0x0000000000000000}}, {{0x000c9c2b49165fd5,0x0005fb318f9f9636,0x0006f676d6c2cb81,0x000c633a7560919e}, {0x00011e2d4752541c,0x000199c5999a79e2,0x000515dfbee081ee,0x00053107dec5265f}, {0x0002bdc9ed0ea4e2,0x00041c5a539ab36f,0x0000000000000001,0x0000000000000000}}}, {{{0x00009de7ecb2ac56,0x0002d837bb7a345c,0x0004863cfd4369c7,0x00077c66a5755a3b}, {0x000682ccc872cef3,0x000bc1363c743442,0x0008b997f1a0d907,0x000d72224eed734a}, {0x000d1850457f924f,0x000f3bbd996258f2,0x0000000000000001,0x0000000000000000}}, {{0x0004953714391350,0x0002a08de1fb04ea,0x0009bb0ca7d3f0e3,0x00020e2fc4a54760}, {0x000d525812eece55,0x000dc3c7c680f4ea,0x00064f097079b269,0x0001e81a267b891a}, {0x0002df53061afa20,0x0007339d7335dbc1,0x0000000000000000,0x0000000000000000}}}, {{{0x000fa11c22d57017,0x0007061bfc65866f,0x000e25c9a781f882,0x00052d54eb5d1a25}, {0x00034e5fcb1fe128,0x0008c5dfb74f3317,0x000cca2e48b7e54d,0x0005e9b41639cfad}, {0x000e1f8c2193402d,0x000348c49e8f71b8,0x0000000000000001,0x0000000000000000}}, {{0x00033ca43943f50d,0x00016ce98a1f644e,0x000bd595ac8a7cb4,0x000d4eb1e328cd45}, {0x000e8ec3fd8cbf8f,0x000eb626b0f768cf,0x0001524476b1bbc9,0x000d8d0ffe31069d}, {0x00025aa89220edd8,0x00063660b3755829,0x0000000000000000,0x0000000000000000}}}, {{{0x0003a78191abe914,0x000aed083110e37c,0x00072de9a657b228,0x0003d434d0dfafec}, {0x0009778c8ba568ce,0x00021f193e09ab8a,0x00032b59891165df,0x00090a0e20c8f7ac}, {0x0005b8a1f64088c4,0x000b717ed2f2d69f,0x0000000000000001,0x0000000000000000}}, {{0x000ac4849a39a0ab,0x000e9224368b5d72,0x0009a57abd9c0589,0x000f04bfeb21218d}, {0x00049bfe57f2080a,0x00082fbca66b72d8,0x000f0c09eaa93852,0x000e04db305e15a6}, {0x000bb2bcc4365052,0x000d0e18047907b5,0x0000000000000000,0x0000000000000000}}}, {{{0x0003c1031f4f778c,0x0009bbc5cc621ce8,0x000ac957c67434bc,0x000a368627bcbc47}, {0x000adace0a905430,0x0008aa0831ed2cb5,0x000c11d0f4f5d323,0x0001c48e91c91fa3}, {0x000229765edbfb35,0x00032bdf2591e498,0x0000000000000000,0x0000000000000000}}, {{0x0008e455572bcfd0,0x000ecba53bea9ae3,0x000196518c997db1,0x0005c33258970b56}, {0x000a3c6b46d1e689,0x0008e44ad30fe772,0x0005dd6482160561,0x000b86d1933faf1a}, {0x0005a53d718ae6de,0x000e4e4345a6badf,0x0000000000000001,0x0000000000000000}}}, {{{0x0009f15950170034,0x0008a7d9e0681bfb,0x0002dc602830c283,0x000e8af178838dfd}, {0x000987d3f8bcc134,0x0008904081cb94f3,0x000a460c0da2bca6,0x000f718b8913d63c}, {0x00022ed274e647de,0x000ff3a58fd52338,0x0000000000000001,0x0000000000000000}}, {{0x0002950ff4836dad,0x000fe4a51fa111b5,0x000e13de206b61a9,0x000941373ab42508}, {0x000c7bf8c1651d7a,0x000dbd9276666a02,0x00056dcdd411c37b,0x000f5a9ab3e87536}, {0x0000f464671775e6,0x000bc59bc827eaae,0x0000000000000000,0x0000000000000000}}}, {{{0x000eafce57fbc903,0x00072ba11885f40d,0x000d640aa98f9421,0x000bfcf817ce6b52}, {0x000389d8e40bcdc1,0x000c804e7d14a7d6,0x0008fa880e955163,0x00034af7c92b6304}, {0x000fd685115381b0,0x000faf73ec6a9688,0x0000000000000001,0x0000000000000000}}, {{0x000f85d1af3848b2,0x0008716ba36666f4,0x000fbfc6c17f47de,0x00003b35f9474540}, {0x0004b72b1ddc670e,0x000f48bdd3ad6387,0x000d7cfd249ea687,0x0009c16141926a15}, {0x000d8d963e9d101f,0x0000771b9b1c2fac,0x0000000000000000,0x0000000000000000}}} }, {/* digit=127 [{1,2,3,..,}]*([2^508]*G) */ {{{0x0006bccc65f30461,0x0006e44b51d15f3b,0x00061b0ed084d989,0x000f84c9df4f3be0}, {0x000626ed8e29bced,0x000a49395cf45bde,0x0001bfb128499bea,0x000d30e7b9a9812a}, {0x0000016d9442e44b,0x000577251b4710e5,0x0000000000000000,0x0000000000000000}}, {{0x000c58ea8faa5f8e,0x0006398972e1afb4,0x0002d603c3a6a3b7,0x000090f464b41953}, {0x0003e1c1cc6d5ad6,0x0009fc4551644bda,0x0003bf0e003b3c67,0x0004879a2d4dc4fe}, {0x0002492059f3993d,0x00089490933a0bd0,0x0000000000000000,0x0000000000000000}}}, {{{0x0003d39ba21abe88,0x000b8dfe497366b8,0x0003fb2e32d1a08b,0x00040dcc68fadea4}, {0x0009bc78d9e5b900,0x000999242f620135,0x000e38d4ca94e098,0x000f3e9a937783f1}, {0x000c271edf5e42de,0x000cdad3d42e09c5,0x0000000000000001,0x0000000000000000}}, {{0x00014caf1b7e4897,0x00092052b710207f,0x000840b578b42fb2,0x000c859d4e0acb78}, {0x000efbd1059c69f5,0x000fc0d187f5ce1f,0x000018dd99b98e1d,0x000fd9d695b6b702}, {0x00087f7037056ff1,0x00080b73121d9b11,0x0000000000000000,0x0000000000000000}}}, {{{0x00078d674ce9ba28,0x00098667edd1931d,0x0007a2c798ce814e,0x00054444ef1eef63}, {0x000bbc4342cdf2cd,0x0008690dad1f9bf2,0x000e17a85c72b72f,0x00027215c615b685}, {0x000ab98eb37dbb69,0x00072850ebda62ab,0x0000000000000000,0x0000000000000000}}, {{0x000b543dc482d1d8,0x00066dc72bee2f05,0x000576c719cbc26f,0x000bf9361970fe88}, {0x00012aede3868858,0x000d0a81339054e9,0x00050f3227db12ff,0x00054f85925da234}, {0x0007c4995e06e9ee,0x000343899d0c96c8,0x0000000000000001,0x0000000000000000}}}, {{{0x000622bfd7a6e63b,0x000ca212bebe9c89,0x000487abee2cafd2,0x000143f4d290457b}, {0x0007d05d13bf4c04,0x00067f0ae3716aab,0x000a3097740d4130,0x000debe6d02d5925}, {0x000ef2c2714370b8,0x000fcffae20be9e8,0x0000000000000001,0x0000000000000000}}, {{0x00009dc727eac0b8,0x000802b463618a8d,0x000e00f824949d83,0x00021e8850666aae}, {0x000a354be3730d5a,0x0006ce164b258522,0x000386cbf3fd223a,0x0000b7ba5ba4fefa}, {0x0008ecff5479bc6a,0x000ec6ece410bb37,0x0000000000000001,0x0000000000000000}}}, {{{0x000fb0fd2b03ceeb,0x000c34d346742d91,0x0007fb1da808f925,0x00014c3e50e576d5}, {0x00045dde45aec274,0x0007634b06ff5225,0x000e8f635cfee4ae,0x0006af16b33722c1}, {0x000b6c9512df9861,0x00087905f5ba1ed3,0x0000000000000001,0x0000000000000000}}, {{0x0006849e44fd7308,0x000ca8c188190c88,0x000568eece8b82ee,0x000afcede37dce03}, {0x000956f0105616d6,0x000fcd4f42159b96,0x00016a63204d42e3,0x000f90e66b95446b}, {0x0003ff7137d7895f,0x00015f08ed8c3b6a,0x0000000000000000,0x0000000000000000}}}, {{{0x000080c877cdc551,0x00063fd88170e394,0x000069a5394fa226,0x000fe13aafd4abd3}, {0x000aac77685a1a56,0x0002270caf504acd,0x000b15ab3b28bcb6,0x000ff30df2535d28}, {0x000dad1836a25af3,0x000fa6c25940501a,0x0000000000000001,0x0000000000000000}}, {{0x00072e0f5dfd0431,0x000680aa3b20ecdb,0x000be825e1b5fe43,0x0005a5c2422130db}, {0x000f0dc02a5e8b8e,0x00053d6d0a6ed0ac,0x0007b39bd52bad22,0x000defc7beec9197}, {0x000d80e249e46059,0x0009869fd32b5153,0x0000000000000000,0x0000000000000000}}}, {{{0x000d5488a9c159ea,0x000c7c99f362daa9,0x000520e4056562a1,0x000f58587c3780d4}, {0x000cf122d12decdc,0x00066fa3df2e094a,0x0006c99c7f2dc2a5,0x0005a3f3e1f8fe88}, {0x000ead106c542a2f,0x0001bd548c70f9bd,0x0000000000000000,0x0000000000000000}}, {{0x00025e9e39905a6d,0x000d9b4651431540,0x0007d3343ac64109,0x00071e3dd6b3d33e}, {0x000a550593155d88,0x0005e988444776c0,0x00092c204b5ef211,0x000132ec6af46f8f}, {0x0000975bc42ba82e,0x0000ec605e3e60a7,0x0000000000000000,0x0000000000000000}}}, {{{0x000ebdae497fc314,0x000068fcc42342b8,0x0002e8a76fa0addd,0x000d98aa1ba58a99}, {0x0006f585d2056972,0x0001a667125a290a,0x000e664a47990be5,0x0003e44696beab19}, {0x0000ab4a22f64d1c,0x00054a0b8ce48449,0x0000000000000000,0x0000000000000000}}, {{0x000cf9a538895145,0x000e7e3b3fd1990a,0x0001c1f1592daaaf,0x000016843015bdb3}, {0x00095b2dbb2d0adb,0x000f77ef5d670d12,0x0008bf1b3f98aca3,0x0003b5280fd35140}, {0x0007a58660b5ee9d,0x000f86e58791223a,0x0000000000000000,0x0000000000000000}}} }, {/* digit=128 [{1,2,3,..,}]*([2^512]*G) */ {{{0x00031c51f5b59b03,0x000c7665ab584951,0x0008739b754d5115,0x000b253e840523eb}, {0x000078a1f77e3b96,0x000742a046765d97,0x000823d7e942e5b8,0x00080b3194bd1539}, {0x0002679bf560b997,0x00061abda6ff32b5,0x0000000000000001,0x0000000000000000}}, {{0x000820e93e66dad8,0x000f2c881e08a892,0x0007e5fd839208f9,0x000d25804e86968c}, {0x000fc76aeb554305,0x0004c686c9b44037,0x0002e51b80d02e02,0x000e5774d5a620e6}, {0x000000eae653df90,0x00072ac9b31961f0,0x0000000000000000,0x0000000000000000}}}, {{{0x000f8d7860917b4f,0x000bb3357359429f,0x000995f4b0a05d76,0x000e0f1c58d0fe01}, {0x0002921dccd2ee40,0x0000ab0ca33af9c6,0x000637c074069c34,0x0002098a102fa30b}, {0x00037701844888bc,0x000d6cb2e96e33de,0x0000000000000000,0x0000000000000000}}, {{0x00070d506a96d190,0x000f2ce57ed3ba0f,0x0002492cf26e59c4,0x000305995879a0eb}, {0x0000675760ae93d1,0x0009f9d0d04103b2,0x000d618a2b740898,0x000e723e7b444b0a}, {0x000b80451ab5c813,0x000616305a1f27eb,0x0000000000000000,0x0000000000000000}}}, {{{0x000b480b60680f46,0x00097a71a65ccb4a,0x0002360920f061e1,0x000428aeb306dab3}, {0x0005aee5267509d9,0x00058e47b1cbaf9d,0x0003350d9a6f7e9f,0x00035af36c30696a}, {0x000ff438c1f66ddb,0x000119d4937e17ea,0x0000000000000000,0x0000000000000000}}, {{0x0009df61e7821be6,0x000b8322655044ac,0x0001ae7bb1e106e2,0x00039508343bc8e6}, {0x000a2bc1e06e0991,0x00066bd6b8166453,0x00044e23756d0eb9,0x00003795c5a1b4bb}, {0x000605deb625fe17,0x000248426f42f1b7,0x0000000000000000,0x0000000000000000}}}, {{{0x000ebb49b8b6d8d8,0x000c9576edd0b2c0,0x000089746d87ef78,0x000ee54686ff89a1}, {0x000cd51992a8e30d,0x000fcb70ff8362ad,0x00008d8883f2631a,0x0002a13e25b5a551}, {0x000d32baa9313847,0x00049764387fbe1f,0x0000000000000000,0x0000000000000000}}, {{0x000652373d0f2fcd,0x0007e9e1299928e8,0x00016c54d21ce8fd,0x000e62d7938b0123}, {0x000ce4d602bacad0,0x00055138cbf9df41,0x000e0e625dfe098c,0x000dbf9a6851bc01}, {0x0000b0da12bdbc63,0x000aec8b07cebaa7,0x0000000000000000,0x0000000000000000}}}, {{{0x0006a52b356ba3e0,0x000fa486ee1abbf6,0x00074bf145f1f28e,0x000ef4af39b6c538}, {0x00084376c3d3f698,0x00007cbe4b46d363,0x0003db26e35a57f0,0x000ecc45a1933b62}, {0x0007b9610a9a44f8,0x000057b84f95bccb,0x0000000000000001,0x0000000000000000}}, {{0x000bdacb48b9bb6b,0x000642a5eb931fe7,0x00097c327f5fbd2e,0x000a3062ea3deca5}, {0x000a3dad9ef787fc,0x00092f83b35a8216,0x00042427945728d9,0x0007537c6394f3cf}, {0x000b615698a93762,0x0001f468793ceb99,0x0000000000000000,0x0000000000000000}}}, {{{0x000217c6562eea14,0x000a6a042cb3da1e,0x00060f9ac91e9595,0x00013fef00e33063}, {0x0001954b4b6c8a05,0x00007e6bb37592ca,0x00018fef0e569527,0x000f4449441c7534}, {0x0003c8e93a050abd,0x00050bb02598e0eb,0x0000000000000000,0x0000000000000000}}, {{0x00044683d956af18,0x000340076bbbf06c,0x00006b8e5826911d,0x000bd47b4442693c}, {0x000bdbfb4883b7be,0x000a67f8d229f111,0x000eceec785481be,0x000d18ec8ccc0a58}, {0x000ed2b1cc9fd671,0x000ee9b77fbdfe40,0x0000000000000000,0x0000000000000000}}}, {{{0x00033f2848525772,0x0002def8aeb9f6cd,0x0009c738e373fa1e,0x000ca3f54bf1bb33}, {0x0000dd3b12e5c621,0x000856fbe6604112,0x0004fa2d98399489,0x0000ba4686140d31}, {0x000be8a65034e7d6,0x000fc1d2c9034f2b,0x0000000000000000,0x0000000000000000}}, {{0x0002e0e02cbac5de,0x00036d1bbef4bfe6,0x000db812e9ceffa7,0x000c4f097569d138}, {0x000c2795f975ff41,0x000cfa1a794c9978,0x000e1e65c9b377a9,0x000e6d66f7a547fd}, {0x00058785dc7270ac,0x000b34d6e188dec1,0x0000000000000000,0x0000000000000000}}}, {{{0x000a511d09de2eac,0x000031698e16faac,0x0002e96a74ccb4d0,0x000b85017b609854}, {0x0005887d91373679,0x00039fd4a56f39c3,0x000f60f3aea2bb2a,0x00084e8edd3fc7ee}, {0x000e1d001d481288,0x0003732f4d1fa989,0x0000000000000001,0x0000000000000000}}, {{0x000629c27855b7b6,0x000652d6fdccbf0a,0x0005f32800f6bc14,0x0007f62ad29c1358}, {0x000dbf3a9fdce69e,0x000aa9f4b69418d0,0x000e5fef492796fd,0x000332f4a27a525a}, {0x0001a7293d91d135,0x0006fadc6b1bb1cc,0x0000000000000001,0x0000000000000000}}} }, {/* digit=129 [{1,2,3,..,}]*([2^516]*G) */ {{{0x00076fe9e4b410aa,0x0002e2e46e8257e7,0x000285dece1c90ea,0x0004f07e02e70a0d}, {0x0007d9e22652fd2e,0x000325ca4b7fb066,0x0001305e36daaa95,0x000feebe9d3d04df}, {0x0000e3be0fcd0755,0x0005f74f74e60357,0x0000000000000001,0x0000000000000000}}, {{0x000a7ff33f158714,0x00012737b93b28b8,0x000a408dc4f02791,0x0009c78d219fcf52}, {0x0008fbf0f03e3758,0x000d6cdb0c0bb10f,0x0007428d517b4d78,0x000d37e06b1f9904}, {0x000f8786ba69f3ae,0x000b508624d39698,0x0000000000000000,0x0000000000000000}}}, {{{0x000314e66fead340,0x0009f5c35e0de977,0x00086281b424220d,0x00095c9d69b8f421}, {0x000075fd90a74e5f,0x000c09fc499a89c7,0x0004b64e12f34808,0x00068c161166a676}, {0x000f40cf1886f3c3,0x000c4968ad8aaa55,0x0000000000000000,0x0000000000000000}}, {{0x0001f4bec36790bc,0x000d77489002d4f9,0x0001759ca38e8177,0x000e759ae14e5a1f}, {0x000289005868dab2,0x000a1dff8ca02b41,0x000a4d82b9cd06ea,0x0004578741ea12d6}, {0x000343e8d641aef6,0x0002d4c6a85c8b1a,0x0000000000000001,0x0000000000000000}}}, {{{0x0007c33639a0b3f1,0x000010f791b828fa,0x00069b98b785836e,0x000f9367ba2d3b6c}, {0x0005ecea4290d504,0x0003dd0621586083,0x000de6622ac6245f,0x0002d8153e71208b}, {0x00091cd77d2a1a55,0x0007ebc7df7c52cd,0x0000000000000001,0x0000000000000000}}, {{0x000fe4e1268ac84e,0x000d05fdf620f30b,0x00078c9c26de9aa6,0x000fef3a7d0e875e}, {0x0001f45acf57d581,0x0009769d1b4f2f3f,0x000f8a2b516d4fb8,0x000ca50e2afa7161}, {0x00069ea98a831731,0x000a4069e2a679a5,0x0000000000000001,0x0000000000000000}}}, {{{0x000573b5ab69b37b,0x00099e464e098a37,0x0004b6ae9bd2eac1,0x0007e83941109e44}, {0x000b3638c710996c,0x0005b0374099e6be,0x000e0cd0943a1c3a,0x0008fab6ecb18490}, {0x0009f0eb14e71bae,0x00011229f06246b6,0x0000000000000001,0x0000000000000000}}, {{0x0006e2d865b8fa8c,0x000e4ba2a3d8ca53,0x0004c428120f4f50,0x00003e5bcb6eaa4c}, {0x0006c69871129b42,0x00018bdacf6da13d,0x0006a314f621f852,0x00031ea900e85204}, {0x000d280193a13fa0,0x000437167b70a8c7,0x0000000000000001,0x0000000000000000}}}, {{{0x000e47d41aa029d1,0x00083c1c1e4e8c82,0x000819d110bf6923,0x00080e340caaa47b}, {0x000e4f6e315e8cb2,0x000865960449f5a7,0x0002a736db3e3bf6,0x0008b38233a8c18d}, {0x0006ab95cab54c2d,0x0007b4670af6e721,0x0000000000000000,0x0000000000000000}}, {{0x0009cd8d15df2f21,0x000c9e95f873ccf7,0x000d4ae259b8946e,0x0003026a352c8cec}, {0x000c84b6773b4638,0x000327edc3574f14,0x000980243f9e1167,0x000c58a2e8d3fc2d}, {0x000e789b426360b9,0x00084beac487c72a,0x0000000000000001,0x0000000000000000}}}, {{{0x000a504d7a128f19,0x000bec706161d077,0x0008d3f449e0d717,0x00027553cd6aa437}, {0x00023bfa097584c3,0x00031032e9ecfed0,0x000de734abfe6661,0x0005972524c62301}, {0x00068a20ad67cd7b,0x0001d7d8e4bd981b,0x0000000000000001,0x0000000000000000}}, {{0x000dd411d75c8560,0x00020a136bd0f9a0,0x000e9c06f6a8521a,0x0001770134117a07}, {0x000c6625cc2c0b14,0x0006f01c93534fec,0x000bcd3698e9742e,0x000543a9724acea5}, {0x000820ced54b554d,0x00005a7954cbcc77,0x0000000000000001,0x0000000000000000}}}, {{{0x00060a7aed1a8afb,0x00037a6526a7b404,0x000f752335e80ab0,0x000a8f65f14c43bd}, {0x0004f9b989eabd11,0x000976a80f23fa92,0x0000171f16dad870,0x000d3baaac454e44}, {0x000f34704b9635c0,0x00051b0e1ca863f0,0x0000000000000000,0x0000000000000000}}, {{0x000fcc07647c957a,0x0007e8420a4e5f40,0x000cec847e324cf5,0x000db2fe1f189869}, {0x0009827f88deeb20,0x00023c17a4487124,0x0009568284e63444,0x000010b9bfa3fe02}, {0x000626ee2d426c18,0x0006c496cbf2d807,0x0000000000000001,0x0000000000000000}}}, {{{0x000a48e1016cc257,0x000e7a08472093bf,0x000b7492e4ec8ac9,0x0001bd1c471d73ed}, {0x000a7243428ce53d,0x0007d49d1740adec,0x000c66dd60077c0b,0x0005737593cb7a95}, {0x0007c6f6ef237e1e,0x000660a7929ff06a,0x0000000000000001,0x0000000000000000}}, {{0x0004bcc2e6c3da59,0x0003e87b3c416f89,0x00021231992a493d,0x0006d0824c0a5993}, {0x000e60d5c6c61f37,0x000a3430f29e1550,0x0005e81f1d1beb92,0x00027b6bc5ab11f9}, {0x000858c60a78bae0,0x000f95bdd9ea9017,0x0000000000000001,0x0000000000000000}}} }, {/* digit=130 [{1,2,3,..,}]*([2^520]*G) */ {{{0x0008b69f6c0a103c,0x00014cb96747cd0b,0x0009e707ed23f30c,0x00092336029690c8}, {0x0002b884265ced12,0x00087e627555cfec,0x0008f62a097ab7dc,0x000df635118ea555}, {0x00070b69e23dda1a,0x00011d1b70ffff57,0x0000000000000000,0x0000000000000000}}, {{0x0002606bce985157,0x000cf38c9c6bbd4f,0x00058d1b308ccb92,0x000fb6fe2ce6913c}, {0x0005b1967bfefbbd,0x00053132fce5cb51,0x000b2f22527584e4,0x00082a1591dfc389}, {0x0002d57610460d61,0x000dc57498b0d160,0x0000000000000000,0x0000000000000000}}}, {{{0x0008cffee5938175,0x000028a135a61fb3,0x0002c9fe1a18ac17,0x000b968e30418249}, {0x0000b4c958b813ec,0x00023285e86f834a,0x000b05e54df836f5,0x0008f77b5fb229e4}, {0x000371505e864d89,0x000fb3cce3c32e48,0x0000000000000000,0x0000000000000000}}, {{0x000a0e5e3ce8bcd8,0x000dc2fb74fd48c4,0x000875aaa2018996,0x000827185e9f86f5}, {0x000196642422b5eb,0x0006d6f0dd874310,0x000f5719d7e7982d,0x0005346044e6cb46}, {0x00002d250a348c67,0x0009ec517508afdc,0x0000000000000001,0x0000000000000000}}}, {{{0x000145140a7a865f,0x000095ded9f8c118,0x00040df2b19ba498,0x0007dec03834dace}, {0x0009e3687e664a0c,0x0009d971f2feee9a,0x0008796a032ee720,0x0003a0b2cc310714}, {0x000067d48b65bcec,0x0007f5d8c2af6546,0x0000000000000001,0x0000000000000000}}, {{0x00015c856b094864,0x0004f779c821c5d7,0x00062cf6310bebe0,0x00086c833844c220}, {0x000322644f899899,0x00080ac439439357,0x0009f2dfd741ec2f,0x000c3022b589299a}, {0x000663af1bcf4790,0x000a46767587f6f5,0x0000000000000001,0x0000000000000000}}}, {{{0x000cdfa0667f8929,0x00055eda7b7826f1,0x000dd93845997fea,0x00073f54c39699cc}, {0x000d85971fbd417d,0x000631f8049f08e1,0x0003b8e65a870ee3,0x000aa3cdc8e351a7}, {0x00099901454f69b2,0x0002d659cbe0fe85,0x0000000000000001,0x0000000000000000}}, {{0x0005bfaeb9c77879,0x00078817f6a7aa08,0x0001e5f6c61e07f9,0x000a5dffb271762a}, {0x000df5d3e3cd3cc6,0x000eadd52e895eb0,0x0003b342cd665b46,0x000393078c5b9252}, {0x0006202122ebcff3,0x0005f4777dd50c48,0x0000000000000000,0x0000000000000000}}}, {{{0x0003fcdbd57bfa90,0x000d1b118dee98fe,0x0000a524ceccfc4a,0x0007420c6d1ffa5c}, {0x00053919d859de0d,0x00081fb74544af55,0x0007c3f0981d6def,0x00076680c297a17a}, {0x000d22135e0cc4fe,0x000d15de36e57af6,0x0000000000000001,0x0000000000000000}}, {{0x0008ae03fd78b0a1,0x000c06ac0c41950b,0x000c994e2c7c2638,0x00075a944523ebb6}, {0x0002bdb72a76549b,0x0007a73d0573310e,0x000ae4c8ce6d6b85,0x000e4309eb9e1e23}, {0x0008aedc0842f06a,0x0006ededf71264f9,0x0000000000000001,0x0000000000000000}}}, {{{0x00047c62f7f81bbb,0x000568d4c38f8cbe,0x000085a52c049173,0x000151d87d057b19}, {0x000462de5c929612,0x0004036de18a4ea9,0x000290b0a8300ddc,0x000e195518bc5a6e}, {0x000e21097894ed83,0x000a74d8dd898c35,0x0000000000000001,0x0000000000000000}}, {{0x000eee2e29a47676,0x000325c0b89ddfd0,0x0000c5c995a8a7bf,0x0003e514a5131a24}, {0x00078e5998b6e957,0x000ba59336939798,0x00032157906f3c87,0x0001093cead5ff51}, {0x0003bc2e1b76588a,0x000a055abc03c824,0x0000000000000001,0x0000000000000000}}}, {{{0x000c9d2081074b7d,0x000b4b234d223107,0x000c6fe7d17524b8,0x000b3e26469a9182}, {0x0001d35461f18688,0x0008f9ef1eb0f49d,0x00072164bb2130a7,0x00069240661ee72b}, {0x0004674d4ec1e4e4,0x000df195346b1529,0x0000000000000001,0x0000000000000000}}, {{0x00094d4cd2beae09,0x00021cf533e3fea5,0x00099051c26db75a,0x0000237aea1a808b}, {0x00066230cfcd19c1,0x0000aedfcfe63965,0x000965518cdd9349,0x0000446502d88c39}, {0x0006de0650de6be1,0x000c487b3640aa4a,0x0000000000000000,0x0000000000000000}}}, {{{0x000315f2c4f3b202,0x000844f2e07c55f6,0x0009040fc8f62ee6,0x0006bb02af168881}, {0x000eea1922677aec,0x0003b90132968e4d,0x000b75f92b21f9e5,0x000b4ae4c1d62b9c}, {0x0000f373265408d1,0x00013d70be8f94d2,0x0000000000000000,0x0000000000000000}}, {{0x000c00995b2d1ac5,0x000acf4e16ae2b05,0x000d04ee882f20b5,0x000b5e061f8c5834}, {0x00040c9dbfe4135d,0x000f7b55b63a42f5,0x0003b47500e266e3,0x0004da6911e652ce}, {0x00043c4db0c53d0a,0x0009946052a6d7ee,0x0000000000000001,0x0000000000000000}}} } }; #endif /* #if !defined(_DISABLE_ECP_521R1_HARDCODED_BP_TBL_) */ IPP_OWN_DEFN(const cpPrecompAP *, gfpec_precom_nistP521r1_radix52_fun, (void)) { static cpPrecompAP t = { /* w */ 4, /* select function */ NULL, /* precomputed data */ (BNU_CHUNK_T *)ifma_ec_nistp521r1_bp_precomp }; return &t; } #endif // (_IPP32E >= _IPP32E_K1) #endif /* #ifndef IFMA_ECPRECOMP4_P521_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_ecprecomp7_p256.h000066400000000000000000017704031470420105600276030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 IFMA_ECPRECOMP7_P256_H #define IFMA_ECPRECOMP7_P256_H #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_ecpoint_p256.h" #define BASE_POINT_WIN_SIZE (7) #define BASE_POINT_N_ENTRY (1 << ((BASE_POINT_WIN_SIZE)-1)) #define OPERAND_BITSIZE (256) #define LEN52_P256 (NUMBER_OF_DIGITS(OPERAND_BITSIZE, DIGIT_SIZE)) /* P256 affine point */ typedef struct { BNU_CHUNK_T X[LEN52_P256]; BNU_CHUNK_T Y[LEN52_P256]; } P256_POINT_AFFINE_IFMA_MEM; extern const __ALIGN64 P256_POINT_AFFINE_IFMA_MEM ifma_ec_nistp256r1_bp_precomp[37][BASE_POINT_N_ENTRY]; #if !defined(_DISABLE_ECP_256R1_HARDCODED_BP_TBL_) /* Montgomery coefficient R = 2^(6*52) mod p */ const __ALIGN64 P256_POINT_AFFINE_IFMA_MEM ifma_ec_nistp256r1_bp_precomp[][BASE_POINT_N_ENTRY] = { { /* digit=0 (1,2,..,64)*(2^{0})*G */ {{ 0x0008905f76bdc7b5, 0x0007bd418a9143c1, 0x000c475d568abc1f, 0x0009a701075ba95f, 0x00003d1f32c8b4b9 }, { 0x000571ff18aafa5c, 0x000f757ce95560a8, 0x000434a7e54432f7, 0x0002797258b4ab8e, 0x00009df870e37032 }}, {{ 0x0006bb32e5348a6d, 0x000d9d410ddd64df, 0x0000ad784f985075, 0x0008a23d9aa6ae3c, 0x00001fb0f13f1e58 }, { 0x0008c57751832101, 0x00047d361bee1a57, 0x000b725df8a6ac15, 0x000e32cbe152cd7c, 0x00008c240484bd0e }}, {{ 0x0006936a3fdd92de, 0x00061904eebc1272, 0x0009e1ea17bc2219, 0x00038de98b027f84, 0x0000be1daceb9daa }, { 0x0005f06a2abb7836, 0x000261fc983a7ebd, 0x000c327193eff4d4, 0x000b6b38e583e47a, 0x0000315e09d4065e }}, {{ 0x00077362f599237a, 0x0003b0d46918dcc5, 0x000d6eb05e7ddb8d, 0x000ec90f24650a6e, 0x0000604e8ac3b74e }, { 0x0004b14c39d10c04, 0x000ee4ce4cbaba68, 0x00017625a80d5c8a, 0x000d1ce2e1762847, 0x00009cb7c6eea514 }}, {{ 0x0009079606520cb9, 0x000d1aec45c61f5c, 0x0009cbb1bd776c0e, 0x0006a090c90ec649, 0x0000ce1d21d8a47e }, { 0x0003a076bba1725f, 0x0003c4ae7ba4f107, 0x000f724b117049be, 0x00007c06873c568e, 0x0000d1631291cbdd }}, {{ 0x0003074b59672881, 0x000c6373e77664a1, 0x000f2165a2e4d910, 0x000ef22ad55ae744, 0x0000cd292bcbc0f3 }, { 0x0004c9916deed188, 0x000da20d377e44ba, 0x000309358347a501, 0x000921711299c2b5, 0x0000cd3e2ccadf00 }}, {{ 0x0003ba5119d6cc8f, 0x000a64ea0173b4f1, 0x0003be81afdd3079, 0x000572c082bd2021, 0x00001db750e89b35 }, { 0x000aedd9165911e1, 0x000ef303f5b9d4de, 0x000172b8a2c6cf35, 0x000b760956742f2f, 0x00007d5db743c61e }}, {{ 0x000763891f69c8ac, 0x000a0d19499a78fb, 0x0004b837ab35be28, 0x00064506b462ab5c, 0x00002c41f6130b86 }, { 0x0006ec12f2cdf2f2, 0x000b1a9532d49775, 0x000d78b2a72327aa, 0x0006dc9f021e3327, 0x00006889435a91f0 }}, {{ 0x00005b3081d12011, 0x0005d8f264e20e8e, 0x000c794c77bfa4a9, 0x000a8da00abe6bfe, 0x0000ec1d857c8273 }, { 0x00086659ce05e9b9, 0x000be7aa45f33140, 0x000dc5f6ec1518cd, 0x000c7761a56af7be, 0x00006928f160cc82 }}, {{ 0x000c61c947f1150b, 0x000d0d19dc21ec8c, 0x0009436db7f13b03, 0x00010004998f9868, 0x0000d698306e8e57 }, { 0x0008719a5563ace5, 0x0005b7880dd9e767, 0x0000bfce23b2a87e, 0x000ef00d2c43a899, 0x00000a4ab8781013 }}, {{ 0x000e7090f1a30d21, 0x000050a6245e4043, 0x0005300f4eef4770, 0x0009ef9b59de4079, 0x00006484903423ea }, { 0x000893002449b8b8, 0x000cd612b944e886, 0x000e7cec61a3d0bd, 0x000f4ac3d250f939, 0x0000b1ed336264d4 }}, {{ 0x000ee1df781a65c0, 0x0005aa7d26977684, 0x00057b527abaea51, 0x000d1785eabdedef, 0x0000cdef8db325d3 }, { 0x000ff57c95d31907, 0x0000bd91cbb5b437, 0x00064a93d9a13993, 0x000c56666170ed2f, 0x00005f7b461764b7 }}, {{ 0x00038477acc71a2f, 0x000f6634b2ed7097, 0x000911eb5b6105a9, 0x0008469110e35676, 0x00000610528b928e }, { 0x000bc0876ac5a83f, 0x000ec90c00ee17ff, 0x000f786e4b786fcc, 0x000771cc16874838, 0x00000146b81bb7f7 }}, {{ 0x000aae7333f7c13a, 0x000695bb0cf664af, 0x000684e894afaa81, 0x000c1ec60126e48f, 0x000061142a8620ce }, { 0x00052706dc43d122, 0x0000bb7995d586b1, 0x000e6dfb30e5e3e4, 0x00094c5dbbe29569, 0x000098178e3461e6 }}, {{ 0x0002aa0e43ed7de8, 0x000f0b7bc60055be, 0x000d74387007853e, 0x00003ab7003cc23e, 0x00004cf9074de0f7 }, { 0x000042170a90bbc4, 0x0008e4f6383c45d2, 0x00042262041aaffc, 0x000ce8397d766355, 0x0000fed56953d3e6 }}, {{ 0x0004d63c80e5d9f3, 0x00018650bc6fb805, 0x0004eb27f1ea9ab1, 0x000aa02495882e07, 0x0000a466f2e5fb46 }, { 0x0004edf7b266ddd9, 0x00042d652a23f9b6, 0x0008e61d6dd58c13, 0x0007a359e3670c31, 0x0000d257b443894a }}, {{ 0x0001a35c0b2e1db3, 0x0006acbd53c5c9dc, 0x0005ea66bb7068eb, 0x000e07afff17624b, 0x0000591d6b9069fe }, { 0x000bd512271e49d5, 0x0005c4693e79987e, 0x000ffcc7a5e70433, 0x000ceaebb0575bf2, 0x0000f661c2e757ee }}, {{ 0x00075abd1bd6dba8, 0x000a9c856ada97a6, 0x000d283083228862, 0x0005281794afc964, 0x0000f61673328f6a }, { 0x000c6fc7d9717201, 0x000bc725e485a1d6, 0x000f22df4362f530, 0x000127aba4b2a5ca, 0x0000262b28cba5aa }}, {{ 0x000e545c2926ec20, 0x000f2baa5659ae8f, 0x0009278d4545d7bc, 0x0004021ac68363ab, 0x000024e11be64e4e }, { 0x000720ee26643347, 0x000a2e7dc4c696bf, 0x000a0488899ec903, 0x00061c1c15806244, 0x0000a0f278b7757f }}, {{ 0x0002d1eeb7e12dea, 0x000a729d2337a31e, 0x000e2cb43d24a969, 0x000a499ba5916868, 0x00000502dc95217c }, { 0x000ee104e224dfe5, 0x00037417884005d5, 0x0007a11ec6cc5e0f, 0x000c97966a2d4ec1, 0x0000b25760a55d65 }}, {{ 0x000cead9f5ae523c, 0x00010ecc135b208e, 0x00045a991a87a7dc, 0x000ecff3074e1b26, 0x0000f12e91b276ab }, { 0x000086d5f289ce55, 0x0007fb2e286e5b9c, 0x000fc334666f68cf, 0x000ddd4a41b0fadb, 0x00009543bc814bf5 }}, {{ 0x000dc777e9e6fad0, 0x00041352f6f3076f, 0x0002e5c9b2b028cb, 0x000fdea3dc99ffa2, 0x00008d533e5e9beb }, { 0x00093e8d07d69b5d, 0x0002abb35415f047, 0x0009d3e5719cbe0c, 0x0009ed8b5640c2d6, 0x00007bfb45e7d23e }}, {{ 0x000f2cea7cc654a9, 0x000cd532de45068a, 0x0007ef0134f22ea3, 0x00003976937c7a7e, 0x0000bee7aa1e25dd }, { 0x0003d0687c1447ce, 0x000d6fb9e4785a98, 0x000ba35936cdef18, 0x000646171e5fda49, 0x0000ead87df3975d }}, {{ 0x00097b2330287754, 0x0002fb215d02819f, 0x000f4762770544c1, 0x000b3f29f6d0d754, 0x00004490d3fcc8f4 }, { 0x00095dc55f23d140, 0x0009750b24bcbc75, 0x00092f441df78180, 0x000fa350111ea494, 0x0000e940dd6ad26f }}, {{ 0x00066742ebfbaa6d, 0x000acacd837879f9, 0x000e570424c4a8f8, 0x0004786af6fc1b49, 0x00001a48d8c34737 }, { 0x000b948dc3d28c27, 0x000a2feb49662287, 0x0001c85fab8c7901, 0x0002b0aee96cc631, 0x00002b68fe2195f7 }}, {{ 0x00094baaa8ef3ea5, 0x0000832ed1f80089, 0x000a3f65ca8f72a6, 0x0004151fbe6c9267, 0x0000b870bac04296 }, { 0x000d178031be45da, 0x0003ae11d248018e, 0x000a757344d6c689, 0x000636af55a39898, 0x0000f7e62c4349a1 }}, {{ 0x000f8aa54bce826c, 0x000bef497e2feb49, 0x00070f34cdc735a9, 0x000cd91d7d36a42d, 0x0000b578ca909f39 }, { 0x000d431069058eee, 0x000c9ba09895e702, 0x000fb074eaef8c71, 0x0005c5ebb3bd0c66, 0x00009a05e3ae9f73 }}, {{ 0x00097f6b6bdc2a47, 0x000f7b7172ccd1fe, 0x000747273d266f27, 0x000b70ceb7323cb2, 0x00000289b30a54f3 }, { 0x0009b4cc5fea0d1e, 0x0001b3ed1a83da1a, 0x0006d6965e083330, 0x000ff991ea6a7f9c, 0x0000d78ac0dce842 }}, {{ 0x000266f95a2ac736, 0x0007e6acb66e132e, 0x00092b2b5f263396, 0x0005083e2f1be963, 0x0000a1dcaaacccd8 }, { 0x000798142a61d3f6, 0x00070735c2088993, 0x00076b6304793707, 0x000a86b9f9047244, 0x000045b4d24b0f15 }}, {{ 0x0000288cb622df88, 0x00094b13298b343d, 0x0008e426d8eb9144, 0x000e7f2cda3a14e4, 0x0000f218abd21717 }, { 0x00060d45ce976d65, 0x000272f1c040abc4, 0x000dc0b2557c3e5f, 0x000cd3f41b675511, 0x00004127c7f96903 }}, {{ 0x00048dc4f9468a4c, 0x000f0696755ff899, 0x0006b2a252ed9c6c, 0x0006d140ddd3cf7e, 0x0000ad40f1efa3f6 }, { 0x00038ae89241062f, 0x000cf814ea53299f, 0x0001a560779698e3, 0x00091d4fc2d921ca, 0x0000d74868346acb }}, {{ 0x0009227077a277a3, 0x00059cfc5e3a3d83, 0x000c07576f48364e, 0x000355e97befd904, 0x00001c25c29ce15c }, { 0x000231d792f7c39a, 0x000a46ddbef42f56, 0x0003e5d8c175121e, 0x000d694407e449b6, 0x00003711285e87b5 }}, {{ 0x0003ec6869243119, 0x000fb560f6645343, 0x000c177c889a62e3, 0x0002671b985ceae7, 0x0000759c4e754541 }, { 0x00016c4304749ba6, 0x000dd2b3a8ec1f1b, 0x0007a6db92eaf628, 0x000a36f745509d12, 0x0000c8bc38c34b01 }}, {{ 0x000982ddd5a6b31c, 0x00004147ca23cd3c, 0x0005da0ea6c80ff8, 0x000b47194caa7a5c, 0x0000393836b1cdce }, { 0x000159100cf86685, 0x0007b0b5db6f971a, 0x000ece2e5f860514, 0x000f00f26bba2cb1, 0x0000051e80a79643 }}, {{ 0x000a640b870d07f0, 0x000947fdec67ef5c, 0x000358da6b30f00e, 0x000bac4c8742ee46, 0x0000a74e3225ade2 }, { 0x000ba90162b75d7c, 0x00085908ceb6aa92, 0x000c28cf5172addc, 0x000c5fef7313c300, 0x00005ab09925afb3 }}, {{ 0x000569656d0ab3a3, 0x000b5d6a8219bb73, 0x000ce59d601232aa, 0x000a3b46ec691d0b, 0x00002fe02f08a3c7 }, { 0x00080b9e12257943, 0x0006bbd94cda03a4, 0x0002ce206001c072, 0x000d85dc6934e82d, 0x000038227865a8bc }}, {{ 0x000763a388070738, 0x00043c58cce08b52, 0x000c57b3e9ccf93f, 0x00070a006b636458, 0x000073a51820269f }, { 0x0008b36143bab3e9, 0x0005b8a7d3cebb65, 0x000e166d770ce677, 0x000a45d2ce7adda3, 0x0000ec583f44a15a }}, {{ 0x000df0c7dd2a5105, 0x000beca4d63c0eea, 0x000661f880f15fdb, 0x000ddee3b5123311, 0x000048f0c43aa7f7 }, { 0x0009a4c281762585, 0x000a83bfe7765e5d, 0x0008e5934187989d, 0x00033ac9cccaab35, 0x0000ce5a2b475518 }}, {{ 0x000853e4c48e856b, 0x0002988a059c1425, 0x0004a6b7ae821b53, 0x00075cb646f5ae71, 0x0000703cc0a9b888 }, { 0x000c0bc0e57524e4, 0x000992363c52f980, 0x00067576c7916db3, 0x00029971c2ec4a76, 0x0000edb0d188156c }}, {{ 0x00062d7b00bc24ad, 0x000bb1db82e9f3e4, 0x000b98f8663c28b2, 0x000cdc58083200f0, 0x000027ff00ca4baa }, { 0x0003466612d4f0d6, 0x000cb88f26517980, 0x000c3364b622041a, 0x000046d5974c6e18, 0x0000427ccfde908a }}, {{ 0x0008100a5073116b, 0x000f5492ed22e919, 0x0004d6f71dd1ef3b, 0x000bcb7716fdfe0b, 0x00009fc9cb71c4c6 }, { 0x00070bfeecfa9449, 0x00091a2a35c628ff, 0x000dd1729b5abc1c, 0x000c390ceb6f94d2, 0x000067c9ff7c6c22 }}, {{ 0x00049c89cec09788, 0x000d4cfed2bad016, 0x0002b90a1bf89f1b, 0x00011a78fa155cbe, 0x0000121edd577d70 }, { 0x0003a8cfe47d654d, 0x000197de9ff257af, 0x0000ff8380ca53f3, 0x000fac7cf9b35961, 0x000020d4bd2f2712 }}, {{ 0x00079c85db554c9f, 0x000a0fd248a7d061, 0x00046febee1efaa5, 0x00027ba8180c5bfb, 0x00006ff589c6b4b0 }, { 0x0007795f4fdd2c3c, 0x000746261a6966c4, 0x0002a3638658dd15, 0x000ba67184d82d05, 0x0000f03444a9ebc8 }}, {{ 0x000f3425f708c1f8, 0x000841fd55a897c5, 0x000b535ceb04e43b, 0x000bfdbb0009194a, 0x000088089bf24fda }, { 0x000b629f9123de43, 0x0002387730d50dae, 0x000b5fa59bee9bc2, 0x000bef1170423446, 0x0000ba71f5c7ecb2 }}, {{ 0x00094f7d3556d1af, 0x00077ccd5cd79bfe, 0x000aab1cf0e2c812, 0x00075d0580032940, 0x0000ac88a0bcab00 }, { 0x00073acbff0414b2, 0x0001996782ba21ad, 0x00091ff067a6c333, 0x000e35a81c525446, 0x0000b3a408dcdfc3 }}, {{ 0x000ec684c472efb6, 0x000ffb149ee90d9c, 0x0009d1a819f5cd85, 0x000086fe0785c339, 0x0000a0452c3e9739 }, { 0x00033da338c4f59b, 0x000c7c9c1586e630, 0x000657769bf27db5, 0x00001e85d45431d6, 0x00009e1980aa8791 }}, {{ 0x000b969975373e25, 0x0005013caa760974, 0x0008eb319f90f0fe, 0x0001ccdc70a624fa, 0x00007256c83b773a }, { 0x000bbff86f099df5, 0x00060ccd921d60e9, 0x000fdfeed1a41869, 0x0004f9ed49b944e0, 0x000095725f99e254 }}, {{ 0x00084039030f437c, 0x000c53077adc612c, 0x0008f397ca9d5bf0, 0x0004489bda749652, 0x0000af611eeda45e }, { 0x0005efc7e9c72224, 0x0007b66175adff18, 0x000b31e8fdcd72d3, 0x0007b51e30b26d7f, 0x0000abe9a851e48b }}, {{ 0x000bdbe608fb93c1, 0x0004a421ff6acd3a, 0x0003a80083002601, 0x000e2a027ffe7048, 0x0000344f04aba92c }, { 0x000394077fc5dc01, 0x00091285e1109e8d, 0x000720d053dabda0, 0x000a58dd826147d2, 0x0000b53fc0ef1331 }}, {{ 0x000dceb8db394d64, 0x0005ed0488c171a0, 0x000a0599999cd66c, 0x00064966aa78bfba, 0x000083197a8d8d9c }, { 0x0007d341959b35cd, 0x000b3899ae2b710d, 0x0005cc715b012468, 0x000de6d46efde7ae, 0x0000a80719fcd630 }}, {{ 0x00020ebe0e2e4e62, 0x0008a1c3b3f64c9d, 0x00094c502131223e, 0x000f4b6d4e20bc0b, 0x000051365d8f7700 }, { 0x000731e3847a272f, 0x0001fa773241ea3d, 0x000b86e87be0bce4, 0x00040ed6261f1511, 0x0000b13c9b2db908 }}, {{ 0x0008f77f3559dd64, 0x0008f6e834459048, 0x0009264e7a8accb5, 0x00097c4b72e0ec46, 0x000077614016cc6c }, { 0x000ef2f2271b0201, 0x0008c295864687c7, 0x000da3ec433bdb78, 0x000bcc29e23b92ea, 0x0000b3f836102480 }}, {{ 0x000c3a318e1ca066, 0x0003038546c4d8de, 0x0003a6b814eb7a95, 0x0002846d95f9c3fc, 0x00003dc194c05f8c }, { 0x000ba1da5a3ee82c, 0x0005341c31cb264f, 0x000e567f3998412e, 0x000c7b5973db82f6, 0x0000dcf49c0e789d }}, {{ 0x000b8a0feba9b0d8, 0x000838eb212cf53b, 0x000e3ccb6c73f691, 0x00013fd6c4f2e512, 0x00003caf4f380d7c }, { 0x000a556e4004eb04, 0x0006cd2e7d6107e1, 0x0004cd0cf76abda4, 0x0002e32b17ee0c44, 0x00002b28880d6418 }}, {{ 0x000cee844a04a5b5, 0x00006f9e73056835, 0x000eab00d79c20e6, 0x000225fc131eea5b, 0x000026b5a23f0042 }, { 0x0005e801401734f5, 0x000a0c5a0182bde2, 0x0007783fa574d37f, 0x000b023caee759f8, 0x000034b41c5e2869 }}, {{ 0x000a3f0c4b2e90ba, 0x00087407e8d7a14b, 0x0009db17e71f6133, 0x000cf4644bb1ff3c, 0x0000added5f139e5 }, { 0x000392768185fea2, 0x000205b1f9af32a8, 0x00062e5faaca59cc, 0x000b6f4ac01e0db8, 0x000089510687411e }}, {{ 0x00013298312c0224, 0x0000ee77acaca28c, 0x00070605c2f812c6, 0x0001c8b381bfeea5, 0x0000fc71519eb2d1 }, { 0x000a44c6c6da463c, 0x000b6db2aac9e59d, 0x000cdc1cb163dec3, 0x000553e015748060, 0x0000ecc5ac9b6bed }}, {{ 0x00005f725f94ec75, 0x0008be8a7ea82f03, 0x000db3ca28505d7f, 0x000eb16e199cac80, 0x00002d3afce656e9 }, { 0x00063749945c9e90, 0x0008bc4623fb21b0, 0x000e742bd018d74e, 0x000c16b3efa70533, 0x0000d56e129c9961 }}, {{ 0x000c2bab1bd708fe, 0x00050d65c46aa8e4, 0x00035ca4b8b592cb, 0x000c87e362100d5d, 0x0000d356747acecb }, { 0x0000624998e75dc4, 0x000250c15426704a, 0x000307d5a251b927, 0x00086b3f8778afcd, 0x000023ad4d716895 }}, {{ 0x00040c4cce907be5, 0x0008328ed8a6e19d, 0x00056d7d8cf94ba2, 0x000a054bc33fc233, 0x0000e2bedf2813d6 }, { 0x0004820109c066e9, 0x0004cbbf80e75ca0, 0x00001e2bfe22ef3a, 0x000eac49612c651a, 0x00003c7feeecb38e }}, {{ 0x00094a44a734cd7a, 0x000711a7f4c04cc9, 0x00010ff60add019a, 0x000013b0a5955662, 0x0000a10d512bac4a }, { 0x000d1bc7809447a3, 0x0005519dbeb9b690, 0x0000e1b86d8d43b3, 0x000fd18a2473c568, 0x0000743d915fe645 }}, {{ 0x000dbcb03af2f664, 0x0008d75a1962f910, 0x0001df9c456cf23f, 0x000933e336ed7e06, 0x00004dfcb458852d }, { 0x000b60cfffa10db0, 0x000924ebb32e38e6, 0x000efca5a01f42ce, 0x0003e39ee6472e5e, 0x00000912f4df98e0 }}, {{ 0x000763a4348a5ffa, 0x000df319ff91fe50, 0x0000e8edeab92e73, 0x00022d126039c480, 0x0000c218bfcbfe07 }, { 0x0000876a01d11d05, 0x000ffd5383e76ba9, 0x000ff1c717959f5e, 0x0000608e0ac98b92, 0x000071d355178dc0 }}, {{ 0x0005fb8394ec96bc, 0x000daf305968b809, 0x000272a3f024eed6, 0x0002f6201380a091, 0x00005bd44243eed6 }, { 0x000967204437eb69, 0x000fc1280edfe2f2, 0x000966478f3e6250, 0x00056e2f88f726bb, 0x0000b48e94ed5c40 }}, }, { /* digit=1 (1,2,..,64)*(2^{7})*G */ {{ 0x000d311f2cf406c5, 0x00006817a2ad62aa, 0x0008ff31e0276fbf, 0x000a6d8b57ef2b6b, 0x0000437e1f6177bf }, { 0x000a38d321e63954, 0x0002c87c2ff3b6df, 0x00023c3f61ddd141, 0x0009d5d38b46feaf, 0x0000a9e4aaa74b8f }}, {{ 0x000c3da1963d1b37, 0x00058fa696946fc7, 0x00083d8e03d70b52, 0x000d8231550fbc6d, 0x0000c23f1ad7a853 }, { 0x00099d49ebcaeaa8, 0x00055b03cfd5d8b3, 0x00024f00b2ba1b89, 0x000385daa0704b7c, 0x00003f881bb6342a }}, {{ 0x000e4b32b147920e, 0x0003b6d6ec293cde, 0x0006a0251f43f078, 0x000b7060a733dbda, 0x0000a65cc513dc70 }, { 0x000af675f284aa5c, 0x000a1a9cae368d14, 0x0000b2ba3d012d1a, 0x00090686e5001a7b, 0x000048a7a97981a9 }}, {{ 0x00042370d35642b3, 0x000ce10399492969, 0x000aa1fa40e1eea0, 0x0002bfcf55b63827, 0x00006300726619ca }, { 0x000dc61f92142820, 0x0008f2ee0d985a17, 0x000af47364dbdea2, 0x0003af2f8192cc64, 0x00009a126d8fb59a }}, {{ 0x000e8aa3ab0b8178, 0x000835bc2da7de94, 0x000ec16e3013acaf, 0x000091e41d0e643d, 0x0000aceee54c0f0d }, { 0x000d296a148a8106, 0x0005f329a49110f0, 0x000620ad480c6f7a, 0x00042e45ad18317f, 0x00005efb94892cc8 }}, {{ 0x0005d5bbfc230970, 0x000353eed4c37174, 0x000ef73916a712cd, 0x0004acaa59f8240c, 0x0000b069410109c2 }, { 0x0004d5e0fcf149d6, 0x000f673137fd28e3, 0x000f92655f0108ba, 0x000ab48f2862ac6e, 0x00009efcb3eef840 }}, {{ 0x000662dcbd70a604, 0x000642008913f4f8, 0x0001646660d881ac, 0x00000ae6cea20ed6, 0x00006d3c305ff6fc }, { 0x00037f7913789dfb, 0x0002e5c725d2aaaa, 0x000eead363c6f511, 0x00079dfccbad2752, 0x000044f72f690d92 }}, {{ 0x000da26e1aec73e6, 0x0009be144cc3adda, 0x0005da1c14b462fc, 0x000697e72d5ffa1d, 0x00007dc85a835122 }, { 0x0001c794b1a357c1, 0x000661563483caaf, 0x00083d98e34b8417, 0x000eead3ce6924cd, 0x0000cfb7382ae666 }}, {{ 0x000adbb3f3f634c4, 0x000728882a8042c0, 0x000fc24bcea4eeec, 0x00062e340d931cfa, 0x00006ff1f31aecff }, { 0x000577c11e875a33, 0x000621e5eaa8eb87, 0x00049c3ccd5a10e4, 0x000a9bfc5e663a8b, 0x00000028143def02 }}, {{ 0x000a786d62a93d0d, 0x0002b5c08369a907, 0x000a9e9647958a75, 0x000519f802990c59, 0x000076b05f00e31d }, { 0x000b2ce9e430d6f9, 0x000b4be20ac3a8dd, 0x00007f8d434c0323, 0x000cdfc6531a2178, 0x00009e7647365eaa }}, {{ 0x000c56feb051eaca, 0x000694b168984df5, 0x0006d73097883b04, 0x0004c56f0e81dce1, 0x00009cec7a5febd4 }, { 0x000233e35ef6807b, 0x000db01fde58c84a, 0x00068c98cfb5957e, 0x0001a0f7874e2411, 0x0000c7113cb30256 }}, {{ 0x000f3a8f9d8cc3f9, 0x00072f38bd7aff18, 0x000a8e4721a92651, 0x00064b0151b5ee4c, 0x00003b792b15a449 }, { 0x000255f53b1b9da9, 0x00010c9a0748be7d, 0x0004d6d86ce4578c, 0x00072ff371d391c9, 0x0000702e661ee631 }}, {{ 0x000f627439d898dc, 0x000c204f1788ee3f, 0x000ea906c4682ecd, 0x000a125c0c14f27a, 0x000041647e0afb10 }, { 0x000c1c33bbabfba6, 0x000dfd8ca2a59655, 0x00027acd85f7ce0d, 0x000fdcce83d9a554, 0x0000b9121e2a4fa0 }}, {{ 0x0008c889de2e32a8, 0x000b0d474a861082, 0x000fc583d3b1de17, 0x0003aa480f8048a8, 0x00003ee931e746ba }, { 0x0001c240230a2d47, 0x0001f2eb214a040f, 0x0007461ec3244db5, 0x0007f2d8ae8c48e9, 0x0000149fdf2f3f76 }}, {{ 0x000359ed623dd564, 0x00070c35f74040ab, 0x00014990dbf56e58, 0x000ef8823409aeb7, 0x00004dda364e2017 }, { 0x0002f1d4df601f90, 0x000b926ed6f4a607, 0x000ed89f5903b254, 0x00050ca59e21e8d7, 0x0000edcf85157a9c }}, {{ 0x000c5fe1306bd6ce, 0x00056b9eb7926b83, 0x0003915e73d8d154, 0x00006960bbff88cb, 0x000076006a867f79 }, { 0x000daf6b21ea15f4, 0x0006ef43764fb3df, 0x000733a24b0b851f, 0x00086f1f37b5af31, 0x000030c22394a5ed }}, {{ 0x0008cc13d69c73d0, 0x00097ec6063540cf, 0x0001ed2db7b8d6e8, 0x00025f6ab50b259c, 0x00005b5c1b0bc3a3 }, { 0x000f8efeb1d7be88, 0x0002b05c52176597, 0x0003cf322ba2a903, 0x00054bdfefe5364d, 0x00003115b68dac90 }}, {{ 0x000e583c57029879, 0x00078e5d59233595, 0x000cf5436359e633, 0x000ed2298db0cea9, 0x00001cb09b717846 }, { 0x000b4d4d5956cfae, 0x0006c2dd48185b77, 0x000df304ca2dbb2c, 0x00040ad8bc93fbc7, 0x000021236a00feae }}, {{ 0x0003768f8316e330, 0x00000b046eb842ab, 0x0009c86455eacc56, 0x00014cdfc8e844a9, 0x0000f8985bdb1afd }, { 0x00051b6eefc870ce, 0x00026e04e09e61c1, 0x00018bac5eec5fb1, 0x0002391cd414dc3a, 0x0000e1888cf3478c }}, {{ 0x000e19084bc4ca0c, 0x000ca136339c0831, 0x0005c19d3eb5ee51, 0x000cbf8ab39ff815, 0x00008e22e48c871d }, { 0x000222840c0fb45d, 0x000f7c0eccd47ef9, 0x0004b83b7724081a, 0x000269cf68969338, 0x000064e761fcef38 }}, {{ 0x000c5d75f6acf986, 0x00082f5803bac625, 0x000cdb3e5e689697, 0x0006a3f810b7dd91, 0x00004626edf8311d }, { 0x000036b9b2545d4c, 0x0007b381f2dc308f, 0x000ee94d9b0c2902, 0x000ba643120faa7b, 0x00005df95dde3c50 }}, {{ 0x00004884ebe91706, 0x0005b0939842194e, 0x000d6987cda9dbf9, 0x0009d28e0b7e2353, 0x000008055a9e7106 }, { 0x00013520c2fe68f0, 0x0006d817419f40e7, 0x00023860a17ef38e, 0x0005c66465b0ac16, 0x0000599f3cf0f8c6 }}, {{ 0x00024a8434f084ae, 0x000ac5ce98c51002, 0x000d0b928b25c421, 0x0001e398b6cec871, 0x000093f359354aab }, { 0x0006936830d34d21, 0x0005e6125f5c46fd, 0x000b71c0f68f5335, 0x0006e3bdc6a22bed, 0x0000bf2268186fde }}, {{ 0x0007c2eec1224f3e, 0x00041e891e5d7d3f, 0x00067bdd87b70fb3, 0x000909f61f14b7d1, 0x0000092310e6f29e }, { 0x0000472beb05816d, 0x00006f43756e621a, 0x000f77de8d5da4d4, 0x000061872c013a23, 0x00006e813df45a5e }}, {{ 0x000e87acdcb83dff, 0x0002f270ac69a804, 0x0005a696a81a3be4, 0x000c1a69134096d2, 0x00005b6a5c9aeed7 }, { 0x0004a56cd8946d50, 0x0009037e285ccb47, 0x0003dc3862797108, 0x000a2a719188089e, 0x000041ca5eaccff2 }}, {{ 0x000421cc52cbf744, 0x0000ae21726931ae, 0x0007523f20aa75d9, 0x0008a4a180bbbb2c, 0x0000d98ec4e59258 }, { 0x000359b3dc444ac7, 0x0000b08bea87be65, 0x00035e7422a6acdd, 0x000509cf716a475d, 0x0000928ea2c9a7ff }}, {{ 0x000fc3a5983894c4, 0x0002dde8bf06e31d, 0x0003fd749369a738, 0x0008323d21fdf8f4, 0x00008669487b1517 }, { 0x0001b4f11e41bf9b, 0x0002da0b1ecff106, 0x000bc68b142b2d0a, 0x0008ff273ee6ed6c, 0x0000d795b8258fd9 }}, {{ 0x000f3d47897647f6, 0x000e09bd4eff2d71, 0x0001234b6e8604ea, 0x00059f12388ae677, 0x0000156c9f102ac1 }, { 0x000794b13b286f95, 0x00083c07f9871da6, 0x00088ea1313d5e21, 0x000e488ac35fbda7, 0x00009a346a1a06b8 }}, {{ 0x00023a9f8173b2f9, 0x0006bac09cc0917d, 0x0008f44aa17b929d, 0x0006f7d7127c5372, 0x000084aea5a60d7b }, { 0x00040f1c67e5aa9c, 0x000f92852650359a, 0x0000d0929045b31a, 0x000ab235cfa09ad0, 0x0000eb49c8d9c125 }}, {{ 0x0002383e48552e85, 0x000f02edcc18770a, 0x000ee5ed855ce52d, 0x00082ceed4baf1f2, 0x00006b9ecc862bcc }, { 0x000b2dfd7c4b99b3, 0x000af0a2646d19a8, 0x000b789a42819c25, 0x000d236f156cb44e, 0x0000656fde1d4d03 }}, {{ 0x0007bdb99d7bc622, 0x00050f2a672c5c73, 0x0007d5960c453caa, 0x0007d3732eacb11c, 0x0000d966e32b0083 }, { 0x00026693bd8b6c09, 0x00026b62899c20f7, 0x0001d2183a676b7a, 0x000eb73e33535d51, 0x0000b014e1e0cb73 }}, {{ 0x000a20ed2a8c1c6f, 0x00041e5ab4b35a24, 0x0001abcdbda4db56, 0x0003f26801d8b600, 0x000004b48afeb9ed }, { 0x000a24142725a709, 0x00053d44fec01e63, 0x000c6ddb3c8679c1, 0x000868efd3ed7ddc, 0x0000203192c73ce6 }}, {{ 0x0007fd26ae8cf314, 0x000cb2c6a8ea8208, 0x000b6a2f9ba58ade, 0x000360026b2b50d3, 0x0000e7087b5a0c2a }, { 0x00066f7ffa7c7f1a, 0x0007ccc02bee4ba6, 0x0003a0128fdc2037, 0x00093cf855312180, 0x000003bbef5c6e85 }}, {{ 0x0006c3200fa35ff3, 0x000da33bccd9617a, 0x000413b4109421a3, 0x0007b1486365dede, 0x0000cb76293645ba }, { 0x000a57354a206551, 0x000aa2ce5e35efd0, 0x000b4afe6c76e5aa, 0x000a5e65199a4e25, 0x00004027e76f2bd6 }}, {{ 0x0006a6f79278950c, 0x000a24bf8e4b0651, 0x000417ac0a99741e, 0x000fde19607a834c, 0x00007e7ec115210d }, { 0x000ea49b3d3fd55e, 0x00005c66a8649edc, 0x000db7faa2d74f3b, 0x000d255ecfbcdfcf, 0x00002d9e2c5a83c0 }}, {{ 0x0000ab7b49321f95, 0x0006f4fe9d964888, 0x000e00d72578140d, 0x0007254e94b53d52, 0x000052362af789d1 }, { 0x000995d53e000a78, 0x0009dd427d3317fc, 0x000a50ce91e0ec03, 0x00091e3928dfc1dd, 0x00006eca410021d4 }}, {{ 0x000c32fbd2c44064, 0x000ddec090090ae0, 0x000ce17d6c5d6bed, 0x0008932902278a0c, 0x0000acd50fc16037 }, { 0x000cf307bda4feac, 0x0009adaf341a6c11, 0x0008fefc60e33292, 0x000789f3aae0ba13, 0x0000954ec449a5e8 }}, {{ 0x0003b88a9ddcf1a4, 0x00019c719803511c, 0x000ac4d03920e342, 0x000d52c5ea9f97b3, 0x00008856a1c81ea8 }, { 0x000bd715882bc1be, 0x0004948c48b0ee35, 0x000babd03139016e, 0x000ab99f37506bc7, 0x0000a2cc32ebf442 }}, {{ 0x0005c8485a9d19bd, 0x0004708c1bc52257, 0x000ab150da1307d3, 0x000737043d0b946d, 0x0000f537f04207d8 }, { 0x000df3874cc30296, 0x000c9499ce4177a4, 0x000e2bcd84f0edb4, 0x0006566d74fa61a1, 0x0000f53571e1b3de }}, {{ 0x0008d158672d3eea, 0x00042f983dfedc91, 0x000474b60ab2fc6f, 0x000eaded2f843713, 0x0000d9c3c4a8aa46 }, { 0x000a5956bae7a26b, 0x000d3cf69769bb7a, 0x00061a2054c79b62, 0x0000e89b2c55eb85, 0x0000df9c408d613a }}, {{ 0x00045c51f0556ac4, 0x000d2c29fe20ebae, 0x000b00ce08e2eb0f, 0x000b2d989f27168b, 0x000069b4c47cc369 }, { 0x000a9db957a6f395, 0x000bd76099b42210, 0x000c1ab9e80238d6, 0x0000fc3958dc6407, 0x000089ab035eddea }}, {{ 0x0006a52433a64b6b, 0x000cbd3df61bc767, 0x000fc8d268a83dbb, 0x00023378f13a619b, 0x0000e79d7f68711f }, { 0x000ac045e020fb6c, 0x000ac91ac5bdc5d3, 0x000280079621025d, 0x000e41853ff4a1a7, 0x00003f7f41088141 }}, {{ 0x000fb4f9a3e59e5a, 0x000da1bad53dba78, 0x000bf3c668b6a4a0, 0x00044b7898ec269c, 0x0000c42d0387de55 }, { 0x0001da22fc32c200, 0x000f823ff9875cf9, 0x0006cb6a079f4d88, 0x00004267923224f5, 0x0000acbd3518a2ba }}, {{ 0x000364ebbf27875b, 0x000d74d6c04a661c, 0x00059ad281587be8, 0x000bd88579710d3b, 0x0000db51af083108 }, { 0x000aa7641d8ee984, 0x000d9517733d61c0, 0x0009c400c2a5a595, 0x000b8d148d55644b, 0x0000c50509008fc6 }}, {{ 0x000b6066dd443936, 0x000b681318106601, 0x0007c2ead965cfff, 0x00004cc739dfa650, 0x00008f398de4fb88 }, { 0x000bf773f8103f84, 0x000c1919c9efebdb, 0x000ee624abfcc370, 0x0003683d3425d4bd, 0x00007bb42dbf21c5 }}, {{ 0x000ed26d818f0304, 0x000b96994b03ed1e, 0x0002747a57c4f532, 0x000e11ccad9ad1de, 0x00005dcd24ba7a71 }, { 0x000ff2db2716bd02, 0x00009e7a4db09d2e, 0x000ca61347d0c139, 0x000d9c529f47f569, 0x00003c0c5c86b05b }}, {{ 0x000187d6657e670b, 0x000c514b913e759b, 0x0005de6d082e2895, 0x000b95de153da478, 0x000092e140a21444 }, { 0x000e8d345fd30ff2, 0x000c4501dc90b596, 0x00030f1ce6c7249f, 0x000fc18848170e94, 0x00005a2d667b789c }}, {{ 0x0004b7839d2bce29, 0x00096a1c5c5ea50e, 0x000b82de82e45901, 0x00006e042d3baf14, 0x0000ff6d502965e2 }, { 0x000d93355322d13b, 0x000bc94e7de6dc08, 0x0003d497727bb320, 0x000dbc3ec5cd0f4d, 0x000059e7d3f99e36 }}, {{ 0x000be924c158e0e0, 0x000aec5776c57224, 0x0001df76044b6efa, 0x0001345a9dc467e6, 0x000033e12139aef7 }, { 0x0000c9ca4e9b5641, 0x00084aea18921310, 0x0003a63bff437207, 0x000da19c58bf8a8e, 0x0000f70e2d2715de }}, {{ 0x000bc2ffb0c0a600, 0x000e80f83774bdde, 0x000199b044d49d58, 0x000a469a96313160, 0x000087769824fdd0 }, { 0x00009015dea24c28, 0x00015b77cfa46a5c, 0x000e60d52571b07d, 0x00070300a71e6161, 0x00003117310e7902 }}, {{ 0x000f2b9ffa5ce94f, 0x000f8b2d174d7aa6, 0x00088475bd09ee91, 0x00010b8ed4072d8e, 0x0000abdc7583857a }, { 0x0001914e9bad73f4, 0x00022153760fe8aa, 0x000f4edb1d776b51, 0x0002edc717a96e6b, 0x000069595ca97461 }}, {{ 0x0005b20d1b136d4c, 0x0009757d8a3c5cf1, 0x000315091df843b9, 0x000413cdd1197ecc, 0x00001969c8be641e }, { 0x00099ea238db2755, 0x0005526705840398, 0x00091e3df50ef1df, 0x0002e83152277c96, 0x0000630e2f484e9d }}, {{ 0x000875384b505bc8, 0x0005a8b760c1c9d4, 0x000152e6e08ee77d, 0x0009b13c5c7efbb1, 0x0000a686f3ab7cc9 }, { 0x000912a263785680, 0x0008baa3ba8cd86a, 0x000b197dbb7d4f6e, 0x000cc9952b0ce40f, 0x0000893fc7e41001 }}, {{ 0x0000049c55f94a22, 0x000bbcceb5b76c16, 0x0004c6f76e5ea2ee, 0x000e2049f746f528, 0x000076ebebbffadc }, { 0x000d3fe2ee578482, 0x0000d823c2f7c9eb, 0x0002d43d7a059070, 0x0007d72696bd9904, 0x0000ce8557b6ba2f }}, {{ 0x000ff4f96876ad1b, 0x0005eca12ef3d36a, 0x000b8e89ac75cb71, 0x000521bf79ee3c36, 0x000090ab39ba4d57 }, { 0x000a347a48af4239, 0x00064d0c47adb7e5, 0x0002a8fa03b1669f, 0x0006bc96a45699b2, 0x0000959575cb4270 }}, {{ 0x000e6e24892d0ac0, 0x000933b3cef0d7d8, 0x00079d4d1ef8b947, 0x000763500d94f7b1, 0x0000842223ee34e1 }, { 0x000d016ec18d3932, 0x000e49716caca6a2, 0x00080b51ac183c3b, 0x000187be1866c49d, 0x0000c9294fa577e4 }}, {{ 0x000e969937eb4c0c, 0x000c0c900eac3f90, 0x0000d456ae10b8bb, 0x0007d820d835f628, 0x000023a90a360f31 }, { 0x00089014af462bca, 0x000fee88f30c9cbf, 0x00043eac31b1d4ea, 0x0002462aba606ae7, 0x0000fd95461debef }}, {{ 0x000b9912384ae29c, 0x000ce9c31c71f7be, 0x00023dd6ec23d54c, 0x000ec27a301f95aa, 0x00007cbf09e9dc08 }, { 0x000c8b46801a5c63, 0x000305e5d91ba877, 0x00008ecb0399943e, 0x00077eb69c6ac628, 0x0000c52861049c21 }}, {{ 0x000e5d49ffd84deb, 0x0003a1fea5b8e69b, 0x000d075a15bd1f24, 0x0003205e5aeecb3b, 0x00003034bad431b0 }, { 0x000f13f5a83d106c, 0x000a7aae5c8646f1, 0x000801cda3d81b1b, 0x0009b5194dbaa12e, 0x00000bad3d6972ba }}, {{ 0x000608b69829f0bc, 0x00035eeaceb4fc02, 0x0002386658aa3391, 0x00022b4c83625600, 0x0000214f4fdc3f4b }, { 0x000209f113e9fbcd, 0x00005fc05268301b, 0x00088e26a0fee5c5, 0x000d514c2a6943d3, 0x000089511c6cae35 }}, {{ 0x0003ffdde3be7cc0, 0x0009e0697bf1298a, 0x000f7d9d85bb314f, 0x000a1cc6fcbdb672, 0x0000c8ea86a332f9 }, { 0x000a3d7005cb8287, 0x00033aaa914d3ba5, 0x000f2ea215e8f9bd, 0x0006b8051836d500, 0x0000034ad2de159b }}, {{ 0x000da3ce9ebe72c9, 0x0009a4d39eedbbab, 0x000746b1d5ce6360, 0x00065220c35cd2e6, 0x0000dcc999f8c73b }, { 0x00032fd30a1b75d3, 0x000a7602c9cf7a47, 0x0004089bb469c24b, 0x000ff75df01572ee, 0x0000ed51712af770 }}, {{ 0x000a4544aa046b21, 0x000e8c716543a402, 0x0006d498f7c2ddb5, 0x000b9c5149acafd3, 0x00004ad54644a863 }, { 0x0003a83affc7b669, 0x000e96291d60b063, 0x0008f4ccfa455de1, 0x0003ad227281b7be, 0x0000b48074a91ac9 }}, {{ 0x00058ae74fac8317, 0x0008162d5d721d5b, 0x0002a648ba32d37d, 0x0001fb6a40c3357a, 0x0000d41eebd7ebce }, { 0x0007312ec0f21311, 0x00009812e6dad6be, 0x00010d0c3d9a387e, 0x00083b3d8de28605, 0x00000e56beae8107 }}, }, { /* digit=2 (1,2,..,64)*(2^{14})*G */ {{ 0x000161957d933aea, 0x00028e76e6485b37, 0x000b05babd7b6596, 0x0000f456d4d3e24d, 0x0000ce6abd42c3d5 }, { 0x000aefa7aee9d873, 0x0009f83cdb12a6c3, 0x0001f36139b52f8a, 0x0008e5973bf3fa88, 0x0000e7a50e16b447 }}, {{ 0x0003f63771beff8f, 0x0006f623b36f9fd2, 0x0003d9eb684ebab1, 0x00084f3ef26543b2, 0x000096ae77bc2ed6 }, { 0x000fb89d795ff65e, 0x0007796b6a1142e5, 0x0005d3a20e91b4d9, 0x00011bfd55ea6aac, 0x0000a386dea94493 }}, {{ 0x00086584c9b213cb, 0x000f83af72e34d46, 0x000fa8a9676c4401, 0x000cad84e0bd9ea3, 0x00006265c102920f }, { 0x00057594c72c920d, 0x00088d38c97b942f, 0x000958e6e09ae71b, 0x000e172894609561, 0x00007cd5b11ce7c5 }}, {{ 0x000564bade8d111c, 0x00049fce3779ee34, 0x000d77e4a2bf81f0, 0x00017327ae00e7f9, 0x0000f7675150c393 }, { 0x0007f7ccb1668c80, 0x000b12ac4708e8e4, 0x000b5f26ce2e2a59, 0x000dbcb9f4f5725f, 0x0000c707f408fcd6 }}, {{ 0x0003a7c17140472d, 0x000581b8d9465810, 0x0003ba4cdea132db, 0x0003dade0f0d1313, 0x0000dedff07af825 }, { 0x00058b1494211ca0, 0x000df38e475381a1, 0x00026ff71ea03acc, 0x000c4dddaca1ba42, 0x0000a403ce5132ea }}, {{ 0x0007c64e36e21202, 0x00075e5522e6b693, 0x000384071de1f828, 0x00012fb5669c908c, 0x00002dc9675211f7 }, { 0x000fb08f0866ab60, 0x0007bdfee478d7d1, 0x000be1e36897f3a4, 0x00021b6dfba75c8b, 0x000059cbb6ef7bf0 }}, {{ 0x0007560abcab01ab, 0x00000f9842e9f302, 0x000f375578f2df7b, 0x0007d7f6aa331d4b, 0x0000a0561e6ffd56 }, { 0x0003b77509e9eaaa, 0x00089870e3a6b750, 0x000267e7dbebaacd, 0x000134cd025c6aea, 0x00001e66709e13cc }}, {{ 0x000dbde4ac826d0d, 0x0007c0361a341c13, 0x000fcf3f7c95b3aa, 0x000c6246c3604dc5, 0x0000ce46d1be3f02 }, { 0x000f0d1f30affc92, 0x0006a5d1c7eef696, 0x000562423070d98e, 0x0003f8fca5889680, 0x00003b45ef942f70 }}, {{ 0x0006f04d3172e6a8, 0x0009cd4196224f85, 0x0004e05cba6c1ba5, 0x00062492375a4ab9, 0x00000994feb99b0a }, { 0x000000efa0311470, 0x0004f1cbda602b24, 0x0002b9603cc9b10c, 0x0003b606b73ee174, 0x00007167141027d7 }}, {{ 0x00099b055d1c6101, 0x0001a4b12cfe2978, 0x000b9f946f882bbf, 0x0008773e83eee129, 0x00009e74c40cf1ad }, { 0x0005132b2b61a7c7, 0x000b3643a39c8cf8, 0x000df383119dec9f, 0x0008c316382f09ef, 0x00008e4c68996471 }}, {{ 0x000b4afef949e9b3, 0x000f0ab516eb17bb, 0x000f177c3832341c, 0x0009fbaa673bec06, 0x0000087396035c70 }, { 0x000f54befe9fd403, 0x000bbc8e61d66b0f, 0x0003efd4710c8da1, 0x00097a75a02bda4b, 0x00003e2c39ecdf62 }}, {{ 0x000c9a9d2168c124, 0x000671dbe7a2af37, 0x0008d31cad5154da, 0x000c67297ec51caa, 0x0000f6a5ba0129fa }, { 0x00003937564cf036, 0x000ae4f6ef5f0145, 0x000298d331a9ca83, 0x00051e01e8abcf41, 0x0000803532cecc34 }}, {{ 0x0001e274de55c8d4, 0x0002956ed6def63f, 0x00018b709b8e424b, 0x00056a6c153cf648, 0x00008cfd0094deed }, { 0x0009fdddc13851d6, 0x000243c44cc78808, 0x000af2278bc0bdee, 0x000524ae0411a426, 0x0000bf64ecb23c5b }}, {{ 0x00088c68b8e8aff1, 0x000162232398baaa, 0x0001b47037788dbe, 0x00052abf2205fee4, 0x0000c5e4c2db8891 }, { 0x000e9e19413381a3, 0x000ad417337aaa82, 0x000ce0156bb388a5, 0x0002a062f9ed364a, 0x0000c9e564f943f6 }}, {{ 0x0009d84aaee0a3f0, 0x000044a3dafd2d50, 0x00058e154e29774b, 0x0006409b135d1fae, 0x000075272e315a42 }, { 0x000286418cf25deb, 0x00030c788aaa6917, 0x00093d60897674a9, 0x0001ac1012dea57a, 0x0000de5fb8c5274b }}, {{ 0x000688350470c6e0, 0x000970977f7195ad, 0x0006d7634e8b89f8, 0x00088212d8ec8616, 0x000043845130a44a }, { 0x000f5c2ee645cfc9, 0x0005bf8309004c28, 0x000584a3ba78a88d, 0x0005275a4a96e4b7, 0x000038c353982c77 }}, {{ 0x000270f0d3fad15e, 0x0004ca5dd968198b, 0x0001bfd0499861e3, 0x000657b03fa131c5, 0x0000619c34d7bc9a }, { 0x000c59900ea25f24, 0x0005164a053a3bc5, 0x0006be2d3ae0af2d, 0x00056cbd0088254b, 0x00006bf9c020a568 }}, {{ 0x00058215b141a06f, 0x00072dda1887395c, 0x0005cda8502dab0c, 0x00008e62940960f3, 0x0000e7123058aaf9 }, { 0x000dd036eeb10f06, 0x0009558f0e1a5240, 0x000be7c0a8ca237d, 0x000ca5062b406856, 0x0000716a9f2d15eb }}, {{ 0x00060caadd4449ef, 0x00082acc33156b3e, 0x000964736c5160b7, 0x000929feff09d24e, 0x0000caac5cb6e932 }, { 0x00018427c2846cf1, 0x00007a6979b1d8f6, 0x000c35f465637c02, 0x00002fdc060908a1, 0x00001090f1c298a2 }}, {{ 0x0006877b288e2940, 0x000f33959145a65f, 0x000803b8e80eaf37, 0x0006112a0cd9bc36, 0x0000b81a72e0ba9f }, { 0x00040fa5a0fd54f6, 0x0008b9bf5cbdb258, 0x000859f95ca88625, 0x00044185f2a4fd1d, 0x0000bbdb6fce4677 }}, {{ 0x000251fe80573ec6, 0x000aebe6558842d7, 0x0003a5a1d225d97a, 0x000041e6d70df8c6, 0x0000a3616cfca01e }, { 0x000d97a9062076a5, 0x0008fcb5e9aac9a8, 0x0004626cb46bc51a, 0x00054784e11bb093, 0x000096e6c4d5afbb }}, {{ 0x00077708c667d059, 0x0003a277946d3f97, 0x00038fd019ad9658, 0x000e65586e132bd2, 0x00002ddf44a145b6 }, { 0x000ac06c3764df11, 0x000b7cd1297029e8, 0x000c3138c426b403, 0x000a6c5d92c61095, 0x000067be85672106 }}, {{ 0x000e2347ffc2edcb, 0x0001139a13046683, 0x0004c9d54e06e078, 0x000d9578de4a9c88, 0x000002ea6f0c8fe9 }, { 0x000ff875671915b2, 0x0004977ea7d23a38, 0x000cd731fc668ce1, 0x0005492d32fac257, 0x0000e0f225fb9165 }}, {{ 0x0000d8b2dae7ca94, 0x000fcb36b0cf82eb, 0x0005753d030cfdc3, 0x000d1805a6438d24, 0x0000a53ea3da217e }, { 0x000afa8c8dcb9f12, 0x000c8dbd9184c4d2, 0x0005ce430ce88936, 0x000756b473dbb18d, 0x000096aae294c905 }}, {{ 0x000ad8848abb5fc6, 0x0008de8bc36742c8, 0x000e63c869056bf3, 0x000e7b500898f427, 0x00006d577bd5f382 }, { 0x00074a2d9a7f8c04, 0x0003838d74a2a464, 0x000954574e07ece4, 0x0002da5e45e3e05a, 0x000086fa3c45cbcb }}, {{ 0x000df865364f0739, 0x00000ad653ae3263, 0x000a6954560d380b, 0x000cd878314bcf72, 0x0000e5984638d7d1 }, { 0x000ccfe3cd6ce14b, 0x00024e7b53ca5557, 0x000d2f05f16b65f7, 0x000f23968688cb00, 0x000083bf9324d5ad }}, {{ 0x00074a1d2d22f9b4, 0x00093e06c4c1fe61, 0x000a12419e4cac55, 0x000daa614557e1f1, 0x0000f204eb2e220d }, { 0x00075797ca396209, 0x0003230c51fbf539, 0x000157111a5b409e, 0x000ad3873d894099, 0x00001cfd1518ece2 }}, {{ 0x000dfe0d903a457a, 0x0001207e3533d77b, 0x000970360f08ec9b, 0x000e84aedd7222e6, 0x00008819a858ad52 }, { 0x000eb874ec49378f, 0x0000bb61d056605f, 0x000587efe032d6ae, 0x000c3fe8ca9ea9df, 0x0000fbcf08ae31fe }}, {{ 0x0005f49faf4f53a7, 0x00043867ee0d98fd, 0x000b060178b5af0c, 0x0006c8ad4201ad34, 0x0000d0bf380597e8 }, { 0x000a24911e00876c, 0x0004691c7f4a40c8, 0x0000e8e94c74da88, 0x0004ffd872e69d9c, 0x0000a4ebb0eb3649 }}, {{ 0x000d6de7bd491998, 0x000801060a716760, 0x0008e8fca31418e2, 0x000fd8b1ee852d1a, 0x0000dc52d76da81a }, { 0x0007f0f335115f76, 0x000f988c8e347f89, 0x000703e8a98e5e7e, 0x000a7f3501c58754, 0x0000eef253d19b22 }}, {{ 0x000b3fe0f9da5724, 0x000bdce4924867ad, 0x000f8578681e0a84, 0x000597679bd5f51a, 0x0000d1366a434662 }, { 0x000ca8b8c079486a, 0x0002ad8556fa9db6, 0x0008b69876ff7430, 0x000332891fa26216, 0x0000f462db921b41 }}, {{ 0x00022a049341c337, 0x00033a9bd7638026, 0x00000306390eab7d, 0x00022f7c4c21486a, 0x0000d141475b8b86 }, { 0x000540cb1b1be032, 0x000da9dbb7a8ee0d, 0x000b96c0e3c063f7, 0x000de42ecdc2ed3b, 0x0000397c62c0f6ec }}, {{ 0x000736f9291ef406, 0x000e74ecf84f6c7a, 0x000b85d2161ab278, 0x0002f97b48561fb9, 0x0000bcf6264a5050 }, { 0x000c70cb296a5d7b, 0x0005e292c1950ee1, 0x00033a6b46899d57, 0x0000d0c8eda17754, 0x0000b3f3cc6b8110 }}, {{ 0x00070c1c8efd9357, 0x000358b6f0f7c500, 0x00087e41afdefe0f, 0x000242f42a8eba2b, 0x00006e5680230b39 }, { 0x00079d74c341868c, 0x00037716484d2e49, 0x000e75a3cc667a4d, 0x00052af0bfb78318, 0x0000b9d00abad929 }}, {{ 0x000667ac0d2f8437, 0x0001f4761fb04286, 0x000a587e78c7cc95, 0x0002a4ffd4d78954, 0x000020826521d389 }, { 0x000ac4bacee14c89, 0x0007c1243bcf832f, 0x0006a53c4668bdcb, 0x0006e01a7fbadf8b, 0x000053ad230ebad2 }}, {{ 0x00058566c410a298, 0x000708d977eab403, 0x0005f1db4ccc80c1, 0x0006b3d5351f4c5b, 0x00008dad5554cb23 }, { 0x0009e5f0b7cfc603, 0x000d39e5068f5ff5, 0x000c81197a4e6a94, 0x00018bcf0f31435f, 0x0000e92434aca407 }}, {{ 0x000943b3af624454, 0x000dbb898559acf1, 0x000e3473e7a0fb04, 0x0005b12aa96018c2, 0x0000fe9ef544dffe }, { 0x000ec75726be2472, 0x00024df15a40d39b, 0x00038d59a09f0400, 0x00073ce4cb2a4468, 0x00009d760075d37d }}, {{ 0x000213754eefea23, 0x0007e63bea064441, 0x0002e51141a3c690, 0x0004ea5ab27e95bb, 0x00006619f7919ae2 }, { 0x000cc970d32e84eb, 0x0002520716e0f742, 0x000ed2f724ef5dbe, 0x000273e326679c82, 0x000049306f2821a2 }}, {{ 0x000f8396342a360d, 0x000122f740f0e66f, 0x000a2be78d984691, 0x000d47ed7545c616, 0x0000556fdb469789 }, { 0x000fcb8983c3880e, 0x00019d9025ac99a0, 0x00001b9859b74109, 0x000503719d314d4a, 0x00003e7c7f956365 }}, {{ 0x000fd58ff1b72f01, 0x000216138634818c, 0x0003e4769e197596, 0x000b0daa3501814f, 0x00007ddf3af2b89d }, { 0x000db6eef931c2b7, 0x0002414d3b507a84, 0x000e7754ebdfc74a, 0x0002342aa57bd478, 0x00004e0dcd5fe91f }}, {{ 0x000de92572a83fdd, 0x000151ad1fc0654d, 0x0002a33d78008489, 0x0003f6cf9c71cc96, 0x000005b75269915f }, { 0x0005f44d1e992bfc, 0x000daa3f97ad8f78, 0x000f0c59969f0192, 0x00014ac00e6c19d3, 0x000025a10641d608 }}, {{ 0x000332b6dc4e101e, 0x000a28b09d64c52b, 0x000f42ace06d0b43, 0x00063417da1b5e49, 0x000046ce47f6dc04 }, { 0x000f0bc5a141ae2f, 0x00059a0b4511aa47, 0x00025cca06b413dd, 0x0001f23bd0978875, 0x00000bd956a4fb97 }}, {{ 0x0009ff29ad65488e, 0x00084d4c11f61ef0, 0x00043084bdf0af25, 0x000773c159ce1075, 0x0000ec6435d82c07 }, { 0x0008b5fef46ca97d, 0x000f5bde7da946e1, 0x000bd5caa5fe7671, 0x000b00fe4ebf9eb3, 0x000075259e3b13aa }}, {{ 0x00038c534e92ad2a, 0x000a3d35958cd79a, 0x000479aaddc64328, 0x000e62d263580a1b, 0x0000ae928f234367 }, { 0x0003cc3e51cd352e, 0x000b60a2ff5845be, 0x000cd9abd92da353, 0x0004a6b20e5bb40b, 0x0000ae386f9756b8 }}, {{ 0x0008ec52c22da1f9, 0x000befee5682d265, 0x000f55dba5b9efc6, 0x0007758ab5206f76, 0x0000dc15c6ab6dd6 }, { 0x000ae060d5586b0b, 0x00084990f75cf9ae, 0x000ecfa270009add, 0x0001d8aabf411951, 0x0000e895791fe909 }}, {{ 0x000bd450efe0661a, 0x000c5737fb54dc25, 0x000ac9c1e559ba7b, 0x0009f36811f3e391, 0x0000aca8c08c3b1d }, { 0x000890e30907b5a8, 0x0005467981eb389e, 0x000751746dcc2ec9, 0x000873f5ced7e192, 0x00002b55533c62a3 }}, {{ 0x000d7f7a52f077e7, 0x000cf82feccef760, 0x00057e3af33fc8e9, 0x000ab8ec48b8e11f, 0x00004d722538f93a }, { 0x000e2b5b0ebc17e7, 0x000ec0a9efe5633d, 0x000a76269e26417c, 0x0003683002d8d246, 0x00005e002152d468 }}, {{ 0x0007d2501ccbde9a, 0x000a25abf776f5b8, 0x0000d8632ae86106, 0x000e0a57a6f72407, 0x0000bbf66580faa5 }, { 0x000a4228cbe2da60, 0x000f2e187b053405, 0x0007c7202366612a, 0x000206ddbb7bf7cc, 0x0000bac9edde0240 }}, {{ 0x000632d18502246d, 0x00069d6fd4fd6717, 0x000e4ca7cf89ed63, 0x0009c7e96a233687, 0x00006b0153bdbf01 }, { 0x000381366bc36648, 0x000b0e940735ff4f, 0x0002cc87fb85426a, 0x00097f7183a3e6e1, 0x00007201b1efff17 }}, {{ 0x00034d89dd22ce0a, 0x00018a960167d923, 0x000841dc67af01f4, 0x00085a71462f9d6f, 0x00002030a417e2e0 }, { 0x0007d6912f7833d4, 0x0008fba2a4383ce6, 0x0006f5229a7161b8, 0x0008aa0c0cec8e93, 0x0000c10be8855950 }}, {{ 0x00084ec70d77159c, 0x000d0461b9131492, 0x000f11ff3bcd0483, 0x00018499436aae2e, 0x000053055174f620 }, { 0x0001596fa6d718a3, 0x0000fd061391d54e, 0x00061cb7deec1cba, 0x0002f8aff69c5d5d, 0x00006bb3ce340edd }}, {{ 0x0008ec05f3a623c5, 0x000965696a71cba9, 0x000264ded8c36a35, 0x000a9bf71944938b, 0x0000d4afba995956 }, { 0x00012ecd8b87d02c, 0x000a21b0698304a7, 0x0003b08f2a1059a1, 0x00051b2c12d69144, 0x0000fce76e99e893 }}, {{ 0x000176fbaba509a9, 0x00057a700fd56e19, 0x000267db806ce842, 0x0003499e102ec969, 0x0000b53556f68ba5 }, { 0x000e116c316d7216, 0x000dbba44b7b6187, 0x000973ccdceb19b4, 0x000436cc0b4d7aae, 0x00006be87ea1879a }}, {{ 0x0008553aba1f2c4a, 0x000c581466265d74, 0x000205a2733679fa, 0x00047457fb15b6fe, 0x00004fd50ac219da }, { 0x0001bd339486e911, 0x00019c8c21e94db8, 0x000d3c038859a5de, 0x00057368f795ac38, 0x0000e90f47c1b4a7 }}, {{ 0x000cf9b00c68264b, 0x00090e956b3c4f2a, 0x000ee347c7bffba2, 0x000dac4c1017a99c, 0x00002d4fa858cee4 }, { 0x0003e8b689fdab85, 0x000378d47173611a, 0x00080894bee52bc5, 0x00029bca21a4cbe0, 0x0000cd609cc3206a }}, {{ 0x00010dfae15b10c8, 0x0009eda4d88f1dda, 0x0004d9c563094fbf, 0x000680267c604f16, 0x0000e738ded43ee9 }, { 0x0004f544eac66991, 0x0008b76af36f4e47, 0x00023a4a4a5e2681, 0x0005f158c994b229, 0x00008811132390b1 }}, {{ 0x0002b76b184bc485, 0x000d6b98113a7572, 0x000467e11acc370b, 0x000e3015f4ef2d2b, 0x00006a474045ccce }, { 0x000def0c94233a80, 0x000a310443516830, 0x000696031bac0d4f, 0x000e459479d86189, 0x0000536ea5513960 }}, {{ 0x000f5796a5a19f3a, 0x0001a174c7c15e09, 0x00019acfe58d4e71, 0x0003d955f539bfb0, 0x000062e8e0c9e958 }, { 0x0004a8ce6d3e344e, 0x0004fe84f157269f, 0x000485874afe4d4f, 0x000560c91c825c1e, 0x000052b87c2a4f9e }}, {{ 0x000a6c9d078887c3, 0x00072a770cbac78d, 0x000b1c459c509446, 0x000e4ed1183488e9, 0x00005eb15cc6694e }, { 0x000d2b810054b0ec, 0x0000f30dd648c523, 0x000c15d01ed16251, 0x000a54486994ca02, 0x0000ab1e189c171a }}, {{ 0x0006c4fcdd32e0c3, 0x00085c85963a46e3, 0x000572d964eab5be, 0x000a454b4658ab87, 0x0000336a4535aa18 }, { 0x000adbe47f352065, 0x000c2a1a3906def5, 0x00070765a4c6a931, 0x000b907de9fe95f5, 0x00005cfb0d9f02c8 }}, {{ 0x0003d6b0785941c9, 0x0006e0f396de2b60, 0x000bed16174546c7, 0x000db3d7298583d4, 0x0000fd49ba83df8b }, { 0x000c93db80ebbbf3, 0x000ea93b0b64912e, 0x000328d49f883c1f, 0x000302da99b3a343, 0x0000fc0ce27be066 }}, {{ 0x000a22cd41ae626e, 0x0001e2466e48bdd8, 0x000887aa0a4c529d, 0x000c298032514f2f, 0x0000980fe0c00e32 }, { 0x00016284b5cf64ac, 0x000e1f4b283e4c6c, 0x0008c9d6f389d580, 0x000c0ec0978c2985, 0x0000926037d62cd5 }}, {{ 0x0001d36874bc33f5, 0x00084161338830dc, 0x000b103ed755e9c1, 0x0009151f86d4b8a6, 0x0000aa1dcf33163d }, { 0x000f1ebe4e82f431, 0x000b3958d436d13c, 0x0000c091c2614a82, 0x000b90eb5d4d9c22, 0x00002e1a3189da65 }}, {{ 0x000e6e2135aa3e34, 0x000406a584c5e205, 0x00015b6e4efffd6a, 0x00016589b267e4ea, 0x000028a50a289a0f }, { 0x000fef4e6229a8b1, 0x0001b6a8c8f936e6, 0x000445d2f37ab589, 0x000b64a868af84d0, 0x00002d1d526d0d0a }}, }, { /* digit=3 (1,2,..,64)*(2^{21})*G */ {{ 0x0005c78880bdb670, 0x0001f09257226088, 0x000a8d556d463880, 0x000fe87ac131260d, 0x0000a978da1cbb3c }, { 0x00081d1c0fbab2fc, 0x00085ffc3bdf24eb, 0x000b3da6a9989162, 0x0009b73405bff75c, 0x0000d9387ea82fe6 }}, {{ 0x0002b79aff1b7640, 0x0003cc8f43a730f8, 0x000bb0f3be0fe168, 0x0008ce40be89b6f3, 0x0000da60e29a2a91 }, { 0x000b662498ee8663, 0x000c556962fe5de3, 0x000b255f6d5a6808, 0x000a245580c590ad, 0x0000e4d2e7887b5b }}, {{ 0x000414582cf35827, 0x000a80d6c39765a2, 0x000d882871de9e8b, 0x0003d1450a2db3ac, 0x000046f7d2fddbd8 }, { 0x000672303b75f511, 0x0007abc60eee9a8a, 0x0001cc28700717f7, 0x0003de4d554c79f0, 0x00009aa79fb6b0ef }}, {{ 0x0004ff052f5917b5, 0x000faa8719c05631, 0x000ca760c26fde52, 0x0005d57d3cd8ad2d, 0x0000bd74588b7072 }, { 0x0006ad71d02a024a, 0x0003acf3e2d65208, 0x00078da16339cd4e, 0x000f011987ebdf0f, 0x0000079790c922a9 }}, {{ 0x0005c0e37aec2320, 0x000de9226f435728, 0x000ad7c163ddcc04, 0x0006d74c1dfd3ab5, 0x0000e297c00ebf67 }, { 0x00035b9485776668, 0x00011727be19ae06, 0x00067bb1a22fdff6, 0x0004b977e616a339, 0x0000d8b5f68742af }}, {{ 0x0005de4f4a416a75, 0x000c7dada430c0b9, 0x000da4b88b7c5154, 0x00041bd6a4702850, 0x00002e74a9165ad4 }, { 0x00017cb319502a4a, 0x0006309e265c17ce, 0x000326fe85685ff1, 0x000d07bca24e4546, 0x0000bf42ebef2391 }}, {{ 0x000819dd9659911d, 0x000754374dcec468, 0x000ccca8d9a91332, 0x000dbbc9c33cfc02, 0x00001f5408b7ae98 }, { 0x000eb357eb3611e6, 0x00044a60871f4274, 0x0005a83cc448d345, 0x000e00faf8e0cf36, 0x00003b6703b79d89 }}, {{ 0x000f5d55f460757a, 0x0004ec4868af75df, 0x000e466b71f6795b, 0x0000c72b0d7325cf, 0x0000e10c5f3da26c }, { 0x00094ad8a7522d79, 0x000cc411977a0ee8, 0x0004e8d5601f6c03, 0x0001e3b955085c4c, 0x000028f635d618a7 }}, {{ 0x000f311e0eabc31c, 0x0000741ada354383, 0x0008c56a6e3fb07b, 0x00054b334f4a9fc8, 0x00001f2b7d334bf3 }, { 0x00027ce89b6036fc, 0x000043892ab98919, 0x0000ac10010e629b, 0x0008e3fee257bdcc, 0x0000d4e8e7aaee28 }}, {{ 0x000cdb6e7895d161, 0x000cbca523db2808, 0x0009c3f8c90b1ad1, 0x000c6706f5c889f8, 0x0000605933f73ab2 }, { 0x000076d41f277058, 0x000c4f0179c8e744, 0x000207aa49414348, 0x00014ba00d8874e5, 0x000029e04258b6c3 }}, {{ 0x0008a790b23045f3, 0x000333c47b517ea8, 0x000ca7c0cdac91c8, 0x000c03ea079a448f, 0x0000f88cfdd1c6c8 }, { 0x00044cc5afb2f094, 0x000787d80969fe8f, 0x00034cfc5609af25, 0x000a4e12654f92fd, 0x00002a65082a73a9 }}, {{ 0x0006c0d50cd87d6c, 0x00017278b1e68b79, 0x0009997e54c71ee5, 0x00052d2cbc731ad7, 0x0000b44017339c7f }, { 0x000bf64f7d3a4aac, 0x000f3e79b4f7f248, 0x0007b1a318728a1b, 0x000e1748dfdd781d, 0x00003026e7244622 }}, {{ 0x00007a3c1ceeb879, 0x0000d2c467be912a, 0x000926c2f4afd167, 0x000ffc5c7f4c85ee, 0x0000156de531a17b }, { 0x0002c133aac4e622, 0x000cd450c00beb33, 0x0002cd4c1893c312, 0x000229d5b30e2c2b, 0x0000fcacc4f9ea39 }}, {{ 0x000894a646301fb9, 0x0005dbb32e5685df, 0x000860524efe08bf, 0x000a632c668a9e06, 0x0000a480e5c2b19d }, { 0x0007ec2caf1e7fea, 0x0004b0a09e27ecf4, 0x000e110aeaeed496, 0x000f877baeced201, 0x0000dd057fe48dca }}, {{ 0x0007eca65a996482, 0x00015c4f68367ced, 0x000ae66db0fb60e8, 0x000342779e4f47d0, 0x0000d6d9565d0319 }, { 0x000b6873efddb317, 0x000a47149ded0a33, 0x0004bfcc5fd5434a, 0x000d273334cb2aad, 0x0000fecf3dc03882 }}, {{ 0x00066010689e1641, 0x000f3b22c11bb373, 0x000db6ec643ab5eb, 0x000afb15d2d0366d, 0x0000ab615f997250 }, { 0x000b5f7e8a49c22d, 0x000402c68d7b6d44, 0x0008c124aab7be0b, 0x000a684eea8f74f0, 0x00006ee0d7c27a2d }}, {{ 0x0008fc242b74d79d, 0x000d47789070d267, 0x000e6420679c51cf, 0x000c68217a1f28e4, 0x00000be63ac7dad1 }, { 0x00042c485ec72b60, 0x00065928b0588f1b, 0x000c610949c0029c, 0x000ba4e35b6b7a0f, 0x0000c2df5af332f6 }}, {{ 0x000752e537b3aeec, 0x0005213dbab98aa3, 0x000b6a282aeced62, 0x00097413ade9d469, 0x0000c4a05092000c }, { 0x000617ba15d6404b, 0x0001fdd15544eb9e, 0x00069ae3e8640d68, 0x000dfb6b5f013aea, 0x0000c07b8448571b }}, {{ 0x000d7158f2903d4a, 0x00038a6936219d36, 0x000440e072274354, 0x000ca5d4c5ce1f19, 0x0000aeea5b76a62e }, { 0x0008beb35eb7c48c, 0x000df21e300ce18d, 0x000f545273fe83bf, 0x0005f0f9b35fba62, 0x00009e3ee834d7e8 }}, {{ 0x0002699749223725, 0x00006b01f7e320d9, 0x0003db3989a12b79, 0x000dc64a30641c36, 0x000085fd6388145f }, { 0x000b92552feb649d, 0x0005217ceb6c1434, 0x00018da120fb460b, 0x000267af867fcb84, 0x0000515b55c60526 }}, {{ 0x00099bdc6fc777ca, 0x000fd0e46aca7930, 0x0004dbdd54abe6f3, 0x0008b2d161cf0b0e, 0x0000bd4ba21f4e90 }, { 0x000ce18473bb041f, 0x0000cb20caf8b051, 0x000a55f4b97f1131, 0x000c0d508f74d505, 0x0000a157aa07d7d6 }}, {{ 0x0004d831d9980ef8, 0x0007d9783abdb4a0, 0x0006da10193eb141, 0x0008f6fdc850fbcb, 0x0000b1f65be994c8 }, { 0x000ca16d905a0431, 0x0007d3bfa12d45da, 0x000d9aa574b633e6, 0x000f1c21ee425f8c, 0x0000472d6784e4ca }}, {{ 0x0006be873329a887, 0x000d36a9152f9347, 0x000d764f8b8de418, 0x0009ef6acf1235e5, 0x000039762606b9b0 }, { 0x0003ee10d17b708a, 0x000ee310c0cd3130, 0x0003a226153c53ce, 0x00041a3153c52455, 0x0000f1a929d0274f }}, {{ 0x00079739f7318d32, 0x00027b21994ef202, 0x00093bf3a921a053, 0x000dc5e102a653b6, 0x0000417acbe360fd }, { 0x000b40cff123155f, 0x000073c8b799336a, 0x000c74fb67fa3a8f, 0x000c69c2dfdfdf14, 0x00008baaad38eb7e }}, {{ 0x00090bdcfccc29da, 0x000d983d20b42d5b, 0x000ee66ca762f3ee, 0x00090c3f0f9a810e, 0x0000f553cd3456f1 }, { 0x000e248f78d9528b, 0x0007a91f01ab782d, 0x00008ccc9b0f3f1f, 0x0006eb901c823f21, 0x00005ba0497c7a34 }}, {{ 0x0005b53add7650bf, 0x00085e50cafe751d, 0x000bff2797447909, 0x00034812473997c9, 0x000097d3990af468 }, { 0x000e25f2ce2b08a5, 0x000d511dcedd8d12, 0x0008468d39b5d584, 0x000d543b1406bd1c, 0x0000fd5a272530da }}, {{ 0x000a70e6bf33183a, 0x000a35e29dfc254e, 0x00054127cba88ba8, 0x00015b8ad4455fcf, 0x00005553f496e694 }, { 0x00036bb6459a57f5, 0x0006c695820f3bf6, 0x000d3acc40499055, 0x0008db783f410d2d, 0x000031a7e7bc74e1 }}, {{ 0x000fa724e36fba72, 0x000dca39754e21c0, 0x00067dbc9e8fb755, 0x0004f699abc87a3e, 0x00008aa8469ef3d1 }, { 0x0006c5db934e2c84, 0x000c829b0720b169, 0x00026fe7131a51c7, 0x0003ca5a62dd0cf1, 0x0000be10a91df994 }}, {{ 0x00074764ddb736f7, 0x000ddc05f18395e0, 0x000418396b551790, 0x0004f105bd3f2274, 0x0000b92a58459d14 }, { 0x000f0b4e7fc1d0d6, 0x00013507bc7f3893, 0x00007a6a15e11d01, 0x000d3ab57c580c85, 0x00003331b44a24bb }}, {{ 0x000f11236279ebc4, 0x000a9e8a9f19c539, 0x0002ca63bfeba930, 0x00064cba95717bd7, 0x000086b4bc72b477 }, { 0x00076fcfeec45e44, 0x0001a31823b73482, 0x000584f3707abbb6, 0x000397e584dd8f0d, 0x00002080c6a3d85e }}, {{ 0x0001374518550834, 0x000e75e2bc0aea9e, 0x0004fcfb4f1939ad, 0x000dc847e4f668fd, 0x00002277741998e3 }, { 0x00010649ba9269ce, 0x00029e6853ac983a, 0x000dc7e1409c87dd, 0x0003f9fd1c3bdf42, 0x00001a9e558bca9c }}, {{ 0x000984d8c0756da9, 0x000f60b879fbbed4, 0x000691183fa97cc8, 0x00008c6450ff0ae8, 0x0000bc7e3aa798e1 }, { 0x0002c0087c8490da, 0x000bba6d21008f03, 0x0000075a13ccfa3b, 0x000db76f329bd54a, 0x0000cdfd68fa494d }}, {{ 0x000eda0108b2b2b2, 0x0008ae60c1cdb260, 0x000746a2a0fce8f9, 0x000ff4bcdcd94d94, 0x000051bef4868fea }, { 0x000105f6c2d3fcbc, 0x000aa1056152fcc1, 0x0006d6133470c109, 0x0003149a4c2f037e, 0x0000f1a1f67957f5 }}, {{ 0x00013c1b9dfbee2e, 0x00007008733913cd, 0x00026dfec0a26cf9, 0x000b44ae9cce8616, 0x0000301eb9bba43c }, { 0x00058c5a3c8e1fd6, 0x000a8c71c74cf5c3, 0x0008bc18677805cd, 0x0001a3bf18887dc4, 0x0000f290c47af3bd }}, {{ 0x000c23f6bd8f7001, 0x000c304890228299, 0x00069f5598bb730d, 0x0004e6dad40e9397, 0x00001a83f93d79a9 }, { 0x0004233cffc4cc06, 0x0001435fbffd8bb2, 0x0008f52696de0ca5, 0x00059d33a60fcfb4, 0x000067aa71b84bb3 }}, {{ 0x0006fe382d94c44a, 0x0009a6ce6d982af4, 0x000ea056154ed2e9, 0x000c78687ebb6bf3, 0x0000ae247fcc48a8 }, { 0x000a247e575d5c4d, 0x0005ae8b5bdbd756, 0x00014ecdaaa75fdd, 0x000bff600ab38133, 0x000002fa41762570 }}, {{ 0x000df2688e5c0bfa, 0x000f81b636288bec, 0x0003fab55a773328, 0x00085a4049dfdca7, 0x000085fc068e8d8e }, { 0x000976ef578a35f1, 0x000ee44d0f8a67ee, 0x000a21e1e0b95bd1, 0x000ef07f4d985df4, 0x000004f8b7366d81 }}, {{ 0x000b539e244d918a, 0x0000baca1c323732, 0x000a47f86bef05d2, 0x000da4bbc351027a, 0x000011f52fa1b210 }, { 0x000bea3fa5e2c7e5, 0x00067ec0eaa1d710, 0x000d5a338fbff1d1, 0x0008ce2402a83381, 0x00009435f8928998 }}, {{ 0x000aad621cd624b4, 0x000028436cc61347, 0x000345f6e1c0c72b, 0x00016c92a8eb9bbf, 0x00007457c7601162 }, { 0x0003e95ca5e2ca28, 0x00025740a8f7cc07, 0x000d936cd0bf865e, 0x000cd30eee820c2c, 0x0000d32e75fd1366 }}, {{ 0x00075553bbd18331, 0x0005fabfbaf50a55, 0x000b10f8b3952494, 0x000f37f05df55e76, 0x000083667f4aec1f }, { 0x0001b91149c64f10, 0x0006ca3553afa736, 0x000beb9cb1077179, 0x000ef4d35315f3ff, 0x0000724cdc42e0e8 }}, {{ 0x0006710053e87e6e, 0x00027d3fa326dc3b, 0x000e628b2c963b4e, 0x000250f591df4da1, 0x00007156cd0888e8 }, { 0x000ea109e476ac64, 0x000027e618344d14, 0x000251c33bcb204d, 0x000e1583acc7ce04, 0x00003fc838df305f }}, {{ 0x00061e97bf3ccbad, 0x000faacb40961bf5, 0x00071486d43b1a75, 0x000ebb8d14ada593, 0x0000416698a685c5 }, { 0x00083dfe218457e7, 0x000beb6da3982f5d, 0x000cdd08f647376c, 0x0000946200c2659e, 0x0000016501cf88d5 }}, {{ 0x000970713804550a, 0x000ba5fb835398c3, 0x000f7a19d08a80db, 0x000a0d2db6106a8b, 0x000024eccd926e31 }, { 0x000c5926d6e5fabb, 0x0007d34d8249f00d, 0x000ececc10c98ac7, 0x0006705c29f14b58, 0x00007dd9e5578e79 }}, {{ 0x00059b045ae4cdd6, 0x0002d398e77738ae, 0x000f16095fcbf91e, 0x000b19886d07a63e, 0x00009b2d8bb94209 }, { 0x000115fba320b394, 0x000f0e520fa03389, 0x000859e95f2ba538, 0x000efef1397939ac, 0x00002792ae3d4093 }}, {{ 0x00097bb53067a096, 0x0007ac25fadf8c35, 0x0002749e0bb22636, 0x0005dba2266be38a, 0x0000e8e24f086be5 }, { 0x0008e7ffb7148254, 0x00032b7c153ca7f9, 0x0002d7956406285c, 0x000de7e1ea8d30fb, 0x000062282ab3dba8 }}, {{ 0x000b613b880d4a8f, 0x000eef8e9726a306, 0x000f446cf9abc9c9, 0x000a75d40b5e216f, 0x000085573a0b1122 }, { 0x00016530e4f15d5b, 0x00032ba792d56100, 0x000aa02bcafc965b, 0x0009826da2ee1270, 0x000079f2ed0cf73d }}, {{ 0x000b9754a0266bcf, 0x0006efd8fd6ee891, 0x00062aed3b5fa54d, 0x00038abdf16d3d98, 0x0000116ae37983f7 }, { 0x000a47cbfca3dc3a, 0x0002cdf70c33b988, 0x000e54ec4c71ebb6, 0x000f60732aadc87a, 0x0000b626c156e4a6 }}, {{ 0x0009f8db144f77e9, 0x000026662b5f3af3, 0x0000d0c25c1ff887, 0x0007b73b1cefab56, 0x0000cd5a1cf3f9ca }, { 0x000d5a818694755a, 0x000725b3c61bfd60, 0x000d33c6e57d6b39, 0x000d8c2c2a5a4d41, 0x0000da06aa84668d }}, {{ 0x000f71b5f5f2e3b8, 0x000bcf7d22da9a9b, 0x00080d18e517fe23, 0x000df74ff45b8a67, 0x00009b0d34e92cca }, { 0x0001751253d7af6a, 0x000152f69fc4db96, 0x000c14e7ef8dbe16, 0x000e0dc35b6dad34, 0x0000dff44628ebf3 }}, {{ 0x0005c4cb0846e24e, 0x000db9781af2c2d1, 0x00046bf50cd29179, 0x00070f08dc0f7d9c, 0x000019b4a7b7a5c1 }, { 0x000c9beacfa5ec60, 0x000d2858e121e14e, 0x000d98641f8ff20b, 0x000390274eea7dc1, 0x00008ec5b0cee6b7 }}, {{ 0x000bad30cf8c7404, 0x000a6d71df978283, 0x00056ce647a78ac9, 0x000f06b3cbf851cb, 0x000022014a98c474 }, { 0x0009c81e9e8866f3, 0x000bf02496bbcea3, 0x000eded9ca1c764b, 0x0009f6d293cf9fd4, 0x000097210cbc6093 }}, {{ 0x00067291d1c7e163, 0x000a9b97b390d355, 0x000d3fd8195610dc, 0x0000e01f801df2bb, 0x0000aeaffaeb93fc }, { 0x000e7ba92c88e286, 0x000166c5f5406d3b, 0x00089d2d39130c67, 0x00026e8ce71fdda3, 0x0000429a520ee24c }}, {{ 0x00059814cd121bf2, 0x000e16bc6fb5a7df, 0x00097795bc1333ec, 0x0007bb16ae3eea15, 0x0000ea9234811e7d }, { 0x000b866e7b5afbdb, 0x000eab01c33c23f3, 0x00043423d2bafbcd, 0x000358a51a96c1da, 0x00000a66348cf983 }}, {{ 0x000243ce8547c141, 0x000e6d81495ed6bc, 0x0002f43f0e622ab5, 0x000c4cff3b239424, 0x0000291035b7c92d }, { 0x000997f8cbbf2476, 0x0009771dbbf370fb, 0x0006bf48fefebc0d, 0x00056dc3fff9afa3, 0x00000d06a64f152b }}, {{ 0x00080c94a72ec503, 0x000ca2a37bbb1840, 0x00099c508afef996, 0x000d131cb51dcec4, 0x0000989196a9bdb3 }, { 0x0008f4ead02f1a6d, 0x000d0b12283fbe37, 0x0007e19e2b1d8b3d, 0x0007bdeec902bddc, 0x0000d0bde74ee357 }}, {{ 0x000633d510319630, 0x0000a4956f908239, 0x000fdde9a26b1a49, 0x000f5c760ba0f507, 0x000011a47fccb3c1 }, { 0x00074a4f6a780782, 0x0003543b8c9de617, 0x0003e69cf7b58be5, 0x000c69ab2b475125, 0x000059a05b225efc }}, {{ 0x000530e06a0e952c, 0x00059f773848f22f, 0x0005fec775249e0e, 0x0002f45f953dad71, 0x000030c4df804685 }, { 0x000aa392d634bc5b, 0x00056ffdd59d31ae, 0x000e1e3714bf08e3, 0x000102dd74382e0d, 0x0000d560753775a1 }}, {{ 0x00032c96e155ca24, 0x0001867648024ee6, 0x0002290314ec3e56, 0x000e4a435188763f, 0x0000359aad14cb65 }, { 0x000aec2c62bf9c7a, 0x0002c0e4c00a95ea, 0x00003525bd976a14, 0x0001af8232ef17f4, 0x0000950b712f6e56 }}, {{ 0x000cb27078304cb0, 0x000d8d83d84e58c4, 0x000c48d30163a309, 0x000b9d2a62af5094, 0x0000f43399bda145 }, { 0x00025423b825ac58, 0x0006d474ff0e321a, 0x000578e0a546e9ad, 0x0000fc3a7169f34a, 0x0000fbaf5744de2d }}, {{ 0x0001d6998c9bae7d, 0x00058d50ac8b7823, 0x000bfbdd2f05c1a7, 0x000dd3942ff6622e, 0x000068b2d4cab4cf }, { 0x00020e9934c184c5, 0x000bb04cadcaed01, 0x0002c60e6c081a2a, 0x000de49c6801b014, 0x0000c34427b5c797 }}, {{ 0x000321a50d8134d2, 0x000c8a4fdc6a4043, 0x000e6e6ef43ad26d, 0x000b3c48119d8e01, 0x0000448b0fd8e456 }, { 0x000066350f1fe586, 0x000e263e9a861112, 0x0000e63d8756b063, 0x000ba08ef8c0cde6, 0x000050af05bd3adc }}, {{ 0x00058deddc932110, 0x0003689e56ddfbd6, 0x000798a4aa5dbc69, 0x0001ba8cbea1b0c0, 0x00007b58c49685f4 }, { 0x0002efa53a6c1ccc, 0x000e34d0f64ef589, 0x000ce01d226df9d2, 0x000e7b170fe43287, 0x00000387e93337d0 }}, {{ 0x000bbb69838b4dc3, 0x000c15794b565268, 0x000e7da596a97b99, 0x0008eee0f415cb80, 0x00008189781ee1eb }, { 0x0008da59e33a17c1, 0x000b85b9abc26689, 0x0003858d35ce15d0, 0x00065e1b9b5d4f53, 0x0000e8073f5adb41 }}, {{ 0x00041b32e5ee0cd0, 0x000bea601799a527, 0x00014451f66c2b00, 0x000f25a7ca20cec4, 0x00001caa549ccc91 }, { 0x000641caaadc47ea, 0x00097814eb57d471, 0x0004006d25c11bc5, 0x000a4cb887a2d0ed, 0x000005cf797f0540 }}, }, { /* digit=4 (1,2,..,64)*(2^{28})*G */ {{ 0x000cf9a2f2b6ddb7, 0x000cb4f20151427a, 0x0005e5495f13c8bb, 0x000336c57206828b, 0x0000deb474abe52a }, { 0x000c630fc54290e0, 0x000e9da279153564, 0x0006b3bbef1e9949, 0x00021a8e27e0734b, 0x0000614b2885f690 }}, {{ 0x0004ab68d7e959ee, 0x000227a1ac2703b2, 0x0008471ceedd9bdd, 0x00080ded1b49258d, 0x0000011c8d9a06d3 }, { 0x0000b360f8d06cf6, 0x000bfd4734e59d08, 0x000843e26b87ae6b, 0x000b0c3b35f8740c, 0x0000b6d468726158 }}, {{ 0x000ac1e3e5d6df58, 0x000075d5fa067d1d, 0x000ebba6b226d7b2, 0x000af82ac4134b57, 0x00001bb953caf0cd }, { 0x000cde538c8bc9c2, 0x0003669d81fbb26c, 0x000be58de047db86, 0x0007841e8449ed3e, 0x0000d643fef5794d }}, {{ 0x0003331d3c69f2bc, 0x0000a8da61a76fa3, 0x000d96e2379febe3, 0x000486b9c598b441, 0x0000390a58c27d0d }, { 0x000cdb9daf4c5417, 0x0006d8e298de399d, 0x0006c4c6e1a6e0f8, 0x000649470cfdb8e7, 0x0000690440cf3b0b }}, {{ 0x000cd3d0d4027b25, 0x000d3c2019f2a596, 0x00035e7beba07964, 0x000164eddb3ce5bb, 0x00000d8037d39488 }, { 0x0000c29968554c2a, 0x0009ad6efed021c1, 0x000059b49a323da0, 0x0003c9c4a09a9f9b, 0x0000c0cc53fbad1c }}, {{ 0x000c73d2287162dd, 0x000c529ed6e82ef1, 0x00034977dd25e6f6, 0x0004a8aae16f338e, 0x0000dc61c21e5eed }, { 0x00096fe447e4eae7, 0x0006a3174a5c8c7d, 0x000fa5f9c92267ca, 0x0007c117e01cd296, 0x000068abc8039604 }}, {{ 0x00041d6367599350, 0x000706e88fbd3813, 0x00042818412bda97, 0x0005e6bcd02cd4a8, 0x0000b40e707676fb }, { 0x0006fe0a3a3a6e7f, 0x000d8fbd238202b9, 0x000a1286e09fb174, 0x000d4efa0600b4d1, 0x00005566cd140a17 }}, {{ 0x000246780b6116f2, 0x00015367f636a38c, 0x00064c305dbfeb38, 0x0009f998b9f943fb, 0x00002a4f058aaf47 }, { 0x000300fadd2ed37d, 0x00097156d549fc2b, 0x0000ad7686ed0d31, 0x00005d713c2953f3, 0x0000c01130ae8caa }}, {{ 0x0000e57c5b8cc8c5, 0x000b65087e9189fa, 0x000c53485dcbf535, 0x000419404db17375, 0x0000410edb213b42 }, { 0x000cf14a112a5ea6, 0x0006bd3f40e3c80d, 0x0000b0c5bbb47bb1, 0x000a038c3b118932, 0x00002d9c468c8d26 }}, {{ 0x0006c8b3e970a581, 0x000a55b556913429, 0x0003fa3be9dd94c6, 0x00015610ae8e0850, 0x00009ceceff70c59 }, { 0x000953c3d70998e4, 0x0001438fb4ee6b40, 0x000b3895091982c7, 0x000476cc6fc5a9ae, 0x000057745cd78df1 }}, {{ 0x00071e305a112a00, 0x000268238dfe7e82, 0x000504996cf1100d, 0x000bdcf2dea417e1, 0x000026436feec265 }, { 0x000396770a6a23bd, 0x000c0fd7253ecbd7, 0x0004dc33ea7bf828, 0x00062b19c2f552e2, 0x00001ac28594c2e3 }}, {{ 0x000b1dac7015ef7f, 0x0009263c27901b4b, 0x000fce7ddf838b5b, 0x000d75b0afd9236d, 0x0000069d82647cb5 }, { 0x000f374bb4fe7c59, 0x000c453a91cf76e1, 0x0002b3e7d3328269, 0x0007376774110a41, 0x00002b0cccd10515 }}, {{ 0x0001616338327868, 0x0007af20d188dab3, 0x0000c35722b72c00, 0x0009bef0fe3968ed, 0x00005947d75b5640 }, { 0x0006a44d86a5f4a0, 0x00047e24f0c8afe3, 0x000fa8462b5372ed, 0x00068ea514caa75f, 0x0000f6f22bba6bd6 }}, {{ 0x000ff17a8fcc8db3, 0x000a8da0333974fb, 0x000d67b586b70a9e, 0x0008146215db516a, 0x000074410c8af154 }, { 0x000c274e88147e8f, 0x000f24e12476da14, 0x0002e79a1af86475, 0x000cebccac1e1661, 0x00006666b278e72d }}, {{ 0x0001da368c16a10b, 0x000ad8d6c2f5226c, 0x00039333461ca008, 0x000230c0914d1b94, 0x0000a4acd35a7009 }, { 0x000b480cfa6c0f39, 0x0004cced5113cf71, 0x00033eec6394bef8, 0x000bd06880670f63, 0x00008997a9636ca9 }}, {{ 0x000953c50eb5331d, 0x00069024147519ad, 0x000b4d5fade16af5, 0x00052cec8d0981ea, 0x0000f785b3ffbbf2 }, { 0x00063ebb7f24f144, 0x0001dccfd590f8f8, 0x000abea80d987872, 0x000fa20cf72e9626, 0x0000721e8be990fd }}, {{ 0x00083e50e54aa3f3, 0x000c4616aca8ee7c, 0x00090f75b27323c6, 0x000bbf80d97d10b3, 0x00005e98ed7591d3 }, { 0x0005f9680c64a8ca, 0x000dffec954b3132, 0x00070b13b7552acc, 0x000af06e0cc2e8f4, 0x0000143469e3b900 }}, {{ 0x000561bf1c36fc6e, 0x000f8094354080b3, 0x000546913f00c25f, 0x000812afa5225bfa, 0x00007cc75ab3c625 }, { 0x000332d9e420107e, 0x0002117ba1514741, 0x00049d1c94e63e5f, 0x0008a4d1edec2f93, 0x00007771c10cbd06 }}, {{ 0x000cf057fdaa6cc2, 0x0000d69df23de05b, 0x000143a2e1a2b66a, 0x000fc772366d17da, 0x00006a8d4733875f }, { 0x000c23b3ee9a963f, 0x00089c5f0b5662c7, 0x000860969b36292f, 0x000952aff25318dd, 0x0000ef7f5b56866d }}, {{ 0x00039af66ebf381e, 0x000ec0a097e4403b, 0x000565ea4ff656a8, 0x000452a26cb3d0a8, 0x0000a7947609a317 }, { 0x000290d33bd0a0a9, 0x0009c88bd475ca8d, 0x0005ede6e4cfd558, 0x00087196ce06b796, 0x00001bfceaea4a09 }}, {{ 0x0003e4fe080af01f, 0x000ad47f34fb0fa1, 0x00080bccad01991b, 0x00083a0e3b4760cc, 0x00004486d52a8b97 }, { 0x00069059367f304a, 0x0006f92fdb05163c, 0x0000459ac07fbc9d, 0x000c299e28c484b1, 0x0000e9d36b72292b }}, {{ 0x000ab74e6a2a524b, 0x000249d586e74e18, 0x000cdd00b61a885b, 0x00049f2db488883a, 0x00009b15259f5d0c }, { 0x000de0781ad6fc39, 0x000f4285e21beb19, 0x000993abcade39ff, 0x000d307c33484518, 0x0000f3708fe8c17c }}, {{ 0x000604437bc3417c, 0x0006c58693807e1b, 0x0006987d894bcc6d, 0x00041df84a386532, 0x00004f10004876ac }, { 0x000a01df0ef92b9e, 0x000ec985ca1823d5, 0x0008a9bc2415bad0, 0x0003cac33b82f7ec, 0x00008c8d609652d6 }}, {{ 0x0005e94efbb5789d, 0x00065f31306583d2, 0x00001d931332b2e9, 0x000f1dec805b10da, 0x00003f4f29f81351 }, { 0x000ede6596524043, 0x00086b7fa3dc26dc, 0x0002c8209e2f37f5, 0x0008351cee0e5fb9, 0x0000f62ae015ad99 }}, {{ 0x00025ef904c10f7c, 0x000a6f6a19935459, 0x0005927778b6116c, 0x0005a468eab01cc3, 0x00007a92aaab72e0 }, { 0x00060897892570ee, 0x000b5cf53aa0b32d, 0x000a9bbc05f115be, 0x00094f47fb27beb5, 0x00009605766eabab }}, {{ 0x000cf6c431cbebca, 0x00082e0d6fbc2acd, 0x0000a469311f571d, 0x00003479c738037a, 0x0000ebc968b789a0 }, { 0x0002ad6eced662ff, 0x000ff7be3ef104a2, 0x000be758e7592a81, 0x0002f053eebdd9a2, 0x0000d738f011f4b1 }}, {{ 0x000c11a2e84862b7, 0x0005cc039cd297dc, 0x000d39ac02f15755, 0x000ad94968ec7e16, 0x0000f7a4858d93c4 }, { 0x0007c422e7b70ed4, 0x000865396ee63809, 0x000536df645adfbb, 0x0003f267d054c865, 0x0000eed4df196b1e }}, {{ 0x000ba62aa6a9ec8b, 0x000ea090c22b5403, 0x000a7c1c3d2e15a3, 0x000c44b932cde42a, 0x000080285f5a46b0 }, { 0x00066c5b9ee54102, 0x000f77bab9ea96a6, 0x00027d49b293cd0a, 0x0000c99d55d03964, 0x000042cd3eeb6797 }}, {{ 0x000a56a7143dc2a2, 0x0003ad98edbd7cc8, 0x00073c76303fbc7d, 0x00024144f4660bb8, 0x0000534e55030be4 }, { 0x000b2524cccf0e8b, 0x00055965726d47f7, 0x00018ff575b2dcee, 0x000a8bf379eed01b, 0x00003984d331077f }}, {{ 0x000539a4fc4c4c2e, 0x0003a3b8f4b002f6, 0x0009dcbb57241ddd, 0x000e75cccc2200d7, 0x000071b64d7d7ded }, { 0x000b7a26a5d05150, 0x000cc14c33c7fcf7, 0x000b4c440b85fe71, 0x000f5a6237eb6799, 0x00004066761e4395 }}, {{ 0x0003ed2c34dbfa56, 0x0009a8d403f46f2f, 0x000226219492ef3d, 0x00037be2f94b8fc4, 0x0000aea3923eaee7 }, { 0x00047ff958e890e9, 0x00097afb639126c8, 0x00005ed54185a48f, 0x000ed4209f7b6be6, 0x0000839d619a4633 }}, {{ 0x0009fb18a0fee18b, 0x000f1f5678a31b0f, 0x000d3f9d9d7f8899, 0x0002e2896d50301a, 0x0000467828ca24c1 }, { 0x000a2f2a98bf1696, 0x00042ebe8758851b, 0x0005a36a8fac4075, 0x000e6fdb71e64e4c, 0x00002450761a46be }}, {{ 0x000106b953c0b0b7, 0x00055bae8053433d, 0x000f6c25dc31bcc8, 0x000283eedc8e7259, 0x000070486fc2230d }, { 0x0009b714490d84cc, 0x000ab5b0eff13a96, 0x000a76a0a4e72ed7, 0x0003240bd242442b, 0x0000e38dc2108bbc }}, {{ 0x000ad0436ab80ab8, 0x0008ef60e2ed7422, 0x00051536312889e3, 0x0004a0b04573f104, 0x00006d3f1bc994e5 }, { 0x0002b773beca9fd2, 0x000d82d431a8121d, 0x000ab5b79e2f23aa, 0x000aa3cb7cd38b3a, 0x0000164fbcfce738 }}, {{ 0x000d927bed2c4843, 0x00057c49b5c1f14c, 0x000970c2633e1e0d, 0x0005bd591c444be1, 0x00007472609e17c1 }, { 0x0007c6a79d00e920, 0x0006516e48c8a348, 0x0001c38dbeccea53, 0x00064d8ec1b7ac81, 0x000001913870f958 }}, {{ 0x0000b9e865afa38c, 0x00016f09b56ddbdb, 0x000bd975348dfe5f, 0x000fa730d1339b5a, 0x0000a2f19f0d61d3 }, { 0x000bafec279d834b, 0x0007f4177bb064e9, 0x00026174b33bb275, 0x000ec1d9a145a281, 0x0000853c8b1d855a }}, {{ 0x0004b8f6ae320ba5, 0x000a7654265aa91f, 0x00030ea60793f5f9, 0x0002e39c7a4b1830, 0x000052a5da5f3864 }, { 0x0008eb65e67a4037, 0x0005ccc971a8a130, 0x000d43a7e7218152, 0x0006c85293f159e5, 0x00000f9da5baca8f }}, {{ 0x0007b514916e3af9, 0x000fc8930b75c3ed, 0x0001bc940801e1b4, 0x0007469bb0bb82fe, 0x0000306f321be91b }, { 0x000a91fcbaa89e73, 0x000277b04497f19d, 0x00093fe8d485032c, 0x00029fbd61b35ed0, 0x0000ab396c946696 }}, {{ 0x00043b4fbd7ee0ab, 0x000a57bd7ab27e14, 0x00051f590bbe1f47, 0x0001bed277c19a55, 0x00004ea5e94be42c }, { 0x00079cdff78fa878, 0x000b6656962c88f7, 0x00045670d0d30682, 0x000e4f44f139da8d, 0x00001bd14a9de58b }}, {{ 0x00003907bb055ec3, 0x0007cddae57c7b7a, 0x00017b5a1d67b643, 0x0000e87a3345342f, 0x00001c62c23c4350 }, { 0x0006a27dca73d570, 0x000a0e1ff2189336, 0x000443af93b0c4da, 0x0001d76eac066b65, 0x00007c9b470b5621 }}, {{ 0x0007ec6e15fb0c4c, 0x000ad93048b37172, 0x000a898c40066ebb, 0x00042d16bbf5a989, 0x0000641d1a6e425b }, { 0x00009c3566d8138b, 0x00078737276e7fc9, 0x0008f93a899b74ba, 0x000ba4e7964086d7, 0x000097a1ea45df74 }}, {{ 0x000ca56513af6eb9, 0x000036b75dd7125f, 0x00068afadd796c99, 0x0007cb29db4c6bc9, 0x0000450348223f4e }, { 0x000cf70def0b74d0, 0x000a181d0e8bd06b, 0x000709c438fb0a64, 0x000dde624384dd31, 0x0000e9a2bfac312d }}, {{ 0x000ec09a48204c79, 0x000886e6628e8c30, 0x0007a749dada16de, 0x000e7d5e207a0d66, 0x000034e09153d2e9 }, { 0x000c7f44552abda4, 0x000994ed83dce467, 0x000d1d53b819438d, 0x00011604c43a6316, 0x00000c57dbe9342c }}, {{ 0x0009b1ddeddfb155, 0x0005c21fbabbe926, 0x000b77812288d335, 0x000d7ab15281850f, 0x0000e27f34f8feb7 }, { 0x000c9f1b87c58c64, 0x0004d8fab1051053, 0x00016bfdb467b764, 0x00004dc09953ced3, 0x000034ba3f40d826 }}, {{ 0x00067e10d16361cc, 0x000d5a14a7eadcb4, 0x00010bb060fe6649, 0x000cc8383928e750, 0x0000a507d1a255d6 }, { 0x000d744bd0c7e26b, 0x000bfc3b955dcf05, 0x000d766199572b61, 0x000958974ba96307, 0x0000c161d1c03e35 }}, {{ 0x000b7e2a947ab5c8, 0x000602aa777899e0, 0x000fc4c1124a57d1, 0x000fab531e20eda8, 0x000078d9b61326d5 }, { 0x00039bad6e2b1553, 0x00011ad19f593cf4, 0x000edadb41af06b6, 0x000180d9c7b1a9e4, 0x0000bec906422f8b }}, {{ 0x0006fb4c2d81211e, 0x0007266e032f1445, 0x000891b7a03ca07c, 0x0008011781db632b, 0x0000932932e1a77c }, { 0x00027d6babb8c904, 0x0002ae1255a03f19, 0x000256ed85caa685, 0x0009fb89761cd6af, 0x00003a067d13fd17 }}, {{ 0x000b89a4e82f20ac, 0x0005be0e90fb21e5, 0x0000601e57b9726e, 0x000acbbb500fd2b8, 0x0000def3cf863f66 }, { 0x000f548f31add03f, 0x0006e3f894407ce5, 0x00040ccdd200e1b3, 0x00036823ba0025b9, 0x000057161113964b }}, {{ 0x00088658197f5e5d, 0x0000e8feac6d1135, 0x000bb5fae45cabee, 0x0008397b9a67e3f9, 0x000027605a7662c0 }, { 0x0005660e1a5eff95, 0x000cf0cf7f06f200, 0x00062500dda83af3, 0x0007a8908dc61021, 0x000035ac8c485b17 }}, {{ 0x0000a886286039e7, 0x00030626d3c46934, 0x0006f744f5c20ad5, 0x000213b6df0e7d62, 0x000063e4a8b99f57 }, { 0x000bf9a358ea18f6, 0x000c4a7bbb38ce0f, 0x0004c1e30a289e84, 0x000b0711fe0404b6, 0x0000cdecdc1fe1a1 }}, {{ 0x000970195f38876c, 0x000fdb028f33398d, 0x000c9978f6062539, 0x00023b2b1b07ec11, 0x0000e90d968debc2 }, { 0x0003e03b335e7e4e, 0x0000ebe0181e6402, 0x00020262f609f432, 0x00074d182f5debd6, 0x0000f8b0b29420ff }}, {{ 0x000447ad7afa3513, 0x00076494fde0c1fc, 0x000e216f3ea60540, 0x000acc86cbf8a1ab, 0x000009a60fde808d }, { 0x0006736b8b4a3189, 0x000213803d0ccf24, 0x00083b271077fea3, 0x000e645cc80acb33, 0x00000d9f85e61323 }}, {{ 0x0007a56d943a749e, 0x000dd60c0432f963, 0x0003a70fd69b9be8, 0x0008acba2ddebe7a, 0x0000b67c71837343 }, { 0x0008b4408a4b9b5b, 0x0002fedf2350d0a8, 0x00057ac6cd104010, 0x0002b01ae13c3f27, 0x000012894baff1f9 }}, {{ 0x000b605ef4a68b33, 0x000b2a35cb026649, 0x0000eb26683a34fd, 0x000f7a23e5d4c0bf, 0x000025f5686f6dff }, { 0x000715b3a144285b, 0x0006702c69645d0f, 0x00097305b3462d92, 0x00066f2c4a115f03, 0x00002d4b3efd98d1 }}, {{ 0x000d8c3079ecf96a, 0x000a048d413213a4, 0x000d72bfbc61a285, 0x0008c1df52035806, 0x0000eb8c40841f70 }, { 0x00042be3c0b0a8c3, 0x00067678d95a8f6a, 0x000d4de5294c6a81, 0x000e6f73fc58c9d7, 0x000028eb6b61151e }}, {{ 0x0001f8fbd7da4886, 0x0007142d43b5eaaa, 0x00063dac9fad46de, 0x000237745054a076, 0x000066d55ce85e38 }, { 0x0000aad9183a3f7e, 0x00002f5d563fccc1, 0x0005e1d5d00ff737, 0x00075facf48ca505, 0x00002d09a02699ed }}, {{ 0x0005475f79a136dd, 0x0009e62b7bdc9534, 0x00021679276438a9, 0x0002811779f0f6ff, 0x00006a65c14a85c4 }, { 0x000d71419bada82b, 0x000fdfa86f702ccb, 0x00045190dd6b9201, 0x000e77dc692e6090, 0x0000c7da1d12ccd1 }}, {{ 0x000831b6ca7da654, 0x0008dcc6028da9ad, 0x0009ea203ea89978, 0x0000343f45352fe1, 0x0000299e73c0a3c2 }, { 0x000d50ba88136cf1, 0x0003d1de350e2c27, 0x0008a0bc297b691a, 0x0000804cbc56240d, 0x0000b08ffae6ef56 }}, {{ 0x000b049ff6e562d0, 0x000c4265a3a2518a, 0x00091b2b9d4cf195, 0x0003b8696cf81779, 0x0000718b68347a7c }, { 0x0000d0bf5e9df0d2, 0x00027b0feb13ec70, 0x00079cbf39ae46dd, 0x00009c4afd5e9711, 0x00000194165fa7fd }}, {{ 0x000d542a16dde633, 0x000fd1f358bcdc04, 0x0008bd491de20858, 0x0005da13a07689e9, 0x00001aaffaa71871 }, { 0x0009749558e9ff03, 0x00090d59ca0a7072, 0x00056151eb0cc4a3, 0x00090fd8cd061fe4, 0x00000ed0be2cc216 }}, {{ 0x000229acb440cbd2, 0x0002a59c1d5d0340, 0x000665b8692c33ea, 0x000362ee6f712e9f, 0x00003d3bf4320945 }, { 0x000d5dbb02d12e1f, 0x000c24cfff0c82e2, 0x00022c68e370cba3, 0x0009e9a8987684b6, 0x0000967e564a19c5 }}, {{ 0x0001f390883520b9, 0x0001a3ae86b173c3, 0x000575ac605bbd0a, 0x000ec5310e8e41ea, 0x00008104ffff9da7 }, { 0x0005cd6ee65978c1, 0x000b0e17829839ea, 0x00039f353f7221c6, 0x00083a0150cf691b, 0x0000faa310dfd765 }}, {{ 0x000fa20deeef2680, 0x0000d7b5f1d23474, 0x0009fd20174b3146, 0x000121e08794645b, 0x000077749c4b1069 }, { 0x000a1c9150ecf76e, 0x00004d8d797770a6, 0x000d55260cd5fea9, 0x000b814797360c91, 0x000033f4db806293 }}, {{ 0x000379ae15e41fc7, 0x0000ca7c35d87949, 0x00076fdd0ccf2ac7, 0x000135bfd042e655, 0x00007cefff827780 }, { 0x000b09f648a49efa, 0x000b462fcc9981ea, 0x0000c21f3e7dc01a, 0x000af6bebaed3d63, 0x0000701de9b6b9b9 }}, }, { /* digit=5 (1,2,..,64)*(2^{35})*G */ {{ 0x000a823a4160c545, 0x000f51222248acc7, 0x000eb7e2a9255142, 0x00038a9281f6ec0e, 0x0000f63c9cc1c2fa }, { 0x000efe9ed3f2c904, 0x0002604e1900a791, 0x000aaaefc6a23190, 0x00095a14acde09d4, 0x00007b2680ab6b58 }}, {{ 0x000c47940a63bdc1, 0x000acbe305406dd9, 0x000f4115854d7ebc, 0x000bf8c8f8eb7dc7, 0x0000eebcc0956bd4 }, { 0x00040deabe2974cf, 0x0008c5d99b307781, 0x00065a6b4bc494d8, 0x0005271e325380c5, 0x00006c75941c35b1 }}, {{ 0x000049d7316af76b, 0x0006567afd32acfd, 0x000a11ad459dd98a, 0x0009f87dad8f0fcc, 0x00002a6cb670db4a }, { 0x00027074910360a8, 0x0007e3d42ab580e7, 0x0000b1869323c43e, 0x000fd66da09411bb, 0x0000931dee156e7f }}, {{ 0x0003c3a8ea6b2c0c, 0x0005526c49a861ec, 0x00051d8b641c7fc2, 0x0006ff017024f3b6, 0x00006af90c54fe5b }, { 0x0006848b57a6af77, 0x000fe2cb103d4c8d, 0x0002bb9428138d50, 0x000a1d94a02bc461, 0x00005196aa6193cf }}, {{ 0x000a9423bc0124a5, 0x0005de6c30fa92bf, 0x000c9fc103c8bc73, 0x0005e719b5a70d96, 0x0000e39716462e3e }, { 0x000d96bc718ee9dd, 0x000e112fe97a5b9f, 0x00087422d4a6a114, 0x0002dab4685da604, 0x0000ff2e0f500dd4 }}, {{ 0x000f0e96b0521716, 0x0006bdb1782269b6, 0x0008b6894ea0436c, 0x000213b53ae34bf7, 0x0000f89e64dfb40d }, { 0x000020f0e5f7aa5e, 0x000a41577884456e, 0x000b89101dc1c7bf, 0x0005074deb3b5688, 0x0000322f52afaf0d }}, {{ 0x0002cfa977b4a1d5, 0x000cbab0976505f7, 0x0002968e854dbe69, 0x0008fd671567f681, 0x00001688d84b98ae }, { 0x000f34f1cd8b8aab, 0x000b3ad8a2373da8, 0x0003ec6f689aa85a, 0x00077f215a8d0d5f, 0x0000c0b67348ce77 }}, {{ 0x00039b66645c58c8, 0x0007a8dbbe5a1a9a, 0x000e8d8b5703704b, 0x000b790268187fd5, 0x000003b8f3f8d5eb }, { 0x000b2f3a4a4db66a, 0x00074ef2d65a8087, 0x000f193430cf1f8c, 0x000a6ec4c4969044, 0x0000c1c8991dfd8f }}, {{ 0x0002864e5048aa8c, 0x000f145300eb294a, 0x000d7415c6444b6a, 0x000f9eea92b2a656, 0x0000f466251b268a }, { 0x0006be862b1eb6e3, 0x0008947db89842e4, 0x00071a89198c63ba, 0x000fc13dc12dfd7d, 0x0000921392892bc1 }}, {{ 0x000b8888bb33c9a0, 0x00038dd0f82b2148, 0x0009657b430acfe7, 0x0000dfe19460c34f, 0x0000b39b6f7347e5 }, { 0x000bf0221449dce2, 0x00055dcc07226779, 0x0008802bed13455f, 0x0001abec610d21be, 0x0000f48269445497 }}, {{ 0x0007c2ae5722977f, 0x000fe1242b48b998, 0x000cc07f923ee912, 0x00063ddfb1bcb665, 0x00006426594d7fc9 }, { 0x0001f5e5985dc788, 0x00029220de367261, 0x00082de9d7899404, 0x000b24c60e7043c6, 0x00006397a224d1f0 }}, {{ 0x000dd04b97f56424, 0x0001d60b7fe7b6e0, 0x000a3239f41aa1f1, 0x000c4a61e7d16189, 0x000064bed27452ed }, { 0x00079b5499dfb43f, 0x000fd9b506db8cc0, 0x000ec79d2cb2ca13, 0x0009706e65cd47aa, 0x00001dff152d73d6 }}, {{ 0x000ad76ee910eedb, 0x0003602c1c24a3b9, 0x0007813ead31dac1, 0x000012f4aca24e56, 0x0000638656568026 }, { 0x0007b4a7bd68d6f7, 0x00028c2538e0ff72, 0x00093e500bf32e6e, 0x00072d8d794f8980, 0x000026a43392b0c9 }}, {{ 0x000aa7cb935a507d, 0x000551ae0ac29416, 0x0004582b4da3a965, 0x0007915d0279b025, 0x00008622b071bf70 }, { 0x00035a70c90666d4, 0x00051800d37c7a50, 0x000730d2e35953b1, 0x0006c1b9213380c3, 0x00008f95b8909dcf }}, {{ 0x000c43c6cd7fe37b, 0x000aadd4ce4f152f, 0x0000fd9bb539417c, 0x0000140141f419a7, 0x00009af0fad64712 }, { 0x0001a9c2a0337ed0, 0x0009591925d6b2de, 0x0002806ea2f81671, 0x0009c46294b37d9d, 0x0000a4de29b6d19c }}, {{ 0x0003fba6baaee763, 0x000548571ba18615, 0x000c7ccd5282a222, 0x0004c589348b22d5, 0x0000c343e640ecd7 }, { 0x000d50cd542a5f8c, 0x000f1f3e5eea7d82, 0x00063b79a4045592, 0x0000f8e05521c879, 0x000038b6e3d1e7a4 }}, {{ 0x000a89dbdc1abdd9, 0x0003cd6c5a3ef169, 0x000d1f7db645ad63, 0x0009fcf1c993eff9, 0x000061650e298230 }, { 0x000c6ab8862e32eb, 0x000b3bf2b892891c, 0x000090a9ec4f324e, 0x000cab92153902b2, 0x000009cc8b82cba9 }}, {{ 0x00084b1fe4ac70cd, 0x000d433f74cff170, 0x0003e46cf40d687a, 0x000f58eee240aaa0, 0x00005873e1125bc2 }, { 0x000ada9f07b6f730, 0x0002d16d081f6a60, 0x0008e41d8d8849a6, 0x000a77a2235304fe, 0x0000eb9e1fd7cdf3 }}, {{ 0x0001bd2ee144dc4b, 0x000cb78968a61446, 0x000ba5f5eb3d6205, 0x000a5b0e154c1f77, 0x00002bb9da949d12 }, { 0x0001db4ebe3697d8, 0x000c9e9781105fc0, 0x000f79543fc2bbc2, 0x00067b99b9cf2971, 0x00002c5b8ddd5497 }}, {{ 0x00065daedf9277bf, 0x0007f23b40df1cf8, 0x00030e8bc2d4eb23, 0x000253a215933737, 0x000043cb71cd34d4 }, { 0x0009699f551d880e, 0x000fdd3832791254, 0x000eeb833b56212e, 0x000ed4eafbc3d5b9, 0x00005766025c2941 }}, {{ 0x00074ce7196c4a18, 0x00058e1d4a7a15b6, 0x000a835fa0cdac0d, 0x000e71bea08f3587, 0x0000153a1d49c1da }, { 0x0001ea48a86150df, 0x000b935088b3e0e6, 0x0008fb22fef91a3c, 0x00023c4c47a0356a, 0x0000149d050cb103 }}, {{ 0x000a6b2421ccb0e5, 0x00092580f3e48342, 0x0001ed3e8ba96390, 0x000e982b3fdbb21c, 0x0000ca17b5625d62 }, { 0x0004efa84d6f03e8, 0x0003f944af02291c, 0x000565685cb0f5ba, 0x000eca7d7ade465c, 0x0000883813fcec37 }}, {{ 0x00007ae2719b9b5b, 0x000c02a442b0f5c9, 0x00073f1e94c5061d, 0x0004db316b748e31, 0x000031983bdb4e33 }, { 0x0001a9c0d712eeb4, 0x0009f4b0c9bcddd6, 0x0003d8040daccc42, 0x00037d06a043fb05, 0x00006a4a48036cc5 }}, {{ 0x000ac71e23fc88f2, 0x0008e46477184276, 0x000b03bbf167de2b, 0x000112147df17ff9, 0x0000d1d24f52c4e8 }, { 0x0008aa8296dcbae1, 0x000d8fd1defd73c7, 0x000743117c2eec10, 0x000c417ea1984065, 0x0000c69deb7b1ec1 }}, {{ 0x000974f73d3cbc56, 0x00061f0a3738c290, 0x000ab2bd5966671d, 0x000a1f6af0a2f235, 0x0000b7892c65b907 }, { 0x0006060d7d7242b0, 0x0000ba35ba2f5a80, 0x000364edf2e9613b, 0x000948e2c542c6e6, 0x0000bb93163dd653 }}, {{ 0x00001b3ad0550c5c, 0x00095c2065fef4a2, 0x000ddd40581378b2, 0x00064275077e60f7, 0x0000900cb66b1fd1 }, { 0x000fc0738fd99566, 0x0005ca10334fc145, 0x0008d484df668635, 0x000cfca828a9a9e0, 0x000018f7ad9443bd }}, {{ 0x000efb14b1a6205e, 0x000c64d17d2d8c38, 0x0004e187f1d2d25c, 0x000d6dce5effc634, 0x0000567500e02c3e }, { 0x000a688b252296a0, 0x0009eee2245ae7aa, 0x000e3fa966194c20, 0x000197f5dbca4061, 0x0000512da556f80e }}, {{ 0x000e48482682519c, 0x000f271bd3502bad, 0x0003d6962d79e50e, 0x0000f89e54ef41f2, 0x000065549732387b }, { 0x0001a43c79f96f00, 0x0008d9865cc22950, 0x00016c6aa32825aa, 0x000845fc7428a377, 0x00004147615b28b4 }}, {{ 0x0002125ed3349bd9, 0x00097590fd3659a3, 0x000c896ccec77bc1, 0x0005dabd38927f30, 0x00001842ad4bd958 }, { 0x000b61fc67c66d39, 0x000f4ad3d4142055, 0x00028898864234e9, 0x0009d1c8173000ef, 0x00000cb713a5822a }}, {{ 0x000568faf8627d03, 0x0008a5b7cae440c3, 0x00010ac27a395ea8, 0x00016202121c08b4, 0x0000a8232e915d7c }, { 0x00081b20b280f35d, 0x00001999ecf965b6, 0x000880fc06bcf0be, 0x000199ce2f14ed24, 0x000030dfcd06ef01 }}, {{ 0x000461905346ffbc, 0x000b78dc6c011203, 0x00037a0f508825de, 0x000b0258c71db081, 0x00003aa89a31f12d }, { 0x00074bf462da8bad, 0x000afeadb2a3b15d, 0x000e04007c10a5d5, 0x0004726670a49a19, 0x00000c115b3d65b5 }}, {{ 0x0005910a01f9dd2f, 0x0003e65533ef2177, 0x00044e3924858ec2, 0x0004e12677158c7e, 0x0000817fb332f9e2 }, { 0x0009f8be4c5579ed, 0x000d207cf88577d2, 0x0000ba656c829dbc, 0x0002850852224525, 0x0000a45a5a5d4127 }}, {{ 0x0000f984312881bf, 0x000fba7076fe12bc, 0x000aed1bb3c8b51c, 0x0003c3c463f2400c, 0x00007182316ff6ef }, { 0x00040b796b1fe386, 0x00067e10170911db, 0x000a80c9381435ad, 0x0004332d27562f5b, 0x0000c44dd22a86f8 }}, {{ 0x0008f3a69b2e986f, 0x00082973467ba92a, 0x000b4e15ae15a7c3, 0x000e0825d8c9b46d, 0x0000fc1d6d6957df }, { 0x000e56dec238f6a0, 0x000c60f61e4ce9b9, 0x0002d04f9a4a094b, 0x000a1c416bf06aab, 0x0000e7611030ccb3 }}, {{ 0x000bb61ceb16d2d4, 0x00072f49a9898d9a, 0x000aaa7db1043ba9, 0x000cb6e97d799e77, 0x00001e9007832b66 }, { 0x0003918e6dab135c, 0x0008ca7f778443cd, 0x0000564ca17913cf, 0x000f05f6f3bb42bf, 0x000063a36f543384 }}, {{ 0x000b7faa84dc37b4, 0x0007e719a5103f11, 0x0006d98f01816fb6, 0x000a50d195243efc, 0x00008d79992c468e }, { 0x000fc83cb87ebe8b, 0x00046bd6dfcd08ca, 0x000d5c1beb25b405, 0x00067b183129dec4, 0x0000b767a1b5e39e }}, {{ 0x00044f601bff0a52, 0x0000e882fa6be76c, 0x000a4ed96be286e1, 0x000573bda892585f, 0x000089fc0fc5d1d0 }, { 0x00076f26dd1cd1c7, 0x000b60b2be1fdfdc, 0x000c59a459115f23, 0x000e3caa8a833bd2, 0x000032e8b64f5910 }}, {{ 0x000c72c01889f6f7, 0x000ed7d3fdf5a517, 0x0002d9570a979390, 0x000e9616e7afb5f9, 0x0000219f402c76ff }, { 0x00053985e9b35d2b, 0x0007ffb99b5c3dc4, 0x000cf30b28c6f648, 0x0000ab982a48a0f1, 0x000083df9c5cf403 }}, {{ 0x0008892c68df5eaf, 0x000196001b25dd8c, 0x0008330050216af6, 0x0004a5dd90dd37f4, 0x000075766028a72f }, { 0x000015de22cdfad4, 0x0001bc0ef514ca5f, 0x0008f716c0c41d51, 0x000c9395f478eb67, 0x00006c79af16b80d }}, {{ 0x0009f0694bcc6e29, 0x00024e0eaf4b8a5d, 0x000971d5a4e6ddfc, 0x00063357068cfd9c, 0x0000e859080ab5b3 }, { 0x0003e274e3cfa9ed, 0x000ddd5ba708bcd2, 0x000937d6e7472719, 0x00016b88f5cd2ba6, 0x00005455f039ef64 }}, {{ 0x000072e8b9f6e62c, 0x0003d2ddfd20a4a9, 0x0002f1337d994ddd, 0x000ba497d091c5fd, 0x0000a3d27ef9d712 }, { 0x000fccd127ddda11, 0x000fdb080848beca, 0x0009ca3065a453f9, 0x0001332f595bd480, 0x0000e62fb4bc3988 }}, {{ 0x000f46369ed3f8aa, 0x0001e2d1cc1884bc, 0x00008e011d1618d7, 0x000955f9fc85ac20, 0x00002ecc593e0d91 }, { 0x0008bfe3c7e56fef, 0x000e149506467ea2, 0x00020f0e0904fd77, 0x00010253a481b63a, 0x00004ffcd9b71108 }}, {{ 0x0002f7b360a494a2, 0x0006e090643d84a3, 0x000878d95ce09757, 0x000a592d6885f366, 0x00001f4c9f31cc53 }, { 0x000d2bd553f44765, 0x0001337dad1fe7ac, 0x00088715cb5cfc25, 0x0008d105060a157a, 0x00007397650095ee }}, {{ 0x00076feec510b8c5, 0x000332f33e24a0b2, 0x000fcae661b4ee9f, 0x000a693259cbee23, 0x000026ff7e0a62da }, { 0x0006368fffd036a1, 0x0008ac6da10032b9, 0x000d5ab09a54017f, 0x000ea46ba718351d, 0x00008ccd45317653 }}, {{ 0x000c8455fd5923e1, 0x0004c26150a49e46, 0x0005d2801a6da7aa, 0x0008db5d00c28b63, 0x000079a775e548ff }, { 0x00039639e7b06e8c, 0x000fd5f2d71867e2, 0x000bca63b9a5389d, 0x0008860045c0be31, 0x000038b70ff37728 }}, {{ 0x0008d12af80f55bd, 0x00096159c7c4c6b6, 0x00006e6f6fffc941, 0x0001b75fb603aa3c, 0x0000305f59cf13f1 }, { 0x00010c71d2070171, 0x00096e7bf5d92796, 0x000549ce02fcb704, 0x0007d1bcb9aa5005, 0x0000308e0578f9b3 }}, {{ 0x000938f757b46a0c, 0x000d5a75aa07093f, 0x000aae24ad24e9c4, 0x0007d4801ca84004, 0x0000e8c27e4df989 }, { 0x00028446eb3f9ed5, 0x000a11800a43421b, 0x0001553831dd567a, 0x000783d7639a2536, 0x0000f2b4a9ff1eca }}, {{ 0x00086d90b771416f, 0x00012bfe3b6a6611, 0x000dce64e93fa706, 0x0005d47627751cb1, 0x00005f51d3741f54 }, { 0x0004fb8c61a5d90b, 0x000abc1dfb4f754b, 0x000a762c757a6872, 0x0007b4b4d5c5cf56, 0x000074b63f62f079 }}, {{ 0x0004d9a14957069f, 0x000f73033ff98c71, 0x000aba3dd553a17d, 0x000f7390a9619fff, 0x0000ad3a3609acc4 }, { 0x00013dbda876d927, 0x0009c606f6df9ea2, 0x000d00515a423c7b, 0x000120d80dbcf770, 0x0000ce7619212003 }}, {{ 0x00051b92e197fca7, 0x000790b29fc81b30, 0x000f1201f4e0144f, 0x00085039eebc3e09, 0x0000dc245aa94e7c }, { 0x00064b685717ec74, 0x0001ee9ecb5537f9, 0x000b92c10c2cc7a3, 0x000f23c1644b1b2c, 0x00008328b2510312 }}, {{ 0x0007a54f50c83a40, 0x0005d99cec036235, 0x0005978d229986db, 0x000b408490553222, 0x00005422c6af52fd }, { 0x000d092808697dfe, 0x000441d9598b3525, 0x000c0a3802abd4af, 0x00045ab12e865a49, 0x000065df0e601cb3 }}, {{ 0x0009d129392f3324, 0x00035084088567a3, 0x000de550212844c1, 0x000bd9d3deb6b280, 0x0000b981fcd6fb9b }, { 0x0001e32d5d00ce68, 0x000d25ebc6edfb49, 0x00016c69f3b1b20d, 0x000b846727485b1b, 0x0000e475193ea3e0 }}, {{ 0x0006e21e7dd420a9, 0x000cbd74be59224c, 0x000baa8b377599d4, 0x000b64433ebc88cc, 0x00008d34017152f6 }, { 0x000ec23629ccb29a, 0x000ea0e5bcc36bb3, 0x000e3ee5193f6012, 0x0009ef9a89292445, 0x00003d19d936f781 }}, {{ 0x000e29493df08894, 0x0001a85b134defa9, 0x000f7d898b37d761, 0x000db2c0d6073b1c, 0x0000020c0cac2037 }, { 0x00014b0d0b49b08d, 0x00090ea4e9acf4f7, 0x000833c2ab82797a, 0x0002a046c3e1f01c, 0x00004988c2f0debb }}, {{ 0x000ee06e882c17f3, 0x000a0fc9920cb5e5, 0x000733e735241fbc, 0x000d49f355b44b1f, 0x0000db6fdef70b90 }, { 0x00050566058761ad, 0x000d473da621607b, 0x000be4f06c8b479d, 0x0009587ac2bb03e4, 0x000036fba157651f }}, {{ 0x0008a673a256cc00, 0x000920ce079afee3, 0x00002ee30f7d0279, 0x0007e5ae5686e17a, 0x0000e8778c4b4660 }, { 0x00015ec10c65e1bb, 0x00006f283141c954, 0x000ecd38237a573b, 0x0000441783b2ecf4, 0x000086f1bda28a0f }}, {{ 0x0007bf22ad35869a, 0x000aa19805033800, 0x000acb5590e4df9c, 0x0004452ae513d917, 0x0000b8de7ca6a12e }, { 0x0001fa0bdb4ffa7c, 0x0006ca1e4306839f, 0x00016bddf2cf9767, 0x000ccfcf11b3be96, 0x0000d0ade7990324 }}, {{ 0x000b1c1f39afd405, 0x00055316ec3f510d, 0x0003f77be53bd54c, 0x0005ce6fd2c7e4a1, 0x00007db2f3ff86bf }, { 0x000930967a574854, 0x000c6755dce364a2, 0x000bdc5ec569a6e0, 0x000b64f8cb7b22a3, 0x0000915aea8087e0 }}, {{ 0x0001bd8b5ca9eac1, 0x00048de0c061c658, 0x000c6c0961e7de05, 0x000c4f0ebcb014aa, 0x0000e471ea525791 }, { 0x0004753e714b1b3f, 0x000797ef01a17aff, 0x0003f29ac7c9d1bf, 0x000e1429321f37ac, 0x0000ccb1125704f7 }}, {{ 0x0004fb0c0cc4be26, 0x000535ea15b0a44b, 0x0006d45d9d4b3d51, 0x000f84fb58f37c8d, 0x0000f6737b028edf }, { 0x000bc5118d042dee, 0x000f839a7ff1f2e5, 0x000305d1036ee967, 0x0004363ab9880f5a, 0x000068871fdb7590 }}, {{ 0x0004ddb6540d8771, 0x000af554c20cea5a, 0x000d6fe72046cb52, 0x000a5e89bcac2776, 0x0000a43574dd6d54 }, { 0x0005542e3d637e0e, 0x000e3511b4941b44, 0x000429a7774ac8d1, 0x0000537e0e1ff19b, 0x000001532d232661 }}, {{ 0x0004dcf4218a8c26, 0x000a591349f7aed5, 0x00003aed8fff670b, 0x0001ed0d83b2b5a0, 0x0000d7b1c690c699 }, { 0x0007a54456147aa0, 0x000a30727d6561e7, 0x000459d06d8bf726, 0x00005ddb5879d5ee, 0x0000236499921d85 }}, {{ 0x0006a53ca0e071a9, 0x00056130105c0720, 0x000f873541040651, 0x000bb8cc118f7a99, 0x00002325fc847f2d }, { 0x0006bd173faf618c, 0x000401ef1aa1d9e1, 0x000433b89aa8fac0, 0x0005d13dc3241433, 0x000099c31187e85f }}, {{ 0x0006aebf577abd9d, 0x00015452133ffd9d, 0x0000ac605ac980fc, 0x000e4582a39a8b2f, 0x00004eec5aa7265a }, { 0x000045d5cf88aa51, 0x00029cb76ccdac60, 0x000c15412957a97b, 0x000342cd1af4d36e, 0x0000e6170f039470 }}, }, { /* digit=6 (1,2,..,64)*(2^{42})*G */ {{ 0x0008c8bf5c4dddf3, 0x000e274c005979da, 0x0001c17823f45915, 0x00004f9f9c2072b4, 0x0000aaa1baf4fa40 }, { 0x0001cb9e28458fbd, 0x0002855114df14a7, 0x000d8bfa4e43521f, 0x000189718d4374a4, 0x0000a04910e166e7 }}, {{ 0x00032caa306d36d2, 0x0007e7903605c397, 0x000e2e161f3c1bd9, 0x0005b6484f0843d9, 0x0000c3ed7e7103a9 }, { 0x0002e9423a811470, 0x000527061160170e, 0x000b6096786931d4, 0x000d933acc32788c, 0x000040d7f8af5425 }}, {{ 0x000fa20877d18f60, 0x000739b0260e52a4, 0x000c40c32aad97d8, 0x0003b1954d42585c, 0x00002a8f892d8d50 }, { 0x0002278164a77a97, 0x00058f8e34a0bbeb, 0x000bd2cf6dffb947, 0x00034ed8356b0040, 0x0000781e1140c00a }}, {{ 0x0001682c10b4b42c, 0x00049455922ac1c3, 0x000c73c31352d93e, 0x0002a2bc4a7b3ef5, 0x00009c11c3b203bd }, { 0x000c092172b4577e, 0x000a6f04bd55d319, 0x00057bacfaff1310, 0x0004d8a9db6d1c08, 0x0000b14a2965910e }}, {{ 0x0004577870abf0ac, 0x000415bc00cc638c, 0x000a9cd01752318c, 0x000474cd61a2015e, 0x00001d16278617be }, { 0x00098cd105a45700, 0x0004cce2c51211a6, 0x0001bb3533930fa7, 0x00036b5e5ad9b10b, 0x0000c8cba2a94a2e }}, {{ 0x00023c2d425da318, 0x0001507e91b536de, 0x0001bc7ddc93f16e, 0x000d9216fceb982f, 0x000065b77c65e9bb }, { 0x000b019211c4463a, 0x0001dd93f330d370, 0x00016e0efbd983c6, 0x000d362e5b3a4c8a, 0x0000e6296830cd06 }}, {{ 0x00025fbe30039a0d, 0x0009992840bb3366, 0x000c440a3c4b2158, 0x0002fb6007c353bd, 0x0000477b5b25ccdb }, { 0x00082dd27d9f45bb, 0x000fb1adbc173281, 0x000f912383a4036b, 0x000db4446008965b, 0x000099d080f1bc26 }}, {{ 0x000910b95bc8d4b3, 0x0009d35ea6c39976, 0x000a5950529391f9, 0x000ac2a3954259aa, 0x0000954edcb4e373 }, { 0x000982812f18224f, 0x000a61043e09aee6, 0x000f3de4d536e4c0, 0x000508c61ced56c9, 0x000097bf82337dc0 }}, {{ 0x000ba2f548cb64d1, 0x00040c6ce8009982, 0x00028d606b905e59, 0x000e6049072bb175, 0x000008cbdb0d4e8e }, { 0x000f7d4aa9ad99b8, 0x00036bbe490ebe0c, 0x000cb030c716d24b, 0x0006a023712a0a4c, 0x0000814fb43cd83b }}, {{ 0x00007b3c44361615, 0x00056f43fd5684c4, 0x000f3fbace5d5c99, 0x0003e55822b26eec, 0x000042b330e7ebca }, { 0x00033f9344702a99, 0x0004cfe249c82ba0, 0x00072123e10816a0, 0x00066c9729e0faec, 0x000059f4e057a424 }}, {{ 0x000fee4cf4b36856, 0x0005ad18be82e84d, 0x000d9a69e2fa6af6, 0x00080cbfa89967f0, 0x0000ae907090e0f3 }, { 0x000caf68098cfd0f, 0x0005a65b493c465c, 0x000ba986582707f3, 0x000f34f9f638b9a1, 0x00002e36b41f5ad9 }}, {{ 0x000fc9cdf0a602a7, 0x0000f90768fccfce, 0x000cc86be572242c, 0x000fb55cef402d37, 0x00007fc53399e03c }, { 0x00038fa2f84181fd, 0x0002e72d1669a8bc, 0x000b93e529c4e96f, 0x000b28a0e33c536b, 0x0000c1aea47311b9 }}, {{ 0x000d9775dc6e01cc, 0x000242bbf81f3f5e, 0x000dc1e6cfa506c4, 0x0003a88ae0525a5a, 0x0000a1093d00ddd5 }, { 0x00031ec1f450f0af, 0x000c48ac0edb37d9, 0x000dd3ad5d5d822f, 0x0006f5e7625fdb6e, 0x00006a6a380a22bf }}, {{ 0x00008d930a7b99e6, 0x000376219ee43f1f, 0x000d6ff50a8cea27, 0x000b200e85cd57c3, 0x0000c75d78e4991c }, { 0x000037762700e77d, 0x000215bc016e4eae, 0x0008319cc70493d5, 0x000889455d391683, 0x00003ba91c61b072 }}, {{ 0x00025cc3dbf43b85, 0x00044ecaa80ba596, 0x000a05f6ca758ac6, 0x00045a3af3083411, 0x00002728e23215f4 }, { 0x000579c8e5f5af02, 0x000646c01ac3107f, 0x0006df8bb1de094a, 0x0000f5bf7b2a8d57, 0x000009b1279bb39d }}, {{ 0x000e413c023b543e, 0x000ff931341ed7a4, 0x000c597461477da5, 0x0006486a44223272, 0x0000e62ade1b4548 }, { 0x00073540e59ce025, 0x0006c27e17e44ceb, 0x00047c7e6d15d0b9, 0x000ca71caee86bf7, 0x000062dc3b140088 }}, {{ 0x000308c289f47083, 0x0009a7b1b4a158cc, 0x000d64d9e0df3e0f, 0x000696e97e571c99, 0x000037723337361c }, { 0x000efbce6ccabf4d, 0x00050d3eb7958f24, 0x000be10cab44dc30, 0x0001fb936a7226df, 0x000059e89431f5b4 }}, {{ 0x00050d86fc79732f, 0x000fb058d6990216, 0x00091217dfe6fc85, 0x000a7a33a586d4c7, 0x0000a84bf24df4fc }, { 0x0004cefe9970cdc2, 0x0001257842ba251a, 0x00059d544a9a0981, 0x000dd14576b65e3e, 0x0000027b14071dc0 }}, {{ 0x000c30477ad22c94, 0x00046909f47befbc, 0x000a7500e598e35b, 0x000c53afe6562e9f, 0x000070ac8e36df1d }, { 0x000c834e7cd5fa4f, 0x000d5610b0ffd3dd, 0x000a7eb20ad9cb68, 0x0002a9d24a1f16f3, 0x0000a6548b8dd66c }}, {{ 0x000bd5ca4b43dca6, 0x000b875b2c69dbcc, 0x000837ee1021381f, 0x000b45c713aa77a2, 0x0000a05614cbf186 }, { 0x0006c5c5b213f9f3, 0x00065076db476cb9, 0x0001c871dd6ccdd0, 0x000210116fde15d6, 0x00006771cf226ee0 }}, {{ 0x000f2bc1c174c5bf, 0x00084b7eb4ceb9be, 0x000f5f4b7558a096, 0x0009784af2e99300, 0x000032a2c38518f2 }, { 0x0000f8a74351233e, 0x0000d7b9342f6b2e, 0x00019b95caad4566, 0x000fc00fc201eadf, 0x0000476372345bf8 }}, {{ 0x00015f9c975edbc2, 0x00082b6b3eba40cc, 0x0009006244398c21, 0x000c18e5ef9739f2, 0x0000d49e0d6c8302 }, { 0x000ec5b26dc91097, 0x000db8583afbe332, 0x000ed62c2e2492d3, 0x0000a0611a3b6d6a, 0x00004081b00b4bac }}, {{ 0x00088d1c341332d0, 0x00024d902f6fb8d2, 0x00016e040530d834, 0x000bc60004063c56, 0x000024d616048d6d }, { 0x0008547775093d38, 0x00030d607806fd8f, 0x000453677d9adf3f, 0x000502e27b2f7f9d, 0x0000af367fefc5a3 }}, {{ 0x0001dde5dfbb6e3a, 0x000b56c872b4a606, 0x0003e4356c3c10e2, 0x000cfdbd1ab2a34a, 0x0000f1935615b0dc }, { 0x000bfd9fd4818329, 0x000cd219f2275f33, 0x0006091fe9776294, 0x0002d94aa0750c8b, 0x000091bb35d3e4f7 }}, {{ 0x0001dc0dbedb662a, 0x0001430ee9120b67, 0x0002b1c86680159b, 0x0006b239e2b51af9, 0x0000f154211bef6d }, { 0x000650c83c8fe6f4, 0x0006ed20180cca4c, 0x0006fd05c1270162, 0x00094d0441ae6067, 0x0000b656885374b3 }}, {{ 0x000c2c8d4a51bcd4, 0x000f3ddfe7ccfc4a, 0x000c6f660ffdd205, 0x000bb6833f925c89, 0x0000a3e9f13e00b4 }, { 0x0007ece5fa9b1c9a, 0x0001a07b807bba06, 0x000d0212a9406024, 0x000d2caa49d1e362, 0x0000acd66e4a8730 }}, {{ 0x0005a83685cf0044, 0x000659b739f10e3a, 0x000959aa229f9a00, 0x000e28c41c3341ca, 0x0000631770b3a0da }, { 0x000031413543d5f2, 0x0001a819d7de3cd3, 0x0005f0318e67af71, 0x0003afbb0edf0258, 0x0000e407d9d3c57c }}, {{ 0x0009529ca84f2105, 0x000db2adb22b94b8, 0x0009189807b37871, 0x000fd1763993d8ae, 0x000032507bd52b7d }, { 0x0006d1b1faa44f66, 0x0007daae572a2530, 0x0007fbd06d00887f, 0x000f39d58e02b643, 0x0000ff4486cf7424 }}, {{ 0x00026e4489446194, 0x000d932c47447335, 0x0000e53159ab1422, 0x000ad62ca40517c7, 0x0000c82158b4d5ce }, { 0x000eb5da0a8b9559, 0x00064177ee4a9765, 0x0003335d89c6f8d2, 0x000d487411d9dc91, 0x00005c05b1cb2924 }}, {{ 0x000bea4094530df8, 0x00044b1197b994f7, 0x0004ac59aa54c901, 0x000fb86a53c95a6c, 0x0000fb4e8ab73552 }, { 0x00098a15acd05a20, 0x000ff734db378f9b, 0x000029f161ffe433, 0x000ca8d4670025b0, 0x000031ab0dd33ade }}, {{ 0x0002618905cfd82c, 0x0000cba2743b0043, 0x000700e28ce86b04, 0x0008aa45ab1c7f4f, 0x0000bc87ba82894e }, { 0x00094df65f20b8d8, 0x00033b5a23a0f46b, 0x000ab0b39b2d0f04, 0x000bb67945bc971d, 0x000089df6cbaeb93 }}, {{ 0x000977faf2fd74af, 0x00010abaf95894c5, 0x0006cdf3274ead88, 0x00068f58b7b9bdc0, 0x0000d28ef6376f5e }, { 0x000d37fa9f638299, 0x000a9ef052c4b5b7, 0x0000893d97515b4d, 0x0006fb5c79fe87f7, 0x0000baaee7122abf }}, {{ 0x0002ca17164dce09, 0x0007b1a15562627c, 0x0002ff79991dd942, 0x000f87d092c01a61, 0x00000ba8174e3fdd }, { 0x000ff6218fe602a4, 0x000c82d3eb81d82a, 0x0009df77cfaee393, 0x00070103bc02abf4, 0x00003fadbfce47a9 }}, {{ 0x0006755712b47088, 0x000ea6c8d55b9d21, 0x0009837468e85634, 0x000495f2adc0adbe, 0x0000242e92858a3b }, { 0x00077f3fc7d01a76, 0x0008384f26847f99, 0x00074833ccf00d71, 0x00057799cbcb8e38, 0x000006fa9868df81 }}, {{ 0x000ac30885fb7702, 0x000ad2bf4babda01, 0x000ddc4e340815f7, 0x00067f326feab68b, 0x000088b297e9debc }, { 0x00080e110807e7ff, 0x0006f7b40142d9d3, 0x0002f8840b031472, 0x000b917a3839b560, 0x00007518cceff22e }}, {{ 0x000356d404f08cea, 0x00000d858854be16, 0x000e687e009888b9, 0x0009cd8ef4111c12, 0x0000fa7a19c7e749 }, { 0x000abe5cc63d28f8, 0x000728f594d320e9, 0x000d5b93700c61e4, 0x00066e5e40989316, 0x0000820e9cacb3d2 }}, {{ 0x00086e2220dbc255, 0x0000bfb9723f6711, 0x000d66cf371bf433, 0x000f7b19621b2a12, 0x0000a5a81f4bb948 }, { 0x000435c651e5363c, 0x00028e088312c29f, 0x000823a6b1008cf9, 0x0004fb28994282a9, 0x0000f15346f16d75 }}, {{ 0x0000179a7dfec12f, 0x000e63943b3a50bb, 0x000b6a3c553ecb3d, 0x000ef96b77132130, 0x000049806974e5f8 }, { 0x0002dd6225d0701e, 0x00046b3c85f455b2, 0x00086c909e3c4260, 0x00005b8d94725932, 0x0000eda3e114e5e8 }}, {{ 0x0008515b8d05849c, 0x000678eb9c3bd6dd, 0x00062368cc3bb0d3, 0x000de285d00cdb0d, 0x000009399b53aa0a }, { 0x0000a8dafe0d5d78, 0x000f19e8cbb5ecf2, 0x0008a55ffcdabe31, 0x000e088db8c4347f, 0x00001718c6220cad }}, {{ 0x00040e94e3de442a, 0x000ea8045ee2f40e, 0x000e5d5ccbebdf33, 0x000057ec475e354a, 0x000019d840edbdaf }, { 0x000a9e01bfa34f38, 0x0006d9f62accd765, 0x000a31d826781a00, 0x0003cef7b05cf466, 0x0000fffe5d10d9a1 }}, {{ 0x000800bf0a44ff12, 0x0006598326aad8d2, 0x00049b9638dd5846, 0x00054d092bdef495, 0x0000f18cb0c7987d }, { 0x000e5e7f141dfe5e, 0x0000f3144438fd49, 0x0002bfc720860444, 0x000f80464ef23392, 0x0000bec1282f27e5 }}, {{ 0x0002b639eaff99d6, 0x000e16c5fcc1aba9, 0x0007c6ff860d56c4, 0x0001cfdfaea63254, 0x000005c26b5c9cab }, { 0x0003b90f531f7c6d, 0x0007a82953b135c8, 0x000dbe99599be78a, 0x0009207697308912, 0x0000c7f561f073e9 }}, {{ 0x000f18cdffd1566d, 0x00046d0244975b3f, 0x0007127d8f7275fa, 0x000375a51f3a4435, 0x0000eee9da0674cb }, { 0x00063c9f3d509320, 0x00018332028e2472, 0x0002cd831d3c736e, 0x000f4ea8496e280e, 0x00008f205a98807f }}, {{ 0x0005a0beee1cf41a, 0x000fbb32d2ce8114, 0x0002b2885e3319c9, 0x000abb5db846dc0c, 0x000088344d69dd5b }, { 0x000cf49ef219e334, 0x0006b0796d69af13, 0x00081ca617ead2ab, 0x000ffac9f31a7c5b, 0x00003db05bdafddf }}, {{ 0x0001e5f7c08d641d, 0x0002ff3086cff9bc, 0x000077bd3e4ede7f, 0x0005ba01d88dbd49, 0x000011ea14de0b80 }, { 0x000c2b9818dff733, 0x0007f1428819d98c, 0x000baebf05b22550, 0x0002635c8c770dd9, 0x0000c0c2bc6fae24 }}, {{ 0x00049dd198ff7e19, 0x000a376fe86c6072, 0x00072b8cc8fc8049, 0x000cf92636b7b933, 0x000056f429238ed1 }, { 0x0003d2fe1f767829, 0x0003c84a981a2029, 0x0007a6b6356871bd, 0x000e449093531dd1, 0x000078fe864a7151 }}, {{ 0x000649cddbdcf87f, 0x00040e2ec6d6b975, 0x000466c0d802a52d, 0x0007f205f9cf6d6f, 0x0000cf17c30aef77 }, { 0x000497381a72d1fc, 0x00039793f26ce5a8, 0x0001d0780b03bf41, 0x000e6506fc289a10, 0x0000f143d893c000 }}, {{ 0x00064e359de41d5c, 0x000f9e6f2606a828, 0x00010aa4c5b9d100, 0x00087877ce25f706, 0x0000a40abe928ccd }, { 0x000056538d0f8dac, 0x000bf187ce573162, 0x00001a405eb03810, 0x00063c1f72cab250, 0x000042dc7ff0d57f }}, {{ 0x000620742019e130, 0x000565ef15d31016, 0x0009fb94dfb78dfe, 0x000f0129480c5533, 0x0000f5ea2ed57734 }, { 0x0005d06cf408388d, 0x0004cc4edc454181, 0x000eabfbdda91999, 0x0008bd5f0005b859, 0x0000bbd16a163c99 }}, {{ 0x000378dfaf3e1b18, 0x0000cee3484be472, 0x00062693b0806164, 0x000f0ac532ff33e9, 0x00008a1b602ca81b }, { 0x000e287f8b8af0ea, 0x00036ec856720f22, 0x000b6850f3059c33, 0x000992b582ad9d95, 0x0000342dec973aeb }}, {{ 0x000a1efa102f0077, 0x000fcd0990cecaa7, 0x0000ed3e46704a67, 0x000f05684ade55f8, 0x000011db276b92f2 }, { 0x0005cbba4dc5488d, 0x000f720037cc0618, 0x0000500883c5313c, 0x000d8fa10682e05f, 0x00004999403c4661 }}, {{ 0x000f5f5dc0118781, 0x00016297a3cd22af, 0x000b4b0325d760e8, 0x000a9e4ed9f8cd5d, 0x00009329e15df9b0 }, { 0x0003608bc8757f53, 0x00091b5654a446d2, 0x000f4411cbf24c65, 0x000f71756d1a9496, 0x000012b5a681cc68 }}, {{ 0x00073e00f8daf702, 0x00020d76688c4d4f, 0x00010ff939c43bae, 0x00037f8a39d6b428, 0x00007889e808b3d9 }, { 0x00072755fb51d00c, 0x00053ec49421c3e1, 0x000b26a7d07ce447, 0x00050e49fc4e44f9, 0x0000cab187f97020 }}, {{ 0x0003ecaa12dc8429, 0x0007457446139cc3, 0x00022bf3767cde34, 0x00061aa990a0a6e0, 0x00001e7652e2cf35 }, { 0x000dcf01768fd984, 0x0000721f7c426641, 0x00028d96cf13c980, 0x00076a126b3e91b3, 0x00001f7562a57864 }}, {{ 0x0000c3aa50085a1b, 0x0003e8f3d589e023, 0x000f811292dc489e, 0x00017b207df0478f, 0x00001d6316d96d0d }, { 0x00082736a4a1651d, 0x000e04b941ade7f2, 0x000c0a51c96c8483, 0x000da82f03d1debd, 0x000040def4c31898 }}, {{ 0x000c4a826abdd1fd, 0x000a3c3d41d3bd3d, 0x00082b57e9743197, 0x0005ce29fb533b8c, 0x00005ac407982d1d }, { 0x00046833e45024d6, 0x00082513d590dbeb, 0x000b39e65f731bf7, 0x0008e5d7484632f6, 0x0000ca6f29d8d329 }}, {{ 0x0001416d4f55d1cf, 0x0006a13f7fc0586d, 0x0006957dd9c9e1b7, 0x0004686dc385315f, 0x00004cf755c4445d }, { 0x00028a41409d5b93, 0x000187851047213e, 0x00010db688562158, 0x0002f8a0c447f6e6, 0x00006e8b3e82ccc6 }}, {{ 0x000df39b884c94aa, 0x000cccb82003f867, 0x00068dda211b1bc5, 0x000101a55610d07f, 0x0000743e976e9950 }, { 0x000fa15eb2e071d1, 0x0008e96e22db2188, 0x000a7901ed91d8b3, 0x0002dc1768cc6d9e, 0x0000e81e206dd3a5 }}, {{ 0x000ffef809be123e, 0x000fa45cf2c24b5a, 0x000ea2facbb12142, 0x0009590b389f66a9, 0x00008f9d35fbb026 }, { 0x000dbfa947e096f3, 0x000eec68eb8fac22, 0x000afaef20465dbc, 0x0000d48cb93c1e4e, 0x0000996990687d52 }}, {{ 0x00088969f06f59c6, 0x0000b90ca84bad76, 0x000f44cf7c6c710c, 0x00071a831fb13919, 0x00002f4311cd9b82 }, { 0x00029f789c4e2b27, 0x00025e721264d452, 0x000950c7da8f86ce, 0x0001a7c9dfdfb65e, 0x0000d786a79714bb }}, {{ 0x00006451aee0821e, 0x000013e6f49f15d1, 0x0008801ab5e3f872, 0x00024ca67678ce82, 0x00003896b89ad41c }, { 0x0009a3bf5194d5f6, 0x00001f019fc32d29, 0x000c1668938086df, 0x000c8ae4564633df, 0x0000568a458b4918 }}, {{ 0x000bac9c2aea0873, 0x000b2a2534d4dbc4, 0x000176f66278228d, 0x00028891a45b8f1d, 0x00005f1547f876bb }, { 0x0006452e97fd7988, 0x0004f6a7b4e35876, 0x000dab3dab4b5c1d, 0x0008e693d0045cde, 0x0000d8b2227e2114 }}, {{ 0x000e4caa4ece9077, 0x00039549f950cd0d, 0x0000f9b126264855, 0x000941f639cc72fb, 0x0000195f212e9897 }, { 0x000d4a60338b6b56, 0x0009f7a55c7ac17f, 0x00031d3b82198646, 0x000f52be7779cbd4, 0x0000760624055358 }}, {{ 0x000e4daa4cf03ebf, 0x000a5880a750c0f3, 0x00031006e436dc3b, 0x000d2500539bacfe, 0x0000d4ef32a1291b }, { 0x000a444f665140ba, 0x0002db55ffc69ff6, 0x000c27c0e1c0d5f3, 0x000e2259446f147b, 0x0000e26f578ece85 }}, }, { /* digit=7 (1,2,..,64)*(2^{49})*G */ {{ 0x000392f2ec04cd39, 0x0000d5ac3f16ea83, 0x000d7f5ede30754d, 0x0009b6872115a461, 0x00008418a223a967 }, { 0x000fc5ff44240c84, 0x00018cde526cdc7f, 0x000b22632c3da39d, 0x000c70d988e537fd, 0x0000709b1f542582 }}, {{ 0x0008d2c9ae428f00, 0x0004f7ea90567e6d, 0x0006dddb93095522, 0x00081903d513257b, 0x0000d1ef01808e5c }, { 0x000ffa707b56bdd1, 0x000c2246b29cb44f, 0x000c77ce5b30e21c, 0x000d3bd42b540a21, 0x0000c8f28344b9aa }}, {{ 0x000c41d1ca8f6911, 0x000d2f1d4e353b7b, 0x00043304ded57d7b, 0x000e262fd062d8a1, 0x0000c7373014e0c7 }, { 0x000d825d0c68baec, 0x000f5e76be77800a, 0x000717e2f324cc7d, 0x000e0471a71fe8b3, 0x00007ed811a51502 }}, {{ 0x00067b085c91370d, 0x000d35b1cb76219d, 0x00009adb7621c58b, 0x0008dbc100ec0bf9, 0x000035a1c37429d0 }, { 0x000539991832fa6f, 0x00095595e93a96a9, 0x000a66a28b826cbe, 0x000e29cb77526c1e, 0x0000acab05a94fb9 }}, {{ 0x000fa297b54139e5, 0x00029e99e240d181, 0x000c9516acb11ffc, 0x000ab4d5c057cdca, 0x0000f108fdca1bee }, { 0x0001468d72cb1fb0, 0x000d1e7db083d762, 0x0006d0c02fa32f20, 0x000a1ef8c31993be, 0x0000ca3322492849 }}, {{ 0x000f2a6cb5724fa2, 0x0002383a4c506ece, 0x0007e28291e1ba7c, 0x000a20ca2957ed18, 0x0000e20ed40d7da0 }, { 0x00052999a29a324e, 0x00090428e195c43b, 0x00095936b72378db, 0x000361c5dc842025, 0x00004a12b227046e }}, {{ 0x000cae6fbba2a2e6, 0x000aab910a5a8bda, 0x00085cb9f51f374d, 0x000c4f5c1ca91d24, 0x000007845f0a029c }, { 0x000257ba0e5ed119, 0x000ade0d21411a01, 0x000fc7b290c9b692, 0x000bb673028fa787, 0x000016219da80e31 }}, {{ 0x00096e6d076e5fb1, 0x000e067ceca9754a, 0x0005a20acc991594, 0x000e01fbf426d2cf, 0x0000e8ea47274e03 }, { 0x0003439dd70f73cd, 0x000dbdd87880e616, 0x000581c546fe37f4, 0x0004291151554381, 0x000076b608169ba2 }}, {{ 0x000f4d069bfe9043, 0x0003d2fc14e35c23, 0x000c03f42ca0baaf, 0x00044b06271735b7, 0x000029c2e58d6818 }, { 0x000d0809671ae302, 0x000ac01f78f5a7c7, 0x000dff46e39ff2a0, 0x000fe0d8350a8ffb, 0x000048652a819f5b }}, {{ 0x000dbc9d0aa61099, 0x0005fe1698e04cc2, 0x0002e8d368be0b0d, 0x0002bc879877be20, 0x00000faac89a81a9 }, { 0x000fe29735ce620f, 0x00040939454d9370, 0x000da49d76e54a1b, 0x000fc59e8e682ce9, 0x000091679212a247 }}, {{ 0x0005ef72b2ec9bc7, 0x0002d0c5b9e02b75, 0x0001dffe92356668, 0x0003a9c2ba37c969, 0x00000df5f3206d48 }, { 0x000de1f2900b0c39, 0x000231f7b91b0620, 0x0007ad51f591a0e0, 0x0009308170a79e1c, 0x0000eab82efa982f }}, {{ 0x000043d055253a89, 0x00013cf3a4434b4b, 0x00006a3584870bc7, 0x0000ee9a7a345811, 0x0000321ed180b8be }, { 0x00093e67f479fe7d, 0x000b49e11137b1a0, 0x000ee41e584a881d, 0x000ebddd400a754c, 0x0000aa7b62dca051 }}, {{ 0x0005185e8a26f6cd, 0x00031e9c97e3f6b8, 0x000431c215d74bd7, 0x000a139b9c10bcab, 0x0000d0dce141728e }, { 0x000380e52200f33e, 0x000551f0eb6c4d46, 0x000d717975e238f3, 0x000cb40b84d4440b, 0x0000ddf18ad14c33 }}, {{ 0x00046e79f34d63c5, 0x0003e51d598d7107, 0x000656cbd3b0d348, 0x0000e191f272c416, 0x000002b47849277d }, { 0x00013ba3f17082d1, 0x000f6364b573e9b5, 0x0006ac0fac4efdfc, 0x00016077b75d03f4, 0x0000927b63f07b9b }}, {{ 0x000fbb3bb17bdaa1, 0x0000e26abb177dde, 0x000788d699b2fdf6, 0x000488073f82ab56, 0x0000c9b786cdf7f6 }, { 0x00048e86e3fd3f51, 0x000c0dba6d183586, 0x00074c02e656b55c, 0x000499190519e279, 0x0000636d8ce30c94 }}, {{ 0x000be5a560218c0f, 0x0002245983c38b5e, 0x000b7795172b6411, 0x000736ce6b14f176, 0x0000b95d3a653da9 }, { 0x00090806472dd13c, 0x000e1cd9f87dc596, 0x000392d3ef194f1a, 0x00019f6577c595cd, 0x000044201d70daf9 }}, {{ 0x000d06a5428770ef, 0x000550381e9ede3c, 0x0003fdf039c7f7bd, 0x000964c11243c389, 0x0000a436caa56e94 }, { 0x0004e52114b12630, 0x000594949d4e2e5b, 0x00069611476b77f0, 0x00082203533649d0, 0x00005fbc01d77138 }}, {{ 0x000b45d0b53b1b49, 0x0006e0678a6513b9, 0x000a0395488ea188, 0x00052e4d892ea4a2, 0x000048a2399a61a0 }, { 0x0005c5b4d8712eaa, 0x000c6dbc69d11ae9, 0x0008b691a486a01f, 0x0004918721477dd1, 0x000074978afddc7b }}, {{ 0x000353dc8bc4376c, 0x000906342e532b72, 0x0002778f7604f48d, 0x000ca80bc386ba42, 0x0000629c4169b70d }, { 0x0003fe03ce10af95, 0x000f0ea68f7e978d, 0x000156d8cd51895b, 0x00046f36d96ec568, 0x00001a9ad92e9ed5 }}, {{ 0x0003a1c621b2b2f9, 0x00026a47ea67c77a, 0x000f4048baeb4ba1, 0x0004eda74952bd2a, 0x00008f88312234da }, { 0x0005059bc76aee10, 0x000c5a9c7ec6d792, 0x000f0d20277aefe2, 0x0007b501bff7038a, 0x0000444624dac251 }}, {{ 0x000600da329b3360, 0x00005b2f2086fbfe, 0x0005a09086465f16, 0x000d4bd6cf6840ea, 0x0000778cdefbedd4 }, { 0x000017637cd7cb9e, 0x000d163529b8a80f, 0x00073d660bc129c5, 0x000992c7ce80e485, 0x000088119f4a6bfe }}, {{ 0x0009ef732984387b, 0x0004d0676cb25661, 0x000198591fb0163d, 0x000d083458f76acb, 0x000001e530c1a29a }, { 0x000baf76b4f735a9, 0x00002715f228bf03, 0x000945c0bc22367f, 0x000763ac0f3cdea3, 0x000010c6a57a79e5 }}, {{ 0x000ef5d295913cb7, 0x000aee010089465d, 0x0008af81f3014353, 0x0000106953bab5d2, 0x00002e287da81088 }, { 0x000de01f9c58ac00, 0x00058b9286b24756, 0x00095fa0668f5980, 0x000ed2388a0b9393, 0x0000e81acea89e97 }}, {{ 0x000a4bf3535ca72f, 0x000398eadd70482e, 0x000990fe5b370e05, 0x000e33fef708de92, 0x000095e812192018 }, { 0x0004f0f83a164ec7, 0x000582c87912868c, 0x00052a18313ff9b5, 0x000a4bf0ab1b1be9, 0x0000846b0bf28b93 }}, {{ 0x000cad0a1ecf03bf, 0x0000da397f6306a7, 0x000debf69a916d7b, 0x0009e19a2744c44a, 0x000096bc23c881e4 }, { 0x000db7091f94675d, 0x000e2cd33791d9ed, 0x000c96fbd74055fd, 0x00013a2a29cc2a05, 0x0000612a63e5bd69 }}, {{ 0x000cbdfda897260d, 0x0001abf8538a5c69, 0x000cecee016f2ff8, 0x0004bd6da195c63d, 0x000048f79961dc84 }, { 0x000c5bd833e2b6f3, 0x00083ca849d7eab8, 0x000aafcb5a3dbb01, 0x00051e9eaebe2764, 0x0000a3bc8e72b00f }}, {{ 0x0003a594c485ad1b, 0x00099f59837fc0d8, 0x000823f75b4b4716, 0x000321e909b641ba, 0x000075762faa795a }, { 0x0000344e3d60af43, 0x000021a526c45028, 0x000deaa6f1565663, 0x0004fc9cd9d39438, 0x000000de2d56a689 }}, {{ 0x00082cc2c2ba07f1, 0x0001c7c2fa4f1264, 0x0005146cdf6fbb88, 0x0001defc308a3b86, 0x0000a19653e4fd21 }, { 0x000d3322183959bf, 0x000bf645f321bb80, 0x000b8d4ce39bfe85, 0x000325a588a93821, 0x0000226bc98df493 }}, {{ 0x000b779c98067abe, 0x000c319e246b0e64, 0x000487d2607f1a30, 0x0009fe300b39781e, 0x0000008d964486ac }, { 0x000b59cb15ee57a6, 0x00073e1c84705003, 0x0008d0f2bb875ce7, 0x0004f15cc45b7efe, 0x0000d78e82ce74b3 }}, {{ 0x00020a4bb98bb7ca, 0x0004adf3fd165e81, 0x0008f4153c582e9d, 0x00037d500499fd6a, 0x000043ec7a9e2734 }, { 0x0002fa487b4aec69, 0x00067955f4a5ac5d, 0x0000c2ad5a75a813, 0x0002b51f1cfd174f, 0x0000044c15223f52 }}, {{ 0x000d3785755ef9c9, 0x000d5feb1dc77e1f, 0x00082492110d3db6, 0x000669ebbe956693, 0x0000caee16ac8c0d }, { 0x000b93cfea66af2d, 0x0003fbe81796b334, 0x00060d54afa0c4bb, 0x0006bd4b462d550f, 0x0000fc36919b3218 }}, {{ 0x0003043896a03a07, 0x0004b381d531696e, 0x000fa5c9a5d318fa, 0x0004ca8c757201bf, 0x00003e9b1ef0bafa }, { 0x0000bf7978610e72, 0x0004fe18555970de, 0x0008447619e614fa, 0x00020318b8267dfa, 0x00002d551502ded1 }}, {{ 0x000b228da47438a6, 0x0000528c06fece4c, 0x000dc9c526f8a5d5, 0x000350528d405991, 0x00009f6e58cf2dfc }, { 0x00076a72c60289e4, 0x0005d64107d1cea6, 0x0003698b662b1fc4, 0x000e45dcdeb9fdab, 0x00000c5b4b14c00a }}, {{ 0x000b95b2310a2529, 0x000b4984d6cb00b1, 0x000ac298db4bf5b1, 0x000f75036cef9c5c, 0x00005f904b6ca659 }, { 0x000bb3c9580effd9, 0x000d02ee8ac25b1c, 0x000b6e64ee6ee865, 0x000ccb066ceb04cf, 0x00005b6ae05c96fb }}, {{ 0x0000ebfbfb92eddc, 0x00095a1a43ff93c7, 0x000730f75cae09ab, 0x000ebe0825bc2db1, 0x00004d67b6663315 }, { 0x000d6c3f4e74d6e2, 0x00082c792871591c, 0x0005e6c0c2cb3b08, 0x000020e3cea5bcae, 0x00008a85be0f06b6 }}, {{ 0x000d7b2902aa47f5, 0x00001230bca6de32, 0x0009846bddfb146e, 0x0004864d4dd20dd9, 0x0000510d80cb9b02 }, { 0x000dbc84fa3046b6, 0x0005459ce98840f7, 0x00000653e31059c2, 0x000ecc3a5a5d947e, 0x00004ffc38657061 }}, {{ 0x000fc1dd78654cb5, 0x000241654a1aff29, 0x00099ab71e2397f4, 0x000dd445eabf318b, 0x00007215a0065fca }, { 0x000e995e35c91e4f, 0x0002a1513595c172, 0x000860c955739687, 0x0001206b0b950466, 0x00005b2b004bef36 }}, {{ 0x000c3c9001d90f0f, 0x000c0697e9bbcfb2, 0x0006bc3106e1aecb, 0x00086985c95d0c1d, 0x0000231244ed3a54 }, { 0x000d62b88afe3771, 0x00044616c973f57b, 0x000be7bf5db81fb3, 0x000b808d4108b7e2, 0x000050a0c350cec6 }}, {{ 0x000320c24f7e2d8c, 0x0009dc4197c75d61, 0x0002a3e6ad9c36af, 0x000c55311266a6df, 0x00003c001f9a9acd }, { 0x00013439c1f03bd2, 0x0000ee101a595966, 0x000b8ec570ea7b76, 0x0001ed4c98317c5b, 0x000050f4c2d89c48 }}, {{ 0x00020ab732d47663, 0x000a19f16a66e918, 0x0000781056db02b9, 0x000d5c5eae97f282, 0x000094939d8bd05b }, { 0x000b2c87b6265c14, 0x0008af9287144234, 0x000a628484fc8c50, 0x0002a90cc54ecfff, 0x0000ff62b0d3b8d2 }}, {{ 0x0007448f03eef746, 0x00087200a44295d8, 0x0000d1822140f960, 0x0009f2f7c707d7d2, 0x0000181637d8f606 }, { 0x000cf227783ae69d, 0x0001f455ebcd58d0, 0x00098430ac48d8c3, 0x00020c94279bcced, 0x0000f56a58b7cf63 }}, {{ 0x0008df2c35144158, 0x00056e471d444b66, 0x000f5c291de84a20, 0x0009292f6211236b, 0x00002a2977e8653b }, { 0x00023b925d834202, 0x0004d0f59bf4f363, 0x000ba5b7bb161b25, 0x00007791df883669, 0x0000991591315aae }}, {{ 0x000aa252908f15e7, 0x000884274082008c, 0x0009fda5d93a92ff, 0x000014d79effc521, 0x00002020dbc62e83 }, { 0x000f621ec39ad5ed, 0x000232a8f1b3c4d1, 0x00010e39cd49e9fc, 0x000cf59efcf64dfc, 0x0000b4beb3b9e9dd }}, {{ 0x000023a25232bd58, 0x0007e27373386156, 0x000aa1b54ba4382f, 0x0002b1366162082a, 0x00002d55d436c6e7 }, { 0x000df2593f2a2fa6, 0x000663abbf04b89f, 0x0008b0824105cb8b, 0x000e4383b6735eb6, 0x00000bfd1da5861c }}, {{ 0x000ec9322dec7ec3, 0x0007e4efdd236675, 0x000a9b56e3c02f10, 0x0001762ffdd52aac, 0x0000b9cbe745e9d1 }, { 0x00021cdfd65b39cd, 0x000df85a96f5294d, 0x00028f8386946139, 0x000cedf4282aa5bf, 0x0000d1d292453a63 }}, {{ 0x0000fc5e10e7712b, 0x0008a7b67f8be10c, 0x000b96034915aa1b, 0x000c1b393365d1a7, 0x0000124aaa91f37d }, { 0x000148c2fe2e9e96, 0x00066f89cbbb1423, 0x000a7e7c43943fb3, 0x0001e18221d436e5, 0x0000b673c1d30111 }}, {{ 0x000e85a1614b76ce, 0x0002fc9233222fa2, 0x0002b5945a0a0751, 0x000ae7b7789ff109, 0x00000859c80837d9 }, { 0x000d07e6b6010c68, 0x000ec7cdc810bc9e, 0x000eb01d956cacc5, 0x000ca499bea3f458, 0x00005b7830a10826 }}, {{ 0x0000f30fee8c3f0a, 0x000134286d2e0f86, 0x0001ad978fe6de9b, 0x0004d1149e592012, 0x0000ed2e1530c0e4 }, { 0x0008c9d2519e343d, 0x0007006858e6a61a, 0x00069709a27ec803, 0x00054a1fbce4c776, 0x0000b72f3fb5dbd3 }}, {{ 0x000e5b62c68d8a29, 0x000e65eb24fe1dcd, 0x000d8d188f85cb71, 0x000dade059eaf9de, 0x0000ef583c1ec4a5 }, { 0x000a60c4ef22069a, 0x00035aed3c2b36ea, 0x000458e370eb3a6c, 0x000784745868c19d, 0x0000a0000634a4bf }}, {{ 0x00029b382fff57d0, 0x000efd23b60c472f, 0x000bf881f819bd9d, 0x000e0c5c9af4ef13, 0x00005143fbdccce1 }, { 0x0008035f45578ded, 0x000cb5373efaef69, 0x000c10c60ffac46e, 0x0008b3124cf56ac9, 0x00000797387ec422 }}, {{ 0x000b0f588a0f9e16, 0x0005bb91e750c846, 0x000bf2b76bdfe46c, 0x0001e03c1c57f7b0, 0x000041ee2fa51260 }, { 0x0004a5ad25356120, 0x000b084a07c4e9ff, 0x0000b68230ef27de, 0x0007f6dccc383011, 0x0000c74f049cd8fe }}, {{ 0x000840fa43472eaa, 0x00018bf490f97ca7, 0x0005ef60d3d59758, 0x000159d8d288f09c, 0x00008305396842d1 }, { 0x0005e16ea2c38bce, 0x0002fd25a631b378, 0x000e1e9b1cda4ede, 0x00090946694761f1, 0x00004a39b68d7484 }}, {{ 0x000a2a463cbfea70, 0x000f033924910480, 0x0003eaa9bc9b0ced, 0x00080165c0c2f696, 0x0000c418f721a31f }, { 0x0001669c5553f128, 0x00073e7bf2f12ee2, 0x000245543d335cf1, 0x0003299d7f0a2200, 0x0000ed5a8309ae3d }}, {{ 0x0003e34ebe7538d4, 0x000c40392f145296, 0x000bffb1ff34a332, 0x0002172f6d3d056c, 0x00001640598299a2 }, { 0x000c8da4b79d1b0b, 0x000e2ee5b80cfa5b, 0x00001774371a4424, 0x0008ecb67e872a12, 0x00004a32f2dc5f4b }}, {{ 0x000ac787ee441dff, 0x000babb1b703e75a, 0x0006296bfb74f2f1, 0x000d17cff6773b18, 0x0000c7b2314a8aa8 }, { 0x000884ecd8191468, 0x000828b0437164b0, 0x00006b798c862eed, 0x000d18373f430ad2, 0x0000e6c1f3907575 }}, {{ 0x000c5a4b66e99b1a, 0x000a6965f5206989, 0x000da89d6d7224d3, 0x000bf4eb9640631f, 0x0000b4e03e0395b9 }, { 0x000436d53d463c5d, 0x000f7bf80b6783d1, 0x000e25fb34d34e57, 0x000cddcb280e701f, 0x000018bf1fde0cd3 }}, {{ 0x000ba1cfa6be5052, 0x0001c6d6556c3629, 0x000046a38dd836b9, 0x00021def9bc23a3c, 0x0000a35d2970adc2 }, { 0x000fc77d5dfd93f1, 0x000147a99c5d7062, 0x000b545b986b85a6, 0x000133e128be85f4, 0x00002b9e4f8b3c69 }}, {{ 0x0001f6c57acb1b9f, 0x000eb805616ee306, 0x000f85b44b08579c, 0x000f6d1cdfb09548, 0x000025f3fb849285 }, { 0x000bf9f676805df1, 0x000ce7290aecb08b, 0x000851fd8e2e2099, 0x000512c03849f87c, 0x000043ec2b969f4f }}, {{ 0x0003e4e910ccd797, 0x0009565765ba5436, 0x000bdf0577ccc478, 0x0006c55b318ce3ca, 0x0000fc4ec1949ba1 }, { 0x000fc62b2afeca4c, 0x00003a3c85932eeb, 0x000a8cca99222759, 0x000c004f696883e8, 0x00000968be080da2 }}, {{ 0x000739fcc7a7b873, 0x0000a906d3e1fa9c, 0x000836cbbbdc2a72, 0x0007329011711561, 0x0000690a8b0f5f13 }, { 0x00013b9b26e41c59, 0x0003857165e439a0, 0x00026954c8b16ff2, 0x000cccea306353a6, 0x0000a667ba136d7d }}, {{ 0x000c2af206d24a25, 0x000c73b973497f10, 0x000dfd13ca267da0, 0x00064e08315c0f94, 0x0000473115252061 }, { 0x000aa99338a37060, 0x0005df14457397cb, 0x0007101327a82eed, 0x00010f3062e8ed01, 0x0000a0cbc7d6001f }}, {{ 0x0008fe977ed7b8cc, 0x00065823b0ec7de9, 0x000abfe06e603098, 0x0000aea831e1b822, 0x00004c9aceb8b0ce }, { 0x0004ee56e7d95e11, 0x00005c20d5e88732, 0x000a981eeb9623c5, 0x000e1b861e48d839, 0x000045fdcadc3088 }}, {{ 0x0002d762b3177523, 0x000825b91e4de589, 0x00054d073fd57a0f, 0x00067a643a7488ca, 0x0000af2bc1467b91 }, { 0x000e0fcd863d7b0f, 0x0003b12091ff4a95, 0x0009ae9dd4edfec9, 0x0005ddbe2581113f, 0x00007099494bbef3 }}, {{ 0x0008e7dd3da6ac7a, 0x0007068c094dbb56, 0x000e7080f6d2bb87, 0x00006862db77d062, 0x0000957c36387eb2 }, { 0x000c48a3b41f412c, 0x0002b40013a5e585, 0x0006e05598676e41, 0x000588aab2131174, 0x0000a5cfa92af35d }}, }, { /* digit=8 (1,2,..,64)*(2^{56})*G */ {{ 0x000b63b80c17b3a5, 0x0009991991724f36, 0x000bce681e7aafdd, 0x00021571e5eda799, 0x0000608a0582bb4c }, { 0x0001f37958fc7a0f, 0x000ed697e5fb5166, 0x000a6efe500b7226, 0x0002f1da5737708b, 0x0000d330af0a0615 }}, {{ 0x0001d5f271b2ffcd, 0x000ce2caa6650728, 0x00046dfd327de7f3, 0x00027f03178322fa, 0x0000216e3f0e2310 }, { 0x00003bbfc59abb34, 0x000d842f48027f5b, 0x000bd4fb27522c72, 0x0007b690faa40cdb, 0x0000abded9d9b492 }}, {{ 0x0002c6f30c43f226, 0x0009e180d738ded3, 0x0000ae17641d02b6, 0x000b5f0756f1a5bb, 0x0000e1022d63ad47 }, { 0x000709b3807f334a, 0x000c89dd8fffb620, 0x0007ad500b84f625, 0x000081d766a281b4, 0x0000baefeb53ba7b }}, {{ 0x000e8143ae4b352e, 0x0008432a3326505c, 0x00021f9bfe1140f1, 0x000adfcfa38d6927, 0x000034810d2f90b4 }, { 0x0000bf0d00ef8992, 0x0002ffa7e6ab6665, 0x000fd1695563a3a5, 0x000ad66ed6cd2d22, 0x0000bbe464cbfd77 }}, {{ 0x0000824eeec7168a, 0x000ce52877a21ec5, 0x0006bed12ba5446b, 0x000931ca2300414a, 0x0000eeb5b0f5515a }, { 0x000322d64e381de0, 0x0001cecf83cba5d5, 0x000840921d7268be, 0x000d46dd7f953814, 0x00002b466f4b1410 }}, {{ 0x000bd6a7d881d987, 0x000ec843d9325f3b, 0x0000379b23abd56a, 0x00044afc5a9bef2d, 0x00004a3dd4f7b324 }, { 0x00032b0b1e2614cb, 0x000de028f61bc0b8, 0x000ceba5ab839425, 0x00059b798f49085e, 0x00003b2eafe5b888 }}, {{ 0x00020cf3f9601768, 0x0005c47f1f0ced18, 0x00031285e9324320, 0x0008926fa800cc79, 0x000017299d89245e }, { 0x00019c8dbe5b7b2e, 0x00054dc1c0f7d133, 0x00005341590ca39e, 0x0007e40e3ef92196, 0x00008544b679b3ea }}, {{ 0x0006e673cd25c857, 0x000e1717b82b99b6, 0x000ce0284257ae21, 0x000cd7d6675922d4, 0x0000134e48cf8715 }, { 0x00020fa3844dead5, 0x00092c4b5f2b89a4, 0x0005e6feb94f1d13, 0x0001f55da3de9c1e, 0x0000bf9802bd31e3 }}, {{ 0x00024c930f786d38, 0x0009e3b0eb919b03, 0x000d74ff03109274, 0x00006f10cd74ee51, 0x00001f7f74fdc12e }, { 0x000970167dca0115, 0x0003819fbac27d45, 0x000a427dd82e631e, 0x0006685b84086e8c, 0x0000417d6e1f9dd1 }}, {{ 0x000343e877e929af, 0x00043c9faf1fc639, 0x00099f48a33c4af7, 0x000c84f4a616d333, 0x0000b1d34afcd46e }, { 0x00039a2aff6798ee, 0x000296be970e78cb, 0x000eacb90b27effc, 0x000350e1ba36cceb, 0x000025b07b3680a2 }}, {{ 0x000613ab7466a572, 0x000a9a16224408a4, 0x0001de6950ea5159, 0x000e65293cc856e9, 0x00009b2282c9735a }, { 0x000316fb85a186df, 0x000099cc420bf2b3, 0x00065d1c833d089f, 0x0007b80c700a5317, 0x000062412e82bddb }}, {{ 0x0007022f7ed617cd, 0x0003df59ac50814f, 0x0007a38c12a4513a, 0x000a6f8a0fdf95e7, 0x0000db96fd7cab80 }, { 0x000a0e79e834cb0c, 0x000deb1cac1fe8ff, 0x000b3d3697805f23, 0x0009cd0e68040188, 0x000080b9a53ca2a4 }}, {{ 0x000e74c82c8bdfad, 0x0007ffc2064cfd1e, 0x000dc1f05107db53, 0x0005c1eea339c31d, 0x0000f20f060da89e }, { 0x000e4bb978fc26e7, 0x000e95ebaf28ee6f, 0x000b9f25d6af0d00, 0x0008c1b8982cecf2, 0x0000a108e862c5e1 }}, {{ 0x000756758aa3f827, 0x0009290640bfd9e7, 0x00070b9fab7e1763, 0x00007b656d226e27, 0x00003f7891bafa5f }, { 0x000ca7e720c3e4d0, 0x00092a35285fe91b, 0x0009cff4ea1fff46, 0x00077e008edbc546, 0x000012258488f2eb }}, {{ 0x000c20ce094f2cf7, 0x00033b817a91cae1, 0x0004ecc1b15a91de, 0x00076e6f9b89aab6, 0x00007bae3c9d9e8c }, { 0x000d1adb3d74632f, 0x000e8b45fcf7e33a, 0x0002e7421004f735, 0x000000e19e679374, 0x0000b0e04475d7e8 }}, {{ 0x000a6b62d93fdd41, 0x00055796424c49b9, 0x0007cd56def02492, 0x000194a49f888dfe, 0x0000f9869f29b9e5 }, { 0x000f96a765fed464, 0x0004e6d179483cb7, 0x0002157b537c82e0, 0x00066411f666f963, 0x00007c51bf707ed6 }}, {{ 0x000f21da47afb8d4, 0x000e1bf074a30ce2, 0x0006d138589ef83f, 0x0006aaad4d7f5210, 0x000072f03502bfa0 }, { 0x000998db4eb5079d, 0x000ffb4eec863a09, 0x000cfb8e86bc3ed9, 0x000747ff8d18f77f, 0x0000d2b07489cd8b }}, {{ 0x00012874a0a79f95, 0x000f4e5c247d44d3, 0x00010e26c8dfd693, 0x000d911c71250714, 0x00005f4b31216fa2 }, { 0x000bb7940ea2bdb7, 0x000a2a6759443709, 0x000f9f7477cf3c12, 0x0000351e3d6123d8, 0x0000f7ac71946caf }}, {{ 0x0000e639fd11e75f, 0x000ce5984ac066c6, 0x000285a62fa36766, 0x000f23eccf5954a9, 0x000013d9c6495b3d }, { 0x00065ad32f4dc3be, 0x00043257de792488, 0x00046ad4f3a87522, 0x000779f32e9ef640, 0x0000b913b812d8dc }}, {{ 0x0002e257466c6324, 0x0000f1b13fb70b6a, 0x0000f27743e13f9f, 0x00059e42c037b44c, 0x000046e406dc7df4 }, { 0x000140e65ebb8a31, 0x00056a81da0263ef, 0x00043bd00d7832a9, 0x000681932931bfb9, 0x0000e425b1bd11e6 }}, {{ 0x00090be4402602f7, 0x000e891b2f1ac7a0, 0x000b6d0409e7294a, 0x000bf31e5f99eaab, 0x0000fb74eb134a23 }, { 0x000a063ac1c5c13d, 0x000bee45004f022a, 0x0001ac97e034e6d0, 0x0005c6da5d838c2c, 0x000081f282d44949 }}, {{ 0x000cc1e4250112ec, 0x000b82259558a787, 0x00090773f60a0825, 0x0003124dc5343c66, 0x0000291b4782f302 }, { 0x000581ddda3dc5d2, 0x000823f16dfbb7d8, 0x0001d5d9f7b848db, 0x00077fe3c921fa94, 0x0000f85610bf9475 }}, {{ 0x00047ab1f32b86a0, 0x000bfcb81d73c9e1, 0x0008f5e3e5b8290c, 0x000b3cbab6d07e97, 0x00000464d3a117a3 }, { 0x0001f4e9cbfa8244, 0x0004a3d9fafdee4f, 0x000a6195a1c9102d, 0x0006ef471fab3dbc, 0x00001448eb4ee774 }}, {{ 0x0009c341cf277327, 0x000fdd366b33f1dd, 0x000f832103f17459, 0x00020d8613b97b81, 0x0000e530424a7a93 }, { 0x000bac5ff89d496b, 0x0003c6e16efb6f3b, 0x0009a4af35445de7, 0x000b6909fdf24b8c, 0x00008e6d72360625 }}, {{ 0x0001088fdb965d4a, 0x000d187459afccd8, 0x0003363a9676ad62, 0x000588d8e6bd4514, 0x00005899c7ff54bf }, { 0x0000a630bc8a6a3d, 0x000682c1e269375c, 0x00036d1fbb542336, 0x000557f11f9f037c, 0x0000eb8a2a124b0a }}, {{ 0x0009609d82cffc8f, 0x000ea7eab64c31ee, 0x000a8aefd3c18eff, 0x000a9ea0cffdb1da, 0x000041dcae34044c }, { 0x000ce67dc8a145d6, 0x000af9500d24fc90, 0x0003d839364f3a43, 0x000b1e5de9c75033, 0x000024e5e262c95d }}, {{ 0x000982daa186bf3d, 0x000d1d44763eb501, 0x0001a82832c513b3, 0x000c80bf324a0e22, 0x000032d177c5f1dd }, { 0x0001ab688e43f0b8, 0x000f1f78bbc55499, 0x0000ed8acfc02b0f, 0x000a6c7507a1783e, 0x0000b89a79b2959a }}, {{ 0x0007e04350f65b7d, 0x00039b56d0bdd662, 0x000e3cd6ced83cbf, 0x00020b82f0a6ef32, 0x000023dea34ebe08 }, { 0x000df290bff0bdd6, 0x000b4cdc1070c828, 0x0002f2d76e2f397e, 0x000e16129fb2034d, 0x000008903ddb617f }}, {{ 0x00014fb49f1ee184, 0x0001b33fc2e43263, 0x000d2d8e3b92e418, 0x00083abb53b30076, 0x00001aa8b3c82fed }, { 0x000ada351697521c, 0x000d0a52f7007501, 0x00035650105f08c1, 0x000dedfb02b9e3c2, 0x00008861ad3c4117 }}, {{ 0x000ebf2c0b49920f, 0x000ddb27b1356705, 0x000f1e3cf422fc64, 0x0003faf9fe85d19d, 0x00004ef9ee33bc0f }, { 0x000f87fda813afff, 0x000ff4eabc199c90, 0x00024732b3060181, 0x0006fed54c703259, 0x0000301ad32fa058 }}, {{ 0x00001e4bd167db75, 0x000d1fc609e4a74a, 0x00031a4833c074c3, 0x000fcbf362a44a14, 0x00002983fab4c44c }, { 0x000f18181f25f8ed, 0x0003c3273483c908, 0x000118af9d79551f, 0x000b1d37ea79c6aa, 0x000005561a58a7c4 }}, {{ 0x00083fd5597eef8d, 0x000467c051af62b9, 0x000a73b96f3d0664, 0x000e60da1e9a998e, 0x00006cc734074631 }, { 0x000f6191644596a8, 0x00018ca65d698049, 0x000dcf446dc950da, 0x00041ba3b732b22d, 0x0000e67d9922451a }}, {{ 0x0001f01cf87103c7, 0x00060eeacee50437, 0x0002bcc0f2099af8, 0x000403405ae419e7, 0x00002218d3d2d918 }, { 0x000ecb8ef6d99c8f, 0x000e47e8887a132f, 0x00086765f5199df3, 0x0003eea5e6751330, 0x0000a872eae8aca4 }}, {{ 0x0002a910af444e76, 0x000d4223021926a4, 0x00092cf23b6d15a8, 0x000dc5aabb7c28a4, 0x00004beebfd8904c }, { 0x0002c1c510c876a0, 0x00026e07bd68cab6, 0x0008141545b76fcc, 0x000dd0aeb2b57fa3, 0x000028f01be29773 }}, {{ 0x000fb2f0f13fe534, 0x0008dfbb2d09dc72, 0x0001f6b8e14a4dfd, 0x000cd49b6c3dfed1, 0x0000cba2af46aa95 }, { 0x000b67125e538c1f, 0x000817b80be73992, 0x000df438154aa4c9, 0x0000fbff7ed9327c, 0x0000e6c8e2a6691f }}, {{ 0x00002e29099045b3, 0x00073e88670ced73, 0x000f92edaaaae805, 0x00082a9bce3dfe41, 0x0000a6fe4cc3fd2c }, { 0x0005bdd6a63370ab, 0x0001411a6eac16e3, 0x0000746d6406529a, 0x0009a52ab7644700, 0x00006744b2717351 }}, {{ 0x00010c6b129788b3, 0x000e1b07e5c9ce97, 0x0002afa2c95c509c, 0x000dcfa4a0f379e5, 0x000038870779d124 }, { 0x000e2ff99da77528, 0x0003ef971954cf1a, 0x00025edaa877aa54, 0x00047fba8b1cec79, 0x000023185a87ebdf }}, {{ 0x0006bf94a9ce8a49, 0x0004c3c340ceaa2d, 0x0004576efe8a0a53, 0x000fca76d2635527, 0x0000ef0d9f9a4fb6 }, { 0x000c6f98643cdd39, 0x000610ab76a9af0c, 0x0002ed99c292f6e8, 0x0005b63a052740ab, 0x00002f34b27f25e7 }}, {{ 0x0001d6152495a6cb, 0x00076a76b2515cf3, 0x000163afb2252000, 0x000dd139771c4160, 0x000019dc05c32b50 }, { 0x000c06a0b6aebb7e, 0x00047e1fbce090b8, 0x000d6fc489a4cb51, 0x0001cce35aac927e, 0x0000dd0bd5bb9272 }}, {{ 0x00040304b2f32575, 0x000608bafe7ddf39, 0x000d2de3e0a8e028, 0x000e121e755851fe, 0x000012305bc663a2 }, { 0x0009215b9ac0aa93, 0x0006561b0a2a8600, 0x0002055b6de6ae99, 0x0000bb796cf12128, 0x0000d6c9a199774a }}, {{ 0x00001d3c3571f271, 0x000420537387c09e, 0x000e1021ab2abf2c, 0x000057919c5832fc, 0x000085c20ac422c1 }, { 0x0003afcdec0503c2, 0x0002c41da48ea80e, 0x000deb9fd6d517a2, 0x000ee1fc734e71e8, 0x000090527eb13975 }}, {{ 0x00010dd399eaf33a, 0x0004ad700235e9a6, 0x00042b3eafd5b269, 0x0003ff3e50308d3f, 0x0000894a8bd16a9e }, { 0x0009738198fc9a32, 0x0007260d1ac16352, 0x000af72f3f46fc54, 0x000b016c584cbb3f, 0x0000e913d664efea }}, {{ 0x000dd645686c5987, 0x000ed7fa6d74081e, 0x000467cc1cabbdbd, 0x0002f3efe60ea4c0, 0x0000d3d1d48d4bb3 }, { 0x00069876a93ccb94, 0x00037ec96460b259, 0x000dd2439ab5990b, 0x000acaceaa12fd0c, 0x0000da6bef5c292c }}, {{ 0x00001c7318116168, 0x000fa17472ff5805, 0x0004fab7a07b4f61, 0x000da2392f422970, 0x00000e0d1e93d88e }, { 0x0001e184b20a7a54, 0x000b5b318464945d, 0x000ba2e4420c0b15, 0x0009fe2606d5e594, 0x0000d365f13f5f27 }}, {{ 0x0006362953e25a5b, 0x000ec524c6a7e046, 0x000adf1ee2117945, 0x000664ea547fa1e2, 0x00008a103e0c9c66 }, { 0x000e3f0859cdc2f8, 0x0004cb15cb12a88b, 0x00096d25592eff44, 0x000ffc8c0561b6f9, 0x0000f36918054b98 }}, {{ 0x000ab5b320711223, 0x000a2beb92041b8f, 0x00062b91c9ed202f, 0x0001a579401ae38c, 0x0000fb40e7e1d360 }, { 0x000f7ad0829dc074, 0x0000092487443e97, 0x0000199242c6d8ee, 0x0008596378595a31, 0x00001217219125df }}, {{ 0x000ab2609e227e6c, 0x000e1b61059705ab, 0x000a2c0765f9ca9e, 0x000351fd5a3dd492, 0x000054b35ef99c4c }, { 0x000517ab66adb516, 0x000e8896e70ee822, 0x000deecf0c7cd20f, 0x0001d59caeff2c56, 0x0000ac23b6003787 }}, {{ 0x00021487098d3893, 0x00021e0bdefdd4f1, 0x0005e1525cf8642f, 0x000032bc06995846, 0x00002ad5c774a21a }, { 0x00067f595255747a, 0x000b83318969006d, 0x000e0b7efa7ee217, 0x00097c961cb4d73c, 0x00007cde45c8bbbd }}, {{ 0x000e56937bdc883b, 0x000a71e9e70c72e5, 0x0008f7103f8014bd, 0x0009b5cf5b2e52e2, 0x000059c31c61ce26 }, { 0x0003442dae76f13a, 0x000bb17456c61e10, 0x000aa56c75d9f1eb, 0x000b77d55bc2e954, 0x00008d57023bf8e9 }}, {{ 0x000621dbccc0ef22, 0x000c547ceb26210c, 0x0007b259d32c7710, 0x000b4bc31983545e, 0x0000a78659cb68c5 }, { 0x0000cb3b3dddc4f9, 0x00049e959266fbbf, 0x000642d20bdea51f, 0x00008b496a3514c3, 0x00002d270b753385 }}, {{ 0x0008c2bf83f14439, 0x000a2ce478e2135c, 0x000ef4e093be4e87, 0x0002341f67547b5c, 0x00000ad1fffb6d99 }, { 0x000c1d8afc50c539, 0x000b1af455809854, 0x00057d1dbacf8e42, 0x000b613acc68d1f0, 0x0000821512510276 }}, {{ 0x0007e0606f082f40, 0x00083fd9eb45ab26, 0x000b6cd1ce05d312, 0x000e6558a5b234b5, 0x00000f7a741d7de9 }, { 0x0003ddf9a8ed377e, 0x0007270ef751b115, 0x0005a3127425be84, 0x0000278b4f352f17, 0x000037791e3b067b }}, {{ 0x00051e4e6b8cb501, 0x000c279c21520b0e, 0x000ff6b7834b4d94, 0x00094c6f790864fe, 0x000042d69c0fb7d2 }, { 0x000d60d912391757, 0x0004f7f5c9dc340a, 0x00070f46ed0e8a4a, 0x000afffd05ad53c3, 0x00002565d3e375f9 }}, {{ 0x000effdf0c11cd5f, 0x0001cdf0eeec8c68, 0x0000788a3915c4f7, 0x0003c36244a27fec, 0x00006b8aecf409b1 }, { 0x000bb395927f21d8, 0x000141c65842df85, 0x00087766136f5c4f, 0x00020dd298821b35, 0x000018965c995c5f }}, {{ 0x000dee4dc0194e60, 0x000d316fd6f7140f, 0x000abfa03437b7c9, 0x000b47962f9fadb5, 0x0000e38b7d704c40 }, { 0x00062cdef4e7d515, 0x0005f0735d7620e5, 0x00039e5f211dd6fc, 0x000802f9a04e3c2c, 0x0000b9308ad3b24c }}, {{ 0x00048abb8f5d2a2e, 0x000fc5f477010973, 0x0008cafe1533323d, 0x0009158dd617125d, 0x000015bd2f4c94fa }, { 0x0006588b45797dda, 0x00010b599d94bbd6, 0x000de02c461b7193, 0x0004b1a1ad51ba28, 0x00008fbf0633d6b7 }}, {{ 0x000970de6f2beb58, 0x0006701fad097a5a, 0x0007b79da2ede893, 0x00026865649883ea, 0x0000dc66c7da4b5e }, { 0x000820bb894ec5ea, 0x0002a245e17fc196, 0x0006990084cddd1e, 0x00078883fd833c65, 0x000023fa1aafb1e7 }}, {{ 0x000baeb23e56969d, 0x000cc70d875d56ae, 0x000b664d448127e8, 0x000719f12d6a0a9a, 0x0000a1bfa272524c }, { 0x000a8a927cea79d8, 0x000843ab99a907a9, 0x000f67e1618ebdee, 0x00088f59ef1e7454, 0x0000b1cb62e5aadd }}, {{ 0x000e3f57dc2d6e51, 0x000a50c08191224d, 0x000b000f68b5b448, 0x000753c84c4126eb, 0x000061310eee001d }, { 0x000304ef0417f39d, 0x000a637d446a1dda, 0x000fe29988f21ca2, 0x0002976f57bf2179, 0x00002b04dfb32376 }}, {{ 0x00051e67299da7b9, 0x000a547d19dfa5a2, 0x00035a8f31025ec7, 0x0008f5cf5db007de, 0x0000c7a0a9aca7c3 }, { 0x0004743570466a59, 0x000f8841ae98e78c, 0x000c62a876c22c05, 0x00089b7f5f818537, 0x0000034a977f0e71 }}, {{ 0x0003e514e5a4fbe0, 0x000fc5ac242316b4, 0x000c980f9b0feddf, 0x0009eaec6abe060a, 0x000079cfa30418eb }, { 0x000756c3e6d3c154, 0x000a63807d784f90, 0x0000ed5eef704cb7, 0x000ec963d1161a88, 0x0000f21eee5e923f }}, {{ 0x000fac0dd10881c6, 0x0003801aaa79697b, 0x0008968d0fe0583b, 0x000197fa004a73b2, 0x0000aa2663657610 }, { 0x00019b3e879170f7, 0x00043f57d3d2ec27, 0x000caee09527a33a, 0x000e416ed6fa2fc2, 0x00009abfc9b90ad4 }}, {{ 0x0007050b07a66baa, 0x000fa966d17fbc7e, 0x00098ccda746ff07, 0x000fbbf370cd1a70, 0x000027f44964c30b }, { 0x000e2646e5bb924d, 0x000fbb61ede9046d, 0x0000b93fdf744056, 0x0006ed7c5a053005, 0x0000ad3637db0835 }}, {{ 0x00054660dbc8b1ab, 0x000d6088cad38c0b, 0x000fb6902a066a7d, 0x000dc7ca3471b7e8, 0x0000e86a1789d644 }, { 0x00095173a8f8b220, 0x000fe11a6fd8de44, 0x000a5a2626461987, 0x000b8a17c44dbffe, 0x000097f4a165ced5 }}, }, { /* digit=9 (1,2,..,64)*(2^{63})*G */ {{ 0x00013e2c380a9bf2, 0x000364d391c2a82a, 0x00027444dcb0941f, 0x00055fbcabcdd486, 0x0000ff69ccdcb479 }, { 0x00052b540c86a1b2, 0x000a4f04a057a87a, 0x000001893b8ba415, 0x000c36a44a876550, 0x00000e23c958c1e1 }}, {{ 0x000f5e69622c79cf, 0x00060c516a0d2bb2, 0x000beb03cb372318, 0x0004c5d8b0d5cc16, 0x0000e18f5d34d82b }, { 0x000648f91783b808, 0x000bf0bf5a01797f, 0x000c6a4c687ad85d, 0x00067d3523d20b44, 0x00009192002a1f83 }}, {{ 0x00028c5bd0e3d52e, 0x0007eafe60b7cf78, 0x0000021d7c9889ec, 0x000e55cc425860a5, 0x00006eb845413903 }, { 0x000c4c0a359d0286, 0x000bd5edc55ae5f2, 0x000c93c569dc0f68, 0x00021ae2ca527f56, 0x000043058b802960 }}, {{ 0x0003271e6c831d51, 0x00077b8fac61d9a1, 0x0002d09fe01d7f5f, 0x000a2a4037d25e06, 0x000064507e385362 }, { 0x000ea6041214d255, 0x00051c0232f76a55, 0x000d1178f014410a, 0x00037fc788957c32, 0x000085a49edcb98c }}, {{ 0x00060cf82fa14b89, 0x0000d4ed0b8892be, 0x0002acf4c3455b03, 0x00078fd269ea1768, 0x0000311da4567f5b }, { 0x00005c27534d6570, 0x0008797d4df55311, 0x00017d92c88f0a48, 0x000cafeb1235b59a, 0x0000809db71804f1 }}, {{ 0x000f3338ee1c0299, 0x000f84bb5def9961, 0x0003040a98f9248d, 0x0003ac5761cb69c8, 0x000000beb921e57f }, { 0x00066c038dfaec8c, 0x000d10d2f5378a8d, 0x00065894c993b6fc, 0x000735690acf4c2c, 0x00003b9318cab2f0 }}, {{ 0x00040461e09c5a97, 0x0008f4af94d70cf7, 0x000eff105d9de3f2, 0x000d95602bdb802e, 0x0000b9b80b8301a6 }, { 0x0003d814bf093a24, 0x0008ec8365e9383a, 0x00029c06e19337d9, 0x0007f32c1ea762c8, 0x000062b44e7d6f3e }}, {{ 0x000e0341bd6ee336, 0x000102bb4d8bc50a, 0x0005fb1615b32bf2, 0x0005df468181c0b1, 0x000049acb4f25f09 }, { 0x0002c9d27e3d254d, 0x000f8cf7003e8666, 0x000a275ad19d7996, 0x00026d7c2f11a6de, 0x0000e62e628f9c93 }}, {{ 0x000b4e10567aa138, 0x0000a3588cceff67, 0x000f0fb9dd12b3f5, 0x000abd50d8594c54, 0x0000be14cc0ee64d }, { 0x00086ed7a832f320, 0x000a0d5b5ec995a1, 0x0004fbb9c2ac7055, 0x00008b777bf4b9d5, 0x0000c5b6259dfe26 }}, {{ 0x000a5ff674823c2b, 0x0000030614c09004, 0x000172a0cbd7525d, 0x0008894a1da98d12, 0x000030b72f8253fc }, { 0x000c72e27f2e7888, 0x0000eb81d7ea1d7e, 0x00029433ef893a49, 0x00053356e38cf289, 0x0000353f5c728ab5 }}, {{ 0x0004cde963d2fb2c, 0x0003cf5a44f77f7a, 0x000d0f6e695842ef, 0x000f5ba097aa5f9f, 0x00008eb52caa0bc1 }, { 0x000239c14011b93e, 0x00062c0eee470afa, 0x000de8059d887af6, 0x000e9d43184137d0, 0x00000f5b3380d1e8 }}, {{ 0x000b6b6e1ca760d8, 0x0007f19a8afd30bb, 0x0007cf16ffb18b25, 0x0004823e08679832, 0x0000efcafa52751d }, { 0x0002beaaf58337ec, 0x0006f11471f1ff0f, 0x0008cb570ffa8731, 0x0005ed83ed76c338, 0x00004c92081ca03b }}, {{ 0x000c9c96430e9a0b, 0x000a59ec3076a27d, 0x000e0779be1a0693, 0x000d3642e5e82908, 0x000023d4c1872f26 }, { 0x000b6eb671cf9704, 0x000b48d519bf6156, 0x00059a3370dc9737, 0x000c72ba0e29ecd7, 0x0000d89e2cc152ef }}, {{ 0x0000aaee181a2a7a, 0x000ff32b88756ddc, 0x000230d35049ce8e, 0x000b74aa4ed4e865, 0x0000261c5ca08124 }, { 0x000d55e8ca475a13, 0x000dab96c168af3a, 0x000f0644ffaace6a, 0x00053a1366563c7b, 0x00008a47ff05a4d9 }}, {{ 0x000813e66abf3deb, 0x00033d8b76da1f56, 0x00063d76e529d81c, 0x000c8178210dfa46, 0x000088e501fc78ec }, { 0x000d7ee53868e5f5, 0x000b91e350cb901c, 0x0005834c92ea4be6, 0x000c54687b653d65, 0x000007ddaf56d876 }}, {{ 0x000f835f9d0aad8a, 0x000272e523b8bf60, 0x000b800dac7dffa3, 0x00068eb888009eb5, 0x00005af05fd9e53f }, { 0x00029d4c6fdd401d, 0x0000c312afceb620, 0x000a13ffebd0185b, 0x0006be5b0c797df2, 0x00003ac5e2304089 }}, {{ 0x00033878925685fc, 0x0009fc1afab4bc58, 0x000ed33fb9b57d7f, 0x000a73a05833f5c6, 0x0000c58881e99e36 }, { 0x0001b7f21a55c701, 0x000b20fadd9419a0, 0x0009ae2c0ace83ac, 0x00042a9c6bcca109, 0x00002b5c2691fab2 }}, {{ 0x000ce9141bcb3848, 0x0004a19909523c8b, 0x000ee6b8b3259a8a, 0x000919d5aa62f648, 0x00009596a8c13395 }, { 0x000520dbd9ba1d54, 0x000298435f9b9887, 0x0001bce399dce0dc, 0x00073f36c0210da6, 0x00000d8103e648d7 }}, {{ 0x000a389397c74a91, 0x0009bfec1ab1bbdd, 0x000e022c75a0a320, 0x00012eac4ef8a65b, 0x0000945f9752a8b9 }, { 0x000b8d4c407c4937, 0x000863674660876b, 0x0003f8d0b2f52d8c, 0x000aca39411d67c5, 0x0000712bb3bc0828 }}, {{ 0x000ecf1276d09b96, 0x00055d1e0a1b12ac, 0x000ca83c96e8b70c, 0x0008f53cb1e4ef88, 0x0000798dffb7e60b }, { 0x00068fc88f16a70b, 0x000f62e1b39b80f3, 0x000cff33731551d4, 0x000ef56c2fd90d0a, 0x00002d84069cd845 }}, {{ 0x000203d2c908ee78, 0x000ef61196a2fa2a, 0x00071b575e65ca1d, 0x00006d231931b981, 0x00000a20eba5436a }, { 0x000781b3c4ff64b0, 0x0002ee098939db32, 0x000c16deb83df347, 0x000bb4643e37d6c2, 0x000068ca7511af52 }}, {{ 0x00077057e537e323, 0x000ddb07850ec06e, 0x000895c9b8ea2e5f, 0x00067909dac5a38b, 0x00009de2a5e3a8ab }, { 0x000620a4c251a5ac, 0x0001442b59e78df5, 0x0007c77739906b4b, 0x0003b1e4a4cfc91e, 0x00007e41e6a9a9ed }}, {{ 0x000e5ae52c223602, 0x000d2aa049f842cb, 0x000456e602ff290e, 0x00090ef56ceabc5d, 0x00009d94422dd0f3 }, { 0x000f78ebd3835c75, 0x00072e6334957f10, 0x0000219b5e9c8395, 0x00039cf7b57e388f, 0x0000e66f4d445c5c }}, {{ 0x00080ff42e6bc91f, 0x00007052b7ce5421, 0x00095c62c9b34c59, 0x00009d5dae6d4ce9, 0x00005ca79a998f9e }, { 0x0005aebf80664f4a, 0x00082022c34a1c65, 0x0008ec7d87425f4c, 0x000c55ea23803d6f, 0x0000a8295081cef5 }}, {{ 0x000d185891700399, 0x000e4587135593fc, 0x00065ecd183bf605, 0x00088ed0d32e6eff, 0x0000f3fb39aa7eba }, { 0x0003c612df40b960, 0x000899d6d97e1340, 0x0000d9be34ef3c31, 0x0000ba273d42c6b7, 0x0000fd96d1086b78 }}, {{ 0x000bf546da5d876f, 0x0005b1504b6c5a08, 0x00088cfb9cc92732, 0x00010fd0035216f3, 0x0000d81054fae260 }, { 0x00001d5cefaf619b, 0x000baa44cd623c3e, 0x0007700e316b2264, 0x0003f24e7366ce71, 0x00007cfc40c2c53f }}, {{ 0x0005eccae559fb71, 0x000d4d9036520f83, 0x00015ce743b334c4, 0x0005a2904dfb3c3d, 0x0000962fbaf2e972 }, { 0x0007e09d0efe288f, 0x000a3dbf8a5a0ac5, 0x00059388f9f119e2, 0x000fe2da0547972a, 0x00006949be49f2cb }}, {{ 0x000564c83f9203e1, 0x000b60e2fdd23cc0, 0x000c511e21322752, 0x000e48dbcb80288b, 0x0000797385f1df08 }, { 0x00012d656be5c3a7, 0x0008ba239560368e, 0x000a236ec3766f55, 0x000ddb1c3e893752, 0x0000ce0f9a1079c0 }}, {{ 0x0003f375576cb563, 0x000f24e63e3bc1da, 0x0001a110da9fde91, 0x000d84707c719b6a, 0x00001a17e6c0b377 }, { 0x0002b1aa240c1a70, 0x0004f760700d3607, 0x00040f793abe8e2d, 0x000d78b4cbb1a182, 0x000018bc4b3b7f7d }}, {{ 0x000b0c591bd83326, 0x000c4cabe063f644, 0x000371d820edcf2c, 0x0009d54ca9b392f4, 0x00002b614ae1ed42 }, { 0x000be79af8c567bc, 0x00021fd92f1169ae, 0x000b60d7889967db, 0x00029e6af63aeb1a, 0x0000d1f76a097e41 }}, {{ 0x000fe8bd2ff0d26a, 0x000c04e40e50acf6, 0x00073f191935df0c, 0x0005f541ff0a98ad, 0x0000d0709fed8f27 }, { 0x00066466bcac1668, 0x0009ba16cafbc916, 0x00091ca479cfe8aa, 0x0006a974f170f875, 0x0000aea394d3eeeb }}, {{ 0x0000b1d093f471bb, 0x0006510f5b343bcf, 0x000a023f726a643d, 0x000ed90df0f2e400, 0x00003c3843aa4ab3 }, { 0x0000bb7742e67add, 0x0003e95c70816030, 0x00093cfe99544825, 0x000be16a6e943e4c, 0x0000792d7df86acd }}, {{ 0x0003a9e4817dcf52, 0x0001e83824297b45, 0x000001da60dd959c, 0x000f8849e9d0e558, 0x0000f7d56e3c5b73 }, { 0x0001d44293968f25, 0x0008be065eb24132, 0x00046defc5136d73, 0x000f02f92dadbbb8, 0x0000281b17b810f6 }}, {{ 0x0002077086307267, 0x00015e63b5f1cc41, 0x000abc7fbddc361f, 0x000938b4437ae52e, 0x0000d5d97371ebf8 }, { 0x000fc8b47bfe2c04, 0x0004a491058edeaf, 0x0002b67015a14d38, 0x0000c551c827510e, 0x0000de8b56068862 }}, {{ 0x000270352a539749, 0x000d7e61b4d5e634, 0x00025b25e620e74a, 0x0003a22edbd86474, 0x0000a57233245448 }, { 0x000a08d537795ccb, 0x00034e664cfc50e9, 0x0009842df60b03bb, 0x0007f949a50dee01, 0x000062e5de6beabc }}, {{ 0x000ff7a5b46ad8be, 0x00056576be5f7de2, 0x0008922e96e9e3fe, 0x000f20d36d93006f, 0x0000601b5481985f }, { 0x000c615b703d9998, 0x000bbf1cd871236b, 0x000d064911e1ff34, 0x000ff3f6df156a39, 0x0000a91dfe2f0173 }}, {{ 0x000cde4adff641f7, 0x00041e8de3eee6b3, 0x00086eb2c2b1af03, 0x0009081bd58c7753, 0x00008deb4969dc62 }, { 0x0001141f046d8047, 0x000d8d25302169cc, 0x000fe875ce874407, 0x0001659ee8ca60f9, 0x0000414e05bc5492 }}, {{ 0x00090cfd9375a854, 0x000ec8d6dfafed30, 0x0003305917f500ce, 0x000ca1ba033a0165, 0x00006da9376c5895 }, { 0x000e293b24e6645a, 0x000f1aea3c40af51, 0x000bb3e7eeccfcea, 0x000bc22e83469ead, 0x00001e948c862537 }}, {{ 0x00073554cc7c12ee, 0x0004f131e6c0bb48, 0x0005094218689b04, 0x000d40b221900469, 0x0000eedc75a767f1 }, { 0x000c08d7b45cd697, 0x0002f27cbf18a512, 0x000b0429e8cca640, 0x0006fec4d4d93651, 0x000034514ce6bcdc }}, {{ 0x0007f5e2fb1758d8, 0x00077b486df2a61b, 0x00073501d1a6fc21, 0x000776affa1ed9c0, 0x0000e7124755e764 }, { 0x0003bc919d78f96e, 0x0007e6bcc2423b79, 0x000f26a75d0a01ad, 0x0005738e175ce0a7, 0x00003c4ce13c1479 }}, {{ 0x0003e291023c1b3b, 0x000ba6f871942dfe, 0x000e94771c645656, 0x000afdf782372ff6, 0x000084b784d593f7 }, { 0x00061a89634cbefb, 0x0001b11e4e8110ce, 0x00044ce70f6b5b2e, 0x00061f4e02a2d70d, 0x0000222495a4851a }}, {{ 0x0006cd7685d97af3, 0x0004785825808bd3, 0x00070909727c9ff2, 0x000e726d151dc3cb, 0x0000b806e9f304b7 }, { 0x000deb57a092fbd7, 0x000c605b22922a44, 0x000e8db73ec050df, 0x000d714c76494c87, 0x00002e35bd113f29 }}, {{ 0x0009ed0eda00c05d, 0x000c259c3d12a732, 0x000c7bd5b6434166, 0x000b91ecb5f71687, 0x00008aa1f29eec04 }, { 0x0003fa2fed9642f5, 0x00066474683c2eb9, 0x0005034a4c594fbb, 0x000dd7c674956eeb, 0x0000dc5d5eff55da }}, {{ 0x0001e6e6273a9971, 0x00099f231f63950e, 0x000032e3bca22cf9, 0x000130d62a77797c, 0x000012ab210bc6ed }, { 0x000864d0edf2e53f, 0x00039b0b3c9fef02, 0x000044fabfd0707c, 0x000e912cfaf7752e, 0x00000d5f6d1d2afb }}, {{ 0x00024de3470dc37d, 0x000668397c69134a, 0x000648db2f4c601f, 0x0009d3de05a42c31, 0x00001832ed2bd25c }, { 0x000033860bde0c47, 0x0002daab75d49411, 0x00061d1c99e46bc7, 0x0006d2dcf9890058, 0x0000216cef95030d }}, {{ 0x0006acbb473c0f8d, 0x0000dc82094cec3b, 0x0007898ebbc57ab7, 0x00049cc0d9976fb8, 0x000043a34cd4250c }, { 0x000d91996754db45, 0x0007f6144569d857, 0x00061a5eefb627fb, 0x000fa5c7dc3190a3, 0x00002f9e3edd2df3 }}, {{ 0x00005c3197c1a20c, 0x0003c37dd1c8a206, 0x0007cf0c0281a36e, 0x000f1f62e7e5410c, 0x000059f6d21710fc }, { 0x00077db2a94dd7cd, 0x000a80101683d546, 0x0004f1dd5f8af1e8, 0x000a95a7f1d7127c, 0x000083f71312d346 }}, {{ 0x00054d652ad70ca6, 0x00026aaddce33450, 0x0006fbdcde261523, 0x0004ce5dc2a6811b, 0x000053683550c6d5 }, { 0x000c91c825e881fb, 0x00056d492a210056, 0x0000c67f47b9218f, 0x000de150fad7f397, 0x0000880885c56630 }}, {{ 0x00093e4b2fa0fdfa, 0x000b8a2ce309f06b, 0x000910e8d51c27ca, 0x0004ae92efdb27b5, 0x00004db9e3997567 }, { 0x000141c1e6fe9e0b, 0x0007fe644aa3dedf, 0x0009ced4138cc692, 0x000f98c07317a666, 0x00003ed5e5173c1b }}, {{ 0x00060318b442f800, 0x0007de5619063736, 0x000e85967ce17243, 0x000a65c36858dbad, 0x0000f669b02efe62 }, { 0x000465311b7e9e0e, 0x0000ecd12ba4b7aa, 0x000b5462f70f3e78, 0x00014050df399daa, 0x000097efc0401f70 }}, {{ 0x000096a8921179a4, 0x0004ac864d3779b8, 0x00062cce18df4dfc, 0x00017a0283c5d047, 0x0000bb1823fedf19 }, { 0x00068eded5c79181, 0x0002d9d23b3ebc2e, 0x000abef1f1010c41, 0x0001e9e6c90bdd6d, 0x0000b133de5a1dfe }}, {{ 0x000990b4e4f167a4, 0x000b77799eb6df0e, 0x000089f602942610, 0x000b0008e26c3cc5, 0x0000153c35c8a372 }, { 0x000a4c3313da4eec, 0x0007f7e2586abba3, 0x00051f7d3b8634f6, 0x0009c5606239ca6a, 0x00001e8329fe8908 }}, {{ 0x000c7bfad0211361, 0x000e706f6a3f6fbe, 0x000e9946570d08fd, 0x0009423d3ad5cad2, 0x0000a4c7595c43d4 }, { 0x00060c43d2476796, 0x00037333e23cb3ba, 0x00041f9a075abd4c, 0x000f0fb063979fe8, 0x000050ba89794e36 }}, {{ 0x00004ca6d9af362f, 0x0006182be7cf3a64, 0x00027c49cb9a7e78, 0x0006a79a9cc86ba9, 0x00008d6173b50eff }, { 0x0000b23616d2a4f4, 0x000a85d005921b83, 0x0001143565e32ad9, 0x000d0e9c2f56297f, 0x00009e435672493a }}, {{ 0x000a3e7d01e42a4d, 0x000c021bfe50e2b2, 0x0000b78170df66dc, 0x00081fde07ef8cfd, 0x00003567a5d00f46 }, { 0x00087981154ff114, 0x00063ece38d9d1cc, 0x000dd3e3acce4961, 0x0004b94c9b500249, 0x0000c4108a4b0ba1 }}, {{ 0x0005187a5a610468, 0x000aa5dec3f1dec5, 0x00003bf8fe7fb8e1, 0x00045ff3807b1f04, 0x000027e52acc802f }, { 0x0000c3db2b856872, 0x000d522eb329d415, 0x000ea0acd8667267, 0x000318628f449099, 0x00009931d6113e45 }}, {{ 0x000842a93785dba6, 0x000d1843757b3927, 0x000d31f9f72363de, 0x00009edd4326caef, 0x00004a867e26046c }, { 0x000d01979080ff2e, 0x00091965f96b10d1, 0x0005e9a735756595, 0x000f199fc373a9df, 0x0000befd7ab4c167 }}, {{ 0x000fc047a72b6bf5, 0x000e3585499fb325, 0x000917e8670fd4f8, 0x0009cf9c57b67bad, 0x0000c3e8ea66d001 }, { 0x000b687b7d967ef6, 0x000db59e54a64bb8, 0x000b38cc1c666ef8, 0x000616a8d8862201, 0x000029b881c8aa96 }}, {{ 0x000ca73dcaf21a68, 0x0006b678b2ecfa91, 0x000d8c64fe6d7cba, 0x000cb5c2b24dfe62, 0x00006a76f958454d }, { 0x000efc172f16fa07, 0x00031b776bb87ad6, 0x000b8346a0f01ef6, 0x0000389cd674976a, 0x0000c0f729ce4f9a }}, {{ 0x000f232b5f42ffb1, 0x000059b92222f1f5, 0x000a0dd48310f507, 0x0005266ee5a2459c, 0x00000b4b667c3d65 }, { 0x000bd63ba4fde95d, 0x000e1c548e9e5167, 0x0006b5c1af8c6824, 0x000136d23124b4e4, 0x0000f392b3ec6ead }}, {{ 0x0003122eee899cef, 0x000e8cc290a7f4fc, 0x000d3f748573265d, 0x0000718af6b409c9, 0x0000611f3640b176 }, { 0x0006bba5dab0844e, 0x00050504ef24d7e7, 0x0003c76eb236673b, 0x0000be0015d92979, 0x00002b8b64708c52 }}, {{ 0x00078e66aa656cc6, 0x000a09cda94951ec, 0x000c9f2a6d6e848c, 0x0006760a44b6af58, 0x0000d198106fc9b2 }, { 0x00085099b31bdc5f, 0x00061834a53b9649, 0x0008670f897ce93a, 0x000e96997fc659d3, 0x0000918e4123a93c }}, {{ 0x000954ac9501ff4f, 0x0004ffcc52fc2384, 0x0008216d2daa041e, 0x00084af08712b272, 0x00008cb41023b490 }, { 0x0004ccdbf9cf67dd, 0x000d0a47fb2e74f1, 0x000ea3cc4ab6b658, 0x00069d25bee8ba98, 0x0000589f94d48354 }}, {{ 0x0009c15b35bafc8c, 0x000bc1b7bfe71786, 0x000dfb7efd32fb77, 0x0008ffa7d4e1deba, 0x00001f575658ec09 }, { 0x000e07633366d529, 0x000ed66368710884, 0x000cc4194ecbd474, 0x00068764de5e29f5, 0x0000a864508101bc }}, }, { /* digit=10 (1,2,..,64)*(2^{70})*G */ {{ 0x000ff71880242404, 0x000f1c7a3e6fced0, 0x0005e468a56ae92f, 0x0000f9670e8cbbdd, 0x0000020c88ed5eef }, { 0x000f9526f1333efc, 0x0008b74bd70437a2, 0x00018a76b379190f, 0x0004cd66e5fb3289, 0x0000132085c0e1be }}, {{ 0x000edc4d24ff34d2, 0x0005e5192c4d6840, 0x00056736a2a84199, 0x00067dc208b04d72, 0x000091aa355f1170 }, { 0x0000b62c6dbea762, 0x00084bf854279005, 0x00058b53b37ca64b, 0x000f4906c3de8129, 0x000017420c7a1978 }}, {{ 0x000c11118ac1c9dd, 0x00006b4c72dfe67a, 0x0005e4d08e55132f, 0x00049e035c416b0f, 0x0000282e71d5028a }, { 0x0004097747951cdc, 0x000c718f00628413, 0x000f55e9dfad607b, 0x000fa9e0cbfe0602, 0x00007edbf6c8369a }}, {{ 0x0004645d0c999206, 0x000f55ed005832ae, 0x000aac9fd1427420, 0x000def2ca5f5efd3, 0x0000d8417da6ba53 }, { 0x00015bfe3a91ab48, 0x000ad8bc9001d1f8, 0x000bccb573cb03eb, 0x000ed588452c8f0b, 0x0000190d99ea9851 }}, {{ 0x0000b35e6bb694d2, 0x000723f23885e5fd, 0x0009178fdc3fe150, 0x000401404f72f8f9, 0x00006aa2e224e92e }, { 0x000c8b1a1eb06618, 0x00088489164722d3, 0x000b4beb04a9a74c, 0x0004220323e3c665, 0x000059dfb811788d }}, {{ 0x00086a67d771ac98, 0x00014e654317cac3, 0x000919ad09dbd2eb, 0x0003350b8be600ab, 0x0000e6ed7070c73f }, { 0x0003ebd5c9545d9c, 0x000f18d4431cc288, 0x00021471ef5ad0f6, 0x000672232a7cff14, 0x0000aa1dd2bbd83f }}, {{ 0x000fd169fdcd85cc, 0x000b4a7b1fd2b0bc, 0x00058c1ac9eaecb4, 0x000ee73b39b3ad39, 0x0000f7b13aef63ab }, { 0x0007e6961db7503a, 0x0005fd79ce0a6af4, 0x00019c46a9db1c64, 0x00073a7b255dc1cf, 0x0000917465424f0f }}, {{ 0x000f6928ec987520, 0x0001acce548b37b2, 0x0002556adc5cbc76, 0x000befb4fb38e754, 0x0000e6f549a164e2 }, { 0x000cbaf6791e178f, 0x000242386ce6c413, 0x0004d3f2b753e67f, 0x0009e6bf901be1c5, 0x0000fea1ab006e2d }}, {{ 0x0003452936f20eda, 0x000474550ca42470, 0x000ae49807739ac2, 0x000811424ba1aa47, 0x00001f1e4b8ebaf3 }, { 0x000ac86d5bc8d43a, 0x0000181243aea965, 0x000ebafb6389c308, 0x000c049619a2919a, 0x00002b0cb20d9047 }}, {{ 0x000f1bcbbb3db35c, 0x0007d18c36cf4406, 0x00075a1da5e1badf, 0x0006e2f64aed3e83, 0x0000987f12991782 }, { 0x00022fe40b1a2d46, 0x00090ed60919b8eb, 0x0000d89215e03057, 0x000a894efd890079, 0x0000d06046a39ef3 }}, {{ 0x000d57eb5760d1c2, 0x00099a2157f2db33, 0x000f50d0df45370f, 0x000e83254bda2fc8, 0x000085807ee44cd6 }, { 0x00038f14b932ce60, 0x0008ba2fb5ee9973, 0x0002ad862411b6e7, 0x00064197401648ca, 0x00007031fac23dc3 }}, {{ 0x000afcbcddc5b4e3, 0x0003f6ad7ab9a2d8, 0x000cf2fe2c7a8c98, 0x0009cf5c29c00090, 0x00000a465e1b5bc1 }, { 0x00039efc04140b7d, 0x000aa29e99d043b6, 0x000b4b1d9836432d, 0x0007aac35ef51263, 0x00007f50574f8f0c }}, {{ 0x0007b58f4a281850, 0x00004b366b4be7ad, 0x000dacedead3f7c8, 0x000bf0cd93f25a9d, 0x0000ff4401b26350 }, { 0x0006a8e2b1dfd7fe, 0x000fba9ff563436b, 0x000932066f358f9c, 0x0001181ecf718ff2, 0x0000bb7b63ee6136 }}, {{ 0x0001fe1782b8ceeb, 0x0004fa8327720c15, 0x0002680b1545ef26, 0x000a5814d956ca32, 0x000014f5d4a9c76f }, { 0x0007ab1de209b63f, 0x000f5db3c832c80a, 0x000bc5f7c5d2c7e4, 0x0005a0dcc60dccc5, 0x0000de8668f74c00 }}, {{ 0x000686123db19be9, 0x000c50b3893d123d, 0x0002dad8d4df00f7, 0x0000d5d8bf7b7578, 0x00008135b99cd691 }, { 0x000b6a20e86bb9c5, 0x000a391a7ab4116f, 0x0007a97c837120a7, 0x0002c35d76fcd72c, 0x0000531c7135280c }}, {{ 0x0003b25760e88423, 0x0009b7d341d81dcf, 0x00083e622c18ffb5, 0x0007e4badcddb688, 0x0000becf33dd410e }, { 0x0009a60cc895ade5, 0x000e3f6a7a73ae65, 0x000e082fa7baab21, 0x000f729bc83879a5, 0x0000c301b48a24ab }}, {{ 0x0007d6af9dfc33c4, 0x000f9ceb18762621, 0x000ffad89f4b1f3f, 0x0003a59072b0d79e, 0x0000cd702c4f6dd8 }, { 0x00002614f15b98f8, 0x0000c616d7364517, 0x0006e68aaa6917b9, 0x00000a39d43cbbd9, 0x0000899bf61d6a7a }}, {{ 0x0006dedaf4a7ec4d, 0x000a31a59c3e9f87, 0x0007578c622162c1, 0x000f162ad40200e7, 0x0000d60b302fdf36 }, { 0x0007b6a2e807e456, 0x0002a7c4bc2e88f8, 0x00008cb732bd420b, 0x000a903e96ba8129, 0x00003121d1ba9275 }}, {{ 0x000582b557d8da3c, 0x0005d971b4e598eb, 0x000e517b95c5fc8d, 0x000d82bc5f499ef1, 0x0000275cd05a5723 }, { 0x000af53901d82522, 0x00090ca1715cb07e, 0x0001998aeb1b5a8e, 0x00031fccd4c3de6a, 0x0000aa50e5e8ebf3 }}, {{ 0x000f2386acf8a72d, 0x000604ac3b819900, 0x00028ee94251e622, 0x0000cfab91cb8372, 0x000019e78eaae4da }, { 0x000f8063ac90f7e0, 0x0006d1eb32912137, 0x000dda25c7380214, 0x00046a9e3a2f82b2, 0x00002b889ab4a768 }}, {{ 0x000586ef16cc6afe, 0x000b76759ad2877c, 0x0001d2ded83e32a3, 0x000039c846f45464, 0x0000d9ede27f0357 }, { 0x0000d0e5fc379cde, 0x000d8e024bafad93, 0x00023409aa6e07c5, 0x0009598a0c8b42bd, 0x00004ed05a16b8a2 }}, {{ 0x00086b599a8c25a4, 0x00086e1e8b4dfd4f, 0x00068a9672118f45, 0x0000495acd754d5c, 0x000052f9c3c08e85 }, { 0x00027d16d7f92149, 0x00095a799f9d5812, 0x0008a07de7d22da8, 0x00003bca50473b1a, 0x0000faeb0de17d42 }}, {{ 0x000721dfee849503, 0x000f43cad3d97f9a, 0x000477f19466ae81, 0x000004b7c52bf3bb, 0x0000ff72b1d2fc85 }, { 0x0004e7ef4acdcc1e, 0x0007a21141d4579b, 0x000bf553e4eae6c6, 0x0002e42153411321, 0x000058c897845f4a }}, {{ 0x000a78b173431ac6, 0x000037c593710000, 0x000074fceaa51d30, 0x000c0a565e1c48c7, 0x0000087805015262 }, { 0x00044c6adeb5098c, 0x000f59dbcc8ad945, 0x0006844fc921b6d7, 0x000aaf80a70dc04f, 0x00009ea6e278d5f1 }}, {{ 0x00018b6ba74db2c9, 0x000294e907a544b9, 0x000a9fb236691c4e, 0x00031d04ba7520dc, 0x000017babaf8cdc4 }, { 0x000818ebab294990, 0x00050fc644be8924, 0x0006b5968097aa9c, 0x0001283fe707a981, 0x0000f54144f9bcc8 }}, {{ 0x000a2e6ab0d7e737, 0x0009cad58d2f767a, 0x000d2db95cc250c3, 0x000c89598dc5267f, 0x0000fb76d298d7eb }, { 0x000b5ae1ce39226a, 0x0008204d0c63eaaf, 0x00041ea4c6649b4d, 0x00017f91fa1cb92c, 0x000080a55559aaab }}, {{ 0x000d96332d46ecf1, 0x0000a906e77de048, 0x000062d7886a21c8, 0x0002acf1d7992bcf, 0x00002e42c527e67d }, { 0x000072690f62575b, 0x0006e3a413aa2b94, 0x0005bc265f962dd8, 0x00007b63799a4d91, 0x00009074a785f7f4 }}, {{ 0x000cf86624af5d13, 0x000f4cf02ff6072b, 0x0008cde126b78788, 0x000985309a47d2ca, 0x0000c4b1abc9fa46 }, { 0x00028fb8b07c6947, 0x000bf87aa9e5cb6d, 0x000144b063bc3aa2, 0x0003ccd35c98124f, 0x0000562b62f1af58 }}, {{ 0x00050467db792ce5, 0x000972a40c251f81, 0x00078dd5dce34079, 0x0006e6f2388cd5d8, 0x00009ca7a668bb67 }, { 0x000b3e67f86537e5, 0x000f9bbcdabb8397, 0x0002764532467c29, 0x000f53b2ba79e974, 0x00008ea58750c9ff }}, {{ 0x00068bd1f9103bc2, 0x000158fb1cb6ac9d, 0x000df3913b4c4a6a, 0x00069fd95ffa13e8, 0x000056704285e41b }, { 0x000990a0579bee8e, 0x000f8f926d783f2c, 0x000332aa0f6a131e, 0x0008f1b7c543a59b, 0x00009d122d6f7adf }}, {{ 0x0006ba4245768c48, 0x0002db8519cce2c4, 0x000f6759961dc7db, 0x00035185cfc9af71, 0x00002da71c5029d1 }, { 0x0009e5918edc1491, 0x0005da4d3fd524d4, 0x000123fc1b33c45b, 0x000399a421e72464, 0x0000b38767166257 }}, {{ 0x000915ee22d46e27, 0x00009b665c7322db, 0x0000faabc5d86f27, 0x00004cf85cf12cc0, 0x00003fe2633a632d }, { 0x0000a1c1ed8106c2, 0x0002e3ba317db248, 0x000897173dd719f7, 0x000cd0e5087dec65, 0x0000d47fab598e63 }}, {{ 0x000caeecf58691f9, 0x000319678bf030ed, 0x000973a71452fdfe, 0x000a42b26fb5e9c9, 0x0000351791169cdc }, { 0x0008168ffbb6faf1, 0x00096bb518d0c6b1, 0x0002b381cba209dd, 0x00080d2819918115, 0x0000fd4bfcc99d38 }}, {{ 0x00083365828a1975, 0x00058aa2502753c1, 0x0006390d16bf0feb, 0x0001befe5bb279e2, 0x0000995cb1132868 }, { 0x000733edbe3a75bd, 0x000fbc4eb8098772, 0x000dc2da79704c0e, 0x000789b67b336e18, 0x00009002f7d131fa }}, {{ 0x000791f21653a4b0, 0x000d09a26025c3c4, 0x00064bbeed725db9, 0x0005e4d8ee6e981a, 0x0000b19e4a202131 }, { 0x000266ff7fb4c307, 0x000608925f02425c, 0x0003b83044c40262, 0x0007ec552ec86319, 0x0000716e68f00346 }}, {{ 0x000c27ebc50428fd, 0x000abc3017025f39, 0x000c5f6d8def3924, 0x0000e19ecefcf628, 0x000032c44e11511b }, { 0x0005c3dffed38017, 0x000f7a11da1767e7, 0x0001d13c6c588b39, 0x000a35cb7fe15145, 0x0000aa988aa4f7b8 }}, {{ 0x0009889769d0f731, 0x000f973ddc925fcd, 0x000055dd56a16ccb, 0x000258eebb679c84, 0x00009268c8cc2b74 }, { 0x00097b2662417e26, 0x000a87fb28ad2470, 0x0003f70e2717aaa2, 0x000e018a7e99146c, 0x000093a9487d1a5d }}, {{ 0x0003e3172fc44d4d, 0x0001de6cf9f82a81, 0x00092fac300b1732, 0x000eb09c3319decb, 0x00004b56a4e95663 }, { 0x0006f61f75789888, 0x00070dc7d5a006c0, 0x00066f0587dcb0c1, 0x00029a49e2dbc27c, 0x00002832c4e33d0f }}, {{ 0x0005c14ee801bced, 0x000cc7104779ce2a, 0x000164ec7c3519ae, 0x000edc5d5aca8381, 0x0000fa85767ed4ac }, { 0x000ab6c37ae9b82f, 0x0009683f17a62c70, 0x000c0c80967bc048, 0x00011798f39eb962, 0x0000d8fded0d599d }}, {{ 0x0001e7018d266862, 0x000e5dba28a0749b, 0x00063c6a8fd87c38, 0x00018a515246c20d, 0x000045c4ea3224ad }, { 0x0003ddb70877d76c, 0x00045faf380ff628, 0x000d6fed75158c1e, 0x000ba3bdaef7fb1d, 0x000069deaeeea084 }}, {{ 0x0005f83f869b4f81, 0x0006111fe7df7a4b, 0x000150472fba2a01, 0x00027069ca7cd07f, 0x000060963577ae8e }, { 0x000e155d967e0f8b, 0x000475ef3d8ac3d1, 0x000f446c416bd09a, 0x000e51a646fe2066, 0x000079aaace72c50 }}, {{ 0x0005c34d6e4e9113, 0x0008e9bc3a72d004, 0x000b3f5075acc01f, 0x0003533374037665, 0x0000a738807c50b6 }, { 0x000a94ea00049bb0, 0x000310ff01fd7967, 0x000183a17db85256, 0x0008620c04dfb810, 0x0000ab6af468538b }}, {{ 0x000fa6b43cf5d930, 0x00080d9bb9aa8822, 0x0005bc5f48d33762, 0x00043764eea20e4e, 0x0000fab3b1672224 }, { 0x00016dd2c48181ee, 0x000f5cf3aa91121f, 0x000948c634d733f5, 0x0005e41c08c6bd5e, 0x0000bc67f9d574df }}, {{ 0x0003b606436178b1, 0x000c5d980101b980, 0x000db479092353f9, 0x0004b3ef3760883f, 0x000083e79a8931ea }, { 0x0007ca7221dd1d3e, 0x00015dfe05beeac9, 0x00022468b3abf051, 0x00031c5c3f2f1e86, 0x00003d226244ff9a }}, {{ 0x0002738eddf0b5e3, 0x00087fe1cd19f723, 0x000cbf106d0d6957, 0x000765d3ca20915d, 0x0000205e1c9f6292 }, { 0x00018be236919468, 0x000b5f6b5eccf1aa, 0x0001872fffb9b505, 0x0007994934b5aff4, 0x00005e213e2348c5 }}, {{ 0x000cecf93e151784, 0x0008bbab00ed3a95, 0x000416e0ff80909b, 0x000ade39734c6137, 0x00001fe486ea0896 }, { 0x0002d754720a1bc6, 0x000f841a968fbf0c, 0x000257852acb7321, 0x0006be3c7d23d458, 0x00003c39d3db2eb6 }}, {{ 0x000b84a8eb836754, 0x0004b4a4eb732ec8, 0x000d2645c301b385, 0x000de24926c943bb, 0x0000f1ce27e0f66e }, { 0x0004a527b9540d18, 0x00054d32499dd5f3, 0x000dda2b269e8c86, 0x00023459d12053d7, 0x00005b6b44f0bd90 }}, {{ 0x000c957990ece73d, 0x0000df09cec46eaa, 0x0000b8f62236fab3, 0x000c7f275b15347a, 0x0000c5ac243cde48 }, { 0x000f0546734a7a95, 0x00048a3c33a655d3, 0x000e494c042fdbef, 0x000d948415d503c2, 0x0000ebeb1661c3ec }}, {{ 0x000222b6eb506da1, 0x000b577496125bd4, 0x0007f55249816eaa, 0x00095d799fb0023c, 0x0000430859f143e9 }, { 0x000dfb4f419b49b7, 0x000a7767866d25a6, 0x0007da3c5b2da294, 0x000a816b8b6eb04f, 0x00007d8063c0d891 }}, {{ 0x000b45f1f50f92af, 0x0008fa448ee1f3a5, 0x0006aa5cbde06eff, 0x000579a489604d9f, 0x000024726a073e31 }, { 0x00065f33c2e91ce3, 0x000a0764acc757ed, 0x00078d775c347692, 0x000f15d4ba7cf9ab, 0x0000a19d93dea6f5 }}, {{ 0x00095867f0c050ab, 0x0003315a377b14ed, 0x000ab4e18e1c0315, 0x00095d6486bf5463, 0x00009848fb503c6c }, { 0x000d4e25b124b432, 0x000d044ef5ab0172, 0x00011d673761aee5, 0x000af5f690bd2d8c, 0x00003bc0b64a021c }}, {{ 0x000ab18bf1911b77, 0x0003cb5e224c5d71, 0x000c4dafdd27e4f1, 0x000f8ae52fa3baf8, 0x0000e716268c21fb }, { 0x000e9459a90edef4, 0x000013e9bdf25ddf, 0x0002ccd877ab4708, 0x000099c8004cc0bf, 0x00006969a689a087 }}, {{ 0x000150ff364d5f18, 0x00071cacce9bb324, 0x0001b68d834f5fce, 0x000f2a54bddea65e, 0x0000dd6efba4ff65 }, { 0x000d6aaf6a6490d4, 0x000f401345f4e475, 0x0000c2cf77022252, 0x000ca4b133bf21f7, 0x0000818207356a20 }}, {{ 0x000e990b48335965, 0x000ade1813d28f11, 0x000d5c3e99daeab5, 0x000eb3c7b6000e11, 0x000048dc9938a793 }, { 0x000bccfa65f60763, 0x00077ee93e976d58, 0x0000ba9412fd72f6, 0x000367788696241d, 0x0000ac1c3f505d93 }}, {{ 0x0007de5f15b7c4ec, 0x00039b4c5cd14112, 0x0002d757f99bfdcf, 0x000bfe393701b404, 0x00007673cbf8b48f }, { 0x000d5487494f9df8, 0x000d7cef8d53f19f, 0x0000a6b5ebc3fb1b, 0x00050128addb1031, 0x0000e5c1f0ad87ff }}, {{ 0x00098a932a972998, 0x000cb16a8123ef0f, 0x0003ee6ec10db2ac, 0x00074e05473c32db, 0x000030cbcdd6de76 }, { 0x0004ed4bc54db179, 0x000c3f60c6aa20a6, 0x0004103a4fed7821, 0x00098fa079a32ba1, 0x00008266f6300629 }}, {{ 0x0002377007b82c41, 0x000d906d4caed0d9, 0x000684e5b2ac09e2, 0x0000627d7b802140, 0x00002dfa1b9afd19 }, { 0x000deb5a5140a60f, 0x000bcc371f21a855, 0x000a9a380f69015e, 0x0002249f918461b7, 0x0000baa37b31dfff }}, {{ 0x00024176970787f9, 0x000a446d5eea89e7, 0x0003960208b4ce0d, 0x000762c4ffdff842, 0x0000b88756f44d35 }, { 0x000fc0da3195c361, 0x00027b9102cae3e6, 0x000d81d583cdc7bf, 0x000b577472d143e3, 0x00006226cc2a450a }}, {{ 0x00019f54522deaac, 0x0003edfe45083a2c, 0x00079cbbf77b74d0, 0x00060e27f66bc721, 0x0000bc98cdbbf0a2 }, { 0x000fb17de31b650e, 0x0001e495b7eeed57, 0x000cfaf861be44b3, 0x000d376add9954ec, 0x0000243fb73909ab }}, {{ 0x0007b8aeb5cd1941, 0x00023c5abb020e8c, 0x0003520c40119c32, 0x0002e52e53d18c18, 0x00009ba1a706394f }, { 0x000fe115bb0b6f18, 0x000b243f0f8c16bb, 0x000c16989d3b2f32, 0x00032edc9224ed5e, 0x00004558e4f0f44a }}, {{ 0x0001277b7939f433, 0x000d5493927f4fec, 0x0003b4732c4c5df1, 0x000f4d751f91fbf9, 0x00009c1127aef031 }, { 0x000ec971f4c96c45, 0x000206ee7a759524, 0x000043c434006fef, 0x00038004f00df7de, 0x0000b58465048083 }}, {{ 0x0000d60da1b917d4, 0x000f107e75d9ccc5, 0x0009ecf2f5648cab, 0x0009c77dc63b7be8, 0x000043a02262c4a4 }, { 0x00017f5de960c25a, 0x0000bee08df1b120, 0x00097e712bf60ed9, 0x00025a73d3873487, 0x0000b1fb76167cdf }}, {{ 0x0005d84aa3afdbbf, 0x000b966e8e575672, 0x000ed4249074932b, 0x000372274c9f781c, 0x0000cdc2169236eb }, { 0x0007c4b46d4fac70, 0x0002e094d0c0ce2b, 0x000adafa0737f634, 0x000c614c71564008, 0x0000178fd068c458 }}, {{ 0x0002aabc59c94f12, 0x00095b397acf4ec2, 0x00003bfdf9e674d3, 0x0004780850426c40, 0x0000ca04d6eb4c85 }, { 0x0006908d03fd22f0, 0x000814c5f5942bc4, 0x000db3a0f5e9bc06, 0x0001e62ba9a6168b, 0x00006bd8a9096113 }}, }, { /* digit=11 (1,2,..,64)*(2^{77})*G */ {{ 0x00009d21104a01b4, 0x00024745a1251fb6, 0x0008668a04b75ff4, 0x000fe349e967747a, 0x00006e02c0c6d4e7 }, { 0x000084a333d89913, 0x00059a82fe122271, 0x0005f3a1a369f264, 0x000fa053caf9b5b9, 0x000022f6b350187d }}, {{ 0x00048ff65b341317, 0x0008233aed1d1f71, 0x00033bc63a356251, 0x0001b22cf566eaff, 0x00007f53d3789579 }, { 0x00086fa303582c2a, 0x0005fd4cf94cf0dc, 0x0003899cb5afac02, 0x00035800d319bec8, 0x0000afb9e2fd22fb }}, {{ 0x000f31d817bed07d, 0x00055ab5c8b06d5c, 0x00022f1cd42f3db3, 0x0009efa79b1a785a, 0x00001ca931baa4c5 }, { 0x000b66d8a740682e, 0x000d06a15d7dc85d, 0x0003d89a928be329, 0x000b486c72f132b0, 0x0000478e55d53bd7 }}, {{ 0x000e23139482dcb9, 0x0001ee1adc1696fc, 0x00023caa5f3be88a, 0x0003ebb3598ebe59, 0x0000801aabeabc49 }, { 0x000560a9c8a8fda0, 0x00082d4db067df91, 0x0005b59ef1377a4c, 0x0000329c198dda09, 0x00005daf596bd7b8 }}, {{ 0x000029268430e2db, 0x000923e99e0925f5, 0x000612f910d69e1d, 0x000881aba2dd74a9, 0x000075a644f8e684 }, { 0x000b66a21626e638, 0x00014b41aeaffa32, 0x000f702ee5abbbdd, 0x000eafd0c8b17203, 0x00001a68d527f1c3 }}, {{ 0x00089de4e0f889d4, 0x0005e5efe51bf748, 0x000dd5a81bb30fc6, 0x000505b259c4f579, 0x000013cc73a8497e }, { 0x00057568b82d7835, 0x000b706646083ce7, 0x00054a6bbebb3b88, 0x000bc0c10be2a033, 0x0000d865d4a67d97 }}, {{ 0x000e11a1d8d399bf, 0x000d87900f7e6c85, 0x000eb19b3117a1bb, 0x00064247538e8b94, 0x0000d5742a10d630 }, { 0x0007b6a724c5c32f, 0x000812ec1e2f2ef2, 0x000b9e4effa0ede3, 0x000d6dc2d193d2bb, 0x00006ad06c86c96d }}, {{ 0x00064232b86345c6, 0x000491cf1c367cab, 0x000b12cd89c580bf, 0x0005b4a329bc85a9, 0x000061507757ea7e }, { 0x0007fbd8ddb9611c, 0x00062b0167dad297, 0x00011cbbb1d53bf6, 0x000c8188b1604f30, 0x00001f4d0fd7d22e }}, {{ 0x000307a8c0590774, 0x0009aa5b964e39a7, 0x000c5dcc1eae81ad, 0x000c9a564d4c29e3, 0x0000ef66dab1bbfd }, { 0x000139e05cf3cde4, 0x000ddaa91708c3b5, 0x000bd7852e8e71ed, 0x000d569b7a151e62, 0x0000050f4937247b }}, {{ 0x0001e893a8e9fd20, 0x00031b494a7cd2e1, 0x0000f4b09fc385f9, 0x0009d696a5671ffd, 0x00009847745f23ad }, { 0x00023ac856040d5f, 0x000a7a165cf7b104, 0x000882d2bc2f947b, 0x0002854de81b6717, 0x0000ef3de081df86 }}, {{ 0x000b2c9190e12088, 0x0008587dac50b74b, 0x000e9d3ce1bbce37, 0x0002da0fb28b2b89, 0x0000cabf97afa5a6 }, { 0x000f9f3f579f2fc2, 0x000a71884a9d5b7c, 0x0004aed7c41c7a6f, 0x000092de27ebe232, 0x000029c3d363af68 }}, {{ 0x000aec5d6d717771, 0x000f8e1096187086, 0x000456979c440027, 0x000f2b0afcc9e836, 0x00008cf2ab4e27c4 }, { 0x00007dfe122baae8, 0x0000f8a994f04e95, 0x0007d694479ec283, 0x00039574fb39ccae, 0x0000aa93a28e976c }}, {{ 0x000a7d33d6e39217, 0x0006acb489b03e9c, 0x000aa446e1236c2d, 0x0008923e5db86ec5, 0x0000d513e9282311 }, { 0x000832e75dca4e42, 0x000ed5c0ae6c4d0e, 0x000d8b63ae0adf74, 0x00059047ea9ca1d1, 0x0000237a1f96d350 }}, {{ 0x000170458c664431, 0x00049ea5232123db, 0x000bb43e414ecb07, 0x0000237ed08307c8, 0x0000c4bbbb01d044 }, { 0x000c7f7317b92a8f, 0x000afc6c19bb9866, 0x0006418391d59403, 0x000750822c5f3484, 0x000021de21b188b3 }}, {{ 0x00068d834bef31c4, 0x000d00e9d6d2e8b4, 0x00010e11f94b7363, 0x0003f7485d318b8c, 0x000049cae972b8a8 }, { 0x000b12c61b315467, 0x0007eb2bfba796e0, 0x000b625f2afba6cb, 0x000620753152364d, 0x0000ade1ce1d3e84 }}, {{ 0x000eb572d99661c4, 0x0008402fcf0a7fd8, 0x0008c5d33d449b8f, 0x000f0f09842fd078, 0x0000da7983de9402 }, { 0x00076f6bdb01f785, 0x0001f4c4d194a88b, 0x00090292128bdeab, 0x0009129fcd2b63fd, 0x0000ebc377dfedf6 }}, {{ 0x000ba4521833ac99, 0x000984bb46c2397b, 0x0005a248d600e4d2, 0x000c9b434004cf56, 0x00002121f29dec04 }, { 0x00078cd8c6df3a54, 0x000f1711171121e1, 0x0001d03cddaa270c, 0x000d52107ad7b7eb, 0x000098a27d377993 }}, {{ 0x0008ca59bbd2a43f, 0x000a201b2a672385, 0x000756d1bb36ec67, 0x000c1e1753556d36, 0x0000c58a255d75d2 }, { 0x000aed0cd5454528, 0x0002b92a569a73b1, 0x00083babe9f4067f, 0x00068af55517a52e, 0x000059afbc58d069 }}, {{ 0x000c3323e86fa8e0, 0x0001f8480af13722, 0x0003c58739374a0c, 0x00050ad31244c311, 0x0000126dd368d686 }, { 0x000979d546fc2f7c, 0x0002f4a5594b1dd8, 0x000b453aa4371b74, 0x00058ee19a1928bf, 0x0000915af098fee8 }}, {{ 0x00033084d9c7276b, 0x000bbbc19f9e9676, 0x000285cb3a74d9cf, 0x000491240d9d0315, 0x0000ba33cddb43f0 }, { 0x000d408f6f73b28c, 0x00010dc55667eaf7, 0x000ab10446007a1b, 0x000e39f1473b7f92, 0x00002ef1a03646da }}, {{ 0x000103f6bba1307c, 0x000d1dc164a89bb6, 0x0001ddefc64a2b32, 0x0005d70bb74a42bb, 0x00005152ad60f6a1 }, { 0x000e4781a0271b2b, 0x000ca81355a5752f, 0x0007024ce4d4d310, 0x00084f73b562f96a, 0x0000c477204acd46 }}, {{ 0x0000757b5f4712e4, 0x0004c75f8dfcf8a2, 0x000a74f11cc657d7, 0x0006a5bd8a284f0a, 0x00007dda9a0af13f }, { 0x0002a3e7718f7a6e, 0x000d22093b8a5ded, 0x0009191c86356347, 0x000f92e33d3f9335, 0x000055ce4eafcd22 }}, {{ 0x000c17e23aa997b3, 0x00096f4cd941534e, 0x000af7af39d3fdd7, 0x0000044e30d37406, 0x000017d4ad645c92 }, { 0x00052737e78e08ec, 0x00019516f496ba27, 0x0001c18619005520, 0x000df03f56a69317, 0x0000b6ddc6edbaf5 }}, {{ 0x0009a1904af269a5, 0x000ee2c68af43eec, 0x000da69b7072b08d, 0x00046bcf55502468, 0x0000f80ea4ac443d }, { 0x000a17081f1c5679, 0x000da8d470c56a4f, 0x000e1f2684ceb758, 0x000ba15f3159abc5, 0x0000964c76954003 }}, {{ 0x0008102033e8adcd, 0x0002e2b10c8c0f59, 0x0009a854e5133f03, 0x00015f2a72102c3e, 0x0000c9a9e311aba2 }, { 0x0007a89342969c71, 0x000f33ff1d18a13b, 0x00012053c7add2ec, 0x0004e3ed835eebd9, 0x0000d9e680e72864 }}, {{ 0x000ce7c67c39f8eb, 0x000838decf2a73a0, 0x0007816d5317f027, 0x0009468a2066a639, 0x000026677b2d0e7f }, { 0x0005a428ef86e036, 0x0009071759a113ce, 0x000269cb3f0ac1ee, 0x000563c7be3b373d, 0x00006ff591e18a76 }}, {{ 0x000b6b40b404a661, 0x0007ac81c86682bd, 0x0006dd64ea76b3ad, 0x00015d19ab78d272, 0x0000fbd431bc398a }, { 0x000802739262b87e, 0x000297db8c4961f6, 0x000bb8e36d198176, 0x00030325eb1a12f7, 0x0000129ba25ce217 }}, {{ 0x000c873312835882, 0x000685f16b1bd5e5, 0x000ff15bd7c0e8a6, 0x000dcb99ef957e41, 0x0000fdf280b53be6 }, { 0x000093ef1a573f41, 0x000b88cb65f57cb1, 0x00014d78ee26f748, 0x00048d340db60a62, 0x0000c4ae6cba4b4f }}, {{ 0x0005f9a99adf6ad0, 0x000dfb53f4ece64e, 0x000d900aab7fe12a, 0x000bbe8cd6a6bb02, 0x0000244f4571b32b }, { 0x000cb9c4a0dadc5c, 0x000682511a7de841, 0x0005e0eaa53ce5b2, 0x0009034a28356809, 0x0000d2319e930091 }}, {{ 0x00070b941f431f96, 0x00035babb2eec644, 0x000492f8199f509d, 0x000c8d4c4a0c23b6, 0x0000055b8ea1eb9d }, { 0x00073291adbc3b63, 0x00073799df435742, 0x0008e83346629e9d, 0x000445a814ccfb8a, 0x0000b7b0d75235ee }}, {{ 0x0005efcdfd123b2e, 0x000866b42a92806b, 0x000bf27ae64de389, 0x000d09bf8810684e, 0x000050a1dcc40eb7 }, { 0x00050352364d1ab7, 0x000d2076e9edd128, 0x00004fd440c2c9e1, 0x000e85a6de29d0b5, 0x0000da6c7734e64d }}, {{ 0x000943b9b2fa6dc9, 0x000e0b2b4b4b67c8, 0x00005ebe4c512574, 0x000128fd8c1d10df, 0x00006e0e8ebb49c2 }, { 0x000b34a5656dfc03, 0x000d6143b3def048, 0x0001c1b2d09a22f2, 0x000c08d4085ab3aa, 0x000060432732650d }}, {{ 0x0009efab06795cba, 0x0000f4a10358560e, 0x0001b46c7da3c8a3, 0x0006b31152d8a507, 0x0000637882aff5d3 }, { 0x00020630df6bfbd5, 0x00072a9d19e9b915, 0x0004b06fe46d6faf, 0x00003090d8cfed74, 0x0000ce2f38fbcec1 }}, {{ 0x0004f8e4921219b0, 0x000ef7ce382360f1, 0x000973c673c5135b, 0x0003f246cb6db05c, 0x00000c2638a18b5a }, { 0x000d76ff4b38f5e9, 0x000897a11c203407, 0x000f3205cc6b7d94, 0x000eab1200386f86, 0x000080180ab081c5 }}, {{ 0x00082444682aa7c3, 0x00028e7db15be7ac, 0x0004107abe9a7d16, 0x00071706467a0805, 0x000025b9428d4196 }, { 0x0007714718a7a5d9, 0x000b58b20d841b88, 0x000854475e368b17, 0x0000c2936127a054, 0x000012a411de8dbc }}, {{ 0x000cc20bdfcef420, 0x000aaaaaa8a5288b, 0x0009f26195e97eb7, 0x0002dee0c91cc0c8, 0x00002946f9408a70 }, { 0x0007409503d2975e, 0x000e4daa20ede1b5, 0x000c1d5f70119b97, 0x000b42e4bc441f00, 0x0000a83a9d6eb2a0 }}, {{ 0x0005f1068db22608, 0x0004a61e4585d453, 0x000d3143dfb4ed4d, 0x0004ae66c9231fae, 0x00004c8d8da2e90c }, { 0x00009002a8263ee7, 0x0001200a2d261155, 0x00029e7afc3b45b0, 0x000e539a1649406f, 0x00005414f28a6295 }}, {{ 0x00027abb0cc2f99c, 0x0009aa53ff3571bf, 0x000790fe6cb4f16e, 0x0003a2b1624f98b7, 0x0000a232d3065d82 }, { 0x00072b0da96f4899, 0x000cbfc5c6d5bfd7, 0x000179a26cce6886, 0x000505c346915c75, 0x000008d2131b6918 }}, {{ 0x00071a4c560e39dd, 0x000490c2e03fa69a, 0x000994c7571e040a, 0x000ccdc6036cf0e3, 0x00004bd59ba6dde0 }, { 0x0005e78c885a065c, 0x000b65133c673db2, 0x00004e0134a9208d, 0x000f06b34c0bea51, 0x00008995c776117a }}, {{ 0x000d702cfbe0903e, 0x0006ef88e2f7d902, 0x00074a4e05d17b88, 0x0005b20e9fdbf33d, 0x000010bd286ddbf2 }, { 0x000dd0fd8fb34fd8, 0x00013db85c88ce89, 0x000b8030d8880391, 0x000235bac23a3ce3, 0x0000fa45c03bfea3 }}, {{ 0x00047e2ad1ea2431, 0x0001602b57872b88, 0x000ee0ff350f3dd3, 0x000ab0c402ef26b4, 0x00004bfae875386d }, { 0x000c3fc966771b4f, 0x0008aa009996a74c, 0x000c5de647f65d59, 0x00053fe4316a56ac, 0x00001cad819b5d5a }}, {{ 0x000c2f5e8ebb9875, 0x0006573ce07d1b0c, 0x00018c7de2e97cd3, 0x0008da2f4d82910c, 0x0000fe01b8994111 }, { 0x00085928bcf47e0c, 0x0001950b8c30ccc0, 0x000a12352e9d8df2, 0x0002d88597b856ae, 0x00004ba7a71332bd }}, {{ 0x0001d44d0c939385, 0x0007decba8f4b4d6, 0x00099ee0887ec970, 0x0008ef97ac07cd4b, 0x00007b8f4d37c895 }, { 0x000aa760774d89e6, 0x000f62b135e6f4d6, 0x000b7cecb07896fc, 0x00076a2b5680962e, 0x0000fd88fe58cca3 }}, {{ 0x0008eb579c89ba85, 0x000b8118fb98871c, 0x0002f2dc1362f68b, 0x00025b114cb26f5c, 0x00008a957abc4172 }, { 0x000dfba9354cbe2e, 0x0001e15c93bae41a, 0x000c8cf0fa7d7f42, 0x000606cb146fbae5, 0x0000f605d4ba99c2 }}, {{ 0x000697b7814fba90, 0x0004013f216c980b, 0x0008410654403924, 0x000dd1237c8ac4fb, 0x0000683bbe6245ab }, { 0x00033aad090c72fd, 0x000c939ddb945b56, 0x00077d5a16a024cf, 0x000b36f90447b06c, 0x00004f7703863965 }}, {{ 0x000d40e0825f1a07, 0x0008c6bb57c64779, 0x00044c0cdc444452, 0x000779f7b871f8b6, 0x000076eaaa21e046 }, { 0x00087b30ac366f12, 0x000d8f6f2d84b5af, 0x0008acea8597faa2, 0x00014068b228993f, 0x0000424abfd6e5f6 }}, {{ 0x000ba6b8ef40499b, 0x000f0317642bca8e, 0x000e66d95628781b, 0x00075f9451a032d7, 0x00004159c0acf639 }, { 0x000ec80051301541, 0x0005badd44856928, 0x000dfabee96d2c76, 0x000f8734884bda40, 0x0000d972ba5752fe }}, {{ 0x000be6868dc83e03, 0x0005e0798fa7aaac, 0x0004248d23c0ea74, 0x00098ae9b41209ee, 0x00003cedae7fcc2a }, { 0x0000a5ccc7b9ebec, 0x0005fdc32c04dd3e, 0x000def4916cf5e80, 0x0009ad4cfa6c35fa, 0x0000a98de7d24b36 }}, {{ 0x000b2d7405bd794a, 0x0002eaa1536189f8, 0x000f2f40816c05a9, 0x0001b0c0e1126c55, 0x0000e641bd7bfcf4 }, { 0x0001863ad3cc6a83, 0x000109e3738be712, 0x0009f8c75cd5b817, 0x000f12615b5090b1, 0x00007dbc50add023 }}, {{ 0x0003c1abe2e2289b, 0x0008b79a7aae5d37, 0x000c9a2415e1f025, 0x000dd1b297076013, 0x00009d9bb7e7d7d8 }, { 0x00022100092b6697, 0x0001d22f2488af76, 0x0002041aa56cc46e, 0x0003ffd57e4105d0, 0x00004447fba18228 }}, {{ 0x0000d8ea16b68aca, 0x0008a7877a50ec69, 0x0006795ebd16449a, 0x00056c47abf0392f, 0x0000c5c659818595 }, { 0x00060dbb7c6ed91f, 0x0008393ef953f575, 0x000567b78ade06a9, 0x00077e81790a64d0, 0x00009be345281b73 }}, {{ 0x000d3b3730c3da90, 0x000a2864b66abfb6, 0x0004ebc7d1cf59b3, 0x000aa041ad26f52e, 0x00008875834f1291 }, { 0x0008f625c182ae12, 0x000942f4789dba54, 0x000529bfa3f61d44, 0x000e1880e91fcb81, 0x0000772dfeb7bbe9 }}, {{ 0x0006ee1cad7e490c, 0x000dc011c6219b80, 0x000921be12763c71, 0x00098f988e7a562d, 0x0000ff590f7684a8 }, { 0x0009c6ab4f30f5e0, 0x000ce43faff79f72, 0x00023b683e91a933, 0x000696bd0c141a41, 0x0000472541b41fe8 }}, {{ 0x0009a4a020384d2c, 0x000e87730448112c, 0x00011afee636432e, 0x000e4241082b51af, 0x0000f39a9a8e69f6 }, { 0x000d49d0784959b5, 0x000e0d8257e5818e, 0x000fc707ca9eace4, 0x0004f5bbfdd8efa0, 0x00002149995867c4 }}, {{ 0x0002daa6890484d1, 0x000db5eb7caee1e4, 0x000d651a33cea7b5, 0x000e198b91033898, 0x00002903be868557 }, { 0x000107f8ce029e4d, 0x000745c1a1d885a8, 0x000073af6f495ffe, 0x000f1422825572ec, 0x00005e04a9386799 }}, {{ 0x000fd321053b8bde, 0x00015a36fa6110cc, 0x00012bc0351a15e4, 0x000cb742b74fb1eb, 0x0000cad7c54d4248 }, { 0x000d56251a7ec868, 0x0001ca2cc80ad571, 0x00056953911caea0, 0x0002c80cd7c27fc3, 0x00000a95d3fdd32f }}, {{ 0x0002503375e361ed, 0x000e509c955bef4d, 0x0001345d7cd1281e, 0x0006562eedf02cad, 0x0000ba01e9851b7b }, { 0x000be946c753683b, 0x0003a5edf53cb366, 0x0001c77f0e544309, 0x00037eaa454dcb61, 0x00000c4e558ee575 }}, {{ 0x000541c7c1655fac, 0x0009ad1a995e0941, 0x0006cfdc3d170c39, 0x000be851365e848f, 0x0000c5364d173f04 }, { 0x0000fc20ed612d22, 0x000a7faf4acfade6, 0x0006e3d0ea83ec7d, 0x00024ab770e58589, 0x00005a5480d97ba9 }}, {{ 0x000018f5e5fc5e81, 0x00083eca42768678, 0x000bb4da53ad5c55, 0x000d864bd46f6c3c, 0x00002cc3c22b21c9 }, { 0x0005acc0361b36ae, 0x0007470e47b668f5, 0x000d986831cd85e9, 0x000c8ed4dcef48cc, 0x000012e983797847 }}, {{ 0x000dbf24eccee72c, 0x000e6af64db44442, 0x0004910eaf9370ff, 0x000496b8a19e9d63, 0x00002081b3c75ada }, { 0x00086167eacf78d7, 0x0000c8c2cd706b27, 0x000abd2eafce6c92, 0x000681eae5b012a5, 0x00008d905b32a1a3 }}, {{ 0x0009ad7d324559d4, 0x000b57d594881dc3, 0x0008960aa38fa09f, 0x000f644de6b5efad, 0x000000bdc3e7618f }, { 0x000a309b4ea8cce9, 0x00039e02cfc0e816, 0x00018ca8025c0c84, 0x000981109117c466, 0x00002b74c94f9322 }}, {{ 0x000b6614f982ece8, 0x000b7b7abea49b1e, 0x000c257cb1cc77aa, 0x000c2f67ab4b1d27, 0x00005154e895caa0 }, { 0x000ea5d68b9993ba, 0x000c76b7f6f7459c, 0x000e3a9037efb0c9, 0x00075d74ce431a44, 0x000063571583a729 }}, {{ 0x000102c8a0fb0bfe, 0x000f8653a0a3f957, 0x00060be8d9da3b5c, 0x0006691e98936941, 0x00000313a1550ce9 }, { 0x00067e106b240330, 0x000010e235d21c8d, 0x0000e87d6f10977d, 0x000925a67505e55d, 0x000059ee2e27a5ee }}, {{ 0x0003858b5c81bd3f, 0x000d2a9431dd80e8, 0x0009efaae17d3682, 0x000f67830eb7c7cc, 0x00002f1f3290cd4f }, { 0x000990a639034a2c, 0x000a593b6251d5c7, 0x000299c23319bc02, 0x000b194511cca1fd, 0x00006f501add6b8d }}, }, { /* digit=12 (1,2,..,64)*(2^{84})*G */ {{ 0x0006beb87707b7a2, 0x000c72a87dec0e16, 0x000d90f4e489ddf2, 0x00017feb5010ded8, 0x00009f1c146a514d }, { 0x0002ae989277487f, 0x00076313476cd0e8, 0x00052ddea0b6d98f, 0x000ff20c6a63d0e6, 0x0000d40ea3d516db }}, {{ 0x00019c667d0d91d1, 0x000e8105ca7d8669, 0x0001a93ed4b79dc6, 0x00058efbc582967e, 0x00007205a3aecabf }, { 0x000187f1f85aef05, 0x00012b160f5dcd7b, 0x000f2c42bbc43ffd, 0x0004562f5ec697b9, 0x000026b5000648eb }}, {{ 0x0000d41a77c52336, 0x000441d214aeb181, 0x000c6340187fcbdb, 0x0006e6ac41506af3, 0x00003b6fa4818220 }, { 0x0006bdb65cf1fb29, 0x0003ce4a84bde96b, 0x00083b4cb3bfaea2, 0x0008473e742f060d, 0x0000fba067aea100 }}, {{ 0x000b6c2d46254ea3, 0x00039b6ec7fae9f1, 0x0004d44a4114c60f, 0x000f5ba52995f271, 0x000066e8cbd34843 }, { 0x00062c42a011d210, 0x0000c318129d7161, 0x0000f32c7f0a2090, 0x000229f63b03909f, 0x00009687ec5c5909 }}, {{ 0x000507db0a04df74, 0x000af43753b9371c, 0x00099a17c1cd2a88, 0x00066679629cab45, 0x0000a296edbca1ad }, { 0x000519b397e39c16, 0x000e052af036c326, 0x00079fe7dac46a92, 0x000efcd5086f0cc7, 0x0000bf3f8cd63cc7 }}, {{ 0x00042e43a80c6fad, 0x000b1ef9c053df72, 0x00078ed2a6c7dc5b, 0x000da22fb8de25b3, 0x000063c34563eabb }, { 0x00066648e3f185ac, 0x000a5f4dd6f958ec, 0x000f2dde11a9f374, 0x00087dd496925a77, 0x00007412068d6cf7 }}, {{ 0x00005e399e662c0f, 0x0000a57173e460c5, 0x0004e0120bf24c7f, 0x000f062621bbbce7, 0x0000fbd676e31f74 }, { 0x000bef99ec94a32a, 0x00023cb57797ab7b, 0x0009ae3d0efbd3a0, 0x000900cc160ad35b, 0x00000124b141f449 }}, {{ 0x0007c8bdf49d7f19, 0x0007df31711ebec8, 0x000f46d03fcfcebc, 0x00035281f2da40f1, 0x0000aacf4dcfdeba }, { 0x0004907c5d800621, 0x00068e3c2eef12d5, 0x000ae7e3f5965a34, 0x0000ca494de95bb9, 0x0000c88b84c6fe58 }}, {{ 0x0000c1e7da0cf5f8, 0x000cdf08db60e357, 0x000689c14b3f9c46, 0x000208bc9743e3cd, 0x00005819e16c67eb }, { 0x000b4a07ea1a52ab, 0x0009f39a6be09070, 0x00057b86afe8f489, 0x000d94f6036d4703, 0x0000fe9b7f7d190c }}, {{ 0x0003057bc03a43d5, 0x000782945c1dd539, 0x000790186ff52f5a, 0x0003b2be0cadc589, 0x0000ce868856076d }, { 0x0009d9be5f0800fd, 0x00081cd027a4cd18, 0x00033c3a42bb278a, 0x000667f68114734b, 0x0000ae65c75c585f }}, {{ 0x000361bc67e9e34d, 0x0007e2e089808ef0, 0x000dd23c849fe842, 0x0002e6cc9f1f7a27, 0x0000c13a3157f998 }, { 0x0001b02bc1e235bd, 0x000a00b7f071426a, 0x00004556f9a54850, 0x000360dbd6a3c181, 0x00007d7ec15b5c2b }}, {{ 0x000f7d41e8e79665, 0x000895931fba2393, 0x000359404fe8f948, 0x00083d71df47424d, 0x000023b7a1aa0b1f }, { 0x000ef6eea564a053, 0x000d0c2cf6eb9980, 0x000f51a339da0be5, 0x00028b46286bb49a, 0x0000f0e9d516a3ff }}, {{ 0x000b44589e394e0d, 0x000207236f5defe7, 0x000bdbb538d8261f, 0x0003ed3c7fa9922d, 0x0000fc2a961330be }, { 0x0009acb43064282b, 0x00010ca9ea837700, 0x000f210a61177cf3, 0x000f5b1c0d7fa2c7, 0x00003784b94dc9c5 }}, {{ 0x000028746afacb37, 0x000132e649d4e574, 0x000fd8eede035012, 0x000e913c4cd53a2a, 0x0000887fc8e5c525 }, { 0x000c3ac1b0c48f95, 0x000ee9064291d4c7, 0x0001722017588ca1, 0x00088c181bf48f15, 0x0000f3153a52a8b6 }}, {{ 0x0008e6567629384f, 0x0002ec3c093c171c, 0x00035c0dd4ef3c20, 0x0002147cbae7acb2, 0x000090ba8583656c }, { 0x0009e2f0802b74dd, 0x00042ba28b8d0b1c, 0x0006ecde1a103afc, 0x000ae4d8015d7413, 0x0000a3d25fc46b0e }}, {{ 0x000cadd1a806623b, 0x000e2b6f79588c00, 0x0009a8a99724a1aa, 0x000f2088afa52fc6, 0x0000f705025b0678 }, { 0x0009b5b7e0f923c4, 0x000e2b31803dd6fc, 0x00048c34f654baea, 0x0000a8a16488e4fa, 0x000078ce7289743f }}, {{ 0x000bf0e7f5c451a2, 0x00030d3957626499, 0x00072bbdbc00a6ca, 0x000755696a9604ee, 0x0000c65ea7b931a9 }, { 0x00082e474cddae64, 0x00064217cb44b924, 0x0003667b7a354fe4, 0x000a641fda2f5ce6, 0x0000f36622cc64b3 }}, {{ 0x000c9dd0ef759995, 0x000ddd0b611c24be, 0x0004740b22624bff, 0x00035cf211d468e6, 0x0000807471447a06 }, { 0x0007b4f8f0064eff, 0x000d3bf956c2e32a, 0x00043529005e550a, 0x0009f776573dc686, 0x0000b45bf82931b6 }}, {{ 0x000d2dba29a420a1, 0x00077dd7280f8553, 0x00004e810c5f5788, 0x0001f6e42bbaac26, 0x00000e0aa6d6e58f }, { 0x000163cfe5ae3f65, 0x000b594985093755, 0x000f7d4053e708b7, 0x000c881fb8f33031, 0x0000315d7722ea99 }}, {{ 0x00023d24bafda93d, 0x0005217cf41c6e88, 0x0009813e6da10623, 0x00029057cf1f03c2, 0x00009f3f08321169 }, { 0x000891e4e39dfe78, 0x0001813901f0b4f7, 0x00018002374a94f1, 0x00029912e684360f, 0x0000123427926e8e }}, {{ 0x0007ced2848ab4fb, 0x0004819ac445e3d2, 0x000766d870fcc671, 0x00034ca0a553432e, 0x00004c49d4d2e4dd }, { 0x000df18da1030901, 0x000d2757a4afa571, 0x0003c69333af3c8d, 0x000b49823de0a14c, 0x0000c31b61984a35 }}, {{ 0x00069041a0c93e91, 0x000fe82d8d38a9b9, 0x0000514dd1f04e0f, 0x00082e4dd2e97c60, 0x0000d5f81ee7afd8 }, { 0x000a8b342d40d5ba, 0x000993b76a2086b3, 0x000b9d37b4d18b27, 0x000c84167d6bba71, 0x000006b92014b8c8 }}, {{ 0x000a7dbf4441e65d, 0x0001949522f9be32, 0x000bb4a18a63f9da, 0x0006e8f42690c075, 0x00000b984a4ca3f6 }, { 0x0000aca623b9e392, 0x0006a0e3faf40783, 0x000eae64e0090621, 0x000be25b3b2f02e9, 0x0000a47a4149ebe6 }}, {{ 0x000e79d046d6c0d9, 0x000e60502f40d9ab, 0x00076db7ba07217b, 0x000db4d744681c46, 0x000074b09e5ed137 }, { 0x0005cee5b6dd4217, 0x000310a78bd01e0c, 0x0003acd63802d1dc, 0x0006da3b66dd359e, 0x00004f7a41696b06 }}, {{ 0x000a2e4e3632e762, 0x000ced46ffd9fbbc, 0x00086c97c281ada3, 0x000fb00cf6e5bc69, 0x0000f75bfce3bc69 }, { 0x00075117090a5ff5, 0x0006fc016de36c5e, 0x000c5b91a11ff6bd, 0x00025b5f8e0b10fd, 0x00009f9ba307785c }}, {{ 0x000ff3974d378756, 0x00082fc3b922bf8a, 0x000f9c3619e62f97, 0x000e743c4e4d8c09, 0x0000070f7ed0ec03 }, { 0x0002c29a21b92463, 0x00031052c18df9b0, 0x00038e3dd7174a50, 0x00055a895c5c3a29, 0x00008d20d8ec2e2a }}, {{ 0x000b0838226e8425, 0x000ccd6141ecf611, 0x000e20a9f7315526, 0x00050ee579195509, 0x0000827cd560e1b4 }, { 0x000ee0b7e6ba0f71, 0x000fd35e07289f09, 0x000bcef7b719136d, 0x000002bfa1f94c48, 0x000063e3e9d89c31 }}, {{ 0x000fbe8ff0b58802, 0x000fc2e34d74e31b, 0x000f7c390ac5a4ca, 0x00076e98fa352c30, 0x0000f58dc8de69f6 }, { 0x0001022c67c9035b, 0x000c1e6a79046089, 0x000a33fa75e20d04, 0x000e287001f812f3, 0x00004fd325eb32f0 }}, {{ 0x000f7a6bb4ac623e, 0x0005e5d30a713a1e, 0x000f9574a3df3bdb, 0x00099bb284876e3e, 0x000058865f427515 }, { 0x00067d2e36052baa, 0x000c828dfa2a659d, 0x000801fa7659b2da, 0x00031653fd5cd339, 0x000060ed537958fd }}, {{ 0x0004a96feb09a9c1, 0x00026d7cc5f43941, 0x000c308d71570ea4, 0x000a0e50ab5551b5, 0x0000c0238a0327c9 }, { 0x0009f80382b52a70, 0x0007f740d12bb0b3, 0x000026c163fb98f7, 0x000cd031dc522f02, 0x0000b4064550e478 }}, {{ 0x000c58e2b0841de2, 0x000810c39024a940, 0x00088ad8b1a25b9a, 0x00085a47caacb96a, 0x00007b4e4f38b169 }, { 0x0008ab30080ea35c, 0x00001634da919fac, 0x000a28b2f2812eb1, 0x000e84f10ef79b69, 0x00003e9ab4693571 }}, {{ 0x000c047df2f3ac76, 0x000c2b67c4a658ad, 0x000864e2a38fcd7a, 0x000ec6e4fb3c4763, 0x000051531fb65393 }, { 0x0005e4fd59db390b, 0x000c9c55e59d92d3, 0x0005b30150334900, 0x000919016cedca47, 0x0000584c78dab3ac }}, {{ 0x0006a76dd7489981, 0x0007e18e4bcf6b1a, 0x000482a8ab23b028, 0x000ca4849856d628, 0x0000dfe5317984e9 }, { 0x0000d6fb0302b210, 0x0001334cc7b4f79f, 0x0001159b13471521, 0x00027aed5a1d0312, 0x0000d3bf917b1a7f }}, {{ 0x000739327907285e, 0x000bcd51fb747d2c, 0x000868fa43b278a8, 0x000c7515aab50f95, 0x0000376a6d9ca2f4 }, { 0x00038542d43e54fa, 0x000a8440df6f9be3, 0x000b3e6a8f41a44a, 0x000e875d99092757, 0x00005ff9309a3d10 }}, {{ 0x0008059420aa911f, 0x000200838961a0f4, 0x000e5063f3a99a11, 0x000f51dc61426ead, 0x0000999972790d9f }, { 0x000bd6e76938fb53, 0x000e7d87396e1dea, 0x00078ceec367f734, 0x00093fd665c8bdc4, 0x000025cb654cb623 }}, {{ 0x0008dd4397eab620, 0x00020bb23330a011, 0x0004aa716c087df4, 0x0002a0c21d23f5ee, 0x00009e0d97bf7d73 }, { 0x0006bba1a6ca60ae, 0x000e59a122d7b44f, 0x0009ac7ccf2f7140, 0x000ef35f8e6d3b40, 0x00006562071bc951 }}, {{ 0x000eb4a728dfb0d1, 0x000ece5cfc0aee0c, 0x0005f1d7a9946ac7, 0x000b2f8b2847edc4, 0x0000f3cb9e6d73cd }, { 0x000fd7e0f19cebb2, 0x000320e26da033d0, 0x000cf4084592072e, 0x000e145256cc3889, 0x0000f9a9e6566860 }}, {{ 0x000e87665c992681, 0x000f23b1f0df9d48, 0x0003142e7e966892, 0x00009ced48cc2c5f, 0x0000034da4569da1 }, { 0x0009723443b0241c, 0x0000decd73dc965f, 0x0004451def97585b, 0x000aa0cb415ace45, 0x00008cda22cac57b }}, {{ 0x00036cf77e985285, 0x000e12eb72d9f264, 0x000ead77798b269b, 0x000e004d0b19396d, 0x0000b0da9787f548 }, { 0x000ed049715c4ef1, 0x00042b3e990ef77c, 0x000c4c41b2b3b279, 0x0007441ce7373e3e, 0x0000c74b8d8215b3 }}, {{ 0x00087b9090eee8d9, 0x0001e857e977ca05, 0x000a8761cc9b0977, 0x000721b61b66ee8d, 0x00000d8c50c1bfa1 }, { 0x000f5f64b5366b2f, 0x0005b1b32ba0127e, 0x000624b6b0f733ae, 0x00003c3f2a7720e0, 0x0000f1e94afee463 }}, {{ 0x0007d52107341dcf, 0x000da6292b8c5599, 0x000fd19ee9087108, 0x0009ff1a50c14aab, 0x0000faa98a57dc72 }, { 0x00064ed85eec4469, 0x00054303e7c253b2, 0x000a21af1562e2d2, 0x000f6422ecc834b1, 0x00005e395857864a }}, {{ 0x0003b3e080e596b9, 0x00020c066d41870b, 0x000093d3d98894b0, 0x0003d8d35a50c20b, 0x00005c4a4156d0fe }, { 0x0006900c54967769, 0x0007c58a179e9d94, 0x00092e175b2d285a, 0x000c91d4f2daa3f7, 0x000009935a179da3 }}, {{ 0x000e2ddd1a219abc, 0x0005b1ef76765d05, 0x0002379a97e897c4, 0x000e1ddbd4ad726d, 0x0000c1f23448c02b }, { 0x000809d5edd717e7, 0x00030fca93e6dea4, 0x000b4b6d3b35eb09, 0x000f0bca2e8a2583, 0x0000004d3d719c22 }}, {{ 0x00066b19648d9dd3, 0x00077a3da7a095ed, 0x0000508a9178ada3, 0x0004ae54a9049acf, 0x000017300723e8de }, { 0x0006ccb81ee1f40b, 0x000b7a0de6e95555, 0x00085ef0cf517a36, 0x000de7e21cf52d09, 0x00008ba0c8b2872d }}, {{ 0x00094348a4e6b6a4, 0x000e6b89f4ccbb8c, 0x000211dece842856, 0x000082d0ced5f44d, 0x00002f608774e31a }, { 0x000c51779a9eec3d, 0x000acc429ef8479b, 0x0002a4faf1a4db07, 0x00027fd144c13a4e, 0x00005e156474bbef }}, {{ 0x0000f4728b20513d, 0x0003c922774856f7, 0x0004fb2782d3e590, 0x000a061166e52fb0, 0x0000b15e370c9ac4 }, { 0x0005ee9fb249de3d, 0x000dbd1b2947f224, 0x0005e22ed0071342, 0x00012adbdc827ea1, 0x0000818801cfdb43 }}, {{ 0x000537c1f02c6851, 0x000b321bb937d636, 0x0005671375b66207, 0x000852a68df8ff2d, 0x0000496bf164c230 }, { 0x00045b0e55c95c63, 0x00007263b37f8e84, 0x000b9a90b8785c72, 0x000cc742c170e9a9, 0x0000126204cdfcbd }}, {{ 0x0000d9a50b845667, 0x000a70683a7337bd, 0x00042f134d3dc726, 0x0004c501f1e3416d, 0x000077d800d0f3e2 }, { 0x0002ade2f283b9d7, 0x000aa506fe28ef7e, 0x00054084698d5e5f, 0x000e17b633cc5ef1, 0x000066c31b2862f2 }}, {{ 0x000e6fbcea358249, 0x000d7fa458d36710, 0x000c1f54c790f34a, 0x00096f8e31549722, 0x0000b594e2aa6b23 }, { 0x0007b2736a31e704, 0x0001a6b3bef0262d, 0x000bb7a26d997c33, 0x000d94eecfa8c472, 0x000052cf6e513e40 }}, {{ 0x00075c9c88b57072, 0x0006ff1716843491, 0x000e1b84ff0e5ecf, 0x0002798ff36b4722, 0x0000fd7a19679edb }, { 0x000cf60d2f9f4605, 0x00056226e6bfdb1f, 0x0001c1e53e170898, 0x0000469445ea5b7b, 0x00001577a6f96234 }}, {{ 0x000ca2e2a9f36d95, 0x000a42d677819e1a, 0x000dfdb7473e6ddc, 0x0005aca3f7be74c7, 0x0000e0f21bb12470 }, { 0x000f16207d6ca7e8, 0x0001b88122a6fe3d, 0x0002a913e42b12c8, 0x000d30557db69f70, 0x0000ec28095ae062 }}, {{ 0x000023dda39ee7d8, 0x00071ab63ed9998a, 0x0004075a01f290e2, 0x0004c6872a3125c4, 0x0000f904a184e285 }, { 0x0002370cab7cf923, 0x0001efc0c743032b, 0x0000ac0c798dc522, 0x00042f8074f2120c, 0x0000c5c63ec4a64b }}, {{ 0x000b922caee9c36d, 0x0006c626cc820fb6, 0x000c4cc8181044ef, 0x000a22bf059feee5, 0x0000001293501b71 }, { 0x000509216ce29c86, 0x000bfad106bed4e9, 0x00054a98c83f1cea, 0x000260e87546e71f, 0x00009ce0ef82db3c }}, {{ 0x0009536e2465169d, 0x000936785c9a2dbc, 0x0001a294f24b62b3, 0x00035c81dd6ae515, 0x0000b9a59ef9c27c }, { 0x0000a8075f1088c7, 0x0006ea934521b032, 0x000c66df4fa0987c, 0x00065293cf39c526, 0x0000932812328d7a }}, {{ 0x0005b9502ede5c00, 0x0009c62640264225, 0x000fcf00804813d3, 0x0009329508dd1077, 0x00003a1cef23fb5d }, { 0x0007fcafd4d1e2ef, 0x00025b486a098170, 0x000c3fbe909cd3bb, 0x000fd6a2fa39dd3a, 0x0000301ef9be9169 }}, {{ 0x0000d74541238bb1, 0x000a1ee346eb2263, 0x0005bb58677672aa, 0x0008f2c267dfab08, 0x00008519f05e7745 }, { 0x000b740ffbc988fa, 0x000ed3ef2c2d065e, 0x000fe8badacd3c5f, 0x00097a322ff9b89f, 0x0000270de0bc09cd }}, {{ 0x00021b2cceb112c7, 0x0003213a8aef5181, 0x000bedd9a2d4160d, 0x000a099487bfc74b, 0x0000bfb60e023e05 }, { 0x0007a59316c50a89, 0x0003f36a01eb3d34, 0x000a17d37464fae9, 0x000fa32cf50eb1c6, 0x00003421f128bfda }}, {{ 0x000c2da0c5ea518b, 0x000897f931020167, 0x000418a384b07616, 0x0006ae09112c5f65, 0x00005b5dd45be1df }, { 0x000c2e94a72326bd, 0x00088b6d4a1dd5d1, 0x000674f41c95d1d6, 0x000cebd483e7ad9b, 0x0000363b24c971c3 }}, {{ 0x000e5d95c2d82265, 0x0002a075a97d231b, 0x00068f25f195c1c4, 0x00064c2277c80de9, 0x0000d8d6a5c50d2d }, { 0x000e26d6207fa264, 0x000f8b19c2492eed, 0x000062269993127a, 0x0005724d342192dc, 0x0000a4ee006ab0b3 }}, {{ 0x0005cdcbbff59de0, 0x000fcb6137c7408e, 0x000550d49b1acec8, 0x00020df1b9a38d7b, 0x0000a28ec5df468e }, { 0x000827dcdbc769cd, 0x0006a6df65965a08, 0x0002638c0c826940, 0x00084a22060fe88c, 0x00007b733efb859f }}, {{ 0x00066d1dfef7b4aa, 0x000f3240c56c6904, 0x000d974a461ec7d5, 0x000b6bc2b40265da, 0x00009a037291c042 }, { 0x000effe346803700, 0x00069621484469b5, 0x0008a3dfac592a2a, 0x00081bf510db6054, 0x00002ee4b2e6bbbc }}, {{ 0x000c3f2c5b8478f1, 0x0006164ff112c32f, 0x000c7f57f357647d, 0x000fc170d8a9c736, 0x0000f62d2b5914f6 }, { 0x000853ac70c175fe, 0x000797e5aeb49c20, 0x000dd1c7318d5bf6, 0x000bfb1fcf3db034, 0x00006e90923fe993 }}, {{ 0x0008ef1d90bd82e4, 0x000f1948b2a29d5d, 0x000674f0f04a7a60, 0x000a94e8b28f1f45, 0x0000cb6517882536 }, { 0x000ed48d66270e5a, 0x000086041dc61bde, 0x000c3919a2246fed, 0x00086105df74e8a9, 0x000062b49a271a05 }}, {{ 0x000fc8a61448916d, 0x000c74f3a29467a3, 0x0009855614595002, 0x0005455f2de81e94, 0x0000c7e3b2cd575d }, { 0x0001458e271cf38c, 0x0006c8f06d0de9fa, 0x00049a303fe35dec, 0x000c8fbd5bbc11cf, 0x0000091b6978a5de }}, }, { /* digit=13 (1,2,..,64)*(2^{91})*G */ {{ 0x00072002d0deafc1, 0x0007568e039c2560, 0x000b74f7fa8c3e04, 0x000fa452b5f26fb8, 0x0000d5c673e4de9a }, { 0x00094308345d1eb9, 0x000e937e84fb7e3e, 0x0000233f0b08ef7d, 0x0005f8881b401d8a, 0x0000861e80d65e10 }}, {{ 0x00076ddafe513028, 0x000b231be24319a2, 0x000bb927cde9a7fd, 0x00047f98503f7d28, 0x0000bacef2354247 }, { 0x000e4d52a90363e2, 0x00072961d7a64eb7, 0x000900d06b997d69, 0x000d4f0d5e436088, 0x0000deb49837ce80 }}, {{ 0x000bab8085f68f7e, 0x00057b11d59715df, 0x0001dbdd17b82354, 0x000627448c7eaa76, 0x000008e08b2e2ab5 }, { 0x0009f8090d0bada8, 0x000652153765b2f5, 0x0003a01a76305a37, 0x000cd7310bdd4e08, 0x0000e04ea95f672d }}, {{ 0x000bb2d0d12e52d0, 0x0002d9d615faa8f2, 0x00006ad2841c4cc3, 0x0005178828fa1eb4, 0x0000037e5443ad4c }, { 0x00018eaef0ca0cd3, 0x00057646caa6d2f2, 0x000e0158862a3d51, 0x0004399628eb879d, 0x0000cd6553865dd0 }}, {{ 0x000c0571a1474d7d, 0x000eb4744ddfa350, 0x0005ceae85a5f097, 0x0009beff49ccfc5c, 0x000030d609ea9dd7 }, { 0x00057759b5198b47, 0x0006cd54b3a7b3cd, 0x0008885661e41633, 0x000b6143a35c0366, 0x00004e96b4e32798 }}, {{ 0x0000a94af9ea7cde, 0x00069d83d30a2c5c, 0x000e36e136e23569, 0x0009d6c9b0857f77, 0x0000ee3ba9363a28 }, { 0x00091c4d690c1482, 0x000da0bdaa6ec1a9, 0x0002efb68a84b025, 0x0004cc597ba9fe49, 0x00009c2e3b6a4baf }}, {{ 0x0001e48f047ae313, 0x0007928d2f01cb3a, 0x0003357921acd842, 0x00099fab493d6eaa, 0x0000971a98af096d }, { 0x0007186cef6f15a9, 0x00051f6c508b23ac, 0x00096ebcc85a8832, 0x000e40f38f137571, 0x0000e4475b94f38d }}, {{ 0x000f0606c39967da, 0x0008ecee978a1d35, 0x00031bb32640de50, 0x0003dde62e3a68b3, 0x0000e08b646ad0ee }, { 0x0000f5f9d3887578, 0x00046276f9326f11, 0x0004b608425a9f9f, 0x00069fb512f521c1, 0x0000178ec5cbaa24 }}, {{ 0x00015759ba88c80e, 0x000536b269fb37d5, 0x00042c8ed42b45c6, 0x000153353aaf7380, 0x000055e311c5bac7 }, { 0x00087e91e457b502, 0x000e9f8aa423a61a, 0x000124c369ae3354, 0x000978736592245a, 0x0000f1cbf0fedd43 }}, {{ 0x00019c380abd55aa, 0x000a2e43d34a2e3f, 0x000dc29f25566282, 0x0003bdcc7ee3759c, 0x00006455153981a4 }, { 0x000fab2b4f7c81ad, 0x00074aade744b1f6, 0x000ff14cda1c443c, 0x000bd5111a7d222a, 0x0000a28194e30835 }}, {{ 0x0004f489bbe9959d, 0x0004d5f4bf1d7255, 0x0001fa780b53c39e, 0x000e212069c1d8ee, 0x00009ce8effaceb9 }, { 0x0005945723762269, 0x0006d34992fb7e89, 0x000a0d0fec2418ef, 0x000dfa5000169a7a, 0x00002dfdd7e68c1e }}, {{ 0x000876812dab14b9, 0x0007f78a4d32282f, 0x000c4f8b89ba0bce, 0x00094fe50e36e029, 0x00004692f67fcd8c }, { 0x000d3eea24df7225, 0x000ee8ed23a17f08, 0x00006374aae9a53a, 0x0006455e06d7b448, 0x00001b31dbe9cf50 }}, {{ 0x00008ccbe2c9375c, 0x000c475b15d5acc9, 0x000f2cf48fe143cd, 0x0006c10f2c6d9c79, 0x000052c6758da616 }, { 0x0004e7f0deea926a, 0x000b8c4ba35afce8, 0x00007882ce2c78f4, 0x00030cbc15a3da8b, 0x00007993789e4ddf }}, {{ 0x000a821ab5d22890, 0x0001522b99a72cb0, 0x00077cdf65604ed9, 0x000cad53e06de6e6, 0x000000279f3d1814 }, { 0x000490a31fb979cc, 0x000d92b7cb0b5a2b, 0x000c1473e470c4c5, 0x00054393aa7fb121, 0x0000cf1f5b79004d }}, {{ 0x0005647406b4d83d, 0x000a77d62dd61ad3, 0x000c367b9f6b2ca3, 0x0000b8eba781a961, 0x0000c08fd788cd26 }, { 0x000f2bdb2ab6d0a3, 0x000f27b2736a129c, 0x00021de8172c3e3d, 0x0004959c5a631370, 0x0000e07bdbb63a83 }}, {{ 0x0007d51e7e42a51e, 0x000f444c5f95cd80, 0x0000ecd677766dc5, 0x00040656dda8c8af, 0x00007a567e594477 }, { 0x0001a1b8848c495f, 0x000ff6ac2ccbcda6, 0x000f23870b5b7597, 0x000568bd43bc1923, 0x0000956dd9ebf318 }}, {{ 0x000e676223b52ac3, 0x000ab08700230ef6, 0x00014eb24bd5447d, 0x0003015f20af585a, 0x00006fbd09543e40 }, { 0x000716998cd613d8, 0x0004d7c4e774d3fe, 0x0002c4f9938e4db7, 0x000fe92a582a3851, 0x0000708acb1bfba4 }}, {{ 0x000ce0a3b86fb6ef, 0x000e671fb1675839, 0x0008348bebd1d282, 0x000eb8619dd011c7, 0x000021f9f273dcf9 }, { 0x000c00295b68f0cc, 0x000a689d5ec67385, 0x000a2c40c61023a6, 0x000546819a3b49f9, 0x0000308d7cb76e31 }}, {{ 0x0004ada5e11c599f, 0x00075fb1d4bcc766, 0x0001e0ece31035ea, 0x000b3720fb07691d, 0x0000d42fa02b82da }, { 0x00097f2f7329b17d, 0x0007c4e5b544cf50, 0x0005f3a7e48b861f, 0x0005af7f4b4a13a1, 0x0000b8d9cdcafafb }}, {{ 0x0008e1b8c2d74b0e, 0x00029d8affa8208d, 0x000b0347f239c200, 0x000ef527fc3c31b0, 0x0000983c109b8ea2 }, { 0x00039cab167742fb, 0x0001d15c8418682f, 0x000e8a2c7280fa2b, 0x000566e82541d487, 0x000043cc4696534f }}, {{ 0x000f6985d44acee8, 0x00019a0e68db0554, 0x00086ac9b300b789, 0x0005c1284f356975, 0x0000a5ac2e22d6a3 }, { 0x000c9d95d6ef7c99, 0x0008615132ed17ab, 0x000403a5d02745a2, 0x000355766510ed0b, 0x0000b2d6d88461f6 }}, {{ 0x000ddcc3fd82271c, 0x000b36e19abd09e2, 0x00012214bade2615, 0x00022eace0b4097c, 0x0000faacf01c7b54 }, { 0x000b860163208096, 0x000ba3d9e8153b8e, 0x00018bee1638b3c8, 0x000587c0c3324fd0, 0x00003de457dc65bb }}, {{ 0x00039ed2562fdbc2, 0x000fbd1972f07f4b, 0x000e1edcea95283b, 0x0003623a6e5579e2, 0x00009e02c169c92f }, { 0x0006d17da40df3f7, 0x0006d17a2f62e55f, 0x000e24fe04fed313, 0x000f732f96b9ab38, 0x0000e962da3c756c }}, {{ 0x00012c0401631864, 0x00079bd0f968c006, 0x000b9ee0840a483b, 0x000826e4da03da7e, 0x0000d17d0ff62307 }, { 0x000c74ec710cf280, 0x0008493109f5df10, 0x0000743a88df63de, 0x000c729b3fbda403, 0x0000893136d324b9 }}, {{ 0x000c593df45e820c, 0x00049646edb951fb, 0x0007c2c9848e3595, 0x0000b05965f4a9d7, 0x00007059afd6a155 }, { 0x00047ed87de67e90, 0x000cbd46af3641a8, 0x000ab91c654ee10d, 0x00064a3047802200, 0x0000176fc6f6b4a5 }}, {{ 0x0008923bbab39469, 0x0002e4e6d6711921, 0x000ac584ba5544c8, 0x0002f1e971e14100, 0x00005ee0cd3a9fe2 }, { 0x000af777f11421a3, 0x0004599bbe7e86e1, 0x000e0668efcedb0a, 0x000b42b3e4a1510e, 0x000081d2b6ac6370 }}, {{ 0x000f3a93c5729e80, 0x00034004ef657241, 0x00091cd213392d1e, 0x00061a9943e04a4c, 0x0000714ea218efe2 }, { 0x000dbd736683a3d4, 0x0003afe3923555b8, 0x00089059de839c3c, 0x00012bf57744bedd, 0x0000f135993bf2e7 }}, {{ 0x0002c8361b7a2aca, 0x0006699df1ea40e2, 0x000b350de8491faa, 0x00043ee12b3f24a0, 0x00002727eb357cdf }, { 0x00035a753655680b, 0x0001497f9c0d95c1, 0x00027ae958781188, 0x000c30ac38846117, 0x0000025367304961 }}, {{ 0x0004c10cf8896213, 0x000ddf75f7ae2f68, 0x000d533960a9a46b, 0x000722eb615fc6e1, 0x0000ae866b88a248 }, { 0x0008a74fcafc168d, 0x000df95a73fbbd0f, 0x000a54e81f1dad9b, 0x0000f13437f24e0c, 0x0000c84c23966c22 }}, {{ 0x00040a120307c01c, 0x0004985c9f842969, 0x000aa7b866ad1714, 0x0008fafd07fbaa8f, 0x0000621c9f76d164 }, { 0x00092f8868ee11e7, 0x000fa2055a4aec84, 0x000492a7ba874698, 0x0007a81ab550e9a7, 0x00002f1e26b56e34 }}, {{ 0x000b6155609a0534, 0x000e1adb2d8f3984, 0x000c102373f2ce23, 0x000b3e3d6f13b51c, 0x0000421c4ce957c1 }, { 0x00020f448ada30a5, 0x000a9850a52c1c82, 0x0004fea81b397d5a, 0x000db0ec6eab1a69, 0x00001f18e2afb1cf }}, {{ 0x000589fb928c5f43, 0x000ab31b0e63d348, 0x0002245b5418c388, 0x0008872a4f460057, 0x0000c3c71e7aa249 }, { 0x000bb0696dee0485, 0x00070cc6583553ae, 0x0009f6a5e077bc6c, 0x000ffc1520879094, 0x0000bccee4609921 }}, {{ 0x000c457b0b8cd23b, 0x000e4deb9718710f, 0x0007f72f2ee9cd44, 0x0006782c138f1bed, 0x0000d9595242d62d }, { 0x00095c766178c8de, 0x000a1d4883841e20, 0x00092f15dd20214f, 0x0002f65958ec25b3, 0x0000f894c054a41e }}, {{ 0x000a9fc894303e0f, 0x000b95c4bdc56104, 0x0003ccfeea6d613c, 0x0003aaeccb2885fe, 0x00002d45649bb35b }, { 0x0005fcc99d08171b, 0x000d5cd3ce299af5, 0x000357f6c183b368, 0x00076c08f195be9b, 0x0000561cacedeacb }}, {{ 0x00098ba31d719d2c, 0x0002f4c721a4593f, 0x00047d0307a4b9cc, 0x000eccd14ed1e9a1, 0x00002d73755fff02 }, { 0x000ffb3c0ec394be, 0x00055739b128eb4e, 0x000de44d733bbc94, 0x000accfd37801214, 0x000050af6c641c91 }}, {{ 0x0005f825c4f07a21, 0x000e67cc7bf3827e, 0x000a61fffdcaef2b, 0x000eab454f2165bc, 0x00005d08b9caa394 }, { 0x000659f053bb7164, 0x000eb67ffed4d6f5, 0x00085eb0445c885a, 0x000d096f1bc60957, 0x000009efc070a594 }}, {{ 0x000c64a71a41fd04, 0x0007ec36044d63bf, 0x000810766586a678, 0x000b5b8f6a608940, 0x000015d2319af57d }, { 0x0002002ddd63570e, 0x000cc8083dbedba1, 0x000219e65019b26d, 0x000e6e1de804ae11, 0x0000b12ba3767b3e }}, {{ 0x000d0a9304441d8a, 0x00024895dd21b96d, 0x000af239cf49a271, 0x000aaff7a8b99f28, 0x00007171f2ff03da }, { 0x0001f37bf44ca0c6, 0x000af224e233de42, 0x000109432cb14982, 0x00098cdd9192445b, 0x000083d6a7497fb5 }}, {{ 0x000a5ab0888caa4f, 0x000f449f8bd2bbd7, 0x0008ce0d68d4a75f, 0x0005367f11d902cd, 0x0000a44f775a6959 }, { 0x000b840d135a5237, 0x0007406f7a09e03c, 0x0006666eb4106a14, 0x000c92f572f8a197, 0x00008f690387b3a9 }}, {{ 0x0007753ef58b6176, 0x000379f7db326750, 0x0003002b30262a9f, 0x000bdea9478fea13, 0x00009fe0ef597427 }, { 0x000109beb4404306, 0x00054ed9c0bea786, 0x00095b35866fc305, 0x0003c6c6d41bb398, 0x0000d3e8797ead29 }}, {{ 0x00025549467a0bf6, 0x0001bea3b6d1145a, 0x00090602dd0e0635, 0x000da6f62b6271ea, 0x0000e2394cc29faa }, { 0x000777d45fafe2fb, 0x0009d5e99bfe35f8, 0x000ff3d9f99729e1, 0x000a51d329770ccb, 0x000030a49d96b3e2 }}, {{ 0x000b3786e5ed1d59, 0x0008122d847999db, 0x0006081ad64caea1, 0x0008c00a103aa33b, 0x0000197d6168ee3b }, { 0x000f6688f1378163, 0x00070ce6961f247b, 0x000e4392b44e7734, 0x000264b4f20aa85a, 0x00009914ec874ca0 }}, {{ 0x000e24bf90175fbf, 0x0004f867469ceadb, 0x0003727b0ab89a54, 0x000f4fcc71904c52, 0x000031f4ae121f33 }, { 0x000f170db279ffb1, 0x0005690bd98764be, 0x0006b3571bec445e, 0x0009033c7a0f45f1, 0x000097d5d9760ff1 }}, {{ 0x000ee1767e237834, 0x0002da029e0ccc17, 0x000de1cbc04beb15, 0x0009f0422cd53e87, 0x0000d2d72323a5a4 }, { 0x0003f6bc86ce1e10, 0x0002259648945af4, 0x000ce1d14415bbd3, 0x000439b8c9e45a5f, 0x00000c39573f5251 }}, {{ 0x000f428fce95e48b, 0x0009848f2142e791, 0x0009a7a393bbf194, 0x0009f129b17d8925, 0x0000aaebd8ce27b4 }, { 0x000b5da0d65b712d, 0x00069010db06dfe5, 0x0000f54602f5c09f, 0x000bfc71bbfc16bc, 0x0000a4f9df66163f }}, {{ 0x000e43c42cf85546, 0x000c44856ef96a74, 0x000849e83415f3c7, 0x000ea2a0db47eb84, 0x00000d10f03005f3 }, { 0x00020e52e37d20d6, 0x0005431d1a4aa2a8, 0x00083df6a0eb24b6, 0x000ddb47a440d466, 0x000048087cb057c8 }}, {{ 0x00097c4c88758f6e, 0x000f1cf25e51b09f, 0x000e26a784d0b41c, 0x0005c8b0e180cd2b, 0x000009259c42e92c }, { 0x0008e2f4d6cd7faf, 0x0001824c03dbb7ea, 0x000458a9c70dd19e, 0x000e82253ae04376, 0x0000c21fa7e45f39 }}, {{ 0x00099cfe2f0814de, 0x0007447d95ea1682, 0x0009ffd3781b0f15, 0x00082a3691758fad, 0x00004a8af81a2215 }, { 0x0002e22a81992dca, 0x0005417b0a98927c, 0x00005d1f1a13cbfc, 0x00047eb6a2e26e1d, 0x000016512c4f1dd8 }}, {{ 0x0008cdcef72b2cef, 0x0000afbd90a060ab, 0x000b0225b18e21e3, 0x0004a7ccf496a27d, 0x000094a48f740aaf }, { 0x0002d4d14b785966, 0x000a937436a0bbaa, 0x0007d3b12efde960, 0x000dbdccf263fa10, 0x00008368434e4361 }}, {{ 0x000e4e4a56705d8e, 0x0000f6812e9a1bcd, 0x000b811fe812283e, 0x0004f583861d9075, 0x000054c73bae5329 }, { 0x000eb36201e51c99, 0x0007b4ad673c0175, 0x000e10baa3e900c7, 0x000b52456667417a, 0x000012e79d4dacf7 }}, {{ 0x00069ef68c67b87f, 0x00046043a1aa9145, 0x0009203d62e8c5c3, 0x0000f935c175a129, 0x000001fa1a6965d8 }, { 0x000d9e2a0a581188, 0x000536363a113b4a, 0x0005eae52d5c3801, 0x0002fa5eae3bd3f5, 0x000066503ca8481e }}, {{ 0x0009192ffa7d59dd, 0x000bb4c508b65e9e, 0x000084d870d6c300, 0x00060a3dabde4a1d, 0x000027aed4e0a762 }, { 0x000479a99a505811, 0x00085965099fe925, 0x000bb6adfbb04f0c, 0x00038c96125ddb65, 0x0000b41360e14375 }}, {{ 0x0004fb15b0510f55, 0x000f905013fe1620, 0x00025e32316b7fd8, 0x000feb39fbe11dc9, 0x0000d62b1f4b95aa }, { 0x000a88e26620cd37, 0x00028c213c999279, 0x000fa35a08cf8550, 0x0000d94b4a033e9d, 0x0000037e5cb1f698 }}, {{ 0x0001d933d32c017b, 0x000346254671ff6c, 0x000a9dcc5230cb16, 0x00075f8c04bd4241, 0x0000bb7123eb38ba }, { 0x000c6641dc5f7a5b, 0x00051f3689e2c70c, 0x00067a54bb55957b, 0x000f99be592aab0e, 0x0000100ca18fcdd4 }}, {{ 0x0002150673a6e180, 0x000f757d31e535ec, 0x0005c5ade79e2400, 0x000211ffa04cc43b, 0x00009f71ec100187 }, { 0x0005a52faef35750, 0x00071e08d68b0139, 0x000f584d694447ac, 0x00028f464a9d6816, 0x0000d379add57aaf }}, {{ 0x0006293a2dec1ae3, 0x0003e600e1cb64eb, 0x0005c8568fd06998, 0x000961893004828f, 0x00004d492af4542f }, { 0x00028e52e6b40b4b, 0x000a421d145d2d9a, 0x00031901531d2a2a, 0x000c3da2dbe6225b, 0x0000a8127987847e }}, {{ 0x0008303593dd6e66, 0x000629b4c371e6da, 0x00048ebed994bfaf, 0x000bac981cebe067, 0x000016931e8d75c6 }, { 0x000130cefca57500, 0x0005b0a7e37a9bb0, 0x000e2a5edfc6fbfc, 0x00054b1028c56f61, 0x0000ecf694a5348e }}, {{ 0x000752496e016bd2, 0x000cda0bd865cfbc, 0x0007f50cd4695497, 0x00052a0244b03e57, 0x0000637b077b76b9 }, { 0x0005ae9668f90345, 0x000e83b564beb6b0, 0x000033f32f9fd853, 0x000f2bc260db1d11, 0x00009c49e1c7cb1d }}, {{ 0x000633e728e450f7, 0x0007637c92544f2b, 0x0002ed2450ac358d, 0x0000057cecc08435, 0x00008ef9d3967336 }, { 0x0002ca7d5cb05be9, 0x000ed9f936c581cb, 0x000dc16f479d4101, 0x000e8a15b96e7b8c, 0x0000175bf8daeb7d }}, {{ 0x0003f3086f736b1f, 0x0000641f50240258, 0x000960cfd0c861ef, 0x000f6f99f47bc576, 0x0000686ca9cfba8f }, { 0x000b7e65f9f1ce62, 0x0000b94b587579ab, 0x0007756906660826, 0x000329dcfec2d22d, 0x0000255e257067be }}, {{ 0x0002c8ff8f6efa40, 0x00054776652a220f, 0x0008e3cdc9f20d82, 0x000f5bff361618f8, 0x0000f1cc52b08e1a }, { 0x00062b9b103f16d5, 0x0003ead8efb4d3e2, 0x000fa7ebd284ee8d, 0x00051001c937b5ad, 0x0000d93b71b723eb }}, {{ 0x000588993b473591, 0x000bee4c43ff28b8, 0x0006e4ddb53f06fb, 0x0006fd4c27647662, 0x00006c003ddbd070 }, { 0x000832749a9bb5b3, 0x0004ed68f938829a, 0x000d96ab08b23bff, 0x0001781c7996627e, 0x0000272b5788c7f5 }}, {{ 0x000ddbacedcf37d2, 0x000bf7d4bf503533, 0x000b178bb90d5ee0, 0x0009dd96685dd726, 0x0000ebe65a8ae8c4 }, { 0x000da2828c5f8f65, 0x00074a412f22e85f, 0x00066f647430480a, 0x0003ab137e2a2486, 0x00009656ded0c9e4 }}, {{ 0x0005aaf668ac79d7, 0x000433ea2dee7a63, 0x000c3da02c1bc912, 0x00031cfaddcde2f3, 0x00001022732669a2 }, { 0x000b89dea0558e1e, 0x000e6a9e5aa049a6, 0x000d25865fe4287c, 0x00021cec3e74083a, 0x00001aa8b5c32deb }}, }, { /* digit=14 (1,2,..,64)*(2^{98})*G */ {{ 0x000be00843e7b7e6, 0x000b723fe67ba665, 0x000037ef26f02671, 0x0004513139145076, 0x00001e80333c65b0 }, { 0x00067e7cf2b69e56, 0x000e805d53ff04d3, 0x0003276aa2047eed, 0x000006ba0bf7ccdc, 0x00008a2d8826cd00 }}, {{ 0x0009356a79debb8e, 0x00065b7b0dc85957, 0x000825e834b42de6, 0x00021f4a727de460, 0x0000c18079e2bfdc }, { 0x0003b0bfe5e20c23, 0x0000045f5f9a0529, 0x00087fe98313de54, 0x000411dfc1a8b0f8, 0x00004e039a515ca2 }}, {{ 0x000607c8357f525c, 0x0008102c024789cf, 0x00094badb3c6d4e2, 0x000e13cdf90dca9e, 0x0000f013f32caca4 }, { 0x000259ced8a8fa9f, 0x0001f97c2c99b76f, 0x00062668c42a120d, 0x00009098c6576ba6, 0x0000ddf41abff43e }}, {{ 0x0009d20f961c2e82, 0x000b85dc8de610b8, 0x000ade101437f35a, 0x0007eebc5e8c515f, 0x00002509d1321032 }, { 0x000842e3dac8ba0c, 0x000fd66098583ce0, 0x00048bafc3fcb163, 0x00076414aa2eedb9, 0x000007db9f48bc83 }}, {{ 0x000c04346f8b4a53, 0x0001fa33b9e2d7b5, 0x0007687de490598f, 0x000ca4a917cc60b2, 0x00003bbf0d26c8f8 }, { 0x0008cace3b4eac97, 0x00066f2614650a98, 0x0007392b98719d3d, 0x0000e25835e35b53, 0x0000792a37dc963a }}, {{ 0x000a9c2a39c1acbe, 0x000e5753de92e23f, 0x0007651f8ca95eef, 0x000048a7eccb03cc, 0x00005893c9a2ca16 }, { 0x000cba2866a3fc9d, 0x0009b236724ceedd, 0x00073c72dabcd16f, 0x00061668e3a90225, 0x0000f7789359b346 }}, {{ 0x000a35b6a1ba7e68, 0x000bb7f788907328, 0x0008c9c6fe382aca, 0x000b618d6c443bef, 0x000027c8cd8a0530 }, { 0x00044a35a0bbe471, 0x000d61665e9a90a2, 0x000d40e5d11ff8ff, 0x000053d3b45bf380, 0x00001226d9bd6c94 }}, {{ 0x000595c4b3f8dbd9, 0x000359d74cd06ff8, 0x000f270e29f8a825, 0x00087d12b9c17c7d, 0x0000b2e80e811f87 }, { 0x000db27ce43a86c1, 0x0003fca990f62ccd, 0x0002ec59bf016957, 0x0000628f5d9bed21, 0x000027d55a4ba6a5 }}, {{ 0x00088b9aa14b8da6, 0x000a46658926ddd8, 0x000907f47b17a1a9, 0x00091d4b8138b2d4, 0x00001b4b6e70d892 }, { 0x000f508ea42a5543, 0x000c04e3a96e3551, 0x0008d3bf2ff6a996, 0x000cbf37aba65b0b, 0x000012115142acd4 }}, {{ 0x000f55cded9f6e0e, 0x0000c49747c866c7, 0x000d85c2d274f8e8, 0x0006e2808bbb1e5f, 0x00001441178e9e4d }, { 0x0005bd1a0a03f0a8, 0x0004495f38c85f0f, 0x000e96069eb98983, 0x000220e6f5b589fd, 0x00000accc96b8e0b }}, {{ 0x000a8761f7872bd9, 0x00061e55e915918c, 0x0008bc714273ddea, 0x000c0209c6158d6d, 0x0000e6410b2c4167 }, { 0x00091666024d7e90, 0x000b9c29ebbc601e, 0x0000f7ad482d61b5, 0x00067a752ef3b0f4, 0x0000530ed4817b10 }}, {{ 0x000d03f718913dd5, 0x000c2befc15aa1ee, 0x0007c847102cc8f2, 0x0005c8a1240d1254, 0x0000fdffe724edc0 }, { 0x000f68ea1cc2db7d, 0x0003e6c4a02c4997, 0x000d509587b544b9, 0x0005f5faff725083, 0x00002c702007fc4c }}, {{ 0x000b3261f5dfe89f, 0x00029c7b7ffd977f, 0x00048543b82d075f, 0x000575c83ec104c3, 0x0000ac684c28b97a }, { 0x0003997db2fbb677, 0x000d260d883e5448, 0x000009297105579d, 0x0001fe89913520d7, 0x00000d81132cc8d8 }}, {{ 0x000236a324c0abe2, 0x0000f060dbd2c016, 0x000abd6646100dc4, 0x000ed57214f8eea6, 0x0000ebb2e4bb264d }, { 0x00004281091086cd, 0x0005284a16022e9a, 0x0007a38f5aa9551d, 0x000c6229c0c18d87, 0x00007ce409a2371c }}, {{ 0x000ceb5971a6fc75, 0x0007c5e9afdfb3cb, 0x00029ef45d6dc1e8, 0x00085c89749a5614, 0x00009b93cd3762b8 }, { 0x0004b4099139dd59, 0x000ec5fb269bbc4a, 0x000e450853d0fc8d, 0x0003b57867cd85e1, 0x00004a5c6d138b15 }}, {{ 0x000d112927153319, 0x0003f1d26ee83821, 0x0005188c3a678749, 0x000f5953dcf17dcc, 0x00006ee6a46384a1 }, { 0x000b8bdb94fd5a59, 0x0002b7750491a746, 0x00019255042413ef, 0x00049dcab687fa76, 0x0000d3bdf3fd8d81 }}, {{ 0x000d8811182f36a0, 0x000bdc93bf834aa0, 0x000941e46d331d24, 0x000001cad0437181, 0x0000a5e4336ef208 }, { 0x000560a8b653f914, 0x000fb82f48c8e33c, 0x0004dc5e9825a5d5, 0x0002e1fe5a11fd07, 0x00008d6b831c2888 }}, {{ 0x000054303f46b6d4, 0x0004be23929d0979, 0x0000029d58b20226, 0x000b8f9ac3885b29, 0x0000aac58d89d493 }, { 0x000f3d6452261dfd, 0x00021440738042ae, 0x0006ce71fff79069, 0x000abe21b98e6a97, 0x00004b0f9c9efeab }}, {{ 0x00018d761d16f241, 0x0006d82b6d72d285, 0x0001a44aca62ed09, 0x0009cbb1c77ca9db, 0x0000674f75f7e28e }, { 0x000e54ba56fa1c83, 0x000f10ef0d1b5ce8, 0x000c5b965d2e6f98, 0x000d8b082717039c, 0x0000b2abaa683928 }}, {{ 0x00073eb5de6f16ea, 0x000838af7f91d0f2, 0x000180eba14a2d69, 0x000c07d543b61b0f, 0x0000a48e18374f25 }, { 0x0002413c252f7b56, 0x00055f77b4e4d538, 0x000f5bfedb51fa0d, 0x000d51bb3b7ce66b, 0x0000bd4cf4850d41 }}, {{ 0x00058897dc9c0e4c, 0x0007cc4e0e8ad934, 0x000e1a22eeb0bf71, 0x0002afaf3b5679ae, 0x0000e7087f871d8f }, { 0x000917072350b58a, 0x0003f3089d0caf3f, 0x000e7f4d276ecde3, 0x00008251839564c5, 0x0000087315f576bd }}, {{ 0x000446bca9aa0ee7, 0x0001c17e4515fa57, 0x000486c5bc65bdfd, 0x0001f2065f85cff8, 0x0000dbfd705501c3 }, { 0x0002113ffe594d91, 0x00076aa6d63184f9, 0x00079416c3a80498, 0x00070ef357c1a46a, 0x0000f69954823f55 }}, {{ 0x0000c22f68309ca1, 0x0003f8312e7e46ca, 0x0009b5503c6d1a9c, 0x00023dd0469d0a37, 0x0000cf8b19a3e343 }, { 0x000c392312daf2bd, 0x00043514d2c7d8fb, 0x00030fa9a7d2b439, 0x000fe3577bc45ced, 0x0000ab008068f4cd }}, {{ 0x0005fe87134cd0da, 0x000a17e3cc8ac855, 0x00078703ee282882, 0x00067052f8d725f5, 0x000030f3d852516a }, { 0x000242d3ae1ef785, 0x0007fa96ab6b01c8, 0x0008fa96637638d6, 0x0008ee49b69a02a8, 0x0000dfec375d87b0 }}, {{ 0x000c24d8d4d1fb51, 0x000be65d62105e5f, 0x00093104e58c9f41, 0x000009e09bb222bf, 0x000003c8d01fc99b }, { 0x000f5d057a938685, 0x000eb85d41299673, 0x000c9cdf24c8ca30, 0x0005254a3db81c3c, 0x0000a0f18edf4572 }}, {{ 0x0000a412c93e0e06, 0x000ef6d88c546946, 0x00053a654474d349, 0x0009ff9d1b26baba, 0x00004c0a14f6e6e4 }, { 0x000e419776983108, 0x000e18b54b25039c, 0x00029a3cd9d75545, 0x000cfad94d4ee67d, 0x000011516306d1e2 }}, {{ 0x000a4bb3d86217f3, 0x0007c851c203a40e, 0x000600b1dbb8dedf, 0x0003f9ad230d352d, 0x00001526e5ac6533 }, { 0x0006ec4cd010437b, 0x0004203b98e782b8, 0x000f7f38453d3262, 0x0001381c8ac958c3, 0x00002e418f417cec }}, {{ 0x000f921d710cc9ab, 0x0008a269be47be0e, 0x0007db96e1305cfa, 0x000a2bce5323b7dd, 0x0000b7178cc6492d }, { 0x0006c2921097b191, 0x000d0fc3c4b880ea, 0x000df1d178576177, 0x0003f6e393f6f914, 0x0000ac9a7fe9fa67 }}, {{ 0x000e1999144d70e0, 0x000616651b8d9a36, 0x0008a1e1749d7d0f, 0x0001207ce42531bc, 0x00005552258e045d }, { 0x000453c20f47dfdb, 0x000d63dd5d369463, 0x0005c23b3f858e11, 0x00030f7308255dc6, 0x000097f02a0dbe3f }}, {{ 0x0000448da6108dbd, 0x000d0c089a6ef014, 0x0000581351df8a6b, 0x0008d1c244dbcc3f, 0x0000ec04c9855b4b }, { 0x000882a424d7120b, 0x000876d4ee343e2f, 0x000c9865fedd1f17, 0x0006f503f6343f1b, 0x00001fce589b6c69 }}, {{ 0x000b6c5db412e00f, 0x000c6f4e7db9f57e, 0x000950cbee732732, 0x000e651b17dfba38, 0x0000cfa203fd495c }, { 0x00067ce8c320f904, 0x000ea661cdfe0491, 0x000e2dd72666a257, 0x000f366ad9baac0c, 0x00006dc6d3d1e884 }}, {{ 0x000bc95725aee3d5, 0x0002ea553fb2b560, 0x0007423c28530356, 0x00000bbd96ce141e, 0x00009b1c7fa39ddb }, { 0x0007326ca7661923, 0x00044911220fd06a, 0x000b99589f2eb8ac, 0x000d2c8a9716e3a3, 0x000016f0b4225082 }}, {{ 0x0001690ce1657980, 0x000051ccd090c436, 0x00038fc32ca6d826, 0x000d1fbe4561e8f1, 0x00005c54597e892a }, { 0x000bc9fb209cabb7, 0x000e3370f009052d, 0x0000145c0e0d8cf2, 0x00051250f258758f, 0x0000f2608411d361 }}, {{ 0x000532da0afeae19, 0x000c46e246518404, 0x00046092c0b1374b, 0x0001c3038dca45a8, 0x000033c9b87864ee }, { 0x0007d1a0f94114b6, 0x000a8a51999a6bf9, 0x0009c69a51f582fe, 0x000472a933aa9505, 0x000027a0c0040cfe }}, {{ 0x000422b0ea14fa4b, 0x000a0ba2e1c21dd4, 0x000be844e6da17b6, 0x00005c51ff41b29f, 0x00007397b90d379e }, { 0x000a349d39ffa32b, 0x000651c92f1bfc4c, 0x000f17ac719f4a41, 0x00085fbb806ab1f8, 0x0000fbba41e33ddb }}, {{ 0x000e959ff7b2ee8f, 0x000ae32343bf1a9e, 0x0007493c06b9bdc7, 0x00079d6b48fd3bd2, 0x000098c8ad76a47e }, { 0x0004498bbccb8f72, 0x0006af89706dc3f5, 0x0001c204bf7138d2, 0x000f8d1c8737db0e, 0x0000b2806c0cc363 }}, {{ 0x00065b514edf386a, 0x00009faa29e24afb, 0x0003ba4f3652565c, 0x0001ed0cefcc3c45, 0x0000b4260964a621 }, { 0x0003d84d2f4de65c, 0x0008bcf2193e3934, 0x0001b16c00689684, 0x00018dced60e9a4e, 0x000031f1675d66b3 }}, {{ 0x0000da1a5636e5cb, 0x000e641ee398a212, 0x000ec2e2ab685487, 0x0004e95eab88a56a, 0x0000f1202655d900 }, { 0x00084fcb18da2d59, 0x000409d65bf0384d, 0x0003850a4cf62127, 0x00046220471a14d2, 0x0000aabe22696247 }}, {{ 0x000c58b582f24ca4, 0x000ef7bfa44b4794, 0x0009104047cc8e91, 0x000a3e3275350549, 0x0000d5c4cf012836 }, { 0x000c293a547b773e, 0x000f8d88327f246f, 0x00095154b8cc443a, 0x000e8e6f2c3a3bfa, 0x0000876c2770053d }}, {{ 0x0001a4c61890bb48, 0x000ed2b5acf6e10e, 0x000cce418caac285, 0x0009c327fc50343f, 0x000054fa09fb1487 }, { 0x0001219614c932a6, 0x0002acd33425d0a3, 0x000d6a5a2e6ad1f4, 0x000390c0b306399e, 0x000069c28a3f1ea7 }}, {{ 0x00080094dc4fe82e, 0x000926487f5d28b0, 0x00018e21e3213666, 0x00082bf5f11392d9, 0x0000b5fd9212666b }, { 0x000eebe7f030377c, 0x000dc8c208ba19bd, 0x000ea6270a941ac2, 0x000bdfd9ad3e7570, 0x0000821cf9f8f5d2 }}, {{ 0x000233c3bcb79698, 0x0007798e5c298ff6, 0x000dd44472627899, 0x00035021617f561b, 0x00004d4a92c755e1 }, { 0x00039704dff5bf49, 0x000cca192e3a2cb7, 0x0001729f4c39863a, 0x000cd0ab1961bcfd, 0x000099be056ddf36 }}, {{ 0x000983e996aeb001, 0x000fa587e7b754b2, 0x00017e82e022cefc, 0x000a043522336079, 0x00001a6d17a03274 }, { 0x0000980f9163017c, 0x0006929958d881dd, 0x000255946bab7a49, 0x00009d6d1026bae0, 0x00008bccd8fe0233 }}, {{ 0x000d2d5a30705fba, 0x000888cd5f30851d, 0x00064d220bffdbbf, 0x000fd8ea494dfed2, 0x0000fde12797428b }, { 0x00094c486a8e2a7a, 0x0009bbdd44cc7a57, 0x000d43c60acfc916, 0x00005ddc94ba6b20, 0x00007845c76e4d96 }}, {{ 0x0000a4725a093707, 0x000cdcef21496e4d, 0x00081bc4f0d7dfee, 0x000567a2ff951d19, 0x000004d0a3778435 }, { 0x000aeb8750fba3d2, 0x000d0b50e3bab661, 0x000590c1a91e5597, 0x00060f29e462caff, 0x00005cc394b808b3 }}, {{ 0x0001170c04952602, 0x000ef2f2f7d0ca2a, 0x00083f53c32b2b0e, 0x000d4ca2f6d2e812, 0x00000b742e457e8c }, { 0x000c212c2c471b8d, 0x000904f7805a99ca, 0x000620057f79b6ee, 0x000379240bde56a3, 0x000033f6108aa3ee }}, {{ 0x00052e379c819e4d, 0x0001ef315697be5d, 0x000b57359024af02, 0x0002f60af6f0545d, 0x00005709fccda5fb }, { 0x0001cedd8c6a019a, 0x000c747f462c23e6, 0x0007e4ed47245af3, 0x00083d34fd44a429, 0x00006bc4a68eae78 }}, {{ 0x000f0076f4926fec, 0x000495699f241d77, 0x00068119bda8ce25, 0x00019f891ee4adbd, 0x00003a1ea5347618 }, { 0x000550518bb90e9b, 0x0007dba9264da3d1, 0x000d4d575100188b, 0x000532e716eb2d2c, 0x0000e97178dd93ce }}, {{ 0x00024db6c372c507, 0x000dbf057d0b70c4, 0x000e8ac584e05e23, 0x0007c63eceea8612, 0x000024b1bdc12cd1 }, { 0x000dd6f3a8ca9d0a, 0x0002fd116213fd1b, 0x00045acc53e70ec3, 0x0006f4621c61e7fa, 0x000085b4cbd42400 }}, {{ 0x00099a3c67370e5c, 0x0003a675d97f7e2b, 0x0000f571b84ecef2, 0x00083067a31db0fc, 0x000017a0dc2e6d1d }, { 0x00085346d4a4a2c2, 0x0009d5536b1ff923, 0x000718d7f1b94518, 0x0005a30632973857, 0x00001c47d9a812ac }}, {{ 0x000f7d00d2868ab4, 0x00011ef31631f9e0, 0x0000f428795737fc, 0x000994421bf91da2, 0x0000273abfaac3f4 }, { 0x0004d97e8ccbeaa3, 0x000c93bd8fe79da6, 0x0000704c4b09c411, 0x00014c02acc5e8c4, 0x0000b4ad51bd9104 }}, {{ 0x0002ef029032eee0, 0x000f97302f1cd1e1, 0x000b0ae310148f43, 0x000a922f7ce87eac, 0x00004d8e4c69e3b3 }, { 0x000bf1615a2e8a8c, 0x0003b4e1bcea6e23, 0x000400c7cb616594, 0x000051105d0b5402, 0x0000087338e47a50 }}, {{ 0x000f0469962cc718, 0x000da79f8a7a838e, 0x0000165cecca8079, 0x0005857a111aea63, 0x00005efd15955b73 }, { 0x00066e898fcc53b0, 0x0000ec9d8080711c, 0x0009d97055e6ac0a, 0x000ce1126e1aec60, 0x0000c1f2ccbe262d }}, {{ 0x000ba8ad1ed135cc, 0x0009dc408811fdbf, 0x0007341f43636885, 0x0001975388bfe1ef, 0x0000b69e74c27446 }, { 0x000526bed9600a55, 0x0007bcebfd2fd5bb, 0x0001b9bf4e885c17, 0x000c7cd530b839a8, 0x00008c55b30c7f4f }}, {{ 0x00038b8ee0eac787, 0x00034c2385644641, 0x000778ba2d92e1fa, 0x0005103789e3ff94, 0x0000d8a525b4c26d }, { 0x0005fab8823fdd61, 0x000c24c4123c4899, 0x000864697a151ca0, 0x000c3fea366e6936, 0x0000a8b00c976bf9 }}, {{ 0x0002f26699c531ca, 0x000a607eafbb1e1a, 0x0006446913f9ed17, 0x00084c378d75c9ce, 0x00002f579798942a }, { 0x000be4b0873a045a, 0x000c4cfe469b17ae, 0x0008fb488e3bb18c, 0x000c6b73f6254577, 0x000013dcc4276048 }}, {{ 0x00017c8bfcafa626, 0x00038d78cdfedb1f, 0x00070ca48e783c87, 0x0002c1ec5a535c07, 0x00007254a1aa9e62 }, { 0x000e719e57fc7500, 0x000412efb11fbc42, 0x00026639a10db9dc, 0x000828243ea0b548, 0x00002ca6e35f3d10 }}, {{ 0x0005b95cd967e18c, 0x0006485304ddc5b8, 0x000cc7f246112826, 0x000bb9ca9095e8c6, 0x0000dc3c5bfcdad7 }, { 0x0008349cc1a3f2ac, 0x0001c19b97447336, 0x0008944abac218e4, 0x0009d8ce429c5f53, 0x0000d9a807c23931 }}, {{ 0x000adb13a8f96a40, 0x000cc1d21830ee5a, 0x000e3ee48eeed2de, 0x00073da9436f9c4e, 0x000084a78c9eeb4f }, { 0x0004d8c4d2962386, 0x00024a081313dbae, 0x0007dd3c6905bb3b, 0x0003055f8c76bb46, 0x000014e6ca4ea310 }}, {{ 0x0006544814c3dd38, 0x000ae75b055cb405, 0x000b41270952f9db, 0x000528063898f8e7, 0x0000345a4f463cf4 }, { 0x000d3837fbd3e57e, 0x0001095263a75a91, 0x000efceac4dedcad, 0x00056557ccfb6836, 0x0000601bca5adf6b }}, {{ 0x0008cfb7c7648894, 0x0002138ff4f94ab1, 0x000254b0012b17d7, 0x000d3be877243c71, 0x0000e33accb24543 }, { 0x000bac55e7f80d33, 0x0008ce6729082196, 0x000b31a4eec38aec, 0x000e7812f35c4592, 0x0000abded42c4fa4 }}, {{ 0x000c639ea67a665e, 0x000231e94dea0f66, 0x0004752922fd3b67, 0x0008002f8259ecae, 0x000098781142c79b }, { 0x000839e6a69aa2dc, 0x000dccb7e1026fd1, 0x000b4aec329bec7e, 0x0004d41a39e73b50, 0x0000263b2ffecddd }}, {{ 0x000014c5132e700e, 0x00086155150b8057, 0x000e8917ab8428ab, 0x000983d951892389, 0x00006f4bc50a7b1b }, { 0x000b4f4f21091832, 0x000a9361b07523ca, 0x000d80cd15d93e68, 0x00013de5a2f6219c, 0x0000812154648f57 }}, {{ 0x000a527e6b978cee, 0x000db82cf7d62d27, 0x000ca96802e48946, 0x000e9519e1f36e29, 0x00007265e87b84fa }, { 0x000802786e991660, 0x0003097581a85e38, 0x000f541313771b92, 0x00067126e1f1a520, 0x0000d10aa19b0e7d }}, }, { /* digit=15 (1,2,..,64)*(2^{105})*G */ {{ 0x0006f0af00724aea, 0x0002a9e36f09ab05, 0x0009f3200c5b7d67, 0x000971f9803f163c, 0x0000abeb83ab4494 }, { 0x000dc4a79b89e736, 0x00099ec70880e0de, 0x000ed078e9a3f10d, 0x000e77ebd7332a66, 0x0000efcf0956aef4 }}, {{ 0x000dce3782cc4229, 0x00054d0c55c44969, 0x000687ed744ff73a, 0x00095ca63a6a9635, 0x00006189f2556fe1 }, { 0x0005e2f1f92bf8e0, 0x000c16ab2b91f71a, 0x0002b5bd2443b5ec, 0x000ec35ade448982, 0x0000c8788b8a39ca }}, {{ 0x000392b0b18c6d03, 0x00098e7abded5516, 0x00086524935ee7e4, 0x000a3d6a903d358b, 0x00006875db035981 }, { 0x0006fc5d51954294, 0x0000e980b75c904f, 0x000db1fb9c1ad202, 0x000ea6532c305b0a, 0x00001aa27478cb82 }}, {{ 0x0008f862ec09473d, 0x0000ac9d64cc78c4, 0x000b52744f8f7011, 0x00038e5ab6c50621, 0x000008c758760cd6 }, { 0x0006d3b2c6ac19b7, 0x0007bede1603c166, 0x000ef5c6e18a250d, 0x0000ffdfc19a80e0, 0x0000dc276b838e08 }}, {{ 0x00006fa37070bc95, 0x000637e822e37bef, 0x000334cc36ddfbe8, 0x0005c75eb73f237b, 0x0000f47794e531d0 }, { 0x000fa0c354bdcde3, 0x000d86efc621c127, 0x0003c1174b714c9d, 0x000d773f35d624b6, 0x0000fc893443d0bd }}, {{ 0x0003d69f745fb237, 0x000c331e3229d41f, 0x0001a07c7c60896f, 0x000214b09a929c65, 0x000030eff0f7b347 }, { 0x0009ce6bfe978f9e, 0x000339a168336319, 0x000d6a06afe4f177, 0x000c17ed868a34c2, 0x0000a6c91a8a3c76 }}, {{ 0x000567bcf9802012, 0x000c8aaffcdb4631, 0x000a1f3bce0ebf8c, 0x00088f58d658bbc1, 0x0000d77d6056ff71 }, { 0x000c08728ddda15b, 0x0003de03572359bb, 0x0004ca5173fe02e3, 0x00082257ccf0353e, 0x00002fdd1fd23a9f }}, {{ 0x00011cac13161f9c, 0x0001bbc453cadd69, 0x00072aef15e577c3, 0x0008c37af203900a, 0x00000e41db5e3490 }, { 0x000b87d44a487f26, 0x000dc42ec965469f, 0x00012e582d33e4d5, 0x0001872850e9f769, 0x000038b03659451d }}, {{ 0x000cc69f23d9740e, 0x000004bfc25419a6, 0x0002df389dda0805, 0x00042da3f3646720, 0x0000f63588d2624c }, { 0x000b9eea3275aa7e, 0x000665a6bc68bb94, 0x0005dde089018c6f, 0x000b34b7ce43d79b, 0x0000cca74fe735d0 }}, {{ 0x00075c28e4f6afb1, 0x00015ba6102d0212, 0x000807e8390524e7, 0x000ef68a8eaafac7, 0x00005aa40be45ccd }, { 0x00072a4f8c8e1dc1, 0x000599ddd2e54e03, 0x0004cedb11fea727, 0x000190c246991adb, 0x0000a2b27ebd40ed }}, {{ 0x0009ee1edba4daa1, 0x0001c73a6a5da60f, 0x000fe25e811523b6, 0x00078cd576f083d9, 0x00001e9fcdcfb94b }, { 0x000aaf21de46d633, 0x0000eec8bdcf8e7c, 0x00004054fc48103c, 0x00029bd40a5db827, 0x0000e01632abbb9d }}, {{ 0x000759b8001f79c6, 0x000ece14f0dd2e8f, 0x000e12ddc2c79568, 0x000005b98e77e7c4, 0x0000b791403a3eee }, { 0x000aa7ff8c7ea4a3, 0x00083eddcfe314e5, 0x0003f92dd00d49d0, 0x000ac95b6eb84c52, 0x000080d5b1ce41d2 }}, {{ 0x000baaaaa42eba90, 0x00083c3b9791a263, 0x000a922ae072d050, 0x000f042de960022d, 0x0000bdcee541ee28 }, { 0x0003bb68bfa63380, 0x000a3460d881efdb, 0x000f9276f56af417, 0x0002898d4506416b, 0x00006f83b035b65d }}, {{ 0x000fd6b0c5230ca5, 0x00013bf5116f9379, 0x0006214fd87df2b3, 0x0000cfdc87c64a58, 0x000027f51850fe61 }, { 0x00092d51304b9476, 0x000443ce8ee0e0e2, 0x0000005ed0ca005c, 0x000d248e06f6fba6, 0x0000747a3ca00962 }}, {{ 0x00048c919c326cd0, 0x000405dbab093b30, 0x0008fdf707eac1e4, 0x00007d89c012f59b, 0x000033b871966602 }, { 0x000eaf517a2fb4d1, 0x000d1b591071cd58, 0x0009749a1f2b94c1, 0x00002c84b791ed89, 0x0000772ac30fc8b2 }}, {{ 0x000da8e4f1aff818, 0x000caa2d551ee106, 0x000804d524b4b06e, 0x00008fc8d87a8f1d, 0x0000ef431fbeb97c }, { 0x0000c0d9b00298e4, 0x00033f0cf9a4e718, 0x000fbb34f16943d4, 0x000ca08c0ff50200, 0x0000745ea7a228cd }}, {{ 0x000d1395ccbc828b, 0x000e6d8033f28764, 0x000630492e0f2bf4, 0x00047311db0186ec, 0x0000dac857b0b37f }, { 0x000038d71b0c1915, 0x0004dd6186244a03, 0x0002e0d184389b23, 0x0000269ab918e5f2, 0x00006cc928b6af68 }}, {{ 0x000de6ad0f11bc0e, 0x000f6b7a93c32461, 0x000982d307be7245, 0x0001a341821ab606, 0x0000a0e9cfcf1ca0 }, { 0x000b972fd6728dfb, 0x000af88ff1929c78, 0x000ad87757dee47c, 0x000d111ccc6df4c6, 0x0000d7c581401c53 }}, {{ 0x0001f7f91b4ffc66, 0x000d0b60b846531f, 0x00051eadeb59f002, 0x0004950c5ba7e45e, 0x0000b7e2a63df2f1 }, { 0x0004c828296f804a, 0x0005c9244de90d77, 0x000a7cd199349397, 0x00056f3eb951a1d4, 0x0000788cafa21d5a }}, {{ 0x000ce2e57adaafd4, 0x000a4fce7560b907, 0x00012b053f53cfb7, 0x0009317a8b4073e6, 0x0000b35cda57c1fb }, { 0x000b6dd71e0124a6, 0x00021891df1ad467, 0x00018e156fdf889e, 0x0000b1b7783a0692, 0x00003ab3282c54d9 }}, {{ 0x000182d411742393, 0x000da0a73fa9cb0d, 0x000d6109219851e6, 0x00008f982edd3992, 0x00006166219cbf0f }, { 0x000cb8df03c5c3e4, 0x0009038d9a528dba, 0x00091e3c5a90b7d9, 0x00055b47ce8b1a0e, 0x0000a0f6e1eafa48 }}, {{ 0x00012fcc62fd2575, 0x000c5328300129f8, 0x0001e7946f9a564a, 0x000bfcb511f63766, 0x00002838b2c1b003 }, { 0x00017bbc879d576e, 0x0002f5f29fb85da6, 0x000a07cb9d60a23f, 0x000afb8b772f4e00, 0x0000907e471fcadb }}, {{ 0x000682238fc10ebe, 0x000cdb997aee3170, 0x0006e19313189010, 0x000b1dd9b812a409, 0x000009ce0a98c979 }, { 0x000b75351318c260, 0x0008ad6aeccb4bdf, 0x00096db6712057b0, 0x0003d3d336a34e9a, 0x000074e57bd9af57 }}, {{ 0x000f1e0fa64b9ba1, 0x000a4ff1d7aadabe, 0x000fe6d896d5ce68, 0x00034116f65d3825, 0x00007bcae08c6246 }, { 0x000ac54f612c30f9, 0x000ceba33db72cdc, 0x00092fb725511bb6, 0x000d9573c017cbc0, 0x0000a29dfebf2fc8 }}, {{ 0x00044c4ab2167d7a, 0x0005980b2369f0f0, 0x000d1f7b169f84ef, 0x000e52fc697d3a70, 0x00000371cf064a81 }, { 0x0002f2497b167080, 0x00020fd834a2ddc6, 0x0002698938f1ecee, 0x0008c649049e6b86, 0x00006463bb9f084c }}, {{ 0x00070d2d35f711e1, 0x00024b6c64582934, 0x0006a1c3ddc10d9e, 0x000d436b836bb527, 0x00000a5cf78fdd97 }, { 0x000e797ecd201480, 0x0008832feeb1b77f, 0x000886ec00cee664, 0x000e180042bb75c3, 0x000057f8a6d620a0 }}, {{ 0x0008abdd527350b0, 0x0003c2a753aebcc9, 0x000c308e0f53280b, 0x00044fd09daf9f3d, 0x00004eb1613ae15d }, { 0x000462e7e6da22c6, 0x00044318d168be52, 0x000ffec2ba55ff61, 0x0004c09afcf7c10d, 0x0000ff5b8008b9a4 }}, {{ 0x000d3eea67fe0e27, 0x000638ba0cc3f125, 0x000d5f283fc1ad1f, 0x0006105d368dd485, 0x0000f512d2d3ea5b }, { 0x0004dc21e92938f6, 0x0002481e6602671c, 0x000f4f264a2357d1, 0x0007c19858f144a3, 0x00008d20d20e844d }}, {{ 0x0001db64b60dcc0f, 0x0001eea521d03782, 0x000de325b7b9b75a, 0x000800aea802b8e0, 0x0000a207924704fd }, { 0x000e7c824e8b91d0, 0x0007ee970342f9d6, 0x000dad47c7c593a7, 0x0006b3baa93a10ae, 0x0000b3c50420ccb3 }}, {{ 0x00044dd196d3754c, 0x000ae819966e7eef, 0x00071169c0771aae, 0x0001b5ed464ec4aa, 0x00006b0c6bc0965a }, { 0x000ca9d721b441b9, 0x000b8f1bb46b6a1a, 0x000350de796ed922, 0x00067beb41e65d31, 0x0000103b3fe2d35f }}, {{ 0x0000c504bf8e9753, 0x00032a0fcff6a17e, 0x00023e05782f0bc3, 0x000b8f8e39970a3f, 0x0000a169715bac3a }, { 0x0006fd0c5dcd460e, 0x000cb5677fcc2f46, 0x0006febe5366b0c3, 0x0004c78aaef1a522, 0x0000e87aa65153be }}, {{ 0x0000903c4cbe46bc, 0x000c0eb1bf4581ca, 0x00060c177519da3e, 0x0005066ace635e18, 0x00005345445cd5a7 }, { 0x0007197ca469b8c0, 0x000858948f214029, 0x0004225140fdccb5, 0x00087719031b49c1, 0x0000a2053b8e6576 }}, {{ 0x000332d0815fb0b2, 0x0002b1e274983d81, 0x000e423eac0e20c3, 0x000b147d1da1a3bd, 0x00005049bb2f20a3 }, { 0x000aa2f407901242, 0x000b5a3aa6d0e10a, 0x00034aac28430b6c, 0x000c1136717db2e7, 0x00007894ad4da6bc }}, {{ 0x000fe4ca540470ce, 0x000a79e7ace3fc7a, 0x000e95c40e7284f5, 0x00012800e9594eac, 0x000074e26fc1378d }, { 0x000ab186fc36c333, 0x000b556e6ee81c69, 0x000ad0d7933ec714, 0x0002305298f671be, 0x00009b93b73b2fc4 }}, {{ 0x000df0fefced17bd, 0x000f66910b5be761, 0x0009dd130cd0a056, 0x0005c2188046b773, 0x0000009bdb10a2de }, { 0x0009ee86e04a5ad7, 0x00080a6bcfcd0279, 0x00052142deea631c, 0x0003ecdd9a8786c7, 0x00002b9a476e5434 }}, {{ 0x000074d3de5dd49a, 0x00093ddc15c9f0ab, 0x00039220c4bffda7, 0x000fbf5dadf87a73, 0x0000e0074caa9da5 }, { 0x0006df62f75d4dc7, 0x000b20351a03776e, 0x000a43811d0fc2f2, 0x000c76a852bb1f77, 0x00003d9c33f35883 }}, {{ 0x0005c11927d7db11, 0x000c0beed51275ad, 0x0006594e2f1817d8, 0x000e7addf5de47dc, 0x0000c87b4cd166bf }, { 0x000890cd3245ae9a, 0x0007800a73a294ea, 0x0009f531344057c6, 0x000c0b66a5f88434, 0x00007a6fab6ca15c }}, {{ 0x0005929d26ae4d60, 0x0004ec170f4d3b44, 0x0008ca69efd95c9e, 0x000881838fd1a136, 0x00008822948519a9 }, { 0x000418f5d76d3725, 0x000ab6025b15ca6a, 0x0000ca2e4e6eecf5, 0x000e72c344b3c83e, 0x000017e3caa4a180 }}, {{ 0x00041b28983194f2, 0x0000a8a213ed68b6, 0x000cecef298c37a2, 0x0005ba953860ae7e, 0x00002530dfcc9dad }, { 0x00085a2310dabfe5, 0x00053e101110f35d, 0x00018c30f6264efd, 0x000d17ff479c26f4, 0x0000836740a708c2 }}, {{ 0x0002dda543915e7e, 0x0005f5d4b07e2b19, 0x000afac0fcdde015, 0x000a72d14d144c4c, 0x000034e73127607f }, { 0x0002db773ecd3720, 0x0000fa8cf03dce66, 0x0004b74758be1c61, 0x0007668c48b5ea96, 0x00009b6250934072 }}, {{ 0x0006f31c01a3dfbe, 0x00044fb93f245674, 0x0009ea5f3bc92e2f, 0x000eafb87fd46c69, 0x0000f667b3eec5e7 }, { 0x00083cc1ece5f671, 0x0006a59888b219e5, 0x000789c00b155ab8, 0x00029106ce50ecc3, 0x0000f8a9874cc0ab }}, {{ 0x0009a7ffecf51501, 0x0002d66a483bf119, 0x0005180ac17cfeb8, 0x000d4f928fa08a6f, 0x00000c4ee2e35856 }, { 0x000cba1424521b06, 0x000b7dbc4ae62da7, 0x000dba90db391823, 0x00031ffbc6cea00a, 0x00007680c0ab694b }}, {{ 0x000ff63e0965f49b, 0x0003121208490def, 0x0002bd04ea6fe3be, 0x0007b166f1ca66ec, 0x0000bbe50fc3adb5 }, { 0x00010d8a6a559d7c, 0x000debe8b2610bed, 0x000f68d0b38a6296, 0x0007eb6b4b732ed7, 0x0000e692b4dee5cb }}, {{ 0x00046bae92221adf, 0x0006498ed4de248b, 0x000d5bdcda959eec, 0x0004c5f13d7cedac, 0x00004112599c6663 }, { 0x000b84c4c8c12811, 0x0007372fcef7ad8e, 0x0007e92e99ce45e0, 0x000ba88866115160, 0x00004192a1db5e1c }}, {{ 0x000f01e9b964c398, 0x0002d5c164e1214b, 0x000ce245d14a5d2b, 0x000e5d035891be86, 0x000058456cfb56a6 }, { 0x000ed62a7c96800a, 0x000d739b186ebc0e, 0x000596e2f14dd4cd, 0x000592e54d5c74c2, 0x000037f83089202c }}, {{ 0x00069dfbf102d869, 0x000846f76b7618a3, 0x0004cd18647184a0, 0x000791ddbbff750a, 0x00000418f22b31b3 }, { 0x0008af82f7454899, 0x000196c7191a321c, 0x0008783dee978292, 0x0008738839edac3f, 0x00008a38ad413f8b }}, {{ 0x00018d12afd54f4c, 0x00098d897ce0b2a0, 0x000fc2184a2fde82, 0x00068cefee6d7c87, 0x0000880946a4e593 }, { 0x0008157478782d1a, 0x000480801206e150, 0x00039ba30e4db2ff, 0x000d448d5e0e4245, 0x0000a2f55c162b2c }}, {{ 0x000d7803581ab555, 0x000eab4820357c72, 0x000e419c5554fe07, 0x000fef5a1992039a, 0x0000d9875b456d0a }, { 0x0000ee0ea7058063, 0x0001b4dc77ad4d4a, 0x000858f1411d534f, 0x000f0bd5ed49a799, 0x000050a8f7fd0e17 }}, {{ 0x00033d6d545551ce, 0x00020cfab7bd7712, 0x00031284f564f60d, 0x0004b93e76c87307, 0x0000270e7036f3e7 }, { 0x0004b690d19b6f88, 0x000ce26fc195bcc5, 0x0007b020fa92369c, 0x0007d06f32544595, 0x00005326f8c26b7c }}, {{ 0x000a5acf73de976d, 0x000bf8a212306466, 0x00089df47218a462, 0x000994d43f51aabb, 0x00006b738c5c4d3b }, { 0x000ea5938bb50b53, 0x0006057d635b4d5d, 0x000d0e302e4e6897, 0x0000f9dddc3de68d, 0x0000247ceec78021 }}, {{ 0x000446bc5330e6c4, 0x000131afe637294c, 0x0005e1616084d14b, 0x000a79fb501968aa, 0x00003b7dc534fcd3 }, { 0x000178d549b09def, 0x00061a696d6134bb, 0x0004ec90cb133eee, 0x000053a1a9361fbf, 0x00006af0a49f5d2c }}, {{ 0x000b745f8fc43a35, 0x000024ba4df39156, 0x000ec4617678c3bc, 0x000a91c02566ce1b, 0x0000719b228fbdb9 }, { 0x000f385adab6fcc4, 0x00066f663122edfe, 0x000c4c603faed143, 0x000bd6d563190f9e, 0x00007f12983cad34 }}, {{ 0x000f1627dec28dca, 0x000b7de3f642c293, 0x000851f9d3a9edf4, 0x0009b5b4620be088, 0x00004176cb7f6c12 }, { 0x000787c0dcf777ac, 0x000f413eefcd6385, 0x00061d44b6e6ae82, 0x000d1495e8f3bf62, 0x00007ad2517a88ab }}, {{ 0x000193cecacc8855, 0x000e5a2d9a23e449, 0x0002bc7c9a4324de, 0x00070bc0888dfa99, 0x00001357e1a16b5f }, { 0x000cdf57355cc9f8, 0x0003a7d2d738fc52, 0x00076a8097379e6a, 0x0007681a56697b03, 0x0000e15f32fe6b63 }}, {{ 0x0000441aedd1db0b, 0x0003920bd55659e1, 0x000b3331ee1ea4b9, 0x000604e1a7973e32, 0x0000b848523ff344 }, { 0x0006429320a3e8ed, 0x000324a045ad915b, 0x0006ee6d1990975a, 0x00014ced86c11b43, 0x0000ed1e5721bace }}, {{ 0x0003cab91b752141, 0x000a5e89c92b2350, 0x000e676eda85d689, 0x0001c8f31a73bbd0, 0x00003841c3e8d0f4 }, { 0x000cd61ad4ee96e2, 0x000a42f1db3574b2, 0x000537e4eb45e77e, 0x000813c06485b018, 0x00002be90410b3b1 }}, {{ 0x000fbec0cb6f0fc0, 0x0002d5a2ff9f403a, 0x000ab264cf5dcff0, 0x00007f70d8dc98d8, 0x0000dfe1570152b0 }, { 0x0008d1e1d5d329b1, 0x000c06480130dfa7, 0x00051130fb1fccc3, 0x000875ec0306dc2b, 0x000026a348354b2b }}, {{ 0x000e31318e23bd1d, 0x0006f5a192ef7106, 0x000acd43006b8a32, 0x00067ef9e88afbd4, 0x00009533ab5f7940 }, { 0x0002a21cf2ee4b63, 0x00061b824f89b4e2, 0x000826214d380f04, 0x000d957a765a5dd8, 0x0000431ac8130d01 }}, {{ 0x0009ea88981c66a0, 0x000fdee42a554f77, 0x000486443c22796b, 0x00047173d828983a, 0x0000d1238eb95f6f }, { 0x0000e913e1673541, 0x00064a7d065fd831, 0x0001a1798cdb2234, 0x000f61027f49af79, 0x00009e532ad5d547 }}, {{ 0x0006b46e1f443280, 0x0001d14bc21ef518, 0x000ac63104730cf1, 0x000894c3be51c3ce, 0x00000536de024903 }, { 0x000be017a2ce58da, 0x000e02380041ef4b, 0x0004a6821c8b404d, 0x00079bad4d72fe50, 0x00006b9d35305a63 }}, {{ 0x000b652edcec4a5b, 0x0009f09b389328ad, 0x0001f4b242d8c5b2, 0x00065eabf322fbc6, 0x0000dd15a5fc8674 }, { 0x000ea672143089ac, 0x000e72c03ec6627f, 0x000cc347decf2065, 0x000adfd0dde1b3b2, 0x0000a98c9af7b1ab }}, {{ 0x0005cdafe7faf119, 0x0009ccb4f2999aa1, 0x0006a2fe40f56991, 0x00042ecbb38476cc, 0x0000d4790f63e31c }, { 0x000bf2c38ae9c943, 0x00018a4d935b7db4, 0x0003d0a6e142ea64, 0x000ec115b648b600, 0x00003a16278132b9 }}, {{ 0x000ee635fb2543bc, 0x00020634442449cd, 0x000954c719bd8c67, 0x00024b182e0e9921, 0x000066a2b2a91885 }, { 0x00074ea6ed7740f1, 0x000314a18ee6e8a7, 0x000675f4394244fb, 0x00033dc08eed748a, 0x0000cce701dd1d5d }}, {{ 0x000add5f69c02408, 0x000d61cf3480d4af, 0x0006c1ad6fb043be, 0x00005529cf0d8edc, 0x0000e6b784db99a8 }, { 0x0005a454130bbd68, 0x0002fad96f8acb1a, 0x0004c17786cf7d98, 0x0001fdbf4bddd49d, 0x00002c7d15e91516 }}, }, { /* digit=16 (1,2,..,64)*(2^{112})*G */ {{ 0x0003c0440fd7f2f9, 0x000bdbfc360e25a8, 0x00048399d668b4f6, 0x0002439f4e642519, 0x000089f1fa0b9870 }, { 0x00097b3d282ee427, 0x0008cf1d720281f6, 0x000e67baa329978c, 0x0002104e72205910, 0x000061a43a34e6ac }}, {{ 0x00071279a45648bd, 0x000de9afb3ff9ed0, 0x000b10e3d7b7d810, 0x00004e74928c2e0a, 0x0000f66bf52858f1 }, { 0x000e9fccc7111eb0, 0x0004f6601fbe8556, 0x0007f13a84fd868d, 0x0003acc0b3ee394e, 0x000011bb82692f56 }}, {{ 0x000f57841f3144bf, 0x0001f9314092ebb4, 0x000cf3369fecda45, 0x0008e3164f17256b, 0x000033b176e2d462 }, { 0x000333e4efa6df27, 0x0001d05e708d8553, 0x0001d0bddee0a802, 0x000f8c7d5856aae7, 0x0000603c90846016 }}, {{ 0x0007512e2eb6a7c2, 0x000b8dedda492f81, 0x000a60d843d6851f, 0x000eb594cc11a3ae, 0x0000e9fde037b87d }, { 0x000cf109a400a483, 0x000c6f3177bf8b6c, 0x00093bd6f59a5d1e, 0x0006c915d232ea4b, 0x000066d0031672f4 }}, {{ 0x00008a54ec2b1382, 0x000f888a1f258972, 0x000f812b7fecbc4a, 0x000e06b5c7ac6961, 0x0000e7ee6a3486dd }, { 0x0003eeb9a9acb8ed, 0x000811978660710a, 0x00067f8f391f11c9, 0x000b760a50cf70a9, 0x0000a64a54a69740 }}, {{ 0x000869d0d5ac68e0, 0x0008233169bca968, 0x0003a53cda259d70, 0x0005a1a9404d286d, 0x000088e4951616f4 }, { 0x00052a733ab82011, 0x00026e5d0150d651, 0x00030ee1a18ef179, 0x0006e1c49a92e250, 0x0000660861970a58 }}, {{ 0x0001843074252dfe, 0x0003f588434a920a, 0x0002c09cd3518f04, 0x0005fc19ac0af8e9, 0x000065ea1ee67b6e }, { 0x0000581fc169a790, 0x00004aa5447ab801, 0x0005b7021d9fcb63, 0x000998a9ee5e5a32, 0x000086ce09c0bdfe }}, {{ 0x000b0da855c77138, 0x0004d7080eb24a90, 0x000d3d8064a79971, 0x000e895b87bedfb4, 0x0000ff2e824b81fa }, { 0x000939b48c4a16ef, 0x00015dbde314c709, 0x000bd2f933b9e136, 0x0004c0d9ecdbf1fb, 0x000042e460791f67 }}, {{ 0x00031e066075581e, 0x0007aa7cb0c9c8cb, 0x000fcea630fbe552, 0x00099ab0f75105f2, 0x00001f912867f6e9 }, { 0x0004564766700a62, 0x0007075d4b6d45a8, 0x000cde96422fe35a, 0x00087645bd363f3a, 0x0000ada1862cd2d3 }}, {{ 0x000f0a0c47a9219b, 0x000f3cc37107c78e, 0x000a68021e1e77af, 0x000af3d45acff3b6, 0x0000e6dd110491f2 }, { 0x0006145e628202b8, 0x000de5176b6028e0, 0x00041e71b471983e, 0x00035f755c49ec67, 0x000098d7591e8ff1 }}, {{ 0x000bedcf6b007f50, 0x0000d07e75746b54, 0x000d781ea953336a, 0x000b0a8e21c1e1f6, 0x0000184b09b48421 }, { 0x00054ff226110b80, 0x00069c13d7a4c8a9, 0x000bd88ff53a5a2c, 0x0002edbbc2748887, 0x00009a72c0defd99 }}, {{ 0x000775780f973b43, 0x00047b197c3dfb92, 0x0000a7a109452cf0, 0x00079c39255a549b, 0x0000db1d2d13d82a }, { 0x00002f1085a734db, 0x000a5b8e1c9d7c80, 0x00013facbcd0a776, 0x000350fce8c69dae, 0x0000dfeeec7f75f2 }}, {{ 0x0000deb4ca3a9977, 0x00053446d3fea556, 0x000693a2509e138a, 0x000c97b7db4ae9c8, 0x000056217a7b50ef }, { 0x000b113eaae38142, 0x00096947de6c34cb, 0x0008898319d2c511, 0x000be485b4ee6825, 0x00002fb9bee4a336 }}, {{ 0x00009ed751690d07, 0x000fcb92115b4c9e, 0x0007a869f38018bc, 0x0000b109a7c163d3, 0x0000d25180d0c741 }, { 0x000626f43012e59c, 0x00047fa26f516cac, 0x0006c84c3b619391, 0x000580cb4753cacf, 0x0000d99e17d2ba70 }}, {{ 0x000d31e20e626aa0, 0x0002899a7b56eaf9, 0x000b97bd91088d33, 0x00016ea8600c0e52, 0x00005520570c169c }, { 0x000e6b9cffa1bae0, 0x000b32d3ed689748, 0x0007ede2eac48130, 0x00023baefe44bbc0, 0x00004454704b6e6c }}, {{ 0x000c8ac9b3f30faa, 0x000821f711b0eb9e, 0x00078b7fefa0a379, 0x000f7e8dbb905f2c, 0x0000d9b3674355ae }, { 0x000e568622b92879, 0x0005fb6b40a24474, 0x0001518d75018f42, 0x00065c23f60121fc, 0x0000b6c0f8efac61 }}, {{ 0x00029b6e563d4ca5, 0x000090d196aa5a1c, 0x00064da647a59d2e, 0x0006673b7e0df8c7, 0x00003ebfc59c82e9 }, { 0x00077c02963ba3d8, 0x000dc8b711484633, 0x00032cc947dff086, 0x0005fd3e4b5738de, 0x00002458f4cf0a1e }}, {{ 0x000f18fb2162c8d8, 0x00018b92bb39c1fd, 0x000c06efdda4112d, 0x00032e00514373f2, 0x00001c606faff29e }, { 0x000b75dfb7307746, 0x000394242b3523f1, 0x000d6c807144512e, 0x00093377ce958532, 0x000075bf8f2eff5a }}, {{ 0x000f8237e184aa56, 0x000a1c92d7d1413a, 0x0004e8b2bdb60c3a, 0x0005e6de867e2d6b, 0x0000a224fd131823 }, { 0x0003b73e5c38837f, 0x000e0dc84687cee2, 0x000181fb2daced27, 0x00066f750c5ded6b, 0x0000dba3169b9090 }}, {{ 0x000e01470209ad8f, 0x000b4183037bf522, 0x00054ac5ded5224d, 0x0000656d7b61e6db, 0x0000906aa9885eb2 }, { 0x0002c37583833f85, 0x0004a9a360aa449b, 0x0004c69fd7852936, 0x000bb90efb70cfd0, 0x0000ef760d62ea7c }}, {{ 0x00045a8ff05fe573, 0x000ccdcf50225f97, 0x000c3c869b135443, 0x000c34c64c52e175, 0x0000b6e1d4a6ca70 }, { 0x0007a71cdf35f6f4, 0x000f1a358321bc3f, 0x0006141dc268fae0, 0x000f35c58b1732be, 0x0000235d7150b4b3 }}, {{ 0x000eeee592f8a112, 0x000413e894c5bbba, 0x0008bae94aef8e2b, 0x00074b0446915c7d, 0x000077f05c59725f }, { 0x000df69b21ac3da5, 0x000f813781354864, 0x000ec8c0d40ddda5, 0x000f943f53a275c1, 0x00001739b2d5fa33 }}, {{ 0x00040e9f29ec6f84, 0x0002e502d0f39aaa, 0x000a7199ba1db519, 0x0007170fa622118b, 0x000062772036e611 }, { 0x000754b54fc3aaa5, 0x000aceb22b57f0fd, 0x0008a72baefab7bf, 0x00045f0fe849a33b, 0x0000513d3bc11f59 }}, {{ 0x000b33f80501f2c1, 0x000fa22236f4a982, 0x0008db3408b65b08, 0x000a7b6740b0c59e, 0x00004d2185638a58 }, { 0x0004d80f0e06a637, 0x0005b9532e6c4662, 0x000f29818d65accc, 0x000b5facc68956d0, 0x00005c86484c910e }}, {{ 0x00093cca39225886, 0x00097fb988baf015, 0x000d82749c0eab29, 0x000f43360e6331a7, 0x0000dde7d468f9e6 }, { 0x0008a7318da83916, 0x000968d265674566, 0x000957a433029011, 0x0007db2f640fa030, 0x0000ecd715314932 }}, {{ 0x00048c5860d99716, 0x000ba4efc4d31579, 0x000197676589c678, 0x0000e5b72b56f8ab, 0x000013465a13e776 }, { 0x000bbbc6da512eeb, 0x00072f00ebd4f086, 0x000ca2c6ccb3e2fc, 0x000b072d03e5168c, 0x0000f06060e5f45f }}, {{ 0x0005959cbe186e9c, 0x0003886605daaa67, 0x00074604cfe0af51, 0x000b65f8946fd72b, 0x00007a875d7ef388 }, { 0x000a73bb803de3a1, 0x000fe65c8a588eea, 0x00060d978e1d0473, 0x000b6bcf1368c92e, 0x0000847dbedc4d5b }}, {{ 0x000eb1b6c88eb6f6, 0x000b10d6457d188b, 0x000accc881c36490, 0x000166a1386eda86, 0x00007a87d33e3d7e }, { 0x000eb5009735b4ad, 0x000768799240a9f2, 0x000f48ac891ad54d, 0x000b16c3a1bbb384, 0x0000158d9593875a }}, {{ 0x00040b8b0c182e20, 0x00089c04a7d2caa5, 0x0001519f1783ee26, 0x000194e8f6f3fb3d, 0x0000f047804535e7 }, { 0x0007a5b479c3334f, 0x000ebc905e214f55, 0x0009fefb01bee293, 0x0006b190b9a74075, 0x00007399d8ab170b }}, {{ 0x000505be1efb2b17, 0x00031e726bfe65cf, 0x000b7d8b04e8129f, 0x0003ed02e097e391, 0x0000ca6e619f0f6b }, { 0x000d838a95ee8071, 0x000cda1e3a3035a8, 0x00060f518312713d, 0x000e396f26431ebf, 0x00004e5e1383c630 }}, {{ 0x00083bf494f1922a, 0x000d07f650006f01, 0x00033885071d3899, 0x000678396dfd7dad, 0x00008e6b9b5a00db }, { 0x00061e1a6d262a4f, 0x00090434a7bd989d, 0x000bcf24f627dcab, 0x00019a63e505385c, 0x0000162da51b10d7 }}, {{ 0x0002b23a10647092, 0x000b4c64a8a3d626, 0x000fc1c509c1f5da, 0x0008752338469c4c, 0x0000592d71f92d24 }, { 0x000e65e5e66ab21c, 0x0007ab4a63d1a4c4, 0x000a2eb259587d83, 0x000fd941c454e7fe, 0x00001e808c047aac }}, {{ 0x000985fe38c5fb2d, 0x00031a1ef74c45bd, 0x0005d4ac86cd7bdd, 0x000df50a92cfbfa6, 0x0000f38525a7bc74 }, { 0x00027e0dfe332909, 0x0005ffe5a0148b4a, 0x00068afa056fbba5, 0x0008e20ce6f9a55c, 0x0000c1b3d8c7c69f }}, {{ 0x0002ab75b80ff311, 0x000335212b4603ee, 0x000088c4f75c8654, 0x000b6c312a876c55, 0x0000ec0c5bfb1759 }, { 0x0009a79cb22aa461, 0x00039761a23ff976, 0x0001f38e005de83b, 0x000defe22c613899, 0x00008b2f4e8bfccf }}, {{ 0x0005afec02a30992, 0x000a30d594cc7e13, 0x0002fda0bf775275, 0x000f5c74a3079ca6, 0x00002d8fc95c11f7 }, { 0x0008853e7d3553e5, 0x00061f406ed2c6ed, 0x0004a50e5bda669a, 0x0007d947e58da173, 0x000046a193aa855a }}, {{ 0x000e471b95b01638, 0x000188da35fcd5fe, 0x000b5b15af55904f, 0x000cb71628965df8, 0x000058d0fcc4ba62 }, { 0x000d74938578142d, 0x0006ec80a08fb758, 0x0004f469a20c56dd, 0x000db2288704958f, 0x0000e41307922cc2 }}, {{ 0x0007a222bccd2e68, 0x000ed378c9049f43, 0x000343f0b5f94e09, 0x000b4556b5be948f, 0x00000a6efbb7a0e9 }, { 0x0004a461c9039832, 0x000e8bb8809bf618, 0x000b8ea28fc4e42d, 0x000e3db1c46f07fb, 0x0000437a4a4ab1e4 }}, {{ 0x000e03fdde9732a4, 0x00038e6d9278d982, 0x00036ff876027328, 0x000107dc324d9481, 0x0000e4b863ced76e }, { 0x0002045a740a4e7f, 0x000871947b533c0b, 0x000e7a9f65e10697, 0x00067ac8f1a8bc73, 0x00005706a2f93e11 }}, {{ 0x000fb693dc0269f5, 0x000e0afbd76e195d, 0x000c898214343849, 0x00079e0cb478dd1a, 0x0000bf92ae14b76c }, { 0x00050e61bd7654af, 0x000959651dbf1a78, 0x000e839485a58314, 0x000470b9acab4b4e, 0x000053da0f7c685d }}, {{ 0x0008bb92b4197f71, 0x000bfe3dc09508b4, 0x000f2b75e3a19e68, 0x000e99255faf6d2c, 0x00008a43244b37c5 }, { 0x00012686517eb89e, 0x000b6845c7cf8929, 0x000944af69cde6fe, 0x000877f69f6cd7ac, 0x0000c9b055220817 }}, {{ 0x0008da07e4a739f9, 0x0000013b78c558ff, 0x000acfd5d2c490d2, 0x000b770d343c0bae, 0x0000eee5df52f0ad }, { 0x000001122fea8b0b, 0x000b99da8a90ea83, 0x000b53a188f1cbeb, 0x0004dc77681c1ff2, 0x0000b1f2bc907c40 }}, {{ 0x0000f5091f08fba5, 0x000efbe6718e4488, 0x0001fb4964f4d8db, 0x0002b10ef246c148, 0x0000fbde6b0ad954 }, { 0x000f886488030d36, 0x000f82f724bdd38b, 0x0003c4e9843fc28b, 0x00002bca902e915b, 0x000027da8403820a }}, {{ 0x0002c8cdd5a84a71, 0x00075a6c93f72d63, 0x0002980f33151397, 0x000628017d5f75d1, 0x00002b6fc243ca3f }, { 0x0001bcaa034d4c38, 0x000e1927023c4994, 0x0006f72f8efe26d5, 0x000c24bf0a8afe5d, 0x0000af62213dc85b }}, {{ 0x000bbee6e35723eb, 0x00074f98d2668d5c, 0x0009af1932828c67, 0x000a2e3110715281, 0x000018a72e0098ac }, { 0x000b8bfd572fd9c8, 0x00047e80cdb9808a, 0x000652b2d5bdd6d6, 0x00031881817d6e06, 0x000045b2eb036f1d }}, {{ 0x00010e2fa9c3473f, 0x0000b59513aed8bf, 0x000c403da0d07f42, 0x000fb7682f77f3b6, 0x00008f8e17dae5ca }, { 0x000f98a2d0c72d35, 0x0001b2262a2f201c, 0x000f81558fe0288c, 0x0007a54a84d59ea4, 0x000094d0140957a6 }}, {{ 0x00034de6ed85c687, 0x000eb39720943c28, 0x0004b642d2e37390, 0x0002c014aba044cf, 0x00009c5d21883610 }, { 0x000c0c6eeb0043f2, 0x000fc9a5f25bd125, 0x000a136e4386c89d, 0x0008c19769259cea, 0x00001522a51ab777 }}, {{ 0x0008f8514711e5e4, 0x000de0f5606b81d7, 0x000494a0cd9e404c, 0x0004cf551abd7b37, 0x0000aae61990ee74 }, { 0x00069b8f8064759f, 0x000d4f0f30c3282a, 0x000000ed938b30a2, 0x00022f77f0da8ac8, 0x000034f8a1881bef }}, {{ 0x0003840fe88767bf, 0x000b8176add85450, 0x00066f408b7e5e73, 0x000da5e771b71cb6, 0x0000d35c39b650e0 }, { 0x000174cced9e5822, 0x000b8d51ec699775, 0x0008df0a9a391539, 0x00071f40cae243fb, 0x0000e2156e1d8e4a }}, {{ 0x0008e419d542ad83, 0x000d666e58ba37d6, 0x00020f33198855f5, 0x0004e44bffdcc8da, 0x000059353e915b41 }, { 0x000e22cd180b3421, 0x00018f402a403801, 0x000f01c6aaa43566, 0x0005abda688940fa, 0x000095b351fd3384 }}, {{ 0x0006fb438a17556f, 0x000f9ce59ffc3e20, 0x0005bae3a15dcb2f, 0x00027446360aa1b5, 0x00007cd6cec33e6c }, { 0x000544607e7d51cd, 0x000b1c4500d8e20f, 0x000c112c7a91b2e3, 0x000e9affd1ad9095, 0x0000a60766068749 }}, {{ 0x0007d49c6cff6daa, 0x000e9b1a20ef103d, 0x000f93d1bb0e184c, 0x000346aa0ad85912, 0x0000118d622a8970 }, { 0x000916a1f7d47a14, 0x000d88d20bb569d7, 0x000275e91a3c185f, 0x00072f067bd4b250, 0x0000837bba3c6297 }}, {{ 0x0002546a940f5586, 0x000c37d53a4f5668, 0x00041560fd7cc5a3, 0x0003f20218973466, 0x0000fc85e2f5dff5 }, { 0x000a16ad6208772e, 0x0009d19c61ac1625, 0x000c51965fdc16c3, 0x00040bc4352f8fa9, 0x000086c395e5c1ac }}, {{ 0x000644324f2ef32f, 0x000897f4faed184c, 0x000c89e5c21081c9, 0x000d382fc5f236b1, 0x0000323cdb72b7dc }, { 0x0000ed6d6bc3b8ef, 0x0002e595c5d84462, 0x0006f2c0ac0dca60, 0x000ecadc7c020807, 0x00002650966fe977 }}, {{ 0x00067238b80e6e38, 0x0008219b6efcffc7, 0x0008214e7fc3fae4, 0x0003bf8bc60f12d6, 0x000005e6dec70c8e }, { 0x000a94dc7004d5b7, 0x0008221501b5d92f, 0x000ec80e9ac7e6f1, 0x00043be433279e3d, 0x0000bdaa02065868 }}, {{ 0x000ae57d7389dc14, 0x000a01a530ccbbd2, 0x0006bf9cb7b1e9b6, 0x000fd790c87c8214, 0x0000c004262ed87b }, { 0x000d81a25c341115, 0x000e2bf3042a6dd3, 0x000fdbe2d8085f66, 0x000b98267b1a007b, 0x000031f1387a3dd8 }}, {{ 0x000030f0a67c1e0d, 0x0005af8ff81578e1, 0x0000801453d6f902, 0x000e79d6f7862215, 0x00001e2caf4c2888 }, { 0x000a817bd311699b, 0x00004151f0bd7390, 0x0007dc5d42b22089, 0x000fde3982d7989c, 0x0000a862ef2d9f7c }}, {{ 0x000a570c2107ac75, 0x0006330b0f2ac952, 0x000a80c9da2db964, 0x0007d589a48d0995, 0x000066ec9369c06f }, { 0x0005135ae5c22331, 0x0008bfd4e86214dc, 0x00020a4df9b2cf0a, 0x0000da66e2d014ee, 0x0000b652f2880073 }}, {{ 0x000ba378872d98f6, 0x000313ad4f3049fd, 0x00030b64fbefd2cd, 0x0002deffdbb8e989, 0x0000f27faf9b53e7 }, { 0x000726e0841b2012, 0x000cea65a72f2cfd, 0x000ea4c375be3f8e, 0x000671a371208bfb, 0x0000a839bfdbb74c }}, {{ 0x0003b681d32f73b1, 0x00029a5061f16587, 0x00016b5650dfe8e1, 0x000c99fdec0016df, 0x0000ea7e61216b53 }, { 0x000fc9eebda36ba8, 0x000c5c43ac343c03, 0x000d45a775638b98, 0x000ac46d49c847e7, 0x0000844582f5d365 }}, {{ 0x000647b7837876bd, 0x000ad727fe02299e, 0x000143077b95970a, 0x000cf08be6335ccc, 0x0000f0ca4f1d1bce }, { 0x000627278ca4b059, 0x000f0de02cafb8aa, 0x000f569bc5401d7d, 0x0005e2982299bc2f, 0x00009199192015c9 }}, {{ 0x00058f5c2f9e22e4, 0x000b3337933e47b6, 0x0002c8e707d309be, 0x00021299ff4ff6b1, 0x000037dd6c45dafa }, { 0x000ca95dd4570da3, 0x000b377c95b3b3ec, 0x0008648e592b39a9, 0x000b6d929fa04426, 0x00008591df48c6ec }}, {{ 0x0004d3be78cdc4c0, 0x000cba42333fc4c2, 0x0008d262e3383d84, 0x000588b2e274f8e6, 0x00001215944a8491 }, { 0x0006a7c58ef9ec49, 0x000af58ca14f530f, 0x000264f068c28b49, 0x000f57662a6e7f16, 0x0000a687c108833c }}, {{ 0x000f323c80b194e1, 0x0005603f9374ab69, 0x0004cf2404c4a6aa, 0x000bd8c50864f919, 0x000016461ee3c770 }, { 0x000be0fe51bd269a, 0x0000dae3f046a9a9, 0x000e43a90548ed71, 0x0008371a670da183, 0x00007e7cae92ca95 }}, {{ 0x0003c2f435522de5, 0x00099b6cbc613e57, 0x0004d5bbb1e76fb3, 0x00050f9d533131d5, 0x0000500dd4c4695d }, { 0x0006451f5801b985, 0x0009f93a4a375fa7, 0x000c41eea66a4aeb, 0x000b4eccf5f06787, 0x0000be0cc26ec73c }}, }, { /* digit=17 (1,2,..,64)*(2^{119})*G */ {{ 0x000274dcf1b355e8, 0x000d5ef694db7e04, 0x0007778800d4cda3, 0x00062f4e1edca878, 0x000092c279274250 }, { 0x000be2b2abb3de8a, 0x000b9b86def6d1a2, 0x0000bff865bb4348, 0x0002de558d25b167, 0x0000a14c44f5e051 }}, {{ 0x000da4a7963ed790, 0x000cc9dd111f8ec7, 0x000d3a203fc9ff36, 0x000619a51bcc33f8, 0x0000c3316282fb7e }, { 0x00058ffec2ca8e3f, 0x000cbe30bb1151be, 0x00071d53238e4f7c, 0x000c05f7854febac, 0x00007acf3890bf9e }}, {{ 0x00074fc72746a6d0, 0x000c2fcd1e0cf9e1, 0x000da997ebc1b1ae, 0x0008e884edea75f0, 0x000051ef991ea87a }, { 0x0007fb62f575580c, 0x0006c77eb930beae, 0x000a76b4c76571cf, 0x000cc0f9b504cacc, 0x000049875ab2027f }}, {{ 0x00066adbf6bb7535, 0x000ff9d29c4120ba, 0x000f1a65fd1f4042, 0x0009b85519f94391, 0x000007d911a8b098 }, { 0x0008234499aed7de, 0x000763c34bfca38e, 0x000fd1be8863128c, 0x00048439ce0f2755, 0x000013608ea8ba39 }}, {{ 0x0000cbaad6fa0860, 0x0002b769d4c54230, 0x0000af867172d5b0, 0x0007ea0a19e56eb1, 0x0000613acac087c4 }, { 0x000d6254b0899ec5, 0x00036ded92a5e67d, 0x000b41d22a615f85, 0x00021935bca4979a, 0x00009335529dd4e2 }}, {{ 0x000b6304a752fd49, 0x0007c13516e19e45, 0x00076a61d0ec2826, 0x000e9d5f656e2e84, 0x00006c970cc1cc09 }, { 0x000935381bb3523e, 0x00069363ab7e433f, 0x0000053ef767b2e6, 0x0002d839f1adea47, 0x0000b39a71be38a8 }}, {{ 0x00035142c413720c, 0x0009f2d799e9a748, 0x000e25f8b46540fc, 0x0001df95a96239e0, 0x0000745a4815a75d }, { 0x000856e0e8e441ac, 0x000ba7aa2e8807fe, 0x0004324cf2b5bfc3, 0x000bac6f529f2c08, 0x000024c840287b5e }}, {{ 0x000cb10d572b5962, 0x000ed9d918e49366, 0x000645a02c2b89f6, 0x000f43ab965035ef, 0x00005fc3fbf56b43 }, { 0x0007c7032b9ad449, 0x0000eb7a242da112, 0x000d3f646f3cae05, 0x0002e606b16a4d3d, 0x000066b08ba950ea }}, {{ 0x000b92420a9f510e, 0x0001d18e4136a147, 0x000cebfbf0b51e6f, 0x0004b2e03bacf969, 0x000059ed4c55993e }, { 0x0008945e1eb1c203, 0x0001c78c64d565c0, 0x0000085e247722f2, 0x0007b021a9f969d0, 0x0000a495ad2457ff }}, {{ 0x000fa003d16724c1, 0x000aa7d5846426f7, 0x0008a4dd404bee11, 0x0004afe48e7d09e8, 0x00004e388ffd7c0c }, { 0x000d40da8e2b1cbb, 0x000a64f17fd95965, 0x0000d88abe4cfada, 0x00066ec6a49e0e0a, 0x000085fa4175ed03 }}, {{ 0x0002031717ee94cd, 0x000f705050bad247, 0x000d50a7310c0423, 0x000ee98a78918426, 0x0000a7a77c69c5b4 }, { 0x000fd7cb763dc643, 0x000939960a94120d, 0x000d09c6e3764d3a, 0x0009a67fd478a255, 0x0000291d53e1e931 }}, {{ 0x00089bc84468e031, 0x0005ab4a595939dd, 0x00084fd839d2cf16, 0x000cd45120355647, 0x0000a31eb877381b }, { 0x00012d8643774d44, 0x000965d85a9184d6, 0x000b3e932a3180a6, 0x0003d448e562563b, 0x0000bf1cf2a46781 }}, {{ 0x0000885735dbeebd, 0x0001ea7f64085e79, 0x000399222ddb6a70, 0x000b41488b230f30, 0x00007e9e9ee9f0f1 }, { 0x000cdbdf44d9a14c, 0x000b39a652f54f6d, 0x000382d24cab9561, 0x00054a2e365c8229, 0x0000b474dc1a9b89 }}, {{ 0x000d03d7d3318572, 0x00049a354530bb24, 0x00077e0492176e2e, 0x000bd9f63bde3ef7, 0x0000086e3e2a72d9 }, { 0x000280da9fc53e22, 0x0002d9e43b6a782b, 0x0006ea07cbe66e70, 0x000c1cbd9216db30, 0x0000dfa49ad0403b }}, {{ 0x000fd508e7dab215, 0x000b68a1635e7417, 0x0009f8e8f9bf57f5, 0x000c8cb30fe14008, 0x0000d09a8cbf4c40 }, { 0x0000c96743cb7c12, 0x0002019d607ad51e, 0x0009ac772f06a74c, 0x0000b7ba20f229c0, 0x0000c906956df251 }}, {{ 0x00048234a455944a, 0x0003c913e538cd75, 0x000c398678aeeffb, 0x000c8cbffa7001f6, 0x00008153cadc4269 }, { 0x000cbd665cbd5dcd, 0x000d02d3d5b40458, 0x0005bdd2db3441fc, 0x00002b28bb0ffeeb, 0x000086864413478b }}, {{ 0x000230378fd7d8e6, 0x0004ee0425830687, 0x000b81c6aef3b01f, 0x000e83c4802da2ae, 0x00008bd11eeccd2d }, { 0x00084d402dbd9f8e, 0x000f2b571e8e5cae, 0x000bcb68e4f6d61d, 0x000fcc72e53ab041, 0x000092f0d852e5ae }}, {{ 0x0007fbf56c3f426c, 0x000c973f37f59371, 0x000db9e90739643c, 0x0004844fceb0f6c7, 0x00001850ac1be86d }, { 0x000ae327a65859cf, 0x0009cd9acf7d720d, 0x0007353f1fbfd5d5, 0x0007b6cef41fc8f8, 0x000076cef0bc0d2d }}, {{ 0x0001699a1c4e7ed0, 0x000d065c48182672, 0x000b165821a51c51, 0x000ba5a9233aa189, 0x00000691ac4135d8 }, { 0x00081497d823b2a6, 0x000d19cc2d7a7fda, 0x0008f1b3a51aa96d, 0x0000e12c7e318605, 0x000025170752334f }}, {{ 0x00044990c52f624e, 0x0000e891f5f82dce, 0x00067f1776d921fb, 0x0004105309a7f67d, 0x0000dff3f33f1de2 }, { 0x000830f09a7edeef, 0x000fe95af103e596, 0x0007257ba1c748f6, 0x000b5c9d3ece8aba, 0x00001dd530aeff14 }}, {{ 0x000520304e191d19, 0x00010b488172d014, 0x000585df6db40bed, 0x00089199a8b20bd6, 0x00006e8ca44ed0cf }, { 0x000244c2cdc93ee2, 0x000f81f2b47f7ef2, 0x000839bb0272e506, 0x000261674e07f528, 0x0000069e938f3b6b }}, {{ 0x0004b043a81d5e7b, 0x0009fc194d7d9b17, 0x0002537e3b6f2665, 0x0007b94ca5bafdd8, 0x00005587b44c1942 }, { 0x000143bdc27d5d11, 0x0009ea19e71734c5, 0x000e4b01516bbe49, 0x0008531b115d5437, 0x0000847671d73bea }}, {{ 0x000037543bac95c5, 0x000c653fc5e89202, 0x00087a6599cca795, 0x000b2a908363bf9a, 0x00000d8e95cfd516 }, { 0x000badceac56e4f2, 0x000cacc625640b46, 0x000e20185d8f1a24, 0x0005a34eacbc1051, 0x0000d0e37c834129 }}, {{ 0x0003505bb870eafa, 0x000d47c6b53f5f95, 0x0004c7c711e131be, 0x000710e1b6424659, 0x00009ecec42b7e48 }, { 0x000febceda1c9c8b, 0x0001361f2ba70b0d, 0x0008ab0f057922d3, 0x0004ebf6ad07e16c, 0x000067dbc750e1cb }}, {{ 0x0000e4587f5ed835, 0x000a7dc53868c8b3, 0x0002077caf2733fb, 0x000c31964174311a, 0x0000356efdbcfd09 }, { 0x00003d37200e52c0, 0x0002a310811b3b2d, 0x000c3c910cca75c8, 0x00047b8036144d41, 0x00004f8461ce611c }}, {{ 0x000602500ca3dbe7, 0x000f0f2b1f3390b4, 0x000c5fb3c266229a, 0x0000540a99f7a1b8, 0x0000cbac9856bd1f }, { 0x000289eb1fd8ddb6, 0x000c11c4711230f9, 0x000b6f851ea1a62b, 0x000082d8b058eb37, 0x0000dff1bd082c26 }}, {{ 0x00009e4ea0d957a8, 0x0009eabd51b9cf59, 0x00020e62d30ee577, 0x000b61a74d2aa9c0, 0x0000dc7f6451320f }, { 0x0007e947df046bb8, 0x0004c966f32dbdb8, 0x00000319c35fe24b, 0x0004a5fe2672188a, 0x00007d6b8255d4cb }}, {{ 0x000f11c4d76b7c46, 0x000e5391770f5a7b, 0x00004f3326ab38d0, 0x000ed2b2ae4d4d79, 0x0000e4ef511e46d3 }, { 0x000a61e28b58878e, 0x00065e542c4224c6, 0x000bda3bb1915d60, 0x000c95a78d6b4e81, 0x0000df4b98688afb }}, {{ 0x000f0956569ac4ed, 0x0003394e6f1cd952, 0x000cde0f10e89862, 0x0003727647512f30, 0x0000d19eb33b73c0 }, { 0x0003d7563e475d5b, 0x000eccaa82262004, 0x000cd6e91d2b1111, 0x000b651be02c868a, 0x00008a5278bd077e }}, {{ 0x000c20578305b14e, 0x0004fc7ab952578a, 0x00017ac7f5884f29, 0x000d5d242b5423df, 0x0000620247456895 }, { 0x000f807ef9d65a21, 0x00075eb21f4c77af, 0x0003ab31f4b5799c, 0x000dc92f11a79c3e, 0x00007300963434bd }}, {{ 0x00011afff4ca371a, 0x000d03d778f22a00, 0x00085a437474b875, 0x000e1d47dfb10b2e, 0x00002489cd838b5d }, { 0x00011554104be448, 0x0008926ad124418d, 0x00051618d54f49c2, 0x00010937531c081a, 0x000071b18a1c2aa7 }}, {{ 0x000d41f01735a335, 0x00073f833f6746cb, 0x00054167a0b39250, 0x0003a7ba921e46f6, 0x00006c09c11aae95 }, { 0x000d59e95785f38c, 0x000b834426ffb589, 0x00057781d8acae7b, 0x000a30f7f8055943, 0x0000f1dc76c3a6d4 }}, {{ 0x00008d0596f30cdc, 0x000bb1c8ad4cf4b4, 0x000fef6e8a21fea3, 0x000272fa40344885, 0x0000efa2f182a572 }, { 0x000acd518b235195, 0x000f9a498c364b09, 0x00046a51392ac475, 0x0000bfb02a4aac4a, 0x0000e0426618d525 }}, {{ 0x0009dd82ce983ea9, 0x000bf8fd06f56c0a, 0x000d3524f6a44c8b, 0x0005bb79da48af70, 0x0000dc57803535c6 }, { 0x000cdada016942b8, 0x0001263a0ef18d34, 0x0004f091c9bc1fc1, 0x000b1c5039fb7ee3, 0x00008fc41c7e9b42 }}, {{ 0x0005a0cad09fcdc8, 0x0006f499355a244c, 0x0005898086d8b232, 0x000e727cbe77fd2b, 0x0000f5438a6a25c6 }, { 0x000338ecde1a98b7, 0x000475cef8118650, 0x00089b6cdf5ef5b6, 0x0001cd6bcf52813e, 0x0000ef9cb64dfe26 }}, {{ 0x000e182e702cbf4d, 0x000093774921592b, 0x000cfba36ec1cce1, 0x000dd0759b4f1261, 0x0000c2c3bb484721 }, { 0x000f11d5488868ed, 0x000c37cdfc50573d, 0x000983acb7fc4b3a, 0x0004278d39ba1afd, 0x00004a4526ea82ca }}, {{ 0x000db4207965c6e3, 0x00020ee02a2404ab, 0x0003635469f7a3cd, 0x0003dcb71497406f, 0x0000db415a568fea }, { 0x000e3be64146ee7c, 0x000270fd88284423, 0x0007be7a06dae484, 0x000b58415283add2, 0x000031007377bf1f }}, {{ 0x000b74b0ed03932d, 0x00050c1e038a6759, 0x0002f0e7b233a87f, 0x00079ff53729deff, 0x0000c01ffe0be7a5 }, { 0x000184c1d9aaf43a, 0x0006c23dab407e5c, 0x0004b52e7eecb1c1, 0x00033ff2ccdbd361, 0x0000098af3b980d2 }}, {{ 0x000904bdbb6109f8, 0x000571981d3a80f5, 0x00016fdb66776216, 0x0003fe8c1fde0c84, 0x00002e8025758320 }, { 0x00011469a106add9, 0x00044d1101b68053, 0x000c189603a82a4e, 0x00069678743c223b, 0x0000a9746fe0a073 }}, {{ 0x00021ed0b2fc0d23, 0x00093845e43fc616, 0x00057eb4daa4b57c, 0x0000afaa8f328237, 0x00006ae9919db4b5 }, { 0x0003856ec86c297e, 0x0000fe1ad9906763, 0x000b234fd19d2eee, 0x0000f4401d51de67, 0x00002462d036fc09 }}, {{ 0x00033a00db254686, 0x0007615be6cdcde0, 0x00039bd26eadffdc, 0x000f7aaa61e603f3, 0x0000199ba172e7ea }, { 0x000eef4c32c845b6, 0x000ee09f7bb7fd76, 0x000dd73dccc40b89, 0x0003a2c9570f8781, 0x000026152e934da0 }}, {{ 0x0000ea7d6756508f, 0x000a13b2f7e85c33, 0x000140ae12343058, 0x000e81db55fce462, 0x00007980f96d8f6a }, { 0x000a553d4d7f0b2d, 0x00088f4e51ab9a22, 0x000a83b13f2b7013, 0x000bf6fa60587c98, 0x0000a508840aeef8 }}, {{ 0x0000b460d07f52d4, 0x000ae364da29ec28, 0x0003391112464836, 0x000853947dbdd5d1, 0x000061c41be19aad }, { 0x0005f292a360f3f1, 0x0009babf963c31e5, 0x0003765aa05a3770, 0x00003d58767f9f63, 0x00004a15f588fa9d }}, {{ 0x0003283f79a5eaca, 0x0009eb2cd21ab3de, 0x0001e06b9418e3f9, 0x0001670f9e504f02, 0x0000446de46c5aff }, { 0x000101dc7671519a, 0x0009bf6226bf99fc, 0x00034d2741f38239, 0x000ba7c2de835427, 0x00003411b6f79f40 }}, {{ 0x000e01db0d46ca69, 0x0004bc2255bd6178, 0x0002de28b6473c59, 0x0009d2a876c96969, 0x0000307faee6531b }, { 0x00082ca080d00c87, 0x000a173893a55595, 0x000aef7740c863b7, 0x000c2aef87630f04, 0x0000b32db7ee850d }}, {{ 0x00037f9c22a738a4, 0x000b2e10b1894a02, 0x0001b49ccc9d8538, 0x0007871b59203400, 0x00001570db64de21 }, { 0x0009ed518775904d, 0x000a62f4470e2c05, 0x0000fed0fd0d9912, 0x0001e0763b725f7c, 0x00008b2ac0c6733c }}, {{ 0x000b0b081e23ebf4, 0x000ff16d0115d4d7, 0x000f585e0d7bd2f4, 0x0009316415180b12, 0x0000ddbe5f1eab2e }, { 0x000974e2b1e03fb6, 0x000f48abf4f0dd06, 0x0006e3b043e48d7a, 0x000b8aefe99b289c, 0x00005cf08248acfb }}, {{ 0x000d737e72363c9d, 0x00021e206ddd6572, 0x000102802afaff9f, 0x0002f4a58e7cbdd1, 0x0000cf910137f5d1 }, { 0x0006f52b1e708142, 0x000696286ec37766, 0x000d2d6a7c82ef02, 0x0006dc73398aa649, 0x0000cffe04031902 }}, {{ 0x00032721221eeb7a, 0x000defbd803738b6, 0x000781c149828000, 0x000c99a9291aaade, 0x00009626df3ef586 }, { 0x000571b8055894f6, 0x00032f0862c51290, 0x00092dafec9b2579, 0x000acd28f0a8f79a, 0x0000403590545ef7 }}, {{ 0x000f5f638ebe18a2, 0x0002adec95207114, 0x000ced2c21311398, 0x000e6511455a9e4e, 0x0000ba02dffbaae3 }, { 0x00017596079bc6ae, 0x00070d32bf9341bd, 0x00007bcd3fa21e63, 0x000a719c5d63c132, 0x0000589ce7628195 }}, {{ 0x000076bc4095656c, 0x000b41ff9e6ed353, 0x000536bfd61a4343, 0x000f2aef7b7b5ee4, 0x0000916f72ab7c03 }, { 0x00070cb65edfe066, 0x000638c02dec312a, 0x00077c8115197531, 0x000bba2c9270de89, 0x0000cc65c87f3d73 }}, {{ 0x00032e89869168bc, 0x000050ecfe57bbde, 0x00055272392f1fc6, 0x000b3abbd82c7b65, 0x0000528c02084684 }, { 0x000152ce2cb419fd, 0x0009744d11a5529a, 0x000182d52bedc6a0, 0x000877a0ae964ed0, 0x0000f927ef680070 }}, {{ 0x000871bfa5e6e0c7, 0x0008ca48ec07649b, 0x000f8d2c14ad8a64, 0x00083ea1018b4c28, 0x00004818a1be6e94 }, { 0x000b0cdf9b0c7f86, 0x0008ce59e2e3c9b3, 0x0005099db15ba9f1, 0x000d40a06fbf250e, 0x00000ac8ed941db0 }}, {{ 0x0006facb0812925d, 0x00042eaf8c511875, 0x000c1d23829fdb64, 0x0007ee64505bb67e, 0x0000b90376a129f5 }, { 0x000841357c4ddd34, 0x000d3e98f6229e49, 0x0003ba2e8493a602, 0x00056697962d103f, 0x00003d04cfbd7b62 }}, {{ 0x000750cc3c1a7b0a, 0x000b159c34e67058, 0x000af889dc10e012, 0x000957b37c3c7180, 0x0000968c82b0c089 }, { 0x000d86dbd34a175e, 0x000689db7275d7d1, 0x000b10d2d7166c05, 0x000b45693ffa0168, 0x0000abf693ace924 }}, {{ 0x00071b360f0679b7, 0x0005467e28ef5ba5, 0x000973fdab5aa7a4, 0x000f206202c9a469, 0x0000e0be2b8f2417 }, { 0x0004bed023283151, 0x0009958101c1d454, 0x000dd3c9342fa56e, 0x0005c83466651788, 0x0000f38d09a711f7 }}, {{ 0x000343b5fb200f96, 0x000952d33da525d4, 0x000dcfd099dce93b, 0x000b1701df193678, 0x0000ef95773ba9d4 }, { 0x000484d4e14aaebc, 0x0006771638127137, 0x000d82dc48b25dc1, 0x0007325d747bf6d2, 0x00005e1c9c82ab72 }}, {{ 0x000c8d3645c866b0, 0x000beea60dbac1fd, 0x0003fd796cb1baa7, 0x00063a35b23d8c48, 0x0000e075408e6a88 }, { 0x0007c5425467d1b6, 0x00043fab12177b4c, 0x00038b881b47a89d, 0x000d9800bf79bf46, 0x0000a2c54416f53e }}, {{ 0x000a0d41b10e0cdc, 0x000c447e5911a766, 0x0007fa71dd36a5ba, 0x00049cf4261ffa5c, 0x000079b9ae6dbe81 }, { 0x000e89e390495427, 0x00042f5cc30d3577, 0x0000ece8db061fa0, 0x000e6ad61be9adf8, 0x0000aae7a36a6e46 }}, {{ 0x000c6cb4fe4e3e7e, 0x000afe5facf69d43, 0x00060b087f4ea2b9, 0x000a4ef04363b7e7, 0x0000a37a66bc1464 }, { 0x00008b945060128f, 0x00034394008e1f2c, 0x000964139e1c25c7, 0x00079cf065e9a85e, 0x0000f97bbcc0ba07 }}, {{ 0x0003879cbfbabf2e, 0x000922c89f71f0f1, 0x0001ebb607012381, 0x000532fedad8f3e3, 0x000042e5dc9aab87 }, { 0x0007a589356da4cc, 0x00048a56b306a0b0, 0x00065fbee32901a2, 0x000cd9768359c2ea, 0x00005460cecc0d99 }}, {{ 0x000dc35c554b2226, 0x0003bd168754ab0e, 0x000c817f3e20d9b4, 0x0006ac169801fce1, 0x0000801dc7720a5a }, { 0x00096d0960303067, 0x000c06fa3f660d1d, 0x000ddf8f6807ba00, 0x0005d49aea0184eb, 0x00007165e44fb9ed }}, {{ 0x0003109d80d2b121, 0x000e1b5f8c2a25b9, 0x0008728167361b42, 0x00003c24c1bb772b, 0x0000da906c6e6147 }, { 0x000cc31b47879cf5, 0x000d7f78ef59fb59, 0x0001eb43ee1bcd5a, 0x00056c59b3b438fe, 0x0000d98902a011aa }}, {{ 0x00097ba641eb7f97, 0x00074a9b733aa5fc, 0x000b26df4bf350af, 0x0002ceba5dece47c, 0x0000cc1ae7e7d3b7 }, { 0x0007fab43b1d99a8, 0x000ad0409c110608, 0x0004beb49cf2a615, 0x00058d94656ea2c0, 0x0000cf90618174d6 }}, }, { /* digit=18 (1,2,..,64)*(2^{126})*G */ {{ 0x000b433b59bb0813, 0x0000341d4c5105f3, 0x000e323c820b4e81, 0x000deaab01ae80f8, 0x0000ba1d2bfa0603 }, { 0x00002fefd81e661f, 0x0004eb693e856387, 0x000273b996572680, 0x000f613ecf7b5925, 0x00002889ae807f47 }}, {{ 0x000e89f3d33e658c, 0x000bb5d0fefb0c3a, 0x000a984dcf89f8ee, 0x000d20ca4d48fb56, 0x0000b9304c4e5ff7 }, { 0x0003083bb07dcf66, 0x00023c86363d14cb, 0x0000b4a396cd193c, 0x000063a218981752, 0x00009e66befec3c7 }}, {{ 0x000047f6491b324e, 0x000f3debe949a447, 0x0007e422595c1d64, 0x000d22ddc638e938, 0x000012ead0995384 }, { 0x0007d3336dfbf8ab, 0x000df9041fbab170, 0x00084f98a83458eb, 0x0003252dcda8e0b2, 0x00002ddc2d664ecb }}, {{ 0x0001d587d483a8ac, 0x0001644bfe209256, 0x00032e076092df00, 0x0008fc46391c19ac, 0x0000ca7c69ca0159 }, { 0x000a11fe134033ed, 0x00086a2a37173eaf, 0x000759658d52a842, 0x00086c73e2384800, 0x0000d0571a330ac5 }}, {{ 0x000b0b43fae02d19, 0x0005e2e81685d7b3, 0x00018429657b244e, 0x000322fef23f27d8, 0x0000be6797dde7b1 }, { 0x0000b732a6bc6506, 0x000f52663ca72840, 0x00041c968590b9ae, 0x000d64c6b7f5729b, 0x000078435f1bf19b }}, {{ 0x000b01ea6b5b07b3, 0x00041262048e3968, 0x0005ad3bb37932fb, 0x00016d2ad436b50b, 0x000041c792fd15ec }, { 0x00054b52698a8d32, 0x0007dee97015c07d, 0x000878f05045493a, 0x000466fd246cdf1a, 0x00005d2f84c497f9 }}, {{ 0x000f1bc8463a493f, 0x00090304e23e9bca, 0x000563526dde04db, 0x000c22e614387f81, 0x0000c1b1d1e0bd00 }, { 0x00058493c7b7d8e9, 0x00018ba527de79c6, 0x0003dcdd27ee6deb, 0x000a262c70e1346d, 0x0000f69deb198370 }}, {{ 0x000617ff6bb8909f, 0x000aafeb8a24a205, 0x00019f14a5d36b68, 0x0006aa95317ebfed, 0x0000c8fde1bb5304 }, { 0x000967ce0fa78f8e, 0x000a6c5e3c99ebdb, 0x000d5e1c475a7c8b, 0x000cdd9dffc64242, 0x000020302e081fc1 }}, {{ 0x000d6c2966703b01, 0x000365121c80b5d3, 0x000c65b2a339f5a0, 0x000fd9f7e2e7a563, 0x0000bb183ed3e7e1 }, { 0x000a43951972d8ef, 0x0008e1aaf70b8855, 0x0008d324cf4076c4, 0x000efcb5bafc3bad, 0x0000bcb50e192c99 }}, {{ 0x00087e191f93cace, 0x00049a85fe4e3142, 0x0000d43a775064ea, 0x0003b4d23e60234d, 0x0000bc6b31f78d5e }, { 0x0002da4b5432efe0, 0x0009ddc09d877d88, 0x000b918d3decee95, 0x000f07ea41c23478, 0x0000526c06550283 }}, {{ 0x0003639eb906c44f, 0x0001891fadb86087, 0x000d08112f3df08e, 0x000f4bb34049e832, 0x0000c537963213bb }, { 0x00072064455862d7, 0x0005c1fe1e4a71b6, 0x0003195294d3f757, 0x00004b9326ffd6b9, 0x0000135f9599d70d }}, {{ 0x000418871e270c0b, 0x00029a3b23358342, 0x000a6cd6e14299eb, 0x000d6b00d9526205, 0x000018ce7f6af8dd }, { 0x000fdb3c22d19812, 0x00064814082c1576, 0x000fb9e6c451057f, 0x000efd528cc914ac, 0x000020534397c913 }}, {{ 0x0009874445537fd6, 0x0003ea6f2f9f8e93, 0x00031665058cdd50, 0x00085d2d9963ece2, 0x0000dfa018b78042 }, { 0x0000899785dc3ccd, 0x000326512bf476a1, 0x0007f945e60b257a, 0x0008189ca598a64d, 0x00009ba39facc3b7 }}, {{ 0x000b8bc785ae777b, 0x00017fd02eee3ad4, 0x0004e4888aeb0a29, 0x0009b3b75a86b3d3, 0x00009495294c40d6 }, { 0x000cd576bcde4c88, 0x0009754413f9cdef, 0x000e2ed5dfa79ee3, 0x000736423a5e4fb4, 0x0000c8fea236703e }}, {{ 0x00088fe5f08c69ad, 0x000d03e83731a34b, 0x000e34f3889d77d8, 0x000a91d7c2bb9028, 0x00002a8744970829 }, { 0x00069e9172abed8b, 0x000e0c6edea4eb34, 0x000301f05b05123c, 0x000837be143b9313, 0x0000a5596eeef405 }}, {{ 0x000e205c1544399e, 0x000710441c23fa36, 0x000053783e19700e, 0x00068fea7b4712eb, 0x0000a112e4fbfa4f }, { 0x000514d89ca1abfd, 0x0007c57b36416860, 0x000d4097b2b1ef2f, 0x000a206500432691, 0x0000b3a43e7e1054 }}, {{ 0x00090d4325fd9679, 0x0009b7fa8e67fc38, 0x000b22134298196a, 0x00091d5579e2e0b8, 0x00008a49ee4dfeae }, { 0x000a54ce4da649a5, 0x000b96ec55e68a39, 0x000aa8e4fa0ce432, 0x000d91155bf12e90, 0x00004d3d79423852 }}, {{ 0x0008a43035135501, 0x000e73af1a142952, 0x000c89e1a4c4c49f, 0x000aad9ba916f955, 0x000087d02c81ab86 }, { 0x00053db5fc807a2d, 0x000d2a2b8a9cef88, 0x000e34ae4f1d89bc, 0x000eeb9725517407, 0x0000f797b5d79a69 }}, {{ 0x00061e9a4969a240, 0x0000ba9e864a51ae, 0x0008886b8141b7a5, 0x0006fca286c26769, 0x0000240005dbdd2a }, { 0x000449c2ec4a9e15, 0x0003b039f84216d6, 0x000748fa0a993339, 0x00074b159ab020d0, 0x0000997a8c005c8f }}, {{ 0x0008a5b251a46688, 0x000c41c2cf9d7c1c, 0x000a25f0335a2815, 0x000478f0c1320886, 0x0000b3973c66051a }, { 0x0004dada9450a7b7, 0x0005d32c11d23031, 0x00020a289c0afe30, 0x000abe1287da6691, 0x0000967694826933 }}, {{ 0x000c3bd859c92095, 0x0002e217ef6b0d15, 0x000a205766c8c264, 0x00023768252a9477, 0x0000b7cbdb2f3134 }, { 0x0000ac583b4bc642, 0x0003ef5f22c2d3e6, 0x0000570f148a45c5, 0x000cf5f1c368d504, 0x0000aba17b2c65da }}, {{ 0x0009f147f44133d1, 0x000ea980eab2437e, 0x000474350cd3f048, 0x000a45f7f8cc08c5, 0x000087556fee2ca5 }, { 0x00043f23a09ea234, 0x0004914d2fd6cf16, 0x0003c910a80fc0fa, 0x000d10df7a3ecd06, 0x0000fce7e70f4fef }}, {{ 0x00085c4a77db6510, 0x00068abe65ab743f, 0x00003d917e24f825, 0x000a8e568bf7c75b, 0x0000f920e13ab677 }, { 0x000d8f276467f157, 0x000feb2e68acf374, 0x000d5da38820e4a7, 0x0006b9d93a544df3, 0x00004f65f0f3913a }}, {{ 0x000ce5870a0c41fd, 0x000faaaf0dcbc49e, 0x000883d62d516f72, 0x000eaa5e57de551f, 0x0000f8ef2d69da92 }, { 0x000ff5e2f5425d4e, 0x000c0dd167d79ae1, 0x0002da879bcbf034, 0x000d36191039df8a, 0x00004f16c971cb78 }}, {{ 0x000fc8cc32aee2fd, 0x000a3396ea51d668, 0x0004f0b4adf36311, 0x000779e24506c144, 0x0000d07ff487d2c6 }, { 0x0003173d2554ae54, 0x000d94d9433d67d1, 0x000f576695712eb5, 0x000cd8a077fa5cb8, 0x00002098fca8b646 }}, {{ 0x000723c7f687405a, 0x000ff9dd5b340fff, 0x0006b9daaecf62ef, 0x0004f00dcfc6b529, 0x000082ac85fad224 }, { 0x0007febee863592d, 0x00096219773d4025, 0x0002c3531e5edeaa, 0x000d2b53cdf7c6aa, 0x00006f48a45191f1 }}, {{ 0x0005d48ee54627c0, 0x000fee47bd8e7397, 0x0004388f30907fc4, 0x000d3c92379d4499, 0x000014e6df0129f2 }, { 0x000bb8f6ef5589da, 0x0009daadb5cdf33b, 0x000580b07079ffc5, 0x000738d4e3396e89, 0x0000d3c9aebf037e }}, {{ 0x000aee99a83de201, 0x0000551cbae2f701, 0x000578bc0f4313d7, 0x0003bf399efc4bc0, 0x00004db1c0ede19f }, { 0x000c5f317b20b8d4, 0x000b1b9ae8274c57, 0x000500d18221751b, 0x000091b816c14d44, 0x0000685f584b909c }}, {{ 0x00037932990a975f, 0x000b1754ef442271, 0x000ec8a7c1fcf689, 0x00000f4cda17bed6, 0x00008003fe108b77 }, { 0x000ac3793bd9befd, 0x0003378dbbe307b4, 0x000e2c2b1ffa6260, 0x0007dad206dd1c20, 0x000049b2e9cf1b68 }}, {{ 0x00013eddb15b9981, 0x000b7ebed1f8ca0c, 0x00078d7c47f137aa, 0x000d0086f3e54665, 0x0000ee5e70525d64 }, { 0x000020737111ef2e, 0x000f24fd49eb8f61, 0x000cc72ea2ff6814, 0x0000cd758d0d5bdf, 0x00004f38669d1545 }}, {{ 0x000ed13c9ad8f9ee, 0x000f8900647a82b8, 0x0004006ec8b4868d, 0x0008b4a03908e0ed, 0x0000ecf41ee539a0 }, { 0x0004380e0ee30563, 0x00093761f460f648, 0x000ab29855275b29, 0x000bf349b53930b9, 0x0000a5933dc89dac }}, {{ 0x0003bc3770684e62, 0x000ca6bc4fe3c395, 0x000318bfb46f7b63, 0x0001ad259ba4a815, 0x00008206cce146bd }, { 0x000c2731bc0908f4, 0x000d4ab5afc60db8, 0x00049492c0e73d3c, 0x00006d107aa02235, 0x0000a2cf845790c5 }}, {{ 0x000e83daed4291aa, 0x0005eab18a0339d4, 0x000ce8b1687fb104, 0x00007814fac7a658, 0x0000c1a639fa1a8b }, { 0x000721d740a55e87, 0x00040be2f39ea3e5, 0x000f598395ede4d6, 0x0007ef938ef0c005, 0x0000b5b0afcf29c9 }}, {{ 0x000530a00b6f6334, 0x000e111fbeeee1be, 0x000309ec6bf9af40, 0x0005d4935d1ef5e7, 0x00009dcd3183c604 }, { 0x000632a3a250e986, 0x00031fef15ebfb03, 0x000c9cefa5780c6c, 0x00071ac37549de03, 0x000059126cd86023 }}, {{ 0x000f033918a2c159, 0x00061890ef59f78e, 0x0002dae1f2816a7a, 0x000a1bb470dfc644, 0x0000c8d185b680cf }, { 0x0003bfaab3be88e6, 0x0008d5db13839481, 0x0002ad1dd2c94e09, 0x000b5ea68c1fc29a, 0x0000900f4ef1e381 }}, {{ 0x0007640487bdae6e, 0x00058a90deeaf523, 0x00021500178d835f, 0x0001696c4b003fb0, 0x0000fe99cf01049e }, { 0x0002f3acc9ce3d00, 0x0001bc6222a77da2, 0x00073b543e47375c, 0x000de432c62260a5, 0x0000b372f8b94a23 }}, {{ 0x000e8055d0741a6d, 0x000dc228e41d155c, 0x00076c40041ede78, 0x0006dd7114d02456, 0x00005f55ba2e84d9 }, { 0x00009bcf6bd46086, 0x0004baff62045490, 0x000ec66a97edf917, 0x000123c29a0a00a3, 0x00001c1ad528832e }}, {{ 0x00017eca6dedef2e, 0x0000aa822305177a, 0x000e9fe591513c37, 0x000b875c0d51d59d, 0x00005bf481a68fd2 }, { 0x00042c3114902bd5, 0x000b2ed60d9dcec0, 0x00011c80f3407b8c, 0x000452dbad6d28e5, 0x00001d77ed06f416 }}, {{ 0x0004dacf96735388, 0x00012c58aa68e305, 0x000bbfa881a889b6, 0x000da070c7a6a3d7, 0x0000eb1e4523df46 }, { 0x000d0b1e0fc6e9e4, 0x000856fa4a9af892, 0x000fd9a17add2f5b, 0x000bc96203a41193, 0x000035db9779e65b }}, {{ 0x000a132f7ea9a6a6, 0x000eb9240be34e8c, 0x0006c77d4fb67e21, 0x000afca2bc7162b3, 0x00001a6fac0542ff }, { 0x000f9b75c44f951a, 0x0002af90e2025b4c, 0x00083cc77b87ef39, 0x0004eb21167aaec6, 0x0000d22d6db853d3 }}, {{ 0x000c7cce51163e7a, 0x000b1164d348272c, 0x0009ccdd071becbb, 0x00037af16bd99d61, 0x0000d10610c58a02 }, { 0x0007eb5875e27497, 0x00054aad846bd832, 0x000c8134cfd36ae5, 0x000aab5a98775a9d, 0x000086c275896b8b }}, {{ 0x0005528b5f9ab927, 0x0002651662cc565f, 0x000a1861882d656f, 0x000797e9482353a6, 0x0000a67f2e464b0f }, { 0x000d6414aca8eb30, 0x000d2312f23c5ff3, 0x000a2d9b8ef54a36, 0x00042ada0e3e8147, 0x00008166c958af77 }}, {{ 0x000188223a7a093e, 0x00044e1a51a168a0, 0x00014726320dde66, 0x0001a00b8b712c67, 0x0000e412af6796fc }, { 0x000487211ce123d4, 0x0008a21f7c18de1f, 0x0000bdf491697418, 0x0002e15297682e45, 0x00006b2b6ce9962d }}, {{ 0x0009c135ff5a9bcb, 0x00077770c24efc82, 0x0004953601a4b26d, 0x000b112280349fd0, 0x0000209df732d2f6 }, { 0x0007f7525d0fd68b, 0x000ba08f78b0b6f2, 0x00023f94c1dfda97, 0x0000b9365176f5dd, 0x000020eff3bcbb3c }}, {{ 0x000a7c2c5789636a, 0x000a409748ab1a42, 0x0000348217db9653, 0x00093f0f29cba50a, 0x0000ffd72e054e8c }, { 0x000e9d1cf178ebdd, 0x00089a43f0a449a3, 0x000b6ef3df4bc9f9, 0x00075f35745474c3, 0x000083ae967e4c12 }}, {{ 0x000fa729a87fe481, 0x0006353f380a6e68, 0x00010b6d0e19961f, 0x00044e00a0b86e43, 0x00009f6a7ecb4a6f }, { 0x0002ed3e3509796d, 0x000026e6c9c217e3, 0x00095ea456ef349f, 0x000c3e2b1be1d307, 0x0000a66932593b0b }}, {{ 0x00008a89af9a9081, 0x000817f9eb1a8b70, 0x0007c527a6393cf4, 0x000462091bc37eb7, 0x0000c5e0712c411f }, { 0x0003154f5208b269, 0x000bffb7d42c10ab, 0x000e969ea76610fd, 0x000ee44e37fe8c92, 0x0000cdae2d966e9c }}, {{ 0x000c5def04862376, 0x00079b6d9790ed61, 0x000c8a4c8a36ca43, 0x0001a8e2ea77a0cb, 0x00004f8456e6379c }, { 0x0007052acbcdeaab, 0x000557873b6c1da8, 0x000275d32aae4098, 0x0007648b155cf85d, 0x00002e5661fcaa36 }}, {{ 0x000e8d5c0dec3769, 0x000c280907eae66d, 0x000f6ee4c07b1ce9, 0x0000e431c3cb068d, 0x0000c8b6234ea0f1 }, { 0x000a212bebfadf0c, 0x00013dce3502e6ed, 0x000073687498df63, 0x000e33ffbc894420, 0x0000da93c59a72f5 }}, {{ 0x000d7b05dd7857f5, 0x000ad4bf82ce682c, 0x00053a7c1a0771d5, 0x000a2e3de058d381, 0x000087e07d1384e7 }, { 0x0002699a5f9d773f, 0x000b9ed1d9f54ec8, 0x0008306a1b6b36cb, 0x000f3ede28be3d61, 0x00001ffd2fb37142 }}, {{ 0x000e5782cd47a8b9, 0x0004df571c0c3a75, 0x0009aedc953ef848, 0x0002f1a758f580f5, 0x000042380c4840db }, { 0x000acf2240badb82, 0x000d60c99c82a70a, 0x000e6b1b6a0b6799, 0x00065dc70e8359fb, 0x00005463c0ed77c0 }}, {{ 0x00044e55ad6bba22, 0x000aaf5e4652f1d2, 0x000ab113020533f0, 0x000a7ca50bd6fdd2, 0x0000ffec60c771f6 }, { 0x000d2dbc0fe69c05, 0x0008e05047d320ba, 0x0004b4536a2fa180, 0x000f3b3ee1ca983d, 0x0000736ebce33440 }}, {{ 0x000b59f3e30d097b, 0x000bfa29268b3de0, 0x000adb866cb76535, 0x000eac7520d1ca29, 0x0000d07af7edc75f }, { 0x0007f84282de8bcf, 0x00016ff7f4a6c51d, 0x000189e3ecfc03a9, 0x00009091fa8768fd, 0x000063e18fffaf2c }}, {{ 0x0005978d0a53ff5e, 0x000de0e0546063ea, 0x0001b7ca1ebc5a0b, 0x0009b66007fbadcb, 0x000016843f73bee2 }, { 0x0007fb68ea74f94b, 0x000d61e4f85eaaca, 0x000152cf5d96b415, 0x0008a39cde61e2ad, 0x0000f97b10343ac3 }}, {{ 0x00048364d3e5d0bd, 0x000fc363daed4c29, 0x000f918392b59488, 0x000d61c0a80a9aa3, 0x000059055976d210 }, { 0x0005f25bd356dc7f, 0x0003d6070985182c, 0x000d6d3eacc1af52, 0x0004d43f5a6db5b0, 0x000050f58b44a28c }}, {{ 0x000c527f92db6aac, 0x00019242d0a4c230, 0x00045f614cbf9dab, 0x000338092eb5d26e, 0x00008b05b2bd83e5 }, { 0x000c81836dfe11e3, 0x00036382aede0ac3, 0x00083041c5cba047, 0x000916061b292220, 0x000053fe2de8f49b }}, {{ 0x000a0369abbd0203, 0x000b27fa001ec5a8, 0x000b16d8f40e8efc, 0x000481080e993f5b, 0x0000af7a86da5db5 }, { 0x000551c295b0441c, 0x00071608c927db84, 0x000f4f1394ac39c2, 0x00072abeabf5f37c, 0x000060b2c65c0c54 }}, {{ 0x000b04f7d8f72e56, 0x0001be7ed77ee8ba, 0x00004804ddee725d, 0x000b92acabddf7bd, 0x0000ccae2b20533d }, { 0x000c088c89918989, 0x000e9944313a8cee, 0x000ba6c1c0748b0a, 0x0001e207ae532e4a, 0x0000e42ef48bf73f }}, {{ 0x00046b3d3b414b91, 0x0008dcc42ce9e515, 0x000d5df49fef1fdf, 0x0009c67398f9840f, 0x0000bb29bacc84c0 }, { 0x0008c7d4845045fe, 0x0001ba980d309162, 0x00072f844c3fd6d1, 0x0008188084549710, 0x0000d0d70dbdf40b }}, {{ 0x000ed2436122cc51, 0x000c66788a2ffe41, 0x00050a0f2644da13, 0x0002d783adc506a3, 0x000069129b160058 }, { 0x000218e8eafe18f8, 0x000b292a3d694e78, 0x000d6d37d38998d1, 0x000f855b4c0f43b4, 0x0000bf4a6ab4a165 }}, {{ 0x0000f3271f894fd3, 0x0008afb185f88448, 0x000a946484dc2331, 0x0007019dfcd7e90c, 0x0000692c2e123626 }, { 0x000981d9ea441cc2, 0x000d8a7d0e62f477, 0x0000cc886efb3ba6, 0x000724e1e88d519d, 0x00000023f082da8e }}, {{ 0x000afff39d12e58b, 0x000da2c9ac382032, 0x000f2c658c484952, 0x00039c91686eaf87, 0x0000523e755bd5cf }, { 0x0005df02e43ae54f, 0x0006c07256d4eab9, 0x0001eca6a8a4fff6, 0x000375ffe2259869, 0x00006edafe5d45c9 }}, {{ 0x000d1c4cc4d8b709, 0x0002c6ec7004bf30, 0x0004ce677b1974ac, 0x000529eb7230a08f, 0x0000f295c26eabae }, { 0x000fed0da0e7efbd, 0x000096e7550fee88, 0x00070d0a16dda21c, 0x000c5fae7369cd4c, 0x00001bcd58dde3aa }}, {{ 0x00044ed736b966ec, 0x000a5c2e48fb8898, 0x0002f73bc5cfb109, 0x0001bb4e226882c1, 0x000063d7619b2c62 }, { 0x0006a413e95e2beb, 0x0005c6fd86e27c75, 0x0009ae0bdbf2ca03, 0x000edf84da04edac, 0x00007492ad45d302 }}, }, { /* digit=19 (1,2,..,64)*(2^{133})*G */ {{ 0x00024f4d696da3cb, 0x0003b1d5a74be506, 0x00047c52228c154a, 0x0001bfda2e41781c, 0x000096ec0545b52c }, { 0x00001059ae4af1e1, 0x000735dbdcc9ae4f, 0x0005508ac4dfef91, 0x000d754392573dbb, 0x000045a30ae8165b }}, {{ 0x000c13673627c363, 0x0003c973112795f7, 0x00071c3b07ab4999, 0x000f308cde824443, 0x000024017b4422c4 }, { 0x0007e6782a430857, 0x000be955dbec38e2, 0x000c10a45929115d, 0x000d83e2f51c0782, 0x0000d2b6c6a41083 }}, {{ 0x000f9b21b06e4d48, 0x000483d4ed2dbc25, 0x00081ca00bd2f9e2, 0x000314b350eba59c, 0x0000879d4fee9d2e }, { 0x000846aa4551a9b0, 0x0002394af267bae5, 0x000565e76b699192, 0x000e51500aa86cc2, 0x00009d486efc3818 }}, {{ 0x00023eed8fe44b7b, 0x0001c40e2c2bf152, 0x000587aaa9751a65, 0x000b04a65627a220, 0x000078ae9a0140de }, { 0x0008dfbb97c7d47d, 0x000a883a8363b49a, 0x000920e2f50e570e, 0x000074b5c1a0b6cb, 0x00004368ec853ac9 }}, {{ 0x0003cdd7ea38297d, 0x000d04c65c7c2aba, 0x00073ef8129a7789, 0x00012cdb51d4610e, 0x0000ae1d9b12315f }, { 0x000a8296356d58cb, 0x0007e83064417ee3, 0x000c72e948f5f2f8, 0x0009e5bc31459b23, 0x00007f5688f80bef }}, {{ 0x000e7c88b34096a2, 0x000ee1fab192c181, 0x000e51b38d9be8b8, 0x0008dc9a6ec5fcbf, 0x0000c004fd1604a1 }, { 0x000d9b52b3513161, 0x0007c93c92d88c5e, 0x000d236ba8a62196, 0x000c4ae1441c2148, 0x0000e3b813e3424f }}, {{ 0x0002d6dbe520bd47, 0x00002ebb0a5b358f, 0x0001aba752f14bc6, 0x000e71bdbb154c5c, 0x00004df8bc57eacc }, { 0x0007ad0af3ff3ee3, 0x0000af38665e5b22, 0x000353d24c2f432c, 0x0008cd086488a851, 0x00006ced5e1bbf8c }}, {{ 0x000c2a360971c31d, 0x000066e846e364f6, 0x000c727ad6974fa9, 0x000639b6d7f33527, 0x000015ca19ee6b97 }, { 0x000b4ef351021aa4, 0x000ba52f024e9245, 0x00044265bc79a45a, 0x000687390e0fa07a, 0x000026bc8f7f2c64 }}, {{ 0x000eb356d99847ee, 0x000c1c4b6205969f, 0x0001f8142e759402, 0x000504d4842563f0, 0x00002d9aff65fb85 }, { 0x000340185f8291c1, 0x0006b81d1a39bd77, 0x000f7353328a0998, 0x000e743da8f44340, 0x00008523dea1bcc1 }}, {{ 0x000c87111ada74f5, 0x0000bfb7409ab463, 0x0006445b7897551a, 0x00013f0d1057e78e, 0x0000fca1d2e611ce }, { 0x000f201ffa6c5d1a, 0x000f41c7809460b4, 0x000222a98bccef3d, 0x0006f03c9e751c85, 0x000002a8d1482e5b }}, {{ 0x000984b27405ee90, 0x000005c3e6721cea, 0x000a272eb4d7fd0e, 0x000927da4d52d70d, 0x00000cba2cc35612 }, { 0x0009d70b01b1eae7, 0x0003e2784de5ca41, 0x0002ae7bd3c2b1ce, 0x000f8f7092f1c987, 0x000030b0c4119210 }}, {{ 0x0005583b9f7c63fb, 0x000702da6dc1d29b, 0x00094319a5a4c61c, 0x000909776d303000, 0x0000ea690a72942e }, { 0x0000d34175165b72, 0x0004c7895695f204, 0x000148fcd1400755, 0x0009aa443fc84181, 0x00009d399222fcef }}, {{ 0x000758ee5709e62d, 0x00069f5674198335, 0x00022ee28cb1cdab, 0x00070430c6059e25, 0x00001b376756c012 }, { 0x0008f5c1bf938d37, 0x000401d013b0ea65, 0x000afbd027f9ea15, 0x000a32680fddf524, 0x0000feb88c703890 }}, {{ 0x000d105f424816f7, 0x00040f17c696042c, 0x000b7d14d99c5d98, 0x0008d2f00d4cba22, 0x0000ca9c23515356 }, { 0x00065cd5704583a6, 0x0002919ddb81e743, 0x00091afae35a6c5e, 0x0001a1285472f2d8, 0x0000a117968098a9 }}, {{ 0x00061f2dfaaea695, 0x0006dbba2be70539, 0x0005e49a78db79a4, 0x000511030dcbbf7c, 0x0000c25cacbca172 }, { 0x0006bc1247ed44bf, 0x000d53570dc80c4f, 0x0002f9bc2ed8f5b8, 0x00011b222104d6b6, 0x0000be75e1d87966 }}, {{ 0x0001a05fe05069b5, 0x00097050f15dde91, 0x0007fbbecba1b4b7, 0x0007e7662a47a76a, 0x0000cef9eea25012 }, { 0x000d251439c9ff5b, 0x000996e9d529b36f, 0x0000927929bcb4b0, 0x000321b9855ab130, 0x0000e6913e2a37cf }}, {{ 0x00002e1795824e90, 0x000a54723d695ead, 0x000d46b77220484d, 0x00039408648ce626, 0x0000dd1d7bdd322f }, { 0x0000941af25d109b, 0x0004e8f7198111d6, 0x00057c65a8da2e48, 0x0002feeb090ca630, 0x0000f1530e7e8096 }}, {{ 0x000b5c989f6938ee, 0x000d2a222eb51e58, 0x00041f4057fb3762, 0x000dcb106c0bb724, 0x0000ad14845ce016 }, { 0x0007d1e1160ea6c5, 0x0002e16512e1f433, 0x000475371e4c0b2c, 0x0002b464e02eac55, 0x0000f6d7ff9c35f9 }}, {{ 0x000f15a10f16a85a, 0x000e41aab7b19a8c, 0x000e0fe32c369f9b, 0x000b5a9daf08d067, 0x000024ab40acda51 }, { 0x0009684eaabd75c3, 0x00009e5b738a4250, 0x00058cce645336d6, 0x000db1305ebe131d, 0x0000484813fc96ba }}, {{ 0x000d8bd56620b954, 0x000129c72ba075b6, 0x00054cbabaaf6b83, 0x000e637a889f78b5, 0x00003d0a3429781d }, { 0x0004afac04fc7b8c, 0x0005a3b805f08d67, 0x000d4f0d15b02979, 0x000aa4c477f48200, 0x0000acd64bf963b3 }}, {{ 0x00065ecce6ddbcf2, 0x0003a2b7e63d6900, 0x000ffbc500d16630, 0x000c7e1feefb6bbe, 0x00008b274a61c74a }, { 0x000c29f8ff0209d3, 0x000c1ce69f790713, 0x000ec8218d676a18, 0x000acca8f0d9a8e5, 0x0000f615e9cc3915 }}, {{ 0x000f37825c9ef1ce, 0x000848febae68c4c, 0x0001618e37c4f175, 0x000eb4cec5b38563, 0x0000d423c83cbc80 }, { 0x0009c52aea308776, 0x0008380beb11454b, 0x0000a6fc857c4768, 0x000022bc740a1a99, 0x0000ca5ec3d496c8 }}, {{ 0x000cd4fde296905a, 0x00062ce45650ef47, 0x00000dcd9ce46f6b, 0x000746a70ae000f1, 0x000007a206cd8fb8 }, { 0x0006cd56404f4acd, 0x000e52ae88408697, 0x0008e8efb046152c, 0x000cc12baa886885, 0x0000b6caba36edc1 }}, {{ 0x000a22c213a1381c, 0x0005998a9d82abfd, 0x000b0c9eaee2416b, 0x0002e94875f188cc, 0x0000ed487d7becaf }, { 0x000a1bfe43d8e989, 0x000d43afbddb4799, 0x0003d3555d553c34, 0x000ae422e4b606b8, 0x0000a98941400820 }}, {{ 0x000d93563973829e, 0x0008a092a67d48a1, 0x000de58c53a8a8ae, 0x000c1054acd6a671, 0x00000d14b278f09a }, { 0x000286662fa4b2d7, 0x0004d898fea73ea3, 0x00046daf4982b9ed, 0x000b2de4c8247b36, 0x00007827af7176ad }}, {{ 0x0004d969cb439a74, 0x000636bb4ec4c20e, 0x00062a667a3273e5, 0x0003e53e8f0a12fa, 0x0000735706c629fe }, { 0x000d4b3454ad59df, 0x00074b743e232a3f, 0x000b3aad70059ea6, 0x0007e3d8fdc7a3fa, 0x000053ec510c7073 }}, {{ 0x000267aa86866f79, 0x0001686d36e30622, 0x00077edc547bf065, 0x000077b2e626c527, 0x000032b789435829 }, { 0x00088821cbb8b0bc, 0x000a75172e572d59, 0x000721eb0f204226, 0x000dcca57ab861af, 0x00001dc0ca62fb88 }}, {{ 0x000ce1680d34fa1e, 0x0000722cccc18ad5, 0x000d94c5781a4479, 0x000c8174daadf3f8, 0x000096cf50e285e2 }, { 0x000921dfeb77456e, 0x0004dfcd9ecbee97, 0x000ba38c82c0be59, 0x000d5558a4330689, 0x0000d3b38073c94d }}, {{ 0x000da886aed8ecd4, 0x000eaf8271d1ca55, 0x00078b0236696085, 0x000b711e33e423bc, 0x000014d2f4ec906b }, { 0x00036e1f5d068ff6, 0x0007034a99643755, 0x0003162eb1a26190, 0x000151fe9356a2fa, 0x0000f7623180c7d5 }}, {{ 0x000f35afef5374dc, 0x000b53a5c04e4ea9, 0x000e37bb65248044, 0x000884194d549dcf, 0x000056a261a80626 }, { 0x0003eb6a05b04ad5, 0x000b824f1314f53b, 0x000816d16e1d2218, 0x000a9b8b062baf94, 0x0000b751a249239e }}, {{ 0x0008e248259fd6b1, 0x0005fae1208e16aa, 0x00054f53f5fe83ea, 0x000752f0b1a4d15b, 0x0000322765d11e76 }, { 0x000a06028f32c493, 0x000e0a290b170cfe, 0x000058eb8f6521c2, 0x000831797a1bef33, 0x0000d5b9b2a9415f }}, {{ 0x000495775835ddea, 0x00038f3dbfb894e2, 0x0006a991d3c0ab53, 0x0007ac0dfbe9b79f, 0x0000a996ed108d94 }, { 0x000a1485e6867237, 0x000b861bb9390993, 0x0009ecbcb0ad8aab, 0x00089ee3b1d6a974, 0x00004490d265e84d }}, {{ 0x0005d8bafdc81765, 0x00002b4147c15b45, 0x000b25ed58041f7f, 0x000f1de81e34f553, 0x00001e756a2afa4e }, { 0x0008b5d2446a18ad, 0x000cc95f1c0e74e9, 0x000e53045657f07f, 0x00033d5515a9b292, 0x00004e129faf6e81 }}, {{ 0x00054ce98632c8d9, 0x000e666683425204, 0x0009755b794b887e, 0x0003dd2cd08d6894, 0x000093ff6f3941b6 }, { 0x00011538eb926db1, 0x000ab9eb55b803b2, 0x000a10ce88821a3d, 0x000060e12b03468e, 0x000072cd7c995240 }}, {{ 0x00032cd90a50d0eb, 0x0005f2f731dea2d9, 0x0001e1c0a21fc8bd, 0x000d579fed5856cf, 0x00009b444a44e0c2 }, { 0x0009e7c0c1c75493, 0x00002d4c0c4ddc0f, 0x00073a980207bdba, 0x000b2d8cbc0f422f, 0x000047b3f99102be }}, {{ 0x000665427bc303fe, 0x0004fdb0f5f27cac, 0x000ae1a81783a295, 0x0005c1223e85461f, 0x000076fba4039ea3 }, { 0x00022639d9c5cdc0, 0x0005a697587fd52b, 0x0007db23b5f4ea89, 0x000744688935289f, 0x0000887566528724 }}, {{ 0x000bc9cdaec3de6b, 0x000f720361ecf90e, 0x000f398696b456af, 0x0007dc079001f23d, 0x000063bcc338ae46 }, { 0x0007015cc0864754, 0x00010a1934aa7289, 0x000e179a04332cea, 0x00055a7fd750eb00, 0x0000b649d7589b15 }}, {{ 0x000c21aa55e58d8c, 0x00038a5bf5151dff, 0x0000b44f6e9cced5, 0x000b2182c21adcc4, 0x000000bf7836051e }, { 0x000405a74bccb408, 0x000bb2f4e51ea80e, 0x000f4195b6421b97, 0x000db135e3dae45e, 0x0000c8a422289ff6 }}, {{ 0x0005afe3df554744, 0x000a5c69f1c56bdb, 0x00079441b2c565d3, 0x0002dc52b8c176b9, 0x00001263e0533213 }, { 0x00004e3fc1406d5b, 0x000a249145813e50, 0x0009e2650265686d, 0x000129a7f687fc4d, 0x00000832fee46c0c }}, {{ 0x0001f9addb3fd772, 0x00068b61430c9ab7, 0x0002b03f3bbc1b26, 0x000a8d0ae0bdd41d, 0x0000a6be72385501 }, { 0x00063accbd8fe7a9, 0x0001716c52dd907b, 0x000c73a737c1e0a9, 0x0002868a6d9bdf44, 0x000035c09edac28b }}, {{ 0x000add2b06f54586, 0x0005c351272a95b5, 0x00074b4a3fc1da82, 0x0009268f70c66771, 0x000044d6759202ed }, { 0x000d2a2bf9fa5f60, 0x000732d14ea5d65e, 0x0005a053a90c3bdb, 0x000554ac6f8e01f0, 0x00005fd71f56197b }}, {{ 0x000d3d1774087028, 0x00051b5e9d3a7c31, 0x0006647adbd73b2d, 0x0005492758e0ee5a, 0x00003bba70bd8115 }, { 0x0007246f125d77c6, 0x000ab127747ae836, 0x000fb258fc2e4b6e, 0x0001e4e0031f4315, 0x000079fb7523dc70 }}, {{ 0x00022cef7e044521, 0x000ab5aef0c31335, 0x000d2be979bd6bea, 0x000e49649247cc45, 0x00008daf607fcbc2 }, { 0x0004be69d5e2999c, 0x000580559ab93b3c, 0x0000da59a69c02d5, 0x0009972d0225fba1, 0x0000cc519897bf32 }}, {{ 0x00000ed311acec40, 0x00036680448087c4, 0x000f31345a9c7960, 0x0000d7f47ac30903, 0x000014a52f1f5454 }, { 0x0006f2e733d21f38, 0x00041fef8fd24247, 0x000a837ac257323f, 0x000ff2f3afdfd974, 0x00009ba0f6470d39 }}, {{ 0x00050c547e9953dd, 0x0000eb52a6017539, 0x000c306fd8ca8187, 0x000b82024b286514, 0x0000a0dcbe1ef184 }, { 0x000f64a7dd340b95, 0x0008469e5d32bfe8, 0x0001e5a8c4619dc8, 0x000d6ea3a30bc147, 0x0000e933dd6721ac }}, {{ 0x0007ccc59280d519, 0x0008037633dfb1fc, 0x0004cfb25fb4af10, 0x000498d46ea82c39, 0x0000e384e83287e5 }, { 0x000e6e0a4144dfdd, 0x0009c6281761e131, 0x000f73287e1b3d37, 0x0001fe070da57596, 0x0000b0e289bb07e4 }}, {{ 0x00066b4e44ff11ff, 0x000882c4152fcf57, 0x0000280c990f629c, 0x0003c0009441c87b, 0x0000b659204e90a4 }, { 0x000df4368ea4d935, 0x000701211f1c7924, 0x0002fdef25b0372d, 0x00033119eea02ae9, 0x0000eb3caf4bdf44 }}, {{ 0x0002ad31f429e92f, 0x0007dab4baef62e3, 0x000275ae5ff44e2e, 0x000fc47109f5a220, 0x0000f78da2e8f242 }, { 0x00089cf1ff54aea4, 0x0008ca425bcf4d6c, 0x000288b364e70dd4, 0x000847d56ea95059, 0x0000d5e592ce8a8c }}, {{ 0x000bb30b4c5c4041, 0x000f81304e60cc0f, 0x000c4a72c8291975, 0x000e6a462ce811e8, 0x0000eb639b79afd0 }, { 0x000e60a95e94bf15, 0x000e32c485281182, 0x00059ec7afb2ce90, 0x000767a287c6fe08, 0x000067e5869c6204 }}, {{ 0x000b6d146193e6d2, 0x000ab3d9b785dbf2, 0x000b7beca8857459, 0x0000f4039530889a, 0x00009e5aa29e84bf }, { 0x0004f877f4c051e2, 0x0004a0451a7bbf7f, 0x000f81f9d270263e, 0x0006a8ba030ad99e, 0x0000b432329b85d8 }}, {{ 0x000cd2b7ced02b6a, 0x0008c2d4c44f1190, 0x0006dce4bc47e034, 0x000836c3b4555f53, 0x0000788b19828abc }, { 0x0004d4598c6d92d3, 0x000557b46945fa35, 0x000081a82e04d1a0, 0x000a4ea08f8785b2, 0x000063de08f3d528 }}, {{ 0x000d3e738b6fd0d3, 0x00087cbc46d7ce17, 0x00070dc9e4ec18cd, 0x000a97d509a515bb, 0x0000c0ed53ffb19b }, { 0x0009fd2c8134d2bd, 0x00005ce2a6cb0ebd, 0x0004b57daff8514a, 0x0002ea6766f2e295, 0x000010bc9a64cffe }}, {{ 0x000465c200623f5c, 0x000db38b2b836a16, 0x000017a7a4228368, 0x000823ef1855b41a, 0x0000cb16497d171a }, { 0x00094b4447686be0, 0x000e23f6974b99e0, 0x000b99263876de79, 0x000c0065875a7cf8, 0x0000dfac4f57f79d }}, {{ 0x000a8e6f779b6900, 0x00085edb940cb5af, 0x00018239bf98af89, 0x0009c26fa6706d79, 0x0000b769a307f467 }, { 0x0007c08b475deaab, 0x000f234591ee4f0d, 0x00066866b61f19ff, 0x0007c69575f46e33, 0x000028a209b8748c }}, {{ 0x000b82c392e80537, 0x000f93c1c08ad635, 0x000ff1019ae85ec6, 0x000ee34f79954343, 0x000039a812312260 }, { 0x000b0e72020ed2dd, 0x00035c4928435d5c, 0x0000ae24917dfa24, 0x00007284a071cf0f, 0x00005e0b1098229a }}, {{ 0x000e70062ee0a4a2, 0x000917ac0b7eff35, 0x000e6774850d2a32, 0x0004c985f8552225, 0x0000ed692c26dd93 }, { 0x000068c99ecd36b0, 0x000a048e7073969a, 0x000922d3ea339e56, 0x00093f20f392d2a2, 0x0000a61b1d58dd81 }}, {{ 0x000a4141443fe874, 0x000f11fb87a29137, 0x0004c28111acbcec, 0x000845fe4ea3e3c1, 0x00002b3d24c59afb }, { 0x00010dc2aa355a06, 0x0008f1aa71ff4939, 0x00022ac5ba4c733b, 0x00075e8fffe980c9, 0x000092ea09a1baa9 }}, {{ 0x000bd61a53336f7c, 0x000c326cca9f54d3, 0x000b572ddc8897d0, 0x0007f6a7c928bbdf, 0x00001633d0f6cb76 }, { 0x000e19742c3c3494, 0x000a4e6395c9a791, 0x000d43d1c100cd6d, 0x00052c2316940ca2, 0x0000fd9b397c3285 }}, {{ 0x000baa11cf6966bf, 0x0001a0823fc2e6e0, 0x0008fceb7f79dccd, 0x00086bea5a76e29a, 0x000020bec34acd1b }, { 0x000a26322d5b0637, 0x000b564961849da5, 0x000f551759fb7518, 0x0009cb74493b75f1, 0x000085589c5471c1 }}, {{ 0x000097196463dab3, 0x000235861a023efa, 0x0004194e0b09b4ae, 0x0007b8bc01d72aab, 0x0000a76ce5fce481 }, { 0x00008748d29fbf98, 0x0003d4badb9b5b76, 0x000163d30978b6be, 0x000794e0873fac1a, 0x00001acf21ce255e }}, {{ 0x0009ab9f40344f97, 0x0008094c486094f9, 0x0002f24809967c07, 0x000bb7725869254a, 0x000017af2e8590fc }, { 0x0003a576905d94dc, 0x000ea8a6706c02e5, 0x000c15d397dbab92, 0x000dc5b6c22b5e76, 0x0000e77621b7d00e }}, {{ 0x000d38e9c47b4340, 0x000b852edffcf3a5, 0x0003ded185911220, 0x0000e5b9eb4d2ed0, 0x00005ef944ff1997 }, { 0x000cbf19807bc19d, 0x0008bbf303747e2b, 0x000c38f6a80d0b53, 0x000aa5c23a208e77, 0x00001f5c1520084e }}, {{ 0x0009789f1f62f6fe, 0x000f230273231941, 0x000b1a24067e38a4, 0x0006f97203b055a8, 0x000043fde981f2ac }, { 0x000ee11ececcedef, 0x000a568aaf018013, 0x00004c88b6cdcf5b, 0x00006d17972ee119, 0x00001719e065c6e0 }}, {{ 0x0006e4617f3e69bc, 0x000caec1ed66f181, 0x000bbf3b6cc4ad74, 0x000551b4d225d906, 0x00003684306257aa }, { 0x000516497c9675a0, 0x0000addb2fbc3dd3, 0x000f55d795decef3, 0x000598fadedb5484, 0x000015e8ee776bd7 }}, }, { /* digit=20 (1,2,..,64)*(2^{140})*G */ {{ 0x00020f2beb76812c, 0x00013ecfa181e695, 0x0000dec76ead7889, 0x000698d5d9ea02f8, 0x00000cd75bcfa2f0 }, { 0x00017a069c2d2cc5, 0x0008f0a1df843618, 0x0000f08066c134ef, 0x000c931ff1203772, 0x00008f19ef39b4e2 }}, {{ 0x0000aecc1c7112bc, 0x00073b6b294cda6a, 0x00051854d3181244, 0x00049ff216ce9bf7, 0x0000f5f14402d398 }, { 0x00056e372344bdbd, 0x0005f3af02909e50, 0x000f436065b91304, 0x0002579f8c7d59ec, 0x00001766823e2146 }}, {{ 0x00027d200e7695ba, 0x000fb3189e800ca4, 0x0006d1d4e8ef137a, 0x0007f003750fe0c1, 0x0000dad25c5ac540 }, { 0x000807804fa82f49, 0x000994fe616e2c00, 0x0008e610d4715daf, 0x00004e1739c25f4c, 0x0000a1ed59eb55e7 }}, {{ 0x000c966787f80791, 0x000d43a4f0d56f34, 0x00077d92507dca1a, 0x0006bb24b961e404, 0x0000a0d775222852 }, { 0x000bb6d594089b2b, 0x0004142864fee422, 0x000a2f57f8c8c37e, 0x000969659c1be93d, 0x0000e98561f48eb8 }}, {{ 0x0003d36eea5a411b, 0x00083c9b809b7ceb, 0x000b2ef3bd41c883, 0x0005fa4368a41486, 0x00005327a94036a4 }, { 0x0009d81a294550be, 0x000028a328cc987f, 0x000b405a4a382a8d, 0x000c01dba0a3bcd2, 0x0000ecbc7c687492 }}, {{ 0x000ee9ea4399d83c, 0x00029ade4d559419, 0x000d914e5643a410, 0x000194f9bdedafa5, 0x0000ab6a2f9c77b5 }, { 0x00023fc56d6b71dc, 0x000ce1637a55a4a5, 0x0003af1fce4bba9d, 0x0002a5998eb19a51, 0x0000fb6b0a026533 }}, {{ 0x0005384859f3a770, 0x000970cb98fe684f, 0x00091d11cbfe5c75, 0x00014fb3fd60fbe9, 0x000024a2c6896e9f }, { 0x000a7731d1c175f6, 0x0007bf7b59e763bd, 0x000880e35c8c898c, 0x0002e8c923d4606a, 0x00001705d921c944 }}, {{ 0x000bd17983bec34f, 0x000e79390d458714, 0x000fba44f409e51f, 0x000e5b503e976403, 0x0000bb28b50bfeca }, { 0x000460fc77585d24, 0x000439ed5d2c53a7, 0x0008896e3f104db9, 0x0000d454e5ec4bcd, 0x00005c92699d9c5e }}, {{ 0x000cb1236b66c01c, 0x0007f8295caabee0, 0x00057be3de780986, 0x000aeb665de024ca, 0x00001dc5e9d49aa0 }, { 0x0001359afecfc3d8, 0x00005bf0972ebf9d, 0x00045177093370a2, 0x000872776f1dd387, 0x000022a719d4d0a4 }}, {{ 0x000802eabd5b22c0, 0x000fa2b91502cf37, 0x0007904acc9ff780, 0x0000df1c92c3832a, 0x0000c8e7c1032083 }, { 0x0006aeb0c9d5f503, 0x0007027a37fddab7, 0x000b8400f8a95d7b, 0x000f1f61a65d6f2a, 0x0000d4946c17ee3b }}, {{ 0x000af61472ec944c, 0x00013f62f93a6750, 0x0003fafe7206fbed, 0x000f69c84a6ec968, 0x0000e64f69ece348 }, { 0x00036a8a8778d2a5, 0x0009e72a5f696be1, 0x000a5bb870e8f960, 0x0009a4590c65e57e, 0x0000b18bf5bd851b }}, {{ 0x000b4b36c8c2e8ff, 0x00082dc0f9f44d43, 0x000ff0fb2191ea75, 0x0005ed2b1f09a695, 0x00007a5902599c01 }, { 0x000a904b3c1f4b94, 0x000837b3b6b234cb, 0x00045ca08e940188, 0x00034bf1d096a250, 0x0000986acd027cd0 }}, {{ 0x0009958546371d81, 0x00058d493a3147a2, 0x000c70c0cffeda75, 0x000d2f1129f30a5d, 0x0000599e39f58537 }, { 0x0008d658f17504df, 0x0005fffc17db9ba2, 0x000ca23febb75e2d, 0x0004520bccb18548, 0x00007564d18ce2da }}, {{ 0x000e430a33a255cb, 0x00095cda99f8c71a, 0x000a9db438cba264, 0x000f5749967b7abd, 0x0000945a43d068ee }, { 0x000cb8f38cf63ea6, 0x000d0d388ace52f4, 0x0004061e12f02828, 0x000c9271b4bc0fa2, 0x00004dad48391d98 }}, {{ 0x000a1c5643447901, 0x000bd808c3bff364, 0x000208478f323f53, 0x00022dbd1005a0bd, 0x0000ae406a2896e1 }, { 0x000137007e0dbeb6, 0x00025b99fe4fc88b, 0x00081b60bb371dbd, 0x000646bae09418e2, 0x0000cc34af053693 }}, {{ 0x0000693a18674889, 0x00096e1c63c4962c, 0x0008d7b6a10d190a, 0x00003a26b50541e8, 0x0000e282f1e08996 }, { 0x0001ed4e5703fca0, 0x000c04e0117f203b, 0x000258ac6a79aec7, 0x000248c44245f196, 0x0000ff00eb7253c2 }}, {{ 0x0002a6cd6b58c40f, 0x000e675f8547be3b, 0x000cf73d922da584, 0x00000f2000a7033c, 0x000044f163153dc0 }, { 0x000273a484b87506, 0x000aef557933c6b8, 0x000ca899db77a846, 0x0006120b6a7538eb, 0x0000ded4a50d08d4 }}, {{ 0x0003995b1a10381b, 0x0007d450168e508a, 0x0001f60fefa3784d, 0x000788b718cbc9bb, 0x000015ddd98778ea }, { 0x000b59fe5b0f3810, 0x000568e1239e1525, 0x0008605ee199d7d9, 0x000b969635689255, 0x0000ae3fda8f50cc }}, {{ 0x0000f551a177b5e0, 0x00040eb34a9f7aec, 0x0002165c9e43067d, 0x000084f37e5e8cf7, 0x0000983560921b62 }, { 0x000e549e04b370fb, 0x0006768038f67254, 0x00051f3e35b1a2ef, 0x0005adb861dd38e3, 0x0000ac6cfc2b7810 }}, {{ 0x000ddba4b3d8e704, 0x000f53b08b193400, 0x0004bceb33e96771, 0x0002e98c7c2fae6f, 0x0000d016b8e9d8b6 }, { 0x0009d9e008a1dcc9, 0x000feb51dd95f8c7, 0x000754cbe24d3872, 0x0006dc34c1d163cd, 0x0000d6587365fd85 }}, {{ 0x000846f5f2308016, 0x00088bfe6ddd5053, 0x00047cc4f727d222, 0x000b2675737064e7, 0x0000ae37a4ce7376 }, { 0x00090c603077e9a7, 0x000cd9160df1b9b3, 0x0004f411426f0fd9, 0x000e7cd3c4cfb289, 0x0000f64f81bf99d6 }}, {{ 0x000762921d03717d, 0x000d6128c0a78de0, 0x000a17234d538bcc, 0x000a9e882ccd02bd, 0x0000eed2d646e6a2 }, { 0x000287c7f8080a37, 0x000d123d85010c02, 0x000addbd0727cb42, 0x000abb08ad73aaac, 0x000037e0c3c8c39b }}, {{ 0x0009ea4996a3c06e, 0x0008942580b1a014, 0x000d1657f1e2a72a, 0x0001e3344f080415, 0x0000093afc473704 }, { 0x00090e3df700aea3, 0x000eeef571f3913f, 0x0003fca41c93b37a, 0x00008fb8f0610f21, 0x0000984f4e2a8e30 }}, {{ 0x000c69c29d48bff8, 0x00065eb43e2e0349, 0x0003a7d6620d144a, 0x0004ca77f53fb5a3, 0x0000f354b8c1cb22 }, { 0x0006812c52e71fa4, 0x0007bebbace47b69, 0x0009082476997303, 0x00043e13ebdce028, 0x0000fc56789759ad }}, {{ 0x000a5a5512b3d42d, 0x0002a7157151692d, 0x0007ff33c7322027, 0x000656ee1eb2721f, 0x0000ca99ca38747e }, { 0x0001ef52167f204a, 0x0008b5dc6f567809, 0x00037bd855ddf45e, 0x00073d003e20d300, 0x00004fefff6aeb76 }}, {{ 0x000c08620a2c393a, 0x00045c14092d85f7, 0x0005e041820ffc39, 0x00031138172d223c, 0x000087580008988e }, { 0x000769b5baf39b4b, 0x000017dfc588b090, 0x0009510b05f510e9, 0x000b0b995728cd49, 0x00004ab8441733f4 }}, {{ 0x00082ded8c15f913, 0x0000f8bf99c24714, 0x000ad0f0c3845063, 0x000745d24f2d8a11, 0x00002d13601a08bd }, { 0x000fc739d67f549d, 0x0000cd8dadd48854, 0x000ea20b7b714a04, 0x000b658507004477, 0x00002739d35a18aa }}, {{ 0x00010188c19608f8, 0x000b727786f08a98, 0x0005c1c0eabddfc4, 0x000452e708700bb2, 0x0000b09a61e07f86 }, { 0x0009d4f07bc35bad, 0x00023c9abcd3297f, 0x0006faac186ffef6, 0x000734030ae4c896, 0x000068869b2a6b55 }}, {{ 0x000a11de9f5e8da7, 0x000e7d583fa1e08b, 0x000e0499f35bfc4b, 0x000ad6a967780d33, 0x00006387ac199d31 }, { 0x00028fa43af1c617, 0x0001dda02c2d064f, 0x000cb1fe3e00767d, 0x000ca72d87ecf360, 0x00008656d8273918 }}, {{ 0x0003edd0e98b762e, 0x00054cbea4570b35, 0x000b51fdfe00672e, 0x000f31ed5ee65d68, 0x00001bd0155d4d2d }, { 0x000500888c6c33f6, 0x0003d07beb9bc6d2, 0x00077a5bdedc774a, 0x000be200fe9abb90, 0x0000328aca3a48e5 }}, {{ 0x000d700c7f811577, 0x00027d9926fce430, 0x0006f76a1cb0b72a, 0x000373b27809dd1c, 0x0000b7a49c601709 }, { 0x000574395a4d1adf, 0x0000b33ab64a0652, 0x0004edc4a625cb0b, 0x00049167faab9b73, 0x00008e3cbcb5b34e }}, {{ 0x000d0301187bc101, 0x0000eb6700a1acd0, 0x0003f09695693995, 0x000f3e0bae823fd7, 0x0000bc494f5d06f0 }, { 0x00015737c0a7b0f1, 0x000bfc989fca8cdb, 0x000b4882d64acc9e, 0x00080e66f970d01d, 0x00002a01327ea3d1 }}, {{ 0x000860368ee95e14, 0x0001fe8a8b484e77, 0x000901c6a838f33b, 0x000c0ed36b2fdbdf, 0x0000699447c715b5 }, { 0x000e12a5ec3c2973, 0x000b91cf9ad3e183, 0x00072a8ca88d9d13, 0x000267eb66d6c5f1, 0x000078786b1aa576 }}, {{ 0x000c54b9cb562934, 0x00040e9a56b872f8, 0x000c70a1d4d6fe0c, 0x0002cdaf7a1ad550, 0x0000563272b206e9 }, { 0x000acf260393473d, 0x000cd4a088ac342d, 0x000b3aa7a0ccb38c, 0x0004f4ce9ec450c7, 0x00001b6e01fa188c }}, {{ 0x000cba2eeb210411, 0x00026c6c8cb6b42a, 0x00030cb4c496878e, 0x000ec67251326fc9, 0x000017ca1f4e8294 }, { 0x0007a18a6d684fc4, 0x000c47a633c30000, 0x0002d02a45040c90, 0x0001d2dbecb6cd17, 0x000008914cbb715b }}, {{ 0x000b3294258afecb, 0x0005b799edce57e9, 0x000443cd891c286d, 0x000a327c652b892f, 0x00002fc850e5378b }, { 0x000c76a331bc95f9, 0x000e1f2bd2e21df5, 0x000ca5d06767748a, 0x000c7ba2e55298d2, 0x0000676b98053ae3 }}, {{ 0x000d2c801bc4bf64, 0x000fdfff8a4f29c3, 0x000099630d2de628, 0x000f1ce1c70dc924, 0x0000ea1da14883bc }, { 0x0001e8e630540696, 0x0006172425218760, 0x000c3f839381a073, 0x00037c5c90bed93b, 0x000079f89d6bd4d2 }}, {{ 0x000f0e75ce977889, 0x000de38c6f3431e1, 0x0002c417ff72df79, 0x00013fe7ce609cb0, 0x00009a2977125eea }, { 0x000b453193606cdc, 0x000ee641158544d7, 0x0008f171ed3d9490, 0x0003d6b555d777e8, 0x0000d3214ae1a449 }}, {{ 0x000a448a130c115a, 0x0009c8839f05ffea, 0x000fc33dcd3bcf48, 0x00017d31b8f4f4bd, 0x0000992eb014f9e2 }, { 0x000af5cebde70108, 0x00089b3f7914967f, 0x000a1e12d72fc4cd, 0x0000f3ae74537f09, 0x0000f1941d7b610e }}, {{ 0x00011f21588397cb, 0x00032874ca6b39ac, 0x000c41d0b1e9ef78, 0x000c4c3db70fb72e, 0x0000a9adbfdfa153 }, { 0x000e9af3e27ac409, 0x000ed35bf3bfebf3, 0x00042d3e6c3d4995, 0x0005cc2733a1ff0b, 0x00008605fa3d4149 }}, {{ 0x00028d0a1e02ab66, 0x000c672b41c34403, 0x0005b0769041de1c, 0x000dc2fa3175239e, 0x00007eb126a76c52 }, { 0x00054fa107e49200, 0x0005f2ed3788a049, 0x0005d171799725b7, 0x0004492d625d8ff1, 0x0000ec4457bdfdba }}, {{ 0x0004ee0734a79d5e, 0x0004df2e98aaa995, 0x000041c2f15629cd, 0x000b6a46a90cd8ba, 0x000006e82e9e4e19 }, { 0x0002e25421fbf8ee, 0x000b05445b4147a9, 0x000107702d4ac0ff, 0x000bd40773d102f2, 0x0000f9d11eeb5c3d }}, {{ 0x000a2e45bf1c1c78, 0x0006071bb608558c, 0x000e2ca6b9dcbb05, 0x000d5fe3e60e4eba, 0x0000055d8f3a5a25 }, { 0x000d5d7316bcf10b, 0x00067ec2bfd7a5f1, 0x000f57733e16a9e0, 0x000cd65dc528a8f2, 0x0000538112b6221d }}, {{ 0x0004396860fdc301, 0x000174adf423e315, 0x00015aa1b1af53ef, 0x00098c9b9cb41729, 0x000050c9de633264 }, { 0x00088ae797a2c6e3, 0x00013c4a54ae57ef, 0x000ff5d9a705ab8d, 0x0003413bc0ffeb58, 0x000021a5f9a644c8 }}, {{ 0x0001abd8610e73d8, 0x0004544d2359ed9e, 0x000311a87481122b, 0x000de0d69ac68dd0, 0x0000f82040d9e6ee }, { 0x00048969704b7037, 0x000e1d9343b6e3a4, 0x00086f80b23dd859, 0x000cf0767480797e, 0x00006cd8d794a707 }}, {{ 0x000fc09d2dcb11e8, 0x000285552a82e8de, 0x000488856faec190, 0x000f18978b2caf78, 0x000085276cc6351d }, { 0x0006b1386691ac89, 0x00070ee9113be5c0, 0x000fad47eeb5cd81, 0x000d773542fbda78, 0x0000a86b95d248fd }}, {{ 0x0006d449d8e3dcd4, 0x000740f43e3865d4, 0x0007d70afe005519, 0x000438bf772dd77a, 0x0000b18fb1739868 }, { 0x00018bef015b1939, 0x000e0ea185d706fc, 0x000b06519061374c, 0x000a2e731e47e02e, 0x0000ca817e6aa631 }}, {{ 0x0002887ba15c20fd, 0x0007d9c6bdf22da8, 0x000f0e54073dbcd2, 0x0004f3951efbc432, 0x0000469ec570ed01 }, { 0x000deaa2e18dbfd8, 0x000c5dab920ec1de, 0x0002fe53ea59ef2c, 0x000e8af47d0d7e8c, 0x000015e430f8b3be }}, {{ 0x000111a7619e2658, 0x000c5936cc874756, 0x00020c11dc5ba7f4, 0x00069dd46d92a52e, 0x00007437d17bf839 }, { 0x00049cab0510e4cd, 0x000b7feb3d5f6126, 0x000cfc4b7de6fa00, 0x00023a3305ea69b8, 0x000003184fab8043 }}, {{ 0x0000efb2747d10ac, 0x00041cf8bdce214d, 0x0001b5bfc0eca8dc, 0x000280de2b5622f7, 0x0000eaba332135f3 }, { 0x00040a52c6704d02, 0x000f68b79df975b7, 0x0005a58efd781132, 0x000ebea46856bf28, 0x000034b117e458df }}, {{ 0x00080784d755ed6d, 0x0004e152cbb1a3f8, 0x000d8fa0af51d84b, 0x000794e74c3eb99f, 0x0000d39835b41a87 }, { 0x00041e50a81e7f57, 0x000f51cb4e7a0be1, 0x000da8f75687bf48, 0x0006cd9e18780510, 0x0000e64f1df80763 }}, {{ 0x00043afaf8568dee, 0x000691847be87ae0, 0x0007f32f4879b707, 0x00079d5d368a6141, 0x00002b47d1718f6f }, { 0x0004001ae4f33965, 0x0007c211552a4d28, 0x0002374d2fcfd8db, 0x000feb1a4b6dee69, 0x00000e25e4bee3ac }}, {{ 0x0003473caf8cdb36, 0x0004d44d795fb455, 0x000d645818f5cf12, 0x000f1a9fc57326e7, 0x0000b402e73630bd }, { 0x0005614508afbc82, 0x0006993a13df4c82, 0x0006726a9f66c94a, 0x000284af8a73e51f, 0x0000c55c0677d85b }}, {{ 0x0000b9c41619d1d1, 0x000286211a71b27b, 0x000abafe3623481e, 0x0000622efdf71412, 0x00003f1c33b3a212 }, { 0x000e3bcc6e9333c9, 0x0007c52014cdde5e, 0x000a343f7f4d5b8d, 0x000b5bff3702c624, 0x000071d00de55440 }}, {{ 0x00046ed52661de90, 0x000f22a42ac6c853, 0x0005e98b1d913b21, 0x000ff8e582db0cea, 0x000088053a8d84e0 }, { 0x0005662908845062, 0x000c7951a2faf097, 0x000006bf38262f45, 0x000a502902fa8a58, 0x0000693f983dd1f8 }}, {{ 0x00020c5984ecc7c0, 0x00035c53d080847c, 0x000890357b714942, 0x000ce5a63cb081d3, 0x000080dfb69e8b8a }, { 0x000fbd9c6a0c8dae, 0x000fc7cf902f245a, 0x00059e95ceb430b2, 0x00025654f9cb1273, 0x000018bbaa36708d }}, {{ 0x000322f9d772ff68, 0x0007b0ac7088c7d2, 0x00000ee43ec82717, 0x0004112535ab6571, 0x0000826ae5c2a874 }, { 0x0003b5b6363c24f8, 0x000fa2d7430de4de, 0x000602d6f37384cd, 0x0006960681938269, 0x000039706131bb55 }}, {{ 0x000a9ac3ed8e4ce8, 0x00011803fbc43419, 0x000fc0c429608622, 0x00035fc1d359f2c7, 0x0000af92e79860e6 }, { 0x000cd6f4e3313ee1, 0x000c5fe91fc50ae7, 0x000b493d05996022, 0x000f4105a89ccc66, 0x0000e63d8e773195 }}, {{ 0x0000f3ffc1435cfd, 0x0009b69ce56b40e9, 0x000c2f39ded7b89a, 0x000912fd7f93e094, 0x000003a249c0e7aa }, { 0x0003ffdeb1ddd9da, 0x000235608241aedd, 0x00072cb1d136a3ce, 0x00057335295ab7ad, 0x0000f449ec6ba460 }}, {{ 0x000389cfbf4c9e0c, 0x0005091d11a8594e, 0x00074e459df97c5a, 0x00017d3d02e74d25, 0x000044ebb0b8e3b6 }, { 0x000ea3c28478a740, 0x0002405941768d8b, 0x0004451bbfd95774, 0x00025d7e24510399, 0x0000fd86525ee1de }}, {{ 0x000301e47f2cd335, 0x0008b6ed9a475207, 0x000a3c833f852147, 0x000b42f8afbfe18a, 0x0000580fe7496353 }, { 0x000afffe040e720e, 0x000ebddb299b9777, 0x000b2ab785106b87, 0x0000a82e776697a7, 0x0000b8a44884646f }}, {{ 0x000cfb5fa19ed6c2, 0x0007c4b28c22cee9, 0x00076d01f60cbc18, 0x000539b6aefb0ecd, 0x0000f84ec5d3906e }, { 0x0001527a37e73f9e, 0x0006d57f36e1ac55, 0x000ce5788145521e, 0x000c926db008fa9a, 0x0000af255a03386b }}, {{ 0x000db8eaa84aa125, 0x000c9305bd213110, 0x000282e3a62f6f6c, 0x000e571d36ed41b2, 0x00002902def1b031 }, { 0x000bc226cb0016cb, 0x0003337b24b4b6f6, 0x0007e66af842d281, 0x0008210d9fe58afe, 0x0000f22b8a2b6b8c }}, {{ 0x00062dbbba9d84ad, 0x0008b4ece53c2d04, 0x000d18184b2003a6, 0x0006765b0779d897, 0x000067fc9538f5d6 }, { 0x000035f7ff931704, 0x00005f2cafe37b68, 0x000f6c983617d6e7, 0x000df03fd273d1eb, 0x0000249da2e138a9 }}, }, { /* digit=21 (1,2,..,64)*(2^{147})*G */ {{ 0x0009d1febf2de9a9, 0x0008bc77e6c55202, 0x000fb2e7eb995763, 0x0009cbd6dc27df9e, 0x0000444476cdaaa8 }, { 0x000ba7ced0785f36, 0x0004b9e93470afed, 0x000906fab0ce1fe7, 0x000bf2f043e6a966, 0x0000d9c1876fd26a }}, {{ 0x0008d94f6be7acf2, 0x0000341338d6e434, 0x0002fc6886610503, 0x0000f96ca56f7dd7, 0x00002f54a7c972af }, { 0x0003e19d89ed269e, 0x00005bb2ef8279cf, 0x000a1736ca68762e, 0x000fbb351d575465, 0x000061e8deb175a7 }}, {{ 0x000f96f33f9e0680, 0x000b268e32dd620a, 0x000eb2e15662f4a1, 0x000310882913ec99, 0x00003ddc488aba8e }, { 0x0003f9b5a7ed9adf, 0x00058e5dc3fa8a51, 0x00019cb68475d2cc, 0x0005558b0236bb53, 0x0000fb0d86c8819c }}, {{ 0x0002aae2b99711c5, 0x00031ce51efb3108, 0x000412e3130475fc, 0x00003c959cb5b2eb, 0x0000efeaac806f9f }, { 0x0004837f98bf8cb0, 0x000da39411aa636f, 0x0004e03d299b3bd8, 0x0006376b77152ecc, 0x0000b7bc15a5f18a }}, {{ 0x0001162ade988968, 0x0009ac4c753c45fb, 0x000648b216204571, 0x0006f3be618ca81b, 0x00009a6be30dbc18 }, { 0x00042cd4528f9326, 0x0008720236e3ab64, 0x00056e788ed3e0dd, 0x000e9967af88cdaf, 0x0000c45162d8c709 }}, {{ 0x00083eca38629302, 0x000f164b71698f58, 0x0002173c96261574, 0x000a82abb6ba418d, 0x0000a7d774e7d73d }, { 0x000c1dd5576a4dbc, 0x000283ff3437f24a, 0x0001f86ddde594be, 0x000503b65e910b43, 0x00004e079387d0c8 }}, {{ 0x0004a222c42e90db, 0x00035f924a0a3fcd, 0x000413dfa13526e5, 0x0007cd19938e17bf, 0x0000dbc59707ebbe }, { 0x00038d8fd101963f, 0x000debe13f542b66, 0x000d80984486c605, 0x0005578791fc65e0, 0x0000318e04247e1c }}, {{ 0x00039d3ee2963f2f, 0x000233a626332d5d, 0x000281c47c620310, 0x000452fa27bc3883, 0x00006bc300c4cda7 }, { 0x0004c341a09ee9c3, 0x0003ad3e7676b0dc, 0x000f36ad1e76c678, 0x0007b36a8620e35f, 0x00009710f4c3af53 }}, {{ 0x00073207beab3a63, 0x0009a2f69beb6e85, 0x0003163e05455030, 0x000493e4f3a50b99, 0x0000ae1c490dee61 }, { 0x000c1b26b4aa0c62, 0x00020e309fe7e5b9, 0x00039f25812cb0ec, 0x00023f4e2957678a, 0x0000be251e8728aa }}, {{ 0x0000e7c2becbd6ac, 0x000da1cf405ff065, 0x000cf786bfcc5059, 0x0009287fcebac86b, 0x000006628092b297 }, { 0x0003a21f33a3f231, 0x0006f95fa90d7679, 0x000b52ce8c481fe2, 0x00088d46dae60eb7, 0x0000dd27b34c3095 }}, {{ 0x00081eea1daaae26, 0x000110babb886433, 0x0006eac32b7bbb8e, 0x000c7f07191df36d, 0x00000e8acae417e0 }, { 0x0009aba1faa58bab, 0x00046ba39966e6ca, 0x00083d7db2981427, 0x00026c07f7c464a2, 0x0000d90bb6000f64 }}, {{ 0x0007112386fc20ce, 0x0005122369b87ada, 0x00088beb81cf895b, 0x0008f96663c00e5d, 0x0000786fe6f72494 }, { 0x0003cd4c08b1b97b, 0x00066986d9bd5f51, 0x000845f5fa36c27c, 0x000c259b22dcc7e3, 0x00003a7a6a264018 }}, {{ 0x00066ec8de9b7d5f, 0x000fef8e32377106, 0x000e65642ed171bd, 0x0002ca92b0dadb26, 0x00004cd467fccd49 }, { 0x000b7d34d2311a46, 0x000d8d5ee5242161, 0x000b265d7be3eae2, 0x0006c90bacd93c59, 0x0000677b279563a0 }}, {{ 0x00014104124194f3, 0x000f16022caf46b4, 0x000f5955fa3d17a1, 0x000fa544e6a45dd8, 0x000027f7e6432277 }, { 0x0001bcd329f0aee1, 0x000ac1241de97bff, 0x0000cbc3ebca8120, 0x0002c1f37b8547b6, 0x000028b36f4746d4 }}, {{ 0x0003e297caf789c4, 0x0006a0910caad676, 0x000ff14f0a163a1f, 0x000c604401f59195, 0x000036cf5f7f1567 }, { 0x000cd19846f4da2f, 0x000dc2e49abad67c, 0x000c206c18924750, 0x00014ee406ec405f, 0x000043041d3be98b }}, {{ 0x0004a07f82ebea7c, 0x000b5769bb816483, 0x00053090a14d150d, 0x000e04062d69eb48, 0x00003488c7727160 }, { 0x00062b085ef31ed0, 0x0002787bbfb55541, 0x00004cb77b99391c, 0x0007343a0b06ed4d, 0x00001334165040ae }}, {{ 0x000ae1cac5e3f9c0, 0x0000b31e0dd3eca2, 0x000cba4d48dfd8b5, 0x000c10297c6237fb, 0x0000108543603d43 }, { 0x0006f85dc5404165, 0x000a2d47845ae4f6, 0x00026761151b0706, 0x00037b0bbfec7dd9, 0x00008f9d062c7bdd }}, {{ 0x000c6ff6e5be4b0a, 0x000ae88bdbcf0ca3, 0x0006a2b7a7ba1b36, 0x00009df34d75f5da, 0x0000309466d23eb2 }, { 0x000f30b5ece886f8, 0x00084f4047d26e4d, 0x00077119364a90d4, 0x000524daff370f7b, 0x0000a8cfc76f60e6 }}, {{ 0x000e32f8475f689e, 0x000ae624896246e5, 0x0006905dc38a3b9a, 0x000963d735652c01, 0x00005aec6e092828 }, { 0x00069e5622c8ef2d, 0x0008612cf933c835, 0x000dc3e0f1c33e14, 0x000acf715d05bb76, 0x00001af4af25e9cb }}, {{ 0x000f6d12f8d61cbc, 0x0002f3a6568013e8, 0x000e93853103e5cd, 0x00025b74a8dbd203, 0x00007ce46d1f9bdd }, { 0x0000b6a7c6e4974b, 0x000c5a2c9eade291, 0x000337266751d4ee, 0x00084c246bab4f32, 0x0000f12b5a16b482 }}, {{ 0x0004d506bf73235e, 0x0007ff33035b41cc, 0x000ed4ef51d687f6, 0x000a4f9e5d336343, 0x000094104ca078e1 }, { 0x000895041f284f32, 0x00096cbbbc33f758, 0x000a09cdc35e1489, 0x000caf6237281f08, 0x000051a7f97c87c8 }}, {{ 0x00013888f004cd15, 0x000d5499c438edfc, 0x0002d0b53154f812, 0x000ed3bf07678dcc, 0x00000b340fc797dd }, { 0x000ce0637b7a5424, 0x00036d41140af420, 0x0003858e6e2c47bf, 0x000a2455f8e5104f, 0x00009c5fb7f1500e }}, {{ 0x00000c81b681942b, 0x000d6e6fe631e8f0, 0x0007d7b150953146, 0x00006a94f1c5563d, 0x0000b00f364d03b5 }, { 0x0006d17634ee0c1b, 0x0008e51aae1fd9a7, 0x000716897755713c, 0x0008cab22e35626c, 0x00003897cfcc2e16 }}, {{ 0x000127ee79d5b629, 0x000e4daeb300f7aa, 0x000c4c8df9876122, 0x0001efb4c9dcf7df, 0x00001b98eaecee9f }, { 0x000be67d99c079ff, 0x000cd53575f1dbba, 0x0004d4ff98848810, 0x000ac51d095037e8, 0x0000af6c7913e968 }}, {{ 0x000227b7d5fa2779, 0x0001b4b3f8e10652, 0x000610e6d14e4258, 0x0002b8836ed908cb, 0x00003ee0ee50ff75 }, { 0x000381ae0cc87753, 0x0007593b5cd6dd54, 0x000162a5e8db86de, 0x000a18e2c82225e1, 0x000026e1628fc502 }}, {{ 0x000ea9dd3d739ece, 0x00045d37fafa4c8b, 0x000145e7cd82c0ba, 0x000ca584c3d91808, 0x00000a483c77e1ca }, { 0x000b89ee5c5235ad, 0x00023673eadd3e7c, 0x000739e9ce7c6b70, 0x0006c9b6c0033c1b, 0x000042ac04521d0b }}, {{ 0x000ec25669d8ed84, 0x00024f322532e5d5, 0x000013bba5e2b6f3, 0x00079a2dbb6410ff, 0x000030dbc6caee49 }, { 0x0005a7ea04cc0c9d, 0x00091064c3beb017, 0x00000526bb51e340, 0x00076ab7a852123d, 0x0000ef64f923f62b }}, {{ 0x0004049e0b602df5, 0x0009a356798e4ba6, 0x000563cc4285eaa9, 0x000fb0f039214e6e, 0x000054c04a0b7d50 }, { 0x0008dabf1a099126, 0x00034f13ae9841ff, 0x0008b7dba38bfa5e, 0x000b40e58dbe4ca1, 0x00003b573ac345f0 }}, {{ 0x0000c60f36acc716, 0x000daaacce2793bb, 0x000e1526388b0989, 0x0005c39a971db851, 0x0000043ab896078e }, { 0x000ff069e32c40e4, 0x0008d21774eadbd4, 0x000f7e41ce7fd901, 0x000c7857625367fa, 0x0000b451922fe6a0 }}, {{ 0x0000e7363ef92c3e, 0x00014568776e6676, 0x000c515535767ae8, 0x0000e4c876e76142, 0x00007574380ed322 }, { 0x0004548dca9348c5, 0x000800eb7366d800, 0x000a43e34e14c3f8, 0x0008b6c6fe4ee14c, 0x0000f0365a22d0d6 }}, {{ 0x000b8dd3d3c731b7, 0x000974c5ae888eb9, 0x0000bb5bd8c5d56d, 0x000390929733abb5, 0x00006206511f4cf3 }, { 0x0006c1ff0991bcef, 0x0005d920bc5d11a2, 0x0007759d899a17fe, 0x000604db8f20127a, 0x0000afba4da06484 }}, {{ 0x00027d09f86b87a6, 0x000672f7189e71f4, 0x00081c5287eec6df, 0x000edd421c643874, 0x0000dd3e802a5f6f }, { 0x0005cba1123d99ff, 0x000318f38384a7a9, 0x00041aa78a8746d0, 0x000ea5919aac3acb, 0x00001546626df6d9 }}, {{ 0x000d7ba8b08355a7, 0x000a87fb00009c49, 0x0006f276e2aeebe7, 0x00041f05db8396c2, 0x0000859783ac9299 }, { 0x000c3a6250aec83b, 0x000b59f34f485b64, 0x000c17d7c2c584c4, 0x0000c36febc0ddac, 0x00001a06deb2c157 }}, {{ 0x000630745c2443f6, 0x000db03d1295837c, 0x000f71d776d34583, 0x000701e91a2893e4, 0x00009134f5638299 }, { 0x000d8586465dff85, 0x0008b9e48661ae16, 0x000b7ca5a02e6a92, 0x0002951b58d17e7e, 0x0000e3f1660e4165 }}, {{ 0x0009be4d8ef6f6d7, 0x0004d3e19115ead5, 0x000df1ee024075e8, 0x000331b5b1ce1393, 0x000093c9ce9841a5 }, { 0x00058519cc609023, 0x000bd6cd0def72b5, 0x000d8aaf0d7bacb6, 0x000dd273db923db5, 0x00006b02deb40132 }}, {{ 0x000c548b69ea5df5, 0x000f6f8827097ef5, 0x000b740069f3544a, 0x000d0db89259353d, 0x0000e612d2045282 }, { 0x0008b57bb32e6372, 0x0008416994b995dc, 0x0005dcceda4ea724, 0x000bc67f04d1531f, 0x00007cded8a96b16 }}, {{ 0x000c6b9000bbb209, 0x00006cb1cd5ad73c, 0x000594d94a4eac92, 0x000b0b5b8b9c860e, 0x00007f19f8ffa9c8 }, { 0x000d03e590e97791, 0x0007ca420c8a471b, 0x0000bafb9a1ec30a, 0x0003e497769ae05a, 0x00000ae589eaa8d6 }}, {{ 0x00098231b2fdae8d, 0x0009e5eb2940d9e2, 0x00062218c3b180d7, 0x00034763d3c663d8, 0x000079ac5ceb7ec0 }, { 0x0008b408269ba673, 0x0009a2c552ad093f, 0x000c06d13e6ea662, 0x000789a00a4799d1, 0x00006bad7b20b037 }}, {{ 0x000f3764f7b38e54, 0x0005dedf1bd72186, 0x000adbed6377389b, 0x000079665d491c53, 0x00000d1755479780 }, { 0x00048c7a526618d7, 0x0003a6dcdc348009, 0x00062d56bf03752a, 0x00092516bcdbcd45, 0x0000cec167b1ee0e }}, {{ 0x000439be9201d0e9, 0x000c1377378058e6, 0x0000a00752c2e9b0, 0x000b1a1c741c746a, 0x0000bb3ea39e2af9 }, { 0x000f7de5688e9cd2, 0x000e2b043a2fbad0, 0x000f733802d7bd56, 0x000faeb4c39e6dad, 0x000033ce90509fd4 }}, {{ 0x000b539dc2f62b1e, 0x000a7a1d2ffbfc15, 0x0009f177c68e623a, 0x000880758f74211f, 0x0000f1010e0ac5ca }, { 0x000a989eca797cca, 0x000b9d02f3af6f6c, 0x0007cefab003de17, 0x0004d1f835213207, 0x000053ff9d904563 }}, {{ 0x000c547b711b42fe, 0x000ca29d6f62f995, 0x0008efd6009b4f01, 0x0005dcd0a8f06a30, 0x0000d50d91362f7d }, { 0x000916e5205bf484, 0x000bce1682afe112, 0x000a522adb87ea28, 0x00018d9369e0fc77, 0x000083acc24ddd86 }}, {{ 0x000fc96822eaed69, 0x000e9e83f883faf0, 0x00091bbd25130ab0, 0x000b42f81396f963, 0x0000c9a426aabc61 }, { 0x000ba8446d25cd38, 0x0003d8766f1c68d2, 0x0003cf9f27a01b56, 0x00052259010fc6de, 0x0000b7f2dba90c5e }}, {{ 0x0002ac509835efa4, 0x0001520ef4a9975b, 0x00037083f2c76c48, 0x000c843b560bb600, 0x0000295a37fec299 }, { 0x000d83ca9a68bcb1, 0x0003d2fb0d1ea67c, 0x0009a7419796877a, 0x000c6d9e6ae779a6, 0x000089f4f8df2e42 }}, {{ 0x000ecbc81ce29d74, 0x0004af5e33deed3a, 0x000e514cca8bd88a, 0x00042493ee6356f6, 0x0000b9f30d92af98 }, { 0x000e29242f1443f0, 0x000c909e6e861dcc, 0x000385ccd3d2d0ba, 0x000f07e5790a247a, 0x00004947dfd69c12 }}, {{ 0x0001d1645c39f241, 0x000e04a2f998a912, 0x0001b2e98e1ecaea, 0x000d02622271ee9b, 0x00004196510475ae }, { 0x0005bbdedb159a7a, 0x000aa2c7501779c0, 0x0007f452a12df2d4, 0x0007df729f006140, 0x0000ac021b7f9c4a }}, {{ 0x000c314056ab1eb9, 0x0008f3225d984730, 0x0005503443d0bd10, 0x0004846a1f207fe8, 0x0000f455eb506396 }, { 0x000e1c005b309371, 0x000938f4107e28f1, 0x0001230567e4dd24, 0x000104f6e74ed387, 0x00008f86c0103426 }}, {{ 0x000a793b2657b1ce, 0x0005c73f37ec3c39, 0x000d42e0b07a8381, 0x0009b6457c65259b, 0x0000b5dfca037683 }, { 0x000a1d4307f2b6b5, 0x0002e4be43756f0e, 0x000db0de13c200e9, 0x00069d6272f76bdc, 0x0000caa7d0f8726e }}, {{ 0x000ad40c5a7ab2a8, 0x000ab308bdf623a6, 0x000a196def2311a6, 0x0002b55955f5accd, 0x0000420ad92fbdb8 }, { 0x000ee1c791d19a99, 0x0002189aeca8709a, 0x00007d42c30b7260, 0x000c8e176c64a7cf, 0x00004c391ad3c0a0 }}, {{ 0x00097b04cf4dcd27, 0x00071fd21a843b21, 0x000d738557e2a32a, 0x0004063be56e4ed4, 0x0000f569b199b0d1 }, { 0x00027ecdb28f119d, 0x000161ffd42c13f0, 0x0002b190c58ab2e8, 0x0004f1dd45ef7feb, 0x00003bb3c53e8fce }}, {{ 0x000985b93206998e, 0x00056d14e3352feb, 0x000eb9d3625dfe11, 0x00040ef6008414d2, 0x00001dabe9e71cb1 }, { 0x00010ec86988d8f2, 0x000e1ab96bf36f90, 0x0005bad089761cb9, 0x00093257d012dbed, 0x0000392d438d5756 }}, {{ 0x0006074b7b7f3ff9, 0x00007f6bf926dffa, 0x00014eb820473ad7, 0x0009a18f57c9fdbd, 0x0000f0b5518a13e5 }, { 0x000bb55bbfa1756b, 0x0009566e84f44a48, 0x000846c6398e72b1, 0x0007e239a99998d3, 0x0000d5d77e99f313 }}, {{ 0x0002f49e3766fab5, 0x000bdb40ea2ab303, 0x0000c448caa69039, 0x000c82cebd365a34, 0x000050f4208830b2 }, { 0x000004213cabc507, 0x00050f101d8b4d66, 0x000bc6b055c40b77, 0x000137b6a03c8423, 0x0000747dddf18bf9 }}, {{ 0x0008f4ffcfd9c86f, 0x000f5a1c1c06681f, 0x000ef60c8e811dc3, 0x0007a43b316e0a16, 0x000027129f4ec201 }, { 0x000aba00062f76e3, 0x0008ecd4cc5e3e06, 0x000a366fe3da9e55, 0x0003be8f1d55c7cf, 0x0000d191984e99e0 }}, {{ 0x000c5d7ec808f4e1, 0x000fa30d232cfc4d, 0x000df92cbe274727, 0x000ebb0499ddcf12, 0x00001e2f6a31d47e }, { 0x000abfb950d7fce1, 0x000b76e0b50d7dd6, 0x000715bf57d98c4a, 0x0000e08f688fdbaf, 0x000030c606a9d9d8 }}, {{ 0x0002335df2a1fb08, 0x0003c878a429f4f8, 0x000b591e08172eac, 0x0006eaddf0649712, 0x0000e4d7ee646545 }, { 0x00038956fb888a73, 0x0007d675c93d9950, 0x000a64de24ea9aff, 0x0004f221b59ac367, 0x0000ca2c7aa20399 }}, {{ 0x000ac7d898fb100b, 0x0003dcbbb734e37e, 0x0001411dd9d6657e, 0x000a195d9c08c0bf, 0x0000b128040fa2fe }, { 0x0004303f220f9f80, 0x000cbafbc1a6dea1, 0x000f02fa70b9b9bc, 0x00096441afdd0e2b, 0x0000f73ba67d9a72 }}, {{ 0x000a9157dd651c99, 0x0009d210408f237b, 0x000a32417a1054e9, 0x0008f1da2cad3b09, 0x000057f0f2c67ced }, { 0x00053cba344ed082, 0x000b3074f013efbe, 0x000ac4fc0a6eafae, 0x000d5c1451b112c4, 0x00003f0ad4322c4c }}, {{ 0x00074ea0b52dc146, 0x0001a63ded40d232, 0x000d2d41ed701785, 0x0007af6313d5f1f4, 0x0000d9a531a3ad12 }, { 0x000744ef50a57f11, 0x0007c99451d1b71a, 0x0002e834e0295a02, 0x0004f26f580e8264, 0x00004d9fa000c2ce }}, {{ 0x000fe5e5592df016, 0x000d1f5cf551396c, 0x000db6a682124601, 0x000541636c616898, 0x0000d5c526596e5e }, { 0x000fa2cd6fae11ac, 0x0002c187051f476d, 0x0005354d66d26431, 0x0003324f656fad2a, 0x0000bcf48f474c5c }}, {{ 0x0002136d7196d889, 0x000f83ad15d15174, 0x0001f569d783786a, 0x000612a5f61214cb, 0x00008b285ec5b82f }, { 0x000ec5c4199a8b19, 0x000581b084172219, 0x0002b38e963dfce9, 0x000c53f2d0a5546b, 0x0000d57c27a12776 }}, {{ 0x000378c25b25433e, 0x0009ead771849f1d, 0x00042e5efd140744, 0x000ce30b2b0c932c, 0x00002dbc7048e363 }, { 0x000fbfe01a53e807, 0x00099da9e6e3e319, 0x000d16caf5b6722a, 0x000dee6b80417a54, 0x0000e7b46d452fce }}, {{ 0x000e093761507e7d, 0x000a805ba9384a2d, 0x000d86a4325fdf2a, 0x000bcb8a621b8596, 0x0000d301c511e847 }, { 0x0004f1d7d5d3607e, 0x0004ec8f7bffe6d9, 0x000ec8a24e675bb4, 0x000936e3027566bf, 0x00008ff4238ff05a }}, {{ 0x000842e7e3646f13, 0x000721aaaca5e9b7, 0x0000de2e53b43348, 0x0009b4ef6518aa52, 0x00004c1f8413e3b0 }, { 0x00027091000d9504, 0x000ab656868a5489, 0x00024df86b81806a, 0x000fc7333d963bd8, 0x000027dffecf8b57 }}, }, { /* digit=22 (1,2,..,64)*(2^{154})*G */ {{ 0x000de8cdd0926a17, 0x000b2a7d298c241d, 0x00097897af2c8ee1, 0x000fad3dbe3b697b, 0x000095a39dc131b2 }, { 0x00088519ea3f0b69, 0x00087a75a4d2604d, 0x000e93901ec55560, 0x0004fb6cc27154d7, 0x00006bfc52e1469f }}, {{ 0x0002571fa1c005d3, 0x0000a1a7cb1282c7, 0x00064bef7798f823, 0x0000303b2a08d762, 0x000094b95e409f27 }, { 0x000cc832f936b83a, 0x000392ff22dfd98c, 0x000633bedd944ef9, 0x000cfe67a87ab01a, 0x00004e149b05af22 }}, {{ 0x000f839761bec299, 0x000fc0e36ff3bf0c, 0x000f212faed6d78a, 0x00014bf5f8ad20f6, 0x0000003cd07951f7 }, { 0x000f568724f96e64, 0x00061b38288c545c, 0x000a43bae4ac5ec1, 0x000b2bcef2f8e4e9, 0x0000482335f80a39 }}, {{ 0x0005d70b7657b7a1, 0x0007085ca8d9d1ae, 0x000cf3b0d35bf0d7, 0x0000cc024adf2c77, 0x000069d110cf7a09 }, { 0x0003a7564e157769, 0x0001d506260e70ff, 0x000703a97ab76d5e, 0x000435a6439d75ea, 0x000076aec3e36360 }}, {{ 0x000b491d7bce26e6, 0x0001ecd2f52d2a7a, 0x000a379638de4a08, 0x00078ccf74fde149, 0x000012daea2770d9 }, { 0x00082aa266a6dcf5, 0x0007718c6312c7fe, 0x000c827977f0f2fa, 0x000766ea0ca0d5f3, 0x0000282fd2c5bf2a }}, {{ 0x000b4394784f1e40, 0x0000700ec3128c2f, 0x000192f4aad1458d, 0x00011e4eb6c76d86, 0x0000e130115cd871 }, { 0x00052289429acd15, 0x000614a8dc796230, 0x000daf1e7270619b, 0x000f8d90d5b86995, 0x0000166c13057d31 }}, {{ 0x0006fdbec46ef830, 0x00010a51e6a75c1d, 0x000537aa19534622, 0x0007f159724327c7, 0x0000279e5d72bd98 }, { 0x000d87b2825485ae, 0x000effb13c90f48c, 0x00029ae73fe0cc43, 0x00070a0ebd6ac527, 0x0000b44da3075aaa }}, {{ 0x0002f99d592d4607, 0x0009d3e3fcd3efca, 0x0004150ef1418504, 0x000f73feadd26c03, 0x0000c8303bb7708f }, { 0x00028bb4209cedef, 0x000e4552f1da46cd, 0x000d486f19b140bd, 0x000e6167872c3f8c, 0x0000b4a36e89cdf5 }}, {{ 0x000c77a0a3360371, 0x0009611745edc116, 0x000cd150d4b51af8, 0x00099ad649dd9ad7, 0x00009c97f502587e }, { 0x0009ae48860379bb, 0x000eb296baf7cb10, 0x0001c348e49c5f3f, 0x000e9d571cf065f9, 0x0000b56bcf3f6375 }}, {{ 0x0003b56be8e6e5b5, 0x00086ecee8314f30, 0x000dd834bda67796, 0x0009af7ec1c068ae, 0x000043ec03cb0895 }, { 0x000635be527dea03, 0x000b5f29222882d6, 0x00065e79cda53115, 0x000db7a8c95ff38f, 0x000042689771e2a1 }}, {{ 0x0006fa038810126b, 0x000e776a5177900a, 0x00074f8b83c9f4be, 0x000030e6c4e1dbb4, 0x000046c45fbd9ab6 }, { 0x000f312eb8992e97, 0x000c6562844c6d0a, 0x000a547118c55450, 0x000088ad6c633cf9, 0x00009ee0bbc48794 }}, {{ 0x0007709b7b97f8c5, 0x000cdd2e7417ce17, 0x00011f9e4c798c2e, 0x0006edf1eff42bc7, 0x0000d3407d05f1c4 }, { 0x000b2930ca06e395, 0x000de1dbe217f2cb, 0x000ca08df0ad2e70, 0x0003a3b592af2a8c, 0x000040a4a94b9f52 }}, {{ 0x000519834b80ba88, 0x00058477d930cfc2, 0x000114564ea90584, 0x000e06fe14c262ad, 0x0000425017607c82 }, { 0x0004968949e7bfda, 0x000414cd105f961c, 0x000511a5410a9516, 0x000e2177ca5415da, 0x0000759aabd156a0 }}, {{ 0x0008eb87587c0983, 0x0000e26cecdaa7af, 0x000d12279d229b41, 0x0007b3ec4fc8c7e0, 0x000092acdf0c79b8 }, { 0x0009f00adefde818, 0x000ea12c00674527, 0x000e01ab878d0446, 0x0005ac2f43f6f69e, 0x0000c28cfb3ac1f1 }}, {{ 0x000aae38b1dc4f8d, 0x0004e7181236c972, 0x000b14323f6d85c1, 0x00094867274f7685, 0x0000efff992ec9c7 }, { 0x0002818fa5d10725, 0x000bd22f6dd9d1bb, 0x0007a909d4e14581, 0x00027b9aa5769544, 0x00000f6612b6817a }}, {{ 0x000cf60f96d10e48, 0x00095daf176f2c08, 0x0004556116c14d5c, 0x00025e7fb01ca460, 0x00006c4e588656b4 }, { 0x0007fb754d3440e4, 0x000851cc9071c4aa, 0x00038c48b2b6677b, 0x0005b2981fd58874, 0x0000cc23558b384c }}, {{ 0x000a3165c2d1e96e, 0x000ce5cd51805e1f, 0x0008b86876e5f775, 0x000018700ab4ccd3, 0x00005515bbda4876 }, { 0x00052c258fdcb035, 0x0005654e160e552a, 0x0009eaedab8f23ae, 0x000ea157adc4972b, 0x000066592aa69e2f }}, {{ 0x000ffedd92412715, 0x0008af4c1e99d816, 0x000633c73a2eb72e, 0x0006556a708e1a7d, 0x00002684c134b0e3 }, { 0x0009bf250d515cb9, 0x000a0d2d629d2080, 0x00052ad12e01390d, 0x000f3a089a9d141d, 0x0000fb8a94900ae6 }}, {{ 0x0005d66a6d649943, 0x00090b1b38227904, 0x00004de22caebda1, 0x0005eb7626c5926c, 0x0000f67f61d51111 }, { 0x0009445c606af316, 0x000c063987d2792d, 0x000c656ec0cad92f, 0x00039a3e64a73caa, 0x0000e4821ae46138 }}, {{ 0x000981afc00085d1, 0x000d0d5af71013f7, 0x0004926c19866a71, 0x000ed9fa0e68216e, 0x00008c7bcfc44bd1 }, { 0x0005694612f9623f, 0x0002b679449f0e1f, 0x000d14dea79b08e7, 0x0009c8b2286cfc4b, 0x00000d346cc223b8 }}, {{ 0x00096cf17200d729, 0x0008e23901515ea5, 0x00051b2ffec6cf8c, 0x000c727594c6c77a, 0x0000320acc1aeeaa }, { 0x000269e868e20629, 0x0002afa6530ae7aa, 0x000d6528bf3d9e09, 0x000d558c90f5e631, 0x0000229c5edcbc0d }}, {{ 0x0004cc22b4444cf0, 0x00009e12cb7191e8, 0x000860e46bf2a7c8, 0x000e63bb978ea1bd, 0x0000d8fbe677e701 }, { 0x00039a0269232967, 0x00082e9d49d5bf18, 0x0005956e7b3add6f, 0x000cd7c57cd4ec1c, 0x000020dc2c6c5c8b }}, {{ 0x00021474c07616b6, 0x0003562c6d8607f9, 0x0004d89521244fd3, 0x0009dcd17759689f, 0x00003d544887a945 }, { 0x000f77453607db96, 0x0007d5b2a354c8c4, 0x000231b85f7fc2e2, 0x0005589e8d51e52d, 0x000081a4d861604b }}, {{ 0x0001287ee355832e, 0x000a8715bde48f8d, 0x000250613d9a672a, 0x00086c08ac970387, 0x0000dae19fd8bb71 }, { 0x0005fdcbcf36d30f, 0x0007974db1dbf1fd, 0x000ac30ebd07464c, 0x000637413ea46588, 0x00007cc18fa7cb4d }}, {{ 0x0000a61162698c8d, 0x000e043810d5ab00, 0x00090431d46a2727, 0x000a6ef336739d8f, 0x0000a26b0295f5a3 }, { 0x0005c0032a22784c, 0x000f53b379f0a1ff, 0x0004f422a86b7376, 0x000e6cd9cfe12660, 0x00003c940fd45b0c }}, {{ 0x00089fa086f4a3d4, 0x000903037577dd85, 0x0003d1265e0202f1, 0x00019ed3283b82af, 0x00002538201d9fd9 }, { 0x00032bd123d0e234, 0x0006138b13799dff, 0x0000df69ff10325c, 0x000bba8ca85fa8b2, 0x000057bcce5a1bec }}, {{ 0x000774df733efabd, 0x000cba7858b044cc, 0x00019335042416f4, 0x000dd98591f0d69c, 0x000024cd837a5001 }, { 0x000d42a35cffec65, 0x00084f6d3bd2e1c7, 0x00002b1b5b735de0, 0x00000a4c4eb30da2, 0x000019e181b75ed4 }}, {{ 0x0008561eaab750ec, 0x000fd959890272db, 0x0009861b1b6617ec, 0x000313bb875f3432, 0x0000725d0e14f52b }, { 0x000a16eb56377ba8, 0x000efa08332aafd7, 0x0004f969b00c6f26, 0x000e75b6f9b0d8bb, 0x0000fe905ed9a6d4 }}, {{ 0x0005c59502191a75, 0x00080f678e62ddc9, 0x00037237e0292642, 0x0002906be2267c45, 0x000076e18afb6945 }, { 0x000b67703ed66163, 0x000fc85f2b254d9a, 0x000c814dbb101610, 0x000e0fcb5844b617, 0x000051187f47b6f8 }}, {{ 0x000df6ef65292f82, 0x000ccc13cf482834, 0x00054e9380f92393, 0x0004dcd84b09daa2, 0x000002ad22636b32 }, { 0x0004d671be580fab, 0x0005c63aa21ba469, 0x00080dbd873d895b, 0x00010ffbfc6b1d17, 0x000037d32eef447d }}, {{ 0x0008511a63429641, 0x00057cf4f5792fac, 0x000648d037fe39e7, 0x0002f65d47c5e0d6, 0x0000b0155eccce65 }, { 0x0003bd08cf6b4388, 0x000da1ca5a60d998, 0x00084ba13ffba0d2, 0x0009a6608f7fbab8, 0x00000b92a4ebd38c }}, {{ 0x0009badc329d1f15, 0x000798a2ac13e274, 0x000f04f6cdc35ac5, 0x000fff5624494f6d, 0x0000234123bdb8fa }, { 0x0003d01cf2e4388b, 0x0001a41004f7571b, 0x00002b4c77fb6c86, 0x000ef3131bac67d1, 0x00001a55a5e1aed2 }}, {{ 0x000dc88b3456a9ee, 0x0008d1b55fd0b8ba, 0x00035123a63efb0d, 0x0006484b7a099d18, 0x000092c90c828310 }, { 0x0005f1462aa51ab5, 0x0006c6af989d9051, 0x000013c446d68fcd, 0x000caa593c2e68d2, 0x00006aa1218b67ca }}, {{ 0x0000bd29c9340da1, 0x0003275ea3d62f2e, 0x0002210b6db3e508, 0x0006d85f6a17765a, 0x00006dc8a9e841b0 }, { 0x000bb9f1ed8d6637, 0x000606d08d84858f, 0x00046e14e3d3d3f9, 0x000cec356370dfe8, 0x0000614d73954f19 }}, {{ 0x000e324aa43d7d34, 0x000b853060dd7ef1, 0x000d50332ed5585a, 0x000234e35eef2dac, 0x0000e1739c044fa5 }, { 0x000d402c7e387317, 0x0006771e6e676710, 0x0000b212ce791c9b, 0x000c9af2abccd519, 0x0000dc23b3bd97e9 }}, {{ 0x000480be272bb944, 0x0007c39306a5a3b6, 0x000d31f77bf47852, 0x0009a89d44e0a41f, 0x00005f69215972d6 }, { 0x000a8f43e1bf1716, 0x000481d2285f3821, 0x000fd17c18552f1f, 0x000f83782188d8d8, 0x00007bd976ec665f }}, {{ 0x00075ffd7e18ac01, 0x000216d77aefb3a4, 0x000dd712c4d568bc, 0x000ad4cf1f69a751, 0x0000e55f50391cd0 }, { 0x000dd2e229415715, 0x000adb13844e95c1, 0x0007bf400d6b744b, 0x000af280085caf64, 0x00003a42515d76af }}, {{ 0x0000db2ffa6b60c9, 0x000179d73d172440, 0x00068eeb23f6cd90, 0x000c0191c3ede774, 0x0000e518c9f2fb70 }, { 0x00079a440a790688, 0x000a43930cfd9057, 0x00042e26ce9b9861, 0x0008576954934d07, 0x000024bf5ca7badd }}, {{ 0x000b28c70e222015, 0x000dd1897d6fbdcf, 0x0006e54ea39dea03, 0x000f2d3dbd3a5cd8, 0x00009af5dacd64b4 }, { 0x00051b3088c8cb5e, 0x0006928b61301a0c, 0x00080e5712cc3715, 0x000c4a0dca628216, 0x00007183a4f877ad }}, {{ 0x00033f48d51a3fa9, 0x0006b7c3902dda59, 0x00066b2a2adf8b68, 0x000179c7e35d2f70, 0x0000efe1c34ffaa8 }, { 0x00032c6af415357b, 0x00034884912beb26, 0x0005b30274a0ae30, 0x000fd784b7f5a4de, 0x000068784fca87f6 }}, {{ 0x000f4a94d8f05720, 0x000d2e3753e43a97, 0x0006a58a4d66687d, 0x00096c6a670e1d21, 0x00003923588250bf }, { 0x000b64615e973715, 0x000f5968d4faa6a0, 0x0002a502553213a1, 0x0007fc6fdd9ed0b3, 0x00008fdecf871ce1 }}, {{ 0x000e553fc34528cf, 0x0005148cfb9fad53, 0x000ce5b636f9dd65, 0x000b208bcbeaa386, 0x000021343a11054b }, { 0x00047831ec12559a, 0x000419b9d5f97505, 0x000a7e142922e027, 0x000f2299b3e85c52, 0x000013d6e4fdc33f }}, {{ 0x000101b9ab1418b8, 0x000ea274a82f424f, 0x00078d463ef2df0e, 0x000ae812c36919c7, 0x0000a9078f376e2f }, { 0x000e6b4528b15e10, 0x0008e9c1c5009d2d, 0x0002be663e1d0b7e, 0x0007067c7fb55ea1, 0x000065c8a8ad08f2 }}, {{ 0x0005e18cc10dacdb, 0x000c8339bb26f5f6, 0x000d9e6bf8f50349, 0x0006ca3541e85db8, 0x0000696b34c84786 }, { 0x0008da3ee5c6c70a, 0x0004550a471fe6ea, 0x0009863904b6dcc5, 0x00040278bf031747, 0x00002271b171d4f9 }}, {{ 0x0000398ec951344f, 0x000641c558216b17, 0x000bbf4057f8b421, 0x0005a9e3c90c7810, 0x0000ef7c615f84ad }, { 0x000d37bb5223d947, 0x000fd9ef701b2350, 0x0003de5d38438590, 0x000f22d310ceecdb, 0x0000b63f014f16ac }}, {{ 0x0007f5e17c602df8, 0x0001538b880d2dd4, 0x000b1d9d2bdaa4e3, 0x000343df5a60f177, 0x00003595db60eb93 }, { 0x00042647efbb60cc, 0x0007f57db394af4c, 0x000cac10af9a0c05, 0x000c6e87239ba215, 0x0000a63e0d4e1e73 }}, {{ 0x00049c0c51c25079, 0x000fc4564488f1d6, 0x000890337983826b, 0x000946663aa92270, 0x00003ecfce6e8391 }, { 0x0006ae337281abf8, 0x000de4e3cffcb6c1, 0x000e3a48ea23ea44, 0x000159ca0e3bf93f, 0x0000c6e00209e63b }}, {{ 0x000bda54e9b5f5de, 0x0003cdf5ca48f3fb, 0x00062650469b09ca, 0x00013c04a64352f0, 0x0000a9c900d6b80b }, { 0x00034c2438695df8, 0x00045f56f6e55fbe, 0x00033ccb4b4fad0c, 0x00059bdff1ca44a2, 0x0000d8197cd15076 }}, {{ 0x0006b3a610c31e52, 0x0006975861421033, 0x000ae881563cbbe1, 0x000a35f226704ba1, 0x0000fa0894f27e4d }, { 0x0009ee25bb322589, 0x00037a775a0d0508, 0x0006b2f5187779d7, 0x000d880be066f919, 0x00000c76c7c238f7 }}, {{ 0x0003422f090ad74e, 0x0009022fd29dc766, 0x0008d3af43571f67, 0x00073f3267fd32ed, 0x0000d0b442ee5f1d }, { 0x000b361400cf8a31, 0x000f3f40807e199e, 0x00003777308f86a0, 0x0002880b4fe9ce5d, 0x00000da749380f3e }}, {{ 0x0003eea570082bb1, 0x00099052680813be, 0x000c722c6366b500, 0x000f4a458527aa55, 0x00005bce35af9e9e }, { 0x0003afeb82f8170f, 0x0002917a0ff58b3a, 0x000476b9faa4836e, 0x00052a6d6b67d3f6, 0x00006f5fdddf36b0 }}, {{ 0x0009432bf6f80693, 0x000ae6d3e5548920, 0x000d39cafe4e671d, 0x0002c0fa08413b53, 0x0000a88888d1f798 }, { 0x000b84f7978aae7d, 0x000d3c6daf0ecc11, 0x0005404428b0ca79, 0x000d2960749ebce5, 0x00002f4edff10ec9 }}, {{ 0x000b1771c2c13be7, 0x0001d818d1d7a0dc, 0x00026f583393b81d, 0x000627635d9fabe0, 0x0000399a341196f9 }, { 0x00046124aa70c355, 0x000f2cae9a6312bd, 0x000f80ccb41ae366, 0x000b5f216a34b355, 0x00003e9a5b7e359c }}, {{ 0x000bc3dd47503d26, 0x0001d5d68afe8b4d, 0x000f9049b15a067a, 0x000db429827f2053, 0x0000558730c6cd22 }, { 0x0007e4665dbf09b3, 0x000e542c03b0c057, 0x0003013d5638d610, 0x000167b0a8b1b3bb, 0x0000b3ec98ffe86c }}, {{ 0x000ac7168a05d60b, 0x00002fcd23e39845, 0x000c910a2bac02e1, 0x0003b40a7ab86e8b, 0x00007c554cfc6e51 }, { 0x0003931577b8f581, 0x00022840139d9af1, 0x000862d13578d007, 0x000e1ce4a72733f8, 0x0000f2968562b2ac }}, {{ 0x0001f568c4e93444, 0x00095eb70f8d5a4d, 0x000705c64963ec81, 0x000e7c732375adde, 0x00006e492766c122 }, { 0x0003224c6ff30b48, 0x000b4835459df02e, 0x000a2cab4e0e2287, 0x0003bf30a2beac0f, 0x0000b7c08ff94828 }}, {{ 0x0002d191d34652ff, 0x000d10ee87edf5b7, 0x0001ae15eb2221b8, 0x000efd2b230385f0, 0x00004abd2d05ed06 }, { 0x000564f3ba13cfbd, 0x0001dca0917d9e55, 0x0008ca2af9c50195, 0x000eb7b96394eab5, 0x000048607473d36b }}, {{ 0x0003da3500cac108, 0x0001505d73654ef8, 0x00038ffd58742011, 0x000886ba068d1a9c, 0x00002aa8c6ea07a2 }, { 0x0008af07c42cfaab, 0x00051a468ae01189, 0x0009377e98a53d43, 0x000b0d802a1b9a4c, 0x0000f99f7b9d03be }}, {{ 0x000dd2d01e319688, 0x000eb26995f0f9ff, 0x000f73e2bba85402, 0x000cbd22b467fadd, 0x0000ea7ba8013c8b }, { 0x0005ee2fa76c4cbc, 0x000f228c693f9fa1, 0x00091ea149f1bfeb, 0x0001539834862232, 0x000070ee1dffe6b5 }}, {{ 0x00052e2214ff073f, 0x00089455777e1891, 0x000030410614a29e, 0x0006eecd5cc10bee, 0x0000bd74b27941db }, { 0x000b6dff74a64cd2, 0x0003c727cb23c74a, 0x000ffd9e676af10e, 0x000132a53fd5d766, 0x000022b0948b387c }}, {{ 0x00015648065531e4, 0x00083816f4cbe9d9, 0x0008d90103d196a3, 0x000769dfa0ed8b24, 0x000076059de2f82c }, { 0x000b69dcba54041f, 0x0000c085b8628093, 0x00011a1bb0c183bd, 0x00005ca2a1facd1f, 0x0000198f2db6c25b }}, {{ 0x0002cf1f8a6fd4d2, 0x000bc9f967365efa, 0x00024532d63e9c0d, 0x000ae632f57300eb, 0x00004160be5ee065 }, { 0x00025c377f9c4ca1, 0x000fa744dcc40cc3, 0x00057b48ec7bdfbf, 0x0004d2b4dfee38c4, 0x0000461e8ab76c74 }}, {{ 0x000377f264a991d9, 0x0007fce476cc9ff0, 0x000cc35cd8ff3792, 0x000e04f9b580e0b6, 0x00003f7b7baf52e6 }, { 0x0008e50f30877c3e, 0x000156288e591a5c, 0x000cac3ebafa9eec, 0x000630733a453a7b, 0x0000a9492c65a23a }}, {{ 0x00010ee253308b7a, 0x0006b0f6d3549cf8, 0x000f79be840ba3a8, 0x0008682b46f33696, 0x0000b318d895599d }, { 0x000485717b66f888, 0x00087e17159bb2cd, 0x000da105c3fffe4c, 0x000a76272f7dfbeb, 0x0000bfbd7894f96f }}, }, { /* digit=23 (1,2,..,64)*(2^{161})*G */ {{ 0x0005fd5fa205d0f4, 0x0004ee8ee36860ce, 0x000c5b16628b839b, 0x0003f4e13daf04df, 0x00008b3aaf4c153e }, { 0x0004e879df3f3f34, 0x00029941a4e0551e, 0x000d33e8877228e4, 0x0005911236772cfb, 0x00007681b72c03ca }}, {{ 0x000e349a4b31aebd, 0x000f2b0285b94916, 0x0007b017d6137900, 0x0002b0dab01a0be8, 0x00008ac2977211f9 }, { 0x0006974d05362415, 0x000fd464a1c6a163, 0x0005f2a0e55b98f7, 0x000493f71d99e6b6, 0x0000a0e9ca0b6129 }}, {{ 0x000b8f7229523466, 0x000e3a1cfe89d80f, 0x000cdf0d11487037, 0x0009c00d2b42c026, 0x0000172110f51188 }, { 0x0009ff21f71bf171, 0x00008ecd850935b3, 0x000c9c32bfbbecc4, 0x00028143434c1a74, 0x00001cad52349f90 }}, {{ 0x000d9cce837c6d61, 0x0003d148f9290579, 0x0006232b855bab85, 0x0007c64ce7a64ae0, 0x000028043d63ffdc }, { 0x000f181a75f69e00, 0x00059796e93b7c7b, 0x000172a383b1d5d0, 0x0000029a0e1e4709, 0x0000b9ee91160db4 }}, {{ 0x000b670a385747ca, 0x00062658ead09f79, 0x0004fc19c7159df7, 0x000d39cbc1335e1d, 0x00000025ace0a875 }, { 0x000ab38fcace8fb2, 0x0002a8128efbeedb, 0x000bc873171affc4, 0x000fee8630c74e77, 0x00001249e10307e9 }}, {{ 0x000ba8e478b7779e, 0x0004ac85c0a3f1ee, 0x000190dedf06d75f, 0x0006c198dbcad249, 0x0000bec9ca1c42e7 }, { 0x000b123f368231d5, 0x000b7b0eeaede4b8, 0x0007ee649f7fb5a1, 0x0002f72fb0bc498e, 0x00003fa9b3e1cde9 }}, {{ 0x0005c8295bc7ccf1, 0x000ebc7de79dc241, 0x00023fc74071d988, 0x0004b5fdff1168a3, 0x0000a46cc6dd3945 }, { 0x0003a26e3c4f8d24, 0x00086367d8184ffe, 0x000d4ca20d9fa6d4, 0x00057819ec396228, 0x0000217db807076e }}, {{ 0x00026fc9c4cd4abf, 0x000e23f1402b9d0c, 0x00026a0bfe9f0668, 0x000417f6e573441c, 0x000042560b13ff8a }, { 0x0003ef07f65b14ba, 0x00061fd7493cea35, 0x000ec7090c603bd2, 0x00077a68fd05d4b3, 0x00006ce1efdc940f }}, {{ 0x000613ddd45cbe56, 0x000a5d27824fc56a, 0x00076d14b2a2aae7, 0x000062d493467521, 0x00004912a1180184 }, { 0x00016c4168b43a86, 0x0003b9c5450d8660, 0x000c8e186318cb3e, 0x000c25c3946f4409, 0x00002251eb5dbfdc }}, {{ 0x00035d95c1f7dfd4, 0x0004ff0c74359787, 0x0007ad857857c300, 0x0001a9bafb152c88, 0x00002220a65483ec }, { 0x0002c5cc53ddbb41, 0x0003473039553173, 0x0009bd757d41255e, 0x0006c05000b4b02a, 0x00005bb2616a0592 }}, {{ 0x0006f267f3450bcf, 0x0009e1f606241297, 0x0004236bc36ba3a3, 0x000fc5e72b7bc5d6, 0x00006d062e175519 }, { 0x000d792d60b7e583, 0x000e00fb36eed930, 0x00072e7c3aa2aa86, 0x00041b3a055230cd, 0x00005222efcee916 }}, {{ 0x00025b58889424a0, 0x0003bfdd5c7c5d2f, 0x000614cfdba46ef4, 0x00069438ab38f8da, 0x0000c9d7330553e7 }, { 0x00099f94c0e0b82c, 0x00086842946ad608, 0x000d6031dbbdd21d, 0x000b21909854f29a, 0x0000f80169f11b4b }}, {{ 0x000d22a1149324b5, 0x0002751f4a55b03c, 0x000d68c111c13c46, 0x0005dc651261762d, 0x00005612c643fd71 }, { 0x00026455eddae243, 0x000931a247c9569c, 0x00030eee68dcf34d, 0x000c4d3d459a5097, 0x0000bc8501472388 }}, {{ 0x000cd3142c078a4f, 0x000e7e049ce89e7e, 0x0008dfb5f889206a, 0x000b1dba11890853, 0x0000fe4b40447fd0 }, { 0x000af34eb1a2b760, 0x0005f59b3f5ab84e, 0x000807cb5614c7ce, 0x000ecf41f3c320a6, 0x0000376551d686ca }}, {{ 0x000d8eec2b43abc0, 0x0004129977c97c4f, 0x000ac7efcdced8cc, 0x0007704785ff9bee, 0x00003fe869d8f984 }, { 0x0005c75015e7e220, 0x000f94ef027458c3, 0x0008e754910013fb, 0x00084b6f4b4ff531, 0x0000df161344c360 }}, {{ 0x000f63cfc83f45b8, 0x00011d646ac49d20, 0x000b73afaae16770, 0x000dca23842c77c0, 0x0000cf54b1e93428 }, { 0x0004dcfda1adde56, 0x0005a1bc6441f959, 0x000957b146ed74f3, 0x000a15bba7d38f71, 0x000080b43552bdca }}, {{ 0x0004512fad93b7bf, 0x000f4395f6d4a09f, 0x000bfa01887930c4, 0x00063d40a6b4f355, 0x000015dc769eb061 }, { 0x0001dbaca543e3fd, 0x00084d5206c4c74f, 0x0003d97181a31083, 0x000245f2dd021d4d, 0x00004c9b52a51d86 }}, {{ 0x000f5829708831a1, 0x000f226490a1aca3, 0x000c01fa4191db95, 0x00065f158cb64dd9, 0x0000b704509d211a }, { 0x000d54e389cc560a, 0x00066d17c213ba70, 0x0005db4beb4b0a15, 0x000ad2ec1c28febb, 0x00007d2a923ea7f4 }}, {{ 0x00069bcfe21bda90, 0x00044604af206ee4, 0x0006314dacd7546e, 0x00089f02e786c88f, 0x0000fea9761aff90 }, { 0x0009a4ef238392e0, 0x000540d470622302, 0x00079c0fb4897908, 0x0005c65ace743bb5, 0x0000ac57eea586d6 }}, {{ 0x0009fcce8362831a, 0x00014feb483689bc, 0x0005873df3dedda1, 0x00023c1722575d3f, 0x0000658b868344aa }, { 0x000525a7345027f1, 0x00021ff0149362d4, 0x0001d725423d3479, 0x00035076c95e5758, 0x0000632aa6fb7444 }}, {{ 0x000caab33910184d, 0x0003e628f3383609, 0x00028c433ff2d754, 0x00072cdec483ff59, 0x000059db5682d119 }, { 0x0008c75049787047, 0x0008bfd668927090, 0x000cac92ccf7e399, 0x000d9fc942496b4d, 0x00000b039ef1d169 }}, {{ 0x000389359d183e8e, 0x00043c2c905d85f7, 0x000f93aa78bab2ac, 0x0003e4f94e9d7f78, 0x0000cdc97efebfd8 }, { 0x0007303b35c1dcbb, 0x0004eb7367e45f70, 0x0007c44e3fa733aa, 0x000da6d181f20306, 0x0000693cf0cbca05 }}, {{ 0x00016554135f365c, 0x00088e4d13b7ea1a, 0x00043f81ed6cbee8, 0x0003a9370e6489b2, 0x0000a763c3cdfd1f }, { 0x0005fb3cd26c7a98, 0x00026fb7af4194e1, 0x000c788e80c9e8e4, 0x0000ec056533c1c3, 0x0000e7c9daf6851d }}, {{ 0x00014e77a0de8421, 0x000cc45526f09fd2, 0x000c5fd9ac6926fb, 0x000a7dc8de8a4f10, 0x0000d25068992420 }, { 0x000b6cda791fe0f2, 0x0007b7314faa40ec, 0x000b3679170d12a8, 0x000c08f3e767867e, 0x00000e1e221077f7 }}, {{ 0x00083667c4ab99b7, 0x000646d349d51aa0, 0x000edb9151250bb8, 0x00006dfdff56b5a9, 0x0000e96a55350487 }, { 0x00075a324beb86c4, 0x000dd3518087f2fd, 0x000bf9dcb2114ad7, 0x000280589f1b8eaa, 0x0000a4dccd763888 }}, {{ 0x000cc4569fc6534b, 0x000850101dae185d, 0x000abeb63e1cf161, 0x00085800b45434e0, 0x00003dded22e1035 }, { 0x000e50258feb27e0, 0x000518a09a512993, 0x0006746000488c61, 0x000c0779281b4d20, 0x000087a3225e890f }}, {{ 0x0001a7ec6bfaf389, 0x000c3db2996864b3, 0x0008eda07338e1f4, 0x00058e15aa2e6708, 0x0000a57bd6c84a58 }, { 0x000d24ee7c6e4db1, 0x000c666d6bc20da4, 0x000c39512313aed3, 0x000225f634acdb5e, 0x000017899b25ac05 }}, {{ 0x0000ef95acc5b65a, 0x00091d3a19fd8680, 0x000cda9e478efabc, 0x000ae7e52612e481, 0x00005879a89ba754 }, { 0x000ff9d98e9d1fb0, 0x00022edaa0a6c469, 0x0005a37d6e017817, 0x000202a106129408, 0x00008051d4fc5997 }}, {{ 0x000a9868340ef12b, 0x000847c468b8835a, 0x000ac8766672f855, 0x000de1f81977a31c, 0x0000ae09622e4cb3 }, { 0x0004b60159822469, 0x00032f3a6bd9d340, 0x000b2f0fd6fae8ce, 0x000eed25e6a62fe9, 0x0000a1ce552aab34 }}, {{ 0x0005f9ee8b1f3b1b, 0x0007bdf5579bea49, 0x0007c6f4ec662d97, 0x00081aab110e35ac, 0x0000838e05f272c4 }, { 0x0008c93722dc320b, 0x0004eee82b6eb0fd, 0x0004bcf973ba5062, 0x000f5f1fe2e84576, 0x0000987ab3588bf6 }}, {{ 0x0007afbfe9bfa97c, 0x000db48f83e8a3b0, 0x00068574d6094e13, 0x0009ff29ba579aa9, 0x0000ac0b5352b6ee }, { 0x0008e78e9f640109, 0x000d36d5b7bd2931, 0x000f573aa39dd6c0, 0x0000935763b592cf, 0x00006b052765f938 }}, {{ 0x0000cd9c328d84f2, 0x000ec10296c36eff, 0x000191f73e449397, 0x000f344da7ee8967, 0x00003d52cf283e17 }, { 0x000adab3ad961303, 0x000c8f7e455fe908, 0x000af39881456bea, 0x0006ae1ec3fb53cb, 0x00007d83567df6b8 }}, {{ 0x000d359f6fd4efcb, 0x000232f53d648293, 0x0007652ba9bb3daf, 0x000db7f2c7a471e1, 0x00009d7cb3d94a0f }, { 0x0006782372900602, 0x00065860aacd6975, 0x00031f4ad535a466, 0x00057f24e92b444c, 0x0000a4012d7fa548 }}, {{ 0x00018c74a1ce7f88, 0x00008f2bbbab3b85, 0x000e39780cc99267, 0x000135cd24851f8a, 0x00000d44135a09ce }, { 0x0003ccc547f7ecdc, 0x000d90af9877d4ca, 0x0000054d05740761, 0x00071d6b614578d9, 0x00002bd6390f7cb4 }}, {{ 0x0007167876861ca8, 0x0004c8e327f83495, 0x00069d263dca7c3f, 0x000f26885f3e9734, 0x0000cc0b31df68c9 }, { 0x00011b5e5c6b6cf5, 0x0001fb9411925a6b, 0x0007eff6df88f06c, 0x000be215d7c078d4, 0x000083a8bd8ed8ac }}, {{ 0x000abc1295834d88, 0x0001f6c1eea7b85f, 0x00009818e5c95ff1, 0x000938dbb2352b46, 0x0000387993489f2c }, { 0x000c5e12df15edd0, 0x000fdc05233f9251, 0x000bcb21d976697d, 0x0007be659e0a802d, 0x000053b74438966a }}, {{ 0x000b70d5488e28d0, 0x00088c64b8457ee6, 0x0008e40dd4aef873, 0x00037e38fa5360f6, 0x00007f082ebb5766 }, { 0x0006f388f3012c36, 0x00001f13bfae3154, 0x000284ec6a763ea6, 0x00088e0f93379785, 0x0000205217d30224 }}, {{ 0x00034f30d0a7f21e, 0x000285889d8ddbbc, 0x000dada45e17bd7a, 0x0001ff4b08830b26, 0x00008227c3ea8c36 }, { 0x0009e76d098d7344, 0x000eda356ab64b81, 0x000cbfb4f01d1e3d, 0x00024d9947f77f0c, 0x000077da11412e32 }}, {{ 0x000ecd83bcdac8cc, 0x000bec396238f398, 0x000e19632faa0ca3, 0x00085e899c0a482b, 0x00002203b4334230 }, { 0x000b32d5095835f0, 0x0003cb7a2f3776f8, 0x00046985b5d63ee5, 0x000e9b446b42176a, 0x0000db866498ec65 }}, {{ 0x00097128795b26d4, 0x000007d53b618c0e, 0x000b80b150a9c145, 0x0006c0564c424f46, 0x00006ae4b9ab6582 }, { 0x0000d841a1380e4e, 0x0005832f815561dd, 0x000502e81430573a, 0x000171a4f85f48ff, 0x000063896020863d }}, {{ 0x00042ad522e18a65, 0x00044260b9267c6a, 0x00012add234060bb, 0x000833924c78913f, 0x000039e7e3dc6b6b }, { 0x000136fd8d64e5e2, 0x0003549a2c989d55, 0x000f90beea015851, 0x00038c4da928292d, 0x0000b65cea1cb0a5 }}, {{ 0x0005f43682904822, 0x00022b1f2c34a996, 0x000459641f29f5c4, 0x0006715be3b00aca, 0x00008ad64a961e6a }, { 0x0000473f5f609763, 0x000f501a11b12e13, 0x000cb1c79515bd02, 0x000aa7dd578a7ab2, 0x0000493e312a1f39 }}, {{ 0x000c13966b2406fb, 0x000e59d169c7d97d, 0x0003f39b6362b933, 0x0009d4d035cd5baa, 0x000048a4caa8a041 }, { 0x000310fa4ebd46a4, 0x00087e82b8357c1f, 0x0004f6c481db4a34, 0x000b8923e0cb1b4c, 0x00003d448294e348 }}, {{ 0x000fb357b1ee936f, 0x0004452f97f68c6f, 0x000f0b4f77a6ed24, 0x0008c27d90c773b4, 0x0000c6d90e5f6f4d }, { 0x000ae575c3e40e20, 0x00004cde0f28039c, 0x00097bbe8620d5bb, 0x00038bb6c0b36c95, 0x0000c238d358e07a }}, {{ 0x00073da0ba4fff56, 0x000bd02a70dab865, 0x00091a87ec422f67, 0x000e17592fcbd12a, 0x00003dc4b150156e }, { 0x00022cb8d1d292ad, 0x0004ffe0d41d5505, 0x0002cf29172c74c0, 0x000c83548e7eec0e, 0x00001f902993f981 }}, {{ 0x0009a38d4ab89a62, 0x000342a70cbb96cb, 0x000a032d975e6da2, 0x00090838de034362, 0x000051f017afdd83 }, { 0x000aebcb837a69e7, 0x00043821ff140fd2, 0x000ff5c31c5d3793, 0x000bb3249bd162f2, 0x0000c09d95c15150 }}, {{ 0x000f921c720023d1, 0x000e15f937b05271, 0x0007cbeb7d25606a, 0x000816929f42e1e4, 0x0000a8cc384e52b8 }, { 0x0006ea82172f000f, 0x0008f7b5b26bbd51, 0x000d247724699de2, 0x0001f0d7e7a8ef5e, 0x0000f1fe050d2c8b }}, {{ 0x000f7199dc46d818, 0x000722b599ff0f94, 0x00073193628eba9f, 0x0009137f368a923d, 0x0000ee5360c30393 }, { 0x0004f710bd7921fc, 0x00093f6e46f2a79c, 0x000d25010260474b, 0x00092d27c08b5dea, 0x0000fab67c859c32 }}, {{ 0x00064519deca0cdb, 0x000d55778bde41ac, 0x000fedd3517b736a, 0x000b97c416474bf7, 0x00003208530088be }, { 0x000025813a05a641, 0x000f7460edfcc4f9, 0x0006b8cc2931d960, 0x000ea5e77319aa73, 0x000029012049c8c4 }}, {{ 0x000de5048b827884, 0x0004fcac0c227196, 0x00045be510935647, 0x00029229cc60209e, 0x00001a8f07ca2a57 }, { 0x000130388eeb5d29, 0x0000fd8e115ac04c, 0x000f5b3ade432bbc, 0x000316be77df7093, 0x000022d0dba6d494 }}, {{ 0x00039aaf90e9d532, 0x0008c8477f54e6e0, 0x0002623b60542e7b, 0x000bc14d69f258a7, 0x00009ce5ba732f82 }, { 0x0000931ba5ed41d1, 0x000a9739460342f0, 0x000c3ee643e44bb0, 0x0003fd87e4703148, 0x00003a0863fbd5a9 }}, {{ 0x00004525097c5017, 0x0005a9d786f337c0, 0x0002e6bf14745166, 0x0000c18efd9c01cd, 0x00002c8b553116d9 }, { 0x0000641053c931ba, 0x000c64784db8e765, 0x000a436499b28b73, 0x0005fda223bacf1a, 0x0000938a983f292e }}, {{ 0x0007bde5834630c1, 0x00077749f7144aea, 0x000e9c16c77a33ff, 0x000ad12ef170c963, 0x00002afc875cc612 }, { 0x0007882dab2f3b77, 0x000638b6fa687508, 0x0001cfa5d49dd82e, 0x000de3631fa64e53, 0x000078a45e28f1f6 }}, {{ 0x0009c5714d71771f, 0x00098316c67a7751, 0x000ad6005f642df7, 0x00040e7b2cb10471, 0x0000cc0be522bf70 }, { 0x000bc82ce45c7f2a, 0x000617bed03fd3f8, 0x000ea5f3ec6a645d, 0x000e3f6b5dd03344, 0x00007777234fc32f }}, {{ 0x00081d837a740b62, 0x000d301b35f1341b, 0x000c6d86bac884d5, 0x000a3565ce53156d, 0x00002f8f9bd103d9 }, { 0x000c596b31a8eb5d, 0x000f76e2e4358674, 0x00049f4c722e721f, 0x000256e9d9020eb9, 0x000000946b032fd9 }}, {{ 0x0004828817b2b97d, 0x0002c0f0e0b040d2, 0x0002217d0167ff6f, 0x00040e422baf02d8, 0x00006eb8e36ece4e }, { 0x0001f86203c5e993, 0x0008a31113ec3567, 0x000da3f78ff4f368, 0x000ea84159e48861, 0x0000bb7e93050f1a }}, {{ 0x000560b0e9aafe66, 0x00042da3fd19408b, 0x000b722cecb04b0f, 0x000c6b6904aa716d, 0x0000052ee2e70dfd }, { 0x00015ca19443e93c, 0x0008d92fa34bdad6, 0x00043b7857295ea6, 0x000c094d3f024fa1, 0x0000ea3f81cb62df }}, {{ 0x000d3a74d028189e, 0x000aa3d6f73c51e3, 0x0002acd34e0d4511, 0x000a079ffa4cb241, 0x00006e3b446570f6 }, { 0x0008027c148bf575, 0x000240f4a7a92024, 0x00095faee0289dbe, 0x000ea1d08a9bccf5, 0x00003daa96c5c819 }}, {{ 0x00079738d8eab83c, 0x000fb7c40b557f08, 0x000645d10d87e8cc, 0x0005ffe27e001c36, 0x0000017e39f092f7 }, { 0x000943d1b495d0bb, 0x0000c4bbda948826, 0x00083d40e0e510b7, 0x0006a7c24d1bbcc4, 0x0000acdbfbfa5df0 }}, {{ 0x000bf3dd51c8d19c, 0x00007bb098cafb4c, 0x000f94e0af5e1773, 0x000601c4d27ed230, 0x0000285109152371 }, { 0x00024c7557bb1196, 0x000891641b1d830b, 0x000d18bfa8cf69f1, 0x0009cdfdba7ec851, 0x000077b4e1b088fa }}, {{ 0x00040f8ac3df8d0b, 0x00006dc1d4636c38, 0x0005e40b0e75786b, 0x000f4a2b3f843652, 0x0000977ae94715bc }, { 0x000123d8f150f27a, 0x0001e11f4387f1af, 0x0002c3f18f8f2228, 0x000f40e677c501cd, 0x0000110598eb168e }}, {{ 0x000796ff08cfa1b0, 0x0005e71d607039eb, 0x000515a3463d5019, 0x0009090912b70e21, 0x0000a34adda11483 }, { 0x00038e8cdf8fccad, 0x000cd863c57c4aa3, 0x000f84360d47a30b, 0x0009660982aed9ca, 0x000082fbf17ecca1 }}, {{ 0x0005213908309c96, 0x000cb8266cde8dbf, 0x000f3851c42e5054, 0x000d1ba724e15997, 0x0000c913344e336a }, { 0x000a1c0c559056b7, 0x000681d8ce4396ea, 0x000ffdd114ecbcec, 0x000c3f86b37a1a67, 0x0000bba57201413f }}, {{ 0x000e3d7a82a07312, 0x000248b4ed80940f, 0x00057c32545a8fa1, 0x00024459f67e6d05, 0x0000781e5623c72a }, { 0x0009422f1dd9d9ed, 0x00045027e096ae27, 0x0006ab7164488446, 0x00002f2fcb1f3e1e, 0x0000a08771e4d556 }}, }, { /* digit=24 (1,2,..,64)*(2^{168})*G */ {{ 0x000b1adfbccd5f72, 0x000bafb9db3b3818, 0x000e49c42a8e58da, 0x000a5741f9c3a2de, 0x0000e1b4d1992caf }, { 0x000d2ae779d25bd8, 0x00001397e053a1bd, 0x000689b00f8d9c66, 0x000aeefabee2be5c, 0x0000ed75eb0e9aae }}, {{ 0x00070ef12df3aecb, 0x0000e7a205b9d8b0, 0x0003fe5865a61087, 0x00049560e6eb8f06, 0x000018c288645dc3 }, { 0x000c1f205200dec5, 0x000d0053bcc876ae, 0x0007bb212c914ca5, 0x000c3165e12a7533, 0x0000fee6eaee8fb7 }}, {{ 0x000b625175d3e131, 0x000ba79b6828f364, 0x0007b65b0a28d9d9, 0x000a31a0c9d7a025, 0x00003f761efd974a }, { 0x000cea06f50c8e7a, 0x00025dd9669b6210, 0x0006ea0e74a30782, 0x0007f7cbc88a2ca5, 0x0000eefdd32a930a }}, {{ 0x0006927bdc72fcef, 0x00092b5c4e83d33c, 0x0008986accaed0f0, 0x000ee5e0fd9f3587, 0x00006fc2b4d5332a }, { 0x000bd4c284a559fb, 0x00092f79f9e0f036, 0x000e91031f24a068, 0x000494df12868661, 0x000064b67a214c5a }}, {{ 0x00038062d4c1e75b, 0x0004591289a8619a, 0x000fc2f14e9e6431, 0x000a96b32ef796e5, 0x0000cf84b53f10ce }, { 0x000e2d93f2a93799, 0x000b1200573274eb, 0x0003eaf97fa1c33c, 0x000a47520d07b67e, 0x000099241c28bfc2 }}, {{ 0x000e16a8fa9459c5, 0x00069533f36d1411, 0x00042fe5fb485de4, 0x000223d3ae84bb3d, 0x0000362e47c092d7 }, { 0x00051ac53cf453e0, 0x00072adddd472e03, 0x0006d8041bea2700, 0x0004e95997d405ee, 0x000072103589e10b }}, {{ 0x000c45b260b78e4a, 0x000cab84444896b8, 0x000f6cfa759ac76b, 0x000f5fe7d64974d2, 0x0000fc1b25688826 }, { 0x00018f2e67924f42, 0x00079c2d84634875, 0x0006ee2d190516ad, 0x000a501c0d1b2b3f, 0x0000036290195036 }}, {{ 0x000578dc4ce14fbe, 0x000b08c06d75fc1f, 0x00063cd0cc5274b3, 0x000f629dd2dcf7bb, 0x0000f36db3fef100 }, { 0x000304c0d907ee38, 0x0005103df2ce7a06, 0x00083934eed34414, 0x00075ccabaee3628, 0x0000f1816df3580c }}, {{ 0x00082f4b52e4cec2, 0x0001aa2a91f6791e, 0x000fb37b53a9c983, 0x000cdb8c12abe418, 0x00008cd67259a170 }, { 0x0009b47fddf3ac31, 0x000ff274073e81c2, 0x000cd201171eb3c4, 0x000d8c60cc0276fa, 0x0000bde77950ebb2 }}, {{ 0x000db1d445e12d1b, 0x000c603459b19402, 0x00092d4f6a4d5460, 0x000260fd3ec881c5, 0x00002404d2934d68 }, { 0x0000c0e5d7b17ee8, 0x0007387df239fd84, 0x0004d45c3f1714c5, 0x000bd7a59c718af7, 0x0000cf1f5fc6cd42 }}, {{ 0x0007e104334dd14b, 0x00045f4721b33f2e, 0x000b16fe00b71c74, 0x00074a4e72124f1f, 0x00000c5ed583ab49 }, { 0x000b6a0a0c1b3b39, 0x000698ee4d0c7e6c, 0x0009bbbb310fa8c1, 0x00008ad43847e339, 0x0000d0eb2a823c1c }}, {{ 0x000c83d2104da3af, 0x00087c327d02dccc, 0x0001ade4eab2adc4, 0x000bae22d5ad0098, 0x00000d9c44913bb2 }, { 0x0005934268273a75, 0x00009c1666fba0ca, 0x00066ee203cd0f18, 0x0003334c26994819, 0x00001a7e83e4402e }}, {{ 0x0001240501d5f60c, 0x00008eda714181da, 0x000abf43ae40161c, 0x0004fd31f609ac13, 0x00006d341d5395cf }, { 0x0002c2adc36656d7, 0x00035231409ca976, 0x0007bda0de8008a3, 0x000a46fcd254cc1a, 0x0000ead8778cec76 }}, {{ 0x00082b49f9e98b30, 0x0006df056e464833, 0x00002b48195cdcf0, 0x000c68c52a55abb2, 0x0000455cf3a69edb }, { 0x0004c589d9fde490, 0x00091ad4dff8d47e, 0x00045eb86afca0dd, 0x00060d50979caf61, 0x0000ed7832e28abd }}, {{ 0x000716dd735d4299, 0x0000fab3fd40e095, 0x000e201a6135ca74, 0x00012ff8be455842, 0x00006f917d8d6ec2 }, { 0x0007e76496178dbd, 0x00054e54e8bf3de2, 0x0005f39e59a54bae, 0x000840fa69a0e77b, 0x0000a545f75f92f1 }}, {{ 0x00065ca49bf70465, 0x0002633070d3aab6, 0x000b33d03149eda8, 0x000f82c732643672, 0x0000dae397b7ff25 }, { 0x0005986e7c2b0613, 0x000c759b3efb9983, 0x000ccf96a4c52f87, 0x000f392308a5b922, 0x000053a40c602f11 }}, {{ 0x00060575d954191d, 0x0004e5cff3513cc7, 0x0009bb938203e64a, 0x000d85286bb0cf8b, 0x00009896e7ac48ed }, { 0x00058c95fcf57592, 0x000bc169f7aa1811, 0x000fdf7d571f4181, 0x000cb1291163a3ec, 0x0000a74ad3d22246 }}, {{ 0x000d52e6bccfbd9d, 0x0007e6e13cda46f1, 0x000516dcc813d3db, 0x000adbc707948241, 0x00009aa625122196 }, { 0x000fc7bf7e178d47, 0x0005ae78608dd3d1, 0x000aca3fa6085efe, 0x0004ed3fa4930db2, 0x000095d11cde96d0 }}, {{ 0x000d1764efa19423, 0x00089cdd9eee96cd, 0x000b08758747c9b3, 0x0006ea12a0ca277f, 0x00003fd5bca22445 }, { 0x000cff95c47d1a9d, 0x000dfde7b3ed7397, 0x0008dfea4bfb8703, 0x0000b151250cb745, 0x0000e035718c4eac }}, {{ 0x0003e982abb759a4, 0x000a8bd8088b454e, 0x0006b6b489deac94, 0x000caa3cbdb7f32f, 0x00004686e7f56cb3 }, { 0x000bbf1d3400c329, 0x00098e4c2a2a5938, 0x00047bb4d51b0609, 0x000c26b2372c3686, 0x0000c3163f597394 }}, {{ 0x0009e8e77eb6f0ef, 0x0001a73da50c991b, 0x000ac8448763bb7e, 0x0000c887148afcd5, 0x00001fe304790c6a }, { 0x0005b82406b0e023, 0x000ec4499a7703de, 0x000d7bd612ecce7d, 0x000a058be6972930, 0x000055f6a476b172 }}, {{ 0x000a9e252eded6d3, 0x000b8e3bd3790620, 0x000d23302563dbb4, 0x000be5b37d64b7a1, 0x0000f8d8432196d3 }, { 0x00008e4790ff828a, 0x0000b6bc39d3bcbd, 0x000fe29ce5d2ddc1, 0x000bef0181a31c9f, 0x000059056576275c }}, {{ 0x000e5d55febb0e31, 0x000e9e9255c09801, 0x00010ced1da0ddbc, 0x0003c14a14bd8638, 0x00002df70d0ce263 }, { 0x000e5bf8ecb0386b, 0x000b0068ff5cc292, 0x000ee05cac07c42d, 0x0004c2124026b389, 0x00009cd54793b7a8 }}, {{ 0x000c6360bfa4642b, 0x0005cd0ad886aac2, 0x000a8b0e55855f5d, 0x000dc1aab5c16878, 0x0000ad287ec6b022 }, { 0x000e29d50b1fec3f, 0x0001cb5b9c972a3d, 0x000d9e7098af043d, 0x000bb5ba6c9e6f88, 0x0000ccd2c2291972 }}, {{ 0x000d8f2c9dc84b95, 0x0005f83d309cbe6a, 0x000a332dc0b1d6bf, 0x000348ee35b020d8, 0x0000d07b2b00cfeb }, { 0x000c5bec9951a99c, 0x000921de7400e938, 0x0008c66271b3c77f, 0x0005ce4bffe3e18a, 0x0000fcae372683dc }}, {{ 0x0009779f4565f3cd, 0x000992a74a55d1f0, 0x000efaf7c792c505, 0x000e87a94e3fbf28, 0x00001e0023586f6e }, { 0x000da67cfc184107, 0x000b6afc3d19d8d3, 0x00041a3029e3c052, 0x000ed5b55d5a7509, 0x0000fb679388fd7c }}, {{ 0x0007c48aae979814, 0x000e22a2c160dcd0, 0x000387cc6040b48b, 0x0000e495a34e6c5e, 0x0000ebc559de6b12 }, { 0x0000871f6c9b95e8, 0x000c6da50068527a, 0x00027c0973fe1c51, 0x000e34a4c2c09ef2, 0x0000a42cfbc74a4c }}, {{ 0x0006897ae28b8aa6, 0x0005568d84d835d2, 0x00095f9447042666, 0x0000a52d7c90caf3, 0x00007477e6db63ea }, { 0x0002c7980e3a62d5, 0x000b508a4d6755dd, 0x000b36ca63cc8293, 0x0005c42e8403ee41, 0x000072dad9713001 }}, {{ 0x000f22110209bd6a, 0x000f832d2e11305f, 0x0001f49e696d2947, 0x00057e69d966be49, 0x0000a57523d1fdb1 }, { 0x000e0267ea28eb43, 0x000134aabe30129b, 0x000f756bfce543b4, 0x000213d22c6f2c93, 0x0000707ad02d7862 }}, {{ 0x000a76e9e4386d11, 0x00081f193bc042b7, 0x000437c0da73ea74, 0x000bf3068f085b53, 0x0000015ec7b9d94a }, { 0x0001889c8d4274a0, 0x000e2fab88911b55, 0x0004635272281033, 0x0003323ffc85345e, 0x0000f694aa06193f }}, {{ 0x000043f2c0486dd3, 0x0004069a5e829e5c, 0x000b55c3b7815495, 0x000afb1c1cbb4c6f, 0x0000adfdd639e5db }, { 0x000d515f74e0a7f0, 0x0009f758ea5e1853, 0x00099b2b5e2aa1fb, 0x000e7d6018bda40b, 0x00002841bc77e94c }}, {{ 0x00003172599604ef, 0x000e04fda79e5acb, 0x0009d5feaf05bd45, 0x00080866e68b83b3, 0x00000b424807d53a }, { 0x0005296e9538c34c, 0x000381ac5ccc2c46, 0x000ad873e1d42e72, 0x0005408bd7d7dc96, 0x00006a74e1c17bc4 }}, {{ 0x0001fdfedce79aef, 0x000c3d0bc8fa5bc5, 0x0006fe0e289f0f1a, 0x000059b5d8a5ead6, 0x000023b6e31609f8 }, { 0x000d66af2147f6ba, 0x000890b289fca32e, 0x000eb0352d1e23d2, 0x000f354dee36ff0c, 0x00005f8a7192aa10 }}, {{ 0x00010989c077ae7b, 0x0001b8b5fa9f4d67, 0x000dc699d9268932, 0x000596c722d4066c, 0x000090b03f888845 }, { 0x0004d874f8f53831, 0x000ae35ce40cbd89, 0x000f826ab444e0a6, 0x0006a1d2cab55c5e, 0x0000acd6cecd4b95 }}, {{ 0x0004c0e1b8f9d216, 0x000dae8a518001b4, 0x000658440d56a993, 0x000bb3725ee605eb, 0x00002b0f4a4a14c0 }, { 0x000bf395cc3b7ed0, 0x00054e88b6740dc8, 0x00036229b9409031, 0x00046137289087a5, 0x0000be581ada8fe4 }}, {{ 0x000d51afe901e219, 0x000b0a1deb8568b6, 0x000013a98d491c8f, 0x00016e281a35daea, 0x0000537d475b7d2b }, { 0x000c6865cafe90b4, 0x000f86e51803a198, 0x000ef9b92ab5832d, 0x000de923ce3d24b7, 0x0000b2e4a54bd2e0 }}, {{ 0x000c70ca45125561, 0x0002a7db743f4ef2, 0x000bbb6053892073, 0x0009d8ae83793909, 0x0000dbb97d8fdd1d }, { 0x0000384cb6274347, 0x0005229cb1131b10, 0x0008255041c3b80a, 0x000952d0a7826f29, 0x00004174450b76ca }}, {{ 0x0009570c16f8f650, 0x000c25b3ab480953, 0x0006297944efd26d, 0x0009f08453451c25, 0x00004a96dc9b66ab }, { 0x000ad4b67319678a, 0x00020d3adecf263d, 0x000101a22a8fbe78, 0x0005f1e36f1c3d8d, 0x0000ed9d0a1de53b }}, {{ 0x000d2db93bcd3273, 0x000260ff0d796a03, 0x0008a1e0d1c6f14c, 0x000d98dad5fc6247, 0x00004b1ab345b835 }, { 0x000ea6e007bc5637, 0x0005379d85d5ddc0, 0x00075d099f2d2836, 0x0004877d5e907caa, 0x00002c068a8b32e7 }}, {{ 0x000651f5d8d828b1, 0x0004069d23233f3a, 0x0005d1796da707e5, 0x000781e6c3e32279, 0x0000b55160373545 }, { 0x0008bdd37cafc9ac, 0x00003191a230c767, 0x000254ec8ace2d98, 0x000e2217ebd52727, 0x00005901810eba20 }}, {{ 0x000491ccaacfb314, 0x00002c217cd93fe1, 0x000dc64b1a37f286, 0x0009b2ef865b97a4, 0x0000b59b701c4047 }, { 0x000da2b7ef8c43e7, 0x0009b80231963324, 0x00070ad88faa8816, 0x00098e9ed3c3862d, 0x00000eddebb7b375 }}, {{ 0x000ee5cf3c1ad26f, 0x0003f33b126e48e4, 0x0002a5af12fbde15, 0x000885bdb404a0b3, 0x00001567d76438aa }, { 0x00055c5bfa632ed7, 0x0005cb97df3c8c32, 0x0003920bad02d03c, 0x00016ea6abd905fe, 0x00005ccd15e48747 }}, {{ 0x0004610714435ee0, 0x0007cbfc3dd9b4d7, 0x000f87a583732e37, 0x000fc229bce23edb, 0x0000d1868b201130 }, { 0x000f1bc7d1d5a193, 0x000645f1266bf52e, 0x000129c8d3e49b75, 0x000cd86e30204672, 0x000000c5c9aacd67 }}, {{ 0x000c3fefca460bc8, 0x0005fc17078c4322, 0x000c8b3ffded87cf, 0x0001d3d70e1961b9, 0x00005038a807927c }, { 0x000eb77640143e4f, 0x000bb36c2af389a8, 0x000d2eefa6aabb49, 0x0006c356396c610f, 0x00004a75c050691e }}, {{ 0x0004778ffba62fa6, 0x0007e542a296e775, 0x0002ee0bea399904, 0x000da2131c871868, 0x0000d6cf7f2694c3 }, { 0x000c13e651883a51, 0x0006eecaf06defd3, 0x000f497ed0b9e2f9, 0x000a01014fe3c105, 0x000029455e6852d9 }}, {{ 0x000dffbb5f63e5d5, 0x000d329855938e83, 0x000e5fe590137f7d, 0x000e725b92eeb5d9, 0x000084e49f54aebc }, { 0x0005d787c5f79f6e, 0x000f0431acc093d5, 0x000ce38d469b87c5, 0x0004a46600cb6cc3, 0x0000f30c7a69dbee }}, {{ 0x000a17ef8e44cede, 0x0001f47deadbf02f, 0x0008b22da0da0860, 0x0002433f011e8021, 0x0000e0cbc364982d }, { 0x000764196f27ef16, 0x000e72593e43bff7, 0x000e947fecc38758, 0x000f707a35cb5ff3, 0x00007e04f36d9766 }}, {{ 0x000cfc53b4244564, 0x0004fedf0290a8fd, 0x0005ee4b6fd35ed5, 0x00009974fcae8196, 0x0000c1f220ef19f4 }, { 0x000bedf5f9d4ef28, 0x000ca3c4cb632f9e, 0x0005cd318a6d91a9, 0x00094f00ac42a1ad, 0x0000689a17da238d }}, {{ 0x000ea61e2a63d186, 0x000c69f97e3e0442, 0x000fe32a819f8e55, 0x000bce8234201851, 0x0000668bd1c6ed6d }, { 0x000868c740040cde, 0x000b3bc575eaa945, 0x000160968aed23c5, 0x000e36f6f9e7bc72, 0x0000880b167f7fa3 }}, {{ 0x000c19e283331498, 0x0002adb7be0eead0, 0x0002f357aeb26c71, 0x000d5f8d7511e784, 0x0000b48101676692 }, { 0x000621b037cb2a49, 0x000a7cfe9206c550, 0x00042f321032bfce, 0x00035370489389cb, 0x000054fee486602b }}, {{ 0x00049dfb6757e9ab, 0x0003b3596e78cc4c, 0x00014768b940c469, 0x000fed2035385c8b, 0x0000146b998f7458 }, { 0x000d882de450b14e, 0x000937059f707727, 0x0003bc9587871fc0, 0x000d9a3903a073a8, 0x0000d3d672691eea }}, {{ 0x000882984a6412d2, 0x0006d0ab2cf89408, 0x0007e711f7072d50, 0x0001381c872b0b17, 0x00004f08b915e614 }, { 0x00012be0ff5c5e45, 0x000180c6a19d2bbd, 0x000bb5cba1cc5bab, 0x000322b644b9e7f0, 0x00003b06299d88d1 }}, {{ 0x000246e8af14e4f9, 0x000d93d0e165dc33, 0x00021bdc901f20a9, 0x000d3a7873d47ce6, 0x00006860c9c10ae9 }, { 0x000c598bba00d6aa, 0x000a4c703ce2b4df, 0x000abf66ec1544c8, 0x000c296c1e9b4ca1, 0x00006a2a90d3380d }}, {{ 0x000a1105556dd7cb, 0x000fb2b45036099d, 0x00013c6b6083296c, 0x000e64e43a9dee74, 0x000078a017dad06c }, { 0x0003baaf9a80f826, 0x0007f2c651a3be27, 0x000d14899a0c2d08, 0x0003b98d1cda5111, 0x00004e13797d5a7e }}, {{ 0x00000cab02e61927, 0x000e59d7fc63668b, 0x000c5bf6f1db6ce1, 0x00098fc516886c9d, 0x000015963851966f }, { 0x000d956d9d123a74, 0x000a2bc81b69442a, 0x000007c6cf517a7b, 0x000612e784148670, 0x0000acd5ae38e4e2 }}, {{ 0x000d774e4ee4ff1f, 0x000d38b638a7e819, 0x000ebc098f74b062, 0x00070057a54155cd, 0x00004efa631b47ed }, { 0x0006843cb3f5f8f6, 0x000782e078637d27, 0x000ce786a3b624a5, 0x000d6ad541c363e2, 0x000040f408018af3 }}, {{ 0x0004197ed9721891, 0x000d491d4b66947f, 0x0007102c8bb348b1, 0x0005dfe55b452ce9, 0x0000b7e62fe46cd1 }, { 0x000ada31f6ad76d5, 0x000df72400dd0f70, 0x000f40443e9cb7aa, 0x0008c63ae59f5ca8, 0x0000bd128c94245a }}, {{ 0x000c2a3869098900, 0x0004eb694a2c2152, 0x000ad97b424b1af0, 0x000e689fed83a43a, 0x00002b03a91bd120 }, { 0x0001ce6e973b5ec6, 0x00073408439d9b28, 0x000188feb07a97d8, 0x000880619715ea67, 0x0000f2fc52299eac }}, {{ 0x000af556ee5923e0, 0x000ffe0d809c7bd0, 0x000c841af9bcabc1, 0x00080376fd7b2580, 0x00006abbc0368a7f }, { 0x000e61844f2bc503, 0x0008873921de0acb, 0x0001c045ffb0ea65, 0x000091e7452ac9c2, 0x0000c85b8dcd9bc4 }}, {{ 0x000b192421f0e56b, 0x00086bc789a283b1, 0x000d6cef12d213ac, 0x000ffd52d72d3ac3, 0x00005f7fe8a58197 }, { 0x000a3bc86647bf41, 0x00058989dc84cacd, 0x000cc232ad52144c, 0x00059dbe2b0a8482, 0x000095d11cda69f2 }}, {{ 0x0007b4d51ba3adb8, 0x0004e53056e6f8fb, 0x0000ad1c5e8c26eb, 0x000bd064084861c4, 0x00001e7739155ad0 }, { 0x0000518677787161, 0x000d111220a255d5, 0x000bb1f017f68d42, 0x0009aceeac997152, 0x0000559f1f223eea }}, {{ 0x00043d74bc914746, 0x00072bacf902b0bb, 0x0004839dbb7ea13c, 0x00008cbbc8d4b4eb, 0x000057a993c570e4 }, { 0x000004512228d85d, 0x0000ec98adba3503, 0x000c8517c8053c9c, 0x000d515ec364eaf8, 0x0000420c9b7173e7 }}, {{ 0x0008a61cf4dc1641, 0x00058b7ea7b979b7, 0x00046e551ed89117, 0x000b9bafecd78cd7, 0x0000ea75547ea9aa }, { 0x00033effd03f2de0, 0x000e8723d502295f, 0x0003524db2b8913d, 0x00001a586f137685, 0x00006e05ca06d0f5 }}, {{ 0x000fd495f78c275c, 0x00068cdb30cfb3a6, 0x0000fcc91ed14bb9, 0x000a17ddf6d09b8c, 0x0000645d0ce04a7b }, { 0x000dc229b0415b16, 0x000009f275264daf, 0x0005e7bb59b2b9b3, 0x000525c2280c2b74, 0x00002b3172744708 }}, }, { /* digit=25 (1,2,..,64)*(2^{175})*G */ {{ 0x000fc20755e3176b, 0x000828452666a58c, 0x000016e7bc6ccdba, 0x00078f9084bcb6e0, 0x0000554faca4c643 }, { 0x00094e142cf0b0d6, 0x00046505294dba30, 0x0006822fbef1afda, 0x0006df474a30ba28, 0x0000e6be6e6ae1a8 }}, {{ 0x000b296904664fc3, 0x000b53e979f39254, 0x000a642320a351cd, 0x000cc34fa1efd130, 0x0000a26d827b4096 }, { 0x000df088ada01cc1, 0x000d534b9db65b69, 0x0001656914dd4d71, 0x00018a2f335c82e3, 0x000058dcd3dda1a0 }}, {{ 0x00036f4fb314c50d, 0x000a366bb3fd30a1, 0x000adc80e59bd10a, 0x0005fd66c429169d, 0x0000d081f2b59f20 }, { 0x0002bf6af341698f, 0x00020011fbba712e, 0x00036dac36ae06bd, 0x00045183e6ef0f0b, 0x000041383caf3e36 }}, {{ 0x00008fc59cde3468, 0x000e7124237b64b8, 0x0009635d376aaed3, 0x0004ff5d8688ebe9, 0x0000c1b55d497018 }, { 0x000b143a98f532c8, 0x000632ba3585862b, 0x000532de58edb3d0, 0x000ebfa9bb66825d, 0x000060efc436424d }}, {{ 0x000ae5a380deb2a8, 0x000ecce12ae381b9, 0x000bebe7370f573b, 0x0005442ca3a7f176, 0x0000600a0769fd67 }, { 0x000d65f035454aa2, 0x000eb15ed251b464, 0x00007d646e2f56a1, 0x000a76d071f5d6d3, 0x0000bb2c5fed005a }}, {{ 0x000f8f66b8a7cdf7, 0x000c324f111661eb, 0x0003f176844bf6c5, 0x00056be78edced48, 0x0000217f1b2be94c }, { 0x000ec85fbc8973e6, 0x00067f4d7ed8216f, 0x00068f645f12fdb9, 0x000735154bf07f37, 0x0000c3cd2d5edd0f }}, {{ 0x0002b052011404ae, 0x0005feea5ba5b0b7, 0x000dd02000988637, 0x000ab7f42e6a116c, 0x0000b74febd1fdd5 }, { 0x000b000c06b573c2, 0x000ad7d31a3b4ea6, 0x000820bd8f2c06dc, 0x0003d6897e589307, 0x000078133015312f }}, {{ 0x000f53916fc6beae, 0x0001122765fa7d04, 0x000fce16c2004cf7, 0x000c22d9859805be, 0x000052df10ff2d7b }, { 0x00099f450e1f9830, 0x000c61f33ddf6269, 0x000e06e68bf551b7, 0x000e86ee34206238, 0x00002aa249bfa9c5 }}, {{ 0x0004c88f374f6f88, 0x000d851e4c79e9bf, 0x0002d1a210b3161a, 0x0004ef3231394cb7, 0x000034829a179e77 }, { 0x00060e7f8aef7dc8, 0x000aa1f4aaa499e0, 0x0005ddecaae02032, 0x00014bd1d68b3a7d, 0x00009e90f751f24b }}, {{ 0x00047aa4c7ac2b3c, 0x00082731a3a93bc2, 0x00057da03752d6c3, 0x000d7d2fd42bbf46, 0x00008348bc06dd42 }, { 0x000825653cf027b6, 0x0001032f60c77da5, 0x000a69fded019b66, 0x0001dc3cf6ffbc26, 0x0000333cf94fd444 }}, {{ 0x000648487f9f745e, 0x000ab7ebc1aa2b92, 0x00031157eabb1368, 0x0002c7d380788939, 0x000092962173f198 }, { 0x00006a7a345f44e5, 0x0002e363fcef2614, 0x000cce4176f57b8b, 0x000e286e26239c81, 0x000007adc1ccaa3d }}, {{ 0x000ddab96e59ccf0, 0x00077ba4a493b31c, 0x0001ce1d36b7f226, 0x000c8a14b54f20a5, 0x00001a428916f43d }, { 0x00047a670dede59a, 0x0002d0aed25ea138, 0x000afd5154d9620d, 0x0009faac5fa1d09e, 0x000024f267bf7958 }}, {{ 0x00006f4098b6440f, 0x000331e64bcb626e, 0x0007466fa01d3aef, 0x000cc256caea638c, 0x00006bacbc3672fc }, { 0x000063d8a3c3a04d, 0x000c7527512a30b9, 0x000d5525ccf645f5, 0x000307480f3d867f, 0x00004f61af99ab8f }}, {{ 0x00017e76ea8b4aec, 0x000d995d314e7bc2, 0x000b24fa2303625b, 0x000d3e9d32ee7464, 0x0000fd86bbb7517e }, { 0x000a5817e3ed6c66, 0x000681fe7cda917f, 0x000a903127323a60, 0x0005ae96b12d8016, 0x000044afeb2ca0b2 }}, {{ 0x00098ad9f490f5c1, 0x00080640821ee4c9, 0x0003723b3f9d8e3f, 0x0007cc69f1583eab, 0x0000a66bfbb2018c }, { 0x000ee4ed6e631317, 0x0000250a41157f70, 0x0006d9f54d0fbb05, 0x00013a25fa9d7e1e, 0x00007eea65ae7d21 }}, {{ 0x000b69cbf65aaebc, 0x00090c5ac751e7b7, 0x000281d845c75cee, 0x0002f93c693f9647, 0x00005a6bb7c3dc6e }, { 0x000be7048732b0cf, 0x0003da2f4bf94e19, 0x00085541905b0af8, 0x00067070b1a5325f, 0x0000e3a10d49e546 }}, {{ 0x000c686e55c3531d, 0x00063bfe1dc5c055, 0x000a92567d01f185, 0x000bcc9a3d738add, 0x0000afd5ebc87e1b }, { 0x0008a947fad2853c, 0x000cf50dfd0b7ec5, 0x000b11a03426ca2b, 0x000cf3096bdd0264, 0x00002575e52919b9 }}, {{ 0x000fab1ac5f1c3a5, 0x000e84e49ccd6d74, 0x000c39123abacef0, 0x00010ceb2ff8fb02, 0x0000b9696ac02316 }, { 0x000d8260aa363274, 0x0002fbc97576ec06, 0x00079dfc1c84ccdd, 0x000fde200e8c946e, 0x00005e0955dd2239 }}, {{ 0x000fba35ff441c20, 0x000104f70bba85cb, 0x0000e4e69d11bf4c, 0x000f9cec1ad090da, 0x000045f5d2d270df }, { 0x0002160efb05643b, 0x000c69ac1e919380, 0x000318e632645d14, 0x00055d30fa47638f, 0x0000433a1488c0b7 }}, {{ 0x000cd99e61699f04, 0x0000c73615cd9e45, 0x0007944a9da57d26, 0x000dc398c498ec04, 0x0000524b1feda847 }, { 0x000ec9746fc9036f, 0x000a3df7851dafeb, 0x0009e8c6ed72b8df, 0x00008ea0ef156f5b, 0x0000108b102601bf }}, {{ 0x00012050d9a73af9, 0x000b0c1c8ed1f7a4, 0x000566fd0f18765d, 0x00065804a09e43bb, 0x0000103c0ab78e66 }, { 0x0003868fbbf33bcb, 0x000b14e90747e405, 0x000b62a3a6cab563, 0x0005268536dc05eb, 0x0000757f03238b3d }}, {{ 0x00080f9fb1b49db5, 0x0001dc3cfdcf7dd0, 0x00036a302b02766c, 0x00057c7a341a9fce, 0x00000720671b4553 }, { 0x000320fd327ff00b, 0x00083849ba7a5317, 0x00067a79174cfc18, 0x00058b83607d3558, 0x0000ab6cf754792f }}, {{ 0x000b96d16da0f72c, 0x000db98b18bd1ff8, 0x0000244657980980, 0x0004b3bcd52c2e30, 0x0000cd07defe68a2 }, { 0x00019448d72e9986, 0x0008a494b45706bd, 0x000da2a8dd214d19, 0x000597a76e7f58b8, 0x00003146bb218459 }}, {{ 0x000769788c7ccd96, 0x000f6b9d3210a041, 0x0003c391d9dca1fe, 0x000f5b29f6bc7d46, 0x0000a7a3bdce7dea }, { 0x000971da0e302072, 0x000462dbd6cb838c, 0x000559fb85145a33, 0x000e7e16e7066d6e, 0x0000166a58b45338 }}, {{ 0x000941b2a22935bd, 0x000eb6bc49a2fac6, 0x000fc75134d7d87d, 0x00039f8563b8420b, 0x000028c1f97d5e54 }, { 0x00075bcd770bf80b, 0x00058080658ff2ac, 0x00026cc8ddbf0813, 0x00059d7998780436, 0x0000b046effada4b }}, {{ 0x0002a6b802d70649, 0x000f7907f8f875d6, 0x000df41bb3bcbbe4, 0x0000a72e79c9d754, 0x0000ec89ec7b5eaa }, { 0x00019fe96bba031c, 0x00025aac6e7394b3, 0x00037bb805a4ed99, 0x000a3d80c445b6a8, 0x0000d094b5aa7fb4 }}, {{ 0x0000920d0920b3ba, 0x0000c1f385f63cb6, 0x0003c22bc41dea5c, 0x0003588c241250c8, 0x00006627f300e7e9 }, { 0x000a9bfe7766cbd7, 0x0008046724d81a52, 0x0002311e3421bbd3, 0x000755932b7ffb89, 0x0000c38dbc2a2a77 }}, {{ 0x000c94a8b3fecb0b, 0x000d7393191f4fd2, 0x0006a74204edcd02, 0x000ab8b0643093e1, 0x00000fea7bdc3f59 }, { 0x000ac3f5f4222e4b, 0x0006ec05c437d8e4, 0x00038e15fdd446f4, 0x0004245a23d4ae42, 0x0000b1ce9686cd0c }}, {{ 0x00048ef841ec905b, 0x000adfc6b6af9917, 0x000fa6cdf37b4794, 0x000b3b2d70d5270f, 0x00003f3048a38ef0 }, { 0x0002c56f83b0eb6a, 0x000940edfc6fafb1, 0x0005e46a9fa3f7f0, 0x000cee4c9eadfdf0, 0x00001b1b2c4fdc4d }}, {{ 0x00000f6ee71a6cd6, 0x0006c03d39b8c34b, 0x000581167ef45d8b, 0x00076c7c5ed8b1be, 0x000070c61c8b5adc }, { 0x000c324341fd93fc, 0x00072cf57d0ea992, 0x0007ebae2901bcb1, 0x000c74faadcae0f5, 0x0000ffd2c5f6a211 }}, {{ 0x000d8607e66825bc, 0x000c355e126d4682, 0x000f48ee862317f1, 0x0008401c2ed325f1, 0x00004e9bb5b46467 }, { 0x0006b0cdc1954e42, 0x000fc276009d660b, 0x000dd65ff7df7908, 0x00041c7a03a525d2, 0x000009b10a289aa6 }}, {{ 0x0002dfa557bfa495, 0x0000476e1337c262, 0x000db45dc38dd4f8, 0x00012d3d96faadeb, 0x0000c13ada75bd32 }, { 0x000c6ca5801dad5e, 0x0007c17be93c6d61, 0x000188985039af29, 0x000bbefa124866c6, 0x0000462261edbc6f }}, {{ 0x000e8d3ac716b9cf, 0x000de8ce964021e7, 0x0009849e47ecab8b, 0x00035c998b83bffb, 0x00005192ceb4ff31 }, { 0x000b2b0564f91674, 0x000ac91bc2d124af, 0x000c0a865a8f2693, 0x00065fbb7bd54c3d, 0x0000ca36576246cf }}, {{ 0x000570dfff87d7fe, 0x000c7575b45afb42, 0x0009ca47b12dc69f, 0x0001ee757e9ded64, 0x0000ffe130d9f5bb }, { 0x00098ca255a80b64, 0x000977888e084bd4, 0x0008a9f3435e8330, 0x0005936eea024b23, 0x00002da3669daeed }}, {{ 0x0005af3c6e99cba1, 0x000c5eaaaa07e869, 0x000b5db14917a1fb, 0x000f6b8c80db6fac, 0x00000dbef989db23 }, { 0x0006542e486c2d07, 0x0008b8c02e30afbc, 0x000c3a365a70473d, 0x000f0979d9b5356a, 0x000015f1407ea962 }}, {{ 0x000afe3247ac4682, 0x0009de87adfb6cc6, 0x00032d694ef9c6bf, 0x00039cf5acc826fd, 0x0000ca422fa86990 }, { 0x000a6778b884ff75, 0x00093b9b6ae8a751, 0x000d3067d9288acb, 0x0006244d6b8cf388, 0x0000c49ee251a7e4 }}, {{ 0x0004f1a6a51a864f, 0x000aec1ecc4c7e38, 0x000c91e9c227bdba, 0x0005bc7aade9fe47, 0x0000637ef4323989 }, { 0x0003365b1415cdea, 0x00093725a7b162b9, 0x00091a91bc8f680e, 0x000e7a346c5cfda1, 0x00002d033d623c62 }}, {{ 0x000f201022c136d0, 0x000022526a1fc900, 0x00023e50603a6d0e, 0x000d575f40d6d10d, 0x00009c8b622aee15 }, { 0x000394ff6b33c8ff, 0x00067c5658fde413, 0x000d4a9260b29b00, 0x0005a0ce7a8d2bc7, 0x000020c000e376cb }}, {{ 0x000550bd2e68ff28, 0x0009d098132c9af4, 0x000af0cdbb3a6f91, 0x0002dedaaaac4b0e, 0x0000ab754349a57f }, { 0x000fb1b899561971, 0x000c08eea5399d41, 0x000a71b1d2e6e9c0, 0x00031302dd989bff, 0x0000dd9508dd374b }}, {{ 0x000f01732de8a9ab, 0x000ce6944c44d6a8, 0x0009c8e6ee09ad42, 0x00004014491df144, 0x00002eeb080df28b }, { 0x0009476f970fa389, 0x00014253aa0a6332, 0x000ca08f6605dcb4, 0x0004bf71006de5e7, 0x000099a78f12c1a2 }}, {{ 0x000aff2f226112af, 0x000c8c0d34c35659, 0x0001809fef7bd257, 0x000cdd102ef1105b, 0x0000c029fa506998 }, { 0x000b332e089dab46, 0x00009853a80e75d8, 0x000de08a787917ca, 0x000ecb77ade71853, 0x000002996859d6e3 }}, {{ 0x0002ca07544326df, 0x000bce8b9c20cda9, 0x000543030543c2b2, 0x00092628389f7aad, 0x0000462f560eaa18 }, { 0x0004fdfd9c7882f6, 0x000e51174a1e0359, 0x00077eececf624e2, 0x0006205f202628cc, 0x000053d65edaa5d1 }}, {{ 0x00013045bf671e99, 0x000c75463428c6ba, 0x0001ef83c3e5fed6, 0x0002715112f7205b, 0x000071bd670eb998 }, { 0x00099f3ec14c07f5, 0x0001fff03ef77fee, 0x000f16504d2e9402, 0x00092e922689cd59, 0x00006897e1a72bd2 }}, {{ 0x000d2466e3ef3d22, 0x0005b91ea1b3c3ec, 0x0002eb5dd366b2c8, 0x0008d231e2d1a705, 0x000040cdd3ee863d }, { 0x00007c4b82673e6c, 0x000882fc8cb762d2, 0x000e5613d59cd383, 0x0009208507e312aa, 0x0000c2327bddf0de }}, {{ 0x0005670fbf65ef80, 0x000a5c1375913eca, 0x0005c229726133e4, 0x000785bf694e45e9, 0x0000158117a0c867 }, { 0x00077fefaeecfab4, 0x000024a66f5b8fca, 0x0009d0effc797a1d, 0x000049552d5a56ae, 0x000049ee3eb9b0d4 }}, {{ 0x00004a61164aac1e, 0x0000f7c98379d445, 0x000b00547b73dedc, 0x000c3c664d000bdf, 0x0000f6c15b16639b }, { 0x00067ecf4a4fa56c, 0x0004c71effea31ae, 0x000d0a434b0a070e, 0x000a1e7bf2d3de26, 0x0000cf8b029be733 }}, {{ 0x000004ceed9ae923, 0x0004652151fe690f, 0x00038f260c71df2e, 0x000cd078d0351580, 0x0000d3995d9f2836 }, { 0x000008e04b1b6128, 0x000c27cf0386fac2, 0x0002b1f3c705ed36, 0x00018dcec3b62ff1, 0x0000371099c99400 }}, {{ 0x0002a2c2241af6c3, 0x000518e41dbd7725, 0x0002cff16430b650, 0x000ce81f72b419f7, 0x00006d2ef331afce }, { 0x0006510652363465, 0x0008914634dfb02e, 0x00000e2763a12775, 0x0005ed5cc5f074ff, 0x000022c4d1e63b6d }}, {{ 0x000fde089e1449b9, 0x000db82f1012e7a7, 0x000028c75e109fa1, 0x00076543b51013cc, 0x00008371ca42a533 }, { 0x000f1f5764038bdc, 0x00078fec731b4b3b, 0x0003dade48fdff7b, 0x0008e59bc12a136a, 0x000052c07ce95456 }}, {{ 0x0000061987d3a8bf, 0x000e66da16d4b346, 0x00097c9c02c81980, 0x000e525867fba9d0, 0x000068da7a517899 }, { 0x000d7e28755b891e, 0x000f1869da28ff0c, 0x0007764631272fb6, 0x0009fad0d3133f70, 0x000092271cbf4392 }}, {{ 0x0008dc98e16ac555, 0x0009bf272ed91fcd, 0x0000c3f80a91efc0, 0x0005fd03c85214f3, 0x0000571a08a1dcae }, { 0x000cbff4f341eeda, 0x000d5fe585cc3a25, 0x000d169c04872f31, 0x000c46b81724952e, 0x0000703ab0cce8fc }}, {{ 0x000126332eeca533, 0x000d70e87d8cc7b9, 0x000360ac4da1a08c, 0x0004994049beaa7f, 0x000085d58a9542af }, { 0x0006092eed4373ee, 0x000d3b48ed3bd6db, 0x0002233cbc36be87, 0x00016f45535bb2c1, 0x00009ff16f286157 }}, {{ 0x00011e4bcd460f2c, 0x000e83fcc058865e, 0x00018d064d550766, 0x00041a7537b0a5af, 0x000046efe0747324 }, { 0x0002573bfa73d9cf, 0x000ca3aa14a90fa5, 0x000c67b515d9d098, 0x00058982d7706e20, 0x00007d1585bc34a1 }}, {{ 0x000717596c322d2f, 0x00087a93b5bdb831, 0x00008d8fc9ac384e, 0x000bdd75f08da65c, 0x0000f1e0a2f83e31 }, { 0x0002f3b50d9aca4d, 0x000a3d0b266d88b4, 0x0007164ddf4c7663, 0x0005edfacf688ae9, 0x000069a04a1ed5e1 }}, {{ 0x0001bc81d1567fa5, 0x00054986a90fc34e, 0x0002840e08bc1725, 0x000d25262c8f257d, 0x00007d37c1cef912 }, { 0x0000aa9ebd5aee4b, 0x0004467251a2a12f, 0x0006cddfd21ec0d8, 0x0000a022e10d8658, 0x00004f408c5bc296 }}, {{ 0x000652b5c82520ed, 0x000d104275968936, 0x0005df6c8f6344c2, 0x000a5abc8b6bb02a, 0x00005bc743f852cf }, { 0x000c773c3afe64cb, 0x0008afd4f5c04999, 0x000818dbeefd7cd2, 0x00084a3f76ea1655, 0x00008333b4274ea4 }}, {{ 0x000f9a78b85b575e, 0x000dc409b323abc8, 0x000161475ed8d00d, 0x0002fb77ae26605e, 0x0000ce1190f5abef }, { 0x000c94bddefb0e25, 0x0001faac407eddd6, 0x000836c6d870d410, 0x000fa149981ddd1d, 0x0000e0d5b79ac001 }}, {{ 0x0003624f3e74bdef, 0x0005bda8545d185d, 0x0009a029698ce572, 0x000c9f20e82ae44e, 0x00002103e5d5a56a }, { 0x0001f363f57898e9, 0x000379b14be42542, 0x000c9bc8cab053ab, 0x0002a92be7d0efcb, 0x0000217605b86c8c }}, {{ 0x000f7246a4a10356, 0x000e71ca85015501, 0x0001b938ca17004c, 0x0005e6f1c2251e0e, 0x00000d5fa3abf1c8 }, { 0x000120a64c2cae9e, 0x000a6ee5f2591f26, 0x000efd41cb0b0208, 0x000451f683c47d33, 0x0000a218fb5a7cf6 }}, {{ 0x0001c18807f2e6b7, 0x0000fc07b5d07df4, 0x00083d320f7b47b4, 0x00053e44fa92b955, 0x00000d924dd02cb8 }, { 0x00001b784f6b6a60, 0x000708980ba9b1c1, 0x000eb517318e9114, 0x000ba0809ac8dc6d, 0x00005f1ad1849fe9 }}, {{ 0x000fd8ae60415444, 0x00001bbb6f116037, 0x000dc1f9d1be7f45, 0x00020f0a857b09db, 0x000074bd20b5cf68 }, { 0x0007958e09141208, 0x0009e6678308435e, 0x000bebf0fe4490f9, 0x000c5a2b09572f77, 0x000007396bf5f419 }}, {{ 0x000fd7296995f44b, 0x000e342253466896, 0x000040a5469aeb31, 0x000a0c3e3716da29, 0x00001e5c16338121 }, { 0x000ef6d5416eee55, 0x000430308b640d30, 0x000e79883d5fe34a, 0x000403e115b0026e, 0x00003880d9961f05 }}, {{ 0x0001e0f84f93b4ba, 0x0006df0f9c41135f, 0x000876c5514402dc, 0x0008ccd5cf21d60c, 0x00008207421ebd51 }, { 0x000f04b824048527, 0x0007c5906002d609, 0x000b67145d2e9747, 0x00092f7c3be2da60, 0x00003cc3292a8a5c }}, {{ 0x0002edf52c078d85, 0x000c57dd4b79bb87, 0x000adfda839ce9d2, 0x000ba33e8aee806f, 0x00007fc8b3dee585 }, { 0x0003b2818874b38e, 0x0001a4e2127015a3, 0x000069054d6b7749, 0x000ba60c89051d0c, 0x0000fcc7ea0acfb4 }}, }, { /* digit=26 (1,2,..,64)*(2^{182})*G */ {{ 0x00063f4153af6dcd, 0x000c683171b445fe, 0x00029af26bf85199, 0x000cbbae89bcf21e, 0x0000e2560e6db219 }, { 0x000e1d75ae224a6c, 0x000f6a930add43df, 0x0002cb637aac5049, 0x000bc7d6862ebb14, 0x00005e73664b3718 }}, {{ 0x00080034798ca4d4, 0x000f2c7af8685c8b, 0x000d778ecd30d2f0, 0x000cf952ad4c1c8c, 0x0000e198f05db898 }, { 0x00063d51806a84e5, 0x000e1e52eca3cdb7, 0x000b75c78219120a, 0x000a6e0cfea1db16, 0x000052a4a35bae24 }}, {{ 0x0006c8bebe50eb45, 0x0007cb808bd98d05, 0x00040ead3381f366, 0x0008a8d70644b1cd, 0x00007b632a717522 }, { 0x0008239899b73b3c, 0x00096acc4632b46f, 0x0009b7b269a90fd8, 0x00021394617da427, 0x000076f048091e12 }}, {{ 0x0008e13092cf573a, 0x0005c3f4c8303203, 0x00005750d3512460, 0x000db40fb842c7aa, 0x0000494598d37817 }, { 0x00077989cb6b3d8b, 0x0007062757558f1a, 0x000150731ef6087b, 0x000f58b273cc3e83, 0x0000ffa7db45a98a }}, {{ 0x000e632a990cd2b6, 0x00061a144a081e00, 0x000da8aafed1d92a, 0x0004cbb9cd797fb7, 0x0000eb29b6b6973b }, { 0x00010f9eff77898f, 0x0004216c5f0c2848, 0x000eac88dd631243, 0x000a457cff51088a, 0x0000f820a5bcdad4 }}, {{ 0x0002830fdbcd7a9a, 0x000fab97ffe4b3ed, 0x000113774d45e378, 0x0008122750b691d2, 0x0000dbabb5016bd0 }, { 0x0004aef03d79fd03, 0x000219c52434f573, 0x0005635a7d6e7d8f, 0x000fbbdb34b1f754, 0x000089b90d825715 }}, {{ 0x0005157b6a28f2a3, 0x000aef4b7ac7ec57, 0x000a6ff82c6bcfde, 0x000476bb8d6ceb95, 0x0000cd5591ba46b3 }, { 0x000117f5ae655dc1, 0x000064ec5413d62f, 0x0006cb47cf197d67, 0x0009cdcdabe329ff, 0x000034f79ff63bfb }}, {{ 0x000d84601a040653, 0x000c4f4b0166f7a3, 0x0007916814ccaa7c, 0x00080f8fdfbd3e3f, 0x0000bdc4370992dc }, { 0x000a6279f7786e45, 0x000a95c7c1620b02, 0x000d01014b0992a4, 0x000fa801eba68b4d, 0x000052fa0f983aed }}, {{ 0x0001c6a659019d30, 0x00039b06ae85c104, 0x0008dc372d4d1620, 0x0006a5bec7294697, 0x0000ab9976bc0f2a }, { 0x000333af21cebd7b, 0x00095240e0239001, 0x00019dd9652bff2c, 0x000cd3ddcbaeec12, 0x0000ff15e9da5236 }}, {{ 0x0009088b4d137854, 0x00096e03aaba1f19, 0x000da268b982cbad, 0x0003344bc2cada16, 0x0000badfeeab305e }, { 0x0002071cf6a8f781, 0x0003fa03549dbd42, 0x000fcf51a6b55cde, 0x000f6558542cbdf8, 0x0000c6c6a717b9de }}, {{ 0x000cdbcd7623a9b8, 0x000ba1fff2811e50, 0x0003f1a3e116af2c, 0x000483fbbdb81b70, 0x0000d353c95f79b0 }, { 0x0004c3074db8bf13, 0x000512a566a808ce, 0x00034f3d5d88967a, 0x00069e76f02b7445, 0x000003ceb7b97c4c }}, {{ 0x000a03aee51cbd7a, 0x0003eb0b796d2197, 0x000eba706ef4966f, 0x000307cf5c3e95f4, 0x00007329daec404c }, { 0x000aacb62b09eeb6, 0x0000d76f53a89aa8, 0x000109dd72b102e5, 0x0003bfa4f0d8af9b, 0x0000584ec8a3c986 }}, {{ 0x0002c97a20562f30, 0x00055ebf62ffd521, 0x000e44ce44efba3a, 0x000b3daefe670b54, 0x0000098ea607e96f }, { 0x0001985e228d3952, 0x000f4ce1fe32093e, 0x0005576f4aa6830c, 0x00035206b13cb4ff, 0x0000bb374024af47 }}, {{ 0x000f278cb2b3179b, 0x00043a910a230cd3, 0x00038e096c95125c, 0x000ca660a24f46a9, 0x00000266524e1cf8 }, { 0x000207cf075b1512, 0x000b47d50b920eb4, 0x000d4c6e366a9240, 0x00080a509f1cb9a2, 0x000070955e1401ad }}, {{ 0x000747d648fddd2d, 0x0005181c4127fe1a, 0x000c93a1ef1d3d25, 0x000e28ea5a9f8b9a, 0x00003db1465f08ae }, { 0x000a7234813df238, 0x000f35c2ba97bf75, 0x000d6287fea38e24, 0x00093ef9d15e0f77, 0x00005486c5bb1638 }}, {{ 0x000a4c97a4abc3b1, 0x000629f8f5fcda83, 0x000483a1c45951ca, 0x0007bee77f3e558c, 0x00000e48e3d45037 }, { 0x000f9b7025a36d96, 0x000524bf6dce6a73, 0x0005d44b52ac36ba, 0x000ec10e9ff373d9, 0x00005254e73f1733 }}, {{ 0x000917ab9ff1c65a, 0x000f031317cd0627, 0x000da087d792e7af, 0x000eac10b30779d8, 0x00007850b5ef6624 }, { 0x0004d90fa2ac1df6, 0x000a6be28fb1d8e4, 0x0002ce95ca910a5c, 0x00053b26c2e31356, 0x000059685056c6f7 }}, {{ 0x000012062fd2dce6, 0x0002267d6b3e243a, 0x000cb8f28618953c, 0x000962f389fe6cd9, 0x00007eebcb8ff8c2 }, { 0x0002260beaa35c3a, 0x0008ebc9399d0822, 0x000a1fb906f7ddab, 0x00093057347e8c54, 0x0000f595f07f2d13 }}, {{ 0x0007401e4d1294c0, 0x000661e1a18cc20d, 0x000e4be1b7e97e55, 0x0007cf6a02192999, 0x0000422ab974c7d0 }, { 0x000b5cbc27a1ccf6, 0x000a3836fbca2bae, 0x0002a46340237734, 0x000b9c94046ad329, 0x00002357b30dce95 }}, {{ 0x000f6e149c30d036, 0x000786c252bd4796, 0x0009a3476ff36be0, 0x000f9406305e0f88, 0x0000f83a58f41674 }, { 0x000e1a0a8596c4ab, 0x000785cde601a897, 0x00087559b39a4f3d, 0x000826d27d17bbe9, 0x00009be39f3ad611 }}, {{ 0x0007ac8746207af9, 0x0003896270580c34, 0x0009aa1d02ce4c08, 0x000b9e7a51e23383, 0x0000cf4081696e8d }, { 0x000d9da6c4963c2a, 0x0004d9a100dd467c, 0x0006814766449538, 0x0002461c9274a433, 0x00004c28dc524eed }}, {{ 0x000774457fbdd20a, 0x0000f9f355116ac9, 0x00091f5d496d688e, 0x00079b671cc38bb5, 0x0000fd56d3b79f71 }, { 0x0000f140b199642b, 0x0007ec8c6db88bb2, 0x000f2dd84d526d42, 0x000887f8b6429d07, 0x00002d0578cfc96c }}, {{ 0x000e6fa37e3db750, 0x000bf09ca4946937, 0x000073e3458ba1d4, 0x000f9fb1248d3a02, 0x00009a0ba3d63119 }, { 0x000d35c7755bbb5b, 0x0005a0649a0c938c, 0x00079eb02caa0b2c, 0x0007a3912b72c0d4, 0x0000f4f8e7d64356 }}, {{ 0x000e3c3c1d7cda3d, 0x00032ea87baa6279, 0x000158ee6a629579, 0x0004420c958c1fec, 0x0000d64ac7b719e3 }, { 0x000792f805f03b27, 0x000eb7b2bcfe0b0f, 0x0001327ffd07ff8c, 0x0003e8c973510710, 0x00002665759bab58 }}, {{ 0x0006229c472f32af, 0x0009904a9b46402f, 0x000ccaec6c09216a, 0x0002f59aaedddf85, 0x000022cb9423951c }, { 0x0004f9e47fc8c2c3, 0x000011e7727b9b64, 0x000b654a63c2fce5, 0x000e684ea289e4e4, 0x00003b8864805a20 }}, {{ 0x000e57c4ea5be12e, 0x00073fe611f8b8ef, 0x0009f6c12f3d9e96, 0x0006d8cc3fd2e416, 0x00006523896385b5 }, { 0x000a38efd1795651, 0x00002acb1aaf6131, 0x000fd01f6a74847a, 0x00041ff3431df210, 0x00000190aa223cab }}, {{ 0x000936a01ee6f056, 0x0009c370b1e9e212, 0x000cf487e88bd896, 0x000d164f9b258514, 0x0000b0dbf25b69a9 }, { 0x000717e61d824da3, 0x0003b986dd5b20c8, 0x0000e9e1a8b25329, 0x000df8cd7b586bf7, 0x000098c804cbf541 }}, {{ 0x0000291d43fc236f, 0x000e82235e6fc06c, 0x000e4b14f6918efa, 0x0006704723477728, 0x0000cd51067b09ae }, { 0x0009f8b71be82198, 0x0002467cec5a196b, 0x0003a235d360dea7, 0x0004c8451deeb31e, 0x000071e8bcc32913 }}, {{ 0x0006bbee27162ea6, 0x000fc87968a2ab91, 0x00092fffdcf8b836, 0x0007f9930e3c5ce6, 0x000052f83aed92d1 }, { 0x000aee94a5c4b253, 0x000cd17fd42cd227, 0x00007dc33dfaa1ab, 0x0006df6321e13997, 0x00008a5c209883b4 }}, {{ 0x00046af04a0b75ce, 0x000336089821a663, 0x00085b2d261f5d51, 0x000566845f7c3767, 0x000046b01307b23d }, { 0x000e266e7ea58076, 0x0003c32370bf29c0, 0x000e34bfe26f7ad7, 0x000a63590f90c73c, 0x0000fa778d8e6bfb }}, {{ 0x0008c7ca3988b700, 0x0008eb90fca65d93, 0x0009dde77b7ef7a0, 0x000105a4e7e2989e, 0x0000f1c42756f442 }, { 0x0008f99897246c90, 0x0003494d402676af, 0x0005fe32e3b161e4, 0x000cdb64e26ab5a6, 0x0000d779dfab8fa9 }}, {{ 0x00005ab8b7207ede, 0x000a6911a335cc88, 0x0009e9fe5b2d6bb2, 0x000344b19563459b, 0x000063bbb632aaa7 }, { 0x000b647545ffb149, 0x000c9da8d006086c, 0x0009f1914bb72b13, 0x0006fefd76ca4846, 0x000088e4372592ac }}, {{ 0x000ffea6429715c7, 0x000278fbd7d90402, 0x000e519cf6536d14, 0x000921044ee66a2d, 0x0000fdbc110ce347 }, { 0x0005fc22ff710224, 0x000b7d1114344eab, 0x00064711998bde17, 0x000ea5b910430453, 0x00004bbc5151aab8 }}, {{ 0x000e608d3b84a63c, 0x00027a91ee682e0d, 0x0000202539ebdc33, 0x000ca402ddf48abc, 0x000039b2f368d7a9 }, { 0x000a5e736f80cbe2, 0x000e08bedafd8830, 0x000eb3366aaf8525, 0x0008d5c413c362ed, 0x00001f043dd12d92 }}, {{ 0x00051c374c6eccaa, 0x0007911f68cf9d16, 0x00075c5d3e0a50dc, 0x000351809a4f9ef8, 0x0000ad1a87ccd2e7 }, { 0x000f8b5ca64e7fbd, 0x0004e5888b5cead1, 0x0008501e7f03fb15, 0x00096363a0ef0005, 0x0000e724123c7fff }}, {{ 0x00090f925a13bf98, 0x00028a3ee9523f07, 0x00021e4f171e207b, 0x000b3eff4bb75eab, 0x000087b67cf8d7fc }, { 0x000a80ca34fe2f62, 0x00001ad1e4f6a5f6, 0x0003f7d0d01bf374, 0x000368fee06e08b8, 0x000092f43fe95274 }}, {{ 0x000932ad964afa6f, 0x0002868aaba4864c, 0x0001c41ffa4036b8, 0x000b294f1b13cabf, 0x000056378b24b243 }, { 0x0006cecce0d322ce, 0x000a28ecae1e27be, 0x0008343f2967812f, 0x000aaeabc9dac426, 0x0000540f92402c0c }}, {{ 0x000d95bc6cfae79d, 0x000e75e95081181f, 0x000f6bfd9968c225, 0x000cbd8a8cc8a791, 0x0000480e6df000c8 }, { 0x000bdbfb94f56234, 0x00036266888523a0, 0x0006bf25a4d854ae, 0x000577f974d142bd, 0x0000a963460af4b8 }}, {{ 0x00001be6298ca10a, 0x00098291660f6a6a, 0x0005b5001e039d37, 0x00022f5e87f6abcd, 0x000023ff88c1c17e }, { 0x000064091feffe54, 0x000ed030ca1c3287, 0x000d489f896e7ea4, 0x00092f0b0c74114b, 0x0000370a3f4a2eae }}, {{ 0x0004f21fd5b99340, 0x000b521e447f2c48, 0x0009db50721aea61, 0x000c5e6de81b8da7, 0x0000050b21dc70c3 }, { 0x0009f72f7ea729c2, 0x0006f814e9df3d85, 0x0009dfb45db575f4, 0x000efe84a1ca4861, 0x0000e4cdd0716db3 }}, {{ 0x00033c65bf36ee47, 0x000f841386d5087c, 0x000c1a2b70906c0a, 0x00081da5840bf739, 0x00003727fb23462f }, { 0x0008de9cfbb71ad6, 0x0008f7c38ca61533, 0x000aa39a7c7b16b2, 0x00053493997f4519, 0x00002e4ab8b82e16 }}, {{ 0x0009ed75a8075803, 0x000e8a37b793f853, 0x0009b67a736cdcf0, 0x000bcab87e9f8dbf, 0x0000d28da38fbee9 }, { 0x000320fecff5c637, 0x00011487ffba390a, 0x000ac7d8bd39b7eb, 0x000ae3fdb67f8cb8, 0x0000a584d17078a6 }}, {{ 0x000c04d32f4cd7b7, 0x0007902b2aced2bb, 0x0008a56701019371, 0x0005a0770dfba180, 0x00007ee3ef2a1576 }, { 0x000b1949fd771f7e, 0x00022d10f9f142d6, 0x0004dcd51025a0e6, 0x0006a36e32c44a0c, 0x00007e3d8d8e45c2 }}, {{ 0x000b87bcd0217256, 0x0004808be0f44920, 0x0003de4e28470c89, 0x0002210a83ff0da0, 0x00000219c682d1d6 }, { 0x00045c0f29f6bf67, 0x0009583ab1f58ab6, 0x000a1d22cd60f4a5, 0x0007c00e56d9598d, 0x00007cfc00573c26 }}, {{ 0x000e4c720d49953f, 0x0009e82eabaf21cb, 0x000963f4f390dba7, 0x0000a319182b9602, 0x0000a7b7f6d4dee4 }, { 0x000b26d3ec37e7f8, 0x000c4036f08d6c97, 0x000733e9eb5434fd, 0x00029071236e8a99, 0x0000804003513506 }}, {{ 0x0008486600572aec, 0x000e6d0c9469ad61, 0x000d18673a5b5b15, 0x00040b686c4a11b4, 0x00004c8a42d0ce86 }, { 0x0001f6653acf2e26, 0x000b0ba8d9ce5be6, 0x00059d5595d2893b, 0x000d2a9730d8f68c, 0x00007023d6e1d087 }}, {{ 0x000ac7e2a0e832ad, 0x000962b5aff5a48b, 0x0008b7f257c9170a, 0x000e5ecef0d81c4b, 0x00009e1bf2654911 }, { 0x000e23feb138dff4, 0x0004b6c1c664399f, 0x00005da714ac9df9, 0x000cb88bf4c288de, 0x0000a0bdbf12fa64 }}, {{ 0x000d63ff677c67f5, 0x0002f66cdedca850, 0x00000ca5542522b3, 0x000a91c5d140bb71, 0x0000061b8edde9e1 }, { 0x000dd6d4fcf285d8, 0x0007d517d234afbb, 0x000dc049bac482d8, 0x00004735d61c2db4, 0x00000bdf475cd200 }}, {{ 0x000379bc0760a44f, 0x000536d3be01cb1e, 0x000b40c0e4757120, 0x000abe6029ba14ff, 0x0000b2768766a251 }, { 0x000499f0b7403ff6, 0x00022e9d4ca8d68a, 0x000bdc215072febc, 0x00005b368083558e, 0x00000674a9be8956 }}, {{ 0x000524194f020327, 0x000303cb8349abe3, 0x0004fb90e2cd1e88, 0x0004f22903baab3e, 0x0000cf54c8866bc9 }, { 0x00078e9bd6163cb1, 0x00066257d4bcc42b, 0x000b01726de44c34, 0x000e730e0e90a3d9, 0x00006e99c9f280fc }}, {{ 0x0001b393ef075bff, 0x000b8469e03d2781, 0x0005c55acea80038, 0x0006d79558017860, 0x00004b0cbffe0992 }, { 0x000975eb80eb4487, 0x000de82d8884f278, 0x000a35a3cede5daa, 0x000dbdbc6bd44737, 0x0000d4e86779cbb8 }}, {{ 0x000a12aeaeda2167, 0x000f0c7d7fe71f3b, 0x000002851f89faec, 0x000cf14631534219, 0x00002b71cc5b2f73 }, { 0x000a778c8bea0c7d, 0x000b8d2a9b4f8f67, 0x0005805f4d10c1d4, 0x00088167c04619d6, 0x000025b9fb741b8f }}, {{ 0x000fbfee7fb522a9, 0x000dd2320a71b899, 0x000c7c62a2e5d72d, 0x000d59199241a2ae, 0x0000474a8ea015f5 }, { 0x00083dd738132807, 0x00051b95c4017e32, 0x000fecd4344ed7ce, 0x000db466f1dc7f9d, 0x000070c33943a538 }}, {{ 0x000e55d0c2e5f7e9, 0x0003d09cd85d6a2d, 0x00051c9030b43387, 0x0001b15de6ebbc34, 0x00002dbfb11b5868 }, { 0x0000178c71b5b3ad, 0x000367f24dcdd5a7, 0x00050eba05896a00, 0x0004e910d8d602da, 0x000031562bd0e4c0 }}, {{ 0x000d3b63b60559ae, 0x000f5863fe54cf05, 0x000ea58050bff57b, 0x00043e6d7a4a3ec4, 0x000068c2c4366a8c }, { 0x000e0ffffce55a24, 0x0000fd85ad3d2aff, 0x000cd39c7a3a9a4d, 0x0001d7214fbc586d, 0x0000260f7349e15b }}, {{ 0x000c326d123c14a3, 0x000437f906151e50, 0x000f49ae99370325, 0x0006854b7cea27f5, 0x0000400c840acf85 }, { 0x000dea4b70fa8920, 0x0008c337dd35df39, 0x000925ac906e0b6e, 0x0002ebb1c0c3b763, 0x00001965b1ca3b09 }}, {{ 0x000ebf9747546784, 0x000ea53aae3f639a, 0x000c4d67f464f2f6, 0x00028b35ffaba0e7, 0x000050bca1ceda40 }, { 0x0004311819988796, 0x000193ff41ad5d66, 0x000c4eb87a0aad72, 0x00047c0aa03c4623, 0x0000ecb71c39431b }}, {{ 0x000e526f3fe97340, 0x000b2118be489ac8, 0x000d2b4ea10c02e4, 0x000f1a0072821895, 0x00003dbc2e993576 }, { 0x000c5a3e30980bb1, 0x00019775b645aee2, 0x000f53b3d2ced666, 0x0009145de3d1dcb9, 0x000083a266843180 }}, {{ 0x000c4e57b437a58e, 0x0003f3e2a6c6fbf0, 0x000a3fab215289e1, 0x000f7db01a74516f, 0x0000f786a2c596ef }, { 0x000965f3c5b529a6, 0x0000c29b6e386b6e, 0x000cb078b861c0d4, 0x000478029b46793f, 0x0000a2baaffa251a }}, {{ 0x000f1ef3355edcbb, 0x0004083425c65590, 0x0005fbd17ca52ef5, 0x000fc9bdf7fc00ee, 0x0000d8394a59efd4 }, { 0x0004329d7084b6fe, 0x0005345b79b8ea2c, 0x0004f98d5517a604, 0x000615fb740fd294, 0x00000a2b05ab5452 }}, {{ 0x0006c177171f353e, 0x0003d52ed1be45d6, 0x000d7e0bb55daa85, 0x0000bfbb1891dd20, 0x00002712c1116863 }, { 0x00091b3fa0fa9f46, 0x0007b412843c4e0c, 0x0006f063761e63bc, 0x0006d4fc7d5ac481, 0x000065f27cb5b34a }}, {{ 0x000c1fcd2acc0b57, 0x000dd0aab9d97f89, 0x0006f48308e66a00, 0x0009ba0e5fb57bd0, 0x00003a73253811da }, { 0x000f78f55b916830, 0x0009ca9c7ea74322, 0x000c0107819b05c3, 0x000f31ca51b0b924, 0x000084e2a1bbee98 }}, {{ 0x0006f2e3dafbe296, 0x000de4ac18a414fe, 0x000da94a26abfc55, 0x00062a955c611eaa, 0x000053a9ca6e3b2e }, { 0x00087883af2cb656, 0x0000a179320dc3cc, 0x000ec57e31f52ec4, 0x0008aa490692e382, 0x0000c6a39be83100 }}, {{ 0x000cfd57c06983bb, 0x00098e453544774f, 0x000b3dde4afbe78c, 0x0005fb6f5834d0ec, 0x00007bae9c3b3751 }, { 0x000ee4d65bdcce8d, 0x000ab3dd6901b1d3, 0x00047673a7680203, 0x00093d2623b49fbb, 0x0000be9b2e57312a }}, }, { /* digit=27 (1,2,..,64)*(2^{189})*G */ {{ 0x0009ae30f9bf470b, 0x000087d0d63d1fae, 0x000118fba7a5a59e, 0x000fc5809658fc05, 0x00005a1e22227a90 }, { 0x00083acb655ee723, 0x000edd1818baf918, 0x0006032f40bacfef, 0x000334844e27e9e0, 0x000040f4d53495bd }}, {{ 0x000ee84e265cd5da, 0x000988dc2c6ff707, 0x000f46f3d40f2a5f, 0x0000c9df979d6122, 0x0000ed01e35bdcbd }, { 0x0002d0793015eb1a, 0x00095b063cd880a6, 0x0005d2a436307bbd, 0x000f365423f3ea7c, 0x000081c0177d53ec }}, {{ 0x00065f36c733ecb7, 0x00097438a5807cef, 0x0002edb163b75a2e, 0x000e8e6daad28389, 0x00005a009a4a047b }, { 0x00026231865878db, 0x0006b9ea60d32b2d, 0x000a6c1f604286b8, 0x000e303b5ee93df4, 0x0000ae2226c13edc }}, {{ 0x000968734e4dd7f6, 0x0008df9dec31a21e, 0x0002817162256254, 0x000a3ed65988c8b2, 0x00009bb859066057 }, { 0x000f94739f3adb65, 0x000858f5da6309bd, 0x0003e25d5a77565c, 0x00068a42110f3a62, 0x000053d37190038f }}, {{ 0x0004cf63c0f10c8f, 0x0005106cce85c9b6, 0x00063ff85f12ae8f, 0x000ed8f60360e70d, 0x00002db912ea29bd }, { 0x000f8b36c18dac42, 0x0003da3e1cf6f904, 0x000686550e256d64, 0x00088999fb7e937c, 0x000091b309d5b740 }}, {{ 0x0002ceef4d55dd08, 0x0005da434a35ea84, 0x00070a7523a8c814, 0x000ab2ec33418e0f, 0x0000b26e001161fb }, { 0x000772f4c008038e, 0x0003c0b543a1957f, 0x000490f9bc634d5d, 0x000955f30c33761e, 0x00003c76f2e45ff6 }}, {{ 0x0009ff51a206fb0a, 0x00036bb4885d4104, 0x000051a6a735edea, 0x0009dd5b17287f81, 0x000044dfcc90c3d7 }, { 0x0009e739a001c317, 0x000e3536bc3012e7, 0x00019d261a7db4f3, 0x0004c32663d31fd7, 0x0000a707f44faf49 }}, {{ 0x00003f3e034d81e9, 0x000580ef4f8b16a8, 0x000e443be8670976, 0x0001a9ec197241af, 0x00001dd783168b20 }, { 0x000097440f10fef1, 0x00018a804dbec69c, 0x00067b238c506e04, 0x0008f287fa83b85f, 0x0000d016711f649c }}, {{ 0x0000c59ad98e2c8c, 0x00023b63524ff164, 0x000e417a2bf4e4e2, 0x00011bec0d7f9b51, 0x0000f07523fe58b6 }, { 0x00038fdb3274f644, 0x000cf6f17c387a48, 0x000567f6a51af73c, 0x000642fc95043b8d, 0x0000e865fd6bdff2 }}, {{ 0x0007b53ed41360f7, 0x000bfdd418e7ddd1, 0x00032f79db02b1a6, 0x000c6f44d39888d9, 0x0000587a59dee9f8 }, { 0x000b2fea9bbd72cd, 0x000351b2b01ae4fe, 0x0006e4189be73eb4, 0x000eb608788462e8, 0x0000369123795063 }}, {{ 0x0003fd41b6333ef3, 0x000685fb821fc28e, 0x0006f820e91c2a59, 0x000f1c76289d2e19, 0x00007ba4f718025c }, { 0x000b586236bb3b57, 0x000552eb9a96d612, 0x000a0b3be1bdfbfd, 0x000c84d407f8567c, 0x000013167b56f73c }}, {{ 0x0003132b63c9bbbe, 0x00042c756b95bce4, 0x00061e5a7b1cf210, 0x0006584525ec0390, 0x000035ffbec182a8 }, { 0x00063e8924f392fe, 0x00041f22f3263bf6, 0x000c3692181d584a, 0x000ae5ecbd5b3733, 0x00000ee6831f5d50 }}, {{ 0x0000089cda3b5352, 0x000505e5236344e0, 0x000dbd9ed20c4505, 0x00078eb2282e8df9, 0x0000041841a4fdd6 }, { 0x000a6297cdfe9726, 0x0007a71bd38a3db5, 0x000095102157933c, 0x000a7b9754ea97fc, 0x0000a0b0d44f8deb }}, {{ 0x000a11dae24e01a0, 0x0000b35ce7c42d4d, 0x000ea8ecd02dbf37, 0x0000f7b459fd493e, 0x0000a4b9f5308b34 }, { 0x00014369a85af1f5, 0x0000d785545a7fb2, 0x000c1f919e3e8182, 0x000750558bdb2601, 0x0000d24bcc8a4315 }}, {{ 0x00019d679200106c, 0x0009dcb06e0956ce, 0x000e1f6f6bb91946, 0x0006139324c9d254, 0x0000df1391186504 }, { 0x000a6bd1e8bf9fff, 0x000a728db5c7be33, 0x000877e20c1d3762, 0x000fb2f2ec714121, 0x0000a3614c505432 }}, {{ 0x000a1a96613ebed5, 0x000aaa0b311898c7, 0x000452f4160400b5, 0x00055fbbce2a272e, 0x000044105e96f0ba }, { 0x0002280dcf97d62e, 0x00039cea1c8cde9a, 0x0008d0499e144dcd, 0x0003fe7cd9d958ba, 0x00007fe9ad9ee6a5 }}, {{ 0x000c0f4672046418, 0x0008dc1cf6401471, 0x000d42748aa65277, 0x000c0ad11ea5a2e3, 0x000085ed223cfbd5 }, { 0x000a05f641ba27d2, 0x000e5a9695653812, 0x0000b4c92919d77e, 0x000cdfe09dc96624, 0x000016ab44addb42 }}, {{ 0x000306333a079f4d, 0x0008866d4312483b, 0x000cb137ee35846f, 0x00064f7935179a95, 0x00005b20b179b20f }, { 0x000dc92787c3fd1b, 0x000d1db0081a726e, 0x000561df74341404, 0x000949bb90149b0c, 0x00002a861cf9d27f }}, {{ 0x000e08e3479258df, 0x000e34aae6a8e13d, 0x000dc12fb46451af, 0x000c1281585833fd, 0x0000a5f7d00a3745 }, { 0x000c0dcfd1df99fd, 0x0001b4ccdeff2e08, 0x000a8a50deff90fa, 0x000e2498a49f9387, 0x0000a9b6e98e5797 }}, {{ 0x00094d3f1ba6043c, 0x0009de37a6a308bd, 0x000f72da28b830d5, 0x0008882b66237582, 0x0000b9540188ab4d }, { 0x0007f04703513909, 0x0006a5bba21f248e, 0x000484e1a8ad4170, 0x000772984272ad0e, 0x000027dd807898b4 }}, {{ 0x00077c871440e1a8, 0x000184acba2ececf, 0x000fec2ab72d4975, 0x000078f250c18126, 0x0000bcb6186f88c3 }, { 0x000109fe96d12373, 0x0001e83fa7f9f909, 0x000bfb8d0916c333, 0x0009e56a3f2e7aa4, 0x00009e0eec3e2355 }}, {{ 0x0003f901e0ee3da8, 0x000c0a9e9adfe1c3, 0x000cfd5537daacaa, 0x000c08f8f3984403, 0x0000096fcbfd4004 }, { 0x000dbd3ddcb09925, 0x00000fe3652438c6, 0x00063014b42f3978, 0x000265abdae9ec4e, 0x000078614ff4c20e }}, {{ 0x000bd4d8f33bce8b, 0x0009fecedd36776e, 0x0007fdb0b7462639, 0x00060e565f612c47, 0x000003f48d640dc7 }, { 0x0006125c1b173232, 0x0006eaaaac4cb325, 0x0006bfdae3ea27f1, 0x000704c63ea3aadb, 0x0000876e11548998 }}, {{ 0x000320c5cb34fa83, 0x000c1a43794f8dcb, 0x0009951b966af168, 0x000a28da0dcca923, 0x0000bdaf4528f40a }, { 0x00083be9a0dbe4b2, 0x00076ff47b50a951, 0x0001b6b449d08629, 0x0002b4f53933e3b0, 0x000077b42a87e4bd }}, {{ 0x0008df26cd861bb0, 0x0002c5ad6bbe24db, 0x000f9aa510c7c822, 0x000d07d4cc6c7462, 0x00007f4555c709df }, { 0x000cd8924978fe2f, 0x000b4995a483f8df, 0x000680fa9ef11fdd, 0x0000da47572d8a95, 0x00005ee12e0f4b32 }}, {{ 0x00058280d4ddee6f, 0x000d4d77613aa81f, 0x000f907be4afaca5, 0x000c29388801007f, 0x0000bc59683be7a1 }, { 0x00091554cb1a8b9b, 0x0003d2f7c978c385, 0x0000b4cef8affa72, 0x000d48a2fdf1204c, 0x000070620062b926 }}, {{ 0x0000f9e4bb715381, 0x000b6d6a05bd5254, 0x000ac69b9680aff6, 0x000bd1ac948d5f09, 0x0000a232a16a1065 }, { 0x0008d30a61a7b345, 0x000b503f46ad2ec6, 0x000f5b10ef8d1b72, 0x00087007700f766c, 0x0000f4ea35a1072c }}, {{ 0x000b867e6badbcba, 0x000c7ea77b46a081, 0x0007abc1882dd01f, 0x000773c83cf5a647, 0x0000cbd5df06c8b8 }, { 0x000a7c66d6817ff2, 0x0001f141f60558ee, 0x000244c4de37c212, 0x000e31c8bcdbcdd6, 0x00001916c3d12b4a }}, {{ 0x000dfcf4d119ad85, 0x00033a504e99fd8c, 0x000179885fc958ac, 0x00057cde198a8dd1, 0x00006e59f62aab6a }, { 0x000f97af8853b43a, 0x00033b253758da79, 0x00034b31e858e0f4, 0x00058217ee643bb8, 0x0000da4a5c964eff }}, {{ 0x0001f37864c9d751, 0x0003720fbeee3f97, 0x000fd715a2986b25, 0x0005aa25c93e5348, 0x000088ce2f7480d0 }, { 0x000c9682db64cb9b, 0x00099e0943aa75e5, 0x00084ef974089e2f, 0x000037219a18c9c5, 0x000082104449d5cf }}, {{ 0x0007678cab68e47e, 0x000cea6b709c3de9, 0x00019e0e2c451e58, 0x0001cd6bb64a8426, 0x00005633f2cb7399 }, { 0x000c5ab10a85e889, 0x000f05f951a95c33, 0x000314a21afe0190, 0x000f06731dd35b16, 0x0000667bfe6e1cad }}, {{ 0x0000a02b0eaceafd, 0x00088c341dca5663, 0x000aa7c1ff9509d6, 0x0003070fb7de7fed, 0x00009716331f83e3 }, { 0x0005f449ec69c78b, 0x00092aa2fd3cf36d, 0x000709959bb35e00, 0x00081dc33d131954, 0x0000174691c29863 }}, {{ 0x00091481c1059a6a, 0x000b11b25fe531df, 0x00017108d4857909, 0x00043e61af979743, 0x00005c928c67b126 }, { 0x000f9f87695e4b85, 0x0005f65f8b05bc60, 0x000ef348b5716c43, 0x000905e3b1844e1c, 0x00004c192e0ee156 }}, {{ 0x000c992a8a0219ee, 0x000c3c038b27fe29, 0x000b0f0ad855471c, 0x00051edab63b6359, 0x000025a641ada563 }, { 0x00048d3f95b0f902, 0x0008d152a60aed16, 0x00047c320a49af15, 0x00049d79aeb089ca, 0x00008fe88effe77c }}, {{ 0x000de501a3cb5123, 0x00060a8e1add3f34, 0x000a017fa1a51172, 0x000dfb8dbf42c0c6, 0x000001a82938cb34 }, { 0x000025a2cad7b920, 0x0005c1f4b9a64bc7, 0x0002b4712a8e7257, 0x000cfbffba77f0ad, 0x000059630c29979e }}, {{ 0x000c477cc78dbf35, 0x0007dd1d1a8f4e7a, 0x0006c70d15b57029, 0x000612235f5b3da4, 0x0000dec5fdbedc4b }, { 0x0009b795f963ab82, 0x000f1d2a883239a8, 0x000642d3ed5e9773, 0x00073cd86e12572f, 0x00006777294aa397 }}, {{ 0x000ef0e314d85ff1, 0x00065f1b54398dc7, 0x0006c0fd0bc04f5e, 0x0000d10401890efd, 0x0000f8bc668d0ac4 }, { 0x0002c591e55172f8, 0x0006e31cc61dab32, 0x000dd1c0dc69ff57, 0x000c343394a39801, 0x00008f9576364d5c }}, {{ 0x000e02fc57543709, 0x0009a08de02a53e8, 0x000f4586f7004114, 0x000bd02662a6c060, 0x000038ad03da91a7 }, { 0x0003660ea088e386, 0x000f19573adb4ba8, 0x000c244a29655bb1, 0x000aae9a67b86122, 0x0000a46975ac7183 }}, {{ 0x00097b8de565ca26, 0x0006b0521ba473cd, 0x000e0559aab8550d, 0x000b275c0b6c50be, 0x00008c7a7b476844 }, { 0x000df7725c5e3459, 0x000e570ab3bbddbe, 0x000e37a00efe4bc1, 0x000e15ad93898aab, 0x0000dfe696962d4d }}, {{ 0x0006166b44b3b527, 0x000e8abe085116b3, 0x00055111e7cb7191, 0x0000aae2f04a4337, 0x0000b8cbd7d43a2f }, { 0x000af71e91ff6ddc, 0x000673cfd4b322cf, 0x0006bf828cbf933f, 0x0006d39eb726aa81, 0x0000f4fde56a46c2 }}, {{ 0x0002cadc98401f3b, 0x0006b40641fad989, 0x0007969748c19d4a, 0x000225edcb799591, 0x00004bb11b390d9e }, { 0x00095f7b90617d6a, 0x000b98b256534e4c, 0x0005bc35c509aeaa, 0x000e05b9b73e80ce, 0x000010012b3ad66e }}, {{ 0x0009cf84aa0fcd26, 0x0004a14d856ac253, 0x000d7282c920e466, 0x0003773f5441bd9d, 0x00002c3a08dedb4f }, { 0x00017edeb92c2909, 0x000a755b2aa95a02, 0x0009ec6039a6d8be, 0x00016624329e33f0, 0x0000c812d89efc16 }}, {{ 0x0005b9b9cd84c5c7, 0x000783583cbea55b, 0x000d065ea3a2d3f2, 0x00099a292c485ee4, 0x0000a2524bfd6d99 }, { 0x0008ca325a560d39, 0x000b58e4e9e8a506, 0x000af99fa8a3269d, 0x000da58c6462e907, 0x0000ea5c18d58fa5 }}, {{ 0x00060fff17c23588, 0x00035f213b5ba885, 0x0009dfdf0bac693d, 0x00084130860294c8, 0x0000c20857b9d557 }, { 0x000c2f31600cb009, 0x0007b87d67703743, 0x000d5e27c525487b, 0x000416cd9a373202, 0x000070a468d0a739 }}, {{ 0x000f684368d3db41, 0x000a8dd7b9520e80, 0x0001fb87f44c3d55, 0x000c0cf4cc078f9e, 0x0000fafd402c5e4a }, { 0x0009cd516968dccf, 0x000e6ed6247e7ef6, 0x0008cfa0acb86b14, 0x000bdd3c2b32d33a, 0x0000aa46051a8ae1 }}, {{ 0x000f0837e6eccb46, 0x000940f4b3234da4, 0x0005654f66d7528e, 0x0005930c7cf0b023, 0x0000ef0adfc93e80 }, { 0x00089a4060c4f953, 0x00022bb906f6e98b, 0x00040ec7a770d547, 0x0007a5c10253bb43, 0x00007cea8d76fea9 }}, {{ 0x000f5d57fd84b794, 0x000acc5b8cc037fb, 0x000ab4a8634a4c70, 0x000abb4b83d093a5, 0x0000a4275cfe559b }, { 0x000ef22458521286, 0x000430c8c3bef483, 0x00031b1871b237e4, 0x00018bcab23ac762, 0x00004ef2dd9f1303 }}, {{ 0x00081dcee597d414, 0x00087dac97e65165, 0x00006a1325b93f7a, 0x000a0d6498877936, 0x000087e6a262fd86 }, { 0x0009a34fc66e7cce, 0x00055918f483f148, 0x000c479481754c72, 0x000f76c426d2dddf, 0x00002d39a7634863 }}, {{ 0x0008653ffddba12a, 0x000cbb312e08ce5b, 0x0007ef8b72cc3850, 0x000f6fe05a80540b, 0x000001a887b97925 }, { 0x00059b30e1948bdc, 0x000ab8702b0b4c9b, 0x000ee52fe628f9ef, 0x0008038e52675261, 0x0000cae50b48aefe }}, {{ 0x000aee5ef0da9c40, 0x0005ea60200ec7db, 0x000850dfb43a4325, 0x000a1e7e0b6f4a3f, 0x00005fd883bfa016 }, { 0x000d4f59c8134ed7, 0x00093aae4c6cf389, 0x000633e73e4d5bf1, 0x0008679c6ab4cfe0, 0x00000083cf7bbfdc }}, {{ 0x00032363a7734ed2, 0x00081b151deb6adc, 0x0003ee6413a23cd6, 0x0001134e1812399a, 0x00001e7ebc657857 }, { 0x000b6f7d030cfaa8, 0x000a7bedc36c64d8, 0x00011c72315df52d, 0x0000f314a86c81e3, 0x0000b2a701f2e2ac }}, {{ 0x000d56d36a2b2bd9, 0x000140756faa38ab, 0x000bd5aee7eac178, 0x0009b5761a3790e6, 0x00007e4559f47050 }, { 0x0008c39768edb7d6, 0x0008349229a8aa9c, 0x00067cd254bfe89f, 0x000f379e6dcca8f4, 0x00007ea637445818 }}, {{ 0x0009ebbecd961518, 0x0004736523f2b367, 0x00031821d4ee4c8f, 0x000dc4b2b995c649, 0x00002214d933e9fa }, { 0x0007d928a6a9b4ac, 0x00091db79592f48f, 0x000a67afc0f21e06, 0x0004c6d3e67216a7, 0x0000a28afa8ce512 }}, {{ 0x000011b6acb767b5, 0x000cf17e991f600b, 0x000d796ff2879e7b, 0x0004986de2a91113, 0x0000f0d31fd49b4f }, { 0x00076430677f20c6, 0x000ef18045ec6135, 0x00016b9162a2f02b, 0x0000d9fde522d2d3, 0x0000d682877747b9 }}, {{ 0x00075b4a21968cc3, 0x000ad5d1c7193f0d, 0x0006648d3b6cc785, 0x0003a1cc7f0f32f4, 0x00007e378db65c00 }, { 0x0007387e1e912b73, 0x0007e7b342659d41, 0x00042db7b9710081, 0x000269f9de596ea3, 0x0000a3bf0865713d }}, {{ 0x000cca31c7a57625, 0x000ade949dee1686, 0x0002d160c071cd59, 0x0001de16a1ae0522, 0x0000da394a68f678 }, { 0x0007da93fd13da3f, 0x000971d9bc499082, 0x000cce082821a131, 0x0009544ac4a9b4a8, 0x000025d76c70fa80 }}, {{ 0x0005f1bfec0f543d, 0x0000f964821c8c54, 0x000d624a5608dadd, 0x0009ef3048de49de, 0x0000fc43c74c346b }, { 0x000087cdaa1179d9, 0x0002d2654b9df609, 0x000c18d43d897611, 0x00089848e5e4fdc3, 0x000036663c4320b0 }}, {{ 0x0009a7b853608cac, 0x00070238319ade44, 0x000a94e545a4d669, 0x000e28b05766f287, 0x0000f55f670cf4d3 }, { 0x0002971e277b213e, 0x000baa75cedadfd1, 0x00057b1b89ee3e92, 0x000d551958f56281, 0x0000b62941f52c86 }}, {{ 0x0002ad741cbec2f6, 0x000c096d0ff34fce, 0x00012f74fd700b35, 0x000d2324d20824de, 0x00005c4e2951824d }, { 0x00078a169ffa86e9, 0x000bddf54043ccfa, 0x000b30b9fc13145c, 0x00042a1f016ff479, 0x00009b49c42140e5 }}, {{ 0x000e5064503a3e24, 0x000634699c930e9d, 0x00076b90b3559e70, 0x000e6519f1d33e85, 0x00006cd16fbc642b }, { 0x000249ef84233f4a, 0x0001300caf3155ed, 0x000bea29f7db9bad, 0x000cbb7db672d66a, 0x0000fcd7af334203 }}, {{ 0x0004b29cdde6a208, 0x000ced473978fe39, 0x0001e09863c37a8f, 0x0003dc7e9cc4e454, 0x0000cd9ff54a2771 }, { 0x000d2de14cb33c91, 0x0007bff9bc7edf24, 0x000d86ac84a73116, 0x000ae7a488ac236f, 0x00008575be2d1315 }}, {{ 0x0004d1f3d3a5e8cd, 0x000eea760430e540, 0x0006d56095d81a1d, 0x000aecf5910a2d0d, 0x0000183d1a538a31 }, { 0x000c80b505a3cfa0, 0x00084738a0983cd2, 0x00089c0315b5fc22, 0x000d5e99528e25b3, 0x0000e560b7c69fa3 }}, {{ 0x000d37c5b1792718, 0x00023714a953beb9, 0x000e790b2245754f, 0x000aecf22502e223, 0x0000c74bd4088fe8 }, { 0x000016a8607ff0a0, 0x0004d70f8330bc73, 0x000645907f288125, 0x000de2cc2139850e, 0x00005677b1f28c7f }}, {{ 0x000e658aedcda8bb, 0x00031644cd8f64c3, 0x000fe937f063f6ea, 0x0001e975658a2d78, 0x0000049c304fd752 }, { 0x000473ffef5b241b, 0x000792e05da59eb6, 0x0002a9683732b03d, 0x0000a6487ba3d60a, 0x00005d72e137e219 }}, }, { /* digit=28 (1,2,..,64)*(2^{196})*G */ {{ 0x00099ee566eb922a, 0x000364f692ac542f, 0x000028dcac6c9771, 0x00018cfbdf079ffe, 0x0000610be982fc2a }, { 0x00013889ee80e815, 0x000511fd62191997, 0x000663545a2e0935, 0x0008cc4048c883bc, 0x00000920149ca0bb }}, {{ 0x000eee0c0ea6e1a4, 0x0009b8f81a1b3bed, 0x0004ef395891f049, 0x000e351f74f3ce14, 0x000069aac489bd81 }, { 0x00027729a694a1ff, 0x000aec0d39e25c35, 0x000071f076d9e952, 0x0002d5b584061982, 0x0000a6863991eccd }}, {{ 0x0001ad919aac7231, 0x000d837b1b76ba6f, 0x00045b7295421df9, 0x000677d0a1a2eab8, 0x0000c06c35fd7a6d }, { 0x000314874f18d1ae, 0x00031b807ea7b0ef, 0x000e4bc5643a1ce2, 0x0009b5aabedf5496, 0x00007faef00cb014 }}, {{ 0x000747ea0bede08a, 0x000e0753f73f449b, 0x0007d5fd126e01d1, 0x000e0524d1d1c94f, 0x0000db80899bb94d }, { 0x000c10697e01e74f, 0x00074fe228d291e6, 0x0004d7b0c0585031, 0x000c5761635b804b, 0x0000e6909f3f3acf }}, {{ 0x000a8f2439972c6b, 0x000d88f0876fd4e6, 0x00071943cf4a2c61, 0x000dcc9cb45f0c30, 0x0000274cda09b319 }, { 0x0004426efde75793, 0x000b01b65ccde7b6, 0x0007c3a4fb720a13, 0x000dcf1d741e2cd1, 0x0000483cddf39166 }}, {{ 0x000d32fba5127c0b, 0x0008344fc94dea3f, 0x000edda3a50b098e, 0x0009531ef34c8cdb, 0x00009ea6e5479af1 }, { 0x0003173f9743bb5a, 0x00036f6795dcfb75, 0x000330414c181516, 0x0006467c0fef01b0, 0x0000608f1137cc86 }}, {{ 0x000731021c804f19, 0x000272aba16f73bc, 0x0003c5c8b7dfaace, 0x0001fdebf2fb3101, 0x000060e66ffcf1c4 }, { 0x00051f55a60c6b7d, 0x000ca244fee99d47, 0x000685a66c4490cf, 0x0007f1df74bca48b, 0x0000e008421c6eaf }}, {{ 0x0008949a50ad4589, 0x0009c1acb452fdbb, 0x0004985e6bffc0ea, 0x000efbfd931ee696, 0x0000aba564d3b7e5 }, { 0x0007a12f75fecfe0, 0x000a3263c88f3bd1, 0x0000c37c6a1321bb, 0x00004ff03ab147c3, 0x00003bd493c68746 }}, {{ 0x000b70130c3e980c, 0x0006d6d36cf69db9, 0x0008baf6f90bfcc1, 0x0006f018e1219eee, 0x000018a15b3aeb3b }, { 0x0007bfbcdfd435df, 0x00045620ae18e0e8, 0x0002bf00e958626d, 0x000f8d1d42021a62, 0x00007271917a37f1 }}, {{ 0x000c923aa6870f8d, 0x0002805cdd61d649, 0x000c2c2f4db1707b, 0x00004e8158c7a53f, 0x00007b90d120c88f }, { 0x000555917e796337, 0x000d2cb5c18871f5, 0x00081e5e3af648e3, 0x0006e9dc47d53bec, 0x0000007d33f08184 }}, {{ 0x0009ea61f1bde96d, 0x0004eda548f5a0e4, 0x0009f1d559f00cff, 0x0008e42c31910eab, 0x00004e2256a193b8 }, { 0x0004b491b0ca83fb, 0x00059784f7c39221, 0x000d0c11fd3eade1, 0x000f39fb995d337c, 0x0000591ec14b3514 }}, {{ 0x000f450138039993, 0x00028e028e3fe894, 0x00047665bfb376d3, 0x000e4be40e7e1fee, 0x000057339c7f6d65 }, { 0x000251437e2a615a, 0x000058495cd81854, 0x00018b61a205b101, 0x000fd13e474be0ba, 0x0000b796f513feb2 }}, {{ 0x0004e39da416895e, 0x00014a0ac6203668, 0x000c31f1f5a051e4, 0x0006217b94be3fb9, 0x0000b0003105438b }, { 0x0005627d144873ff, 0x0001590b38f04092, 0x000306c8616def58, 0x0001ca3d80295194, 0x0000cebe7a096ec9 }}, {{ 0x000f637e4fd3515f, 0x000f1aa658a6d877, 0x00075038f4d59b63, 0x00035e9c91405aaa, 0x0000302534f4de89 }, { 0x000f15b373895ff9, 0x0002e7614ffad2c7, 0x000d3be5b41e6f6a, 0x0002f9afce58fb1b, 0x0000c8215fd1b036 }}, {{ 0x0008d69d5541959a, 0x00013d2d842ca726, 0x0000d602c5aff83f, 0x0006b2414a71e439, 0x00004b346f996925 }, { 0x0007ac7bdebe7e5f, 0x000f46737183bcfe, 0x000a4bc46418e5e0, 0x00093f35b7152b7b, 0x0000aba65a5ecc00 }}, {{ 0x00032811a7abd874, 0x000db7881fdad909, 0x00057a04e50379b8, 0x0002cd9e5cf638f5, 0x0000f7d1bc229820 }, { 0x000dd099becd5a2a, 0x00089309bbd11ff0, 0x000fa633afb561a6, 0x000f7a86676108a6, 0x0000803fa54a21da }}, {{ 0x000c23f829f27693, 0x00017aaabe329866, 0x0009e4b1a3fd664f, 0x000b9e0050fe9dd2, 0x0000a20ae7baca9a }, { 0x0009a25a18798042, 0x000e0180b136a798, 0x000dedffaf7dd73a, 0x0003b0ba67e2174d, 0x0000f25ede8ca147 }}, {{ 0x000ca5bdc1609c2b, 0x000777ec11ee01d3, 0x000aa94b503a968c, 0x000505e3cf900553, 0x0000383c90f106a2 }, { 0x000b715a6d47b75e, 0x000b73797eada9f1, 0x0002f4b407c350c0, 0x000850bb359c50ab, 0x0000b660a6466bea }}, {{ 0x000adfe0af71e0c3, 0x00011766ae06e0be, 0x000db26301b0323d, 0x000d19720cdd7888, 0x00002c963a41c4e4 }, { 0x0007e4b0dd7b445f, 0x000f3a9699500937, 0x000aba9adc633558, 0x0009b296a3525d9c, 0x00009fbb8308b6ec }}, {{ 0x0001610588bce8e4, 0x000ce0a517d7061b, 0x0002baccf0fa5475, 0x000de186777fe343, 0x00000b73f8bc3f10 }, { 0x0006327dec759e0e, 0x00076cad9c4ddbe2, 0x000c1742cdf5be97, 0x00048ba94b3164f1, 0x000038569d7d4e4c }}, {{ 0x000aeebb5d055643, 0x00083de97b5cd328, 0x000e2afe337097f3, 0x0008894fe40835da, 0x00006140cad890d4 }, { 0x00048990ad4be3f7, 0x00038b75b8ee9ecc, 0x000cc9b3106b05f0, 0x00010490ed7a17bd, 0x0000a0c831b76ce3 }}, {{ 0x000b19131435469c, 0x000e12a2199e347e, 0x00053f20cd3d5899, 0x00027b5dcbee7555, 0x0000ffa0bf10725c }, { 0x000a33a79b0335bc, 0x000a50d37d341eda, 0x0000aca174906343, 0x0001371ba434fbb4, 0x00002e3e4d934cd4 }}, {{ 0x00031af02f504322, 0x0002e54e4bd6d3d2, 0x0004379a61a0f9b9, 0x000ffb1a609540f0, 0x00006ab7f4c255f8 }, { 0x000c8be793b491d3, 0x000b9ac0992c163c, 0x0000bc025420deb3, 0x000fa538c1fef8e7, 0x0000930f5d791209 }}, {{ 0x000a5e00b2f8398a, 0x000f1aec61c3855c, 0x000c8e63fc8830ec, 0x000d209b8ebff429, 0x00000550b4100d93 }, { 0x000174306911bdd3, 0x0002e17c3fed8b79, 0x0009f027d18dbd75, 0x00051ea54d49ac6f, 0x000037ee2449542a }}, {{ 0x000db067bf6ab9fa, 0x0009e1eaff2ef812, 0x0004fa6846c16bc5, 0x00070ae92c3654d3, 0x0000e7bed9e284b0 }, { 0x0007c60de3cf3529, 0x0007586703dcc974, 0x0007996dd4321892, 0x00065515ce66f9b3, 0x000045556034c314 }}, {{ 0x000ee790cfd235d5, 0x0008439d860f1b25, 0x000c9705bc7a9c0a, 0x00080e7bd3e9a1db, 0x000066b271a5cef7 }, { 0x0005613245b1f9b0, 0x00084b15bdaf9bbe, 0x0006674163ab3eae, 0x00094878c02cedda, 0x0000e912b227e619 }}, {{ 0x0009176f1bf4b9dc, 0x00046cc76b23a502, 0x000ce154b2b21706, 0x00010e7f54a2793a, 0x00007203d4f46495 }, { 0x000438b216a5a2bb, 0x000a6874f6f59eb5, 0x000937a3b3776086, 0x00040490286e9bca, 0x0000d17e13cdbcb2 }}, {{ 0x0005ab800dbb99e9, 0x0001d3c7672765ab, 0x00034f9c39b14ed0, 0x00017bd3337a3ce6, 0x00006e48af02badd }, { 0x000ed04363ca7756, 0x000e95911a5acd6a, 0x0006974fcd00271e, 0x0001ecb0abaee615, 0x0000ef5280b8e5db }}, {{ 0x0002ace7a063fccf, 0x000ae1ca4a82b765, 0x000ea0d384496b84, 0x000df9cb55586960, 0x00008b8c0663e8a5 }, { 0x000afe4322af8875, 0x0000118cbbc9b701, 0x000a454e62bf1e10, 0x000356c334f06fd5, 0x000087253946a7be }}, {{ 0x0009b42e68963555, 0x000d7a6c44b2c6c4, 0x0008c5444f9610d7, 0x000340e77ab72679, 0x0000087d908b7398 }, { 0x000d2878a8e58f15, 0x0002fc3cea0b1760, 0x0007bdfe18d92915, 0x0002b88cb53a8ddf, 0x0000dccc4d1142d6 }}, {{ 0x000803fc21b1eff9, 0x0003cd5d019b6a39, 0x000da86b222452c9, 0x00067c811bb5cf88, 0x000099bb7d29f4a9 }, { 0x000469591564f145, 0x000d79ec07764a90, 0x000eb2f2773fea31, 0x000f584ded93286e, 0x0000a5e431316829 }}, {{ 0x0002ede0e2398f58, 0x000858a58d6cd461, 0x00057b7853efdb37, 0x0008c6b289cb633b, 0x0000c7e7d1c765be }, { 0x0009e66e59813ff9, 0x000d162065a6f4f9, 0x000ccdd7da21b1ec, 0x00007f41cc3a47ec, 0x00006d5b783c2d8e }}, {{ 0x000ff6ea2132c1aa, 0x0009aca63d0ff123, 0x00047619b63e3c43, 0x000ebd147e5efc78, 0x0000e1e9f3d79049 }, { 0x000b88bb8cfbac0c, 0x0006d1bf21db8b7e, 0x0000ec5079d8d077, 0x0009fcead7dac70b, 0x0000f978502a906d }}, {{ 0x000d9e8a3ff2c9a2, 0x00092b4dfdbeb1be, 0x0001c74fc3aad1fc, 0x00088a62122f5ca7, 0x0000f11570bb28f3 }, { 0x00061bd711a3d136, 0x000f6b1b961f49a5, 0x000124e4bf5ef7ad, 0x0007f446d7fee2ec, 0x00002e82c2e6427e }}, {{ 0x0000ba9d0379c1f5, 0x000a7cc320bbcaff, 0x000eee634788d256, 0x000e6fc28568434c, 0x00003ef3f9080a95 }, { 0x0008117623d9511e, 0x000220432ff9f60d, 0x0005ea4c590f9a09, 0x000762eef3dd8e4b, 0x0000d0f362b6f269 }}, {{ 0x0007df2ca0800f08, 0x0002076f51fe76eb, 0x000b59f6f8e8b673, 0x000134f188a6811c, 0x00006d8c2c59c4c6 }, { 0x00047ed447b1ad6a, 0x000e452dd7b205bb, 0x000793240fcc896f, 0x000fba748b695947, 0x0000bc03136d4c3d }}, {{ 0x000c521308e5a687, 0x00011b904c9d9bfb, 0x00005f271d3f34ca, 0x000785d61661e288, 0x000077daf5dd5dca }, { 0x000d465b18f0dbea, 0x000b6fc2477de506, 0x000c1076f6d6d82d, 0x0004d5f05d80bb41, 0x0000b02bf176d362 }}, {{ 0x000288573948f643, 0x000b030fb6840fd2, 0x000411798f8ece00, 0x000bf71f8faaeb21, 0x000084d5f1bed683 }, { 0x000b394dafddac9a, 0x0009c7c7bc467dfe, 0x0002ed0984ca7407, 0x0003d7aa6926562e, 0x000088d23eb26432 }}, {{ 0x0004b74cc6bc1151, 0x00094d211c0be981, 0x00016c97349e82d9, 0x0001a7d1cb1e6ed1, 0x0000a0c06a8af629 }, { 0x000cbac448c5b98a, 0x00087868c060985e, 0x000d4102bb339e15, 0x0004fb8ca071047d, 0x0000652742014308 }}, {{ 0x0003ca782157f884, 0x0004ce2ebf3232f7, 0x000e515fb6bc3716, 0x000bcdbdbfff80f9, 0x00003291c8c0121d }, { 0x000f24a939bc6d67, 0x00079a0e6251b462, 0x000c1ce8e9f3b13f, 0x000f03a9a89bc6b5, 0x000034c1818b3d4c }}, {{ 0x00027c1c2e5d8f7c, 0x0000246766561b79, 0x00057c5415fc3c25, 0x000fe9c65736600e, 0x00002dd1b7dc8305 }, { 0x000cdd998788c6f5, 0x0002e370cc5df696, 0x00019cf8b021a08d, 0x00028e62799b37c0, 0x0000aee1d95fb4e2 }}, {{ 0x0004274408c7cb95, 0x0007431390420d28, 0x000b855cab9ba1b9, 0x0006e19ad299c40a, 0x00009b7daa386fe7 }, { 0x00051fddc7f82d4e, 0x000c1b991a711a0c, 0x0007da32cd4f739f, 0x0000f20d6461592c, 0x00002ee7a072ece2 }}, {{ 0x000bcde201ec9e56, 0x00068b6da50d5311, 0x000d8ad9d7d8a81c, 0x000ad8689521b840, 0x00004b23d5891c53 }, { 0x000e61d34d4d78fc, 0x000ab8b3b76a59a8, 0x000d791746cea6ae, 0x00018f11cf84841c, 0x000090aaea3d7172 }}, {{ 0x000e7ba65e352870, 0x00054515541b8923, 0x0001be21f7f5e835, 0x00096f10db186ee4, 0x0000fd944bfe00a0 }, { 0x0006f4ce31269aef, 0x000897aa83694867, 0x000717c0ec22773f, 0x000ad2cc309f9dab, 0x0000350aa14102af }}, {{ 0x000ff862f1ec19ab, 0x00055cff4f066b52, 0x000316254cd0bce0, 0x0001eee9889ab514, 0x0000f50054e6e5b7 }, { 0x0001743d0a1819e9, 0x0001085b05556e3e, 0x000d52f2cb14146f, 0x000ac4eeacd96058, 0x0000e5b40fed6cd5 }}, {{ 0x000d1e0148639a3f, 0x00033e27eb37726e, 0x000d27639eef0363, 0x0005a6b79f7fa264, 0x00006a16397995e2 }, { 0x0000ad13cee1fbfd, 0x000fc7982e7abe2a, 0x0001a54920299425, 0x0003bc23a19eedc7, 0x00001d27e9fe8f7f }}, {{ 0x00045446dee19896, 0x0003f241c0e651a2, 0x0009de79db9fb24b, 0x00019e8caab1a6e2, 0x000018a4f366b869 }, { 0x00075841e5ee98b0, 0x0007a2156c07613a, 0x000e4ccf12b26b49, 0x00064594643deafc, 0x0000c457c3bae579 }}, {{ 0x000e4bf888b90c57, 0x0004f777b0ac93d1, 0x000d5aa9e84f32ca, 0x000e8f22ba6e37b0, 0x0000c2bfd71f0dbd }, { 0x00029438c4942ce8, 0x00044e04df0ba2b4, 0x000d0dcdfb573987, 0x0007fc420935d5cf, 0x0000d2dbc8e26eee }}, {{ 0x0002e6bead7a7f69, 0x000d2c9049d33fa6, 0x000a3188a951a288, 0x000226da358b82dd, 0x000075c3d6d80aed }, { 0x0006a933d8e7223f, 0x000590fde46c58c0, 0x0009631fa3e61563, 0x00058f6eca7f6937, 0x0000e503ce844e9c }}, {{ 0x000ca3f44a175048, 0x000c69b077ff55dc, 0x0007ee82f2366b2b, 0x0004c6d4f5397779, 0x000038a3ff5c2a06 }, { 0x00093eed830e7f4f, 0x0000d87a07eda0fc, 0x000f34251345035d, 0x000668b72c138bcc, 0x00000099d6e25005 }}, {{ 0x0009915109fb7643, 0x0006e574d0b75c00, 0x000259f4b65201c7, 0x00004e9169716eb4, 0x00000af81e525286 }, { 0x0003c7b8c6ede208, 0x000a1285cca6c3bc, 0x0009713e103947e7, 0x0002278c4b25f7d1, 0x0000e315b9cc5975 }}, {{ 0x0008f732f82265f4, 0x000243c5a1f8e24e, 0x0009b4db22f81d33, 0x000196ea6fdb118f, 0x000088f3204c98a0 }, { 0x00032a76c6083b31, 0x000fc910be786ab0, 0x000f079b2a2f4a0e, 0x000eac5945d32ade, 0x00004fa0648f108e }}, {{ 0x000ceb151b607fe0, 0x000b1a3ebeb15447, 0x000bc1ec25a82383, 0x000ecd8b344b7b88, 0x00002db5e0795ec4 }, { 0x000e9e1a3e4dbbe7, 0x0007fd05bc1e6a8e, 0x000a1a70ed816faf, 0x000d78e89ec70cec, 0x00003b862411af2f }}, {{ 0x000a22d40d38f45d, 0x000ad84745b98d25, 0x0000cb34193377df, 0x000202fb9da429a2, 0x000043d54875e04c }, { 0x0009c0bb328b4510, 0x000a9e570e8a4cea, 0x000af4ed4846b07f, 0x000c6c47ebfd1445, 0x000063d3c380d98e }}, {{ 0x0008653ca70dc05b, 0x000f2600a4c3f6b0, 0x000923b0b29d901b, 0x00087efccbdfaad7, 0x0000bcd3b0c08f71 }, { 0x000be1fdf72ebf6f, 0x0001824538873a39, 0x000d10ffc9f0003b, 0x00023c3ba09299e5, 0x0000ad9a8d1c6f7f }}, {{ 0x0004957d29e4f3e6, 0x00077595758b11cd, 0x0002f3cfd216bfa7, 0x00043ae470b85289, 0x000035c69d5fca6d }, { 0x000e1c2610168c00, 0x0004363646559b01, 0x000c2b5c647e66bc, 0x0004254a9f4a8273, 0x0000abe6b046a81e }}, {{ 0x0006133b9250e9e5, 0x000fd28cf6a4a81c, 0x000255354be09066, 0x000bfdc5b1fa3b6a, 0x0000d8a9469a7e74 }, { 0x000ceecdb6a205f7, 0x000de5c9dffa978f, 0x000c624a983be8bf, 0x0002cbe2fba1d1c1, 0x0000bd9e811e29d5 }}, {{ 0x0009e1cce6add388, 0x000825f10f2b8f5d, 0x000e826a627d023e, 0x000263a13c83a6cd, 0x0000bb21395fab4b }, { 0x000121696926c8fb, 0x000c17caba7e3721, 0x0008ceb03971e6c8, 0x0007d1de5fcdc74c, 0x0000c71b97399710 }}, {{ 0x0001acfdfce2e995, 0x0000323f6021c5dd, 0x00041e444626f1df, 0x000e37e96880d5e8, 0x0000877660535d8a }, { 0x0005ab89623c630f, 0x00055e8bbb66840f, 0x000d7d09faf7745e, 0x000d5d9ecf7f4301, 0x0000fb09525a4469 }}, {{ 0x0005b6c3c5a8fbdb, 0x0009e740e9547505, 0x00080f430f00f4c1, 0x00089482e0121de8, 0x00003c819e927d30 }, { 0x000f3e226365392e, 0x000b747519cb9fb2, 0x000f54ea3daa561a, 0x000484b1af134019, 0x00006b90423d137b }}, {{ 0x00062246dec7aa4b, 0x000e51773d273b06, 0x000610ffa8bbeae1, 0x000a69139ccd2107, 0x00003c66d4c6b3ee }, { 0x000b65168903af15, 0x0003dfa6b83c0d12, 0x00076c84b6bd8c9c, 0x000e810e4a72df26, 0x0000ab60b5424485 }}, {{ 0x00088043d808618d, 0x0000e7902f345331, 0x0003f3f77d7057e6, 0x000f1ef785e354c1, 0x000037a49cbea99f }, { 0x00040c9ad6afca4a, 0x000e5428c1d50261, 0x00067fc80fd4ebd6, 0x0008d7a502e0c8a2, 0x0000c659782ab4fa }}, {{ 0x000ce3f19260a150, 0x0005a4225ac0f182, 0x000ad7ee0a60bfc6, 0x0000ef824f7b1295, 0x000023483fef7f44 }, { 0x0008e821b9993c9c, 0x00081558f2e1b72b, 0x00057742808a033d, 0x00081f954fe93228, 0x00002729d121fb3b }}, {{ 0x000aebfa4044443e, 0x000fabe67e573e06, 0x0008d598ca0bb6e3, 0x0007d84c505891db, 0x00008b6a89573352 }, { 0x000fd835db9f7005, 0x000d7e9e56e55c19, 0x00028cd210f50d2c, 0x000afe3eb7148ced, 0x0000282da8971416 }}, }, { /* digit=29 (1,2,..,64)*(2^{203})*G */ {{ 0x0009d7b51caacc1c, 0x0008509081e9387c, 0x0006c2bba30bf8a1, 0x000749415fb9780d, 0x000016b6886a163a }, { 0x0009d9971a12e8dd, 0x000f041d6d9f6711, 0x000897c914fde7c4, 0x00037415fba6c1e2, 0x000044ff79be19da }}, {{ 0x000a38783edbf56a, 0x0008a62060b5f619, 0x0003e197df84183c, 0x000ec5565a56f46b, 0x00003d764abc2d6b }, { 0x000a0edc3fc096b3, 0x00080a9da710718f, 0x000633fc0eb6b9c6, 0x000931e875a77998, 0x000072910f080d6c }}, {{ 0x000f379672eac03b, 0x000fb216a31e09bd, 0x000ce1fd77c2b332, 0x000e09452de89e44, 0x0000aa34a9ecfe61 }, { 0x000697c8bf759643, 0x0000e0a2591d61b1, 0x000741c37bbc5394, 0x000923c7779aa87d, 0x000040557c30456f }}, {{ 0x000c351b873ccd50, 0x000f849cb198ac73, 0x000cd2f12adddfbb, 0x00052b678a884a93, 0x00006d2e4199685e }, { 0x000ba6f9e2ce488e, 0x000619fe2c4b44b8, 0x0006a77f7f29e16a, 0x000b9984a580f6c4, 0x0000c4fae9993e3c }}, {{ 0x0003c99a73f9f984, 0x000135f8fb547385, 0x0007d3fa5060028e, 0x00050845a3516078, 0x00000a2971005ebd }, { 0x0009a4598291f660, 0x000fbe05b81c51b3, 0x00088463f934f561, 0x00056b9a7925bafa, 0x000056cef7017b16 }}, {{ 0x00043775095179f6, 0x00074b65eb03c0ee, 0x00038e84cad4f821, 0x000c08ad2f19b795, 0x0000a815addc931c }, { 0x000a6a2475d15354, 0x000e250bb3ee8a3e, 0x000bc6c7e2e9f012, 0x00084e0f675eb14f, 0x0000728fb5f890a9 }}, {{ 0x00058b5fe31ed9d4, 0x00029950f8d67583, 0x00010b00a7fa7e99, 0x000085e21cb84e10, 0x00000fa25fc01a87 }, { 0x0003e86e791375d2, 0x000a5ec95f40e756, 0x0000d98b855d088f, 0x000a5c966f015545, 0x0000404ce330eea9 }}, {{ 0x00079fb23be5ff7d, 0x000b7abd3c095f18, 0x000e5d17bb3553d9, 0x0003eec8404b261b, 0x00004c7b8e343501 }, { 0x000f0ac52ff88cf7, 0x0007572dfd754907, 0x0004e2b22c9118c3, 0x000d179073a97d08, 0x0000d6bca24f52c6 }}, {{ 0x0003c66b47990520, 0x000abc46eb564d4c, 0x000bda90a2e18e10, 0x000f0dd5d8d6c752, 0x00005bcd40fc8105 }, { 0x0008ac0b779ee6a7, 0x0000d010f87de563, 0x000f8e19f83df780, 0x000692242ce62c06, 0x00009114b5e7e8df }}, {{ 0x00062d8c5230f8f7, 0x00029ee4b049136e, 0x00014f3cb9c19a54, 0x000e78a288b63bf1, 0x0000675ced19a43f }, { 0x0004ac0245017d70, 0x000da67379e7896c, 0x000206517d607078, 0x000c44a6ab25237a, 0x0000c32d492b5336 }}, {{ 0x000eff66bf542bac, 0x000fc6921fea4ca8, 0x000764e07402005f, 0x0003cb3afd36d081, 0x000058cf051c60a0 }, { 0x00069fb9dd0bb00e, 0x000a0e70b57235e6, 0x00009a66b74e0c7f, 0x0004cceb0ee3c39b, 0x000096f6178742b5 }}, {{ 0x000e008c5bcdd3fe, 0x00003fb319d76820, 0x0008fc97a392e47d, 0x0008db544b029312, 0x00005611953b5d34 }, { 0x000d3a1aadc08c32, 0x000ab1c0278ca331, 0x0006c870390417da, 0x0008770cf666f76a, 0x0000e48921cecb9f }}, {{ 0x000a418ea93670f8, 0x0002d3173faa4851, 0x000fa665d9cf986c, 0x000a06e7dc8ee6c4, 0x000003f9ec391ff3 }, { 0x0001e3de1002180f, 0x000ae9251f73971d, 0x0002084afa8fd8f9, 0x00025f4193e4b3c8, 0x0000beca7924e4e5 }}, {{ 0x0000ffc1739db82e, 0x000d6ff50f75f9cd, 0x0002ad7569ae9e9d, 0x000e1e3181d8eddf, 0x0000eddba8e1699e }, { 0x00002aac66c37326, 0x000c6e3037d90f29, 0x0005d02ad905e85e, 0x000d947afe3f307d, 0x00000675780cc1ba }}, {{ 0x00081be1ba9dae65, 0x00082bf94cdfadef, 0x000c87aaf47a18f3, 0x0004cfef86c97e1e, 0x0000bf0bbd559305 }, { 0x00049a602bc81752, 0x00013e4d14b4206e, 0x000dab067b39bec0, 0x00068756cbecc2e0, 0x00007986052ab4e9 }}, {{ 0x000709def8c8c5c7, 0x0004c1a567193ec5, 0x000a8eed0812adee, 0x0005924ddaf3c305, 0x00002a0743a5403a }, { 0x000f431d23ed5fa0, 0x000f9830eb2b6692, 0x000b5818530569a5, 0x000050c164d80ce1, 0x0000cf41a7008416 }}, {{ 0x000bead645c0c39c, 0x00076a6f9294dd32, 0x000f6f60373224a4, 0x00024945cb448d01, 0x0000848887261b44 }, { 0x000041af6242087e, 0x000c54d84fd8b072, 0x000fd7682f82c87c, 0x0004d3f85537b983, 0x0000ee0f932db6ad }}, {{ 0x0003d2646d5d67ea, 0x0009d4cb940c71e3, 0x0009a78ce6cd30ea, 0x000b333c3211935a, 0x00008dbdca8a24d2 }, { 0x0003929f2c8f6353, 0x000834bef9114044, 0x000a56a9bfc7874d, 0x000d1d9789d1f25e, 0x0000546cc2b4beba }}, {{ 0x0001b0310c8f78fa, 0x0006c67c7196e295, 0x000041e18d3c15ec, 0x00067d36e7992c2f, 0x0000cbe87245b10f }, { 0x000d6e5a5a506ca1, 0x000e9cfdd9f22cb0, 0x0001a8177b29d312, 0x000d4c288bb1d81a, 0x0000a9d05bcc9b3b }}, {{ 0x000d04e18964b4be, 0x000696638235d4e4, 0x0006fc69510f82cc, 0x000629dc81c62bd6, 0x0000d69b284282da }, { 0x000f0e6f4ef7aeaf, 0x000670185a8068c5, 0x000133a42b363af9, 0x0005edb3bdb58e4e, 0x00008a81469b37cf }}, {{ 0x000d487b80c0f188, 0x0000e8469ed23707, 0x000c8b2972a54721, 0x000aad30534dc30b, 0x0000077e05f5c7bb }, { 0x0008c4e13b06dfc6, 0x000f437dd0e71799, 0x00011b3f36d639a9, 0x00094b5a545f8019, 0x0000cc8a58f51d91 }}, {{ 0x0003ff120d6b43b6, 0x00080e6e82c9f9e4, 0x000c7f3afe366902, 0x000473605711db87, 0x0000b79687b6563f }, { 0x000c63a68310f640, 0x000492fae77779bc, 0x0008c078f8ffc2c7, 0x000cf71bcf0fe0cc, 0x0000f50ef21963e0 }}, {{ 0x0007fcd27a7b8803, 0x000b70c09dbe19a1, 0x000d535fa1484c62, 0x0005d09302f3585a, 0x000034ee43c2d08f }, { 0x000ec3df2b85cbb5, 0x000983410b3d5a5a, 0x00017bd6edc62975, 0x0009ead4209c107d, 0x00006cece29a740e }}, {{ 0x000eb585fc03a598, 0x000fab73f894ae03, 0x000578a992d2287e, 0x000ae32d0f59df3e, 0x00009041a752d68b }, { 0x000f18757657a10e, 0x000fe8632c7f717e, 0x000ac07bc9d5c038, 0x000db43d2eb8c795, 0x0000beb76ad83f9e }}, {{ 0x000f678f4d369698, 0x00025b20389168b6, 0x00087aefedb6701e, 0x000dd9882c4ecd25, 0x00001a019280de1e }, { 0x0006b6c517470dd7, 0x0003acf65e58dd88, 0x000e4d4bfbb60e27, 0x00029ea4cd53b4e3, 0x0000c0f835501259 }}, {{ 0x000e54523f9dd595, 0x000453eb38dff6f0, 0x0002dc0f19a88a5f, 0x00007a2f8be012c5, 0x00001ab8ae664cc4 }, { 0x0008e19b0ec8804e, 0x0006636036a05d8c, 0x000e55b225f11a9e, 0x00001cfdf83e3cdf, 0x0000493f71b10088 }}, {{ 0x000a39687fe60d79, 0x0001b3fb569a5fec, 0x000409fac4f5e2bf, 0x000df2700ad0090d, 0x00006a9ddd1bcbe4 }, { 0x0005efb775a4c718, 0x000f5f765959d77e, 0x0007b6a6922442f3, 0x0007a3c5139d7821, 0x00007d9756c3730d }}, {{ 0x00063dec3e3e2558, 0x000b9a4e822f0d08, 0x0000d44918ba007a, 0x000a12a0fbc647ad, 0x00002a7318c6f712 }, { 0x00063dde65759c1b, 0x000423af017bfc7f, 0x0008a12da3c38c63, 0x00020f23b2005443, 0x00007385de06d196 }}, {{ 0x000223802a112a4d, 0x000a2b32a4c94e9b, 0x000de4d4a76011b1, 0x000d92c3dafbff0f, 0x000052dfb56d8723 }, { 0x0002e8a4369887b3, 0x0008b578ec3fecad, 0x00036655cc1ccce8, 0x000df81c406c3831, 0x000054665660b4e3 }}, {{ 0x000668270095818c, 0x00004525e9ca895c, 0x000dd0b84bde7efc, 0x00044e95c2f4dd31, 0x00005870893f8e51 }, { 0x00050bf75458d456, 0x00020a30cf43895a, 0x000fdeb71226c646, 0x00064b80ea9d604d, 0x0000539558e1b50d }}, {{ 0x00090b3defe902aa, 0x00013def6a702510, 0x000b335f737a1d94, 0x000cddd62548b801, 0x00003e17f46314bb }, { 0x0009b0f6c59961be, 0x0000d8969cb91584, 0x00044fadd77dee87, 0x000783df544a9074, 0x0000f348045d2e71 }}, {{ 0x00037dccb38225c9, 0x000f315adf7cccff, 0x0005ec2414fcf3b3, 0x00075f87e81a3e5d, 0x0000f61ae1e090a2 }, { 0x00009fa4f71b333a, 0x0000e73907fba12d, 0x00097997840dbf32, 0x000506cc535daa6d, 0x0000b54ff864cf47 }}, {{ 0x000f979bec99a237, 0x00067c9aeb19a362, 0x000e982823c7ceec, 0x00020c3a6d913f1c, 0x0000fee386354fc8 }, { 0x000f2edcdad2a280, 0x0001d0f359679ec3, 0x000cc86c2785e2f4, 0x000583870ebcf523, 0x00007790dea32d3e }}, {{ 0x0001f3e3242b67c2, 0x00037a76f568431c, 0x000b4104a667e1fd, 0x000a399d5f848c27, 0x00000c5d8c8cbcfa }, { 0x000519b637651d15, 0x0001c9c26c185ddb, 0x00079f55548ce1cc, 0x0006288576d85b7d, 0x00007ef27cc4babf }}, {{ 0x000f6557c2e6a3cf, 0x00094a9ab87d59c5, 0x0002da65524e84bd, 0x000d3697bff9f58c, 0x0000bbd202141b4a }, { 0x000ea096448fc959, 0x000e70636a830417, 0x0009f74e8327d786, 0x000c320409b1c96c, 0x00005b046b469a20 }}, {{ 0x000e20be26cf50fa, 0x000b9b56aa39dff0, 0x0002916d8f65e5bf, 0x000fb519f59b43da, 0x00002869fe6dd6ce }, { 0x00029808bacacede, 0x0009382e8ee47c94, 0x000b3b2178464d49, 0x0001271f6d9687cd, 0x00002d0288e392d7 }}, {{ 0x000aa219cfc47b4c, 0x0005a0d4944b6639, 0x000909570115df01, 0x000bb97b1f901f7a, 0x0000200ebd199ed9 }, { 0x000598dee385254a, 0x0009875056a2512b, 0x000928ccfa78af5a, 0x0007a79eda4d643d, 0x0000a165f63eb2e4 }}, {{ 0x000ef8428d09f84c, 0x00075e5dda9e5c65, 0x00026bb1ba085e32, 0x000339e444e0d3c7, 0x000054c2fab4516d }, { 0x000e342afaa45999, 0x0004b7a460ff0166, 0x000f041e56d127f3, 0x000ca11d2da6d12b, 0x0000227aebe64d5d }}, {{ 0x000d33b92ef918a8, 0x000130b93a37c047, 0x000b5fdd04671ae8, 0x000939eb762b1bc9, 0x00007fee369cbc14 }, { 0x000ef80e1f1184ae, 0x000fb4be61fa29a5, 0x000ea74a1414172d, 0x00088df374b2be13, 0x000023e963704321 }}, {{ 0x000d96dd292ac476, 0x000d0996d16768e9, 0x0009c4f514edec88, 0x00089d30d9fc4ff6, 0x0000a3049df36aea }, { 0x000386b3c21696a6, 0x00033d8ce5d72c41, 0x0004ad95bd8d614c, 0x0004dfa3e9d06c5a, 0x00004d05ba437463 }}, {{ 0x0007d17dc0d747a5, 0x00043a6fb283f61f, 0x0004fbda463b273b, 0x0000591227df203e, 0x000021ce3dea9063 }, { 0x00056d9dd063bbcd, 0x000a144522055f0a, 0x000aea39ab0b5fd9, 0x00061ff14de3012d, 0x00000a88edfa935b }}, {{ 0x000ff42bc607a539, 0x0004db68bcec9c2f, 0x000868177340b0bc, 0x0002d59817cf24df, 0x0000d7cc1c5324b9 }, { 0x0004c5f529e4d5e0, 0x0005c404d289427b, 0x0008ffbe999a2d50, 0x0006aa00c3d5f189, 0x00004942095ae6eb }}, {{ 0x0009c75b689ed4a6, 0x000998fde94fdcb0, 0x0009bdfb94f62d7f, 0x00051ece1e96af73, 0x0000523f6b4acde9 }, { 0x00018c7501c3e7db, 0x00062f2b5932a7a7, 0x000e6c7d04ab9f0e, 0x000febb312658252, 0x00006c7c749a3df1 }}, {{ 0x0006ba6d4797b4e0, 0x0004d69ea40dc3a4, 0x0002681194478eef, 0x000bc104adc84ad2, 0x00003476bddf339a }, { 0x000c417d369d684d, 0x00084c593e58a8e2, 0x0000e5ca8b55cecf, 0x0000639daa239473, 0x00006f34e5122d2e }}, {{ 0x00056f1bda88811f, 0x000dac58b6f8efae, 0x00095202695bd2ef, 0x000b8aa2b671a2fa, 0x00009c76e0d6ec2c }, { 0x000d267e667d7ee6, 0x00088c49ff3c8eb5, 0x0001e6229e840d8a, 0x0001551942deae43, 0x0000a944be2e849a }}, {{ 0x0000009e494c202c, 0x000e56db07159d03, 0x000f9188c3c7511c, 0x00075e979ae07a67, 0x00001fabe7db3e6f }, { 0x0007b796c365a4fe, 0x000b122e31328195, 0x000c9a831e3c24e7, 0x000b8d887cffa197, 0x00006565fda180ba }}, {{ 0x000195969620544b, 0x000ef6ca1779ad79, 0x000da3e6732eeb47, 0x000605a7ea33cfe2, 0x0000c3bd61477f1d }, { 0x0004f291ca3b4ea1, 0x00018a6e546c8792, 0x00043da3370bd63f, 0x0009ddf6b8e996df, 0x0000fff3f513ba1a }}, {{ 0x000136d7f23d9040, 0x000e3bb440e22296, 0x000212b875128f14, 0x00081ac39324673a, 0x0000c58b94474200 }, { 0x00061d7940cb50ff, 0x0002999b053a9270, 0x0001a7e9058caf2a, 0x000269dd93eaa266, 0x00002b4a7d3f8737 }}, {{ 0x0003f67568134616, 0x0009283f06d18bd9, 0x00031e7992db2ac5, 0x000d4884d4ba6de5, 0x00005538b6570045 }, { 0x0002d4d4f88e4a39, 0x000381b4347237bd, 0x000f14bf8b95cbb8, 0x000ad048cbc041e2, 0x0000ef112474fce2 }}, {{ 0x000533837f402aea, 0x0009089b3e93ce7b, 0x0004a806a89c97a7, 0x00030378af7b5a87, 0x0000d33d95cf20e5 }, { 0x000972a7c51e92cf, 0x0008b73579fab2e2, 0x0001c3649bc0b31d, 0x000cbc215b41055a, 0x000013a756b9af25 }}, {{ 0x000fd1823a519a79, 0x000ba4ef678e68a2, 0x000069ded5b31a6d, 0x000323d9a4e4160f, 0x0000ac5ec7087e01 }, { 0x000c3930bb0e4209, 0x000fe2f3298f0557, 0x0009828e19b3d13c, 0x00072c7418c0566f, 0x00000b7752b85e4d }}, {{ 0x00058d3c48fce8ff, 0x00042fcaaa2902bc, 0x00091f695e8ae388, 0x00056a0fd539ad79, 0x00003fdda1024b84 }, { 0x000ceb97675efd50, 0x0001fad5dc64e964, 0x000965554bed5435, 0x000a497a93aafcaa, 0x0000072f2cc19c4d }}, {{ 0x000fde3ee29e89ec, 0x0005249e32a858e7, 0x000e2eb23ccb4e1e, 0x0002fc8944c32892, 0x0000fdf45fd7d390 }, { 0x0000793aacf7c0a2, 0x0000909caf549579, 0x000e557c9b281bf5, 0x0004340c0bfb028b, 0x0000eff9d16da328 }}, {{ 0x0009ee5f4330c617, 0x0001779c81710a00, 0x00061dde4e912dce, 0x00009560c557e4a3, 0x00004f997a74131b }, { 0x000606bdf720e7be, 0x0001de9d4292f19b, 0x0005adeaad214a89, 0x00013f62a56f74c2, 0x0000372d1eb10015 }}, {{ 0x000b1ef85cb235c6, 0x000974d044573ac0, 0x00064a4c13476c7b, 0x000d830f77dc3cf8, 0x0000e93ec667d713 }, { 0x000aaf7c181ff6b2, 0x0004684c96958bee, 0x00034ab98d4b092c, 0x000a94e617c32fa9, 0x00007362c69c64ca }}, {{ 0x0005faa9c8bd37eb, 0x000f34687032d585, 0x00030831d017617c, 0x000cd0423c54f3d8, 0x00007c6ebecf2b9f }, { 0x000b53e0cd41d986, 0x000c96f89b95355d, 0x0009dbed7bb78cfc, 0x0003534d34860d2e, 0x00008bc6614104c3 }}, {{ 0x0004603695bcdea6, 0x0001a319feb65939, 0x000fd66cc881fb52, 0x00076b610dd87f30, 0x0000fa4b825b15e2 }, { 0x0002aac5a362f271, 0x000a0c32e83358c6, 0x00048c503bd59590, 0x000c81552508dd9b, 0x0000887ce9e262ca }}, {{ 0x00078ebe5bca260d, 0x000c5a08b1ea7b31, 0x000396fc5629d03b, 0x000df2299d495ab6, 0x000045eb0b5e28bc }, { 0x0004348796ae1fc6, 0x000f6ca5b36d17fa, 0x000306c3e75354eb, 0x000d923e0b5e4cce, 0x00000bbf054089ba }}, {{ 0x00055e14b2edfcf1, 0x0003209eef1a7522, 0x000749cc8d3ad05c, 0x000038cd25d7162d, 0x0000d5775e923a21 }, { 0x000c80242e03d505, 0x000db720303b6972, 0x0005c3d6fcd1b6b0, 0x00053e6b6c5d17e2, 0x000040da0a6e404d }}, {{ 0x00094cc7f33d38db, 0x000ef5fabfae1ca1, 0x000c00d47da85466, 0x0002dc9d2937afaa, 0x000024c1f8bc28e2 }, { 0x000c53b0093312f3, 0x000213a8aa116906, 0x000c9d61edff7a12, 0x0003d930abe40ad8, 0x000054fe955092b4 }}, {{ 0x000b70ce22f66999, 0x000a85d1356eb809, 0x0002fa0810b5bf08, 0x000261a8bb8bf9da, 0x0000447d5e591368 }, { 0x0008f8655fa050ca, 0x000378a829a81803, 0x00037f266d35dbaf, 0x000ec208384329f9, 0x000095e38ca342be }}, {{ 0x0009bb9dc9c786dd, 0x000c3d01d3ec517a, 0x0001a76783e4deda, 0x0002248989874465, 0x0000b42617e4c825 }, { 0x00071bb70b07ff38, 0x0000b5578b4c2405, 0x000b09f0f8d10cc6, 0x000394c6b5ed62a3, 0x00006bb834b02c13 }}, {{ 0x000e530573a2840b, 0x000ae5b2da705d20, 0x0006a34d8a2512d2, 0x00068f0e53ef8ada, 0x000041196132343b }, { 0x0007f458eb02c886, 0x000c75521a9255d9, 0x00015aff273f5d8c, 0x0007ef27563a32fa, 0x00008ba09cf2c5ca }}, {{ 0x0008797e91aea7cc, 0x000a480eb6b242d6, 0x0002d2f863b4d485, 0x00089479dd30bd02, 0x0000e4b655e68a0f }, { 0x000d53005ec1aeb9, 0x000290a6b4e185ab, 0x000d8586b6a88091, 0x00048c81b82f2c67, 0x0000bb2a23d0098b }}, }, { /* digit=30 (1,2,..,64)*(2^{210})*G */ {{ 0x0002f4209bf9bcf0, 0x00059be9d8e68fd9, 0x000288102284ec39, 0x000064398db0f053, 0x00004a5dc6b917e7 }, { 0x000420b560d4b030, 0x0007fcc1a739d4b6, 0x000f3e6a037e1521, 0x00016c1d009aea75, 0x00000584c6da5516 }}, {{ 0x00082b921a859ae8, 0x000619c6254dc41f, 0x00038257ec641913, 0x0006a3ca77e29392, 0x00000c021e167183 }, { 0x000a3d8c1544aca0, 0x000f62e1402cec5e, 0x00070ff1a4d2048f, 0x0000bd9cb9f17ca1, 0x000074174697d3a5 }}, {{ 0x0006d4822ab85c35, 0x000e0e75e0dee6e5, 0x0002858e08782681, 0x00005869374f2487, 0x00000b357177d3c0 }, { 0x0000031f8adc8033, 0x000e4cfc59826f90, 0x00092404f713d9e3, 0x0001ec585ca26096, 0x00001aca73b07beb }}, {{ 0x000e0ace9790f135, 0x00011e60ebcf7262, 0x0001342678767f4b, 0x0008aec094482b83, 0x000086d2546132b7 }, { 0x000cf8daedabfb38, 0x00071d31f8d1f420, 0x00014a5069e4864b, 0x00083fb4b1b1e83f, 0x00006eb2e2034cf9 }}, {{ 0x0003ad49be80c260, 0x0002ea800ee11c1c, 0x0003f23693b6b015, 0x000c9e3c5eb053cd, 0x000021587ac78054 }, { 0x000143e74d589844, 0x0004a41b64279905, 0x000d1f3ac6d14165, 0x00013731e12cf15b, 0x00005b3101abcdc2 }}, {{ 0x00088690b3b5dbba, 0x000a936c88bdee1c, 0x00058fefe5c87a4a, 0x000975f9625f2930, 0x000004895caebe10 }, { 0x00007be238c00228, 0x000042d852705b44, 0x00040d8d72f4674d, 0x000634dd1b0bf8d4, 0x000089f5af04b2d8 }}, {{ 0x000bcaced2f7f0f6, 0x0003a49a639fc6b8, 0x0008fa356752166d, 0x000db2046e75c35d, 0x00000c7919830565 }, { 0x000757ac98dd7581, 0x0004e1db55367425, 0x0006c34659f304b9, 0x0000388c5013dd89, 0x00009e9e11e632ad }}, {{ 0x0004d5ef9bcae914, 0x0000b0d1e935abb5, 0x0003c077f3debaf5, 0x000b3d7b5defd10b, 0x00005a2eed07f66b }, { 0x000687601569519a, 0x000a7ba74f17e266, 0x0008123a7dcee411, 0x000877efdc0a0e3c, 0x000028a9a1af6c1e }}, {{ 0x0008f0539945768c, 0x000b29cf36658f0c, 0x000ba907b1e581ba, 0x000f3f75ac433ef1, 0x0000e501b89aacd5 }, { 0x000e4ebf5dc2f5a3, 0x000e9dfe983c4a11, 0x0001e568f9d43c43, 0x000c3615bbf5e816, 0x0000c937c01fe8f4 }}, {{ 0x000792a7ad2ea66a, 0x000c06043a24fe7c, 0x000e3820a17ecaed, 0x00089740529c1191, 0x0000da0679e69c61 }, { 0x000df141eef101e6, 0x000a4d8b737982c6, 0x0009342d1ef43ed6, 0x00081731a7e3a031, 0x0000448cc1825582 }}, {{ 0x00001f483720d8ad, 0x000f339e6d6f4714, 0x000ed17988f78de8, 0x0001638ac14b2ba0, 0x000005cc7b06291a }, { 0x000e8e9670cc34e3, 0x00054964fd03f663, 0x00099f00a8a162af, 0x000032c183fdb4e4, 0x000086fc98b4855d }}, {{ 0x0009432af25a44dc, 0x0003c0c207674f17, 0x0006ba6b64e961d4, 0x00069db1e112e09a, 0x0000b97a68266210 }, { 0x00016fbbff8bf955, 0x000008fde2ddec64, 0x000f11e7b94049f2, 0x000e7c08a81392d1, 0x000090f2310497ae }}, {{ 0x00073c690595d548, 0x000b5fd0d4a9dcf2, 0x00086d11760d0890, 0x000b020667bc29e4, 0x0000e82ab371d3a6 }, { 0x000ed3d505fc5b0f, 0x000d518cdfaa6b88, 0x0002c18df1996da1, 0x0009c4f27606bd82, 0x000024b05bcf9a6e }}, {{ 0x00060e86489642ef, 0x00039416ab25b6a0, 0x0007250bbedb1912, 0x00086af03c6c0ffc, 0x0000643b4ceb328b }, { 0x0004f435d3812e8a, 0x0006f0f93c7f3988, 0x000afe049b37d0d9, 0x000a26fe39f4a96c, 0x0000c8d9ac21a5b9 }}, {{ 0x0008aca1dc8cc929, 0x0009c5b8e33787f1, 0x00058d8ba496be3a, 0x0008890f0ef42f97, 0x00009f738f8c1ac3 }, { 0x000f6c9c74fac735, 0x000eba72d4bfe80d, 0x000c25d1d6b75c29, 0x000709516fd823b3, 0x0000df2d17686f7a }}, {{ 0x000a995e5dfbc6e3, 0x0004fc7904fc3fa4, 0x00057d4a050cf2ac, 0x000caf6aa14a23f4, 0x00009e74b3de65f4 }, { 0x00016c563b4a41b8, 0x00083ecf3a5598a7, 0x0007407e5359d663, 0x000c3283c56534b1, 0x0000a377a93e6974 }}, {{ 0x000bf3352222107c, 0x000fba41d6178e77, 0x000fecaeca6c05a9, 0x000037a3de4c80c3, 0x0000151b1e5776e8 }, { 0x000829e76053679c, 0x000858e10b365bbb, 0x000357ae0314b797, 0x0004c0d258102180, 0x000045a0e1b22a51 }}, {{ 0x000867e8fbae98cc, 0x000a9a54d53e5fb8, 0x00024cbf2ee7bd43, 0x0000b62c204a5dc0, 0x00007dace033343b }, { 0x0007f6fd799a066e, 0x000ee6ebec9889bd, 0x0001f350cc14257d, 0x00005bc1254f491f, 0x00000465189040df }}, {{ 0x000fa37d174d524d, 0x0005f30acde5e173, 0x000028af37c05817, 0x000b76154d0f996d, 0x000078f2cc1b9df8 }, { 0x000a99951b3d4f35, 0x000518434b8fb41f, 0x000ca461cfd62559, 0x000f9acf299a2acb, 0x000083fa11ba4326 }}, {{ 0x00064110e3d7be93, 0x000db892f3b26e7d, 0x00000446416395d6, 0x000c44aa3f470986, 0x0000d33c4ed3954c }, { 0x0002e3c7706265bd, 0x000d02cfad414e41, 0x00081bec63b3b22c, 0x0001c5ef12b155f5, 0x00004a979c09ab69 }}, {{ 0x000f6db89c6efc0b, 0x00052e59fff83814, 0x00020c510ff875a0, 0x000517dc41105323, 0x0000b7c05ea42fd6 }, { 0x0007d34d61e350d7, 0x00068d6ca563a441, 0x000541073d5751ad, 0x0002419a17f5c221, 0x00006c4fc28b0bb1 }}, {{ 0x0004b95e3dbdc078, 0x000c1101c474019d, 0x0009007390bdd0dc, 0x000a1b42bcaff262, 0x000042e2d657f503 }, { 0x00021d322b01c90c, 0x0009a1f1594438c2, 0x0005e28dacb4f9f3, 0x000183d401eb6e6a, 0x0000c764dc01c967 }}, {{ 0x000629a6c01aa769, 0x00040f6b7cb179a6, 0x000d5169a70cd2e7, 0x00061af0ddc7b764, 0x00009db12efb8043 }, { 0x0007d3a142e389a6, 0x000b84e9f5a915e1, 0x00074a30a2dbdc3b, 0x00082b953b1db9d3, 0x0000f4c3e36d8caf }}, {{ 0x000e709afd4ebe8c, 0x000b8ea308780f21, 0x000119d55ae78e9a, 0x000664ba3dc8de76, 0x00001b9c38ab8027 }, { 0x000526074ae5ec7c, 0x000c776021704560, 0x000ac3d34419af49, 0x000944e68bf204b3, 0x0000bf2f1a243170 }}, {{ 0x000f57691dba40a3, 0x0002bf8ecd92af61, 0x000a4d7a0b3cdb98, 0x000e520e4e6b9fa7, 0x0000cbd83da71fe8 }, { 0x000c2134f4315826, 0x000cdfe9d2e1a33d, 0x000ecfe50841b739, 0x000bb7d27d430093, 0x00008342dc8c1e23 }}, {{ 0x000a626f3a19601b, 0x000e32c5c2102869, 0x000d8248f65290f1, 0x000d557923f68aae, 0x000026d9214bd1df }, { 0x00023bbc1636c361, 0x000daf3199d78e38, 0x0006ef80072fc767, 0x000961f2cb7a2af7, 0x000031f1a12763e7 }}, {{ 0x00049f321e4bf811, 0x00028f299d0a4221, 0x0005dfb794dd3969, 0x000277ad69ac3df6, 0x0000a5e53844a824 }, { 0x000d0299708cd13b, 0x000bc14721b7ebaf, 0x000734a097ba251b, 0x000f39a81e17df09, 0x0000236afe787c48 }}, {{ 0x000a45755beb5e5a, 0x0004c3e7882f14f1, 0x0004ed815580f741, 0x0002464d0c9f6dc3, 0x000088180b1213cd }, { 0x000ca2ca9f747a28, 0x00054277c4608cf7, 0x0001d9dd48232ab2, 0x000f8730e7ccbdf3, 0x00005ef4880c3dec }}, {{ 0x000a91f32af5551d, 0x000cfb16f640f620, 0x000b2f63261c003a, 0x000339244e274b92, 0x0000106a1125d96d }, { 0x000ec1cc3386a669, 0x000be4bd6aaba315, 0x000fb0a6b8c5bd06, 0x00052b520719a163, 0x0000859041c6c354 }}, {{ 0x0008724aa3301862, 0x0007c963b54a0599, 0x0005574ab31008dc, 0x000a32ba60e0015e, 0x00004faf233b361d }, { 0x000a0642cb6dca07, 0x000815bfdb6558ef, 0x0009cd8357cac326, 0x00063ba12f9f7a28, 0x00002446724efd19 }}, {{ 0x0007e5eeb46274cc, 0x0009d81e7dfc8d6c, 0x000f57cfca95b2b4, 0x00069313767cd444, 0x00007aa955fa3cac }, { 0x0002cf71b93c6df1, 0x0009d3d81d950286, 0x00020de171a3c63e, 0x0001a2ee30088f17, 0x000063c5a29ef2a5 }}, {{ 0x0006539c7de5db9b, 0x00043a7e0f222c2d, 0x000b9c92b4c46a68, 0x0003b3230309d42a, 0x000069a4869c5fac }, { 0x000331fb46a1f47e, 0x000277c432ac7d72, 0x00000f4ddec961d1, 0x000121ade72692cf, 0x0000f86aeb4b1886 }}, {{ 0x0005cc064fc464c6, 0x00034322867e6332, 0x0001e4d0c1c60ee7, 0x000f969a578709a8, 0x00000556972914c2 }, { 0x0008ecec23a18976, 0x0009f1c493a65c5a, 0x0000aa2b3840fd26, 0x000bca2e25fb5d94, 0x0000d962837b0d4e }}, {{ 0x0003895ce010bd56, 0x000728bb96209bd8, 0x000b30586d00bcad, 0x000d038ac65fa8cd, 0x00004331b11c1539 }, { 0x000e7f5c64f975b7, 0x0001359b56cd3d1b, 0x000b1c7425cdaf38, 0x00092539f10c8350, 0x00009e660c7a4eab }}, {{ 0x000780dd3a8a4d1b, 0x000253997403a113, 0x0006da9ab974a228, 0x0004b23c294626cf, 0x00003195ea2589e0 }, { 0x0004c61ed6713b28, 0x000e6462baf8e3b1, 0x000d3d0c7ad8714e, 0x0003efc08abe68aa, 0x000057bcb3c222f3 }}, {{ 0x000a3f84425ebffe, 0x0004614c53352e78, 0x000b88f8502c29f3, 0x0009f2dc85a34889, 0x00007c35ac8f1e9a }, { 0x000c80f9252c564d, 0x00051975224da68d, 0x0007e76a07c43bb7, 0x00015767560cd6e8, 0x0000e6884afd696e }}, {{ 0x000dbc7e7af4947a, 0x000ba156ac774075, 0x000ec785880677b6, 0x000732a58a1e5ea8, 0x000073eaf3f59951 }, { 0x0004bc8be8ae5699, 0x000ec1b31590a478, 0x00099131e20fb613, 0x0005da6c0039e85b, 0x0000ecfb39af4929 }}, {{ 0x00021c3831e88d1f, 0x0000a36f20df03ab, 0x0001d3ec9c404310, 0x000bc012a2405438, 0x0000e8ad27a0d2a8 }, { 0x0002abde10a71547, 0x000e959d6fdee104, 0x0003359cb06136c3, 0x000e7b4259da47ad, 0x000064fe3586ecf9 }}, {{ 0x0008660001e36d74, 0x000a1fc17eab9fe8, 0x00044b810970315e, 0x000c49d2cd6e863e, 0x0000d984aeea5a80 }, { 0x000086431bc9586b, 0x000ac5a2c088eaef, 0x000d91aa75b86dd0, 0x00006d87913afbca, 0x00002d1d48a935c8 }}, {{ 0x00092167c2a88bb1, 0x0006855c298b9743, 0x0000bf4fb6418eba, 0x0000aec18905fb5f, 0x000010e7e5087856 }, { 0x0000016589c91554, 0x000b92d28c511da9, 0x000c2668c0a43364, 0x0004ea9f0f127c7d, 0x0000d032d8aa0c34 }}, {{ 0x0008dd39e5a927e3, 0x000c43c11aa600d6, 0x000d36d8716ccbaa, 0x0008f1d682f5379b, 0x00008d24e8fcbed6 }, { 0x0005ff84acc088eb, 0x000e4572ecaa9c3c, 0x000b2224fdbef927, 0x000a8b8c4ba0e103, 0x00004e5b4b7fde85 }}, {{ 0x000b9042d1372832, 0x0008c22ac95aff87, 0x000b3a142a37f646, 0x000c61d8d1c9bb6d, 0x0000bffd2852091c }, { 0x0000111675a26c12, 0x000de80830cf6bdb, 0x0009beb790506d1b, 0x000c2efaa4861d19, 0x00004ac5fbd62b7d }}, {{ 0x000f2bed06be1b4e, 0x00088cf1afb20d91, 0x0000213b2ebeaee5, 0x0006a9c9b1369500, 0x0000b3302a11d566 }, { 0x00088a52e02d7437, 0x0004b176d799e206, 0x0006c9e76ffe5798, 0x000db221093415f3, 0x0000011fe4eb093e }}, {{ 0x000ea4725092fb05, 0x00056a3e2a9a6db4, 0x000d0a54b43a9d4e, 0x000b5eb4f4601303, 0x0000be0291a05ceb }, { 0x000e240a57294dcf, 0x000b898d33fd3e7b, 0x00092d1f2cb16361, 0x000af81ad1ccd8a8, 0x0000360a29a8915e }}, {{ 0x000acada29bfbe26, 0x000d798ca0e7ebd0, 0x000adc7d87452c91, 0x000bd8499f586783, 0x0000c65aa3596607 }, { 0x0004fd5e3650c743, 0x000937d0fe723ac6, 0x0004d4c60de7e613, 0x00084a7411d8e53a, 0x000016d0a718f6ce }}, {{ 0x000d2fe3065bcddd, 0x000429057908805e, 0x000c71a49dd73b22, 0x0002f50d0b5b9ea3, 0x00002ca50a57bbe3 }, { 0x00041b9241ca1156, 0x00092926e9197e27, 0x00093734981b7b64, 0x0000dcb3f11719c0, 0x0000987c423fab1e }}, {{ 0x0001f06bcf00e99c, 0x000df6849a5f4f41, 0x00028dd3efae77c2, 0x0000c5755f91d70a, 0x0000a828a98575b0 }, { 0x000341205886affa, 0x000d85d038d05e1c, 0x0004f78afcf954d4, 0x000dee60b04838ee, 0x0000776112a82e17 }}, {{ 0x000a0f5ab82fff45, 0x000741364d9c2f41, 0x000386014e477e81, 0x0003658417468bac, 0x000084f5c1ea7f07 }, { 0x000549d8e1b91689, 0x000242f659d0ce0a, 0x000ac23bf70fc30f, 0x0000b09c74011bcb, 0x0000c926584930c5 }}, {{ 0x00079ff428e80f59, 0x0002fd8c85438b17, 0x000d4485d6fe9846, 0x0003ca4f45680332, 0x00008f4d41216d32 }, { 0x0001d426d9f3da01, 0x000e898f059987ad, 0x0001fa94470d97e4, 0x00062fcb2f6ce8cf, 0x0000101ab31670a1 }}, {{ 0x000bd0c9b88b7971, 0x000803fc781a2419, 0x000e3b8298f02847, 0x0002fa0843e89360, 0x0000acbc78ffab3d }, { 0x0000be4b4b26462d, 0x00020538a912a4b1, 0x0008ac36cdb271a8, 0x00021b4e0de5e15f, 0x0000a17f8d3dad9e }}, {{ 0x000be980de325ae2, 0x00032f2668621c9c, 0x0000dfb311e3a6b1, 0x00079993cd5518f5, 0x000052f4db6222a4 }, { 0x000f159768ae1fb0, 0x0008f10ddd83683c, 0x000ccab52fd3a1ed, 0x0006425503b6cb35, 0x0000ef327d2522b2 }}, {{ 0x0006283e8437a770, 0x0005f5343ad73b3b, 0x000f98db1c104d18, 0x000473c691b528c1, 0x0000c3c4141f72fc }, { 0x0003347161a895a5, 0x00024590a5f25b1e, 0x000475107cc11b68, 0x000483fdeefaf8aa, 0x000020a387cf4433 }}, {{ 0x000de20ec9734397, 0x000ab198d9ea9f87, 0x000b761a0bec4dd4, 0x000ae95da090de5d, 0x00005d35adbfe798 }, { 0x000182de8a62cc1b, 0x0003d8eecdaecabd, 0x000cb6b148b91280, 0x000dd1dec6ca4b0e, 0x0000550839c85391 }}, {{ 0x000cd9daab10e14f, 0x000763ec8a4186a5, 0x000b3793b388c571, 0x00056173cb3e878d, 0x000035bc8bc8154e }, { 0x0009c5d26f779d48, 0x000d17f586d5e720, 0x0008ba7df7ea2a57, 0x000c7dc2447500be, 0x0000ece6c6ab436a }}, {{ 0x000636393a1d534b, 0x0005c9aa74d3f7b3, 0x000d99286b1f5422, 0x0007e296d0428fd8, 0x0000b23839cb4288 }, { 0x0008021fc06fa7bf, 0x0003a5510350bf49, 0x0008c8a8c7c25f86, 0x000c0c909b381743, 0x0000c67eee6023ce }}, {{ 0x000caffa79164dbb, 0x000ec0c0e367a98a, 0x000462b2bd497a28, 0x000b04843bea1bc1, 0x0000c78fe367131a }, { 0x000b512e742ec763, 0x0003664457bf9c43, 0x000ad1dd7f0fc57f, 0x000ff90eb0db6407, 0x0000e05c4ba13983 }}, {{ 0x0007f983c7b84b15, 0x000f91ffce104080, 0x00035264a1b62bef, 0x00017d0b389ddc00, 0x00002960ff9e4a4b }, { 0x000967d1accb38ae, 0x0009f155d5231e7b, 0x000c51e7c366f7b0, 0x0009802b5cff22ae, 0x000081c1f665309f }}, {{ 0x0007012c7d47081d, 0x0004ec6cf777b6c0, 0x000d456becdc46a4, 0x000edaf850062bdb, 0x0000cc93e16237c7 }, { 0x00095cb26b4e0be4, 0x0001562ac47800d1, 0x000ba7a63b09f80c, 0x000ace5d353365f2, 0x000034e8d2215ffc }}, {{ 0x000f81609ee40822, 0x0004c2905f2c4ce9, 0x000af8d535cd568a, 0x0004a4e15bd2bdec, 0x0000cfa19d6c9ba1 }, { 0x000241b6f9fad805, 0x000662cda350002f, 0x000007d9c63cdde1, 0x0004574bcbd05469, 0x000047e52739fbec }}, {{ 0x0005ce69cde21889, 0x000fd432fe3cd4c0, 0x000baeedf96e9a6a, 0x000fb161fe0f33ac, 0x00001790f40c1e5a }, { 0x000b8e29796a6e6a, 0x000b116f5f98aaf9, 0x0005d395b776372e, 0x0005f93d345bb71d, 0x0000430258e053dc }}, {{ 0x000fb4879b3fe9bf, 0x000f346ae0a6828c, 0x0003a0c44e0f5c7f, 0x000cb3cdbba533d2, 0x0000f6ea637a253b }, { 0x000dbf6a4042ef68, 0x0006b0b3281705b5, 0x000be2907641494e, 0x00070e6df7e361c6, 0x0000876051625bfc }}, {{ 0x0000e78507af85ef, 0x0008d234b54d9bf9, 0x0000a42a3ed21495, 0x0002cc8581374e68, 0x00009d3702290f12 }, { 0x0000946dbd4e2626, 0x000d38d5d86f1749, 0x0002f55502275d25, 0x0009fad44d74e0bd, 0x000004488f9be27c }}, {{ 0x000f710571dd1d02, 0x0002158fe1a838c8, 0x0004d299c4671897, 0x000b1580b05aae6c, 0x0000e3dbc53866c4 }, { 0x00091241f3b00662, 0x0007b48182caaac9, 0x00096af503dbdd89, 0x000b2dc6d8c4aeef, 0x0000048abae31743 }}, {{ 0x000ffdfc7e7c2a09, 0x00085eae457a4773, 0x000bae6fdf8723eb, 0x0009a0d71d19857d, 0x0000d6ef525ea59c }, { 0x000d15002a515a26, 0x0002c5426ee7cda3, 0x0009a1edc37de8e0, 0x000e199c8341b086, 0x0000bbb468e51820 }}, }, { /* digit=31 (1,2,..,64)*(2^{217})*G */ {{ 0x000f6927b0d79bd1, 0x000614c85edfa308, 0x0003f86bcc29875b, 0x000193b862597655, 0x00001c7d62051005 }, { 0x000d0721ecd294e3, 0x000feba55f2f94c5, 0x0008d744240dfdf9, 0x00015625d6a996f9, 0x0000e456c18ca0d6 }}, {{ 0x0004cae01e64c20e, 0x0009b2079e5fb67e, 0x000a8bdf924006e5, 0x00033ca37e1331fe, 0x00003ed077fad719 }, { 0x000c957822ca746f, 0x000cfe60412a77db, 0x000c22af18030eaf, 0x0007aeb3106ff7ca, 0x0000cacc54eeaa59 }}, {{ 0x0007e0aa7adc7a48, 0x000db0cb0ce1c552, 0x0004e3df0b8cb07c, 0x0009bee3b5b534d0, 0x0000fda2b88e9831 }, { 0x000f7d9eeff2ac2e, 0x0007e2d79362c410, 0x0000823dcdc0db71, 0x00077b12467920c9, 0x00001801931c732f }}, {{ 0x000f5fa5904e2bd3, 0x000209afa8338349, 0x000206d2dfd21b18, 0x0004529102295172, 0x0000fd30a26b44f3 }, { 0x000137b286ed0846, 0x0004125e77d9a3b0, 0x000a624d3959c964, 0x0003d9c4a11235ce, 0x000037f27954916b }}, {{ 0x0000d262f88de12c, 0x000b5ce44ace1509, 0x0008b2af868437a8, 0x000e478b8e0f8d3d, 0x0000f156f86418d4 }, { 0x000dbdf5922834ef, 0x00065c9283e13c98, 0x0007211e7af3d393, 0x000a7cfcb2d04fde, 0x0000f09ff470d31f }}, {{ 0x00073c8530e34004, 0x00002950de1e5786, 0x000782baa695ecd5, 0x000f9e8a52e1463e, 0x0000607baa031037 }, { 0x000c1d160b022745, 0x0006100747f91da5, 0x00016dae62deceaf, 0x0008e89f5b08d43e, 0x0000e0b5caf53925 }}, {{ 0x0004669f46350981, 0x0002d5328c8e13bb, 0x0003fe873d8bc483, 0x000c485ad375f10c, 0x000035558e6d3927 }, { 0x0009293790f894ed, 0x0000cd05bbd8699b, 0x00092e6e3582dcff, 0x000e93bd35528a4c, 0x000007788f960423 }}, {{ 0x00061bbb05f9956d, 0x000106ac42bd6d29, 0x00082503dba8e1c1, 0x000ae458e6df8646, 0x00004572780d144e }, { 0x00004d881133b185, 0x00070f070a6a26b8, 0x000cb240e6288319, 0x000ae43d370686c0, 0x0000da343e03be55 }}, {{ 0x0008584ef74bf3d5, 0x000b27b207f16700, 0x00084609039a722e, 0x000afedbf9b0dd18, 0x0000dfa5f66ee54b }, { 0x000c334771dc5db5, 0x000dba5dcd898ffc, 0x000f5425a6cc0213, 0x00029fcc126286c3, 0x0000264ddb1fa583 }}, {{ 0x000725af16318964, 0x00085542f770fb1d, 0x000f75b1a448a814, 0x000806afc97c1c61, 0x00000e2e1a79320d }, { 0x000e079d3c015b41, 0x000914fc01e20ecf, 0x00039cdf74e30b3a, 0x0001c76ecdfd3749, 0x0000e980c17f36eb }}, {{ 0x0000d6a5c42da56f, 0x000780a2e6ac8d23, 0x0002df97b64102c1, 0x000402c8c9c6b5a4, 0x0000724fa29031c0 }, { 0x000d131ab892404e, 0x0002e224fc0a9ef0, 0x000388ae52355bac, 0x0009dc1de190ff08, 0x0000ec43401fd702 }}, {{ 0x000eec726a98db71, 0x0006f7e857012919, 0x00087a53ef3da9d1, 0x00019338594793ed, 0x0000b72ad73d6c3f }, { 0x00032b2c8ec764fc, 0x000be590c9d8005a, 0x00077b4e8d42c947, 0x000eb6e1e5feca45, 0x000035b3f8239855 }}, {{ 0x0006c04225a0b97d, 0x000447373dd0b4ea, 0x00039de012a075b8, 0x000d1d6f137a2821, 0x0000c37b6f44f5ad }, { 0x000f54feb8e2353a, 0x0001134cf671e3ce, 0x0001de54badb3643, 0x00075fe4881bbecd, 0x0000e52b6354c0d0 }}, {{ 0x0003469898a0538f, 0x000eda7fb8088fa5, 0x0006fa95fe2d2ec5, 0x00023e2760142724, 0x0000b5efdf4b7190 }, { 0x000e706aca43c3d6, 0x00061b83a2aaac68, 0x0002cc8322d12925, 0x000fb5299e9f91dc, 0x0000dfdaec18b984 }}, {{ 0x00093ea6c3ee3c56, 0x0001e95f688dc983, 0x0006d90da43852a0, 0x000dc215c26490cd, 0x00000e9b4f9bc030 }, { 0x00059cacd2538ba3, 0x00090437f338e0d8, 0x000adab73ae2ca93, 0x0001271d539fb832, 0x0000b214d5f9080e }}, {{ 0x0001567f755e516f, 0x0002de74462007dd, 0x00047b5f76420568, 0x0000d6ee7b8ab48a, 0x00004f2bc1635d97 }, { 0x000931de26c2af42, 0x000d96b0887bcec5, 0x000e8847159b8388, 0x000b324cb694497c, 0x000039c7e289bc5b }}, {{ 0x000bd0a121216b32, 0x000ad7c0e58d4939, 0x000fbce69df1668d, 0x00035914db1ae5ec, 0x0000c149038863bd }, { 0x0007f13e98b5b5ed, 0x0009bb7cc863c683, 0x000e052e0eccfa57, 0x000f268933a1cc11, 0x00008167fd8f4e54 }}, {{ 0x000ee1b6170663fd, 0x0008967bc947badd, 0x000d4b5538170a6f, 0x00013ffac738e07c, 0x000023f0b6b7b6bf }, { 0x0007cdc47eb25821, 0x0003d672e793d12f, 0x000de923c25b844a, 0x0008859f7d6aa6ca, 0x00005201d76c5ace }}, {{ 0x000236ac0915006e, 0x000ff9dab15247f0, 0x00004703a77613ae, 0x000a2c6e77c789c1, 0x0000808d9373070e }, { 0x00042da81b066709, 0x000b4251d7a51446, 0x000a8d111cd1a17e, 0x00089a2ca098b9c2, 0x000013d8733bafcd }}, {{ 0x0005441757848811, 0x0004b054f7269b13, 0x0007ad43ac2df8a6, 0x0001c5e21fcf3077, 0x00008d6031c1f86e }, { 0x000728edac03ee8f, 0x000e999fd703431a, 0x00056fb46aceed43, 0x000d9a62da438d7a, 0x0000f9c288edabe5 }}, {{ 0x000356c23a712a04, 0x00086bc42531689f, 0x00070db2a1b53dad, 0x000edd5b30a51a0e, 0x0000c4d54a3bd065 }, { 0x00050964756fe418, 0x00027ff8d3a3dace, 0x0009588ae4a9b9ac, 0x000663ea4409597f, 0x0000d6d7b2598a4f }}, {{ 0x0001c02c179a9537, 0x0001a265c3427b0b, 0x000c20c29da60ee6, 0x0009725456401405, 0x0000041eff03bf87 }, { 0x000a43463e984012, 0x000db75d9635bc92, 0x000743e10ef12662, 0x000b1be66226790c, 0x00006caa30be64cd }}, {{ 0x0009f2f368831642, 0x000033adb4837611, 0x00054be273c309ad, 0x00028ba87e7cc608, 0x00001790a225635b }, { 0x000590dd601ac1f6, 0x0004d175c0b800bd, 0x0008b5dcc9827fed, 0x0008cd15e1f1e7c8, 0x000021b22c5fb59e }}, {{ 0x000b15d6243f1091, 0x0000ca11f17a34c7, 0x0008a8443e31d5d4, 0x0003fa53b5420ab3, 0x0000927b5e2d1cf0 }, { 0x000424051138a243, 0x000fdb1e274e49c4, 0x0004528d80f9684c, 0x0000da2a45cf5074, 0x0000abcad67dae2e }}, {{ 0x000248c0344ff4d0, 0x000734311b2d595d, 0x00091c801f234930, 0x0007f0d05f136749, 0x00005dba5d3c2cee }, { 0x000e8c07a9b72e10, 0x0003f13a77739f5e, 0x000a3546a79917e7, 0x000b691cfbf4288c, 0x00009c7306d20c7b }}, {{ 0x00089e1462801321, 0x00028996fe8393f2, 0x000fc08125d060fa, 0x0001c42c80f809a3, 0x00009fb87e79ba00 }, { 0x0001826047e09dee, 0x000287e9889feea9, 0x00024f16d8c20c68, 0x000b29cc6d5c9c0e, 0x0000ca96182e9075 }}, {{ 0x000a074b4cbdc635, 0x000527a9a4a27515, 0x000270dfb3609166, 0x000e3e44171bd007, 0x0000f49c9e777f48 }, { 0x000fb0efe038c226, 0x0003334c1cec8edc, 0x000ddb0b13dd9e14, 0x000c85e15a6ecb49, 0x0000c013efc7e2a5 }}, {{ 0x0003ceb3f5d13058, 0x000edee23ab3495c, 0x000747a89247407e, 0x0002caef4a132df8, 0x00002b96856566b0 }, { 0x000c0899c9fa2622, 0x000071de88fb1da6, 0x0003b19887afb52c, 0x000d8d520ea05797, 0x00000f3ef4a9c2d8 }}, {{ 0x000f5d86d67ee298, 0x000dd04752ddad71, 0x000f824903c11932, 0x000766399d60bd74, 0x0000bacfccb4d377 }, { 0x000571960bc9fc41, 0x0007b424b5a6d88f, 0x0002254d6471eea8, 0x000cd841069eb2c3, 0x00004e6a49e4dc49 }}, {{ 0x0009b988353bd1dd, 0x0001ecf704e23c66, 0x0001bef11e2642bb, 0x0008c5f83c71b7d2, 0x000034725a0787e8 }, { 0x000a08f0037397b3, 0x00074a3963bfeec0, 0x000ad474b7c8163a, 0x000d0f6b199947aa, 0x00006b872dacd87a }}, {{ 0x000ed489e3948b33, 0x0000d9478ef24870, 0x0004f3fb6243555f, 0x00051c028c8d2d41, 0x00001b4ae6438b23 }, { 0x000b9784bc1dfe6e, 0x0002a6bbef3366e9, 0x0000524658fc7d96, 0x000df6de20de59c7, 0x0000fc82425dd0cc }}, {{ 0x00084e81ad96c3d5, 0x00080021a93507a4, 0x000744ed85217d67, 0x000286a40b4cd118, 0x0000702de63abcfb }, { 0x00077e27e30a727b, 0x0000cb5272e9d6ec, 0x0004ff812967789d, 0x000a6af8eea1c93e, 0x00003caac07df9b9 }}, {{ 0x000fcc837acc3f62, 0x0004936d2b713c5b, 0x00000fae8958d09c, 0x00070206b86274ea, 0x00001d84b95f783d }, { 0x000f1a38bcdc1a88, 0x000769dd6529b73d, 0x0007848e4745cca3, 0x00002bdb9708aa22, 0x000012697ae997ed }}, {{ 0x0003317d153dbf41, 0x0005926b8bad853a, 0x000293f26dd1f0cd, 0x0000ae7302d52cea, 0x0000259fdb316c19 }, { 0x0006bc5834b6d375, 0x000edfefd4ddedab, 0x0009fea120f6e9b2, 0x000f37444ed2a153, 0x000027704cde3608 }}, {{ 0x0004269d64c13d9e, 0x000b4b383d102b6b, 0x000652201ae42133, 0x00030cf37fe695a4, 0x0000c2b2d20a73d0 }, { 0x000282e5be5c5683, 0x000d3a10a1d22850, 0x0001444f87b4312a, 0x000fdb1a7feef6c5, 0x0000eff77ff509ef }}, {{ 0x0005aaf78c7288d5, 0x0001c81721c486d5, 0x000066ad8ac27b77, 0x000ce2b31301baf1, 0x0000f49e14841d8d }, { 0x000dd8c0882b51a7, 0x000ec7159c639522, 0x00045de99b26fb30, 0x0009386c33a3bd27, 0x000050ea586ccf8c }}, {{ 0x0001dbe32c1fbaaa, 0x0008874f5531461d, 0x00008bb9666f009a, 0x000c64fd28b4a128, 0x00008430a73d0dfa }, { 0x000431531ac44d42, 0x000df0d30c34169a, 0x0002d4895218eac4, 0x000ebb054ba74a95, 0x0000755d2f2b53df }}, {{ 0x00006ae448efaa11, 0x0004d22f669d7ec1, 0x00042514d0cc257f, 0x000f9ecb3ca374f6, 0x0000f169c333b6fa }, { 0x00010a7d3f6b9eaa, 0x000609033c8e9a1f, 0x000180a2db4623fc, 0x0006c4314234645e, 0x000084b79c5ee4b0 }}, {{ 0x000d8727967cf447, 0x00097ee40d5c9be3, 0x000f7cfdc601ff1d, 0x000e146ddb2bae7f, 0x000039d35690a32d }, { 0x000213071385c0a3, 0x00027818569ff132, 0x000b784d085ec27a, 0x000ae88868b89a5f, 0x00001eb069c3b03a }}, {{ 0x000098baf9cb4cd3, 0x000b81e48ac28403, 0x0004bc21d97de9e8, 0x0004798431831129, 0x000013750d1196db }, { 0x000ae9e34b83b95b, 0x00066584198da522, 0x000be98219cfe30b, 0x0007d4e08ab4fc17, 0x00008387d9c3f13b }}, {{ 0x00010ea88587f6e9, 0x000699e3fa11b1f7, 0x0007263c4a2f6c1a, 0x00039903b21e4367, 0x0000789308d6093a }, { 0x000722a5d5edffef, 0x00032fcc5dc67cf9, 0x0006f11db1430e0b, 0x000e4afb708d5164, 0x0000f530330b49e1 }}, {{ 0x0006370339f57e7c, 0x000d4e2c861baa5c, 0x000ccecea904d470, 0x000fd8a3fc0c21a5, 0x0000fadeb312f995 }, { 0x000ef031de2f466c, 0x0002dc7638167c3f, 0x00057a6d812df399, 0x0003edd89fe6ffe7, 0x0000825bd8675575 }}, {{ 0x0002fcb419b70685, 0x0001a82d57c667f8, 0x000e490ec2d75faa, 0x0000b05ecc70312c, 0x00004cf30e7acd12 }, { 0x000d8db5533f5c10, 0x000a385ab45d44d1, 0x000243edce4fdb2e, 0x0008c0b52fba0722, 0x000052d22dab8a19 }}, {{ 0x000dc5e37371a728, 0x00090d4e344a8732, 0x000dd070f1cabef0, 0x000cebf507d8d116, 0x00005db19373e506 }, { 0x00072b8ab82adaeb, 0x00047e6e799eb95b, 0x000eb16e5c349584, 0x000d038d5e9e5f4d, 0x00009e31731daff4 }}, {{ 0x00089197287c3914, 0x00066e02cecc84ab, 0x0007c349eff41179, 0x0008b5b58600016d, 0x000061064bc7eb5b }, { 0x000c91e7660a8876, 0x00045bddafd60884, 0x00061f4025d3c53e, 0x0003b9a721a74014, 0x0000074a6b09578e }}, {{ 0x000f2874056008c5, 0x00020ca08819a786, 0x00095a30051c1c8d, 0x000b3077dcf48b72, 0x00004df9fccd5a7e }, { 0x0007e550b59c1a48, 0x00012c226cd44ecc, 0x00060804d4595c21, 0x000eca3c588ae32a, 0x0000363ef9fbc480 }}, {{ 0x00061b1ca7d7673a, 0x000e2f25c727bd2e, 0x000036ddf9088a43, 0x00035ff202e4badb, 0x0000a50c99cb451f }, { 0x000f2e941699137f, 0x000faccbd6bd51f4, 0x000131175819f7a0, 0x000db8f628024e40, 0x0000d71497878c8c }}, {{ 0x0009f80d55b0c703, 0x0003dec0ccced589, 0x000b73ac42429524, 0x000510fc625cd4b9, 0x0000a65aaf5a02d6 }, { 0x000f34bb38b3eac6, 0x0007ac9ce6dc1532, 0x0007a93199e8a328, 0x0001c3b4d138d511, 0x0000ca319150839a }}, {{ 0x000b70ab66820487, 0x000c8d22ae8921e6, 0x000e1dbaf67c7245, 0x000bcf9b2b039288, 0x0000edb438dd0e2f }, { 0x000b5629d34a9d60, 0x0004bc9e70574810, 0x000f912ab26e33fe, 0x0008be6824581dde, 0x0000b84bd043d606 }}, {{ 0x000fbfb416c23b23, 0x000a49eb06f5b41e, 0x000d5e6480526105, 0x0001f4ea9a42e84c, 0x0000cccc1d701e42 }, { 0x000897f9fd8a78ab, 0x0003f239d33cd6f3, 0x000871d410fa9b73, 0x00055c4969caedb8, 0x000057a5bd2f9d4f }}, {{ 0x000f306e8d3ef41b, 0x00096f88e5d788e9, 0x000842a42261b628, 0x00064b03c1aec7ba, 0x0000bdc61d3e538d }, { 0x0002865801e16113, 0x000ed6e5040a0acd, 0x000328c1172c7e8b, 0x000896723ca9d504, 0x000064b076c1e6dd }}, {{ 0x000671c6f1b51569, 0x000c03f6967469a8, 0x00090718c7e7267c, 0x000b208222894d83, 0x00005bb66d861506 }, { 0x000fc913dfbae46d, 0x0008bd6d7de9853b, 0x0005f229a8e82949, 0x000b8e3cf2e3ce34, 0x00006ed57b771cce }}, {{ 0x000dbe9e4865fdfb, 0x000959fe61f7908e, 0x000eadfddce11bc6, 0x00006b838192e304, 0x0000a93c2ce3f05b }, { 0x000ebd91e9d1f474, 0x00075be2db30660f, 0x000ec22deba43a12, 0x00039956eda3e613, 0x000030ac3120ad60 }}, {{ 0x0003a058ce6c6132, 0x0009ac4df655a499, 0x000bcb11a94222b2, 0x000f584eaa9e00df, 0x0000155d23f64159 }, { 0x0003455bbbdf94ba, 0x000d64a67bd3448e, 0x000a104fa1a088b1, 0x0008da5524a3d4e1, 0x000055bd521fe9fb }}, {{ 0x000381dd5350039c, 0x000fc5b4b9ad1ce1, 0x000648361a401b32, 0x000ae0816a981853, 0x00003aa8a7a07cf8 }, { 0x00041e541e27a4b9, 0x00054617a4a76209, 0x0005a59a402eaafe, 0x000f30a3ac841292, 0x000004cfa2d4a052 }}, {{ 0x00061e15b0193f73, 0x00026e84a34f239b, 0x000c02e5ed252835, 0x000fb353215fdb83, 0x0000611a80a40f29 }, { 0x00053277336c58d7, 0x00082d4a127f89a5, 0x000bb2b59fa73e65, 0x000bfdf925d541e0, 0x000059c1e0662639 }}, {{ 0x0000309532509fa6, 0x000fafc95f57552b, 0x000fbc7c1b975eb3, 0x0008218013294764, 0x000077c5af065b77 }, { 0x000e03f65c2dc5db, 0x000e2f505c2e54da, 0x000c78e4e6c62bf5, 0x000b84353158f27a, 0x0000694c1d649f0b }}, {{ 0x0007332f3b061b87, 0x000c7bd9c95f0f98, 0x00019d30d836a35c, 0x00039dac45ed9deb, 0x000018b00ca2bbfd }, { 0x0005cb917ba93167, 0x000079e2b9e0d888, 0x0003d0d4cecd60b0, 0x00027c84852d910f, 0x0000f373e4a9fc00 }}, {{ 0x000137a6d994065e, 0x000be934c8998d19, 0x0000e1d6feb6644a, 0x000fc3fb02186a3f, 0x00003352e74d4d1d }, { 0x000ca1b89b828df6, 0x0008937748bc82c0, 0x000173a4e6f0ad53, 0x000fb24a287c2e93, 0x000028fafbaf323c }}, {{ 0x000737d6fb05a03f, 0x00004aa5e1cd3cd7, 0x00082350a52d4bcc, 0x00049e09f8939780, 0x0000f18ec22e9ed8 }, { 0x000429759f59ae9f, 0x000d56a60f1524b3, 0x000585dbb50813e4, 0x000e39fa536985e5, 0x0000b06736fc8393 }}, {{ 0x000ac8aaf9b029b8, 0x000b6c3092e9f414, 0x0006175cc0c40ea0, 0x00083907d3a238c6, 0x00008d3d8a65f0c0 }, { 0x00090005fc438ce7, 0x0001ab15e4ccab05, 0x000244e145fefc14, 0x000a4a29d9bf430f, 0x0000798b9c3dca21 }}, {{ 0x0000075aacd2e5f0, 0x000a12f24544cb60, 0x000ad7936836f151, 0x00072b2129987b71, 0x0000b2e6c26f30ed }, { 0x0007813de7e02a59, 0x000f78b6cac83696, 0x00078dce2ea1a080, 0x0009ad9a487842be, 0x0000b0205681558b }}, {{ 0x00040896be942344, 0x0001dcec3427239e, 0x000fe1609e1ac9a8, 0x000f5d1915f3c7ce, 0x00006570948e3d4e }, { 0x0003d4708d9dd274, 0x000f3910492d25f2, 0x0009c36c11e8ef73, 0x000b536cc8aeb30c, 0x00006263417807f4 }}, {{ 0x000f9b71b8c0f425, 0x00077f2d0c051995, 0x00029b4c129bcbe6, 0x0007e7c82502fbc2, 0x00002b22165d2734 }, { 0x000b6e3e8373047f, 0x000bb592b82dd077, 0x000519b4c4ab6dee, 0x0004bdb327630273, 0x0000227777e79e51 }}, }, { /* digit=32 (1,2,..,64)*(2^{224})*G */ {{ 0x000c41114d0d0f0a, 0x00071c035d0b34a2, 0x000b56e6af5ad632, 0x000f458d1440b386, 0x00009070851ee09e }, { 0x0000477abf63470d, 0x000c1f1ad95a0b12, 0x0008478dc8a2c85e, 0x0009d79c9c09b37a, 0x00005669d660129e }}, {{ 0x000a68df70882277, 0x00065b3292a92874, 0x00062d47b35717e2, 0x000498f05ddc15cf, 0x00002045f41bf3f8 }, { 0x000a8b9343580755, 0x000f94505bf7dd0a, 0x0008e243ec49440b, 0x000aea3afa4e63d3, 0x00000f5462133be9 }}, {{ 0x0006113c503cd9d4, 0x00061b51e706ad97, 0x00044d98af8ed595, 0x00086b990b99cebb, 0x0000a86e1c215f82 }, { 0x0003cbb144e6b9aa, 0x000e4b097e2b5aa3, 0x000c2fed61bf9a24, 0x000125c6c7e1022c, 0x000044eec8aec086 }}, {{ 0x0004e7b4f75c69c7, 0x0009d717af715d2e, 0x0003eb2b959f67ad, 0x000b50256e2f7f59, 0x0000faa39a85f847 }, { 0x000657624d4d6888, 0x000779788d5374a6, 0x00031a2adb0e9860, 0x0008607e22b915e6, 0x00009ed17ced0865 }}, {{ 0x0007e49f538144e9, 0x0000801dace5aca9, 0x000179c203139436, 0x000579d09c4fdbcf, 0x0000b8c43e3ced43 }, { 0x000f036040802177, 0x0007090937e2ad5c, 0x0007636ab7b11bc7, 0x0009a49dc846e250, 0x000015f05617398b }}, {{ 0x000858e1e42fa26a, 0x00096e07442f1d58, 0x0000de8801c7a755, 0x00023d647475607d, 0x00002129ca073288 }, { 0x0007cdea3e2c120d, 0x000050b8231ee10a, 0x000abbbc34902c47, 0x0009866a41b80e7e, 0x0000ea4fb6751c9a }}, {{ 0x0005b9d57b4ca325, 0x0009b07f8ae7c38d, 0x000b67ba2c17122d, 0x0004048b36db07a5, 0x0000c13547ebaf13 }, { 0x000fe5a101822457, 0x000dbe78eba20f2f, 0x000e71d40250d287, 0x000744f58ef11ca8, 0x000067b29ced3d7d }}, {{ 0x000af127793627f3, 0x0008811e51732d26, 0x0007ba47d495211f, 0x00011fbc5dfd6eb2, 0x0000d0277a7c5305 }, { 0x00059aba7caa2e14, 0x000712d06c425aef, 0x000b6687611ec682, 0x00054599c6df92f8, 0x00003f2120a92224 }}, {{ 0x000eee4194a7b79a, 0x0003ed5da64309d0, 0x000682c4c56fb4d7, 0x000e3be0861a6de5, 0x00003c6f7e87d587 }, { 0x0000847a2186a0fc, 0x0009eab771e4caa3, 0x000d4837a79d473c, 0x0001408f583965df, 0x0000b258cc7ec22d }}, {{ 0x000c06085b99b726, 0x00006f152bfda056, 0x0008f591b1313934, 0x000ea4c6fe0e4c4e, 0x0000984ae625115e }, { 0x000eea86f0bd9963, 0x00061d74463ba14f, 0x000201459c9b5827, 0x0008df06d9d292f8, 0x00000dd1c0ca9a79 }}, {{ 0x000c48ec0b853213, 0x00079d366131e2e7, 0x000f04b53a77349f, 0x000e3ef89f31d974, 0x0000a4bfcdc5045e }, { 0x00080a6ebc348716, 0x000fbd8d1989aa7f, 0x0009f3eeb83d4cf9, 0x000be314ab34fa0a, 0x00001217dc8a396d }}, {{ 0x000f4dca515118cd, 0x0009354afa05dd8e, 0x00010d61474d56e0, 0x0004bee5926dfcf2, 0x00000943d9f591b4 }, { 0x0009b587257c123f, 0x000448a65d306723, 0x0004c3aff7615195, 0x000c356c88b08d53, 0x00005b8eb7fb6fca }}, {{ 0x0008c318b548154d, 0x000c3593de9abe37, 0x00012418eb094690, 0x000d8818c4043488, 0x0000566a78469087 }, { 0x00030ce97683fa8d, 0x0004216fde24c99d, 0x0004cfb615e6cd11, 0x0009b82b42a77cb7, 0x0000a14d76ffb4a3 }}, {{ 0x000ac78848467605, 0x0004e931a62cc262, 0x000625f9580ab732, 0x000502ef323c69b9, 0x000090bdd65bcd79 }, { 0x0008b8974d570b21, 0x00057f9187d073d8, 0x00090dc6e92ff16d, 0x000634c8f6c2be91, 0x00009044aaeb8adc }}, {{ 0x000c764803a21e34, 0x000dd77ff57d0517, 0x00077ef3d15d6733, 0x000b936d42ff3803, 0x00001b21b2a67101 }, { 0x000a30e0b2c6a5f0, 0x000e75f48879bc89, 0x000fbe9d8b0eae8c, 0x000e37c16ea7eacb, 0x00009ff4968601c7 }}, {{ 0x0006605ecd65db55, 0x000d72e421d3aa42, 0x000cc1ef49735da2, 0x000798f1cf926407, 0x0000115826b66fae }, { 0x000b337ce7ef919a, 0x000a7a6d6a5eabf5, 0x0003c637e9a63491, 0x0006f67021edb84f, 0x0000746c950ad014 }}, {{ 0x00034288799ea710, 0x0004c77c055dc14a, 0x0004de9614663360, 0x00056bbaf2a0ffa2, 0x0000e0884c9d70d1 }, { 0x000fd61e66f6e09b, 0x000fecf884655fb3, 0x0005f6771fda3095, 0x0003d81b7fa5b5bd, 0x0000cdb900fd5f4d }}, {{ 0x00059455d0433f8f, 0x00013dccc78cf662, 0x00044a47a9a7232c, 0x0004db768b301817, 0x0000faaaf90a0ad3 }, { 0x0005deb6ca3cd246, 0x0001ec5cde3acec5, 0x0004bdcefbacb8b3, 0x0005df9657714192, 0x000045397101934d }}, {{ 0x00068f895e9004fd, 0x000b957b1fa70fbf, 0x000ee177b0a26d56, 0x0009b2800fa07f50, 0x00006b90a3ae492c }, { 0x00066663c21efba8, 0x00078605cae2a6aa, 0x00075c20e4801115, 0x000e8d3d301bd721, 0x0000b7b5d77ccf5d }}, {{ 0x00030d7189e49226, 0x000dfd73272d8383, 0x0009c755243ba1ba, 0x0009db432e22924f, 0x0000ce330e0db587 }, { 0x0000a894fbc9777d, 0x000292cbde1f7140, 0x0004e5228567b078, 0x000a5063235771c9, 0x00004ff8170ebc9a }}, {{ 0x0002b9e66ddcbd1a, 0x000899b36194d408, 0x0004f4a73f93d7fc, 0x000121558e857a7c, 0x0000f54e23d16472 }, { 0x000c57761e509ec5, 0x000a434e4e8b9dd4, 0x000d57cc01b97144, 0x0009c1f3bd2372c9, 0x00008d5623e3a8bd }}, {{ 0x000653a576829f13, 0x000ba0a1058a3184, 0x000531b195245a3b, 0x000277ae2369cf3f, 0x000016030f4bd9af }, { 0x0007f95f135e7fcf, 0x0000e5aaa4e5c975, 0x00015fb1dd60b809, 0x000e5f3835be80aa, 0x0000a477556e695d }}, {{ 0x000d4690afc07e00, 0x00014e24415503b6, 0x0005df748739e313, 0x00060c966c08ff7c, 0x0000127236d69e17 }, { 0x000d769c04659257, 0x0008c2eea74237b0, 0x000ebfe0b48a99dd, 0x00039e9fec436d17, 0x0000486dc5e3dd88 }}, {{ 0x0001787c9e286fcf, 0x000e7de34eaacda9, 0x00079a28754099d0, 0x000d3bf55d9e116e, 0x00007562dbb12950 }, { 0x00014f95d0e6cf70, 0x000e32bf129ac2fd, 0x000788e74c5ba2af, 0x000d048f3d307b7c, 0x0000f8a713e0a48d }}, {{ 0x000d063b675b0d68, 0x00068296ae550430, 0x000f37a2427aa344, 0x000d796e28931e98, 0x0000fa3386495eae }, { 0x00040f65cbe226f3, 0x000a5b9ed0e4316a, 0x000a8c5b647a8e82, 0x000b3a4c7e74a736, 0x00005f2b0889266d }}, {{ 0x000497e5c3ee0d06, 0x000300416df4285e, 0x000aec2d851e2818, 0x000b8c9c3b0c9bab, 0x0000197c784b55e1 }, { 0x000c8f0069e898e6, 0x00085b4164bda960, 0x000994284d372970, 0x0009f40ba1ee4241, 0x0000ca6bcd47d957 }}, {{ 0x000394f375958bf5, 0x000f481c27253c98, 0x000b0f1e76cff0db, 0x0002bc64605a6aef, 0x0000f0b8234cc107 }, { 0x000753d452dd6652, 0x000759c5f109d0fe, 0x00057438f1b79715, 0x0008a4c68cad88a7, 0x0000fe76d824187b }}, {{ 0x000c362a70e2529b, 0x000d9a15b0ec6f5e, 0x000366538847e1f8, 0x00084617347989fe, 0x00001b6a7bf51376 }, { 0x000a56149e2522b2, 0x000e6a7b3a8ad418, 0x000ff10dc6b2e1e9, 0x0002983f473a20fb, 0x00006887f8bed5cf }}, {{ 0x0001f4d76b4d26fa, 0x0007e819ac6e0f4f, 0x000eb21ede824bca, 0x000d9b6fd360fdea, 0x00003d6157db8955 }, { 0x0005570e9aed5fe8, 0x0006909587f76b89, 0x000c8dc0ef1ab00f, 0x00008c8958b4ee08, 0x000053e011751c9f }}, {{ 0x00043ef52d2d581c, 0x000a76f35d33ae72, 0x00032c7c6567763d, 0x00057cc4b200ea12, 0x00009729e0b08fde }, { 0x0008914cb19c5b91, 0x0003477e23ae233d, 0x000ecbcf853a9cd9, 0x0009ee5a4b93807a, 0x0000427af498005c }}, {{ 0x0008f30be32aa9eb, 0x00099943fb42622f, 0x000b5715fbf20368, 0x000ec01633b2700a, 0x0000a02527da25ef }, { 0x0004d487b147ea98, 0x00060d269e55f156, 0x0001673e9c38aac8, 0x000fb56f61fead85, 0x00002fdd4c705f91 }}, {{ 0x000add3db7ec68b8, 0x000b386d23ddc820, 0x000c732406385f9e, 0x000123ac503fd344, 0x0000078adedd4745 }, { 0x000755e7ed4c6729, 0x000153f8260e01bc, 0x00048d4be4a45000, 0x0008bbb33fbeb49e, 0x0000d816465d0546 }}, {{ 0x00045bbb58e226bb, 0x0009639296077453, 0x00006e136fcfe782, 0x000a03edd0ca0742, 0x00001978f2908e69 }, { 0x0003f5cdb0aae739, 0x0006a8cbe0f27a29, 0x000bd029fda61b77, 0x000fb8e5767c24d7, 0x0000f943175bf6fe }}, {{ 0x000c4647529cc278, 0x00031d7c5ee30a1e, 0x0004ccc36fd68fe3, 0x0001c8748d159363, 0x00001530c91aa13e }, { 0x0001789e131a19dd, 0x00082f39e49af6a5, 0x000a1dc463a96fbc, 0x000b4fb43f2d6238, 0x0000ead936950af1 }}, {{ 0x000ce1ad11ac24e3, 0x0001629763231dff, 0x000ceaea30de2a0f, 0x000017aa846df9f7, 0x0000e2b10bbfaf1f }, { 0x0004deb125091869, 0x000a4f6fc6a0a7e8, 0x0007e8c574b783f8, 0x0001c41bedd431b9, 0x00002151fe66860f }}, {{ 0x000e9dd70df9b33d, 0x000b4693c2a59987, 0x0003faa941ff8de3, 0x000a633149b9247b, 0x0000fbd0cf3f9717 }, { 0x0006a6e285611fca, 0x000aef7cbcd5e64a, 0x0006f52dddad338d, 0x000a258ae0359ac1, 0x000096f58aa22a1b }}, {{ 0x00073f78f0342793, 0x000723f24cea1a04, 0x0009ec229ba14f6a, 0x000120be9c97bce4, 0x0000c16b99f54401 }, { 0x0001a21357d12b82, 0x000ade0f63d3d0d4, 0x00006e094fa470ab, 0x000ea0183e620b88, 0x0000c42192da71c1 }}, {{ 0x000a9e41a1d48ae1, 0x00001fac7dcfcabd, 0x000dbaa89e6546d4, 0x000254d07650acfd, 0x0000deba6e56a7dd }, { 0x000c591b9fe8b554, 0x0005327175a54ab2, 0x0000be0471701886, 0x0004842a9ca0cd19, 0x0000e042468b20ad }}, {{ 0x000a78a81b42cff9, 0x000dbe42bad4d5f9, 0x000064775d802ce4, 0x000422994fa4c359, 0x0000ec1267726fb2 }, { 0x000cc8b1f090da45, 0x000c079a98e84e7f, 0x000f4ccf33c47417, 0x000479ce4fe1242b, 0x00008d7b8bba4b39 }}, {{ 0x000700ef747f8ab2, 0x000f10292d0487a1, 0x000c124aa28a6283, 0x000e05c8f1442dbe, 0x00008c88040d8a3b }, { 0x0000b08ab557d66b, 0x00094c370f1fc62b, 0x0005b91712159de5, 0x0001fc90d3b31d4b, 0x0000bf8fe20af650 }}, {{ 0x000b9ed428d2bc49, 0x0000e01ae3400501, 0x00060151f1407234, 0x000255151ba4b301, 0x00005711c0145b29 }, { 0x000bf2831a40ba61, 0x000844eeb4819f5f, 0x000ca2263440d5ac, 0x000281a0b616cdfe, 0x00006655f6b3a3fe }}, {{ 0x0003e7363ac7c9d0, 0x0001c85e0e60d843, 0x000fe9d0b83e0ebc, 0x000727d6e68037e2, 0x0000a4ef48579238 }, { 0x0009b9aa509df363, 0x000d76108d0756c9, 0x000b95f568fafb67, 0x000401523d727f85, 0x000004ff00a6a67f }}, {{ 0x0000cb3198286b38, 0x0007904e2b4e075d, 0x000472b1178e49c3, 0x0003e802d4998729, 0x00008d0984c74c1e }, { 0x000afaaaa6c45a17, 0x000f87dd7808c569, 0x000eb6fdeccc2f83, 0x000631aaab5c54d8, 0x00005179697da3e9 }}, {{ 0x00019ed11ae91fb6, 0x000a82104cf667af, 0x000aab9a64bcab50, 0x000e9707cfc2a811, 0x0000554d8be76583 }, { 0x000d6d34f69204ef, 0x0008d09067b6269c, 0x00028f41c0a35e1d, 0x000eaffbc967b853, 0x0000dbd9f34c4cd6 }}, {{ 0x0000c8e44f888e23, 0x000b2d36cceb3707, 0x000936c497a9954a, 0x0002857622aeac57, 0x0000b6752a402de8 }, { 0x000c4acd0404bf66, 0x000a35086a34d092, 0x0006bac87c03cd3c, 0x0003e6d15e0fca25, 0x0000b1bac43b987c }}, {{ 0x0004309c3d5be708, 0x0006d173b5a9ba6e, 0x00052eb47e145ec8, 0x0002e4097b9cbe1f, 0x0000dd504546a602 }, { 0x000270b2a44f2d47, 0x0001105f67f37466, 0x000a40f34f5ba628, 0x0001c535385fc37b, 0x0000ffcc4377268a }}, {{ 0x000b87878a9289fb, 0x00069f5974ad33b0, 0x0007f2f3a6671d24, 0x00026447304d8597, 0x000094b1402774b8 }, { 0x000a86f6939e30ae, 0x00091015a0617323, 0x000e68a3226dcef5, 0x000e4a218c25430c, 0x0000225b9562aa3c }}, {{ 0x00074a9e86f273ac, 0x0003768da9f3804c, 0x000dda1996154227, 0x000ef0ea5470f07f, 0x00007a00585a4292 }, { 0x000a3d7f108e6847, 0x000633543471a24c, 0x000deddbc6014539, 0x000748d4d239446b, 0x00003d82eda4eff3 }}, {{ 0x000052b13e4c4fc6, 0x000ea85fdaf45207, 0x000fd4f729b3d2ed, 0x0005d9642bb6d3e7, 0x00004fd193b24bcd }, { 0x00032412778a49c4, 0x000491b682b90604, 0x0003691032b4873f, 0x000ee41b4a71d388, 0x0000b5eb5db6e3ed }}, {{ 0x00089111e4596bb4, 0x000456e4901bbed5, 0x00009ba190d798a1, 0x0003e197d6419c71, 0x00002d587b9dd586 }, { 0x00051bb0af6d78db, 0x000bf337b60554e1, 0x0007d8c6d2f4ac07, 0x000c32235ea5f888, 0x00000285ce6252e2 }}, {{ 0x000dd50e6646b5c5, 0x000ca7443b30ca81, 0x000abbbe371cf9fa, 0x0005b4bade10b5bb, 0x00002c1185fd706e }, { 0x0002c679e115a447, 0x0005654cff2b821f, 0x000c54619d7f138a, 0x000808fe33882555, 0x0000813626061721 }}, {{ 0x0006e2ff3e3cf7e4, 0x000a4156d2a57687, 0x0001a53b7eef03f6, 0x0005810437f227bd, 0x0000890e9085f693 }, { 0x000ab8ff4c5d4c80, 0x0000d6fa3177ec75, 0x0000c87000a8d96c, 0x0006d958ebf731d5, 0x0000d478202f55ec }}, {{ 0x0000a38f5769375d, 0x000035635edc56d2, 0x00095df07e21caaa, 0x0004f10cb5a69d34, 0x000046b4e39da99a }, { 0x0002061ea52a1372, 0x0007590fac3a15b2, 0x000e58496fc6d1e0, 0x0002758866ed7ea2, 0x00009cae713eaa92 }}, {{ 0x0009654db53619a3, 0x0003ce6f546783f8, 0x0009d0a51668ee67, 0x000c4e665d38bc6d, 0x000084a7bd921bf8 }, { 0x0005f504d34681c8, 0x000f79a26e1adee2, 0x0004113d9000faba, 0x000febbfe291f376, 0x000014210635841d }}, {{ 0x000e987967ce4bc6, 0x000c85ec3a0ee43c, 0x000999001f97950e, 0x0007a775670aaebc, 0x0000679e9d41df8f }, { 0x0004eac8b0e95f7e, 0x000ed195e26310aa, 0x0003933fc3f81098, 0x000d5b1e49e43548, 0x00002169b080d0d8 }}, {{ 0x000fb265b41cf750, 0x0002512c1ad8cf84, 0x000e4a2e50e3a4c2, 0x000f10df0193b4e9, 0x0000b160e21161e4 }, { 0x0001099ad8ca10c5, 0x000b8cde51e1ae29, 0x000652cf15bd680d, 0x0004f84988e3a8ca, 0x00007fc6eb96d788 }}, {{ 0x0001c9c40bf7f829, 0x000d01c93aa96b8d, 0x000aae006a072e1f, 0x0003a5e230fc8716, 0x00002dcd3ed4529d }, { 0x000363fc5ef58287, 0x000778642b7c094a, 0x000c71dfc3c2c438, 0x0003c765d1873439, 0x00005e33d9307f67 }}, {{ 0x000b6c8350158412, 0x000200df862eaacc, 0x00025759c48cda62, 0x000c2c22814419c6, 0x0000de581dff2c38 }, { 0x000c9b41c4227517, 0x0002345d30f917c7, 0x00091bde6e29ed24, 0x000dae963d4c4b04, 0x0000c95bedff5a4d }}, {{ 0x000bfb7557c62b30, 0x000cc2f2f8ba2c73, 0x000f406c34d0f5d5, 0x0004d39720966eb2, 0x0000f79e276fbe94 }, { 0x00021e887875bdea, 0x00065235a2b96204, 0x00072d90be459d5e, 0x000593923bff3ed2, 0x0000becee3d55908 }}, {{ 0x00064e33579d3be5, 0x000737a25a416322, 0x00047d0d393b726c, 0x000afd3dbc081412, 0x0000f3a2065b9dbc }, { 0x000961bb956822d9, 0x00083cdc87c51e26, 0x000ae6bca67f4701, 0x00015a9ce16b3015, 0x000099b9f2e2caa2 }}, {{ 0x000154c9356b909d, 0x000be8deff7a3a0d, 0x0007e08aa9f0cff1, 0x000cfad1fbec3373, 0x0000ce02e948472d }, { 0x00011828d5dd509d, 0x000b36f1cc7a906c, 0x0001ab3de5b9cee2, 0x000ed9c4473bb539, 0x000009806170e848 }}, {{ 0x00085a892ec2931e, 0x0002de13e4b12ff9, 0x0008952ddd4d7a3d, 0x000ee02cfc3aad9f, 0x000060ef6671c961 }, { 0x000785426e98218f, 0x000231b3bb85fa06, 0x000026771ffb6393, 0x000c11deaf95375e, 0x00008e2bebfcfde6 }}, {{ 0x00099fe2c7f70e55, 0x000c2c8d8ceb147d, 0x000ddd6a728c6e8c, 0x0005d71349b649ee, 0x0000f688ee12edb5 }, { 0x0003baeb490b7ac9, 0x0001e628d3abba2e, 0x0006c3dccc50256c, 0x0001b7d4d18fee6e, 0x00005a845d13c4bb }}, {{ 0x000157c30c88e767, 0x0007447f23206d55, 0x000fcbce3e45a30e, 0x000a8919a2f6d341, 0x0000644f481a46b6 }, { 0x000508455987e93f, 0x00086c52d4fb936f, 0x000bf1494782ed2e, 0x0009b3b64ef22f7a, 0x0000e271957d8d37 }}, }, { /* digit=33 (1,2,..,64)*(2^{231})*G */ {{ 0x000595cd1fa2a781, 0x000d8d8df7304d44, 0x000bb98b416f08ee, 0x000983c60b71bcf1, 0x0000fe06b3f76c34 }, { 0x0009429622589d67, 0x000cb9a4835859dc, 0x000cb478d834436f, 0x000f5234e4a0f0d2, 0x000076555e5f3c86 }}, {{ 0x0004c9b20d431706, 0x0002e62f23f2d925, 0x000d0bef8e6b4e0a, 0x00055d8206cab71b, 0x0000c95a2a5e55d4 }, { 0x00031469c615f1a7, 0x00031aa9f2ac02f8, 0x00069d5a83ea26e1, 0x00016bd3403f8e61, 0x00007f5ad3cb507d }}, {{ 0x0006930a553f291e, 0x000c1248f9813540, 0x000c2ef5980445f8, 0x000777b2c587e23e, 0x00005d0484062c98 }, { 0x000c4f3993ac460c, 0x00001ebbe5bbe21a, 0x0004784247eb5cec, 0x000c04560a7ffa5b, 0x00003ce6bf87455c }}, {{ 0x0008b75007f2d3e8, 0x000b9583ae9c1bde, 0x0007fac5923887d3, 0x000d750b4e0af6d9, 0x0000d1ef5fdad135 }, { 0x0004069ea597b54b, 0x0003bafe02358f2b, 0x0006368b73835819, 0x000671cfc31b8b85, 0x0000fde8d8c56c72 }}, {{ 0x0002f45c13822eb4, 0x00022e27fa03cb3d, 0x000a3ce92174b004, 0x0009d485ddb938e5, 0x000021b3fc2ab9aa }, { 0x000cc71d2d719fc7, 0x00059b57883e6142, 0x000891b541f8e786, 0x000c81ae35fd27e6, 0x0000dc5876ef7ba3 }}, {{ 0x00028ad2a84e6c41, 0x0004fcde36d07576, 0x00017717c0d9fc24, 0x000484cdff722d7b, 0x0000ebe7611ea3b6 }, { 0x000c336b09195735, 0x0008ab520226040e, 0x000064d14bbbb3e8, 0x000ac8c886c34ecb, 0x0000b85de43f45af }}, {{ 0x0001830b48c43912, 0x00050a21e206ee56, 0x00002ac69aea8304, 0x000bda0c3f1e2748, 0x000032ea619c2425 }, { 0x0004c11642e0594c, 0x0001c46e78e815f7, 0x000ed740f1e78774, 0x000d57765fe40139, 0x0000edbe53f588b4 }}, {{ 0x000dcefcddd2868c, 0x000b79e558df0194, 0x000a5ea22e49ccca, 0x00091ce24230da4b, 0x00002dd640a90582 }, { 0x00072d824d931811, 0x000feb2a47d4c5ab, 0x000efbe07e5114c0, 0x000d6c17355ac9ab, 0x0000fcd91a520be1 }}, {{ 0x000b1757ee1625e4, 0x00036744513e2cae, 0x00014d0cb33eb84c, 0x00094c0500b41861, 0x0000123028257abf }, { 0x000558a2a835c536, 0x00008283dfac6d55, 0x000df349954d38f7, 0x00030de99b2431e2, 0x0000130b37f17b1d }}, {{ 0x000b8b3bb657e0d1, 0x0002823cbb13d1b0, 0x0002507060487a33, 0x0003073a998799f4, 0x0000a4673e731318 }, { 0x00071b9484805f36, 0x000b92e3ecebb211, 0x000b1f5665228e4a, 0x0000fe71f17cb6c4, 0x0000fab132e7caf2 }}, {{ 0x0008f096fe69263f, 0x0006f2d7ef0329c3, 0x000258d3a92be87e, 0x000ae1cbc0850922, 0x00004f94dbc53746 }, { 0x000b4c0dfa96c3eb, 0x000a074a1dec0270, 0x0007447bcec03082, 0x000dc7853e8cf10e, 0x00006175addc465d }}, {{ 0x000e8ef838c9fbc1, 0x000c452de7e5c194, 0x000973312d33ad9f, 0x000d8b33dfab2860, 0x000073e06257b5e1 }, { 0x000ec0507e35022e, 0x000df264cb1bf3d1, 0x0009551e8ee3b962, 0x000b4deed4c1f9d0, 0x00009cc539a7598a }}, {{ 0x00038fd905d568c2, 0x0009ac7cde450794, 0x000a0ddaf0def815, 0x000076f5cde173c9, 0x000000e3536d8eec }, { 0x00053add2c142e87, 0x0003e06c7d9630b4, 0x000baf4270493d17, 0x0006bf9e86457a87, 0x0000eaa209f092f9 }}, {{ 0x00094abebcf27683, 0x0008e09a607419d5, 0x000262210bc3d71d, 0x0004daef3faa71e6, 0x000036cd41505615 }, { 0x000a29a36702adec, 0x000ba91eb78399f1, 0x00052519283d6b50, 0x000ce18f048aafb3, 0x000081d651ae4804 }}, {{ 0x000568d2e1c64bfe, 0x00042e51c21f2bf8, 0x000c1f9ca80c3bee, 0x0005f092ef99a513, 0x0000b0e4e1a943f6 }, { 0x0007a6dafc4f015a, 0x0003aebd3f69d9f8, 0x000280091fb54144, 0x000e1d6f4181a973, 0x0000bdac310c7a67 }}, {{ 0x000a55b52ea9cdb8, 0x000fab5ef7d92893, 0x0007df294c2baacf, 0x00036dbb62480d4a, 0x00005fd14d5bdd1a }, { 0x000d5e9d7d31477a, 0x0000715309eadb09, 0x0009f58728a80fa4, 0x00022c35adea7de5, 0x0000ddf8bf0e739b }}, {{ 0x0004d8163beea5c0, 0x000fef5206d3ffce, 0x000298a8759903f1, 0x000a735ba23d5e03, 0x0000c5541d12d6e3 }, { 0x000219da8243f413, 0x000d6efd3082e8e5, 0x000baf7918ddca19, 0x0009adb0a4fe1246, 0x00009d116a39ce07 }}, {{ 0x0003fcac89cfa8ee, 0x000b7c1f7ea25aaa, 0x000f57b3d0d5ac4d, 0x0003e9871d165e6b, 0x0000a30effd4d7ba }, { 0x000e263feae7d9d1, 0x0009ed4f0baa8abc, 0x0001149b82faf7d1, 0x000fe87495a4adac, 0x00006b868aef4658 }}, {{ 0x0005547c4f5be3f1, 0x00012d307032c722, 0x000e53b4ec796f84, 0x0000587f07f40d5c, 0x00006bdd6dfb6e81 }, { 0x0007df465d70f0e6, 0x0009ffd65fb2a9eb, 0x000e66d9d13f40f5, 0x0005f5e42ce69336, 0x0000c86a6ebbc9a1 }}, {{ 0x00058de498e2b259, 0x000aba3315980cd1, 0x0002e4ae075ed625, 0x000a16c04693bc49, 0x00003b029d23553f }, { 0x000836ce7e2b454a, 0x000abc7cfda83685, 0x000320a048ffe7ec, 0x0007c9a6ed2d7bbb, 0x000066b26f8ebcc8 }}, {{ 0x0002b52f65c725d1, 0x0007e1994f834cbc, 0x00037fe9a81cbbe2, 0x000bfb143d35653d, 0x000092a9b3930992 }, { 0x000f186cdd7031a0, 0x000821b18f23d962, 0x000c1039e5d77384, 0x000a47402cb05aba, 0x0000c20b19c6ae17 }}, {{ 0x0005624623a128a9, 0x00043e59a29a5c5b, 0x0006860a3ddf3f1a, 0x000b07d84b19b3c0, 0x000095b53ccaa378 }, { 0x0005a9d0868addaf, 0x000bf653c04fa024, 0x000c4900692381db, 0x000c3b43f83a7176, 0x0000f9656734975f }}, {{ 0x000b179393f74d6f, 0x000bd1d3dc090bc7, 0x000f2f422dd3e906, 0x0009a8d4d82c996e, 0x00000d602d115417 }, { 0x0007c5dff255af16, 0x0008825f8c5dbfdc, 0x000d576c9b126092, 0x000dee6a84d9d7a1, 0x00005c2588a5a8d3 }}, {{ 0x000ea886daec0451, 0x000078d04c82bdd5, 0x0004998917222f76, 0x000e744806800553, 0x00005c6be61fdaec }, { 0x000de96ef613e33c, 0x000ce01252a0b4d7, 0x000db80131abd46f, 0x0000659631bffb4f, 0x00007cc0d1f5bbc5 }}, {{ 0x000fe64809d55519, 0x000140cd77d970c2, 0x0003a358b1c17566, 0x000cc06e903cfb93, 0x0000d055c34cf7b5 }, { 0x0003d31b05a74dde, 0x0007824c2ac98ccf, 0x000f2666232e242f, 0x0001827212a1372b, 0x0000ee7c4caf1682 }}, {{ 0x00061891a0a38e82, 0x00067df5ece6e7ce, 0x000e299469b4ff0c, 0x00013b1a50603ac8, 0x0000588d5e4bda3a }, { 0x0003b117efd74152, 0x00051d299bf1603d, 0x00091dd30d6b1e14, 0x00058ec021f43afc, 0x000028e06b2d515a }}, {{ 0x000103fa05977e5a, 0x000801365d1d131c, 0x00070276d6394917, 0x000ae7edd86f1636, 0x0000eb35b19898ae }, { 0x0001ae47f2c3b604, 0x0003f44f4b478f01, 0x0008cf69819a940d, 0x00069bd2ece91edd, 0x0000bdb21f33bd5f }}, {{ 0x000d53ae910e4572, 0x0005d8d20f8a2425, 0x000d94da6c47cb3e, 0x0007f8cb37aff5b1, 0x00007219eed53f71 }, { 0x000e86515094eea4, 0x000d505ec0418032, 0x0006e5b9f737bc0c, 0x00073e98f85e3c97, 0x00007c74d04d9d17 }}, {{ 0x000a04ca6726822e, 0x0007ca46a67a6b02, 0x0005885821d9ef2a, 0x00044421ef4cdee2, 0x00003f466bb9f3be }, { 0x0004a874138b9a64, 0x000ec18ef0543fbf, 0x0004dd08640a5f75, 0x0007b6f33f709a4f, 0x0000bdf2825ed29d }}, {{ 0x0007b80581df3f89, 0x000a6a74d82f4c2b, 0x000fb04cea31d778, 0x00083b95e90725a5, 0x0000bfe40a6fc4ce }, { 0x00087f6f736e6376, 0x000631cdd1fc74cd, 0x000b0f04375170e3, 0x000a155badc1c62c, 0x0000d6efb5c07fab }}, {{ 0x0007be9ed2271299, 0x00036c1317f4a765, 0x000b3944ccfbdba2, 0x000d491568d2703e, 0x0000e1677466f47e }, { 0x0000d9e943522c82, 0x000c371ef0b17acc, 0x000e183e31f4b70a, 0x00066db0e74b2655, 0x0000795a4aa76537 }}, {{ 0x0008d2fe5724a2d6, 0x0008a411e84e0e5b, 0x0002f5d04e3bf4c5, 0x000d0d132a5db84d, 0x00001765a592c24b }, { 0x0008b4a422ebc11c, 0x0004336f3eb82fab, 0x000c454ae73559b6, 0x000b3a5108cb20cc, 0x0000bc49662e3c97 }}, {{ 0x000ed06e285bdac8, 0x000fbea6fe8208b7, 0x0003a99e0ad61a08, 0x000fe721abd74b9e, 0x0000d5e8ed41f37b }, { 0x0003186b23df1bb9, 0x000a1586be8b800c, 0x0001152e70049303, 0x000ccd5d3428299d, 0x000034b1cedc477c }}, {{ 0x00017aae8c429f29, 0x000039e8977d99b6, 0x0001227a835b6392, 0x0003488d4be94433, 0x0000ff63573b35d6 }, { 0x0001efae75205711, 0x0002ec4282aec3b3, 0x000fc5c949ae1fbe, 0x000ade84cc6063d2, 0x0000bb575870e312 }}, {{ 0x000184a526e63b6f, 0x000fd6d40a9b97c5, 0x0002fde1bd2fd49f, 0x0004943e314702c6, 0x00006773701eca6b }, { 0x00059cd28024561a, 0x0003937003c32ea4, 0x000cdabca247db9a, 0x000b7bd1a5aa374d, 0x00006c792f7fd426 }}, {{ 0x0003e1589a804b9d, 0x000e461459c2b92c, 0x0007b20d365b2696, 0x00064c6102f020fa, 0x0000ca6d9d3092b0 }, { 0x0008466ee83f88e8, 0x0006bfeaa3f451a6, 0x00035a933dc49cd6, 0x0009efd8b3a3c7f2, 0x000087060571aa2b }}, {{ 0x00013994bea33721, 0x0002cd41fa266138, 0x000b3c8908a4f4fb, 0x000dbb557a2dc6da, 0x0000d41b64ebec33 }, { 0x0000b65bedddf81b, 0x0009c22fd4f75534, 0x000bb2ed0f327ed3, 0x0005d82f55135ff8, 0x00001de1ffe7c18b }}, {{ 0x000331c0941a20d5, 0x0001da43734e5205, 0x0002cd6a1c26bf6b, 0x0007386355e3abbe, 0x00003e3eb679bfa2 }, { 0x0008f2c0da9416e2, 0x0001c2976b60c80e, 0x000a91db561dbd79, 0x00014b5842285593, 0x000090564385f22a }}, {{ 0x0005c558090f5634, 0x0003d74c1df065c4, 0x000b19a020f15227, 0x000e520a8afeeb5a, 0x0000ebe08fef2016 }, { 0x000ab226cebd5622, 0x00094c0ecc8c1778, 0x0004ced0c5db8594, 0x000b1cd8e799ea9b, 0x0000fb29019d75f8 }}, {{ 0x000a741ef1df7c17, 0x0002ae57ea973dc8, 0x000f9614703c94db, 0x0008185f15c00ca6, 0x000063d1e4dbdd66 }, { 0x0003b6c6786317cb, 0x000512f196b4cec3, 0x000395c7df9fe4ad, 0x00099bf2b70d08e4, 0x00008cc26ea5e3b2 }}, {{ 0x000ef2c5fb93c237, 0x000adf807ac97946, 0x00004b14057e32a0, 0x000171de51eccf05, 0x0000be44bff72854 }, { 0x00006e0b10d8d552, 0x00011d2679784532, 0x0005fcf73fe7d9eb, 0x000e85837a0cf379, 0x0000f1351989d9a5 }}, {{ 0x000c6469812142a9, 0x000055fd5ecfefc4, 0x0008765b8f7b26db, 0x000ef9c9607084fd, 0x0000b7551edf99c8 }, { 0x000ae28483d757ee, 0x000bd4ed65abfc39, 0x000e78719a43c760, 0x000116212e01cb91, 0x00006fcb78045826 }}, {{ 0x00091c285c2a4c9a, 0x000b29ea66d80a18, 0x0003ecd9d0b57b14, 0x0006db5c1680a3e4, 0x00001cad3822f1a4 }, { 0x0006f8b13781c29d, 0x000dfeb799ece3c0, 0x00093ae7ccf04903, 0x00021942329b910a, 0x0000f5e1879fd271 }}, {{ 0x00043be0aaf3f89b, 0x0005ffd385470908, 0x000f01a760b26589, 0x000ea802719ab8b9, 0x0000ed6be57be9d3 }, { 0x00085f39d0ed1528, 0x000c543a6db836ca, 0x000359452235069c, 0x000ac7b772a1330e, 0x00000393cfe1f4a8 }}, {{ 0x000ad599c449623a, 0x000546d4ae528342, 0x0009494e42ebf43f, 0x000d510ef5a403b3, 0x0000d5d9e1fe46a8 }, { 0x000827cf81a805c4, 0x0006bb9014b3bf81, 0x0004de4580857334, 0x0002e3d027309268, 0x00005f977d08a51c }}, {{ 0x000b5212970e3e2d, 0x000d8f6f10ff9276, 0x0000b8218d2fb9f7, 0x0008395ccd387145, 0x00005c10024eb9bc }, { 0x0003ea9e97f9fabf, 0x00005f96e3cb4a55, 0x000123a0215f0c0c, 0x000937b45e47d3f4, 0x0000f7e86aadc6c4 }}, {{ 0x000a9b83894c7656, 0x000ba6e39cbb688c, 0x0002289ce9a8fb03, 0x000435e21532401d, 0x0000c8103121db65 }, { 0x0002767c4b7d6814, 0x000174e2093913eb, 0x0001b74604c733da, 0x0007f9ec7533d2f9, 0x0000110a91af736e }}, {{ 0x000581cf9346f15c, 0x000a387aedbae9f1, 0x000921063ac18234, 0x0005bb2717daf0eb, 0x000088c3f46a6255 }, { 0x0003d318ac75f3ac, 0x000fc873ac1f4527, 0x00098797d751c8f8, 0x00007e1c3b417fce, 0x0000aca7b2139a79 }}, {{ 0x000f8a35b721d031, 0x0000f0f728693e5f, 0x000a340ef236c630, 0x0001a6810e87d814, 0x00001fb62f488436 }, { 0x00014052c2a4d35e, 0x000f5d77f200d34a, 0x00076e24ea1e5f64, 0x000cd0579470f1e6, 0x0000eb853f10fab4 }}, {{ 0x00078fe4024f3dda, 0x00020b526bc27979, 0x00060261836f1c35, 0x000006ed113670d1, 0x000079b7c4f64fcf }, { 0x000768d7e586bd52, 0x000a992d41c5dd45, 0x00077049a5bfcf2f, 0x0008264065ff8e24, 0x00002216a5fc8c7a }}, {{ 0x000c3672af71c96a, 0x00080a360017a5ff, 0x0003a02e5bec495b, 0x0007474076b18e6e, 0x00009937b8bda59e }, { 0x000c948f1455702e, 0x0007f77d06283a1a, 0x000038410e854096, 0x000d0b9c2542fc65, 0x00006954911b34d4 }}, {{ 0x000fc87df6be7f7a, 0x0001c82b04465c31, 0x000a44a03f1eaecd, 0x000b2137ee3d062f, 0x00008c43ce25b5a0 }, { 0x000f663391d373da, 0x0006ca80591f6528, 0x0006c92fee18905d, 0x000bd5a8ca861b8f, 0x00006b9e0397c8fa }}, {{ 0x000aab4e6a3238d0, 0x000a8acb591ffa38, 0x0004c2349d649d6e, 0x00015d6b3027ca9c, 0x0000be661b873b12 }, { 0x00068aae83dc529a, 0x000564fb474d6b85, 0x0003add089d147e5, 0x000f552aa6597ffd, 0x00008040d2d5caed }}, {{ 0x00043d8baa45a8fd, 0x0007164c73b23834, 0x00078d3ffbb7c8ed, 0x000f760ab49eb344, 0x0000e0df7be97747 }, { 0x000bf53de2fa0299, 0x000caa5ea7610d6e, 0x0004e2276b961c38, 0x000b80832e47e418, 0x000046bc71e68286 }}, {{ 0x000de1666fe499b7, 0x00045b4d3c8c1cab, 0x00029f234c99a8a2, 0x0004e1c950d914ef, 0x0000577ca7b4a559 }, { 0x000e9faf6f83c4d3, 0x000f76ed449ab198, 0x000259fa7703581c, 0x00006a7538902b32, 0x00006ea68c6f0f57 }}, {{ 0x000da8564dcf371f, 0x00016da9a85788bc, 0x000def5dd0869c6e, 0x0003cbd64d21f03a, 0x0000cb0b2e54fa19 }, { 0x0004ee3dffcc2d2b, 0x0004f5cde92c68ca, 0x0000ce43fec47260, 0x00053d47c78e035a, 0x0000a966314f762c }}, {{ 0x000e2ab3decb0797, 0x0009e07af4e18f85, 0x0004a8483f498d7a, 0x000959a86967ec9b, 0x00007b0ac9fcfa8a }, { 0x000c0c1a5b8ce6b8, 0x000b64d11c226dff, 0x00028b6615b91ec6, 0x000a19f19f9783f4, 0x00001a2b243e738d }}, {{ 0x0002f2a62f45d86b, 0x0008149571d92ac3, 0x000e139fab5045e2, 0x0007639af569e85f, 0x0000dc961974e55b }, { 0x0006e5ba0c5b997b, 0x000533a06d89b85d, 0x00095911bffc3d29, 0x0005e1aa2b90741a, 0x0000a4a9e49fefa6 }}, {{ 0x000b842ac7fd440d, 0x000775112e4c9366, 0x000d5187b6b3804a, 0x000e21ec9ae419f7, 0x0000853743dec424 }, { 0x0006ae3fc4509621, 0x000d3e9440d68277, 0x000e78d3bb4fe338, 0x000b99a925f69f4d, 0x00001ccb54d831d2 }}, {{ 0x000f9a722461f223, 0x000d3c2e9740b335, 0x000ce9c8647cec97, 0x000deea15677bc85, 0x0000f16ec53b5b06 }, { 0x000eb6094dff8468, 0x00051164ad859617, 0x000767a1a1fc7112, 0x000c1b57e5f8c47f, 0x0000305f263682f7 }}, {{ 0x0008ca06c000315d, 0x000c0fd341905477, 0x00037793ca900aec, 0x000ade7e68a394f4, 0x0000d89206088d97 }, { 0x0001ba76c1885187, 0x000ad626ffeec228, 0x0009b5136239e6b9, 0x000b437479d91bce, 0x0000a4b31a467b18 }}, {{ 0x000b0c03e9bb6ab5, 0x0006fcb28c682c67, 0x00080b06537181b0, 0x0007bb99827f2522, 0x0000e7f5e678902d }, { 0x000287223f5705ed, 0x000e33015b548e76, 0x000fd62c48b8a6ea, 0x0002b1f40a8be76d, 0x00002b41597b0af8 }}, {{ 0x000fcf45b93bfe6a, 0x000f6558b399320d, 0x0005e04f008d2b8f, 0x00027b05e61fe3fa, 0x00000320b1aab1c7 }, { 0x000c421d977c1dfe, 0x0009c512f684b432, 0x00049adfeccf138d, 0x00091a78ff796c65, 0x0000756d6c50e779 }}, {{ 0x000dc9d1ec6f170f, 0x000bea3af2ebc2fd, 0x000ced852c3855dd, 0x000b601b1a0af843, 0x0000efe50594d52d }, { 0x000740f316de5b77, 0x00051bb62771deb1, 0x000a7a84b76a9d83, 0x000c81aae829277a, 0x0000e1420c11bfa4 }}, }, { /* digit=34 (1,2,..,64)*(2^{238})*G */ {{ 0x000fcf57c64d0fe1, 0x000089aeeaf8c495, 0x000d0e557f623c19, 0x0001b346cee7aa73, 0x0000e3399090fc9a }, { 0x0006eb38aad81cf7, 0x000a739b6057604e, 0x0000db9b5314c754, 0x000f3472d7d343c0, 0x00004c1dfbe3a0a5 }}, {{ 0x000848949c160154, 0x0000e4f8be762b49, 0x00006d459f779d3d, 0x000d6b1fa2a9ee4d, 0x000073144722cd51 }, { 0x000631594e5d8939, 0x0009ee5d23a84178, 0x000d6db14456f57f, 0x000650e1f892f3b1, 0x0000d7a0b3f34fe0 }}, {{ 0x000a613a9e60b8e8, 0x000423cde918dcce, 0x00033c9c94ad800f, 0x00012332d2e7b599, 0x0000a4f91cafaad2 }, { 0x00000da7133e2037, 0x000286cf1fdc9f70, 0x000887923f6f84cb, 0x000fc857fb6eae8b, 0x0000f963508ecd1a }}, {{ 0x000585113ba8dd62, 0x00080ea1f095615b, 0x00065f617af767a6, 0x000aab6be0a28ad7, 0x0000085f54531694 }, { 0x00033ed1deec48b1, 0x000ae0b30df8aa1c, 0x000b877911cd914a, 0x000e64fcbaddda07, 0x00004abbcd21ba68 }}, {{ 0x000610ffa32530f1, 0x000285d80e877662, 0x000877ce4b1cfd91, 0x000b658349e99e6d, 0x0000e408841fab40 }, { 0x00090cb5663d4ea5, 0x000a2d4751c8159a, 0x0005062dddfd0fce, 0x000f8d733697b498, 0x000058975ab9e049 }}, {{ 0x00091be071c8396f, 0x000c94836f024cb1, 0x00071ce580f69081, 0x0004498f185be1f7, 0x0000741b76e70b14 }, { 0x00048a876e5adf25, 0x0007aa5cca5e55cb, 0x000c4345c73e6437, 0x0009de0db3864ba3, 0x0000cb37b2d41132 }}, {{ 0x00053fc7d8535a0e, 0x000b856580e40a2f, 0x000b7d40a0e49c2f, 0x0001f82c9f194ed8, 0x000020d26cc66d51 }, { 0x0003b7d63457b0ca, 0x000e49b78593e7d5, 0x0002ee238fa36714, 0x000f3099b2cac4ee, 0x000023acbadeefac }}, {{ 0x00032b33d4f558d6, 0x00037483e07113c9, 0x0008ea602fd9386b, 0x0000f762b6e4a5d3, 0x000040b7b04b7684 }, { 0x000f178169d618d6, 0x00020510dbbf08dd, 0x000885aab8e91f1c, 0x00043069b211d07c, 0x0000c105f022a618 }}, {{ 0x000b741973430cb0, 0x00096350a712229b, 0x00074db32619911c, 0x000070c8393cbe44, 0x0000fe88492c7c4c }, { 0x000da7715e131810, 0x000f9a256dbe6e72, 0x00062cb5c88e8a5a, 0x000078a31e578ec5, 0x0000121ed1b3bd72 }}, {{ 0x00084867a70ea8a3, 0x0008d1753dfabf0f, 0x0007c09b2ab277d6, 0x000b4f658728d207, 0x00008772d5dc2672 }, { 0x000c9017adeb92a2, 0x0000f3d70e35b1c7, 0x00079d20267edcd3, 0x0008c8f210241446, 0x00002a5362cc2cc0 }}, {{ 0x000461d767714a05, 0x00068e90a482873d, 0x0000e31c7d6d3a7f, 0x0003383e74265d6b, 0x00004a05abbc1234 }, { 0x000626833fe129d4, 0x000cac564a7e489c, 0x000cdab872b2a050, 0x00033754ecc5675c, 0x000089b5043845b7 }}, {{ 0x000568d0917c4acb, 0x000c55a83cdd60ed, 0x0004cbae30f32f9c, 0x000d8992a50602fb, 0x0000910f7a813c33 }, { 0x000ec2057b354ced, 0x00035c70259217fd, 0x0008e56f3c6925cc, 0x000490b6e93831cd, 0x0000a336551d0bd7 }}, {{ 0x000563cce247e851, 0x0005499f98a759a3, 0x0002c25e6f3b7c66, 0x000dca58755a0a7a, 0x00005ae8843b044c }, { 0x000eea4056f758e4, 0x0005117e7b1fbe12, 0x00092088f88989d2, 0x0007764db8a7dc97, 0x00000ee98d72925b }}, {{ 0x000ee376f827fa0f, 0x00059a7ba772b34e, 0x0000706aae49b0d1, 0x000f205dbe16ed34, 0x0000b5d4498eade7 }, { 0x0009a59c3b7533ce, 0x000dc1783674c027, 0x0006de9d65ef7473, 0x00070cb0f65832f9, 0x0000512581da9ee6 }}, {{ 0x000fa352b73388b3, 0x0009a2ebd19bb161, 0x00009382dacf6953, 0x000135847c6c7cfd, 0x0000dfe8b3751963 }, { 0x00059df31f52f920, 0x00035b8973db6d32, 0x0000c347c49fe544, 0x000c2371f7183685, 0x0000f1f4cc727793 }}, {{ 0x0008835dedbc740c, 0x0007d25913cc16df, 0x000ce91f116c9a1b, 0x000808dae18bc5b6, 0x000071a394c1d139 }, { 0x000ce433b9ac0821, 0x000ead865a40ab05, 0x0008bc6703c50add, 0x0000029696559643, 0x00009a0bfc436be6 }}, {{ 0x0001e29ee4d40158, 0x000984f6ad651437, 0x000764feac1214e7, 0x0009468c71151182, 0x0000fa9f57c32bae }, { 0x000b4d4bd6ce4114, 0x000e80963717b46b, 0x000e251d88cbd747, 0x00081172202be02f, 0x00001fa60920ef36 }}, {{ 0x0001cc10cacd0147, 0x000ad9620efd6628, 0x000043c91c4987a3, 0x000963dc292ba6d2, 0x00000e78ee2053ff }, { 0x0005c6097c119aa3, 0x000cdad4b4d7f6ce, 0x00059edbd3562f1a, 0x000ad44975c9f1d9, 0x0000702d0c39051f }}, {{ 0x000ea0e79fe0f90d, 0x000a2a6328e5e200, 0x000a45e06db05fe3, 0x000c6bc78f7b5244, 0x0000518bfd167866 }, { 0x000e3a0690854dfd, 0x00099eb646c7ecfb, 0x00028633e40d1fc1, 0x0005dd269eb81149, 0x000077f2043ce75a }}, {{ 0x00066dd6d2079f06, 0x0004c3d42e06189e, 0x000067cd28417e6e, 0x000130050bf07794, 0x0000de2c929cf8ba }, { 0x000333b1e86df344, 0x000b967ff99abde3, 0x00009477132566ad, 0x000536ed7c990355, 0x0000973cee61a30e }}, {{ 0x000982aad98c4636, 0x000db3c6c491c14e, 0x0007975a94ae8585, 0x00092fced0597668, 0x0000469878650d9d }, { 0x00092d6943d57f62, 0x000f1478be0dcf0e, 0x000d7c9ceaae9a12, 0x000bd457f700080a, 0x0000c7c4650a126e }}, {{ 0x00038b135b3697ef, 0x0009bf885dfe9aef, 0x0004599f736f9c08, 0x000480120d825d9a, 0x00009a6f60743203 }, { 0x000847fb2ab7025d, 0x0002de062a7150b5, 0x000db3ec1370558f, 0x000b9932ef31fd8d, 0x0000640e5b498396 }}, {{ 0x000ce5e866272fbc, 0x0008bdcdccbac8b2, 0x0007da0e9d6243e6, 0x0000930dfb642aa7, 0x00006481890aff49 }, { 0x0009424317123bb7, 0x0008088c98c44004, 0x000da8b80f62d7e6, 0x0008318d78104a8c, 0x0000c585f14062f4 }}, {{ 0x0000428dffccb096, 0x000cfe784d6365d8, 0x000f0f3311b8f429, 0x000378330bcb7443, 0x0000aa82351ab1ae }, { 0x00058c1fb6bdb9c6, 0x000e9efa4faf8433, 0x000dca1d65a933e3, 0x0008101ceced8538, 0x0000d4a8d9e6e600 }}, {{ 0x0008aba53a05bf33, 0x0008de5fd349961a, 0x0000db761dc2a9ea, 0x000e35a382b2cfa5, 0x0000b7879468dded }, { 0x000eebef3fda587c, 0x000b11d6e96eb8db, 0x00000cc3a6e277a8, 0x0000c796c65d8dea, 0x0000e172dfe107d8 }}, {{ 0x0005a760658ad3df, 0x0008e98ce7852541, 0x0002a5bd40fc7160, 0x000a56bddd50e8d7, 0x00005c3561e661be }, { 0x000e509af3870a6a, 0x0003822961f23d6a, 0x0007c59c25bcd2e9, 0x0007893e4378e443, 0x000027a005b340d3 }}, {{ 0x0005626678970f60, 0x0008e46577f44a13, 0x000c80af7872b352, 0x000e85884e09b748, 0x0000e421f514b45e }, { 0x000ceafe50229ea3, 0x0002218bf8d21e6b, 0x0000f51aa91d1556, 0x000a1d0c022d9653, 0x0000b69daf2a9172 }}, {{ 0x000e6c984782812a, 0x000b4f7be42a5821, 0x00004697d39f6d6b, 0x00067b1a9d3fc608, 0x0000472dc3a58087 }, { 0x0006fec314288ecc, 0x0007d25d30c31f70, 0x000aa52b5e0e12c8, 0x000798de7b7eb72b, 0x00005698fa1698c6 }}, {{ 0x000a05261d35c7d3, 0x000e910f8c22049d, 0x0006ad59994bee9c, 0x0006e5f6b9bfbcce, 0x000017336b3b0d0d }, { 0x000c744e8ee14501, 0x0005adceba7efc8d, 0x00094967709fe15a, 0x00030f027471237c, 0x0000b4abf8266348 }}, {{ 0x0007b411642b925d, 0x0009016a56edb730, 0x0007244c6d0c0d15, 0x000ee570064357e3, 0x000045c5461cf724 }, { 0x0008434e8e56e691, 0x0008d3274c898834, 0x0000e03f995f5bf2, 0x0001d53823c16282, 0x0000bfbc0e792c1e }}, {{ 0x00017b66ac0eda90, 0x000624f2c7ae0b94, 0x0000d7be4d9e6b1a, 0x0007eceb1c46fbf8, 0x000073445e243c47 }, { 0x000d06252a7f7cde, 0x00054b2c5ceec209, 0x000f449ba5b7dfa6, 0x00085a8e6d69661f, 0x0000bd415537281b }}, {{ 0x0009650f1aafc77c, 0x00018b07e50122b3, 0x000b118b6d8a8280, 0x000784d7bdd744f8, 0x0000b7a7039bee26 }, { 0x0003cde18959c8fa, 0x0004df71fa38477c, 0x0009110e30c5b652, 0x000a5bb8a3d815f1, 0x00000fab64c70c58 }}, {{ 0x000af52d3611da39, 0x000ba7bf9539a488, 0x0005e913946f430f, 0x0007dd3bbb0100e0, 0x00008c0902a3dbd8 }, { 0x0008a53a687694aa, 0x000f347dbbf698b0, 0x0009fb36e20b6928, 0x000d5b3f82961a1e, 0x0000e28e2ca89070 }}, {{ 0x0009d84d2e9b0fce, 0x0002d481bee45d41, 0x0006229033078bdf, 0x0001f5669b3cee34, 0x000090c773d3e729 }, { 0x000fb1fb1bd23754, 0x0006fc51c4d349f6, 0x0003a68b5ea950a0, 0x000747aae6596584, 0x0000f1319ee53ae6 }}, {{ 0x000f0bece2f566fc, 0x000010607bf8fe31, 0x0008155b86689659, 0x00090f4d346259c5, 0x0000d4aef04c0740 }, { 0x000849f911d26148, 0x0006cb3f3c72914e, 0x0004546b3a782574, 0x0000a254629e8ea9, 0x0000ef344da514b1 }}, {{ 0x00007d28f8169af0, 0x0003fbbf4737f217, 0x000af18cccb4682b, 0x0005ebdbed8dba5a, 0x00005fcad39eb18f }, { 0x0008f0c981a47c9b, 0x000ab0bcaa999eab, 0x000c63a21b4ad294, 0x00058242dba7b174, 0x0000fa27d77ce474 }}, {{ 0x0009619367bed35c, 0x0008e9a324b47379, 0x00029946a8624378, 0x0005f80edfba9e42, 0x00002193d51edbe3 }, { 0x000898978136c517, 0x000dc5754b7032b4, 0x0009dbaa3dc9b204, 0x000cbaf5af936b3b, 0x00005c1090706f4b }}, {{ 0x000ed617a5a061dc, 0x000f95a13d4f95eb, 0x0004eec56d5b0d63, 0x00012183d737cff8, 0x00001b08a819d5ea }, { 0x000791e248259760, 0x000f4017dfd8ab26, 0x000dd2968e62408c, 0x000108545ae7b89a, 0x000093d95add0afe }}, {{ 0x000d5c3a7fff1f96, 0x000a0ad324fa34d3, 0x00070f6273a886e1, 0x000bd9c99ea11144, 0x0000b3c3fd9df0bf }, { 0x000a251c3731c8ea, 0x000f1678d0412d2e, 0x000212b74f637f2d, 0x0005fbf82d92625e, 0x0000b4da522a951c }}, {{ 0x000cf06fd6232db8, 0x000d132790691bf5, 0x0008a9c6c6d87a37, 0x000a8836eed61058, 0x0000653769772e9d }, { 0x000cf4a1aa26fac0, 0x0007facd9588e411, 0x00020e9e83d4703b, 0x000800ace1f9bf76, 0x000079b3d81e1a3f }}, {{ 0x000fc099ea249902, 0x0008849dc1818d01, 0x000983a180c61c4b, 0x00005f4390643ff3, 0x00003e5c40cc22bf }, { 0x00058d9a82959817, 0x000a2c3eccd28fd0, 0x0002795eba28fb98, 0x0001c5eb6d743cbd, 0x0000a1953590ed50 }}, {{ 0x000603700554b317, 0x0000b9291262b72f, 0x0008c50b6efe112d, 0x0006d514296f924f, 0x000024bbaa00c3a9 }, { 0x00040606f5dab0ef, 0x0007a9e18d7dd96b, 0x000217a51d9f847f, 0x000dafa49381e878, 0x0000e4b811835102 }}, {{ 0x00020c00eed74984, 0x0003439fc6751a47, 0x0004899c000050c9, 0x000d0a4751619621, 0x000037a8d658db74 }, { 0x0007d16ea9dbaf18, 0x00086b0d820007cf, 0x000fabc9e97be6ba, 0x000705184880ee65, 0x0000435446efea6b }}, {{ 0x0005512b4e835c1f, 0x00056b2c0519a238, 0x000dca182794a57a, 0x000cd2b8a9ebf94f, 0x000043f096ab191e }, { 0x0003ebbb9869ab72, 0x00019a899b16a0de, 0x000bd6898d0eaeea, 0x000c0741595c2430, 0x0000e438ccd17837 }}, {{ 0x0003ec66f6fddbd1, 0x0006bfe18549fdb7, 0x000edbe1509ba54b, 0x000cfd46cf6e200b, 0x000098de96d82185 }, { 0x000c5616c5a42a40, 0x0006dd7d1b9a305c, 0x0008eb5804d7e8ed, 0x000a1c94aa959c5b, 0x00007e60385e5cc7 }}, {{ 0x000a06b329f8877b, 0x0005f01e6a33f7ce, 0x0006b347bd83ae53, 0x00039e07cc6217a0, 0x00007de49a6fee11 }, { 0x00012c4acbdef85a, 0x000b7cea5f5e7b9c, 0x000fb7501b28384f, 0x0001e515466dfc30, 0x00003b6c73cc9d54 }}, {{ 0x0005ad49e51ce957, 0x000361a1e407dd9b, 0x000bdc025fb2c747, 0x0008e60a5e8a3587, 0x0000375165792d8e }, { 0x0003f99fc369de26, 0x0008cb27006085ab, 0x000fd3c5cefed71b, 0x0005240a6a88ff33, 0x0000a54d6a89ede4 }}, {{ 0x00017969cd6413a4, 0x0009b5eb2e636456, 0x0007234ed864a3a1, 0x0000131cfbe57e54, 0x000097da13fc490e }, { 0x0008c4f4f07e5b7f, 0x000e9cd8a7017a0a, 0x000a15d689f8531a, 0x000ba987677b4d19, 0x0000622e9398a31d }}, {{ 0x000b8c3c1ca6d7d7, 0x0009acc67b3de77b, 0x000da7c33ce88288, 0x0009929c9ae3c0b8, 0x00005e532fdba5e3 }, { 0x00018487aab79e34, 0x000b4eac51b35836, 0x000f33a15e97b5d3, 0x00056d5f37591f5a, 0x0000464d53dbd05c }}, {{ 0x0007623bd0306c82, 0x00063f79d61718a7, 0x000bfe3096bc0a06, 0x000cfb3cf00413bc, 0x0000bd36a5580365 }, { 0x000b0231a0568154, 0x000d33bdcdd2a50c, 0x000a3aff52ce886d, 0x0004595294a741f9, 0x00006cbf37c0b0b8 }}, {{ 0x000a0c030ad04bbc, 0x000940d084bae24a, 0x00068a312388eb95, 0x000933c112f0ae8d, 0x000059d33f6ee7ac }, { 0x00089e38dd68ef7a, 0x0009361a0f442dea, 0x00067f1300f605ff, 0x000e94228f92e181, 0x00000cdb381fd9a1 }}, {{ 0x000ff5b8f078049a, 0x0001e65d2fdca23e, 0x0007dc993fa509ea, 0x0008bbc145a15ee0, 0x00008afe9e821989 }, { 0x0006f2789726e911, 0x000b9bbcb1c8a0ef, 0x000cc1d5c062c9d7, 0x0006103c02e1ee9c, 0x00007b357e712163 }}, {{ 0x00078ec0a2491df2, 0x000fd1c89ee6256c, 0x000da3a67aa3a41a, 0x000cb11b3f44ee1f, 0x00008112a4f22527 }, { 0x00023aae4f91b961, 0x000d224b7dccbc61, 0x000304010dd5da46, 0x000347705d96dd1f, 0x000040b329358dcb }}, {{ 0x000ccb9b14c45c47, 0x000b5f5a26262cd2, 0x000cd39550c052c7, 0x0008e5caf1f7f4d5, 0x0000e4892d07ecee }, { 0x0002fe771f54a03a, 0x000e2ad52324aa65, 0x00061f496834cafb, 0x0002935826320052, 0x0000a358d4c12366 }}, {{ 0x000d971c910c2659, 0x000483db1001684e, 0x000db3d982e44846, 0x000b52d72b56b4ee, 0x00008b44f48218c9 }, { 0x0008b44cb030e094, 0x000f291e3a07b296, 0x000c7c024a091d9c, 0x000e755ae7570d9e, 0x0000f4a48be7b74a }}, {{ 0x000e62960e80d5a9, 0x0008bb3bf44da801, 0x00093c509857d0c7, 0x000a2f700283834f, 0x000004d0d39a88e1 }, { 0x0006394239b24d7d, 0x000357be6901c550, 0x00081ec479e5e93a, 0x0005f457d80e7853, 0x00009467d044177d }}, {{ 0x0006f9d9edf5287c, 0x000ce40376c1944a, 0x0003bce03b234092, 0x000ec0e3b7cb6269, 0x0000dbfe013373c1 }, { 0x0006ce2871c6ea89, 0x000a3a2880dd2123, 0x00036f4311374ef1, 0x00024fe85903c381, 0x000070bac414fba5 }}, {{ 0x000d3ed11bf23e7f, 0x0003128e10d9c12f, 0x000105f062b7d445, 0x000649c587573baa, 0x00002d7ca95fda75 }, { 0x000beec455ef108f, 0x0001b9a0cb2748e2, 0x000831811ac094cc, 0x00064aa418239f01, 0x00008c7d897f4683 }}, {{ 0x000939e11117c855, 0x00001063f8b84cec, 0x0002c3fee75e7039, 0x000c0fedd7641708, 0x00003953dd909641 }, { 0x000585638f431edf, 0x000e3b35a914f2f1, 0x0003d1c62c0d57fb, 0x000fc50b039e35ed, 0x000031fe78392334 }}, {{ 0x000e8d6d63ec1c25, 0x0003f6e9e2fce99d, 0x00003ff3181bb02f, 0x00027902a68a2108, 0x0000a6146405e04a }, { 0x0003b6c03c53dedd, 0x000386342146a0a4, 0x00021af375e61c53, 0x00034aa878ba826f, 0x00007332a2758132 }}, {{ 0x00093c8fa198c421, 0x0008ebbb54dde39a, 0x000a32329dbdca62, 0x0002d37e1744e5e8, 0x000030383a3af937 }, { 0x00096449c0bb9f0d, 0x000ec56de058c5cc, 0x0001ca0b54b965e3, 0x000441167216235d, 0x0000a79f1b841b17 }}, {{ 0x00022e45572f2733, 0x000f574170693bd8, 0x000d22301dde4f72, 0x0001b4044a28e14f, 0x0000500450e45c27 }, { 0x00086c3726a97a95, 0x000d9e2e6a285cd9, 0x0001117303c981ff, 0x000cb23445866f21, 0x00006f51ec40b74e }}, {{ 0x000ad1ce128a1832, 0x000da2af7172277b, 0x000e51fae431e94f, 0x0002b5aa757b94f0, 0x00000f8d45d654a3 }, { 0x000ebc4f922ef269, 0x000849dd8f71caef, 0x000597638b146921, 0x0007aad37f43272a, 0x000009ef351a878e }}, {{ 0x0009c02205f112dc, 0x0009e952f41deff1, 0x000acc7b67b111a0, 0x0002d1d510e44a59, 0x0000fa3e8511d623 }, { 0x00051ff946f13b54, 0x000dc69c4b7d692e, 0x000317f509655586, 0x000e6b4462e6392c, 0x0000a96c730c5b29 }}, }, { /* digit=35 (1,2,..,64)*(2^{245})*G */ {{ 0x0000a3933301eb25, 0x000a651566c5c43e, 0x000854f45d136c9a, 0x000a9b44acff9c91, 0x0000afb49c7ad947 }, { 0x000a2e067e61d8ad, 0x0004dc10dc1eb2bf, 0x000135c5137c224f, 0x000bda57488cfd8c, 0x0000c44a7f8d059f }}, {{ 0x0006c13cc1c1b2ba, 0x000707f3e5f9f11f, 0x0009e009feccf526, 0x0004546bd9afe153, 0x0000da180beb161c }, { 0x000f8417a1d44bc5, 0x000008e325fc3ee3, 0x00006399ac1041ab, 0x000580ee77109540, 0x0000ceab562965db }}, {{ 0x000fab17514db1c6, 0x0008172813b230d7, 0x000e97892cd69e71, 0x000cdff6a634d0f5, 0x0000c7df5b396089 }, { 0x000b9815a106666f, 0x000a1a74f7c4f830, 0x000416725238afc5, 0x000ab9aa0a7d2edc, 0x000091170e9acf8b }}, {{ 0x000db6d961011f15, 0x000439b319540c33, 0x000964ccfd972723, 0x0008f8acb18490f5, 0x00000165db5b23d9 }, { 0x0003f6e09555115e, 0x00005bb146110697, 0x000e9391de70734b, 0x0006302d2b19436a, 0x000046716ed749df }}, {{ 0x0007e83eda22ea79, 0x0001a8eb6357f373, 0x0008f3f06b88b995, 0x000bf00fcc5d00f7, 0x000073b37b16df09 }, { 0x000b956bc10c800a, 0x000d8731560bf3d1, 0x0009017a42a05ea3, 0x000140abd1086e45, 0x000062690f21558e }}, {{ 0x000610ad741347e3, 0x000d891c31b9c38e, 0x000a62deaa41683d, 0x000f3c86f0c5aa90, 0x0000f90c15e6f59b }, { 0x000921d5778fdb23, 0x0004ddf02ba8e15d, 0x0005b38621fa615d, 0x00050e06c0337edb, 0x0000f89b6644d026 }}, {{ 0x000357c9e3ee8927, 0x0003d392c422f7ac, 0x000229dcbeb4ed3f, 0x000d2d5d1fb63536, 0x0000f4ae39a384d5 }, { 0x000c225a84c23dc0, 0x000f5405b2e5b8ce, 0x0000f4e05f1fef35, 0x000d1f1997e94693, 0x0000aeede3f666b8 }}, {{ 0x000b8a4cbe978aa8, 0x000fbc8ee3c76cb3, 0x0003979fd2b05b7b, 0x000d941563cf1162, 0x0000e542d606a5d0 }, { 0x0005e56df6f115ed, 0x0003ca59ce6bb278, 0x00017eef4378ebbf, 0x0000d8c8dc4afaa5, 0x0000a21b92c92f88 }}, {{ 0x0000ceb3fa8e1f73, 0x000163c2bf296984, 0x000496ffc2087462, 0x0007ae28f91fc19a, 0x000071c2f69ba91f }, { 0x0004cf10c29819fa, 0x0006660bc9ba369d, 0x000684a977ff8395, 0x000895207927e103, 0x0000429c81a856ee }}, {{ 0x0009c0d0a7824c13, 0x0004034859dd614c, 0x000a4f0ff846b7f2, 0x000813ed59c475b5, 0x0000cd1b934f7785 }, { 0x000230a6e8f478a9, 0x000dd91c234296f5, 0x00044257d8cd2650, 0x00071f3f22a0a83a, 0x0000ddf899163e18 }}, {{ 0x0000030a795ce50d, 0x000b20f72e3d5c1e, 0x00056f1e39259abd, 0x000fdf6343771744, 0x0000727bbec1ac3f }, { 0x000c8d087f282848, 0x00056bf1202e9ca6, 0x000c0959dd124705, 0x000b27cf8e79dde6, 0x0000ccb0bbb230c9 }}, {{ 0x00025cd048f7a136, 0x000913dbce913af4, 0x000b032d3782b56e, 0x0004ed68a909e587, 0x0000f4c845403bdd }, { 0x0001af92d3eba46f, 0x0004abe90e9d8bf9, 0x000aac93883ac9f8, 0x000767dff991616d, 0x00000f2d9eeda667 }}, {{ 0x000653fe47f4d959, 0x0006992e93fda293, 0x0007b3299374a645, 0x000d388e676bb6c1, 0x00002b338f3417ba }, { 0x000d70a99798c8cb, 0x00040280f680e752, 0x000bc14618d4da4f, 0x000a4773675eefd1, 0x000070102614081d }}, {{ 0x00005cf3d8688b24, 0x000be0720445c36d, 0x0001892a7d9c11b3, 0x000144fe971d1ac8, 0x000058a7f36a1f2c }, { 0x000e16f5c25e1654, 0x0008e0b7b1c7129b, 0x000f98876c302942, 0x0003df82dffadcc1, 0x000015505c986cfb }}, {{ 0x000e029db51b3c16, 0x0004fb8aad581350, 0x0008f57808095893, 0x00033c0a0622c211, 0x0000848670b38a49 }, { 0x000627cfbfce8544, 0x000803794fba0377, 0x0006ebdfc7e6bd5a, 0x000ab8f8eaefbd68, 0x0000239802ac6bee }}, {{ 0x00035dc5396eb247, 0x000c8ef4e4ca4631, 0x00072209072a4380, 0x000c5c200bcef728, 0x0000b72cb6549160 }, { 0x000b0c5738b12183, 0x000822e27bf1bc68, 0x000f7cd34933b26d, 0x000119eda10a224e, 0x0000c80f888434bc }}, {{ 0x0002cf43d8bba995, 0x000ba2a346060743, 0x00086e27c0a14c45, 0x000f74e0680fe7fe, 0x0000fac5f4d27a25 }, { 0x000dcd1a75979538, 0x000715f5f02ffe6f, 0x0003829db97527f4, 0x00033ad5e3d9eb9a, 0x0000209af43545e2 }}, {{ 0x000e5c0304618223, 0x000f48bb95560983, 0x000f41c035820ec0, 0x000e596124090a1d, 0x0000cc98be20fb39 }, { 0x000626289bc31852, 0x000ea4b70dceecab, 0x000461f93bf28884, 0x0001ae25cbb2d3c1, 0x0000160674019bab }}, {{ 0x000865a96da8e141, 0x00085598baebdcf4, 0x00092d795877cd89, 0x0007735d81a28ae0, 0x00006e178e1b6c8e }, { 0x00097f5dfc26037f, 0x0009ccd237936b24, 0x000b16c21697ffd9, 0x00006a247332f4f4, 0x0000ffad165e6c11 }}, {{ 0x000ec6787acea84e, 0x000febd32be5e0fc, 0x000648d99afacf1e, 0x0003024b17475bcb, 0x0000b743664d4e82 }, { 0x000fe814369d2cde, 0x0008214d8578c70c, 0x0007a8d35754fdd3, 0x000ce5a06c9ad99a, 0x0000e934ddca5774 }}, {{ 0x0008474a9996f7eb, 0x0002a822f4fb344d, 0x000f6ff85c520bf6, 0x000348c49b882344, 0x0000f420ddd2a3ce }, { 0x0007a033ec204ecb, 0x0004a4d5d1c00d06, 0x0008a69e46c0c3ed, 0x000d712f87fd581d, 0x000024e3f35d2d04 }}, {{ 0x00023c422eac602c, 0x000d2c19ef2d2e4a, 0x000e3364a85064df, 0x00011200a1bf6767, 0x00001c6223e12f57 }, { 0x00013599f87f98e9, 0x000822d540f83afd, 0x000d84b4acaf5dc6, 0x000912908c2c2c27, 0x00007299ce914de7 }}, {{ 0x000f627fd7a63a1a, 0x000315cd7b32c6ee, 0x000ffb93983d2957, 0x0005001bb61a5a63, 0x00007c449b79b37a }, { 0x00080cf93461f5c1, 0x0006efcc4c86bc81, 0x000aee0840c9e22d, 0x00095d433e6f9231, 0x0000b966edba2633 }}, {{ 0x000e0efb3b8b1b5d, 0x00038959884aaf7a, 0x000259a44d6afe4d, 0x000f91f87b1959be, 0x0000337331701bb0 }, { 0x000b01a0216bb368, 0x0000c5eca8c325e7, 0x000671fd9f4f814d, 0x000e76c1d3c91169, 0x000010645e8443c5 }}, {{ 0x0003a375e672dfca, 0x000e89363a1483f9, 0x0000e68119b07752, 0x000518de589eabe7, 0x0000537b9e85ecc1 }, { 0x000e0eb3eb3def9e, 0x000f5436a2afe69a, 0x0000335814a3a97e, 0x000978293c4f8910, 0x00004bb46fe72211 }}, {{ 0x0006fcd2c98f37de, 0x0009b0d9d79046e6, 0x000d05f136ad2051, 0x000cf40ca4d650f2, 0x0000c7cbce68d0b3 }, { 0x0006ddebdb5a0c55, 0x00009b5696605f18, 0x00071e6ee7b1b45a, 0x000ccfbcfe77e5d0, 0x000090641c6e2ee9 }}, {{ 0x000de285025363f9, 0x000513dfddf74157, 0x0008c18c08581775, 0x000318675f7fa130, 0x0000499a04911b96 }, { 0x00079deed354d5f0, 0x00080789e2aeb6b4, 0x0004aedc64ef1a47, 0x000c7ffc3ba2b9ff, 0x0000ff43ce38948a }}, {{ 0x000eaefbd10b4a81, 0x000379b3a8631e8d, 0x000d9b723b75c7a3, 0x000c1de118de855d, 0x0000b4dea0f1e6a4 }, { 0x00072cd4b1febb5e, 0x0003c8dd150892d4, 0x0005da5ea4d30538, 0x0007c011a37b8468, 0x00003fedb7f726b8 }}, {{ 0x000910e7019eb79c, 0x0005a51e9f05de9b, 0x000873d8a4a77728, 0x00080664cd404506, 0x0000f06a0d5cacfc }, { 0x000d896e2f49d140, 0x00016eab3aa8f0df, 0x000681650677644b, 0x0007b0620bab2a50, 0x0000225a11e3b301 }}, {{ 0x000d55e62f7b147f, 0x0002f53308fbd93d, 0x000d256d89ab7031, 0x00090048546cd5a2, 0x00008f07fbe7613f }, { 0x000f410b11223a4e, 0x0001ca02a81ede7f, 0x0003f9e643967f06, 0x0000701866860dd1, 0x000037f2d5f3b15e }}, {{ 0x00004aa9d3156f13, 0x000b93849ad467b6, 0x000baa288c1e44c4, 0x000e49060efb48b6, 0x00009eca1fbdd19b }, { 0x0003345e17323e5d, 0x0006786754e48e96, 0x0004d412c0772c5f, 0x000fcdab6693cb45, 0x00001eca39d6b65a }}, {{ 0x0005b4488b3fb1e8, 0x000d26b23a5d8961, 0x00056a2fedc3595e, 0x00081de771fe19e3, 0x00005b981b48385a }, { 0x0002c4f79da9b17b, 0x00017541a1f22bff, 0x000fb8bc6c4a7592, 0x00033ea8e920a8a6, 0x000037f6be35ab5e }}, {{ 0x0003272fd83d30cb, 0x000f8d04aa38d1b5, 0x000c62b22135dd8a, 0x0003013c03b0db35, 0x00000b015e47a001 }, { 0x0008a2e909f55c72, 0x000d74f07a8e1078, 0x0006e1dea8f06a53, 0x000ee63444a89e13, 0x0000850dcd40ec46 }}, {{ 0x0002e8a6205f5be2, 0x0007be3b44a3f84f, 0x000324de206fb879, 0x000c74190acb2f34, 0x0000169e7bbd47b0 }, { 0x000baae31cbf3f3b, 0x0006fb69c2d76521, 0x0003d1eae29fe835, 0x00042b610fb5307e, 0x0000e643f0cba58a }}, {{ 0x000959c3f21417f3, 0x000255bcbea62e7d, 0x000e119c6c6709d7, 0x00009921ce8ac9ea, 0x00004c4448bc0b85 }, { 0x0008f6c667720f2c, 0x000692520e40ae55, 0x0002aeab843a32e2, 0x0008386bc320789e, 0x0000f23eb6cec001 }}, {{ 0x00005e16bb852160, 0x00052bbc55d2d8b9, 0x00076498b39b48fc, 0x00066161441d58bb, 0x0000a86b13ffc50a }, { 0x00053f7146de7703, 0x0004e40f661acacd, 0x000ff5e2ff690eca, 0x000c929ba3b8784e, 0x00006044fa1265ab }}, {{ 0x000d45e2d4b575cf, 0x000bfe5e5681e833, 0x0005b966bb760ac6, 0x000f54b386212610, 0x0000920d33916add }, { 0x0000ca34a27332f1, 0x000d33976e8ae983, 0x000b8eea7b6bf672, 0x000057b89b53b2ee, 0x00008733d0036fff }}, {{ 0x0008a92a0eca49dd, 0x000fb6c783417303, 0x00087c7cb839b4d4, 0x00005e2388ef5beb, 0x0000914d653ceeed }, { 0x00093b5505c32a66, 0x000543f22433ccf6, 0x00063963b0a3b74d, 0x000ee34fcde8362d, 0x000054d95941e49d }}, {{ 0x000cbb9da03036b6, 0x000b5c0cd1797a18, 0x000e67fc118d1fef, 0x000c2923eea17b47, 0x0000697a3f1abc0d }, { 0x000986f3fa1f44ea, 0x000139c4d8424cff, 0x0000b195410c7287, 0x0003d1ca3db7048f, 0x0000c7c46d5a24e3 }}, {{ 0x0006210d9e58a61a, 0x00029b5224c08dca, 0x0003db93fef2cd7b, 0x00002ae4f2bbb09b, 0x00004673f3e36b54 }, { 0x000acede4893a3e0, 0x000167a09cb54d69, 0x000fb53a3b5bd9ea, 0x0006f485791eef6d, 0x0000d389cb15387b }}, {{ 0x000410cbabdf6c15, 0x000067190b771c33, 0x000486535b12a4e1, 0x0004bedff563b71e, 0x0000ecda5577d7de }, { 0x0003d7d5dee03f61, 0x000cc2630da84dd0, 0x0009ea44ecbb751b, 0x000151692d0711ae, 0x000014aba617814f }}, {{ 0x0004912ebf56ac82, 0x000ada8ced806b84, 0x000424ede5b8b06d, 0x0005059bf222e613, 0x000077ee32509e55 }, { 0x00024cc23645bf6a, 0x000cc742496c27c5, 0x000bcdaf647a66d4, 0x0001f552c8ea3176, 0x000068aa54cc75ce }}, {{ 0x0005468b2dae9bab, 0x00036d89f6f1b18b, 0x00048f86582e286b, 0x000f286fc2552f00, 0x00007485d84694f9 }, { 0x000ee3525470e487, 0x000b7883ff90f2ba, 0x000e802701cf5d83, 0x000725c2877947bd, 0x00000092a2e7377c }}, {{ 0x000c1f75e1fc6e4d, 0x000e97d3567962f6, 0x000f15694a198229, 0x00082e3a1379ed61, 0x000016040a7a66fe }, { 0x0005b5c318e65050, 0x00016423b4a79fce, 0x000c6f39817a3245, 0x000c19ca1f20bc83, 0x0000e78407cf44aa }}, {{ 0x000450a8760aef29, 0x000895d13221bc57, 0x0001f6ee42812871, 0x0004b6ca1707baad, 0x0000156dc61f6269 }, { 0x0002697b59a57f39, 0x0008453e5d0338fe, 0x000e491ec0628d37, 0x000e4b3d01e77f7a, 0x0000a053efd0726a }}, {{ 0x000d3b14f7467390, 0x00015bdda85d5347, 0x000f825cf9f2e0fe, 0x0008ff5e753e78c1, 0x000059772a4a8d49 }, { 0x0005e906b119a241, 0x00033b0cb8f2bd25, 0x00062c96a2e1fd6c, 0x00050eaab2d50b48, 0x0000699177c6e9dd }}, {{ 0x000dc63a9d42470f, 0x00013fc8fe280d19, 0x0005151ada0e3238, 0x000c459b0cd8e0de, 0x00004eff38b04e9e }, { 0x000f4187bc92bdf7, 0x000c53b4be1495fb, 0x0007d4178a70e616, 0x0004bd4dc25eb3db, 0x0000eb13072f9e75 }}, {{ 0x00078c2ec1e3ed4f, 0x00051691416a6a5e, 0x00085c63595aa0e1, 0x000163b5d8f860c7, 0x0000283d923fc854 }, { 0x0005beef7ad3f5b3, 0x0007b815ad735813, 0x000023a1511c7557, 0x0006b79bab4cc9e0, 0x0000199d8c4e721f }}, {{ 0x0000a1b1af1e78d3, 0x000f4cfdbcf41b9d, 0x0009de07e610f9cc, 0x0008a23d85703662, 0x000010d9697c4fc5 }, { 0x00023c2688aafc37, 0x0007c7503c41c4b1, 0x000af155a9b9f44b, 0x0003f540aa023829, 0x00006df810563aa5 }}, {{ 0x000f8aff74187332, 0x0008ecc36ba06eee, 0x00044e47cc9819db, 0x000c0b71fface311, 0x000023dc4d264ada }, { 0x00009a815983bd68, 0x00045042d05841bb, 0x000e84cfa0889ade, 0x0001ffa7e42f0e3d, 0x00006a7649f271c7 }}, {{ 0x000cee582b9889e1, 0x00045a10fee104a6, 0x0007ca159e31ee59, 0x000326733ad7788f, 0x000065aa11dd04af }, { 0x00044cc9c627cd7f, 0x0002267e8f55a7b8, 0x000655974f477505, 0x0003eaf9defbee3c, 0x00000dd76f26bfac }}, {{ 0x00065e1d58e34a25, 0x00069cd66926e04d, 0x000eaab2a4614ef5, 0x000205a070001e38, 0x00007f9aa8b3ba19 }, { 0x00091abd3f792d82, 0x000bf41be76ca2da, 0x000c3f7835fb599f, 0x00043b7d27895cf5, 0x000000657fe7cdbd }}, {{ 0x000e6ea8cc26f72a, 0x0001e8387eb36bff, 0x000192dce6e80e03, 0x000c29f5fc5f0710, 0x000060b97966ad86 }, { 0x000db3af99846589, 0x000c765edfa9284e, 0x00013dd8ddcbf735, 0x0008321fd6c510bd, 0x0000a06e6ac55647 }}, {{ 0x000b32a66e2632f7, 0x000809d6295d4269, 0x0006a471070d02cc, 0x0005b2f040c4f6ac, 0x00004f774520e665 }, { 0x000688122ab3d6ee, 0x0004566f0476ce2b, 0x0002ef7ab5896bbd, 0x000783a097554d95, 0x000014bb84887b9e }}, {{ 0x0009e6c0473150eb, 0x000218f508efb637, 0x0007f0d62f80b77c, 0x000f0c04f9eb5b5c, 0x000069accc4a1882 }, { 0x000dea6143dd9627, 0x000522ce37a1f698, 0x000a7569ca1c970e, 0x0002be4d3cbd252c, 0x00004fc80b2b91d6 }}, {{ 0x000e42f66dd9a70c, 0x0000846de6736294, 0x000e21f936b36c3b, 0x000215cc757f7aa1, 0x0000e42c4db111bf }, { 0x000f78959874b51d, 0x00067dc910778965, 0x000f6350f2c2eb73, 0x000e53487a0d690c, 0x00008713f1619ac6 }}, {{ 0x0009401711af5ba4, 0x000394752b16dba7, 0x0005bbe4aa9f7237, 0x000dc9293deefc0e, 0x0000a97c7a345d34 }, { 0x000c122b07c3fd19, 0x00093e9f21a15cb6, 0x000383dc6fe3e1fc, 0x00079e86c73d2616, 0x00000e249332ac22 }}, {{ 0x000e79dab8354f95, 0x00047e715f096905, 0x0001cf8235118233, 0x000890ac6508b9b1, 0x0000c766eb659330 }, { 0x000d4ca47748ce93, 0x0008ef06c775aa2e, 0x000b4a7b482a1c21, 0x000611206df09d8c, 0x00003cf5f801f0a6 }}, {{ 0x00087fc1cec8e5a8, 0x000363610bbb8b54, 0x0002bdc1ebd45d49, 0x0009d74cc0737ce8, 0x000003ccfa0ebc20 }, { 0x000a1b8ea3c1eb6f, 0x0000bb3b8bb36591, 0x000e6b42b27cef52, 0x000ff9344dea5df3, 0x000047617165cfc3 }}, {{ 0x000fbbcec8aedc8a, 0x000e71967b0867ce, 0x0007ad7a76578ca6, 0x0005466e38d5e0d0, 0x00007711fd87562a }, { 0x000079e8e108ea31, 0x000cbab0263ad100, 0x000dfc57a6a990e5, 0x00006d517d8199e6, 0x0000296d52bf5ee1 }}, {{ 0x0003b3afef9ade77, 0x000219f8a3422839, 0x000c147c62f6768b, 0x0008c19018097799, 0x0000ebf4142ddbef }, { 0x000ac70895b5ba6b, 0x000cf2a2db3d5ba7, 0x00020ef8474730ce, 0x0007efb73263dc46, 0x00004bc34642342a }}, {{ 0x00025b0834bbbd7c, 0x000524d5c2f342bb, 0x000a02d27279ffdf, 0x000a440d0bf80907, 0x000081a156479865 }, { 0x000ccd9a92ebac1a, 0x00074a56c3a1ddad, 0x000a29fb8884da05, 0x0007030fefe4ec7e, 0x0000acc66637fdc1 }}, {{ 0x000105a92d7a6a29, 0x000b4dadb58da1f8, 0x000f37c53dc1205c, 0x000f2214322bbc12, 0x0000f4c05d3cc006 }, { 0x00023213222f51a0, 0x0003bf37a859d51f, 0x00053e0f0648de72, 0x000bec7c9e3ec7ce, 0x0000fa1715d802dd }}, {{ 0x000bdec2116e9b29, 0x000389c76497ee80, 0x0006bb3874fd1cc1, 0x000343fe15d2b0ac, 0x0000a3fadcb3a4e1 }, { 0x00037248e9d64745, 0x00087efa63b10110, 0x0007dd6bd1db932c, 0x000c6c78bf9e3fa9, 0x00009e31d0655466 }}, }, { /* digit=36 (1,2,..,64)*(2^{252})*G */ {{ 0x000be5ed0e405bae, 0x0007fc91ec34f9e7, 0x0004b79b18f54024, 0x000b106f3d8772d3, 0x000037037c975e12 }, { 0x000aec44147d71ff, 0x0003d1931e82b100, 0x0007bf1327384e2c, 0x0002fb55ec63d285, 0x0000df2ba6d3b215 }}, {{ 0x0007a23f356e3059, 0x00041e71e29a3efb, 0x000f94f0f0f98de8, 0x0007a880ecbe906e, 0x00002d869e92df60 }, { 0x000cf0bbf87a34ec, 0x00089c2efd2119d3, 0x000ebfbd0dd06fa3, 0x0006c851303198c6, 0x000030a29d4bfdd3 }}, {{ 0x00089caef387625f, 0x000fcb72b7247593, 0x00017a38174726e5, 0x0001b102c945353e, 0x0000fcd0db4d1457 }, { 0x0003429bba3484a4, 0x0001753db65ef147, 0x000e6a574289160a, 0x0006d9c5f2dc2cb7, 0x00005d42b1ac334f }}, {{ 0x00012c9e1ee0d0a1, 0x0003490b01e6e274, 0x000da05414bdd548, 0x000de03a9047e2cc, 0x0000c371569c9623 }, { 0x00078851bc8c9a7d, 0x0000d36794075521, 0x0006dbaa6726fc38, 0x000ce611949c5013, 0x000053af2d9b1059 }}, {{ 0x00035aa24062df0d, 0x0002a52fb85fa4ca, 0x000d94e1eaa94f02, 0x0001840aed61257c, 0x0000fb93c2113070 }, { 0x0000d05aabec972c, 0x000f75d4421fc835, 0x00007292ec8f71dc, 0x000b37558f6df8ee, 0x0000d9d09ec67e4f }}, {{ 0x0000235a102cb4ec, 0x000fb35a64785f45, 0x000b0f0672f75fa1, 0x0002e6467bc56637, 0x00008030444d7012 }, { 0x000881065be741fe, 0x000b8d8f2c4aa658, 0x0000fb14fbdf31d8, 0x000b607bac347583, 0x00006adf01034a09 }}, {{ 0x000f12502f6f25d9, 0x0000c22cc1b5e838, 0x0000f6f93bcc544b, 0x0008c7ddfde2d4ad, 0x0000c68d49d6c0f8 }, { 0x0003511dcdcef6f9, 0x000a7dc7783920a0, 0x000dbd6b689c8148, 0x0000f52a6e80014a, 0x0000730b2f927704 }}, {{ 0x000211e48a709134, 0x000a06d95a7b1a29, 0x0005aa515d70a8ec, 0x000baface9c4e7ad, 0x00001420ee199ed7 }, { 0x0005f92e47355a0e, 0x000716ec78ef1f42, 0x000fe05e173edf3f, 0x000e4dfe82b2c090, 0x00005f26894a26e6 }}, {{ 0x0000e5daec35c312, 0x000444631890a36e, 0x000f77190f6f4a99, 0x000791e30703ef5f, 0x0000248d7cab9079 }, { 0x000a1bd7b6437663, 0x00041c3c9c9f1554, 0x00066b1d61acbaae, 0x000aa5c297e4bf17, 0x0000f13072c92c6b }}, {{ 0x000372def7fe9e8e, 0x000089946191d3d6, 0x000d1815135fa99d, 0x00071e788281fc8d, 0x0000e04cb9db1b55 }, { 0x0003bcefb0c7e3f0, 0x000cb480d8972cae, 0x000672598a8f1310, 0x0004d1cf43f2dd4b, 0x00005a02d3e37cbc }}, {{ 0x0005e8048f16243a, 0x0002f1ed785e73d3, 0x0005f8bdffd849c1, 0x000a2174aa5db5ab, 0x0000f3e31e72b2c9 }, { 0x000343d185ef14b5, 0x0005c8f1adaa0f81, 0x0005718a48d45076, 0x0005191b828ec3b4, 0x000095c49bafe83d }}, {{ 0x00037b515fb7aa40, 0x000b844caaa358cb, 0x0003e5a8c6cb2e2d, 0x000dd1d9a1a1db7e, 0x000027da7bc2cde4 }, { 0x0005a481c0d7db4b, 0x00089097b165fbe5, 0x00098c626e327572, 0x000dc967efc322ed, 0x0000c100250a4181 }}, {{ 0x00056b31e0992f90, 0x000c312c23fc9759, 0x0005706af79af358, 0x0005f4d391571580, 0x000032a43ce4ae5e }, { 0x000b37b634d74c5f, 0x00016d5ff7b33a68, 0x00098146b10a6fb6, 0x000e2c698c8d5dc3, 0x0000a98da6d07fa6 }}, {{ 0x000f40ac3c4dd2af, 0x000cfd68b11888c9, 0x000de0fd79a08293, 0x000b4f34a5e0e8c3, 0x00005ee377d3a06b }, { 0x000ef1ec28436dca, 0x000149534e0f63a7, 0x0001ec713cd110f6, 0x000f727b7a128bf9, 0x00005d0d98ab5496 }}, {{ 0x0000f1a43a4a1ad5, 0x0004f0fa36a27378, 0x0005e27077875e3c, 0x000e0939735dc136, 0x0000d7436395198a }, { 0x0000d7c67d880277, 0x000b04bf8cb0ba05, 0x00062fa0ff6e7415, 0x000ff59efb0b5376, 0x00001a3237f9a695 }}, {{ 0x0008910bd3c74498, 0x000d8af3aeac968f, 0x0008cc252692ed9e, 0x00067be64e4f7fee, 0x000092836060ef1c }, { 0x000890896b28139e, 0x000470cc9c0726e3, 0x0009a0eab753f427, 0x00046bc1b1530956, 0x000038600b6014d5 }}, {{ 0x00053794e8af97d5, 0x0007c5ca5618c937, 0x000b02a1ade8a949, 0x0005f92a8e665432, 0x0000f8ed81c1d707 }, { 0x000c21fb8d99ba56, 0x000957ce8c0dbccf, 0x00025d6478156ff5, 0x0008c850031e0261, 0x0000b4fb313fc9e3 }}, {{ 0x000b3bcc8886aff4, 0x0000d16b0843e0bb, 0x0007ae7478a94254, 0x00027e43053b1b3a, 0x000070a88a7167ff }, { 0x00047e1384f31100, 0x0001100c93dce831, 0x00018d1416a58415, 0x000039ce87e79da6, 0x000008370d177e00 }}, {{ 0x00034714e4870f2c, 0x00057d3af077f30f, 0x00031311a055c13d, 0x0006bc053ea78f84, 0x00006124e88ddd7b }, { 0x000ba0c58a21a931, 0x0002c15c2376c840, 0x00093179e1f91646, 0x000dbf9908315b65, 0x00005e507e2ffacd }}, {{ 0x000b7587e7d8f6a9, 0x000e47a529a6d482, 0x000d977c0a1b5071, 0x0003784f99c7f250, 0x0000a3bfb164138f }, { 0x00043e21ae8a2808, 0x000fa33e0182a650, 0x0007dfa2f0dba6d3, 0x000d3018fb82ecf8, 0x000055f7520eb309 }}, {{ 0x000e6559e9dabe39, 0x00010d666c834ea0, 0x000838dbe89dd09d, 0x000dbf1473be43e1, 0x000026c068976f46 }, { 0x000e63ef6977674b, 0x000b38e0c6615b48, 0x000cc7e1ae0786b6, 0x00076b88614abc8f, 0x0000e564e456248e }}, {{ 0x000faca8d0cebb8d, 0x00074b453b31e91a, 0x0003948a0c0742a8, 0x000bf70660cba7ad, 0x000094b060ddcf41 }, { 0x0008fb9a616bc52b, 0x000311d9ee9761ca, 0x000b47c4be2e0a39, 0x0003f554c3497a16, 0x00001a01ac4f5b97 }}, {{ 0x00024d301b78fa64, 0x000cefe392511143, 0x000c987a034b5852, 0x000ace55c36bf25b, 0x0000a71003604b62 }, { 0x000b211a0e5ee431, 0x000310cd670407e5, 0x000188521ff34062, 0x000def3e00ea8d4f, 0x0000dbd759ec2451 }}, {{ 0x000e220933648ca0, 0x000dd205ffe7b376, 0x000aa925c9a6a480, 0x000c325193b7f3ef, 0x0000519935e92c50 }, { 0x0006fa48a2afcd4b, 0x00015dfb486d440d, 0x000568e6ebc32df4, 0x0001776517fcfec4, 0x0000575cad80abc7 }}, {{ 0x000f59e604baf773, 0x000dc265872cd88f, 0x000b2831aa9d0b38, 0x000f9491c806c1d3, 0x00005ff0f174210f }, { 0x000212f245cd494b, 0x000c4327a0b85dd7, 0x000a21d9cfd1d70b, 0x0008cd713dec5720, 0x00009a66bf0ffb9c }}, {{ 0x000b75466ceb202d, 0x0001411b5cae787e, 0x00073287eab73556, 0x0005581fb13cb7f5, 0x0000e12d755e6d26 }, { 0x0000fbf8f7c29358, 0x000173bdb6cff322, 0x000a4100e1a2b244, 0x00091aa8b7440f37, 0x000020bd4b0b9af2 }}, {{ 0x000913b93cb994fa, 0x00098e1df83097f7, 0x000bdc374ec3de91, 0x00039352f28738f6, 0x0000d11cf177dae9 }, { 0x0000deb384609912, 0x00033931fe896366, 0x000f96a98121a3f9, 0x0007b93a17b98443, 0x0000d01181097cf0 }}, {{ 0x000ab007761cf94e, 0x00006c601a982e6c, 0x000069e1c5b02fb1, 0x000c41d051dd35e1, 0x000099e98577e95f }, { 0x0009c7a367e425f4, 0x000a71f6565e15ae, 0x0008a2c80cbe203f, 0x0007aea37bf30f52, 0x00007bf67fb4b3c4 }}, {{ 0x000f733e7e5b9a30, 0x0006ca552f03ad8b, 0x000842daf7427fea, 0x000299789c7e8dbe, 0x0000e03dc9ad2e74 }, { 0x000abfec927f95e5, 0x00016f5b8444823a, 0x0007c1385ba9089a, 0x000291140b7224e8, 0x00005f27d833f8e6 }}, {{ 0x000cff1ae2810e9b, 0x0007a10079ea1bd1, 0x000cb35e424422ff, 0x000d7f24f1ad9add, 0x0000223f4eaec892 }, { 0x0002b37f69fa04b0, 0x0000749d4cee1172, 0x000b1d83599fe6e3, 0x000489c388e9f275, 0x000066a58613b395 }}, {{ 0x000f59bf5ce72e10, 0x000e1fdb40146044, 0x000939e7911b9cb2, 0x0004b1efea8ce991, 0x0000b81a0bac185a }, { 0x0002588530df2495, 0x0009d4f923a277d8, 0x000ce2b6aed5cd2a, 0x000152751d9bc9b7, 0x0000c023c697a0ab }}, {{ 0x000cd15a3cc6fb9b, 0x000a19f82e4c6346, 0x0003cd730abb95f1, 0x000222f258efb831, 0x000068413078deb3 }, { 0x0001e7c1ed462bd3, 0x000d5fdbfcd8fb51, 0x000f5c6d0b354d1b, 0x000acc02f31db2ee, 0x00009cf8f2c231b2 }}, {{ 0x000c1b23430b5424, 0x000e10cdc9a151e9, 0x00079f9585161afe, 0x000026de79edbfc0, 0x0000dd01a58284f2 }, { 0x000676c6277d628a, 0x000928b7f8474b9c, 0x00063aff51f1e745, 0x0007dad5a90657c0, 0x0000a3eff6f709d8 }}, {{ 0x0006cc32b494aa16, 0x0001c47b7d6dee80, 0x00077299605ebcb8, 0x000011fed0948d92, 0x0000bd274de4ad55 }, { 0x0004428c5ee2c46b, 0x0006b64061ef338c, 0x0001fdc05d8e8c6b, 0x000d73e9b1606fa0, 0x0000c773ba6a62af }}, {{ 0x000205fb46da5307, 0x00021aef91b0b2ab, 0x00033e3801f8f3cd, 0x000ace1edce870a2, 0x0000468f39384030 }, { 0x0007205ff5fc9697, 0x00068e744cefa48d, 0x0007ca7816e1c2c7, 0x000209163b6fc37a, 0x000044e445df560c }}, {{ 0x000b1f606a304a7a, 0x00093328887de41e, 0x000b9b7f44ca4fe8, 0x0000c70175de0df0, 0x0000e1591f40e90c }, { 0x000901a9494fafda, 0x0006996e30ea15cb, 0x0001084797dc0097, 0x000bbd98f575816a, 0x00004054cb1612ae }}, {{ 0x0009f2630bb6056d, 0x000a208d8fc35489, 0x00003d4999fd2fa9, 0x000f8f85a5010b5d, 0x000008b55032749d }, { 0x00083d306cbd6562, 0x00019afb4e3b76fc, 0x000bf00347df1b02, 0x0009b30ce14e51dd, 0x00007b2794a6a001 }}, {{ 0x0007c824b04ea420, 0x000471577d4715c5, 0x000913a80d8575a1, 0x000c5c986d30019f, 0x0000d81758c67e87 }, { 0x000c66382097faea, 0x000692fd8f92a230, 0x00048f5357b258f0, 0x000eb2f9a4a557fd, 0x00000e310f808729 }}, {{ 0x000f50250aaa7e2c, 0x000928ff83a92661, 0x0006e1b1983af0c4, 0x0003f70ebc7741c9, 0x00004f20a513065d }, { 0x000e8025b4418b73, 0x0007bc81477b6547, 0x000d976fbfe6b5d7, 0x000bb3597c65b900, 0x0000304bd4ae9453 }}, {{ 0x000683125ec1f5d5, 0x00090ef12045cf9f, 0x000ea649d65eec4a, 0x000d990256fcb2ca, 0x00006feb137cf030 }, { 0x0005f11e11f4e767, 0x0003deae312410e0, 0x000766e7ca1eab36, 0x00013d80767e2867, 0x0000b79acfa040a4 }}, {{ 0x0004f1f61b1ed88a, 0x00070ef9d3472c26, 0x0007628b1d2a9b6f, 0x0003d25ee3adff69, 0x00007d01488de9be }, { 0x000bb88d5112808b, 0x00094ab9bfb9093f, 0x000ea55ab0ade7e8, 0x0004be60d3df8ae8, 0x0000c9e427871646 }}, {{ 0x000b283e83436d45, 0x000d64ce88c50d10, 0x00079d4eddcc4a93, 0x000ba49e47532e80, 0x0000ad9d0c90c59e }, { 0x0000afcff7b09b52, 0x000a09149e692749, 0x000787b8e224e80b, 0x0000d3e8eb96e966, 0x00009458dc2fcb01 }}, {{ 0x0001382d0c39d19c, 0x0000783210b08568, 0x00025db81b7d5f44, 0x000933909a5a8060, 0x00007b38a809ed42 }, { 0x0004fa1871dda89f, 0x0001b5381927e27e, 0x000165fae9106b66, 0x00004c3ce46c63b3, 0x0000a770fae667f6 }}, {{ 0x00070bd00e57f777, 0x00059bcd7466b255, 0x000a84178c56f6d2, 0x000449f8884ddbe1, 0x0000555f11ecdfbe }, { 0x000c7d249df1def7, 0x000bf29128bfa0f9, 0x000ccfa016cb0872, 0x0008881b192fce1b, 0x00005893d5343ec4 }}, {{ 0x000ac38b3da9a9f7, 0x00031bf0bbc6229b, 0x000e25158959fa61, 0x000d9e8051c83c05, 0x0000da4e85bd1746 }, { 0x000896ef10770631, 0x00086e3ec0dfcfd2, 0x000e627395068017, 0x0000c7966f2ecda8, 0x000082a16d1f7601 }}, {{ 0x0004a0885be18687, 0x000916a0fe9a745f, 0x000c5529e8801da0, 0x00096254908249fc, 0x0000b2610ba18a62 }, { 0x0009895a50a60550, 0x00067317d7ead588, 0x00058f0f76b3c827, 0x000274a89f96cf7d, 0x00000ccc62724ca9 }}, {{ 0x00023b9b36df10cd, 0x000ebe5573cecfa3, 0x000e9f2368affd6b, 0x000f7772066497ea, 0x0000e7189610325f }, { 0x0009369a44ac6ad3, 0x000660a0115a3c12, 0x000b042f2fca2382, 0x000e839789414c40, 0x000036e7483f7882 }}, {{ 0x000ee3e9bd875a0b, 0x00079f5903fa2711, 0x00029af6a861120e, 0x000561354e6da0fd, 0x00000c0f6913abd6 }, { 0x000948148819fd8a, 0x0008e1ce27a94979, 0x0003f4d9497c8870, 0x0002f21ca36d254e, 0x00009bc3a89fe40b }}, {{ 0x0007862d5db75ad2, 0x0002c6940d9cae17, 0x000f9a1ae1ab94f3, 0x00036e44b0586957, 0x00009909fd1ff97d }, { 0x00039531fedb222b, 0x0005a6e503491266, 0x00010e2ff490e472, 0x0009425a62be30bd, 0x0000fb87c6381af0 }}, {{ 0x0007bbabb687d4ad, 0x000bd11b29353593, 0x000677d066b77a80, 0x0008b697fda38aa9, 0x00008397f4e80b81 }, { 0x000dd9c0966b3966, 0x00013e02c9477784, 0x00052c405d304bb0, 0x00066490cd69a517, 0x000086e14cf5ff32 }}, {{ 0x00059cf5ae217581, 0x000af4d64f16ea85, 0x000628d490757f4e, 0x000f26f3e8b1cac1, 0x0000aed72ff0985a }, { 0x000c6e2c5d3b9f54, 0x00023bb0e2af19ae, 0x0000b4b46034cba9, 0x000cf35201f717ec, 0x000060bfeddfa2f6 }}, {{ 0x00077eaf4cee5651, 0x000997d3fca4752b, 0x00086a9346dd5414, 0x0009165b5f12c094, 0x0000c95b968e8b8d }, { 0x000b6d88c7322484, 0x000a381fda78fd37, 0x000faae161f6e327, 0x000d9a7c4848a83a, 0x0000f137df7a291d }}, {{ 0x000cc1bade2b6b43, 0x0007647ce417d99b, 0x0002cecfb1e654f4, 0x000bbf0234b93dcc, 0x00004be18fe3d4f5 }, { 0x0000e6a5a4e609ba, 0x00076114bc5ee855, 0x000470a83c3f2818, 0x000b337f1a561be7, 0x00002e0b52e72fc0 }}, {{ 0x000ae9bcf25208f9, 0x000071fa00b500bb, 0x000ba2941103788d, 0x0003b71855c098cf, 0x0000543d6d693c3a }, { 0x000d4f3fa4da32f1, 0x00035838435a2c5b, 0x000b8e5e069e748f, 0x0009a03e38ceaed6, 0x0000c306dcaca2f2 }}, {{ 0x0000ccfe8e6e9bc7, 0x000ea10a3db32927, 0x000a4469c7dc6903, 0x000ae1fa9e28a37d, 0x000071256bb0ed1f }, { 0x0008ff50ee6ae731, 0x000b3e03ba464b2d, 0x000dd3aa52a9b6ac, 0x00044e1ab0f39d60, 0x0000e50f6112c18d }}, {{ 0x000bd9abbfb15903, 0x0000d58fa28a7e00, 0x0005001c40b5393d, 0x000c99366c726cf2, 0x0000598cccad0929 }, { 0x00032a8b5f2075fd, 0x000f2074dfc47b3a, 0x000269286dbe5403, 0x00032c0e2d9c65fc, 0x0000df0b4df59f16 }}, {{ 0x000db8b22b2b7d9a, 0x000e26112e832330, 0x0002cf110cfd3ee9, 0x000fa75610fbb351, 0x0000c773f37679e1 }, { 0x000b47b17faba833, 0x0009efb89be01445, 0x00066f0f5fbb5ec7, 0x00061961c8c77d24, 0x0000cb969988de53 }}, {{ 0x000d2b61710647ca, 0x000d8b016287b52d, 0x000ff3a22d3f5266, 0x0008dbb73a134351, 0x00001e8a651d5fbf }, { 0x000061da3d7648b8, 0x00081291da3b3b75, 0x0008b862d1d32fd2, 0x000cf1d835f946d7, 0x00009b66ecb267fb }}, {{ 0x0005057a8f03a393, 0x000010dec1b49919, 0x0000a1ef0b1f2d70, 0x000769be0f12195e, 0x0000fd15ee98236f }, { 0x0007f25d916cad26, 0x000a3112e1301367, 0x0005bbd3af843715, 0x00053c82b97dfbb3, 0x000049bfae8df046 }}, {{ 0x0001f37cbd3c62c7, 0x00088986d840cd64, 0x0000a440abcf9eb9, 0x00065da61471d62c, 0x00009f893242a192 }, { 0x000904261943916d, 0x000350f4b7099851, 0x000bd6a472422402, 0x000fcf7467a7bd33, 0x0000da56f786a44f }}, {{ 0x00056fbb9354d802, 0x0008467cc36975fb, 0x0007e7ef6267c1ac, 0x00063a89402acf16, 0x000003023c61410c }, { 0x0001b7d9bedec678, 0x000950de9e405698, 0x000eb390c630ef9a, 0x0002b13977b99c65, 0x00009969974b5c5f }}, {{ 0x0007c7289562f9a3, 0x00075c0c716cc0a1, 0x00006da1f3b47558, 0x0003bc7c6f4b5ff9, 0x00000ff02fe0d66b }, { 0x000283d331c15563, 0x000ed85da6be7de9, 0x000da07e001d37e7, 0x0009ee5e8ff71530, 0x00002b7baaf41117 }}, {{ 0x000b9d6b1bdf4ea1, 0x0003c992a8498705, 0x000ae5b9f8196de5, 0x0004d3fe5a716964, 0x00004e830f707f38 }, { 0x000e1481a495c70b, 0x000ccd4a52f313bc, 0x000f9565c4bba5c4, 0x00077168fc9dd959, 0x0000dff7b5e2bd75 }}, {{ 0x0004af860fe1d658, 0x0005c3a43228d831, 0x00003626b989c96b, 0x000ceba2924ae1c3, 0x0000c45b79310a64 }, { 0x0002ceb1de0d0667, 0x00088613f714aa18, 0x000d68a9c780c9b4, 0x000a36f94f51865a, 0x0000055e19d4f0d9 }}, }, }; #endif /* #if !defined(_DISABLE_ECP_256R1_HARDCODED_BP_TBL_) */ IPP_OWN_DEFN(const cpPrecompAP *, gfpec_precom_nistP256r1_radix52_fun, (void)) { static cpPrecompAP t = { /* w */ 7, /* select function */ p256r1_select_ap_w7_ifma, /* precomputed data */ (BNU_CHUNK_T *)ifma_ec_nistp256r1_bp_precomp }; return &t; } #endif // (_IPP32E >= _IPP32E_K1) #endif /* #ifndef IFMA_ECPRECOMP7_P256_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_norm.c000066400000000000000000000225761470420105600257310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_defs.h" #include "gfpec/ecnist/ifma_norm.h" #include IPP_OWN_DEFN(m512, ifma_lnorm52, (const m512 a)) { const m512 mask52 = set1_i64(DIGIT_MASK); const m512 one = set1_i64(1ULL); const mask64 mask_shift_carry = 0xffffffffffffff00; const m512 idxi8 = set_i64(0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908, // 15, 14, 13, 12, 11, 10, 9, 8 0x0706050403020100, // 7, 6, 5, 4, 3, 2, 1, 0 0x0); // 0, 0, 0, 0, 0, 0, 0, 0 m512 r = a; int k1, k2; m512 carry = srai_i64(r, DIGIT_SIZE); carry = maskz_permutexvar_i8(mask_shift_carry, idxi8, carry); r = and_i64(r, mask52); r = add_i64(r, carry); k2 = (int)(cmp_i64_mask(mask52, r, _MM_CMPINT_EQ)); k1 = (int)(cmp_i64_mask(mask52, r, _MM_CMPINT_LT)); k1 = k2 + (k1 << 1); k1 ^= k2; r = mask_add_i64(r, (mask8)(k1), r, one); r = and_i64(r, mask52); return r; } IPP_OWN_DEFN(void, ifma_lnorm52_dual, (m512 pr1[], const m512 a1, m512 pr2[], const m512 a2)) { const m512 mask52 = set1_i64(DIGIT_MASK); const m512 one = set1_i64(1UL); const mask64 mask_shift_carry = 0xffffffffffffff00; const m512 idxi8 = set_i64(0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908, // 15, 14, 13, 12, 11, 10, 9, 8 0x0706050403020100, // 7, 6, 5, 4, 3, 2, 1, 0 0x0); // 0, 0, 0, 0, 0, 0, 0, 0 m512 r1 = a1; m512 r2 = a2; int k1_1, k1_2, k2_1, k2_2; m512 carry1 = srai_i64(r1, DIGIT_SIZE); m512 carry2 = srai_i64(r2, DIGIT_SIZE); carry1 = maskz_permutexvar_i8(mask_shift_carry, idxi8, carry1); carry2 = maskz_permutexvar_i8(mask_shift_carry, idxi8, carry2); r1 = and_i64(r1, mask52); r1 = add_i64(r1, carry1); r2 = and_i64(r2, mask52); r2 = add_i64(r2, carry2); k2_1 = (int)(cmp_i64_mask(mask52, r1, _MM_CMPINT_EQ)); k1_1 = (int)(cmp_i64_mask(mask52, r1, _MM_CMPINT_LT)); k2_2 = (int)(cmp_i64_mask(mask52, r2, _MM_CMPINT_EQ)); k1_2 = (int)(cmp_i64_mask(mask52, r2, _MM_CMPINT_LT)); k1_1 = k2_1 + (k1_1 << 1); k1_1 ^= k2_1; k1_2 = k2_2 + (k1_2 << 1); k1_2 ^= k2_2; r1 = mask_add_i64(r1, (mask8)(k1_1), r1, one); r1 = and_i64(r1, mask52); r2 = mask_add_i64(r2, (mask8)(k1_2), r2, one); r2 = and_i64(r2, mask52); *pr1 = r1; *pr2 = r2; return; } IPP_OWN_DEFN(m512, ifma_norm52, (const m512 a)) { const m512 mask52 = set1_i64(DIGIT_MASK); const m512 one = set1_i64(1LL); const m512 mone = set1_i64(-1LL); const mask64 mask_shift_carry = 0xFFFFFFFFFFFFFF00; const m512 idxi8 = set_i64(0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908, // 15, 14, 13, 12, 11, 10, 9, 8 0x0706050403020100, // 7, 6, 5, 4, 3, 2, 1, 0 0x0); // 0, 0, 0, 0, 0, 0, 0, 0 m512 r = a; /* standard step - first round normalization */ m512 carry = srai_i64(r, DIGIT_SIZE); carry = maskz_permutexvar_i8(mask_shift_carry, idxi8, carry); r = and_i64(r, mask52); r = add_i64(r, carry); /* create mask add ONE(1) to slot */ int k2 = (int)(cmp_i64_mask(mask52, r, _MM_CMPINT_EQ)); /* (r) == 0xF(13) */ int k1 = (int)(cmp_i64_mask(mask52, r, _MM_CMPINT_LT)); /* (r) > 0xF(13) */ k1 = k2 + (k1 << 1); k1 ^= k2; r = mask_add_i64(r, (mask8)(k1), r, one); /* create mask add MINUS ONE(-1) to slot */ const int cadd = 0x100; int ma = (int)(cmp_i64_mask(r, one, _MM_CMPINT_GE)); /* (r) >= 1 */ int mb = (int)(cmp_i64_mask(r, setzero_i64(), _MM_CMPINT_LT)); /* (r) < 0 */ /* add 0x100 - we make a number from which we subtract intentionally more */ ma += cadd; /* we emulate a shift to a neighboring slot, * as well as perform masking with 0xFF, * so as NOT to get a number greater than from which we will subtract. */ mb = (mb << 1) & 0xFF; /* calculate loans */ const int mc = ma - mb; /* after the step above, the problem arises that after subtracting from (ma), * we see dips of units (below in response) in those slots that do not need to add -1 * and these slots can be determined if 3 conditions are met: * 1) (ma) == 1 * 2) (mb) == 0 * 3) (mc) == 1 */ const int mx = ~(ma & (~mb) & mc); /* add mask mx AND if there was a suppression of 1 in the slot - add minus 1 */ const int mask_mone = (mx & mc) | (ma & ~mc); r = mask_add_i64(r, (mask8)mask_mone, r, mone); r = and_i64(r, mask52); return r; } IPP_OWN_DEFN(void, ifma_norm52_dual, (m512 pr1[], const m512 a1, m512 pr2[], const m512 a2)) { const m512 mask52 = set1_i64(DIGIT_MASK); const m512 one = set1_i64(1ULL); const m512 mone = set1_i64(-1); const mask64 mask_shift_carry = 0xFFFFFFFFFFFFFF00; const m512 idxi8 = set_i64(0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908, // 15, 14, 13, 12, 11, 10, 9, 8 0x0706050403020100, // 7, 6, 5, 4, 3, 2, 1, 0 0x0); // 0, 0, 0, 0, 0, 0, 0, 0 m512 r1 = a1; m512 r2 = a2; /* one */ /* 1 */ m512 carry1 = srai_i64(r1, DIGIT_SIZE); carry1 = maskz_permutexvar_i8(mask_shift_carry, idxi8, carry1); /* 2 */ m512 carry2 = srai_i64(r2, DIGIT_SIZE); carry2 = maskz_permutexvar_i8(mask_shift_carry, idxi8, carry2); /* 1 */ r1 = and_i64(r1, mask52); r1 = add_i64(r1, carry1); /* 2 */ r2 = and_i64(r2, mask52); r2 = add_i64(r2, carry2); /* add one slots */ /* 1 */ int k21 = (int)(cmp_i64_mask(mask52, r1, _MM_CMPINT_EQ)); int k11 = (int)(cmp_i64_mask(mask52, r1, _MM_CMPINT_LT)); /* 2 */ int k22 = (int)(cmp_i64_mask(mask52, r2, _MM_CMPINT_EQ)); int k12 = (int)(cmp_i64_mask(mask52, r2, _MM_CMPINT_LT)); /* 1 */ k11 = k21 + (k11 << 1); k11 ^= k21; /* 2 */ k12 = k22 + (k12 << 1); k12 ^= k22; r1 = mask_add_i64(r1, (mask8)(k11), r1, one); r2 = mask_add_i64(r2, (mask8)(k12), r2, one); /* add minus one in slots */ const int cadd = 0x100; /* 1 */ int ma1 = (int)(cmp_i64_mask(r1, one, _MM_CMPINT_GE)); int mb1 = (int)(cmp_i64_mask(r1, setzero_i64(), _MM_CMPINT_LT)); /* 2 */ int ma2 = (int)(cmp_i64_mask(r2, one, _MM_CMPINT_GE)); int mb2 = (int)(cmp_i64_mask(r2, setzero_i64(), _MM_CMPINT_LT)); /* 1 */ ma1 += cadd; mb1 = (mb1 << 1) & 0xFF; /* 2 */ ma2 += cadd; mb2 = (mb2 << 1) & 0xFF; /* 1 */ const int mc1 = ma1 - mb1; const int mx1 = ~(ma1 & (~mb1) & mc1); /* 2 */ const int mc2 = ma2 - mb2; const int mx2 = ~(ma2 & (~mb2) & mc2); const int mask_mone1 = (mx1 & mc1) | (ma1 & ~mc1); const int mask_mone2 = (mx2 & mc2) | (ma2 & ~mc2); /* 1 */ r1 = mask_add_i64(r1, (mask8)mask_mone1, r1, mone); r1 = and_i64(r1, mask52); /* 2 */ r2 = mask_add_i64(r2, (mask8)mask_mone2, r2, mone); r2 = and_i64(r2, mask52); *pr1 = r1; *pr2 = r2; return; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/ecnist/ifma_norm.h000066400000000000000000000042111470420105600257200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 _IFMA_NORM_H_ #define _IFMA_NORM_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "ifma_alias_avx512.h" /** * \brief * * Lightweight single-round normalization. Can be used after multiplication or * addition only. * * \param[in] a ptr value (52 radix and more) * \return m512 value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_lnorm52, (const m512 a)) /** * \brief * * Dual variant of ifma_lnorm52() function. * * \param[out] pr1 ptr first value (in radix 2^52) * \param[in] a1 value first (52 radix and more) * \param[out] pr2 ptr second value (in radix 2^52) * \param[in] a2 ptr value second (52 radix and more) */ IPP_OWN_DECL(void, ifma_lnorm52_dual, (m512 pr1[], const m512 a1, m512 pr2[], const m512 a2)) /** * \brief * * Subtraction single-round normalization. Can be used after subtraction or other. * * \param[in] a ptr value (52 radix and more) * \return m512 value (in radix 2^52) */ IPP_OWN_DECL(m512, ifma_norm52, (const m512 a)) /** * \brief * * Dual variant of ifma_norm52() function. * * \param[out] pr1 ptr first value (in radix 2^52) * \param[in] a1 value first (52 radix and more) * \param[out] pr2 ptr second value (in radix 2^52) * \param[in] a2 ptr value second (52 radix and more) */ IPP_OWN_DECL(void, ifma_norm52_dual, (m512 pr1[], const m512 a1, m512 pr2[], const m512 a2)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_NORM_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccp.h000066400000000000000000000145741470420105600241160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal ECC (prime) basic Definitions & Function Prototypes // // */ #if !defined(_NEW_PCP_ECCP_H) #define _NEW_PCP_ECCP_H #include "gfpec/pcpgfpecstuff.h" __IPPCP_INLINE IppsBigNumState* cpConstructBN(IppsBigNumState* pBN, cpSize len, BNU_CHUNK_T* pData, BNU_CHUNK_T* pBuffer) { BN_SET_ID(pBN); BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = len; BN_ROOM(pBN) = len; BN_NUMBER(pBN) = pData; BN_BUFFER(pBN) = pBuffer; return pBN; } /* // Recommended (Standard) Domain Parameters */ extern const BNU_CHUNK_T secp112r1_p[]; // (2^128 -3)/76439 extern const BNU_CHUNK_T secp112r1_a[]; extern const BNU_CHUNK_T secp112r1_b[]; extern const BNU_CHUNK_T secp112r1_gx[]; extern const BNU_CHUNK_T secp112r1_gy[]; extern const BNU_CHUNK_T secp112r1_r[]; extern BNU_CHUNK_T secp112r1_h; extern const BNU_CHUNK_T secp112r2_p[]; // (2^128 -3)/76439 extern const BNU_CHUNK_T secp112r2_a[]; extern const BNU_CHUNK_T secp112r2_b[]; extern const BNU_CHUNK_T secp112r2_gx[]; extern const BNU_CHUNK_T secp112r2_gy[]; extern const BNU_CHUNK_T secp112r2_r[]; extern BNU_CHUNK_T secp112r2_h; extern const BNU_CHUNK_T secp128r1_p[]; // 2^128 -2^97 -1 extern const BNU_CHUNK_T secp128r1_a[]; extern const BNU_CHUNK_T secp128r1_b[]; extern const BNU_CHUNK_T secp128r1_gx[]; extern const BNU_CHUNK_T secp128r1_gy[]; extern const BNU_CHUNK_T secp128r1_r[]; extern BNU_CHUNK_T secp128r1_h; extern const BNU_CHUNK_T* secp128_mx[]; extern const BNU_CHUNK_T secp128r2_p[]; // 2^128 -2^97 -1 extern const BNU_CHUNK_T secp128r2_a[]; extern const BNU_CHUNK_T secp128r2_b[]; extern const BNU_CHUNK_T secp128r2_gx[]; extern const BNU_CHUNK_T secp128r2_gy[]; extern const BNU_CHUNK_T secp128r2_r[]; extern BNU_CHUNK_T secp128r2_h; extern const BNU_CHUNK_T secp160r1_p[]; // 2^160 -2^31 -1 extern const BNU_CHUNK_T secp160r1_a[]; extern const BNU_CHUNK_T secp160r1_b[]; extern const BNU_CHUNK_T secp160r1_gx[]; extern const BNU_CHUNK_T secp160r1_gy[]; extern const BNU_CHUNK_T secp160r1_r[]; extern BNU_CHUNK_T secp160r1_h; extern const BNU_CHUNK_T secp160r2_p[]; // 2^160 -2^32 -2^14 -2^12 -2^9 -2^8 -2^7 -2^2 -1 extern const BNU_CHUNK_T secp160r2_a[]; extern const BNU_CHUNK_T secp160r2_b[]; extern const BNU_CHUNK_T secp160r2_gx[]; extern const BNU_CHUNK_T secp160r2_gy[]; extern const BNU_CHUNK_T secp160r2_r[]; extern BNU_CHUNK_T secp160r2_h; extern const BNU_CHUNK_T secp192r1_p[]; // 2^192 -2^64 -1 extern const BNU_CHUNK_T secp192r1_a[]; extern const BNU_CHUNK_T secp192r1_b[]; extern const BNU_CHUNK_T secp192r1_gx[]; extern const BNU_CHUNK_T secp192r1_gy[]; extern const BNU_CHUNK_T secp192r1_r[]; extern BNU_CHUNK_T secp192r1_h; extern const BNU_CHUNK_T secp224r1_p[]; // 2^224 -2^96 +1 extern const BNU_CHUNK_T secp224r1_a[]; extern const BNU_CHUNK_T secp224r1_b[]; extern const BNU_CHUNK_T secp224r1_gx[]; extern const BNU_CHUNK_T secp224r1_gy[]; extern const BNU_CHUNK_T secp224r1_r[]; extern BNU_CHUNK_T secp224r1_h; extern const BNU_CHUNK_T secp256r1_p[]; // 2^256 -2^224 +2^192 +2^96 -1 extern const BNU_CHUNK_T secp256r1_a[]; extern const BNU_CHUNK_T secp256r1_b[]; extern const BNU_CHUNK_T secp256r1_gx[]; extern const BNU_CHUNK_T secp256r1_gy[]; extern const BNU_CHUNK_T secp256r1_r[]; extern BNU_CHUNK_T secp256r1_h; extern const BNU_CHUNK_T secp384r1_p[]; // 2^384 -2^128 -2^96 +2^32 -1 extern const BNU_CHUNK_T secp384r1_a[]; extern const BNU_CHUNK_T secp384r1_b[]; extern const BNU_CHUNK_T secp384r1_gx[]; extern const BNU_CHUNK_T secp384r1_gy[]; extern const BNU_CHUNK_T secp384r1_r[]; extern BNU_CHUNK_T secp384r1_h; extern const BNU_CHUNK_T secp521r1_p[]; // 2^521 -1 extern const BNU_CHUNK_T secp521r1_a[]; extern const BNU_CHUNK_T secp521r1_b[]; extern const BNU_CHUNK_T secp521r1_gx[]; extern const BNU_CHUNK_T secp521r1_gy[]; extern const BNU_CHUNK_T secp521r1_r[]; extern BNU_CHUNK_T secp521r1_h; extern const BNU_CHUNK_T tpmBN_p256p_p[]; // TPM BN_P256 extern const BNU_CHUNK_T tpmBN_p256p_a[]; extern const BNU_CHUNK_T tpmBN_p256p_b[]; extern const BNU_CHUNK_T tpmBN_p256p_gx[]; extern const BNU_CHUNK_T tpmBN_p256p_gy[]; extern const BNU_CHUNK_T tpmBN_p256p_r[]; extern BNU_CHUNK_T tpmBN_p256p_h; extern const BNU_CHUNK_T tpmSM2_p256_p[]; // TPM SM2_P256 extern const BNU_CHUNK_T tpmSM2_p256_a[]; extern const BNU_CHUNK_T tpmSM2_p256_b[]; extern const BNU_CHUNK_T tpmSM2_p256_gx[]; extern const BNU_CHUNK_T tpmSM2_p256_gy[]; extern const BNU_CHUNK_T tpmSM2_p256_r[]; extern BNU_CHUNK_T tpmSM2_p256_h; extern const BNU_CHUNK_T* tpmSM2_p256_p_mx[]; /* half of some std modulus */ extern const BNU_CHUNK_T h_secp128r1_p[]; extern const BNU_CHUNK_T h_secp192r1_p[]; extern const BNU_CHUNK_T h_secp224r1_p[]; extern const BNU_CHUNK_T h_secp256r1_p[]; extern const BNU_CHUNK_T h_secp384r1_p[]; extern const BNU_CHUNK_T h_secp521r1_p[]; extern const BNU_CHUNK_T h_tpmSM2_p256_p[]; __IPPCP_INLINE BNU_CHUNK_T* cpModAdd_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, const BNU_CHUNK_T* pM, int ns, BNU_CHUNK_T* pBuffer) { BNU_CHUNK_T e = cpAdd_BNU(pR, pA, pB, ns); e -= cpSub_BNU(pBuffer, pR, pM, ns); MASKED_COPY_BNU(pR, e, pR, pBuffer, ns); return pR; } __IPPCP_INLINE BNU_CHUNK_T* cpModSub_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, const BNU_CHUNK_T* pM, int ns, BNU_CHUNK_T* pBuffer) { BNU_CHUNK_T e = cpSub_BNU(pR, pA, pB, ns); cpAdd_BNU(pBuffer, pR, pM, ns); MASKED_COPY_BNU(pR, (0-e), pBuffer, pR, ns); return pR; } #endif /* _NEW_PCP_ECCP_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_112r1.c000066400000000000000000000032151470420105600257440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp112r1 // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp112r1 */ const BNU_CHUNK_T secp112r1_p[] = { // (2^128 -3)/76439 LL(0xBEAD208B, 0x5E668076), LL(0x2ABF62E3, 0xDB7C)}; const BNU_CHUNK_T secp112r1_a[] = { LL(0xBEAD2088, 0x5E668076), LL(0x2ABF62E3, 0xDB7C)}; const BNU_CHUNK_T secp112r1_b[] = { LL(0x11702B22, 0x16EEDE89), LL(0xF8BA0439, 0x659E)}; const BNU_CHUNK_T secp112r1_gx[] = { LL(0xF9C2F098, 0x5EE76B55), LL(0x7239995A, 0x0948)}; const BNU_CHUNK_T secp112r1_gy[] = { LL(0x0FF77500, 0xC0A23E0E), LL(0xE5AF8724, 0xA89C)}; const BNU_CHUNK_T secp112r1_r[] = { LL(0xAC6561C5, 0x5E7628DF), LL(0x2ABF62E3, 0xDB7C)}; BNU_CHUNK_T secp112r1_h = 1; #endif /* _IPP_DATA */cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_112r2.c000066400000000000000000000032151470420105600257450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp112r2 // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp112r2 */ const BNU_CHUNK_T secp112r2_p[] = { // (2^128 -3)/76439 LL(0xBEAD208B, 0x5E668076), LL(0x2ABF62E3, 0xDB7C)}; const BNU_CHUNK_T secp112r2_a[] = { LL(0x5C0EF02C, 0x8A0AAAF6), LL(0xC24C05F3, 0x6127)}; const BNU_CHUNK_T secp112r2_b[] = { LL(0x4C85D709, 0xED74FCC3), LL(0xF1815DB5, 0x51DE)}; const BNU_CHUNK_T secp112r2_gx[] = { LL(0xD0928643, 0xB4E1649D), LL(0x0AB5E892, 0x4BA3)}; const BNU_CHUNK_T secp112r2_gy[] = { LL(0x6E956E97, 0x3747DEF3), LL(0x46F5882E, 0xADCD)}; const BNU_CHUNK_T secp112r2_r[] = { LL(0x0520D04B, 0xD7597CA1), LL(0x0AAFD8B8, 0x36DF)}; BNU_CHUNK_T secp112r2_h = 4; #endif /* _IPP_DATA */cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_128r1.c000066400000000000000000000035221470420105600257540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp128r1 (* Montgomery Friendly Modulus (+1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp128r1 */ const BNU_CHUNK_T h_secp128r1_p[] = { // halpf of secp128r1_p LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0x7FFFFFFE)}; const BNU_CHUNK_T secp128r1_p[] = { // 2^128 -2^97 -1 LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFD), LL(0, 0)}; const BNU_CHUNK_T secp128r1_a[] = { LL(0xFFFFFFFC, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFD)}; const BNU_CHUNK_T secp128r1_b[] = { LL(0x2CEE5ED3, 0xD824993C), LL(0x1079F43D, 0xE87579C1)}; const BNU_CHUNK_T secp128r1_gx[] = { LL(0xA52C5B86, 0x0C28607C), LL(0x8B899B2D, 0x161FF752)}; const BNU_CHUNK_T secp128r1_gy[] = { LL(0xDDED7A83, 0xC02DA292), LL(0x5BAFEB13, 0xCF5AC839)}; const BNU_CHUNK_T secp128r1_r[] = { LL(0x9038A115, 0x75A30D1B), LL(0x00000000, 0xFFFFFFFE)}; BNU_CHUNK_T secp128r1_h = 1; #endif /* _IPP_DATA */cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_128r2.c000066400000000000000000000033271470420105600257600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp128r2 (* Montgomery Friendly Modulus (+1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp128r2 */ const BNU_CHUNK_T secp128r2_p[] = { // 2^128 -2^97 -1 LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFD), LL(0, 0)}; const BNU_CHUNK_T secp128r2_a[] = { LL(0xBFF9AEE1, 0xBF59CC9B), LL(0xD1B3BBFE, 0xD6031998)}; const BNU_CHUNK_T secp128r2_b[] = { LL(0xBB6D8A5D, 0xDC2C6558), LL(0x80D02919, 0x5EEEFCA3)}; const BNU_CHUNK_T secp128r2_gx[] = { LL(0xCDEBC140, 0xE6FB32A7), LL(0x5E572983, 0x7B6AA5D8)}; const BNU_CHUNK_T secp128r2_gy[] = { LL(0x5FC34B44, 0x7106FE80), LL(0x894D3AEE, 0x27B6916A)}; const BNU_CHUNK_T secp128r2_r[] = { LL(0x0613B5A3, 0xBE002472), LL(0x7FFFFFFF, 0x3FFFFFFF)}; BNU_CHUNK_T secp128r2_h = 4; #endif /* _IPP_DATA */cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_160r1.c000066400000000000000000000034101470420105600257440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp160r1 // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp160r1 */ const BNU_CHUNK_T secp160r1_p[] = { // 2^160 -2^31 -1 LL(0x7FFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0xFFFFFFFF)}; const BNU_CHUNK_T secp160r1_a[] = { LL(0x7FFFFFFC, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0xFFFFFFFF)}; const BNU_CHUNK_T secp160r1_b[] = { LL(0xC565FA45, 0x81D4D4AD), LL(0x65ACF89F, 0x54BD7A8B), L_(0x1C97BEFC)}; const BNU_CHUNK_T secp160r1_gx[] = { LL(0x13CBFC82, 0x68C38BB9), LL(0x46646989, 0x8EF57328), L_(0x4A96B568)}; const BNU_CHUNK_T secp160r1_gy[] = { LL(0x7AC5FB32, 0x04235137), LL(0x59DCC912, 0x3168947D), L_(0x23A62855)}; const BNU_CHUNK_T secp160r1_r[] = { LL(0xCA752257, 0xF927AED3), LL(0x0001F4C8, 0x00000000), LL(0x00000000, 0x1)}; BNU_CHUNK_T secp160r1_h = 1; #endif /* _IPP_DATA */cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_160r2.c000066400000000000000000000034501470420105600257510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp160r2 // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp160r2 */ const BNU_CHUNK_T secp160r2_p[] = { // 2^160 -2^32 -2^14 -2^12 -2^9 -2^8 -2^7 -2^2 -1 LL(0xFFFFAC73, 0xFFFFFFFE), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0xFFFFFFFF)}; const BNU_CHUNK_T secp160r2_a[] = { LL(0xFFFFAC70, 0xFFFFFFFE), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0xFFFFFFFF)}; const BNU_CHUNK_T secp160r2_b[] = { LL(0xF50388BA, 0x04664D5A), LL(0xAB572749, 0xFB59EB8B), L_(0xB4E134D3)}; const BNU_CHUNK_T secp160r2_gx[] = { LL(0x3144CE6D, 0x30F7199D), LL(0x1F4FF11B, 0x293A117E), L_(0x52DCB034)}; const BNU_CHUNK_T secp160r2_gy[] = { LL(0xA7D43F2E, 0xF9982CFE), LL(0xE071FA0D, 0xE331F296), L_(0xFEAFFEF2)}; const BNU_CHUNK_T secp160r2_r[] = { LL(0xF3A1A16B, 0xE786A818), LL(0x0000351E, 0x00000000), LL(0x00000000, 0x1)}; BNU_CHUNK_T secp160r2_h = 1; #endif /* _IPP_DATA */cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_192r1.c000066400000000000000000000040451470420105600257560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp192r1 (* Montgomery Friendly Modulus (+1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp192r1 */ const BNU_CHUNK_T h_secp192r1_p[] = { // half of secp192r1_p LL(0xFFFFFFFF, 0x7FFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0x7FFFFFFF)}; const BNU_CHUNK_T secp192r1_p[] = { // 2^192 -2^64 -1 LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFE, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x0, 0x0)}; const BNU_CHUNK_T secp192r1_a[] = { LL(0xFFFFFFFC, 0xFFFFFFFF), LL(0xFFFFFFFE, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF)}; const BNU_CHUNK_T secp192r1_b[] = { LL(0xC146B9B1, 0xFEB8DEEC), LL(0x72243049, 0x0FA7E9AB), LL(0xE59C80E7, 0x64210519)}; const BNU_CHUNK_T secp192r1_gx[] = { LL(0x82FF1012, 0xF4FF0AFD), LL(0x43A18800, 0x7CBF20EB), LL(0xB03090F6, 0x188DA80E)}; const BNU_CHUNK_T secp192r1_gy[] = { LL(0x1E794811, 0x73F977A1), LL(0x6B24CDD5, 0x631011ED), LL(0xFFC8DA78, 0x07192B95)}; const BNU_CHUNK_T secp192r1_r[] = { LL(0xB4D22831, 0x146BC9B1), LL(0x99DEF836, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF)}; BNU_CHUNK_T secp192r1_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_224r1.c000066400000000000000000000042461470420105600257550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp224r1 (* Montgomery Friendly Modulus (-1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp224r1 */ const BNU_CHUNK_T h_secp224r1_p[] = { // half of secp224r1_p LL(0x00000000, 0x00000000), LL(0x80000000, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x7FFFFFFF, 0x0)}; const BNU_CHUNK_T secp224r1_p[] = { // 2^224 -2^96 +1 LL(0x00000001, 0x00000000), LL(0x00000000, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0x0)}; const BNU_CHUNK_T secp224r1_a[] = { LL(0xFFFFFFFE, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFE), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0xFFFFFFFF)}; const BNU_CHUNK_T secp224r1_b[] = { LL(0x2355FFB4, 0x270B3943), LL(0xD7BFD8BA, 0x5044B0B7), LL(0xF5413256, 0x0C04B3AB), L_(0xB4050A85)}; const BNU_CHUNK_T secp224r1_gx[] = { LL(0x115C1D21, 0x343280D6), LL(0x56C21122, 0x4A03C1D3), LL(0x321390B9, 0x6BB4BF7F), L_(0xB70E0CBD)}; const BNU_CHUNK_T secp224r1_gy[] = { LL(0x85007E34, 0x44D58199), LL(0x5A074764, 0xCD4375A0), LL(0x4C22DFE6, 0xB5F723FB), L_(0xBD376388)}; const BNU_CHUNK_T secp224r1_r[] = { LL(0x5C5C2A3D, 0x13DD2945), LL(0xE0B8F03E, 0xFFFF16A2), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0xFFFFFFFF)}; BNU_CHUNK_T secp224r1_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_256r1.c000066400000000000000000000044141470420105600257570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp256r1 (* Montgomery Friendly Modulus (+1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp256r1 */ const BNU_CHUNK_T h_secp256r1_p[] = { // half of secp256r1_p LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x7FFFFFFF, 0x00000000), LL(0x00000000, 0x80000000), LL(0x80000000, 0x7FFFFFFF)}; const BNU_CHUNK_T secp256r1_p[] = { // 2^256 -2^224 +2^192 +2^96 -1 LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0x00000000), LL(0x00000000, 0x00000000), LL(0x00000001, 0xFFFFFFFF), LL(0x0, 0x0)}; const BNU_CHUNK_T secp256r1_a[] = { LL(0xFFFFFFFC, 0xFFFFFFFF), LL(0xFFFFFFFF, 0x00000000), LL(0x00000000, 0x00000000), LL(0x00000001, 0xFFFFFFFF)}; const BNU_CHUNK_T secp256r1_b[] = { LL(0x27D2604B, 0x3BCE3C3E), LL(0xCC53B0F6, 0x651D06B0), LL(0x769886BC, 0xB3EBBD55), LL(0xAA3A93E7, 0x5AC635D8)}; const BNU_CHUNK_T secp256r1_gx[] = { LL(0xD898C296, 0xF4A13945), LL(0x2DEB33A0, 0x77037D81), LL(0x63A440F2, 0xF8BCE6E5), LL(0xE12C4247, 0x6B17D1F2)}; const BNU_CHUNK_T secp256r1_gy[] = { LL(0x37BF51F5, 0xCBB64068), LL(0x6B315ECE, 0x2BCE3357), LL(0x7C0F9E16, 0x8EE7EB4A), LL(0xFE1A7F9B, 0x4FE342E2)}; const BNU_CHUNK_T secp256r1_r[] = { LL(0xFC632551, 0xF3B9CAC2), LL(0xA7179E84, 0xBCE6FAAD), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x00000000, 0xFFFFFFFF)}; BNU_CHUNK_T secp256r1_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_384r1.c000066400000000000000000000052461470420105600257650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp384r1 (* Montgomery Friendly Modulus (0x0000000100000001) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp384r1 */ const BNU_CHUNK_T h_secp384r1_p[] = { // half of secp384r1_p LL(0x7FFFFFFF, 0x00000000), LL(0x80000000, 0x7FFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0x7FFFFFFF)}; const BNU_CHUNK_T secp384r1_p[] = { // 2^384 -2^128 -2^96 +2^32 -1 LL(0xFFFFFFFF, 0x00000000), LL(0x00000000, 0xFFFFFFFF), LL(0xFFFFFFFE, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x0, 0x0)}; const BNU_CHUNK_T secp384r1_a[] = { LL(0xFFFFFFFC, 0x00000000), LL(0x00000000, 0xFFFFFFFF), LL(0xFFFFFFFE, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF)}; const BNU_CHUNK_T secp384r1_b[] = { LL(0xD3EC2AEF, 0x2A85C8ED), LL(0x8A2ED19D, 0xC656398D), LL(0x5013875A, 0x0314088F), LL(0xFE814112, 0x181D9C6E), LL(0xE3F82D19, 0x988E056B), LL(0xE23EE7E4, 0xB3312FA7)}; const BNU_CHUNK_T secp384r1_gx[] = { LL(0x72760AB7, 0x3A545E38), LL(0xBF55296C, 0x5502F25D), LL(0x82542A38, 0x59F741E0), LL(0x8BA79B98, 0x6E1D3B62), LL(0xF320AD74, 0x8EB1C71E), LL(0xBE8B0537, 0xAA87CA22)}; const BNU_CHUNK_T secp384r1_gy[] = { LL(0x90EA0E5F, 0x7A431D7C), LL(0x1D7E819D, 0x0A60B1CE), LL(0xB5F0B8C0, 0xE9DA3113), LL(0x289A147C, 0xF8F41DBD), LL(0x9292DC29, 0x5D9E98BF), LL(0x96262C6F, 0x3617DE4A)}; const BNU_CHUNK_T secp384r1_r[] = { LL(0xCCC52973, 0xECEC196A), LL(0x48B0A77A, 0x581A0DB2), LL(0xF4372DDF, 0xC7634D81), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF)}; BNU_CHUNK_T secp384r1_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_521r1.c000066400000000000000000000061771470420105600257620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // secp521r1 (* Montgomery Friendly Modulus (+1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters secp521r1 */ const BNU_CHUNK_T h_secp521r1_p[] = { // half of secp521r1_p LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0x000000FF)}; const BNU_CHUNK_T secp521r1_p[] = { // 2^521 -1 LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0x000001FF)}; const BNU_CHUNK_T secp521r1_a[] = { LL(0xFFFFFFFC, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0x000001FF)}; const BNU_CHUNK_T secp521r1_b[] = { LL(0x6B503F00, 0xEF451FD4), LL(0x3D2C34F1, 0x3573DF88), LL(0x3BB1BF07, 0x1652C0BD), LL(0xEC7E937B, 0x56193951), LL(0x8EF109E1, 0xB8B48991), LL(0x99B315F3, 0xA2DA725B), LL(0xB68540EE, 0x929A21A0), LL(0x8E1C9A1F, 0x953EB961), L_(0x00000051)}; const BNU_CHUNK_T secp521r1_gx[] = { LL(0xC2E5BD66, 0xF97E7E31), LL(0x856A429B, 0x3348B3C1), LL(0xA2FFA8DE, 0xFE1DC127), LL(0xEFE75928, 0xA14B5E77), LL(0x6B4D3DBA, 0xF828AF60), LL(0x053FB521, 0x9C648139), LL(0x2395B442, 0x9E3ECB66), LL(0x0404E9CD, 0x858E06B7), L_(0x000000C6)}; const BNU_CHUNK_T secp521r1_gy[] = { LL(0x9FD16650, 0x88BE9476), LL(0xA272C240, 0x353C7086), LL(0x3FAD0761, 0xC550B901), LL(0x5EF42640, 0x97EE7299), LL(0x273E662C, 0x17AFBD17), LL(0x579B4468, 0x98F54449), LL(0x2C7D1BD9, 0x5C8A5FB4), LL(0x9A3BC004, 0x39296A78), L_(0x00000118)}; const BNU_CHUNK_T secp521r1_r[] = { LL(0x91386409, 0xBB6FB71E), LL(0x899C47AE, 0x3BB5C9B8), LL(0xF709A5D0, 0x7FCC0148), LL(0xBF2F966B, 0x51868783), LL(0xFFFFFFFA, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), L_(0x000001FF)}; BNU_CHUNK_T secp521r1_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_BN_256.c000066400000000000000000000031761470420105600260770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // tpm_BN_p256 (BN, TPM) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters tpm_BN_p256 (Barreto-Naehrig) */ const BNU_CHUNK_T tpmBN_p256p_p[] = { LL(0xAED33013, 0xD3292DDB), LL(0x12980A82, 0x0CDC65FB), LL(0xEE71A49F, 0x46E5F25E), LL(0xFFFCF0CD, 0xFFFFFFFF)}; const BNU_CHUNK_T tpmBN_p256p_a[] = { LL(0, 0)}; const BNU_CHUNK_T tpmBN_p256p_b[] = { LL(3, 0)}; const BNU_CHUNK_T tpmBN_p256p_gx[] = { LL(1, 0)}; const BNU_CHUNK_T tpmBN_p256p_gy[] = { LL(2, 0)}; const BNU_CHUNK_T tpmBN_p256p_r[] = { LL(0xD10B500D, 0xF62D536C), LL(0x1299921A, 0x0CDC65FB), LL(0xEE71A49E, 0x46E5F25E), LL(0xFFFCF0CD, 0xFFFFFFFF)}; BNU_CHUNK_T tpmBN_p256p_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccpstdca_SM2_256.c000066400000000000000000000063341470420105600262000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC over Prime Finite Field (recommended ECC parameters) // // Contents: // tpmSM2_p256_p (SM2) (* Montgomery Friendly Modulus (+1) *) // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #if defined( _IPP_DATA ) /* // Recommended Parameters tpm_SM2_p256 */ #ifdef _SM2_SIGN_DEBUG_ const BNU_CHUNK_T tpmSM2_p256_p[] = { LL(0x08F1DFC3, 0x722EDB8B), LL(0x5C45517D, 0x45728391), LL(0xBF6FF7DE, 0xE8B92435), LL(0x4C044F18, 0x8542D69E), LL(0x0, 0x0)}; const BNU_CHUNK_T tpmSM2_p256_a[] = { LL(0x3937E498, 0xEC65228B), LL(0x6831D7E0, 0x2F3C848B), LL(0x73BBFEFF, 0x2417842E), LL(0xFA32C3FD, 0x787968B4)}; const BNU_CHUNK_T tpmSM2_p256_b[] = { LL(0x27C5249A, 0x6E12D1DA), LL(0xB16BA06E, 0xF61D59A5), LL(0x484BFE48, 0x9CF84241), LL(0xB23B0C84, 0x63E4C6D3)}; const BNU_CHUNK_T tpmSM2_p256_gx[] = { LL(0x7FEDD43D, 0x4C4E6C14), LL(0xADD50BDC, 0x32220B3B), LL(0xC3CC315E, 0x746434EB), LL(0x1B62EAB6, 0x421DEBD6)}; const BNU_CHUNK_T tpmSM2_p256_gy[] = { LL(0xE46E09A2, 0xA85841B9), LL(0xBFA36EA1, 0xE5D7FDFC), LL(0x153B70C4, 0xD47349D2), LL(0xCBB42C07, 0x0680512B)}; const BNU_CHUNK_T tpmSM2_p256_r[] = { LL(0xC32E79B7, 0x5AE74EE7), LL(0x0485628D, 0x29772063), LL(0xBF6FF7DD, 0xE8B92435), LL(0x4C044F18, 0x8542D69E)}; #else const BNU_CHUNK_T h_tpmSM2_p256_p[] = { // half of tpmSM2_p256_p LL(0xFFFFFFFF, 0x7FFFFFFF), LL(0x80000000, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x7FFFFFFF, 0x7FFFFFFF)}; const BNU_CHUNK_T tpmSM2_p256_p[] = { // 2^256 -2^224 -2^96 +2^64 -1 LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0x00000000, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFE), LL(0x0, 0x0)}; const BNU_CHUNK_T tpmSM2_p256_a[] = { LL(0xFFFFFFFC, 0xFFFFFFFF), LL(0x00000000, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFE)}; const BNU_CHUNK_T tpmSM2_p256_b[] = { LL(0x4D940E93, 0xDDBCBD41), LL(0x15AB8F92, 0xF39789F5), LL(0xCF6509A7, 0x4D5A9E4B), LL(0x9D9F5E34, 0x28E9FA9E)}; const BNU_CHUNK_T tpmSM2_p256_gx[] = { LL(0x334C74C7, 0x715A4589), LL(0xF2660BE1, 0x8FE30BBF), LL(0x6A39C994, 0x5F990446), LL(0x1F198119, 0x32C4AE2C)}; const BNU_CHUNK_T tpmSM2_p256_gy[] = { LL(0x2139F0A0, 0x02DF32E5), LL(0xC62A4740, 0xD0A9877C), LL(0x6B692153, 0x59BDCEE3), LL(0xF4F6779C, 0xBC3736A2)}; const BNU_CHUNK_T tpmSM2_p256_r[] = { LL(0x39D54123, 0x53BBF409), LL(0x21C6052B, 0x7203DF6B), LL(0xFFFFFFFF, 0xFFFFFFFF), LL(0xFFFFFFFF, 0xFFFFFFFE)}; #endif BNU_CHUNK_T tpmSM2_p256_h = 1; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpeccresultca.c000066400000000000000000000047251470420105600254710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // ECC operation results // // Contents: // ippsECCGetResultString() // // */ #include "owndefs.h" #include "owncp.h" /*F* // Name: ippsECCGetResultString // // Purpose: Returns the string corresponding to code // that represents the result of validation // // Parameters: // code The code of the validation result // *F*/ IPPFUN( const char*, ippsECCGetResultString, (IppECResult code)) { switch(code) { case ippECValid: return "Validation pass successfully"; case ippECCompositeBase: return "Finite Field produced by Composite"; case ippECComplicatedBase: return "Too much non-zero terms in the polynomial"; case ippECIsZeroDiscriminant: return "Zero discriminamt"; case ippECCompositeOrder: return "Composite Base Point order"; case ippECInvalidOrder: return "Invalid Base Point order"; case ippECIsWeakMOV: return "EC cover by MOV Reduction Test"; case ippECIsWeakSSSA: return "EC cover by SS-SA Reduction Test"; case ippECIsSupersingular: return "EC is supersingular curve"; case ippECInvalidPrivateKey: return "Invalid Private Key"; case ippECInvalidPublicKey: return "Invalid Public Key"; case ippECInvalidKeyPair: return "Invalid Key Pair"; case ippECPointOutOfGroup: return "Point is out of group"; case ippECPointIsAtInfinite: return "Point at Infinity"; case ippECPointIsNotValid: return "Invalid EC Point"; case ippECPointIsEqual: return "Points are equal"; case ippECPointIsNotEqual: return "Points are different"; case ippECInvalidSignature: return "Invalid Signature"; default: return "Unknown ECC result"; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpecprime.h000066400000000000000000000035251470420105600246220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Fixed EC primes // // */ #if !defined(_PCP_ECPRIME_H) #define _PCP_ECPRIME_H #include "owndefs.h" #include "pcpbnuimpl.h" /* // Recommended (NIST's) underlying EC Primes */ extern const BNU_CHUNK_T secp112r1_p[]; // (2^128 -3)/76439 extern const BNU_CHUNK_T secp112r2_p[]; // (2^128 -3)/76439 extern const BNU_CHUNK_T secp128r1_p[]; // 2^128 -2^97 -1 extern const BNU_CHUNK_T secp128r2_p[]; // 2^128 -2^97 -1 extern const BNU_CHUNK_T secp160r1_p[]; // 2^160 -2^31 -1 extern const BNU_CHUNK_T secp160r2_p[]; // 2^160 -2^32 -2^14 -2^12 -2^9 -2^8 -2^7 -2^2 -1 extern const BNU_CHUNK_T secp192r1_p[]; // 2^192 -2^64 -1 extern const BNU_CHUNK_T secp224r1_p[]; // 2^224 -2^96 +1 extern const BNU_CHUNK_T secp256r1_p[]; // 2^256 -2^224 +2^192 +2^96 -1 extern const BNU_CHUNK_T secp384r1_p[]; // 2^384 -2^128 -2^96 +2^32 -1 extern const BNU_CHUNK_T secp521r1_p[]; // 2^521 -1 extern const BNU_CHUNK_T tpmBN_p256p_p[]; // TPM BN_P256 /* // Recommended (SM2) underlying EC Prime */ extern const BNU_CHUNK_T tpmSM2_p256_p[]; // TPM SM2_P256 #endif /* _PCP_ECPRIME_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp.c000066400000000000000000000073341470420105600237470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // cpGFpGetSize() // cpGFpInitGFp() // // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /* // size of GFp engine context (Montgomery) */ IPP_OWN_DEFN (int, cpGFpGetSize, (int feBitSize, int peBitSize, int numpe)) { int ctxSize = 0; int elemLen = BITS_BNU_CHUNK(feBitSize); int pelmLen = BITS_BNU_CHUNK(peBitSize); /* size of GFp engine */ ctxSize = (Ipp32s)sizeof(gsModEngine) + elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* modulus */ + elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* mont_R */ + elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* mont_R^2 */ + elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* half of modulus */ + elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* quadratic non-residue */ + pelmLen*(Ipp32s)sizeof(BNU_CHUNK_T)*numpe; /* pool */ ctxSize += sizeof(IppsGFpState); /* size of IppsGFPState */ return ctxSize; } /* // init GFp engine context (Montgomery) */ static void cpGFEInit(gsModEngine* pGFE, int modulusBitSize, int peBitSize, int numpe) { int modLen = BITS_BNU_CHUNK(modulusBitSize); int pelmLen = BITS_BNU_CHUNK(peBitSize); Ipp8u* ptr = (Ipp8u*)pGFE; /* clear whole context */ PadBlock(0, ptr, sizeof(gsModEngine)); ptr += sizeof(gsModEngine); GFP_PARENT(pGFE) = NULL; GFP_EXTDEGREE(pGFE) = 1; GFP_FEBITLEN(pGFE) = modulusBitSize; GFP_FELEN(pGFE) = modLen; GFP_FELEN32(pGFE) = BITS2WORD32_SIZE(modulusBitSize); GFP_PELEN(pGFE) = pelmLen; //GFP_METHOD(pGFE) = method; GFP_MODULUS(pGFE) = (BNU_CHUNK_T*)(ptr); ptr += modLen*(Ipp32s)sizeof(BNU_CHUNK_T); GFP_MNT_R(pGFE) = (BNU_CHUNK_T*)(ptr); ptr += modLen*(Ipp32s)sizeof(BNU_CHUNK_T); GFP_MNT_RR(pGFE) = (BNU_CHUNK_T*)(ptr); ptr += modLen*(Ipp32s)sizeof(BNU_CHUNK_T); GFP_HMODULUS(pGFE) = (BNU_CHUNK_T*)(ptr); ptr += modLen*(Ipp32s)sizeof(BNU_CHUNK_T); GFP_QNR(pGFE) = (BNU_CHUNK_T*)(ptr); ptr += modLen*(Ipp32s)sizeof(BNU_CHUNK_T); GFP_POOL(pGFE) = (BNU_CHUNK_T*)(ptr);/* ptr += modLen*(Ipp32s)sizeof(BNU_CHUNK_T);*/ GFP_MAXPOOL(pGFE) = numpe; GFP_USEDPOOL(pGFE) = 0; cpGFpElementPad(GFP_MODULUS(pGFE), modLen, 0); cpGFpElementPad(GFP_MNT_R(pGFE), modLen, 0); cpGFpElementPad(GFP_MNT_RR(pGFE), modLen, 0); cpGFpElementPad(GFP_HMODULUS(pGFE), modLen, 0); cpGFpElementPad(GFP_QNR(pGFE), modLen, 0); } IPP_OWN_DEFN (IppStatus, cpGFpInitGFp, (int primeBitSize, IppsGFpState* pGF)) { IPP_BADARG_RET((primeBitSize< IPP_MIN_GF_BITSIZE) || (primeBitSize> IPP_MAX_GF_BITSIZE), ippStsSizeErr); IPP_BAD_PTR1_RET(pGF); { Ipp8u* ptr = (Ipp8u*)pGF; GFP_SET_ID(pGF); GFP_PMA(pGF) = (gsModEngine*)(ptr+sizeof(IppsGFpState)); cpGFEInit(GFP_PMA(pGF), primeBitSize, primeBitSize+BITSIZE(BNU_CHUNK_T), GFP_POOL_SIZE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_exp.c000066400000000000000000000023131470420105600246130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpExp // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpExp, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pE, int nsE, gsModEngine* pGFE)) { int elemLen = GFP_FELEN(pGFE); cpMontExpBin_BNU(pR, pA,cpFix_BNU(pA, elemLen), pE,cpFix_BNU(pE, nsE), pGFE); return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_get.c000066400000000000000000000026001470420105600245750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpGet // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" //tbcd: temporary excluded: #include IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpGet, (BNU_CHUNK_T* pDataA, int nsA, const BNU_CHUNK_T* pElm, gsModEngine* pGFE)) { int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(pTmp !=NULL); GFP_METHOD(pGFE)->decode(pTmp, pElm, pGFE); ZEXPAND_COPY_BNU(pDataA, nsA, pTmp, elemLen); cpGFpReleasePool(1, pGFE); return pDataA; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_getoctstring.c000066400000000000000000000026621470420105600265420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpSetOctString // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" //tbcd: temporary excluded: #include IPP_OWN_DEFN (Ipp8u*, cpGFpGetOctString, (Ipp8u* pStr, int strSize, const BNU_CHUNK_T* pElm, gsModEngine* pGFE)) { int elemLen = GFP_FELEN(pGFE); int error; BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(pTmp !=NULL); GFP_METHOD(pGFE)->decode(pTmp, pElm, pGFE); error = (0 == cpToOctStr_BNU(pStr, strSize, pTmp, elemLen)); cpGFpReleasePool(1, pGFE); return error ? NULL : pStr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_gfeqnr.c000066400000000000000000000033411470420105600253030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // cpGFEqnr() // // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" //tbcd: temporary excluded: #include IPP_OWN_DEFN (void, cpGFEqnr, (gsModEngine* pGFE)) { BNU_CHUNK_T* pQnr = GFP_QNR(pGFE); int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* e = cpGFpGetPool(3, pGFE); BNU_CHUNK_T* t = e+elemLen; BNU_CHUNK_T* p1 = t+elemLen; //tbcd: temporary excluded: assert(NULL!=e); cpGFpElementCopyPad(p1, elemLen, GFP_MNT_R(pGFE), elemLen); /* (modulus-1)/2 */ cpLSR_BNU(e, GFP_MODULUS(pGFE), elemLen, 1); /* find a non-square g, where g^{(modulus-1)/2} = -1 */ cpGFpElementCopy(pQnr, p1, elemLen); do { cpGFpAdd(pQnr, pQnr, p1, pGFE); cpGFpExp(t, pQnr, e, elemLen, pGFE); cpGFpNeg(t, t, pGFE); } while( !GFP_EQ(p1, t, elemLen) ); cpGFpReleasePool(3, pGFE); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_inv.c000066400000000000000000000023511470420105600246150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpInv // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpInv, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE)) { GFP_METHOD(pGFE)->decode(pR, pA, pGFE); /* gs_mont_inv(pR, pR, pGFE, alm_mont_inv); */ gs_mont_inv(pR, pR, pGFE, alm_mont_inv_ct); /* switch on CTE internal function */ return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_rand.c000066400000000000000000000034031470420105600247440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpRand // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" //tbcd: temporary excluded: #include IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpRand, (BNU_CHUNK_T* pR, gsModEngine* pGFE, IppBitSupplier rndFunc, void* pRndParam)) { int elemLen = GFP_FELEN(pGFE); int reqBitSize = GFP_FEBITLEN(pGFE)+GFP_RAND_ADD_BITS; int nsR = (reqBitSize +BITSIZE(BNU_CHUNK_T)-1)/BITSIZE(BNU_CHUNK_T); int internal_err; BNU_CHUNK_T* pPool = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(pPool!=NULL); cpGFpElementPad(pPool, nsR, 0); internal_err = ippStsNoErr != rndFunc((Ipp32u*)pPool, reqBitSize, pRndParam); if(!internal_err) { nsR = cpMod_BNU(pPool, nsR, GFP_MODULUS(pGFE), elemLen); cpGFpElementPad(pPool+nsR, elemLen-nsR, 0); GFP_METHOD(pGFE)->encode(pR, pPool, pGFE); } cpGFpReleasePool(2, pGFE); return internal_err? NULL : pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_set.c000066400000000000000000000030341470420105600246130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpSet // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" //tbcd: temporary excluded: #include IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpSet, (BNU_CHUNK_T* pElm, const BNU_CHUNK_T* pDataA, int nsA, gsModEngine* pGFE)) { const BNU_CHUNK_T* pModulus = GFP_MODULUS(pGFE); int elemLen = GFP_FELEN(pGFE); if(0 <= cpCmp_BNU(pDataA, nsA, pModulus, elemLen)) return NULL; else { BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(pTmp !=NULL); ZEXPAND_COPY_BNU(pTmp, elemLen, pDataA, nsA); GFP_METHOD(pGFE)->encode(pElm, pTmp, pGFE); cpGFpReleasePool(1, pGFE); return pElm; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_setgfp.c000066400000000000000000000041211470420105600253060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // cpGFpSetGFp() // // */ #include "gsmodmethod.h" #include "gsmodstuff.h" #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" IPP_OWN_DEFN (IppStatus, cpGFpSetGFp, (const BNU_CHUNK_T* pPrime, int primeBitSize, const IppsGFpMethod* method, IppsGFpState* pGF)) { gsModEngine* pGFE = GFP_PMA(pGF); int primeLen = BITS_BNU_CHUNK(primeBitSize); /* arithmetic methods */ GFP_METHOD(pGFE) = method->arith; pGFE->method_alt = method->arith_alt; /* store modulus */ COPY_BNU(GFP_MODULUS(pGFE), pPrime, primeLen); /* montgomery factor */ GFP_MNT_FACTOR(pGFE) = gsMontFactor(GFP_MODULUS(pGFE)[0]); /* montgomery identity (R) */ ZEXPAND_BNU(GFP_MNT_R(pGFE), 0, primeLen); GFP_MNT_R(pGFE)[primeLen] = 1; cpMod_BNU(GFP_MNT_R(pGFE), primeLen+1, GFP_MODULUS(pGFE), primeLen); /* montgomery domain converter (RR) */ ZEXPAND_BNU(GFP_MNT_RR(pGFE), 0, primeLen); COPY_BNU(GFP_MNT_RR(pGFE)+primeLen, GFP_MNT_R(pGFE), primeLen); cpMod_BNU(GFP_MNT_RR(pGFE), 2*primeLen, GFP_MODULUS(pGFE), primeLen); /* half of modulus */ cpLSR_BNU(GFP_HMODULUS(pGFE), GFP_MODULUS(pGFE), primeLen, 1); /* set qnr value */ cpGFEqnr(pGFE); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_setoctstring.c000066400000000000000000000030641470420105600265530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpSetOctString // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" //tbcd: temporary excluded: #include IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpSetOctString, (BNU_CHUNK_T* pElm, const Ipp8u* pStr, int strSize, gsModEngine* pGFE)) { int elemLen = GFP_FELEN(pGFE); if((int)(elemLen*(Ipp32s)sizeof(BNU_CHUNK_T)) < strSize) return NULL; { BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(pTmp !=NULL); { int nsTmp = cpFromOctStr_BNU(pTmp, pStr, strSize); BNU_CHUNK_T* ret = cpGFpSet(pElm, pTmp, nsTmp, pGFE); cpGFpReleasePool(1, pGFE); return ret==NULL? NULL : pElm; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfp_sqrt.c000066400000000000000000000075601470420105600250210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over prime GF(p). // // Context: // cpGFpSqrt // */ #include "owncp.h" #include "pcpbn.h" #include "gfpec/pcpgfpstuff.h" static int factor2(BNU_CHUNK_T* pA, int nsA) { int factor = 0; int bits; int i; for(i=0; i= BITSIZE(BNU_CHUNK_T)) { int nchunk = bits/BITSIZE(BNU_CHUNK_T); cpGFpElementCopyPad(pA, nsA, pA+nchunk, nsA-nchunk); bits %= BITSIZE(BNU_CHUNK_T); } if(bits) cpLSR_BNU(pA, pA, nsA, bits); return factor; } static BNU_CHUNK_T* cpGFpExp2(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, int e, gsModEngine* pGFE) { cpGFpElementCopy(pR, pA, GFP_FELEN(pGFE)); while(e--) { GFP_METHOD(pGFE)->sqr(pR, pR, pGFE); } return pR; } /* returns: 0, if a - qnr 1, if sqrt is found */ IPP_OWN_DEFN (int, cpGFpSqrt, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE)) { int elemLen = GFP_FELEN(pGFE); int poolelementLen = GFP_PELEN(pGFE); int resultFlag = 1; /* case A==0 */ if( GFP_IS_ZERO(pA, elemLen) ) cpGFpElementPad(pR, elemLen, 0); /* general case */ else { BNU_CHUNK_T* q = cpGFpGetPool(4, pGFE); BNU_CHUNK_T* x = q + poolelementLen; BNU_CHUNK_T* y = x + poolelementLen; BNU_CHUNK_T* z = y + poolelementLen; int s; //tbcd: temporary excluded: assert(q!=NULL); /* z=1 */ GFP_ONE(z, elemLen); /* (modulus-1) = 2^s*q */ cpSub_BNU(q, GFP_MODULUS(pGFE), z, elemLen); s = factor2(q, elemLen); /* // initialization */ /* y = qnr^q */ cpGFpExp(y, GFP_QNR(pGFE), q,elemLen, pGFE); /* x = a^((q-1)/2) */ cpSub_BNU(q, q, z, elemLen); cpLSR_BNU(q, q, elemLen, 1); cpGFpExp(x, pA, q, elemLen, pGFE); /* z = a*x^2 */ GFP_METHOD(pGFE)->mul(z, x, x, pGFE); GFP_METHOD(pGFE)->mul(z, pA, z, pGFE); /* R = a*x */ GFP_METHOD(pGFE)->mul(pR, pA, x, pGFE); while( !GFP_EQ(z, MOD_MNT_R(pGFE), elemLen) ) { int m = 0; cpGFpElementCopy(q, z, elemLen); for(m=1; mmul(q, q, q, pGFE); if( GFP_EQ(q, MOD_MNT_R(pGFE), elemLen) ) break; } if(m==s) { /* A is quadratic non-residue */ resultFlag = 0; break; } else { /* exponent reduction */ cpGFpExp2(q, y, (s-m-1), pGFE); /* q = y^(2^(s-m-1)) */ GFP_METHOD(pGFE)->mul(y, q, q, pGFE); /* y = q^2 */ GFP_METHOD(pGFE)->mul(pR, q, pR, pGFE); /* R = q*R */ GFP_METHOD(pGFE)->mul(z, y, z, pGFE); /* z = z*y */ s = m; } } /* choose smallest between R and (modulus-R) */ GFP_METHOD(pGFE)->decode(q, pR, pGFE); if(1 == cpCmp_BNU(q, elemLen, GFP_HMODULUS(pGFE), elemLen)) GFP_METHOD(pGFE)->neg(pR, pR, pGFE); cpGFpReleasePool(4, pGFE); } return resultFlag; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpadd.c000066400000000000000000000052321470420105600244130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpAdd() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpAdd // // Purpose: Sum of GF elements // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // NULL == pB // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pB Pointer to the context of the second finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpAdd,(const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pB, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pB), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pB)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); GFP_METHOD(pGFE)->add(GFPE_DATA(pR), GFPE_DATA(pA), GFPE_DATA(pB), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpaddpe.c000066400000000000000000000056221470420105600247430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpAdd_PE() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpAdd_PE // // Purpose: Sum of GF element and parent GF element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // NULL == pParentB // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pParentB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr pGFp does not specify prime field // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pParentB Pointer to the context of the second finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpAdd_PE,(const IppsGFpElement* pA, const IppsGFpElement* pParentB, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pParentB, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pParentB), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFP_IS_BASIC(pGFE), ippStsBadArgErr ) IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); IPP_BADARG_RET( (GFPE_ROOM(pParentB)!=GFP_FELEN(GFP_PARENT(pGFE))), ippStsOutOfRangeErr); cpGFpxAdd_GFE(GFPE_DATA(pR), GFPE_DATA(pA), GFPE_DATA(pParentB), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpbufsize.c000066400000000000000000000053131470420105600253320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpScratchBufferSize // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpScratchBufferSize // // Purpose: Gets the size of the scratch buffer. // // Returns: Reason: // ippStsNullPtrErr pGFp == NULL // pBufferSize == NULL // ippStsContextMatchErr incorrect pGFp's context id // ippStsBadArgErr 0>=nExponents // nExponents>6 // ippStsNoErr no error // // Parameters: // nExponents Number of exponents. // ExpBitSize Maximum bit size of the exponents. // pGFp Pointer to the context of the finite field. // pBufferSize Pointer to the calculated buffer size in bytes. // *F*/ IPPFUN(IppStatus, ippsGFpScratchBufferSize,(int nExponents, int ExpBitSize, const IppsGFpState* pGFp, int* pBufferSize)) { IPP_BAD_PTR2_RET(pGFp, pBufferSize); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( 0>=nExponents ||nExponents>IPP_MAX_EXPONENT_NUM, ippStsBadArgErr); IPP_BADARG_RET( 0>=ExpBitSize, ippStsBadArgErr); /* gres 06/10/2019: ExpBirSize=BNU_CHUNK_BITS*n -- meet CTE implementation */ ExpBitSize = ((ExpBitSize + BNU_CHUNK_BITS-1)/BNU_CHUNK_BITS) * BNU_CHUNK_BITS; { int elmDataSize = GFP_FELEN(GFP_PMA(pGFp))*(Ipp32s)sizeof(BNU_CHUNK_T); /* get window_size */ int w = (nExponents==1)? cpGFpGetOptimalWinSize(ExpBitSize) : /* use optimal window size, if single-scalar operation */ nExponents; /* or pseudo-oprimal if multi-scalar operation */ /* number of table entries */ int nPrecomputed = 1<idCtx // invalid pA->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pB Pointer to the context of the second finite field element. // pResult Pointer to the result of the comparison. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpCmpElement,(const IppsGFpElement* pA, const IppsGFpElement* pB, int* pResult, const IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pB, pResult, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pB), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pB)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); { BNU_CHUNK_T* a = cpGFpGetPool(2, pGFE); BNU_CHUNK_T* b = a + GFP_PELEN(pGFE); GFP_METHOD(pGFE)->decode(a, GFPE_DATA(pA), pGFE); GFP_METHOD(pGFE)->decode(b, GFPE_DATA(pB), pGFE); ZEXPAND_BNU(a, GFP_FELEN(pGFE), GFP_PELEN(pGFE)); ZEXPAND_BNU(b, GFP_FELEN(pGFE), GFP_PELEN(pGFE)); int flag = cpCmp_BNU(a, GFP_PELEN(pGFE), b, GFP_PELEN(pGFE)); if( GFP_IS_BASIC(pGFE) ) *pResult = (0==flag)? IPP_IS_EQ : (0idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr 2!=GFP_EXTDEGREE(pGFE) // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the source finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpConj,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); IPP_BADARG_RET( 2!=GFP_EXTDEGREE(pGFE), ippStsBadArgErr ) cpGFpxConj(GFPE_DATA(pR), GFPE_DATA(pA), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpcpyelem.c000066400000000000000000000043471470420105600253270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpCpyElement() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpCpyElement // // Purpose: Copy GF Element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA pointer to the source element // pR pointer to the result element // pGFp pointer to Finite Field context *F*/ IPPFUN(IppStatus, ippsGFpCpyElement, (const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); cpGFpElementCopy(GFPE_DATA(pR), GFPE_DATA(pA), GFP_FELEN(pGFE)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec.c000066400000000000000000000044571470420105600242620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // cpGFpECGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" IPP_OWN_DEFN (int, cpGFpECGetSize, (int basicDeg, int basicElmBitSize)) { int ctxSize = 0; int elemLen = basicDeg*BITS_BNU_CHUNK(basicElmBitSize); int maxOrderBits = 1+ basicDeg*basicElmBitSize; #if defined(_LEGACY_ECCP_SUPPORT_) int maxOrderLen = BITS_BNU_CHUNK(maxOrderBits); #endif int modEngineCtxSize; if(ippStsNoErr==gsModEngineGetSize(maxOrderBits, MONT_DEFAULT_POOL_LENGTH, &modEngineCtxSize)) { ctxSize = (Ipp32s)sizeof(IppsGFpECState) +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* EC coeff A */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* EC coeff B */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* generator G.x */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* generator G.y */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* generator G.z */ +modEngineCtxSize /* mont engine (R) */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* cofactor */ #if defined(_LEGACY_ECCP_SUPPORT_) +2*elemLen*3*(Ipp32s)sizeof(BNU_CHUNK_T) /* regular and ephemeral public keys */ +2*maxOrderLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* regular and ephemeral private keys */ #endif +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T)*3*EC_POOL_SIZE; } return ctxSize; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_add.c000066400000000000000000000101231470420105600250550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_point_add() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "pcpmask_ct.h" #if ( ECP_PROJECTIVE_COORD == JACOBIAN ) /* // S1 = y1*z2^3 // S2 = y2*z1^3 // // U1 = x1*z2^2 // U2 = x2*z1^2 // R = S2-S1 // H = U2-U1 // // x3 = -H^3 -2*U1*H^2 +R2 // y3 = -S1*H^3 +R*(U1*H^2 -x3) // z3 = z1*z2*H // // complexity = 4s+12m */ IPP_OWN_DEFN (void, gfec_point_add, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, const BNU_CHUNK_T* pQdata, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_sub sub = GFP_METHOD(pGFE)->sub; /* gf sub */ mod_mul2 mul2= GFP_METHOD(pGFE)->mul2; /* gf mul2 */ mod_mul mul = GFP_METHOD(pGFE)->mul; /* gf mul */ mod_sqr sqr = GFP_METHOD(pGFE)->sqr; /* gf sqr */ /* coordinates of P */ const BNU_CHUNK_T* px1 = pPdata; const BNU_CHUNK_T* py1 = pPdata+elemLen; const BNU_CHUNK_T* pz1 = pPdata+2*elemLen; /* coordinates of Q */ const BNU_CHUNK_T* px2 = pQdata; const BNU_CHUNK_T* py2 = pQdata+elemLen; const BNU_CHUNK_T* pz2 = pQdata+2*elemLen; BNU_CHUNK_T inftyP = GFPE_IS_ZERO_CT(pz1, elemLen); BNU_CHUNK_T inftyQ = GFPE_IS_ZERO_CT(pz2, elemLen); /* get temporary from top of EC point pool */ BNU_CHUNK_T* U1 = pEC->pPool; BNU_CHUNK_T* U2 = U1 + elemLen; BNU_CHUNK_T* S1 = U2 + elemLen; BNU_CHUNK_T* S2 = S1 + elemLen; BNU_CHUNK_T* H = S2 + elemLen; BNU_CHUNK_T* R = H + elemLen; BNU_CHUNK_T* pRx = R + elemLen; /* temporary result */ BNU_CHUNK_T* pRy = pRx+ elemLen; BNU_CHUNK_T* pRz = pRy+ elemLen; mul(S1, py1, pz2, pGFE); // S1 = Y1*Z2 sqr(U1, pz2, pGFE); // U1 = Z2^2 mul(S2, py2, pz1, pGFE); // S2 = Y2*Z1 sqr(U2, pz1, pGFE); // U2 = Z1^2 mul(S1, S1, U1, pGFE); // S1 = Y1*Z2^3 mul(S2, S2, U2, pGFE); // S2 = Y2*Z1^3 mul(U1, px1, U1, pGFE); // U1 = X1*Z2^2 mul(U2, px2, U2, pGFE); // U2 = X2*Z1^2 sub(R, S2, S1, pGFE); // R = S2-S1 sub(H, U2, U1, pGFE); // H = U2-U1 { BNU_CHUNK_T mask_zeroH = GFPE_IS_ZERO_CT(H, elemLen); BNU_CHUNK_T mask = mask_zeroH & ~inftyP & ~inftyQ; if(mask) { if( GFPE_IS_ZERO_CT(R, elemLen) ) gfec_point_double(pRdata, pPdata, pEC); else cpGFpElementPad(pRdata, 3*elemLen, 0); return; } } mul(pRz, pz1, pz2, pGFE); // Z3 = Z1*Z2 sqr(U2, H, pGFE); // U2 = H^2 mul(pRz, pRz, H, pGFE); // Z3 = (Z1*Z2)*H sqr(S2, R, pGFE); // S2 = R^2 mul(H, H, U2, pGFE); // H = H^3 mul(U1, U1, U2, pGFE); // U1 = U1*H^2 sub(pRx, S2, H, pGFE); // X3 = R^2 - H^3 mul2(U2, U1, pGFE); // U2 = 2*U1*H^2 mul(S1, S1, H, pGFE); // S1 = S1*H^3 sub(pRx, pRx, U2, pGFE); // X3 = (R^2 - H^3) -2*U1*H^2 sub(pRy, U1, pRx, pGFE); // Y3 = R*(U1*H^2 - X3) -S1*H^3 mul(pRy, pRy, R, pGFE); sub(pRy, pRy, S1, pGFE); cpMaskedReplace_ct(pRx, px2, elemLen*3, inftyP); cpMaskedReplace_ct(pRx, px1, elemLen*3, inftyQ); cpGFpElementCopy(pRdata, pRx, 3*elemLen); } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_addaffine.c000066400000000000000000000072311470420105600262340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_affine_point_add() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "pcpmask_ct.h" #if ( ECP_PROJECTIVE_COORD == JACOBIAN ) /* // complexity = 3s+8m */ IPP_OWN_DEFN (void, gfec_affine_point_add, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, const BNU_CHUNK_T* pAdata, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_sub sub = GFP_METHOD(pGFE)->sub; /* gf sub */ mod_mul2 mul2= GFP_METHOD(pGFE)->mul2; /* gf mul2 */ mod_mul mul = GFP_METHOD(pGFE)->mul; /* gf mul */ mod_sqr sqr = GFP_METHOD(pGFE)->sqr; /* gf sqr */ BNU_CHUNK_T* mont1 = GFP_MNT_R(pGFE); /* coordinates of projective P point */ const BNU_CHUNK_T* px = pPdata; /* x1 */ const BNU_CHUNK_T* py = pPdata+elemLen; /* y1 */ const BNU_CHUNK_T* pz = pPdata+2*elemLen; /* z1 */ /* coordinates of affine A point, az==mont(1) */ const BNU_CHUNK_T* ax = pAdata; /* x2 */ const BNU_CHUNK_T* ay = pAdata+elemLen; /* y2 */ BNU_CHUNK_T inftyP = GFPE_IS_ZERO_CT(px, elemLen) & GFPE_IS_ZERO_CT(py, elemLen); BNU_CHUNK_T inftyA = GFPE_IS_ZERO_CT(ax, elemLen) & GFPE_IS_ZERO_CT(ay, elemLen); /* get temporary from top of EC point pool */ BNU_CHUNK_T* U2 = pEC->pPool; BNU_CHUNK_T* S2 = U2 + elemLen; BNU_CHUNK_T* H = S2 + elemLen; BNU_CHUNK_T* R = H + elemLen; BNU_CHUNK_T* pRx = R + elemLen; /* temporary result */ BNU_CHUNK_T* pRy = pRx+ elemLen; BNU_CHUNK_T* pRz = pRy+ elemLen; sqr(R, pz, pGFE); // R = Z1^2 mul(S2, ay, pz, pGFE); // S2 = Y2*Z1 mul(U2, ax, R, pGFE); // U2 = X2*Z1^2 mul(S2, S2, R, pGFE); // S2 = Y2*Z1^3 sub(H, U2, px, pGFE); // H = U2-X1 sub(R, S2, py, pGFE); // R = S2-Y1 mul(pRz, H, pz, pGFE); // Z3 = H*Z1 sqr(U2, H, pGFE); // U2 = H^2 sqr(S2, R, pGFE); // S2 = R^2 mul(H, H, U2, pGFE); // H = H^3 mul(U2, U2, px, pGFE); // U2 = X1*H^2 mul(pRy, H, py, pGFE); // T = Y1*H^3 mul2(pRx, U2, pGFE); // X3 = 2*X1*H^2 sub(pRx, S2, pRx, pGFE); // X3 = R^2 - 2*X1*H^2 sub(pRx, pRx, H, pGFE); // X3 = R^2 - 2*X1*H^2 -H^3 sub(U2, U2, pRx, pGFE); // U2 = X1*H^2 - X3 mul(U2, U2, R, pGFE); // U2 = R*(X1*H^2 - X3) sub(pRy, U2, pRy, pGFE); // Y3 = -Y1*H^3 + R*(X1*H^2 - X3) cpMaskedReplace_ct(pRx, ax, elemLen, inftyP); cpMaskedReplace_ct(pRy, ay, elemLen, inftyP); cpMaskedReplace_ct(pRz, mont1, elemLen, inftyP); cpMaskedReplace_ct(pRz, ax, elemLen, inftyP&inftyA); cpMaskedReplace_ct(pRx, px, elemLen*3, inftyA); cpGFpElementCopy(pRdata, pRx, 3*elemLen); } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_baseprod.c000066400000000000000000000050451470420105600261330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_BasePointProduct() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (IppsGFpECPoint*, gfec_BasePointProduct, (IppsGFpECPoint* pR, const BNU_CHUNK_T* pScalarG, int scalarGlen, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalarP, int scalarPlen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalarG, scalarGlen); FIX_BNU(pScalarP, scalarPlen); { gsModEngine* pGForder = ECP_MONT_R(pEC); int orderBits = MOD_BITSIZE(pGForder); int orderLen = MOD_LEN(pGForder); BNU_CHUNK_T* tmpScalarG = cpGFpGetPool(2, pGForder); BNU_CHUNK_T* tmpScalarP = tmpScalarG+orderLen+1; cpGFpElementCopyPad(tmpScalarG, orderLen+1, pScalarG,scalarGlen); cpGFpElementCopyPad(tmpScalarP, orderLen+1, pScalarP,scalarPlen); if(ECP_PREMULBP(pEC)) { BNU_CHUNK_T* productG = cpEcGFpGetPool(2, pEC); BNU_CHUNK_T* productP = productG+ECP_POINTLEN(pEC); gfec_base_point_mul(productG, (Ipp8u*)tmpScalarG, orderBits, pEC); gfec_point_mul(productP, ECP_POINT_X(pP), (Ipp8u*)tmpScalarP, orderBits, pEC, pScratchBuffer); gfec_point_add(ECP_POINT_X(pR), productG, productP, pEC); cpEcGFpReleasePool(2, pEC); } else { gfec_point_prod(ECP_POINT_X(pR), ECP_G(pEC), (Ipp8u*)tmpScalarG, ECP_POINT_X(pP), (Ipp8u*)tmpScalarP, orderBits, pEC, pScratchBuffer); } cpGFpReleasePool(2, pGForder); } ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR)? 0 : ECP_FINITE_POINT; return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_comppont.c000066400000000000000000000064221470420105600261730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_ComparePoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #if ( ECP_PROJECTIVE_COORD == JACOBIAN ) IPP_OWN_DEFN (int, gfec_ComparePoint, (const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); /* P or/and Q at Infinity */ if( !IS_ECP_FINITE_POINT(pP) ) return !IS_ECP_FINITE_POINT(pQ)? 1:0; if( !IS_ECP_FINITE_POINT(pQ) ) return !IS_ECP_FINITE_POINT(pP)? 1:0; /* Px==Qx && Py==Qy && Pz==Qz */ if( GFP_EQ(ECP_POINT_Z(pP), ECP_POINT_Z(pQ), elemLen) &&GFP_EQ(ECP_POINT_X(pP), ECP_POINT_X(pQ), elemLen) &&GFP_EQ(ECP_POINT_Y(pP), ECP_POINT_Y(pQ), elemLen)) return 1; else { mod_mul mulF = GFP_METHOD(pGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGFE)->sqr; int isEqu = 1; BNU_CHUNK_T* pPtmp = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pQtmp = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pPz = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pQz = cpGFpGetPool(1, pGFE); if(isEqu) { /* Px*Qz^2 ~ Qx*Pz^2 */ if( IS_ECP_AFFINE_POINT(pQ) ) /* Ptmp = Px * Qz^2 */ cpGFpElementCopy(pPtmp, ECP_POINT_X(pP), elemLen); else { sqrF(pQz, ECP_POINT_Z(pQ), pGFE); mulF(pPtmp, ECP_POINT_X(pP), pQz, pGFE); } if( IS_ECP_AFFINE_POINT(pP) ) /* Qtmp = Qx * Pz^2 */ cpGFpElementCopy(pQtmp, ECP_POINT_X(pQ), elemLen); else { sqrF(pPz, ECP_POINT_Z(pP), pGFE); mulF(pQtmp, ECP_POINT_X(pQ), pPz, pGFE); } isEqu = GFP_EQ(pPtmp, pQtmp, elemLen); } if(isEqu) { /* Py*Qz^3 ~ Qy*Pz^3 */ if( IS_ECP_AFFINE_POINT(pQ) ) /* Ptmp = Py * Qz^3 */ cpGFpElementCopy(pPtmp, ECP_POINT_Y(pP), elemLen); else { mulF(pQz, ECP_POINT_Z(pQ), pQz, pGFE); mulF(pPtmp, pQz, ECP_POINT_Y(pP), pGFE); } if( IS_ECP_AFFINE_POINT(pP) ) /* Qtmp = Qy * Pz^3 */ cpGFpElementCopy(pQtmp, ECP_POINT_Y(pQ), elemLen); else { mulF(pPz, ECP_POINT_Z(pP), pPz, pGFE); mulF(pQtmp, pPz, ECP_POINT_Y(pQ), pGFE); } isEqu = GFP_EQ(pPtmp, pQtmp, elemLen); } cpGFpReleasePool(4, pGFE); return isEqu; } } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_dblpoint.c000066400000000000000000000065621470420105600261540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_point_double() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #if ( ECP_PROJECTIVE_COORD == JACOBIAN ) /* // A = 4*x*y^2 // B = 3*x^2 + a*z^4 // // x3 = -2*A + B^2 // y3 = -8y^4 +B*(A-x3) // z3 = 2*y*z // // complexity: = 4s+4m (NIST's, SM2 curves) // = (EPID2 curve) // = 6s+4m (arbitrary curves) */ IPP_OWN_DEFN (void, gfec_point_double, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_add add = GFP_METHOD(pGFE)->add; /* gf add */ mod_sub sub = GFP_METHOD(pGFE)->sub; /* gf sub */ mod_div2 div2= GFP_METHOD(pGFE)->div2; /* gf div2 */ mod_mul2 mul2= GFP_METHOD(pGFE)->mul2; /* gf mul2 */ mod_mul3 mul3= GFP_METHOD(pGFE)->mul3; /* gf mul3 */ mod_mul mul = GFP_METHOD(pGFE)->mul; /* gf mul */ mod_sqr sqr = GFP_METHOD(pGFE)->sqr; /* gf sqr */ const BNU_CHUNK_T* pX = pPdata; const BNU_CHUNK_T* pY = pPdata+elemLen; const BNU_CHUNK_T* pZ = pPdata+2*+elemLen; BNU_CHUNK_T* rX = pRdata; BNU_CHUNK_T* rY = pRdata+elemLen; BNU_CHUNK_T* rZ = pRdata+2*elemLen; /* get temporary from top of EC point pool */ BNU_CHUNK_T* U = pEC->pPool; BNU_CHUNK_T* M = U+elemLen; BNU_CHUNK_T* S = M+elemLen; mul2(S, pY, pGFE); /* S = 2*Y */ sqr(U, pZ, pGFE); /* U = Z^2 */ sqr(M, S, pGFE); /* M = 4*Y^2 */ mul(rZ, S, pZ, pGFE); /* Zres = 2*Y*Z */ sqr(rY, M, pGFE); /* Yres = 16*Y^4 */ mul(S, M, pX, pGFE); /* S = 4*X*Y^2 */ div2(rY, rY, pGFE); /* Yres = 8*Y^4 */ if(ECP_STD==ECP_SPECIFIC(pEC)) { add(M, pX, U, pGFE); /* M = 3*(X^2-Z^4) */ sub(U, pX, U, pGFE); mul(M, M, U, pGFE); mul3(M, M, pGFE); } else { sqr(M, pX, pGFE); /* M = 3*X^2 */ mul3(M, M, pGFE); if(ECP_EPID2!=ECP_SPECIFIC(pEC)) { sqr(U, U, pGFE); /* M = 3*X^2+a*Z4 */ mul(U, U, ECP_A(pEC), pGFE); add(M, M, U, pGFE); } } mul2(U, S, pGFE); /* U = 8*X*Y^2 */ sqr(rX, M, pGFE); /* Xres = M^2 */ sub(rX, rX, U, pGFE); /* Xres = M^2-U */ sub(S, S, rX, pGFE); /* S = 4*X*Y^2-Xres */ mul(S, S, M, pGFE); /* S = M*(4*X*Y^2-Xres) */ sub(rY, S, rY, pGFE); /* Yres = M*(4*X*Y^2-Xres) -8*Y^4 */ } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_getpoint.c000066400000000000000000000046451470420105600261720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_GetPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #if ( ECP_PROJECTIVE_COORD == JACOBIAN ) /* returns 1/0 if point is finite/infinite */ IPP_OWN_DEFN (int, gfec_GetPoint, (BNU_CHUNK_T* pX, BNU_CHUNK_T* pY, const IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); if( !IS_ECP_FINITE_POINT(pPoint) ) { if(pX) cpGFpElementPad(pX, elemLen, 0); if(pY) cpGFpElementPad(pY, elemLen, 0); return 0; } /* affine point (1==Z) */ if( IS_ECP_AFFINE_POINT(pPoint) ) { if(pX) cpGFpElementCopy(pX, ECP_POINT_X(pPoint), elemLen); if(pY) cpGFpElementCopy(pY, ECP_POINT_Y(pPoint), elemLen); return 1; } /* projective point (1!=Z) */ { mod_mul mulF = GFP_METHOD(pGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGFE)->sqr; /* T = (1/Z)*(1/Z) */ BNU_CHUNK_T* pT = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pZinv = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pU = cpGFpGetPool(1, pGFE); cpGFpxInv(pZinv, ECP_POINT_Z(pPoint), pGFE); sqrF(pT, pZinv, pGFE); if(pX) { mulF(pU, ECP_POINT_X(pPoint), pT, pGFE); cpGFpElementCopy(pX, pU, elemLen); } if(pY) { mulF(pT, pZinv, pT, pGFE); mulF(pU, ECP_POINT_Y(pPoint), pT, pGFE); cpGFpElementCopy(pY, pU, elemLen); } cpGFpReleasePool(3, pGFE); return 1; } } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_makepoint.c000066400000000000000000000041001470420105600263120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_MakePoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (int, gfec_MakePoint, (IppsGFpECPoint* pPoint, const BNU_CHUNK_T* pElm, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_mul mulF = GFP_METHOD(pGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGFE)->sqr; mod_add addF = GFP_METHOD(pGFE)->add; BNU_CHUNK_T* pX = ECP_POINT_X(pPoint); BNU_CHUNK_T* pY = ECP_POINT_Y(pPoint); BNU_CHUNK_T* pZ = ECP_POINT_Z(pPoint); /* set x-coordinate */ cpGFpElementCopy(pX, pElm, elemLen); /* T = X^3 + A*X + B */ sqrF(pY, pX, pGFE); mulF(pY, pY, pX, pGFE); if(ECP_SPECIFIC(pEC)!=ECP_EPID2) { mulF(pZ, ECP_A(pEC), pX, pGFE); addF(pY, pY, pZ, pGFE); } addF(pY, pY, ECP_B(pEC), pGFE); /* set z-coordinate =1 */ cpGFpElementCopyPad(pZ, elemLen, GFP_MNT_R(pGFE), elemLen); /* Y = sqrt(Y) */ if( cpGFpSqrt(pY, pY, pGFE) ) { ECP_POINT_FLAGS(pPoint) = ECP_AFFINE_POINT | ECP_FINITE_POINT; return 1; } else { gfec_SetPointAtInfinity(pPoint); return 0; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_mul.c000066400000000000000000000074551470420105600251400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_MulPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #include "pcpmask_ct.h" IPP_OWN_DEFN (void, gfec_point_mul, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, const Ipp8u* pScalar8, int scalarBitSize, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { int pointLen = ECP_POINTLEN(pEC); /* optimal size of window */ const int window_size = 5; /* aligned pre-computed table */ BNU_CHUNK_T* pTable = (BNU_CHUNK_T*)IPP_ALIGNED_PTR(pScratchBuffer, CACHE_LINE_SIZE); setupTable(pTable, pPdata, pEC); { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_neg negF = GFP_METHOD(pGFE)->neg; BNU_CHUNK_T* pHy = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pTdata = cpEcGFpGetPool(1, pEC); /* points from the pool */ BNU_CHUNK_T* pHdata = cpEcGFpGetPool(1, pEC); int wvalue; Ipp8u digit, sign; int mask = (1<<(window_size+1)) -1; int bit = scalarBitSize-(scalarBitSize%window_size); /* first window */ if(bit) { wvalue = *((Ipp16u*)&pScalar8[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; } else wvalue = 0; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pTdata, pointLen, pTable, digit-1, 5-1); for(bit-=window_size; bit>=window_size; bit-=window_size) { gfec_point_double(pTdata, pTdata, pEC); /* probably it's better to have separate calls */ gfec_point_double(pTdata, pTdata, pEC); /* instead of gfec_point_double_k() */ gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); wvalue = *((Ipp16u*)&pScalar8[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTable, digit-1, 5-1); negF(pHy, pHdata+elemLen, pGFE); cpMaskedReplace_ct(pHdata+elemLen, pHy, elemLen, ~cpIsZero_ct(sign)); gfec_point_add(pTdata, pTdata, pHdata, pEC); } /* last window */ gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); wvalue = *((Ipp16u*)&pScalar8[0]); wvalue = (wvalue << 1) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTable, digit-1, 5-1); negF(pHy, pHdata+elemLen, pGFE); cpMaskedReplace_ct(pHdata+elemLen, pHy, elemLen, ~cpIsZero_ct(sign)); gfec_point_add(pTdata, pTdata, pHdata, pEC); cpGFpElementCopy(pRdata, pTdata, pointLen); cpEcGFpReleasePool(2, pEC); cpGFpReleasePool(1, pGFE); } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_mul1.c000066400000000000000000000051011470420105600252030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_MulPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #if 0 IPP_OWN_DEFN (IppsGFpECPoint*, gfec_MulPoint, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { gsModEngine* pGForder = ECP_MONT_R(pEC); BNU_CHUNK_T* pTmpScalar = cpGFpGetPool(1, pGForder); /* length of scalar does not exceed length of order */ int orderBits = MOD_BITSIZE(pGForder); int orderLen = MOD_LEN(pGForder); cpGFpElementCopyPad(pTmpScalar,orderLen+1, pScalar,scalarLen); gfec_point_mul(ECP_POINT_X(pR), ECP_POINT_X(pP), (Ipp8u*)pTmpScalar, orderBits, pEC, pScratchBuffer); cpGFpReleasePool(1, pGForder); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR)? 0 : ECP_FINITE_POINT; return pR; } } #endif IPP_OWN_DEFN (IppsGFpECPoint*, gfec_MulPoint, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); BNU_CHUNK_T* pTmpScalar = cpGFpGetPool(2, pME); int orderBits = ECP_ORDBITSIZE(pEC); int orderLen = BITS_BNU_CHUNK(orderBits); cpGFpElementCopyPad(pTmpScalar, orderLen + 1, pScalar, scalarLen); gfec_point_mul(ECP_POINT_X(pR), ECP_POINT_X(pP), (Ipp8u*)pTmpScalar, orderBits, pEC, pScratchBuffer); cpGFpReleasePool(2, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_mulbase.c000066400000000000000000000061611470420105600257640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_base_point_mul() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "pcpmask_ct.h" IPP_OWN_DEFN (void, gfec_base_point_mul, (BNU_CHUNK_T* pRdata, const Ipp8u* pScalar8, int scalarBitSize, IppsGFpECState* pEC)) { /* size of window, get function and pre-computed table */ int window_size = ECP_PREMULBP(pEC)->w; selectAP select_affine_point = ECP_PREMULBP(pEC)->select_affine_point; const BNU_CHUNK_T* pTbl = ECP_PREMULBP(pEC)->pTbl; IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elmLen = GFP_FELEN(pGFE); mod_neg negF = GFP_METHOD(pGFE)->neg; BNU_CHUNK_T* mont1 = GFP_MNT_R(pGFE); /* number of points per table slot */ int tslot_point = 1<<(window_size-1); int tslot_size = tslot_point * (elmLen*2); BNU_CHUNK_T* negtmp = cpGFpGetPool(1, pGFE); /* temporary element */ BNU_CHUNK_T* pointT = cpEcGFpGetPool(1, pEC); /* temporary point */ Ipp8u digit, sign; int mask = (1<<(window_size+1)) -1; int bit = 0; /* processing of window[0] */ int wvalue = *((Ipp16u*)&pScalar8[0]); wvalue = (wvalue << 1) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); select_affine_point(pRdata, pTbl, digit); /* if(sign) R.y = -R.y */ negF(negtmp, pRdata+elmLen, pGFE); cpMaskedReplace_ct(pRdata+elmLen, negtmp, elmLen, ~cpIsZero_ct(sign)); /* R.z = R!=O? mont(1) : 0 */ cpGFpElementCopy(pRdata+elmLen*2, mont1, elmLen); cpGFpElementSetChunk(negtmp, elmLen, 0); cpMaskedReplace_ct(pRdata+elmLen*2, negtmp, elmLen, cpIsZero_ct(digit)); //T afine cpGFpElementCopy(pointT+elmLen*2, mont1, elmLen); /* processing of other windows.. [1],[2],... */ for(bit+=window_size, pTbl+=tslot_size; bit<=scalarBitSize; bit+=window_size, pTbl+=tslot_size) { wvalue = *((Ipp16u*)&pScalar8[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); select_affine_point(pointT, pTbl, digit); negF(negtmp, pointT+elmLen, pGFE); cpMaskedReplace_ct(pointT+elmLen, negtmp, elmLen, ~cpIsZero_ct(sign)); gfec_affine_point_add(pRdata, pRdata, pointT, pEC); } cpEcGFpReleasePool(1, pEC); cpGFpReleasePool(1, pGFE); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_mulbase1.c000066400000000000000000000037621470420105600260510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_MulBasePoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (IppsGFpECPoint*, gfec_MulBasePoint, (IppsGFpECPoint* pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { gsModEngine* pGForder = ECP_MONT_R(pEC); BNU_CHUNK_T* pTmpScalar = cpGFpGetPool(1, pGForder); /* length of scalar does not exceed length of order */ int orderBits = MOD_BITSIZE(pGForder); int orderLen = MOD_LEN(pGForder); cpGFpElementCopyPad(pTmpScalar,orderLen+1, pScalar,scalarLen); if(ECP_PREMULBP(pEC)) gfec_base_point_mul(ECP_POINT_X(pR), (Ipp8u*)pTmpScalar, orderBits, pEC); else gfec_point_mul(ECP_POINT_X(pR), ECP_G(pEC), (Ipp8u*)pTmpScalar, orderBits, pEC, pScratchBuffer); cpGFpReleasePool(1, pGForder); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR)? 0 : ECP_FINITE_POINT; return pR; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_negpoint.c000066400000000000000000000025671470420105600261650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_NegPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (IppsGFpECPoint*, gfec_NegPoint, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, IppsGFpECState* pEC)) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elmLen = GFP_FELEN(pGFE); if(pR!=pP) gfec_CopyPoint(pR, pP, elmLen); GFP_METHOD(pGFE)->neg(ECP_POINT_Y(pR), ECP_POINT_Y(pP), pGFE); return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_prod.c000066400000000000000000000120301470420105600252700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_point_prod() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #include "pcpmask_ct.h" IPP_OWN_DEFN (void, gfec_point_prod, (BNU_CHUNK_T* pointR, const BNU_CHUNK_T* pointA, const Ipp8u* scalarA, const BNU_CHUNK_T* pointB, const Ipp8u* scalarB, int scalarBitSize, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { int pointLen = ECP_POINTLEN(pEC); /* optimal size of window */ const int window_size = 5; /* number of table entries */ const int tableLen = 1<<(window_size-1); /* aligned pre-computed tables */ BNU_CHUNK_T* pTableA = (BNU_CHUNK_T*)IPP_ALIGNED_PTR(pScratchBuffer, CACHE_LINE_SIZE); BNU_CHUNK_T* pTableB = pTableA+pointLen*tableLen; setupTable(pTableA, pointA, pEC); setupTable(pTableB, pointB, pEC); { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_neg negF = GFP_METHOD(pGFE)->neg; BNU_CHUNK_T* pHy = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pTdata = cpEcGFpGetPool(1, pEC); /* points from the pool */ BNU_CHUNK_T* pHdata = cpEcGFpGetPool(1, pEC); int wvalue; Ipp8u digit, sign; int mask = (1<<(window_size+1)) -1; int bit = scalarBitSize-(scalarBitSize%window_size); /* first window */ if(bit) { wvalue = *((Ipp16u*)&scalarA[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; } else wvalue = 0; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pTdata, pointLen, pTableA, digit-1, 5-1); if(bit) { wvalue = *((Ipp16u*)&scalarB[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; } else wvalue = 0; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTableB, digit-1, 5-1); gfec_point_add(pTdata, pTdata, pHdata, pEC); for(bit-=window_size; bit>=window_size; bit-=window_size) { gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); wvalue = *((Ipp16u*)&scalarA[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTableA, digit-1, 5-1); negF(pHy, pHdata+elemLen, pGFE); cpMaskedReplace_ct(pHdata+elemLen, pHy, elemLen, ~cpIsZero_ct(sign)); gfec_point_add(pTdata, pTdata, pHdata, pEC); wvalue = *((Ipp16u*)&scalarB[(bit-1)/8]); wvalue = (wvalue>> ((bit-1)%8)) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTableB, digit-1, 5-1); negF(pHy, pHdata+elemLen, pGFE); cpMaskedReplace_ct(pHdata+elemLen, pHy, elemLen, ~cpIsZero_ct(sign)); gfec_point_add(pTdata, pTdata, pHdata, pEC); } /* last window */ gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); gfec_point_double(pTdata, pTdata, pEC); wvalue = *((Ipp16u*)&scalarA[0]); wvalue = (wvalue << 1) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTableA, digit-1, 5-1); negF(pHy, pHdata+elemLen, pGFE); cpMaskedReplace_ct(pHdata+elemLen, pHy, elemLen, ~cpIsZero_ct(sign)); gfec_point_add(pTdata, pTdata, pHdata, pEC); wvalue = *((Ipp16u*)&scalarB[0]); wvalue = (wvalue << 1) & mask; booth_recode(&sign, &digit, (Ipp8u)wvalue, window_size); gsScrambleGet_sscm(pHdata, pointLen, pTableB, digit-1, 5-1); negF(pHy, pHdata+elemLen, pGFE); cpMaskedReplace_ct(pHdata+elemLen, pHy, elemLen, ~cpIsZero_ct(sign)); gfec_point_add(pTdata, pTdata, pHdata, pEC); cpGFpElementCopy(pointR, pTdata, pointLen); cpEcGFpReleasePool(2, pEC); cpGFpReleasePool(1, pGFE); } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpec_selectp192r1w7.c000066400000000000000000000034071470420105600267500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // p192r1_select_ap_w7() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "pcpmask_ct.h" /* // select affine point */ #if (_IPP32E < _IPP32E_M7) IPP_OWN_DEFN (void, p192r1_select_ap_w7, (BNU_CHUNK_T* pVal, const BNU_CHUNK_T* pTbl, int idx)) { #define OPERAND_BITSIZE (192) #define LEN_P192 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) #define LEN_P192_APOINT (2*LEN_P192) const int tblLen = 64; int i; unsigned int n; /* clear output affine point */ for(n=0; nidCtx // invalid pP->idCtx // invalid pQ->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pP)!=GFP_FELEN() // ECP_POINT_FELEN(pQ)!=GFP_FELEN() // ECP_POINT_FELEN(pR)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pP Pointer to the context of the first elliptic curve point // pQ Pointer to the context of the second elliptic curve point // pR Pointer to the context of the resulting elliptic curve point // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECAddPoint,(const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECPoint* pR, IppsGFpECState* pEC)) { IPP_BAD_PTR4_RET(pP, pQ, pR, pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_POINT_VALID_ID(pP), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_POINT_VALID_ID(pQ), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_POINT_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(ECP_POINT_FELEN(pP) != GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET(ECP_POINT_FELEN(pQ) != GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET(ECP_POINT_FELEN(pR) != GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { gfec_AddPoint_nistp256_avx512(pR, pP, pQ, pEC); return ippStsNoErr; } case cpID_PrimeP384r1: { gfec_AddPoint_nistp384_avx512(pR, pP, pQ, pEC); return ippStsNoErr; } case cpID_PrimeP521r1: { gfec_AddPoint_nistp521_avx512(pR, pP, pQ, pEC); return ippStsNoErr; } case cpID_PrimeTPM_SM2: { gfec_AddPoint_sm2_avx512(pR, pP, pQ, pEC); return ippStsNoErr; } default: /* Go to default implementation below */ break; } } /* no else */ #endif // (_IPP32E >= _IPP32E_K1) if (pP == pQ) gfec_DblPoint(pR, pP, pEC); else gfec_AddPoint(pR, pP, pQ, pEC); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbindstd192r1.c000066400000000000000000000056761470420105600263350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECBindGxyTblStd192r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime, const cpPrecompAP* preComp, IppsGFpECState* pEC) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); Ipp32u elemLen = (Ipp32u)GFP_FELEN(pGFE); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(pPrime, (cpSize)elemLen, GFP_MODULUS(pGFE), (cpSize)elemLen), ippStsBadArgErr); { BNU_CHUNK_T* pbp_ec = ECP_G(pEC); int cmpFlag; BNU_CHUNK_T* pbp_tbl = cpEcGFpGetPool(1, pEC); selectAP select_affine_point = preComp->select_affine_point; const BNU_CHUNK_T* pTbl = preComp->pTbl; select_affine_point(pbp_tbl, pTbl, 1); /* check if EC's and G-table's Base Point is the same */ cmpFlag = cpCmp_BNU(pbp_ec, (cpSize)elemLen*2, pbp_tbl, (cpSize)elemLen*2); cpEcGFpReleasePool(1, pEC); return cmpFlag? ippStsBadArgErr : ippStsNoErr; } } } /*F* // Name: ippsGFpECBindGxyTblStd192r1 // // Purpose: Enables the use of base point-based pre-computed tables of EC192r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsBadArgErr pEC is not EC192r1 // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECBindGxyTblStd192r1,(IppsGFpECState* pEC)) { IppStatus sts = cpGFpECBindGxyTbl(secp192r1_p, gfpec_precom_nistP192r1_fun(), pEC); /* setup pre-computed g-table and point access function */ if(ippStsNoErr==sts) ECP_PREMULBP(pEC) = gfpec_precom_nistP192r1_fun(); return sts; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbindstd224r1.c000066400000000000000000000056761470420105600263310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECBindGxyTblStd224r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime, const cpPrecompAP* preComp, IppsGFpECState* pEC) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); Ipp32u elemLen = (Ipp32u)GFP_FELEN(pGFE); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(pPrime, (cpSize)elemLen, GFP_MODULUS(pGFE), (cpSize)elemLen), ippStsBadArgErr); { BNU_CHUNK_T* pbp_ec = ECP_G(pEC); int cmpFlag; BNU_CHUNK_T* pbp_tbl = cpEcGFpGetPool(1, pEC); selectAP select_affine_point = preComp->select_affine_point; const BNU_CHUNK_T* pTbl = preComp->pTbl; select_affine_point(pbp_tbl, pTbl, 1); /* check if EC's and G-table's Base Point is the same */ cmpFlag = cpCmp_BNU(pbp_ec, (cpSize)elemLen*2, pbp_tbl, (cpSize)elemLen*2); cpEcGFpReleasePool(1, pEC); return cmpFlag? ippStsBadArgErr : ippStsNoErr; } } } /*F* // Name: ippsGFpECBindGxyTblStd224r1 // // Purpose: Enables the use of base point-based pre-computed tables of EC224r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsBadArgErr pEC is not EC224r1 // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECBindGxyTblStd224r1,(IppsGFpECState* pEC)) { IppStatus sts = cpGFpECBindGxyTbl(secp224r1_p, gfpec_precom_nistP224r1_fun(), pEC); /* setup pre-computed g-table and point access function */ if(ippStsNoErr==sts) ECP_PREMULBP(pEC) = gfpec_precom_nistP224r1_fun(); return sts; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbindstd256r1.c000066400000000000000000000066651470420105600263350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECBindGxyTblStd256r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpmethod.h" static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime, const cpPrecompAP* preComp, IppsGFpECState* pEC) { IppsGFpState *pGF = ECP_GFP(pEC); gsModEngine *pGFE = GFP_PMA(pGF); Ipp32u elemLen = (Ipp32u)GFP_FELEN(pGFE); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(pPrime, (cpSize)elemLen, GFP_MODULUS(pGFE), (cpSize)elemLen), ippStsBadArgErr); { BNU_CHUNK_T *pbp_ec = ECP_G(pEC); int cmpFlag; BNU_CHUNK_T *pbp_tbl = cpEcGFpGetPool(1, pEC); selectAP select_affine_point = preComp->select_affine_point; const BNU_CHUNK_T *pTbl = preComp->pTbl; select_affine_point(pbp_tbl, pTbl, 1); /* check if EC's and G-table's Base Point is the same */ cmpFlag = cpCmp_BNU(pbp_ec, (cpSize)elemLen * 2, pbp_tbl, (cpSize)elemLen * 2); cpEcGFpReleasePool(1, pEC); return cmpFlag ? ippStsBadArgErr : ippStsNoErr; } } /*F* // Name: ippsGFpECBindGxyTblStd256r1 // // Purpose: Enables the use of base point-based pre-computed tables of EC256r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsBadArgErr pEC is not EC256r1 // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECBindGxyTblStd256r1, (IppsGFpECState * pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { /* ModulusId as well as IFMA-based GF(p) method are assigned in * ippsGFpECInitStd* function. If modulusId is not set (i.e. GFp method is * not IFMA-based), then bind regular table (not for IFMA implementation). */ if (ECP_MODULUS_ID(pEC) == cpID_PrimeP256r1) { ECP_PREMULBP(pEC) = gfpec_precom_nistP256r1_radix52_fun(); return ippStsNoErr; } } #endif const cpPrecompAP *precomp = gfpec_precom_nistP256r1_fun(); IppStatus sts = cpGFpECBindGxyTbl(secp256r1_p, precomp, pEC); /* setup pre-computed g-table and point access function */ if (ippStsNoErr == sts) ECP_PREMULBP(pEC) = precomp; return sts; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbindstd384r1.c000066400000000000000000000066651470420105600263370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECBindGxyTblStd384r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpmethod.h" static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime, const cpPrecompAP* preComp, IppsGFpECState* pEC) { IppsGFpState *pGF = ECP_GFP(pEC); gsModEngine *pGFE = GFP_PMA(pGF); Ipp32u elemLen = (Ipp32u)GFP_FELEN(pGFE); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(pPrime, (cpSize)elemLen, GFP_MODULUS(pGFE), (cpSize)elemLen), ippStsBadArgErr); { BNU_CHUNK_T *pbp_ec = ECP_G(pEC); int cmpFlag; BNU_CHUNK_T *pbp_tbl = cpEcGFpGetPool(1, pEC); selectAP select_affine_point = preComp->select_affine_point; const BNU_CHUNK_T *pTbl = preComp->pTbl; select_affine_point(pbp_tbl, pTbl, 1); /* check if EC's and G-table's Base Point is the same */ cmpFlag = cpCmp_BNU(pbp_ec, (cpSize)elemLen * 2, pbp_tbl, (cpSize)elemLen * 2); cpEcGFpReleasePool(1, pEC); return cmpFlag ? ippStsBadArgErr : ippStsNoErr; } } /*F* // Name: ippsGFpECBindGxyTblStd384r1 // // Purpose: Enables the use of base point-based pre-computed tables of EC384r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsBadArgErr pEC is not EC384r1 // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECBindGxyTblStd384r1, (IppsGFpECState * pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { /* ModulusId as well as IFMA-based GF(p) method are assigned in * ippsGFpECInitStd* function. If modulusId is not set (i.e. GFp method is * not IFMA-based), then bind regular table (not for IFMA implementation). */ if (ECP_MODULUS_ID(pEC) == cpID_PrimeP384r1) { ECP_PREMULBP(pEC) = gfpec_precom_nistP384r1_radix52_fun(); return ippStsNoErr; } } #endif const cpPrecompAP *precomp = gfpec_precom_nistP384r1_fun(); IppStatus sts = cpGFpECBindGxyTbl(secp384r1_p, precomp, pEC); /* setup pre-computed g-table and point access function */ if (ippStsNoErr == sts) ECP_PREMULBP(pEC) = precomp; return sts; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbindstd521r1.c000066400000000000000000000066651470420105600263300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECBindGxyTblStd521r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpmethod.h" static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime, const cpPrecompAP* preComp, IppsGFpECState* pEC) { IppsGFpState *pGF = ECP_GFP(pEC); gsModEngine *pGFE = GFP_PMA(pGF); Ipp32u elemLen = (Ipp32u)GFP_FELEN(pGFE); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(pPrime, (cpSize)elemLen, GFP_MODULUS(pGFE), (cpSize)elemLen), ippStsBadArgErr); { BNU_CHUNK_T *pbp_ec = ECP_G(pEC); int cmpFlag; BNU_CHUNK_T *pbp_tbl = cpEcGFpGetPool(1, pEC); selectAP select_affine_point = preComp->select_affine_point; const BNU_CHUNK_T *pTbl = preComp->pTbl; select_affine_point(pbp_tbl, pTbl, 1); /* check if EC's and G-table's Base Point is the same */ cmpFlag = cpCmp_BNU(pbp_ec, (cpSize)elemLen * 2, pbp_tbl, (cpSize)elemLen * 2); cpEcGFpReleasePool(1, pEC); return cmpFlag ? ippStsBadArgErr : ippStsNoErr; } } /*F* // Name: ippsGFpECBindGxyTblStd521r1 // // Purpose: Enables the use of base point-based pre-computed tables of EC521r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsBadArgErr pEC is not EC521r1 // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECBindGxyTblStd521r1, (IppsGFpECState * pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { /* ModulusId as well as IFMA-based GF(p) method are assigned in * ippsGFpECInitStd* function. If modulusId is not set (i.e. GFp method is * not IFMA-based), then bind regular table (not for IFMA implementation). */ if (ECP_MODULUS_ID(pEC) == cpID_PrimeP521r1) { ECP_PREMULBP(pEC) = gfpec_precom_nistP521r1_radix52_fun(); return ippStsNoErr; } } #endif const cpPrecompAP *precomp = gfpec_precom_nistP521r1_fun(); IppStatus sts = cpGFpECBindGxyTbl(secp521r1_p, precomp, pEC); /* setup pre-computed g-table and point access function */ if (ippStsNoErr == sts) ECP_PREMULBP(pEC) = precomp; return sts; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbindstdsm2.c000066400000000000000000000066341470420105600262530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECBindGxyTblStdSM2() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpmethod.h" static IppStatus cpGFpECBindGxyTbl(const BNU_CHUNK_T* pPrime, const cpPrecompAP* preComp, IppsGFpECState* pEC) { IppsGFpState *pGF = ECP_GFP(pEC); gsModEngine *pGFE = GFP_PMA(pGF); Ipp32u elemLen = (Ipp32u)GFP_FELEN(pGFE); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(pPrime, (cpSize)elemLen, GFP_MODULUS(pGFE), (cpSize)elemLen), ippStsBadArgErr); { BNU_CHUNK_T *pbp_ec = ECP_G(pEC); int cmpFlag; BNU_CHUNK_T *pbp_tbl = cpEcGFpGetPool(1, pEC); selectAP select_affine_point = preComp->select_affine_point; const BNU_CHUNK_T *pTbl = preComp->pTbl; select_affine_point(pbp_tbl, pTbl, 1); /* check if EC's and G-table's Base Point is the same */ cmpFlag = cpCmp_BNU(pbp_ec, (cpSize)elemLen * 2, pbp_tbl, (cpSize)elemLen * 2); cpEcGFpReleasePool(1, pEC); return cmpFlag ? ippStsBadArgErr : ippStsNoErr; } } /*F* // Name: ippsGFpECBindGxyTblStdSM2 // // Purpose: Enables the use of base point-based pre-computed tables of ECSM2 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsBadArgErr pEC is not ECSM2 // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECBindGxyTblStdSM2,(IppsGFpECState* pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { /* ModulusId as well as IFMA-based GF(p) method are assigned in * ippsGFpECInitStd* function. If modulusId is not set (i.e. GFp method is * not IFMA-based), then bind regular table (not for IFMA implementation). */ if (ECP_MODULUS_ID(pEC) == cpID_PrimeTPM_SM2) { ECP_PREMULBP(pEC) = gfpec_precom_sm2_radix52_fun(); return ippStsNoErr; } } #endif const cpPrecompAP* precomp = gfpec_precom_sm2_fun(); IppStatus sts = cpGFpECBindGxyTbl(tpmSM2_p256_p, precomp, pEC); /* setup pre-computed g-table and point access function */ if(ippStsNoErr == sts) ECP_PREMULBP(pEC) = precomp; return sts; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecbufsize.c000066400000000000000000000044171470420105600256460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECScratchBufferSize() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpScratchBufferSize // // Purpose: Gets the size of the scratch buffer. // // Returns: Reason: // ippStsNullPtrErr pEC == NULL // pBufferSize == NULL // ippStsContextMatchErr invalid pEC->idCtx // ippStsBadArgErr 0>=nScalars // nScalars>6 // ippStsNoErr no error // // Parameters: // nScalars Number of scalar values. // pEC Pointer to the context of the elliptic curve // pBufferSize Pointer to the calculated buffer size in bytes. // *F*/ IPPFUN(IppStatus, ippsGFpECScratchBufferSize,(int nScalars, const IppsGFpECState* pEC, int* pBufferSize)) { IPP_BAD_PTR2_RET(pEC, pBufferSize); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( (0>=nScalars)||(nScalars>IPP_MAX_EXPONENT_NUM), ippStsBadArgErr); { /* select constant size of window */ const int w = 5; /* number of table entries */ const int nPrecomputed = 1<<(w-1); /* because of signed digit representation of scalar is uses */ int pointDataSize = ECP_POINTLEN(pEC)*(Ipp32s)sizeof(BNU_CHUNK_T); *pBufferSize = nScalars * pointDataSize*nPrecomputed + CACHE_LINE_SIZE; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpeccmppoint.c000066400000000000000000000053471470420105600260330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECCmpPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECCmpPoint // // Purpose: Compares two points // // Returns: Reason: // ippStsNullPtrErr pP == NULL // pQ == NULL // pEC == NULL // pResult == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pP->idCtx // invalid pQ->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pP)!=GFP_FELEN() // ECP_POINT_FELEN(pQ)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pP Pointer to the context of the first elliptic curve point // pQ Pointer to the context of the second elliptic curve point // pEC Pointer to the context of the elliptic curve // pResult Pointer to the result of the comparison // *F*/ IPPFUN(IppStatus, ippsGFpECCmpPoint,(const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppECResult* pResult, IppsGFpECState* pEC)) { IPP_BAD_PTR4_RET(pP, pQ, pResult, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pP), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pQ), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pP)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pQ)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); *pResult = gfec_ComparePoint(pP, pQ, pEC)? ippECPointIsEqual : ippECPointIsNotEqual; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpeccpypoint.c000066400000000000000000000051121470420105600260350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECCpyPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECCpyPoint // // Purpose: Copies one point to another // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pR == NULL // pEC == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pA)!=GFP_FELEN() // ECP_POINT_FELEN(pR)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the elliptic curve point being copied // pR Pointer to the context of the elliptic curve point being changed // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECCpyPoint,(const IppsGFpECPoint* pA, IppsGFpECPoint* pR, IppsGFpECState* pEC)) { IPP_BAD_PTR3_RET(pA, pR, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pR), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pA)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pR)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); gfec_CopyPoint(pR, pA, GFP_FELEN(GFP_PMA(ECP_GFP(pEC)))); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecdh.c000066400000000000000000000150641470420105600245720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECSharedSecretDH() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECSharedSecretDHC // // Purpose: Compute Shared Secret (Diffie-Hellman) // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pPrivateA // NULL == pPublicB // NULL == pShare // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pPrivateA->idCtx // illegal pPublicB->idCtx // illegal pShare->idCtx // // ippStsRangeErr not enough room for share key // // ippStsShareKeyErr (infinity) => z // // ippStsNoErr no errors // // Parameters: // pPrivateA pointer to own private key // pPublicB pointer to alien public key // pShare pointer to the shared secret value // pEC pointer to the EC context // pScratchBuffer pointer to the scratch buffer // *F*/ IPPFUN(IppStatus, ippsGFpECSharedSecretDH,(const IppsBigNumState* pPrivateA, const IppsGFpECPoint* pPublicB, IppsBigNumState* pShare, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IppsGFpState *pGF; gsModEngine *pGFE; /* EC context and buffer */ IPP_BAD_PTR2_RET(pEC, pScratchBuffer); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); /* test private (own) key */ IPP_BAD_PTR1_RET(pPrivateA); IPP_BADARG_RET(!BN_VALID_ID(pPrivateA), ippStsContextMatchErr); /* test if 0 < pPrivateA < Order */ IPP_BADARG_RET(0==gfec_CheckPrivateKey(pPrivateA, pEC), ippStsInvalidPrivateKey); /* test public (other party) key */ IPP_BAD_PTR1_RET(pPublicB); IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPublicB), ippStsContextMatchErr); /* test if pPublicB belongs EC */ IPP_BADARG_RET(0==gfec_IsPointOnCurve(pPublicB, pEC), ippStsInvalidPoint); /* test share secret value */ IPP_BAD_PTR1_RET(pShare); IPP_BADARG_RET(!BN_VALID_ID(pShare), ippStsContextMatchErr); IPP_BADARG_RET((BN_ROOM(pShare) < GFP_FELEN(pGFE)), ippStsRangeErr); { /* init tmp Point */ IppsGFpECPoint T; cpEcGFpInitPoint(/* pPoint = */ &T, /* pData = */ cpEcGFpGetPool(1, pEC), /* flags = */ 0, /* pEC = */ pEC); int finite_point = 0; const int elmLen = GFP_FELEN(pGFE); /* share data */ BNU_CHUNK_T *pShareData = BN_NUMBER(pShare); int nsShare = BN_ROOM(pShare); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { finite_point = gfec_SharedSecretDH_nistp256_avx512(&T, pPublicB, BN_NUMBER(pPrivateA), BN_SIZE(pPrivateA), pEC, pScratchBuffer); if (finite_point) { cpGFpElementCopy(pShareData, ECP_POINT_X(&T), elmLen); cpGFpElementPad(pShareData + elmLen, nsShare - elmLen, 0); } goto exit; break; } case cpID_PrimeP384r1: { finite_point = gfec_SharedSecretDH_nistp384_avx512(&T, pPublicB, BN_NUMBER(pPrivateA), BN_SIZE(pPrivateA), pEC, pScratchBuffer); if (finite_point) { cpGFpElementCopy(pShareData, ECP_POINT_X(&T), elmLen); cpGFpElementPad(pShareData + elmLen, nsShare - elmLen, 0); } goto exit; break; } case cpID_PrimeP521r1: { finite_point = gfec_SharedSecretDH_nistp521_avx512(&T, pPublicB, BN_NUMBER(pPrivateA), BN_SIZE(pPrivateA), pEC, pScratchBuffer); if (finite_point) { cpGFpElementCopy(pShareData, ECP_POINT_X(&T), elmLen); cpGFpElementPad(pShareData + elmLen, nsShare - elmLen, 0); } goto exit; break; } case cpID_PrimeTPM_SM2: { finite_point = gfec_SharedSecretDH_sm2_avx512(&T, pPublicB, BN_NUMBER(pPrivateA), BN_SIZE(pPrivateA), pEC, pScratchBuffer); if (finite_point) { cpGFpElementCopy(pShareData, ECP_POINT_X(&T), elmLen); cpGFpElementPad(pShareData + elmLen, nsShare - elmLen, 0); } goto exit; break; } default: /* Go to default implementation below */ break; } } /* no else */ #endif // (_IPP32E >= _IPP32E_K1) { /* T = [privateA]pPublicB */ gfec_MulPoint(&T, pPublicB, BN_NUMBER(pPrivateA), BN_SIZE(pPrivateA), /*ECP_ORDBITSIZE(pEC),*/ pEC, pScratchBuffer); /* share = T.x */ IppsGFpElement elm; /* Buffer by GFpElement - get in Pool data */ cpGFpElementConstruct(&elm, cpGFpGetPool(1, pGFE), elmLen); finite_point = gfec_GetPoint(GFPE_DATA(&elm), NULL, &T, pEC); /* check finit point */ if (finite_point) { /* share = decode(T.x) */ GFP_METHOD(pGFE)->decode(pShareData, GFPE_DATA(&elm), pGFE); cpGFpElementPad(pShareData + elmLen, nsShare - elmLen, 0); } cpGFpReleasePool(1, pGFE); /* GFpElement */ } #if (_IPP32E >= _IPP32E_K1) exit: #endif if (finite_point) { BN_SIGN(pShare) = ippBigNumPOS; FIX_BNU(pShareData, nsShare); BN_SIZE(pShare) = nsShare; } cpEcGFpReleasePool(1, pEC); /* ECPoint */ return finite_point ? ippStsNoErr : ippStsShareKeyErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecdhc.c000066400000000000000000000113361470420105600247330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECSharedSecretDHC() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECSharedSecretDHC // // Purpose: Compute Shared Secret (Diffie-Hellman with cofactor) // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pPrivateA // NULL == pPublicB // NULL == pShare // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pPrivateA->idCtx // illegal pPublicB->idCtx // illegal pShare->idCtx // // ippStsRangeErr not enough room for share key // // ippStsShareKeyErr (infinity) => z // // ippStsNoErr no errors // // Parameters: // pPrivateA pointer to own private key // pPublicB pointer to alien public key // pShare pointer to the shared secret value // pEC pointer to the EC context // *F*/ IPPFUN(IppStatus, ippsGFpECSharedSecretDHC,(const IppsBigNumState* pPrivateA, const IppsGFpECPoint* pPublicB, IppsBigNumState* pShare, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pGFE; /* EC context and buffer */ IPP_BAD_PTR2_RET(pEC, pScratchBuffer); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); /* test private (own) key */ IPP_BAD_PTR1_RET(pPrivateA); IPP_BADARG_RET(!BN_VALID_ID(pPrivateA), ippStsContextMatchErr); /* test if 0 < pPrivateA < Order */ IPP_BADARG_RET(0 == gfec_CheckPrivateKey(pPrivateA, pEC), ippStsInvalidPrivateKey); /* test public (other party) key */ IPP_BAD_PTR1_RET(pPublicB); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPublicB), ippStsContextMatchErr ); /* test if pPublicB belongs EC */ IPP_BADARG_RET(0 == gfec_IsPointOnCurve(pPublicB, pEC), ippStsInvalidPoint); /* test share key */ IPP_BAD_PTR1_RET(pShare); IPP_BADARG_RET(!BN_VALID_ID(pShare), ippStsContextMatchErr); IPP_BADARG_RET((BN_ROOM(pShare)decode(pShareData, GFPE_DATA(&elm), pGFE); cpGFpElementPad(pShareData+elmLen, nsShare-elmLen, 0); BN_SIGN(pShare) = ippBigNumPOS; FIX_BNU(pShareData, nsShare); BN_SIZE(pShare) = nsShare; } cpGFpReleasePool(2, pGFE); cpEcGFpReleasePool(1, pEC); return finite_point? ippStsNoErr : ippStsShareKeyErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesdecryptsm2.c000066400000000000000000000043731470420105600266240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESDecrypt_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESDecrypt_SM2 // // Purpose: Decrypts the given buffer, updates the auth tag // // Returns: Reason: // ippStsNullPtrErr pInput == NULL / pOutput == NULL / pState == NULL // ippStsContextMatchErr pState invalid context or the algorithm is in an invalid state // ippStsSizeErr dataLen < 0 // ippStsNoErr no errors // // Parameters: // pInput Pointer to input data // pOutput Pointer to output data // dataLen Size of input and output buffers // pState Pointer to a SM2 algorithm state // *F*/ IPPFUN(IppStatus, ippsGFpECESDecrypt_SM2, (const Ipp8u* pInput, Ipp8u* pOutput, int dataLen, IppsECESState_SM2* pState)) { IPP_BAD_PTR3_RET(pInput, pOutput, pState); IPP_BADARG_RET(!VALID_ECES_SM2_ID(pState), ippStsContextMatchErr); /* a shared secret should be computed and the process should not be finished by getTag */ IPP_BADARG_RET(pState->state != ECESAlgoProcessing, ippStsIncompleteContextErr); IPP_BADARG_RET(dataLen < 0, ippStsSizeErr); { int i; for (i = 0; i < dataLen; ++i) { pOutput[i] = pInput[i] ^ cpECES_SM2KdfNextByte(pState); } } ippsHashUpdate_rmf(pOutput, dataLen, pState->pTagHasher); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesencryptsm2.c000066400000000000000000000043721470420105600266350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESEncrypt_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESEncrypt_SM2 // // Purpose: Encrypts the given buffer, updates the auth tag // // Returns: Reason: // ippStsNullPtrErr pInput == NULL / pOutput == NULL / pState == NULL // ippStsContextMatchErr pState invalid context or the algorithm is in an invalid state // ippStsSizeErr dataLen < 0 // ippStsNoErr no errors // // Parameters: // pInput Pointer to input data // pOutput Pointer to output data // dataLen Size of input and output buffers // pState Pointer to a SM2 algorithm state // *F*/ IPPFUN(IppStatus, ippsGFpECESEncrypt_SM2, (const Ipp8u* pInput, Ipp8u* pOutput, int dataLen, IppsECESState_SM2* pState)) { IPP_BAD_PTR3_RET(pInput, pOutput, pState); IPP_BADARG_RET(!VALID_ECES_SM2_ID(pState), ippStsContextMatchErr); /* a shared secret should be computed and the process should not be finished by getTag */ IPP_BADARG_RET(pState->state != ECESAlgoProcessing, ippStsIncompleteContextErr); IPP_BADARG_RET(dataLen < 0, ippStsSizeErr); ippsHashUpdate_rmf(pInput, dataLen, pState->pTagHasher); { int i; for (i = 0; i < dataLen; ++i) { pOutput[i] = pInput[i] ^ cpECES_SM2KdfNextByte(pState); } } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesfinalsm2.c000066400000000000000000000055241470420105600262420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESFinal_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESFinal_SM2 // // Purpose: Ends SM2 algorithm chain and returns an auth tag // // Returns: Reason: // ippStsNullPtrErr pTag == NULL / pState == NULL // ippStsContextMatchErr pState invalid context or the algorithm is in an invalid state // ippStsSizeErr tagLen < 0 || tagLen > IPP_SM3_DIGEST_BITSIZE / BYTESIZE // ippStsShareKeyErr All the kdf provided bytes were 0. The operation is completed successfully, but the warning is given // ippStsNoErr no errors // // Parameters: // pTag Pointer to a tag buffer to write to // tagLen Size of the tag [0; IPP_SM3_DIGEST_BITSIZE / BYTESIZE] // pState Pointer to a SM2 algorithm state // *F*/ IPPFUN(IppStatus, ippsGFpECESFinal_SM2, (Ipp8u* pTag, int tagLen, IppsECESState_SM2* pState)) { IPP_BAD_PTR2_RET(pTag, pState); IPP_BADARG_RET(!VALID_ECES_SM2_ID(pState), ippStsContextMatchErr); /* a shared secret should be computed and the process should not be finished by getTag */ IPP_BADARG_RET(pState->state != ECESAlgoProcessing, ippStsIncompleteContextErr); IPP_BADARG_RET(tagLen < 0 || tagLen > IPP_SM3_DIGEST_BITSIZE / BYTESIZE, ippStsSizeErr); ippsHashUpdate_rmf(pState->pSharedSecret + pState->sharedSecretLen / 2, pState->sharedSecretLen / 2, pState->pTagHasher); if (tagLen == IPP_SM3_DIGEST_BITSIZE / BYTESIZE) { ippsHashFinal_rmf(pTag, pState->pTagHasher); } else { Ipp8u pFinal[IPP_SM3_DIGEST_BITSIZE / BYTESIZE]; int i; ippsHashFinal_rmf(pFinal, pState->pTagHasher); for (i = 0; i < tagLen; ++i) { pTag[i] = pFinal[i]; } } pState->state = ECESAlgoFinished; /* cannot proceed further due to closing ippsSM3Update */ /* do the operation, but return an error code in 0-case */ return pState->wasNonZero ? ippStsNoErr : ippStsShareKeyErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesgetbufferssizesm2.c000066400000000000000000000041031470420105600301700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESGetBuffersSize_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESGetBuffersSize_SM2 // // Purpose: Returns sizes of used buffers // // Returns: Reason: // ippStsNullPtrErr pState == NULL if pPublicKeySize != NULL or all the pointers are NULLs // ippStsContextMatchErr pState invalid context if pPublicKeySize != NULL // ippStsNoErr no errors // // Parameters: // pPublicKeySize Pointer to write public (x||y) key length in bytes // pMaximumTagSize Pointer to write maximum tag size in bytes // pState Pointer to a state to get pPublicKeySize from // *F*/ IPPFUN(IppStatus, ippsGFpECESGetBuffersSize_SM2, (int* pPublicKeySize, int* pMaximumTagSize, const IppsECESState_SM2* pState)) { IPP_BADARG_RET(pPublicKeySize == NULL && pMaximumTagSize == NULL && pState == NULL, ippStsNullPtrErr); if (pMaximumTagSize) *pMaximumTagSize = IPP_SM3_DIGEST_BITSIZE / BYTESIZE; if (pPublicKeySize) { IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(!VALID_ECES_SM2_ID(pState), ippStsContextMatchErr); *pPublicKeySize = pState->sharedSecretLen; } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesgetsizesm2.c000066400000000000000000000037551470420105600266270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESGetSize_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESGetSize_SM2 // // Purpose: Computes space required to allocate a SM2 algorithm state // // Returns: Reason: // ippStsNullPtrErr pSize == NULL / pEC == NULL // ippStsContextMatchErr pEC invalid context // ippStsNotSupportedModeErr pGFE->extdegree > 1 // ippStsNoErr no errors // // Parameters: // pEC Pointer to an EC to calculate a shared secret size // pSize Pointer to write a SM2 algorithm state size // *F*/ IPPFUN(IppStatus, ippsGFpECESGetSize_SM2, (const IppsGFpECState* pEC, int* pSize)) { IPP_BAD_PTR2_RET(pEC, pSize); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!pEC->subgroup, ippStsContextMatchErr); IPP_BADARG_RET(1 < pEC->pGF->pGFE->extdegree, ippStsNotSupportedModeErr); { int sm3size; ippsHashGetSize_rmf(&sm3size); *pSize = (Ipp32s)sizeof(IppsECESState_SM2) + sm3size * 2 + BITS2WORD8_SIZE(pEC->pGF->pGFE->modBitLen) * 2; } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesinitsm2.c000066400000000000000000000053661470420105600261200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESInit_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESInit_SM2 // // Purpose: Inits the SM2 algorithm state // // Returns: Reason: // ippStsNullPtrErr pState == NULL / pEC == NULL // ippStsContextMatchErr pEC, pPoint invalid context // ippStsNotSupportedModeErr pGFE->extdegree > 1 // ippStsSizeErr size of the provided state is less than needed // ippStsNoErr no errors // // Parameters: // pEC Pointer to an EC to calculate a shared secret size // pState Pointer to a SM2 algorithm state buffer // avaliableCtxSize Count of available bytes in the context allocation // *F*/ IPPFUN(IppStatus, ippsGFpECESInit_SM2, (IppsGFpECState* pEC, IppsECESState_SM2* pState, int avaliableCtxSize)) { IPP_BAD_PTR2_RET(pEC, pState); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!pEC->subgroup, ippStsContextMatchErr); IPP_BADARG_RET(1 < pEC->pGF->pGFE->extdegree, ippStsNotSupportedModeErr); { int realCtxSize; ippsGFpECESGetSize_SM2(pEC, &realCtxSize); IPP_BADARG_RET(avaliableCtxSize < realCtxSize, ippStsSizeErr); { int sm3size; ippsHashGetSize_rmf(&sm3size); ECES_SM2_SET_ID(pState); pState->sharedSecretLen = BITS2WORD8_SIZE(pEC->pGF->pGFE->modBitLen) * 2; pState->pSharedSecret = ((Ipp8u*)pState) + sizeof(IppsECESState_SM2); pState->pKdfHasher = (IppsHashState_rmf*)(((Ipp8u*)pState) + sizeof(IppsECESState_SM2) + pState->sharedSecretLen); pState->pTagHasher = (IppsHashState_rmf*)(((Ipp8u*)pState) + sizeof(IppsECESState_SM2) + pState->sharedSecretLen + sm3size); ippsHashInit_rmf(pState->pKdfHasher, ippsHashMethod_SM3()); pState->state = ECESAlgoInit; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecessetkeysm2.c000066400000000000000000000102521470420105600264470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESSetKey_SM2() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECESSetKey_SM2 // // Purpose: Resets all counters, computes shared secret and saves it into the SM2 algorithm state // // Returns: Reason: // ippStsNullPtrErr pPrivate == NULL / pPublic == NULL / pState == NULL / pEC == NULL // ippStsContextMatchErr the algorithm is in an invalid state or any of the specified contexts does not match the operation // ippStsOutOfRangeErr private key does not belong to the EC's finite field or public key/result does not belong to EC // ippStsNotSupportedModeErr pGFE->extdegree > 1 // ippStsBadArgErr curve element size is not the same as in init / pPrivate is negative / pPrivate > pEC GFp mod // ippStsPointAtInfinity shared secret is a point at infinity // ippStsNoErr no errors // // Parameters: // pEC Pointer to an EC to calculate a shared secret size // pState Pointer to a SM2 algorithm state buffer // pPrivate Pointer to a private component of shared secret // pPublic Pointer to a public component // pEcScratchBuffer Pointer to a scratch buffer for computations on the EC // *F*/ IPPFUN(IppStatus, ippsGFpECESSetKey_SM2, (const IppsBigNumState* pPrivate, const IppsGFpECPoint* pPublic, IppsECESState_SM2* pState, IppsGFpECState* pEC, Ipp8u* pEcScratchBuffer)) { IPP_BAD_PTR4_RET(pPrivate, pPublic, pState, pEC); IPP_BADARG_RET(!VALID_ECES_SM2_ID(pState), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!pEC->subgroup, ippStsContextMatchErr); IPP_BADARG_RET(1 < pEC->pGF->pGFE->extdegree, ippStsNotSupportedModeErr); { gsModEngine* pGFE = pEC->pGF->pGFE; /* curve element size is not the same */ IPP_BADARG_RET(BITS2WORD8_SIZE(pGFE->modBitLen) * 2 != pState->sharedSecretLen, ippStsBadArgErr); { IppStatus multResult; IppsGFpECPoint PT; IppsGFpElement ptX, ptY; int finitePoint = 0; cpEcGFpInitPoint(&PT, cpEcGFpGetPool(1, pEC), 0, pEC); multResult = ippsGFpECMulPoint(pPublic, pPrivate, &PT, pEC, pEcScratchBuffer); if (ippStsNoErr == multResult) { cpGFpElementConstruct(&ptX, cpGFpGetPool(1, pGFE), pGFE->modLen); cpGFpElementConstruct(&ptY, cpGFpGetPool(1, pGFE), pGFE->modLen); finitePoint = gfec_GetPoint(ptX.pData, ptY.pData, &PT, pEC); if (finitePoint) { ippsGFpGetElementOctString(&ptX, pState->pSharedSecret, pState->sharedSecretLen / 2, pEC->pGF); ippsGFpGetElementOctString(&ptY, pState->pSharedSecret + pState->sharedSecretLen / 2, pState->sharedSecretLen / 2, pEC->pGF); pState->kdfCounter = 0; pState->kdfIndex = IPP_SM3_DIGEST_BITSIZE / BYTESIZE; /* will generate a kdf window */ pState->wasNonZero = 0; pState->state = ECESAlgoKeySet; } cpGFpReleasePool(2, pGFE); /* release ptX and ptY from the pool */ } cpEcGFpReleasePool(1, pEC); /* release PT from the pool */ if (multResult) return multResult; return finitePoint ? ippStsNoErr : ippStsPointAtInfinity; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecessm2.h000066400000000000000000000042661470420105600252370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // ES encryption/decryption API // // */ #if !defined(_CP_GFP_ES_SM2_H) #define _CP_GFP_ES_SM2_H #include "owncp.h" typedef enum { ECESAlgoInit, ECESAlgoKeySet, ECESAlgoProcessing, ECESAlgoFinished } ECESAlgoState; struct _cpStateECES_SM2 { Ipp32u idCtx; Ipp8u* pSharedSecret; Ipp32s sharedSecretLen; ECESAlgoState state; Ipp32u kdfCounter; Ipp8u pKdfWindow[IPP_SM3_DIGEST_BITSIZE / BYTESIZE]; Ipp8u wasNonZero; Ipp8u kdfIndex; IppsHashState_rmf* pKdfHasher; IppsHashState_rmf* pTagHasher; }; #define ECES_SM2_SET_ID(stt) ((stt)->idCtx = (Ipp32u)idxCtxECES_SM2 ^ (Ipp32u)IPP_UINT_PTR(stt)) #define VALID_ECES_SM2_ID(stt) ((((stt)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((stt))) == (Ipp32u)idxCtxECES_SM2) /* get a byte, update 0-kdf status */ __IPPCP_INLINE Ipp8u cpECES_SM2KdfNextByte(IppsECESState_SM2* pState) { if (pState->kdfIndex == IPP_SM3_DIGEST_BITSIZE / BYTESIZE) { ++pState->kdfCounter; pState->kdfIndex = 0; { Ipp8u ctnStr[sizeof(Ipp32u)]; ippsHashUpdate_rmf(pState->pSharedSecret, pState->sharedSecretLen, pState->pKdfHasher); U32_TO_HSTRING(ctnStr, pState->kdfCounter); ippsHashUpdate_rmf(ctnStr, sizeof(Ipp32u), pState->pKdfHasher); ippsHashFinal_rmf(pState->pKdfWindow, pState->pKdfHasher); } } pState->wasNonZero |= pState->pKdfWindow[pState->kdfIndex]; return pState->pKdfWindow[pState->kdfIndex++]; } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecesstartsm2.c000066400000000000000000000034101470420105600262760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECESStart_SM2() // */ #include "gfpec/pcpgfpecessm2.h" /*F* // Name: ippsGFpECESStart_SM2 // // Purpose: Starts an SM2 encryption chain. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsContextMatchErr pState invalid context or the algorithm is in an invalid state // ippStsNoErr no errors // // Parameters: // pState Pointer to a SM2 algorithm state // *F*/ IPPFUN(IppStatus, ippsGFpECESStart_SM2, (IppsECESState_SM2* pState)) { IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(!VALID_ECES_SM2_ID(pState), ippStsContextMatchErr); IPP_BADARG_RET(pState->state != ECESAlgoKeySet, ippStsContextMatchErr); ippsHashInit_rmf(pState->pTagHasher, ippsHashMethod_SM3()); ippsHashUpdate_rmf(pState->pSharedSecret, pState->sharedSecretLen / 2, pState->pTagHasher); pState->state = ECESAlgoProcessing; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecget.c000066400000000000000000000055361470420105600247610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECGet() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECGet // // Purpose: Extracts the parameters of an elliptic curve // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // invalid pA->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM(pA)!=GFP_FELEN(pGFE) // GFPE_ROOM(pB)!=GFP_FELEN(pGFE) // // ippStsNoErr no error // // Parameters: // ppGFp Pointer to the pointer to the context of underlying finite field // pA Pointer to a copy of the coefficient A of the equation defining the elliptic curve // pB Pointer to a copy of the coefficient B of the equation defining the elliptic curve // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECGet,(IppsGFpState** const ppGFp, IppsGFpElement* pA, IppsGFpElement* pB, const IppsGFpECState* pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); { const IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); Ipp32u elementSize = (Ipp32u)GFP_FELEN(pGFE); if(ppGFp) { *ppGFp = (IppsGFpState*)pGF; } if(pA) { IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); cpGFpElementCopy(GFPE_DATA(pA), ECP_A(pEC), (cpSize)elementSize); } if(pB) { IPP_BADARG_RET( !GFPE_VALID_ID(pB), ippStsContextMatchErr ); IPP_BADARG_RET( GFPE_ROOM(pB)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); cpGFpElementCopy(GFPE_DATA(pB), ECP_B(pEC), (cpSize)elementSize); } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecgetinfo.c000066400000000000000000000041331470420105600256250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECGetInfo_GF() // */ #include "owncp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECGetInfo_GF // // Purpose: Returns info regarding underlying GF // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pInfo // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsNoErr no error // // Parameters: // pInfo Pointer to the info structure // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECGetInfo_GF,(IppsGFpInfo* pInfo, const IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pInfo, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); return ippsGFpGetInfo(pInfo, ECP_GFP(pEC)); #if 0 { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFpx = GFP_PMA(pGF); /* current */ gsModEngine* pGFp = cpGFpBasic(pGFpx); /* basic */ pInfo->parentGFdegree = MOD_EXTDEG(pGFpx); /* parent extension */ pInfo->basicGFdegree = cpGFpBasicDegreeExtension(pGFpx); /* total basic extension */ pInfo->basicElmBitSize = GFP_FEBITLEN(pGFp); /* basic bitsise */ return ippStsNoErr; } #endif } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecgetpoint.c000066400000000000000000000063171470420105600260310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECGetPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECGetPoint // // Purpose: Retrieves coordinates of a point on an elliptic curve // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // pX != NULL && invalid pX->idCtx // pY != NULL && invalid pY->idCtx // pX != NULL && GFPE_ROOM(pX)!=GFP_FELEN() // pY != NULL && GFPE_ROOM(pY)!=GFP_FELEN() // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // pX != NULL && GFPE_ROOM(pX)!=GFP_FELEN() // pY != NULL && GFPE_ROOM(pY)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // pX, pY Pointers to the X and Y coordinates of a point on the elliptic curve // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECGetPoint,(const IppsGFpECPoint* pPoint, IppsGFpElement* pX, IppsGFpElement* pY, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pPoint, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( pX && !GFPE_VALID_ID(pX), ippStsContextMatchErr ); IPP_BADARG_RET( pY && !GFPE_VALID_ID(pY), ippStsContextMatchErr ); IPP_BADARG_RET( pX && GFPE_ROOM(pX)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( pY && GFPE_ROOM(pY)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); /* returns (X,Y) == (0,0) if Point is at infinity */ gfec_GetPoint((pX)? GFPE_DATA(pX):NULL, (pY)? GFPE_DATA(pY):NULL, pPoint, pEC); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecgetpointoctstring.c000066400000000000000000000062561470420105600277700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECGetPointOctString() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECGetPointOctString // // Purpose: Converts a point on EC into x||y octstring // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL / pEC == NULL / pStr == NULL // ippStsContextMatchErr pEC, pPoint invalid context // ippStsNotSupportedModeErr pGFE->extdegree > 1 // ippStsSizeErr strLen is not equal to double GFp element // ippStsOutOfRangeErr the point does not belong to the EC // ippStsPointAtInfinity a point on infinity cannot be converted to a string // ippStsNoErr no errors // // Parameters: // pStr pointer to the string to read from // strLen length of the string // pPoint pointer to output point // pEC EC ctx // *F*/ IPPFUN(IppStatus, ippsGFpECGetPointOctString, (const IppsGFpECPoint* pPoint, Ipp8u* pStr, int strLen, IppsGFpECState* pEC)) { IPP_BAD_PTR3_RET(pPoint, pEC, pStr); IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); { gsModEngine* pGFE = pEC->pGF->pGFE; IppsGFpInfo gfi; ippsGFpGetInfo(&gfi, pEC->pGF); { int elemLenBits = gfi.basicGFdegree * gfi.basicElmBitSize; int elemLenBytes = BITS2WORD8_SIZE(elemLenBits); int elemLenChunks = BITS_BNU_CHUNK(elemLenBits); IPP_BADARG_RET(strLen != elemLenBytes * 2, ippStsSizeErr); IPP_BADARG_RET(pPoint->elementSize != elemLenChunks, ippStsOutOfRangeErr); { int finitePoint; IppsGFpElement ptX, ptY; cpGFpElementConstruct(&ptX, cpGFpGetPool(1, pGFE), elemLenChunks); cpGFpElementConstruct(&ptY, cpGFpGetPool(1, pGFE), elemLenChunks); finitePoint = gfec_GetPoint(ptX.pData, ptY.pData, pPoint, pEC); if (finitePoint) { ippsGFpGetElementOctString(&ptX, pStr, elemLenBytes, pEC->pGF); pStr += elemLenBytes; ippsGFpGetElementOctString(&ptY, pStr, elemLenBytes, pEC->pGF); } cpGFpReleasePool(2, pGFE); /* release ptX and ptY from the pool */ return finitePoint ? ippStsNoErr : ippStsPointAtInfinity; } } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecgetpointreg.c000066400000000000000000000067421470420105600265310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECGetPointRegular() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECGetPointRegular // // Purpose: Retrieves coordinates of a point on an elliptic curve in the regular domain // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // invalid pX->idCtx // invalid pY->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // BN_ROOM(pX)*BNU_CHUNK_BITSdecode(x, x, pGFE); ippsSet_BN(ippBigNumPOS, GFP_FELEN32(pGFE), (Ipp32u*)x, pX); } if(pY) { GFP_METHOD(pGFE)->decode(y, y, pGFE); ippsSet_BN(ippBigNumPOS, GFP_FELEN32(pGFE), (Ipp32u*)y, pY); } cpGFpReleasePool(2, pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecgetsize.c000066400000000000000000000035311470420105600256450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECGetSize // // Purpose: Gets the size of an elliptic curve over the finite field // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pSize // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pSize Buffer size in bytes needed for the IppsGFpECState context // *F*/ IPPFUN(IppStatus, ippsGFpECGetSize,(const IppsGFpState* pGFp, int* pSize)) { IPP_BAD_PTR2_RET(pGFp, pSize); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); *pSize = cpGFpECGetSize(cpGFpBasicDegreeExtension(pGFE), GFP_FEBITLEN(cpGFpBasic(pGFE))); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecgetsubgroup.c000066400000000000000000000106121470420105600265370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECGetSubgroup() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECGet // // Purpose: Extracts the parameters (base point and its order) of an elliptic curve // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // // ippStsContextMatchErr invalid pEC->idCtx // NULL == pEC->subgroup // invalid pX->idCtx // invalid pY->idCtx // // ippStsOutOfRangeErr GFPE_ROOM(pX)!=GFP_FELEN(pGFE) // GFPE_ROOM(pY)!=GFP_FELEN(pGFE) // // ippStsLengthErr BN_ROOM(pOrder) < orderLen // BN_ROOM(pCofactor) < cofactorLen // // ippStsNoErr no error // // Parameters: // ppGFp Pointer to the pointer to the context of underlying finite field // pX, pY Pointers to the X and Y coordinates of the base point of the elliptic curve // pOrder Pointer to the big number context storing the order of the base point. // pCofactor Pointer to the big number context storing the cofactor. // pEC Pointer to the context of the elliptic curve. // *F*/ IPPFUN(IppStatus, ippsGFpECGetSubgroup,(IppsGFpState** const ppGFp, IppsGFpElement* pX, IppsGFpElement* pY, IppsBigNumState* pOrder, IppsBigNumState* pCofactor, const IppsGFpECState* pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); { const IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); Ipp32u elementSize = (Ipp32u)GFP_FELEN(pGFE); if(ppGFp) { *ppGFp = (IppsGFpState*)pGF; } if(pX) { IPP_BADARG_RET( !GFPE_VALID_ID(pX), ippStsContextMatchErr ); IPP_BADARG_RET( GFPE_ROOM(pX)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); cpGFpElementCopy(GFPE_DATA(pX), ECP_G(pEC), (cpSize)elementSize); } if(pY) { IPP_BADARG_RET( !GFPE_VALID_ID(pY), ippStsContextMatchErr ); IPP_BADARG_RET( GFPE_ROOM(pY)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); cpGFpElementCopy(GFPE_DATA(pY), ECP_G(pEC)+elementSize, (cpSize)elementSize); } if(pOrder) { BNU_CHUNK_T* pOrderData = MOD_MODULUS(ECP_MONT_R(pEC)); int orderBitSize = ECP_ORDBITSIZE(pEC); int orderLen = BITS_BNU_CHUNK(orderBitSize); FIX_BNU(pOrderData, orderLen); IPP_BADARG_RET(!BN_VALID_ID(pOrder), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pOrder) < orderLen, ippStsLengthErr); ZEXPAND_COPY_BNU(BN_NUMBER(pOrder), BN_ROOM(pOrder), pOrderData, orderLen); BN_SIZE(pOrder) = orderLen; BN_SIGN(pOrder) = ippBigNumPOS; } if(pCofactor) { BNU_CHUNK_T* pCofactorData = ECP_COFACTOR(pEC); int cofactorLen = (cpSize)elementSize; FIX_BNU(pCofactorData, cofactorLen); IPP_BADARG_RET(!BN_VALID_ID(pCofactor), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pCofactor) < cofactorLen, ippStsLengthErr); ZEXPAND_COPY_BNU(BN_NUMBER(pCofactor), BN_ROOM(pCofactor), pCofactorData, cofactorLen); BN_SIZE(pCofactor) = cofactorLen; BN_SIGN(pCofactor) = ippBigNumPOS; } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinit.c000066400000000000000000000111641470420105600251370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInit() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpmethod.h" /*F* // Name: ippsGFpECInit // // Purpose: Initializes the context of an elliptic curve over a finite field. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pA // NULL == pB // // ippStsContextMatchErr invalid pEC->idCtx // invalid pA->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM(pA)!=GFP_FELEN(pGFE) // GFPE_ROOM(pB)!=GFP_FELEN(pGFE) // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pA Pointer to the coefficient A of the equation defining the elliptic curve // pB Pointer to the coefficient B of the equation defining the elliptic curve // pEC Pointer to the context of the elliptic curve being initialized // *F*/ IPPFUN(IppStatus, ippsGFpECInit,(const IppsGFpState* pGFp, const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { Ipp8u* ptr = (Ipp8u*)pEC; gsModEngine* pGFE = GFP_PMA(pGFp); int elemLen = GFP_FELEN(pGFE); int maxOrderBits = 1+ cpGFpBasicDegreeExtension(pGFE) * GFP_FEBITLEN(cpGFpBasic(pGFE)); /* Hasse's theorem */ #if defined(_LEGACY_ECCP_SUPPORT_) int maxOrdLen = BITS_BNU_CHUNK(maxOrderBits); #endif int modEngineCtxSize; gsModEngineGetSize(maxOrderBits, MONT_DEFAULT_POOL_LENGTH, &modEngineCtxSize); ECP_SET_ID(pEC); ECP_MODULUS_ID(pEC) = cpID_Prime; ECP_GFP(pEC) = (IppsGFpState*)pGFp; ECP_SUBGROUP(pEC) = 0; ECP_POINTLEN(pEC) = elemLen*3; ECP_ORDBITSIZE(pEC) = maxOrderBits; ECP_SPECIFIC(pEC) = ECP_ARB; ptr += sizeof(IppsGFpECState); ECP_A(pEC) = (BNU_CHUNK_T*)(ptr); ptr += elemLen*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_B(pEC) = (BNU_CHUNK_T*)(ptr); ptr += elemLen*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_G(pEC) = (BNU_CHUNK_T*)(ptr); ptr += ECP_POINTLEN(pEC)*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_PREMULBP(pEC) = (cpPrecompAP*)NULL; ECP_MONT_R(pEC) = (gsModEngine*)(ptr); ptr += modEngineCtxSize; ECP_COFACTOR(pEC) = (BNU_CHUNK_T*)(ptr); ptr += elemLen*(Ipp32s)sizeof(BNU_CHUNK_T); #if defined(_LEGACY_ECCP_SUPPORT_) ECP_PUBLIC(pEC) = (BNU_CHUNK_T*)(ptr); ptr += 3*elemLen*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_PUBLIC_E(pEC) = (BNU_CHUNK_T*)(ptr); ptr += 3*elemLen*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_PRIVAT(pEC) = (BNU_CHUNK_T*)(ptr); ptr += maxOrdLen*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_PRIVAT_E(pEC) = (BNU_CHUNK_T*)(ptr); ptr += maxOrdLen*(Ipp32s)sizeof(BNU_CHUNK_T); ECP_SBUFFER(pEC) = (BNU_CHUNK_T*)0; #endif ECP_POOL(pEC) = (BNU_CHUNK_T*)(ptr); //ptr += ECP_POINTLEN(pEC)*sizeof(BNU_CHUNK_T)*EC_POOL_SIZE; cpGFpElementPad(ECP_A(pEC), elemLen, 0); cpGFpElementPad(ECP_B(pEC), elemLen, 0); cpGFpElementPad(ECP_G(pEC), elemLen*3, 0); //gsModEngineInit(ECP_MONT_R(pEC), NULL, maxOrderBits, MONT_DEFAULT_POOL_LENGTH, gsModArithMont()); gsModEngineInit(ECP_MONT_R(pEC), NULL, maxOrderBits, MONT_DEFAULT_POOL_LENGTH, NULL); cpGFpElementPad(ECP_COFACTOR(pEC), elemLen, 0); cpGFpElementPad(ECP_POOL(pEC), elemLen*3*EC_POOL_SIZE, 0); /* set up EC if possible */ if(pA && pB) return ippsGFpECSet(pA,pB, pEC); else return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd128r1.c000066400000000000000000000077231470420105600263560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd128r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); } /*F* // Name: ippsGFpECInitStd128r1 // // Purpose: Initializes the context of EC128r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd128r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp128r1_p, BITS_BNU_CHUNK(128), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(128)), ippStsBadArgErr); ippsGFpECInit(pGFp, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(128), secp128r1_a, BITS_BNU_CHUNK(128), secp128r1_b, BITS_BNU_CHUNK(128), secp128r1_gx, BITS_BNU_CHUNK(128), secp128r1_gy, BITS_BNU_CHUNK(128), secp128r1_r, secp128r1_h, pEC); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd128r2.c000066400000000000000000000077231470420105600263570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd128r2() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); } /*F* // Name: ippsGFpECInitStd128r2 // // Purpose: Initializes the context of EC128r2 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd128r2,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp128r2_p, BITS_BNU_CHUNK(128), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(128)), ippStsBadArgErr); ippsGFpECInit(pGFp, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(128), secp128r2_a, BITS_BNU_CHUNK(128), secp128r2_b, BITS_BNU_CHUNK(128), secp128r2_gx, BITS_BNU_CHUNK(128), secp128r2_gy, BITS_BNU_CHUNK(128), secp128r2_r, secp128r2_h, pEC); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd192r1.c000066400000000000000000000077231470420105600263570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd192r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); } /*F* // Name: ippsGFpECInitStd192r1 // // Purpose: Initializes the context of EC192r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd192r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp192r1_p, BITS_BNU_CHUNK(192), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(192)), ippStsBadArgErr); ippsGFpECInit(pGFp, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(192), secp192r1_a, BITS_BNU_CHUNK(192), secp192r1_b, BITS_BNU_CHUNK(192), secp192r1_gx, BITS_BNU_CHUNK(192), secp192r1_gy, BITS_BNU_CHUNK(192), secp192r1_r, secp192r1_h, pEC); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd224r1.c000066400000000000000000000077231470420105600263530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd224r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); } /*F* // Name: ippsGFpECInitStd224r1 // // Purpose: Initializes the context of EC224r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd224r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp224r1_p, BITS_BNU_CHUNK(224), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(224)), ippStsBadArgErr); ippsGFpECInit(pGFp, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(224), secp224r1_a, BITS_BNU_CHUNK(224), secp224r1_b, BITS_BNU_CHUNK(224), secp224r1_gx, BITS_BNU_CHUNK(224), secp224r1_gy, BITS_BNU_CHUNK(224), secp224r1_r, secp224r1_h, pEC); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd256r1.c000066400000000000000000000103531470420105600263510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd256r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/pcpgfpmethod.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { ECP_MONT_R(pEC)->method_alt = gsArithGF_n256r1_avx512(); } #endif } /*F* // Name: ippsGFpECInitStd256r1 // // Purpose: Initializes the context of EC256r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd256r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp256r1_p, BITS_BNU_CHUNK(256), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(256)), ippStsBadArgErr); ippsGFpECInit(pGFp, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(256), secp256r1_a, BITS_BNU_CHUNK(256), secp256r1_b, BITS_BNU_CHUNK(256), secp256r1_gx, BITS_BNU_CHUNK(256), secp256r1_gy, BITS_BNU_CHUNK(256), secp256r1_r, secp256r1_h, pEC); ECP_MODULUS_ID(pEC) = cpID_PrimeP256r1; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd384r1.c000066400000000000000000000103161470420105600263520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd384r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/ecnist/ifma_arith_method.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { ECP_MONT_R(pEC)->method_alt = gsArithGF_n384r1_avx512(); } #endif } /*F* // Name: ippsGFpECInitStd384r1 // // Purpose: Initializes the context of EC384r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd384r1,(const IppsGFpState* pGFp, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGFp, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp384r1_p, BITS_BNU_CHUNK(384), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(384)), ippStsBadArgErr); ippsGFpECInit(pGFp, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(384), secp384r1_a, BITS_BNU_CHUNK(384), secp384r1_b, BITS_BNU_CHUNK(384), secp384r1_gx, BITS_BNU_CHUNK(384), secp384r1_gy, BITS_BNU_CHUNK(384), secp384r1_r, secp384r1_h, pEC); ECP_MODULUS_ID(pEC) = cpID_PrimeP384r1; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstd521r1.c000066400000000000000000000103171470420105600263440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStd521r1() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { ECP_MONT_R(pEC)->method_alt = gsArithGF_n521r1_avx512(); } #endif } /*F* // Name: ippsGFpECInitStd521r1 // // Purpose: Initializes the context of EC521r1 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStd521r1,(const IppsGFpState* pGF, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGF, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGF), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGF); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(secp521r1_p, BITS_BNU_CHUNK(521), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(521)), ippStsBadArgErr); ippsGFpECInit(pGF, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(521), secp521r1_a, BITS_BNU_CHUNK(521), secp521r1_b, BITS_BNU_CHUNK(521), secp521r1_gx, BITS_BNU_CHUNK(521), secp521r1_gy, BITS_BNU_CHUNK(521), secp521r1_r, secp521r1_h, pEC); ECP_MODULUS_ID(pEC) = cpID_PrimeP521r1; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstdbn256.c000066400000000000000000000100231470420105600264200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStdBN256() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); } /*F* // Name: ippsGFpECInitStdBN256 // // Purpose: Initializes the context of ECBN256 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStdBN256,(const IppsGFpState* pGF, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGF, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGF), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGF); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(tpmBN_p256p_p, BITS_BNU_CHUNK(256), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(256)), ippStsBadArgErr); ippsGFpECInit(pGF, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_a, BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_b, BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_gx, BITS_BNU_CHUNK(BNU_CHUNK_BITS), tpmBN_p256p_gy, BITS_BNU_CHUNK(256), tpmBN_p256p_r, tpmBN_p256p_h, pEC); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecinitstdsm2.c000066400000000000000000000105101470420105600262660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECInitStdSM2() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gfpec/pcpgfpmethod.h" #endif // (_IPP32E >= _IPP32E_K1) static void cpGFpECSetStd(int aLen, const BNU_CHUNK_T* pA, int bLen, const BNU_CHUNK_T* pB, int xLen, const BNU_CHUNK_T* pX, int yLen, const BNU_CHUNK_T* pY, int rLen, const BNU_CHUNK_T* pR, BNU_CHUNK_T h, IppsGFpECState* pEC) { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IppsGFpElement elmA, elmB; __ALIGN8 IppsBigNumState R; __ALIGN8 IppsBigNumState H; /* convert A and B coeffs into GF elements */ cpGFpElementConstruct(&elmA, cpGFpGetPool(1, pGFE), elemLen); cpGFpElementConstruct(&elmB, cpGFpGetPool(1, pGFE), elemLen); ippsGFpSetElement((Ipp32u*)pA, BITS2WORD32_SIZE(BITSIZE_BNU(pA,aLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pB, BITS2WORD32_SIZE(BITSIZE_BNU(pB,bLen)), &elmB, pGF); /* and set EC */ ippsGFpECSet(&elmA, &elmB, pEC); /* construct R and H */ cpConstructBN(&R, rLen, (BNU_CHUNK_T*)pR, NULL); cpConstructBN(&H, 1, &h, NULL); /* convert GX and GY coeffs into GF elements */ ippsGFpSetElement((Ipp32u*)pX, BITS2WORD32_SIZE(BITSIZE_BNU(pX,xLen)), &elmA, pGF); ippsGFpSetElement((Ipp32u*)pY, BITS2WORD32_SIZE(BITSIZE_BNU(pY,yLen)), &elmB, pGF); /* and init EC subgroup */ ippsGFpECSetSubgroup(&elmA, &elmB, &R, &H, pEC); cpGFpReleasePool(2, pGFE); #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { ECP_MONT_R(pEC)->method_alt = gsArithGF_nsm2_avx512(); } #endif // (_IPP32E >= _IPP32E_K1) } /*F* // Name: ippsGFpECInitStdSM2 // // Purpose: Initializes the context of ECSM2 // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pGFp // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsBadArgErr pGFp does not specify the finite field over which the given // standard elliptic curve is defined // // ippStsNoErr no error // // Parameters: // pGFp Pointer to the IppsGFpState context of the underlying finite field // pEC Pointer to the context of the elliptic curve being initialized. // *F*/ IPPFUN(IppStatus, ippsGFpECInitStdSM2,(const IppsGFpState* pGF, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pGF, pEC); IPP_BADARG_RET( !GFP_VALID_ID(pGF), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGF); /* test if GF is prime GF */ IPP_BADARG_RET(!GFP_IS_BASIC(pGFE), ippStsBadArgErr); /* test underlying prime value*/ IPP_BADARG_RET(cpCmp_BNU(tpmSM2_p256_p, BITS_BNU_CHUNK(256), GFP_MODULUS(pGFE), BITS_BNU_CHUNK(256)), ippStsBadArgErr); ippsGFpECInit(pGF, NULL, NULL, pEC); cpGFpECSetStd(BITS_BNU_CHUNK(256), tpmSM2_p256_a, BITS_BNU_CHUNK(256), tpmSM2_p256_b, BITS_BNU_CHUNK(256), tpmSM2_p256_gx, BITS_BNU_CHUNK(256), tpmSM2_p256_gy, BITS_BNU_CHUNK(256), tpmSM2_p256_r, tpmSM2_p256_h, pEC); ECP_MODULUS_ID(pEC) = cpID_PrimeTPM_SM2; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpeckeys.c000066400000000000000000000117331470420105600251510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECTstKeyPair() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" /* // checks privateKey // // returns 1 if private_key belongs (0,order) range // 0 if otherwise */ int gfec_CheckPrivateKey(const IppsBigNumState* pPrivate, IppsGFpECState* pEC) { /* order */ BNU_CHUNK_T* pOrder = MOD_MODULUS(ECP_MONT_R(pEC)); int orderLen = BITS_BNU_CHUNK(ECP_ORDBITSIZE(pEC)); /* key under check */ BNU_CHUNK_T* pKey = BN_NUMBER(pPrivate); int keyLen = BN_SIZE(pPrivate); IppsGFpState *pGF = ECP_GFP(pEC); gsModEngine *pGFE = GFP_PMA(pGF); BNU_CHUNK_T* F = cpGFpGetPool(1, pGFE); int ret = BN_POSITIVE(pPrivate); if (ret) ret = !IsZero_BN(pPrivate); if (ret) ret = ECP_ORDBITSIZE(pEC) >= cpBN_bitsize(pPrivate); if (ret) { cpGFpElementCopyPad(F, orderLen, pKey, keyLen); /* cpSub_BNU() returns borrow bit, so any non - zero value corresponds to a valid key range(key < order) */ ret = 0 != cpSub_BNU(F, F, pOrder, orderLen); } cpGFpReleasePool(1, pGFE); return ret; } /*F* // Name: ippsGFpECTstKeyPair // // Purpose: Test Key Pair // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pPrivate // NULL == pPublic // NULL == pResult // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pPrivate->idCtx // illegal pPublic->idCtx // // ippStsRangeErr ECP_POINT_FELEN(pPublic)idCtx // invalid pPoint->idCtx // invalid pX->idCtx // // ippStsBadArgErr !GFP_IS_BASIC(GFP_PMA(ECP_GFP(pEC))) // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // GFPE_ROOM(pX)!=GFP_FELEN() // // ippStsQuadraticNonResidueErr square of the Y-coordinate of // the pPoint is a quadratic non-residue modulo // // // ippStsNoErr no error // // Parameters: // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // pX Pointer to the X-coordinate of the point on the elliptic curve // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECMakePoint,(const IppsGFpElement* pX, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IPP_BAD_PTR3_RET(pX, pPoint, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !GFP_IS_BASIC(GFP_PMA(ECP_GFP(pEC))), ippStsBadArgErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pX), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( GFPE_ROOM(pX)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); return gfec_MakePoint(pPoint, GFPE_DATA(pX), pEC)? ippStsNoErr : ippStsQuadraticNonResidueErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecmulpoint.c000066400000000000000000000131471470420105600260460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECMulPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECMulPoint // // Purpose: Multiplies a point on an elliptic curve by a scalar // // Returns: Reason: // ippStsNullPtrErr pP == NULL // pQ == NULL // pR == NULL // pEC == NULL // // ippStsContextMatchErr invalid pEC->idCtx // pEC->subgroup == NULL // invalid pP->idCtx // invalid pQ->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pP)!=GFP_FELEN() // ECP_POINT_FELEN(pR)!=GFP_FELEN() // // ippStsBadArgErr pN is negative // pN > MOD_MODULUS(ECP_MONT_R(pEC)) // // ippStsNoErr no error // // Parameters: // pP Pointer to the context of the given point on the elliptic curve // pN Pointer to the Big Number context storing the scalar value // pR Pointer to the context of the resulting elliptic curve point // pEC Pointer to the context of the elliptic curve // pScratchBuffer Pointer to the scratch buffer // // Note: // computes [N]*P, 0 < N < order // *F*/ #if 0 IPPFUN(IppStatus, ippsGFpECMulPoint,(const IppsGFpECPoint* pP, const IppsBigNumState* pN, IppsGFpECPoint* pR, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_BAD_PTR4_RET(pP, pR, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pP), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pR), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pP)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pR)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BAD_PTR1_RET(pN); IPP_BADARG_RET(!BN_VALID_ID(pN), ippStsContextMatchErr ); IPP_BADARG_RET( BN_NEGATIVE(pN), ippStsBadArgErr ); { BNU_CHUNK_T* pScalar = BN_NUMBER(pN); int scalarLen = BN_SIZE(pN); IPP_BADARG_RET(0= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { gfec_MulPoint_nistp256_avx512(pR, pP, pScalar, scalarLen, pEC, pScratchBuffer); return ippStsNoErr; } case cpID_PrimeP384r1: { gfec_MulPoint_nistp384_avx512(pR, pP, pScalar, scalarLen, pEC, pScratchBuffer); return ippStsNoErr; } case cpID_PrimeP521r1: { gfec_MulPoint_nistp521_avx512(pR, pP, pScalar, scalarLen, pEC, pScratchBuffer); return ippStsNoErr; } case cpID_PrimeTPM_SM2: { gfec_MulPoint_sm2_avx512(pR, pP, pScalar, scalarLen, pEC, pScratchBuffer); return ippStsNoErr; } default: /* Go to default implementation below */ break; } } /* no else */ #endif // (_IPP32E >= _IPP32E_K1) gfec_MulPoint(pR, pP, pScalar, scalarLen, pEC, pScratchBuffer); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecnegpoint.c000066400000000000000000000050461470420105600260210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECNegPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECNegPoint // // Purpose: Computes the inverse of a point // // Returns: Reason: // ippStsNullPtrErr pP == NULL // pR == NULL // pEC == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pP->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pP)!=GFP_FELEN() // ECP_POINT_FELEN(pR)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pP Pointer to the context of the first elliptic curve point // pR Pointer to the context of the resulting elliptic curve point // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECNegPoint,(const IppsGFpECPoint* pP, IppsGFpECPoint* pR, IppsGFpECState* pEC)) { IPP_BAD_PTR3_RET(pP, pR, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pP), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pR), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pP)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pR)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); gfec_NegPoint(pR, pP, pEC); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecpoint.c000066400000000000000000000064221470420105600253260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECPointGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECPointGetSize // // Purpose: Gets the size of the IppsGFpECPoint context // // Returns: Reason: // ippStsNullPtrErr pEC == NULL // pSize == NULL // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsNoErr no error // // Parameters: // pEC Pointer to the context of the elliptic curve // pSize Pointer to the buffer size // *F*/ IPPFUN(IppStatus, ippsGFpECPointGetSize,(const IppsGFpECState* pEC, int* pSize)) { IPP_BAD_PTR2_RET(pEC, pSize); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); { int elemLen = GFP_FELEN(GFP_PMA(ECP_GFP(pEC))); *pSize = (Ipp32s)sizeof(IppsGFpECPoint) +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* X */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* Y */ +elemLen*(Ipp32s)sizeof(BNU_CHUNK_T);/* Z */ return ippStsNoErr; } } /*F* // Name: ippsGFpECPointInit // // Purpose: Initializes the context of a point on an elliptic curve // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // // ippStsContextMatchErr invalid pEC->idCtx // // ippStsNoErr no error // // Parameters: // pX, pY Pointers to the X and Y coordinates of a point on the elliptic curve // pPoint Pointer to the IppsGFpECPoint context being initialized // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECPointInit,(const IppsGFpElement* pX, const IppsGFpElement* pY, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pPoint, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); { Ipp8u* ptr = (Ipp8u*)pPoint; int elemLen = GFP_FELEN(GFP_PMA(ECP_GFP(pEC))); ECP_POINT_SET_ID(pPoint); ECP_POINT_FLAGS(pPoint) = 0; ECP_POINT_FELEN(pPoint) = elemLen; ptr += sizeof(IppsGFpECPoint); ECP_POINT_DATA(pPoint) = (BNU_CHUNK_T*)(ptr); if(pX && pY) return ippsGFpECSetPoint(pX, pY, pPoint, pEC); else { gfec_SetPointAtInfinity(pPoint); return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecpointstuff.c000066400000000000000000000076741470420105600264100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // Context: // gfec_IsPointOnCurve() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gsscramble.h" #if ( ECP_PROJECTIVE_COORD == JACOBIAN ) IPP_OWN_DEFN (int, gfec_IsPointOnCurve, (const IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { /* point at infinity does not belong curve */ if( !IS_ECP_FINITE_POINT(pPoint) ) //return 1; return 0; /* test that 0 == R = (Y^2) - (X^3 + A*X*(Z^4) + B*(Z^6)) */ else { int isOnCurve = 0; IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); mod_mul mulF = GFP_METHOD(pGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGFE)->sqr; mod_sub subF = GFP_METHOD(pGFE)->sub; BNU_CHUNK_T* pX = ECP_POINT_X(pPoint); BNU_CHUNK_T* pY = ECP_POINT_Y(pPoint); BNU_CHUNK_T* pZ = ECP_POINT_Z(pPoint); BNU_CHUNK_T* pR = NULL; BNU_CHUNK_T* pT = NULL; BNU_CHUNK_T* pZ4 = NULL; BNU_CHUNK_T* pZ6 = NULL; #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { isOnCurve = gfec_point_on_curve_nistp256_avx512(pPoint, pEC); goto exit; break; } case cpID_PrimeP384r1: { isOnCurve = gfec_point_on_curve_nistp384_avx512(pPoint, pEC); goto exit; break; } case cpID_PrimeP521r1: { isOnCurve = gfec_point_on_curve_nistp521_avx512(pPoint, pEC); goto exit; break; } case cpID_PrimeTPM_SM2: { isOnCurve = gfec_point_on_curve_sm2_avx512(pPoint, pEC); goto exit; break; } default: /* Go to default implementation below */ break; } } #endif // (_IPP32E >= _IPP32E_K1) pR = cpGFpGetPool(1, pGFE); pT = cpGFpGetPool(1, pGFE); sqrF(pR, pY, pGFE); /* R = Y^2 */ sqrF(pT, pX, pGFE); /* T = X^3 */ mulF(pT, pX, pT, pGFE); subF(pR, pR, pT, pGFE); /* R -= T */ if( IS_ECP_AFFINE_POINT(pPoint) ) { mulF(pT, pX, ECP_A(pEC), pGFE); /* T = A*X */ subF(pR, pR, pT, pGFE); /* R -= T */ subF(pR, pR, ECP_B(pEC), pGFE); /* R -= B */ } else { pZ4 = cpGFpGetPool(1, pGFE); pZ6 = cpGFpGetPool(1, pGFE); sqrF(pZ6, pZ, pGFE); /* Z^2 */ sqrF(pZ4, pZ6, pGFE); /* Z^4 */ mulF(pZ6, pZ6, pZ4, pGFE); /* Z^6 */ mulF(pZ4, pZ4, pX, pGFE); /* X*(Z^4) */ mulF(pZ4, pZ4, ECP_A(pEC), pGFE); /* A*X*(Z^4) */ mulF(pZ6, pZ6, ECP_B(pEC), pGFE); /* B*(Z^4) */ subF(pR, pR, pZ4, pGFE); /* R -= A*X*(Z^4) */ subF(pR, pR, pZ6, pGFE); /* R -= B*(Z^6) */ cpGFpReleasePool(2, pGFE); } isOnCurve = GFP_IS_ZERO(pR, GFP_FELEN(pGFE)); cpGFpReleasePool(2, pGFE); #if (_IPP32E >= _IPP32E_K1) exit: #endif // (_IPP32E >= _IPP32E_K1) return isOnCurve; } } #endif cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecprivatekey.c000066400000000000000000000057571470420105600263720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECPrivateKey() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECPrivateKey // // Purpose: Generate random private key // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pPrivate // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pPrivate->idCtx // // ippStsSizeErr BN_ROOM(pPrivate)*BITSIZE(BNU_CHUNK_T)idCtx // pEC->subgroup == NULL // illegal pPrivate->idCtx // illegal pPublic->idCtx // // ippStsInvalidPrivateKey !(0 < pPrivate < order) // // ippStsRangeErr ECP_POINT_FELEN(pPublic)= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { gfec_PubKey_nist256_avx512(pPublic, pS, nsS, pEC, pScratchBuffer); return ippStsNoErr; } case cpID_PrimeP384r1: { gfec_PubKey_nist384_avx512(pPublic, pS, nsS, pEC, pScratchBuffer); return ippStsNoErr; } case cpID_PrimeP521r1: { gfec_PubKey_nist521_avx512(pPublic, pS, nsS, pEC, pScratchBuffer); return ippStsNoErr; } case cpID_PrimeTPM_SM2: { gfec_PubKey_sm2_avx512(pPublic, pS, nsS, pEC, pScratchBuffer); return ippStsNoErr; } default: /* Go to default implementation below */ break; } } /* no else */ #endif // (_IPP32E >= _IPP32E_K1) { gfec_MulBasePoint(pPublic, pS, nsS, pEC, pScratchBuffer); } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecset.c000066400000000000000000000065351470420105600247750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECSet() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECSet // // Purpose: Sets up the parameters of an elliptic curve over a finite field // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pA // NULL == pB // // ippStsContextMatchErr invalid pEC->idCtx // invalid pA->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM(pA)!=GFP_FELEN(pGFE) // GFPE_ROOM(pB)!=GFP_FELEN(pGFE) // // ippStsNoErr no error // // Parameters: // pA Pointer to the coefficient A of the equation defining the elliptic curve // pB Pointer to the coefficient B of the equation defining the elliptic curve // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECSet,(const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpECState* pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BAD_PTR2_RET(pA, pB); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pB), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(ECP_GFP(pEC)); int elemLen = GFP_FELEN(pGFE); IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); IPP_BADARG_RET( GFPE_ROOM(pB)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); /* copy A */ cpGFpElementPad(ECP_A(pEC), elemLen, 0); cpGFpElementCopy(ECP_A(pEC), GFPE_DATA(pA), elemLen); /* and set up A-specific (a==0 or a==-3) if is */ if(GFP_IS_ZERO(ECP_A(pEC), elemLen)) ECP_SPECIFIC(pEC) = ECP_EPID2; cpGFpElementSetChunk(ECP_B(pEC), elemLen, 3); GFP_METHOD(pGFE)->encode(ECP_B(pEC), ECP_B(pEC), pGFE); GFP_METHOD(pGFE)->add(ECP_B(pEC), ECP_A(pEC), ECP_B(pEC), pGFE); if(GFP_IS_ZERO(ECP_B(pEC), elemLen)) ECP_SPECIFIC(pEC) = ECP_STD; /* copy B */ cpGFpElementPad(ECP_B(pEC), elemLen, 0); cpGFpElementCopy(ECP_B(pEC), GFPE_DATA(pB), elemLen); /* and set type of affine infinity representation: // (0,1) if B==0 // (0,0) if B!=0 */ ECP_INFINITY(pEC) = GFP_IS_ZERO(ECP_B(pEC), elemLen); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpoint.c000066400000000000000000000057731470420105600260520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECSetPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPoint // // Purpose: Sets a point on an elliptic curve // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pX == NULL // pY == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // invalid pX->idCtx // invalid pY->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pX)!=GFP_FELEN() // ECP_POINT_FELEN(pY)!=GFP_FELEN() // ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pX, pY Pointers to the X and Y coordinates of a point on the elliptic curve // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECSetPoint,(const IppsGFpElement* pX, const IppsGFpElement* pY, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pPoint, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BAD_PTR2_RET(pX, pY); IPP_BADARG_RET( !GFPE_VALID_ID(pX), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pY), ippStsContextMatchErr ); IPP_BADARG_RET( GFPE_ROOM(pX)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( GFPE_ROOM(pY)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); if(gfec_SetPoint(ECP_POINT_DATA(pPoint), GFPE_DATA(pX), GFPE_DATA(pY), pEC)) ECP_POINT_FLAGS(pPoint) = ECP_AFFINE_POINT | ECP_FINITE_POINT; else ECP_POINT_FLAGS(pPoint) = 0; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointatinf.c000066400000000000000000000040411470420105600270570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECSetPointAtInfinity() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointAtInfinity // // Purpose: Sets a point on an elliptic curve as a point at infinity // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN()!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointAtInfinity,(IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pPoint, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); gfec_SetPointAtInfinity(pPoint); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointhash.c000066400000000000000000000123341470420105600267050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitives. // EC over GF(p) Operations // // Context: // ippsGFpECSetPointHash() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointHash // // Purpose: Constructs a point on an elliptic curve based on the hash of the input message // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pScratchBuffer == NULL // (msgLen && !pMsg) // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // // ippStsBadArgErr !GFP_IS_BASIC(pGFE) // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsQuadraticNonResidueErr square of the Y-coordinate of // the pPoint is a quadratic non-residue modulo // // ippStsLengthErr msgLen<0 // // ippStsNoErr no error // // Parameters: // hdr Header of the input message // pMsg Pointer to the input message // msgLen Length of the input message // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // hashID ID of the hash algorithm used // pScratchBuffer Pointer to the scratch buffer // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointHash,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, IppHashAlgId hashID, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pGFE; /* get algorithm id */ hashID = cpValidHashAlg(hashID); IPP_BADARG_RET(ippHashAlg_Unknown==hashID, ippStsNotSupportedModeErr); /* test message length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); IPP_BAD_PTR3_RET(pPoint, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* pModulus = GFP_MODULUS(pGFE); Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int hashLen = cpHashAlgAttr[hashID].hashSize; BNU_CHUNK_T hashVal[BITS_BNU_CHUNK(IPP_SHA512_DIGEST_BITSIZE)+1]; int hashValLen; IppsHashState hashCtx; ippsHashInit(&hashCtx, hashID); { BNU_CHUNK_T* pPoolElm = cpGFpGetPool(1, pGFE); /* convert hdr => hdrStr */ BNU_CHUNK_T locHdr = (BNU_CHUNK_T)hdr; Ipp8u hdrOctStr[sizeof(hdr/*locHdr*/)]; cpToOctStr_BNU(hdrOctStr, sizeof(hdrOctStr), &locHdr, 1); /* compute md = hash(hrd||msg) */ ippsHashUpdate(hdrOctStr, sizeof(hdrOctStr), &hashCtx); ippsHashUpdate(pMsg, msgLen, &hashCtx); ippsHashFinal(md, &hashCtx); /* convert hash into the integer */ hashValLen = cpFromOctStr_BNU(hashVal, md, hashLen); hashValLen = cpMod_BNU(hashVal, hashValLen, pModulus, elemLen); cpGFpSet(pPoolElm, hashVal, hashValLen, pGFE); if( gfec_MakePoint(pPoint, pPoolElm, pEC)) { /* choose even y-coordinate of the point (see SafeID Specs v2) */ BNU_CHUNK_T* pY = ECP_POINT_Y(pPoint); GFP_METHOD(pGFE)->decode(pPoolElm, pY, pGFE); /* due to P(X,Y,Z=1) just decode Y->y */ if(pPoolElm[0] & 1) cpGFpNeg(pY, pY, pGFE); /* R = [cofactor]R */ if(ECP_SUBGROUP(pEC)) { BNU_CHUNK_T* pCofactor = ECP_COFACTOR(pEC); int cofactorLen = GFP_FELEN(pGFE); if(!GFP_IS_ONE(pCofactor, cofactorLen)) gfec_MulPoint(pPoint, pPoint, pCofactor, cofactorLen, /*0,*/ pEC, pScratchBuffer); } cpGFpReleasePool(1, pGFE); return ippStsNoErr; } } cpGFpReleasePool(1, pGFE); return ippStsQuadraticNonResidueErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointhash_backc.c000066400000000000000000000125001470420105600300230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitives. // EC over GF(p) Operations // // Context: // ippsGFpECSetPointHash() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointHashBackCompatible // // Purpose: Constructs a point on an elliptic curve based on the hash of the input message // This version provide back compatibility with ipp2019update5 and before // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pScratchBuffer == NULL // (msgLen && !pMsg) // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // // ippStsBadArgErr !GFP_IS_BASIC(pGFE) // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsQuadraticNonResidueErr square of the Y-coordinate of // the pPoint is a quadratic non-residue modulo // // ippStsLengthErr msgLen<0 // // ippStsNoErr no error // // Parameters: // hdr Header of the input message // pMsg Pointer to the input message // msgLen Length of the input message // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // hashID ID of the hash algorithm used // pScratchBuffer Pointer to the scratch buffer // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointHashBackCompatible,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, IppHashAlgId hashID, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pGFE; /* get algorithm id */ hashID = cpValidHashAlg(hashID); IPP_BADARG_RET(ippHashAlg_Unknown==hashID, ippStsNotSupportedModeErr); /* test message length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); IPP_BAD_PTR3_RET(pPoint, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* pModulus = GFP_MODULUS(pGFE); Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int hashLen = cpHashAlgAttr[hashID].hashSize; BNU_CHUNK_T hashVal[BITS_BNU_CHUNK(IPP_SHA512_DIGEST_BITSIZE)+1]; int hashValLen; IppsHashState hashCtx; ippsHashInit(&hashCtx, hashID); { BNU_CHUNK_T* pPoolElm = cpGFpGetPool(1, pGFE); /* convert hdr => hdrStr */ BNU_CHUNK_T locHdr = (BNU_CHUNK_T)hdr; Ipp8u hdrOctStr[sizeof(hdr/*locHdr*/)]; cpToOctStr_BNU(hdrOctStr, sizeof(hdrOctStr), &locHdr, 1); /* compute md = hash(hrd||msg) */ ippsHashUpdate(hdrOctStr, sizeof(hdrOctStr), &hashCtx); ippsHashUpdate(pMsg, msgLen, &hashCtx); ippsHashFinal(md, &hashCtx); /* convert hash into the integer */ hashValLen = cpFromOctStr_BNU(hashVal, md, hashLen); hashValLen = cpMod_BNU(hashVal, hashValLen, pModulus, elemLen); cpGFpSet(pPoolElm, hashVal, hashValLen, pGFE); if( gfec_MakePoint(pPoint, pPoolElm, pEC)) { /* set y-coordinate of the point (positive or negative) */ /* because y is in Montgomery domain the code below is not matched to SafeID Specs v2 */ BNU_CHUNK_T* pY = ECP_POINT_Y(pPoint); if(pY[0] & 1) cpGFpNeg(pY, pY, pGFE); /* R = [cofactor]R */ if(ECP_SUBGROUP(pEC)) { BNU_CHUNK_T* pCofactor = ECP_COFACTOR(pEC); int cofactorLen = GFP_FELEN(pGFE); if(!GFP_IS_ONE(pCofactor, cofactorLen)) gfec_MulPoint(pPoint, pPoint, pCofactor, cofactorLen, /*0,*/ pEC, pScratchBuffer); } cpGFpReleasePool(1, pGFE); return ippStsNoErr; } } cpGFpReleasePool(1, pGFE); return ippStsQuadraticNonResidueErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointhash_backc_rmf.c000066400000000000000000000122711470420105600306740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitives. // EC over GF(p) Operations // // Context: // ippsGFpECSetPointHashBackCompatible_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointHashBackCompatible_rmf // // Purpose: Constructs a point on an elliptic curve based on the hash of the input message // This version provide back compatibility with ipp2019update5 and before // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pScratchBuffer == NULL // (msgLen && !pMsg) // pMethod == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // // ippStsBadArgErr !GFP_IS_BASIC(pGFE) // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsQuadraticNonResidueErr square of the Y-coordinate of // the pPoint is a quadratic non-residue modulo // // ippStsLengthErr msgLen<0 // // ippStsNoErr no error // // Parameters: // hdr Header of the input message // pMsg Pointer to the input message // msgLen Length of the input message // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // pMethod Pointer to the hash method // pScratchBuffer Pointer to the scratch buffer // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointHashBackCompatible_rmf,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pGFE; /* test method pointer */ IPP_BAD_PTR1_RET(pMethod); /* test message length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); IPP_BAD_PTR3_RET(pPoint, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* pModulus = GFP_MODULUS(pGFE); Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int hashLen = pMethod->hashLen; BNU_CHUNK_T hashVal[BITS_BNU_CHUNK(IPP_SHA512_DIGEST_BITSIZE)+1]; int hashValLen; IppsHashState_rmf hashCtx; ippsHashInit_rmf(&hashCtx, pMethod); { BNU_CHUNK_T* pPoolElm = cpGFpGetPool(1, pGFE); /* convert hdr => hdrStr */ BNU_CHUNK_T locHdr = (BNU_CHUNK_T)hdr; Ipp8u hdrOctStr[sizeof(hdr/*locHdr*/)]; cpToOctStr_BNU(hdrOctStr, sizeof(hdrOctStr), &locHdr, 1); /* compute md = hash(hrd||msg) */ ippsHashUpdate_rmf(hdrOctStr, sizeof(hdrOctStr), &hashCtx); ippsHashUpdate_rmf(pMsg, msgLen, &hashCtx); ippsHashFinal_rmf(md, &hashCtx); /* convert hash into the integer */ hashValLen = cpFromOctStr_BNU(hashVal, md, hashLen); hashValLen = cpMod_BNU(hashVal, hashValLen, pModulus, elemLen); cpGFpSet(pPoolElm, hashVal, hashValLen, pGFE); if( gfec_MakePoint(pPoint, pPoolElm, pEC)) { /* set y-coordinate of the point (positive or negative) */ /* because y is in Montgomery domain the code below is not matched to SafeID Specs v2 */ BNU_CHUNK_T* pY = ECP_POINT_Y(pPoint); if(pY[0] & 1) cpGFpNeg(pY, pY, pGFE); /* update point if cofactor>1 */ if(ECP_SUBGROUP(pEC)) gfec_MulPoint(pPoint, pPoint, ECP_COFACTOR(pEC), GFP_FELEN(pGFE), /*0,*/ pEC, pScratchBuffer); cpGFpReleasePool(1, pGFE); return ippStsNoErr; } } cpGFpReleasePool(1, pGFE); return ippStsQuadraticNonResidueErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointhash_rmf.c000066400000000000000000000121071470420105600275470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitives. // EC over GF(p) Operations // // Context: // ippsGFpECSetPointHash_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointHash_rmf // // Purpose: Constructs a point on an elliptic curve based on the hash of the input message // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pScratchBuffer == NULL // (msgLen && !pMsg) // pMethod == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // // ippStsBadArgErr !GFP_IS_BASIC(pGFE) // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsQuadraticNonResidueErr square of the Y-coordinate of // the pPoint is a quadratic non-residue modulo // // ippStsLengthErr msgLen<0 // // ippStsNoErr no error // // Parameters: // hdr Header of the input message // pMsg Pointer to the input message // msgLen Length of the input message // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // pMethod Pointer to the hash method // pScratchBuffer Pointer to the scratch buffer // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointHash_rmf,(Ipp32u hdr, const Ipp8u* pMsg, int msgLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pGFE; /* test method pointer */ IPP_BAD_PTR1_RET(pMethod); /* test message length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); IPP_BAD_PTR3_RET(pPoint, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* pModulus = GFP_MODULUS(pGFE); Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int hashLen = pMethod->hashLen; BNU_CHUNK_T hashVal[BITS_BNU_CHUNK(IPP_SHA512_DIGEST_BITSIZE)+1]; int hashValLen; IppsHashState_rmf hashCtx; ippsHashInit_rmf(&hashCtx, pMethod); { BNU_CHUNK_T* pPoolElm = cpGFpGetPool(1, pGFE); /* convert hdr => hdrStr */ BNU_CHUNK_T locHdr = (BNU_CHUNK_T)hdr; Ipp8u hdrOctStr[sizeof(hdr/*locHdr*/)]; cpToOctStr_BNU(hdrOctStr, sizeof(hdrOctStr), &locHdr, 1); /* compute md = hash(hrd||msg) */ ippsHashUpdate_rmf(hdrOctStr, sizeof(hdrOctStr), &hashCtx); ippsHashUpdate_rmf(pMsg, msgLen, &hashCtx); ippsHashFinal_rmf(md, &hashCtx); /* convert hash into the integer */ hashValLen = cpFromOctStr_BNU(hashVal, md, hashLen); hashValLen = cpMod_BNU(hashVal, hashValLen, pModulus, elemLen); cpGFpSet(pPoolElm, hashVal, hashValLen, pGFE); if( gfec_MakePoint(pPoint, pPoolElm, pEC)) { /* choose even y-coordinate of the point (see SafeID Specs v2) */ BNU_CHUNK_T* pY = ECP_POINT_Y(pPoint); GFP_METHOD(pGFE)->decode(pPoolElm, pY, pGFE); /* due to P(X,Y,Z=1) just decode Y->y */ if(pPoolElm[0] & 1) cpGFpNeg(pY, pY, pGFE); /* update point if cofactor>1 */ if(ECP_SUBGROUP(pEC)) gfec_MulPoint(pPoint, pPoint, ECP_COFACTOR(pEC), GFP_FELEN(pGFE), /*0,*/ pEC, pScratchBuffer); cpGFpReleasePool(1, pGFE); return ippStsNoErr; } } cpGFpReleasePool(1, pGFE); return ippStsQuadraticNonResidueErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointoctstring.c000066400000000000000000000060011470420105600277700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECSetPointOctString() // */ #include "gfpec/pcpgfpecessm2.h" #include "gfpec/pcpgfpecstuff.h" /*F* // Name: ippsGFpECSetPointOctString // // Purpose: Converts x||y octstring into a point on EC // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL / pEC == NULL / pStr == NULL // ippStsContextMatchErr pEC, pPoint invalid context // ippStsNotSupportedModeErr pGFE->extdegree > 1 // ippStsSizeErr strLen is not equal to double GFp element // ippStsOutOfRangeErr X or Y from the string exceeds the EC's field modulus or the point does not belong to the EC // ippStsNoErr no errors // // Parameters: // pStr pointer to the string to read from // strLen length of the string // pPoint pointer to output point // pEC EC ctx // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointOctString, (const Ipp8u* pStr, int strLen, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IPP_BAD_PTR3_RET(pPoint, pEC, pStr); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); { gsModEngine* pGFE = pEC->pGF->pGFE; IppsGFpInfo gfi; ippsGFpGetInfo(&gfi, pEC->pGF); { int elemLenBits = gfi.basicGFdegree * gfi.basicElmBitSize; int elemLenBytes = BITS2WORD8_SIZE(elemLenBits); int elemLenChunks = BITS_BNU_CHUNK(elemLenBits); IPP_BADARG_RET(strLen != elemLenBytes * 2, ippStsSizeErr); { IppStatus ret; IppsGFpElement ptX, ptY; cpGFpElementConstruct(&ptX, cpGFpGetPool(1, pGFE), elemLenChunks); cpGFpElementConstruct(&ptY, cpGFpGetPool(1, pGFE), elemLenChunks); ret = ippsGFpSetElementOctString(pStr, elemLenBytes, &ptX, pEC->pGF); if (ippStsNoErr == ret) { pStr += elemLenBytes; ret = ippsGFpSetElementOctString(pStr, elemLenBytes, &ptY, pEC->pGF); } if (ippStsNoErr == ret) { ret = ippsGFpECSetPoint(&ptX, &ptY, pPoint, pEC); } cpGFpReleasePool(2, pGFE); /* release ptX and ptY from the pool */ return ret; } } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointrand.c000066400000000000000000000110371470420105600267050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECSetPointRandom() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointRandom // // Purpose: Sets the coordinates of a point on an elliptic curve to random values // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pScratchBuffer == NULL // // ippStsContextMatchErr invalid pEC->idCtx // NULL == pEC->subgroup // invalid pPoint->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // rndFunc Pesudorandom number generator // pRndParam Pointer to the pseudorandom number generator context // pScratchBuffer Pointer to the scratch buffer // // Note: // Is not a fact that computed point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointRandom,(IppsGFpECPoint* pPoint, IppsGFpECState* pEC, IppBitSupplier rndFunc, void* pRndParam, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pGFE; IPP_BAD_PTR3_RET(pPoint, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); IPP_BAD_PTR2_RET(rndFunc, pRndParam); { int internal_err; if( GFP_IS_BASIC(pGFE) ) { BNU_CHUNK_T* pElm = cpGFpGetPool(1, pGFE); do { /* get random X */ internal_err = NULL==cpGFpRand(pElm, pGFE, rndFunc, pRndParam); } while( !internal_err && !gfec_MakePoint(pPoint, pElm, pEC) ); cpGFpReleasePool(1, pGFE); /* R = [cofactor]R */ if(!internal_err && ECP_SUBGROUP(pEC)) { BNU_CHUNK_T* pCofactor = ECP_COFACTOR(pEC); int cofactorLen = GFP_FELEN(pGFE); if(!GFP_IS_ONE(pCofactor, cofactorLen)) gfec_MulPoint(pPoint, pPoint, ECP_COFACTOR(pEC), GFP_FELEN(pGFE), /*0,*/ pEC, pScratchBuffer); } } else { IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); { /* number of bits being generated */ int generatedBits = ECP_ORDBITSIZE(pEC) + GFP_RAND_ADD_BITS; int generatedLen = BITS_BNU_CHUNK(generatedBits); /* allocate random exponent */ int poolElements = (generatedLen + GFP_PELEN(pGFE) -1) / GFP_PELEN(pGFE); BNU_CHUNK_T* pExp = cpGFpGetPool(poolElements, pGFE); /* setup copy of the base point */ IppsGFpECPoint G; cpEcGFpInitPoint(&G, ECP_G(pEC),ECP_AFFINE_POINT|ECP_FINITE_POINT, pEC); /* get random bits */ internal_err = ippStsNoErr != rndFunc((Ipp32u*)pExp, generatedBits, pRndParam); if(!internal_err) { /* reduce with respect to order value */ int nsE = cpMod_BNU(pExp, generatedLen, MOD_MODULUS(ECP_MONT_R(pEC)), BITS_BNU_CHUNK(ECP_ORDBITSIZE(pEC))); /* compute random point */ gfec_MulPoint(pPoint, &G, pExp, nsE, pEC, pScratchBuffer); } cpGFpReleasePool(poolElements, pGFE); } } return internal_err? ippStsErr : ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetpointreg.c000066400000000000000000000072361470420105600265440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECSetPointRegular() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECSetPointRegular // // Purpose: Sets a point with Big Number coordinates // // Returns: Reason: // ippStsNullPtrErr pPoint == NULL // pEC == NULL // pX == NULL // pY == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pPoint->idCtx // invalid pX->idCtx // invalid pY->idCtx // // ippStsOutOfRangeErr GFP_FELEN() < pX <= 0 // GFP_FELEN() < pY <= 0 // ECP_POINT_FELEN(pPoint)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pX, pY Pointers to the X and Y coordinates of a point on the elliptic curve // pPoint Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // *F*/ IPPFUN(IppStatus, ippsGFpECSetPointRegular,(const IppsBigNumState* pX, const IppsBigNumState* pY, IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) { IPP_BAD_PTR2_RET(pPoint, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pPoint), ippStsContextMatchErr ); IPP_BAD_PTR2_RET(pX, pY); IPP_BADARG_RET( !BN_VALID_ID(pX), ippStsContextMatchErr ); IPP_BADARG_RET( !BN_VALID_ID(pY), ippStsContextMatchErr ); IPP_BADARG_RET( !BN_POSITIVE(pX), ippStsOutOfRangeErr); IPP_BADARG_RET( !BN_POSITIVE(pY), ippStsOutOfRangeErr); { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr ) IPP_BADARG_RET( BN_SIZE(pX) > elemLen, ippStsOutOfRangeErr); IPP_BADARG_RET( BN_SIZE(pY) > elemLen, ippStsOutOfRangeErr); IPP_BADARG_RET( ECP_POINT_FELEN(pPoint)!=elemLen, ippStsOutOfRangeErr); { BNU_CHUNK_T* pointX = ECP_POINT_X(pPoint); BNU_CHUNK_T* pointY = ECP_POINT_Y(pPoint); BNU_CHUNK_T* pointZ = ECP_POINT_Z(pPoint); cpGFpElementCopyPad(pointX, elemLen, BN_NUMBER(pX), BN_SIZE(pX)); cpGFpElementCopyPad(pointY, elemLen, BN_NUMBER(pY), BN_SIZE(pY)); cpGFpElementCopy(pointZ, MOD_MNT_R(pGFE), elemLen); if( cpGFpSet(pointX, pointX, elemLen, pGFE) && cpGFpSet(pointY, pointY, elemLen, pGFE) ) ECP_POINT_FLAGS(pPoint) = ECP_AFFINE_POINT | ECP_FINITE_POINT; else gfec_SetPointAtInfinity(pPoint); return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsetsubgroup.c000066400000000000000000000110301470420105600265460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECSetSubgroup() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECSetSubgroup // // Purpose: Sets up the parameters defining an elliptic curve points subgroup. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pX // NULL == pY // NULL == pOrder // NULL == pCofactor // // ippStsContextMatchErr invalid pEC->idCtx // invalid pX->idCtx // invalid pY->idCtx // invalid pOrder->idCtx // invalid pCofactor->idCtx // // ippStsBadArgErr pOrder <= 0 // pCofactor <= 0 // // ippStsOutOfRangeErr GFPE_ROOM(pX)!=GFP_FELEN(pGFE) // GFPE_ROOM(pY)!=GFP_FELEN(pGFE) // // ippStsRangeErr orderBitSize>maxOrderBits // cofactorBitSize>elemLen*BITSIZE(BNU_CHUNK_T) // // ippStsNoErr no error // // Parameters: // pX, pY Pointers to the X and Y coordinates of the base point of the elliptic curve // pOrder Pointer to the big number context storing the order of the base point. // pCofactor Pointer to the big number context storing the cofactor. // pEC Pointer to the context of the elliptic curve. // *F*/ IPPFUN(IppStatus, ippsGFpECSetSubgroup,(const IppsGFpElement* pX, const IppsGFpElement* pY, const IppsBigNumState* pOrder, const IppsBigNumState* pCofactor, IppsGFpECState* pEC)) { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BAD_PTR2_RET(pX, pY); IPP_BADARG_RET( !GFPE_VALID_ID(pX), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pY), ippStsContextMatchErr ); IPP_BAD_PTR2_RET(pOrder, pCofactor); IPP_BADARG_RET(!BN_VALID_ID(pOrder), ippStsContextMatchErr); IPP_BADARG_RET(BN_SIGN(pOrder)!= IppsBigNumPOS, ippStsBadArgErr); IPP_BADARG_RET(!BN_VALID_ID(pCofactor), ippStsContextMatchErr); IPP_BADARG_RET(BN_SIGN(pCofactor)!= IppsBigNumPOS, ippStsBadArgErr); { gsModEngine* pGFE = GFP_PMA(ECP_GFP(pEC)); int elemLen = GFP_FELEN(pGFE); IPP_BADARG_RET( GFPE_ROOM(pX)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); IPP_BADARG_RET( GFPE_ROOM(pY)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); gfec_SetPoint(ECP_G(pEC), GFPE_DATA(pX), GFPE_DATA(pY), pEC); { int maxOrderBits = 1+ cpGFpBasicDegreeExtension(pGFE) * GFP_FEBITLEN(cpGFpBasic(pGFE)); BNU_CHUNK_T* pOrderData = BN_NUMBER(pOrder); int orderLen= BN_SIZE(pOrder); int orderBitSize = BITSIZE_BNU(pOrderData, orderLen); IPP_BADARG_RET(orderBitSize>maxOrderBits, ippStsRangeErr) /* set actual size of order and re-init engine */ ECP_ORDBITSIZE(pEC) = orderBitSize; gsModEngineInit(ECP_MONT_R(pEC),(Ipp32u*)pOrderData, orderBitSize, MONT_DEFAULT_POOL_LENGTH, gsModArithMont()); } { BNU_CHUNK_T* pCofactorData = BN_NUMBER(pCofactor); int cofactorLen= BN_SIZE(pCofactor); int cofactorBitSize = BITSIZE_BNU(pCofactorData, cofactorLen); IPP_BADARG_RET(cofactorBitSize>elemLen*BITSIZE(BNU_CHUNK_T), ippStsRangeErr) COPY_BNU(ECP_COFACTOR(pEC), pCofactorData, cofactorLen); } ECP_SUBGROUP(pEC) = 1; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsigndsa.c000066400000000000000000000222051470420105600256220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECSignDSA() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpgfpstuff.h" /*F* // Name: ippsGFpECSignDSA // // Purpose: DSA Signature Generation. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pMsgDigest // NULL == pRegPrivate // NULL == pEphPrivate // NULL == pSignR // NULL == pSignS // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pMsgDigest->idCtx // illegal pRegPrivate->idCtx // illegal pEphPrivate->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsInvalidPrivateKey 0 >= RegPrivate // RegPrivate >= order // // 0 >= EphPrivate // EphPrivate >= order // // ippStsMessageErr MsgDigest >= order // MsgDigest < 0 // // ippStsRangeErr not enough room for: // signR // signS // // ippStsEphemeralKeyErr (0==signR) || (0==signS) // // ippStsNotSupportedModeErr pGFE->extdegree > 1 // // // ippStsNoErr no errors // // Parameters: // pMsgDigest pointer to the message representative to be signed // pRegPrivate pointer to the regular private key // pEphPrivate pointer to the ephemeral private key // pSignR,pSignS pointer to the signature // pEC pointer to the EC context // pScratchBuffer pointer to buffer (1 mul_point operation) // *F*/ IPPFUN(IppStatus, ippsGFpECSignDSA,(const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IppsGFpState* pGF; gsModEngine* pMontP; /* EC context and buffer */ IPP_BAD_PTR2_RET(pEC, pScratchBuffer); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); pGF = ECP_GFP(pEC); pMontP = GFP_PMA(pGF); IPP_BADARG_RET(1= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { sts = gfec_SignDSA_nistp256_avx512(pMsgDigest, pRegPrivate, pEphPrivate, pSignR, pSignS, pEC, pScratchBuffer); goto exit; break; } case cpID_PrimeP384r1: { sts = gfec_SignDSA_nistp384_avx512(pMsgDigest, pRegPrivate, pEphPrivate, pSignR, pSignS, pEC, pScratchBuffer); goto exit; break; } case cpID_PrimeP521r1: { sts = gfec_SignDSA_nistp521_avx512(pMsgDigest, pRegPrivate, pEphPrivate, pSignR, pSignS, pEC, pScratchBuffer); goto exit; break; } default: /* Go to default implementation below */ break; } } /* no else */ #endif // (_IPP32E >= _IPP32E_K1) { int elmLen = GFP_FELEN(pMontP); int ns; /* compute ephemeral public key */ IppsGFpECPoint ephPublic; cpEcGFpInitPoint(&ephPublic, cpEcGFpGetPool(1, pEC), 0, pEC); gfec_MulBasePoint(&ephPublic, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate), pEC, pScratchBuffer); /* // signR = int(ephPublic.x) (mod order) */ { BNU_CHUNK_T* buffer = gsModPoolAlloc(pMontP, 1); IPP_BAD_PTR1_RET(buffer); // buffer can be NULL, stop processing gfec_GetPoint(buffer, NULL, &ephPublic, pEC); GFP_METHOD(pMontP)->decode(buffer, buffer, pMontP); ns = cpMod_BNU(buffer, elmLen, pOrder, ordLen); cpGFpElementCopyPad(dataC, ordLen, buffer, ns); gsModPoolFree(pMontP, 1); } cpEcGFpReleasePool(1, pEC); if(!GFP_IS_ZERO(dataC, ordLen)) { /* // signS = (1/ephPrivate)*(pMsgDigest + private*signR) (mod order) */ /* copy and expand message is being signed and reduce just in case */ ZEXPAND_COPY_BNU(buffF, ordLen, pMsgData, msgLen); cpModSub_BNU(buffF, buffF, pOrder, pOrder, ordLen, buffT); /* private representation in Montgomery domain */ ZEXPAND_COPY_BNU(dataD, ordLen, pPriData, priLen); GFP_METHOD(pMontR)->encode(dataD, dataD, pMontR); /* (private*signX) in regular domain */ GFP_METHOD(pMontR)->mul(dataD, dataD, dataC, pMontR); /* pMsgDigest + private*signX */ cpModAdd_BNU(dataD, dataD, buffF, pOrder, ordLen, buffT); if(!GFP_IS_ZERO(dataD, ordLen)) { /* (1/ephPrivate) in Montgomery domain */ ZEXPAND_COPY_BNU(buffT, ordLen, pEphData, ephLen); gs_mont_inv(buffT, buffT, pMontR, alm_mont_inv_ct); /* (1/ephPrivate)*(pMsgDigest + private*signS) */ GFP_METHOD(pMontR)->mul(dataD, dataD, buffT, pMontR); /* signR */ ns = ordLen; FIX_BNU(dataC, ns); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = ns; /* signS */ ns = ordLen; FIX_BNU(dataD, ns); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = ns; sts = ippStsNoErr; } } } #if (_IPP32E >= _IPP32E_K1) exit: #endif /* clear ephemeral private key */ cpBN_zero(pEphPrivate); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsignnr.c000066400000000000000000000167351470420105600255050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECSignNR() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECSignNR // // Purpose: NR Signature Generation. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pMsgDigest // NULL == pRegPrivate // NULL == pEphPrivate // NULL == pSignR // NULL == pSignS // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pMsgDigest->idCtx // illegal pRegPrivate->idCtx // illegal pEphPrivate->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsInvalidPrivateKey 0 >= RegPrivate // RegPrivate >= order // // 0 >= EphPrivate // EphPrivate >= order // // ippStsMessageErr pMsgDigest < 0 // pMsgDigest >= order // // ippStsRangeErr not enough room for: // signC // signD // // ippStsEphemeralKeyErr (0==signR) || (0==signS) // // ippStsNotSupportedModeErr 1decode(buffer, buffer, pMontP); ns = cpMod_BNU(buffer, elmLen, pOrder, ordLen); cpGFpElementCopyPad(dataC, ordLen, buffer, ns); gsModPoolFree(pMontP, 1); } cpEcGFpReleasePool(1, pEC); /* C = (ephPublic.x + msg) mod order */ ZEXPAND_COPY_BNU(buffF, ordLen, pMsgData, msgLen); cpModAdd_BNU(dataC, dataC, buffF, pOrder, ordLen, dataD); if(!GFP_IS_ZERO(dataC, ordLen)) { /* signS = (eph_private - private*signR) (mod order) */ ZEXPAND_COPY_BNU(dataD, ordLen, pPriData, priLen); GFP_METHOD(pMontR)->encode(dataD, dataD, pMontR); GFP_METHOD(pMontR)->mul(dataD, dataD, dataC, pMontR); ZEXPAND_COPY_BNU(buffF, ordLen, pEphData, ephLen); cpModSub_BNU(dataD, buffF, dataD, pOrder, ordLen, buffT); /* signR */ ns = ordLen; FIX_BNU(dataC, ns); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = ns; /* signS */ ns = ordLen; FIX_BNU(dataD, ns); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = ns; sts = ippStsNoErr; } /* clear ephemeral private key */ cpBN_zero(pEphPrivate); return sts; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecsignsm2.c000066400000000000000000000214231470420105600255550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECSignSM2() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECSignSM2 // // Purpose: SM2 Signature Generation. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pMsgDigest // NULL == pRegPrivate // NULL == pEphPrivate // NULL == pSignR // NULL == pSignS // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pMsgDigest->idCtx // illegal pRegPrivate->idCtx // illegal pEphPrivate->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsInvalidPrivateKey (1 + regPrivate) >= order // // ippStsMessageErr MsgDigest >= order // MsgDigest < 0 // // ippStsRangeErr not enough room for: // signR // signS // // ippStsEphemeralKeyErr (signR + ephPrivate) == order // (0==signR) || (0==signS) // // ippStsNotSupportedModeErr 1= _IPP32E_K1) // if (IsFeatureEnabled(ippCPUID_AVX512IFMA) && ECP_MODULUS_ID(pEC) == cpID_PrimeTPM_SM2) { // sts = gfec_Sign_sm2_avx512(pMsgDigest, pRegPrivate, pEphPrivate, pSignR, pSignS, pEC, pScratchBuffer); // goto exit; // } /* no else */ // #endif // (_IPP32E >= _IPP32E_K1) { int elmLen = GFP_FELEN(pMontP); int ns; /* compute ephemeral public key */ IppsGFpECPoint ephPublic; cpEcGFpInitPoint(&ephPublic, cpEcGFpGetPool(1, pEC), 0, pEC); gfec_MulBasePoint(&ephPublic, pEphData, ephLen, pEC, pScratchBuffer); /* extract X component: ephPublicX = (ephPublic.x) mod order */ { BNU_CHUNK_T* buffer = gsModPoolAlloc(pMontP, 1); IPP_BAD_PTR1_RET(buffer); // buffer can be NULL, stop processing gfec_GetPoint(buffer, NULL, &ephPublic, pEC); GFP_METHOD(pMontP)->decode(buffer, buffer, pMontP); ns = cpMod_BNU(buffer, elmLen, pOrder, ordLen); cpGFpElementCopyPad(dataR, ordLen, buffer, ns); gsModPoolFree(pMontP, 1); } cpEcGFpReleasePool(1, pEC); /* compute R signature component: r = (msg + ephPublic.X) mod order */ ZEXPAND_COPY_BNU(buffS, ordLen, pMsgData, msgLen); cpModSub_BNU(buffS, buffS, pOrder, pOrder, ordLen, buffR); cpModAdd_BNU(dataR, dataR, buffS, pOrder, ordLen, buffR); /* t = (r+ephPrivate) mod order */ ZEXPAND_COPY_BNU(buffR,ordLen, pEphData, ephLen); cpModAdd_BNU(buffR, buffR, dataR, pOrder, ordLen, buffS); /* check if r!=0 and t!=0 */ if(!GFP_IS_ZERO(dataR, ordLen) && !GFP_IS_ZERO(buffR, ordLen)) { /* S = (1+regPrivate)^1 *(ephPrivate-r*regPrivate) mod order */ ZEXPAND_COPY_BNU(buffS, ordLen, pPriData, priLen); GFP_METHOD(pMontR)->encode(buffS, buffS, pMontR); /* mont(regPrivate) */ GFP_METHOD(pMontR)->mul(buffS, buffS, dataR, pMontR); /* r*mont(regPrivate) */ ZEXPAND_COPY_BNU(buffR, ordLen, pEphData, ephLen); cpModSub_BNU(buffR, buffR, buffS, pOrder, ordLen, buffS); /* ephPrivate-r*mont(regPrivate) */ gs_mont_inv(dataS, dataS, pMontR, alm_mont_inv_ct); /* 1/(1+regPrivate) */ GFP_METHOD(pMontR)->mul(dataS, dataS, buffR, pMontR); if( !GFP_IS_ZERO(dataS, ordLen)) { /* signR */ ns = ordLen; FIX_BNU(dataR, ns); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = ns; /* signS */ ns = ordLen; FIX_BNU(dataS, ns); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = ns; sts = ippStsNoErr; } } } // Optimization is disabled due to a bug // #if (_IPP32E >= _IPP32E_K1) // exit: // #endif /* clear ephemeral private key */ cpBN_zero(pEphPrivate); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecstuff.h000066400000000000000000000534401470420105600253330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Internal EC over GF(p^m) basic Definitions & Function Prototypes // // */ #if !defined(_CP_ECGFP_H_) #define _CP_ECGFP_H_ #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcpmask_ct.h" #define _LEGACY_ECCP_SUPPORT_ /* // EC over GF(p) Point context */ typedef struct _cpGFpECPoint { Ipp32u idCtx; /* EC Point identifier */ int flags; /* flags: affine */ int elementSize; /* size of each coordinate */ BNU_CHUNK_T* pData; /* coordinate X, Y, Z */ } cpGFPECPoint; /* // Content Access Macros */ #define ECP_POINT_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxGFPPoint ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define ECP_POINT_FLAGS(ctx) ((ctx)->flags) #define ECP_POINT_FELEN(ctx) ((ctx)->elementSize) #define ECP_POINT_DATA(ctx) ((ctx)->pData) #define ECP_POINT_X(ctx) ((ctx)->pData) #define ECP_POINT_Y(ctx) ((ctx)->pData+(ctx)->elementSize) #define ECP_POINT_Z(ctx) ((ctx)->pData+(ctx)->elementSize*2) #define ECP_POINT_VALID_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR(ctx)) == (Ipp32u)idCtxGFPPoint) /* point flags */ #define ECP_AFFINE_POINT (1) #define ECP_FINITE_POINT (2) #define IS_ECP_AFFINE_POINT(ctx) (ECP_POINT_FLAGS((ctx))&ECP_AFFINE_POINT) #define SET_ECP_AFFINE_POINT(ctx) (ECP_POINT_FLAGS((ctx))|ECP_AFFINE_POINT) #define SET_ECP_PROJECTIVE_POINT(ctx) (ECP_POINT_FLAGS((ctx))&~ECP_AFFINE_POINT) #define IS_ECP_FINITE_POINT(ctx) (ECP_POINT_FLAGS((ctx))&ECP_FINITE_POINT) #define SET_ECP_FINITE_POINT(ctx) (ECP_POINT_FLAGS((ctx))|ECP_FINITE_POINT) #define SET_ECP_INFINITE_POINT(ctx) (ECP_POINT_FLAGS((ctx))&~ECP_FINITE_POINT) /* // define using projective coordinates */ #define JACOBIAN (0) #define HOMOGENEOUS (1) #define ECP_PROJECTIVE_COORD JACOBIAN //#define ECP_PROJECTIVE_COORD HOMOGENEOUS #if (ECP_PROJECTIVE_COORD != JACOBIAN && ECP_PROJECTIVE_COORD != HOMOGENEOUS) #error ECP_PROJECTIVE_COORD should be either JACOBIAN or HOMOGENEOUS type #endif /* // pre-computed Base Point descriptor */ IPP_OWN_FUNPTR (void, selectAP, (BNU_CHUNK_T* pAP, const BNU_CHUNK_T* pAPtbl, int index)) typedef struct _cpPrecompAP { int w; /* scalar's window bitsize */ selectAP select_affine_point; /* get affine point function */ const BNU_CHUNK_T* pTbl; /* pre-computed table */ } cpPrecompAP; /* EC over GF(p) context */ typedef struct _cpGFpEC { Ipp32u idCtx; /* EC identifier */ cpModulusID idModulus; /* Modulus type */ IppsGFpState* pGF; /* arbitrary GF(p^d)*/ int subgroup; /* set up subgroup */ int elementSize; /* length of EC point */ int orderBitSize; /* base_point order bitsize */ BNU_CHUNK_T* pA; /* EC parameter A */ BNU_CHUNK_T* pB; /* B */ BNU_CHUNK_T* pG; /* base_point */ BNU_CHUNK_T* cofactor; /* cofactor = #E/base_point order */ int parmAspc; /* NIST's, EPIDv2.0 A-parameter specific */ int infinity; /* 0/1 if B !=0/==0 */ const cpPrecompAP* pBaseTbl; /* address of pre-computed [n]G tabble */ gsModEngine* pMontR; /* EC order montgomery engine */ BNU_CHUNK_T* pPool; /* pool of points */ #if defined(_LEGACY_ECCP_SUPPORT_) BNU_CHUNK_T* pPublic; /* regular public key */ BNU_CHUNK_T* pPublicE; /* ephemeral public key */ BNU_CHUNK_T* pPrivat; /* regular private key */ BNU_CHUNK_T* pPrivatE; /* ephemeral private key */ BNU_CHUNK_T* pBuffer; /* pointer to scaratch buffer (for legacy ECCP only) */ #endif } cpGFPEC; #define ECGFP_ALIGNMENT ((int)(sizeof(void*))) /* Local definitions */ #define EC_POOL_SIZE (10) /* num of points into the pool */ #define EC_MONT_POOL_SIZE (4) /* num of temp values for modular arithmetic */ #define ECP_SET_ID(pCtx) ((pCtx)->idCtx = (Ipp32u)idCtxGFPEC ^ (Ipp32u)IPP_UINT_PTR(pCtx)) #define ECP_MODULUS_ID(pCtx) ((pCtx)->idModulus) #define ECP_GFP(pCtx) ((pCtx)->pGF) #define ECP_SUBGROUP(pCtx) ((pCtx)->subgroup) #define ECP_POINTLEN(pCtx) ((pCtx)->elementSize) #define ECP_ORDBITSIZE(pCtx) ((pCtx)->orderBitSize) #define ECP_COFACTOR(pCtx) ((pCtx)->cofactor) #define ECP_SPECIFIC(pCtx) ((pCtx)->parmAspc) #define ECP_INFINITY(pCtx) ((pCtx)->infinity) #define ECP_A(pCtx) ((pCtx)->pA) #define ECP_B(pCtx) ((pCtx)->pB) #define ECP_G(pCtx) ((pCtx)->pG) #define ECP_PREMULBP(pCtx) ((pCtx)->pBaseTbl) #define ECP_MONT_R(pCtx) ((pCtx)->pMontR) #define ECP_POOL(pCtx) ((pCtx)->pPool) #if defined(_LEGACY_ECCP_SUPPORT_) #define ECP_PUBLIC(pCtx) ((pCtx)->pPublic) #define ECP_PUBLIC_E(pCtx) ((pCtx)->pPublicE) #define ECP_PRIVAT(pCtx) ((pCtx)->pPrivat) #define ECP_PRIVAT_E(pCtx) ((pCtx)->pPrivatE) #define ECP_SBUFFER(pCtx) ((pCtx)->pBuffer) #endif #define VALID_ECP_ID(pCtx) ((((pCtx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((pCtx))) == (Ipp32u)idCtxGFPEC) /* EC curve specific (a-parameter) */ #define ECP_Acom (0) /* common case */ #define ECP_Ami3 (1) /* a=-3 NIST's and SM2 curve */ #define ECP_Aeq0 (2) /* a=0 EPIDv2.0 curve */ #define ECP_ARB ECP_Acom #define ECP_STD ECP_Ami3 #define ECP_EPID2 ECP_Aeq0 /* std ec pre-computed tables */ #define gfpec_precom_nistP192r1_fun OWNAPI(gfpec_precom_nistP192r1_fun) #define gfpec_precom_nistP224r1_fun OWNAPI(gfpec_precom_nistP224r1_fun) #define gfpec_precom_nistP256r1_fun OWNAPI(gfpec_precom_nistP256r1_fun) #define gfpec_precom_nistP256r1_radix52_fun OWNAPI(gfpec_precom_nistP256r1_radix52_fun) #define gfpec_precom_nistP384r1_fun OWNAPI(gfpec_precom_nistP384r1_fun) #define gfpec_precom_nistP384r1_radix52_fun OWNAPI(gfpec_precom_nistP384r1_radix52_fun) #define gfpec_precom_nistP521r1_fun OWNAPI(gfpec_precom_nistP521r1_fun) #define gfpec_precom_nistP521r1_radix52_fun OWNAPI(gfpec_precom_nistP521r1_radix52_fun) #define gfpec_precom_sm2_fun OWNAPI(gfpec_precom_sm2_fun) #define gfpec_precom_sm2_radix52_fun OWNAPI(gfpec_precom_sm2_radix52_fun) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP192r1_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP224r1_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP256r1_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP256r1_radix52_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP384r1_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP384r1_radix52_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP521r1_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_nistP521r1_radix52_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_sm2_fun, (void)) IPP_OWN_DECL (const cpPrecompAP*, gfpec_precom_sm2_radix52_fun, (void)) /* // get/release n points from/to the pool */ __IPPCP_INLINE BNU_CHUNK_T* cpEcGFpGetPool(int n, IppsGFpECState* pEC) { BNU_CHUNK_T* pPool = ECP_POOL(pEC); ECP_POOL(pEC) += n*GFP_FELEN(GFP_PMA(ECP_GFP(pEC)))*3; return pPool; } __IPPCP_INLINE void cpEcGFpReleasePool(int n, IppsGFpECState* pEC) { int chunk_size = n*GFP_FELEN(GFP_PMA(ECP_GFP(pEC)))*3; ECP_POOL(pEC) -= chunk_size; // Clean the pool for the security reasons // (intermediate sensitive data may be stored here) ZEXPAND_BNU(ECP_POOL(pEC), 0, chunk_size); } __IPPCP_INLINE IppsGFpECPoint* cpEcGFpInitPoint(IppsGFpECPoint* pPoint, BNU_CHUNK_T* pData, int flags, const IppsGFpECState* pEC) { ECP_POINT_SET_ID(pPoint); ECP_POINT_FLAGS(pPoint) = flags; ECP_POINT_FELEN(pPoint) = GFP_FELEN(GFP_PMA(ECP_GFP(pEC))); ECP_POINT_DATA(pPoint) = pData; return pPoint; } /* copy one point into another */ __IPPCP_INLINE IppsGFpECPoint* gfec_CopyPoint(IppsGFpECPoint* pPointR, const IppsGFpECPoint* pPointA, int elemLen) { cpGFpElementCopy(ECP_POINT_DATA(pPointR), ECP_POINT_DATA(pPointA), 3*elemLen); ECP_POINT_FLAGS(pPointR) = ECP_POINT_FLAGS(pPointA); return pPointR; } __IPPCP_INLINE IppsGFpECPoint* gfec_SetPointAtInfinity(IppsGFpECPoint* pPoint) { int elemLen = ECP_POINT_FELEN(pPoint); cpGFpElementPad(ECP_POINT_X(pPoint), elemLen, 0); cpGFpElementPad(ECP_POINT_Y(pPoint), elemLen, 0); cpGFpElementPad(ECP_POINT_Z(pPoint), elemLen, 0); ECP_POINT_FLAGS(pPoint) = 0; return pPoint; } /* // test infinity: // IsProjectivePointAtInfinity */ __IPPCP_INLINE int gfec_IsPointAtInfinity(const IppsGFpECPoint* pPoint) { return GFP_IS_ZERO( ECP_POINT_Z(pPoint), ECP_POINT_FELEN(pPoint)); } /* signed encode */ __IPPCP_INLINE void booth_recode(Ipp8u* sign, Ipp8u* digit, Ipp8u in, int w) { Ipp8u s = (Ipp8u)(~((in >> w) - 1)); int d = (1 << (w+1)) - in - 1; d = (d & s) | (in & ~s); d = (d >> 1) + (d & 1); *sign = s & 1; *digit = (Ipp8u)d; } #define gfec_point_add OWNAPI(gfec_point_add) #define gfec_affine_point_add OWNAPI(gfec_affine_point_add) #define gfec_point_double OWNAPI(gfec_point_double) #define gfec_point_mul OWNAPI(gfec_point_mul) #define gfec_point_prod OWNAPI(gfec_point_prod) #define gfec_base_point_mul OWNAPI(gfec_base_point_mul) #define setupTable OWNAPI(setupTable) IPP_OWN_DECL (void, gfec_point_add, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, const BNU_CHUNK_T* pQdata, IppsGFpECState* pEC)) IPP_OWN_DECL (void, gfec_affine_point_add, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, const BNU_CHUNK_T* pAdata, IppsGFpECState* pEC)) IPP_OWN_DECL (void, gfec_point_double, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, IppsGFpECState* pEC)) IPP_OWN_DECL (void, gfec_point_mul, (BNU_CHUNK_T* pRdata, const BNU_CHUNK_T* pPdata, const Ipp8u* pScalar8, int scalarBitSize, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (void, gfec_point_prod, (BNU_CHUNK_T* pointR, const BNU_CHUNK_T* pointA, const Ipp8u* pScalarA, const BNU_CHUNK_T* pointB, const Ipp8u* pScalarB, int scalarBitSize, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (void, gfec_base_point_mul, (BNU_CHUNK_T* pRdata, const Ipp8u* pScalarB, int scalarBitSize, IppsGFpECState* pEC)) IPP_OWN_DECL (void, setupTable, (BNU_CHUNK_T* pTbl, const BNU_CHUNK_T* pPdata, IppsGFpECState* pEC)) /* size of context */ #define cpGFpECGetSize OWNAPI(cpGFpECGetSize) IPP_OWN_DECL (int, cpGFpECGetSize, (int deg, int basicElmBitSize)) /* point operations */ #define gfec_GetPoint OWNAPI(gfec_GetPoint) #define gfec_SetPoint OWNAPI(gfec_SetPoint) #define gfec_MakePoint OWNAPI(gfec_MakePoint) #define gfec_ComparePoint OWNAPI(gfec_ComparePoint) #define gfec_IsPointOnCurve OWNAPI(gfec_IsPointOnCurve) IPP_OWN_DECL (int, gfec_GetPoint, (BNU_CHUNK_T* pX, BNU_CHUNK_T* pY, const IppsGFpECPoint* pPoint, IppsGFpECState* pEC)) IPP_OWN_DECL (int, gfec_SetPoint, (BNU_CHUNK_T* pP, const BNU_CHUNK_T* pX, const BNU_CHUNK_T* pY, IppsGFpECState* pEC)) IPP_OWN_DECL (int, gfec_MakePoint, (IppsGFpECPoint* pPoint, const BNU_CHUNK_T* pElm, IppsGFpECState* pEC)) IPP_OWN_DECL (int, gfec_ComparePoint, (const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) IPP_OWN_DECL (int, gfec_IsPointOnCurve, (const IppsGFpECPoint* pP, IppsGFpECState* pEC)) __IPPCP_INLINE IppsGFpECPoint* gfec_DblPoint(IppsGFpECPoint* pR, const IppsGFpECPoint* pP, IppsGFpECState* pEC) { gfec_point_double(ECP_POINT_X(pR), ECP_POINT_X(pP), pEC); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR)? 0 : ECP_FINITE_POINT; return pR; } __IPPCP_INLINE IppsGFpECPoint* gfec_AddPoint(IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC) { gfec_point_add(ECP_POINT_X(pR), ECP_POINT_X(pP), ECP_POINT_X(pQ), pEC); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR)? 0 : ECP_FINITE_POINT; return pR; } #define gfec_NegPoint OWNAPI(gfec_NegPoint) #define gfec_MulPoint OWNAPI(gfec_MulPoint) #define gfec_MulBasePoint OWNAPI(gfec_MulBasePoint) /* #define gfec_PointProduct OWNAPI(gfec_PointProduct) */ #define gfec_BasePointProduct OWNAPI(gfec_BasePointProduct) #define p192r1_select_ap_w7 OWNAPI(p192r1_select_ap_w7) #define p224r1_select_ap_w7 OWNAPI(p224r1_select_ap_w7) #define p256r1_select_ap_w7 OWNAPI(p256r1_select_ap_w7) #define p384r1_select_ap_w5 OWNAPI(p384r1_select_ap_w5) #define p521r1_select_ap_w5 OWNAPI(p521r1_select_ap_w5) IPP_OWN_DECL (IppsGFpECPoint*, gfec_NegPoint, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, IppsGFpECState* pEC)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_MulPoint, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_MulBasePoint, (IppsGFpECPoint* pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* IPP_OWN_DECL (IppsGFpECPoint*, gfec_PointProduct, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalarP, int scalarPlen, const IppsGFpECPoint* pQ, const BNU_CHUNK_T* pScalarQ, int scalarQlen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) */ IPP_OWN_DECL (IppsGFpECPoint*, gfec_BasePointProduct, (IppsGFpECPoint* pR, const BNU_CHUNK_T* pScalarG, int scalarGlen, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalarP, int scalarPlen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (void, p192r1_select_ap_w7, (BNU_CHUNK_T* pAffinePoint, const BNU_CHUNK_T* pTable, int index)) IPP_OWN_DECL (void, p224r1_select_ap_w7, (BNU_CHUNK_T* pAffinePoint, const BNU_CHUNK_T* pTable, int index)) IPP_OWN_DECL (void, p256r1_select_ap_w7, (BNU_CHUNK_T* pAffinePoint, const BNU_CHUNK_T* pTable, int index)) IPP_OWN_DECL (void, p384r1_select_ap_w5, (BNU_CHUNK_T* pAffinePoint, const BNU_CHUNK_T* pTable, int index)) IPP_OWN_DECL (void, p521r1_select_ap_w5, (BNU_CHUNK_T* pAffinePoint, const BNU_CHUNK_T* pTable, int index)) /* AVX512-IFMA implementations */ #define gfec_SignDSA_nistp256_avx512 OWNAPI(gfec_SignDSA_nistp256_avx512) #define gfec_SignDSA_nistp384_avx512 OWNAPI(gfec_SignDSA_nistp384_avx512) #define gfec_SignDSA_nistp521_avx512 OWNAPI(gfec_SignDSA_nistp521_avx512) #define gfec_Sign_sm2_avx512 OWNAPI(gfec_Sign_sm2_avx512) #define gfec_VerifyDSA_nistp256_avx512 OWNAPI(gfec_VerifyDSA_nistp256_avx512) #define gfec_VerifyDSA_nistp384_avx512 OWNAPI(gfec_VerifyDSA_nistp384_avx512) #define gfec_VerifyDSA_nistp521_avx512 OWNAPI(gfec_VerifyDSA_nistp521_avx512) #define gfec_Verify_sm2_avx512 OWNAPI(gfec_Verify_sm2_avx512) #define gfec_SharedSecretDH_nistp256_avx512 OWNAPI(gfec_SharedSecretDH_nistp256_avx512) #define gfec_SharedSecretDH_nistp384_avx512 OWNAPI(gfec_SharedSecretDH_nistp384_avx512) #define gfec_SharedSecretDH_nistp521_avx512 OWNAPI(gfec_SharedSecretDH_nistp521_avx512) #define gfec_SharedSecretDH_sm2_avx512 OWNAPI(gfec_SharedSecretDH_sm2_avx512) #define gfec_PubKey_nist256_avx512 OWNAPI(gfec_PubKey_nist256_avx512) #define gfec_PubKey_nist384_avx512 OWNAPI(gfec_PubKey_nist384_avx512) #define gfec_PubKey_nist521_avx512 OWNAPI(gfec_PubKey_nist521_avx512) #define gfec_PubKey_sm2_avx512 OWNAPI(gfec_PubKey_sm2_avx512) #define gfec_MulPoint_nistp256_avx512 OWNAPI(gfec_MulPoint_nistp256_avx512) #define gfec_MulPoint_nistp384_avx512 OWNAPI(gfec_MulPoint_nistp384_avx512) #define gfec_MulPoint_nistp521_avx512 OWNAPI(gfec_MulPoint_nistp521_avx512) #define gfec_MulPoint_sm2_avx512 OWNAPI(gfec_MulPoint_sm2_avx512) #define gfec_AddPoint_nistp256_avx512 OWNAPI(gfec_AddPoint_nistp256_avx512) #define gfec_AddPoint_nistp384_avx512 OWNAPI(gfec_AddPoint_nistp384_avx512) #define gfec_AddPoint_nistp521_avx512 OWNAPI(gfec_AddPoint_nistp521_avx512) #define gfec_AddPoint_sm2_avx512 OWNAPI(gfec_AddPoint_sm2_avx512) #define gfec_point_on_curve_nistp256_avx512 OWNAPI(gfec_point_on_curve_nistp256_avx512) #define gfec_point_on_curve_nistp384_avx512 OWNAPI(gfec_point_on_curve_nistp384_avx512) #define gfec_point_on_curve_nistp521_avx512 OWNAPI(gfec_point_on_curve_nistp521_avx512) #define gfec_point_on_curve_sm2_avx512 OWNAPI(gfec_point_on_curve_sm2_avx512) IPP_OWN_DECL (IppStatus, gfec_SignDSA_nistp256_avx512, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppStatus, gfec_SignDSA_nistp384_avx512, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppStatus, gfec_SignDSA_nistp521_avx512, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppStatus, gfec_Sign_sm2_avx512, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppECResult, gfec_VerifyDSA_nistp256_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppECResult, gfec_VerifyDSA_nistp384_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppECResult, gfec_VerifyDSA_nistp521_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppECResult, gfec_Verify_sm2_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (int, gfec_SharedSecretDH_nistp256_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (int, gfec_SharedSecretDH_nistp384_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (int, gfec_SharedSecretDH_nistp521_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (int, gfec_SharedSecretDH_sm2_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_PubKey_nist256_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_PubKey_nist384_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_PubKey_nist521_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_PubKey_sm2_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_MulPoint_nistp256_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_MulPoint_nistp384_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_MulPoint_nistp521_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_MulPoint_sm2_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_AddPoint_nistp256_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_AddPoint_nistp384_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_AddPoint_nistp521_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) IPP_OWN_DECL (IppsGFpECPoint*, gfec_AddPoint_sm2_avx512, (IppsGFpECPoint* pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) IPP_OWN_DECL (int, gfec_point_on_curve_nistp256_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) IPP_OWN_DECL (int, gfec_point_on_curve_nistp384_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) IPP_OWN_DECL (int, gfec_point_on_curve_nistp521_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) IPP_OWN_DECL (int, gfec_point_on_curve_sm2_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) #define gfec_CheckPrivateKey OWNAPI(gfec_CheckPrivateKey) IPP_OWN_DECL(int, gfec_CheckPrivateKey, (const IppsBigNumState* pPrivate, IppsGFpECState* pEC)) #endif /* _CP_ECGFP_H_ */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpectstpoint.c000066400000000000000000000047451470420105600260670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECTstPoint() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECTstPoint // // Purpose: Checks if a point belongs to an elliptic curve // // Returns: Reason: // ippStsNullPtrErr pP == NULL // pEC == NULL // pResult == NULL // // ippStsContextMatchErr invalid pEC->idCtx // invalid pP->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pP)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pP Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // pResult Pointer to the result of the check // // Note: // Even if test passed is not a fact that the point belongs to BP-related subgroup BP // *F*/ IPPFUN(IppStatus, ippsGFpECTstPoint,(const IppsGFpECPoint* pP, IppECResult* pResult, IppsGFpECState* pEC)) { IPP_BAD_PTR3_RET(pP, pResult, pEC); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pP), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pP)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); if( gfec_IsPointAtInfinity(pP) ) *pResult = ippECPointIsAtInfinite; else if( !gfec_IsPointOnCurve(pP, pEC) ) *pResult = ippECPointIsNotValid; else *pResult = ippECValid; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpectstpointinsubgroup.c000066400000000000000000000060551470420105600302010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // EC over GF(p) Operations // // Context: // ippsGFpECTstPointInSubgroup() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsGFpECTstPointInSubgroup // // Purpose: Checks if a point belongs to a specified subgroup // // Returns: Reason: // ippStsNullPtrErr pP == NULL // pEC == NULL // pResult == NULL / pScratchBuffer == NULL // // ippStsContextMatchErr invalid pEC->idCtx // pEC->subgroup == NULL // invalid pP->idCtx // // ippStsOutOfRangeErr ECP_POINT_FELEN(pP)!=GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pP Pointer to the IppsGFpECPoint context // pEC Pointer to the context of the elliptic curve // pResult Pointer to the result of the check // pScratchBuffer Pointer to the scratch buffer // *F*/ IPPFUN(IppStatus, ippsGFpECTstPointInSubgroup,(const IppsGFpECPoint* pP, IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_BAD_PTR4_RET(pP, pResult, pEC, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); IPP_BADARG_RET( !ECP_POINT_VALID_ID(pP), ippStsContextMatchErr ); IPP_BADARG_RET( ECP_POINT_FELEN(pP)!=GFP_FELEN(GFP_PMA(ECP_GFP(pEC))), ippStsOutOfRangeErr); { IppECResult tstResult; ippsGFpECTstPoint(pP, &tstResult, pEC); if(ippECValid==tstResult) { IppsGFpECPoint T; cpEcGFpInitPoint(&T, cpEcGFpGetPool(1, pEC),0, pEC); gfec_MulPoint(&T, pP, MOD_MODULUS(ECP_MONT_R(pEC)), BITS_BNU_CHUNK(ECP_ORDBITSIZE(pEC)), /*0,*/ pEC, pScratchBuffer); tstResult = gfec_IsPointAtInfinity(&T)? ippECValid : ippECPointOutOfGroup; cpEcGFpReleasePool(1, pEC); } *pResult = tstResult; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecverify.c000066400000000000000000000107651470420105600255060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // EC over GF(p^m) definitinons // // Context: // ippsGFpECVerify() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpeccp.h" //tbcd: temporary excluded: #include /*F* // Name: ippsGFpECVerify // // Purpose: Verifies the parameters of an elliptic curve. // // Returns: Reason: // ippStsNullPtrErr pEC == NULL // pResult == NULL // pScratchBuffer == NULL // ippStsContextMatchErr invalid pEC->idCtx // ippStsNoErr no error // // Parameters: // pResult Pointer to the verification result // pEC Pointer to the context of the elliptic curve // pScratchBuffer Pointer to the scratch buffer // *F*/ IPPFUN(IppStatus, ippsGFpECVerify,(IppECResult* pResult, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_BAD_PTR3_RET(pEC, pResult, pScratchBuffer); IPP_BADARG_RET( !VALID_ECP_ID(pEC), ippStsContextMatchErr ); *pResult = ippECValid; { IppsGFpState* pGF = ECP_GFP(pEC); gsModEngine* pGFE = GFP_PMA(pGF); int elemLen = GFP_FELEN(pGFE); mod_mul mulF = GFP_METHOD(pGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGFE)->sqr; mod_add addF = GFP_METHOD(pGFE)->add; /* // check discriminant ( 4*A^3 + 27*B^2 != 0 mod P) */ if(ippECValid == *pResult) { BNU_CHUNK_T* pT = cpGFpGetPool(1, pGFE); BNU_CHUNK_T* pU = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(NULL!=pT && NULL!=pU); if(ECP_SPECIFIC(pEC)==ECP_EPID2) cpGFpElementPad(pT, elemLen, 0); /* T = 4*A^3 = 0 */ else { addF(pT, ECP_A(pEC), ECP_A(pEC), pGFE); /* T = 4*A^3 */ sqrF(pT, pT, pGFE); mulF(pT, ECP_A(pEC), pT, pGFE); } addF(pU, ECP_B(pEC), ECP_B(pEC), pGFE); /* U = 9*B^2 */ addF(pU, pU, ECP_B(pEC), pGFE); sqrF(pU, pU, pGFE); addF(pT, pU, pT, pGFE); /* T += 3*U */ addF(pT, pU, pT, pGFE); addF(pT, pU, pT, pGFE); *pResult = GFP_IS_ZERO(pT, elemLen)? ippECIsZeroDiscriminant: ippECValid; cpGFpReleasePool(2, pGFE); } if(ECP_SUBGROUP(pEC)) { /* // check base point and it order */ if(ippECValid == *pResult) { IppsGFpECPoint G; cpEcGFpInitPoint(&G, ECP_G(pEC), ECP_AFFINE_POINT|ECP_FINITE_POINT, pEC); /* check G != infinity */ *pResult = gfec_IsPointAtInfinity(&G)? ippECPointIsAtInfinite : ippECValid; /* check G lies on EC */ if(ippECValid == *pResult) *pResult = gfec_IsPointOnCurve(&G, pEC)? ippECValid : ippECPointIsNotValid; /* check Gorder*G = infinity */ if(ippECValid == *pResult) { IppsGFpECPoint T; cpEcGFpInitPoint(&T, cpEcGFpGetPool(1, pEC),0, pEC); gfec_MulBasePoint(&T, MOD_MODULUS(ECP_MONT_R(pEC)), BITS_BNU_CHUNK(ECP_ORDBITSIZE(pEC)), pEC, pScratchBuffer); *pResult = gfec_IsPointAtInfinity(&T)? ippECValid : ippECInvalidOrder; cpEcGFpReleasePool(1, pEC); } } /* // check order==P */ if(ippECValid == *pResult) { BNU_CHUNK_T* pPrime = GFP_MODULUS(pGFE); int primeLen = GFP_FELEN(pGFE); gsModEngine* pR = ECP_MONT_R(pEC); BNU_CHUNK_T* pOrder = MOD_MODULUS(pR); int orderLen = MOD_LEN(pR); *pResult = (primeLen==orderLen && GFP_EQ(pPrime, pOrder, primeLen))? ippECIsWeakSSSA : ippECValid; } } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecverifydsa.c000066400000000000000000000173321470420105600261730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECVerifyDSA() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECVerifyDSA // // Purpose: DSA Signature Verification. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pMsgDigest // NULL == pRegPublic // NULL == pSignR // NULL == pSignS // NULL == pResult // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pECC->idCtx // pEC->subgroup == NULL // illegal pMsgDigestDigest->idCtx // illegal pRegPublic->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsMessageErr 0> MsgDigest // order<= MsgDigest // // ippStsRangeErr SignR < 0 or SignS < 0 // // ippStsOutOfRangeErr bitsize(pRegPublic) != bitsize(prime) // // ippStsNotSupportedModeErr 1 cpCmp_BNU(BN_NUMBER(pSignR), BN_SIZE(pSignR), pOrder, orderLen) && 0 > cpCmp_BNU(BN_NUMBER(pSignS), BN_SIZE(pSignS), pOrder, orderLen)) { #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { switch (ECP_MODULUS_ID(pEC)) { case cpID_PrimeP256r1: { verifyResult = gfec_VerifyDSA_nistp256_avx512(pMsgDigest, pRegPublic, pSignR, pSignS, pEC, pScratchBuffer); goto exit; break; } case cpID_PrimeP384r1: { verifyResult = gfec_VerifyDSA_nistp384_avx512(pMsgDigest, pRegPublic, pSignR, pSignS, pEC, pScratchBuffer); goto exit; break; } case cpID_PrimeP521r1: { verifyResult = gfec_VerifyDSA_nistp521_avx512(pMsgDigest, pRegPublic, pSignR, pSignS, pEC, pScratchBuffer); goto exit; break; } default: /* Go to default implementation below */ break; } } /* no else */ #endif // (_IPP32E >= _IPP32E_K1) { int elmLen = GFP_FELEN(pGFE); int pelmLen = GFP_PELEN(pGFE); BNU_CHUNK_T *h1 = cpGFpGetPool(3, pGFE); BNU_CHUNK_T *h2 = h1 + pelmLen; BNU_CHUNK_T *h = h2 + pelmLen; IppsGFpECPoint P; cpEcGFpInitPoint(&P, cpEcGFpGetPool(1, pEC), 0, pEC); /* copy message and reduce */ ZEXPAND_COPY_BNU(h1, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); cpModSub_BNU(h1, h1, pOrder, pOrder, orderLen, h2); /* h = d^-1, h1 = msg*h, h2 = c*h */ ZEXPAND_COPY_BNU(h, orderLen, BN_NUMBER(pSignS), BN_SIZE(pSignS)); gs_mont_inv(h, h, pMontR, alm_mont_inv); cpMontMul_BNU(h1, h, h1, pMontR); ZEXPAND_COPY_BNU(h2, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); cpMontMul_BNU(h2, h, h2, pMontR); /* P = [h1]BasePoint + [h2]publicKey */ gfec_BasePointProduct(&P, h1, orderLen, pRegPublic, h2, orderLen, pEC, pScratchBuffer); /* check that P!=O */ if (!gfec_IsPointAtInfinity(&P)) { /* get P.X */ gfec_GetPoint(h1, NULL, &P, pEC); /* c' = int(P.x) mod order */ GFP_METHOD(pGFE)->decode(h1, h1, pGFE); elmLen = cpMod_BNU(h1, elmLen, pOrder, orderLen); cpGFpElementPad(h1 + elmLen, orderLen - elmLen, 0); /* and make sure c' = signC */ cpGFpElementCopyPad(h2, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); if (GFP_EQ(h1, h2, orderLen)) verifyResult = ippECValid; } cpEcGFpReleasePool(1, pEC); cpGFpReleasePool(3, pGFE); } } #if (_IPP32E >= _IPP32E_K1) exit: #endif *pResult = verifyResult; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecverifynr.c000066400000000000000000000140221470420105600260340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECVerifyNR() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECVerifyNR // // Purpose: NR Signature Verification. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pMsgDigest // NULL == pRegPublic // NULL == pSignR // NULL == pSignS // NULL == pResult // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pEC->idCtx // pEC->subgroup == NULL // illegal pMsgDigestDigest->idCtx // illegal pRegPublic->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsMessageErr 0> MsgDigest // order<= MsgDigest // // ippStsRangeErr SignR < 0 or SignS < 0 // // ippStsOutOfRangeErr bitsize(pRegPublic) != bitsize(prime) // // ippStsNotSupportedModeErr 1cpCmp_BNU(BN_NUMBER(pSignR), BN_SIZE(pSignR), pOrder, orderLen) && 0>cpCmp_BNU(BN_NUMBER(pSignS), BN_SIZE(pSignS), pOrder, orderLen)) { int elmLen = GFP_FELEN(pGFE); int pelmLen = GFP_PELEN(pGFE); BNU_CHUNK_T* h1 = cpGFpGetPool(3, pGFE); BNU_CHUNK_T* h2 = h1+pelmLen; BNU_CHUNK_T* f = h2+pelmLen; IppsGFpECPoint P; cpEcGFpInitPoint(&P, cpEcGFpGetPool(1, pEC),0, pEC); /* P = [d]BasePoint + [c]publicKey */ ZEXPAND_COPY_BNU(h1, orderLen, BN_NUMBER(pSignS),BN_SIZE(pSignS)); ZEXPAND_COPY_BNU(h2, orderLen, BN_NUMBER(pSignR),BN_SIZE(pSignR)); gfec_BasePointProduct(&P, h1, orderLen, pRegPublic, h2, orderLen, pEC, pScratchBuffer); /* check that P!=O */ if( !gfec_IsPointAtInfinity(&P)) { /* get P.X */ gfec_GetPoint(h1, NULL, &P, pEC); /* x = int(P.x) mod order */ GFP_METHOD(pGFE)->decode(h1, h1, pGFE); elmLen = cpMod_BNU(h1, elmLen, pOrder, orderLen); cpGFpElementPad(h1+elmLen, orderLen-elmLen, 0); /* and recover msg f = (signC -x) mod order */ ZEXPAND_COPY_BNU(f, orderLen, BN_NUMBER(pMsgDigest),BN_SIZE(pMsgDigest)); cpModSub_BNU(h1, h2, h1, pOrder, orderLen, h2); if(GFP_EQ(f, h1, orderLen)) vResult = ippECValid; } cpEcGFpReleasePool(1, pEC); cpGFpReleasePool(3, pGFE); } *pResult = vResult; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpecverifysm2.c000066400000000000000000000153641470420105600261300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsGFpECVerifySM2() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsGFpECVerifySM2 // // Purpose: SM2 Signature Verification. // // Returns: Reason: // ippStsNullPtrErr NULL == pEC // NULL == pMsgDigest // NULL == pRegPublic // NULL == pSignR // NULL == pSignS // NULL == pResult // NULL == pScratchBuffer // // ippStsContextMatchErr illegal pECC->idCtx // illegal pMsgDigestDigest->idCtx // illegal pRegPublic->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsMessageErr 0> MsgDigest // order<= MsgDigest // // ippStsRangeErr SignR < 0 or SignS < 0 // // ippStsOutOfRangeErr bitsize(pRegPublic) != bitsize(prime) // // ippStsNotSupportedModeErr 1cpCmp_BNU(BN_NUMBER(pSignR), BN_SIZE(pSignR), pOrder, orderLen) && 0>cpCmp_BNU(BN_NUMBER(pSignS), BN_SIZE(pSignS), pOrder, orderLen)) { // Optimization is disabled due to a bug // #if (_IPP32E >= _IPP32E_K1) // if (IsFeatureEnabled(ippCPUID_AVX512IFMA) && ECP_MODULUS_ID(pEC) == cpID_PrimeTPM_SM2) { // vResult = gfec_Verify_sm2_avx512(pMsgDigest, pRegPublic, pSignR, pSignS, pEC, pScratchBuffer); // goto exit; // } /* no else */ // #endif // (_IPP32E >= _IPP32E_K1) { int elmLen = GFP_FELEN(pGFE); int ns; BNU_CHUNK_T* r = cpGFpGetPool(4, pGFE); BNU_CHUNK_T* s = r+orderLen; BNU_CHUNK_T* t = s+orderLen; BNU_CHUNK_T* f = t+orderLen; /* expand signatire's components */ cpGFpElementCopyPad(r, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); cpGFpElementCopyPad(s, orderLen, BN_NUMBER(pSignS), BN_SIZE(pSignS)); /* t = (r+s) mod order */ cpModAdd_BNU(t, r, s, pOrder, orderLen, f); /* check if t!=0 */ if( !cpIsGFpElemEquChunk_ct(t, orderLen, 0) ) { /* P = [s]G +[t]regPublic, t = P.x */ IppsGFpECPoint P, G; cpEcGFpInitPoint(&P, cpEcGFpGetPool(1, pEC),0, pEC); cpEcGFpInitPoint(&G, ECP_G(pEC), ECP_AFFINE_POINT|ECP_FINITE_POINT, pEC); gfec_BasePointProduct(&P, s, orderLen, pRegPublic, t, orderLen, pEC, pScratchBuffer); gfec_GetPoint(t, NULL, &P, pEC); GFP_METHOD(pGFE)->decode(t, t, pGFE); ns = cpMod_BNU(t, elmLen, pOrder, orderLen); cpEcGFpReleasePool(1, pEC); IPP_UNREFERENCED_PARAMETER(ns); } /* t = (msg+t) mod order */ cpGFpElementCopyPad(f, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); cpModSub_BNU(f, f, pOrder, pOrder, orderLen, s); cpModAdd_BNU(t, t, f, pOrder, orderLen, f); if(GFP_EQ(t, r, orderLen)) vResult = ippECValid; cpGFpReleasePool(4, pGFE); } } // Optimization is disabled due to a bug // #if (_IPP32E >= _IPP32E_K1) // exit: // #endif *pResult = vResult; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpelemgetsize.c000066400000000000000000000037531470420105600262060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpElementGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" //tbcd: temporary excluded: #include /*F* // Name: ippsGFpElementGetSize // // Purpose: Gets the size of the context for an element of the finite field. // // Returns: Reason: // ippStsNullPtrErr pGFp == NULL // pBufferSize == NULL // ippStsContextMatchErr incorrect pGFp's context id // ippStsNoErr no error // // Parameters: // nExponents Number of exponents. // ExpBitSize Maximum bit size of the exponents. // pGFp Pointer to the context of the finite field. // pBufferSize Pointer to the calculated buffer size in bytes. // *F*/ IPPFUN(IppStatus, ippsGFpElementGetSize,(const IppsGFpState* pGFp, int* pElementSize)) { IPP_BAD_PTR2_RET(pElementSize, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); *pElementSize = (Ipp32s)sizeof(IppsGFpElement) +GFP_FELEN(GFP_PMA(pGFp))*(Ipp32s)sizeof(BNU_CHUNK_T); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpeleminit.c000066400000000000000000000047341470420105600254770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpElementInit() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" //tbcd: temporary excluded: #include /*F* // Name: ippsGFpElementInit // // Purpose: Initializes the context of an element of the finite field. // // Returns: Reason: // ippStsNullPtrErr pGFp == NULL // pR == NULL // pA && nsA>0 == NULL // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pR->idCtx // // ippStsSizeErr pA && !(0<=lenA && lenA= modulus // // ippStsNoErr no error // // Parameters: // pA Pointer to the data array storing the finite field element. // lenA Length of the element. // pR Pointer to the context of the finite field element being initialized. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpElementInit,(const Ipp32u* pA, int lenA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR2_RET(pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET(0>lenA, ippStsSizeErr); { int elemLen = GFP_FELEN(GFP_PMA(pGFp)); Ipp8u* ptr = (Ipp8u*)pR; ptr += sizeof(IppsGFpElement); cpGFpElementConstruct(pR, (BNU_CHUNK_T*)ptr, elemLen); return ippsGFpSetElement(pA, lenA, pR, pGFp); } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpexp.c000066400000000000000000000054341470420105600244630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpExp() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpExp // // Purpose: Raise GF element to the specified power // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // NULL == pE // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pE->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pE Pointer to the Big Number context storing the exponent // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // pScratchBuffer Pointer to the scratch buffer. // *F*/ IPPFUN(IppStatus, ippsGFpExp,(const IppsGFpElement* pA, const IppsBigNumState* pE, IppsGFpElement* pR, IppsGFpState* pGFp, Ipp8u* pScratchBuffer)) { IPP_BAD_PTR4_RET(pA, pE, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); IPP_BADARG_RET( !BN_VALID_ID(pE), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); cpGFpxExp(GFPE_DATA(pR), GFPE_DATA(pA), BN_NUMBER(pE), BN_SIZE(pE), pGFE, pScratchBuffer); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpgetelem.c000066400000000000000000000052001470420105600253000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpGetElement() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" //tbcd: temporary excluded: #include /*F* // Name: ippsGFpGetElement // // Purpose: Get GF Element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pDataA // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsSizeErr !(0=GFP_FELEN32(pGFE)) // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the finite field element. // pDataA Pointer to the data array to copy the finite field element from. // lenA Length of the data array. // pGFp Pointer to the context of the finite field. *F*/ IPPFUN(IppStatus, ippsGFpGetElement, (const IppsGFpElement* pA, Ipp32u* pDataA, int lenA, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pDataA, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); IPP_BADARG_RET( !(0=GFP_FELEN32(pGFE)), ippStsSizeErr ); { int elemLen = GFP_FELEN(pGFE); BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(NULL!=pTmp); cpGFpxGet(pTmp, elemLen, GFPE_DATA(pA), pGFE); cpGFpxCopyFromChunk(pDataA, pTmp, pGFE); cpGFpReleasePool(1, pGFE); return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpgetelemoctstr.c000066400000000000000000000057541470420105600265550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpGetElementOctString() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpGetElementOctString // // Purpose: Get GF Element to the octet string // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pStr // NULL == pA // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsSizeErr !(0=GFP_FELEN32(pGFE)) // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the finite field element. // pStr Pointer to the octet string. // strSize Size of the octet string buffer in bytes. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpGetElementOctString,(const IppsGFpElement* pA, Ipp8u* pStr, int strSize, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pStr, pA, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( 0>=strSize, ippStsSizeErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { gsModEngine* pBasicGFE = cpGFpBasic(pGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFE); int basicElemLen = GFP_FELEN(pBasicGFE); int basicSize = BITS2WORD8_SIZE(BITSIZE_BNU(GFP_MODULUS(pBasicGFE),GFP_FELEN(pBasicGFE))); BNU_CHUNK_T* pDataElm = GFPE_DATA(pA); int deg, error; for(deg=0, error=0; deg GFP_MAX_BITSIZE), ippStsSizeErr); *pSize = cpGFpGetSize(feBitSize, feBitSize+BITSIZE(BNU_CHUNK_T), GFP_POOL_SIZE); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpinfo.c000066400000000000000000000037271470420105600246250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p) ectension. // // Context: // ippsGFpInfo() // */ #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" /*F* // Name: ippsGFpInit // // Purpose: finite field info // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pInfo // // ippStsContextMatchErr invalid pGFp->idCtx // // ippStsNoErr no error // // Parameters: // pInfo pointer to finite field infon // pGFp Pointer to the context of the finite field. *F*/ IPPFUN(IppStatus, ippsGFpGetInfo,(IppsGFpInfo* pInfo, const IppsGFpState* pGFp)) { IPP_BAD_PTR2_RET(pGFp, pInfo); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); { gsModEngine* pGFpx = GFP_PMA(pGFp); /* current */ gsModEngine* pGFpBasic = cpGFpBasic(pGFpx); /* basic */ pInfo->parentGFdegree = MOD_EXTDEG(pGFpx); /* parent extension */ pInfo->basicGFdegree = cpGFpBasicDegreeExtension(pGFpx); /* total basic extension */ pInfo->basicElmBitSize = GFP_FEBITLEN(pGFpBasic); /* basic bitsise */ return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpinit.c000066400000000000000000000102111470420105600246170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpInit // // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpInit // // Purpose: initializes prime finite field GF(p) // // Returns: Reason: // ippStsNullPtrErr NULL == pGFpMethod // NULL == pGFp // // ippStsSizeErr !(IPP_MIN_GF_BITSIZE <= primeBitSize <=IPP_MAX_GF_BITSIZE // // ippStsContextMatchErr invalid pPrime->idCtx // // ippStsBadArgErr pGFpMethod != ippsGFpMethod_pXXX() or != ippsGFpMethod_pArb() // prime != pGFpMethod->modulus // prime <0 // bitsize(prime) != primeBitSize // prime IPP_MAX_GF_BITSIZE), ippStsSizeErr); /* use ippsGFpInitFixed() if NULL==pPrimeBN */ if(!pPrimeBN) return ippsGFpInitFixed(primeBitSize, pGFpMethod, pGFp); /* use ippsGFpInitArbitrary() if NULL==pGFpMethod */ if(!pGFpMethod) return ippsGFpInitArbitrary(pPrimeBN, primeBitSize, pGFp); /* test parameters if both pPrimeBN and method are defined */ else { IppStatus sts; /* test input prime */ IPP_BADARG_RET(!BN_VALID_ID(pPrimeBN), ippStsContextMatchErr); IPP_BADARG_RET(BN_SIGN(pPrimeBN)!= IppsBigNumPOS, ippStsBadArgErr); /* prime is negative */ IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPrimeBN),BN_SIZE(pPrimeBN)) != primeBitSize, ippStsBadArgErr); /* primeBitSize == bitsize(prime) */ IPP_BADARG_RET((BN_SIZE(pPrimeBN)==1) && (BN_NUMBER(pPrimeBN)[0]modulusID & cpID_Prime), ippStsBadArgErr); /* test if size of the prime is matched to method's prime */ IPP_BADARG_RET(pGFpMethod->modulusBitDeg && (primeBitSize!=pGFpMethod->modulusBitDeg), ippStsBadArgErr); /* if method assumes fixed prime value */ if(pGFpMethod->modulus) { int primeLen = BITS_BNU_CHUNK(primeBitSize); IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pPrimeBN), primeLen, pGFpMethod->modulus, primeLen), ippStsBadArgErr); } /* init GF */ sts = cpGFpInitGFp(primeBitSize, pGFp); /* set up GF and find quadratic nonresidue */ if(ippStsNoErr==sts) { cpGFpSetGFp(BN_NUMBER(pPrimeBN), primeBitSize, pGFpMethod, pGFp); } return sts; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpinitarbitrary.c000066400000000000000000000056101470420105600265460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpInitArbitrary() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpInitArbitrary // // Purpose: initializes prime finite field GF(p) // // Returns: Reason: // ippStsNullPtrErr NULL == pPrime // NULL == pGFp // // ippStsSizeErr !(IPP_MIN_GF_BITSIZE <= primeBitSize <=IPP_MAX_GF_BITSIZE) // // ippStsContextMatchErr incorrect pPrime context ID // // ippStsBadArgErr prime <0 // bitsize(prime) != primeBitSize // prime IPP_MAX_GF_BITSIZE), ippStsSizeErr); IPP_BAD_PTR1_RET(pPrime); IPP_BADARG_RET(!BN_VALID_ID(pPrime), ippStsContextMatchErr); IPP_BADARG_RET(BN_SIGN(pPrime)!= IppsBigNumPOS, ippStsBadArgErr); /* prime is negative */ IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPrime),BN_SIZE(pPrime)) != primeBitSize, ippStsBadArgErr); /* primeBitSize == bitsize(prime) */ IPP_BADARG_RET((BN_SIZE(pPrime)==1) && (BN_NUMBER(pPrime)[0]modulusID & cpID_Prime), ippStsBadArgErr); /* test if method is not prime based arbitrary */ IPP_BADARG_RET(!pGFpMethod->modulus, ippStsBadArgErr); /* size of the underlying prime must be equal to primeBitSize parameter*/ IPP_BADARG_RET(pGFpMethod->modulusBitDeg!=primeBitSize, ippStsBadArgErr); { /* init GF */ IppStatus sts = cpGFpInitGFp(primeBitSize, pGFp); /* set up GF engine */ if(ippStsNoErr==sts) { cpGFpSetGFp(pGFpMethod->modulus, primeBitSize, pGFpMethod, pGFp); } return sts; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpinv.c000066400000000000000000000050271470420105600244610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpInv() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpInv // // Purpose: Multiplicative inverse GF element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsDivByZeroErr pA is zero // // ippStsBadArgErr computational error // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the source finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpInv,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); IPP_BADARG_RET( GFP_IS_ZERO(GFPE_DATA(pA),GFP_FELEN(pGFE)), ippStsDivByZeroErr ); return NULL != cpGFpxInv(GFPE_DATA(pR), GFPE_DATA(pA), pGFE)? ippStsNoErr : ippStsBadArgErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpisunityelem.c000066400000000000000000000051621470420105600262340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpIsUnityElement() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpIsUnityElement // // Purpose: Compare GF Element with unity element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pResult // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the finite field element. // pResult Pointer to the result of the comparison // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpIsUnityElement,(const IppsGFpElement* pA, int* pResult, const IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pResult, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { gsModEngine* pBasicGFE = cpGFpBasic(pGFE); int basicElmLen = GFP_FELEN(pBasicGFE); BNU_CHUNK_T* pUnity = GFP_MNT_R(pBasicGFE); int elmLen = GFP_FELEN(pGFE); int flag; FIX_BNU(pUnity, basicElmLen); FIX_BNU(GFPE_DATA(pA), elmLen); flag = (basicElmLen==elmLen) && (GFP_EQ(GFPE_DATA(pA), pUnity, elmLen)); *pResult = (1==flag)? IPP_IS_EQ : IPP_IS_NE; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpiszeroelem.c000066400000000000000000000044661470420105600260510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpIsZeroElement() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpIsZeroElement // // Purpose: Compare GF Element with zero element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pResult // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the finite field element. // pResult Pointer to the result of the comparison // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpIsZeroElement,(const IppsGFpElement* pA, int* pResult, const IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pResult, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFPE_ROOM(pA)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { int flag = GFP_IS_ZERO(GFPE_DATA(pA), GFP_FELEN(pGFE)); *pResult = (1==flag)? IPP_IS_EQ : IPP_IS_NE; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod.h000066400000000000000000000036731470420105600251570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal GF(p) basic Definitions & Function Prototypes // */ #if !defined(_CP_GFP_METHOD_H) #define _CP_GFP_METHOD_H #include "owncp.h" #include "pcpbnuimpl.h" #include "gsmodmethod.h" /* modulus ID */ typedef enum { cpID_Prime = 0x1000, cpID_PrimeP192r1 = cpID_Prime+6, cpID_PrimeP224r1 = cpID_Prime+7, cpID_PrimeP256r1 = cpID_Prime+8, cpID_PrimeP384r1 = cpID_Prime+9, cpID_PrimeP521r1 = cpID_Prime+10, cpID_PrimeTPM_SM2 = cpID_Prime+11, cpID_PrimeTPM_BN = cpID_Prime+12, cpID_Poly = 0x10000000, /* id=0x10000000: general polynomial */ cpID_Binom = 0x01000000, /* id=0x11000000: x^d+a */ cpID_Binom2_epid20 = cpID_Binom|0x220000, /* 0x11220000 */ cpID_Binom3_epid20 = cpID_Binom|0x230000 /* 0x11230000 */ } cpModulusID; typedef struct _cpGFpMethod { cpModulusID modulusID; int modulusBitDeg; const BNU_CHUNK_T* modulus; const gsModMethod* arith; const void* arith_alt; // alternative radix implementation } cpGFpMethod; /* common GF arith methods */ #define gsArithGFp OWNAPI(gsArithGFp) IPP_OWN_DECL (gsModMethod*, gsArithGFp, (void)) #endif /* _CP_GFP_METHOD_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_192r1.c000066400000000000000000000157221470420105600260060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpecprime.h" //tbcd: temporary excluded: #include #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) /* arithmetic over P-192r1 NIST modulus */ #define p192r1_add OWNAPI(p192r1_add) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_add, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p192r1_sub OWNAPI(p192r1_sub) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_sub, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p192r1_neg OWNAPI(p192r1_neg) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_neg, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_div_by_2 OWNAPI(p192r1_div_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_div_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_mul_by_2 OWNAPI(p192r1_mul_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mul_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_mul_by_3 OWNAPI(p192r1_mul_by_3) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mul_by_3, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #if(_IPP_ARCH ==_IPP_ARCH_EM64T) #define p192r1_mul_montl OWNAPI(p192r1_mul_montl) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mul_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p192r1_mul_montx OWNAPI(p192r1_mul_montx) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mul_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p192r1_sqr_montl OWNAPI(p192r1_sqr_montl) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_sqr_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_sqr_montx OWNAPI(p192r1_sqr_montx) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_sqr_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_to_mont OWNAPI(p192r1_to_mont) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_to_mont, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_mont_back OWNAPI(p192r1_mont_back) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mont_back, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #endif #if(_IPP_ARCH ==_IPP_ARCH_IA32) #define p192r1_mul_mont_slm OWNAPI(p192r1_mul_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mul_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p192r1_sqr_mont_slm OWNAPI(p192r1_sqr_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_sqr_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p192r1_mred OWNAPI(p192r1_mred) IPP_OWN_DECL (BNU_CHUNK_T*, p192r1_mred, (BNU_CHUNK_T* res, BNU_CHUNK_T* product)) #endif #define OPERAND_BITSIZE (192) #define LEN_P192 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* // ia32 multiplicative methods */ #if (_IPP_ARCH ==_IPP_ARCH_IA32) IPP_OWN_DEFN (static BNU_CHUNK_T*, p192r1_mul_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpMulAdc_BNU_school(product, pA,LEN_P192, pB,LEN_P192); p192r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } IPP_OWN_DEFN (static BNU_CHUNK_T*, p192r1_sqr_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpSqrAdc_BNU_school(product, pA,LEN_P192); p192r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } /* // Montgomery domain conversion constants */ static BNU_CHUNK_T RR[] = { 0x00000001,0x00000000,0x00000002,0x00000000, 0x00000001,0x00000000}; static BNU_CHUNK_T one[] = { 1,0,0,0,0,0}; IPP_OWN_DEFN (static BNU_CHUNK_T*, p192r1_to_mont, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p192r1_mul_montl(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p192r1_mont_back, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p192r1_mul_montl(pR, pA, (BNU_CHUNK_T*)one, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p192r1_to_mont_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p192r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p192r1_mont_back_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p192r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #endif /* _IPP >= _IPP_P8 */ /* // return specific gf p192r1 arith methods, // p192r1 = 2^192 -2^64 -1 (NIST P192r1) */ static gsModMethod* gsArithGF_p192r1 (void) { static gsModMethod m = { p192r1_to_mont, p192r1_mont_back, p192r1_mul_montl, p192r1_sqr_montl, NULL, p192r1_add, p192r1_sub, p192r1_neg, p192r1_div_by_2, p192r1_mul_by_2, p192r1_mul_by_3, }; #if(_IPP_ARCH==_IPP_ARCH_EM64T) && ((_ADCOX_NI_ENABLING_==_FEATURE_ON_) || (_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_)) if(IsFeatureEnabled(ippCPUID_ADCOX)) { m.mul = p192r1_mul_montx; m.sqr = p192r1_sqr_montx; } #endif #if(_IPP_ARCH==_IPP_ARCH_IA32) if(IsFeatureEnabled(ippCPUID_SSSE3|ippCPUID_MOVBE) && !IsFeatureEnabled(ippCPUID_AVX)) { m.mul = p192r1_mul_mont_slm; m.sqr = p192r1_sqr_mont_slm; m.encode = p192r1_to_mont_slm; m.decode = p192r1_mont_back_slm; } #endif return &m; } #endif /* (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) */ /*F* // Name: ippsGFpMethod_p192r1 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = 2^192 - 2^64 - 1 *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p192r1, (void) ) { static IppsGFpMethod method = { cpID_PrimeP192r1, 192, secp192r1_p, NULL, NULL }; #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p192r1(); #else method.arith = gsArithGFp(); #endif return &method; } #undef LEN_P192 #undef OPERAND_BITSIZE cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_224r1.c000066400000000000000000000157431470420105600260050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpecprime.h" //tbcd: temporary excluded: #include #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) /* arithmetic over P-224r1 NIST modulus */ #define p224r1_add OWNAPI(p224r1_add) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_add, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p224r1_sub OWNAPI(p224r1_sub) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_sub, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p224r1_neg OWNAPI(p224r1_neg) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_neg, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_div_by_2 OWNAPI(p224r1_div_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_div_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_mul_by_2 OWNAPI(p224r1_mul_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mul_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_mul_by_3 OWNAPI(p224r1_mul_by_3) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mul_by_3, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #if(_IPP_ARCH ==_IPP_ARCH_EM64T) #define p224r1_mul_montl OWNAPI(p224r1_mul_montl) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mul_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p224r1_mul_montx OWNAPI(p224r1_mul_montx) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mul_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p224r1_sqr_montl OWNAPI(p224r1_sqr_montl) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_sqr_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_sqr_montx OWNAPI(p224r1_sqr_montx) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_sqr_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_to_mont OWNAPI(p224r1_to_mont) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_to_mont, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_mont_back OWNAPI(p224r1_mont_back) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mont_back, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #endif #if(_IPP_ARCH ==_IPP_ARCH_IA32) #define p224r1_mul_mont_slm OWNAPI(p224r1_mul_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mul_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p224r1_sqr_mont_slm OWNAPI(p224r1_sqr_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_sqr_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p224r1_mred OWNAPI(p224r1_mred) IPP_OWN_DECL (BNU_CHUNK_T*, p224r1_mred, (BNU_CHUNK_T* res, BNU_CHUNK_T* product)) #endif #define OPERAND_BITSIZE (224) #define LEN_P224 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* // ia32 multiplicative methods */ #if (_IPP_ARCH ==_IPP_ARCH_IA32) IPP_OWN_DEFN (static BNU_CHUNK_T*, p224r1_mul_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpMulAdc_BNU_school(product, pA,LEN_P224, pB,LEN_P224); p224r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } IPP_OWN_DEFN (static BNU_CHUNK_T*, p224r1_sqr_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpSqrAdc_BNU_school(product, pA,LEN_P224); p224r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } /* // Montgomery domain conversion constants */ static BNU_CHUNK_T RR[] = { 0x00000001,0x00000000,0x00000000,0xfffffffe, 0xffffffff,0xffffffff,0x00000000}; static BNU_CHUNK_T one[] = { 1,0,0,0,0,0,0}; IPP_OWN_DEFN (static BNU_CHUNK_T*, p224r1_to_mont, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p224r1_mul_montl(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p224r1_mont_back, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p224r1_mul_montl(pR, pA, (BNU_CHUNK_T*)one, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p224r1_to_mont_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p224r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p224r1_mont_back_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p224r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #endif /* _IPP >= _IPP_P8 */ /* // return specific gf p224r1 arith methods, // p224r1 = 2^224 -2^96 +1 (NIST P224r1) */ static gsModMethod* gsArithGF_p224r1 (void) { static gsModMethod m = { p224r1_to_mont, p224r1_mont_back, p224r1_mul_montl, p224r1_sqr_montl, NULL, p224r1_add, p224r1_sub, p224r1_neg, p224r1_div_by_2, p224r1_mul_by_2, p224r1_mul_by_3, }; #if(_IPP_ARCH==_IPP_ARCH_EM64T) && ((_ADCOX_NI_ENABLING_==_FEATURE_ON_) || (_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_)) if(IsFeatureEnabled(ippCPUID_ADCOX)) { m.mul = p224r1_mul_montx; m.sqr = p224r1_sqr_montx; } #endif #if(_IPP_ARCH==_IPP_ARCH_IA32) if(IsFeatureEnabled(ippCPUID_SSSE3|ippCPUID_MOVBE) && !IsFeatureEnabled(ippCPUID_AVX)) { m.mul = p224r1_mul_mont_slm; m.sqr = p224r1_sqr_mont_slm; m.encode = p224r1_to_mont_slm; m.decode = p224r1_mont_back_slm; } #endif return &m; } #endif /* (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) */ /*F* // Name: ippsGFpMethod_p224r1 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = 2^224 - 2^96 - 1 *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p224r1, (void) ) { static IppsGFpMethod method = { cpID_PrimeP224r1, 224, secp224r1_p, NULL, NULL }; #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p224r1(); #else method.arith = gsArithGFp(); #endif return &method; } #undef LEN_P224 #undef OPERAND_BITSIZE cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_256.c000066400000000000000000000026641470420105600255450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "gfpec/pcpgfpmethod_256.h" /*F* // Name: ippsGFpMethod_p256 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). Arbitrary 256 bit modulus. *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p256, (void) ) { static IppsGFpMethod method = { cpID_Prime, 256, NULL, NULL, NULL }; #if(_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p256(); #else method.arith = gsArithGFp(); #endif return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_256.h000066400000000000000000000105221470420105600255420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpecprime.h" #if !defined(_PCP_GFPMETHOD_256_H_) #define _PCP_GFPMETHOD_256_H_ #if(_IPP32E >= _IPP32E_M7) /* arithmetic over arbitrary 256r-bit modulus */ #define gf256_add OWNAPI(gf256_add) IPP_OWN_DECL (BNU_CHUNK_T*, gf256_add, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, const BNU_CHUNK_T* pModulus)) #define gf256_sub OWNAPI(gf256_sub) IPP_OWN_DECL (BNU_CHUNK_T*, gf256_sub, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, const BNU_CHUNK_T* pModulus)) #define gf256_neg OWNAPI(gf256_neg) IPP_OWN_DECL (BNU_CHUNK_T*, gf256_neg, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pModulus)) #define gf256_mulm OWNAPI(gf256_mulm) IPP_OWN_DECL (BNU_CHUNK_T*, gf256_mulm, (BNU_CHUNK_T* pR,const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, const BNU_CHUNK_T* pModulus, BNU_CHUNK_T m0)) #define gf256_sqrm OWNAPI(gf256_sqrm) IPP_OWN_DECL (BNU_CHUNK_T*, gf256_sqrm, (BNU_CHUNK_T* pR,const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pModulus, BNU_CHUNK_T m0)) #define gf256_div2 OWNAPI(gf256_div2) IPP_OWN_DECL (BNU_CHUNK_T*, gf256_div2, (BNU_CHUNK_T* pR,const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pModulus)) #define OPERAND_BITSIZE (256) #define LEN_P256 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) static BNU_CHUNK_T* p256_add(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) { return gf256_add(pR, pA, pB, GFP_MODULUS(pGFE)); } static BNU_CHUNK_T* p256_sub(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) { return gf256_sub(pR, pA, pB, GFP_MODULUS(pGFE)); } static BNU_CHUNK_T* p256_neg(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { return gf256_neg(pR, pA, GFP_MODULUS(pGFE)); } static BNU_CHUNK_T* p256_div_by_2(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { return gf256_div2(pR, pA, GFP_MODULUS(pGFE)); } static BNU_CHUNK_T* p256_mul_by_2(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { return gf256_add(pR, pA, pA, GFP_MODULUS(pGFE)); } static BNU_CHUNK_T* p256_mul_by_3(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { BNU_CHUNK_T tmp[LEN_P256]; gf256_add(tmp, pA, pA, GFP_MODULUS(pGFE)); return gf256_add(pR, tmp, pA, GFP_MODULUS(pGFE)); } static BNU_CHUNK_T* p256_mul_montl(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) { return gf256_mulm(pR, pA, pB, GFP_MODULUS(pGFE), GFP_MNT_FACTOR(pGFE)); } static BNU_CHUNK_T* p256_sqr_montl(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { return gf256_sqrm(pR, pA, GFP_MODULUS(pGFE), GFP_MNT_FACTOR(pGFE)); } static BNU_CHUNK_T* p256_to_mont(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { return gf256_mulm(pR, pA, GFP_MNT_RR(pGFE), GFP_MODULUS(pGFE), GFP_MNT_FACTOR(pGFE)); } static BNU_CHUNK_T one[] = {1,0,0,0}; static BNU_CHUNK_T* p256_mont_back(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE) { return gf256_mulm(pR, pA, one, GFP_MODULUS(pGFE), GFP_MNT_FACTOR(pGFE)); } /* return specific gf p256 arith methods */ static gsModMethod* gsArithGF_p256(void) { static gsModMethod m = { p256_to_mont, p256_mont_back, p256_mul_montl, p256_sqr_montl, NULL, p256_add, p256_sub, p256_neg, p256_div_by_2, p256_mul_by_2, p256_mul_by_3, }; return &m; } #endif /* _IPP32E >= _IPP32E_M7 */ #undef LEN_P256 #undef OPERAND_BITSIZE #endif /* #if !defined(_PCP_GFPMETHOD_256_H_) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_256bn.c000066400000000000000000000027731470420105600260660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "gfpec/pcpgfpmethod_256.h" /*F* // Name: ippsGFpMethod_p256bn // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = // 0xFFFFFFFFFFFCF0CD46E5F25EEE71A49F0CDC65FB12980A82D3292DDBAED33013 *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p256bn, (void) ) { static IppsGFpMethod method = { cpID_Prime, 256, tpmBN_p256p_p, NULL, NULL }; #if(_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p256(); #else method.arith = gsArithGFp(); #endif return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_256r1.c000066400000000000000000000162761470420105600260140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpecprime.h" #include "gfpec/ecnist/ifma_arith_method.h" //tbcd: temporary excluded: #include #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) /* arithmetic over P-256r1 NIST modulus */ #define p256r1_add OWNAPI(p256r1_add) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_add, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p256r1_sub OWNAPI(p256r1_sub) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_sub, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p256r1_neg OWNAPI(p256r1_neg) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_neg, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_div_by_2 OWNAPI(p256r1_div_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_div_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_mul_by_2 OWNAPI(p256r1_mul_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mul_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_mul_by_3 OWNAPI(p256r1_mul_by_3) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mul_by_3, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #if(_IPP_ARCH ==_IPP_ARCH_EM64T) #define p256r1_mul_montl OWNAPI(p256r1_mul_montl) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mul_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p256r1_mul_montx OWNAPI(p256r1_mul_montx) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mul_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p256r1_sqr_montl OWNAPI(p256r1_sqr_montl) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_sqr_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_sqr_montx OWNAPI(p256r1_sqr_montx) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_sqr_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_to_mont OWNAPI(p256r1_to_mont) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_to_mont, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_mont_back OWNAPI(p256r1_mont_back) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mont_back, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #endif #if(_IPP_ARCH ==_IPP_ARCH_IA32) #define p256r1_mul_mont_slm OWNAPI(p256r1_mul_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mul_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p256r1_sqr_mont_slm OWNAPI(p256r1_sqr_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_sqr_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p256r1_mred OWNAPI(p256r1_mred) IPP_OWN_DECL (BNU_CHUNK_T*, p256r1_mred, (BNU_CHUNK_T* res, BNU_CHUNK_T* product)) #endif #define OPERAND_BITSIZE (256) #define LEN_P256 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* // ia32 multiplicative methods */ #if (_IPP_ARCH ==_IPP_ARCH_IA32) IPP_OWN_DEFN (static BNU_CHUNK_T*, p256r1_mul_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpMulAdc_BNU_school(product, pA,LEN_P256, pB,LEN_P256); p256r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } IPP_OWN_DEFN (static BNU_CHUNK_T*, p256r1_sqr_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpSqrAdc_BNU_school(product, pA,LEN_P256); p256r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } /* // Montgomery domain conversion constants */ static BNU_CHUNK_T RR[] = { 0x00000003,0x00000000, 0xffffffff,0xfffffffb, 0xfffffffe,0xffffffff, 0xfffffffd,0x00000004}; static BNU_CHUNK_T one[] = { 1,0,0,0,0,0,0,0}; IPP_OWN_DEFN (static BNU_CHUNK_T*, p256r1_to_mont, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p256r1_mul_montl(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p256r1_mont_back, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p256r1_mul_montl(pR, pA, (BNU_CHUNK_T*)one, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p256r1_to_mont_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p256r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p256r1_mont_back_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p256r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #endif /* _IPP >= _IPP_P8 */ /* // return specific gf p256r1 arith methods, // p256r1 = 2^256 -2^224 +2^192 +2^96 -1 (NIST P256r1) */ static gsModMethod* gsArithGF_p256r1 (void) { static gsModMethod m = { p256r1_to_mont, p256r1_mont_back, p256r1_mul_montl, p256r1_sqr_montl, NULL, p256r1_add, p256r1_sub, p256r1_neg, p256r1_div_by_2, p256r1_mul_by_2, p256r1_mul_by_3, }; #if(_IPP_ARCH==_IPP_ARCH_EM64T) && ((_ADCOX_NI_ENABLING_==_FEATURE_ON_) || (_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_)) if(IsFeatureEnabled(ippCPUID_ADCOX)) { m.mul = p256r1_mul_montx; m.sqr = p256r1_sqr_montx; } #endif #if(_IPP_ARCH==_IPP_ARCH_IA32) if(IsFeatureEnabled(ippCPUID_SSSE3|ippCPUID_MOVBE) && !IsFeatureEnabled(ippCPUID_AVX)) { m.mul = p256r1_mul_mont_slm; m.sqr = p256r1_sqr_mont_slm; m.encode = p256r1_to_mont_slm; m.decode = p256r1_mont_back_slm; } #endif return &m; } #endif /* (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) */ /*F* // Name: ippsGFpMethod_p256r1 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = 2^256 - 2^224 + 2^192 + 2^96 - 1 *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p256r1, (void) ) { static IppsGFpMethod method = { cpID_PrimeP256r1, 256, secp256r1_p, NULL, NULL }; #if (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p256r1(); #else method.arith = gsArithGFp(); #endif #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { method.arith_alt = gsArithGF_p256r1_avx512(); } #endif return &method; } #undef LEN_P256 #undef OPERAND_BITSIZE cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_384r1.c000066400000000000000000000157211470420105600260100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "pcpbnumisc.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "pcpbnuarith.h" #include "gfpec/pcpecprime.h" #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) /* arithmetic over P-384r1 NIST modulus */ #define p384r1_add OWNAPI(p384r1_add) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_add, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p384r1_sub OWNAPI(p384r1_sub) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_sub, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p384r1_neg OWNAPI(p384r1_neg) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_neg, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p384r1_div_by_2 OWNAPI(p384r1_div_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_div_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p384r1_mul_by_2 OWNAPI(p384r1_mul_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_mul_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p384r1_mul_by_3 OWNAPI(p384r1_mul_by_3) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_mul_by_3, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #if(_IPP_ARCH ==_IPP_ARCH_EM64T) //BNU_CHUNK_T* p384r1_mul_montl(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE); //BNU_CHUNK_T* p384r1_sqr_montl(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); //BNU_CHUNK_T* p384r1_mul_montx(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE); //BNU_CHUNK_T* p384r1_sqr_montx(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); //BNU_CHUNK_T* p384r1_to_mont (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); //BNU_CHUNK_T* p384r1_mont_back(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); #endif #define p384r1_mred OWNAPI(p384r1_mred) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_mred, (BNU_CHUNK_T* res, BNU_CHUNK_T* product)) #if(_IPP_ARCH ==_IPP_ARCH_IA32) #define p384r1_mul_mont_slm OWNAPI(p384r1_mul_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_mul_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p384r1_sqr_mont_slm OWNAPI(p384r1_sqr_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p384r1_sqr_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #endif #define OPERAND_BITSIZE (384) #define LEN_P384 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* // multiplicative methods */ IPP_OWN_DEFN (static BNU_CHUNK_T*, p384r1_mul_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpMul_BNU_school(product, pA,LEN_P384, pB,LEN_P384); p384r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } IPP_OWN_DEFN (static BNU_CHUNK_T*, p384r1_sqr_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { BNU_CHUNK_T* product = gsModPoolAlloc((gsModEngine*)pGFE, 2); if(NULL == product) return NULL; cpSqr_BNU_school(product, pA,LEN_P384); p384r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } /* // Montgomery domain conversion constants */ static Ipp64u RR[] = { 0xfffffffe00000001,0x0000000200000000,0xfffffffe00000000, 0x0000000200000000,0x0000000000000001,0x0000000000000000 }; static BNU_CHUNK_T one[] = { #if(_IPP_ARCH == _IPP_ARCH_EM64T) 1,0,0,0,0,0}; #elif(_IPP_ARCH == _IPP_ARCH_IA32) 1,0,0,0,0,0,0,0,0,0,0,0}; #endif IPP_OWN_DEFN (static BNU_CHUNK_T*, p384r1_to_mont, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p384r1_mul_montl(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p384r1_mont_back, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p384r1_mul_montl(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #if (_ADCOX_NI_ENABLING_==_FEATURE_ON_) || (_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_) //BNU_CHUNK_T* p384r1_mul_montx(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) //BNU_CHUNK_T* p384r1_sqr_montx(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) #endif #if(_IPP_ARCH ==_IPP_ARCH_IA32) IPP_OWN_DEFN (static BNU_CHUNK_T*, p384r1_to_mont_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p384r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p384r1_mont_back_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p384r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #endif /* _IPP_ARCH ==_IPP_ARCH_IA32 */ /* // return specific gf p384r1 arith methods, // p384r1 = 2^384 -2^128 -2^96 +2^32 -1 (NIST P384r1) */ static gsModMethod* gsArithGF_p384r1 (void) { static gsModMethod m = { p384r1_to_mont, p384r1_mont_back, p384r1_mul_montl, p384r1_sqr_montl, NULL, p384r1_add, p384r1_sub, p384r1_neg, p384r1_div_by_2, p384r1_mul_by_2, p384r1_mul_by_3, }; #if(_IPP_ARCH==_IPP_ARCH_IA32) if(IsFeatureEnabled(ippCPUID_SSSE3|ippCPUID_MOVBE) && !IsFeatureEnabled(ippCPUID_AVX)) { m.mul = p384r1_mul_mont_slm; m.sqr = p384r1_sqr_mont_slm; m.encode = p384r1_to_mont_slm; m.decode = p384r1_mont_back_slm; } #endif return &m; } #endif /* (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) */ /*F* // Name: ippsGFpMethod_p384r1 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = 2^384 - 2^128 - 2^96 + 2^32 - 1 *F*/ IPPFUN(const IppsGFpMethod *, ippsGFpMethod_p384r1, (void)) { static IppsGFpMethod method = { cpID_PrimeP384r1, 384, secp384r1_p, NULL, NULL }; #if (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p384r1(); #else method.arith = gsArithGFp(); #endif #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { method.arith_alt = gsArithGF_p384r1_avx512(); } #endif return &method; } #undef LEN_P384 #undef OPERAND_BITSIZE cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_521r1.c000066400000000000000000000165021470420105600257770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "pcpbnuarith.h" #include "gfpec/pcpecprime.h" #include "gfpec/ecnist/ifma_arith_method_p521.h" //tbcd: temporary excluded: #include #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) /* arithmetic over P-521r1 NIST modulus */ #define p521r1_add OWNAPI(p521r1_add) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_add, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p521r1_sub OWNAPI(p521r1_sub) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_sub, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p521r1_neg OWNAPI(p521r1_neg) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_neg, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p521r1_div_by_2 OWNAPI(p521r1_div_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_div_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p521r1_mul_by_2 OWNAPI(p521r1_mul_by_2) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_mul_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #define p521r1_mul_by_3 OWNAPI(p521r1_mul_by_3) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_mul_by_3, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #if(_IPP_ARCH ==_IPP_ARCH_EM64T) //BNU_CHUNK_T* p521r1_to_mont (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); //BNU_CHUNK_T* p521r1_mont_back(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); //BNU_CHUNK_T* p521r1_mul_montl(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE); //BNU_CHUNK_T* p521r1_sqr_montl(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); //BNU_CHUNK_T* p521r1_mul_montx(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE); //BNU_CHUNK_T* p521r1_sqr_montx(BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE); #endif #define p521r1_mred OWNAPI(p521r1_mred) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_mred, (BNU_CHUNK_T* res, BNU_CHUNK_T* product)) #if(_IPP_ARCH ==_IPP_ARCH_IA32) #define p521r1_mul_mont_slm OWNAPI(p521r1_mul_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_mul_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) #define p521r1_sqr_mont_slm OWNAPI(p521r1_sqr_mont_slm) IPP_OWN_DECL (BNU_CHUNK_T*, p521r1_sqr_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #endif #define OPERAND_BITSIZE (521) #define LEN_P521 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* // multiplicative methods */ IPP_OWN_DEFN (static BNU_CHUNK_T*, p521r1_mul_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpMul_BNU_school(product, pA,LEN_P521, pB,LEN_P521); p521r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } IPP_OWN_DEFN (static BNU_CHUNK_T*, p521r1_sqr_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpSqr_BNU_school(product, pA,LEN_P521); p521r1_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } /* // Montgomery domain conversion constants */ static BNU_CHUNK_T RR[] = { #if(_IPP_ARCH == _IPP_ARCH_EM64T) 0x0000000000000000,0x0000400000000000,0x0000000000000000, 0x0000000000000000,0x0000000000000000,0x0000000000000000, 0x0000000000000000,0x0000000000000000,0x0000000000000000}; #elif(_IPP_ARCH == _IPP_ARCH_IA32) 0x00000000,0x00004000,0x00000000,0x00000000,0x00000000,0x00000000, 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, 0x00000000,0x00000000,0x00000000,0x00000000,0x00000000}; #endif static BNU_CHUNK_T one[] = { #if(_IPP_ARCH == _IPP_ARCH_EM64T) 1,0,0,0,0,0,0,0,0}; #elif(_IPP_ARCH == _IPP_ARCH_IA32) 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; #endif IPP_OWN_DEFN (static BNU_CHUNK_T*, p521r1_to_mont, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p521r1_mul_montl(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p521r1_mont_back, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p521r1_mul_montl(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #if (_ADCOX_NI_ENABLING_==_FEATURE_ON_) || (_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_) //BNU_CHUNK_T* p521r1_mul_montx(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) //BNU_CHUNK_T* p521r1_sqr_montx(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE) #endif #if(_IPP_ARCH ==_IPP_ARCH_IA32) IPP_OWN_DEFN (static BNU_CHUNK_T*, p521r1_to_mont_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p521r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, p521r1_mont_back_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return p521r1_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #endif /* _IPP_ARCH ==_IPP_ARCH_IA32*/ /* // return specific gf p521r1 arith methods, // p521r1 = 2^521 -1 (NIST P521r1) */ static gsModMethod* gsArithGF_p521r1 (void) { static gsModMethod m = { p521r1_to_mont, p521r1_mont_back, p521r1_mul_montl, p521r1_sqr_montl, NULL, p521r1_add, p521r1_sub, p521r1_neg, p521r1_div_by_2, p521r1_mul_by_2, p521r1_mul_by_3, }; #if(_IPP_ARCH==_IPP_ARCH_IA32) if(IsFeatureEnabled(ippCPUID_SSSE3|ippCPUID_MOVBE) && !IsFeatureEnabled(ippCPUID_AVX)) { m.mul = p521r1_mul_mont_slm; m.sqr = p521r1_sqr_mont_slm; m.encode = p521r1_to_mont_slm; m.decode = p521r1_mont_back_slm; } #endif return &m; } #endif /* (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) */ /*F* // Name: ippsGFpMethod_p521r1 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = 2^521 - 1 *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p521r1, (void) ) { static IppsGFpMethod method = { cpID_PrimeP521r1, 521, secp521r1_p, NULL, NULL }; #if (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p521r1(); #else method.arith = gsArithGFp(); #endif #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { method.arith_alt = gsArithGF_p521r1_avx512(); } #endif return &method; } #undef LEN_P521 #undef OPERAND_BITSIZE cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_com.c000066400000000000000000000025511470420105600260020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owncp.h" #include "gfpec/pcpgfpmethod.h" /*F* // Name: ippsGFpMethod_pArb // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). Arbitrary modulus q. *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_pArb, (void) ) { static IppsGFpMethod method = { cpID_Prime, 0, NULL, NULL, NULL }; method.arith = gsArithGFp(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmethod_sm2.c000066400000000000000000000160671470420105600257340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) methods // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpmethod.h" #include "gfpec/pcpecprime.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_method_sm2.h" #endif // (_IPP32E >= _IPP32E_K1) //tbcd: temporary excluded: #include #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) /* arithmetic over 256-bit SM2 modulus */ #define sm2_add OWNAPI(sm2_add) #define sm2_sub OWNAPI(sm2_sub) #define sm2_neg OWNAPI(sm2_neg) #define sm2_div_by_2 OWNAPI(sm2_div_by_2) #define sm2_mul_by_2 OWNAPI(sm2_mul_by_2) #define sm2_mul_by_3 OWNAPI(sm2_mul_by_3) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_add, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_sub, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_neg, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_div_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_mul_by_2, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_mul_by_3, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #if(_IPP_ARCH ==_IPP_ARCH_EM64T) #define sm2_mul_montl OWNAPI(sm2_mul_montl) #define sm2_mul_montx OWNAPI(sm2_mul_montx) #define sm2_sqr_montl OWNAPI(sm2_sqr_montl) #define sm2_sqr_montx OWNAPI(sm2_sqr_montx) #define sm2_to_mont OWNAPI(sm2_to_mont) #define sm2_mont_back OWNAPI(sm2_mont_back) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_mul_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_mul_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_sqr_montl, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_sqr_montx, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_to_mont, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_mont_back, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) #endif #if(_IPP_ARCH ==_IPP_ARCH_IA32) #define sm2_mul_mont_slm OWNAPI(sm2_mul_mont_slm) #define sm2_sqr_mont_slm OWNAPI(sm2_sqr_mont_slm) #define sm2_mred OWNAPI(sm2_mred) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_mul_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, gsEngine* pGFE)) IPP_OWN_DECL (BNU_CHUNK_T*, sm2_sqr_mont_slm, (BNU_CHUNK_T* res, const BNU_CHUNK_T* a, gsEngine* pGFE)) IPP_OWN_DECL (void, sm2_mred, (BNU_CHUNK_T* res, BNU_CHUNK_T* product)) #endif #define OPERAND_BITSIZE (256) #define LEN_SM2 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* // ia32 multiplicative methods */ #if (_IPP_ARCH ==_IPP_ARCH_IA32 ) IPP_OWN_DEFN (static BNU_CHUNK_T*, sm2_mul_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpMulAdc_BNU_school(product, pA, LEN_SM2, pB, LEN_SM2); sm2_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } IPP_OWN_DEFN (static BNU_CHUNK_T*, sm2_sqr_montl, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { BNU_CHUNK_T* product = cpGFpGetPool(2, pGFE); //tbcd: temporary excluded: assert(NULL!=product); cpSqrAdc_BNU_school(product, pA, LEN_SM2); sm2_mred(pR, product); cpGFpReleasePool(2, pGFE); return pR; } /* // Montgomery domain conversion constants */ static BNU_CHUNK_T RR[] = { 0x00000003,0x00000002, 0xffffffff,0x00000002, 0x00000001,0x00000001, 0x00000002,0x00000004}; static BNU_CHUNK_T one[] = { 1,0,0,0,0,0,0,0}; IPP_OWN_DEFN (static BNU_CHUNK_T*, sm2_to_mont, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return sm2_mul_montl(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, sm2_mont_back, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return sm2_mul_montl(pR, pA, (BNU_CHUNK_T*)one, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, sm2_to_mont_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return sm2_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)RR, pGFE); } IPP_OWN_DEFN (static BNU_CHUNK_T*, sm2_mont_back_slm, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFE)) { return sm2_mul_mont_slm(pR, pA, (BNU_CHUNK_T*)one, pGFE); } #endif /* _IPP >= _IPP_P8 */ /* // return specific gf p256sm2 arith methods, // p256sm2 = 2^256 -2^224 -2^96 +2^64 -1 (SM2 curve) */ static gsModMethod* gsArithGF_p256sm2 (void) { static gsModMethod m = { sm2_to_mont, sm2_mont_back, sm2_mul_montl, sm2_sqr_montl, NULL, sm2_add, sm2_sub, sm2_neg, sm2_div_by_2, sm2_mul_by_2, sm2_mul_by_3, }; #if(_IPP_ARCH==_IPP_ARCH_EM64T) && ((_ADCOX_NI_ENABLING_==_FEATURE_ON_) || (_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_)) if(IsFeatureEnabled(ippCPUID_ADCOX)) { m.mul = sm2_mul_montx; m.sqr = sm2_sqr_montx; } #endif #if(_IPP_ARCH==_IPP_ARCH_IA32) if(IsFeatureEnabled(ippCPUID_SSSE3|ippCPUID_MOVBE) && !IsFeatureEnabled(ippCPUID_AVX)) { m.mul = sm2_mul_mont_slm; m.sqr = sm2_sqr_mont_slm; m.encode = sm2_to_mont_slm; m.decode = sm2_mont_back_slm; } #endif return &m; } #endif /* (_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) */ /*F* // Name: ippsGFpMethod_p256sm2 // // Purpose: Returns a reference to an implementation of // arithmetic operations over GF(q). // // Returns: Pointer to a structure containing an implementation of arithmetic // operations over GF(q). q = 2^256 - 2^224 - 2^96 + 2^64 - 1 *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpMethod_p256sm2, (void) ) { static IppsGFpMethod method = { cpID_PrimeTPM_SM2, 256, tpmSM2_p256_p, NULL, NULL }; #if(_IPP >= _IPP_P8) || (_IPP32E >= _IPP32E_M7) method.arith = gsArithGF_p256sm2(); #else method.arith = gsArithGFp(); #endif #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { method.arith_alt = gsArithGF_psm2_avx512(); } #endif // (_IPP32E >= _IPP32E_K1) return &method; } #undef LEN_SM2 #undef OPERAND_BITSIZE cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmul.c000066400000000000000000000053261470420105600244640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpMul() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsGFpMul // // Purpose: Multiply of GF elements // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // NULL == pB // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pB Pointer to the context of the second finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpMul,(const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pB, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pB), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pB)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); GFP_METHOD(pGFE)->mul(GFPE_DATA(pR), GFPE_DATA(pA), GFPE_DATA(pB),pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpmulexp.c000066400000000000000000000112551470420105600251770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpMultiExp() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" //tbcd: temporary excluded: #include /*F* // Name: ippsGFpMultiExp // // Purpose: Multiplies exponents of GF elements // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == ppElmA // NULL == pR // NULL == ppE // // ippStsContextMatchErr invalid pGFp->idCtx // invalid ppElmA[i]->idCtx // invalid pR->idCtx // invalid ppE[i]->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr 1>nItems // nItems>6 // // ippStsNoErr no error // // Parameters: // ppElmA Pointer to the array of contexts of the finite field elements representing the base of the exponentiation. // ppE Pointer to the array of the Big Number contexts storing the exponents. // nItems Number of exponents. // pR Pointer to the context of the resulting element of the finite field. // pGFp Pointer to the context of the finite field. // pScratchBuffer Pointer to the scratch buffer. // *F*/ IPPFUN(IppStatus, ippsGFpMultiExp,(const IppsGFpElement* const ppElmA[], const IppsBigNumState* const ppE[], int nItems, IppsGFpElement* pR, IppsGFpState* pGFp, Ipp8u* pScratchBuffer)) { IPP_BAD_PTR2_RET(ppElmA, ppE); if(nItems==1) return ippsGFpExp(ppElmA[0], ppE[0], pR, pGFp, pScratchBuffer); else { /* test number of exponents */ IPP_BADARG_RET(1>nItems || nItems>IPP_MAX_EXPONENT_NUM, ippStsBadArgErr); IPP_BAD_PTR2_RET(pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { int n; gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFPE_ROOM(pR)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); /* test all ppElmA[] and ppE[] pairs */ for(n=0; nmul; BNU_CHUNK_T* pTmpR = cpGFpGetPool(1, pGFE); //tbcd: temporary excluded: assert(NULL!=pTmpR); cpGFpxExp(GFPE_DATA(pR), GFPE_DATA(ppElmA[0]), BN_NUMBER(ppE[0]), BN_SIZE(ppE[0]), pGFE, 0); for(n=1; nidCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pParentB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr pGFp does not specify prime field // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pParentB Pointer to the context of the second finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpMul_PE,(const IppsGFpElement* pA, const IppsGFpElement* pParentB, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pParentB, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pParentB), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFP_IS_BASIC(pGFE), ippStsBadArgErr ) IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); IPP_BADARG_RET( (GFPE_ROOM(pParentB)!=GFP_FELEN(GFP_PARENT(pGFE))), ippStsOutOfRangeErr); cpGFpxMul_GFE(GFPE_DATA(pR), GFPE_DATA(pA), GFPE_DATA(pParentB), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpneg.c000066400000000000000000000045121470420105600244340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpNeg() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpNeg // // Purpose: Additive inverse GF element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the source finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpNeg,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); GFP_METHOD(pGFE)->neg(GFPE_DATA(pR), GFPE_DATA(pA), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsetelem.c000066400000000000000000000056041470420105600253240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSetElement() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" //tbcd: temporary excluded: #include /*F* // Name: ippsGFpSetElement // // Purpose: Set GF Element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pR // NULL == pA && lenA>0 // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pR->idCtx // // ippStsSizeErr pA && !(0<=lenA && lenA= modulus // // ippStsNoErr no error // // Parameters: // pA pointer to the data representation Finite Field element // lenA length of Finite Field data representation array // pR pointer to Finite Field Element context // pGFp pointer to Finite Field context *F*/ IPPFUN(IppStatus, ippsGFpSetElement,(const Ipp32u* pA, int lenA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR2_RET(pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); IPP_BADARG_RET( !pA && (00 // // ippStsNotSupportedModeErr hashID is not supported // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pElm->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr !GFP_IS_BASIC(pGFE) // // ippStsLengthErr msgLen<0 // // ippStsNoErr no error // // Parameters: // pMsg pointer to the message is being hashed // msgLen length of the message above // pElm pointer to Finite Field Element context // pGFp pointer to Finite Field context // hashID applied hash algorithm ID *F*/ IPPFUN(IppStatus, ippsGFpSetElementHash,(const Ipp8u* pMsg, int msgLen, IppsGFpElement* pElm, IppsGFpState* pGFp, IppHashAlgId hashID)) { /* get algorithm id */ hashID = cpValidHashAlg(hashID); IPP_BADARG_RET(ippHashAlg_Unknown==hashID, ippStsNotSupportedModeErr); /* test message length and pointer */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); IPP_BAD_PTR2_RET(pElm, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr); IPP_BADARG_RET( !GFPE_VALID_ID(pElm), ippStsContextMatchErr); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr); IPP_BADARG_RET( GFPE_ROOM(pElm)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { Ipp8u md[MAX_HASH_SIZE]; BNU_CHUNK_T hashVal[(MAX_HASH_SIZE*8)/BITSIZE(BNU_CHUNK_T)+1]; /* +1 to meet cpMod_BNU() implementation specific */ IppStatus sts = ippsHashMessage(pMsg, msgLen, md, hashID); if(ippStsNoErr==sts) { int elemLen = GFP_FELEN(pGFE); int hashLen = cpHashAlgAttr[hashID].hashSize; int hashValLen = cpFromOctStr_BNU(hashVal, md, hashLen); hashValLen = cpMod_BNU(hashVal, hashValLen, GFP_MODULUS(pGFE), elemLen); cpGFpSet(GFPE_DATA(pElm), hashVal, hashValLen, pGFE); } return sts; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsetelemhashrmf.c000066400000000000000000000063661470420105600267030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSetElementHash_rmf // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsGFpSetElementHash_rmf // // Purpose: Set GF Element Hash of the Message // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pElm // NULL == pMsg if msgLen>0 // NULL = pMethod // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pElm->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr !GFP_IS_BASIC(pGFE) // // ippStsLengthErr msgLen<0 // // ippStsNoErr no error // // Parameters: // pMsg pointer to the message is being hashed // msgLen length of the message above // pElm pointer to Finite Field Element context // pGFp pointer to Finite Field context // pMethod pointer to hash method *F*/ IPPFUN(IppStatus, ippsGFpSetElementHash_rmf,(const Ipp8u* pMsg, int msgLen, IppsGFpElement* pElm, IppsGFpState* pGFp, const IppsHashMethod* pMethod)) { /* test method pointer */ IPP_BAD_PTR1_RET(pMethod); /* test message length and pointer */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); IPP_BAD_PTR2_RET(pElm, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr); IPP_BADARG_RET( !GFPE_VALID_ID(pElm), ippStsContextMatchErr); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr); IPP_BADARG_RET( GFPE_ROOM(pElm)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); { Ipp8u md[MAX_HASH_SIZE]; BNU_CHUNK_T hashVal[(MAX_HASH_SIZE*8)/BITSIZE(BNU_CHUNK_T)+1]; /* +1 to meet cpMod_BNU() implementation specific */ IppStatus sts = ippsHashMessage_rmf(pMsg, msgLen, md, pMethod); if(ippStsNoErr==sts) { int elemLen = GFP_FELEN(pGFE); int hashLen = pMethod->hashLen; int hashValLen = cpFromOctStr_BNU(hashVal, md, hashLen); hashValLen = cpMod_BNU(hashVal, hashValLen, GFP_MODULUS(pGFE), elemLen); cpGFpSet(GFPE_DATA(pElm), hashVal, hashValLen, pGFE); } return sts; } } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsetelemoctstr.c000066400000000000000000000064011470420105600265570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSetElementOctString() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpSetElementOctString // // Purpose: Set GF Element from the input octet string // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pR // NULL == pStr && strSize>0 // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pR->idCtx // // ippStsSizeErr !(0= modulus // // ippStsNoErr no error // // Parameters: // pStr Pointer to the octet string // strSize Size of the octet string buffer in bytes. // pR pointer to Finite Field Element context // pGFp pointer to Finite Field context *F*/ IPPFUN(IppStatus, ippsGFpSetElementOctString,(const Ipp8u* pStr, int strSize, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR2_RET(pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); IPP_BADARG_RET( (!pStr && 0idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsErr internal error caused by call of rndFunc() // // ippStsNoErr no error // // Parameters: // pR Pointer to the context of the finite field element. // pGFp Pointer to the context of the finite field. // rndFunc Pseudorandom number generator. // pRndParam Pointer to the context of the pseudorandom number generator. *F*/ IPPFUN(IppStatus, ippsGFpSetElementRandom,(IppsGFpElement* pR, IppsGFpState* pGFp, IppBitSupplier rndFunc, void* pRndParam)) { IPP_BAD_PTR3_RET(pR, pGFp, rndFunc); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFPE_ROOM(pR)!=GFP_FELEN(pGFE), ippStsOutOfRangeErr); return cpGFpxRand(GFPE_DATA(pR), pGFE, rndFunc, pRndParam)? ippStsNoErr : ippStsErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsetelemreg.c000066400000000000000000000037441470420105600260250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSetElementRegular() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpSetElement // // Purpose: Set GF Element from the input Big Number // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pR // NULL == pBN // // ippStsContextMatchErr invalid pBN->idCtx // // ippStsOutOfRangeErr BN is not positive // // ippStsNoErr no error // // Parameters: // pBN pointer to the Big Number context // pR pointer to Finite Field Element context // pGFp pointer to Finite Field context *F*/ IPPFUN(IppStatus, ippsGFpSetElementRegular,(const IppsBigNumState* pBN, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR1_RET(pBN); IPP_BADARG_RET( !BN_VALID_ID(pBN), ippStsContextMatchErr ); IPP_BADARG_RET( !BN_POSITIVE(pBN), ippStsOutOfRangeErr); return ippsGFpSetElement((Ipp32u*)BN_NUMBER(pBN), BITS2WORD32_SIZE( BITSIZE_BNU(BN_NUMBER((pBN)),BN_SIZE((pBN)))), pR, pGFp); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsqr.c000066400000000000000000000046221470420105600244720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSqr() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsGFpSqr // // Purpose: Square of GF element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the source finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpSqr,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); GFP_METHOD(pGFE)->sqr(GFPE_DATA(pR), GFPE_DATA(pA), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsqrt.c000066400000000000000000000051341470420105600246550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSqrt() // // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpSqrt // // Purpose: Square root of GF element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsDivByZeroErr pA is zero // // ippStsBadArgErr pGFp is not prime // // ippStsQuadraticNonResidueErr pA is a square non-residue // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the source finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpSqrt,(const IppsGFpElement* pA, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR3_RET(pA, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( !GFP_IS_BASIC(pGFE), ippStsBadArgErr ) IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); return cpGFpSqrt(GFPE_DATA(pR), GFPE_DATA(pA), pGFE)? ippStsNoErr : ippStsQuadraticNonResidueErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpstuff.h000066400000000000000000000171321470420105600250210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal GF(p) basic Definitions & Function Prototypes // */ #if !defined(_PCP_GFP_H_) #define _PCP_GFP_H_ #include "owncp.h" #include "gfpec/pcpgfpmethod.h" #include "pcpmontgomery.h" #include "pcpmask_ct.h" /* GF element */ typedef struct _cpGFpElement { Ipp32u idCtx; /* GF() element ident */ int length; /* length of element (in BNU_CHUNK_T) */ BNU_CHUNK_T* pData; } cpGFpElement; #define GFPE_SET_ID(pCtx) ((pCtx)->idCtx = (Ipp32u)idCtxGFPE ^ (Ipp32u)IPP_UINT_PTR(pCtx)) #define GFPE_ROOM(pCtx) ((pCtx)->length) #define GFPE_DATA(pCtx) ((pCtx)->pData) #define GFPE_VALID_ID(pCtx) ((((pCtx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR(pCtx)) == idCtxGFPE) /* GF(p) context */ typedef struct _cpGFp { Ipp32u idCtx; /* GFp spec ident */ cpModulusID modulusID; gsModEngine* pGFE; /* arithmetic engine */ } cpGFp; #define GFP_ALIGNMENT ((int)(sizeof(void*))) /* Local definitions */ #define GFP_MAX_BITSIZE (IPP_MAX_GF_BITSIZE) /* max bitsize for GF element */ #define GFP_POOL_SIZE (16)//(IPP_MAX_EXPONENT_NUM+3) /* num of elements into the pool */ #define GFP_RAND_ADD_BITS (128) /* parameter of random element generation ?? == febits/2 */ #define GFP_SET_ID(pCtx) ((pCtx)->idCtx = (Ipp32u)idCtxGFP ^ (Ipp32u)IPP_UINT_PTR(pCtx)) #define GFP_PMA(pCtx) ((pCtx)->pGFE) #define GFP_PARENT(pCtx) MOD_PARENT((pCtx)) #define GFP_EXTDEGREE(pCtx) MOD_EXTDEG((pCtx)) #define GFP_FEBITLEN(pCtx) MOD_BITSIZE((pCtx)) #define GFP_FELEN(pCtx) MOD_LEN((pCtx)) #define GFP_FELEN32(pCtx) MOD_LEN32((pCtx)) #define GFP_PELEN(pCtx) MOD_PELEN((pCtx)) #define GFP_METHOD(pCtx) MOD_METHOD((pCtx)) #define GFP_METHOD_ALT(pCtx) MOD_METHOD_ALT((pCtx)) #define GFP_MODULUS(pCtx) MOD_MODULUS((pCtx)) #define GFP_MNT_FACTOR(pCtx) MOD_MNT_FACTOR((pCtx)) #define GFP_MNT_R(pCtx) MOD_MNT_R((pCtx)) #define GFP_MNT_RR(pCtx) MOD_MNT_R2((pCtx)) #define GFP_HMODULUS(pCtx) MOD_HMODULUS((pCtx)) #define GFP_QNR(pCtx) MOD_QNR((pCtx)) #define GFP_POOL(pCtx) MOD_POOL_BUF((pCtx)) #define GFP_MAXPOOL(pCtx) MOD_MAXPOOL((pCtx)) #define GFP_USEDPOOL(pCtx) MOD_USEDPOOL((pCtx)) #define GFP_IS_BASIC(pCtx) (GFP_PARENT((pCtx))==NULL) #define GFP_VALID_ID(pCtx) ((((pCtx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR(pCtx)) == idCtxGFP) /* // get/release n element from/to the pool */ #define cpGFpGetPool(n, gfe) gsModPoolAlloc((gfe), (n)) #define cpGFpReleasePool(n, gfe) gsModPoolFree((gfe), (n)) __IPPCP_INLINE int cpGFpElementLen(const BNU_CHUNK_T* pE, int nsE) { for(; nsE>1 && 0==pE[nsE-1]; nsE--) ; return nsE; } __IPPCP_INLINE BNU_CHUNK_T* cpGFpElementCopy(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pE, int nsE) { int n; for(n=0; nadd(pR, pA, pB, pGFE); } __IPPCP_INLINE BNU_CHUNK_T* cpGFpSub(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsModEngine* pGFE) { return GFP_METHOD(pGFE)->sub(pR, pA, pB, pGFE); } __IPPCP_INLINE BNU_CHUNK_T* cpGFpNeg(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE) { return GFP_METHOD(pGFE)->neg(pR, pA, pGFE); } __IPPCP_INLINE BNU_CHUNK_T* cpGFpMul(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsModEngine* pGFE) { return GFP_METHOD(pGFE)->mul(pR, pA, pB, pGFE); } __IPPCP_INLINE BNU_CHUNK_T* cpGFpSqr(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE) { return GFP_METHOD(pGFE)->sqr(pR, pA, pGFE); } __IPPCP_INLINE BNU_CHUNK_T* cpGFpHalve(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE) { return GFP_METHOD(pGFE)->div2(pR, pA, pGFE); } #define GFP_EQ(a,b,size) (0 == cpCmp_BNU((a), (size), (b), (size))) #define GFP_IS_ZERO(a,size) cpGFpElementIsEquChunk((a),(size), 0) #define GFP_IS_ONE(a,size) cpGFpElementIsEquChunk((a),(size), 1) #define GFP_ZERO(a,size) cpGFpElementSetChunk((a),(size), 0) #define GFP_ONE(a,size) cpGFpElementSetChunk((a),(size), 1) /* construct GF element */ __IPPCP_INLINE IppsGFpElement* cpGFpElementConstruct(IppsGFpElement* pR, BNU_CHUNK_T* pDataBufer, int ns) { GFPE_SET_ID(pR); GFPE_ROOM(pR) = ns; GFPE_DATA(pR) = pDataBufer; return pR; } /* size of GFp context, init and setup */ #define cpGFpGetSize OWNAPI(cpGFpGetSize) IPP_OWN_DECL (int, cpGFpGetSize, (int feBitSize, int peBitSize, int numpe)) #define cpGFpInitGFp OWNAPI(cpGFpInitGFp) IPP_OWN_DECL (IppStatus, cpGFpInitGFp, (int primeBitSize, IppsGFpState* pGF)) #define cpGFpSetGFp OWNAPI(cpGFpSetGFp) IPP_OWN_DECL (IppStatus, cpGFpSetGFp, (const BNU_CHUNK_T* pPrime, int primeBitSize, const IppsGFpMethod* method, IppsGFpState* pGF)) /* operations */ #define cpGFpRand OWNAPI(cpGFpRand) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpRand, (BNU_CHUNK_T* pR, gsModEngine* pGFE, IppBitSupplier rndFunc, void* pRndParam)) #define cpGFpSet OWNAPI(cpGFpSet) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpSet, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pDataA, int nsA, gsModEngine* pGFE)) #define cpGFpGet OWNAPI(cpGFpGet) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpGet, (BNU_CHUNK_T* pDataA, int nsA, const BNU_CHUNK_T* pR, gsModEngine* pGFE)) #define cpGFpSetOctString OWNAPI(cpGFpSetOctString) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpSetOctString, (BNU_CHUNK_T* pR, const Ipp8u* pStr, int strSize, gsModEngine* pGFE)) #define cpGFpGetOctString OWNAPI(cpGFpGetOctString) IPP_OWN_DECL (Ipp8u*, cpGFpGetOctString, (Ipp8u* pStr, int strSize, const BNU_CHUNK_T* pA, gsModEngine* pGFE)) #define cpGFpInv OWNAPI(cpGFpInv) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpInv, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE)) #define cpGFpExp OWNAPI(cpGFpExp) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpExp, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pE, int nsE, gsModEngine* pGFE)) #define cpGFpSqrt OWNAPI(cpGFpSqrt) IPP_OWN_DECL (int, cpGFpSqrt, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFE)) #define cpGFEqnr OWNAPI(cpGFEqnr) IPP_OWN_DECL (void, cpGFEqnr, (gsModEngine* pGFE)) #endif /* _PCP_GFP_H_ */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsub.c000066400000000000000000000052361470420105600244600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSub() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpSub // // Purpose: Subtract of GF elements // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // NULL == pB // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pB Pointer to the context of the second finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpSub,(const IppsGFpElement* pA, const IppsGFpElement* pB, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pB, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pB), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pB)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); GFP_METHOD(pGFE)->sub(GFPE_DATA(pR), GFPE_DATA(pA), GFPE_DATA(pB), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpsubpe.c000066400000000000000000000056261470420105600250100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p). // // Context: // ippsGFpSub_PE() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpSub_PE // // Purpose: Subtract of GF element and parent GF element // // Returns: Reason: // ippStsNullPtrErr NULL == pGFp // NULL == pA // NULL == pR // NULL == pParentB // // ippStsContextMatchErr invalid pGFp->idCtx // invalid pA->idCtx // invalid pR->idCtx // invalid pParentB->idCtx // // ippStsOutOfRangeErr GFPE_ROOM() != GFP_FELEN() // // ippStsBadArgErr pGFp does not specify prime field // // ippStsNoErr no error // // Parameters: // pA Pointer to the context of the first finite field element. // pParentB Pointer to the context of the second finite field element. // pR Pointer to the context of the result finite field element. // pGFp Pointer to the context of the finite field. // *F*/ IPPFUN(IppStatus, ippsGFpSub_PE,(const IppsGFpElement* pA, const IppsGFpElement* pParentB, IppsGFpElement* pR, IppsGFpState* pGFp)) { IPP_BAD_PTR4_RET(pA, pParentB, pR, pGFp); IPP_BADARG_RET( !GFP_VALID_ID(pGFp), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pA), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pParentB), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pR), ippStsContextMatchErr ); { gsModEngine* pGFE = GFP_PMA(pGFp); IPP_BADARG_RET( GFP_IS_BASIC(pGFE), ippStsBadArgErr ) IPP_BADARG_RET( (GFPE_ROOM(pA)!=GFP_FELEN(pGFE)) || (GFPE_ROOM(pR)!=GFP_FELEN(pGFE)), ippStsOutOfRangeErr); IPP_BADARG_RET( (GFPE_ROOM(pParentB)!=GFP_FELEN(GFP_PARENT(pGFE))), ippStsOutOfRangeErr); cpGFpxSub_GFE(GFPE_DATA(pR), GFPE_DATA(pA), GFPE_DATA(pParentB), pGFE); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx.c000066400000000000000000000046061470420105600241360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p) ectension. // // Context: // pcpgfpec_initgfpxctx.c() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /* the "static" specificator removed because of incorrect result under Linux-32, p8 what's wrong? not know maybe compiler (icl 2017) need to check after switchng on icl 2018 */ /*static*/ IPP_OWN_DEFN (void, InitGFpxCtx, (const IppsGFpState* pGroundGF, int extDeg, const IppsGFpMethod* method, IppsGFpState* pGFpx)) { gsModEngine* pGFEp = GFP_PMA(pGroundGF); int elemLen = extDeg * GFP_FELEN(pGFEp); int elemLen32 = extDeg * GFP_FELEN32(pGFEp); Ipp8u* ptr = (Ipp8u*)pGFpx + sizeof(IppsGFpState); /* context identifier */ GFP_SET_ID(pGFpx); GFP_PMA(pGFpx) = (gsModEngine*)ptr; { gsModEngine* pGFEx = GFP_PMA(pGFpx); /* clear whole context */ PadBlock(0, ptr, sizeof(gsModEngine)); ptr += sizeof(gsModEngine); GFP_PARENT(pGFEx) = pGFEp; GFP_EXTDEGREE(pGFEx) = extDeg; GFP_FEBITLEN(pGFEx) = 0;//elemBitLen; GFP_FELEN(pGFEx) = elemLen; GFP_FELEN32(pGFEx) = elemLen32; GFP_PELEN(pGFEx) = elemLen; GFP_METHOD(pGFEx) = method->arith; GFP_MODULUS(pGFEx) = (BNU_CHUNK_T*)(ptr); ptr += elemLen * (Ipp32s)sizeof(BNU_CHUNK_T); /* field polynomial */ GFP_POOL(pGFEx) = (BNU_CHUNK_T*)(ptr); /* pool */ GFP_MAXPOOL(pGFEx) = GFPX_POOL_SIZE; GFP_USEDPOOL(pGFEx) = 0; cpGFpElementPad(GFP_MODULUS(pGFEx), elemLen, 0); } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_add_gfe.c000066400000000000000000000027041470420105600255640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxAdd_GFE() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxAdd_GFE, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pGroundB, gsModEngine* pGFEx)) { gsModEngine* pGroundGFE = GFP_PARENT(pGFEx); mod_add addF = MOD_METHOD(pGroundGFE)->add; if(pR != pA) { int groundElemLen = GFP_FELEN(pGroundGFE); int deg = GFP_EXTDEGREE(pGFEx); cpGFpElementCopy(pR+groundElemLen, pA+groundElemLen, groundElemLen*(deg-1)); } return addF(pR, pA, pGroundB, pGroundGFE); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_conj.c000066400000000000000000000025171470420105600251460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxConj() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxConj, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFEx)) { gsModEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); if(pR != pA) cpGFpElementCopy(pR, pA, groundElemLen); MOD_METHOD(pGroundGFE)->neg(pR+groundElemLen, pA+groundElemLen, pGroundGFE); return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_exp.c000066400000000000000000000116741470420105600250150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxExp() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" //tbcd: temporary excluded: #include static int div_upper(int a, int d) { return (a+d-1)/d; } /* sscm version */ IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxExp, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pE, int nsE, gsModEngine* pGFEx, Ipp8u* pScratchBuffer)) { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); /* remove leding zeros */ /* gres 06/10/2019: FIX_BNU(pE, nsE); */ { mod_mul mulF = GFP_METHOD(pGFEx)->mul; /* mul and sqr methods */ mod_sqr sqrF = GFP_METHOD(pGFEx)->sqr; BNU_CHUNK_T* pScratchAligned; /* aligned scratch buffer */ int nAllocation = 0; /* points from the pool */ /* size of element */ int elmLen = GFP_FELEN(pGFEx); /* exponent bitsize */ int expBitSize = nsE * BNU_CHUNK_BITS; /* gres 06/102019: BITSIZE_BNU(pE, nsE); */ /* optimal size of window */ int w = (NULL==pScratchBuffer)? 1 : cpGFpGetOptimalWinSize(expBitSize); /* number of table entries */ int nPrecomputed = 1<>shift) & dmask; /* initialize result */ //cpScrambleGet((Ipp8u*)pR, elmDataSize, pScratchAligned+windowVal, nPrecomputed); gsScrambleGet_sscm(pR, elmLen, pScratchAligned, (Ipp32s)windowVal, w); for(wPosition-=w; wPosition>=0; wPosition-=w) { int k; /* w times squaring */ for(k=0; k>shift) & dmask; /* extract value from the pre-computed table */ //cpScrambleGet((Ipp8u*)pTmp, elmDataSize, pScratchAligned+windowVal, nPrecomputed); gsScrambleGet_sscm(pTmp, elmLen, pScratchAligned, (Ipp32s)windowVal, w); /* and multiply */ mulF(pR, pR, pTmp, pGFEx); } } } cpGFpReleasePool(nAllocation+2, pGFEx); return pR; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_get.c000066400000000000000000000032531470420105600247720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxGet() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxGet, (BNU_CHUNK_T* pDataA, int nsA, const BNU_CHUNK_T* pE, gsModEngine* pGFEx)) { cpGFpElementPad(pDataA, nsA, 0); if( GFP_IS_BASIC(pGFEx) ) return cpGFpGet(pDataA, nsA, pE, pGFEx); else { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); int basicElemLen = GFP_FELEN(pBasicGFE); BNU_CHUNK_T* pTmp = pDataA; int basicDeg = cpGFpBasicDegreeExtension(pGFEx); int deg; for(deg=0; deg0; deg++) { int pieceA = IPP_MIN(nsA, basicElemLen); cpGFpGet(pTmp, pieceA, pE, pBasicGFE); pE += basicElemLen; pTmp += pieceA; nsA -= pieceA; } return pDataA; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_getpolyterm.c000066400000000000000000000023041470420105600265620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxGetPolyTerm() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxGetPolyTerm, (BNU_CHUNK_T* pDataA, int nsA, const BNU_CHUNK_T* pE, int deg, gsModEngine* pGFEx)) { pE += deg * GFP_FELEN(pGFEx); return cpGFpxGet(pDataA, nsA, pE, pGFEx); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_inv.c000066400000000000000000000156131470420105600250120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxInv() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" //tbcd: temporary excluded: #include static BNU_CHUNK_T* gfpxPolyDiv(BNU_CHUNK_T* pQ, BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsModEngine* pGFEx) { if( GFP_IS_BASIC(pGFEx) ) return NULL; else { int elemLen = GFP_FELEN(pGFEx); gsModEngine* pGroundGFE = GFP_PARENT(pGFEx); int termLen = GFP_FELEN(pGroundGFE); int degA = degree(pA, pGFEx); int degB = degree(pB, pGFEx); if(degB==0) { if( GFP_IS_ZERO(pB, termLen) ) return NULL; else { gsModEngine* pBasicGFE = cpGFpBasic(pGroundGFE); cpGFpInv(pR, pB, pBasicGFE); cpGFpElementPad(pR+GFP_FELEN(pGroundGFE), termLen-GFP_FELEN(pGroundGFE), 0); cpGFpxMul_GFE(pQ, pA, pR, pGFEx); cpGFpElementPad(pR, elemLen, 0); return pR; } } if(degA < degB) { cpGFpElementPad(pQ, elemLen, 0); cpGFpElementCopyPad(pR, elemLen, pA, (degA+1)*termLen); return pR; } else { mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; int i, j; BNU_CHUNK_T* pProduct = cpGFpGetPool(2, pGroundGFE); BNU_CHUNK_T* pInvB = pProduct + GFP_PELEN(pGroundGFE); //tbcd: temporary excluded: assert(NULL!=pProduct); cpGFpElementCopyPad(pR, elemLen, pA, (degA+1)*termLen); cpGFpElementPad(pQ, elemLen, 0); cpGFpxInv(pInvB, GFPX_IDX_ELEMENT(pB, degB, termLen), pGroundGFE); for(i=0; i<=degA-degB && !GFP_IS_ZERO(GFPX_IDX_ELEMENT(pR, degA-i, termLen), termLen); i++) { /* compute q term */ mulF(GFPX_IDX_ELEMENT(pQ, degA-degB-i, termLen), GFPX_IDX_ELEMENT(pR, degA-i, termLen), pInvB, pGroundGFE); /* R -= B * q */ cpGFpElementPad(GFPX_IDX_ELEMENT(pR, degA-i, termLen), termLen, 0); for(j=0; jmul; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; int termLen = GFP_FELEN(pGroundGFE); BNU_CHUNK_T* pInvB = cpGFpGetPool(2, pGroundGFE); BNU_CHUNK_T* pTmp = pInvB + GFP_PELEN(pGroundGFE); int degB = degree(pB, pGFEx); int i; //tbcd: temporary excluded: assert(NULL!=pInvB); cpGFpElementCopy(pR, GFP_MODULUS(pGFEx), elemLen); cpGFpElementPad(pQ, elemLen, 0); cpGFpxInv(pInvB, GFPX_IDX_ELEMENT(pB, degB, termLen), pGroundGFE); for(i=0; i 0) { gfpxPolyDiv(quo, temp, lastrem, rem, pGFEx); SWAP_PTR(BNU_CHUNK_T, rem, lastrem); // SWAP_PTR(BNU_CHUNK_T, temp, rem); GFP_METHOD(pGFEx)->neg(quo, quo, pGFEx); GFP_METHOD(pGFEx)->mul(temp, quo, aux, pGFEx); GFP_METHOD(pGFEx)->add(temp, lastaux, temp, pGFEx); SWAP_PTR(BNU_CHUNK_T, aux, lastaux); SWAP_PTR(BNU_CHUNK_T, temp, aux); } if (GFP_IS_ZERO(rem, elemLen)) { /* gcd != 1 */ cpGFpReleasePool(pxVars, pGFEx); return NULL; } { BNU_CHUNK_T* invRem = cpGFpGetPool(1, pGroundGFE); //tbcd: temporary excluded: assert(NULL!=invRem); cpGFpxInv(invRem, rem, pGroundGFE); cpGFpxMul_GFE(pR, aux, invRem, pGFEx); cpGFpReleasePool(1, pGroundGFE); } cpGFpReleasePool(pxVars, pGFEx); return pR; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_mul_gfe.c000066400000000000000000000027241470420105600256330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxMul_GFE() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxMul_GFE, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pGroundB, gsModEngine* pGFEx)) { gsModEngine* pGroundGFE = GFP_PARENT(pGFEx); mod_mul mulF = MOD_METHOD(pGroundGFE)->mul; int grounfElemLen = GFP_FELEN(pGroundGFE); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; deg static int GetIndex(const BNU_CHUNK_T* ppE[], int nItems, int nBit) { int shift = nBit%BYTESIZE; int offset= nBit/BYTESIZE; int index = 0; int n; for(n=nItems; n>0; n--) { const Ipp8u* pE = ((Ipp8u*)ppE[n-1]) + offset; Ipp8u e = pE[0]; index <<= 1; index += (e>>shift) &1; } return index; } static void cpPrecomputeMultiExp(BNU_CHUNK_T* pTable, const BNU_CHUNK_T* ppA[], int nItems, gsModEngine* pGFEx) { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); //int nPrecomputed = 1<mul; /* mul method */ int i, baseIdx; for(i=1, baseIdx=2; i=0; k--) { int tblIdx = baseIdx; int n; for(n=0; nmul; /* mul and sqr methods and parameter */ mod_sqr sqrF = GFP_METHOD(pGFEx)->sqr; int elmLen = GFP_FELEN(pGFEx); /* find out the longest exponent */ int expBitSize = cpGetMaxBitsizeExponent(ppE, nsE, nItems); /* allocate resource and copy expanded exponents into */ const BNU_CHUNK_T* ppExponent[IPP_MAX_EXPONENT_NUM]; { int n; for(n=0; n=0; expBitSize--) { sqrF(pR, pR, pGFEx); tblIdx = GetIndex(ppExponent, nItems, expBitSize); //cpScrambleGet((Ipp8u*)pT, elmDataSize, pScratchBuffer+tblIdx, nPrecomputed); gsScrambleGet_sscm(pT, elmLen, pTable, tblIdx, nItems); mulF(pR, pR, pT, pGFEx); } /* release resource */ cpGFpReleasePool(1, pGFEx); } /* release resource */ cpGFpReleasePool(nItems, pGFEx); return pR; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_neg.c000066400000000000000000000026541470420105600247700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxNeg() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxNeg, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pGFEx)) { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degneg(pTmp, pA, pBasicGFE); pTmp += basicElemLen; pA += basicElemLen; } return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpx_rand.c000066400000000000000000000031341470420105600251350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Internal operations over GF(p) extension. // // Context: // cpGFpxRand() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "gfpec/pcpgfpxstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxRand, (BNU_CHUNK_T* pR, gsModEngine* pGFEx, IppBitSupplier rndFunc, void* pRndParam)) { if( GFP_IS_BASIC(pGFEx) ) return cpGFpRand(pR, pGFEx, rndFunc, pRndParam); else { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degsub; if(pR != pA) { int groundElemLen = GFP_FELEN(pGroundGFE); int deg = GFP_EXTDEGREE(pGFEx); cpGFpElementCopy(pR+groundElemLen, pA+groundElemLen, groundElemLen*(deg-1)); } return subF(pR, pA, pGroundB, pGroundGFE); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxgetsize.c000066400000000000000000000055331470420105600255310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p) ectension. // // Context: // pcpgfpxgetsize.c() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /* Get context size */ static int cpGFExGetSize(int elemLen, int pelmLen, int numpe) { int ctxSize = 0; /* size of GFp engine */ ctxSize = (Ipp32s)sizeof(gsModEngine) + elemLen*(Ipp32s)sizeof(BNU_CHUNK_T) /* modulus */ + pelmLen*(Ipp32s)sizeof(BNU_CHUNK_T)*numpe; /* pool */ ctxSize = (Ipp32s)sizeof(IppsGFpState) /* size of IppsGFPState*/ + ctxSize; /* GFpx engine */ return ctxSize; } /*F* // Name: ippsGFpxGetSize // // Purpose: Gets the size of the context of a GF(p^d) field. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL. // ippStsContextMatchErr !GFP_VALID_ID(pGroundGF) // ippStsBadArgErr degree is greater than or equal to 9 or is less than 2. // ippStsNoErr no error // // Parameters: // pGroundGF Pointer to the context of the finite field GF(p) being extended. // degree Degree of the extension. // pSize Pointer to the buffer size, in bytes, needed for the IppsGFpState // context. // *F*/ IPPFUN(IppStatus, ippsGFpxGetSize, (const IppsGFpState* pGroundGF, int degree, int* pSize)) { IPP_BAD_PTR2_RET(pGroundGF, pSize); IPP_BADARG_RET( degreeIPP_MAX_GF_EXTDEG, ippStsBadArgErr); IPP_BADARG_RET( !GFP_VALID_ID(pGroundGF), ippStsContextMatchErr ); #define MAX_GFx_SIZE (1<<15) /* max size (bytes) of GF element (32KB) */ { int groundElmLen = GFP_FELEN(GFP_PMA(pGroundGF)); Ipp64u elmLen64 = (Ipp64u)groundElmLen * (Ipp64u)sizeof(BNU_CHUNK_T) * (Ipp64u)degree; int elemLen = (int)IPP_LODWORD(elmLen64); *pSize = 0; IPP_BADARG_RET(elmLen64> MAX_GFx_SIZE, ippStsBadArgErr); *pSize = cpGFExGetSize(elemLen, elemLen, GFPX_POOL_SIZE); return ippStsNoErr; } #undef MAX_GFx_SIZE } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxinit.c000066400000000000000000000101731470420105600250160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Operations over GF(p) ectension. // // Context: // pcpgfpxinit.c() // */ #include "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpxstuff.h" #include "pcptool.h" /*F* // Name: ippsGFpxInit // // Purpose: initializes finite field extension GF(p^d) // // Returns: Reason: // ippStsNullPtrErr NULL == pGFpx // NULL == pGroundGF // NULL == ppGroundElm // NULL == pGFpMethod // // ippStsContextMatchErr incorrect pGroundGF's context ID // incorrect ppGroundElm[i]'s context ID // // ippStsOutOfRangeErr size of ppGroundElm[i] does not equal to size of pGroundGF element // // ippStsBadArgErr IPP_MIN_GF_EXTDEG > extDeg || extDeg > IPP_MAX_GF_EXTDEG // (IPP_MIN_GF_EXTDEG==2, IPP_MAX_GF_EXTDEG==8) // 1>nElm || nElm>extDeg // // cpID_Poly!=pGFpMethod->modulusID -- method does not reference the polynomial one // pGFpMethod->modulusBitDeg!=extDeg -- fixed method does not match to degree extension // // ippStsNoErr no error // // Parameters: // pGroundGF pointer to the context of the finite field is being extension // extDeg degree of extension // ppGroundElm[] pointer to the array of extension field polynomial // nElm number of coefficients above // pGFpMethod pointer to the basic arithmetic methods // pGFpx pointer to Finite Field context is being initialized *F*/ IPPFUN(IppStatus, ippsGFpxInit,(const IppsGFpState* pGroundGF, int extDeg, const IppsGFpElement* const ppGroundElm[], int nElm, const IppsGFpMethod* pGFpMethod, IppsGFpState* pGFpx)) { IPP_BAD_PTR4_RET(pGFpx, pGroundGF, ppGroundElm, pGFpMethod); IPP_BADARG_RET( !GFP_VALID_ID(pGroundGF), ippStsContextMatchErr ); /* test extension degree */ IPP_BADARG_RET( extDegIPP_MAX_GF_EXTDEG, ippStsBadArgErr); /* coeffs at (x^0), (x^1), ..., (x^(deg-1)) passed actually */ /* considering normilized f(x), the coeff at (x^deg) is 1 and so could neither stored no passed */ /* test if 1<=nElm<=extDeg */ IPP_BADARG_RET( 1>nElm || nElm>extDeg, ippStsBadArgErr); /* test if method is polynomial based */ IPP_BADARG_RET(cpID_Poly != (pGFpMethod->modulusID & cpID_Poly), ippStsBadArgErr); /* test if method is fixed polynomial based */ IPP_BADARG_RET(pGFpMethod->modulusBitDeg && (pGFpMethod->modulusBitDeg!=extDeg), ippStsBadArgErr); InitGFpxCtx(pGroundGF, extDeg, pGFpMethod, pGFpx); { BNU_CHUNK_T* pPoly = GFP_MODULUS(GFP_PMA(pGFpx)); int polyTermlen = GFP_FELEN(GFP_PMA(pGroundGF)); int n; for(n=0; n extDeg || extDeg > IPP_MAX_GF_EXTDEG // (IPP_MIN_GF_EXTDEG==2, IPP_MAX_GF_EXTDEG==8) // // cpID_Poly!=pGFpMethod->modulusID -- method does not reference the polynomial one // pGFpMethod->modulusBitDeg!=extDeg -- fixed method does not match to degree extension // // ippStsNoErr no error // // Parameters: // pGroundGF pointer to the context of the finite field is being extension // extDeg degree of extension // pGroundElm pointer to the IppsGFpElement context containing the trailing coefficient of the field binomial. // pGFpMethod pointer to the basic arithmetic methods // pGFpx pointer to Finite Field context is being initialized *F*/ IPPFUN(IppStatus, ippsGFpxInitBinomial,(const IppsGFpState* pGroundGF, int extDeg, const IppsGFpElement* pGroundElm, const IppsGFpMethod* pGFpMethod, IppsGFpState* pGFpx)) { IPP_BAD_PTR4_RET(pGFpx, pGroundGF, pGroundElm, pGFpMethod); IPP_BADARG_RET( !GFP_VALID_ID(pGroundGF), ippStsContextMatchErr ); IPP_BADARG_RET( !GFPE_VALID_ID(pGroundElm), ippStsContextMatchErr ); IPP_BADARG_RET(GFPE_ROOM(pGroundElm)!=GFP_FELEN(GFP_PMA(pGroundGF)), ippStsOutOfRangeErr); IPP_BADARG_RET( extDegIPP_MAX_GF_EXTDEG, ippStsBadArgErr); /* test method is binomial based */ IPP_BADARG_RET(cpID_Binom != (pGFpMethod->modulusID & cpID_Binom), ippStsBadArgErr); /* test if method assumes fixed degree extension */ IPP_BADARG_RET(pGFpMethod->modulusBitDeg && (extDeg!=pGFpMethod->modulusBitDeg), ippStsBadArgErr); /* init context */ InitGFpxCtx(pGroundGF, extDeg, pGFpMethod, pGFpx); /* store low-order coefficient of irresucible into the context */ cpGFpElementCopy(GFP_MODULUS(GFP_PMA(pGFpx)), GFPE_DATA(pGroundElm), GFP_FELEN(GFP_PMA(pGroundGF))); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom.c000066400000000000000000000065051470420105600265230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods, if binomial generator // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" //tbcd: temporary excluded: #include /* // Multiplication in GF(p^d), if field polynomial: g(x) = x^d + beta => binominal */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxMul_pd_binom, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { BNU_CHUNK_T* pGFpolynomial = GFP_MODULUS(pGFEx); int deg = GFP_EXTDEGREE(pGFEx); int elemLen= GFP_FELEN(pGFEx); int groundElemLen = GFP_FELEN(GFP_PARENT(pGFEx)); int d; BNU_CHUNK_T* R = cpGFpGetPool(4, pGFEx); BNU_CHUNK_T* X = R+elemLen; BNU_CHUNK_T* T0= X+elemLen; BNU_CHUNK_T* T1= T0+elemLen; //tbcd: temporary excluded: assert(NULL!=R); /* T0 = A * beta */ cpGFpxMul_GFE(T0, pA, pGFpolynomial, pGFEx); /* T1 = A */ cpGFpElementCopy(T1, pA, elemLen); /* R = A * B[0] */ cpGFpxMul_GFE(R, pA, pB, pGFEx); /* R += (A*B[d]) mod g() */ for(d=1; dadd(R, R, X, pGFEx); } cpGFpElementCopy(pR, R, elemLen); cpGFpReleasePool(4, pGFEx); return pR; } /* // Squaring in GF(p^d), if field polynomial: g(x) = x^d + beta => binominal */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxSqr_pd_binom, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { #if defined(__INTEL_COMPILER) #pragma noinline #endif return cpGFpxMul_pd_binom(pR, pA, pA, pGFEx); } /* // return specific polynomial arith methods // polynomial - general binomial */ static gsModMethod* gsPolyArith_binom (void) { static gsModMethod m = { cpGFpxEncode_com, cpGFpxDecode_com, cpGFpxMul_pd_binom, cpGFpxSqr_pd_binom, NULL, cpGFpxAdd_com, cpGFpxSub_com, cpGFpxNeg_com, cpGFpxDiv2_com, cpGFpxMul2_com, cpGFpxMul3_com, //cpGFpxInv }; return &m; } /*F* // Name: ippsGFpxMethod_binom2 // // Purpose: Returns a reference to the implementation of arithmetic operations over GF(pd). // // Returns: pointer to a structure containing // an implementation of arithmetic operations over GF(pd) // g(x) = x^d - a0, a0 from GF(p) // // *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpxMethod_binom, (void) ) { static IppsGFpMethod method = { cpID_Binom, 0, NULL, NULL, NULL }; method.arith = gsPolyArith_binom(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom2.c000066400000000000000000000126671470420105600266130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods, if binomial generator // */ #include "owncp.h" #include "gfpec/pcpgfpxmethod_binom_mulc.h" #include "gfpec/pcpgfpxmethod_com.h" //tbcd: temporary excluded: #include /* // Multiplication in GF(p^2), if field polynomial: g(x) = x^2 + beta => binominal */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxMul_p2_binom, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; const BNU_CHUNK_T* pB0 = pB; const BNU_CHUNK_T* pB1 = pB+groundElemLen; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* t0 = cpGFpGetPool(4, pGroundGFE); BNU_CHUNK_T* t1 = t0+groundElemLen; BNU_CHUNK_T* t2 = t1+groundElemLen; BNU_CHUNK_T* t3 = t2+groundElemLen; //tbcd: temporary excluded: assert(NULL!=t0); #if defined GS_DBG BNU_CHUNK_T* arg0 = cpGFpGetPool(1, pGroundGFE); BNU_CHUNK_T* arg1 = cpGFpGetPool(1, pGroundGFE); #endif #if defined GS_DBG cpGFpxGet(arg0, groundElemLen, pA0, pGroundGFE); cpGFpxGet(arg1, groundElemLen, pB0, pGroundGFE); #endif mulF(t0, pA0, pB0, pGroundGFE); /* t0 = a[0]*b[0] */ #if defined GS_DBG cpGFpxGet(arg0, groundElemLen, pA1, pGroundGFE); cpGFpxGet(arg1, groundElemLen, pB1, pGroundGFE); #endif mulF(t1, pA1, pB1, pGroundGFE); /* t1 = a[1]*b[1] */ addF(t2, pA0, pA1, pGroundGFE); /* t2 = a[0]+a[1] */ addF(t3, pB0, pB1, pGroundGFE); /* t3 = b[0]+b[1] */ #if defined GS_DBG cpGFpxGet(arg0, groundElemLen, t2, pGroundGFE); cpGFpxGet(arg1, groundElemLen, t3, pGroundGFE); #endif mulF(pR1, t2, t3, pGroundGFE); /* r[1] = (a[0]+a[1]) * (b[0]+b[1]) */ subF(pR1, pR1, t0, pGroundGFE); /* r[1] -= a[0]*b[0]) + a[1]*b[1] */ subF(pR1, pR1, t1, pGroundGFE); cpGFpxMul_G0(t1, t1, pGFEx); subF(pR0, t0, t1, pGroundGFE); #if defined GS_DBG cpGFpReleasePool(2, pGroundGFE); #endif cpGFpReleasePool(4, pGroundGFE); return pR; } /* // Squaring in GF(p^2), if field polynomial: g(x) = x^2 + beta => binominal */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxSqr_p2_binom, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGroundGFE)->sqr; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* t0 = cpGFpGetPool(3, pGroundGFE); BNU_CHUNK_T* t1 = t0+groundElemLen; BNU_CHUNK_T* u0 = t1+groundElemLen; //tbcd: temporary excluded: assert(NULL!=t0); #if defined GS_DBG BNU_CHUNK_T* arg0 = cpGFpGetPool(1, pGroundGFE); BNU_CHUNK_T* arg1 = cpGFpGetPool(1, pGroundGFE); #endif #if defined GS_DBG cpGFpxGet(arg0, groundElemLen, pA0, pGroundGFE); cpGFpxGet(arg1, groundElemLen, pA1, pGroundGFE); #endif mulF(u0, pA0, pA1, pGroundGFE); /* u0 = a[0]*a[1] */ sqrF(t0, pA0, pGroundGFE); /* t0 = a[0]*a[0] */ sqrF(t1, pA1, pGroundGFE); /* t1 = a[1]*a[1] */ cpGFpxMul_G0(t1, t1, pGFEx); subF(pR0, t0, t1, pGroundGFE); addF(pR1, u0, u0, pGroundGFE); /* r[1] = 2*a[0]*a[1] */ #if defined GS_DBG cpGFpReleasePool(2, pGroundGFE); #endif cpGFpReleasePool(3, pGroundGFE); return pR; } /* // return specific polynomi alarith methods // polynomial - deg 2 binomial */ static gsModMethod* gsPolyArith_binom2 (void) { static gsModMethod m = { cpGFpxEncode_com, cpGFpxDecode_com, cpGFpxMul_p2_binom, cpGFpxSqr_p2_binom, NULL, cpGFpxAdd_com, cpGFpxSub_com, cpGFpxNeg_com, cpGFpxDiv2_com, cpGFpxMul2_com, cpGFpxMul3_com, //cpGFpxInv }; return &m; } /*F* // Name: ippsGFpxMethod_binom2 // // Purpose: Returns a reference to the implementation of arithmetic operations over GF(pd). // // Returns: pointer to a structure containing // an implementation of arithmetic operations over GF(pd) // g(x) = x^2 - a0, a0 from GF(p) // // *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpxMethod_binom2, (void) ) { static IppsGFpMethod method = { cpID_Binom, 2, NULL, NULL, NULL }; method.arith = gsPolyArith_binom2(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom3.c000066400000000000000000000141441470420105600266040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods, if binomial generator // */ #include "owncp.h" #include "gfpec/pcpgfpxmethod_binom_mulc.h" #include "gfpec/pcpgfpxmethod_com.h" //tbcd: temporary excluded: #include /* // Multiplication in GF(p^3), if field polynomial: g(x) = x^3 + beta => binominal */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxMul_p3_binom, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; const BNU_CHUNK_T* pA2 = pA+groundElemLen*2; const BNU_CHUNK_T* pB0 = pB; const BNU_CHUNK_T* pB1 = pB+groundElemLen; const BNU_CHUNK_T* pB2 = pB+groundElemLen*2; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* pR2 = pR+groundElemLen*2; BNU_CHUNK_T* t0 = cpGFpGetPool(6, pGroundGFE); BNU_CHUNK_T* t1 = t0+groundElemLen; BNU_CHUNK_T* t2 = t1+groundElemLen; BNU_CHUNK_T* u0 = t2+groundElemLen; BNU_CHUNK_T* u1 = u0+groundElemLen; BNU_CHUNK_T* u2 = u1+groundElemLen; //tbcd: temporary excluded: assert(NULL!=t0); addF(u0 ,pA0, pA1, pGroundGFE); /* u0 = a[0]+a[1] */ addF(t0 ,pB0, pB1, pGroundGFE); /* t0 = b[0]+b[1] */ mulF(u0, u0, t0, pGroundGFE); /* u0 = (a[0]+a[1])*(b[0]+b[1]) */ mulF(t0, pA0, pB0, pGroundGFE); /* t0 = a[0]*b[0] */ addF(u1 ,pA1, pA2, pGroundGFE); /* u1 = a[1]+a[2] */ addF(t1 ,pB1, pB2, pGroundGFE); /* t1 = b[1]+b[2] */ mulF(u1, u1, t1, pGroundGFE); /* u1 = (a[1]+a[2])*(b[1]+b[2]) */ mulF(t1, pA1, pB1, pGroundGFE); /* t1 = a[1]*b[1] */ addF(u2 ,pA2, pA0, pGroundGFE); /* u2 = a[2]+a[0] */ addF(t2 ,pB2, pB0, pGroundGFE); /* t2 = b[2]+b[0] */ mulF(u2, u2, t2, pGroundGFE); /* u2 = (a[2]+a[0])*(b[2]+b[0]) */ mulF(t2, pA2, pB2, pGroundGFE); /* t2 = a[2]*b[2] */ subF(u0, u0, t0, pGroundGFE); /* u0 = a[0]*b[1]+a[1]*b[0] */ subF(u0, u0, t1, pGroundGFE); subF(u1, u1, t1, pGroundGFE); /* u1 = a[1]*b[2]+a[2]*b[1] */ subF(u1, u1, t2, pGroundGFE); subF(u2, u2, t2, pGroundGFE); /* u2 = a[2]*b[0]+a[0]*b[2] */ subF(u2, u2, t0, pGroundGFE); cpGFpxMul_G0(u1, u1, pGFEx); /* u1 = (a[1]*b[2]+a[2]*b[1]) * beta */ cpGFpxMul_G0(t2, t2, pGFEx); /* t2 = a[2]*b[2] * beta */ subF(pR0, t0, u1, pGroundGFE); /* r[0] = a[0]*b[0] - (a[2]*b[1]+a[1]*b[2])*beta */ subF(pR1, u0, t2, pGroundGFE); /* r[1] = a[1]*b[0] + a[0]*b[1] - a[2]*b[2]*beta */ addF(pR2, u2, t1, pGroundGFE); /* r[2] = a[2]*b[0] + a[1]*b[1] + a[0]*b[2] */ cpGFpReleasePool(6, pGroundGFE); return pR; } /* // Squaring in GF(p^3), if field polynomial: g(x) = x^3 + beta => binominal */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxSqr_p3_binom, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGroundGFE)->sqr; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; const BNU_CHUNK_T* pA2 = pA+groundElemLen*2; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* pR2 = pR+groundElemLen*2; BNU_CHUNK_T* s0 = cpGFpGetPool(5, pGroundGFE); BNU_CHUNK_T* s1 = s0+groundElemLen; BNU_CHUNK_T* s2 = s1+groundElemLen; BNU_CHUNK_T* s3 = s2+groundElemLen; BNU_CHUNK_T* s4 = s3+groundElemLen; //tbcd: temporary excluded: assert(NULL!=s0); addF(s2, pA0, pA2, pGroundGFE); subF(s2, s2, pA1, pGroundGFE); sqrF(s2, s2, pGroundGFE); sqrF(s0, pA0, pGroundGFE); sqrF(s4, pA2, pGroundGFE); mulF(s1, pA0, pA1, pGroundGFE); mulF(s3, pA1, pA2, pGroundGFE); addF(s1, s1, s1, pGroundGFE); addF(s3, s3, s3, pGroundGFE); addF(pR2, s1, s2, pGroundGFE); addF(pR2, pR2, s3, pGroundGFE); subF(pR2, pR2, s0, pGroundGFE); subF(pR2, pR2, s4, pGroundGFE); cpGFpxMul_G0(s4, s4, pGFEx); subF(pR1, s1, s4, pGroundGFE); cpGFpxMul_G0(s3, s3, pGFEx); subF(pR0, s0, s3, pGroundGFE); cpGFpReleasePool(5, pGroundGFE); return pR; } /* // return specific polynomi alarith methods // polynomial - deg 3 binomial */ static gsModMethod* gsPolyArith_binom3 (void) { static gsModMethod m = { cpGFpxEncode_com, cpGFpxDecode_com, cpGFpxMul_p3_binom, cpGFpxSqr_p3_binom, NULL, cpGFpxAdd_com, cpGFpxSub_com, cpGFpxNeg_com, cpGFpxDiv2_com, cpGFpxMul2_com, cpGFpxMul3_com, //cpGFpxInv }; return &m; } /*F* // Name: ippsGFpxMethod_binom2 // // Purpose: Returns a reference to the implementation of arithmetic operations over GF(pd). // // Returns: pointer to a structure containing // an implementation of arithmetic operations over GF(pd) // g(x) = x^3 - a0, a0 from GF(p) // // *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpxMethod_binom3, (void) ) { static IppsGFpMethod method = { cpID_Binom, 3, NULL, NULL, NULL }; method.arith = gsPolyArith_binom3(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom3_epid2.c000066400000000000000000000202531470420105600276650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods, if binomial generator over GF((p^2)^3) // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" #include "gfpec/pcpgfpxmethod_binom_epid2.h" //tbcd: temporary excluded: #include /* // Intel(R) Enhanced Privacy ID (Intel(R) EPID) 2.0 specific. // // Intel(R) EPID 2.0 uses the following finite field hierarchy: // // 1) prime field GF(p), // p = 0xFFFFFFFFFFFCF0CD46E5F25EEE71A49F0CDC65FB12980A82D3292DDBAED33013 // // 2) 2-degree extension of GF(p): GF(p^2) == GF(p)[x]/g(x), g(x) = x^2 -beta, // beta =-1 mod p, so "beta" represents as {1} // // 3) 3-degree extension of GF(p^2) ~ GF(p^6): GF((p^2)^3) == GF(p)[v]/g(v), g(v) = v^3 -xi, // xi belongs GF(p^2), xi=x+2, so "xi" represents as {2,1} ---- "2" is low- and "1" is high-order coefficients // // 4) 2-degree extension of GF((p^2)^3) ~ GF(p^12): GF(((p^2)^3)^2) == GF(p)[w]/g(w), g(w) = w^2 -vi, // psi belongs GF((p^2)^3), vi=0*v^2 +1*v +0, so "vi" represents as {0,1,0}---- "0", '1" and "0" are low-, middle- and high-order coefficients // // See representations in t_gfpparam.cpp // */ /* // Intel(R) EPID 2.0 specific // ~~~~~~~~~~~~~~~ // // Multiplication over GF((p^2)^3) // - field polynomial: g(v) = v^3 - xi => binominal with specific value of "xi" // - xi = x+2 */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxMul_p3_binom_epid2, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; const BNU_CHUNK_T* pA2 = pA+groundElemLen*2; const BNU_CHUNK_T* pB0 = pB; const BNU_CHUNK_T* pB1 = pB+groundElemLen; const BNU_CHUNK_T* pB2 = pB+groundElemLen*2; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* pR2 = pR+groundElemLen*2; BNU_CHUNK_T* t0 = cpGFpGetPool(6, pGroundGFE); BNU_CHUNK_T* t1 = t0+groundElemLen; BNU_CHUNK_T* t2 = t1+groundElemLen; BNU_CHUNK_T* u0 = t2+groundElemLen; BNU_CHUNK_T* u1 = u0+groundElemLen; BNU_CHUNK_T* u2 = u1+groundElemLen; //tbcd: temporary excluded: assert(NULL!=t0); addF(u0 ,pA0, pA1, pGroundGFE); /* u0 = a[0]+a[1] */ addF(t0 ,pB0, pB1, pGroundGFE); /* t0 = b[0]+b[1] */ mulF(u0, u0, t0, pGroundGFE); /* u0 = (a[0]+a[1])*(b[0]+b[1]) */ mulF(t0, pA0, pB0, pGroundGFE); /* t0 = a[0]*b[0] */ addF(u1 ,pA1, pA2, pGroundGFE); /* u1 = a[1]+a[2] */ addF(t1 ,pB1, pB2, pGroundGFE); /* t1 = b[1]+b[2] */ mulF(u1, u1, t1, pGroundGFE); /* u1 = (a[1]+a[2])*(b[1]+b[2]) */ mulF(t1, pA1, pB1, pGroundGFE); /* t1 = a[1]*b[1] */ addF(u2 ,pA2, pA0, pGroundGFE); /* u2 = a[2]+a[0] */ addF(t2 ,pB2, pB0, pGroundGFE); /* t2 = b[2]+b[0] */ mulF(u2, u2, t2, pGroundGFE); /* u2 = (a[2]+a[0])*(b[2]+b[0]) */ mulF(t2, pA2, pB2, pGroundGFE); /* t2 = a[2]*b[2] */ subF(u0, u0, t0, pGroundGFE); /* u0 = a[0]*b[1]+a[1]*b[0] */ subF(u0, u0, t1, pGroundGFE); subF(u1, u1, t1, pGroundGFE); /* u1 = a[1]*b[2]+a[2]*b[1] */ subF(u1, u1, t2, pGroundGFE); subF(u2, u2, t2, pGroundGFE); /* u2 = a[2]*b[0]+a[0]*b[2] */ subF(u2, u2, t0, pGroundGFE); /* Intel(R) EPID 2.0 specific */ { int basicExtDegree = cpGFpBasicDegreeExtension(pGFEx); /* deal with GF(p^2^3) */ if(basicExtDegree==6) { cpFq2Mul_xi(u1, u1, pGroundGFE); cpFq2Mul_xi(t2, t2, pGroundGFE); addF(pR0, t0, u1, pGroundGFE); /* r[0] = a[0]*b[0] - (a[2]*b[1]+a[1]*b[2])*beta */ addF(pR1, u0, t2, pGroundGFE); /* r[1] = a[1]*b[0] + a[0]*b[1] - a[2]*b[2]*beta */ } /* just a case */ else { cpGFpxMul_G0(u1, u1, pGFEx); /* u1 = (a[1]*b[2]+a[2]*b[1]) * beta */ cpGFpxMul_G0(t2, t2, pGFEx); /* t2 = a[2]*b[2] * beta */ subF(pR0, t0, u1, pGroundGFE); /* r[0] = a[0]*b[0] - (a[2]*b[1]+a[1]*b[2])*beta */ subF(pR1, u0, t2, pGroundGFE); /* r[1] = a[1]*b[0] + a[0]*b[1] - a[2]*b[2]*beta */ } } addF(pR2, u2, t1, pGroundGFE); /* r[2] = a[2]*b[0] + a[1]*b[1] + a[0]*b[2] */ cpGFpReleasePool(6, pGroundGFE); return pR; } /* // Intel(R) EPID 2.0 specific // ~~~~~~~~~~~~~~~ // // Squaring over GF((p^2)^3) // - field polynomial: g(v) = v^3 - xi => binominal with specific value of "xi" // - xi = x+2 */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxSqr_p3_binom_epid2, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int groundElemLen = GFP_FELEN(pGroundGFE); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGroundGFE)->sqr; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; const BNU_CHUNK_T* pA2 = pA+groundElemLen*2; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* pR2 = pR+groundElemLen*2; BNU_CHUNK_T* s0 = cpGFpGetPool(5, pGroundGFE); BNU_CHUNK_T* s1 = s0+groundElemLen; BNU_CHUNK_T* s2 = s1+groundElemLen; BNU_CHUNK_T* s3 = s2+groundElemLen; BNU_CHUNK_T* s4 = s3+groundElemLen; addF(s2, pA0, pA2, pGroundGFE); subF(s2, s2, pA1, pGroundGFE); sqrF(s2, s2, pGroundGFE); sqrF(s0, pA0, pGroundGFE); sqrF(s4, pA2, pGroundGFE); mulF(s1, pA0, pA1, pGroundGFE); mulF(s3, pA1, pA2, pGroundGFE); addF(s1, s1, s1, pGroundGFE); addF(s3, s3, s3, pGroundGFE); addF(pR2, s1, s2, pGroundGFE); addF(pR2, pR2, s3, pGroundGFE); subF(pR2, pR2, s0, pGroundGFE); subF(pR2, pR2, s4, pGroundGFE); /* Intel(R) EPID 2.0 specific */ { int basicExtDegree = cpGFpBasicDegreeExtension(pGFEx); /* deal with GF(p^2^3) */ if(basicExtDegree==6) { cpFq2Mul_xi(s4, s4, pGroundGFE); cpFq2Mul_xi(s3, s3, pGroundGFE); addF(pR1, s1, s4, pGroundGFE); addF(pR0, s0, s3, pGroundGFE); } /* just a case */ else { cpGFpxMul_G0(s4, s4, pGFEx); cpGFpxMul_G0(s3, s3, pGFEx); subF(pR1, s1, s4, pGroundGFE); subF(pR0, s0, s3, pGroundGFE); } } cpGFpReleasePool(5, pGroundGFE); return pR; } /* // return specific polynomi alarith methods // polynomial - deg 3 binomial (Intel(R) EPID 2.0) */ static gsModMethod* gsPolyArith_binom3_epid2 (void) { static gsModMethod m = { cpGFpxEncode_com, cpGFpxDecode_com, cpGFpxMul_p3_binom_epid2, cpGFpxSqr_p3_binom_epid2, NULL, cpGFpxAdd_com, cpGFpxSub_com, cpGFpxNeg_com, cpGFpxDiv2_com, cpGFpxMul2_com, cpGFpxMul3_com, //cpGFpxInv }; return &m; } /*F* // Name: ippsGFpxMethod_binom3_epid2 // // Purpose: Returns a reference to the implementation of arithmetic operations over GF(pd). // // Returns: pointer to a structure containing // an implementation of arithmetic operations over GF(pd) // g(v) = v^3 - U0, U0 from GF(q^2), U0 = u + 2 // // *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpxMethod_binom3_epid2, (void) ) { static IppsGFpMethod method = { cpID_Binom3_epid20, 3, NULL, NULL, NULL }; method.arith = gsPolyArith_binom3_epid2(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom_epid2.c000066400000000000000000000205671470420105600276120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods, if binomial generator // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" #include "gfpec/pcpgfpxmethod_binom_epid2.h" //tbcd: temporary excluded: #include /* // Intel(R) Enhanced Privacy ID (Intel(R) EPID) 2.0 specific. // // Intel(R) EPID 2.0 uses the following finite field hierarchy: // // 1) prime field GF(p), // p = 0xFFFFFFFFFFFCF0CD46E5F25EEE71A49F0CDC65FB12980A82D3292DDBAED33013 // // 2) 2-degree extension of GF(p): GF(p^2) == GF(p)[x]/g(x), g(x) = x^2 -beta, // beta =-1 mod p, so "beta" represents as {1} // // 3) 3-degree extension of GF(p^2) ~ GF(p^6): GF((p^2)^3) == GF(p)[v]/g(v), g(v) = v^3 -xi, // xi belongs GF(p^2), xi=x+2, so "xi" represents as {2,1} ---- "2" is low- and "1" is high-order coefficients // // 4) 2-degree extension of GF((p^2)^3) ~ GF(p^12): GF(((p^2)^3)^2) == GF(p)[w]/g(w), g(w) = w^2 -vi, // psi belongs GF((p^2)^3), vi=0*v^2 +1*v +0, so "vi" represents as {0,1,0}---- "0", '1" and "0" are low-, middle- and high-order coefficients // // See representations in t_gfpparam.cpp // */ /* // Multiplication case: mul(a, vi) over GF((p^2)^3), // where: // a, belongs to GF((p^2)^3) // xi belongs to GF((p^2)^3), vi={0,1,0} // // The case is important in GF(((p^2)^3)^2) arithmetic for Intel(R) EPID 2.0. // */ __IPPCP_INLINE BNU_CHUNK_T* cpFq6Mul_vi(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); int termLen = GFP_FELEN(pGroundGFE); const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+termLen; const BNU_CHUNK_T* pA2 = pA+termLen*2; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+termLen; BNU_CHUNK_T* pR2 = pR+termLen*2; BNU_CHUNK_T* t = cpGFpGetPool(1, pGroundGFE); //tbcd: temporary excluded: assert(NULL!=t); cpFq2Mul_xi(t, pA2, pGroundGFE); cpGFpElementCopy(pR2, pA1, termLen); cpGFpElementCopy(pR1, pA0, termLen); cpGFpElementCopy(pR0, t, termLen); cpGFpReleasePool(1, pGroundGFE); return pR; } /* // Intel(R) EPID 2.0 specific // ~~~~~~~~~~~~~~~ // // Multiplication over GF(p^2) // - field polynomial: g(x) = x^2 - beta => binominal with specific value of "beta" // - beta = p-1 // // Multiplication over GF(((p^2)^3)^2) ~ GF(p^12) // - field polynomial: g(w) = w^2 - vi => binominal with specific value of "vi" // - vi = 0*v^2 + 1*v + 0 - i.e vi={0,1,0} belongs to GF((p^2)^3) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxMul_p2_binom_epid2, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; int groundElemLen = GFP_FELEN(pGroundGFE); const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; const BNU_CHUNK_T* pB0 = pB; const BNU_CHUNK_T* pB1 = pB+groundElemLen; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* t0 = cpGFpGetPool(4, pGroundGFE); BNU_CHUNK_T* t1 = t0+groundElemLen; BNU_CHUNK_T* t2 = t1+groundElemLen; BNU_CHUNK_T* t3 = t2+groundElemLen; //tbcd: temporary excluded: assert(NULL!=t0); mulF(t0, pA0, pB0, pGroundGFE); /* t0 = a[0]*b[0] */ mulF(t1, pA1, pB1, pGroundGFE); /* t1 = a[1]*b[1] */ addF(t2, pA0, pA1, pGroundGFE); /* t2 = a[0]+a[1] */ addF(t3, pB0, pB1, pGroundGFE); /* t3 = b[0]+b[1] */ mulF(pR1, t2, t3, pGroundGFE); /* r[1] = (a[0]+a[1]) * (b[0]+b[1]) */ subF(pR1, pR1, t0, pGroundGFE); /* r[1] -= a[0]*b[0]) + a[1]*b[1] */ subF(pR1, pR1, t1, pGroundGFE); /* Intel(R) EPID 2.0 specific */ { int basicExtDegree = cpGFpBasicDegreeExtension(pGFEx); /* deal with GF(p^2) */ if(basicExtDegree==2) { subF(pR0, t0, t1, pGroundGFE); } /* deal with GF(p^6^2) */ else if(basicExtDegree==12) { cpFq6Mul_vi(t1, t1, pGroundGFE); addF(pR0, t0, t1, pGroundGFE); } /* deal with GF(p^x^2) - it's not Intel(R) EPID 2.0 case, just a case */ else { cpGFpxMul_G0(t1, t1, pGFEx); subF(pR0, t0, t1, pGroundGFE); } } cpGFpReleasePool(4, pGroundGFE); return pR; } /* // Intel(R) EPID 2.0 specific // ~~~~~~~~~~~~~~~ // // Squaring over GF(p^2) // - field polynomial: g(x) = x^2 - beta => binominal with specific value of "beta" // - beta = p-1 // // Squaring in GF(((p^2)^3)^2) ~ GF(p^12) // - field polynomial: g(w) = w^2 - vi => binominal with specific value of "vi" // - vi = 0*v^2 + 1*v + 0 - i.e vi={0,1,0} belongs to GF((p^2)^3) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, cpGFpxSqr_p2_binom_epid2, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; mod_sqr sqrF = GFP_METHOD(pGroundGFE)->sqr; mod_add addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; int groundElemLen = GFP_FELEN(pGroundGFE); const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+groundElemLen; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+groundElemLen; BNU_CHUNK_T* t0 = cpGFpGetPool(3, pGroundGFE); BNU_CHUNK_T* t1 = t0+groundElemLen; BNU_CHUNK_T* u0 = t1+groundElemLen; //tbcd: temporary excluded: assert(NULL!=t0); mulF(u0, pA0, pA1, pGroundGFE); /* u0 = a[0]*a[1] */ /* Intel(R) EPID 2.0 specific */ { int basicExtDegree = cpGFpBasicDegreeExtension(pGFEx); /* deal with GF(p^2) */ if(basicExtDegree==2) { addF(t0, pA0, pA1, pGroundGFE); subF(t1, pA0, pA1, pGroundGFE); mulF(pR0, t0, t1, pGroundGFE); addF(pR1, u0, u0, pGroundGFE); /* r[1] = 2*a[0]*a[1] */ } /* deal with GF(p^6^2) */ else if(basicExtDegree==12) { subF(t0, pA0, pA1, pGroundGFE); cpFq6Mul_vi(t1, pA1, pGroundGFE); subF(t1, pA0, t1, pGroundGFE); mulF(t0, t0, t1, pGroundGFE); addF(t0, t0, u0, pGroundGFE); cpFq6Mul_vi(t1, u0, pGroundGFE); addF(pR0, t0, t1, pGroundGFE); addF(pR1, u0, u0, pGroundGFE); } /* just a case */ else { sqrF(t0, pA0, pGroundGFE); /* t0 = a[0]*a[0] */ sqrF(t1, pA1, pGroundGFE); /* t1 = a[1]*a[1] */ cpGFpxMul_G0(t1, t1, pGFEx); subF(pR0, t0, t1, pGroundGFE); addF(pR1, u0, u0, pGroundGFE); /* r[1] = 2*a[0]*a[1] */ } } cpGFpReleasePool(3, pGroundGFE); return pR; } /* // return specific polynomi alarith methods // polynomial - deg 2 binomial (Intel(R) EPID 2.0) */ static gsModMethod* gsPolyArith_binom2_epid2 (void) { static gsModMethod m = { cpGFpxEncode_com, cpGFpxDecode_com, cpGFpxMul_p2_binom_epid2, cpGFpxSqr_p2_binom_epid2, NULL, cpGFpxAdd_com, cpGFpxSub_com, cpGFpxNeg_com, cpGFpxDiv2_com, cpGFpxMul2_com, cpGFpxMul3_com, //cpGFpxInv }; return &m; } /*F* // Name: ippsGFpxMethod_binom2_epid2 // // Purpose: Returns a reference to the implementation of arithmetic operations over GF(pd). // // Returns: pointer to a structure containing // an implementation of arithmetic operations over GF(pd) // g(x) = x^2 - a0, a0 from GF(q), a0 = 1 // g(w) = w^2 - V0, v0 from GF((q^2)^3), V0 = 0*s^2 + v + 0 // // *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpxMethod_binom2_epid2, (void) ) { static IppsGFpMethod method = { cpID_Binom2_epid20, 2, NULL, NULL, NULL }; method.arith = gsPolyArith_binom2_epid2(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom_epid2.h000066400000000000000000000065251470420105600276150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // internal functions for GF(p^d) methods, if binomial generator // with Intel(R) Enhanced Privacy ID (Intel(R) EPID) 2.0 specific // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" //tbcd: temporary excluded: #include /* // Intel(R) EPID 2.0 specific. // // Intel(R) EPID 2.0 uses the following finite field hierarchy: // // 1) prime field GF(p), // p = 0xFFFFFFFFFFFCF0CD46E5F25EEE71A49F0CDC65FB12980A82D3292DDBAED33013 // // 2) 2-degree extension of GF(p): GF(p^2) == GF(p)[x]/g(x), g(x) = x^2 -beta, // beta =-1 mod p, so "beta" represents as {1} // // 3) 3-degree extension of GF(p^2) ~ GF(p^6): GF((p^2)^3) == GF(p)[v]/g(v), g(v) = v^3 -xi, // xi belongs GF(p^2), xi=x+2, so "xi" represents as {2,1} ---- "2" is low- and "1" is high-order coefficients // // 4) 2-degree extension of GF((p^2)^3) ~ GF(p^12): GF(((p^2)^3)^2) == GF(p)[w]/g(w), g(w) = w^2 -vi, // psi belongs GF((p^2)^3), vi=0*v^2 +1*v +0, so "vi" represents as {0,1,0}---- "0", '1" and "0" are low-, middle- and high-order coefficients // // See representations in t_gfpparam.cpp // */ /* // Multiplication case: mul(a, xi) over GF(p^2), // where: // a, belongs to GF(p^2) // xi belongs to GF(p^2), xi={2,1} // // The case is important in GF((p^2)^3) arithmetic for Intel(R) EPID 2.0. // */ __IPPCP_INLINE BNU_CHUNK_T* cpFq2Mul_xi(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); mod_mul addF = GFP_METHOD(pGroundGFE)->add; mod_sub subF = GFP_METHOD(pGroundGFE)->sub; int termLen = GFP_FELEN(pGroundGFE); BNU_CHUNK_T* t0 = cpGFpGetPool(2, pGroundGFE); BNU_CHUNK_T* t1 = t0+termLen; const BNU_CHUNK_T* pA0 = pA; const BNU_CHUNK_T* pA1 = pA+termLen; BNU_CHUNK_T* pR0 = pR; BNU_CHUNK_T* pR1 = pR+termLen; //tbcd: temporary excluded: assert(NULL!=t0); addF(t0, pA0, pA0, pGroundGFE); addF(t1, pA0, pA1, pGroundGFE); subF(pR0, t0, pA1, pGroundGFE); addF(pR1, t1, pA1, pGroundGFE); cpGFpReleasePool(2, pGroundGFE); return pR; } /* // Multiplication case: mul(a, g0) over GF(()), // where: // a and g0 belongs to GF(()) - field is being extension // // The case is important in GF(()^d) arithmetic if constructed polynomial is generic binomial g(t) = t^d +g0. // */ static BNU_CHUNK_T* cpGFpxMul_G0(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); BNU_CHUNK_T* pGFpolynomial = GFP_MODULUS(pGFEx); /* g(x) = t^d + g0 */ return GFP_METHOD(pGroundGFE)->mul(pR, pA, pGFpolynomial, pGroundGFE); } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_binom_mulc.h000066400000000000000000000033041470420105600275420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods, if binomial generator // */ #if !defined(_CP_GFP_METHOD_BINOM_H) #define _CP_GFP_METHOD_BINOM_H #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" static BNU_CHUNK_T* cpGFpxMul_G0(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx) { gsEngine* pGroundGFE = GFP_PARENT(pGFEx); mod_mul mulF = GFP_METHOD(pGroundGFE)->mul; BNU_CHUNK_T* pGFpolynomial = GFP_MODULUS(pGFEx); /* g(x) = t^d + g0 */ #if defined GS_DBG BNU_CHUNK_T* arg0 = cpGFpGetPool(1, pGroundGFE); BNU_CHUNK_T* arg1 = cpGFpGetPool(1, pGroundGFE); int groundElemLen = GFP_FELEN(pGroundGFE); #endif #if defined GS_DBG cpGFpxGet(arg0, groundElemLen, pA, pGroundGFE); cpGFpxGet(arg1, groundElemLen, pGFpolynomial, pGroundGFE); #endif mulF(pR, pA, pGFpolynomial, pGroundGFE); #if defined GS_DBG cpGFpReleasePool(2, pGroundGFE); #endif return pR; } #endif /* _CP_GFP_METHOD_BINOM_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_com.c000066400000000000000000000035651470420105600262000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" /* // return common polynomi alarith methods */ static gsModMethod* gsPolyArith(void) { static gsModMethod m = { cpGFpxEncode_com, cpGFpxDecode_com, cpGFpxMul_com, cpGFpxSqr_com, NULL, cpGFpxAdd_com, cpGFpxSub_com, cpGFpxNeg_com, cpGFpxDiv2_com, cpGFpxMul2_com, cpGFpxMul3_com, //cpGFpxInv }; return &m; } /*F* // Name: ippsGFpxMethod_binom2 // // Purpose: Returns a reference to the implementation of arithmetic operations over GF(pd). // // Returns: pointer to a structure containing // an implementation of arithmetic operations over GF(pd) // g(x) = x^d + x(d - 1) a_(d-1) + x^(d - 2)a_(d - 2) + ... + x1a1 + a0, ai from GF(p) // // *F*/ IPPFUN( const IppsGFpMethod*, ippsGFpxMethod_com, (void) ) { static IppsGFpMethod method = { cpID_Poly, 0, NULL, NULL, NULL }; method.arith = gsPolyArith(); return &method; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_com.h000066400000000000000000000050251470420105600261760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods // */ #if !defined(_CP_GFP_METHOD_COM_H) #define _CP_GFP_METHOD_COM_H #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #define cpGFpxAdd_com OWNAPI(cpGFpxAdd_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxAdd_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) #define cpGFpxSub_com OWNAPI(cpGFpxSub_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxSub_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) #define cpGFpxNeg_com OWNAPI(cpGFpxNeg_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxNeg_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #define cpGFpxMul_com OWNAPI(cpGFpxMul_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxMul_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) #define cpGFpxSqr_com OWNAPI(cpGFpxSqr_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxSqr_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #define cpGFpxDiv2_com OWNAPI(cpGFpxDiv2_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxDiv2_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #define cpGFpxMul2_com OWNAPI(cpGFpxMul2_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxMul2_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #define cpGFpxMul3_com OWNAPI(cpGFpxMul3_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxMul3_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #define cpGFpxEncode_com OWNAPI(cpGFpxEncode_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxEncode_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #define cpGFpxDecode_com OWNAPI(cpGFpxDecode_com) IPP_OWN_DECL (BNU_CHUNK_T*, cpGFpxDecode_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) #endif /* _CP_GFP_METHOD_COM_H */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_com_add.c000066400000000000000000000026521470420105600270040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxAdd_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { gsEngine* pBasicGFE = cpGFpBasic(pGFEx); mod_add addF = GFP_METHOD(pBasicGFE)->add; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degdecode; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degdiv2; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degencode; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; deg IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxMul_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { int extDegree = GFP_EXTDEGREE(pGFEx); BNU_CHUNK_T* pGFpolynomial = GFP_MODULUS(pGFEx); int degR = extDegree-1; int elemLen= GFP_FELEN(pGFEx); int degB = degR; BNU_CHUNK_T* pTmpProduct = cpGFpGetPool(2, pGFEx); BNU_CHUNK_T* pTmpResult = pTmpProduct + GFP_PELEN(pGFEx); gsEngine* pGroundGFE = GFP_PARENT(pGFEx); BNU_CHUNK_T* r = cpGFpGetPool(1, pGroundGFE); int groundElemLen = GFP_FELEN(pGroundGFE); const BNU_CHUNK_T* pTmpB = GFPX_IDX_ELEMENT(pB, degB, groundElemLen); //tbcd: temporary excluded: assert(NULL!=pTmpProduct && NULL!=r); /* clear temporary */ cpGFpElementPad(pTmpProduct, elemLen, 0); /* R = A * B[degB-1] */ cpGFpxMul_GFE(pTmpResult, pA, pTmpB, pGFEx); for(degB-=1; degB>=0; degB--) { /* save R[degR-1] */ cpGFpElementCopy(r, GFPX_IDX_ELEMENT(pTmpResult, degR, groundElemLen), groundElemLen); { /* R = R * x */ int j; for (j=degR; j>=1; j--) cpGFpElementCopy(GFPX_IDX_ELEMENT(pTmpResult, j, groundElemLen), GFPX_IDX_ELEMENT(pTmpResult, j-1, groundElemLen), groundElemLen); cpGFpElementPad(pTmpResult, groundElemLen, 0); } cpGFpxMul_GFE(pTmpProduct, pGFpolynomial, r, pGFEx); GFP_METHOD(pGFEx)->sub(pTmpResult, pTmpResult, pTmpProduct, pGFEx); /* B[degB-i] */ pTmpB -= groundElemLen; cpGFpxMul_GFE(pTmpProduct, pA, pTmpB, pGFEx); GFP_METHOD(pGFEx)->add(pTmpResult, pTmpResult, pTmpProduct, pGFEx); } /* copy result */ cpGFpElementCopy(pR, pTmpResult, elemLen); /* release pools */ cpGFpReleasePool(1, pGroundGFE); cpGFpReleasePool(2, pGFEx); return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_com_mul2.c000066400000000000000000000025721470420105600271340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxMul2_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { gsEngine* pBasicGFE = cpGFpBasic(pGFEx); mod_mul2 mul2F = GFP_METHOD(pBasicGFE)->mul2; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degmul3; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; degneg; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; deg IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxSqr_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pGFEx)) { int extDegree = GFP_EXTDEGREE(pGFEx); BNU_CHUNK_T* pGFpolynomial = GFP_MODULUS(pGFEx); int degR = extDegree-1; int elemLen= GFP_FELEN(pGFEx); int degA = degR; BNU_CHUNK_T* pTmpProduct = cpGFpGetPool(2, pGFEx); BNU_CHUNK_T* pTmpResult = pTmpProduct + GFP_PELEN(pGFEx); gsEngine* pGroundGFE = GFP_PARENT(pGFEx); BNU_CHUNK_T* r = cpGFpGetPool(1, pGroundGFE); int groundElemLen = GFP_FELEN(pGroundGFE); const BNU_CHUNK_T* pTmpA = GFPX_IDX_ELEMENT(pA, degA, groundElemLen); //tbcd: temporary excluded: assert(NULL!=pTmpProduct && NULL!=r); /* clear temporary */ cpGFpElementPad(pTmpProduct, elemLen, 0); /* R = A * A[degA-1] */ cpGFpxMul_GFE(pTmpResult, pA, pTmpA, pGFEx); for(degA-=1; degA>=0; degA--) { /* save R[degR-1] */ cpGFpElementCopy(r, GFPX_IDX_ELEMENT(pTmpResult, degR, groundElemLen), groundElemLen); { /* R = R * x */ int j; for (j=degR; j>=1; j--) cpGFpElementCopy(GFPX_IDX_ELEMENT(pTmpResult, j, groundElemLen), GFPX_IDX_ELEMENT(pTmpResult, j-1, groundElemLen), groundElemLen); cpGFpElementPad(pTmpResult, groundElemLen, 0); } cpGFpxMul_GFE(pTmpProduct, pGFpolynomial, r, pGFEx); GFP_METHOD(pGFEx)->sub(pTmpResult, pTmpResult, pTmpProduct, pGFEx); /* A[degA-i] */ pTmpA -= groundElemLen; cpGFpxMul_GFE(pTmpProduct, pA, pTmpA, pGFEx); GFP_METHOD(pGFEx)->add(pTmpResult, pTmpResult, pTmpProduct, pGFEx); } /* copy result */ cpGFpElementCopy(pR, pTmpResult, elemLen); /* release pools */ cpGFpReleasePool(1, pGroundGFE); cpGFpReleasePool(2, pGFEx); return pR; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxmethod_com_sub.c000066400000000000000000000026521470420105600270450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p^d) methods // */ #include "owncp.h" #include "gfpec/pcpgfpxstuff.h" #include "gfpec/pcpgfpxmethod_com.h" IPP_OWN_DEFN (BNU_CHUNK_T*, cpGFpxSub_com, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pGFEx)) { gsEngine* pBasicGFE = cpGFpBasic(pGFEx); mod_sub subF = GFP_METHOD(pBasicGFE)->sub; int basicElemLen = GFP_FELEN(pBasicGFE); int basicDeg = cpGFpBasicDegreeExtension(pGFEx); BNU_CHUNK_T* pTmp = pR; int deg; for(deg=0; deg=n_opt) break; w_opt = w_trial; n_opt = n_trial; } return w_opt; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/pcpgfpxstuff.h000066400000000000000000000147771470420105600252250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // GF(p) extension internal // */ #if !defined(_PCP_GFPEXT_H_) #define _PCP_GFPEXT_H_ #include "gfpec/pcpgfpstuff.h" /* GF(p^d) pool */ #define GFPX_PESIZE(pGF) GFP_FELEN((pGF)) #define GFPX_POOL_SIZE (14) //(8) /* Number of temporary variables in pool */ /* address of ground field element inside expanded field element */ #define GFPX_IDX_ELEMENT(pxe, idx, eleSize) ((pxe)+(eleSize)*(idx)) __IPPCP_INLINE int degree(const BNU_CHUNK_T* pE, const gsModEngine* pGFEx) { int groundElemLen = GFP_FELEN(GFP_PARENT(pGFEx)); int deg; for(deg=GFP_EXTDEGREE(pGFEx)-1; deg>=0; deg--) { if(!GFP_IS_ZERO(pE+groundElemLen*deg, groundElemLen)) break; } return deg; } __IPPCP_INLINE gsModEngine* cpGFpBasic(const gsModEngine* pGFEx) { while( !GFP_IS_BASIC(pGFEx) ) { pGFEx = GFP_PARENT(pGFEx); } return (gsModEngine*)pGFEx; } __IPPCP_INLINE int cpGFpBasicDegreeExtension(const gsModEngine* pGFEx) { int degree = GFP_EXTDEGREE(pGFEx); while( !GFP_IS_BASIC(pGFEx) ) { pGFEx = GFP_PARENT(pGFEx); degree *= GFP_EXTDEGREE(pGFEx); } return degree; } /* convert external data (Ipp32u) => internal element (BNU_CHUNK_T) representation returns length of element (in BNU_CHUNK_T) */ __IPPCP_INLINE int cpGFpxCopyToChunk(BNU_CHUNK_T* pElm, const Ipp32u* pA, int nsA, const gsModEngine* pGFEx) { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); int basicExtension = cpGFpBasicDegreeExtension(pGFEx); int basicElmLen32 = GFP_FELEN32(pBasicGFE); int basicElmLen = GFP_FELEN(pBasicGFE); int deg; for(deg=0; deg0; deg++, nsA -= basicElmLen32) { int srcLen = IPP_MIN(nsA, basicElmLen32); ZEXPAND_COPY_BNU((Ipp32u*)pElm, basicElmLen*(int)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)), pA,srcLen); pElm += basicElmLen; pA += basicElmLen32; } return basicElmLen*deg; } /* convert internal element (BNU_CHUNK_T) => external data (Ipp32u) representation returns length of data (in Ipp32u) */ __IPPCP_INLINE int cpGFpxCopyFromChunk(Ipp32u* pA, const BNU_CHUNK_T* pElm, const gsModEngine* pGFEx) { gsModEngine* pBasicGFE = cpGFpBasic(pGFEx); int basicExtension = cpGFpBasicDegreeExtension(pGFEx); int basicElmLen32 = GFP_FELEN32(pBasicGFE); int basicElmLen = GFP_FELEN(pBasicGFE); int deg; for(deg=0; deg= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gfpec/sm2/ifma_arith_psm2.h" #include "gfpec/sm2/ifma_arith_nsm2.h" IPP_OWN_DEFN(ifmaArithMethod*, gsArithGF_nsm2_avx512, (void)) { static ifmaArithMethod m = { /* import_to52 = */ fesm2_convert_radix64_radix52, /* export_to64 = */ fesm2_convert_radix52_radix64, /* encode = */ fesm2_to_mont_norder, /* decode = */ fesm2_from_mont_norder, /* mul = */ fesm2_mul_norder, /* mul_dual = */ 0, /* sqr = */ 0, /* sqr_dual = */ 0, /* norm = */ ifma_norm52, /* norm_dual = */ ifma_norm52_dual, /* lnorm = */ ifma_lnorm52, /* lnorm_dual = */ ifma_lnorm52_dual, /* add = */ fesm2_add_norder_norm, /* sub = */ fesm2_sub_norder_norm, /* neg = */ 0, /* div2 = */ 0, /* inv = */ fesm2_inv_norder_norm, /* red = */ fesm2_fast_reduction_norder}; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_arith_method_psm2.c000066400000000000000000000034331470420105600275710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gfpec/sm2/ifma_arith_psm2.h" IPP_OWN_DEFN(ifmaArithMethod*, gsArithGF_psm2_avx512, (void)) { static ifmaArithMethod m = { /* import_to52 = */ fesm2_convert_radix64_radix52, /* export_to64 = */ fesm2_convert_radix52_radix64, /* encode = */ fesm2_to_mont, /* decode = */ fesm2_from_mont, /* mul = */ fesm2_mul, /* mul_dual = */ fesm2_mul_dual, /* sqr = */ fesm2_sqr, /* sqr_dual = */ fesm2_sqr_dual, /* norm = */ ifma_norm52, /* norm_dual = */ ifma_norm52_dual, /* lnorm = */ ifma_lnorm52, /* lnorm_dual = */ ifma_lnorm52_dual, /* add = */ 0, /* sub = */ 0, /* neg = */ fesm2_neg_norm, /* div2 = */ fesm2_div2_norm, /* inv = */ fesm2_inv_norm, /* red = */ 0}; return &m; } #endif /* #if (_IPP32E >= _IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_arith_method_sm2.h000066400000000000000000000025161470420105600274170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 IFMA_ARITH_METHOD_SM2_H_ #define IFMA_ARITH_METHOD_SM2_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "owncp.h" #include "gfpec/ecnist/ifma_alias_avx512.h" #include "gfpec/ecnist/ifma_arith_method.h" /* Pre-defined AVX512IFMA ISA based methods */ #define gsArithGF_psm2_avx512 OWNAPI(gsArithGF_psm2_avx512) IPP_OWN_DECL(ifmaArithMethod*, gsArithGF_psm2_avx512, (void)) #define gsArithGF_nsm2_avx512 OWNAPI(gsArithGF_nsm2_avx512) IPP_OWN_DECL(ifmaArithMethod*, gsArithGF_nsm2_avx512, (void)) #endif /* #if (_IPP32E >= _IPP32E_K1) */ #endif /* #ifndef IFMA_ARITH_METHOD_SM2_H_ */ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_arith_nsm2.c000066400000000000000000000215051470420105600262270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_nsm2.h" #include "gfpec/sm2/ifma_arith_psm2.h" #include "gfpec/sm2/ifma_defs_sm2.h" /* * EC SM2 base point order * in 2^52 radix */ static const __ALIGN64 Ipp64u nsm2_x1[PSM2_LEN52] = { 0x000bf40939d54123, 0x0006b21c6052b53b, 0x000fffffff7203df, 0x000fffffffffffff, 0x0000fffffffeffff}; /* k0 = -( (1/nsm2) mod 2^DIGIT_SIZE_52 ) mod 2^DIGIT_SIZE_52 */ static const Ipp64u nsm2_k0 = 0x000f9e8872350975; /* r = 2^((52*8)) mod nsm2 */ static const __ALIGN64 Ipp64u nsm2_r[PSM2_LEN52] = { 0x00062abedd000000, 0x00006cb726ecad3c, 0x00056c361b698a7e, 0x0000000008dfc209, 0x0000010000000000}; /* To Montgomery conversion constant * rr = 2^((52*6)*2) mod nsm2 */ static const __ALIGN64 Ipp64u nsm2_rr[PSM2_LEN52] = { 0x000643f5455b3830, 0x000c453935b521eb, 0x0009ec21d42b082e, 0x0004d74634238016, 0x0000ca6ea35cbdde}; static const __ALIGN64 Ipp64u ones[PSM2_LEN52] = { 0x1, 0x0, 0x0, 0x0}; #define MULT_ROUND(R, A, B, IDX) \ const fesm2 Bi##R##IDX = permutexvar_i8(idx##IDX, (B)); \ const fesm2 amBiLo##R##IDX = madd52lo_i64(zero, (A), Bi##R##IDX); \ fesm2 tr##R##IDX = madd52hi_i64(zero, (A), Bi##R##IDX); \ { \ /* low */ \ (R) = add_i64((R), amBiLo##R##IDX); \ const fesm2 R0 = permutexvar_i8(idx0, (R)); \ const fesm2 u = madd52lo_i64(zero, R0, K0); /* u = R0 * K0 */ \ tr##R##IDX = madd52hi_i64(tr##R##IDX, N, u); \ (R) = madd52lo_i64((R), N, u); \ /* shift */ \ const fesm2 carryone = maskz_srai_i64(maskone, (R), DIGIT_SIZE_52); \ tr##R##IDX = add_i64(tr##R##IDX, carryone); \ (R) = maskz_permutexvar_i8(mask_sr64, idx_sr64, (R)); \ /* hi */ \ (R) = add_i64((R), tr##R##IDX); \ } /* R = (A*B) - no normalization (in radix 2^52) */ IPP_OWN_DEFN(fesm2, fesm2_mul_norder, (const fesm2 a, const fesm2 b)) { const fesm2 N = FESM2_LOADU(nsm2_x1); /* p */ const fesm2 K0 = set1_i64(nsm2_k0); const fesm2 zero = setzero_i64(); const mask8 maskone = 0x1; /* index broadcast */ const fesm2 idx0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const fesm2 idx1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const fesm2 idx2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const fesm2 idx3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const fesm2 idx4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const fesm2 idx5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 /* shift right 64 bit line [R >> 64] */ const mask64 mask_sr64 = 0x00FFFFFFFFFFFFFF; const fesm2 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 fesm2 r = setzero_i64(); /* PSM2 * m' mod b = 1 * * Algorithm * a[] b[] - input data ((in radix 2^52)) m[] - module nsm2 * * when u = R[0]*m' mod b * 1) R = R + a[] * b[i] (lo) * 2) R = R + m[] * u (lo) * 3) R = R >> 64 * 4) R = R + a[] * b[i] (hi) * 5) R = R + m[] * u (hi) */ /* one round = O(32) */ MULT_ROUND(r, a, b, 0) MULT_ROUND(r, a, b, 1) MULT_ROUND(r, a, b, 2) MULT_ROUND(r, a, b, 3) MULT_ROUND(r, a, b, 4) MULT_ROUND(r, a, b, 5) return r; } IPP_OWN_DEFN(fesm2, fesm2_add_norder_norm, (const fesm2 a, const fesm2 b)) { const fesm2 zero = setzero_i64(); const fesm2 N = FESM2_LOADU(nsm2_x1); /* r = a + b */ fesm2 r = add_i64(a, b); r = ifma_lnorm52(r); /* t = r - N */ fesm2 t = sub_i64(r, N); t = ifma_norm52(t); /* lt = t < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(t, DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 4) & 1)); /* mask != 0 ? a : r */ r = mask_mov_i64(t, mask, r); return r; } IPP_OWN_DEFN(fesm2, fesm2_sub_norder_norm, (const fesm2 a, const fesm2 b)) { const fesm2 zero = setzero_i64(); const fesm2 N = FESM2_LOADU(nsm2_x1); /* r = a - b */ fesm2 r = sub_i64(a, b); r = ifma_norm52(r); /* t = r + M */ fesm2 t = add_i64(r, N); t = ifma_lnorm52(t); /* lt = r < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 4) & 1)); /* mask != 0 ? t : r */ r = mask_mov_i64(r, mask, t); return r; } IPP_OWN_DEFN(fesm2, fesm2_fast_reduction_norder, (const fesm2 a)) { const fesm2 zero = setzero_i64(); const fesm2 N = FESM2_LOADU(nsm2_x1); fesm2 r = sub_i64(a, N); r = ifma_norm52(r); const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 4) & 1)); /* mask != 0 ? a : r */ r = mask_mov_i64(r, mask, a); return r; } IPP_OWN_DEFN(fesm2, fesm2_to_mont_norder, (const fesm2 a)) { const fesm2 RR = FESM2_LOADU(nsm2_rr); const fesm2 r = fesm2_mul_norder(a, RR); return ifma_lnorm52(r); } IPP_OWN_DEFN(fesm2, fesm2_from_mont_norder, (const fesm2 a)) { const fesm2 ONE = FESM2_LOADU(ones); fesm2 r = fesm2_mul_norder(a, ONE); r = ifma_lnorm52(r); r = fesm2_fast_reduction_norder(r); return r; } __IPPCP_INLINE fesm2 mul_norder_norm(const fesm2 a, const fesm2 b) { const fesm2 r = fesm2_mul_norder(a, b); return ifma_lnorm52(r); } __IPPCP_INLINE fesm2 sqr_norder_norm(const fesm2 a) { const fesm2 r = fesm2_mul_norder(a, a); return ifma_lnorm52(r); } #define SIZE_TBL (16) #define sqr(R, A) (R) = sqr_norder_norm((A)) #define mul(R, A, B) (R) = mul_norder_norm((A), (B)) IPP_OWN_DEFN(fesm2, fesm2_inv_norder_norm, (const fesm2 z)) { const fesm2 r_norder = FESM2_LOADU(nsm2_r); int i; // pwr_z_Tbl[i][] = z^i, i=0,..,15 __ALIGN64 fesm2 pwr_z_Tbl[SIZE_TBL]; pwr_z_Tbl[0] = r_norder; pwr_z_Tbl[1] = z; for (i = 2; i < SIZE_TBL; i += 2) { sqr(pwr_z_Tbl[i], pwr_z_Tbl[i / 2]); mul(pwr_z_Tbl[i + 1], pwr_z_Tbl[i], z); } // pwr = (nsm2-2) in big endian const Ipp8u pwr[] = "\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF" "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" "\x72\x03\xDF\x6B\x21\xC6\x05\x2B" "\x53\xBB\xF4\x09\x39\xD5\x41\x21"; // init r = 1 fesm2 r = pwr_z_Tbl[0]; for (i = 0; i < 32; ++i) { const int v = pwr[i]; const int hi = (v >> 4) & 0xF; const int lo = v & 0xF; sqr(r, r); sqr(r, r); sqr(r, r); sqr(r, r); if (hi) mul(r, r, pwr_z_Tbl[hi]); sqr(r, r); sqr(r, r); sqr(r, r); sqr(r, r); if (lo) mul(r, r, pwr_z_Tbl[lo]); } return r; } #undef SIZE_TBL #undef sqr #undef mul #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_arith_nsm2.h000066400000000000000000000052171470420105600262360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ARITH_NSM2_H_) #define _IFMA_ARITH_NSM2_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_defs_sm2.h" /** * \brief * * Montgomery multiplication * * a * b * R mod n, where R = 2^(6*52) mod n * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) * \return value no normalization */ IPP_OWN_DECL(fesm2, fesm2_mul_norder, (const fesm2 a, const fesm2 b)) /** * \brief * * A + B (mod n) * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) * \return value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_add_norder_norm, (const fesm2 a, const fesm2 b)) /** * \brief * * A + B (mod n) * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) * \return value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_sub_norder_norm, (const fesm2 a, const fesm2 b)) /** * \brief * * Conversion to Montgomery domain modulo n (subgroup order). * * a * R mod n, where R = 2^(6*52) mod n * * \param[in] a value (in radix 2^52) * \return value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_to_mont_norder, (const fesm2 a)) /** * \brief * * Reduction modulo n (subgroup order). * * (a >= n) ? a - n : a * * \param[in] a value (in radix 2^52) * \return value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_fast_reduction_norder, (const fesm2 a)) /** * \brief * * Conversion from Montgomery domain modulo n (subgroup order). * * a mod n * * \param[in] a value (radix 2^52) * \return value (radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_from_mont_norder, (const fesm2 a)) /** * \brief * * Modular inverse modulo n (subgroup order). * * 1/z mod n * * \param[in] z value (in radix 2^52) * \return value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_inv_norder_norm, (const fesm2 z)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ARITH_NSM2_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_arith_psm2.c000066400000000000000000000377371470420105600262470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_psm2.h" #include "gfpec/sm2/ifma_defs_sm2.h" /* modulus psm2 = 2^256 - 2^224 - 2^96 + 2^64 - 1 */ static const __ALIGN64 Ipp64u psm2_x1[PSM2_LEN52] = { 0x000fffffffffffff, 0x000ff00000000fff, 0x000fffffffffffff, 0x000fffffffffffff, 0x0000fffffffeffff}; /* 4*p */ static const __ALIGN64 Ipp64u psm2_x4[PSM2_LEN52] = { 0x000ffffffffffffc, 0x000fc00000003fff, 0x000fffffffffffff, 0x000fffffffffffff, 0x0003fffffffbffff}; /* to Montgomery conversion constant * rr = 2^((PSM2_LEN52*DIGIT_SIZE)*2) mod psm2 */ /* rr = 2^(52*6*2) mod psm2 */ static const __ALIGN64 Ipp64u psm2_rr[PSM2_LEN52] = { 0x0006000000070000, 0x000fffffd0000000, 0x00000400000003ff, 0x0000000000300000, 0x0000000800000003}; static const __ALIGN64 Ipp64u ones[PSM2_LEN52] = { 0x1, 0x0, 0x0, 0x0, 0x0}; /* R = (A/2) mod M */ IPP_OWN_DEFN(fesm2, fesm2_div2_norm, (const fesm2 a)) { const fesm2 M = FESM2_LOADU(psm2_x1); const fesm2 zero = setzero_i64(); const fesm2 one = set1_i64(1LL); const mask8 is_last_one = cmp_i64_mask(and_i64(a, one), zero, _MM_CMPINT_EQ); const mask8 mask = (mask8)((is_last_one & 1) - 1); fesm2 r = mask_add_i64(a, mask, a, M); r = ifma_lnorm52(r); /* 1-bit shift right */ /* extract last bite + >> 64 */ const mask64 mask_shift = 0xFFFFFFFF; const fesm2 idx_shift = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 fesm2 shift_right = maskz_permutexvar_i8(mask_shift, idx_shift, and_i64(r, one)); /* set last bit is first byte (52 radix) */ shift_right = slli_i64(shift_right, DIGIT_SIZE_52 - 1); /* join first new bite */ r = srli_i64(r, 1); /* create slot by first bite 1111 -> 0111 */ r = add_i64(r, shift_right); /* join first and other bite */ return r; } IPP_OWN_DEFN(fesm2, fesm2_neg_norm, (const fesm2 a)) { const fesm2 M4 = FESM2_LOADU(psm2_x4); /* a == 0 ? 0xFF : 0 */ const mask8 mask_zero = FESM2_IS_ZERO(a); /* r = 4*p - a */ fesm2 r = mask_sub_i64(a, (mask8)(~mask_zero), M4, a); r = ifma_norm52(r); return r; } #define MULT_ROUND(R, A, B, IDX) \ const fesm2 Bi##R##IDX = permutexvar_i8(idx##IDX, (B)); \ const fesm2 amBiLo##R##IDX = madd52lo_i64(zero, (A), Bi##R##IDX); \ fesm2 tr##R##IDX = madd52hi_i64(zero, (A), Bi##R##IDX); \ { \ /* low */ \ (R) = add_i64((R), amBiLo##R##IDX); \ const fesm2 u = permutexvar_i8(idx0, (R)); /* u = R0 * 1 */ \ tr##R##IDX = madd52hi_i64(tr##R##IDX, M, u); \ (R) = madd52lo_i64((R), M, u); \ /* shift */ \ const fesm2 carryone = maskz_srai_i64(maskone, (R), DIGIT_SIZE_52); \ tr##R##IDX = add_i64(tr##R##IDX, carryone); \ (R) = maskz_permutexvar_i8(mask_sr64, idx_sr64, (R)); \ /* hi */ \ (R) = add_i64((R), tr##R##IDX); \ } /* R = (A*B) - no normalization (in radix 2^52) */ IPP_OWN_DEFN(fesm2, fesm2_mul, (const fesm2 a, const fesm2 b)) { const fesm2 M = FESM2_LOADU(psm2_x1); /* p */ const fesm2 zero = setzero_i64(); const mask8 maskone = 0x1; /* index broadcast */ const fesm2 idx0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const fesm2 idx1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const fesm2 idx2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const fesm2 idx3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const fesm2 idx4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const fesm2 idx5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 /* shift right 64 bit line [R >> 64] */ const mask64 mask_sr64 = 0x00FFFFFFFFFFFFFF; const fesm2 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 fesm2 r = setzero_i64(); /* PSM2 * m' mod b = 1 * * Algorithm * a[] b[] - input data ((in radix 2^52)) m[] - module psm2 * * when u = R[0]*m' mod b * 1) R = R + a[] * b[i] (lo) * 2) R = R + m[] * u (lo) * 3) R = R >> 64 * 4) R = R + a[] * b[i] (hi) * 5) R = R + m[] * u (hi) */ /* one round = O(32) */ MULT_ROUND(r, a, b, 0) MULT_ROUND(r, a, b, 1) MULT_ROUND(r, a, b, 2) MULT_ROUND(r, a, b, 3) MULT_ROUND(r, a, b, 4) MULT_ROUND(r, a, b, 5) return r; } IPP_OWN_DEFN(void, fesm2_mul_dual, (fesm2 pr1[], const fesm2 a1, const fesm2 b1, fesm2 pr2[], const fesm2 a2, const fesm2 b2)) { const fesm2 M = FESM2_LOADU(psm2_x1); /* p */ const fesm2 zero = setzero_i64(); const mask8 maskone = 0x1; /* index broadcast */ const fesm2 idx0 = set_i64(REPL8(0x0706050403020100)); // 7, 6, 5, 4, 3, 2, 1, 0 const fesm2 idx1 = set_i64(REPL8(0x0f0e0d0c0b0a0908)); // 15, 14, 13, 12, 11, 10, 9, 8 const fesm2 idx2 = set_i64(REPL8(0x1716151413121110)); // 23, 22, 21, 20, 19, 18, 17, 16 const fesm2 idx3 = set_i64(REPL8(0x1f1e1d1c1b1a1918)); // 31, 30, 29, 28, 27, 26, 25, 24 const fesm2 idx4 = set_i64(REPL8(0x2726252423222120)); // 39, 38, 37, 36, 35, 34, 33, 32 const fesm2 idx5 = set_i64(REPL8(0x2f2e2d2c2b2a2928)); // 47, 46, 45, 44, 43, 42, 41, 40 /* shift right 64 bit line [R >> 64] */ const mask64 mask_sr64 = 0x00FFFFFFFFFFFFFF; const fesm2 idx_sr64 = set_i64(0x0, // 0, 0, 0, 0, 0, 0, 0, 0 0x3f3e3d3c3b3a3938, // 63, 62, 61, 60, 59, 58, 57, 56 0x3736353433323130, // 55, 54, 53, 52, 51, 50, 49, 48 0x2f2e2d2c2b2a2928, // 47, 46, 45, 44, 43, 42, 41, 40 0x2726252423222120, // 39, 38, 37, 36, 35, 34, 33, 32 0x1f1e1d1c1b1a1918, // 31, 30, 29, 28, 27, 26, 25, 24 0x1716151413121110, // 23, 22, 21, 20, 19, 18, 17, 16 0x0f0e0d0c0b0a0908); // 15, 14, 13, 12, 11, 10, 9, 8 fesm2 r1, r2; r1 = r2 = setzero_i64(); /* PSM2 * m' mod b = 1 * * Algorithm * a[] b[] - input data ((in radix 2^52)) m[] - module psm2 * * when u = R[0]*m' mod b * 1) R = R + a[] * b[i] (lo) * 2) R = R + m[] * u (lo) * 3) R = R >> 64 * 4) R = R + a[] * b[i] (hi) * 5) R = R + m[] * u (hi) */ /* one round = O(32) */ MULT_ROUND(r1, a1, b1, 0) MULT_ROUND(r2, a2, b2, 0) MULT_ROUND(r1, a1, b1, 1) MULT_ROUND(r2, a2, b2, 1) MULT_ROUND(r1, a1, b1, 2) MULT_ROUND(r2, a2, b2, 2) MULT_ROUND(r1, a1, b1, 3) MULT_ROUND(r2, a2, b2, 3) MULT_ROUND(r1, a1, b1, 4) MULT_ROUND(r2, a2, b2, 4) MULT_ROUND(r1, a1, b1, 5) MULT_ROUND(r2, a2, b2, 5) *pr1 = r1; *pr2 = r2; return; } IPP_OWN_DEFN(fesm2, fesm2_to_mont, (const fesm2 a)) { const fesm2 RR = FESM2_LOADU(psm2_rr); fesm2 r = fesm2_mul(a, RR); return ifma_lnorm52(r); } static fesm2 fesm2_fast_reduction(const fesm2 a) { const fesm2 M = FESM2_LOADU(psm2_x1); const fesm2 zero = setzero_i64(); /* r = a - M */ fesm2 r = sub_i64(a, M); r = ifma_norm52(r); /* 1 < 0 */ const mask8 lt = cmp_i64_mask(zero, srli_i64(r, DIGIT_SIZE_52 - 1), _MM_CMPINT_LT); const mask8 mask = (mask8)((mask8)0 - ((lt >> 4) & 1)); /* mask != 0 ? a : r */ r = mask_mov_i64(r, mask, a); return r; } IPP_OWN_DEFN(fesm2, fesm2_from_mont, (const fesm2 a)) { const fesm2 ONE = FESM2_LOADU(ones); /* from mont */ fesm2 r = fesm2_mul(a, ONE); r = ifma_lnorm52(r); r = fesm2_fast_reduction(r); return r; } __IPPCP_INLINE fesm2 fesm2_mul_norm(const fesm2 a, const fesm2 b) { fesm2 r = fesm2_mul(a, b); return ifma_lnorm52(r); } __IPPCP_INLINE fesm2 fesm2_sqr_norm(const fesm2 a) { fesm2 r = fesm2_sqr(a); return ifma_lnorm52(r); } #define mul(R, A, B) (R) = fesm2_mul_norm((A), (B)) #define sqr(R, A) (R) = fesm2_sqr_norm((A)) #define mul_dual(R1, A1, B1, R2, A2, B2) \ fesm2_mul_dual(&(R1), (A1), (B1), &(R2), (A2), (B2)); \ ifma_lnorm52_dual(&(R1), (R1), &(R2), (R2)); __IPPCP_INLINE fesm2 fesm2_sqr_ntimes(const fesm2 a, int n) { fesm2 r = a; for (; n > 0; --n) sqr(r, r); return r; } #define sqr_ntimes(R, A, N) (R) = fesm2_sqr_ntimes((A), (N)) IPP_OWN_DEFN(fesm2, fesm2_inv_norm, (const fesm2 z)) { fesm2 tmp1, tmp2, D, E, F; tmp1 = tmp2 = D = E = F = setzero_i64(); fesm2 r; r = setzero_i64(); sqr(tmp1, z); mul(F, tmp1, z); /* F = z^3 */ sqr_ntimes(tmp2, F, 2); /* tmp2 = z^0xC */ /**/ mul_dual(D, tmp2, z, /* D = z^0xD */ E, tmp2, tmp1); /* E = z^0xE */ mul(F, tmp2, F); /* F = z^0xF */ /**/ sqr_ntimes(tmp2, F, 4); /* tmp2 = z^0xF0 */ /**/ mul_dual(D, tmp2, D, /* D = z^0xFD */ E, tmp2, E); /* E = z^0xFE */ mul(F, tmp2, F); /* F = z^0xFF */ /**/ sqr_ntimes(tmp2, F, 8); /* tmp2 = z^0xFF00 */ mul_dual(D, tmp2, D, /* D = z^0xFFFD */ E, tmp2, E); /* E = z^0xFFFE */ mul(F, tmp2, F); /* F = z^0xFFFF */ /**/ sqr_ntimes(tmp2, F, 16); /* tmp2 = z^0xFFFF0000 */ mul_dual(D, tmp2, D, /* D = z^0xFFFFFFFD */ E, tmp2, E); /* E = z^0xFFFFFFFE */ mul(F, tmp2, F); /* F = z^0xFFFFFFFF */ /**/ /**/ /* z ^ FFFFFFFE 00000000 */ sqr_ntimes(r, E, 32); /* z ^ FFFFFFFE FFFFFFFF */ mul(r, r, F); /* z ^ FFFFFFFE FFFFFFFF 00000000 */ sqr_ntimes(r, r, 32); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF */ mul(r, r, F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF 00000000 */ sqr_ntimes(r, r, 32); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF */ mul(r, r, F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 00000000 */ sqr_ntimes(r, r, 32); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF */ mul(r, r, F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 00000000 */ sqr_ntimes(r, r, 64); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF */ mul(r, r, F); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF 00000000 */ sqr_ntimes(r, r, 32); /* z ^ FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFD */ mul(r, r, D); return r; } IPP_OWN_DEFN(fesm2, fesm2_convert_radix64_radix52, (const Ipp64u* a)) { /* load mask to register */ const mask8 mask_load = 0x0F; const fesm2 mask_rad52 = set1_i64(DIGIT_MASK_52); /* set data */ const fesm2 idx16 = set_i64(0x001f001f00170016, // 31, 31, 23, 22, 0x0016001500140013, // 22, 21, 20, 19, 0x0013001200110010, // 19, 18, 17, 16, 0x0010000f000e000d, // 16, 15, 14, 13, 0x000c000b000a0009, // 12, 11, 10, 9, 0x0009000800070006, // 9, 8, 7, 6, 0x0006000500040003, // 6, 5, 4, 3, 0x0003000200010000); // 3, 2, 1, 0 const fesm2 shift_right = set_i64(12LL, 8LL, 4LL, 0LL, 12LL, 8LL, 4LL, 0LL); fesm2 r = maskz_loadu_i64(mask_load, a); r = permutexvar_i16(idx16, r); r = srlv_i64(r, shift_right); r = and_i64(mask_rad52, r); return r; } IPP_OWN_DEFN(void, fesm2_convert_radix52_radix64, (Ipp64u * out, const fesm2 a)) { /* mask store */ const mask8 mask_store = 0x0F; const fesm2 shift_left = set_i64(4LL, 0LL, 4LL, 0LL, 4LL, 0LL, 4LL, 0LL); const fesm2 idx_up8 = set_i64(0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3e3d3c3b, // {63,63,63,63,62,61,60,59} 0x3737363534333231, // {55,55,54,53,52,51,50,49} 0x302e2d2c2b2a2928, // {48,46,45,44,43,42,41,40} 0x1f1f1f1f1f1f1e1d, // {31,31,31,31,31,31,30,29} 0x1717171716151413, // {23,23,23,23,22,21,20,19} 0x0f0f0f0e0d0c0b0a, // {15,15,15,14,13,12,11,10} 0x0706050403020100); // { 7, 6, 5, 4, 3, 2, 1, 0} const fesm2 idx_down8 = set_i64(0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3f3f3f3f3f3f3f3f, // {63,63,63,63,63,63,63,63} 0x3a39383737373737, // {58,57,56,55,55,55,55,55} 0x2727272727272726, // {39,39,39,39,39,39,39,38} 0x2524232221201f1f, // {37,36,35,34,33,32,31,31} 0x1c1b1a1918171717, // {28,27,26,25,24,23,23,23} 0x1211100f0f0f0f0f, // {18,17,16,15,15,15,15,15} 0x0908070707070707); // { 9, 8, 7, 7, 7, 7, 7, 7} fesm2 r = a; r = sllv_i64(r, shift_left); fesm2 T = permutexvar_i8(idx_up8, r); r = permutexvar_i8(idx_down8, r); r = or_i64(r, T); mask_storeu_i64(out, mask_store, r); return; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_arith_psm2.h000066400000000000000000000111071470420105600262330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ARITH_PSM2_H_) #define _IFMA_ARITH_PSM2_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_alias_avx512.h" #include "gfpec/sm2/ifma_defs_sm2.h" #include "gfpec/ecnist/ifma_norm.h" /** * \brief * compute R = (-A) enhanced Montgomery (Gueron modification group operation) * \param[in] a value (in radix 2^52) * \return fesm2 value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_neg_norm, (const fesm2 a)) /** * \brief * * Montgomery multiplication * * a * b * r mod n, where r = 2^(6*52) mod n * * Note: final normalization to 2^52 radix is not performed and shall be * handled separately. * * \param[in] a first value (in radix 2^52) * \param[in] b second value (in radix 2^52) * \return fesm2 not normalization value */ IPP_OWN_DECL(fesm2, fesm2_mul, (const fesm2 a, const fesm2 b)) /** * \brief * * Montgomery multiplication * * a * a * r mod n, where r = 2^(6*52) mod n * * Note: final normalization to 2^52 radix is not performed and shall be * handled separately. * * \param[in] a value (in radix 2^52) * \return fesm2 not normalization value */ __IPPCP_INLINE IPP_OWN_DEFN(fesm2, fesm2_sqr, (const fesm2 a)) { return fesm2_mul(a, a); } /** * \brief * * Dual Montgomery multiplication without final normalization to 2^52 radix. * (two independent multiplications) * * a1 * b1 * R mod p * a2 * b2 * R mod p, where R = 2^(6*52) mod p * * \param[out] pr1 ptr first value no normalization * \param[in] a1 value first (in radix 2^52) * \param[in] b1 value second (in radix 2^52) * \param[out] pr2 ptr second value no normalization * \param[in] a2 value first (in radix 2^52) * \param[in] b2 value second (in radix 2^52) */ IPP_OWN_DECL(void, fesm2_mul_dual, (fesm2 pr1[], const fesm2 a1, const fesm2 b1, fesm2 pr2[], const fesm2 a2, const fesm2 b2)) /** * \brief * * Dual Montgomery multiplication without final normalization to 2^52 radix. * (two independent multiplications) * * a1 * a1 * R mod p * a2 * a2 * R mod p, where R = 2^(6*52) mod p * * \param[out] pr1 ptr first value no normalization * \param[in] a1 value (in radix 2^52) * \param[out] pr2 ptr second value no normalization * \param[in] a2 value (in radix 2^52) */ __IPPCP_INLINE IPP_OWN_DEFN(void, fesm2_sqr_dual, (fesm2 pr1[], const fesm2 a1, fesm2 pr2[], const fesm2 a2)) { fesm2_mul_dual(pr1, a1, a1, pr2, a2, a2); return; } /* R = A + B */ #define fesm2_add_no_red(A, B) add_i64((A), (B)) /* R = A - B */ #define fesm2_sub_no_red(A, B) sub_i64((A), (B)) /** * \brief * R = A/2 * \param[in] a value (in radix 2^52) * \return fe384 value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_div2_norm, (const fesm2 a)) /** * \brief * * Modular inverse modulo p. * * 1/z mod p * * \param[in] z value (in radix 2^52) * \return fesm2 value (in radix 2^52) */ IPP_OWN_DECL(fesm2, fesm2_inv_norm, (const fesm2 z)) /** * \brief * * Conversion to Montgomery domain modulo p. * * a * r mod p, where r = 2^(6*52) mod p * * \param[in] a value (in radix 2^52) * \return fesm2 value in Montgomery domain */ IPP_OWN_DECL(fesm2, fesm2_to_mont, (const fesm2 a)) /** * \brief * * Conversion from Montgomery domain modulo p. * * a mod p * * \param[in] a value (in radix 2^52) * \return fesm2 value from Montgomery */ IPP_OWN_DECL(fesm2, fesm2_from_mont, (const fesm2 a)) /** * \brief * convert radix 64 to (in radix 2^52) * \param[in] arad64 ptr array size (6) * \return fesm2 value in register 52 */ IPP_OWN_DECL(fesm2, fesm2_convert_radix64_radix52, (const Ipp64u* a)) /** * \brief * convert (in radix 2^52) to radix 64 * \param[out] rrad64 ptr array size (6) * \param[in] arad52 value (in radix 2^52) */ IPP_OWN_DECL(void, fesm2_convert_radix52_radix64, (Ipp64u * out, const fesm2 a)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ARITH_PSM2_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_defs_sm2.h000066400000000000000000000044311470420105600256670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_DEFS_SM2_H_) #define _IFMA_DEFS_SM2_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/ecnist/ifma_alias_avx512.h" typedef m512 fesm2; #define DIGIT_MASK_52 (0xFFFFFFFFFFFFF) #define DIGIT_SIZE_52 (52) #define PSM2_LEN52 (5) #define PSM2_LEN64 (4) #define REPL8(e) e, e, e, e, e, e, e, e /* from Montgomery conversion constant * one */ static const __ALIGN64 Ipp64u PSM2_ONE52[PSM2_LEN52] = {0x1, 0x0, 0x0, 0x0, 0x0}; /* Montgomery(1) * r = 2^(PSM2_LEN52*DIGIT_SIZE) mod psm2 */ /* r = 2^(52*6) mod psm2 */ static const __ALIGN64 Ipp64u PSM2_R[PSM2_LEN52] = { 0x0000000001000000, 0x000ffff000000010, 0x0000ffffffffffff, 0x0000000000000000, 0x0000010000000000}; /** * \brief * check is most significant bit * \return mask8 * 0xFF - is equal one * 0x00 - is no equal one */ __IPPCP_INLINE mask8 sm2_is_msb(const mask8 a) { return (mask8)((mask8)0 - (a >> 7)); } /** * \brief * check is zero input value * \param[in] value * \return mask8 * 0xFF - is zero value * 0x00 - no equal zero */ __IPPCP_INLINE mask8 sm2_is_zero_i64(const m512 a) { const mask8 mask = cmp_i64_mask(a, setzero_i64(), _MM_CMPINT_NE); return sm2_is_msb((~mask & (mask - 1))); } #define FESM2_LOADU(A) maskz_loadu_i64(0x1F, (A)) #define FESM2_IS_ZERO(A) sm2_is_zero_i64((A)) #define FESM2_CMP_MASK(A, B, ENUM_CMP) cmp_i64_mask((A), (B), (ENUM_CMP)) #define FESM2_MASK_MOV(R, SRC, MASK, A) (R) = mask_mov_i64((SRC), (MASK), (A)) #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_DEFS_SM2_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_addpoint_sm2.c000066400000000000000000000035131470420105600272120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_AddPoint_sm2_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const IppsGFpECPoint* pQ, IppsGFpECState* pEC)) { gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod* pmeth = (ifmaArithMethod*)GFP_METHOD_ALT(pME); __ALIGN64 PSM2_POINT_IFMA P, R; BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPool, pmeth, pME); if (pP == pQ) { gesm2_dbl(&R, &P); } else { __ALIGN64 PSM2_POINT_IFMA Q; recode_point_to_mont52(&Q, ECP_POINT_DATA(pQ), pPool, pmeth, pME); gesm2_add(&R, &P, &Q); } recode_point_to_mont64(pR, &R, pPool, pmeth, pME); cpGFpReleasePool(3, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_dh_sm2.c000066400000000000000000000051611470420105600260040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/sm2/ifma_defs_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" IPP_OWN_DEFN(int, gfec_SharedSecretDH_sm2_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod* pmeth = (ifmaArithMethod*)GFP_METHOD_ALT(pME); ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Copy scalar */ BNU_CHUNK_T* pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 PSM2_POINT_IFMA P52, R52; BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); /* Convert point coordinates to a new Montgomery domain */ recode_point_to_mont52(&P52, ECP_POINT_DATA(pP), pPool, pmeth, pME); gesm2_mul(&R52, &P52, (Ipp8u*)pExtendedScalar, orderBits); /* Check if the point - point to infinity */ const mask8 is_zero_z = FESM2_IS_ZERO(R52.z); int finite_point = ((mask8)0xFF != is_zero_z); /* Get X affine coordinate */ gesm2_to_affine(/* x = */ &(R52.x), /* y = */ NULL, /* a = */ &R52); R52.x = p_from_mont(R52.x); from_radix52(ECP_POINT_X(pR), R52.x); cpGFpReleasePool(5, pME); return finite_point; } } #endif // IPP32E >= _IPP32E_K1 cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_mulpoint_sm2.c000066400000000000000000000043611470420105600272610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_MulPoint_sm2_avx512, (IppsGFpECPoint * pR, const IppsGFpECPoint* pP, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod* pmeth = (ifmaArithMethod*)GFP_METHOD_ALT(pME); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T* pPool = cpGFpGetPool(5, pME); BNU_CHUNK_T* pExtendedScalar = pPool; /* 2 pool elem to hold scalar */ BNU_CHUNK_T* pPointPool = pPool + 2 * elemLen; /* 3 pool elem to to hold 3 point coordinates */ /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 PSM2_POINT_IFMA P, R; recode_point_to_mont52(&P, ECP_POINT_DATA(pP), pPointPool, pmeth, pME); gesm2_mul(&R, &P, (Ipp8u*)pExtendedScalar, orderBits); recode_point_to_mont64(pR, &R, pPointPool, pmeth, pME); cpGFpReleasePool(5, pME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_on_curve_sm2.c000066400000000000000000000027731470420105600272370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/ecnist/ifma_arith_method.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" IPP_OWN_DEFN(int, gfec_point_on_curve_sm2_avx512, (const IppsGFpECPoint *pPoint, IppsGFpECState *pEC)) { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); __ALIGN64 PSM2_POINT_IFMA P; recode_point_to_mont52(&P, ECP_POINT_DATA(pPoint), pPool /* 3 elem */, pmeth, pME); const int onCurve = gesm2_is_on_curve(&P, /* use_jproj_coord = */ !IS_ECP_AFFINE_POINT(pPoint)); cpGFpReleasePool(3, pME); return onCurve; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_pubkey_sm2.c000066400000000000000000000050431470420105600267070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" #include "gfpec/sm2/ifma_arith_psm2.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" IPP_OWN_DEFN(IppsGFpECPoint*, gfec_PubKey_sm2_avx512, (IppsGFpECPoint * pR, const BNU_CHUNK_T* pScalar, int scalarLen, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { FIX_BNU(pScalar, scalarLen); { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine* nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod* pmeth = (ifmaArithMethod*)GFP_METHOD_ALT(pME); BNU_CHUNK_T* pPool = cpGFpGetPool(5, nME); BNU_CHUNK_T* pExtendedScalar = pPool; BNU_CHUNK_T* pPointPool = pExtendedScalar + 2 * GFP_FELEN(pME); /* Copy scalar */ cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, pScalar, scalarLen); __ALIGN64 PSM2_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); if (ECP_PREMULBP(pEC)) { gesm2_mul_base(&R, (Ipp8u*)pExtendedScalar); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 PSM2_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPointPool /* 3 elem */, pmeth, pME); gesm2_mul(&R, &G52, (Ipp8u*)pExtendedScalar, orderBits); } recode_point_to_mont64(pR, &R, pPointPool /* 3 elem */, pmeth, pME); cpGFpReleasePool(5, nME); ECP_POINT_FLAGS(pR) = gfec_IsPointAtInfinity(pR) ? 0 : ECP_FINITE_POINT; return pR; } } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_sign_sm2.c000066400000000000000000000126151470420105600263530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/sm2/ifma_defs_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" IPP_OWN_DEFN(IppStatus, gfec_Sign_sm2_avx512, (const IppsBigNumState* pMsgDigest, const IppsBigNumState* pRegPrivate, IppsBigNumState* pEphPrivate, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppStatus sts = ippStsNoErr; gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine* nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); ifmaArithMethod* pmeth = (ifmaArithMethod*)GFP_METHOD_ALT(pME); ifmaArithMethod* nmeth = (ifmaArithMethod*)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_add n_add = nmeth->add; ifma_add n_sub = nmeth->sub; ifma_inv n_inv = nmeth->inv; ifma_red n_red = nmeth->red; fesm2 sign_r, sign_s; sign_r = sign_s = setzero_i64(); /* compute r-component * 1) (x1,y1) = [s]G * 2) r = (e + x1) mod n */ /* 1) (x1,y1) = [s]G */ /* copy scalar */ BNU_CHUNK_T* pExtendedScalar = cpGFpGetPool(2, pME); cpGFpElementCopyPad(pExtendedScalar, orderLen + 1, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); __ALIGN64 PSM2_POINT_IFMA P; if (ECP_PREMULBP(pEC)) { gesm2_mul_base(&P, (Ipp8u*)pExtendedScalar); } else { BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); /* Convert base point to a new Montgomery domain */ __ALIGN64 PSM2_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool, pmeth, pME); gesm2_mul(&P, &G52, (Ipp8u*)pExtendedScalar, orderBits); cpGFpReleasePool(3, pME); } /* extract affine P.x */ gesm2_to_affine(/* x = */ &(P.x), /* y = */ NULL, /* a = */ &P); P.x = p_from_mont(P.x); P.x = n_red(P.x); /* 2) r = (e + x1) mod n */ BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pME); fesm2 msg = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); msg = to_radix52((Ipp64u*)pTmp); msg = n_red(msg); /* reduce just in case */ msg = n_to_mont(msg); P.x = n_to_mont(P.x); sign_r = n_add(msg, P.x); /* check r == 0 or r + k == n(0) */ /* r == 0 */ const mask8 sign_r_err_zeros = FESM2_IS_ZERO(sign_r); /* r + k == 0 */ /* extract k */ fesm2 eph_key = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pEphPrivate), BN_SIZE(pEphPrivate)); eph_key = to_radix52((Ipp64u*)pTmp); eph_key = n_to_mont(eph_key); fesm2 t; t = n_add(eph_key, sign_r); const mask8 rpk_err_zeros = FESM2_IS_ZERO(t); if (((mask8)0xFF == sign_r_err_zeros) || ((mask8)0xFF == rpk_err_zeros)) sts = ippStsEphemeralKeyErr; fesm2 reg_key = setzero_i64(); ZEXPAND_COPY_BNU(pTmp, orderLen, BN_NUMBER(pRegPrivate), BN_SIZE(pRegPrivate)); reg_key = to_radix52((Ipp64u*)pTmp); const fesm2 one = FESM2_LOADU(PSM2_ONE52); t = n_to_mont(one); reg_key = n_to_mont(reg_key); sign_s = n_mul(sign_r, reg_key); /* sign_s = r * d */ reg_key = n_add(reg_key, t); /* reg_key = 1 + d */ reg_key = n_inv(reg_key); /* reg_key = (1 + d)^(-1) */ sign_s = n_sub(eph_key, sign_s); /* sign_s = (k - r * d) */ sign_s = n_mul(sign_s, reg_key); /* sign_s = (1 + d)^(-1) * (k - r * d) */ sign_s = n_from_mont(sign_s); sign_r = n_from_mont(sign_r); const mask8 is_zero = (mask8)(FESM2_IS_ZERO(sign_r) | FESM2_IS_ZERO(sign_s)); if ((mask8)0xFF == is_zero) sts = ippStsEphemeralKeyErr; // return sign_s from_radix52((Ipp64u*)pTmp, sign_s); ZEXPAND_COPY_BNU(BN_NUMBER(pSignS), BN_SIZE(pSignS), pTmp, orderLen); // return sign_r from_radix52((Ipp64u*)pTmp, sign_r); ZEXPAND_COPY_BNU(BN_NUMBER(pSignR), BN_SIZE(pSignR), pTmp, orderLen); /* clear secret data */ clear_secrets(&eph_key, &(P.x), &t); clear_secrets(&sign_r, &sign_s, ®_key); /* clear buffer */ cpGFpReleasePool(3, pME); /* pExtendedScalar(2) + tmp(1) */ return sts; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ec_verify_sm2.c000066400000000000000000000117241470420105600267170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" IPP_OWN_DEFN(IppECResult, gfec_Verify_sm2_avx512, (const IppsBigNumState* pMsgDigest, const IppsGFpECPoint* pRegPublic, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); IppECResult verifyResult = ippECInvalidSignature; gsModEngine* pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine* nME = ECP_MONT_R(pEC); const int orderBits = ECP_ORDBITSIZE(pEC); const int orderLen = BITS_BNU_CHUNK(orderBits); const int elemLen = GFP_FELEN(pME); ifmaArithMethod* pmeth = (ifmaArithMethod*)GFP_METHOD_ALT(pME); ifmaArithMethod* nmeth = (ifmaArithMethod*)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod p) */ ifma_decode p_from_mont = pmeth->decode; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_add n_add = nmeth->add; ifma_red n_red = nmeth->red; /* init message | sign_r | sing_s */ fesm2 msg, sign_r, sign_s, t; msg = sign_r = sign_s = t = setzero_i64(); /* buffer extract msg */ BNU_CHUNK_T* pPool = cpGFpGetPool(3, pME); BNU_CHUNK_T* pBufMsg = pPool; BNU_CHUNK_T* pBufSignR = pPool + elemLen; BNU_CHUNK_T* pBufSignS = pPool + 2 * elemLen; ZEXPAND_COPY_BNU(pBufMsg, orderLen, BN_NUMBER(pMsgDigest), BN_SIZE(pMsgDigest)); ZEXPAND_COPY_BNU(pBufSignS, orderLen, BN_NUMBER(pSignS), BN_SIZE(pSignS)); ZEXPAND_COPY_BNU(pBufSignR, orderLen, BN_NUMBER(pSignR), BN_SIZE(pSignR)); /* radix64 -> radix52 */ msg = to_radix52((Ipp64u*)pBufMsg); msg = n_red(msg); /* reduce just in case */ sign_r = to_radix52((Ipp64u*)pBufSignR); sign_s = to_radix52((Ipp64u*)pBufSignS); /* Convert public point to proper Montgomery domain and 2^52 radix */ __ALIGN64 PSM2_POINT_IFMA P; recode_point_to_mont52(&P, ECP_POINT_DATA(pRegPublic), pPool /* 3 elem */, pmeth, pME); /* compute t = (r + s) mod n */ t = n_to_mont(sign_r); sign_s = n_to_mont(sign_s); t = n_add(sign_s, t); t = n_from_mont(t); /* check zeros t != 0 */ const mask8 sign_err_mask = FESM2_IS_ZERO(t); if ((mask8)0xFF == sign_err_mask) verifyResult = ippECInvalidSignature; BNU_CHUNK_T* pExtendedS = cpGFpGetPool(2, pME); BNU_CHUNK_T* pExtendedT = cpGFpGetPool(2, pME); BNU_CHUNK_T* pTmp = cpGFpGetPool(1, pME); /* compute [s]G + t[P] */ /* copmute [s]G */ __ALIGN64 PSM2_POINT_IFMA sG; /* create s */ cpGFpElementCopyPad(pExtendedS, orderLen + 1, pBufSignS, orderLen); if (ECP_PREMULBP(pEC)) { gesm2_mul_base(&sG, (Ipp8u*)pExtendedS); } else { /* Convert base point to a new Montgomery domain */ __ALIGN64 PSM2_POINT_IFMA G52; recode_point_to_mont52(&G52, ECP_G(pEC), pPool /* 3 elem */, pmeth, pME); gesm2_mul(&sG, &G52, (Ipp8u*)pExtendedS, orderBits); } /* create t */ from_radix52((Ipp64u*)pTmp, t); cpGFpElementCopyPad(pExtendedT, orderLen + 1, pTmp, orderLen); /* compute [t]P */ gesm2_mul(&P, &P, (Ipp8u*)pExtendedT, orderBits); /* compute [s]G + [t]P */ gesm2_add(&P, &P, &sG); fesm2 sign_r_restore; /* extract X affine coordinate */ gesm2_to_affine(/* x = */ &sign_r_restore, /* y = */ NULL, &P); sign_r_restore = p_from_mont(sign_r_restore); /* x = x mod n */ sign_r_restore = n_red(sign_r_restore); /* R = (e + x1) mod n */ msg = n_to_mont(msg); sign_r_restore = n_to_mont(sign_r_restore); sign_r_restore = n_add(msg, sign_r_restore); sign_r_restore = n_from_mont(sign_r_restore); const mask8 mask_ok = cmp_i64_mask(sign_r_restore, sign_r, _MM_CMPINT_EQ); if ((mask8)0xFF == mask_ok) verifyResult = ippECValid; cpGFpReleasePool(8, pME); return verifyResult; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ecpoint_sm2.c000066400000000000000000000577141470420105600264160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/ifma_arith_psm2.h" #include "gfpec/sm2/ifma_defs_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" /* 2*p */ static const __ALIGN64 Ipp64u psm2_x2[PSM2_LEN52] = { 0x000ffffffffffffe, 0x000fe00000001fff, 0x000fffffffffffff, 0x000fffffffffffff, 0x0001fffffffdffff}; /* 4*p */ static const __ALIGN64 Ipp64u psm2_x4[PSM2_LEN52] = { 0x000ffffffffffffc, 0x000fc00000003fff, 0x000fffffffffffff, 0x000fffffffffffff, 0x0003fffffffbffff}; /* 6*p */ static const __ALIGN64 Ipp64u psm2_x6[PSM2_LEN52] = { 0x000ffffffffffffa, 0x000fa00000005fff, 0x000fffffffffffff, 0x000fffffffffffff, 0x0005fffffff9ffff}; /* 8*p */ static const __ALIGN64 Ipp64u psm2_x8[PSM2_LEN52] = { 0x000ffffffffffff8, 0x000f800000007fff, 0x000fffffffffffff, 0x000fffffffffffff, 0x0007fffffff7ffff}; /* Mont(a) = a*r mod psm2, where r = 2^(6*52) mod psm2 */ static const __ALIGN64 Ipp64u psm2_a[PSM2_LEN52] = { 0x000ffffffcffffff, 0x000ff03000000fcf, 0x000cffffffffffff, 0x000fffffffffffff, 0x0000fcfffffeffff}; /* Mont(b) = b*r mod psm2, where r = 2^(6*52) mod psm2 */ static const __ALIGN64 Ipp64u psm2_b[PSM2_LEN52] = { 0x00040fe188de30c4, 0x00012da4d9019422, 0x000b0dc519344af3, 0x000a51c3c71cf379, 0x00005130aa45505e}; #define add(R, A, B) (R) = fesm2_add_no_red((A), (B)) #define sub(R, A, B) (R) = fesm2_sub_no_red((A), (B)) #define mul(R, A, B) (R) = fesm2_mul((A), (B)) #define sqr(R, A) (R) = fesm2_sqr((A)) #define div2(R, A) (R) = fesm2_div2_norm((A)) #define norm(R, A) (R) = ifma_norm52((A)) #define lnorm(R, A) (R) = ifma_lnorm52((A)) #define inv(R, A) (R) = fesm2_inv_norm((A)) #define from_mont(R, A) (R) = fesm2_from_mont((A)) /* duplicate mult/sqr/norm */ #define mul_dual(R1, A1, B1, R2, A2, B2) fesm2_mul_dual(&(R1), (A1), (B1), &(R2), (A2), (B2)) #define sqr_dual(R1, A1, R2, A2) fesm2_sqr_dual(&(R1), (A1), &(R2), (A2)) #define norm_dual(R1, A1, R2, A2) ifma_norm52_dual(&(R1), (A1), &(R2), (A2)) #define lnorm_dual(R1, A1, R2, A2) ifma_lnorm52_dual(&(R1), (A1), &(R2), (A2)) IPP_OWN_DEFN(void, gesm2_to_affine, (fesm2 prx[], fesm2 pry[], const PSM2_POINT_IFMA* a)) { fesm2 z1, z2, z3; z1 = z2 = z3 = setzero_i64(); inv(z1, a->z); /* 1/z */ sqr(z2, z1); /* (1/z)^2 */ lnorm(z2, z2); /**/ /* x = x/z^2 */ if (NULL != prx) { mul(*prx, a->x, z2); /* x = x/z^2 */ lnorm(*prx, *prx); /**/ } /* y = y/z^3 */ if (NULL != pry) { mul(z3, z1, z2); /* (1/z)^3 */ lnorm(z3, z3); /**/ mul(*pry, a->y, z3); /* y = y/z^3 */ lnorm(*pry, *pry); /**/ } return; } IPP_OWN_DEFN(void, gesm2_dbl, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * l1 = 3x^2 + a*z^4 = (if sm2 a = -3) = 3*(x^2 - z^4) = 3*(x - z^2)*(x + z^2) * z2 = 2*y*z * l2 = 4*x*y^2 * x2 = l1^2 - 2*l2 * l3 = 8*y^4 * y2 = l1*(l2 - x2) - l3 * * sum aripmetic: 8 mul; 9 add/sub; 1 div2. */ const fesm2* x1 = &p->x; const fesm2* y1 = &p->y; const fesm2* z1 = &p->z; fesm2 x2; fesm2 y2; fesm2 z2; x2 = y2 = z2 = setzero_i64(); fesm2 T, U, V, A, B, H; T = U = V = setzero_i64(); A = B = H = setzero_i64(); const fesm2 M2 = FESM2_LOADU(psm2_x2); /* 2*p */ const fesm2 M4 = FESM2_LOADU(psm2_x4); /* 4*p */ const fesm2 M8 = FESM2_LOADU(psm2_x8); /* 8*p */ add(T, *y1, *y1); /* T = 2*y1 */ lnorm(T, T); /**/ /*=====*/ sqr_dual(V, T, /* V = 4*y1^2 */ U, *z1); /* U = z1^2 */ /*=====*/ sub(B, *x1, U); /* B = 2*p + x1 - z1^2 */ add(B, B, M2); /**/ add(U, *x1, U); /* U = x1 + z1^2 */ /*=====*/ /* normalization */ lnorm_dual(V, V, /**/ U, U); /**/ norm(B, B); /**/ /*=====*/ mul_dual(A, V, *x1, /* A = 4*x1*y1^2 */ B, B, U); /* B = (x1 - z1^2)*(x1 + z1^2) */ /*=====*/ add(x2, A, A); /* x2 = 8*x1*y1^2 (4p) */ add(H, B, B); /**/ add(B, B, H); /* B(l1) = 3*(x1 - z1^2)*(x1 + z1^2) */ /*=====*/ /* normalization */ lnorm(B, B); /**/ /*=====*/ sqr_dual(U, B, /* U = l1^2 */ y2, V); /* y2 = 16*y^2 */ /*=====*/ sub(x2, U, x2); /* x2 = 4*p + l1^2 - 2*l2 */ add(x2, x2, M4); /**/ div2(y2, y2); /**/ /*=====*/ sub(U, A, x2); /* U = 8*p + l2 - x2 */ add(U, U, M8); /**/ /*=====*/ /* normalization */ norm(U, U); /**/ /*=====*/ mul_dual(z2, T, *z1, /* z2 = 2*y1*z1 */ U, U, B); /* U = B(l1)*(A(l2) - x2) */ /*=====*/ sub(y2, U, y2); /* y2 = 2*p + B(l1)*(A(l2) - x2) - y2(l3) */ add(y2, y2, M2); /**/ /*=====*/ /* normalization */ norm_dual(r->x, x2, /**/ r->y, y2); /**/ lnorm(r->z, z2); /**/ return; } IPP_OWN_DEFN(void, gesm2_add, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p, const PSM2_POINT_IFMA* q)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * A = x1*z2^2 B = x2*z1^2 C = y1*z2^3 D = y2*z1^3 * E = B - A F = D - C * x3 = -E^3 - 2*A*E^2 + F^2 * y3 = -C*E^3 + F*(A*E^2 - x3) * z3 = z1*z2*E */ const fesm2* x1 = &p->x; const fesm2* y1 = &p->y; const fesm2* z1 = &p->z; const mask8 p_is_inf = FESM2_IS_ZERO(p->z); const fesm2* x2 = &q->x; const fesm2* y2 = &q->y; const fesm2* z2 = &q->z; const mask8 q_is_inf = FESM2_IS_ZERO(q->z); fesm2 x3; fesm2 y3; fesm2 z3; x3 = y3 = z3 = setzero_i64(); const fesm2 M2 = FESM2_LOADU(psm2_x2); /* 2*p */ const fesm2 M4 = FESM2_LOADU(psm2_x4); /* 4*p */ const fesm2 M8 = FESM2_LOADU(psm2_x8); /* 8*p */ fesm2 U1, U2, S1, S2, H, R; U1 = U2 = S1 = setzero_i64(); S2 = H = R = setzero_i64(); mul_dual(S1, *y1, *z2, /* s1 = y1*z2 */ U1, *z2, *z2); /* u1 = z2^2 */ /*=====*/ /* normalization */ lnorm_dual(S1, S1, /**/ U1, U1); /**/ /*=====*/ mul_dual(S2, *y2, *z1, /* s2 = y2*z1 */ U2, *z1, *z1); /* u2 = z1^2 */ /*=====*/ /* normalization */ lnorm_dual(S2, S2, /**/ U2, U2); /**/ /*=====*/ mul_dual(S1, S1, U1, /* s1 = y1*z2^3 (C) */ S2, S2, U2); /* s2 = y2*z1^3 (D) */ /*=====*/ /* normalization */ lnorm_dual(S1, S1, /**/ S2, S2); /* (need by correct compute F = D - C) */ /*=====*/ mul_dual(U1, *x1, U1, /* u1 = x1*z2^2 (A) */ U2, *x2, U2); /* u2 = x2*z1^2 (B) */ /*=====*/ /* normalization */ lnorm_dual(U1, U1, /**/ U2, U2); /**/ /*=====*/ sub(R, S2, S1); /* r = D - C (F) */ sub(H, U2, U1); /* h = B - A (E) */ /* checking the equality of X and Y coordinates (D - C == 0) and (B - A == 0) */ const mask8 f_are_zero = FESM2_IS_ZERO(R); const mask8 e_are_zero = FESM2_IS_ZERO(H); const mask8 point_is_equal = ((e_are_zero & f_are_zero) & (~p_is_inf) & (~q_is_inf)); __ALIGN64 PSM2_POINT_IFMA r2; r2.x = r2.y = r2.z = setzero_i64(); if ((mask8)0xFF == point_is_equal) { gesm2_dbl(&r2, p); } add(R, R, M2); /**/ add(H, H, M2); /**/ /*=====*/ /* normalization */ norm_dual(R, R, /**/ H, H); /**/ /**/ mul_dual(z3, *z1, *z2, /* z3 = z1*z2 */ U2, H, H); /* u2 = E^2 */ /*=====*/ /* normalization */ lnorm_dual(z3, z3, /**/ U2, U2); /**/ /**/ mul_dual(z3, z3, H, /* z3 = (z1*z2)*E */ S2, R, R); /* s2 = F^2 */ mul(H, H, U2); /* h = E^3 */ /*=====*/ /* normalization */ lnorm(H, H); /**/ /*=====*/ mul(U1, U1, U2); /* u1 = A*E^2 */ sub(x3, S2, H); /* x3 = F^2 - E^3 */ add(x3, x3, M2); /**/ add(U2, U1, U1); /* u2 = 2*A*E^2 */ mul(S1, S1, H); /* s1 = C*E^3 */ sub(x3, x3, U2); /* x3 = (F^2 - E^3) -2*A*E^2 */ add(x3, x3, M4); /**/ /*=====*/ sub(y3, U1, x3); /* y3 = A*E^2 - x3 */ add(y3, y3, M8); /**/ /*=====*/ /* normalization */ norm(y3, y3); /**/ /**/ mul(y3, y3, R); /* y3 = F*(A*E^2 - x3) */ sub(y3, y3, S1); /* y3 = F*(A*E^2 - x3) - C*E^3 */ add(y3, y3, M2); /* normalization */ norm_dual(x3, x3, /**/ y3, y3); /**/ lnorm(z3, z3); /**/ /* T = p_is_inf ? q : T */ FESM2_MASK_MOV(x3, x3, p_is_inf, *x2); FESM2_MASK_MOV(y3, y3, p_is_inf, *y2); FESM2_MASK_MOV(z3, z3, p_is_inf, *z2); /* T = q_is_inf ? p : T */ FESM2_MASK_MOV(x3, x3, q_is_inf, *x1); FESM2_MASK_MOV(y3, y3, q_is_inf, *y1); FESM2_MASK_MOV(z3, z3, q_is_inf, *z1); /* r = point_is_equal ? r2 : T */ FESM2_MASK_MOV(x3, x3, point_is_equal, r2.x); FESM2_MASK_MOV(y3, y3, point_is_equal, r2.y); FESM2_MASK_MOV(z3, z3, point_is_equal, r2.z); r->x = x3; r->y = y3; r->z = z3; return; } IPP_OWN_DEFN(void, gesm2_add_affine, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p, const PSM2_AFFINE_POINT_IFMA* q)) { /* * Algorithm (Gueron - Enhanced Montgomery Multiplication) * * A = x1 B = x2*z1^2 C = y1 D = y2*z1^3 * E = B - A(x1) F = D - C(y1) * x3 = -E^3 - 2*A(x1)*E^2 + F^2 * y3 = -C(y1)*E^3 + F*(A(x1)*E^2 - x3) * z3 = z1*E */ /* coordinates of p (jacobian projective) */ const fesm2* x1 = &p->x; const fesm2* y1 = &p->y; const fesm2* z1 = &p->z; const mask8 p_is_inf = FESM2_IS_ZERO(p->z); /* coordinate of q (affine) */ const fesm2* x2 = &q->x; const fesm2* y2 = &q->y; const mask8 q_is_inf = (FESM2_IS_ZERO(q->x) & FESM2_IS_ZERO(q->y)); fesm2 x3; fesm2 y3; fesm2 z3; x3 = y3 = z3 = setzero_i64(); const fesm2 M2 = FESM2_LOADU(psm2_x2); /* 2*p */ const fesm2 M4 = FESM2_LOADU(psm2_x4); /* 4*p */ const fesm2 M8 = FESM2_LOADU(psm2_x8); /* 8*p */ fesm2 U2, S2, H, R; U2 = S2 = H = R = setzero_i64(); mul_dual(R, *z1, *z1, /* R = z1^2 */ S2, *y2, *z1); /* S2 = y2*z1 */ /*=====*/ lnorm_dual(R, R, /**/ S2, S2); /**/ /*=====*/ mul_dual(U2, *x2, R, /* U2 = x2*z1^2 (B) */ S2, S2, R); /* S2 = y2*z1^3 (D) */ /**/ sub(H, U2, *x1); /* H = B - A (E) */ add(H, H, M8); /**/ sub(R, S2, *y1); /* R = D - C (F) */ add(R, R, M4); /**/ /*=====*/ norm_dual(H, H, /**/ R, R); /**/ /**/ mul(z3, H, *z1); /* z3 = z1*E */ /**/ sqr_dual(U2, H, /* U2 = E^2 */ S2, R); /* S2 = F^2 */ /**/ lnorm(U2, U2); /**/ /**/ mul(H, H, U2); /* H = E^3 */ /**/ lnorm(H, H); /**/ /**/ mul_dual(U2, U2, *x1, /* U2 = A*E^2 */ y3, H, *y1); /* y3 = C*E^3 */ /**/ add(x3, U2, U2); /* x2 = 2*A*E^2 */ sub(x3, S2, x3); /* x3 = F^2 - 2*A*E^2 */ add(x3, x3, M4); /**/ sub(x3, x3, H); /* x3 = F^2 - 2*A*E^2 - E^3 */ add(x3, x3, M2); /**/ /**/ sub(U2, U2, x3); /* U2 = A*E^2 - x3 */ add(U2, U2, M8); /**/ norm(U2, U2); /**/ mul(U2, U2, R); /* U2 = F*(A*E^2 - x3) */ sub(y3, U2, y3); /* y3 = F*(A*E^2 - x3) - C*E^2 */ add(y3, y3, M2); /**/ /* normalization */ norm_dual(x3, x3, /**/ y3, y3); /**/ lnorm(z3, z3); /**/ const fesm2 ONE = FESM2_LOADU(PSM2_R); /* T = p_is_inf ? q : T */ FESM2_MASK_MOV(x3, x3, p_is_inf, *x2); FESM2_MASK_MOV(y3, y3, p_is_inf, *y2); FESM2_MASK_MOV(z3, z3, p_is_inf, ONE); /* T = q_is_inf ? p : T */ FESM2_MASK_MOV(x3, x3, q_is_inf, *x1); FESM2_MASK_MOV(y3, y3, q_is_inf, *y1); FESM2_MASK_MOV(z3, z3, q_is_inf, *z1); r->x = x3; r->y = y3; r->z = z3; return; } IPP_OWN_DEFN(int, gesm2_is_on_curve, (const PSM2_POINT_IFMA* p, const int use_jproj_coords)) { /* * Algorithm * * y^2 = x^3 + a*x + b (1) * * if input * * Jacobian projection coordinate (x,y,z) - represent by (x/z^2,y/z^3,1) * * Affine coordinate (x/z^2,y/z^3,z/z=1) * * mult formala (1) by z^6 * * y^2 = x^3 + a*x*z^4 + b*z^6 */ const fesm2 M6 = FESM2_LOADU(psm2_x6); const fesm2 a = FESM2_LOADU(psm2_a); const fesm2 b = FESM2_LOADU(psm2_b); fesm2 rh, Z4, Z6, tmp; rh = Z4 = Z6 = tmp = setzero_i64(); sqr(rh, p->x); /* rh = x^2 */ /* rh = x*(x^2 + a*z^4) + b*z^6 = x*(x^2 - 3*z^4) + b*z^6 */ if (0 != use_jproj_coords) { sqr(tmp, p->z); /* tmp = z^2 */ lnorm(tmp, tmp); /**/ /**/ sqr(Z4, tmp); /* z4 = z^4 */ lnorm(Z4, Z4); /**/ mul(Z6, Z4, tmp); /* z6 = z^6 */ lnorm(Z6, Z6); /**/ /**/ add(tmp, Z4, Z4); /* tmp = 2*z^4 */ add(tmp, tmp, Z4); /* tmp = 3*z^4 */ /**/ sub(rh, rh, tmp); /* rh = x^2 - 3*z^4 */ add(rh, rh, M6); /**/ norm(rh, rh); /**/ /**/ mul_dual(rh, rh, p->x, /* rh = x*(x^2 - 3*z^4) */ tmp, Z6, b); /* tmp = b*z^6 */ /**/ add(rh, rh, tmp); /* rh = x*(x^2 - 3*z^4) + b*z^6 */ } /* rh = x*(x^2 + a) + b */ else { add(rh, rh, a); /* rh = x^2 + a */ lnorm(rh, rh); /**/ mul(rh, rh, p->x); /* rh = x*(x^2 + a) */ add(rh, rh, b); /* rh = x*(x^2 + a) + b */ } lnorm(rh, rh); /**/ /* rl = Y^2 */ sqr(tmp, p->y); /* tmp = y^2 */ lnorm(tmp, tmp); /**/ /* from mont */ from_mont(tmp, tmp); from_mont(rh, rh); const mask8 mask = FESM2_CMP_MASK(rh, tmp, _MM_CMPINT_EQ); return (mask == 0xFF) ? 1 : 0; } #undef add #undef sub #undef mul #undef sqr #undef div2 #undef norm #undef from_mont #undef mul_dual #undef sqr_dual #undef norm_dual static __NOINLINE void clear_secret_context(Ipp16u* wval, Ipp32s* chunk_no, Ipp32s* chunk_shift, Ipp8u* sign, Ipp8u* digit, PSM2_POINT_IFMA* R, PSM2_POINT_IFMA* H, PSM2_AFFINE_POINT_IFMA* A) { *wval = 0; *chunk_no = 0; *chunk_shift = 0; *sign = 0; *digit = 0; if (NULL != R) (*R).x = (*R).y = (*R).z = setzero_i64(); if (NULL != H) (*H).x = (*H).y = (*H).z = setzero_i64(); if (NULL != A) (*A).x = (*A).y = setzero_i64(); return; } __IPPCP_INLINE mask8 is_eq_mask(const Ipp32s a, const Ipp32s b) { const Ipp32s eq = a ^ b; const Ipp32s v = ~eq & (eq - 1); const Ipp32s msb = 0 - (v >> (sizeof(a) * 8 - 1)); return (mask8)(0 - msb); } #define WIN_SIZE (5) static void table_get_point(PSM2_POINT_IFMA* r, const Ipp32s digit, const PSM2_POINT_IFMA tbl[]) { const Ipp32s idx = digit - 1; __ALIGN64 PSM2_POINT_IFMA R; R.x = R.y = R.z = setzero_i64(); for (Ipp32s n = 0; n < (1 << (WIN_SIZE - 1)); ++n) { const mask8 mask = is_eq_mask(n, idx); FESM2_MASK_MOV(R.x, R.x, mask, tbl[n].x); FESM2_MASK_MOV(R.y, R.y, mask, tbl[n].y); FESM2_MASK_MOV(R.z, R.z, mask, tbl[n].z); } r->x = R.x; r->y = R.y; r->z = R.z; return; } #define dbl_point gesm2_dbl #define add_point gesm2_add #define neg_coord(R, A) (R) = fesm2_neg_norm((A)) #define add_point_affine gesm2_add_affine /* r = n*P = (P + P + ... + P) */ IPP_OWN_DEFN(void, gesm2_mul, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p, const Ipp8u* pExtendedScalar, const int scalarBitSize)) { /* default params */ __ALIGN64 PSM2_POINT_IFMA tbl[(1 << (WIN_SIZE - 1))]; __ALIGN64 PSM2_POINT_IFMA R; __ALIGN64 PSM2_POINT_IFMA H; fesm2 negHy; negHy = setzero_i64(); R.x = R.y = R.z = setzero_i64(); H.x = H.y = H.z = setzero_i64(); /* compute tbl[] = [n]P, n = 1, ... , 2^(win_size - 1) * tbl[2*n] = tbl[2*n - 1] + p * tbl[2*n + 1] = [2]*tbl[n] */ /* tbl[0] = p */ tbl[0].x = p->x; tbl[0].y = p->y; tbl[0].z = p->z; /* tbl[1] = [2]*p */ dbl_point(/* r = */ (tbl + 1), /* a = */ p); for (int n = 1; n < ((1 << (WIN_SIZE - 1)) / 2); ++n) { add_point(/* r = */ (tbl + 2 * n), /* a = */ (tbl + 2 * n - 1), /* b = */ p); dbl_point(/* r = */ (tbl + 2 * n + 1), /* a = */ (tbl + n)); } Ipp16u wval; Ipp8u digit, sign; mask8 mask_neg; const Ipp32s mask = ((1 << (WIN_SIZE + 1)) - 1); /* mask 0b111111 */ Ipp32s bit = scalarBitSize - (scalarBitSize % WIN_SIZE); Ipp32s chunk_no = (bit - 1) / 8; Ipp32s chunk_shift = (bit - 1) % 8; if (0 != bit) { wval = *((Ipp16u*)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); } else { wval = 0; } booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, /* w = */ WIN_SIZE); table_get_point(/* r = */ &R, /* digit = */ (Ipp32s)digit, /* tbl = */ tbl); for (bit -= WIN_SIZE; bit >= WIN_SIZE; bit -= WIN_SIZE) { dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u*)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, /* w = */ WIN_SIZE); table_get_point(/* r = */ &H, /* idx = */ (Ipp32s)digit, /* tbl = */ tbl); neg_coord(negHy, H.y); mask_neg = (mask8)(~(sign - 1)); FESM2_MASK_MOV(H.y, H.y, mask_neg, negHy); add_point(/* r = */ &R, /* a = */ &R, /* b = */ &H); } /* last window */ dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); dbl_point(&R, &R); #if (WIN_SIZE == 5) dbl_point(&R, &R); #endif wval = *((Ipp16u*)(pExtendedScalar + 0)); wval = (wval << 1) & mask; booth_recode(/* sign = */ &sign, /* digit = */ &digit, /* in = */ (Ipp8u)wval, /* w = */ WIN_SIZE); table_get_point(/* r = */ &H, /* idx = */ (Ipp32s)digit, /* tbl = */ tbl); neg_coord(negHy, H.y); mask_neg = (mask8)(~(sign - 1)); FESM2_MASK_MOV(H.y, H.y, mask_neg, negHy); add_point(/* r = */ &R, /* a = */ &R, /* b = */ &H); r->x = R.x; r->y = R.y; r->z = R.z; /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, &H, NULL); return; } #include "gfpec/sm2/ifma_ecprecomp7_sm2.h" /* affine */ #define BP_WIN_SIZE BASE_POINT_WIN_SIZE #define BP_N_ENTRY BASE_POINT_N_ENTRY __IPPCP_INLINE void extract_point_affine(PSM2_AFFINE_POINT_IFMA* r, const SINGLE_PSM2_AFFINE_POINT_IFMA* tbl, const Ipp32s digit) { const Ipp32s idx = digit - 1; __ALIGN64 PSM2_AFFINE_POINT_IFMA R; R.x = R.y = setzero_i64(); for (Ipp32s n = 0; n < (1 << ((BP_WIN_SIZE)-1)); ++n, ++tbl) { const mask8 mask = is_eq_mask(n, idx); FESM2_MASK_MOV(R.x, R.x, mask, FESM2_LOADU(tbl->x)); FESM2_MASK_MOV(R.y, R.y, mask, FESM2_LOADU(tbl->y)); } r->x = R.x; r->y = R.y; return; } IPP_OWN_DEFN(void, gesm2_select_ap_w7_ifma, (BNU_CHUNK_T * pAffinePoint, const BNU_CHUNK_T* pTable, int index)) { __ALIGN64 PSM2_AFFINE_POINT_IFMA ap; extract_point_affine(&ap, (SINGLE_PSM2_AFFINE_POINT_IFMA*)pTable, index); ap.x = fesm2_from_mont(ap.x); ap.y = fesm2_from_mont(ap.y); fesm2_convert_radix52_radix64(pAffinePoint, ap.x); fesm2_convert_radix52_radix64(pAffinePoint + PSM2_LEN64, ap.y); } IPP_OWN_DEFN(void, gesm2_mul_base, (PSM2_POINT_IFMA * r, const Ipp8u* pExtendedScalar)) { const SINGLE_PSM2_AFFINE_POINT_IFMA* tbl = &ifma_ec_sm2_bp_precomp[0][0]; __ALIGN64 PSM2_POINT_IFMA R; __ALIGN64 PSM2_AFFINE_POINT_IFMA A; fesm2 Ty; R.x = R.y = R.z = setzero_i64(); A.x = A.y = setzero_i64(); Ty = setzero_i64(); Ipp16u wval; Ipp8u digit, sign; const Ipp32s mask = ((1 << (BP_WIN_SIZE + 1)) - 1); /* mask 0b11111 */ Ipp32s bit = 0; Ipp32s chunk_no, chunk_shift; wval = *((Ipp16u*)(pExtendedScalar + 0)); wval = (Ipp16u)((wval << 1) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ neg_coord(Ty, A.y); mask8 mask_neg = (mask8)(~(sign - 1)); FESM2_MASK_MOV(A.y, A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); for (bit += BP_WIN_SIZE; bit <= 256; bit += BP_WIN_SIZE) { chunk_no = (bit - 1) / 8; chunk_shift = (bit - 1) % 8; wval = *((Ipp16u*)(pExtendedScalar + chunk_no)); wval = (Ipp16u)((wval >> chunk_shift) & mask); booth_recode(&sign, &digit, (Ipp8u)wval, BP_WIN_SIZE); extract_point_affine(&A, tbl, (Ipp32s)digit); tbl += BP_N_ENTRY; /* A = sign == 1 ? -A : A */ neg_coord(Ty, A.y); mask_neg = (mask8)(~(sign - 1)); FESM2_MASK_MOV(A.y, A.y, mask_neg, Ty); /* R += A */ add_point_affine(&R, &R, &A); } r->x = R.x; r->y = R.y; r->z = R.z; /* clear secret data */ clear_secret_context(&wval, &chunk_no, &chunk_shift, &sign, &digit, &R, NULL, &A); return; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ecpoint_sm2.h000066400000000000000000000131711470420105600264100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ /* Paper referenced in this header: * * [1] "Enhanced Montgomery Multiplication" DOI:10.1155/2008/583926 * */ #if !defined(_IFMA_ECPOINT_SM2_H_) #define _IFMA_ECPOINT_SM2_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/ifma_arith_psm2.h" #include "pcpbnuimpl.h" /* SM2 point (x,y,z) */ typedef struct PSM2_POINT_IFMA { fesm2 x; fesm2 y; fesm2 z; } PSM2_POINT_IFMA; /* SM2 affine point (x,y) */ typedef struct PSM2_AFFINE_POINT_IFMA { fesm2 x; fesm2 y; } PSM2_AFFINE_POINT_IFMA; /** * \brief * * compute R = [pExtendedScalar]*P = (P + P + ... + P) * * \param[out] r point (in radix 2^52) * \param[in] p point (in radix 2^52) * \param[in] pExtendedScalar ptr Extended scalar * \param[in] scalarBitSize size bits scalar */ IPP_OWN_DECL(void, gesm2_mul, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p, const Ipp8u* pExtendedScalar, const int scalarBitSize)) /** * \brief * * compute R = [pExtendedScalar]*BasePoint * * \param[out] r point (in radix 2^52) * \param pExtendedScalar ptr scaler (length 256 bits) */ IPP_OWN_DECL(void, gesm2_mul_base, (PSM2_POINT_IFMA * r, const Ipp8u* pExtendedScalar)) /** * \brief * * convert point to affine coordinate * * \param[out] r point affine coordinate * \param[in] a point */ IPP_OWN_DECL(void, gesm2_to_affine, (fesm2 px[], fesm2 py[], const PSM2_POINT_IFMA* a)) /** * \brief * * check point on curve SM2 * * \param[in] p point (in radix 2^52) * \param[in] use_jproj_coords is Jacobian Projection coordinate or Affine Coordinate * \return int 1 - is true | 0 - is false */ IPP_OWN_DECL(int, gesm2_is_on_curve, (const PSM2_POINT_IFMA* p, const int use_jproj_coords)) /** * \brief * * compute double point SM2 (Enhanced Montgomery Algorithm) * * \param[out] r point * \param[in] p value point (in radix 2^52) */ IPP_OWN_DECL(void, gesm2_dbl, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p)) /** * \brief * * compute add point SM2 (Enhanced Montgomery Algorithm) * * \param[out] r point * \param[in] p first point (in radix 2^52) * \param[in] q second point (in radix 2^52) */ IPP_OWN_DECL(void, gesm2_add, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p, const PSM2_POINT_IFMA* q)) /** * \brief * * compute add point affine SM2 (Enhanced Montgomery Algorithm) * * \param[out] r point * \param[in] p first point (in radix 2^52) * \param[in] q second affine point (in radix 2^52) */ IPP_OWN_DECL(void, gesm2_add_affine, (PSM2_POINT_IFMA * r, const PSM2_POINT_IFMA* p, const PSM2_AFFINE_POINT_IFMA* q)) /** * \brief * * Extracts affine point from the precomputed table. * * \param[out] pAffinePoint array of x and y coordinates of affine point in 2^64 radix * \param[in] pTable pointer to a precomputed table * \param[in] index index of desired point in the table */ IPP_OWN_DECL(void, gesm2_select_ap_w7_ifma, (BNU_CHUNK_T * pAffinePoint, const BNU_CHUNK_T* pTable, int index)) #include "gfpec/sm2/ifma_arith_method_sm2.h" #include "gsmodstuff.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" __IPPCP_INLINE void recode_point_to_mont52(PSM2_POINT_IFMA* pR, const BNU_CHUNK_T* pP, BNU_CHUNK_T* pPool, ifmaArithMethod* method, gsModEngine* pME) { ifma_import to_radix52 = method->import_to52; ifma_encode p_to_mont = method->encode; const int elemLen = GFP_FELEN(pME); BNU_CHUNK_T* pX = pPool; BNU_CHUNK_T* pY = pPool + elemLen; BNU_CHUNK_T* pZ = pPool + 2 * elemLen; GFP_METHOD(pME)->decode(pX, pP, pME); GFP_METHOD(pME)->decode(pY, pP + elemLen, pME); GFP_METHOD(pME)->decode(pZ, pP + 2 * elemLen, pME); pR->x = to_radix52((Ipp64u*)pX); pR->y = to_radix52((Ipp64u*)pY); pR->z = to_radix52((Ipp64u*)pZ); pR->x = p_to_mont(pR->x); pR->y = p_to_mont(pR->y); pR->z = p_to_mont(pR->z); } __IPPCP_INLINE void recode_point_to_mont64(IppsGFpECPoint* pR, PSM2_POINT_IFMA* pP, BNU_CHUNK_T* pPool, ifmaArithMethod* method, gsModEngine* pME) { ifma_export to_radix64 = method->export_to64; ifma_decode p_from_mont = method->decode; const int elemLen = GFP_PELEN(pME); BNU_CHUNK_T* pX = pPool; BNU_CHUNK_T* pY = pPool + elemLen; BNU_CHUNK_T* pZ = pPool + 2 * elemLen; pP->x = p_from_mont(pP->x); pP->y = p_from_mont(pP->y); pP->z = p_from_mont(pP->z); to_radix64((Ipp64u*)pX, pP->x); to_radix64((Ipp64u*)pY, pP->y); to_radix64((Ipp64u*)pZ, pP->z); GFP_METHOD(pME)->encode(ECP_POINT_X(pR), pX, pME); GFP_METHOD(pME)->encode(ECP_POINT_Y(pR), pY, pME); GFP_METHOD(pME)->encode(ECP_POINT_Z(pR), pZ, pME); } #endif // (_IPP32E >= _IPP32E_K1) #endif // _IFMA_ECPOINT_SM2_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_ecprecomp7_sm2.h000066400000000000000000016552321470420105600270260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2021 Intel Corporation * * 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. *************************************************************************/ #if !defined(_IFMA_ECPRECOMP7_SM2_H_) #define _IFMA_ECPRECOMP7_SM2_H_ #include "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/ifma_defs_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" typedef struct SINGLE_PSM2_AFFINE_POINT_IFMA { __ALIGN64 Ipp64u x[PSM2_LEN52]; __ALIGN64 Ipp64u y[PSM2_LEN52]; } SINGLE_PSM2_AFFINE_POINT_IFMA; #define BASE_POINT_WIN_SIZE (7) #define BASE_POINT_N_ENTRY (1 << ((BASE_POINT_WIN_SIZE)-1)) extern const __ALIGN64 SINGLE_PSM2_AFFINE_POINT_IFMA ifma_ec_sm2_bp_precomp[37][BASE_POINT_N_ENTRY]; #if !defined(_DISABLE_ECP_SM2_HARDCODED_BP_TBL_) const __ALIGN64 SINGLE_PSM2_AFFINE_POINT_IFMA ifma_ec_sm2_bp_precomp[][BASE_POINT_N_ENTRY] = { { /* digit=0 [{1,2,3,..,}]*([2^0]*G) */ {{0x0001167a5f72d7b5,0x000c43181404d9e9,0x000e6dbd3aaf42f3,0x00024c3c33e7981e,0x0000654979a299ac}, {0x0003cd65d4e5a49b,0x0008384568872dd6,0x0008f0fffbcf430c,0x0002a48f8c1f5e57,0x00009272f196066e}}, {{0x000d7e9c18d8240f,0x000aaa6e417d56a0,0x000a3b0e4550d595,0x00088cd2483bdc9b,0x0000832b6de84b57}, {0x00047e746600a032,0x000d7b7693b68c19,0x000859275c90d69f,0x0007157acccbd8d3,0x00005bc85177169b}}, {{0x000019fd6c2ea279,0x000d0917cb6254a3,0x000a0b6907791b62,0x000eb4a0a2676528,0x0000d038c8d3308c}, {0x0008ad3478846130,0x000f770c6ce91902,0x000bb07902d865c4,0x000c13c97f40aa52,0x00002d50aa9bfa6d}}, {{0x0000dc8e3b19766a,0x000581f7eeae6605,0x000039ddf04401d9,0x0009f9020487ea28,0x00001ca3fd26b4a0}, {0x000ffc31c595b91b,0x000797e67a87e986,0x000aec6fb58321c6,0x000cf70ed1de135e,0x0000a8e2c4f05632}}, {{0x000f443ef3733cb4,0x000cb3ff75fcd620,0x000231240b46fe4f,0x000f5f4c515aa58f,0x0000acee1008bf1e}, {0x000b4152768f6bb9,0x0003d1943d948337,0x000e5ea1cf8e42ac,0x0002258efb30f4bb,0x0000df40ee234c36}}, {{0x0005e74ca112a1cc,0x0001baaf82ba6ba8,0x0005e46613dca025,0x000e34db6b1274a2,0x0000e903fc536e5d}, {0x000568bc9800f516,0x000a645b374d537b,0x00007f00118f53d1,0x00030e9848fbf6d2,0x0000221155fdf8ec}}, {{0x000bf492e195f07f,0x0001de5ebffe884b,0x0003c307b8018431,0x000fe18c50b89419,0x00000a1adeda69ac}, {0x000ba05a8f672532,0x0000d327ed0e66d2,0x000ea11a5c476cbf,0x000d99baf0e449a2,0x000006fdeeeb922b}}, {{0x00015c2fc0eb2070,0x0007a5b1df1b6701,0x000a3428b0cdb816,0x00087df9e90be6f2,0x0000f4f38ed34143}, {0x00077fd5f39cf758,0x000c519eaa1d82ae,0x0001c9fb549748ab,0x0008f3382693b350,0x00003b68d86b6f9a}}, {{0x0007d88740be6daa,0x000b882728e34867,0x000622fa36cfdf7c,0x0008669b48e5e049,0x000008f7936983b4}, {0x00022a6c24b493eb,0x0000a36e3e719ce8,0x0008bd29b04cc229,0x000a6e96963c563a,0x0000711254fc6553}}, {{0x000e8237d906e272,0x00063b15d4a3f432,0x00085b93464a3fd4,0x00088728eecdb60d,0x000063eef3231b13}, {0x00031bbfda8cd29f,0x0004821c3dc4be1e,0x000a4a6263ce10f0,0x000dd716508c65d1,0x000015073445b5d7}}, {{0x00083da169291613,0x0009c670b0bce154,0x00080eed9d6a0bfd,0x0005092677557c8c,0x00003202222cfd8a}, {0x00028398a7eae7b7,0x000180bd61f72bf5,0x0001683a9ec60b3b,0x0002c587d5dd8402,0x00006a86e659db9f}}, {{0x00090ea13d89cc69,0x000255069e37462b,0x00018fe68620e964,0x0008d4f0789f3850,0x000031ef3cf56a9d}, {0x0006bd39ee352fe8,0x0000667570e4332b,0x000673b80d8ed70b,0x000385ffafa48d5c,0x0000a591652ce762}}, {{0x000c80c9d04d2808,0x0005a9a32d8f64e3,0x000dc6453311458c,0x000bc2b2e7da2bdf,0x00002cb3a3b11de1}, {0x0005fa508acb12e2,0x0007d33fce2e44d4,0x0004849da0dcd4c6,0x000ec55f9aef09eb,0x0000eae191c31b26}}, {{0x000f8babeb190812,0x0000a4e094c1dc30,0x000ced3824c7aa66,0x00074d0533f194a6,0x000002c062f92d6f}, {0x000f6cd2b110e9a8,0x00091ab321a1a47f,0x000bbc8af71c2e8f,0x0009b55adfe0c027,0x0000ebfab3c299b6}}, {{0x000df89411540793,0x000923289e1ea4d0,0x000ac9ab62313957,0x000ddf2219c14e38,0x000002798dfc11cf}, {0x000c5c1e9ea4d4d6,0x000aa6fced9ad262,0x0008fa2e93406f8c,0x000885947d9be66a,0x000020846630e236}}, {{0x000d01076ee1cd74,0x000cd5a581b2d20c,0x00093f74bd090be1,0x000f4639d7121d6b,0x0000c74662a9ce8e}, {0x000a4759c17b4394,0x000acd91ba3bb8a6,0x0000bf7a5d3f3801,0x0003c5c62b07e323,0x000082838a70c166}}, {{0x000e33014346c3a9,0x000095088fa55ffb,0x000107c9d987c4a3,0x000f2b6584a31dd2,0x0000ff8f6b14a019}, {0x000da3bda2d72e1e,0x000953e595c8241b,0x00053ede9ccb4205,0x000cdc439cbf5da2,0x000018a52a7858cd}}, {{0x000617c54f3a57d1,0x0009e6cda402d38f,0x000dcba397c6a7df,0x00017bfe48ed8eea,0x0000a909b54de6b4}, {0x000b7154885c6b51,0x00052ad21227839e,0x00060f8cff874f5d,0x0007e8e972e6a3a7,0x0000255f5e75e5e0}}, {{0x0002d8e3f61e46a0,0x000ef8a682a8116e,0x00086b27e23bfa6a,0x0009e513f9b9e970,0x0000e27f60beec8c}, {0x0003246dbc6eb4e8,0x000255fe0d47ce4e,0x0003d805a7b4087e,0x0009af4f3ee12d06,0x0000dffd18b1c09a}}, {{0x0008e3e09541188e,0x0006b0d2ff10201a,0x000abedec872090a,0x00069c20e3d876d4,0x000087ecb8de0f7b}, {0x000da6987805758b,0x00077a3929596b9a,0x00032632c2a7c1aa,0x0007d153d274c1de,0x000090621fde36d4}}, {{0x000f01e019ea2472,0x000266cb630aa808,0x0000f49041d7deaa,0x0009350681611dea,0x00003d0a0dce821b}, {0x000abe5cc3f2bfb4,0x000d5418bd40f896,0x000e02ff3a27ab02,0x000e86399ce4ac99,0x000049d0896d001d}}, {{0x000dbc0b894bb4f4,0x0002e20681014988,0x0001f9c1e48b7e8e,0x0006bcc8cbd44336,0x0000923926eb0c2c}, {0x000005bcfa05f5a4,0x000429e49d6299a7,0x000c78170090ecdb,0x0005f7927afb6fed,0x00000a0af6725bb3}}, {{0x000f6ae59570ee69,0x000423cbdcc1639d,0x00074bb372d8a3e0,0x0006915c4c7c42e7,0x0000354c77faf967}, {0x0001bb84d9312a64,0x000a22b967527d11,0x0000bbd1e7d36ed8,0x0006f2599638cb07,0x000082f920f072ba}}, {{0x000668304566ea9f,0x000c5a73b2b5ea29,0x0001b72e0dfb6f53,0x00068c65d19de7a9,0x0000b028d8339d06}, {0x000f529385702e1f,0x000b15aaaac89ff3,0x000446feccaf4f3e,0x000f06e44bc53bc2,0x00009f9c624cb5d9}}, {{0x000e53aa7d49eafb,0x000cdac9d5e2826d,0x000fe4b7a2a6312c,0x0008cfdc13addc3d,0x0000b1d9952c6972}, {0x00071e68556c226a,0x000774683bb5d64a,0x000bb10c1848b985,0x0003d48c9d605474,0x000068340188b965}}, {{0x00092bed74888d36,0x000cbce275c0fb58,0x000e72fe273b12ce,0x0002e80de91707e7,0x0000db762f73c5fb}, {0x0003605d1822de60,0x000264f60af612d9,0x000d43631ab3bd6b,0x0004629df73fd298,0x0000cfe82714262c}}, {{0x000746a77aa308aa,0x0001a9c30737acc0,0x0002eb6e3ed4ce48,0x000f943a95bb54ee,0x00006010a8bdd232}, {0x000560e7e5cf332c,0x000be9efdeac35b0,0x000f8b7e87813782,0x0002181fb9421fe7,0x00000340a99e9269}}, {{0x0007671e24561bb4,0x00000d8f762de2a3,0x00001886c3580ffe,0x0007956cd67f42a4,0x00002cf5abf25b97}, {0x000de5ed1dcc00e4,0x000478255fa3c47b,0x000bf3c02988a494,0x0007bba59141f96f,0x000072ac7d2040d2}}, {{0x0003afcc938edfa0,0x000981cc61252576,0x000913c163700794,0x00002d5bdecb033c,0x0000e4e3c5ff4d82}, {0x0001d8f4668b50d7,0x0007cd2a51338b78,0x000edd0f0b7e280a,0x000f0bbe8dc91387,0x0000219bfbb5cbf8}}, {{0x0007c9d827edc576,0x000d568cf9f5796f,0x0003c6b070fad2a5,0x000143c45bc8ac15,0x0000c8cc3708f7a1}, {0x000c780d9d193ed6,0x0007191b007b950e,0x000ab8ba8c708175,0x000ad5467340f445,0x000052592b31e902}}, {{0x000802fb3eb3d841,0x000e04d04b1868a7,0x000982cd2e03b6ec,0x0001b9a36069a7ab,0x00006f98bd625e59}, {0x0004e2dfb27220ca,0x0007d60b11ba4ebf,0x000e42ff9a6e1785,0x000e36f3b18c612a,0x0000d89ac35c73c0}}, {{0x00050e3e71fd4a23,0x000f7f7b071198b5,0x000ba19d01ea4efc,0x000f0a982d78af40,0x00007cfcfdcb0d03}, {0x0001c52fadb094b5,0x000950490fa2f5bb,0x0003b956e911832b,0x00047e33b5297cf4,0x0000601800188ccc}}, {{0x00091c76dcf25dc1,0x00000084b5c6b0ec,0x0008cb89c5ee1953,0x000f206fba6c6844,0x00001903b72eb3c3}, {0x0009f9329b4a17d7,0x0005e366f36057c5,0x0007b0a7b8ab0858,0x000734400dfb20ce,0x0000db8842f3d9d8}}, {{0x0003c17aa0e9a859,0x000f26b39a949a9e,0x000ca30e12c38332,0x000068df9575c1e1,0x00009178ba1bca31}, {0x0001ea1386258de0,0x000e8ea2a8ea6306,0x00082a7454b4a9cb,0x0000492d7ad24091,0x00003d94af9fb739}}, {{0x000bd0a4c60f2724,0x000c9bd244c18bc3,0x000063be261d339f,0x00071ad908da622a,0x0000c90f49d55404}, {0x0005922faeaab30b,0x00008552e7fd4231,0x00008fb1810871af,0x000375b0f859ed94,0x000046581a19632a}}, {{0x0002eab5669ebb2b,0x0004708bb2fef9b6,0x000fe7fc9aa83744,0x00090c3213ee8cc1,0x00003abf92585915}, {0x0009761c3595cedf,0x0006a92651244ab0,0x000f2886cba43860,0x000a8ac5d83b89ab,0x0000e8dc6841ec1d}}, {{0x0009fed874184a69,0x000fdea655ea6c93,0x000d96c14ff60a53,0x000268939458e5ff,0x000084dc3eef11b9}, {0x00041b5b6de8e246,0x0007a0b14c452ccd,0x00027d8f16bd2bb6,0x0009b725bb028dc2,0x0000572ecdca9ee2}}, {{0x000130b4de2895f9,0x0005f439cc75e202,0x0002c214bff765f8,0x0000651a5b628ccb,0x0000c56a9a48fe00}, {0x0004695e9be17d1b,0x00041f854faac0fd,0x0009ccfdbc214556,0x00069ae44fdcdb03,0x00007edcab584c41}}, {{0x000e3590f168d2b1,0x000339e9acab36da,0x000f5f613429ffb6,0x00023e7d6983b7a2,0x00005c48a5be3e59}, {0x000d83804d41f76e,0x000c0e774de782a4,0x0004cbc3ab5f71cc,0x000ae8e01b15b054,0x00003bee4f4f1362}}, {{0x000b014c73ee1325,0x00054d9da08a3283,0x00083663a292e2bc,0x000c2fa93b16ed9d,0x0000813ab0c77049}, {0x000434a3b15969fc,0x000b5b49bda3732d,0x0005c2f25b7357d1,0x000ce9480b6457d5,0x000006200abb3a4c}}, {{0x00045b268a2411df,0x0005891671a913cc,0x0003cf1240da7743,0x000b948d5605bba5,0x00004b4552738e3d}, {0x000ea61903ca09a3,0x000f0db2771a4bd7,0x000aad4157e88d82,0x00061433957627a5,0x00004ab7fd350a66}}, {{0x000e4964e7611bb9,0x000295adae74d432,0x000d8cac7948a4d6,0x000c3da9c7112bb3,0x0000028720a3c72b}, {0x000903eadc6af862,0x000266a7dbde62a9,0x000bbdd6677a6604,0x0007c5f888f772fc,0x0000717d5496d7ca}}, {{0x000a1261ea8c6488,0x000ca2d55afe929b,0x0003b29c6c19e3fc,0x000283f973ccef5c,0x0000a10539a87a90}, {0x000b7937899af0f6,0x00050bf36f6aa1c7,0x00060f93ea46df3f,0x000a0668b373f1cd,0x0000948b79142119}}, {{0x00008f8d46c0616e,0x0005754a372e43dd,0x000bc0c92bf53994,0x000a2a74df8df2cb,0x0000da1b4aba6922}, {0x000b4c696835e3a0,0x000565c909e53769,0x000987ddf078fecb,0x00008f50f3a8e25c,0x0000ab1518d04d06}}, {{0x000cc1c4cbf2eada,0x0000b07cccf2a3b4,0x00073637b5075beb,0x0002cbb01aff4f89,0x0000cbdd0a13bdae}, {0x000af408e2bf7bff,0x000a5c0ca6d44b87,0x000590425f3ca33c,0x0002bced68c4d27e,0x0000860daa597e7f}}, {{0x0006fe7e8c09b138,0x00085228df4d5e7c,0x000d0b002f39288d,0x0009113f99774834,0x0000f38034f3008a}, {0x000e75ecfbf60757,0x000c0515ee009c8c,0x0001dffbf3bde851,0x0003cd7b9f7b0540,0x00001d4b51f20fec}}, {{0x000f73502b13dfd6,0x0000f6bfe31b4bdb,0x0004c8f0f3d24ad0,0x000df99852ba6e75,0x00007531d7f6850f}, {0x00076e3627f19150,0x000acfbce9c4ce08,0x00036c4b44a54a01,0x00043b9b4580491e,0x000069d8a672d2ae}}, {{0x00006262266ce0ea,0x0007ceb468278ecf,0x0007246abb7f770e,0x00070c62b11c5a9f,0x00004d940c70f297}, {0x000a1dd93504b336,0x000c58ae56addebf,0x0002c8778a299d26,0x000826f34db89297,0x0000216c1d191d4f}}, {{0x000d757d105035e9,0x0000892525eeeea3,0x000b8207d3ab24fe,0x000dd86c38699063,0x000048ba86d3e9a8}, {0x000543f2cf2834f5,0x000c4f1160cf0568,0x000be874b4e8fd83,0x00084d925a64595e,0x0000d3990d091ae1}}, {{0x000e9af8e18b884c,0x00003c1132459043,0x000b64b2b57c9247,0x000641003b9843a4,0x00006be6b120ee1b}, {0x0008b29a50338313,0x0007739485c6ac24,0x00020bd7e43e2261,0x000cd2f42c7c7494,0x000007104b3c5bab}}, {{0x00075df6aa322652,0x0008438ee19c58e7,0x000f0e751ca64953,0x000ee2cc1ceff8f3,0x0000007cbe08fafc}, {0x0005d3fe7d60d02b,0x000f86971b9f6cc4,0x000af3ff81584de1,0x000e38e96e8b86ad,0x0000c8a5afe65086}}, {{0x000c0c2ef468013e,0x000447a6a3e240d9,0x000ce19f2d3f4f80,0x000f5b1d82e8fa8a,0x0000a47b981fb33a}, {0x0006f55f89eb0100,0x000573f986d93e93,0x00003f8e75c98dfb,0x000a00d1be6eb587,0x00006025306d77dc}}, {{0x0005004985706114,0x0003a99c2255a574,0x00039ede58b41f12,0x00057962df076847,0x00004155be8eedab}, {0x0000393d7b59e2eb,0x0004af37b669d889,0x0001361a3ce556fd,0x000088c50176ce1a,0x0000ab255f00efdc}}, {{0x000f2508973a0049,0x000e1a9999674ce0,0x000b7ed788a7049c,0x00076b0df4215b78,0x00003fc339599f2f}, {0x0008a181cc31d786,0x00004b008af5a09e,0x0006e20a280096e6,0x000aefa786ef0ad9,0x0000708a7fb34b8e}}, {{0x000ecd84e8002ca5,0x0006e4c51e07c6d3,0x000605339c03f827,0x000e29d372b2ef6b,0x00009294965e1f2c}, {0x0008e0d1f90738b6,0x000ea3c21f6272c6,0x0002e51519ef8f60,0x000ea3fdf6d43936,0x00004958f256a93e}}, {{0x0002ae43cded4986,0x0008c0786370d1e5,0x000d72bfe828c06d,0x000de1ca387f03fa,0x0000fe77288924ef}, {0x0005c10049922062,0x0001e1b0f661a1bf,0x00078e2792579aa8,0x000f50251dd874f6,0x0000e1fb6309e4fc}}, {{0x000ccd7fbba38366,0x0006a2f5d13d7662,0x0000c2887037a707,0x000822e131ce6676,0x0000ab184d3f7174}, {0x0000417ce21feaac,0x000ba6783f71e187,0x000c16456fd30111,0x0002534b61beb5bb,0x000057298cddd196}}, {{0x000938b88b271119,0x000cdf7ba43a3002,0x0008b28d3c70b643,0x000ff1e445a0b19e,0x0000e8d8708505a0}, {0x000b509b7bcaa8da,0x0004889cc6d3bc35,0x000c1b8dbbb4f0d8,0x00076ce646be6d56,0x000064c9e731d2c4}}, {{0x00068a9aaae04721,0x00049c19bd83c3bb,0x000c97a89201474f,0x0007e36f61e60b19,0x00008e006d3601e3}, {0x000264283d8cd6ac,0x000a26d694677ca3,0x00050811d256561a,0x000f93bb86344083,0x0000be34e422eda5}}, {{0x000f8047fec93faa,0x00073131b791a8e2,0x00020dd5c4c96fd6,0x000b598413ee227a,0x000003f52b6a9a3c}, {0x0000a3aa35db586e,0x000e80870eb165fc,0x000407776015d23f,0x00014524d484ac18,0x00007d7bd4527603}}, {{0x0007d6e92e359c6f,0x000b32a6697b084d,0x00085cc819e78cf5,0x000e64343264911a,0x0000b8665b43083e}, {0x000987117e217dc3,0x000f6ea5f2ff0fb6,0x000d0aba23bc49fd,0x000e1da50005ab33,0x00006631cedcfd42}}, {{0x0006861e633bad54,0x0009090870f777a7,0x000efcf8e7ed6758,0x00048f60795ddd3e,0x000066e4b07a455f}, {0x00057bcc2dcfcebf,0x0009631b8b2b3172,0x000c4e0e7bda1bfd,0x00084c79157e95b6,0x0000dfc62d4f9b9e}}, {{0x000229bde0a25f6d,0x000c029e3fcf95af,0x000222ea492c862b,0x000ec26fcddc3afe,0x00003df0533d4aef}, {0x00093afe4a6dc67d,0x000928563cb37395,0x000db3baa6ee4ad4,0x0006c1219f41b8f6,0x0000aed543421b6f}}, {{0x0003d9b4b1683537,0x00027fca4ce53d4f,0x000429ff213ff55b,0x000978dcef44d3df,0x0000c87265aec8bc}, {0x0008adaee633517a,0x0000f9e83600b2c5,0x00046726aded6663,0x000c242380cd02ed,0x00003bc51cfc7e49}}, }, { /* digit=1 [{1,2,3,..,}]*([2^7]*G) */ {{0x0003f6205b429ade,0x0008bf1c0a4e32ae,0x00022c7d1370668b,0x0006f3f11ba4f98a,0x00003ef4e616f3e6}, {0x000eda7e2acd29f6,0x000cb5cda51a38f4,0x0007e42471db7ebf,0x0003a61d62c9b445,0x000045ac20585b53}}, {{0x000e1431a0e449d7,0x000b00a18c82a340,0x0009ce6b623dbfa8,0x000726ce7b22b908,0x0000257d316c6584}, {0x000316fa44c65236,0x000abdf21e2c9a6a,0x000fa681abf2e073,0x00024b68464198dd,0x0000b20d3821b191}}, {{0x00047be60cbe754a,0x000f718c602db135,0x00077d7fb8185623,0x0007f9aeed67c8ab,0x0000af29dafc6215}, {0x000785ec118bf7e4,0x000eb16620c35dba,0x000199925c15e48d,0x000c1ccda92fa080,0x000033aa09cb45cd}}, {{0x0008bb37bbc8eaff,0x000c954d84c1ba41,0x00006d707a0a6cc6,0x00064269baff481a,0x00008b85ca90fd0e}, {0x000470e9650bf952,0x0004614637082390,0x000f1b05fe17e127,0x000e19ae44e27a58,0x0000d28ce5f3ca66}}, {{0x00030cd9e7bba66b,0x0002a47d0f6c9f6f,0x000f98fa70856f4b,0x0006d7ae2af062ff,0x0000407848c30d3a}, {0x000ad179dbe5e183,0x00081bb63f0280dd,0x000e0af2bc5b9ef5,0x000814831cfa3aa4,0x000057f28a37fd0a}}, {{0x000045cccc33ac82,0x00041300a514028b,0x000e69aa5701e6de,0x0005a99b5c0bae0a,0x0000570e393aab01}, {0x0008b5223fabe3c9,0x00035b4958105bd7,0x00093e95309ea81e,0x00079468e41e71fc,0x00006d2120c20644}}, {{0x0008216623c8051a,0x000974d15e695a2b,0x0000ed4105279fa7,0x000b0efdc15ffcce,0x00008407c2795c45}, {0x000e93eb01f7bc66,0x000aabb5b8017b63,0x00053f362f01a15a,0x000e5aaeaf3866d1,0x00003fe8d5b0e2a0}}, {{0x0007e4a6bab88bb5,0x000ac749feb21e8b,0x00068a9ac9915331,0x0005411d793c48f8,0x00004c41659fc83e}, {0x0006563f1f63710c,0x000b29b8e532f2ea,0x000f494986fd6c33,0x00009638f46578c7,0x0000487d3b7f6df0}}, {{0x00099ffa74b0a131,0x00003c57e9ff5e74,0x00041fcef932469d,0x000943242ecc22d1,0x00006e8a53cc4b10}, {0x00053e70b02ce3d3,0x0000f7bfea4c6526,0x000f62519e5d6a4f,0x000cebfd7945f306,0x00003029e98b8415}}, {{0x000328a51d2191fb,0x000aa9835ebb3353,0x0006ddec4b72ed65,0x000c31d009d2f054,0x00005adafdcd98fa}, {0x00033a5443f17c91,0x000464a519cce4e8,0x00062cd2554ecc5b,0x00047ccb6657f4ba,0x0000ea376f2b8440}}, {{0x0008bc857ba2453a,0x000354b27eeba2be,0x0003efa1af80516d,0x0009be57220a5103,0x0000fe282dac550a}, {0x000b6dd98b001e61,0x0001d5dc16564000,0x000e0a4e87ba6cd5,0x0004d1decf33a87f,0x0000a1f0885f20c6}}, {{0x0005611ee5405eb8,0x0008bb358c3e290d,0x0008f2d2f416d96a,0x000e3a8b7a6840bc,0x0000f3c09d0c0771}, {0x0001b7ebe5a31b29,0x000072918a3d173b,0x000c77a4349cc89d,0x000dea0ec6082dba,0x0000e943c639dfbb}}, {{0x0009c5a35b857733,0x000b43af66b31410,0x000618bc27427626,0x000dd611df52cb1b,0x0000dea20d731f39}, {0x000a53863aaa59ac,0x000287d564c29a15,0x000e07486f27f2f6,0x000cc58c64e300dd,0x00008bb7806200b4}}, {{0x000e6cf633beb827,0x0007541ee6485223,0x000f064e09c8e331,0x000479c4a2008653,0x000005672dd401d9}, {0x0002ef49575fc255,0x000fb1756ee1946b,0x000faaa78a620586,0x00078458d74c45db,0x0000286229ac59c2}}, {{0x000f183d4950bd4e,0x0006829e2dd608d3,0x00024b281ebe2bef,0x0005d5ac1a775b95,0x0000ffcbf6fa1b5d}, {0x000c6f7a38b05932,0x0009a4d54018e45e,0x000735a43f67590e,0x0006365280498d29,0x000083d04586749b}}, {{0x000a36193b229fdd,0x000d6a1f04e7a9d7,0x000b81137c112f74,0x0001d75822a9a12a,0x000092df75029907}, {0x000e19344b0a3b18,0x0004947df3b965bf,0x0003ac1801a2dec0,0x00014686de82c871,0x000005c6bebc40f7}}, {{0x0003e45d0a32fcee,0x0005a7fa4a4a3aeb,0x0004023d27d3a94b,0x000a1159700a2516,0x0000f05f61efb8e4}, {0x00094cf5c5dd948a,0x000c6eb880b4b16a,0x000f504d1ef5ec3c,0x000cd2d4d99cf64d,0x0000e533ca08d4f2}}, {{0x00022bc0f01f06e1,0x0001254579a83be0,0x000ba95a583c43a3,0x00031de06bd83e20,0x00002d83f0a341da}, {0x000a009dec653ef8,0x000a9def081681f6,0x00021b6942705a2a,0x00043026da1504f9,0x0000091f0e90b112}}, {{0x000572cecfe7bf86,0x000ee8278a5f0508,0x0006508e5c6e542b,0x000b6af13a5bbd8f,0x0000f885cd1a4781}, {0x0008a541d84528e9,0x000447f8ada787a5,0x0006f2151fe114b5,0x000878e13175c476,0x0000495badfdb204}}, {{0x000325396578ba7e,0x000f1d5b140820f9,0x000f5534905a956f,0x000b7ba771977a8d,0x00007dbdca2d6fc5}, {0x00060a74da50d8cb,0x0006557137368856,0x000e0eaff086fcbc,0x00033a7ba6c24de9,0x0000d539d80b8c55}}, {{0x000e7fac53e5832a,0x000d1e7a73f7e66c,0x0009be7bb912cbb5,0x00008b9b169f23f1,0x00005bf337922a53}, {0x0002b5e9ce1f9bdc,0x0008af5eaec7f01a,0x000e559ad53c6d06,0x000d4b81bd375c03,0x000065d670d2c170}}, {{0x000cf320046dae34,0x0003dc84af3ffc3d,0x0009110ca683092d,0x000d3d8dc44ef5dd,0x0000146ddfa12279}, {0x00091848ad843b2e,0x000e677ff21f464c,0x0008d7eea9091dcf,0x00044e760768c865,0x00001e2755ed17fc}}, {{0x0008a20903a4deda,0x00053f20c8da65f4,0x000dc571a79e0955,0x000122dd7b74cc0e,0x00001f3b1489237b}, {0x00074eec705b4e7f,0x000b345d9736c54a,0x0000f9d3c9235647,0x0009c2ee431a3c33,0x0000a634b54e5906}}, {{0x0008d3493802aedd,0x0007f6143720a39a,0x00079ce8e3d24e2a,0x000b745b17663a59,0x0000ba7c742c42b4}, {0x00008e23e6376d36,0x000eb442027cbdff,0x0004192ba0107cd9,0x000f3d3711d81bbe,0x00001954cdd874dd}}, {{0x0008536eb6e977e0,0x00031c30a317f04a,0x000150b5cecb8ce9,0x0006ae3ac0b43e66,0x0000c0d72af52624}, {0x0005a628eb6b6cae,0x0002cf4928e1e625,0x00001afda0667e5a,0x0007f4265f3de227,0x0000cf11f93b8c0d}}, {{0x0001910c3b106232,0x000b54c4e6c94ee9,0x000dbb97ce7d0b7e,0x000f00a7d4aefda2,0x00000a5704423357}, {0x00005307a4979c43,0x00049a5bc7522d2f,0x00044591f664b2c8,0x0004e020b15ed1b9,0x0000304591f7dbd2}}, {{0x0002e01cb8acccaf,0x000db23b53a5142b,0x00077554ae226c41,0x000098d0174d7152,0x000044df36341e6f}, {0x000ed3679f629911,0x0008282c8aa57cdc,0x00046fbfad702a88,0x000e5b3ac8eb84b0,0x000001d5d3e16826}}, {{0x000a64b76a2ec18e,0x00078c3aead2a764,0x000aeda893a50823,0x000054515bd98ad9,0x0000ae9054cb0356}, {0x000b64e7f5d86a85,0x00000fd39ede8e65,0x000fd4dbcfc6de80,0x0002a0a6b04984a9,0x00003c88762946cd}}, {{0x0002fee193a647ca,0x000b670c4033ee6b,0x0001643aa02f7b4a,0x00087114e66f3146,0x0000e357bcb2874d}, {0x0008627cf129e3fd,0x000a292529e30056,0x000cf7e52e3bc05f,0x0005f1b5d8d50c49,0x0000864bce4c6e0f}}, {{0x000ad7991fa05182,0x0004decea29a2582,0x000bb694041f373a,0x000e6989d82ab62b,0x0000931b87e7d76c}, {0x0005776952079845,0x0006358770640105,0x00085f9043a52233,0x000f00fdcb296a03,0x000059005bf4862b}}, {{0x000cc11e5684c1b7,0x000e3f8f8bc1e41e,0x0008eb1d9286e66e,0x0000297b1812feac,0x000066f0a15d3e34}, {0x00096054a3178eff,0x0000bc29acc99c03,0x00023c25e83fcc7b,0x000147c408a07b0d,0x0000ddb2c5c07623}}, {{0x000976011b1bc461,0x00060f0107f30719,0x0007818994a2a18f,0x0000776333ff85ee,0x00003e669ead7d8f}, {0x00054bbcc73bbbba,0x0000ed0af38e5638,0x00005b56c91358c0,0x000b3df90dff2123,0x0000265625f4bbba}}, {{0x000db00f4b4772bf,0x000145e2b12b3c1c,0x0003c88be095cc1c,0x00090b61b8a4923a,0x0000344af5ccf9cd}, {0x0009dcc691662dd8,0x000962a4096193de,0x000145eaab6e7b80,0x000a2e933dee45c3,0x0000dda44baf48fb}}, {{0x000d5d161871cf5e,0x000bf96b711c1622,0x0001b7c2140db6c3,0x0004fb357c8e120a,0x000091f47ad1dff2}, {0x0001508663c0622f,0x00026c2d6643c86f,0x000fb96dbf23d874,0x000f766581d547ca,0x0000da7eebc0a4d0}}, {{0x000c00bde07e9500,0x00040dcbd4ee582e,0x000af33a5075386f,0x0006f9598d9f545b,0x0000ff588a64a467}, {0x000a474e6ea6e85c,0x0001ea51b156b584,0x000fb3e7504d1e38,0x00007f044e32f572,0x0000d5ab75d376b9}}, {{0x000b47dc0dc20f02,0x00003326e2aa2b72,0x000a2cd6bec5fb3e,0x0007365f285de9ba,0x00008bcea35cebfd}, {0x0002605ff74f7a52,0x0003aafb4968c25b,0x000ac9d2a2b84e45,0x00004ff873ba7a11,0x000063946120e765}}, {{0x000ea745b0f8807a,0x000e9d8587aa16bb,0x0001307a4103df44,0x000b78e0498dc118,0x00004e9d7e40f8a1}, {0x0008dcff7bc5f923,0x00065ad9cdec8732,0x0008b45d8a3f4963,0x000ca219f7b76513,0x0000644e1c93afd0}}, {{0x000d04a8b55db72c,0x000f435dabbc4a91,0x0008fcbaeb67078e,0x000bbdfc9b2f2124,0x000019e43abb0f65}, {0x0003be91f3aae668,0x000f8a9736725587,0x00016e8f3bc10c21,0x00040ec4a74ee5e2,0x0000c0d08c02ae5a}}, {{0x0006ce7146590851,0x00020187d3713eba,0x000d38a163074e6b,0x000cdbf349943c34,0x000053c9b5c6d74f}, {0x000e1b66247a7101,0x00069c95293b8e92,0x000d7308e5ba5fc1,0x000136280b9ebeb8,0x00008f80fc44a55d}}, {{0x000b576e500ea398,0x000b82245cf3e7b2,0x0008f9cbc2bec6cc,0x0001d58f77345037,0x0000cdd0554e6eea}, {0x000cc7ccaae38d62,0x000534c4be5c6035,0x0000fc56156e4977,0x0004f1cf337aea39,0x0000ee6f49181e94}}, {{0x00079d789c195287,0x00027477408790a6,0x0000930aceb86101,0x0006cbe2723b0edd,0x0000392b0905f00d}, {0x00088b89f8858b86,0x0007f3db1a0ba159,0x000ffe03a89fc719,0x0000201ba5da50ba,0x00006a863f2cd455}}, {{0x0001a4387e58a913,0x000648acceb75521,0x0007521152b339f5,0x000d2dd874036bbb,0x000041757e920823}, {0x000a54437646ae42,0x00019047e92f959e,0x0006f40a3de71463,0x00075397ce58940c,0x0000ebb7ab93546a}}, {{0x000a1b010e4aab26,0x000e3c5617a973ad,0x00044532982b8675,0x000a969681bed3c3,0x00007d4f1ae7cdba}, {0x0009ae9fffe1232f,0x000e65305444e20d,0x0006fe785b41f639,0x0004120e08eac5d0,0x0000aaa419560e8f}}, {{0x000758b9c8293920,0x0008c6cbfbe97afe,0x000e690a1af49bfb,0x0004203981fcd743,0x00000b943f7aa23d}, {0x000f5a347a711abb,0x000b1d90df6603b8,0x000e12a3bbabc3a5,0x0008154f4b9ee0a5,0x0000c0badc5131ea}}, {{0x000d8fbf079db722,0x0003ab9c82633610,0x000e51bbae11705a,0x0004eff476c3420f,0x0000c6baf02761a6}, {0x0009a0b4c2b16f08,0x00045aaf34d60563,0x0007d8efd5c37a31,0x0002406427c1b59a,0x00008f17aca33851}}, {{0x00076f86426c3280,0x00065a8f5c36655c,0x000a66bb836ec14c,0x000111b0275c4c04,0x00005124ac1a1510}, {0x0005aa9d9a40b2c9,0x0002362d7acf7364,0x00073b575ab0d288,0x00008cff853212bd,0x0000e58faa0c1f04}}, {{0x0001293d9c195932,0x000eef2d6ea5365d,0x00041ddd78506af1,0x0002081d18e3a2ee,0x0000175ed7253823}, {0x000cab1223717464,0x00081eaf69bff654,0x000231c48aeca4f3,0x000a6a4d3a8f27aa,0x00008dde1551daa6}}, {{0x000901ca13309f4b,0x000cc1b25d3b7455,0x000e3ab715f6fdc0,0x00089282b9a04c15,0x0000c045df01cfee}, {0x000d75e0c168f76d,0x000e0171344f2fd0,0x0005435774ec19e9,0x00056bece16d3efb,0x0000be9d895f073b}}, {{0x000a4a40e4749395,0x0003734cc0308f44,0x000ce52d8c15a3ea,0x000e8df3075e4632,0x00004bbedaed5c68}, {0x00006feb5915c0d9,0x000949c11a211e9d,0x00019a13bc8bd809,0x000ff23cfa204cd8,0x0000b0ba02c5fdd1}}, {{0x00054deaaba5d8eb,0x000a6f6362a3502a,0x0007aa9e44e1e1d7,0x000cb2b299a780e5,0x000070536c702e08}, {0x00097282cef3adbd,0x000014bed566650a,0x000e5203d864d70e,0x000ddd1dc2014b85,0x00008605d670e497}}, {{0x0000ad950d9dd8e2,0x0001a65713c77ad9,0x0003175ee249e6a4,0x00060f1892e877fa,0x0000ea9facbe9436}, {0x0009dfd972df6c3e,0x000cbedb2b8203e3,0x00058343fdd04e5e,0x0003d97ebfc1bf8d,0x00003e108caa72ac}}, {{0x000b277b4f2aa16d,0x0008230545a5016c,0x0002e2769b2435ab,0x0002779964fdc84e,0x00002e12bff6b35c}, {0x0006dbbcbe4dd215,0x0009cf4e0ff812c7,0x0000e963f1c305f5,0x0005e69a0be36a64,0x00007762740fc054}}, {{0x000c36a9138a7f68,0x0008470ee63806de,0x000cb7255647a569,0x0007fd1b252fccff,0x00007c9171f47258}, {0x00097ff34fc8093d,0x0008de7129a90bdd,0x0000a742e5f26310,0x00051c078b3f740a,0x00003fd65a14fa19}}, {{0x000341e2c79fcc59,0x000d996d461221d7,0x000e9d32b3c02d65,0x000bf9b355c0b280,0x0000b04f743f16ea}, {0x000c8edc4bc3438f,0x00096016b5362987,0x00010d7d0315dd2e,0x000a6516e8c2661c,0x00009b5fb13a3567}}, {{0x000012645f461429,0x00093cfe4e77bfe0,0x0000678940510b04,0x000c3c83e76847ae,0x0000aff2f45006a2}, {0x000568a45e9f4ac7,0x00003ec5016c2bdf,0x0000224802e6c323,0x0008a3781ba7f616,0x0000b608cbc8aa43}}, {{0x0006e23886af7a22,0x0004d87701710104,0x000dd4329762ec47,0x000b0c85a529a29f,0x0000ca8eb75290d6}, {0x000944765a1f3112,0x0004526223465ae1,0x0008b3e5061d9db9,0x000c05c301f5a96a,0x00003eea325d3356}}, {{0x000ea3fbc35ccbaf,0x0003d0980f8881d4,0x000742058b853b8f,0x000a93c1cd768f5a,0x0000aed3d20d113d}, {0x000f0613da6d40d8,0x000bfc5a47958e97,0x00078f3cffc06a56,0x000231aedfc6fba6,0x0000fe6d947b0cd3}}, {{0x000959b0ed60b577,0x000f5ec0253c6f66,0x0008e5689b3f8d47,0x00064ea48fbc6376,0x000021581d29868b}, {0x0009abba118e8524,0x000b62a3b710d54d,0x00007ed07686fcbc,0x0002ac100d616b1a,0x00008f7e4edf5463}}, {{0x000afd83d0bbed45,0x0009a4a423d92e83,0x0007efe97713bc6d,0x0002864fd29134cd,0x0000f105bf080515}, {0x00099d5c6362bc3b,0x000301adc72d227d,0x0007d741e5cbbe71,0x0003e8ec90a2b500,0x00002cb9449eed3c}}, {{0x0007431dacc6cd8f,0x000327d0afc47ee7,0x0004cf1e41610068,0x00016c7df373dad7,0x00000042e51a0bb4}, {0x0000030244d5b5c0,0x00046436c0b767e7,0x000a283bcb615adb,0x0001f3281f151893,0x00002a5797383854}}, {{0x000aa5a92ffbb0f3,0x000ddf4779f321c1,0x000d9726ba60bd3b,0x000141269fac0c6a,0x00009d33c89d1a6a}, {0x0001d981b6db934f,0x00097c858d13b960,0x00095003d1097326,0x000b1547c517a25b,0x000006db28fb4238}}, {{0x00014be21fa8ba83,0x000723ee01b8bba9,0x00053235fc70e3a3,0x000854ee045851bf,0x000076061a1e3082}, {0x0000ed8989d0ade3,0x000e0475957e0684,0x0000b493f0327c6c,0x000c0eec5255cb9c,0x0000fb2ef57cd978}}, {{0x0006e16fd686583d,0x00057ec048801ddf,0x00069f1cc520e3ff,0x000612fe4ef3e986,0x000004ce0c5522b7}, {0x00081124788f63ea,0x000409a1a13cbddd,0x000c67aaf921c06f,0x000d218fe7051bf6,0x00008b2ed76302fe}}, {{0x000dfc779262f1ac,0x000f6f4b5df8fd32,0x000451c354acf03a,0x000b9cf87bbf3a89,0x0000202b08c85e13}, {0x000e0f0ccae32d7b,0x000d462b52f30d47,0x000ccba62aab00b8,0x0004cba64588a6eb,0x000032bdcd539457}}, }, { /* digit=2 [{1,2,3,..,}]*([2^14]*G) */ {{0x000da81d1a2da736,0x00040521de498b84,0x0001c2d52e2068c9,0x00034dcbf6d4ec10,0x0000ea5880b663f8}, {0x0006df66b322ab71,0x000871f17ecb7ffc,0x0000f54419e4a898,0x00008b81cf1e389b,0x00007a05a6db6c73}}, {{0x000d667d4f8e5a50,0x0005f26536b3c801,0x0004a16346a9cdbf,0x000ccbcf92ba9de0,0x0000fd5b3900eedf}, {0x00033c3069b93deb,0x000cf3b7ce8ad20c,0x000bd324a9a9bcab,0x000e5cfb2329a308,0x000095f2c48470ed}}, {{0x0004bce015ccff87,0x000eb34d4a8f11bc,0x000721bc1cd438c9,0x0000827146cb5b70,0x0000a843732fe483}, {0x0001dd088c05eae6,0x0007da74df7bf31b,0x00093d301e85027f,0x0005ab37a147b28f,0x0000a2d230e7336c}}, {{0x0007c5babcf7ea0d,0x000569819d685897,0x00078e0634866c49,0x0003879a283042ba,0x0000ab406b710c6e}, {0x000d69f7c9fd8080,0x000e1dc73087360a,0x000d64b5dfb2ca8d,0x00033828902da352,0x00009013008cdbe0}}, {{0x000c1bee4cf1095b,0x000bd1666a4b713a,0x000b431e3d19fcc0,0x000938196d536753,0x00009b8e71621624}, {0x000a316451576162,0x000c76ddc87f3039,0x000e232d808e2b09,0x0006544735ee9f1f,0x000087a1d181f421}}, {{0x000997691124b333,0x000d451eb882ca26,0x0000f886014ca42e,0x000749cbae97f712,0x000066796b2b5be8}, {0x00085f944d025c08,0x0007702f28a19d3f,0x000e61bdac26a8c0,0x000db2ea8aad567e,0x00008078a3f854ce}}, {{0x00007ba56ac78d16,0x0009448f1d1d7ddb,0x000b3a1404a747c0,0x000254738fd1d565,0x00000fc34247734c}, {0x000dcc5f098ff4c6,0x000ef2299588fd1a,0x000526f2f3ca3291,0x000225dc6ae0385c,0x0000d29a013f2711}}, {{0x000264880c2de156,0x000947380fee3995,0x0003cc64079cf1c7,0x0008da6ea4de174d,0x000003341f9f4354}, {0x000e8151f6e4ad1b,0x000bc54650c77ccc,0x000de287aa666044,0x000db0e21e16b6f4,0x0000efb7d194ac4c}}, {{0x0007348efe215c9e,0x000a931c79ae7459,0x000bc87a3f8399b5,0x000a1bcc9091643d,0x0000c57a72438223}, {0x000cbcc9f0323ea7,0x0003f4633ae285d5,0x00075e694b36151f,0x000d0d5c1d1a3493,0x0000014dccf8288a}}, {{0x00030900d2988954,0x0003e2d547c4b1d6,0x0003d769a258c9fd,0x00064ff7bf5754d0,0x00000bcff2e3a601}, {0x000995fcc5b48583,0x0002cf93957e8bcd,0x000d37ccadf3bf57,0x00031fc7dc53bffe,0x000071bb6556f9f8}}, {{0x000f0306abec554b,0x000c8bc468067e3f,0x000d6238fc116a66,0x00069b8bd7796b94,0x0000a6558eced667}, {0x000af21c707b4feb,0x000a2aa0e68fd01b,0x0006f4d94f62eeee,0x0000ccb1d1af09d8,0x00003f1221391f32}}, {{0x000eb563bf3376c9,0x0008f5d8ea00637f,0x000675ed8c7dbfa9,0x00051a85bac437f4,0x000037bf89c8189d}, {0x000ba46a66de87e9,0x000d24fe7e880662,0x000a387ef19a5076,0x0004953dbcdc6eb5,0x0000e2e1c4016e3e}}, {{0x000f9b9bb42c0485,0x000ff2e8def6906c,0x000dacfee25d0f89,0x0001242fe1bc12ce,0x0000ba97a0a64232}, {0x0001c99c56cf201c,0x000d455c2ed2dbcd,0x000509787b117d3b,0x00095af8690b3a9b,0x0000417bd19de076}}, {{0x000424aaeb3b91d4,0x000a998c13da2eb4,0x000c3d55be8eaf2e,0x000e03205c693bdb,0x0000fd5cf1c45d66}, {0x000d0f0a7ea7323d,0x0005a0440c0cb913,0x000e433cbef81c62,0x000ea78c3ad814d5,0x000070dbb0fed04a}}, {{0x00090203a46ae630,0x0001c021ff3b323e,0x0008f647e46c84d1,0x00057306c16c8124,0x0000a93f9c553d27}, {0x0007068a29d80ae0,0x00066d1e92ca2f02,0x000d3c68f1fe6df3,0x000db0092823efe5,0x000043f0b8b11afd}}, {{0x000ab7a126c29381,0x000d4f017773e3eb,0x00051c6ad9458693,0x0004188703c92ac9,0x00008d7d6ab30ed3}, {0x000fcc5e3f382814,0x0000f7ef5c71c3f7,0x0007acea6adea02a,0x000f418dc0bf1f23,0x0000b54ae9a11e38}}, {{0x0002f3a2514a57f2,0x000755bd0ab98c69,0x000170e5611bc333,0x0001ad1373538876,0x0000a7a18cb1378a}, {0x0001b5efeee3ae1e,0x00054b58ddc3cceb,0x00036b1de1bda0d1,0x00035fe338e63f0a,0x000007514aeac9d8}}, {{0x00012e9031f0a5ba,0x000cc72344d0cb10,0x000f9f81fac388f1,0x000819ec8de87114,0x000074f23945d20f}, {0x0003e7f085b71746,0x00040c6c0934c56a,0x00090588b97228a8,0x000b5a380052b408,0x0000fac86ae9306a}}, {{0x000c5184d549deec,0x000d52b46bc9e417,0x000192f5462b2c21,0x000c8f8e355f7d23,0x0000cd177410648a}, {0x000d55e33cdefe21,0x000c7275af172a79,0x000eebe63c04f4ee,0x0007c713ff4aa0b7,0x00008d8307613e4b}}, {{0x0004d3cd58e4d852,0x0006bab993f02b8b,0x00026693cfd3cf03,0x000af4e6d5408547,0x0000c2aabff8fa45}, {0x000a3c809ae43c50,0x000cf7a0f723e79e,0x00046edbbfbdccc1,0x000982a8cd0b6af1,0x00002b1e5a091517}}, {{0x000fd07201deffac,0x00025809cadf872a,0x000cb98046995509,0x000ff21f4ff84d98,0x0000963d2bcbfe56}, {0x0002499093a6be69,0x000585326f80abc8,0x000f80d703b9d497,0x0001bfd4d58fc0e7,0x00004a60473ceb19}}, {{0x000e5caaad4486b4,0x0005d1e24444b21e,0x000d3ed0c0b72819,0x000f982fc3cff018,0x00004ba520fa8898}, {0x000a25bbc397a8af,0x0002998611e20d76,0x000406e1ccb223d3,0x000b86f4e2652aa2,0x00009c27f8856e6a}}, {{0x0009fc879466ceba,0x0001f18b2f8e875d,0x000210013a7160b9,0x000c7186305ed045,0x0000eb43ec41e200}, {0x0002cb32611aaefe,0x000c458e587ba1f1,0x0002c7fb38833b1b,0x0008800e363b5a76,0x00002467a594f1ce}}, {{0x000404e6c71b8202,0x000e48bf41f295b4,0x0003bbd6407bf067,0x000844a0d45ccf07,0x0000dfc2ca06446e}, {0x0004dedc225205ce,0x00035847c15238fa,0x0001bcdcdbedad65,0x000bf3d178a82808,0x0000a8e3bc0a11ca}}, {{0x0000c6ae5018d027,0x000a419015aee791,0x000bdfb1d84f73ff,0x000d4b9963b67b87,0x0000485df021db40}, {0x000ff3d64526fc0f,0x000809d05281ec5e,0x00034417b79ccca5,0x0008a68f1ced9e92,0x000084c11d3c4c8d}}, {{0x000c1ee614663ebd,0x000eefc957140edb,0x0004cb8ebdd6ee14,0x000c319463886ccb,0x00003f1f77e17b13}, {0x0008c813d019b2ae,0x000ae3a496d29903,0x000b0b3353a94e2a,0x000af96c39382e3b,0x0000a718f3f170b3}}, {{0x000c164496ab3d67,0x0006ea56a382dda6,0x000036dc6d5437ab,0x0008c51072a7b515,0x0000956b614be2c0}, {0x00073c805d2be046,0x000e2a99459dcad8,0x0005bf1a2e6a28d1,0x00042bc725dbc286,0x0000b972c00e8d03}}, {{0x000aa44ce9e0496f,0x000a7518060ed141,0x000452f518ef97a7,0x000abccfd1dc35d3,0x000044605da47e0c}, {0x000f1fba3870f0ae,0x000ece7c99396b4b,0x000488733ee9559f,0x000e5da54cf3f91b,0x0000a28e5309a1c9}}, {{0x0006d871fcfa1706,0x000e3b101284285a,0x0002d9406b0f302d,0x000121cb8a49debb,0x0000c65e2ed97a1e}, {0x0005b77a782ee91a,0x000a18fff5f1afba,0x0000590abfa71329,0x000f8f32227e83f1,0x000050dde9b93ce1}}, {{0x0009607b794f0285,0x000f0c89ef49400c,0x00029e7554b7902b,0x000a03702d679b84,0x000027d77adc7fb0}, {0x000c9a2c835846f8,0x000d19300fc32289,0x000389f09dc87369,0x000449f520da060a,0x0000929d2a527a1a}}, {{0x000d034270025e0c,0x0009dc6d5d8f5f46,0x0008b8bd0e581906,0x00031cd1e56e8bfe,0x0000ed5db268c8c6}, {0x000d7cfa60528665,0x0003499dd0753176,0x000a49d661bee9a9,0x00055f095fcec179,0x000078f295389204}}, {{0x00010c7a09f07b72,0x00054a4f28f770b2,0x0000ebb86416fc49,0x000e678562cc3429,0x0000c146c66ed941}, {0x0006c78f44e0f9a9,0x000ed0e1730b01d2,0x000dd20b61e67d48,0x0004e94705fe8cc4,0x00004cb9e577978b}}, {{0x0005b05d6914ffce,0x000bbcbc25e829c9,0x00064f5723a4258e,0x0009424439122bbc,0x000062a0f760a317}, {0x0008e2d3db0cdd63,0x0006e0a06d9aac8f,0x000ef51a43b76bd2,0x000e313b4e84259e,0x0000cd05a227ffe3}}, {{0x0007a74f56626479,0x000ed3a968075def,0x0002063cf858014f,0x00060623e3b51455,0x0000d8a825e00c73}, {0x000803d1b3ff54bb,0x00057ca25942c21f,0x000b4932e5b4a102,0x0003a09d5ae52fa2,0x00001c461ac9803f}}, {{0x000b28d11887efae,0x000ea168fa1b64e1,0x000b56a252fe844a,0x000dfae103e32b3d,0x000025b4f7dea5d3}, {0x000947e940ce1f1b,0x000ca48aa1767741,0x000a6ef9a8c24921,0x000739056310da94,0x0000c91e4f7cec0d}}, {{0x000631d5545c61d7,0x000e9f1a5c65d6fa,0x00046c01c5cb2c3e,0x000b12160108765b,0x0000037e6b0239be}, {0x000f48f86beaf031,0x00003582003a33aa,0x0005101c310ecee8,0x000a3f604e6cbfb5,0x0000370d71300c7c}}, {{0x0000b578f398f5c2,0x0002684aeddb0ff5,0x000a40bb38f9bc76,0x0008d0e81bf9c714,0x00005ffb3646b97a}, {0x0006781ae38091b4,0x0003bde34988e66e,0x00063bae09eddb66,0x0000f7f47a3c3027,0x0000045549bcc1b5}}, {{0x000293017d41f805,0x00015b6e5b119f8a,0x0007fe0ad1dcef79,0x000dcb03d2f4f593,0x0000bc5de02b9ec2}, {0x000fe4bde4a50c54,0x00075fbe79e7001c,0x000f666fd4f9eba0,0x00036e2014942d8c,0x0000174ec1b3aeae}}, {{0x000fca2c37292e34,0x000df0d50a803e6a,0x0009860576e3da8a,0x00016b82c8491f1a,0x0000f908c5eb3698}, {0x0007bce061481fee,0x0004ca0326e92580,0x0004ef03e64401e2,0x000e3e3b0b3335a2,0x00006a363fee2346}}, {{0x0009631af51f3820,0x000310bcf577dfc0,0x0009a7fe9a4d5c89,0x0006e8e893b8e850,0x00004aa3176b18d3}, {0x000fe9e9998db107,0x00088de616ddcf17,0x0003cbbbcb14c557,0x00003faac8272dc8,0x0000f37f11c6d949}}, {{0x000ba3b57ca7d9fb,0x000fd143f3a1d7db,0x000b58fe1aeb5b1f,0x0000b20f07391ec2,0x000053738f59c6e1}, {0x00071b4df4657720,0x00037c87c0c02e8f,0x00048a4dda850a8e,0x000c2bbecdb49b0f,0x00001e0e88fb7249}}, {{0x00038cdac58335c3,0x000c66df86cb8aa1,0x000a5efe055d4c77,0x0008683ad1af4476,0x00001273e06eec8a}, {0x000a2ce980ef2516,0x000377fed539bad2,0x000293912c3a97cd,0x0005bf11b26fc0b7,0x00002701f2738b12}}, {{0x0003ba8b2493b148,0x0007d81bf2ec5d3b,0x000ba5926cd37918,0x00003b04098e8707,0x0000993e2bf0b8df}, {0x000b9e789a25168f,0x00011110cc4fd0b4,0x000f73b82fcc0949,0x00025b8664697e9b,0x00008b52da34d004}}, {{0x000c26b8aa6f79d5,0x000e067dcfb9770c,0x000edbc74258b6a8,0x0008a01b52d4c4ee,0x0000e4bcfdfaa83b}, {0x000fb6562627da7f,0x00009f556e31fea7,0x000812774e7e1710,0x00049a0c8d511a79,0x0000bbd260be01ec}}, {{0x000722aab36249e1,0x0000a40db721fc3e,0x000026a00c5e1911,0x000d74549b846153,0x0000b622aadebdd0}, {0x000ca6686c5b5ea1,0x000292c7cbcce6e4,0x000fead6468bad0d,0x000bbc79632dbaa5,0x00008d702b3a959e}}, {{0x000945ee8039f7f9,0x000e245d6a8c7bdc,0x00087d06e54cdf17,0x000783d6f1f6930d,0x0000551ed8a2334d}, {0x0008ab5b4cc0c954,0x000c9e84281ae650,0x0000185519e20a39,0x0007ef592eb5d96e,0x0000ec44157cc235}}, {{0x000fa33716016f7e,0x000e46af2f5045d6,0x000a09af49a8fdb5,0x000e43c6a1cc8371,0x0000c277d0e603e7}, {0x00075a70fd1e4ccb,0x000139ebdaf3db97,0x000de03d23466af0,0x000a4a43866e1ef2,0x0000fdf225ba7f64}}, {{0x000f14821c351edd,0x00021666bac77433,0x00028a88c1031a4f,0x00003eb20264c266,0x0000b50cc08ac4a3}, {0x000b467364f7c8ff,0x0009bc822547761a,0x000838d0cd7ef0bb,0x0004c66a947c25a3,0x0000d8d71347dba3}}, {{0x000a2a39c57739c8,0x0003badbd20048ba,0x0002c2455087a0da,0x000600d3308eeb44,0x000035ab7e73bb70}, {0x00039893a9299ac7,0x000e1e5fae8a6704,0x00048b6bc37d45c8,0x0006000cec119be8,0x00002354d9fe710d}}, {{0x00044539e0bf2fd6,0x0009b8e02b90f648,0x000d689709228660,0x0002c31506185413,0x000035c1a6a9b616}, {0x0002e4cfa6e7a7b9,0x000883f5b421e0bd,0x0006decae0701125,0x000ca3d924eb9b7e,0x00008973fbb6a139}}, {{0x00084810bd80b472,0x000c9d87096bfb22,0x000213dd306a948b,0x000f10fc1ad42d95,0x00008adbd51369b8}, {0x0005716e1bc7e9cd,0x000e88f207a0a817,0x00081194cb775ec2,0x0000051502eda484,0x00001655fde650e6}}, {{0x0002d8529ab17664,0x000febdd18efe4ef,0x0008f93d5bb9e7aa,0x0005bd5b6398956a,0x00003781ce087bdb}, {0x000adb3daf55c56c,0x00037ad269a5439a,0x000db01176c3f26d,0x0003e296872f7e7c,0x0000033a30fcd1df}}, {{0x000bd6335284b84e,0x0008f43880ca626c,0x000925adb6bbaeb5,0x000a46b04a59bffa,0x0000f0ff8d1a11f0}, {0x000a185a6e7f82fb,0x000f677d6d0f0bf9,0x000fe783b2b1463c,0x0001df2e23eaa59a,0x0000740f8798259e}}, {{0x000c722cfd41d7fc,0x00094d23f0bdd09a,0x000c4e6261ce5297,0x000c7c34230caad3,0x000087ee7f4ba1d9}, {0x000c5464bb31d104,0x000cc2b2971e1826,0x0006075a6c6d5093,0x00046ca459e99e4e,0x0000a65a1fb97994}}, {{0x000c644d48d918fa,0x000a94d0bf8c23b4,0x0006cfb155d1a0ec,0x000071c4322d7bc1,0x00001f3bfe3fb2c5}, {0x000783f98fc491e3,0x000a7c0a39281925,0x0008235ca69e46fd,0x0008ae01fc9d169e,0x0000ca900548dc79}}, {{0x000bda541349a39a,0x000c425a2a1aa23c,0x000962d9a09f1913,0x000462f7c27405d0,0x0000bde10d8a970c}, {0x000e683472ead4af,0x000cb9cfd08a2467,0x0009aeb8afaa4737,0x000ded0ac9c9a0d3,0x0000ce90da220b05}}, {{0x0008f648f58227f8,0x0008836fa6d3184c,0x000e3ba47dcb6caa,0x000da665bec76370,0x0000b6a20603deac}, {0x000582c5e925265f,0x00046c9943a97cef,0x000568b96c2b5af9,0x000cc39e771b3bdd,0x0000841b94d6bf73}}, {{0x000bf54149dde419,0x000a87dd1b4541dc,0x000e114d1eae42db,0x000618a1da2ae53e,0x0000d375cfe5fb7d}, {0x000c7151c5ec6dc1,0x0006021ec84fcd40,0x000c06e7f03abd0c,0x000e5abab6ac4a9f,0x000092cc4d88e993}}, {{0x0004a400aa461c13,0x000fbb8169ed26cc,0x00035b80cc32eeed,0x000c0e53577fae15,0x0000c26d785c466c}, {0x00060512ceba4cd9,0x0004d5dbd6d77e63,0x0003d73e01830fe7,0x000f552a7971b6cb,0x0000ff6234aaf953}}, {{0x000264d6ed5d6a7c,0x000e0ce67dac839d,0x0009760722497bcc,0x000fa7d6b7f1b9b1,0x0000412325c4dc51}, {0x0006aab96f5c6a1f,0x00010838ccd0083c,0x000477f4aed2a7fc,0x0003b9babdf5da39,0x0000b6954a4db685}}, {{0x000b9720f5c665de,0x0007b936adb439b1,0x000f941b1f83f35f,0x000b862417afe4c2,0x0000bf88e1af3c59}, {0x0003fc188202f659,0x0002281f3bbbe4c4,0x0002a4f2f7105f4f,0x000558633d4e7b95,0x000028d27173eaf4}}, {{0x00076bd78c722e88,0x0001551700e67635,0x00094f20827e73e4,0x000aef9bcfe57d6e,0x000097aad46ac9e8}, {0x000fb4432357b1de,0x0002f28bc7ebf10c,0x000ebcc31c6cab55,0x00039f2999933d7e,0x0000f5102b0ca303}}, {{0x000a7e1a8ba693a5,0x000ba49ec02c239a,0x00067e4df2c98264,0x0004249f27435ecc,0x0000c02baa7777ec}, {0x000e994e304f2110,0x00083fbacc530a15,0x000fefab6e1cec97,0x000590dcbf287767,0x0000795c0592733f}}, {{0x000984b1ef514e65,0x000ebd81411e2260,0x00032dfef40dafe3,0x00094956e4f8c6ae,0x0000136ba04fa012}, {0x0009ccee49a09296,0x00064c3b8e8e0968,0x000892b26d304e0f,0x000a112d29d432b7,0x00003ed12545e12b}}, }, { /* digit=3 [{1,2,3,..,}]*([2^21]*G) */ {{0x000ce669fe8edc64,0x000977cc52c3285c,0x00000d67ed46f754,0x00061b80f9f0ec69,0x000012dbd13ccd38}, {0x000807b39e2a78af,0x000206aed104adae,0x0004dbd4a5d72c92,0x000027f3b3295361,0x0000693ac17f9250}}, {{0x000f594afa4a4a7e,0x0000f5b4b990ac34,0x0006399e2ee44b8b,0x000b41f7bd0670ff,0x0000001c5d479361}, {0x000a8e6617658623,0x00048daa039ef32b,0x0006f48d6ebc6748,0x00037741a7683353,0x000042075593bdb8}}, {{0x000094eefdd302c8,0x0009c460befb138c,0x00020963d227f072,0x000d142da3f15ca9,0x0000ba9e641f3b9d}, {0x000e401530c93b7d,0x00059744a3037da9,0x0003796f4979883e,0x00016795e7569395,0x00000c613cf9d65c}}, {{0x000b20d1bb21d958,0x000fae479a31475e,0x000d97dd75179a2e,0x000145b32680eacd,0x00006b0a592db55e}, {0x00009e2a418bd004,0x0006a13ebcb0ebbf,0x0002fc81c9f8657b,0x000a128ce6f290ff,0x0000c2bf7d73e0f4}}, {{0x00034ee8f7ca2841,0x000957847db5272e,0x00051343550a99c6,0x00027dce2b87e02c,0x000008e06a87c6fb}, {0x0003e4982cf177a8,0x0006fef4d4a55e9c,0x000544e47582945f,0x00026aa21056b319,0x0000bff078406896}}, {{0x00002033f3eacba9,0x0001ecdd9087e29c,0x0005322e2493e6b9,0x000f6eadf4905da2,0x000016f929c8a045}, {0x00059f8488967f6f,0x0007be7575f06e12,0x000d9b6612dab69a,0x000892e6af43919b,0x00009097672f7684}}, {{0x00083aac2d553230,0x000e2ff837639a05,0x0009af89299438f4,0x0004cfd3b1df4866,0x0000926c091d5ae1}, {0x000a5356cab1f151,0x00008a0b5e8d9e9f,0x0001ca41a7e71ebf,0x000839a4f0b024e7,0x000062a46f632c13}}, {{0x000b21b7651b535d,0x000ed1ed8043c9bb,0x000ce1e1641850f3,0x000ddb9452c21474,0x00004ffeff4a6ad3}, {0x000dfe0c1b878ca7,0x0005170036f8309a,0x00092f2e778c4742,0x0002eb6f51aac2f0,0x00008b0fb8da7185}}, {{0x000858780433abbd,0x00033774b30fce56,0x00038782098ecd9b,0x00099b6cee29ec01,0x00008890c1e6e660}, {0x000f67858c8ce86a,0x000d24efffce7d38,0x000387b8a9346a50,0x000711dcd7ef98b7,0x000069a697b171f9}}, {{0x0003d469b1729fe4,0x0003a650ac09ae3b,0x0007f3ea0e2a6394,0x00028ea3015db36d,0x0000ff7f5572ee9d}, {0x000e9e34a5b7a36a,0x000b713b7a4042cc,0x000b2865c4506a15,0x000d73147264da3a,0x0000d28e88eb3d3c}}, {{0x000c180b52f9cd55,0x00035dbd16da5551,0x0005671d63efc307,0x000d083bc2c9bef2,0x000077cd3b33b7bc}, {0x00016701d2c8f290,0x000af20f7a38f325,0x000c4fa1e8432fcd,0x000902477a71103f,0x0000c13307631946}}, {{0x000a6de9599a5692,0x000b8cbb1dad4d5d,0x000317ddb4c6dcc3,0x000820def3a0ba2c,0x0000523c6f46afb3}, {0x000507a5b0666ce8,0x00009a4e67dd5fa6,0x0001f27b937bc419,0x000e17182d353469,0x000013aba876630c}}, {{0x000e231e63f86155,0x0001ac0dd78b9590,0x00056fcf6a929cf7,0x000aff49a7e599c7,0x0000f2beae09c341}, {0x000c54d7d94bca5d,0x000460a94c47dce4,0x0002a0654f786ff2,0x000ef6bb318918dd,0x000043199fd3902e}}, {{0x000672c94de6b79d,0x00065b645d1cb3c6,0x0006de9aae65c98a,0x00020c93993596a1,0x0000084850324b2b}, {0x0007470e2ed88727,0x00078a44113efdd4,0x000588cca7c8e729,0x00036e449a848413,0x000086370e30c8fe}}, {{0x000cabc373c129c0,0x000b795474aefcee,0x00074d1801c4d4d6,0x0000903a019fb1d5,0x000090a24a4b2a71}, {0x000bcf6d4c7ea10b,0x00045a7dff3768f0,0x000f699905cf4cac,0x0004d37be1302ac8,0x000059f9ed7615c4}}, {{0x0004954a8c5f8491,0x00036d6e05110de4,0x0001ebf0a61838fb,0x0003c617a5d05e90,0x0000931b4242abcb}, {0x00055e87db36946f,0x000d5c8c8d5ff47c,0x0001d34b9a502d72,0x000abe95f6140f42,0x0000eef1dfbb044d}}, {{0x000af702fdfc658e,0x0009b5edcfe4f6b2,0x0003916044a0e71b,0x0009253d633d18f7,0x000067827258be5d}, {0x0002270c1591a40c,0x000aac7e34119c0c,0x0005718100a44dc3,0x0007de482d9958a4,0x0000936a6e932f8e}}, {{0x00002d829e0de935,0x000d2b09417b0748,0x000bfb976a3c1581,0x000b232260ee014c,0x0000912559287882}, {0x000a3a2e63eb8e6a,0x000cdebf51672313,0x00079a1f51566a56,0x000a7c04a1f1a9ec,0x000070a867c7854d}}, {{0x0008953d6fbc948f,0x000f59036928cf85,0x00092b62a61d026f,0x000b727b9d2522d8,0x0000d4740c141ba6}, {0x000e7258d3488637,0x000fa4f6dd639d25,0x000c32176d124824,0x000ef5dc0aae73c5,0x0000a6763062fc85}}, {{0x000816180ac7b35c,0x0005671668988232,0x000293310c1fe0fe,0x000d24b7b7e35a0a,0x0000fbc7f7dfa8ee}, {0x00002f829b61fff0,0x0004af7a42839a1d,0x000ff28e0716b31b,0x0006c53c4262a0be,0x0000eeadb1a1ce5d}}, {{0x00015f1a3129e10f,0x000af2b4e6c937c8,0x0002977a7267764a,0x00073c6a478a6c0d,0x0000cb95cba1c483}, {0x0009a10260d9eee0,0x00063e1488dd8e2c,0x000bef43bc3079ea,0x00087b3e5515d1e2,0x000027a54dfc6c17}}, {{0x000bb05b171e260f,0x0000312f11202e54,0x000cbd9782e9eb34,0x0007071408c05d3f,0x00007b0ad44d5ffa}, {0x0008e0fdb6bdc2ae,0x00083bcf267acc86,0x000abae442a4c99c,0x000059d8f7232875,0x0000d3f091a78c65}}, {{0x00025e9ecbca3bd5,0x0005b277501df3f8,0x00002e53470ab011,0x000c2c5c9f5f0879,0x00001e324f25d94a}, {0x0002c87b5f5c096e,0x0003690c467cfb66,0x00083478fe443b48,0x000ffa57d95db742,0x000084fcea7f7f1a}}, {{0x000be1e8d816e34a,0x0005ed0373a139a1,0x0005503eb6c76567,0x000d72c0a0c0fe38,0x00000930e2800fd6}, {0x000a839aa5e6043c,0x0001feb1c5709e13,0x00063fa936978e73,0x0001cc67e25bec26,0x0000b4bdbcf0e7e5}}, {{0x00063de507ea770d,0x000de8db50e250d4,0x0003df144efaa8e2,0x000948957b939cd8,0x0000f00ebd59ede6}, {0x00058f76309396a2,0x00070b764deb6457,0x0001c9d75c4c6c1f,0x0009d4bd7c9c7109,0x000094ab2f959459}}, {{0x0008e62912bb0c69,0x0007715b88eb025b,0x0008b374d95a85ef,0x0008d1ee3692017d,0x0000e00546935947}, {0x00067e18f669c1a6,0x00031e71bb112d7b,0x000f45f7f358f9cd,0x0002a153c6281ddf,0x00009ce24d9faa21}}, {{0x000f23a149bca110,0x0006b07752dadb87,0x00012f665e907d38,0x0000550047f8ad59,0x0000a6b2737c88e3}, {0x000df2eae0d2d96f,0x000d847b47f5dc0c,0x0008afaaf8da34d4,0x0000c0a53b08c91b,0x0000e0c5963803ea}}, {{0x000040a69d08ead8,0x0005d6ad8eece93f,0x000e87e8da444df5,0x000e5f2b193b1fa2,0x00000036b7fac7e9}, {0x0004a15b7ebad244,0x00033aabbc15474c,0x000fda83a8c245cb,0x000c2ef6f58e5947,0x0000ab5619ed45b0}}, {{0x0006744b238ad74a,0x00032c3f045f7417,0x000a0cd8d1dfa1dd,0x00031dc9d44dabde,0x000084c351aa16ef}, {0x00066dbbbd4b79cd,0x0004a96d5540a264,0x000654e5bf972fe2,0x000124ed39cff7e8,0x000006fad5584afd}}, {{0x0009b54ae4ccf190,0x0006b5139c106a36,0x0000e8f52cd3cb71,0x000bf08f80ab4008,0x000063ecb5195105}, {0x000e88b3133f9c79,0x000eeb2da83f3530,0x00079992670c5be7,0x000c619c9d672568,0x00009c94c9c60e0b}}, {{0x0002d3810e75db98,0x0005272729ef9b4f,0x0007ff48b8893550,0x00078145eb9f842d,0x0000b7c621d7385a}, {0x000e48f3bca9cf86,0x000b8618ffd026ad,0x000e625e5d56e39f,0x000ab106e697de51,0x0000a9125a0d4e5c}}, {{0x000447e9cc831545,0x00039cab5ded44d9,0x000acfe1552fee6f,0x0002053a733d2726,0x0000d8fb9153c30d}, {0x000e7b29e73a90d1,0x000b934edb6a2c09,0x00051fd35387a394,0x000def08b496427e,0x00005f85a2688694}}, {{0x000424e8f9ba0b93,0x0007cc5433ef7479,0x0002d758a3e8cabd,0x0002c570b4f000a1,0x0000648310308664}, {0x00091a20f1e32de3,0x00041f7fce3ececd,0x0006f7a6a4a18ef2,0x0007a40a6f273f95,0x00006d7bc3eb35a4}}, {{0x000d62c3c0d878cc,0x000bd2f14f772133,0x000506fc0d074a1e,0x00053b069efcbcf3,0x000054da173b382d}, {0x0006a1152b4b6ab6,0x00077d56291d93b5,0x000356e41211a144,0x000cf742c41cc0cc,0x0000d44d93647521}}, {{0x000f6db69902561b,0x0009788fc670cdc9,0x00011bc01617c072,0x0001039ee89bce70,0x0000cfeb4e30a91c}, {0x0008f453c12e47f9,0x0008ce538b6874d1,0x00013f0f3dd733fa,0x000df596b652acc4,0x0000070c70ded8f9}}, {{0x0002577943ed1947,0x000c51f97d56ec8b,0x000635b321c1dce6,0x000f4c0548ac452f,0x0000108844a039c5}, {0x000d188c05a8f588,0x000c907ce36d8dc7,0x000454c24921477f,0x000444f341fa52c4,0x0000a2d7f2d74a60}}, {{0x0004981202326049,0x0009f23af30ee110,0x000d64a57e4877b7,0x0008d66d3bca95de,0x0000aa95f1b4aaaf}, {0x000957488a1fa688,0x000248ced945f9d8,0x00053e4500e34b51,0x0004ec08199ff786,0x0000dc704075eeaf}}, {{0x000432d7fec902b7,0x000dcb98903b6701,0x000d7b52267dcb60,0x000413111b403207,0x00001357bed41bd7}, {0x0003d756c1125098,0x000a7a9535cc50ee,0x00098d003854c0f0,0x0004962fbbd5ae57,0x00004841bca8d5b6}}, {{0x000e30c76057eb58,0x00068ca7bfadc9c6,0x000b3aae0116da0a,0x0004e7debde602db,0x0000de60723a0a04}, {0x000c372afe5f7c62,0x00098fdeab5ccde3,0x000b5f5be690997e,0x0002ac9676df4a3c,0x000028ff6485238f}}, {{0x000d7abe5b2e9d52,0x0002ffa22191deca,0x0001b9811b5540a1,0x000d459ea5db7dd7,0x00007563c3351050}, {0x000a75fab5e73768,0x00027ca2af62afa4,0x00063a4216da6470,0x000fd71b1066c376,0x0000728e0ecfca8f}}, {{0x000cadd177056db7,0x0007112b5eaff3d4,0x0003bc769207538f,0x0007fbd0b226cdcd,0x0000d68a971cb7ae}, {0x000d3db0039f89bc,0x0001dce3018f0114,0x0000cd40c9ae9f18,0x000bb3ef18abf742,0x0000e4c4353ecb88}}, {{0x000fdced3ed27960,0x000a90267c9be8cd,0x0001590535eb2ae4,0x0007701b0fc0c04a,0x00000a023e8bb8a0}, {0x00066947177447ea,0x000e06cde38d8e01,0x0001fff605dcc55c,0x000c26be22dda145,0x0000b32e709b81ae}}, {{0x000518964e0c5fd9,0x00008a23f3ad0b05,0x00008aad44cb4866,0x000c136a024b9aaa,0x000067192f7f61c3}, {0x000aa96177525e8e,0x0006f03cf1735dcf,0x000d9114dd244865,0x000888ad108db4cf,0x0000aec1bfd08a5e}}, {{0x000ab3806cce7241,0x000c1ce423887790,0x0000a059a1dfabf2,0x000a244b273397bb,0x00003d65f2a93933}, {0x000a60d1b06036f8,0x000cea8ca3b592d5,0x000964a2fa69559d,0x000e4b4a59647493,0x000017ee9471a84d}}, {{0x00014f6deef40534,0x000a82e14d3d8207,0x00033d6449a055d1,0x000d431c43f7ed5f,0x00002ed0948cf9d7}, {0x0005e0389a99f1ac,0x000c7cbdce132937,0x0000397e12268f39,0x0003760a23c2f5d9,0x0000c935abac75ea}}, {{0x00052b1e1073e1a5,0x000f84a0c1c1455f,0x000d942637ad068c,0x000010f8a702108f,0x00002c64ff56f96c}, {0x000b9a16d727e0b6,0x000acf06fe3379e5,0x0005d2bc212790e2,0x000afddcb18846f9,0x00004d030329bc97}}, {{0x00000106b178893e,0x0007ae2c3659cf4c,0x0007128b98eaa6be,0x000d0f17c825e01d,0x0000fd2e94e765ff}, {0x000797e208c8a081,0x000d12668d49e74a,0x000cbfb9b2628f2c,0x000072932fe4d074,0x00002abae9bd73bf}}, {{0x000793e3b6b83b30,0x00064f8714d7bcdf,0x0000861188ceb25a,0x000836b57f887559,0x0000aa70f4c39c97}, {0x000e5a6ccef975d5,0x00068bb3df26c700,0x000b1425b20bccac,0x0001beb2c7708823,0x0000c3e597f24036}}, {{0x000920b4d475bedf,0x000601c20860a37a,0x0001a6c7768b0a63,0x0009437bdf506d72,0x0000de3d4aed0bf9}, {0x00051b6900b359cf,0x000cbfe3d2fe1e07,0x0002762542109347,0x0009d5d83f981349,0x00002085a33e208c}}, {{0x000b427915cb2d9c,0x000fec8d33d25907,0x000a6b6f878fe209,0x0004da0927589135,0x00008ba9de943b1c}, {0x000a09fab0991dff,0x00080c1e31c86c33,0x0006792b45738377,0x00022fbfabbfabf8,0x00000b81945640ae}}, {{0x0007aa27ff722866,0x00095500f6877413,0x0003805fcb9e8eeb,0x000097b2ddfcf0b7,0x0000906494cfde74}, {0x0001dad9278c86af,0x0001a53f73534dfe,0x00017c8e51d0b3ee,0x000e2264fe779fe2,0x0000f9399f5c2391}}, {{0x000f2b9a899efa35,0x00044c5bebbb0c89,0x000f7a937ed79daf,0x000d8393645c3d73,0x000002e30297a15c}, {0x00000d05a8de6267,0x000f1c09869fb65a,0x00001a95369da17e,0x0001d8284f596a68,0x0000a54eb42f428d}}, {{0x0007afd35e423eb1,0x000207737f624bca,0x0000589345b1b05d,0x000841ab44d9b3f6,0x0000856926f19438}, {0x00031d759bbd89f1,0x000491c56f96ea9e,0x000d5c66b3d428f8,0x0008f65ae85d04dd,0x0000fe7d32eb79df}}, {{0x0006c9eef207e08f,0x0001e7e6e201fa79,0x00066ba39be6e809,0x000ae2ff6bec79f1,0x0000b616f14c0f5e}, {0x000a3da1546202dd,0x0000e77aab41895a,0x00093e7c9fe3e873,0x00005f4a80c70b54,0x0000548eeadf6f0a}}, {{0x000cc1a29a108d50,0x0006ccd7dab0a262,0x000ec67c8390b012,0x0005dcb4c64bcf06,0x0000f259d55a3603}, {0x000d5ece299782c2,0x0007a0a1dc54ab27,0x000dd366a6679ec3,0x000a9f22b1d8fa56,0x00000463c1d0eece}}, {{0x000e0e293cec1e79,0x000efc99ec7f6002,0x000ea6e4722d8500,0x000d2880f2620157,0x000054e88ff06240}, {0x0008fcb8d2e2a682,0x000bb41a29a94f41,0x000046598dbf7cca,0x000fc1c555e4fa70,0x0000e866a08c23df}}, {{0x00055eaf0cd106ed,0x000eac0ffa583fe3,0x00075d5cb5db3a43,0x00068fdd48ba02fb,0x000000f80f6d4c38}, {0x000dffd39b9c5153,0x000091f21f2463a0,0x000a549ca0718f92,0x00093a5a7c8b59ed,0x000071141a9807b8}}, {{0x0007357890dd4e38,0x000ad26368db2df2,0x000025d8495c27cf,0x000ff989f1617b78,0x000034d4937f3648}, {0x00079875fcdf6a41,0x0003bafc7add2319,0x00065054796a385e,0x00063f88333b6cfe,0x0000ba555751f971}}, {{0x00044e669582dd15,0x000609ef7f52438b,0x00028c7c925d34d3,0x00088a39d0f09e7f,0x00001aa149662b55}, {0x000de74ef350ef69,0x00050efa2a33bc70,0x0004e9b4ca36537b,0x000f476a52619b28,0x0000e5cc6e2e16b7}}, {{0x000740b19e406537,0x0001128987018afd,0x0008c9ef1e3cfcf5,0x000147c2788d343a,0x000000bd40c703bc}, {0x0006907b78203587,0x00054432615b4606,0x000a2fae0e3938e1,0x000420ac9fc4cd7e,0x000061a1a83680d7}}, {{0x0001e1652f266287,0x0002072786662748,0x0004d6d5004b921b,0x0009798d1624a8c9,0x0000a6c2afe78ace}, {0x000b4716993415ad,0x0000b70c175d0b87,0x0003efa55ba75b9e,0x0009da493ef2cd19,0x0000967d0431319d}}, {{0x0001bb3328972e05,0x00081d050273498c,0x000b43e91b4aea4e,0x0009d7c51b0b14e4,0x000036a831285442}, {0x00092962275aebf9,0x000ceea0fb01f9e0,0x000ea5a49dab5109,0x00062df927cf2354,0x0000f8845418f676}}, {{0x000f39d3d76f2654,0x0008b5cef1752354,0x0002c38aeabb3b6c,0x00065abb0b5fd32d,0x00009a4a07ce1f25}, {0x0005648873cbfad2,0x000e64e5d115d4b3,0x000e40d2e3544b37,0x000823b6b1a1b049,0x0000420db940926a}}, {{0x000a61e31101b401,0x000b74d28dad2d7c,0x0008f99381581fb1,0x0006d98a29dc712e,0x000046c5f42fff53}, {0x000011451423b3eb,0x0003c0d9f657b72f,0x0000ef292dbb3276,0x0002a7c4929e7744,0x0000ee6ba08f8841}}, }, { /* digit=4 [{1,2,3,..,}]*([2^28]*G) */ {{0x000c50fdfbffcbfe,0x000a12ee6bc0d5f3,0x000d1eb16b2119f0,0x0003b21259ba1e92,0x000095afdef8cbeb}, {0x000584520b9e2c92,0x0008610feb591e96,0x000754802ab80276,0x00031ea8ecb90bdd,0x000002948477a4c6}}, {{0x000fc6d460d9c206,0x00024b68998b6f02,0x000fc9a84a798355,0x0003bd99ba516a43,0x0000f1c752d2f2ce}, {0x000717f6e91c96f3,0x000ba1ff04750021,0x0000101ff724bb9d,0x0000f57875a3b062,0x00001911b2aa36f6}}, {{0x000c9dbce96a690e,0x00020a9b23952efd,0x000ece1eda0be426,0x0003e42c87d6e797,0x00004250a5772078}, {0x000f792fd6216e65,0x00011a4a7752b22b,0x0004f0652e1c761c,0x0007d6395f3037f3,0x00000f9718cd45f8}}, {{0x0004c7f57ef9e74f,0x0007af373f4ee836,0x000f3d49fd3a3dde,0x00003bd7ef68deb6,0x000023a2d231ebcd}, {0x000eca838c637b01,0x0002f973dfd6c576,0x0000dfe2ab1c805e,0x0005a94572e7fda6,0x00009401440f369a}}, {{0x0007d74400024b40,0x0001f5b00db08719,0x0004509077de17a2,0x000354c8eb4c5624,0x000076dc0dfdda91}, {0x0004925d7e16e234,0x000e71fb7a5cd3e3,0x000628461ccda123,0x0001e761ca242827,0x000040a6ef696001}}, {{0x000e553f6d124300,0x000275d95d682353,0x000d2b82b5b6dca7,0x000d63f3a355d098,0x0000ae0d057f7ca3}, {0x0001f9e4577d877b,0x000c3279477c834c,0x000c7e5cafae2064,0x000a2108248735aa,0x0000554c8dbd94eb}}, {{0x000176969fce95fd,0x000241c5aa6dc450,0x000beb9be4d5ea44,0x0006fb48576985bc,0x0000dd0c88c86a87}, {0x0008fffa1635a744,0x00014b52e79efa78,0x0008c0387af837e9,0x000b1463f31ea88f,0x00003e02994385b3}}, {{0x000adf82eec10655,0x0006da35576881ff,0x0001f3593b826072,0x0005479f5a9118fc,0x000081b7ed8887c5}, {0x0009f9ff322cf7ed,0x000a52f29f0216a2,0x000a1c6f5503a339,0x000087e4359a783f,0x00001f2f7550b63d}}, {{0x000d2b7c76e70230,0x000cac6501adec50,0x000d15eb9ef1627f,0x0007ec71504ac4d0,0x0000e8e72360119c}, {0x000a6a690fe5719f,0x0000b2a6adf1eff9,0x0008001065e53180,0x000c3e7128f929d5,0x0000a8ed05310b1d}}, {{0x0000184375155611,0x000680c6035cb9d5,0x0009cd9ebedaf7db,0x000025f68ebbaadd,0x00009b22d47c19e6}, {0x0009ed7e238ec156,0x00087ebb00fe3165,0x000f4fc1d9495e60,0x000a7fb7a835fe31,0x0000cbc5fbf249f5}}, {{0x000ddaf091b1a54d,0x0005aa18a0a22a3e,0x0008c82e61dfde58,0x000ef6fe2926ccce,0x00006f8bf537ed18}, {0x000f182c887d4a0e,0x00001be42965f456,0x000e7c978127d1ce,0x000537d0a1d9e889,0x0000569de4dc738d}}, {{0x000fa89a0e74e6d0,0x0003d52a6a5b2e22,0x0009d6028cb9cb9c,0x000868143cf11bcb,0x0000f98ceb8beb7c}, {0x0004f0bd89ceabf3,0x000d3055f6bc7d18,0x0000611f84ca8c91,0x0009ceb37e7fcea7,0x00002ab69d8e4537}}, {{0x0006164be8ef810c,0x000c68f62e3a73d7,0x00042132ea0f220f,0x0009b931a8cfae76,0x0000120e0489c3ff}, {0x000056c882e544e9,0x000dba82d21f227a,0x0003f4d8ead76b96,0x000524458fba4ab8,0x0000af5f9fc5fd38}}, {{0x00084efca06ca980,0x000f34de85805779,0x000729e45600bd35,0x000abe8d8f71256b,0x0000c757c5918e10}, {0x000d8a877f78c2e4,0x0008eba882fe2edb,0x000ff0a632610953,0x00000ba6c1759a7a,0x0000b96a1b55892e}}, {{0x0007062382d80b8a,0x000852b7fcb37ae6,0x0000105dffe9b512,0x000554b3f092abdf,0x000049e87155c674}, {0x00073628f54f8dad,0x000eba81d77012b6,0x0001176a2e46bb7e,0x000f52d8011507b0,0x0000fc7de4c283a2}}, {{0x0000a3774b40ba51,0x000d2e1cc3a9ee5d,0x000566b1a46d5ccf,0x00059f07988c4721,0x0000c80b4f9aef60}, {0x000f16c5f230e80a,0x000da03ec1812abb,0x00006315b4b346ed,0x000fedf2b2d744df,0x000097e8aa16c20a}}, {{0x000d6e10aa7185cb,0x000017ccc3b062e6,0x00011d8ad8b90450,0x000f8e927aa95f45,0x0000358b43fc06a6}, {0x0001d5d7e36dcfc2,0x000fc29193e72912,0x00012443b6776098,0x0009b04e627380b4,0x0000fd059fca40f2}}, {{0x00006b777ce58f01,0x000345cefa37e057,0x00050cf438f95f41,0x0008ee0abf1f45d9,0x0000d3ab82dfe23f}, {0x000dec2fdf1e1687,0x0003a9ada1e3f0b0,0x000621bc115b07d9,0x00091804b5c24dae,0x00005a536309e580}}, {{0x0001a1f36d5a3e11,0x0008dc2f815e7fc9,0x000a6ab5b38987d7,0x00005ba64e516fa6,0x0000e35f790ff4a1}, {0x0000a6a16d83c088,0x0006ceefab1c6182,0x000449d91c98968f,0x0007bb24e4313214,0x0000f72073843b6f}}, {{0x000bdb5454f13c39,0x000a22272f00d7ab,0x0002e178a51c5620,0x0007ffab23452bb1,0x000095fe77e2c7ec}, {0x0005269f7a15d9c8,0x00096a8c061d84bd,0x0004524b8f8eebd0,0x000df15fadf6f11d,0x000006922729d2f3}}, {{0x0003db3cfadbe550,0x0007ea332972b6cb,0x000375df17c3205b,0x0003d308348750d8,0x0000156569ad36a1}, {0x0005c1e5a6730825,0x000935b88ef2de6e,0x000bf9f4cdfbcd4a,0x000c1aa110289f97,0x0000e8b4b218715f}}, {{0x00047831dd65d665,0x00061c4f2c50ca7b,0x000e125f3749ad4c,0x000d6b6dedd6ee5b,0x00008f3560aa418f}, {0x0004cca576eb6ef0,0x0006bf234f5421e2,0x0002931e2453d90c,0x000a5a30ba21d2d2,0x0000f40aef62be5b}}, {{0x000906e3dcb95765,0x0003952a2d0bb27c,0x00071e7a288f483b,0x0000b33851620f5e,0x000049133fb7e046}, {0x0006fedc5361d7ed,0x000097bdcdbabe80,0x000b57799cd31b0b,0x000f7bdbe9c25b69,0x00005ac7039c2b9c}}, {{0x000b6b867e927375,0x000fa63b9d79dc5c,0x0006f3e1b3db6fd1,0x0007c0d5e633292b,0x00008252bcf8f282}, {0x000208df42a98b04,0x000321910210d248,0x000c2cc0bbf1cf7e,0x000fda998a5ce085,0x00004661e9931c1c}}, {{0x0003ff64af040144,0x0000271a4dc2976c,0x000f713650222aaa,0x000a7b0407b2fb4a,0x0000de28d8759197}, {0x00046b6fabd1d7f3,0x000f4abb6a1aa945,0x0000e83a29065344,0x000c3009a559142d,0x00004e4b62383c59}}, {{0x0009e0629876866b,0x000baa1e5ef979af,0x000344a68c0b5f09,0x000b007ac8563053,0x00009d8b747143ec}, {0x000042138fad570e,0x000f593e59ae3704,0x000886949e418ec7,0x00095cfd231c4091,0x0000cff10c404233}}, {{0x0006585937313d7d,0x000c05513277642a,0x0003aea43c3c0b6e,0x000f848100f54c99,0x0000872c0c47c3fb}, {0x00097cc55eb26b25,0x0002361e834684ad,0x000dd6b60df38d56,0x000f85fa83e5f219,0x000080ec5b9b7a9b}}, {{0x0008e57fdd7ade46,0x00059b24d6140c44,0x00002d217ca3f679,0x000cabad76479b8f,0x000088094d742238}, {0x0000f8a7e3617373,0x00035946e4869acc,0x000c11e58b0c0758,0x00047a937c7d9950,0x00006d8fa5650507}}, {{0x0003e42674ed11ef,0x000404828d8b786a,0x000696d9b1c4a0b2,0x000a64d22d72fb93,0x000014d70fab6fd3}, {0x000db48af8bdb685,0x0000a04eb44f8247,0x000dd01bf9cf8243,0x0005d612508a37df,0x00003b03be491bcb}}, {{0x00052e217a1d1fb3,0x000e03733ad7df0e,0x0003c7441a511a17,0x000e3fe73bb6fe95,0x0000c210edd71197}, {0x000e1c3b3b5b574a,0x000d784c56ae9c1b,0x0002719fec3c39ba,0x000ac883f91c7e72,0x0000596cbb0e72a7}}, {{0x00087a7c47d16487,0x0007c27d1eee4af9,0x000efb643de140a8,0x000af19f4764d9f4,0x000015e713bb998e}, {0x000e86dcbb8a91af,0x00012fcbf8d52174,0x00004c90675aec42,0x000d6fee55cd1165,0x0000473a26dbefc9}}, {{0x00036638b477ef6d,0x000889bef8c0d8f8,0x000f69f8ac86759b,0x0002c5990ba889fc,0x000077c230155958}, {0x000318fe4ed774b1,0x000943b1be4baa60,0x000ee1a405a3bdc0,0x000f93f1b2f417c0,0x0000d8aff7c79fd5}}, {{0x000ab61ec541eea4,0x0001ddc9914833ea,0x000ddea233e07a02,0x00092d963c34f544,0x000044eff2fab1eb}, {0x000151dc44d86278,0x0003f0a1ebb24397,0x000d4968c888b6c7,0x000fdf950aa9dbd8,0x00009aceb5a6375e}}, {{0x0008f88f4b8f4675,0x0003e1eb007bd2ce,0x00071e4c30d657d9,0x000e4cd8527b3006,0x0000e64c785f241a}, {0x00060c0a55cbc596,0x000f64194d67dbb6,0x000a74f7e445f24d,0x0008892b9bf8cc55,0x000087103038e47a}}, {{0x000c4132cd9b183d,0x000612f382df8229,0x000787543d725563,0x0008dc0dafa6bf3a,0x000054b1d9938b00}, {0x000909776b50d022,0x000e79e83c7dbff4,0x000339f55e1b465e,0x000b542cad7a0e54,0x0000ba6a0a29e068}}, {{0x000468725b4544cb,0x000d798fc46027b3,0x00037c0fef8d6693,0x0001f562e64ba62d,0x0000f4f40675932d}, {0x000d29eb4b2b5d30,0x00096664493a478f,0x000a8ba7c916705b,0x000ac523815da842,0x00002363b3a920b8}}, {{0x0005576b1b9c4387,0x00012f0b382afb58,0x00090cf5e15b9217,0x000e25c7b242acfc,0x000019252c1e86b5}, {0x000d5ad8a3d0a645,0x000eeaf47eba0955,0x000f27b0e1492667,0x000c14fd914315df,0x00004f8a7c6076b0}}, {{0x000807ac46701c33,0x000b8d6d492ad054,0x000c5c86829eeafe,0x0003db877d68abd2,0x0000fca131606089}, {0x00046fb59b42ee1f,0x0003ac322ebe5b5b,0x000567698797e76a,0x0003c7d91f0f74fd,0x0000c77ff2c96539}}, {{0x0002670ed84701aa,0x0009919671d435d3,0x0006aa77f196a6d1,0x0009ff14771936f5,0x000045e8ec81d56d}, {0x0008ff7e385075a2,0x00053a57ae34859f,0x000496f4ac1269ed,0x000ab1e97fce260b,0x0000bc829794fbcc}}, {{0x000727a64762c5b0,0x00023d5228f62cfc,0x000f9e44f2954c41,0x0006a900f293a819,0x00009324b17896cd}, {0x00027fe6fe89cd5b,0x000c3c1764b979f4,0x000d84375a0a4d5f,0x0007be72e67bd8fe,0x00007978b94bf0c7}}, {{0x000014848f08e5f8,0x0000dc08a46d3f0d,0x000f2f51cd2de0cd,0x000f26442abb9c85,0x0000b1f0caf156bd}, {0x0001a678227aedd6,0x000363358fbe9f6c,0x000e8c01632b677f,0x00025feaa88fbae1,0x0000dd95784a0bf0}}, {{0x00036ab62c9baf2f,0x000e3a0427cc9a23,0x000a9a0ba77b1f0f,0x000b2ba599b2ab1c,0x00006167aaef6883}, {0x0000834b4a11c2b3,0x0007e5fdfd466b81,0x000b1bdee8b8d4df,0x0001c6c0b819a31b,0x00006b8ce7712b3e}}, {{0x000472ce5ee2aa98,0x000a7c8a447852c7,0x000e5e562934541d,0x000111e5956b46a2,0x0000c2def91e1de2}, {0x0004c70da2035d12,0x0009ecf24750f0ed,0x000774bd31fbde41,0x000bef51f1644a0a,0x000075f1a69ccb8d}}, {{0x000a76901a375370,0x000534a3899464c4,0x000e1bd64649cb25,0x0008de028a8fda1f,0x0000afcf366ebe08}, {0x0003cc2fe33a0853,0x000c655169d3adba,0x0008bacebd18e2f2,0x0001722b708df59d,0x0000673842d3ffb5}}, {{0x00084f5b5b4155b8,0x0003bee12769b41d,0x000d7c141a89a9b9,0x000f02731f3e90d4,0x0000f5807b7dec20}, {0x000e4d79f5f291c3,0x0007e1820075ebee,0x000d095ee31719b1,0x000e77b13e98787c,0x00009bacf15e8239}}, {{0x00021e1ade0c9f13,0x0006baad0ce722d7,0x000d6be87abd4fcc,0x000228a81f7554c5,0x0000e992ec32bf51}, {0x000dfe81a7d3c300,0x00060efd94bfa623,0x0007abb915ac1f99,0x0001008b04e471a8,0x00006a6dfb158b1c}}, {{0x000895918d9c587c,0x000b90d8c07b4267,0x000ab468e989eec5,0x00096f5f2fd3207a,0x00000c4fd8f7ddf2}, {0x0008b1cd86dd7ac0,0x000a8a8ab83f3bab,0x0005768923fb00d7,0x0001e0496024dfd8,0x000093c337f8280a}}, {{0x000f2f33fb1ed546,0x000f5524877cacf3,0x0009dec562c094ff,0x0002af42d6955bb6,0x000051aac6f16c54}, {0x000f747f4566c18d,0x0000f500d0f779ed,0x0009bf4c72dfb961,0x000237be0f508927,0x00009d1af0421cb4}}, {{0x000a30ddfb3c9567,0x00044273b206d755,0x000b8261642fa0c9,0x000999c462c3d5ec,0x0000e5cfff9087cb}, {0x0007f4092bba64cd,0x0003c030e85f29c6,0x0000dcbcd00ede6d,0x0001f5c5ab9995bb,0x0000d909fe94ac39}}, {{0x0004393c8401d21e,0x0008419e515f55e0,0x000b70a2c970650a,0x000812aa1988dfb2,0x00004579ea7e0f77}, {0x00001ae0b356ff64,0x000a67b2f4f8d464,0x0004e4808c24fb2c,0x0003cc7049b70ecf,0x0000d988de6931b1}}, {{0x0005205bc1daf6aa,0x000b46ea4ce6aedd,0x0001b36b71d5ade6,0x000c684feda79817,0x0000c1b97fd8fcc2}, {0x00015296e4680f82,0x00039c979c619a51,0x00019b0dc58bdb9c,0x000edbf5165245ca,0x0000dda5f64c3464}}, {{0x0002da59de36c6d3,0x000dc41490e573d0,0x000197752e9c3c3d,0x000caf7729881db7,0x00005781ea0add88}, {0x000709293651cc16,0x000b2ea5e1c2adf9,0x000040381b05df36,0x000cd96512965ec0,0x0000cf761e9b4f6f}}, {{0x00012f98f1b3e1b2,0x00055f5544270463,0x000c9e4a1d2b7326,0x00007925876fdd82,0x000074ea097a9061}, {0x0006e346721dc27b,0x000037acb54bd914,0x00011e8654a4af5d,0x000c7efafad16cfe,0x0000f0e1c71ca6c9}}, {{0x00056bad8c8fb6bb,0x000d537ea4bef324,0x000e9fd62945dd49,0x000f97b5d567fef7,0x000086c5b4120ca3}, {0x0002cbc8de7435c4,0x000ef4e32422c90f,0x000915725631070d,0x00056753035060bb,0x0000ac9120611153}}, {{0x0001ce2ea4b332e4,0x0008a88d39b03943,0x000be58c21e92546,0x000b8614d72a258c,0x0000d6dccab15931}, {0x0000f4d58db96687,0x0009b295553ee450,0x0000bd38d9439d07,0x000760d9baad6913,0x00000af15cbf9b45}}, {{0x000e116715a75218,0x000ee37a35141d7c,0x000d96ee6c976ad7,0x00008be27249f510,0x0000dd9663c48776}, {0x000806b3a6abaec9,0x000974d53433737a,0x00034026f2f4f6f0,0x0003631542622247,0x000033f84d61ede9}}, {{0x0005789811a3ae5f,0x000145466230de30,0x00035f272f8c7bcd,0x0008464d6e1bcc51,0x0000c0b21060c721}, {0x00056b9c81e33e1a,0x000ecf8a7f58e633,0x000b78291f065f2b,0x000e115598fa93ae,0x000008d4d5dc0246}}, {{0x00023976b401d760,0x0006a4914be6b70b,0x000cd32b79cb8bde,0x0001ffab9c10c28c,0x000071ebaf4d93ce}, {0x00025fddbaeca2e7,0x0008b2280bebff24,0x000a3891662f455e,0x000cee7ab7537d72,0x00000da3f309f420}}, {{0x000d2fa921a168a7,0x0002e4b7b670cfd8,0x0001d3d2b35868fd,0x000fd4925f10a54f,0x0000d3ce9bd12974}, {0x000176530f52e7e9,0x0005ca6a8cc32d2c,0x00019482b90bd81b,0x000cd9a2087e9855,0x0000804eb315a666}}, {{0x0002197860bc9037,0x000d8b8123349561,0x0003876dc1f987c0,0x000583fb6e6ef179,0x00008cb21fa0cf30}, {0x000fc89c021518a8,0x0001fe3269ddefc5,0x000e6ecf600526c8,0x00082dc869beeb1a,0x0000ceed4cbeee27}}, {{0x0000659ae15c0cff,0x000524432040fd35,0x000c95fbcb5411e2,0x00010634f1a87377,0x00003ae2a14e5951}, {0x000c01abc86960db,0x0007837753dd90d3,0x000b3a5cbd54cd6d,0x00025ee3849235af,0x00005aead12b08c4}}, {{0x000b7d73502d7d8e,0x000d7454261868b3,0x000e46fbdbc13c21,0x000713844ea5cc30,0x000049be3239b611}, {0x0002b0432aea713a,0x000625e8db9e6204,0x000d1b612358a422,0x000bb2de468b3935,0x0000d73f40958c1c}}, {{0x000ef0b57b47fd09,0x0005a747602a55e1,0x000ef3a6ec69c95a,0x000a9812736cac28,0x000000509d742fc3}, {0x000649cba516376b,0x000241310dde1462,0x000486dad6e304cf,0x00067a74ba5dd344,0x000076e637f5c43c}}, {{0x00011c2158de7341,0x0007322124e7a4f5,0x00002187b24db413,0x0007c89cf37f3770,0x00005c2bbc1a94be}, {0x000c3a8a2a94c5d1,0x000019673c8091ee,0x000a670f1d766afb,0x000dcaf7cc3d5518,0x000067e6f9927685}}, }, { /* digit=5 [{1,2,3,..,}]*([2^35]*G) */ {{0x00005700bcae739d,0x00002be037d24753,0x00015b109f3a7bb3,0x000e43f9da256a61,0x000093ad7b5eea05}, {0x0009fd0396309d30,0x00051affa8b57a31,0x0009e17000aa55be,0x000584057dd782f4,0x00008fc1c3299638}}, {{0x000d93c48b3b2619,0x00080481131fe4d5,0x0004069419aa8668,0x0002802c3872251d,0x0000e0421b9f2df1}, {0x000bdc567515ba99,0x000aa60a7a56df82,0x000c254922dcad79,0x0003014dbea6f756,0x00003529c91e3e54}}, {{0x000f4cead9303d8e,0x0007da2afde793dd,0x0006deeafd0c52d0,0x0002cee4e07a6bb6,0x0000805a8d0d1862}, {0x000bb34d90f85393,0x00081fd23389603e,0x000a4addd74321cb,0x000ce7a3c9e82e99,0x0000dd06c08d7e68}}, {{0x0004e4b39f1a7fc3,0x000685bd324dc746,0x00077329f942afb5,0x0004c07e4ddb8995,0x0000a7edd72789c7}, {0x0005b61b34ef6322,0x0000a0c0708326c5,0x000423a1ac63d4b6,0x000e55cca0e0f401,0x00009daa63d66c01}}, {{0x000d5fa96476c552,0x0001a9871f6885b5,0x0004ffaab3c7c9d1,0x000d4603f8de64d8,0x00007b2e031462b5}, {0x0008c9e92f0c5787,0x000de242f7202665,0x0003c82030726817,0x0006a6a3eaa87186,0x00003c95078f22e7}}, {{0x00023916557f453e,0x0004ae26a44583ee,0x000fb5b0a3af5dde,0x0008c41782c4831c,0x0000ea56bb04a5ee}, {0x0000d169d9ff58e9,0x0007dac5db5ca14c,0x00004bf3faad365c,0x000cefa7842801b9,0x0000c473429c32cd}}, {{0x000d3a6e10d62089,0x0002e7b29cd9afa4,0x000148cd51c8b2ae,0x000a75007bff9823,0x000091ea2803d58f}, {0x000a6e1d7cd54ba9,0x00012006683ca3d4,0x0006b0cc5578ac68,0x0005cbf6720ff656,0x0000c9b8e7ae81da}}, {{0x0009db6d2b5b0c57,0x0000d45183dbc273,0x000c532d1cd3ebe1,0x000638b8aa1df7af,0x0000d1b32952af42}, {0x0005152b969da4ab,0x000ffc53c8ae6a5a,0x000f8a7ed96e444b,0x00021fa7d3dcb0a7,0x00009f0fef615ad7}}, {{0x000b2a69f40c9752,0x000d9c51b7ec3baa,0x0003ed0013ffe154,0x000b0917e419d1a5,0x000087bc5ca8dc9f}, {0x0006dfe0e70f6230,0x000bdcab123ee058,0x0001e5900c76841c,0x0001e44fe0b74ae1,0x00003adc613ad53b}}, {{0x00063c9f8355c127,0x0001540eb5653460,0x000b854039ff3d78,0x0008ae7c2d9a955b,0x00009ca4d64c814d}, {0x0001356a07c69e07,0x000e21ebd8080839,0x000a3b9495398a52,0x000846dcfe86a411,0x0000787df0a13b19}}, {{0x00027c45c73a8764,0x0001414547d3af8f,0x000fb60a1bb40672,0x0004ae7a70f5fd99,0x000082531e392b1b}, {0x000da4c7c8966027,0x0005e83a98dbec18,0x000a67cc1dd3e148,0x000d57deb57d902c,0x0000f11b0aa60752}}, {{0x0007d863d57f3414,0x000fe1509dc623ed,0x0008df4273550cea,0x00065f9b96e5fcb4,0x00009ae9885ba4ab}, {0x000ac350b383e5bd,0x000a0f46498bc168,0x000a58596f3b798e,0x000fe6aeb0539155,0x000054e1d4ea8874}}, {{0x0003b275d29dc04d,0x0007d76747fcb13b,0x000306ea3b2fe9b6,0x000e902e3d618276,0x0000789aaa24ff3b}, {0x000d025585e1c78e,0x000596e4aecfcc94,0x0004f5b5dff9c8eb,0x000695d3ac036938,0x0000d2e6787c6ac0}}, {{0x000ccd3ce60d460f,0x00007ea73fe2e166,0x000b13997331a00f,0x000bf84382342cbf,0x00007e70f6af3225}, {0x000335bae3648d46,0x0005c252c9be9d30,0x000b173ced6a5a93,0x00062cd16c887a31,0x00002a4f9fbbbf9f}}, {{0x0005a47a979741b1,0x0009565bbf2dd4e9,0x000af96bbcbc82aa,0x00026bf44f9cd822,0x00004b2b149910a4}, {0x00050f9cdf45d19a,0x0001eda90005e40d,0x0000abd40b1a8e66,0x000244881e5b8a56,0x00000e73a53fe7c9}}, {{0x0001dd32de445aa6,0x0001fc91cf2f9f3c,0x000cf76c57384160,0x0006f62abd1f13b2,0x000052e2ed7e3fc4}, {0x000d88787f35a985,0x000e2148e3be1e7a,0x0007b25528a99e57,0x00035b65281c2f4e,0x0000c1eb2107c6cd}}, {{0x00035d5a8c2927bb,0x0008de6d2b0185a1,0x00024afffb21509f,0x00056b3b64117f50,0x000014162b8f15d3}, {0x00024513d05bd8b3,0x000434f9385172af,0x0001a1f98c4d653f,0x0005e9ef0660e5cd,0x0000273cbf1678a5}}, {{0x0005911351a59103,0x000e04b05be68d91,0x0004a7bede129f38,0x000a1a51eec3037b,0x00009215fc231a08}, {0x000dd81523b72a23,0x000894715cc1a87c,0x00091f600ab80cef,0x0005a0ab3eca37dc,0x0000b2bc149ce4ad}}, {{0x00068d2c36fd9f9f,0x0002973c5be71204,0x000e5a97f4bb36f9,0x000f1907757b63c9,0x0000fcc1fbc2fc33}, {0x000eb5cac213cead,0x0001c14e861adc28,0x000f903943fc7081,0x000da639df6e310f,0x000040d070b3e432}}, {{0x000d7619d49860f4,0x000ea16ce8ca2f98,0x000f7a39c2b109d7,0x00055c8ae1632632,0x00003a28a5876314}, {0x000509cc3ed28df0,0x000cc59ccd51ee9a,0x000cdc1784ba5cb3,0x0005898cfd78caf0,0x00008e1987ffc9c4}}, {{0x0006780551ed5362,0x0000162b85d37aab,0x00052c0a5dccf49a,0x0000008978e8fe28,0x00002aef7a358742}, {0x0003eaf9eb9304c7,0x0002bc6376029477,0x000c2b67f2b6f818,0x00045ae346f21474,0x0000533e9491e7ee}}, {{0x000821aa8c6a2ac8,0x000818984232ecee,0x00008bcff77eddc2,0x000f1868ed1e27bd,0x000057062274e3c7}, {0x000f1f1e845f219e,0x0006638746018c4b,0x00079c20a4d39735,0x0003878465feda34,0x0000ad6855572cb6}}, {{0x0009354b24d7ada1,0x0001567cc35e0245,0x000f79c525b386c1,0x00013a1c4fe295fd,0x0000734ae5333989}, {0x00049712b0342f42,0x000a478fead6dbc2,0x00041f2ad87713c3,0x00037135a752173d,0x0000b5a42c879097}}, {{0x00066a43e3dbd58e,0x000729043504c8bd,0x0001dfe5e88ce125,0x000b8e4a214027f1,0x0000e0bfff41c734}, {0x000497d8ef9bff74,0x000dfbd8ec3dde6c,0x0009dae39fbaeced,0x000c615eeff4aecd,0x00000b575a8087f6}}, {{0x0006858fe09d95af,0x000e54554313a7ae,0x0003adbfb75fad76,0x0006af4c0e89f84b,0x0000cbc199841374}, {0x000d3daf04bee219,0x0002f16c60fc3b73,0x0000bf406b089be7,0x0004df5aec57f12e,0x0000f4b714839375}}, {{0x0001a7b34a992617,0x000262b67fd16035,0x000f4cded03bd337,0x000a495f4d446c82,0x0000de7f0ecd39ef}, {0x0004309127b7e470,0x000333eca6abb6e3,0x000e251b37d1836e,0x000e19b24cc67dda,0x00006986f3fce1fe}}, {{0x00006b3c165ba83e,0x00040763b7168cd5,0x0005b2089849d3ee,0x000158864b408e50,0x0000d1e7c3c11ba3}, {0x000951b1022b0811,0x000a6ba9409ee8d0,0x00082031e38d13ee,0x000986a7af0f043e,0x0000cf5bbfcacd65}}, {{0x0006ed33eb976593,0x000cb73bb5996a5d,0x000a8d40797d331a,0x0008195eab513d66,0x0000745011a8ad57}, {0x0009172aa1b56b55,0x000681e0477e446e,0x0004dd55b38c0636,0x00046c34beadb245,0x0000f622ee53fa27}}, {{0x0007b0a3ab20cf47,0x0005b6ecbe5bf999,0x0009b3cdaea41415,0x000dddb1a4af7693,0x0000c87b4d02be99}, {0x00044162383848a6,0x0009bae35ed444fc,0x000b61b91b37a6bb,0x000c991cfe2a21c2,0x000005e9cfbed62a}}, {{0x000a1a9489a1a5ec,0x000ce2cc85fbf558,0x000f2223a8aee3ca,0x000478fc82ab4b29,0x0000ce60dd26d1b6}, {0x000dc4d8f75b7e43,0x000c8e7ae5cb1be6,0x0009bc9a205da2e2,0x0000b9d8f07fbb11,0x000007c9c2797b7d}}, {{0x000ba6fe16b74a37,0x000c9ef80b1e2a3a,0x0009b6ba80ac3749,0x000a58cf3522eba3,0x00004f2c5f7bc7fd}, {0x000ae382cb1abc5b,0x0005df37a1e6cd6d,0x0004f4dd227488b9,0x000587f8906c8701,0x0000c94e7603d61a}}, {{0x000f31b12c8e946f,0x00041998676a0cd3,0x00012cccc0790516,0x000d05413f948da8,0x0000915d9bc125cc}, {0x000631c24a7ac56f,0x000cc7dbbc6a8f6e,0x000a263d88d9b845,0x000ac140e423d536,0x0000abcdfb4c1ede}}, {{0x00036dfe301d6bcf,0x000976515927a0af,0x000260fcbb9fec72,0x000d7a1d042bcb4e,0x00003986716d1e65}, {0x0007a8b84e008f31,0x0001a9e0bbf32708,0x0003023c184225e5,0x000006bbd97e7f72,0x00007a8476f8c3f8}}, {{0x000200faf183b044,0x00091921123920f6,0x000df3ccbb457e6d,0x0001c38fa6eba464,0x0000347d78c4d002}, {0x000b2f467c70d83f,0x000a9b0ee2ba361f,0x000def1984834b5b,0x0006757a81659a0a,0x00005cf0e1308d83}}, {{0x00041ecde4f12ba0,0x00055e2ab6f60ccc,0x000400171094c76e,0x0001f83d982ca07e,0x0000bfd8343191ee}, {0x000f9f86ae6ad522,0x000bd01e24ac8cdd,0x000622bbda9e9819,0x000bfccf5e80a139,0x0000ea19704218e6}}, {{0x000fb670adeb0531,0x000a2e1cb11d95f2,0x0002237733ba53d6,0x0002af7a4f5b85d2,0x0000d11b8b4df863}, {0x000f21077157d779,0x00029dae46ae076e,0x000ef1a942676f1f,0x000698d2955c21b4,0x0000366784d1b5f8}}, {{0x000d37ab64d1b8a3,0x00048a552398fb88,0x0001d701426c97ce,0x00054721bdb66fec,0x0000bdc35f96e76d}, {0x000480bc0f59b636,0x000445d5741bd54e,0x00007a408f26f505,0x0003f9d9158c7ff6,0x0000ff89ff1faf90}}, {{0x000bc2333e034b3a,0x00064dea255dc2e1,0x000153b1d74a371a,0x0009201c2dd539c2,0x00008464ef965378}, {0x0003be3e2d7ffc4f,0x000a0233bf14077a,0x0002bb433fcdcb11,0x000fb8623c1e9373,0x0000767ed200d1a8}}, {{0x00082d0bd4f64295,0x0009f5eb0d7a40a1,0x000e40bed0984111,0x0000c3c234be2868,0x0000a55bb693492a}, {0x00003589e0e1c59a,0x000b79f78b50c3dd,0x0008e289bb712956,0x0000c85c99d84cfa,0x0000a5af77c7b795}}, {{0x0006c6e73e758063,0x000aa4c0ca07be80,0x000a771d1a3c2b89,0x000f8e30bbd4d1f2,0x0000707591fefd22}, {0x000baf90e9d177b6,0x0002f80643449531,0x000fa11454675837,0x0002074957d79a89,0x000023d4bf71171b}}, {{0x00012ff13201e572,0x0001c2d35ca8a962,0x0009211dfb91e1bb,0x000d6b83cbe76c57,0x00005b47bc9b1b75}, {0x000cf3690ccde132,0x000203bdc7c14ed2,0x0009be86fc27ebba,0x0004eba9b9fc557d,0x000081e537c1cfda}}, {{0x000edfee74727d78,0x000980a22c07efda,0x000b10e358fad228,0x0005c368538ea7ce,0x0000b7ca5d8c2865}, {0x0006c1397b278758,0x000841d382b260a7,0x00040b29c25b9e45,0x00049b72f524c365,0x00001fffd1819be9}}, {{0x000e1fe027315046,0x000e4a8e9ae005a4,0x000e29dad879e0cf,0x000713338832c69a,0x00003efed8d22203}, {0x000e9be0c541ee45,0x00043c0e163d6976,0x0006689793657bcd,0x0008f5b80673d362,0x0000c7348859135d}}, {{0x00072bc3bd04c059,0x0008da4e3ff7f4d9,0x00070f0f1e03cebe,0x0004a82cb1df491d,0x0000cff4a142a9a8}, {0x0007a0aa0adfeeed,0x000d8ea5a8781ca7,0x000f8a9d70def5c5,0x0005f0e216119383,0x000056865c8536c9}}, {{0x000c2b7335282880,0x000df2155af305ab,0x0003cc18f696a952,0x0003e94feda61624,0x0000074ce58fe838}, {0x000d1423175154af,0x000fe1ae0cacb704,0x0006b7521866fd89,0x000dc49d637a4c2f,0x00008dccfc32bf4d}}, {{0x00058b746d6febb7,0x00056fdc8cde8233,0x000c5724a2fcaf62,0x0002c41d3479ab73,0x0000cd65f0ee0ad5}, {0x0004b4965d7be852,0x0006736dfdce5b87,0x00022e44ee30b9ff,0x000510f3c1fd2443,0x0000b17b0a94a0b8}}, {{0x000ed9da5acaa517,0x000e2d9bc48b2b20,0x0009589a56d9ec6e,0x0000cd50699c9cf1,0x0000c0682f67c25b}, {0x000ad83acc2d9df4,0x000b491d3a194ec3,0x000f43e0aa5860a7,0x0008825d7c9356bf,0x0000ffd010d5ac2b}}, {{0x000ad7d4257077af,0x0007d06b6e41f434,0x00081d274d0d97bc,0x000d46b97f058b8a,0x00008141f09a57ee}, {0x00059c2c95a92ba2,0x0004dbd7225bde57,0x0005ec9647f39a2e,0x000a46b029f14b8e,0x0000e8a3e62f0c3d}}, {{0x000af97ab489033e,0x0005ffc2cbd90b39,0x000bc39c20e78840,0x000b48cd3c1d2d1a,0x000065f064cee3fc}, {0x000a3b79e03ee91a,0x000d739b8fffef5d,0x0008d7784f339ddf,0x000a02d5cc657cb5,0x00001fb78c5705a2}}, {{0x000fe19eecc5e624,0x000306f9bcd832a1,0x000b535333e9171a,0x0000a14c3dd19f34,0x0000bfd509e3ec8f}, {0x000d131ff598e707,0x000efce0b7cd59b2,0x00008b2e08b38876,0x00028c0e783e18dd,0x0000a91d85b2dfd9}}, {{0x0004382f883cfa65,0x00007fc08c3e7142,0x00031d2cf6a1e10f,0x000b73831dee9409,0x0000a725ec88ef3c}, {0x000e45138849f25c,0x000af48749f6cddb,0x000d14475f1cac00,0x0002cabd31e17b50,0x0000d48626e3da74}}, {{0x000d0de0ff499960,0x0003fbfcf664ef0c,0x000452faffdd7772,0x0005d14882e7b0ee,0x0000b786850a0512}, {0x000390625f2d5fad,0x00097f518ec1a4a5,0x0002f3d039da3312,0x0001a9edc17472da,0x000096d8837d422c}}, {{0x00098d1cd3290a63,0x0009e70dc26c34ec,0x000fb8080a9ca335,0x000e643ad8d71805,0x00009473d89368fb}, {0x0003a8f3f95413da,0x0006d4ba18760cd3,0x00015ad17f92f4f3,0x000ce2649cf662d6,0x00004e46841f615b}}, {{0x000d33f7c64c592a,0x000b6794f7501394,0x000df640f443e759,0x0001115b48de8e41,0x0000a085e12aedd8}, {0x0008c0b7e2b229ef,0x000b6d02a9baf2c0,0x00022cc20ae9044c,0x000e8d6e6ca27b62,0x00005703e8b98911}}, {{0x0002cefc1f02f736,0x000540270033b3e8,0x0003ceb47e84f986,0x000e14fc35ec1c12,0x0000f46085bdda1b}, {0x000cbc25542ce047,0x0005a07add73f5e2,0x000320971ec0822e,0x00035a98911e32d6,0x0000881d02f4e758}}, {{0x000387b347fbdee2,0x0006458ebef829c1,0x000f7bdfa33f4d8a,0x0002883778b30bae,0x0000a57a86aa56f3}, {0x0001ee174ceb06c4,0x000b005d309fccfd,0x0004d56aaf05a383,0x0007b122e2a74e83,0x00003ae917835919}}, {{0x000b2e078e41d080,0x000d82af788420d2,0x00062fb2b0bd6d30,0x0000d29e31188cbe,0x0000fb42bc94f44b}, {0x0003accbe6f8e771,0x0007513275c93443,0x000099c782740df3,0x000b459fad4b877a,0x000033181c9bb1c4}}, {{0x000dde73fb0eda0e,0x0008f6af3e12a3b0,0x00070b40f538cf4b,0x000dfc9a8cad561c,0x00005c1801d14801}, {0x0002dc79588dc298,0x0009f476f2307348,0x00070463a39ee33f,0x00014bb90225bd9b,0x000010b40545d203}}, {{0x00036dc7a7be1464,0x00010d064c152673,0x00019582bc150f70,0x000cb20deb2fe94d,0x00003c415ba4f212}, {0x000985f73eec9d69,0x000f765a6fccae60,0x00097f2f3c826fb7,0x00047dd07d59c9ae,0x0000707066e8983c}}, {{0x00041a35ed2eefac,0x0003a0fbcccb63d2,0x000fd5d39ee7f02c,0x000d05a5130a3242,0x0000bbb31c95b0bc}, {0x000ca4ba534b4c07,0x000fbe96ffe723e0,0x000b5137627b8873,0x00053eb426e6c7a7,0x0000febe40fcfcba}}, {{0x000346e0b45a707b,0x0009552613f225f5,0x000803741bd4eedf,0x000933cc8d49c2e1,0x0000a0a7a1802a2d}, {0x00015993942ef2d8,0x000a6714ab7c1ec9,0x00037e0ce22b32c3,0x000ffe9aeaab9bc3,0x000007042cafe458}}, {{0x000b755d669d39d8,0x000c3024b484f11d,0x00034f49b01e2ce1,0x0008ed0468857e28,0x0000254a9385fdf0}, {0x00055e07a3d440f8,0x00042678ee665499,0x000d14e839ec6cdb,0x00015ef57c3c712e,0x0000ed2a33990852}}, {{0x000957be96b408de,0x0001ebc7fea66f42,0x000ee42926b6ac46,0x0000b4e4cb455b9f,0x00007fb272c87861}, {0x0005ea64c175d75c,0x000e57ab709e7669,0x000f97d844601eea,0x000524f6c42043f9,0x0000257150f4b193}}, {{0x00019b55359a6996,0x00066ea8746126f1,0x0003984c698d3b0b,0x000148d30ea757f0,0x0000a5a62e68d1b0}, {0x000b1ceb549a8926,0x000f6127020a2f62,0x000cb3fd49371a21,0x000f1e9c3dfc9693,0x0000f10737a457e3}}, }, { /* digit=6 [{1,2,3,..,}]*([2^42]*G) */ {{0x0008da4ebfceed2f,0x000160ab87632830,0x000a7a776b62d8f6,0x0004161d81461a65,0x0000d2503d370ab1}, {0x000a3a28b12e059b,0x0006dba7a43ef9af,0x000eb449b66afd29,0x000b4f497099cf91,0x0000b740d849144f}}, {{0x000d1cb14db150ae,0x000c2825db119cee,0x000e5fa06f3d8cd3,0x0001519236fc45ff,0x000017232f7c8181}, {0x0008b9e65214d82e,0x000a8d9bebd6dcfe,0x000c1e6f59806e97,0x000d0a1cae163880,0x0000454a197aa771}}, {{0x000fb2e99ff222fe,0x0002f6cd6bc0c742,0x00011048d43a1261,0x0002bc6c0346ba52,0x00000874002068cc}, {0x000d17dfae243b95,0x000e8b373c9aa0e8,0x000e84c66747a444,0x0002560f7e0b8280,0x0000dcfd670f7595}}, {{0x0002524b949e4535,0x00090f56a6cde629,0x00006c5056ca68db,0x00087837cf37f5e8,0x0000287aeba17f2c}, {0x000194d41a0f7a82,0x000aff261f9d588b,0x0006ee54936659f4,0x0003de1c86018de4,0x00005bb7bee891ac}}, {{0x000dd4596bac0c33,0x000a79383e647f24,0x00062bfb0f5a73be,0x00082923eee62853,0x00009c04543340c6}, {0x0004c782a0e9f2c3,0x000e03645715f5f5,0x000fa691a3c1b9a6,0x000e7ab9adcc6de5,0x0000db83ee04ac86}}, {{0x000d23467ed57309,0x000db8f9d25bed94,0x000dbe922092fe90,0x000764e90499c35e,0x0000cd06d43dbfbb}, {0x0000064077438554,0x0001c32ae4be0845,0x00061d2fcaebf091,0x000c4346a089d960,0x000055f71e1c5a73}}, {{0x0002f96218c9d5a6,0x0001641dd16123d0,0x0008ab2e1526c4ed,0x0003e09ffc5e3edf,0x0000df1e41035c68}, {0x00077bcd67728b89,0x00047ee4e6273040,0x000cb877fdbfcf62,0x000eff21cb5a44a2,0x00003511953a16ce}}, {{0x000409ffca73851f,0x000c3de29624b94e,0x0002a47c5c60b925,0x000e16665847cd08,0x00008e7f8ebd9097}, {0x000eeb9e98545750,0x0000ce814b1f1ed6,0x000b01ac8d35a5c3,0x00075837d8e25100,0x0000c3c5bd7d279b}}, {{0x00076e1d283c6ce1,0x000f7174959c50ba,0x000dc4eaecd286d4,0x000634535982fee9,0x00009158cb09e7d4}, {0x00017b5f6cd33044,0x0002969dcb333eca,0x0005d0e40dd7519e,0x0006b515ebd579a2,0x000024e41aff93ab}}, {{0x000040ff1375951b,0x000a1e839dda7393,0x0006bb352da54b3b,0x0002ae6c9597e201,0x0000d9dbd47572b3}, {0x00056e9021dda66f,0x000e6fe0123fc320,0x0007cca3903d3977,0x000ef0e68cdaccaf,0x0000bb4084bf66da}}, {{0x000d2f201031c945,0x000b772e503d6e75,0x00042cdc17bd8ed3,0x0007777ce2a48632,0x00005c328a9c3027}, {0x00070c96d90b6fdf,0x0006762cff8288de,0x00001a6ce10f17ed,0x0004b60b2595dea4,0x0000d81fe47c8c90}}, {{0x000c39102e4fe37e,0x0007b23e92ab7da2,0x000353e2a4aa27de,0x000cc7a3fc098e3d,0x00002536baff989e}, {0x000be55df78b163c,0x000cb15a4f900b15,0x000738e13e4be770,0x000cf45a8c0b1e35,0x0000d1c8b85e4c20}}, {{0x000d8a6f91768025,0x000780bb92a70307,0x000ec75e9f0a4627,0x00018b3f31d5783a,0x0000ef5c08e724f6}, {0x00056b23247f3db8,0x00038ade392d9748,0x000a43483fdba1d5,0x000a5c1dc4f1a93d,0x0000b35fcbd53c35}}, {{0x0006e5b5f09bd9de,0x0000bc9fb162290f,0x000034f2dbce94c6,0x000c8626fd489944,0x0000d0a4061eae30}, {0x000b78b3bd8a273d,0x0009de5ae80b923c,0x000eef67b29524b2,0x00014e750cd4e68d,0x000073f7f21962fc}}, {{0x000877c7f92f06b5,0x000b95cee57a30e3,0x000ffcb286123ae9,0x00022d50fbf6547e,0x00004800675d1bc9}, {0x0009b9e818f59d1a,0x00077d2030cdc4a4,0x0003a9ed390ee53a,0x0001df3669085b25,0x0000f51fe98bf18b}}, {{0x000ccbecccc94f0b,0x0008c99893a55b13,0x00041516d980406a,0x00012ad64445dc39,0x000003dcb08f3616}, {0x000905907009deb2,0x000ded15742863c2,0x0003a9de2612f089,0x0003f2f1e316164a,0x000095cdb1f35323}}, {{0x00048f32683a1106,0x0003a7a5b3460224,0x000343e47d7bd6af,0x000126c091046994,0x00005de2a5b586f7}, {0x000254188f58af50,0x00060974a069758d,0x00091651f61f3bac,0x000a319e608f0298,0x000076b7f2c0358b}}, {{0x00000d3f381e3ef3,0x000ceeb6c1dc33a4,0x0002adde75fa3959,0x0009beae4a15a271,0x0000d91f39a52916}, {0x0006e68167f8436b,0x000613d0010f1b08,0x0003bdc583de98b5,0x0008ced07b396a51,0x0000f5f1ccd47883}}, {{0x00053474745b4111,0x0008d69ab64986d6,0x00028504062204bd,0x0000eca3a2c7a367,0x0000a183bd071463}, {0x000618d9a29310fd,0x000c586fd5dfd7f9,0x00026b628f55ea0d,0x000e9141be7be638,0x00009ab70426722c}}, {{0x000f4c6b7f0b2b2e,0x000b35498ad70152,0x00093c54616a18ed,0x000e4887a4d5a30c,0x0000c8ce85111073}, {0x000b61623a4c2109,0x0007aaf6df31d435,0x000e6d28f6f0b661,0x00010c63d8f4fd58,0x0000a716f19ad118}}, {{0x0009cc90fff48c76,0x0001a62b3ac032a0,0x000b5de11f98ce03,0x00066f2164aead02,0x0000da752ba1afdb}, {0x000d7ff20909c958,0x00089515a1f95adc,0x000675794b9fa634,0x000e20f2564f7acb,0x0000bcf3634218fa}}, {{0x000e4e170e87d63e,0x00033b1ac864b298,0x000d6cac3ba652e6,0x0003f216dfe43c73,0x00000994b53a9850}, {0x000ef04ead3ef321,0x000f6d077d47a1c2,0x00091df581572494,0x0004bc458f8e24b3,0x0000c2de27be5104}}, {{0x0004d336eb2b06dc,0x000d438af59f9816,0x00086b544e2a7565,0x0008feca007deaa8,0x000038b1c05044a7}, {0x000eacd2e1baa833,0x000ab3d6f9a39bf7,0x0005f9a26b4a4cd8,0x0007fe97e08d97c1,0x0000e07374b44b2d}}, {{0x0004dd2e81908fd2,0x00053362700b61c4,0x00047b4115ede230,0x000e824902002b8e,0x0000fbcc6260def8}, {0x0003325697f653d2,0x0008966e57020f8d,0x0003416143080196,0x0004c4d2fd9b6e91,0x00007ade93e02f1e}}, {{0x000ecd682caa18e1,0x000f70d2a0a391d9,0x0002000a80040e56,0x000857d371f72e8b,0x000053775b161201}, {0x000f90ea5eb901bc,0x0009364d5c28a36b,0x00005a3daaeff7bb,0x000133f544a030cc,0x0000c4cbbce12e0b}}, {{0x000f8c9fcc7163d1,0x000572b83e473108,0x000bba1ec860c1e4,0x0001e09ceb4984ee,0x00008bbae4d3fd8e}, {0x0000e95aa9b6fff8,0x00013bf54498bb71,0x00098c0dc39f81a0,0x000f4d5f47a7767f,0x000053d12f97e872}}, {{0x0000a32458403bc2,0x00082b711c5a4e92,0x000be5918eedb420,0x0007560f86f6b115,0x00009eef65546fcf}, {0x00081bcf351ff9e7,0x00039fdb3c33d733,0x0000221a9d2cfe38,0x0009978c093d8420,0x00008091d026a7bf}}, {{0x00007fce2951dfdb,0x0009b16e29e1fefc,0x000e24c61a1bc2dc,0x00064ec20795b0f7,0x00006867bc74d613}, {0x000ea7544ff9e1a7,0x000863bcedd14dac,0x000776fbd052c35f,0x000040b845e5e89f,0x00008d3631aa2f1a}}, {{0x00078cb5cf75d160,0x00082adcd531e19f,0x0001f334ec5d686b,0x0007bcfc67e75339,0x000083292fd5cb3c}, {0x000ca0f2c79e4395,0x000d7220b49dc04c,0x000d3bf945b11bd7,0x000dced7c2b83ea6,0x00005baf7714ff68}}, {{0x0003508c06e840d9,0x000135b5a2b19028,0x000ee969d63b1a38,0x000161e84ec50423,0x0000f2fa14216578}, {0x0004bfe086722bf4,0x0003cf085472f45e,0x000dfda75e905f33,0x00079bdd9d624bac,0x0000fae3603f75ba}}, {{0x000ee7df45826065,0x000159449fe4f3af,0x0001d996e565d3d7,0x000672368612ab1d,0x0000b960776c83e6}, {0x000d3ecc1939a703,0x0009f6c9772241da,0x00098eef9abac2b5,0x00032adbadd70bae,0x000062ee5f76ad58}}, {{0x000fd21287e5c826,0x0009b0b6759542e3,0x00065f7682b53c33,0x000431f1b099e8c5,0x0000215359e247e6}, {0x000ecefb66ae71b0,0x000c047b9bdf08b0,0x0005d0993282cf6b,0x0001c428f51699c8,0x00006ac5644d7483}}, {{0x0008a6bf88a12bc8,0x000cdb7063092912,0x0001649711d448cf,0x000792826cbe6242,0x0000b333087bceb8}, {0x0006b67ab7ffab12,0x00025a16516d0184,0x000c86a31293dd6e,0x000a457b718e848d,0x00005e930921509d}}, {{0x00045277b9938fd7,0x000e086e2c20dff9,0x0007dce3453814e0,0x000e253ca6ba6c61,0x0000f538b78fd25f}, {0x0008e6179f3b912f,0x00078b639a80001e,0x000414bf793b6324,0x000bb8e28cac8f71,0x000031ad39adcade}}, {{0x000a465f76d43f56,0x00090150ef7afe7d,0x000b2300b65a46dc,0x000e4e184f9a0661,0x0000561c2fc130d9}, {0x0000a143683c7212,0x0009a56843b2c208,0x0005135d6f7b6c2b,0x0000a908bec8776a,0x000034f7ab83b724}}, {{0x0008c05b480c3297,0x0005a07fc36b2bc3,0x00097924fce51403,0x00007eaa739b3ab6,0x0000265fbf04966b}, {0x0002950b0f740005,0x0008cf8940d2564d,0x0005fd0c6b2dbfd1,0x000c6ce9a6b44dbe,0x000084a9579b81e7}}, {{0x000e916369db82e0,0x00020510f751afcf,0x000eed18f269af1a,0x00013c1ce9324e71,0x00008683d69fc1e4}, {0x0004e5889623baec,0x0009ba4018b294b8,0x000e6bfb3c0b24e6,0x000bb0651dbdf225,0x000027ab085ca68d}}, {{0x000f09a4ab6c3aaa,0x000de01cb3ba63c4,0x000e95f1d210e7b4,0x000f3a8d12cf38b4,0x000018d1e9f0e6ad}, {0x0005dfe6cbc23716,0x000aa7708956bd51,0x000a734e02a987f9,0x000198b26b6caa0c,0x000066d2bdfa41f7}}, {{0x0009b8808e884a94,0x00056a949ba89d55,0x0006dd0557bc07d6,0x000df3f286c34b23,0x0000010cc2c61658}, {0x0003c84869304a8b,0x000c4e02538c802a,0x00014310ac59c7a8,0x0004e213a3299cbe,0x00008091b8c7dd4c}}, {{0x00066d7d54bb7037,0x0009fc78a9ea064d,0x000c8c718ecb6d4e,0x000b29b0b388df47,0x00005ce278ce6360}, {0x000615c03685384f,0x0001493d593abf47,0x0007bd22554fbd0f,0x000cda5b2fbacf9b,0x00000be25106f6db}}, {{0x000db548aff3dd66,0x0009fc3e222a2257,0x00021af9576355f5,0x00038fa46dacfcf1,0x0000a39c02de3477}, {0x000e5949738ae55b,0x0002b82b325aa2c3,0x000316cfaab2be69,0x000c3155c811feef,0x000094001c4354f9}}, {{0x000e52c880cebefd,0x000fbac37dc45285,0x00047d8233836931,0x000393a52c077d39,0x0000f2cef1dcb976}, {0x0004fff652069879,0x000f14bd96afc0f1,0x000d7647c5393c35,0x000b655fa3d54814,0x0000b31085f87723}}, {{0x000c64f583e1f402,0x000473a19323b48d,0x000d2fce8f8f79be,0x000cd0f61edb557d,0x00009ba886a6747e}, {0x000f6589946073be,0x00002e0d1b415ede,0x000135675a16d9b8,0x0002cee38fd0b032,0x0000a1d1db71309c}}, {{0x0008a92ead7f3bdd,0x000ea3397552948c,0x000df72673192c3a,0x0006ba2de5b32e77,0x00009c0d4111e5a8}, {0x000bd04137e03344,0x00089b4162fd10fb,0x000ebd666ce66159,0x00064d877840eaad,0x0000381e39594fa2}}, {{0x00000628e098c674,0x0009cdcbf9ca0680,0x000c9f9fe4c5a3c1,0x0000f7b96570ef82,0x0000049c1cd347b3}, {0x000fb672fa7243a5,0x000c2b46489362bf,0x0009a950e91645d7,0x000e29f1b1a58485,0x000003188482ca65}}, {{0x000e8a5a08e6c7c8,0x000d1896d6be3d81,0x000632895b101d4c,0x00031a37b4f35e11,0x00007da1f2d7abe7}, {0x000576beeab98952,0x000748d0ccd0c23e,0x000b5c50c67fca2a,0x000936a558e370e5,0x0000985eec700203}}, {{0x00037f6ba08ad439,0x0006926c8ad8398f,0x000df38a044b9452,0x0009463c48a42ddf,0x0000a860dd55a6b4}, {0x000d162812b222ed,0x000fd854816b2dad,0x000e65262e4eb660,0x0005a5b527b029ea,0x0000175bad33bdec}}, {{0x0002c3da8cbbe229,0x000aa90abc735562,0x000bb0db89d0e690,0x0003454c1c36d6e8,0x000036f4e1df9931}, {0x0000ad2fb609c4b6,0x000745f01f277c0a,0x0004f07d4ce8634e,0x0007939a3356bbf7,0x00009fa9bbd0303c}}, {{0x000834bdba6935df,0x00068b5bf0655c17,0x00009c8960d66e80,0x000b3b6460148a4f,0x0000f945f0f28aea}, {0x00008c5ad9f47c68,0x00079e9a1df4281a,0x000eb5d36cee9dce,0x000d177605462f15,0x0000bdcbfae25681}}, {{0x0004c6b9e03db771,0x0001da5fbc75f102,0x000950b5e2ab475f,0x00073cbe4e444a5a,0x0000bd5871471640}, {0x000d74a1ca5ad868,0x00048ec67d0c8551,0x00000d3328df82c8,0x000e5f6f20f8912a,0x00002e0fe080c362}}, {{0x0001c3d6d6d5d264,0x000b218027996557,0x0001970f15dafe9f,0x0000511096cf81f4,0x0000c9526de03ea1}, {0x0001e30dad4e3f37,0x0003aaa14b7782f7,0x0000539fa89532b3,0x000cc848b2ec61a4,0x00002b6f09d9ff2f}}, {{0x000dfdd25cf29291,0x000dda0092de30ae,0x0000a4e132261624,0x0007de7dd4994fc6,0x00001c40532fba17}, {0x00018feb438b5b0b,0x0003e95815fe08be,0x000948087b006e4d,0x0005efbc2a9ef7a4,0x000009e6d587a5d6}}, {{0x000969e4f9206d0f,0x00075a33642fbb5e,0x0001c4b5d8ec63ca,0x000a4b54ef559a14,0x00009b489e45d4b8}, {0x00079fd87810f9e3,0x00005eec7620bd39,0x000e3eca2d32cf90,0x000386a4932bc4fd,0x000080d2dfd12b4c}}, {{0x0002bab6b693b018,0x0005396af6ef38e8,0x000153f766a56bc4,0x00059f4479f1c4a8,0x000065854adf0b46}, {0x000ca7e73f59716e,0x0006eb462570ba76,0x0001e66b58a3ff32,0x0007e313f7e7d714,0x000075a290729d59}}, {{0x00062bf29147d07f,0x000b71338d29fb95,0x000a83b78c68c915,0x0008e5f7bbf7376c,0x00002d08e6ebdc2b}, {0x000022479e069a78,0x000529a2b2914757,0x00012616758d3d5f,0x00000b75f51a9a10,0x00005ca72d9581a1}}, {{0x00056185d307f683,0x000a74cb99c3929c,0x000b06852fc4967f,0x00067199709504e7,0x000075f08dbc7f90}, {0x0007d8f5aec63809,0x00005c9d1e1a8854,0x000031b69a7b3391,0x000d26bf93901560,0x00004fd890aed914}}, {{0x000e962e74fa42b4,0x0008b6eef166545e,0x000872fa7032fb4a,0x000897ad192d20e0,0x000094230f24ef1d}, {0x00071573ec958b1f,0x000ed4a294849e47,0x000b5bb10b0cb9ef,0x000c1bd82e65ac22,0x0000021aaa1f3222}}, {{0x0003cf15c474b96e,0x0009e70fb75491a6,0x00055261629d3ef4,0x000ccabb565167c7,0x0000cc5624a31510}, {0x000841e7e25d97e2,0x000c7e403d770905,0x000be67912255f30,0x000c36beb19eb409,0x000000ba1f7537e3}}, {{0x00022bdb04b10d27,0x000bf434239c52db,0x0008d4498f41ccfa,0x00035c025e14818a,0x0000e4cd009815c9}, {0x000292bfc4a245f8,0x00097364e9de7d60,0x000cb48c1de328ef,0x0007e4db08fe9d56,0x0000d6112b78e540}}, {{0x000831ddebf9598e,0x000979bb92d0eac8,0x0000cfca46f5cab4,0x000b6015ad2f7772,0x0000d41fe36ef39c}, {0x0003a2ea9b69dc25,0x00042dff273b08cb,0x000f81461d1ffb14,0x000a4c36404a0c68,0x0000bd4f3b25d7e1}}, {{0x000b52447a59ca38,0x000412904d355b9b,0x0009d306c9363867,0x00067f6caa01f11d,0x0000041bf277bf17}, {0x0009fef689c4169e,0x000e3dc4bfdf9266,0x0004eceb55ee1f01,0x0002944c74b71d64,0x000046d3fb3b5264}}, {{0x000d89c6b8902588,0x0004a43fc1846231,0x0001866a88efa1d1,0x000fa61d29d42923,0x00004af39ae87686}, {0x000be51bae53ac07,0x0008423ad27f8d1c,0x0003aa54acb70da7,0x0007b8f235bf292c,0x00000305b9d0943e}}, {{0x000514fe38c4f7de,0x000b829401fdb149,0x000db76997df5622,0x000f807d9447624a,0x00005ac0b00fbb71}, {0x000727b2d9749d3e,0x0001289dda4509a3,0x000629016714c594,0x000780af9268e465,0x00007f6db4424a1f}}, {{0x0002aae6462c8c00,0x000054a3be95cf37,0x000ef28c0b873e69,0x000af8ca81887394,0x0000225ad865d446}, {0x000ef44f58dd3666,0x000173b419047734,0x0004dbd8a69723d0,0x000254b9684a7eec,0x00008b1aa366d4f9}}, }, { /* digit=7 [{1,2,3,..,}]*([2^49]*G) */ {{0x0001aeed239f4556,0x00049d4ddf57cac1,0x0001d2a819808334,0x00000b6a5d2670cb,0x00000f2e4aea4ac9}, {0x000c8f8ccc05367c,0x0002818771212a6d,0x00085497ca404a57,0x000d31fe2406ea3f,0x000066d75813b43b}}, {{0x000510a53ce5c73d,0x000fc461cc13581a,0x000c24ae8baba850,0x000a7dee213f3d39,0x0000f50e637950f1}, {0x000bbff69e5103db,0x000a85cb5f3beadb,0x000a70f73cee5aaa,0x000c947b2cc95a87,0x0000ba0e771ec061}}, {{0x00040300d97bfe32,0x0006a033e7779a90,0x0006d553f95b3008,0x0007b47c5e9b61ac,0x0000021b54e152ca}, {0x000c553aa7a3a110,0x00046dd1c7ec0c1e,0x000577c34df1edd3,0x000d7165340112a0,0x0000d5fa7bfd90cc}}, {{0x000f022a7558380e,0x0001ba7b90f5fdee,0x000e0da2bcb36cce,0x0007745bd4959204,0x0000dd2eac35ad01}, {0x0002c8521c0c5af3,0x0003ad91885450a0,0x000fb8b9f94c617a,0x0001771d86ee2b64,0x000058a7459f4852}}, {{0x00087c696cede771,0x000a6d45b0f224af,0x000936b54c8b1b48,0x0008998378d19198,0x000043233bf94432}, {0x000fa637bed26bac,0x0005c18a17d7bb9a,0x00086ab22583df2c,0x000cd022a04cdac7,0x000073f0dad5030b}}, {{0x0004aef507316508,0x0005e17245c6d9b5,0x000bfb309240aa80,0x000b0fce93d46ee3,0x0000cb28ae82deb4}, {0x00028ce7431d4cf7,0x000e6de34e2fd644,0x00027a4a239496d1,0x0005695b9f53f16f,0x000026a63f905548}}, {{0x000eeda91a8f07be,0x00010b8144a4e27f,0x0005df4bc4b7698c,0x000c15c892204fe5,0x0000de3f93a307f0}, {0x000af35ec993e2fe,0x0004c71f0d310b53,0x000194dcb0a3be66,0x00024460840d4b9a,0x0000015279dfb876}}, {{0x000dc97176f5fc32,0x00084c41f3ea9f74,0x000fcdfe91636818,0x000109e6007a66ed,0x0000d9337c74353b}, {0x0000aa28be36eb52,0x000f0a17aefcc5c9,0x00073205c1bdaa3f,0x000aa1cff6aa02da,0x0000e49689d28f4f}}, {{0x000568b08146d249,0x00059da996f8b53d,0x000b5c2a3f70a11c,0x0005b73182b847ef,0x0000b7cbc8379d11}, {0x0001c6a0bb8a4a9a,0x000842be45b2e521,0x00032433b189ace9,0x000b9407f99f918b,0x000034002e73cc09}}, {{0x0002b2c99ae289bb,0x0005a8aa4e3f5fdd,0x00024d4d0bab6201,0x00089e755c5401ca,0x0000536b9ff65767}, {0x000b91bfbcc62323,0x0004d65e1912fdcd,0x0003cb2f76182d10,0x0009c80f7ce8e668,0x0000cec3a67b10da}}, {{0x000a8bf6d5778d03,0x000fbd801fe4d51f,0x00093d2ccba1f75b,0x000c28520bd7ebc8,0x00004d0d1b357aba}, {0x000f08f86aeb0018,0x000603f6c973af40,0x0004f47cd1006667,0x00016f77b47974d8,0x000047e82a24dcfe}}, {{0x0005d1ddd12aa937,0x000401ffeda864d3,0x000e540c0684a675,0x000cbc4f9b990931,0x0000df6e60528b00}, {0x0001f5e0ad0b56b8,0x0006c70bafd39118,0x00050a6ae9d54b72,0x0004803e3bbc4682,0x0000b9184d9f5217}}, {{0x000608dde1c5dff6,0x000b8a3467306f98,0x000e8e6eacb62013,0x000117376a795382,0x00002bc99d4c1ce7}, {0x000805d31cafc6c2,0x000ec33f2e2c8ccc,0x0007d9e547cce509,0x00073b8f1902fa58,0x0000c31805d21dfa}}, {{0x000140b741887605,0x000490cd29bd1c0f,0x0007f308ee8d7d25,0x000275aecba30f74,0x0000780fa9561b0c}, {0x0007bfafab75c4b5,0x000f2bd8d7c718e3,0x00065faa7126ee22,0x00084992c17bc317,0x0000c7fdce2c0389}}, {{0x0006e725b1a6606d,0x000e6576abca1b85,0x0003e60b5a32ce43,0x000b5e491da7eb02,0x0000f4529d1fd659}, {0x000f1cd618e6a1c1,0x0003d3b5f111ef6f,0x000aee2dc2902aa9,0x000819dbfeafe73b,0x00003af3de73bc78}}, {{0x0008ffd479c62248,0x000654fd6beb4d68,0x000ebb327cc04add,0x00075d822732ea65,0x000044a14f2a186a}, {0x0002035bf8fb9958,0x00026d9f7591361a,0x000e0a6a62a3e29f,0x00023597cfb7041b,0x00007ddf6f52755e}}, {{0x0001437de25e2c58,0x000a749e6e860bd4,0x0004848f10153cd7,0x00021532257cb78b,0x000082b7e982d724}, {0x000a791c09ebadfa,0x0009cc48599d4809,0x0007f5347df19150,0x0003790eb5e46213,0x0000eda7a00a335a}}, {{0x000cb72c3119f7b8,0x0006335b4e574c18,0x000df0fee556561f,0x000efa728a3e48e9,0x00001de12a3aa369}, {0x0007bd62de5ff0d8,0x0009cb8e1debaebc,0x0000eeafa40c9382,0x00041ab5aef3f42a,0x0000f23bb1d172a9}}, {{0x000007ee68dddd09,0x00041db7068d3bd9,0x000c45236df97f5e,0x000b27fec3b2979c,0x0000781fbd0bf529}, {0x00048429ebf0462b,0x00018b77dddaa659,0x00040b96a20bdeb6,0x0009b32be3321f34,0x0000677d50046519}}, {{0x00093f5b430ae985,0x00063b607652d48b,0x0004cb9ee7647460,0x0008bed34ed097f7,0x000006e6a9aa175f}, {0x000dc50978b6e14f,0x0001b2110553d449,0x0005ca3c3412890a,0x0005f156e99a5a79,0x000027e794aaa77a}}, {{0x000337bb4674f974,0x000faaf40bb50fe2,0x0001da97103f3a93,0x000f86ae5da89eac,0x00000d28934fa09e}, {0x000fe143abd373e0,0x0004d19798f1348e,0x0005faddb07be1f3,0x0000fce18709f123,0x0000a65d7f258bb4}}, {{0x000ec2ea13bf8a9f,0x000fff94d1c2fc03,0x0004a5e758d72c01,0x000c2538fcb23537,0x0000519f25ad891e}, {0x000031644a896ea4,0x00095a8473f8d465,0x000e93c5c4dacb49,0x000ebe7a4d3ac4e1,0x00006a7515c98397}}, {{0x00003531ef7c3513,0x000151a1adfcb1a2,0x0000fe90dea9dc2c,0x0003b8148c62d66d,0x0000b432f7beeb90}, {0x0009b4a3a3eb7360,0x000233afcef8ad73,0x000553d8625eca21,0x000dda60321e643d,0x00001b01349d116e}}, {{0x00018c3569e6b0ee,0x00024b0d2fb5954c,0x000a0ecb65c4006a,0x000a62dc0f497e6e,0x0000b96b836c3a3f}, {0x00010ca5b00f3cf2,0x000d5a4d44403cb8,0x000ca83b4a082049,0x00032849181d8221,0x00007f7edd74f65f}}, {{0x00010a1af882102e,0x0002f1c8b66b8d50,0x000cb8b5c86b5ba5,0x000aa20f54bd38af,0x00001096c5fa2608}, {0x00026d294ccad71f,0x000702638eb68c00,0x000abeba69f87807,0x0007937a69ba5105,0x00008964bbd724b0}}, {{0x000ea9ea2bf0fdf7,0x000eb49d812be215,0x0005067fc7c83d3f,0x000764be2c803ded,0x00001fb9b50ab062}, {0x0006b70932d37f40,0x000d09395b17d0e8,0x0003a6022e7f0771,0x0000b27ee57052e5,0x0000c6cf1f16992b}}, {{0x000add9e8bef59b2,0x000614c0c4be9be8,0x000e8fd1ff296e27,0x00093497783204fe,0x0000741476659093}, {0x000e8eb504b04abb,0x0001bcf379fb506d,0x000b9b91e1361604,0x00058b7cb22333c0,0x00002497bd48c840}}, {{0x0004e4dfa0cd999d,0x0008b8d7ba3d9c29,0x000f6ce974ea95f3,0x000c95eb8a425f3a,0x0000f716a99f71ea}, {0x000edb51e52dc87b,0x000b25a37471e30f,0x000e4f019949d742,0x0001d40be1fa0a07,0x0000f2656c3c690d}}, {{0x000f1a6bbf53c9fe,0x00054f2c7694ab45,0x0003232eb20d9b90,0x0006e109a9e361f4,0x0000bc91dee0ee17}, {0x000789bdbed0ccfa,0x0008288b3f1bee5f,0x00028f5d1ef0caa0,0x000ca42aeac3f01c,0x00006007b363bf84}}, {{0x0006f0a64f93a622,0x000b3a5637862d42,0x000380c6ee69a504,0x000e6fa7057de947,0x0000433d4e4199f5}, {0x00023cf1f314c175,0x0009f1ff15bc3feb,0x0009fc8449252302,0x0000e595c6fae70e,0x00004481bce01d84}}, {{0x000f51b3f1021673,0x00053d64db91443d,0x0008e54c650a1225,0x000220d157dc4221,0x0000a3341db93f5c}, {0x000f3d7a5bd331cf,0x00098ff4240a45b9,0x0007ceab2fcf47cf,0x00096f888d766253,0x0000ef3c60ed0577}}, {{0x00097e010ff08ddf,0x000968240b00767f,0x0008602279b7acee,0x00099242875c872d,0x000019a7093413c4}, {0x00062417e2d75285,0x0005d70899ba18c1,0x00020ca0eb040adf,0x000bc187c981b514,0x00008b8cf4318d4f}}, {{0x00080a709a32342a,0x0002965305d1f38d,0x000bf1feb4d161e5,0x0008904dcd385285,0x00009237da3aa1a2}, {0x000aa5a46cea858c,0x0009ce6d6f2234ac,0x000c28dcf76092ac,0x000e838a0ac0bd91,0x000030791072687a}}, {{0x000accda4225c342,0x00029636e0fff56b,0x00021ccb1fb397b9,0x000dc741822beffb,0x0000d48cbd35cefc}, {0x0006d5bfe9ba3d6a,0x000225360b6d5563,0x000741b6001dfac4,0x0009b486b1b23b18,0x0000ef14d08ff4e9}}, {{0x000f90e78c1f3bb0,0x0009b6f85de2028b,0x00037d91cf6b7783,0x000a3f03a27b6beb,0x000069ac8d736c15}, {0x0000c62e806bd30b,0x000056746a7ab9f6,0x0007ab1b6c245999,0x0000fe72037ecf0c,0x00008ca60c732f21}}, {{0x000abe30741481cf,0x00040b18ce478cd1,0x000e7f8c34c982fe,0x000f0fe79cffb728,0x000074960aec39c4}, {0x00066aa9050b893e,0x0000122edd8925c8,0x00092c673fe40d52,0x0004b39f8c9033a8,0x0000ce1891820586}}, {{0x00005206bf1ee33b,0x0000e4979d7a9a80,0x0009b650b8c12ac8,0x00054e4da9f88d79,0x00008aec7e264a80}, {0x000ae68f7b28d79c,0x000387cef16ca493,0x00089b6b0a4dc3e4,0x0003e40509431dcd,0x0000bbe744fec78a}}, {{0x0005978ad410ef01,0x00014cc3515d61f0,0x000a46f70afcb4b4,0x00041970a01aa3fe,0x0000884ec45da55a}, {0x00063b35165dbca5,0x000cbc71ac33d0cd,0x000e4c38ef210420,0x000cf3a0f23b9fb7,0x00008858d7174d5f}}, {{0x0000478139115bed,0x00093f433881438c,0x000447a7d8813dc2,0x0001188cb8732df2,0x0000f920508aa0d1}, {0x000bdd9b8248baca,0x00051a0fda74f21a,0x0004f3bd406ce881,0x000c164428836dd4,0x00000a2424cb008e}}, {{0x00089b69fbbbca39,0x000b1669463edd19,0x000ccb304c3b438d,0x000a7733db961ef9,0x00006f2d432afb6d}, {0x000acc1b78bef59c,0x0000abcdba630ae8,0x000bcad61d6beb51,0x000b213bab1c81a0,0x0000f6c677215aa6}}, {{0x000314509f77691d,0x000070083e4fdae3,0x000d7f1f5feb96d3,0x000a7d9f0c18c1cf,0x00001b7ddfe0651f}, {0x000db98fcc9de7a6,0x00069a529dcdc450,0x00097718843d4122,0x000d3e0ad913fe75,0x000005594f0670c8}}, {{0x000e4506cab3068a,0x000d1d2494770a89,0x00030ec9b9955748,0x000846ab8cbf8946,0x00007c89daf9778a}, {0x000acec4f4606444,0x00078c364d73231b,0x000fe41c31286866,0x0005d3f1ce47c3d8,0x0000e365480c68c0}}, {{0x0003e4160b45a121,0x0003baef5d6683e7,0x0004dd85a1e42102,0x00071f5e34c234f5,0x000091f9fbced850}, {0x0007767771328099,0x000d49be9c6b664d,0x000a38f38d829f06,0x000ec330eedef076,0x000026c48800340e}}, {{0x000736dd0e1d6e43,0x0005022facfe3f4c,0x000191340b7da1b5,0x000d914f559d6ff2,0x00004e994ce30fd5}, {0x0002295702306bc8,0x00057ed0842bb003,0x0002112cacc1577d,0x000b4491fdafe49f,0x0000ad39b895860d}}, {{0x0007eec37bfa3de4,0x000b16863791d4ec,0x00079f652f765dc5,0x000986d0c1bbc9c3,0x00002abf602df07d}, {0x0001e932edcf3171,0x000edb53f5fb229b,0x0009b60fc290f0be,0x00091a4acbc35e94,0x0000ba30ad68659e}}, {{0x000dd8d9660b26f8,0x000350ca1223a663,0x00032ab3d4eba231,0x0002804991c779fe,0x000099f830e34a06}, {0x0000e71d3111ffed,0x000005ce14589dcb,0x000f365f377370cd,0x000623a24a8ccbf5,0x0000059fbf358ace}}, {{0x0003a4098bbc3934,0x00004dcd090a5572,0x0005a7255ffc94fe,0x000185dfe7e5e6b6,0x0000bee85029ef3f}, {0x0002743db2177911,0x000d5e6bd9ce4510,0x000caa6d30f32aac,0x000f4f7b671a2e7f,0x00004304bbc2b68c}}, {{0x000a04d9e64e4d35,0x0002ec1e1c9b0135,0x0000551455e12027,0x0002be716a3c508b,0x000085f4f1c5deaa}, {0x000fae6e86f4a15b,0x000864a7631005d0,0x000975559b3bb56e,0x000c45a95a184010,0x000086bd840e2d14}}, {{0x0000c3fb351ec55d,0x000a716ba8612e75,0x000373c466979ea0,0x00032b4b9a776a63,0x00005a8b35671cd3}, {0x0002093dd7493ce9,0x00006ec41ba2b630,0x00026128f18e92b4,0x0006d1dd3049143e,0x00008405ec34615a}}, {{0x0005e208a0356f29,0x000e456a9eac7617,0x0001f6a6f856d9b0,0x0008e436387a6c14,0x0000127cd283e4d8}, {0x00000f6a32221562,0x00012f58a6e1e3b9,0x000372ba690134c2,0x0000101938ae6152,0x0000a86d5af405d0}}, {{0x000699670a64b1ab,0x0001fbf935745441,0x0002aba2b5b797e6,0x0007c9bbf9463769,0x0000dba14e270cb8}, {0x00013412230852bc,0x00022cfc37cc9c35,0x0006bb6af3ec8fc8,0x000ff9c5283e7b80,0x0000a3777b633ffa}}, {{0x0004f15ce0554be8,0x000ecfa3ddcbe763,0x00055667be6039ae,0x0001a5485efcc93e,0x0000e042ceb13077}, {0x000e81d073599e34,0x000d6585f158bd8f,0x000f7f92cec7e3c7,0x000d61a31bb59a5b,0x000045f686d482c7}}, {{0x0004eda272cf63fa,0x000636f1a9b8a218,0x000e1b6bb618ea24,0x000da926f4254f89,0x0000afeb6d402035}, {0x000c73357c46ecb5,0x000afe899f44ab86,0x0006183a62887e7c,0x0002c32e74795194,0x00001a51e3704cb7}}, {{0x00044bb9b131bcf7,0x0006417f905f29da,0x000271aea17d6518,0x000225822f44b473,0x0000442a5c8529e6}, {0x00050fa2d6e447c8,0x0000dfcafbd2ec61,0x000f4ccd550401ca,0x0006a0f1350b7a4f,0x00001ec4502e2e21}}, {{0x000bd15bf9662113,0x000335bcb1799bcd,0x00031ca94fd47034,0x000e1949d595cf1e,0x00001a8e934c2d2e}, {0x00034f38faa8ec78,0x000cbe16f46d9dc4,0x000bae7880239684,0x000b553e8a39b8ef,0x0000f6b6e14a3ec7}}, {{0x000b937dc23032aa,0x0003d9c256e1f314,0x0009f15c9e65fc03,0x00090371034ea18b,0x00003c9a3c47dcaf}, {0x000484226b0c9336,0x0005daf367bd47e5,0x000896a1e101650b,0x00011d3fe8f106a5,0x000030553fa62618}}, {{0x000620f5d69edeec,0x000d7a4eec8de791,0x000287a787907f50,0x0005ea68c4827aaa,0x00001a26fe08385c}, {0x0003a8e0e67d376e,0x000c9cb8e62ecdd8,0x0006423b3147defe,0x000bab0d5392e6ea,0x000093a79e3c20b0}}, {{0x000e6ca8c201225a,0x000d361ddc9c9290,0x000842db93584608,0x000de2a6a6a74023,0x000052a66d55df1d}, {0x000ae8c9463e80db,0x000b580b54c73462,0x000d39a08482e062,0x000d4f4e9168d66b,0x0000432fa82c4408}}, {{0x000cd6a07c166baa,0x000d0aab204c73a5,0x000f172b51bb0308,0x0000f224f298465e,0x0000bcb5fbbe0394}, {0x0003887f31da1be4,0x000fab42c7ea084b,0x000288810250c3d3,0x000243da8e6bf318,0x00006e11ea969a39}}, {{0x00042beab44de79b,0x000d1bdf4e1ef56f,0x00092d95c84dc218,0x000ac84ec350fbab,0x000078c07677a9e8}, {0x0004fbd04103d16e,0x0008505240255fd8,0x000f4c2e83bf1669,0x0000f248fbf6016d,0x00003b3a59853adf}}, {{0x0004d0bc9d68c082,0x00028f23db2991b1,0x0003cc0616167f9d,0x000e770931c7b4b1,0x0000da5ad5d2e0b8}, {0x000d6695dfec5d44,0x000981be910db292,0x000c7ac75239d091,0x000574e433511309,0x000082d8c29306e3}}, {{0x0002be7195675921,0x000957bf6119ef73,0x000d96cb0c4d5c87,0x0006f8fa6a706d42,0x000021e1cb73d95a}, {0x00093b14fe798a38,0x000ad3f85e91623b,0x00033662ce9ac003,0x000caedbca9b36c8,0x000092ff41dd7e0c}}, {{0x00076b51b75fec0d,0x000340db61af3e02,0x000abd899caf72bb,0x000472cd7bd7ae60,0x00007641cac436d9}, {0x000f1a178cf6f1cc,0x000000d23b7cffb0,0x000f77b796e5b6e4,0x000f33328af949d5,0x000010f779508865}}, {{0x000eb802f32faab8,0x000060554f3b532e,0x0005ecce4b511538,0x000343924e7bc29d,0x0000c15966b6c62f}, {0x000f12a31d85149e,0x000702536a1b1333,0x0006deae7e597135,0x000a1cb884c1d3a3,0x00008b957c6d3bc7}}, }, { /* digit=8 [{1,2,3,..,}]*([2^56]*G) */ {{0x000a0db802ad8e2a,0x000198c71fc20913,0x0001af4b76762aa1,0x000d0991a59e2221,0x0000724ce9039cad}, {0x000bf205e5876d57,0x000c736f68df81c5,0x000ab6ba1fb2636b,0x000ffe34868e7098,0x0000261df12d1037}}, {{0x0003fb0efa0b1ffd,0x000a3fc568975624,0x000bdb4591f15f6b,0x000439654edf2cac,0x000003491ab55faf}, {0x000f3c88c630e16f,0x000e7a922cea29a0,0x00036b058547f279,0x00065d2986844536,0x0000159df225491f}}, {{0x00016886aba2e444,0x0002ff5dc5081177,0x000694e142d2637f,0x000aae0245602bd1,0x000056094e9d2d91}, {0x000aac623d3970d5,0x000712ba9937c039,0x0003188e393e6d1a,0x000724cb6f2c4b0b,0x000051c7142d857d}}, {{0x000a6c4126387d4f,0x0000d207fd54b018,0x0002d2c2fa82305e,0x0005af7f76e4d82a,0x00007991440733c6}, {0x0008b1ad2efa1bdb,0x000aa0154ec58403,0x000b501e885ff98a,0x000882de171aa384,0x00007914f6044142}}, {{0x000ab01c6935b4f9,0x00003b6de76d230d,0x0004d5a6213a18df,0x0007963145617526,0x0000823e1682c1e6}, {0x0005e79ac9b872f3,0x0003ce7021be0c18,0x000c686947c500e0,0x0000a6319f616513,0x000045678a89295e}}, {{0x0000c88440eaa722,0x000e347df565ba08,0x0000930155047bb6,0x0009d6475a78682d,0x0000591de4ffe082}, {0x000f7732b9087359,0x0001861be64be6ff,0x0005a48107286612,0x000bbfcd5daff943,0x0000410a05140a8b}}, {{0x0003711d4a4e4fe6,0x0003fe30c63f29e9,0x000a2de989dabddd,0x000323866f1580ec,0x0000b9de281a175a}, {0x00007a398f7e9455,0x000debaed06f5308,0x0001392b17b31e3a,0x000de3ce5bf10e00,0x0000f2a8f37e8d28}}, {{0x000eef460cea0d86,0x00080c089ea3e5c6,0x000d79ed4ba91ad4,0x000b168d4eb1f87a,0x00004c8dd11d9a52}, {0x0007631e210a2732,0x000522f1cfd893f3,0x000c313c40f24058,0x000538b4a53f3f1b,0x0000805ea5ac03cd}}, {{0x000f2b4d9647871e,0x000698c6a70f2bf6,0x0000618fa5bbc040,0x000f35bdaacafdb1,0x00004d56a93f6a15}, {0x0002747db37534d4,0x000940549a7cacd3,0x0006eb9286c071e0,0x00086eb8426639ff,0x0000fb0a02399634}}, {{0x000263cc8597555e,0x0000bcd376a4bf19,0x00078d8efc8cd230,0x000ecce815e792d7,0x0000672dbeb03db9}, {0x000ca483874e7dcc,0x00062391ae793e10,0x000b5a3cd1e05af9,0x00033f3361c5cc5e,0x00001ee94edad6df}}, {{0x000e3a27b278aaf5,0x000acb57977526c7,0x0006911103ffb78e,0x000ed702ab4ad712,0x000051d4dd701893}, {0x00006061e1dd4f36,0x00024dbe375be15b,0x0000d19abf430996,0x00010fcc798197c9,0x0000dd790c374a6f}}, {{0x000330e15cde34f8,0x000d285ca782df9c,0x00013e0f4ad9ca71,0x000b872d7e70e9f4,0x00009c965ed8166e}, {0x0006bfdf82982e7b,0x00029a67518e8d8e,0x000332d8a97d85f5,0x00001948637867f7,0x00005ff8016f7f28}}, {{0x0004eddddb576a2e,0x000f99c20d415c51,0x00088bdcb245ef5e,0x000767739e179128,0x00007e8feed3b2d1}, {0x00060bf9c8d8bd74,0x0004fe343ddabcce,0x000534d9ae42b1a0,0x000cb78d550b1cb4,0x000062a4b409550d}}, {{0x000c9aa9f5ec19fa,0x00036bab280e495f,0x000ec8135bd5fe5a,0x000257848b5c6e13,0x0000761ea009ba1c}, {0x000dd3c7a0d41127,0x000e4675e99a1705,0x00055926d841432c,0x000ebb9724b23770,0x000008204e2070fe}}, {{0x0004bd37f61b0433,0x0007488b1baf6c6a,0x0001ff33dd611c9d,0x0003daff36d77f21,0x000012e12b486b0e}, {0x000d3d308ad3a01e,0x000cffbd52d205a0,0x000a3c9d1ddc263a,0x0008c49be3889951,0x0000c3cbb88dc5e4}}, {{0x0008494d5ac38a60,0x000d1abd383b64d1,0x0008d5867de2630a,0x000e7c899c27a88d,0x0000cc4dc229cdf4}, {0x000e69248c51c51f,0x0001de98813939c0,0x000c9fc3540049af,0x0005acb02b92dd45,0x000015dbe915bf51}}, {{0x00030100f6fd2798,0x000b5cc6b3f2de4c,0x0002cc9a1693c61a,0x0009d7cd8f059e65,0x00002cf62e1b8fd2}, {0x000b441e397cce3e,0x0004b8ee5b2a90b6,0x0001f1bf731ac8fe,0x00044622a0067d97,0x00007c2cb7412bf5}}, {{0x0005ded4da08c914,0x000c57bc50d57705,0x000c17c0e5e74346,0x000674093e88cce1,0x00009d958b500cee}, {0x00011fd4c2ef91c2,0x0003d68c5fc39edf,0x000a3b166dbadb86,0x000c83e5a523a4dd,0x0000e1e7d5670101}}, {{0x000e3abd49188ad4,0x00088dffda2a80be,0x000f3b05945c192d,0x0000c7b93d42d6a9,0x000002b90dd3fd2b}, {0x000346bd29b792b4,0x000c03609852e2b4,0x0009c492438fc4c5,0x000f90a6d5d4b916,0x0000d555a212879b}}, {{0x000fdb47bd87a424,0x0008b5138112db69,0x0008d1d2f115354e,0x0005bc50db48e3da,0x0000aac2eb70e66f}, {0x00051bc6aba63664,0x000e262acc9ce72b,0x000438ba3085117e,0x000822be56bb230f,0x00006d5cca79124d}}, {{0x00053f5fe3dc39cc,0x000b414d5f67bdc8,0x00046b348c10dd5e,0x000770a76e02dbd6,0x000009c3240fcb02}, {0x0008fb52645c9dfe,0x000c18c396fe8d53,0x00092dad0baa2238,0x00018629d37c8b0c,0x0000c60386360546}}, {{0x0004a8de81e01bee,0x0007f8321592e20c,0x0006931b55bb7970,0x00076794a7e10024,0x00005ebf25e72a07}, {0x000483a0f5a9edca,0x0002bb646d9e6312,0x000e37073230f82d,0x0002517b5dddff68,0x000029ce765a98e3}}, {{0x0000ae6e544c6ea6,0x000b57855552f6d8,0x000b8a5e25ebab2d,0x0003d955707f9c00,0x00007b357c483d08}, {0x0005361eff79a535,0x000156e0268e623e,0x000996462124b446,0x000a24e231e90f3c,0x0000bd6b1f150e05}}, {{0x00040b77de486a19,0x000cf6c03fc07914,0x00036c6bfd63554f,0x000429473dad2c7a,0x0000929e308049f7}, {0x00070a9c2bbc1283,0x000621dd51016272,0x000eed7cf3413478,0x00025a8e63501e29,0x00003512397dbb12}}, {{0x0006891e7084f0f2,0x000fd6a38da9e393,0x000256ae79ed2f3d,0x000d874a6b4d7cd2,0x00007695b9534b5e}, {0x0006e9d024eb60ec,0x000c40f326d7afea,0x000852c01e0e4684,0x00071b37bae69e1e,0x0000a388523fa1cc}}, {{0x0007b4d81320b2e9,0x00042b4678e1317e,0x00031c45fcb6ea5c,0x000c542ee5785311,0x00009b995cc107ba}, {0x000eaebcec18878a,0x000a9849b1c2e018,0x000ad5438bae1123,0x0007805e180c0e02,0x00002ce8e4160ee9}}, {{0x0003c9f0bf831b63,0x000e9bbb471a25f2,0x000ed4ce91f1e7dd,0x0008472d76956795,0x00005e67d84a19be}, {0x000eab76f5a65259,0x00060239051663e7,0x000a9f4ea42d2626,0x000b8a344f8f5d2c,0x0000bb99d60d6793}}, {{0x0008053bb8d37d24,0x0000355c03827c18,0x000a8454066ad23b,0x000f6d341b9405ea,0x00009fdcc57978a0}, {0x0004e26d8aafb17b,0x000c4ec79ef02ddf,0x00008c46fe8c88b8,0x00016777aec8ea64,0x00005ea6fe832ac5}}, {{0x0003b361878c3d3d,0x0007921447678781,0x0009b469595fe31b,0x00055924b0bcc3b2,0x00003e4b82a2e59e}, {0x0007f61727308214,0x000569f22b76dbd2,0x000233c6e2a1b59a,0x000e7aa7cea941b6,0x0000a51665729aa9}}, {{0x000cc4b553fbe60d,0x000b1cc8f5672bc8,0x0004471a809c494b,0x000e7ff3633cdd40,0x000094b3115ecf90}, {0x000e7e954727f93d,0x000b292aa6dd5242,0x000798c3d8b2f132,0x0009e8fae560b438,0x00009604a24394ff}}, {{0x00074df40c36a876,0x0008139bcd46117f,0x000f04c1dd9ab144,0x0007151706edf335,0x0000ca29fddf0c9f}, {0x00077943d7b52cc2,0x0005759e0b8ef052,0x000c4fbae923b66a,0x000b4312d8827f47,0x0000b2cac97b4362}}, {{0x000ba3b3d8c333e3,0x00084249ddfc6f82,0x000412b21bbeeda4,0x0003f2feb78ebe73,0x00000f4a98190b90}, {0x0002b13fcaefd68e,0x000db2497727d8a1,0x00050310717e05a5,0x0009b4f4db117595,0x00002bad33ee056c}}, {{0x000aa899669a94d0,0x0001eab7a00c5660,0x000041a733d2c8c1,0x0009450c1e253b75,0x000017bf47981a80}, {0x000f809d4fd21a7d,0x000be6533241ae79,0x000d829dd7bdcd33,0x000be78a25e57321,0x0000c09f94cc338d}}, {{0x000f8d0a468848c5,0x00047b41a21d9ca1,0x000bc0e5b17c3f9a,0x00029374333d5705,0x000030912604ccc2}, {0x00008d0d6ceeefc1,0x0002a8c72cc8005f,0x000e6cd79d355262,0x00085d0e66445e88,0x0000b6ec8a4e04c2}}, {{0x000dbc54066477ec,0x0000a8c5bea950c1,0x000684204e2e4f7e,0x00086fee8955629f,0x00009b1f71580e9d}, {0x00087fc2c0029688,0x00027479146bdc72,0x000667694cbc6782,0x000b7b2f7af3baef,0x0000f7f90385b159}}, {{0x000bb32253f3a82d,0x000b3a639c9cb63d,0x000360890138bc41,0x00057b610a116196,0x0000ab4e04b9e339}, {0x000ae727cbd17ddf,0x000a2b1a48784582,0x0004ee4100db6d3b,0x0008cb38cff9eb42,0x000029b0c8dd23a8}}, {{0x0005ed5e3f62c22d,0x00032b06f482bc86,0x000b2a80097544a1,0x000c7f76ed319dc3,0x000088eb3caa8336}, {0x000408416a3468e2,0x000cfcaa5c73b399,0x0002ccb5869caecf,0x000834622f2f7c10,0x00003ebea2e23bae}}, {{0x000f634159c3f145,0x0001a314fd75ceb9,0x0009e502cefadb01,0x00082007b8010960,0x00008a2bf184a15c}, {0x000886d3ec835a82,0x00004bf7840e310a,0x000d8eaf18c9f355,0x000c84d39c35be1c,0x00003fa5437b08b0}}, {{0x000e7c76ba48af4d,0x000a39c3a01a8fd9,0x000c62e23ddb4853,0x000913a6ec0c12f0,0x0000b9479a5d516f}, {0x000b51d7e32dbba9,0x0001abd8aa7d25f0,0x000afffda4d3a475,0x000270e67e9ae172,0x0000c1fa7bf9b1fb}}, {{0x000931c17cdd8a73,0x000e0448a021a8ba,0x000920e03df7fecf,0x0001bcbd374eea3f,0x0000c62edf80f11e}, {0x0001ce6736088569,0x0003c0fe97f45d51,0x000ddb622fb70fe3,0x00042189193abf63,0x0000bace900bcb83}}, {{0x000f81a878a56754,0x0004f75c479fee4a,0x0000afb5829b49ce,0x0005854186889ece,0x000032530cbd047d}, {0x000be7c429c1cf6a,0x000cc541d81ed275,0x000d999296d29cc7,0x00011ced6e04b532,0x00007aeadda8e71a}}, {{0x0001699a94bbbc79,0x0000b3ed33d3b98c,0x00012db7668dbab9,0x0004d7e3a0ec5fbf,0x00002de225c570ce}, {0x0005c39338ab6850,0x000f612c245ee97d,0x0000222a78aa03b1,0x0001e27e4e3af28d,0x0000e34817cbf8ba}}, {{0x0006fd6e8a4a3f4a,0x00070c75489636df,0x0002579d316b0e9f,0x000fe12b5fb3bc1f,0x0000fe57d4f72a95}, {0x0009a194ceff9331,0x000354f75a487036,0x0004549b046aab24,0x00032749a77772fd,0x0000f44e63c940f8}}, {{0x000f73f8f359b8e8,0x0003626aa63db40c,0x0000ebb81b7bdea9,0x000ce970626f7e55,0x0000c692abaa0eb5}, {0x0009cffcdb9d6804,0x000f4c9bb068b774,0x0004adbce122a50e,0x000b00be247e3384,0x00009320ea728f86}}, {{0x000300cb47746a83,0x000d765cce2bcb1c,0x000afbb2ba8b05a6,0x000c89050d56aac6,0x0000f10deb3e6496}, {0x000f6adeb5e3c3ca,0x00005b59f7d73f44,0x00034333fd8fef09,0x000cccc06179b892,0x0000d42424834343}}, {{0x000cd7b1178680b4,0x00067205cb9300e2,0x00022f86af9a63f5,0x000dce7ea9cb6c53,0x00004736f3842b23}, {0x00053bf6f5d17905,0x0001af4b062f5ef8,0x000c8e412a224d5f,0x00097adffffe0026,0x00003f676531b201}}, {{0x00046ade65aa0b35,0x000ab957bcc5a7c6,0x00021fd3aa044a8d,0x0002d742145aae3e,0x0000d79efcd7c6e3}, {0x0006479ffb6a9280,0x000fcff2758345e5,0x000cd168eaebbf6e,0x0001d311cb1cf204,0x0000d5fd7233e385}}, {{0x00021f9564df392e,0x0000cdfbb4120dea,0x000697ef6773fc9e,0x000b33b64b26b1f1,0x00002ed2ba1b7d83}, {0x00069e6145eab824,0x0008a8dbc68bf47f,0x0005827d6b1acd9f,0x0009476929807897,0x0000cb8cab70e2ce}}, {{0x000ed39da3052f0f,0x000d683870bcdc6f,0x000c41480005e7ed,0x000791569848974f,0x0000beac60351f97}, {0x00001799275b950a,0x000212527d574202,0x000173d93889bee7,0x000bea8685758a76,0x0000cfa1096d830e}}, {{0x0006dbc7d5bcd224,0x00049799a90fe43e,0x000bf8e13f9e8a5d,0x000a40e9cc8d918c,0x0000f177852be5ed}, {0x000b278ab0123dd5,0x00010994e23c910c,0x00023635812c11f7,0x0002ee5d1ffddf6d,0x00000572865c55b3}}, {{0x0007eec59607df89,0x000f6fc041bea2df,0x00025c8a86ba453c,0x0000ffdb8cd4fc82,0x000014b0c0ae3f77}, {0x000cb43d27069607,0x0001c526ab3aa02c,0x000c9d06bf4b1f88,0x0001c5df41cbbb56,0x00004c4747afd9b5}}, {{0x000a373fd41c7efb,0x00008eee150edc52,0x00072492cd833b3f,0x000e6300f3ccb31b,0x0000df8c0cc0bc7d}, {0x000a3eb385d47b1a,0x0009bb3430739063,0x0004ff4afb3a8a1d,0x000739f02eb25348,0x0000cc1efa44f33c}}, {{0x0000f4a61e1db8d0,0x000240c3ad0a8e2b,0x00003e752f6d15cf,0x000f1a4cb501fcec,0x0000253b9aa06d6b}, {0x00012854f610f356,0x000b9e867e0b0f0d,0x000cb4fae8d8d727,0x000e686ca560b0d7,0x0000fb6839787c32}}, {{0x0008c30ba2a7b38c,0x0002c05a1e186e3f,0x000aa6ac9caa3aff,0x0002b57828d97c22,0x0000aa7fc12f8eff}, {0x000efe970785dc5d,0x0009dc8818f3ac30,0x0009c0b682ad0746,0x0008e4675851d1cb,0x00008a8897cf8c31}}, {{0x0001252f65cf5ee5,0x00088f29ac5a604d,0x000ac9bbce3667bf,0x0006a0c6475eb601,0x00004bbc154f2060}, {0x0008776fe257543c,0x000a239d34de6a98,0x0009a87768ce62b2,0x000fab0fe16c0d6f,0x0000926673d22d5d}}, {{0x000b2b3ad94a7b97,0x0008fed58b128f18,0x0008946706b30053,0x000479259ca13ce2,0x00006d23f69d840e}, {0x00025e4177e33430,0x0001bec8e41e4120,0x000d93e910ab22df,0x0009ade579d0c842,0x0000e273816addac}}, {{0x00002ccc6fe7dff9,0x0009b502353dbed7,0x000ac7e295c845f3,0x000f70849f73ac4d,0x0000cd4776c48c6e}, {0x000669075bd0861c,0x000bd7cfe206c5c1,0x000ed7294a8a2fda,0x000631c9abfc3e62,0x0000ac1761b8c654}}, {{0x00056155c59e3804,0x000fc6e8eea72563,0x000b382c5c09c5a2,0x0005601fb0724e41,0x0000a8641a0b7d43}, {0x0006e955b7a680f5,0x0009f5c576494068,0x0003be93435b2e37,0x00051a6a679fa13c,0x0000a5238a3c9d8f}}, {{0x000957c5dad3b707,0x0006a860fe3b104b,0x0003bcab2013b711,0x000909be66aeae78,0x000014befe48deb9}, {0x0009073742c9ed9e,0x000a54923d3e39f5,0x000340d1ddd320c1,0x000b66ed03354572,0x0000f7d8e0dc288b}}, {{0x000a09a0d72bae2a,0x000846530c949b89,0x000fc27421739535,0x000c46467b80b4a2,0x000049fd2b8b03fa}, {0x00047f3041803387,0x000a220b9b0be858,0x00019bcc545b9dc6,0x000a8ba2614c8a67,0x0000f019df8137ad}}, {{0x00091858054e09c5,0x000179f271fdc8ca,0x000544ccb6eaaa79,0x000a8115523b3f72,0x00000e9b891c122a}, {0x000c7af09e9c2711,0x000a1a2a3a281d16,0x000a7927fc4edb0f,0x000f2cb10b6c326f,0x0000487e43472560}}, {{0x000c0c37e2cff914,0x0006f180c765eabb,0x0003ddc4575d45d5,0x0008a0dd271d5c6a,0x00006393dbeb0d29}, {0x0008b4d194b3cc34,0x00073b2327d37a43,0x00016dc625fb4e30,0x000d1937f15f8154,0x0000fbc9f81b7d07}}, {{0x000db8bec3a5d60d,0x000e4aa12f4eec94,0x00084204e9449ca2,0x00024cefe7cfc0d6,0x00000c8fbdf94de6}, {0x000813864f28dbf2,0x0004ab156ec6f5ad,0x0006721654073837,0x000938a6d1b62c4a,0x000068b432494983}}, {{0x0007e91a84283e66,0x000bd6aeeb6f7400,0x0008a39d7929a015,0x0005543ca7019543,0x00009dac0d6ff2a3}, {0x00049431bd9902dd,0x0008243c9a6f36ef,0x000314d8d81ff65b,0x000423dd900e14c6,0x00000a4a34591300}}, }, { /* digit=9 [{1,2,3,..,}]*([2^63]*G) */ {{0x000383af5664e7e2,0x000b6de6b7968a12,0x0009f4c5338a7675,0x000c15b898bae977,0x0000425a4bff82b8}, {0x00042e3b2dda3220,0x000b8c25241d990c,0x000f6aea17aabb56,0x0005ec6348df82e9,0x00006ce9658aa8d7}}, {{0x00002787f882d1b1,0x000092838067fd23,0x000e893587ab9dde,0x00080ecb05c101f9,0x0000374fdfb598bc}, {0x000b09697248eb9b,0x0007e7ad923f4c84,0x000109184ce9bdb8,0x00013b128cf5cebe,0x0000ec24ef3b3889}}, {{0x000944e7099b0bd8,0x000b1d537ca60adf,0x0008486e846852bf,0x00068d48e47fc8c7,0x00000d6c7de2929b}, {0x000987a8e27182cf,0x00074222fc3b99be,0x0007d0d1d309bede,0x00052f53cb0aad2d,0x0000f65f3dd24bca}}, {{0x00020afe823378bd,0x000482dc3af323ad,0x000605e6877ccdc1,0x000ae077795ffeb9,0x0000845b442d429d}, {0x000ff1016818e3da,0x00066b078681d060,0x00031508ce71189e,0x000e406443b1e66f,0x0000623d9847ce12}}, {{0x000cd6f7fd3f5519,0x00031e2aad87484a,0x00089654d2767308,0x0009ab132e31f05e,0x00006d3deb114a4e}, {0x000838481a653456,0x00035a31e914dead,0x000e292969158f5a,0x00028101fed010c0,0x000004a96f918ab8}}, {{0x000bdfb703ba17af,0x0002cc4c9c4a5470,0x000b10c4a0a49397,0x0009166a2be76243,0x00000e3312fbbc81}, {0x000e0d4441ca1098,0x0007c4cf80735a8e,0x000250bc8597d46c,0x000ae9d302662bb7,0x00000b98758a9150}}, {{0x00029cb244f2a00b,0x00002a5ca85559c2,0x0003d6204ed00e65,0x0003736e24ccaea9,0x00004d64bcfaa3e4}, {0x000b99a1975140f1,0x00011452dcfbdbb7,0x0003320cd47e6913,0x0008d1132c93a100,0x0000c845f62ed4f9}}, {{0x0007c03d7c90a692,0x000ff6139f403262,0x000a916341661a22,0x000a50f3c701c63f,0x0000fc4a23f87ab0}, {0x000307b826279712,0x00040ecc37944070,0x000d90e024f1cfb4,0x000986d684936aed,0x00008b59b0818a0a}}, {{0x0003cc56e8a58cfb,0x000ef645720b7ad2,0x0002b007e30ba2a1,0x000aa9db14cb4a09,0x0000d1f68b371a1c}, {0x000e1ce22bb53b31,0x000e06d532c443f4,0x000a47f15e80c1ce,0x0009bcc885a253d1,0x000061f7667f031a}}, {{0x0001ec094d82f598,0x000e76868c8fc9f8,0x0006eb6e2aa85998,0x000f863c0b776229,0x00009ebfbdd5d6cf}, {0x000c395d97adaf8f,0x0009b131054a3d02,0x000c908ef314a2c3,0x000dc1eabe4e52a9,0x0000074223caa8fa}}, {{0x000960a997f80b8f,0x0002574eeafbe347,0x00063a35458a6961,0x000959c7e7364dc5,0x0000b4cf05fd40e6}, {0x00049a6133af3f0b,0x000e62fe5ab6cc23,0x000fab20cf050c2f,0x000bba8ca2cf4997,0x0000e6736055bfbc}}, {{0x000ef812191ed798,0x000315e7a6df324a,0x0005ddb2427d462b,0x000068f036fe19e2,0x00006eb983703d74}, {0x0008114f4f93c566,0x000e92bd193d9efe,0x000ee2b5a701a0ba,0x00003dff40a1ad85,0x000032ba327506a3}}, {{0x000e85754a60d6f8,0x00078cd09cea9b87,0x000d99e0a120c995,0x0002e2c46af84652,0x0000cdebf2e2b109}, {0x00059f3155bc92d0,0x0008b8beca561249,0x000b156131d692d6,0x000046cab8309442,0x0000e1db93bb8bc3}}, {{0x00091e5ece80aac8,0x0004c050f1825938,0x0006020f5726a25c,0x000a35ec48344664,0x00007fd9893709dd}, {0x000c9bc10425f548,0x000d2a56bcbf5675,0x000da5191679c8a3,0x000303a7e6e78063,0x0000f14860aa1e8d}}, {{0x000bc50407ea0a28,0x00025007431b93e1,0x00055d0ffd5cf6dd,0x000aa71a55e8c0ac,0x0000f7f913113bea}, {0x000075d17988cb54,0x000b0f10950926bc,0x000b82f37b6b32bf,0x000e90e2937113ba,0x000081507f1a3652}}, {{0x0001af7dc8c1da8f,0x0006951c6c9cc65d,0x00013a9509e4508a,0x0005bfe1ccb78920,0x00009fd6a67c65bc}, {0x0007a0698fe8bfa1,0x0005330e47adbc82,0x0008c7bae1477953,0x000e2a4028e9aefe,0x0000e977aa9f875a}}, {{0x0003cf64d646bbcd,0x0000731b0f3ca569,0x000d322aebf578d1,0x0003eed7bffd65bc,0x000052a965205742}, {0x000bf947dfca9551,0x00086f7f3c853793,0x0007560c93ea9354,0x000c6925cdcceabd,0x00006d6f1ca191c5}}, {{0x0007f133182d35c5,0x0000458e49b6d3bf,0x000ddcb73784e7a6,0x000a6aac37769247,0x0000fb26f76fabcf}, {0x0001ec3853bf14c5,0x000e7aa2a072ab68,0x000d7447c7e088fe,0x0000ff4d93e78cd8,0x00009fe9f418ede6}}, {{0x000bd19d394d62fe,0x0008b38a0d8f64ab,0x000d938764136c16,0x000f4e72039b4ef6,0x0000849491679644}, {0x0009ba557055c06f,0x000dc7bdb007a9d4,0x000ba1745af2aec2,0x00015963a29318d7,0x00004187f01e40d3}}, {{0x0003790c271585da,0x000ed5ad056f666e,0x000ee31740b9f498,0x000f8992c64d1268,0x000057c0938d8ebd}, {0x000298e2374bea71,0x0009768daf973b0c,0x000a2d513284e305,0x000c9eaf3e9e5fe2,0x00001291b298bd83}}, {{0x00007ba27d3f2f53,0x0003b984e0b60811,0x0008eb875a3de64e,0x0004b33536bb951e,0x00007b9dec8b54be}, {0x00097920a0321af4,0x00038ad145d78b4c,0x000398b33b4205a3,0x000662f72f46d835,0x000081db115da0a1}}, {{0x000d732092e35463,0x000b86781f2b173c,0x0003cc924b3fdc2a,0x0000dd4011f8eec0,0x0000d8fea672cc8d}, {0x000be33d826c6f6a,0x000a55623182076b,0x000d30071e7711f0,0x0002af15f3579d49,0x00000e7e0ed76e1b}}, {{0x000d7abf4bb64eed,0x000c77dcee5b655c,0x000413063595edf1,0x0008c03bde3f3ddd,0x00008473cd3eaabc}, {0x00009fca27519070,0x0001a00dfd0763f0,0x00073571029941ca,0x000cb885e258bba0,0x00006ca17e26473d}}, {{0x000a5610e0e8924f,0x000ff65b0e50d4e0,0x000400c48de61d42,0x0003ab903b10a4ed,0x0000007b9332ca3a}, {0x000f94cac8105ccf,0x000774a0a98a0b7d,0x0006b6f26564134a,0x0001f89637e2a236,0x000050ac987f5af1}}, {{0x000a8d78638737d8,0x000c7cba5d96bf5f,0x000baf6465e23c9b,0x000bce6625837e83,0x00001f7b1951beb4}, {0x000cfde3643f8760,0x0007e0b1a62f4c1b,0x0009f918acc64067,0x000b46863c488c82,0x00007eeb70136714}}, {{0x00038b733005eaec,0x00069bc862a3754b,0x00082e20a6c7da3d,0x00057108fdec85db,0x000022986577100b}, {0x00050a08db1555eb,0x00042a9d5da8256d,0x000025309b01beb5,0x000ddfa119befeff,0x0000030fdcce76ca}}, {{0x0005d057caacf707,0x0003d6856c44b3cf,0x000bb66402bb6e67,0x0005d6fcf6d21aa4,0x000073ffa1ebc9a8}, {0x0007b52ffeaf8928,0x000b35e49a37db24,0x00070c9914f1e14d,0x0001ec5174b1f793,0x000068dbdc6a0007}}, {{0x0002077a6effe60c,0x000e9ae84ebb9b28,0x000a90020b39c7e9,0x000c72996fc825a4,0x00009d2dd8f89811}, {0x000de4719ce198b8,0x0002073bd8ffd842,0x00091284580c3d61,0x0001c29d754578eb,0x0000e5723eaf004a}}, {{0x000ea43768534f8b,0x00051abc588d36b7,0x00095d1fc7b73df0,0x00059713790bd820,0x00009bab617eb6a4}, {0x000918138f1334ab,0x000287a8ecff86f3,0x0007dc27cafd58e0,0x00090f2bea43a4a5,0x0000876309bff8e0}}, {{0x00040a23110d738d,0x000d4d107a0cd20e,0x000fdfb6a9c754af,0x000106b9828ccb2c,0x000019c605440704}, {0x00026be98b9211c5,0x000da44d15bd9119,0x000db2afb42c11b6,0x000ef7dcddaea218,0x000006a2d4b20f0a}}, {{0x0001358309571482,0x0001812df972a300,0x000a8cab38d53d41,0x00080cc32e21acfa,0x0000e6a672ed9fd1}, {0x000d45c4e36faaca,0x000be60297f9cf33,0x00070c34df7f4d7f,0x00001dcb91ebe024,0x0000d911f768257a}}, {{0x0007255a2e0c5dd5,0x000d22bbbf673853,0x000ab32207a670b8,0x0008fe78ebe9b99c,0x0000fdde390be12b}, {0x000115f1b1cf88b4,0x000fc8cd1c7f9323,0x00039787a00aa2bd,0x00052384bc65bc2a,0x0000b21156bb8e1d}}, {{0x0007c6bedf5eb992,0x000ccfb71e9c6a08,0x000a23eae9cb1f72,0x0007b145f4b20c36,0x0000cdd6cd364c1c}, {0x0002b96009e153bf,0x0000791667fd4b16,0x0006d6b0e682b36d,0x000dce91c1e9f97c,0x0000b3acb50ee02e}}, {{0x000ffd490f51cbae,0x00013a606f79d85e,0x0009bf4dbe0ae081,0x000c1de9ba256a47,0x000044c5bde85698}, {0x0003bc53c7a38530,0x000bb62a6e6e5c80,0x000103b8eb6cc532,0x000dc7a5791e202a,0x0000707bc1728e28}}, {{0x0000b00ef08771e0,0x0001e0a13ee687b0,0x0001b533b57773fb,0x0009a5ccaa4259f9,0x0000b79966f77917}, {0x0003e85beb00e9ce,0x000df3ff0394ced9,0x000c6bf70673db5a,0x0003f1d646c1a702,0x00007ad3795a15d2}}, {{0x0009e4bc97bc7da4,0x000771d5ff2a522f,0x000985f8205c96c1,0x000f2cc4eaadd196,0x00002c57d9e6d752}, {0x000d1929233b3620,0x000e75373d1e4ac7,0x000b30d44f4b9421,0x0007bf6bda441140,0x0000bfb154cbcad3}}, {{0x00070a4205b81469,0x0009a9885929e3d4,0x000ad5364994946f,0x000dfb6f3fb7423e,0x000003c1097c2e3a}, {0x000dc4ea3c0c73f6,0x0000a781ef8a533b,0x0008fa9cfdfb0cba,0x0000a169994d9edc,0x00004caf3b9da044}}, {{0x0007bff77c009156,0x000b45f526c72d31,0x0009ca544fe44325,0x000af0abe60485f3,0x0000d0555feb6700}, {0x0009417bc4ccc145,0x0008e6c415362ec1,0x000df5ddfbceb3a1,0x000947ada3efdb22,0x00000c675f6c474d}}, {{0x0001b02ff106393d,0x0009ab788c98851e,0x0004e8fd1bb09653,0x000a43a2d782d5da,0x00008c9f428680c1}, {0x000ad17045780bde,0x0001b95cdcc517cc,0x00061b333987fc28,0x00047c5787ae170a,0x0000f427985ca04d}}, {{0x0008761292146075,0x000a0cf3aec278b9,0x000329f90f12cd22,0x000d72cb478d1718,0x000082d33765d490}, {0x000d6264ebe63b58,0x000388509017bfc0,0x00049f0b28500032,0x00044eb2df475953,0x000023dc015fc527}}, {{0x0001a099d4037afa,0x000c7d2a4f51d503,0x0000b909ab658722,0x0002f75dc1387e94,0x000054c7cceb78bd}, {0x00084d3f96fe1299,0x00029004be5e603f,0x0009034366d312d5,0x00042265d0b7585f,0x00003b342c682c11}}, {{0x000abe562108741f,0x00090edafcb0db97,0x00050a1e77625189,0x000612928f4ef0b5,0x000028436f533db9}, {0x00066a445e95a984,0x00061b7395817080,0x0008a14b66b45ca8,0x000fda5f298d70b3,0x00009d4a0366568d}}, {{0x00099ff0ea5b0fba,0x000aa38e73001b62,0x00067dc4c57987d3,0x0006d5467cc55ce3,0x000040e6da53b93b}, {0x0009e490c345dc3c,0x00054155af276568,0x0009f77de77c956b,0x00064f912443ecdb,0x000013d1f2e35d2f}}, {{0x00069dc8827b81ba,0x000ff2e3d5a36319,0x000f13ca81af30b3,0x000d3db2c866e0bb,0x00001728b7fa6e1d}, {0x0006d11ba4e53cde,0x0008c3f44d47dc80,0x000de776c71aa9a6,0x000377d5cb45efd5,0x000001fc46a09355}}, {{0x000b7f02f609bf48,0x000d851c333890b5,0x0009646d5de532e0,0x00050dd82571cd4d,0x0000381d38f402a4}, {0x000a13f8fe5abf74,0x000e980cfbe80cee,0x000d8244e4e987e1,0x0002547265bb3560,0x00003bb71799807c}}, {{0x000711e9d0717f73,0x00098bcbfceb725e,0x000af2faf4e210f9,0x000aaffcf4b3dad3,0x00001d7b1680a432}, {0x000a9fc79b356741,0x0009b13d5198f7a8,0x000714c9efebfbdc,0x000e9183ee381471,0x00008113de151b1d}}, {{0x000b068e8dac101f,0x00082a77a77808b1,0x0005fe83ee2d68db,0x0009cd82fcc849c8,0x0000ced2c5678a6b}, {0x0002eaa12ebbd351,0x0006fe07a1b126f4,0x000c1b353de97cf6,0x000303776ab40f94,0x000029ea20475cdb}}, {{0x0001c2d1586be5b9,0x000cc911b89d6385,0x00075acf780e9258,0x0000604f7cd421d7,0x0000cadd878a2dad}, {0x000218369356e650,0x0001634ebb7f5e99,0x000cda3a8202c34c,0x000abf90720028f5,0x0000fd4e963d3750}}, {{0x0000f0db1730827b,0x000d644fc900fdd6,0x00037410dd37db24,0x000309b2d883f43c,0x00003acdbdd5534d}, {0x000703eac7e1a004,0x00004f5796e43be6,0x0008988176129b8d,0x00003dd7ccc20dde,0x00003c8ca33f4853}}, {{0x000d0c1c7047f195,0x0002fc7ed2afa267,0x00088562adc95dd6,0x000098dd5add39ac,0x000066c878035e61}, {0x0004fefb47537004,0x000a5a743ef55e47,0x00047591d972f249,0x0009adda486006ed,0x00007c2df25f0a81}}, {{0x00056ba80ce1e1cc,0x000e67cf1faba833,0x00089e7a051528a4,0x000c6753125898cd,0x0000607dcedb32bc}, {0x0009d23e8c6cd3f2,0x000ffcb09ace85e4,0x000b7d6c1505f623,0x000df6e74aae2597,0x0000001f7693e568}}, {{0x0002f4fb58a08ff9,0x000b22b767ddd77a,0x00020e33dc68c924,0x0007b51b436b1d3d,0x000015859ad34f0d}, {0x000bb551c67e100c,0x00072572c5dcce84,0x000057987a70e414,0x0002b07c8616056a,0x0000bd0d7de543e1}}, {{0x00091ff11bfcf2c7,0x000d9646c09265fc,0x0000510cfe52d918,0x0008aa8cca65d05a,0x00007afc5385da20}, {0x0005903d91d0fa38,0x00048cd25652dd29,0x000688d81a6042f6,0x0009e3be9a92ed90,0x00005df7150a5df5}}, {{0x000edbae38271e0a,0x0008b5cc06bce54a,0x0001bfd7a369474c,0x000e44e3c9d39cd5,0x0000e2bf2cdfd46d}, {0x00082c92389f1ca3,0x0005c88dcb5d5b81,0x000a825a0e26bc70,0x00005671cf4bee96,0x00000b65e1f6a6a6}}, {{0x000a928368d1a456,0x0000e11cb329d7af,0x00041e0414116b46,0x000a28451a71e385,0x000027ce6313e7a8}, {0x000e5e5782687675,0x000f0685af014510,0x000d3b826aac14a7,0x000bdffd100fad1e,0x000080ca2ea3195d}}, {{0x000a01041994c103,0x000f47a314e14992,0x00008ef0842886db,0x000927a87388d695,0x0000b98c4ff30fce}, {0x00097d3fcc147238,0x000a8c29c45c7e2f,0x000f67220c5a2e9c,0x00037e0bd4619da3,0x0000189f33c99079}}, {{0x0006fce6fd4eb1d2,0x00096d33c1253a1c,0x000e10ffc8333657,0x0002c4acbc619c17,0x00003e3f4c29d31b}, {0x00042a47b0149578,0x000ebc09d858af7b,0x000c49e700d501cc,0x000b440ce075301f,0x0000f231d5f803e1}}, {{0x000ef3caffa4bdec,0x0002ac777c54035b,0x0003cd0bc68eba77,0x00045b2505bebe91,0x0000e4644ce7cd8b}, {0x00042777579dea15,0x000298fca9661f18,0x000590619d9f2264,0x00054720eabbb3fc,0x0000e6455a9be8fb}}, {{0x000a577c0e475eea,0x000d6bc1436c96d9,0x00016236e94d021e,0x00008c00a8850a9b,0x00004b2d015d7f50}, {0x000c9dc4c6f4a38c,0x00028553656de8a8,0x000a90c362732682,0x0002bf3d15dd9142,0x000052c5e5dfbb42}}, {{0x0000cbe5411c8dfd,0x0008a17b7a24b8c2,0x000b9b87fd8cb545,0x0005e6a11f9fc178,0x00006c1feb2d790c}, {0x000c58e0b0881f88,0x0003c321556f92f3,0x000a34013603d060,0x000d70aff166a927,0x0000d99e1e8e4319}}, {{0x00020a329430fd34,0x00091b753e241ff6,0x000dc9b1f4a806fc,0x000873c09454c63f,0x000053aade33de2d}, {0x000c8ed7cf2adaa3,0x0009418f8a188df3,0x000e4faf13fb7d84,0x000bef84861cf96d,0x0000860acea4d6d0}}, {{0x0001d18705dde70a,0x00011272a18859a9,0x00033f5014638a28,0x0009304080653c0b,0x00008c599a15b5b1}, {0x0001a5a4482a49b3,0x00092f456786cb4c,0x00064ba9b7822d73,0x00018755a97a72d7,0x0000b095c5fcf342}}, {{0x00068b2d8952a5dc,0x0001384c32454373,0x0001e2922c3926d4,0x000aa3dca16b1fa7,0x000037a2bd72600f}, {0x0000a741ebdedfbf,0x000e23ed58f44104,0x0007baa3fe459532,0x00006a13286a4d62,0x00000256f65a8e61}}, {{0x0009fdf904d40a4c,0x000a46face48942e,0x00021d60e882feb0,0x000dd0396add6456,0x0000900d2cd7fcc5}, {0x000a7b9be3cfc441,0x0003708a50df4de0,0x00082f25a62b3146,0x0008d616896ec237,0x0000efc52dd341af}}, }, { /* digit=10 [{1,2,3,..,}]*([2^70]*G) */ {{0x00074cd669b25cd3,0x00058c67881c256b,0x000c2d070504e035,0x000ce9e47e328af1,0x0000334f9064ef41}, {0x000e26a1c2dcf305,0x0006722062f65cf3,0x000d10bc4005653d,0x000d490fca65ad22,0x000019179d890699}}, {{0x00026e7838ac11e5,0x000e2a5a280f9fc4,0x0004127710bbdb6c,0x000c0919081aeb17,0x00009d3642b34a2e}, {0x0002ad9a69ff2662,0x000684c317570d7d,0x00000f6f3f188512,0x0005163b33b1c24b,0x0000d7b1d0e34234}}, {{0x0009ff3fb1c1c89c,0x0005aabccb1a5742,0x0002d53a4eef7623,0x000053470aedff2d,0x00002e085185e01f}, {0x0003bc9f5fe3ea55,0x000e66ca1fc53dfa,0x000605f7ffc83fe6,0x000716623aa4d317,0x0000f64c0b56ddf9}}, {{0x000674732b26ecaa,0x0006a9b93619c51b,0x0000bd8947d766ea,0x000f1f8da8cf9566,0x000039fdfa96c371}, {0x0008371eaa4eb5cf,0x000f1c2fe16a83bd,0x0006b6beb3c7b8ee,0x0003dfb56c848ff3,0x0000baf4cad5a849}}, {{0x000b862c0fdd559d,0x0003472c11580706,0x0008b856520b2638,0x0006879e81a90197,0x000029294aa97e5e}, {0x0001e0f85a0008ae,0x000842f061b6095f,0x000af5f1784d787b,0x000532b513ddfaa0,0x000056317941cc65}}, {{0x000d1d3a33d19d98,0x000d7df2ca8dcb4f,0x0007f4e6b5456b29,0x000f5ae912a132ae,0x00000f2c9a6887a5}, {0x000e27431535c2c9,0x00023aba1f2ffbd4,0x00049250f22df234,0x000935fba35d186e,0x0000929b2503d242}}, {{0x000c9391c1b57c4b,0x000d954532e6f2ad,0x0004d08859d320c1,0x0004f4b4c12b6234,0x0000d868d83b4346}, {0x0000ea15c6c613ad,0x000238397325f0de,0x0000c2f9dc73b139,0x0004b7db504ce64c,0x0000dc963c4af5aa}}, {{0x0005e02dca527597,0x000576587c548e0b,0x000cc2767c475cfc,0x000859476ce6a9bd,0x0000665715a85b0c}, {0x000b469bab32bb4d,0x000d0b6de7c31b91,0x0002327265da0fa4,0x00047cf1f57b245a,0x00006cda9501707b}}, {{0x0008d572808b4fc0,0x00011694ede0e70b,0x000f8b71405a8e19,0x00015233c02d5353,0x0000ab4ce2e44ab2}, {0x000c47dfd222e80b,0x0008cc293dda614c,0x0002292f07c1d085,0x0006cbfeae2c20e7,0x000061ec173fa523}}, {{0x000876bc63806f07,0x00024d66914b313a,0x0008170d851534d4,0x000b76faa20f3de5,0x0000aab05f61a766}, {0x000664f3ab471d0d,0x00011fdc64a701f2,0x000ea68223acb6e7,0x00013a23fabc7bb1,0x000090227c181a7d}}, {{0x000ce1496c8edd99,0x000b6594d679e5a6,0x0002b74d6e54b8ba,0x0003a13ee780ee06,0x00000955d9961a01}, {0x000cd19a119ac211,0x00082f7e73061c51,0x0007bf37a3de8103,0x0005363b406e5945,0x00006f8f87f664ee}}, {{0x000815967b132401,0x00064ecccb2576eb,0x0005d3b7d625290b,0x000ec5d6f358953e,0x0000a5226a7375ae}, {0x000abb11ef347a92,0x0007143ccb0f7b41,0x000c82f4ddf3c9db,0x0000dfd73dd924bb,0x000087da47b38012}}, {{0x000aa601588458f9,0x0000975e5cf241d9,0x00060b80ec71bf1f,0x00029fcc1fb01f45,0x0000823f9d230d8f}, {0x000657c67a86fd8d,0x00034e709b0f413d,0x000642ec3286cfe5,0x000ba7caac701a18,0x0000fa3bb61f6852}}, {{0x000801b0303fe8c1,0x000fbe0cde9a2307,0x000713051354d6fb,0x0006e735aff62229,0x000025ef6c00b818}, {0x000306588dd6cb80,0x000a99185c90f436,0x000ae928b4ff1484,0x0000b1c883be31ae,0x0000a9c05acf7be6}}, {{0x000b28128cceb413,0x00082eab515e529c,0x000d8b8e887dd9a3,0x0002d5b9d67b20e6,0x00008b59180e89cb}, {0x00059e2abcbade3b,0x0006184d19e316ec,0x00044d27ee72fc4a,0x000c67731c05e18c,0x0000a8c4db3ec2d5}}, {{0x00048bb35989f3d6,0x0009b3067fb4c320,0x0001a0ffbcfe88ff,0x000004e03be2c82f,0x0000fcbfa01af932}, {0x000f814e7e4cf8e6,0x00024ee9f240c53f,0x00086fc0004f7b88,0x0000ac34de98e74d,0x00007917ef356057}}, {{0x000c6c4a11a11477,0x000d8b1cf6d0d720,0x000694efa1c1285e,0x000e0c1350e984be,0x000078cb9118b03f}, {0x000bf89c99dbbb29,0x0004fbfdfc88574b,0x000eee84278a2c53,0x0008ff0a649b25e5,0x00003d025e893279}}, {{0x00037a391d54688c,0x000c7c592115f719,0x0007653bbcda0dcf,0x000a69f5817c7617,0x000029a05f07e803}, {0x000753fad30733d0,0x00072bd1849daff3,0x0002fca30fa2fd8a,0x0007feecaa47e99b,0x0000b0731727e7c5}}, {{0x0005a21b38ecce44,0x0006e415c2abd742,0x0002c0e950133c0d,0x00000ea72b809264,0x00003015ecb9ba58}, {0x000360d2878775ae,0x000bc41c8e4f6d21,0x0003c10aa67f95a8,0x000900e292f6829e,0x0000a4ee43081d92}}, {{0x000fe9693df562e6,0x0002fad17b8b0aa9,0x0003de3c362eb368,0x000d534ef25783ce,0x0000ebda4537f429}, {0x0003627aba553bd5,0x00097af716fc435e,0x00095a844547dbf0,0x00093eb262399131,0x0000588e07a230c3}}, {{0x000af60d3202fb41,0x0004c8c7c74a1d4e,0x0009e5b39057f717,0x000f7cf49850c859,0x00008d151014d7b0}, {0x0008fa60b07a5144,0x000d9ab459ce85f3,0x00097edc90f40721,0x0000fbad27012797,0x00005754882b9450}}, {{0x000dbfc225b16955,0x000deb78b51638a3,0x000458d99f09b93c,0x00061e32d72821e7,0x0000340498c56d86}, {0x0004bf05323cf76a,0x0002ff7ffc746f1f,0x0007d6ce5b44bb0a,0x000c88717795b069,0x000004ab2bd3e89f}}, {{0x000605a2ca22e4c3,0x0008ac2d7351ad97,0x000eab2e88f2760d,0x00021fc887db7e2e,0x000029bc5ec3ebf3}, {0x00086560b7317f55,0x0004d18b91ce9d01,0x000b6f646f4fb8e4,0x0002a1695833078c,0x0000d6a694f08f66}}, {{0x000c95e3b72c81be,0x000e8a03275a6b4a,0x000d6b09aa4f69a1,0x0002be1ee61ad29f,0x00002844ca4e17dd}, {0x000e76f8794eee2d,0x00087cd0bdb33924,0x00040e3f2ddfa70f,0x00072fa4a906265c,0x0000b96580f51259}}, {{0x000023b688cad9cb,0x00076df8951487ec,0x00010c9cdd6ac550,0x000ae554e43a52b9,0x0000fef35226f5fe}, {0x000cbe7fdb2ed39f,0x000a0a5e1bf9b554,0x0009afefe7699601,0x000c50b5d7563445,0x0000010fb3404117}}, {{0x000279f9137ac6ab,0x000249953bb50af7,0x0000826f6345477d,0x000865968a387bb2,0x000005a5cf531199}, {0x000c5268a915e259,0x0009720c4f4b65a7,0x000b7b99cd26125c,0x00058b59772469f6,0x0000853ae820ffe3}}, {{0x0006b4b6ec89e3e9,0x000333d0ff1c8c17,0x00059b5dc3204606,0x0005662b172727c1,0x000080e1bebb1c71}, {0x00018894c4864ef8,0x000a9eca02e2c6e8,0x000cab3d09dad501,0x00060af51c7c848e,0x000047e4fa35bc16}}, {{0x000570befacb28ea,0x0008743dc8f455c5,0x000f40096cf59c5c,0x0004b182c494694d,0x00003c0fc958c313}, {0x0003107f39793424,0x0000cce996b712e9,0x0000246006fd67c3,0x0007be905a6fad26,0x0000fbfc527a687c}}, {{0x00095e1c222ce3ef,0x0005747315cd6f47,0x000423b7afe75d5e,0x00019bbc54314d23,0x0000ef8b8f77d09c}, {0x000803127214c810,0x00015ffb94e2fbe1,0x0006d06ac1164fef,0x000f30476727cb12,0x0000a8113857ebf7}}, {{0x00087efddf19eaed,0x000e96b6e5f5f6d7,0x000ece472e89ecf0,0x000c927cc82cb9ae,0x00000feebacc040c}, {0x00099970ce1340b7,0x00074081fa310631,0x000f300ce340cba2,0x000a1055a8739566,0x0000fa0cef064603}}, {{0x000082c59b5bc93f,0x000b65fc16a6d50a,0x0004bee2ba80b4cf,0x00016533174cf7dd,0x00006aceb571e5f7}, {0x000006d350847cb5,0x0008616d7f8911a7,0x0008b0f735565146,0x000122795d2872d6,0x00007b8ca3d3efb5}}, {{0x0000a88e8800df98,0x00025448903b908a,0x0004349a5a375804,0x0005b13ac924efa4,0x0000a5e450fd59f3}, {0x000055716f999f92,0x000de9af288dca33,0x00069f12c2367b4d,0x000284d0897fc5ab,0x00004fc4fac80274}}, {{0x000eb7eb35f2a934,0x000d353268becc03,0x0000a4174b282d2d,0x000f5ddd6356402d,0x0000e7ffa1bdee1a}, {0x000aaa4d2ca7e708,0x000704fc0f9760eb,0x000357060cd33f91,0x000d81e7eb1971de,0x00003d746cad3a0a}}, {{0x0005e0ddb5450c74,0x0002a674a2e0aec2,0x000bc7d3441bdd25,0x00079a58f6e1b7da,0x00001d2cad53a42d}, {0x00076a79d2639d68,0x0003f32fc3bfb513,0x0002bfdf25a3776e,0x0005d91a51232583,0x00009aba866b1079}}, {{0x0001534fdb96049f,0x000d73c129cc545a,0x000caf544a6dce8e,0x000d95f07d61f6ae,0x0000dcef4f010d17}, {0x0003b9847259e03f,0x000e08eaf94b5a31,0x0000a320a3862f66,0x000f35bfb4c3fc13,0x00003ce88af25ac5}}, {{0x00084f5111ed5705,0x000b79be0976a8d9,0x0009ab22e7a6498e,0x000cda52cf1ba030,0x000013d88452929f}, {0x0006f21a33ad72d6,0x000e27b4947e3ec9,0x0000022021b0fa2a,0x0009c5f35557b5e4,0x0000f01ef8814f2f}}, {{0x000c2442542799ce,0x000f9b3064143739,0x000f1d943ee0b9f4,0x000e26265a704416,0x0000e87d46c8a352}, {0x000a8e3615322bd7,0x0008190d24dbc6d6,0x0003d81377ed07b0,0x00056a2a112749e9,0x000094697b190dce}}, {{0x0004cf425219eac2,0x0002cb6fb9207e1b,0x000cc82f73e79b1e,0x00073ae27f3c4a54,0x0000554f3a88ed84}, {0x0006de42a1700f2e,0x00006f9c40687f07,0x00093ba557a83e9c,0x0000a11fbe078a85,0x0000e7643032099a}}, {{0x000f9abfe9907a6c,0x0007cc63f2dfda1c,0x000bac69ee3043cc,0x00041648aa637938,0x0000bbada2c4f2c0}, {0x0001495c9e6f03da,0x000fb7b4eda11e13,0x000b4954affd78b1,0x0009d34c115f6b0b,0x00000db881c07854}}, {{0x00029e61ad8613f5,0x000c9ddb326c11c4,0x000869e2813f8b2e,0x0000b0117db8ee3a,0x0000dda75e5f5ffb}, {0x00073327c49cc58a,0x000d0c3da6be20e6,0x00070dd5c65cada3,0x000ef461959c8261,0x0000fa5cb2cf4faa}}, {{0x000e000a34fd0c8a,0x00058901bb98ca77,0x0006eb2905cd2973,0x0003336dda93946a,0x0000934ccf97e513}, {0x000c1d692b201b8a,0x000f029af6321234,0x0008d9dfac9c7c2b,0x000f582d8679e67a,0x00008046ce69fc1a}}, {{0x000ab8eb6e0336a9,0x0006ea229cba0232,0x000dedbcad54fcf3,0x000667a7a0cc9245,0x00000a2c42237703}, {0x000b601fbb80bfde,0x000a2c63fd8939e8,0x00049e20428365e9,0x0007aca1417dd6d7,0x00003f11af7e1f8b}}, {{0x0002330b4c09a0de,0x000902a37b9c9a53,0x00036cda4e95cf6e,0x0005ec789015573d,0x000029deb51579af}, {0x00020a37b9ea8e07,0x000799397a517f13,0x000557b7511fa4f0,0x0004370b092cc886,0x00004fe2aea14013}}, {{0x000b5c6a9db98dcc,0x000dd04a3aba71dd,0x0006608f14057254,0x0006b8b756359d19,0x0000c4455860c9f8}, {0x000a2e774f5cc99b,0x000300a46307126b,0x000302ddbaa681cb,0x000535fc96dbf608,0x0000c681d0076c06}}, {{0x0004d84c9e62370a,0x000a69eb6fa1f9bb,0x0000ef588241feb6,0x000245740d6249c1,0x0000be2d5006f181}, {0x00041f73dee49528,0x000c00da95bad9d3,0x0000e049a1eb457a,0x0001bbb11190a486,0x0000110d97c60ffd}}, {{0x0009877303f6c251,0x000a1c17dc10f282,0x000bb8dca73e7560,0x000a683b3ec4fd74,0x0000a9f75e1bb560}, {0x000919d9da696d60,0x000d217fedcd3ac2,0x0006adcd9d53df79,0x000215470c8bf19e,0x0000b0f430bfb8a1}}, {{0x0004ec0bc6dcdfa8,0x00046693c98632a8,0x000bba59e9150cd8,0x00022c245639b8fc,0x00003d4bb7590c93}, {0x0004d6a04c6abc20,0x00066201cd556fb0,0x0001e5e4afc3d001,0x000ae07774cab315,0x00003d6c82521fe2}}, {{0x000c32cbecb96f49,0x000a3005ab64ddcf,0x000baf06df924953,0x0005e8ae7d321d49,0x0000b2d331a8c32b}, {0x000d67cb123fdcbb,0x00088a617dcd4f59,0x000e94c2e5129661,0x0008ad46352e5f1a,0x0000d5565de6b48f}}, {{0x000e6659b3560d39,0x000ffa229f90747e,0x00023180522e466d,0x0004d6c4a3f828c0,0x0000e455d80ec3ff}, {0x000e2eebf20d3aec,0x000c736f73d855fb,0x0002184b7e5febc1,0x000b11155c63fc28,0x0000a428c274cade}}, {{0x0001c636e5373dbe,0x00086eb6f714bd17,0x000e1b6a90d860ea,0x00060dc93cbac42b,0x0000d34c45c4c0f5}, {0x000659cadd09b1eb,0x000ccdb20e3300d0,0x000141729d71e84b,0x00060e782510dc77,0x0000ec0565e653b0}}, {{0x0009e4d6e92f36d7,0x000825cbda73f299,0x000665eeb18db8b5,0x00018f9cfee6e9a6,0x0000ca23779281ee}, {0x0005db4b1418ca14,0x00024447b1c7f54f,0x0004f104fcae5744,0x00000ab06a6080e1,0x00001054c45b9651}}, {{0x00055d5f2446ec83,0x000467a9ebe2680a,0x000c77fc1761cda9,0x0005aa015446cd46,0x00001c27acc7da7f}, {0x00077703a89b1b78,0x000cd191b9b97518,0x00013cfd2ff9eac2,0x000e94ceb77c72d1,0x0000fb9cf6eb1afc}}, {{0x000c0193744cd46e,0x0008b3ceea178d94,0x00014a628cfe494b,0x0009d6820be8421f,0x000094afe6f01bc6}, {0x000e28b4eda452b7,0x000538785cad4748,0x00037da88fc3c7e7,0x0009fc488a0a24ad,0x0000cc96f2897d92}}, {{0x000f9f92b892fabe,0x000e8fb2e6bf1cfd,0x00099f05d11cf6a7,0x000c3b1597b79e80,0x0000a26740afb0a3}, {0x0003b35d8b31a83f,0x000396846e25cbc8,0x00082f6f006b2f50,0x000a658d89e03e35,0x0000db716db3d591}}, {{0x000d177e1fa4ed0a,0x000dd5607e4daf0e,0x000573a2cc2358b6,0x0002b7ee7eca899a,0x00003a1628589e78}, {0x000f908d149527d0,0x0002262175b94b20,0x00013e200c0bcd10,0x0003975b06898fb3,0x00008491f71c53a0}}, {{0x0002d700f31b0e00,0x00019237b591c539,0x0009fe9bccb246e6,0x000017bf39be6432,0x000028e4046f6380}, {0x00046c9c0d21521f,0x000fd73f252bbf1a,0x00043fdf02581ac2,0x000babf43b3c4272,0x00001a5ee9169a81}}, {{0x000e5448aa1f7350,0x000f3edd6264a716,0x000253daee2205fe,0x000b4e7addb5be46,0x000055192f8f04cf}, {0x000b2643882ff890,0x000c409401a9d5ae,0x000413e0c8a16ec1,0x0002f7f8a4fe486c,0x000089973c8ecdb6}}, {{0x000af3487f6b18cd,0x0008a3d07d2ec763,0x0000e5a1521e2961,0x000427104e65b30c,0x0000bdacad3f1ac8}, {0x000145358f37a6dd,0x000d004a44da735c,0x0009eebe68dd299b,0x0006b05a62c5ac63,0x00000ac76876f8b1}}, {{0x0008acf5a8209bcb,0x000560df7a62c194,0x000c1fb14acfeda4,0x000df2c2224f5fad,0x00003404df8d5798}, {0x0009a77b70e54968,0x000520108a2364b0,0x00015fccaf6ebdf0,0x000566e36cd047b8,0x00005e46d74586d1}}, {{0x000844d8e8ce5587,0x00092279b1356b90,0x00091add341ad4ae,0x000a7d2fa10f0f42,0x0000148c77380f8c}, {0x000496d6691d4cc8,0x000782bb8243fd56,0x000627db185c1156,0x000a5418645f44bd,0x0000d506007bdf79}}, {{0x0000bd279fead68e,0x00056182e4e75be9,0x000dd1b6509c30b6,0x000ed8c47b692128,0x0000f5fe87abfda7}, {0x0003143dc3675e1a,0x000c502b0a119eb5,0x0004fe0aff458d3c,0x000a31f46a7b233d,0x00005acb343f0376}}, {{0x0002d15eee0e0d34,0x0003d148684f5225,0x000cdbe9722216f4,0x000c5cce42f45a7d,0x0000e205d19ad51e}, {0x0000f64c68b5fa7c,0x000058e30f053866,0x000a6c9cb5f06a10,0x000f6f5287fecaf3,0x00001883d276db11}}, {{0x000527672331c67e,0x000a87a64576176e,0x000c391a5c3662b4,0x0006c076cdba095c,0x0000f9220fdeba1e}, {0x000ccfc868b90cca,0x0008290a8b4bca9a,0x0000e92873faa03c,0x0009492e8d17378b,0x0000a47f8c64e176}}, {{0x00028cb6de5ee8de,0x000cd5efcb0928d3,0x00077e0ccf78a9c3,0x0001c402efb29bef,0x0000459ba0ccaa24}, {0x00015eff8dc3bb71,0x0001926d930b21d2,0x000c2f8d6a0caf81,0x000f17b13725955f,0x00005d65bf7dfab7}}, }, { /* digit=11 [{1,2,3,..,}]*([2^77]*G) */ {{0x000f9aa8775da137,0x000593a6332e3942,0x000acdfba04c12e0,0x00036116cc38b202,0x00008a8960a21793}, {0x0002d21251bfcee2,0x000d5d5e4ebe7fd4,0x000ecd2b4f06757e,0x0004179312209cb9,0x0000116a47ce63c7}}, {{0x000fff36dfdd5049,0x000f7ce6110d0407,0x00098a9fc7cb9e1f,0x000926e424e2d9ea,0x0000835121b0ef1b}, {0x000d9bfa74da96b0,0x0002cd0f068f3fbe,0x000fb3442f781253,0x00047bf2a224f7f4,0x00003b3786a0183b}}, {{0x000297122b1f3105,0x000638dba8324c9a,0x0007684493f6706f,0x0006825bd6946011,0x0000954fb43f082f}, {0x0009146aaba29f01,0x0004e9c6324aadf7,0x0008d8428f5d9954,0x00015d922efe9529,0x0000d292e4285a89}}, {{0x000eda370bf670ce,0x000eff959124f0b7,0x000cac220c098413,0x000042e12faaaa26,0x0000895133539985}, {0x000e3efc5819a77d,0x00057c57c1941637,0x000d0cc10c5d3a74,0x0002ffae97c4601b,0x0000cc0b9439604c}}, {{0x000eebc15ab85274,0x00019d13c980241c,0x0003a82e05366ff3,0x000eab4894fa90a8,0x0000f875d5053ef5}, {0x000f960988cc3ea5,0x000ead66986792b7,0x0002473220ad7ea6,0x000afad402fea6ab,0x0000112495728583}}, {{0x000f4636a79fb44b,0x00090857f24b3d06,0x0000bd52a5b7cd91,0x00064839569b4ec8,0x0000d1b1ac7d83e4}, {0x000a69c7aac7f865,0x0006f8fb84cd4b3a,0x000b5e37812c149e,0x00091eb184db0903,0x000048acff136f66}}, {{0x0001299f5efe435e,0x000b7f1400ac2880,0x00059719edb65124,0x000c51a678fab01d,0x0000165002ee9aa8}, {0x000bbf3f226f941d,0x00011de495d3deba,0x0007d94842b6a345,0x0003d2d9919c7098,0x00000d6590e37520}}, {{0x0004ee9ebab5f9c3,0x000ee5aa2862cfa0,0x0000825883683453,0x0005a0745585d074,0x00009825b8191988}, {0x000e1d078fb65329,0x00028cc58f8e9d76,0x000caa6ecd94a45d,0x000e336d0acf4acd,0x0000622e82ce2bfc}}, {{0x000008a44a2706aa,0x00041b1add588771,0x0007569a605cb923,0x000def6163a01430,0x0000a568614fb2eb}, {0x000f81a9ffce874d,0x0004c0a48585c4da,0x000233e6225a5f0a,0x000d30ea80e24f54,0x000012a0f8a98988}}, {{0x000b7355cdc2f284,0x000d2a27b9adaef6,0x00093f3b59e1ed0c,0x000b746910956189,0x0000c77d5df71c8b}, {0x0001803652237193,0x000739b9537fbfa5,0x000a62d938c3a3e5,0x00058e9ebd4a1293,0x00008b4fbeec3446}}, {{0x00052179751d0b7d,0x0000f901f8a82fe0,0x000136ce503fb389,0x000dba5498f02145,0x0000cb7cf9a661f9}, {0x0007016c2992806e,0x0001add3eb9fc4a7,0x000307dc5f99dbd8,0x0004c304da7f5ed0,0x00006fb20bdf58fc}}, {{0x000325b563f62c26,0x00088e338763fd2e,0x00070b882d81d583,0x00086a60eec0789c,0x00000900a5d21f5d}, {0x000b2fb282b41ea8,0x00039ddb91517ee8,0x000f77556d931d68,0x000bf902f126e703,0x0000b19f00d7d3a7}}, {{0x000110e849fc28b5,0x000b011096883b49,0x0007657f512d21a5,0x00011f76afc44bf5,0x0000746d7f32aaff}, {0x000037a74dc795a3,0x0002395a1c198937,0x000a8ef1664ed39e,0x000c26cdb84ee945,0x0000696b907f6d28}}, {{0x0009d6f7600276fa,0x0006d3198ab29dd7,0x0005cb1d12f3e169,0x000f3329a912fc79,0x000030c403e7632d}, {0x0005a8f5ede17ddb,0x000859c12cf6284f,0x000881ae76605fac,0x0003ae8ff98c78aa,0x000023ec368ec733}}, {{0x000130cefa1d5675,0x000a003664f802bf,0x0004bd36ef9058a3,0x000a3113c314fc7c,0x00002389880af8c5}, {0x0007ec1959838d48,0x000fb01ed3b95705,0x000f59b95a2c3c69,0x000e21c93ecb7a35,0x0000427f7b9b8f6f}}, {{0x00004ae4288bb5a2,0x00037f3270264a85,0x00010b20b51cafa3,0x000a0e9e414efa30,0x0000157a33e62123}, {0x000d80dd6415cd8e,0x00020677cad8cac6,0x000c9fbc4f37610d,0x000d6dae155e1c85,0x00001d0a4ba60f48}}, {{0x00067d8c0e279e91,0x0008245afbee6855,0x00078ddecf33ca01,0x0007946ed3edf19b,0x0000f617d59ab035}, {0x0007945ae089290f,0x0005fe0200f2c492,0x000bf24784884e8b,0x000928852fe9c760,0x0000ffcb8771fa43}}, {{0x00066fd3da53da79,0x000b479eb0a7ecd0,0x000b2d549c3fc2d9,0x000b9c3ae4337ac7,0x0000ad4d200fc335}, {0x000f93463a303081,0x00096441398584c8,0x0008f0df55fc6eb7,0x0006d5481aed496a,0x000038658e97f52a}}, {{0x0009033a9a9ec889,0x00029548d2a17999,0x000b47721fa1d736,0x0008158e33920d87,0x0000045c74a58e24}, {0x000307917a0bc1d9,0x000057635c548972,0x0000f6f88a032dce,0x000d42aa81563402,0x00004682835e5a05}}, {{0x000ff28d04ebc165,0x000507686c2c4e6f,0x00063dcb51fce3da,0x000d9fe06896b6ea,0x00002e5ce05439c7}, {0x0009d2e6bdf7eace,0x0000afa52e93e883,0x000674e412921b90,0x000bce92640a5a16,0x00008b7c0dd9fa63}}, {{0x00028f0d3d5e18ee,0x000c30590eb006cf,0x000aec8faba412fc,0x00093e1f0888bc96,0x0000616d1fdc8348}, {0x00044c101c5f2508,0x00006dc12d0c3c51,0x000280f9293afec0,0x00028d276ff0f7e6,0x00004cf82b9fbef0}}, {{0x000644eb6ad3daea,0x000f9da617bed4fa,0x000591916a0aea40,0x0004a62c8bc21622,0x0000b14787fa4323}, {0x00029dbaddcfdc82,0x0007d2c3a56f1f85,0x000d278b64ee5284,0x0007a85b4f7a0572,0x00004776f3f249a9}}, {{0x0009bdc6a9c5425d,0x000a74cb2e08037a,0x000c41e34d0fdfda,0x000259c1bfad07fa,0x0000ef71695d1f87}, {0x0003cd312e6c539f,0x000dfe79874c3b10,0x000e03e026c03074,0x000366d7932c1541,0x000049edec49dd5a}}, {{0x00048153ce2a6ced,0x0005cb374595998b,0x0001d374c1a016c7,0x00056bdfd770e4d1,0x0000152c3e66158d}, {0x0004234660137887,0x000baf4ea70fc909,0x0007a4061d5c4126,0x000a704f10817eaf,0x0000e2581ebc91a6}}, {{0x000b859e2c097385,0x00023910a6cd24e1,0x000b5f1edfe2b5b0,0x000a39c796e06e2c,0x000061b222422caf}, {0x000f6e990b5ae344,0x0000276106c10652,0x000091bb1af35abd,0x00082644cec3093f,0x00005d1cd36bc1c2}}, {{0x000fc1520ced10f5,0x0003010001daedfa,0x000eaefb25ebd7e8,0x0001d7614a3f50ef,0x0000f52e9b2b27ec}, {0x000b038acc2e629a,0x00014e35ab802696,0x0004c8730d623772,0x000307b05e87064d,0x00000c762bd34c12}}, {{0x000e308ddcbf0bd1,0x000b96a5dc0cf082,0x0006cc07a52337c2,0x000fe84ae58e4cfb,0x0000659e706d98c1}, {0x0002ec7dd17741b3,0x000486171f471006,0x0002a5bee3b6d6b9,0x000eb91bd92dd984,0x0000975826a09b31}}, {{0x0003c9292ce02260,0x000d0dd17ee212fc,0x000bd9b2da2e3c4b,0x00035318456b64ac,0x0000a1961934d45b}, {0x0007febf09ab4caf,0x000002c812353920,0x000942e1afcfb9c6,0x000a778eaf0948fc,0x000043ec3002cc4d}}, {{0x00064b180a723820,0x0001aa42c8b77ff8,0x000fb95a1ada2085,0x000241ea27c78812,0x0000c96b8e900b7d}, {0x000a8792d5ec82d4,0x0000509cd684235d,0x000785d18e35f6ca,0x000788a287dd65ad,0x0000e9f2d7e56386}}, {{0x000b08a242d1b6d6,0x00041b0fd09c63e7,0x0000cea65281d8c2,0x000dd0e09cd34ca3,0x0000cac233c630e7}, {0x000013f31fa41372,0x00054e81b46f3496,0x0006319dc9ade00f,0x000f520220b1fc74,0x0000e2b1a530749c}}, {{0x000606de55192498,0x000c5809c40aa334,0x00096632d3890f16,0x0007e02bad0a1796,0x00005d185bd38bc9}, {0x00077cab67b3412d,0x00046a2cdd3292a0,0x000c830a347d5c0a,0x0000aa324c123aca,0x0000685c38fa87b6}}, {{0x00038414a19d3175,0x000e6a1704e8a59a,0x00040b43fbe48253,0x000ce06f982b9219,0x0000d5b7bcfbcfc2}, {0x000713f4576e6000,0x00031b8ba82c39f1,0x00005f1c4af7d65c,0x000c3034d34805c2,0x0000f4899f930218}}, {{0x0009d84b49c30b6d,0x000c425a60175a5c,0x0000a9f29180d182,0x0006fad47d4cfa1a,0x0000b40b136882cc}, {0x000d6a7c603f3345,0x0001bae3d9f84dde,0x0002e1b29542ed45,0x000b004616436a00,0x000003fa1413eddf}}, {{0x000cfbbd57abdae4,0x00020fc5888c8737,0x000a4476d73cd5c7,0x000218725a0deed8,0x00005bf9e51796ff}, {0x0002e189a1751dcb,0x0001228d9683dc50,0x00093baabf58f351,0x0000af8fdceae65b,0x0000cc7a48df0733}}, {{0x0003e0d34f77c46d,0x000fbc6edb0f3c88,0x000068e756b0e5b0,0x000e78037099eec3,0x000038e0b3c5fb3d}, {0x000f6109612e790d,0x0001867cb2863958,0x000f3a5af9ead942,0x000e99527c7a360b,0x0000669299225f30}}, {{0x000378d02aded289,0x0003c0423ea0efed,0x00076140c21c9274,0x000f78ad1a14b332,0x0000f0a890144187}, {0x00021349cb6cb96e,0x00056d9c9076e14a,0x000e9750cf7a0c30,0x000eb4b264c96979,0x0000fb23ad7c9708}}, {{0x00082f88233a37da,0x000d23f23abb42d1,0x0004b3734df9d345,0x000d6521d54ea368,0x000059fae532d7b1}, {0x0007515524ef218e,0x00007a73ae6b69e7,0x00058efc608d1521,0x00074e26beb85e78,0x0000aca7c3b8b78d}}, {{0x000c9e891767e9cc,0x000a6db0fc3a5dec,0x000195eb1598acc5,0x00005382d1cca30d,0x0000094de8c7a92f}, {0x000eb3338b3392a9,0x00013886c546dc13,0x0000d496c04db373,0x000adde62bf2b9c8,0x00002f299eed9137}}, {{0x0008bd479af2b8a7,0x000ea590b94dddfb,0x0009b3b12d8c5034,0x000cf0e1ced752cf,0x0000b36722ea39b4}, {0x00069628a0877b3a,0x00015bad064c4d30,0x0008ac446518bb7f,0x0006b03992b46ea9,0x000065fc30503fde}}, {{0x000bc2015b83fd15,0x000dc269799522b1,0x000b535f20b2820a,0x00069a5142759c76,0x00006f2ac98f9822}, {0x00083169e636983e,0x000e591e55c80622,0x0005a4241aa4d2a1,0x000591cfdd294197,0x00007b55447387c4}}, {{0x0003498722f42f3f,0x000a59410f413e15,0x00032a6354667481,0x0002956d7b04af7f,0x00006a645082d4e9}, {0x0000da5be5d8d302,0x00093df7e7583fbf,0x000d7c2be3abd8e1,0x000a000194d9418a,0x00000149bc9eb3d2}}, {{0x000f986a073e3517,0x000f9b73f9e38de2,0x000a58bf2571610c,0x000b0af920fb7224,0x00003d4b8dd4ddf2}, {0x00030e4ce112c73f,0x0003bf36e1c67f91,0x0003453afe2dc80e,0x0005ac201a013e91,0x0000c59ce10e30f2}}, {{0x0003b1cdc7f8928d,0x000ebc41452df139,0x0007451137f6868d,0x00053ce9613ed210,0x0000649aaa42f694}, {0x000b7ba1a932b30b,0x000f2a4924b83721,0x00040f1f33138c74,0x0003dd58146c6cea,0x0000e7f4ae83e138}}, {{0x00085f185870b6bf,0x000b92eed3fa9528,0x000d2b635e2b8998,0x0007568a94e9d333,0x00000526592b1491}, {0x0008aab3be513b25,0x00045303376d3cfa,0x0007c72c989eae8c,0x0001f30e65c1f409,0x00005b94d4c0e401}}, {{0x0003d066fe100843,0x00074d0b7004bb28,0x000967116b79d60d,0x000cb60757a89246,0x0000029e71f8c407}, {0x00065bff0dfe7d8a,0x000f7f471826dacf,0x0005753bb87557ed,0x000d529de1afaaf7,0x00003c27f0415370}}, {{0x000c10c40e0ad658,0x000d03d36ac61fc1,0x000143c6a50f0060,0x000b87a02cab6659,0x0000aa0ac941392a}, {0x00077a9d795672d8,0x0009caada373a423,0x000f29a04260b72e,0x0002e8475833e9de,0x0000035e64a7ec99}}, {{0x0001b1e50eb884d8,0x000fb550dec7d443,0x00015188fa1435ef,0x000fed29334dd65c,0x0000cd2d5a342204}, {0x00054e8f171c4219,0x000d2a2a4537bac5,0x000bde4f44854e54,0x000cf4c3773aace3,0x0000a962593e8aa2}}, {{0x000a77a80d8d4ad6,0x00075f34cbc4dbca,0x00009e3fe02abb2c,0x0008ca980524452e,0x00006411b8d00213}, {0x0001764627b7712a,0x00023948a2b5cb5a,0x000858785cea3d52,0x0002036e6e748680,0x00000042eb925ac7}}, {{0x000751674ece9ae9,0x000a512b2c44e9c8,0x000e88fccc205168,0x0002c75cd9811607,0x0000f9001ef938ff}, {0x000ac81e5a48ef97,0x0002e0109b2bb3fd,0x0008c3273e7e9d5a,0x0007b2dcb6ff8d2a,0x0000cc1bdbc8ee70}}, {{0x00056fa2bf280369,0x000a9e2e674b01be,0x000c71f07ded96d9,0x000002b55134dba0,0x0000dd1195c38794}, {0x000266f2f86721fc,0x000adda42ae0dc28,0x000d8561fa395767,0x0008fd2270c1219d,0x0000d0cfc1b86620}}, {{0x000bf27baf63ff66,0x00009ebc66252bbd,0x00081af1cacfa286,0x0007812dbb29b31b,0x0000fb9396e63aab}, {0x000ada1d38323f82,0x000ad4f13aa595b7,0x0001d791ee24a41d,0x000c0b1e03dfd84e,0x00007cfadee3c277}}, {{0x000f91b24c3fdcf9,0x000dc39512d9d6c2,0x00079ea474581c15,0x000b3037480385b4,0x0000d036170f05a4}, {0x000567ff9990c1cf,0x000c52022e9733fd,0x000e053c243f4d6a,0x000e8d640b9aa656,0x000085f487e4d5f7}}, {{0x00091898d9f31562,0x000dfbe0453c7472,0x0009e6b7f7af420e,0x0004b20e2b916673,0x0000164bef06f4b6}, {0x000b80fc51993f6f,0x000c34d3d86975a3,0x000ff3c930f61aa4,0x000b4918539af658,0x000059a8d10c4494}}, {{0x00066e89fdfd1ee2,0x000e2e6e602e0282,0x000d5c751cb890ad,0x0005b84b04a46bd2,0x0000ce8ef41b6ed0}, {0x000a5fa420cfae5a,0x000f8b6e315d4386,0x000903ae604fd4ff,0x0004b04a393c9fe1,0x0000cd608fd28510}}, {{0x000b3e82dc9c8f33,0x00059d7a2a568260,0x000ec023ab8ab819,0x000b4672639387f7,0x00002043db1d435e}, {0x0003a6c41ed2e7cf,0x00005ab1014aa9f9,0x0007dc38d75705e1,0x0004e061bd047969,0x0000eb648e51640a}}, {{0x000f0f57c547a961,0x000d990237650041,0x0004510d6c34d742,0x00063c4132ff339a,0x0000408528595bcf}, {0x000a71c3fe658de8,0x0001c3cf64c2960f,0x000e6a5c2ae5ee0f,0x000e11651433eea4,0x00003984cde74fca}}, {{0x0000003ac6f58504,0x000341671c32ea49,0x0002b8921facbf78,0x0004fa3c67b6d380,0x0000873d3817bc08}, {0x0000d0e2edff3bef,0x000ceefbd4439499,0x0008b941acf60583,0x00068f3529a5a269,0x000098b50bd525cf}}, {{0x000a25873e60025a,0x00053855a627b0b2,0x0005a4f0d708e8e4,0x000b258de1632834,0x00003056505bfd84}, {0x00090d0a530bf0e6,0x00043c0c25a53dab,0x000f5fa79e358944,0x000b501d65285c91,0x000077599220aadc}}, {{0x000decde86b39648,0x0003ad7ad0f350fc,0x000fe462f1844e2c,0x0003d39cc52142ca,0x00007a06c317b146}, {0x000867e4dc14e8c7,0x000ff41bcd37d80a,0x00032c5b0675151c,0x000653c449373f36,0x00005a57dc103d6d}}, {{0x0000a2a7c0db9bfc,0x00011c2811b663de,0x0007ec267d1c9049,0x000b23256ba8b300,0x0000534d306792e2}, {0x00026c1d52004b5a,0x0007a3f4dc127efd,0x000d195c762760cc,0x000221924b8c8b14,0x000026c7b7eb7f67}}, {{0x0002f18ed29ebf14,0x00098c2b10a9d4ab,0x000a74882a5d041b,0x000d5bf9c651a0c2,0x000088a4278579c9}, {0x00051235c715721d,0x0000e9dced4d4ef7,0x000ee67bd5212bc6,0x000d93da86c0e051,0x00006c0ebc2e5127}}, {{0x00070438f33a86ab,0x0006a9c27c7efe20,0x0005fcfb1eb8742d,0x000157f616499b3f,0x0000133c81b68e98}, {0x00010f66856c8633,0x000cda9e424d843f,0x000454d474e9ef7f,0x000d084addbbba56,0x0000f1d7dd5fa3c0}}, {{0x000d7b41a5dc9f16,0x0009ef12f95203b7,0x00013189c2fc91e0,0x000aec2347a9cef1,0x00002719ff12516e}, {0x000d3b82a3b61af6,0x000df7f38b308736,0x000bf80445b12e06,0x0000c743ba9b2725,0x00005ba45f8b88ed}}, {{0x000261f56f9e574d,0x000455263e563df4,0x000e18043b012748,0x0002a907208773a4,0x0000ddabf1b7aae1}, {0x000554210f1c434d,0x0002ff3445d34069,0x000445f11b6f9f3a,0x000dae4831b39805,0x0000edfbc2a2b1d5}}, }, { /* digit=12 [{1,2,3,..,}]*([2^84]*G) */ {{0x000c554483b6753e,0x0006801db8f9d305,0x000886fd9162b06d,0x000476456139bb92,0x0000ea4a8915ea88}, {0x0008d47007a48524,0x000e4818a4c5c808,0x00015a22cdb69736,0x0005f81ca589aaf2,0x00001d936a1d6f7b}}, {{0x000ab2dcbd28cd7d,0x000a1162cfc4011b,0x000cc1af050d89ce,0x000063b3e8402465,0x000083d0e91f2d65}, {0x000f946464985316,0x000f0b6261148253,0x00038d8cb0463eb2,0x000a2eaf46232053,0x0000d3acff868021}}, {{0x000dd5140afb7993,0x000bd8f7f093f0f0,0x000c26e525fd4cce,0x0006ac8e6399e015,0x0000a1f765c42a88}, {0x000b1ca956564f4b,0x00094bcd0652818d,0x0009c185081d8880,0x0008442cde2c9ec7,0x000025a44064aecd}}, {{0x000f5f559bf4a74e,0x00050b61dbdb8ccb,0x0007c812ac18b374,0x0005a3f24ba94aac,0x00004f5dad1bf4c0}, {0x000b7e537d97e833,0x0002de512f6471df,0x00071b5884053ab5,0x00043d89f56b8b9d,0x0000c58226e7c64c}}, {{0x000f0f17bc532082,0x000fed58cc574ab4,0x000e10b8d86bc64e,0x0007d2b3542fc362,0x0000a757378d0112}, {0x0006ccd629ef57cc,0x000f7b5d9c080f6f,0x00088029c11069f6,0x0000bff2e914dc87,0x00000558c2f6e839}}, {{0x000da9445a23fc09,0x000605eeb8c005a6,0x000fff46275f912d,0x00078b2667155c28,0x000052569c27476d}, {0x0000ed991150c753,0x0003d9531b755efa,0x00075e9f483c52f1,0x00031dab94d69b7c,0x0000df793c3e38af}}, {{0x0005af0c0e6e3ad8,0x000fa2bd1fd197e3,0x00019540b108b614,0x0001cf02f81fa984,0x0000838602012d96}, {0x00015ecd5143acca,0x000e93ececd5fb07,0x0004ae6741960659,0x00087c273955714a,0x0000f440efd280a5}}, {{0x000e7c32fd3348a4,0x000777077b4c8efe,0x000fe73e11c88faa,0x000b96ecece59c8d,0x000009715b464a77}, {0x000aa5d14df28d16,0x0005301318185b7c,0x0005350981bb9857,0x0009644ee837ada5,0x00006a9819ff80d1}}, {{0x000a414f9b65e700,0x0008351d28b72fc0,0x000807cb5eaeea1e,0x0005c55f09163a37,0x000086eb6b36bd63}, {0x00044698cc2a4ea8,0x000466e5324dbb10,0x000664773c425160,0x0003514ef5e7b9d3,0x0000bfc6b8578654}}, {{0x000f3a37768912e9,0x000fade19cf47741,0x0004368c97f7e0cd,0x000b78a509039326,0x0000e3961c3955f3}, {0x000d1b5709e33830,0x000bcb212af98fb2,0x00071b5c07cebb92,0x000dab556ee7dd40,0x000022c98a5e5d55}}, {{0x0007c40f3d55f440,0x0005850ab4bcb8d7,0x0005dc2904c0ecd9,0x000fc094f9552e74,0x000065bde9a45b12}, {0x0001b213e07d2a05,0x000dac491152e816,0x000bbb468a73324f,0x00022eaf5017795a,0x00000333c55c0892}}, {{0x0002fde94b3766cf,0x0007174a526e10e3,0x00046da5e56aac35,0x000ac2d0c1c51f5e,0x000035efc2472eb4}, {0x000da0a323be075b,0x000717ec17895a91,0x0008ad7c571d2b3c,0x000bf89dbcd26f41,0x00006d4343245d6e}}, {{0x000dc2eac62fb9f5,0x00084e51c141aa70,0x0009798c2bb7e6c3,0x0002dbd11d4a05b6,0x000074f72cf5e639}, {0x000fd435dd15c827,0x000425e3562b0e0d,0x000886af23f9d33f,0x000b98eee1982216,0x00002d9339f90269}}, {{0x00046ab0a3564848,0x000023087b4fdedc,0x000aa974dfa3f8b2,0x000c5683df032518,0x00008d37e3dd003e}, {0x000b497bcaf07eb2,0x000a80cfce97a4ae,0x000e8c971e5379fe,0x0009ba740afedac2,0x000087c1f6eafee3}}, {{0x00083a26aac344f6,0x00074201b2856380,0x0007578c50361026,0x0005b40a8a67be24,0x0000605b8627889a}, {0x000aabd30a19439e,0x000ca53f88dd0bbf,0x0004a3ee818767c1,0x0006663ec91f08b6,0x0000bcc3862cf387}}, {{0x00084ddfe58cda46,0x0003b276513902f5,0x00002aed28befe9b,0x00072ae88c3c7ae7,0x00004c8c2205288a}, {0x0001cb844e502e5a,0x0000d9ae644c5df9,0x000c1aa51015e574,0x000a6be30714bc7d,0x0000f41ed76cc10d}}, {{0x00033bb53beeec19,0x00007eefd1662fa0,0x00011a9bf3b2cd1d,0x000d5a31a0c88f70,0x000032688031e363}, {0x00016c08ae3a3eca,0x00015b3281e6f092,0x0008a75e39d7d5a3,0x0000909972d7b786,0x0000c65def428795}}, {{0x00005874e890e300,0x00041d95ddabcf98,0x000368cbf916f257,0x0002fcdd589ca455,0x0000f2d91af1373c}, {0x0001207d3f06d40e,0x000b5b5367021a75,0x000f49339cc99d98,0x000d3d50f580d82b,0x0000a7749f8b2793}}, {{0x00086dac65846f84,0x000b8b184a18be90,0x000f50dfc9f9163e,0x000bdfa618f3c6e4,0x0000afe515af4887}, {0x000e16cfa60c51e7,0x0009ee647322d93d,0x000691d42a467932,0x0002e56863b1a893,0x0000c8721a2b5b90}}, {{0x000ee5987897056a,0x0006fff7338cc84d,0x0003cd0a29f7d1a7,0x000f4c1eeec55391,0x00008625bca9aef8}, {0x000f0fe0533242d8,0x000ddebee7314e38,0x00034542be2dc785,0x000311e6d17be942,0x0000a2343b6a2094}}, {{0x0004301cf477c5cd,0x0002ab6a3d1b7d53,0x00030cd8103b9cfb,0x00095e6e96f2ce03,0x000038fbea44936b}, {0x000b90a008acc54b,0x000a8904b3609016,0x000c686bd1acda20,0x0000e048114fd494,0x00005ab0f4d4d8f9}}, {{0x000bdef90ead4f46,0x0007246d293b9ec5,0x000303573d9de112,0x000f45aadc6dc3d3,0x00001af5d644db85}, {0x000f4601e63bbd49,0x000a087a714b4af8,0x0000935870f2f324,0x000f960a6914e009,0x000012ad683418ae}}, {{0x0003354792bcf5ae,0x00007f41be3c88c1,0x000c142b47e1eca6,0x000ddebdc8cbf3a6,0x00008e5a41a3acc1}, {0x000d1ff364d640ad,0x00071b7bbff3b08e,0x0009b246ca485c01,0x0001f1e241e73b86,0x00008915bc9ac6a8}}, {{0x000cb418d14bdcd6,0x00009b819b92ec5f,0x000ecaff2142a74c,0x00019578fa6a421a,0x0000cda9a55a8acc}, {0x0006359363a78d5a,0x0000ebce5d6e8f57,0x0005c404f6dc243f,0x00056438b0c481d8,0x000021f1152ba645}}, {{0x0003438f3e2fc0c3,0x0002778ec5d0bef6,0x0000bab2acfaf639,0x000a613040995c34,0x00009c33c69e3d8f}, {0x000a7896b97bf0fb,0x000d924183025e51,0x000de7e95ff5c9f9,0x000871ae0c7dd05b,0x000034587b2ddc5e}}, {{0x000a79da8f271b1b,0x000381332a91ce35,0x00037e9d38ecec65,0x0005eaabd737de2e,0x0000827fb571e37a}, {0x0002f6167f95c9a9,0x000a0030b5abafa6,0x00086b6bf174705e,0x0009211f763fc83d,0x0000ded86cb103bd}}, {{0x000f7cf342886a76,0x000e724e6bc2322c,0x000265932e8929ba,0x0005ba669f694ca2,0x0000767c25712d5f}, {0x000c9821f6a99f7f,0x0005f36eff86ec2b,0x0005ed3486fe21b9,0x00084100857e6f4b,0x00003ba09b776464}}, {{0x000a956c6538d32b,0x000ce0ebaa99bb77,0x0006e54dfc273705,0x000ca26fc41d2862,0x0000ec59f9c31c58}, {0x0005dddbc05f1be4,0x000eabd6ef105f32,0x00011aa76a1b687f,0x000ce473e0cb49ae,0x0000f0197e08a6ca}}, {{0x0006580b23d6fb8b,0x0002f22ce000c4dc,0x00088dc5c9518521,0x00070c22efb775fe,0x0000e08eaf386d96}, {0x0000f9e5bdd09ac2,0x0000337c16dba3d8,0x0000363489849e43,0x0001c3c9be67c37a,0x0000d611ceba3199}}, {{0x0009d284701935ec,0x0004f56adc223b4e,0x000d1eee70422ff8,0x000e16a6f16e99eb,0x00005bde8bd944aa}, {0x000c5e0516c8252f,0x000bdb9bbaf3e0fa,0x000b35adb2dccf13,0x00031f937c0cb137,0x00004bea07b8f8ab}}, {{0x000bf359cf0ad3be,0x000eb4ce9011d0d0,0x000eac2cdc3b6101,0x0008c802272d1fdc,0x0000ce74ad8a8b66}, {0x000e8fac38d80fc9,0x000537f10c1a619e,0x000432c10ce4a266,0x0002836eede88f40,0x0000bf1a37e07a03}}, {{0x0002775c8d90f0f3,0x00029d5b535f043e,0x0009d75c2586f7e6,0x000648a06f699957,0x0000735f63f9f6b8}, {0x00040e7726af474e,0x000bd520fc28421c,0x000f156aa1f46680,0x000b48b41f5251e1,0x000071b7c6df2177}}, {{0x0001cfc4cbfca31b,0x000f57ed1f1f84af,0x000d23dc50912828,0x000085f1b1048a1b,0x000002a9d0f5f8e3}, {0x000caf1497eea594,0x000546369358a96e,0x0007ce467f4e2dcf,0x000867022d181302,0x0000af96b3e41c15}}, {{0x000872dc000aeb4a,0x000cc793dc01eb7b,0x0004d8c005622aa4,0x000edbf05a0f117e,0x0000cda49f07a17d}, {0x000c8c1f58a0f7cc,0x000e8d9b661613ce,0x000639e32b5f0a90,0x000ecad3e495fbb0,0x00009ea83415cbfa}}, {{0x000d0c201f5ce32c,0x00016577157dbc72,0x00073d070c744357,0x0002426c39bbf87d,0x000042537dcae3af}, {0x00021ce869d0da00,0x0007377f351b6617,0x000d8fe45a48f43b,0x000cfafa73e6ae19,0x0000ed3189970de3}}, {{0x000ae762be466e04,0x00021e7720f0ade5,0x0002843c06a19691,0x00013fc0033576f0,0x00004a129decc0c4}, {0x0008e8867fa59016,0x0002d5e9a56b0dc7,0x000237f5a534e8d8,0x000fa748cb4f9d00,0x00005d9983dbb9d4}}, {{0x0007d12937513371,0x000403b7cbdf14b2,0x000bcfac2b7fb8e8,0x000d9866bfdce003,0x0000db5c06aff71a}, {0x00031018effa29e8,0x00004fbcf727d6a1,0x00022a8553be0ad9,0x000bf7969cfb64da,0x0000e985eacf416f}}, {{0x0008e834cedc78a2,0x0005c97f5478967f,0x000c186a2a467c85,0x0009469dee8aa6cd,0x00006d837221b315}, {0x000629dbdec3f949,0x000478eadc28ad1d,0x000bcf7c9c16219c,0x000b53383eac76a4,0x0000c5ec8b33a0e5}}, {{0x00007c0f0e12ca94,0x00018bf91307ba11,0x00071d9ab1a24d3f,0x0007747bf130fd05,0x000079c81e5f13b5}, {0x0005fa3e80924361,0x000c57f2b1fbeef3,0x000248ba50a359ac,0x000af11a98df62ec,0x0000363f004297c0}}, {{0x00019cde83118148,0x000e64cb25d0fba2,0x000c4ad7b162ac09,0x00058e222b481ca1,0x00000cc2a53bbb20}, {0x0002508860462ab2,0x000b158a37864da9,0x00086722e4f10c86,0x000d14158a829423,0x0000e4fb785f8862}}, {{0x00027d333d753d0e,0x00099a2600a68bd8,0x0002fa817222a7a3,0x000b8713381a4c58,0x00008f9cd717634e}, {0x0004b7b30e02de62,0x00075c3ea937f197,0x0002821c922ac428,0x000a3c40e3d9b177,0x000003323a2e093f}}, {{0x000fc05a7e4d4e55,0x0008f1cefec7348f,0x000192a2b46ee68b,0x000353c77d99e99d,0x00009d818e97658d}, {0x000392d3e49f6104,0x000248caf3c8ec9a,0x0003023ca2d7b6c1,0x000b2c8a0f354f8b,0x000074921f13eab8}}, {{0x000df76d07f39331,0x0003d350ece61581,0x00081c9e57d42e69,0x0000f9cb516a8c9e,0x0000d6335e12edb9}, {0x00090961506c4c3b,0x0005bc7192868ceb,0x0007bcc0497dec67,0x0002067339d0df2b,0x0000cdd06eb70f33}}, {{0x000f7ed789462fbf,0x0007ef672b19b20b,0x000e33cd81a16b1f,0x000f12f89df2aa89,0x00005dea3af5b77f}, {0x000838649cd0da1e,0x000c5bfcd2a2c5be,0x000c32ff1d3c1e34,0x000f06839599cfa2,0x00007239d0120da8}}, {{0x0000e69d0c2b5ec3,0x000b79db1e73bda6,0x0008b9c4a330f8b4,0x00035cddc5f73aa3,0x000006f789e69775}, {0x000bfed204c713d0,0x00093bf9b2e7bd72,0x000422f0f0282a2f,0x000a48b205e175a1,0x0000d820622b824f}}, {{0x000e515a23d90057,0x00022d89b47f4c3f,0x0000548b05e86278,0x0000426dc052b635,0x00005bef95a0b629}, {0x000089b8f8a1e0dd,0x000c7a412f79fcbb,0x0002f0be65d47bba,0x000090db03dec5f6,0x000085fb777a8161}}, {{0x0007aaf19ae92fdd,0x000b5b9b429c59f5,0x000ef392e01cd435,0x000166a7e522b3e3,0x0000ce727a8ae2ac}, {0x000a5bed9bc9a546,0x000c27594ab2b1ac,0x0008e070e66e8389,0x0007d19f80cafd14,0x00005a8fbc95dc3f}}, {{0x000cc3bbb7c912f1,0x000bff31beae296c,0x000fa0357fab8a10,0x000dfefdef6e8a9e,0x00002f8fc87142a5}, {0x00042101a914d6cc,0x00008a1ca0911556,0x000418ad615b500e,0x0002d61e09ea4513,0x0000e1df01fe2923}}, {{0x000e5cc99cf67fd2,0x000ce5fb36c081a0,0x0006e1396618f51d,0x00059123402398bd,0x00009ecfd4e3d980}, {0x000e341bff7f018d,0x000c1f6950d1ea13,0x00091e965892d500,0x0004e189b9fe1910,0x000072842d82d9d7}}, {{0x000cf638f90465fb,0x000755cc7173d4dc,0x000b1dada810c125,0x00004d9dfedee32d,0x0000d16f02f61958}, {0x000aa8044614721e,0x000015fccdbc214b,0x00003a0873eb45a7,0x000b58c3b0135086,0x0000180d15fc5f69}}, {{0x000a048c4901672a,0x000b2340b7ff98dd,0x000caf804fb759b4,0x00075f5cad446960,0x0000319c7e6dceb2}, {0x000b09071211838a,0x000d7c9c2382267d,0x000bf6ab01dd36cd,0x0008da89262c392f,0x000032c1ea49aea1}}, {{0x000deaa5ca6ee65f,0x0004c1800a9c59a9,0x000680184e358c6c,0x0008d4ad86de1415,0x00000b504795d3b3}, {0x000795b139b52e54,0x000ee69f5a0fce3c,0x000b814ff6a9423d,0x000cb742a66e5645,0x0000032d10e19448}}, {{0x00072569564d217a,0x000429fd0889deee,0x0004319cdca4ef8f,0x000f3e3b6ac95065,0x0000f32517aa4f71}, {0x000b21b117693d29,0x000183555154e948,0x0005077940c71c7c,0x000c0754bdaf53be,0x0000cc60c2cdf8eb}}, {{0x000b43f7dce0b1b4,0x0009c72824968563,0x00065de307f4a3b5,0x000b7842c8a92f9e,0x00002c0e25912368}, {0x0004adf586027566,0x0004f78ce7e8eca4,0x000a94b38a6951fd,0x0008f5eaddabfb1b,0x0000f4735e8fe842}}, {{0x0002dc3c7e725420,0x000d3f88fcc2867c,0x000ecf5483ea2af7,0x000783793f2f306b,0x000045bad8bfd57e}, {0x0002ca4b36818218,0x000835b27feb5f63,0x000453187115ad6a,0x000070eab7ca7b7a,0x0000719ffe4782c5}}, {{0x0000593929af0d40,0x000e5664a3d91ab9,0x0001e9eb544e57b3,0x000d2f624b4757ae,0x000032347a13f3b4}, {0x000d1da32f451911,0x000266acc7aa2e45,0x00091a4d237ee7c0,0x000dc21ed6afba7a,0x000010b7c3ccaa69}}, {{0x0001d7c699cfaf4f,0x0007ca6c922936b5,0x000449a44405d498,0x000f2f24d9456a6c,0x00003f6e5ffdbb14}, {0x00037c452dfb4b57,0x000926a4b56d7971,0x000a9f7ea115ed0a,0x000d5afaa27d8ea2,0x00003adc089d4a10}}, {{0x000d5a0f6239d756,0x00018c596b9e37b8,0x0003af1688d17ce9,0x0005a37b04b307bf,0x00007aa9f6053a7f}, {0x00074342f5e14850,0x000fbae0c42ca37b,0x0000e1ec491136fe,0x0000eb4e610854f1,0x0000f0ebf7930ca3}}, {{0x0007b6e75a63ab1b,0x0001d7cbd366e9fe,0x000fda58c355abe3,0x00062d68e49464a8,0x0000bcb1280d5e57}, {0x000777d197806999,0x000a9ecf9715de06,0x000f6afd589c8aee,0x0004af4e62d3ff71,0x00006b88426b88bc}}, {{0x00074d1d902ef8eb,0x000cdb0df8d05362,0x000e73dab4f8bd22,0x000917798e1bb263,0x0000747ec50844e3}, {0x00053692d52a05db,0x000f6ca8d9b29727,0x000f02477bc17e87,0x000f3a1726632e3b,0x00003ce08d4ab050}}, {{0x00048d2262daaba8,0x000aa837e39f0f7c,0x0009320f1da31454,0x000ea364915f9041,0x00002e8921d77b9b}, {0x000423a958563826,0x000a3497921fbf0a,0x0000461a0e93409b,0x000ec5b86536c442,0x0000775d4ee0d067}}, {{0x0004ed2cae04d7ad,0x000171ad7cb36930,0x000d2d311bc08ed7,0x000f695e13619e36,0x0000d2e0eeab2d2e}, {0x000ee6772c62de91,0x000baa1b52e55366,0x00004bce2a244410,0x00054fc30c34b0bc,0x000005c73893a90c}}, {{0x000cccf4a1a0cca9,0x000722bdc2035d63,0x00057bd07cf346bb,0x000f316c79ae4fd5,0x0000ac63d30daba2}, {0x000ff39d838e4cd7,0x000204741c2e1f2e,0x00069d840c3461d8,0x000a84505593db6d,0x0000741dc28c944a}}, {{0x0000876a8b27f44b,0x0008bb19870aa30b,0x000f8e9ec31cc2ec,0x0004c4e60731153a,0x0000c55b52b0033d}, {0x00089b1ed9e1929b,0x000e314409183cd1,0x000e19b9a4f6719c,0x0007dd490b7456b3,0x00001a8b428feb17}}, }, { /* digit=13 [{1,2,3,..,}]*([2^91]*G) */ {{0x00023862936ccd46,0x000c9f3bb8a5bfc7,0x000ca23157985ce2,0x00081bc9abd0a0d9,0x0000af5b9895adc3}, {0x0005faaee4832a45,0x000d59f64358253c,0x00046da055a2f27c,0x000f568dc06afc75,0x00002ba011d7eeb2}}, {{0x00055fc1cf25ca24,0x00020e1d348934fe,0x0002536cb0ab57ca,0x000233ee745fbe8e,0x00003e16abce68d9}, {0x000e1c0522422409,0x000a5979e6309e7a,0x00066b196881b4f7,0x000c1edac5fd108b,0x0000142c6726f6ee}}, {{0x000c2137390618df,0x000be970f27a0fee,0x0002f4c961a17241,0x000f8a198a977f70,0x0000195907ddcf67}, {0x000f379501c8471f,0x00059ed6d515c9a1,0x000bb63a198210a5,0x0001b9124b243403,0x0000ed746bd02b9c}}, {{0x0006e74ded67841b,0x0004cc8fd37f409b,0x0002803b1af55986,0x000c3bf000b91399,0x00007ceb09bcb37f}, {0x000f8d459310a1cb,0x0007593dba573a77,0x000ed294ac4fff32,0x00092052bf2f7fbb,0x0000fe022e7f7a32}}, {{0x000c7a6ac040f2fb,0x00055a54b073122b,0x0003e7acd6ce751a,0x000107d66c28518c,0x00003aeca2c1f0ec}, {0x00033bbbdafae2cc,0x0009f8fa7af36884,0x000dd647c01943c3,0x00009696d6c87579,0x00001c20d14c8db3}}, {{0x000a61a0c68f6032,0x0006a9123a83491a,0x000bd0c5a9dc2dd5,0x000db59a99946a29,0x000081228cdb3c43}, {0x000cd2ebd0599303,0x000f84227c8ed033,0x0009053e94a3bae2,0x00069f434a9ed1b1,0x00002474f03f1410}}, {{0x000126dbaaed16c2,0x0009899463a3470c,0x000eb820a2fb87f6,0x00066fd977557dc9,0x0000a9950295b8de}, {0x000646dbf257d07b,0x000e7a4e19ec84a4,0x0006a7eaee3f42b8,0x00025c05ee05cfcd,0x000057200c018815}}, {{0x000d1bc968cdc161,0x0009f62c0803d083,0x0007eca12854bc1a,0x0008683a5785328d,0x000052551f11c77b}, {0x0005bb2ee4edb660,0x0002b2b5a388ab4d,0x0004ac3bf9559546,0x0003650232668dd4,0x0000b1b0d76d1f17}}, {{0x00004047d03bfb04,0x000267ecceeb6096,0x00091101feb19ab6,0x00010ef35c6beedb,0x00003595d5f45735}, {0x0004e8ad3b49694d,0x000206d570226401,0x0007f45f06b32f3d,0x000807cfb7433dee,0x0000c15e03794afd}}, {{0x000e7a6211af3d16,0x000c95e02ef4989f,0x000bbdf2c96b6185,0x000b8ad9fd10ece4,0x00003291adf91780}, {0x0003b209aa3794c1,0x0008e8ddaca35358,0x00074558fbaca474,0x00087d9bbf1f277d,0x0000f61a073f7b35}}, {{0x000d8adb85ee3f83,0x000ebd78bd46cfa0,0x00011af45006aa9f,0x000c03cb789b856f,0x000038718b3de225}, {0x000b87d218ea96d0,0x0008296dd64f240a,0x000a55d762afba77,0x0000c106f6b48540,0x00001637a1067f29}}, {{0x000fe903a2ddee0b,0x000c2147304ab5b6,0x000bce46578683be,0x000529212a7403d4,0x00000a0c11ee7628}, {0x0002eeb8c98226d4,0x000acd7eace9cfb7,0x0007ed1f6bef5b8a,0x000c572a94bfb860,0x0000fb6e6fd9f827}}, {{0x000129845c7d39d8,0x000c08fc8d104a0a,0x00091c5df9c60f44,0x000c84addd4d5bba,0x0000117fecbad4ea}, {0x000e5b606f925139,0x00040714a55c0cef,0x000e33820c14e7e6,0x0000982da6e9998e,0x0000df370032e21c}}, {{0x000f523358513503,0x0001fd64adfb3997,0x0006889ad5e8f89b,0x000efd415f1bcdca,0x00000dc5193d322a}, {0x0006d6646cc33bcf,0x000bc53d4982b948,0x0008f8e8fa9ce266,0x00054acf5820c0d5,0x0000307c2eb0ed58}}, {{0x000613f329e775c2,0x00074e8d77c0eda9,0x000f3edcede373e6,0x000303ea32e7c5f4,0x0000ace4b9dce770}, {0x000d62a55c54561d,0x0004408d9c3361f9,0x0005d18ac4c51c97,0x00082e094177a277,0x00004c611cafa47c}}, {{0x000f298db093d970,0x000d8fc659552b85,0x0004088b59c6d6fc,0x00017f0a2d06747c,0x000086eba0701cbd}, {0x0003e9934facc02a,0x000b5a33252cc71a,0x000700d0a64d5a86,0x000a74776c01c506,0x00000d58cf6a3492}}, {{0x000e24841127be4d,0x0006109c01c62f85,0x0009d1e24f0d7950,0x000f9906c5f8998d,0x0000d14baa86e1ba}, {0x0006495cd2b7045c,0x00079b660d67c95c,0x000b91fd538bc207,0x000698f1bfde9d01,0x000069d46f82ef5f}}, {{0x00054cb598765316,0x0003c6ee2235eecf,0x0001d05682fcdb79,0x0000cf6e6100f9ff,0x0000dc6262cd1fb3}, {0x0002721130ab0425,0x000fd66b83432c4b,0x00068d04d701f922,0x000c56e867326ed1,0x0000fa2450fdaf47}}, {{0x000e18b2b572c025,0x0007aabc185629d1,0x00011115af0a8c3d,0x00059e153c5e496b,0x00006571350e5f65}, {0x0000804bcbbda06e,0x000ba4057dba77c0,0x0005a19dc3818e66,0x00007db6d31ee3f2,0x00008435030e7d57}}, {{0x00046d989cf9775b,0x00008bbdbfa6a9e1,0x0004e3b35a8bc449,0x000972cffc49e7a3,0x000053ed79153d43}, {0x0008b080e14ff257,0x000ace79b7fe22f9,0x00059f0939c733aa,0x0000aeb72dd048de,0x00002619ceb8b79a}}, {{0x0001e4f65ecf7496,0x000ae8ee251022a3,0x000790a0b8ce447b,0x000e5b7dc58d2831,0x00004c7c03b41e33}, {0x0008b362b8088d3b,0x000cbcb87bd9c6d1,0x000cb48e67cf5c74,0x00069f85efc38c53,0x00003fa36fb3ee0e}}, {{0x00043ceed8105788,0x00090734b644bac6,0x00036bb8ea2711c0,0x000b3810041eb459,0x000093c69a1b4b83}, {0x00084710540e3d01,0x000d719e03fd4f77,0x0005e622babf321d,0x0007b11922ccf87d,0x000096e359a83944}}, {{0x000fc5fc73da9b5d,0x000b1595fc9ab291,0x0005a95066904c34,0x00015959fe032bdc,0x0000b4b92b11f12d}, {0x00034add676f593d,0x000519f1f0786c3b,0x000697738b1c970a,0x0009584fb4963dc9,0x00001084921d81d4}}, {{0x000b5da661dacece,0x000f6b0cd23bd2f4,0x0001cb076a96cfbf,0x000ee755e6ddc3ce,0x00006cb5574c3f61}, {0x0003a2123b371d00,0x00074a4a55ca4cdf,0x000b8d605f7131d5,0x00082c751d8514b8,0x0000089e6493eacc}}, {{0x0001884e243e59de,0x0008f13be7d12276,0x00090809ee25d4f7,0x00092c13560a056d,0x0000cbd0fd7048aa}, {0x000c7cf11455b365,0x000880bcf192c1c8,0x000ee71e5bebb543,0x0001694d7bdb0baa,0x00000e46da8bb58a}}, {{0x000ef46c771c87f8,0x000f7f262a6e438d,0x00050eb2f306408e,0x0009c80d5cc4d430,0x0000385ce31c91e8}, {0x000059abc1a67c19,0x0002e387ea4cab0c,0x0003e03c8b9bbf51,0x0005c84742501cfa,0x0000918e418e3d1d}}, {{0x00022bbef09486e0,0x00010f5c122211d7,0x000b2de7adf0502a,0x00049b5ef8799064,0x0000cd147024c20b}, {0x00090d67f2d70c08,0x0001cc8fbaf0cafb,0x0001547cd4a1a267,0x000146a52fc4ab4f,0x0000fe8ec3c3592c}}, {{0x0007c5d6d28ee3f0,0x000c1f5e25a2d30a,0x0005a067148ab16a,0x000b0e3e550cbb99,0x0000cdbad202b2a5}, {0x00093875ccf1d8a9,0x0005756ac2a6bcdb,0x000720061b8c60e4,0x0005ffd19c95c274,0x00006cf02b509a1c}}, {{0x00091e12337f16c0,0x000c7393588f049a,0x000c7530b5c0408c,0x000e8d167beb1eb4,0x0000bb3b2a2771f5}, {0x0000d4b2f53140be,0x0001dd263d66660e,0x000799cccb650354,0x000900827c699d37,0x00001ecf8af970a8}}, {{0x000b005909514a74,0x000ecbe20fc8996c,0x0008fe96ae8999fe,0x00053c02484ea215,0x000081ece97b1b2e}, {0x000b646f679d3fed,0x0005b8da2343f2fe,0x0006cabdc877b5b6,0x0000406a1d29230e,0x0000aedcbd3b6bca}}, {{0x00043b54f4b39c27,0x000d249a5720a07d,0x0002cb9000f597f6,0x0003ab0ac7a0dc36,0x0000fc9c13cdf3e6}, {0x000c0eb22fd82d5c,0x0003b8a81a1aedd4,0x000364a7c0e3f20e,0x00046fbf635e9939,0x0000c199b407168e}}, {{0x000014cc44058054,0x0004050153cddf02,0x000dba3274172b05,0x000f0217ddb34198,0x000092ae38e923a0}, {0x000179277af42fa1,0x000c90d55c033ee8,0x0000a9f8725ae26f,0x000fd2debf1b8171,0x0000ce7e032b9a99}}, {{0x000a44861b8554c2,0x0000a3a94aeb35be,0x0003e71fba83aa07,0x0001d959d8dc768f,0x0000eb913a4c91a2}, {0x000e183a28b0b33c,0x00088becfd84e460,0x000c958afe20d5c9,0x0004b5d299882015,0x0000649765aefe9f}}, {{0x000230fd8633e864,0x0001f08ee9e87f37,0x000e6f193bf5b4b2,0x000cde4fcb7532ce,0x0000104b82017ce0}, {0x000132f59550b517,0x0009ea49ea36c092,0x00091a39ec7cc727,0x000b70bfe7e175f2,0x000021a2ab8b1372}}, {{0x000eab9e1005ec21,0x000f75e979b06cba,0x000c6a4d8a9df400,0x000a67cc9a2af77f,0x000035cd470f6031}, {0x00096537b57815e9,0x00097e2741ed2894,0x0009a6fac39520fe,0x00003d6cc06b9003,0x0000eee76b0b2e06}}, {{0x000f7b48f6edb04b,0x0005a929e3038237,0x000f7857536e7673,0x000901ecac573596,0x00004eb199d3fae8}, {0x000d3cac11a43ab4,0x0000d55fddc2f291,0x0007aa2635d37480,0x000ab944155f4673,0x000043238379f1ee}}, {{0x000de044927b3f1d,0x000241bc54ae6068,0x0001082ef75dcd95,0x000d7d5dae8d8aba,0x0000eb60878f5e1f}, {0x000c905f7e55fe92,0x0001e240bd8a7772,0x000081d2630467e4,0x00059a6904f58040,0x0000ecaa62c1a4d8}}, {{0x000e9f68575333da,0x000f00ecfae86bca,0x0009f8c83e13f2bc,0x000c5c3e371a2ec9,0x000037a85cb421a7}, {0x0005b5a329bbed02,0x00045419c8fd74f1,0x0009823120e28310,0x0007e3cdd91afbd7,0x0000839b1b682506}}, {{0x0006e9d3ccc341ba,0x0002150f316b25f3,0x00080a38e4c7c7e3,0x0003c01f7e4d50a7,0x0000c3ea0d40f57c}, {0x0001c7b30f55321e,0x000e7d20d94bdaea,0x000a029fadf45df8,0x00097ee167f6b768,0x00002aa6cc9459c7}}, {{0x000c17a91f1ba0e5,0x0009787593f0d015,0x000f9ce851544d29,0x0000a7d6fd2eac07,0x00006e42a2d03161}, {0x00047f0cf39d2dc2,0x000e394ce9aef618,0x000c79ad7bb38167,0x0007952cfa312fd5,0x00006e9508b6606b}}, {{0x0004a9337b6501f3,0x00038724b1274086,0x0004b9735e20280a,0x0005a7b1685a2355,0x000049e5df053c39}, {0x0003d8976fcc51f6,0x000f211285be64a1,0x000a5a1dce61af27,0x000534f6c0f84385,0x0000330e4e187016}}, {{0x000e341cd1abcafb,0x0009212e247ca60e,0x000d11cf4928ec27,0x00068275c242a86e,0x0000701b7f29cc07}, {0x000113f0cb2d0c5e,0x000a0e15728ff118,0x000ce069dd37a910,0x000e33fbaf062392,0x0000da9bf4139bfe}}, {{0x000d893ecc8a3843,0x000aee3422fc03c4,0x000bc5cc45125f34,0x0003fa03d850b732,0x0000d9db328e612b}, {0x00093a198c9fdc42,0x0008d59f8b1b219f,0x000cf49c0b2febe9,0x00075e07a055d8a4,0x000070db58a14b84}}, {{0x0001b49f9f74da4b,0x00079c277b30b6ae,0x0007a713eb7573ce,0x0004bdf55e41397d,0x0000c4c19bd84865}, {0x000931c026a86997,0x000de2bca5cf171e,0x000656b2300e38bb,0x000d5f65e8930d8b,0x0000ceba324ca80b}}, {{0x0000f392145ceee1,0x000cec5519c0f83f,0x000ccf35a80091ac,0x0003f61fdd589fd8,0x0000aeb32670044b}, {0x000c35391cc68921,0x0007d7a227dab6a6,0x000a75a4bbb2c563,0x0004940e0441f13d,0x00000acf8254d41e}}, {{0x000b7c2475bc8687,0x000275d5d3d4a8e7,0x000998b4c20aa04c,0x000a5a3f2c0804e0,0x0000f72faa30ab18}, {0x000cd37890ebf796,0x0000909c43568186,0x000ac20ea2015287,0x0002acdab79ef3d0,0x00008e23170d603d}}, {{0x0001b7430856e702,0x000e326886326e48,0x000c9d6b951f2e59,0x0004074d31e623cd,0x0000e0b17d35a649}, {0x000830e9a2c52388,0x000c4af19a13dffa,0x0006e6405881b51b,0x000b8fb31e1b7bc8,0x0000bc0283606a6b}}, {{0x000cd1399b0fbf20,0x0003ae7bfaaa7476,0x000515068398a2ea,0x000ccf4a67748a0f,0x000052c9dbaa0de7}, {0x000b107df0bab755,0x0000bf5cd043bd9d,0x000ca0aad0f46f5d,0x000122d95fa8e659,0x00004b88235175a9}}, {{0x00063c7b5bcf7a13,0x000e4a0fcad630a2,0x0002e5101cfd5a29,0x0009bffc7f24c1e2,0x00003d1eff35a181}, {0x00005715a33e4b08,0x000243d6669d649c,0x000cac16fe982911,0x000ca0d08374e968,0x00008326799f5651}}, {{0x0005bba6afc5ab95,0x000f1153dd46fad0,0x0005a6b8ed84540e,0x00031d26cc136a2a,0x00007c4b8712243d}, {0x00093b3f4bd9ae24,0x00099ed80b28abfd,0x000a5a784db8f876,0x0006abdfb9bb8a47,0x00007c9037ec1306}}, {{0x0008517c194a6c3b,0x000ff8b4e080bad5,0x00095ef1ab25163b,0x000fd601840b3f70,0x0000f57e65fa20a0}, {0x000761f8718a4635,0x000026a37b1da3f5,0x0007d62b14f1d622,0x000a97dd8bb7dfe2,0x0000b65d15c8388c}}, {{0x000fb630f9f3c36b,0x0003514f1507f908,0x000709730fc5a09d,0x0001a551491ecda3,0x0000eace9768d59b}, {0x0005fa0c62ba40c9,0x00057a73f9217bef,0x0000e19c42c546db,0x0005238d4079ca10,0x0000ca0c26f55313}}, {{0x000ef817c3b2618c,0x000516c3678b7d65,0x000af4eab31e6d46,0x0005e838846fbf7e,0x0000cf31a0360563}, {0x000d8d7395cabd57,0x0003bfdfda36daaf,0x000e52df3d83d332,0x000c0c667a2f6684,0x0000e1a16cbedcfb}}, {{0x0009566376fcec40,0x0004537333dd7cc5,0x00051d3c0941a4af,0x0000dbfb72206ff2,0x0000e6496b4df3a2}, {0x000340da7a61207b,0x000de24d61e2c6b0,0x000afa106554c6de,0x000514a942394f93,0x0000959becd8bae7}}, {{0x000e7c288392edd9,0x000e09e87173c5d5,0x000badf27f43f861,0x0000875f56cbbdc6,0x000059011eb4dd0b}, {0x000b4176f01cea75,0x000d52c23a0d6c81,0x000f0b5d771b4b78,0x000415b0fd29a184,0x00006d4d765d5cff}}, {{0x0004fbf6e5ab1c10,0x000c5e16117aed34,0x000068ab71d61e70,0x000d5853f76aac64,0x000041afad97ee21}, {0x000f2590f3380ea0,0x0000057fe06e1782,0x000ac009aab5f995,0x0008523a89866ffc,0x000010ad3182779e}}, {{0x000edf9d8e340aa5,0x00013c432c9525be,0x000c5b0938e52347,0x000f7f2b547dc9ce,0x0000337edbcd4751}, {0x0005f8d089a8d34f,0x000849d94da27c6b,0x00021344d3091355,0x00019ae8dccbb520,0x00003db4afef5bb0}}, {{0x000221483572979c,0x000f488d38f240cc,0x00001d197443feef,0x0007cba0ff6fdd65,0x0000c8ed1a1e245f}, {0x00043ac345ea9f35,0x0007ed4c13607cff,0x000ee8dc785c5171,0x000ce453e3b03a22,0x00000d9cd4fd626e}}, {{0x0000e350ac33d68a,0x000cd316d7ea5a59,0x000d601e37ae8df2,0x000a613a4ef1b40d,0x0000b969a55dfd9c}, {0x000b7d820baae471,0x000789e5546e638d,0x000adea90d131722,0x000588b4bafc01bb,0x000020136f521961}}, {{0x000719f9325b2400,0x0005ba8ad2510bfb,0x000c18046ed327c0,0x000dae7c4bb581f8,0x0000f5c43bf2821c}, {0x00064d2b8967b272,0x000ff2fc977093bf,0x000e43bcf14f6a54,0x000c6150374246de,0x0000edc1c38954d2}}, {{0x000d28e4579a1c60,0x000a23ad0bc91684,0x000159efe0e89838,0x00013c18b907beb2,0x0000f982933523bf}, {0x0005a3d80fcaa3fd,0x000e71da29914720,0x000260190947110d,0x00044d6527935a8d,0x0000b8cdec4b3dda}}, {{0x00078460ca8fa191,0x000f5396fa5eb6d6,0x000f8451a2349560,0x00008834935f4c4c,0x00009300128571d5}, {0x000dab31e4ba5a79,0x00014b60c848233f,0x0007e000ae8f45d3,0x000156c4a44930f5,0x0000e9ee0a99bbad}}, {{0x000d5403bff252a4,0x0003c2c93f8b1649,0x0002ae1a111254e6,0x0008a652e0510e35,0x0000025872deaf32}, {0x000f49fcd577ca3c,0x000a66df694207c9,0x00088c106ad78c7e,0x000eacacb6deef66,0x0000ae91691d5244}}, {{0x000a1a6556a90c69,0x000f247842e0528e,0x00055287f1f99c51,0x0000834918eed56d,0x0000addf95032778}, {0x0001770d1ffbb4c6,0x0006ee9a94d1ca36,0x000a5c9aeb4f8224,0x0002c9a6b1ea0ae2,0x0000815b08430763}}, }, { /* digit=14 [{1,2,3,..,}]*([2^98]*G) */ {{0x000dc06264c6edf0,0x000ee76ada9f8a5a,0x00093a29ac0d4b89,0x000bd589805d8eab,0x0000a3f857d466c7}, {0x0008cdc0af4d7692,0x0003a4587e2c7fe4,0x000068fb7ac8249d,0x000cf84bb97b33ee,0x000025f782d1e221}}, {{0x0007b344d830d611,0x00090706b372f099,0x0007c5d82081ecfb,0x00062e5f1d371461,0x0000630e68f8309b}, {0x000027ecab0d0e7b,0x0008eeffeefc38fb,0x0005a3f00f139e51,0x0006235555687383,0x0000000539130fe6}}, {{0x000a7d994abc3339,0x000eada42542f0dd,0x000d2774877be20f,0x000d3e01fd92532d,0x000045b905b58c4b}, {0x000f4f6018764c26,0x000b906b0e9ad737,0x0005a7ddd213dad2,0x000979cb47e139ca,0x00007e5ac0e28093}}, {{0x0005bb244b1a7745,0x0004d3be15ecec3f,0x0006b92215c50b54,0x0005c2343f4af69d,0x000061a0fb33d6b8}, {0x000996c8fb6c5f4c,0x000f7c15d9d2bd46,0x0001d8db7e469c42,0x000997e76e202eb9,0x000079e3e7b012a6}}, {{0x0004e3dba4f34c34,0x00037e53915042c8,0x0002eb606a8d77ef,0x0004eacde90607b9,0x00001bf86bfff708}, {0x000dcfe17dc51185,0x000be051f4755508,0x00005d090cce6cc7,0x000d86e74d036824,0x000003082999813d}}, {{0x0008952a021a9b5f,0x000accd265a08868,0x0006f5e0a1762020,0x0001ec077c5bca7f,0x000051a150e7a0c8}, {0x000c4dedb17071d6,0x00091d7d3367b9a8,0x000cb4a59fc13868,0x000144624e29dd68,0x00004aa6d75f039a}}, {{0x000a3fa97e6e0640,0x000d7477c822e5cb,0x0006d71cfa74fbe6,0x0003b6e7f42fe5a5,0x0000e15e3b313245}, {0x0003747e55840168,0x0000f0b46d9f18e2,0x00012b245efd94b3,0x000e0e8bb7ed74b5,0x000071a6634049eb}}, {{0x000afafb42e29add,0x00018d9ad91573de,0x0009c54ad6e3aa89,0x0007703a1f57b2de,0x00004626948ca4b6}, {0x000abbb815e6ca50,0x00035b40f7f54940,0x000a08f33a48dad8,0x00084e31e14799ef,0x000095a109d11471}}, {{0x00002547eca94470,0x0004a32c671602cc,0x00040116a86806e6,0x000e8db86a0dfb11,0x0000467b5c6238db}, {0x00065c7b3957d267,0x000579251baa175c,0x00083f53398cd355,0x00066bef5f51a807,0x0000599690598dba}}, {{0x000a1e066f254055,0x000e6ae221534d5b,0x0008d3bb91428e24,0x000b46795bd47970,0x000023f090e0e98d}, {0x000018f58c20dcc8,0x00068a6f249e38a2,0x000915d4db72af54,0x000729b41ac98972,0x00001f3ec32bf5b1}}, {{0x000c30853828ecc8,0x00003ae49031a5b0,0x00016d35710f0304,0x000166de6aa30f87,0x00000b38f0b6be3c}, {0x000422386ba22348,0x000d2a6b4a859201,0x00069a2f618226b7,0x000dabb6b9065ae6,0x0000a1c3854e2ba7}}, {{0x00086a14823ea47f,0x0000554a1c55f1c1,0x000a974aa782f893,0x0008ae49b3fe8e67,0x0000129a2c97602f}, {0x000d903dd777718a,0x000e76223c4293a4,0x0009a1637ef4efe8,0x0000b2f996c38d78,0x0000dfebadce6272}}, {{0x000d950e92810589,0x000774dfa90b0136,0x000039faf2b175ce,0x000e185a260a83db,0x0000561f8e4b6c93}, {0x000ebf0e2fe28b50,0x00034acbe16edd05,0x000320d07af8414a,0x0004430be5fad27f,0x00000ee98f0868da}}, {{0x000cae8c6791947b,0x00007996853c4c82,0x00019a0f47f2509f,0x00004935af953959,0x000027cd71f58bb6}, {0x00083fd8bc62211c,0x0009bfefe89d61da,0x000ddddf3c87eab0,0x00047e03a5e0f6f5,0x00008b3c456c5505}}, {{0x000137df36f714f4,0x000582323ed21aa9,0x000cc68386a00b41,0x000bbd594ecffcce,0x0000cecf5b089abd}, {0x000983eaea96fcfe,0x000b24d12f6ae33a,0x00053fa16977b26c,0x0005befbcf594bb7,0x000088d8f7495883}}, {{0x0007b8acedb9388e,0x000400efbaa8ca48,0x0000a06b17cd0588,0x000a7400dc760aec,0x000015cdfa858e76}, {0x000e7f3b8048b0e3,0x000ffae832778b42,0x0006b52cfbc15e64,0x0000d578158f0142,0x0000af7e47c0508f}}, {{0x0008eb22823149ed,0x0009745fbd4f13e8,0x00047180965d7326,0x000b40df9c9b9a8f,0x0000c9f0be3c6954}, {0x000a28f9b361f46a,0x000c072e07a5a9d2,0x0000f2ed0ac3a2dc,0x000392aaeebda466,0x0000336c3e9cacdf}}, {{0x000d1d43afceea08,0x000616a9cef394de,0x00024432a5bde0a6,0x00043191915f59c4,0x00002f62d7e1fcac}, {0x000fa75ea0b786d5,0x000a12c9de645b54,0x000d5287986117cc,0x0002a68bb817b967,0x00001ceae3eadae0}}, {{0x000b7ef5b2d3b2f1,0x000000070d048432,0x000c6c03e4e7e07b,0x000c7ff417809ed3,0x000025fe6da4c479}, {0x000e17e440a00118,0x000671aa9008cffe,0x000c32ed6a56c499,0x000f577463eea607,0x0000831162ce69d7}}, {{0x000e4805943376fa,0x000b1eca3608d8c9,0x000ed34782092af8,0x000ccd599e1ef20e,0x00008d7322137ad2}, {0x000f359d5c8c0d56,0x00038757adcde109,0x000514301b31564f,0x0003bb5fcb028045,0x000004f028be60c4}}, {{0x00058323cd637177,0x00028200d4cf1cd6,0x00046e38835c4220,0x000d0b6ca712117f,0x000024a80f8a1923}, {0x0009bb310add934b,0x0009b0984f44f959,0x000603516ff5e5c7,0x000bbee13c21257e,0x000090eda9f674c5}}, {{0x00005458fc6dd126,0x0000947af627b5ab,0x0008f966ca449c6d,0x000b0cc003e78cf1,0x00008256aa596830}, {0x000a0e079d35b70a,0x0009940a5f36cb04,0x0000c3f2d26877d1,0x000730ed00d82660,0x0000ab865b6523ff}}, {{0x0009177f2d61f6a6,0x00066af811bf4a06,0x0003b1c247bd378c,0x00062465ea93b39f,0x00009171cdde60f3}, {0x00095252b216763b,0x000749e6bd882dfc,0x000ff92142ce99f9,0x0000524b31478981,0x00009b67920e8098}}, {{0x000f5eab873e5982,0x00002b05e8702523,0x0009e3071bab7eec,0x00049dcb63dd8dd0,0x000065a0588f39b8}, {0x000f19f79a322046,0x000b6ebf2f4ddf97,0x0002dafc0af5691a,0x000d2c5d445ac1d5,0x00000c9570bf9541}}, {{0x0008c920c8a7eca8,0x00034d2fb0311be7,0x0001335f7aa6a1a4,0x0005a8062bc8fbb6,0x0000934c72c41287}, {0x00035614cdaa4860,0x000b9d9596f7a99a,0x0008ec39c47104fc,0x000fd127b936a44b,0x0000930bd26ecf89}}, {{0x00031bd38f4959f4,0x000209f43efcc5ff,0x000222f36c2b77df,0x0005f4ea5ceeacfd,0x0000dad55f834b8f}, {0x000abbbfbb9bf288,0x00085dc8869ed851,0x000c867e63c03f7e,0x0008257f770d1a05,0x0000ee1f000730c6}}, {{0x000b8711de100539,0x0006ad95dfe207b6,0x0006cb512680143a,0x000f506e2c18fddb,0x0000bce3ca0378e8}, {0x0004eb8130d57fba,0x000fa5840b8715bb,0x000c84823eaae39c,0x000b26629e9d3145,0x00003031a8c8c1af}}, {{0x000fec3fb7df9633,0x000f793017b5239e,0x000d417edfbe62de,0x0003a2bd4ed6d43f,0x00005cfa222922a4}, {0x000cd26d9111ed55,0x000332b5b95f6de9,0x00094dce34d4e23d,0x000ea1652aaebfcb,0x0000a74a2880fcc4}}, {{0x000b85e6b698c60f,0x0006bd05bb9009a9,0x00080f4cd386aba1,0x000414fc79987378,0x000022a41cd0ade5}, {0x000386b37f02931d,0x000144ed3b36adc8,0x000831113fcbf024,0x00062655c85d148e,0x0000abf8c2abb579}}, {{0x0008a280beb3d98e,0x00022e4dceaef7f5,0x00019e2cd5a2c67e,0x000d97b0a1fc4ced,0x0000ccb55ec7430e}, {0x000927ea8db4dbb2,0x00054287f738760d,0x0009e0694ad868fc,0x0009547719050c59,0x0000b8bd54ad1b07}}, {{0x000b919915296235,0x000b9440eecccfab,0x0000df1d4f7f9db7,0x000fd803b66d2b79,0x000021f810f61fb8}, {0x000374ab0babbfca,0x000b1da810b6567a,0x00007019ae31b3a4,0x000e6dc732421879,0x0000aee1fd5d3d9e}}, {{0x0003dca799b1e8c7,0x000498f64369d75b,0x0009b0643f842b8f,0x0001b609c435b8d7,0x00009e18a4dc6dd7}, {0x00093f286cd43de1,0x00000522ebfb1d7b,0x000981ef58ef5f5c,0x0009a7c511d1c979,0x0000079e84ba8d07}}, {{0x000e22bd3c256aa8,0x0002fd4c94bbe5d5,0x000ad29c666de35f,0x00035e3b865874b6,0x0000224e3c128523}, {0x000d5f4d614945e5,0x0007845bb7831b45,0x00099e134cb89357,0x0005ec39f9f5f9ca,0x00002f887fca2984}}, {{0x000ef0e4412d59f4,0x00035ee9036e0f4d,0x000ddd0c48d53893,0x0000fc472a1ce74a,0x0000a17b9b8404fa}, {0x0003f18afac2a705,0x000d43fe74db5f3c,0x000c2267174d55ce,0x0000895e0f14e108,0x00005dd34a549d92}}, {{0x00026468b946678b,0x000bad393b4640d4,0x0009805afa144f1f,0x0005586d58b328cd,0x0000b5a443e9ccf4}, {0x00058637fc0a22d1,0x000e069b47544588,0x00019ddb88467c90,0x000d6df432509399,0x0000e17ce7f02ef7}}, {{0x00091620e2b9010e,0x0003b1a55e8e98b3,0x000c2c0459f0e8a3,0x0001e1dcfff42fc9,0x0000dd65a82c1053}, {0x000a151f4aca9977,0x000c1b7e25a6edab,0x00038c1f361d8bb1,0x00000cd30261823d,0x000058c4491cd6bb}}, {{0x0001b0cb59285f27,0x0000f4ffe44d5c38,0x0003e8dac0335ca3,0x00035f7325d84a82,0x00005079b33341fc}, {0x00012eba3b28d558,0x0004bcc94ac65271,0x000e2e85b998a96e,0x000224df60868980,0x000070d7cdb23165}}, {{0x0004ee5b665a2bf1,0x000dc11697de8321,0x000e9fb2b99d4d00,0x000b6248a3b6b7cc,0x0000ebb83a1c6e31}, {0x0000e7f18e605d33,0x0006d595cf04d7a0,0x0008c209f036abd3,0x000f7b5e7c03f37f,0x0000202f91c41e8d}}, {{0x0005fed58160235b,0x0004f5fcdab49aa8,0x000ad6f5b0d663cd,0x00046955fcc1cc31,0x000055aa92af2c90}, {0x0003cc5ae6b06c50,0x00057eaea58e748e,0x00014924cb8d73af,0x000859aefc2fbb85,0x0000055f1f24388c}}, {{0x000b0ed88e1a7efb,0x000e7ceefbfc0fce,0x0006d857cea82848,0x000cba7abdcd838d,0x0000ec1dae8cead4}, {0x00000a669ceda0f7,0x00011d3126dfc250,0x000f4b9ca2e7c1e0,0x0009b84cbfd34e07,0x000040e4bcfea9b1}}, {{0x0003f728819ea128,0x000b06e16cf36161,0x0002919408897f08,0x000e528858cfd6a6,0x000058155bc25fd9}, {0x000ae2986292c0c6,0x000167af291c84aa,0x000e79cb6ec4f1f0,0x000c81fd358f1993,0x0000ce475e3b0ba1}}, {{0x000f785374d12d02,0x00012d98caadc70a,0x000d42f2a8babbf5,0x0006c2fa867fbae1,0x000053850d2b0795}, {0x000def812567bf3a,0x000d771344b51fe6,0x0006e684f2a6edf9,0x000c5e0a73f6690e,0x0000e282dbcf75a6}}, {{0x0006d9be5836ecb2,0x00020a13c0defb0b,0x000e52387a145e68,0x000f89ba1fac2f4a,0x000009824d57a58e}, {0x000dae8413ed668b,0x000ade3adc47d3d5,0x00080a12938ac94a,0x0001e632ee79ec52,0x0000a4e43332753f}}, {{0x0003b2a5bc9d9932,0x000a0b017d90e7c9,0x0008d33771f5faba,0x0001f007e829cfb3,0x0000a6756330d4e3}, {0x00071776f7f71d2a,0x0006552d8f758b90,0x0004bfebc559f745,0x000c49858fe49424,0x000017dcb740493d}}, {{0x00036a95aead4696,0x0008faa7b0da3af4,0x000525e90dec1412,0x0008746bab082157,0x00007f8eaf99f609}, {0x0009610fdfd3120b,0x000a43ab469f1ec9,0x0009ad77bd19d496,0x000fd9a9a5d8758d,0x0000da7732d94025}}, {{0x000ed2476d66cd25,0x000cfb4dafef99b7,0x000305d194636025,0x000c900c1346a4a9,0x0000bf0491ebcdab}, {0x00076b6079e2c2ca,0x0008b0b6c5b084b1,0x000dc7edc14533fe,0x0006f61b6cefcf0f,0x00003ee45c6b478a}}, {{0x00092f1d816eabc1,0x000722ec5d199636,0x000d057ce2867339,0x000d5e74d26433eb,0x0000e5c102c41805}, {0x000cee82359f79ac,0x0007e6aa805964ea,0x000dc458eb929320,0x00072db27bd3f9bb,0x0000da2bf8fef359}}, {{0x0002a01a0a8db27a,0x000a64fac978817d,0x00003993bedf7365,0x000f0423b74a2535,0x0000333bccf9f3ef}, {0x00020cdf3fdfc059,0x00040b069a38f55f,0x000d5dce6c8fed38,0x0006a5e2563db264,0x000065193986cacc}}, {{0x0008add2e2366c41,0x0007d5b50c4b1c42,0x000492b8899d7804,0x0004015c2e9b786c,0x0000f1dfde4b6b08}, {0x000d8bfe14c5f775,0x000829260c708e76,0x0005519b1411e966,0x000b9c856fae8b5d,0x000022c66ad8a1ce}}, {{0x000b24afec4eb474,0x0009ba269084ce0e,0x000929f95b4dc777,0x000103abb56c569f,0x000039c57b19bb9e}, {0x0009031d0f495421,0x000062aa769f5f16,0x0007f07c0d92f631,0x000de2bef7db92f6,0x0000309aec890e63}}, {{0x000cd3221ad58754,0x0002a8fe3bfffc16,0x0007b21f1823e90d,0x000f9fd19412d4c9,0x00004e8e63528a95}, {0x000e5d23d1dae12b,0x000a643cacc7fff1,0x000061101366f4ce,0x0007da91960c70f9,0x0000b2e33c5a3b2c}}, {{0x0000f0bc9de883e4,0x000832bc530773e8,0x000d6df7a905063c,0x000a3c143b5a28fe,0x0000e8befcc34662}, {0x0007800fa2c481ae,0x0000406435301c79,0x000f58b02d2a187a,0x00023349b0fc5eaf,0x000039152a95f548}}, {{0x000eef8fa126aaf1,0x00086d7f5322c9ce,0x000e1277f0f736ba,0x00079b9f64d938c5,0x00003a4c8e990669}, {0x000b0604ed199f47,0x000bb8abe33c1b87,0x0009c5ec77b8ec2a,0x00068db6e60ca7ff,0x0000e2cbee08542a}}, {{0x00097c18666cd322,0x00082e95d7c8b9ef,0x00093771f688714b,0x00001533c086020f,0x000059d210c8cad6}, {0x000146ca0174b83e,0x00073cf08052cb68,0x0003514a6f0317c9,0x000ee2740ce05a48,0x0000abd0c44aba33}}, {{0x0007d09b4e2c6759,0x00045d92c0b09bb7,0x0009f5fadb7aa0a8,0x0006eb2aa8468c02,0x0000370e2b02e3bd}, {0x00010c5a05206771,0x0008d7564df22bf1,0x000eb5eadfc154a9,0x00080f2066bbcc22,0x00004986aca010b1}}, {{0x000304ad640228e4,0x000ac74a48b12e47,0x000d9f11db8146e2,0x0005ae640f64bb3f,0x0000acaf40843993}, {0x000ef32dfa787e99,0x000d6ba59fa31a9d,0x0002fd7827169dbc,0x0007a251119b89c6,0x0000bb57c8e0e96e}}, {{0x000a64d08043f76e,0x000da608af1ec1fc,0x0006d54e3eb16ab7,0x000343e63bacf520,0x0000468f9a504a0b}, {0x0005095ccc8689fe,0x000dbfc0d9ad075a,0x0007a7114b6bd402,0x0007cde5f2d4add3,0x0000ebcb63ead038}}, {{0x000f2b16e394b9b4,0x00089a6e75339f88,0x0008cab78c7f95ab,0x000401234f291dc7,0x0000822d72a3dc49}, {0x000c53f4bd8392a2,0x0002d49a448fe0fe,0x000a59bac7adae0d,0x00085a96b5bb8fca,0x0000dd8cc17c987b}}, {{0x0007f9fe72d2861b,0x000fbe6490d8b0f2,0x000f57650932916c,0x0009a9e1d65e06ec,0x0000368b49073e56}, {0x0000a09ec18478ba,0x000abce485c1be25,0x0009c2fd23e9d0cb,0x00070b0b05a40e0a,0x0000c0ac2a141ed4}}, {{0x000b7f57b5a811f1,0x00003a332880bf5a,0x000f6ed2c331b72a,0x000c931b13881ef1,0x0000c494779169fb}, {0x000ff8589c026ea0,0x0007bf5b9f354528,0x0006516d66583a3c,0x000f0465c5c1aa93,0x0000533827189b9f}}, {{0x0005d47b7457ae62,0x000e4dc51a1c0b6e,0x000a10b057309d30,0x000b80ea82422056,0x00006b7b1f3b4fd2}, {0x0008248dfe28471d,0x000da74653e6332f,0x000c48220afb600a,0x0002c84e00411034,0x00009c3060c6f37c}}, {{0x0005a2209fb690bc,0x0001a6a994eb0794,0x00095af9bd66e6b6,0x000d3705c195b4b5,0x000080dddd3881f8}, {0x000d168d5bdbac0a,0x0004b0d2f72778b2,0x000fe8afb40cf8e5,0x0002a796b74d05e5,0x0000b591f243ce3f}}, {{0x00024db163540742,0x000b30cc20fd6460,0x00051c51aa345835,0x0005a09a17bb71d1,0x0000277fb5139649}, {0x000d2c2542771796,0x0004d1f708634ac1,0x000d7e0ba72c1b8a,0x000e347e4f17f54b,0x00005fbc77bc2e9a}}, {{0x000e083726268248,0x0003e07229767fec,0x00046e11f43b98b1,0x000a62eb12d4a2ea,0x00004a6f742ff8c1}, {0x000d16b330001ec8,0x0003aebe7cce5d32,0x000632924719bb7c,0x00039e6ff7ca5c15,0x0000f3e8d249e5fe}}, }, { /* digit=15 [{1,2,3,..,}]*([2^105]*G) */ {{0x000f55e0ced7400f,0x0003959d5ee8a6a9,0x000d3d46dd0617bd,0x000c3976364d4eee,0x00005d6544ad3ddd}, {0x0007dfe795845bb1,0x00083b8c79468842,0x000dc535a3e15078,0x000da895f764d5c3,0x0000ff1d2743a1cf}}, {{0x0003913423373fef,0x00099abec687f2cd,0x000c07192b34ea8e,0x0003509d102ac466,0x0000f4fa4a09c2d6}, {0x000f87ba71f45a5c,0x0001a2d1230874fd,0x000228058781f14e,0x000e8a4b4499f2d0,0x0000de5d3cffbca3}}, {{0x0002e2e7392ec41e,0x000f0600583807b9,0x00044309ceb93a1b,0x0001bd4299d5f2dc,0x0000d341d792fd4f}, {0x000f7da2004fe859,0x000e680815368116,0x0000f675be924d2d,0x00063913a6fbfc35,0x00005c62b2743092}}, {{0x0008a0d964e634ff,0x00016c532fb1c163,0x0001f4d76384f515,0x000adb344233bc23,0x000006bf9a0792cb}, {0x0007491415365c1b,0x000c3dd1431327e5,0x00020f4fe2b3068d,0x00070d4734ccd16b,0x000095b95b5bf075}}, {{0x000761a38bb70b8b,0x0002166f263692b7,0x000d87e0b6acdec9,0x000d4767e1fd967e,0x0000224a8eaf9729}, {0x000363860e37a986,0x0008c4b2e8807f28,0x0004c4d7e510f286,0x000ce1a869283ca4,0x0000c3368915a32c}}, {{0x000ff0d6cc67c43e,0x0004588de301c896,0x000096bf10683593,0x0005e94798800c86,0x00006f62ea26dac2}, {0x000a1e2efe6138ff,0x0008a3848069990f,0x000443db897dd7cb,0x00054d1aac07ca40,0x0000b2c088eca6ed}}, {{0x000757ff5dacb5df,0x0003409dfa108aaf,0x000d1d3c5b1d8fa4,0x00021c63739d04cd,0x000002d31bfad6af}, {0x000e35f347dbf5cd,0x0006989679f1e20e,0x000e1a052e17f4f1,0x0005c7e7fe010b19,0x0000b14dd7d01c8e}}, {{0x0007e840f9e4040a,0x0000a26798b65abf,0x000aa3d54ac179a9,0x000acbb1e5e42083,0x0000903524ea794a}, {0x00076ce040ccabc9,0x000befaca5bfabb7,0x000925f5fab22e60,0x000bb22783ab4b8b,0x00005d8af2205673}}, {{0x000f399058b20522,0x0000dd5d61d0c0af,0x0002ded111c639bc,0x000df9d3a3f3688f,0x0000b2d2d7fb44a6}, {0x000af40a6c2a4094,0x000fe11fdb14a199,0x000a1ab6062e9058,0x0007ef709be94066,0x0000fa64f9da0087}}, {{0x000b4a8964e772ad,0x000159d89cc553ab,0x000c8bf365c823e9,0x000a41337be0bf3d,0x000033f0eb462664}, {0x0008667a8e33616b,0x000bb9985acdac62,0x0003608bdf3a9d74,0x0005f0bcd80283fd,0x0000986dd5d601fa}}, {{0x0009de4efcc85c15,0x00096f139013d950,0x00057dacdd1eab4d,0x0006ecb65bd6678a,0x000055db869cf233}, {0x0001dd30ad5ab142,0x000ee6314b871bd5,0x00033a0d66fdc7ae,0x0005777e6357c61e,0x000026c5eda33aa4}}, {{0x0006dc5456e8775c,0x00046e911188ec30,0x00090025c7708950,0x000a20b40e8e0032,0x0000e507b2640d0c}, {0x000d535e705092a7,0x0006166bd3b5bcb5,0x0004cd250c59127e,0x0005550d02d21554,0x0000e39d008a8c05}}, {{0x000a050a62fa45aa,0x000e1007a06593d1,0x000091014c6dbd3d,0x0004f5b6d0706a49,0x0000f6d6e35f5c39}, {0x0003b19cd3f850d4,0x000b5e7d85a52f32,0x0009e78ab4f434d5,0x000e32db2b9c0723,0x0000b10cf992d5a3}}, {{0x000f592e7efa4378,0x0000fd0f0290dce3,0x000a14ca9b7d8b33,0x00085bdcf8aefff1,0x00004f13e355b1ab}, {0x00008a0f61a817bf,0x0009c5549bdd0f62,0x0009a0730387141b,0x000a93fd602598a9,0x0000cd8cdef9e264}}, {{0x00004ae9a503381f,0x000a859248c8366d,0x000f3a32b04731ef,0x00078d74accfc96a,0x000061c0b6905f8e}, {0x0000ebd5f59d1b15,0x000331d6846375ff,0x00082480114edc5a,0x00058cfd89817663,0x00006f41ecdeb28a}}, {{0x000aba7b5341a587,0x000bbbdbc220d5f2,0x00002e2f859f0298,0x000c85b9d62c9cff,0x00004cb6beaa83a0}, {0x0009ed02cf8d6bf1,0x0009bdb17547e9ad,0x0003397b4afb4753,0x00091a79f573a86a,0x0000919e0860dce7}}, {{0x000d88918e2f47d3,0x000f6264e8e698b4,0x00076fd1ccd75cde,0x000411bc9ae6e276,0x0000d08e3e91b76a}, {0x0004a951353f00ca,0x000e856c3a8b5bcc,0x000143eb164cf5f9,0x000249e23f45b2a5,0x000001ab36c56983}}, {{0x00042bf7db15975d,0x0005d84f2911ff78,0x000a7eef9c1ef2df,0x0009ce3c9dcfc71d,0x0000f79ee6983307}, {0x000ec3041bc41cb1,0x0004a53e33bf1432,0x0004e1053cb62983,0x0003a7aa20e23f98,0x0000b8294d01f0c0}}, {{0x00048d0372d37ea5,0x0007626c450c99bb,0x0008f91caa38c50f,0x000b126bffd090f3,0x0000f3229a1aac39}, {0x000fd864b7a8296a,0x00036564a892a1ff,0x000a8d75bf858c5d,0x000d9ad955b9a736,0x0000da662d7fc17a}}, {{0x0006ba795e751920,0x000846f147608e81,0x000ad1441e7d892d,0x00005e448a0cfc30,0x00005a4d96d983e1}, {0x00004229da172130,0x000ea801e09a0949,0x000fe63f9fc0e627,0x0001c8d681971a10,0x00004012304767fd}}, {{0x000a19b17530f16f,0x00043fcb789432ba,0x0001dd7acbc549a0,0x0002eb708cbe384a,0x00006369e0348ead}, {0x000a6090c1b89596,0x0001c1598ed95616,0x000f9fbf0c2ef829,0x000f07a5a10b751f,0x000083266ab6634f}}, {{0x00006753208ff59b,0x00024fc44d274298,0x000b8da4cc5e633c,0x0001eedd9e76d668,0x0000984dc35fc919}, {0x000742fdc2fb0b16,0x0003f1a37ea501bc,0x000ccd5c8f47f7dc,0x0004a12079fcbe1a,0x0000d15e05379840}}, {{0x00012f5c7b57a458,0x000171b1fea8f655,0x000933ccf5a81d61,0x000369e7fda656f5,0x0000c0ab37cf5bb4}, {0x000b16333f34c676,0x000fff92c2932e05,0x000f70718aea2f68,0x0006ad4391ab6d2d,0x0000b621d11d77e2}}, {{0x000ee9cb342f4650,0x0009e9f60819a72c,0x000640fbba78926d,0x000eda1a2390b4ef,0x0000ca57e589451f}, {0x0008eb97ffa2d64f,0x0005596f4451997f,0x0004125bb6a63afb,0x0002c6b2bdf70c17,0x00006643535dcda9}}, {{0x0003cdda9cd82b35,0x000509e3611c4e81,0x0003f16e05c37f8a,0x000b18efdffa6c50,0x0000bf1aed211a9c}, {0x00082a34eed8ee8a,0x0000444ef3243f53,0x000e9936c0eb0c00,0x000a9ca6ba337bc5,0x00009e6106f21806}}, {{0x00025aa6380f2af4,0x0005491d9d165dff,0x0008eb846ca78f20,0x0003a9f6e0d46b69,0x0000928b01e0eb89}, {0x0000f19d4744bdd2,0x0007232b1a35b4a7,0x000fcfede71fc522,0x000c5bdc58c9372c,0x00001f4e89d71396}}, {{0x000b414c8ec0e785,0x000a1033d145c6c2,0x000e07a15d9a7bd5,0x0008686748b7db2f,0x000064f63f44f8f7}, {0x0007c5bd8808eb44,0x0009724642e6865c,0x00059e076e717c8b,0x0002161fb2086420,0x000012f7226e4689}}, {{0x000812cbca321347,0x000e632740ba2570,0x0001db927a9e88dc,0x00052b0aba4374ba,0x000031227b96461e}, {0x000cd5dc06746bbe,0x0000cf772208a93f,0x00002a73b5a86ada,0x0008c08bbb02ac6e,0x0000f0196a56dc06}}, {{0x000d114588509806,0x000fb66505d56d8e,0x0005d67e3ade8c1e,0x000119098b390daf,0x000036106afbab3f}, {0x00018cd4db085aa0,0x00060de60f8f3920,0x0008384555865e57,0x000c8b560c8a7794,0x0000bb865e6fb6e4}}, {{0x0009a2695dcb03be,0x00082dce5033ad58,0x0009607c5c6bfee0,0x00022ae3df25d171,0x00000969faa0ee1b}, {0x000ba9a77472ec5a,0x00093546739c439c,0x000ea5d5c7a4c0b8,0x000e1e00c8fe66ae,0x00009ce280523997}}, {{0x0005978b851b77b5,0x000283c18a02a8b6,0x0009ba7aa0364b0a,0x000f94a6337a27cd,0x000046af7665f865}, {0x000ca9cbf97d5b16,0x0002237045beff1c,0x00083538584b0821,0x0002838dc37d07a3,0x00008db8ece96033}}, {{0x000c181d162aea79,0x000e82e60793d69b,0x0007258aefe6f5c3,0x000ff59bc53c6eba,0x0000fb553ca68c8c}, {0x000a8ffea309a6f3,0x0000b9a56441bca8,0x000e2c97bc141056,0x0001715ae34273f8,0x0000514b5e4a2efa}}, {{0x000c99927b057ad6,0x0006c8df3e109788,0x00042efcbb33a466,0x000e21d25a75adbb,0x0000e29ea59779da}, {0x000921fdb43a94d1,0x0000339d1820fc2c,0x000ca4ed5d01956e,0x0007bd7de58e797b,0x00001e6e6b666ea0}}, {{0x000db2987fced620,0x0009ec446ac47b5f,0x0004a043cfcbd482,0x00041a6a0c7495f3,0x000012af53d2f54a}, {0x0006ad3c90c6bfe5,0x0009e9382b437e60,0x000b911675112180,0x0001fe21b90ecd21,0x00003c0b3c579d34}}, {{0x00027b6e3c50668c,0x0006d6d8d96df5a4,0x000da74b2f2f21c7,0x0004a2b1e238a1ad,0x000010d7b0c82fc3}, {0x0003512ea402316a,0x000e879853dbc21c,0x000ce88096dab781,0x0007d667b34f9207,0x00004b1eb299bb04}}, {{0x000d118c309e65a1,0x000fabfb4147a551,0x0002cb43addff781,0x00012d35f7873d69,0x000027471214c7b1}, {0x000d72dac4e3e7ed,0x0007353a272c9f63,0x00092a6b9af262dd,0x000220bf901e7534,0x00007a7efb0540e6}}, {{0x000b0ea863d4195d,0x0005368db7c846e3,0x00005939496972ef,0x000a5e8c21297c56,0x000067666c5eaca1}, {0x00025d8b0dad395b,0x000865268b8fdc43,0x00006bcfdef1f33c,0x000a4774da449704,0x0000a1358f89d014}}, {{0x00029a88642c8c87,0x0008c8e1555b9104,0x00039a9aba22bed1,0x000fc7e5fe7cb866,0x00000202dfe03ad7}, {0x0008d27cd6bd32a5,0x000cf32a6b477ed5,0x000dfd6a90e47d00,0x000f4011739d9316,0x000009017911ff40}}, {{0x000b591cfe2d8435,0x000da2d587d5570f,0x000368c95c0226cf,0x00024b0fb7a4d410,0x0000747cde3537b4}, {0x000b950273cff74b,0x000e13c9336c4563,0x000c3960d19448b9,0x0005749ac83ef9fe,0x00006bda1afb9c11}}, {{0x000fd3c13fb0e65d,0x000fa286d2d8dee1,0x000429aebef8efe9,0x000941fc4bebd474,0x0000003c2cbf1f69}, {0x000b443a5eb895a6,0x000b471ff243422f,0x000bd3be819ff465,0x0001c38b9d452cce,0x00005d9b85ed78f9}}, {{0x000375126cded2da,0x00007e9257a8c6bc,0x000dee102a30f31b,0x0008fe55ab4546ff,0x00000dd53a3fae81}, {0x0005cbb5a649fc4a,0x000817a77abd2632,0x000e1e9abc600dd8,0x00067b95baef2e23,0x0000de3e4fb2653e}}, {{0x000383df4f38b019,0x0004818f9a6a720b,0x0002d4e1a9ca0f4f,0x00035b6d14a33e46,0x000044289f623629}, {0x00007a387d0c040d,0x000b1fa4bbe11901,0x000d31de4afc1507,0x000d61847236f98d,0x000092524f93ecbb}}, {{0x000133e59049afec,0x0005726f65d7ad5c,0x000c20ba29b6689a,0x000fe847a4377af2,0x00000527d1b09af8}, {0x00040fab9f632b99,0x000399c6fd2087c9,0x000492e8aa07a977,0x0006bb6bf24157f1,0x0000127f701cf38b}}, {{0x000a5446b8fad411,0x00094c04141b6e5b,0x0000c0c227c20ebf,0x000d5a04ab83fce1,0x0000bcb816fe010c}, {0x0003b1f39b167b8b,0x000508ecf57d0da8,0x000f43aa56b9dd56,0x00056a8cd6338fd7,0x0000bbded8d9e446}}, {{0x0007cc07c0803c55,0x000f213fe5473232,0x000a3cfe69566daf,0x000b4b379c15809b,0x00005eb247e4e96e}, {0x0008c0ee69a81c78,0x000ca494920f6e7f,0x0000bf99b798df73,0x000a22034f1f6531,0x000097e6aeccea96}}, {{0x000a954927e7800d,0x000a826d0a072de2,0x000d54515c3845d4,0x0009d7df7dea11cb,0x0000bd898c3c179c}, {0x0002dadc7f97ca3e,0x000c0dc928e98ba2,0x00044da48b29b42f,0x000aa74a564df536,0x0000634de334dbe8}}, {{0x000fefbdd58c6c26,0x000505d10919ecdd,0x00022059482fdceb,0x000567341aff5332,0x0000c224f55a4389}, {0x000cb2becafcf4b7,0x00068c9356cee825,0x0005bf8155b2741c,0x00073337ed23e3fa,0x0000db5fb517c0d7}}, {{0x000bd96248ab8040,0x0009230d301d5d87,0x00070e14ad7011c1,0x0003d21ef8438468,0x00006554bc48fe6a}, {0x00060d553e3bc93d,0x000d4998ea4a6e08,0x0008cdd7522b6e14,0x00008239e466a48c,0x0000715f93d875c7}}, {{0x000ebb47ef45b374,0x0007b2b58c3731da,0x000e00a0e3d0dc78,0x000bc2a199fdb8b8,0x0000bfed2128b73b}, {0x000e635d70a51a82,0x000ba44f2975b044,0x000dad6e7aecd152,0x000a50eeccc149a8,0x0000aa60be904d47}}, {{0x00057e2a9da811f5,0x000d8f3097464c41,0x000484e775d2c457,0x000cd6e150802622,0x0000d436e5ccb8e0}, {0x000b7da9c87674cf,0x000a0e9207076833,0x000861876e15b63c,0x0000a8cf27564749,0x00003acadb457197}}, {{0x000409f6aa3e6037,0x000e9cd0f03103a4,0x0003670a08cb8a11,0x00029d97e7af5af4,0x000033d7696897ea}, {0x000513f584bf83dc,0x00003556fed046f4,0x000673b14b6edf6d,0x00085fcef8b7c83a,0x0000b1cd839a4b63}}, {{0x000185d2c4242479,0x00097a295f96baea,0x000a2a8c7280ed03,0x0007ef7fc1f8550a,0x0000d696d88afdda}, {0x000ad885a9e3c7bd,0x000370ee8f9c98dd,0x000bda7835528be5,0x0009132edb484473,0x000039c54d3c3c08}}, {{0x000279ed119371f3,0x00001fce787efaaf,0x000c87c24f135eb6,0x0009d979f366c07b,0x000041ca760045fc}, {0x000acb26b190eed1,0x000fcaffe42e29c7,0x000d6d3ab87c3da8,0x0008c050fea0c3b1,0x0000f921a3b9c2b3}}, {{0x00019080b28583c8,0x00084271f1c9cd2f,0x000d88b4d5344abf,0x0006e6a1fa410880,0x00009780cad6113a}, {0x0008fccf32dc4852,0x000c09cdb1201d95,0x0009f592a499a670,0x00020202a5504704,0x0000b368bdb51e7b}}, {{0x000bf0d270faaadb,0x000e467299302de8,0x000d5b29c9761e25,0x00038c9a2a3ca3e2,0x0000cc9ce0564bca}, {0x000feb5640283cae,0x000933c755cd2702,0x000ab454778cdcf5,0x0000f1802df412fa,0x0000a3fa943ac400}}, {{0x000b9788e6e633fd,0x000544369ee142c4,0x00015ff93aad8109,0x000247c388415df8,0x0000bda8886b6aad}, {0x0001ae09bbfc6389,0x0003224a5c85ae86,0x000c8b0d806937c2,0x00033767015db086,0x00001093bc829ba2}}, {{0x0006738d95956325,0x0006c14fe2f45374,0x000738d03b49c9e4,0x000f4f514a895f38,0x00004126445d21c6}, {0x0001bdd19accfc3f,0x000c75923b83aa21,0x000d4420ccc62233,0x0008570259ea62dc,0x0000ac5e9fd95e6a}}, {{0x000f02f1e3020f7e,0x000abf391444e199,0x000d33d014595d4d,0x000243d1b275d094,0x00009fe416192225}, {0x000927e9313cc8ae,0x00007cbfad2bd631,0x0007d6f47c38a96a,0x000212ca8293dcf8,0x00009e934e1b8edc}}, {{0x0007e895fac16188,0x000c48ddace03666,0x000ea05367de0677,0x000beff7720f6b94,0x0000f0cfc3ab04dc}, {0x000ffaae7332b4aa,0x000376aed4df1fee,0x000d7d9139fe5560,0x000cec33e0ed75b6,0x0000b793cbe3ee57}}, {{0x00004d1db2df89a2,0x000fe1bb790eea99,0x0002e037ee87f71a,0x0001a43ef529bd8a,0x00003f57ccee309a}, {0x000e652d001535bf,0x000531e580c75add,0x000537db16a02484,0x00016ec744e0c9ec,0x000031da47f5dbff}}, {{0x0004c7e6c2a25fa1,0x000d2f543aa6ac56,0x00040245d6d44b13,0x000d4cfd0af04138,0x00008a3e6f94f447}, {0x00053a1887a0b642,0x0004e78ebfe0b50a,0x000560e378ad1f19,0x000ddca374718976,0x000076c2fad52831}}, {{0x00033c240fe437af,0x0004155b36bc99b8,0x0001d74ac6678611,0x000a5b24b825c503,0x0000dc5a9fb55609}, {0x000f6da55d8b0a12,0x00077b276db4ac76,0x0008fc93aacf912a,0x0005dd0cd8b799c4,0x000026948bba026c}}, {{0x000e5dc6a8543fd2,0x000c1dd380d7e3a3,0x000f3ef8413c4a39,0x0001dfdffc537730,0x00006f878d18b4d0}, {0x00050e41bd35c986,0x000f502371f32ab5,0x000f1a88844ef8ee,0x00013ba15e21b99a,0x000064aa063b9517}}, {{0x0000dc7a8ef6fb13,0x00029eb3893a9f55,0x000be61b7ffb9975,0x00084bb486f2c400,0x00007200d4bf41dd}, {0x000b00036c8f5e50,0x000f666addc17762,0x000741de8eaa75d7,0x0006e2beadda312e,0x00000cf20707c3ce}}, }, { /* digit=16 [{1,2,3,..,}]*([2^112]*G) */ {{0x000263e88928ae78,0x0005b4e82be78b48,0x000573a10668411d,0x0006003ba7a1e67f,0x000055ce3d847374}, {0x0003d7e7e0444965,0x0003b5779daedf79,0x0006fec0025603ce,0x0005537019312576,0x000058c17835ab3a}}, {{0x000f3801bf458e27,0x000267db440dcbaa,0x0009ae263c36f812,0x0007e4c9536223b8,0x0000a3cc7df0233d}, {0x000b1cd94cbeb372,0x00039f4807f8b9d0,0x000c597324185b52,0x000edcac170724de,0x0000d2110bf132b7}}, {{0x0006829bfc72b079,0x0001d7df36f44abc,0x00071f67bd4d4b36,0x000dfe954c4d7c53,0x0000ce1626d4ce63}, {0x0001b137ff8ce06d,0x00074664f8dd7874,0x000300b6012fe268,0x000838c0a9ba2942,0x0000ccd61cd61418}}, {{0x000561feaf4022a9,0x00054750df9b560d,0x0009e8873c0034a5,0x000babe5354bb528,0x00001434cb13b39b}, {0x000661885c701bf4,0x000024ea8f5c6d71,0x00087a94fb5f8163,0x0001f69289cb22b9,0x0000fc615e56fb16}}, {{0x000183c12ef9b892,0x000bca4be6ce2dbc,0x00034f0eb5247e9b,0x0009319bfc5e8667,0x0000d7c61ce40520}, {0x000391e7aecc2dc4,0x000502b7dbd4b402,0x000c8e5c4c4cfbd9,0x0009e83613bcab0b,0x0000346c5d1041e3}}, {{0x00061fe951496001,0x000940d172cbd2f2,0x0007178c0c43ab46,0x000faf9dccdec82f,0x0000adca0a729af1}, {0x000d70cf6f648cdd,0x00020f732870a2e6,0x000edafaf9b5c25d,0x000106ce0db1e405,0x0000d951a4245711}}, {{0x00083ffb1021d71b,0x0002312ad996176a,0x000fe8f4b2e72ec8,0x000a2d26d3a1eb2f,0x0000d0da0974fbb1}, {0x0007b253b22acbc9,0x0008e75e121ea26e,0x0001d0d96ac731e4,0x0002d71a94473e82,0x00001f7b3a36202f}}, {{0x00038deafeaad237,0x000df374aa4943cb,0x00049341a28d1f25,0x000da0001e16e457,0x00005d5a690e8563}, {0x00039cc322cd1a1e,0x0000e69f3d0f0287,0x0001f380debb0624,0x000965b31a6ca354,0x0000e9cbcd994718}}, {{0x000c6922682f05da,0x00017d91dac21c30,0x000d9a935d39a514,0x0001318bfcdaa873,0x000086e4fe5534c0}, {0x000794e1a75fbff5,0x000536f457094f58,0x00038cd634ba889d,0x000e8fdf2b2976a5,0x00008ca32ea075ce}}, {{0x000d5a656febc1de,0x0001902e98f903df,0x000f488a40aafbb9,0x0000728ee7bae61c,0x00004af95a5c8955}, {0x000e37e156e3a046,0x0004accd7ad577a5,0x000b8bf99c4f1997,0x000c3dc8efc06d64,0x00009535e542d847}}, {{0x000c071894059e33,0x000e16afeee5055d,0x000d7c4e58da0f59,0x000f92484480872e,0x0000d26d813b9d7f}, {0x000db103b383d063,0x0003a77d69385adf,0x000f5cdf0dbbbe77,0x00044de79f617d94,0x000045aa4efb1858}}, {{0x00024757beec731d,0x000827d28fdb9e94,0x000c2342a93d6395,0x000aa543b7350b9d,0x00003ff4ae312e55}, {0x0007f066a93f5d0f,0x000b7bb2a8d24025,0x0004453ce9313341,0x00018ac52053dcf8,0x000034eb883f74c1}}, {{0x000eaef662e4d0d3,0x000059a256134cb7,0x00039f0720131fce,0x000403b640ec2ad1,0x0000bf5af241564f}, {0x000e90b3a2dc95fd,0x00011936e70af541,0x000cb4d905df5c12,0x000eec1d816ac3c6,0x0000f7bdb6871a08}}, {{0x000a5314edacbf64,0x000cea476e8d2cbb,0x000329c989b5d217,0x00006210a624d6bd,0x0000117009f54cea}, {0x000f3c08ecd2255b,0x00003a9d114b6cd3,0x000eb5279e0c672a,0x000350f0cf81ab63,0x00007bd811141a39}}, {{0x000e5ad10c0f9e13,0x000ca384048e1e66,0x0002e8128b54f642,0x0003a4179217c0e0,0x00007023624a2bbf}, {0x000303ed950a4a7b,0x000f2ab587314f2f,0x000579025c85df88,0x000da0e847c3dd28,0x0000ad36a42e0005}}, {{0x000f3942e984ec00,0x00069b01d25ffd3e,0x00052e58aeb37752,0x000648244408f942,0x000050a44776d1a5}, {0x000a111b2f83e4d2,0x000a55031541fd7c,0x00010e5caab3d571,0x0008ea6a31cb7862,0x00004f23739f63cb}}, {{0x00034d5aa351e7fa,0x000767b6bdceee2f,0x000c32c404785e1e,0x0005856ee43745dd,0x00009ac4c31ca9a2}, {0x000d00120efac828,0x000cbe4c18a7102f,0x000f056f5a74ffbe,0x000556b56adf5d31,0x000034b8508f4fca}}, {{0x00072bd8e4e38d94,0x00066bc1a50e3f67,0x000eccca9fcbfd5d,0x000094357266d3bf,0x00005d1ab86354c8}, {0x000e84f97431deeb,0x000b71de91ac3fca,0x000c099c7cfa4e84,0x000438463acc3dc9,0x00005a3b751b8423}}, {{0x000ae45e109ee44a,0x000869005ea9c422,0x0008dc7eefa037b1,0x0007cb207cd5ca5c,0x000002e590572ee6}, {0x000d6f711e0c867a,0x000b67004688c5c8,0x000ac0175a217761,0x000d346dca0af57f,0x0000834eafd30443}}, {{0x000031a244eb62a0,0x0006e2bc5ae2ffe1,0x000da78702a1ecdb,0x0007d86a6091a100,0x0000efb1036654d2}, {0x00050d8f92e2f743,0x000f3b2dd2ae5d9c,0x00085081efcb5469,0x0009bb2381877fc6,0x0000a09d4c8315e0}}, {{0x000d2bc606eecd87,0x000ce811461f32c0,0x000d2a5d24c90b85,0x000778f04514b56d,0x00009c7f1fec2e61}, {0x000670973b59d05b,0x0009bb1567fe8aea,0x0008152ae455eabf,0x00049b39a03b8257,0x000076e8321067c3}}, {{0x000293372ff91a46,0x0006b775c576ea7b,0x000a3cde27e9c747,0x000bf429095d14f4,0x0000218f90c2db67}, {0x0008acca306563ab,0x00024d4b59a65276,0x000cf8c68ef2c300,0x0008a593a9f027a1,0x0000fb08f6575918}}, {{0x00001bb71891edaf,0x00064a5d6ffe31b4,0x0002b148e3202aca,0x000672cd924679ac,0x0000f9aae98a214e}, {0x0005dab10356c4c1,0x000a2de53c8e3a1a,0x000fe283ee091971,0x000d484dfedf9266,0x0000a8b4a0624aae}}, {{0x000cafe59e1c69e4,0x000ec2f66c9b2eab,0x0004aa0e4ce53351,0x0005f826078a7569,0x0000640f3228ba1a}, {0x000925c496579dc0,0x00038c97b76be7ee,0x00049904eb6310b9,0x000d1abde130dd9e,0x00007e9c5c47ec9a}}, {{0x000747bf4a461c92,0x000604cac505b161,0x00039e37325036a3,0x000e3d40936c8564,0x0000d8a870eb02c7}, {0x000b9d2f973fb7f5,0x000c1a615f5d3397,0x000a0a4c943f3401,0x0002887b120a3cc0,0x0000f101a1ac6662}}, {{0x0004a3d4fee19353,0x00015d011130b451,0x0005ac2c73b7caa8,0x000becf5b0c09c90,0x00003f82f1440fe4}, {0x000b4ab74f14c961,0x000bba7943306bd1,0x000b78631291e728,0x0009cb5c97bf6fe9,0x00001c908352f56f}}, {{0x000a431a92b58b20,0x000f68a51d86d62b,0x000861d00fcae533,0x0000dd371413a4a8,0x0000cf49037f8657}, {0x000eaf4c3d1f3eb4,0x000521e2f9631faf,0x000851b77e971282,0x000ea6acb91a72c4,0x0000206da3cce7c9}}, {{0x000d754a64d62c61,0x000ee0355ea5a1a9,0x000e8ba7266cd17c,0x000a54959bf91b62,0x000070bfd9a18d33}, {0x0008a1b0be98472a,0x00030fe418fb02b7,0x00052676e46d3013,0x0006d3b58f556cbb,0x000078fb2237e0f1}}, {{0x0008653a9f8bb2b0,0x000e96befa270587,0x0006dad18832ede3,0x00068e53b0c689cc,0x0000db79f085c9af}, {0x0001c7d93d122b99,0x000db352a7a11671,0x000c8f1e726becff,0x0001d858067471da,0x00007d1cc378fead}}, {{0x0007f002486685af,0x000e214080b0257d,0x000cb1b8970c4633,0x000a75ed72c06edc,0x0000da0218c79771}, {0x000f32f5200f7c7b,0x0003a69a8df75540,0x000d5f6e2ddffd2b,0x000fe2ec9a3ffb8f,0x00007df766b5d4e0}}, {{0x0004d27b3dd34f56,0x0007de6fca2c5512,0x000787744861e22c,0x00006ce2f3d6847d,0x00001ec88437590b}, {0x000c281f52950ec0,0x0007bd6b5c7cab50,0x0003c2642b1c400e,0x0003890397e8e47e,0x0000cf7d2df12202}}, {{0x0003266882874e03,0x000a89e81d0194cc,0x000549a334f700e7,0x000ebbbe4d500db4,0x0000433030eb4bf5}, {0x000d4c6fbdcd9292,0x000d720ac8474589,0x0001ef26b9eb5ed5,0x000acee19219c5ec,0x000001a7fc35fdee}}, {{0x000f286f78c7ae3f,0x0000f6fe1ca839e0,0x0005678a2b39fbed,0x000a8e7ba6e825c9,0x00007d7bcb5335db}, {0x00060809ff657696,0x00043fe88e0ad6ff,0x000de58633c659b1,0x000251056cdae14b,0x0000b0b64689f024}}, {{0x00008e21178a099f,0x0009afd88898f531,0x0006270b71af681a,0x000926359a6e55cd,0x0000e1e802206d9d}, {0x0000c10a39d0de19,0x00011dfc0b3fc87e,0x00058de46f676bbf,0x000ebc32f304138e,0x0000fd44af065751}}, {{0x000837bfd2c4dafe,0x000f55cb3e99d194,0x000e83b433ea9169,0x000d019bf4f952b7,0x00005a04c25b21a2}, {0x000bf1e7dcbb4739,0x000c3be7dffaeeaf,0x000b4829d1ec04ec,0x000909474be22c14,0x00007e4c57a57cd7}}, {{0x00061cc613abb95e,0x000cb58aa468c130,0x0000103c600933a2,0x000a98fc90deaeda,0x0000ce472cea4bfd}, {0x000ffac971727969,0x000fb1241fe002c2,0x00094fc710ac9f69,0x000df476c5db7755,0x00008ee99ab46283}}, {{0x000da7a9e6fa679a,0x00050244f9571a74,0x0002bfdb99609f5f,0x000a0ca351106f8b,0x0000726ad35b71e8}, {0x0001399059b1506c,0x000d5f4c5d58d7c0,0x0004e983e0eec7d9,0x00024d47eab45931,0x000073b2a5db146b}}, {{0x00053cd8ac3fd6e5,0x000911ae915c1c68,0x00035e452713cfe5,0x000bf9b5b88ed861,0x0000768dd4358000}, {0x00055d4bf4bc4280,0x000cfe3ceae694b1,0x00039860a90b33a4,0x00044533c50782b7,0x0000e0258fbe654f}}, {{0x000483703eb7f60b,0x0007d6d369a806b8,0x00012af7a09ec39b,0x00037d6f136e5aac,0x0000dd8a6565513c}, {0x000255d417353feb,0x0007cebf91f97a59,0x000d5caba59e9564,0x00024a85f33bf2bd,0x0000a4be8c2c5c77}}, {{0x000796c75120b49d,0x0008a90e9b928b9a,0x0008f95c1622af0a,0x000ede13d8b3fc2c,0x00003c265423eb9e}, {0x000ebc9a15bd7812,0x000ae6b2d10435bf,0x00011101cea171ae,0x000e63bfb9273095,0x00006dd7cd57f8d1}}, {{0x000198e5d68cb6c0,0x000c190df284c844,0x0007e36c27d05eea,0x000e6fa431aa9dc0,0x00003b61254ff61e}, {0x0001a8e2b8663dba,0x000587bc144f1d1f,0x0005a87f2ae85cbf,0x0000fb374e6f7b1b,0x00008c121dbc747f}}, {{0x0004c7bb9087d92a,0x0007c0e6a9bc8960,0x000c69ec2a7a547c,0x000ec22623c94a7a,0x0000525b055cda91}, {0x000b110ac44d3bf8,0x000f1422b1652063,0x000642f08b288324,0x000c8d48a8d2d517,0x000012612181f2e2}}, {{0x0008cc568e4c47a0,0x00034c3e8a1d2cf8,0x000b8406ce8cac5c,0x00032c23bc082944,0x0000bb19f797a36a}, {0x000f360a586e48de,0x0006e44743247522,0x000e06255c5208aa,0x0004e8f858612ae7,0x0000b4ea39d737ef}}, {{0x000bc460db94e995,0x00005080649d163b,0x00096d07ee0617ef,0x00093fde45ac2df3,0x00009614177e10ff}, {0x000dbd16ee571c89,0x000a36b028cc1b9b,0x0003821897ca0e3d,0x0005b2397d51cfd3,0x00005ff63bbd9c6e}}, {{0x000776420861ada2,0x0005c1493e967a64,0x000d92b3fba264b6,0x00026a2e174e2760,0x00001c08d1309e77}, {0x0003add07c55bcbf,0x000e21a28772cc02,0x0006ed92bc89eea5,0x0002ab9f631e159e,0x0000237c626df26a}}, {{0x000eb0be483e60b1,0x0008a8144da94b61,0x0007e3c9442ec74a,0x0008d5659b08da90,0x00003a62569751ae}, {0x000a60e8fe99eac3,0x000c83f07f5cddae,0x000b6a2c4f4d939e,0x000c3686516e4f8f,0x0000ce14006ae498}}, {{0x0008be5037f0aef1,0x000400d9612b3b49,0x00000f5494e4a5f1,0x0004b350178c1bec,0x00002194ca390f0b}, {0x000371e991e9b508,0x00066f5513d3e57d,0x000bfed44a8a1cd6,0x000d0caaae2503dd,0x0000e2217e3ec2d1}}, {{0x000de10dc8a838bc,0x000cb4db84f09e5f,0x000fc31b998d83b9,0x000d314cdae49c2c,0x0000e17fbf4482ca}, {0x0003d5685bc44cd4,0x00011b173b41f973,0x000b6c609b97d020,0x000fa8129cec8ae7,0x00008eb425aa9285}}, {{0x0000d499bbee7027,0x000794e7726f36ed,0x000f7e50f1106588,0x000372016e8a20bb,0x00007cad5d314d87}, {0x000dd1a9c4d420b0,0x0002e0853dfe07df,0x000883f4657bcb1d,0x000e264db07a30b7,0x0000d54953a43577}}, {{0x000b7bac5d80fad0,0x00044b2255967200,0x0006673244b80849,0x000399b432f19ed6,0x00007a899f7c61f9}, {0x000ec5ef6da900c1,0x000f95e8e63010d3,0x000ee7310e72fe29,0x0002467c0da3b206,0x0000d1381a884ad6}}, {{0x000647f72ba142a2,0x000510a8a8617f04,0x0008c5b890377f95,0x0000384970fca731,0x00001b0e8d4dc56f}, {0x00069cdcd6ed4bd9,0x000dc638ead2b445,0x000d215fcc875e7a,0x0003c6dc06beb69a,0x00000645a027babb}}, {{0x000b0431983cd6ed,0x00007bf2175a80d4,0x000798d7519a205d,0x000fa59086f5341d,0x00007f0d0b4ab66e}, {0x0001892cc0405eac,0x000cbf6a8145fae0,0x000fa60ef8231d5f,0x000d9bcd49a89231,0x0000ddf2a97a89fc}}, {{0x000d2ffecb831b3c,0x0006c64be18ccf99,0x000b95a73a3566b9,0x0006ade17af67343,0x0000bb14c802d2dd}, {0x000046d9f8cb107c,0x000510d859fadfd1,0x000c8a0784b62dc2,0x000c0a6ad339c802,0x0000cd11269bffaf}}, {{0x000468da94f038ab,0x000bb71bb5963514,0x00006cfbbfe6dae2,0x000e61154fc00490,0x0000bc8ae6a43e13}, {0x00044f06569f3f31,0x0006aa775eff10e0,0x00034b8704d0054d,0x0006b4251e6260c2,0x0000ef2a9d02c95e}}, {{0x000ff430a65cf5cf,0x000e5b64c8a24667,0x000eac3ffcec204e,0x000777251bae8db8,0x0000c0889a098bf9}, {0x000fce13803c0161,0x000401026ff03bad,0x000f5e552f8dc21d,0x00091ae48fc57a54,0x0000609011dcbb57}}, {{0x0002643d816f6738,0x000c3753f6e86736,0x000879b02d8cb868,0x000c7e594838c395,0x000067972ca999f1}, {0x0007d34dfd7c1088,0x0004614e333a9fad,0x00058a876d7b6624,0x000108e3cfac8612,0x000025823b4b5af0}}, {{0x000268f6a19bb9b3,0x00070a8958a2b4db,0x000e8549f04fad60,0x000d9a69a06eac4e,0x0000d03548e51195}, {0x0004f596dcd373eb,0x00006334b296340e,0x000d58c42a009c79,0x000881171c453a68,0x00001b31a3104480}}, {{0x000638d6478b071d,0x000d506ebaf4c8e1,0x000f38ac3c0decc2,0x000ef39e647b5165,0x0000428075e5d414}, {0x00028b3e3fe5a0cb,0x0009c6c2309c09a7,0x00009c0e65089762,0x0000d298398ccc4d,0x00001a2ece4161ce}}, {{0x0004ed542000ffef,0x0006547c39491113,0x00093d2fae58456c,0x000070c2b32044ae,0x0000c506a795a7b1}, {0x0000510c08f5f461,0x0004b53bcfd62e25,0x00072129bad0f10f,0x000fe39c16f090ce,0x00003107a2433ad4}}, {{0x00094ca6b8261d16,0x00015268752c1c63,0x000960928360a4b3,0x0000531849d69193,0x0000f72583b238ad}, {0x000fb502a8493e40,0x0006bd817731e757,0x000993764b0c236c,0x000d4f08682dde88,0x000027590fa24c64}}, {{0x0004af2f50460797,0x000d37f2b0ce2a1e,0x0009a8ba740bbb10,0x0008100c3fd4bc4d,0x00002775b5aff598}, {0x000144f7f34177e8,0x000d1f57ccfb628e,0x000e818c9097dd78,0x000458b5e547accb,0x0000c02a026db11c}}, {{0x000ce91cac08c3d1,0x0002b2736bca265d,0x00089001c395d92d,0x0000fcf505b6519e,0x00008c614d9cb52d}, {0x000ab8803efd70d8,0x0007c604446b154a,0x000619c8c4d96a6e,0x00064ae8fc9320b6,0x000068e0fb54c0f2}}, {{0x0000cefcf4e70ec5,0x0004e2cf688d23cd,0x0008a11035bb79a6,0x00062874c5aaedce,0x000057759d2b1417}, {0x0001d559128402a1,0x00048367bea79cef,0x00096c617f84a0eb,0x0000d3fd7070c334,0x0000553c0472599b}}, {{0x000d20f989b9e29c,0x00099deae2b2ff99,0x0005ec2b4b690d6e,0x0008df9c55072b82,0x0000bbf457111cd8}, {0x0009822f0aef2354,0x00029207a036f4ad,0x000ed9f8978a6431,0x0006e9dcb5c728b1,0x0000b9e20713e8f7}}, }, { /* digit=17 [{1,2,3,..,}]*([2^119]*G) */ {{0x00041fa6a39c7f6a,0x0009eb5589baab08,0x000627ba2093d7e4,0x0005a1f11df73ccf,0x0000a3a9614f842b}, {0x0003036faf95407a,0x000a6b88f15492a3,0x000ef2aa8c72f6ed,0x000797929383c9bd,0x00000d4b788e861e}}, {{0x00028e853253b32c,0x000764a3d3e50baf,0x000523564b25a2db,0x000cc7f385d655ff,0x0000d11a0255d54c}, {0x0005cc1bf209a125,0x000965f5e1df998c,0x000023464fa162cf,0x0009a40a48610028,0x0000fd3f9f50b2cb}}, {{0x000a5228e90b176f,0x0000c1c3bcbc9702,0x0005ae8e770765a1,0x000f8b56923d8d2e,0x00008e74adba5e4c}, {0x0008ac1d36d9dbc1,0x0000bb6bcfb20110,0x000fa9d7efcf1d34,0x000aaad4625764cd,0x0000a06c7fa8fafb}}, {{0x0006be82919499b2,0x0005b2e0e8754c2a,0x000ae54ff9e14e89,0x000853a30ef155b2,0x0000ecea0175c713}, {0x000d2365ed695a76,0x0009c344487f8ecb,0x000cbd5f7dd9d9ec,0x00093f8a2fa3c895,0x0000b4000583e162}}, {{0x0006dfb3c80537c1,0x000928b656a8e73c,0x0001a720c007d242,0x000f0f7f2f75140d,0x0000307b44bb2faf}, {0x0001a93776043d2a,0x000131bbd300fe21,0x00012b8b0d581890,0x000bbec7aa05b0c8,0x0000c0d90f4dd862}}, {{0x0001ca3ee253969f,0x0009e918dfe27423,0x0006aa687b67bc7c,0x000dacd55607b710,0x000066e8c14a024b}, {0x000f5d052e5ba875,0x0000afcc0c31ef9e,0x000cda3636263f60,0x000872630cbc5ef3,0x00001148ad0d4f22}}, {{0x000777b4aa7e5304,0x0003615e1bdfba24,0x000858bacb14b766,0x000b945ec88b6fcd,0x0000bd20cb06635a}, {0x0006f5bdaadf1ec6,0x000c7d8267bddc7d,0x0008015bc00a297f,0x000366ce5cbef6fb,0x0000bef7be68218b}}, {{0x000a98c52873cedd,0x000a4dce333a9777,0x000c49337107cb38,0x000d4e5d090eebee,0x00009c1f6657ee06}, {0x000ec426251c702c,0x000182c9b521b4df,0x00075e02a1270247,0x000e54af1cdaf2a3,0x0000dc7ffbf6f46f}}, {{0x000522738eddba89,0x000f79659871f8b8,0x0003d82764c79ac3,0x0001c2fc21f3b82c,0x0000caedd9348e18}, {0x0001c424c016898b,0x000369f16a2211bf,0x000d0ee361012838,0x000e2f5b3b65c786,0x0000dbd3e2f44b64}}, {{0x000ade03aff4bb02,0x0008b4529f4e17b0,0x00043bbb7fdbc450,0x000dd77af503eac2,0x00002cee72b9a511}, {0x00047cc71bb2a4b8,0x000c42f41d52bb5a,0x0003a786fb0e56c3,0x000b64068993ab40,0x00002c6197dabf9f}}, {{0x00037d63972795aa,0x0009bbdc815efc80,0x0007ab6e71ef405c,0x000a874747c3c51e,0x0000f1d220edee78}, {0x000211ed3c96c1b7,0x0001bc179709211a,0x0000e0198510be77,0x000ea2a633d65d9e,0x0000562f78442b7d}}, {{0x0007889df799db5f,0x000ba012c603f759,0x000ca505b101e3f2,0x0008490b743f6b4f,0x000042757e975d7c}, {0x00039e82875f4bb1,0x000f8ff53a5da9f0,0x000ec746f6aa587c,0x000474838f092ff9,0x00002758b9877567}}, {{0x000825e7bf6ef16d,0x000e3b0e3eed4f65,0x00082804995e95a3,0x0009ac66e3d6ef1e,0x0000140e9150990d}, {0x00048379d22a5ca1,0x00006beaef803d57,0x000d94eb0997a2d9,0x0006df77b8617ffd,0x00005a68f3e15466}}, {{0x00044939e5337133,0x000022bfa31f90af,0x0003a6b0a68785ce,0x000614dc6b2e1ac3,0x00004b2ee53c3f17}, {0x0009ceacff767259,0x000500352afe92bc,0x000b09c4726df2fa,0x0009aa62ed60a55b,0x0000d183787441ab}}, {{0x0005c96dda71597f,0x000683e67ec813b4,0x000d724183cd30fd,0x0006536b8f8530d6,0x0000632c3ac24270}, {0x000b011fe29506ef,0x00057d43147ea463,0x0002a70211a49273,0x0008988dfb701702,0x0000debd588711ec}}, {{0x00090744b027acb8,0x000909729b2dd4cf,0x000c784e4eef7dfd,0x0006feaaf145f925,0x0000ec26936eb073}, {0x0003622990de2b9d,0x0000059c4c7d2565,0x000f374f6997d858,0x00015e6db4239a6c,0x000061e73252bdd5}}, {{0x0000c24d522fbc0b,0x000a942bb73d7298,0x0001ead460b4f626,0x0001ddb380775ed4,0x000081f005390776}, {0x000d2a88d7ed3d9a,0x000a953ef7cd9a17,0x0008cb51593a12b6,0x00041c930e0d8397,0x0000396686f3a8cd}}, {{0x000a7aca5295f85c,0x000d1715f010ada4,0x000137d62ed99476,0x000a2c1fcf92691a,0x0000965ba19a5dad}, {0x0006e96b9c400652,0x000a0f797bf078b5,0x00027bfa01d46a27,0x00088481a98f9ead,0x0000e828cd3a93a3}}, {{0x0008afbdbd10a431,0x000d106c891c4914,0x000c9e0e75d3c212,0x000d14e69985bb06,0x000006751cf618c4}, {0x000a3dc9130b9b81,0x000c1201b63586c7,0x000247844a994f46,0x0000e8518f9b96f4,0x0000552e79eb2973}}, {{0x000a7cf36346748c,0x0004f02b5ab08498,0x000a67c8add8490b,0x0004083da6e9932a,0x000000ef8174e556}, {0x000ebdb7e8317689,0x0009dcee991652fa,0x000b17155928e7e7,0x000bfb43e0c0dcf1,0x000061d9f54d10b7}}, {{0x000fea920dc3621a,0x0004c5a9ef80adda,0x000bf625b196feb3,0x000c75a487e45e47,0x00001586634f3500}, {0x00078e658ad24f8b,0x000b7ec508d6416e,0x00086e5d355ff7df,0x000160bf2a2a10f6,0x0000e97f906d9cd7}}, {{0x000cf2ecce6a83cb,0x0002141a1def5419,0x000b08f6b415a133,0x0003ee9d14d27344,0x000001759dafa67d}, {0x000806af6fec05ea,0x000d7b011a04ca90,0x0001b07594714b39,0x0003766edb734998,0x000077fdd00849e4}}, {{0x000869459607c4c7,0x000c4a2823d2a191,0x000f0c346c25108b,0x0007d785158a6d3b,0x00007e489373cae3}, {0x000a7f304840c842,0x000a08f43f2912a2,0x0002fbe1729e4bb0,0x00028709c4f280f9,0x0000201f93611efb}}, {{0x000ad0bda7974af4,0x0005389c05296416,0x0004cb76abda5ecf,0x00088f85f754c7c2,0x000047c39eefff6a}, {0x000ef4343c9b4a94,0x000d4bb7a27b96c8,0x000f48abe786978c,0x000ca9cd7614727c,0x000061d39a4e9882}}, {{0x000b2bcdba7c5bef,0x0002040e82c7d98c,0x0003da87f7a20776,0x000de1523702befb,0x00001de9d096e046}, {0x0008b008f178210e,0x0000448332b989b3,0x00042b84ffde25ce,0x00070d3efeacb710,0x0000f18da37a2d17}}, {{0x00060e26735666d2,0x000fc57f5610acbb,0x0007546d4a7366dc,0x0003a833bb5f11b2,0x00001d815c609e9c}, {0x00095cb0437ffbfa,0x0000948f5b486c09,0x0006bd916f7bcf31,0x0000b87395b09b27,0x00004e8d8c9a4070}}, {{0x00041de5bdbd9371,0x0007be38711fa84d,0x0006f2cb401fcc83,0x0000193a4baf92d1,0x00005c9fa811626e}, {0x0007ce2ec2720c70,0x0008351012112d54,0x000741181f3df95f,0x000fb101caa1421f,0x0000a6d145391ef7}}, {{0x0003e76f52e737b3,0x0008b153cd4c597a,0x000b1f2cb690af03,0x000fe5aac80ff54e,0x0000f1fde4870f82}, {0x0001d9fc80aa5815,0x000701e0254a9b91,0x00008d9e03b39021,0x00058cb9d9791e0e,0x0000755cc5bcb5bc}}, {{0x0009e0c2ce860434,0x000fad99789d9347,0x000ca723a383cfe4,0x000ab93713011097,0x000015d43c8d3294}, {0x00089eb941c9f1c0,0x00077e0a78126ce0,0x000da428594a8b44,0x00045995df8d73b1,0x0000085b5acc6ba9}}, {{0x0007d41d3b9f2be9,0x0001e317380a4f50,0x000743cd69a185b7,0x000a3cb0ef1dd23f,0x0000c6f878d3ac81}, {0x0002defd67e4c7a9,0x000b3b6178e5ad5a,0x0008fa9c2073e098,0x000e3f845fb5d329,0x00000ed787e92ecd}}, {{0x000c2092f308c0e2,0x000cf372518753d3,0x00059ce271c67fa0,0x000b1d3d864e401a,0x000067229588778a}, {0x0009ac48d524d467,0x00099d0876b9e6ac,0x000365b626974faa,0x000f2027749d4cf2,0x000070d784766bdb}}, {{0x0005d1d7ca4afe69,0x000f7a9e7f152ce1,0x0003ff356ee399b9,0x000662e7d64a6c2b,0x00004e83beaf5730}, {0x000c85f020b5cda9,0x0001bec166277cc4,0x000cfd24f3afda30,0x00076a744e4b56c9,0x0000a9916a5eedfe}}, {{0x000fa6272bc5acf5,0x000cefa642bb8d4c,0x00068f5594a97456,0x000df80bedbcfd29,0x000069874eb72838}, {0x0008a12ad07adf76,0x000a250132b7f40a,0x000e03fac5809168,0x000a22c9ab9c544f,0x0000df51bc0f4dd0}}, {{0x000ad692517a2b9d,0x000b734402ced5e2,0x0000f7b228d8914c,0x0009398f05425fa0,0x0000ec8d276b76ec}, {0x00069d5463a061d6,0x000728f1acfb036d,0x000cd88a2d6ddbd4,0x000ba149b9378346,0x00002bbbfad499d0}}, {{0x00010c3a4809f81d,0x000743c8ba6258e1,0x000de0fe62140ab3,0x00009b8609de61a8,0x0000981e461acd1e}, {0x0003461543c36db0,0x0000f993771d6b06,0x00033281a273ba0d,0x000c77143e6ff6e1,0x000035a642c2fc19}}, {{0x000ef8af2b81260e,0x0007770b18ec5710,0x000a1ea80ad37192,0x0004707b4022fecc,0x0000fe51b5f7bf41}, {0x00093d72d28d2eae,0x0009b90c140f34a6,0x000335e00449e2e1,0x000091fe11c41f75,0x0000eaa50b2c1865}}, {{0x000cfccee288755a,0x00076204618d3307,0x000b666fc9acda01,0x0009c38ee7071f98,0x00006f3fade76154}, {0x000c58c20c01f25e,0x000a2f9c9a157e82,0x0008d7ef9691b1e0,0x00034c9b3ea053c1,0x0000fe72dbc256d6}}, {{0x0005764654f25ab6,0x0009ae7b52161674,0x000bc1c4b22e7a1d,0x000c905ff14471fa,0x00008d2388cb4775}, {0x00068e06e8a88b79,0x0007d25e7385d977,0x000b4997f422d547,0x00018f9575d9ad31,0x00008a642eb9c009}}, {{0x000635f43433b57d,0x000665e0a64cd543,0x000f7611b6157565,0x000371fe20970719,0x00008f08a7576fb0}, {0x000f528e7c19e126,0x000d86a273b686fd,0x000ecb6a9eb7491c,0x00099d7cc31d126b,0x00006d5b3b32c1c2}}, {{0x000d0b2e25cc9404,0x0007ea222455a916,0x00089fc82928a4da,0x000ac5c3a8de8988,0x000064f26e535f2e}, {0x0009e29fd63260f0,0x000dd3e24fc71457,0x000bae4202864593,0x0003c6895e5601a6,0x0000c5a1f6069911}}, {{0x000dfcc37d0c2daa,0x00007dfc9cca7ffc,0x000b7d28f4112fdc,0x0000060424fc5c4e,0x0000dc27dc84402c}, {0x0005cf0f7a1c6f9c,0x00072632a0fbbeb0,0x0001285f3c9bf405,0x00052cb7ba5b1373,0x000024a1d802dd1c}}, {{0x00005e8e5d9c7c3d,0x00038f7b6bf10095,0x00089e65c94ef08c,0x000d589c3fc80399,0x0000512ab462c8e0}, {0x0006248da5cee075,0x0004b0bf71366122,0x00009b19f788483f,0x00068461ae7d4670,0x0000e3240047ed4d}}, {{0x0004a8045830ec3f,0x000ff27347bdebd9,0x000eb6a8bec329d4,0x000a3bc9be726d25,0x0000afd3ea7f8f65}, {0x000de1f94e8ec819,0x0000fd5786e2d77e,0x0008c8d2f48236de,0x00088e979e9d9bc8,0x00004177d03e4855}}, {{0x000a920680b0b442,0x000dd67952d80308,0x0003db335984f1ab,0x000ab57e1ee014c2,0x0000efa311d1fa2b}, {0x000fa774c0978f94,0x000d6ef134fea6a1,0x0003be2502663d93,0x000589a91cb57c89,0x0000e81b2b61a07d}}, {{0x000445556f590009,0x0001d606164fbd7f,0x00055c8b39ec5161,0x0007b36417bf0954,0x0000bfb7b6cc3e60}, {0x0007ef44ff8e3e17,0x000ee02f7cb58de9,0x000726935b92e359,0x000ec248d2c5ba66,0x00008f73b6ca1537}}, {{0x000ea9a101c27ebd,0x00088450bc2d762c,0x000a6b7821eaee2f,0x000e7617f29336dc,0x0000bc610f11b9ee}, {0x00020c50b2e18605,0x0009a3531a079c62,0x0003c6f4589a8346,0x0002726dc650c838,0x00002cf4bee72e9b}}, {{0x0005ef53014f895c,0x000dd9551573a2a6,0x000147dcafddcafa,0x000427c62e1a2646,0x00006be9a834c331}, {0x00031b08c02f0e7f,0x000609f1f2c5658d,0x0009db9bc2cb949f,0x00041b03603bb15e,0x0000294d7c597e01}}, {{0x000f7cbdd4b39e30,0x0007591b53bf0d2c,0x00051085bc0a78af,0x000d6563b36998a2,0x00008f29a516edf9}, {0x0002df96b9af9b9a,0x000aceaf18ac1998,0x000cb38bd6224ff1,0x0009b595e64776cd,0x000086b39f9d62a5}}, {{0x0006cc6d42576447,0x000663d1585e0963,0x000718b6eb780a69,0x0008a786d3112c4f,0x000050513009055f}, {0x0001c1f94b567f55,0x0008f04cad491658,0x00005055750428c6,0x0005942f8ebe9db1,0x0000bff399ae72d9}}, {{0x000b37679ef9c071,0x0007c79b043a42e2,0x0001c11d543e3065,0x000090850df636db,0x0000cf5e687e4648}, {0x0004641c28d6f0e4,0x0009d91286f41e3b,0x0005a6a95105c1d3,0x00040a84b6eed5a4,0x00004f9c5c40b1f7}}, {{0x000635917a1fc0e6,0x000de448fa1d343e,0x000d04e3e582a0ed,0x000b5be78e3f3810,0x0000e69322253204}, {0x0003f2d8fdb2f68b,0x000dd150d2fb477b,0x000e74fd46b26937,0x000832fb96b093bb,0x0000fd4236540d29}}, {{0x000627c7da59bb55,0x0004a420a8a1e312,0x000b69e2db5a517b,0x000f174190a03a06,0x000034c0dc213d8b}, {0x0007341656c0a5bc,0x0004601ccf3374cd,0x000728ffe8da09bf,0x0006f93d580e29f4,0x000070d257e9d4a4}}, {{0x0007cb0ef9a7de8e,0x000c7be468b6982a,0x00013cbb99b936ba,0x0006099f3a374002,0x0000d5e01e4045c3}, {0x000fd2a477e5592a,0x0008ab788c4a8e5a,0x00062949464a88f7,0x000f822e6ed3ab7b,0x000049956ac60d9d}}, {{0x000632ac60494b85,0x000755001958b3c9,0x00092a6b084635a0,0x0005d4a6261cd6ca,0x0000c5c5a09d09d8}, {0x0003c778bbdfbed1,0x0000571017535054,0x0007f0364db303b2,0x000211c2f39c2c8c,0x0000b2228378b171}}, {{0x0001b82327cbef8e,0x0006712292a1eb20,0x000d0aa8149ef800,0x00044484bd3c30a6,0x00001bc4794e2151}, {0x00007c4a40a45ab2,0x00072ef2f8c60537,0x000ab01c42dd4a68,0x0004c68445e92c6b,0x00009930cf73325b}}, {{0x000e0f195743160d,0x0005e665920d09ed,0x00037949c34c1646,0x0001563924baaef5,0x0000864d65b629cd}, {0x000d0645d626af27,0x000b919ee5e27e75,0x000bcf4e3b28ade6,0x00072b450f7afe7d,0x00002fc16bb41c90}}, {{0x0001f5474504517d,0x0007449fd75747aa,0x000d80fd4dd4e899,0x0000fb1503a0575a,0x00000bcf27aa872b}, {0x0001562ee6845a9b,0x0003adcbda3beec7,0x000e87f54cea9040,0x000d9aa4b0fd3e40,0x000055424363272e}}, {{0x00000c0c822a63bb,0x0004adabf48f17a0,0x000c2629e0a4d95c,0x0005564c47efec06,0x0000fbcf94b6fd09}, {0x0007de8757b55d12,0x000113777841f5cc,0x0003e33bdeb58cf8,0x000534cfd0dd9945,0x000091a701a6191e}}, {{0x00034fc2d6c998c3,0x000f5f1753a09b2d,0x000707feecebe5aa,0x00069ae9d032ee76,0x0000b6aa01f1d59f}, {0x000215a8ac67882a,0x0004aa4451eab1bb,0x0003598726a6d1c4,0x000ec7ca810ae0fb,0x0000c1072b2ff7a7}}, {{0x00062dfef6c9d3f9,0x00089e8be45575b3,0x000c3679a444f608,0x00071da3d3cefd86,0x00009c6b4fe674c5}, {0x000df41f2400d99b,0x000e475f7d54f051,0x000134e5aa9dfed3,0x000b7685cd7bf7e3,0x0000b240168e9d1c}}, {{0x000f0d440f9f2318,0x000c0a943da7cf17,0x0009cb3de587af78,0x00062e9e6652099c,0x0000b949476ce142}, {0x0005db129e890250,0x000a0753258e9fa5,0x0002708f8e51d5ee,0x00097e68246e57ab,0x00009d5a84444486}}, {{0x000537887ec45f50,0x0004ae322bdb29f2,0x000adb167eb07940,0x0007ad30b3e3e19d,0x0000cd3891451308}, {0x000e460bdfbaf9e1,0x0006182f1a4179d4,0x00095e491e6878d6,0x00021d1b6dcd2c5e,0x0000e017c1488203}}, {{0x00015e8bff7115fc,0x000daac297105666,0x000baadbd6bf7eec,0x000495ef121aecb3,0x00004b4a97a0b0f0}, {0x000019c825163c75,0x00095c56e3c4a123,0x000b6668b677a76b,0x00092bc127011ec5,0x000076ef43ce65f6}}, {{0x00079e1d0309f4a9,0x000d470e28f20534,0x000381c00c0cf6f4,0x000f7d93eb4f59fb,0x00008542677c1440}, {0x000f92b296bd38fb,0x0002503a89b42228,0x00027708a23f058b,0x0006defa6cc068e8,0x0000ed74c5c5e932}}, }, { /* digit=18 [{1,2,3,..,}]*([2^126]*G) */ {{0x000bda36cacdb2cf,0x000910b10ef58eee,0x000d29b4c26a98fa,0x0003e3520f48c766,0x000080d336a84be4}, {0x000adf4bead7d2a2,0x0007e7f8e550baac,0x00016417827824fb,0x00050949f19c4c62,0x0000c4b8ae7907f7}}, {{0x000429a647025b7c,0x000f6df2b6d14a77,0x000609d41bea840f,0x000070b3276b7b67,0x0000d649bb3d432a}, {0x00057149509e594e,0x0009f596b64efcab,0x000a64e95827d522,0x000fd96c407e119a,0x0000c8006ba42564}}, {{0x0001f1f6379bea52,0x0003f11b63e85354,0x000bd1b7caedef57,0x00000814fa04ef2b,0x00000ba83d7a9136}, {0x000975bc42555421,0x0003bef8e88beb41,0x0009541ba9f5aed0,0x00002dcdb28a4ddb,0x0000c066be89e1f7}}, {{0x0009e6504120719c,0x000a1d96a1faf50c,0x000f5b3b23b7d22a,0x0009b4c352bf7130,0x0000978872929651}, {0x000356cf46ef6d36,0x000d4b97e2b6d316,0x000745689d64bc86,0x000562e5f781a12f,0x00008e0f6cd43d40}}, {{0x0004a418781db583,0x000ddb124e3c2a76,0x00081c4f1f2539f9,0x000d86b17c619fe1,0x000024aecc3f2e6f}, {0x000536d45da54e56,0x00008208d6bf93b5,0x000bbdebc0443405,0x00079e4ec013e263,0x0000aed5ad15e7e7}}, {{0x00005bb45d491a70,0x0004f423f59393d2,0x0008aca8510e837a,0x00078a4b50263ba4,0x00007b7f90bb8d6b}, {0x0003e303142c350f,0x000579c8254cdd54,0x00007552b0caff31,0x000f3c7248599467,0x0000b09e2c65643a}}, {{0x0000623413605a2a,0x000e240c98eef219,0x000f738bd35a0ab1,0x0009cd49fd931436,0x00004b15c7d1bfb8}, {0x000dbe8e750cc8c8,0x000b2cf64775adee,0x000319f210d69428,0x0004c23bb86bcc34,0x00000692bf71bc31}}, {{0x000dfb3eb9b38812,0x00060a94cb32edd2,0x0002674cf6680001,0x0004a91b08a68240,0x0000a3f5713fd970}, {0x000b550f67fb936a,0x00009cdf975dc67d,0x000d4f8ab994e401,0x00062714fffa287d,0x000076cbd2a37974}}, {{0x000e793d6134da7d,0x000bfbaad67700c8,0x000044bc3a9b1458,0x00077a29db52c0a4,0x0000ae12105ecf19}, {0x0002c2d93e614751,0x000a3490a4cf1ae9,0x000abd69904507c2,0x0008d306a123b893,0x0000b8500fd782db}}, {{0x000abf3c48af855b,0x0003d34d16708b4f,0x000a6ed07a282725,0x00019f730cb8f53d,0x00004ed0b7fb72b8}, {0x000816f3f3cbd30d,0x000d59260df36d85,0x0005cd9529f3ed7d,0x000918b8a442833c,0x000032c62276ad4e}}, {{0x000505323819ad11,0x000a66c1746fd93f,0x0004515701dbeb19,0x000ac25d76041aa0,0x000039541e46492f}, {0x00082e4f5acecbe4,0x00047f003d36ac5c,0x00043a011a75a08d,0x000a029ab7481052,0x0000a07bbb938ff3}}, {{0x000313ef5b5203b0,0x000154281306d809,0x0007c4b68fff9649,0x000164f75079e9fa,0x0000ddc7de06c72a}, {0x000a43bee64870b2,0x00058d075707ead1,0x0007b284d06638d0,0x00026466a4426597,0x0000eaeec425f7aa}}, {{0x0009ce770a7c3145,0x000bb6337494e900,0x000a3e657770528c,0x00046d72c5c2351c,0x00002af88081301c}, {0x000002b6736a4987,0x000c03a730f22f8e,0x000a208d941c9745,0x000aed32506797d7,0x000039e0f2030605}}, {{0x0003d4dfd808ef40,0x0004a58fcc7a1a47,0x000d19ae0ad86492,0x000cfe1443bf900b,0x0000040e88ad8cdc}, {0x000fb32cf6f58d39,0x0004562194b4f5d3,0x000375f3350db919,0x0008ebda78332dc7,0x00005e8bc45b952d}}, {{0x00037937dd5f4dc8,0x000ad87dee916fc5,0x0000f9f838cdd726,0x00035bd06c293d17,0x000082c987f7d4fb}, {0x000e6e2af0881b65,0x000cecc3a59895a3,0x000db383e0d7d33a,0x00049900fdc70f9b,0x0000f53161d8db37}}, {{0x00019a6df48dd005,0x00078c392aee7d99,0x00047da22270b610,0x0004292dad3f50d6,0x00004f9084de0936}, {0x0005ceb1e6d4f40f,0x00031c3e122362e4,0x000da2cb1ca24344,0x00089b025e58689c,0x0000ccbfb734d9f3}}, {{0x00056e296b1d2a7c,0x00059aa411c51ff2,0x000534da9f87d206,0x000e1eef18a860a5,0x0000cafe63ce745f}, {0x000de8dab4468f3a,0x0000fb7e0c6a3275,0x0006193be6dadc7b,0x000ba599d3ced6ee,0x0000dbb9b3d4d796}}, {{0x000f56c3e083f9ab,0x0000f603effd3017,0x0009c1d0099ea92c,0x0007d4e4fbe0dbe4,0x000058f3d2157ba5}, {0x000ca441fd54b954,0x0001acfab07e949c,0x0004453173fafb5c,0x0003e4c363c1d941,0x00009a533ea85b8d}}, {{0x0006b73590d7896f,0x000cf513e5a6272a,0x00050b6b74115ef2,0x0008e802ec0c8d3c,0x000049dfcec6abc6}, {0x00026d644b778478,0x000145e3ef68d48e,0x000f9b1877d7f703,0x000ca9888630059d,0x0000e9f78f370136}}, {{0x000cde2c3f33edbe,0x000ec5924d163d97,0x000758c8e3452e6c,0x00032d47700eb684,0x000001d15f0a9f82}, {0x000418cc0818999e,0x0007ac6d0ed810c4,0x000b5e011052bb51,0x0000cd43a902bc60,0x00002a9eeb8b57ff}}, {{0x0009cbbf986df839,0x000414b85d3a71d7,0x00005e069c77aa0d,0x000f8f79dbf4a89a,0x00001526933b2c78}, {0x000844b710bed445,0x000cab49b00f7c1c,0x000718415d8c3d66,0x000865e5b99f683e,0x0000f111505bec98}}, {{0x000b317b5fec109d,0x000ee60dd74ac94c,0x00063fc3e8bcf0db,0x0005aea594aafcc1,0x00002fd718e53283}, {0x0006bfa2ad47da58,0x00065d79c62c0537,0x00022ffb34140d60,0x000316bdfd12c941,0x00008ff86a718219}}, {{0x00005b5677be2211,0x000de539062c2e91,0x000ee1b283c1d085,0x0000ba39a96ec9f8,0x00005bef7b5be408}, {0x000d5fcee8efdc4c,0x000c2f4b6689630b,0x000821b7000e829a,0x0006ac1efeb571f2,0x0000900fa02078a3}}, {{0x000ac0bb76286c73,0x000d00f0c3a98fed,0x00087e24013a68d6,0x000322ae9cfa421f,0x00001657a067cc6f}, {0x0002945e67c00f12,0x00008ced22dd80a8,0x0005f0311374391e,0x000812c96c16f73e,0x00008be3307fc625}}, {{0x0000d24be55cf092,0x000bdccaaa5ce5da,0x0008f0f8dc643eb3,0x0000f68b247fa097,0x0000c0f660a3692d}, {0x00041339e5f44cd6,0x00038483a65d698e,0x00067c073941df7a,0x000ed7f027b59c3c,0x00000823924cbd81}}, {{0x000e36f7b744a49f,0x0001e8cea2841e6e,0x000a884d4e78ac9b,0x0002006211afc386,0x0000bc9bb9210e86}, {0x0001811b825aa7d6,0x000fb8213b25406e,0x00056e2bd62d5f8f,0x000b0d142d4390b7,0x000075f859df9893}}, {{0x00057cfe953f406d,0x0006157c97bac651,0x00024b6d0bf2ff3c,0x0000073279a7e31e,0x0000cd7666235cc9}, {0x0005f46b2d76ca4b,0x000b0c3acdad6d7e,0x000d9e9e19354299,0x0000b8f783e65fb7,0x00000c641307f969}}, {{0x000c59b6284008a8,0x000ad0ccb64fab61,0x000697bfa47d385d,0x0000a004d91fef33,0x0000201b805d7b1a}, {0x000b4cdbd7634bf8,0x000a8b1db7c95182,0x000a7b2b0dc8df9b,0x0004e30b652cca38,0x00009346424294cf}}, {{0x000967ec6fb1f7d1,0x00013f8595e9532f,0x000760d79b0e83e4,0x0005cb6f0edab69a,0x000015764aef0bc4}, {0x0009ea00e9a799c7,0x000ac5b817fb15d5,0x000ad401b2f89864,0x0007afaa02dcaefc,0x00008c0d626305da}}, {{0x000f2627ea780449,0x0004d0e16afee339,0x0001b1273fed7f14,0x000b2aaf8ae2dddc,0x00008e33f95fb10b}, {0x0003ee06234667b5,0x000f276fd3a5674e,0x000130d66a2b11a9,0x00010566bac7e07b,0x00002e0bb494f27c}}, {{0x00054f5c6635026b,0x000a5a2c274a495c,0x0003d78d5e70c783,0x000d415596f0ba22,0x0000bea114aab96c}, {0x0006e4a26ec6994e,0x0003684f55dc21ce,0x000cb57be6c33dcb,0x000313516f6d6dbd,0x00008f669b41b988}}, {{0x000c339ae3dc8edc,0x000f91873e0a1cd8,0x0006e937184cc542,0x000c8d374985e854,0x000064db8f80da1e}, {0x000fd63fc2e60274,0x000092f545cfdc42,0x000f97827e622ee9,0x00065dad12fb4d99,0x00009f63d4cea6ee}}, {{0x0001d6efcdf88357,0x0008d95feecaa92e,0x00070e0938b6f590,0x000a9f0529925a20,0x0000cc42d8fc5d2e}, {0x0008c449b39c8e3e,0x00018b9ff21e615e,0x000c5b91c41f334c,0x0002004dc2fadbb9,0x00006d8605de3771}}, {{0x0008cef52c6038cb,0x000595e25e5d6385,0x000a8e39d52faa35,0x00038504ffcbe219,0x00000875f8ef9618}, {0x0009872453c11381,0x0005c29f2eb78994,0x00004e6c20daf621,0x0005430dcf55501e,0x0000288ec97e36c0}}, {{0x000c030591d26efd,0x0004d6d48ef7dce4,0x0009fd5d0405d2b4,0x0009ebbe289fc630,0x0000f97f0f01043c}, {0x0000b590022dc8ea,0x0004f976d4fbb359,0x000cecbf9a4644fc,0x0003207c99203ebf,0x0000edece41acc46}}, {{0x000a362d721e9089,0x000a8925abc2aab2,0x0005350debe2e21e,0x00009fc91b3baa47,0x000048d66950c56c}, {0x000efeca03b29fb8,0x000f6bfda542da62,0x000139636634ba83,0x000c501c74caf2cd,0x0000b76d82e0f5b3}}, {{0x000f6a56da8987c3,0x000e1aae6fe463a2,0x00059cd2c45e1dbf,0x000f0def678e8651,0x0000cea256fdc1ed}, {0x0003034d6ed1ba9c,0x000d0bf5e4dac73e,0x00084887837e23c3,0x00093ecd182d4808,0x00009476a1eec1f3}}, {{0x00052dc77d7fb769,0x00013ff38f95cc7b,0x000733f795b3e21d,0x00090f612de561ca,0x00000f59a5455061}, {0x0007d48864196b53,0x000db4e3286957a1,0x00022d8d9ef59a96,0x000546011073136b,0x0000f1697c656115}}, {{0x000317c1f8fc48ed,0x0006c0c0118eb24c,0x0000b3a095d3b7f5,0x000bbb608213550f,0x00005d5ad61f1fac}, {0x000a62d9583b13f2,0x0003577ecca5129c,0x0008c4140f3beafb,0x000b94480bfb33f0,0x00003f0a96a83959}}, {{0x00031c65de0895cf,0x0006825228776fba,0x000cc88cce49fb2c,0x000d50e32472dd56,0x0000e65850b7a0d3}, {0x0002d9997abc2bc7,0x000247d47511ebbf,0x0000c31ba0b5abb4,0x000ba45f83b7816c,0x0000b1293a82eebf}}, {{0x00014867763f2007,0x000c9a238ab540ca,0x0002810892f80e56,0x0000ae04b954b5a9,0x000009638ba155c2}, {0x00045f04b72df059,0x0007c79932f148e2,0x000f4ad95262dd9a,0x00058706f74ca482,0x00007911b864b69c}}, {{0x0000b9c737140708,0x000667edd421d9f3,0x0008968685c81d98,0x0002788a4eac735f,0x0000023a157c9f57}, {0x000b4b003c82278b,0x000a81472fd167f3,0x000e0926bf38ac74,0x000e573126c462f5,0x00001ca6838518a1}}, {{0x0001d85ac1d95c07,0x00033d583ca23351,0x0005118833877919,0x0002e080183f6e60,0x0000ff39e0469cbc}, {0x0002e04f226307cc,0x000f4bacaf9a2435,0x00074e2a51232d0b,0x0004f77d72b628f0,0x0000acec834b62bf}}, {{0x0004545c8ad66709,0x000cfc688d8046a9,0x0004edfdc8d75925,0x000f05ae813c9e06,0x0000f09d9f9bb086}, {0x00062ca1db3df5b7,0x000c5b5ffcee14c9,0x00098918be83ad5a,0x000ac894b0684569,0x0000a8eed798d0b3}}, {{0x0007970ef932b7f4,0x000f2ef627b27d5d,0x000b1f232a660b84,0x00047a67e2544348,0x0000f46ef3c81556}, {0x000ae5e50254dbfc,0x0000dbc8b8f53a6f,0x000f81f9760130dd,0x00056daa15ae29e5,0x0000531c6e3d8872}}, {{0x0003fc5aec293c17,0x000fae2a8b3062bd,0x000d294391c65007,0x000ba8bc7a567060,0x0000e892b188f41d}, {0x000fea5c9cbb5a66,0x000a06ddbfb94b09,0x000a553dda4501d5,0x000c2b5f030fbe8d,0x00009f35d7661397}}, {{0x00053c7d6c32ad49,0x000e202b6f62edae,0x0009918ca0e11d30,0x00064c3b7cc78f3d,0x0000aeb2ed04daba}, {0x000308348ade515d,0x000a42f73385ada9,0x000c1e0d66b4b6db,0x0008698732c86253,0x000004118fd191f3}}, {{0x000796becef5c499,0x0007cd9c3e671366,0x0006808dd995c7ed,0x000e24412560f80a,0x000092c05fbf5a45}, {0x0001d3fb0df606cc,0x000bfd721b8febb4,0x00095b3096c03c24,0x0004db6d2624db4d,0x0000abed17dbcf2b}}, {{0x000c4df41f71eab0,0x000a65e016a9a3c4,0x000dcf582ca058e1,0x0007f71ec4c968da,0x000026cfe1cad268}, {0x00096c924f46e504,0x0004491a46f19726,0x00070b7c43b16a8b,0x000da051694c0dab,0x00004ee2a129241e}}, {{0x000900a5814e9247,0x0005613cf2606c1c,0x0005cccca1791d81,0x00048d0077d293ce,0x00006bc874a43ebc}, {0x000037e17cc1b585,0x0001d8d11bf83c3b,0x0005987d393c01a5,0x000228591bf583aa,0x000025efdb1260d8}}, {{0x0003d91512d96c5e,0x0007e4b4ad0fa8de,0x0007b0bb68b040c8,0x00043c9dabe6dfa3,0x00000d7ee9b62348}, {0x0006da6bed5911cd,0x0009a6ece7ff38f6,0x000e5dd83880a808,0x00053087b04129e5,0x00001bbc6c30ba0f}}, {{0x000e84dbadaa5f56,0x000cd377815fe20e,0x0008c62698e27faa,0x000347e02c37a9b4,0x00008e9bf569f39b}, {0x0007b248d318a6ae,0x000474a21df44e51,0x00031719dd246130,0x00074f8d75f0927c,0x0000b89236c1ad86}}, {{0x00017308e1e58e7c,0x000867db13b9dde7,0x000306f021259e44,0x0001a4349c8e56e3,0x0000b578ecfaafa1}, {0x00084505fc0f3955,0x000c9cf62fa54df9,0x00036b0d416db73b,0x0005d79d27a78dac,0x00009d0ac179612c}}, {{0x0004b0085e82cbc7,0x000abb85d10839db,0x0005f3bffdf52af9,0x00079078e4cbea13,0x00006cbba6b97a8a}, {0x000b82422c5fa00d,0x000a3ab275192d04,0x000e62fb0c96cace,0x00026b9b5e0fdcda,0x000028851c8af90b}}, {{0x00012449f8c83d3e,0x00021b484ffb3484,0x0002a03c330d56a3,0x000de8f64f1a4e29,0x0000968c4493bb60}, {0x000b81bd33e1a3ce,0x000aa34a593e8cb6,0x0001cdb8a73950dd,0x000c5aca2dd94ae8,0x00002196c60ad005}}, {{0x0002ecd9e6a86c14,0x0005bf4b4d550dfa,0x000030370fc52488,0x00002d4d8f6fdb09,0x000086c76907c7c6}, {0x00017c32a9829592,0x00024cd68ba39a26,0x0004748f380234c0,0x0006b496816425bd,0x0000b82c805a4841}}, {{0x0008d667d5dc4d15,0x00099cf2f678940d,0x000694f978881dfb,0x000dbc7192ed98d2,0x0000de896634885e}, {0x0009ddbb3cc587e7,0x000d4b22b2d17299,0x000c81311033e3ff,0x0003b651ec3fe79f,0x0000aae471a0e640}}, {{0x0004cd3ea6e3d753,0x00060a108f5907d1,0x00041859d6c895b2,0x0006353d871a05a2,0x00000971096c4c9a}, {0x000fa44e4d592627,0x000e35522b5be21a,0x0002456c5b24ea58,0x000fdf656200f0b2,0x000002a5a001b93e}}, {{0x000a930b41d968d7,0x0005f45cda83c150,0x00048023ce9f4ff1,0x000af875c0255a23,0x0000618af75ec0f1}, {0x0004f16f88f7d864,0x000f11b9e30e6555,0x0008bf8f34a212db,0x000a4894a74095b8,0x0000f73c218673af}}, {{0x000719474c355ac3,0x0007767feed9b317,0x0001495f898e9455,0x00044f2e1c716c37,0x00008656ae1b3716}, {0x0001a34aa65dcb6a,0x000d0b1c27a68be4,0x000536b1b2ce4de7,0x000a67af11085552,0x00009a395ffaad98}}, {{0x000d3f4d7c754474,0x000c22c337ab180f,0x00072abe02a8ff15,0x0003fc10970c2e93,0x00003c652e722cfb}, {0x000c02f3684913d4,0x000297055bcefbca,0x00000984f91a0cab,0x0006a13ef0aec851,0x000083ec8cccc61c}}, {{0x000a2ec8681d7400,0x000eb2e1e27bf54d,0x00021ca664bfbd0b,0x0009eecb3fb586d7,0x0000407b0b572888}, {0x0009fa49e7df0d49,0x000c8db83e5cf139,0x0008d62a8d255ab6,0x00064e972c4b357c,0x0000b7d17a711fc4}}, {{0x000bb7a820c7747c,0x0008591aae71b534,0x0000ffe0e9e5c12a,0x0006d406fec50176,0x0000f79f9725d57d}, {0x00087fd706dc3021,0x00069d9f06684b74,0x00056d2a20079b4b,0x000da7fcbf83e575,0x0000880dacfe1d20}}, {{0x00058e9c302ba867,0x00031efb88acbef5,0x000b99aabe4819fa,0x00022ba1871c5dd5,0x00009777c5931fe9}, {0x00099616dc64a369,0x0002003ba21a955b,0x000169185be37b58,0x0004c6afe824b374,0x0000bfc77522de74}}, }, { /* digit=19 [{1,2,3,..,}]*([2^133]*G) */ {{0x000a727255b1faf7,0x000452ecd6f25da6,0x0004ecafd5a5a652,0x000bad00768839c1,0x0000a47db65e8b03}, {0x0008ff333559d9cb,0x000966d9582a7941,0x000861751aab0822,0x00061a8937485277,0x0000e70755598baa}}, {{0x000d0b3a9d6e707a,0x000deb1e6b972802,0x000a9cdc816ee683,0x000300c2c0420274,0x0000882a6225668e}, {0x0005839e9d3e56bd,0x0003671e54dd8b9a,0x0004f99975d7c4b5,0x0007ae4fc6ef3c37,0x0000fc5b94dbc8c6}}, {{0x000a6cf4e2db7b3d,0x0005cf35c5c3f019,0x000bdb6f316a364f,0x0006e1221c2e18a4,0x0000dc4b2200d39e}, {0x00078f1c8e821915,0x00009b22f686d8fb,0x000a305a94c1ab12,0x000cd236717c6df2,0x0000b14404a2f1a7}}, {{0x000bac5f488d5a8b,0x000732f43799d874,0x000877268650340b,0x0003966fe4b48921,0x000034a8a84a9b2d}, {0x0000e4682408320c,0x000cb0f0f018a4e6,0x000fcb65b28d1028,0x000898348a10c5df,0x0000188d1de6f0a9}}, {{0x000e203166a36c7b,0x000b4b6efd58b491,0x000b8cf6095cca77,0x00087b5779dd6452,0x00003dee080aa1e6}, {0x000516401adcd8a2,0x000c863c78749a85,0x0004b4b58a717ce5,0x000b1c6419ecb4d4,0x00001c953dfc5f7f}}, {{0x0005a4caf12ba860,0x0000c62e1874ce63,0x000fde52b08d1a6b,0x000a7df06d9f7da7,0x00009e538c0d777f}, {0x000d8554da32762d,0x000fb42b270d4ac9,0x0006c0faa9638fdf,0x000554ad39e13597,0x000052af20a0ab43}}, {{0x000de3d347ef0da1,0x0000e86b94de0d5d,0x00081ede6978f54a,0x00004b7554d28aca,0x000093f67d8e3d7e}, {0x000d6d4b2accb9b0,0x000eaac44bfff953,0x000334bb519d0743,0x0004597cb4782f84,0x0000e289c03cc10b}}, {{0x000d7c4e6d753278,0x00056ab83d3f5734,0x0003ee15022d081a,0x000b4954cbe1d2ec,0x0000296520fe0c21}, {0x000b30c9f320aecd,0x00021106ddcb4b09,0x000f1b1848a3530d,0x000247c734a80168,0x0000496e464291ce}}, {{0x00090a90c5f1581d,0x00021f437e8ccdee,0x00069fdd47f1c872,0x000a9c2e4357299f,0x00002d0483696306}, {0x000b5fd8d746c503,0x000c8bd661cb171d,0x0002cd43b1cc7a71,0x0001118c6769457e,0x0000150b880fe3d7}}, {{0x0000f541d58b53b7,0x0006631c29ba2789,0x0002be7fa10f036c,0x0004b70db1abcfa3,0x00008eb4ca6712a3}, {0x0007134fe95a5dc8,0x00009bfdd4921a07,0x0004074f4fc33414,0x000344776f51e869,0x000039fcc742b48d}}, {{0x000b7d00d6409a81,0x000dd67668b16ac9,0x000adde6b0cd175b,0x0003b8db64a49847,0x000077b648118844}, {0x000b3a9b85df3c57,0x0002bc406a3f3c24,0x000c75b3c764621e,0x00010e175b8c2793,0x0000b0bdce77a0e4}}, {{0x0004813b51c2e64e,0x00005742d51835f0,0x000ecc30fadd8650,0x000bedf50410b627,0x000021e7232979d7}, {0x0005b9c764997bfb,0x000b0468d42cf2f8,0x00060163f7fd4379,0x000bda4d0bb60197,0x0000a925ae795940}}, {{0x000c27028b18d58d,0x0009810f017ccd8a,0x000df69987d79344,0x000c3b7f59b76dce,0x0000dae304e49afd}, {0x0006d38b645dc0df,0x0006de4e4718ba52,0x000f7e2d51a37fea,0x000a96abfb95fdb4,0x00001485263258e0}}, {{0x0007d52ce0614c9e,0x0004e699b20813ee,0x0006fd82d87f7d47,0x0004dd26820af588,0x00005ed613674375}, {0x000d90e6407c8b58,0x00045ffbeb5f5d2b,0x000b95218b07597c,0x000bce1f2697c7b4,0x0000512e42cb5fed}}, {{0x0007ba3ac56e0291,0x00063e80caf76d16,0x000402f16cd63473,0x00035e2bb89abbd8,0x0000bbb3d5dfbc8e}, {0x0009ac52a39e9a6b,0x000961b06920b768,0x0007fad592b5ca40,0x000305260906fb21,0x0000df04971052ab}}, {{0x0009f76f719e0c19,0x0009462eab4521c4,0x000093d14459bb4f,0x0009e86bfea8af42,0x0000c845c0599acb}, {0x000619f255078fa3,0x00078ac8483e27a2,0x0002f48e15d94779,0x0006657197c26f1c,0x00001b0bbf55242a}}, {{0x00058c998e87eec5,0x0009d5bf41a5e976,0x00045718c33c7d9d,0x00008841dd908702,0x000048d0cab1bd20}, {0x00064a0500d4afb9,0x000806c82de8d3f0,0x000fd2028c970708,0x0006951017002380,0x00009d99f573ff71}}, {{0x0005b58a79b2ebda,0x00028acfec229986,0x000fb08398ff8388,0x0006debd733c9ea8,0x0000aafb0b851b1a}, {0x000791b3602750dd,0x000f1eb59cdb2015,0x0005a8c5e25286fd,0x000fcdbccb6aa395,0x0000b0031f1a9f9e}}, {{0x00036c2ab12c2213,0x00029a74288bef01,0x000813cfd8d67fb8,0x000edc144e8dbaa8,0x00001e994264cc9f}, {0x000d9b6095487f1f,0x000fbce801322d42,0x000d781e3f5b5610,0x000a5f163843cfa3,0x000018ad797760f0}}, {{0x000104980838bd3e,0x0001d4b775d53e56,0x00032e1224b44db2,0x000b72ba0d374dfa,0x00002d1e993def8e}, {0x0000a19b53d7c05c,0x0001f3fcbd21bd3d,0x00040bbe6188a3aa,0x000cde0596e5ba59,0x00001c6391029e21}}, {{0x0002b014fcbe1856,0x000b95e13a2b28d5,0x0006d0d4b135f7ef,0x00088914fd801d5a,0x000039be473b9886}, {0x0005da0db71ae0b1,0x00021d1359895df5,0x000fdaa6f9a87424,0x00086a4b6a38e436,0x00004b52ba6a46aa}}, {{0x00012f2761b2f3c5,0x000c6614fc53bbdb,0x00042cf5cddc872d,0x000f394469eb926a,0x00000be240fe2dd0}, {0x000ba88505bde5bc,0x000093955a18ec7e,0x000d0aa3265bd9f6,0x0008cf2aba473ef4,0x00005612ed21f6df}}, {{0x000c255f6facee1e,0x00050647746dc2e6,0x0003ba4f655a3120,0x0008bc9b08c0899c,0x0000ebed9359dd89}, {0x000b9c2f4be6d27a,0x0000379fa923f100,0x000ecd610db4fb74,0x000f5c0a7070baae,0x0000e5703880295d}}, {{0x0002792b86361989,0x000c70e0ea1d1795,0x000cee4b2945e4cc,0x000e49191f5928e0,0x00005a092513973c}, {0x0001517aa0eec014,0x00022752e7d55c3b,0x00099eab1d2d4b0f,0x000a05485931759e,0x0000052fe15cd96c}}, {{0x00079adbeed33d6a,0x000d9bb0b38172df,0x00014e338c2cf0c2,0x000c9072e49e377e,0x00006fbab6774105}, {0x0005c6b6657d9f8b,0x0007430c8a4f90d4,0x000273d11fc0a286,0x0004aa737c3f3d03,0x000085bc56c4d2aa}}, {{0x0002379568227447,0x000d5a076a384854,0x000c19f6f86ca3f6,0x0001602451c729ff,0x00008f792dda5ecc}, {0x000f7755d8802213,0x000bd503649e95d2,0x0004c555e4ab7e6c,0x00014024efaf7d22,0x00008f2776245832}}, {{0x0003c0c7fc837d12,0x0000c7efb2ca73af,0x000f96a119684707,0x00064f56fc1c5a8f,0x0000616d7204226b}, {0x0000d16d3a7388e9,0x00086882de5f323a,0x000e0dd9dbd81663,0x000c0961f0e26e4a,0x000063cf17e2495b}}, {{0x0008a4eeed230bed,0x0003d0d557870091,0x000ee3dfbcc65b1b,0x000d4ec313899e1b,0x000034cc4615e318}, {0x00033c138a95f8fe,0x000a9bbf13a3a311,0x0008ef1d5a245a64,0x000b9c9d0bbf5c1a,0x0000d9889cd87380}}, {{0x0006bf10834f02c6,0x0006e01e457cc3a7,0x000006873fbea818,0x00084c35cf9b69b4,0x0000f15793516087}, {0x000fb13cc05f8ada,0x000cdff5bcccc418,0x0007c49b2d54eb80,0x0008d54143bb4a8d,0x0000da62cdad2bc2}}, {{0x0003138c57e0d795,0x000edaf3c2b5f7c2,0x00093802977df609,0x000f578d94d77af8,0x000044741cd9805e}, {0x000fe570c9322596,0x000592415a9bc8ab,0x0005e9bd3fe94d08,0x000c8e55ad18e986,0x000069c5461d43cd}}, {{0x000d798d927c8bd1,0x000814dbe62b28e3,0x00071e6bacb5f66e,0x000791daf2930488,0x00002760f363ab82}, {0x000fb66661da3b86,0x000fc1f4f6b755e3,0x0003fd1f289bbecb,0x0009b11762446e5b,0x0000e4bbf14d6d68}}, {{0x0004365872cbe5af,0x00013550dcea306a,0x000e8ef29eb2b51f,0x0000e37d100ab735,0x00008b0e721f1781}, {0x0003dfa6b34d3b08,0x000b96fbd55f946d,0x0007e3d70db70874,0x000d6f1c8c13ccdd,0x000067a70e52d644}}, {{0x000ff9a5bce55c35,0x0000f532d926f394,0x0002cb267ae6b423,0x000cfe98bafbbea3,0x0000a47e9ec49a68}, {0x0001fac4aeef377b,0x00065088b8ca39aa,0x000fcb1b33346e68,0x0003f37c4595cf03,0x0000553a9a1f2973}}, {{0x000db5078afd98f1,0x0009a5b1d544b457,0x0003cc22ac17ad50,0x00013f9c1f670349,0x0000b99d9c60b42d}, {0x00070f5e725ed33e,0x000ff4e76c5e3634,0x0009bb5aa3712ced,0x00077c075d63270e,0x0000feb5464092f1}}, {{0x000266f5a6fae80b,0x000e77cf1d11cf5c,0x000c25058047f7d4,0x000d72477c80fbc1,0x00002ae841fc8624}, {0x000298af8ec94027,0x000f332b3001e607,0x00057ef418781d9a,0x0006e8f3cd58c10e,0x0000ae32ae0e9391}}, {{0x000e957ce0b54fb1,0x0006972fc16c8d59,0x0009e1ac6a5ec5c0,0x0003cc0e2a509f44,0x0000ae99269d43b5}, {0x000dcfe7f8edbf2d,0x000c4c38a98ab0de,0x000f2b7fe3eb2afb,0x000251d41c2c671f,0x0000eed98b1d120d}}, {{0x0007bb64c21224ff,0x000ff9321251834b,0x000b9cc1597d501f,0x000a592604354ccf,0x0000558105b4b952}, {0x000e794b05479262,0x00063092655e2220,0x000e9a375065befc,0x0002a52d2ca9bacf,0x000070e81eda0f95}}, {{0x000c09aee59dc5b6,0x0006cb27787722db,0x0005983dff716c05,0x000b4410ab2999dc,0x0000ae99f605e39d}, {0x000a294b8a218144,0x000f9bdcdec057d9,0x00013071db4aa486,0x000cb97a73b9e06e,0x0000df58e4a10434}}, {{0x00068854ccb5cd86,0x00099dfa38302192,0x000c6d69b04ec80a,0x00057f0b4854370f,0x0000695534ea04ee}, {0x000848f83b02064b,0x0002521616e17746,0x00016cdfc7d6dc14,0x000e2fc170a55382,0x0000c5b8c572de15}}, {{0x00031c02e59f130f,0x00069247772d5603,0x00074879039b6cd8,0x0005614566fae8b3,0x000048c68435d8dc}, {0x000c560826cc061b,0x000ed2785591eb7c,0x000662c22886c967,0x00001f926b7e0d13,0x0000a566862f57c4}}, {{0x000008cc2d2b80fc,0x000f5cb30fd3cfcf,0x0005075763e6f872,0x000b507b8d542c1a,0x000005ea27771e0b}, {0x000c23881dac761e,0x000cabc5e2d0bbca,0x0002d7913f2786aa,0x000fbe4390fd746f,0x00000c3ae903f765}}, {{0x000fbd330058a1d6,0x00002ef54fb2b3c9,0x0008118044f97ba9,0x000b32b660df7427,0x0000e5c26ccf676b}, {0x000d3b470f7e68e0,0x000e721fa57e439d,0x0001dcdffd33db06,0x000ac717c7489a8f,0x00007ed817eec38a}}, {{0x0002b4c45f41a24e,0x00055384c01b0f07,0x00027702295b3c4e,0x00021305b5164d72,0x0000213182bcadfc}, {0x000702c3c59da1dc,0x0000a16ef0a14df7,0x000d1c39e1032dcc,0x000e831d50a0d7c0,0x0000644edd83072a}}, {{0x000e10ecfc435d32,0x000d54284c66de7f,0x000050600e3840da,0x000645f7f5805c2f,0x0000742262a04570}, {0x000079ecb500097e,0x000b82599044767d,0x00048fcfba3571b0,0x0002688ed95a5d75,0x000064270f1e0c8c}}, {{0x000a352dc9346c12,0x00023d6f6fd90c8d,0x000b10eb8580e708,0x0001c595b7b0f310,0x00007adb908efd25}, {0x000fbfa7696a0663,0x000ea1f8a2cafde0,0x000feb5f1555b2d3,0x000b2d6e3ef80a48,0x0000afa35e99343f}}, {{0x00009298d4b6dbfb,0x000061e47941a985,0x0001fd13f88f9bba,0x000f2b1b2d1d0d09,0x0000fb0457f5ddd7}, {0x00012be21119e4a3,0x0008bebb0f558503,0x0002cd850fffa065,0x00088482acdbcb76,0x000045182c46b168}}, {{0x000a84723ad876d1,0x0000f44279fae932,0x0000d0bc65997267,0x00005d8a11945700,0x0000641726724e50}, {0x000b9a05034241c4,0x0003db865000b9ef,0x0003bf2b3fd17345,0x000b98f1f94024dc,0x000095ee6f7d1d97}}, {{0x00026356f22e6e7c,0x00024c3361929d42,0x000551b739519480,0x0006ba8fcc02a12b,0x0000c866d3c65741}, {0x00082ef71dd1d595,0x00088888e5b5dac9,0x0002351988936e99,0x000912104b788baa,0x00005b38d17ef74e}}, {{0x00078e44dd47b196,0x0006e3a7433dd3ac,0x0000e11737fb1f59,0x0000f52fec79569a,0x0000143a6b04cb9e}, {0x0005dfaa4b44dc9f,0x0002f6a3f86504ff,0x000e7730114be502,0x0005c09e9f83c1f6,0x0000a40c0dddb1a6}}, {{0x000ad7a5d9a7c749,0x000bd0b3e979591a,0x000b18984b0c8837,0x000c930f85a5824b,0x0000523198d420b4}, {0x0008c2966f8c5ecd,0x000c7529d2eed63b,0x0007a1cec89e0293,0x000ce2ee43e4b31b,0x00002b2eb6888152}}, {{0x0004dd204d849aaa,0x000d7aac3dc6fc74,0x0005bdf821345352,0x000d21fafcb0f7ae,0x0000c9bb14c6adc8}, {0x0007dbb7c46a380c,0x0002f91f52fe0303,0x000095c182afa9ec,0x00053300cfb28879,0x0000759b435956ca}}, {{0x000ec5f3969f68e0,0x000700e5f0e3ef78,0x000faae20f28d8af,0x0009c666fe212050,0x000038ae7b9b88f0}, {0x000157ba6e527edb,0x0008a283e2353b72,0x00056665a3b00c20,0x000fb0165eb77eee,0x00007f6601175858}}, {{0x0001cfbcf87353f5,0x0001b45b7fba97e9,0x000c88529186f293,0x00017cb9b7e1b550,0x00008d032cbbc13e}, {0x0008803b380a2bc6,0x000ce0e1eebebc7f,0x0000b3070c817171,0x000219f2106f56d1,0x000043c2b31388af}}, {{0x000e260a60f350a6,0x0006b02cac1de1ec,0x00028ab680baa38e,0x00084fa849c9cc42,0x00001ef5b54b9710}, {0x000d93de4657ad0f,0x0005315d84295f24,0x000d5350e7f70518,0x000b1b81c02b900a,0x000086bacb6bfb11}}, {{0x000b24f6599254b3,0x0002db150c28450e,0x0002523f2e8c805a,0x00016e26bd712d3a,0x0000cb4ef15dd141}, {0x000099a2e6f10b03,0x00002209f4af5024,0x0009230a1a79e9f8,0x00021b395212446f,0x0000a9513044d617}}, {{0x000a8350780042bb,0x000fb7e23271391c,0x000a21d82290ac12,0x000018afb2dc3763,0x0000debc97de697c}, {0x0004834481d067c4,0x000bdc1916ceca62,0x00074c52ab470d9c,0x00057cbf28f87f59,0x0000397d4d3c4093}}, {{0x000666ce7e64dcc5,0x000bfd2765fa9474,0x0009f08475f3c2aa,0x0004f9d5e1f47951,0x0000ac986961d2f1}, {0x000df6492b43447a,0x0007e6aa220eae5f,0x000687d74899951c,0x000190b730db55ed,0x0000fbcbbde88500}}, {{0x000a91cf73f6d56d,0x000dd4ac318013b0,0x0002e920d4b81d0e,0x000af89bc5c79628,0x000009d7f0a3bdb6}, {0x000654d7b2096ba9,0x0001bac0128551c6,0x00000c2c28355efe,0x000725460cf1f377,0x000031708465e5f7}}, {{0x0004c76c4fe9380a,0x000c3951a5ba03ba,0x0009390e3a0d1f19,0x000afc40881217e1,0x00004df0a88e83a7}, {0x000384ea5baa9628,0x000bb158f86192b3,0x0008e81ff877e966,0x000d6c002eb4c264,0x00006978687377e4}}, {{0x0001f239971de4e9,0x00066b14c2bc0eae,0x000eec2d481fcc62,0x000e4ad4346cda42,0x0000812e9df26d7a}, {0x0005f2aa6c2765b2,0x000c0d4e6727b197,0x000cf9203e0c7cc3,0x0006a71e0008e593,0x0000cc328562e6d8}}, {{0x00041b3f24c2e3f2,0x0000057bc18560ae,0x000dab87a402cc26,0x0004fc026500b9d8,0x000039eb743203ec}, {0x000cad3bc772a9a3,0x0003237fe16c560b,0x0001e4e176f45fb2,0x00086a0c35cb9a4d,0x0000b15ebf1dbd99}}, {{0x00084d9c6bca11af,0x000efba4998ed17e,0x00030f688bbf5028,0x0003d90bfa347c4a,0x00003511c41bb988}, {0x000e04455e4a4408,0x0008eb1d2233b9f9,0x0004641f70bb7f2a,0x000bdb4bed7797bb,0x0000525831ae528e}}, {{0x000feb573b5f15b2,0x000c92dc8b2b488e,0x0008915cb16e2b26,0x000bc6409f7cf294,0x0000643f5d55e347}, {0x0009c716263c840c,0x00099899481ae3bc,0x00030c337aa831fb,0x0008390b15f01b4c,0x0000ccb40e5e4096}}, {{0x00034dc70a22059a,0x00095bf4dd319094,0x000ae3a347a94846,0x00022943c512ea17,0x0000f04ad0dee788}, {0x00057b3916c3e773,0x0005eba57fff134d,0x00040dab29c7a71f,0x00005e7267cf24ed,0x0000d39e69d8fe29}}, }, { /* digit=20 [{1,2,3,..,}]*([2^140]*G) */ {{0x0008a58ed016cd2c,0x0009dc5bbdaedb58,0x0009d19885238728,0x000afe3665291aaf,0x0000f811206507f0}, {0x000a1acb3e875c10,0x000b5e9738520bc9,0x000b92c017b2fc48,0x000d82b6aee9ccf1,0x000062c002883ebe}}, {{0x0000bfc1cb150958,0x000d323c4b7d62aa,0x00022080f25a592e,0x0002c2d0f11983fc,0x0000ee53be304d89}, {0x00037069d21f2963,0x0003e06e21bb46bf,0x00016283512c9c3c,0x000a67545bb2988e,0x00005bfe9d31adad}}, {{0x000ffe7d4dc02b42,0x000fa98dc963d65b,0x000b49d8292da276,0x000c09ae3c49b3e9,0x0000d5431f45032f}, {0x0000664a7193cbb1,0x0005b74ae8346136,0x000506bf40d18877,0x0008baea2b86bf65,0x0000caf5ff39d91c}}, {{0x000a3c28239094f1,0x0002a7547af8d168,0x0006f05d9a001ef2,0x00048b8e617195d7,0x000046b964d7a1f4}, {0x00087515a695697f,0x000f6e306cc6952f,0x000023ac96fca948,0x0000113b6adf1cd3,0x0000162f07c0aff3}}, {{0x00048e3747fee076,0x0006b0d9898348ee,0x000bb6470ff98685,0x000533883290ae3e,0x00002a3d0c700bbf}, {0x0000cabf7bd10d8a,0x000bc597ff059eda,0x000be93bc3ae7d83,0x000241f3fb57e695,0x000038751d9c581b}}, {{0x0009f4d266fe37d0,0x0001760efc6d5220,0x0008adf5ade25d2e,0x000f03a0868e028b,0x00009d6b114bf7a8}, {0x000ea7aedf8eb0cf,0x0009fb1cec06b1ff,0x00062e007b93aad0,0x000ddc47d356e3a3,0x0000f4c08726f1f8}}, {{0x0002fe66ccc2faa5,0x000e00587d9fa66a,0x000e403eece74ae7,0x000a225f516ff2ba,0x0000d7e840f4377d}, {0x000c2e2512283ec5,0x000ed6d8436ba415,0x0002293851324017,0x00074b2665c85d3d,0x000061f518ef05c9}}, {{0x0001472c11f2e3f8,0x000f1235e29595f7,0x000cb9e5a4678386,0x0000d17bcc861c54,0x0000988eac405b68}, {0x00035f6f32a0837b,0x000a0526e17e28b0,0x0008d388e1404513,0x000f50161698c9fe,0x0000290d6d02d161}}, {{0x000e406349253af7,0x000d0541fb134eda,0x0003250ff90e5eba,0x000f014ee0bc4f4a,0x0000642c5dcc7c88}, {0x00087e04f81b7760,0x0007fe70876a68d8,0x0001713f35bc975d,0x0004f149dd30b653,0x000069332df09855}}, {{0x000ae7c2d9437a12,0x000c29850a20044f,0x00048fd99d2889e0,0x00019802a1d48fe5,0x0000f30505df8965}, {0x00029dc332e26e50,0x000aaad107e92aff,0x0008fd1562aaff01,0x0002079447e8e0e0,0x0000a12a48f5f9b6}}, {{0x000d35f7339a4cc6,0x0003ce58997c960a,0x00043b09663f8920,0x00086a9cabcc6fe5,0x000039df7b26f9bb}, {0x00004ebedc941e64,0x000a6c597d5e1f73,0x0005265ba7702fac,0x00039a977b7848e9,0x0000c0f2844cca29}}, {{0x000dbd0c20287ea4,0x0007f00fcae2255a,0x0006723143b1f47c,0x000fdba1ca3b9a4e,0x0000a61bac73eb36}, {0x000d0243021dac3d,0x000f566be9665cd8,0x0007af8bea21805e,0x000fc6df478b1ca3,0x0000ee9bcbadfe87}}, {{0x00079ee748becd5c,0x000fb2987ffe5418,0x0007a1ffc02d6eee,0x00056fea13c0fed1,0x0000c469e61b060f}, {0x000a5fdafddb3776,0x000368241f08c069,0x000473ca9d3dc589,0x000a42ebca40d7ce,0x0000bb3880b5b1fe}}, {{0x0003d7e9a039d299,0x000ba8ffe689e1ce,0x000a4b476b07cf06,0x0005849486dae5df,0x00008b49ee4dfe4c}, {0x00043c12bbee57f5,0x000913e24f4393b8,0x000ffe1e8a443ce5,0x000d0a6060aa2a71,0x0000c42edaeca67e}}, {{0x0009179cd2d899c7,0x00018a17e501d737,0x0001ed55b3c10df5,0x00048ca04cecde6c,0x00000472a0b8057c}, {0x000052a555cd31c5,0x0005e9616214105a,0x0003eccda90583ec,0x000ea0cb4bacb30c,0x00008fd7c1a7540e}}, {{0x000f42db00490cd2,0x0000c875327c51bf,0x0008e6a820cf37cd,0x000a81bb95829eb0,0x00001100b078ae33}, {0x00022e00511257b1,0x0005f34ada3e41b7,0x0003409ef3752978,0x0008b1f12815fe3e,0x00000e75bd15cb42}}, {{0x0006d6b5522c8d1e,0x00020c4a6e6885b0,0x0000674f8eb11a13,0x000d2924af2210e0,0x0000da23f4f5a620}, {0x000ca47360f31777,0x0003d3885edeca1f,0x00023929c46c52bd,0x000db6297cea00a9,0x000049714f519cd2}}, {{0x00015a866630391b,0x00035087f3dd975b,0x000f2793a140b12b,0x0006fe1693367845,0x00002d5263bccea2}, {0x0006ef773fa9b4cd,0x000b902c1b552332,0x0001ac526ad1de38,0x00006620625db61e,0x000003a7023f0df2}}, {{0x000651d3e64ea2e3,0x0006a54af43e7a32,0x0003ae4c9330df34,0x000236a6234eb5e1,0x0000759979693586}, {0x0008b45a9d54dd05,0x000e8978baa36a6c,0x0000ebaa91e3142f,0x00008dac63becce7,0x000003546ca0617c}}, {{0x00094d5565a427ca,0x0007ad634538fdc5,0x0000250b2a522b76,0x00055a43ef3e4b9f,0x000011bf92e19348}, {0x00072023ecc683ce,0x000ea22ed8cf7efc,0x0003fc8983d51051,0x00075d723fc11811,0x0000633cf0cc488f}}, {{0x000ba977892ce284,0x000b4cf71171d65a,0x000030c443d4463c,0x000202ca09b1099f,0x000056bf294a1a66}, {0x000a54aeda67248d,0x000d88b53799a85a,0x000ecc75a25eefd9,0x000ddc8babc0388b,0x0000a2fbe4a79e00}}, {{0x00095a2a1a8636b1,0x000233d7f690fd6d,0x0009ce730bdac772,0x0003be8fed0f34c3,0x000049bee0dc1db5}, {0x00000cdcd095ded2,0x000d8b21e3539d6f,0x000e3d0a33e83d8f,0x00022450c4084ba9,0x00008d82e03dfafd}}, {{0x00051869548ddcc5,0x00070778339d1ea2,0x00035f5f50d6f915,0x000e57fa01f58a4d,0x0000841779dd56a5}, {0x000f9ee31d9a47c9,0x000d12d602675ece,0x0009553f46c32b16,0x000eacdcd3c358d4,0x00001f6870b61f3f}}, {{0x000628f163be6450,0x0005cd9c95d766bb,0x000f6a04ec28e610,0x000c81dc5fc2b063,0x0000b71137ccd020}, {0x00075183bdc05d4a,0x00016d6bde53c0ba,0x0004d7c49a68f235,0x0008d99b6b877a74,0x0000336e49572d6b}}, {{0x0007024b4657059e,0x00054cef3d11f446,0x0003050457ac1b21,0x0002913d9da01ad5,0x0000b9bcb5753d0c}, {0x0007f76845c2dce5,0x00038068a539d060,0x00087fda517cafe7,0x0006476a3fa020c8,0x00005d290857bd93}}, {{0x000092acd18e938c,0x0000f8464b918049,0x0004df7e752475a5,0x0002fde898e40329,0x0000287032729a40}, {0x000569905ec6b4ba,0x0002cfe346da592c,0x0007a24d3ae26557,0x0001e988692d9424,0x0000d3469d8df997}}, {{0x000c0c46de1a94d9,0x0001e6f60e7509ba,0x0001814113ff2984,0x00011dee43d289c6,0x000082b07bdc2bd3}, {0x000f143c2c8cc0b0,0x00062d458fcb4868,0x000b290b3fd69d9a,0x000c0ecd23f4d8da,0x00000b05a52925f0}}, {{0x000d9a283c536a93,0x000606d6de13d945,0x0003f7737b671559,0x0009ba66c6cc19e4,0x00003fc1b1d79963}, {0x000562a67776f95b,0x000cad8332c80b59,0x000985a2553fa97e,0x0007a0d727ab42a4,0x0000e8b82ed15b64}}, {{0x00038e15452a1658,0x0008ec07d0a74207,0x0007878830171954,0x00059bac99ed3f63,0x00009f0f97c7517f}, {0x0001965ce020f57a,0x000438613db8102d,0x000c51ab225ad31a,0x0005e2bff0e582c6,0x00005ddc35e3ae14}}, {{0x000fd23340796b5e,0x000244ac37f7a6da,0x000dbe23ff187911,0x0002ebb7c0ba278b,0x0000966a8a7ef6ac}, {0x0000656ed69c1c7b,0x000dd0d9607f7b6d,0x000ad9bd90340e14,0x000f7e0e40027a74,0x00000579cf7ce74c}}, {{0x000a4a6a443029db,0x000d35ade4c87e84,0x00062de4100e89ee,0x00097010cdaa8575,0x0000847c3b75ba72}, {0x0001ce999ab945cf,0x00008688e09a9735,0x000d23c79201d508,0x0006dc217c5b0e19,0x000019d1d199e64f}}, {{0x0002e32a7846845b,0x0008812fb2a589f1,0x000e90b88698136a,0x000814075eeda86f,0x0000f51b3d5754fb}, {0x00051260155595b0,0x0001d15da3c67d16,0x000140e2d64ddbfd,0x000dc7d8b5f5f20c,0x0000f851ed143a53}}, {{0x000a956daaf5fc5b,0x000e309911eb23d1,0x000ec8c6b1504ee5,0x000ae12b96b7e04c,0x0000b90457102eb7}, {0x000f92df9e505e56,0x000f4a99a48ae2ee,0x0009af17826cba30,0x000679b8bbbc3531,0x0000173fb3989c78}}, {{0x0008c28d0d5a2453,0x0001b72c3ae14d66,0x000253ce4f0708c7,0x00051484000a3ec7,0x00009309c4f55650}, {0x0002432cca3eca7f,0x000ca9872fce7dcd,0x0004a7f072317326,0x000e46d7d6868a46,0x00002b388e557070}}, {{0x0000a1cb9e317b0e,0x0007686d711ded9e,0x000795851809a425,0x0008f153b3f1818e,0x0000d86c68fea802}, {0x0006abf4b7386739,0x00066a8acbc7e643,0x000a1ca448e39d09,0x000f6b81ecba6cba,0x0000b3922a40e4a8}}, {{0x0002eda200d56537,0x000c11407fd1b8c8,0x00026245193f49e0,0x000b4f9680d4a834,0x000087c24bcc7dc9}, {0x0007394081d392c6,0x0004a065b74266bd,0x000b68e1b771b55c,0x000ad0c13127dd7b,0x00004fda7e5cd833}}, {{0x0001b8779c1d0b47,0x0005ec5490f634d9,0x0001f8d01b7ced9f,0x000168ad06fe10a1,0x0000d38933d35353}, {0x00083efd496b859f,0x000068aafd56bb9b,0x0000ab4c451c3d2d,0x0001760199f69b45,0x00004f69ed69d503}}, {{0x000d12f2dc71d6ed,0x00042873d131f911,0x0002f868f327b8c0,0x000917defbabf904,0x0000be4cf0dfeea9}, {0x0003a085c409e88a,0x0009aeb4bfae3400,0x00086f86c0eb81fc,0x000f9a5b91f6c11f,0x0000e0a0c02204ca}}, {{0x0002d3ae9ccb3990,0x000a386ea321f4cd,0x000d286fce5d33ba,0x000d3cebb04af8c4,0x0000fed10ee266ab}, {0x000e7bc2e8e31050,0x00057520aee8c544,0x000ce0a339acd068,0x00016a6f230a6ff1,0x000075e1ddd84516}}, {{0x000487cfa067d791,0x000998485f2e74ba,0x00090c71ee89da30,0x00025626b84584f9,0x00009454c2a51886}, {0x0004c5dd0d1b619d,0x000adc58a1b4f365,0x0006270fe416156b,0x00048f3ee0862486,0x00004e631cb6096a}}, {{0x000d441dc42369c4,0x000382251bd526ee,0x000e37dea0d84bc8,0x000584bd68a92370,0x00002e0d68345dda}, {0x0007c227fd8dee47,0x00048d0a275abded,0x000c3b0af42e5ba5,0x000cc19c02809fe4,0x0000921ff2645404}}, {{0x000de9f9684495a6,0x0009aeb8877a37c7,0x000d90721210b3aa,0x000e4725d8d1ea9f,0x0000a2fa64d2282a}, {0x000cf23abf5b2492,0x000693d5625863c4,0x000f2269b836d47c,0x0009574447f14d0f,0x00008a199e166c12}}, {{0x000f1b41c43f8b0a,0x000c5c92e76aa8ef,0x00075e03be67ce10,0x000c96b9463a7ff1,0x0000c9d06afed35c}, {0x000b46fd3cde2980,0x000abe85c9d9c413,0x00090aace2da8075,0x000e0512bec57f1b,0x000053813aed6f3c}}, {{0x0002d5a447d4f496,0x000f4cc8b20d45ec,0x000418aa14176c8a,0x00046f0dbfab3afe,0x00007f1b0c286c98}, {0x000399890aae6ec0,0x000cfc7435ee3b17,0x0004406fd3b6b369,0x00040be2ba195cf0,0x0000499740616294}}, {{0x0000732badc26dd7,0x00095818d5141997,0x000bb5614607b7d7,0x0006880fb44d9c8a,0x00002af102cfc840}, {0x000ac0001b8ab28c,0x00095c267369f525,0x0005973685ec0685,0x000bfbaa025f9a67,0x00003dc0b77f0b1d}}, {{0x000e6447298e5722,0x0009fd0c41f0b8d2,0x00063b53dd21c481,0x000fbb57d4fc248c,0x00007b8a669230e5}, {0x000412928c65556d,0x000525fd21fda1cb,0x0009148934fd899b,0x000cb3873e258005,0x000018bdfa0f4f09}}, {{0x000257a9696db0da,0x000c6e1ebe6be7ab,0x0000ca7d82e3d900,0x00097095c69765ff,0x0000d64c3bbe074c}, {0x0004df32910ad555,0x000467cc458a6d2a,0x0000c4ac0377e6db,0x000f1093e2b3b04b,0x0000049f7467348f}}, {{0x000169e23b854731,0x000c33e4abe5efac,0x000fd974f020f438,0x000a0585fe459ecf,0x0000dc81273d088c}, {0x0008b457450c4b5f,0x000085537b7106ee,0x0004064b559c8970,0x0008ed1e0bbc258c,0x0000c9e438969c32}}, {{0x00002b120b62bc55,0x0000bc38a5440b51,0x000dd5bf16b581d6,0x00073e09f25725b0,0x0000e14d4eb778a2}, {0x00040298b8f7908c,0x000f4748986c1100,0x00095285cc66b0b9,0x000f606450bf5cf8,0x00008763246fb0b2}}, {{0x000225d3ce00fd73,0x000562eb7a0a5fde,0x000b4dfc8355830b,0x0001747a548d6584,0x00007847c613610e}, {0x0003b60593ab7bd1,0x0006627b0acd38b0,0x000dddee8f6a141d,0x0008febdfc7a5ff4,0x00005caefa8d4b00}}, {{0x00062bce0697db84,0x000364744ceaf19b,0x00056d73ed4ae9f0,0x0002e794e38b0f08,0x00001b958bddc911}, {0x000e012417427134,0x000459f114d48028,0x0006a3400cfc75c0,0x00058727f66fc710,0x0000756a6e62a482}}, {{0x000219fe0b28a503,0x0006d50aecc17ee2,0x000b2435a97443af,0x00001d69d66a83c3,0x00000f96b615a755}, {0x00081a62fb7e0fb7,0x000a7c62b16f41b8,0x0005def12d53a09a,0x0001ef4471c81af9,0x00008288a92a8022}}, {{0x000c8e03ffcc6378,0x00014bd82b7e98ab,0x000d883a9ce80865,0x000c6a7adb20e161,0x00008a1096cab53b}, {0x000e056288dce6c5,0x000cd762fbd62fcf,0x00047ac13d2142e1,0x000347c471a47759,0x00003efed5dffd1a}}, {{0x00071f160d9b4fc7,0x00068ccde2a4414d,0x00076c3b61dd617f,0x000e354a6e4e01a4,0x0000394adf687f7f}, {0x000ace232376e7ce,0x0002f140cec9de0d,0x00033c69dda8f7d0,0x00032704299d10d8,0x00007b0ca9ef9df4}}, {{0x0006175bbdd36444,0x000a4a9f510cbe77,0x000b49c3438fe5f8,0x000aa894881ab300,0x000081360b1cd545}, {0x0007e5993bcd0e48,0x0006045c198c176b,0x000dafcbc3541e85,0x00011a7fe785de3f,0x00001e918704e8ed}}, {{0x0001b16510a4e3db,0x000cec6d1df534ba,0x0003cf6dff71bd1e,0x00007410def81561,0x0000e0dc1013565e}, {0x000f21a48f9585d6,0x000c6f1ecde37262,0x0000bf75a4803ebc,0x000ff11f11cb9818,0x000073d6d772e7c1}}, {{0x00059115abc00ba2,0x000cb26283346405,0x0008740e0a87969c,0x000d13385833ae70,0x00005dac93f5d8ac}, {0x000474e1140c01a2,0x0006c16df16ac717,0x000f357675f37a81,0x000ca0828679abbc,0x0000ea1c1b3e843a}}, {{0x000e6660da9a2e5c,0x0000a16aaba8f9a2,0x0000b0f1059a100e,0x0009bff504cde526,0x0000976e00939024}, {0x00047a5c49758124,0x00088fcebc829f02,0x0001304805038f43,0x0006e00b76e9a157,0x0000a4de4f473e09}}, {{0x00004366e61d6724,0x0008876389533579,0x000a479bbe7f7414,0x0009e747e452682b,0x0000eaa1b7c1fe86}, {0x000039271078dc74,0x000ee3d381ab86d8,0x0006994cd10f6bc7,0x0008a6b5d9fbe311,0x0000aea87c1a2a42}}, {{0x000ab7ba68c31022,0x0004f457d6aca783,0x000dbd1c13359695,0x0006f46d44d935d3,0x0000ddba6dd9dbfc}, {0x0009cd2d080265cd,0x000149797b3be503,0x0002299249e3b52b,0x0007bc0e30ffc768,0x0000209779d3d5e1}}, {{0x000f9ce2a49386cb,0x00068985f70cff66,0x000479f3b00cc1ad,0x000fbdbdf292f316,0x0000fe7032ecf9f6}, {0x00019d7e849d0bd1,0x000249cfa039b34e,0x00027fcb6b7edb80,0x0008ff327d2e6371,0x0000d2b6d3758911}}, {{0x000242405e3c60ec,0x000e43c80b9566b8,0x00010ea9d9b080a3,0x000e2687f432ff7b,0x0000ed8dcda9fac5}, {0x0009b28d87f8b2a0,0x00043ca1256e54e6,0x000a8cd15700f2af,0x00073f0b2cecd0fa,0x0000ed3ff9133f72}}, {{0x0004550dc5a3b02e,0x000f5412342343c5,0x0006db191c975ce2,0x000a20f3bd209a9c,0x0000ef49682be20f}, {0x0006351ac6c47b86,0x000ab813a62241b8,0x00015ecebd6574ce,0x000f1186751398fa,0x000028d91f9cbecd}}, {{0x000f6978b74df5f8,0x0001129ebc5501ab,0x000b5901ba0c64cb,0x000d8e622dcdc072,0x0000ebedc46638d2}, {0x000a78bab0638bbc,0x000e9c428abdd0a9,0x0008a8ed5636732d,0x000dc7c12d1f0e06,0x0000c1be2ebfb1cb}}, }, { /* digit=21 [{1,2,3,..,}]*([2^147]*G) */ {{0x00041c6aa03286f9,0x0003770815b0f7b0,0x000348c284d38d56,0x000cd5c0fbd016dd,0x0000353258e98148}, {0x0002a661efd9b9ba,0x0008dd5eaf283913,0x000595edc99487af,0x00040c2b55829810,0x00008f3adaa1cb10}}, {{0x000dd15cc4abcc6d,0x0007acc11a85a0ea,0x000e38c7cfb75800,0x0004e9a4844f7d00,0x00002e87f21868ef}, {0x0006dbfdafb2737d,0x0007c78ecbcb6bf4,0x000c3294b6571d8c,0x000d2861c088a49b,0x0000659cbbd569a8}}, {{0x0009b01652619368,0x00097cc76f780883,0x000ad592edff2cc9,0x000558427112d204,0x000052f6c13013db}, {0x000b41e1bc721e44,0x00022128ce489bbe,0x000c29c730081266,0x0009efd2b1381a99,0x00009dda36961899}}, {{0x000a8efe8dfc0aac,0x0009cb206c5feff9,0x000e08f69e7003e0,0x00088bdcea678c07,0x000046cbfbe7e7fd}, {0x00081f0181edacd6,0x0007c93bfad4cf46,0x000166e29a349916,0x0004fc2da8f82140,0x00007573537b65ff}}, {{0x000bebd8693c0ce2,0x00010dc55e193bc7,0x0000e0dde6b99ca8,0x000d3d417badbf94,0x00003a2ff7257f49}, {0x00060a0c7bbfddb5,0x00081c1118dfd409,0x000b93b5a839109c,0x000a3b4702087141,0x0000534d9835ff20}}, {{0x0004d062b05c59a2,0x000f5879c926f51c,0x000c6face7f545ea,0x000d0985a415dd36,0x000001497b737669}, {0x0007660300e35aab,0x00062195020d6f9d,0x000f8f2766a25988,0x00016e4edb995fe9,0x0000e827d9aa3b54}}, {{0x000d3fcce93a152b,0x00024b91cc4b50f5,0x000d575f2dc97aea,0x00082a9bea228491,0x00000b0f559c3e87}, {0x00059372ba709ae1,0x0003193c52d9a904,0x00023ee401efcc7e,0x000302d47c1d80aa,0x00002c8592c8fc92}}, {{0x0009708665ae5753,0x0005c56a03be8192,0x000d0ebf2fcec8fd,0x000acbb56af2db74,0x000082e5523113ae}, {0x0003f42e6dc35a1d,0x000e073f338c297b,0x00031eda91747ee5,0x000685f205a68c1a,0x00005a4916714ce7}}, {{0x0008f1dbcd1c229e,0x00061773f6f1844d,0x000b29bcde833251,0x0009f684f808b930,0x0000a5e1fcfc8609}, {0x0009762c3a5334b6,0x000547b852bd1766,0x0001805b9b973ca7,0x00035282b13c8977,0x00005ad0b2362ab1}}, {{0x0005af1b45cdc26c,0x0000c675c4635dcc,0x000b44dcd5bf1c0a,0x00064f5a3a7131e4,0x00004f42e03a4878}, {0x0009d8e6279a73f4,0x00083cfb4946f6e0,0x000537fe046fcce8,0x000d988539949b2f,0x0000ac6abd6d779b}}, {{0x0005d5a30f177232,0x000e2df357dbfc95,0x00019bdcb3d911f3,0x00080abc003ca457,0x00000224695fee54}, {0x00070ac4186c55f7,0x000970319fe286f7,0x000f87d49b139392,0x00060915c89b2e48,0x000098096c2f2b08}}, {{0x0006538c7cd583fa,0x0007504a26b85672,0x000751b6cd45e59d,0x0007acf63fefec94,0x00006952679a5609}, {0x0005299959d65ea3,0x000bf04521f25d19,0x000bd9b1bd07cbc0,0x00070fc519431095,0x00000659b6ab7a79}}, {{0x0007da91e66c9574,0x000db441e739dd4f,0x000fb78e063f2620,0x0009ce36edde855e,0x000048530862d43d}, {0x000d326b7f93428b,0x00051bd23ff3de67,0x0002465efd4d3577,0x000e73c428efd466,0x000015e8b1961a78}}, {{0x0002b67847e6ed6e,0x000e4c4145b4f3a8,0x000f47bea8e5ec4b,0x000709c101bbbe13,0x00009d64c85e6167}, {0x000258b265c6bb03,0x00052603cb62b641,0x000250984d93deb8,0x000184b5dac1f036,0x0000af93396d0909}}, {{0x000454335c724255,0x0003604c60816548,0x0001f152c66dc7e0,0x0009f43ccde48316,0x000077cb80034588}, {0x0001b1a2abd9c810,0x00068976064aced9,0x00035e3f6e20d90a,0x000233aa7895ed69,0x00000b721fe71914}}, {{0x000d5d2047e6bce3,0x000c5f2809e64a06,0x0004d29f57d77556,0x0005ec248cb3669c,0x00008e7d6893f712}, {0x000931b877a115c3,0x000d470ee473cb67,0x000837d7a680ceaa,0x0004ffd6fb968f2c,0x00003fd042aa3584}}, {{0x00064b623466f8c0,0x0008b9ac46b1538c,0x000eba98de2d82a3,0x000aec359395681d,0x0000ec5727adf754}, {0x0001f29793223a53,0x0004f341230b56ae,0x000acb4a49d60698,0x000a48020fcf8ecc,0x00007f03e722fa1c}}, {{0x000ffae3070a4cd2,0x0006c399579ec252,0x0009c2399abb8b5b,0x00058f54502d33d1,0x0000d2a871f20c1f}, {0x0005a7fcf9b1e2ad,0x00026c80ecd64f25,0x00094c286464daa8,0x0007fc8c2edbd839,0x000055ea342cc28d}}, {{0x000e3f38fa4d2ebb,0x000a628413f152d1,0x00063d684664336d,0x00099a6d07b3bf0e,0x00002d0a21e1fc6a}, {0x000404c2235d7455,0x0000aeab84670292,0x000ec318fdc3d200,0x0005e4ed594202e0,0x0000b11acb9c1288}}, {{0x00046804810695a3,0x000de9ba648df863,0x00051c17067ea77a,0x00015a8eb8039779,0x0000789adb2007f6}, {0x00094251845852f8,0x000597dd3f5a4cf4,0x000e0ca98f3213e5,0x000cdfe4111dea4b,0x000092e80e45f558}}, {{0x000a77ccd1cefee3,0x000ada8387b76cec,0x000d53bdf4c487a2,0x0008553f0ee08fb0,0x0000ecf034e8072f}, {0x000d2cf4f5b884c3,0x000eecc4f5c4d598,0x000c4b8e274becd4,0x000fe18c1cf74be6,0x000033bf7648e6a5}}, {{0x0003309c7f4956c1,0x0004bbd8072c2e72,0x0007386ff557979f,0x000400bd4c7d2735,0x0000d3097df1694f}, {0x0005419b24eddf2b,0x000fdec834dd8149,0x00008eb07ebf4b08,0x000944251b925cec,0x0000cf5bd49c0873}}, {{0x000cc2b7fb7521cb,0x000cfca0448c3e29,0x0000c79198983000,0x000fa291122a2253,0x0000d819e4970366}, {0x000f14ca4bc473dc,0x0009d3f09a14b90a,0x0007cbc4041d07a8,0x000c0822fd840600,0x0000cc4468dc6484}}, {{0x0008e2d3ac836bc5,0x000fa9f064bbcc21,0x00031a1b07517bc7,0x000b9cf6d996bf89,0x00007baa282710c0}, {0x00003689803b8618,0x000b9bc669415358,0x000927d51b0e7c4e,0x000917e22409c259,0x0000bd3b557da0b6}}, {{0x000c21b01b14908b,0x000de4a8a31f4d7d,0x0009e8787bcbe4d4,0x0009e9ec73c5ca1a,0x000065165667e1be}, {0x0005566f103c7aad,0x00068820ea33101b,0x000afa05ad1acf04,0x000445b6f0613b7c,0x00003aa0c574081c}}, {{0x00087a329c8ed384,0x00092d62bcbb14af,0x0004e3df6cf9f17d,0x0004809f2aca4e9d,0x0000ccfeca144a51}, {0x00041c1043c54414,0x000eaa7c807bc51f,0x000cfbed8d9c0b13,0x000f8173166f05f5,0x0000edbf62fa73e0}}, {{0x000fa8831a8af89d,0x0007f4021d8aff5c,0x000dbeefd7a8d79a,0x0003ee6c7dc72f5b,0x00004336006bff0b}, {0x000e58807631b0f9,0x0003b6ca73f467c0,0x0002ef220dd8f222,0x0008681b33098d75,0x0000a8d5cb00940a}}, {{0x0003a4465384338c,0x0002212dac4e37c8,0x0001527f99ca46a7,0x0007381b651de843,0x0000c4920dfc4a73}, {0x000defe279009365,0x00039c537acb711e,0x000d3684b5f0845f,0x000b186a2879fe49,0x000022890953f9ea}}, {{0x0001888a21d8062f,0x000e6963bb268fdc,0x000fec2167faac6c,0x0000b12e8fefd495,0x0000fde1d1fbfc68}, {0x0008c3a8ac6e9251,0x000f165cd203fb4c,0x000da224da3bcfee,0x0009c76f7dcac95f,0x0000d2bc8ba06270}}, {{0x00089f169709f64c,0x000ac1b2dac6c136,0x000f04db98b2b71f,0x0003d6ff19b52803,0x0000984ae8728ccb}, {0x000b07419ce76448,0x0006d40a72dd7560,0x000ce49974f769d2,0x000dc4f4b5d8a990,0x0000484a9d5d3a20}}, {{0x000d0288e3a46587,0x000ff69f35c7af94,0x000ef3387d56412e,0x00038a84fec04a52,0x0000600f11d74aa5}, {0x000b58c2b1ee7fb6,0x0002d3e464c1a9a6,0x000491727fa92dac,0x000d338d06f7e0e9,0x0000c00602b9dd0d}}, {{0x00025ec2a0a97736,0x000894c54fcb0993,0x000c79b1272a0fd3,0x0001dcc6d7533abd,0x000003f49dcc0749}, {0x0002691f11601ac4,0x0004f081e7ff4653,0x000af4c3b359a421,0x00031b5ba1c105b4,0x00008a6b864d6305}}, {{0x000fd57dfc2a81d6,0x000625b39bc719c1,0x000bd95af6db2f85,0x0003bed53048b27c,0x00005b3082cf3fe5}, {0x00075165c86fc86c,0x0002759020878e09,0x000c8d6462169c4e,0x000a7ec795ff10df,0x0000740ea7b723b5}}, {{0x000c734b07d5d331,0x000c0fc9ac292c4e,0x000275f2fa5774f9,0x0005b64cb6519644,0x00000932f708d9dd}, {0x00099e5189916537,0x000dab579fa96e9e,0x0003d581a498ab6c,0x0008466030186ad2,0x0000487b0b95ef84}}, {{0x00035b4387096d4f,0x0003df6e71b2ea65,0x000937553df75f29,0x00010b31d49965f7,0x00006c0c5a717d4f}, {0x0008a025671103ec,0x000e123bb180d8a5,0x000b43b65a239855,0x000f61fa25b52a09,0x0000f771fc550da3}}, {{0x0001111d075e5253,0x0004096fe18d6290,0x000c240dc07656fa,0x000abcb58d552e84,0x0000e3c9762d4f9e}, {0x0005b0b103502350,0x0009f566340da097,0x0004d4fa8636d51a,0x0005251761de667f,0x0000e20349d77617}}, {{0x000804e04fc602d9,0x000ef28a89d0ded4,0x00086f1cd8ffccc5,0x000cc149f28d2957,0x00001630741537d4}, {0x000f2ba70b640180,0x000b39ff8919aa63,0x000ddf64f6350c9c,0x000ed9819793e411,0x00009e24759c0d79}}, {{0x0000f19f4fd5dffc,0x0001ceff4bc9c7a1,0x0008f73cf0116b0c,0x00061f4e478201cb,0x0000d21b82382518}, {0x0000765f0c491b5b,0x000013baad4faf40,0x000300e32e5639f7,0x000d8d4ad69ae26b,0x000039328a470b33}}, {{0x000c84a820e49c2a,0x000632dbefb4207c,0x0003a58a5ed4c55f,0x000382bac82b1f88,0x0000b15eb7c77391}, {0x000f20e1f1265f7c,0x00061058e88c9ab7,0x0006384f1cf8b862,0x0003879fb6321663,0x0000cb9aeb634518}}, {{0x0008bbf43ae6df99,0x000e2d6ab4528524,0x0005334bce88a401,0x0008055ec2fa9a47,0x0000d4dca87805f4}, {0x0006ced09a787cb1,0x000d0999c03d5db5,0x000b45d8fbfd1741,0x000babb6f0173a87,0x0000a2096bb2323f}}, {{0x000a21bedb16d4bd,0x000e6b75d1d16e09,0x0006bc64045b4bcf,0x00039d063765236c,0x00000a23f6f637d9}, {0x00074751ceb98088,0x000dba263631ffca,0x0005c24d5fa3b792,0x000afdf1a7fd6b25,0x000059077c5a10c5}}, {{0x000da27ddfed9085,0x000e4268009b9ec1,0x0004b5d55add639a,0x000c645ca7d97f79,0x0000f7c88b1f440c}, {0x000dd0e67085ac15,0x00091a87c0cc8497,0x000956ebd13e13f9,0x000f43f208267e50,0x0000950c4ee3dc87}}, {{0x000767687730a906,0x00086fc6d094b775,0x000902ef6b5667e3,0x0004940ab659cccb,0x00002c5c7ca26500}, {0x0007b7f151927dcb,0x0003251daf1587c1,0x000e13028bcd4fe6,0x000bec56ed9812dc,0x00002b1a165bd153}}, {{0x000922b16d41f3ed,0x0003171dcd2ee6c0,0x000fb901db1d6685,0x0003a9ae9e9a3b18,0x0000fa1c572a62e6}, {0x000eddd1acbe3647,0x00057c3b62c81e6b,0x00095ef93b30ae10,0x0007c242fa98c96d,0x00004313bd27d329}}, {{0x000590d655a44d1d,0x0007a791be183844,0x0003d3938484d868,0x000d526b8e7d0675,0x000025aa4d1a7d94}, {0x0002fc193234941e,0x000c53450cb67e66,0x000dd6fd063acd11,0x000fb3683bb3f0a6,0x0000017b88e1cd67}}, {{0x000dfe137bc4a4d3,0x000a6f70d1220567,0x0005d43015bd4b27,0x000073c03a5810f2,0x000038319b9cc364}, {0x000e596aa8cf3d1b,0x000eff7eb1c9ff82,0x000b8e2dfd434646,0x000515518b703e5d,0x00000fd92c1335d7}}, {{0x000f2ed01b9068a2,0x00003e0f5e11999b,0x00081ad391d14a72,0x0000ec9e891cb005,0x000034d551dfbd27}, {0x000e3e94269c7442,0x0002bdf2d623f98c,0x0000ac69fcba079f,0x0006b8e6df04439d,0x000094022be24a1e}}, {{0x000624f1ce0f1e4d,0x00066318ff1e2b3e,0x000cf68fd9152d17,0x00026fa5d91b3a87,0x0000450cb4e504c4}, {0x0006852e3c9f1ef5,0x000539195d3f5568,0x000858b621b8887c,0x0002f2742dea5594,0x00008e75022bf2f9}}, {{0x000b07bf5bdb8d74,0x0005adfca4449042,0x0002e1d1ead50f78,0x000484f785f4721a,0x000049993fef7c9f}, {0x000c8c0c7eeaa416,0x000b7f465774cab3,0x000a78325aa244d0,0x0000243470b1e003,0x0000822e9e020093}}, {{0x000c845fa39fbc60,0x0002293ec4ec1d40,0x0006379a019debff,0x000755eda9d51a99,0x00009f94dc7743ec}, {0x00010b3843c61a6b,0x0009f974867d68ea,0x0005dbef26fadbc5,0x0008f2b3e875258e,0x00006cb8dd761e1a}}, {{0x0000ad3ad5e6e384,0x000e291dd98cff89,0x000718231c43f57a,0x0006f21945dfe8c7,0x000061970b97a133}, {0x00082cfd677dce23,0x000f52f49f824e05,0x000b7784bdd02efb,0x000b85cc1c90ef12,0x000014d0c33b781f}}, {{0x00060c791130be5d,0x000a3b5dc85a2ad9,0x00089ae96957ee66,0x000500bf4143b0b4,0x0000de968fbf16d4}, {0x000480887ad52fa6,0x0000d040ca0e6706,0x0001fc876898a967,0x00096b92364ae69e,0x0000dedc76278467}}, {{0x0003de2fb18ca7df,0x000864975906c34c,0x0008c99c77a4177c,0x000744f9db29337a,0x0000758b714ec06b}, {0x0000287f5082885b,0x0009f9b49e575a58,0x0009f2005dcaeb2c,0x00057c4f90329a9b,0x0000e7c828178ce3}}, {{0x000070cd2e84852f,0x000127c1c04293d3,0x00082b797b024206,0x000ae76c1b1ad1a5,0x0000f75b079c03e1}, {0x000e4e6207b73a21,0x0008751ccacd3daf,0x000a230c168e33ef,0x0003bebb75b39a80,0x0000ce273b967045}}, {{0x000e4cf7ea2bf1e2,0x00002aee47c0de34,0x000ad4d02064992f,0x000d96aed6f23dc7,0x00000258e1fb9565}, {0x000d4dca99aff602,0x000578622da2f6bd,0x00013f2c376d4555,0x0004856bed645115,0x000023c2392fbfc8}}, {{0x000c65742561338a,0x0000f335e54959ea,0x000e714b02e99bd9,0x000531924d4cd35a,0x00001199bd5dd95a}, {0x0009f7a238d15ffe,0x000e09222be15441,0x000374b05d41934b,0x00061df1d9a1aed2,0x00005508ba021f85}}, {{0x000279df95030f56,0x0000f9ea1ab0d177,0x000f99992a351c3b,0x00064e9220c44b6d,0x00003455043e8fbd}, {0x0005de277b82a5bc,0x000ac3b68530cd38,0x000ca086694c0653,0x00063ce81e602ff2,0x0000ef40f405268b}}, {{0x000b7c3a8d2bbe19,0x0001bb32fc4ebdbc,0x000caf9eea029867,0x00095c27a58c50c3,0x0000c0ab3cd9d1bf}, {0x000e9607ac0e8a6e,0x000fc1426abde891,0x00074904b992b549,0x000b98a3dd1a72aa,0x00003c2e33afdede}}, {{0x0000a5f93a4e96de,0x000c85e5eafc25af,0x0005a62bdb7ac424,0x000558424b99e578,0x00003c24c7e4a4ea}, {0x00094a38275f9857,0x000c9c7fa4275e32,0x00081251fc7ef065,0x000800bc303dc5a0,0x00001f0537c463a9}}, {{0x0009bd0faab7ac3d,0x000e80f256cd6560,0x0001cdf6644f220a,0x000341d90e8fe916,0x00002d221d5ca965}, {0x00019a678ae67ba6,0x00030f33b841d032,0x000d5af5d16ce5f4,0x00070b06fcd2214d,0x00007fcb30a9c986}}, {{0x000c6d4993412281,0x000466c0976b7162,0x000e48195e68d8b7,0x000a7c3a400a9f5d,0x00003f11324f1feb}, {0x00068a9ee5214a73,0x000895b4a3f14392,0x00035066970be472,0x000438b2cae53e6e,0x00000e849079c7c8}}, {{0x000ab4705ac23184,0x0007e535509d183e,0x0001a9d696cd87c5,0x0003178c8f88a2f8,0x0000610bf6f3760b}, {0x000d814c4dca8a05,0x00010f8ceb1157a8,0x000537398b47d20c,0x000424fa8d6446e9,0x00001fe7a476cec4}}, {{0x00072bb2d03ec2ff,0x00025023cd075ac0,0x000d7ecf72f0f3d6,0x000efca8d8dd2d56,0x0000a3d270a63597}, {0x0005bdb8fa49c984,0x0003984320dca40c,0x0004211099e72bd4,0x0003af1f17bff561,0x000078129a3f3005}}, {{0x000cb54f682dd291,0x000a10b13967c1cd,0x0009cda2fbf3fcfc,0x00038cfb00e857a7,0x00003a87c6a0cf82}, {0x0002489b23f1d3cd,0x0009ca41c9084179,0x000f0d3e98ef9e8e,0x0007bab2cdc4e833,0x0000e159ac26b23d}}, }, { /* digit=22 [{1,2,3,..,}]*([2^154]*G) */ {{0x000b73dbe429e6f4,0x000c3138ffc05f82,0x000a3b67f590e285,0x0007bcb900484c1a,0x0000aec77b3d8941}, {0x000e442032e0e61f,0x00070b271f75c0ad,0x000b1798d01dbbbd,0x0007e3958d61f8ee,0x00007c8bd0d03ca0}}, {{0x000e6d0844c0e6f2,0x000c3284a1e580fb,0x000933260fbe850c,0x000f1d49fa978af8,0x0000f631a40a5bff}, {0x000151afce47898b,0x000d97771637ce9d,0x00029ce3be231f37,0x0001bb143714824a,0x00008614e5ed8aaf}}, {{0x000e80c351d61ae9,0x00034e58cbd057c7,0x000018bc8ecfdb95,0x000c2ca5a58c2283,0x00007d50125d76ea}, {0x000465a381106373,0x00041f1dd517dfc6,0x000184218d7ec5e4,0x000ea6cc1e142bb3,0x0000006ce0efce95}}, {{0x00003b993a36842c,0x0004ff423a275d4d,0x000ea1fe70c60a7c,0x0001025151148bb1,0x0000be81326d9e64}, {0x0008d837d64990b2,0x000d2db8c89e7194,0x000692e72baae2d5,0x000e8c0dd17618c3,0x00004b6ea9b40d6f}}, {{0x000fd692bf95567f,0x00053ebad159ba68,0x000340f3a53fec60,0x000ad6552431579d,0x0000df4e7d133f2e}, {0x000144d67c90b92c,0x000167158f063ae2,0x000abd10013a5c86,0x000729b8ee2bc967,0x0000b9abf1b96668}}, {{0x000f140c73562945,0x000cfe3add38ebf2,0x000df7dbc2a2e566,0x000476e0e3f9dbd8,0x0000ae24bb41e6fc}, {0x0002d58819c1c23f,0x000517b2f5b645b3,0x000e863c8b271901,0x00069def3f6a2be5,0x00008f784e4c8202}}, {{0x0005b1d21ec38f34,0x000d1346ef526b08,0x0001aaf39a530ac7,0x000336aa7792bc04,0x0000759ab5765fb1}, {0x000d665388e67c77,0x000e31ff335430b3,0x0002f4df0b037e8b,0x000bb1010d23084e,0x000085bacaea9944}}, {{0x000e2601dd188f66,0x0009e8c268296001,0x0001a9eeecbb5766,0x000b9f7ae1f2b5d0,0x00004069ef9b9ba6}, {0x000798a2fcf1d940,0x00063d59f8620844,0x0009af2a19d2299b,0x00026abee6e38778,0x00001f7192df4bae}}, {{0x00053eb08c850a38,0x000ec6ad45b295c2,0x000029b17c77b7ec,0x00066724f2c9dfb6,0x0000f4bbf5043f22}, {0x00027dfbadc1cfc0,0x000c9c9b43c55b3e,0x000f3904abe353eb,0x00010196a71e4ce1,0x0000960958fa8fb7}}, {{0x0002fce77ea0ed70,0x000f5ed5ec66f089,0x000f00db8587d743,0x000085766c95169c,0x00005b6bf27de7cc}, {0x0003e7f9cb37cbcf,0x000f9ff50ac46924,0x000c0bf82abe04a4,0x000e20c506429d30,0x0000cf6603411d09}}, {{0x00079d7ccf998928,0x00053aec1803601b,0x00023b4297648463,0x000aff355968bc95,0x0000d5d4c0854553}, {0x00057ac873f512b4,0x000cd320d16e1b4c,0x0004ed91186b08c1,0x0003e4608228cf7f,0x00004c70e3dd005d}}, {{0x00088f1944156ff7,0x00011e971438cb5e,0x000058fa1b18ee73,0x000cdcb89e85f304,0x00006e2f51891388}, {0x000232f34ba5cffe,0x00003843e83b0cce,0x00097c9aa7eaba9a,0x000ece9610dcd10b,0x00009f5f0d594daf}}, {{0x000986810095f72f,0x0001ac29a7c24844,0x00032e78ed086800,0x00098f626c35c5a8,0x0000d83403c23bba}, {0x000a7f5c20ac35fa,0x000d88d0bbc7266d,0x000e582bac8b42d0,0x000935657786ea28,0x0000bf7fdda51e43}}, {{0x000de66539c57709,0x00029ab48f57c79a,0x00053b7f7c92d81d,0x0008ccd6929d04ad,0x0000d6805ffa633a}, {0x000c653e3c30e224,0x000a25014af38c1a,0x0000fb9056ff7e72,0x00036e84863461cf,0x0000feff997e9cd2}}, {{0x0008f4fbfe1bb87e,0x000b234bf5009643,0x0003e08355419bfe,0x00059cb34567fe1c,0x00007cd632f8cfe3}, {0x000b06cf3a3127e3,0x0004a9a97e2d7d25,0x0007d0094b3c4c3d,0x000715572ac1af4e,0x000097c70eb31cd4}}, {{0x000a30dbbe55bebb,0x000acbe0f0b73fc0,0x000b583ca72ac528,0x00058a26c3397a15,0x0000690f6fc7ed03}, {0x000c62882b679996,0x000a4e77a75d9acb,0x00038d76d9db5245,0x000eece8f87c7f73,0x0000595862fdb1d5}}, {{0x0004badd8661917d,0x0005007f84c3acbd,0x00040fa3d59ba026,0x0002ed184e937c66,0x00001369d0f0a780}, {0x000fd94d28839e74,0x00021cd14e0c49ef,0x0007442dff19b151,0x0001044685338c05,0x0000b46081f8392f}}, {{0x00011d53d358e352,0x000ad7cfd455b082,0x000bac2fd8bbbf06,0x000acc8cd30a233d,0x0000d70c7b7f7357}, {0x00026832fec7aa71,0x0005d1d2ead1c40d,0x000b7a761f51ab79,0x000816ec07f749be,0x0000c5ae5e6830a9}}, {{0x00099bbb81316b37,0x000eee7327744649,0x00036c6dd3fa17e1,0x000cf40d417b7a4b,0x0000cdaf38243743}, {0x00092c6085af8552,0x000765fbc2a4eb0a,0x000a3aabcb9c1f75,0x000715c991d08c04,0x000063b26b5053f4}}, {{0x000869e8f8653478,0x000498cb16b98bce,0x000bd2b92786668b,0x00070a1e52fd90fb,0x0000fcf025fb7145}, {0x0003105fe53d4b78,0x000c7d1f08cb8199,0x000e90aa136b8d03,0x000adab87b877995,0x0000ff5b8a7416f5}}, {{0x0006181e6127b8f3,0x000e26986975931a,0x00050fa780fda309,0x0004c9cbf2d51ead,0x00000b52ace1f172}, {0x0007cae0f0e4d834,0x000d5d6c4773705a,0x0003f0301bc79516,0x00008598de8bea90,0x000050e748954ca6}}, {{0x000313f2b32b8c07,0x0008ad46a7a7864a,0x00071aba203009b8,0x00019786bab2c270,0x00009eea2825dfae}, {0x00022bea3c6feb06,0x00067e299123604c,0x000aa7d5ba6e907b,0x000bc50302538712,0x000018eb27f3228f}}, {{0x0005c9df43643466,0x000f22a16dea2da5,0x000026ad0fac5dd5,0x0003677c40f2faab,0x0000af1895ff0f0d}, {0x0005cc7072a95ee8,0x0002231880e3d2a1,0x0003245ac109f07c,0x000a3343e7d98a81,0x000053adddb5139a}}, {{0x000da35f08f5eeaa,0x000b0c8141361e77,0x000274120e93a89c,0x000d2380e4856041,0x00001a55e742ddff}, {0x00047074615459da,0x000a3cae4a32bc77,0x0002bc1e180630de,0x0008995de64b3ee8,0x000066bb84bd1667}}, {{0x000fde701d4ff7a0,0x0000c53f426d150c,0x000b25dbb8593360,0x000302331d9505e7,0x0000ed1a8e859f94}, {0x000ba4e5e0f86f6b,0x0001e557b53b35d7,0x0006087ef1317fc7,0x00069a1f34ef53a5,0x000023a1a44d68a2}}, {{0x0002686d46f85357,0x000f2b2aa5adc9c6,0x0002bcd92779e24e,0x000ac2af4f9ea4cb,0x00005036fdea645c}, {0x0009945ac233c5b5,0x00042cd0ab16222f,0x00096a9d0c598bc8,0x000b25254749518e,0x00006f6d06bcc429}}, {{0x000e2d17828d97f6,0x000a6cb1d21e5e54,0x0002876e02980d80,0x000fdd11debb54d5,0x000002f74e3fc7a2}, {0x000a25518c05c3ef,0x0004a101d6408d80,0x000ed1c406f00af2,0x00036f5c1f6158d6,0x0000932ec7aec045}}, {{0x0000dd90c8eacd14,0x00051c277d39ced7,0x00037b995a86eabb,0x00069c2d692f5dc3,0x0000aaa65fcbd3f3}, {0x000fb8dac3487ba7,0x000fd9030bc0445e,0x0005b00d8a303975,0x0005ebfc43a8d1f7,0x0000cf7e4b1a80b0}}, {{0x000e7d3babe2bed5,0x00008ed9aa788262,0x0009ae8cf61b9b73,0x000a2cb8859a7ead,0x000009dd0bff2a08}, {0x00089563be5f62a1,0x000c60b33a1ce2ba,0x000eb11c00b2efd6,0x00076537bfd95b86,0x00001760e857be9a}}, {{0x000df2f2e4d68602,0x0005e7f162bab259,0x0008073b4332202d,0x00097922f1857cec,0x00001ada3db5ada4}, {0x000feabac21545b5,0x00044b8366fdd7cb,0x000823597e0a8ab9,0x0001b19ca5ad3fd4,0x0000556946280dc4}}, {{0x00068bc679af7df3,0x0004d09bd4c65b7c,0x000c3d5c8bb79f15,0x000a8eb5a55faae6,0x00000e146d53e240}, {0x000bb5275fa8a745,0x000f9bc67f8fc6e7,0x0004d7d55f437e48,0x000162aaaac77964,0x00008f7b8a4e25c7}}, {{0x000addb9871528de,0x000efb8f6e9085a4,0x0002b3dce56c416d,0x0009f9352c94a7f5,0x0000cb572963cc8d}, {0x00073bb6f154d061,0x00094ceb155e9479,0x000479f043bcfa01,0x00094fef2ebc01a0,0x00007c190148abea}}, {{0x0007288c1fd2f6a9,0x0007ccb5f2f0c85d,0x000cd8ddf6f0d1dc,0x000d6d1b46cbab39,0x0000a99e4c52cc37}, {0x0006b442e61e355b,0x000805cf7f7f0461,0x00062ca1fbf6d2d2,0x000a6685af0aca3a,0x000059f9cee65508}}, {{0x0009830a1370ba94,0x00066f630ed4cc2a,0x000c49043c9c70f2,0x000cda45b0a9a339,0x0000981cac0d3fd4}, {0x000fd2b1537c0568,0x000d2df567bfdb10,0x000f06ee7b678713,0x000035476bfd49ac,0x00007e163ef8dffc}}, {{0x000a43558915672f,0x000c1ac1fda86ae8,0x00060c9a1cd95a10,0x000104f8c2f7429f,0x00008f5ad3637888}, {0x000c8fcf90898e9a,0x000df624e89346a2,0x000c1fea87fac86a,0x0004b83fd83bf0ac,0x000084646a23ba36}}, {{0x000f4fb4cc23cc0e,0x000d0fdfd051e92b,0x000f292128680d8b,0x0001f9e822e278e0,0x00007d4d9e59445c}, {0x00015c16f300247b,0x00007aa90db5c335,0x000342a9caef4b57,0x0003e1dcae37a135,0x0000333cb5dfa28f}}, {{0x000acedb3b302867,0x0007a112c1fd206e,0x000c8ec52d01b8c9,0x000b94e452325cab,0x00009f884b8bdf35}, {0x00097e89f70cf04a,0x000d749d1ae5ecdb,0x00044351436bbabf,0x0008abe4530f2f42,0x0000bb3ffc216d9c}}, {{0x00001be0aef6af88,0x0003999c0a70d435,0x0003287b2e21580a,0x000a5b6ddd29cc9d,0x0000458091850c10}, {0x0003a83b67e26fc0,0x000ea4f022126008,0x000f9f5f013525d0,0x000f6daa2f518f8a,0x000004d78d00bb76}}, {{0x00007dce35d51eb2,0x000bd3f986bf114d,0x0006bae418c11481,0x000fad9aa9bf9aed,0x000077c4aa6b8996}, {0x000c111fbadb653d,0x000475bd860ae81c,0x00037b28ab206311,0x000dced3249e29fe,0x0000f13e34b76224}}, {{0x0000d8d46c6cabee,0x000f1556df1e311a,0x000bc9a29620950f,0x00069f3a256b625a,0x0000845ca024ae37}, {0x000bde60adf24a88,0x000bb4cd5c340731,0x000458b3da58fa82,0x000fbd43156083f6,0x0000e80538fd3b33}}, {{0x000d5c8a4f806766,0x000e48d81dc67831,0x000430a5bacb70bf,0x000d86bda3b12c13,0x0000e602fe106d61}, {0x00026aa4d9ab33e0,0x000174ef7d6aae6e,0x00040016264165cb,0x000be577ac555a74,0x0000910d31ed147a}}, {{0x00081f76af0426f7,0x0008410d604b45b2,0x0009a1d45d6fd752,0x000806aa4fbd4908,0x0000c1de40f80886}, {0x000bf8d15847181c,0x000703c99e3ba93d,0x000125e520380a85,0x0007d15781da897b,0x00000c67ed4697fc}}, {{0x00028041ae87db81,0x0009887b3bc50e3e,0x0003fd20d364a165,0x000aadeb000f0f28,0x000038d839993e13}, {0x00085d6a8b8661a7,0x000b34e820a8623b,0x000eab235775fc13,0x0003ba5f2815b147,0x0000d88868130267}}, {{0x000d1e00b2843c2b,0x0004df08cfc65f61,0x0008c6f049ce3d0e,0x000d175a3aa4f905,0x00009ff1be643e16}, {0x000c16adf8587d83,0x000242fe78408aef,0x00047747318730e3,0x000fe910dd08eac8,0x0000bef97b69315d}}, {{0x00099942d00d801c,0x00081d20b58aab1d,0x00083cc49dd642b9,0x000a89b8d67ee603,0x0000d28c6d5ee521}, {0x000f3f9e69075ff4,0x0001d35323720055,0x0007768d68b51dbf,0x0001e7c55669a92c,0x0000298cf352d79d}}, {{0x000f2548f7c0a953,0x00011d0960107f3e,0x000e0af7bb667c89,0x00064816f354cac5,0x0000d50791b116b8}, {0x0006848e4fd86c6e,0x000c9b7eb17c143a,0x000b947b4f8a167c,0x00060e30ba6169c4,0x0000133e463aa3a4}}, {{0x00029106d1d6a7ce,0x000ba4385d93bdd2,0x000ee80a9f04f720,0x000132b787a4ec14,0x00004ea21e5863a8}, {0x0000364500d59b88,0x00060f60934a7413,0x000ef1d84166c20c,0x00031d1fab6365d3,0x000088cd5fbaa114}}, {{0x000d32fedbd19814,0x000221d0419272e7,0x000c4ec059041e52,0x0004de9d2dbd541b,0x0000443d10dc8775}, {0x00078b0d3f94e824,0x000ad40784f9f399,0x000fcf6218b57c8e,0x000b5e55522304d1,0x000047969a949e6f}}, {{0x00011391108d6518,0x000f28d0956f98d4,0x00002d8f8d2ccf71,0x000b41502b1a4d7c,0x0000df02a4b0a6b6}, {0x000be826697a7400,0x000bbaede068213b,0x000c698316391575,0x000947ceb3b39955,0x000092ee9cb03fb9}}, {{0x000acdeec1fc6432,0x0002bf85fe71a639,0x000483fcd152b2d9,0x0006a076d90c3e2e,0x0000f765abd75a8f}, {0x000eaa6605b6e935,0x0005d4661347735e,0x000b692ca9771efb,0x000033f6b4f4f2c0,0x00009e887ec099c1}}, {{0x0000f5f11e1df448,0x00062268eb0e4b3b,0x0007263a3032513a,0x000cc00b41244642,0x0000522b093085dd}, {0x000a4316959d64c4,0x000aece72aeebcb6,0x000a57e25bca4137,0x000a307ad4f570ca,0x0000ea827aee1273}}, {{0x0001c403871a258f,0x0003c3e40bd72b4f,0x0002aef142a3cf29,0x000c0c94b6f5d42b,0x0000c868d6bb0915}, {0x000fdf303a147183,0x00075f9ac83d925c,0x00078cfb4a2974c2,0x000cc66f8a5e4142,0x0000ffea4657d7cf}}, {{0x0003d2857b0fb80c,0x00071f7a356b4ff2,0x00028236aa740396,0x00073184ebce593e,0x0000eeb59035372a}, {0x000a4ef592e84599,0x00099e31e3885ac7,0x000dca9f931251e7,0x000405a7e073ded2,0x0000ffaa7091f0ca}}, {{0x000993353be2eb86,0x000523cb41aea060,0x000f52305f75d323,0x0002da1c19ae132a,0x000005aaaff1356a}, {0x0000b58337d86433,0x000ea1fc9f91fef1,0x0002a47dd5fb33df,0x0009e296da6bdb2b,0x0000d30051c46b7e}}, {{0x0001396d37931aa4,0x00042fe59d13f6e2,0x0003436e3bc1ea61,0x00095019fd93e242,0x00008077ea00eefa}, {0x000d18f2e5c1305e,0x000ee6a4b029fad4,0x0007af0a58115f19,0x0006774913164569,0x0000f85f4ccc0bf6}}, {{0x000abfabc6473ac9,0x00076f8f0f80e13e,0x000ca19fb9dad550,0x0000add3a04f0b57,0x0000371e049416e8}, {0x00061632d80ea152,0x000278e8a04dac3d,0x000220d15df178e2,0x00019959c39ef8ff,0x000054bc5557480c}}, {{0x000faf5f45158e7a,0x000d1f1c1ad0350b,0x000f15bb4fef27d8,0x000e3fc4f652ed78,0x0000166e75983350}, {0x0002cfe2e4cbe8e4,0x0008a56c51d904f9,0x000ec83d02ce2901,0x000b1cbafabfbd51,0x00001176ec3b0b9e}}, {{0x00085b4bca3d230c,0x000a63179d4ba4da,0x000a166590810b39,0x000b36088f040c03,0x0000773154019362}, {0x0004e8f53d96a2e5,0x000b3ce80126aff0,0x000eca232cc5998f,0x00000d61e47aa73e,0x0000dd3cdf403670}}, {{0x00055f69d0a7a33b,0x000d34ce0392f3dc,0x000bee0d7944608b,0x0005132e2a2b5516,0x0000cb2be45b0370}, {0x000fb9ef66b067f6,0x000160aba278abd1,0x0007f0556104063a,0x000b4519469ecf88,0x0000d00218f6f0a9}}, {{0x000775dcbbf023f3,0x00045ef40d8ecd2b,0x000eee1c75c73796,0x00033027bf36185b,0x000082791736f63d}, {0x000d829fc7d15216,0x0003028b4561845d,0x000fbbee37cd94d7,0x00092fad0aff8b0a,0x0000180e25ae0f03}}, {{0x000f7e62927d7a9a,0x000c839904e36315,0x0005df42f47d356d,0x0009290393e21cd2,0x0000466787630e0d}, {0x00025ee6ced93469,0x000f010090774044,0x0007a7592fd8fdb2,0x000a03dd870e7a31,0x0000e332fd788110}}, {{0x0009edb975ec2c09,0x0005175735d65d1b,0x00064bc88e72b8be,0x000ef80b4c4c003f,0x00003be7738bb2d9}, {0x0006e0fd72ac494f,0x000ecf9a7a5fdcc7,0x000b1e5a2028d854,0x00097874b4af8b2c,0x0000b21fce5d8966}}, {{0x00092d9ee6a8ebf2,0x000f26040d80ea6a,0x000852efe4c46437,0x0005037006c5176e,0x0000866683ba0c93}, {0x000bfd0134476305,0x00040e03c13b63bd,0x0008885347ace166,0x0003339702e75cc7,0x0000f159cdfbc73a}}, {{0x0002a9170ad6789d,0x000d2234dc9ad48f,0x000f2a7d5e25f59e,0x0007a488b843c73e,0x000027897d1cc561}, {0x0000fd3365d34202,0x00012bb48f85ef77,0x00069764c4ade689,0x000d9404b74787a3,0x000055e4a1bf0653}}, }, { /* digit=23 [{1,2,3,..,}]*([2^161]*G) */ {{0x000e715ce388849c,0x0009bb7a2d2af7f9,0x000661db13a1607c,0x000108dedcca8040,0x0000b1a7d04a99e3}, {0x0003a8e4d163dfdc,0x0001783f0e3121ce,0x0001fa2958fee10c,0x000e438b956bab30,0x0000a007e991f63f}}, {{0x000c2bbff739fa94,0x000c017ea854bdf5,0x0007a64f91d3bfa6,0x0000fdc41fb9d90e,0x000083aa0d7f2c19}, {0x00010d24d367c028,0x0004597010d57ebc,0x00032c5579b43146,0x00072bbd8b596396,0x0000ddf287538ee7}}, {{0x000d002aead503ac,0x000702bbfd247478,0x0000b804d9f4d7e3,0x0002ca633f318949,0x00003505e7867a6d}, {0x000e5d7dbff73d80,0x000335f9e633fe97,0x000ec9aa42cc3a3e,0x00034df252891ec7,0x00004900747ed888}}, {{0x000d54830481b038,0x000e2747a4cb9b56,0x000c55970078ce04,0x00066e74e17ce4fa,0x0000ea3c99c7fdac}, {0x00047874a0836e33,0x0008462862478e13,0x000af3763a660e33,0x000f8efb8318cfbd,0x0000993ecdd67d59}}, {{0x000143d1036960c6,0x0001ffe5607a28b5,0x000be0da767df772,0x000db340e2fc542c,0x00007bc3d3e1614e}, {0x0000a909a4228534,0x000df6d0a4402b66,0x00036e7c5f663676,0x000900fa2bc94c05,0x0000d5caab23f5a3}}, {{0x000c9afe79e70193,0x000d0fec85a37b5e,0x000a360abb585419,0x000883bc10053d78,0x000097415c9102d7}, {0x0000686637dc9a27,0x0004c4b95f42fa66,0x000cd93361d4b524,0x00042e32721d0b6a,0x00007db0d3bdbc70}}, {{0x000bffcda8b06d6c,0x000713d8d2427048,0x000cd16bb5d30666,0x000c2197309cf437,0x0000a11a6f46e8f0}, {0x0008bc17a71c4e20,0x000a92d41371975b,0x0008eb0f5349e195,0x0002ce43cc3800ca,0x000041f3bf72ccf0}}, {{0x0001daeea3ed0905,0x000e1bd5e3c53fbf,0x000c1100344d6a8d,0x000e5e4699602597,0x000060ea92b03fab}, {0x000e180e331a3fe2,0x00080a41fd2b20f8,0x000cdb94814472c1,0x0006c8ec624980f6,0x00000f649cdb7533}}, {{0x0004ac13e9d9a85e,0x000ac7ff9c45703b,0x000329fbf150d4b2,0x0001fe9bfe98b07d,0x00006ef7b3a05b5a}, {0x000f985fb40d4e51,0x00028cdb30c4b3f3,0x00069b998490bd1f,0x000ee22e2266c121,0x00005d8c7fd5c464}}, {{0x00017c9deb217fde,0x0000d74da8211aad,0x0001d8f1f679025c,0x00046eae0861688b,0x00003593982918fa}, {0x0009d1bfbf4ff519,0x00072a742f2a69e4,0x000bc2636c0fae9c,0x00046b33d049c63c,0x0000197ec842285d}}, {{0x000624c23eaa251f,0x00071318ca3c4e9a,0x00095832234ba387,0x000151f4edec7eb9,0x000040bfde516f7b}, {0x0008fa54043404cb,0x000a18aa5c602ed4,0x000ae3268e047506,0x000d7eab79eb8def,0x0000d3b0628dd6e8}}, {{0x000c4cbd66e8fe68,0x000dc69d604cf338,0x00037b6dd97e28fd,0x00035b246f37d007,0x00000272666649ae}, {0x00093d37810cf944,0x000a459f78ac9a38,0x000ce165aabf2ebc,0x000d640453946fae,0x00008fa3bf971e87}}, {{0x000b48a8dba5c4e8,0x0002279adf9d8dc3,0x0000634c4f3162b0,0x000b99b53c9ff728,0x000007d5d4dfaa42}, {0x000ff5483cd41f20,0x000f99d21f8d8aa4,0x00081bda1da27bb5,0x00014e9a023684cb,0x0000f7ca6a09c875}}, {{0x000567e48aaf12a4,0x00072c6ad9edf914,0x000cbc02cdd34885,0x000546ad9d3126ff,0x0000421b423fa8d3}, {0x00006150c5383199,0x00071eb71f6ae471,0x000ba9109ff4978e,0x0004c14e33185f0d,0x00001b2adaf1a25b}}, {{0x00022a2429dd8dec,0x0007cd18b13b0a91,0x000b0ceea09a2c07,0x0003e4cfd65c5719,0x0000c9bfb6cc8897}, {0x000ab8bb6da6f448,0x000361113f5c0f75,0x0004bcd4ce388639,0x0009b3c84e7da532,0x0000c1fd90d251ff}}, {{0x000043aa2a095bb7,0x000f9b9f786a3956,0x0002db051d57f81a,0x000149260ef94740,0x00007bf6371cac51}, {0x0001f2f5c58d7ca4,0x00040f7f7b148a02,0x0007371672527386,0x0004b3f38f333829,0x0000dd7a77b276e8}}, {{0x0005457a7eca1884,0x000cbe9cc41123f9,0x000136109bbb2c81,0x000d931b767fb526,0x00007e27c293ef66}, {0x0003f2073a6659c9,0x000dc1c5bb8bcb6e,0x0009084018ee6a36,0x000ecce3dcbff9b0,0x00008f3df8af2dc0}}, {{0x000d83214c8380e8,0x000a3ec7ffe0ad3c,0x0000a2a618aea404,0x0000c47d0790d1b1,0x00000273e67906f3}, {0x00015287e729a739,0x000c7793bec7e17d,0x000acf922b6820b6,0x000254244b10a6d9,0x000075cf6a5b4cab}}, {{0x000e81a727320b70,0x0002224f04c96aed,0x00023666fc18bf83,0x000b00b1675a97e2,0x00003640ad09f382}, {0x000efc15509f9819,0x000644de6fa11fe7,0x0008a4478b13a59f,0x000e660ba6778ad8,0x0000f50b5ac51bf3}}, {{0x000335a6248572ee,0x000fe809fb5fe516,0x0009687ddec290cd,0x0005b5dde9196a7c,0x00005c7d5573c17b}, {0x000ca4c51c772072,0x000a292ca0ca7c47,0x00061427ea87854a,0x0003e4b62b22808a,0x0000c0e5c44caaf5}}, {{0x000cad5d48a4d850,0x00038d63ffac15ef,0x000132f45987e66b,0x00026ccf724889b5,0x000098deb93b1efa}, {0x000c62a168e65f44,0x000179a62036dfda,0x0008c6dbc9a4ca00,0x0000127fb88e937e,0x000082fd3c4bc09a}}, {{0x000f3ad4813e9d65,0x000bea963f775c93,0x000f6998a46925b6,0x00042bbe8efab45a,0x000029a003ea7de6}, {0x00043182741135fa,0x000c3b74e1a693fe,0x000868769efe7061,0x0001612e436da60a,0x0000de122bdce426}}, {{0x000e61a87ddb5720,0x000452750c03edbd,0x000b38089eb41621,0x00024498574681e0,0x00004444c5108b2d}, {0x00036ed4405c72c4,0x000be6b96571a817,0x000f46d03728b4d6,0x000d22955878f06c,0x00002f2165d6e0b3}}, {{0x00094e84458cd24f,0x0003bef3dc9a70f5,0x000015cc27ea5fec,0x0005fb57e2473ea9,0x00002182214585b4}, {0x000ebd801e198aee,0x00041dd30f306bbd,0x0008a039acb01cbb,0x0008fcba8a783d98,0x00006a26d47437cf}}, {{0x00036d49031103bd,0x000fe7923cfb91e1,0x0009eb93161c2874,0x000b42decc591c88,0x0000df51011dba39}, {0x000990ab10e9def1,0x000b6e7f06951c4f,0x00063898370d2788,0x0006086393208c48,0x0000fe1f66e971ef}}, {{0x000b1d4d77c20846,0x0003b33e6323e50a,0x000985e8c9dc50c0,0x000486a05634b919,0x0000032a15357882}, {0x00036b5f08065726,0x0001971634554a52,0x000f5fabff87414c,0x0006926e37e37906,0x000043513f70d8fb}}, {{0x000739d209dee688,0x00006a1bf22b1a5c,0x0000f4d7e2ebc0fb,0x0006423d3abeed81,0x000036c96818fb4e}, {0x000d76faf0aa49ac,0x000c17dc5923cdc1,0x000780973c293b0a,0x0007d05101c6532d,0x000094adf9339dbb}}, {{0x00046923a1ecf415,0x000a0f9ea7f71cc9,0x0005779649d48858,0x0002e729830f9f5a,0x0000a791f0968938}, {0x000b5938d2d48da3,0x000e4a63cc188eb4,0x000352d09bbdb586,0x00085e41ea2ca55d,0x0000adb9408e7ccc}}, {{0x0000274ff274c238,0x000cf4ed75e4ccfb,0x000a58613ca6532f,0x0002f08974ef32d2,0x00009439f94f5580}, {0x000e9bd5e20f70f3,0x0008a3a320b0c62e,0x0009802b6b371846,0x000eb1e8d6efb074,0x0000fa8cacacc87a}}, {{0x0007eae23823fcbb,0x0007a6db12378b1f,0x0005b04d466a2702,0x00074dc0e7967d3f,0x0000380c34854b55}, {0x0003c2ba3855dc42,0x00079c231fffe07b,0x000441be0c2f630c,0x000d9ac7ff5f1f15,0x000079fc2752ae5b}}, {{0x000d5c7dfb3b7db6,0x000f2ca2b44387bf,0x000dd902aca2989f,0x000944ef359e06f4,0x000056de67cc5e30}, {0x000a7f7dc035890b,0x000b9b3ae32060de,0x000a3a327bb2950a,0x000ad059416d8521,0x00005f50358a117c}}, {{0x0004d697d518207c,0x0008e8767b105e78,0x00004f1169c01bf5,0x00094aab5136a0ca,0x00007aff0662c2f3}, {0x0008afdcb5efc86f,0x000e9d607a6dc3be,0x0006fbaec814892d,0x000876bc381a1cec,0x0000804cfbddb73e}}, {{0x000450c84a71f470,0x0001720cbb4694c3,0x00056165c8b36095,0x0003d3e5828b276c,0x000045bbc6744164}, {0x00051eb64e2708b8,0x000f53a1d23ebe35,0x000cf38009d06145,0x00098675fca31411,0x00002fe56c9b4d77}}, {{0x00089e8111b8d201,0x00028297bce0d27e,0x0006a7f74f80e76c,0x000d806d8e7591d1,0x00003296fccf5a57}, {0x000b45c6234aea5e,0x0006dbb033b176cc,0x00001216b62e1303,0x00059592a07ef8c3,0x00008ded78bdb4a6}}, {{0x000ba2653b58b0d9,0x000642b1c2d703cd,0x0000554cb792e88c,0x000b255ed4d6bdaf,0x00007f42217534e2}, {0x000de0e9cf5e143c,0x000f7f941fa77e41,0x000e9891ce2c2bc0,0x000551a51e978228,0x0000c49845f6fd9d}}, {{0x000072da6b911236,0x000b00c92cb9f1c0,0x00011381534f49ec,0x000547bce7c215c9,0x0000dae67dc8e0ed}, {0x0001fe5736a8717c,0x0003fdb486b086b4,0x0005017a01d7b53a,0x000770705d0f3b3b,0x0000be31d50dc547}}, {{0x00031863932c2b1f,0x0009f501ea21d51e,0x0007b61c6b454bba,0x0007c33cb217df73,0x0000437c6550aee4}, {0x00044ddc161b29fc,0x000c0745a7be39af,0x0008b4e070c24b6d,0x0009ad9f92882f93,0x000012fd81676997}}, {{0x00027b5c52289a6d,0x00032826de7fbaeb,0x00017117cc11f3cc,0x00032957907378e9,0x000000bca115722b}, {0x000ac722f5f70b15,0x000c503d941e10b4,0x00062a5c2c8da21e,0x000534a9a3154dff,0x000008a1f7b230d8}}, {{0x0003ceff9e7ddb51,0x000d455c86afb70d,0x0007400b6fcc1c34,0x00025964e9b9b522,0x0000c5cc14c5bb83}, {0x000dab9215029d5f,0x00095e492977ca58,0x000c4a20aa8d4a22,0x00079b19ad26e547,0x0000d91ae79427ea}}, {{0x000785990e90367d,0x000a07e301b6cf61,0x000f636872d8e93b,0x000ab534875194e9,0x00009e9353e6c1d6}, {0x0003bbdf1baa0db0,0x000c20a4cb66f8ea,0x000ab37b0f01de77,0x00087161e429924e,0x00006efdcdf4befb}}, {{0x000058743128a14e,0x000e066c3cd7d9ca,0x000e7e113a4a62ae,0x0000fbffb51b4a5f,0x0000cea959c32023}, {0x000a40cdef43eec5,0x000504a425d60020,0x000bb9d80185d21f,0x000572b5f2b10cbf,0x0000666c56168409}}, {{0x0000890f3b3930eb,0x0001779057c83ef0,0x0005d2430da067a2,0x000527201bd76b42,0x00007acf20f1cd5e}, {0x000b427b09507e58,0x0007d0ae9fe8ebe9,0x0001249697373a3b,0x00059d9893406aaa,0x0000e193839ab695}}, {{0x0003e416acc4f41a,0x000c0e4846f77700,0x0002367dc52fe292,0x0003b7ea2b9fb2b4,0x00004b818d575942}, {0x0001acd23a6740da,0x0002e5fd8bd4aaaa,0x000dbddefe835656,0x000f8fa01421ea02,0x00000ea7a8551c0e}}, {{0x0004fb87bb00fd80,0x00047858e175eccf,0x00085edcf225c4cf,0x000c38fd395e90d8,0x0000c586da7163c3}, {0x000add010694ccaa,0x000a11f48044f949,0x0005c948f8de7c64,0x0009280114c685fa,0x0000715d4a32473d}}, {{0x000e9f8ae08c8338,0x000c24ac457f9136,0x0007263471950b1c,0x000630b176b52349,0x0000e8f83579b684}, {0x000f9d951a40fda3,0x00089ef984f41fe3,0x000cddfe9a94991d,0x0002c27fae887b02,0x0000f0c63c32ebc6}}, {{0x0008af107ba4d8d5,0x0003fbb10a2c242d,0x000f5b66318b0abf,0x000ce7ec492bfd61,0x00000fb5641a0bfd}, {0x0004113b1af6e684,0x0004855508208921,0x00033ccaf19c703d,0x000f8a48d57f4293,0x0000d1b2b012f3aa}}, {{0x0007bfe9a941e18d,0x00055afc95f9e3ce,0x000005028fe66b94,0x000660d24af86ca7,0x0000eaa16abe3583}, {0x00042b18956071d8,0x00069c5ee733a2e0,0x000c62790d044917,0x000243845bb68654,0x00003a6cb05a0b5e}}, {{0x00023c0963370038,0x0004f22524f47160,0x0002b7ff5d5eaddf,0x0008db0d442eb80f,0x0000556e77aff7df}, {0x00075e94c9c29a9e,0x000f494e0b218d01,0x000e6d2ba70c6541,0x000cd9f24ffb8b01,0x0000c6ad519d7d87}}, {{0x0006285b576c16f8,0x0001de9045f059de,0x00073148979af3b5,0x0001d1be76385156,0x0000309c88e12487}, {0x000c2eaef778ff77,0x0009e31d2d017dc4,0x000396fd24eca05e,0x000f6feb4f3a3681,0x0000a6b0a015343c}}, {{0x000eb84a8ff46d92,0x000e9fb21b2cd2a3,0x0007ea66290a8efa,0x000bf97c2fe9112a,0x0000c3722457ee2b}, {0x0004b94de41e2c1a,0x00070bb0903edd96,0x00012b5c31d350a5,0x000a101dae61431c,0x000045a6d6340610}}, {{0x0004e955e16f4b09,0x00069c988f51727f,0x0004df57c7386200,0x000bdbe4bbb1fa5e,0x000074b4ca3ca24e}, {0x000dcfef41e02f97,0x000d622895da0cf7,0x000400bcaaaab9ed,0x000e8d05fbb139e2,0x00009606bc9991cf}}, {{0x00007c5d049d81b1,0x000af8afecbf4e38,0x0009913b9af5ff22,0x0007bf2c6b5e2220,0x0000094dcf820643}, {0x000323f6bb2b4620,0x0005b4b00c0dd155,0x00004087e0e046ba,0x000c8dca3773450b,0x0000a3ee21010695}}, {{0x000e23bf4f40ccea,0x000d69f16f378bb4,0x00081b75cffb5728,0x0001f674fcd6adee,0x0000975281c93b18}, {0x0001fa9b52577c5b,0x0000ddc2d2be26f4,0x0001deac33380425,0x0005e5008eaa09d5,0x0000fdd6b2fd7884}}, {{0x0005aeef4710b606,0x0009620131b1a6ac,0x000ed6b51ad3a398,0x0001f7326c04601c,0x00004fed7c15b6f3}, {0x00051ae4e75e2291,0x000b2b77e46a8eb4,0x00024864f5396c6b,0x000a307fe44bd15a,0x0000fddf9a7fb162}}, {{0x00004463e73b8ec4,0x000f55cec5c6d935,0x000affcd58b06c2e,0x00044e00ad788e57,0x0000872bf18a0fd9}, {0x0008d14e5d71e574,0x000d2c3030bc88b1,0x0005dddd1ce58ea7,0x00057d1f9dc7c5a3,0x00004d1818d515b6}}, {{0x000ddb8bf4b54748,0x00023305f0daf6ed,0x00052038139d4af5,0x000efb7d652772de,0x0000069ae58d16c6}, {0x000bf73dfb68fd92,0x0003fde5dff8e66d,0x0005f967c0e4a7d2,0x00069cea388c3b52,0x000000d338cf626d}}, {{0x00045c714519e589,0x000e0913096476e5,0x0000d02d7cf59be2,0x0008386476786752,0x0000a99633c4e597}, {0x0000911b961f3964,0x000589bdb3f722c1,0x00040b0284c204f6,0x000310c471f04659,0x0000b8f29400b771}}, {{0x0007580908012844,0x0006c059281b1ac5,0x0001c35df7e30017,0x000950b68a678586,0x0000423082ebc843}, {0x0003aee90a09598e,0x000a9913987d1e31,0x0002a51b3792cb2b,0x000d1a18355dcf9d,0x00002891458b1327}}, {{0x00059e6c45add90c,0x00035578dc6b43e3,0x0002ce37e6ba1e8c,0x0002e4a6505c2877,0x0000b821b953f4ae}, {0x00022256fceb3969,0x000fbf38ecb4e108,0x000eef42aaee7a3b,0x00075dab0d35094d,0x000025f891427625}}, {{0x000bb97d0edfa1ce,0x000e46b5d78101cf,0x00056ac5655ba12e,0x0004dc4b371feede,0x0000daa9c221667c}, {0x000b374aafd9ed41,0x000ac3a4679a8a4c,0x00000de55fba1126,0x000b1bafaeade880,0x00003e746cdf818e}}, {{0x000990ec0f88d5f8,0x000288b4c7c62b24,0x00084d7118dfe4c9,0x0009fca983eed9ba,0x0000a1b21a93ca27}, {0x0008872895a60682,0x000024e18c538587,0x000ca73ba0accfc1,0x00000837dd0e2487,0x00008513be562083}}, {{0x00003f947b6ea260,0x0001bb7a4729c734,0x00032750426849a0,0x0004026b72cf4cd4,0x0000c0fffc1c5d6f}, {0x00085c96173719aa,0x000c05910bfce43c,0x000acef18e018793,0x00032e0f069d5faa,0x00009fae2afd5c69}}, {{0x000acf01ed8bd7cd,0x0000263477c55128,0x00078d6112535697,0x000b9055421fe02d,0x0000f1a20e6ea246}, {0x0005ae7d073d4a89,0x000bd63778b84373,0x000bc7a37abb5f3e,0x00009b5483301a33,0x000036ae26c63a8e}}, {{0x000061c767eff576,0x000dd9ea79a1ccc2,0x0003437b2eba650c,0x000cfcac1b11574d,0x0000cfb31a0d11b8}, {0x00054f89f42bfdbc,0x000cc2703661fe7c,0x00070d58a8d1569e,0x000bba5a9527776b,0x0000161cf8545e19}}, }, { /* digit=24 [{1,2,3,..,}]*([2^168]*G) */ {{0x000c25e9f5170aa7,0x0001f8f5338bd76c,0x00040201a3c0073f,0x00012ffbf6fcc231,0x000009be87d49f50}, {0x000bfe953dc74903,0x0003d8653153dc6e,0x0000eb06e85facca,0x0003077c47d716a6,0x00009f6514c80bee}}, {{0x0007b09654c48577,0x0004fdb0f5200d71,0x0004e6cb015e94bb,0x000f88dcf3519dc6,0x000059d275f2ebdb}, {0x000ec0fd11aeb819,0x000c8be9fb8ae833,0x0007d57ad2893bce,0x000e52f8ada66e74,0x00002d1bbca1a1e3}}, {{0x000d4246631e6f4c,0x00052539fdfdb824,0x000b8f0507304674,0x00065e29c10ef5e6,0x00006b779bb7066a}, {0x0005a5380f5abd81,0x000523a56e993fe2,0x000c373f30122a40,0x000a4ff3a52697bc,0x0000de214925f8e6}}, {{0x000a957eb8abd51b,0x0001bb0ab69abf50,0x000e7252ad43d460,0x000fe24207ecc4bb,0x0000964c4fe8348f}, {0x00091eb0668c06ef,0x00037f512c2d1c55,0x000cc3a429333eb0,0x00061923cd82147c,0x00008b93a9d6c59e}}, {{0x000cc48773e35954,0x000e214b22340fa4,0x0007830d996f413a,0x000907b196a2bc70,0x000037ecd06850c4}, {0x00039bfe3ef35b95,0x000b82f5d6ce3ace,0x000d52cc302fad75,0x000d0d41e6e89210,0x000090aa6d71bfce}}, {{0x000dc3c8f4aa5889,0x0003a50cbedadb5e,0x0007a52111e6d592,0x000a80177e437ee8,0x0000df8d7c441860}, {0x000eda8cf92436a5,0x000296bc8560bcf4,0x0009734d2066ad91,0x000059756ccdd882,0x000043cd11c08558}}, {{0x000077ab273751fb,0x000c255f1d1bdcb6,0x000d46eee885b68f,0x0006411656e793e5,0x0000bcc61e8b1ba0}, {0x0004299f88dfd877,0x00072838b3a069d4,0x00011a67cda79c15,0x00041b6a28140e4e,0x000038faae273c96}}, {{0x000cc732728468c7,0x000bdfa9a3bd9569,0x000d743f442bfed7,0x0002dd74b6f74702,0x00001de0fb3c4843}, {0x000e7d2fa94e43b9,0x000e83587eed4ca6,0x00099758a506eec9,0x000192a4a5292aa3,0x000006038c3c85a0}}, {{0x000e8448ca36b091,0x000724026db2dc96,0x000a6f0c367dc2bd,0x000865e5b7051140,0x00009f8943f82b64}, {0x0005ff5fc9a5ec8e,0x0007001fcd7a9b31,0x000237cd7ebe7ebb,0x00005c2a5148967d,0x0000e997301ffa6b}}, {{0x0004c665b9eac65a,0x00052ba5a915a9f2,0x00066278cc6bdeae,0x000b249b5e33760c,0x0000ebc09e8ac7b1}, {0x000caea5a6199620,0x000be60abe7d7c0b,0x00088044342ec817,0x0000a54835970666,0x000050d8ef2ff279}}, {{0x0006c27846f75d05,0x0002cbb8971b0591,0x000fef98918d6613,0x000d3bb003639aad,0x00002a37323294ad}, {0x0004bdefdbf09029,0x0000fea38bc50670,0x00075dd7401061a2,0x000972a86fb9b7f3,0x00002a9ef8a399aa}}, {{0x0004bb6ac1207afa,0x000e9580f1b1a4df,0x0009301d506bb9e3,0x0003ddb25c740d34,0x000024a77e6b0e29}, {0x0009997ebbefc02a,0x0000f9bee7b2e05d,0x000c3f6c1d1e9c60,0x000930fe3607022d,0x0000b29cca36dccc}}, {{0x000a13edfc3232c8,0x000071af81e3d653,0x00093d6ba80325a6,0x000faf2033e68207,0x00001c7c20a162eb}, {0x0003995532aaaf64,0x000c4aecfc68ed5a,0x00098196ea438ecb,0x000c5c5fff04de2b,0x0000069d497969cf}}, {{0x00016cb6ab4f0071,0x0002ebe7c2a951b2,0x0001507db4c9e3b8,0x0000e1bf7e75c535,0x00006b09f4ba63d2}, {0x0005b11f97734d28,0x0006dc581c376458,0x000cec0864a46ba7,0x0001fc733dcc712f,0x0000aa53b9688ed5}}, {{0x000da0620844de29,0x0008013f258339b4,0x00080097b1ef8c8a,0x000716541e0eaa04,0x0000c5dfd5748615}, {0x00091ec9a14f247b,0x000b9fd915415a11,0x00018caef9331112,0x00097f0fe5bf0968,0x0000636405ec0ca8}}, {{0x000dd20ccee2cb48,0x000695b1e68483ba,0x00039267fb005c14,0x000991f285b3686f,0x0000596c8811740c}, {0x0000039d01b2c886,0x0000066b542dfb66,0x00090ad7b941b21f,0x000fb42690c453ab,0x00002b8741e90fa7}}, {{0x000af8194dadc627,0x0001edf51bfe1834,0x0009bd348776705b,0x0001ad70ee1dce5c,0x0000b26f64d4ae19}, {0x000a67e9b9267406,0x000dbf7a60d3b5cb,0x000bbaec7f815e13,0x000b9534b3ab92f3,0x0000d60d991417fd}}, {{0x000ce9cfb15625e8,0x000fc4db106913f8,0x000b2c9cd8cedab6,0x000a59e395243e6e,0x0000434f60bd1431}, {0x00012f01f634f2cd,0x000c40ae9ddbe0ed,0x000b866c6a73238f,0x00081e4ad4d13cf2,0x0000375a9d4fdb5d}}, {{0x000cffc53160c73c,0x00007539809f73a4,0x0005b23b923b3241,0x000b5195c30c96c5,0x000094fdb86cfd44}, {0x0009dbb264a47a78,0x0004d93efb5e99fe,0x000e9a68933cc2c1,0x000ffe8e878bb037,0x0000f7d2e44d123a}}, {{0x0007e32ebbba9682,0x000be1ca85ab0b5d,0x000c9697a03f4a69,0x0000a0e9870318d2,0x0000e8015aabeaf5}, {0x0008c0ba7e1dfd93,0x000f56bc29921b79,0x0001d1608f5ae798,0x0000ee85a0922135,0x00007f26d995d2fb}}, {{0x00089e5230cc1b43,0x000be3c41cfda991,0x000292450b3d3c1d,0x000dd89d5989e496,0x0000cfc1ecde9524}, {0x000d6a36c7493761,0x00031f1678e9dfa7,0x000a563232985073,0x000479ad7e48450c,0x0000ac60c6fc5646}}, {{0x000e435ab0cf52fb,0x000756ea25b6a16d,0x000034b17c2186b4,0x0001f2fc7036334a,0x0000bd1c9eafb0ed}, {0x0004b6d249b21b42,0x000c8600552f96ed,0x000bfc49b2fc4e76,0x000ab86179a640ee,0x0000742b6f2cd85f}}, {{0x000836e93b510939,0x00034ecdc5de9094,0x000cfec954c59e8e,0x000659f87fcc53cf,0x0000a4568a7a9057}, {0x000c03e5826f6ff5,0x0002f83faeae31ed,0x000b8b111d7a6557,0x0001ce6cb4bee145,0x0000e343b357add3}}, {{0x0007124356c03ca5,0x0005e9256c013890,0x0003b390b3f0ccfa,0x00096e541ed7e668,0x00005b7692759858}, {0x000db7904f1906ec,0x0009f798fee14430,0x000c762aa8e0adfd,0x0009c408beb39255,0x000089f982ccad3d}}, {{0x00079b689457b765,0x000fea0f5b956815,0x0003aae2e20e7df7,0x00036deeee3b323c,0x0000b98cee329d35}, {0x000cece61a5f45d6,0x00042e78c9cbc2e3,0x000ecf95735d7b06,0x00009e205e0aa2ca,0x0000e5839c503b44}}, {{0x0008f9208fcdecb3,0x00061b66dbf41f69,0x000a1af91975c299,0x000495d23b37428d,0x00003d9b8eb27748}, {0x000c26ec038dd208,0x0007733cdf67d14c,0x000f975e452454ca,0x000c01fabd49971b,0x0000982b9f5186b5}}, {{0x00082d71ed519447,0x000dd9063242dd6c,0x00086537a94dbe4e,0x0007e5159224fc27,0x000080fe5639583f}, {0x000c13fce88adb1a,0x000bc57f2f24f1ae,0x000fa63cf0fdf9e6,0x000b6d90fd8fafda,0x000044733d44e643}}, {{0x0001fe8821de4787,0x000ad971ee6fb14a,0x000eeebab19b43ff,0x000fd6931813e718,0x0000f9d90866ab81}, {0x000ab8c25b81d6ec,0x00085bd040950086,0x000b02351a4be98f,0x000418cdeb6e4418,0x0000e57c7e8aa473}}, {{0x00026d051d0b0c81,0x000c03f43bb4e055,0x000108d9671ce09f,0x0001db9508e74a7b,0x00001f1327927748}, {0x000b0010c84e7c59,0x000517a0dad7005a,0x000eefc16dacdfff,0x0009472e6bfbd9e3,0x0000daaed22249a2}}, {{0x00068df75e5be29d,0x000385fff9a99479,0x000bb571140db0d9,0x00046304b0b4cfd7,0x00001addb26ae24b}, {0x000581856fb91014,0x0001696d3fdf03ca,0x0009d9e027eb9076,0x0002876031e89681,0x00003e9950d59c6e}}, {{0x0008caae157977b0,0x000674349dcf9d6a,0x000b699a60e8b54c,0x00076b8f3c4ad763,0x00005cc559c43b1b}, {0x000211ff4c8d557b,0x000e78905358fe5c,0x00083936f8309b2c,0x0004af64acf5051f,0x0000481e7e0c6fec}}, {{0x00053fe33c602daf,0x0004cf85cb7ed0f4,0x000d1adf62c3095c,0x0002834573d068b4,0x00002d0fd0243c96}, {0x000b5a83acc5f984,0x000951b8242871ac,0x00042785559a72b1,0x000383e0b9e6f513,0x0000eef0713ace69}}, {{0x0001642514077632,0x000b7843397d07f7,0x0004342ab2e8b92a,0x000548eb3dea716a,0x0000fd46ebf66d9f}, {0x000108bf0b8a44a2,0x000444151a9a68e5,0x0006fbd93700306f,0x000a840cbdf94002,0x0000c577ee629894}}, {{0x0000bca8d5a234cb,0x0002ada976341eed,0x0000d8f5b9ffe4f4,0x000614ea32e31bba,0x00009640fc08e2ba}, {0x000bd3091a3cc172,0x000dd6813f60e5d6,0x0000955ef6102e8d,0x000c318e716035a8,0x00007083188700d7}}, {{0x00015232afdb4a80,0x0002497d796b320f,0x000fcb99991c4603,0x0008a8e8ee7f7f71,0x000086a97ca03731}, {0x0008e6620f196d18,0x000bfb677ecebb7a,0x00084316a2c3361d,0x00098a5a92e2000f,0x0000ad5b02777783}}, {{0x000dd0efcada3ed5,0x000bc43a9054d4be,0x000db0e54123501a,0x000e0f955966efef,0x0000e31aa4eeecf5}, {0x00049cefca5df228,0x0001b845465e6d45,0x000595d6a9287939,0x0005be1879d8875b,0x000050e3ad18c18e}}, {{0x0000ae732271801c,0x0005b803d1ed6ccd,0x000be65e61856a37,0x0006cdb05d43079f,0x0000757438954a07}, {0x000ff113986411c7,0x00005e8c6b438f05,0x00082dcb49c55eac,0x00095ff8773437d6,0x0000797c7879b91a}}, {{0x000418f19e79e5c2,0x000898e184288dfc,0x000811bdb644c310,0x00017641a8142536,0x0000ec41eefe56df}, {0x00005b4e27fb6bc1,0x000f8e054fba1edc,0x00089e0e1650e5e9,0x00095692ab6f4529,0x0000fbcc505276d3}}, {{0x000281ca2dfe6dc8,0x000110de712c653e,0x000ee928158404b6,0x000cf6d7e6105cd0,0x0000d388140e6953}, {0x000ed39f0617f89f,0x00067a61a5286d8c,0x0000ab74f3f1e213,0x00006e8ba2227632,0x00002cba3b64a144}}, {{0x00019bb3ef88b573,0x0009c9454c264310,0x000e75b084b05970,0x00090f0042faa6a0,0x0000c42b966c283b}, {0x00069924227e2345,0x00081e764b1d0c29,0x00085621fbc826d9,0x0005ac4deb50a990,0x00003a0c83012d01}}, {{0x000eedb8289fe19d,0x000455d8703a0f39,0x00069318dd303312,0x000f22bc207eb1d1,0x00009a1b36be080e}, {0x000a07cf89baf3ea,0x000d625b41a9e3cb,0x000bfa4f0e365656,0x000ce1cc88025770,0x000065eacea3656e}}, {{0x0005c19ef45d6b91,0x0003ff6ee7a1c188,0x00095b614626c796,0x00008cdf716625be,0x0000905d59e52e68}, {0x000e8445d0e57d94,0x00010289d5e86e38,0x000258e2d5292144,0x000960edda6c726d,0x000078f149d15866}}, {{0x0003b373eeb3be5d,0x000008cdfd007c91,0x00020d539c7e74db,0x000a226c08d0199f,0x0000f14535325914}, {0x000f5b02288d3d99,0x000c450de2506ea7,0x000a273bce6ad41d,0x000bdbc8e36df7c0,0x00001ad366534f40}}, {{0x000602ba827d0dcb,0x00091adbf560c3f3,0x00013a340f90f764,0x00093eb8c55e59f6,0x000080ec3bdb9d66}, {0x000fa139bc659726,0x000f737f930cd576,0x00052013011430c2,0x0003652c9fa7479f,0x00006624def0a0e1}}, {{0x0009772769b19129,0x0009d1ada7cf07e3,0x000c9a259ebf722e,0x000cc4241ca31714,0x0000b844dffaaf8c}, {0x000a55fb9723c092,0x000761a9a645934e,0x0000f493a79cd872,0x000410ce7fa8a9c6,0x0000992cbc50218e}}, {{0x0009ec972907a41a,0x0003f2fe9e468bbf,0x000807c9a4ff51da,0x0000ea9411ccb7b4,0x0000798a299aa8f4}, {0x000bb39dfa6de2ba,0x000d102a830388a3,0x0009be6602815a52,0x00097420a96dc3e2,0x0000698523b7ae24}}, {{0x000e5e2695331daf,0x000aa511993e978f,0x000890d5eea027e9,0x000380801eac0409,0x0000079a353c8f13}, {0x000d2aab807ac122,0x0003153b7b007d3e,0x000c8146f9dc100f,0x000de36f0b42a3f9,0x0000837fb01d7d39}}, {{0x000bad9ce4ff7c82,0x0001f47732d9a89b,0x000ee5faee22e6f7,0x000d5ea181969613,0x0000e30cc88547dd}, {0x000c36cde1dae9e9,0x0006bc67c475249f,0x000dfb408d12c773,0x0000395cb3b91c3c,0x0000d1c1cf946d61}}, {{0x00040f67eafffb16,0x000b5075d48b2a76,0x0002c7c72f3112e3,0x000256a2a08a64cb,0x00007bb6c8e3ab45}, {0x000cdb3da1c5cb8b,0x0003c150935de71c,0x00071dd0d002611f,0x0001db99d4d16d56,0x000038a095f1bbf4}}, {{0x000d0fa367f54448,0x0003146d9fd69644,0x00003ace9de42457,0x000b4368540bef28,0x00007344421ec2ec}, {0x00080473886c71dd,0x0002dbd4c0da1c7f,0x000e1b1b8096a337,0x000b47b29c3663ce,0x00009b850a4fe4c5}}, {{0x000e92e2711f6c64,0x000b96297ee64980,0x0000a0287ce98611,0x000f59621aee88a6,0x00003a13d7736ee6}, {0x00042a0c754f85e6,0x000e90b3dd1a56d1,0x000bc903c6539c68,0x000a0c394962bd7b,0x00000c0dac7c0d84}}, {{0x00006ed5888a2297,0x000751181c6bd971,0x00001fa29f66bddf,0x0003dc751ce5d2c6,0x000030a703678c28}, {0x0001544a52f8cedf,0x000be7386c005d73,0x000b3a1020b312a8,0x000964a3e7d61e3b,0x0000cd0a1f2cc51e}}, {{0x000bbb7730637d22,0x000c0ee69ffebac1,0x000752c78cf96785,0x0003758cc83733f2,0x0000a885c698de85}, {0x00081b51bc9dd850,0x000b4da7bf040293,0x00006ffb160bfa60,0x0008090cb031432f,0x0000a5961de3acd8}}, {{0x000544e3c5d8a4f3,0x000d695380f1fb71,0x0001dd2550cdfc3a,0x00008c41c6df5c9a,0x000015751273680e}, {0x000829ee56b6eed1,0x0008736e5950fa14,0x00084ee6a21b66ec,0x00068cf12d853922,0x0000aacb8733b362}}, {{0x000744efd56dcf02,0x000d5ea49439ff91,0x000ae04d42849b3c,0x0006a13b6e556b78,0x000068bec5e02e90}, {0x000aa440bca4d3c9,0x00061e186837ca14,0x000a14da69cfee5a,0x000e96cde0f100bd,0x0000a67e8a765191}}, {{0x000e0aa93f9d4461,0x0008116ba5c9f703,0x000eec78f1b1b2fe,0x00027eda47d1be72,0x0000185448619cd4}, {0x0002b1e0e6c02d92,0x0005c61712615570,0x0007a197ef949c1d,0x000c916bf10a070e,0x0000fd96d47b2de6}}, {{0x000688afda1eadac,0x0005b4195e38ca30,0x000eef15dd8a8720,0x00033df5b11f7a9b,0x00009f2a47d71132}, {0x00023ac090f6dd40,0x0002214691c3f9a8,0x0005cbd3a69343c1,0x00055aad1e8ad7b1,0x000084d228267ea4}}, {{0x00086fe50c54cbcb,0x000f653d0a7793ff,0x000c8c956c1fb89e,0x000283d2e92f9f9a,0x0000056a14c921b1}, {0x00089485a04b6501,0x00077ea06a75ec6e,0x000a3c4a6d6534de,0x0002a89696e721dd,0x00007fda5cefe58f}}, {{0x000c5318d0e40d7e,0x000f6a538eee8279,0x0004e48a6eb9f6e1,0x000da4bcb94b8cff,0x0000c4899eed700f}, {0x0002a357b45aee63,0x00099a0087e74e39,0x0001e767f55766e7,0x0000e932c5c64a26,0x00002c5fc6626169}}, {{0x000c2d890c562791,0x0001c4070cc2c8dd,0x00054def1b70c1f0,0x000d5c30fdf7b1ee,0x0000dbfe11c8f13f}, {0x00065c130ac48a93,0x0003ce26b496f369,0x000fd989f121c642,0x00072c727a8a1055,0x00003a348bb24777}}, {{0x000dcd25a190461a,0x000a106657730c58,0x000f65f30110341f,0x00052183383995bd,0x0000425c381d25fe}, {0x0004adfd6e549001,0x00041290a9292ea2,0x000b76df784221ca,0x0001819281717876,0x00003c6286226714}}, {{0x000956ce903181f9,0x000756047fd2cff5,0x00082b850c30f551,0x000016a192cb7cc1,0x0000164246ae1ae0}, {0x000fc004f248d82d,0x000270a5afc4b0e4,0x000bbe52be2cd809,0x000bcc98f97e693a,0x000059d87c21fa20}}, {{0x00041646e13ab52e,0x00054c259320b618,0x0000a293fa0cd0bf,0x00055b81537d75a9,0x000051de543bb104}, {0x00001de5fec9a0eb,0x000afab3f9905655,0x000b5b3263792733,0x0000f68755608613,0x00000d4e6f054c47}}, {{0x000710267c542a45,0x00079aa6faea8981,0x000ab176cd6156ab,0x000dab6a3f451e57,0x0000377dae7b0730}, {0x00017a92f3c84900,0x0003ce118d488c05,0x00076348955e451d,0x0001227de12fc278,0x0000a2604acecd69}}, }, { /* digit=25 [{1,2,3,..,}]*([2^175]*G) */ {{0x0000f07eb83bd033,0x000c42728bc15e5b,0x0007503622eb0cfa,0x000572855689e6d5,0x0000ffe17a0fa82e}, {0x000666a2a34814bf,0x000cdc30d17ce550,0x0008d4ebe4148a9a,0x000ee9bc0fe3fc26,0x0000237a4fb4ebee}}, {{0x0001c57cbb6521da,0x0007e013ad088fb8,0x000e523b034683c9,0x0003fd973cba032f,0x0000bdd5593a2694}, {0x0002b0ee317fe3b8,0x000b0cf3aa3671bd,0x00053dd74d87c697,0x000950259f03a8c0,0x0000bd48cf81120b}}, {{0x000c2d85f00903b9,0x00023d280c52e198,0x00003f2253a05cf2,0x000053ca5bce1e21,0x000095953ca7afa1}, {0x0007eaf045a97253,0x000b61ef1e17ab18,0x0001cc69a1ea96f0,0x000d886265e99974,0x00009d16dd8088db}}, {{0x000070d24ea591be,0x000ddb1395a861ea,0x000c708bf3a531a9,0x00045cf5cab52096,0x0000f8dd80a0756c}, {0x00018008dc9efd3b,0x0008df4b56e64d3e,0x00050e16e3f81f4e,0x0005b29b73276fb7,0x00003164beeb41b9}}, {{0x0008e3a4e414233d,0x0007c6b84bc799a9,0x000bf981390050aa,0x0001b5245d5f66b0,0x00008ade8eaa35b9}, {0x000dd15f5c095ff5,0x000754ae9f8d06a9,0x0001d477cbbf72a4,0x00022cbd33b02ff2,0x0000807cdb0901cb}}, {{0x000ee8912650bd3e,0x00053f782a39217e,0x000618997e9887ca,0x00025a0184c0779b,0x0000f717203cdc98}, {0x0002d521bdde7363,0x000c28fb3a2da14f,0x00001a0c2ef900e1,0x000e1af7a79f2377,0x0000b5d67fcc63cb}}, {{0x0002eb021df78d51,0x000b081c9f307643,0x0006e5c92268a6e3,0x000e68d0b6f1d616,0x0000780b514a1250}, {0x000363c9b4b5ca38,0x000c14058ae8d88f,0x000abcfae84c017a,0x00001c021a267bf1,0x0000352d6c69a7e8}}, {{0x0000ce578ee0421a,0x000ce61cdee800a5,0x00088829e74b485e,0x0004993b7a9f52f5,0x000021992713481a}, {0x000d96b4c61e5ad5,0x000c4dfe48a2ed65,0x0001425d4368e4fb,0x00016f34820cdfc5,0x0000a61d206e3b36}}, {{0x000e3ec504534afc,0x00004ec7955c88a4,0x00050fed6537707e,0x000f6d10700e71b5,0x00000877ca57aa69}, {0x0002364134c7dfdb,0x0005855b263b3933,0x000dd5682153885c,0x000150675240b632,0x00005d29c6405791}}, {{0x000b0d18666db72a,0x000f2d06582741e7,0x0001793ca3db5107,0x00077db29e38bab0,0x000084e11850de3a}, {0x000c8c2f41c8d79b,0x000501d15f801de0,0x000e2fa4edb21191,0x00055b0e59608ebc,0x0000e2af30fb06fa}}, {{0x000365bea852e986,0x00023d23f18d3454,0x0002a0a0c61de9a0,0x000db69a0b114ba2,0x00001a64b5ee88ce}, {0x0007873ef9d06036,0x000df11ed48a5e35,0x00071a5b115f7948,0x00021de1c334adcb,0x0000265cf2f68415}}, {{0x000cad85cb2c08f1,0x00013050f5bebd73,0x000c923a2320bf0c,0x000fbc656f4c2f1f,0x0000b53d151eb2a0}, {0x000b47255d36eef0,0x000a7b1171c22301,0x000724d1552a8c41,0x0001e7407c769b93,0x0000a4c8f8e5501e}}, {{0x000ea34e3d43a020,0x000a28fe86195962,0x00015f931be0edab,0x000b1a5b51a1a2e1,0x00008f3b12193b36}, {0x000f4bbef5440b0a,0x000163cb97e2f791,0x0009344115a98d55,0x00030bfa810b1d2c,0x00009ac76ae97e64}}, {{0x000a89f24dbe5bbf,0x00027581706f6f1e,0x000b2064b8a59052,0x000c28e5a7101b9d,0x00005819dae01ddd}, {0x0008e03d02d3f29a,0x000fbf2a1752e0db,0x000e534102f0d5bc,0x00036cd64e0d1f26,0x0000e99c7c9e4cab}}, {{0x000adc1b52d2c43f,0x00033f467ac3b66e,0x000ff7454896c1f4,0x0005b725476ddb98,0x000076bf8f2486b1}, {0x000fd017adb3aa43,0x000cb44c8927398a,0x00058f3e9553da51,0x0009000230e271cb,0x0000539e7977c345}}, {{0x000fad0b915022c3,0x0002106d7a523ebc,0x000335d2c80fc99c,0x000c9cb1584ffa37,0x0000e03e0f554705}, {0x00006adb6d93260c,0x00003a928e28cd3a,0x000cb2640092877a,0x0007e59d702481ee,0x000096acaf7a1b0d}}, {{0x00043348d46add3e,0x00017b9f7c368909,0x000a1f1374adebe3,0x000cf21b998ac50b,0x00006e1a007a85e5}, {0x000fc1c2509d7d1e,0x0004e813db920aac,0x00064a506bbbc35e,0x0005c8293e917e2c,0x0000a0658874c8bf}}, {{0x0003c2cd968d2bbe,0x000cd4c6eb2327bc,0x000bc548ced0417b,0x000e8d485d4af2f9,0x00004dacd98b166f}, {0x000b9e5cc5ded1dc,0x000ae2a98ba23580,0x000492a536faaf10,0x000e70e356736920,0x0000e510a11666b8}}, {{0x000f3f1dc1e8b2dc,0x00066500e64a04a3,0x00036c76bbd3bb86,0x0008bbbf79e266ec,0x000021afeb04482e}, {0x00077f89864546f7,0x000725833277b7ee,0x000c09d42161b114,0x0003b6320fd7a5fb,0x00008b814a9efdb6}}, {{0x000a001441991ea3,0x000ddf08d40e88f7,0x000233055e0b07ef,0x0001ccea6feaab02,0x0000bc15f20a5108}, {0x00095e60f38e9c6b,0x000c2ae91436b227,0x000f0513590543c5,0x000e03be4e76138c,0x00005328faf22271}}, {{0x000a10d536481292,0x000410288d8eb4c5,0x00019c657d7affd4,0x0008693fb147884e,0x000050afa8840f2a}, {0x0004ae9998b069e2,0x000cb30712223137,0x000e91fd044e1f54,0x000424e7c6c23e5b,0x000007d112a47f0f}}, {{0x0000f60ce2868df5,0x00049dc327eeea11,0x00046812a36db546,0x00080d91bf0f5a1e,0x000048f22bd3d877}, {0x000dfe5037a0b7e2,0x0007ecb51339b1cb,0x00071e2f0fd2d522,0x0001f8676a49b5a4,0x0000c769f1a6e725}}, {{0x0002bf88dc2f0a70,0x000a3e68dc50f43a,0x0006cb84e98ae70a,0x000c6a2dab22067b,0x0000b91bfae77104}, {0x000ca4c4e1a302aa,0x0007c10be63cbe8f,0x000d88a1c0a2bd81,0x0005edd219abbb19,0x000010f5e51606e8}}, {{0x000a2ad1f09fbd80,0x000db1f885fd8bea,0x0004e03fbf5c1af0,0x000c71abe93ec293,0x000068d6944c156d}, {0x0008f5795e2c39d0,0x0007de2a058c1fb2,0x000f391b7a363cec,0x000c511d56812b80,0x0000f1912e543c50}}, {{0x000fa1bea2fc7856,0x000facf2d79b50ca,0x000b4dc605ee792c,0x000e37949b168ca7,0x0000f9f755e580ab}, {0x000214f4f0dfe3d3,0x000cb8f668d68881,0x00035d50ad3e2ab5,0x000d53349af8b5fb,0x0000eaf332242029}}, {{0x000b3c0c5daf0c95,0x0000abd9ca770b96,0x0007491231340717,0x000c014e3753afa8,0x0000c1c50ae93cc7}, {0x00019a912d2fa053,0x000518344b1ceaad,0x000ee6c426f62582,0x0001b96bc3e144fc,0x00001b86a8ec07a6}}, {{0x000f7a88ba02f836,0x00073dda3e59c0b9,0x0009cccb19acdf4b,0x00089607ecb07e22,0x0000e179a7fe03f0}, {0x000d066aa749105e,0x000cc15f2c1af78e,0x00014bae07f26f5c,0x00089e31dede1a78,0x00007ba2b8802bf3}}, {{0x0008fa37e8bbf903,0x0002caeac4c26d3b,0x00054f9cd941b0e0,0x000695d6897bed90,0x0000879936aa651b}, {0x000a4948166b0278,0x0006106510d0399a,0x0006d4927293dbad,0x000dc9d16600bdd4,0x00002fd5ac433045}}, {{0x000ea7b9f63a3889,0x00052557fcca4d89,0x000f2529e5e6ada2,0x0008362a0cdc0208,0x00008c8b9774d48c}, {0x00017a89e8d0e96d,0x000e14b6920ed486,0x00029494b799f387,0x000de743c654d3c3,0x0000a2f31f9adfaf}}, {{0x0007183488f904f9,0x000017bbed9c088a,0x000762e0db3b3f4c,0x000a3f18431c2c9e,0x0000d188af79e181}, {0x000747e667c0d1bd,0x000e968e2a6500ae,0x000769759bb4bffe,0x00055beab9f86803,0x0000262d46060ae5}}, {{0x0000f4053aa9a78f,0x000f79c35e544089,0x000fd839d2c910e7,0x000055db8e7ca105,0x0000db97ad2b5831}, {0x000eaadbd3c4f7a6,0x00049ef7c107421b,0x000f045e1644c17b,0x0004119453602525,0x0000e5c41998aa2b}}, {{0x000ae5b06add8234,0x000ece621122e9d0,0x0005aa6bbb8095fb,0x0004f8f151cbaa93,0x0000c30736f0d3f2}, {0x0004bb0b2c0934c3,0x0007af112376af19,0x00016cc005f81abf,0x0002b33e6640b099,0x000054837f425912}}, {{0x00060e6aff8da2bf,0x0007b2b372a89876,0x0003629cb60a2cfb,0x00061c0c2676d696,0x0000a734b56f2086}, {0x00098761fa9a1967,0x000560b82b8f4fd4,0x000c50fbf8a331bb,0x00006ab7b7096885,0x0000ee75dde39230}}, {{0x00076dffc96c21b4,0x00063017c3d1bee4,0x000d9abd38be81d2,0x000f32f709fcddee,0x0000acb956a0808a}, {0x000b9e25e66f3281,0x00033831c8a599f0,0x0007eb06721417f1,0x0005cd4833b0079e,0x0000493a266fb576}}, {{0x0004baa2d5668523,0x00003689fc40b0ae,0x000279c28d2c7f3e,0x0005629534d2937e,0x000098a4d84f2ecf}, {0x00035f14cb929a91,0x00061f8963790393,0x00009e7b7b25a5d5,0x0001016ac69aab90,0x00003d893e043064}}, {{0x0006b786a36bceb5,0x000f6c58efedb4f1,0x0004457a463ce9bd,0x000b72d69b1127cc,0x0000fe789e83b3a4}, {0x00017c51f7e29b87,0x0001531fdf820296,0x000f2588967ed30b,0x000ed5a3df57f4a1,0x0000ce6d4a94d6a8}}, {{0x00021eb676b5af75,0x0006aeb5c3a18291,0x00043eaf051ebc58,0x0004ef8bd71c578c,0x000001fbd625ad3c}, {0x00032c1d4663f519,0x00045aeb159107de,0x0007a554a8e64c3b,0x000cc9cbc678ad96,0x000020a01fc96657}}, {{0x000be89bb43950a1,0x0005817b762b4266,0x00047f7019afa059,0x0003ca4a2c7f75fd,0x00003dbf549fffe8}, {0x00097451ad446c62,0x00064f101758f41a,0x00094ed44c88f148,0x000c5d31f7dab03b,0x000007789b3fa42d}}, {{0x000b763df689270c,0x000edece73483d7e,0x000aee476fae171e,0x0006c30996252a7b,0x000068c6d9b71408}, {0x000802d40be0a180,0x000279f7214afa5c,0x000a50baf4c90054,0x0006601236076d44,0x0000f1a4df9f611b}}, {{0x000a1d871f3ad971,0x0001471f93998a18,0x0007cb6b4089cfe6,0x00046e2888680be6,0x0000a4a0b67496c8}, {0x00051504d9720c99,0x000b82f1dec98c6e,0x000bc6615e19ef35,0x000cbff674933ffd,0x000029e4752286b2}}, {{0x00010cf8006801ed,0x000ff3f96b824680,0x000ece9035f8b7c1,0x0004370ed08d2e0f,0x00008e43d7f5270a}, {0x0007758e8c30cba1,0x000a4c5e382f556d,0x000374942bed58f8,0x000f7b4d390b896a,0x00003148cdc67c81}}, {{0x0003a9cd5c44392f,0x000e47bdfe21ed29,0x000491c1481a25a7,0x0006fe1cd7dae300,0x0000b9d3868cc4ee}, {0x0002068ada03a6a0,0x0000340f5762442b,0x000e0b53a208f677,0x000762b2ee05976c,0x000047fee704c66e}}, {{0x00045be28bb6cc47,0x000bf9a6e2427822,0x0006b0e18c349f9d,0x000d413cbad70f27,0x00005db7ba2cd50e}, {0x0006fa76a8688440,0x000f17cc272cd775,0x0000a9aacfd31874,0x00081d50e472af63,0x000031b1bf3d98d8}}, {{0x0003b11d230fb125,0x0006dafeaf84ff7c,0x000c87a66c21c356,0x000c83a7fe395ccd,0x00009e0055334e3f}, {0x000b297d762bcd8f,0x0004090b1e777788,0x0005f7ff73f79031,0x000b978916e41f31,0x0000d6a86b093da1}}, {{0x000049a7d1255d7e,0x0008c8b12a9250ae,0x000341efc83f0f58,0x000003e1e125c570,0x0000f75675c0a287}, {0x000daf8b1258cf93,0x000cabe2242a1697,0x000503d8cea55b42,0x0002e7bc47653393,0x000010c33e17e789}}, {{0x00005ea79f286771,0x000e27569d6a75ce,0x00081e4e2f605135,0x000742a515ec1123,0x0000af60690f9618}, {0x000edaa92529d0d8,0x000dd00e97be79b0,0x0002108f6ae93abe,0x0000519721405467,0x0000ef5c7cd11264}}, {{0x000d7e85074cf812,0x0000fdaef4fbe1a1,0x00029585e7cd8874,0x000bf4683db12a45,0x0000f263cdb933fd}, {0x0000daef9cecfd73,0x0002d1cb1ad9ff75,0x0001e2010333c1bd,0x000602f2eb13e6e4,0x00008c434479fa32}}, {{0x000f364154e53c02,0x000b2c50b3e176ec,0x000b8ac60e89a87b,0x000d69c11fc58ebe,0x000070424c27f1ba}, {0x0003d753d21bb139,0x000b6450de0ee6cb,0x00061e4b1f84aa55,0x0003f32665545bec,0x000084a236952f13}}, {{0x0003559faf384825,0x00038d591b30f3b7,0x00072436cb28e627,0x0002d24feb572f5d,0x0000a8b72daa2f39}, {0x0003eb59a42e3589,0x000e94348dc3c258,0x000373f8afa9d0e6,0x00065df154badfc5,0x0000c01d9c6026b4}}, {{0x000a5d00987d7af1,0x00054d16fb7aa127,0x000a5390ebddde5e,0x000638bdd6eb95cc,0x0000ad6055b0a46b}, {0x000e6fcc176765e6,0x000a926d17614afd,0x0005b60ce8f86b23,0x000cb7cce2306fd5,0x00003641982b357a}}, {{0x00025cfb6810afc0,0x0000d2ca6813e5c2,0x000d4b0af3ff9d91,0x00060ae0e7a3e4a7,0x0000f245dbc069b1}, {0x000feb26a5cb6ec8,0x000bccbcb43885f0,0x000e47433ac2cdbc,0x000d82e118d811be,0x0000f794b01a4d8c}}, {{0x000b7da95b4aaf8b,0x000e80a2c2af911a,0x000a345252c2ffde,0x000120078e3c033d,0x000043c12ac705de}, {0x000a2b459a347a22,0x0008ec984c45ab7f,0x0004f78db43cb528,0x000713cad280f6bc,0x000082a8e65b4562}}, {{0x0005a98aa0ade635,0x0007b2a62c54a937,0x00023803b526bfcf,0x000b028e8fa38d03,0x0000e116fb100b08}, {0x00099fca2c266e2a,0x000cb41473a5abfe,0x000cbd4a3edc82fc,0x000ee0a832b0f682,0x0000c6da25c35e5c}}, {{0x00004550befd3bc3,0x000b40a480954444,0x00050861335df122,0x0002e8d27b00d3c2,0x0000e5cf22108602}, {0x00032b19ede4f65d,0x0005402e3b45b297,0x00081c377a4b3990,0x000db8602b61ae64,0x0000853d2136c902}}, {{0x00041daa3fade2f3,0x000c4f5787b60696,0x0000017c50c733ce,0x000cae7f1ea7c369,0x0000822da6a5138f}, {0x000278eeafc2f192,0x000da7b7d5aa7a6f,0x00077a2da02fd70e,0x000a24eb85681571,0x00004c69d2e8b3fc}}, {{0x00061ccef0bb0ac3,0x0005ae0f16b6abe3,0x0006987ba1d88953,0x0000e4764662ef0f,0x0000fed054617265}, {0x000889078fd300ed,0x000dc644c4935004,0x000723fc14e7aeb9,0x00001edc7f36fff0,0x00004b9f194f4d3c}}, {{0x0002cce358b66aac,0x00016e2bf8e318a5,0x00084f0df71d65c7,0x000699f185f6f605,0x0000d06b9aba0d6f}, {0x0005205b7b70371e,0x0001c3cc258b70b1,0x00064ef797aab8d5,0x000ae313d81500be,0x000091b0d1e2d796}}, {{0x000c14085cd77a2e,0x00055b024ee5e095,0x000a1a0b278a5dd8,0x0005b23d4b412cf3,0x0000f1bb25ca44f8}, {0x000da53ecc55a1cc,0x00040b943b5047b6,0x00089e5806f90cad,0x000403b58fa8ea96,0x00002429e57eaa6d}}, {{0x000fdb4fc9660aab,0x000ae4b79d49d8f8,0x000e3da0cdf3ff94,0x00095a287b418943,0x00000220fb3bf163}, {0x000a22b7dbf3af75,0x00010e4436d28b1b,0x000a5068eb344ae3,0x0005e62736f5e1f3,0x0000f7041a241e82}}, {{0x000ddbeb3f0ad80e,0x00075c157deb17ed,0x00083992e4d16850,0x00000290b495d7d2,0x0000c100310a5d3f}, {0x000f68ee053ebdad,0x000e0742709e626d,0x000d131a85412994,0x00030749a376ce4a,0x00006015a407e49b}}, {{0x00032582654c7441,0x00053280089731ac,0x000bb5cd371832d1,0x0001aaba1ddd1d3b,0x0000ce419eac3358}, {0x0009570f5151ed5a,0x00076d6327900c1f,0x000c1968aa5e7f59,0x0006745c1da0190e,0x0000929c46f7b7b8}}, {{0x000957b50de1fb7f,0x000cd8dfe690465c,0x000125b716eecbf0,0x0006b08cc2cd7fde,0x0000cd58f093a3bc}, {0x0007ffe391cfca39,0x0001ad8536a941f1,0x00047fec75582f2a,0x000ad3a9a7bfe386,0x0000e968cdb6aa35}}, {{0x0003c22a58371af3,0x0009c11c7d557ef0,0x0007d54999e44d4f,0x000d7878f8030b46,0x00009bd72fb1023c}, {0x000507350d5a894e,0x0000975cf9c22941,0x0007ee69d55c81fa,0x000da33294738695,0x0000dcd116f20c82}}, {{0x0003d73ce3e731f6,0x00067ef5c65f87ca,0x000cdad304e237bb,0x000b03dfef249e4c,0x0000d7ab5f93a8aa}, {0x000687e71c7835b9,0x000ada6bfddeaf3c,0x000b7e2419bf388b,0x0008a2c3f86d5779,0x0000dbf47353ff02}}, }, { /* digit=26 [{1,2,3,..,}]*([2^182]*G) */ {{0x000d03b214a50ffc,0x000ef4d64a402d36,0x000aa27d487e7e1e,0x000960971f296c17,0x00001a46349f6f07}, {0x0006c65b2e7b77fc,0x000e7b3f579f668a,0x00003a0809d29fb8,0x0002f59cccc9b480,0x00008b96ae5ed56d}}, {{0x0005623d2692dce7,0x000bb1439ee234b8,0x000abb782d3d06e6,0x000ad2f5b24c26bb,0x0000e1e5daf85aee}, {0x000f6b36e620b2be,0x000a6ea10ef984fc,0x000e9c789089a1c0,0x0008b74663659974,0x0000964db299747a}}, {{0x0000e9e78a6de0fd,0x000e2abdcd0cfd27,0x00058ced92b387f3,0x000ff3a326731463,0x0000d2b37033bfd7}, {0x000a11f5037eb879,0x000c93128308bcfd,0x0002cecfc87b981c,0x000a5ce342d6130b,0x0000f944d511fb1c}}, {{0x000f4a7a5b2673fb,0x0002ae68fae4404a,0x000f3366ba0604c7,0x0000b42cf803c9c0,0x0000ee8762def9c5}, {0x00068b0cc0c37ee0,0x0009620fc01bad69,0x00028d071cb3006d,0x000f8e637903ab4b,0x0000248af8b7ed90}}, {{0x0004cdaba9bab8b8,0x000b4adf23c61405,0x000ea4e3112b10ca,0x000cff8f40c789d1,0x0000f3193286f762}, {0x000bc201e35954b8,0x0000e44d9cd0d7e3,0x0002dddc5389fd0d,0x000726e698571e6e,0x00003a64f0002bc3}}, {{0x0007fb0822f35da0,0x000f09896ddacf82,0x00029979bd5bf27e,0x000381fe1269fc42,0x000052db83e4e95b}, {0x00050a861613e2cc,0x0001b06477bfb26e,0x000ecf598588df85,0x000b11c80fd01053,0x0000225a35dddd00}}, {{0x00008399fa0ca14f,0x0009af16e80f4a00,0x000377c5e70b4acb,0x000c7c3b7a59ec93,0x000030724a30aaf5}, {0x00045d067262f443,0x0004b25982507749,0x000bd81b974e4f49,0x000a4d9132316fb9,0x00009a156b7e230d}}, {{0x00040413b3024eea,0x0005d69b55098af7,0x0002a1af66a8f315,0x0008239a731304b0,0x0000e91a74955492}, {0x0003e0c7ee6a3f82,0x0008e0bd9c79b191,0x000152ebf5971c24,0x0000a198183e438f,0x0000d267b51648c7}}, {{0x0009e678da935547,0x000192f9368350a5,0x00092c6744306b26,0x0001c83d266e0e8e,0x0000ff9bbcdce63d}, {0x0006b94ad0d71138,0x0007aa419046b6e4,0x0003f4797c423b94,0x0002636860d19aed,0x0000349f4cb07f5a}}, {{0x0003e6b28a2b8001,0x000d21d65179ca2e,0x0001871c7a0e4390,0x000d93c4cf04dd6a,0x00003d99bc265487}, {0x0004e3cb86057988,0x000c2fe15fb3216b,0x000560cc19a197d1,0x0004a67b74e959eb,0x0000f4e1b585517c}}, {{0x0004cc98e585076f,0x000e80aad228c051,0x0004600361200736,0x0006fca66598227e,0x0000a461711c06d4}, {0x00065a584be71d79,0x000f1f684055450f,0x0003eef672a8e1c0,0x0009f9a749b821fe,0x0000188a93a6ca82}}, {{0x000d9a6edbbf0204,0x0007fde9666ee420,0x000b10356afb0a5c,0x0004d7dfc83b0c37,0x00000e52e0312799}, {0x0009e4ce359cd84b,0x000bf43f9183ab0f,0x00099c7e0393de76,0x0004427f846ebac9,0x0000439eeb2f8904}}, {{0x000fce31fa271e8f,0x00085dcd6ab53339,0x000bf17ca52896f3,0x000c00ceed5c8afa,0x0000aead04245383}, {0x000a90776147dd2a,0x0001155288ca6668,0x000a7aac8449f137,0x0004f1a2e10e32a3,0x0000c8394d4d3c0c}}, {{0x000f50c692933c5a,0x000c78ee682abe36,0x000b3d9a6c4ffe44,0x000be5c7b7730907,0x000000a137e49709}, {0x0001aca96183079e,0x000f9f04811611ad,0x000e37c96ce57770,0x000dec262fa1d23f,0x0000e281f8c1077d}}, {{0x00025dacbfdb5d2b,0x00008995387e4bda,0x0006607c2701b7ab,0x00021e573e7f7184,0x00007a3aa3d01161}, {0x0000e9867cd0a313,0x000894b24ebf17cb,0x00086622314b0868,0x000340b1fc343aaa,0x0000480efbe0da3c}}, {{0x0001cf09163daf1a,0x000e3feb1c836f08,0x0005a4a98decbf2d,0x0000d647b2ceaa70,0x00006d8310bc54fc}, {0x000b4c2600d63727,0x0003e4d5e8071ebd,0x000666689b444f65,0x000194168bb5dd62,0x00000c6b36071bc8}}, {{0x0003c4390dc638a6,0x00084ed1e9bfb767,0x0003234c2e027266,0x0007342738b46e6c,0x0000f7959e2d7589}, {0x000dd45f4888ca02,0x000eb5127527806a,0x000e9bae4eab90bd,0x000a8b2d4fa5ffe4,0x000087b16d15c5a1}}, {{0x000095b3fc633a8a,0x0007316bca0fc94f,0x000d8b2668cd3581,0x0008cbfa5aa5e026,0x0000c8c21a873920}, {0x0003e4ecb61679d4,0x000355a4fcc28c11,0x000ca6257920c25f,0x000b82d2d14b872a,0x000011540c35e1d0}}, {{0x0006e26c82c45233,0x0001a997670789d5,0x0002a43f81b41944,0x000726ab8025355b,0x00003f01d8297cfb}, {0x00048146db204a06,0x000c7e02913ffa0e,0x0009ca312337ee0e,0x0008727e2840e097,0x0000fc4d0f49b524}}, {{0x000b8a12308e33da,0x000337ec4d8beb7b,0x000c1659146b745d,0x000de150304503d7,0x0000d024f01e4921}, {0x000a6c823f9984d7,0x000eea03c4fda33f,0x000cc3e9c09105f7,0x000b318d61bb4a13,0x00006e743847f379}}, {{0x0002cd374b837d25,0x0006c2ce00b7c947,0x00043b58db8cf662,0x000ecfef51327052,0x0000ac22adc4bf4f}, {0x000d1d45993f14ab,0x000739554cb38af5,0x000a81d9c426f8b4,0x000c7f0bb7e92096,0x00009053648a82fe}}, {{0x000ed373accc4794,0x0003f4fa67ee2977,0x0000311becb2042d,0x000b24d99c7a2ceb,0x000036169432637f}, {0x000893691b72a9eb,0x000ecc61e9fc1546,0x000f6ea558e349b4,0x000779af664fd7fe,0x0000108ee2c5323d}}, {{0x000ae27d9b8b43d8,0x000f3dcc55d2272f,0x000fb53844004b23,0x0004b76bc98d5c82,0x0000ce7f298d8e2d}, {0x000e2a94d1a64a33,0x00061562e50f2006,0x000029eca89ef15b,0x000ee81c47d9d4c0,0x00001a9fd03172d1}}, {{0x000e1f968fcfc9eb,0x00006954531ab241,0x0008e861c066d0b4,0x000dc8c192eba4ff,0x0000ce2adf88d121}, {0x000aad0af982f095,0x000e37d4476b8527,0x000cf5d53ffa76e5,0x0009468c298e73ad,0x00005bffed75e1d3}}, {{0x0007b7598b4f4c18,0x0008c456357c5e26,0x00015f31642f0a26,0x000bc5a0a3a625d5,0x0000d18b2d13a25f}, {0x00020409ad1c3378,0x000465836e75f72c,0x0002c5ec514b90a3,0x00016a126f9a9b39,0x0000d930609e4c2e}}, {{0x000c5bc32c3d376d,0x000ee0c900c8573f,0x000eba03819e1ab3,0x0001b7ec2fecc561,0x00001001e880c624}, {0x00029ce1174fb908,0x000642285b2c2478,0x000e27cd432e3da1,0x00017bfd02b9a902,0x00007f7b6a8b6d20}}, {{0x000b1e4ecc5b0dae,0x0005c2c0e62e9f5a,0x0006c9b1bc80f2c5,0x0006a81d4c1fe7be,0x0000c726d37bcccb}, {0x0001e5d17cfa0d17,0x00024f9bf26ab169,0x000ae21bd95ea4e3,0x000c96246db5808d,0x0000a655e7c27c6b}}, {{0x000c7fa80a03a60a,0x0006bec2b0bd1212,0x0005bf438beb7af3,0x000a43da5be37048,0x000068eef804296a}, {0x0008674e2d968fc6,0x000f0425a5c48998,0x0003907aaaec9eee,0x00004751bd315af3,0x0000485845c77215}}, {{0x0002d3539f63c362,0x0004eb689b184334,0x000fbfda21a18b97,0x0003b8d5ec44e740,0x0000b3ef041e5ea3}, {0x000172b46d952e28,0x000695f9dd9c7154,0x000c09cc503a2dad,0x000a80b8da9fe4df,0x00006bc6f98f03ef}}, {{0x000aeb710af227b1,0x00042752ebd12219,0x0007f5abe6fddce3,0x000db478c999a0d0,0x0000464bcddc627b}, {0x00057116a55b2f45,0x000c46f39dc73fc6,0x000bc331ade611c7,0x00096a74bc1efafa,0x0000696914d1a572}}, {{0x0005d9abb772a0a7,0x0002a585878f4775,0x000a12aabfef29ac,0x00077327bdcdc5cb,0x00006acb1b0fff47}, {0x000942a009622cf5,0x00060793cbe33a99,0x0004e6319018ba81,0x000462893e1ab4e1,0x0000067a7a34b6f7}}, {{0x000c5d6a01c29e20,0x000c5755b9592a39,0x00003bd60271462e,0x000f05b7ed4bed82,0x00002c26351eea6e}, {0x00034a423d7cf134,0x000f08beb438aa4e,0x0009c47c4106b0b3,0x000affb4d68d1672,0x000093c8daf9d600}}, {{0x000ba868113c9a1d,0x0000338cd1fd0610,0x00063c596a184b17,0x000121f53902bc06,0x00002a0f700a0162}, {0x000d41437a1108ab,0x00028b89ad88ec92,0x0000900636b15cde,0x0005693beb3a30fe,0x0000f596d95269aa}}, {{0x000383992de6a0ea,0x0001c0eadf49d191,0x000b6249f08b65ce,0x0001bf26ab78aa37,0x000036b6d694e14f}, {0x000cd0f12f4691f3,0x000c7064c2be3f58,0x0006959713f90dad,0x0006d890ca9925ff,0x0000501135076e91}}, {{0x0007b0cd9dce526c,0x000768dafc03b308,0x000d34455379120c,0x000a2d9703f89047,0x0000693de4cd17fe}, {0x000b57df03438758,0x000d3febe5d03f63,0x00006a2f5070a0ea,0x0005caa95fc81462,0x0000a1d0ef60cf4f}}, {{0x000faed6a35b31e6,0x00027b0d2c666a29,0x000c0459970c0221,0x000d9efff00dd62e,0x00009fd870cfce88}, {0x00072489fe1ebe36,0x00056c3b41919584,0x00047468a39ca80d,0x000ed62caf69e96b,0x0000f68b71d9b183}}, {{0x000f69c3fcce6d5b,0x000cf30e7ccdbcc6,0x0008023f7571be87,0x0006101b76ba1de8,0x00008ff4180c3051}, {0x000651f6c7323796,0x000d92757ac444f2,0x000e84bd2228de69,0x000d6650d8cb40a0,0x00009a11dcee05e3}}, {{0x000a9ef3a388cd6d,0x00079a08b3f94c88,0x0004ed893c32273c,0x000eaa93278afa0a,0x0000804db1067191}, {0x0003ed02eeb1eaca,0x000aa269e85917ec,0x000b98ab4063caf8,0x000a9141573324dc,0x00003c41f6a74303}}, {{0x0000a2c274fafa67,0x0007661f730e3668,0x0002382fe8bfcaf3,0x00019134ffd8ed37,0x0000935125943aa4}, {0x000244800946cd0c,0x000df0e459918728,0x00032302f204b042,0x0007899c8ebafedf,0x0000be5328a81cb7}}, {{0x0006d0031fcee36f,0x00055e0a95cad3b7,0x00011f2abc910fa9,0x0005739da8677699,0x0000b7ac64a83b18}, {0x0005369151002784,0x0009d0563f5b5d1b,0x0007eef50df8b5bf,0x0008efc54918844c,0x00005ba66117f7e1}}, {{0x00017aaebb23a9a3,0x000fad1195b0c4f6,0x000a08f41d8d5df0,0x00015b6a2f309dff,0x0000436a93489d4e}, {0x0002a63bf9a141ab,0x000fe97001b45cb3,0x0004f5b5f37347b5,0x000d0a7ffc6ce12a,0x00009b94f9ad54b9}}, {{0x0006d07205aef3fc,0x0005231a57be8a89,0x0005a94a39f4563e,0x0003e9dea91ed89a,0x0000f63dabb48ec7}, {0x00024642fba4d373,0x000230b44974c808,0x0004d50af40a7979,0x00079137f5088ce2,0x00000609fca476c9}}, {{0x000e8b2818c83ff4,0x0002f8faff6baa52,0x000d294722da303e,0x000f9977a2d4c556,0x0000cf6d037dbbd3}, {0x0003f7b469280f8b,0x0005bfc44a6f2f63,0x000adb24e051b615,0x000224ead0ac57d2,0x0000adcd2c71b8b8}}, {{0x000f8bf1604c0532,0x000c14fadeb8bf40,0x0000e2ae1f370c05,0x0003afc120728f88,0x00001b8f66baa365}, {0x00075ab77c2209cf,0x000d8c32043fe2aa,0x0002c82e849b56c7,0x00012fd42038c184,0x0000fe0f8955a57b}}, {{0x000d850f732fb7fa,0x000609faf4d7ae20,0x000f7f1924417e70,0x000349fc42eeeeb6,0x0000a6a934517190}, {0x00018b7cf247e02d,0x000f500de589351b,0x0009687358eba05b,0x0009fc5f5739e627,0x0000ddef5f556d65}}, {{0x000774d30f504541,0x000f79d101da68e4,0x0005271bce5362f0,0x0001e6faa152f180,0x0000b838e945b4b6}, {0x0004064dd6323f11,0x0005ebb09f685488,0x000d8d4d8dcd854a,0x0006b7868850b02b,0x00009b7ff60aa093}}, {{0x00094c377476a6c8,0x000f8bd879dbc613,0x00067c19587966a7,0x0002fdcaec3c6f44,0x0000f61ae7f6b03a}, {0x000e1fad21564449,0x0002c030664334ba,0x000c37cd03a60116,0x0003c2589ba1879d,0x0000869a09a56a80}}, {{0x000ca054eff5af2f,0x000c2afeb00c909e,0x00030409f4f95238,0x00042f33519755ec,0x0000a031194f7bc2}, {0x0002d9d860515c64,0x000282b7c41b8262,0x000d58ae84b75001,0x00033911d917c2ec,0x0000382de3015dad}}, {{0x000b6f92039287b2,0x000424f610648a17,0x000f670c6adaa03e,0x0005ebcc4155c96c,0x00008a428fdd5ded}, {0x000dc8bef29ae895,0x000feb853aa156db,0x000d58735fdd8c1d,0x0008ef18dbe67090,0x00005223ae90f12f}}, {{0x000da0a305e720fa,0x000a9efc2a6ba83f,0x0009bb0d2d9ee4f0,0x000f424f84963425,0x000028fb31a147c9}, {0x0007a129692f9dca,0x0002c69d8dbf3308,0x0004070a2d33c240,0x000e53497ed09a9d,0x000056c1a642f857}}, {{0x000fea20ff9207e7,0x000cdcba65125a16,0x00026ad2a6c19e9f,0x000dc711f4cf52db,0x000097fefb6bc4e8}, {0x000a94c4f27e69b5,0x000570e2212029fe,0x00031e5f3eb7feca,0x0005eb519c7da3b5,0x00007bb88afb91d0}}, {{0x000a7012729021cb,0x000f25e2a3025023,0x000308907678c8f1,0x0003c3d53c45e204,0x0000ef510928bb4b}, {0x0002e7148c22ff2d,0x0008709b3aeae6c4,0x0007356abf6dcc9d,0x0005788d1b63fe8c,0x00009e378edf3940}}, {{0x000ddeb357d98af5,0x0001e85a4558478c,0x00080a0cbd7e0c6a,0x0001dd3ddac79b65,0x0000056d8d40a6df}, {0x00091ba3a685470f,0x000a930cac5404b8,0x00005c3833644e17,0x0003a3e93f00d595,0x00008ff0d37e4337}}, {{0x000882736c20485a,0x00008eebd8ed436b,0x00008765d62ca0ee,0x000eb404c1e6a63c,0x00001f51c3d2f4c5}, {0x0001dead0e0240b4,0x0005dc01cee53aaf,0x000ff1626340c23c,0x000eeab99ab3c4fb,0x00001c9f03e31c0c}}, {{0x000ae756a6906fad,0x00063f4f9ceccc4a,0x000097866d772f72,0x00049ade04e7abe4,0x0000daaa2d4ec655}, {0x000f24569a5e1b2d,0x000cf346e0eedaf7,0x000077bb20e192c6,0x0002e1123812eec0,0x000043676cdfbb9b}}, {{0x00058d8a85049646,0x000da101751a9416,0x0004052f48e7403b,0x00083e451d1f0c3c,0x000099b66e6f5e43}, {0x00099f641750313c,0x00052d7eb737c5b3,0x000781bc1f3ec6ea,0x0000d8f06b519c58,0x0000207bc899b604}}, {{0x0008f806abe9cc03,0x0000a9a929601fb3,0x00009bbbf082d14e,0x0002f8208e30f142,0x0000554af3ba8279}, {0x0007f63f5b712db0,0x000f5e6bec6bc64b,0x00064a6500c0f15b,0x000c133fac18ffe8,0x0000426e543866c0}}, {{0x0009d4ef17dca9b7,0x000a30ed49144714,0x000b7c7c7ff66bc6,0x00050b6f85c5627e,0x00001b5beb731ddf}, {0x0006b5a5059abd38,0x000239a4d95c865e,0x000fcce6a4320b87,0x000f54de8482cded,0x00004902e9c46a14}}, {{0x000b7856664976a7,0x00078969c15376b1,0x00040ec0985a2ed7,0x000c001d865d85f0,0x0000f36fd193022a}, {0x0005392113e30f9c,0x0009f74dd0ed247a,0x0005828f69efb3ea,0x000a340b38e8b204,0x0000360f51bc06b3}}, {{0x00080676229e895d,0x000b73902cd1daa3,0x00033ab334e9238b,0x000898af084a55e4,0x0000ad12d95a215d}, {0x0009537f56338b7b,0x0006b9ccc450a222,0x00005543a3bcfda1,0x000c3e65d49dd006,0x00007bfd6c4ca559}}, {{0x0004e97c95dade65,0x000a255cb184c7af,0x0001913f02135561,0x000dacc6ec185432,0x0000c67073eac645}, {0x0006dbb0217a30c4,0x000ff3ddda1e0927,0x0001ccae8f3399c2,0x000457eca9825683,0x00009678071934aa}}, {{0x0001b26feb7180b0,0x0003efd985904aad,0x000b49ff165faabd,0x0001d381a30fea11,0x0000c5c8356509ff}, {0x00001e0aa66f02a5,0x000536ad9cf84113,0x000abbdc628e871a,0x000d020376aaac57,0x0000a1378acc9219}}, {{0x000d95e7668e901f,0x000060472569120d,0x000fc85db23dc73c,0x000aa6886846b97d,0x0000132a04ded861}, {0x000d5373fb18ede0,0x0004a57df5ac83b6,0x000da2aea92385a7,0x00022238fd2cc831,0x00002fe0eb0e035e}}, {{0x00024cd9846e4d56,0x000a4f069d729131,0x0001f60df8dab9fc,0x000503b97c211a7a,0x000006e35fac3fa2}, {0x0003c474bc694434,0x00075c5dfd89e498,0x00042a47aa5934ee,0x000302b62af4f70a,0x00001298623271cc}}, }, { /* digit=27 [{1,2,3,..,}]*([2^189]*G) */ {{0x0001b9cf1fff1383,0x0002e979256fd16d,0x000024e5cabb7109,0x000174971f93d488,0x0000f4a50d323ce2}, {0x00069687a5e60329,0x00035725ef1c291b,0x000d78bd756a79e4,0x000d4bb336a131fa,0x0000a42d2de19780}}, {{0x0000770b1fd77c42,0x00073832340c46a0,0x0008fa3e971dd6ac,0x00055cfef494e03a,0x0000a4bd01ea78ff}, {0x000549569ec3b61c,0x0009fab41b9cb0b0,0x00085d069aee9d31,0x0005df668e37395d,0x0000222a186cd468}}, {{0x0009034839af8af4,0x00043f6fb866f9e9,0x000b3d4bd58c9dea,0x000f06eb6869dd3b,0x000070c089100bba}, {0x00084c12d0fa30f3,0x00063a684ef0b7b3,0x000c5e098f27fa26,0x00008ba673334a74,0x0000febfadaaed70}}, {{0x0004aabd136b85c6,0x000e5936fc61535e,0x000d5983d0ba7b67,0x000ed94d56bc23ae,0x0000fafa92939d12}, {0x0005ed1e9964a345,0x0001980b9f13e261,0x000c2d91983b5b76,0x0007686f1cf68c47,0x000002a1721de2ca}}, {{0x0003d97f0a373569,0x0009541867b5c615,0x0002be69e5b1a6cf,0x000d318011508202,0x0000616a3fc9c362}, {0x000f8fb5bc1d92d7,0x000014a7ecae4920,0x000a07c0dbe70008,0x000136174fb9a821,0x00004a51fb854142}}, {{0x00094501f646ae21,0x00093a3042a9aa65,0x000c3d31b80e7d9c,0x000f2a8addb71e1f,0x0000e4b00409743c}, {0x000cfea457fca237,0x000419bd5f99c642,0x000c9c750bb14dcf,0x000201a965cbd91a,0x000003a84781aab2}}, {{0x000fc80219d626fa,0x0003948b0d1fdda0,0x0006db88bb4e6b39,0x000ff4f7b88d70b8,0x00003574172195ac}, {0x000d5e56f3d1172c,0x0002cead1829e0f5,0x000565f4996ea68d,0x000bab6b497081b3,0x0000f563edef0941}}, {{0x00052442b55502c1,0x00010eecb291d39d,0x0005128fee4d7b18,0x0007125122549f56,0x0000056059074287}, {0x000a0909597c6015,0x00008af2773cc6e7,0x000b42443316a926,0x0006dec8c5b194f0,0x000077ea1102d890}}, {{0x00069a576212f358,0x000506a394e93535,0x0009b22ea1ceb350,0x0000677ead07678a,0x00005b082f491db8}, {0x0004a81bf9ec1ad2,0x00071aee7ba0c916,0x0004e80a1337bc58,0x000abdbd5c577480,0x00000fc252a5dd59}}, {{0x000a054c1e13f877,0x0003dcc6b450cabd,0x000d3144e7b6b2ae,0x000ed4c39ca22c31,0x0000f9567c38732a}, {0x00084e2f2344d0aa,0x000ec5ad8d221d7b,0x000e1a873a63bb2f,0x0009666a6747d67c,0x0000358844479c6b}}, {{0x0007d2edba4a511e,0x000f2f775e00973e,0x0006cd11f44770c8,0x000bfe41e571cfc7,0x000075b695fd8542}, {0x00006e872fba8b1e,0x000e6a6534ab0dc0,0x000f0febaa07564a,0x00029bcfde2d885e,0x000025ff3bd3db13}}, {{0x000f42c3d41c8e40,0x00027896206e317b,0x000581e8807e38f9,0x00072dbb1ab849ed,0x00008c003afb741e}, {0x000b05a75a716b03,0x000c35acc098339f,0x0006bb409efb624e,0x00044ea061fe93db,0x0000639c1c4896a9}}, {{0x0005df2305ee4c95,0x000fb06813dbe2b0,0x000f5f222f613984,0x000e07b842f57781,0x000029d555fdb379}, {0x00085c8602f378f1,0x00078c23e6a3833d,0x000b5d0c4a1b72cb,0x000d5feb45473e34,0x0000db9aac6b4203}}, {{0x0004b65361be7b6a,0x0002f2fb6b49ee6b,0x000913c64c9b2f8f,0x000d30a7c4338ec9,0x0000f69135ef57dd}, {0x000249afd7bdd274,0x000d7c213f9526e6,0x000247857a28573d,0x0005a9aaa2885378,0x0000cb194be632fd}}, {{0x000c83d371b3f5e8,0x000cb5a067330a04,0x0001dc3a2fef33cc,0x000b187549f824ec,0x000091fb8cc00b56}, {0x0005b558729aa3fe,0x000dcc9c90c35486,0x000ebaa7ccca0c6a,0x00040c03f91930e5,0x0000d41e9d7170af}}, {{0x000369c517263725,0x000f5b9c4d8f25e2,0x000af08d2fb833d3,0x000dfff4079aaa6e,0x00007b1dbc5eff3e}, {0x00095ef86114ccdf,0x000218447b952ff6,0x00028ac9591e2d52,0x00061a5f9065e821,0x00005b37299373e7}}, {{0x0006de0bbde89cb9,0x000178894e0dfd48,0x00099f1f42306512,0x0005ae303a17d3a6,0x0000e98f7a864629}, {0x000854fd72db1c36,0x00018599b7d0f8ec,0x00067d94864ff03b,0x000a9a11c827deba,0x0000e7fc586d6b42}}, {{0x0003905c60a37318,0x00020e672390fffd,0x000cc82bc8f9ef8c,0x0009dd202cb0dc17,0x00004b4757605370}, {0x000bd76d355ffa78,0x00062640c3b569ce,0x000d7be663352441,0x000fa5cc00063e7a,0x000041ec6b307eff}}, {{0x0003445ff1d4f48d,0x00019ad186af8290,0x0003ec32546962ff,0x000c74bee7a65ffd,0x0000f3c5bfad6d70}, {0x0002af7a0d407d12,0x0003b49a55ee5914,0x000e67fde3d1641a,0x00017386bd678d4a,0x00006a7789b10f86}}, {{0x000279671048d213,0x000fbf93af1c754a,0x0005ef03eed832a3,0x000166c4c086a7ec,0x00002ce472c668aa}, {0x00083e191dfa1fef,0x0001f9f62e555da2,0x00033e09245f9681,0x000834d7128c2232,0x00005980492cfaa4}}, {{0x00005ed385c6f58d,0x0001e940322f855b,0x000abd1bdfe12344,0x000560254323ce5d,0x00003f3272b8e138}, {0x00091b1129ec9aef,0x000937dae4ab0926,0x0003b89972cd1064,0x000feb302abe5ff3,0x0000ac9ab092ccdb}}, {{0x000ab8834fcbe7cb,0x00079a36285466b2,0x00021763ddf9573a,0x00087f23dd49e9d1,0x0000960a7dc34467}, {0x00024b2027d5087d,0x0008789865adccc4,0x0009d56dc06f79cb,0x0001e483a7a6349e,0x0000439526bf4c6c}}, {{0x000850573c100bd9,0x000e92a154270a32,0x0002c03764947229,0x0001b3abcb8d85d4,0x0000c6b864e12fb5}, {0x00099a63a0948b0b,0x0003d11e7737521b,0x000f11ee54cc22bd,0x000c0f3897c28fe9,0x0000887a86105810}}, {{0x000e64b613b901f0,0x00020b63d0cf3e5a,0x0000509aed92b157,0x000a4af71b397af8,0x00000f70a508ac7d}, {0x000443b477982ac4,0x0007bfcf80070119,0x0000ee5d52ca6ab5,0x0000fb76fea256a7,0x00001425f8a18955}}, {{0x0002520e8f5fdd9a,0x0004415b44379a62,0x00013a5cfb245513,0x0007ff26da58b6c6,0x0000c62c15ae2094}, {0x000a325e4261f9e4,0x0006f038d32e2ef0,0x000ef3fc6abc70f6,0x000e30d93ea52afe,0x0000eebb6abb94e6}}, {{0x0000247702ed7bce,0x00034f5464e44269,0x0009e8b128e5bb85,0x00080926518e624b,0x00002be136277a21}, {0x000471e16b34ec34,0x00012108d0ce4dbc,0x00009af5e6abb920,0x0002e754d17d1efb,0x00008a48cc1afe3e}}, {{0x000e0422139c98e7,0x00020a9fb3a64484,0x000e10ede0bcc79d,0x0005a6dc2fa5ba99,0x0000ef0d52b0fc6c}, {0x00063d55b1d96541,0x0009f6d4c86785fe,0x0000eb9acfac3d5f,0x000572a8f2469101,0x0000dcb464d4523f}}, {{0x0004f69a1b9f6cfb,0x000ce213f5056161,0x0008b7d48946501e,0x000149f12d547fe0,0x0000445a285c7f6a}, {0x000c4823f1a2ea23,0x0001385a5394c778,0x0001c1b9366acedc,0x000ab1c3ad0d81be,0x0000a11359b3675e}}, {{0x000fad96e9cd5888,0x000b7a1e29d6289d,0x000c4b2381c4c5f0,0x000230ec1a276eae,0x0000dbfa685019cc}, {0x000f4922efdee4bc,0x00075cf61a1c6547,0x000edaf4fae86ec1,0x000804a8d53bbe31,0x0000fd5e6fb848cf}}, {{0x000990f9e61819db,0x000a087bf284d04e,0x00046cc595c29ec5,0x000d285ade5df61f,0x00004427bdb3cd77}, {0x000aa52009715323,0x00064ee140eb5a6f,0x0007110a230db79a,0x0005beabf7fc498a,0x00005a15127fb48e}}, {{0x0007b770b5f6a321,0x000f362ee591d72d,0x000bf83136cbb8cd,0x00084a2589241c8a,0x00004ee648e03895}, {0x000bb8cbdefa6e1f,0x00067c4e78df9a78,0x0002e73ca978976c,0x0001b28eef0426bd,0x0000de8fdba87229}}, {{0x000066e356b5ba28,0x00042d6df6f58037,0x00011deaf6527ec0,0x000997dd3caa6655,0x0000dea9d72a1583}, {0x00071e5d50786fae,0x000acede2fe32d7f,0x0001c5ebbc758eac,0x00052ae508ead45d,0x0000105b61fc2cd2}}, {{0x000a424820880205,0x000253ccc5077e5f,0x000f8c3fe20dc632,0x00062cc0c59b343a,0x0000155e23d52734}, {0x000ac65688011857,0x0001b16ae629218e,0x000d6756f09ff09a,0x0005fb7b7fd5fd37,0x000039a7040ebf80}}, {{0x0003f9fc60cc69b0,0x000dc05b085eb973,0x0006e237d7c4ee9f,0x000c1aa988f662dd,0x00001d5d34fe8760}, {0x00031c971d36ad9a,0x00021af6097f9cda,0x000a112b99050a85,0x000760dd5b19501f,0x00004b8f2b2a3525}}, {{0x00023daebb9c4933,0x00067f5f980754fd,0x00044b040f42405c,0x000cf1365bb83ea9,0x0000607651d34cdf}, {0x000cd8bdf6af7f24,0x0009f667d24992b6,0x000fdb2cba8a3b43,0x000216082779e2aa,0x000088707ba1c834}}, {{0x000625373378cf7a,0x0006fbf97109acf9,0x0002a22d6e706614,0x0003b2b54dde5fc2,0x00007e3dc99d87cb}, {0x000e1cd88864bc14,0x00094f0b89418e8a,0x000a64fc194c02ee,0x0006b75b5f046f5a,0x0000bd2c8c6b65ac}}, {{0x0002c8cf2c1c71b8,0x00034ba2d46ae80e,0x0005f7bfd38ee996,0x000b7c07f17b75fa,0x0000c9cda0385190}, {0x000ab3a305fb5758,0x000f9bedaa65e5b5,0x0002fd3ce5ea38ea,0x000693fb2d8b1c01,0x00000024b4599946}}, {{0x000b3720ed0dfde1,0x000d03618777a3f3,0x0001f1f7a5cb0edf,0x000e6286b75f35df,0x0000463e61ef6663}, {0x000b207d0b79891f,0x000bc03f51f18bec,0x00045012b8dadaea,0x0000ea4f5238c4d9,0x0000e7374d260339}}, {{0x000b9cdebf558d6e,0x000a7fe8cd19b8fc,0x000466552cced26d,0x0007ab4a23901802,0x00007cffa718628b}, {0x000bbebacd192e54,0x000631e137725179,0x0003765188e7a414,0x000a907dbaadfd47,0x00002b4be3e6d8da}}, {{0x00094dd9e1077a92,0x000ff54da5dfa25d,0x000275244547d0a6,0x000af9942339905e,0x00001db13a32ed62}, {0x0009e8b2ff2ea6f0,0x000ccdb7c81f268b,0x000c0b9228169c5b,0x00091f33ef28ab69,0x000063fd42c2ea96}}, {{0x00026bdfdc8fe7b7,0x00006cf1c07e97d3,0x000cadbd9a6a9283,0x0002d6bf51c2ba05,0x0000b8cb99a356d3}, {0x000ae7bb14928177,0x000b0e246da65b16,0x0004b026ae4c5b8e,0x000f61a66781bfd3,0x0000dbdfa283ad1e}}, {{0x00056863c55d6206,0x0008826bbed476aa,0x0000f81fe2cd68ff,0x00028ab98204a548,0x0000057156e622a3}, {0x0005fd89b91e90fe,0x0003deeafbbf9bdc,0x00098a9587ab8014,0x0002738fcf98e3f5,0x0000b981ec89c6f5}}, {{0x000b316827a46307,0x000a300d18683649,0x000f2fa071726038,0x000d3794466aabaa,0x00003b21867de806}, {0x000d2944b3ec91e9,0x000fdf4baecce9b4,0x000c417b42945b46,0x000aa79fdb7f35bb,0x00003a9f897a4e64}}, {{0x0005a34d2eebeba1,0x000e6afd5bc4437f,0x000b456c7dd1b3d2,0x000b4153b76695e9,0x00003307619aebbc}, {0x000956bb3e38fdd6,0x0000426ed87648e5,0x0005f711ecd8c046,0x000079d6d63de859,0x0000dbf4b9f107da}}, {{0x0007e175ead15d39,0x000561b4f3f83c33,0x00011b177a1402ec,0x000a58752be2a08d,0x00000da4d4e2fe92}, {0x000e6e8276401658,0x00032d6c4199ae4a,0x0001faba2e498fdd,0x00014b1af4332ef3,0x00005ba35a81c223}}, {{0x000649050769b34f,0x00083bfbb56c5761,0x00021ee2541366b4,0x0008704cdec9bb64,0x0000d7945159c0d3}, {0x0008bafaf13e0aea,0x00036e13e82d5eb7,0x000339761f9d8d47,0x0009eca4591e67dd,0x0000d96c07568a95}}, {{0x0003d5fd2029df76,0x000a5fb33c0e0f3c,0x0001ff5fc68759f4,0x00051f621da14b63,0x00003caa71b11ccb}, {0x0007c30a7e617c2a,0x0009b711ffee663b,0x000759b3ba8a1266,0x0007f0dc13775b68,0x00007e1383f3a56c}}, {{0x0002e53bb23c1e0e,0x00092de4f81808c0,0x000027ce8893cbad,0x0000f3ec1a375761,0x000021cb492d2c4f}, {0x000aa3245f82dbb4,0x00069cced42a6e8c,0x000b6d15012948dc,0x000fb237260c2eac,0x0000ea4c9c423931}}, {{0x000296fd70720795,0x000229b349f0d757,0x000372c7ecdb2d87,0x0000ab683986a30a,0x00008eebfefdf917}, {0x0007b20676f23d23,0x0001b68216600cd4,0x000d60209e8a6542,0x00056e7d5a86ec0d,0x00000dcc35fe04cd}}, {{0x0003bd54c9a586b6,0x000b8854c7485039,0x0005a40f4ec5f1bd,0x000289a4e41a1f76,0x000049dafe50ee7f}, {0x000fd6e34d712730,0x00053fcc6922c67f,0x0006083c963c85d5,0x000ce0b410b01af9,0x0000bcb42a6ffe90}}, {{0x000b767ca282a4d0,0x00020bd980476c87,0x000bfbe1aabbbaaf,0x000b88e6d7f7cc73,0x0000b94422c7d82d}, {0x0008f139b5e18b15,0x000af37294afe4be,0x00004cff3264b3dc,0x000c73112544433a,0x00005a6007937b5b}}, {{0x0004af8e5428d95b,0x00010191ac710f35,0x0007cbedd6b7a565,0x000b814d7e43f856,0x00001c5e2eb7d556}, {0x000fcff49a2a7cf6,0x00072f558310e77c,0x00038dd2bc421df3,0x000a70595301fb38,0x000070f7e2a9b2d2}}, {{0x00078d66e9dbffa4,0x000fd8c7ca048a86,0x0007e3eda5c2456e,0x000dfc3b87b2b93c,0x00008309da1e8c6d}, {0x000d753512b919a2,0x000af02b49c6907b,0x00097e34d80b0b22,0x000116caf4066684,0x0000a329ce0d5c8e}}, {{0x00018e79cbc3d261,0x0005c013dcb21798,0x0002b229899226c7,0x000ec7a427d40e6e,0x00009be63696ee9d}, {0x0002ca736795eca8,0x000ab6fbe78de343,0x000bd2519b13a095,0x000f556bca40cafe,0x0000db7209b1f081}}, {{0x00073c09004f67ac,0x000b29108a8f67d1,0x000d371b9f9fcb0c,0x0007a067e6fb34ba,0x00007b352a5eff65}, {0x0004bcafc8686e3b,0x0009f001e6a411ec,0x000e8fb4225c8102,0x0006a982156a2ca9,0x0000d80803a38166}}, {{0x000da2e4dabb9727,0x000355d6f6b308ba,0x000f1255aae1bef5,0x0001611794716339,0x00007b4e604aae5b}, {0x000972e788159151,0x000fa3d326703740,0x00098bc1191d5969,0x00078a0d4a378bf7,0x00006a59fa849d24}}, {{0x0000fa58dc098923,0x000a1856964a0842,0x0006b9932f4e037c,0x000814ca2cabcd97,0x000078dcf9cd7aba}, {0x000a197dc3eebe13,0x00042e556e9988d9,0x000157e412bf69e5,0x0009df4f48dcf986,0x00003aded6912caa}}, {{0x00084e2f15edb89d,0x000ca9cc6e956412,0x00012680b1917ab9,0x0006783f51439caf,0x00005d29d2d26dd3}, {0x000ab0638623d5b5,0x000fed329f9f8df8,0x000792dc163a5fd0,0x000655955e82993f,0x000069608a1e7223}}, {{0x00050665c639e317,0x0007cd3a0be23b31,0x000d42c79903f0b3,0x0002c444001375bb,0x0000929d6d962097}, {0x000772643d922771,0x000edf18c8218c66,0x000ac87392e06af9,0x0002719c1204c4eb,0x0000d70ae05eaaac}}, {{0x000b98d73f6132c3,0x0002d06ff3aa0dea,0x000114d3850749fa,0x0007044ffa876d9b,0x0000f45872e2fb66}, {0x00016ce3d2f5b6fd,0x0001dbce4a5c1e39,0x00023420be2346fc,0x000ad2073526e3aa,0x0000ec42bf82e3b4}}, {{0x000a0e0400250d20,0x00073477185ee8db,0x00076add835f002a,0x000b3b5382a489fd,0x0000bee501d59ba8}, {0x000f808fc2a3269f,0x0005a1a324483855,0x0004b0561e253e07,0x0006877e92305edd,0x0000fe56709ccee3}}, {{0x000c69fd4d6e9ddc,0x0001efe17ab5ebee,0x000e8772fcc9e90c,0x00075476218c92d3,0x000034d8fe876b89}, {0x0009a53714b3d5de,0x000392d52e8cffab,0x000f9a84a7982c75,0x000969339421caf1,0x0000be235f473bd7}}, {{0x0004db392168c345,0x000a7d3a892289ad,0x0001c36832b48c85,0x000ed9a7ee4e9c5f,0x0000c04e75e82317}, {0x0001be0108fab1b2,0x000295b25288526c,0x000465a6858de779,0x00095b9a8e5cb36a,0x000089a16a0405f4}}, {{0x0004dfd0a2e212af,0x00036b8548f44a8d,0x0000661b76948703,0x0005acf11a3d8f18,0x00001c00c194d622}, {0x000d5c1f47b27588,0x0009b03b8c767f30,0x000cb8a097b7b205,0x000c759ac3acc6de,0x0000805e35066db9}}, }, { /* digit=28 [{1,2,3,..,}]*([2^196]*G) */ {{0x000c38a2a1d9a703,0x00081b56c40e7912,0x000dd8e69ee22588,0x0002cd3934da3f86,0x00009ea1c46f7d16}, {0x000bbb8bb266d6f5,0x0008f24907c529d6,0x000f29a7ebd75276,0x0002d5547c914e08,0x00001c5ef3df3449}}, {{0x000a76cc5116d7af,0x000eadafba1a14c1,0x00024709cc081b48,0x00081c7e2a466abb,0x00008b57f0616a3e}, {0x000f956ec6c161e4,0x00000fb95d4f3aeb,0x00097cb468593666,0x000bf252520b3955,0x0000ed97cbc6ae5f}}, {{0x00086b91a9173051,0x0002f80999c69a5e,0x000310070a4efd46,0x000f45d8957ef5bd,0x00007ce05888474d}, {0x000f95d561b01a26,0x0009d0c4e3c33152,0x0006abee75a4662f,0x00001c4bce657471,0x00009c915c04da63}}, {{0x0003fced8aa40761,0x000b87e4ac77d3d7,0x0005ac612e5b0c4c,0x000de0d7711889b3,0x0000d21f2a009398}, {0x00066281b56378cd,0x00067c47fa3c2881,0x000dd18a00054474,0x00087c02c8db20bd,0x0000cff165d7702b}}, {{0x000b9efc0d760cf6,0x00050c278d0980c9,0x00007feafd3862e1,0x000aa3eb68afab38,0x0000647da2895fe4}, {0x000f70e5bbb84fbf,0x000d1eef05b4940e,0x0004b7c6fbbfd8cf,0x000db93150f3a4b6,0x0000b3e4f8d0efd5}}, {{0x0005488239f8e105,0x00014cfadc9e08bb,0x0008dc975fdc87d6,0x000be3c9a3d0798e,0x000016550e4b2cc2}, {0x00023a4e3abd5d4c,0x000b906da2001e44,0x000060bc93fedeb4,0x000093dc27fd9104,0x00004cd7ca88713b}}, {{0x000fbf542fa80e44,0x0005f10928bc0a3f,0x0006293cef2e8b64,0x000a898509b32c4e,0x0000b22619841e62}, {0x0007f5cec0217b2b,0x0001d20d8159ff53,0x0004247eb95b2102,0x000f96a510270434,0x000007a5eaff6c63}}, {{0x0004d031f8bb00dc,0x000b5e02bac4ddc4,0x0000aed50c213344,0x000e05b337dca4b1,0x0000c86350c6fcad}, {0x000a47ddf9ce7cad,0x000feacff71799c2,0x000bb0df8204bce3,0x000e5f8261e40571,0x0000e0c599f1adf0}}, {{0x0001b1bb94f507fc,0x000b0e3b80fd0544,0x000d3472c146d60f,0x00084fae8223732d,0x0000101a1e7f36e2}, {0x000e5e9e34bd1816,0x000f545cc7b24119,0x000d9ddc782a4857,0x0003d7ca719e13d3,0x0000d9522fd316f2}}, {{0x0007bed302860d5b,0x000b5abd9969e2fc,0x0005b5076fa90a70,0x000ea613dd5e38e8,0x0000f8c38f07a470}, {0x0003fd5e928fd844,0x0008d2c777f94dbe,0x000e5e8ee0421bb0,0x00090b66f1472441,0x0000b3088fcb535a}}, {{0x000e1ae7289c2895,0x00025afe82ac1535,0x000bdff2cd902878,0x000f4ef1b8d241de,0x00004fb71fcc98fa}, {0x0004222f68f44d53,0x0002c233b26fdb58,0x00075ebee32eda92,0x000808e057bccbe0,0x0000e4465cfeab5b}}, {{0x000dfdcd833d339a,0x00020e7a389e4f2b,0x000d23683025a3a7,0x00035da3027d310d,0x0000fdf534e8caad}, {0x000c3671c7931bc6,0x000295770ef2045c,0x0000c060bf62b8ca,0x0000be1c0672ffae,0x00003930a309702d}}, {{0x0001923fdb3e29eb,0x0001b817d72ab678,0x000b46b1a5f7f642,0x00070769c8c3e584,0x0000d0238e461de5}, {0x000c2ab9f826b572,0x000076be5f5577c6,0x00026baf39420c61,0x000bfa2c745c1765,0x00008bee5c5cf98c}}, {{0x000b34e1ffbd4f2a,0x000747c36e6384e6,0x000188caf2580fc4,0x000021a1cc113e97,0x0000166f801bb0a2}, {0x000ee689dc2b83c4,0x000fc7170038b4d4,0x00020d913b44f23a,0x0006f4916eaa0f95,0x0000a37abc373fb5}}, {{0x0008e478edbc9edb,0x000b6cdbf59f53be,0x0007bc01ef6645bc,0x00030d7b078b0e6d,0x000048412e9378f1}, {0x0002f15c532138a7,0x000dc14eed557fb9,0x000c77fae6fb3f15,0x0001ec558fe1463a,0x0000f318b95338a1}}, {{0x000b7438e5468e71,0x000caedffb29bb1f,0x0002ff19da1a8652,0x000de068d72097f2,0x00007621c88c8098}, {0x00078d98bb33eb05,0x000422f044eced99,0x000e8c4b19e1266e,0x000800261d9ad034,0x00000d3bbc0defd4}}, {{0x000b6e60f54419ae,0x000b6eca8a0201c6,0x0007bd20f02e3c59,0x000f848a270d2b43,0x00006c057044b677}, {0x00047dc47384cc81,0x0003e307e3f7012d,0x000f9a650ee8e3f4,0x0009500539cdb1a6,0x000072f13befc47a}}, {{0x0007e2ac62f29ecc,0x000c7076b6aa4df4,0x0008c07b37559318,0x00062001974448d9,0x00008a44c6309b81}, {0x000e2de6bcf14f8a,0x000f4990ab063f22,0x0004697a9bbec1c2,0x00030cecea565c48,0x0000fd3da1c5e5d8}}, {{0x000aabb0b18a6f6d,0x000e3c002fa1b7dc,0x000818bf3e956799,0x000cb0a09f9d8ac6,0x00004c37af29089f}, {0x000975ede76d2691,0x0000edc449b75047,0x00054acd30477815,0x000fff298f1059ac,0x00007ac93c57a2ee}}, {{0x000b8d64baf52f42,0x000b09a3292f23a0,0x000456c047f3f84b,0x000fc353ae21c75e,0x0000110967ba5ea7}, {0x000db604a4420675,0x0000bc0332e07024,0x000f18635c4ebf20,0x000ecf2e0f788c83,0x000050d2e58fb836}}, {{0x000c9678e5433b08,0x00070837189e593c,0x000f524cd351331b,0x000d2130907177b5,0x000027851eca7500}, {0x0004709b248eca72,0x000a87322fbb36f3,0x0009e73d0e54945e,0x00023d52f940920a,0x00005827d8bfa825}}, {{0x000b019bac0eecc0,0x000cc707f8790281,0x0004e858045722f8,0x000538e7e32b5f38,0x0000c291610a5aee}, {0x000c51ee868e43d1,0x0000b754959a25fb,0x000f424af9289eaf,0x00069ecaf0bb54a6,0x0000923b39262f9a}}, {{0x000eb037fabec5a2,0x000f5113b5f773df,0x00015a54ebc1d2d4,0x000181f233f0f51b,0x0000fe807bffeb66}, {0x00046d05b62ce294,0x00098d67cf9c5ed1,0x000a8fc4e5cef5ef,0x000aadad520b5c8e,0x00007039215094ef}}, {{0x000a1db4a22af952,0x000cb9edece623c4,0x000366394458ac70,0x0001dfb057f7a0ae,0x00001fe7a1fbcf33}, {0x000d7cf370fe2a14,0x0005732e78fb4925,0x00055e87c37f393a,0x00011bffd64640e5,0x0000ec4a5ddbe8c0}}, {{0x0004d4d3a17880f7,0x000daa8f972e8527,0x000d1a6e2ec1bea4,0x000c27636300963b,0x0000efe1ddeeeed6}, {0x0004f3e8c69f40b8,0x0000b1029582dbbf,0x000af32882bd8807,0x0000a6c9827573a8,0x00007105abfc154b}}, {{0x0002a5c62b9097eb,0x0008d4989c3a69bd,0x000c39b3112f1d05,0x0000d73bfed8eb5d,0x0000a4dd7028190d}, {0x000df21e7c9ea92c,0x000cb9a2427202b9,0x00055d8cf2e18cf8,0x00000d9225aa33bc,0x000093d58b32465e}}, {{0x00056d7e3c7e81fc,0x00063f455beb34d8,0x00041bac0617ff16,0x000d390004aab0d3,0x000066a594a7db36}, {0x000674ef21314c13,0x000cd499799bff44,0x000674e5b127989b,0x0006f3d0eac3e533,0x0000475033eb386f}}, {{0x0003be03f488b066,0x000afe3e2458f80e,0x000cbb0ca9c1df72,0x00032d854724a756,0x0000f294d9ced004}, {0x00099d4fed7a8bf1,0x0000a3d4dc031bbf,0x00098fe4b4fa6535,0x000d3d62a156b316,0x000061c892ad39b5}}, {{0x00057062dd51b0e3,0x000fb0b6ede2e44a,0x0009b84b4bb2e66b,0x0003892b535e65bf,0x0000f04bbbd4cfae}, {0x000e254b0efecf74,0x000c7b425efa6f99,0x0006fc1223cb5014,0x000ed3775dda3b47,0x00007d91e4176c7b}}, {{0x0001e11238f17189,0x00055477448462ca,0x00076d1ca907db73,0x000957e211b110df,0x00009f00d6031218}, {0x0008148bbf09b400,0x00081c3bb9e89771,0x0008b25f9e1f66b9,0x0003658ee958d873,0x00008ea2bc754377}}, {{0x00040ec2f8b18d2b,0x0005720588c7874c,0x00012febf68a4ccf,0x0000ad74cc5bc416,0x0000c0cd6c894bb8}, {0x000a5770732df031,0x0009df7b0dec4b86,0x000bf3c40616b170,0x000ad41d43d29a1c,0x0000eb2874f42570}}, {{0x00075fff53df8b53,0x00080ad93ea9fdeb,0x00094201518d77bf,0x0007e5c4c968a760,0x0000623567d0a637}, {0x000b5f86a4738b2d,0x000027189c03c512,0x00071bad6653470f,0x0007c87146d1d64f,0x0000a1a59a4469af}}, {{0x000b514e53719c74,0x0004263a91d246bf,0x00026ec908be45b4,0x00047bf0842913d7,0x0000b483a7ba011e}, {0x000411dadfaf9c39,0x0005f75f1a475043,0x0000622a4242b2a6,0x00076430694e65b7,0x0000cb0de0487bd5}}, {{0x000a48d97cccb4f8,0x000039d242ee958b,0x0007a2d265fc7e92,0x0004f9b0346ee66d,0x0000ae6d9eccb1ec}, {0x00071cb876b50704,0x000b3a208b80528c,0x000e466e83bea7e3,0x000f09d38293ce87,0x0000f7bc81782076}}, {{0x000cc15e3a833811,0x00027d31aa50385b,0x000d0e82633ec551,0x000ec7922987876d,0x000070d03a64f875}, {0x000cfaf5650d15f6,0x0003473ac211140c,0x000c98877e0f73f0,0x000c08a75c5c482d,0x0000622d09e823c7}}, {{0x0000b7e8cbf9ba79,0x000cd6e710efc7c9,0x00077ce47b6bd4ab,0x000960be8ff09b54,0x00004e8f8dbc6cc5}, {0x00021368a1283c7b,0x000f518b32eb7e5c,0x000cbf5b162623fa,0x000005dbef4d2e43,0x000088b15fa01ecb}}, {{0x0000073cbb4b6ec4,0x000b0a7babe5c5c5,0x000fe549f4ecc335,0x0008c322d1e8f812,0x0000c49af93d1581}, {0x0002b2e39f0417cf,0x0003d9808a14c3e1,0x00017386e20adee0,0x000690f7522d1fa4,0x0000be41fb5f632d}}, {{0x000d671707701933,0x000297bc3160d8f6,0x000cd76c64b8a53c,0x000dd64e0e6d9406,0x000034d74fce765d}, {0x000daf8269a471c5,0x00075ff07d0520f0,0x0007f32fb264506f,0x000b4a0a95e8f527,0x00009abfb62dfbd9}}, {{0x00005b5fd8e98e12,0x000e14ad70cc06de,0x0008fa21ed10a09e,0x000d8d84fd47afe8,0x0000d6f824d23bd3}, {0x000baae0dd9c557e,0x000ad65982a3dbde,0x00009c77a82ec43d,0x0005bf745e0fa843,0x00003f0eeb6c0fc7}}, {{0x00088e490854a78d,0x00018930eadc94c0,0x0006910aa320ffac,0x0000a278a57e2f16,0x000051dd5b2d1423}, {0x00005547cd73a6e7,0x000cfd1d02fc869d,0x000428efc74b6a1e,0x0001e7c08394445e,0x00004579b6ee7a03}}, {{0x00024c9bcf01037b,0x0009474916aabed7,0x0000d51d09748fda,0x000cd6db5cd430b8,0x0000dfdeb4fdd00d}, {0x000893bdeed91a80,0x000f120778a2597c,0x000058a2e837a8e0,0x000cbf18735f2428,0x000099a77bb6fe13}}, {{0x000ab7d29b0fc1d2,0x0000c2ff82ad4240,0x0003e8b1824be74b,0x000b66033eda9291,0x0000639f82a1d05b}, {0x0000f2c91ad5de88,0x0006ee9ddf6690a1,0x0005fc7fbf5d854f,0x00072ac4ded94a95,0x00002682d9b714a2}}, {{0x0001a874ed7acebe,0x00029408c1b46ebe,0x00096d405f800d1d,0x000d48657b969e8f,0x000025248132720c}, {0x000113432ff0aab9,0x000ed7506e97a2de,0x000f3ff61e19447d,0x0008868795e67865,0x0000dd308ae491e6}}, {{0x0000c4982db65ca2,0x0007cd8b3cfa5d15,0x0008b3c34d779cee,0x00007ce56f66df9b,0x00002bad9190373e}, {0x0007dacf82c7cd70,0x000170cd5e21faae,0x000d737aa745c2ed,0x0003683c666088dd,0x00002a7ff3c66133}}, {{0x000a25b51b2364ab,0x000cca23ad8f56c0,0x000cc5060f4037d8,0x0002d7b40bd50e15,0x00003c6b05849780}, {0x000dfb5580a54f98,0x00017736f3f4da3c,0x000fd025f36ffc28,0x0008e648f7012618,0x0000d358c70b39f6}}, {{0x00058b4c855a6e77,0x00057c0c522b55f1,0x000aab00625e8fee,0x000e46856ddaf929,0x0000358453361f0a}, {0x0009303af2d55212,0x0002aa5a6f6c0d2d,0x000148546bae13b5,0x0008b24d4e4ab630,0x0000d7472f84840d}}, {{0x00053970acdb5e8f,0x0007fc269b0f06da,0x000ed8404fc5b791,0x0007e86e017875d8,0x0000ae584763a508}, {0x0008f45064b6f293,0x00033c845a65aaf0,0x0002b4eb7bd3ce36,0x000130fa6c359a38,0x0000a8bd9f84a685}}, {{0x0008edd0663f8f91,0x000dfd59df5ea31a,0x000b723f079a56bf,0x0009327b892c2263,0x0000ca95b5e3d558}, {0x000ff18c4e8a781b,0x0001e49ef80c48df,0x000240760a2bb746,0x0007c06223d5cf77,0x000078f428a9e459}}, {{0x0007912ca1754a1b,0x00092318062eb864,0x000974e01c1c5675,0x00077e15df7992f8,0x0000a5205ad4cc39}, {0x0007e259fb6cbd53,0x00069eb726a354b4,0x000e567fe8f54419,0x0009e27f6dd9bb81,0x00001e04658e6f27}}, {{0x0003571b3d512de4,0x0003b7ec1208dbee,0x00021dbe93f6b7c2,0x000e0305001dba00,0x00002cde309eec3b}, {0x0000e38dd838d4f1,0x0005ed3f3ec2efea,0x000695c674c80611,0x000b53a586d725c7,0x000023cf980c45f2}}, {{0x000b294c00e93609,0x00036582b06d7012,0x0002b6731864a65d,0x00038b0faad9a9f5,0x0000f77e45dc3d84}, {0x00049e1125dd970b,0x0006521b5e3f5cef,0x00026ca225bd9b00,0x000e53d27026153a,0x0000ffc6effc2de9}}, {{0x00049dac9eda55e0,0x0008ed551742ae1e,0x000db16b7071ad42,0x0007e519f35180de,0x0000acf03adba5a9}, {0x000674fe200f7515,0x000041ad6226b24d,0x000bc185532514d9,0x000f57098d181f26,0x00003a47ab5d1829}}, {{0x00065694a7f9b78f,0x000f181f805c903a,0x000293f8c82ead90,0x000dc417c53de726,0x00002878d513c8f0}, {0x0005fb44bef65dc1,0x000c159a08f75e63,0x000e766741f4f5d0,0x000925d04127a52d,0x00000eabd36a8ede}}, {{0x000b38bd3f9e6f35,0x000a429a8af3f5ad,0x000b3d4c94dd8b95,0x0005081f01c01e1e,0x0000a43459cea12f}, {0x000266c93a596f15,0x000fbb27f18ef36e,0x0005dc2d06428594,0x000875dbb1d59fd7,0x0000123eea204f7f}}, {{0x000b96fae7ffdf8b,0x0002c722fe26e092,0x0005b25bf727e271,0x00079b4b3ece9d22,0x000029e084fabe5d}, {0x000cd0f3353903c6,0x0000436a938bfe7c,0x00097acfe3f67b99,0x000bce9cd2d1a3c7,0x00006253f0aaad9f}}, {{0x00044bbce9995733,0x000f073624473dd5,0x00033abee446da98,0x000978d07a005203,0x0000caeaa7309d7f}, {0x000150d1bf2bcd41,0x000ccb53f84c0b65,0x000ac6215464c51e,0x000609e277528a4e,0x000098cc59ce3166}}, {{0x000efcad4a7da4d5,0x0008301bbee31186,0x000b3db7feb894f7,0x000f1f8ace71e7f1,0x0000112c9354a5eb}, {0x0003b627286dce6e,0x00095a30713afd8d,0x0001c6f0a0610827,0x000d93fc4c531160,0x0000964d3161c3a4}}, {{0x000ed7017f788ea0,0x00094674852856bf,0x000c96919c78850c,0x000d11c15e8987ef,0x00008ec3fd406441}, {0x0001d9a8b2134698,0x000beec4889b6406,0x0003f1ad5d6f0bd8,0x000240648f309015,0x0000e5b581f2cb82}}, {{0x00027926c5189337,0x0002741b168b71e7,0x000a4a599fdcd605,0x0007cba7afaa4cd6,0x00002940e9635844}, {0x000a7689dae16a8a,0x000dba4b641f4ffb,0x0002ff98dda84226,0x000dd3217fd968b2,0x0000584b3c0e2f5c}}, {{0x00031b6de16fdb99,0x0008582a440f2355,0x0001c6e1855a3304,0x0005300eec11c310,0x0000d21585a61848}, {0x00011b3ef7a3b94e,0x000505e21369d2ce,0x0004b130e8bfbb57,0x000a18b7f8363266,0x000093672301cecb}}, {{0x00006d08ad2b8a84,0x000174564b2255b8,0x00072579bbdec57c,0x0009ce6932d9aefc,0x00002be0f18664b2}, {0x000379820c03f35b,0x000b81cc51d23ac4,0x0003b05894b88c59,0x0003d5999a808624,0x00005debcd1e1590}}, {{0x00063183e156632d,0x00095cc68bbb24c7,0x0001bdedfb33c7bb,0x000fc8798ec08681,0x00004d45061bb8c2}, {0x00096921fd5268a1,0x0006fb5a73e1eaff,0x000c44fe9ef420da,0x0002d2e7d1a2a7ff,0x000099f6ec68c8bf}}, {{0x000b091537d50e00,0x0004c4d8240e0105,0x00088289db80bb3d,0x000f2516e62e6a1d,0x000049b3d353af60}, {0x0006c1e8a9308ea7,0x000a834375ce9c5d,0x000bb4bf8bdb7520,0x0000568aac390a23,0x00000b0ddd236d48}}, {{0x00072da34e3add6e,0x000a25b562a221be,0x000f893f7463701f,0x0001b78a85dc4a41,0x0000b8945c02e7af}, {0x0004515392a4b278,0x0007224cf9eb4248,0x000a36d27223dc97,0x0000469b1c26a8fb,0x0000c8a286157f29}}, }, { /* digit=29 [{1,2,3,..,}]*([2^203]*G) */ {{0x0003d44e194a9fdf,0x0002786ca99f031c,0x000ad1c1ca8706b5,0x00016f6144a3f729,0x00007cd191d19930}, {0x000032e9850c5a09,0x00064ac49359a6c2,0x000556cf735b82bf,0x000ee923f58e8bf0,0x00004134d7aa14f9}}, {{0x000d9bb86ddaba10,0x000af2ff8d7f7ad8,0x000598bba183ded6,0x0009e01bf6f62c72,0x0000b0e9cfa9acd8}, {0x000fa485b832c346,0x000511c3faaf2d1e,0x000b424d4c7077aa,0x000d2f6f4b824a1c,0x0000e6cb10d909b1}}, {{0x0002f3ece47545bf,0x000cc82281bab5ca,0x000fef90fb8bf71c,0x000bee7b6c1c7445,0x00009f6c799f8590}, {0x000043420d1a0c68,0x00050384ca2526ca,0x0006d804758be80b,0x0004f8d0335e99b1,0x00007f6cdd65f76d}}, {{0x0009dee69ba8813b,0x000aa6bce2ade252,0x000b5e21e2f41814,0x000311e74086449d,0x0000fd363bf4202e}, {0x000eef53cd037a91,0x000f421162d3c6c0,0x000c1bfd296d4eed,0x0006d0ff1ba38cc4,0x00007b7b0d0ae516}}, {{0x000118e549825790,0x00087608d2b36a6a,0x000db2f0bc20e5a2,0x000100d9275dfc96,0x0000fde447ee7b6c}, {0x00028286516d65bb,0x00018776f794bb5d,0x00073d44dfb1675b,0x0007d7116902d37d,0x0000b303e3549334}}, {{0x0002b20e7355edc0,0x00029cd368ead897,0x0008b57463d27897,0x0009c3165bfa78bc,0x00002fe2446e3da6}, {0x000b89e933220b48,0x000cf81af9f1c16e,0x000c693a260f9ee9,0x000a0fd40f000040,0x000052f4665ea9b0}}, {{0x000e8f27a45c0327,0x000e86dd8982d9c4,0x000e56fb7618c159,0x00082ae92801f788,0x0000cb0bbd114f00}, {0x0002622a7b7bdd1f,0x0001cde8a1787ac9,0x00079d3f0007ae73,0x0002f8c21efea529,0x000059193889e5c5}}, {{0x000d6baee189bb56,0x000e053f037f48a7,0x000fad7013164603,0x00005fdb161acf55,0x0000e17a5d95e63f}, {0x00019ffe09ff7228,0x0008cace368cf35f,0x00091ae861843311,0x0004e6206e370ead,0x0000ddd9c9e96ad8}}, {{0x000c45cd3f314ad9,0x000d67364744703a,0x000b4a453c3af51f,0x000b9543050e4e10,0x0000fc178295f043}, {0x0007775ac574c8d3,0x000779f0b9acb4d8,0x0005b7ce50c8b03d,0x000b17132e5af1fb,0x0000c9a4f064d508}}, {{0x000f522e5ae3e277,0x00035c35e812e660,0x00042cb0bdb0d2f5,0x00094342c735bbee,0x0000907ea8901582}, {0x000ec0462e80ee09,0x0004686fb3008f47,0x00006f827e223116,0x0009550860a2ce31,0x00000a75951e7b8d}}, {{0x000f70c1ae342323,0x00018ad9615f80b9,0x000cdb22b183eae2,0x0007f44fe13030aa,0x0000096480bb3134}, {0x00051223b16a6387,0x0009942d6ff78220,0x0007ab9f39c0104a,0x000222d1b2b20f04,0x0000e09b38b19739}}, {{0x00015cdd08fa5ad2,0x0009abe3f073baa9,0x000000d8e4981763,0x000177db88ef6f94,0x00003eaac824bcb0}, {0x000eec6acf802868,0x000ce8144efca222,0x000da7040d7d51ac,0x000194f0b2b6495c,0x0000cabd0cde140b}}, {{0x00017df57e74652b,0x000f4607f76a84d1,0x000a479ff1f3d544,0x00007f04801c4412,0x0000698c2293de3c}, {0x0007faa80f480970,0x000345e6a405407c,0x000b9c66fdd33168,0x000aa0cb4a878f56,0x0000967b41c670b8}}, {{0x000e336c7c6f0782,0x00096d368d37636b,0x0007cb94d59ddda6,0x000066012877b72b,0x00001a597b4c1bdb}, {0x0001a77f61e01063,0x000941d2f7f6a765,0x000adc00b4c447fc,0x00091ec195fdceab,0x0000225175f8fbf6}}, {{0x00092cdef9b9f47a,0x0006904c0879edbb,0x0006347c48b0eaac,0x000a434c1967d357,0x0000a127c7caa1a9}, {0x0008363c59d19935,0x0001d39d521da939,0x0003198ee98fb3d9,0x00029ecfd6c18cdc,0x0000c77256b8e3c5}}, {{0x0004c3f4f7c6da11,0x00061ad5689997f7,0x00062877229a2a25,0x0007088588d5eba7,0x000058d5cc44dfa4}, {0x00035cc9a95c4417,0x0004bc289fdf6e40,0x00019b3a507f5383,0x000ce233b96c0c50,0x00000c852a997bcf}}, {{0x00074ab6e99c27db,0x000700add209d2de,0x0003682485035083,0x0001df8625e5b7c7,0x00000b17bc10dbf5}, {0x000a3800fdb2a3d9,0x000dcddadf173751,0x00052591af594942,0x0009ba307d31c514,0x00002993a31f60d9}}, {{0x000f10830427f20c,0x000f3b328a7fe500,0x0008f3641b8a00c1,0x000ddb433bdf6377,0x00009d207a3e0f16}, {0x000ad2c986b8e3d4,0x0000a50419f77145,0x0002215e5dba85f9,0x00036043616de9a7,0x0000890c85022c4d}}, {{0x000c79fb017c6831,0x0007a3ac08d0d0c0,0x000029dfa2a4a427,0x000ad7d78feae29b,0x00008d9adfa5f678}, {0x0009c5a65d795f42,0x000b9846b9bb1ee6,0x00058ffe0f45ce60,0x000e91a8c1a88f3e,0x0000be10bcc58190}}, {{0x0005faab9590cb5e,0x0001342fabcea57b,0x0003e7b2710e9804,0x0002cc1450419041,0x000074d1a8f02914}, {0x00094b897325bd19,0x00008ae2d222f310,0x000d2bd77ff05aef,0x000980085cf5bd1e,0x0000b0fe23af35c4}}, {{0x0004fcb8b197112f,0x000f08c2d9a81289,0x000d49a846e64b4e,0x0007aa5f20e1a8fa,0x00007cbd1a7ba201}, {0x00064a4a4bc89168,0x0001fad822dd3cda,0x0005d3c95cf37a38,0x00042789c1ac2c12,0x0000ff1fe3c1d92e}}, {{0x00092a5b1d033025,0x000fa30de8fdc44d,0x000a4e718fcef607,0x0004fbc816269dfb,0x0000bf7617c683f1}, {0x000de6a2dba301dc,0x000825272ede6fb6,0x000b46c3e8670aae,0x000f2ae811ace7dc,0x000059fa6d27c8ae}}, {{0x0002c9a0ef6d99fa,0x0009458f7d2ffabd,0x000a81b1810c0ec1,0x0000355e7c18df1c,0x0000c49e954b5556}, {0x0006c6fcf3518d17,0x000b3430cd0f57ce,0x000ed76dc6ca44be,0x000fa9be95d0a2cb,0x0000228db9607d58}}, {{0x00029d5eb1852497,0x000c231b03be4c4d,0x000b6be41e03aa73,0x0000c8bd817ca00c,0x000045736b555b18}, {0x0002467e0d2667c6,0x000112c70e0b53ce,0x000ce135f6da78ac,0x00097cce5c18f0ce,0x0000e522cc53caf7}}, {{0x0002eccb8b0b2cc8,0x0001b5ccf40f2f60,0x0004aebd14979660,0x000e7c210c1a93ee,0x00006c082ccfbf4d}, {0x0005a29cf6241ec3,0x00051c57365898d3,0x000c5cea4126aa24,0x000fb5f29b7ff954,0x000035d47dc88418}}, {{0x000e379fec34dd00,0x000af10f04b2da8c,0x000244ba7b67c67d,0x000b291e6c1fc84c,0x000064b8ffb56a4b}, {0x000f0c726a01b425,0x0000ab4e63c20a03,0x000daa4bfc15dee4,0x000b2ba598f42985,0x00000412dc5ee9a6}}, {{0x0008e2b0cbea7f60,0x0008aa38f3dd0462,0x000bbefab03aae77,0x000928ca9669f559,0x0000980eab114d68}, {0x00060ecf7e0890f4,0x000add678a21193d,0x000e75ce55e32dff,0x000b93e865c3741f,0x0000c6b7dadc3ac3}}, {{0x0000ebc9c7982a25,0x000c291e4d112cd9,0x00016c66bcb45331,0x000f8b46194b0c7f,0x0000dfc74610f6eb}, {0x000d1481dd4169f3,0x00038b5f60af605b,0x00009d46e7986887,0x000bb629eb8a4bc3,0x00004d4d57fb25fa}}, {{0x00045dd030229a4b,0x000f628bf05c5a04,0x000c8ae68bb98061,0x000b9637143f5451,0x000055db14aaf091}, {0x000c500b3ec39fe8,0x0009d418e00ae4c8,0x000f274dda387c10,0x00044d258b0c3190,0x000082d86c4dad00}}, {{0x000c6b74352596ac,0x000bbda2c19cc12f,0x000372be7ac616b8,0x00068ef8dd414a4a,0x0000a5c3507d3814}, {0x0005c60076424b1e,0x0008521878c8f96f,0x000720621f0ecd3b,0x00092f64b81e74eb,0x0000538ab09b9a9e}}, {{0x000147af5c6b6fc3,0x0009d626e2d99fe0,0x000e4efc5d3b7322,0x00023ead978b1f26,0x0000f06e93347735}, {0x000048486ca8b31c,0x00068bde8b51ab05,0x00034d7e9ebce61e,0x000b3f2f10632b10,0x000093e107c4e9cc}}, {{0x000a93461fccf159,0x000ac594ab715187,0x00023895d730753c,0x000cc5a17e2ac232,0x0000ef8cc49c9735}, {0x000ae251f43e9bef,0x000f1381286e7f14,0x000ece1bd4bbc7ec,0x000c24d2741d2d9d,0x00004d288de19a8e}}, {{0x000485ef01499626,0x0001422c7178e581,0x00079cbd8df6a745,0x0008dba5d0e4b656,0x000073799e051574}, {0x00030e5c106aa63a,0x0007bb8bf1bfe2fb,0x00051e7a789d99b2,0x000550c0acf7e0c2,0x00003f634d522030}}, {{0x000bba47947ece86,0x0009f8484a1cb45b,0x0001b504f55b8127,0x0005f5297e6d1f72,0x0000ecb79c9e7225}, {0x000a586963b03fbe,0x0009a9a594524654,0x000722ee4a3b403a,0x000ab40a3e93989d,0x0000606778e918ca}}, {{0x0009e70fcdb5c523,0x0009777edeab081f,0x000b6321e92e6fc6,0x0007d56dca6cbab0,0x0000481a9a365925}, {0x000c9c830d7147e8,0x000d7ed3c882eb18,0x0002ffe1754187e3,0x000ba41b2d1d263d,0x0000d9341cfa1024}}, {{0x000c73485db43e65,0x00072de631cdb39c,0x000dddde68822312,0x0009f1cca53521df,0x00008999320f891a}, {0x000dc155336fa529,0x00035bc4fb3d5300,0x000d60db809e08ae,0x000611c315d50e15,0x00009de175044122}}, {{0x000fa9194d351ac8,0x00074be1275acbad,0x000d047459aa08d5,0x0006b7f0a2a4d8f4,0x0000b07256b61364}, {0x000b6c992e60611d,0x000e5798e15351c8,0x0005f15a3b1f6a0e,0x000ebc7ea67466ba,0x0000be447e50b869}}, {{0x0005d7c17fc06372,0x000ab2ce49cccaab,0x000161cd0f703ffe,0x0006f3af701e3650,0x0000a22686632fac}, {0x0004ffc699f8f077,0x000cbff2b120fb16,0x000f1296557865ec,0x000e28bb4519d52c,0x000031c60ef40cec}}, {{0x00058f18eab52d1d,0x000560d708260815,0x000f6f11289d112b,0x0003447238d0bb08,0x0000ec9f217619aa}, {0x0009a34620f0a1e1,0x0008b55172a98dc1,0x0000ef9ddda42dee,0x000e7f1fef171e88,0x00001dc69d22f38b}}, {{0x00081cbe5c6b0ffc,0x000a70f127a082a1,0x00036c3fcc49c7b5,0x00032943bcf4908c,0x00006403b86cd8db}, {0x000d0a77264c886d,0x000074c46e8308b8,0x0002b835f05f0d1b,0x000920f60b800c29,0x000049222a687aa8}}, {{0x000576f2d8ff940d,0x0008af6e9ad4ff42,0x0001881bf2265dc0,0x0006ff7cb9f24d1e,0x000088c9c79e4b0a}, {0x00073d5b18e1c9f9,0x00006a4d2af38012,0x000cf1d6666875b3,0x0001d3988b576672,0x000045dbe0545fff}}, {{0x000abeb891f1ec6b,0x000fd53801df03ff,0x000b2923fddd0a86,0x000d0d90338c4e04,0x000093b7a1c89855}, {0x0007c6d30f5cdae0,0x000fec5d2630aa27,0x00063d74b39cc985,0x000af9d1a3f8d39f,0x00004b3d5f66a46b}}, {{0x000c9f671d7b1d51,0x000a34d571ffd097,0x000e017c1332810b,0x000ac856d2de4856,0x0000b5ac59d08ba6}, {0x000c9395a299f7d6,0x000550364c6c872d,0x00073ca853f70ad0,0x000d64e23185ac4e,0x0000a0dc786f885e}}, {{0x000365ca2f6cc753,0x0001950b7492d550,0x00003bfbde327978,0x000b87d29fe0d9cb,0x0000746555bd48ce}, {0x000c895bc1abe035,0x0003dbcf3d569c94,0x000bf1343778745b,0x000ef3214b6486b3,0x000047aa6736af22}}, {{0x000a2fcbbaf2c939,0x000d9fb3b552fd25,0x000b6e203f0b0875,0x00062eb1f0689b22,0x00002dad5d7a6b6d}, {0x000e02be2a7f8910,0x000f4be85299fed4,0x000459f8ce325e28,0x000f4d4865b62c76,0x0000b1af905e5737}}, {{0x00052120e85c6041,0x0001ba10be26a162,0x000d804fd3ec775c,0x0002eaa61440fb52,0x0000068ea63e38d2}, {0x000b7fc5f961a053,0x000cc635146d1c90,0x000e33657bdda345,0x00085ee9c9428d6b,0x0000446275189867}}, {{0x000784a3c5468e85,0x00047984ba27c370,0x0004066d7e5a8330,0x00061c6d875b96cd,0x00009ef1394bc3b5}, {0x0008a9fa2de76220,0x000e636f54a420bd,0x0002ea4587bdbb30,0x000e5caf449dd5f0,0x000010d9580bf257}}, {{0x000bc0df5663cc09,0x0008ce45bea99fdc,0x00066c8aadefcd5e,0x000c717280653351,0x000013d1b8e2e804}, {0x000e2ee1bcaa98d5,0x000a89c86e998159,0x0007ba8b8fd3241b,0x000cda83ec96ed7d,0x0000cbcf8e5c4088}}, {{0x00013b8639ee43e4,0x0001cd5b01220ed1,0x0003036576d0f097,0x00062825f0577f4c,0x00008ef888dd7597}, {0x0002f120ef9824af,0x000bdfedb88169eb,0x00096098c26c3113,0x000fb30d47829f28,0x0000b9a090863684}}, {{0x000e1d9cbc3fde8e,0x00004d7bb98ff2fe,0x000f525f9a307331,0x0005b55bcd46bc61,0x0000018644ffde13}, {0x0006b02f72aa32c6,0x00064f4c36a1c7cd,0x0000fd885a8f4dfe,0x00087bd6ea8c9b1e,0x000074cf3eb4034c}}, {{0x00073bd32b3ce74a,0x000ae1cd16e13987,0x000ae6b331a3b6f6,0x00046de18f795e62,0x00001b268c2eac8f}, {0x00069500b796bcb9,0x00084b0bba811e96,0x000f2ccf64d07f55,0x00041c6d9453b627,0x0000ab5a6b96d1e4}}, {{0x0006ec3a747b5540,0x000399f0d80c1e58,0x0007fdb082affb22,0x000eb0c210e996e8,0x0000e95e547a6d00}, {0x000c9c0049c9c5cf,0x000e0f520325da72,0x0005ebfd1d560466,0x00076497d952c276,0x000045f0b3696836}}, {{0x00008a22bc43724c,0x0003c41e774eef64,0x0003a4dfeb9d0e74,0x00004b006555b0ab,0x00005d1666eb0348}, {0x000248fd93a49062,0x000be3c4df2ca530,0x000998ee3e168071,0x000d38f9f0133243,0x000048b66cacb6bb}}, {{0x00089d9f89790db3,0x0005f889a66e42ae,0x00077b13eaca57e7,0x000143092c735596,0x000008aacec1a523}, {0x0001e6516c69967d,0x0006f9a3b6e5c1e8,0x0009f29dfbf864b7,0x000799dd8c521037,0x000071100f81f8ea}}, {{0x00095a4465926123,0x000cefa1e2ba3fe7,0x00026ef78e5b31e1,0x000a78581fbbd306,0x0000cae68ad41793}, {0x000c18c2eb0d08ca,0x0003ef8c811ae66b,0x000e2252da9bb52c,0x0008a2c5369b8118,0x0000bd6b4123893e}}, {{0x00098fbeb198837b,0x0007e591d932f152,0x000a139813f9b9d2,0x0001b9a3399f77e4,0x0000a1298c3d05c0}, {0x00022a6bfb15d6ef,0x0001033da01cb0e1,0x0002fb9fda76e2c7,0x000f5fbc3f0ec949,0x00006c65aa22897f}}, {{0x000c71c17acd4295,0x0001011c393d2328,0x000286245219bdd6,0x000cba4b683f2657,0x0000f802506bd066}, {0x000b96620f24420c,0x000fa4428c9d74ac,0x000aacb236ad94a3,0x0002c648f91ae4f5,0x0000fa1ce59741a2}}, {{0x0003b3ce11cb6f2d,0x0004d34dc8b8ff58,0x0002fd7cc9dfed18,0x000f048bfd16a8b9,0x00002ef21c9d0bcb}, {0x000be2a7a86c43c4,0x000ab9dfeed3f183,0x00013c43d69b6205,0x0008db23413a7f78,0x00001d39c7d32aa1}}, {{0x0005b43063f50fcd,0x000194e360c3747b,0x0003b425a290fd4f,0x000535e867f57238,0x000025fd6b026625}, {0x000adc9d6e1191c5,0x00026e3cd549d280,0x000ec1539adc8332,0x0000cdb1ae29236a,0x0000810251d55eab}}, {{0x00029cb4887c43a9,0x000bf0ecbf8060fe,0x0000dc5c04dd638d,0x0005a407f09b063c,0x0000c90890142afc}, {0x000c7f52d04bee9f,0x0006e697fab88589,0x000126de25d7c826,0x000402657a0ae9f1,0x0000e4761b55036e}}, {{0x00025a23ef5de284,0x00092f812e80c46a,0x0003fc24edd7ca58,0x000462dfde4b0b1d,0x0000cd2f0f0bb018}, {0x00086a72d1cc82af,0x000c2a483fcf4d9f,0x000519f9a53040b2,0x00086b7b2c6bb96c,0x000049adc46ab823}}, {{0x0008d0ffa742f123,0x000a2df6bdd73b6b,0x000a1cc8e1a0bf73,0x000c4aaf283aa1df,0x00001ce68bd7aa7a}, {0x000282e1f607c5f2,0x000ef137e8b5ad86,0x00037413093d7e59,0x000744f3271f905b,0x00008c6b4eb4ee8c}}, {{0x0005cb112391f8f0,0x0008641ea3f94138,0x000a010f48cd20ed,0x00039d7c395dd04d,0x00005c716598493c}, {0x000e3a42b6e9113f,0x00069cfdaf0139c0,0x0008a7df12e8d24d,0x00074ace4e33416a,0x0000674561bb3fb8}}, {{0x0002c06cde003641,0x0007882475bc642a,0x0000572001a99da3,0x000608dd4b142d6f,0x000093c30c54e876}, {0x0005a56a6f3399b1,0x000625608bc9ef4a,0x000c52c2c93c2f89,0x0002135ade60f126,0x000004d9ce986570}}, }, { /* digit=30 [{1,2,3,..,}]*([2^210]*G) */ {{0x0005587744fc9b0d,0x0002235a186fab45,0x00014d4716a6ca8e,0x0008e21b61f724f3,0x0000f3f72b99a2c5}, {0x00080e1a9312fb07,0x0007d9cef9613e14,0x0003e5490ac148ab,0x0003955a1c207543,0x0000f96356794b0f}}, {{0x000819be29f68267,0x00009fe4deb38664,0x00050b6e73cb6078,0x000558aacd6e06b1,0x0000279daf8f7d63}, {0x00018e07f25095c8,0x0008331cfc9f5f26,0x000782972feb9f2c,0x000658f802fca94e,0x000038c50f53e7be}}, {{0x0003d4ddbebe9fdc,0x000143df4bab03d1,0x000400f0c967a672,0x000eb663cc254819,0x00004477f6a2dd2c}, {0x000ee0d4c3d37c69,0x00009f15d2633c34,0x000643fc0eb2b41e,0x00009b2d010432e1,0x000030aa45907c25}}, {{0x000ec65be9e92878,0x000c55c6b87a3bca,0x000db423a40a8edd,0x000575f207c56c36,0x0000de77bbae2005}, {0x000580d56553246c,0x0002d79f3040d372,0x000398bd3d4cafaf,0x000cf3e0535cea88,0x0000d8835ad63a58}}, {{0x000938515a35e548,0x000bad5845ecfedf,0x00085e8461dfb3c4,0x000503cd8b2d66fc,0x0000a93de3d98e57}, {0x000f822006f36a34,0x000a47a6f9bfc29e,0x0009551254d51965,0x000048cb979c84c0,0x00001df6019a10a8}}, {{0x00078cab73289d88,0x000b9d9fa4701c6b,0x0003396e135bd0c6,0x000974c909a06d9c,0x000019ac99ac8f6b}, {0x000ceba50d80dbc5,0x0001303b634316a2,0x000b684d771cc7e9,0x000516e058c5049e,0x0000292ba043dbc8}}, {{0x00038fbb6d7a003c,0x0005cf09193bfc73,0x0009d8f07894acea,0x000acadc9f445791,0x0000d19f61fbcab1}, {0x000ee3f4a227ca59,0x000da7f63d2a427b,0x000791f62bd40826,0x00024a161e806c1e,0x0000add1e908c47f}}, {{0x0009ab29ea7ebd27,0x0005e96d975a66cf,0x00089209baa3ca4d,0x00014f686c002e33,0x00002fc9f0d6de64}, {0x0008c324e1c3942b,0x0000f90ac257b88c,0x000d3ac5c6940150,0x000a881ab7db6e14,0x000041cfa9e1e973}}, {{0x000cd33ae6949b59,0x000c4ebf33ea027e,0x000599a62bed515f,0x00080a74262307f2,0x0000658216a1a59c}, {0x00032e776bfdb8c8,0x00017f7f1e742947,0x000e4d1cd2135990,0x0004b293f38844b0,0x00007a0099785d21}}, {{0x00037890b4606073,0x000bb550c322b536,0x0004ba1bce567534,0x0009e06d2e436e29,0x0000a4c94f2a27ce}, {0x000138a6812a277f,0x000f29b99d6648ce,0x000a581647b50956,0x000333ece9cb729d,0x000027d4916a975c}}, {{0x0008ffdfd9dd8995,0x000722772d432015,0x0006c364a3ab59c6,0x00070a5bf413de34,0x0000d46f8062e931}, {0x000b960a7a4ea0ea,0x000695d0db76048e,0x000e021533582f16,0x000878c9174f8cee,0x00005573b093f78c}}, {{0x0008ee06f4cb971e,0x000eb1dfdb17fcb4,0x00055a1b0f4066e7,0x0004c7cd2cec053a,0x0000ebdb6c1c4266}, {0x000350374bfd9193,0x0007524863bd2f5f,0x000948b9fb7ad01f,0x0008761103a17657,0x000010efd69bf34f}}, {{0x000e391227b7b918,0x000179b0e8190ad9,0x0003188ad2f3b5ab,0x000db428f6ac1ae1,0x0000ac2d65e8d7e1}, {0x0005fad05741fe5d,0x000766f6f06a7260,0x000ce0f46f458b8d,0x000fce97f099d97c,0x0000ce699ff7d01f}}, {{0x000d627bbbfea21b,0x00065bc86f5b59c9,0x000cbb800712f816,0x00030ace738f6336,0x00006b1e3676ef63}, {0x000629b9767990f6,0x0002ea49f8676b78,0x000441c77086b44f,0x00050133cf0e09be,0x0000f290415611c6}}, {{0x0008e4736e5a00cc,0x00089440d1089750,0x0001a583a42edd9e,0x00093fd719bfc55b,0x0000b56d2dda07ce}, {0x000d6fc706e0a7f0,0x00032881de026303,0x0005d65f6c087882,0x00067db008ec67a8,0x000014533f4dc722}}, {{0x0002f3d088db12bd,0x000fcf97a9b2b8b5,0x00019e14ff0d94a7,0x0001362fa0525b50,0x00003579f0be0bb6}, {0x000f2ad6651cd253,0x000f8099f9cb7e45,0x000375844682073c,0x000b76f4525fe726,0x0000a75ebc0af507}}, {{0x000f75b1f2819cef,0x000f19e282729c41,0x000e04765719be03,0x00083fadad0e2c38,0x0000a88c8f8e6bca}, {0x00095351371d8ffa,0x000a01a80f584579,0x0002533ae7490891,0x00012b5f33fb816d,0x0000bbdbc03aae64}}, {{0x0009a60af672be3e,0x000fbb1bf99b39df,0x0003def3e27b2b86,0x000698ab5d32dc62,0x00000c7f112674f8}, {0x0006c0939385470a,0x000d3c072ad3f6a4,0x000e841d647176dd,0x00050201733adfd1,0x00008ba67afea17f}}, {{0x00061ae2b3427567,0x000dea4fd3f60fe6,0x000698aad50aa6e4,0x000b8d08d2ad5882,0x00000e1b9baf7513}, {0x000488bb1d898d7e,0x0006ce8c0168ad39,0x00091a4ad9a1c7e1,0x000819b619ef164f,0x000047df7d2d85b7}}, {{0x000feab634bed6f8,0x0009357dce07ffc6,0x0001f22c07bc045d,0x00020284bf369c39,0x000000ec5355d927}, {0x0004492e1ef8e017,0x000bebc2c0cb9bef,0x0007f47cb55429b9,0x0001452791fca0d9,0x0000446d21780520}}, {{0x0007bbe224fcd24c,0x00073d7bf6169471,0x000ac5c21a5a8b44,0x00039b7699434475,0x0000c24ec0229fa1}, {0x000ef056abea3468,0x0001b5631170484a,0x00014686e31baa0f,0x0008aa6711643949,0x0000ab5fe36c56bc}}, {{0x0000fc5e6fc64867,0x0007fa43f868a21a,0x0003a88ba36f8db7,0x0002e70eb5ad6bdf,0x0000871d27ec8c07}, {0x0000eb5d0d0dfac6,0x00046fcb36133cf6,0x000b30f407d7c7a9,0x00000d6528aeb587,0x0000c3c8285253b9}}, {{0x00054b828518597c,0x0008972f858fb628,0x00099871d157ba17,0x0007e3f4033329ca,0x00007518282b4088}, {0x0008335b1c0daefa,0x000b28c6fa72dbe1,0x00044e1cdd57d324,0x000b9e9bd8eb94d6,0x000090a27421fd2e}}, {{0x0004aa7033c1794b,0x000b58d101a5a260,0x0009e75d4582f913,0x000c67d11d071709,0x00000c26db9ab4c4}, {0x000e2fd553fa1538,0x00092583731d4527,0x000ab1e032a78837,0x000565e5708eb33c,0x0000c48e233e93b4}}, {{0x0000f3606cd3c7e1,0x000f9cf3f1a25ffb,0x0003c6509d6f19f6,0x000fc6ce3b57e1f2,0x0000c8aa53c29394}, {0x00013193e35bc970,0x00071c65a63e7410,0x00003fc0f1d93591,0x000631583a7d1998,0x000061d7972661e4}}, {{0x000f3b0ec646b6fc,0x000ab80b5bc4d4b2,0x000e871c1dc2998c,0x0006f2466508817e,0x0000fbc22289a212}, {0x000d2a00a06285a6,0x000173fe65578efc,0x0004a98cb75bf247,0x0008fac92d989d9c,0x0000948f4932b9f7}}, {{0x000845cf66cfa8d6,0x000482a7592908e7,0x000938c783adbd0a,0x0003fdf2c40e9dc3,0x000081189439bf8c}, {0x0001dfbde2120af3,0x000ec8f666c61cac,0x000049635e3b8104,0x000b570d910b372a,0x00003b0a13fe3b6a}}, {{0x000bc798fcd4c386,0x000e2d3e989b0ec2,0x000354b0ebfb4e64,0x000ad6b241e9e539,0x0000e64b4499f9ea}, {0x000824a5c0b286bc,0x00095daf822450de,0x000b5e3cda89f6da,0x0002c25d832cbc77,0x00009df72511f703}}, {{0x000d12e444a0e491,0x000990d76c78030c,0x000c2baffeec0fbc,0x000f8c635cc28c64,0x0000eed641f9bf3a}, {0x000c2a90ac6e705a,0x000a41dfdafd6d8f,0x000c5e6d0fab169c,0x0009e24840dfe5bb,0x0000261cb58c5df6}}, {{0x00068c7c8f041f5d,0x000195a9be95746c,0x000e714fd26f00e2,0x00086a2fa5e86163,0x00005265628346d5}, {0x000d2f1ae615f3b1,0x0005881ec186cd66,0x0001f8ebdd09686d,0x00062642c2578874,0x0000b8d0ec7aa3ef}}, {{0x00058a6e2678b76a,0x000c3decc2e12e45,0x000400578f26b5fe,0x000e9c64934cdf4a,0x0000ac4e70084d31}, {0x0005269ba3707c6c,0x0000ea75e26ae313,0x00076aec64c7ef65,0x000cede81346c1e0,0x0000e7007b498e3f}}, {{0x000ea93372944b60,0x00032e7f0407c535,0x0004662e884f3908,0x000ff3b4dba2af07,0x00002dd0c0bfba19}, {0x000a01101857f415,0x00002e9c6bfcd3bb,0x000b305efdfbac49,0x000f445da2626ecc,0x0000907070059481}}, {{0x0007b22d683b3a49,0x0009bcf9beabef21,0x000c7562a038a49c,0x000910aa13a5841f,0x0000c9389d6162bd}, {0x00075090b585818a,0x0009316773fa9595,0x0009848a8d0f9dd8,0x0001f651555c4021,0x0000d05a8d89f69f}}, {{0x0004d24ad962db65,0x000543238c6a727e,0x00075965517dee3d,0x000a85f8def34db8,0x00000d3a88c6d24b}, {0x00034a623ebab5d8,0x000bf7b417eac935,0x00037ce6949c24d6,0x000036e934f11b54,0x000018002a7a5455}}, {{0x0003123c18986e41,0x0004271e4976ebd1,0x0009925168a8da06,0x0004b18aa1334900,0x00002665721f0fa9}, {0x000b0ff43133deb8,0x00000a9c1b9fdf83,0x0006c154d3516d4b,0x000d735850f7ed9b,0x0000e079bec8fd08}}, {{0x00069c12865882fc,0x0008d9957a5ac327,0x00093aac73f8192c,0x000ceac6fcd6d246,0x000006af48a5b01e}, {0x000026027353e4aa,0x000e1c3a62c87965,0x0006a866c4b5c0d4,0x00057ef67206ffc3,0x0000f866c2bb479c}}, {{0x0006024ef491d5db,0x0004e2704aefb3f8,0x00074dc8b5853c6d,0x00063b3be06adb19,0x00000a163a242c3d}, {0x000472d0e212765c,0x000adbffde000bf9,0x00095dfc6114a063,0x0002ffa142ae6b29,0x00003767dae16b26}}, {{0x0004392a32caaba8,0x00067d4e7317e8fe,0x00062cd25f60018a,0x0002429928340b9d,0x0000d019c13c0075}, {0x0005df10a659460f,0x000ede055af81262,0x000fbaec0f8c8158,0x0004dd990e40671f,0x0000f1d47ce0cdde}}, {{0x000b86d5de825fda,0x000827ad5ef1c31e,0x00017d3651481ad4,0x0006f11c7f12dd40,0x000023ccbabe1ee2}, {0x0006b90aaec673e6,0x000becfdce1eaa36,0x0004ffdf0bd56245,0x000f51bd73c118ef,0x0000fc7f3b398c76}}, {{0x000b507845c7e712,0x00083994ff8becf0,0x000b099529c1c424,0x0000bc950938df6d,0x0000f211f0736bc4}, {0x00067c661de70ba3,0x0001d734eec5882f,0x0008914f01a0144a,0x000a3c5faebc04d3,0x0000aa86b02d5b26}}, {{0x00019c31bec876f4,0x0001988ea72cfa1a,0x000ee8601d01485d,0x00046183d3520a82,0x000047ab80a29f96}, {0x0004251df44392bf,0x000a29983d364de2,0x000a88da2e7b5ba4,0x000954f4e59b9a0f,0x000037e6c24257f1}}, {{0x000e6dfb09a4ace1,0x00047c55d4e26d05,0x000e515e1f45c89b,0x00043f7bd69ae93f,0x00005479b4aa9e09}, {0x000ba9bbf74ce4ec,0x000f332dccae40b7,0x00003a3676d0e1de,0x00089f9a692179b6,0x00006ac8d0990a7d}}, {{0x000b612be9f087c7,0x0005d2b73fa0575c,0x0002ca2ba11c214a,0x000ed841f6a65480,0x00000b110025c00f}, {0x000d80afd4f314e3,0x000f3c64e352cab2,0x000798d050b2af3d,0x0004185885404c7a,0x000023d177bde8cb}}, {{0x000178806542640b,0x000d88c52d25f44d,0x000446d579176f30,0x000397051da7626c,0x00008886aafbab41}, {0x00015912cf9cea49,0x0006e21fa90bb0ab,0x000908b221aaa808,0x0003a7333bfb3941,0x0000ff4d7efda834}}, {{0x0006e39f3414f11f,0x0009d29f664e12c5,0x000500f05843165b,0x0007ffcb61460ce2,0x0000626de1e0448f}, {0x000c9f888fd60e9b,0x000814b7c85bdd05,0x000503d082652999,0x000f69928a0fbae7,0x000079af9aa5c51b}}, {{0x000b748853dc369e,0x0001d5c46a9c7c80,0x0004943a99974554,0x0007adda66e0232a,0x0000290429a60883}, {0x000995ec151d853c,0x0008ff3a1822fa7f,0x0006eaede0e6bbab,0x000cba88badae027,0x0000c256d3997a8b}}, {{0x000e2a41663b8554,0x00092366f160ca96,0x0001c123d905387b,0x00034e0adcd7509c,0x00007b1f6e4adc08}, {0x000b82f6a17de8df,0x00016127f77fa75a,0x0004d788321ad9a0,0x000a97ae85ad92ca,0x0000b54c99e120fb}}, {{0x000bffe361a46388,0x000fa4c0605193de,0x0000fcdd0adb800a,0x000f5618356c1336,0x0000436032ec11de}, {0x00053a068b16e75a,0x0007a5a6a6730ec0,0x0001a5ba4dbd79ac,0x0005fe6729055356,0x00003a575af0acad}}, {{0x000fdc35bf0c9f33,0x000da45b9b398957,0x000ad7beef5e41db,0x0006432a7c818563,0x00008c2e1c2b7db9}, {0x000b00db46177027,0x0003e2b378f87bf1,0x000a0f28a308889e,0x00097ba082187936,0x0000acef7ee2ea51}}, {{0x0009390c918d6270,0x000362caac635c08,0x00015b8376799de3,0x000eaa821a885535,0x0000cabcf406953c}, {0x000d04fc7648475d,0x00098dc7d882d0c2,0x000aa0b4c0a7dc6d,0x000adf01bdcf234e,0x00000e2626b268f4}}, {{0x000220825ed35afa,0x0009576f7cccbe00,0x0003a8d37c11d3dc,0x000bd7a0701b842c,0x00007dc318423ed8}, {0x000dc6851e23a270,0x0001482baddbc17b,0x000ef80594dcf07c,0x000635f48b62fcd6,0x00004ba3f7faffe9}}, {{0x000df3379d5aaa09,0x00053e95a9719715,0x00094035e04096ab,0x000371086a53ef79,0x0000479c7b8f06c0}, {0x0006071ec85431de,0x000b4d8ac75c33e6,0x000b91fc3cf2421d,0x0000c5a713565a6e,0x000093f6b5095293}}, {{0x00053433c213411b,0x000f19421558a32f,0x000cb3419d7893da,0x0003e94fca316dfb,0x0000374884a86a35}, {0x00018637e8891bd7,0x000dda699e3631dd,0x00099f03059dff7f,0x000c475d060ebfba,0x0000bdd0e28de233}}, {{0x0008625a553631ce,0x000a9796b7c66042,0x00069e1a8d149b49,0x000b9d24bf15c71d,0x0000499b36421998}, {0x000c53bf713ec42e,0x0004b77890566781,0x000528324cc47d1a,0x000e99ee4752d162,0x0000b9b11a1afa93}}, {{0x00081a0ffb5c9c9c,0x000e055f0aae4142,0x000f67533c055cb5,0x000ba1661d64b05f,0x0000d37a37649d4f}, {0x000fbbba5ad491dd,0x000cf8282ecf7198,0x0005ccb6e6b04c81,0x0007ebe65a66949f,0x0000c80d786e0584}}, {{0x0008203f4211c7b1,0x0002f22609747204,0x00046dc191e8d62d,0x00019cebf4ef9152,0x00009163ffa00eb0}, {0x00076e6fe036a5d9,0x000f17c8eb9e7d4d,0x000b94224aca7e98,0x0007dafc52c4dd07,0x00008fcefbaee74b}}, {{0x000f5f295afbe525,0x000dabfbf6f56e65,0x00029dd9bee154ba,0x00075fc7e43056b1,0x0000c6703f05bb43}, {0x000575770ca61480,0x00034ab150f37095,0x000ceacefada8fcc,0x000f68dcc0b53bd8,0x0000e9010313dffa}}, {{0x0003c71f5c8dd248,0x00064afb2df6f44b,0x000c4e22d86f05fd,0x0006bdb2e524154b,0x0000823ebb857629}, {0x00050ddefbd1fc06,0x000d57e3a6573398,0x000e9fd87a05db65,0x00097c5a82bfea97,0x000012602f1dc978}}, {{0x000d464401ebe000,0x000aae7249d91866,0x00036dc90713e6e6,0x0005568974870842,0x0000783ee0137c6c}, {0x00074662eccf7759,0x000d7f6b891712b7,0x000f43eca62ac342,0x000072ff0edd30ee,0x00008a7880f860aa}}, {{0x0006cebf5ed71c29,0x0009efe22291ed90,0x000b496537c3d7bd,0x00085a93bb5041ed,0x0000dfedb68b74e5}, {0x00072c8d5958c8f8,0x000afb5d5f31f91d,0x000f4d874ee28bf5,0x0004f7e7a69fd006,0x0000529fdae49ca5}}, {{0x0004deb5cf2cc3c6,0x0008c9d887dc815c,0x000d6a375e22f1ae,0x00076773ad520b03,0x0000de108610ca0d}, {0x0004e8cb47e14977,0x000ad0aea66d4a4a,0x000783042dd19814,0x0008d9e54672563b,0x0000b890128daa2e}}, {{0x000808410ee3d23c,0x000392a615b14640,0x000d2683f464306a,0x000bd3ab01e405c2,0x0000e70e8511df3b}, {0x000fdca6a9e839a1,0x000c9403fb89e6fe,0x0006a9fa129439dd,0x0006d65462b965b3,0x0000f3fd2b9110f6}}, {{0x000afdf466dca9a6,0x000ca27896b1bc08,0x00026b7aac5ebb91,0x000b7ee6800bd153,0x000059f83a9b154b}, {0x000160df796189f5,0x00088ae54694e160,0x000d66289e9c55c3,0x000b00a2b43c3c19,0x00003413ff683fcd}}, {{0x000aad2f31e88186,0x0004568332d1f745,0x00085e5b8099a8b9,0x0006911240d922f2,0x0000f5f060aefdca}, {0x0008a8cc9a6632e2,0x00009a8ad40a2cac,0x000b2ec9b7267e5f,0x00067797ad93d424,0x000056880826d350}}, }, { /* digit=31 [{1,2,3,..,}]*([2^217]*G) */ {{0x000c5b31b84523e2,0x000be6e4ef99ea3b,0x000a69918305e9d7,0x000f226013092787,0x0000aeef51df4898}, {0x000935d577020efe,0x00047c06a751ec81,0x0009737700fb9a01,0x0008f210ddae1671,0x000078a0d0f4c882}}, {{0x000d5e8ccd993818,0x0000454160028f27,0x00035c9e5ac962fe,0x0003961bd348325d,0x0000f7888f9d08c4}, {0x00028e7cc2ce2849,0x000864e2a7ab864d,0x00004f4743155567,0x000056ef40757409,0x0000de9ba7203fc3}}, {{0x0005c0ee77817ffe,0x000841cea362486f,0x0007dd9962de3465,0x00073b6d58d6ef81,0x000092b6a9f738f6}, {0x0008e609ec8a67f5,0x000d874bf95d4493,0x000f082668cc88ea,0x00018e51a53b6999,0x0000c44968fda017}}, {{0x0006d9a9c9c7ecd6,0x0004277106c7b597,0x0006ce73e23fd318,0x00098a67c30e1c70,0x0000f0d0fe2ac602}, {0x00005926a46c71a3,0x0006512eff4774d6,0x00068ac6f253f036,0x00014e045f24b5e9,0x0000148b466e0cd7}}, {{0x000fcfcd84a929d3,0x0002ad54a2149937,0x00096084028ac0c1,0x000a98eb3a256be9,0x0000a028f7a712e1}, {0x0003ed11da5648c6,0x000765175dac0cf5,0x0007e6793730e016,0x0006e12887741adb,0x00007b90747e694e}}, {{0x00095060b7f3155e,0x000baaf4df36ae23,0x000b773beedb6ad9,0x000e9434c85948c6,0x0000285db363d9d0}, {0x000ba7a7d1c9fea8,0x000fd444e8a8f514,0x0001079dfc491f23,0x000423e35a941ff6,0x000029feac4a3859}}, {{0x000f263a7b127166,0x000ffda74297f963,0x0000d25cbda01050,0x000eb7ffa92a1540,0x0000d4cfd6140a62}, {0x000ec796b38c0f5d,0x000b3301612e7e11,0x00088f375bb456a6,0x000f1d2e639ccef5,0x000023c5b7ec9322}}, {{0x0000d0706eeee3b3,0x0002383bb3c41af5,0x000789d57412b36c,0x0004f76f161f4348,0x00009d54f9fa323c}, {0x00098713416de57e,0x000f289880622fb7,0x000ffa44b6065378,0x000ae646228a95c0,0x0000e77ebc11e012}}, {{0x0002e057a7667ee3,0x000980621f16ec01,0x000dc6a70ce7de5d,0x0000ab25dd09f571,0x00006ba631c46be3}, {0x000a3ceb0468f0d6,0x0005cca0a4b4f979,0x0006814d43b03db2,0x000c037bf72fa0df,0x000070b2e22306cc}}, {{0x0006e4060e56d291,0x00073f9eac2a60a7,0x000609574bf57884,0x000850711a75007e,0x00004257875312d3}, {0x000515eddc745f56,0x0008085a3ecc7070,0x0000354544ed84c9,0x000a74204234e39c,0x000012c06b29876a}}, {{0x0003f156c03f4661,0x00016f589034ebea,0x000b6ec7176a4552,0x000ff259e041df5b,0x00004ed99b1037dd}, {0x00086d386ad2e060,0x000fad2ab5238d4b,0x00011e6c46846865,0x0002b3a450957a0a,0x0000c5d260143d1e}}, {{0x0008e38152258344,0x000fef5032e4a93c,0x00001424b43ecac7,0x0006743325458b93,0x00007f95a9785eba}, {0x000a205186d9025c,0x000035a7fe558fef,0x000a3c8776c0b58d,0x0009496073e77a5c,0x0000b53d4427a2a0}}, {{0x000aa0fa4a2e211c,0x000f72cc7932a003,0x000c29fd7e905873,0x0007a0116f12125d,0x0000e442886f9b48}, {0x00007e055af80e44,0x000c596df90f2dc5,0x000d6c18109d73f5,0x0001df729ebcf653,0x00004160bd446d9c}}, {{0x000fd2d788ba6520,0x000d76ff5738c9bb,0x0007fb3242d9cc46,0x0003339c8d8920af,0x00005c508f078998}, {0x0009e3679f4ab8a7,0x000e2634f4ee182c,0x0009bfae6cc835e1,0x00046a9f81c34f84,0x00003d0468bc1916}}, {{0x0003b15660f59ef7,0x00088c12554eef23,0x0009330a3a321c51,0x000b3626b05480ad,0x0000c022c30d43d6}, {0x0000661046f68e00,0x000e80e8e9ae5d65,0x000b4697993ae49c,0x000eb1d32afb6dc9,0x00003f033a44cbae}}, {{0x00087e5163cbc0a8,0x00006ae98f3ee679,0x0007b68448c3e107,0x00085d27aa4bdafa,0x0000aae2dbd0b3f1}, {0x000ac1ef01e8f3c8,0x000854cda9282656,0x00092a068b13fa74,0x0009658322dae1bb,0x0000f651015f4306}}, {{0x000161d5feff15b2,0x00050345887b8e42,0x0007f685e1f8bca9,0x000a5e069e055b08,0x000014e3f1706090}, {0x0005bacd466e93c2,0x00024cc6b95b9719,0x00056a22d1b25609,0x000c93c6c0448103,0x000081192897bb0a}}, {{0x00036a0c08a594ea,0x0003b66986efe95b,0x0002f86466896b35,0x000998b3227efd50,0x0000227f683c30e5}, {0x000dc9ff42ea5c5c,0x000e34f0f1d46fea,0x00047ca2cad6837e,0x000856ab3a67ba93,0x0000f0eb2cce452f}}, {{0x000a1589e0b82fbe,0x000de449e007aa58,0x000d14a4ee633c68,0x000e61af8fef7e89,0x0000f60872f433ac}, {0x000016d64afd1619,0x00060de62c698aca,0x000269bb3d24f6f1,0x0006b7f138fd2d41,0x0000d75248556ff5}}, {{0x0005206689b92bee,0x000843322d9c7cc9,0x0009915cd7756249,0x0003f02dfc1956ca,0x00005236e7bf69e6}, {0x000a95adca139b5d,0x0008994070b778a3,0x000f73bdbd4254b2,0x0000abac251dcf19,0x00001d28ad0b0466}}, {{0x000a1cb8a87fdd06,0x00090886a6941375,0x00048f1903f9324c,0x000cf3376989c09c,0x00008b982f180de2}, {0x000716ea40012c9a,0x0001f5874d1db96a,0x000ec9471af0aa5e,0x000a1ab118cd78d2,0x0000f9537952f8cf}}, {{0x0000b7eee1e1bf2f,0x000297cd743a214a,0x0006a906ae3eb720,0x000f876830a1a414,0x0000eec17838e9e3}, {0x000c737251493343,0x00025cba6f7cb12f,0x00039b703deff11a,0x0000f4e3aceabbfd,0x00002ffa04f9bc74}}, {{0x0008f06e2aff6bdd,0x0009c7332d94e0e2,0x000f1e13c0a81628,0x0000ff353b4e659f,0x0000c3f048b4016c}, {0x0002e01399fc2da4,0x000c7348679e5b47,0x000abca0e8e7b659,0x00038dd0e20e577d,0x0000dd894b007fae}}, {{0x000396824f4dbc09,0x000ef06eb9cd7555,0x0000b18acd3df1a5,0x000c18b8dac35ee4,0x00001c7903921397}, {0x0001731faf0f10d2,0x0002d760c1326c4a,0x000f6f5ffea89051,0x000fc39c0f9ced36,0x0000da37d490e5c2}}, {{0x00023c3b69935ff7,0x0001b3e28de35919,0x000607e0e5dba168,0x000e0a1c7a1ab695,0x0000bc842d58c6bb}, {0x00050d68e758fca3,0x0000ca556db21bc5,0x00047dbec3ec857a,0x00078a4f47c22922,0x00009b45db21fb1f}}, {{0x000d2b6ed3921dae,0x000414a6a41de350,0x000e1bfe1f418863,0x000a7247d4440aa1,0x0000b202e69be99b}, {0x00035efe5f191a91,0x000303646d9b68c0,0x0007fafb6834e5cd,0x000afd13b66152d2,0x0000e96ff34fa402}}, {{0x000b50e619a7cc77,0x0000dee84fe2d25c,0x0007ba3f798fa246,0x0003a2051c8c69ea,0x00001559f9755949}, {0x000191005085716a,0x00048db5ae91d058,0x0007c9a5df811350,0x0001e3e76081f3fe,0x0000a0f5614b8aeb}}, {{0x00018f0a36ef4ceb,0x000febaebf8d4eae,0x000e5c11972c983d,0x000173cfd8c7fe1f,0x0000ff0b6553b58d}, {0x0009033ebd26a6ee,0x0009ca7741c57b63,0x0006d6d0466228cd,0x000813a88d56d595,0x0000001ac00370c6}}, {{0x0005d49926257fb8,0x00077f587dd695d7,0x00072592f34e8e90,0x00023c28f9cfa11c,0x00008d9950a9e218}, {0x00075ebe481c5af1,0x00050e45ff723481,0x000f61f5abfd66c4,0x000a368b3c547be6,0x00004be914ed594c}}, {{0x000d4cb73f9b6f7d,0x000e6906174ac89e,0x0004880c64f0fe98,0x00036ab58f236e04,0x0000e2d38bcdc3ab}, {0x000079f3c7af69a5,0x000d95f71ef374c3,0x00041a7447c72579,0x0002667971715ac4,0x0000cb5f998473fa}}, {{0x00092f2379f7fce1,0x000b91a877864bd9,0x000364c15e47690f,0x000ea25416b9dd02,0x0000a7502960f53b}, {0x00054d4ece71149c,0x00063a28d0321ca5,0x00027b740cac9de6,0x00064ca0b521c06f,0x000059d3a7108c18}}, {{0x0005870ea005a99e,0x000ded4e493a6467,0x0008b6342b1f047f,0x000374e92a439f17,0x0000a8cf07331051}, {0x0000b513642fc657,0x000dc5e958827812,0x0009b568996f4efd,0x000bfc8f6ef537ee,0x00006743642f3440}}, {{0x000e3950009e8bd3,0x000279e9228e1db5,0x0007ea75e0e087a5,0x000f0b16adfbb8b1,0x000019ff54645b70}, {0x000dbac58096735c,0x000bb470fce96e38,0x00074907665c92ce,0x0003152b53c9925c,0x00007fc121cadb2c}}, {{0x0002ee6e219e439c,0x0008fe4475fcfc8f,0x00032583de9c8ba6,0x000c3513fd771433,0x00001a001f040451}, {0x000cd5f7de1cf983,0x00085bb184294f07,0x000f814357b1fe00,0x0001ccad465687a2,0x00004f0c50019ffd}}, {{0x00030d60cc283637,0x0007dd26a89da97e,0x000f66c26f3bdc24,0x00028716946a9f2d,0x000049a732f2b2fe}, {0x000eef2bd92b8614,0x000b8f3412a393ac,0x000dd110fa90e595,0x0008b581363eb9d0,0x000070f21b629f74}}, {{0x000fad5927308e4f,0x00030bb54d64004a,0x000a41ebe0fe1a31,0x000560cebeee51f9,0x0000dac11edecab6}, {0x0001e3b630efedfc,0x00077c2beb530f9d,0x0005792e9f5dc319,0x000a71d1a7ea1706,0x00007af663c8c1cd}}, {{0x000da7bfbd9bb256,0x00088f98890312d0,0x0009548cec55316c,0x000574630b21bcd3,0x000068afb84e9c85}, {0x0009deff6c589987,0x0008e55e9876e7b2,0x000294123dbb7769,0x000712eb8772a9b1,0x0000839395ed1e6f}}, {{0x000c0a30eb328e86,0x000d5f3a638185aa,0x000c9547dffb413a,0x000f6fae6f8615ab,0x0000e8a6e4701dce}, {0x000b06cc1508bb6c,0x0001b02dbc1f68a9,0x000300f8c0971c4b,0x000fcc371a6d703e,0x0000572fdf15650b}}, {{0x00014db965071922,0x0003fd3a06369215,0x00011156ac525f3f,0x00027cdb39a981f8,0x00009ff3e0ddcbaf}, {0x0009eefc2c911a83,0x000dae8564210d12,0x000e48efd1688b3d,0x0001eba6dd9308c0,0x00001e6c71545583}}, {{0x000239152df58a36,0x0008b88e7897dc94,0x000725ab0da0e680,0x0005712ab70e052f,0x00002dfafe3d4212}, {0x0000c2b547371a4b,0x000f4634997de154,0x000cf959ac418e8c,0x0002b4c8fd0e263e,0x000002ca92f3a644}}, {{0x000805c84e906013,0x000919f4512d7d81,0x000b903bdb4e8554,0x000102020b9b4abd,0x0000a2f04651f18c}, {0x0006d4fa96d8846c,0x00065f0a7d84a420,0x000a4f5352b5e62c,0x000aebcd087cf50a,0x000089c1c7665b9e}}, {{0x0008e8c15f4490e1,0x000c711806b5723b,0x000f3dfcc9e3ac69,0x0003592e9cdffd09,0x0000676c5f59ab6b}, {0x000e90769fc0122e,0x000ab513ee51387a,0x0006265ef72c716a,0x000395f648e85a3a,0x0000f4445a0a69c7}}, {{0x00018151ce7faf96,0x0000532c5b17ec8e,0x00077e27fb8ef2dc,0x0009410a4e7962b7,0x0000c7bebe0dfb90}, {0x0005b36791119157,0x000f9791b658b9e3,0x000be736d2983a2e,0x000e11010136896a,0x0000c94c6654ec0f}}, {{0x000406ad44de0c1b,0x000c823978422f9c,0x0006f3621ed79654,0x0001a45243e9cb05,0x00005a526aaf5259}, {0x0006e9a9952c4041,0x000855d7a5dd0ef8,0x000dfa8b751cd3ea,0x00025c3d5a28b82f,0x00002a085cddda12}}, {{0x000574c792dd046d,0x000f5db7e04c0de0,0x0002d73f5299ae27,0x000f2bc6f076a4c8,0x0000f2221a703b2e}, {0x0002417d54d5b7b6,0x000fc839da3fd624,0x00044fe6c06c3727,0x000aaebb622fca7a,0x00001614329d0960}}, {{0x000325aa1dbc71da,0x0003a3f618cb10ed,0x000260f367d91c3c,0x00030ea528ea5e8e,0x0000e7f55131cb6b}, {0x0004e5c73aafc584,0x00007632d1f4e563,0x0003a9ada2a5f580,0x0003d5c9f78e98cd,0x00002612d9f9a844}}, {{0x0003160cc8cf665b,0x000e9e2cfb82d281,0x000edb5756ac3c06,0x000e86af8cadc78b,0x000071b8a8a9cc1f}, {0x0003f77d6e5686cf,0x0005209f60fd7801,0x0008985728540dc7,0x0000e66d1006fb9d,0x0000dc1d2d11771e}}, {{0x0004b1a3a9ebb91f,0x00079e23c8e26301,0x0003f0318faa7688,0x000cb05ca5649a17,0x0000ebcaa67af4d9}, {0x0002c158208295bd,0x000371886d2c6ec3,0x000e776fbf3d9c03,0x000b7362ad550edf,0x00001334c9a2dcf7}}, {{0x0005cdabf52ae483,0x000f0023da388f9f,0x000ea4f0b62843e1,0x0000cd6ef53468be,0x0000740e9f1ab937}, {0x00048cac670d194c,0x00029ef042cd432f,0x0004ca10792b2164,0x0001b35141393fa9,0x0000aa5fc8cb5d0c}}, {{0x0000b35727eb78be,0x0002fb568e8e3d15,0x0001e26a3e2ebfea,0x0002fe87e6eee810,0x00002e0c18aae6ca}, {0x000ae2e653b7bf2a,0x000aaae347811b25,0x000b752f14d7c1f6,0x000db47d5881de85,0x0000780051b01dcf}}, {{0x000c69e25aa2f590,0x000fcfeff037dd97,0x0006795b3afeec1a,0x000072a7aa5584f8,0x0000bd60ddffb0ab}, {0x0003d1d63579ef96,0x00038bdcb0ce53e6,0x0004cf4f0c7d0452,0x000c8c0caec14839,0x0000f6a443c4bfe1}}, {{0x000aec68e12bb566,0x000cadd2bf62c823,0x000164fe059a6763,0x0005e5b4c9c33897,0x0000c530539c6f12}, {0x00069d17e4ca16f3,0x00092006835fcdad,0x000446dd2c99910f,0x0006bb216844cce3,0x000072cda8fd616a}}, {{0x000043b5b6bfe4cb,0x000c16005febbe5c,0x0009968d097918c5,0x000f4e4a462373a4,0x0000b41b04486447}, {0x000539244c050f62,0x000a32282ebb4b0f,0x000cce069df1c278,0x00019d3afcac56b9,0x0000055958d3f6cc}}, {{0x0005beb93e6a98a7,0x0001afe915c2b32c,0x00073fe92bbdb3df,0x000079b9f6b3c836,0x00000e14fe20db48}, {0x0007c1023143cf73,0x000f8f3cb4626a39,0x0004f700663c36e3,0x00032fd7c3f3a263,0x0000681de4ac3a90}}, {{0x000e480c11b6a9ee,0x000d18da2ed97ee4,0x0008b99486776294,0x000a1dcdde1ed3b2,0x0000d4858b9d272d}, {0x000b8bde14ee45e7,0x000f52dae44f1c3c,0x00050b513d37586f,0x00076d444fd07f6a,0x0000af995ed1d2ea}}, {{0x00044d16e12de73c,0x0008fa09833ad676,0x000cd6eff8c6eec8,0x000211ef8af11042,0x0000dde13acc2a1a}, {0x000e1eb4ffd0ff5c,0x0007d068a68888ad,0x00042fbf6b645660,0x000e072b8fa57096,0x0000277b6578737e}}, {{0x0005f4f9aa856e82,0x000f2619d7efce68,0x0003de1a8a355582,0x000a02db631aaf40,0x0000ab82cdeda7bf}, {0x000e072b3caaef56,0x000a8199f1d82785,0x000d0fbdc36aed81,0x000cf338edd76909,0x0000ee323f0115ec}}, {{0x00091002ce826ecb,0x0005070eb620e97c,0x00030a866284171d,0x00087fc5ea32117f,0x0000e6dc3918a37d}, {0x00077c1f1c8587bf,0x0006106dfc0658fb,0x000423e93d2aa347,0x000d9893fef10a37,0x0000e7353a966099}}, {{0x000cd1f4fed94fd1,0x000122df66a25b2d,0x000312cbb38fa84c,0x00087fa9de6e108d,0x0000e58b82e39071}, {0x00062712709f1afb,0x0008220f16bf0299,0x0000e9cc7fc74306,0x000d421bdb073052,0x0000513ee8efcfab}}, {{0x00068279bad9b185,0x000b327666c7d175,0x0008c9c1dd36184d,0x0004cd676a4d1d70,0x000008a102f5f44f}, {0x000c7971cffbe4aa,0x0003a2729dcd0b70,0x000906aa5389c9b7,0x000ba57ecfcc1302,0x0000e349023971ac}}, {{0x000f9aa0de1a61d9,0x0001f5fa5b318663,0x00043909cd0eb9de,0x00070dd7cd579618,0x0000a3eba0c2f73f}, {0x0001563d342860ad,0x00037b084a171284,0x000349978d04890b,0x000779882982abae,0x0000299f32178cc3}}, {{0x0009f8c49c28aac3,0x00063d222aa77172,0x000103c13f3dda6b,0x000d9a62596af21a,0x00005e568bfd037b}, {0x0001e0a3cdd62251,0x0008c79442a934a4,0x0005966bddbc1924,0x000d996eb83bb296,0x0000d90edb6dce94}}, {{0x00040493f8013851,0x000ede0d970de34f,0x0009faf7a3b27f40,0x00096ad59ba58757,0x000057262f97764c}, {0x000fd035bf8844cc,0x0005a298a25a667c,0x000fe862aa4f48dd,0x000cfe02fa51099d,0x000012af89f023a9}}, {{0x000031e9fdea2db1,0x000832d1378f3a95,0x000a5138980ba7d5,0x00069a4bbdba0178,0x000013224e7af549}, {0x000465bcc967c9e7,0x0002d4159c9f2428,0x0007c9b27802478e,0x0008fa77cdc3d6ab,0x00005eb845feb91c}}, }, { /* digit=32 [{1,2,3,..,}]*([2^224]*G) */ {{0x000b2d9543778c7e,0x0000f184ad17cd35,0x0009a46cd9fa03ad,0x000d6d473d03630b,0x0000d62ab38692bf}, {0x0004c753b746abb8,0x000a9805cc3c45f4,0x000dcf780bd4f09d,0x0008b45e59befc01,0x0000428ee8930818}}, {{0x000e7e4fe75c81d7,0x00043a055bf3f186,0x00035ef774abdc47,0x000c9255708754bd,0x0000dc4ba227334a}, {0x0008b967e563c5e5,0x0005ffd12d0380e3,0x000770a428f47d00,0x000757a882b69d41,0x00001a9a96d95f73}}, {{0x000a784242f916eb,0x0003881ba08bc794,0x0005598b45b14359,0x000d754b78024dc8,0x0000f1f6b99a6382}, {0x000032cfc2cfa484,0x000c8e929e3f547d,0x00059d8829cc674e,0x0003a46aa7f2ecfc,0x0000788320c644f6}}, {{0x000719cf322c469b,0x000508f3f43cf975,0x000e62459967e01c,0x000174d43d2e7f3d,0x00008d9e6307095b}, {0x00021eba643504f0,0x000978c05daa5177,0x000a1e00ca592f59,0x000eacc0e1e26416,0x00003636fec99769}}, {{0x000f92768319d8df,0x00052450c06acb5c,0x000f8507a4008c6c,0x0003b281d931f721,0x0000415627b3750a}, {0x000f1a6fba4408d2,0x00097d431af170c9,0x000e56bd0b53c06d,0x00067f2c806e5c24,0x00008d4461687aa1}}, {{0x000c802e66289036,0x000a3e8fef25bf13,0x000531667a83b699,0x00062916e69a9032,0x0000326f5c93428d}, {0x00025675e2faf33d,0x000b9c7672692bbf,0x000dc358ce94e379,0x000e142af942870d,0x00008672198b68a5}}, {{0x000f91306ebdde85,0x000deccb55825166,0x000e2bed929a65cb,0x00089e0295a92cc2,0x0000e1f181df2c17}, {0x000223e7b6db2362,0x0001fcafee6e4f52,0x000d6487f3719ea2,0x0007b3ae4fb532be,0x000028642271114a}}, {{0x0002cedb269ab580,0x000d60cc26c5261c,0x000b8d89fae34d79,0x0001b3b61a336289,0x000038143332f363}, {0x0002e8df47ebad1e,0x000adec248835328,0x000adff3c2c72144,0x00017c5c7e5f1fb4,0x00000b437c44a55d}}, {{0x000f096ee9f20f71,0x0002602065c66848,0x000be0ba3d5ed400,0x000170008711a9db,0x0000c675cabb9082}, {0x00001a5382a25585,0x0009146dcc0627aa,0x000b9e8cd2497f62,0x000ce9d3863516a6,0x0000450d5c077a1d}}, {{0x000bb204eb1ee993,0x0000248697876b8e,0x0009b153201c458b,0x00061176db7875fa,0x0000a7194d5e99bd}, {0x000677cfea8c0c4a,0x000a3b5e4b4ebf64,0x000a40a1a68a382e,0x00017da42f53941e,0x0000cf37a3fd9a99}}, {{0x000f89d531aa521b,0x000d2cd651bbe08a,0x000e4807dc9acf2e,0x00064b6fd48bb09e,0x00000c23a0ed988d}, {0x000accaacd9c0465,0x000107b9102820de,0x0002f26b1b74087c,0x00024fc03e2a1a8c,0x0000e96ef37c79f5}}, {{0x000728e8507807fb,0x0000036e51fa4423,0x000c53ff715475b8,0x000abd5504dd5344,0x0000af2d60b21d24}, {0x000bcbc1aee6b633,0x0005403e9323219e,0x000c98408f908e14,0x000b388b548ad17f,0x000090118c4e2230}}, {{0x000dee15b199bc28,0x000c3ec9bdce59de,0x00065ca517f3fca5,0x0008ae7e6b17138e,0x0000784fd240f6aa}, {0x000b34895517b55d,0x000b5fbb4bca8fc7,0x0009e51560b1461d,0x00084b390e438efc,0x00008237a0c71050}}, {{0x000f4029482f6db1,0x000118db548d0404,0x000c18f0bbf747da,0x0001ad66134afd23,0x000094dcd37be9fe}, {0x00063b0dee6fdae6,0x00067ddfb415ac18,0x00080f9c5669ba44,0x0006d1752f950c9f,0x0000804af7be1120}}, {{0x0002ac943502b506,0x0004a8db8753f15a,0x00091c2ab67133b3,0x000a77d46c93c8cb,0x0000eb11fc244912}, {0x0007ed2e8e4fb729,0x000c26141a84a0bb,0x00028a4201f1077b,0x00044796a9fb7240,0x00008a44d90c3a6b}}, {{0x000b1148a2a41ffc,0x000c4865b95ebce8,0x000339dcdf6479e2,0x0005ca788dbd8b54,0x00002ea6baafdd0b}, {0x000edbe9b9fed913,0x000b6fe6b2206245,0x0001105f7b61f901,0x000d311b9cd2149f,0x0000736ac5f8b6fe}}, {{0x000559ba097b695f,0x000aa4c95ed7fd2b,0x000e2778f8711990,0x000cdc8cbf812ce5,0x000005cbb9ac407c}, {0x00027bd9059f0688,0x00032d37e6550791,0x000b95e9ffc012b5,0x00026ca112f8f653,0x000081248e6edfeb}}, {{0x000fd09736f5292d,0x000fed6e1546c027,0x0005355f15af57c6,0x0000dd4d11a6061f,0x0000478b38244148}, {0x0002a6999d7e8576,0x0007e0506d5152b7,0x0002a801e7ac65ff,0x0006595b43ed6866,0x00009951fde545e7}}, {{0x0001a071295d542e,0x000a51a0cc328460,0x0007e1fe3156a9fc,0x000d31bc6de53c42,0x000060f47cd2c597}, {0x000fe89df3012d41,0x0002da5a61ccecc0,0x000fcc1cfbeb7505,0x0003e0edb233e400,0x00001296a606f2cc}}, {{0x000af7da8d3682b4,0x0007212de42eeccd,0x000e95389b488c0b,0x00018a5aeeda5a59,0x0000474193abe0b7}, {0x000ee97fbc642a3d,0x000cfc9230f0fde2,0x000e131dd8901307,0x000d7c11c9bdb27c,0x0000d12ac316724b}}, {{0x000d17162e8e5a89,0x000bc66e49efb223,0x00032c9d77f37db3,0x00008043efc71fee,0x00006af3cf6922ce}, {0x0008b9edfb4d41be,0x000844d25cc9d80e,0x000b65b33958a078,0x00079779756de346,0x00001047c9633e6c}}, {{0x0001564562861678,0x0007624f5cf93034,0x00042ddd963d4ea7,0x000eaa5452277ebc,0x0000f778004d947a}, {0x0001d5def2c56adf,0x0003ae9887f18ecf,0x000a1bf7ebc72b29,0x00097380809dd58f,0x000017a4ef6dc806}}, {{0x000ffbc9689eda66,0x000883cbbaca1e51,0x000bd0b4d8274f68,0x000fe6bc2914046c,0x0000ec4eebe6b263}, {0x0005ffb314eea5f2,0x000725a4dacce9fb,0x000c953fe6a21a13,0x000ec703932270ec,0x0000c0a405e7c67e}}, {{0x000c2104134b7fa7,0x000cb3ca29958ec1,0x0005393c52936dfd,0x0004c4da1702d97f,0x0000076b85955721}, {0x0004e97b47458ce3,0x000b0255e87b6495,0x000978b25d48c2ed,0x00049992e3869a33,0x0000244683c71001}}, {{0x000bbb5e9143e442,0x00055db9d859c5c0,0x000375cb2b951190,0x0001b1733a3e81f9,0x0000ac5b03ec9ddb}, {0x0007d302948b0cd7,0x0004f9a6575ac87e,0x0007e4790e2f1bd4,0x000630d239465cc1,0x0000495665c00aab}}, {{0x00003d0220dd5b89,0x00050373b8bcb287,0x000b0ad2922a78e9,0x000846833d2f1554,0x000074a397b3fb03}, {0x000d9918bc837c91,0x000769a8126c6a24,0x000f1b5a8b117dd9,0x0001af8d5aafba53,0x0000dd131159eb82}}, {{0x000a397f380ea2a5,0x000e34cd48b2b67c,0x0008c1b9089a0492,0x0000b7cfb2598235,0x00000f8994fbca51}, {0x0001ef0d4dc6c624,0x0009298199b2a1ec,0x00087db3d9e0b8b3,0x00099bbc93b64cd2,0x0000cd843c51f5fb}}, {{0x000f2327e09ec79d,0x00048f5c71fc1d62,0x000a82286325e75b,0x000fe92ccbe59c8d,0x00006fa414a59f54}, {0x000724008dcda821,0x00010b18f8339015,0x000cf347b8cc0b11,0x000128d6947544c4,0x0000ee012db1fa6c}}, {{0x00050c20403a0188,0x000194e8aeedbe60,0x0004a13ba2ac81b4,0x0004e49f3507ba09,0x0000a84889026e6f}, {0x0007b081fb782f23,0x00008c896e27b256,0x000d7b64ff3aa055,0x0008e9a6a881dd34,0x000087a29a866dca}}, {{0x000f6328d9d29d96,0x000d08db211bfd9b,0x000196c59440e6de,0x0006dfc8e0e709a0,0x0000f9e5f4bbfa4c}, {0x000465c50215dae0,0x0005eb2929551f20,0x000717e82209b62c,0x0005f3c4562e90e6,0x0000e285dee28eb8}}, {{0x000205c0600232bd,0x000431f8827f3763,0x000527014aa51d8a,0x000c1fa849aa3f41,0x00008ba1d2ff2e5d}, {0x0001bc02ae95f211,0x000374b719625b66,0x000a5dfbf82172e2,0x000b0210053bc018,0x0000a5c238000900}}, {{0x0006fb6e9e7d0596,0x000bb48d628f76a4,0x000537258d83215f,0x0000496c09409290,0x000066b4a0c8e820}, {0x0001553dd1a5b840,0x00079e8bc4811584,0x00014f392f62ee96,0x0004d21271a3266c,0x0000c58bc7ed96c9}}, {{0x000f14924e235001,0x0007aac142e06662,0x000c167087c97cfa,0x000e77976870a24d,0x000066e483cc4979}, {0x000f427bdff1294c,0x000acb0b96b81737,0x0003562de53d5748,0x00004ef798c420eb,0x0000348b0d67a82f}}, {{0x00034268181809e0,0x000330cf8b408ce8,0x000667cd7f1007cc,0x00096db7b5dbc432,0x00004a5fdb5ab287}, {0x0000a0bbf904ec7c,0x0004515938c30e2e,0x0000e23f53a28bcd,0x0009f9b087f747b9,0x00007ca540d88594}}, {{0x0000d0129cd59a23,0x00046c9cc596ba69,0x0006da59b804d17f,0x0003a7fcd9be29ff,0x00009391f4a28708}, {0x0002481b5b5fd7cc,0x0002560774cebe2d,0x000e9d1e0bc3a862,0x000a4e0a9a5290cb,0x00009ae842e67c86}}, {{0x00070bee0bc209ae,0x0001fa68d56bcc57,0x000336ccfc8acb05,0x00056142ff984b5a,0x00002395e2c8eaf0}, {0x000ee62df7bd9c4d,0x000e990aead7b27a,0x0008b9905f304af8,0x00087890cb620c4e,0x00008a6a079e2dad}}, {{0x000c8dcd3073a282,0x000eccbae3857ecd,0x0006a1bbf1f16623,0x000a2b699d780d31,0x0000a776063eab23}, {0x00035739c18802d9,0x0008be6cd5f5211c,0x0009c468c8a0afc2,0x00066879d94b3d64,0x000009f3b2c364ec}}, {{0x000a623675caa390,0x00028de287f93701,0x00038ba2ae9ab86e,0x0007f403801b55dd,0x00005f51848e944f}, {0x00047ca0ec88095e,0x000876d34449537b,0x000f35de03bacc95,0x00060e05b1b4f1ff,0x0000e43d1be7522d}}, {{0x00091191b64ddcb0,0x000c0794106d2195,0x0003f8ccc8b5d196,0x000c12c9dc943645,0x000075d1ab7bf58a}, {0x000f0de89450cd20,0x0002aef9f6ef6324,0x000c1a78a35e6afc,0x000a26e7aaebd3f9,0x00004364f4e1540f}}, {{0x000647708e12eadb,0x000e541c5a2c7a67,0x00065c0fd50feaec,0x00094ee408014a21,0x000031b912b28fcf}, {0x000e4a198d6c20a2,0x00014241bc066c87,0x0003cfb9a4b52b25,0x000955038acdc322,0x000092e10576361d}}, {{0x000de1ccb3d8e2fa,0x0007927ebdcc0d1a,0x0002337815f56cdd,0x0000d85fffd1121b,0x00003cbd45e59c0c}, {0x0007f3a600093df9,0x0008803285131a3e,0x000bc6bc473d5036,0x000a13a8c656b44d,0x00000f99f5a3c8cd}}, {{0x000e2b91357917d6,0x0004af49c788ab9d,0x0009b75be9a83bb4,0x000609521c19f260,0x00006e8679e9c4c9}, {0x0009644a604a9c50,0x0006a166441a0a62,0x000f865732bd6b62,0x0004a024589222df,0x00009ff82ef1d308}}, {{0x000eb11759f3013a,0x000c301c5150e323,0x000fc70dfc2b0fa7,0x0005d3b88ecf6620,0x000062d12a272f04}, {0x000692973b38bb4e,0x000d47714e446b89,0x0004821687518ba7,0x000a53ba0fa24858,0x0000f49c5dc1b4cd}}, {{0x00074d983ef0560e,0x00040d3c61a6ebd3,0x00049367c38c1271,0x000f0b2401895ccb,0x000001ef869f5737}, {0x000614a7234ff845,0x000dea374efd0e7d,0x000f6ee62c289cdf,0x0009ae62ef2db27b,0x000014784cee48aa}}, {{0x000159129c7218f2,0x000a4b541372a190,0x000bd9f602675cae,0x0004cd6bce2b878e,0x00002512bc39576b}, {0x000dce0a8803d993,0x000c6cb44bb6fca3,0x000f6629ead7ed05,0x000912b0c7932084,0x00004002232bf471}}, {{0x00001d2621033b58,0x0001f8fc3dd965c4,0x000ffb247e571eb2,0x000a0595cb93a225,0x00006a8adbe4947a}, {0x00051a6245eb6e91,0x000576eef743cb9c,0x00071f3cc875e4bd,0x000d32e4f4b68e10,0x0000cfc7a753fcc9}}, {{0x0004b5ad8454309c,0x0006a96c32757c42,0x0002adc838288f2e,0x000629309a27d6c0,0x0000768fa5916f5e}, {0x000ffe6b0e8c2f5b,0x00052be31993a968,0x00095c2da86b50da,0x0002e92416e8bccf,0x0000ead84d4d2c31}}, {{0x0004170fe1d6eaee,0x0000fc0d00121e46,0x000299ad5553d9d8,0x000da5c3949da0b4,0x00003391fdbfb09d}, {0x000007f4de911dcb,0x000013813852ad9b,0x00059598b370cba1,0x000b9b0b5de1bad6,0x00005d49170081f0}}, {{0x0006b63bfed067e9,0x000222470ef49d4e,0x000e7714fcfc954f,0x0003504782951149,0x0000a36523156374}, {0x000bffff641c505c,0x000a9e6f797f68f4,0x0005b45bf19da0eb,0x00014b7ce6bed3d2,0x0000cf9f5296d91a}}, {{0x0009f207b21eb218,0x00028586cffb7a0b,0x0008f3fbd0c3918c,0x00078201c70c1850,0x0000fb503e59c258}, {0x000cfbaddcbe4dc7,0x000f3120734c0d9c,0x000bd2bfeb7c7b4f,0x0001a34a1db6fa8d,0x00005381611bf031}}, {{0x0000a263cc6eff32,0x0002da89d5f5188f,0x000998b48a9b7274,0x000a6a1ab7e090ce,0x0000c9c108427eed}, {0x000f32ca05971eb5,0x000453079a84fa1b,0x000b8e4604f377cc,0x000af86c83784d7c,0x00008f9d8ae61637}}, {{0x0006bab37064a7ba,0x000afe0450e00b42,0x000d6875d28c4234,0x000c62f083b2f98b,0x00000c3d4377d759}, {0x00076976a45017b2,0x000880119d2b1ae5,0x0002e89d560ca989,0x00017efbe57b32f3,0x0000d217b1d4d05a}}, {{0x0001246609a703d2,0x0008581f5ff0012b,0x000ed431681c4d33,0x000889e339cc9e61,0x0000c41d7af37992}, {0x00040e40ee5add10,0x00035ce326c02808,0x00011acb7ee358e6,0x000753b73e148f47,0x0000b41cc70c70ed}}, {{0x0001e8a27fc5bb80,0x00023f9ce2773a00,0x000f5d4d0de3c75a,0x000ae0e67462e5ab,0x00005f356d1edad7}, {0x0005eb5f99aa27f3,0x000299fa1850b2d6,0x000ed719ea950e23,0x000f6d30fbc3a134,0x0000c607bc2d868a}}, {{0x000e0dfc812789b9,0x000bf86fbb02a48d,0x0004c91b7d673e7b,0x0009d220bd69b769,0x00007aa28a6d3b5b}, {0x000c81d68bb3e89c,0x000a9675845e91f9,0x00021b13aa03e749,0x000266a5bef7793d,0x00004d522c8aac9d}}, {{0x000314f0f6a1c7c8,0x0008a2a54dd0d604,0x00034a4a739d70d0,0x000841041cd0a4f0,0x00004a610e679a6e}, {0x0004259d51ad71d0,0x00042afded7b4144,0x000ec9b81308724e,0x000c0385af63d00e,0x000069d0017809f1}}, {{0x000cc7faf31bc33c,0x000170b86ea12ac6,0x000118a6da045fa1,0x00064c601bb95001,0x00000823d360ce62}, {0x000d0907a77ed7bb,0x000c5e207baeca4a,0x00060d6267b9621f,0x0000becb62bef413,0x0000d67d9cdb9a0f}}, {{0x000944561b2ae48d,0x0007606ca32aa2ce,0x000a0f576a73ae7e,0x0001f59d79acd4f0,0x0000f91e47274349}, {0x000f58ed0786fa06,0x00003b6fb73155cd,0x0008196d63d3af60,0x0004a1abf0728a90,0x0000cc301947a07d}}, {{0x000173fcda66688d,0x000968f54078a044,0x000b892a6e4f3e8d,0x0000a6e9a8aa3f76,0x000003f2358c3edd}, {0x000c73ddba515a86,0x00031571066fc332,0x0009a52dd8494f4f,0x000596f40df54b23,0x000033c2a77c2737}}, {{0x000ccc6a38469a7b,0x0000dfeabba0419f,0x00010b4aef255f07,0x0006f5fc0d85c473,0x0000844714199f30}, {0x00044a1800f79726,0x00003e748495b202,0x000fe708b728cd1d,0x00039fdb9df876a1,0x000044dfaeed2e69}}, {{0x0009efb3b1befb52,0x000dd3db9ff2d119,0x000d54531b9666f3,0x000ef6ae6ecaa250,0x00000a5b3d55478d}, {0x00017d0cbe53c8f4,0x000f93025e9358c1,0x000f7b33ecb21d3e,0x0009e51f5b49200c,0x0000a7b0480bbb55}}, {{0x000419c661687e70,0x000df62ce653f542,0x000907c00a126d6e,0x00080f9eed2326cd,0x0000422a8722b335}, {0x000534595c60a63b,0x0001ede5c24ec59f,0x00040fac2dc4f284,0x000b07e5a5d36fcf,0x000093bb56108a49}}, {{0x000250012f4ef06f,0x0009f321814949f5,0x000d1cc017a50bad,0x0007969417282b08,0x000037ff4efb3e13}, {0x00043412190a4c29,0x0004b018dc035a37,0x0002185201cb14ca,0x00062453f92f5aeb,0x00006f2a7e6de00e}}, {{0x000cc31c7ee87f99,0x0004ff0f8aafbabc,0x000a827098c656c9,0x000768469f364b3b,0x0000447f273ba78e}, {0x00012a02b0c76f80,0x000531f409e3b92c,0x0003182511cfed50,0x000d99f57fb201e9,0x000056a73dfa1e29}}, }, { /* digit=33 [{1,2,3,..,}]*([2^231]*G) */ {{0x000a2dbe215c3b8b,0x000f884ce45689c6,0x0001d2f99ea9d0b4,0x000bd1cc1cb2174b,0x000007f8af7769d6}, {0x000eccb56ca3c064,0x000c39f4aea85da5,0x000dfcc2e6466598,0x000634cd8c935e85,0x00006ec507784fa1}}, {{0x0009bc96b496a337,0x0001a1b2a3f800a5,0x000d4849519c3461,0x000db18fc2569c8b,0x0000b3cfcd94befa}, {0x000b4eb10b12d26e,0x000c1e97882a2059,0x00063f99dce2a002,0x000c447d77efe3aa,0x0000db216f26ed6a}}, {{0x00018c63ece662c0,0x000a493d31f196f3,0x000906fc16932e12,0x00049057ef719d82,0x000018862ee36f81}, {0x00038809d700b8c4,0x0007c005edd01de2,0x000ff477e0932f9a,0x000e87c6433b3745,0x000003ad9c08d54a}}, {{0x000c11886bc24c43,0x000e560aecce0485,0x000f9b2977cba2fd,0x000e25b0e545401b,0x000025a455e793cd}, {0x00031a786e57de70,0x0007942d10e0c90b,0x000728cff7ca8ade,0x000d9169618b125a,0x00006ddeb0245afa}}, {{0x000527e462b3815e,0x000471040d6d3d81,0x0006a10bf201ce2e,0x00030111185978fa,0x000050eb91c129a9}, {0x000e282a5d067477,0x00069217051858a0,0x0004001b5ab39043,0x000546a05205fa47,0x000092822e494ea6}}, {{0x0000adf6b5dfc7f2,0x00013e0797f2d1f2,0x000d16de2c2918ec,0x000bf5a4b2e613de,0x00009b8761499478}, {0x000f016f7b3256e4,0x0003de3e31def4dd,0x0009e833ac658d9e,0x0002df9cf95488f0,0x00007b7761d27f55}}, {{0x0005841c4e740ce0,0x000b177b99bc2a6d,0x000904ce22809135,0x00082f03a03fc8cf,0x0000705c0bf36b5b}, {0x000056724d3e873d,0x000a122406826f04,0x000e68bc339873d5,0x000fe7ba392091ad,0x00008baee7844c64}}, {{0x000929675be6922d,0x0001213a70da1b6f,0x0009a47bf6932638,0x000303b2b11e85f7,0x000061c91b9a2552}, {0x000f571053bef378,0x0008b2051d390a9a,0x0007f02ef5fb0b6e,0x00041047f4682ca1,0x00009401362dc590}}, {{0x0007de12cad37a4f,0x00067f0d1f0a5333,0x000e96610c120cd7,0x0006283c745aaf2c,0x0000076bfca61a10}, {0x000798e91fe1dac9,0x0001ad2dd163c294,0x000e1f0a0c8c6588,0x000935de3e18d763,0x0000ba965532ca62}}, {{0x0007623440b9b877,0x000a956d4db76d55,0x00020f4c8385ebbf,0x000d33d8735cdb8e,0x000016f0b0a75dfe}, {0x00036c0ba0e7092d,0x000d6dfad54aad69,0x00060683455d3376,0x0007bf127965ffcb,0x0000681b61bb1f63}}, {{0x0009fcb83e9c7da1,0x000095ad4e66dedd,0x000319f0c0213304,0x000440bc0916b195,0x0000b5e953298188}, {0x0004bdc725dd35fc,0x0002eb60236de83f,0x000f3212cba2f5b6,0x0006b84c9c629414,0x000096bd8d34a8c1}}, {{0x0004d6dc80f87d6a,0x000f7d8a2163bc94,0x000ceda80be2312d,0x000b2aa43026be75,0x00002edd166aede9}, {0x000c606ca8c0666c,0x00010c2bcbd751bc,0x000382e1aeb1ed71,0x000c659561279121,0x000056fe8e73cf6c}}, {{0x000adbcbc1c3b15f,0x00046039a4313266,0x0002f2dea642ad5a,0x0007adadcfbaf904,0x00007547c5c21508}, {0x00015c16ec80761e,0x0003fa9e8435733a,0x000d36a8d8a3a115,0x000a4ddd0a6919aa,0x00009e7377d0e427}}, {{0x0006e39e2d28ea84,0x000e750985b22c70,0x00029d6b3707d572,0x0000eff5dcca6438,0x0000aefa25e7768d}, {0x00017dff52661252,0x0005251d4caff7af,0x000902575f409232,0x000c7c7a8e670e6c,0x00005774dda3abf1}}, {{0x00001285e5eb464b,0x000cecbc4c7510fd,0x00036c854df0124e,0x0000a49a1c719cf6,0x0000cc1c52a5ebe0}, {0x00070df7350f9229,0x0001991f61845b72,0x000192d67dac63a8,0x000be321af84188b,0x0000748d9575b564}}, {{0x000b281c9947edae,0x000fa609d25cf20c,0x000adaa68d459e53,0x000b86b0a79588cb,0x000097fec12d5258}, {0x000b88cb27d7e1dc,0x00050c5b8023206c,0x0006b92572ba3d39,0x000d3a3da394ded9,0x000058c9b408ddbc}}, {{0x0005a17512d500c9,0x000bf90baf002f44,0x00044b074849f6d7,0x0009a667b85738a4,0x00001d723bfeecaf}, {0x00019a4f16591f2b,0x0002d5b54c67aba9,0x0003cb20eafab933,0x00052d84b720e282,0x000036c1b31c4a53}}, {{0x000dc48359ae88b3,0x00095b94925a7673,0x000d28c38c7da6d7,0x000449b9611f43d1,0x0000507e76bb8c39}, {0x000a4109b143d327,0x00085897b4d64670,0x000ec856db407a04,0x000c3391b35a7c2b,0x00004729f04e48e2}}, {{0x0000e287d444576f,0x000fa46c0fcedfc1,0x000c4bc495541641,0x000dc4c61a898da2,0x0000c49474474950}, {0x0005d34a86e99ff6,0x000dde84f0eb279c,0x0008b517448eb4a2,0x00020f168c48d9af,0x0000d2e2947e6a6c}}, {{0x000d4b7fc5ddff94,0x0008b8cd5d76c4ee,0x000e6ec7533c62e9,0x000b64d05167db0e,0x0000723b4547dadf}, {0x0003255992390795,0x000cf88d2ea48646,0x0007f30d8f37975a,0x00001460943feac1,0x0000681ac9cf176a}}, {{0x000b8b6daae521b7,0x000adbdf2be35556,0x000f2c0e8441695d,0x00052433bb1bc3fe,0x0000a6eeb8381b5f}, {0x0008b6d0a7d65ee1,0x0008d0ed4f2aa649,0x0009d15a7352ac47,0x0008209e26a67a00,0x0000eabbbcca5492}}, {{0x000ce07d1a83db8c,0x0001217601ca6e80,0x000bf1f026fe55be,0x00067c6a6a9b77f3,0x00002da4da482151}, {0x00050ce0660bb9c8,0x000c647dbdd30a3f,0x0000ce6acc0badf2,0x000af2afe2cb4eb2,0x0000df11e844ac4c}}, {{0x000bcbea50bf7b2c,0x000d6fa5e1ea7e76,0x0005104e4d183277,0x0003530de5287e95,0x000061dbeae917cc}, {0x000361797e3c36a8,0x0006a4c11975d8d7,0x00056ffe587eac28,0x000ec4cf96fe62e6,0x0000ff2a60a5ece8}}, {{0x0005b7d6b5c17565,0x000e725336dfb23f,0x000f699eb5967d95,0x0001d71cc4a1282c,0x00006f2d1e5dbace}, {0x000cc2260eba8909,0x000a041a0642f2b6,0x0009abfc6cbfaebf,0x000997d9347b4051,0x00006c695a44b98a}}, {{0x0001ae8291d465ef,0x000694bf89326d90,0x0001c482f1ffe9f3,0x000d2382bad4525e,0x0000168c52db0bcd}, {0x0006017568b375d4,0x00089290b50e580a,0x000f160a15743a92,0x0005551201b0040b,0x0000581e3cdcd77d}}, {{0x000874ca4cd68d8e,0x000f8c4484600f4f,0x0005c73324d85176,0x000fecbac7c97f28,0x000079aa93211324}, {0x00075824d0274253,0x00064d8b475d6b62,0x000eaa57375d9aa1,0x0000f362be914bdd,0x00004995d6eeabfd}}, {{0x0009820f41846ba3,0x0000604085981174,0x000978a94fd1bcdf,0x000d0ba2fed0a907,0x0000ba1d2eda2efd}, {0x0008512656b5739f,0x000594918c39e3e4,0x0000b6224e9c896a,0x000d5bbb1875d792,0x0000b93012187315}}, {{0x00019ed5ba8931b4,0x0005acd90608de3c,0x000b33a89ff0f3a9,0x00089e41298c1df6,0x00000292d30c3fde}, {0x000d7df4a273bfe2,0x000087b011c26348,0x000a2dc24b8b9f1f,0x0000ad39d9d45852,0x000067daaf3663ad}}, {{0x000dd476f0bcde8e,0x00074f1aef494e4f,0x0004bfcbf6a3568b,0x0004f71520bf6fc8,0x00000306160f678b}, {0x000e43f9114c874a,0x0006a66a6723e3a0,0x000fa916c94626c1,0x000e1a4c6dbb2fcb,0x0000a2a7851b6164}}, {{0x000f6c17b91cb2fb,0x000022d25723d046,0x000c4a5d56108b74,0x000423bab6def6ce,0x0000c2cabcf84f05}, {0x0009b3aeef06e341,0x00032ae65511bd33,0x0009815f724c639f,0x00015a5666c8aa1e,0x00004c097c5786e0}}, {{0x000b7ddec96a31f1,0x000bb6126e7d0171,0x0003107612ab4881,0x000f991937b21ce8,0x0000c2f1836cf5e4}, {0x000f324d669b052c,0x000bbf0d0024898d,0x000fedf68f963603,0x000e5446be060625,0x00008eaa3a89c4b0}}, {{0x0003578addae3db2,0x0001256b65bb4a56,0x000f89bb28f673ae,0x000ce0f3897587f4,0x0000e7b5627e000b}, {0x000373d4ebc646ed,0x000c26c01b67d1af,0x00046e755320c491,0x000df2ed183b1a53,0x00003dc80714e3ef}}, {{0x0001d181707854b5,0x000e045ed6440d70,0x0008141226b65beb,0x0005fac44ea8ce1b,0x00004d31afc2b255}, {0x0000f1d4fd98ed23,0x0000361122a75ad2,0x000dba8c53597134,0x000fd9b5173a0d9d,0x00005c6b22beb557}}, {{0x0002ee43acde4fa2,0x0003572b4de2188c,0x0009e491b7321151,0x000935ef340f8681,0x00003ae38901b2ff}, {0x0001fe8fde235367,0x0003c3ac4d9e99a9,0x0002c2b7c3253510,0x000130bcc3a87d5a,0x000018cf5dc1d05b}}, {{0x000b0ea388337482,0x0005bc0ab3d81a29,0x000f26100c68ffe3,0x000c3d24c4d4108f,0x0000f14a32ccd1dd}, {0x0000a315097789d0,0x000b428d4c71c703,0x000a782fabac5dc1,0x00014d3bba4799bd,0x0000e5c67c1d3f71}}, {{0x000dee9bee66b26b,0x00040993141604b7,0x000f8818745348d7,0x000064a5cf2b66d8,0x000035fa570e7a60}, {0x000e3b2e90a9f6a4,0x000a93d618844b8b,0x000e1533c3136043,0x0004b406fc07f2f6,0x0000e68110e4d8d2}}, {{0x0009c06a197144e0,0x000a0ebd90e8998b,0x0004637e982d59c0,0x000346ad1dcaf45b,0x000059c29fb15ffe}, {0x000e68bd0de11ce1,0x0000ef9123f1e4ad,0x000809e2e7028807,0x0001a38b44fb792e,0x000021fdeb0bf5a4}}, {{0x000b525dfbbe18f4,0x0006ce6bebd7328a,0x0005014218d893eb,0x0007f27415906d1b,0x0000683c30795a82}, {0x0003859154db22e4,0x0003c459a6b28d30,0x000d54f8a9fdddf8,0x000441f5e0dcb8f5,0x0000b323984a4542}}, {{0x00020890ea27494a,0x000e1e35ace9abf1,0x0005949a7637aefb,0x00092a65ed6aed2e,0x00009fb6d9b1e31c}, {0x000c850fe43da55b,0x000c7a2aebb47154,0x0005a1f29c49139d,0x000f8c8a3b6609e8,0x0000c0e447c73747}}, {{0x0003b83c899e16c9,0x0007290a4c485b88,0x0005c11ac3264056,0x000b31c23fdf0557,0x0000d6294d704452}, {0x0005adda6fd01b3a,0x000ed638d76cebf3,0x000bc2a591640d40,0x00090bcb6beb8873,0x00005774079636cf}}, {{0x000d07a4df05112a,0x000c75ef10b3ed9e,0x00000dc454558b1b,0x00068ee57b1c4e11,0x0000c05303af0df1}, {0x000ff70dbf770c49,0x00078abb8add6239,0x00051783cf1da24a,0x00085717000ea909,0x000083c07443aa20}}, {{0x000e669c9aa38ff1,0x000cdf9b6663ec67,0x000fbaf822c76f14,0x000d8f2e05f459fa,0x000081bfa0e72146}, {0x00031960fccc9403,0x000079ddbab69572,0x000c0f236afff64a,0x000c6b8a2dc2b77e,0x0000cd9b9db0072c}}, {{0x000f50005e38e681,0x00011d2a53bfce83,0x000d3127de4fb9f7,0x000a7389040d2691,0x000090991b1df4f9}, {0x000f4d487fb49c70,0x000acbf3cd2d4b92,0x0004a8e9f3453a0d,0x00056284948bf480,0x0000bf9b42b8763c}}, {{0x00085bea7295b89f,0x00032c67fdbe5c4a,0x000dfa99ff9b5214,0x0003dcf7dd419d4b,0x000053b1b1f00c14}, {0x000fc48e64a06587,0x000c86e4c0bd1189,0x000f07b904597445,0x00012361c88b11d0,0x0000de6046f7d84d}}, {{0x00087bbacc585b5c,0x00054110d0cc505c,0x000cc9394ff5fa6b,0x000013753c1362a9,0x0000f747b69989a6}, {0x0001acdff683da86,0x00085c9ade093e40,0x0009346cc256f729,0x0003da9907d05802,0x000068d87f52e4e5}}, {{0x00072320892f7939,0x000ecfb65e03e668,0x00005b60e8867af8,0x0006db6855960ac2,0x00007cfe82946f8d}, {0x000126504e895a59,0x00082f9ab1ae37c7,0x0003475b8072a97d,0x0009b271cf682e37,0x0000a001e427da0c}}, {{0x000f56aa1c2ac6a2,0x000b0056bb5e8607,0x000840d5e7b5a2f6,0x0002a8575fce01b3,0x0000bd0d02a2a11f}, {0x00020acf5e461b5d,0x000143f8b7882cb9,0x0005684f429c8f84,0x000b43261bec02c9,0x0000976e4c74bcf7}}, {{0x0008818531ad28e4,0x0004e2d377207b87,0x0004885027f26899,0x000503f289ead51e,0x000098cca8ee68f8}, {0x000c970b5c5d77dc,0x000080459981f27b,0x000b87fa1544bbcc,0x00070d2411cca590,0x000054ea81cf6071}}, {{0x000086e61ca59dc9,0x00021cd8c326fa3c,0x000811dadebe13e0,0x00041b5d83482a0d,0x0000a49369b21466}, {0x000c7cd8304d967f,0x000e9364df0d6130,0x000343b0e27f449a,0x000d17ab76d37fee,0x00008a1d0ed05ee5}}, {{0x00046cadc6205653,0x000ab65343bf3181,0x000556549569c932,0x0006bd0af34c44f4,0x0000ee209046d270}, {0x0000c0ef40c6247e,0x000dedf91b009463,0x000bb38be3f102c0,0x000064d340ea43f7,0x0000e2d7c507278a}}, {{0x0001fc4894efce0e,0x000d16f705c791bb,0x00001c6f5dcb8966,0x000e5e4eff50cb1f,0x000096a8482ad3cb}, {0x000dec26d0cfd830,0x0003040d53e317a4,0x0007f8e26336612c,0x000559bd95bdd1d6,0x0000ccd1e540626e}}, {{0x00068bdee681a9fd,0x00019176d44b5bc5,0x00088a36d1aaa6b0,0x000c7bf9e56290f9,0x0000b5d955ba2779}, {0x00025fcd134d4965,0x0005ff8f9c5b8014,0x00085dfc847e63e2,0x0001a0634eecfe39,0x00008b0e4909de31}}, {{0x000397d6afe3edfb,0x000ead213cf0c484,0x000fe129db20b9ba,0x0004aa03eebcca16,0x0000ac8b193bcbab}, {0x000d00ec766789a2,0x00007b641c6280af,0x00012d36a671a1b6,0x000788d44e1010d6,0x0000e906a8a2cc4f}}, {{0x00085346f1857b14,0x0003410a4089af78,0x000c2398d5cc5098,0x000b93ca8a5f67b0,0x00004695f3af907d}, {0x000f016bdb075823,0x00067ed27633c156,0x000a99381e81d34c,0x000d88bd4282e4c4,0x00008536f5808ba6}}, {{0x00099ab2afcd854b,0x0007d8eda94411de,0x000c8a192d747cf5,0x000c2d246295bece,0x00001424f4c40f48}, {0x0001c25b3f186f40,0x0003eb32b7394006,0x000ddbfc3b2985f6,0x000d7fda0dd1d8fa,0x00009df5df39c2fc}}, {{0x000736cb9995a1c8,0x0003f161f3b15ad2,0x00016b96e4f367b2,0x000c18470c49cfa2,0x00001b9d55b9d130}, {0x0005a5f78a9f0c67,0x00021aa433e2085d,0x0000dcf549740986,0x000faed0c9af8ba4,0x00009380b92d46a9}}, {{0x0002c88c54018551,0x00029c0673e5a8f4,0x00054155f79a8500,0x0007f49c76fa0d73,0x0000e0e7821cfcaf}, {0x000a0f6255d3014f,0x0001c980f9fa8f28,0x000cc0b0ed7bc620,0x0000f657b694eb76,0x00003dc3e7fd436b}}, {{0x000900f0e2ab22a4,0x0007485db521beeb,0x000e657e4f9fc7b6,0x000645a1ee59ad38,0x00005db32d0f9721}, {0x000237fe16ed3e0e,0x000bbb7178cab7d5,0x0001c17f2278f133,0x000c4cba85c30874,0x00007993168c23c7}}, {{0x00019588e7f16445,0x0007acc30bbdcc18,0x0000d00fb3765dae,0x000e56c47a4fe57d,0x0000540123b0db2d}, {0x00027a35c65a51ed,0x000209b84b2313a2,0x0007634784e94bf1,0x0001a877d76a3143,0x0000a49efebe4d8e}}, {{0x000c9dbf562fa402,0x00091c7548693347,0x0001d08b33389499,0x00003924b7a2ed2c,0x000073ffa2df5839}, {0x0004bddada7df426,0x0007a35d8ec44b5a,0x000d0629a0a53add,0x000c22216b46cf5c,0x0000156ae4a410f7}}, {{0x000684c43a0908b4,0x0008578d18268934,0x0008e8668505170f,0x000d80851c09a959,0x000081f6e0c2f121}, {0x000e6b0e93141606,0x0003960731d37a3f,0x000fc8e4b7861d75,0x000aec6eb173ec4d,0x0000839de40cf2b4}}, {{0x0009da66960a1d07,0x00027d771fe97d30,0x000fac3ad619dafb,0x000baf9f688aba90,0x0000f8d73eab08be}, {0x0004a8a35306c347,0x0002ece26a385f6e,0x0005297e499a6cb6,0x0000e956434c7490,0x0000f8fac1dfe93b}}, {{0x0000533de36faba0,0x00016d1b717153e6,0x000e7b6a46cd71d1,0x000b0d8454ddf26c,0x0000d2dfeda7af6e}, {0x000a49d8f229e942,0x000aeebbb5a51c05,0x00026ea87b89faf8,0x00040f65455941df,0x0000270c9e42b6c2}}, {{0x000fccb792331f1f,0x000bbd5f4310303e,0x0005487a9aa841df,0x000687415985039d,0x00000722f292f10a}, {0x0002b63fa69dbac1,0x00055c77189d6d9a,0x0001b8b7eb40e9fd,0x0007b2ad14152df7,0x000026e00b8e2fe4}}, }, { /* digit=34 [{1,2,3,..,}]*([2^238]*G) */ {{0x000164b77ff9c88f,0x000a2ef7eb4901c8,0x0004be8651e6510a,0x0003146b0427bac9,0x0000014ba0639f38}, {0x000079d912a4b87c,0x00053718addb5b8b,0x0009350d61f10a85,0x0008cd383ef5b3aa,0x0000b3050be022e5}}, {{0x0004372d2fb6aded,0x000801214c59b7ee,0x0009a805676222c1,0x000393e75f878b61,0x0000bc0e9d60d556}, {0x000dcc68fb3aa122,0x0008198ce83ad58a,0x000c586f80dd8a70,0x000608da5fa2a4de,0x00005c1fbffecc79}}, {{0x0000cd3410794975,0x00002f17f97e1c7c,0x000edb80180e62e3,0x000677d857c7cf22,0x00003c5dc338930a}, {0x000919ff266e4f08,0x000d7ce8b10eb218,0x000a415a98781060,0x00067eb9c65da11c,0x00000a82892a18eb}}, {{0x000e99ea38b2555e,0x000c2d0f78b90aed,0x000f899f908f42d0,0x00045b85d2246e6f,0x00006affd17a8110}, {0x0007243c95adc81b,0x0005ff1b55034f43,0x00020858fc587c33,0x0001203202a22342,0x000031c328f6ed23}}, {{0x00094131d1a510a8,0x000fb492e59d9b18,0x000d46eeacaad4c2,0x0001e0f8cfbc62bf,0x00002d9b92bdc756}, {0x00054b85d74c27e5,0x0007ec6f99df2367,0x000ce9d06698647c,0x00058b504025de05,0x00006aaf1cab6c68}}, {{0x000994dd11fe6a9d,0x0008eba83bfa0e00,0x0001b31f14d4500d,0x00041e927422e49b,0x00000c3d5fda89be}, {0x000bfc9eaa562805,0x0000baca1c2c7a32,0x0000a870fecfd05a,0x000e1425337b4e23,0x0000170a512337a8}}, {{0x000ce57b66ce8b33,0x00017e3f3e322882,0x000fd4d1b4d897aa,0x000a30a6df75816f,0x00007c5429d1c726}, {0x00001a389212e06f,0x0008462c37e1fc25,0x000bf5f267708a70,0x000088314bab6b3b,0x00003e8cf2215d7b}}, {{0x0001ca59294b3b6f,0x0008266971b412b0,0x0003fc23a009e882,0x00035452a7149569,0x00005836d205ffc3}, {0x00041dbb019e639c,0x000004f228ef2720,0x000c74f69a1c8850,0x0009110f82baac62,0x00006c6dc96e97f4}}, {{0x000cebdedd438eb2,0x00067491a855ec0d,0x000b83f8e144f459,0x000c0ddacb21f3c6,0x000017a832750eba}, {0x0002281cf11b5e08,0x000c27889bbd621d,0x0000eb5a495a0f12,0x0004fca13a692b6a,0x00009360a8e55b15}}, {{0x000c8e9a166a355e,0x00013d1882ac523b,0x000719f73df1639b,0x000eec37a772fb6a,0x00000b5f4f23d476}, {0x000f7e07224ee886,0x00021d0a2a679ee5,0x00027786b2648c3d,0x00080ad189601c14,0x00005554b996f704}}, {{0x00085c70ed8b7a07,0x00080ff5ac69721f,0x000229dbea53ae19,0x000124751f671465,0x000026c04728ff80}, {0x00077fee956c748e,0x0005e60b02d0294d,0x000be3040a2ee31b,0x000b41001c513f66,0x0000124ec995bdb9}}, {{0x0002a05eef749b88,0x000bb345f0296e45,0x000ca0decb1b42ac,0x000a45c34c8832a2,0x00000ad9447c3da3}, {0x000bd418f40be07d,0x0004656d8d611385,0x000b4a01a333c0e0,0x0005b7da85289120,0x0000d53f63e89842}}, {{0x000b1030f7484975,0x00072638cc84ef88,0x000da3c65c73ce22,0x000f0fcae17f1301,0x00006f3f5a252d97}, {0x000c09e996d5598f,0x000a57310512997d,0x0002aa7f9e694253,0x000b70e1bfdb23ac,0x0000064f9d6804f2}}, {{0x000e6573eacaea0b,0x000e59b058bd265c,0x00018847df779bb5,0x000c3b678c0d39ce,0x0000ca9ee0828efd}, {0x000a29bc7409894f,0x000c8845e22607a3,0x000bdea795bbeea4,0x00059242b80706da,0x00007c709434bcc0}}, {{0x0008ffb240e3f455,0x0008556a6fe6a748,0x0003f5486e2d2ded,0x00044844798dbb44,0x000001050e8f96eb}, {0x0002f32ccee8cca7,0x0005765b412f7202,0x000a163954aedf33,0x0000057cca4d0d83,0x0000e78e9b71d3f0}}, {{0x000ffd0f38bd9188,0x0009b09114aa4975,0x000b8b6035798f34,0x000fb588ff0f5489,0x0000206e2219ddcb}, {0x000fcf8f821d742a,0x000dc1fbd6f34da9,0x000702c041ed9195,0x0009dde18d25563a,0x0000b89d7575171b}}, {{0x00061fbbe6d6db62,0x0006e63bc763d31c,0x000286d321f07966,0x000195bc5e14c35c,0x00001600cfa9dd08}, {0x000c3c815ed8598f,0x0006fed767ed31a9,0x000fa58d2625008e,0x000a2a33e8005f67,0x0000a1b81d42e593}}, {{0x000e39db02b697a5,0x00078d8dcf8a266d,0x000715a9abbdf72f,0x000d03033cd5e0cf,0x00003393e3d87890}, {0x000b10a596c6ff72,0x000ea2c1ffb438b0,0x0000785544e805be,0x0000a95e6d16d794,0x00004806b6418ed2}}, {{0x0003c28b02565d5e,0x0007d5fa9a84ed33,0x00087b17db552969,0x0007d18d709db6b2,0x0000409c35a8857e}, {0x0000777198594e1a,0x00013ba1996d94c2,0x0006d6c719c95731,0x000a209aa81eefbe,0x00006ea2d1d24a2a}}, {{0x0000e3d894cee1e8,0x000477071278725a,0x000e8d65d9c5ec97,0x000993f9c900d4bd,0x00009bf052b7d32a}, {0x000ac8b02844a89b,0x000f631c9d556098,0x000ad2c6940519ec,0x00089816ac904985,0x0000c65a021584cb}}, {{0x00047d3f3cd9f24a,0x0001c7f8a5e5779c,0x000bbab07ed17207,0x0004e1d7fd448a70,0x000021c3bbf36482}, {0x000b4d80d3b11d25,0x0001b97fcb26f826,0x000f528f4f86db6f,0x0003d789800557ff,0x0000663c86f8f635}}, {{0x0009ee695e5a5075,0x000b919d6729edaf,0x000b61dd4a9723a0,0x000611b1586f96c3,0x00008566b6eac708}, {0x00090af73a830815,0x000615254047d580,0x0007aef29bec2d5a,0x00092f6291bc2b1e,0x0000eabbda6cf8ef}}, {{0x0007c0801e864ec4,0x00015d26f447ee51,0x000264c5b394057a,0x000ab54aad486936,0x00001a0403c8e25f}, {0x000f7a8a4659ea6a,0x0002d1bb980af413,0x0003681ec617ee00,0x000b355725932b75,0x000004af07f35eac}}, {{0x00090a00a5ea679e,0x00042580d3b41835,0x000bbd5c4dea2f9c,0x0006aee218b68b26,0x0000c25f328cab12}, {0x00064ebe2ea67e19,0x000017ca33af5ff5,0x000e8443bc7fab12,0x000fcb6ed74b4cb1,0x00005ea985061107}}, {{0x000c21ef95df3779,0x0002c982d5270ba1,0x000ba11436031d1f,0x000a1a8a0967f9df,0x0000ae6a5eba6c26}, {0x00012ea2c092ccc9,0x0004117991571e9b,0x0004fed8c28f898c,0x000f9c7d71f312d0,0x000041fa4fc14344}}, {{0x0008d9030a2bad30,0x00069b5a65848afc,0x000b84311cbe35b8,0x00058c03c5566460,0x00008cb2a3f860b6}, {0x000df7536be38e1b,0x0006d87e7fa21eb3,0x00001ad6290d1f0c,0x000eb810bf6f5cf1,0x00003208e36ab1d3}}, {{0x000df5d231c91e4c,0x0001b04babfe5cd7,0x000ef58bbdc77085,0x0002bc2357ac532e,0x0000b5c3bbcfa9b1}, {0x0004ae41da37806e,0x000d71c7d7131ce2,0x00003eb2a144c5bc,0x000449e6a7caabfb,0x00005ca49bed40b1}}, {{0x0003b89bd18f3d12,0x00016f2316cbf28d,0x000482896f8e6c7c,0x000e778e62adc34d,0x00008bddfc697813}, {0x00008eed3e3e9d68,0x0002fe9f8a3d153c,0x000d994921af5ead,0x000a79c09952b705,0x000069094582de86}}, {{0x000602c441b88cd0,0x000bcc20f7e71964,0x000ececa70c2a3c9,0x000f16fa225449ec,0x00008d5f586ad324}, {0x0001d115f0909ea3,0x000fc97c961679ce,0x0004d1588ead7203,0x000773fdc146623e,0x000053a8ea43b1f0}}, {{0x0009c4809a0bba36,0x00009d9a25c286c4,0x000d5a52060f0403,0x000cff7d9efe137c,0x00009b20f1c2576f}, {0x00078ce06fa3e86d,0x000c77f529c06f14,0x000c1aad527c7769,0x000a54cada78329b,0x0000cfdc46bf1bdc}}, {{0x00010cd2058985aa,0x000552e40f6a34b4,0x0003e1a2087169d6,0x000feeaa1773f3ab,0x0000a8f013b7117a}, {0x00075210df843d49,0x00035b92e42bd467,0x0006eaf3ecce3434,0x00067ed3af118378,0x000053710064d275}}, {{0x000b1bba80892cbc,0x000c43c116286ff5,0x0000a537bd1a5cb1,0x0004dd41b6297424,0x0000c9e812b1f69e}, {0x000fb4b5fc8601f1,0x00025def2d88f167,0x000097bead9b6112,0x000f8c0dec297878,0x0000a5bfd4cccee3}}, {{0x000058b90fa84dff,0x000b95e24fa1bb46,0x000c99c141fa4b7f,0x00021f36fc4b15c5,0x000072ede8886dd4}, {0x000db218df104f8a,0x000d8929fa061e56,0x00031369dba8acfc,0x000139ca445c97ab,0x0000aa7da404f985}}, {{0x000459fd466786f7,0x0000835940e6a840,0x000323c0080d2d9b,0x00021bceb6682b6e,0x00000ea0e0da968b}, {0x000b8e9e1c90e07a,0x00000efe4121cbbe,0x0000849c5d166c93,0x00035bdf729b9cad,0x000020e1465218fc}}, {{0x00062a0d6f379255,0x000b70dda2ca99e5,0x000ecaa30b5d30e5,0x000a688e3a88f1fc,0x00004f71443553af}, {0x000916b0bbc4b3da,0x000778f700e9314c,0x0008470ccc4bf1a1,0x0005e5a395ebe872,0x0000286cde27e46b}}, {{0x000f5cdfe6b7d846,0x00082cb76457a1e3,0x000f3b9f74697b1a,0x0004560f07699d92,0x000028a5e6885a15}, {0x000742ef4c2f1f4d,0x000e56fb6d72c4ed,0x0008faf1ba1dca49,0x000ca351c97d7358,0x000087771442b909}}, {{0x000d00ef6e81de3d,0x0006e2eef62dd862,0x00034f24d63d21af,0x000c7950c94d5766,0x0000a5a468b10066}, {0x0006314bb09920b7,0x00046433ceeafbe0,0x000590fbbe003195,0x000e38446743c58a,0x000060b8843b0644}}, {{0x000c8a2f33ef7892,0x000014bcb8cc69d1,0x0002dc33430b7a34,0x00007b190c3a3959,0x00003317543deedf}, {0x0009efc31735b604,0x000fda1ad6889634,0x00021830c3784c8e,0x0007f7a98ea1604d,0x0000198b9ed3ee3d}}, {{0x000802942dc95293,0x0006c607840b614b,0x0007638241011618,0x0001a891626667c7,0x000070fae3ebdba7}, {0x000e767cf31f42c5,0x00037886da27ff5b,0x00092f5eedb3bfca,0x00092071df531c71,0x0000a96add241b4d}}, {{0x0003414c0c83975e,0x000af2aeddc23ead,0x0004d9fda7d76f8e,0x000ff1110efd9e98,0x0000f15023276067}, {0x000a0520d36f0d27,0x00065322372861ad,0x00021d9344f19d56,0x000a4fab8999bd58,0x00002a7b9e9d02fa}}, {{0x000e6f66be15bbbf,0x000516ab8735bf29,0x0004d4bebda1a8ad,0x000fa68f061186d8,0x000009f9261ec025}, {0x000668b5b3fc0a45,0x0004af0a2c0ff9a9,0x000282c2bc1a8bb3,0x000ddb6c3b1e0b34,0x0000492f782c6d6c}}, {{0x00069b4c267cd575,0x000f0f8ff694e887,0x0005b7442ef62630,0x000ae31d653545b0,0x0000bc15dfb1c514}, {0x00074dc7419111ed,0x0005eb2728c3a9f2,0x00099a7d7ad03866,0x000fa05d8bfc5cfb,0x0000c82b07903c82}}, {{0x0003de54e014c472,0x000560e61eab8f72,0x000f8cf303460a19,0x000c58bf40488c19,0x00002ba1ddf14e5f}, {0x000aed63d9564f0b,0x00077c5ee525ae10,0x0005271ab84a9fdf,0x000b311db9987806,0x0000c50919caad39}}, {{0x0006e874c69e8a6d,0x00032ff1ff6a3eff,0x000e47e1fe98ab13,0x0008fe8b0aab1917,0x0000a9ac0b6b9835}, {0x0004bc04f8bcb879,0x00083e021fbaa981,0x00053100e36bad61,0x00027f3c2bad3e08,0x0000a510218c5f1c}}, {{0x00079c291c3fac17,0x000e406762ecb91a,0x00013af2e1a7b0db,0x000eba4e6ce29057,0x000053a167cb4639}, {0x000c07bdeddcb8a5,0x00067183cdd67c61,0x000128f146849aa2,0x00077df6fb0823f4,0x00000acf75062e13}}, {{0x0003ab8aa1b413a0,0x000ad9f830d7fd57,0x000b78539eb24027,0x000bf1c67bd704a6,0x0000c3195072ee6a}, {0x000bf133f8b12d87,0x000380475ed535cc,0x000990604c95a5f7,0x000535334f567cae,0x00000582b15227a5}}, {{0x000037febb43ed1f,0x0005fbda9e9827e0,0x000aa2514e69769a,0x000cd35866ce6da9,0x000060ec889f5458}, {0x000a6da95e75646d,0x0006670efd9bf0bf,0x00024a9dc8b0395e,0x000ea954fc07a1ed,0x0000f86eef9860f5}}, {{0x00072012ca58fbc7,0x000d4c78a8cd5b1b,0x00068b7af601e664,0x000a63128123fc55,0x00000084c070ef02}, {0x0005a8e658751508,0x000195ae0550346b,0x000d111eeefc4be2,0x000fce20fe4c6f46,0x00003a287fc76838}}, {{0x000be4e9312c54eb,0x000f0cda2786e630,0x000d6ceae55abd5a,0x00091e346e84f200,0x000022eede6ca985}, {0x000356024525d0aa,0x00045586290c118a,0x0005c6e264b2b3b4,0x0005742743dac9f5,0x00009827e4a6a765}}, {{0x0002a6dd9cfb4cd8,0x000f94e215cb934e,0x0007b3210b4858a1,0x000417a6b0a4b56f,0x0000befcc636ca75}, {0x00004b44b52cd3b7,0x000e7d15df655d8e,0x000f5c7d81066051,0x0008319bf3c2bb26,0x00001fd03c43aee3}}, {{0x000a7603cb34c2dc,0x0003d057be5ae4c3,0x0002a595a6d0f925,0x000e18e4a3e6cf15,0x0000bdb8d991f000}, {0x0009ebe420d29fb1,0x000a2deac279fefc,0x000be608d12593b8,0x000c2f8c1e1867f9,0x0000eb5a9f81fbda}}, {{0x000421680a0ed616,0x00052f2f3c60e7e7,0x000419cfa67feadd,0x00070817ed6225a4,0x0000fc0a15bd1cf9}, {0x00005b2338e5c066,0x0003160bddbc9130,0x000287049b60afe7,0x000489555a8336e4,0x0000959d1b6599b6}}, {{0x000420ce0721159a,0x000f3b431364134f,0x000a77054c77e7e2,0x000491139bf22e1c,0x0000068bc7711297}, {0x000e3f9245e5d473,0x00083b6ccdc556ac,0x000a7a2b057ab72b,0x000b7e04442765dd,0x00008a61f6aeb745}}, {{0x000e96dd576a73a9,0x00026d0897ab34e8,0x000fe2f8ff6c7c7e,0x000a5a99c1721c5b,0x0000d26a77a616ad}, {0x000b65c58aa4fc27,0x0003d809efc1048e,0x0006fac2acd58b42,0x0006717ad71cac4a,0x0000645d4fc1ffd4}}, {{0x000d73a164aaf5d6,0x00013d6daf2c817e,0x00075d36a7d62437,0x000d90df8c94fad6,0x000026a8207e0f81}, {0x000826b934843b84,0x0008b84eeafc1dd4,0x000dd85215de1db7,0x000128812417e355,0x0000ae2d30deaad5}}, {{0x00051dada3211cde,0x000c64018309c929,0x00044e2d5c6376e3,0x000d9d80ccba2315,0x000025f7a4a621f6}, {0x00027257fd00e719,0x000b2f36f2fefad5,0x00022f938ceefce9,0x000665f7ca6333cd,0x000077ef898fcf04}}, {{0x00081bfe708b52ee,0x000c42359c865bd7,0x000be20854eefe76,0x000e15fd0ae7807d,0x0000c6305412aa5d}, {0x0007eb6ec1300871,0x0009cb3a7019cfc1,0x0003b73c3064cd8f,0x0008e6c1c89da37f,0x0000329e0ea397cd}}, {{0x0001b5e44c3250c6,0x00006ceb294648c0,0x000b962637706782,0x000130c3b3acfe89,0x0000a6dce5b66ebc}, {0x000aa6186ce36869,0x000b1852bf94c5bd,0x0004c261dc5ebfe3,0x000f138a1bef6195,0x0000a279dbb67a1b}}, {{0x000879d90e03a540,0x00098a4ef9ff4a24,0x000a26c0ce8f5edb,0x0003796474413661,0x00004350b4104b6d}, {0x000757164564536b,0x00057d4f4adebe01,0x00050b82d298dc7a,0x0005b791e2842835,0x0000a781123e3c5c}}, {{0x00007c48619e84ab,0x00097a8e0f19b2f3,0x000b3c9db52cf19a,0x0007e35d5659ce7d,0x00003886ff23b704}, {0x0001aaf58811dc26,0x0002bfed52b1bbd1,0x0007104ca16ad476,0x000b79c4f1138a88,0x00007658715f7d62}}, {{0x000f110ecabcba82,0x0004da27d56ef2b7,0x000dc00cb29c9167,0x000ea38be30c384b,0x0000551fbe178550}, {0x0009ceb4b6cda9b1,0x0001c0f8dbf0f1e2,0x000ff617a844614b,0x000b9bb65d23f3e8,0x0000463bcf08ebf8}}, {{0x00046fb3c9c2f2f6,0x000d8bc887881058,0x000acf39df0c62e8,0x0005e06d804143a8,0x000012fea1c85697}, {0x000fe3dccde965f2,0x0008b508c90850a3,0x000e602055cb2212,0x00026281f1187920,0x0000af846cb5a96b}}, {{0x00094218aed1a517,0x0007bcb7d8e4e5ea,0x00070f71ce083200,0x000c497f01ba571e,0x0000e6ebb21847cb}, {0x000aed8c6da82ba6,0x000ab2db4b4da475,0x000a869cd33a684d,0x00064cc689a3ac37,0x0000ae1ee3463a89}}, {{0x0005bb9f1e1c66ff,0x000777e629c50f4c,0x0009fd3d89dfbcb2,0x000022138efb8fcd,0x00005816bef7a97b}, {0x000fefc894aa6e34,0x000e9903a64777f7,0x0001f799abf92380,0x0007f487d3d67ad7,0x0000656fe81b0c1f}}, }, { /* digit=35 [{1,2,3,..,}]*([2^245]*G) */ {{0x0009dc05b0daeb6a,0x0007ab1c9719331b,0x0003d0d262ae4dc8,0x000f3de5109dd56d,0x0000ad73296a5d14}, {0x0009fb2ac31d9136,0x000163a6acd79e56,0x0003de3fe8aed60f,0x00087300abd5213d,0x000039462f009289}}, {{0x00020a59b6efa79b,0x00089cfab3fb90fb,0x0002133c42d820c4,0x000a360c8d738663,0x0000971de4ead8f2}, {0x0001f841e142f900,0x0003ccd560f2a34c,0x000e1379d650f3b7,0x000d1d007fad6aa7,0x0000b1bf229b9aa2}}, {{0x000bb724b855a969,0x000c193ee3fa5bdf,0x00081b7e4fbe8611,0x00094f40258b7810,0x000069302e6ce1af}, {0x000a01254526c745,0x0004141d611305a4,0x000ed085a7fc0c93,0x0009be3d57407cde,0x000071742a3a7834}}, {{0x000014a8c1f3bf07,0x00073102160f5085,0x0000c42214175c4e,0x000f472abaa79acf,0x0000dfe26a0804cd}, {0x0005aae6f42d4acd,0x0001a1106a667256,0x0009bd963bc85414,0x0008a723b2b776b4,0x00002e675791ac54}}, {{0x00067e282d8e77ae,0x0000ec55fe6a99c2,0x0003bf9a2c0250ad,0x0007bfa7c31cc937,0x00001ae266831856}, {0x000738a847ecbcce,0x00022dac7b970a0a,0x00088ad41f4b09ba,0x0004ba5b4ead8383,0x0000ba6d2a78d509}}, {{0x000e67853c1c0424,0x000ba067d80a0c28,0x000861c400f926de,0x00063b09e1a3bce2,0x0000fc011f0af635}, {0x0003dedbb918e260,0x0000921523ea0b52,0x0007bc667773bf8b,0x00086b039e89a24f,0x00007701e4145ce2}}, {{0x000d665659750b64,0x000d981e7b419f25,0x000fc4ca88f75ecd,0x0002d199aed274fd,0x0000d837ba7e0764}, {0x000405c0720a84bb,0x000ef4af02130827,0x00080e040098122a,0x0007d9f41d3bcfc6,0x000033b4e1e14860}}, {{0x0007596d7efa47e7,0x000f87ae55f9ba41,0x00018c27027f5c32,0x00038f7626dadc8e,0x000092ffbbe90edc}, {0x0009f3f053fc1017,0x00081a3a20f73dc5,0x0006fe6d0df44113,0x0007b5d805ac5f21,0x0000201193396b7b}}, {{0x00031a2aa5514055,0x000aa37a81ddbd9a,0x000cad5460bb8634,0x000043fa6ecf5041,0x00007ba1f9908b03}, {0x000b451a99c6a86b,0x00003d70f946e8da,0x0006874cbe002fcc,0x00047b59ffb89cc6,0x000098339a4a6b4d}}, {{0x0006655d65ec88df,0x000d6e79f896eff1,0x000d38236946c197,0x000510068781a8c4,0x0000cbe735a054e3}, {0x00062486280cc181,0x000cd52f7a4924a4,0x0009772668ab80e3,0x0006ec2371a3f51b,0x000083cd4419a909}}, {{0x00061f179879b951,0x000df0c07e6ff0f8,0x0006434d1b7fed81,0x000899e3c92db27d,0x00005fb78635f682}, {0x00007019f0959708,0x000123fd44581616,0x000f3cd7af2e4c82,0x000d794d693d2a88,0x0000a039a63f0492}}, {{0x000a5a141c4747c7,0x000c91edbabb6659,0x0008cd292c269efb,0x00017244e70fd00c,0x00005746625ed20b}, {0x0001a886d579ca7d,0x000ce93524c3eb4b,0x000e55b6cbbeb85f,0x000ac397f9b15372,0x00008d4f84e13615}}, {{0x00014bfea7be6361,0x0000f328d17ed214,0x000ea80165d13b52,0x00041cc1aad9829f,0x0000c636f9bdefd5}, {0x0000ae640d4367fe,0x000cfcc82e5d8210,0x000bf012b1a13811,0x000a40021a0ebf68,0x0000ad45395140c8}}, {{0x000093d07e16c03e,0x0008c6451c1a84f0,0x000852fb8e51a85e,0x00027647baccab5c,0x00000422dfc5ea59}, {0x000ae8d127196bf4,0x000b0cd1f307d1d4,0x000f0c06f05e1809,0x000207246e68d69a,0x0000bcbd7a6ea8b4}}, {{0x0005696102fe7961,0x000128787cbabc0b,0x00047e5568e8a8ab,0x0009702b888f7629,0x00007005dc539317}, {0x000060a74a16a3d8,0x00059d11f5a2d057,0x000d3eee179fdf94,0x000b1336970f75a5,0x0000b65be596af2e}}, {{0x0009a12055784ff3,0x0007e7ad17886a59,0x00083e1be483ccc5,0x0009c2326844874a,0x000091668f7d203c}, {0x000ccc39b9c01312,0x00079a1a3a021ae3,0x0005da5e7959cb5b,0x000b1b1efee9f28a,0x0000e21b1fe45033}}, {{0x000b7effce6692d1,0x000d13f99991b95a,0x000da1b42890b0d4,0x000cec15a2ba2f18,0x000018e795c7c8cd}, {0x0000ea0ad07b7906,0x00006d2815a727cf,0x000f20348a8fa2cd,0x0000bbc96ae70635,0x000009c2b7d97f76}}, {{0x00046418aa05aea8,0x00032c224067ea96,0x000401680c850519,0x0007cca8ecdb3161,0x0000a6a937b896d5}, {0x00066b96e440f85f,0x00058873f7cca1fb,0x0001e2cd22d99b85,0x0005da4df8221d94,0x0000a05eba0d7a8a}}, {{0x000ccce912fa29fb,0x0009036040b56b4f,0x000aaa682139e237,0x00037b99fe6891cc,0x00002cac906e3f6b}, {0x000c39a68efd2423,0x000f8bc753e95cc7,0x0000629055d8668e,0x00004e48e5d349cb,0x000092775e6d287e}}, {{0x0007764026e7e174,0x000920bd6ff6034a,0x0009b2c9a18833c8,0x000cb370c9651f3d,0x00007e2a44c0c972}, {0x00096a65b39a0b5d,0x0001d09cbc9e0807,0x000b2736f0b90d16,0x000112ddcf44a1bc,0x000042acfae127da}}, {{0x000a76b6b44ab8e2,0x0009970211cceab3,0x0007bcb9b4bb22b4,0x0002bea529e44146,0x0000e0960bc476de}, {0x0009eb77378cd806,0x000d80e280c90b95,0x00014d594586a4dd,0x000310e90d20f04b,0x0000702dbd838d2b}}, {{0x0003a01c57e6e9d5,0x00050dcc40c8c9ea,0x00090cba6fe563eb,0x000cdf395633b94e,0x0000c9d1045e8592}, {0x000d2588f46a6120,0x000b035c6210c59d,0x000e8248377f9aa0,0x0001aa4bc93a5152,0x00009dc56ac7a30e}}, {{0x0000c564a8ac4c7c,0x0000d81af1627a56,0x00070a724e6dfb29,0x0006e7fb2bded10e,0x00002349505c61bf}, {0x000695464c03716f,0x0003bbcbebaa5c11,0x0008aabafd07239a,0x000af38c2eeda57e,0x00005d614c1d1436}}, {{0x000e2d0f37b76522,0x00070e55eb8f1e79,0x00012eab7fa064b1,0x000522fe70f9abc2,0x000086b2a1081854}, {0x000fa02edae5aa1f,0x0006c5bece8a7b0e,0x000db187a76faee6,0x0006c55f3bafbf59,0x00006262ab51cd1b}}, {{0x000bbe31e35d4f00,0x0003907a6029f9fd,0x0001b672f257cd8f,0x000429f29248e19a,0x000039e13d803d69}, {0x000c3c7908e58df4,0x000b0c985ea865df,0x00061454801424f8,0x000683ceefa02118,0x0000ab80f32400a3}}, {{0x000ccbfa3d84058f,0x0005df204d3c0698,0x0009081ed4ca5c5b,0x000e64a883950e9e,0x00003c31bda6008e}, {0x000eba6a97909010,0x000507b1fb8d71ea,0x000c9169209e9956,0x00037554f52879e7,0x0000877f94c1ed32}}, {{0x00041833560eed57,0x000a8ec17822793f,0x000852b85ba8088a,0x000eb3fbd9a1b805,0x0000c928511df25b}, {0x00049c211a3b0cf4,0x000018434a1def45,0x000091951e39b0e8,0x000d49dac937eddd,0x0000e6ee324776c1}}, {{0x00037b1d92a17bf5,0x00096a699f0dc99a,0x000418df6afc0eee,0x000e8cc36e947922,0x00009cd84baf92d6}, {0x000fb2308f6ca879,0x0004189720d764a4,0x000e233b6e8157a4,0x00069ab8b5bb2ca4,0x000095141e790e65}}, {{0x0009a7ad4edfeab9,0x00058ba474c78c2d,0x000efd6802660b1d,0x0005206e51d4a61f,0x0000d0fffb51a30d}, {0x000df5af5e13c41d,0x0007aa82333d762c,0x000e12bdbf9f9cad,0x00053d28e2c067f3,0x0000c214dd58c9c4}}, {{0x00078f73d96f6c3f,0x0009940a0114e12a,0x0001b5edb91b616f,0x0007802baa7c46a6,0x0000bbaf38454705}, {0x0007732bce06e6f0,0x0003fc6ea51ec6d4,0x0005ac7dbbd02767,0x000aa24c78933088,0x000003fd48baf268}}, {{0x000f8cb8b6b4ac7c,0x00022da8657e62e9,0x0003e709fac0ceda,0x00044cb8924265f7,0x0000c2125359b00d}, {0x000a800aa4354d4a,0x000d4c76651dc137,0x0007663922833c83,0x000b7a7093741920,0x00005c10ea46162b}}, {{0x000b2b4671f489d4,0x00020e7e4b59a1a6,0x0004a86d078a8249,0x000b641af729005d,0x0000ea40b308107c}, {0x000def837872ffaa,0x0007857e65950d35,0x000ed651235c3f22,0x00011d318b69bc2b,0x00007d4a4d9d4cd9}}, {{0x000fd6bd4e1c6acf,0x000b32bebbbb5828,0x0006ac0ea31f3e32,0x00040df9c1459119,0x0000c2fd4bfc2e76}, {0x000758062d718466,0x00050f36b4cdcb16,0x000ce037ecddce26,0x000d9b542106c49a,0x00001395c0f493cf}}, {{0x000af914a54fc7e6,0x0006b42c62b10386,0x000d7e90af5bd329,0x000fcca6ab95b008,0x000058cf981705ac}, {0x0006ad0ad9ea67f5,0x0002735b7f791274,0x000a4060040b2faa,0x00095a83921bae30,0x0000ffd2c5e32b21}}, {{0x000674b3b3f874f0,0x0007d4409b672a9d,0x0000672a80e68f8e,0x000a89bb24a6bbac,0x0000764bbd0e6bff}, {0x0009c13926cecbb4,0x000855e317e76a63,0x0007ef017f7e5c24,0x0004e80cc86df969,0x00002f0f42dbf4c7}}, {{0x000b383892850d4c,0x000fac8523726a45,0x000089ef29685093,0x0008bea48bf7c4ea,0x00008aeda7a9e560}, {0x000a3efd995bd374,0x00059297e7208f9d,0x00083d14216bcb93,0x00036a46e7fc0aee,0x000007b7c7bbdeb6}}, {{0x000994e8c70b66c1,0x000130bc81bb46d0,0x000e193a3bdca94e,0x000df90e3c0eaa9d,0x00006ef1f3cb51b1}, {0x000e07f5cad99fe6,0x0007bf8cf7c18d04,0x0006f9681ba9db21,0x0002692711c2a3e4,0x00007a115d42378b}}, {{0x0003015fb3d08b6f,0x000c4f6c706ce14e,0x0002810d3977d0d0,0x000113a60a8549f6,0x00007a49710c6b40}, {0x0006aaa6c9b79e08,0x00001c5d3a5208aa,0x000f719168540d4a,0x0004423dbcbdb8ca,0x00008b82b284445f}}, {{0x000621189521a131,0x00084775b0e3f2a7,0x000ce99086411768,0x000ba2af92188e83,0x00005862571e2559}, {0x0006c25a01159e10,0x000092ee012a048e,0x000ac9e25f213af8,0x000a7eb2d7503aca,0x000090ced06d85df}}, {{0x0007e9d9f2f897e2,0x000607493cf5a89c,0x0006d18655a12aad,0x000b1e1b64925a04,0x00004203d3d79adb}, {0x000e22319c02fe70,0x00061fa0ca3076f5,0x000fc06ebb171574,0x0003534d5b2e1b98,0x0000ffaca4b07d6c}}, {{0x000e95aa6360241f,0x00033dbc40dbd017,0x000e41655d78a47f,0x0003ae0c5478f797,0x00000bc57e149c3b}, {0x000dae7e92fcb87d,0x0003e73d7446c12a,0x00038f6c156141b3,0x000d7b8287f1b57a,0x00002551bb07d0a3}}, {{0x000fd03ba124dcca,0x0005595509e778f5,0x0003963210ede681,0x000218ecbd904ba4,0x000057275ec31263}, {0x00098cc31aed8686,0x0002beb9be3d4ea4,0x00082eebaa59cd5c,0x000fd1991ab4d3f2,0x00005b2b384a3ded}}, {{0x000f10557f7f4aa8,0x0003141d09cb5332,0x000b95beb2cef476,0x0004c82395b067df,0x00006a03a2c01446}, {0x0007dfef0be79d46,0x0001874b97275902,0x000f1f7d4d0de182,0x00099478e33b191e,0x000006558b7e81b4}}, {{0x0002253a17cfb28b,0x0008ebf590ba262d,0x0002d72dd21664a7,0x000c4587d06f2f4c,0x000078a8de65b6b7}, {0x0006920bc17757f4,0x000cced7a68a4b12,0x0009387c7e16b5bc,0x000b542e5005a393,0x000035a62cdf92da}}, {{0x000c560972894920,0x0000c17d3c2a87c6,0x000f1f08a4bdb0dc,0x000b2096faa4d313,0x0000f5c7607dec01}, {0x000241e51762f134,0x000fb8b10c63b6bf,0x0006515f30290df0,0x000b35eeaa2454cf,0x0000f60852859665}}, {{0x000ffb9fdfce9b8b,0x000d43b966a89729,0x000dfbd7523680f5,0x0004c7b2c6ef98d2,0x0000bddbb8a5b1c7}, {0x0009eb62b7763240,0x00018e7f61e7f249,0x000509a885746186,0x000dad9a93d36959,0x000078c35a5126bc}}, {{0x0006dffe227d9c28,0x000f28fcd749c021,0x00055e1af43fc164,0x000360f372e79f59,0x00000013b15b60ce}, {0x000642c77d088ab9,0x000603408ad40c33,0x000e18e96bf7079b,0x00099f840d636eca,0x0000098c58ab14b4}}, {{0x00077dceae2302a1,0x0003c806e6c54271,0x000040bb8f335915,0x00091da3eadeb94d,0x00009926a3190114}, {0x0000b030aa56fd94,0x0000717246b8a0c9,0x00086222ff4d2833,0x000a76bce47d40bd,0x000009d403daad8c}}, {{0x00049006bdc08788,0x0002a29d68a05f2d,0x00010f595a285de4,0x000fb4d722cd48f7,0x0000b96085211d89}, {0x000ed5908b41453b,0x0009af492a0d2a10,0x00067065f4429afa,0x0000d313f5f74aa4,0x00002f8641f9b3a4}}, {{0x0006ef58b386c69e,0x0001a846d58225da,0x0007c90a64e5c80e,0x000f8c90401eaf20,0x0000f4a430a9b672}, {0x00083d647db36e0e,0x000066dcdadc8cb2,0x00012d7df32946b6,0x00087fb7f7b1c8b7,0x00003c85bb7e9e41}}, {{0x000f20bba2439114,0x0008ff1b65fc2e61,0x000bd0e126bb920d,0x000d9abec02fc3dd,0x000015d3897b9394}, {0x0009c1cab00a9be5,0x000d661f585cd907,0x000eaf788c0705c8,0x0001aea79d859521,0x0000252c9d8f4143}}, {{0x000b2d546f92c5d7,0x0003d47db7b536a2,0x0009dff2df753503,0x000b555388239913,0x00004372074066a3}, {0x0008723137e3f7e9,0x0001485151c6d57c,0x0000aa2a55b532c8,0x000edd04c3cc6736,0x000002f7dcf55657}}, {{0x0006d3ff179e220d,0x00068eb3de8acd58,0x000fd1863a8fa7c9,0x000f449cd5617fb7,0x00003a190b0c03e8}, {0x0003da277108421a,0x00071f8b6dc858d4,0x000e4ee68a60e733,0x0007f658c12f0abb,0x000025d073738153}}, {{0x0003d6dc16b4e186,0x000656aa6bd02ef6,0x00089e652e089004,0x000d744acb852631,0x000092e329517ff8}, {0x000d8b234333e0b7,0x0001098802c15416,0x000dadb64e1c1b30,0x000c8f225decbe5f,0x0000d948a7a85c34}}, {{0x000c6469dc81a049,0x00001a4e55e5d35c,0x000fef56b28459f3,0x00059cd0155f5c27,0x00001ebe8d5d8309}, {0x00085c4a7131df9f,0x00088fdec6667457,0x000715d18057e535,0x000cd2d684d8573c,0x0000a9ca6c7cd549}}, {{0x000e2e3446f9e281,0x000846c258bb86ce,0x000f37d5b739bc37,0x000c9b9746166b21,0x00008414a89a8b8e}, {0x000bb1b9f25ff8ad,0x0002a4dd50af0d98,0x0005b5a78084af6f,0x000ddb4667c708f9,0x0000c1e90d79e098}}, {{0x0000f830f7f7a925,0x000962af6600ea3e,0x00042c1e3595c08f,0x000cafae22538bd4,0x0000b3101d3fcabd}, {0x00078afde4e64419,0x00007b0a9e895fab,0x000894659c483333,0x0005c40891f85893,0x000036cd9f687b51}}, {{0x0000fdb1e5a3d569,0x0009b0374bf3035e,0x000a9b06d21be1c3,0x000609411de8deaa,0x00005478125def93}, {0x000338bc9cf8d1b1,0x0008608556303bd3,0x0001d00508c2e2ca,0x000a2a6d1106d92f,0x00001e1311fff629}}, {{0x00008c0c7abe48cc,0x000a32325b3f3714,0x000cdd15b7dbb702,0x0009f3c37123b082,0x0000f285904b770f}, {0x00005a5f3b665bd4,0x0000eb9cff9258ce,0x000ae583f954f24f,0x000e2d7d0276a007,0x00008112308cea23}}, {{0x0006ebf442107be7,0x0007b1a909f1ccdf,0x000684e1ca8ff7cb,0x0003f085d46ef075,0x00007121a630d6bf}, {0x0005761fbdeb7490,0x000711a947654819,0x000865547aecae1a,0x0007358f2f2b4382,0x0000d528600f8f9b}}, {{0x0006e9b28d21be4d,0x000d16dba462a3c9,0x00054aae39c8bb2c,0x000b130de6632450,0x0000287f45d91f55}, {0x000e421a7d459f3d,0x0002a3b3137c7299,0x00044882490d7904,0x000bfb28faff33f9,0x0000bfb8dc9f56ed}}, {{0x0006eaf73f22dd85,0x00040159d50c4c19,0x00084c5827c96b79,0x000f295616bb5386,0x00009e99fb634b73}, {0x000fa8d3a114007f,0x000921cf2fb36503,0x0007d77d78896f76,0x000aa84fde09fec7,0x00003da7be4c60d5}}, {{0x0002bfa99958d23f,0x000c81847d0a62cc,0x000dfe7c5fb5c76d,0x0005c6e11e7e50b2,0x000088e3280b0e5e}, {0x000682d38e3cd1aa,0x0008a2d2a17ecd17,0x000fbf0977af10a9,0x00050e0a422c42e4,0x0000a1dd9f7d6448}}, {{0x000e96433c0805a5,0x000d7869abf94e41,0x000dc5ed1e35cc84,0x000f55a120bac5dc,0x0000d5f11d73cf91}, {0x000b444c48e7a259,0x000d3d34f5e7ffb3,0x000617df908d9b25,0x00074f19c9a1d296,0x0000b424cec270cf}}, }, { /* digit=36 [{1,2,3,..,}]*([2^252]*G) */ {{0x0004e9d192cabe16,0x000136ac20d6f4c3,0x000b9a9a95ed7b38,0x00037f743f5452cd,0x00003e7e859d699c}, {0x000288719e08654e,0x00055a84a99d8b7c,0x000b5e1d47df6f11,0x000affb8f70d6ecf,0x00000f85856658fd}}, {{0x000989794fdccb99,0x000664d2a5d09eb7,0x000f3dbd4a6c29d7,0x00006c08e7b46244,0x0000d3275732baf1}, {0x00078611cb5eac27,0x0009d9c76502f96b,0x0008f3ffdf832947,0x0006d50496b021f2,0x0000f3bea3e2eab2}}, {{0x000d467bef953373,0x000f071bddfa0d77,0x000be423588d7262,0x00060e99185a1f4d,0x0000bc436399b964}, {0x0008c2ad1207560e,0x0002054fdbb7908a,0x00099c759edae8a1,0x000c0e4e054bfa36,0x00002db152ab5cf2}}, {{0x0006019816bb79c3,0x00025d9ee9893bd2,0x0005c447c9f4d46a,0x0009c26760f22454,0x00003b25455b00de}, {0x0000cad04873a72e,0x00074e432c4decdc,0x0006750b41e24738,0x0009f681a6c25f63,0x00003d05248bbaa4}}, {{0x000481d262409089,0x00085ea18d0661c9,0x000e20eb4c37806a,0x0009090d6babcb16,0x00008acecc7050ae}, {0x0006575fb2de613b,0x000121a2f094246e,0x000405eec4b33ebe,0x000e1064f6eb1a6a,0x0000d337e63aa2db}}, {{0x0001242ccb9661a4,0x000e4b4b735a681a,0x000038cb78b1e57f,0x00048653161304f1,0x0000e5b9a8a398a9}, {0x0006e7de5b2bfae6,0x0000b846b3a7915a,0x000464483729cd42,0x000aefe28c607ed3,0x00003f2fb772d468}}, {{0x000198fd906ce680,0x000617f59c8fd445,0x000002f38f184755,0x000e15c2f310b252,0x0000a4410ce1ced3}, {0x000ed8c1a5559846,0x000e72884eb22a13,0x00019d74e6e7911f,0x000e37cee1a905d1,0x00006f730d7170da}}, {{0x0002fb6223e426f1,0x00089ec0aa53e22b,0x00041c88f08382bc,0x000f3ce723df210f,0x0000eab10c6e3af5}, {0x000e9ee919f420f9,0x0007feb7d658384a,0x000d6cb287d7bf16,0x000e7944e141cd92,0x000072357ff59e5d}}, {{0x000c56b5bf5b4709,0x000351a00ac5adc6,0x0000eea7fa5bc587,0x000fa53e96a1bcfc,0x000037fcff36ffa5}, {0x0009f297dcabee43,0x000a97014f90ac36,0x000a4fb4897cf19a,0x00023c3e53d9a7ae,0x000088e0a1c87728}}, {{0x00085910c59fc2ff,0x000edd337895b65f,0x000511aab9da9784,0x0003096a69799310,0x0000e52ae4181572}, {0x000749531e18c1e3,0x0008b80751a2bb45,0x00001252b398f247,0x00055b499d5957ef,0x00003146d57f9c23}}, {{0x00016eba4eecc3be,0x000ce1567b234d2f,0x000efba21f561158,0x000a7d55857190e0,0x0000320ec77503ce}, {0x0002c5e31d91219f,0x0008a202612ab98d,0x00046d14dd97213e,0x000914064ebf5b24,0x0000252742c3551c}}, {{0x000892bae35f8fff,0x0007393a7330c288,0x000e452adeb6025c,0x000fa6fdb0931841,0x00000230ffaf8bad}, {0x0009c569666cb64c,0x00028c9c1a11d83c,0x0006d175be8ee2b7,0x000fc1d4d08c60fb,0x0000e59f68cfb17a}}, {{0x0004746057984cd0,0x0000120adf81173d,0x000dccffa456524a,0x0003ddbb34c2a11e,0x000094498314e67d}, {0x000864a8165bdf84,0x0001548f9fd22672,0x0002502dc589998c,0x0002ff4896359671,0x000033a8860e87ea}}, {{0x0004df6843c364e9,0x000b16a5ee86621f,0x000f9457ae1f592d,0x000240793da6c122,0x00002d742b08fcfb}, {0x0008c3f73811884b,0x0007e71f910c2c7a,0x000405a5a15bfcfb,0x000f363a542968cd,0x0000a72904aaf04d}}, {{0x000ffef7441e12e9,0x00042919f0edc246,0x000792a5bbf274ab,0x000883a1dbf3b485,0x00006fed0fa498e2}, {0x000247ca159aa0db,0x000cb4ac34f0f016,0x0007adee02259b6f,0x000ab0e110a89e6a,0x0000df1a3bccde15}}, {{0x0009939fe95894f3,0x0006d80da64f7f5b,0x0005668fb3c50e7c,0x000b18adf2c440f9,0x00002885888ec566}, {0x00067d3ea0cc76aa,0x000b0b26bc3ba506,0x0004568d5f276915,0x0001f136016d96ad,0x0000a9984da49550}}, {{0x000d0ed6b7a871b6,0x000ab42c02ff0806,0x0009af12f46ee10a,0x0005d377ff131d77,0x00005a677099acd8}, {0x000ac9b951626815,0x0009abdb942babd9,0x00036440880eb706,0x000163339c586c4f,0x0000709ca935dc3b}}, {{0x000ff3ccda445aca,0x000f0859e39c86a5,0x00090203fe429386,0x0008a52bf2703bab,0x0000720aa0200a65}, {0x0007538fdce5c9c9,0x00015246ebcb614e,0x0001842f337ae4a6,0x000828acc435ef95,0x00005e104588fd92}}, {{0x0003cab9fe36412f,0x000c67555bd68737,0x0001bae6459ab06a,0x000fa54dfd187fa0,0x0000876a919b3578}, {0x0002b2279ace5b23,0x00067ca98cbd005b,0x000e40955a4d14a0,0x000970e03ea45012,0x00007185a2170d87}}, {{0x0005612acb6e9367,0x0000244b28116bc6,0x0000fe9ace978300,0x00001bd8b738ef68,0x0000764500d3e681}, {0x0005a153f84b39ee,0x0004d79c4f71c297,0x000ad48b40f23e0d,0x000fe1df83cf30f0,0x0000ed994a14ad8c}}, {{0x0006efacdd042013,0x0003311876df9490,0x0002bc23a0bac093,0x00009572e8adfc0d,0x0000c9e44ac33ba1}, {0x0007febbe90ab31f,0x0000bd134ef68004,0x0007788b8aa2b3eb,0x00025338748a1e98,0x0000b0f3a19b0368}}, {{0x0006fbd381cc78af,0x00071706d2d15d34,0x000ee95e156dcdce,0x00005368df42e000,0x00005cd53efe90cd}, {0x00031ea895eeeb96,0x000ccf55d9280aea,0x0007880c92d842de,0x00017146595637e4,0x0000641ce44806ad}}, {{0x000824118043c9a3,0x0005cf70caa98b65,0x000f51f396391481,0x000f7d40813d12f8,0x0000547dad76afc8}, {0x000149d080befd0b,0x000b7195cedc7d61,0x0009dc3f0e5886a2,0x0004cb9a99003a55,0x00007bf2af415c17}}, {{0x000b64ed8b470837,0x000667567a1863c8,0x000a8958dda010c6,0x0009d8fce07e107c,0x0000333c3dcb7dec}, {0x000eef3725031b69,0x000b3d8017798df6,0x0004553846f57184,0x000740a78efac9c4,0x000091dcab915273}}, {{0x00034d3d7a665eae,0x000176ef69c8e8cc,0x0002d1efd49af983,0x000c8da18040aabd,0x00003d8b47daa6ea}, {0x0002a6ab05930688,0x000ae5a1d5b5c164,0x000ec89eb5f6487d,0x000e45cd4ff7be70,0x0000da3d01424bad}}, {{0x00038654291e9930,0x0005df3ebe005344,0x00051191326bf2e8,0x0002cb4d29e094e5,0x0000c2bfc12b6dc4}, {0x000c45947fa997d1,0x000efc7b04beec10,0x00092b0b4c905403,0x0008649820b0076a,0x00000768c5a27aa6}}, {{0x0004fa4594af9a68,0x000599a9cc36d9eb,0x000b7f57263399f3,0x0000337fb3d0ceae,0x00005ca399f0e87c}, {0x000ea931d2385710,0x0001ed59e07954dc,0x000a7c626181c100,0x000429eb1a4ec0a3,0x000096fa65837c79}}, {{0x000024de86d1520e,0x00030986cb7e66af,0x000efe7c68e15b56,0x000d805f49c36865,0x0000ab5898f85171}, {0x0005276853f145ec,0x000381824620abe6,0x000b802ce92b4fb6,0x00036d087612db6f,0x0000a0d67a1b76f7}}, {{0x0004f2782c6ac72a,0x0003cafa67117a5c,0x0002aab6fb1c93c9,0x0004a540bc21b67e,0x0000934f022b3868}, {0x000d03cbbc8303f2,0x0004a4fb67b44644,0x00075a8b54b44e4e,0x0007e18bf968e89e,0x00000f6f42ac1a37}}, {{0x000486f46ce1f619,0x000037a2e0f90539,0x00020a418cea6f5e,0x000ba43f6c178ddf,0x00006ab2cb90f6c4}, {0x0004b1c6938cfc22,0x00020e13845f695e,0x000d68e0193de57e,0x000ebc9ff5be6cb4,0x000002c5058b0d9d}}, {{0x000c3c04fde203fa,0x0005baff5dd91577,0x000ef4054c12be81,0x0006add827ff0b61,0x0000a1f02d5283f0}, {0x0006692f1555eecd,0x000c44b0a336ee5a,0x00082f8f5b11fe2e,0x000da11c05d843a5,0x0000c68bae17ef36}}, {{0x000ee12df5fabf2b,0x000be45a670b441d,0x000c610623c7e5fd,0x000d5872bd798c04,0x00009e1db3844e1d}, {0x0005ddaf191ee063,0x000f3d7cea2df0ad,0x00086387d70cdf49,0x000cefd8af41cf1c,0x00009846533056ae}}, {{0x00021d62549e2b45,0x00037cb224e3c015,0x000678b1ce2f4b85,0x0000525f28baa01d,0x00005d6e33c34710}, {0x000d0d35e745bee9,0x000f90455fdf7490,0x000eb3d3ef5582c0,0x000a223455ee33cb,0x0000ede029ddb7d6}}, {{0x00094f9647c9d90c,0x0009ae5f214b69bd,0x0007a420dba58efa,0x000a1778c3aa70bb,0x00005b6de0077a42}, {0x0009d9ea019d4132,0x0007f0e583e34c87,0x0005be0ce07a75bd,0x000b6b3d395891e3,0x0000411317743abc}}, {{0x00071e9d9637bd7b,0x000aa30673d89731,0x0004f6faaa823ed5,0x0008bb2383e64b03,0x00002b4b7d4e2602}, {0x00010fb3c893e582,0x00051b773cca2248,0x0007552b33ebecfb,0x00069cecde31e97f,0x00008f7134559072}}, {{0x000b81bd0d95dfea,0x000920c24df0288c,0x000310dd6c5ef9f3,0x000d5abf1b0350c5,0x0000ad3ddb3e8a48}, {0x000dd398b526731f,0x0005384805e5c192,0x000b7e61e9fed2fe,0x000e23cfdd2588ba,0x0000c740a3eef5c3}}, {{0x000eac2018c33f78,0x0006fe797f0c8057,0x000b588aee816f24,0x000cabc89d091be7,0x00003cd7be0bdaf6}, {0x0009197eaba2edb2,0x000261290082c9bf,0x0002d252eb7c7e7f,0x000069d1ae302bc4,0x000059df1546cf2c}}, {{0x000c6ed00d94ec36,0x00088e1af59b2c21,0x000e2ff2bcf61175,0x000869457c578360,0x0000523a23621201}, {0x00034a09be29e76a,0x000690f5c6bae145,0x0006b6f117764e98,0x000976119eff6ee2,0x000083c1f34b5380}}, {{0x000aa5996ef32628,0x000199d82779220a,0x000d1241a4aeba26,0x000ed2f9f34d5f06,0x00004acf34a65fce}, {0x000315c7f2ccd41e,0x000c5fdf0096ae54,0x00080691f3391667,0x00052631991b02d6,0x0000c48b23574895}}, {{0x0008812c701e04a9,0x0002050be8112a19,0x000edb9dd4072896,0x000fd219a3328fa8,0x0000e4723d681c68}, {0x0004a362eddf7e14,0x000fa26194b59490,0x000cc6e78db8c366,0x0006655f1cc62e79,0x0000d82e71dbd404}}, {{0x00042661e0e01d69,0x000365b508430cfc,0x0009c570783ab355,0x000126719831e04a,0x000080fe3aa553aa}, {0x0005fba614f1229e,0x000ff23b90b04642,0x00088bd06048f481,0x0003938fab45f5ed,0x000081191df8129f}}, {{0x000e6fa9951025d2,0x00041ecbf164a4d8,0x000d2f4e8491ed8a,0x00055b97fd6f9239,0x00006956adf726ae}, {0x0003a64e362a0314,0x000daa7b2078d584,0x00085660784da40f,0x000e2e4313534367,0x000074d604a28332}}, {{0x000a9eacf4537898,0x0002535b7ed6beae,0x000d61511432f159,0x000edfe8ae015426,0x0000e7ad54ed3027}, {0x0008791dd6d06fcd,0x000cbb7fbce3acab,0x000bc7d0c0bc5826,0x000ec5864d8cb9b5,0x0000d5249e385260}}, {{0x00031d9a10b92593,0x000b60bc06806933,0x000608f7d34ced3d,0x000e6d0d2006d8b2,0x0000aed68ceedb49}, {0x00015ad47c543ae5,0x000bbf84989e807a,0x00020645060e02d8,0x000196b5ba87d4ae,0x000068321bbe2e41}}, {{0x000fa99480713a9b,0x00006bf34178f755,0x000be4593bc93577,0x0006d10a3c6ef3f1,0x0000310bacda7514}, {0x00057088f40a62e7,0x0005ee7b59e56baa,0x000af9ff64d366c7,0x0004ffc6b10b30ad,0x0000d6bd4deb6eb0}}, {{0x0003bad7134faa7e,0x000c0b033f5eaa35,0x000e4f98ff42bcb8,0x000ec9a998139559,0x0000f99dd5db139f}, {0x00009ecb311e12f8,0x0002adc0a4dc54fc,0x0005c0b088460433,0x000ce37796ea0ae1,0x0000ece0022c632b}}, {{0x000a05993f51c69f,0x00070bea577129dd,0x00064408337ea113,0x0005a48ba7c02c90,0x000035f93ee50fde}, {0x0001277019f51c41,0x0006adfd4c1abe93,0x00083e23a3e47aca,0x000aa67a89f9df66,0x000092d1f5304fa0}}, {{0x000ac330d6c7b459,0x00082e88c3411e11,0x00005313b3e445d1,0x0006bc33cc1dc4d9,0x00004685343106e0}, {0x00051b83920ae37d,0x0001c71d6750f1e5,0x000b709a1faade96,0x0007149f2dc25e54,0x0000b71cc89b494b}}, {{0x000f3f8d09521bed,0x0008512c9daab73a,0x0003da2ba27d45d8,0x00053296a099b7b5,0x0000e7f2156e567c}, {0x00017ea24df91ea0,0x000270e60988d6c3,0x000418dde749e07d,0x0007a0c55165c906,0x00000189658e7c42}}, {{0x0005554a920980f5,0x0004d83056f4f7dc,0x000745be3258ac61,0x000646af5b2b9c78,0x000032efb61c140e}, {0x00065f3c23f4987a,0x00029a1787327ea8,0x000b93558610d559,0x0001dac6b44f9ef7,0x00008c3f3947610c}}, {{0x00036c41c02e3f96,0x000c00d78de5829f,0x0006cdb1416e315b,0x0006d6039934b045,0x00005408b5b7c401}, {0x000046423ee53cf9,0x000ca2000b9b28d8,0x000ac80402e6f559,0x000737cf3b0e8eab,0x00000a478fff164c}}, {{0x000d5dbc3bce5259,0x000a79bab068adc4,0x000702cff0e692d9,0x0009162104dab4e1,0x00007c3b223bc6e0}, {0x000a4bae9b92e722,0x00066cd5c34091b3,0x0006af7b98c5842b,0x00046e36bf2afb32,0x0000e0928bb0a702}}, {{0x000e1f1c48f51b67,0x000e3017ad888cfc,0x000124d6978fa7fb,0x00020cae67af53f3,0x00001d14379ab093}, {0x0006d3efd5b32f13,0x0008955fa05fbe53,0x0000194e6d931907,0x0003184e5f4c7300,0x0000f48a960c8670}}, {{0x0004dae073946e67,0x00069e56390f104b,0x00034438ec69b46a,0x0003d9a22a832b30,0x000078dfabdaf745}, {0x00083fe3d2f9dc1d,0x000b45b9863f9203,0x000ed43a45a02d9b,0x0004dc1e596b8494,0x00001045a9c041b7}}, {{0x00016c0a59ce7847,0x0003816390641219,0x000c52eac415e082,0x0004dd076ea35e04,0x0000e4629568ba7c}, {0x00071b6a7b975de1,0x0007b677e54ee47d,0x0004a7e4c03aec55,0x0002fc9359233ebf,0x00003b0f0abe072b}}, {{0x000dfefe8800dcd2,0x0007813d211bb68d,0x0006e883a7a79b7c,0x0004ea45689552b4,0x00008de706a7de1a}, {0x000c4e3d983df145,0x000fdfedeea597b3,0x0000e50daef33ef9,0x00096c99395a861b,0x0000f4ee038dd678}}, {{0x0002fa9a80943602,0x000a160fc4fb1606,0x000a18843d079884,0x000fdcfc9ae67dea,0x0000de5999876f2b}, {0x0001e086666832ff,0x000ac7312a202d98,0x000df4eb39af1d51,0x0006ba69df8bab4d,0x00004f813058f3c4}}, {{0x000e4d9deba1f764,0x00046544992ba84d,0x00062571d3ef1e08,0x0003d6cdf5b4eef3,0x0000c6b0de82e039}, {0x00019759c17b4e15,0x0007eb4e8f856535,0x0002db7b0e1f35cb,0x000a2de21c2ce964,0x0000ede5f6162f54}}, {{0x0002e8ff962e6fb2,0x0003791b5f6c1220,0x000daf6cb28042fd,0x000a0d5f509fdfe4,0x0000a70291c45d04}, {0x000e258b0e2b68da,0x000b17fac85bdaf9,0x000d1b986bf47d76,0x0002f63d6778a846,0x0000223266c01388}}, {{0x000f6489e4813958,0x00073454ba37e004,0x000852a0cf198eb2,0x0001c1d7d37038b3,0x00005057db2e3939}, {0x000ab92ce347b4c8,0x000ca340fa0188c7,0x000ef094a8b99eb3,0x00014dcfa7df268e,0x00005a65feda02ad}}, {{0x0006ea594087938e,0x000c2c29c1b6b97c,0x000fcd2e662321e1,0x0007d0edd9981f5b,0x0000571509bfdac6}, {0x000506cccb99c73e,0x000781554bcdd381,0x00076723b50a8b0a,0x000df26130d1d4f5,0x00007791681ec370}}, {{0x00016a84ca2278a7,0x0005b22100cbee90,0x0008b97d91e063af,0x000ba251ae16b457,0x0000b228a1a62245}, {0x00037ce46041bf2a,0x0009154529a0343c,0x00093bcf590509e3,0x000354b75ffee430,0x0000d443bb4bab01}}, {{0x000f1435aaae6483,0x000a104f999a4352,0x0009f21ba7c9f131,0x0005b56e3000fcee,0x000045e97d130480}, {0x000862d2138a5c21,0x0006da716279c728,0x0006fa6fa150dba3,0x00084fa32f114503,0x000020200ebf2740}}, {{0x00090af2a4f30bb8,0x000233a2204ec06a,0x000572fbdc316dfd,0x0002843a0475a78f,0x00004ba9e239c4e7}, {0x0009abfc1137d0a0,0x00011346b7ea4127,0x000361a1d3145421,0x00011092560f9c0e,0x0000e66391042bad}}, } }; #endif //(_DISABLE_ECP_SM2_HARDCODED_BP_TBL_) IPP_OWN_DEFN(const cpPrecompAP *, gfpec_precom_sm2_radix52_fun, (void)) { static cpPrecompAP t = { /* w = */ BASE_POINT_WIN_SIZE, /* select_function = */ gesm2_select_ap_w7_ifma, /* precomputed_data = */ (BNU_CHUNK_T *)ifma_ec_sm2_bp_precomp }; return &t; } #endif //(_IPP32E >= _IPP32E_K1) #endif // _IFMA_ECPRECOMP7_SM2_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/ifma_sm2_key_exchange_shared_key.c000066400000000000000000000253221470420105600315730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #if (_IPP32E >= _IPP32E_K1) #include "gfpec/sm2/sm2_stuff.h" #include "gfpec/sm2/ifma_defs_sm2.h" #include "gfpec/sm2/ifma_ecpoint_sm2.h" #include "gfpec/sm2/ifma_arith_method_sm2.h" /* clang-format off */ __IPPCP_INLINE void ifma_sm2_set_affine_point_radix52(PSM2_POINT_IFMA *rp, const BNU_CHUNK_T *x, const BNU_CHUNK_T *y, ifmaArithMethod *method) /* clang-format on */ { ifma_import to_radix52 = method->import_to52; ifma_encode p_to_mont = method->encode; rp->x = to_radix52(x); rp->y = to_radix52(y); rp->x = p_to_mont(rp->x); rp->y = p_to_mont(rp->y); rp->z = FESM2_LOADU(PSM2_R); return; } /* clang-format off */ __IPPCP_INLINE void ifma_sm2_get_affine(BNU_CHUNK_T *x, BNU_CHUNK_T *y, const PSM2_POINT_IFMA* p, ifmaArithMethod* method) /* clang-format on */ { /* extract affine coordinate */ fesm2 loc_x, loc_y; gesm2_to_affine(/* x = */ &loc_x, /* y = */ &loc_y, /* p = */ p); ifma_export to_radix64 = method->export_to64; ifma_decode p_from_mont = method->decode; loc_x = p_from_mont(loc_x); loc_y = p_from_mont(loc_y); to_radix64((Ipp64u *)x, loc_x); to_radix64((Ipp64u *)y, loc_y); return; } /* clang-format off */ IPP_OWN_DEFN(IppStatus, gfec_key_exchange_sm2_shared_key_avx512, (Ipp8u* pSharedKey, const int sharedKeySize, Ipp8u* pSSelf, const IppsBigNumState* pPrvKey, IppsBigNumState* pEphPrvKey, IppsGFpECKeyExchangeSM2State *pKE, Ipp8u* pScratchBuffer)) /* clang-format on */ { IPP_UNREFERENCED_PARAMETER(pScratchBuffer); const IppsKeyExchangeRoleSM2 role = EC_SM2_KEY_EXCH_ROLE(pKE); const IppsGFpECPoint *pPubKey = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE) : EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE); const IppsGFpECPoint *pSelfEphPubKey = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE) : EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE); const Ipp8u firstNum = (ippKESM2Requester == role) ? 0x03 : 0x02; IppStatus sts = ippStsNoErr; IppsGFpECState *pEC = EC_SM2_KEY_EXCH_EC(pKE); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gsModEngine *nME = ECP_MONT_R(pEC); const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ ifmaArithMethod *pmeth = (ifmaArithMethod *)GFP_METHOD_ALT(pME); ifmaArithMethod *nmeth = (ifmaArithMethod *)GFP_METHOD_ALT(nME); ifma_import to_radix52 = pmeth->import_to52; ifma_export from_radix52 = pmeth->export_to64; /* Mod engine (mod n - subgroup order) */ ifma_encode n_to_mont = nmeth->encode; ifma_decode n_from_mont = nmeth->decode; ifma_mul n_mul = nmeth->mul; ifma_add n_add = nmeth->add; /* check that Ephemeral Public and Private Keys are related (R(a/b)=r(a/b)G) */ /* Ephemeral Private Key -> r(a/b) */ IppsGFpECPoint pTmpPoint; cpEcGFpInitPoint(&pTmpPoint, cpEcGFpGetPool(1, pEC), 0, pEC); BNU_CHUNK_T *pDataEphPrv = BN_NUMBER(pEphPrvKey); gfec_PubKey_sm2_avx512(&pTmpPoint, pDataEphPrv, BN_SIZE(pEphPrvKey), pEC, pScratchBuffer); // r(a/b)*G int result = gfec_ComparePoint(&pTmpPoint, pSelfEphPubKey, pEC); // R(a/b) == r(a/b)G cpEcGFpReleasePool(1, pEC); IPP_BADARG_RET(!result, ippStsEphemeralKeyErr); /* create buffer data (it needs further use compute tmp_p) * -> SM3( x(u/v)(0) || Za(1) || Zb(2) || xa(3) || ya(4) || xb(5) || yb(6) ) */ BNU_CHUNK_T *pDataBuff = cpGFpGetPool(7, pME); BNU_CHUNK_T *xuv = pDataBuff; /* x(u/v)(0) */ BNU_CHUNK_T *za = pDataBuff + 1 * elemSize; /* Za(1) */ BNU_CHUNK_T *zb = pDataBuff + 2 * elemSize; /* Za(1) */ BNU_CHUNK_T *xa = pDataBuff + 3 * elemSize; /* xa(3) */ BNU_CHUNK_T *ya = pDataBuff + 4 * elemSize; /* ya(4) */ BNU_CHUNK_T *xb = pDataBuff + 5 * elemSize; /* xb(5) */ BNU_CHUNK_T *yb = pDataBuff + 6 * elemSize; /* yb(6) */ PSM2_POINT_IFMA Ra; /* ephemeral public key User A */ PSM2_POINT_IFMA Rb; /* ephemeral public key User B */ PSM2_POINT_IFMA P; /* public key User (A/B) */ /* convert to Montgomery IFMA SM2 */ /* extract -> xa | ya | xb | yb */ BNU_CHUNK_T *_xa_ = za; /* use Za(1) */ /* 2) x(a/b)` = 2^w + (x(a/b) & (2^w – 1)) */ /* point to affine coordinate */ cpSM2KE_get_affine_ext_euclid(/* x = */ xa, /* y = */ ya, /* p = */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE), /* pEC = */ pEC); /* set affine coordinate radix 52 */ ifma_sm2_set_affine_point_radix52(/* rp = */ &Ra, /* x= */ xa, /* y = */ ya, pmeth); /* reduction x = 2^w + ( x & (2^w - 1) ) */ cpSM2KE_reduction_x2w(_xa_, xa, pEC); /* to big endian */ cpSM2KE_xy_to_BE(xa, ya, pEC); BNU_CHUNK_T *_xb_ = zb; /* use Zb(2) */ /* 4) x(b/a)` = 2^w + ( x(b/a) & (2^w – 1) ) */ cpSM2KE_get_affine_ext_euclid(/* x = */ xb, /* y = */ yb, /* p = */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE), /* pEC = */ pEC); /* set affine coordinate radix 52 */ ifma_sm2_set_affine_point_radix52(/* rp = */ &Rb, /* x = */ xb, /* y = */ yb, pmeth); /* reduction x = 2^w + ( x & (2^w - 1) ) */ cpSM2KE_reduction_x2w(_xb_, xb, pEC); /* to big endian */ cpSM2KE_xy_to_BE(xb, yb, pEC); BNU_CHUNK_T *pPool = cpGFpGetPool(3, pME); recode_point_to_mont52(&P, ECP_POINT_DATA(pPubKey), pPool /* 3 elem */, pmeth, pME); cpGFpReleasePool(3, pME); /* pPool(3) */ /* extract to role */ BNU_CHUNK_T *_xf_ = (ippKESM2Requester == role) ? _xa_ : _xb_; BNU_CHUNK_T *_xs_ = (ippKESM2Requester == role) ? _xb_ : _xa_; PSM2_POINT_IFMA *R = (ippKESM2Requester == role) ? &Rb : &Ra; /* 3) t(a/b) = ( d(a/b) + x(a/b)`*r(a/b) ) mod n */ fesm2 d, r, x1; d = r = x1 = setzero_i64(); /* preparation d(a/b) */ d = to_radix52((const Ipp64u *)BN_NUMBER(pPrvKey)); d = n_to_mont(d); /* preparation r(a/b) */ r = to_radix52((const Ipp64u *)pDataEphPrv); r = n_to_mont(r); /* preparation x(a/b)` */ x1 = to_radix52((const Ipp64u *)_xf_); x1 = n_to_mont(x1); /* compute */ r = n_mul(x1, r); /* r = x(a/b)`r(a/b) */ d = n_add(d, r); /* t = ( d(a/b) + x(a/b)`*r(a/b) ) */ /* t -> convert form Montgomery */ d = n_from_mont(d); /* 5) U/V = [h*t(a/b)]( P(b/a) + [x(b/a)`]R(b/a) ) = ( x(u/v), y(u/v) ) */ const int scalarBits = ((elemBits + 1) / 2); gesm2_mul(R, R, (const Ipp8u *)_xs_, scalarBits); /* R = [x(b/a)`]R(b/a) */ gesm2_add(&P, &P, R); /* P = P(b/a) + [x(b/a)`]R(b/a) */ BNU_CHUNK_T *pScalar = xuv; /* use buffer x(u/v)(0) and Za(1) */ from_radix52((Ipp64u *)pScalar, d); pScalar[elemSize] = 0u; /* extended scalar - add 0 -> R = [scalar]P */ gesm2_mul(&P, &P, (const Ipp8u *)pScalar, elemBits); /* P = [h*t(a/b)]( P(b/a) + [x(b/a)`]R(b/a) ) */ /* check U/V == 0 */ const mask8 is_zero = (mask8)(FESM2_IS_ZERO(P.x) & FESM2_IS_ZERO(P.y) & FESM2_IS_ZERO(P.y)); if ((mask8)0xFF == is_zero) sts = ippStsEphemeralKeyErr; /* extract x(u/v) ,y(u/v) */ ifma_sm2_get_affine(/* x = */ EC_SM2_KEY_EXCH_POINT_X(pKE), /* y = */ EC_SM2_KEY_EXCH_POINT_Y(pKE), /* p = */ &P, pmeth); cpSM2KE_xy_to_BE(/* x = */ EC_SM2_KEY_EXCH_POINT_X(pKE), /* y = */ EC_SM2_KEY_EXCH_POINT_Y(pKE), pEC); /* Precompute Hash */ Ipp8u *pBuff = (Ipp8u *)pDataBuff; /* tmp_p = SM3( x(u/v) || Za || Zb || xa || ya || xb || yb ) */ /* copy x(u/v)(0) */ cpSM2_CopyBlock(xuv, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_X(pKE), elemBytes); /* copy Za(1) */ cpSM2_CopyBlock(za, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE), IPP_SM3_DIGEST_BYTESIZE); /* copy Zb(2) */ cpSM2_CopyBlock(zb, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE), IPP_SM3_DIGEST_BYTESIZE); /* xa || ya || xb || yb - is exists */ const int sizeS_SM3 = elemBytes + 2 * IPP_SM3_DIGEST_BYTESIZE + 4 * elemBytes; /* 224 bytes */ /* copy to next operation */ cpSM2KE_compute_hash_SM3(EC_SM2_KEY_EXCH_PRECOM_HASH(pKE), pBuff, sizeS_SM3); if ((NULL != pSSelf) && (ippStsNoErr == sts)) { /* 6) S(a/b) = SM3( 0x0(3/2) || y(u/v) || tmp_p ) */ /* copy 0x0(3/2) */ pBuff[0] = firstNum; /* copy y(u/v) */ cpSM2_CopyBlock(pBuff + 1, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_Y(pKE), elemBytes); /* copy tmp_p */ cpSM2_CopyBlock(pBuff + 1 + elemBytes, EC_SM2_KEY_EXCH_PRECOM_HASH(pKE), IPP_SM3_DIGEST_BYTESIZE); const int sizeSab_SM3 = 1 + elemBytes + IPP_SM3_DIGEST_BYTESIZE; /* 65 bytes */ cpSM2KE_compute_hash_SM3(pSSelf, pBuff, sizeSab_SM3); } /* compute KDF */ /* 7) K(a/b) = KDF(x(u/v) || y(u/v) || Za || Zb, klen) */ /* copy x(u/v)(0)*/ cpSM2_CopyBlock(xuv, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_X(pKE), elemBytes); /* slot x(u/v)(0) */ /* copy y(u/v)(1) */ cpSM2_CopyBlock(za, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_Y(pKE), elemBytes); /* slot Za(1) */ /* copy Za(2) */ cpSM2_CopyBlock(zb, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE), IPP_SM3_DIGEST_BYTESIZE); /* slot Zb(2) */ /* copy Zb(3) */ cpSM2_CopyBlock(xa, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE), IPP_SM3_DIGEST_BYTESIZE); /* slot xa(3) */ const int sizeKab_KDF = 2 * elemBytes + 2 * IPP_SM3_DIGEST_BYTESIZE; /* 128 bytes */ /* set pointer start */ pBuff = (Ipp8u *)pDataBuff; /* compute KDF */ KDF_sm3(pSharedKey, sharedKeySize, (const Ipp8u *)pBuff, sizeKab_KDF); cpGFpReleasePool(7, pME); /* clear Ephemeral Private Key */ cpBN_zero(pEphPrvKey); /* clear secret register */ PurgeBlock(&r, sizeof(r)); PurgeBlock(&d, sizeof(d)); return sts; } #endif // (_IPP32E >= _IPP32E_K1) cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/pcpsm2pprecomca.c000066400000000000000000017725671470420105600263110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // EC over Prime Finite Field (SM2 precomputed) // // */ #include "owncp.h" #include "gfpec/pcpgfpecstuff.h" #define OPERAND_BITSIZE (256) #define LEN_P256 (BITS_BNU_CHUNK(OPERAND_BITSIZE)) /* SM2 affine point */ typedef struct{ BNU_CHUNK_T X[LEN_P256]; BNU_CHUNK_T Y[LEN_P256]; } SM2_POINT_AFFINE; extern const __ALIGN64 SM2_POINT_AFFINE precomputed_ec_sm2[37][64]; #if defined( _IPP_DATA ) #if !defined(_DISABLE_ECP_SM2_HARDCODED_BP_TBL_) /* see ippcp_baseptbl.cpp test for generation details */ const __ALIGN64 SM2_POINT_AFFINE precomputed_ec_sm2[37][64] = { /* digit=0 base_pwr=2^0 */ { {{LL(0xf418029e,0x61328990),LL(0xdca6c050,0x3e7981ed),LL(0xac24c3c3,0xd6a1ed99),LL(0xe1c13b05,0x91167a5e)}, {LL(0x3c2d0ddd,0xc1354e59),LL(0x8d3295fa,0xc1f5e578),LL(0x6e2a48f8,0x8d4cfb06),LL(0x81d735bd,0x63cd65d4)}}, {{LL(0xbc3be46a,0x0af037bf),LL(0x2d8fa938,0x83bdc9ba),LL(0x5788cd24,0x5349d94b),LL(0xcaa5736a,0x0d7e9c18)}, {LL(0x69db9ac1,0x6a7e1a1d),LL(0xc4a8e82b,0xccbd8d37),LL(0x9b7157ac,0xc7b14516),LL(0x6c21bdf5,0x947e7465)}}, {{LL(0xab589e4a,0x1cda54fd),LL(0xdb4f0a0d,0x26765289),LL(0x8ceb4a0a,0x0a265a30),LL(0xfe887c64,0x3019fd6b)}, {LL(0x4b2fc190,0x0a10fbe9),LL(0x87cbce60,0xf40aa52b),LL(0x6dc13c97,0xcc496bfa),LL(0x5bb3fbb4,0x28ad3478)}}, {{LL(0x98615060,0x393f7c5a),LL(0xe9016209,0x487ea27f),LL(0xa09f9020,0x8a86bcb4),LL(0xc899dbe1,0x50dc8e3a)}, {LL(0xfd619998,0xfc099043),LL(0x7c7383bd,0x1de135ea),LL(0x32cf70ed,0x4d0bd556),LL(0x25bce9e3,0x6ffc31c5)}}, {{LL(0x6a9c8162,0x9a575633),LL(0x21dfcc53,0x15aa58f2),LL(0x1ef5f4c5,0x7ad354bf),LL(0x63f875b9,0x0f443ef3)}, {LL(0xd3450133,0x2e81d68f),LL(0xe3607d18,0xb30f4bbd),LL(0x362258ef,0xb1826a4c),LL(0x142a6768,0x7b415276)}}, {{LL(0x0acd72ba,0x136a9c4c),LL(0x5e7ec73c,0xb1274a25),LL(0x5de34db6,0xf15a876e),LL(0x8cba8047,0x85e74ca0)}, {LL(0xb469eb37,0x08454cdd),LL(0xc99754f8,0x8fbf6d1f),LL(0xec30e984,0x1060e7f8),LL(0x4b8c598a,0xb568bc97)}}, {{LL(0x81f06784,0xaa3531c7),LL(0x07132520,0x0b894193),LL(0xacfe18c5,0x84ee5b69),LL(0xd9fbec28,0xbbf492e0)}, {LL(0xe5f6186d,0x313a35c1),LL(0x757a01b8,0x0e449a2e),LL(0x2bd99baf,0x96c9b992),LL(0x3b84d777,0x2ba05a8f)}}, {{LL(0x09122670,0xde523a1c),LL(0x22cc810c,0x90be6f2a),LL(0x4387df9e,0x086e6341),LL(0xd9c44134,0x115c2fc0)}, {LL(0x8799302a,0x9334430d),LL(0xe27b7ea4,0x693b3500),LL(0x9a8f3382,0xcbe1136f),LL(0xb5778247,0xe77fd5f2)}}, {{LL(0x30fbde86,0x98e795c3),LL(0xab21af8f,0x8e5e0495),LL(0xb48669b4,0x3925bf83),LL(0x469522c8,0x77d88740)}, {LL(0x987b04ce,0x8fbf8b5b),LL(0x3aff4428,0x63c563a8),LL(0x53a6e969,0x5dc11165),LL(0x32697f4c,0x822a6c24)}}, {{LL(0x642cb143,0x6774298a),LL(0x2d110e71,0xecdb60d8),LL(0x1388728e,0xe810b11b),LL(0xd8603a8a,0x2e8237d8)}, {LL(0x50aeeae1,0x673968fc),LL(0x6746a3f4,0x08c65d19),LL(0xd7dd7165,0x7a61a6b5),LL(0xa9b6df3a,0xe31bbfd9)}}, {{LL(0x3421e115,0x2b252ad0),LL(0xc6affc01,0x7557c8c7),LL(0x8a509267,0xd90c19fd),LL(0xe0d871c8,0x483da168)}, {LL(0xc10729bf,0x72d6f9b3),LL(0x15b7061e,0x5dd84021),LL(0x9f2c587d,0x9bfea2db),LL(0x98641ec2,0x528398a7)}}, {{LL(0xf3afdd62,0x18a65d8d),LL(0xd6d7e4e4,0x89f38500),LL(0x9d8d4f07,0x65708c6a),LL(0xd0bdc7f4,0xb90ea13c)}, {LL(0x8c3e2b32,0x58985855),LL(0xbcfad3a1,0xfa48d5c5),LL(0x62385ffa,0x5c3544e7),LL(0x7e72aeb7,0xb6bd39ed)}}, {{LL(0x8000fe4e,0x34e51c6a),LL(0x89c46941,0x7da2bdfd),LL(0xe1bc2b2e,0x667ba91d),LL(0x10a73e5c,0x3c80c9d0)}, {LL(0xc7f5c64d,0x4fadebbe),LL(0x3ea35052,0xaef09eb4),LL(0x26ec55f9,0x167ee11b),LL(0x85189260,0x45fa508a)}}, {{LL(0x22542fc3,0xa0e9a439),LL(0xddac78dc,0x3f194a6c),LL(0x6f74d053,0xa75ae72d),LL(0x097c6617,0x0f8babeb)}, {LL(0x4303c247,0x1d12bc5c),LL(0xbd1e246c,0xfe0c027a),LL(0xb69b55ad,0xe9ca1a99),LL(0x117cd63a,0xff6cd2b0)}}, {{LL(0xdde97d4d,0xf3489343),LL(0xbbb2ce1f,0x9c14e38a),LL(0xcfddf221,0x25866911),LL(0x460efef1,0x0df89411)}, {LL(0x73ae8326,0xf713f30e),LL(0xcdd274a1,0xd9be66a8),LL(0x36885947,0xdf915ae2),LL(0x7878b781,0x2c5c1e9e)}}, {{LL(0x39e8a120,0xf71560c9),LL(0x7273b59a,0x7121d6b8),LL(0x8ef4639d,0x649535ce),LL(0x14cc6d58,0xcd01076e)}, {LL(0x96e74f8a,0x2705729a),LL(0x5533037e,0xb07e3230),LL(0x663c5c62,0x0846dcc1),LL(0x10fc3ac1,0x6a4759c1)}}, {{LL(0xcfbdfeff,0x3c126193),LL(0x4996d845,0x4a31dd20),LL(0x19f2b658,0x48a76ba0),LL(0x8890a8bc,0xbe330142)}, {LL(0x308aa041,0x287b34e1),LL(0x813adf29,0xcbf5da24),LL(0xcdcdc439,0xcdfc5a58),LL(0x198a6075,0xbda3bda2)}}, {{LL(0x1497fe38,0x639f92bc),LL(0xd58bd278,0x8ed8eeac),LL(0xb417bfe4,0xcf5d7ce6),LL(0x44400c59,0xf617c54e)}, {LL(0x7d8dc939,0xde635635),LL(0x241baaff,0x2e6a3a75),LL(0xe07e8e97,0x02f324e5),LL(0x70f9fc9d,0xeb715487)}}, {{LL(0x86712116,0xbefd3380),LL(0x884efe46,0x9b9e9707),LL(0x8c9e513f,0x611a1eec),LL(0x3b6dbcec,0xe2d8e3f5)}, {LL(0x4f8964e4,0x7cedab1c),LL(0xf4e139f8,0xee12d062),LL(0x9a9af4f3,0x8e63c9c0),LL(0x8b907b23,0xe3246dbb)}}, {{LL(0x71099001,0x70d5bda2),LL(0x15fae7dd,0x3d876d4a),LL(0x7b69c20e,0xaba0500f),LL(0x9834adf2,0xa8e3e094)}, {LL(0x980b21b9,0x69db851b),LL(0x788c2a30,0x274c1de2),LL(0xd47d153d,0x5caa5336),LL(0x57cef318,0xada69877)}}, {{LL(0xa0551c80,0x83879486),LL(0x658e61be,0x1611dea0),LL(0x1b935068,0x1fe95c82),LL(0x5b229223,0x8f01e019)}, {LL(0x7e93c389,0x23017e05),LL(0x9840dd64,0xce4ac99d),LL(0x1de86399,0xddc9b900),LL(0x88015785,0x6abe5cc3)}}, {{LL(0xb3c50898,0xc09545a9),LL(0x6c05d902,0xbd443361),LL(0x2c6bcc8c,0xed71f70c),LL(0xbdf8e908,0x8dbc0b88)}, {LL(0x4fcbcd9a,0x56eb5b98),LL(0x08114397,0xafb6fedc),LL(0xb35f7927,0x0500ce5b),LL(0x95efe710,0x7005bcf9)}}, {{LL(0x2eba7f39,0x125cbed2),LL(0x6c488d44,0xc7c42e76),LL(0x676915c4,0xdb8991f9),LL(0x9183839f,0xdf6ae594)}, {LL(0xc79f8bd1,0x4f69c304),LL(0xaa1662fa,0x638cb070),LL(0xba6f2599,0xc7f68c72),LL(0x1f6edfa9,0x11bb84d9)}}, {{LL(0xa215fda2,0x9ed156ec),LL(0x20c5ddb6,0x19de7a91),LL(0x0668c65d,0xc1ed949d),LL(0xd0826f6a,0x96683044)}, {LL(0x1adaa8ff,0x1e6325e0),LL(0x07ac392a,0xbc53bc24),LL(0xd9f06e44,0x2c342db5),LL(0x30db8c1a,0x3f529385)}}, {{LL(0xe7492326,0xc5957d29),LL(0x0663f829,0x3addc3df),LL(0x728cfdc1,0x8faa3169),LL(0x6b975134,0xde53aa7c)}, {LL(0xefddc764,0xf481759b),LL(0x09edaff3,0xd605474b),LL(0x653d48c9,0xc7df1eb9),LL(0xc5040212,0xa71e6854)}}, {{LL(0xafe945b5,0x136d8342),LL(0xe9d239c7,0x91707e7d),LL(0xfb2e80de,0xeda23dc5),LL(0xff614966,0x892bed73)}, {LL(0x838dc12d,0x2ded2367),LL(0xb002bd9c,0x73fd298c),LL(0x2c4629df,0xc548b426),LL(0x8f7e03b7,0x93605d17)}}, {{LL(0xd37c24cc,0x32861816),LL(0xe427975a,0x5bb54ee2),LL(0x32f943a9,0x6da013d2),LL(0x9bc202e5,0x0746a77a)}, {LL(0xcd1def5b,0x6db07a84),LL(0x861d9f9b,0x9421fe7f),LL(0x692181fb,0x71767292),LL(0xc9d2441d,0x0560e7e5)}}, {{LL(0x4d7e922a,0xf1496afd),LL(0xe11fa533,0x67f42a3f),LL(0x977956cd,0x9f903e5b),LL(0x1eb49608,0x37671e24)}, {LL(0x21fb2047,0x967950a0),LL(0x35da3c6b,0x141f96fb),LL(0xd27bba59,0xe07c3c40),LL(0x0e1af754,0xbde5ed1d)}}, {{LL(0x54f1f257,0xdc64c4b0),LL(0xb01196dc,0xecb033c8),LL(0x8202d5bd,0x54e65f4d),LL(0x2b2fd451,0x63afcc93)}, {LL(0x30640fb7,0x1e929a39),LL(0x5b361718,0xdc91387e),LL(0xf8f0bbe8,0x10aadecb),LL(0x0977e2bb,0x81d8f466)}}, {{LL(0xbd64cd96,0xdcaa3790),LL(0xcee698d3,0xbc8ac152),LL(0xa1143c45,0xde7192f7),LL(0xf5fb9ea0,0xf7c9d826)}, {LL(0xc9468f50,0x54aea92e),LL(0xcc427ed4,0x340f4459),LL(0x02ad5467,0x3fec5be9),LL(0x2cc6c8b5,0xec780d9c)}}, {{LL(0xb889c78a,0x7b179a8b),LL(0x0aca32c5,0x069a7ab9),LL(0x591b9a36,0xe4e5215e),LL(0x3bd54630,0x7802fb3e)}, {LL(0x233c6eeb,0x9a479313),LL(0x4e1cbabc,0x18c612ad),LL(0xc0e36f3b,0x28a29273),LL(0x7d3deb26,0xf4e2dfb1)}}, {{LL(0xadbb3c8b,0xa6c11369),LL(0x4c8ec378,0xd78af40b),LL(0x03f0a982,0xffb3a80d),LL(0xa83be50a,0x550e3e71)}, {LL(0x418ee45b,0x845c0fb2),LL(0x0791b964,0x5297cf43),LL(0xcc47e33b,0x676b638c),LL(0xfecf85b2,0xb1c52fac)}}, {{LL(0x3dba2c0e,0xf011b5e5),LL(0x026d4f11,0xa6c68448),LL(0xc3f206fb,0x11596db3),LL(0x29414a3c,0xc91c76dc)}, {LL(0xb94ddc7c,0x1839b9d1),LL(0x56ae8610,0xdfb20ce7),LL(0xd8734400,0x3e2b1cd9),LL(0xf01ea540,0x59f9329a)}}, {{LL(0x2351a2a9,0x7d4c140c),LL(0xbf4c9823,0x575c1e1b),LL(0x31068df9,0x8f11c2ca),LL(0x05e6def0,0xe3c17aa0)}, {LL(0x501c8630,0xe6281c70),LL(0xc88a412e,0xad240917),LL(0x390492d7,0x6f21bfb7),LL(0xc3a3ccb7,0x61ea1385)}}, {{LL(0x33733cbc,0x60494a83),LL(0x27ed8157,0x8da622a0),LL(0x0471ad90,0x0022b154),LL(0xd3568003,0x3bd0a4c5)}, {LL(0xd932df23,0xdc8e2d03),LL(0x7a1f5159,0x859ed940),LL(0x2a375b0f,0xad670e63),LL(0x9520db97,0x15922fae)}}, {{LL(0x59eb1a9b,0xfb73d16f),LL(0x8511e541,0x3ee8cc1f),LL(0x1590c321,0x20d72d59),LL(0x3bd075d4,0x62eab566)}, {LL(0xfae123ab,0xac07a7c7),LL(0x1f10af6e,0x83b89abf),LL(0x1da8ac5d,0x469962ec),LL(0x8c58c3b3,0x09761c35)}}, {{LL(0x7da90fc9,0x2c086d5e),LL(0x5cc27782,0x458e5ffd),LL(0xb9268939,0xc3f48611),LL(0xde4b9110,0x39fed873)}, {LL(0xfda698cc,0x16ef8f78),LL(0xa973bb50,0xb028dc21),LL(0xe29b725b,0x45eb849e),LL(0x14c6eae9,0xd41b5b6d)}}, {{LL(0xc55d5720,0x5e931b21),LL(0xa0e40b19,0xb628ccb2),LL(0x000651a5,0x42044ffe),LL(0x076544e7,0x2130b4de)}, {LL(0x3677c70f,0x38428594),LL(0xf8945d86,0xfdcdb038),LL(0x4169ae44,0xfb2e3d4c),LL(0x0d13bce2,0xd4695e9b)}}, {{LL(0x039d646d,0x45191390),LL(0xb12ba339,0x983b7a2e),LL(0x5923e7d6,0xdfd30d3e),LL(0xba9d206a,0xae3590f0)}, {LL(0xb6d5e62a,0x7d58d334),LL(0x7e402b12,0xb15b0544),LL(0x62ae8e01,0xac57e113),LL(0xf473edee,0x4d83804c)}}, {{LL(0xc81bc828,0x2faa7c4d),LL(0xfb62561f,0xb16ed9d7),LL(0x49c2fa93,0x4c9da270),LL(0xb311d90d,0x3b014c73)}, {LL(0xf5443332,0xd29c5d65),LL(0xeebdb7c2,0xb6457d54),LL(0x4cce9480,0xc6a0bf3a),LL(0x85355854,0xd434a3b0)}}, {{LL(0x8b2c703c,0x178ca01b),LL(0x0ab71a51,0x605bba53),LL(0x3db948d5,0x2140948e),LL(0x5fb6b8c1,0xc45b2689)}, {LL(0xf17b47bd,0x421f66de),LL(0x2e9b3ee5,0x57627a5a),LL(0x66614339,0xedf3920a),LL(0x4b638a46,0x7ea61903)}}, {{LL(0x3c030643,0x7203d542),LL(0x5e631461,0x7112bb3d),LL(0x2bc3da9c,0x2604eac7),LL(0x32d2541b,0x2e4964e7)}, {LL(0xe8b6482a,0x940faf46),LL(0x24d27c9e,0x8f772fcb),LL(0xca7c5f88,0x125c34d7),LL(0xd1f47795,0x9903eadb)}}, {{LL(0xe2147129,0x11aaa417),LL(0xf88a0a30,0x3ccef5c2),LL(0x90283f97,0x78d5207a),LL(0xd25226b6,0xba1261e9)}, {LL(0xd1e7a01c,0xbfc79248),LL(0x941ab2bd,0x373f1cd5),LL(0x19a0668b,0xf0881e21),LL(0x1f77bf0a,0x7b793789)}}, {{LL(0x63d4523d,0x49c2769b),LL(0xf0399eaf,0xf8df2cba),LL(0x22a2a74d,0x5ae94c69),LL(0xefd1e193,0xd08f8d45)}, {LL(0xc681f376,0x64341fc4),LL(0xec918711,0x3a8e25c8),LL(0x0608f50f,0xdf35304d),LL(0x9a973742,0x9b4c6967)}}, {{LL(0xbfba043b,0xb5c1f5d3),LL(0xe975f03b,0xaff4f896),LL(0xae2cbb01,0xea1f39bd),LL(0xa62915ff,0x4cc1c4cb)}, {LL(0x89e943b8,0x5eb4afa3),LL(0x154e565a,0x8c4d27e5),LL(0x7f2bced6,0x4e2e5a7e),LL(0x4487f6a3,0x7af408e2)}}, {{LL(0x97a60de7,0xe5dacbae),LL(0x4401b0ad,0x9774834c),LL(0x8a9113f9,0x7683bb00),LL(0x42b2ba67,0xc6fe7e8b)}, {LL(0x54e760c8,0xc0c0564d),LL(0x118606c2,0xf7b05401),LL(0xec3cd7b9,0x554a9b0f),LL(0x27916a21,0xce75ecfb)}}, {{LL(0x12118abd,0xf6638997),LL(0x097da3a7,0x2ba6e754),LL(0x0fdf9985,0x1df82085),LL(0x546c864a,0xbf73502a)}, {LL(0xc02d9ce0,0xdfde9323),LL(0xe4dd0e7d,0x580491e2),LL(0xae43b9b4,0xe71522d2),LL(0x6a231a41,0x876e3627)}}, {{LL(0xb36362ec,0xfa8ff511),LL(0x34085959,0x11c5a9f6),LL(0x9770c62b,0x272b86f2),LL(0x7c7e8827,0xf0626225)}, {LL(0xea1e13eb,0x929168bf),LL(0xce59b0f5,0xdb892971),LL(0x4f826f34,0x6769e31d),LL(0x0a955cec,0xfa1dd934)}}, {{LL(0xa294d7ea,0x123d9ca2),LL(0x4492569b,0x8699063b),LL(0xa8dd86c3,0x6a50eae9),LL(0x12c06c38,0x3d757d10)}, {LL(0x3e41e556,0x5a92c2c0),LL(0x6330c21a,0xa64595eb),LL(0xe184d925,0x70d8141a),LL(0xa2f10304,0x8543f2ce)}}, {{LL(0x9eaca504,0x4559b0a2),LL(0x2617bc9b,0xb9843a4b),LL(0x1b641003,0x5b28d4ee),LL(0x4ced538a,0x3e9af8e1)}, {LL(0x7bdf7dc2,0x3790fe89),LL(0xc32549ee,0xc7c74941),LL(0xabcd2f42,0xdcc8295b),LL(0xead078b6,0x48b29a4f)}}, {{LL(0x2040178e,0x8e8b28e3),LL(0x971725fc,0xceff8f3e),LL(0xfcee2cc1,0x4a97b6fa),LL(0xbac85b56,0x775df6a9)}, {LL(0xd28a21cc,0x32e5cbe6),LL(0xae2b82db,0xe8b86ada),LL(0x86e38e96,0x44dfbb50),LL(0x1afc2d4b,0x45d3fe7d)}}, {{LL(0xd23f620d,0x838b356e),LL(0x4592fe4b,0x2e8fa8ac),LL(0x3af5b1d8,0x1396e1b3),LL(0xcbf50fb0,0x9c0c2ef3)}, {LL(0x836e93e9,0xd9efb6c9),LL(0x0899163f,0xe6eb5870),LL(0xdca00d1b,0x3a2f6d77),LL(0xb40ba0d6,0x36f55f89)}}, {{LL(0x32866e57,0xf3b1701f),LL(0x59de0f2e,0xf0768473),LL(0xab57962d,0xe55d7aed),LL(0x2b60cabb,0x45004985)}, {LL(0xd5498888,0x8d539d6e),LL(0xa5e0ff6a,0x176ce1a0),LL(0xdc088c50,0xcb7c15ef),LL(0xc9a9ae2f,0x90393d7a)}}, {{LL(0xd396bdce,0xd9c1a140),LL(0x6fb2800f,0x4215b78b),LL(0x2f76b0df,0x8939109f),LL(0x2adb40a8,0x0f250897)}, {LL(0x3a86e009,0x4db0007c),LL(0xf968a635,0x6ef0ad95),LL(0x8eaefa78,0x58a82d4b),LL(0x493604a4,0xe8a181cb)}}, {{LL(0x520d216d,0x36c84e34),LL(0xc666171c,0x2b2ef6b5),LL(0x2ce29d37,0x9469b91f),LL(0xc15f20aa,0x3ecd84e7)}, {LL(0x292edd2c,0xf1090635),LL(0x7c3447f6,0x6d439362),LL(0x3eea3fdf,0x51b9a0a9),LL(0x9e57e450,0x68e0d1f8)}}, {{LL(0x7380931e,0x25d249d5),LL(0x2011a45b,0x87f03fad),LL(0xefde1ca3,0x89df0324),LL(0x9a9b4330,0x52ae43cd)}, {LL(0xa1867c1b,0xfe48bc64),LL(0x9866920e,0xdd874f66),LL(0xfcf50251,0x6942a7e4),LL(0x9c5f6298,0xf5c10048)}}, {{LL(0x00973d66,0x305183eb),LL(0x95baf07c,0x1ce66760),LL(0x74822e13,0x74c9d971),LL(0x76b5e6ef,0x2ccd7fbb)}, {LL(0xa3e1ca18,0x51688b49),LL(0xa603f2f1,0x1beb5bbb),LL(0x962534b6,0x09a231d1),LL(0xafa92f75,0x70417ce1)}}, {{LL(0xe154bc00,0xb86b6d82),LL(0x895483e5,0x5a0b19e8),LL(0xa0ff1e44,0xb15f6c05),LL(0xfdd8615d,0x2938b88a)}, {LL(0x971615c3,0x81800a05),LL(0xc03d2039,0x6be6d56b),LL(0xc476ce64,0xff3e57d2),LL(0x6f583ee8,0x5b509b7b)}}, {{LL(0x7c1f5d3b,0x1d92c36c),LL(0xe11df757,0x1e60b19b),LL(0xe37e36f6,0x20261501),LL(0x29bc86e3,0xb68a9aaa)}, {LL(0xf61d23ca,0xfba81eaa),LL(0xd5adaa18,0x63440834),LL(0xa5f93bb8,0xa80d76ed),LL(0x5a728480,0x3264283d)}}, {{LL(0xe4b8c48e,0xd6171111),LL(0xde557cca,0x3ee227a1),LL(0x3cb59841,0x2bebc09a),LL(0x99bf6205,0x2f8047fe)}, {LL(0x4c43845f,0xb78b243e),LL(0x46d3b5e0,0x484ac183),LL(0x0314524d,0xa07be476),LL(0x1ab4c447,0xc0a3aa35)}}, {{LL(0x9c341f84,0x2f302d58),LL(0x84f130ba,0x264911a7),LL(0x3ee64343,0x30bed408),LL(0x5dc5868a,0xd7d6e92d)}, {LL(0x80adb3fb,0x92074568),LL(0xa133123e,0x005ab33c),LL(0x42e1da50,0x105119fd),LL(0xb7f6b1e8,0x6987117d)}}, {{LL(0xc2bccb7a,0xa2315af3),LL(0x8672c98a,0x95ddd3ee),LL(0x5f48f607,0xa9032645),LL(0xc5273603,0x76861e62)}, {LL(0x88817217,0x71aaa35f),LL(0x2892afac,0x57e95b6c),LL(0x9e84c791,0xf65e909b),LL(0xaa52f3b1,0x257bcc2d)}}, {{LL(0x865c665a,0xd5f6110a),LL(0x30c08b4c,0xddc3afe1),LL(0xefec26fc,0x4df3d04a),LL(0xb035af5d,0xf229bddf)}, {LL(0xd191b439,0x364913cf),LL(0x5a7fa8a4,0xf41b8f6d),LL(0x6f6c1219,0x677cc51b),LL(0x148b7f64,0x593afe4a)}}, {{LL(0x0d038ad4,0x80ffa5ae),LL(0x36256c8f,0xf44d3df3),LL(0xbc978dce,0x0a3077c8),LL(0x745b8317,0xf3d9b4b0)}, {LL(0xb6b1852c,0x8bbf4484),LL(0x0e78ff07,0x0cd02ed4),LL(0x49c24238,0x91cb827e),LL(0xdaa3cb55,0x58adaee5)}}, }, /* digit=1 base_pwr=2^7 */ { {{LL(0x033fc12a,0x07e6ce4d),LL(0x4886f316,0xba4f98a1),LL(0xe66f3f11,0xb24b38f3),LL(0x5ea4bde3,0xe3f6205a)}, {LL(0xa77b998f,0x00705387),LL(0x9549f3b1,0x2c9b4457),LL(0x533a61d6,0xdef6625b),LL(0x7e4f781a,0x4eda7e2a)}}, {{LL(0xfd120134,0xe9730aaa),LL(0xc057309c,0xb22b9089),LL(0x84726ce7,0x98e79565),LL(0xd635a584,0x0e1431a0)}, {LL(0xe834ffa6,0xbd387023),LL(0x036ab1ae,0x64198ddf),LL(0x9124b684,0x46e5ebb1),LL(0x233b3c6d,0xa316fa44)}}, {{LL(0x84782513,0xec2a9325),LL(0x2903d20b,0xd67c8ab7),LL(0x157f9aee,0x6b65b262),LL(0x69f964a2,0x547be60c)}, {LL(0xee0419db,0x001bf327),LL(0xf20c7005,0x92fa0800),LL(0xcdc1ccda,0x1e11e745),LL(0xe471f822,0xa785ec10)}}, {{LL(0xa1371aa4,0xbc970210),LL(0x54b5424e,0xaff481a0),LL(0x0e64269b,0xbcdf91fd),LL(0xb02fc7cf,0x18bb37bb)}, {LL(0x6f69d439,0xd99edd79),LL(0x169514b2,0x4e27a58f),LL(0x66e19ae4,0x80eca1ca),LL(0x0788696d,0x0470e965)}}, {{LL(0x8c9d34f6,0xa6b1992f),LL(0xa5ed969e,0xaf062ffe),LL(0x3a6d7ae2,0xbca2580d),LL(0xc8999158,0xf30cd9e6)}, {LL(0x49d1ab0d,0x93e57897),LL(0x30214280,0xcfa3aa4d),LL(0x0a814831,0x0ca8b4fd),LL(0x0b10097c,0xdad179db)}}, {{LL(0x3dfdc228,0x63778bfc),LL(0xb9648a36,0xc0bae0ad),LL(0x015a99b5,0xda8cb8ab),LL(0x8366b58a,0xb045cccb)}, {LL(0x4164cebd,0x74ef8ef4),LL(0xc5e00e5f,0x41e71fc8),LL(0x4479468e,0x753cf906),LL(0x332ea72d,0x78b5223f)}}, {{LL(0xddebafa2,0x8fc3e370),LL(0x351f9f04,0x15ffcce0),LL(0x45b0efdc,0x3fbd5f5c),LL(0x0fe3b460,0xb8216623)}, {LL(0x533c7db6,0xe8322fbd),LL(0x00a243ff,0xf3866d15),LL(0xa0e5aaea,0xf1194ae2),LL(0xb9287b3d,0x3e93eb01)}}, {{LL(0x5876d6e8,0x528a9e2f),LL(0xd2b622d7,0x93c48f85),LL(0x3e5411d7,0x88d9eac8),LL(0x00a70e91,0xb7e4a6ba)}, {LL(0xf1c43b2e,0xaf18e5ba),LL(0xa2f347de,0x46578c7e),LL(0xf009638f,0x19ca736d),LL(0xbd1acd29,0xa6563f1e)}}, {{LL(0x2f4126e7,0xdf9bcd3a),LL(0xd62efebd,0xecc22d13),LL(0x10943242,0xd9b29b4b),LL(0x670136f9,0x499ffa74)}, {LL(0x2b889952,0xa2a9ad2c),LL(0xfd132dad,0x945f306e),LL(0x15cebfd7,0xfd05b884),LL(0xc7a5627f,0x653e70af)}}, {{LL(0x577dae35,0xfefc54b5),LL(0xaac3a655,0x9d2f0546),LL(0xfac31d00,0xb96bd298),LL(0xee69563d,0x3328a51c)}, {LL(0x43195f4e,0x5e19098e),LL(0xa998010b,0x657f4ba5),LL(0x4047ccb6,0x45f29a84),LL(0x6e423da6,0x833a5443)}}, {{LL(0xca33f42b,0x97e480c6),LL(0x06e52a05,0x20a51033),LL(0x0a9be572,0x85e87255),LL(0xb988b582,0xe8bc857a)}, {LL(0xc183c500,0x782495e8),LL(0xfee0ae2f,0xf33a87fd),LL(0xc64d1dec,0xf069fe20),LL(0xf4b08816,0x0b6dd98a)}}, {{LL(0x99229a90,0x6e6cf298),LL(0x1d71d532,0xa6840bc8),LL(0x71e3a8b7,0x803e5407),LL(0x6afd9a0e,0xd5611ee4)}, {LL(0xbbbefa73,0xd739ca0e),LL(0xc5ec48b7,0x6082dbab),LL(0xbbdea0ec,0xa0ab10df),LL(0xf1633e03,0xb1b7ebe4)}}, {{LL(0x7be26441,0xfa752496),LL(0x0ef683e6,0xf52cb1b6),LL(0x39dd611d,0x1c96401f),LL(0x7bb19083,0x09c5a35b)}, {LL(0x00a5d5a1,0xa2f002b8),LL(0xacf4e8ed,0x4e300ddd),LL(0xb4cc58c6,0x0d26b600),LL(0x50062651,0x5a53863a)}}, {{LL(0xad1cac22,0x62e64475),LL(0xc7e11395,0x2008653e),LL(0xd9479c4a,0xa875ad01),LL(0x804b30d1,0x3e6cf633)}, {LL(0xb6b06e46,0x58b3ef6e),LL(0xf7b8410b,0x74c45dbe),LL(0xc278458d,0x02675759),LL(0xacd30bd1,0xb2ef4956)}}, {{LL(0x339aae8d,0x1a4a5773),LL(0x0c0fe175,0xa775b952),LL(0x5d5d5ac1,0x7b39ac1b),LL(0x11a511b6,0x3f183d49)}, {LL(0x045ac045,0x9524e286),LL(0x4934c52f,0x0498d296),LL(0x9b636528,0x1fec5474),LL(0xc3e9b84b,0xec6f7a37)}}, {{LL(0x12ee579d,0x870b12dd),LL(0x06dd62d6,0x2a9a12ab),LL(0x071d7582,0xbcd52599),LL(0xa869c457,0x7a36193a)}, {LL(0xe976ae5b,0xd29e6592),LL(0xadfecd58,0xe82c8712),LL(0xf714686d,0xbc83a440),LL(0x0c21e3ba,0xfe19344a)}}, {{LL(0xd7a191ae,0x2a32c989),LL(0x4e58caca,0x00a25163),LL(0xe4a11597,0x2c6501b8),LL(0x7f1891e6,0xb3e45d09)}, {LL(0x659fd516,0xb7f532b1),LL(0xa7002930,0x99cf64de),LL(0xf2cd2d4d,0x56357ed4),LL(0x3447951f,0xa94cf5c5)}}, {{LL(0x76a164be,0x26c7f244),LL(0xa72e974c,0xbd83e20b),LL(0xda31de06,0x64e9c241),LL(0x1cdb203d,0x022bc0f0)}, {LL(0x55c0601f,0x5eec4fcb),LL(0xb168a484,0xa1504f91),LL(0x1243026d,0xb9cf98b1),LL(0xfb3e5a1c,0x6a009deb)}}, {{LL(0x60657650,0xf1df3752),LL(0xcb1b8d9e,0xa5bbd8f5),LL(0x81b6af13,0x9e0d9447),LL(0x624cb828,0x8572cecf)}, {LL(0xd003617a,0x28319d57),LL(0x996fde09,0x175c4766),LL(0x04878e13,0x168514b2),LL(0xec83a771,0x58a541d7)}}, {{LL(0x29fb000f,0xafdaad3b),LL(0xc20f56f5,0x1977a8de),LL(0xc5b7ba77,0x450faf6f),LL(0xe5954518,0x93253964)}, {LL(0x644c3385,0x11ee0f31),LL(0xa8a57bad,0x6c24de9d),LL(0x5533a7ba,0xe8ff408c),LL(0xeace56fa,0x660a74d9)}}, {{LL(0x8cc2a866,0xb4b2543b),LL(0xeffc0cbf,0x69f23f18),LL(0x5308b9b1,0x0db4682a),LL(0x17037e08,0xce7fac53)}, {LL(0x0a885b01,0xf02098c4),LL(0xb2e4eb6e,0xd375c03d),LL(0x70d4b81b,0xb6d4f6c1),LL(0x7ce5f297,0xa2b5e9cd)}}, {{LL(0xb8a233c3,0x787229cc),LL(0x3419867f,0x44ef5dd8),LL(0x79d3d8dc,0x00316d22),LL(0x90bb1410,0xdcf32003)}, {LL(0x835d2264,0x62ad0125),LL(0x0ed6605c,0x768c8658),LL(0xfc44e760,0xa31abf17),LL(0xbb22e570,0xc91848ac)}}, {{LL(0xb16c805f,0xad1882f5),LL(0x7ccf9e9a,0xb74cc0ed),LL(0x7b122dd7,0x9635af23),LL(0x5c3cd11b,0x48a20903)}, {LL(0x34c1eb54,0xa24820b6),LL(0x5284dcb3,0x31a3c330),LL(0x069c2ee4,0xd966cf59),LL(0xb3ff9335,0xa74eec6f)}}, {{LL(0x4620e739,0xf44eeb99),LL(0xf4159a9a,0x7663a596),LL(0xb4b745b1,0x79c54f42),LL(0x59db9482,0xa8d34937)}, {LL(0x579501df,0x35fad92a),LL(0x289d7c2b,0x1d81bbe3),LL(0xddf3d371,0x1d60a274),LL(0x46df1233,0xf08e23e5)}}, {{LL(0xf3a95f04,0x4bc4c079),LL(0xa8626015,0x0b43e660),LL(0x246ae3ac,0xedb31526),LL(0x41247209,0xa8536eb6)}, {LL(0xfdfacc62,0x6893a7df),LL(0xc557777b,0xf3de226f),LL(0x0d7f4265,0xa68c8d8c),LL(0x15c685e3,0x55a628eb)}}, {{LL(0x5ecec6ee,0x8cad8f87),LL(0x2a06c242,0x4aefda2d),LL(0x57f00a7d,0x46a21033),LL(0x7ed125cf,0x91910c3a)}, {LL(0x541165d2,0x0b7f0e4a),LL(0x553eeec1,0x15ed1b93),LL(0xd24e020b,0xadf5b4db),LL(0xa7493b8b,0xf05307a3)}}, {{LL(0x62070042,0x725548dc),LL(0xc274916a,0x74d71526),LL(0x6f098d01,0x3269851e),LL(0xf9ec928c,0xb2e01cb7)}, {LL(0x2b4368cd,0x96c2d922),LL(0xa0ec45d1,0x8eb84b03),LL(0x26e5b3ac,0x733ad068),LL(0x93c5a962,0xced3679e)}}, {{LL(0xdd6eb876,0x23c6a22d),LL(0xa343dc3b,0xbd98ad9a),LL(0x56054515,0x61933d03),LL(0xe45cd744,0x4a64b769)}, {LL(0x12586de6,0x617a63f3),LL(0x7976e7d1,0x04984a9f),LL(0xcd2a0a6b,0xb00ba446),LL(0x7d059d46,0x5b64e7f5)}}, {{LL(0x6a4b08e6,0x8801ce04),LL(0xb13bbe9c,0x66f31460),LL(0x4d87114e,0xb174e887),LL(0xf348e94f,0xb2fee192)}, {LL(0x7c822d05,0xfede2283),LL(0x8f82b14a,0x8d50c49c),LL(0x0f5f1b5d,0x21ea4f6e),LL(0xc1818095,0x68627cf0)}}, {{LL(0x8a7b2458,0xc1c0650c),LL(0x8bbc6aff,0x82ab62bb),LL(0x6ce6989d,0x7b3665d7),LL(0x7579e973,0x2ad7991f)}, {LL(0x7e9e8510,0x701287aa),LL(0x0a18da53,0xb296a038),LL(0x2bf00fdc,0xf8c3af86),LL(0xb220dc06,0x55776951)}}, {{LL(0x7d7dd541,0x4e6e4b4f),LL(0xfe5c7431,0x812feac7),LL(0x340297b1,0x6bdfa63e),LL(0x98009910,0xecc11e55)}, {LL(0xb25b98c0,0xee4c6165),LL(0x02c5939c,0x8a07b0d2),LL(0x23147c40,0x9b36c176),LL(0xde2eab3a,0x396054a2)}}, {{LL(0x2c439171,0x1f41010b),LL(0xe8139388,0x3ff85ee6),LL(0x8f077633,0x4ada4c7d),LL(0x824e6023,0x9976011a)}, {LL(0xeaf49f63,0xa2501197),LL(0xd60b0c4c,0xdff2122f),LL(0xbab3df90,0x1a6a3abb),LL(0xb66ffd5f,0x854bbcc6)}}, {{LL(0x728572c1,0x525964a9),LL(0xfadbd14b,0x8a4923a2),LL(0xcd90b61b,0x03830df9),LL(0x79c2afe9,0xcdb00f4a)}, {LL(0xa6c3f13d,0xff2f84bb),LL(0x5c0de4dd,0xdee45c30),LL(0xfba2e933,0x3e1dd748),LL(0x7c51124c,0xe9dcc690)}}, {{LL(0x28e11f62,0x725177af),LL(0x8a64fdf5,0xc8e120a1),LL(0xf24fb357,0x82ab73df),LL(0x44724879,0x2d5d1618)}, {LL(0x96c66b86,0x09627e26),LL(0xc81d38c1,0x1d547cae),LL(0xd0f76658,0xbe8991a4),LL(0xcf11a976,0xf1508662)}}, {{LL(0x3be3e582,0xa5dafebd),LL(0x07399295,0xd9f545ba),LL(0x676f9598,0xd9f564a4),LL(0x9294431e,0xec00bddf)}, {LL(0xc1fdc758,0xc1971113),LL(0x69a001de,0xe32f572f),LL(0xb907f044,0x048d7776),LL(0x5ca10e67,0x4a474e6e)}}, {{LL(0x3039a4b7,0x6476dd40),LL(0x018ee2b8,0x85de9baa),LL(0xfd7365f2,0x0c945aeb),LL(0x96c7267e,0x2b47dc0d)}, {LL(0x0410de25,0xb12b48a7),LL(0x177242c1,0x3ba7a11a),LL(0x6504ff87,0x44e6cee7),LL(0x9d19f26c,0xb2605ff6)}}, {{LL(0x50fb1b6b,0xa56bb589),LL(0x71d2fb53,0x98dc1180),LL(0xa1b78e04,0xa4fdc6f8),LL(0x39d9349d,0xbea745b0)}, {LL(0x62d7eb73,0xac474229),LL(0x8b808ac3,0x7b765138),LL(0xd0ca219f,0x882370af),LL(0x9d1c23e8,0x28dcff7b)}}, {{LL(0x3872f0a9,0xc6dc70eb),LL(0xdfb642b1,0xb2f21248),LL(0x65bbdfc9,0x86838f0f),LL(0x40b28364,0x1d04a8b5)}, {LL(0x1e4d8d58,0xd4fa229d),LL(0xfad0a9cd,0x74ee5e20),LL(0x5a40ec4a,0x25a59aae),LL(0x3727d6cd,0x73be91f3)}}, {{LL(0xd63f64eb,0x9c31405e),LL(0x91d2f1c1,0x9943c34c),LL(0x4fcdbf34,0x70ad75d7),LL(0xb239e00d,0xa6ce7145)}, {LL(0xcd04b9e9,0x136bceed),LL(0x44ed7f96,0xb9ebeb8d),LL(0x5d136280,0x068b43a5),LL(0x4c559b6b,0x2e1b6624)}}, {{LL(0x5472d67b,0xe3808e72),LL(0xce74546e,0x73450378),LL(0xea1d58f7,0xc1b1b66e),LL(0xe34c2a7d,0x2b576e4f)}, {LL(0x2f732803,0xc2b1bdf7),LL(0x9f8e48c3,0x37aea390),LL(0x944f1cf3,0x8bbbb61e),LL(0x86c59643,0x5cc7ccaa)}}, {{LL(0x8d5b000a,0xaf4c18e3),LL(0x2b6d561c,0x23b0edd0),LL(0x0d6cbe27,0x11b67ef0),LL(0xb1b50e9d,0x679d789b)}, {LL(0x372c4015,0xda198336),LL(0x65781ea7,0x5da50baf),LL(0x550201ba,0x00b3a6d4),LL(0xecfffc72,0x988b89f7)}}, {{LL(0x25948852,0xf2f08a09),LL(0x406d1a34,0x4036bbb7),LL(0x23d2dd87,0x1cd57f08),LL(0x4704dac3,0x11a4387e)}, {LL(0xc5413b59,0xb8091a7a),LL(0x09b5fa71,0xe58940c6),LL(0x6a75397c,0x70fd5154),LL(0x5c59ff75,0xea544375)}}, {{LL(0xac25bd3a,0x15e5bed3),LL(0x6b17971e,0x1bed3c33),LL(0xbaa96968,0x046fc1cd),LL(0x7090256f,0xda1b010d)}, {LL(0xe6677d20,0xeec55752),LL(0x24c9bb42,0x8eac5d06),LL(0x8f4120e0,0xc2f6270e),LL(0x07748faa,0xd9ae9fff)}}, {{LL(0xe8f7b7af,0x5a1b2634),LL(0x81b1612d,0x1fcd743d),LL(0x3d420398,0x6b065aa2),LL(0x41e06643,0xe758b9c7)}, {LL(0x7f111b3b,0xe1e52b53),LL(0x83498731,0xb9ee0a5d),LL(0xea8154f4,0x49c19631),LL(0xe1c08746,0x8f5a3479)}}, {{LL(0x65dd5561,0xe032d7c1),LL(0x442bef09,0x6c3420fe),LL(0xa64eff47,0x1d390561),LL(0x902763bf,0x0d8fbf07)}, {LL(0xa4bc6856,0x0262f26d),LL(0x9f4f2101,0x7c1b59a7),LL(0x51240642,0x663d9b38),LL(0x77ce53cc,0x39a0b4c2)}}, {{LL(0x61f5e655,0x1c896beb),LL(0x9f4bfd2d,0x75c4c049),LL(0x10111b02,0xb8799a15),LL(0xa4c2fa0e,0xc76f8641)}, {LL(0x185fc036,0xd77ff7fd),LL(0xf5acbd16,0x53212bd6),LL(0x0408cff8,0x4ef7431f),LL(0xfb082c4b,0x45aa9d99)}}, {{LL(0xf0438565,0x22c1fa8e),LL(0x4cb43ab5,0x8e3a2ee3),LL(0x232081d1,0x457df338),LL(0x482ff47b,0xd1293d9b)}, {LL(0x68106365,0x802a300e),LL(0xe51978c9,0xa8f27aa1),LL(0xa6a6a4d3,0x6ca0edda),LL(0x24c9526a,0x4cab1223)}}, {{LL(0x56730245,0x26234b2e),LL(0xe1b54be4,0x9a04c15d),LL(0xee89282b,0x153fb6cf),LL(0xd79d81ad,0x5901ca12)}, {LL(0x7c3c5ffd,0xbe6853d8),LL(0x35e1942a,0x16d3efb5),LL(0x3b56bece,0x3491f207),LL(0x5b818cfd,0x0d75e0c1)}}, {{LL(0x40969df4,0x79a0e319),LL(0x9ae34b31,0x75e4632c),LL(0x68e8df30,0x4a47585c),LL(0x2a495467,0x4a4a40e4)}, {LL(0x2762eae9,0x92b8a6f5),LL(0xc9a3d133,0xa204cd80),LL(0xd1ff23cf,0xa441ecfd),LL(0x4550ee57,0xd06feb58)}}, {{LL(0xdc032002,0xe14ca6a1),LL(0x05505a36,0x9a780e57),LL(0x08cb2b29,0xad93852e),LL(0x008b00c4,0xa54deaab)}, {LL(0xe1042350,0x8cd2c71a),LL(0xa8915596,0x2014b85d),LL(0x97ddd1dc,0x1228b3e4),LL(0x4a3b3ab7,0xa97282ce)}}, {{LL(0x0f1559ad,0xd978cd73),LL(0x86b14d3c,0x2e877fa2),LL(0x3660f189,0x01d3dc94),LL(0x0d2b4ddd,0x90ad950d)}, {LL(0x92245e3e,0xa8d26760),LL(0x4964245d,0xfc1bf8d5),LL(0xac3d97eb,0x31206c72),LL(0xa58c64cb,0x39dfd972)}}, {{LL(0x7efbbd16,0xd631907f),LL(0x174f1fd5,0x4fdc84e2),LL(0x5c277996,0xe81e89b3),LL(0x5f79f1de,0xcb277b4e)}, {LL(0x2ed1962c,0x2eff44b3),LL(0x72883505,0xbe36a640),LL(0x545e69a0,0x14a1fac0),LL(0xd6f658b9,0x76dbbcbd)}}, {{LL(0x78e2e86d,0x0720c584),LL(0xcaeead35,0x52fccffb),LL(0x587fd1b2,0x06f28c72),LL(0x9e48bf69,0xec36a912)}, {LL(0xdaa3cdbd,0x74874436),LL(0xcdc2f2a3,0xb3f7409f),LL(0x1951c078,0x0e50d7fa),LL(0xee8949f0,0xd97ff34e)}}, {{LL(0x742d7b1d,0x00db635e),LL(0x29f0d0f9,0x5c0b280e),LL(0xeabf9b35,0xafa7e616),LL(0x2c8a76e8,0x7341e2c7)}, {LL(0x2e96f198,0x9679e34d),LL(0x90ee26ca,0x8c2661c0),LL(0x67a6516e,0x9c6dab35),LL(0x46b4b34f,0x7c8edc4b)}}, {{LL(0x2afba4fe,0xc502cf2f),LL(0x6776dbf1,0x76847ae0),LL(0xa2c3c83e,0xace02706),LL(0x4601c550,0x0012645f)}, {LL(0xef6189bd,0x1940e14a),LL(0x2cdf5e89,0xba7f615f),LL(0x438a3781,0x698101aa),LL(0xa9e22357,0xf568a45d)}}, {{LL(0x1f913210,0x83af640e),LL(0x8d505edc,0x529a29fd),LL(0xd6b0c85a,0xdf3d3090),LL(0x6897ea43,0x46e23886)}, {LL(0x416577ae,0x97cca980),LL(0x9aa08fc3,0x1f5a96a8),LL(0x56c05c30,0xcb014b33),LL(0x05ec9be4,0x1944765a)}}, {{LL(0xddc4371d,0x2d6789cc),LL(0xf3618fc2,0xd768f5a6),LL(0x3da93c1c,0x77065e11),LL(0x0e27b3eb,0x4ea3fbc3)}, {LL(0x11ba30e9,0x7c1bfba0),LL(0x1036ebe6,0xfc6fba67),LL(0xd3231aed,0x0053a30c),LL(0xee3ac524,0x7f0613d9)}}, {{LL(0x63093df6,0x95ec2fd9),LL(0x7c0eea52,0xfbc63768),LL(0x8b64ea48,0xf767b286),LL(0xf75bc633,0x6959b0ec)}, {LL(0xc9f63154,0x47e34c3b),LL(0xa524bc76,0xd616b19f),LL(0x632ac100,0xefc9bb54),LL(0xb4d96a7d,0xd9abba10)}}, {{LL(0xfe2ad7e8,0x3b7dd91a),LL(0xb4ebf343,0x29134cd7),LL(0x152864fd,0x49d1c305),LL(0x80efc220,0x3afd83d0)}, {LL(0x3f2f0d27,0x3552517e),LL(0xfda48969,0x0a2b5006),LL(0x3c3e8ec9,0x568863ed),LL(0x891edec9,0xd99d5c62)}}, {{LL(0xd1c9d6ee,0xb0ddc129),LL(0x57db23b4,0x373dad74),LL(0xb416c7df,0x7c178b0b),LL(0x4f8a7153,0x77431dac)}, {LL(0x41c1367e,0xf5288888),LL(0xb838c91c,0xf1518939),LL(0x541f3281,0x81e17838),LL(0x65b2bde5,0x70030244)}}, {{LL(0x7350251c,0xdc309424),LL(0x7c811130,0xfac0c6ad),LL(0x6a141269,0x3817aa1a),LL(0xe10b4a6d,0x1aa5a92f)}, {LL(0x34648a96,0x996cca7f),LL(0x4e2a4f52,0x517a25b9),LL(0x38b1547c,0xff95ac42),LL(0xd9b9cd4f,0x01d981b6)}}, {{LL(0x88d60eba,0xcc34d15e),LL(0xa0ea1a51,0x45851bf4),LL(0x82854ee0,0x5d5f9b30),LL(0x176ea156,0x914be21f)}, {LL(0x2a05c368,0xecac86d1),LL(0x73a666a8,0x255cb9c0),LL(0x78c0eec5,0x5e4799d9),LL(0x8fc05a71,0x40ed8989)}}, {{LL(0x8ae03edd,0x54888ac2),LL(0xa83b554b,0xef3e9865),LL(0xb7612fe4,0x47b41822),LL(0x8f76cd2e,0xf6e16fd5)}, {LL(0xa977b5dd,0x091c7b12),LL(0x8f99d4aa,0x7051bf6b),LL(0xfed218fe,0x9f737902),LL(0xb752c612,0xd8112477)}}, {{LL(0x18d13bd3,0xbb45c287),LL(0x23c6dd1a,0xbbf3a894),LL(0x13b9cf87,0xc8171c5e),LL(0x34f5348d,0x2dfc7792)}, {LL(0x985cabd4,0x9b9a662d),LL(0x4d971de0,0x588a6ebc),LL(0x574cba64,0xda9fd894),LL(0x651e6e67,0x7e0f0cca)}}, }, /* digit=2 base_pwr=2^14 */ { {{LL(0x4b8bceb8,0x88ca276c),LL(0x752d1106,0x6d4ec101),LL(0xf834dcbf,0x2ad98063),LL(0xdfff19d0,0x4da81d19)}, {LL(0x3a9828ff,0x4ccc7cd2),LL(0x2e64b332,0xf1e389b0),LL(0x7308b81c,0xe2fb6a6c),LL(0x5bcc0ac6,0xc6df66b2)}}, {{LL(0xe1c58c80,0x5ccb8c75),LL(0x83fcc95a,0x2ba9de04),LL(0xdfccbcf9,0xccdeb0ee),LL(0x70f3d3ad,0x1d667d4f)}, {LL(0x36269820,0xc6aa14a5),LL(0x0fe87940,0x329a308b),LL(0xede5cfb2,0x39869970),LL(0xf601bb2c,0xc33c3068)}}, {{LL(0xa1a8781b,0x3087444a),LL(0x5cff3cbf,0x6cb5b706),LL(0x83082714,0x7673a8e4),LL(0x0842a792,0xc4bce015)}, {LL(0x53e2a531,0xae71a033),LL(0x8b5315f9,0x147b28f8),LL(0x6c5ab37a,0xcc460133),LL(0x540dde16,0xb1dd088b)}}, {{LL(0x11c09289,0xec250455),LL(0x164079c9,0x83042ba7),LL(0x6e3879a2,0x4881640c),LL(0x802452ee,0x77c5babc)}, {LL(0x7088f360,0x7a7759a6),LL(0xb74be7e9,0x02da352c),LL(0xe0338289,0x15800cdb),LL(0x501688c6,0xad69f7c9)}}, {{LL(0x57ae1213,0xb7d35063),LL(0x97024ecd,0xd536753a),LL(0x24938196,0x9d680716),LL(0x44ed6d4e,0xac1bee4c)}, {LL(0x33e95503,0x6dd9c9bf),LL(0x88fc1c3d,0x5ee9f1fd),LL(0x21654473,0x4a701ff4),LL(0xbd2ffe36,0x9a316450)}}, {{LL(0x103b5fa2,0xe9130a63),LL(0x8eee983b,0xe97f7120),LL(0xe8749cba,0x54b7f85b),LL(0xbb1bca55,0x69976910)}, {LL(0xf4e621d3,0x9ec4034f),LL(0x695e17da,0xaad567ed),LL(0xcedb2ea8,0x7647f054),LL(0x09fc7433,0xf85f944c)}}, {{LL(0xb95eeddd,0x30af23b3),LL(0x89985f3d,0xfd1d565a),LL(0x4c254738,0xfbb53173),LL(0x171170a4,0xb07ba56a)}, {LL(0x294d55d1,0x5069882c),LL(0x792694c1,0xae0385c4),LL(0x11225dc6,0x0a0c7927),LL(0xe22867c9,0xadcc5f08)}}, {{LL(0xaee03999,0x164ac67f),LL(0x79ff7f91,0x4de174d3),LL(0x548da6ea,0x063e4943),LL(0xdb7ccdf7,0x5264880b)}, {LL(0x49b992cc,0x4a18f34b),LL(0x14065870,0xe16b6f4d),LL(0x4cdb0e21,0xd32479ac),LL(0x162bc9f8,0xce8151f6)}}, {{LL(0xe8f78545,0x0f8d9a2f),LL(0x3145b086,0x091643db),LL(0x23a1bcc9,0x5915a582),LL(0x8a280fc7,0x97348efd)}, {LL(0x65eccf5d,0x3f9d6236),LL(0x01ac8146,0xd1a34937),LL(0x8ad0d5c1,0x1b8e5128),LL(0xd581dd11,0x5cbcc9ef)}}, {{LL(0xed059f1d,0x947ceaff),LL(0x7460a186,0xf5754d03),LL(0x0164ff7b,0x37698fa6),LL(0x35805339,0x630900d2)}, {LL(0xeddd6bbc,0xe467a6be),LL(0x5e36b12e,0xc53bffec),LL(0xf831fc7d,0x06dfd3f9),LL(0xdaef86ac,0xd995fcc4)}}, {{LL(0x32d5b2e3,0x7d148468),LL(0x6335f566,0x7796b94c),LL(0x6769b8bd,0x693983d6),LL(0xed5244fa,0xff0306aa)}, {LL(0x89b8e801,0x2e90d41a),LL(0x39e732f3,0x1af09d86),LL(0x320ccb1d,0x96d14e1f),LL(0xc05dcece,0xbaf21c6f)}}, {{LL(0xc216cf37,0x8ae82a1c),LL(0x773828bf,0xac437f45),LL(0x9d51a85b,0x8c12ff18),LL(0x34c16578,0xfeb563be)}, {LL(0xc6706966,0x9d9353b6),LL(0x0cda8733,0xcdc6eb5a),LL(0x3e4953db,0x033c186e),LL(0xb2e37f7c,0x2ba46a66)}}, {{LL(0xb9f3ee06,0xb32115e2),LL(0xdd6346a9,0x1bc12cec),LL(0x321242fe,0x6b9c2142),LL(0x5c68ea06,0xcf9b9bb3)}, {LL(0x920d49bc,0x7fe554ac),LL(0x37aedebb,0x90b3a9b4),LL(0x7695af86,0xacb181e0),LL(0xfd567fea,0xd1c99c55)}}, {{LL(0xfccf76eb,0xb7c18083),LL(0xf93113a3,0xc693bdbb),LL(0x66e03205,0x215ff05d),LL(0xf76d2a12,0x4424aaea)}, {LL(0xe7f30891,0xb23f2782),LL(0x062db479,0xad814d5e),LL(0x4aea78c3,0x347ec1d0),LL(0x6a2332f2,0x3d0f0a7e)}}, {{LL(0x8ad9e323,0x02ecefa6),LL(0x0d45e0c9,0x16c81248),LL(0x2757306c,0xd4b6253d),LL(0x81e42d04,0xe90203a3)}, {LL(0xc13782f0,0xbcef10fb),LL(0x156267d4,0x823efe5d),LL(0xfddb0092,0x18add11a),LL(0xb104561a,0x27068a29)}}, {{LL(0xda0abf3e,0x7eb7f516),LL(0x61b3381f,0x3c92ac94),LL(0xd3418870,0xbad7320e),LL(0x07dbe066,0xbab7a126)}, {LL(0x2def303f,0xe7ce59be),LL(0x2d1e0c9f,0x0bf1f237),LL(0x38f418dc,0x12c18d1e),LL(0xb85bb676,0x7fcc5e3e)}}, {{LL(0x1b038ac6,0x0bcf25ad),LL(0xddf1becb,0x35388760),LL(0x8a1ad137,0x5734bf37),LL(0xb7645056,0x92f3a250)}, {LL(0x718a5ace,0x6ed926a4),LL(0xb967f1cf,0x8e63f0a2),LL(0xd835fe33,0x6d9cccc9),LL(0x31f82e18,0xb1b5efee)}}, {{LL(0x24f2c6b1,0x997aa2a4),LL(0x9e536a91,0xde87114f),LL(0x0f819ec8,0x01938bd2),LL(0xef772a43,0x012e9031)}, {LL(0x77aa9256,0x1578eb4c),LL(0x61a0c8ed,0x052b4088),LL(0x6ab5a380,0x1153a330),LL(0x132f5675,0xa3e7f085)}}, {{LL(0x909b8a41,0x5e946e00),LL(0x16a3c156,0x55f7d231),LL(0x8ac8f8e3,0xcd952464),LL(0xcd8d67f7,0x7c5184d4)}, {LL(0x39ef93a7,0xb3468964),LL(0x4e9058c8,0xf4aa0b7e),LL(0x4b7c713f,0xa409403e),LL(0x41a83e50,0x9d55e33c)}}, {{LL(0x7e1754b8,0x9efee704),LL(0xb1c0027b,0x54085471),LL(0x45af4e6d,0xc5e7a6fa),LL(0x30048569,0xb4d3cd58)}, {LL(0xf3ae8e79,0xd2c20014),LL(0x849f3f23,0xd0b6af13),LL(0x17982a8c,0x3a1db915),LL(0xf9ffcf90,0xea3c8099)}}, {{LL(0x7bada472,0x25d9eb82),LL(0x09afd498,0xff84d98c),LL(0x56ff21f4,0x5e2c1ffe),LL(0x2f2f3a94,0xafd07201)}, {LL(0xcdb673bc,0xb0227fe6),LL(0xfe8d7326,0x58fc0e7e),LL(0x191bfd4d,0xb988d3eb),LL(0x2474d8b6,0x82499093)}}, {{LL(0x68caff21,0xd1ef53cb),LL(0x5074160a,0x3cff018c),LL(0x98f982fc,0x609a4688),LL(0x562a099e,0xee5caaac)}, {LL(0xf8c6cfd7,0xf650365b),LL(0x9cbc10ee,0x2652aa23),LL(0x6ab86f4e,0x904fd66e),LL(0x2d82f3d8,0x6a25bbc3)}}, {{LL(0x19c7a275,0xd3e6ecad),LL(0x3604b2dd,0x05ed0451),LL(0x00c71863,0xdd1d87e2),LL(0x8cd23356,0xd9fc8793)}, {LL(0x0036b81f,0x3337f8ba),LL(0xb5300622,0x63b5a762),LL(0xce8800e3,0x4cf696f1),LL(0x07e3cbc3,0x12cb3261)}}, {{LL(0x0fa12b5b,0x18eac953),LL(0x77d159b5,0x45ccf073),LL(0x6e844a0d,0xa7480444),LL(0xd77d1c18,0x4404e6c6)}, {LL(0xce1af18f,0x003e43a6),LL(0x17fdffcc,0x8a828081),LL(0xcabf3d17,0x91b63c11),LL(0xad26f286,0xa4dedc21)}}, {{LL(0x1a2b1579,0x6bf62b69),LL(0xceeb29ff,0x3b67b87b),LL(0x40d4b996,0x451ffadb),LL(0x080978f8,0x10c6ae50)}, {LL(0x2c242dc5,0x959d47e2),LL(0x5423e158,0xced9e922),LL(0x8d8a68f1,0x9a212d4c),LL(0x3708393f,0xeff3d644)}}, {{LL(0xfbaffded,0x43f51810),LL(0x0f6fd7c3,0x3886ccb4),LL(0x13c31946,0xb939247b),LL(0xaa1fd72a,0xbc1ee613)}, {LL(0x631fd790,0x6d40140a),LL(0xd26b3fd9,0x9382e3ba),LL(0xb3af96c3,0xff414370),LL(0xe0ea9ad6,0x38c813cf)}}, {{LL(0x157594da,0xf8844c3c),LL(0xcac628bd,0x2a7b514f),LL(0xc08c5107,0xc023e4e2),LL(0x3f2722fe,0x6c164496)}, {LL(0xc03a22ad,0x842e1d06),LL(0x37ddae0d,0x5dbc2865),LL(0x0342bc72,0x46dfc88d),LL(0xa4a3c65c,0x873c805c)}}, {{LL(0x60aa5c14,0xd202853b),LL(0x3850cc05,0x1dc35d34),LL(0x0cabccfd,0x8014357e),LL(0xc5a5225a,0x1aa44ce9)}, {LL(0x3a8444b4,0xa3cef920),LL(0xc95384b1,0xcf3f91b3),LL(0xc9e5da54,0x1d625ba1),LL(0xb1d0f46a,0xbf1fba37)}}, {{LL(0xfb3f4885,0xdcef4fad),LL(0x3267f912,0xa49debb2),LL(0x1e121cb8,0x6417d37a),LL(0x533e94c9,0xa6d871fc)}, {LL(0x2e4834fb,0x89f80208),LL(0xb353452f,0x27e83f0f),LL(0xe1f8f322,0xaf009f3c),LL(0x89319fd8,0xa5b77a77)}}, {{LL(0xedf71900,0x0a89e741),LL(0xd514d93f,0xd679b841),LL(0xb0a03702,0x8878577f),LL(0x85a209ae,0xc9607b78)}, {LL(0x59432a28,0xb7bd0616),LL(0xed567145,0x0da060a2),LL(0x1a449f52,0x44e35a7a),LL(0xbbaccc0f,0x9c9a2c82)}}, {{LL(0xd83701f4,0x83abd436),LL(0x4bb9cbe8,0x56e8bfe8),LL(0xc631cd1e,0x5b545cc8),LL(0x955aca7d,0x6d03426f)}, {LL(0x2f8db817,0x049fc9fa),LL(0xdc59675f,0xfcec1799),LL(0x0455f095,0xa00ed392),LL(0xe5096b18,0x6d7cfa5f)}}, {{LL(0xe30ae90b,0x2cda5cae),LL(0xcaabea0d,0x2cc34290),LL(0x41e67856,0x564afcd9),LL(0xcf6ef8b7,0x210c7a09)}, {LL(0xf82a591d,0xc316d352),LL(0xab43d2a1,0x5fe8cc4d),LL(0x8b4e9470,0xd8ebce97),LL(0xba321a07,0x26c78f44)}}, {{LL(0xd75e509c,0xa63f4b34),LL(0xb9a6c63b,0x9122bbc5),LL(0x17942443,0x8bf792a3),LL(0x7f4f70f9,0x95b05d68)}, {LL(0x13b70dc8,0x57d7dee5),LL(0xfc376fdd,0xe84259ed),LL(0xe3e313b4,0xf8c4c4ff),LL(0x13fa8ff1,0xf8e2d3da)}}, {{LL(0xf8e4eede,0x9692c390),LL(0x0e95a902,0x3b514551),LL(0x7360623e,0x45c1670c),LL(0x6abd2a82,0xf7a74f55)}, {LL(0x24e8e721,0x99b16e7e),LL(0x512f1401,0xae52fa2a),LL(0x3f3a09d5,0x46c60e80),LL(0x0750e968,0xf803d1b3)}}, {{LL(0x1791644e,0x17840d2f),LL(0x3b7981e6,0x3e32b3db),LL(0xd3dfae10,0x2d0830a5),LL(0x6cc6dd0d,0x1b28d118)}, {LL(0x78368274,0x944a9889),LL(0x55b1bf81,0x310da94a),LL(0x0d739056,0x503061ec),LL(0xb4d73288,0x1947e940)}}, {{LL(0x0228346f,0x760ee846),LL(0xc5cff077,0x108765b3),LL(0xbeb12160,0x22092b39),LL(0xb63001af,0xa631d553)}, {LL(0x0af3d43a,0x9340cac4),LL(0x60d338a3,0xe6cbfb54),LL(0x7ca3f604,0x2280ff0c),LL(0x3ba738cb,0xaf48f86b)}}, {{LL(0x47d372ff,0x7435dd78),LL(0xf005c006,0xbf9c7149),LL(0x7a8d0e81,0x624084b9),LL(0x4840496c,0x50b578f3)}, {LL(0xb52a4266,0x414ca2c1),LL(0x5535ef0b,0xa3c30275),LL(0xb50f7f47,0xd4b808c1),LL(0x9a199920,0xe6781ae2)}}, {{LL(0x27a91ef8,0x50141234),LL(0x5b77d060,0x2f4f5937),LL(0xc2dcb03d,0x1be8269e),LL(0x9f65043f,0xa293017c)}, {LL(0x8caac401,0x1678dfe0),LL(0x968b1716,0x4942d8ce),LL(0xae36e201,0xa9b55fae),LL(0xd5279632,0xcfe4bde3)}}, {{LL(0x79d637e6,0x6126d744),LL(0xd63b4aad,0x8491f1a8),LL(0x9816b82c,0xdf97b736),LL(0x796408c1,0xafca2c36)}, {LL(0x7a8e8058,0xc17f3f01),LL(0xe74705e2,0xb3335a24),LL(0x46e3e3b0,0xee200023),LL(0x40630e08,0x07bce061)}}, {{LL(0xee8f9dfc,0x46b42c00),LL(0x9e9b7f58,0x3b8e8509),LL(0xd36e8e89,0x83df4b18),LL(0x15d50555,0x09631af5)}, {LL(0xef1ee3f1,0xb7906b77),LL(0x4bd1e17b,0x8272dc83),LL(0x4903faac,0xf160bfd9),LL(0x0dc71e59,0x7fe9e999)}}, {{LL(0xe714187d,0x6ee9b790),LL(0x9d5a656f,0x7391ec2a),LL(0xe10b20f0,0xcbb55ec6),LL(0xec3645d6,0xbba3b57b)}, {LL(0xe18322e8,0x9c3265bc),LL(0x93328c91,0xdb49b0f3),LL(0x49c2bbec,0xa911db72),LL(0x6e5bd229,0xf71b4df3)}}, {{LL(0x7ba27baa,0xdccede33),LL(0x4b712a97,0x1af4476a),LL(0x8a8683ad,0xf0aaabec),LL(0x6fa8e84c,0x138cdac5)}, {LL(0xdc78b1ad,0xd2d50b00),LL(0x696442b9,0x26fc0b72),LL(0x125bf11b,0x12cd5d8b),LL(0xc4f82ca6,0x2a2ce980)}}, {{LL(0x52e00dd3,0x9921c0a6),LL(0xf1d7e1af,0x98e8707a),LL(0xdf03b040,0xaa7aa8b8),LL(0xdff6bd74,0xb3ba8b23)}, {LL(0x31db8c0b,0x2fd0faab),LL(0x2819b732,0x4697e9bf),LL(0x0425b866,0x2dc3a5d0),LL(0xd97816f1,0x4b9e7899)}}, {{LL(0x4c756c70,0x1355c412),LL(0x0fa089af,0x2d4c4eee),LL(0x3b8a01b5,0x4d8425a8),LL(0xa3531d3a,0xcc26b8a9)}, {LL(0x7ebd9eea,0x6eebe11b),LL(0x92c0f858,0xd511a797),LL(0xec49a0c8,0xaa863f01),LL(0xa8242995,0x7fb65625)}}, {{LL(0x3dbc00c3,0x9de9d3f4),LL(0x3f7d61ab,0xb846152f),LL(0xd0d74549,0xc060fdbd),LL(0x7b273702,0xe722aab2)}, {LL(0xd81b6f6e,0x9e54f098),LL(0x9e2fde1f,0x32dbaa5f),LL(0x9ebbc796,0x14cc9995),LL(0x0eb83921,0x4ca6686c)}}, {{LL(0x10a0c0bd,0x6e65d7c6),LL(0xb3c0f6cd,0x1f6930d7),LL(0x4d783d6f,0xe4e0a933),LL(0x70b20ad4,0xc945ee7f)}, {LL(0x034b0265,0x521bd135),LL(0x0fa9be95,0xeb5d96e0),LL(0x357ef592,0x834c28c2),LL(0xb81df99f,0x08ab5b4c)}}, {{LL(0xf464825d,0x6be99d80),LL(0x9a0c1293,0x1cc83719),LL(0xe7e43c6a,0x76616803),LL(0x91cc47ac,0x6fa33715)}, {LL(0xdbfc08b9,0xc3fdb99b),LL(0x68e2b249,0x66e1ef2d),LL(0x64a4a438,0xd3d8ef7f),LL(0xa6f25b00,0x775a70fc)}}, {{LL(0xa0cb5443,0x2444c682),LL(0x4b743ee7,0x264c2662),LL(0xa303eb20,0xd7a1adc4),LL(0xf60a5b98,0x3f14821b)}, {LL(0x1a1d7661,0xa439102d),LL(0x8d8a5a1a,0x47c25a37),LL(0xa34c66a9,0xdf4a48db),LL(0x4c828c73,0xab467364)}}, {{LL(0x3459cc8b,0xd3caad73),LL(0x181b16c2,0x08eeb442),LL(0x70600d33,0x3444abbb),LL(0xcd0f8e70,0xaa2a39c4)}, {LL(0x24836d70,0x5fc6ae8f),LL(0x47d32fd4,0xc119be84),LL(0x0d6000ce,0x2b3f3771),LL(0xe602337a,0x439893a8)}}, {{LL(0xc1e8e564,0x4b75ff6e),LL(0xe451cf42,0x6185413c),LL(0x162c3150,0x0276d3b6),LL(0x3aea9c55,0x844539e0)}, {LL(0x42e9d70b,0xfc629ee6),LL(0x0be610c9,0x4eb9b7e6),LL(0x39ca3d92,0x8c53fda1),LL(0x14c2e9e2,0xd2e4cfa6)}}, {{LL(0xf14b31b2,0x3c1f6895),LL(0xeb951fad,0xad42d951),LL(0xb8f10fc1,0x5b20a169),LL(0x586c61cd,0x284810bd)}, {LL(0xe863d781,0x0c4a89aa),LL(0x9c235d5c,0x2eda4847),LL(0xe6005150,0x8e141950),LL(0x52785efa,0x75716e1b)}}, {{LL(0x8305624e,0x290ced58),LL(0x06650920,0x398956a8),LL(0xdb5bd5b6,0xd057a47b),LL(0xbe9e119c,0xf2d85299)}, {LL(0x7c5fc039,0x4783095c),LL(0x05363915,0x72f7e7cd),LL(0xdf3e2968,0xe46b90d1),LL(0xaaea2e53,0xaadb3dae)}}, {{LL(0x0cc4f426,0xf5d37496),LL(0x59d78369,0xa59bffa8),LL(0xf0a46b04,0x7ad4cc11),LL(0xb8e21b9e,0xcbd63351)}, {LL(0x5653ebbf,0x60d255e6),LL(0x4d6b5843,0x3eaa59af),LL(0x9e1df2e2,0x90049d25),LL(0xe56aa105,0x9a185a6d)}}, {{LL(0x80e3d909,0xbd31c5cf),LL(0xa1f034d1,0x30caad3b),LL(0xd9c7c342,0xaca74fa1),LL(0x9565cf8a,0xac722cfc)}, {LL(0x5b42e582,0x8b172ce6),LL(0x9b0607b2,0x9e99e4e5),LL(0x9446ca45,0x284eb579),LL(0xc57c9feb,0x6c5464ba)}}, {{LL(0xe511bc3b,0x1437fc95),LL(0x834d0889,0x22d7bc16),LL(0xc5071c43,0x62e545b2),LL(0x8cb4acd6,0x4c644d48)}, {LL(0x68246492,0xd9efbe50),LL(0xcbd8ad0e,0xc9d169e7),LL(0x798ae01f,0xcb7365dc),LL(0x6d0dea3a,0x5783f98f)}}, {{LL(0xec454423,0x9b4a7e38),LL(0x96ff4c8c,0x27405d08),LL(0x0c462f7c,0x9769f097),LL(0x7dc946aa,0xcbda5412)}, {LL(0xe7dd5146,0xdacb510f),LL(0x30507b37,0x9c9a0d39),LL(0x05ded0ac,0xa605730b),LL(0x6c6c7b5b,0x7e683472)}}, {{LL(0x7c952984,0xb378d92c),LL(0x72ae34d6,0xec76370d),LL(0xacda665b,0x1fde0bde),LL(0xb931afc1,0xc8f648f4)}, {LL(0xb960f6ce,0x2b55adb2),LL(0x7336a643,0x71b3bdd4),LL(0x73cc39e7,0xf66e77bf),LL(0x2fa3999a,0xf582c5e8)}}, {{LL(0xaf986d1d,0x30ecd0c7),LL(0x4557dd65,0xa2ae53ed),LL(0x7d618a1d,0x97ebccfb),LL(0x11eed889,0xcbf54149)}, {LL(0xd8f2bdd4,0xdd0ff0e7),LL(0xfa769e74,0x6ac4a9fb),LL(0x93e5abab,0xdfdfc7e9),LL(0xdffc6fcc,0x0c7151c5)}}, {{LL(0x5cbae56c,0x6d75e962),LL(0x96dccb89,0x77fae152),LL(0x6cc0e535,0x275c4946),LL(0x81781318,0xc4a400a9)}, {LL(0x77ba50e6,0x8b9f872c),LL(0xa138eeb4,0x971b6cb3),LL(0x53f552a7,0xa7e7d1f9),LL(0x8447c730,0x360512ce)}}, {{LL(0xc5454439,0xf0c73bbb),LL(0xa3a24b5c,0x7f1b9b18),LL(0x51fa7d6b,0xc5bb48dc),LL(0x8b05a553,0xd264d6ec)}, {LL(0xe9371f83,0x123caaf2),LL(0xb149f564,0xdf5da393),LL(0x853b9bab,0x38e02eb6),LL(0x95bf6647,0xc6aab96e)}}, {{LL(0x3141219b,0x4890be89),LL(0x7883fe8e,0x7afe4c2f),LL(0x59b86241,0xc27bd13c),LL(0xaacebdc9,0x1b9720f5)}, {LL(0xf6b2174c,0xa054e203),LL(0x60f6de8e,0xd4e7b952),LL(0xf4558633,0xcf7b1aea),LL(0xbefa40a6,0x43fc1881)}}, {{LL(0xe23cef63,0x592164dd),LL(0xf7b4aaf2,0xfe57d6e8),LL(0xe8aef9bc,0x38a5e2c9),LL(0x1ac2b10b,0x576bd78c)}, {LL(0x14309d10,0x2357944c),LL(0xed0ed94a,0x9933d7ed),LL(0x0339f299,0xb8792ea3),LL(0x87fd9bd1,0xcfb44322)}}, {{LL(0x92966739,0x864f2fd5),LL(0xd3cfd83e,0x7435ecc5),LL(0xec4249f2,0x8516d277),LL(0xfc158b34,0xaa7e1a8a)}, {LL(0xfbe640a1,0xfc0fc22b),LL(0x91121fec,0xf287767f),LL(0x3f590dcb,0x0ce48273),LL(0xf087c249,0x5e994e2f)}}, {{LL(0x65604726,0x681a38c7),LL(0x247a421e,0x4f8c6ae3),LL(0x1294956e,0x1a51eaa0),LL(0x47c9b324,0x0984b1ef)}, {LL(0x597b7696,0x3749bd0d),LL(0x08e57ee7,0x9d432b78),LL(0x2ba112d2,0x3092afe1),LL(0x16c5a7f5,0x89ccee49)}}, }, /* digit=3 base_pwr=2^21 */ { {{LL(0x54089685,0x355e9d7b),LL(0x40818349,0x9f0ec68f),LL(0x3861b80f,0x4cf4d8cd),LL(0xc1f5fa14,0xcce669fd)}, {LL(0x1788f9da,0xea212509),LL(0xf3ccf239,0x32953613),LL(0x50027f3b,0x1048d092),LL(0x4270fbcb,0xe807b39d)}}, {{LL(0x95e388c3,0x5099dc55),LL(0xea44e3ea,0xd0670ff5),LL(0x61b41f7b,0xd212c993),LL(0xfaf13305,0x4f594af9)}, {LL(0x05c01232,0xbc508bf2),LL(0x39ff08a5,0x76833536),LL(0xb837741a,0xa1cf70bd),LL(0xaaf7bd2a,0xba8e6616)}}, {{LL(0xdef27938,0xde04c343),LL(0x48cee32a,0x3f15ca91),LL(0x9dd142da,0xcb61573b),LL(0x126dd9bc,0xc094eefd)}, {LL(0x136bb4da,0x5d42f1a5),LL(0xdb2f3449,0x75693952),LL(0x5c16795e,0x98017cd6),LL(0x2afb67db,0x9e401530)}}, {{LL(0x9b7c6c75,0x6376749f),LL(0xacbca35d,0x680eacdc),LL(0x5e145b32,0xe87fd5b5),LL(0x36b886af,0xeb20d1ba)}, {LL(0x779b12bb,0xca499055),LL(0x0be39fb7,0x6f290ff2),LL(0xf4a128ce,0x33ad6fe0),LL(0x9b31da81,0xf09e2a40)}}, {{LL(0x12039372,0xb2ed3d70),LL(0x2ff46c13,0xb87e02c4),LL(0xfb27dce2,0x164246c6),LL(0xe6d95811,0xe34ee8f6)}, {LL(0x3ec1fde9,0x66cc601c),LL(0x80ffdd56,0x056b3194),LL(0x9626aa21,0xff009868),LL(0x2d931092,0xc3e4982c)}}, {{LL(0xc3d42729,0xbc0da9c1),LL(0x720df0a0,0x4905da24),LL(0x45f6eadf,0x0e5e1fa0),LL(0x2aab7523,0xc02033f3)}, {LL(0xedde75e1,0x45ba916f),LL(0x75c68e52,0xf43919bd),LL(0x84892e6a,0x00e7c076),LL(0x70dfeb08,0x259f8488)}}, {{LL(0xd8a869a0,0x3bfd5f2c),LL(0x574e7d67,0x1df48669),LL(0xe14cfd3b,0x16d6ed5a),LL(0xfcf78465,0x583aac2c)}, {LL(0x67da2ae9,0x67210e6b),LL(0xcfee511d,0x0b024e70),LL(0x13839a4f,0xf27e122c),LL(0xb79dfa97,0xfa5356c9)}}, {{LL(0xf357999b,0xf0c24783),LL(0x26bfacb3,0x2c21474c),LL(0xd3ddb945,0xe3abed6a),LL(0x6031a5ea,0xbb21b764)}, {LL(0x8afc2a09,0x6db3b68b),LL(0x81306b71,0x1aac2f08),LL(0x852eb6f5,0x882c3371),LL(0xd98e9b6f,0xadfe0c1a)}}, {{LL(0x7edcb9e5,0x0247ee7b),LL(0x1f29918b,0xe29ec013),LL(0x6099b6ce,0x5d1629e6),LL(0xcb534584,0x68587803)}, {LL(0x8ce551d3,0x6ccfeddb),LL(0xf85123a8,0x7ef98b72),LL(0xf9711dcd,0x19af4771),LL(0xfd80e4dd,0x8f67858b)}}, {{LL(0x7d607ee3,0xa4c8c016),LL(0x4015a479,0x15db36d7),LL(0x9d28ea30,0x0cb58eee),LL(0xbecb7b4e,0xb3d469b0)}, {LL(0x6f476e2c,0x811081b9),LL(0x59c78fab,0x264da3aa),LL(0x3cd73147,0xd6e5813d),LL(0xe905362c,0xce9e34a4)}}, {{LL(0xcb3afa55,0xe551ec2e),LL(0x4b05589c,0x2c9bef25),LL(0xbcd083bc,0xd36ddeb7),LL(0xddb54a24,0x1c180b52)}, {LL(0xc0961f32,0xb84220f3),LL(0xfe3ae670,0xa71103fb),LL(0x46902477,0x6a14d319),LL(0x778b8eee,0x516701d2)}}, {{LL(0x4c3166d5,0x1cdb1025),LL(0x3d6fcb6e,0x3a0ba2c2),LL(0xb3820def,0xa218b4af),LL(0xbfe8a8f8,0xda6de958)}, {LL(0x4ceabdfa,0xc2b3c755),LL(0x8d73edcb,0xd3534691),LL(0x0ce17182,0x453b8e63),LL(0x01654263,0x6507a5b0)}}, {{LL(0xd5da0e59,0xb2b8e424),LL(0x61ac4c2e,0x7e599c75),LL(0x41aff49a,0xc64cb4c3),LL(0xea3e378e,0x0e231e63)}, {LL(0xe08edace,0x707cc0e3),LL(0x5410779f,0x18918dd2),LL(0x2eef6bb3,0xcdd57690),LL(0xff758569,0x4c54d7d8)}}, {{LL(0x2c89683c,0x49459204),LL(0x7827e518,0x93596a16),LL(0x2b20c939,0x6198954b),LL(0x8044d3ba,0x6672c94d)}, {LL(0x199b16dd,0x55e95fd3),LL(0x4185999a,0xa8484135),LL(0xfe36e449,0x5e8709c8),LL(0x91401957,0x47470e2e)}}, {{LL(0x0874afce,0x0058bb09),LL(0x606c3e52,0x19fb1d56),LL(0x710903a0,0xe1208b2a),LL(0xd47dfd1c,0xecabc372)}, {LL(0x5e94818f,0xd9daa7f4),LL(0x5dc99882,0x1302ac8f),LL(0xc44d37be,0x7b4c6b15),LL(0x72d19e0d,0x0bcf6d4c)}}, {{LL(0x3fd5a1de,0x1e0bf063),LL(0xa75b5b8c,0x5d05e901),LL(0xcb3c617a,0xbbbdb1ab),LL(0x1aef4706,0x44954a8c)}, {LL(0xff6a6e47,0xbc3ceea3),LL(0x0ded1275,0x6140f421),LL(0x4dabe95f,0xbb4b4c04),LL(0x7135e813,0xc55e87da)}}, {{LL(0xd963dd6b,0x15ad105c),LL(0x666941a3,0x33d18f73),LL(0x5d9253d6,0x860ccabe),LL(0xd16e8b69,0x2af702fd)}, {LL(0x74e525c0,0x7e46aadd),LL(0xaf59f48f,0xd9958a44),LL(0x8e7de482,0xd8ca872f),LL(0xcf7d007d,0xc2270c14)}}, {{LL(0xa200e574,0x87c6204e),LL(0x7b69e79e,0x0ee014cb),LL(0x82b23226,0x176ff378),LL(0x8dbbb2f3,0x802d829d)}, {LL(0xe0a4dc31,0xb902924f),LL(0x5fe522f2,0x1f1a9ec7),LL(0x4da7c04a,0xbcd95d85),LL(0xb1543c0c,0x3a3a2e63)}}, {{LL(0xf3271bf8,0x9e70a3ff),LL(0xd2cd68ad,0xd2522d88),LL(0xa6b727b9,0xb777851b),LL(0x63ff5264,0x58953d6f)}, {LL(0xb65c70d2,0x5e111c22),LL(0xd3a5143f,0xaae73c5b),LL(0x85ef5dc0,0x2daa2bfc),LL(0xea13ded3,0x5e7258d2)}}, {{LL(0x2e3ce423,0x4161127c),LL(0x6b1af415,0x7e35a0a2),LL(0xeed24b7b,0x004483a8),LL(0x9f9d44f1,0x2816180a)}, {LL(0x062829a1,0x214add93),LL(0x225e847c,0x262a0bef),LL(0x5d6c53c4,0x4bb1b1ce),LL(0x91d06e53,0xd02f829a)}}, {{LL(0x784da27c,0xcdc8ba5c),LL(0x161b5836,0x78a6c0d2),LL(0x8373c6a4,0x6bea92c4),LL(0xa881f59a,0x815f1a30)}, {LL(0x227cb8e2,0x699c8642),LL(0x25a2b9d0,0x515d1e2b),LL(0x1787b3e5,0xcb5f1c6c),LL(0x104dddc6,0xc9a10260)}}, {{LL(0x0f3811e5,0x18be4f2a),LL(0x71e727d3,0x8c05d3fc),LL(0xfa707140,0xecae3e5f),LL(0xd275b463,0x4bb05b16)}, {LL(0xb02a5ac8,0x74bad373),LL(0x520344ee,0x7232875a),LL(0x65059d8f,0x32cef98c),LL(0x54e1b11d,0x68e0fdb6)}}, {{LL(0x3f3db43f,0x683424f3),LL(0xabf4a83f,0xf5f0878f),LL(0x4ac2c5c9,0x681350d9),LL(0x47dd3652,0x825e9ecb)}, {LL(0x20713db6,0x420743f0),LL(0xd1b082e5,0x95db7427),LL(0x1affa57d,0xa0e1117f),LL(0xf940f325,0x62c87b5e)}}, {{LL(0x4e1d5d9a,0x6a65fda8),LL(0x345ccdef,0x0c0fe385),LL(0xd6d72c0a,0x19ff360f),LL(0xfb016131,0x1be1e8d7)}, {LL(0x025b45e1,0xe2f27e91),LL(0x05259bf1,0x25bec266),LL(0xe51cc67e,0xd7b8b4e7),LL(0xab80a20e,0x3a839aa5)}}, {{LL(0x9f85320d,0x04a9b695),LL(0x98d669f3,0xb939cd83),LL(0xe6948957,0x24464ced),LL(0xa43928e8,0x463de507)}, {LL(0xf8755845,0x4e1844e7),LL(0x5447e61c,0xc9c71091),LL(0x599d4bd7,0x1798f394),LL(0x1e072c64,0x758f7630)}}, {{LL(0x739b1925,0x83c93728),LL(0xfa8eb048,0x692017d7),LL(0x478d1ee3,0x4a3a2a59),LL(0x022640cd,0xb8e62912)}, {LL(0x8572b8d7,0x4689a4dd),LL(0x8f79da63,0x6281ddfe),LL(0x212a153c,0x788bf9aa),LL(0xb3438da6,0xb67e18f5)}}, {{LL(0x31cebdb8,0x3fbafc51),LL(0xb042bd47,0x7f8ad590),LL(0xe3055004,0xf5d26c88),LL(0x3d7d6f5c,0x7f23a149)}, {LL(0x8758ccc0,0x2fee5428),LL(0xe1b80dfa,0xb08c91b7),LL(0xea0c0a53,0xf2bcc903),LL(0x04e684ff,0xcdf2eae0)}}, {{LL(0xe1d9a693,0x354b2c07),LL(0x97a833a8,0x93b1fa2d),LL(0xe9e5f2b1,0x2dcd22c7),LL(0x18aa3163,0xf040a69c)}, {LL(0x76939874,0x4f9a4b29),LL(0x15e24d44,0x58e5947f),LL(0xb0c2ef6f,0x9b47a945),LL(0xf630e92c,0xc4a15b7d)}}, {{LL(0x7b1d4141,0x8d7a33e7),LL(0x966486bc,0x44dabde9),LL(0xef31dc9d,0x387a6016),LL(0x1462ff61,0x76744b23)}, {LL(0x20cdd726,0x2ad63954),LL(0x0e7803da,0x9cff7e86),LL(0xfd124ed3,0xaf5b8b4a),LL(0x050c1149,0x466dbbbd)}}, {{LL(0x06b296a3,0x68352636),LL(0x7f3fe1ef,0x0ab40080),LL(0x05bf08f8,0x1fc38951),LL(0x633c457f,0x69b54ae4)}, {LL(0x1a206c53,0x2ad428c6),LL(0x8b09b3f9,0xd6725687),LL(0x0bc619c9,0x552d4d0e),LL(0x3113c689,0x0e88b313)}}, {{LL(0xe87a91b4,0xb2483b80),LL(0x0c75377b,0xb9f842d7),LL(0x5a78145e,0x50463f38),LL(0x830817a9,0xf2d3810d)}, {LL(0x39cc886a,0x1819261e),LL(0x8415699b,0x697de51d),LL(0x5cab106e,0x688a874e),LL(0xcb8692ec,0xde48f3bb)}}, {{LL(0x38f4194d,0xffa1de97),LL(0x3b996b63,0x33d2726a),LL(0x0d2053a7,0x787c0ec3),LL(0xeecd5c0c,0x9447e9cb)}, {LL(0x284773c0,0x077f121c),LL(0x815829a1,0x496427e4),LL(0x94def08b,0x4b119786),LL(0x9c15a778,0x9e7b29e6)}}, {{LL(0xfd4a8a47,0xa4d6d2be),LL(0x4333baef,0x4f000a12),LL(0x642c570b,0xc9049d86),LL(0x25e6aa6a,0x9424e8f9)}, {LL(0xe011cfec,0x84de7fe9),LL(0x1e8c83b0,0xf273f956),LL(0xa47a40a6,0x98960835),LL(0x0a13c27b,0xd91a20f1)}}, {{LL(0xed703e13,0xaf08b4ef),LL(0xc9994946,0xefcbcf34),LL(0x2d53b069,0x019e6f38),LL(0x9b160894,0x3d62c3c0)}, {LL(0xadfc8f3b,0xac7ad700),LL(0x0042fce6,0x41cc0cc3),LL(0x21cf742c,0x0228ae75),LL(0xf4c9a1a9,0x56a1152a)}}, {{LL(0xfebd27dc,0x5d8a3321),LL(0x7c525f7f,0x89bce700),LL(0x1c1039ee,0xe8f815a9),LL(0x62e86536,0x9f6db698)}, {LL(0x66fe804d,0x1ea6e7a6),LL(0x261aea16,0x652acc41),LL(0xf9df596b,0xde28e5d8),LL(0x1553a545,0x18f453c1)}}, {{LL(0x84eeb5c8,0xa224f763),LL(0x835ba87e,0x8ac452f5),LL(0xc5f4c054,0x9b2b5939),LL(0x3ac1cdcc,0xb2577943)}, {LL(0x772c60dc,0x1ba2cd0d),LL(0xd7a9bd1c,0x1fa52c43),LL(0x60444f34,0x2efd4f4a),LL(0x2bdcfc9d,0x7d188c05)}}, {{LL(0xe1913711,0x49ef6825),LL(0x600d6c46,0xbca95ded),LL(0xaf8d66d3,0x63916baa),LL(0x2dc837a8,0x04981202)}, {LL(0x0d3ae79d,0xb501e517),LL(0xb4edb859,0x99ff7864),LL(0xaf4ec081,0x5099edee),LL(0x964f4052,0x89574889)}}, {{LL(0x52066d70,0x1690fdb8),LL(0x671f4e7f,0xb403207d),LL(0xd7413111,0x8ebc1d1b),LL(0xb4cfdf14,0x1432d7fe)}, {LL(0x65ad5d0e,0x9277666a),LL(0xa928e194,0xbd5ae578),LL(0xb64962fb,0x2f6c10d5),LL(0x2e794187,0xe3d756c0)}}, {{LL(0xd3e6349c,0xf04fd82a),LL(0xcc7d39b6,0xde602dba),LL(0x044e7deb,0x0886e20a),LL(0xe9ba917e,0x6e30c75f)}, {LL(0x4a322ede,0x763961fc),LL(0x2324bb92,0x6df4a3cb),LL(0x8f2ac967,0x9fe82323),LL(0x2345372a,0x3c372afe)}}, {{LL(0x50b66fec,0xbf7e9c55),LL(0x0c065cfa,0x5db7dd71),LL(0x50d459ea,0x3525e310),LL(0x8122941a,0xad7abe5a)}, {LL(0x122d92fa,0xc7aeba80),LL(0xefcc1c24,0x066c3765),LL(0x8ffd71b1,0xa6d767ca),LL(0x9cc16dbc,0x4a75fab5)}}, {{LL(0xbb58b63d,0x9acf8b89),LL(0x6fc8c090,0x226cdcd3),LL(0xae7fbd0b,0x852965b7),LL(0xb8bfe65f,0x4cadd176)}, {LL(0xcfa2ac11,0x4ccc11d1),LL(0x800319ab,0x8abf7420),LL(0x88bb3ef1,0x24ab82cb),LL(0x524c0ce1,0x4d3db003)}}, {{LL(0x3a431e8c,0x38483641),LL(0x792848ad,0xfc0c04a0),LL(0xa07701b0,0x2fc52bb8),LL(0xf29c72cb,0xdfdced3d)}, {LL(0x5280c2e0,0x677e3d84),LL(0xe98cbec5,0x2dda1451),LL(0xaec26be2,0xba28b181),LL(0x5ddea39b,0x16694717)}}, {{LL(0x4b9aa9b0,0x911ec5f0),LL(0x3594ae7d,0x24b9aaa0),LL(0xc3c136a0,0x0ccfa661),LL(0xb7474319,0x5518964d)}, {LL(0x2175c3dc,0xf0b0427b),LL(0x966b7bad,0x08db4cfc),LL(0x5e888ad1,0x6f61428a),LL(0x57b52d37,0xfaa96176)}}, {{LL(0x10aac879,0xe834013b),LL(0x95a62172,0x73397bb0),LL(0x33a244b2,0x97806839),LL(0xc3bec0d0,0x0ab3806c)}, {LL(0x2a72512d,0x4fc7a859),LL(0x0a4228b9,0x96474939),LL(0x4de4b4a5,0x8e5d79a8),LL(0x05d62667,0x5a60d1b0)}}, {{LL(0x08d90c20,0xd31be21d),LL(0xcc14dbb1,0x3f7ed5f2),LL(0xd7d431c4,0xdc8f58f9),LL(0x82b5c63f,0x714f6dee)}, {LL(0x76d2de93,0x6b285466),LL(0xc39dd98c,0x3c2f5d8f),LL(0xea3760a2,0x9bba0075),LL(0x2411742e,0x75e0389a)}}, {{LL(0x7ffdb955,0x87d6715a),LL(0x9efb199d,0x702108fc),LL(0x6c010f8a,0xf11db1f9),LL(0x7eb6871b,0xf52b1e0f)}, {LL(0x97c3ed9e,0xc49c0dc7),LL(0x77220a50,0x18846f95),LL(0x97afddcb,0xdb2273bc),LL(0xcc469f75,0x5b9a16d6)}}, {{LL(0x3beedaf4,0xee364394),LL(0x528a9239,0x825e01d6),LL(0xffd0f17c,0xb60ba965),LL(0xb888384b,0xc00106b0)}, {LL(0x31751f74,0x6e24322f),LL(0x1821d05a,0xfe4d074c),LL(0xbf072932,0xf2493c73),LL(0x21089f21,0xa797e208)}}, {{LL(0x2988abcd,0xf1b318af),LL(0x8e7da518,0xf887558f),LL(0x97836b57,0xb8b9939c),LL(0xc0a74cf3,0xf793e3b5)}, {LL(0x37684170,0xe191008a),LL(0x05cb453c,0x7708823b),LL(0x361beb2c,0xec221d40),LL(0xeb1b68f4,0x0e5a6cce)}}, {{LL(0x9644e937,0x3dc535f0),LL(0xfda6c1b7,0xf506d720),LL(0xf99437bd,0xc78c0e0b),LL(0xcc9e2b09,0xa920b4d3)}, {LL(0xf089b0e0,0x550965fe),LL(0x0109d910,0xf9813492),LL(0x8c9d5d83,0xd2496f20),LL(0x3e3e661f,0x751b6900)}}, {{LL(0x9e6ac190,0x921edbde),LL(0xf02d0e7a,0x75891359),LL(0x1c4da092,0xdeb0f83b),LL(0x4feb2375,0x7b427915)}, {LL(0x7c3a85c3,0x24637c72),LL(0x3f214ac3,0xbbfabf86),LL(0xae22fbfa,0xe8765740),LL(0x5f14045a,0x3a09fab0)}}, {{LL(0x8190dd41,0x546d574f),LL(0x48b5a39f,0xdfcf0b73),LL(0x74097b2d,0xf26c69de),LL(0x3a7e3e90,0x37aa27ff)}, {LL(0x83bbe3df,0x0942447b),LL(0x9ab378aa,0xe779fe20),LL(0x91e2264f,0xad18ad23),LL(0xaaabd6d1,0xe1dad926)}}, {{LL(0x5db5e5c8,0x9de0aa4f),LL(0xdb67e44e,0x45c3d73e),LL(0x5cd83936,0x440862a1),LL(0xffce9a79,0x9f2b9a88)}, {LL(0x76cc6265,0x63299069),LL(0x7a8830f5,0xf596a67f),LL(0x8d1d8284,0x7051c842),LL(0x3e5561fc,0xa00d05a8)}}, {{LL(0x7a34d5bc,0x15ce42d5),LL(0xb0e37254,0x4d9b3f5f),LL(0x38841ab4,0x26e84094),LL(0x9a8ede27,0xa7afd35d)}, {LL(0x14835fa9,0x4e8bcdb8),LL(0x79493e39,0x85d04ddc),LL(0xdf8f65ae,0xbfa8fa79),LL(0xda6c7c62,0xe31d759a)}}, {{LL(0x7600aea7,0x76f27e70),LL(0xd4d9acf5,0xbec79f15),LL(0x5eae2ff6,0x0f10bd0f),LL(0x7116a0c4,0x96c9eef1)}, {LL(0x0cb6f595,0x30add2cc),LL(0x943efe90,0x0c70b548),LL(0x0a05f4a8,0x2ce8026f),LL(0xb7c53c00,0xaa3da153)}}, {{LL(0x8e385a26,0xcc46bf67),LL(0x99bae0f6,0x64bcf06e),LL(0x035dcb4c,0x49480a36),LL(0xe3cbae58,0x2cc1a299)}, {LL(0xb5480cb2,0x849f8633),LL(0x5607d83e,0x1d8fa56d),LL(0xcea9f22b,0xcc3f0eee),LL(0x1a23f3da,0x7d5ece29)}}, {{LL(0x8ae66f00,0xc6f0a006),LL(0x78d648f0,0x2620157e),LL(0x40d2880f,0xfc717762),LL(0xbe105017,0x2e0e293c)}, {LL(0x854116f4,0xb320f214),LL(0x2d5cd4ec,0x5e4fa700),LL(0xdffc1c55,0x83fa0a23),LL(0xc9a9ca15,0x18fcb8d2)}}, {{LL(0xd0ac70fe,0x9e9baccd),LL(0x27fe06ce,0x8ba02fb7),LL(0x3868fdd4,0x2708804c),LL(0x9ba83df4,0x355eaf0c)}, {LL(0xbe43993a,0x014089ba),LL(0x469cccd6,0xc8b59eda),LL(0xb893a5a7,0x77c94507),LL(0x8e517fd5,0x0dffd39b)}}, {{LL(0x13dbeadf,0x71b6edb7),LL(0xfea2d0cb,0x1617b77f),LL(0x48ff989f,0xf7454736),LL(0xb618bfa3,0x27357890)}, {LL(0xa7181331,0xf08c70ac),LL(0xb8bc036d,0x33b6cfe5),LL(0x7163f883,0x75ed10f9),LL(0x47d1cbbd,0x979875fc)}}, {{LL(0x7ad23938,0x6644b234),LL(0xd82e2bc8,0x0f09e7f1),LL(0x5588a39d,0x1e6c512b),LL(0xce8eae85,0xb44e6694)}, {LL(0xf392a4c7,0x107336e2),LL(0xdbcd7b43,0x2619b284),LL(0xb7f476a5,0x7b7ec516),LL(0x43081af2,0x0de74ef3)}}, {{LL(0xd8d54faf,0x93d08bc6),LL(0xf2ae6c9f,0x88d343a7),LL(0xbc147c27,0x7cdb9003),LL(0x69248562,0xd740b19d)}, {LL(0x464b3b60,0x7f3c48bb),LL(0xc91d92c1,0xfc4cd7e9),LL(0xd7420ac9,0x8172af80),LL(0xb9a50be9,0x66907b77)}}, {{LL(0x9ec8e974,0xed99fea1),LL(0x54f39b1c,0x624a8c94),LL(0xce9798d1,0x9c4d608a),LL(0xa4812277,0x81e1652e)}, {LL(0xf58b7db8,0xa2cf7509),LL(0x745e450e,0xef2cd193),LL(0x9d9da493,0x48ee8431),LL(0xb8ce96fd,0x7b471698)}}, {{LL(0xe7553998,0x14dbaff8),LL(0x822de823,0xb0b14e4a),LL(0x429d7c51,0x11032354),LL(0xd572d20e,0xc1bb3327)}, {LL(0x6a9c189e,0xff473811),LL(0x9c7b3b83,0x7cf2354e),LL(0x7662df92,0x29681ff6),LL(0x51c297d1,0x09296227)}}, {{LL(0x5e3da635,0x1b800b34),LL(0x745116e4,0xb5fd32d2),LL(0x2565abb0,0xdae17a1f),LL(0x1fec80c2,0x4f39d3d7)}, {LL(0x290c2f4b,0xb4a19cc2),LL(0x0b6e5ae0,0x1a1b049e),LL(0x6a823b6b,0x41be6e92),LL(0x969649ce,0x35648873)}}, {{LL(0x2a8ed3d7,0xe85f995e),LL(0x2f319e47,0x9dc712e8),LL(0x536d98a2,0xc4402eff),LL(0x37521e35,0xca61e310)}, {LL(0xc3196672,0xfed39621),LL(0xff17e8a7,0x29e7743f),LL(0x412a7c49,0x47eca488),LL(0x33a2a6da,0xf0114513)}}, }, /* digit=4 base_pwr=2^28 */ { {{LL(0xe6880b5f,0x5675a12a),LL(0xe2606d25,0x9ba1e92c),LL(0xeb3b2125,0xb012facb),LL(0xc37b0099,0x3c50fdfb)}, {LL(0x9ce223e9,0xc9ce461c),LL(0xeefbd8ac,0xcb90bdd6),LL(0xc631ea8e,0xf657e5a4),LL(0x38a83ff6,0x6584520b)}}, {{LL(0x635abcf0,0xd959f317),LL(0x99e17618,0xa516a43f),LL(0xce3bd99b,0xed90ccf2),LL(0xa9fb3290,0x2fc6d460)}, {LL(0x0cde4302,0xb61ebe09),LL(0xf908003b,0x5a3b061f),LL(0xf60f5787,0xf51bb736),LL(0x057efc2f,0x1717f6e9)}}, {{LL(0x1ca260ef,0x565acf93),LL(0xf1811d23,0x7d6e797d),LL(0x783e42c8,0xe63c6920),LL(0x8dcb5158,0xdc9dbce8)}, {LL(0xc8e39022,0x1426dc7a),LL(0x30ebfe47,0xf3037f34),LL(0xf87d6395,0x75aa6845),LL(0x61f53539,0xbf792fd5)}}, {{LL(0x6ddc3d83,0xa8bf2172),LL(0xd88207bb,0xf68deb6e),LL(0xcd03bd7e,0xa8eae2eb),LL(0x951f59a4,0x64c7f57e)}, {LL(0xa1786d57,0x8badb223),LL(0x71182790,0x2e7fda60),LL(0x9a5a9457,0x9dc90e36),LL(0xf4b07e07,0x6eca838b)}}, {{LL(0x03264871,0xad2e235b),LL(0xb8b933de,0xb4c56243),LL(0x91354c8e,0xd9c2bdda),LL(0x6a73fc76,0x97d743ff)}, {LL(0xce88013e,0xbed4109d),LL(0xf3b3bf4f,0xa2428275),LL(0x011e761c,0x900d3560),LL(0xe24fd6c2,0x34925d7d)}}, {{LL(0xa8198235,0x08b966ca),LL(0xed2d764a,0x355d098c),LL(0xa3d63f3a,0xfac27f7c),LL(0xd3edc140,0x3e553f6c)}, {LL(0x11ff4334,0x64d72c7f),LL(0xbc62cb57,0x48735aab),LL(0xeba21082,0xcf064294),LL(0xbb8d96fd,0xc1f9e456)}}, {{LL(0x293cd945,0x1d24bdbc),LL(0xea254e36,0x76985bcb),LL(0x876fb485,0x3df2cb6a),LL(0xcd1f673d,0x0176969f)}, {LL(0x642133a7,0x8b41cacb),LL(0x373880e2,0x31ea88f8),LL(0xb3b1463f,0xccf1ff85),LL(0xaca74a27,0x88fffa15)}}, {{LL(0x167cdd1f,0x9a4b9b92),LL(0xf879b894,0xa9118fc0),LL(0xc55479f5,0xf6e73387),LL(0xc626d292,0xfadf82ed)}, {LL(0x56e80e6a,0xa03bb761),LL(0xf27555d1,0x59a783f9),LL(0x3d087e43,0x027d63b6),LL(0x02fdeded,0x29f9ff32)}}, {{LL(0x371d0ec5,0x88a9173d),LL(0x08c0227a,0x04ac4d0d),LL(0x9c7ec715,0x00213011),LL(0xd9d6b472,0x0d2b7c76)}, {LL(0x5050bdff,0xe678d53a),LL(0x65a5fcd5,0x8f929d57),LL(0x1dc3e712,0x0793920b),LL(0x4b073699,0x9a6a690f)}}, {{LL(0x758bdc9d,0x329d9a81),LL(0x7d867b66,0xebbaadd9),LL(0xe6025f68,0x0d7e6b19),LL(0xc53dce26,0x50184374)}, {LL(0x3ed13916,0x298cb00f),LL(0xf5d45b26,0x835fe31e),LL(0xf5a7fb7a,0x373a9c49),LL(0x34d3d8a8,0x59ed7e23)}}, {{LL(0x3baf6fa3,0x1a8dfe33),LL(0xda53714f,0x926ccce7),LL(0x18ef6fe2,0xda4feaed),LL(0xc3ca5cdd,0xeddaf090)}, {LL(0xbfe06d45,0xc39c2046),LL(0x0d7f549f,0x1d9e889e),LL(0x8d537d0a,0x209ace73),LL(0x0e31e1ce,0x6f182c88)}}, {{LL(0x1b8c82e2,0x865e0761),LL(0xa659f2ab,0xcf11bcb9),LL(0x7c868143,0x1804bbeb),LL(0x453e36eb,0x2fa89a0e)}, {LL(0x2e17bad1,0x42d69d8f),LL(0xdc2ec741,0xe7fcea6f),LL(0x379ceb37,0xe7f19b45),LL(0x49bb35a0,0x84f0bd89)}}, {{LL(0x5264b33d,0xa8a50678),LL(0xab1c9e26,0x8cfae763),LL(0xff9b931a,0x1e837dc3),LL(0x796ac029,0x76164be8)}, {LL(0x1266db27,0x26a8bb2b),LL(0x54822255,0xfba4ab83),LL(0x38524458,0x7a5adcfd),LL(0x44ee212c,0xa056c882)}}, {{LL(0x55018577,0xe8db6fee),LL(0x91955960,0xf71256b6),LL(0x10abe8d8,0xeb1c118e),LL(0xd45a8426,0x984efc9f)}, {LL(0x00f2c6ed,0x4e1b323a),LL(0x331baae2,0x1759a7af),LL(0x2e00ba6c,0xf1587189),LL(0xbb385d39,0xbd8a877e)}}, {{LL(0x57d6c1ae,0x440d1eae),LL(0xa957dc67,0x092abdef),LL(0x74554b3f,0x1065cbc6),LL(0x710566c7,0x67062382)}, {LL(0x6d04ae2b,0xd327679d),LL(0xb0340551,0x11507b00),LL(0xa2f52d80,0x2e571583),LL(0xe8578507,0x673628f4)}}, {{LL(0x0cf4efe5,0xecb8f92d),LL(0x960e2d22,0x88c47214),LL(0x6059f079,0xca9549ef),LL(0x7016da7c,0xd0a3774a)}, {LL(0x1d001cab,0xd51c95f6),LL(0xa3feeec1,0x2d744def),LL(0x0afedf2b,0xb7c20cc2),LL(0x71d144a5,0xbf16c5f1)}}, {{LL(0x3dc0d12e,0x00384727),LL(0xb01cc80f,0xaa95f450),LL(0xa6f8e927,0x19be3106),LL(0x0417ba8b,0x6d6e10aa)}, {LL(0x870e3491,0x149f120c),LL(0x026dde94,0x27380b41),LL(0xf29b04e6,0x97d00840),LL(0x4bf9eb19,0x21d5d7e3)}}, {{LL(0xd5327f05,0xea1daad9),LL(0x9c88c17c,0xf1f45d94),LL(0x3f8ee0ab,0xc5f3dee2),LL(0x75238a56,0x706b777c)}, {LL(0xf834c60b,0xf7aee379),LL(0x13cfe17b,0x5c24dae6),LL(0x8091804b,0x354c82e5),LL(0x102a577b,0x0dec2fdf)}}, {{LL(0x5253f8fc,0xbf3b7030),LL(0xd913c01c,0xe516fa69),LL(0xa105ba64,0x053afef4),LL(0xc89c1e76,0x91a1f36c)}, {LL(0x7e724e18,0x3375865c),LL(0x29327b2b,0x43132144),LL(0x6f7bb24e,0x9cb2fc3b),LL(0x6319e789,0x20a6a16d)}}, {{LL(0x642c467a,0x20bfbd77),LL(0x259d50c8,0x3452bb12),LL(0xec7ffab2,0x0d3ba9c7),LL(0x3560e541,0xbbdb5454)}, {LL(0xd63ba04b,0xab1d6e22),LL(0x7d24f015,0xdf6f11d3),LL(0xf3df15fa,0x7c4d61d2),LL(0x40b3288c,0xd5269f79)}}, {{LL(0x0e7c7b6c,0xf8516b9e),LL(0xc203dac8,0x48750d82),LL(0xa13d3083,0x89845d36),LL(0x280a131a,0xb3db3cfa)}, {LL(0xfbf752e6,0x40045401),LL(0x1432e856,0x0289f97b),LL(0x5fc1aa11,0x41a9f371),LL(0x8d464042,0xe5c1e5a5)}}, {{LL(0x589b71a7,0xfbee2ea2),LL(0x5de7056c,0xdd6ee5bd),LL(0x8fd6b6de,0xcf8a4541),LL(0xb15e33b1,0xb47831dc)}, {LL(0x2064321e,0x126a2169),LL(0x6e517edd,0xa21d2d22),LL(0x5ba5a30b,0x1f8072be),LL(0xc6a24b7d,0x24cca576)}}, {{LL(0x5c282027,0x57eab82f),LL(0x557344b3,0x1620f5e6),LL(0x460b3385,0x59e852e0),LL(0xf050816c,0xc906e3db)}, {LL(0x3eb398e8,0xc031f8cf),LL(0x507ac07f,0x9c25b69b),LL(0x9cf7bdbe,0x652baf2b),LL(0x5ad91107,0x06fedc53)}}, {{LL(0x4c4b12c5,0xa8ca0be2),LL(0x28762d5d,0x633292b6),LL(0x827c0d5e,0xc04983f2),LL(0xc707ef03,0xcb6b867d)}, {LL(0xb9ac1124,0xa7fc0d5b),LL(0xaab7dcaf,0xa5ce085b),LL(0x1cfda998,0xb85e8f1c),LL(0x27822503,0x8208df42)}}, {{LL(0xa8dd6d76,0xeaa82320),LL(0xad36eb73,0x7b2fb4ae),LL(0x97a7b040,0x24d73191),LL(0x4001e02f,0xc3ff64ae)}, {LL(0x88799d94,0xd5d87157),LL(0x93ceb95a,0x559142d0),LL(0x59c3009a,0x798a453c),LL(0x7d6c83a2,0x546b6fab)}}, {{LL(0x5c76029a,0xe263b23a),LL(0x4ac62973,0x85630532),LL(0xecb007ac,0x14ee0643),LL(0x7ca60905,0xf9e06297)}, {LL(0x92f1f170,0x21b2fb23),LL(0x46528ab2,0x31c40918),LL(0x3395cfd2,0x43b53242),LL(0x6d14fb40,0x4042138f)}}, {{LL(0x4464f342,0x80899c8c),LL(0x084be305,0x0f54c993),LL(0xfbf84810,0xfacecac3),LL(0x8ae5244f,0xa6585936)}, {LL(0x9a9f8d4a,0xb467c3c0),LL(0xfd394895,0x3e5f219c),LL(0x9bf85fa8,0x39f0767a),LL(0xd8ee6022,0xd97cc55d)}}, {{LL(0xc83f86c4,0xc480938f),LL(0xe43bfcc6,0x6479b8ef),LL(0x38cabad7,0x8e6f2e22),LL(0x31f8c6aa,0x48e57fdd)}, {LL(0xcfbbdcac,0x66dd6a77),LL(0x50ece329,0xc7d9950b),LL(0x0747a937,0x2e31f205),LL(0xa07acb8a,0xc0f8a7e2)}}, {{LL(0x15eaa686,0x578477bd),LL(0xf2f58b50,0xd72fb935),LL(0xd3a64d22,0xe9fdbc6f),LL(0x492dc89f,0xa3e42674)}, {LL(0xa8fb7d24,0x42410ffd),LL(0x52676ed7,0x08a37dfd),LL(0xcb5d6125,0x4607c41b),LL(0x4001fa42,0x7db48af8)}}, {{LL(0x50cd30f0,0xe2264eb1),LL(0xe215f8d7,0xbb6fe952),LL(0x97e3fe73,0xf3ce2411),LL(0x37f19247,0xe52e2179)}, {LL(0x20c233c1,0x9c7fc8c0),LL(0xb383b101,0x91c7e721),LL(0xa7ac883f,0x1163c472),LL(0x9d3b0f1e,0xbe1c3b3a)}}, {{LL(0xa3536baf,0x07be716f),LL(0x62e9c19a,0x764d9f4e),LL(0x8eaf19f4,0x15af3499),LL(0x38ea0ace,0x987a7c47)}, {LL(0x4a1f0117,0xb03740b8),LL(0xfe098a9f,0x5cd1164f),LL(0xc9d6fee5,0xaf952cef),LL(0x3c0ad28b,0x4e86dcbb)}}, {{LL(0x677b7a8f,0x81125450),LL(0xe69273d2,0xba889fce),LL(0x582c5990,0x4a40a859),LL(0xf48934c3,0x836638b3)}, {LL(0xf3596ba6,0xe964e189),LL(0xde8b0754,0x2f417c0e),LL(0xd5f93f1b,0xd883169f),LL(0xd45bb389,0x0318fe4e)}}, {{LL(0xdb03273e,0xe2c998a1),LL(0x33ec151b,0xc34f544d),LL(0xeb92d963,0xae0456b1),LL(0x9738857f,0xaab61ec4)}, {LL(0xf71d9c39,0x4fb6a34e),LL(0xd816ec44,0xaa9dbd8c),LL(0x5efdf950,0xf6532e37),LL(0x67109c55,0x7151dc44)}}, {{LL(0x3f4e322c,0xb18b586a),LL(0x3553a18b,0x27b30066),LL(0x1ae4cd85,0xbd31ea24),LL(0xa64de69a,0xe8f88f4a)}, {LL(0x609c13bb,0x8c946a97),LL(0x0eebd9f0,0xbf8cc55a),LL(0x7a8892b9,0x446aa2e4),LL(0x65b98c31,0x660c0a55)}}, {{LL(0xd3463522,0x568c56fc),LL(0xeb130aa5,0xfa6bf3a6),LL(0x008dc0da,0x16c1568b),LL(0xfed70a87,0x9c4132cc)}, {LL(0xd497fdff,0x3e983d09),LL(0xf0ebe6b0,0xd7a0e542),LL(0x68b542ca,0x193a07e0),LL(0x07c6ab4f,0x4909776b)}}, {{LL(0x418acd7b,0x55b77ef4),LL(0x47a77d32,0x64ba62d3),LL(0x2d1f562e,0xaec1aa93),LL(0x10dc5999,0x3468725b)}, {LL(0x6ff0d478,0x422851b1),LL(0x8e7dddcc,0x15da8429),LL(0xb8ac5238,0x38567920),LL(0x2e3344d8,0xfd29eb4a)}}, {{LL(0x4fc636b5,0x7b2af70c),LL(0x879e7640,0x242acfc8),LL(0xb5e25c7b,0x88e89786),LL(0x16ec1bfd,0x85576b1b)}, {LL(0x1891e595,0xb31c8253),LL(0xca5608a5,0x14315dfe),LL(0xb0c14fd9,0xb9d61b76),LL(0x734b6cab,0x5d5ad8a3)}}, {{LL(0x44aee005,0xc2ea321d),LL(0x147ed658,0xd68abd2c),LL(0x893db877,0x31152d60),LL(0x281487b6,0x4807ac46)}, {LL(0x65da04b5,0x58ebd15e),LL(0xb2f9d1fd,0xf0f74fd4),LL(0x393c7d91,0x3d04aa65),LL(0x8e7e6a2c,0xb46fb59a)}}, {{LL(0xae1eed5d,0x9236fdf1),LL(0x7810e2be,0x71936f56),LL(0x6d9ff147,0xa1ead7d5),LL(0x149a9b6d,0x32670ed8)}, {LL(0xcb58ea59,0x12772fdd),LL(0x9df52ddb,0xfce260b3),LL(0xccab1e97,0x3221f2fb),LL(0x57762484,0xf8ff7e37)}}, {{LL(0x855512cf,0xb0a31a1c),LL(0xd71d4c4e,0x293a819e),LL(0xcd6a900f,0xc1ebc896),LL(0x9b9e0a4b,0xc727a646)}, {LL(0x0018f29f,0x06124fc0),LL(0x41b7730c,0x67bd8fed),LL(0xc77be72e,0xeeebf0f0),LL(0x474d747a,0x427fe6fe)}}, {{LL(0x932ccbf0,0xa7fb9a4f),LL(0x5f3d489f,0xabb9c85e),LL(0xbdf26442,0xe7e4f956),LL(0x38d17422,0xd014848e)}, {LL(0xd3e9bff6,0xae37d855),LL(0xca5aeb09,0x88fbae1d),LL(0xf025feaa,0x1a8a740b),LL(0xb9475ebb,0xc1a67821)}}, {{LL(0xde2bf8a2,0xb6cb6acc),LL(0x66a0f14e,0x9b2ab1ca),LL(0x83b2ba59,0xcbfbc068),LL(0x68447934,0x336ab62c)}, {LL(0xf19719b8,0xd3a016a9),LL(0x0b5b9d6e,0x819a31bb),LL(0x3e1c6c0b,0x7b24be2b),LL(0x013f6821,0x10834b4a)}}, {{LL(0x86f21d2c,0xe5e5de27),LL(0xe9e35ad5,0x56b46a2d),LL(0xe2111e59,0xfc4e861d),LL(0x6e37ca63,0x7472ce5e)}, {LL(0x27d2210e,0xafab9a71),LL(0x9ff6245a,0x1644a0a6),LL(0x8dbef51f,0xee498acb),LL(0x2e9604d3,0xd4c70da1)}}, {{LL(0x6fecb64c,0xde487364),LL(0xd15fb62f,0xa8fda1fd),LL(0x088de028,0x97e2febe),LL(0xecdce095,0x4a769019)}, {LL(0x50a58ddb,0x4cb6a338),LL(0x17028d36,0x08df59d8),LL(0xb51722b7,0xfe3a80ff),LL(0x963c2383,0xa3cc2fe2)}}, {{LL(0x53cc5341,0x40b2df49),LL(0xa3c4bf2f,0xf3e90d4c),LL(0x20f02731,0x3f25c5ec),LL(0x69065d9a,0xd84f5b5a)}, {LL(0x129921be,0x156d350e),LL(0x1b116922,0xe98787cc),LL(0x39e77b13,0xba5f9b82),LL(0x044449a5,0xee4d79f5)}}, {{LL(0xdd6d852d,0xb54b7388),LL(0xf9ca5fdf,0xf7554c5c),LL(0x51228a81,0x864d1fbf),LL(0x9a80f90b,0x721e1add)}, {LL(0xad0efa62,0x89d4e297),LL(0x6dba9404,0x4e471a87),LL(0x1c1008b0,0x9a38158b),LL(0x95c47ec2,0x3dfe81a7)}}, {{LL(0x28603026,0xcb02ce9b),LL(0x3bd357fc,0xfd3207aa),LL(0xf296f5f2,0xb3807bdd),LL(0x23c2ea7e,0x7895918d)}, {LL(0x88feb3ba,0xdc0eb62f),LL(0xbdd75674,0x024dfd84),LL(0x0a1e0496,0xe5bd3828),LL(0x24c8f30c,0xb8b1cd86)}}, {{LL(0x674d10cf,0xb559e34d),LL(0x9f962ec5,0x6955bb69),LL(0x542af42d,0x8bf1ab6c),LL(0xdfa61256,0x3f2f33fa)}, {LL(0x73d1049e,0x32140195),LL(0xdfd7f39b,0xf5089278),LL(0xb4237be0,0xb42eb51c),LL(0x874d0e57,0xdf747f44)}}, {{LL(0x77b5d475,0xbe64bb22),LL(0x28308634,0x2c3d5ecb),LL(0xcb999c46,0x936a2987),LL(0xe26489ea,0x5a30ddfa)}, {LL(0xc8eabf9c,0x8bfc782e),LL(0x74c8c6e3,0xb9995bb0),LL(0x391f5c5a,0x4f99c7ac),LL(0x5270c4ad,0x67f4092b)}}, {{LL(0xe6e8135e,0x6771a29d),LL(0x6c698cec,0x988dfb2b),LL(0x77812aa1,0x7818600f),LL(0xfd98e1c1,0x04393c83)}, {LL(0x864ef146,0xe448232e),LL(0xa465ab71,0x9b70ecf4),LL(0xb13cc704,0x31df0531),LL(0x16e48426,0x401ae0b3)}}, {{LL(0x7fc514ed,0xa8106630),LL(0xde4b1614,0xda798170),LL(0xc2c684fe,0xde892efc),LL(0x05d64eff,0xd5205bc1)}, {LL(0xe1d59ba5,0x84df4ead),LL(0x89bb2ea7,0x65245ca1),LL(0x64edbf51,0x3de6ca34),LL(0x56bcebf9,0x115296e4)}}, {{LL(0x7fd52a3d,0x0851631f),LL(0x949ad4be,0x9881db71),LL(0x88caf772,0x4b2337dd),LL(0x33ec7979,0x02da59de)}, {LL(0xafe840df,0x2473c620),LL(0xa92ef1d0,0x2965ebff),LL(0x6fcd9651,0x2452854f),LL(0xbac2ed99,0x97092935)}}, {{LL(0x08242246,0xf0743ce7),LL(0x6d1a8439,0x76fdd82c),LL(0x61079258,0x3627c890),LL(0x82b21983,0x312f98f1)}, {LL(0xe9173891,0xd87dceec),LL(0xd7a30e32,0xad16cfe0),LL(0xc9c7efaf,0xc404a1a6),LL(0xd6df357e,0x46e34671)}}, {{LL(0x7a02aa32,0x92fec7c4),LL(0x5a6a7bb9,0x567fef7e),LL(0xa3f97b5d,0x35fd570c),LL(0x4a4b0dfa,0x456bad8c)}, {LL(0xa677f090,0x85a3f42c),LL(0x22a68d53,0x35060bb8),LL(0x53567530,0x1cea9d11),LL(0x8169fbce,0xf2cbc8dd)}}, {{LL(0x86cde794,0xa3e1d52d),LL(0xb3bdf344,0x72a258cb),LL(0x31b8614d,0x2997cd59),LL(0x8164b632,0x31ce2ea4)}, {LL(0x0eba7545,0xe495e9b7),LL(0xbc4403b5,0xaad69130),LL(0x45760d9b,0x37f6389b),LL(0xb871b17d,0x00f4d58d)}}, {{LL(0x4aa359d7,0x91973d4d),LL(0xc8dd0582,0x249f510c),LL(0x7608be27,0xef11ac87),LL(0xd940b1c7,0xce116714)}, {LL(0xfef20037,0xf34881f3),LL(0x98203f4e,0x26222472),LL(0xe9363154,0x4c9e98ed),LL(0x03a8158d,0xa806b3a6)}}, {{LL(0x09d16ce3,0xdd974d66),LL(0x59ae977a,0xe1bcc513),LL(0x218464d6,0x0e6201c7),LL(0x9e35c7af,0x05789811)}, {LL(0x8b33a863,0xb1596f7a),LL(0x42bd8284,0x8fa93aeb),LL(0x46e11559,0xf197c202),LL(0xadd27d86,0x356b9c81)}}, {{LL(0x1695cb70,0x3c4080fd),LL(0x20f20318,0xc10c28cc),LL(0xce1ffab9,0xe9d7ed93),LL(0x4f9de9bd,0xb23976b3)}, {LL(0x6d61a6f2,0x9b1b81dd),LL(0xf6318874,0x7537d729),LL(0x20cee7ab,0xb75022f4),LL(0xaa430952,0x425fddba)}}, {{LL(0x1ccfb3fd,0x54c4306d),LL(0x46a30a37,0xf10a54f1),LL(0x74fd4925,0x2d332a29),LL(0x1438feb2,0x8d2fa921)}, {LL(0xfbb41bd2,0x46a9c6b5),LL(0xd30c65fd,0x87e98550),LL(0x66cd9a20,0xfbcb2ca6),LL(0x91719670,0xc176530e)}}, {{LL(0xcec38056,0xdd4a1a18),LL(0x75544998,0xe6ef1793),LL(0x30583fb6,0xf58f69cf),LL(0xaa76bf2b,0x12197860)}, {LL(0x3bb686fc,0x717813e5),LL(0x0f06c403,0x9beeb1ae),LL(0x2782dc86,0xd83416ee),LL(0xb5500ccc,0x5fc89c01)}}, {{LL(0x8e110ed3,0x063aee25),LL(0x45963073,0x1a87377c),LL(0x5110634f,0x86944f59),LL(0x0ba76459,0x50659ae1)}, {LL(0xde9eb40d,0xa00e48ff),LL(0xfe5b118c,0x49235afa),LL(0xc425ee38,0x81705008),LL(0x2d5f2f92,0x3c01abc8)}}, {{LL(0x6fdf148b,0x4a21bc95),LL(0x0b7e6871,0xea5cc30e),LL(0x11713844,0x90b4abb6),LL(0xf2001af9,0x3b7d734f)}, {LL(0x782b2020,0xfc616b89),LL(0xd8b0e02d,0x68b3935c),LL(0x1cbb2de4,0x54cf5b8c),LL(0xa7c0f7ac,0x42b0432a)}}, {{LL(0xbdffae5e,0xa04e06ef),LL(0xd4b636ee,0x36cac28e),LL(0xc3a98127,0x08a06b2f),LL(0x290c5385,0x1ef0b57b)}, {LL(0x27154c46,0x14e184b8),LL(0x60910b3e,0xa5dd3444),LL(0x3c67a74b,0xd0008ac4),LL(0xefed9fd1,0x2649cba4)}}, {{LL(0xf0c1bb4f,0x26bc537a),LL(0xd06b90f5,0x37f376ff),LL(0xbe7c89cf,0x4d48d994),LL(0x8d572003,0x511c2158)}, {LL(0x088dda1e,0xc26fbac1),LL(0x7ad4934c,0xc3d55189),LL(0x85dcaf7c,0x5233c176),LL(0xa88b473d,0xec3a8a29)}}, }, /* digit=5 base_pwr=2^35 */ { {{LL(0xb1f0c175,0xfd96667a),LL(0x2ab99e7d,0xa256a611),LL(0x05e43f9d,0xff07c1ea),LL(0x7e1c9cd6,0x305700bc)}, {LL(0x2b2887a3,0x3f1e2546),LL(0xc772fd14,0xdd782f49),LL(0x38584057,0x9125f996),LL(0x16a02cf9,0x19fd0396)}}, {{LL(0x4c58174d,0xa8d62bd3),LL(0xa900551f,0x872251d3),LL(0xf12802c3,0x06f5862d),LL(0xdd925555,0x5d93c48a)}, {LL(0xbd6006f8,0xc39b67d5),LL(0xf96ccc67,0xea6f756b),LL(0x543014db,0x140e853e),LL(0xe9de42c0,0x2bdc5674)}}, {{LL(0xe01c073d,0x01dfda7b),LL(0xff9e1234,0x07a6bb65),LL(0x622cee4e,0x2a4f7f18),LL(0x50f0a3a7,0xdf4cead8)}, {LL(0x1b8c2903,0x152b3c8e),LL(0x5f2a89b3,0x9e82e999),LL(0x68ce7a3c,0x0e6cfa7e),LL(0x0ca0464c,0xebb34d90)}}, {{LL(0xeda49f74,0xfa1a58fa),LL(0x0e4545a3,0xddb89957),LL(0xc74c07e4,0xd3576489),LL(0xb59b1008,0x64e4b39e)}, {LL(0xf66b546c,0x3b090340),LL(0xcdeb912f,0x0e0f4013),LL(0x01e55cca,0xbb00b46c),LL(0x99ad0768,0x55b61b34)}}, {{LL(0xe8bbda5b,0xb06b71fc),LL(0xa24b0a63,0x8de64d84),LL(0xb5d4603f,0xb73dc262),LL(0x1965a916,0x5d5fa964)}, {LL(0x3bc98966,0xb48a4053),LL(0x6f564743,0xaa871863),LL(0xe76a6a3e,0x88b00822),LL(0xb38d9e0d,0x58c9e92e)}}, {{LL(0xe989963e,0xc0d22337),LL(0xd3778d5a,0x2c4831ce),LL(0xee8c4178,0xd775c6a5),LL(0x9d0c2894,0xe2391654)}, {LL(0x5d0eb314,0xf7d4fe86),LL(0x8b2290d3,0x42801b8f),LL(0xcdcefa78,0x73e9b332),LL(0x3e877fea,0xc0d169d9)}}, {{LL(0xffee23fa,0x29c8138b),LL(0xfb92e3b8,0xbff98230),LL(0x8fa75007,0x14077ad5),LL(0x88e61b81,0x4d3a6e10)}, {LL(0x3bcf733d,0x218a867d),LL(0x665e37fc,0x20ff6566),LL(0xda5cbf67,0xe39c0581),LL(0x8add8c4c,0x4a6e1d7c)}}, {{LL(0x734a1327,0xcab02370),LL(0x1951afa8,0xa1df7afc),LL(0x42638b8a,0x581cfbaf),LL(0x2130eaa6,0x39db6d2b)}, {LL(0xda2f91a5,0x4bbc805b),LL(0xe569add8,0x3dcb0a7e),LL(0xd721fa7d,0x724ab65a),LL(0xf88f8008,0xa5152b95)}}, {{LL(0x281615ba,0x7fe7f1b9),LL(0x41d5aa0c,0x419d1a53),LL(0x9fb0917e,0xafc556dc),LL(0x616ce893,0xab2a69f3)}, {LL(0xc0861e05,0xfb9a6eb1),LL(0x5eb02b8f,0x0b74ae11),LL(0x3b1e44fe,0xccff0ad5),LL(0x88824f53,0x86dfe0e6)}}, {{LL(0x41177a46,0xedf38dc4),LL(0x7f039a7b,0xd9a955bb),LL(0x4d8ae7c2,0x4f152581),LL(0x4f848819,0x063c9f83)}, {LL(0x841e8783,0x54ea4526),LL(0xaa5f2b32,0xe86a4119),LL(0x19846dcf,0xb7529a3b),LL(0x35689d70,0x91356a07)}}, {{LL(0x8f049ef8,0xbe66f5db),LL(0xc38dd5ed,0x0f5fd99e),LL(0x1b4ae7a7,0x1896d52b),LL(0x480b1ebb,0xf27c45c6)}, {LL(0x3fede5c1,0xd88cff4c),LL(0xda27560b,0x57d902c9),LL(0x52d57deb,0x84aa7f07),LL(0x08bb6028,0x8da4c7c8)}}, {{LL(0x8910763e,0x658f4dea),LL(0x076a0f80,0x6e5fcb48),LL(0xab65f9b9,0x6a5447a4),LL(0xa75bb0c5,0xd7d863d4)}, {LL(0xe87e7916,0x806c34a7),LL(0xcd961e88,0x05391559),LL(0x74fe6aeb,0x5def2d88),LL(0xf9226ca1,0x8ac350b2)}}, {{LL(0x12401813,0xffa8a649),LL(0x5337c55d,0xd6182762),LL(0x3be902e3,0xfce9d7ff),LL(0xea0dd7a5,0xb3b275d1)}, {LL(0x2cb48ac9,0x342620f4),LL(0xa8b38a74,0xc0369384),LL(0xc0695d3a,0x04b0ee6a),LL(0x94c5394d,0x4d025585)}}, {{LL(0x81443d16,0xff9635d0),LL(0xa6cc364b,0x2342cbfa),LL(0x25bf8438,0x63b0a032),LL(0xa078d298,0x6ccd3ce5)}, {LL(0x91292fd3,0xf93bd108),LL(0x14073286,0xc887a31b),LL(0x9f62cd16,0xeb1275bf),LL(0x61578b46,0x0335bae3)}}, {{LL(0x53348e4e,0x810d5efd),LL(0x63c74225,0xf9cd822a),LL(0xa426bf44,0x93d2e810),LL(0x019d36b3,0x95a47a97)}, {LL(0xd5d1f840,0x1da421b9),LL(0xd6c46e3c,0xe5b8a55f),LL(0xc9244881,0x2dd3a5e7),LL(0x70c1fd2f,0xd50f9cde)}}, {{LL(0x614d9ff3,0xbee2aca7),LL(0x358f245a,0xd1f13b2c),LL(0xc46f62ab,0x9e92d83f),LL(0x827d7374,0xc1dd32dd)}, {LL(0xc3e566e7,0x1636d593),LL(0x04ccb02b,0x81c2f4e7),LL(0xcd35b652,0xb57782c6),LL(0x88210d42,0xad88787e)}}, {{LL(0xfbd7d35a,0x3ad52d72),LL(0x37a2a095,0x4117f502),LL(0xd356b3b6,0xed03d415),LL(0x15ca6087,0x135d5a8c)}, {LL(0xef5dca2a,0xfbaba41f),LL(0xafb4787d,0x660e5cd0),LL(0xa55e9ef0,0xe0e66378),LL(0x69939f56,0xf24513cf)}}, {{LL(0xab4f6bd9,0x0f38f09c),LL(0x922dcac1,0xec3037b4),LL(0x08a1a51e,0x706b201a),LL(0x8ffff040,0x15911351)}, {LL(0xccf63d87,0x239d7b6a),LL(0x5187f595,0xeca37dc8),LL(0xad5a0ab3,0x04ea79e4),LL(0xe9520e8f,0xcdd81522)}}, {{LL(0xc35e1020,0x7fe6b6aa),LL(0x140ac884,0x57b63c9e),LL(0x33f19077,0xc45c23fc),LL(0xb71273c5,0x468d2c36)}, {LL(0xfc305ac2,0xeb6839d6),LL(0x0183793a,0xf6e310ff),LL(0x32da639d,0xbca206e4),LL(0x8518e27e,0x8eb5cac1)}}, {{LL(0x66ed96f9,0xfeed0feb),LL(0xecc3a8dc,0x1632632e),LL(0x1455c8ae,0x90449363),LL(0x0aeada65,0x8d7619d4)}, {LL(0x9f630ee9,0x2f2fa898),LL(0x370db87c,0xd78caf0c),LL(0xc45898cf,0x46fa0fc9),LL(0x2d84244f,0xa509cc3e)}}, {{LL(0xa5b099aa,0xbdbea4b4),LL(0x7592587b,0x8e8fe284),LL(0x42000897,0x0226d387),LL(0x36db5cd9,0xb6780551)}, {LL(0xca64f047,0xd8fe5eb1),LL(0xb77cf8cb,0x6f21474b),LL(0xee45ae34,0xab8fcae7),LL(0x1f19cd67,0x73eaf9eb)}}, {{LL(0xee4df6ce,0x5bb96415),LL(0xa3ae4cf3,0xd1e27bcf),LL(0xc7f1868e,0x9bf7ace3),LL(0x82091dca,0xe821aa8b)}, {LL(0xd381b6c4,0xf732e6bc),LL(0xdd01864f,0x5feda346),LL(0xb6387846,0x0933b92c),LL(0xa0028029,0xbf1f1e83)}}, {{LL(0xa3e38124,0x0848bf8c),LL(0x208fda8f,0xfe295fdf),LL(0x8913a1c4,0x73379239),LL(0x7e78564e,0x59354b24)}, {LL(0x32dcafbc,0x042b7529),LL(0xfa93c5c7,0x752173d3),LL(0x9737135a,0x6ffd4590),LL(0x0f983005,0x249712b0)}}, {{LL(0x1f25da8b,0xdbba2874),LL(0x097ba4a9,0x14027f11),LL(0x34b8e4a2,0xe429b3c7),LL(0x056b4afc,0xd66a43e3)}, {LL(0x2ac351e6,0x158644ad),LL(0x164bc6cc,0xff4aecd9),LL(0xf6c615ee,0xbb5b0c87),LL(0xd7679b1b,0xc497d8ee)}}, {{LL(0xf1c6e97a,0xf666c625),LL(0xc73a277f,0xe89f84b2),LL(0x746af4c0,0x2403d513),LL(0xb7101feb,0xe6858fdf)}, {LL(0x84f1dcb7,0x1a42c51b),LL(0x8202bc04,0xc57f12e0),LL(0x754df5ae,0xf8326a93),LL(0x81a46aef,0x3d3daf04)}}, {{LL(0x01232d03,0x8bb8c276),LL(0xfb371cf1,0xd446c82e),LL(0xefa495f4,0xe5e8b639),LL(0x477e6493,0x51a7b34a)}, {LL(0x824f2b6e,0xffba5466),LL(0xf0eaa6a9,0xcc67ddad),LL(0xfee19b24,0xcf0f8ce1),LL(0x83b3df41,0x34309127)}}, {{LL(0x9719a6cd,0xc8b13e8c),LL(0x619d5c33,0xb408e505),LL(0xa3158864,0x8c1b831b),LL(0x0b3d02bb,0x506b3c16)}, {LL(0xbf11ff8d,0xf23846bc),LL(0x16e0328a,0xf0f043e8),LL(0x65986a7a,0x30b7b9cd),LL(0x21b660cd,0x0951b102)}}, {{LL(0x52bf29a5,0x72a26c5f),LL(0xb6534592,0xb513d669),LL(0x578195ea,0xb8ac15ad),LL(0xc0785f88,0xd6ed33ea)}, {LL(0xb9e33946,0x39e23dbf),LL(0xf43e88eb,0xeadb2453),LL(0x2746c34b,0x6d82fefa),LL(0xcc542b54,0xe9172aa0)}}, {{LL(0xecb50699,0x8af6b819),LL(0x1c1d0af9,0x4af76939),LL(0x99dddb1a,0x5a7dbbbe),LL(0x891ea41d,0x97b0a3aa)}, {LL(0x6e35ea4f,0x32b457e6),LL(0x9d77b900,0xe2a21c2a),LL(0x2ac991cf,0xb18718d6),LL(0x740743cd,0xc4416237)}}, {{LL(0x6a05ab55,0xcc3f76b6),LL(0x98091425,0x2ab4b29e),LL(0xb6478fc8,0xbf373ad1),LL(0x178b5844,0x8a1a9489)}, {LL(0x09daf4be,0xb5295edf),LL(0x4ed54766,0x07fbb119),LL(0x7d0b9d8f,0x6e44367b),LL(0xedb96a10,0x6dc4d8f6)}}, {{LL(0x37fc19a3,0x2ba69106),LL(0x0b138296,0x522eba39),LL(0xfda58cf3,0x751544c7),LL(0x0ba33938,0xaba6fe16)}, {LL(0x94dac7d6,0x48e085be),LL(0x19f99faa,0x06c87014),LL(0x1a587f89,0x33b9a8d6),LL(0x3fd8d8fe,0xdae382ca)}}, {{LL(0x150b0fcd,0xb5b383c6),LL(0xed9b0f4c,0xf948da80),LL(0xccd05413,0xcf075225),LL(0x4f62be64,0x3f31b12c)}, {LL(0x368c17f6,0x23b21fc8),LL(0x400bc690,0x423d5369),LL(0xdeac140e,0x5335dd1e),LL(0x9493ad61,0xe631c249)}}, {{LL(0x32fe490a,0xc274c695),LL(0x6d8ebd70,0x42bcb4e1),LL(0x65d7a1d0,0x69059e1e),LL(0x29fdd109,0xf36dfe2f)}, {LL(0x0c4e6370,0xacfea1ec),LL(0x7a935ff4,0x97e7f722),LL(0xf8006bbd,0x83e7c7c3),LL(0x78e6792c,0x87a8b84d)}}, {{LL(0x94d3d60f,0x5cbe4883),LL(0x91cbc054,0x6eba464d),LL(0x021c38fa,0xf9c880d0),LL(0x21af4942,0x6200faf1)}, {LL(0x5f03e261,0xd5b2b12d),LL(0xf3ea3e07,0x1659a0ac),LL(0x836757a8,0x8008f18d),LL(0x75a8f8e0,0xfb2f467b)}}, {{LL(0x9c9b00cc,0x9a6183c7),LL(0x3bf842b0,0x82ca07e3),LL(0xee1f83d9,0xe7089191),LL(0x2d0cd2da,0xc41ecde4)}, {LL(0x4d1feacd,0x0ce421b0),LL(0x431c53f1,0xe80a1395),LL(0xe6bfccf5,0xae9b2018),LL(0x8b359c3b,0xdf9f86ad)}}, {{LL(0xb6170a5f,0x9887e28f),LL(0xf3c0c30c,0xf5b85d21),LL(0x632af7a4,0x30861cf8),LL(0xbb4ec123,0x2fb670ad)}, {LL(0x3c425976,0x0668b84c),LL(0x02883af7,0x55c21b4e),LL(0xf8698d29,0x0fad58b5),LL(0x68b671c5,0xef210770)}}, {{LL(0x23f232b8,0x534d510a),LL(0x49c99708,0xdb66fec1),LL(0x6d54721b,0xf1a6f3e7),LL(0x4480f858,0x8d37ab64)}, {LL(0xb0f7f354,0x7fcfca6c),LL(0x95bfd318,0x58c7ff5f),LL(0x903f9d91,0x3048e9af),LL(0x75357af0,0xe480bc0e)}}, {{LL(0xa5a1162e,0x4f915e1c),LL(0x37efa40c,0xdd539c21),LL(0x789201c2,0x61a45c53),LL(0xe7890746,0x1bc2333d)}, {LL(0xbbed8f77,0xeed38f50),LL(0x178501a0,0xc1e93732),LL(0xa8fb8623,0xfed5b1d1),LL(0xdc3e1148,0xa3be3e2c)}}, {{LL(0xa71a390a,0x62fc1633),LL(0x2891c4c3,0x4be2868e),LL(0x2a0c3c23,0x6573fe49),LL(0xde1589d0,0x182d0bd4)}, {LL(0x5a7aa63d,0x17c6a780),LL(0x12543191,0x9d84cfa8),LL(0x950c85c9,0xcdb22db7),LL(0x119010c4,0xd03589e0)}}, {{LL(0x8220dee8,0xbcd02e8a),LL(0x705632fd,0xbd4d1f2a),LL(0x22f8e30b,0x00119bfd),LL(0x6eb97c32,0x06c6e73e)}, {LL(0x35abff53,0xa26f0a6a),LL(0x8564c37d,0x7d79a89f),LL(0x1b207495,0x0347bb17),LL(0xb5c8253a,0x1baf90e9)}}, {{LL(0x37affc96,0x01059b5f),LL(0xffee0a60,0xbe76c578),LL(0x75d6b83c,0x45d7291b),LL(0xe0b58129,0x212ff131)}, {LL(0xaa5d46ed,0x4acc5748),LL(0x9193931b,0x9fc557d9),LL(0xda4eba9b,0x17568fcf),LL(0xa0edc975,0x2cf3690c)}}, {{LL(0x953df6fd,0x0e8b0e7e),LL(0x62036a87,0x38ea7cea),LL(0x655c3685,0x57e01428),LL(0xc39d8a43,0xaedfee73)}, {LL(0x5fb27e0a,0xed7f6598),LL(0x946888e0,0x524c3653),LL(0xe949b72f,0xd84a299b),LL(0xb0c61ea4,0x76c1397a)}}, {{LL(0x1afe465a,0xfd9f7ed0),LL(0xdbbaf852,0x832c69ad),LL(0x03713338,0xcd888c22),LL(0xe3306617,0x4e1fe026)}, {LL(0x23521b97,0xa87adf86),LL(0xf9fbb2a0,0x673d3625),LL(0x5d8f5b80,0xf29a1413),LL(0xd3526501,0x6e9be0c4)}}, {{LL(0xe8bfd84d,0x6129f861),LL(0x77e35a47,0x1df491d6),LL(0xa84a82cb,0xefe0e9a9),LL(0x6d949612,0x972bc3bc)}, {LL(0x3a766eca,0x8d7795f5),LL(0x12fcc6d4,0x6119383f),LL(0xc95f0e21,0xa66d9836),LL(0x684e434b,0x77a0aa0a)}}, {{LL(0x7dd7b05a,0x3d55d256),LL(0x0fed8362,0xda616243),LL(0x383e94fe,0x24bd0fe8),LL(0x6bfd0cd2,0xbc2b7334)}, {LL(0x321f7a70,0xf9497232),LL(0x6a3df54f,0x37a4c2f6),LL(0x4ddc49d6,0x7ba783bf),LL(0x04408c76,0x4d142317)}}, {{LL(0x38b99f23,0x7502146b),LL(0x21992e8f,0x479ab73c),LL(0xd52c41d3,0xf605370a),LL(0x3a60435f,0x358b746d)}, {LL(0x5bc537b8,0xb2cbab94),LL(0xb99057d3,0x1fd24431),LL(0xb8510f3c,0xff2242a0),LL(0x0733bc53,0x74b4965d)}}, {{LL(0x86edc9b2,0x30a3a634),LL(0x49c07c7f,0x99c9cf19),LL(0x5b0cd506,0x9d8a50c2),LL(0xbbcb3d65,0x0ed9da5a)}, {LL(0x013f88ec,0x6de1fb5e),LL(0x09086f8c,0xc9356bff),LL(0x2b8825d7,0xa272e1ac),LL(0xf2c5ba33,0x3ad83acb)}}, {{LL(0x275bce43,0x721ca22c),LL(0xd24f78e8,0xf058b8a7),LL(0xeed46b97,0xd178eb57),LL(0x259fdb5b,0x4ad7d425)}, {LL(0x1b515fe5,0x669ed853),LL(0x76fa1b5e,0x9f14b8e5),LL(0x3da46b02,0xfaba8d0c),LL(0x338f7652,0x759c2c95)}}, {{LL(0xb5c0ceb3,0x9a369cb0),LL(0x28a2a633,0xc1d2d1ab),LL(0xfcb48cd3,0x676190e3),LL(0xee09c3b1,0x9af97ab3)}, {LL(0xf7e918f5,0x39323719),LL(0xfd3cd554,0xc657cb57),LL(0xa2a02d5c,0x78a33d05),LL(0x64ada03f,0xda3b79df)}}, {{LL(0x61b3a72a,0x7115ab5c),LL(0x337194fc,0xdd19f34b),LL(0x8f0a14c3,0x0f23bfec),LL(0xa60485d3,0x1fe19eec)}, {LL(0xa463dc9b,0x1ca308c3),LL(0x5e1ae8be,0x83e18dd0),LL(0xd928c0e7,0x849eabdf),LL(0x6bd3e7b3,0x2d131ff5)}}, {{LL(0x45be4c14,0xc84cd284),LL(0xf8f4c719,0xdee94092),LL(0x3cb73831,0xe8f223ef),LL(0x18c2361e,0x24382f88)}, {LL(0xbe91c8dd,0x205366d0),LL(0x56024b95,0x1e17b50c),LL(0x742cabd3,0x3c3487da),LL(0x8bad494c,0xbe451387)}}, {{LL(0x18ffaef0,0xfae6c0bf),LL(0x85ed1ede,0x2e7b0ee3),LL(0x125d1488,0x3cebaa05),LL(0x7c8b7fb8,0xcd0de0fe)}, {LL(0x464bc74a,0x59434d54),LL(0xa03fd77b,0x17472da2),LL(0x2c1a9edc,0xab23d042),LL(0xd9cf4b37,0x5390625e)}}, {{LL(0x0531264e,0x43b85844),LL(0xee7aedca,0x8d71805e),LL(0xfbe643ad,0x4ace3068),LL(0x5f7d46c1,0xc98d1cd2)}, {LL(0xf59b3acd,0xd4888744),LL(0x27288b99,0xcf662d61),LL(0x5bce2649,0xf2704561),LL(0x206ae654,0x33a8f3f9)}}, {{LL(0x9bce2b39,0xe834843f),LL(0xa90cfc7d,0x8de8e41d),LL(0xd81115b4,0x398800ed),LL(0xff2532da,0x4d33f7c5)}, {LL(0xdcc59e2c,0x5ae37fb2),LL(0x24015306,0xca27b622),LL(0x11e8d6e6,0x51beca89),LL(0xa9693774,0x08c0b7e2)}}, {{LL(0x72fa713e,0x795e1a21),LL(0x4be58266,0x5ec1c123),LL(0x1be14fc3,0x5d8e87da),LL(0x80283ad5,0x82cefc1e)}, {LL(0xdab7865e,0x820a385b),LL(0xf3daf96c,0x11e32d62),LL(0x5835a989,0xf022ade7),LL(0x00242233,0x2cbc2554)}}, {{LL(0xe7ce649c,0x653335a0),LL(0x6857eff7,0x8b30baef),LL(0xf3288377,0x7ea7c856),LL(0xe8572f5d,0x1387b347)}, {LL(0xbe10c0cf,0x8a6b0352),LL(0x037c97b9,0x2a74e834),LL(0x197b122e,0xfe10bf59),LL(0x1918aced,0xd1ee174c)}}, {{LL(0x3958c20d,0x568e5fb9),LL(0x0484a92f,0x1188cbe6),LL(0x4b0d29e3,0x00ec14f4),LL(0x16a2796d,0x2b2e078e)}, {LL(0x20440444,0x48b8cffa),LL(0x661ab68d,0xd4b877a0),LL(0xc4b459fa,0x1f352ab1),LL(0xc53aa54c,0x33accbe6)}}, {{LL(0x02bb383b,0xce4ff566),LL(0xfd62813d,0xcad561c6),LL(0x01dfc9a8,0x0927c348),LL(0x00fb9a61,0x0dde73fb)}, {LL(0xfce59f34,0xd859809f),LL(0x81872a46,0x225bd9b6),LL(0x0314bb90,0x2642add2),LL(0x0ae61eb8,0x82dc7958)}}, {{LL(0x22d5b667,0x84c97478),LL(0x6214f46d,0xb2fe94d1),LL(0x12cb20de,0x834740f2),LL(0x8aa69c94,0x336dc7a7)}, {LL(0x939a33e6,0x8ca085a4),LL(0x75a94543,0xd59c9ae9),LL(0x3c47dd07,0x83c97f98),LL(0xe3177231,0x0985f73e)}}, {{LL(0xebbc623d,0xe556c3fc),LL(0xb1b968fa,0x30a3242f),LL(0xbcd05a51,0x842ce9b0),LL(0x0ad576ce,0x241a35ed)}, {LL(0xbb4a793e,0x49ccaf3c),LL(0x4492a828,0x6e6c7a7b),LL(0xba53eb42,0x72f4f5fc),LL(0x3ea74dab,0x0ca4ba53)}}, {{LL(0xbbaf9d5f,0xe7b5fb06),LL(0xb02d3b20,0xd49c2e17),LL(0x2d933cc8,0x4d31052a),LL(0x07299aec,0x5346e0b4)}, {LL(0x79aa99ec,0x952a6205),LL(0xecb34e97,0xaab9bc32),LL(0x58ffe9ae,0xd539d7e4),LL(0x9d994472,0x91599393)}}, {{LL(0xe8822711,0x6b1d4868),LL(0x73d452b8,0x8857e282),LL(0xf08ed046,0xad59adfd),LL(0xc1c47abe,0xdb755d65)}, {LL(0x63275d49,0x2df8520b),LL(0x7f8a3249,0xc3c712ec),LL(0x5215ef57,0x55f2a108),LL(0x3ee2f149,0x955e07a3)}}, {{LL(0x33f344f4,0x2194ff53),LL(0xbad16820,0xb455b9fe),LL(0x610b4e4c,0xfe69ea78),LL(0x8ab11fe8,0x2957be96)}, {LL(0x2ce14366,0x3efdee3c),LL(0x01eddf9f,0x42043f9f),LL(0x93524f6c,0xfb7998b1),LL(0xdfecf763,0x95ea64c0)}}, {{LL(0x21afa86f,0xb23d2620),LL(0x86b11457,0xea757f03),LL(0xb0148d30,0x0bc4d2d1),LL(0x88ce4170,0x119b5535)}, {LL(0x0aa9c8f6,0xaab5bb67),LL(0x88e05de2,0xdfc9693c),LL(0xe3f1e9c3,0x6cae7e57),LL(0x6f6c3b9c,0x2b1ceb54)}}, }, /* digit=6 base_pwr=2^42 */ { {{LL(0x87636183,0x12e335ca),LL(0x719d1ca3,0x1461a65a),LL(0xb14161d8,0x8150080a),LL(0xc612e112,0x08da4ebf)}, {LL(0xa8498a9a,0xc95dfb6b),LL(0xba0f8dba,0x099cf91d),LL(0x4fb4f497,0x12d2ae14),LL(0x33cb7306,0xfa3a28b0)}}, {{LL(0x0f01c7ce,0xc89fc5d0),LL(0x7283bdf0,0x6fc45ffd),LL(0x81151923,0x71dece81),LL(0xc433fcc9,0xed1cb14c)}, {LL(0xd3959bcf,0x4279612b),LL(0x35b5732f,0xe163880b),LL(0x71d0a1ca,0x35414ca7),LL(0x2c1e47f3,0xe8b9e651)}}, {{LL(0xc8df0a74,0x4ff11b0c),LL(0xe095ea9a,0x346ba520),LL(0xcc2bc6c0,0x81dd2268),LL(0xc2701468,0x2fb2e99f)}, {LL(0x98053f0e,0x0d213361),LL(0xf7ae879a,0xe0b8280d),LL(0x952560f7,0xd92b7a75),LL(0x9723b62e,0x8d17dfad)}}, {{LL(0x08b21362,0x5ce8a78a),LL(0xd9fe0b36,0xf37f5e7f),LL(0x2c87837c,0xdca66c7f),LL(0x0bf2e993,0x92524b94)}, {LL(0x71745788,0xfc0f020c),LL(0x3cbfbf4c,0x6018de46),LL(0xac3de1c8,0xa8446691),LL(0x5de5ae41,0xb194d419)}}, {{LL(0x2ff27af2,0x1586cdff),LL(0xde26b5ef,0xee628535),LL(0xc682923e,0x58480040),LL(0x5e37da30,0x4dd4596b)}, {LL(0x2f64225f,0x247b9fd7),LL(0x51ca2121,0xdcc6de5f),LL(0x86e7ab9a,0x99fb41ac),LL(0x952b413a,0x54c782a0)}}, {{LL(0x7298c7d9,0x7641190e),LL(0x716eda14,0x499c35ed),LL(0xbb764e90,0x316134bf),LL(0x884fc34e,0x4d23467e)}, {LL(0xf1d13484,0xfd1208a9),LL(0xcd298a74,0x089d9605),LL(0x73c4346a,0xb398c85a),LL(0xf37f13de,0x50064076)}}, {{LL(0xa6ebb83d,0xfe10d25a),LL(0xa834b30d,0xc5e3edf8),LL(0x683e09ff,0x546b5d5c),LL(0xc6dc44c6,0x02f96218)}, {LL(0xc0edfc04,0x64528c55),LL(0xb0fc3058,0xb5a44a2c),LL(0xceeff21c,0x9f09b116),LL(0x6b0fbbcd,0x077bcd67)}}, {{LL(0x9ce76a94,0x29aaa4a8),LL(0xc0725c97,0x847cd081),LL(0x97e16665,0x0c099e90),LL(0x8f7b1fc4,0xe409ffc9)}, {LL(0x690941ed,0xc0575b80),LL(0x92c0ee9d,0x8e25100a),LL(0x9b75837d,0x71662d27),LL(0xe56bb22b,0x6eeb9e97)}}, {{LL(0x85c6a60b,0xf1d6333f),LL(0x1d7ccfaa,0x982fee9d),LL(0xd4634535,0x1c5e28e7),LL(0x94fec469,0xa76e1d27)}, {LL(0xafe377ec,0x1fe944d6),LL(0x2f68ae6b,0xbd579a25),LL(0xab6b515e,0x10eabb93),LL(0x31b4e4b8,0xa17b5f6c)}}, {{LL(0xaf72c239,0x05e785fb),LL(0x8af42e92,0x597e2016),LL(0xb32ae6c9,0x663f5a72),LL(0x45541cc6,0x3040ff13)}, {LL(0xdeca6b32,0x6140081f),LL(0xc735001b,0xcdaccaf7),LL(0xdaef0e68,0x62de5066),LL(0xd837df99,0x056e9021)}}, {{LL(0x16cd1be7,0xba399283),LL(0xcfacf7ad,0x2a486323),LL(0x277777ce,0x00c15730),LL(0xd49a254c,0x5d2f200f)}, {LL(0xdb68078d,0xf38a1f3b),LL(0x33604a36,0x595dea3f),LL(0x904b60b2,0x14749d8c),LL(0x246348ff,0xe70c96d8)}}, {{LL(0x390e35da,0x04340d52),LL(0x27a9947c,0xc098e3d3),LL(0x9ecc7a3f,0xe6d78198),LL(0x23aa6df6,0x2c39102e)}, {LL(0x300f3cb1,0xb83fed0d),LL(0xdcfbe054,0xc0b1e356),LL(0x20cf45a8,0x3da2224c),LL(0x2f30deda,0x5be55df7)}}, {{LL(0x2faa9530,0x4d31c29d),LL(0x49d42f79,0x1d5783ae),LL(0xf618b3f3,0xe588c224),LL(0xf8f5b65d,0x7d8a6f90)}, {LL(0x62d09174,0xa802a3d2),LL(0xbddd1cb7,0x4f1a93d9),LL(0x35a5c1dc,0xe08e1d3c),LL(0xf9d2958e,0x856b2323)}}, {{LL(0x96f00090,0xefd1e3ba),LL(0x3e0d25de,0xd489943f),LL(0x30c8626f,0x082c40ae),LL(0xa4f428e0,0xf6e5b5ef)}, {LL(0x38a7f623,0x660414a3),LL(0x23eefed8,0xcd4e68de),LL(0xfc14e750,0x6dcadc62),LL(0xbeae89b6,0xcb78b3bc)}}, {{LL(0x1d5e580e,0x445acc56),LL(0xc43abe19,0xbf6547ef),LL(0xc922d50f,0xd160a81b),LL(0xf68eed4e,0x3877c7f8)}, {LL(0xf8a9f64a,0x395745ea),LL(0x603350f6,0x9085b253),LL(0x8b1df366,0x2a4c71f1),LL(0xabe332dc,0x49b9e818)}}, {{LL(0x528960b1,0xb3e76e66),LL(0xd84aecb3,0x445dc393),LL(0x1612ad64,0x13618436),LL(0x8c831e37,0x3ccbeccc)}, {LL(0x6121383c,0x0fb0bd41),LL(0x80d895a3,0x316164a3),LL(0x233f2f1e,0xc3d34153),LL(0xe0d92225,0x2905906f)}}, {{LL(0x95456622,0xe12d66e2),LL(0xff554b13,0x10469942),LL(0xf7126c09,0xa894af86),LL(0xf581d3f5,0x448f3267)}, {LL(0xa2b5e758,0xb5512926),LL(0x43fddd90,0x08f02988),LL(0x8ba319e6,0x5f437035),LL(0x865b37e7,0xd254188e)}}, {{LL(0x8a5cb63a,0x5b281b23),LL(0x6dd136c2,0xa15a2712),LL(0x169beae4,0x00fab229),LL(0xde31b4a1,0x400d3f37)}, {LL(0xf8545cb0,0x275877a4),LL(0x36df0277,0xb396a513),LL(0x838ced07,0xf9896978),LL(0x715cea8d,0x86e68167)}}, {{LL(0x06a5a96d,0x0eb0f0de),LL(0x1fcf91ae,0x2c7a3672),LL(0x630eca3a,0x287bf614),LL(0xf60c9d2d,0x65347473)}, {LL(0x906efa7f,0xed15a229),LL(0xd549b5b3,0xe7be6381),LL(0x2ce9141b,0x23f32972),LL(0xfcf823f8,0x9618d9a1)}}, {{LL(0xa3d89e15,0x3d0ef0d3),LL(0x0d07f5eb,0x4d5a30c9),LL(0x73e4887a,0xc359e310),LL(0xdbdec349,0x2f4c6b7e)}, {LL(0xba142643,0xc5a1d3e9),LL(0x11c794b6,0x8f4fd58e),LL(0x1810c63d,0xcad091d1),LL(0xf0bfa76c,0x5b616239)}}, {{LL(0xa838792a,0xe3433562),LL(0x54148e98,0x4aead02b),LL(0xdb66f216,0x809f2baf),LL(0xeabfe5da,0x09cc90ff)}, {LL(0x63e8edad,0x69eb235a),LL(0xa7f95997,0x64f7acb5),LL(0xfae20f25,0xe999ea18),LL(0x3c4966b3,0xcd7ff208)}}, {{LL(0x345c8929,0x595e0cc0),LL(0xde5e2498,0xfe43c73c),LL(0x503f216d,0x0cdefc98),LL(0xf98826fb,0x8e4e170d)}, {LL(0xb6c79b1c,0x1492247d),LL(0xef0532aa,0xf8e24b38),LL(0x044bc458,0x9f349d51),LL(0x1002d315,0x2ef04ead)}}, {{LL(0xda60d581,0xaf322f23),LL(0x0681173f,0x07deaa88),LL(0xa78feca0,0x86b97444),LL(0xc633a54d,0x64d336ea)}, {LL(0x2a426cbf,0x10dd4b1f),LL(0x7af59869,0x08d97c15),LL(0x2d7fe97e,0xb8cc814b),LL(0x3bfb60fe,0x7eacd2e1)}}, {{LL(0xb790881c,0x967dafb7),LL(0x3663e76c,0x2002b8e4),LL(0xf8e82490,0x3bd28ede),LL(0x4bb2a47a,0x44dd2e81)}, {LL(0xdbc3f2f8,0xde750dfe),LL(0x6e2eec70,0xd9b6e912),LL(0x1e4c4d2f,0xe8400e2f),LL(0x23217be2,0xd3325697)}}, {{LL(0xd4231a1d,0x030b7e39),LL(0x613d17d8,0x1f72e8b1),LL(0x01857d37,0xcd423512),LL(0x0b4b7926,0x9ecd682c)}, {LL(0x8ec44636,0xfe4ac1c3),LL(0x9aacc091,0x4a030cbf),LL(0x0b133f54,0x12bb252e),LL(0xf970d266,0xbf90ea5d)}}, {{LL(0xf5484410,0xe00d25f7),LL(0x2a922894,0xb4984eeb),LL(0x8e1e09ce,0x498102fd),LL(0xe1d731bf,0x8f8c9fcb)}, {LL(0x0b4983b7,0xdb897669),LL(0x7b2468f5,0x7a7767f9),LL(0x72f4d5f4,0x1a2f9fe8),LL(0xa6169daa,0x10e95aa9)}}, {{LL(0x520166e9,0x9487e50f),LL(0xc4ee6a95,0x6f6b115b),LL(0xcf7560f8,0xaf29926f),LL(0x1f989e46,0x20a32458)}, {LL(0xd3bd2473,0x165a2232),LL(0xe9fecdf8,0x93d841ff),LL(0xbf9978c0,0x71d63fa7),LL(0xe7de184b,0x381bcf34)}}, {{LL(0x347dfaef,0x317c8e40),LL(0x64464bf3,0x795b0f7d),LL(0x1364ec20,0x15dc99d6),LL(0x91600d3f,0xc07fce28)}, {LL(0xc8bebbda,0x9825338b),LL(0xa8547c03,0x5e5e89f6),LL(0x1a040b84,0x3c50032f),LL(0x2b3a533d,0xcea7544f)}}, {{LL(0x43247e19,0xea26d87d),LL(0xfba8368e,0x7e753390),LL(0x3c7bcfc6,0xb35e75cb),LL(0x7e44aab3,0xf78cb5ce)}, {LL(0xa98d7104,0x4a3534e9),LL(0x6f5852ea,0x2b83ea6c),LL(0x68dced7c,0x11337fff),LL(0xd1a2a294,0xcca0f2c6)}}, {{LL(0x426bf202,0xb547c662),LL(0x66194a34,0xec50423e),LL(0x78161e84,0x11d34865),LL(0x64f04dec,0x83508c06)}, {LL(0xf7732345,0xd1c72976),LL(0x18e77e0a,0xd624bacd),LL(0xba79bdd9,0x71344b75),LL(0x8d6c1474,0xe4bfe085)}}, {{LL(0xcc5eb43a,0x505e8fd9),LL(0xdaaf0621,0x612ab1d0),LL(0xe6672368,0xde170783),LL(0x83788673,0xfee7df44)}, {LL(0xd119271d,0x364d6885),LL(0xe1b0cea2,0xdd70bae8),LL(0x5832adba,0xb4b873ad),LL(0x8c683749,0xad3ecc18)}}, {{LL(0x4d217a2e,0x963d8793),LL(0x1fa4702d,0x099e8c56),LL(0xe6431f1b,0x6d91bc47),LL(0xa5f61399,0x3fd21287)}, {LL(0x682fa08b,0x2fc90bae),LL(0xc1ca371c,0x51699c85),LL(0x831c428f,0x16f29d74),LL(0x9fa2b504,0x0ecefb66)}}, {{LL(0xa75c5a91,0xd04ac53f),LL(0x3bf0524b,0xcbe62421),LL(0xb8792826,0x91dcb3ce),LL(0x7885092a,0x28a6bf88)}, {LL(0x64c1e218,0x24798e59),LL(0x3fec97dc,0x18e848dc),LL(0x9da457b7,0x935e0f50),LL(0xb8f497a6,0x46b67ab7)}}, {{LL(0x7651e4ff,0x15a38140),LL(0x4890cd7f,0x6ba6c617),LL(0x5fe253ca,0xa527b8d2),LL(0xff3d603b,0x945277b8)}, {LL(0x75392f01,0x10796155),LL(0x2bd9619d,0xcac8f713),LL(0xdebb8e28,0x71a87eca),LL(0x52ab1792,0xe8e6179e)}}, {{LL(0xe33705e7,0x4ce3998b),LL(0x48ba56e4,0xf9a0661a),LL(0xd9e4e184,0x47f06b30),LL(0xf9f8f6df,0xda465f75)}, {LL(0xc0ad3e20,0xb05acbbe),LL(0x92bc2c13,0xec8776a4),LL(0x240a908b,0xbb3971b7),LL(0xbbd0cecc,0x80a14367)}}, {{LL(0x086949bc,0x40911e50),LL(0x4064a19d,0x39b3ab69),LL(0x6b07eaa7,0x538c6d96),LL(0xd3723bde,0x38c05b47)}, {LL(0x080d2a64,0x1e669308),LL(0x2a77601f,0x6b44dbe5),LL(0xe7c6ce9a,0x35579681),LL(0xa16afa75,0xd2950b0e)}}, {{LL(0xeaf7fafc,0xd228a3ba),LL(0xee878f00,0x9324e71d),LL(0xe413c1ce,0xa853bfc1),LL(0xdcf17d1c,0xfe916368)}, {LL(0x2546154b,0x8611383a),LL(0xe715b375,0xdbdf225d),LL(0x8dbb0651,0x874d70a6),LL(0x9ed56391,0x84e58895)}}, {{LL(0x3776503c,0xca83d8ad),LL(0x46e82d65,0x2cf38b4e),LL(0xadf3a8d1,0x65af46e6),LL(0x1d31056d,0x4f09a4ab)}, {LL(0xcacc81d5,0xdba27b42),LL(0x5d6e1bdd,0xb6caa0ca),LL(0xf7198b26,0x1086e441),LL(0xac572f9b,0x15dfe6cb)}}, {{LL(0xd2051dd5,0xd9444337),LL(0x834cd72d,0x6c34b236),LL(0x58df3f28,0x84783216),LL(0x2e921372,0x59b8808e)}, {LL(0x55835302,0x3b268249),LL(0x9f4863f1,0x3299cbe0),LL(0x4c4e213a,0x616e3cdd),LL(0x8c824317,0xa3c84868)}}, {{LL(0x460ed764,0x884be61c),LL(0xb6041177,0x388df47b),LL(0x60b29b0b,0x27089763),LL(0xe502ba08,0xd66d7d53)}, {LL(0x5acbfaf4,0xadec85ca),LL(0x470c9519,0xfbacf9b7),LL(0xdbcda5b2,0x5d18b7f6),LL(0x0f228ed5,0x7615c036)}}, {{LL(0xd6000825,0xdfcd8273),LL(0x9d440eb3,0xdacfcf11),LL(0x7738fa46,0xa8257834),LL(0x76281df3,0x7db548af)}, {LL(0x3e0b052c,0x71dd19f6),LL(0xd876613f,0x811feef2),LL(0xf9c3155c,0x7536e854),LL(0x4c8c1220,0x3e594973)}}, {{LL(0x069b4228,0xf8c5c72d),LL(0x1f2f6b02,0xc077d394),LL(0x76393a52,0x0032dfb9),LL(0x706c3572,0x5e52c880)}, {LL(0xe003750f,0x4a9d6e9d),LL(0x6147cee7,0x3d54814d),LL(0x23b655fa,0x09ed7f77),LL(0xf1988361,0x14fff651)}}, {{LL(0xfb263d48,0x742f3abd),LL(0x53699a0c,0xedb557dc),LL(0x7ecd0f61,0xc692a474),LL(0x058f0d17,0xdc64f583)}, {LL(0x3227d3ed,0x68a9ce75),LL(0x4601d083,0xfd0b0320),LL(0x9c2cee38,0x7167b330),LL(0x710e350d,0xef658993)}}, {{LL(0x16910648,0x75a83be1),LL(0x2e7d446c,0x5b32e77d),LL(0xa86ba2de,0x8e0534e5),LL(0xb692aeee,0xc8a92eac)}, {LL(0xf663150f,0x3cf686eb),LL(0x01962baf,0x840eaade),LL(0xa264d877,0x3e06154f),LL(0x24630300,0xbbd04137)}}, {{LL(0x58631468,0x0b0151bd),LL(0x9f99bbe5,0x570ef82c),LL(0xb30f7b96,0x03565f47),LL(0x98c04b24,0x000628e0)}, {LL(0xd6ccdb2b,0xd34a90ae),LL(0xa99a761c,0x1a584858),LL(0x65e29f1b,0xa640ddca),LL(0x728d3208,0xffb672f9)}}, {{LL(0x5433abd8,0x550f6392),LL(0x13ff0107,0x4f35e116),LL(0xe731a37b,0xbb2b0fab),LL(0xc83d6e74,0x1e8a5a08)}, {LL(0xc6565e23,0xf617e177),LL(0x76da0795,0x8e370e5a),LL(0x03936a55,0xa5631e02),LL(0xd41293ad,0xe576bee9)}}, {{LL(0x5381bc98,0xfcfd9bc7),LL(0x000a98ab,0x8a42ddfd),LL(0xb49463c4,0xd6091ca6),LL(0x9754ce07,0xf37f6b9f)}, {LL(0xfa399fda,0xe1543897),LL(0x8810063c,0x7b029ead),LL(0xec5a5b52,0xa98a46bd),LL(0xd50cc504,0xdd162811)}}, {{LL(0x67a95e56,0x4d725c1d),LL(0x8e17af44,0xc36d6e8b),LL(0x313454c1,0x38ffb699),LL(0x991e4eaa,0x22c3da8c)}, {LL(0x0bb72dc0,0xfa36ee15),LL(0x4fd01d32,0x356bbf74),LL(0x3c7939a3,0x9ff71a30),LL(0x691786e9,0xa0ad2fb5)}}, {{LL(0x283c34c1,0x7d7f4770),LL(0x2454a31c,0x0148a4f0),LL(0xeab3b646,0xdcbb138a),LL(0xf101223e,0x7834bdb9)}, {LL(0x965baa81,0x49de6cc3),LL(0x15471215,0x5462f15e),LL(0x81d17760,0xd77e7a56),LL(0x53f00de3,0xa08c5ad9)}}, {{LL(0x397ed010,0x2e6e6686),LL(0x2bef28cb,0xe444a5a9),LL(0x4073cbe4,0x1ab9d616),LL(0x18f0b7dd,0x24c6b9e0)}, {LL(0xc2a93055,0x456482b6),LL(0xefbe8715,0x0f89129f),LL(0x62e5f6f2,0xb50818c3),LL(0x3d63c663,0x1d74a1ca)}}, {{LL(0xd84bfa55,0x9a9124ee),LL(0x254b3f04,0x6cf81f41),LL(0xa1051109,0x7c9b7c3e),LL(0x640e8df2,0x71c3d6d6)}, {LL(0x62f6af2f,0x56571157),LL(0xe1bc9ae8,0x2ec61a3f),LL(0x2fcc848b,0x20caa2ff),LL(0xdc5c297e,0x71e30dac)}}, {{LL(0xfbc0740a,0x11901efc),LL(0xb6e35fca,0x4994fc5f),LL(0x177de7dd,0x4dc09eba),LL(0x0494bebf,0xedfdd25c)}, {LL(0x0cbaeb8b,0xc4821ed9),LL(0x66788fbd,0xa9ef7a48),LL(0xd65efbc2,0x5b7a7ca5),LL(0xa9cb1fc6,0xe18feb42)}}, {{LL(0x56b00ab5,0x2cc74b9c),LL(0xdb4bf3f4,0xf559a140),LL(0xb8a4b54e,0x283136d4),LL(0x37032aa2,0xe969e4f8)}, {LL(0xd85beed3,0x5635fb66),LL(0xa72a54bb,0x32bc4fdd),LL(0x4c386a49,0xc1e5ee2b),LL(0x795a0b08,0x979fd877)}}, {{LL(0x431f0b8e,0x5acef24d),LL(0xd13cafef,0x9f1c4a80),LL(0x4659f447,0xf19ac70b),LL(0x10f561ae,0x82bab6b6)}, {LL(0xbbc879a7,0x1268e7f3),LL(0x79c37165,0x7e7d7141),LL(0x597e313f,0x491f049d),LL(0xecc98736,0x6ca7e73e)}}, {{LL(0x80a31eb9,0xd7712aa4),LL(0x2d8b99d7,0xbf7376ca),LL(0x2b8e5f7b,0xc1166cdc),LL(0xf1a48c9b,0x562bf290)}, {LL(0x31c38c75,0xa6e72238),LL(0xb5f42def,0x51a9a100),LL(0xa100b75f,0xa0931d81),LL(0x967830be,0x7022479d)}}, {{LL(0xc192bc29,0x53eaaa1f),LL(0x4123a9f2,0x09504e7a),LL(0x90671997,0xe897397f),LL(0x4294fda2,0xc56185d2)}, {LL(0x9819b185,0xb531f278),LL(0xe9dda4cc,0x390155ff),LL(0x14d26bf9,0x1258a5d9),LL(0x7e5f13a1,0x47d8f5ae)}}, {{LL(0xe9591945,0xef9e05e3),LL(0x846441be,0x92d20e07),LL(0x1d897ad1,0x28cc70ef),LL(0x0bac861f,0xee962e74)}, {LL(0xbed368e4,0x9b7a4236),LL(0xe49b9720,0xe65ac22a),LL(0x22c1bd82,0x851f0032),LL(0x1e75ab15,0x771573ec)}}, {{LL(0x702eb71a,0x2e0a4635),LL(0xee924cd9,0x65167c74),LL(0x10ccabb5,0xe16b3515),LL(0x10ea5907,0x63cf15c4)}, {LL(0x616f5290,0x59dacdc6),LL(0x8e372a43,0x19eb409b),LL(0xe3c36beb,0x5c879337),LL(0x0555fa1e,0x5841e7e2)}}, {{LL(0xf346ec2d,0xce197347),LL(0x221db43d,0xe14818a8),LL(0xc935c025,0x1bf37115),LL(0xfee14ce0,0xb22bdb03)}, {LL(0xf0e3dfd6,0x893c5efa),LL(0xb1f95e1e,0x8fe9d56c),LL(0x407e4db0,0x6ee580e5),LL(0x9fb33911,0x0292bfc4)}}, {{LL(0xb2869cac,0x598ce787),LL(0x4798690a,0xd2f77720),LL(0x9cb6015a,0x2689e0f3),LL(0x7127b0e8,0x8831ddeb)}, {LL(0x5c4fd58c,0x44db087b),LL(0xcda33285,0x04a0c68e),LL(0xe1a4c364,0xe55f00d7),LL(0xb6393b21,0xb3a2ea9a)}}, {{LL(0x5e9d8db9,0x99ef4da3),LL(0x17b484bc,0xa01f11d9),LL(0x1767f6ca,0xc2283fbf),LL(0x9e77f389,0xbb524479)}, {LL(0x10149726,0xc4ea3c66),LL(0x82ec5f64,0x4b71d644),LL(0x642944c7,0x0fe49d52),LL(0x5a17a7bd,0x69fef689)}}, {{LL(0x8c3dce23,0x2f3588fc),LL(0x68e0c237,0x9d429231),LL(0x86fa61d2,0x63756076),LL(0x729bc192,0x1d89c6b8)}, {LL(0x00d3ffd1,0x85e098d2),LL(0xde6f9109,0x5bf292c2),LL(0x3e7b8f23,0xb20dc994),LL(0x87c6eb54,0xcbe51bad)}}, {{LL(0x0517b914,0x263fd862),LL(0x225499a7,0x447624ad),LL(0x71f807d9,0xfbb831bb),LL(0x2fe2e021,0x9514fe38)}, {LL(0x52418e9a,0x881e8763),LL(0xf1d9b43b,0x268e4655),LL(0x1f780af9,0xf917044a),LL(0x3d758ba5,0x3727b2d9)}}, {{LL(0x68755cf3,0x8487eb90),LL(0x7fe12541,0x1887394e),LL(0x46af8ca8,0x2e4c65d4),LL(0xb9e119dc,0x72aae645)}, {LL(0x1ec6ad73,0x958e0094),LL(0x8ce4573e,0x84a7eec4),LL(0xf9254b96,0x3d6d00d4),LL(0x8e421732,0x4ef44f58)}}, }, /* digit=7 base_pwr=2^49 */ { {{LL(0x7d3ad2ac,0xf59de0f8),LL(0xc0f92c5c,0xd2670cb1),LL(0xc900b6a5,0x8f05944a),LL(0x8d9668eb,0x11aeed23)}, {LL(0x7c488ea6,0x21b038e4),LL(0x78083d75,0x406ea3f7),LL(0x3bd31fe2,0xd22197b4),LL(0x28a6ef9a,0xdc8f8ccb)}}, {{LL(0x02887281,0x679a6483),LL(0x7f9de66f,0x13f3d39b),LL(0xf1a7dee2,0x289c3c50),LL(0x40b698b8,0xa510a53c)}, {LL(0x06f799ad,0xc566c3fb),LL(0xb5374650,0xcc95a879),LL(0x61c947b2,0xbd7343c0),LL(0x9543e51b,0xbbbff69d)}}, {{LL(0xba75aba9,0xb80d38dc),LL(0xd150f881,0xe9b61ac6),LL(0xca7b47c5,0x9f56af52),LL(0x77fb3128,0x040300d9)}, {LL(0xc01fd0c1,0x36877184),LL(0x8b6e134b,0x40112a04),LL(0xccd71653,0x56daed90),LL(0xb74bd62e,0xec553aa6)}}, {{LL(0x11476dde,0x0398381d),LL(0x1ea0923f,0x4959204d),LL(0x017745bd,0xd67427ad),LL(0x6935e467,0xef022a74)}, {LL(0x24e0380a,0x57e799f5),LL(0xb5f1a730,0x6ee2b64f),LL(0x521771d8,0x9aeaac48),LL(0x0992a13c,0x02c8521c)}}, {{LL(0x48f6934a,0x25dd9f41),LL(0x3e38e31f,0x8d191988),LL(0x32899837,0x35548844),LL(0xf56b07d6,0xf87c696b)}, {LL(0x73e927b9,0xbc66e7d7),LL(0xbb0bedc5,0x04cdac77),LL(0x0bcd022a,0x1e6f2903),LL(0x22c574b5,0xafa637be)}}, {{LL(0x55c1759b,0xcdca4b1e),LL(0xa6819d39,0x3d46ee3b),LL(0xb4b0fce9,0xf7497ade),LL(0xdcb613c3,0x54aef506)}, {LL(0x522ff464,0xbc11d721),LL(0x37bd3c51,0xf53f16f2),LL(0x485695b9,0x88f29955),LL(0xdac00fe3,0x428ce742)}}, {{LL(0xa3520c27,0xd971fbd2),LL(0xe05e1b9d,0x2204fe54),LL(0xf0c15c89,0xb08be507),LL(0x901a15c3,0xfeeda919)}, {LL(0x84b60eb5,0x6576ad3b),LL(0x59e951da,0x40d4b9a1),LL(0x76244608,0xbe96e1b8),LL(0x58ef9f37,0x3af35ec9)}}, {{LL(0x153adbf7,0xbfe5c43b),LL(0x80351fec,0x07a66edf),LL(0x3b109e60,0x3d804235),LL(0xa832c162,0x4dc97176)}, {LL(0xb1db1e5c,0x03fec75f),LL(0xa15b9900,0x6aa02da6),LL(0x4faa1cff,0x5f9e808f),LL(0xa6412a26,0x90aa28bd)}}, {{LL(0xe041d453,0x2fb2c15b),LL(0x86c18ef0,0x2b847efa),LL(0x115b7318,0x84f5ee9d),LL(0x71699936,0xd568b080)}, {LL(0x6ea5c852,0x34658ae7),LL(0x126d10ce,0x99f918b3),LL(0x09b9407f,0x75e3d9cc),LL(0x7883f978,0x11c6a0bb)}}, {{LL(0x876db0fd,0x522a6925),LL(0x7a9a4211,0xc5401ca1),LL(0x6789e755,0x89163b57),LL(0x0fd6f1b8,0xd2b2c99a)}, {LL(0xa7b452dc,0x427eea22),LL(0xef9db65c,0xce8e6682),LL(0xda9c80f7,0xfd835810),LL(0xea916411,0xdb91bfbb)}}, {{LL(0x798b5051,0x7a5aefad),LL(0x42a0d4cd,0xbd7ebc88),LL(0xbac28520,0x958e327a),LL(0x7d010c77,0xfa8bf6d4)}, {LL(0x579752f4,0x8a7040aa),LL(0xe573d895,0x47974d84),LL(0xfe16f77b,0xfd2a0cdc),LL(0xdbf71fdc,0x0f08f86a)}}, {{LL(0x2983bd4d,0xb19de6f1),LL(0x1e3a28b3,0xb990931e),LL(0x00cbc4f9,0x43b71b8b),LL(0xf4d75a0e,0x35d1ddd0)}, {LL(0xc653f111,0xc211951d),LL(0x88750928,0xbbc46824),LL(0x174803e3,0x0cf6e752),LL(0x8960d80c,0x81f5e0ac)}}, {{LL(0x0c52fcf9,0xe03ca085),LL(0x0865ced4,0xa795382e),LL(0xe7117376,0x03bd561c),LL(0x3fd7184a,0x8608dde1)}, {LL(0xa2a98acc,0xfd48fd50),LL(0x11df74b0,0x902fa587),LL(0xfa73b8f1,0x683f101d),LL(0xe7c0efa6,0xc805d31b)}}, {{LL(0x5b11d6c0,0xe5effb4e),LL(0x01c8374c,0xba30f747),LL(0x0c275aec,0x8733511b),LL(0x97354e36,0xf140b740)}, {LL(0x0341268e,0xb01ded69),LL(0x27eac17b,0x17bc3176),LL(0x8984992c,0x88097703),LL(0x3e05061c,0x37bfafab)}}, {{LL(0x111d0eb8,0x7eca9f09),LL(0x8f243481,0xda7eb023),LL(0x59b5e491,0xac3cb2d6),LL(0x4f794842,0x56e725b1)}, {LL(0x45b2dff6,0x43245254),LL(0xef10ec78,0xeafe73b9),LL(0x78819dbf,0x0d3cb2bc),LL(0xe784eb22,0xff1cd617)}}, {{LL(0x9ce0fcd6,0x0dbaf1c9),LL(0x3232a847,0x732ea65e),LL(0x6a75d822,0xdb2ce218),LL(0x3d2273ca,0x88ffd479)}, {LL(0xf2f26b61,0x89092ad2),LL(0x686706ab,0xfb7041bd),LL(0x5e23597c,0xe3d5fa75),LL(0x5995fc84,0xa2035bf8)}}, {{LL(0x4514b8bd,0x1feecd2c),LL(0x434b9233,0x57cb78b4),LL(0x24215322,0x59bd2ad7),LL(0x1ce8daa0,0x41437de2)}, {LL(0x7147ce80,0x401bbece),LL(0x5abb61e8,0x5e462137),LL(0x5a3790eb,0xbbf21033),LL(0x5134dee3,0x9a791c09)}}, {{LL(0xcedd2cc1,0xc8ded766),LL(0x6447b925,0xa3e48e9d),LL(0x69efa728,0xc73282a3),LL(0x8d408bec,0x8cb72c30)}, {LL(0x41cf92eb,0xfb4f2797),LL(0x26f2412e,0xef3f42a0),LL(0xa941ab5a,0xdbc0f972),LL(0x98337613,0xc7bd62dd)}}, {{LL(0x4e45dcbd,0x31892744),LL(0xb51b7f91,0x3b2979cb),LL(0x29b27fec,0x41e002f5),LL(0x4dd51b0f,0x9007ee68)}, {LL(0x6e23d565,0x82f417a3),LL(0x77127820,0x3321f343),LL(0x199b32be,0x8d09d965),LL(0x5bc2017b,0x948429eb)}}, {{LL(0x124eb248,0x22b639f9),LL(0x125f8c22,0xed097f74),LL(0x5f8bed34,0xdbc02517),LL(0x51aa29c3,0xb93f5b42)}, {LL(0xc7368c44,0x6fedd599),LL(0x2c772a9a,0x99a5a795),LL(0x7a5f156e,0x30b35ba7),LL(0x191c45af,0x9dc50978)}}, {{LL(0xb5b4c4fe,0xe8d241f5),LL(0xb75f54f8,0xda89eac1),LL(0x9ef86ae5,0xb399dba0),LL(0x51c1b8c6,0x2337bb46)}, {LL(0x4d02f348,0xfe60b0c5),LL(0x0afc6cd0,0x709f1235),LL(0xb40fce18,0x8a0b458b),LL(0xe3929cfa,0xefe143aa)}}, {{LL(0x0ca6cec0,0xab3a4b0d),LL(0x67246ec3,0xcb235374),LL(0x1ec2538f,0xdf9b0e89),LL(0x80c7b53d,0x3ec2ea13)}, {LL(0xd0ae3146,0x920c55f2),LL(0x43946090,0xd3ac4e1e),LL(0x97ebe7a4,0xeba72583),LL(0x393d401f,0x5031644a)}}, {{LL(0x9714de1a,0x802c3409),LL(0xde5bacba,0xc62d66d0),LL(0x903b8148,0xb6c2abeb),LL(0x5bffe1c4,0x203531ef)}, {LL(0xe862ead7,0x186266de),LL(0x1a23bebb,0x21e643d5),LL(0x6edda603,0x15c13d11),LL(0xb1bebc77,0x39b4a3a3)}}, {{LL(0xb9ac4754,0xdb456c1a),LL(0x4d3f305a,0xf497e6e9),LL(0x3fa62dc0,0x84d27e3a),LL(0x2524b94f,0xc18c3569)}, {LL(0xe380f5cb,0x92198954),LL(0x272ea458,0x81d8221c),LL(0x5f328491,0x6fa082f6),LL(0x8e304ccf,0x810ca5af)}}, {{LL(0x0d76e6d5,0xda9f1c15),LL(0xb7abad72,0x4bd38afc),LL(0x08aa20f5,0x14b5cc26),LL(0x81061318,0x010a1af8)}, {LL(0x03c287c0,0xaf9d7a73),LL(0xbc4d40ab,0x9ba5105a),LL(0xb07937a6,0x99e4b824),LL(0xc869f63c,0x026d294c)}}, {{LL(0xc910b521,0xaaebde75),LL(0xa7d5dd9c,0xc803ded4),LL(0x62764be2,0xc8b713b0),LL(0x92540cf3,0x5ea9ea2b)}, {LL(0x6930bd0e,0xbaa999c6),LL(0x1f4b254c,0x57052e53),LL(0x2b0b27ee,0xfb9fd699),LL(0x4cc83793,0x86b70932)}}, {{LL(0xfba59bbe,0x09ab4dd7),LL(0x04f4609e,0x83204fee),LL(0x93934977,0x251cb390),LL(0x647c13e8,0x8add9e8b)}, {LL(0xe7ea7006,0x444815d3),LL(0xbd032c32,0x22333c0a),LL(0x4058b7cb,0xe7728dc8),LL(0xd1bc061f,0xde8eb503)}}, {{LL(0x493d76c2,0x5d3ece2e),LL(0xd804954a,0xa425f3ae),LL(0xeac95eb8,0x49100271),LL(0x38b4be56,0x94e4dfa0)}, {LL(0x650f9930,0xa855893f),LL(0x50264765,0x1fa0a07d),LL(0x0d1d40be,0x37a3c169),LL(0x2eed2a0d,0xfedb51e4)}}, {{LL(0x1b3348b4,0xa6e0c2b2),LL(0xc414464e,0x9e361f42),LL(0x176e109a,0x3e14e2ee),LL(0xf4af92fd,0x5f1a6bbe)}, {LL(0x84beb8e5,0xf15d4647),LL(0x97d36132,0xac3f01c1),LL(0x84ca42ae,0x36e669bf),LL(0xd9433ca1,0xf789bdbd)}}, {{LL(0xf71e84d4,0x384f37f4),LL(0x59d6481a,0x57de9473),LL(0xf5e6fa70,0xa9a81f99),LL(0x6cb57bf3,0x26f0a64f)}, {LL(0x061d38fe,0xc07e1c13),LL(0x4a475732,0x6fae70e9),LL(0x840e595c,0x6cfb6b1d),LL(0x62848351,0xb23cf1f2)}}, {{LL(0x4fcf8743,0xef6094c7),LL(0x05fab119,0x7dc42218),LL(0x5c220d15,0x3207463f),LL(0x22c4bfb2,0xdf51b3f0)}, {LL(0x1572735b,0x13db445b),LL(0x2f6db574,0xd7662537),LL(0x7796f888,0x692f1e05),LL(0x33f45593,0x9f3d7a5b)}}, {{LL(0x313de667,0xb5deb892),LL(0x66a478a8,0x75c872d7),LL(0xc4992428,0xb67b5513),LL(0xf70fde09,0xf97e010e)}, {LL(0x60ee268c,0x49b0f053),LL(0xf67cd321,0x981b5141),LL(0x4fbc187c,0xb5a1ac8d),LL(0xc12e6da8,0x162417e2)}}, {{LL(0x62914938,0x07bb6fff),LL(0x19f44438,0xd385285b),LL(0xa28904dc,0x05a610a1),LL(0x5a29b9f8,0xd80a7099)}, {LL(0xc177af4a,0x72ccb553),LL(0x5e3752f4,0xac0bd91b),LL(0x7ae838a0,0x8e8ae668),LL(0x1fdfe7c3,0xcaa5a46c)}}, {{LL(0x93d34156,0x2cc2c1a5),LL(0x61fe4572,0x22beffb1),LL(0xfcdc7418,0x66f9f3ce),LL(0x6af66892,0xbaccda41)}, {LL(0x1af43f56,0x775c783d),LL(0x0ae04034,0x1b23b187),LL(0xe99b486b,0x5a9325f4),LL(0x8367ab05,0x36d5bfe9)}}, {{LL(0xa519d028,0x17d8d2fb),LL(0xbe00e7e0,0x27b6beb2),LL(0x15a3f03a,0x8d51c36c),LL(0x5faac8dd,0xbf90e78b)}, {LL(0xb27ab69f,0x4e8c28e7),LL(0x4a553da4,0x37ecf0c7),LL(0x210fe720,0x3a39682f),LL(0x0b0cdd0c,0x60c62e80)}}, {{LL(0xa16647cd,0x893aa225),LL(0x64ce0455,0xcffb728e),LL(0xc4f0fe79,0x81891d39),LL(0xf9c39f00,0x1abe3073)}, {LL(0xf961d05c,0x88336c27),LL(0xa5fc96df,0xc9033a88),LL(0x864b39f8,0x0d084405),LL(0x851e95c9,0x866aa904)}}, {{LL(0x98bae4a8,0x0c36da08),LL(0xb5feb202,0x9f88d799),LL(0x8054e4da,0xcd9aeb4a),LL(0x1e9134cb,0x005206bf)}, {LL(0x17ee6649,0xd5f32bf8),LL(0x60847ad2,0x9431dcd8),LL(0x8a3e4050,0xbe6d62c7),LL(0xedf10d40,0x3ae68f7a)}}, {{LL(0x4604d71f,0xa95c9ea0),LL(0x415f8028,0x01aa3fea),LL(0x5a41970a,0x3dd55ca5),LL(0x0b5776b4,0x05978ad4)}, {LL(0x787fe20c,0x7c9f5bdd),LL(0x75fdba0b,0x23b9fb7d),LL(0x5fcf3a0f,0xfb1a724d),LL(0x87817071,0xd63b3515)}}, {{LL(0x44e40138,0xecae282d),LL(0x87605748,0x8732df23),LL(0xd11188cb,0x0ef49da0),LL(0x51146cc0,0xc0478138)}, {LL(0x46621921,0x4ba42323),LL(0x47dfa4eb,0x8836dd44),LL(0x8ec16442,0xdb6a0100),LL(0x9cdd2e87,0xabdd9b81)}}, {{LL(0x502e26d1,0x205ee262),LL(0x3294e240,0xb961ef9c),LL(0x6da7733d,0x7178f1fb),LL(0x232ecf73,0x989b69fb)}, {LL(0x9a9bccae,0xb7278a35),LL(0x400a01f3,0xb1c81a0b),LL(0xa6b213ba,0x0781855a),LL(0x3429817e,0x8acc1b78)}}, {{LL(0xfb4e1aae,0x527e3a9f),LL(0x4c0b0f4c,0xc18c1cfd),LL(0x1fa7d9f0,0x0676c365),LL(0x4454cc7c,0x3314509f)}, {LL(0xc7c48245,0xb0f45371),LL(0x695ef470,0x913fe759),LL(0xc8d3e0ad,0xbb676070),LL(0x902e1638,0x0db98fcc)}}, {{LL(0xfc4dfaa8,0x42874e9c),LL(0x7084b2cb,0xcbf89462),LL(0x8a846ab8,0xd6d46f77),LL(0x14c183b1,0x9e4506ca)}, {LL(0xc53b7631,0xc2d0f9b7),LL(0x294d6c34,0xe47c3d8f),LL(0xc05d3f1c,0x04e3c868),LL(0xa5957fef,0xbacec4f3)}}, {{LL(0x3b77893e,0x4f4530ba),LL(0x69a18bd9,0x4c234f54),LL(0x5071f5e3,0xb45aadd8),LL(0xd1bd0b86,0x73e4160a)}, {LL(0x1c474f64,0x43fcb30d),LL(0x617d1612,0xedef0769),LL(0x0eec330e,0x92076734),LL(0x5b0a21b5,0xd7767770)}}, {{LL(0x183e26f4,0x4b7dea31),LL(0xc9fd2e70,0x59d6ff20),LL(0xd5d914f5,0x7bdea00f),LL(0x56376640,0xc736dd0d)}, {LL(0x38ae8300,0x593ae6ef),LL(0xdf0355bf,0xdafe49f1),LL(0x0db4491f,0x094ccd86),LL(0xfe4271ab,0x32295701)}}, {{LL(0x5db7014e,0x2b7690e4),LL(0xd7766bfb,0x1bbc9c36),LL(0x7d986d0c,0xc52249f0),LL(0x324f20ae,0xc7eec37b)}, {LL(0x0e912329,0xd376afa3),LL(0x04268fa3,0xbc35e949),LL(0x9e91a4ac,0x617bf765),LL(0x1d483ecc,0xb1e932ed)}}, {{LL(0xac493266,0xd4e31672),LL(0xecdafb85,0x1c779fe2),LL(0x06280499,0xed09eb4a),LL(0xcd4e1f33,0x3dd8d965)}, {LL(0xf34576dc,0x0fb4308d),LL(0x85781a43,0xa8ccbf5e),LL(0xce623a24,0x8dbf488a),LL(0x6118cfd4,0xb0e71d30)}}, {{LL(0x8cc9d957,0xfc68da68),LL(0x83815670,0x7e5e6b65),LL(0x3f185dfe,0x2c16f5ef),LL(0x98952b33,0x23a4098b)}, {LL(0xd515f551,0x15a80298),LL(0xa7f8f341,0x71a2e7fc),LL(0x8cf4f7b6,0xed42b1b6),LL(0x1504d390,0x02743db2)}}, {{LL(0x3016e513,0x2bded3a8),LL(0xfb0f7bfb,0xa3c508af),LL(0xaa2be716,0xa6a490de),LL(0xf4485b9f,0x5a04d9e5)}, {LL(0x6ad25b5d,0xd07b99d1),LL(0x65a72cb4,0xa1840109),LL(0x14c45a95,0xc8e2b32d),LL(0xe4f2ecff,0x0fae6e86)}}, {{LL(0xd94b6fe7,0xd09f454b),LL(0x23006b62,0xa776a633),LL(0xd332b4b9,0x6c700a1c),LL(0xce016225,0x50c3fb34)}, {LL(0x8af71463,0x4b805bc3),LL(0x5f1fb3b7,0x049143e2),LL(0x5a6d1dd3,0xbcaf4b61),LL(0x4733abac,0x02093dd7)}}, {{LL(0xdf59f061,0x1a23c3f6),LL(0x80c4efb7,0x87a6c141),LL(0xd88e4363,0x47635ae4),LL(0xbf8d2072,0x75e2089f)}, {LL(0xac83803b,0xa2bc1b27),LL(0xe2aafecf,0x8ae61522),LL(0xd0010193,0x4b459205),LL(0x9205f876,0x900f6a31)}}, {{LL(0xf808f044,0x49cddbc9),LL(0x95094ead,0x94637692),LL(0xb87c9bbf,0x3c9c7c0c),LL(0x4e1844d1,0x1699670a)}, {LL(0xcbcf85c3,0xd8a978f2),LL(0x6a36e1c9,0x83e7b806),LL(0xfaff9c52,0x6f28a73f),LL(0xb71eaa80,0x51341222)}}, {{LL(0x9328a676,0x195461da),LL(0x21766180,0xefcc93e5),LL(0x771a5485,0xed82c930),LL(0x205a8bff,0x34f15ce0)}, {LL(0xb8b3bfd8,0x88ab72cb),LL(0x8110fe55,0xbb59a5be),LL(0xc7d61a31,0x9ce8a082),LL(0x5b1c63d2,0xfe81d072)}}, {{LL(0xe9ff8421,0x9fae0be1),LL(0x967e13a6,0x4254f89d),LL(0x35da926f,0x1c094620),LL(0x4a76583d,0x84eda272)}, {LL(0xe0e0ffb8,0xa4033064),LL(0xabc72d0c,0x47951945),LL(0xb72c32e7,0x0af6bb4c),LL(0xda797f9e,0x6c73357b)}}, {{LL(0x2ac2e99d,0xd7a726c9),LL(0xcd62e7cc,0xf44b4731),LL(0xe6225822,0xf89f8e29),LL(0x8d713d92,0xa44bb9b0)}, {LL(0x9404f6c6,0x3291e8d3),LL(0x37bdb22d,0x50b7a4ff),LL(0x216a0f13,0xe008662e),LL(0xcf382547,0x150fa2d6)}}, {{LL(0x3138acbc,0xe5e47c55),LL(0x40d7f3db,0x595cf1e2),LL(0x2ee1949d,0x2872392d),LL(0x8a4fb721,0xdbd15bf8)}, {LL(0x183351dc,0x30e78cdc),LL(0x6b294729,0xa39b8efb),LL(0xc7b553e8,0x0df4d23e),LL(0x659d3ffc,0x434f38fa)}}, {{LL(0x55a0c931,0x1764115e),LL(0xa5c920a4,0x34ea18b9),LL(0xaf903710,0x6a099ddc),LL(0xe49f2c7a,0x4b937dc1)}, {LL(0x430f0a7e,0xacfc4a1a),LL(0x421dbe96,0x8f106a58),LL(0x1811d3fe,0x48ac7026),LL(0xb80f13c5,0x5484226a)}}, {{LL(0x8da7ca79,0xf692e17b),LL(0x718691b9,0x4827aaa2),LL(0x5c5ea68c,0x881f1c38),LL(0x88bdf643,0x1620f5d6)}, {LL(0x0b9a5add,0xe5703cb2),LL(0xbe925061,0x392e6ea5),LL(0xb0bab0d5,0x2a66ce20),LL(0xf98e8dad,0x83a8e0e5)}}, {{LL(0xdeec2329,0x53532223),LL(0x346eea96,0x6a740238),LL(0x1dde2a6a,0xa54afbdf),LL(0xf2b5b190,0x0e6ca8c1)}, {LL(0xf3cd4e46,0xcccaa3c6),LL(0x0eb7bb3c,0x168d66bd),LL(0x08d4f4e9,0xf1275144),LL(0x139811fc,0x2ae8c946)}}, {{LL(0xc870713a,0x4973c726),LL(0xba54b13f,0x298465ee),LL(0x940f224f,0x9f901403),LL(0xb9950a40,0x5cd6a07b)}, {LL(0x069a8484,0x9d4095e6),LL(0xd4f8831f,0xe6bf3181),LL(0x39243da8,0x37ceb29a),LL(0x2693653c,0xb3887f31)}}, {{LL(0x42c98a56,0x685d2172),LL(0x3969dd9a,0x350fbab8),LL(0xe8ac84ec,0x728edca9),LL(0x59bbb0c4,0xf42beab3)}, {LL(0x27d3c3fd,0x9793e746),LL(0xc732b37e,0xbf6016de),LL(0xdf0f248f,0x3688173a),LL(0x7ed59dfa,0x84fbd040)}}, {{LL(0xa6731b1b,0x2bad638f),LL(0xb7355979,0x1c7b4b13),LL(0xb8e77093,0xf21550e0),LL(0x53efc63c,0x14d0bc9d)}, {LL(0xd56e1f29,0x119ae9fb),LL(0x4d60bc5a,0x3511309c),LL(0xe3574e43,0xec654f06),LL(0xbef6aea2,0x2d6695df)}}, {{LL(0x5d6abff7,0x27ece611),LL(0x640c9ab8,0xa706d42d),LL(0x5a6f8fa6,0x7a7252d9),LL(0x349aaf8c,0x32be7195)}, {LL(0xff734e23,0xffb48a3d),LL(0x7d27b99c,0xa9b36c82),LL(0x0ccaedbc,0x85b7a57e),LL(0xc04f2394,0xb93b14fd)}}, {{LL(0x160700e0,0x3a3a78c5),LL(0x961e4af8,0xbd7ae60a),LL(0xd9472cd7,0xe1deb736),LL(0x3880bbbe,0x276b51b7)}, {LL(0x1aa99bfb,0xcf0c4b9a),LL(0x689d7f58,0xaf949d5f),LL(0x65f33328,0x00878488),LL(0xe7d7b484,0x0f1a178c)}}, {{LL(0x849e6d32,0xd44550f8),LL(0xfe16485e,0xe7bc29d4),LL(0x2f343924,0x29bbfec6),LL(0x40f2b5ce,0xeeb802f2)}, {LL(0xbbb64f33,0x2b337542),LL(0x9f9bdb3c,0x4c1d3a36),LL(0xc7a1cb88,0x1067cf3b),LL(0x4601fb6e,0x3f12a31d)}}, }, /* digit=8 base_pwr=2^56 */ { {{LL(0x1f8a4a91,0xb720a78f),LL(0x753dbe73,0x59e22211),LL(0xadd0991a,0x9f5ad99c),LL(0x7380726f,0x3a0db802)}, {LL(0x7dfb4f1c,0x37f0761c),LL(0x5ac819cd,0x68e7098a),LL(0x37ffe348,0x9683d610),LL(0x2b7b5140,0x5bf205e5)}}, {{LL(0x61a97262,0x9846b5f6),LL(0x974a82f7,0xedf2cacb),LL(0xaf439654,0x3dfab85f),LL(0xc724ee09,0x43fb0ef9)}, {LL(0x53b0119a,0xd0d5016f),LL(0x5bc8fc81,0x68445363),LL(0x1f65d298,0x6d10b649),LL(0x21a4e64f,0x0f3c88c6)}}, {{LL(0x7f34c517,0x320372a1),LL(0x2378bc27,0x5602bd16),LL(0x91aae024,0x666a592d),LL(0x317bbdaa,0x716886ab)}, {LL(0xe3045103,0xce55fe68),LL(0x7de1d701,0xf2c4b0b2),LL(0x7d724cb6,0x8da35885),LL(0x9ec47314,0x9aac623c)}}, {{LL(0xb8529a01,0x824cff46),LL(0x4856b95c,0x6e4d82a2),LL(0xc65af7f7,0x58c6b833),LL(0xae110e53,0x8a6c4125)}, {LL(0x4f083340,0x38207c30),LL(0x176cdb31,0x71aa384b),LL(0x42882de1,0x1ada2941),LL(0xc16a2e4a,0x38b1ad2e)}}, {{LL(0x142bcb30,0xbdda2720),LL(0xfaf604d1,0x56175263),LL(0xe6796314,0x086189c1),LL(0x5b04dd19,0xdab01c68)}, {LL(0xba8ed3c1,0xce54e4b0),LL(0xe281acfb,0xf616513b),LL(0x5e0a6319,0xaf179629),LL(0x328b587b,0x85e79ac9)}}, {{LL(0xc9fd7da0,0x11d84588),LL(0x1238d0c4,0xa78682d0),LL(0x829d6475,0x333ddde0),LL(0x69de9e18,0x80c88440)}, {LL(0xc6d8176f,0x5d15f21a),LL(0xa509d470,0xdaff9434),LL(0x8bbbfcd5,0x0191bb0a),LL(0x08fc2688,0xff7732b8)}}, {{LL(0x5ab3d89e,0x02fe772d),LL(0x9a786c91,0xf1580ec9),LL(0x5a323866,0x8fd83417),LL(0xbadec96f,0x93711d49)}, {LL(0x6b9b4a30,0x2020c34a),LL(0xb8b0de24,0xbf10e000),LL(0x28de3ce5,0x2a5f298d),LL(0xfe1a1c63,0x807a398e)}}, {{LL(0x73f7c45c,0x9fb640cd),LL(0x0afe059c,0xeb1f87ad),LL(0x52b168d4,0xa3c3979a),LL(0x7b1e403f,0x6eef460c)}, {LL(0x2724bb3f,0x6d943e50),LL(0xf9d922d1,0x53f3f1bb),LL(0xcd538b4a,0x547e7a03),LL(0xd2c4145f,0x37631e20)}}, {{LL(0xb1f810bf,0xe7e49922),LL(0xf2645825,0xacafdb0f),LL(0x15f35bda,0x0f22216a),LL(0xd85bd0b7,0x6f2b4d95)}, {LL(0xbedc9ecd,0x2f203db8),LL(0xb91e090d,0x26639ff6),LL(0x3486eb84,0x94cd6596),LL(0x42c05747,0x32747db3)}}, {{LL(0xcebfa9f1,0xcd3e7a52),LL(0xfb2b3007,0x5e792d76),LL(0xb9ecce81,0x9669523d),LL(0x04f191e1,0x9263cc85)}, {LL(0x69655fe1,0x192019c0),LL(0x4d984e59,0x1c5cc5eb),LL(0xdf33f336,0x9ad10ed6),LL(0x41d94897,0x0ca48387)}}, {{LL(0xf222476c,0xbd1ddf67),LL(0x12d6dc4d,0xb4ad7126),LL(0x93ed702a,0x5c327b18),LL(0xfa70cd9f,0x7e3a27b1)}, {LL(0xc0c4f415,0xdca750bd),LL(0x213a5d61,0x98197c90),LL(0x6f10fcc7,0x9bbd014a),LL(0x2ceed4fb,0xb06061e1)}}, {{LL(0xa8ad25f9,0xaf6dbbe2),LL(0x7ade697d,0xe70e9f40),LL(0x6eb872d7,0xb829e016),LL(0x1b04173f,0xc330e15c)}, {LL(0x0d4763d8,0xd4868e29),LL(0x4c18c9fb,0x37867f72),LL(0x28019486,0x5fd2f47f),LL(0xb16e9bdd,0xe6bfdf81)}}, {{LL(0x783e43c5,0xace2a977),LL(0x76eed46a,0xe1791288),LL(0xd1767739,0x3884a5b2),LL(0x427c50a3,0x14eddddb)}, {LL(0x1c9b1fcc,0xbeeed5ac),LL(0x4ecdb47a,0x50b1cb44),LL(0x0dcb78d5,0xcbf69555),LL(0xf2b17a99,0xe60bf9c7)}}, {{LL(0x9e9ade95,0x0edae6b0),LL(0xcb78b1e1,0xb5c6e13d),LL(0x1c257848,0x32860fba),LL(0xef7f5080,0xfc9aa9f4)}, {LL(0x32aac870,0xccef8508),LL(0xfb5310a0,0x4b237704),LL(0xfeebb972,0x4c3cf970),LL(0x763d5f67,0x5dd3c7a0)}}, {{LL(0xccbf29c6,0xa656797e),LL(0x5a76a56b,0x6d77f211),LL(0x0e3daff3,0xc627156b),LL(0x7646fb1c,0xa4bd37f5)}, {LL(0xa8cd3e5a,0x5fd7e286),LL(0x2f5fed51,0x3889951a),LL(0xe48c49be,0xf8186fc5),LL(0xc662ee38,0x0d3d308a)}}, {{LL(0x970e164d,0xb7c9bf06),LL(0xbd3d3087,0xc27a88d8),LL(0xf4e7c899,0x8a37c9cd),LL(0xab411371,0x18494d5a)}, {LL(0xd9d8b29c,0x06532375),LL(0x915a2f74,0xb92dd45c),LL(0x515acb02,0x8a23f6bf),LL(0x435bfa89,0x0e69248c)}}, {{LL(0x6866c5e4,0x8bf41ec3),LL(0x0999159d,0xf059e652),LL(0xd29d7cd8,0xf906838f),LL(0x3a269735,0xc30100f6)}, {LL(0x6280e70b,0xb7742bc8),LL(0x867b54e1,0x0067d971),LL(0xf544622a,0xafe9032b),LL(0x118a2042,0x6b441e39)}}, {{LL(0xcdd66b70,0x905c8655),LL(0xc1e2110d,0xe88cce1b),LL(0xee674093,0x8cc23c0c),LL(0xb2ea3fc3,0x55ded4d9)}, {LL(0xb58dfbed,0xdd14502b),LL(0x49f698f8,0x523a4dd9),LL(0x01c83e5a,0xf843a501),LL(0xfe71ee1e,0xf11fd4c1)}}, {{LL(0x162d7c0b,0xeedd7229),LL(0x4ccad713,0xd42d6a9e),LL(0x2b0c7b93,0xa082fffd),LL(0x2a5016b9,0xee3abd48)}, {LL(0xc117e22b,0x5079c95f),LL(0x814b8666,0x5d4b9169),LL(0x9bf90a6d,0x9e0f5e87),LL(0x744bf7ab,0x4346bd29)}}, {{LL(0xbfb551b6,0x4d85af0e),LL(0x31f7a958,0xb48e3da8),LL(0x6f5bc50d,0x3b474ce6),LL(0xe7c8dced,0x9fdb47bc)}, {LL(0x53003272,0x2064450e),LL(0x839e69da,0x6bb230f3),LL(0x4d822be5,0xb6941512),LL(0xf11a9dc1,0xb51bc6aa)}}, {{LL(0xb23047dc,0x866447f8),LL(0xe5f52c2d,0xe02dbd63),LL(0x02770a76,0xe6ea43cb),LL(0x56fa6c25,0x853f5fe3)}, {LL(0x960de6d5,0xfe9615f0),LL(0xf4b1b945,0x37c8b0c8),LL(0x4618629d,0xa6e83805),LL(0x23a2ac61,0x38fb5264)}}, {{LL(0x01751c20,0x5dfd7005),LL(0xce72773a,0x7e100245),LL(0x0776794a,0xdf09f92a),LL(0x1b730fdc,0xc4a8de81)}, {LL(0xf0c7b031,0x72c302ab),LL(0x1283913b,0xdddff68e),LL(0xe32517b5,0x24889098),LL(0x856a2934,0x2483a0f5)}}, {{LL(0xa1c3d56d,0xdf6d7dcc),LL(0x09afb797,0x07f9c00b),LL(0x083d9557,0xe90da23d),LL(0xcbc03826,0x80ae6e53)}, {LL(0x7c0e1b23,0x1fd6ff6d),LL(0xb1100226,0x1e90f3c8),LL(0x05a24e23,0xf179e00e),LL(0x946f16bd,0xe5361efe)}}, {{LL(0x4c662091,0x50f12e4a),LL(0x28608585,0xdad2c7a3),LL(0xf7429473,0x55c66749),LL(0x045ea1b4,0x440b77de)}, {LL(0x91229927,0x9f707b49),LL(0xc6725715,0x3501e29e),LL(0x1225a8e6,0x5626fabb),LL(0x9507e709,0x270a9c2b)}}, {{LL(0xbdcb9039,0xe0d629da),LL(0x20255b7c,0xb4d7cd22),LL(0x5ed874a6,0x10c8614b),LL(0x4e67d406,0x36891e70)}, {LL(0x1dce66fe,0x020da834),LL(0xabd64dea,0xae69e1e7),LL(0xcc71b37b,0x9cf153a1),LL(0x44771c7e,0xa6e9d024)}}, {{LL(0x8840fc17,0xb15e31c7),LL(0x349124a4,0x57853112),LL(0xbac542ee,0x78a9d807),LL(0x38fe1188,0xe7b4d812)}, {LL(0xb3a3b801,0x874adc70),LL(0x4694cec2,0x80c0e02a),LL(0xe97805e1,0xd05c8c0e),LL(0x89d8cd40,0x8eaebceb)}}, {{LL(0x378d055f,0x888c777b),LL(0xb104a132,0x6956795e),LL(0xbe8472d7,0xe4bce719),LL(0x5f51729e,0x23c9f0bf)}, {LL(0x36a3bf3e,0xfe7f7e19),LL(0x20a32d37,0xf8f5d2ca),LL(0x93b8a344,0xf383b467),LL(0x27a6e2c5,0x7eab76f5)}}, {{LL(0x93b54bc1,0x86c31b0e),LL(0xfc4ecab2,0xb9405ea9),LL(0xa0f6d341,0x09485578),LL(0x4b77e8e7,0x88053bb8)}, {LL(0x29a07ddd,0xcde9b777),LL(0x97649102,0xec8ea63f),LL(0xc516777a,0xf74d082a),LL(0xbacf0dd3,0xf4e26d89)}}, {{LL(0xd0b3b578,0x6a919da8),LL(0xa0b5f7d8,0x0bcc3b29),LL(0x9e55924b,0xbf4565e5),LL(0x7889dbb6,0x13b36187)}, {LL(0x533981bd,0xad0e59c6),LL(0x0bd0cb7a,0xea941b62),LL(0xa9e7aa7c,0xe5e35e9a),LL(0x088bfd7d,0x27f61727)}}, {{LL(0x8b3c7fbc,0xda2a5a20),LL(0xba55cb48,0x33cdd403),LL(0x90e7ff36,0xb72b51cf),LL(0x6f215840,0x8cc4b553)}, {LL(0xd2671224,0xf7b80ad9),LL(0x6a45436b,0x560b4387),LL(0xff9e8fae,0xdca90694),LL(0xf97aa84e,0x2e7e9546)}}, {{LL(0xf37cd717,0x71e9ff45),LL(0x0d73e98f,0x6edf335e),LL(0x9f715170,0xf355690c),LL(0x3f5a82bd,0xf74df40b)}, {LL(0x95e5b105,0x28b6d931),LL(0x2841a54c,0x8827f47c),LL(0x62b4312d,0x159cb943),LL(0x8db37edb,0x277943d7)}}, {{LL(0x6113a9f8,0x561454fd),LL(0xe70e67e6,0x78ebe733),LL(0x903f2feb,0x8764360b),LL(0x97902f36,0x2ba3b3d8)}, {LL(0x87490b8a,0x28808cef),LL(0xf05f31b3,0xb1175954),LL(0x6c9b4f4d,0xbd5d6005),LL(0xdd254e60,0x12b13fca)}}, {{LL(0x14959566,0x38d4e812),LL(0x36fe9a6c,0xe253b750),LL(0x809450c1,0x24b2c81a),LL(0x8fec36b1,0x0aa89966)}, {LL(0x053e97e7,0x9a99deb5),LL(0xe31d3a6e,0x5e57321c),LL(0x8dbe78a2,0xcd7a4f33),LL(0x3299e070,0x9f809d4f)}}, {{LL(0xa26a9eca,0xd6de8cfa),LL(0xa158a735,0x33d5705b),LL(0xc2293743,0x08dd3fcc),LL(0x68bbbaea,0x1f8d0a46)}, {LL(0x61bc4105,0x53ff76f9),LL(0x7c4a8fc9,0x6445e88d),LL(0xc285d0e6,0xfd9a8d04),LL(0xfe62b449,0xf08d0d6b)}}, {{LL(0xc062810c,0x08c27292),LL(0x6663fa28,0x955629f6),LL(0x9d86fee8,0xbaf96c0e),LL(0x46bb9894,0x1dbc5406)}, {LL(0x93dd45c7,0x8d6b6207),LL(0x3ee989fc,0xaf3baef6),LL(0x59b7b2f7,0xf66cfdb1),LL(0xda16c637,0x287fc2bf)}}, {{LL(0x2d71f863,0xa44ca8fa),LL(0x84d5dee5,0xa1161962),LL(0x3957b610,0x5a5c8ce3),LL(0x17f50b57,0xdbb32253)}, {LL(0x76056358,0xc6a4eb7d),LL(0xc359d90f,0xff9eb424),LL(0xa88cb38c,0xdf4afe23),LL(0xa696b75d,0x2ae727cb)}}, {{LL(0xd20a58c8,0x47cc63ef),LL(0xc492ab36,0xd319dc3a),LL(0x36c7f76e,0x887a7d83),LL(0xfcd4cf49,0x65ed5e3e)}, {LL(0xda301d39,0x0e6f2f34),LL(0x38ad4533,0xf2f7c102),LL(0xae834622,0x8a3a003b),LL(0xa060a0d4,0x94084169)}}, {{LL(0x13c8a1eb,0xb673168b),LL(0x459f8da1,0x80109609),LL(0x5c82007b,0x68003fa1),LL(0x248e0430,0x9f634159)}, {LL(0xfb9b6510,0x188156ab),LL(0xe62844de,0xc35be1cc),LL(0xb0c84d39,0x21e8f908),LL(0xdad3ae53,0xa886d3eb)}}, {{LL(0x82b0f5fd,0x9e20cd56),LL(0xc465c721,0xc0c12f0b),LL(0x6f913a6e,0xfeeb1051),LL(0xaa32d6fe,0x9e7c76b9)}, {LL(0xb8637b5f,0x820b49a0),LL(0xf4abccf0,0xe9ae172a),LL(0xfb270e67,0xccc050b1),LL(0x2269d1de,0x0b51d7e3)}}, {{LL(0x678c8d8b,0xca772ec1),LL(0x77ae7c7b,0x74eea3f8),LL(0x1e1bcbd3,0x51550df1),LL(0x3458b249,0xa931c17c)}, {LL(0xf204aed5,0x192c3a45),LL(0xc993c881,0x93abf63d),LL(0x83421891,0xc60aa2cb),LL(0xf6b70284,0x11ce6735)}}, {{LL(0x69e152e4,0x53e8a3ee),LL(0x0033da23,0x6889ece0),LL(0x7d585418,0xada56904),LL(0xf5e5abb9,0xaf81a877)}, {LL(0xdf515727,0x36e0267d),LL(0x3daad2a9,0xe04b532d),LL(0x1a11ced6,0x290e3ee7),LL(0x65e7a651,0x5be7c429)}}, {{LL(0x8ef9b498,0xc0662cd3),LL(0x6c4dcbf9,0x0ec5fbf0),LL(0xce4d7e3a,0x26694c70),LL(0xfa52de99,0xc1699a93)}, {LL(0x6dae3e97,0x2e0d394b),LL(0x4c66e572,0xe3af28cf),LL(0xba1e27e4,0x9caf7bf8),LL(0xd5a4bdaa,0xd5c39337)}}, {{LL(0x9ec8ad6d,0xbb5d9551),LL(0x609fc2e1,0xfb3bc1f1),LL(0x95fe12b5,0x0d95ad2a),LL(0x5341dc74,0xf6fd6e89)}, {LL(0x7537b803,0x1532991e),LL(0xeaf96f9c,0x77772fd3),LL(0xf832749a,0x4ed09840),LL(0x95f19d25,0x69a194ce)}}, {{LL(0x041cc340,0x5464471a),LL(0x1c442289,0x26f7e550),LL(0xb5ce9706,0x38f2c20e),LL(0x8a44efd3,0xcf73f8f2)}, {LL(0x586e8f77,0x5176eda5),LL(0x63ece447,0x47e33844),LL(0x86b00be2,0x83826e8f),LL(0x539807b7,0x49cffcdb)}}, {{LL(0x414d3fb1,0x543d1fad),LL(0x38b1ef44,0xd56aac6a),LL(0x96c89050,0x9980bb64),LL(0xb169b8a9,0xc300cb46)}, {LL(0x83413df4,0x5ab01a6b),LL(0xf3c91eda,0x179b8922),LL(0x43cccc06,0x4060b943),LL(0x9458ec1e,0x4f6adeb5)}}, {{LL(0xe339e40e,0x0a4c6437),LL(0x02aefe83,0x9cb6c532),LL(0x23dce7ea,0xb072d02b),LL(0x59a9032f,0x2cd7b117)}, {LL(0x81dbfaef,0x01220cea),LL(0x0905332d,0xffe0026c),LL(0x0197adff,0x95ec2cb2),LL(0x4c3d0e49,0x853bf6f5)}}, {{LL(0x25d78f7c,0x04ed54fb),LL(0xbb68cb9f,0x45aae3e1),LL(0xe32d7421,0xf4f1a2c6),LL(0x45a05771,0x646ade65)}, {LL(0x91eab45e,0xab241cfa),LL(0x7b214af0,0xb1cf204c),LL(0x851d311c,0x92dfb3e3),LL(0x144ae0da,0x56479ffb)}}, {{LL(0x9a7a4ede,0xbf847444),LL(0xf5cfd20f,0xb26b1f15),LL(0x83b33b64,0xf380ed7d),LL(0x3d1998c9,0xa21f9564)}, {LL(0xa720e347,0xd985c7d3),LL(0x8bdf09d5,0x98078974),LL(0xce947692,0xa1f34ce2),LL(0xf419c385,0xf69e6144)}}, {{LL(0x8c3adcc6,0xe1926526),LL(0x42746263,0x848974fb),LL(0x97791569,0xa731261f),LL(0x065b721b,0xfed39da2)}, {LL(0x836a7e20,0x8369b04c),LL(0x53c19f62,0x5758a761),LL(0x0ebea868,0x45746383),LL(0x3b7d71a8,0x20179927)}}, {{LL(0x57632243,0xb466ed4f),LL(0x120577c9,0xc8d918cb),LL(0xeda40e9c,0xbab307e5),LL(0xd5f65d1b,0xe6dbc7d4)}, {LL(0x60619e10,0xcae0c649),LL(0x6b0df67c,0xffddf6d1),LL(0xb32ee5d1,0x60488755),LL(0x47164a55,0xcb278aaf)}}, {{LL(0x0bfb732d,0x354c3392),LL(0x649bc125,0xcd4fc821),LL(0x770ffdb8,0xa8e1253f),LL(0x0ff0c37e,0xf7eec595)}, {LL(0x7149b102,0xe5a65279),LL(0xd0528224,0x1cbbb56b),LL(0xb51c5df4,0x40b1a8d9),LL(0x39e1ca25,0xccb43d26)}}, {{LL(0xfdcfe8c5,0x48f74dc2),LL(0xfa5b8daf,0x3ccb31b6),LL(0x7de6300f,0x6f8dc5bc),LL(0xf247bc0b,0x2a373fd3)}, {LL(0x17825306,0xefe13539),LL(0xc50c47b4,0xeb253484),LL(0x3c739f02,0x4a7f2af3),LL(0x9a3c6746,0x3a3eb385)}}, {{LL(0x588978e2,0xa90afa2a),LL(0x8d80894f,0x501fcebf),LL(0x6bf1a4cb,0x1de1d06d),LL(0x6cc42a07,0xb0f4a61d)}, {LL(0x78d406f0,0x975cb8de),LL(0xe3d293e3,0x560b0d7b),LL(0x32e686ca,0x5746227c),LL(0x3fcb0205,0xd12854f5)}}, {{LL(0x499512e3,0x8c0eaba8),LL(0xade99108,0x8d97c229),LL(0xff2b5782,0xd80da38e),LL(0xaef08107,0xf8c30ba1)}, {LL(0x076b97c3,0x9068d7d0),LL(0xb1b7eba5,0x851d1cb9),LL(0x318e4675,0x02bb728c),LL(0x76ddc683,0x0efe9707)}}, {{LL(0x6a248b04,0x6985d358),LL(0xf8969ed1,0x75eb6019),LL(0x606a0c64,0xecb66a20),LL(0xfe39b5e5,0xd1252f64)}, {LL(0x2aa222a9,0x93d5d61c),LL(0x1ffff8ec,0x16c0d6f9),LL(0x5dfab0fe,0x0f1f962d),LL(0xcedcccb0,0x88776fe1)}}, {{LL(0xa32cbff1,0x410333c6),LL(0x093bcbda,0xca13ce28),LL(0x0e479259,0xd97b0684),LL(0xbf505c93,0x8b2b3ad8)}, {LL(0x71761412,0x42092d64),LL(0x918acf33,0x9d0c842d),LL(0xac9ade57,0x904d3add),LL(0xe0d5ef6a,0x025e4177)}}, {{LL(0x0b33d4ed,0xce406ec0),LL(0x57b5c958,0xf73ac4da),LL(0x6ef70849,0x5f96cb8c),LL(0x77b32d5d,0x702ccc6f)}, {LL(0xcea6885c,0x75bda8d8),LL(0xc0c0432e,0xbfc3e62e),LL(0x54631c9a,0x46db9cc6),LL(0xba1d1550,0x1669075b)}}, {{LL(0x2d227656,0x5ccc4e34),LL(0x02cb0644,0x0724e41b),LL(0x435601fb,0xc5e2077d),LL(0x68d6aee2,0x356155c5)}, {LL(0xfde58906,0x0ea00013),LL(0x37a9eda4,0x79fa13c3),LL(0x8f51a6a6,0x7d09479d),LL(0x1f979fed,0x86e955b7)}}, {{LL(0xe39ab804,0x9cb22960),LL(0x03535a39,0x6aeae783),LL(0xb9909be6,0xeb4741de),LL(0x1a5f4139,0xb957c5da)}, {LL(0xedc1819f,0xafdb3e8b),LL(0xe7caa690,0x33545722),LL(0x8bb66ed0,0x0ef33e28),LL(0x70e667b5,0x59073742)}}, {{LL(0x5c7773b8,0x0390fb3c),LL(0x286a809d,0xb80b4a2f),LL(0xfac46467,0xd17d6103),LL(0x91a48972,0x9a09a0d6)}, {LL(0x39e44585,0xa2124b62),LL(0x174d241a,0x14c8a671),LL(0xada8ba26,0x99abfa37),LL(0xfbb457ae,0x847f3040)}}, {{LL(0x7529a18c,0x0587aaa4),LL(0x9bb45ee6,0x23b3f724),LL(0x2aa81155,0x4d7f5712),LL(0xa4f16d09,0xa9185804)}, {LL(0x3fc992d1,0xab638141),LL(0x0cad0bb0,0xb6c326fa),LL(0x60f2cb10,0xe21c3625),LL(0x2fac20a9,0x6c7af09e)}}, {{LL(0xdc6f72ab,0x31e892fa),LL(0x21b81f7b,0x71d5c6a3),LL(0x298a0dd2,0xc3e2d70d),LL(0x13ecdc80,0xbc0c37e2)}, {LL(0xe6496ba4,0xd3191146),LL(0x35115466,0x15f81541),LL(0x07d1937f,0x162be77d),LL(0x7b176367,0x38b4d194)}}, {{LL(0xb8cafbc9,0x4485966d),LL(0xf44c2a81,0x7cfc0d67),LL(0xe624cefe,0xe9e7ec4d),LL(0x581d4e48,0x4db8bec3)}, {LL(0x7fc8615a,0xe76edf00),LL(0x9a02cdb8,0x1b62c4a5),LL(0x83938a6d,0x8b565749),LL(0x50c86c19,0xd813864e)}}, {{LL(0x16f55d40,0x7fc071ef),LL(0x9bb45ea5,0x70195438),LL(0xa35543ca,0x83cf09f2),LL(0x20554c19,0x07e91a84)}, {LL(0x62a9d06e,0x51ecd701),LL(0x2044a663,0x00e14c62),LL(0x00423dd9,0xb1317c13),LL(0xa46eab4c,0xf49431bc)}}, }, /* digit=9 base_pwr=2^63 */ { {{LL(0xd0614aa1,0x35118434),LL(0xd1418434,0x8bae9779),LL(0xb8c15b89,0xf5641d82),LL(0x416432eb,0x2383af56)}, {LL(0x2c73f990,0xa552d3f0),LL(0xa6bbdc7d,0x8df82e9e),LL(0xd75ec634,0x0f336aa8),LL(0x1603e53f,0xc42e3b2d)}}, {{LL(0xbad830d2,0x4b33e020),LL(0x590dffb3,0x5c101f9e),LL(0xbc80ecb0,0xcd0e0498),LL(0x52aa293e,0x302787f8)}, {LL(0x220f8fc8,0xbfd64ced),LL(0xbe0ee377,0xcf5cebe0),LL(0x8913b128,0xdc03a038),LL(0xfde23279,0x4b096971)}}, {{LL(0xd2d638ad,0xb0f8c0de),LL(0x4f299d5f,0x47fc8c77),LL(0x9b68d48e,0xd1720a92),LL(0xa1c6f103,0xf944e708)}, {LL(0xa146889b,0x36e34e04),LL(0xe74a2a28,0xb0aad2d6),LL(0xca52f53c,0xedbb034b),LL(0x87fb2713,0xe987a8e1)}}, {{LL(0xf727ef3a,0x6c5389af),LL(0x33db88fb,0x95ffeb95),LL(0x9dae0777,0x27cb7042),LL(0x616dbf02,0xd20afe81)}, {LL(0x914bf706,0x0fab8e18),LL(0x0517cd09,0x3b1e66f3),LL(0x12e40644,0x24b46dce),LL(0x08f2d8fa,0x0ff10168)}}, {{LL(0xea2d8d84,0xe08a10df),LL(0xe97dda79,0xe31f05e7),LL(0x4e9ab132,0xfe95f84a),LL(0x927e216f,0xacd6f7fc)}, {LL(0x83c5a3ea,0x025e27bd),LL(0x50f120fc,0xed010c0d),LL(0xb828101f,0x443b3b8a),LL(0x8cfc0dea,0xd8384819)}}, {{LL(0x83dc5447,0xe55f34c8),LL(0x04e4e9a0,0xbe76243b),LL(0x819166a2,0x78fb4cbc),LL(0xae37f80a,0x0bdfb703)}, {LL(0xc217cda8,0xf869288e),LL(0x62af4156,0x2662bb71),LL(0x50ae9d30,0xce64f291),LL(0xdc0353c9,0xee0d4440)}}, {{LL(0xbd25609c,0x3e61a9ea),LL(0xb3839c8b,0x4ccaea93),LL(0xe43736e2,0x721cefa3),LL(0xd0035908,0x229cb244)}, {LL(0x7f10aebb,0x936bc1dc),LL(0xb67332e7,0xc93a1002),LL(0xf98d1132,0xf4b53dd4),LL(0xd5a75030,0x7b99a196)}}, {{LL(0xca9a9526,0xb13caadd),LL(0x69a303e9,0x701c63fa),LL(0xb0a50f3c,0xb97d667a),LL(0x68e6557f,0x27c03d7c)}, {LL(0xeb105607,0xab24e712),LL(0x8dd86ccb,0x4936aedd),LL(0x0a986d68,0x32196f8a),LL(0x248f5a65,0x0307b826)}}, {{LL(0xfcadb2ad,0x20e14b4c),LL(0x8c3b8c23,0x4cb4a092),LL(0x1caa9db1,0x50fe3c1a),LL(0x81c0a4e9,0x23cc56e8)}, {LL(0x0867753f,0x5ab09199),LL(0xf9d47c55,0x5a253d19),LL(0x1a9bcc88,0x422b4e03),LL(0x671e4f36,0x4e1ce22b)}}, {{LL(0xebbe949f,0x588f58b5),LL(0x6982215b,0xb7762296),LL(0xcff863c0,0x3cc83dd6),LL(0x01098f51,0x81ec094d)}, {LL(0xbe0432d0,0x214d69aa),LL(0x6455957d,0xe4e52a9c),LL(0xfadc1eab,0x94743ba8),LL(0x8176316f,0x2c395d97)}}, {{LL(0xe6bb4d34,0xeab6400c),LL(0xc0d49bf2,0x7364dc55),LL(0xe6959c7e,0xd6fa6e40),LL(0x7eaae61c,0x7960a997)}, {LL(0x94ea77c2,0x918b3c63),LL(0x76866dd1,0x2cf4997f),LL(0xbcbba8ca,0xc4214abf),LL(0x7aa4aab2,0x349a6133)}}, {{LL(0x99458b24,0xd64bab77),LL(0x2eba3064,0x6fe19e25),LL(0x74068f03,0x9aabd83d),LL(0x6fdf8655,0xaef81218)}, {LL(0x65593fef,0xf506d27b),LL(0xfaa457b2,0x0a1ad85d),LL(0xa303dff4,0x266d0f06),LL(0xabb416e3,0xe8114f4e)}}, {{LL(0x6aa5a1b8,0xe743f617),LL(0x1b5b2bd6,0xaf84652d),LL(0x092e2c46,0x8b1beab1),LL(0xe2518383,0x7e857549)}, {LL(0xa9383124,0x6be2ece1),LL(0x7fc20081,0x8309442a),LL(0xc3046cab,0x1f00eb8b),LL(0x26f39f8c,0x959f3155)}}, {{LL(0x8fc2ed93,0xaacfe2d3),LL(0x78f0f858,0x83446645),LL(0xdda35ec4,0x58de6f09),LL(0xf78c69b1,0x891e5ecd)}, {LL(0x91c13d67,0xff4a4ba9),LL(0x487d5575,0x6e78063d),LL(0x8d303a7e,0x226b621e),LL(0xc95987ed,0x5c9bc103)}}, {{LL(0x5e3be13e,0x28980108),LL(0x414af955,0x5e8c0ac5),LL(0xeaaa71a5,0x0f08e93b),LL(0xce4524f0,0x1bc50407)}, {LL(0x921be66b,0x6a6a2e6a),LL(0xc27da9f2,0x37113baa),LL(0x52e90e29,0xc7b3c636),LL(0xc8558307,0xc075d178)}}, {{LL(0x88a45b65,0x605f581a),LL(0x68e58c1c,0xcb789200),LL(0xbc5bfe1c,0x14cbed65),LL(0xf02b11d7,0xd1af7dc7)}, {LL(0xcd3a7cc8,0xb8341bc0),LL(0xa01a77b7,0x8e9aefe8),LL(0x5ae2a402,0x8eeafe87),LL(0xc11f3859,0x27a0698f)}}, {{LL(0xf7af9756,0xc5e49f07),LL(0x9e5b871f,0xffd65bcc),LL(0x423eed7b,0x62a95357),LL(0xb2ec687c,0x93cf64d5)}, {LL(0xbe5da479,0x04b87dd7),LL(0x1a134c0b,0xdcceabd7),LL(0xc5c6925c,0xa4875091),LL(0x8e9c098d,0x3bf947df)}}, {{LL(0x11d1323b,0xb2617271),LL(0xe4c6046d,0x7769247c),LL(0xcfa6aac3,0xf9c1aaab),LL(0x354492e2,0xf7f13317)}, {LL(0xe91befb6,0x4bd65afd),LL(0xf25b8f8d,0x3e78cd8c),LL(0xe60ff4d9,0x2adf53ed),LL(0x3d288d4c,0x81ec3853)}}, {{LL(0xee3bf44a,0xda852a71),LL(0xd7b5c6da,0x39b4ef6c),LL(0x44f4e720,0x472e6996),LL(0x9191614b,0xbbd19d38)}, {LL(0x30c0e99d,0xa2bcc2ec),LL(0x57ba0582,0x29318d7b),LL(0xd315963a,0x322faf40),LL(0x0c0619d1,0x49ba5570)}}, {{LL(0xe5dcd066,0xc28c1f81),LL(0xff9e3493,0x64d1268d),LL(0xbdf8992c,0xab0db38e),LL(0x320cce30,0xe3790c26)}, {LL(0x26e3e4b0,0x59b408a0),LL(0x6ab8504e,0xe9e5fe29),LL(0x83c9eaf3,0x45c827bd),LL(0x89518edb,0xc298e236)}}, {{LL(0x8d3ab381,0xb79a8b15),LL(0xdb0bb7c0,0x6bb951e8),LL(0xbe4b3353,0x5ebd3854),LL(0x2eb3b0fe,0x107ba27d)}, {LL(0x46786cb4,0x9d01654d),LL(0xcf3a1aa2,0xf46d8352),LL(0xa1662f72,0xa8f669a0),LL(0x68a1d3e1,0xc979209f)}}, {{LL(0x65471473,0xc64975fa),LL(0xff1f2aad,0x1f8eec02),LL(0x8d0dd401,0x1b520fcc),LL(0x15e14346,0xcd732092)}, {LL(0x8f878a76,0x616478d8),LL(0x7423e0f5,0x3579d49c),LL(0x1b2af15f,0x119f6d6e),LL(0xb08c2c8c,0xbbe33d81)}}, {{LL(0x8534a355,0x051d99c9),LL(0x458b764b,0xe3f3ddd3),LL(0xbc8c03bd,0xbd7e51aa),LL(0xe8d42e38,0xcd7abf4a)}, {LL(0x3160e63f,0xf0d97428),LL(0x34d13871,0x258bba07),LL(0x3dcb885e,0x4fedb647),LL(0x50f0a645,0x009fca27)}}, {{LL(0x99775c4e,0x3f06c146),LL(0xf66e7d05,0xb10a4ed3),LL(0x3a3ab903,0x9300e3ca),LL(0xde3c3e1f,0x0a5610e0)}, {LL(0x1af56fb7,0xe2827312),LL(0xd75d9a9c,0x7e2a2365),LL(0xf11f8963,0x9c3bb05a),LL(0x30c80488,0xdf94cac7)}}, {{LL(0x2d1143f5,0xaff1682f),LL(0xb4d6ed7f,0x5837e83a),LL(0xb4bce662,0xf3e179be),LL(0x8caa5fbb,0xfa8d7862)}, {LL(0x59ea54c1,0xbdde016f),LL(0x3c1ac962,0xc488c829),LL(0x14b46863,0xabe8b367),LL(0x82897d1a,0xbcfde363)}}, {{LL(0x8c152354,0x87ddf0ec),LL(0x7a953398,0xdec85db7),LL(0x0b57108f,0x927a8b10),LL(0x525f78f2,0xb38b732f)}, {LL(0xeb306d56,0x7e696084),LL(0x50269227,0x9befefef),LL(0xcaddfa11,0xfa86e376),LL(0x404be227,0xd50a08da)}}, {{LL(0x03bb523c,0xb7408e33),LL(0xc093aaf1,0x6d21aa4a),LL(0xa85d6fcf,0x52aae4c9),LL(0xb726afa9,0xf5d057c9)}, {LL(0xf92ca5b2,0x7979bb5c),LL(0xc4e3e4f3,0x4b1f7936),LL(0x071ec517,0x2c534200),LL(0x67d3f86a,0x47b52ffe)}}, {{LL(0x84d1c5b2,0x4a0b581d),LL(0x0dfa90cb,0xfc825a4a),LL(0x11c72996,0x2df2ec98),LL(0x7dde922e,0x82077a6e)}, {LL(0x9f28b584,0x89acda10),LL(0xe49fe66f,0x54578eb8),LL(0x4a1c29d7,0x90a5f700),LL(0xb3b44748,0x2de4719c)}}, {{LL(0x18d85e6b,0x6944fe14),LL(0xde7b904f,0x90bd8208),LL(0xa4597137,0x5811f3b6),LL(0xd4ab5433,0x7ea43767)}, {LL(0xa204a36f,0x7ec39109),LL(0xa30fb76e,0xa43a4a57),LL(0xe090f2be,0x4fd514f8),LL(0xda1c97f8,0x3918138e)}}, {{LL(0x15145a20,0x2b466ae2),LL(0xfbac86b7,0x28ccb2ce),LL(0x04106b98,0xb891b707),LL(0x29696a08,0xe40a2310)}, {LL(0x636d9e11,0x1210fed0),LL(0x2043caa1,0xdaea218d),LL(0x0aef7dcd,0x10c2ed0f),LL(0xffa5db7b,0x926be98a)}}, {{LL(0x36abac30,0xe762191c),LL(0x8b75b5cb,0xe21acfaa),LL(0xd180cc32,0x4f5e6b9f),LL(0x55deffdd,0x01358309)}, {LL(0x992a66f3,0x1b1ab943),LL(0xceef1a9c,0x1ebe0246),LL(0x7a01dcb9,0xa24c9e25),LL(0x326505f5,0x3d45c4e3)}}, {{LL(0xc8544885,0x9b805759),LL(0x7bfcad78,0xbe9b99ca),LL(0x2b8fe78e,0xd1db36e1),LL(0xd5387bcf,0x37255a2d)}, {LL(0xa150ad32,0x044b3a3e),LL(0x6671ae59,0xc65bc2a3),LL(0x1d52384b,0x41ce078e),LL(0x9e72c300,0x3115f1b1)}}, {{LL(0xd0a358a0,0x487ff9da),LL(0x9c242aec,0x4b20c369),LL(0x1c7b145f,0x7813a44c),LL(0xd6f2d3ee,0x87c6bede)}, {LL(0x47d393b1,0x34d2a89b),LL(0x73f78679,0x1e9f97c6),LL(0x2edce91c,0xcb614fe0),LL(0x7e9a5fa9,0x62b96009)}}, {{LL(0x58c34b85,0x7eb2aeb5),LL(0xcf5074fc,0xa256a478),LL(0x98c1de9b,0x73f23a56),LL(0x61ce6535,0xeffd490e)}, {LL(0x4a6c15c8,0x2569df2a),LL(0xfffc97a5,0x91e202a0),LL(0x28dc7a57,0xd83c428e),LL(0x9fc8dca8,0x03bc53c7)}}, {{LL(0x9b60487b,0xed394cfa),LL(0xb483a686,0xa4259f91),LL(0x179a5cca,0x11f51779),LL(0x86c1d1c7,0x00b00ef0)}, {LL(0xf1231aed,0x6e596d2a),LL(0xd80eaa89,0x6c1a702b),LL(0xd23f1d64,0xd28f8c15),LL(0x6d01728f,0x93e85bea)}}, {{LL(0x1c704922,0xd4288fb5),LL(0x8c1363c5,0xaadd1968),LL(0x52f2cc4e,0x9b5c42d7),LL(0xc298e794,0xf9e4bc96)}, {LL(0xaf0804ac,0xd604f076),LL(0xb3bb2628,0xa441140a),LL(0xd37bf6bd,0x761eabca),LL(0xbe1cf79c,0x7d192922)}}, {{LL(0x3da7073d,0x2365739e),LL(0x8e2c078f,0xfb7423ea),LL(0x3adfb6f3,0x08f5132e),LL(0x710a26fe,0x470a4205)}, {LL(0x2b6c9b33,0xbe0afeb4),LL(0x3cd813bf,0x94d9edc8),LL(0x440a1699,0xa2c7a7a0),LL(0x4eaf0c10,0xbdc4ea3b)}}, {{LL(0x52fdc8d3,0x5a5455db),LL(0xb2945868,0x60485f39),LL(0x00af0abe,0x54ce9567),LL(0xe8d15f54,0x17bff77b)}, {LL(0x0e14a7ec,0x0021c531),LL(0xdc9c800a,0x3efdb22d),LL(0x4d947ada,0x9a9e2747),LL(0xb37fc947,0x19417bc4)}}, {{LL(0x8f02c551,0x71ca8da8),LL(0x074cebc0,0x782d5da4),LL(0xc1a43a2d,0x99094980),LL(0x24890d9b,0xe1b02ff0)}, {LL(0x45d82f7c,0x4eedaddb),LL(0x5061c943,0x7ae170a5),LL(0x4d47c578,0xaf8c7ea0),LL(0xad3a6eae,0xcad17044)}}, {{LL(0x4f4c9c8b,0x51383e61),LL(0x9182fc81,0x78d17182),LL(0x90d72cb4,0xbed6f0d4),LL(0x7bea62f0,0x98761291)}, {LL(0xef3cd3fc,0x27594570),LL(0x91a8c364,0xf4759534),LL(0x2744eb2d,0xf5c607c5),LL(0xd8d8f337,0x0d6264eb)}}, {{LL(0xa8701750,0xb54867a6),LL(0x87691191,0x1387e940),LL(0xbd2f75dc,0xc451f178),LL(0xd1da6080,0x31a099d3)}, {LL(0x49f87f03,0x0d0fcf97),LL(0x0af6273d,0x0b7585f8),LL(0x1142265d,0x3619cf2c),LL(0x05c559a4,0xf84d3f96)}}, {{LL(0xb83f2cb9,0xc3d3c80e),LL(0x8f602141,0xf4ef0b54),LL(0xb9612928,0x3afb343d),LL(0x8db5c907,0x7abe5620)}, {LL(0xcf019b08,0xcd692215),LL(0x9ae12255,0x98d70b38),LL(0x8dfda5f2,0xb459e256),LL(0x8f3f403e,0x066a445e)}}, {{LL(0x423fbbb6,0x5663e123),LL(0x5424d48f,0xcc55ce36),LL(0x3b6d5467,0x8bca99b9),LL(0x316fc956,0x299ff0ea)}, {LL(0xa0ceb256,0xd973a8d8),LL(0x6d9956b9,0x443ecdb9),LL(0x2f64f912,0x8c16a75d),LL(0xbbf7ab50,0x89e490c2)}}, {{LL(0xb8dbf031,0x4bd00db0),LL(0x7d2cb92d,0x866e0bbe),LL(0x1dd3db2c,0xad36406e),LL(0xe4e3f194,0x969dc881)}, {LL(0x2a115bc8,0xcb3ac9e4),LL(0xe0a5ab75,0xb45efd5d),LL(0x55377d5c,0x1709c293),LL(0xde6bc25d,0x06d11ba4)}}, {{LL(0xccf2d10b,0x84a09347),LL(0x08ee5aef,0x571cd4d9),LL(0xa450dd82,0x1379ac02),LL(0xae404542,0x5b7f02f5)}, {LL(0x2a7df4ce,0x17366e7f),LL(0x9830ebec,0x5bb3560c),LL(0x7c254726,0x5c582580),LL(0x70ab7b3d,0xea13f8fd)}}, {{LL(0x314e2a25,0x868c0f8d),LL(0x0be90b12,0x4b3dad3a),LL(0x32aaffcf,0x09970da4),LL(0x8a6d894d,0xe711e9cf)}, {LL(0x0a80d07a,0x511521af),LL(0x8a2a2851,0xe3814716),LL(0x1de9183e,0xde76d41b),LL(0xaac779e5,0x8a9fc79a)}}, {{LL(0x26879f8b,0xd7d1f235),LL(0xe37d5f9f,0xcc849c85),LL(0x6b9cd82f,0x26b5488a),LL(0x91099141,0x1b068e8d)}, {LL(0x35ee636f,0x040dc00f),LL(0xd84a9cbb,0xab40f94b),LL(0xdb303776,0x2e4cf65c),LL(0x78e8affb,0x42eaa12e)}}, {{LL(0x876f8f38,0x7835e4e9),LL(0x090ca6b6,0xcd421d77),LL(0xad0604f7,0x71a1d12d),LL(0x1a22e872,0x51c2d158)}, {LL(0x429e45e9,0xfe7dfcc8),LL(0x48224b6f,0x20028f5c),LL(0x50abf907,0xf7afed37),LL(0xc4ce1a69,0x92183692)}}, {{LL(0x2d128add,0x0b93365c),LL(0x13200221,0x883f43c3),LL(0x4d309b2d,0x9d3b5a53),LL(0xcf91a023,0x60f0db16)}, {LL(0x5b0e47be,0x20f0ebbd),LL(0x317d8b4b,0xcc20dde8),LL(0x5303dd7c,0xab033b48),LL(0x7a9c1974,0x6703eac7)}}, {{LL(0x351c8f26,0x92f0b738),LL(0x08569159,0xadd39ac8),LL(0x61098dd5,0x80866e5e),LL(0xcae578f6,0x7d0c1c6f)}, {LL(0x975f59e4,0x13d89cee),LL(0x0092de2c,0x86006ed4),LL(0x819adda4,0xda825b0a),LL(0xde710934,0x74fefb46)}}, {{LL(0xd3dc8683,0x7c2ec289),LL(0x690e5d08,0x25898cd8),LL(0xbcc67531,0x9bed0f32),LL(0xac762453,0x356ba80c)}, {LL(0x7680da5e,0xd3224c57),LL(0x3399d679,0xaae2597b),LL(0x68df6e74,0xb2a2a1e5),LL(0x2301b373,0x49d23e8c)}}, {{LL(0x170dd677,0xcb89b484),LL(0x6b3ee110,0x36b1d3d1),LL(0x0d7b51b4,0xe50ada4f),LL(0xfd9afdbc,0xa2f4fb57)}, {LL(0xaa6dd8e8,0xb1b9b81d),LL(0x0be328aa,0x616056a0),LL(0xe12b07c8,0x8f6dd943),LL(0x325abaf6,0x4bb551c6)}}, {{LL(0x68fbed5f,0xa5460380),LL(0x87ed0d37,0xa65d059f),LL(0x208aa8cc,0xff60beda),LL(0x33d2d65e,0xc91ff11b)}, {LL(0xf65f65d2,0x078c4e5e),LL(0xf347dccf,0xa92ed905),LL(0xf59e3be9,0x261ad25d),LL(0x3b69facc,0x95903d91)}}, {{LL(0xe789d854,0xcf0a2f94),LL(0x10fbf531,0x9d39cd51),LL(0x6de44e3c,0x980ed5d4),LL(0x78425caa,0xaedbae37)}, {LL(0x7bd278b8,0x35804bc1),LL(0x6a2d7bee,0xf4bee96a),LL(0xa605671c,0xc6c553a6),LL(0x86f010d2,0x182c9238)}}, {{LL(0x9cd6f37a,0x94343b7a),LL(0x237190a9,0xa71e3853),LL(0xa8a28451,0xfcbebde7),LL(0xd711d2be,0xfa928367)}, {LL(0xc3668951,0xba8fd2ea),LL(0x2d241329,0x00fad1ed),LL(0x5dbdffd1,0x61b82e19),LL(0x5a181dfe,0x0e5e5782)}}, {{LL(0xc60f1799,0x1c1bf593),LL(0x64ef800f,0x388d6950),LL(0xce927a87,0xf78ef00f),LL(0x6abfff9f,0x2a010419)}, {LL(0xb0b7ffe2,0x13a7b08e),LL(0x6da4cc8f,0x4619da3e),LL(0x7937e0bd,0x8ac19190),LL(0x1af4f84c,0xf97d3fcb)}}, {{LL(0x8ac425a1,0xaea2abd0),LL(0x4a02e136,0xc619c17d),LL(0x1b2c4acb,0xf09a57d3),LL(0x87b4eb40,0xc6fce6fc)}, {LL(0xb21b02f7,0xa161bb70),LL(0x95bcb925,0x075301fb),LL(0xe1b440ce,0x1d408003),LL(0x606b3142,0xb42a47af)}}, {{LL(0x1c832c35,0xd4ad09c7),LL(0x0e17fb8f,0x5bebe913),LL(0x8b45b250,0xbf8efbcd),LL(0xe5ca21e4,0xbef3cafe)}, {LL(0x688076f1,0x08a18be7),LL(0x0c3a2648,0xabbb3fc5),LL(0xfb54720e,0xa77086e8),LL(0x19c29e8e,0x84277757)}}, {{LL(0x5b95b36d,0x551768ca),LL(0xc7df6d3f,0x8850a9b0),LL(0x5008c00a,0xe5a2737f),LL(0xad076e3c,0x9a577c0d)}, {LL(0x2afa6a8a,0xbe7c611c),LL(0x04259dac,0x5dd9142a),LL(0x422bf3d1,0xd14253bb),LL(0x6805c78b,0x8c9dc4c6)}}, {{LL(0xd430488c,0xb9837258),LL(0x7abc184b,0xf9fc178b),LL(0x0c5e6a11,0x035d3079),LL(0xfbc2182b,0x20cbe540)}, {LL(0x9d76812f,0x849994e2),LL(0xf7a85553,0x166a9279),LL(0x19d70aff,0x15ff0643),LL(0x4bc6a829,0x3c58e0b0)}}, {{LL(0x84df75ff,0x3809904b),LL(0x67a7c214,0x454c63fd),LL(0x2d873c09,0x79e0ffde),LL(0xcef301bf,0x620a3293)}, {LL(0x237c2bdf,0x8f38c8e8),LL(0x13203c2c,0x61cf96de),LL(0xd0bef848,0xdff401d6),LL(0xee4bcbb6,0x3c8ed7ce)}}, {{LL(0x07ff8f9a,0x3e128e2d),LL(0xad7e8d5e,0x0653c0b2),LL(0xb1930408,0x7bb30bb5),LL(0x4c158386,0x91d18705)}, {LL(0x80c21fb4,0xc4cf843c),LL(0x8a04133a,0x97a72d75),LL(0x4218755a,0x6b7c49f3),LL(0x68a40f68,0xc1a5a447)}}, {{LL(0x15ca3037,0x0ab9650e),LL(0xac06feb0,0x16b1fa71),LL(0x0faa3dca,0x50179660),LL(0x1c1aaeae,0x368b2d89)}, {LL(0xb46f0310,0xf6fa652a),LL(0x79fcbc59,0x86a4d627),LL(0x6106a132,0x78169b8e),LL(0x9e387d16,0x40a741eb)}}, {{LL(0x80eed542,0x14a45174),LL(0x3362ef7f,0xadd64561),LL(0xc5dd0396,0x39228bfc),LL(0xea0c538b,0xe9fdf903)}, {LL(0x74d235de,0x6bfd91ec),LL(0x24aa0a47,0x96ec2378),LL(0xaf8d6168,0xf5699241),LL(0xc548a60b,0x0a7b9be3)}}, }, /* digit=10 base_pwr=2^70 */ { {{LL(0x2ade9556,0xe5255c30),LL(0x75ba2e9b,0xe328af1b),LL(0x41ce9e47,0x9d3391ef),LL(0xfb0ffcc9,0xb74cd668)}, {LL(0xe3226acf,0xc67103e4),LL(0xd2959e42,0xa65ad22c),LL(0x99d490fc,0x3aaa8406),LL(0x9ecc6356,0x3e26a1c2)}}, {{LL(0x4e92defc,0x71c975de),LL(0xd0089883,0x81aeb173),LL(0x2ec09190,0x8a30ce4a),LL(0x69a36d64,0x426e7838)}, {LL(0x309bd2d7,0x5899a0b6),LL(0x3cc1a4af,0x3b1c24af),LL(0x345163b3,0xb2aa8142),LL(0x2c78c86d,0xd2ad9a69)}}, {{LL(0x8e7a4174,0xde59fe5d),LL(0xab3b0f3d,0xaedff2d2),LL(0x1f053470,0x4688e9e0),LL(0x97c95c7c,0x29ff3fb1)}, {LL(0x85e6a8df,0xffb930cc),LL(0x623b6068,0xaa4d3175),LL(0xf9716623,0x682101dd),LL(0x402db696,0xa3bc9f5f)}}, {{LL(0xba4e4651,0xf67233c6),LL(0x0714d4ac,0x8cf95660),LL(0x71f1f8da,0xd70decc3),LL(0x7078370e,0xb674732a)}, {LL(0x4ccc773b,0x4270416d),LL(0xde87951e,0xc848ff35),LL(0x493dfb56,0xa61506a8),LL(0x767eb110,0xd8371ea9)}}, {{LL(0x9e6b1d70,0xb468c382),LL(0x4cd025fb,0x1a901978),LL(0x5e6879e8,0x4bf50c7e),LL(0x71cf7119,0x6b862c0f)}, {LL(0x06240e95,0x6a53ce89),LL(0x04107ff4,0x3ddfaa0a),LL(0x65532b51,0x317093cc),LL(0x0e27b5fc,0xf1e0f859)}}, {{LL(0xfe4674b4,0x96a97a12),LL(0xf7c97b12,0x2a132ae6),LL(0xa5f5ae91,0x5afcd087),LL(0xd4805ddb,0xfd1d3a32)}, {LL(0xd7b5c8bd,0x0a989dc0),LL(0x4429af19,0x35d186e4),LL(0x42935fba,0x65623ad2),LL(0xe79b867d,0x4e274314)}}, {{LL(0x08aaba2a,0x47d92016),LL(0xf3f4c812,0x12b62343),LL(0x464f4b4c,0xb35bf043),LL(0xd8e8ba16,0xdc9391c0)}, {LL(0x5d460c0d,0xcc0f8c4a),LL(0xe20fc6ad,0x04ce64bf),LL(0xaa4b7db5,0xd0289df5),LL(0xe5299815,0xe0ea15c5)}}, {{LL(0xda3adfe0,0xc066ee2f),LL(0x0c964e7d,0xce6a9bdc),LL(0x0c859476,0x04a0115b),LL(0x9c95699c,0xb5e02dc9)}, {LL(0x11377eb9,0xf8301f62),LL(0x172bca2e,0x57b245a2),LL(0x7b47cf1f,0xa7d9b470),LL(0x1774b1c1,0x1b469bab)}}, {{LL(0xda2dce70,0xbb9ec3e9),LL(0xd29bcdda,0x02d5353e),LL(0xb215233c,0xc193244a),LL(0xd27a4e2a,0xb8d5727f)}, {LL(0xb6c5b114,0x79e56194),LL(0x5ce727f0,0xe2c20e71),LL(0x236cbfea,0xc92f34a5),LL(0x56a02b8f,0xcc47dfd1)}}, {{LL(0xe983ba13,0x5cdbda39),LL(0x6e96c8b2,0x20f3de57),LL(0x66b76faa,0x2ff05aa7),LL(0xd7f84b47,0xa876bc62)}, {LL(0x0d677d1f,0x962ef8a9),LL(0x801d3001,0xabc7bb1e),LL(0x7d13a23f,0xdb5f0b1a),LL(0x20b819e4,0x2664f3ab)}}, {{LL(0xdc45375a,0x96be66c5),LL(0x4a6c24e8,0x780ee062),LL(0x013a13ee,0xc6fbfd1a),LL(0x21fc4f9c,0x6ce1496c)}, {LL(0x81f272c5,0x03130c09),LL(0xa26609cd,0x06e59457),LL(0xee5363b4,0xf4c5e564),LL(0x7df0775d,0x1cd19a11)}}, {{LL(0xdfd6586e,0xcdfcfa67),LL(0x1ba23faa,0x358953e5),LL(0xaeec5d6f,0x0f467275),LL(0x5b0e6b2a,0xb815967a)}, {LL(0x012b89b4,0xb01bf133),LL(0x6839cc04,0xdd924bbc),LL(0x120dfd73,0xa5cd2180),LL(0x19bf8098,0x1abb11ef)}}, {{LL(0x6a281d1d,0xd56c11ce),LL(0x70daeb19,0xfb01f455),LL(0x8f29fcc1,0xbb442a0d),LL(0xe9b2f829,0x9aa60157)}, {LL(0x90ae8113,0x1f3f6e61),LL(0x6c946c0d,0xc701a185),LL(0x52ba7caa,0xb4b89268),LL(0xb0a5c77f,0xd657c679)}}, {{LL(0x0dd26330,0x0f14eb11),LL(0x9b036325,0xff622296),LL(0x186e735a,0xaf833fb8),LL(0xc7e710f5,0x7801b02f)}, {LL(0x5c948f43,0xa0bf821f),LL(0x86225c71,0x3be31aea),LL(0xe60b1c88,0xe98f4f7b),LL(0x73c5281b,0x6306588d)}}, {{LL(0x83c9f829,0xd6178277),LL(0xc06675f1,0x67b20e6c),LL(0xcb2d5b9d,0x8a63fb89),LL(0x038c00fe,0xcb28128c)}, {LL(0x8c7c6c6e,0x070a5141),LL(0x8789c3b7,0xc05e18c3),LL(0xd5c67731,0x09fd03c2),LL(0xf54010ec,0xc59e2abb)}}, {{LL(0xf1ef2232,0x03977889),LL(0x9c7409a5,0xbe2c82f1),LL(0x32004e03,0x35ac44f9),LL(0x856823a3,0x048bb359)}, {LL(0xec1cf253,0x2e108d6c),LL(0x703eb1d2,0xe98e74d7),LL(0x570ac34d,0xcaf64f60),LL(0x4d7797fa,0xff814e7d)}}, {{LL(0x70818472,0x93b6abc3),LL(0x888357af,0x0e984be6),LL(0x3fe0c135,0x2a7ca1b0),LL(0x94a82d67,0x0c6c4a11)}, {LL(0xbb83ae74,0x0c90c359),LL(0x328b8af1,0x49b25e5e),LL(0x798ff0a6,0x26a36032),LL(0x1fc28ca3,0xbbf89c99)}}, {{LL(0xe679eb71,0x4ce174e2),LL(0xd1c183bd,0x17c76176),LL(0x03a69f58,0x4bf67be8),LL(0xc0ee530c,0x937a391c)}, {LL(0x1f7daaff,0x2daa9d90),LL(0xc54f14d0,0xa47e99b2),LL(0xc57feeca,0x6be357e7),LL(0xcfdfd5dd,0x3753fad2)}}, {{LL(0x48f90174,0x74e1457a),LL(0x9b4734da,0xb8092642),LL(0x5800ea72,0x291e75ba),LL(0xc72c28f7,0x25a21b38)}, {LL(0x505aa4d2,0x2193e0c9),LL(0xada9d3f8,0x2f6829e3),LL(0x92900e29,0x66cd5a1d),LL(0x7414dc1d,0x1360d287)}}, {{LL(0x0d1b96aa,0x5deeb2eb),LL(0x3e52ccf1,0x25783ce3),LL(0x29d534ef,0xe4e251f4),LL(0x55797dad,0x9fe9693d)}, {LL(0xc6ab9935,0x6a173d69),LL(0x7721ca8e,0x23991318),LL(0xc393eb26,0x38cbcd30),LL(0x71d95a9e,0xe3627ab9)}}, {{LL(0x7f6fe2d4,0xdf1218be),LL(0xfabd8326,0x850c8598),LL(0xb0f7cf49,0x1214d3d7),LL(0x1805345b,0xeaf60d31)}, {LL(0xbfee2c5f,0xc5caf65b),LL(0x45e23043,0x70127979),LL(0x500fbad2,0xda36e794),LL(0x4156e3a6,0x38fa60b0)}}, {{LL(0x3cbab88a,0x45934bdd),LL(0x1b19dce4,0x72821e74),LL(0x8661e32d,0x532f706d),LL(0x73a9930e,0x3dbfc225)}, {LL(0x3cbeb0f1,0x72d1cb2a),LL(0xe20f5613,0x795b0696),LL(0x9fc88717,0x6e3469e8),LL(0x483864d2,0xf4bf0531)}}, {{LL(0xfa19ddd9,0xc92e6a8c),LL(0x3528e628,0x7db7e2ee),LL(0xf321fc88,0x997a00eb),LL(0xacdf205f,0x7605a2c9)}, {LL(0xea9c3ed0,0x9fca58cf),LL(0x56ff0e98,0x833078cb),LL(0x662a1695,0x75159b8f),LL(0x1919f51f,0x186560b7)}}, {{LL(0x5ef764b4,0xe9b60e57),LL(0xbe73c698,0x61ad29fc),LL(0xdd2be1ee,0x18489017),LL(0x7febda71,0xac95e3b6)}, {LL(0x5ac96092,0xa6985346),LL(0xbfc83566,0x906265c3),LL(0x5972fa4a,0x1692c812),LL(0x00773540,0x4e76f879)}}, {{LL(0x542b137e,0xba9a6268),LL(0x4c7926e2,0x43a52b90),LL(0xfeae554e,0x28785bf5),LL(0x0ab61576,0xc023b688)}, {LL(0x10933a55,0xb3ec8181),LL(0x6331678e,0x75634459),LL(0x17c50b5d,0xe0dfa141),LL(0xe2151f25,0x4cbe7fda)}}, {{LL(0xce81fbaf,0x3f3072ac),LL(0x0ff56a32,0xa387bb20),LL(0x99865968,0x2b08a811),LL(0x084cb1f2,0x7279f913)}, {LL(0xdad70f5a,0x78cca6c9),LL(0xff47647d,0x72469f6a),LL(0xe358b597,0x2505c7ff),LL(0x998ff0dc,0x7c5268a8)}}, {{LL(0x99d5b1c1,0x32d70129),LL(0x24a90c34,0x72727c15),LL(0x715662b1,0x57dad21c),LL(0x132f3294,0x76b4b6ec)}, {LL(0x267d246e,0xd03b46b1),LL(0x29b47516,0xc7c848ec),LL(0x1660af51,0x5eab3dbc),LL(0x04c66383,0x818894c4)}}, {{LL(0xa7b82f5c,0x26a45c3e),LL(0xea98adfb,0x494694de),LL(0x134b182c,0x44a06ec3),LL(0x75b82b41,0x5570befa)}, {LL(0x129f952e,0x819f6808),LL(0x914f87c4,0xa6fad25f),LL(0x7c7be905,0x831e5668),LL(0xe623a5c2,0x93107f38)}}, {{LL(0x5e40c5f4,0xa9d88469),LL(0xaa5993c5,0x4314d233),LL(0x9c19bbc5,0x5eab88d0),LL(0xb385d3cd,0x795e1c21)}, {LL(0xce163fbe,0x532a1871),LL(0xb867aea4,0x727cb126),LL(0xf7f30476,0xfc7047eb),LL(0xfcc4fe35,0x18031271)}}, {{LL(0x884a4c6d,0x4b84fa4a),LL(0x55c830ab,0x82cb9aee),LL(0x0cc927cc,0xd4cfdf04),LL(0xa16bef30,0x787efdde)}, {LL(0x32e3c763,0xd1fb2dd6),LL(0x16737272,0x8739566f),LL(0x03a1055a,0xf9ae4f46),LL(0xf9a7472b,0x199970cd)}}, {{LL(0x1d33ac50,0xf9893cfb),LL(0x1e5ff4e5,0x74cf7dd4),LL(0xf7165331,0x72ec32e5),LL(0xbb4679cf,0xa082c59a)}, {LL(0x5c75461a,0x3cd0a467),LL(0x40f06206,0xd2872d68),LL(0xb5122795,0x08271eef),LL(0x1475e22b,0x7006d350)}}, {{LL(0x89e35108,0xf7cd1bcc),LL(0x93f1cbaf,0x924efa43),LL(0xf35b13ac,0xe3716559),LL(0x60370a1d,0xa0a88e87)}, {LL(0x8c286ea3,0x1203be0a),LL(0x6ebd50c7,0x97fc5ab6),LL(0x74284d08,0x2b5b3602),LL(0x694a20e0,0x3055716f)}}, {{LL(0x193520c0,0x793c8a89),LL(0x655f5ff2,0x356402d0),LL(0x1af5ddd6,0x0cf889ee),LL(0xb3f149b2,0x3eb7eb35)}, {LL(0x68e07e0e,0x5254b57c),LL(0x9c5bbfa7,0xb1971de2),LL(0x0ad81e7e,0xcc85a53a),LL(0xed3cbb10,0xbaaa4d2b)}}, {{LL(0x8f3a7eec,0xbdf9941c),LL(0xa1f26666,0x6e1b7dab),LL(0x2d79a58f,0xe7a0dfa4),LL(0x1f2b9667,0x25e0ddb5)}, {LL(0x5fd96351,0x4b3b5105),LL(0x8874abd1,0x12325832),LL(0x795d91a5,0x56e90310),LL(0x2c32eec8,0x376a79d2)}}, {{LL(0xa8a16445,0xd9dd8817),LL(0x0e00fa92,0xd61f6aec),LL(0x17d95f07,0x594a620d),LL(0xf4b15001,0xa1534fda)}, {LL(0x0974f4a3,0xe9402601),LL(0x8f671f13,0x4c3fc130),LL(0xc5f35bfb,0x8eaab35a),LL(0x4626baca,0x13b98472)}}, {{LL(0xcdee6f8d,0xf48703ad),LL(0x12d39694,0xf1ba0309),LL(0x9fcda52c,0xeb2d4d92),LL(0x5507b401,0x984f5111)}, {LL(0xf6bab9ec,0xe3aa26ae),LL(0x6b2e077d,0x557b5e3f),LL(0x2f9c5f35,0x7185ab4f),LL(0x1680bcbc,0x96f21a33)}}, {{LL(0x2ddb1173,0x2e7f6e07),LL(0x816ffc8d,0xa704416e),LL(0x52e26265,0x55acfaa3),LL(0x8b758c94,0x9c244253)}, {LL(0x0479936d,0x4012e0a6),LL(0x6d8541d8,0x12749e93),LL(0xce56a2a1,0x374f420d),LL(0xc79da17f,0x6a8e3614)}}, {{LL(0x157cc9e1,0x3602ad09),LL(0x13603196,0xf3c4a54c),LL(0x8473ae27,0x354fc6ed),LL(0x651b8003,0xb4cf4251)}, {LL(0x3415b5f0,0x456b1b9b),LL(0xc4c71507,0xe078a858),LL(0x9a0a11fb,0xf4210409),LL(0xf930ec45,0x76de42a0)}}, {{LL(0xcfa869a1,0x82ecd0af),LL(0xdccf2e47,0xa637938a),LL(0xc041648a,0x1d2858f2),LL(0xc0dfacd2,0xcf9abfe8)}, {LL(0xbdddebe1,0x3af77e19),LL(0x180b535f,0x15f6b0bb),LL(0x549d34c1,0x497de678),LL(0x3dba7d6f,0x31495c9e)}}, {{LL(0x393ab61c,0x47b9368b),LL(0x27441f92,0xdb8ee3a8),LL(0xfb0b0117,0x214a6a5f),LL(0x43759430,0x429e61ad)}, {LL(0x77316c0e,0x78116e88),LL(0xa6a29e98,0x59c82616),LL(0xaaef4619,0xbfed454f),LL(0x35926335,0x673327c4)}}, {{LL(0x18c616a7,0xaa66d8c5),LL(0x6d28fb98,0xa93946a6),LL(0x133336dd,0x4fc30de5),LL(0x7f0c805e,0x7e000a34)}, {LL(0xcf7eab23,0xa82dcf54),LL(0x8dc24371,0x679e67a8),LL(0x1af582d8,0x26b2dffc),LL(0xd3fe2155,0x4c1d692a)}}, {{LL(0x2d024923,0x2475b110),LL(0xc303c1e7,0x0cc9245d),LL(0x03667a7a,0x290b7a77),LL(0xd87dbd9c,0x2ab8eb6d)}, {LL(0xc098719e,0x7089e481),LL(0x12c022c8,0x17dd6d74),LL(0x8b7aca14,0x90efa01f),LL(0xf55fbe83,0x8b601fba)}}, {{LL(0x415aa7a5,0xf800bd76),LL(0x3aa74349,0x015573d3),LL(0xaf5ec789,0xd5143779),LL(0xd76dd2dd,0x32330b4b)}, {LL(0x82331ef1,0xec6caa4d),LL(0x25ad1965,0x92cc8865),LL(0x134370b0,0xf8209a40),LL(0xb883cf95,0x320a37b9)}}, {{LL(0x5d39731d,0x94237ba2),LL(0x8532a968,0x6359d195),LL(0xf86b8b75,0x8bca94c9),LL(0xde316226,0xdb5c6a9c)}, {LL(0xa2fa0c26,0xdf300c59),LL(0x48af4357,0x6dbf6082),LL(0x06535fc9,0x25066c6c),LL(0xa29b2477,0xba2e774e)}}, {{LL(0x1931299b,0x5157e93d),LL(0x3a8035a4,0xd6249c10),LL(0x81245740,0xcb18fcf1),LL(0xad5ebe1f,0xb4d84c9d)}, {LL(0x8df0d59d,0x95050bec),LL(0xac2a2e0c,0x190a4860),LL(0xfd1bbb11,0x29029e0f),LL(0xb075b432,0x341f73de)}}, {{LL(0x74836028,0xa825c3c5),LL(0x8f55343a,0xec4fd74b),LL(0x60a683b3,0x009bcab5),LL(0xcd3adea6,0x29877303)}, {LL(0x684a33ac,0x9f264bf2),LL(0x84b3c379,0xc8bf19e6),LL(0xa1215470,0x8ac35fb8),LL(0x405386d6,0x2919d9da)}}, {{LL(0x19780b2a,0xb4e4aa30),LL(0x356ddd4e,0x639b8fcb),LL(0x9322c245,0x6ed7b10c),LL(0x57f39c76,0x84ec0bc6)}, {LL(0x879176fb,0x6a1be66c),LL(0xe10e0f77,0x4cab3151),LL(0xe2ae0777,0x01c6321f),LL(0x65e57ff1,0x04d6a04c)}}, {{LL(0x142596dc,0x8c1725ed),LL(0xb2d413a6,0xd321d49a),LL(0x2b5e8ae7,0x19c25fc3),LL(0xbd3c7dc6,0xfc32cbeb)}, {LL(0x57b98ff5,0xf3ec98b8),LL(0xf75b1a00,0x52e5f1ad),LL(0x8f8ad463,0x16812bb4),LL(0xa274f0c3,0x9d67cb11)}}, {{LL(0x80064047,0xdec72055),LL(0x4319f87b,0x3f828c01),LL(0xff4d6c4a,0xffcad5c3),LL(0x67a6e030,0xee6659b2)}, {LL(0x0478715f,0x9cb5c729),LL(0x5a1c926e,0xc63fc281),LL(0xdeb11155,0x1b8788ca),LL(0x4f0c00b2,0xbe2eebf1)}}, {{LL(0xa6af09d1,0x9b72ffd0),LL(0xa9a459f3,0xcbac42bd),LL(0xf560dc93,0x150806c0),LL(0xc57787ee,0x71c636e4)}, {LL(0x2a951b0d,0xe4f3acb8),LL(0x3b18d294,0x510dc771),LL(0xb060e782,0xfbb3fb53),LL(0x0358210e,0x0659cadd)}}, {{LL(0xecde1629,0x23638245),LL(0xcc09daa5,0xee6e9a65),LL(0xee18f9cf,0xf440bb81),LL(0x955200e0,0x99e4d6e8)}, {LL(0x93e69354,0x34555b58),LL(0xfb29b19b,0xa6080e13),LL(0x5100ab06,0x3bfa4796),LL(0x22eec8fc,0xf5db4b13)}}, {{LL(0xe5aaa980,0x2c1a229e),LL(0xd29eb83e,0x446cd46b),LL(0x7f5aa015,0xe0c044da),LL(0xa18f23f7,0xa55d5f23)}, {LL(0xb6b70f51,0xd71e58c1),LL(0xb5862c51,0x77c72d10),LL(0xfce94ceb,0x01db731a),LL(0x13a47553,0x877703a8)}}, {{LL(0x3b75e6d9,0x4878b0b1),LL(0xfe60f98a,0xbe8421f0),LL(0xc69d6820,0x6312821b),LL(0x00d2db20,0x4c019374)}, {LL(0x2a1d8b74,0xb1bd5175),LL(0xef7fdad6,0xa0a24ad2),LL(0x929fc488,0xf29fd27d),LL(0x162a02de,0x8e28b4ed)}}, {{LL(0xc166afcf,0x434cbdb3),LL(0xbf663e65,0x7b79e808),LL(0xa3c3b159,0xd445f1b0),LL(0xb35b2be9,0xdf9f92b7)}, {LL(0x788a9bbc,0x815b57f3),LL(0xabbba2e0,0x9e03e357),LL(0x91a658d8,0x3fc574d5),LL(0xadf4e250,0x83b35d8a)}}, {{LL(0xacd1e4f0,0xa0e15175),LL(0x868b4e04,0xeca899a4),LL(0x782b7ee7,0x713b4e9e),LL(0xb7d58c1a,0xed177e1e)}, {LL(0xac8364b2,0x4778df76),LL(0x2e8f7ef7,0x6898fb31),LL(0xa03975b0,0xfccf4c53),LL(0x8597436f,0x0f908d14)}}, {{LL(0x96671c53,0xbeaf1a16),LL(0x6bc4cbbf,0x9be64329),LL(0x80017bf3,0xc8f66f63),LL(0x8836ff35,0x92d700f2)}, {LL(0x13a4daf1,0x9ddd7a81),LL(0x9b72664b,0xb3c42723),LL(0x81babf43,0x3d96f79a),LL(0x7ce5830d,0xa46c9c0c)}}, {{LL(0xf5999a71,0x54dfec97),LL(0xe586a578,0xdb5be461),LL(0xcfb4e7ad,0xf9bc3f04),LL(0xb11f07aa,0x6e5448a9)}, {LL(0x70132d5a,0x29ef7791),LL(0x28ba851a,0x4fe486c3),LL(0xb62f7f8a,0x6743fecd),LL(0x44d24d01,0xeb264387)}}, {{LL(0x72ebb976,0xf93c05bc),LL(0xaaae099e,0xe65b30c0),LL(0xc8427104,0x4194721a),LL(0x3025853e,0x3af3487f)}, {LL(0xdbf48435,0xb33a2893),LL(0x2d79334e,0x2c5ac639),LL(0xb16b05a6,0x8fc199f8),LL(0x7661a77b,0xc145358e)}}, {{LL(0x1841f719,0x15b580b6),LL(0xd7045528,0x24f5fadb),LL(0x98df2c22,0xe443c257),LL(0xd7eed58b,0x48acf5a7)}, {LL(0xedeb9e4b,0xe24e6571),LL(0x562533fd,0xcd047b81),LL(0xd1566e36,0x618ddd86),LL(0xdba1eced,0x09a77b70)}}, {{LL(0x6968ddb9,0x0e9de410),LL(0x12985b32,0x10f0f429),LL(0x8ca7d2fa,0xbe21b10f),LL(0xc610ae2b,0x0844d8e8)}, {LL(0xd57107d5,0x58a08694),LL(0xc34441f3,0x45f44bd5),LL(0x79a54186,0xe8b3b3df),LL(0xb8b5f26b,0x6496d668)}}, {{LL(0x192503be,0xd69cefb8),LL(0x40f928fc,0xb692128d),LL(0xa7ed8c47,0x13b11dfd),LL(0x5a196756,0x90bd279f)}, {LL(0x17ff33eb,0x78f2e8c6),LL(0xaaf6c182,0xa7b233d4),LL(0x76a31f46,0x63d62503),LL(0x1449dc97,0x53143dc3)}}, {{LL(0x94922922,0x5bb86802),LL(0x89181334,0x2f45a7dc),LL(0x1ec5cce4,0xf7c466d5),LL(0xbb3bd5f3,0x52d15eed)}, {LL(0xe6eacf86,0x150bd5f6),LL(0x0ba66988,0x7fecaf3a),LL(0x11f6f528,0xcdd7fadb),LL(0x55042faf,0x60f64c68)}}, {{LL(0x961ddf76,0x1615919d),LL(0x53f2f514,0xdba095cb),LL(0x1e6c076c,0xf04960ba),LL(0x4c9f17d5,0xe5276722)}, {LL(0x61c186a9,0x93ff80f9),LL(0x3c58ab92,0xd17378b0),LL(0x769492e8,0xc67f9ae1),LL(0x0c3d023b,0xaccfc868)}}, {{LL(0x5b99708d,0x7d67a63d),LL(0x4b80189a,0xfb29bef7),LL(0x241c402e,0x3cb7eeaa),LL(0x2c5c2767,0x328cb6de)}, {LL(0x9cec231d,0x0d24a7b4),LL(0x0e2e6a7f,0x725955fc),LL(0xb7f17b13,0xa2040cfa),LL(0xa25c71cf,0x215eff8d)}}, }, /* digit=11 base_pwr=2^77 */ { {{LL(0xc0d41a94,0xe4d9cab1),LL(0x9e60f7d4,0xc38b202a),LL(0x9336116c,0x2bbf6b17),LL(0x2e068f13,0x2f9aa877)}, {LL(0xa4bac9fd,0xf8820627),LL(0x8a593cb4,0x2209cb9e),LL(0xc7417931,0xaa78ec63),LL(0x7cfccfbf,0x42d21251)}}, {{LL(0x3e611940,0x40cee5ae),LL(0x0aa090ec,0x4e2d9ea9),LL(0x1b926e42,0x73d167ef),LL(0x5d5112a3,0x7fff36df)}, {LL(0xcaffa3fb,0x25587745),LL(0xc5a83504,0x224f7f4e),LL(0x3b47bf2a,0x5ceff018),LL(0xecfab5c6,0xed9bfa73)}}, {{LL(0xd9b429c9,0xf3d570b8),LL(0xc5ad81cb,0x69460116),LL(0x2f6825bd,0x30833a08),LL(0x7c99f36a,0xa297122a)}, {LL(0x05c3abdf,0x6fc9b848),LL(0x5f2e24b2,0xefe95298),LL(0x8915d922,0xf045275a),LL(0x298a9726,0x79146aab)}}, {{LL(0x4f831d0b,0x0c7d5905),LL(0x2d47d4fe,0xfaaaa26c),LL(0x85042e12,0x5ac28599),LL(0x7796977d,0x7eda370b)}, {LL(0x95c0be63,0x9f0bd71d),LL(0x8e821005,0x7c4601bc),LL(0x4c2ffae9,0xf1ecbc60),LL(0x9b688173,0x7e3efc57)}}, {{LL(0xf4ea7641,0x868c672b),LL(0xd94243dc,0x4fa90a82),LL(0xf5eab489,0xbd82913e),LL(0xe966b39d,0xceebc159)}, {LL(0x35c51e2b,0x31fe4f5f),LL(0xc79c1725,0x2fea6ab1),LL(0x83afad40,0x5856cd85),LL(0x4ca89b88,0x7f960988)}}, {{LL(0x1ed8fed0,0x9d237c2d),LL(0x4e0c6f10,0x69b4ec80),LL(0xe4648395,0x11f83283),LL(0x306e152a,0x6f4636a7)}, {LL(0x804539b3,0xf70fd23a),LL(0xb3cdb981,0x4db0903a),LL(0x6691eb18,0xe506ae6f),LL(0x1d8e9d9d,0xaa69c7aa)}}, {{LL(0x3e4e2088,0x540af950),LL(0x95f04e57,0x8fab01d5),LL(0xa8c51a67,0x51bf909a),LL(0xfd19beb7,0x01299f5e)}, {LL(0xb8f15aeb,0xdf703400),LL(0x2d890394,0x19c70987),LL(0x203d2d99,0xf5fcc675),LL(0xc3d4ddea,0xabbf3f21)}}, {{LL(0x587feffa,0x8348ca15),LL(0x7d69e4ad,0x585d0740),LL(0x885a0745,0x6fbe5619),LL(0xb10b24dd,0x04ee9eba)}, {LL(0x0f4c12d7,0x5c27075c),LL(0x3c51c605,0xacf4acdc),LL(0xfce336d0,0x782fa52b),LL(0x483621d2,0x6e1d078f)}}, {{LL(0xd4dc3277,0xa2253bfb),LL(0x4691bc12,0x3a014307),LL(0xebdef616,0x415aa5b2),LL(0x16fe065b,0x1008a44a)}, {LL(0x16dfa94d,0x4004a90a),LL(0x8464785b,0x0e24f541),LL(0x88d30ea8,0xd2715c89),LL(0x1f05a312,0xaf81a9ff)}}, {{LL(0x3e8d5eef,0x958da470),LL(0xd3c80414,0x09561898),LL(0x8bb74691,0xba6b731c),LL(0x577f2ef9,0x6b7355cd)}, {LL(0xb8a98efa,0xd1f416ed),LL(0x11590271,0xd4a1293a),LL(0x4658e9eb,0x2c4d5934),LL(0xd1f15d39,0x51803651)}}, {{LL(0x3c95fffe,0x9b9f0c05),LL(0x31acd6ca,0x8f021451),LL(0xf9dba549,0x5fee2961),LL(0x17ea0456,0x05217975)}, {LL(0xd13a6a4a,0xc0591906),LL(0x90daf370,0xa7f5ed02),LL(0xfc4c304d,0x1f8b7158),LL(0x1b7f0246,0x77016c29)}}, {{LL(0x2ea265d2,0xc27d1847),LL(0x2862781e,0xec0789c6),LL(0x5d86a60e,0x0a79ac1f),LL(0x130670a5,0xe325b563)}, {LL(0x6d33bfee,0xf4794460),LL(0xec25bb10,0x126e703e),LL(0xa7bf902f,0xeae22fd3),LL(0x28eef62e,0x8b2fb282)}}, {{LL(0x059138b4,0xb68de35b),LL(0xd46e68e3,0xfc44bf56),LL(0xff11f76a,0x71567daa),LL(0x6b17cd2a,0x9110e849)}, {LL(0x69573b93,0x7c4027e3),LL(0x1eb9bf01,0x84ee945a),LL(0x28c26cdb,0xa3fadc6d),LL(0x575dfc1b,0x7037a74d)}}, {{LL(0x9b2223dd,0x58c96a91),LL(0x51461b94,0x912fc795),LL(0x2df3329a,0xc18ced63),LL(0x88a002d0,0x79d6f75f)}, {LL(0xf44d3d84,0x73d7a089),LL(0x8c058073,0x98c78aa7),LL(0x333ae8ff,0x0ab8b3c7),LL(0xebd4e536,0xf5a8f5ec)}}, {{LL(0x83a5f52b,0x2c7df9fd),LL(0xcc062097,0x314fc7c3),LL(0xc5a3113c,0x6c3195f8),LL(0x2c25a629,0xf130cef9)}, {LL(0x70c8dd70,0x10c8cc5b),LL(0x01cd40d3,0xecb7a35f),LL(0x6fe21c93,0xfbee538f),LL(0x2ba12ee8,0x57ec1959)}}, {{LL(0xb2b806a8,0x74387a1b),LL(0xbad5d0f4,0x14efa300),LL(0x23a0e9e4,0xee7e4421),LL(0x3b6abdec,0x504ae428)}, {LL(0x927b1aac,0xb8c06fcb),LL(0x323b71d3,0x55e1c85c),LL(0x48d6dae1,0xf47e180f),LL(0xa84cb0b8,0x6d80dd63)}}, {{LL(0xd75d7785,0xf8e07d53),LL(0x37614325,0x3edf19b7),LL(0x357946ed,0xf03709b0),LL(0xd12105e7,0x567d8c0d)}, {LL(0xa9383b49,0xecf6abc0),LL(0xcab329a7,0xfe9c760b),LL(0x43928852,0x425e62fa),LL(0x6194b51f,0x27945ae0)}}, {{LL(0x3ee4f7cd,0x756f0f54),LL(0x26e4c865,0x4337ac7b),LL(0x35b9c3ae,0xf94596c3),LL(0x4d6aa5d2,0x066fd3da)}, {LL(0x43c8d94c,0xce1a5b7e),LL(0x614c0fc2,0xaed496a8),LL(0x2a6d5481,0x355e16f5),LL(0xa09d3afe,0x8f934639)}}, {{LL(0x2bf2a099,0xd170daef),LL(0xae6ee507,0x3920d87a),LL(0x248158e3,0xbdac1c8e),LL(0x05c54e69,0x99033a9a)}, {LL(0x41872197,0x4513bdf0),LL(0xd3f0f889,0x15634020),LL(0x05d42aa8,0x76c1855a),LL(0xe8ba47cc,0x23079179)}}, {{LL(0x728429e6,0xf80b787b),LL(0x3dd8c4f8,0x896b6ea5),LL(0xc7d9fe06,0x711eef39),LL(0xebced829,0xfff28d03)}, {LL(0x4ad40c88,0x5d7823b8),LL(0x3b112bd4,0x40a5a166),LL(0x63bce926,0x84230bfa),LL(0xbe17e7cd,0x39d2e6bd)}}, {{LL(0xef03ee6c,0xa772e242),LL(0xfa009e67,0x888bc969),LL(0x4893e1f0,0x0f06ee83),LL(0x6b89e124,0xf28f0d3c)}, {LL(0x71f5cbc5,0xb3e70ef8),LL(0x6cad191e,0xff0f7e62),LL(0xf028d276,0x990697be),LL(0x4ad8f830,0x144c101c)}}, {{LL(0x3556d74f,0xbcaafb45),LL(0xeb4c7ea0,0xbc216224),LL(0x234a62c8,0x73ad1043),LL(0x2d95ff46,0xa644eb6a)}, {LL(0x0a3373f8,0xd545b60a),LL(0xd4edaa10,0xf7a0572c),LL(0xa97a85b4,0xa7177049),LL(0x7d3ec769,0x529dbadd)}}, {{LL(0x7822dd37,0xc45610f6),LL(0x98258666,0xfad07fab),LL(0x87259c1b,0xac27001f),LL(0x1b849745,0xa9bdc6a9)}, {LL(0x04c862b1,0xc7ee7216),LL(0x0012f591,0x32c1541e),LL(0x5a366d79,0x8198aadd),LL(0x68866e1b,0x03cd312e)}}, {{LL(0x9ec64698,0xa0dbc381),LL(0x1ef36dd2,0x770e4d11),LL(0x8d56bdfd,0x01d17915),LL(0x75eb9947,0xb48153cd)}, {LL(0xfde98390,0xc1d17a54),LL(0x0fe2d6fc,0x0817eaf7),LL(0xa6a704f1,0x44a63591),LL(0x7f554182,0x9423465f)}}, {{LL(0x13e0574e,0xc7c23cbd),LL(0x439941b6,0x6e06e2cb),LL(0xafa39c79,0xa8aebd2c),LL(0xedede735,0x1b859e2b)}, {LL(0x6b4f5465,0x2f485781),LL(0x624c81e8,0xec3093f0),LL(0xc282644c,0xc1f027c1),LL(0x2b74ab51,0x2f6e990b)}}, {{LL(0xed2ea3df,0x9a988d1c),LL(0xff39d3df,0xa3f50efd),LL(0xec1d7614,0x418a3627),LL(0x3d4fa3e8,0xafc1520c)}, {LL(0x891a9c69,0x741305af),LL(0x5d6f8296,0xe87064d4),LL(0x12307b05,0x47c9394c),LL(0xc35f0f40,0x6b038acb)}}, {{LL(0x1ccca008,0xa6e77647),LL(0x9dd71746,0x58e4cfb6),LL(0xc1fe84ae,0xdf649c98),LL(0x90db4388,0x2e308ddc)}, {LL(0xe9362400,0xc2641332),LL(0x42d265e5,0x92dd9842),LL(0x31eb91bd,0xe0e4ed9b),LL(0x145535c5,0x62ec7dd1)}}, {{LL(0xf810812f,0x1ff29a09),LL(0x15e9b102,0x56b64acb),LL(0x5b353184,0xb5f6d4d4),LL(0x1c593774,0xc3c9292c)}, {LL(0x2c700292,0x16781036),LL(0x3ae2f0c6,0xf0948fc9),LL(0x4da778ea,0x40e353cc),LL(0xa34df03a,0x07febf09)}}, {{LL(0x9ec397ff,0x349812ae),LL(0x330f02d0,0x7c78812f),LL(0x7d241ea2,0xf956700b),LL(0xebed08be,0x864b1809)}, {LL(0xb9eb1635,0xe4cec3df),LL(0xab49fb60,0x7dd65ad6),LL(0x86788a28,0x06551163),LL(0x11fb4214,0xda8792d5)}}, {{LL(0xcec09c3e,0x82140df3),LL(0x539db03f,0xcd34ca30),LL(0xe7dd0e09,0xf07cf030),LL(0x56ae3487,0x7b08a242)}, {LL(0xbf5a6549,0x9c0fd607),LL(0xd189d68e,0x0b1fc745),LL(0x9cf52022,0x0d91be74),LL(0x43ff7fc3,0x6013f31f)}}, {{LL(0xb5654233,0x3bf90bd5),LL(0x202bf534,0xd0a17969),LL(0xc97e02ba,0xff373b8b),LL(0xd31dba07,0x4606de54)}, {LL(0x8114562a,0xb045c50a),LL(0x7b8d8915,0xc123acac),LL(0xb60aa324,0xa8f7cd87),LL(0xabc48200,0x077cab67)}}, {{LL(0x0d7fff59,0x88a68643),LL(0x67bfe743,0x82b92193),LL(0xc2ce06f9,0x1a8b86cf),LL(0xf9ad6134,0xa38414a0)}, {LL(0x28e2c39f,0x7f102610),LL(0x480856a0,0x34805c20),LL(0x18c3034d,0x1b3f9302),LL(0x574c0c9d,0x1713f457)}}, {{LL(0x690ce2a5,0xd84fa26f),LL(0xe01a4637,0xd4cfa19f),LL(0xcc6fad47,0x4807fb82),LL(0xf933226a,0xc9d84b48)}, {LL(0x7cd2c9dd,0x9b7c530e),LL(0xf44818e3,0x6436a001),LL(0xdfb00461,0xbae0ceed),LL(0x51c8c8a3,0xed6a7c5f)}}, {{LL(0x0463ac73,0xa6e7fa54),LL(0xc77b19e5,0xa0deed89),LL(0xff218725,0x4e0a3396),LL(0x2edf2704,0x7cfbbd57)}, {LL(0x4e8608c5,0x8114d0ca),LL(0x38c935b7,0xceae65b9),LL(0x330af8fd,0x052b1407),LL(0x723c422b,0x02e189a1)}}, {{LL(0x657560c8,0xf1cd6216),LL(0xe5068361,0x099eec2f),LL(0x3de78037,0x68ef58fb),LL(0xf3e399e9,0x83e0d34e)}, {LL(0xf9a17095,0x3a2a14c8),LL(0xaaf9f08a,0xc7a360be),LL(0x30e99527,0x6420155f),LL(0x9f180405,0x8f610960)}}, {{LL(0x02bc97fe,0x871a832f),LL(0x8dc7f1f2,0xa14b3326),LL(0x87f78ad1,0xc9bd8b41),LL(0x0b59b9c5,0xd378d02a)}, {LL(0x35c0dc14,0x418a32a5),LL(0xf53d85af,0x4c96979d),LL(0x08eb4b26,0xb6f40e97),LL(0xcaa6252f,0xa21349ca)}}, {{LL(0x5de38e2d,0xb13d8062),LL(0x9b43c5d6,0x54ea3684),LL(0xb1d6521d,0xc0ad58d7),LL(0x22085236,0x182f8823)}, {LL(0x2a08449e,0x9d50cecc),LL(0x17ab0b68,0xeb85e785),LL(0x8d74e26b,0xb8a22ab7),LL(0x77d03987,0x77515524)}}, {{LL(0x77ad71de,0x117a63f2),LL(0xc94c8c82,0x1cca30d0),LL(0x2f05382d,0xe5fefba9),LL(0x9b4b42f1,0xcc9e8916)}, {LL(0x9fe716c1,0xbe939e13),LL(0x95e38cc2,0xbf2b9c80),LL(0x37adde62,0xf60c4491),LL(0xf4df75a3,0x3eb3338a)}}, {{LL(0xfe4d84df,0x16398af3),LL(0xfaf3e5f2,0xed752cf8),LL(0xb4cf0e1c,0x746a4339),LL(0x39fb6018,0xb8bd479a)}, {LL(0x57dffed3,0x3a9a045b),LL(0xa5ae3c78,0x2b46ea98),LL(0xde6b0399,0x74b5163f),LL(0x80e511c5,0x069628a0)}}, {{LL(0x1b96672b,0x19cfc882),LL(0x379d1f57,0x2759c76b),LL(0x2269a514,0xa6cc7a98),LL(0x683b1413,0x1bc2015b)}, {LL(0x1bf4be62,0xc43b1178),LL(0x7bf2b0be,0xd2941975),LL(0xc4591cfd,0x1eac3587),LL(0x0e66d495,0x283169e6)}}, {{LL(0x052352e1,0xd39bedb7),LL(0xd719cd43,0xb04af7f2),LL(0xe92956d7,0x702143d4),LL(0xa0e5b847,0x53498722)}, {LL(0x574885fb,0xf0e8edc5),LL(0x8b5187c6,0x4d9418ac),LL(0xd2a00019,0x70e99cb3),LL(0xe7f8a61b,0xf0da5be4)}}, {{LL(0x7dd34fde,0x52704cbe),LL(0x2926bb6a,0x0fb7224a),LL(0xf2b0af92,0x0d58bddd),LL(0x0e9cad36,0x2f986a07)}, {LL(0x80e3a6f9,0xc85549d4),LL(0x322cb14c,0xa013e913),LL(0xf25ac201,0x8a19cf30),LL(0xffb8f2e4,0x130e4ce0)}}, {{LL(0x0ce56c13,0x21ad2c8c),LL(0xb15f6a2f,0x13ed2106),LL(0x9453ce96,0xa217b5f6),LL(0x64e0bf9c,0x93b1cdc7)}, {LL(0xc4fe8e72,0x753d894d),LL(0xf3a3916a,0x46c6cea3),LL(0x383dd581,0xc1fb78e1),LL(0x17376a3e,0x1b7ba1a9)}}, {{LL(0x5df66852,0xa1411287),LL(0xa30445d3,0x4e9d333c),LL(0x917568a9,0xb5a26c14),LL(0xe857a6ac,0x885f1857)}, {LL(0x84b1f8cf,0x05fbd3ee),LL(0x1e81e4e1,0x5c1f4097),LL(0x011f30e6,0x43999be4),LL(0xa890719d,0xa8aab3bd)}}, {{LL(0xc7088eb2,0x49d598ce),LL(0xe341047c,0x7a892468),LL(0x07cb6075,0x8e69b5c4),LL(0x8c37dc04,0x83d066fd)}, {LL(0x6ffff7ac,0x4fcc6d02),LL(0x7edfb968,0x1afaaf74),LL(0x70d529de,0x2972b753),LL(0x08218b2e,0xf65bff0d)}}, {{LL(0x4182b9fc,0x119b3c4b),LL(0x27b5e101,0xcab66591),LL(0x2ab87a02,0xfff2e939),LL(0xeec5949b,0x1c10c40d)}, {LL(0x30aa1242,0x98366224),LL(0xf225a4e7,0x833e9dee),LL(0x992e8475,0x07f1cfec),LL(0x1ef83a8a,0x377a9d79)}}, {{LL(0xc6715544,0xaf1d0863),LL(0x1fd71505,0x34dd65c1),LL(0x04fed293,0x74d55c22),LL(0x86d2f3be,0x31b1e50e)}, {LL(0xc09594ac,0x876148b9),LL(0x8900b56e,0x73aace3b),LL(0xa2cf4c37,0x4617258a),LL(0xc6f38a92,0x554e8f16)}}, {{LL(0xda0723bc,0xd8594800),LL(0xf3c8381d,0x524452df),LL(0x138ca980,0x846dfa02),LL(0xe2d32e56,0xaa77a80c)}, {LL(0x419c86b5,0x27573fbc),LL(0xb70216c3,0xe7486807),LL(0xc72036e6,0x8b7a685a),LL(0x15fae3d8,0xa1764627)}}, {{LL(0x815f379c,0x0a1f2361),LL(0x01ab64d2,0x9811607e),LL(0xff2c75cd,0x31841038),LL(0x474982aa,0x8751674e)}, {LL(0x52a2523f,0x2f32b55b),LL(0xe85f2025,0x6ff8d2a7),LL(0x707b2dcb,0xd2ec31ee),LL(0x6e277971,0xdac81e59)}}, {{LL(0x0e78191b,0x5445e3a2),LL(0x8c80db2f,0x134dba0b),LL(0x94002b55,0xe9925a87),LL(0x4293c71d,0xe56fa2be)}, {LL(0xa9d009c2,0x72aca4d2),LL(0x02fb0741,0x0c1219dd),LL(0x208fd227,0x689fbc66),LL(0xe4bb09d8,0x8266f2f7)}}, {{LL(0x2a61b8bb,0x1a791f9b),LL(0x3eff4f21,0xb29b31b7),LL(0xab7812db,0x2f97803a),LL(0x880ceb4c,0xdbf27bae)}, {LL(0x45e9db5b,0xecb84887),LL(0x5cb7d0ec,0x3dfd84e1),LL(0x77c0b1e0,0xc89f61c2),LL(0xb7656544,0x7ada1d37)}}, {{LL(0x910a966c,0x0bca9585),LL(0x6f12c20c,0x80385b47),LL(0xa4b30374,0xf63a1605),LL(0x104b4783,0x2f91b24c)}, {LL(0xb3ab423f,0x9210f5b9),LL(0x2fd424a6,0xb9aa656d),LL(0xf7e8d640,0x63c615d5),LL(0xbb59cfec,0xd567ff98)}}, {{LL(0xf7692947,0x78121697),LL(0xbd9f5ed5,0xb9166739),LL(0xb64b20e2,0x58d9a4f4),LL(0xc9fcc93c,0x291898d9)}, {LL(0xd6c6065a,0xbce6509e),LL(0xb84834a4,0x39af658f),LL(0x94b49185,0x0f919d44),LL(0x5dbe7308,0x3b80fc51)}}, {{LL(0xe321c228,0xb9fd8ae4),LL(0x360692ba,0x4a46bd2d),LL(0xd05b84b0,0x91d5396e),LL(0xd6b058d0,0x266e89fd)}, {LL(0xb2c42e38,0x6fb142d7),LL(0x994ebc2f,0x93c9fe18),LL(0x104b04a3,0x90e17885),LL(0x654eb6ac,0x6a5fa420)}}, {{LL(0x3f349b26,0x26c8a9b4),LL(0xb4e528ae,0x39387f7e),LL(0x5eb46726,0xa74bea43),LL(0x9150b043,0x0b3e82dc)}, {LL(0xe2fc799f,0xc69ffac9),LL(0x48921338,0xd0479697),LL(0x0a4e061b,0x91a68264),LL(0x3f410bcc,0x93a6c41e)}}, {{LL(0x6b1fb104,0xaea8d055),LL(0x31fe146f,0x2ff339a4),LL(0xcf63c413,0x3d7ef85b),LL(0x289a097b,0x1f0f57c5)}, {LL(0x5bda1160,0x82f2f83b),LL(0x6fea66e8,0x433eea4d),LL(0xcae11651,0x1f3fff4f),LL(0x6b1c243b,0xfa71c3fd)}}, {{LL(0x674832a4,0x59f36add),LL(0x2891e4e6,0x7b6d3802),LL(0x084fa3c6,0x47b313bc),LL(0x6584c9c0,0x90003ac6)}, {LL(0xbc802849,0x9718c2dd),LL(0x2870ca08,0x9a5a2698),LL(0xcf68f352,0xb5cfe625),LL(0x6e6b0caa,0x90d0e2ed)}}, {{LL(0xba64d50b,0xb30780c3),LL(0x7acb4fca,0x16328345),LL(0x84b258de,0xf64e01fd),LL(0x35dcd2f1,0x2a25873e)}, {LL(0xce4b39da,0x36606813),LL(0xa69a93e3,0x5285c91e),LL(0xdcb501d6,0x4da13aaa),LL(0x52e3dc24,0xb90d0a52)}}, {{LL(0x60a57d0f,0x6882d15e),LL(0x167612fe,0x52142caf),LL(0x463d39cc,0x532ccfb1),LL(0xe5a969f3,0xcdecde85)}, {LL(0xd1bc4480,0xa89c1d1d),LL(0x83f32199,0x9373f362),LL(0x6d653c44,0x42f3493d),LL(0x6c80e27e,0xa867e4db)}}, {{LL(0x5cb7623d,0x954fbd83),LL(0x0b83d55c,0xba8b3007),LL(0xe2b23256,0x71946b92),LL(0xfaf95492,0xe0a2a7bf)}, {LL(0x4e0c81ef,0x32ed3d91),LL(0x46f058d6,0xb8c8b14c),LL(0x67221924,0xc76c917f),LL(0x2ddf3cd4,0xd26c1d51)}}, {{LL(0x4fc9b14a,0x184e1395),LL(0xc1969b8b,0x651a0c29),LL(0xc9d5bf9c,0x05687179),LL(0xebcd85b6,0xb2f18ed1)}, {LL(0xe446f1ef,0x8b662764),LL(0x71699f5a,0x6c0e051e),LL(0x27d93da8,0xf94a1151),LL(0xa05fe7a4,0x751235c6)}}, {{LL(0x624e9ae2,0x40aaf88f),LL(0xf5f6e5c5,0x6499b3f5),LL(0x98157f61,0x01fb0b8e),LL(0x33827220,0x070438f3)}, {LL(0x50ab0b43,0x7409012f),LL(0x63c50e65,0xdbbba563),LL(0xc0d084ad,0x6b572ca3),LL(0x7b76cd6c,0xf10f6684)}}, {{LL(0x0c34363b,0x32bcca97),LL(0xb40e8157,0x7a9cef10),LL(0x6eaec234,0x3d5ffc51),LL(0x5f23d481,0x7d7b41a5)}, {LL(0xeecdfe73,0xe5276c22),LL(0x8ac8c30d,0xa9b2725b),LL(0xed0c743b,0xee449588),LL(0x48df73b7,0x6d3b82a3)}}, {{LL(0x023cb0df,0xcb52edc2),LL(0xd5a24591,0x08773a4d),LL(0xe12a9072,0x0d9a6aaa),LL(0x5bf5586e,0x4261f56f)}, {LL(0x60a08106,0x184b0402),LL(0xb09cfa61,0x1b398053),LL(0xd5dae483,0xdf7f55b1),LL(0x86ef2cde,0x9554210e)}}, }, /* digit=12 base_pwr=2^84 */ { {{LL(0x9204db30,0x564d6e85),LL(0x2aa84cdf,0x139bb928),LL(0x88476456,0x9413d7ea),LL(0x5a1ffa66,0x5c554483)}, {LL(0x2ed18080,0x7b863089),LL(0xd14e5daf,0x589aaf20),LL(0x7b5f81ca,0xeee4f96f),LL(0x1bb0b415,0x88d47007)}}, {{LL(0x55c9bd11,0x1bb400d3),LL(0x06fc2851,0x8402465c),LL(0x65063b3e,0xa81ba22d),LL(0x6e1aa0c6,0xbab2dcbc)}, {LL(0xbe645e25,0xe5f43f1a),LL(0x4df84be1,0x62320533),LL(0x21a2eaf4,0x14ac7080),LL(0x58beb26f,0x3f946464)}}, {{LL(0x7a82d20f,0x5f2a3e9a),LL(0x191011f2,0x399e015c),LL(0x886ac8e6,0xfbec312a),LL(0xeda47f96,0x0dd5140a)}, {LL(0x26b47318,0x0d4df313),LL(0xe6685ec8,0xe2c9ec78),LL(0xcd8442cd,0x4df119ae),LL(0x7b32a1cf,0xdb1ca955)}}, {{LL(0x126506cc,0x7e2c5852),LL(0x08b3567d,0xba94aac7),LL(0xc05a3f24,0x6905cdf4),LL(0x3547f8b3,0xbf5f559b)}, {LL(0xaade7a1d,0x9e4b4e62),LL(0x1fda3088,0x56b8b9d6),LL(0x4c43d89f,0xea3eb4c6),LL(0x9c69e047,0xfb7e537c)}}, {{LL(0xdfe5f6ab,0xc23d9491),LL(0xc1a9c0af,0x42fc362d),LL(0x127d2b35,0x04170b01),LL(0x04116aeb,0x4f0f17bc)}, {LL(0xc9184cf6,0x716c01df),LL(0x895ceae7,0x914dc877),LL(0x390bff2e,0x696b2ae8),LL(0xf88af5db,0xf6ccd628)}}, {{LL(0x0f88095a,0xdada9bb9),LL(0x919ce305,0x7155c28f),LL(0x6d78b266,0x32a01e47),LL(0xb652c4f8,0x6da94459)}, {LL(0x827ea8ef,0xa31783a6),LL(0xbdb1af2b,0x4d69b7c6),LL(0xaf31dab9,0x2874eb38),LL(0xafd9bace,0xa0ed9910)}}, {{LL(0x4037f17e,0x7d892e3a),LL(0x5f91a4fa,0x81fa9841),LL(0x961cf02f,0x17c7292d),LL(0x388bcc75,0x35af0c0e)}, {LL(0x127a29b0,0x340bec90),LL(0x3d087445,0x955714a4),LL(0xa587c273,0xfd430880),LL(0xd24dfda2,0x715ecd50)}}, {{LL(0xaafd6cef,0x4ade066d),LL(0xf8c1decc,0xce59c8de),LL(0x77b96ece,0x3e12a24a),LL(0x44cc710c,0xee7c32fc)}, {LL(0x240e9bb7,0x70700e4f),LL(0x6a63b06e,0x837ada54),LL(0xd19644ee,0xa58ce980),LL(0x27e7451c,0xcaa5d14d)}}, {{LL(0x387272fc,0x8e78d2ed),LL(0xfd8a0f13,0x9163a377),LL(0x635c55f0,0x858436bd),LL(0x5ba5b0eb,0x0a414f9b)}, {LL(0x7d7383b1,0x2b58373a),LL(0x6030a376,0x5e7b9d36),LL(0x543514ef,0x9c69af86),LL(0x26080ff3,0x044698cc)}}, {{LL(0xa2e23074,0x76f54954),LL(0x17526081,0x90393264),LL(0xf3b78a50,0x0d095055),LL(0x69d8b26d,0x1f3a3776)}, {LL(0xf5e7c8fb,0x0575e3bb),LL(0xee40b0c5,0xee7dd406),LL(0x55dab556,0xe6522e5d),LL(0xb61cd918,0x2d1b5709)}}, {{LL(0x01400b8d,0x0ea9278e),LL(0x6464f584,0x9552e745),LL(0x12fc094f,0x67f5645b),LL(0xde303128,0x77c40f3c)}, {LL(0x0e3f3381,0x16d7e9a5),LL(0x59947693,0x017795ab),LL(0x9222eaf5,0xb69b5708),LL(0x1b77f122,0x61b213e0)}}, {{LL(0xdc8db00e,0xa7cc8bbf),LL(0x3aa7fc1f,0x1c51f5e4),LL(0xb4ac2d0c,0xb85b782e),LL(0x0468e5ea,0x32fde94b)}, {LL(0x7f7ff0a9,0x8ad5b9a2),LL(0x8fdbb3f9,0xcd26f418),LL(0x6ebf89db,0x853bc95d),LL(0xa066b849,0x1da0a323)}}, {{LL(0x4bce0fa7,0xc4cc7aab),LL(0x6bc940f1,0xd4a05b69),LL(0x392dbd11,0xc77300e6),LL(0x21f70aae,0x0dc2eac6)}, {LL(0x4b2ad7e0,0x9d4b513b),LL(0xa6daee1d,0x19822167),LL(0x69b98eee,0x7d71d202),LL(0x35f3f150,0xdfd435dc)}}, {{LL(0xddfd45ed,0x66d46ad3),LL(0xe50a2f01,0xf0325189),LL(0x3ec5683d,0xe19b9500),LL(0x91dd97e9,0xc46ab0a2)}, {LL(0xed682c4a,0x74c971d7),LL(0xa14da289,0xafedac2d),LL(0xe39ba740,0xd17838fe),LL(0x053536bc,0xeb497bca)}}, {{LL(0xde6d4c38,0x551ba4ca),LL(0x4f52298b,0xa67be247),LL(0x9a5b40a8,0x98413188),LL(0xbb0acfb5,0x083a26aa)}, {LL(0x11d16ebb,0x4929ff5e),LL(0xa942ae7e,0x91f08b63),LL(0x876663ec,0xaa428ef3),LL(0x1e97cbb2,0xfaabd309)}}, {{LL(0xf1edd62f,0xca0ed50c),LL(0xd29f48d9,0xc3c7ae6f),LL(0x8a72ae88,0xff47bf28),LL(0x348c6666,0x584ddfe5)}, {LL(0x36731fdf,0x271137e9),LL(0x88d98bc8,0x714bc7db),LL(0x0da6be30,0xcea912c1),LL(0xbe62d6a5,0x91cb844d)}}, {{LL(0xec027bfa,0xe16ca42a),LL(0x17603e76,0x0c88f701),LL(0x63d5a31a,0x799418e3),LL(0xebb063f6,0x033bb53b)}, {LL(0x625d3909,0xbcd05461),LL(0x85f23129,0x2d7b7868),LL(0x95090997,0x23b07887),LL(0x18d2c218,0x216c08ae)}}, {{LL(0xeebdbcf9,0xe1ccb6c1),LL(0xe873842e,0x89ca4552),LL(0x3c2fcdd5,0x4837f137),LL(0x108a8c0a,0x805874e8)}, {LL(0x3d442fa7,0xe7e524f4),LL(0xf8131f8a,0x580d82be),LL(0x93d3d50f,0x6dcb7d27),LL(0xb5b39168,0x51207d3e)}}, {{LL(0x09110fe9,0x9a3ce117),LL(0x48721d93,0x8f3c6e4f),LL(0x87bdfa61,0x60a62b48),LL(0x7c01d84a,0x086dac65)}, {LL(0x53841493,0x4af7878c),LL(0xb3bd5aa1,0x3b1a8935),LL(0x902e5686,0x65c8445b),LL(0x2e3b1822,0xde16cfa5)}}, {{LL(0x0a3e3684,0x19879e78),LL(0xee249180,0xec553912),LL(0xf8f4c1ee,0x8eb73fae),LL(0xb81fd20d,0xdee59877)}, {LL(0x20b5ece3,0x2452e63f),LL(0xb632dddb,0x17be9422),LL(0x94311e6d,0x01f89220),LL(0xa332f84f,0x8f0fe052)}}, {{LL(0x1b9784d5,0x59657aab),LL(0xd8a7f347,0x6f2ce032),LL(0x6b95e6e9,0x84247793),LL(0x4395b044,0x34301cf4)}, {LL(0xf7fb5401,0x98ebfd98),LL(0xfcdb31a4,0x14fd494b),LL(0xf90e0481,0x042f89d8),LL(0x4134ab52,0x6b90a008)}}, {{LL(0x7fe2ffec,0x8fa22555),LL(0xa778448f,0xc6dc3d32),LL(0x85f45aad,0x4886fedb),LL(0x51704d0c,0x5bdef90e)}, {LL(0xe2d1fdaf,0x46ad596d),LL(0x04126f0d,0x914e0090),LL(0xaef960a6,0x71aaeb18),LL(0xac77472c,0x8f4601e5)}}, {{LL(0xd8d9768c,0x42e5a186),LL(0x00f6004f,0x8cbf3a6c),LL(0xc1ddebdc,0x9d4bf5ac),LL(0xa9c066fb,0x13354792)}, {LL(0x923fe808,0x72e0b81c),LL(0xc526d6e4,0x1e73b868),LL(0xa81f1e24,0x3f7bedc6),LL(0xe920ba24,0xed1ff363)}}, {{LL(0x659604c5,0x58234c89),LL(0xce4b0872,0xa6a421ad),LL(0xcc19578f,0x5dc8848a),LL(0x4f28bdfc,0xfcb418d0)}, {LL(0x8d6442f5,0xf2e74820),LL(0x4dcf6378,0x0c481d85),LL(0x4556438b,0x4987d1a6),LL(0x3157c6be,0x76359363)}}, {{LL(0x1c1dceef,0x29bbf3b7),LL(0x576f1dbd,0x0995c340),LL(0x8fa61304,0x0405db3d),LL(0xcc7d345e,0x63438f3d)}, {LL(0x942120e5,0x688174dd),LL(0xcd70c93c,0xc7dd05bd),LL(0x5e871ae0,0xdc8a32dc),LL(0x6178647a,0x1a7896b9)}}, {{LL(0x59c437e3,0x1fc3f7a2),LL(0x24235e5e,0x737de2e3),LL(0x7a5eaabd,0x589a56e3),LL(0xcca140f3,0x5a79da8e)}, {LL(0xa12463fa,0x3d8b0d82),LL(0x0875daf5,0x63fc83d8),LL(0xbd9211f7,0x42a30803),LL(0x32d3935f,0x62f6167f)}}, {{LL(0x6f269922,0x70cd6467),LL(0x96163b47,0xf694ca21),LL(0x5f5ba669,0xf3bafb2d),LL(0xb8ed8333,0xcf7cf341)}, {LL(0x9997edc2,0x34b2022d),LL(0x309c6508,0x57e6f4b5),LL(0x64841008,0xf6fbf864),LL(0xed075d44,0xbc9821f5)}}, {{LL(0xf37cc6b7,0x78c80f73),LL(0x6ab88fc2,0x41d28626),LL(0x58ca26fc,0x2126981c),LL(0xbe3dbf87,0x7a956c64)}, {LL(0xce0ce9f3,0x2f41e27d),LL(0xf4c98e5b,0x0cb49ae0),LL(0xcace473e,0xba6224a6),LL(0x393e092f,0x25dddbc0)}}, {{LL(0xa4fb974d,0x747daf46),LL(0xc76dbe2e,0xfb775fe7),LL(0x9670c22e,0xb7b3ad6d),LL(0x10a380bc,0xc6580b23)}, {LL(0x92087c3d,0x4ea226f5),LL(0xb53aa3c7,0xe67c379f),LL(0x991c3c9b,0x4133f831),LL(0x4fa0dd18,0x80f9e5bd)}}, {{LL(0xc6f80fb4,0x0094e7c6),LL(0x351bebd3,0x16e99ebc),LL(0xaae16a6f,0xc555ed44),LL(0x2f6367eb,0xe9d2846f)}, {LL(0x83d46d0f,0xb34c93d0),LL(0x894fadc6,0xc0cb137a),LL(0xab31f937,0x21e289f8),LL(0x1bc72a35,0xac5e0516)}}, {{LL(0xf3d4db0d,0x6221871b),LL(0xa039826c,0x72d1fdce),LL(0x668c8022,0x69d9cc8b),LL(0xfee064ff,0x0bf359ce)}, {LL(0xe8d16f19,0xb8e636b7),LL(0x443160ac,0xde88f403),LL(0x032836ee,0x4228177a),LL(0xe9801d86,0xee8fac37)}}, {{LL(0x4626e343,0x496c9363),LL(0xf4e4c8fa,0xf6999578),LL(0xb8648a06,0xce7306f6),LL(0xae7996e5,0xe2775c8c)}, {LL(0xbf09d221,0x7b47e678),LL(0x515c2ace,0xf5251e1e),LL(0x77b48b41,0x087f9121),LL(0xeb38d74b,0xc40e7725)}}, {{LL(0xce95134a,0x1d559f4a),LL(0x320c8bc6,0x1048a1bc),LL(0xe3085f1b,0xad2ddaf8),LL(0x0ad35636,0xf1cfc4cb)}, {LL(0x57db1e96,0x2bd8d4fb),LL(0xe1976ab7,0xd1813026),LL(0x15867022,0xa80e501c),LL(0x01f68017,0xecaf1497)}}, {{LL(0x48ab68b7,0xd82c5e79),LL(0x204d2962,0xa0f117e4),LL(0x7dedbf05,0x99b3bda1),LL(0x52786ecd,0xb872dbff)}, {LL(0x57592d3c,0x56253c32),LL(0x4d570c07,0x495fbb05),LL(0xfaecad3e,0x073c49cb),LL(0xb46bad46,0xec8c1f57)}}, {{LL(0xce3b07c7,0x13800a76),LL(0x0ffaec55,0x9bbf87d7),LL(0xaf2426c3,0xf69a9ee3),LL(0x2fd70c22,0x2d0c201f)}, {LL(0xc42bb661,0x957e5be1),LL(0x1dc771df,0x3e6ae19d),LL(0xe3cfafa7,0x60af970d),LL(0x5ebd1883,0x721ce869)}}, {{LL(0xb87d0ede,0xab0a80a5),LL(0x2954a3e3,0x33576f02),LL(0xc413fc00,0xcc2fe8c0),LL(0xeb86a18b,0x5ae762bd)}, {LL(0x3fe6c6dc,0xbc309dde),LL(0xbf0d1eb5,0xb4f9d001),LL(0xd4fa748c,0xf3f3c5b9),LL(0x2ca78fdd,0x78e8867f)}}, {{LL(0xcdf1624b,0x8f85f872),LL(0xa7db0248,0xfdce003b),LL(0x1ad9866b,0x0ad33ef7),LL(0x296248a4,0x27d12937)}, {LL(0xc99c656a,0x23bf35eb),LL(0x17753ace,0xcfb64da2),LL(0x6fbf7969,0x8bc0e741),LL(0xe719cff9,0x131018ef)}}, {{LL(0xd1c02b67,0x98f4ef66),LL(0x1f81f578,0xe8aa6cdb),LL(0x159469de,0xa6f97fb3),LL(0xe3906d9e,0xf8e834cd)}, {LL(0x71bbd3d1,0x33ccda6d),LL(0xf952c038,0xeac76a4a),LL(0xe5b53383,0x2891eaa0),LL(0xedcf6de7,0xd629dbdd)}}, {{LL(0xa3fb0fa1,0x4af093cd),LL(0x0d1ea294,0x130fd057),LL(0xb57747bf,0xb553cb13),LL(0x024e856b,0x107c0f0e)}, {LL(0xbd631fef,0xfd63a2ff),LL(0x12c01222,0x8df62ec2),LL(0xc0af11a9,0xacbce197),LL(0x5c4922b5,0x35fa3e80)}}, {{LL(0xc3de57ba,0xbc257ccf),LL(0x293ad2df,0xb481ca1c),LL(0x2058e222,0xb123f3bb),LL(0xefe46989,0x219cde82)}, {LL(0xe9a316da,0x58ac87b8),LL(0xd4d25c91,0xa8294237),LL(0x62d14158,0xb54dad88),LL(0xb3da2a84,0x9250885f)}}, {{LL(0xd54776bd,0xb4e3bedf),LL(0x78043ee5,0x81a4c582),LL(0x4eb87133,0x279a0963),LL(0xf2bfdb52,0x827d333c)}, {LL(0xed71e119,0x3601c6d1),LL(0x0d64df1d,0x3d9b1772),LL(0x3fa3c40e,0x2f5bcc09),LL(0x8e26aef5,0x74b7b30d)}}, {{LL(0x3d3ac848,0x98fd949b),LL(0x92e259f1,0xd99e99d0),LL(0x8d353c77,0x34404265),LL(0x4d8dfb1f,0xffc05a7d)}, {LL(0x4e9d92c9,0xbaf2f471),LL(0x5ea9cef3,0xf354f8b2),LL(0xb8b2c8a0,0xf2be0fea),LL(0xfbce308f,0xa392d3e3)}}, {{LL(0x02619258,0x58cd793d),LL(0xfea6eacc,0x16a8c9e7),LL(0xb90f9cb5,0x3fcae1ed),LL(0xd59bc4ce,0x1df76d07)}, {LL(0x8574a3ce,0x39248217),LL(0x03b6e82e,0x9d0df2b7),LL(0x33206733,0x64227c0f),LL(0xb342da7d,0xb909614f)}}, {{LL(0xb8e15a20,0xe46e977f),LL(0x744eaa18,0xdf2aa89d),LL(0x7ff12f89,0xa40b36b7),LL(0x86b0e7d4,0xbf7ed788)}, {LL(0x9e044a5b,0x35930c5c),LL(0x4ac6b8a0,0x599cfa2b),LL(0xa8f06839,0x68f5f40d),LL(0xe8a1b9d5,0xe838649b)}}, {{LL(0xdd45feda,0x2e3c91a9),LL(0x58de0625,0x5f73aa38),LL(0x7535cddc,0xcc2b2397),LL(0xca7825fa,0x60e69d0b)}, {LL(0x62424bd7,0x8f1a95c4),LL(0xf6f21e23,0x5e175a13),LL(0x4fa48b20,0x594e5b82),LL(0x9b14fed3,0x2bfed204)}}, {{LL(0x74484bc3,0x87c925fc),LL(0x5639abc5,0x052b634f),LL(0x290426dc,0x169549b6),LL(0xdaaefd38,0xfe515a22)}, {LL(0xb4d87ccb,0x8a63a39c),LL(0x4034acdc,0x3dec5f62),LL(0x61090db0,0x59969d81),LL(0xf157248d,0xb089b8f7)}}, {{LL(0x9d59a29f,0x42b0ca54),LL(0x9be7ee82,0x522b3e3e),LL(0xac166a7e,0x894aade2),LL(0x9184ec33,0x57aaf19a)}, {LL(0x5e50711a,0x84406a11),LL(0x1614f8d3,0x0cafd148),LL(0x3f7d19f8,0xc6174fdc),LL(0xff4958be,0xca5bed9a)}}, {{LL(0xe4fdd396,0x8dc18aaa),LL(0xd371c3f4,0xf6e8a9ee),LL(0xa5dfefde,0xc6b58042),LL(0xfc4f3577,0xccc3bbb6)}, {LL(0xdedfdd55,0x9f583e4a),LL(0xb48c5fb2,0x9ea45133),LL(0x232d61e0,0xca2b3229),LL(0xb0b5cb38,0x642101a8)}}, {{LL(0xa9ebda1a,0x0cfac5fc),LL(0xd2dc9c7c,0x02398bd6),LL(0x80591234,0xd95511d9),LL(0xe8230901,0x0e5cc99c)}, {LL(0x140eaba1,0x943350f6),LL(0xe0623c93,0x9fe19108),LL(0xd74e189b,0x052bf5d9),LL(0x40cd7173,0x3e341bff)}}, {{LL(0xcb7d384d,0x89b5b355),LL(0x50b76f18,0xedee32da),LL(0x5804d9df,0x6a9cfb19),LL(0x376fc2d8,0xccf638f8)}, {LL(0xe14de014,0xebdce7a5),LL(0x7f606fa5,0x0135085f),LL(0x69b58c3b,0xf8a3de5f),LL(0x59ca19d1,0xbaa80445)}}, {{LL(0x0ce7238d,0x3252147d),LL(0xd57bc36f,0xd446960b),LL(0xb275f5ca,0x9b1743ce),LL(0x27629de8,0xda048c48)}, {LL(0xd3bbac67,0x005354db),LL(0x1ba1facc,0x62c392fb),LL(0xa18da892,0xb066bfae),LL(0x367a8320,0xdb090711)}}, {{LL(0x6f90249a,0xbb7092e2),LL(0xe22da86b,0x6de14155),LL(0xb38d4ad8,0xe16136d3),LL(0xd0fbb940,0x9deaa5c9)}, {LL(0xaacf50e3,0x54a54ba3),LL(0xb9ba4570,0x66e5645a),LL(0x48cb742a,0x77e28d94),LL(0xed98a2c9,0xc795b138)}}, {{LL(0x1daa17ee,0x899331f6),LL(0x4a77734f,0xac950653),LL(0x71f3e3b6,0xd7f6304f),LL(0x65fc119c,0xe7256955)}, {LL(0xbe527794,0x3e60a04c),LL(0x7c578fb0,0xdaf53be4),LL(0xebc0754b,0xf785a4f8),LL(0xde1b78b4,0x8b21b116)}}, {{LL(0x62fb1c56,0xfe47e04f),LL(0x229f1017,0x8a92f9e6),LL(0x68b7842c,0x2d73dd23),LL(0xa56dbc4f,0x3b43f7dc)}, {LL(0xd0f3f4ca,0x9435defe),LL(0x500594e3,0xdabfb1ba),LL(0x428f5ead,0x70e929e8),LL(0xbdc7716e,0x44adf585)}}, {{LL(0x02204867,0x7b7ff077),LL(0x0c78476c,0xf2f306be),LL(0x7e783793,0x48849fd5),LL(0xaf77e3c7,0xc2dc3c7d)}, {LL(0xa980cdf6,0x5eb2b691),LL(0x204e25df,0x7ca7b7a4),LL(0xc5070eab,0x1e7c2f82),LL(0x4eb7cd3b,0x32ca4b36)}}, {{LL(0xf94ad1ab,0x38ffde8f),LL(0x59921b25,0xb4757ae1),LL(0xb4d2f624,0x856cd3f3),LL(0x1eb40708,0x90593929)}, {LL(0x1193b3e4,0xffc4b89a),LL(0xbd2f804f,0x6afba7a8),LL(0x69dc21ed,0x72aabbaa),LL(0xe7fb6de1,0x5d1da32e)}}, {{LL(0x98d1e26b,0x56c0f440),LL(0xf7cc7d6c,0x9456a6c3),LL(0x14f2f24d,0x9eb0aebb),LL(0x7dd788a5,0x51d7c699)}, {LL(0x46a22e97,0x053b8098),LL(0x8c025be8,0x27d8ea2a),LL(0x10d5afaa,0xe0bd464a),LL(0xe7cf120c,0x137c452d)}}, {{LL(0xd091397b,0xd06bd227),LL(0x21bc796f,0x4b307bf3),LL(0x7f5a37b0,0x701eaf3a),LL(0xac7d4718,0x8d5a0f61)}, {LL(0xed8b1a37,0x0cf9eea3),LL(0x2aa9061c,0x10854f10),LL(0xa30eb4e6,0x0aaf430c),LL(0x2a050dfb,0xb74342f5)}}, {{LL(0x20e1899f,0x2feee9d7),LL(0xf2a1dbfc,0x49464a8e),LL(0x5762d68e,0x4d7cf25e),LL(0x7bf43462,0xe7b6e759)}, {LL(0x79daf6e0,0x71fce284),LL(0x03858705,0x2d3ff71f),LL(0xbc4af4e6,0x07d8d288),LL(0x18f1c7d4,0x6777d197)}}, {{LL(0x0e85f036,0xb5770041),LL(0x4c8d9768,0xe1bb263e),LL(0xe3917798,0x4fcc1d44),LL(0x07abcde4,0x274d1d90)}, {LL(0xb7a10472,0xc9b8ae9f),LL(0x8d10e8ec,0x6632e3be),LL(0x50f3a172,0xb6876fb0),LL(0xb4cf4867,0x753692d4)}}, {{LL(0x58e598f7,0xfe3624e6),LL(0x6d81fb40,0x15f90418),LL(0x9bea3649,0xae762f7b),LL(0x161e85cb,0xc48d2262)}, {LL(0xcf5a21f0,0x8e8726a1),LL(0xa1f6653b,0x536c441f),LL(0x67ec5b86,0x0716bad0),LL(0xb2147d1f,0xa423a957)}}, {{LL(0xdca2e393,0x8eec96c8),LL(0x2843ef12,0x3619e36d),LL(0x2ef695e1,0xdc16fe2d),LL(0xffea8124,0x04ed2cad)}, {LL(0x180ce636,0x5018a0ce),LL(0xdce7b2f8,0xc34b0bbf),LL(0x0c54fc30,0x645a02a9),LL(0xf3f819d9,0x6ee6772b)}}, {{LL(0x7cecded6,0xe2bbbdcd),LL(0x3f038851,0x9ae4fd55),LL(0xa2f316c7,0xc30664ab),LL(0x63ffb50a,0x3cccf4a1)}, {LL(0xd00fb8f2,0xc37ee6ca),LL(0xad906eb1,0x593db6d5),LL(0x4aa84505,0x8f75b594),LL(0x9e5939f0,0xeff39d82)}}, {{LL(0xc064f530,0x4b7fab3c),LL(0xde175892,0x731153ae),LL(0x3d4c4e60,0x335e6503),LL(0x776ce13a,0xb0876a8a)}, {LL(0x22241ecd,0xa8a566ee),LL(0x011e861c,0xb7456b3e),LL(0x177dd490,0xa9aff4eb),LL(0xc8f77c40,0x189b1ed9)}}, }, /* digit=13 base_pwr=2^91 */ { {{LL(0x2857a1fc,0x624de687),LL(0x2ff8f505,0xbd0a0d9c),LL(0xc381bc9a,0xeecb4fad),LL(0xfa94e41b,0x72386292)}, {LL(0xe75fc753,0x354d3f83),LL(0xa7a5a6bf,0x06afc753),LL(0xb2f568dc,0x1ce792ee),LL(0xbd2f9647,0xc5faaee3)}}, {{LL(0xf912b74f,0x175fbeb0),LL(0x6e0ceedd,0x45fbe8e1),LL(0xd9233ee7,0xf0e1aa68),LL(0x406a626e,0xe55fc1ce)}, {LL(0xe08712e7,0x20efa1b9),LL(0xbcfd6360,0x5fd108b5),LL(0xeec1edac,0xea431df6),LL(0x940803f1,0xae1c0521)}}, {{LL(0x15407ffe,0x584a16d0),LL(0x08a82a69,0xa977f702),LL(0x67f8a198,0x52eefecf),LL(0x19f7a7e0,0xec213738)}, {LL(0x35987b9a,0x6795cfef),LL(0x97028480,0xb243403b),LL(0x9c1b9124,0xac24b12b),LL(0xa90f8aeb,0x1f379501)}}, {{LL(0x64bc0f09,0xa8e97fb6),LL(0xc953cd08,0x0b913991),LL(0x7fc3bf00,0x8385a1b3),LL(0xb09ccd8f,0xb6e74dec)}, {LL(0xec473ea7,0x6e1df026),LL(0x530766bd,0xf2f7fbbe),LL(0x3292052b,0xf18cb47a),LL(0x9114866a,0x7f8d4592)}}, {{LL(0x8bfa2c22,0xf0a1c565),LL(0x2b326c0e,0xc28518c3),LL(0xec107d66,0xabafc6f0),LL(0x8478907a,0xbc7a6abf)}, {LL(0xa2920288,0x8c1c8f6a),LL(0x930c043e,0x6c87579d),LL(0xb309696d,0x25ee808d),LL(0xb7a71041,0x433bbbda)}}, {{LL(0xb3086691,0x48d6d957),LL(0x26640916,0x9946a29b),LL(0x43db59a9,0x932ca93c),LL(0xe4fe91ba,0xaa61a0c5)}, {LL(0x815bf003,0x9e22e112),LL(0xc86ba8d3,0xa9ed1b18),LL(0x1069f434,0x1b5d3c14),LL(0x1cc01754,0x3cd2ebd0)}}, {{LL(0x3350f670,0x5c06b244),LL(0xf6f9c751,0x7557dc9d),LL(0xde66fd97,0xa7ebd3b8),LL(0x2befe6fe,0xc126dbaa)}, {LL(0x396f434a,0x312f4897),LL(0x61a4124d,0xe05cfcd6),LL(0x1525c05e,0xc83b8688),LL(0x11899f64,0x4646dbf2)}}, {{LL(0x8e419e08,0x2b7507cb),LL(0xaf855eec,0x785328d7),LL(0x7b8683a5,0x875db0c7),LL(0x90a597e9,0x3d1bc968)}, {LL(0x47eeeab4,0x7d4afa10),LL(0xd680ca71,0x2668dd43),LL(0x17365023,0xc3210d1f),LL(0x17fb31cc,0xd5bb2ee4)}}, {{LL(0x08e9ba09,0xbefb6a4f),LL(0xb0c1b6e1,0xc6beedb8),LL(0x3510ef35,0x59daf057),LL(0xdbbabc65,0x604047cf)}, {LL(0xa06b7340,0xfabc80a8),LL(0xdf765977,0x7433dee7),LL(0xfd807cfb,0x149a2c4a),LL(0x3480a086,0x14e8ad3b)}}, {{LL(0xb22c5f89,0xb0c3156f),LL(0xbf78675a,0xd10ece4a),LL(0x80b8ad9f,0xe270e317),LL(0xb0c2b420,0xfe7a6210)}, {LL(0x125ef635,0xf091d738),LL(0xc1a6f202,0xf1f277d6),LL(0x3587d9bb,0xe2727e7b),LL(0xb3e2b84b,0x83b209a9)}}, {{LL(0x7a13effa,0xc9eb445d),LL(0x0d697480,0x89b856f1),LL(0x25c03cb7,0x834bbae2),LL(0xe0b4a7b2,0x0d8adb85)}, {LL(0xc7fbc240,0x7b6884af),LL(0xaa4f9097,0x6b485409),LL(0x290c106f,0x4d0a367f),LL(0x3f0efdfd,0xab87d218)}}, {{LL(0x50f2b65b,0x15b9bab7),LL(0x5e5d53e4,0xa7403d4b),LL(0x28529212,0x2e23e376),LL(0x6e050767,0x6fe903a2)}, {LL(0x6cf570fb,0x4c5291a1),LL(0x7a30b326,0x4bfb8607),LL(0x27c572a9,0xec4905f8),LL(0x0f381c31,0x72eeb8c9)}}, {{LL(0x460adca0,0x33346cec),LL(0x7b34756a,0xd4d5bba8),LL(0xeac84add,0x02b2e2d4),LL(0xdc1053b5,0xa129845b)}, {LL(0xdca6f9ce,0x53f067e0),LL(0x3526aba6,0x6e9998ed),LL(0x1c0982da,0xa4aef9e2),LL(0x93f5d96f,0xfe5b606e)}}, {{LL(0x9c14b699,0x26b8502e),LL(0x0948a291,0xf1bcdca6),LL(0x2aefd415,0x73e43a32),LL(0xd1e2cfb5,0x7f523357)}, {LL(0x97d3fa94,0xa60151c0),LL(0x72129630,0x820c0d58),LL(0x5854acf5,0xb8f2e1ed),LL(0x3c656ac3,0x86d6646c)}}, {{LL(0xbef1d0da,0x2284a612),LL(0xa8c8faba,0x2e7c5f4e),LL(0x70303ea3,0xfd441ae7),LL(0x5161cf82,0x9613f329)}, {LL(0x2e19531f,0x65a3cc65),LL(0x34281f69,0x177a2775),LL(0x7c82e094,0x0cc692a4),LL(0xb6f377f0,0x9d62a55b)}}, {{LL(0xf96ec2b8,0xa24cf6ac),LL(0xa961cc16,0xd06747c3),LL(0xbd17f0a2,0x57c7001c),LL(0x34afe2d6,0x5f298db0)}, {LL(0xdf12f671,0x51b01ef2),LL(0x5ce712fe,0xc01c5066),LL(0x92a74776,0xac0f4034),LL(0x08d696bd,0xa3e9934f)}}, {{LL(0xe7daaff8,0xafb6981a),LL(0x73bdcafc,0x5f8998d9),LL(0xbaf9906c,0x23ec39e1),LL(0xc999c9c0,0x5e248410)}, {LL(0x17dad895,0xd14c7a89),LL(0xcbb3f6b9,0xfde9d01a),LL(0x5f698f1b,0x1d6b26ef),LL(0xf0baff97,0xc6495cd1)}}, {{LL(0x587674ec,0x5a72dc07),LL(0xdb09cd65,0x100f9ff0),LL(0xb30cf6e6,0xec0fb71f),LL(0x81066143,0xf54cb597)}, {LL(0x633857c4,0x0090e997),LL(0xda92c5d2,0x7326ed15),LL(0x47c56e86,0x794cd8af),LL(0xf89214c9,0xb272112f)}}, {{LL(0x3445879d,0x37960861),LL(0xf2fcfc55,0xc5e496b0),LL(0x6559e153,0xfe74e95f),LL(0x54a772af,0x1e18b2b5)}, {LL(0x157c157c,0xd146980c),LL(0xa11d77b5,0x31ee3f25),LL(0x5707db6d,0x7762a07d),LL(0xbd2022b8,0x00804bcb)}}, {{LL(0xd571c59e,0xdf3f4658),LL(0xcf45c1ee,0xc49e7a34),LL(0x43972cff,0xf401ba3d),LL(0xe509c2b6,0x146d989c)}, {LL(0xeb72392f,0x7c68d6c8),LL(0x0658b8e6,0xdd048de5),LL(0x9a0aeb72,0xc9dc61b7),LL(0xb741d644,0x98b080e0)}}, {{LL(0xb1c5982a,0xa6ec0eed),LL(0x5ebbc26f,0x58d28317),LL(0x33e5b7dc,0xac8f1e1e),LL(0x9d8f9fed,0x31e4f65e)}, {LL(0x904ad76d,0x6c9af383),LL(0x9bdb0517,0xfc38c53c),LL(0x0e69f85e,0x9ae278ee),LL(0xefd9d887,0x18b362b7)}}, {{LL(0x5bbbd3ac,0x65a5f74b),LL(0x077bfb4f,0x41eb4593),LL(0x83b38100,0xb642934b),LL(0xac1a99bb,0x643ceed7)}, {LL(0xee7cd5f7,0x9c27e66d),LL(0x6ddbaa6b,0x2ccf87d5),LL(0x447b1192,0xd51ca739),LL(0x95f5f142,0x78471053)}}, {{LL(0x3a650829,0x915f50cd),LL(0x898a6a1c,0xe032bdc5),LL(0x2d15959f,0xde8fb4f1),LL(0xbad56140,0x1fc5fc73)}, {LL(0x8e60c3c3,0xdafbf206),LL(0xe428adb5,0x4963dc95),LL(0xd49584fb,0x1538e081),LL(0xbc0e5fa9,0xb34add66)}}, {{LL(0xa7f28b2f,0x404ecf12),LL(0x7fa9c435,0x6ddc3ce1),LL(0x61ee755e,0xda887e3f),LL(0x8f71280a,0x4b5da661)}, {LL(0xdc79a4cd,0xee5a86df),LL(0x99be4d36,0xd8514b8a),LL(0xcc82c751,0x674793ea),LL(0x437aedcd,0xf3a2123a)}}, {{LL(0xfcd6f027,0xf825ff37),LL(0xa681a001,0x60a056d8),LL(0xaa92c135,0x92a39248),LL(0xdcd190a7,0x61884e23)}, {LL(0x24cc911c,0xec0d1420),LL(0x5aa16ad7,0xbdb0baae),LL(0x8a1694d7,0xf12726b5),LL(0xc93673f9,0x8c7cf113)}}, {{LL(0x7f2edc38,0x02fb6c69),LL(0x2fbe8690,0xcc4d4304),LL(0xe89c80d5,0x405b2491),LL(0x3d938bc1,0xdef46c76)}, {LL(0x2520e3b0,0xd92ec0fa),LL(0x1fe2dfda,0x2501cfa3),LL(0x1d5c8474,0xe7c5753d),LL(0xe6226dcf,0xc059abc0)}}, {{LL(0x55a9011d,0x2dceefe6),LL(0xbbbbef00,0x8799064a),LL(0x0b49b5ef,0x7fe944c2),LL(0x225b21dc,0x722bbef0)}, {LL(0xd2bb14af,0x84687cbb),LL(0x9b6f6caf,0xfc4ab4f0),LL(0x2c146a52,0xb7b7bb59),LL(0x1dfea10b,0xb90d67f2)}}, {{LL(0x713e1d30,0xca4ca8c8),LL(0xf8a13db8,0x50cbb994),LL(0xa5b0e3e5,0x2bee12b2),LL(0xe71e19fb,0xa7c5d6d1)}, {LL(0x9e0314cd,0x28442423),LL(0x66cda5c0,0xc95c2746),LL(0x1c5ffd19,0xfe52a79a),LL(0x38a0339f,0xb93875cc)}}, {{LL(0xb49fb049,0x6a94196c),LL(0xcc12a38d,0xbeb1eb4b),LL(0xf5e8d167,0xbc136771),LL(0xd5f8ae87,0xa91e1232)}, {LL(0x95172460,0xb2e812c7),LL(0xb8f81870,0xc699d376),LL(0xa8900827,0x9e4a3b70),LL(0x506c0b29,0xe0d4b2f4)}}, {{LL(0x7246fd96,0x13b4d1c7),LL(0x33965581,0x84ea2158),LL(0x2e53c024,0x9b9f071b),LL(0x864a1b78,0xcb005908)}, {LL(0x3f742c2f,0x03daddf5),LL(0xdf595911,0xd29230e5),LL(0xca0406a1,0x3f7d4e6b),LL(0xb1db7e47,0xeb646f66)}}, {{LL(0x590e3107,0xb896003e),LL(0xf754ac01,0x7a0dc361),LL(0xe63ab0ac,0xe877a6f3),LL(0xdf60d307,0xd43b54f3)}, {LL(0x59cf0add,0x65ef91ba),LL(0x18990eb4,0x35e99393),LL(0x8e46fbf6,0xc186ab16),LL(0x8c1eaa91,0x4c0eb22f)}}, {{LL(0x1abd31f0,0x4599b894),LL(0x9a1da7d3,0xdb34198d),LL(0xa0f0217d,0xa8b89523),LL(0xe56b884e,0x2014cc43)}, {LL(0x49efd4ee,0x6fb94f88),LL(0x287f4ae0,0xf1b81710),LL(0x99fd2deb,0x89d38a9a),LL(0x72b67a53,0x8179277a)}}, {{LL(0x1a03755b,0x0ef6ce56),LL(0xfcdb3469,0x8dc768f2),LL(0xa21d959d,0x0be58a91),LL(0x9b103cd0,0xea44861a)}, {LL(0x808b8a46,0x332e86e7),LL(0x8772c3f8,0x9882015c),LL(0x9f4b5d29,0xe6b272fe),LL(0xa29b023b,0x0e183a28)}}, {{LL(0x2286ebf3,0xf2fab88f),LL(0xfce83e6f,0xb7532ced),LL(0xe0cde4fc,0x17999d7c),LL(0xc1b7668a,0x7230fd85)}, {LL(0xef588309,0x97a57d39),LL(0xf906f6e7,0x7e175f28),LL(0x72b70bfe,0x51f67413),LL(0x2f82218c,0x2132f595)}}, {{LL(0x9d8727cb,0x9cc0746e),LL(0xbba1ec8e,0xa2af77fb),LL(0x31a67cc9,0xc75aee60),LL(0x57408325,0xaeab9e0f)}, {LL(0xec34bb89,0xf24de697),LL(0x5d958bdf,0x06b90039),LL(0x0603d6cc,0x6f55222e),LL(0x2eb0b239,0x496537b5)}}, {{LL(0x8be08323,0x083e5889),LL(0xf8dc0a78,0xc573596e),LL(0xe8901eca,0xc3e988fa),LL(0x6e350257,0x7f7b48f6)}, {LL(0xa216e329,0xed820567),LL(0x8ce989c1,0x55f46737),LL(0xeeab9441,0x7f48c5f1),LL(0x86fe0831,0x1d3cac11)}}, {{LL(0x408a0306,0xe0364bae),LL(0x7a4eb2cb,0xe8d8aba0),LL(0x1fd7d5da,0xe548725e),LL(0xed5ed958,0x8de04491)}, {LL(0x61d73977,0x3e75eba2),LL(0x55420386,0x4f580400),LL(0xd859a690,0x54642fa4),LL(0x296e336e,0x2c905f7e)}}, {{LL(0x22e260bc,0x4e287e66),LL(0x4a28d5bd,0x71a2ec99),LL(0xa7c5c3e3,0x5528da21),LL(0xa49471e0,0xae9f6856)}, {LL(0x587cd94f,0xdcd8e66b),LL(0x6c7b7db8,0x91afbd79),LL(0x067e3cdd,0xdf2e6625),LL(0xa6375f59,0x15b5a329)}}, {{LL(0xb6586c5f,0x3b8b3b1d),LL(0xd34f10fb,0xe4d50a77),LL(0x7c3c01f7,0x26cb86f5),LL(0x8c57e6f7,0x36e9d3cc)}, {LL(0x62c6dbae,0xaa8e7ce1),LL(0x60d7fae5,0x7f6b7689),LL(0xc797ee16,0x519a7659),LL(0xb36a6b1b,0xa1c7b30e)}}, {{LL(0x74dff201,0x8da05ba6),LL(0x40d0a835,0xd2eac07f),LL(0x610a7d6f,0x2701eb31),LL(0xbf893c4f,0x5c17a91e)}, {LL(0x6bc8b161,0x68b92e88),LL(0xf52e6ec0,0xa312fd5b),LL(0x6b7952cf,0xf7daf460),LL(0x18aeb57a,0x847f0cf3)}}, {{LL(0xb0146708,0x27b178ed),LL(0x54ca2aa5,0x85a23554),LL(0x395a7b16,0x80dd123c),LL(0x0058bfce,0x64a9337b)}, {LL(0xf4addc4a,0xf6ae9380),LL(0x464536f1,0x0f84385a),LL(0x16534f6c,0x41fc2270),LL(0xb8795ec3,0x13d8976f)}}, {{LL(0x8e12c560,0x2e90b3e4),LL(0x239b2c58,0x242a86ec),LL(0x0768275c,0x6fb42ecc),LL(0xbd96de9e,0xee341cd0)}, {LL(0x84355d11,0xfd1833ac),LL(0x5f55ec6c,0xf062392c),LL(0xfee33fba,0x6ee7b59b),LL(0xabf86e0f,0x8113f0ca)}}, {{LL(0xcc68033c,0x2285aaaf),LL(0x78430646,0x850b732b),LL(0x2b3fa03d,0x50fa4b61),LL(0x3caf050d,0x4d893ecc)}, {LL(0x988df419,0x454764e6),LL(0xfb61f1a4,0x055d8a4b),LL(0x8475e07a,0x3b7c5f4b),LL(0xa6a228e4,0xf93a198b)}}, {{LL(0xec8d566a,0xe0a8ce61),LL(0xc55f4bd6,0xe41397d6),LL(0x654bdf55,0x4cc18d48),LL(0x9325ac25,0xe1b49f9e)}, {LL(0x72c68871,0x79840752),LL(0x6d806fe8,0x8930d8b5),LL(0x0bd5f65e,0x11c8b5a8),LL(0xbf37d7a8,0xe931c025)}}, {{LL(0xae8af083,0x25b17fd9),LL(0xde4215ed,0xd589fd8b),LL(0x4b3f61fd,0x56378f04),LL(0x6bfb4f9a,0xf0f39213)}, {LL(0xe906cc6a,0x6b0f9596),LL(0x096f8296,0x441f13da),LL(0x1e4940e0,0x08f933d4),LL(0x5a53e7ee,0x6c35391c)}}, {{LL(0x19c3d18e,0x5f41c4d3),LL(0x1d389d95,0xc0804e09),LL(0x18a5a3f2,0x7323a9ab),LL(0x410a6381,0x7b7c2475)}, {LL(0xb02cfe18,0xd362eb9a),LL(0x553b2970,0x79ef3d0a),LL(0x3d2acdab,0x371f7760),LL(0x7f241dfd,0x6cd37890)}}, {{LL(0xdf4a28e4,0x592a242e),LL(0x1bb45217,0x1e623cdc),LL(0x494074d3,0x5a9633a6),LL(0xd52fbfd8,0x81b74307)}, {LL(0xdec4c5ff,0x98292651),LL(0x3e0f6edf,0xe1b7bc86),LL(0x6bb8fb31,0x3d5fd86a),LL(0x1cf29f19,0xa830e9a2)}}, {{LL(0xcf69c747,0xfffc5482),LL(0xa83549fd,0x7748a0f4),LL(0xe7ccf4a6,0xba1c8a0d),LL(0xa2ede6b7,0x6cd1399a)}, {LL(0x87bb90d9,0x8fb634e6),LL(0xc59a5304,0xfa8e659b),LL(0xa9122d95,0xcd6bfc75),LL(0xdfa6d75a,0xdb107def)}}, {{LL(0xcc27760a,0xb0ec4cfc),LL(0xbed3a1a1,0xf24c1e22),LL(0x819bffc7,0x4f8522a1),LL(0xa93d97e1,0x263c7b5b)}, {LL(0xa4b4de49,0xab1d31e0),LL(0xebbfe8f5,0x374e968b),LL(0x51ca0d08,0xe82e9756),LL(0x7df3f2df,0xc05715a2)}}, {{LL(0x038004ad,0x941f02c5),LL(0xa0fd46d4,0xc136a2a5),LL(0x3d31d26c,0x85db7d24),LL(0xbfefeecc,0x05bba6af)}, {LL(0x5a60aebf,0xf803b539),LL(0x813d0e6d,0x9bb8a479),LL(0x066abdfb,0xb689c813),LL(0x0072e530,0xd93b3f4b)}}, {{LL(0x987446ad,0x242140a4),LL(0x06a02f0c,0x40b3f709),LL(0xa0fd6018,0x33f9bf20),LL(0xf21abfdc,0x58517c18)}, {LL(0xc1f80f3f,0xa33dc5db),LL(0x7ec91c80,0xbb7dfe27),LL(0x8ca97dd8,0xd2cf9338),LL(0x32e43d44,0x5761f871)}}, {{LL(0xe513ea90,0x3c8ffb0e),LL(0x79bcdecc,0x91ecda36),LL(0x9b1a5514,0xdad3fdd5),LL(0x640d3af0,0x8fb630f9)}, {LL(0xf9d2e0be,0x82949b09),LL(0xeba23663,0x079ca0ff),LL(0x135238d4,0x51e62c53),LL(0xc446bd67,0xf5fa0c61)}}, {{LL(0xe8da43d6,0x19dcdd2f),LL(0x95f29b5b,0x46fbf7ea),LL(0x635e8388,0x7f3eaa05),LL(0x5369750b,0x5ef817c3)}, {LL(0xc860c4aa,0x06025893),LL(0x5551c9ef,0xa2f6684d),LL(0xfbc0c667,0xd6af67dc),LL(0xcd2fe44b,0xfd8d7394)}}, {{LL(0x302a17cc,0x011968ae),LL(0xc3e5a5cb,0x2206ff24),LL(0xa20dbfb7,0x4c7f0df3),LL(0xa395dd6f,0x59566376)}, {LL(0x373ea76b,0x68ff3d9f),LL(0xf6cf8ada,0x2394f93a),LL(0xe7514a94,0x3acc5dba),LL(0x5ddfa11b,0x0340da7a)}}, {{LL(0x1a05155d,0xc3f03022),LL(0x4f7656c0,0x6cbbdc6b),LL(0x0b0875f5,0x6e30dbdd),LL(0x3471b0d5,0x5e7c2883)}, {LL(0x408b4bc8,0x49cfd71c),LL(0xf01c002b,0xd29a184e),LL(0xff415b0f,0x308be85c),LL(0x01a8fe7d,0x1b4176f0)}}, {{LL(0x0c33bed3,0xb850acc7),LL(0x23af7af0,0x76aac640),LL(0x21d5853f,0x049187ee),LL(0x6620195c,0x44fbf6e5)}, {LL(0x36158178,0xf0abf14b),LL(0x90e419c2,0x9866ffca),LL(0x9e8523a8,0x7522e277),LL(0x08e90f1d,0x2f2590f3)}}, {{LL(0x66d3f75b,0xde1c0c52),LL(0x6c299b57,0x47dc9ceb),LL(0x51f7f2b5,0x4ad12847),LL(0x452b07a5,0xeedf9d8d)}, {LL(0x3dad76c6,0x207b0627),LL(0x5d4c0280,0xccbb5201),LL(0xb019ae8d,0x0bdca05b),LL(0xf2da7eb4,0xb5f8d088)}}, {{LL(0x4626c00c,0x4e79a0be),LL(0x5af82c0f,0xf6fdd64f),LL(0x5f7cba0f,0x7a828224),LL(0xb0765493,0xc2214834)}, {LL(0xabd53ccf,0x5b0d0d1a),LL(0xf4a1b517,0x3b03a22d),LL(0x6ece453e,0xb235c862),LL(0xf66471c7,0xf43ac344)}}, {{LL(0xa1552fa5,0xeaff93dd),LL(0xcf3ae702,0xef1b40dc),LL(0x9ca613a4,0x35ced3fd),LL(0xa2f33a0d,0x90e350ab)}, {LL(0x002b5738,0x47bb89aa),LL(0x032b8b08,0xafc01bba),LL(0x61588b4b,0x688ae119),LL(0xcf66ef14,0xdb7d820a)}}, {{LL(0x084910bf,0x83b654db),LL(0x60ea75a1,0xbb581f8b),LL(0x1cdae7c4,0x6917f282),LL(0xa40a07c3,0xb719f931)}, {LL(0x31297b3b,0xf8efb8b9),LL(0x4d6fc5c6,0x74246ded),LL(0xd2c61503,0x5a111754),LL(0x71654764,0xf64d2b88)}}, {{LL(0x6ad8f168,0x4b452692),LL(0x0cc6fc91,0x907beb21),LL(0xbf13c18b,0xe876d523),LL(0x4cf37ca1,0x4d28e457)}, {LL(0x6d3d1172,0x4c0dc22d),LL(0x5a753137,0x7935a8d2),LL(0xda44d652,0x03484e3d),LL(0xc50025a9,0x05a3d80f)}}, {{LL(0xff477c6d,0x6d43c503),LL(0x1ccd416a,0x35f4c4cf),LL(0xd5088349,0x7070f471),LL(0x281d30c8,0x678460ca)}, {LL(0xc6defb33,0x8923cd9a),LL(0xe2557cab,0x44930f56),LL(0xad156c4a,0x33b020bb),LL(0xbcaf4805,0xfdab31e3)}}, {{LL(0x864b5564,0xffe79bec),LL(0x10c60d52,0x0510e352),LL(0x328a652e,0x66203aaf),LL(0x54fea042,0x9d5403bf)}, {LL(0x6e5e5c7c,0xb3fe6743),LL(0xecc66e02,0x6deef667),LL(0x44eacacb,0x199ee152),LL(0xd8803fd9,0x9f49fcd4)}}, {{LL(0x2d3a6e28,0xdd5fee9e),LL(0x686d8ca3,0x8eed56d4),LL(0x78083491,0x36889a27),LL(0xbef20457,0xea1a6555)}, {LL(0xa501e2a3,0xe7e6b609),LL(0xfb23de2f,0x1ea0ae29),LL(0x632c9a6b,0x5f537d07),LL(0x9a3db961,0x61770d1f)}}, }, /* digit=14 base_pwr=2^98 */ { {{LL(0x7497e8a5,0x325c60db),LL(0x8c6949a9,0x05d8eab8),LL(0xc7bd5898,0x3169e466),LL(0x192d8e3f,0xadc06264)}, {LL(0xd55959fe,0x1ff468f4),LL(0x202dba19,0x97b33ee0),LL(0x21cf84bb,0xaa0c3fe2),LL(0x04a8d176,0x48cdc0af)}}, {{LL(0x9c0d4009,0x53d8c448),LL(0x2e24dbaa,0xd3714617),LL(0x9b62e5f1,0xdd92e730),LL(0x9922cc8a,0x97b344d7)}, {LL(0x0bfe3e8f,0x416b009b),LL(0xf3c82269,0x56873834),LL(0xe6623555,0xf82a980f),LL(0x5ce68e54,0xb027ecaa)}}, {{LL(0xfe87680d,0x005a4b24),LL(0x4cf6ee32,0xd92532dc),LL(0x4bd3e01f,0xfcd27c8c),LL(0xe1b59ffa,0xda7d9949)}, {LL(0x2735d373,0xe3d5f31f),LL(0x288e71fb,0x7e139ca5),LL(0x93979cb4,0xe474bc80),LL(0xf6fcc665,0x7f4f6017)}}, {{LL(0xfbd613c3,0xe6982c86),LL(0xc366f17a,0xf4af69d5),LL(0xb85c2343,0x8683eed6),LL(0x24bc2116,0xf5bb244a)}, {LL(0xc9fc77d4,0x997a74bc),LL(0x6f44b54b,0xe202eb91),LL(0xa6997e76,0x77886412),LL(0x02c8837e,0x6996c8fb)}}, {{LL(0x2c61382c,0x0986df8a),LL(0x667c8ee9,0x90607b92),LL(0x084eacde,0x051fcbf7),LL(0x6e685877,0x84e3dba4)}, {LL(0xe458da50,0x35861a82),LL(0xcf392b51,0xd036823f),LL(0x3dd86e74,0x43181481),LL(0x3741a385,0x8dcfe17d)}}, {{LL(0x40f56786,0x8e1a77cf),LL(0x6d4b7774,0xc5bca7f6),LL(0xc81ec077,0x86b588a0),LL(0x9206354f,0x88952a01)}, {LL(0x43a8519a,0x5444a989),LL(0x2857b210,0xe29dd68c),LL(0x9a144624,0x36658903),LL(0xe423e899,0x8c4dedb0)}}, {{LL(0xea886e5c,0x482040c5),LL(0x1cdd50f7,0x42fe5a56),LL(0x453b6e7f,0xf034f132),LL(0xb3c69762,0xba3fa97d)}, {LL(0xcadb598e,0x34262560),LL(0x07afe0a8,0x7ed74b51),LL(0xebe0e8bb,0x2261d849),LL(0x608cea1c,0x23747e55)}}, {{LL(0x902c343d,0xb2e9371c),LL(0xda4fdba1,0xf57b2de8),LL(0xb67703a1,0x43f9afa4),LL(0xf79fe203,0xeafafb41)}, {LL(0xf649a494,0xfec99dc9),LL(0xfe378232,0x14799ef9),LL(0x7184e31e,0xba3f8114),LL(0xdc0e987f,0x0abbb815)}}, {{LL(0x6fb5d02c,0x1dc7221f),LL(0x40f1607c,0xa0dfb113),LL(0xdbe8db86,0xd217f238),LL(0xe91f2859,0xc02547eb)}, {LL(0xa98d0875,0x41df6bcb),LL(0x78f6be54,0xf51a8077),LL(0xba66bef5,0x3ebdf28d),LL(0x9175ec20,0xc65c7b38)}}, {{LL(0x475589d5,0x2302981d),LL(0x199d8ad4,0xbd479708),LL(0x8db46795,0xcb508be9),LL(0x6b224eb4,0xba1e066e)}, {LL(0x1326ab8a,0xae909633),LL(0xf5bbe5e6,0xac989728),LL(0xb1729b41,0x1de663f5),LL(0x00c3d293,0x2018f58c)}}, {{LL(0x71efe25b,0xe647c0e6),LL(0x6104ebd6,0xaa30f871),LL(0x3c166de6,0x1003eebe),LL(0x1cbc42d3,0x0c308538)}, {LL(0x56cba120,0x98b6c312),LL(0x860d2916,0x9065ae66),LL(0xa7dabb6b,0x2162062b),LL(0x8e011036,0x1422386b)}}, {{LL(0xe069de1c,0xd2589ad6),LL(0x7ee09300,0x3fe8e67a),LL(0x2f8ae49b,0x5b881860),LL(0x263a6a90,0x186a1482)}, {LL(0x9b35b33a,0xc6079b39),LL(0x53d3411d,0x6c38d789),LL(0x720b2f99,0x743c4462),LL(0x29e14d08,0x4d903dd7)}}, {{LL(0x7b963913,0x625dfce0),LL(0xcc65e41f,0x60a83daf),LL(0x93e185a2,0x9e88c26c),LL(0x13707ac3,0x6d950e92)}, {LL(0xa0a23dd0,0xbd7df2dc),LL(0xc2116cc8,0x5fad27f2),LL(0xda4430be,0x0703b868),LL(0x83cc41df,0x5ebf0e2f)}}, {{LL(0xf9e83fc8,0xebb91900),LL(0x6d60bb8a,0xf9539591),LL(0xb604935a,0x3bdd7a8b),LL(0x64e5eec0,0x2cae8c67)}, {LL(0x60aaf21d,0x30cf58bb),LL(0x359f63cc,0x5e0f6f5d),LL(0x0547e03a,0xda245055),LL(0xb9e143ce,0xa83fd8bb)}}, {{LL(0x1b0215aa,0xa564435a),LL(0x354ba769,0xecffccec),LL(0xbdbbd594,0xd846149a),LL(0x65dd1597,0x9137df36)}, {LL(0xa9f3ac33,0xc4f39f37),LL(0x961d7e8d,0xf594bb74),LL(0x835befbc,0x41fa4b58),LL(0xed79139e,0xa983eae9)}}, {{LL(0xb4e31aa4,0xd4085efc),LL(0x18b26adf,0xc760aec0),LL(0x76a7400d,0x14c1f78e),LL(0x317fe128,0x87b8aced)}, {LL(0xcbd85bb4,0x4433582e),LL(0x86adc041,0x58f01426),LL(0x8f0d5781,0x3596dd50),LL(0x1a31a82f,0x2e7f3b80)}}, {{LL(0x2d1ede3e,0xcac7ccc8),LL(0xe89573db,0xc9b9a8f3),LL(0x54b40df9,0xbf744f69),LL(0xa85ecb47,0x88eb2281)}, {LL(0x426ec49d,0x6b115026),LL(0xc8c41110,0xebda4660),LL(0xdf392aae,0x0a4a32ac),LL(0x37cb7080,0x2a28f9b3)}}, {{LL(0x6bd9414d,0xfed99d1a),LL(0x5715620e,0x15f59c41),LL(0xac431919,0x93edd9fc),LL(0xe1ccc47f,0xed1d43ae)}, {LL(0x556d1ab5,0xafed2acd),LL(0x02e039c0,0x817b967d),LL(0xe02a68bb,0x335d15da),LL(0x67df767c,0x4fa75ea0)}}, {{LL(0x44833943,0x384704b3),LL(0x4084ef35,0x7809ed3c),LL(0x79c7ff41,0x2abab3c4),LL(0xa833fb73,0x2b7ef5b2)}, {LL(0x4901a4ff,0x12b0335b),LL(0x44d58617,0x3eea607b),LL(0xd7f57746,0x7161b669),LL(0xb1e93442,0xee17e43f)}}, {{LL(0xd6d7878c,0x95c9bd80),LL(0x34ff7c75,0xe1ef20ee),LL(0xd2ccd599,0x3fab197a),LL(0x952ef4f9,0x9e480593)}, {LL(0x06ea3410,0x69777fd2),LL(0x74fa7dd5,0xb0280454),LL(0xc43bb5fc,0x641b6860),LL(0xecd7b8a8,0x9f359d5b)}}, {{LL(0x70be68cd,0x4431d4ed),LL(0x08b55f8f,0x712117f4),LL(0x23d0b6ca,0x449e1319),LL(0xfdee5357,0x658323cc)}, {LL(0x62879a95,0xa1ef8114),LL(0x69963eeb,0xc21257e5),LL(0xc5bbee13,0x1016ab74),LL(0x43d81a86,0x99bb310a)}}, {{LL(0x1d33a15a,0xdef03c44),LL(0x49127148,0x3e78cf18),LL(0x30b0cc00,0xe8d93368),LL(0xbd7ccd85,0xb05458fb)}, {LL(0xdbaa76b0,0x8c2896dd),LL(0x79e4cacb,0x0d826600),LL(0xff730ed0,0x50a45b23),LL(0xeba9030e,0x4a0e079c)}}, {{LL(0xe3129aa0,0x3ead3fdc),LL(0x48aac890,0xa93b39f3),LL(0xf362465e,0x0fd73860),LL(0xf8df2764,0x69177f2c)}, {LL(0x824ebddf,0x4cd58c50),LL(0x2fcef01d,0x1478981f),LL(0x980524b3,0x511bd380),LL(0x4d23e8e9,0xc95252b1)}}, {{LL(0x9ce08452,0x7ff12c37),LL(0xa3a87024,0x3dd8dd09),LL(0xb849dcb6,0x61ff0d39),LL(0xfefad6de,0x3f5eab86)}, {LL(0x251523f9,0xb6146886),LL(0x5be2135b,0x45ac1d52),LL(0x41d2c5d4,0x63507995),LL(0xb3064e72,0x7f19f799)}}, {{LL(0xa2efb9be,0x7280ad9b),LL(0xba9659de,0xbc8fbb60),LL(0x875a8062,0xa4861c12),LL(0x2f2387ca,0x78c920c8)}, {LL(0x03b7da99,0xfe0a6ea7),LL(0x48e3afa3,0x936a44b8),LL(0x89fd127b,0x618a0ecf),LL(0x06f24bc5,0xa35614cd)}}, {{LL(0x8d49c05f,0x21a1002e),LL(0x2fd7989d,0xceeacfd1),LL(0x8f5f4ea5,0x8c058f4b),LL(0x563e214b,0xf31bd38e)}, {LL(0x245c7585,0xbe47bd98),LL(0x6bc2a404,0x70d1a05c),LL(0xc68257f7,0x830d7f30),LL(0x8136c932,0x1abbbfbb)}}, {{LL(0x6e03597b,0x6fbc43b7),LL(0x5fca14a2,0xc18fddb6),LL(0xe8f506e2,0xd3c4ca78),LL(0xa47e27de,0x6b8711dd)}, {LL(0x16382b5b,0xc308c189),LL(0xcf96bd7a,0xe9d3145b),LL(0xafb26629,0x5c290ec1),LL(0x209438ff,0xb4eb8130)}}, {{LL(0xe1118539,0x7335044a),LL(0x5192a007,0xed6d43fc),LL(0xa43a2bd4,0x1a8bf622),LL(0xefa9f3a5,0xefec3fb6)}, {LL(0x6d834bde,0x6d224bbc),LL(0xb0fbc744,0xaaebfcb8),LL(0xc4ea1652,0x383b2bfc),LL(0x751ae816,0x9cd26d90)}}, {{LL(0xf47f0f9a,0xae614386),LL(0x73c6ecd0,0x99873787),LL(0xe5414fc7,0x0b56c1ad),LL(0xfd40286c,0x9b85e6b5)}, {LL(0xd64687dc,0x7117aacd),LL(0xad8a8c4d,0x85d148e7),LL(0x7962655c,0xf62f8eb5),LL(0x7f0c6a2c,0x8386b37e)}}, {{LL(0x90c47d7f,0x6b4715a3),LL(0x458a54e4,0x1fc4ced1),LL(0x0ed97b0a,0x01853943),LL(0x5b370e0e,0x58a280be)}, {LL(0x344f3960,0x8d488cb6),LL(0x0741604b,0x9050c599),LL(0x07954771,0x0878fb1b),LL(0xdbb3c82b,0xd927ea8c)}}, {{LL(0x384f01fa,0x2fe71d59),LL(0x238bb66b,0x66d2b790),LL(0xb8fd803b,0xceaec11f),LL(0x6dd09c0c,0xbb919914)}, {LL(0x2ccb2f67,0xab5992e6),LL(0xcca50326,0x2421878f),LL(0x9ee6dc73,0x363d933d),LL(0x084b1fa3,0xa374ab0b)}}, {{LL(0x161f6475,0x2d832a29),LL(0xfc8797eb,0x435b8d78),LL(0xd71b609c,0x66bc156d),LL(0xfe0c2004,0xb3dca798)}, {LL(0x02fd92d7,0x445d47bf),LL(0xc8b03083,0x1d1c9798),LL(0x079a7c51,0xca46d98d),LL(0x1afeb89a,0xb93f286c)}}, {{LL(0xeeb6665d,0x1c174510),LL(0x7479a932,0x65874b6a),LL(0x2335e3b8,0x28d16a85),LL(0xc747eae6,0x5e22bd3b)}, {LL(0x04be16b4,0xa770e0a7),LL(0x40b3ff57,0x9f5f9ca9),LL(0x845ec39f,0x3f39e529),LL(0xebe697ce,0x5d5f4d60)}}, {{LL(0xbd90d4f4,0xea2a262f),LL(0xfe1b6494,0xa1ce74ac),LL(0xfa0fc472,0x4e419004),LL(0x4e691060,0xdef0e440)}, {LL(0xa9f4baf3,0x57195a3a),LL(0x5e758c53,0xf14e108b),LL(0x920895e0,0x10a34f9d),LL(0xfeb57a63,0xc3f18af9)}}, {{LL(0xda1bef0d,0x4b1c988c),LL(0x3df6915b,0x8b328cd9),LL(0xf45586d5,0x5ddc5ecc),LL(0x040322fc,0x426468b9)}, {LL(0xbe981558,0xf7f44765),LL(0x1855504a,0x25093991),LL(0xf7d6df43,0x72c51f2e),LL(0x849c99e5,0x858637fb)}}, {{LL(0x0ee9f78b,0x68b84dfd),LL(0xf2ee390e,0xff42fc9b),LL(0x531e1dcf,0xaca71e10),LL(0x7feaedfa,0x391620e2)}, {LL(0xacf3e5da,0x7b2d6a02),LL(0xd20a16d3,0x261823d2),LL(0xbb00cd30,0xf9afa5d6),LL(0x1084580d,0xba151f4a)}}, {{LL(0x26a3fcc3,0xb5f4b3a9),LL(0x6729f4da,0x5d84a823),LL(0xfc35f732,0x51540c41),LL(0xa6ae5bf7,0x81b0cb58)}, {LL(0xbd81bd27,0x91c7ae07),LL(0x1d56ff5d,0x0868980e),LL(0x65224df6,0xaef85a31),LL(0x17a69e35,0x112eba3b)}}, {{LL(0xc3a9d932,0x07c34677),LL(0x8ac45e37,0x3b6b7cce),LL(0x31b6248a,0x5e0e2b6e),LL(0x453d9685,0x14ee5b66)}, {LL(0xbd4d807a,0x4c5e2be7),LL(0xc121fea8,0xc03f37f8),LL(0x8df7b5e7,0xcf34911e),LL(0x5f754191,0x00e7f18e)}}, {{LL(0x2dcea4aa,0x89a8c9e1),LL(0x50f6db55,0xcc1cc31a),LL(0x9046955f,0x4a6f542c),LL(0xda2485d4,0x85fed580)}, {LL(0x9ac53748,0xa70f62d1),LL(0x655870a7,0xc2fbb850),LL(0x8c859aef,0xaeb2d438),LL(0xcc9ff51e,0xe3cc5ae5)}}, {{LL(0x0a3ebbfc,0xf8d8c55d),LL(0xed48f61a,0xdcd838d5),LL(0xd4cba7ab,0x032f91ea),LL(0x2f70235e,0xeb0ed88d)}, {LL(0x000ef325,0xd4498170),LL(0x4b923c4a,0xfd34e07f),LL(0xb19b84cb,0xf71c07a9),LL(0xed9690a3,0x000a669c)}}, {{LL(0xb5705e16,0xf45eb0ef),LL(0x7d9ce007,0x8cfd6a62),LL(0xd9e52885,0x76ba9a5f),LL(0x8aa9ffd6,0x13f72881)}, {LL(0x85528e4a,0x0a11e8dd),LL(0xcee8d663,0x58f1993d),LL(0xa1c81fd3,0xb49d750b),LL(0xe7de2e6b,0xaae29861)}}, {{LL(0x5dd7de70,0x9a40644e),LL(0x937a5546,0x67fbae1c),LL(0x956c2fa8,0xb3e02907),LL(0x21b4aede,0xaf785374)}, {LL(0x9c0a8bfe,0xf42a1e96),LL(0x78957181,0x3f6690e6),LL(0xa6c5e0a7,0x1b1c9575),LL(0xf9cfb9bd,0x6def8124)}}, {{LL(0x72faa1b0,0xde552cf9),LL(0x9b5ebbbc,0xfac2f4ad),LL(0x8ef89ba1,0x4b60a5a5),LL(0x8012f3b1,0xb6d9be57)}, {LL(0x9b2b083d,0x3992a6f7),LL(0xac640f77,0xe79ec527),LL(0x3f1e632e,0xf6cca775),LL(0x8fb80790,0x5dae8413)}}, {{LL(0xb572407c,0xf0d4146c),LL(0x3f84cc39,0x829cfb38),LL(0xe31f007e,0xd7c9fed4),LL(0x09e68ce9,0x93b2a5bc)}, {LL(0xd01482b9,0x073fb24a),LL(0xb8d44e62,0xfe494244),LL(0x3dc49858,0xe59a1649),LL(0xf005b31f,0x071776f7)}}, {{LL(0x285439af,0xaa368f59),LL(0xe27e783d,0xb0821574),LL(0x098746ba,0xe16903f6),LL(0x69dc00d0,0x436a95ae)}, {LL(0x877bfcec,0x9ae5a91a),LL(0x1416ad3a,0x5d8758d9),LL(0x25fd9a9a,0xa420ce40),LL(0x39b0fbfa,0x99610fdf)}}, {{LL(0x41cc1e9b,0x782af222),LL(0x86ff4cf6,0x346a4a92),LL(0xabc900c1,0x9dc4c6cd),LL(0xe7fade51,0x7ed2476c)}, {LL(0x4f1dd24b,0x68a72185),LL(0xb08260cb,0xcefcf0fd),LL(0x8a6f61b6,0x0199a147),LL(0xcb5769c5,0x176b6079)}}, {{LL(0x347d5a63,0x6dbcceb0),LL(0x9c4dc505,0x26433ebc),LL(0x05d5e74d,0x52570318),LL(0x057ca464,0x692f1d81)}, {LL(0x477f424e,0xa09554a0),LL(0x176a695d,0xbd3f9bbd),LL(0x5972db27,0x8c7f52f3),LL(0xf28b2aa4,0xacee8234)}}, {{LL(0x3a4a0217,0xb853465a),LL(0x66f3a4d5,0x74a2534f),LL(0xeff0423b,0xae1a7ff3),LL(0xbb126028,0xd2a01a09)}, {LL(0x4963e855,0xff84c6f0),LL(0x6bc18d50,0x63db264c),LL(0xcc6a5e25,0x39792dca),LL(0xedb37a25,0xf20cdf3e)}}, {{LL(0x8730f2c4,0x6a460f3d),LL(0x6a0ab6bb,0xe9b786c4),LL(0x084015c2,0xa9720a6b),LL(0x0dbe6f0f,0x28add2e2)}, {LL(0x26be7de7,0x90fb0ba7),LL(0xe40f15fd,0xfae8b5d4),LL(0xceb9c856,0x007363a1),LL(0x586b770e,0x6d8bfe14)}}, {{LL(0xb7bcc0e0,0x63e7d78e),LL(0x3ed4ab62,0x56c569f8),LL(0x9e103abb,0x76c6a5bb),LL(0x638fc44d,0xeb24afeb)}, {LL(0xf0be16f1,0x15e00239),LL(0x8778f084,0x7db92f67),LL(0x63de2bef,0x5198680e),LL(0xe0510421,0x69031d0e)}}, {{LL(0xb94753c1,0x8058f8aa),LL(0x454bf609,0x412d4c97),LL(0x95f9fd19,0xb8dbfe8a),LL(0x68b43233,0x6cd3221a)}, {LL(0xa5adaaff,0x384a9f15),LL(0x42b2ef95,0x60c70f90),LL(0x2c7da919,0x085b2f3b),LL(0xbc8407e1,0x1e5d23d1)}}, {{LL(0xadb45b3e,0x9ea95bc9),LL(0xed06ec67,0xb5a28fec),LL(0x62a3c143,0xd678df46),LL(0x6793284a,0x80f0bc9d)}, {LL(0x07d4afc7,0xeb7865a9),LL(0xc1301d87,0x0fc5eafe),LL(0x4823349b,0x50a8e7f5),LL(0x2d019e96,0x97800fa2)}}, {{LL(0x1bdd1d9c,0xfeff2579),LL(0x23886156,0x4d938c5d),LL(0x6979b9f6,0x25e3a806),LL(0x37bb6199,0xeeef8fa0)}, {LL(0xd7d308b8,0x4d917977),LL(0x4ae672cc,0x60ca7ff9),LL(0x2a68db6e,0xb24ec154),LL(0x9e9942f5,0x7b0604ec)}}, {{LL(0xca4fad9e,0xfdf4794f),LL(0x3df5de22,0x086020f8),LL(0xd601533c,0x653da6ca),LL(0x735709f3,0xf97c1865)}, {LL(0x7cbd6ab6,0x2457ffd0),LL(0xd003a502,0xce05a482),LL(0x33ee2740,0x5c0c0cba),LL(0xf37174aa,0x8146ca00)}}, {{LL(0x587262bb,0xec118827),LL(0x7e2a402c,0x8468c029),LL(0xbd6eb2aa,0xe1c3a9e3),LL(0xb496bde8,0x77d09b4d)}, {LL(0x854693bf,0x454e767a),LL(0xa4de85bc,0x6bbcc22e),LL(0xb180f206,0x66452f10),LL(0x0f5b1744,0x110c5a05)}}, {{LL(0xa6b3f6e4,0xb7be75d8),LL(0x2c0d2e1d,0xf64bb3fd),LL(0x935ae640,0xad17a039),LL(0x8f243748,0x7304ad63)}, {LL(0xd278caa9,0x04316bb4),LL(0x1e84f91d,0x19b89c62),LL(0x6e7a2511,0xdf4a47e9),LL(0x998b6bc0,0xdef32df9)}}, {{LL(0xcee95a1f,0xf1253ce0),LL(0x0ae96e31,0xbacf5206),LL(0x0b343e63,0x4ba2e24a),LL(0x79929dc6,0xca64d07f)}, {LL(0x9424ce75,0xf2823ac8),LL(0x0207ee9f,0x2d4add37),LL(0x387cde5f,0x44d9ecd0),LL(0xe180a21f,0xa5095ccb)}}, {{LL(0x7c0cedf8,0x901cec8a),LL(0x3b8c759c,0xf291dc78),LL(0x49401234,0x98b8efdc),LL(0x058e9d9e,0x8f2b16e3)}, {LL(0x27dba00f,0x16ce8007),LL(0x6d66d2f1,0x5bb8fca9),LL(0x7b85a96b,0x092eda98),LL(0x973eae20,0xec53f4bc)}}, {{LL(0x1b93a60f,0xe6e0df59),LL(0x2f6b0abf,0x65e06ecf),LL(0x569a9e1d,0xb8c2ec3e),LL(0xaa8c1cc3,0x27f9fe72)}, {LL(0xccd4d5e2,0x9cf3908f),LL(0x725c8528,0x5a40e0a9),LL(0xd470b0b0,0x27b15a1e),LL(0x33d81bff,0x50a09ec1)}}, {{LL(0xda99fcf5,0xba976a58),LL(0xc3536b7c,0x3881ef1e),LL(0xfbc931b1,0xec65a069),LL(0xfc929a0e,0xab7f57b4)}, {LL(0xbc61f452,0xc7c63491),LL(0xc1750dbc,0x5c1aa935),LL(0x9ff0465c,0x35b8789b),LL(0x727647b7,0x8ff8589b)}}, {{LL(0xa95022b6,0x2b56fe50),LL(0x2adbdbbd,0x24220569),LL(0xd2b80ea8,0x2370d94f),LL(0x71d9e6f7,0xe5d47b73)}, {LL(0x8d858032,0x2fe84b72),LL(0x4ffd7cfe,0x0411034b),LL(0x7c2c84e0,0x0819a9f3),LL(0x30228f9e,0xf8248dfd)}}, {{LL(0x4fdf6c79,0x75c77f0a),LL(0x15579cc7,0x195b4b59),LL(0xf8d3705c,0x274c7c81),LL(0x70ee9be1,0x45a2209f)}, {LL(0x0b1e818b,0x4a4fce69),LL(0xbb9926b1,0x74d05e5f),LL(0x3f2a796b,0xb64639ce),LL(0xae957d59,0x2d168d5b)}}, {{LL(0x16171846,0x067c2270),LL(0x1a03f8d1,0x7bb71d15),LL(0x495a09a1,0x2badd196),LL(0x51b990c4,0x024db163)}, {LL(0xe79dcaac,0xc19edc61),LL(0x60df81e9,0xf17f54bd),LL(0x9ae347e4,0x4560262e),LL(0x59eb711d,0x1d2c2542)}}, {{LL(0x4919affe,0x40372d2d),LL(0xa009bd16,0x2d4a2ea3),LL(0xc1a62eb1,0x48f1e7f8),LL(0x587a1124,0xce083725)}, {LL(0xe7ebadd3,0xe874261b),LL(0x057b93e9,0x7ca5c156),LL(0xfe39e6ff,0xe8b381e5),LL(0xd30815c3,0x2d16b32f)}}, }, /* digit=15 base_pwr=2^105 */ { {{LL(0xad2e996a,0xdfd30b28),LL(0x9df0fc37,0x64d4eeec),LL(0xddc39763,0x8e049e3d),LL(0x37ea2e8e,0x9f55e0ce)}, {LL(0x4bf01984,0xf3fcba4e),LL(0x9d55bc4b,0x764d5c3d),LL(0xcfda895f,0x98cb92a1),LL(0x5c7bca69,0x27dfe795)}}, {{LL(0x23a86e2c,0x86dfdecf),LL(0x3387f712,0x02ac466b),LL(0xd63509d1,0xc30a1ac2),LL(0x63aebbd1,0xd3913422)}, {LL(0x068ae34f,0xdc7b789f),LL(0x487dcd10,0x499f2d01),LL(0xa3e8a4b4,0x68e2a3bc),LL(0x14d2a26c,0xdf87ba71)}}, {{LL(0x34479e7b,0x9e3ab999),LL(0xb026e780,0x9d5f2dc3),LL(0x4f1bd429,0x131374fd),LL(0x9be1379a,0x92e2e738)}, {LL(0xd13bc111,0x6cc32f80),LL(0x86f81c92,0x6fbfc350),LL(0x9263913a,0x12ca1b30),LL(0xe06ab75c,0x6f7da1ff)}}, {{LL(0x19301b16,0x4780f12a),LL(0xbc368a20,0x233bc231),LL(0xcbadb344,0xd9650892),LL(0xad9425a1,0x38a0d964)}, {LL(0x4a8d4d7e,0x277abcf2),LL(0xb806ce9e,0x4ccd16b1),LL(0x7570d473,0x82ff40f0),LL(0xdf130780,0x57491414)}}, {{LL(0xa96ef42b,0x9f1f39f2),LL(0x107f1321,0x1fd967ed),LL(0x29d4767e,0x93832497),LL(0x3fa9e796,0x7761a38b)}, {LL(0x66318df2,0x3e408c59),LL(0x41745f03,0x9283ca44),LL(0x2cce1a86,0xfedf8fa3),LL(0xb44600b4,0x8363860d)}}, {{LL(0x45f45a89,0x3dbfde55),LL(0x26ce399c,0x8800c860),LL(0xc25e9479,0xfb25e8da),LL(0xf7d367a2,0x6ff0d6cb)}, {LL(0xa93f9890,0x70b0ba36),LL(0x49bd5a80,0xc07ca403),LL(0xed54d1aa,0x5f4feda6),LL(0x671ad0b4,0xfa1e2efd)}}, {{LL(0x8c56e7aa,0xda465467),LL(0x25e45bc0,0x39d04cdc),LL(0xaf21c637,0x26661bd6),LL(0xb55ddfa5,0xf757ff5c)}, {LL(0x4394eb20,0x07318fd1),LL(0x2bcf3ad1,0xe010b19d),LL(0x8e5c7e7f,0x71e2031c),LL(0xedbfda69,0xee35f346)}}, {{LL(0x5d8f6fab,0x8d8d4120),LL(0xabed09c8,0x5e420839),LL(0x4aacbb1e,0x5120e079),LL(0xec1bc996,0xf7e840f8)}, {LL(0x9707c3bb,0xd921d63b),LL(0xae891a71,0x3ab4b8b8),LL(0x73bb2278,0xbe465756),LL(0x553ee91c,0x776ce040)}}, {{LL(0x88222e0a,0x86f07c2e),LL(0xdf97816e,0x3f3688f1),LL(0xa6df9d3a,0x20d2d944),LL(0xb2cb925a,0xff399057)}, {LL(0x27f1de19,0x010c747e),LL(0x7fc1fbc3,0xbe940669),LL(0x877ef709,0x3ab94600),LL(0x8f4c8a8e,0x9af40a6b)}}, {{LL(0x713f023a,0xf7c0f202),LL(0xd0a8dc63,0xbe0bf3db),LL(0x64a41337,0x09789926),LL(0x2c2823cf,0xbb4a8964)}, {LL(0xb90e45c6,0x9279cb27),LL(0x382564ac,0x80283fd3),LL(0xfa5f0bcd,0x3a746b01),LL(0x0afaf10a,0x28667a8e)}}, {{LL(0x015d5295,0xeccfd0ee),LL(0x73ce8e21,0xbd6678a5),LL(0x336ecb65,0x132a87f2),LL(0xbe7dc659,0x09de4efc)}, {LL(0x6f69b3bd,0xbedadd10),LL(0xe8303650,0x357c61e2),LL(0xa45777e6,0x6b3c613a),LL(0x08d41179,0x51dd30ad)}}, {{LL(0xf98feac3,0xa7b53f3f),LL(0xf9497319,0xe8e00328),LL(0x0ca20b40,0x1f3b080d),LL(0xe19b088e,0x06dc5456)}, {LL(0x0dce02cb,0x1f3f18d7),LL(0x6fd1ade9,0x2d215544),LL(0x055550d0,0x4c6de38c),LL(0xf33f4973,0x5d535e6f)}}, {{LL(0x744c033d,0xdcfd4163),LL(0x76fc420a,0x0706a490),LL(0x394f5b6d,0xdc9db55c),LL(0xe040a093,0x1a050a62)}, {LL(0xd0ab26f3,0x60367ebb),LL(0xc3d91820,0xb9c07239),LL(0xa3e32db2,0x14a8bed5),LL(0xd49f37dd,0x23b19cd3)}}, {{LL(0xea6c85ce,0xd048c64f),LL(0xd5716cfe,0x8aefff19),LL(0xab85bdcf,0x199fddb1),LL(0xbaea49d0,0x3f592e7e)}, {LL(0xf1d58ff6,0x8c8decb6),LL(0x7fe8f425,0x02598a99),LL(0x64a93fd6,0xe4c73ae2),LL(0x878db06b,0x208a0f61)}}, {{LL(0x27c4a266,0xff0272fe),LL(0x69e7c6a2,0xccfc96ae),LL(0x8e78d74a,0xbd7e715f),LL(0x32ed35bc,0xd04ae9a4)}, {LL(0x05614c5f,0x302af413),LL(0x33943b5a,0x98176637),LL(0x8a58cfd8,0xa4d1c9b2),LL(0xac2f3f79,0xf0ebd5f4)}}, {{LL(0xfdc7945f,0xebadb010),LL(0x03750a4b,0x62c9cff0),LL(0xa0c85b9d,0x75192383),LL(0x16eb0bf9,0x2aba7b53)}, {LL(0xa4c06f9a,0x93d4adaa),LL(0x5f8e482c,0x573a86a2),LL(0xe791a79f,0x109c6fdc),LL(0xb37eeec2,0xd9ed02ce)}}, {{LL(0x7dd63c8b,0x7b1fb4b4),LL(0x22493b49,0xae6e2767),LL(0x6a411bc9,0x5ef6beb7),LL(0xe1bf4242,0x4d88918d)}, {LL(0x02a97fbc,0x7ba26f8c),LL(0x7f41c518,0xf45b2a50),LL(0x83249e23,0x6c35fb69),LL(0x7a5778cc,0xc4a95134)}}, {{LL(0x08287cf7,0x6173f860),LL(0xfac3a444,0xdcfc71d9),LL(0x079ce3c9,0x894f3b33),LL(0x916b661c,0x842bf7da)}, {LL(0xa758a243,0x94299d6f),LL(0xb242389a,0x0e23f984),LL(0xc03a7aa2,0x653050f0),LL(0x9559ad9c,0x2ec3041b)}}, {{LL(0x97cf6e9b,0xa61dd499),LL(0x448fa6c6,0xfd090f38),LL(0x39b126bf,0x4f1b75ac),LL(0x1ef1a280,0xb48d0372)}, {LL(0xf2b2941f,0xe40c310d),LL(0x8d9d5ace,0x5b9a7369),LL(0x7ad9ad95,0xbe0415c1),LL(0xa8510622,0xffd864b6)}}, {{LL(0x898f28e8,0x2aceddcd),LL(0xba89a51f,0xa0cfc30a),LL(0xe105e448,0xd87db983),LL(0x5e5ea6fb,0x16ba795e)}, {LL(0x352ad094,0x5f48e45a),LL(0x55fd75e7,0x1971a10f),LL(0xfd1c8d68,0xfb0f1767),LL(0x86df0665,0x904229d9)}}, {{LL(0xe87ab22b,0xc2c88671),LL(0x33611a50,0xcbe384a1),LL(0xad2eb708,0x38eec58e),LL(0x86d7bdee,0xaa19b174)}, {LL(0x51832b61,0xa9f416d7),LL(0x355e7b6d,0x10b751ff),LL(0x4ff07a5a,0x6dd52063),LL(0x4e3505c1,0x6a6090c1)}}, {{LL(0xd4c80f29,0x53addd1c),LL(0x0d3d793e,0xe76d668b),LL(0x191eedd9,0xbdcdc4c9),LL(0x0f8e4877,0x80675320)}, {LL(0x32f5661b,0xc41426dd),LL(0x06199185,0x9fcbe1ac),LL(0x404a1207,0x62fa2198),LL(0x33c8190e,0xc742fdc2)}}, {{LL(0x778ee765,0x16ec1b96),LL(0xe29d992d,0xda656f58),LL(0xb4369e7f,0x5393775b),LL(0x0674fc45,0x512f5c7b)}, {LL(0x60efa8e0,0x55b8bd38),LL(0x155b57ab,0x1ab6d2df),LL(0xe26ad439,0xed0aa777),LL(0xd9b04376,0x5b16333e)}}, {{LL(0x8fc7ea72,0x321119d3),LL(0x7211ef45,0x390b4ef5),LL(0x1feda1a2,0x289f3945),LL(0x605c8596,0xcee9cb33)}, {LL(0x971b6897,0x91109e96),LL(0x19701ea7,0xdf70c173),LL(0xa92c6b2b,0xa07d0ecd),LL(0xa9eab766,0xf8eb97fe)}}, {{LL(0x0e3cf9e8,0xbb2cf63b),LL(0xdda02b26,0xffa6c503),LL(0x9cb18efd,0x42c1ec1a),LL(0xc45d5b22,0x13cdda9c)}, {LL(0xc820cdf5,0x6b3baf33),LL(0x610c8bfc,0xa337bc5e),LL(0x06a9ca6b,0x88186818),LL(0xa0c455af,0x382a34ee)}}, {{LL(0xe8fc59df,0x725006c9),LL(0xf929c670,0x0d46b697),LL(0x893a9f6e,0x7bd6eceb),LL(0x1cd04e5a,0xf25aa637)}, {LL(0xf6612d4a,0xf1563d79),LL(0x5efc49d8,0x8c9372cf),LL(0x96c5bdc5,0x09cc0513),LL(0xd3cc34d8,0x70f19d46)}}, {{LL(0xfdfbe16c,0xe62f6891),LL(0xdc60110b,0x8b7db2fd),LL(0xf7868674,0x3557bff8),LL(0x95a638d6,0x2b414c8e)}, {LL(0x6d19ac65,0x3b6610ac),LL(0xd641b0ea,0x20864204),LL(0x892161fb,0xee372a46),LL(0x4125868a,0xc7c5bd87)}}, {{LL(0xa61ee957,0x5edc6afc),LL(0xd37faed4,0xa4374ba1),LL(0x1e52b0ab,0xf0684f46),LL(0x2a007b66,0x0812cbca)}, {LL(0xe68c4893,0xf3442afd),LL(0x2d9dd9a2,0xb02ac6df),LL(0x068c08bb,0xa4fe98dc),LL(0x7795e2e9,0xfcd5dc05)}}, {{LL(0xa0f55cd8,0x28983aee),LL(0xe96cf557,0xb390daf4),LL(0x3f119098,0xbfd2f5ab),LL(0x6386c0ad,0xed114587)}, {LL(0x69539392,0x578995b9),LL(0x36b880ab,0xc8a77948),LL(0xe4c8b560,0x7e03cfb6),LL(0x06cdcbe0,0x018cd4db)}}, {{LL(0xb006f8d5,0xbd7f2e3a),LL(0xd6d9f30e,0xf25d1718),LL(0x1b22ae3d,0x9ef6e2ee),LL(0x416154ab,0x89a2695d)}, {LL(0xda261e39,0x1975e0c8),LL(0xda2c2031,0x8fe66aed),LL(0x97e1e00c,0x6f93f839),LL(0xa742b328,0xcba9a773)}}, {{LL(0x3417df8b,0x9529fec1),LL(0x54e314b1,0x37a27cd9),LL(0x65f94a63,0x93feb0f8),LL(0xb5e029c1,0x65978b84)}, {LL(0x81b705f1,0x576fd830),LL(0x688e8c52,0x37d07a37),LL(0x332838dc,0x3b91d360),LL(0xb0b14a94,0xcca9cbf8)}}, {{LL(0x8b63b669,0x86f18c44),LL(0x6972d2d1,0x53c6eba6),LL(0x8cff59bc,0x2a522d8c),LL(0x6ed25ce5,0xbc181d15)}, {LL(0x5feb0eca,0x913f173d),LL(0xa207bd71,0x34273f8d),LL(0xfa1715ae,0x41b7572e),LL(0x7f16f4ae,0x8a8ffea2)}}, {{LL(0xf95bdf78,0x2b852908),LL(0xa26328b9,0xa75adbb3),LL(0xdae21d25,0x992ac179),LL(0x78e14467,0x8c99927a)}, {LL(0x0c16e0c2,0x23fb2fee),LL(0xdbcb5f4e,0x58e797bb),LL(0xa07bd7de,0x33d6956e),LL(0x7172d36a,0xc921fdb3)}}, {{LL(0x158267b5,0x035f1744),LL(0xa291374d,0xc7495f33),LL(0x4a41a6a0,0xe07db2f5),LL(0xd1238792,0xfdb2987e)}, {LL(0x49741ce6,0x616df624),LL(0x8a693880,0x90ecd21b),LL(0x341fe21b,0x447c729d),LL(0xc012a8ab,0x06ad3c90)}}, {{LL(0xddfd6b5a,0x13dc4fa9),LL(0x64cfc0f3,0x238a1add),LL(0xc34a2b1e,0x874a3c2f),LL(0x0deb1dd4,0x427b6e3c)}, {LL(0x876f2621,0x78a1ad1d),LL(0x252f6837,0x34f9207c),LL(0x047d667b,0x1c812fbb),LL(0x3ee03ba7,0xc3512ea3)}}, {{LL(0x527a1b55,0x762de5f0),LL(0xae3221af,0x7873d692),LL(0xb112d35f,0xa8ac73c7),LL(0x815414f6,0x1d118c30)}, {LL(0x865ab6f6,0xbc686118),LL(0xecf8c02d,0x01e75348),LL(0xe6220bf9,0x9b131840),LL(0xa67512b5,0x3d72dac4)}}, {{LL(0xaf95e16e,0xd9e49ecc),LL(0x1e2aa105,0x1297c560),LL(0xa1a5e8c2,0x925301ac),LL(0x990ab503,0x3b0ea863)}, {LL(0x15f258c4,0x7860b660),LL(0x397253e4,0xa4497040),LL(0x14a4774d,0x88562ed0),LL(0x7adbd093,0x325d8b0d)}}, {{LL(0x41e24010,0xd4df8df2),LL(0x580031be,0xe7cb8663),LL(0xd7fc7e5f,0xd653593a),LL(0xe9f1fe9d,0x429a8863)}, {LL(0x63e71ced,0x18a0a709),LL(0xa498140e,0x39d9316d),LL(0x40f40117,0x44466cff),LL(0x64602832,0x58d27cd6)}}, {{LL(0x86018a70,0xf4a4c22b),LL(0x6d703f04,0x7a4d4102),LL(0xb424b0fb,0x4f5a0037),LL(0x322b1876,0xfb591cfd)}, {LL(0x632e0f56,0xb45798b0),LL(0xfdcbcf20,0x83ef9feb),LL(0x115749ac,0x0a23b09c),LL(0x946248f8,0x3b950273)}}, {{LL(0x1e13eaee,0x5ed75e68),LL(0x09dafdb9,0xbebd4744),LL(0x69941fc4,0x8b46621f),LL(0x91129bc0,0x1fd3c13f)}, {LL(0xb7b9da22,0x371448d0),LL(0xd87a4742,0xd452ccea),LL(0xf91c38b9,0xe2f04778),LL(0xbd516bfe,0xfb443a5d)}}, {{LL(0x044d666b,0xd7bd4056),LL(0x2a9b17c4,0xb4546ffd),LL(0x818fe55a,0xf66765ae),LL(0x1b5dc7a0,0xc375126c)}, {LL(0xc1a81c63,0xe9a7ed20),LL(0xf8cf06b9,0xaef2e23d),LL(0x3e67b95b,0xf4536865),LL(0x24309537,0x25cbb5a6)}}, {{LL(0x3256c020,0x8a230e68),LL(0x215dca7b,0x4a33e462),LL(0x2935b6d1,0xefef4936),LL(0x852c39f4,0xb383df4e)}, {LL(0x57c21e90,0x197ddd77),LL(0x2164127f,0x236f98dd),LL(0xbbd61847,0x464b86ec),LL(0xfb89d515,0x107a387c)}}, {{LL(0x400d66d5,0xe01e50b7),LL(0x5f864426,0x4377af2b),LL(0xf8fe847a,0xde21c49a),LL(0x887c0674,0xc133e58f)}, {LL(0xd2fda17c,0xda5b4c3b),LL(0xfed8fe68,0x24157f13),LL(0x8b6bb6bf,0x1c4483f3),LL(0xcf1bed73,0x940fab9e)}}, {{LL(0x3c15c7e5,0xce3fca79),LL(0x066de109,0xb83fce10),LL(0x0cd5a04a,0xbd42ed01),LL(0x407fcb03,0xba5446b8)}, {LL(0xe5d35bda,0x4a8cb929),LL(0xbff8631f,0x6338fd7e),LL(0x4656a8cd,0xc85d4ee4),LL(0x92c99820,0x83b1f39a)}}, {{LL(0x7e90c823,0x153fa4d4),LL(0x15326196,0xc15809ba),LL(0x6eb4b379,0x320b8fe9),LL(0x58704d9e,0x27cc07c0)}, {LL(0xf13d6ee7,0x301840b2),LL(0xc6d8c930,0xf1f6530f),LL(0x96a22034,0x3e9254ea),LL(0xaf5b8a2e,0xf8c0ee68)}}, {{LL(0xb8207fde,0x88e9e44e),LL(0x29bc1310,0xdea11cbd),LL(0x9c9d7df7,0xa20c2f17),LL(0xbceac495,0x2a954927)}, {LL(0x2a58d6ba,0x3f405f5c),LL(0x2ac9aeaa,0x64df5364),LL(0xe8aa74a5,0xb618f6db),LL(0x74ef61e3,0x22dadc7f)}}, {{LL(0x9cfdc4cd,0x306ee832),LL(0x40698a5b,0xaff53321),LL(0x89567341,0x98893443),LL(0xac7c68ec,0xdfefbdd4)}, {LL(0x3261a582,0xd3da7094),LL(0x62ce96e7,0xd23e3fa5),LL(0xd773337e,0x62c060c0),LL(0xa041f910,0x5cb2beca)}}, {{LL(0x7e8215d8,0xe21ab479),LL(0x923b4b27,0x84384686),LL(0x6a3d21ef,0xa93c08fe),LL(0x2fa6de1c,0x7bd96248)}, {LL(0xca6de3e0,0xb858ecd7),LL(0x47c9fced,0x466a48c8),LL(0xc708239e,0x23ca9b75),LL(0xb5bbe833,0x860d553d)}}, {{LL(0x9e76e71d,0x45804f1a),LL(0x51e59be2,0x9fdb8b8d),LL(0x3bbc2a19,0xa76db4b7),LL(0x96f82cd0,0xaebb47ee)}, {LL(0x97b1dd04,0x7a9b95b5),LL(0x5f0b1d7c,0xcc149a8d),LL(0x47a50eec,0xbba40e4d),LL(0x56b72539,0x4e635d70)}}, {{LL(0xb18659c4,0x31c40e90),LL(0x6f694b35,0x08026224),LL(0xe0cd6e15,0x8ed3d7b8),LL(0x9293cb36,0x157e2a9d)}, {LL(0x96e54583,0x7b457bb1),LL(0x2609c44d,0x75647498),LL(0x970a8cf2,0x54667671),LL(0x3af72572,0x3b7da9c8)}}, {{LL(0x4d63473a,0x8fbba977),LL(0x23001221,0x7af5af43),LL(0xea29d97e,0x99093197),LL(0xfa564089,0x4409f6a9)}, {LL(0x2f70e06f,0x64fd1cda),LL(0x2e9d55ea,0x8b7c83a6),LL(0x6385fcef,0x0dffbe4b),LL(0x7a6fe72d,0x4513f584)}}, {{LL(0xba1de4ae,0x6a64f166),LL(0x89069fbd,0x1f8550a9),LL(0xda7ef7fc,0x72b411fd),LL(0x829ea712,0xa185d2c3)}, {LL(0xccc1868d,0x82f5ffb8),LL(0xff9fafa9,0xb484473a),LL(0x089132ed,0xe1857f3c),LL(0x08ef378f,0xdad885a9)}}, {{LL(0x7af9e2aa,0xbdbdfc0e),LL(0x95486202,0x366c07bb),LL(0xfc9d979f,0x37040d45),LL(0xa0f80630,0xf279ed10)}, {LL(0x8f31b39c,0x27855261),LL(0xf26f91cb,0xea0c3b1c),LL(0xb38c050f,0x90b4e8c2),LL(0x1623ab47,0x7acb26b1)}}, {{LL(0xa4a064d2,0xb6cc3cd9),LL(0x97245482,0xa410880c),LL(0x3a6e6a1f,0xfb470e11),LL(0x93f347e4,0xf19080b1)}, {LL(0xb75a53d9,0x23253dcf),LL(0x9c95d567,0x55047049),LL(0x7b20202a,0x8c75631e),LL(0x834b8380,0x58fccf32)}}, {{LL(0x243dddde,0xaf6bdbd8),LL(0xcf38f705,0xa3ca3e2c),LL(0xca38c9a2,0xa2357b4b),LL(0x6eba095b,0x8bf0d270)}, {LL(0x9d998070,0xe4a43b7c),LL(0x8469214c,0xdf412faa),LL(0x000f1802,0xd2578cc4),LL(0xf8515863,0x2feb563f)}}, {{LL(0x5022112c,0xe66ce02a),LL(0x1461b1c6,0x8415df81),LL(0xad247c38,0xc2546e6a),LL(0x9a9c74d6,0x4b9788e6)}, {LL(0xa22be3e8,0x9d0cb2e0),LL(0x295f76ad,0x15db086c),LL(0xa2337670,0x9758f99b),LL(0x9ab57f54,0x61ae09bb)}}, {{LL(0x93926a37,0x7af4d4aa),LL(0xf25cadb4,0xa895f386),LL(0xc6f4f514,0x90e13821),LL(0x4eef97ab,0x46738d95)}, {LL(0xf0b479a2,0x66f559f3),LL(0x3262fb2b,0x9ea62dcd),LL(0x6a857025,0x91a39a5e),LL(0xbb3e6e11,0x11bdd19a)}}, {{LL(0x9353cc19,0xfa411fd6),LL(0x94cd2276,0x275d094c),LL(0x25243d1b,0xe2069b22),LL(0x630c8cbc,0x9f02f1e2)}, {LL(0x379b6b63,0x85c942fd),LL(0xbdcc9307,0x293dcf87),LL(0xdc212ca8,0x56856d8e),LL(0x23a0c56d,0x1927e931)}}, {{LL(0x9c2f8b66,0xacfed288),LL(0x386ad1e3,0x20f6b94e),LL(0xdcbeff77,0x0e622304),LL(0x5978f2f6,0x67e895fa)}, {LL(0x20029bfe,0x12a63bde),LL(0x8d968b8c,0x0ed75b6c),LL(0x57cec33e,0x611739ee),LL(0x42b9fc44,0xeffaae72)}}, {{LL(0x971a90a9,0xa7de79ce),LL(0x4fead0d5,0x529bd8a2),LL(0x9a1a43ef,0x78434c30),LL(0x4f3c848c,0x904d1db2)}, {LL(0x6d4234ad,0xedb3c11e),LL(0x5975e9a0,0x4e0c9ec4),LL(0xff16ec74,0xc51236db),LL(0x36d09231,0xde652cff)}}, {{LL(0xe60a0bc5,0x0d7c18b7),LL(0x9d7df012,0xaf041383),LL(0x47d4cfd0,0x9c0ff3f4),LL(0x3d97bac7,0x64c7e6c2)}, {LL(0x8cb44d50,0x239d2500),LL(0xbba96026,0x47189764),LL(0x31ddca37,0x22449328),LL(0xfb7c29ef,0xa53a1886)}}, {{LL(0x97a3789b,0x2515b665),LL(0x540ea258,0x825c5031),LL(0x09a5b24b,0x76680656),LL(0x60fb8bcc,0x833c240f)}, {LL(0x01e55cc7,0x758e0b10),LL(0x8d260572,0x8b799c48),LL(0x6c5dd0cd,0x0981a802),LL(0x1b9c6cc9,0x6f6da55d)}}, {{LL(0x8c4d503a,0x3457b685),LL(0x009a7a94,0xc537730f),LL(0xd01dfdff,0x334d46b4),LL(0x15e20bc7,0x3e5dc6a8)}, {LL(0x6ce8b8ab,0x1833b0bf),LL(0xc57a4292,0xe21b99ae),LL(0x1713ba15,0x743cb595),LL(0xe0bb44a7,0x550e41bc)}}, {{LL(0x2f8ebcf5,0xf356917a),LL(0x953f056c,0x6f2c400b),LL(0xdd84bb48,0x09d9ac41),LL(0xa61e98e3,0x50dc7a8e)}, {LL(0x3d3a6776,0x1179a9d3),LL(0x16de8b3e,0xdda312e7),LL(0xce6e2bea,0x62a8b7c3),LL(0x645e4ca0,0x2b00036c)}}, }, /* digit=16 base_pwr=2^112 */ { {{LL(0xab6cf0b4,0x9ad2cbd7),LL(0xf13d1ddf,0x7a1e67f4),LL(0x746003ba,0xa58f0c73),LL(0xa64a8fcc,0x8263e888)}, {LL(0xbe2452f7,0x535cbe37),LL(0x6ae81a76,0x93125766),LL(0x3a553701,0x7d2ed0ab),LL(0xb0717d78,0x93d7e7df)}}, {{LL(0xf9cf03ba,0x61bc013c),LL(0xfeee3a78,0x36223b88),LL(0x3d7e4c95,0x86efc923),LL(0x965625e4,0xaf3801be)}, {LL(0x3f32fd9d,0xa7bba141),LL(0x4e564acb,0x70724dec),LL(0xb7edcac1,0x52587f32),LL(0xb3969985,0x0b1cd94c)}}, {{LL(0x661fbdab,0x9f08407a),LL(0x58e52151,0xc4d7c536),LL(0x63dfe954,0xa3765bce),LL(0xac2dddd1,0xc6829bfb)}, {LL(0xdc6e4487,0x97393f65),LL(0xbf04c930,0x9ba29422),LL(0x18838c0a,0x493c6914),LL(0x4b2f35cd,0x41b137ff)}}, {{LL(0x4e1c5e60,0xc9e4aa24),LL(0x13253d51,0x54bb5289),LL(0x9bbabe53,0xf4a86ab3),LL(0x6ac0aa64,0xd561feae)}, {LL(0x1911bad7,0x27a896ab),LL(0x64337303,0x9cb22b98),LL(0x161f6928,0xf14262fb),LL(0x59ba6c9f,0x1661885c)}}, {{LL(0xb82574db,0x4666ebd3),LL(0x8d8af3f6,0xc5e86672),LL(0x209319bf,0xcc645205),LL(0x3834d1a8,0xc183c12e)}, {LL(0x49eb0f40,0x533d73da),LL(0x6aca649e,0x3bcab0bc),LL(0xe39e8361,0xa02f4c41),LL(0xa89bdc85,0x2391e7ae)}}, {{LL(0x608cbe2f,0x88067c5e),LL(0xf16c22f2,0xcdec82f6),LL(0xf1faf9dc,0x80aa719a),LL(0x2340185c,0x261fe951)}, {LL(0x9713e72e,0xcb411366),LL(0x6d8a2a46,0xdb1e405e),LL(0x11106ce0,0xed174757),LL(0xf71c0e69,0x6d70cf6e)}}, {{LL(0xcf707c76,0xb5310322),LL(0x40b4b7d7,0x3a1eb2ff),LL(0xb1a2d26d,0xb83259fb),LL(0x799720c0,0xa83ffb0f)}, {LL(0x0bedb326,0xeecb1928),LL(0xe9271715,0x4473e820),LL(0x2f2d71a9,0x506e6d20),LL(0x4319756d,0xe7b253b1)}}, {{LL(0xf576cb3c,0x27e19335),LL(0xdfb3b78f,0xe16e4573),LL(0x63da0001,0xaf96d785),LL(0xf7444c5e,0xb38deafd)}, {LL(0xc0eb0e28,0xaca6b38c),LL(0x7fe41b98,0xa6ca3541),LL(0x18965b31,0xfeb37b47),LL(0x597d5bc6,0x739cc322)}}, {{LL(0x4cb1fbc3,0x82776041),LL(0x8e2a3ad1,0xcdaa873d),LL(0xc01318bf,0xb5f87b34),LL(0x229cb81e,0x0c692268)}, {LL(0xa53089f5,0xb0724016),LL(0x05415313,0xb2976a53),LL(0xcee8fdf2,0x436eab75),LL(0xd82b13e5,0x8794e1a6)}}, {{LL(0xd5516e3d,0x0d51a072),LL(0x4b2fdb3c,0x7bae61ce),LL(0x550728ee,0x0d987e89),LL(0xee6778db,0xfd5a656e)}, {LL(0xbb4d9d7a,0x942ee623),LL(0x2dc1baf8,0xfc06d64b),LL(0x47c3dc8e,0x5244fcd8),LL(0x8568653e,0x5e37e156)}}, {{LL(0x048c8355,0xe5c2c6ff),LL(0xa0474046,0x480872ec),LL(0x7ff92484,0x67e3089d),LL(0x29971b3e,0xdc071893)}, {LL(0x5a63e8ad,0x3857db2b),LL(0x5f2e0a09,0xf617d94e),LL(0x5844de79,0x267e9818),LL(0x861f5f92,0xfdb103b2)}}, {{LL(0x1570d6e9,0xb969bd3c),LL(0xe0fb517e,0x7350b9db),LL(0x55aa543b,0x083b142e),LL(0xaa2bc581,0x424757be)}, {LL(0x69ea3302,0x4bd50f64),LL(0xed4c8288,0x053dcf83),LL(0xc118ac52,0xac2b3074),LL(0xe76ca88b,0x57f066a8)}}, {{LL(0x0a3207cb,0xb9ac28fd),LL(0x205829b0,0x0ec2ad13),LL(0x4f403b64,0x76216e56),LL(0x6621dd5c,0x7eaef662)}, {LL(0x4b06ac54,0x9e0cc836),LL(0x9648523c,0x16ac3c6c),LL(0x08eec1d8,0xe1208a1a),LL(0xbe054a54,0x1e90b3a2)}}, {{LL(0x23a836cb,0xdfab7f92),LL(0x6f7674c8,0x624d6bd2),LL(0xea06210a,0xc34a914c),LL(0xf26c4f23,0xba5314ec)}, {LL(0xa33a11cd,0xd440b196),LL(0x75eb951f,0xf81ab63e),LL(0x39350f0c,0x05ebb91a),LL(0x92e9528f,0x3f3c08ec)}}, {{LL(0x4fe6f4e6,0x54ff8844),LL(0x79b7ba49,0x217c0e02),LL(0xbf3a4179,0x13c4372b),LL(0xa1434264,0x6e5ad10b)}, {LL(0x62bd8ff2,0xc8426540),LL(0x85fe6ef1,0x7c3dd284),LL(0x05da0e84,0x2c59b300),LL(0x17468e18,0xf303ed94)}}, {{LL(0xa211ffd3,0xe19fac99),LL(0x3f1f6bca,0x408f9424),LL(0xa5648244,0x1f5b76d1),LL(0x95b2bd67,0xef3942e8)}, {LL(0xb538f1d7,0x1b9dee7f),LL(0x444b8f85,0x1cb78620),LL(0xcb8ea6a3,0x9f8ecd63),LL(0xb9d3b71f,0xca111b2e)}}, {{LL(0xbdc4e8e2,0xff83d71e),LL(0x3f76a9d5,0x43745ddb),LL(0xa25856ee,0x72db22a9),LL(0x5e9a9ff7,0xf34d5aa2)}, {LL(0xbc529902,0x01f6b5f3),LL(0x086f4867,0xadf5d31e),LL(0xca556b56,0xbd88674f),LL(0xfdc81625,0xfd00120d)}}, {{LL(0xfdde77f6,0x90fbaba0),LL(0x559ec6e7,0x266d3bfe),LL(0xc8094357,0x372acf54),LL(0x6c61bb78,0x772bd8e4)}, {LL(0x1af9aefc,0xcb2ac592),LL(0x5b178386,0xacc3dc9b),LL(0x23438463,0x09963084),LL(0x8359f1e6,0xae84f973)}}, {{LL(0xa4cee642,0xc3b19aa0),LL(0xb19a918f,0xcd5ca5c8),LL(0xe67cb207,0x46ac0d2e),LL(0x73ffebf2,0x2ae45e10)}, {LL(0x10ef065c,0xf84aad8e),LL(0x32a7e903,0xa0af57fa),LL(0x43d346dc,0x42295904),LL(0x7f170965,0x8d6f711d)}}, {{LL(0xb110cffe,0x11aa7070),LL(0x9755605d,0x091a100d),LL(0xd27d86a6,0xc5a0c654),LL(0xdb30feaa,0x1031a244)}, {LL(0xc02228d9,0x36804045),LL(0x8b746039,0x1877fc67),LL(0xe09bb238,0xba554015),LL(0x1de9b40d,0xc50d8f92)}}, {{LL(0x032f7a2c,0x29e40d88),LL(0x1d315ec2,0x514b56dd),LL(0x61778f04,0x9052652e),LL(0xe1a1c195,0x0d2bc606)}, {LL(0xb05043ae,0x375fd7ec),LL(0x6eba4d1b,0x03b82577),LL(0xc349b39a,0x8e61b567),LL(0xb35fc43b,0xa670973a)}}, {{LL(0x5571b4a7,0x80c05ca7),LL(0x8a4af0ba,0x95d14f49),LL(0x67bf4290,0x96767cdb),LL(0x46870ef1,0xb293372f)}, {LL(0x1afe1027,0xc6494405),LL(0x9019c4c2,0x9f027a1c),LL(0x188a593a,0xa392ac59),LL(0xfcb6e1ca,0x68acca2f)}}, {{LL(0x68ed921b,0xd8f86cbe),LL(0x712d2c07,0x24679ac2),LL(0x4e672cd9,0x18fbdb21),LL(0x51d1f8e1,0x401bb718)}, {LL(0xaa8da4a1,0x688792e1),LL(0x3ca93d06,0xedf9266f),LL(0xaed484df,0x5ddba14a),LL(0xb0ea10a5,0xa5dab102)}}, {{LL(0x833396ea,0xd397edcd),LL(0xed5e6747,0x78a75693),LL(0x1a5f8260,0xf2c844ba),LL(0x5fb9fec5,0xbcafe59d)}, {LL(0xd3147e7e,0xa2413d5f),LL(0xafdf26cd,0x130dd9e3),LL(0x9ad1abde,0x44be87ec),LL(0x6e77fbe8,0xe925c495)}}, {{LL(0xf26ced16,0x07ce8d96),LL(0x86ef7306,0x36c85643),LL(0xc7e3d409,0x62545902),LL(0x2ed4d38e,0x1747bf4a)}, {LL(0x55adc839,0x6fe6fc3d),LL(0x8eaf64a8,0x20a3cc09),LL(0x622887b1,0xc1e9b766),LL(0xc41ac659,0x7b9d2f96)}}, {{LL(0xf2a65e45,0xfdb897ce),LL(0x97889eb8,0x0c09c905),LL(0xe4becf5b,0xa15df10f),LL(0xccef7e40,0x14a3d4fe)}, {LL(0xa8fc67bd,0xedaa11f6),LL(0x5d185b42,0x7bf6fe9b),LL(0x6f9cb5c9,0x7bb9f1f5),LL(0xf97ea9cd,0x1b4ab74e)}}, {{LL(0x07638d62,0xe9ebf11d),LL(0xa78cf538,0x413a4a87),LL(0x570dd371,0x93785f86),LL(0xfb48063c,0xba431a91)}, {LL(0x4ed4e5fa,0xf1f2ea5b),LL(0x5308325a,0x91a72c47),LL(0xc9ea6acb,0x4e6518e7),LL(0x208f67e3,0xfeaf4c3c)}}, {{LL(0x2c16bb1a,0x98c5d768),LL(0xee31dc08,0xbf91b62d),LL(0x33a54959,0xe9ad408d),LL(0x38b7170b,0x9d754a64)}, {LL(0xd9d6da2b,0x106db7bc),LL(0xadd533af,0xf556cbb4),LL(0xf16d3b58,0x62db0de0),LL(0x1fa579ba,0x78a1b0be)}}, {{LL(0x7b552058,0xda96740b),LL(0x626c4d93,0x0c689cc6),LL(0xaf68e53b,0xee3dd5c9),LL(0x134d763b,0x78653a9f)}, {LL(0x3ca5aa67,0xec9c1b72),LL(0x7d56992e,0x67471dac),LL(0xad1d8580,0x0a97dffe),LL(0x0063c040,0x11c7d93d)}}, {{LL(0x6e90b157,0xb79e355c),LL(0xd9c894c4,0x2c06edcb),LL(0x71a75ed7,0x9b931897),LL(0x8e95ad91,0xd7f00247)}, {LL(0xb85bf054,0xfce1b489),LL(0x503b38bf,0xa3ffb8fd),LL(0xe0fe2ec9,0xe7ea3ad4),LL(0x0049865d,0x0f32f520)}}, {{LL(0xcff21b51,0x33afa324),LL(0x62a1cd24,0x3d6847d7),LL(0x0b06ce2f,0xf534e159),LL(0xae7cdae0,0x24d27b3d)}, {LL(0x4ad68ab5,0xb727db29),LL(0xb63c0bc9,0x7e8e47e3),LL(0x02389039,0xe81f3122),LL(0x88e6a17c,0x0c281f52)}}, {{LL(0x091e1c4c,0x3cc00e21),LL(0x867ccc75,0xd500db44),LL(0xf5ebbbe4,0xa8e2e84b),LL(0xc4279ac0,0xc3266881)}, {LL(0x7a170658,0x2e8fb4de),LL(0x51da4a2e,0x219c5ec1),LL(0xeeacee19,0xda69a3fd),LL(0x30462243,0x9d4c6fbd)}}, {{LL(0xa978c29e,0x43673fe8),LL(0x5861bbc1,0x6e825c95),LL(0xdba8e7ba,0xb41d1435),LL(0xb885d004,0x0f286f78)}, {LL(0xee57436f,0xea42b7fd),LL(0xef7e29c7,0xcdae14bc),LL(0x24251056,0x50cff3f0),LL(0x6f6e8cb1,0xf60809fe)}}, {{LL(0x12932e53,0xee9f1d15),LL(0x167d5097,0xa6e55cd6),LL(0x9d926359,0x5df8816d),LL(0x797b7eca,0x108e2117)}, {LL(0x91921587,0x7ba20319),LL(0xad23652e,0x304138e4),LL(0x51ebc32f,0x73d0ed57),LL(0xf01d0fc3,0xe0c10a38)}}, {{LL(0x78c49b19,0x14c6b72f),LL(0x3b7c7418,0x4f952b7e),LL(0xa2d019bf,0x3fe75d21),LL(0x7ca33e87,0x4837bfd2)}, {LL(0x3946e7ea,0x4597729b),LL(0x4c37ea10,0xbe22c14a),LL(0xd7909474,0x91106c7c),LL(0xbf5551a1,0xfbf1e7db)}}, {{LL(0x55ffea13,0x8e06336c),LL(0x0a1f99f5,0x0deaeda0),LL(0xfda98fc9,0x9b738c4b),LL(0xa59c98ba,0x061cc613)}, {LL(0xb477692c,0x5ceb5b83),LL(0x1fcc473b,0x5db77559),LL(0x83df476c,0x77214b62),LL(0x427ea01d,0x2ffac971)}}, {{LL(0x49fd0ba7,0xf29f600b),LL(0x7233ef79,0x1106f8b2),LL(0xe8a0ca35,0x706bc171),LL(0xacbff08b,0x4da7a9e6)}, {LL(0x7725f97c,0x17c2fa4e),LL(0xe84a5095,0xab459314),LL(0x6b24d47e,0x01556f14),LL(0xb016dc1a,0x01399059)}}, {{LL(0x28eca6c6,0x154b84c7),LL(0xd9084e68,0x88ed8612),LL(0x00bf9b5b,0x4dfd5080),LL(0xba9a0cca,0x853cd8ab)}, {LL(0x8af0e94b,0x8cbf9bd8),LL(0x83035d16,0x50782b73),LL(0x4f44533c,0x694d3e65),LL(0xa6e534eb,0x155d4bf4)}}, {{LL(0xee908b6b,0x9028e2ab),LL(0xa6743060,0x36e5aac0),LL(0x3c37d6f1,0xd26f5a51),LL(0x33729b9e,0x8483703e)}, {LL(0x2e5f82a5,0xf27a6603),LL(0xca55d187,0x33bf2bdc),LL(0x7724a85f,0x894c415c),LL(0xa2ea178d,0x9255d416)}}, {{LL(0x0a6dc5b9,0x35ecb4e2),LL(0x51c54ed2,0x8b3fc2c8),LL(0x9eede13d,0x059f86eb),LL(0x791dd5eb,0xa796c750)}, {LL(0xea88555b,0xb2f33680),LL(0x1245348c,0x92730950),LL(0xd1e63bfb,0x1a5545f8),LL(0xbebb7858,0xfebc9a14)}}, {{LL(0x6bdf0c84,0x13cce767),LL(0xa1d341fa,0x1aa9dc07),LL(0x1ee6fa43,0xd46e8ff6),LL(0x4b1dda64,0x4198e5d6)}, {LL(0x2782abd1,0xe82a8134),LL(0xb6d64830,0xe6f7b1b4),LL(0x7f0fb374,0xabe00274),LL(0x7494d7d3,0xf1a8e2b7)}}, {{LL(0xf274f296,0xd16b0d9e),LL(0x65246ee9,0x3c94a7ac),LL(0x91ec2262,0xd32c32da),LL(0x83116ec1,0x04c7bb90)}, {LL(0x78524a06,0x70fa0406),LL(0x07df8064,0x8d2d5176),LL(0xe2c8d48a,0x13e589f2),LL(0x122aed4e,0x3b110ac4)}}, {{LL(0x34e972cf,0xe8e0eb52),LL(0xfb3a77fe,0xc082944a),LL(0x6a32c23b,0xcdaff7a3),LL(0xc37b4a2c,0x88cc568d)}, {LL(0xe27b2552,0xc9979a9c),LL(0xd6ef51f9,0x8612ae7d),LL(0xef4e8f85,0x7bf0f937),LL(0x3f12d45c,0x2f360a58)}}, {{LL(0x9b336663,0x3ec9d0e3),LL(0xb1438d2b,0x5ac2df38),LL(0xff93fde4,0x7f2de910),LL(0xd92534ba,0xbbc460da)}, {LL(0x59a94ab9,0x74de3159),LL(0xc45b80dc,0xd51cfd32),LL(0x6e5b2397,0x9f1f349c),LL(0x995f7271,0xbdbd16ed)}}, {{LL(0xf59709a6,0x4a7efc1c),LL(0x4b3db99a,0x74e2760d),LL(0x7726a2e1,0xa7238e9e),LL(0x1a376013,0x47764208)}, {LL(0x7e33ebc0,0xbc96f396),LL(0xc9e4ec0d,0x31e159e6),LL(0x6a2ab9f6,0x26a5aef2),LL(0x320eeea7,0x23add07c)}}, {{LL(0x833b45b6,0xa79a97c9),LL(0xc51885e6,0xb08da907),LL(0xae8d5659,0x23f5e651),LL(0x1faff2f2,0x1eb0be48)}, {LL(0xa1e090da,0xe414ee3d),LL(0x7fcb664f,0x16e4f8fa),LL(0x98c36865,0x7a15a7e4),LL(0xaf89dacf,0xea60e8fd)}}, {{LL(0x86c1a4b4,0x4e009f45),LL(0x769644ad,0x78c1bebf),LL(0x0b4b3501,0xa41b480f),LL(0x57f0a0e9,0x98be5037)}, {LL(0x3af24657,0x06934887),LL(0x2b6260f9,0xe2503ddb),LL(0xd1d0caaa,0x37c936c2),LL(0x16431f50,0xd371e991)}}, {{LL(0x6087c5e5,0xd9621d16),LL(0xc53a8bc5,0xae49c2ce),LL(0xcad314cd,0xd7868882),LL(0xaa57af18,0xfde10dc7)}, {LL(0x3800f397,0x3fa8a60d),LL(0x388b333c,0xcec8ae7b),LL(0x85fa8129,0xefd8d692),LL(0x90776c32,0x33d5685b)}}, {{LL(0x65971a6e,0x47ecec0a),LL(0xad7c5755,0xe8a20bbe),LL(0x87372016,0xbeed0a4d),LL(0x1d9b8dc0,0xd0d499bb)}, {LL(0x2800907d,0xf4ce27cd),LL(0x8622bbb7,0x07a30b77),LL(0x77e264db,0x7532f435),LL(0xd64f0710,0xfdd1a9c3)}}, {{LL(0xa6543720,0x92ca210f),LL(0x5bb6985a,0x2f19ed66),LL(0xf9399b43,0x08a4ac61),LL(0x757f241d,0x0b7bac5d)}, {LL(0x3763c20d,0x93ef27cc),LL(0xa86b1f05,0xda3b206e),LL(0xd62467c0,0x8f19c74a),LL(0x6a3ad263,0x3ec5ef6d)}}, {{LL(0x2bc8b9f0,0x249aa636),LL(0x7f70990c,0x0fca7318),LL(0x6f038497,0x6d4aabc5),LL(0x5afaaaef,0x4647f72b)}, {LL(0x7bf90444,0xc7cbe03a),LL(0xcac2efb0,0x6beb69ac),LL(0xbb3c6dc0,0x58544eba),LL(0x96aefc2f,0x569cdcd6)}}, {{LL(0x5e4c950d,0x2e8a4c57),LL(0x4dd32002,0x6f5341d7),LL(0x6efa5908,0xd0345db6),LL(0xf1d2bbe6,0x4b043197)}, {LL(0xe8730bae,0xde8a4cb6),LL(0xa485cb62,0x9a89231f),LL(0xfcd9bcd4,0xb24ace89),LL(0x3ed5801d,0x01892cc0)}}, {{LL(0x413408f9,0x80ce2f30),LL(0xf8773b6a,0xaf67343a),LL(0xdd6ade17,0x91acc6d2),LL(0xe5eb3def,0x9d2ffeca)}, {LL(0x50b029fd,0x72f8af06),LL(0x79c0aabd,0x339c802c),LL(0xafc0a6ad,0x46161fff),LL(0xbac9a2d4,0x1046d9f8)}}, {{LL(0xab920e51,0x2f12eb06),LL(0x2892e552,0xfc004900),LL(0x13e61154,0x9aadf93e),LL(0xabcfd127,0x4468da94)}, {LL(0x152f220e,0x6a5d3ffe),LL(0x4737fe79,0xe6260c23),LL(0x5e6b4251,0x8b5dd1c9),LL(0x9af02b98,0x044f0656)}}, {{LL(0xa97ff366,0x434d475c),LL(0x2c4bcc46,0xbae8db8e),LL(0xf9777251,0x2ba43a8b),LL(0xdd019f1a,0x7ff430a5)}, {LL(0x630064ba,0x65e9f290),LL(0x7e871c0e,0xfc57a54e),LL(0x5791ae48,0x54107bbb),LL(0x5c334de0,0xdfce137f)}}, {{LL(0xaed5be73,0xab65c8f6),LL(0x174bf00b,0x838c3958),LL(0xf1c7e594,0x27c57199),LL(0x0d02fae6,0x62643d81)}, {LL(0x5f4431fa,0xc1e70c12),LL(0xb2b41f7e,0xfac86124),LL(0xf0108e3c,0x062ac35a),LL(0xa43d3a28,0xd7d34dfc)}}, {{LL(0x3143de4d,0xc40fb44a),LL(0xd2e0f9ae,0x06eac4ed),LL(0x95d9a69a,0x998f3211),LL(0xe950bd2e,0xb268f6a0)}, {LL(0x1e9d4e40,0xadfab210),LL(0x73ce9324,0xc453a68c),LL(0x80881171,0x5e2f2544),LL(0xee7e543e,0xe4f596db)}}, {{LL(0x76b6698e,0x77f48e4e),LL(0x227365c6,0x47b5165f),LL(0x14ef39e6,0xf56ec8d4),LL(0x74ce46fa,0x1638d647)}, {LL(0x08aa8b9a,0x244d0fac),LL(0x298326c9,0x98ccc4d0),LL(0xce0d2983,0x492d7661),LL(0x73158cda,0x728b3e3f)}}, {{LL(0xc4948011,0x7959ca67),LL(0x08425a38,0x32044ae9),LL(0xb1070c2b,0x05a7a6a7),LL(0xcc129ba5,0x34ed541f)}, {LL(0xb2f1c3e2,0x4b6bf65c),LL(0xd0d8aec8,0x6f090ce6),LL(0xd4fe39c1,0x11ade23a),LL(0xa5a35528,0x50510c08)}}, {{LL(0xad6fd7c6,0xb7e2a5de),LL(0x2745dca8,0x9d691939),LL(0xad053184,0xff669c38),LL(0xecd0703e,0x394ca6b7)}, {LL(0x60b15e75,0x59e32e80),LL(0x13c14864,0x82dde889),LL(0x64d4f086,0x0fd1624c),LL(0xc9893d7f,0x7fb502a7)}}, {{LL(0x711479a1,0x59b86bcf),LL(0xc40b44bc,0xfd4bc4d8),LL(0x988100c3,0x2fae18f5),LL(0x615867d7,0xe4af2f4f)}, {LL(0xbe479e28,0x7d45e1e8),LL(0xa04798a5,0x547accbd),LL(0x1c458b5e,0xe88a85b1),LL(0x6032f0cc,0xe144f7f2)}}, {{LL(0x3f807365,0xad5276d3),LL(0xb318a6ea,0x5b6519e7),LL(0x2d0fcf50,0x5889cbb5),LL(0x2bdab4e0,0xdce91cab)}, {LL(0x41b78954,0x17b6249f),LL(0x6f10449b,0xc9320b65),LL(0xf264ae8f,0xe38a7cc0),LL(0x52b85829,0xaab8803e)}}, {{LL(0xdd97973c,0x63668621),LL(0xd04138c7,0x5aaedce7),LL(0x1762874c,0x8e8e6614),LL(0x163fc862,0xd0cefcf4)}, {LL(0xffed1ace,0x0ebe0048),LL(0x7a8c2673,0x070c3348),LL(0x9b0d3fd7,0xb801d159),LL(0x922d4842,0xf1d55911)}}, {{LL(0x680dcbf9,0xf0acf768),LL(0x4f0a51df,0x5072b825),LL(0xd88df9c5,0x3a74751c),LL(0x1cc1a332,0x9d20f989)}, {LL(0x6926c34a,0x4e90042b),LL(0x00766880,0x5c728b1e),LL(0xf76e9dcb,0xf2e3bfe8),LL(0x15a125ae,0xd9822f0a)}}, }, /* digit=17 base_pwr=2^119 */ { {{LL(0xf51b14b0,0xbf84db58),LL(0xa39a79f0,0xdf73ccf5),LL(0x2b5a1f11,0x0ce1e584),LL(0x185fc400,0x841fa6a3)}, {LL(0x2455c32a,0x94b09c68),LL(0xbfa71cc3,0x383c9bde),LL(0x1e797929,0xb6381486),LL(0x623d0a5d,0x33036faf)}}, {{LL(0x90f17cba,0x41b6cf7c),LL(0x30c7c5f4,0x5d655ff4),LL(0x4ccc7f38,0xc64f29d5),LL(0x6124a79e,0xf28e8531)}, {LL(0x67bf1e98,0x1efa8d51),LL(0x5d7a33b0,0x8610027f),LL(0xcb9a40a4,0x35fe2bb2),LL(0x43d50a0b,0xc5cc1bf1)}}, {{LL(0x46e33870,0x84dbc605),LL(0x843c4e1e,0x23d8d2e5),LL(0x4cf8b569,0x69964b5e),LL(0xe0c546a5,0x2a5228e8)}, {LL(0x96d6e111,0x4c0467ed),LL(0xa12bd298,0x25764cdf),LL(0xfbaaad46,0x92a3e7fa),LL(0xd12fa469,0x08ac1d36)}}, {{LL(0xa32106c2,0x60ae2bbf),LL(0x3e917750,0xef155b2a),LL(0x13853a30,0x5567c3c7),LL(0xeddb305b,0xa6be8290)}, {LL(0xade26eec,0x2db58c21),LL(0x003c17ed,0xfa3c895c),LL(0x6293f8a2,0x96ab0de1),LL(0xac3710c6,0xbd2365ec)}}, {{LL(0x6aa24f73,0x93ea8553),LL(0xe0410c40,0xf75140d0),LL(0xaff0f7f2,0x760cfa2f),LL(0x3e580d68,0xc6dfb3c7)}, {LL(0xc16d39e2,0x25fc2091),LL(0x19e1d5e2,0xa05b0c81),LL(0x62bbec7a,0xd4d223d8),LL(0xf293f34a,0x11a93775)}}, {{LL(0xe194c642,0x9ab03e73),LL(0x789e3c85,0x607b7106),LL(0x4bdacd55,0x952aab02),LL(0x21cc6084,0x31ca3ee2)}, {LL(0x1c6b93f9,0xd3149b2b),LL(0xead930f8,0xcbc5ef3b),LL(0x22872630,0xed04984f),LL(0x6c4b6fe2,0xef5d052d)}}, {{LL(0x6010ffa2,0x808ae6c0),LL(0x1143166a,0x88b6fcd8),LL(0x5ab945ec,0xa2780263),LL(0x36db5012,0x4777b4aa)}, {LL(0x059aa3c7,0x2156bf83),LL(0x2a660260,0xcbef6fb7),LL(0x8b366ce5,0x189fa221),LL(0x08290914,0xd6f5bdaa)}}, {{LL(0x57028677,0xd2028d05),LL(0xce9aabdf,0x90eebeeb),LL(0x06d4e5d0,0xab977aee),LL(0xf9361873,0x7a98c527)}, {LL(0xb7c2474d,0xe49b1251),LL(0x5f3e7b02,0xcdaf2a36),LL(0x6fe54af1,0x638bcaf4),LL(0x1dac06b7,0xfec42624)}}, {{LL(0x3741a88b,0x422be225),LL(0x5304f139,0x1f3b82c3),LL(0x181c2fc2,0x101eab8e),LL(0x5898163c,0x8522738e)}, {LL(0x2d2bac1b,0x0372d05f),LL(0x1d1f3c42,0xb65c786c),LL(0x64e2f5b3,0xbd59694b),LL(0x24c5671b,0xf1c424bf)}}, {{LL(0x1eafe37b,0xda738cf5),LL(0x30dd7c2b,0x503eac24),LL(0x11dd77af,0xf9b7b7a5),LL(0xe9dcfe7c,0x0ade03af)}, {LL(0xf479e3b5,0x489bd34a),LL(0x030a33f3,0x993ab403),LL(0x9fb64068,0xaef322bf),LL(0x0e27f110,0xa47cc71b)}}, {{LL(0xefab99c8,0x1c445554),LL(0xa7f10e58,0x7c3c51e7),LL(0x78a87474,0xaa8b43ee),LL(0x2418475a,0x037d6397)}, {LL(0x10324911,0xc9c751fe),LL(0x3e0797d4,0x3d65d9e0),LL(0x7dea2a63,0x98b68d2b),LL(0xf4afca19,0xa211ed3b)}}, {{LL(0xc63b9e75,0xe19ff8f8),LL(0x0d7d130a,0x43f6b4fc),LL(0x7c8490b7,0xdba3385d),LL(0x0252c14a,0x97889df7)}, {LL(0xb2f18b9f,0xfccfca86),LL(0xc3a87422,0xf092ff9e),LL(0x67474838,0xf96dd675),LL(0x5bad2e9f,0x039e8287)}}, {{LL(0x52e041f6,0x7ed85e70),LL(0xcfdeb19f,0x3d6ef1e7),LL(0x0d9ac66e,0x9f9fe399),LL(0x16cb8554,0x5825e7bf)}, {LL(0xd954a4d5,0xecffdf90),LL(0x20678fc5,0x8617ffdd),LL(0x666df77b,0x3e974054),LL(0xb5d92788,0x748379d1)}}, {{LL(0x2da32c0a,0x46a60911),LL(0xb2676ca3,0xb2e1ac32),LL(0x17614dc6,0xfb74093f),LL(0x3f27f965,0xf44939e4)}, {LL(0xc922422b,0x4656a402),LL(0x3ff5c56f,0xd60a55ba),LL(0xab9aa62e,0x0d061b41),LL(0xaca3acd2,0xc9ceacfe)}}, {{LL(0xd946003b,0x056d5718),LL(0x2c7815f3,0xf8530d6d),LL(0x706536b8,0xbae14342),LL(0x2b901188,0x45c96dda)}, {LL(0xc64ed946,0x386d88b6),LL(0x6c00f1c2,0xb7017022),LL(0xec8988df,0x28519811),LL(0x5a05cffc,0x3b011fe2)}}, {{LL(0x515f954c,0x4f581d47),LL(0x7f470a40,0x145f925b),LL(0x736feaaf,0xfee6b6b0),LL(0x2ea5743b,0xf90744af)}, {LL(0xa2f36f56,0x4d8e8cea),LL(0xe3ed4007,0x4239a6ce),LL(0xd515e6db,0x0906b5bd),LL(0x8ac973d1,0x53622990)}}, {{LL(0xeb2fe229,0x472ceb94),LL(0x6a121363,0x0775ed41),LL(0x761ddb38,0xc0492e07),LL(0xaef9be2f,0x80c24d51)}, {LL(0xdcba73a1,0xa2a3982b),LL(0x4e26d062,0xe0d83978),LL(0xcd41c930,0x794959a8),LL(0x70131161,0x7d2a88d7)}}, {{LL(0xf4f966da,0x48f93fc3),LL(0xed5b6487,0xf92691a0),LL(0xada2c1fc,0xc5a93e5d),LL(0x4b7d9243,0x4a7aca52)}, {LL(0xd7c5598b,0x810aba93),LL(0x25109638,0x98f9ead2),LL(0xa388481a,0xe8c6e893),LL(0xe91ce74b,0x56e96b9b)}}, {{LL(0xd935f591,0xfa1e5dc3),LL(0x555eb816,0x985bb06c),LL(0xc4d14e69,0x6478c518),LL(0xc7f47349,0x48afbdbc)}, {LL(0x26fed96c,0xbde90933),LL(0xcd468186,0xf9b96f41),LL(0x730e8518,0x22de6a29),LL(0x915db842,0x7a3dc912)}}, {{LL(0xfc1f9449,0x8d13b665),LL(0xdd4bba75,0x6e9932a9),LL(0x564083da,0xa90ce8e5),LL(0xbbf7989d,0x8a7cf362)}, {LL(0x1b07ee2f,0x652eccb7),LL(0x6857a141,0x0c0dcf1a),LL(0xb7bfb43e,0xa87ec410),LL(0x82b8d179,0xaebdb7e7)}}, {{LL(0x625a24dd,0xeb3bc468),LL(0x463b1f89,0x7e45e47b),LL(0x00c75a48,0xc3013535),LL(0x13778807,0xafea920d)}, {LL(0x22dcef16,0x0d1e9277),LL(0x86cecfd6,0xa2a10f67),LL(0xd7160bf2,0xad40e29c),LL(0xeac1265e,0xe78e6589)}}, {{LL(0x0c62c041,0xd3a24310),LL(0x6c03c747,0x4d27344a),LL(0x7d3ee9d1,0x0b19e4a6),LL(0xcd90de33,0x9cf2eccd)}, {LL(0xfda636a9,0x673a9d1f),LL(0xa86ee501,0xb7349981),LL(0xe43766ed,0x11ca1e49),LL(0xe3ff3b08,0x0806af6f)}}, {{LL(0x8a01f119,0x21304338),LL(0xf3cb268f,0x58a6d3be),LL(0xe37d7851,0x40ceacca),LL(0xef5b81e8,0x18694595)}, {LL(0x84bad32a,0x35678ed7),LL(0xd1624256,0x4f280f92),LL(0xfb28709c,0xdecb1f1e),LL(0x164911d7,0x2a7f3048)}}, {{LL(0x579d8a41,0x32551d31),LL(0x60a5ee33,0x754c7c24),LL(0x6a88f85f,0x2c53fbff),LL(0x2c7a36a0,0x6ad0bda7)}, {LL(0x15724d6c,0x8b3674f8),LL(0xb9b7b34a,0x614727ce),LL(0x82ca9cd7,0x384fba98),LL(0x0c566025,0x8ef4343c)}}, {{LL(0x64886c98,0x5645fefb),LL(0x0f5c29e8,0x702befb3),LL(0x46de1523,0x6d74a7e0),LL(0xb1302163,0xcb2bcdb9)}, {LL(0xab4ca69b,0xe65cff39),LL(0xf2d4f6ec,0xeacb7103),LL(0x1770d3ef,0x15826c2d),LL(0x3f710600,0x38b008f1)}}, {{LL(0x4bc7dccb,0xc68450cb),LL(0x9e5f2400,0xb5f11b26),LL(0x9c3a833b,0x2af58e9e),LL(0xa058abaa,0xb60e2672)}, {LL(0x75b080c0,0xe891bf8c),LL(0x2434bf38,0x5b09b276),LL(0x700b8739,0x0d90a040),LL(0xe69f4a0b,0x995cb042)}}, {{LL(0x44a56b84,0xe30df0a1),LL(0x1ead5a62,0xbaf92d16),LL(0x6e0193a4,0xe214a062),LL(0xe9758b9e,0xd41de5bc)}, {LL(0x732d82d5,0xcf214213),LL(0xf949f07b,0xaa1421f6),LL(0xf7fb101c,0x5f38c91e),LL(0x2a3e41e4,0x47ce2ec2)}}, {{LL(0x240c7897,0x6bb34768),LL(0x7b45473e,0x80ff54ea),LL(0x82fe5aac,0x16acd40f),LL(0x4350449f,0xa3e76f52)}, {LL(0xacacbeb9,0xf7a3579e),LL(0x7bc40732,0x9791e0e0),LL(0xbc58cb9d,0xb26da7b5),LL(0x987e18f4,0x11d9fc80)}}, {{LL(0x1d8e0d34,0xc3c189a8),LL(0x2d42e0b5,0x3011097c),LL(0x94ab9371,0x4e385932),LL(0x0c237147,0x79e0c2ce)}, {LL(0x7172e6ce,0xc9f17122),LL(0x9b89a008,0xf8d73b1d),LL(0xa945995d,0x91690c6b),LL(0xc15306c6,0x089eb941)}}, {{LL(0x12ac8df5,0xee5f526d),LL(0x3bf94c65,0xf1dd23f7),LL(0x81a3cb0e,0x594ceaac),LL(0x9757cc8b,0x07d41d3b)}, {LL(0xfc5603d5,0x9eb0081d),LL(0x57bd230c,0xfb5d3298),LL(0xcde3f845,0xf2c0402e),LL(0x41e8aba6,0xa2defd67)}}, {{LL(0x2dd9573d,0xb300802a),LL(0x60c1ded3,0x64e401a5),LL(0x8ab1d3d8,0x19d4a677),LL(0xcca04f74,0x3c2092f2)}, {LL(0xac40056a,0xf4827ba5),LL(0x9c09ddc2,0x49d4cf22),LL(0xdbf20277,0xb2b00f6b),LL(0x5b281e9b,0xc9ac48d4)}}, {{LL(0x32efbbce,0x648d6674),LL(0xe9639719,0x64a6c2b3),LL(0x30662e7d,0x38c04657),LL(0x352c9184,0x15d1d7ca)}, {LL(0xcc3020cc,0x70e8630c),LL(0xb09f038f,0xe4b56c9c),LL(0xfe76a744,0xdb9cb5ed),LL(0x6947b988,0x4c85f020)}}, {{LL(0x29d8add4,0x7e500126),LL(0xbfaf6d7e,0xdbcfd295),LL(0x38df80be,0xc1a1c228),LL(0xf606ce3d,0xcfa6272a)}, {LL(0x8e0af540,0xbf2a5720),LL(0x5b599ab0,0xb9c544fd),LL(0xd0a22c9a,0xd6dc994d),LL(0xd23e4c0e,0xa8a12acf)}}, {{LL(0xba588a5e,0x41f7ac85),LL(0xccdb9687,0x5425fa00),LL(0xec9398f0,0x12fbce76),LL(0x4f550b9b,0x2ad69251)}, {LL(0xbb318636,0x120ff0f2),LL(0x01ecd90b,0x9378346c),LL(0xd0ba149b,0x1b98fe99),LL(0xc9c481c8,0xd69d5462)}}, {{LL(0x959e428e,0x11c79184),LL(0xcff227cc,0x9de61a8d),LL(0x1e09b860,0x144dfdcd),LL(0xf8ebe350,0x110c3a47)}, {LL(0xfadf86b0,0x59e574dc),LL(0xcf3b8d30,0xe6ff6e12),LL(0x19c77143,0xe2d512fc),LL(0x60279af1,0x63461543)}}, {{LL(0x32b4d371,0xff65189c),LL(0x0faf5ba7,0x022fecca),LL(0x414707b4,0xd08fe9bf),LL(0x722d5fd2,0x0ef8af2b)}, {LL(0x4e6fa14a,0xbef06063),LL(0xcca29177,0x1c41f752),LL(0x65091fe1,0x17dc7e18),LL(0x23f13c18,0x693d72d2)}}, {{LL(0xce8e2d30,0xce88eb02),LL(0xe972faca,0x7071f98a),LL(0x549c38ee,0xb7388d61),LL(0x0b788b8c,0x7cfccee2)}, {LL(0xcb93b5e8,0xdc470705),LL(0xab96d485,0xea053c18),LL(0xd634c9b3,0x70e96456),LL(0xd5999cf2,0x2c58c20b)}}, {{LL(0xa77c1767,0xcd392b3c),LL(0x7c4e6bd9,0x14471fab),LL(0x75c905ff,0x312e1547),LL(0xace47038,0x45764654)}, {LL(0x8fc3d697,0xa34a0b0e),LL(0xd309ed3a,0x5d9ad31a),LL(0x0918f957,0xbba340c0),LL(0x31fd72a1,0x768e06e8)}}, {{LL(0x3e1a4a54,0x77e5dd92),LL(0x3fdbc1e1,0x0970719f),LL(0xb0371fe2,0xd4f1da6f),LL(0xfd7f895a,0x3635f433)}, {LL(0x411c8e6f,0x0e8e40e6),LL(0xec18103c,0x31d126bd),LL(0xc299d7cc,0x415a0cc1),LL(0x3a8e97f1,0xdf528e7b)}}, {{LL(0xeed95e91,0x4551a8c7),LL(0x32bcfb03,0x8de89888),LL(0x2eac5c3a,0x25da4f5f),LL(0x5f88d63f,0x6d0b2e25)}, {LL(0x575d6145,0x8d158d14),LL(0x345f62b0,0xe5601a6b),LL(0x113c6895,0x6f951699),LL(0xb87e50ef,0x79e29fd5)}}, {{LL(0xd5fa51ff,0xf1ab215c),LL(0xaf2c3094,0x4fc5c4ea),LL(0x2c006042,0x1baeda40),LL(0x3e30e75f,0xcdfcc37c)}, {LL(0x467f57eb,0xdd64e5dd),LL(0x22902d21,0xa5b13731),LL(0x1c52cb7b,0x856866dd),LL(0x16a08caa,0x05cf0f7a)}}, {{LL(0x533b4d09,0xa46e8a55),LL(0x4e073af1,0xfc803998),LL(0xe0d589c3,0x8e3825c8),LL(0x4c1daef3,0x505e8e5d)}, {LL(0xc5f3db12,0x9f8363b1),LL(0x74f569e2,0xe7d46700),LL(0x4d68461a,0x551fd2ed),LL(0xa8bbe83d,0x26248da5)}}, {{LL(0x65681dbd,0x8d90c47f),LL(0x2200ba6b,0xe726d25e),LL(0x65a3bc9b,0xa2fe408f),LL(0x9c443b57,0x94a80457)}, {LL(0x07364677,0x95f7f024),LL(0xdaf0fb34,0xe9d9bc87),LL(0x5588e979,0xe9082548),LL(0xa0e61ff2,0xede1f94d)}}, {{LL(0x45e1c230,0xcb89a1e8),LL(0x50a15304,0xee014c23),LL(0x2bab57e1,0xf25d8ffa),LL(0x26223c6e,0x8a920680)}, {LL(0xaadf7e6a,0xc5abb7af),LL(0x9e7d8da5,0xcb57c893),LL(0x7d589a91,0x839bcda0),LL(0x77e82027,0x1fa774c0)}}, {{LL(0xba6504d7,0xeca669cf),LL(0x6845e47d,0x7bf09544),LL(0x607b3641,0x5eb6c33e),LL(0x64bab450,0xf445556e)}, {LL(0x86096fde,0xed0b1c02),LL(0x8ea41693,0x2c5ba666),LL(0x37ec248d,0xe578b315),LL(0xf64ed28f,0x97ef44fe)}}, {{LL(0xce419462,0xfa5a6c46),LL(0x9cce80e9,0x29336dc9),LL(0xeee7617f,0x9e9054b9),LL(0xf3d51cba,0xcea9a100)}, {LL(0x13267ec6,0xc3cce5e8),LL(0xa4e807e7,0x650c8383),LL(0x9b2726dc,0x1338e22e),LL(0xbf79b47a,0x220c50b2)}}, {{LL(0xa0e0962a,0xe160d496),LL(0xe1ed5cdc,0xe1a26460),LL(0x31427c62,0x9a1ed8c3),LL(0xe99a096a,0x65ef5300)}, {LL(0x4e3ad558,0x38abea5f),LL(0x0880ba0c,0x03bb15e9),LL(0x0141b036,0x1e6dda7e),LL(0x5bf37669,0xd31b08bf)}}, {{LL(0x68da20d2,0x948e0366),LL(0x4108fe36,0x36998a24),LL(0xf9d6563b,0x7606e6ed),LL(0xe42172ba,0xcf7cbdd3)}, {LL(0xa1265b99,0x2335a9a4),LL(0x30ac3f69,0x64776cdc),LL(0xa59b595e,0x04040362),LL(0x2cbc03cd,0x82df96b9)}}, {{LL(0x6cea2796,0xe9d18c7f),LL(0xe1ea7e35,0x3112c4f6),LL(0x5f8a786d,0xf9cbc205),LL(0x2097da0d,0x36cc6d42)}, {LL(0x2153e665,0x54093350),LL(0xce937bb9,0xebe9db0f),LL(0xd95942f8,0x9d1a5972),LL(0xd4bd5c74,0x81c1f94a)}}, {{LL(0xaa04152e,0x61dc7318),LL(0x95e5ec9f,0xdf636db1),LL(0x48090850,0x64a80d46),LL(0xce890a30,0x2b37679e)}, {LL(0xff6025e3,0x9f46d5b9),LL(0xf24534dd,0x6eed5a44),LL(0xf740a84b,0xc56b5cb1),LL(0x228cc826,0xb4641c28)}}, {{LL(0xaf62b943,0x676289be),LL(0x1eae5409,0xe3f3810c),LL(0x04b5be78,0x73613f32),LL(0x398b556c,0xe6359179)}, {LL(0xc0263f77,0x6a342b12),LL(0xc10a6db5,0x6b093bbd),LL(0x29832fb9,0x8f3fc90d),LL(0xff03b2ff,0xb3f2d8fc)}}, {{LL(0x64457331,0x1de7bd1c),LL(0x43bb1380,0x0a03a06b),LL(0x8bf17419,0x6720cc3d),LL(0x33938d5a,0x2627c7da)}, {LL(0x8d98f34c,0x204da058),LL(0x51cbd284,0x80e29f46),LL(0xa46f93d5,0x11b22dd4),LL(0xe971a61a,0xd7341655)}}, {{LL(0xee69f782,0x36a748b7),LL(0x94f08ac0,0xa3740020),LL(0xc36099f3,0x383fb245),LL(0x00137fdc,0xa7cb0ef9)}, {LL(0x6e1dd2e5,0x5371052f),LL(0x7976a1d3,0xed3ab7b5),LL(0x9df822e6,0xb0119c0d),LL(0x358685d1,0xafd2a477)}}, {{LL(0x4ae1103c,0x82879cb0),LL(0x94385be6,0x61cd6ca8),LL(0xd85d4a62,0x7c551809),LL(0xb318d965,0x9632ac5f)}, {LL(0xe1340605,0x67baad2c),LL(0xac6ed4f7,0x39c2c8c7),LL(0x71211c2f,0x42c4a7b1),LL(0x9bf758f6,0x43c778bb)}}, {{LL(0xf519acb2,0x2dc8fc39),LL(0x08eff177,0xd3c30a6d),LL(0x5144484b,0xf889c021),LL(0xca376af3,0x01b82327)}, {LL(0xd3e71253,0x168a0b2f),LL(0x3f9ff89d,0x5e92c6ba),LL(0x5b4c6844,0x8c74c132),LL(0x33de6858,0x707c4a40)}}, {{LL(0x9c36dd9e,0xb13f6abd),LL(0x9b3aa9f5,0x4baaef52),LL(0xcd156392,0x0a4fa929),LL(0x6506f42f,0xde0f1956)}, {LL(0x150d4ee7,0xe43dd7f0),LL(0x7247f552,0xf7afe7db),LL(0x9072b450,0x9abc8d1c),LL(0xc9a8e159,0x5d0645d5)}}, {{LL(0x01c6f17a,0x863d3e8f),LL(0xdf080690,0x3a0575ac),LL(0x2b0fb150,0xcad62d87),LL(0x625c35c6,0xa1f54744)}, {LL(0x41fe59ec,0x7d3bcec3),LL(0x169f1e04,0x0fd3e40e),LL(0x2ed9aa4b,0xbde8c827),LL(0x13046c6e,0x71562ee6)}}, {{LL(0xe9acac7a,0xaf049c5c),LL(0x261dd422,0x7efec06c),LL(0x095564c4,0xa530fbfd),LL(0x2a57af79,0x000c0c82)}, {LL(0x2ce1315c,0x9f79868f),LL(0x1b5d575e,0x0dd99453),LL(0x1e534cfd,0xf1a49419),LL(0xed7e8b39,0xc7de8756)}}, {{LL(0x3ed2ccb2,0xef61f5c8),LL(0x34af2a15,0x032ee766),LL(0x9f69ae9d,0xe0692ed5),LL(0xf64900df,0xd34fc2d5)}, {LL(0xaca6d51b,0x1c51c950),LL(0xa7717dfb,0x10ae0fb2),LL(0xa7ec7ca8,0x9fa305f7),LL(0xb5728214,0xb215a8ab)}}, {{LL(0x8819505b,0x62628fdf),LL(0x004ba54e,0x3cefd86c),LL(0xc571da3d,0xa17bed74),LL(0x93a5faa5,0x362dfef6)}, {LL(0xf8aeea05,0x1bee6899),LL(0x16f18b7a,0xd7bf7e31),LL(0x1cb7685c,0x3f3cf39d),LL(0xe2e57c8e,0x1df41f23)}}, {{LL(0xe2fd94f1,0x8f62ecb8),LL(0x4c30a178,0x652099c9),LL(0x4262e9e6,0xaa2454e1),LL(0x2015d4a9,0x7f0d440f)}, {LL(0xbb5b39fa,0xa2c76313),LL(0x1ab47bb3,0x46e57ab2),LL(0x8697e682,0xd181f444),LL(0x33273dfe,0x55db129e)}}, {{LL(0xe71d029f,0xda188361),LL(0xb5def631,0x3e3e19da),LL(0x087ad30b,0x7431f513),LL(0x9f27c84e,0x2537887e)}, {LL(0xac9df89d,0x0c228c62),LL(0x10031289,0xdcd2c5e9),LL(0x0321d1b6,0x5cc76782),LL(0x6cb3d600,0x4e460bdf)}}, {{LL(0x9a870166,0x6f356aab),LL(0x497d4ac0,0x21aecb3b),LL(0xf0495ef1,0xd981a4b0),LL(0x0fb7704b,0x615e8bff)}, {LL(0x8478bf12,0xc148e8ea),LL(0x364eee52,0x7011ec5b),LL(0xf692bc12,0xd9075965),LL(0xe622ad51,0x3019c824)}}, {{LL(0xec83c953,0x349e4873),LL(0x3a21ef0a,0xb4f59fb3),LL(0x40f7d93e,0x3872d314),LL(0xc2568c82,0x479e1d02)}, {LL(0x65d43d22,0xd7e4dc9a),LL(0xe775efa8,0xcc068e81),LL(0x326defa6,0xb78ccae9),LL(0x2da64956,0x8f92b296)}}, }, /* digit=18 base_pwr=2^126 */ { {{LL(0xdea227ee,0xb721f8d5),LL(0x3dda8ba0,0xf48c766c),LL(0xe43e3520,0x0583d94b),LL(0xe1d898b6,0xebda36c9)}, {LL(0x6627adaa,0x1808286a),LL(0x9938368e,0x19c4c620),LL(0xf750949f,0xe0dbd707),LL(0x0cf356d9,0xcadf4bea)}}, {{LL(0x2dc890a7,0xf5de2126),LL(0x95aa75a3,0x76b7b675),LL(0x2a070b32,0x475fc143),LL(0x8e31d68f,0x7429a646)}, {LL(0x09be3dca,0xec3a9aaa),LL(0xaf780ed7,0x07e119a9),LL(0x64fd96c4,0x62125625),LL(0xe8e80577,0xb571494f)}}, {{LL(0x5228d735,0x955ee349),LL(0x8fc5d4b6,0xa04ef2bb),LL(0x3600814f,0x0c532891),LL(0x59f85bd4,0x41f1f637)}, {LL(0xe3dcdfb4,0x72f1d731),LL(0x3aa5edb3,0x28a4ddb9),LL(0xf702dcdb,0x116a68e1),LL(0x3bde657e,0x1975bc42)}}, {{LL(0x8a914b50,0x7b9f561a),LL(0x9154d377,0x2bf7130e),LL(0x519b4c35,0x6800f696),LL(0x568b4c56,0xc9e65040)}, {LL(0x6d98a331,0x30706e00),LL(0xe211ce1e,0x781a12f6),LL(0x40562e5f,0x1fff9e3d),LL(0x8c166747,0x6356cf46)}}, {{LL(0x429945a7,0x80e87329),LL(0xb7ab06ad,0xc619fe17),LL(0x6fd86b17,0x9116bc2e),LL(0xb9116aac,0x64a41877)}, {LL(0x32ba4f3b,0xe3ed867e),LL(0x68b4ebe6,0x013e263b),LL(0xe779e4ec,0x305ebfe7),LL(0x50178251,0x5536d45d)}}, {{LL(0x8873a93d,0x5abb939f),LL(0x8c4c9cb1,0x0263ba48),LL(0x6b78a4b5,0x36764b8d),LL(0x28bebc1e,0x205bb45d)}, {LL(0xae89dcd5,0x16df4bb0),LL(0x316fadb7,0x85994670),LL(0x3af3c724,0x71f75664),LL(0xe8520c9c,0x43e30313)}}, {{LL(0x29e91921,0x3ab9ec54),LL(0xe3299f47,0xd931436e),LL(0xb89cd49f,0xb56da7bf),LL(0xcff7f637,0x90623412)}, {LL(0x714022de,0x751e7944),LL(0x2c338262,0x86bcc342),LL(0x314c23bb,0x85f6a9bc),LL(0x1f0a3991,0xedbe8e74)}}, {{LL(0x003b40dd,0x7a748d63),LL(0x3951b7ae,0x8a682402),LL(0x704a91b0,0x41e92dd9),LL(0x858cd3ea,0x2dfb3eb9)}, {LL(0xf5094667,0xc3c2af35),LL(0x7435aa2d,0xffa287dc),LL(0x7462714f,0xd03f3979),LL(0x203e5b0e,0xdb550f67)}}, {{LL(0xe241ed0c,0x6df7801b),LL(0xb642fd3a,0xb52c0a3f),LL(0x1977a29d,0xdd35e1cf),LL(0xa661404c,0x8e793d60)}, {LL(0x6b9442ae,0x393e2b87),LL(0x2aa6b707,0x123b893a),LL(0xdb8d306a,0xeec88682),LL(0xce847879,0x92c2d93d)}}, {{LL(0x80ec63b4,0x725f1e7d),LL(0x74113de0,0xcb8f53d9),LL(0xb819f730,0x2132a072),LL(0xb4c61f06,0xfabf3c47)}, {LL(0x2cb243d8,0x79c1bc86),LL(0x757e3600,0x442833c5),LL(0x4e918b8a,0xfa4f69ad),LL(0x73bc193e,0x5816f3f3)}}, {{LL(0x30f40e93,0xc671c7a4),LL(0x5c51cfa4,0x6041aa03),LL(0x2fac25d7,0x3a713549),LL(0x24a7df01,0xf5053237)}, {LL(0xd29f4ec5,0x99efb34a),LL(0x71d2cb1b,0x74810523),LL(0xf3a029ab,0xacefaf8f),LL(0x069d9545,0xc82e4f5a)}}, {{LL(0xd3341d80,0xd759549d),LL(0x31a2a0a4,0x079e9fa7),LL(0x2a164f75,0x75da56c7),LL(0xbeefc182,0x9313ef5a)}, {LL(0xbde130ad,0x0aa365b6),LL(0x98411180,0x44265977),LL(0xaa26466a,0xa65373f7),LL(0x2e2cf404,0x1a43bee6)}}, {{LL(0xb37a9390,0xe029ed6d),LL(0x34970065,0x5c2351ca),LL(0x1c46d72c,0x7c4f3c30),LL(0x7262ce20,0x09ce770a)}, {LL(0xdd58a9f8,0x0cfeefad),LL(0x408addaa,0x06797d79),LL(0x05aed325,0x76a87c06),LL(0x8a46d0c6,0xe002b672)}}, {{LL(0x05b6e1a4,0xcf77ea31),LL(0xa5d92b00,0x3bf900bc),LL(0xdccfe144,0x05996d8c),LL(0x951a602c,0x73d4dfd7)}, {LL(0x0ed8885d,0x033f3959),LL(0x36400817,0x8332dc73),LL(0x2d8ebda7,0x96372295),LL(0xb5da0c67,0x3fb32cf6)}}, {{LL(0x3e36defc,0xcb521d65),LL(0xa67f00f0,0xc293d170),LL(0xfb35bd06,0x6a3a2fd4),LL(0x0bd490a5,0x537937dd)}, {LL(0xc274ee5a,0x898d94bc),LL(0x7515b5e7,0xdc70f9bd),LL(0x3749900f,0xa94673db),LL(0x49ad3b04,0x3e6e2af0)}}, {{LL(0x207eecd9,0xb9dae1b8),LL(0xec07b47c,0xd3f50d63),LL(0x364292da,0x02b4d909),LL(0xfc35975b,0x919a6df3)}, {LL(0xb616452e,0xb41ed4aa),LL(0x5cfc6abb,0xe58689cd),LL(0xf389b025,0xeac325d9),LL(0x8f255de5,0x45ceb1e6)}}, {{LL(0x5e46cdff,0xda4a0715),LL(0x0f6c761c,0x8a860a55),LL(0x5fe1eef1,0xe1395274),LL(0xf7bc535f,0x256e296a)}, {LL(0x2755dd27,0xf3d4b06c),LL(0xbb530c26,0x3ced6ee5),LL(0x96ba599d,0x73249ad7),LL(0xe8a66027,0x5de8dab3)}}, {{LL(0xc2f97e01,0xa4892840),LL(0x427945be,0xbe0dbe49),LL(0xa57d4e4f,0x6fd86a7b),LL(0x04a2e778,0x7f56c3e0)}, {LL(0xffc13d49,0x734708cc),LL(0x788d31fe,0x3c1d9413),LL(0x8d3e4c36,0xfe85545b),LL(0x8815129c,0xcca441fc)}}, {{LL(0x15e3d172,0x2e2095e2),LL(0x64b43e81,0xc0c8d3c4),LL(0xc68e802e,0x084557ab),LL(0x30d239b9,0xa6b73590)}, {LL(0xb67b0548,0x61ec00a9),LL(0xb8ab138d,0x630059de),LL(0x36ca9888,0x800abf01),LL(0x9517149e,0xe26d644a)}}, {{LL(0x58bf21d9,0x775d5a98),LL(0xdbeab706,0x00eb6846),LL(0x8232d477,0x9d714c9f),LL(0xb70f91c2,0x7cde2c3e)}, {LL(0xe9871f0c,0xe6d0a8ce),LL(0x19e8444a,0x902bc60b),LL(0xff0cd43a,0x8651ed57),LL(0xd480d222,0x4418cc07)}}, {{LL(0xf3cbe01d,0xb5e0c7e3),LL(0xe43adcdf,0xbf4a899f),LL(0x78f8f79d,0xb89b022c),LL(0xf42c797c,0x79cbbf97)}, {LL(0x59d53cc1,0x46d73cc5),LL(0x4ffca67c,0x99f683e6),LL(0x98865e5b,0x527c16ec),LL(0xf68f8ee0,0xc844b70f)}}, {{LL(0xc9854994,0xcffcccc0),LL(0x74926d5d,0x4aafcc15),LL(0x835aea59,0xeb084832),LL(0x20df21cf,0xcb317b5f)}, {LL(0xe43d1853,0x3c45b084),LL(0xb93b9167,0xd12c9411),LL(0x19316bdf,0xb0901982),LL(0xd11ab5e2,0x76bfa2ac)}}, {{LL(0x4e84d3e9,0x22bf23cb),LL(0xd1572d4a,0x96ec9f8e),LL(0x080ba39a,0x31594ae4),LL(0xadc6bae4,0x105b5677)}, {LL(0xa644e230,0x501e45dd),LL(0x64573126,0xeb571f27),LL(0xa36ac1ef,0x1fc3d478),LL(0x327c7da7,0xbd5fcee8)}}, {{LL(0x34a70bfe,0x1b2b1885),LL(0xa36345c5,0xcfa421f7),LL(0x6f322ae9,0x2f33f4cc),LL(0x4dabb7a0,0xdac0bb75)}, {LL(0x923cea0a,0xfba35536),LL(0x6d9cb50c,0xc16f73e5),LL(0x25812c96,0x23216dc6),LL(0x3d7ab424,0x82945e67)}}, {{LL(0x0796605d,0x829577b2),LL(0x5026907f,0x47fa0978),LL(0x2d0f68b2,0x99701169),LL(0xbc1e46db,0xa0d24be4)}, {LL(0x2eb2ac98,0xcf409c2e),LL(0x97f3ff5c,0x7b59c3c5),LL(0x81ed7f02,0x2f4576bd),LL(0x10399c22,0xe41339e5)}}, {{LL(0x2ecce0e6,0x562d7744),LL(0x9a1656c2,0x1afc3869),LL(0x86200621,0x5714820e),LL(0x566da805,0xee36f7b6)}, {LL(0x6e5a2a06,0xe6694104),LL(0x8caabaab,0xd4390b74),LL(0x93b0d142,0x9db20998),LL(0x7926baf3,0xe1811b81)}}, {{LL(0x08bc1965,0xd578f2ed),LL(0x35f00d5d,0x9a7e31e2),LL(0xc9007327,0x3725b65c),LL(0x29c36f38,0x157cfe95)}, {LL(0x23a521d7,0xb1c3d0f1),LL(0xb8a9ae08,0x3e65fb7c),LL(0x690b8f78,0xed48bcf9),LL(0x90d5dfde,0xe5f46b2c)}}, {{LL(0x0b6da2b6,0x14aebb35),LL(0x7b65ee55,0x91fef336),LL(0x1a0a004d,0xdb77b57b),LL(0x23aef1f7,0x1c59b628)}, {LL(0x3ec88d18,0xa79c8c89),LL(0x4fde31f1,0x52cca38a),LL(0xcf4e30b6,0xe2f64a94),LL(0x37ff1cbb,0x2b4cdbd7)}}, {{LL(0x0b566632,0xcb542f68),LL(0x676fae9f,0xedab69a6),LL(0xc45cb6f0,0xc4531e0b),LL(0xb88fe4a5,0xf967ec6e)}, {LL(0x2919785d,0x4ab4e645),LL(0x7a17b20f,0x2dcaefca),LL(0xda7afaa0,0x65c89c05),LL(0x4dafc6a2,0x59ea00e9)}}, {{LL(0x8eb43733,0xa6362bf8),LL(0x12011803,0xae2dddc1),LL(0x0bb2aaf8,0xbbf516b1),LL(0xd8de21a3,0x9f2627e9)}, {LL(0x43a20b74,0xaf30439a),LL(0x4ce86408,0xac7e07b0),LL(0x7c10566b,0xc54cdff2),LL(0x6279af0a,0xe3ee0622)}}, {{LL(0xf7770f95,0x57d09708),LL(0x123e020b,0x6f0ba223),LL(0x6cd41559,0x6c123fb9),LL(0x6fb30f58,0xc54f5c65)}, {LL(0xbbf7101c,0x5e168af3),LL(0xce974455,0xf6d6dbdb),LL(0x88313516,0xa001f3b9),LL(0xdfb4ac20,0xe6e4a26d)}}, {{LL(0x506f7dcd,0x74e7b7fc),LL(0x5d037d69,0x985e8546),LL(0x1ec8d374,0xff00a4da),LL(0x505b4180,0x8c339ae3)}, {LL(0x3a5f71c4,0x78bcd4f2),LL(0x67ac3e9f,0x2fb4d99f),LL(0xee65dad1,0x7dd25aa6),LL(0xb62c34dc,0x2fd63fc2)}}, {{LL(0xf7700192,0xdee42663),LL(0x2c3248e9,0x9925a206),LL(0x2ea9f052,0x4a55a55d),LL(0x16ac67fe,0xe1d6efcd)}, {LL(0x9bb02415,0x7f82246d),LL(0x72cd7a6c,0x2fadbb9b),LL(0x712004dc,0xe977a037),LL(0xb3c9f4b9,0xe8c449b2)}}, {{LL(0x861ea138,0xa2cb838a),LL(0x356ae003,0xfcbe219a),LL(0x1838504f,0x15c02496),LL(0x0769d5dc,0x58cef52c)}, {LL(0xb3fef999,0x7e94ff7d),LL(0x04e4fc87,0xf55501e0),LL(0xc05430dc,0xcdb5fd36),LL(0x778c5cd4,0x49872453)}}, {{LL(0x1b5e7ace,0x4c4855ff),LL(0xb159fe74,0x89fc6309),LL(0x3c9ebbe2,0xaca00404),LL(0x866bf867,0x4c030591)}, {LL(0x9b18a535,0xa7e8f599),LL(0x5c0a0a44,0x9203ebfc),LL(0x463207c9,0xbf1b30cc),LL(0x9d135aeb,0x90b59001)}}, {{LL(0x794cb3ab,0xedc44d04),LL(0x0ad7be70,0xb3baa475),LL(0x6c09fc91,0xb7d8c7c5),LL(0xf45a5bd6,0x2a362d71)}, {LL(0x8cf3e5a6,0x36e308c3),LL(0x0a649c31,0x4caf2cd1),LL(0xb3c501c7,0xbae328f5),LL(0x83a0eeb3,0x2efeca03)}}, {{LL(0x7086093a,0xc3a27585),LL(0x6d686d83,0x78e86515),LL(0xedf0def6,0x18cf3ac1),LL(0x5a1d6cf4,0x2f6a56da)}, {LL(0x30084873,0x350c822e),LL(0x65843610,0x82d48087),LL(0xf393ecd1,0xa4e752c1),LL(0xeeb74f25,0xe3034d6d)}}, {{LL(0xb8b0c5c7,0x1793727c),LL(0x7ec9ce37,0xde561ca6),LL(0x6190f612,0xd9eddc50),LL(0xca89a191,0xb52dc77c)}, {LL(0x4bf1e87a,0x990010b2),LL(0x15b91691,0x073136b2),LL(0x15546011,0x50111261),LL(0x0196cb8d,0x17d48864)}}, {{LL(0xfd61d824,0x7ec44104),LL(0xf088d3db,0x213550ef),LL(0xacbbb608,0x5e8d321f),LL(0x39312b64,0xc317c1f8)}, {LL(0x27de4329,0x7a4a1cd0),LL(0xf9b135e4,0xbfb33f07),LL(0x59b94480,0xcf82b639),LL(0x70b118e6,0xca62d957)}}, {{LL(0x2b1d45fb,0x95b2ff03),LL(0x2570686c,0x472dd56c),LL(0xd3d50e32,0x4fbae8a0),LL(0x65796a08,0xa31c65dd)}, {LL(0x037ce5bb,0xe261f6f8),LL(0xd042073b,0x3b7816bf),LL(0xbfba45f8,0x6d0ebbee),LL(0xc9522e36,0xf2d99979)}}, {{LL(0x77cb5b0c,0x707f2a18),LL(0xdfc02b82,0x954b5a91),LL(0xc20ae04b,0x246b9a55),LL(0x9dd79f93,0xa1486775)}, {LL(0xc11f6d8e,0xd4092830),LL(0x267a4dab,0x74ca482f),LL(0x9c58706f,0xe3c80bb6),LL(0x099154c1,0x245f04b7)}}, {{LL(0xf149259f,0x3a4b25b5),LL(0x65ccbe91,0xeac735f8),LL(0x572788a4,0x260e749f),LL(0xe34d40cb,0x30b9c736)}, {LL(0xf524a17f,0x65981d50),LL(0xcddbbefc,0x6c462f5d),LL(0xa1e57312,0x245bfa18),LL(0x46dc8ae0,0x3b4b003c)}}, {{LL(0x5d262a35,0xb1958797),LL(0xffafd8c5,0x83f6e604),LL(0xbc2e0801,0x60843f9c),LL(0xc783ad3d,0x11d85ac1)}, {LL(0x2e016e43,0x1ce477dd),LL(0xfb4a0201,0x2b628f06),LL(0xbf4f77d7,0x897b7f62),LL(0x10277d8a,0x52e04f22)}}, {{LL(0x5f3f0d6a,0x17132351),LL(0x59a96c4d,0x13c9e064),LL(0x86f05ae8,0xc73892b0),LL(0x4212ad65,0x94545c8a)}, {LL(0x3dc4984c,0x0591b091),LL(0xf2ec1ca9,0x06845698),LL(0xb3ac894b,0xb0e1e1d0),LL(0xa7c915cd,0x962ca1da)}}, {{LL(0x95331bd5,0xb0640de8),LL(0x478c1b6d,0x2544348a),LL(0x5647a67e,0x3c3bd415),LL(0x5b20e5fb,0xd7970ef8)}, {LL(0xe06b4fa6,0xd6e6f6be),LL(0x871390ff,0x5ae29e5e),LL(0x7256daa1,0xc7924188),LL(0x59f61750,0xfae5e501)}}, {{LL(0xd1ef1d2b,0xfac83ece),LL(0x554736da,0xa567060c),LL(0x1dba8bc7,0x697571f4),LL(0x553fbcfc,0xd3fc5aeb)}, {LL(0x9755fab0,0xe665970a),LL(0xb5537da8,0x30fbe8d9),LL(0x97c2b5f0,0x7a7d0013),LL(0x1b700a02,0x9fea5c9c)}}, {{LL(0xe9a377da,0xcfc0166e),LL(0xac502375,0xcc78f3d8),LL(0xba64c3b7,0x803fbbda),LL(0x4d70cc42,0xe53c7d6b)}, {LL(0x5189b7da,0x6b927bba),LL(0x8b05322a,0x2c86253b),LL(0xf3869873,0x333e7491),LL(0x4b492879,0x9308348a)}}, {{LL(0xb9ab0a36,0x39bfa2a8),LL(0x18f71ac7,0x560f80a6),LL(0x45e24412,0xca9b265a),LL(0x8e2ddac3,0x6796bece)}, {LL(0x17bfcabb,0x87f1eee5),LL(0x195c9bb2,0x624db4d9),LL(0x2b4db6d2,0xf7110fcf),LL(0xb432d19d,0x41d3fb0d)}}, {{LL(0x73554a3c,0x3344ea7d),LL(0x830a3881,0x4c968dad),LL(0x687f71ec,0x5df71ad2),LL(0x259cbc07,0x4c4df41f)}, {LL(0xeb541d72,0x8d12d2e0),LL(0xa20fb162,0x94c0dab6),LL(0x1eda0516,0x9bbc2524),LL(0xdd7871ff,0x696c924e)}}, {{LL(0x1db84dc1,0x97efb495),LL(0x03cbfbf8,0x7d293ce5),LL(0xbc48d007,0x79e25d3e),LL(0x8591a1ea,0xc900a580)}, {LL(0xd37508c3,0xf0277a09),LL(0xe84557bf,0xbf583aa4),LL(0xd8228591,0x2e258d60),LL(0x117da3a9,0xb037e17c)}}, {{LL(0x243d588d,0x4b35355e),LL(0xcce2539e,0xbe6dfa36),LL(0x4843c9da,0xa57d5823),LL(0xf59348fa,0xe3d91511)}, {LL(0x2791c08f,0xb5d1395c),LL(0xf6fdcc93,0x04129e5d),LL(0x0f53087b,0x635a63ba),LL(0xf237612e,0x66da6bec)}}, {{LL(0x22755420,0xc3d052e5),LL(0xd7a1bd35,0xc37a9b47),LL(0x9b347e02,0xf19613f3),LL(0xbbda7ae0,0xee84dbac)}, {LL(0x3a85f2e5,0x603be21d),LL(0xff679451,0x5f0927c2),LL(0x8674f8d7,0x799013ad),LL(0x00f465e5,0x17b248d3)}}, {{LL(0x96ca19de,0x2a29135f),LL(0x957d1844,0xc8e56e32),LL(0xa11a4349,0x935e7eaf),LL(0x741b73d3,0x717308e1)}, {LL(0x7233a9df,0x40477acb),LL(0xd2c83b72,0x7a78dac2),LL(0x2c5d79d2,0xfb882461),LL(0x76f44fa0,0x984505fb)}}, {{LL(0xdfdc4a9d,0x5cdded16),LL(0x3f0ff597,0x4cbea135),LL(0x8a79078e,0x38daf27a),LL(0xce1bbf0e,0xb4b0085d)}, {LL(0x86f19fd0,0xb6b0d8d7),LL(0x1778ca6a,0xe0fdcdae),LL(0x0b26b9b5,0x257c7df9),LL(0x141dcafc,0x4b82422c)}}, {{LL(0x4d3cf148,0xcf8a2dad),LL(0x5f17e914,0xf1a4e292),LL(0x60de8f64,0xc40755bb),LL(0x8718f49d,0x412449f8)}, {LL(0x8737b6cb,0xdabb9968),LL(0x6236ea05,0xdd94ae81),LL(0x05c5aca2,0xb5223cd0),LL(0x762210ed,0x6b81bd33)}}, {{LL(0x5d4164df,0x1f0921db),LL(0x8d4a35df,0xf6fdb08f),LL(0xc602d4d8,0x1efcf3c7),LL(0x057f3aa0,0xa2ecd9e6)}, {LL(0xeb4fcba2,0x13a6c576),LL(0x13130559,0x16425bd4),LL(0x416b4968,0xa9eac848),LL(0x2119600e,0x617c32a9)}}, {{LL(0x0bb49e40,0x1a84eca5),LL(0xbc2310b3,0x2ed98d25),LL(0x5edbc719,0xad191f88),LL(0x0376ae08,0xd8d667d5)}, {LL(0xf0b4fe29,0xb855a8ee),LL(0xe75354f7,0xc3fe79fb),LL(0x403b651e,0x1ee9b9e6),LL(0x2baa2c6e,0x99ddbb3c)}}, {{LL(0xeccce37d,0xc6a84c47),LL(0x038c9821,0x71a05a24),LL(0x9a6353d8,0x8d32194c),LL(0xcf0a1462,0x14cd3ea6)}, {LL(0x7bdbe521,0x40d70aa2),LL(0x95c80cd8,0x200f0b21),LL(0x3efdf656,0x4c79dab9),LL(0xa981d8b5,0xafa44e4c)}}, {{LL(0xa7111315,0x811b9387),LL(0x7590c35d,0x0255a234),LL(0xf1af875c,0xb18e87c0),LL(0xced5cc1f,0x0a930b41)}, {LL(0x96094a55,0x6ff4fca4),LL(0x6a9dc519,0x74095b88),LL(0xafa4894a,0x44492273),LL(0xa2e6f56e,0x54f16f88)}}, {{LL(0x34485e31,0xd613fbb4),LL(0xd2464242,0xc716c370),LL(0x1644f2e1,0x21535837),LL(0xbe417c3a,0x7719474b)}, {LL(0x2045d2be,0x31bfb158),LL(0xf50e6828,0x10855524),LL(0x98a67af1,0xdb9490ad),LL(0x1c281ff3,0x41a34aa6)}}, {{LL(0xa8bf2580,0x87109ba8),LL(0x2d7eb52d,0x70c2e936),LL(0xfb3fc109,0xefe9fe2c),LL(0x780526bf,0xfd3f4d7b)}, {LL(0x9ed0c3bc,0x6f9a48d8),LL(0x5d8205b2,0x0aec850f),LL(0x1c6a13ef,0xa378f8c6),LL(0x9d10e11b,0xac02f367)}}, {{LL(0x3b9bbf54,0x79c6b396),LL(0x42779c58,0xfb586d71),LL(0x889eecb3,0x5d975728),LL(0x434537d8,0xda2ec867)}, {LL(0x62f31813,0x15a3c9c3),LL(0x3c30433e,0xc4b357c8),LL(0xc464e972,0xf26d281f),LL(0x4512ffcf,0x99fa49e7)}}, {{LL(0x725b9753,0x456db1b2),LL(0xb42941c5,0xec501760),LL(0x7d6d406f,0xd822a9d5),LL(0x7bbcd4d6,0x4bb7a820)}, {LL(0xcc96a5b7,0x079b1fe0),LL(0x24aa4901,0xf83e5755),LL(0x20da7fcb,0x317cdd1d),LL(0x93b04a81,0x487fd706)}}, {{LL(0xe43332ef,0x43e0671f),LL(0x441c2218,0x71c5dd5b),LL(0xe922ba18,0x4c1d2c1f),LL(0xd619cb67,0x558e9c2f)}, {LL(0x1ec51255,0xd04acde0),LL(0xaf824507,0x824b3740),LL(0x744c6afe,0x62d1b9de),LL(0xab0d52e3,0xb99616db)}}, }, /* digit=19 base_pwr=2^133 */ { {{LL(0x7f6a1cda,0x5ec9c084),LL(0x823d6350,0x68839c14),LL(0x03bad007,0xcbbb678b),LL(0x4788854e,0x6a727255)}, {LL(0xef5c7294,0xc747fea2),LL(0x4875e775,0x74852778),LL(0xaa61a893,0xad7b8e8b),LL(0x40da98b1,0x18ff3335)}}, {{LL(0x5529ec80,0xa51e9f4f),LL(0x6fd146d1,0x0420274a),LL(0x8e300c2c,0xbbf1ab66),LL(0x41653fea,0x2d0b3a9d)}, {LL(0x23a495b9,0x2be2180f),LL(0x5415d73b,0x6ef3c374),LL(0xc67ae4fc,0x1d3e1ec8),LL(0x98d31f5f,0xa5839e9c)}}, {{LL(0x37d77c01,0xf54114d6),LL(0x41023c87,0xc2e18a4b),LL(0x9e6e1221,0x6fa6c3d3),LL(0x410e48f9,0x9a6cf4e2)}, {LL(0xb181828f,0xe0881140),LL(0x78cb7833,0x17c6df29),LL(0xa7cd2367,0xc1eb8df1),LL(0xca89f922,0xb78f1c8d)}}, {{LL(0xd0d42887,0xf25d4777),LL(0x2b7a2707,0x4b489218),LL(0x2d3966fe,0x1b4dbf9b),LL(0x41ae2bec,0x4bac5f48)}, {LL(0x1733964e,0x68db2733),LL(0x6a814a69,0xa10c5dff),LL(0xa9898348,0x84ebdaf0),LL(0xa74da3f4,0x60e46823)}}, {{LL(0x93420649,0x452b6b1d),LL(0x6ed5d7f6,0x9dd6452b),LL(0xe687b577,0x4a9b8fa1),LL(0x854c49d7,0x1e203166)}, {LL(0xa45feba8,0xf523667e),LL(0x5f9f4a56,0x9ecb4d44),LL(0x7fb1c641,0xb8655a5f),LL(0x87c26201,0x5516401a)}}, {{LL(0x0d2face6,0x24677754),LL(0xa8ade59c,0xd9f7da7f),LL(0x7fa7df06,0x27e3ad77),LL(0xf60395ad,0x35a4caf0)}, {LL(0xe4e701ac,0xfaef231c),LL(0x23755489,0x9e135976),LL(0x43554ad3,0x7caa73ab),LL(0x94f0d878,0x9d8554d9)}}, {{LL(0xa85b81d5,0xe42040ce),LL(0x40fa9631,0x4d28aca7),LL(0x7e04b755,0x076fed3d),LL(0x1129ce4c,0xdde3d347)}, {LL(0x1179af95,0x77f785d7),LL(0xf74e0672,0x4782f842),LL(0x0b4597cb,0xbd068cc1),LL(0x8f4c65b7,0x3d6d4b2a)}}, {{LL(0xf9066d73,0xe0642d18),LL(0xa098b3bf,0xbe1d2ec3),LL(0x21b4954c,0xefee860c),LL(0x27b629bb,0x4d7c4e6d)}, {LL(0x8e8b81b0,0xcd8f1e03),LL(0x7fe77eb0,0x4a80168e),LL(0xce247c73,0x4d977591),LL(0x857e0356,0x9b30c9f2)}}, {{LL(0x2940e9de,0xc02495ba),LL(0xb6d2b72c,0x357299f5),LL(0x06a9c2e4,0x132b4c63),LL(0x084d8c67,0xe90a90c5)}, {LL(0xace1b471,0x0f0c9e94),LL(0xf1e3d8f6,0x769457e1),LL(0xd71118c6,0xc4c30ce3),LL(0x6b652a3d,0xdb5fd8d6)}}, {{LL(0x4def5978,0x090df107),LL(0x2d8a5f3a,0x1abcfa32),LL(0xa34b70db,0x2976b012),LL(0xfa5e75b9,0x90f541d4)}, {LL(0x37a6e9a0,0x50c991a9),LL(0x903bffda,0xf51e8693),LL(0x8d344776,0xa2697ab4),LL(0xe34a7850,0x77134fe8)}}, {{LL(0xa72597ac,0x723e5d3d),LL(0x4269aff7,0x4a49847a),LL(0x443b8db6,0x75ad9088),LL(0xa51d80a1,0x9b7d00d5)}, {LL(0xe5e04ac2,0xce1c7049),LL(0x2a792bde,0xb8c2793c),LL(0xe410e175,0xde9220a0),LL(0x9401bc2a,0x4b3a9b85)}}, {{LL(0xf037d15f,0xc7eaf2c5),LL(0xc7afbf8b,0x410b627e),LL(0xd7bedf50,0x243cdb79),LL(0xbe6512d0,0x04813b51)}, {LL(0x26beca2f,0x2fb77cab),LL(0x7baa3099,0xbb601975),LL(0x40bda4d0,0x8c327e59),LL(0x13c23444,0x85b9c764)}}, {{LL(0x08ed59d8,0x26960d9c),LL(0x4a72854d,0x9b76dced),LL(0xfdc3b7f5,0xca2f579a),LL(0x6cae8b4f,0xac27028a)}, {LL(0x42326aa5,0x48fd1a49),LL(0x5759c63f,0xb95fdb4f),LL(0xe0a96abf,0x27655358),LL(0x36ed53b0,0x26d38b64)}}, {{LL(0xfc6d1f3e,0x03cfdd49),LL(0x15adaba0,0x20af5886),LL(0x754dd268,0x74c6c943),LL(0x7977717e,0xe7d52cdf)}, {LL(0x3b414dd2,0x9a81d440),LL(0xd790a4c7,0x697c7b4a),LL(0xedbce1f2,0xb1b7735f),LL(0xbefa7210,0xbd90e63f)}}, {{LL(0x7ab207d1,0x2e2b0dad),LL(0x9b373211,0x89abbd83),LL(0x8e35e2bb,0x45d34ebc),LL(0x064856f6,0x67ba3ac5)}, {LL(0xa52c7676,0xb5527dbe),LL(0x71294012,0x906fb217),LL(0xab305260,0x65fca552),LL(0x14ee193b,0x89ac52a3)}}, {{LL(0x88c06b1c,0x673aead4),LL(0x49d9d4e8,0xea8af420),LL(0xcb9e86bf,0xa7b4409a),LL(0x5414aa56,0x49f76f71)}, {LL(0x8c13857a,0x6603c801),LL(0xce742384,0x7c26f1c2),LL(0x2a665719,0x042fb224),LL(0xe175b0c6,0x2619f254)}}, {{LL(0x7c092397,0x5b3b71ea),LL(0xf18c29ae,0xd9087023),LL(0x2008841d,0x48dbecbd),LL(0x22622bba,0x658c998e)}, {LL(0x578e463f,0x38a2cc6d),LL(0xcbb88796,0x7002380f),LL(0x71695101,0xc545baff),LL(0xce65b49c,0x064a0500)}}, {{LL(0xb1ae0398,0x3651d926),LL(0x4ace0e86,0x33c9ea8f),LL(0x1a6debd7,0x481fab1b),LL(0x4d365031,0x65b58a79)}, {LL(0x811e8f01,0xb73ec84b),LL(0x51342ef2,0xb6aa3955),LL(0x9efcdbcc,0xdbce3d9f),LL(0xcfbf2a4f,0x5791b35f)}}, {{LL(0x6eaad1f0,0x67024158),LL(0x0063ae25,0xe8dbaa88),LL(0x9fedc144,0x6d2051cc),LL(0x18b5e86d,0x136c2ab1)}, {LL(0xc89241d4,0x3b2d3d63),LL(0x4a82dec6,0x843cfa3d),LL(0xf0a5f163,0x64fa5860),LL(0x1ae3be83,0x2d9b6095)}}, {{LL(0xb01a91e5,0x75f97753),LL(0xcd0d8cac,0xd374dfa2),LL(0x8eb72ba0,0xe5dbffef),LL(0xd7b8a624,0x61049807)}, {LL(0xa39277d3,0x9c8b5e93),LL(0x3b1cc635,0x6e5ba593),LL(0x21cde059,0x8bd0a69e),LL(0x071ec0c8,0xd0a19b53)}}, {{LL(0xd1bb088d,0x8c87785a),LL(0x7e249c39,0xd801d5a6),LL(0x8688914f,0x002ee598),LL(0x6b68413d,0x52b014fc)}, {LL(0x507946df,0xaf1d7e88),LL(0x84ccebf1,0xa38e436f),LL(0xaa86a4b6,0x37d9b946),LL(0xc506a394,0x55da0db6)}}, {{LL(0x02b900bd,0x856928c3),LL(0x7bc6a67b,0x9eb926a3),LL(0xd0f39446,0x2f4d392d),LL(0x01c49daa,0xb12f2761)}, {LL(0x13874ac7,0x07b8d23f),LL(0x1efaa157,0xa473ef4c),LL(0xdf8cf2ab,0x550765f6),LL(0xd23d3750,0xeba88504)}}, {{LL(0x2434fa2e,0xf05791d4),LL(0x4e2a05ea,0x8c0899c3),LL(0x898bc9b0,0x40a53bdd),LL(0x40c8bf7c,0x6c255f6f)}, {LL(0xe164b910,0x203db8c5),LL(0xc1c4de69,0x070baaee),LL(0x5df5c0a7,0x89660629),LL(0xdb364b99,0x0b9c2f4b)}}, {{LL(0x44bb5a79,0x012c6994),LL(0x9bd1fdc0,0xf5928e0c),LL(0x3ce49191,0xd30b8a97),LL(0xe3a05dd3,0x52792b85)}, {LL(0x1d3d69c3,0x0da08916),LL(0xed59a28d,0x931759e8),LL(0x6ca05485,0x412148d9),LL(0x3d6e9964,0xb1517aa0)}}, {{LL(0xde75812d,0x15204ba9),LL(0x5698b03f,0x49e377e0),LL(0x05c9072e,0xe7790d41),LL(0xdba28e80,0xf79adbed)}, {LL(0x4644840d,0x6aad9f96),LL(0x2e0a695b,0xc3f3d032),LL(0xaa4aa737,0x3eb739d2),LL(0x37d8d520,0x45c6b665)}}, {{LL(0x9917cb85,0xc3ba2408),LL(0xd7bf6304,0x1c729ffb),LL(0xcc160245,0x56b9935e),LL(0xe03cb227,0x42379567)}, {LL(0xb66bfc5d,0x2dc20028),LL(0x95de8ed3,0xfaf7d224),LL(0x3214024e,0xa7541158),LL(0x50aabdb6,0x2f7755d8)}}, {{LL(0x7ea9b93a,0xb74ac27b),LL(0xa2e0516c,0xc1c5a8fe),LL(0x6b64f56f,0xe9f4f222),LL(0x8fbc4a64,0xf3c0c7fb)}, {LL(0xa16edc23,0x43ac0ac2),LL(0x6d086e9e,0x0e26e4ad),LL(0x5bc0961f,0x5b8ef949),LL(0xd2b77c29,0xa0d16d39)}}, {{LL(0x78845d09,0x50b43efa),LL(0xcb3acdd9,0x3899e1be),LL(0x18d4ec31,0xa93a28e3),LL(0x0a66fe47,0x18a4eeed)}, {LL(0x87333831,0xd7a7bf46),LL(0xdbe14699,0xbbf5c1a8),LL(0x80b9c9d0,0xf2a3da73),LL(0x82bceb4e,0x133c138a)}}, {{LL(0x335a923a,0xcfd4b885),LL(0x8fc82f3b,0xf9b69b3f),LL(0x8784c35c,0x08908b60),LL(0xd843b66e,0x76bf1082)}, {LL(0xbb57a641,0x1ba730bf),LL(0x34e9f095,0x3bb4a8d7),LL(0xc28d5414,0x0342d32b),LL(0xcfd99e1a,0x8fb13cbf)}}, {{LL(0x1d02f47c,0x3845e507),LL(0x14ef0b26,0x4d77af89),LL(0x5ef578d9,0x93454480),LL(0xbdc408ec,0x23138c57)}, {LL(0x47cf528a,0xdac833ed),LL(0x29d7cf20,0xd18e9865),LL(0xcdc8e55a,0x93208743),LL(0x724025a0,0xbfe570c8)}}, {{LL(0x3aee838e,0xb75c3de0),LL(0xe0f21f23,0x29304886),LL(0x82791daf,0xe46792ab),LL(0x3f124394,0x3d798d92)}, {LL(0x29a6fb5e,0x2446dc81),LL(0xbd68c23a,0x2446e5b3),LL(0x689b1176,0xe1b5c76d),LL(0x9a852082,0x3fb66661)}}, {{LL(0xd9b45206,0x8d6fbcc7),LL(0xeabc4640,0x00ab735d),LL(0x810e37d1,0x428c7017),LL(0x27af5718,0xa4365872)}, {LL(0x0a910146,0x8f195823),LL(0x0ff76704,0xc13ccdd7),LL(0x44d6f1c8,0x59d34ad6),LL(0x795b61b4,0xd3dfa6b2)}}, {{LL(0x12eea439,0x1ec08010),LL(0x7b2cd52a,0xafbbea32),LL(0x68cfe98b,0x99428f9a),LL(0x95628fe7,0x4ff9a5bc)}, {LL(0x7ac41e9a,0x212baeb7),LL(0x29206e86,0x595cf03f),LL(0x733f37c4,0x4b62a429),LL(0x4d3cb6a6,0xa1fac4ae)}}, {{LL(0x1aed3c45,0x2d6cb0e6),LL(0x4e6da48d,0xf6703493),LL(0x2d13f9c1,0xa0036fb4),LL(0x7fe3ea2e,0x7db5078a)}, {LL(0xd5992163,0x152a1fc0),LL(0x744b44ff,0xd63270e9),LL(0xf177c075,0x56730292),LL(0x17c3e08c,0x470f5e72)}}, {{LL(0xecb927f5,0xbf53d223),LL(0x629e8aa1,0xc80fbc1b),LL(0x24d72477,0xed59f186),LL(0x38811583,0xc266f5a6)}, {LL(0x7c404560,0xc6f37bc1),LL(0x0c5b68e9,0xd58c10e5),LL(0x916e8f3c,0x696de793),LL(0x56a7781f,0x7298af8e)}}, {{LL(0xb16679d5,0xaf063553),LL(0x4316ed7e,0xa509f449),LL(0xb53cc0e2,0xe3d6ec43),LL(0x16ba34cd,0x9e957ce0)}, {LL(0x7857d80d,0x2b0c7fbc),LL(0x3daffbf3,0xc2c671fe),LL(0x0d251d41,0xebcbf012),LL(0xffef45f5,0xedcfe7f7)}}, {{LL(0x334a1734,0xf5b66555),LL(0xe505f4bb,0x4354ccfa),LL(0x52a59260,0x6ee0b5b9),LL(0x5a699a93,0xb7bb64c1)}, {LL(0x6de84422,0x85e34c0e),LL(0x8bbe0560,0xca9bacfe),LL(0x952a52d2,0xa08c780f),LL(0x3919176b,0x0e794b05)}}, {{LL(0x154d282d,0x8a496598),LL(0xdc34508c,0xb2999dc4),LL(0x9db4410a,0xfc304fe3),LL(0xe1bc07c8,0xbc09aee4)}, {LL(0xef6d497d,0x1d2f0147),LL(0x96488fc1,0x3b9e06e0),LL(0x34cb97a7,0x37635d04),LL(0x8757f955,0x9a294b89)}}, {{LL(0x59508819,0x38c568ac),LL(0x46e15b82,0x854370fc),LL(0xee57f0b4,0x9f676404),LL(0x8f45319c,0x268854cc)}, {LL(0x63746274,0x4256d25c),LL(0x0496cf9c,0x0a553821),LL(0x15e2fc17,0xb6bf27de),LL(0x99bd538a,0x6848f83a)}}, {{LL(0x1685e460,0x00e15d0a),LL(0x155d00b6,0x6fae8b37),LL(0xdc561456,0x277126d8),LL(0x6bf70c63,0x331c02e5)}, {LL(0x515f39b7,0xc9b7da4e),LL(0x966c2060,0xb7e0d135),LL(0xc401f926,0x9a801457),LL(0xffb0137e,0xcc560825)}}, {{LL(0x5c7e38fc,0xbcfac5f8),LL(0x174e97ba,0xd542c1a4),LL(0x0bb507b8,0xbea67b1e),LL(0x3b782fd8,0xf008cc2c)}, {LL(0x0aa329bc,0x865834da),LL(0x2b6db70a,0x0fd746f2),LL(0x65fbe439,0x8e72e5f7),LL(0x005295ee,0xac23881d)}}, {{LL(0xad9d013c,0xc2c45fef),LL(0x71c311f9,0x0df74277),LL(0x6bb32b66,0x69caf967),LL(0xb8e4a3e5,0x9fbd32ff)}, {LL(0x78c0c439,0x39d94e31),LL(0xffa4b625,0x7489a8f0),LL(0x8aac717c,0x59af0ec3),LL(0xa12d996f,0xdd3b470e)}}, {{LL(0x8da3fef0,0x6d60cb97),LL(0x044d64fc,0x5164d722),LL(0xfc21305b,0xefe06ead),LL(0xceed89c1,0x72b4c45e)}, {LL(0x8cabf0df,0x072cf1dc),LL(0xa5371d3e,0x0a0d7c0c),LL(0x2ae831d5,0xb13ba707),LL(0x269f189e,0x7702c3c5)}}, {{LL(0xc8239fe7,0xfb8e903e),LL(0x524f213c,0x5805c2ef),LL(0x70645f7f,0xdf056e45),LL(0x454c4577,0xfe10ecfb)}, {LL(0x990dc567,0x422126da),LL(0xbf55cd81,0x95a5d753),LL(0x8c2688ed,0x2705a00c),LL(0x2f8f91af,0xd079ecb4)}}, {{LL(0x2b69a2c8,0x8cd13fa0),LL(0x36b657b8,0x7b0f310a),LL(0x251c595b,0xa7247cfd),LL(0x5a36e4b1,0xda352dc8)}, {LL(0xf43312de,0x588d2e88),LL(0xdb9f6dec,0xef80a48f),LL(0x3fb2d6e3,0x39583634),LL(0x5a46bc46,0x0fbfa769)}}, {{LL(0xfe701598,0x3570a3f2),LL(0xac815fbb,0xd1d0d091),LL(0xd7f2b1b2,0x4d7bfadd),LL(0x66496326,0x509298d4)}, {LL(0xcad9fb50,0xb7accafc),LL(0x9c592dee,0xcdbcb762),LL(0x6888482a,0xfe47a3b1),LL(0xe8b8c133,0x312be210)}}, {{LL(0x00167f93,0xc474b07f),LL(0xa637f35e,0x19457000),LL(0x5005d8a1,0x3eafa14e),LL(0xadf25f29,0x2a84723a)}, {LL(0xa741cf9e,0x2c9d7ebb),LL(0xc3913acf,0x94024dc2),LL(0x97b98f1f,0xac2db91d),LL(0x46a7bf92,0xfb9a0502)}}, {{LL(0x6487a5d4,0x8874ffb5),LL(0x2f53e25f,0xc02a12b5),LL(0x416ba8fc,0x38654a57),LL(0x0c0b25d6,0x226356f2)}, {LL(0x6030f2ac,0x34f2eaa6),LL(0x9cea9176,0xb788baa1),LL(0x4e912104,0x66fbe9f7),LL(0x39a69e3d,0x982ef71d)}}, {{LL(0xbbe5733a,0x9f361d17),LL(0x1988f31e,0xc79569a0),LL(0x9e0f52fe,0xf2b96ecb),LL(0x80235136,0xc78e44dc)}, {LL(0x8462ef4f,0x96053ab5),LL(0x81506701,0xf83c1f6d),LL(0xa65c09e9,0xc7313eb1),LL(0x4efcf558,0xf5dfaa4a)}}, {{LL(0xe65ede91,0x8b4819e4),LL(0x6dc0a533,0x5a5824ba),LL(0xb4c930f8,0x89d18b20),LL(0xfcefa378,0xaad7a5d8)}, {LL(0x298dba63,0x2ef790c2),LL(0xe90c322f,0x3e4b31b6),LL(0x52ce2ee4,0xa257bb81),LL(0xd39c36bb,0xb8c2966e)}}, {{LL(0x487719c7,0x13954df8),LL(0x791b00e7,0xcb0f7ae5),LL(0xc8d21faf,0x367a1cad),LL(0x3fbd8a7c,0x44dd204d)}, {LL(0x5f67ec30,0x778fdb56),LL(0x5de5caeb,0xfb288790),LL(0xca53300c,0x310b4d56),LL(0x325c54b1,0x37dbb7c4)}}, {{LL(0xfe771ef7,0xc80c83a4),LL(0x1c1c1b92,0xe212050f),LL(0xf09c666f,0x0f12bb88),LL(0x10a2eca2,0x8ec5f396)}, {LL(0x90a22eb7,0xdaf96996),LL(0x450de941,0xeb77eee5),LL(0x58fb0165,0x13823c58),LL(0x31272111,0x2157ba6e)}}, {{LL(0x2b4f9e7e,0x110ee33e),LL(0xf682d48f,0x7e1b550b),LL(0x3e17cb9b,0x8fd8c6c1),LL(0xe1843894,0x91cfbcf7)}, {LL(0x2917b1c7,0x5fc64346),LL(0xba86d14a,0x06f56d0f),LL(0xaf219f21,0xb8874d88),LL(0x11ab8b0b,0xf8803b37)}}, {{LL(0xbe12841e,0x7e63cf63),LL(0xbc90765a,0x9c9cc421),LL(0x1084fa84,0x0264a597),LL(0x252a9bbe,0xce260a60)}, {LL(0x2fefa4f2,0xfaff225c),LL(0x05bd09b0,0x02b900ad),LL(0x11b1b81c,0x631e5cfb),LL(0x0a193140,0x4d93de46)}}, {{LL(0xe3173750,0xd92a710a),LL(0x671a3833,0xd712d3a1),LL(0x4116e26b,0xbc9caad1),LL(0xa72fbd71,0xeb24f658)}, {LL(0x9055f802,0x3986a207),LL(0xe2707793,0x212446f8),LL(0x1721b395,0x602541d6),LL(0xb07160c2,0x4099a2e6)}}, {{LL(0x2369ce91,0x765390f6),LL(0x5754d219,0x2dc37639),LL(0x7c018afb,0xbc552369),LL(0x35bf6b66,0xca835077)}, {LL(0x61d4b0a6,0x61b83e43),LL(0x27cf66c5,0x8f87f597),LL(0x9357cbf2,0xace57840),LL(0xabe47fb7,0x24834481)}}, {{LL(0xdb3c6e47,0xa434c950),LL(0xaa1da775,0x1f479519),LL(0xf14f9d5e,0x338c9cd2),LL(0x1e75f72e,0x4666ce7e)}, {LL(0xe56564e5,0x4fce4d95),LL(0x89e0ff6f,0x0db55ed5),LL(0x00190b73,0x88796e85),LL(0x454e31d0,0xfdf6492a)}}, {{LL(0xb9ed6e3b,0x30cb3fbe),LL(0xde8f0544,0x5c796282),LL(0xb6af89bc,0xe11b36bd),LL(0xec439d95,0x0a91cf73)}, {LL(0x0a93fe1c,0xbbe74a5e),LL(0xa5d75083,0xcf1f376f),LL(0xf7725460,0x6718bce5),LL(0xa316d17f,0x6654d7b1)}}, {{LL(0x0393aa3b,0xdaa925e5),LL(0x9446cdbd,0x81217e18),LL(0xa7afc408,0x07708483),LL(0x44709dfe,0xa4c76c4f)}, {LL(0x3a1c412b,0x72557d71),LL(0xb49b0e1c,0xeb4c2648),LL(0xe4d6c002,0xcdd24b77),LL(0x77113e0d,0x3384ea5b)}}, {{LL(0x6a10a9ea,0x906fb748),LL(0x0a3b0e89,0x46cda42e),LL(0x7ae4ad43,0x10b9096d),LL(0x3bf2afea,0xe1f23996)}, {LL(0x0dd82d19,0xcb50b941),LL(0x832d93a0,0x008e593c),LL(0xd86a71e0,0x0b1fb0e6),LL(0xb1730860,0x75f2aa6b)}}, {{LL(0x7efc480a,0xed5d4d7c),LL(0xc76c64de,0x500b9d8c),LL(0xec4fc026,0x28904003),LL(0xdec8b315,0xe41b3f23)}, {LL(0x70c06860,0xa9b5caff),LL(0x28343b2d,0x5cb9a4d1),LL(0x9986a0c3,0xec157abd),LL(0xb5fc67e9,0xbcad3bc6)}}, {{LL(0x13aa9c17,0x6e64dd26),LL(0x271aef54,0xa347c4a2),LL(0x883d90bf,0x47b26cb9),LL(0xe1c412c9,0xe84d9c6a)}, {LL(0x1c67439f,0xd2eacc10),LL(0xc61b2b5d,0xd7797bb3),LL(0x8ebdb4be,0x0deda652),LL(0xac3fc2f4,0x9e04455d)}}, {{LL(0x27c86688,0xbbfc6e69),LL(0xa1715a33,0xf7cf2947),LL(0x47bc6409,0xe047a3e3),LL(0x6f2a5b28,0xefeb573a)}, {LL(0xd105ba3b,0xbf3ea3af),LL(0x426c6482,0x5f01b4c2),LL(0x968390b1,0x778a5240),LL(0x72bcf6a6,0xc9c71625)}}, {{LL(0x6fd8b309,0x698ec2c9),LL(0xa055809f,0x512ea17a),LL(0x8822943c,0x28cb44e7),LL(0xdeb7d3e6,0x434dc709)}, {LL(0x1be76434,0xb8b324d1),LL(0x382ff0b1,0x7cf24ed3),LL(0x2905e726,0xda8265fe),LL(0xee6c3abc,0xd57b3915)}}, }, /* digit=20 base_pwr=2^140 */ { {{LL(0xd2a819b5,0xf9010095),LL(0x48f2f653,0x5291aaf9),LL(0xf0afe366,0xfa533907),LL(0x8e279e27,0x88a58ecf)}, {LL(0xfae130bc,0x0f077127),LL(0xf8a54c75,0xee9ccf1a),LL(0xbed82b6a,0x38a6783e),LL(0xed414524,0x9a1acb3d)}}, {{LL(0xd9c12e2a,0xe4e53cee),LL(0x7fc1308f,0x11983fc1),LL(0x892c2d0f,0x3eb4d84d),LL(0x74499723,0xa0bfc1ca)}, {LL(0x0145176b,0x708344d9),LL(0x6f12e75b,0xbb2988e0),LL(0xada67545,0xdf73cead),LL(0x2bb8f989,0xf37069d1)}}, {{LL(0x9cc17f65,0xa24a35e6),LL(0x89d9abe0,0xc49b3e9a),LL(0x2fc09ae3,0x82f40303),LL(0x002cc587,0xbffe7d4d)}, {LL(0x424ef713,0x5511f4e6),LL(0xa658f660,0xb86bf654),LL(0x1c8baea2,0x623388d9),LL(0x33656759,0x60664a71)}}, {{LL(0xd8447e16,0x18996198),LL(0x662171dd,0x17195d76),LL(0xf448b8e6,0x28cfe6a1),LL(0x0658c923,0x8a3c2823)}, {LL(0x9c35e852,0x0c548d89),LL(0x2b378157,0xadf1cd2f),LL(0xf30113b6,0x999e41af),LL(0x9cf4696f,0xf87515a5)}}, {{LL(0x9778aa8e,0x6c332c55),LL(0xd1b8d8b2,0x290ae3ea),LL(0xbf533883,0x3e2bfa0b),LL(0x1a523ee2,0xe48e3747)}, {LL(0x50fde3ed,0x4d40f1d5),LL(0x48710433,0xb57e695b),LL(0x1b241f3f,0xa4101258),LL(0x3042cabc,0xa0cabf7b)}}, {{LL(0xedfea522,0x68eb19c7),LL(0xa400db7b,0x68e028b8),LL(0xa8f03a08,0x6cd97bf7),LL(0xf442fe36,0x09f4d266)}, {LL(0x5d713a1f,0x1ac77f91),LL(0x2f58ccb5,0x356e3a35),LL(0xf8ddc47d,0x31d657f1),LL(0x90092115,0xfea7aede)}}, {{LL(0x4ad49f66,0x2aeba1d2),LL(0x9d40861b,0x16ff2bad),LL(0x7da225f5,0x25464f37),LL(0x1ffc3f0b,0xa2fe66cc)}, {LL(0xac757f41,0x74074d7f),LL(0xcd0a2c20,0x5c85d3d1),LL(0xc974b266,0xccda2a05),LL(0xcc10a04f,0x5c2e2511)}}, {{LL(0x510d515f,0x01ea2535),LL(0x489e7856,0xc861c54c),LL(0x680d17bc,0x9bc8485b),LL(0x819ccc86,0x71472c11)}, {LL(0x0e9b5d8b,0xa7ef9485),LL(0xd029720d,0x698c9fe8),LL(0x61f50161,0x6ce987d1),LL(0x9d240bf6,0x035f6f32)}}, {{LL(0x44ec2bed,0xe7c03c9d),LL(0x76cf95c5,0x0bc4f4a2),LL(0x88f014ee,0x0722d57c),LL(0x76fa941b,0xae406348)}, {LL(0x23ee068d,0x046424df),LL(0xe8c130c5,0xd30b6530),LL(0x554f149d,0x17b69098),LL(0x92f95b71,0x887e04f7)}}, {{LL(0x941c1244,0x414e7371),LL(0x94f1da50,0x1d48fe53),LL(0x6519802a,0xc18bcd89),LL(0x48925019,0xfae7c2d8)}, {LL(0xf2ece2af,0x0f311ddf),LL(0x0a779f79,0x7e8e0e08),LL(0xb6207944,0x47daa5f9),LL(0xefd08d6e,0xf29dc331)}}, {{LL(0x23e48f60,0x9c096e19),LL(0x8dd36f0c,0xbcc6fe53),LL(0xbb86a9ca,0x452e60f9),LL(0xed16cf06,0xad35f732)}, {LL(0x2bf445f7,0xcbdd01a2),LL(0xf60ce893,0xb7848e94),LL(0x2939a977,0x5e65e8ca),LL(0x63cfa5e4,0x304ebedc)}}, {{LL(0x252cc655,0x79bae721),LL(0xc4743792,0xa3b9a4e5),LL(0x36fdba1c,0xf32dcfeb),LL(0x7ac19885,0xadbd0c1f)}, {LL(0xdc42a2cd,0xefb4fb68),LL(0x2289a71f,0x78b1ca37),LL(0x87fc6df4,0x7e1f70fe),LL(0x90a9faec,0x8d024301)}}, {{LL(0x46cd4141,0x37c08672),LL(0x1a60d8e5,0x3c0fed17),LL(0x0f56fea1,0xab18bf06),LL(0x372e757b,0x879ee748)}, {LL(0x1d280206,0x84b19b80),LL(0xd96ac240,0xa40d7ce3),LL(0xfea42ebc,0x5d493fb1),LL(0x40d79bbd,0x9a5fdafd)}}, {{LL(0x383b371c,0x790c0b30),LL(0x676f8168,0x6dae5df9),LL(0x4c584948,0x101bb4fe),LL(0x55faafeb,0xe3d7e99f)}, {LL(0x134c2e3b,0xd2c9aefa),LL(0x79e27788,0x0aa2a71f),LL(0x7ed0a606,0x4082f7a6),LL(0x6a1be308,0x843c12bb)}}, {{LL(0x56e9e473,0xae72ee74),LL(0x743e16ee,0xcecde6c1),LL(0x7c48ca04,0x9a06f105),LL(0x5f822a31,0x79179cd2)}, {LL(0xe3530605,0x570d3eeb),LL(0x4c7b03b0,0xbacb30c3),LL(0x0eea0cb4,0x0a8fe254),LL(0x2cdf203a,0xa052a555)}}, {{LL(0x9c34971b,0xee031587),LL(0xe76545cf,0x5829eb07),LL(0x33a81bb9,0xb7a3a6ae),LL(0x49c9f710,0xff42daff)}, {LL(0xbffb951b,0x894eae85),LL(0xce70f324,0x815fe3e2),LL(0x428b1f12,0x636564cb),LL(0xa029b0bd,0x722e0050)}}, {{LL(0xd373a65b,0xf45cb816),LL(0x6078d95e,0xf2210e00),LL(0x20d2924a,0xf767d7a6),LL(0x25b66987,0x06d6b552)}, {LL(0x790563a1,0x5c4a3999),LL(0x3c85510c,0xcea00a91),LL(0xd2db6297,0x7e37da9c),LL(0xf67303e8,0xfca4735f)}}, {{LL(0xaf76f475,0x324ca06e),LL(0x76391adb,0x3367845e),LL(0xa26fe169,0x222aa1ce),LL(0x7ede94c7,0xb15a8665)}, {LL(0x6b6a1f33,0x5b736342),LL(0x8562f392,0x25db61e1),LL(0xf2066206,0xfd4d720d),LL(0x82c555c3,0x26ef773f)}}, {{LL(0xfde6caa3,0xb6e35b3a),LL(0x87fabf4a,0x34eb5e13),LL(0x86236a62,0x4ad68635),LL(0x28510f8f,0x2651d3e6)}, {LL(0xe0873ba6,0x88073e34),LL(0x22f63746,0x3becce70),LL(0x7c08dac6,0xff8f9b61),LL(0x8c28aa65,0xc8b45a9c)}}, {{LL(0xd87b59dc,0xe09c063b),LL(0xcbbdd4ec,0xf3e4b9ef),LL(0x4855a43e,0x1b6b1793),LL(0x4ada74ac,0x594d5565)}, {LL(0xb410c5ef,0x10ee400f),LL(0x35695fe9,0xfc118113),LL(0x8f75d723,0x766cfe48),LL(0xff63aa76,0xc72023eb)}}, {{LL(0x9df9a165,0xc503a858),LL(0x851acc4b,0x9b1099ef),LL(0x66202ca0,0x9246c61a),LL(0x81390ccd,0xaba97788)}, {LL(0xba9e2785,0x3309fa65),LL(0x2220f385,0xbc0388be),LL(0x00ddc8ba,0x94c01a9e),LL(0xbccfdec8,0xaa54aed9)}}, {{LL(0x059fc0d6,0x1a959c58),LL(0xf518e1c1,0xd0f34c38),LL(0xb53be8fe,0x38aa2b1d),LL(0xacdc872f,0xd95a2a19)}, {LL(0xb4140bd6,0x97bde382),LL(0x4cfd5718,0x4084ba9d),LL(0xfd22450c,0xed016bfa),LL(0xa5d1f5bc,0xf00cdccf)}}, {{LL(0x111696ea,0x905114cc),LL(0x3a46e782,0x1f58a4d3),LL(0xa5e57fa0,0x899d1856),LL(0x68c45c2f,0x25186954)}, {LL(0xfa6e3eec,0x806deb4a),LL(0x65a063a6,0x3c358d48),LL(0x3feacdcd,0xce28ed1f),LL(0xaaa8e601,0xef9ee31c)}}, {{LL(0x87c1c66b,0xddd4fe3d),LL(0xb3dbfac5,0xfc2b063e),LL(0x20c81dc5,0x52d37cd0),LL(0x083b5f53,0xb628f163)}, {LL(0x7e42860b,0xd9295094),LL(0x307316ab,0xb877a744),LL(0x6b8d99b6,0xadec0d2d),LL(0x190bc675,0xa75183bd)}}, {{LL(0x4ad6bd44,0x2b1e0215),LL(0x9e020c66,0xda01ad52),LL(0x0c2913d9,0x65afd73d),LL(0xf0035373,0x67024b45)}, {LL(0x4d308206,0xf501bb4c),LL(0x77e2e936,0xfa020c88),LL(0x936476a3,0x662b72bd),LL(0xbae57d17,0x07f76845)}}, {{LL(0xf34ca404,0x77a43055),LL(0x4eebc853,0x8e403294),LL(0x402fde89,0xe19ee69a),LL(0xfe00df56,0x9092acd0)}, {LL(0xfb225f92,0x640c035c),LL(0xdce3aa84,0x92d94246),LL(0x971e9886,0x7fe8d3f9),LL(0x014b2a74,0xc569905e)}}, {{LL(0x7b7c299b,0xbafb8c4d),LL(0xd534cd21,0x3d289c60),LL(0xd311dee4,0x95e7032b),LL(0x6e8892a4,0xac0c46dd)}, {LL(0xe5bd6486,0x9fedef00),LL(0x99f703aa,0x3f4d8daa),LL(0xf0c0ecd2,0x78e47925),LL(0xfdac73de,0x8f143c2b)}}, {{LL(0xc14bd094,0x1f88f5a9),LL(0x99d9532b,0x6cc19e43),LL(0x639ba66c,0x6e474499),LL(0xf5d06b03,0x5d9a283b)}, {LL(0xaa25dbb5,0xc7e8164f),LL(0xf03faec8,0x7ab42a48),LL(0x647a0d72,0x4135765b),LL(0xe196b571,0x9562a676)}}, {{LL(0xa720cc20,0x62cc4c05),LL(0x13fa1ad2,0x9ed3f637),LL(0x7f59bac9,0xe5816f51),LL(0xb6884359,0x738e1544)}, {LL(0x34d0fb02,0x83bb2666),LL(0x8014c57b,0x0e582c6b),LL(0x145e2bff,0xbb4069ae),LL(0x4f5f1d7d,0xd1965cdf)}}, {{LL(0x3cead86d,0xaf77f98b),LL(0x0e51cbd8,0x0ba278bd),LL(0xac2ebb7c,0xf11f20f6),LL(0xc9992b55,0xafd2333f)}, {LL(0x322472b6,0x425dd0e4),LL(0x0958215e,0x0027a74a),LL(0x4cf7e0e4,0xddb301e7),LL(0xcbb70c2e,0xd0656ed5)}}, {{LL(0x0e7662e8,0xa40f629f),LL(0xe399a5ca,0xdaa85755),LL(0x7297010c,0x4c119aba),LL(0xe5df7140,0x4a4a6a43)}, {LL(0x474f7873,0x6d90d303),LL(0xd1f8f867,0xc5b0e19c),LL(0x4f6dc217,0x188bcae6),LL(0x6777357f,0x51ce999a)}}, {{LL(0x41aeb39f,0xdfc9578b),LL(0x7dd55c1f,0xeeda86fe),LL(0xfb814075,0xd4b8fc54),LL(0x33a1317c,0x12e32a78)}, {LL(0x2fd217d1,0xeb79cd2b),LL(0xdbd07638,0x5f5f20c0),LL(0x53dc7d8b,0xfc57643a),LL(0xf08350e2,0x65126014)}}, {{LL(0x871b0d3d,0x737ef5b4),LL(0xae3143a5,0x6b7e04ce),LL(0xb7ae12b9,0x0e5ab52e),LL(0xdb66ee0e,0x1a956daa)}, {LL(0xeaa7042e,0x59657e47),LL(0xbf84a2cf,0xbbc35318),LL(0x78679b8b,0xef55429c),LL(0x60cb7678,0xef92df9d)}}, {{LL(0x1dd267d6,0x17655580),LL(0xeb0bc1fa,0x00a3ec71),LL(0x50514840,0xafa0a256),LL(0xf161c685,0x68c28d0c)}, {LL(0xb1c766dc,0x069f7862),LL(0xd5ad4568,0x6868a463),LL(0x70e46d7d,0xf9c3d670),LL(0x6c875260,0xd2432cc9)}}, {{LL(0x088cecd9,0x534c3425),LL(0xb4e34c6c,0x3f1818e6),LL(0x028f153b,0x3aedf0a8),LL(0x50d9433a,0xe0a1cb9d)}, {LL(0xe523b764,0x9b4e225f),LL(0xe5f8542c,0xcba6cba9),LL(0xa8f6b81e,0x59c307e4),LL(0x01bb44fc,0x36abf4b7)}}, {{LL(0xdd62528c,0xf7692c14),LL(0xdf57773e,0x0d4a8341),LL(0xc9b4f968,0xece6957d),LL(0x52779586,0x82eda200)}, {LL(0x2f06ec6b,0xb902c488),LL(0x91a876f0,0x127dd7ba),LL(0x33ad0c13,0x06eb96d8),LL(0xfc5985ce,0xd7394080)}}, {{LL(0x661aaa4d,0x624c8f61),LL(0x6717a3e1,0x6fe10a11),LL(0x53168ad0,0x6c288c53),LL(0x8b52d037,0x91b8779b)}, {LL(0x1b5b0ab9,0x89e664d4),LL(0xf30d47d3,0x9f69b44f),LL(0x03176019,0xfe67cad5),LL(0xb346a205,0xb83efd48)}}, {{LL(0xaeea0c91,0x63fc4863),LL(0xdb56004b,0xbabf9042),LL(0xa9917def,0xdb19f2ee),LL(0x54c3fae1,0x1d12f2dc)}, {LL(0x55e36d40,0x7bb496af),LL(0x6be63b27,0x1f6c11f8),LL(0xcaf9a5b9,0x96d79804),LL(0x0648051c,0x03a085c4)}}, {{LL(0xb56baf4c,0x3b54c223),LL(0x559c1fc1,0x04af8c4c),LL(0xabd3cebb,0x05d55266),LL(0xf865e262,0xd2d3ae9b)}, {LL(0xedfedc54,0x3bd3ca3a),LL(0x922776c4,0x30a6ff1c),LL(0x1616a6f2,0xfecd8845),LL(0x94948d8c,0x4e7bc2e8)}}, {{LL(0xedca784b,0x16e0d824),LL(0x67ea1eea,0x84584f98),LL(0x8625626b,0xeceb1418),LL(0xc34fc1f3,0xa487cf9f)}, {LL(0xa57cec36,0x4ecfedd2),LL(0xd24a0709,0x08624865),LL(0x6a48f3ee,0x47bb1909),LL(0xc69bc041,0x54c5dd0c)}}, {{LL(0x7527166e,0x15a291e6),LL(0x4a9a8315,0x8a92370d),LL(0xda584bd6,0xe9fe705d),LL(0x3625a669,0xed441dc3)}, {LL(0x3063f2de,0xa57929ce),LL(0x6348cc31,0x2809fe4b),LL(0x04cc19c0,0x92041d54),LL(0xb62c1f94,0xd7c227fc)}}, {{LL(0xcd0d497c,0xecfeee53),LL(0x128818a8,0x8d1ea9fd),LL(0x2ae4725d,0xb5cf2c28),LL(0xc6abad3a,0x7de9f967)}, {LL(0xb14a183c,0xc64a11fc),LL(0xd5777d77,0x7f14d0fe),LL(0x12957444,0xbe79846c),LL(0x0e3257ca,0x4cf23abf)}}, {{LL(0x6e01b48e,0x8da0fd8d),LL(0x5ee87ca4,0x63a7ff16),LL(0x5cc96b94,0x90dff4d3),LL(0x406fc905,0xff1b41c3)}, {LL(0x3ac71c41,0xdd932925),LL(0xcf65e59d,0xec57f1b8),LL(0x3ce0512b,0xa3116d6f),LL(0xa2e28316,0x3b46fd3c)}}, {{LL(0x60156a5e,0x5a6c0314),LL(0x55d46fd0,0xfab3afe3),LL(0x9846f0db,0x4617926c),LL(0x121ef237,0xc2d5a447)}, {LL(0xf1cda3b1,0x789498d1),LL(0xccd64aac,0xa195cf03),LL(0x9440be2b,0xe8d1a162),LL(0x3ad5373e,0x7399890a)}}, {{LL(0x4fbf1899,0x65dcea2f),LL(0x44ee1a5a,0x44d9c8ab),LL(0x406880fb,0x2e94f8c8),LL(0x51faab7d,0x70732bad)}, {LL(0xf1e92b52,0xd69309dd),LL(0x3c7685d0,0x25f9a675),LL(0x1dbfbaa0,0x3604f30b),LL(0x2ff28c22,0x5ac0001b)}}, {{LL(0x52762d8d,0x648ec4fa),LL(0x0cef95f8,0x4fc248c6),LL(0xe5fbb57d,0xfc0f7030),LL(0x5ff2db51,0x2e644729)}, {LL(0x3775471c,0xd85877ec),LL(0x6076a271,0xe2580058),LL(0x09cb3873,0x58a4a24f),LL(0xb142da8c,0xb412928b)}}, {{LL(0x5997987a,0x1da7964b),LL(0x1825d97b,0x69765ff0),LL(0x4c97095c,0xde8ae407),LL(0xbb59316c,0xb257a968)}, {LL(0xcf2dfbd2,0x80e5240d),LL(0x1fccd0e7,0x2b3b04b0),LL(0x8ff1093e,0x949f1234),LL(0x65f62273,0xa4df3290)}}, {{LL(0xd0058ffa,0x305b7479),LL(0x180b0de6,0xe459ecff),LL(0x8ca0585f,0xfbe00c08),LL(0xc3dd4fa0,0xc169e23a)}, {LL(0x44026f6e,0x65d9009a),LL(0x1d96fe58,0xbbc258c3),LL(0x328ed1e0,0xd7ed379c),LL(0x23970884,0xe8b45744)}}, {{LL(0xed1095b5,0x2f44c8ce),LL(0xc59404aa,0x25725b0d),LL(0xa273e09f,0xea926278),LL(0x529143d5,0x102b120b)}, {LL(0x81174d10,0xbd2c012d),LL(0x4e8333ad,0x0bf5cf89),LL(0xb2f60645,0x6b93e3b0),LL(0xf38df3ce,0x040298b8)}}, {{LL(0xb89e18fd,0x6433b6fc),LL(0x6bd6af88,0x48d6584a),LL(0x0e1747a5,0x46c8a061),LL(0x1ed79faa,0xe225d3cd)}, {LL(0x5c28a48b,0x6c579abb),LL(0xda3889d6,0xc7a5ff4d),LL(0x008febdf,0x037ebc4b),LL(0xa7c5cbc9,0x03b60593)}}, {{LL(0xdcaa3319,0x0840804d),LL(0xb7481f45,0x38b0f084),LL(0x112e794e,0xfdb059c9),LL(0xe1afb614,0xb62bce05)}, {LL(0x53be7c02,0xc15035b6),LL(0x153ee8e5,0x66fc7106),LL(0x8258727f,0x27fd2ea4),LL(0xb470105e,0x8e012416)}}, {{LL(0xd7711aee,0x3d24685b),LL(0x021bab69,0x66a83c3b),LL(0x5501d69d,0x6e1112a7),LL(0x068b0504,0x2219fe0b)}, {LL(0xa926ab1b,0xaaa553c1),LL(0x56d6ca58,0x1c81af95),LL(0x221ef447,0x0a997380),LL(0xf5f55487,0x881a62fa)}}, {{LL(0x4f1b618a,0xf88fa0bd),LL(0xcbac98e8,0xb20e161c),LL(0x3bc6a7ad,0x443352b5),LL(0x0fd5748a,0xbc8e03ff)}, {LL(0x0ca427fc,0x64006aff),LL(0x7cbbda99,0x1a477593),LL(0x1a347c47,0x21ef1afd),LL(0xdee162b6,0xfe056287)}}, {{LL(0x797a0b14,0x9d4eb7da),LL(0x951c4bd0,0xe4e01a46),LL(0x7fe354a6,0xaf8fa17f),LL(0xc430b12b,0xd71f160c)}, {LL(0x83d46be0,0x5bb68437),LL(0x619bba86,0x99d10d82),LL(0xf4327042,0x95c2219d),LL(0x9c19ab57,0xdace2322)}}, {{LL(0xc8750fe7,0x88abbc67),LL(0xd3abe7d2,0x81ab300a),LL(0x45aa8948,0x62a6d8d5),LL(0x5d4ce8c3,0x76175bbd)}, {LL(0x8ea70976,0x095cb181),LL(0xf7e62a19,0x785de3fc),LL(0xed11a7fe,0xc478bce8),LL(0x1528aee2,0xb7e5993b)}}, {{LL(0x76c32e4b,0xb9ec58d7),LL(0x2dbc9a61,0xef815613),LL(0x5e07410d,0x372c3856),LL(0x033276d0,0xa1b16510)}, {LL(0x82640d26,0xd8589581),LL(0x9053fff0,0x1cb98180),LL(0xc1ff11f1,0x41519ce7),LL(0x666431e4,0x2f21a48f)}}, {{LL(0xe83ee840,0x2c223ed1),LL(0x1e7cf4dc,0x833ae708),LL(0xacd13385,0xec8853d8),LL(0x6a7a8cb1,0x559115ab)}, {LL(0xeb184e71,0xe2f4ab2a),LL(0xc10194df,0x679abbce),LL(0x3aca0828,0x10199c84),LL(0x978cc1d6,0x7474e113)}}, {{LL(0x44e8eb9a,0xa4460ef1),LL(0x828aa4bf,0x4cde5260),LL(0x249bff50,0xd3d23790),LL(0x6bc7fbbc,0x2e6660da)}, {LL(0x61494df0,0x3e3cc146),LL(0x0bcda8ba,0x6e9a1571),LL(0x096e00b7,0x68ce233e),LL(0x5106c85b,0x247a5c49)}}, {{LL(0x55fc5757,0xe6f0cb5c),LL(0xb7585799,0x452682b9),LL(0x869e747e,0x84509dfe),LL(0x8d23be04,0x904366e5)}, {LL(0xb0f72c6d,0x7324a14d),LL(0x1913a9ff,0x9fbe3116),LL(0x428a6b5d,0x2f9fa62a),LL(0xf8a34d9e,0x8039270f)}}, {{LL(0x407aec78,0x0e3ce7ae),LL(0x826458cd,0x4d935d3d),LL(0xfc6f46d4,0xf75db7db),LL(0x88586874,0x3ab7ba68)}, {LL(0x9a198b50,0xec92749f),LL(0xefc51cdb,0x0ffc7681),LL(0xe17bc0e3,0x951406d5),LL(0xc898a018,0x39cd2d07)}}, {{LL(0xf2f79af6,0x9dc3803c),LL(0x0a56cd68,0x292f3164),LL(0xf6fbdbdf,0xdcac21f9),LL(0x23e9e959,0x6f9ce2a4)}, {LL(0x970f6c34,0x2011d221),LL(0x9e2decfb,0xd2e63711),LL(0x118ff327,0x19c7a489),LL(0xbb6e534e,0xe19d7e83)}}, {{LL(0xbd1a426b,0xc685389a),LL(0x8c679952,0x432ff7b0),LL(0xc5e2687f,0x516cbdfa),LL(0xba1eac8f,0x8242405d)}, {LL(0x0b09854e,0x63af3152),LL(0x231ec979,0xcecd0faa),LL(0x7273f0b2,0x4746733f),LL(0x8f001365,0x69b28d87)}}, {{LL(0xc6f2623c,0x0d87d506),LL(0x86c40ed2,0xd209a9c6),LL(0x0fa20f3b,0xa5b7fde2),LL(0x4f5b2129,0x54550dc5)}, {LL(0xfeddaa1b,0x36884047),LL(0xd899a29f,0x51398fa0),LL(0xcdf11867,0x14a416be),LL(0x3e466b62,0x86351ac6)}}, {{LL(0x39bb481a,0xd63e91e1),LL(0x99984155,0xdcdc072a),LL(0xd2d8e622,0x9fce6e38),LL(0x8e8c8034,0xbf6978b6)}, {LL(0x8c37990a,0xaa1ae874),LL(0x0e749b86,0xd1f0e068),LL(0xcbdc7c12,0x5aa303b1),LL(0xc9130211,0x9a78baaf)}}, }, /* digit=21 base_pwr=2^147 */ { {{LL(0xb3e2087b,0x5eeba910),LL(0x44a61a33,0xbd016dd3),LL(0x48cd5c0f,0xffd1f081),LL(0x2e6a8e94,0x041c6aa0)}, {LL(0xc4ac3d91,0xe09c35c5),LL(0x634767a4,0x58298105),LL(0x1040c2b5,0x6120e7cb),LL(0xa713589f,0x32a661ef)}}, {{LL(0xbd74c70e,0x5a056a90),LL(0x8af672f3,0x44f7d00d),LL(0xef4e9a48,0xdc25ab68),LL(0xfdfb1069,0xadd15cc3)}, {LL(0x9f3033bf,0xb1f4fd28),LL(0xebb8b8a7,0x088a49bb),LL(0xa8d2861c,0xea485869),LL(0x6b977fb5,0x46dbfdaf)}}, {{LL(0xd88ae888,0x04e6461e),LL(0x9be2d7ad,0x112d204a),LL(0xdb558427,0x952dc813),LL(0x27e35200,0x39b01652)}, {LL(0xff02cdbb,0x8b89bfce),LL(0x3e854e4c,0x1381a99b),LL(0x999efd2b,0x68185218),LL(0x86dc62e1,0xeb41e1bb)}}, {{LL(0x02d0aaff,0xa264ef40),LL(0x6e679fe2,0xa678c07d),LL(0xfd88bdce,0xcff13be7),LL(0x617badb8,0x9a8efe8d)}, {LL(0xad5a22f4,0x1388a815),LL(0xfec398b3,0x8f821400),LL(0xff4fc2da,0x85a6a565),LL(0x858dd4f3,0x681f0181)}}, {{LL(0x91ee75bc,0xdc870745),LL(0x64f20e50,0xbadbf940),LL(0x49d3d417,0xf3ea437f),LL(0xc02109d0,0x7bebd868)}, {LL(0xd16bb240,0xe6c8d93c),LL(0xfdab9bbd,0x2087141a),LL(0x20a3b470,0x8dba80ff),LL(0x29d3a8d7,0x960a0c7b)}}, {{LL(0xf8ec1151,0xae61b637),LL(0xaadc8545,0x415dd36b),LL(0x69d0985a,0xed21d176),LL(0x97893f50,0xc4d062af)}, {LL(0x337b81f9,0x4d93ba1a),LL(0xb7c163a2,0xb995fe9e),LL(0x5416e4ed,0x447eff3b),LL(0x0bf4a8e7,0xd7660300)}}, {{LL(0x56d9e00f,0x9e14c6a2),LL(0xfa1f60e0,0xa228491c),LL(0x8782a9be,0xd540713e),LL(0xdcd55e21,0x5d3fcce8)}, {LL(0x35c87b90,0xa176c34e),LL(0xf9508f35,0xc1d80aa1),LL(0x92302d47,0x14f7e7fc),LL(0x2b076e72,0x459372ba)}}, {{LL(0x4e933b19,0x44168fbc),LL(0xe54ea969,0xaf2db74c),LL(0xaeacbb56,0x36fade13),LL(0x84e6cd1d,0x29708665)}, {LL(0xb692df97,0x6f7ff1e1),LL(0x6ae66307,0x5a68c1a2),LL(0xe7685f20,0x85bc544c),LL(0x0f65eeec,0xb3f42e6d)}}, {{LL(0x5b91b644,0xef209f44),LL(0x50cb02b6,0x808b930a),LL(0x099f684f,0xc5da5e86),LL(0x4330c2d8,0xd8f1dbcc)}, {LL(0xd8608776,0x52e8cab5),LL(0x16e56f5d,0x13c89771),LL(0xb135282b,0x7d7d802a),LL(0xe9be8a20,0x69762c39)}}, {{LL(0x2a08a1dc,0x13f6bbad),LL(0x7f2dba7a,0xa7131e4a),LL(0x7864f5a3,0x751dce48),LL(0x08135109,0xc5af1b45)}, {LL(0x4f08636e,0x3c4d75f7),LL(0x2e251e48,0x9949b2f5),LL(0x9bd98853,0xd0497977),LL(0x909b0e84,0x09d8e627)}}, {{LL(0x4ceff1c9,0x505753ee),LL(0x460710ca,0x03ca4571),LL(0x5480abc0,0x0cf72dee),LL(0xc19c8ef3,0x55d5a30e)}, {LL(0x86541f6f,0x9e47641b),LL(0x10c9d6fb,0x89b2e48f),LL(0x0860915c,0x9d16382b),LL(0xf54b337f,0x770ac417)}}, {{LL(0x77ef7f67,0x366d0781),LL(0x2b6340c9,0xfefec947),LL(0x097acf63,0x7ce3a056),LL(0xaf306dec,0x26538c7c)}, {LL(0x287dc8d1,0x8a8bb55e),LL(0x448823ae,0x9431095b),LL(0x7970fc51,0x8358087a),LL(0x413509ac,0x95299959)}}, {{LL(0x8b0911d4,0xb165f92a),LL(0xbfb37459,0xdde855ee),LL(0x3d9ce36e,0xe672eed4),LL(0x74bae261,0xf7da91e5)}, {LL(0xb741c8e6,0x1f67323c),LL(0xc92c91ce,0x8efd4661),LL(0x78e73c42,0x556f0b1a),LL(0x16101f96,0x7d326b7f)}}, {{LL(0xfb48bd3a,0x8814ef0b),LL(0xc508309e,0x1bbbe13e),LL(0x67709c10,0x7ddaf061),LL(0x6436f655,0x82b67847)}, {LL(0x03712e64,0x2a5601c6),LL(0x3e3f9b2e,0xac1f0362),LL(0x09184b5d,0xcc7e6a09),LL(0xb4625149,0x1258b265)}}, {{LL(0x384a6b54,0xd9f21461),LL(0x6cfe9311,0xde483161),LL(0x889f43cc,0x593dae45),LL(0xedee221b,0x8454335b)}, {LL(0x3a2cbced,0x90f3fb43),LL(0xcc8dcb75,0x895ed692),LL(0x14233aa7,0x9857d719),LL(0x48166d5f,0x91b1a2ab)}}, {{LL(0x675b47a0,0xfbf7033a),LL(0x6542378f,0xcb3669c4),LL(0x125ec248,0x96abb0f7),LL(0x795fc346,0x6d5d2047)}, {LL(0x8f5cffb6,0xa6c6c9e8),LL(0xbea5ee09,0xb968f2c7),LL(0x844ffd6f,0x2f2ce735),LL(0x27e40ac8,0x7931b877)}}, {{LL(0x2b63d538,0xe1f62dcf),LL(0xf44d7bf9,0x395681dd),LL(0x54aec359,0xf02eedf7),LL(0xa0ad5eb7,0xc64b6233)}, {LL(0x346b086a,0xc65093c7),LL(0xe957b243,0xfcf8ecc9),LL(0x1ca48020,0xe1accffa),LL(0x4047bbeb,0xe1f29792)}}, {{LL(0x9fc6be25,0xb1097d40),LL(0x923eb7b4,0x02d33d19),LL(0x1f58f545,0x9e25200c),LL(0xda51efcb,0x2ffae306)}, {LL(0xc0b011f2,0x7e6d76c1),LL(0xf680676b,0xedbd8398),LL(0x8d7fc8c2,0x38517fc2),LL(0x5c3ab05c,0x55a7fcf9)}}, {{LL(0x8e6dd02d,0x047e2422),LL(0x1f290d6a,0x7b3bf0e6),LL(0x6a99a6d0,0xbcf326fc),LL(0x2eef8232,0x1e3f38fa)}, {LL(0x15bac529,0x9890780e),LL(0x9f143ba0,0x94202e0e),LL(0x885e4ed5,0xbd574712),LL(0x396f938d,0x2404c223)}}, {{LL(0xacde8286,0xd54d401c),LL(0xe7af01fd,0x80397794),LL(0xf615a8eb,0x94457d07),LL(0xd22d9ef7,0x34680480)}, {LL(0x2c489ccf,0x04d4b302),LL(0xc3673dae,0x11dea4bd),LL(0x58cdfe41,0x8fbb4df5),LL(0x0f10a70e,0x49425184)}}, {{LL(0x077a59ce,0x831b977a),LL(0x894627f3,0xee08fb0c),LL(0x2f8553f0,0x21360507),LL(0x0487171b,0xca77ccd1)}, {LL(0x07e11059,0xc17d20c2),LL(0xbe613256,0xcf74be6b),LL(0xa5fe18c1,0x06f185e6),LL(0x2b57ce3e,0x8d2cf4f5)}}, {{LL(0xc9c983e7,0x7179273c),LL(0x153f58d8,0xc7d27357),LL(0x4f400bd4,0xc0273069),LL(0x26262553,0x23309c7f)}, {LL(0x712d0314,0xf26b6e11),LL(0xf96ee39a,0xb925cebf),LL(0x73944251,0x6df57108),LL(0x589d90aa,0x95419b24)}}, {{LL(0x796a8ee2,0x57a1bcc5),LL(0x2acee09d,0x22a22530),LL(0x66fa2911,0xa4c2cc03),LL(0xd85f13dc,0x9cc2b7fa)}, {LL(0xce152790,0xf2498b8a),LL(0x1caf39d1,0xd8406007),LL(0x84c0822f,0x7ff50064),LL(0x155f1280,0xaf14ca4b)}}, {{LL(0x89b781c2,0x113f094b),LL(0x013833a5,0x996bf893),LL(0xc0b9cf6d,0x26bc6210),LL(0x6a88f1cf,0x18e2d3ac)}, {LL(0xa21a2d35,0xc0ff2b3c),LL(0xa79e918e,0x409c2598),LL(0xb6917e22,0xffcf65a0),LL(0xbb4f8f3c,0x8036897f)}}, {{LL(0x9ec27fd7,0xac660365),LL(0x0c56cbb1,0x3c5ca1a9),LL(0xbe9e9ec7,0x01c5dce1),LL(0x386edb4a,0xdc21b01a)}, {LL(0x4b1dde01,0x47e02a92),LL(0x44af3e0b,0x0613b7ca),LL(0x1c445b6f,0x644ac708),LL(0x87243e2a,0xb5566f0f)}}, {{LL(0xba9f354a,0x5b244172),LL(0xeb653a5e,0xaca4e9d3),LL(0x514809f2,0x6ff6904a),LL(0x96595230,0xf87a329b)}, {LL(0x8d4bd051,0x39ebe6eb),LL(0x07d17d59,0x66f05f5c),LL(0xe0f81731,0xfa1ee673),LL(0xd12804a9,0xf41c1042)}}, {{LL(0xacd14cf5,0x1c4a655a),LL(0xef47548f,0xdc72f5bc),LL(0x0b3ee6c7,0xab07ceff),LL(0xbb501a28,0xcfa88319)}, {LL(0xd8f03f7c,0xcec9c2e2),LL(0xe0c98d62,0x3098d752),LL(0x0a8681b3,0xa41a0794),LL(0x23587932,0x0e588076)}}, {{LL(0x5ef86f7c,0x4617dc66),LL(0xcedb5377,0x51de8430),LL(0x737381b6,0x0dda704a),LL(0x008f4671,0x83a44653)}, {LL(0x38401c11,0x71bbb73e),LL(0x4894d378,0x879fe49c),LL(0xeab186a2,0x8875eef9),LL(0x12a382a9,0xedefe278)}}, {{LL(0x13b897fd,0x95ef41b8),LL(0x2a98ddd9,0xfefd495f),LL(0x680b12e8,0x09cbccfc),LL(0x167da5dc,0xc1888a21)}, {LL(0x3bb290b4,0x2a204912),LL(0xd9613190,0xdcac95fc),LL(0x709c76f7,0x4df94f62),LL(0xa5cea926,0xc8c3a8ab)}}, {{LL(0x37a2b813,0x15c876b2),LL(0x9c3c821c,0x9b52803e),LL(0xcb3d6ff1,0x40f2268c),LL(0xa1573601,0x689f1696)}, {LL(0x8e921f56,0x8d7566dd),LL(0xd992335a,0x5d8a990c),LL(0x20dc4f4b,0x6339153a),LL(0xdc5d06ab,0x0b07419c)}}, {{LL(0x97c201f9,0xe9cc014d),LL(0xa635f472,0xec04a52e),LL(0xa538a84f,0x6aac504a),LL(0x5762fe7c,0x4d0288e3)}, {LL(0x34cbd09a,0xaa8539f0),LL(0x2619bcf7,0x6f7e0e94),LL(0x0dd338d0,0x178303dd),LL(0x8326f40e,0x6b58c2b1)}}, {{LL(0xfe73e699,0x98bb15ec),LL(0x47526489,0x7533abdc),LL(0x491dcc6d,0x4b269607),LL(0x77187363,0x325ec2a0)}, {LL(0x7e9ab865,0x766faa19),LL(0xc25a9448,0x1c105b4a),LL(0x0531b5ba,0x0b6b8963),LL(0x2db1a579,0x32691f11)}}, {{LL(0x643e479c,0x24d90a57),LL(0xb98578df,0x048b27cb),LL(0xe53bed53,0x0600f93f),LL(0x0aac585f,0x1fd57dfc)}, {LL(0x71d0e4e0,0xc3d72121),LL(0xf612fc4e,0x5ff10dfb),LL(0xb5a7ec79,0x9edf4b23),LL(0xd87706ab,0x975165c7)}}, {{LL(0x7095c3c4,0x8b99db04),LL(0x897faf50,0x65196441),LL(0xdd5b64cb,0x5d23d7d9),LL(0xe95fe601,0xec734b06)}, {LL(0x0b5fcde9,0x03a5f53f),LL(0xebe35310,0x0186ad22),LL(0x84846603,0xe9a65eef),LL(0xa7c6e5be,0xe99e5188)}}, {{LL(0xf0887da6,0xa917327d),LL(0xe3f9fa70,0x49965f78),LL(0x4f10b31d,0x02ed227d),LL(0xb6120be5,0x535b4386)}, {LL(0xcc1bf98a,0xdff21a8a),LL(0xeb1634bc,0x5b52a09a),LL(0xa3f61fa2,0x60f8690d),LL(0xb863c790,0x58a02566)}}, {{LL(0x5c6b2929,0xf9b90a9e),LL(0x22fca36e,0xd552e84c),LL(0x9eabcb58,0x6b23da4f),LL(0x5d4136dc,0x01111d07)}, {LL(0xb3642a09,0xfaa80059),LL(0x5f49d533,0x1de667f4),LL(0x17525176,0xb3268776),LL(0xda729fde,0x75b0b102)}}, {{LL(0x6e9fe6ed,0x4ec7f678),LL(0x2717f8b0,0x28d29578),LL(0xd4cc149f,0x6a713c37),LL(0x7dfdf8c6,0x4804e04f)}, {LL(0x5c931aa6,0xe7c6daab),LL(0xa0394f29,0x793e411d),LL(0x79ed9819,0xc0741c0d),LL(0x24d5d992,0x3f2ba70b)}}, {{LL(0xca9c987a,0xa61dc03f),LL(0xe64b50c1,0x78201cb8),LL(0x1861f4e4,0x45a23c25),LL(0xc4ee5d82,0x10f19f4f)}, {LL(0xf3f055f4,0xf1520547),LL(0x006ccf49,0x69ae26b3),LL(0x33d8d4ad,0xe96eec0b),LL(0x48a4fc2c,0x00765f0c)}}, {{LL(0xa3976c07,0xad47e14e),LL(0xd905b6b4,0x82b1f882),LL(0x91382bac,0x7a1b9d73),LL(0x18178290,0xcc84a820)}, {LL(0xb4e845ab,0x1123c6f6),LL(0xb92e3b08,0x63216635),LL(0x183879fb,0x748be745),LL(0xa73e9ada,0x7f20e1f0)}}, {{LL(0x9224c152,0x05de3e11),LL(0xea8fda4e,0x2fa9a474),LL(0xf48055ec,0xf5c8df05),LL(0x9e23a599,0x48bbf43a)}, {LL(0x148086db,0xf593f034),LL(0xef0a2b62,0x0173a87a),LL(0x3fbabb6f,0x90ef0132),LL(0x21ade107,0x56ced09a)}}, {{LL(0x73f1d3e0,0xcf1ce892),LL(0x22424580,0x765236c6),LL(0xd939d063,0x0d223937),LL(0x7cb2fe2f,0x9a21beda)}, {LL(0x1ce3a7fc,0xa559a571),LL(0x1b060dd5,0x7fd6b255),LL(0xc5afdf1a,0x4dfbd210),LL(0x1239368a,0xa74751ce)}}, {{LL(0x6d9a3eec,0x93acdd06),LL(0x9832dcfd,0x7d97f794),LL(0x0cc645ca,0xdafa9a44),LL(0xcfee0817,0x1da27ddf)}, {LL(0x01b8dd49,0x0c1e6319),LL(0xd91aeace,0x8267e508),LL(0x87f43f20,0x86a2cedc),LL(0x07db2f24,0x7dd0e670)}}, {{LL(0x9db25177,0x8ea1e973),LL(0xab8802df,0x659cccb8),LL(0x004940ab,0x2bd39c65),LL(0xd9419db5,0x57676876)}, {LL(0x6d6f237c,0xd52058a3),LL(0xfb4a9a7b,0xd9812dcd),LL(0x53bec56e,0x879890d1),LL(0x7ac5d9d9,0x17b7f151)}}, {{LL(0x1ec6db6c,0x2db3f5df),LL(0xafdf29b0,0xe9a3b18f),LL(0xe63a9ae9,0xda633d62),LL(0x38d13c8c,0x0922b16d)}, {LL(0x7462c8e6,0xaeb7e270),LL(0xa01b6984,0xa98c96d8),LL(0x297c242f,0x5586e0d3),LL(0xff587596,0xbeddd1ab)}}, {{LL(0xc02ea084,0x79ac33ce),LL(0x8e02ae2f,0xe7d06753),LL(0x94d526b8,0x05fffd7d),LL(0x5ebc46d0,0x4590d655)}, {LL(0x855f85e6,0xfb79c066),LL(0x7400ed08,0xbb3f0a6d),LL(0x67fb3683,0x46f4c3cd),LL(0xd19804cf,0x62fc1931)}}, {{LL(0xd1b6f356,0x0480e772),LL(0x56320242,0xa5810f25),LL(0x64073c03,0x6cf6c9c3),LL(0x46a6bfbc,0x7dfe137b)}, {LL(0xba59baf8,0xa5633fa0),LL(0x5fd4929a,0xb703e5db),LL(0xd7515518,0x09eef835),LL(0xa0e3b067,0x2e596aa8)}}, {{LL(0x8649bb99,0x793831fc),LL(0x5ba4c1b6,0x91cb0057),LL(0x270ec9e8,0x44e93dbd),LL(0xd139d219,0xbf2ed01a)}, {LL(0xc9d68198,0x39697e05),LL(0xde2b6894,0xf04439cf),LL(0x1e6b8e6d,0x65b7a04a),LL(0xce35ae6d,0xce3e9425)}}, {{LL(0x9f102fb3,0x041e0aff),LL(0x106ae748,0x91b3a87c),LL(0xc426fa5d,0xfd969804),LL(0x28f95b76,0xe624f1cd)}, {LL(0x34f2ea56,0x6fe28cce),LL(0xd230f37c,0xdea55947),LL(0xf92f2742,0xd5e336f2),LL(0x1899c751,0x86852e3c)}}, {{LL(0xa5d1bd04,0x5ef2a63b),LL(0xb6ca2b79,0x5f4721a2),LL(0x9f484f78,0xbdb27b7c),LL(0xb085b4ed,0x2b07bf5b)}, {LL(0x501b62ab,0x96b8ae73),LL(0x3ba64e23,0x0b1e003a),LL(0x93024347,0x43f9ec00),LL(0xae180a03,0x3c8c0c7e)}}, {{LL(0x8c0b21d4,0x58c72237),LL(0x2b15a1fa,0x9d51a996),LL(0xec755eda,0xf5201743),LL(0x933800fb,0x0c845fa3)}, {LL(0x0e82418e,0xb6b66cdb),LL(0x3ae3eeb7,0x875258e5),LL(0x1a8f2b3e,0xf2c30b1e),LL(0x250f3328,0xa10b3843)}}, {{LL(0xc47c53f8,0x9f449967),LL(0x8775e16e,0x5dfe8c76),LL(0x336f2194,0xb02813a1),LL(0x5636498b,0x90ad3ad5)}, {LL(0xc7c647e0,0x095acf96),LL(0x1f57c069,0xc90ef12b),LL(0x1fb85cc1,0x52f51878),LL(0x25a125ad,0x582cfd67)}}, {{LL(0x0d43ffad,0x53b4bfc7),LL(0x04dcf047,0x143b0b48),LL(0xd4500bf4,0x65d16216),LL(0x9ab1e4cd,0x960c7910)}, {LL(0xe1d08c70,0x38b7ef7e),LL(0x9806e01e,0x64ae69e1),LL(0x6796b923,0x07468184),LL(0x70af1e64,0x6480887a)}}, {{LL(0x02384b34,0x4eb2d6fb),LL(0x05be47f3,0xb29337a8),LL(0x6b744f9d,0xfec96fc0),LL(0xc8c9afc3,0xc3de2fb0)}, {LL(0xcc6dd0a5,0xe8ccc3eb),LL(0x71d7de7a,0x0329a9b9),LL(0xe357c4f9,0x459fbc8c),LL(0x025fdc97,0x80287f50)}}, {{LL(0xa089583d,0xedf1b0aa),LL(0xfb08add3,0xb1ad1a57),LL(0xe1ae76c1,0xd6826d03),LL(0x541462c8,0x3070cd2e)}, {LL(0x83e6f4da,0x7b03c859),LL(0x24bdb487,0x5b39a809),LL(0x453bebb7,0x70017570),LL(0xb8ebbfc6,0xfe4e6206)}}, {{LL(0x106defe3,0xbb8a1899),LL(0x8683287a,0x6f23dc7a),LL(0x65d96aed,0x2cf01995),LL(0xdda4ea18,0x4e4cf7e9)}, {LL(0xd2d0316b,0x72ad201f),LL(0x61de6cd4,0xd6451150),LL(0xc84856be,0x12432dbf),LL(0xd2a8378a,0xdd4dca98)}}, {{LL(0xbf881f9e,0xe70af958),LL(0xc4e58ec4,0xd4cd35ad),LL(0x5a531924,0x3889d3d9),LL(0xb4ce15ec,0xac657424)}, {LL(0xf41e1344,0xdbe384ca),LL(0x5ab8bb08,0x9a1aed23),LL(0x8561df1d,0x375a041f),LL(0xb7685c1c,0x19f7a238)}}, {{LL(0xa4ba6317,0x8ba59933),LL(0x271f4aa0,0x0c44b6df),LL(0xbd64e922,0x51f4e88f),LL(0x9095769f,0x7279df94)}, {LL(0xeaf8c8d3,0x098c17b6),LL(0x1aa841d1,0xe602ff2c),LL(0x8b63ce81,0xbe4e4926),LL(0xfcc79573,0x85de277a)}}, {{LL(0x5b8304db,0x38253d40),LL(0xe422af76,0x58c50c3b),LL(0xbf95c27a,0x7f7ec0d1),LL(0x6041df33,0xcb7c3a8c)}, {LL(0x35364c89,0xc55595c0),LL(0x2a6eb1e6,0xd1a72aa7),LL(0xdeb98a3d,0x1fa941de),LL(0xeff46690,0x1e9607ab)}}, {{LL(0xad46a05a,0x6633e398),LL(0xb585e241,0xb99e5784),LL(0xea558424,0xd63106a4),LL(0x5df0e501,0xf0a5f939)}, {LL(0x59dacce3,0xba17aaef),LL(0xe907c457,0x03dc5a07),LL(0xa9800bc3,0xa59f6d63),LL(0x364e1ef7,0x294a3827)}}, {{LL(0xdd191356,0x741bbab9),LL(0xc43954a4,0xe8fe9161),LL(0x65341d90,0x6a711fa9),LL(0xadef2d82,0x09bd0faa)}, {LL(0x21ffc303,0x2112f27e),LL(0x395b69e2,0xcd2214dd),LL(0x8670b06f,0xe4b503c9),LL(0xc4e13ef4,0x219a678a)}}, {{LL(0x4a993816,0xc4020eff),LL(0x1bac14d5,0x00a9f5de),LL(0xeba7c3a4,0xd00fce1f),LL(0x14b537ab,0x2c6d4993)}, {LL(0x6b898739,0xe9b2b540),LL(0x29dbf826,0xae53e6e3),LL(0xc8438b2c,0x634606c7),LL(0xfabfd429,0x268a9ee4)}}, {{LL(0x173b5583,0xb0486aae),LL(0xbf222673,0xf88a2f80),LL(0x0b3178c8,0x49c56f76),LL(0xd77d1406,0xeab47059)}, {LL(0x993b1a7a,0x95035846),LL(0xa9b83efa,0xd6446e94),LL(0xc4424fa8,0x1d1a71ce),LL(0x3d08b8d2,0x8d814c4d)}}, {{LL(0x7b9374ac,0xbc3ed8d2),LL(0x77a3c020,0x8dd2d56d),LL(0x97efca8d,0x93ada735),LL(0x37974cd3,0x072bb2d0)}, {LL(0x7bd74e40,0xa7c86e7e),LL(0x5b52e0ed,0x7bff5613),LL(0x053af1f1,0xc8d0bb30),LL(0x840bcb7d,0xc5bdb8f9)}}, {{LL(0x41690d1c,0xabdf5f73),LL(0xf0edac8c,0x0e857a78),LL(0x8238cfb0,0x59f40fcf),LL(0x511d41d2,0xdcb54f67)}, {LL(0x0e645117,0x3f036ac8),LL(0x7af5fdcc,0xdc4e833e),LL(0x3d7bab2c,0x67d859b2),LL(0x5f8b32bd,0x92489b23)}}, }, /* digit=22 base_pwr=2^154 */ { {{LL(0xb9e2f9f8,0xe412aaf7),LL(0x0ff419ac,0x0484c1aa),LL(0x417bcb90,0x9d944989),LL(0xfe7318ca,0x2b73dbe3)}, {LL(0x52dd7b0a,0xb91b71e5),LL(0x3954afeb,0xd61f8eea),LL(0xa07e3958,0xaaeab13c),LL(0x02a1ff49,0xde442032)}}, {{LL(0x0b054a0f,0x8292d96d),LL(0x74b9077a,0xa978af88),LL(0xfff1d49f,0x70bd185b),LL(0x0279eab1,0xbe6d0844)}, {LL(0xb8ed07e9,0xa8fffe45),LL(0xcb920e55,0x714824a1),LL(0xaf1bb143,0xcd5c628a),LL(0x7637dbb7,0xd151afcd)}}, {{LL(0x62d7ee7c,0x83fb0f37),LL(0x9a3bcb7e,0x58c2282f),LL(0xeac2ca5a,0x79f77476),LL(0x579a262b,0x7e80c351)}, {LL(0xedb4f0fc,0x19e67272),LL(0x1fbbe9fe,0xe142bb31),LL(0x95ea6cc1,0x5c7d7cce),LL(0xabfdcf7f,0x6465a380)}}, {{LL(0x5a26a1d4,0xa433bd2e),LL(0xd1c2d78c,0x1148bb1d),LL(0x64102515,0x4aae419e),LL(0x66489384,0xd03b9939)}, {LL(0xd61a9919,0xe21d58b1),LL(0x4a0ef3d4,0x17618c36),LL(0x6fe8c0dd,0x2519020d),LL(0x00b87a75,0x48d837d6)}}, {{LL(0x426c1aa6,0xe6e067ab),LL(0xb11d1280,0x431579d2),LL(0x2ead6552,0xb926943f),LL(0x057fed1f,0x8fd692bf)}, {LL(0xe9a98fae,0xed11c0ed),LL(0x9bcb2abd,0xe2bc967a),LL(0x68729b8e,0x1b388d66),LL(0x6f74563d,0x2144d67c)}}, {{LL(0x03fcd3bf,0xbe519757),LL(0xc8c7b62f,0x3f9dbd8d),LL(0xfc476e0e,0xce91fce6),LL(0x2715393a,0x2f140c73)}, {LL(0xf11da35b,0x8a149a94),LL(0x5367030d,0xf6a2be5e),LL(0x0269def3,0xb68c0d82),LL(0x8eecb775,0x32d58819)}}, {{LL(0x32845ab0,0xccea6f53),LL(0x2541c834,0x792bc041),LL(0xb1336aa7,0xd726425f),LL(0x3ddd6256,0x85b1d21e)}, {LL(0xd9b1ba0b,0xd575bfa8),LL(0xb778b77a,0xd23084e2),LL(0x44bb1010,0xd44e7399),LL(0xa91623fc,0x3d665388)}}, {{LL(0x3f11fc00,0x5cfd3a69),LL(0x8bc8eade,0x1f2b5d01),LL(0xa6b9f7ae,0x5160359b),LL(0xfa696463,0x1e2601dc)}, {LL(0x915f6084,0x7f5ac6d2),LL(0x679176d5,0x6e387789),LL(0xae26abee,0x7fb99f4b),LL(0xaa409d22,0x4798a2fc)}}, {{LL(0x5965615c,0x582164f7),LL(0x0472cbeb,0x2c9dfb60),LL(0x2266724f,0x36eacc3f),LL(0x5fcb8868,0x253eb08c)}, {LL(0x760c15b3,0x749a0577),LL(0x5686b036,0x71e4ce1e),LL(0xb710196a,0x47893a8f),LL(0xdf51c4e8,0xe27dfbac)}}, {{LL(0xffb3df08,0xc9536d6b),LL(0x6dde9e09,0xc95169ce),LL(0xcc085766,0xcb050de7),LL(0x0df088dc,0x92fce77e)}, {LL(0x88781592,0x10c124ca),LL(0xc81030f3,0x6429d30b),LL(0x09e20c50,0x2e37721d),LL(0xf3e3d604,0x43e7f9ca)}}, {{LL(0x5b095e01,0xa277a87e),LL(0x83a51a95,0x968bc951),LL(0x53aff355,0x3b375d45),LL(0xe1ebac06,0xb79d7cce)}, {LL(0x022995b4,0xd929e1a6),LL(0x28164ff7,0x228cf7f4),LL(0x5d3e4608,0x7bd12900),LL(0x2f97ebd8,0xc57ac873)}}, {{LL(0x86b383b5,0xc192342d),LL(0x706b01d5,0xe85f303f),LL(0x88cdcb89,0x19e19213),LL(0x2ce0de2a,0xe88f1943)}, {LL(0xe453aecc,0xf6fcf8cf),LL(0x9a67b49f,0x0dcd10b8),LL(0xafece961,0xb93d5b4d),LL(0xc39d0b53,0xe232f34a)}}, {{LL(0x30735384,0x1b8f6cc3),LL(0xe4f26c08,0xc35c5a82),LL(0xba98f626,0x9e0c933b),LL(0x4c70aed7,0x49868100)}, {LL(0xb7f26c66,0x711a3aad),LL(0x7dac506b,0x786ea28d),LL(0x43935657,0xd3a7ab1e),LL(0xd1b69e9e,0xda7f5c1f)}}, {{LL(0x0e6c8579,0xc08c85e5),LL(0x8d991759,0x29d04ad4),LL(0x3a8ccd69,0xbae8f163),LL(0x1790a49c,0xade66539)}, {LL(0x45915cc1,0xf9f5bc8c),LL(0x4f2b18c3,0x63461cf0),LL(0xd236e848,0xceb75a9c),LL(0x847ce6c2,0xac653e3b)}}, {{LL(0xdb088764,0xb93b3032),LL(0xa78e5943,0x567fe1c3),LL(0xe359cb34,0xba7a7acf),LL(0xe2c3827e,0x38f4fbfd)}, {LL(0xc90abad2,0x761c36d4),LL(0x75027c02,0xac1af4e7),LL(0xd4715572,0x95e6d01c),LL(0xd621145d,0x5b06cf39)}}, {{LL(0x64ca2efc,0x799acd7c),LL(0x4e0bcb6c,0x3397a15b),LL(0x0358a26c,0xb9b10ced),LL(0x4b8ddfaa,0x0a30dbbe)}, {LL(0xe20f6fac,0xa70e9712),LL(0xd11451b0,0x87c7f732),LL(0xd5eece8f,0xf0c967b1),LL(0xab370e2d,0xbc62882a)}}, {{LL(0x59ddb7cb,0x134fb08e),LL(0x3ae8f816,0xe937c663),LL(0x802ed184,0x083f73a7),LL(0x8cd69f8d,0xd4badd85)}, {LL(0x987f389e,0x2d8bfaf5),LL(0x4454b1f2,0x5338c056),LL(0x2f104468,0xdce38439),LL(0x83c5278b,0xffd94d27)}}, {{LL(0x5628ad08,0x8740af50),LL(0x8b1284e8,0x30a233db),LL(0x57acc8cd,0xb3982d73),LL(0x37c5ff03,0x211d53d3)}, {LL(0xf6578d40,0xb6371f1b),LL(0xa80dec53,0x7f749bea),LL(0xa9816ec0,0xe6b3f730),LL(0xf5423ec6,0xd26832fd)}}, {{LL(0x63e27b64,0x80127368),LL(0xd2d21879,0x17b7a4b2),LL(0x43cf40d4,0x7dcced37),LL(0x97cf7c4c,0x999bbb80)}, {LL(0x6bafa0b0,0x191c84e5),LL(0x917f6b17,0x1d08c049),LL(0xf4715c99,0x02e5fe53),LL(0x0658f1de,0xa92c6085)}}, {{LL(0x16a010bc,0xe9c0ba85),LL(0xea4f3e8e,0x2fd90fba),LL(0x4570a1e5,0x8af18371),LL(0x7cca9004,0xe869e8f7)}, {LL(0x2dd83019,0xe2c8afb7),LL(0xfd99b386,0xb877995d),LL(0xf5adab87,0x1e3efc16),LL(0xaa3b191a,0x93105fe4)}}, {{LL(0xae504c31,0x21690dca),LL(0x698f629d,0x2d51ead4),LL(0x724c9cbf,0x2af3eef1),LL(0x81a0d4aa,0xa6181e60)}, {LL(0xa94f6b05,0x580982c7),LL(0x48653ad7,0xe8bea903),LL(0xa608598d,0x0270614c),LL(0x3d0d5360,0xa7cae0f0)}}, {{LL(0x96067f64,0x81407687),LL(0x77a62d7d,0xab2c2706),LL(0xae19786b,0xbe9c1edf),LL(0x887814eb,0xa313f2b2)}, {LL(0x08fd3c04,0xe2bc4c1f),LL(0xe5a9d032,0x25387129),LL(0x8fbc5030,0x7b3ced22),LL(0xadbf1bdc,0xc22bea3b)}}, {{LL(0x7b1308da,0x4f6b6b6d),LL(0xd0e33069,0x0f2faaaf),LL(0x0d3677c4,0xb461990f),LL(0x0e6a876b,0x55c9df43)}, {LL(0x316d252a,0x5ce9aaa4),LL(0x0e8e5097,0x7d98a813),LL(0x9aa3343e,0x047ecd13),LL(0x939277e1,0x15cc7072)}}, {{LL(0x0a020be7,0x305165d1),LL(0xf66eaf8b,0x48560411),LL(0xffd2380e,0x5ff898dd),LL(0x784b4b11,0x7da35f08)}, {LL(0x38fd05c7,0x50f53e2c),LL(0x47ada3a5,0x64b3ee82),LL(0x678995de,0x672ae316),LL(0xdfe96605,0x74707460)}}, {{LL(0x441e7150,0xb346dc71),LL(0x55fd483c,0xd9505e7a),LL(0x94302331,0xca96e59f),LL(0x801930cf,0xcfde701c)}, {LL(0x73c31e5d,0x02fc9936),LL(0x8cda0b51,0x4ef53a55),LL(0xa269a1f3,0xa934e268),LL(0x7cca8542,0x7ba4e5e0)}}, {{LL(0xa2ae339c,0x4c6408f9),LL(0x5a70ba33,0xf9ea4cb2),LL(0x5cac2af4,0x3eaa9364),LL(0x95eaea09,0x62686d46)}, {LL(0x3e771722,0x5196e88f),LL(0x7108b198,0x749518e8),LL(0x29b25254,0x394107c4),LL(0x3a315aad,0xf9945ac1)}}, {{LL(0xaab9dbe5,0xce15c84d),LL(0x3940eb15,0xebb54d52),LL(0xa2fdd11d,0x69b649c7),LL(0x3f6ade80,0x4e2d1782)}, {LL(0x2327f7d8,0x0f53ac9c),LL(0xc79eb564,0xf6158d6e),LL(0x4536f5c1,0x2903bfc0),LL(0xfb9e9e07,0x0a25518b)}}, {{LL(0x62a0b0ed,0x70cbce8b),LL(0x0abbc9be,0x92f5dc33),LL(0xf369c2d6,0xbb92b7d3),LL(0x79ef83e1,0x70dd90c8)}, {LL(0x7937ab45,0xe0b33153),LL(0xc054af6d,0x3a8d1f74),LL(0xb05ebfc4,0x35cf7380),LL(0x58c2cd0c,0xefb8dac2)}}, {{LL(0x7d665d26,0xe7316f99),LL(0x800fba6f,0x59a7ead9),LL(0x08a2cb88,0xfa4d2a2a),LL(0xb441995d,0x2e7d3bab)}, {LL(0x93046f2b,0x390988c9),LL(0x08869cf5,0xfd95b86e),LL(0x9a76537b,0x0185b6be),LL(0xb6cd3d59,0xa89563bd)}}, {{LL(0xecb1ad25,0xe79a4f63),LL(0x6948504d,0x1857cec7),LL(0xa497922f,0x03b7b3ad),LL(0x38930f36,0x9df2f2e4)}, {LL(0x4bb5927c,0x355e4a7a),LL(0x636ec349,0x5ad3fd47),LL(0xc41b19ca,0x5400730d),LL(0x555afa93,0xbfeabac1)}}, {{LL(0x6cca58b7,0xb6232083),LL(0x76d0c53e,0x55faae6b),LL(0x40a8eb5a,0x64ef60e2),LL(0xe8f22c94,0xc68bc678)}, {LL(0x10a0416e,0x5156dc1c),LL(0x5c2037e4,0xac779644),LL(0xc7162aaa,0xd2e30925),LL(0x2cf21e2f,0x7bb5275f)}}, {{LL(0x0c11e65a,0x7722cb40),LL(0x68ff2be5,0xc94a7f52),LL(0x8d9f9352,0x420085cc),LL(0xca4b2544,0x4addb986)}, {LL(0x06264a47,0x3c6ceac0),LL(0xe2b48ccc,0xebc01a03),LL(0xea94fef2,0xc430e7ab),LL(0xbd94aa8a,0x973bb6f0)}}, {{LL(0x3225b585,0xd60e5feb),LL(0x01b56ad1,0x6cbab39c),LL(0x37d6d1b4,0xcb55a9cc),LL(0xfbce1d89,0xd7288c1e)}, {LL(0x162d4b46,0xcb516843),LL(0x15edb910,0xf0aca3a6),LL(0x08a6685a,0xdb998b55),LL(0x07811873,0x16b442e6)}}, {{LL(0xa1a7e0c2,0xa9badd09),LL(0x9f813289,0x0a9a339b),LL(0xd4cda45b,0xabf1793f),LL(0xc7378a84,0xa9830a12)}, {LL(0xd28165b1,0x1ae11c32),LL(0xf71bca14,0xbfd49ace),LL(0xfc035476,0x9a3990df),LL(0x6c32b72a,0x0fd2b153)}}, {{LL(0x3541b5ae,0xceece835),LL(0x8256c750,0x2f7429f5),LL(0x88104f8c,0x456c3478),LL(0x8b23da06,0x8a435588)}, {LL(0xd817ce6a,0x6b6c14f2),LL(0xf35ab86a,0x83bf0acb),LL(0x364b83fd,0xdadb89ba),LL(0x5cfecaf3,0x2c8fcf90)}}, {{LL(0x20d12c92,0xa90f77ca),LL(0x69d1739c,0x2e278e0e),LL(0x5c1f9e82,0x29d24b44),LL(0x647c59b1,0xbf4fb4cb)}, {LL(0x90ffd733,0x9c8ea39d),LL(0xf14db3fc,0xe37a1352),LL(0x8f3e1dca,0x3c9164a2),LL(0xaec86440,0x515c16f2)}}, {{LL(0x5c483906,0x736fee4c),LL(0xa3f651c7,0x2325cabb),LL(0x35b94e45,0x582324df),LL(0x45598c64,0xeacedb3a)}, {LL(0xde9ea8cd,0x674e1740),LL(0x89d2b975,0x30f2f423),LL(0x9c8abe45,0x330bd76d),LL(0x5371c0c4,0xb97e89f6)}}, {{LL(0xb7569543,0xb1769248),LL(0xd85f4d72,0xd29cc9d2),LL(0x10a5b6dd,0x89e1fd0c),LL(0xa693a796,0x501be0ae)}, {LL(0xe490e600,0xc70965b6),LL(0x1bb6c5cd,0xf518f8af),LL(0x76f6daa2,0xf51d40bb),LL(0x5ec7849c,0x83a83b67)}}, {{LL(0x6d8aa314,0x0fe0d975),LL(0xea664a8c,0x9bf9aed5),LL(0x96fad9aa,0xef8bb989),LL(0x04a0e441,0xd07dce35)}, {LL(0xb3c5eb81,0x53bd2a16),LL(0xaf178b66,0x49e29fe2),LL(0x24dced32,0x62cf7a62),LL(0x0f541e36,0xcc111fba)}}, {{LL(0xda9dd111,0xc93cd7c1),LL(0x28c9c1b4,0x56b625ab),LL(0x3769f3a2,0xeff436ae),LL(0xcbd31a17,0xa0d8d46b)}, {LL(0xc80dc873,0x241693fa),LL(0x3cd579ab,0x56083f64),LL(0x33fbd431,0x12ee753b),LL(0xd66c283a,0x1bde60ad)}}, {{LL(0x0243cd83,0x0db508dd),LL(0x1349307c,0x3b12c134),LL(0x61d86bda,0x8296aa6d),LL(0x630adc96,0x1d5c8a4f)}, {LL(0xa30a8ae6,0x9d01dc28),LL(0x1dab8168,0xc555a743),LL(0x7abe577a,0x61fe0d14),LL(0xc8c93bb7,0xe26aa4d8)}}, {{LL(0xda2bab5b,0xfb4b03bf),LL(0x79b4e6c0,0xfbd49089),LL(0x86806aa4,0xda1a0108),LL(0xdc078112,0x281f76ae)}, {LL(0xe0fbd693,0x9f662594),LL(0x49ec4ee0,0x1da897b0),LL(0xfc7d1578,0x20d52a97),LL(0x6b1f4ab4,0xdbf8d157)}}, {{LL(0x3b97d1e3,0xfc0a5936),LL(0x1aa091b6,0x00f0f283),LL(0x13aadeb0,0x505e183e),LL(0xa55b3f8a,0xe28041ad)}, {LL(0x086c2d23,0x2e0f76da),LL(0xf2c5eceb,0x815b147d),LL(0x673ba5f2,0x02066c02),LL(0xce043d4d,0xb85d6a8a)}}, {{LL(0x113890f6,0xd5f023a3),LL(0xa9d2491b,0xaa4f9058),LL(0x16d175a3,0x6d82393e),LL(0x671e2aed,0x1d1e00b2)}, {LL(0x40018bae,0xd47c4f28),LL(0x7b30838f,0xd08eac83),LL(0x5dfe910d,0xa0fde631),LL(0x5c66d5c6,0xfc16adf7)}}, {{LL(0x18d8c6b1,0x0ed2a8a2),LL(0x632b5b07,0x67ee6037),LL(0x21a89b8d,0x7eed42e5),LL(0x33e6da02,0xd99942cf)}, {LL(0x39971405,0x759ec79e),LL(0x174dca4c,0x669a92c7),LL(0x9d1e7c55,0x85935ed7),LL(0xa82055c0,0x5f3f9e68)}}, {{LL(0x56aa5af3,0xab0507c8),LL(0x1bd2726f,0x354cac5d),LL(0xb864816f,0x46e85e16),LL(0xd1840add,0xef2548f6)}, {LL(0xc3842f43,0xe494ea07),LL(0xedf6c13a,0xa6169c4a),LL(0xa460e30b,0x65d9cca3),LL(0x31e7dfc3,0xa6848e4f)}}, {{LL(0x5c8109dd,0x4309f315),LL(0xc5799833,0x7a4ec14e),LL(0xa8132b78,0xcb768a63),LL(0xb416c77c,0x229106d1)}, {LL(0xded02f41,0x1ca71df6),LL(0xc1a1fc66,0xb6365d3e),LL(0x1431d1fa,0xf7c432a1),LL(0xa5654387,0x30364500)}}, {{LL(0xd5b13b2e,0xc9ed0cf8),LL(0xd18d5a28,0xdbd541bb),LL(0x754de9d2,0x6b78c887),LL(0x54651568,0x7d32fedb)}, {LL(0x0d37c339,0x7f319680),LL(0x37d70b76,0x22304d1f),LL(0x6fb5e555,0x01b2709e),LL(0xfd5d1708,0x978b0d3e)}}, {{LL(0x96bc118d,0x83206b9d),LL(0xec7bfc1c,0xb1a4d7bf),LL(0xb6b41502,0x753f98a6),LL(0x4c5187ce,0x41139110)}, {LL(0x587a8213,0x56e9e218),LL(0xad9aefd0,0x3b39955b),LL(0xb9947ceb,0x7428b03f),LL(0xbe8bda29,0xbbe82668)}}, {{LL(0x5c4b4c63,0x5142e8ba),LL(0xe92ee291,0x90c3e2e3),LL(0x8f6a076d,0x6947a55a),LL(0x61964435,0x9acdeec1)}, {LL(0x181dac35,0x56bc8e4c),LL(0x7a824372,0x4f4f2c0a),LL(0xc1033f6b,0xd1958b99),LL(0xc83ecf98,0xeeaa6604)}}, {{LL(0xaca52cb3,0xe43c0b44),LL(0x75443f14,0x12446426),LL(0xddcc00b4,0x0d14e885),LL(0x6cfe5734,0xb0f5f11d)}, {LL(0x1013afcb,0x0e160164),LL(0xed9f4535,0x4f570ca9),LL(0x73a307ad,0xe5162a12),LL(0x3321ae54,0x6a431695)}}, {{LL(0x5ae301b4,0xa6c7b0c5),LL(0xbd2d3f1d,0x6f5d42b1),LL(0x15c0c94b,0x4eb12c09),LL(0x28618c41,0xf1c40386)}, {LL(0xc0f55c25,0x30302333),LL(0xbd1c19f0,0xa5e41426),LL(0xcfcc66f8,0xd5d4d4d7),LL(0x449253c5,0xcfdf3039)}}, {{LL(0xb30ec0ff,0x17b0eb72),LL(0x5e6424f9,0xbce593e2),LL(0x2a73184e,0xa5d82937),LL(0xebe58773,0x23d2857a)}, {LL(0x067e1eac,0xe3f0f676),LL(0x50509d7f,0x073ded2d),LL(0xca405a7e,0xc22af8f0),LL(0x6df6a46c,0x7a4ef592)}}, {{LL(0x97067006,0xf9cb0178),LL(0x489d2a39,0x9ae132af),LL(0x6a2da1c1,0xc7c46b35),LL(0xd95850c9,0x0993353b)}, {LL(0xa25d52ef,0x6c313a57),LL(0x93c852c3,0xa6bdb2b2),LL(0x7e9e296d,0x27ed916b),LL(0xc7aeb09b,0x10b58337)}}, {{LL(0xecebe36e,0x78800c35),LL(0x2234ce8a,0xd93e2423),LL(0xfa95019f,0xe4cf5cee),LL(0x71e13748,0x21396d37)}, {LL(0x0c32fdad,0xeb028350),LL(0x61f1652b,0x31645697),LL(0xf6677491,0x9e1c6e0b),LL(0x74176c12,0x4d18f2e5)}}, {{LL(0x3832d713,0x78d559bf),LL(0xb6e00e15,0x04f0b57b),LL(0xe80add3a,0xd6c9cb16),LL(0x5c7b1d70,0xeabfabc5)}, {LL(0x98a62cc3,0x40570866),LL(0x4abb2b1a,0x39ef8ff1),LL(0x0c19959c,0xadb40548),LL(0x388b1f7c,0xd61632d7)}}, {{LL(0xd73b7d50,0xd1f9b736),LL(0x560bf0aa,0x652ed78e),LL(0x50e3fc4f,0x58e71e33),LL(0x55df1ad1,0xbfaf5f44)}, {LL(0x9106744f,0xefe8893b),LL(0x356d1fe9,0xabfbd51e),LL(0x9eb1cbaf,0xab03570b),LL(0x3919012c,0x92cfe2e4)}}, {{LL(0xb6f7c64d,0x7671e5fb),LL(0x6e0a44b7,0xf040c039),LL(0x62b36088,0xf430f593),LL(0x94c7c0ac,0xa85b4bc9)}, {LL(0x16b54fff,0x07d5c40c),LL(0xc53a3788,0x47aa73ee),LL(0x7000d61e,0xa63c5b36),LL(0x91b9f09f,0x04e8f53d)}}, {{LL(0x87dc6a3d,0x7e48021d),LL(0x28ae0f74,0xa2b5516b),LL(0x705132e2,0x84412003),LL(0xe243d1fa,0xc55f69cf)}, {LL(0x6a8f80bd,0x758c0f71),LL(0xd09b719d,0x69ecf887),LL(0xa9b45194,0x51b100f0),LL(0x90ae0769,0x1fb9ef66)}}, {{LL(0x30fcdfd2,0xfee82fab),LL(0x36a6990b,0xf36185be),LL(0x3d33027b,0x88f343f6),LL(0x38ae16c6,0xb775dcbb)}, {LL(0x85a82e45,0xa107b9f0),LL(0xde6b9806,0xaff8b0ae),LL(0x0392fad0,0x3cd3980f),LL(0xf3cf7650,0xdd829fc6)}}, {{LL(0x0dc8d031,0x177190cc),LL(0x7fc491eb,0x3e21cd25),LL(0x0d929039,0xea0cc90e),LL(0x1dfc37b3,0x5f7e6292)}, {LL(0xe23bdd04,0x66dd6dde),LL(0x64fa490a,0x70e7a317),LL(0x10a03dd8,0x59c90f81),LL(0x96d58314,0x425ee6ce)}}, {{LL(0x5f896ed1,0x868001eb),LL(0x91dad4fd,0xc4c003f5),LL(0xd9ef80b4,0xfb4782b2),LL(0x323e4fc5,0xb9edb975)}, {LL(0x53ef4ccc,0xa2ec9b6c),LL(0xa77922b6,0x4af8b2ca),LL(0x6697874b,0x73850e89),LL(0x3568523f,0x76e0fd72)}}, {{LL(0xe9c400a6,0x64799f46),LL(0xa9c245de,0x6c5176e7),LL(0x93503700,0xbd97c80c),LL(0xffbe539f,0xa92d9ee5)}, {LL(0x8376bb3b,0x76003d14),LL(0xac564679,0x2e75cc77),LL(0x3a333970,0x126af6c7),LL(0x6b6604bd,0xdbfd0133)}}, {{LL(0x24424a48,0x11cf4c2e),LL(0x37d4471c,0x843c73ee),LL(0x617a488b,0xb3047fc5),LL(0xe3cf861c,0xf2a91709)}, {LL(0x1c3a60f7,0x84444421),LL(0x26679148,0x74787a36),LL(0x53d9404b,0x115fbd06),LL(0x6244cef0,0x70fd3365)}}, }, /* digit=23 base_pwr=2^161 */ { {{LL(0x2b574b7f,0x76695c9b),LL(0xc369b6be,0xcca80405),LL(0xe3108ded,0x1f4bae99),LL(0xea133fce,0x9e715ce2)}, {LL(0x54c2ee1c,0x60d52055),LL(0x1680742e,0x56bab301),LL(0x3fe438b9,0xa409b5f6),LL(0x8036f7ce,0xe3a8e4d0)}}, {{LL(0x247fdfdf,0xe1d7ec0f),LL(0x4a23d1dc,0xfb9d90e7),LL(0x190fdc41,0x7012eb2c),LL(0xddced48c,0x5c2bbff6)}, {LL(0x68cd7feb,0x8a93426a),LL(0x6b4854e1,0xb5963962),LL(0xe772bbd8,0x8ac72b8e),LL(0xa6b3040a,0xc10d24d2)}}, {{LL(0x94d5f347,0x8fdfef16),LL(0x2b04af0a,0xf3189490),LL(0x6d2ca633,0x30e3da7a),LL(0x4803814a,0x8d002aea)}, {LL(0x95a0bfe9,0xc15e311f),LL(0x4b4cc50c,0x2891ec7e),LL(0x8834df25,0x0936fed8),LL(0x78e00289,0x7e5d7dbf)}}, {{LL(0xfbfcf1b5,0xb9a92d78),LL(0xe8427d74,0x17ce4fab),LL(0xac66e74e,0xbae98ffd),LL(0x145bb5e5,0x6d548304)}, {LL(0x0992abe1,0xbf3dc603),LL(0xbefdc5c5,0x318cfbda),LL(0x59f8efb8,0xbb5fa37d),LL(0x4ef5bef8,0x347874a0)}}, {{LL(0xbf68688b,0xdf552b01),LL(0x8f96a57a,0x2fc542cb),LL(0x4edb340e,0x5a731b61),LL(0x181cf578,0x5143d103)}, {LL(0x2cc936b6,0x749ab511),LL(0x0dd355c2,0xbc94c053),LL(0xa3900fa2,0xa825eff5),LL(0xc1dc2b31,0x60a909a3)}}, {{LL(0xaf5bcab5,0x59b33c78),LL(0x496fbcdf,0x0053d789),LL(0xd7883bc1,0x5a5afe02),LL(0xfa66951d,0xec9afe78)}, {LL(0x728e56a6,0x38f28b83),LL(0x78cafb9d,0x21d0b6ac),LL(0x7042e327,0xd43996bc),LL(0x7c31c145,0x60686637)}}, {{LL(0x3d919304,0xe1f8d2e6),LL(0x456be82a,0x09cf437c),LL(0xf0c21973,0x6a01dae8),LL(0x246d9ef8,0x8bffcda8)}, {LL(0x5d853975,0x7e03a0d4),LL(0x32533ba3,0xc3800ca8),LL(0xf02ce43c,0xd77152cc),LL(0x6392089a,0xb8bc17a6)}}, {{LL(0x4b4558fb,0x6f5fcb61),LL(0x1f2545aa,0x9602597b),LL(0xabe5e469,0xfd89ab3f),LL(0xfb2e16bc,0xf1daeea2)}, {LL(0x3a12940f,0xe699acd7),LL(0x4d7c7311,0x24980f6c),LL(0x336c8ec6,0x4a5cf975),LL(0x8c27d3dc,0x8e180e32)}}, {{LL(0xd36cb503,0xafb66269),LL(0x754fdd67,0xe98b07d2),LL(0x5a1fe9bf,0x1e0b425b),LL(0x24fc4a85,0xb4ac13e9)}, {LL(0xc05a9c3f,0xef693781),LL(0x5c0124dc,0x266c1216),LL(0x64ee22e2,0x7f3184c4),LL(0xcdb5f1a9,0x3f985fb3)}}, {{LL(0xfc01efaa,0xb258cd5f),LL(0x0775588e,0x861688b1),LL(0xfa46eae0,0x72184b18),LL(0x5003404a,0xd17c9dea)}, {LL(0x92e7bf9e,0xa8791966),LL(0x7891ac50,0x049c63cb),LL(0x5d46b33d,0x2ed32928),LL(0x0623595a,0x49d1bfbf)}}, {{LL(0x36c8e3e9,0x9f871470),LL(0xb20d610d,0xdec7eb98),LL(0x7b151f4e,0x15b9326f),LL(0x04005d02,0xa624c23e)}, {LL(0xd9cacded,0x89fc2a8e),LL(0x9a2c3a00,0x9eb8defa),LL(0xe8d7eab7,0x7c5dc2d6),LL(0xeb0a77cf,0x48fa5403)}}, {{LL(0xbf033733,0xcc4c31d0),LL(0xef211c17,0xf37d0072),LL(0xae35b246,0x8967fe49),LL(0x5cb1aa9b,0x8c4cbd66)}, {LL(0x04840da3,0xab0097db),LL(0x5828733e,0x3946faec),LL(0x87d64045,0x96c6531e),LL(0x83bc0d0e,0x893d3780)}}, {{LL(0x53bec0dc,0xf833e355),LL(0x2803a655,0xc9ff7280),LL(0x42b99b53,0x300ff7aa),LL(0x6a7c3f2c,0x3b48a8db)}, {LL(0xf617f8aa,0xf78c21d9),LL(0xcbe4d565,0x23684cb7),LL(0x7514e9a0,0xf64ae9c8),LL(0x8429d8ba,0x4ff5483c)}}, {{LL(0x5cb18391,0xdedab351),LL(0x769ae948,0xd3126ffc),LL(0xd3546ad9,0x6c2f9ba8),LL(0x69aabfb7,0x4567e48a)}, {LL(0xaa284747,0x6fbe29b0),LL(0x98af4f2f,0x3185f0db),LL(0x5b4c14e3,0xf2a958a2),LL(0x27d04855,0x106150c5)}}, {{LL(0x68a19ca9,0x60a3b4fb),LL(0xfac47c70,0x65c5719a),LL(0x973e4cfd,0xe228e088),LL(0xcb63c89f,0x122a2429)}, {LL(0xbaea08f7,0x39fda97e),LL(0x621c12cb,0xe7da5324),LL(0xff9b3c84,0x569c8a51),LL(0x4c3b8d54,0x5ab8bb6d)}}, {{LL(0x00e25a95,0x4f02ece4),LL(0x7ac1732e,0xef947402),LL(0x51149260,0xecdb65ac),LL(0xa9180d51,0x6043aa29)}, {LL(0x852deca0,0x07fc92bd),LL(0x15237c8d,0xf3338297),LL(0xe84b3f38,0xecfb0e76),LL(0x6b89af17,0x21f2f5c5)}}, {{LL(0x9659963f,0xf7aec268),LL(0xa0cb213c,0x67fb5260),LL(0x66d931b7,0x5daa0fef),LL(0x34d309ff,0x95457a7e)}, {LL(0xc21285b6,0xe7cf1a56),LL(0x244e11b4,0xcbff9b08),LL(0xc0ecce3d,0xd79ee62d),LL(0x8267c254,0xe3f20739)}}, {{LL(0x037ef2d3,0xee06dd39),LL(0xd522f762,0x790d1b0f),LL(0xf30c47d0,0xf0659106),LL(0xb5fdc6b5,0xcd83214b)}, {LL(0x6593b717,0xc8621660),LL(0xfe3fa381,0xb10a6d99),LL(0xab254244,0xa5c3224c),LL(0x5854b18e,0xd15287e6)}}, {{LL(0x225806ae,0x6bf9594c),LL(0x57e554f2,0x75a97e21),LL(0x82b00b16,0x0ea199f3),LL(0x5389c90f,0xde81a726)}, {LL(0x86922afe,0x8503609e),LL(0x254b75c3,0x6778ad88),LL(0xf3e660ba,0x6bc2ac1b),LL(0x209c04a4,0x7efc1550)}}, {{LL(0x2528ec51,0x6e90b6a5),LL(0x0548389e,0x9196a7c9),LL(0x7b5b5dde,0xf7e285c1),LL(0x223d4837,0x6335a624)}, {LL(0x412d19c4,0x8acef5af),LL(0x9783256b,0xb22808a5),LL(0xf53e4b62,0x6ea3daaa),LL(0xfa7bada4,0x7ca4c51b)}}, {{LL(0xe4d3115e,0x3e40461e),LL(0x3646fc40,0x24889b50),LL(0xfa26ccf7,0x39e0eb1e),LL(0xa82af350,0xfcad5d47)}, {LL(0x4862b1fd,0x90037503),LL(0x1a79283c,0x88e937e8),LL(0x9a0127fb,0x16dd07c0),LL(0x39fca31a,0xac62a168)}}, {{LL(0xa294dac9,0x26542e2a),LL(0x2a5dcfe8,0xefab45af),LL(0xe642bbe8,0x6166857d),LL(0xff6290a8,0x3f3ad480)}, {LL(0x5f50633f,0x435d4c2b),LL(0x84451c8b,0x36da60a7),LL(0x261612e4,0x00f5e2e4),LL(0x2d04786a,0xe4318273)}}, {{LL(0x2c175edb,0x192bcda5),LL(0x59a6f637,0x74681e0a),LL(0x2d244985,0x696df08b),LL(0xfcf577c6,0xde61a87c)}, {LL(0xf2c9de81,0xcbd2ceab),LL(0xd36162e8,0x878f06ce),LL(0xb3d22955,0xc4f312e0),LL(0xe903efee,0x736ed43f)}}, {{LL(0xca9bf60f,0x2c687134),LL(0xbc7da3a5,0x2473ea8f),LL(0xb45fb57e,0xf54ef685),LL(0x3383cadb,0x594e8445)}, {LL(0x4a7df4bb,0xe1edd3fb),LL(0xc17c2c92,0xa783d987),LL(0xcf8fcba8,0x0d498637),LL(0x3acd6e4c,0xdebd801d)}}, {{LL(0x34d3761e,0x2ade8a7c),LL(0xd825cd19,0xc591c889),LL(0x39b42dec,0x3ffd60ba),LL(0xfd9674dc,0x136d4902)}, {LL(0xda4842c4,0x373a70f8),LL(0x3f078bfd,0x3208c485),LL(0xef608639,0x3587f871),LL(0xf04e46ed,0xf990ab0f)}}, {{LL(0xa83a8450,0x39d542ab),LL(0xdacb7c65,0x634b9198),LL(0x82486a05,0x680cef78),LL(0x16eaf88b,0xab1d4d77)}, {LL(0x699c7aa5,0x5e605279),LL(0x3c40a07f,0x7e37906f),LL(0xfb6926e3,0x4ae84ad8),LL(0xe2ebc73b,0x236b5f07)}}, {{LL(0x9e0939a5,0xa94e50ab),LL(0x2d9e10e2,0xabeed810),LL(0x4e6423d3,0xea8190fb),LL(0x17acb62c,0xc739d209)}, {LL(0x6fdbe8dc,0xae38106e),LL(0x63204138,0x1c6532d7),LL(0xbb7d0510,0x03af879d),LL(0x8cd2b1a4,0x1d76faf0)}}, {{LL(0xd77386cc,0x2fcdaf9b),LL(0xe32d2633,0x30f9f5a4),LL(0x382e7298,0xa4fc8189),LL(0x588af205,0x946923a1)}, {LL(0x114f2beb,0x2c527a79),LL(0x077762eb,0xa2ca55d3),LL(0xcc85e41e,0xe4b2eb7c),LL(0x89346ada,0x4b5938d2)}}, {{LL(0x4c2084cf,0x8e94e741),LL(0xa839ecb4,0x4ef32d29),LL(0x802f0897,0xc5371755),LL(0xc49ae8a1,0xb0274ff1)}, {LL(0x417bff62,0xf7716d1c),LL(0x918f9555,0x6efb0748),LL(0x7aeb1e8d,0x7d3bb9c8),LL(0x20d51e18,0xee9bd5e1)}}, {{LL(0xd52033b1,0xfaf0a1a5),LL(0xb8626432,0x7967d3f4),LL(0x5574dc0e,0xe837ca4b),LL(0x2c11d8ff,0xf7eae237)}, {LL(0x87dc4007,0xc0f2f1fa),LL(0x8dfb51f7,0xf5f1f153),LL(0x5bd9ac7f,0xa64b10ae),LL(0xa2198841,0xb3c2ba37)}}, {{LL(0x66c1ee7b,0x5a7ebac5),LL(0xdba62ea8,0x59e06f4c),LL(0x30944ef3,0xa2ea165e),LL(0x3e21385b,0xfd5c7dfa)}, {LL(0xe3bb110d,0x4a012c73),LL(0x4fb2fdf3,0x16d85219),LL(0x7cad0594,0x1aac7f11),LL(0x4b098d9f,0xea7f7dbf)}}, {{LL(0x7fd181e7,0x88abaa5c),LL(0xca3ad1eb,0x136a0c9f),LL(0xf394aab5,0xe6e5e6c2),LL(0x9349e4a5,0x84d697d4)}, {LL(0xf76f4b3b,0x8215578b),LL(0x12feeb5f,0x81a1cec6),LL(0x3e876bc3,0x5d336eb7),LL(0x071892ca,0xe8afdcb5)}}, {{LL(0x3da8d94c,0x22f16f6b),LL(0x2d150069,0x28b276c5),LL(0x643d3e58,0x49d20441),LL(0x3da3a7fb,0x3450c84a)}, {LL(0x442ca3e3,0x8f5bf388),LL(0x9e615382,0xca31411c),LL(0x7798675f,0xbe63e34d),LL(0xd1ea01e1,0x551eb64d)}}, {{LL(0x34a00e27,0x1738a83b),LL(0xbf58ce70,0xe7591d15),LL(0x57d806d8,0xde2ace5a),LL(0xd0338020,0xe89e8110)}, {LL(0x4e25756c,0x935ed5de),LL(0x46d0f00b,0x07ef8c2f),LL(0xa659592a,0xa28e5fb4),LL(0x7fa4986a,0xcb45c622)}}, {{LL(0x74de493c,0x6b7df066),LL(0x79aa5258,0x4d6bdaef),LL(0xe2b255ed,0xe9709c34),LL(0x7d0e7443,0xdba2653a)}, {LL(0xa00eb3e4,0xeb8da5c8),LL(0x7ab0e45c,0xe978228e),LL(0x9d551a51,0x3a31bafd),LL(0x403352f5,0x1de0e9cf)}}, {{LL(0x23ddd51c,0xb94d5478),LL(0x130e78e3,0x7c215c91),LL(0xed547bce,0x556b92e0),LL(0x909f5c6f,0x0072da6b)}, {LL(0xf0dc846b,0x4ec71b11),LL(0xbf7baaa1,0xd0f3b3b4),LL(0x47770705,0x896391c5),LL(0x66732587,0x41fe5736)}}, {{LL(0x4acd3c51,0x02a7e3e3),LL(0xd30407b3,0x217df736),LL(0xe47c33cb,0x503a31ae),LL(0x4912bbb0,0xe3186392)}, {LL(0x75a5df9a,0x2491a08a),LL(0xc09294ad,0x2882f937),LL(0x979ad9f9,0xe2576b69),LL(0x26dc1ffc,0xf44ddc15)}}, {{LL(0x968268ae,0x7dad21d4),LL(0xbe9c6fc0,0x07378e90),LL(0x2b329579,0x9406a872),LL(0x761f10ae,0xb27b5c51)}, {LL(0xd04cf60b,0xf5dad2f9),LL(0xdf950997,0x3154dff5),LL(0xd8534a9a,0xaaec9d30),LL(0xac43f212,0x4ac722f5)}}, {{LL(0x46464c70,0x722882f4),LL(0x6c3c702e,0x9b9b5226),LL(0x8325964e,0x4e3974bb),LL(0xaa0c5227,0xd3ceff9d)}, {LL(0x9534dba5,0xd530c8f9),LL(0xbc751878,0xd26e547b),LL(0xea79b19a,0x184a3527),LL(0x74f1cdc4,0x8dab9214)}}, {{LL(0xc051e9f6,0x708abc8c),LL(0x4be2d9ca,0x75194e9f),LL(0xd6ab5348,0x031d69c1),LL(0x78b0e490,0x1785990e)}, {LL(0xf6c41f8e,0xd825f125),LL(0x0fbf2fe6,0x429924ea),LL(0xfb87161e,0x53c044be),LL(0x0651d153,0xa3bbdf1b)}}, {{LL(0xec6ecb9c,0xda660697),LL(0xddb8c619,0x51b4a5fd),LL(0x230fbffb,0x80b87520),LL(0x8848da9d,0xa0587430)}, {LL(0x864c2502,0x98715939),LL(0xaf973396,0x2b10cbfb),LL(0x09572b5f,0x28675184),LL(0x39adf777,0x0a40cdef)}}, {{LL(0x3ead6eef,0x2efa3bb4),LL(0xd1b9fe65,0xbd76b425),LL(0x5e527201,0x95f006cd),LL(0x38a7dc3f,0x00890f3b)}, {LL(0x3a7ce6be,0x84ffa014),LL(0x89541c2e,0x3406aaa0),LL(0x9559d989,0x430542b6),LL(0xb53bddd8,0x9b427b08)}}, {{LL(0x49639170,0x2182bd91),LL(0x3299ae83,0xb9fb2b42),LL(0x423b7ea2,0xbc993d59),LL(0xc110039e,0x03e416ac)}, {LL(0x3ffe24aa,0x90c2269a),LL(0x1c322c49,0x421ea02d),LL(0x0ef8fa01,0x40677b1c),LL(0xc59407d4,0xa1acd239)}}, {{LL(0x8f14decc,0xb8cd4f40),LL(0x69e16a6b,0x95e90d87),LL(0xc3c38fd3,0x85dcf163),LL(0x0c01f90a,0xf4fb87ba)}, {LL(0xdcd0f994,0x8274f825),LL(0x2e6bf7d8,0x4c685fa5),LL(0x3d928011,0xc87d8847),LL(0xf9efa96a,0x9add0105)}}, {{LL(0x50db3113,0xed39152b),LL(0xb794e6b4,0x6b523496),LL(0x84630b17,0x6bb241b6),LL(0x1de3ae08,0x6e9f8ae0)}, {LL(0xd94ce4fe,0x97bd7c09),LL(0x9e61057a,0xe887b02c),LL(0xc62c27fa,0x853e8feb),LL(0x01600ed6,0x3f9d951a)}}, {{LL(0xb57b9742,0x3e957b36),LL(0x82b72110,0x92bfd61e),LL(0xfdce7ec4,0x108b450b),LL(0xcc29c494,0xd8af107a)}, {LL(0x47688c92,0x8d67ff70),LL(0x28b9b681,0x57f42933),LL(0xaaf8a48d,0xbbc98ef3),LL(0xe2d549b6,0x14113b1a)}}, {{LL(0x0b412b3c,0x1172b259),LL(0x1d42a63e,0xaf86ca6f),LL(0x83660d24,0x5f893135),LL(0x5a21a441,0xe7bfe9a8)}, {LL(0x4ee5122e,0xecd0aa5b),LL(0x5e4df46e,0xbb68654c),LL(0x5e243845,0x0c3e820b),LL(0x5c46bfa5,0x042b1895)}}, {{LL(0x894f7f16,0x791b2085),LL(0xb5c353fb,0x42eb80f2),LL(0xdf8db0d4,0x377777f7),LL(0x34c42ef2,0x023c0963)}, {LL(0xa34cb6d0,0xba05eb5e),LL(0x55cd1242,0xffb8b01e),LL(0x87cd9f24,0xeab6ff7d),LL(0xab3c09fc,0x175e94c9)}}, {{LL(0x7075fd9d,0x6dc68140),LL(0x4b203c44,0x63851566),LL(0x871d1be7,0x3071e924),LL(0x85ee9cd9,0xe6285b56)}, {LL(0x4bcf8edc,0x738dd629),LL(0x4ace75f5,0xf3a36813),LL(0x3cf6feb4,0x37a09e34),LL(0x2cd0c8af,0x4c2eaef7)}}, {{LL(0x16205f2a,0xd945a28b),LL(0xabadde7a,0xfe9112a7),LL(0x2bbf97c2,0x7db6c5ee),LL(0xb5b54833,0x3eb84a8f)}, {LL(0x273007d9,0x9732a49f),LL(0xc6a2e3ef,0xe61431c0),LL(0x10a101da,0x88aa1a06),LL(0xb972cc61,0x64b94de3)}}, {{LL(0xf8402027,0xe79eb6aa),LL(0xea6e7157,0xbb1fa5e3),LL(0x4ebdbe4b,0x457f33a2),LL(0x7a61b393,0xf4e955e0)}, {LL(0x698d37cf,0x578e2e64),LL(0x82ecbb69,0xbb139e23),LL(0xcfe8d05f,0x268d0291),LL(0x625fa854,0x7dcfef41)}}, {{LL(0x9c4da5e3,0xe21d5b8f),LL(0x10bf3df1,0xb5e22209),LL(0x437bf2c6,0xb04dd106),LL(0x1d055404,0x807c5d04)}, {LL(0x2c06fd15,0x6e983206),LL(0xed63ea25,0x773450af),LL(0x95c8dca3,0xc2dae106),LL(0xd82229e8,0x5323f6ba)}}, {{LL(0x57c062bb,0x647fabee),LL(0xcd5210ac,0xcd6adee7),LL(0x181f674f,0x11b4df3b),LL(0xf2a92b48,0x4e23bf4e)}, {LL(0x84a83d6f,0xeea34e2e),LL(0x9cb197e5,0xeaa09d51),LL(0x845e5008,0x7f36a278),LL(0x1581c0ab,0x41fa9b52)}}, {{LL(0x23d1206a,0x58917f67),LL(0x11062b8d,0xc04601ce),LL(0xf31f7326,0xdcc60fb6),LL(0x4b071708,0xc5aeef46)}, {LL(0xdc6939eb,0x5364069e),LL(0x034a1052,0x44bd15a2),LL(0x62a307fe,0x8177eeb1),LL(0x1907ad16,0x451ae4e7)}}, {{LL(0x27eb3193,0x80e49544),LL(0xaf88f4c9,0xd788e57a),LL(0xd944e00a,0xf062c60f),LL(0xeb4a609f,0x504463e6)}, {LL(0x74f13c8b,0x3593ad20),LL(0xc50bce88,0xdc7c5a35),LL(0xb657d1f9,0xa6336115),LL(0x591425ef,0x18d14e5d)}}, {{LL(0x1454f76e,0x73896725),LL(0x425c87a9,0x52772de4),LL(0xc6efb7d6,0xe59e4516),LL(0xd76bbc11,0xdddb8bf3)}, {LL(0xc6fd2066,0x1acbebd9),LL(0x1d7082ea,0x88c3b525),LL(0x6d69cea3,0x6a3b3d62),LL(0x8d065405,0xdbf73dfa)}}, {{LL(0x4a7bd06e,0xd659c8d6),LL(0x7bd10bb0,0x67867520),LL(0x97838647,0x7c4e3be5),LL(0xc5891864,0x545c7144)}, {LL(0xfa78d62c,0xf64e1031),LL(0xfa71692b,0x1f046593),LL(0x71310c47,0xd35a9cb7),LL(0x0ea84922,0x10911b96)}}, {{LL(0x93a9f5ac,0x5647310d),LL(0x6c05eedb,0xa6785861),LL(0x43950b68,0x2f5aa7c8),LL(0xa9d03b3a,0x57580907)}, {LL(0x42e15fe3,0xd581049b),LL(0x916c4e88,0x55dcf9d2),LL(0x27d1a183,0x87ebfd13),LL(0xf5aaa51e,0x13aee909)}}, {{LL(0x3b9fc03e,0xa651959d),LL(0x98997a74,0x05c28772),LL(0xae2e4a65,0x73e047f4),LL(0x783aa072,0x359e6c45)}, {LL(0x7a04b710,0x1124e9f0),LL(0x6d2053f2,0xd35094de),LL(0x2575dab0,0x0d57d976),LL(0x69171229,0x822256fc)}}, {{LL(0x3d19de1c,0xbd46937a),LL(0x6f0be84d,0x71feede4),LL(0x7c4dc4b3,0xca205366),LL(0xe3e851cb,0xfbb97d0d)}, {LL(0x2066e9a4,0x0270b5ea),LL(0x42ae150b,0xeade87ff),LL(0x8eb1bafa,0x9a7f9e81),LL(0x0eb5f68e,0xcb374aaf)}}, {{LL(0xd5525ab2,0xa5841c9a),LL(0x03e02cd0,0x3eed9ba8),LL(0x279fca98,0x29449bca),LL(0x3f450c92,0x4990ec0f)}, {LL(0xbecbba58,0xa241a8e3),LL(0x2eb47817,0xd0e2487c),LL(0x8300837d,0x6db7d420),LL(0x2d7f59ef,0x78872895)}}, {{LL(0x1314fc73,0x1b3d5033),LL(0xe710aded,0x2cf4cd42),LL(0x6f4026b7,0x9159bc5d),LL(0x2e62cc45,0x403f947b)}, {LL(0x47d97843,0x18d6ac70),LL(0x0694f7eb,0x69d5faaa),LL(0x6932e0f0,0x7711535c),LL(0x6ebd1488,0xc85c9616)}}, {{LL(0xd3542212,0x558e3750),LL(0x02921066,0x21fe02d7),LL(0x46b90554,0x1636a1a2),LL(0x0108cc04,0x8acf01ed)}, {LL(0xb4d60d37,0x57a2b16a),LL(0x91f4fdb4,0x3301a33b),LL(0x8e09b548,0x70dc3d3a),LL(0x079c0c2f,0x35ae7d07)}}, {{LL(0x978f92cc,0x95792f06),LL(0x23196752,0xb11574d3),LL(0xb8cfcac1,0xc3249711),LL(0xcf93af67,0x2061c767)}, {LL(0x2f63dbe7,0xeff09a1b),LL(0x48091edd,0x527776b6),LL(0x19bba5a9,0xf0fa985e),LL(0x66ae3221,0xc54f89f3)}}, }, /* digit=24 base_pwr=2^168 */ { {{LL(0x6a436476,0xbc5a6284),LL(0x35dbb9cb,0x6fcc2313),LL(0x5012ffbf,0xa77d2d9f),LL(0x4ae4bd14,0xcc25e9f4)}, {LL(0x1a5e40c6,0xd17fcfc4),LL(0xff085322,0x7d716a5f),LL(0xee3077c4,0x9dcbc50b),LL(0xdb4a6e61,0xebfe953c)}}, {{LL(0xd3d777d7,0xe7e66f2f),LL(0xcf1a6b09,0x3519dc64),LL(0xdbf88dcf,0x0df07beb),LL(0xacd4e105,0x17b09654)}, {LL(0x4e70c783,0xcbd7acd0),LL(0x96b9d577,0xda66e747),LL(0xe3e52f8a,0x6d0488a1),LL(0x6ff71c1b,0x3ec0fd11)}}, {{LL(0xbe4f2782,0x75474cb6),LL(0x41c2c0cd,0x10ef5e6b),LL(0x6a65e29c,0x592c6b06),LL(0xd12d0608,0x4d424662)}, {LL(0xb1a714fe,0xf5280949),LL(0x1199f802,0x52697bcc),LL(0xe6a4ff3a,0xc68ba4f8),LL(0x351849ce,0x25a5380f)}}, {{LL(0x573ec6f5,0x33207f69),LL(0x67bd2e8b,0x7ecc4bbe),LL(0x8ffe2420,0xa07acd34),LL(0xa13f9cdd,0x0a957eb8)}, {LL(0x9ec9c0c5,0x0bc7f95b),LL(0x6a8578cd,0xd82147cc),LL(0x9e61923c,0x07a2e7c5),LL(0x32e83f25,0x591eb066)}}, {{LL(0x957c94fa,0xaaa61588),LL(0x364911fb,0x6a2bc707),LL(0xc4907b19,0x09771450),LL(0x9694ccc4,0x4cc48773)}, {LL(0x50c878ac,0x9db6216e),LL(0x6f3031f1,0x6e89210c),LL(0xced0d41e,0xb711dcbf),LL(0x0fbf9751,0xe39bfe3e)}}, {{LL(0x764636b5,0x18fd7a45),LL(0xb75d48f3,0xe437ee86),LL(0x60a80177,0xe323bb18),LL(0xbc94c0ea,0xedc3c8f3)}, {LL(0xec8cb0cf,0xd8351164),LL(0x2472936d,0xccdd8829),LL(0x58059756,0xa8db1b85),LL(0xd55c184a,0x4eda8cf8)}}, {{LL(0x2923b8cb,0xdfb5727d),LL(0xe6773d5e,0x6e793e5c),LL(0xa0641165,0x8ecc901b),LL(0xd6da5095,0x6077ab26)}, {LL(0x6b127d9d,0x00669b0c),LL(0xd63e2e1f,0x8140e4e0),LL(0x9641b6a2,0x1ad5b03c),LL(0x9baed7b0,0x44299f88)}}, {{LL(0x1ea4a056,0x1736296d),LL(0xd77811ba,0x6f74702c),LL(0x432dd74b,0x5c927548),LL(0xe7a194ab,0x9cc73271)}, {LL(0xd6328dca,0x0f035ede),LL(0x28db755e,0x5292aa39),LL(0xa0192a4a,0xb5488385),LL(0xdfc6895c,0x6e7d2fa8)}}, {{LL(0x5d8bbec9,0xfa912a0a),LL(0x0087edb3,0x7051140a),LL(0x64865e5b,0x5293672b),LL(0xc82c48d5,0x6e8448c9)}, {LL(0xa2c437b3,0xeece41cb),LL(0x21ce1ef4,0x148967d2),LL(0x6b05c2a5,0xf14391fa),LL(0x8fed2f1f,0x15ff5fc9)}}, {{LL(0x4557b49f,0x18ae5e74),LL(0x3db266b2,0xe33760c6),LL(0xb1b249b5,0xd5d830c7),LL(0xc5fff531,0x24c665b9)}, {LL(0xc57df7c0,0x6b304406),LL(0xc3958e89,0x59706667),LL(0x790a5483,0xbf590ff2),LL(0x5ce77aaa,0xbcaea5a5)}}, {{LL(0x80ceb559,0x8578a002),LL(0xd8d61946,0x3639aadf),LL(0xadd3bb00,0x3fd52d94),LL(0xe09a8ce3,0x16c27846)}, {LL(0x294c7967,0x75cfd6c6),LL(0x59195034,0xfb9b7f37),LL(0xaa972a86,0xae687a99),LL(0xebd2394e,0x04bdefdb)}}, {{LL(0x2f96144d,0x8e245a19),LL(0x3b61e5ab,0xc740d348),LL(0x293ddb25,0x8703710e),LL(0x2bbf8f63,0xf4bb6ac0)}, {LL(0xde3b5805,0x86396457),LL(0x65d29e63,0x607022db),LL(0xcc930fe3,0xad0a0cdc),LL(0x1626abf6,0xd9997ebb)}}, {{LL(0x2a510565,0x2d872d17),LL(0x0357ba07,0x3e682079),LL(0xebfaf203,0x49edd962),LL(0xf81eda20,0x3a13edfb)}, {LL(0x7a75f2d5,0x87b5b5e1),LL(0xddfd9511,0xf04de2b8),LL(0xcfc5c5ff,0xf29a1569),LL(0x07160ed3,0xa3995532)}}, {{LL(0xcb2b061b,0xb6247469),LL(0x2f10fe1e,0xe75c5351),LL(0xd20e1bf7,0xbaf44963),LL(0x2d93babf,0x216cb6ab)}, {LL(0xf5109e45,0x7e0b655c),LL(0x6657450d,0xdcc712fc),LL(0xd51fc733,0xe06c408e),LL(0xed9c0912,0x85b11f96)}}, {{LL(0x37365c9b,0x954cb91c),LL(0xb2f74fe7,0xe0eaa047),LL(0x15716541,0x9af74b86),LL(0xf73dc7bd,0x4da06207)}, {LL(0xe07890a1,0xdb0d089e),LL(0x73902f91,0x5bf09681),LL(0xa897f0fe,0x14e1710c),LL(0x3605b1c2,0x191ec9a1)}}, {{LL(0x0133903b,0x271b2e2a),LL(0xe495ee32,0x5b3686f2),LL(0x0c991f28,0x89bcc974),LL(0x34f93b8a,0xadd20cce)}, {LL(0x680b65b6,0x5f5a1768),LL(0xaad41c40,0x0c453ab8),LL(0xa7fb4269,0xd479630f),LL(0x52c4e929,0x60039d01)}}, {{LL(0xff860883,0x0d8d112c),LL(0x723c6e29,0xe1dce5c9),LL(0x191ad70e,0xc19eadae),LL(0x62ce0e64,0x4af8194d)}, {LL(0xcc81415c,0xf207bfb0),LL(0x008495c8,0x3ab92f3b),LL(0xfdb9534b,0xe7250e17),LL(0x6c0c1d1c,0xba67e9b8)}}, {{LL(0x072c793f,0x117ae3ff),LL(0x9fb3091e,0x5243e6ea),LL(0x31a59e39,0xf93ad514),LL(0xc93c1891,0x8ce9cfb0)}, {LL(0x1ed08b0e,0xbfcbf901),LL(0xb53d687d,0x4d13cf2a),LL(0x5d81e4ad,0x25aa82db),LL(0x63c3cb41,0xd12f01f5)}}, {{LL(0xf8d1333a,0x1e799084),LL(0x653bcd0a,0x30c96c55),LL(0x44b5195c,0x9cf130fd),LL(0x13c77763,0x4cffc531)}, {LL(0x9430619f,0x082287f8),LL(0xb08ce0d9,0x78bb037d),LL(0x3affe8e8,0x2e69d512),LL(0xba9ec693,0xe9dbb263)}}, {{LL(0x62f132b5,0x67b66ad8),LL(0xbeb47184,0x70318d2b),LL(0xf50a0e98,0x46c429ea),LL(0xe2b3542c,0xd7e32eba)}, {LL(0xe096b4b7,0x625c1ce9),LL(0x389fd4dd,0x09221351),LL(0xfb0ee85a,0x08dc02d2),LL(0x853cd901,0x98c0ba7d)}}, {{LL(0x0deb1d99,0x88a0cd6d),LL(0x79a6b90c,0x989e4962),LL(0x24dd89d5,0xf5d19b95),LL(0xb37cf19e,0x189e5230)}, {LL(0xb0c5fefa,0x84a607b8),LL(0xd8c7fbd1,0xe48450c9),LL(0x46479ad7,0x178f9b56),LL(0xcbcd2ae5,0x7d6a36c6)}}, {{LL(0x71ae6516,0x95a4d51f),LL(0x566e2171,0x0363349f),LL(0xed1f2fc7,0x4d4bb4b0),LL(0xf10fa10c,0xde435aaf)}, {LL(0xb76e3b6e,0x711258a9),LL(0x2792e0b3,0x9a640eeb),LL(0x5fab8617,0x7953ead8),LL(0xdd64702a,0xd4b6d248)}}, {{LL(0x2d672209,0x95bbe528),LL(0xb6926b8a,0xfcc53cfc),LL(0x57659f87,0x05814190),LL(0x08d25069,0x4836e93b)}, {LL(0x6a5ad81e,0xd1eb2006),LL(0xaf0d37f8,0x4bee145a),LL(0xd31ce6cb,0xd44362ad),LL(0x936c1060,0xdc03e581)}}, {{LL(0x16fcb889,0x13cffce9),LL(0xac7e709a,0xed7e6683),LL(0x5896e541,0xb655d098),LL(0xb92a6204,0x07124356)}, {LL(0xa8f50043,0xa2ae43c8),LL(0x68731891,0xeb39255c),LL(0x3d9c408b,0xe07be0ad),LL(0x0b4f5c3a,0x0db7904f)}}, {{LL(0x4d70bb81,0x7ddc0235),LL(0x5347797a,0xe3b323c3),LL(0x3536deee,0x3536cd9d),LL(0x001bfd25,0x579b6894)}, {LL(0xebe2922e,0x58ad5301),LL(0x92a88d43,0xe0aa2cae),LL(0x4409e205,0x24567a3b),LL(0x2258f0cb,0x3cece61a)}}, {{LL(0x3babf4f6,0x8da5cf46),LL(0x81fff8e6,0xb37428d9),LL(0x48495d23,0xcda1ff77),LL(0x34f392ad,0x98f9208f)}, {LL(0x5bc88514,0x931f5b37),LL(0xcb375921,0xd49971be),LL(0xb5c01fab,0x9dcd4986),LL(0xc1ab1c94,0xcc26ec02)}}, {{LL(0xb4b874d6,0x34e8087d),LL(0x9d0a3761,0x224fc277),LL(0x3f7e5159,0xacc1f258),LL(0x8966d593,0xc82d71ec)}, {LL(0x7dcd691a,0x5b1f9f40),LL(0xba28f416,0xd8fafdae),LL(0x43b6d90f,0xe8622ae6),LL(0x9ec71d5b,0xec13fce7)}}, {{LL(0xfd2e8214,0x07b6aeb8),LL(0x4cbc297a,0x813e718e),LL(0x81fd6931,0xfac0dfab),LL(0x3c48ffd7,0xa1fe8821)}, {LL(0x85e03c08,0xd2715c18),LL(0x977c57f0,0xb6e4418a),LL(0x73418cde,0xfaa79ea4),LL(0x171e2a89,0x6ab8c25b)}}, {{LL(0x4ec7cf05,0x2800445c),LL(0xb66c6200,0x8e74a7b0),LL(0x481db950,0x081b1177),LL(0xb89f7c02,0x526d051c)}, {LL(0x5c29c905,0x3c830942),LL(0x44c15ce5,0xbfbd9e3e),LL(0xa29472e6,0x6055c949),LL(0xa37c4912,0xab0010c7)}}, {{LL(0x5b7d3647,0xeb8492be),LL(0x1ee31caf,0x0b4cfd7b),LL(0x4b46304b,0x81cfcde2),LL(0xc554a5bc,0x968df75d)}, {LL(0x8d0e043c,0x7ce78806),LL(0x345ea27c,0x1e896819),LL(0x6e287603,0xe040c19c),LL(0x138e8ece,0xa581856f)}}, {{LL(0xc354a9d6,0xe49f6558),LL(0xc0cfb2d3,0xc4ad763a),LL(0x1b76b8f3,0x4be2143b),LL(0xd0ad0247,0xa8caae14)}, {LL(0x928b0ae5,0xcfe96bd5),LL(0x7724f8e4,0xcf5051f7),LL(0xec4af64a,0x9128916f),LL(0xcb437bfb,0xc211ff4b)}}, {{LL(0xbce59c0f,0xee6e8134),LL(0xd59f7f86,0x3d068b4c),LL(0x96283457,0xafa2753c),LL(0x1aedcbf0,0x453fe33c)}, {LL(0x483c0b1a,0x781294c8),LL(0x5c2ad1ee,0x9e6f5133),LL(0x69383e0b,0x2a77b6ce),LL(0xfa9f0142,0xcb5a83ab)}}, {{LL(0x3b0e027f,0x2318aa98),LL(0xc2c68dd5,0xdea716a3),LL(0x9f548eb3,0x3f75c46d),LL(0x96120de9,0x71642513)}, {LL(0xdbee488e,0xf733614c),LL(0xaad077f4,0xdf940026),LL(0x94a840cb,0xeda9c098),LL(0x393be3b9,0x5108bf0b)}}, {{LL(0x39980cee,0x137c08b0),LL(0x0839112b,0x2e31bba0),LL(0xba614ea3,0x9ec73de2),LL(0xd17822c0,0xd0bca8d4)}, {LL(0x50b7805d,0x5d9f7482),LL(0x298becf6,0x16035a80),LL(0xd7c318e7,0x46571500),LL(0xd0ee6956,0x6bd30919)}}, {{LL(0xb2e13320,0x5c0ad747),LL(0xda47666d,0xe7f7f71e),LL(0x318a8e8e,0xce322037),LL(0xe9f84dd6,0xf15232ae)}, {LL(0x915a03b7,0xc59709c5),LL(0x9a3040b4,0x2e2000f7),LL(0x8398a5a9,0x41955f77),LL(0x7086b69e,0xa8e6620e)}}, {{LL(0x8344224b,0x63acd70e),LL(0xc3145159,0x966efefc),LL(0xf5e0f955,0x406619ec),LL(0xec6de618,0xedd0efc9)}, {LL(0xb2580ed4,0x6fe3e34e),LL(0x4139b95e,0x9d8875b5),LL(0x8e5be187,0x85baf0c1),LL(0x09553886,0x549cefca)}}, {{LL(0xae9ef2cc,0xc965b2a2),LL(0x15afee63,0xd43079fb),LL(0x076cdb05,0x02b8794a),LL(0xa0d1a953,0xd0ae7321)}, {LL(0x2ac5fff0,0x5a8b5281),LL(0xcdda362d,0x73437d67),LL(0x1a95ff87,0x1866b2b9),LL(0x0420b3e1,0x5ff11398)}}, {{LL(0x92284adf,0x0d43b92c),LL(0x4da4c4a7,0x81425367),LL(0xdf17641a,0xc8093c56),LL(0xb5ccd14d,0xc418f19d)}, {LL(0x506762ed,0xaad98608),LL(0xddb2c829,0xb6f45297),LL(0xd395692a,0xd0e49176),LL(0x3b1073d3,0xc05b4e27)}}, {{LL(0xe5808e53,0xe8ca133b),LL(0x06a64b56,0x6105cd0e),LL(0x53cf6d7e,0x89a64669),LL(0x1bebfea5,0xe281ca2d)}, {LL(0x324b25d8,0x98ee67ac),LL(0xdca154ec,0x2227631f),LL(0x4406e8ba,0xa242c5a1),LL(0x49250026,0xced39f05)}}, {{LL(0xdd77d731,0xd256dd83),LL(0x7414d0c0,0x2faa6a0e),LL(0x3b90f004,0xa2e0f928),LL(0x8719bfd4,0x019bb3ef)}, {LL(0xe2d515c2,0x3f4f6109),LL(0xbf88d7a6,0xb50a9907),LL(0x015ac4de,0x8e5fbc2d),LL(0xe78a2117,0x96992421)}}, {{LL(0x26e53df3,0x321e6086),LL(0xf42b2508,0x07eb1d15),LL(0x0ef22bc2,0x7b552108),LL(0x00f3e571,0x9eedb828)}, {LL(0x6f0e883c,0x556abbaf),LL(0x40473ead,0x8025770b),LL(0x6ece1cc8,0x2fdab965),LL(0x00ec1adc,0xba07cf89)}}, {{LL(0x4be5ad18,0xefec4deb),LL(0xd59fa732,0x16625be8),LL(0x6808cdf7,0xffee542e),LL(0xd7a9f29b,0x85c19ef3)}, {LL(0x82dc1ae3,0xca4ac1f9),LL(0xca5e8f58,0xa6c726d1),LL(0x66960edd,0x0bcc3d58),LL(0x56f94ea8,0x8e8445d0)}}, {{LL(0x938e64c9,0xd4d0177b),LL(0xf9a0288f,0x8d0199f1),LL(0x14a226c0,0x9176d559),LL(0xa00aea02,0x13b373ee)}, {LL(0x6b629fea,0xc63b2d79),LL(0xa7e0cc42,0x36df7c09),LL(0x40bdbc8e,0x4628ba4f),LL(0x0de296f2,0x7f5b0228)}}, {{LL(0x3c63d73f,0xb0598130),LL(0x0431550e,0x55e59f61),LL(0x6693eb8c,0x6f2e109d),LL(0x470b10fe,0x3602ba82)}, {LL(0x5ec7f357,0x3acd0af4),LL(0xb071c758,0xfa7479f4),LL(0xe13652c9,0xbf47caa0),LL(0xf5f5eca9,0x6fa139bb)}}, {{LL(0x8c0e197e,0xfa149b84),LL(0x60ae7755,0xca31714c),LL(0x8ccc4241,0x934ed1af),LL(0x781a024e,0x39772769)}, {LL(0xbe24eb34,0x9f07dfb1),LL(0x0a3dac06,0xfa8a9c60),LL(0x8e410ce7,0x08fbbe21),LL(0x396a9702,0xea55fb96)}}, {{LL(0xf18882bb,0x4422bc58),LL(0x0ddd0dd7,0x1ccb7b47),LL(0xf40ea941,0x828580a8),LL(0x0db78350,0xf9ec9728)}, {LL(0x1612f28a,0x2823b4fd),LL(0x82b26487,0x96dc3e29),LL(0x2497420a,0x1740fdae),LL(0x322f1c6f,0x3bb39dfa)}}, {{LL(0x4cb19878,0xf32a21e6),LL(0x9277c80b,0xeac04097),LL(0x13380801,0x67178d8f),LL(0x34bf8872,0xfe5e2694)}, {LL(0x327129d3,0x8278bad4),LL(0x941c4e5c,0xb42a3f9b),LL(0x39de36f0,0x04eefb7d),LL(0x8d967703,0xed2aab7f)}}, {{LL(0x72aa1c89,0xa3283a2c),LL(0x2a4d513e,0x1969613e),LL(0xddd5ea18,0x0d4c0347),LL(0x43cee5fe,0xbbad9ce4)}, {LL(0x57313b49,0xe8c050a8),LL(0xff09bf31,0x3b91c3cc),LL(0x610395cb,0xe6e5ab6d),LL(0xdeb31bef,0xfc36cde0)}}, {{LL(0x5d43c8a7,0x76f806f2),LL(0x63b7c746,0x08a64cb2),LL(0x45256a2a,0xb6cdcdab),LL(0x9bebae90,0x640f67ea)}, {LL(0xcf016971,0x682eeeb6),LL(0x50f59261,0x4d16d566),LL(0xf41db99d,0xdaca66bb),LL(0xf8f04d96,0xccdb3da0)}}, {{LL(0xcf41b164,0x7c228cae),LL(0xedbefa7c,0x40bef27f),LL(0xecb43685,0x4efdd6c2),LL(0xa834a50b,0x4d0fa367)}, {LL(0xb87f7ec7,0x2ec9c445),LL(0x23170d0f,0xc3663ced),LL(0xc5b47b29,0x189872e4),LL(0x746d6a13,0xf8047387)}}, {{LL(0xb75ac898,0x753837d3),LL(0x91959a78,0xaee88a60),LL(0xe6f59621,0xf46b0f6e),LL(0x10d981c8,0x0e92e271)}, {LL(0x8d578b6d,0x610d0f80),LL(0xb4d9b9de,0x962bd7bb),LL(0x84a0c394,0xbe26960d),LL(0x3b5bd996,0x142a0c75)}}, {{LL(0x0be95497,0x442bb39a),LL(0x0f33c9de,0xce5d2c60),LL(0x283dc751,0x1ce0d08c),LL(0x79b3c1a8,0x106ed588)}, {LL(0x7f8ee4d7,0x4b2e29c6),LL(0x08bbd660,0x7d61e3bb),LL(0x1e964a3e,0x11504dc5),LL(0xc77a957a,0x31544a52)}}, {{LL(0xcd7d0dac,0x1fc4161e),LL(0x370c15c9,0x83733f27),LL(0x853758cc,0x224976de),LL(0x47c1ab78,0x1bbb7730)}, {LL(0x19c89029,0x94a3b697),LL(0x37dfc44f,0x031432f0),LL(0xd88090cb,0xf84593ac),LL(0x65bcfee8,0x381b51bc)}}, {{LL(0x10b412b7,0x38dac75b),LL(0xc7e06d08,0x6df5c9a1),LL(0x0e08c41c,0x9c6d8068),LL(0xc3600f4f,0x1544e3c5)}, {LL(0x9c83e0a1,0xf827a48d),LL(0x06bcb3c4,0xd8539228),LL(0x6268cf12,0x149862b3),LL(0x6ec4e354,0x4829ee56)}}, {{LL(0xb712a1f9,0x44b2c3bf),LL(0xc90852af,0xe556b78a),LL(0x906a13b6,0x50f6de2e),LL(0x568a1293,0x1744efd5)}, {LL(0x2b5745a1,0x942ad99e),LL(0xca362913,0x0f100bd9),LL(0x91e96cde,0xd9b6ad51),LL(0x5a2f88e9,0x4aa440bc)}}, {{LL(0x57a10070,0x53c4c956),LL(0xae6e4872,0x7d1be72e),LL(0xd427eda4,0xb704009c),LL(0x5f39b7d8,0x3e0aa93f)}, {LL(0x3153a757,0xdea1ab48),LL(0x9ee60ead,0x10a070e7),LL(0xe6c916bf,0xd6a6e92d),LL(0xbd7bb216,0x02b1e0e6)}}, {{LL(0xb49138a3,0x6efb5f1b),LL(0xe88d2db0,0x11f7a9be),LL(0x3233df5b,0x0b9a2b11),LL(0x1824fcc5,0x0688afda)}, {LL(0x5ff97f9a,0xcf1ea2a5),LL(0x4998e602,0xe8ad7b15),LL(0xa455aad1,0xdb4ae67e),LL(0x74a27ff3,0x823ac090)}}, {{LL(0x2573443f,0x5c431060),LL(0x94258714,0x92f9f9ab),LL(0xb1283d2e,0x1548fe21),LL(0x5c5be5f9,0xf86fe50b)}, {LL(0x520c5fc6,0xd20dfc8a),LL(0x53b5e7c5,0x6e721dd9),LL(0x8f2a8969,0x8ef7eee5),LL(0x62d07bdf,0xe894859f)}}, {{LL(0x1cfc6627,0xaf279176),LL(0x483755e9,0x94b8cff4),LL(0x0fda4bcb,0xa5916f70),LL(0x47ba65f3,0x9c5318d0)}, {LL(0x636cd7e3,0x9e9c8e54),LL(0x54c49da3,0x5c64a261),LL(0x690e932c,0x04d7ff61),LL(0xc84b0b78,0x92a357b3)}}, {{LL(0xc6f3bd8d,0x47f6144c),LL(0x71c19265,0xdf7b1ee4),LL(0x3fd5c30f,0xa7ea37f1),LL(0x79fa08cf,0xdc2d890b)}, {LL(0x2fd40236,0x9813bced),LL(0x432dde17,0xa8a1055f),LL(0x7772c727,0x70011f47),LL(0x2e2e802f,0x965c130a)}}, {{LL(0xf5bd4ac5,0x31a6aca7),LL(0xd825db6f,0x83995bde),LL(0xfe521833,0xcbf20325),LL(0x0278f4a0,0x8dcd25a1)}, {LL(0x5f2293ea,0xf1e83d97),LL(0x52317ad3,0x1717876b),LL(0x14181928,0x0df62167),LL(0x2fe203ce,0x24adfd6e)}}, {{LL(0x797f25ff,0x1d264af0),LL(0xd22e3da1,0x2cb7cc17),LL(0xe0016a19,0x10c4b51a),LL(0xd82b2a86,0x5956ce8f)}, {LL(0xa3d4780e,0xdef0fefc),LL(0x6e92b93a,0x97e693ab),LL(0x20bcc98f,0x8fa3f4fa),LL(0xf9182867,0x4fc004f1)}}, {{LL(0x93e73961,0x1a206da3),LL(0x1e7db32c,0x37d75a90),LL(0x0455b815,0xa39f0db1),LL(0xb69ee770,0x841646e0)}, {LL(0x0939f065,0xadb0aaaa),LL(0x0b147d7a,0x5608613b),LL(0x470f6875,0x84ce1a4c),LL(0x7983050e,0x501de5fe)}}, {{LL(0xc3d8ed98,0x19915b26),LL(0x9a66a6e5,0xf451e57a),LL(0x30dab6a3,0x29843607),LL(0x3d1a1ebb,0x1710267c)}, {LL(0xe11d88c0,0xce4ecfd4),LL(0x11ce026a,0x12fc2787),LL(0x691227de,0x9801cecd),LL(0x76ce6dae,0x517a92f3)}}, }, /* digit=25 base_pwr=2^175 */ { {{LL(0x648c48e5,0x821b0fdf),LL(0x9f45a433,0x689e6d56),LL(0x2e572855,0xa5a9dca8),LL(0x8adfb547,0xb0f07eb7)}, {LL(0x552c8d55,0x48ecb166),LL(0xce854171,0xfe3fc268),LL(0xeeee9bc0,0x323af5eb),LL(0x41ae1c80,0x0666a2a3)}}, {{LL(0x9ff262fb,0xa06d20bc),LL(0xd075868b,0xcba032fd),LL(0x943fd973,0x70376026),LL(0xe35c5e02,0x81c57cba)}, {LL(0xba871f1b,0x1964e700),LL(0x6b265f57,0xf03a8c04),LL(0x0b950259,0xc8ebc912),LL(0xad32ca8b,0xd2b0ee30)}}, {{LL(0x89c8e719,0xe01bf0c2),LL(0xb2f4cdb0,0xbce1e20f),LL(0xa1053ca5,0x8c38eeaf),LL(0x7cd633a5,0x8c2d85ef)}, {LL(0x9b53cdb1,0x75695364),LL(0x447eb1a5,0x5e999741),LL(0xdbd88626,0x6d6b2d88),LL(0x21876357,0x87eaf045)}}, {{LL(0xdeec441e,0x2c88f1ff),LL(0xd01b2157,0xab52096b),LL(0x6c45cf5c,0x37eee275),LL(0x0520ecaa,0xa070d24e)}, {LL(0x546b9fd3,0x61d15bd1),LL(0x2c96db1c,0x3276fb74),LL(0xb95b29b7,0xc5c1b041),LL(0xbd7d3254,0xe18008db)}}, {{LL(0x98dfb69a,0xd56ae44f),LL(0x609d941c,0xd5f66b0b),LL(0xb91b5245,0xca6b6d35),LL(0x7b3f98a6,0x98e3a4e3)}, {LL(0xf358c56a,0x0715dfa6),LL(0x36a66c64,0x3b02ff21),LL(0xcb22cbd3,0x737b1401),LL(0x6b8e9624,0x9dd15f5b)}}, {{LL(0xd360d017,0x25f5a71d),LL(0x29b0ed73,0x4c0779b5),LL(0x9825a018,0xc662fedc),LL(0x61d4add0,0xeee89125)}, {LL(0x92163d14,0x1543814d),LL(0x27370d3c,0x79f2376f),LL(0xcbe1af7a,0xf80c6963),LL(0xeb9e41f7,0xf2d521bc)}}, {{LL(0xc1805864,0xe241619f),LL(0xb2de204a,0x6f1d6166),LL(0x50e68d0b,0x13c3f912),LL(0xc4a24f5a,0x32eb021d)}, {LL(0x0e78c588,0x3f1452f5),LL(0xc9971e98,0xa267bf19),LL(0xe801c021,0x77a231a7),LL(0xc2666e80,0xf363c9b3)}}, {{LL(0xae309a0a,0xb8eb0bf0),LL(0x375b8fbc,0xa9f52f58),LL(0x1a4993b7,0xb8e4f948),LL(0x8f73c292,0x50ce578e)}, {LL(0x02e503d6,0x2437a4a6),LL(0xe4c68ea3,0x20cdfc50),LL(0x3616f348,0xfec5993b),LL(0xc0c420df,0x5d96b4c5)}}, {{LL(0xcca0c48a,0x6b71cdf0),LL(0xc1aea033,0x00e71b54),LL(0x69f6d107,0x247f5baa),LL(0x050c3704,0x4e3ec504)}, {LL(0x7a438e93,0xf2b2be8a),LL(0xa331e01e,0x240b632d),LL(0x91150675,0x61e66557),LL(0x95a99a28,0x32364134)}}, {{LL(0xd3399e1e,0x5e5de136),LL(0xfe2f8b75,0xe38bab00),LL(0x3a77db29,0x736126de),LL(0xf2aa121e,0x7b0d1865)}, {LL(0xdecf9cde,0x5545e45e),LL(0x2318be70,0x9608ebce),LL(0xfa55b0e5,0xe6596006),LL(0xbc4b6ca0,0x0c8c2f41)}}, {{LL(0x92025945,0xda1c5c7a),LL(0x5d3b0775,0xb114ba22),LL(0xcedb69a0,0x11cc6888),LL(0x0f83c772,0x4365bea8)}, {LL(0xbda8dbe3,0x006fe80b),LL(0xc2d3d266,0x334adcb6),LL(0x1521de1c,0x8c92c084),LL(0x78d8f72c,0x57873ef9)}}, {{LL(0x3b64dcd7,0xcfb0a7d0),LL(0x558c9d55,0xf4c2f1fc),LL(0xa0fbc656,0x110c2db2),LL(0xef5b6bea,0x3cad85ca)}, {LL(0x4e0b1230,0x7099dd0e),LL(0x098a2fcd,0xc769b937),LL(0x1e1e7407,0x9209f550),LL(0x1ba7cb47,0x1b47255d)}}, {{LL(0x2c01b596,0xd8aed0cd),LL(0x30efcda3,0x1a1a2e11),LL(0x36b1a5b5,0xf771f93b),LL(0x14fcd251,0x2ea34e3d)}, {LL(0xfd893979,0x6895cb31),LL(0x14f556b4,0x10b1d2c9),LL(0x6430bfa8,0x835fdf7e),LL(0x24bf4ba5,0x1f4bbef5)}}, {{LL(0xd562b5f1,0xbc805aa5),LL(0x35dac658,0x7101b9da),LL(0xddc28e5a,0x5b7f211d),LL(0xd3d1cd0a,0xea89f24c)}, {LL(0x7567c80d,0xbaaa9ef5),LL(0x9a60c5ee,0xe0d1f26d),LL(0xab36cd64,0xc88a044c),LL(0x1b125de6,0xb8e03d02)}}, {{LL(0x3a707a66,0xda0c1047),LL(0x0c692d44,0x76ddb98f),LL(0xb15b7254,0xeccae586),LL(0xe7e82423,0xeadc1b51)}, {LL(0x7c3cb698,0xd6779ff2),LL(0xdf6e7da6,0x0e271cb4),LL(0x45900023,0xeacf34c3),LL(0x03da2ba5,0xafd017ad)}}, {{LL(0x27c7e6eb,0x49266998),LL(0x6625bc7f,0x84ffa372),LL(0x05c9cb15,0xedec9247),LL(0x8075b84e,0xcfad0b90)}, {LL(0xbc0898d3,0x94bed316),LL(0x11f92525,0x02481eec),LL(0x0d7e59d7,0x19896e1b),LL(0xf2bb3129,0xa06adb6c)}}, {{LL(0x62a0a690,0x1539228e),LL(0x8ae02bda,0x98ac50b9),LL(0xe5cf21b9,0xaf233c85),LL(0xd6a9f599,0x943348d3)}, {LL(0xdb363eaa,0xf5a2f2d1),LL(0x7a8ea96b,0xe917e2c5),LL(0xbf5c8293,0xc80b56c8),LL(0xcdbb5c4f,0xcfc1c24f)}}, {{LL(0xfbddf07b,0x7812dce2),LL(0x0186013a,0xd4af2f9b),LL(0x6fe8d485,0x1fadcd16),LL(0xc968f0b7,0xc3c2cd95)}, {LL(0x778bff58,0xdbdd2ef0),LL(0x8706da34,0x67369204),LL(0xb8e70e35,0x31cf3a66),LL(0xd333801f,0x0b9e5cc5)}}, {{LL(0xf7177c4a,0x1212a811),LL(0x2d379e12,0x9e266ec3),LL(0x2e8bbbf7,0xc7382848),LL(0xa973be5f,0x3f3f1dc1)}, {LL(0x786e727e,0x534d04de),LL(0x225497dc,0xfd7a5fbb),LL(0xb63b6320,0x3c03a7fd),LL(0x5dc76e05,0xe77f8985)}}, {{LL(0x265f8b8f,0xe8d14f32),LL(0xb90549c9,0xfeaab021),LL(0x081ccea6,0x7cd36751),LL(0x1f1e8f7a,0x7a001441)}, {LL(0x1fdfd622,0x2e87b8a2),LL(0x8bb4f812,0xe76138ce),LL(0x71e03be4,0x9a5e8722),LL(0x153e0a5f,0x795e60f3)}}, {{LL(0xd0eb7d4c,0x11d28438),LL(0x4254a845,0x147884e1),LL(0x2a8693fb,0x6795f20f),LL(0xee01bd1a,0x5a10d535)}, {LL(0x218c0513,0xe39982c9),LL(0x1d4e6ab5,0x6c23e5be),LL(0x0f424e7c,0x20a8c27f),LL(0x3bbb486f,0x74ae9998)}}, {{LL(0xb90ce3a1,0x3fae61be),LL(0x571c968b,0xf0f5a1e4),LL(0x7780d91b,0x6b9dded8),LL(0x7597e866,0x10f60ce2)}, {LL(0xf1eb7d1c,0xf268ed02),LL(0x6030bf9b,0xa49b5a46),LL(0x251f8676,0xc939c4e7),LL(0xe2b9928f,0xbdfe5036)}}, {{LL(0xbccf7f43,0x5abfbcc2),LL(0x28c560af,0xb22067b6),LL(0x04c6a2da,0xecf07771),LL(0x8c4ae7dc,0xa2bf88db)}, {LL(0x616675e8,0x172396f2),LL(0x8bfcfbc2,0x9abbb19c),LL(0xe85edd21,0x52e26c06),LL(0xa65de52f,0xfca4c4e0)}}, {{LL(0x281d58be,0x255e2d10),LL(0x3614ed6c,0x93ec2934),LL(0x6dc71abe,0x36d6cc15),LL(0xf592ae78,0xaa2ad1ef)}, {LL(0xcc9291fb,0x39a82740),LL(0x102600d8,0x6812b80f),LL(0x50c511d5,0x64f4843c),LL(0x03445793,0x28f5795e)}}, {{LL(0x29f20b0c,0x2c566372),LL(0x9e24474c,0xb168ca7a),LL(0xabe37949,0xfadd8f80),LL(0x4cd69856,0xafa1bea2)}, {LL(0x46713b88,0x5ce6ed80),LL(0x4b3bb84d,0xaf8b5fb3),LL(0x29d53349,0x134e5120),LL(0xcdcedefa,0x1214f4f0)}}, {{LL(0x4bb405b9,0xc346821b),LL(0xddd624d6,0x753afa86),LL(0xc7c014e3,0x15fe543c),LL(0x43d08964,0x6b3c0c5d)}, {LL(0x745221aa,0xc77c8fb0),LL(0x152995c9,0x3e144fce),LL(0xa61b96bc,0x57089907),LL(0x5e05c1ee,0xd19a912c)}}, {{LL(0xa6ddd20b,0x7bcdc697),LL(0x2d5090f3,0xcb07e229),LL(0xf089607e,0x76afc803),LL(0x637dae27,0x9f7a88b9)}, {LL(0x3bd20d78,0x1352d8bd),LL(0x5ea79d4c,0xede1a780),LL(0xf389e31d,0x59a8222b),LL(0x5c09f3d4,0xed066aa6)}}, {{LL(0x684529d3,0xade16197),LL(0x96a2a159,0x97bed904),LL(0x1b695d68,0xdd3da765),LL(0x02fecb9e,0xb8fa37e8)}, {LL(0xbc0f7b99,0x1af4311c),LL(0x2a492a7e,0x600bdd46),LL(0x45dc9d16,0x6aa9cb30),LL(0xc0b93019,0xaa494815)}}, {{LL(0xba052dd8,0x1211834b),LL(0x86822bf1,0xcdc0208e),LL(0x8c8362a0,0x515eebd4),LL(0x9b90cf96,0x9ea7b9f5)}, {LL(0x3a0a5a48,0x8418fe34),LL(0x331a2db1,0x654d3c32),LL(0xafde743c,0x22362ddf),LL(0x6f6ee3ba,0x617a89e8)}}, {{LL(0xb7deb988,0xed5f3d04),LL(0xbbc8a6b2,0x31c2c9e6),LL(0x81a3f184,0x8faa80e1),LL(0x51ecc548,0xa7183488)}, {LL(0xa3780d0a,0xe67512d0),LL(0x822db54d,0x9f868036),LL(0xe555beab,0x6c74490a),LL(0xd989d6be,0xe747e666)}}, {{LL(0xdf8cd308,0xf8346dd6),LL(0x4745cd8e,0xe7ca105f),LL(0x31055db8,0xee059c58),LL(0x18b38aa0,0x90f4053a)}, {LL(0x41081a21,0xbb2e7fc3),LL(0x45b33a71,0x3602525e),LL(0x2b411945,0xff21f2aa),LL(0x064ccb11,0xbeaadbd3)}}, {{LL(0xfe94629d,0xc35f6950),LL(0x9f860b15,0x1cbaa935),LL(0xf24f8f15,0x29b4bcd3),LL(0xd29c8458,0x0ae5b06a)}, {LL(0x1b6c2df1,0xa645c31d),LL(0xd804facc,0x640b0990),LL(0x122b33e6,0x7a4a7f59),LL(0x7479b828,0x94bb0b2b)}}, {{LL(0xc4cd4887,0x0567272a),LL(0xfc8e4b0b,0x676d6962),LL(0x8661c0c2,0xa712b020),LL(0x279454a7,0x660e6aff)}, {LL(0x1cd25bfd,0xe1295106),LL(0x077496a8,0x7096885c),LL(0x3006ab7b,0xdbc47c92),LL(0x509205f3,0x498761fa)}}, {{LL(0xe85ecfee,0x5d1eaeca),LL(0x534f38f5,0x9fcddeed),LL(0x8af32f70,0x4d34ec80),LL(0x24b3b4e3,0x476dffc9)}, {LL(0x8bbcda9f,0xb45cd869),LL(0xdf684c2d,0x3b0079e7),LL(0x765cd483,0xcaf3eeb5),LL(0x63945b62,0x0b9e25e6)}}, {{LL(0x06492e0a,0xfd73833e),LL(0x9507ea57,0x4d2937e1),LL(0xcf562953,0x3e532c2e),LL(0x81ca80c3,0xe4baa2d4)}, {LL(0x28d22139,0x4699e5c4),LL(0x6b1c665a,0x69aab900),LL(0x641016ac,0xf6a37330),LL(0x5f3b7c71,0x335f14cb)}}, {{LL(0xfacd904f,0x94a6c868),LL(0x2ec2bf99,0xb1127cc4),LL(0xa4b72d69,0x0ccfceb3),LL(0x55172f5b,0x16b786a3)}, {LL(0xe093a729,0x51ebe029),LL(0xc40c4487,0xf57f4a1e),LL(0xa8ed5a3d,0x8aaf0dd6),LL(0x811f35d6,0x617c51f7)}}, {{LL(0x11e98d29,0x18c7ac62),LL(0x2c904ea8,0x71c578c4),LL(0x3c4ef8bd,0x4626b0ad),LL(0xa390be8b,0x121eb676)}, {LL(0x154e297d,0xcb7249f5),LL(0xc2288ba0,0x678ad966),LL(0x57cc9cbc,0x3c2ab066),LL(0x80c8fbda,0xe32c1d45)}}, {{LL(0xf0b35526,0xd2f152cb),LL(0x13877dfb,0xc7f75fd4),LL(0xe83ca4a2,0x8603feff),LL(0xcd680589,0x6be89bb3)}, {LL(0x45e1f141,0x5650549e),LL(0xa55ffadc,0x7dab03b8),LL(0x2dc5d31f,0x342edda4),LL(0x9af8105a,0xa97451ac)}}, {{LL(0x705b8fd7,0x796e1fe3),LL(0x02d131b8,0x6252a7ba),LL(0x086c3099,0x3db2ab14),LL(0x9db0ce72,0xeb763df5)}, {LL(0x52b62fa5,0xe7b57bab),LL(0x88b820bd,0x6076d449),LL(0x1b660123,0xc43e1f61),LL(0x189eace5,0xc802d40b)}}, {{LL(0x341309a1,0x1f2a2a91),LL(0x414db96b,0x8680be67),LL(0xc846e288,0x65dd0396),LL(0xb0bbea85,0x8a1d871e)}, {LL(0x8ff931c6,0x623e2408),LL(0xe14c5941,0x4933ffda),LL(0xb2cbff67,0x72688986),LL(0x8cf79450,0xe51504d8)}}, {{LL(0xfeba1168,0x50cd0a3f),LL(0xcd833df8,0x08d2e0fe),LL(0x0a4370ed,0xdbd60827),LL(0x66f4f58d,0x010cf800)}, {LL(0x144e9656,0xffa29252),LL(0x9d1e9d61,0x90b896a2),LL(0x81f7b4d3,0x1802257c),LL(0x595612a5,0xd7758e8b)}}, {{LL(0x241b4dd2,0x751882d8),LL(0xfe177abe,0x7dae3003),LL(0xee6fe1cd,0x8f4d5dc4),LL(0xb08f625d,0x93a9cd5b)}, {LL(0xf91cc442,0xa4d6ee1a),LL(0x594d172f,0xe05976cd),LL(0x6e762b2e,0xfb4064c6),LL(0x51a0156d,0xb2068ad9)}}, {{LL(0x24f06e82,0x0d2d5b26),LL(0x8c85a9a9,0xad70f276),LL(0x0ed413cb,0x00ede5d5),LL(0x927064d2,0x245be28b)}, {LL(0x2af70d77,0x06eb2825),LL(0x52b0592b,0x472af630),LL(0xd881d50e,0x493afd98),LL(0x1189c989,0x56fa76a8)}}, {{LL(0xfaa974f7,0x775665d2),LL(0xc3f54eff,0xe395ccdb),LL(0x3fc83a7f,0xf0a40e4e),LL(0x4c00087a,0xc3b11d22)}, {LL(0xddb50678,0xef8d2f06),LL(0x6cd5f681,0x6e41f315),LL(0xa1b97891,0x7c9d7a3d),LL(0xa0a41260,0x8b297d75)}}, {{LL(0x3806a30a,0xca44b65c),LL(0x61a6206e,0x125c5702),LL(0x87003e1e,0x311842a2),LL(0x4513d726,0xe049a7d0)}, {LL(0x7b123469,0x8022c2d0),LL(0x86294393,0x76533934),LL(0x892e7bc4,0x6a6e84e7),LL(0xdb2007fe,0x7daf8b11)}}, {{LL(0x923e185c,0x092d1914),LL(0x3def87c2,0x5ec11237),LL(0x18742a51,0x38019e96),LL(0x4808ca10,0xe05ea79e)}, {LL(0x134cbf9b,0x1fc8ae26),LL(0x01b4c1c4,0x14054672),LL(0x64051972,0x32abf912),LL(0x1af62fca,0x0edaa925)}}, {{LL(0x3c47d01a,0x58fa82e2),LL(0x780762c6,0xdb12a452),LL(0xfdbf4683,0x16d5a733),LL(0x2f798deb,0x1d7e8507)}, {LL(0x9eab12f7,0x259aa9b9),LL(0x91261397,0xb13e6e41),LL(0x32602f2e,0x564706fa),LL(0x9c2283ef,0x50daef9c)}}, {{LL(0xf07a196e,0x9275f219),LL(0xbb8fcd35,0xfc58ebea),LL(0xbad69c11,0x5d1025f1),LL(0x1605c11b,0xcf364154)}, {LL(0x2992276c,0x427bd117),LL(0x6a73cbb3,0x5545bec5),LL(0x133f3266,0x86855c2f),LL(0x67d9e5b2,0xb3d753d1)}}, {{LL(0xc9fb343b,0x2134b384),LL(0xb0e12b7a,0xb572f5d6),LL(0x392d24fe,0x7ee5852f),LL(0xc4f285f9,0x73559fae)}, {LL(0x7711c525,0x269cb9e7),LL(0xf00d5606,0x4badfc52),LL(0xb465df15,0xef66d726),LL(0xaa4a301b,0x83eb59a3)}}, {{LL(0xed329b12,0xdb406469),LL(0xd933eb45,0x6eb95cc9),LL(0x6b638bdd,0xe2dabfa4),LL(0x031df114,0x7a5d0098)}, {LL(0x38dbfaaf,0xe22d8f3e),LL(0xd79d1ce1,0x2306fd54),LL(0x7acb7cce,0xda324535),LL(0x88f61a1e,0xde6fcc16)}}, {{LL(0xb730fe5c,0xaf3e4894),LL(0x28adf897,0x7a3e4a7d),LL(0xb160ae0e,0x352c0069),LL(0xee52c58a,0x225cfb67)}, {LL(0x96b2505f,0x12391b71),LL(0x3758141d,0x8d811bee),LL(0x8cd82e11,0xc941524d),LL(0xbb83a251,0x0feb26a5)}}, {{LL(0x76da8411,0x60ad0665),LL(0x88d4a968,0xe3c033d9),LL(0xde120078,0x767b3c05),LL(0x9f31e1e8,0xab7da95a)}, {LL(0xb93e7cb7,0x7ad9b263),LL(0xfd626ea3,0x280f6bc3),LL(0x62713cad,0x746c3945),LL(0x3a4edce8,0xfa2b4599)}}, {{LL(0x10ab7f93,0x8792d0cb),LL(0xc25a2a86,0xfa38d031),LL(0x08b028e8,0x6914db0b),LL(0x383cab40,0x75a98aa0)}, {LL(0x6da884bf,0x462e6b6d),LL(0xd3aa74b1,0x2b0f682b),LL(0x5cee0a83,0xb3b7995e),LL(0x3cce609a,0xe99fca2b)}}, {{LL(0x45451744,0x342c41c9),LL(0xc81be29f,0xb00d3c24),LL(0x022e8d27,0xd1e64d86),LL(0xbcf67326,0x404550be)}, {LL(0xc8aab829,0xc7c510f0),LL(0xa90c605d,0xb61ae647),LL(0x02db8602,0x582ad9c9),LL(0x71cb4397,0x732b19ed)}}, {{LL(0x265e5369,0xea097c35),LL(0x9d5ea687,0xea7c368f),LL(0x8fcae7f1,0x7fc3b213),LL(0x49c54942,0x641daa3f)}, {LL(0x404c39a6,0x0696372b),LL(0x87b4b181,0x56815716),LL(0xfca24eb8,0xa6e156b3),LL(0xd078a39c,0xf278eeae)}}, {{LL(0xac762dbe,0x046566d1),LL(0x625ed2e8,0x662ef0f6),LL(0x650e4764,0x15499e72),LL(0x84edf50e,0x361ccef0)}, {LL(0x1f4a2200,0x2441f6f4),LL(0xdb730d58,0xf36fff06),LL(0x3c01edc7,0xcc18624d),LL(0x8a77e5bb,0x4889078f)}}, {{LL(0x75f8dd8a,0x02294e3b),LL(0xfc4113c5,0x5f6f6057),LL(0x6f699f18,0xb5300e0d),LL(0x639dc977,0x52cce358)}, {LL(0x328fd50b,0x5dbe59b8),LL(0x39d73c2f,0x81500be6),LL(0x96ae313d,0x409ac4d7),LL(0x5b16c316,0x15205b7b)}}, {{LL(0xfc688c09,0xe272300c),LL(0xbdf71f2d,0xb412cf39),LL(0xf85b23d4,0xe3ab9c44),LL(0x7b662694,0x5c14085c)}, {LL(0x9956d07b,0x24b0b385),LL(0x30b2c82d,0xfa8ea968),LL(0x6d403b58,0xd443b2aa),LL(0xe7fc8d57,0x6da53ecb)}}, {{LL(0xdfdf488f,0x29655314),LL(0xadc57e2b,0xb418943d),LL(0x6395a287,0xbaf090f1),LL(0xd62f5b38,0x8fdb4fc8)}, {LL(0x371c9db1,0x115653c0),LL(0x96463359,0x6f5e1f39),LL(0x825e6273,0x106aaf1e),LL(0x398cbe1b,0xba22b7db)}}, {{LL(0x62b6bf7e,0x3b545300),LL(0x5bb6f993,0x495d7d27),LL(0x3f00290b,0xf558fc5d),LL(0x2cfc2381,0xdddbeb3e)}, {LL(0x65c79326,0xca402179),LL(0x33b1973c,0x376ce4ac),LL(0x9b30749a,0xd6e65ae4),LL(0x5f54bf5a,0xdf68ee04)}}, {{LL(0x4cfdb41a,0xa982948d),LL(0xf2a7b4b3,0xddd1d3ba),LL(0x581aaba1,0xf52a6b33),LL(0x894ebf68,0xc3258264)}, {LL(0x84665ac1,0x26c32c27),LL(0x20119b0e,0xda0190eb),LL(0xb86745c1,0x4a599db7),LL(0x58964b41,0xf9570f50)}}, {{LL(0xe0648365,0xb34d039b),LL(0x5c5f61e1,0x2cd7fde0),LL(0xbc6b08cc,0x76f514a3),LL(0x18a3cabf,0xc957b50d)}, {LL(0x2334cd1f,0x775fc56a),LL(0x67ec91c6,0x7bfe3864),LL(0x35ad3a9a,0x99037daa),LL(0xb7ca5657,0x17ffe391)}}, {{LL(0xfef04aef,0x19f6d369),LL(0xd1876f8c,0x8030b467),LL(0x3cd7878f,0xa014be02),LL(0x3358c943,0x03c22a58)}, {LL(0x2a257094,0x3c77f083),LL(0xd962a04f,0x47386957),LL(0x82da3329,0x768da40c),LL(0x458219cf,0x1507350d)}}, {{LL(0x4397ee7c,0xf460aed3),LL(0x36fbc7fe,0xf249e4cc),LL(0xaab03dfe,0xc42d9da8),LL(0x435ab9f3,0xa3d73ce3)}, {LL(0x3813a3f3,0x86dddbc3),LL(0xb79c32a3,0x86d5779a),LL(0x028a2c3f,0x7c3d9aff),LL(0xb1add2bf,0xc687e71b)}}, }, /* digit=26 base_pwr=2^182 */ { {{LL(0x09b3fed3,0x4612a562),LL(0x3579966a,0xf296c17a),LL(0x07960971,0xa124a36f),LL(0x380c4a05,0x6d03b214)}, {LL(0x70f1f268,0xcb0746e2),LL(0x9341aea4,0xcc9b47ff),LL(0x6d2f59cc,0x1b3662d5),LL(0xd4b1a15d,0xa6c65b2d)}}, {{LL(0xcccb0a4b,0xf96c113a),LL(0x3615f016,0x24c26bba),LL(0xeead2f5b,0x52fe115a),LL(0x0d7aaabb,0x85623d26)}, {LL(0x31a2564f,0x50791fd0),LL(0xcd0d59a4,0x3659974d),LL(0x7a8b7466,0x2cffdb74),LL(0x514787b0,0xcf6b36e5)}}, {{LL(0x4ab1ccd2,0x8afccd36),LL(0x1c03ab29,0x67314635),LL(0xd7ff3a32,0x458f36bf),LL(0xfcf71648,0x70e9e789)}, {LL(0xa6e904cf,0xf3764534),LL(0xf4bdd378,0x2d6130b1),LL(0x1ca5ce34,0xc61c98fb),LL(0xa4a684f5,0xda11f502)}}, {{LL(0xb6223f04,0x8d9daa41),LL(0x841c3fab,0x803c9c0e),LL(0xc50b42cf,0x60eee3f9),LL(0x77298193,0xaf4a7a5a)}, {LL(0xbf809ad6,0xd379c2e1),LL(0xf67c0ff2,0x903ab4b1),LL(0x90f8e637,0xc779d7ed),LL(0x2cf3d363,0x968b0cc0)}}, {{LL(0xacf51940,0xaadfa857),LL(0x50156581,0x0c789d1e),LL(0x62cff8f4,0x5e79cef7),LL(0x65eb0d49,0x54cdaba9)}, {LL(0x3321c57e,0xdf7a5828),LL(0xa21a51a6,0x8571e6e2),LL(0xc3726e69,0x0b9b482b),LL(0x1d92b657,0x3bc201e3)}}, {{LL(0x8a3b4cf8,0x271c58bb),LL(0x717eb539,0x269fc422),LL(0x5b381fe1,0xe82644e9),LL(0xcb62982f,0x27fb0822)}, {LL(0x5b5ec726,0xb0acd51c),LL(0xea4eff73,0xfd01053d),LL(0x00b11c80,0x465311dd),LL(0x2ed8460c,0xe50a8615)}}, {{LL(0x7b2243a0,0x3eade5eb),LL(0x77424d11,0xa59ec933),LL(0xf5c7c3b7,0x65a8e1aa),LL(0x0c1db536,0x008399fa)}, {LL(0xfb194a74,0x80b20e97),LL(0x43be90dc,0x2316fb9b),LL(0x0da4d913,0xb2773b23),LL(0xce973d27,0x945d0671)}}, {{LL(0xb79f82af,0x64ca871c),LL(0x2dab52f6,0x31304b02),LL(0x928239a7,0x1825ab54),LL(0x8e4ad736,0x740413b2)}, {LL(0x44071d19,0xc5c5d3fa),LL(0x3f0b2da8,0x83e438f1),LL(0xc70a1981,0xfd759448),LL(0x565ebae3,0x13e0c7ee)}}, {{LL(0x26bd7c0a,0x31b74b0a),LL(0xd280cb56,0x66e0e8e8),LL(0x3d1c83d2,0x086795e6),LL(0x396ecf25,0x59e678da)}, {LL(0xf015a36e,0xab3c8d74),LL(0xadc03171,0x0d19aed3),LL(0x5a263686,0xc83b787f),LL(0x9057ed63,0x46b94ad0)}}, {{LL(0x90979da2,0xfbf783a7),LL(0xa335c784,0xf04dd6a0),LL(0x87d93c4c,0x6e3c2554),LL(0x47994eb3,0xe3e6b289)}, {LL(0x1b74ba16,0x473c0684),LL(0xabe84e1c,0x4e959eb4),LL(0x7c4a67b7,0xdc3bfd51),LL(0x5095bd6e,0xb4e3cb85)}}, {{LL(0x3229fb05,0x96fc11f0),LL(0x4b36c83a,0x598227e4),LL(0xd46fca66,0xdc69ad06),LL(0x703ad6be,0x14cc98e5)}, {LL(0x6b22cd50,0xf0fdd142),LL(0xf89c1a5d,0x9b821fe2),LL(0x829f9a74,0xa3762dca),LL(0xf0c320cc,0xf65a584a)}}, {{LL(0x5568f242,0x58f4eaba),LL(0x029afc1f,0x83b0c37b),LL(0x994d7dfc,0x93de2d27),LL(0xb1679532,0x0d9a6edb)}, {LL(0x95f085b0,0x3b834279),LL(0xa299355f,0x46ebac98),LL(0x044427f8,0x0212e489),LL(0xa2f37d0e,0xf9e4ce34)}}, {{LL(0xfdc9e233,0x0fa328d6),LL(0x51ae732f,0xd5c8afab),LL(0x83c00cee,0x85e59553),LL(0x87505db4,0x9fce31f9)}, {LL(0x7069d066,0x33ea5eb6),LL(0xf01c0ce9,0x10e32a39),LL(0x0c4f1a2e,0xf170233c),LL(0xbd4cb366,0x8a907760)}}, {{LL(0x79bf05e3,0xda593421),LL(0xce49a5bd,0x7730907a),LL(0x09be5c7b,0x0dfb8a97),LL(0x23eb936e,0x6f50c692)}, {LL(0xcb18ff1a,0xc6160551),LL(0x661cc384,0xfa1d23fd),LL(0x7ddec262,0xfef12307),LL(0xb15af580,0xd1aca960)}}, {{LL(0x2ee50fbd,0x7eab8a59),LL(0xbe1e7a42,0xe7f71845),LL(0x6121e573,0x5f46a511),LL(0x38ff7eba,0xa25dacbf)}, {LL(0xf58f047c,0xe8aefcc7),LL(0xb538aace,0xc343aaa7),LL(0x3c340b1f,0x3e58cdda),LL(0x1fb98ccb,0xb0e9867c)}}, {{LL(0xef7750f0,0x034dd314),LL(0x22da84d7,0x2ceaa705),LL(0xfc0d647b,0x4561a254),LL(0xbbe01157,0x81cf0915)}, {LL(0x34b798eb,0x547a3d4e),LL(0x8b1c7544,0xbb5dd625),LL(0xc8194168,0x94fee01b),LL(0xfaeb010b,0xdb4c25ff)}}, {{LL(0xe4d4a176,0x1ff217fa),LL(0xaf87f4f5,0x8b46e6c2),LL(0x89734273,0xcf658775),LL(0x52746de9,0x73c4390d)}, {LL(0xb01c7a06,0xb5c84899),LL(0xedd9ef63,0xfa5ffe4d),LL(0xa1a8b2d4,0x28a313c5),LL(0xdaf5a33f,0xadd45f47)}}, {{LL(0x1fdb8694,0xc2dc9d13),LL(0x9a90b4d1,0xaa5e026c),LL(0x208cbfa5,0x5edffd39),LL(0x72a4d6cc,0xf095b3fb)}, {LL(0x6645fcc1,0xbfca4e10),LL(0x92408c6a,0x14b872ac),LL(0xd0b82d2d,0x3d9261e1),LL(0x0294e75b,0x13e4ecb6)}}, {{LL(0x3ac2ab9d,0xabd4541c),LL(0x4d5d1531,0x025355b2),LL(0xfb726ab8,0x3d85f67c),LL(0x6d6fc6bc,0x56e26c82)}, {LL(0x495e05a0,0xb24608bb),LL(0xe5afdc5d,0x840e0978),LL(0x248727e2,0x2cc543b5),LL(0x3bc8c021,0xe48146da)}}, {{LL(0x530c98b7,0xa1b36baf),LL(0x5acf023b,0x04503d7b),LL(0x21de1503,0x96bc4449),LL(0xd2a9c89f,0xbb8a122f)}, {LL(0xd5d4b133,0x66df99df),LL(0xc97d3e52,0x1bb4a13b),LL(0x79b318d6,0xdab370f3),LL(0x9f18552e,0xfa6c823e)}}, {{LL(0x6388a194,0xe5b27e78),LL(0xc88ba441,0x13270523),LL(0x4fecfef5,0x9f309fbf),LL(0x10afee60,0x72cd374b)}, {LL(0x93dfe3af,0x16bd0e2e),LL(0x24bc7e8e,0x7e92096a),LL(0xfec7f0bb,0x144fdf82),LL(0xe1f765f7,0x5d1d4598)}}, {{LL(0x72c67697,0xb6b91efc),LL(0xb2487905,0xc7a2ceaf),LL(0x7fb24d99,0x4a4c9e63),LL(0x4d742089,0x7ed373ac)}, {LL(0x9149ac54,0x3f9e6ae1),LL(0x0611efc8,0x64fd7fef),LL(0x3d779af6,0x1c38da32),LL(0x0a1681f5,0x6893691b)}}, {{LL(0x50a0fa72,0xbac29978),LL(0xba55c665,0x98d5c82e),LL(0x2d4b76bc,0xf3e5b58e),LL(0x90615b32,0xfae27d9a)}, {LL(0xd49b2500,0xb93bc327),LL(0xbbc213cd,0x7d9d4bff),LL(0xd1ee81c4,0xf985fe72),LL(0x381f9e48,0x6e2a94d1)}}, {{LL(0x14fb9624,0x1f09b225),LL(0xca4229d7,0x2eba4ff8),LL(0x21dc8c19,0x5b159dd1),LL(0xb1aa553e,0x1e1f968f)}, {LL(0xc7674d52,0x6ea25976),LL(0x7b283501,0x98e73adc),LL(0xd39468c2,0x7cfce0e1),LL(0x08438a62,0x7aad0af9)}}, {{LL(0xb2a3dde2,0x2291cdd0),LL(0xf77a0aa4,0x3a625d50),LL(0x5fbc5a0a,0x3be0fba2),LL(0xe794bf46,0x67b7598a)}, {LL(0x531ad772,0x3673d805),LL(0x03e8479f,0xf9a9b392),LL(0x2e16a126,0x142d264c),LL(0x5a2f6f2c,0xc20409ac)}}, {{LL(0xcd43f273,0xd9d84438),LL(0xbda7be72,0xfecc561d),LL(0x241b7ec2,0xc4b113c6),LL(0x40dba9e3,0xfc5bc32b)}, {LL(0xd56bca47,0x70853d39),LL(0xa5306217,0x2b9a902d),LL(0x2017bfd0,0x2bb1836d),LL(0xcd1c2768,0x829ce116)}}, {{LL(0x697097f5,0x42d5fcf8),LL(0x1e936db5,0xc1fe7be6),LL(0xcb6a81d4,0xcbc5cdcc),LL(0xafef5ffa,0xab1e4ecb)}, {LL(0xb933c216,0x3cbbdf76),LL(0x503607e2,0xdb5808da),LL(0x6bc96246,0x5bdaab7c),LL(0x68274629,0x91e5d17c)}}, {{LL(0x2eb1db21,0xa3cd09f6),LL(0x92c3e3e1,0xbe370485),LL(0x6aa43da5,0xeb51fa29),LL(0xd726625e,0x2c7fa809)}, {LL(0xf0ec0e99,0x90c6786f),LL(0x08135cbf,0xd315af33),LL(0x1504751b,0xc1b60172),LL(0x0e28781a,0x88674e2d)}}, {{LL(0xed74e633,0x6aa74055),LL(0x7d06ce02,0xc44e740f),LL(0xa33b8d5e,0x8b40bc5e),LL(0x20f00f14,0x42d3539f)}, {LL(0x3307ef15,0xd9f1f5cd),LL(0xc8599bcc,0xa9fe4dfb),LL(0xefa80b8d,0x31cb6703),LL(0x53bb73fe,0x4172b46d)}}, {{LL(0x20e4c321,0x85a70280),LL(0x5ac075f3,0x999a0d07),LL(0x7bdb478c,0x59a62b62),LL(0x573c403b,0x9aeb710a)}, {LL(0x950bb8fc,0x1c099614),LL(0x5dc09741,0xc1efafab),LL(0x7296a74b,0x0de58ca5),LL(0xf5be2ec4,0x657116a4)}}, {{LL(0xcb199b77,0x0ce52f0f),LL(0xbcd11438,0xdcdc5cb9),LL(0x4777327b,0x587a68ff),LL(0x1cc6fbb3,0x55d9abb7)}, {LL(0x9eeb28a9,0xf1970b82),LL(0x4ceef00f,0xe1ab4e14),LL(0xf7462893,0x184d3fb6),LL(0xc8ea54fd,0x9942a008)}}, {{LL(0x1e33b2a3,0x1fee0f77),LL(0x9f789870,0xd4bed81f),LL(0x6ef05b7e,0x6396feea),LL(0x2640b62a,0x9c5d6a01)}, {LL(0x6834bea4,0x170cfec9),LL(0xe131feca,0x68d16728),LL(0x00affb4d,0x4be9c5d6),LL(0x99a6f256,0xe34a423c)}}, {{LL(0x09b9ed61,0x1a254e4a),LL(0x30b10207,0x902bc066),LL(0x62121f53,0xd2d5ed01),LL(0x30f1b518,0x0ba86811)}, {LL(0xabe139c9,0x7916c132),LL(0x62c4f337,0xb3a30fe0),LL(0xaa5693be,0x85d0a769),LL(0xe3c7687b,0x2d414379)}}, {{LL(0x94958719,0x92b0cb3c),LL(0x4ec6575d,0xb78aa37b),LL(0x4f1bf26a,0xd035aae1),LL(0xd31d5108,0x1383992d)}, {LL(0x92bdd6f5,0x53ecc535),LL(0x08c622ca,0xa9925ff6),LL(0x916d890c,0xcaa3146e),LL(0xb9c10220,0x8cd0f12e)}}, {{LL(0x7e12a730,0xcb6ad82b),LL(0xac9485db,0x3f89047c),LL(0xfea2d970,0x6f926117),LL(0x46a19ecb,0x87b0cd9d)}, {LL(0x01e45bf6,0x98bb5b02),LL(0x2ed7716d,0xfc814620),LL(0x4f5caa95,0x8d6808cf),LL(0x082f799e,0x3b57df03)}}, {{LL(0x2df84ca2,0x469e1854),LL(0x64aac069,0x00dd62eb),LL(0x88d9efff,0x7d3ee9ce),LL(0xbb830ffc,0x9faed6a2)}, {LL(0xd2d74f58,0xd073aac1),LL(0x2d44199e,0xf69e96b4),LL(0x83ed62ca,0x6cb3a3b1),LL(0xd799acf8,0x472489fd)}}, {{LL(0xb63a36cc,0x5f84382d),LL(0x92d5b175,0x6ba1de87),LL(0x516101b7,0x25aab130),LL(0x5f039793,0x6f69c3fc)}, {LL(0x89e3da4f,0xd28439ee),LL(0x5e6b2b61,0x8cb40a0e),LL(0xe3d6650d,0xdfa55805),LL(0x0be59fd2,0x2651f6c7)}}, {{LL(0x140d01c8,0x290e0044),LL(0x62ea488f,0x78afa0a4),LL(0x91eaa932,0xc4e39971),LL(0xfe2e79dc,0x8a9ef3a2)}, {LL(0x50705b7e,0xdcfae315),LL(0xd4be3d75,0x73324dca),LL(0x03a91415,0x900bdd43),LL(0xedfdc74d,0xc3ed02ed)}}, {{LL(0xf22b4a66,0x509bd1d6),LL(0xb78d264b,0xfd8ed371),LL(0xa419134f,0x562b2d3a),LL(0x7a57a51e,0x80a2c274)}, {LL(0x8c662472,0xebba5317),LL(0xa0be71fb,0xebafedf2),LL(0xb77899c8,0x0c5b9c1c),LL(0xc4888cb5,0x82448008)}}, {{LL(0x78401c3b,0xb795ea00),LL(0xa85ab971,0x86776990),LL(0x185739da,0xdd81393b),LL(0x58136c97,0x76d0031f)}, {LL(0x641d39d1,0x6aceaa56),LL(0x39be7ca8,0x918844c7),LL(0xe18efc54,0xa63993f7),LL(0x4af0f30a,0xb5369150)}}, {{LL(0x3d04af4f,0x9bc2068c),LL(0xa7796ed2,0xf309dff9),LL(0x4e15b6a2,0x46e9a59d),LL(0xc22ef488,0x617aaeba)}, {LL(0xa15cf0cb,0xd91a8f90),LL(0xc30fb779,0xc6ce12a4),LL(0xb9d0a7ff,0xf3b80254),LL(0x6e9b6fa1,0x32a63bf9)}}, {{LL(0x546fe4a8,0x3e1ac837),LL(0x1279c7ef,0x91ed89a5),LL(0xc73e9dea,0x8eb7b88e),LL(0x18238af0,0x96d07205)}, {LL(0xe96abf80,0x56ebf306),LL(0x52c4b10f,0x5088ce24),LL(0xc979137f,0x65293176),LL(0x228d300a,0x824642fb)}}, {{LL(0x7836aea5,0x968963a8),LL(0xfabbfac1,0x2d4c556c),LL(0xd3f9977a,0xa4c389bb),LL(0x99b4ccb6,0x2e8b2818)}, {LL(0x6cb67df6,0xc1fd8565),LL(0xa72d2be8,0x0ac57d2a),LL(0xb8224ead,0xa51ce6b8),LL(0xf417d744,0x33f7b468)}}, {{LL(0xf9f0bdf4,0xcf8c80af),LL(0xd3222dd6,0x0728f880),LL(0x653afc12,0x436188a3),LL(0x3c7940bb,0x0f8bf160)}, {LL(0x424dcd2a,0xdc18c13f),LL(0x20d3cd1f,0x038c1842),LL(0x7b12fd42,0xed7f86a5),LL(0x7aaf1881,0xa75ab77b)}}, {{LL(0xdf0574e2,0x5c3d7612),LL(0x719414ce,0x2eeeeb6f),LL(0x90349fc4,0x797c5771),LL(0x2232eb33,0x0d850f73)}, {LL(0x2638c051,0x0a0744f3),LL(0xb6e7dbfa,0x739e6278),LL(0x659fc5f5,0xa77f286d),LL(0x9654b0eb,0xb18b7cf1)}}, {{LL(0x6062e78e,0x5a2089ac),LL(0xdfa6fb44,0x152f1804),LL(0xb61e6faa,0xe8a404b4),LL(0x08d06ea8,0x4774d30f)}, {LL(0x3c359648,0xd7119b91),LL(0x09473ff7,0x850b02bd),LL(0x936b7868,0x4db6f9a0),LL(0xae38c3c5,0x84064dd5)}}, {{LL(0xfe448461,0x294d6831),LL(0x42cd2105,0xc3c6f446),LL(0x3a2fdcae,0xa4412eb0),LL(0x3d5a9181,0x394c3774)}, {LL(0x5ca87c4b,0x58f19024),LL(0x89ad5685,0xba1879db),LL(0x803c2589,0x43c55c6a),LL(0xa8249c65,0xae1fad20)}}, {{LL(0xe0aff809,0x4929e89f),LL(0x1769a00a,0x19755ec2),LL(0xc242f335,0x3b6a207b),LL(0x090edab0,0xeca054ef)}, {LL(0xcd9e1c26,0x217e9c8b),LL(0x35d4ac57,0x917c2ecd),LL(0xad33911d,0xdc869d5d),LL(0x2e828bd7,0x22d9d860)}}, {{LL(0xf38dfaa1,0x89262252),LL(0xeb9cd8d7,0x155c96ce),LL(0xed5ebcc4,0xb0082b5d),LL(0x17182086,0x7b6f9203)}, {LL(0xee92aa6d,0xaefe28aa),LL(0x9aaaa0eb,0xbe67090c),LL(0x2f8ef18d,0x88c5fbf1),LL(0xdd1fd65f,0xbdc8bef1)}}, {{LL(0xa9c7b483,0xfb7052f5),LL(0xbd6c8a99,0x49634258),LL(0xc9f424f8,0x1410a747),LL(0xe9805723,0xfda0a304)}, {LL(0x0879bd30,0x1a438bd3),LL(0x7f6903cb,0xed09a9d3),LL(0x57e53497,0x920878f8),LL(0xa7fca0ed,0x87a12968)}}, {{LL(0x38590ca1,0x7c8207cb),LL(0xfae885c2,0x4cf52db1),LL(0xe8dc711f,0x6cf384c4),LL(0x221dc698,0x6fea20ff)}, {LL(0xa07bb79f,0x6af56700),LL(0x33ca79c6,0xc7da3b52),LL(0xd05eb519,0x3a214691),LL(0x93d4f089,0xea94c4f1)}}, {{LL(0xba51f002,0x734039d0),LL(0xce206406,0xc45e2042),LL(0x4b3c3d53,0xc0e75dbb),LL(0x55b1b97c,0x3a701272)}, {LL(0xd6addb6c,0xec856e95),LL(0xf283aae1,0xb63fe8c6),LL(0x405788d1,0x148fb239),LL(0xe0181912,0x42e7148b)}}, {{LL(0x7de07978,0x00bddcdd),LL(0x3c2e0a27,0xac79b657),LL(0xdf1dd3dd,0x94024ba6),LL(0x0bac41ad,0xcddeb357)}, {LL(0x500c4f4b,0x51ec3dd7),LL(0xd31c8fbe,0xf00d594f),LL(0x373a3e93,0x6b8c6f43),LL(0xfc2b6be9,0x891ba3a5)}}, {{LL(0xddd72e36,0x3928225a),LL(0xcee362c1,0x1e6a63bf),LL(0xc5eb404c,0x317b78f4),LL(0x67c5e6b3,0xb882736b)}, {LL(0x1f2f07aa,0xb1da56ce),LL(0xff83b633,0xab3c4fbe),LL(0x0ceeab99,0x9cc32f1c),LL(0x1062070e,0xf1dead0d)}}, {{LL(0x8a3e79c4,0x49ea0d9b),LL(0xec9f16d1,0x4e7abe3f),LL(0x5549ade0,0x19bda1c6),LL(0xe5885734,0xaae756a5)}, {LL(0xcc2a1aaf,0xb3cff8ce),LL(0xf896ca47,0x812eebff),LL(0x9b2e1123,0x0951b2bb),LL(0xdef6d6a9,0x7f245699)}}, {{LL(0x1be7ef41,0xa1331e95),LL(0x9fa1be62,0xd1f0c3c3),LL(0x4383e451,0xb1d8295e),LL(0x9f08bc14,0x658d8a84)}, {LL(0x3ba4b85b,0xb0587aef),LL(0x481cbb27,0xb519c587),LL(0x040d8f06,0x2b975db6),LL(0x1691d809,0x399f6417)}}, {{LL(0x7c6204fb,0x207a0e46),LL(0x62c3e9d7,0xe30f1420),LL(0x792f8208,0x6127b782),LL(0xb0d3fca9,0x38f806ab)}, {LL(0x2ff46c64,0x38248542),LL(0x926ec166,0xc18ffe85),LL(0xc0c133fa,0xfd268866),LL(0xb93770e6,0xb7f63f5a)}}, {{LL(0xb13afb71,0xd8f1db26),LL(0x32a790de,0x5c5627eb),LL(0xdf50b6f8,0x7f41bc1d),LL(0x92d4c803,0x49d4ef17)}, {LL(0xe8530065,0x577f909f),LL(0xe630ff2d,0x482cdede),LL(0x14f54de8,0x682c8c6a),LL(0xb4079343,0xe6b5a504)}}, {{LL(0xe58bde6b,0x00d927fc),LL(0xf34841f4,0x65d85f03),LL(0x2ac001d8,0x265aec02),LL(0x2dfe518d,0x1b785666)}, {LL(0xc01e6e47,0x76142488),LL(0xdd5648dc,0x8e8b2044),LL(0xb3a340b3,0x2c422006),LL(0x3dd67b22,0xa5392113)}}, {{LL(0xa1567aaa,0xbd08d05b),LL(0x02acbec6,0x84a55e43),LL(0x5d898af0,0x744ffd21),LL(0x6682e78a,0x38067622)}, {LL(0xffd08522,0xf3696ff2),LL(0x2bf02466,0x49dd0060),LL(0x59c3e65d,0xc9e0d1a5),LL(0x0a37fc25,0x29537f56)}}, {{LL(0xa5f6b17a,0x6f6cb9eb),LL(0x9c55857e,0xc1854320),LL(0x45dacc6e,0x959585c6),LL(0xe5f4e930,0xf4e97c94)}, {LL(0x57d2a492,0x966deb5f),LL(0x55d2df12,0x98256831),LL(0xaa457eca,0xfdd65534),LL(0x03551474,0x76dbb021)}}, {{LL(0x09d9b4aa,0x0aeefee9),LL(0x784ca675,0x30fea11a),LL(0xff1d381a,0x56b4b509),LL(0x9fce40da,0xd1b26fea)}, {LL(0x48d22911,0x4835b911),LL(0x8bbe57e8,0x6aaac57a),LL(0x19d02037,0xc8882792),LL(0x3ee49afa,0x301e0aa6)}}, {{LL(0x00e6b020,0x1641ce6b),LL(0xeac7cad8,0x846b97de),LL(0x61aa6886,0x9b74bfd8),LL(0xb0fa37ac,0xdd95e765)}, {LL(0xf848a83b,0xda0cde52),LL(0x355b3528,0xd2cc831d),LL(0x5e22238f,0xc7fd2e03),LL(0xab9a6c34,0x6d5373fa)}}, {{LL(0xd8247f13,0x5dfc2874),LL(0xe3c11f56,0xc211a7a1),LL(0xa2503b97,0x7512563f),LL(0x5c007c82,0x124cd984)}, {LL(0x491cd249,0x4f6eb682),LL(0xa683359d,0xaf4f70a3),LL(0xcc302b62,0x2f1dfe71),LL(0xe57fbf56,0x83c474bb)}}, }, /* digit=27 base_pwr=2^189 */ { {{LL(0x916a8016,0x43af7ab7),LL(0x532bfb9c,0xf93d487f),LL(0xe2174971,0xa5f9af3c),LL(0x2d59b4d4,0xd1b9cf1f)}, {LL(0x44f4eb91,0x4a779418),LL(0xc226edc5,0x6a131fac),LL(0x80d4bb33,0x472ab897),LL(0x2f6ca1fe,0xb69687a5)}}, {{LL(0xfabd066a,0xffa73ca2),LL(0xf9c78bfd,0x494e03a8),LL(0xff55cfef,0xe585a878),LL(0xd7053784,0x00770b1f)}, {LL(0x056fe70b,0xdec4da4a),LL(0x57bd444f,0xe37395d8),LL(0x685df668,0x666250d4),LL(0xbe6cc583,0x0549569e)}}, {{LL(0xab11639e,0x87629830),LL(0xa4488d53,0x869dd3ba),LL(0xbaf06eb6,0x10fe1c0b),LL(0x1687ac37,0x99034839)}, {LL(0x7f1ffe7b,0x38418377),LL(0x25bd7c57,0x3334a74c),LL(0x7008ba67,0xc57cb7ed),LL(0xc1e4e12d,0x384c12d0)}}, {{LL(0xdb4bdb35,0xf48cdca6),LL(0x74d913a7,0x6bc23aec),LL(0x12ed94d5,0x8f0ccd9d),LL(0x86db09e7,0xe4aabd12)}, {LL(0x1e948326,0x0cbff31a),LL(0x17a479a2,0xcf68c47c),LL(0xca7686f1,0x3cced8e2),LL(0x4eb62669,0x15ed1e99)}}, {{LL(0xbdb0c561,0xc373ab4b),LL(0x6a9066a7,0x15082022),LL(0x62d31801,0x330a60c3),LL(0xe35bea57,0x53d97f09)}, {LL(0x9c5dbb92,0xf204e006),LL(0xf831262a,0xfb9a8219),LL(0x42136174,0x3468ae41),LL(0x0e03218e,0x0f8fb5bc)}}, {{LL(0x4ad8bba6,0x90337499),LL(0xe3ecb618,0xdb71e1fb),LL(0x3cf2a8ad,0x6955e874),LL(0xed691fee,0x594501f5)}, {LL(0xd29bd364,0x7e2baef3),LL(0x6f766759,0x5cbd91ac),LL(0xb2201a96,0xaba54aaa),LL(0xcfa392ab,0x2cfea457)}}, {{LL(0x86f8f7da,0xa4da4162),LL(0xcbc0b934,0x88d70b86),LL(0xacff4f7b,0x9df02795),LL(0xc65ef81b,0x0fc80219)}, {LL(0xa299ca0f,0x32d457de),LL(0x0896427b,0x97081b35),LL(0x41bab6b4,0x92d6c309),LL(0x73b8d601,0x5d5e56f3)}}, {{LL(0x202bde39,0xfb3992a4),LL(0x3d6bab98,0x2549f564),LL(0x87712512,0x0b564642),LL(0x7fde7e50,0xd52442b4)}, {LL(0xa3d3e16e,0xa6cefd08),LL(0xc83b29bd,0x5b194f0a),LL(0x906dec8c,0x6db0edd8),LL(0x02570c1e,0x7a090959)}}, {{LL(0x4c41eb53,0xf6f74fcc),LL(0x5b944a6c,0xd07678a9),LL(0xb80677ea,0xf53bf11d),LL(0xbc5900f8,0x569a5761)}, {LL(0xd3d4de91,0x34e5bba8),LL(0x8361f73e,0xc5774804),LL(0x59abdbd5,0xd637d3dd),LL(0x8772b615,0x64a81bf9)}}, {{LL(0x7f3d83ab,0x78bb12ea),LL(0x573f9b99,0xca22c31c),LL(0x2aed4c39,0x4283c173),LL(0x39f32bdb,0xda054c1d)}, {LL(0x1da2cbd7,0x2ead717e),LL(0x62390b41,0x747d67cd),LL(0x6b9666a6,0x43739d9c),LL(0x8c827b12,0xb84e2f22)}}, {{LL(0xc0312773,0x0e4ac2b1),LL(0xe53f068e,0x571cfc75),LL(0x42bfe41e,0x6c44df85),LL(0x627e30bb,0xe7d2edb9)}, {LL(0x0dd5cedc,0x9c2e4fd6),LL(0x0f7d22d7,0xe2d885ef),LL(0x1329bcfd,0x44b0b5db),LL(0xba1c96f6,0x006e872f)}}, {{LL(0x7e952317,0xdbadab5d),LL(0xc2a5bcaa,0xab849ed4),LL(0x1e72dbb1,0xe3acbb74),LL(0x5d4b7cb7,0xbf42c3d3)}, {LL(0x3d748639,0xebe967b5),LL(0xc03af7a1,0x1fe93db5),LL(0xa944ea06,0x2ab14596),LL(0x76655c09,0xfb05a759)}}, {{LL(0x6f8a532b,0x5117890c),LL(0x59430c5b,0x2f57781f),LL(0x79e07b84,0xe70968b3),LL(0xe86d7223,0x05df2305)}, {LL(0x31e32933,0x57af0dc5),LL(0x84afc419,0x5473e34a),LL(0x03d5feb4,0xa7337a42),LL(0x1b1c6bd8,0xd85c8602)}}, {{LL(0x753008e6,0x25ca1891),LL(0x5f0ff93a,0x4338ec98),LL(0xddd30a7c,0xd2ba8557),LL(0x09c51794,0xb4b65361)}, {LL(0xd1cbc66e,0xfbb51399),LL(0xe53bca50,0x28853781),LL(0xfd5a9aaa,0x5b797232),LL(0x5b88c4f3,0x6249afd7)}}, {{LL(0xba6918a0,0xcc5ab6cb),LL(0x8fb65c7d,0x9f824ec1),LL(0x56b18754,0x4796d80b),LL(0x67721520,0x4c83d371)}, {LL(0x63b03348,0xd77c373c),LL(0x54f27457,0x91930e5e),LL(0xaf40c03f,0x83f97370),LL(0x34eea661,0x65b55872)}}, {{LL(0xeb10175e,0x310695d0),LL(0xcd236aa1,0x79aaa6ea),LL(0x3edfff40,0xf78539ff),LL(0x02cd6063,0x2369c517)}, {LL(0x5c8631ff,0x81e43ae5),LL(0x216a60bd,0x065e8212),LL(0xe761a5f9,0x225cb473),LL(0xab6de6fa,0x695ef860)}}, {{LL(0x7d7d98d4,0x03536a46),LL(0x18413673,0xa17d3a69),LL(0x295ae303,0xa6ddcd46),LL(0x61beae2b,0x86de0bbd)}, {LL(0x7699458e,0xdd73dfcc),LL(0xb53f88dd,0x827deba5),LL(0x42a9a11c,0x213c376b),LL(0x12c73975,0xc854fd72)}}, {{LL(0x15ac27ff,0x1fa96547),LL(0xf49b6c9a,0xcb0dc17b),LL(0x709dd202,0xa3e44853),LL(0xcfe2bbea,0xd3905c5f)}, {LL(0x6c35ce9c,0xb01e5799),LL(0x900ef600,0x0063e7ac),LL(0xfffa5cc0,0x8c70b87e),LL(0x74230b0c,0xebd76d34)}}, {{LL(0xed5f8529,0x914eec9e),LL(0xe8edf477,0x7a65ffd3),LL(0x70c74bee,0xf0cb206d),LL(0xd1b02e01,0x03445ff1)}, {LL(0xe5dbf791,0x664ca356),LL(0x254e69c4,0xd678d4ae),LL(0x8617386b,0x370c9f0f),LL(0xfdcd985d,0x42af7a0c)}}, {{LL(0x83c3da54,0x8c4b5009),LL(0x4c8a87c8,0x086a7ec5),LL(0xaa166c4c,0x9ba0b368),LL(0xa658ac1c,0xa279670f)}, {LL(0x5d0544da,0xc49f49bd),LL(0x15cb0b41,0x28c22323),LL(0xa4834d71,0x86293dfa),LL(0xd1e1d63b,0x283e191d)}}, {{LL(0xca188555,0x0cad6519),LL(0x0cbd0c5c,0x323ce5da),LL(0x38560254,0x6b7d2be1),LL(0x1696b9b9,0xb05ed385)}, {LL(0x9ae59f92,0x8ce4b5a7),LL(0x4f7e61a3,0xabe5ff33),LL(0xdbfeb302,0xae15a3cc),LL(0x837fde82,0x691b1129)}}, {{LL(0x2e6d116b,0xb60b31f3),LL(0xecab5aa9,0xd49e9d11),LL(0x6787f23d,0x3e95f844),LL(0xa12f4846,0x2ab8834f)}, {LL(0x5b6359cc,0xe70e2ab1),LL(0x9322a047,0x7a6349e9),LL(0x6c1e483a,0xc01e424c),LL(0x92bd5d1b,0x424b2027)}}, {{LL(0x254e49a3,0x8a6e6766),LL(0x97e70d58,0xb8d85d42),LL(0xb51b3abc,0xa859082f),LL(0xe7bb828a,0x2850573b)}, {LL(0x7bfe8021,0x47cc95b2),LL(0x5853f12c,0x7c28fe9e),LL(0x10c0f389,0xe5fb0558),LL(0xdaf0a7e7,0xb99a639f)}}, {{LL(0xf60ee3e5,0xa6b9e6c9),LL(0xa236377f,0xb397af7f),LL(0x7da4af71,0xb7a318ac),LL(0x0a9d39fb,0xae64b613)}, {LL(0x902b3411,0x66ce6c74),LL(0x5a199e53,0xea256a70),LL(0x550fb76f,0x8dcddd89),LL(0x03e70f9c,0x9443b477)}}, {{LL(0x142113a6,0x1787b8a5),LL(0x180aec95,0xa58b6c61),LL(0x947ff26d,0xcc381420),LL(0x3d8b8c36,0x22520e8f)}, {LL(0xef2cc6ef,0x192ee945),LL(0xe9ca0c7a,0xea52afee),LL(0xe6e30d93,0x5970d794),LL(0x57c786ac,0x0a325e42)}}, {{LL(0x33ca1226,0x5e2dddf8),LL(0x588cb1e3,0x18e624b9),LL(0x21809265,0xf3ba597a),LL(0x5d575728,0x90247702)}, {LL(0xc1f918db,0x48a5bf7b),LL(0xd6840541,0x17d1efaf),LL(0x3e2e754d,0x13dfe6fe),LL(0x707a531f,0xc471e16a)}}, {{LL(0x97d34b48,0x79085bbd),LL(0xc2e9bea9,0xfa5ba99d),LL(0x6c5a6dc2,0x70b9c9fc),LL(0x4e94c5db,0x4e042213)}, {LL(0x25ebb95f,0x4a37b41f),LL(0x055d79fb,0x24691010),LL(0x3f572a8f,0xdaff9352),LL(0xf327ec2a,0xe63d55b0)}}, {{LL(0xdebd5116,0xc5a86d3c),LL(0xa2ddef2a,0xd547fe08),LL(0x6a149f12,0xbabb617f),LL(0x8a766128,0x14f69a1b)}, {LL(0x48236f77,0xb83a1477),LL(0x35711279,0xd0d81be1),LL(0x5eab1c3a,0x706f9067),LL(0x16a1ffaf,0x8c4823f1)}}, {{LL(0xaff5ea89,0xd845c68b),LL(0x6b75eadb,0xa276eaeb),LL(0xcc230ec1,0x2d0fc819),LL(0xedaaf1f2,0xdfad96e8)}, {LL(0x40868254,0x0f25dcbf),LL(0x5babd7f9,0x53bbe31e),LL(0xcf804a8d,0x7f8afc48),LL(0x5f9b9a0d,0x7f4922ef)}}, {{LL(0xd7422804,0x703cbf6d),LL(0x83349bdd,0xe5df61f3),LL(0x77d285ad,0x0fa3d8cd),LL(0x2e88e15e,0xe990f9e5)}, {LL(0x8561d8a6,0x40ec61f7),LL(0x16650305,0x7fc498a6),LL(0x8e5beabf,0xa3bf5cb4),LL(0x76ae0350,0xfaa52008)}}, {{LL(0xe4fc3e72,0x99e24318),LL(0x2079c616,0x9241c8ab),LL(0x9584a258,0xefa5bf38),LL(0x1eebb098,0xd7b770b5)}, {LL(0xe1fc18a7,0x28b714a3),LL(0x5b83dd9a,0xf0426bd2),LL(0x291b28ee,0x956d8972),LL(0x6eb553ff,0x8bb8cbde)}}, {{LL(0x95298003,0x396cfe2d),LL(0xad8412fc,0xcaa66550),LL(0x83997dd3,0xf41d0215),LL(0x45534587,0x7066e356)}, {LL(0x5b6de0d7,0x0d5b5c3e),LL(0xcecd5f26,0x8ead45d0),LL(0xd252ae50,0xe2f24e2c),LL(0x815150bf,0xf71e5d4f)}}, {{LL(0x54527ce5,0x3872685d),LL(0x91fd99ee,0x59b343ae),LL(0x3462cc0c,0xd621d027),LL(0x8dbfbcf4,0xfa42481f)}, {LL(0xaf7ae918,0xda481a9e),LL(0x7c909a18,0xfd5fd37c),LL(0x805fb7b7,0xa5ebb7bf),LL(0x165200b1,0xeac65687)}}, {{LL(0x7cef9b97,0x56302866),LL(0xae3ddb64,0x8f662dd6),LL(0x60c1aa98,0x90cb4e87),LL(0x986fb3bc,0x33f9fc60)}, {LL(0x974593cd,0x76f41ecc),LL(0x6e0f01e8,0xb19501f9),LL(0x25760dd5,0x587d9035),LL(0x9391032e,0xa31c971c)}}, {{LL(0x95c9a84f,0x7650e3b1),LL(0x78c66087,0xbb83ea93),LL(0xdfcf1365,0xda08a04c),LL(0xca0b84a4,0xd23daeba)}, {LL(0x2ca3bd2b,0xf89d395d),LL(0x6e53fc93,0x779e2aaf),LL(0x34216082,0xc0fc7dc8),LL(0x42a66691,0x6cd8bdf6)}}, {{LL(0x0fe014cf,0x836a2cf3),LL(0x0c08373d,0xdde5fc22),LL(0xcb3b2b54,0xc4fa2387),LL(0xe2aa434a,0x96253732)}, {LL(0x1d502ce8,0x4c4f5979),LL(0xb6df40c4,0xf046f5a9),LL(0xac6b75b5,0xc7d05765),LL(0xb69f3c34,0xae1cd887)}}, {{LL(0x49b86680,0xafed4be6),LL(0x14f70463,0x17b75fa5),LL(0x90b7c07f,0xb12e8051),LL(0x39a8e99d,0xe2c8cf2b)}, {LL(0xd5fdb65b,0x984744c4),LL(0xa28942e4,0xd8b1c012),LL(0x46693fb2,0x295d0199),LL(0xa0a3b4fa,0x5ab3a305)}}, {{LL(0x26755b3f,0x3c191023),LL(0xb6c084de,0x75f35df1),LL(0x63e6286b,0x30640e66),LL(0xd2c6c059,0x3b3720ec)}, {LL(0x6ea837be,0x2c821a0f),LL(0x84f23bd0,0x238c4d93),LL(0x390ea4f5,0xbdc40703),LL(0xae68a2db,0xcb207d0a)}}, {{LL(0xe25f098f,0x487d18bd),LL(0x9ab84e10,0x39018023),LL(0x8b7ab4a2,0xaa19aa62),LL(0x89f08fbd,0xcb9cdebe)}, {LL(0x2ca57917,0x26a4c9eb),LL(0xda92ce1b,0xaadfd472),LL(0xdaa907db,0x32b592d8),LL(0x7d6f995e,0x9bbebacc)}}, {{LL(0xe1d88c25,0xa27a4735),LL(0x9bd66b67,0x339905e1),LL(0x62af9942,0xa9bfa0ed),LL(0x2e2cb83c,0xd94dd9e0)}, {LL(0xab28e268,0x279d8fda),LL(0x51a97518,0xf28ab69b),LL(0x9691f33e,0xce9bd2ea),LL(0x74be3d64,0xb9e8b2fe)}}, {{LL(0xabefa07d,0x35072fab),LL(0x7b51ba8e,0x1c2ba05c),LL(0xd32d6bf5,0x3bb1ec56),LL(0x5d7bd7dc,0x326bdfdc)}, {LL(0xd95bdcb1,0x33f4f4f6),LL(0x453ef338,0x781bfd34),LL(0x1ef61a66,0x4d210cad),LL(0x2799bcc7,0x6ae7bb14)}}, {{LL(0x194f4d6a,0xb105e5ec),LL(0x52b77f08,0x204a5480),LL(0xa328ab98,0x13f4e022),LL(0xb7f9a240,0xa56863c4)}, {LL(0xce4cf7bd,0x2780c9a7),LL(0xc497fdf3,0xf98e3f58),LL(0xf52738fc,0x635b8bc6),LL(0x58937500,0xc5fd89b8)}}, {{LL(0x75e98a64,0x57070428),LL(0x946f094b,0x66aabaae),LL(0x06d37944,0x7d2376e8),LL(0x09319f13,0x9b316827)}, {LL(0xa77eb79b,0xbbde59a8),LL(0xf451fde0,0xb7f35bbb),LL(0x64aa79fd,0xb2f7914e),LL(0x9f68a486,0x4d2944b3)}}, {{LL(0xc1a7e537,0xbd8a92de),LL(0x4fc930a3,0x76695e9a),LL(0xbcb4153b,0x1b75f9eb),LL(0xf6485404,0xf5a34d2d)}, {LL(0x26853a8e,0xe09ee965),LL(0x9dbb319a,0x63de8595),LL(0xda079d6d,0xbbbc1b07),LL(0xdfa71b9d,0x5956bb3d)}}, {{LL(0x209cbcc3,0x69709306),LL(0xe3360429,0xbe2a08d0),LL(0x92a58752,0xd377a9fe),LL(0x997bc322,0x37e175ea)}, {LL(0x042ff2e4,0xfe355d4d),LL(0x4c4babd3,0x4332ef31),LL(0x2314b1af,0x634429c2),LL(0x91a7d5e5,0xae6e8275)}}, {{LL(0x250a1476,0x134a39c7),LL(0x08994f0c,0xec9bb642),LL(0xd38704cd,0x2a9e0ac0),LL(0x536a4ad0,0x16490507)}, {LL(0x7c8dbfeb,0xc7f747d2),LL(0xc0bb24ac,0x91e67dd2),LL(0x959eca45,0x2dfc6c8a),LL(0xc54fefe8,0x78bafaf0)}}, {{LL(0x5da056f3,0xf3eb2d1b),LL(0x3b89c967,0xda14b631),LL(0xcb51f621,0x80923b1c),LL(0x6609791c,0xc3d5fd1f)}, {LL(0x817b1063,0x68ad7bef),LL(0xa1f0b00c,0x3775b686),LL(0x6c7f0dc1,0xb207c9a5),LL(0xa9b91fff,0xb7c30a7d)}}, {{LL(0x8b9f8e8c,0x9274c090),LL(0x24e94ce1,0xa3757610),LL(0x4f0f3ec1,0x8f2b1f2c),LL(0x3938d26f,0x02e53bb2)}, {LL(0x701e5ae8,0x90a3da2c),LL(0xa271dcca,0x60c2eaca),LL(0x31fb2372,0xc9c08e39),LL(0xb838908a,0xcaa3245e)}}, {{LL(0xa6a6a275,0x2e168b0b),LL(0x0030ef6b,0x986a30a3),LL(0x170ab683,0x79f768f9),LL(0xff70981e,0x7296fd6f)}, {LL(0x13a323cd,0xbab6fedf),LL(0x186e9813,0xa86ec0dd),LL(0xcd56e7d5,0xd9f8db04),LL(0xaa8b1c96,0x47b20676)}}, {{LL(0xf1fb3b03,0xdff4574e),LL(0x1051f9fc,0x41a1f765),LL(0x7f289a4e,0x35779aee),LL(0x11c96180,0x93bd54c9)}, {LL(0x37b95c67,0x1485074a),LL(0x0865b2f0,0x0b01af95),LL(0x90ce0b41,0x43033ffe),LL(0x71504d6f,0xffd6e34c)}}, {{LL(0x1aa946c8,0xb380cd60),LL(0x806b2e19,0x7f7cc73b),LL(0x2db88e6d,0xc17df7d8),LL(0x072e5416,0x7b767ca2)}, {LL(0x0ad6134b,0xbb42d3ed),LL(0x640df8af,0x5444339f),LL(0x5bc73112,0x7e7c7e7b),LL(0xf899dba4,0xe8f139b4)}}, {{LL(0x43a06bf3,0xd13b436d),LL(0x773e4863,0xe43f8567),LL(0x56b814d7,0x35555cd5),LL(0xd429ccc8,0x54af8e53)}, {LL(0x82ae0477,0xc346718f),LL(0xbe02c7a8,0x301fb382),LL(0xd2a70595,0xcd65b3b2),LL(0x5aad01d6,0xcfcff499)}}, {{LL(0x589feca8,0xd0fcc076),LL(0x7c603ed8,0x7b2b93c7),LL(0x6ddfc3b8,0x2dda7a8c),LL(0x74723d99,0x678d66e9)}, {LL(0x6db60b07,0x0f7e4215),LL(0xc0bfa2f9,0x40666848),LL(0x8e116caf,0x70b46b5c),LL(0xfba46d90,0xbd753511)}}, {{LL(0x019d8279,0xe48374cd),LL(0x309b0fc6,0x7d40e6e2),LL(0x9dec7a42,0x226435ee),LL(0x4243e7d0,0x818e79cb)}, {LL(0x54658634,0x3d7376d7),LL(0x9f8727ac,0xa40cafeb),LL(0x81f556bc,0xdc1d09f0),LL(0x63223573,0x32ca7367)}}, {{LL(0x5810a27d,0x92e10f91),LL(0x1fdf969f,0x6fb34bad),LL(0x657a067e,0xe5c2b2ff),LL(0x382ba37a,0x173c0900)}, {LL(0x86d87c1e,0xdd5113c8),LL(0xcaf77294,0x56a2ca9d),LL(0x666a9821,0x9f956881),LL(0xa3b18c0f,0xc4bcafc7)}}, {{LL(0x2b02578b,0xb100f338),LL(0x64b2c607,0x4716339e),LL(0x5b161179,0x92c923ae),LL(0x0df442a0,0xada2e4da)}, {LL(0x47f85474,0x4d4b90c5),LL(0x824e3195,0xa378bf79),LL(0x2478a0d4,0x4469339d),LL(0x0c1e69e2,0x0972e788)}}, {{LL(0x72edc384,0x1aedd761),LL(0x9898d672,0xcabcd976),LL(0xba814ca2,0xd370aa7a),LL(0xe88eca9c,0x20fa58db)}, {LL(0x45a7ab8d,0x1540ada9),LL(0xbdca94fc,0x8dcf9860),LL(0xaa9df4f4,0xf0187e2c),LL(0x54a49576,0x9a197dc3)}}, {{LL(0xb4a1f341,0xb54f5cb2),LL(0xfe32827b,0x1439caf0),LL(0xd36783f5,0x3c1a356d),LL(0xc56a6e47,0x284e2f15)}, {LL(0x4dcfaddf,0xc6abad59),LL(0x082bb2b4,0xe82993f7),LL(0x23655955,0x3cb46972),LL(0x992551e3,0x8ab06385)}}, {{LL(0xdaa13ab3,0xcbd6cb99),LL(0x2dc1333d,0x01375bbd),LL(0x972c4440,0x638a7f20),LL(0x24dcb1cc,0x150665c6)}, {LL(0x1ea989c6,0x4044e12f),LL(0x61012ea3,0x204c4eba),LL(0xac2719c1,0x78b8edaa),LL(0x2ab50d99,0x6772643d)}}, {{LL(0x606d63de,0x94604146),LL(0x693aadc8,0xa876d9b0),LL(0x667044ff,0xf7401ffb),LL(0xb599ecb4,0xab98d73e)}, {LL(0xda5cbee3,0xe2b2048f),LL(0xa2b3da50,0x526e3aa1),LL(0xb4ad2073,0x4d0885e3),LL(0x644a1a19,0x916ce3d2)}}, {{LL(0x96930e8d,0x952b5747),LL(0xb0cf7f5f,0x2a489fd6),LL(0xa8b3b538,0xbff4b59b),LL(0x6aff1cbe,0xba0e03ff)}, {LL(0xd56b2285,0xfa614adc),LL(0x50d58e62,0x2305edd4),LL(0xe36877e9,0xb349fdce),LL(0x43a6103b,0x5f808fc2)}}, {{LL(0x86493abe,0x66d8404b),LL(0x9b08ff7d,0x18c92d3d),LL(0x89754762,0x6a60ab6b),LL(0x8233dee7,0xec69fd4c)}, {LL(0x06beadfa,0x32449242),LL(0xe0df7084,0x421caf1e),LL(0xd7969339,0x6f89693b),LL(0xfa30a7a9,0xb9a53713)}}, {{LL(0x11556d9a,0xf89d9bf5),LL(0xee8cf993,0xe4e9c5f0),LL(0x17ed9a7e,0xe5b2a323),LL(0x93e80c9e,0xd4db3920)}, {LL(0x1fda3726,0xae857864),LL(0xa3e88485,0xe5cb36a3),LL(0xf495b9a8,0xa6b85205),LL(0x38f3b180,0xc1be0108)}}, {{LL(0x36a1f3a8,0x79d0585b),LL(0x913ba5f2,0xa3d8f17f),LL(0x225acf11,0x1eaee5d6),LL(0x0d32de79,0xd4dfd0a2)}, {LL(0x6b3ceff3,0x0cec324b),LL(0xab447870,0x3acc6dec),LL(0xb9c759ac,0xabbf7e6d),LL(0xa5196938,0x0d5c1f47)}}, }, /* digit=28 base_pwr=2^196 */ { {{LL(0x45e7ea91,0x781a2157),LL(0xacadfc40,0x4da3f86d),LL(0x162cd393,0xc81d6c7d),LL(0xad6e60fc,0x2c38a2a1)}, {LL(0xf753479d,0x575b25d6),LL(0xbdec6025,0xc914e08e),LL(0x492d5547,0xf81cea34),LL(0xfb1b6969,0x6bbb8bb1)}}, {{LL(0x1279504c,0x1ee8082c),LL(0x2c92ffb7,0xa466abb2),LL(0x3e81c7e2,0x4118b26a),LL(0xfc60e33a,0x1a76cc50)}, {LL(0x5736d7ae,0x34998bc2),LL(0xbd1ef993,0x20b39558),LL(0x5fbf2525,0xd669e2ae),LL(0x01cc7626,0xbf956ec6)}}, {{LL(0xb0ccbaa5,0xce817029),LL(0x279b78a6,0x57ef5bd2),LL(0x4df45d89,0xc9283747),LL(0x2ec4bfd3,0xe86b91a8)}, {LL(0xfe565915,0xe5ab4c6d),LL(0x7c58a042,0xe6574716),LL(0x6301c4bc,0xe141deda),LL(0x8084513a,0x2f95d561)}}, {{LL(0xeecede3d,0xdc424508),LL(0x386440d0,0x11889b35),LL(0x98de0d77,0x7b229f93),LL(0x300a7447,0x73fced8a)}, {LL(0xe31c8f88,0xf75e1c79),LL(0xbb277e4f,0x8db20bdd),LL(0x2b87c02c,0x8ded0a70),LL(0x4d164c1a,0x166281b5)}}, {{LL(0xeedd8e0c,0x887356cf),LL(0xe44c012b,0x8afab37f),LL(0xe4aa3eb6,0x0795935f),LL(0xda6dfa57,0x9b9efc0c)}, {LL(0xa8ab0840,0x0ff0f8aa),LL(0xc8561605,0x0f3a4b63),LL(0xd5db9315,0x2ca911ef),LL(0xc8ded9f8,0xef70e5ba)}}, {{LL(0xa6aae58b,0x443d9209),LL(0x274edda3,0x3d0798e8),LL(0xc2be3c9a,0x5c2d462c),LL(0x439882dc,0xb5488239)}, {LL(0x977d4de4,0x6391bb41),LL(0x1e8245c4,0x7fd91040),LL(0x3b093dc2,0x1a6d3c71),LL(0x7b22fe12,0x423a4e3a)}}, {{LL(0x3a9a04a3,0xe3156f40),LL(0x297d9aff,0x9b32c4e5),LL(0x62a89850,0x7e0b401e),LL(0xa84ef082,0xffbf542e)}, {LL(0xf990caf5,0x377cc0e0),LL(0xec88ea9b,0x02704343),LL(0x63f96a51,0x846fd46c),LL(0xe9855c47,0x37f5cebf)}}, {{LL(0xe6ad29dc,0xbd140bd8),LL(0x6a04da28,0x7dca4b10),LL(0xade05b33,0xa84feafc),LL(0x7630aacf,0x44d031f8)}, {LL(0xcdee269c,0x18af2fa6),LL(0x8697a40b,0x1e40571b),LL(0xf0e5f826,0xf71d44ad),LL(0xa434cfe6,0x2a47ddf9)}}, {{LL(0xad17cc54,0x22b97078),LL(0xf2c105b2,0x223732dc),LL(0xe284fae8,0x25168336),LL(0xb356407b,0x41b1bb94)}, {LL(0x89933a11,0x299e7d7a),LL(0xff7dd9f6,0x19e13d3c),LL(0xf23d7ca7,0x9517bd16),LL(0x1eb978a4,0x9e5e9e34)}}, {{LL(0x5fa3f92f,0x4c222dae),LL(0xed489ca7,0xd5e38e84),LL(0x70ea613d,0x3d81aca4),LL(0xbe4e88f6,0xc7bed301)}, {LL(0x0757d8db,0x6fd5a7bf),LL(0x7a9181b0,0x1472441d),LL(0x5a90b66f,0x78b78753),LL(0xabdae620,0xe3fd5e91)}}, {{LL(0x84535653,0xea6a77d8),LL(0x81d7e667,0x8d241deb),LL(0xfaf4ef1b,0x1af73798),LL(0x3e0dae27,0x5e1ae728)}, {LL(0x2f7450b5,0x6a67088c),LL(0xda9cb3c6,0x7bccbe06),LL(0x5b808e05,0x520fabab),LL(0x702b247b,0x84222f68)}}, {{LL(0xe0bd7ef2,0x2471546a),LL(0x656a62a3,0x27d310dc),LL(0xad35da30,0xb8014eca),LL(0x7f35cd7a,0xbdfdcd82)}, {LL(0x040ae645,0xf1e4d51f),LL(0xf42a4d9b,0x672ffadf),LL(0x2d0be1c0,0x9d874370),LL(0xc6e55471,0xcc3671c6)}}, {{LL(0xbb9c9667,0x39aa705c),LL(0xc51f661d,0x8c3e584a),LL(0xe570769c,0xe5645b1d),LL(0xbc97abf4,0x81923fda)}, {LL(0x0caac97c,0x51d64f64),LL(0xff847f4a,0x45c17651),LL(0x8cbfa2c7,0xc7a6eaf9),LL(0xba8ab893,0x6c2ab9f7)}}, {{LL(0xf435624e,0xbdaa2c7b),LL(0x1d961058,0xc113e971),LL(0xa2021a1c,0xb230f1b0),LL(0x521a4816,0x6b34e1ff)}, {LL(0x9b874f4d,0x159dc24d),LL(0xbeaab169,0xeaa0f951),LL(0xb56f4916,0x4f38733f),LL(0xdc9d3ac7,0x4ee689db)}}, {{LL(0x7bf8d03b,0x720254bb),LL(0xd31d7679,0x78b0e6d6),LL(0xf130d7b0,0x848fb878),LL(0xd3ba625a,0xe8e478ec)}, {LL(0x100dfefb,0xb0ce9168),LL(0xe5098aa8,0xfe1463ab),LL(0xa11ec558,0xf780ac38),LL(0x8e474b9f,0x92f15c52)}}, {{LL(0x46410cb1,0x3b3892d3),LL(0x03a5a136,0x72097f22),LL(0x98de068d,0xdb3a1b80),LL(0x4b1a3890,0xfb7438e4)}, {LL(0x3839d3d9,0x8a10d5ea),LL(0xf4bd8126,0xd9ad034d),LL(0xd4800261,0x07d108ef),LL(0x9c5d6c52,0x978d98ba)}}, {{LL(0xecb9ce1c,0x63ae69e1),LL(0x51b28f39,0x70d2b437),LL(0x77f848a2,0xc15696b6),LL(0xd8ab4d76,0x6b6e60f4)}, {LL(0x030bf112,0x33a581a4),LL(0xc5e74a76,0x9cdb1a6e),LL(0x7a950053,0x6c6f6ec4),LL(0xb04ebcff,0xd47dc472)}}, {{LL(0x5e0970df,0xe85ca76a),LL(0x78988af2,0x74448d98),LL(0x81620019,0x5227649b),LL(0xaabc2027,0x47e2ac62)}, {LL(0xfbffedf2,0xfea15155),LL(0x3b4cb501,0xa565c484),LL(0xd830cece,0x4c523be5),LL(0xc321a440,0x2e2de6bc)}}, {{LL(0x8d69887d,0xa7d62771),LL(0x4e138de4,0xf9d8ac67),LL(0x9fcb0a09,0xad3fbc08),LL(0xbfc3bc9a,0xcaabb0b0)}, {LL(0xb1c20604,0x84646bc3),LL(0xd1574260,0xf1059ac4),LL(0xeefff298,0x5c15c6a2),LL(0xf3b0a393,0x7975ede6)}}, {{LL(0x27c2343a,0x0ea9d355),LL(0x4b32e339,0xe21c75e4),LL(0xa7fc353a,0x1438785e),LL(0xe9a1dd56,0x0b8d64ba)}, {LL(0x75347c02,0xcacf9b64),LL(0xcaad57aa,0xf788c83e),LL(0x36ecf2e0,0x90df1ab8),LL(0xf45070ac,0x4db604a3)}}, {{LL(0xb4c4ed93,0xbc76e168),LL(0x85b65a6c,0x07177b5e),LL(0x00d21309,0x41e3c275),LL(0x76a48f42,0xcc9678e4)}, {LL(0xb1c6256f,0x3a04d197),LL(0xb2cc7330,0x940920a9),LL(0x2523d52f,0x990e4da8),LL(0x5a59d733,0x34709b24)}}, {{LL(0x8e745028,0x2f0da81c),LL(0xcd5668ab,0x32b5f384),LL(0xee538e7e,0x82744a5a),LL(0xf3eb2516,0x1b019bab)}, {LL(0xd79d735f,0xccbd28fb),LL(0x85f90aa2,0x0bb54a6e),LL(0x9a69ecaf,0xacf5552f),LL(0xd1f1e30b,0xbc51ee85)}}, {{LL(0xfa25193d,0x12bf8b0b),LL(0x5ba4b3c8,0x3f0f51b0),LL(0x66181f23,0xc1b65deb),LL(0xc0156b03,0xfeb037f9)}, {LL(0xa9dc59ed,0xdd7a0a8c),LL(0x7b57e018,0x20b5c8ea),LL(0xefaadad5,0x0c3ebc94),LL(0x18758eba,0x146d05b6)}}, {{LL(0x09c7b43c,0xcb952e41),LL(0x1c1b8fb6,0x7f7a0ae3),LL(0x331dfb05,0xbca8a9cf),LL(0xe0db9d7d,0x4a1db4a1)}, {LL(0xe5b9c892,0x988d36a3),LL(0x010ad00e,0x64640e55),LL(0xc011bffd,0x4c33c7e8),LL(0xa0ad217b,0x5d7cf370)}}, {{LL(0x71f3df52,0xbaf8b74a),LL(0xa5995b20,0x300963bc),LL(0xd6c27636,0x695cf7ee),LL(0x03ac244e,0x74d4d3a1)}, {LL(0xc898e5bb,0xddba3bd6),LL(0xfe3499f7,0x27573a89),LL(0x4b0a6c98,0x666b4415),LL(0xaa4ccfaa,0xf4f3e8c5)}}, {{LL(0x1a5b919b,0x5f136875),LL(0x670d4b04,0xed8eb5db),LL(0x0d0d73bf,0x4cd83d19),LL(0xbdf22579,0xd2a5c62a)}, {LL(0xc2d04c2b,0x8c41be16),LL(0xbf9ad465,0x5aa33bc4),LL(0x5e00d922,0x36e20646),LL(0x00b70e17,0x9df21e7c)}}, {{LL(0xd440af4d,0x0601e630),LL(0x963e87dc,0x4aab0d33),LL(0x36d39000,0x2712abdb),LL(0xf9147e2a,0x856d7e3b)}, {LL(0xc8e5d2f4,0xadc4a96a),LL(0x2e70c206,0xac3e5336),LL(0x6f6f3d0e,0x1ee7d838),LL(0xead72426,0x4674ef20)}}, {{LL(0x6af5f580,0x3a804dd8),LL(0xd74ea5ce,0x724a756b),LL(0x0432d854,0x0c2968d0),LL(0xa4f262fe,0xe3be03f3)}, {LL(0xc84c22bb,0xe446692a),LL(0x9647650d,0x156b3168),LL(0xb5d3d62a,0x4e06bc39),LL(0x80eea174,0xf99d4fec)}}, {{LL(0xc08f1144,0x3a2b7ae8),LL(0x12dae8d6,0x35e65bf9),LL(0xae3892b5,0xfa0af1cf),LL(0xac408112,0xa57062dc)}, {LL(0x24bf1af9,0xef6a9ec3),LL(0x5decd8bc,0xdda3b476),LL(0x7bed3775,0x9314a36c),LL(0x60aa296e,0x9e254b0e)}}, {{LL(0x65b9cf2c,0x8be2de80),LL(0xcb3b96cf,0x1b110df6),LL(0x18957e21,0x0f647a12),LL(0x4f907766,0xa1e11238)}, {LL(0xc5528977,0x751a0d82),LL(0x9a4b1260,0x958d8738),LL(0x773658ee,0x99087543),LL(0xf19f74cf,0x18148bbe)}}, {{LL(0x0a19a374,0x5f50ef19),LL(0x6bdd3392,0xc5bc4160),LL(0xb80ad74c,0x1bdf5e4b),LL(0xed7e68c8,0xc40ec2f7)}, {LL(0xdecef5b8,0xedd7dd6a),LL(0x896c95a3,0x3d29a1cb),LL(0x70ad41d4,0xfa84c325),LL(0xc398c177,0x6a577072)}}, {{LL(0x7375f2de,0x4f942d01),LL(0x8aa1523a,0x968a7608),LL(0x377e5c4c,0x55dc7da6),LL(0x282b540e,0xb75fff53)}, {LL(0xfd4b6951,0xfee35c15),LL(0xf04ddfae,0x6d1d64f6),LL(0xaf7c8714,0x320f1769),LL(0x482ba6fd,0x2b5f86a4)}}, {{LL(0x1ab9986b,0xcf691cb7),LL(0x7377ba6b,0x42913d71),LL(0x1e47bf08,0x120b4601),LL(0x764b2661,0xfb514e52)}, {LL(0xa140ae04,0x371c0155),LL(0x2e186763,0x94e65b70),LL(0xd5764306,0x5e440f7b),LL(0x7b8a5eeb,0x3411dadf)}}, {{LL(0xf0e3e158,0x6c25e519),LL(0xe8898c80,0x46ee66d6),LL(0xec4f9b03,0xa0e9d4b1),LL(0x126c1f31,0xba48d97c)}, {LL(0xbdbf0928,0xb9f96818),LL(0x7f51cb48,0x293ce87d),LL(0x76f09d38,0x077a7420),LL(0xedea4c81,0xc71cb875)}}, {{LL(0x9ddd1485,0xfeda750d),LL(0x51c10504,0x987876dc),LL(0x75ec7922,0x4d0253f8),LL(0xc676b336,0xbcc15e39)}, {LL(0xb9370740,0x33d533d8),LL(0xcb8c88ab,0xc5c482db),LL(0xc7c08a75,0x1ff3f223),LL(0x401b00fd,0xccfaf564)}}, {{LL(0x6ac9757c,0x6ba93d3a),LL(0xec2c92a0,0xff09b546),LL(0xc5960be8,0x95d3436c),LL(0x69029082,0x90b7e8cb)}, {LL(0xdb6b32e5,0xbdd1e2b9),LL(0xfd47ad85,0xf4d2e43b),LL(0xcb005dbe,0x8923251e),LL(0x662912e7,0xc21368a0)}}, {{LL(0x062d205c,0xc7ce2963),LL(0x9542b831,0x1e8f812f),LL(0x818c322d,0x4f8a7915),LL(0xfb678809,0x50073cba)}, {LL(0x0cb91b3e,0xed7b5237),LL(0x60d3fe6b,0x22d1fa41),LL(0x2d690f75,0x3de39063),LL(0xf164ec1f,0x12b2e39e)}}, {{LL(0x332f408f,0xa28a0d83),LL(0x6a054db1,0xe6d9406c),LL(0x5ddd64e0,0x67369b76),LL(0x02b21c2d,0x6d671707)}, {LL(0xac42170f,0xb9ad3368),LL(0xe5802ffa,0x5e8f5277),LL(0xd9b4a0a9,0x1b4468fb),LL(0x96c24331,0x0daf8269)}}, {{LL(0xc09ad26d,0x976c2f23),LL(0x19c68d38,0xd47afe88),LL(0xd3d8d84f,0x0e96c03b),LL(0x0932b2fe,0xe05b5fd8)}, {LL(0x347fbbbd,0x13931043),LL(0xb0ccc752,0xe0fa842f),LL(0xc75bf745,0x7295ee0f),LL(0xb0aa9d61,0xebaae0dc)}}, {{LL(0x6355564c,0xb392d49b),LL(0x887c5a18,0x57e2f166),LL(0x230a278a,0x88b3a014),LL(0x4c194449,0x088e4908)}, {LL(0x43d6af69,0xc6cd309f),LL(0x589a7f7e,0x394445e3),LL(0x031e7c08,0x0610077a),LL(0xa3519f78,0xd05547cc)}}, {{LL(0x926e26ed,0x0123b543),LL(0x62d06da6,0xcd430b80),LL(0x0dcd6db5,0xddb182d0),LL(0x8eb6e010,0x724c9bce)}, {LL(0x50a4a597,0x985a2f0f),LL(0x900f2a49,0x35f2427f),LL(0x13cbf187,0xce6136fe),LL(0x1086c2aa,0xc893bdee)}}, {{LL(0x07eca624,0xe2410ccb),LL(0xddf9afb0,0xeda92913),LL(0x5bb66033,0x8fc0cfd0),LL(0x0509ffc8,0x0ab7d29b)}, {LL(0xb3d4f10a,0xc063b004),LL(0xeb8cf642,0xed94a955),LL(0xa272ac4d,0xacfb2f14),LL(0xc4ebbf0b,0x10f2c91a)}}, {{LL(0x06ea04eb,0x73f6e02e),LL(0x8b97ea93,0xb969e8f8),LL(0x0cd48657,0xa9b27472),LL(0x99264937,0xe1a874ec)}, {LL(0xf794332d,0x34e677a4),LL(0x5ee2daea,0x5e67865e),LL(0xe6886879,0x3fe02b91),LL(0x0f9776ad,0xe113432f)}}, {{LL(0x6a2c47d1,0x37567306),LL(0x62feb54a,0xf66df9b8),LL(0x3e07ce56,0xf734ee37),LL(0x659809fd,0x50c4982d)}, {LL(0x9daf8faa,0xe2fa768f),LL(0x8b9fd7c3,0x66088ddc),LL(0x333683c6,0xb8265661),LL(0xdff2a0a7,0xe7dacf81)}}, {{LL(0x5e3da06c,0x1e99d6bd),LL(0xbae05a25,0xbd50e15c),LL(0x802d7b40,0x47a0d997),LL(0x193ef621,0x0a25b51b)}, {LL(0x148ee5a3,0x24d3d4f4),LL(0x022a9df0,0x7012618f),LL(0xf68e648f,0xb3777339),LL(0xd7544352,0xcdfb557f)}}, {{LL(0x1f912c5f,0x4b0b2d46),LL(0x957515d9,0xddaf929a),LL(0x0ae46856,0x29e4bf1f),LL(0x44e32ab0,0x158b4c85)}, {LL(0x7c48d2d2,0x17935398),LL(0x6f2430bc,0xe4ab6300),LL(0x0d8b24d4,0x71dd7284),LL(0xfc21d7e4,0xd9303af1)}}, {{LL(0x450f7f6d,0x816c616f),LL(0x3306df19,0x17875d8e),LL(0x087e86e0,0x7ce8d4a5),LL(0x36251f01,0xa53970ac)}, {LL(0xfc98edaf,0x2037f12c),LL(0xabf72b6f,0xc359a382),LL(0x85130fa6,0x06acf1a6),LL(0xadfe4344,0x08f45064)}}, {{LL(0xdd857b31,0xc01e1f3b),LL(0xc9513734,0x92c2263a),LL(0x589327b8,0x562652d5),LL(0x96a1c164,0xa8edd065)}, {LL(0x79f8df8d,0x2cbf8f98),LL(0x40847dde,0x3d5cf771),LL(0x597c0622,0x69b08ee4),LL(0x8a868f2a,0xfff18c4d)}}, {{LL(0xf5ad0686,0x28bca3d2),LL(0x2d4eef7b,0xf7992f89),LL(0x3977e15d,0xab10b9cc),LL(0x2db8ef03,0x47912ca1)}, {LL(0xdf27884b,0x1f3e70e6),LL(0x0e9d8efa,0xdd9bb81e),LL(0x279e27f6,0x97a83b6f),LL(0x24daf922,0x47e259fb)}}, {{LL(0x124e71be,0x49eb72bc),LL(0x3a6778ba,0x01dba001),LL(0x3be03050,0x8d02baec),LL(0x6dd6c8ef,0xe3571b3c)}, {LL(0x2cc11ffe,0x6e1ffbac),LL(0xf4e2e6f0,0x6d725c75),LL(0xf2b53a58,0x96c31b45),LL(0x97f1634b,0xa0e38dd7)}}, {{LL(0x143ce001,0xe8507959),LL(0x8b49cc63,0xad9a9f52),LL(0x8438b0fa,0x950fd33d),LL(0xbe0cbdf6,0x2b294c00)}, {LL(0x937b00ce,0xb2076b47),LL(0x78041498,0x026153a1),LL(0xe9e53d27,0xe958f12d),LL(0xe8f8fad9,0xf49e1124)}}, {{LL(0x2bca0ae1,0xb78a5b74),LL(0xcccdc3d3,0x35180dec),LL(0xa97e519f,0x15e4fba5),LL(0xf5b8340e,0xe49dac9d)}, {LL(0xe5978024,0xdbd8ed3a),LL(0xeb105505,0xd181f26a),LL(0x29f57098,0x38364818),LL(0x3900171a,0xd674fe1f)}}, {{LL(0xf1bd5803,0x5a2ff729),LL(0xeda23387,0x53de7261),LL(0xf0dc417c,0x7f1d84c8),LL(0x5360fa80,0xa65694a7)}, {LL(0x96ed36e6,0x356e4518),LL(0x406bfd36,0x127a52de),LL(0xde925d04,0xb575a98e),LL(0xc0627c4f,0x35fb44be)}}, {{LL(0x471e745a,0xc85f2c69),LL(0x6213d79e,0x1c01e1ea),LL(0x2f5081f0,0x95ea99a1),LL(0xc3367864,0xdb38bd3e)}, {LL(0xd8880436,0x0e8cafec),LL(0xf9c63d09,0x1d59fd74),LL(0x7f875dbb,0xe57b0b4f),LL(0x77084bd7,0xe266c939)}}, {{LL(0x2fc1f909,0x0e289c5a),LL(0x86c4fc40,0xece9d225),LL(0x5d79b4b3,0xe0a56fbe),LL(0xd4489041,0x2b96fae7)}, {LL(0xe23c85e7,0x0f66316b),LL(0xadfef0c2,0x2d1a3c78),LL(0x9fbce9cd,0x1aece4ad),LL(0x6c32d32d,0xccd0f334)}}, {{LL(0xfb9ba6dd,0x958d7a5c),LL(0xe673275d,0xa0052032),LL(0x7f978d07,0x514ffd9d),LL(0x450b76e1,0x544bbce9)}, {LL(0x6b5201b6,0xeaa25d74),LL(0x74d082a5,0x7528a4ea),LL(0x66609e27,0xa08c8d31),LL(0xda7c6fd9,0x5150d1be)}}, {{LL(0x39930618,0x864f5b4c),LL(0xcebb516e,0xe71e7f1a),LL(0xebf1f8ac,0xaeee7fa5),LL(0x0ea827c6,0x6efcad4a)}, {LL(0x74e21dd8,0x6e0f4ecb),LL(0xf33a7939,0xc5311600),LL(0xa4d93fc4,0xdf62f3c3),LL(0x9a18476d,0xd3b62727)}}, {{LL(0xc0e1256b,0x0b54f5e6),LL(0x97ba9afa,0xe8987efb),LL(0x41d11c15,0x4b6ea064),LL(0x79b79f0f,0xfed7017e)}, {LL(0x5bd04e40,0x5a6bcf9e),LL(0x8fd3b4bd,0xf3090153),LL(0x82240648,0xa23b5acb),LL(0xb16cf033,0x61d9a8b1)}}, {{LL(0xc9fbee1e,0x2feb1706),LL(0xd7e07918,0xfaa4cd69),LL(0x447cba7a,0x28562c58),LL(0xa61a1064,0x727926c4)}, {LL(0x97ac7eff,0x1b32db7f),LL(0x452253ce,0xfd968b22),LL(0x5cdd3217,0x69d1842f),LL(0x26f4007d,0xba7689da)}}, {{LL(0x141c8b35,0x16445a64),LL(0x73c61779,0xc11c3101),LL(0x485300ee,0xa5aa0d18),LL(0x1cc02bf0,0x531b6de1)}, {LL(0xc4efeb2c,0xf8b94155),LL(0xd015a9c8,0x83632663),LL(0xcba18b7f,0xc369b3ce),LL(0xc29e0f9b,0xe11b3ef6)}}, {{LL(0x903ca95b,0x1a5e9bf2),LL(0xa50cb332,0x2d9aefc6),LL(0xb29ce693,0xb5670264),LL(0xab1d7b7e,0x806d08ac)}, {LL(0xc9107eac,0xcbdfdf28),LL(0x6cdf12ac,0xa8086243),LL(0x903d5999,0xe7d9c315),LL(0xc079d951,0x4379820b)}}, {{LL(0xbf1edf4c,0xe789ecad),LL(0x47bc7752,0xec086811),LL(0xc2fc8798,0xeea2eeb8),LL(0xe031a96b,0x763183e0)}, {LL(0xf9a6bfaf,0xc7daf0b2),LL(0x4b957cf7,0x1a2a7ffb),LL(0xbf2d2e7d,0xa483c7c8),LL(0x58ff7f9c,0xf96921fc)}}, {{LL(0x574ee010,0x41386185),LL(0x2780c649,0x62e6a1d8),LL(0x60f2516e,0xdec553af),LL(0x7a04eb11,0x5b091537)}, {LL(0x67eb90c5,0x1b53e9dd),LL(0xddfda333,0xc390a23a),LL(0x480568aa,0xdd4e7c6d),LL(0x59ccbe61,0xd6c1e8a8)}}, {{LL(0x9107901b,0x1c6fd7a9),LL(0xa211d116,0x5dc4a41e),LL(0xaf1b78a8,0x597e94e7),LL(0x53afcb6a,0xe72da34d)}, {LL(0x74512c24,0xbc364db7),LL(0xb2811e91,0xc26a8fb9),LL(0x290469b1,0xfdd39d7f),LL(0x20612535,0x84515392)}}, }, /* digit=29 base_pwr=2^203 */ { {{LL(0x1539cf31,0x7fe996a0),LL(0x0ded7c6e,0x4a3f729a),LL(0x3016f614,0x86f1f299),LL(0x86cb9163,0xc3d44e18)}, {LL(0x558fa36c,0x96984531),LL(0x369c89d6,0x58e8bf05),LL(0xf9ee923f,0x287da114),LL(0xec271fbc,0x2032e984)}}, {{LL(0xd39207ad,0x91b8579d),LL(0x0b1fe916,0x6f62c725),LL(0xd89e01bf,0x0f1599ac),LL(0x4d1e5843,0x8d9bb86d)}, {LL(0x726e38d1,0x348b90d4),LL(0x52a8c6b9,0xb824a1ca),LL(0xb1d2f6f4,0x984d9309),LL(0x431ec12e,0xefa485b7)}}, {{LL(0x9d616a5c,0x24cafa66),LL(0x4c9d0ea8,0xc1c7445f),LL(0x90bee7b6,0xf733e085),LL(0xd251d2ba,0xa2f3ece3)}, {LL(0x66aeba6c,0x6e422a45),LL(0x37c1337f,0x35e99b16),LL(0x6d4f8d03,0x52d0fdf7),LL(0x79c92672,0xa043420c)}}, {{LL(0x76ac1925,0x99725607),LL(0x3442fc58,0x086449db),LL(0x2e311e74,0x8dbab920),LL(0x7ea25561,0x29dee69b)}, {LL(0x19a7cd6c,0x5a62b6ee),LL(0x0d0dd5a0,0xba38cc4c),LL(0x166d0ff1,0x779279e5),LL(0xf48b3dae,0x0eef53cc)}}, {{LL(0x0f82c6a6,0x0463dcaa),LL(0x11d7d6d8,0x75dfc96d),LL(0x6c100d92,0x61f05e7b),LL(0xe13eabb4,0xa118e548)}, {LL(0xdcdf06b5,0xcc77e3c8),LL(0x6ac25960,0x902d37d6),LL(0x347d7116,0x967d9993),LL(0x9ae33561,0xd2828650)}}, {{LL(0x8c7c6d89,0x955b7840),LL(0x42c2555f,0xbfa78bc8),LL(0xa69c3165,0x8c56ae3d),LL(0xe33bb1bc,0x72b20e72)}, {LL(0xd1aa6416,0x686870b4),LL(0x7db03cdd,0xf000040b),LL(0xb0a0fd40,0xd25b16a9),LL(0x36815f1f,0xeb89e932)}}, {{LL(0x349b549c,0xb3e5e912),LL(0x086c4e74,0x801f788e),LL(0x0082ae92,0xafb9ea4f),LL(0x0d740026,0x4e8f27a4)}, {LL(0x05f4a6ac,0xc4f8285a),LL(0x0adcd58c,0xefea5297),LL(0xc52f8c21,0x9d5b6ae5),LL(0xe97af4dd,0x92622a7a)}}, {{LL(0x79f34a8a,0x39b43935),LL(0x30046435,0x61acf55f),LL(0x3f05fdb1,0xf0a23fe6),LL(0x0c4fa7ff,0x7d6baee1)}, {LL(0xe2daf735,0x253f62b6),LL(0x2948637b,0xe370ead8),LL(0xd84e6206,0xda57c16a),LL(0x0dd22ad3,0xf19ffe09)}}, {{LL(0x95bf2003,0x701acab2),LL(0x9dff6efc,0x50e4e10a),LL(0x43b95430,0xe637bcf0),LL(0x85050cbc,0xac45cd3e)}, {LL(0x80639e4d,0xc2ebff64),LL(0x3056f603,0xe5af1fb5),LL(0x08b17132,0x302791d5),LL(0xed517904,0x87775ac4)}}, {{LL(0x4263a566,0xfe64ed1e),LL(0x1d5e8f55,0x735bbee4),LL(0x8294342c,0x9ac61915),LL(0xd4904935,0x0f522e5a)}, {LL(0x7c1e11f4,0x2ee883b5),LL(0xf0c237f4,0x0a2ce30f),LL(0x8d955086,0xf4a7157b),LL(0x022dc2db,0x7ec0462e)}}, {{LL(0xca391b0b,0x562fb75b),LL(0x3bb1efd6,0x13030aac),LL(0x347f44fe,0x305d9831),LL(0x94b2615b,0x9f70c1ad)}, {LL(0x4162ff22,0xaaf935f4),LL(0xa68d160e,0x2b20f047),LL(0x39222d1b,0x30d52a97),LL(0x6551642f,0x051223b1)}}, {{LL(0x39620daa,0xae65a5c7),LL(0x6f7c078f,0x8ef6f93f),LL(0xb0177db8,0xb06d52bc),LL(0x68fdf535,0x915cdd08)}, {LL(0xc5183222,0x0070d150),LL(0x7817a2ae,0x2b6495cd),LL(0x0b194f0b,0x3ce47614),LL(0x513bfdfb,0x2eec6acf)}}, {{LL(0xf3dbd34d,0x725dbede),LL(0x3621fc75,0x01c4412a),LL(0x3c07f048,0x17bd68de),LL(0x62e735eb,0x117df57e)}, {LL(0xb249c407,0xb1596c6d),LL(0xd46c55c4,0xa878f56a),LL(0xb8aa0cb4,0x33385670),LL(0x800ec887,0xc7faa80e)}}, {{LL(0xd7daf836,0x2cd2814f),LL(0x0d616922,0x877b72b7),LL(0xdb066012,0xea73ca1b),LL(0xb0d4159d,0xbe336c7b)}, {LL(0x0f8fcd76,0xb993b07f),LL(0x8a593562,0x5fdceaba),LL(0xf691ec19,0x716595fb),LL(0x8e68e3c0,0x51a77f61)}}, {{LL(0x7a7c18db,0xe9e4cdfe),LL(0x7b4f69b7,0x967d3575),LL(0xa9a434c1,0x6dd350a1),LL(0x00c79ba7,0xb92cdef9)}, {LL(0xa6bb0f93,0x7a762493),LL(0x8158ad36,0x6c18cdc2),LL(0xc529ecfd,0xa0bd83e3),LL(0x3962f96d,0x98363c59)}}, {{LL(0x1d63aa7f,0xd80f45a5),LL(0xb3b32da2,0x8d5eba75),LL(0xa4708858,0x0ef233df),LL(0x52161c61,0x74c3f4f7)}, {LL(0xe6420de4,0xfa9bfe6b),LL(0x97dd86d5,0x96c0c501),LL(0xcfce233b,0x28e6827b),LL(0x58e74d63,0x035cc9a9)}}, {{LL(0x7948782d,0x9ba64bf4),LL(0x80d9ce1a,0x5e5b7c72),LL(0xf51df862,0x7b9435db),LL(0xb4dd2421,0xe74ab6e8)}, {LL(0x60954c75,0xb0d704db),LL(0x0b59ae5b,0xd31c5145),LL(0xd99ba307,0xe0ff4660),LL(0x986bd82b,0x1a3800fd)}}, {{LL(0x509a0a50,0xe7e06ab7),LL(0xe4539885,0xbdf63778),LL(0x16ddb433,0xf888320f),LL(0x18e18998,0x0f108304)}, {LL(0xfa834b14,0x27e7ffd6),LL(0xc68b9434,0x16de9a71),LL(0x4d360436,0x53a12e2c),LL(0x5e110b02,0x5ad2c986)}}, {{LL(0x3cf53e0c,0x3439443c),LL(0x1d65a7a3,0xfeae29b0),LL(0x78ad7d78,0x1e7774f6),LL(0x6fee368c,0x0c79fb01)}, {LL(0xe4faf3ee,0xbec71de1),LL(0x263868e8,0x1a88f3e5),LL(0x90e91a8c,0x975d8381),LL(0x0f999c60,0x69c5a65d)}}, {{LL(0x8b884857,0xbd3360d8),LL(0x31b7c579,0x04190413),LL(0x142cc145,0x40dd9229),LL(0xdad0b2df,0xb5faab94)}, {LL(0x52df4831,0x3e7d7921),LL(0x228bf67d,0xcf5bd1ed),LL(0xc4980085,0xd8669635),LL(0x1c71903d,0x094b8973)}}, {{LL(0xc4abb028,0x493a7a3d),LL(0xb4ab8e35,0x0e1a8fac),LL(0x017aa5f2,0x26094ca2),LL(0x021476cb,0x94fcb8b1)}, {LL(0x4abf3bcd,0x57f101f9),LL(0x2d7f12a8,0x1ac2c125),LL(0x2e42789c,0x575259d9),LL(0x22471eb3,0xa64a4a4b)}}, {{LL(0xe1c00144,0xcc02304d),LL(0x754734b2,0x6269dfb9),LL(0xf14fbc81,0x72e7a183),LL(0x2a05caa2,0xd92a5b1c)}, {LL(0x15efc2fb,0xd593492e),LL(0xd8dd458b,0x1ace7dca),LL(0xaef2ae81,0x576b4bc8),LL(0x351b397e,0x6de6a2db)}}, {{LL(0x656cf9ab,0x73f13b48),LL(0xaee7e01d,0xc18df1c9),LL(0x560355e7,0x30fb5155),LL(0x9ad059d5,0xd2c9a0ee)}, {LL(0x5e5e0c7c,0xd9f89936),LL(0xf0a6c9d7,0x5d0a2cbd),LL(0x58fa9be9,0x3c2c497d),LL(0x6ac61a2f,0xe6c6fcf2)}}, {{LL(0x35607bc4,0xf7ec89e3),LL(0x9946bf52,0x17ca00ca),LL(0x180c8bd8,0xee46be5b),LL(0xb2873893,0xd29d5eb0)}, {LL(0x97487b3c,0x348ac939),LL(0xfeef78ce,0xc18f0ceb),LL(0xf797cce5,0xfc648dca),LL(0x442148d7,0xe2467e0c)}}, {{LL(0xda6dbaf6,0x8e201ee7),LL(0xabd0490c,0xc1a93ee4),LL(0x4de7c210,0xfd0007bf),LL(0x083ffce0,0x02eccb8b)}, {LL(0x97844c8d,0xbba82bbb),LL(0x2747a430,0xb7ff954c),LL(0x18fb5f29,0xb05f0584),LL(0xee7c263f,0x35a29cf5)}}, {{LL(0x25282da8,0x5fd84efd),LL(0x7682db7c,0xc1fc84c1),LL(0x4bb291e6,0x8422b56a),LL(0x66a56078,0xce379feb)}, {LL(0xe7f045a0,0x1c3c581e),LL(0x6b3f89ac,0x8f42985d),LL(0xa6b2ba59,0x112839e9),LL(0xc2a7b29a,0x3f0c7269)}}, {{LL(0x79bd3046,0xecdadb6f),LL(0x9617ff6e,0x669f559b),LL(0x68928ca9,0x242bb14d),LL(0xc19cafcc,0x28e2b0cb)}, {LL(0x81330593,0xfb7d8954),LL(0x9fbf8665,0x5c3741fd),LL(0xc3b93e86,0xaf49e83a),LL(0x32822548,0xd60ecf7d)}}, {{LL(0x7cfb37cd,0x4bf36759),LL(0xdb7af2ed,0x94b0c7f0),LL(0xebf8b461,0x2f1bebf6),LL(0x073e5c18,0x90ebc9c7)}, {LL(0x3774e905,0xe431c793),LL(0xe03265bb,0xb8a4bc2f),LL(0xfabb629e,0x0bee0825),LL(0x84557170,0xbd1481dc)}}, {{LL(0xe1a010a0,0xa2257b58),LL(0x4688bb89,0x43f5451c),LL(0x91b96371,0xb87a5ff0),LL(0xde3c7b25,0x445dd02f)}, {LL(0x51a0964c,0x44c0c080),LL(0x9afdcefa,0xb0c3190e),LL(0x0044d258,0x14cc65ad),LL(0x374fdd44,0x8c500b3e)}}, {{LL(0x51b07812,0xed8d840f),LL(0x76530691,0xd414a4a2),LL(0x1468ef8d,0x9db9d138),LL(0x292b3870,0xfc6b7434)}, {LL(0xc9d7ad96,0x80b66797),LL(0x2a9c1e99,0x81e74eb6),LL(0x9e92f64b,0x48657d9a),LL(0x4c851ddd,0xf5c60075)}}, {{LL(0xd99d5cfe,0x08fa89be),LL(0x4db4addf,0x78b1f26e),LL(0x3523ead9,0x03237177),LL(0x6a281494,0x0147af5c)}, {LL(0x916836b0,0x8db3952a),LL(0xfd365650,0x0632b102),LL(0xccb3f2f1,0x3854a8e9),LL(0x586ad427,0x5048486c)}}, {{LL(0x17a86e18,0x22de9979),LL(0xbe029111,0xe2ac2321),LL(0x35cc5a17,0xbfd34397),LL(0x525e13cf,0x7a93461f)}, {LL(0x5122d6f1,0xd433542c),LL(0x833982c7,0x41d2d9de),LL(0x8ec24d27,0xe9f1f29a),LL(0xf3b99d58,0x4ae251f3)}}, {{LL(0x10adb458,0x7234dd24),LL(0x88379ef5,0x0e4b6567),LL(0x748dba5d,0x3007df15),LL(0x35103772,0x1485ef01)}, {LL(0x29c2382f,0xe21a9dc9),LL(0x6b6c1c8d,0xcf7e0c24),LL(0x30550c0a,0xf8a71820),LL(0xb797de2e,0xb30e5c0f)}}, {{LL(0x03705145,0xbe136119),LL(0xf94aadc7,0xe6d1f720),LL(0x255f5297,0x38ce1872),LL(0xc3143f58,0xbbba4793)}, {LL(0x0984e265,0xda5345fe),LL(0xd895e0d7,0xe93989d6),LL(0xcaab40a3,0xb7392b18),LL(0x65e754fc,0x4a586963)}}, {{LL(0xa3afd381,0xb3e88445),LL(0x693ad961,0xa6cbab0a),LL(0x257d56dc,0x64d51359),LL(0xbbde137a,0xf9e70fcc)}, {LL(0xadd016b1,0xa33872fa),LL(0x7344f234,0xd1d263d2),LL(0x24ba41b2,0xc2d51210),LL(0xe4ab65cb,0x8c9c830c)}}, {{LL(0x175b4039,0x3b47563c),LL(0x116b2025,0x53521dfd),LL(0x1a9f1cca,0xe4f3aa89),LL(0xe7cb1d2b,0xcc73485c)}, {LL(0xbf58fe30,0xa6ca61ef),LL(0x531a2b6a,0x5d50e15d),LL(0x22611c31,0x71cfdb41),LL(0x61e3d46a,0x0dc15533)}}, {{LL(0x479074ba,0xb363c60b),LL(0x24cb405d,0x2a4d8f4c),LL(0x646b7f0a,0x3d3bee13),LL(0x5571af63,0xdfa9194c)}, {LL(0xee76521c,0x951a61a7),LL(0x65eda1f1,0x67466ba5),LL(0x69ebc7ea,0xe41d33b8),LL(0xd4f4848f,0x8b6c992d)}}, {{LL(0xa5003eaa,0x3572faac),LL(0xabf54df1,0x01e36500),LL(0xac6f3af7,0x6622f12f),LL(0x0a8bb122,0xb5d7c17f)}, {LL(0x240286b1,0xd1fc1b99),LL(0xad968ede,0x519d52ce),LL(0xece28bb4,0xcd1e7d0c),LL(0x93f0b097,0x64ffc699)}}, {{LL(0x25af7d81,0xb18d51f8),LL(0x19820fb2,0x8d0bb08f),LL(0xaa344723,0xe9f45919),LL(0x5f9e0501,0x558f18ea)}, {LL(0x07cc79dc,0x56eff076),LL(0xd5fa9783,0xf171e880),LL(0x8be7f1fe,0xd5fb41f3),LL(0xd6fe9afc,0x19a34620)}}, {{LL(0x7d8a042a,0x74c2696b),LL(0x54230ded,0xcf4908c3),LL(0xdb32943b,0x98a870d8),LL(0x52f33e07,0x181cbe5c)}, {LL(0x93709d8b,0x4d9d1172),LL(0x2b2b7939,0xb800c292),LL(0xa8920f60,0xd5a1fb7a),LL(0xbf7df622,0x8d0a7725)}}, {{LL(0xe9415cf4,0x83a370cf),LL(0x62a4ff4d,0x9f24d1e1),LL(0x0a6ff7cb,0xca33914b),LL(0xda1d1aaf,0x2576f2d8)}, {LL(0xb4793101,0xbb2668bd),LL(0xca990b4f,0xb576672c),LL(0xff1d3988,0xfa165b5f),LL(0xba8c9e2c,0x273d5b18)}}, {{LL(0x720a5b3f,0x13594ae5),LL(0x2e65454c,0x38c4e04a),LL(0x55d0d903,0xc5b55d98),LL(0xf72db301,0xfabeb890)}, {LL(0x2f3deaa2,0xe471f1d5),LL(0xc5ade08d,0x3f8d39f5),LL(0x6baf9d1a,0xe08486a4),LL(0xe5140d3b,0x77c6d30e)}}, {{LL(0xd23d4e09,0x828db96a),LL(0x84dcac15,0x2de4856d),LL(0xa6ac856d,0x313c7f8b),LL(0xfe7dea98,0x7c9f671c)}, {LL(0xfebe9e72,0x4d6c14a5),LL(0x6014be55,0x185ac4e6),LL(0x5ed64e23,0x42809988),LL(0xbd6440fe,0xdc9395a1)}}, {{LL(0x24108055,0x10169080),LL(0x38961403,0xfe0d9cb0),LL(0xceb87d29,0xf88e6a48),LL(0x69618944,0x0365ca2f)}, {LL(0x9fb59ec9,0x1504647e),LL(0xa4aadbb7,0xb6486b3b),LL(0x22ef3214,0xfe8701af),LL(0x5f56d985,0x4c895bc1)}}, {{LL(0x2e1e68d2,0x6fdc6cb6),LL(0x13f07350,0x0689b22b),LL(0x6d62eb1f,0xba94416b),LL(0x98996d72,0x5a2fcbba)}, {LL(0x04b2afed,0x2ca2a2e9),LL(0x0bf61008,0x5b62c764),LL(0x37f4d486,0x30074e57),LL(0x31865287,0x4e02be2a)}}, {{LL(0x6842ab16,0x401cfb89),LL(0x5b2eb304,0x440fb52d),LL(0xd22eaa61,0x3245fd38),LL(0x373f201e,0x252120e8)}, {LL(0xb2e724c9,0x4d253f5c),LL(0x27e5b5e4,0x9428d6be),LL(0x6785ee9c,0x00d4c598),LL(0x56208d4b,0x0b7fc5f9)}}, {{LL(0x92310137,0x4426665d),LL(0xfee8da95,0x75b96cd3),LL(0xb561c6d8,0xaaaac6c3),LL(0x3f09e1d9,0x0784a3c5)}, {LL(0xdcac620b,0xac78c064),LL(0x119b8d90,0x49dd5f02),LL(0x57e5caf4,0xf1f5ebf2),LL(0x0eb825e2,0xd8a9fa2d)}}, {{LL(0xbfb6a2fd,0x3553633a),LL(0xa0c9ce9a,0x06533515),LL(0x04c71728,0x6decd9e8),LL(0x980b29bd,0xcbc0df55)}, {LL(0x31826d15,0x17b1b559),LL(0x1c5cae17,0xc96ed7d7),LL(0x88cda83e,0x24f58740),LL(0x0c69f40f,0x9e2ee1bc)}}, {{LL(0x9e5604ed,0x138ebf0f),LL(0xf229f097,0x0577f4c2),LL(0x9762825f,0x0a44f975),LL(0xdd085e55,0x113b8639)}, {LL(0x73acc59e,0x4be02fee),LL(0xada7a17d,0x7829f288),LL(0x84fb30d4,0x086bd736),LL(0xe5338eca,0xb2f120ee)}}, {{LL(0xfb778d2f,0x21701393),LL(0x6441fd75,0xd46bc61e),LL(0x135b55bc,0x466671de),LL(0x51c0f145,0xee1d9cbb)}, {LL(0x6d9ce27c,0x7a7bce67),LL(0x26d82b1d,0xa8c9b1e0),LL(0x4c87bd6e,0x250bee03),LL(0xd3829702,0xd6b02f71)}}, {{LL(0x0e555d98,0xf14b3748),LL(0x6f775e78,0xf795e62a),LL(0x8f46de18,0xe9a4e4ac),LL(0xc5ab76ef,0x773bd32a)}, {LL(0x5264cae9,0x4f2dcc68),LL(0xc63a6419,0x453b627e),LL(0xe441c6d9,0xc3aeddd1),LL(0x3027b8f3,0x669500b7)}}, {{LL(0x88d601e5,0x06b93413),LL(0x76c4483c,0x0e996e87),LL(0x00eb0c21,0xe2ff3a6d),LL(0xf4690674,0x86ec3a73)}, {LL(0xe9f82ca7,0x673d123e),LL(0xbf611d0c,0x952c2765),LL(0x3676497d,0x26ed9a68),LL(0x9d29cefc,0x2c9c0049)}}, {{LL(0x2ae73af6,0x0b8c12fe),LL(0x6455c8e1,0x555b0ab3),LL(0x4804b006,0xd2f49f03),LL(0x02e829a0,0x408a22bc)}, {LL(0xf2832c53,0xde2a59cf),LL(0x96a54082,0x01332439),LL(0xbbd38f9f,0x11dc4ab6),LL(0xa24764b5,0x0248fd93)}}, {{LL(0x1374972a,0xc7774c12),LL(0x92764b41,0xc7355966),LL(0x23143092,0x31c10ea5),LL(0x9070137f,0xe89d9f88)}, {LL(0xa504d91e,0x7d074406),LL(0x70b7aa8c,0xc5210379),LL(0xea799dd8,0xa67904f8),LL(0xe7b02c04,0x81e6516b)}}, {{LL(0xb08cc6fe,0x18daf05f),LL(0xf59d49f6,0xfbbd3061),LL(0x93a78581,0x5429b117),LL(0x1906df65,0x795a4465)}, {LL(0xd51a7866,0x643c37e3),LL(0x663a17b1,0x69b8118d),LL(0x3e8a2c53,0x5e385989),LL(0x50f007d2,0xbc18c2ea)}}, {{LL(0xb616aa15,0x4adec20a),LL(0xea085548,0x99f77e49),LL(0xc01b9a33,0x9108c205),LL(0x6ef3bcef,0x298fbeb1)}, {LL(0xefd8ba0e,0xdf1a8d2e),LL(0xe9756e7b,0xf0ec9492),LL(0x7ff5fbc3,0x4fd33389),LL(0x03ac8371,0x122a6bfb)}}, {{LL(0x90d66732,0x7d053c8c),LL(0xf9b2909f,0x83f26571),LL(0x66cba4b6,0x350dd6d0),LL(0x40d0d47d,0x8c71c17a)}, {LL(0x4d0be34a,0x3bf85053),LL(0xe11bd49f,0x91ae4f59),LL(0xa22c648f,0xf8a38b41),LL(0x58abaaea,0xcb96620e)}}, {{LL(0xa7fabcf5,0xa55cee46),LL(0x79c8fbce,0xd16a8b92),LL(0xcbf048bf,0x26ad700b),LL(0x47bb5f1d,0x83b3ce11)}, {LL(0x6b310318,0x31a48f46),LL(0x00612ef3,0x13a7f781),LL(0xa18db234,0xcd840f2a),LL(0x30611c74,0x3be2a7a8)}}, {{LL(0x2b1c0447,0xbdf37cb2),LL(0xfe71722d,0x7f572382),LL(0x25535e86,0x085b3566),LL(0x3f5b9cc2,0xb5b43063)}, {LL(0xdee66228,0x7c7cff51),LL(0xb676fd6e,0xe29236ae),LL(0xab0cdb1a,0xf0c0105e),LL(0x06b52812,0x0adc9d6e)}}, {{LL(0x483baf0f,0xc9e6ca97),LL(0xf9bf5055,0x09b063bf),LL(0xfc5a407f,0x8c4c6b2a),LL(0x99a6f540,0xe29cb487)}, {LL(0xcb9a2758,0x18b72239),LL(0x8a5ed308,0xa0ae9f10),LL(0x6e402657,0x2a2cb603),LL(0xaf6f4d14,0x9c7f52cf)}}, {{LL(0x70ca9046,0x0ed032e7),LL(0x59cac9e9,0xe4b0b1d3),LL(0x18462dfd,0xd12c87b0),LL(0xbb8860dd,0xa25a23ee)}, {LL(0x507fa3d9,0x6c9a8676),LL(0x218f325f,0xc6bb96c4),LL(0x2386b7b2,0xe141bbb8),LL(0xd4183c77,0xf86a72d0)}}, {{LL(0xaece96b6,0x35537f86),LL(0x63f7e1fa,0x83aa1df9),LL(0x7ac4aaf2,0xa39ab4aa),LL(0x8a202375,0xb8d0ffa6)}, {LL(0x86514cd8,0xd916df09),LL(0x11902747,0x71f905b3),LL(0x8c744f32,0x6388c2ee),LL(0xa5431096,0x6282e1f5)}}, {{LL(0x7c388413,0x14bfa765),LL(0x7b4437aa,0x95dd04d9),LL(0x3c39d7c3,0xdf6ca849),LL(0x0c2ddf38,0x85cb1123)}, {LL(0xc401529c,0xf7766d86),LL(0x99a4d031,0xe33416a8),LL(0xb874ace4,0x5c507c3f),LL(0xdad6fcb0,0x0e3a42b6)}}, {{LL(0x47920742,0x402da460),LL(0xb45f94cc,0xb142d6ef),LL(0x76608dd4,0xc2d613e8),LL(0x5d75d4b5,0xa2c06cdd)}, {LL(0x3c564ff4,0xa1951bc5),LL(0xad1d5ecd,0xe60f126b),LL(0x702135ad,0xa634e765),LL(0x8df44695,0xa5a56a6e)}}, }, /* digit=30 base_pwr=2^210 */ { {{LL(0x9e2207b4,0x234b8c7a),LL(0xf7ee9f62,0x1f724f30),LL(0xc58e21b6,0xfa908ca2),LL(0xa74296ae,0x55587744)}, {LL(0x02911ae1,0x7dbe9130),LL(0x9d3af02e,0xc2075433),LL(0x0f3955a1,0x505b724b),LL(0xcaeced66,0x480e1a92)}}, {{LL(0x446d9f66,0xb20f6128),LL(0xc354b5a1,0xd6e06b14),LL(0x63558aac,0xa72d287d),LL(0xae68a8fd,0x4819be29)}, {LL(0x205fbdf2,0xb024c324),LL(0x210927f9,0x2fca94e7),LL(0xbe658f80,0x74798be7),LL(0xef07c046,0x618e07f1)}}, {{LL(0xb35a8c3d,0xfba715fc),LL(0xed1beba8,0xc2548193),LL(0x2ceb663c,0xb956c6dd),LL(0xaacafe85,0x13d4ddbe)}, {LL(0x30a29cc3,0x2f8275b5),LL(0xf51b39ef,0x10432e15),LL(0x2509b2d0,0xd6c9277c),LL(0x849b946c,0x4ee0d4c3)}}, {{LL(0x54b01bbc,0x547ba946),LL(0x055d4821,0x7c56c36d),LL(0x05575f20,0x8e933620),LL(0x3a621cf4,0xaec65be9)}, {LL(0x46287937,0x820b96df),LL(0x733c67e7,0x35cea883),LL(0x58cf3e05,0x30366a3a),LL(0x2da39773,0x2580d565)}}, {{LL(0xba4417ed,0x7717c42f),LL(0x654c1086,0xb2d66fc7),LL(0x57503cd8,0x07fe918e),LL(0x3cacf74f,0xf9385159)}, {LL(0x63063029,0x157d9081),LL(0x659034cf,0x79c84c08),LL(0xa8048cb9,0x02976610),LL(0x03e81417,0xef822006)}}, {{LL(0x22e489c6,0x5fb5dd4d),LL(0x81e167e9,0x9a06d9c2),LL(0x6b974c90,0x83fc248f),LL(0x7110dca6,0xb78cab72)}, {LL(0x370ff66a,0x73f8f311),LL(0x3b61d20f,0x8c5049eb),LL(0xc8516e05,0xaac47edb),LL(0x53f0201b,0x2ceba50d)}}, {{LL(0x0b93fbc7,0x6679dc5e),LL(0xa560bd27,0xf4457919),LL(0xb1acadc9,0x2561bfca),LL(0x46708164,0x338fbb6d)}, {LL(0x8b9cfd27,0x9f407621),LL(0xd3123732,0xe806c1e6),LL(0x7f24a161,0xaa1eafc4),LL(0x68e6650b,0xbee3f4a1)}}, {{LL(0x5832cd6c,0x453b6181),LL(0x985e90ba,0xc002e337),LL(0x6414f686,0x4b33afde),LL(0x8511fd45,0xf9ab29e9)}, {LL(0x6fb9a688,0x067f0972),LL(0x7202a1b3,0x7db6e14c),LL(0x73a881ab,0x0c15b6e9),LL(0xfad10660,0xc8c324e0)}}, {{LL(0x87d9f927,0xa997a6d2),LL(0xacd2f107,0x62307f24),LL(0x9c80a742,0xed7b48a5),LL(0xa7c81e7e,0xecd33ae5)}, {LL(0xefa00a94,0xcf05c763),LL(0xd9ee5aa7,0x38844b0d),LL(0x214b293f,0x02e0b05d),LL(0x8a8a510e,0x732e776b)}}, {{LL(0x6c929e53,0x784cd909),LL(0x56a33da2,0xe436e294),LL(0xce9e06d2,0x68eeb727),LL(0xfce7e2f0,0x637890b3)}, {LL(0xc3fde38c,0xc0681a1c),LL(0x76dda134,0x9cb729d9),LL(0x5c333ece,0xaa69eb97),LL(0x48eed8a6,0xe138a680)}}, {{LL(0x505dc701,0xd53cbd01),LL(0x6a64c3d1,0x413de346),LL(0x3170a5bf,0x91f6cde9),LL(0x8489b5fa,0x58ffdfd9)}, {LL(0x5c584a48,0xcc0b89d7),LL(0x167f28de,0x74f8ceed),LL(0x8c878c91,0x250fa9f7),LL(0x630adfdb,0xeb960a79)}}, {{LL(0xc9489dcb,0xe43ed412),LL(0x112d084b,0xcec053a5),LL(0x664c7cd2,0x0fd4fe42),LL(0x82a917f7,0x48ee06f4)}, {LL(0x83cd65f5,0xc5de1970),LL(0x5569c42f,0x3a176578),LL(0x4f876110,0xf24508f3),LL(0x0a415bc4,0xf350374b)}}, {{LL(0xc63aa8ad,0x9c2b11c2),LL(0x7a51c0cc,0x6ac1ae12),LL(0xe1db428f,0x75acd0d7),LL(0x19800684,0x9e391227)}, {LL(0xb1050426,0x4f89e9c6),LL(0xdaf99eee,0x099d97cc),LL(0x1ffce97f,0x27a19ad0),LL(0x3c038d77,0x05fad057)}}, {{LL(0x8597d09c,0x96d6c678),LL(0x1e1d8b57,0x38f6336c),LL(0x6330ace7,0x1f945bef),LL(0x613f9faf,0x9d627bbb)}, {LL(0x19176cb7,0xc0e7f21b),LL(0xbb9db710,0xf0e09be3),LL(0xc650133c,0x16b06011),LL(0xf3673d7c,0x8629b975)}}, {{LL(0x67115575,0x8c8230b2),LL(0x9c9f30c0,0x9bfc55b1),LL(0xce93fd71,0x132d0e07),LL(0x511c5947,0x08e4736e)}, {LL(0xfe881630,0xd54a098e),LL(0x98efa501,0x8ec67a85),LL(0x2267db00,0x72975dc7),LL(0xa338290d,0x3d6fc706)}}, {{LL(0x55ade88b,0x0c891082),LL(0x4b212e85,0x0525b501),LL(0xb61362fa,0x9ede010b),LL(0x881eecac,0x52f3d088)}, {LL(0xbc6f0ae4,0x49957b6e),LL(0x1659701d,0x25fe7263),LL(0x07b76f45,0x41e9b7f5),LL(0xbda77d42,0x5f2ad664)}}, {{LL(0xa9c418c4,0x5bdcb490),LL(0xe500a527,0xd0e2c38d),LL(0xca83fada,0x0af29f6b),LL(0x62273db6,0x1f75b1f2)}, {LL(0x9e857e57,0x8454f751),LL(0xb9e79612,0x3fb816d1),LL(0x6412b5f3,0xbe3040ae),LL(0x843ca984,0x99535136)}}, {{LL(0x3257f19d,0xb26ec8a8),LL(0xe54dd785,0xd32dc622),LL(0xf8698ab5,0x0c52e874),LL(0x79183316,0xf9a60af5)}, {LL(0xf7f4496a,0x38575d53),LL(0x3d5cd0de,0x33adfd1e),LL(0x7f502017,0x2133f4a1),LL(0x3e8676f8,0x46c09393)}}, {{LL(0x3fb4c7fe,0xca8a5a58),LL(0x328ff257,0x2ad58826),LL(0x13b8d08d,0xd9264875),LL(0xdc5a845a,0x661ae2b2)}, {LL(0x49a408d3,0xd2dcaa06),LL(0x85c21e84,0x9ef164f8),LL(0xb7819b61,0x55efaf85),LL(0xf504c32a,0x9488bb1c)}}, {{LL(0x9bb777fc,0xb571518c),LL(0x82415187,0xf369c391),LL(0x2720284b,0x2d7c5dd9),LL(0x4eec41cc,0x6feab634)}, {LL(0x24ecd0be,0x2522d5db),LL(0x00338736,0x1fca0d97),LL(0x20145279,0x74416105),LL(0x0496e925,0xf4492e1e)}}, {{LL(0xbc33b547,0xa62e09fc),LL(0xae063835,0x9434475a),LL(0xa139b769,0x51edd69f),LL(0xe5166a9d,0x17bbe224)}, {LL(0x1b4b6c84,0x6ecb0a02),LL(0x97968c70,0x16439490),LL(0xbc8aa671,0x75af0456),LL(0x3b4411ff,0xaef056ab)}}, {{LL(0x05cef121,0x686b7714),LL(0x078f4500,0x5ad6bdf3),LL(0x072e70eb,0x56df858c),LL(0x254c0917,0xa0fc5e6f)}, {LL(0xc15bf9cf,0x1a99de09),LL(0xd008aacb,0x8aeb587a),LL(0xb900d652,0xba2d8c53),LL(0xad0f69b6,0x60eb5d0c)}}, {{LL(0x10b27762,0x27098ff8),LL(0x13264ed3,0x33329ca9),LL(0x887e3f40,0xffceaf40),LL(0x930df9ef,0x854b8284)}, {LL(0x7d5627be,0xdda913a8),LL(0x35e9823b,0x8eb94d64),LL(0x2eb9e9bd,0x94c527fd),LL(0xf57b9f74,0x18335b1b)}}, {{LL(0xd193a526,0x3c44dac0),LL(0xe2b2d54f,0xd0717099),LL(0xc4c67d11,0x65624fb4),LL(0xbccedad8,0x04aa7033)}, {LL(0x31470c52,0x0c522fac),LL(0x33b05d54,0x08eb33ca),LL(0xb4565e57,0x940e0693),LL(0x7be56370,0x7e2fd553)}}, {{LL(0x12e206ff,0xf722793c),LL(0x155d3d02,0xb57e1f23),LL(0x94fc6ce3,0xd68be193),LL(0x22d4815b,0xb0f3606c)}, {LL(0xb62d5741,0xdaf995a9),LL(0x3e8f5df5,0xa7d19980),LL(0xe4631583,0x7bcdb661),LL(0x5a97dc7e,0x013193e3)}}, {{LL(0xfc73494b,0x8210be46),LL(0x57e10efc,0x508817ee),LL(0x126f2466,0x7b6b8da2),LL(0x177bee35,0x2f3b0ec6)}, {LL(0x48db1eef,0x5ceb71e0),LL(0xdc62b6bc,0xd989d9c3),LL(0xf78fac92,0x2cc38cb9),LL(0x955ba5f4,0xcd2a009f)}}, {{LL(0x453b668e,0x65a74191),LL(0xc081b447,0x40e9dc38),LL(0x8c3fdf2c,0x48eb63bf),LL(0x5763071a,0x7845cf66)}, {LL(0x787754ca,0x30d9b771),LL(0x8783a05a,0x10b3729f),LL(0x6ab570d9,0xf8090b3b),LL(0x502b3558,0xc1dfbde1)}}, {{LL(0xbe4d36ec,0xa568f5d0),LL(0x28e952fe,0x1e9e5393),LL(0xeaad6b24,0x768113f9),LL(0xa8fbede9,0x2bc798fc)}, {LL(0xaaa9010d,0x2c787f9b),LL(0x761834ca,0x32cbc77a),LL(0x032c25d8,0x449e55f7),LL(0xca6216dd,0xe824a5bf)}}, {{LL(0x17ac1130,0x3beaec52),LL(0x5e9d1aa8,0xcc28c64b),LL(0x3af8c635,0x355d68bf),LL(0xd3d1adaa,0xcd12e443)}, {LL(0x6c2030d8,0xa456daca),LL(0x62427eff,0x0dfe5bbb),LL(0xf69e2484,0xae45325d),LL(0x7245c979,0xfc2a90ab)}}, {{LL(0xa008b446,0xc34f38e9),LL(0xaac355e0,0x5e86163d),LL(0xd586a2fa,0x61432646),LL(0x3d92e0c3,0xc68c7c8e)}, {LL(0x020c1dd6,0xbfa8c268),LL(0x8bbcc223,0x25788741),LL(0xef62642c,0xbaf8c9a3),LL(0xa8c496d2,0x6d2f1ae5)}}, {{LL(0x44e57ce4,0x92d1c805),LL(0xaacd2100,0x34cdf4a3),LL(0x31e9c649,0xd5b89e4d),LL(0x232cfc85,0x558a6e26)}, {LL(0xcea31a31,0xb40f3e4a),LL(0x35c5c924,0x346c1e07),LL(0x3fcede81,0x8ffedd8e),LL(0x3b55d143,0x35269ba3)}}, {{LL(0x848bdc53,0x0366065a),LL(0x078554dd,0xba2af074),LL(0x19ff3b4d,0x3c755fba),LL(0x35a22cbb,0x5ea93372)}, {LL(0x1eb3e23b,0x0e55fe02),LL(0x765dede4,0x2626ecca),LL(0x81f445da,0x187bf094),LL(0x9df30578,0xba011017)}}, {{LL(0xd72507f2,0x81148037),LL(0x5db072d0,0x3a5841fc),LL(0xbd910aa1,0xfd631862),LL(0x23881c60,0x17b22d68)}, {LL(0xfcc13359,0x6fa799cb),LL(0x2d39fc5a,0x55c40219),LL(0x9f1f6515,0xd50bfff6),LL(0x2e30fa1a,0x575090b5)}}, {{LL(0x9ba20c27,0x70343a0b),LL(0x749306a5,0xef34db86),LL(0x4ba85f8d,0xd7ad61d2),LL(0x7e091a33,0xe4d24ad8)}, {LL(0xfc348493,0xbd6b49b9),LL(0x299c325d,0x4f11b543),LL(0x55036e93,0x4574a254),LL(0x676b75d9,0x534a623e)}}, {{LL(0x7d05afbd,0x54aa3d8a),LL(0x7f3f2c90,0x13349009),LL(0xa94b18aa,0xcd03de0f),LL(0x855c050d,0x13123c18)}, {LL(0xf598b5f8,0x747c3cda),LL(0x8644df20,0x0f7ed9b6),LL(0x08d73585,0x45e010fd),LL(0xf8cec4af,0x3b0ff430)}}, {{LL(0xb028a832,0x3745a41f),LL(0xc4106172,0xcd6d2468),LL(0x1eceac6f,0x56c5a9b0),LL(0xe1e6e980,0x769c1285)}, {LL(0xfa113196,0xbd163a36),LL(0x5840c242,0x206ffc36),LL(0x9c57ef67,0x12de1147),LL(0x03bea885,0x50260273)}}, {{LL(0x9684d63f,0x3099c21b),LL(0xc7c66691,0x06adb196),LL(0x3d63b3be,0x8464492c),LL(0x0bd38c15,0x86024ef4)}, {LL(0x10565cbf,0x226022a2),LL(0xc9899033,0x2ae6b298),LL(0x262ffa14,0x5564856b),LL(0x7e038b55,0x9472d0e1)}}, {{LL(0xb1dd268f,0x1b17ea07),LL(0x4899352e,0x8340b9d5),LL(0x75242992,0x4f159400),LL(0xe6727e9d,0xe4392a31)}, {LL(0xaef59026,0x4df1ef86),LL(0x950cfee6,0xe40671ff),LL(0xde4dd990,0x7b36d1cd),LL(0x3366ff4b,0x25df10a6)}}, {{LL(0x584ef631,0x83fb7e59),LL(0x91af7b6a,0xf12dd400),LL(0xe26f11c7,0x4a5ae41e),LL(0x96d90445,0xeb86d5dd)}, {LL(0xa355d0a3,0x028ae37e),LL(0x99260127,0x3c118ef4),LL(0x76f51bd7,0xb8c7538c),LL(0x5fbadc4d,0x66b90aae)}}, {{LL(0x17dfd0cf,0x078de9df),LL(0xfe44b17c,0x938df6da),LL(0xc40bc950,0x4a09616b),LL(0xbc969aac,0x0b507845)}, {LL(0x35f7fb82,0x23bae091),LL(0x9ad29b83,0xebc04d37),LL(0x26a3c5fa,0x9fa48a5b),LL(0xf08f3d8c,0xf67c661c)}}, {{LL(0xb2e9c3a1,0x21825747),LL(0x46c3eb43,0x3520a82e),LL(0x9646183d,0xe309ae9f),LL(0x26dac288,0xa19c31be)}, {LL(0xc76623de,0x3c37018d),LL(0x64b51087,0x59b9a0fa),LL(0xf1954f4e,0xa32f8357),LL(0x1f6da143,0x24251df4)}}, {{LL(0x01fb07d0,0x825c61cf),LL(0xf2f0243c,0x69ae93fd),LL(0x0943f7bd,0xd507c99e),LL(0x463ee64a,0x5e6dfb09)}, {LL(0x29afd00b,0x10a3c32a),LL(0xbe8cbada,0x92179b5f),LL(0x7d89f9a6,0x7bebad0a),LL(0xd13b3073,0x7ba9bbf6)}}, {{LL(0x6481cc75,0xfc23c215),LL(0xfeca7532,0x6a654801),LL(0x0fed841f,0x20785ec0),LL(0x25269b21,0xcb612be9)}, {LL(0x414a0fab,0xe9a9c09b),LL(0x6b4fa0dd,0x5404c7a7),LL(0xcb418588,0xde62dae8),LL(0xc594334e,0x2d80afd4)}}, {{LL(0x95366a44,0xfe454df1),LL(0x755cf8b2,0xda7626c3),LL(0x41397051,0x4446f0ab),LL(0x70eb8b23,0xd1788064)}, {LL(0x977b040a,0xbc7737f1),LL(0x57590edb,0xbfb39418),LL(0x343a7333,0xb094b4a8),LL(0xeb91372f,0xb15912ce)}}, {{LL(0x0b56002c,0x584e1d5e),LL(0xaa0cb90f,0x1460ce24),LL(0x8f7ffcb6,0x58f0c144),LL(0xbe0d802e,0x56e39f33)}, {LL(0x529458d0,0xb02a6edb),LL(0xa730f9d5,0xa0fbae74),LL(0x1bf69928,0xd98c0ac5),LL(0x796f12e9,0x5c9f888f)}}, {{LL(0x22e065c8,0x749207b0),LL(0x88c61143,0x6e0232a4),LL(0x837adda6,0x27f30808),LL(0xd0c215d5,0x0b748853)}, {LL(0xbf076ba7,0x97bc4008),LL(0xf157f4d2,0xadae0275),LL(0x8bcba88b,0x394e5d7a),LL(0x23ef50ad,0xf995ec14)}}, {{LL(0xaa9b60a9,0x6b207f9c),LL(0x52f9979f,0xcd7509c1),LL(0x0834e0ad,0xe3e8f6dc),LL(0xcd5b1314,0x6e2a4165)}, {LL(0xfd60d975,0x073a2db3),LL(0x2c053b7a,0x5ad92ca4),LL(0xfba97ae8,0xceb10220),LL(0xd265e913,0xab82f6a0)}}, {{LL(0xaa68a13d,0xc7a755ad),LL(0x10dd277a,0x56c13360),LL(0xdef56183,0xbbcf6411),LL(0xb863a4e1,0xebffe360)}, {LL(0x814e8aec,0x67ff26e5),LL(0xa0804732,0x90553561),LL(0xad5fe672,0x407396ac),LL(0x11ad53af,0x053a068b)}}, {{LL(0xc652cb95,0xb518dd04),LL(0x57e2b99f,0xc818563a),LL(0xb96432a7,0x217cf87d),LL(0x8cc2fdcd,0x7fdc35be)}, {LL(0x4effaebf,0x8c2ef271),LL(0xf427c7c2,0x21879369),LL(0x5197ba08,0xd80ebbea),LL(0xfc6f4c66,0x1b00db45)}}, {{LL(0x3828a5c0,0x99b9d2be),LL(0xd24a69e8,0xa8855350),LL(0x3ceaa821,0x2f919695),LL(0x04296439,0x89390c91)}, {LL(0xc5cf8a0c,0xc12b3852),LL(0x73afc431,0xdcf234ea),LL(0xf4adf01b,0xdddf5568),LL(0x1b426097,0x2d04fc76)}}, {{LL(0xcb27c5e0,0x02a21dd5),LL(0xa6b2f9b3,0x01b842c3),LL(0xd8bd7a07,0xefbd483e),LL(0xd13a781e,0x0220825e)}, {LL(0xde802c17,0x8aa029a0),LL(0x3a3f0fbf,0xb62fcd6e),LL(0xe9635f48,0x80558aff),LL(0x65dbeb2d,0xbdc6851d)}}, {{LL(0xb5412271,0x99f48286),LL(0xe242a8a3,0xa53ef798),LL(0xc0371086,0x41d18606),LL(0xfcb6d1aa,0x5df3379c)}, {LL(0x00a7a13e,0x53f2f5a1),LL(0x2bf51e2a,0x3565a6eb),LL(0x930c5a71,0xa2832b52),LL(0xee2abfcb,0x66071ec7)}}, {{LL(0x3496a532,0x75ce0a56),LL(0xbe0d69b7,0xa316dfbb),LL(0x353e94fc,0x35438d6a),LL(0x1e0ce775,0xf53433c1)}, {LL(0x22ff3a1d,0x47ea3e8f),LL(0xcd7ccdb6,0x60ebfba8),LL(0x33c475d0,0x47c6b6e2),LL(0xb7959fd5,0xd18637e7)}}, {{LL(0xa1ae3404,0x8d7a35ce),LL(0x75b832bf,0xf15c71d6),LL(0x98b9d24b,0x65047419),LL(0x0dcf73f4,0x28625a55)}, {LL(0xc7c99478,0x5aa9dce8),LL(0x0bde8d53,0x752d1625),LL(0x93e99ee4,0x7255ecfa),LL(0x22706f48,0x1c53bf71)}}, {{LL(0x4d478014,0x28335451),LL(0x3f392c0a,0xd64b05ff),LL(0x4fba1661,0x1d9ac89d),LL(0x34828cd8,0x281a0ffb)}, {LL(0x577ed419,0x07abacdd),LL(0x3cfb2c56,0xa66949f5),LL(0x847ebe65,0x38e69105),LL(0x44d6236d,0x8fbbba5a)}}, {{LL(0x725ef820,0x0c85bd64),LL(0x25a152a7,0x4ef91524),LL(0xb019cebf,0x5237ef0e),LL(0xc9a7724f,0x48203f41)}, {LL(0xc55fc0d4,0x1f61885c),LL(0xbcb3daeb,0x2c4dd07a),LL(0x4b7dafc5,0x9855d5e7),LL(0x5f3769af,0xd76e6fdf)}}, {{LL(0xbb547be6,0xb834df1a),LL(0x3e7a9586,0x43056b12),LL(0x4375fc7e,0x7459e0bb),LL(0x9c85fc6b,0x5f5f295a)}, {LL(0xbb23b709,0x3f2d2bb7),LL(0x955983ce,0x0b53bd8c),LL(0xfaf68dcc,0x5aee93df),LL(0x509f09dc,0x5575770c)}}, {{LL(0x40b1b744,0x2bf23c0c),LL(0x9a5bb913,0x524154bb),LL(0x296bdb2e,0xb0e93d76),LL(0xda0b2925,0xb3c71f5b)}, {LL(0x0c617939,0x8e77ae7a),LL(0x1aca9b0a,0x2bfea97e),LL(0x7897c5a8,0x8e3317c9),LL(0x4cee2716,0x850ddefb)}}, {{LL(0x107d9186,0x684ceee9),LL(0x0082c312,0x48708423),LL(0x6c556897,0x5300137c),LL(0x7e99bc76,0x6d464401)}, {LL(0x8808ca2b,0x6b11e1e3),LL(0xcca6433e,0xedd30eee),LL(0xaa072ff0,0xa9099f60),LL(0x5830f69d,0x774662ec)}}, {{LL(0xf94547d9,0x0770355c),LL(0x42967865,0xb5041edb),LL(0xe585a93b,0x169a6274),LL(0xd04d6a81,0x06cebf5e)}, {LL(0x2ebc1791,0x0a59450f),LL(0x765ac18a,0x69fd006e),LL(0xa54f7e7a,0x4711ec9c),LL(0x819c6af9,0xd72c8d58)}}, {{LL(0xb5418e15,0x89c97c6c),LL(0xa558a854,0xd520b03c),LL(0x0d76773a,0xe3c24aca),LL(0x67e5110e,0xc4deb5ce)}, {LL(0xcbb04ba4,0x5bb40152),LL(0xde1b628a,0x672563b6),LL(0x2e8d9e54,0xaec916aa),LL(0x3c60ac70,0xa4e8cb47)}}, {{LL(0x452d5064,0x54a03e39),LL(0x1e7bb355,0x1e405c2d),LL(0x3bbd3ab0,0x2ab2d5df),LL(0xdbc9fbd8,0x0808410e)}, {LL(0x27f23f6f,0x4180ceea),LL(0xba1d6beb,0x2b965b35),LL(0xf66d6546,0x14f1f010),LL(0xf85cfb4a,0xefdca6a8)}}, {{LL(0x6614c1c0,0x69e6188e),LL(0xe07cb7f8,0x00bd1531),LL(0x4bb7ee68,0x1b90f515),LL(0x51abb1f3,0x8afdf466)}, {LL(0xb5f34316,0xf59a7327),LL(0x64c7bf22,0x43c3c19d),LL(0xcdb00a2b,0xb275733f),LL(0x602915ba,0x0160df79)}}, {{LL(0x1baea574,0x1ae4ee9a),LL(0x03ae5168,0x0d922f28),LL(0xca691124,0x07df28fd),LL(0x8dd457c4,0x5aad2f31)}, {LL(0x137384ca,0xe0d4f443),LL(0x6620ea8c,0xd93d424a),LL(0x5067797a,0x21d544d3),LL(0x9d8a15bc,0xc8a8cc99)}}, }, /* digit=31 base_pwr=2^217 */ { {{LL(0x941d80a3,0x610f0e26),LL(0xad36514e,0x30927879),LL(0x98f22601,0xaa2dfd48),LL(0x88c8b0f6,0xbc5b31b7)}, {LL(0x6c841cc8,0xb1281f37),LL(0x5a412b84,0xdae16719),LL(0x828f210d,0x9ec1f6c8),LL(0xe8d92901,0x1935d576)}}, {{LL(0xaf3840f2,0x47247921),LL(0xdf3fcdfc,0x348325d2),LL(0xc43961bd,0xef578508),LL(0x1bd98c29,0x7d5e8ccd)}, {LL(0xf8a30164,0x59cdba10),LL(0x7cb8c653,0x0757408f),LL(0xc3056ef4,0xcd7ed73f),LL(0xfb99cd1b,0xd28e7cc1)}}, {{LL(0x6bb62286,0xa8a67494),LL(0xe7d87467,0x8d6ef816),LL(0xf673b6d5,0x3529f938),LL(0x8bbf101b,0xf5c0ee76)}, {LL(0x49fdc949,0x3768ed61),LL(0xcf405ee0,0x53b6999e),LL(0x1718e51a,0xbf0108a0),LL(0x5181ebd7,0x38e609ec)}}, {{LL(0xd8595159,0x82051640),LL(0x579a3876,0x30e1c706),LL(0x0298a67c,0x091154c6),LL(0x51132d27,0x76d9a9c9)}, {LL(0x5c661a4d,0xe41de8b7),LL(0x2a6dcbaf,0xf24b5e96),LL(0xd714e045,0x1ed4cb0c),LL(0x0c187c70,0x605926a4)}}, {{LL(0xf34b1c93,0x97672559),LL(0xe0b43506,0xa256be98),LL(0xe1a98eb3,0x7fcdd412),LL(0x295a061b,0x7fcfcd84)}, {LL(0xcc2386cf,0xddbac22b),LL(0x928c2556,0x7741adb7),LL(0x4e6e1288,0x3a2bb869),LL(0x025bb4a1,0x53ed11da)}}, {{LL(0x4108c8e2,0xb114bd67),LL(0x3deb8e23,0x85948c6b),LL(0xd0e9434c,0x6a9e05d9),LL(0xb9c4fd70,0x395060b7)}, {LL(0x18893751,0xa0ccfd16),LL(0xbbf65477,0xa941ff60),LL(0x59423e35,0x34ada238),LL(0x7e570058,0x4ba7a7d1)}}, {{LL(0x869ae596,0x3d05d455),LL(0x93368325,0x92a15400),LL(0x62eb7ffa,0xbd64ae0a),LL(0xd34b2c59,0x3f263a7a)}, {LL(0xa22244e1,0xe95eece3),LL(0x706fc500,0x39ccef58),LL(0x22f1d2e6,0x39a88f93),LL(0x6d47c670,0x1ec796b3)}}, {{LL(0xaa1ff4af,0x1558e0f2),LL(0x390503a4,0x61f43487),LL(0x3c4f76f1,0x66164732),LL(0x9e13432e,0x50d0706e)}, {LL(0xf5eba0fb,0x5f1a87ca),LL(0x80bda2c5,0x28a95c0f),LL(0x12ae6462,0x10d693e0),LL(0xf45e6ba6,0x79871340)}}, {{LL(0x887051c0,0x8abf0cad),LL(0xb3c6b540,0xd09f571d),LL(0xe30ab25d,0x3fb2e16b),LL(0x539e8bc4,0x12e057a7)}, {LL(0x733c2597,0x6efe71ce),LL(0xe71058ac,0x72fa0df5),LL(0xccc037bf,0x49f14d06),LL(0xceb3eb6c,0x9a3ceb03)}}, {{LL(0x4195370a,0x9895e908),LL(0x927345e7,0xa75007e5),LL(0xd3850711,0x00b4c212),LL(0xdfee8b34,0x76e4060d)}, {LL(0x184c1d07,0x15801862),LL(0x302f5711,0x234e39c0),LL(0x6aa74204,0x4c0bd387),LL(0x6f496836,0x0515eddc)}}, {{LL(0xc849afbe,0xa9fd0cb5),LL(0xcad5c0aa,0x041df5ba),LL(0xddff259e,0x9a54af37),LL(0x9b550a8e,0xa3f156bf)}, {LL(0x7e3298d4,0x4df2d33d),LL(0x65ff0e1a,0x0957a0a0),LL(0x1e2b3a45,0xff7fb43d),LL(0x1a73285a,0xb86d386a)}}, {{LL(0x28b18e93,0x6e283c47),LL(0x4b4132ed,0x5458b92f),LL(0xba674332,0x7026345e),LL(0x5c9fc32d,0xc8e38151)}, {LL(0x58e7b4fe,0xd6aaf8e1),LL(0x4267253a,0x3e77a5c9),LL(0xa0949607,0x6441cba2),LL(0xdee20b2e,0xfa205185)}}, {{LL(0xf5b44600,0x64f3d576),LL(0xef5c8446,0xf12125db),LL(0x487a0116,0x1467539b),LL(0xf380229a,0x3aa0fa49)}, {LL(0xd79f36dc,0xcc6586f1),LL(0x1b9a0b42,0xebcf653d),LL(0x9c1df729,0x68af006d),LL(0xa7903ee6,0x507e055a)}}, {{LL(0xafd8ac9b,0xd1b48ef8),LL(0x3b5f6b51,0xd8920af7),LL(0x983339c8,0x9629e789),LL(0xfa9248d3,0xbfd2d787)}, {LL(0x9a078882,0xb50ca302),LL(0xf5cb0529,0x1c34f848),LL(0x1646a9f8,0xb9b01519),LL(0x80d53f9d,0xc9e3679e)}}, {{LL(0x1af3e5f2,0x5a63e822),LL(0xff58e3d1,0x05480ad8),LL(0xd6b3626b,0x2d241643),LL(0xc1eda15f,0x33b15660)}, {LL(0x8528e5d6,0x3e74f855),LL(0xf63188f4,0xafb6dc9a),LL(0xaeeb1d32,0x0cac44cb),LL(0xa627eff8,0x50661046)}}, {{LL(0x64b49667,0xadc4b012),LL(0x1e05f760,0xa4bdafa7),LL(0xf185d27a,0x171b28b3),LL(0x33425747,0x987e5163)}, {LL(0xc3864a65,0x7c42ac4e),LL(0xbf449c12,0x2dae1bb8),LL(0x06965832,0x680d9743),LL(0x7e31d9f4,0x6ac1ef01)}}, {{LL(0x579d6ae4,0xdef57433),LL(0xd5240bf9,0xe055b087),LL(0x90a5e069,0xe4dbbe60),LL(0xddb3dc15,0x2161d5fe)}, {LL(0xda297b71,0x7d303012),LL(0xd468046c,0x04481034),LL(0x0ac93c6c,0xaa94d5bb),LL(0xd8d8f53a,0x95bacd45)}}, {{LL(0x3e03e895,0x790a5d6f),LL(0x44fa5a81,0x27efd502),LL(0xe5998b32,0xd9d35230),LL(0xf22ade19,0xb36a0c07)}, {LL(0xf979a2fe,0x46ec8691),LL(0xced8cb94,0xa67ba933),LL(0x2f856ab3,0x00d07245),LL(0x3c925dae,0xadc9ff42)}}, {{LL(0x563038a5,0x0e4eaa25),LL(0x8a8f6483,0xfef7e89c),LL(0xace61af8,0x50433633),LL(0x2e1a3515,0x8a1589e0)}, {LL(0x5fdcb1ac,0x99f21e29),LL(0xc9a466da,0x8fd2d411),LL(0xf56b7f13,0x55323c6f),LL(0x5cff438c,0xa016d64a)}}, {{LL(0xdc05b5cc,0x3e3dfcbc),LL(0xfc3c70ec,0xc1956ca8),LL(0xe63f02df,0x7dbbd169),LL(0x240b87c8,0x95206689)}, {LL(0x1aa6d48a,0x7bacda5e),LL(0x39280f78,0x51dcf19f),LL(0x660abac2,0x1511ae04),LL(0xd905af53,0x3a95adc9)}}, {{LL(0xea464737,0x0c8c4330),LL(0x34fc4b51,0x989c09c4),LL(0xe2cf3376,0x1852120d),LL(0x25c04de3,0x5a1cb8a8)}, {LL(0x75fe7596,0x50486f98),LL(0x223030b1,0x8cd78d2e),LL(0xcfa1ab11,0x524cb8f8),LL(0x5a15b0b9,0xa716ea3f)}}, {{LL(0xb902d114,0x7618e95e),LL(0x084ebf5d,0x0a1a4146),LL(0xe3f87683,0xdfb909e9),LL(0x4107410c,0xa0b7eee1)}, {LL(0xf02b0e12,0xa45a551c),LL(0x9efccb9f,0xceabbfd2),LL(0x740f4e3a,0xb0d1b6bc),LL(0x4cbfd0de,0xfc737250)}}, {{LL(0x32452b0e,0x3fad2d9e),LL(0xf523527d,0xb4e659fe),LL(0x6c0ff353,0xf0dcd701),LL(0xd67b6f98,0x28f06e2a)}, {LL(0x82a789b4,0x2d0c36ce),LL(0x49c0d54e,0x20e577da),LL(0xae38dd0e,0x8d1d5c7f),LL(0x894d9143,0x72e01399)}}, {{LL(0x3958e055,0xf7806856),LL(0x5df44aee,0xac35ee40),LL(0x97c18b8d,0x2b478913),LL(0xfa2586cd,0x5396824e)}, {LL(0x1b23f8c4,0x22b37b25),LL(0xcdecdefa,0xf9ced36e),LL(0xc2fc39c0,0x28c3bee5),LL(0x6d9db32b,0xa1731fae)}}, {{LL(0xbc3e2c91,0xa0445fa7),LL(0x75a4aa72,0xa1ab6955),LL(0xbbe0a1c7,0xf0cd61c6),LL(0x0123bc52,0x923c3b69)}, {LL(0xafd7c4bc,0x818ad28c),LL(0x28b15b05,0x7c229224),LL(0x1f78a4f4,0xecde7efb),LL(0x03ef3ab3,0x550d68e7)}}, {{LL(0xfc5f8c35,0x0371021d),LL(0x0ed2b06e,0x4440aa1e),LL(0x9ba7247d,0x70c8ede9),LL(0x84f23fde,0x0d2b6ed3)}, {LL(0x5ff4478c,0xd0119d95),LL(0xf79c69d5,0x66152d27),LL(0x02afd13b,0x56d8bea4),LL(0x15bb938a,0x035efe5f)}}, {{LL(0x2ccaa425,0xc5ca7d08),LL(0xeeee9376,0xc8c69ea6),LL(0x493a2051,0xb22cfe59),LL(0xdc7b90fb,0xcb50e618)}, {LL(0xe05a8705,0x0f6fdf2b),LL(0x4814df31,0x081f3fe7),LL(0xeb1e3e76,0x6fefe18a),LL(0x03e06a50,0x81910050)}}, {{LL(0xdb45bfea,0x8a801df1),LL(0x7a828cf6,0x8c7fe1fd),LL(0x8d173cfd,0x1c1868b5),LL(0x0dbde1c8,0xe18f0a36)}, {LL(0x9ac345b6,0x3b29ed64),LL(0x9dcd07a5,0xd56d5956),LL(0xc6813a88,0xf4191570),LL(0xeda3af42,0x39033ebc)}}, {{LL(0xad5d215d,0xdee5591b),LL(0xafbe5a28,0x9cfa11c6),LL(0x1823c28f,0x73d0f1e2),LL(0xafab1f67,0x75d49925)}, {LL(0x7c521448,0x61c81e2c),LL(0x4a96edb5,0xc547be6f),LL(0x4ca368b3,0xccb9fc59),LL(0x04fc3303,0x175ebe48)}}, {{LL(0xfce42989,0x507620cf),LL(0x9abfadb2,0xf236e043),LL(0xab36ab58,0x381c50c3),LL(0xae22c6a3,0xed4cb73e)}, {LL(0x2158dc4c,0xa68a2827),LL(0xe9fa53ff,0x1715ac43),LL(0xfa266797,0xb02fdf73),LL(0x7eefb203,0x3079f3c7)}}, {{LL(0x7f7545bd,0x0a41fb94),LL(0xcb923ace,0x6b9dd022),LL(0x3bea2541,0x582c7ff5),LL(0x5ecdbe2d,0x992f2379)}, {LL(0xfe17bdca,0x821f1670),LL(0x2626bdde,0x521c06f2),LL(0x1864ca0b,0x6292748c),LL(0x1bc74d8b,0x554d4ece)}}, {{LL(0xea3d4446,0x745d4f74),LL(0x40ad1c7f,0xa439f178),LL(0x51374e92,0xc95d9510),LL(0x90229008,0x75870e9f)}, {LL(0xc54e7e81,0x3fec98c2),LL(0x94b3860b,0xef537ee9),LL(0x40bfc8f6,0x139dd834),LL(0x0f114403,0x20b51364)}}, {{LL(0x30b4b4db,0x4752a49f),LL(0x8c3c90e0,0xdfbb8b17),LL(0x70f0b16a,0x60c8915b),LL(0x40528319,0x5e395000)}, {LL(0xa641f2e3,0x8a1624c7),LL(0xbb4ca0dc,0x3c9925c6),LL(0x2c3152b5,0x2aae6edb),LL(0x08b896ff,0x8dbac580)}}, {{LL(0xe5a36bc8,0xe0516205),LL(0x3295707b,0xd7714332),LL(0x51c3513f,0x61db6804),LL(0xab552df8,0xf2ee6e20)}, {LL(0x353c17f0,0x5ddcfa99),LL(0x046d5fd4,0x65687a2f),LL(0xfd1ccad4,0xef567e9f),LL(0xa0238b70,0x7cd5f7dd)}}, {{LL(0x92c01197,0x96fba79e),LL(0x83b50e70,0x46a9f2de),LL(0xfe287169,0x7efcbbb2),LL(0x4528d67d,0xe30d60cb)}, {LL(0x6cb04d3a,0x88fed0cc),LL(0x0221ceb8,0x63eb9d0d),LL(0x748b5813,0xc6954e9f),LL(0x5c96e897,0xceef2bd8)}}, {{LL(0x85648f04,0x99503ae2),LL(0x923e87d7,0xeee51f99),LL(0xb6560ceb,0x90908fca),LL(0x80e0f6b3,0xafad5926)}, {LL(0xaea32cf9,0xa50f31f3),LL(0xa74ae92d,0x7ea17064),LL(0xcda71d1a,0x0675ccc1),LL(0x1e0a464a,0xd1e3b630)}}, {{LL(0x2442872d,0xa361f2b7),LL(0x46e52c97,0xb21bcd39),LL(0x85574630,0x1405f89c),LL(0x8e0a96ab,0x0da7bfbd)}, {LL(0x4220f57b,0x48af06c2),LL(0x6a333e4f,0x772a9b12),LL(0x6f712eb8,0x3afc661e),LL(0x2eba8817,0x29deff6c)}}, {{LL(0xd8c69e5a,0xbab680de),LL(0xe93daf10,0xf8615abb),LL(0xcef6fae6,0x7455ea1d),LL(0x868455fd,0xac0a30ea)}, {LL(0xe47d628a,0xae967b17),LL(0x65f1f482,0xa6d703e2),LL(0x0bfcc371,0x2723a965),LL(0x6db4a042,0x9b06cc14)}}, {{LL(0xa77c8b21,0xa973d738),LL(0xc008f2ed,0x9a981f80),LL(0xaf27cdb3,0xecc7bbcb),LL(0xb5cb693a,0x514db964)}, {LL(0xe75c93d1,0x24125414),LL(0x1f00d53c,0xd9308c0e),LL(0x831eba6d,0xdb56d155),LL(0x672b86f1,0x29eefc2c)}}, {{LL(0xdd13b3c9,0x332f6ab6),LL(0xe371f873,0x70e052f6),LL(0x125712ab,0x05740742),LL(0xb3512100,0x4239152d)}, {LL(0x80b22915,0x98355eaa),LL(0xb896f6fa,0xd0e263ec),LL(0x442b4c8f,0x9378a8a6),LL(0xf65795bb,0x40c2b546)}}, {{LL(0xd572ead8,0x0cfa46ed),LL(0x78361300,0xb9b4abdb),LL(0x8c102020,0x5fe63ef1),LL(0x785a4b54,0x1805c84e)}, {LL(0x805cb642,0x147cf487),LL(0x487e581f,0x87cf50aa),LL(0x9eaebcd0,0xe942fa5b),LL(0xd1af71f2,0x06d4fa96)}}, {{LL(0xc4fc3823,0x20c1a770),LL(0x85140885,0xcdffd09e),LL(0x6b3592e9,0x27ce78ab),LL(0x8ba82008,0xb8e8c15e)}, {LL(0xfef74187,0x5fe8f3f0),LL(0x77ce808d,0x8e85a3a5),LL(0xc7395f64,0x8447dc69),LL(0x1181b854,0xae90769f)}}, {{LL(0x456114c8,0x54adc101),LL(0x9ca6a9c1,0xe7962b76),LL(0x909410a4,0x3f0e77fb),LL(0x9e2e44f9,0xe18151cd)}, {LL(0x2cf6e29e,0x5e510a0a),LL(0xb1836b07,0x136896ab),LL(0x0fe11010,0x3ad4fdec),LL(0xdbddf038,0x35b36790)}}, {{LL(0x75903df9,0x7c4f5a68),LL(0x2f5b7193,0x3e9cb056),LL(0x591a4524,0x745e9452),LL(0x1a056e15,0xc406ad44)}, {LL(0xa69e11ef,0x2e93edf2),LL(0x73a1cb88,0xa28b82fd),LL(0x1225c3d5,0xdc1c9cda),LL(0xa5569794,0x86e9a994)}}, {{LL(0x5b092dde,0xd698506e),LL(0xd1ca8b06,0x076a4c82),LL(0x2ef2bc6f,0x4516033b),LL(0xd78fa65f,0x0574c792)}, {LL(0x735bb362,0xa3b1c3d8),LL(0x0da54317,0x22fca7a4),LL(0x60aaebb6,0x3e7ae709),LL(0x937638c1,0x42417d54)}}, {{LL(0x1dfe8b0e,0x32f00a5d),LL(0x8dcdbdbc,0x8ea5e8e1),LL(0x6b30ea52,0x38df57cb),LL(0xe94c30ca,0xd325aa1c)}, {LL(0xdce4d256,0x7aa04a9d),LL(0x74c7db6b,0x78e98cd3),LL(0x443d5c9f,0x631475a8),LL(0x7adfbceb,0x34e5c73a)}}, {{LL(0x9f1e8828,0x7fb69bab),LL(0xc84149e3,0xcadc78be),LL(0x1fe86af8,0xe9424ecc),LL(0xbc504ea8,0x13160cc8)}, {LL(0x4c96a680,0xcb380078),LL(0x845faae5,0x006fb9d8),LL(0x1e0e66d1,0xc6a64277),LL(0x428f526d,0x13f77d6e)}}, {{LL(0x28474530,0x9f80fe8c),LL(0xdb7fec00,0x5649a173),LL(0xd9cb05ca,0xdeed5bf4),LL(0xd7077c41,0x14b1a3a9)}, {LL(0x096883ec,0x4c2ed239),LL(0x44ae671d,0xd550edfe),LL(0xf7b7362a,0xb233e5dc),LL(0x4fd464f2,0x32c15820)}}, {{LL(0x68880bf9,0x0ecb18f7),LL(0xaf230a34,0x53468bed),LL(0x370cd6ef,0xe3ba97b9),LL(0x3516d77e,0xf5cdabf4)}, {LL(0x11462032,0x08d78a56),LL(0xd583ccc5,0x1393fa93),LL(0x0c1b3514,0x52af7f5d),LL(0x188ca043,0xf48cac66)}}, {{LL(0x5461a1d1,0x2524c8dd),LL(0x91b6e707,0x6eee8101),LL(0xca2fe87e,0x209fece6),LL(0x9ac56706,0x50b35727)}, {LL(0xec373bb2,0x651a6701),LL(0x1a4c2e84,0x881de85b),LL(0xcfdb47d5,0x4892861d),LL(0x5cdc4424,0x5ae2e653)}}, {{LL(0xa1f90dd9,0xc58f4f59),LL(0xfcf158a4,0xa5584f85),LL(0xab072a7a,0xbde86fb0),LL(0x268bae62,0x7c69e25a)}, {LL(0x44fc7b3e,0xee3478f3),LL(0x6b7d3647,0xec148394),LL(0xe1c8c0ca,0x2a542ebf),LL(0x161dc0c1,0x63d1d635)}}, {{LL(0x57ab9282,0x769acdbe),LL(0x2a119cb9,0x9c338971),LL(0x125e5b4c,0x049e366f),LL(0xf0c8fde4,0x3aec68e0)}, {LL(0x324cefda,0x9d95b6e5),LL(0x704014b5,0x844cce33),LL(0x6a6bb216,0x03920a61),LL(0xf379db8e,0xd69d17e3)}}, {{LL(0xc5e386e5,0x1924ac16),LL(0xd64953c3,0x62373a48),LL(0x47f4e4a4,0x5b1f7d64),LL(0xffa115fd,0xc043b5b5)}, {LL(0x87fb16b0,0xb2a2656e),LL(0xd8cd79a6,0xcac56b9b),LL(0xcc19d3af,0x544971f6),LL(0x0fd63db9,0xf539244b)}}, {{LL(0xfbf4d232,0x0f052d3c),LL(0x7a2a7280,0x6b3c8366),LL(0x48079b9f,0xaa6579db),LL(0xa4d9edcf,0xc5beb93d)}, {LL(0x0f1599a3,0x8ad58825),LL(0x5f3f640b,0x3f3a2634),LL(0x9032fd7c,0xda15393a),LL(0xac0e7136,0x97c10230)}}, {{LL(0x599785ee,0xfa32ef9f),LL(0x6b4c7a65,0xe1ed3b28),LL(0x2da1dcdd,0xcee1af27),LL(0x6861e2c2,0x4e480c11)}, {LL(0x9c8ad8c3,0x35b5ec42),LL(0x3fc55f23,0xfd07f6a4),LL(0xea76d444,0xab18ead2),LL(0x22ba099a,0xcb8bde14)}}, {{LL(0xc61ae967,0x252e6a81),LL(0x72a2e1e6,0xaf11042c),LL(0x1a211ef8,0xb353902a),LL(0xc99a25fc,0x644d16e0)}, {LL(0x5b67e48a,0x637fd606),LL(0x51a0b665,0xfa570963),LL(0x7ee072b8,0xaa661c73),LL(0xf2e0a727,0xde1eb4fe)}}, {{LL(0x22ed7ee6,0x56096a0c),LL(0x5825908b,0x31aaf403),LL(0xbfa02db6,0xfd5f6ba7),LL(0xff798900,0x85f4f9a9)}, {LL(0x4a0cd878,0xa0997d56),LL(0xb1b6982e,0xdd76909c),LL(0xeccf338e,0x874fab15),LL(0x4ce82bb1,0x5e072b3c)}}, {{LL(0x6dd0d997,0x5dbe883f),LL(0x41765fb6,0xa32117f2),LL(0x7d87fc5e,0x59ca4da3),LL(0xb95ec918,0xc91002cd)}, {LL(0x6548248f,0xd53bc123),LL(0x6c6d1e0e,0xef10a373),LL(0x99d9893f,0xafb2d760),LL(0xce0ba0ca,0xb77c1f1b)}}, {{LL(0xcfb9f6b2,0xabce362c),LL(0x35f9be91,0xe6e108d2),LL(0x7187fa9d,0xb2331290),LL(0xfc7ddce6,0xdcd1f4fd)}, {LL(0x9086eb29,0x3a129991),LL(0x53a56d57,0xb0730520),LL(0xabd421bd,0x9fcdf4cf),LL(0x08f3e8e0,0x96271270)}}, {{LL(0x401e0217,0x951ea7e2),LL(0x733f637b,0xa4d1d708),LL(0x4f4cd676,0xc75170f4),LL(0x832f0b4d,0x568279ba)}, {LL(0x25c17ab7,0xda4c01f7),LL(0xfa30e1b9,0xfcc13028),LL(0xacba57ec,0x4d1d8f71),LL(0xef6b3913,0x0c7971cf)}}, {{LL(0xc014f166,0xdf16e73d),LL(0xf96f2c30,0xd5796183),LL(0x3f70dd7c,0xd13ee9f7),LL(0xdac738c5,0x3f9aa0dd)}, {LL(0xad021e28,0xa200c7e4),LL(0x08414fd0,0x982abae3),LL(0xc3779882,0x76d16a8c),LL(0xe70a6ff5,0x41563d33)}}, {{LL(0x4b553a17,0xdbb9656e),LL(0xd9c87aa1,0x96af21a0),LL(0x7bd9a625,0x2de13a03),LL(0xfeb1fec2,0x29f8c49b)}, {LL(0x1a4ce44a,0x84e2df47),LL(0x548b39ee,0x83bb2965),LL(0x94d996eb,0x38b91cce),LL(0x9441ae0b,0x41e0a3cd)}}, {{LL(0xdaa92f34,0x720d30d8),LL(0x06f30fbb,0xba587579),LL(0x4c96ad59,0x24f74676),LL(0x0d33bd5f,0xf40493f7)}, {LL(0x126a7267,0x9068c3e9),LL(0x18927490,0xa51099df),LL(0xa9cfe02f,0x27452423),LL(0xb8749653,0xcfd035be)}}, {{LL(0xfda6a4a9,0x0dd9bc2a),LL(0x0106ae0e,0xdba0178a),LL(0x4969a4bb,0x3820c9f5),LL(0x99fbc715,0x5031e9fd)}, {LL(0xc193d942,0x642a030a),LL(0x454cbb39,0xdc3d6ab7),LL(0x1c8fa77c,0x507c17b9),LL(0xe3642a95,0x8465bcc8)}}, }, /* digit=32 base_pwr=2^224 */ { {{LL(0xc25dfad3,0xe74e265b),LL(0x493f44b6,0xd03630b9),LL(0xbfd6d473,0xb3270892),LL(0x1c5ee992,0x5b2d9543)}, {LL(0xa36f7c5f,0xeeb94537),LL(0x8ab0b81d,0x9befc01d),LL(0x188b45e5,0x483cdb08),LL(0x01e4648b,0x44c753b7)}}, {{LL(0xb2411618,0xee43bc87),LL(0xf07924c4,0x08754bd2),LL(0x4ac92557,0xef205033),LL(0xee0387f4,0x6e7e4fe6)}, {LL(0x76961d0e,0x51f3e2e2),LL(0x37eac10f,0x2b69d417),LL(0x73757a88,0x36d0f45f),LL(0x2b0c7d35,0x38b967e5)}}, {{LL(0xb31fa779,0x94ba8fc4),LL(0x0f13036e,0x8024dc85),LL(0x82d754b7,0xfda2af63),LL(0xae9ea9ae,0x4a784242)}, {LL(0xf9887947,0x67dd14ab),LL(0xcd555a0a,0x7f2ecfc4),LL(0xf63a46aa,0xb37c4244),LL(0xff71b4b5,0xd032cfc1)}}, {{LL(0x6b8a6a97,0x0aef84c1),LL(0x0b2bca36,0xd2e7f3de),LL(0x5b174d43,0x721c6c09),LL(0xd52ccc5b,0x5719cf31)}, {LL(0x3adf9517,0x6c7361f0),LL(0xabe20ff5,0x1e264169),LL(0x69eacc0e,0x01f9d997),LL(0xc2e635d2,0x721eba63)}}, {{LL(0x25df8bb5,0x4225e9c8),LL(0xb5752d7e,0x931f721e),LL(0x0a3b281d,0x3c4ed475),LL(0x4a4668be,0xcf927682)}, {LL(0x75b7e90c,0x1b7f358e),LL(0xb7a29b9a,0x06e5c24d),LL(0xa167f2c8,0x0058967a),LL(0xa4ee62d3,0x9f1a6fb9)}}, {{LL(0x278291f1,0xca899c4f),LL(0xf4e64c1d,0x69a90324),LL(0x8d62916e,0x46cc5d42),LL(0xec1007cc,0x3c802e65)}, {LL(0x6219cfbb,0xdadcf2aa),LL(0xd10258b2,0x942870dc),LL(0xa5e142af,0x77264e68),LL(0x089cc7a3,0xf25675e2)}}, {{LL(0x7336aa16,0x177e8a3b),LL(0xbc5c622c,0x5a92cc2d),LL(0x1789e029,0x33a35a2c),LL(0x4e4d5573,0x6f91306e)}, {LL(0xda0a46f5,0xe5a2a581),LL(0x42640bba,0xfb532bed),LL(0x4a7b3ae4,0x88ff0f11),LL(0xb8ff7a71,0x2223e7b6)}}, {{LL(0x5d21d261,0x75933133),LL(0xcabb1fbd,0xa336289a),LL(0x631b3b61,0x797db2f3),LL(0xd7e6a511,0xc2cedb25)}, {LL(0x10355332,0xb8806f34),LL(0x5d0ae37f,0xe5f1fb4a),LL(0x5d17c5c7,0x57cf26a5),LL(0x68c43ec3,0x82e8df47)}}, {{LL(0xf86bd784,0x70fa23eb),LL(0x51b0ce75,0x711a9dbb),LL(0x82170008,0x83bb4a90),LL(0x630602dc,0x8f096ee9)}, {LL(0x7f15e77a,0x7d275fc9),LL(0xfe727ec7,0x63516a6a),LL(0x1dce9d38,0x6b06827a),LL(0x023b31c2,0xa01a5382)}}, {{LL(0x886209b8,0x12537433),LL(0xc5a11b32,0xb7875fa8),LL(0xbd61176d,0xfa63cb99),LL(0x33378ebb,0xebb204ea)}, {LL(0x70c135f6,0xf29a29a0),LL(0xfa29d69f,0xf53941e9),LL(0x9917da42,0xab97b39a),LL(0x45947ae4,0x4677cfea)}}, {{LL(0x0f6dd908,0xd4668cff),LL(0x987e0769,0x48bb09ed),LL(0x8d64b6fd,0x794ed298),LL(0xfac845da,0xaf89d530)}, {LL(0x2d06e70d,0x57445649),LL(0x079e70a7,0xe2a1a8c2),LL(0xf524fc03,0xd2ef1779),LL(0xb137bb1b,0xeaccaacc)}}, {{LL(0x5d279f42,0x34d8ed87),LL(0x1cd68904,0x4dd5344c),LL(0x24abd550,0xb558b71d),LL(0x40df135e,0x3728e850)}, {LL(0xcfe86519,0x9329e2b2),LL(0xac74cde2,0x48ad17fb),LL(0x30b388b5,0x2ad61b22),LL(0xfaea71e1,0xebcbc1ad)}}, {{LL(0x35990d9d,0x50d7b19e),LL(0x6eb70243,0xb17138e5),LL(0xaa8ae7e6,0xb61618f6),LL(0xabce12c6,0xedee15b0)}, {LL(0xcc7205fc,0xa99ce250),LL(0x69e0d75c,0xe438efc9),LL(0x5084b390,0x1feb6a10),LL(0x9c80d42d,0x7b348954)}}, {{LL(0xe4b68140,0x67ac89d5),LL(0xc9b092af,0x34afd23b),LL(0xfe1ad661,0xad65cae9),LL(0xe02d884c,0x4f402947)}, {LL(0x6b1c40c1,0xd0a48fcc),LL(0x8961487b,0xf950c9f7),LL(0x206d1752,0xdb1cd811),LL(0xe99fd891,0x863b0ded)}}, {{LL(0xbb2a4515,0xd3aad8c2),LL(0x797e223c,0xc93c8cb8),LL(0x12a77d46,0x0f471e49),LL(0x600872b6,0xa2ac9434)}, {LL(0x915f730b,0x6fb1c7ef),LL(0xd254d363,0x9fb72401),LL(0x6b44796a,0xf521e33a),LL(0x97c9fafb,0xb7ed2e8d)}}, {{LL(0xffb5e7ce,0x60d41128),LL(0xaecb96c2,0xdbd8b542),LL(0x0b5ca788,0x029ab3dd),LL(0x190eb38c,0x8b1148a2)}, {LL(0x69fb1924,0x59048db8),LL(0xb18391a8,0xcd2149f0),LL(0xfed311b9,0x6bece5b6),LL(0x9ffd29b9,0x5edbe9b9)}}, {{LL(0x1156ded2,0x53810556),LL(0x721f3e68,0xf812ce5d),LL(0x7ccdc8cb,0x50504d40),LL(0xc60fa4fc,0xb559ba08)}, {LL(0x1d6bd879,0x862a83d9),LL(0x836e26ba,0x2f8f653b),LL(0xeb26ca11,0x8587e6df),LL(0x8c8aaf7b,0x127bd905)}}, {{LL(0xd67d9902,0xe26e690d),LL(0xb58e7e78,0x1a6061f4),LL(0x480dd4d1,0x960ef741),LL(0x75589610,0x7fd09736)}, {LL(0x855a8b2b,0x5a20a1a2),LL(0x355b4e0f,0x3ed68662),LL(0xe76595b4,0xd3786f45),LL(0x0bdedcfb,0x72a6999d)}}, {{LL(0x6a175646,0x4e48e843),LL(0xe05dc02d,0xde53c427),LL(0x97d31bc6,0x9728a4c5),LL(0x5bb3bd37,0x01a07129)}, {LL(0xa74a0fcc,0x83c08a98),LL(0xbc345df8,0x233e400f),LL(0xcc3e0edb,0x9578c5f2),LL(0xf144a31f,0x0fe89df2)}}, {{LL(0x14c5a2cc,0x308098a0),LL(0xba40c0bc,0xeda5a59d),LL(0xb718a5ae,0x0b10f7e0),LL(0x5b8ad9ba,0xdaf7da8c)}, {LL(0x87394cde,0xddc71285),LL(0xe43458d3,0x9bdb27cd),LL(0x4bd7c11c,0xc698d972),LL(0x3540be14,0x2ee97fbc)}}, {{LL(0x72f98422,0x2c704995),LL(0xef8661c5,0xfc71fee2),LL(0xce08043e,0x6574e022),LL(0x5143733c,0x3d17162e)}, {LL(0x730e5b80,0x3bf0b448),LL(0x7cf94b5e,0x56de346a),LL(0x6c797797,0xfa87a53e),LL(0x6487d014,0xe8b9edfa)}}, {{LL(0x7be60b03,0x09e74387),LL(0xec8750db,0x2277ebc3),LL(0x7aeaa545,0xf1e9d594),LL(0x44c03394,0x41564562)}, {LL(0x4de9f7ec,0x57943adc),LL(0x2a220cd5,0x09dd58f9),LL(0x06973808,0xdf848ec8),LL(0xd3950024,0xf1d5def1)}}, {{LL(0x5a8707e5,0xd089eba5),LL(0xb0b90ebe,0x914046cb),LL(0x63fe6bc2,0xb01180b2),LL(0x7ede9d83,0x1ffbc968)}, {LL(0x3c52c09f,0xe16d336f),LL(0xdf40338d,0x32270ecb),LL(0x7eec7039,0xb55ff5c6),LL(0x38a63fab,0xb5ffb314)}}, {{LL(0xee18ffec,0x3e9f284f),LL(0x1d1b4e80,0x702d97f5),LL(0x214c4da1,0x2005ee57),LL(0x2f5ea2f4,0x1c210413)}, {LL(0xa4149949,0xd24a486c),LL(0x23c8e201,0x3869a339),LL(0x0149992e,0x00f6e410),LL(0xf0a367dd,0x54e97b46)}}, {{LL(0xe169de5c,0xd967726c),LL(0x6a0fcd03,0xa3e81f93),LL(0xdb1b1733,0x171faa9d),LL(0x3828e41b,0x0bbb5e91)}, {LL(0xf0828387,0x789a7b2e),LL(0xfca60b9b,0x9465cc16),LL(0xab630d23,0xcb58e90a),LL(0xa339d4b4,0xe7d30293)}}, {{LL(0x18e75428,0x0bcac958),LL(0x9a95900a,0xd2f1554a),LL(0x03846833,0xc63c2afb),LL(0x6d1e8753,0x703d0220)}, {LL(0x04a357a2,0x47f5fe57),LL(0xcdc17255,0xaafba53e),LL(0x821af8d5,0x8f94c8eb),LL(0x35e37920,0x4d9918bc)}}, {{LL(0xe32dd067,0xc029bd84),LL(0xf77f8962,0x25982357),LL(0x510b7cfb,0x7af256ca),LL(0x446925d7,0xca397f37)}, {LL(0xe0614e1e,0xb3dc7be5),LL(0xbbc4cc93,0x3b64cd27),LL(0xfb99bbc9,0xbd762df5),LL(0x04d7177f,0xc1ef0d4d)}}, {{LL(0x65e75ed6,0x77b6d3d6),LL(0x53053b45,0xbe59c8da),LL(0x54fe92cc,0x054d089f),LL(0x6fa4758f,0x2f2327e0)}, {LL(0x5d2b5a01,0x948cf03f),LL(0x9c23b83e,0x47544c4c),LL(0x6c128d69,0x338590fa),LL(0x76842160,0x5724008d)}}, {{LL(0xc4f063e6,0x4cbeb18e),LL(0x9c2f826c,0x507ba094),LL(0x6f4e49f3,0x0e877a6e),LL(0x34f56868,0x050c2040)}, {LL(0x0f119e25,0x8fd667c4),LL(0x13b47d3f,0x881dd34d),LL(0xca8e9a6a,0x2a6b636d),LL(0x107ea18c,0x67b081fb)}}, {{LL(0x84af55d9,0xd3a46367),LL(0xd7626b67,0x0e709a00),LL(0x4c6dfc8e,0x135725fa),LL(0x133a6e20,0xbf6328d9)}, {LL(0xa87031f2,0xa4b743b4),LL(0x13825d07,0x62e90e67),LL(0xb85f3c45,0x7004028e),LL(0x11751be0,0x0465c502)}}, {{LL(0x8a5ab076,0x4d5d467f),LL(0xf4fb8a45,0x9aa3f414),LL(0x5dc1fa84,0x9fa0422e),LL(0xd02cfd2b,0x3205c05f)}, {LL(0x078836b6,0x3eac28fa),LL(0xfc3ff573,0x53bc0189),LL(0x00b02100,0x2c45ef09),LL(0x34360ef7,0x61bc02ae)}}, {{LL(0x532e8d6a,0xeb5593e7),LL(0xf02a1ee4,0x94092904),LL(0x200496c0,0x379b32e8),LL(0x360a27c8,0x46fb6e9e)}, {LL(0x62005158,0x8a3377ba),LL(0x0de3f191,0x1a3266c1),LL(0xc94d2127,0xe60fad96),LL(0x646302f3,0x41553dd1)}}, {{LL(0x377e0766,0x88bf0bfa),LL(0xe75bf57b,0x870a24db),LL(0x79e77976,0xc133cb49),LL(0xf43b6f18,0x2f14924d)}, {LL(0xaa94cd73,0xe561dc90),LL(0xd6eb695d,0x8c420eb2),LL(0x2f04ef79,0x99e41ba8),LL(0x71e6d054,0x7f427bdf)}}, {{LL(0x10bde8ce,0x7304bb25),LL(0xe48b16f8,0x5dbc4325),LL(0x8796db7b,0x47d17ab2),LL(0x94c77832,0x83426817)}, {LL(0x9878ace2,0x6781850e),LL(0x019e97aa,0x7f747b90),LL(0x949f9b08,0xa0545c85),LL(0x244bc083,0xe0a0bbf8)}}, {{LL(0xa1f38ea6,0x8cb53666),LL(0x4989a568,0x9be29ff6),LL(0x083a7fcd,0xbc5a7f87),LL(0x44ca10f6,0x90d0129c)}, {LL(0xd724b7e2,0x1ad274bb),LL(0xcad5f069,0xa5290cbd),LL(0x86a4e0a9,0x886b1a7c),LL(0x8d8fb13f,0xd2481b5a)}}, {{LL(0x4f606ac5,0x80075fb2),LL(0xbfc10e7f,0xf984b5a2),LL(0xf056142f,0xd3d91aea),LL(0x4afdc017,0x770bee0b)}, {LL(0x6c49c827,0x3c42ca88),LL(0x0aaa3139,0xb620c4e8),LL(0xad87890c,0xac6b512d),LL(0x0eb61f92,0xaee62df7)}}, {{LL(0x21dad9ec,0xcf0f37fc),LL(0xc52e24c1,0xd780d315),LL(0x23a2b699,0x0263bcab),LL(0x9714b577,0xdc8dcd2f)}, {LL(0x55622b11,0xeb16eca8),LL(0x01118edf,0x94b3d649),LL(0xec66879d,0x6bafea64),LL(0xc4ab9f48,0xc35739c0)}}, {{LL(0xf3232370,0x082ccf53),LL(0x71407825,0x01b55dd3),LL(0x4f7f4038,0x86e0fe94),LL(0xb04159e9,0x1a623675)}, {LL(0xbc4df337,0xf908ca59),LL(0x816162ce,0x1b4f1ffe),LL(0x2d60e05b,0xb5128952),LL(0xd38cbdf7,0xb47ca0eb)}}, {{LL(0x8ee38219,0xdccba22f),LL(0x9fbb36ff,0xc9436453),LL(0x8ac12c9d,0x83cecbf5),LL(0xf4cb1ebf,0x591191b5)}, {LL(0xf03c1632,0x693cf383),LL(0xcb6abaca,0xaebd3f9b),LL(0x0fa26e7a,0x1427c154),LL(0x01bf37af,0x4f0de894)}}, {{LL(0xd88da2a6,0x4e497acf),LL(0xe5c86482,0x8014a215),LL(0xcf94ee40,0xa627d78f),LL(0x9ca36aa3,0x7647708d)}, {LL(0x87e108c8,0x3d4e8bb1),LL(0x516f8b28,0xacdc3223),LL(0x1d955038,0x74e4d436),LL(0xedd68905,0x7e4a198c)}}, {{LL(0xc4bfbad1,0x41dc4bdb),LL(0x85964942,0xfd1121b1),LL(0x0c0d85ff,0xe462eb9c),LL(0x2b012d88,0xade1ccb3)}, {LL(0x318f2aa3,0x2eec3503),LL(0xdec8a13e,0x656b44da),LL(0xcda13a8c,0x90b7aac8),LL(0x214a530f,0xe7f3a5ff)}}, {{LL(0x159060b9,0xa0c8062a),LL(0xd9305873,0xc19f2608),LL(0xc9609521,0x0d6213c4),LL(0x9aec4539,0xde2b9134)}, {LL(0xaeddf0a6,0x4a2a6476),LL(0x5cf2e85d,0x89222dff),LL(0x084a0245,0xad92a1d3),LL(0x2138063f,0x29644a60)}}, {{LL(0xb8164832,0x5b57a05b),LL(0x885ce4d1,0xecf6620f),LL(0x045d3b88,0xde28ed2f),LL(0xb4502308,0x3eb11759)}, {LL(0x4d9f94b8,0xe97f1db2),LL(0xeb83f016,0xfa248583),LL(0xcda53ba0,0x63a273b4),LL(0xa228b7b9,0x9692973a)}}, {{LL(0xb6707cbd,0x5968cb12),LL(0x5c1a2b4d,0x1895ccb4),LL(0x37f0b240,0xff309157),LL(0xb90875c2,0x374d983e)}, {LL(0xc4e815e7,0x22fc40c6),LL(0x98d18506,0xf2db27be),LL(0xaa9ae62e,0x2854a948),LL(0x79e39df1,0xd614a722)}}, {{LL(0xb3501c19,0xebeec551),LL(0xd89cefca,0xe2b878eb),LL(0x6b4cd6bc,0xa0a34757),LL(0x70bfdf88,0x0159129c)}, {LL(0x489502ca,0x26fa3e53),LL(0x285be050,0x7932084f),LL(0x71912b0c,0xfe4998f4),LL(0xc60b88b7,0x3dce0a87)}}, {{LL(0xc718ee5c,0x5b93edb0),LL(0xbb075836,0xb93a225f),LL(0x7aa0595c,0x87a08c94),LL(0xc31e3249,0x401d2620)}, {LL(0xdae2cdb9,0xbe6928b4),LL(0x5a226630,0x4b68e106),LL(0xc9d32e4f,0xdc38c2fc),LL(0x26542f89,0xc51a6245)}}, {{LL(0x1757f3c4,0x5fb37c1b),LL(0x89128aa4,0xa27d6c02),LL(0x5e629309,0x3b74f56f),LL(0x2f7aeef2,0x24b5ad84)}, {LL(0xbdc89596,0x54a962cc),LL(0xcc2f3d5d,0x6e8bccf8),LL(0x312e9241,0x4c1df22c),LL(0xfc30f0dc,0x8ffe6b0d)}}, {{LL(0xa6ec0fe4,0x670431a2),LL(0x35964572,0x49da0b42),LL(0x9dda5c39,0xbb12d1b0),LL(0x72d3de51,0x64170fe1)}, {LL(0xa4a2f5d9,0xea8b2b16),LL(0xe590be92,0xde1bad64),LL(0xf0b9b0b5,0xb7f93581),LL(0xe115d67e,0xb007f4dd)}}, {{LL(0x415732d4,0xab9d7523),LL(0x905ec0fe,0x2951149d),LL(0x74350478,0x94bb2c63),LL(0xe9b1ada4,0xe6b63bfd)}, {LL(0x13e8528f,0xd09b4d4b),LL(0x685bf239,0x6bed3d25),LL(0x1a14b7ce,0x83023ad9),LL(0xd0505d6b,0x4bffff63)}}, {{LL(0x8bb1cfa0,0x2ccc180a),LL(0x3a09c912,0x70c18508),LL(0x5878201c,0x318c41c2),LL(0x64c01149,0xb9f207b1)}, {LL(0xc58287d9,0x89fdd9ee),LL(0x05c43da0,0xdb6fa8db),LL(0x311a34a1,0xc31354f0),LL(0xf1521976,0xccfbaddb)}}, {{LL(0x0c5e8388,0xf4175f75),LL(0xa81226cf,0x7e090ce8),LL(0xeda6a1ab,0x5209107e),LL(0x7e5ccefd,0xf0a263cb)}, {LL(0x10c704a1,0x9fe05a36),LL(0xcf133aee,0x3784d7ca),LL(0x37af86c8,0x066c3116),LL(0xd7ebeb8a,0xbf32ca04)}}, {{LL(0xa9b5bab4,0x0447a950),LL(0x41bb1f1c,0x3b2f98bd),LL(0x59c62f08,0xd89bbdd7),LL(0x3ded069b,0x26bab370)}, {LL(0x69ea63ae,0xb0db4ca5),LL(0x9133df68,0x57b32f32),LL(0x5a17efbe,0xc79a22d0),LL(0xf8ae3c2d,0x576976a3)}}, {{LL(0x9d02d212,0x5754198b),LL(0x230d0213,0x9cc9e61e),LL(0x92889e33,0x76772179),LL(0xf5df6cba,0xb1246608)}, {LL(0x8d491280,0x821766bc),LL(0x96bd3df5,0xe148f470),LL(0xed753b73,0xc1e9fc70),LL(0xd6cecfc5,0x840e40ed)}}, {{LL(0x93e2f3a0,0x03874679),LL(0x5b646b64,0x462e5abf),LL(0xd7ae0e67,0x6fb19eda),LL(0xc3d2dddf,0x01e8a27f)}, {LL(0x4bacfe2d,0xc9e69639),LL(0x712e8afb,0xbc3a134e),LL(0x8af6d30f,0x5d943a86),LL(0x443c942c,0x65eb5f99)}}, {{LL(0x2339e348,0xf5000308),LL(0xeb0d80e6,0xd69b7693),LL(0x5b9d220b,0x7b00b43b),LL(0x497bbcf9,0xde0dfc80)}, {LL(0x0c2e851f,0xcfe2e3f3),LL(0x7e91d378,0xef7793d1),LL(0x9d266a5b,0x9e43eeac),LL(0x1766c5c1,0x9c81d68b)}}, {{LL(0xf6a4d560,0x121db320),LL(0x073582a7,0xcd0a4f03),LL(0x6e841041,0xbf469f9a),LL(0x5eb2d753,0x4314f0f6)}, {LL(0x8c498414,0x09021001),LL(0x859275b7,0xf63d00ee),LL(0xf1c0385a,0x228fa809),LL(0x694c3318,0x44259d51)}}, {{LL(0xa2ad4eac,0xb0a5d5fe),LL(0xabdedf11,0xbb950010),LL(0x6264c601,0x081024ce),LL(0xaefb4115,0x6cc7faf2)}, {LL(0x8692a7a4,0x90511289),LL(0x60596012,0x2bef4135),LL(0x0f0becb6,0xfec5209a),LL(0xd1ceb42e,0xad0907a6)}}, {{LL(0xf517372c,0x6cde3f21),LL(0x26131459,0x9acd4f09),LL(0x491f59d7,0xf3629a43),LL(0x41a037dd,0xe944561a)}, {LL(0x826d1b5c,0x07beeabe),LL(0x3a1476cd,0x0728a907),LL(0x7d4a1abf,0xa91f41a0),LL(0xa7a119c4,0xdf58ed06)}}, {{LL(0xba701704,0x19990669),LL(0x47b67175,0x8aa3f76b),LL(0xdd0a6e9a,0x8bccff3e),LL(0x24f49029,0x4173fcda)}, {LL(0x61c18233,0x2a688911),LL(0x78b9fa8f,0xdf54b239),LL(0x37596f40,0x714cf627),LL(0x24e6a879,0x2c73ddba)}}, {{LL(0xf2547f19,0x1538fd36),LL(0x0e7e84ee,0xd85c4730),LL(0x306f5fc0,0x00799e9f),LL(0x49ce114c,0xfccc6a37)}, {LL(0x3fe08120,0xf9cff5e8),LL(0xc2be9f27,0xdf876a1f),LL(0x6939fdb9,0xe817c72e),LL(0xd34d0e43,0x244a1800)}}, {{LL(0x78fa7f11,0x41e83eef),LL(0xba6367e5,0xecaa250c),LL(0x8def6ae6,0x9c420347),LL(0x250b9e58,0x99efb3b1)}, {LL(0x79b2298c,0xdaf311ee),LL(0x69b6dff3,0xb49200cf),LL(0x559e51f5,0x5c7f17bb),LL(0x424be7e9,0x117d0cbe)}}, {{LL(0x36e3af54,0x290a35c4),LL(0xe3a643b1,0xd2326cd8),LL(0x3580f9ee,0xc208b2b3),LL(0x4464a9e0,0x2419c661)}, {LL(0xbccb2759,0x87123d3a),LL(0x1a77d469,0x5d36fcf3),LL(0x49b07e5a,0x5aafd58a),LL(0x6b71e237,0xf534595b)}}, {{LL(0x6705039f,0x0f0d3161),LL(0xca701676,0x7282b08c),LL(0x13796941,0xb05e8c3e),LL(0xfca06e08,0x5250012e)}, {LL(0x980c5ea3,0x7eb2341a),LL(0xa41defb2,0x92f5aeb1),LL(0x0e62453f,0x203244e0),LL(0x96181756,0x74341218)}}, {{LL(0xe12a94ab,0x3b0cd36f),LL(0xb5ad7c48,0xf364b3b9),LL(0x8e768469,0x96a7a2a7),LL(0x1bbc7cc5,0xccc31c7e)}, {LL(0x080dbb92,0xe70ad5d0),LL(0x56fb0f1f,0xfb201e92),LL(0x29d99f57,0xdfce7a1e),LL(0x06457da5,0xc12a02b0)}}, }, /* digit=33 base_pwr=2^231 */ { {{LL(0x2a80f39c,0xdea72ba6),LL(0x68cbe088,0xcb2174b1),LL(0xd6bd1cc1,0x9c73ec69),LL(0xf20dcce6,0x6a2dbe20)}, {LL(0xeeaae9da,0x20a5150b),LL(0x9df630da,0xc935e85d),LL(0xa1634cd8,0x2147144f),LL(0x44f3af02,0x5eccb56c)}}, {{LL(0xc0e2b70a,0xf77a79cf),LL(0xee8cbae7,0x2569c8bc),LL(0xfadb18fc,0x392a5dbe),LL(0x3ce6a0ff,0x59bc96b4)}, {LL(0x8b551005,0x287f04f4),LL(0xa44b2bd8,0x7efe3aa5),LL(0x6ac447d7,0x0e9cb8ed),LL(0x7783bdd0,0x9b4eb10a)}}, {{LL(0xb981d96f,0x793c4880),LL(0xd56fb2a6,0xf719d828),LL(0x8149057e,0x9fcc236f),LL(0xb4d65c2b,0x318c63ec)}, {LL(0x5f95c5de,0x5269c1d7),LL(0xd0efd6bc,0x33b3745f),LL(0x4ae87c64,0xace344d5),LL(0xdd30ba2c,0x238809d6)}}, {{LL(0x71192348,0x3cc32acc),LL(0x3f17ef60,0x545401bf),LL(0xcde25b0e,0xe209a493),LL(0x663abab9,0x5c11886b)}, {LL(0x28ec7c90,0xe61a81b1),LL(0x75b57f5c,0x18b125a6),LL(0xfad91696,0x86d1b45a),LL(0xa4c3f7ff,0xb31a786d)}}, {{LL(0xf45831d8,0x2fd4cd72),LL(0x8be40d9f,0x85978fa6),LL(0xa9301111,0x38106329),LL(0x9e5979ee,0x1527e462)}, {LL(0x76c5fc8a,0x97f71c7e),LL(0xf1f33056,0x205fa473),LL(0xa6546a05,0x7bb9d24e),LL(0xf84c4d35,0x0e282a5c)}}, {{LL(0x59471f1f,0x59d21896),LL(0xf6303573,0x2e613dec),LL(0x78bf5a4b,0xa7995794),LL(0xbf19fbe5,0x20adf6b5)}, {LL(0x1574d34d,0x3a48c95f),LL(0x09323ceb,0x95488f09),LL(0x552df9cf,0x450aee7f),LL(0x53557500,0xdf016f7a)}}, {{LL(0x2da8a2a6,0xf2acedc6),LL(0x2f4a0632,0x03fc8cf8),LL(0x5b82f03a,0xe7ff136b),LL(0x9e88c421,0xd5841c4d)}, {LL(0x7eef63f0,0x75a4d66f),LL(0x2865c14b,0x92091ade),LL(0x64fe7ba3,0x7060474c),LL(0xfe30cb3e,0x4056724c)}}, {{LL(0x8d9fceb6,0x38cf4c6f),LL(0xab528f38,0x11e85f78),LL(0x52303b2b,0xe2896d25),LL(0xed68c605,0xf929675a)}, {LL(0x10c708a9,0xfbd22374),LL(0x40d7e5a7,0x4682ca17),LL(0x9041047f,0x4242b5c5),LL(0x0f9c6840,0xaf571053)}}, {{LL(0xa56af433,0x713b2bbb),LL(0x5e82f947,0x45aaf2ce),LL(0x106283c7,0x9882571a),LL(0x9b9c3c3c,0x37de12ca)}, {LL(0xbef10529,0xcb463af2),LL(0xd771236c,0xe18d763d),LL(0x62935de3,0xb47a69ca),LL(0x9a41e09a,0x4798e91f)}}, {{LL(0x8e93edd5,0x89696697),LL(0xb7ea4f45,0x35cdb8e1),LL(0xfed33d87,0x36f8305d),LL(0x625642d6,0x57623440)}, {LL(0x945dd7d6,0xdfd9b580),LL(0x731739bc,0x965ffcb5),LL(0x637bf127,0x34588e1f),LL(0x539d21c7,0x936c0ba0)}}, {{LL(0x71640eed,0x70832099),LL(0x3ff407e3,0x916b1952),LL(0x88440bc0,0x4cd58881),LL(0xc280e977,0xd9fcb83d)}, {LL(0xdf6cda83,0x0d3df9db),LL(0x3d55047e,0xc629414e),LL(0xc16b84c9,0xe05738a8),LL(0xe8783570,0xf4bdc724)}}, {{LL(0x9a93a5c9,0x7d876a59),LL(0xa8d12f61,0x026be75c),LL(0xe9b2aa43,0xe49900ed),LL(0xb3a68dad,0x44d6dc80)}, {LL(0x7d23e11b,0xf96b116b),LL(0xb6814209,0x12791212),LL(0x6cc65956,0x3e2807cf),LL(0xf405ffae,0xcc606ca7)}}, {{LL(0x5df47226,0x5484b2c5),LL(0x8802da81,0xfbaf9042),LL(0x087adadc,0x84146315),LL(0x58d593b3,0x6adbcbc1)}, {LL(0x68b97533,0xc1fb3896),LL(0x954cc1b7,0xa6919aac),LL(0x27a4ddd0,0xf301b2e4),LL(0xdf1a07b1,0xa15c16eb)}}, {{LL(0xc145a6c7,0xb36c017d),LL(0x968798da,0xcca64382),LL(0x8d0eff5d,0xd13b6376),LL(0x2206e681,0x06e39e2d)}, {LL(0x3add517a,0x1d9dffa4),LL(0x10d95fef,0xe670e6c8),LL(0xf1c7c7a8,0x0ecb51ab),LL(0x74945305,0xf17dff51)}}, {{LL(0xb00d9c0f,0xf71b09b1),LL(0x9c72c80a,0xc719cf62),LL(0xe00a49a1,0x310c5aeb),LL(0x1b33c5e6,0xd01285e5)}, {LL(0x05aa6eb7,0x7b23e7c7),LL(0x6bc88677,0xf84188b1),LL(0x64be321a,0x7e034cb5),LL(0xe884323f,0x270df734)}}, {{LL(0xe5137d20,0x218e68f9),LL(0x0f7e70ad,0x79588cba),LL(0x58b86b0a,0xb6d37f52),LL(0x7cc591fe,0xcb281c98)}, {LL(0x8fe40e06,0x30e03fed),LL(0xed9ca793,0x394ded95),LL(0xbcd3a3da,0xf1d22cdd),LL(0x0c591130,0xcb88cb27)}}, {{LL(0x8ff0cbf4,0x67786ba3),LL(0x0565d337,0x85738a44),LL(0xaf9a667b,0x9d3b35ec),LL(0x8f5f540a,0x45a17512)}, {LL(0xade5a5ba,0xf1ae5171),LL(0x39869be4,0x720e2823),LL(0x5352d84b,0x6893f14a),LL(0xc784dc20,0x919a4f15)}}, {{LL(0xf7ae5a67,0x36136612),LL(0xeaff0924,0x11f43d1c),LL(0x39449b96,0xcfee088c),LL(0x70c42ff6,0x3dc48359)}, {LL(0xbf208b67,0x4072683a),LL(0xbe15d18f,0x35a7c2be),LL(0xe2c3391b,0xe61d2748),LL(0x39921d95,0x0a4109b1)}}, {{LL(0x05545cfc,0xe2cd131b),LL(0x3ae20d7f,0xa898da2c),LL(0x50dc4c61,0x501cd849),LL(0x3374e7f0,0x10e287d4)}, {LL(0x38aea879,0x90d6326f),LL(0xef43fa08,0xc48d9af7),LL(0x6c20f168,0xf8f4886a),LL(0x23ccac4b,0xc5d34a86)}}, {{LL(0xb3d7004e,0x72357752),LL(0x817bd377,0x167db0ed),LL(0xdfb64d05,0x5d45b3da),LL(0xf0b414ac,0xed4b7fc4)}, {LL(0x0bf1dd64,0xc178941b),LL(0x8fe835a5,0x43feac17),LL(0x6a014609,0xe1c23a17),LL(0xd5e23bd5,0x63255991)}}, {{LL(0xd7dfec55,0xefc76468),LL(0xc0831696,0xb1bc3fee),LL(0x5f52433b,0x0996811b),LL(0x799649fc,0x6b8b6daa)}, {LL(0xab518b64,0x6e9f7cb6),LL(0x38a3a2ab,0x6a67a009),LL(0x928209e2,0xe55de954),LL(0x3da81142,0x98b6d0a7)}}, {{LL(0xe3f832e8,0xdec30331),LL(0xe50fa9e3,0xa9b77f3b),LL(0x5167c6a6,0x20febc21),LL(0x76fb0f13,0x0ce07d1a)}, {LL(0xe796f8a3,0x9745dead),LL(0xd95deba6,0x2cb4eb1f),LL(0x4caf2afe,0x062e7cac),LL(0x16ace879,0xf50ce065)}}, {{LL(0x1d99d3e7,0xdec8954b),LL(0xa48262c7,0x5287e954),LL(0xcc3530de,0x1c6fbd17),LL(0x53af4211,0x6bcbea50)}, {LL(0x4dce058d,0xe3533bca),LL(0xfc9cdf00,0x6fe62e64),LL(0xe8ec4cf9,0xee29fdec),LL(0xc8d52f80,0x7361797d)}}, {{LL(0xf4e36023,0xb1d858da),LL(0x73e6dee1,0x4a1282ce),LL(0xce1d71cc,0x6ba8f8ba),LL(0xcbbd8eb9,0xf5b7d6b4)}, {LL(0x5aed382b,0x60f8bd50),LL(0x3f3a46b1,0x47b40519),LL(0x8a997d93,0xaed13bb9),LL(0x4dc6e35d,0x6cc2260e)}}, {{LL(0xccf915d9,0x173bfcdd),LL(0xc2d46f6e,0xad4525e1),LL(0xcdd2382b,0xb7ecec0b),LL(0xd2b76c84,0x01ae8291)}, {LL(0xbec6b980,0x2d1e2a91),LL(0x7008a00c,0x1b0040be),LL(0x7d555120,0x6ac708d7),LL(0x0d745eef,0xa6017568)}}, {{LL(0x1ed38ef4,0x735e3511),LL(0xcebe5a8c,0x7c97f284),LL(0x24fecbac,0xd4059313),LL(0xde18c42c,0xf874ca4b)}, {LL(0xdbb829b6,0x9ab736a8),LL(0x82ff128d,0xe914bdde),LL(0xfd0f362b,0x6e949bab),LL(0xffea2e79,0x275824cf)}}, {{LL(0x8cc52417,0x81f57245),LL(0x2f274090,0xed0a9079),LL(0xfdd0ba2f,0x98c3372e),LL(0x3ae99478,0x49820f41)}, {LL(0xce373d3e,0x1c47e09f),LL(0x6dd12846,0x875d7920),LL(0x15d5bbb1,0x7a9e7973),LL(0x6d227962,0x48512656)}}, {{LL(0x199241e3,0x2c167c88),LL(0x7209ca37,0x98c1df6a),LL(0xde89e412,0x09a1583f),LL(0xc792de48,0xc19ed5b9)}, {LL(0x74dc0834,0xb8dd1b1d),LL(0xa04456e9,0x9d458529),LL(0xad0ad39d,0x66ef5463),LL(0xe641edc5,0x8d7df4a1)}}, {{LL(0x6bd322e4,0x97815de2),LL(0xc1f77fb3,0x0bf6fc83),LL(0x8b4f7152,0x49378167),LL(0xbf0a1712,0xfdd476ef)}, {LL(0xf2f9883a,0xe87e1977),LL(0x9ad2d034,0xdbb2fcbf),LL(0x64e1a4c6,0x5afdd161),LL(0x3e435191,0x0e43f911)}}, {{LL(0x42253804,0xde2d1ee6),LL(0xdaf13e57,0x6def6ceb),LL(0x05423bab,0xae09fd4f),LL(0xad46e409,0x6f6c17b8)}, {LL(0x6c345cd3,0x966fa09d),LL(0x47abc35d,0x6c8aa1e9),LL(0xe015a566,0x02991686),LL(0xcd2f925d,0x39b3aeee)}}, {{LL(0x9119c117,0xf9cda92a),LL(0xf4f833e1,0x7b21ce82),LL(0xe4f99193,0x87517bf5),LL(0x4eb412f9,0x1b7ddec9)}, {LL(0x6b077498,0x7a30dd57),LL(0x0ec44230,0xe060625f),LL(0xb0e5446b,0x0f355dc4),LL(0xbbd2df28,0xdf324d65)}}, {{LL(0x649966a5,0x28c7eb34),LL(0x26639e19,0x97587f4f),LL(0x0bce0f38,0x0724cc00),LL(0x4ae6280a,0x63578add)}, {LL(0xc7fd6a1a,0xf1beaa57),LL(0x7b017e35,0x83b1a533),LL(0xefdf2ed1,0x01c027e3),LL(0xd2d31852,0xf373d4ea)}}, {{LL(0x65b8f5d7,0xe568acb6),LL(0x1240a545,0xea8ce1b8),LL(0x555fac44,0xb95b0db2),LL(0x768333dc,0x01d18170)}, {LL(0xab1798ad,0xf938b55e),LL(0x999a7e5b,0x73a0d9dd),LL(0x57fd9b51,0xd2359bb5),LL(0x77fb4e5e,0x20f1d4fd)}}, {{LL(0x932dc388,0xf5efd71f),LL(0x21a37385,0x40f86819),LL(0xff935ef3,0x05395fb2),LL(0x1b615e8e,0xc2ee43ac)}, {LL(0xe82d509a,0xa3bb6518),LL(0x30b93347,0x3a87d5a2),LL(0x5b130bcc,0xac0a5ad0),LL(0x9154d73a,0x91fe8fdd)}}, {{LL(0xdeb203a2,0x677d7d48),LL(0x8b0168e1,0x4d4108fe),LL(0xddc3d24c,0x16be4ad1),LL(0x9865df69,0x9b0ea387)}, {LL(0x4c50ec70,0x16daf932),LL(0x478c96a3,0xa4799bda),LL(0x7114d3bb,0x4ef24d3f),LL(0x46e6bbdc,0x30a31509)}}, {{LL(0x97f3cb4b,0x60137187),LL(0x0a29d865,0xf2b66d8f),LL(0x60064a5c,0x93a4a37a),LL(0xe8c3cf47,0x7dee9bed)}, {LL(0x0b7ee8b8,0x748833ce),LL(0x56f89483,0xc07f2f6d),LL(0xd24b406f,0xd71a40d8),LL(0xebbb7655,0xbe3b2e8f)}}, {{LL(0x4a536998,0xa23c2b05),LL(0xa9be2e14,0xdcaf45b3),LL(0xfe346ad1,0x515ad15f),LL(0xb7847640,0xb9c06a18)}, {LL(0xf35bff4a,0x8552eb06),LL(0x2b7a29f5,0x4fb792e7),LL(0xa41a38b4,0x1cce2af5),LL(0x02b42414,0xde68bd0d)}}, {{LL(0x7cd66728,0x8124d6e2),LL(0x55efbadd,0x5906d1b4),LL(0x827f2741,0x7e17855a),LL(0x12c6966c,0xab525dfb)}, {LL(0x758e0cd3,0x065ae99a),LL(0x517318a9,0x0dcb8f5d),LL(0x42441f5e,0x48756645),LL(0xd79d535e,0x03859154)}}, {{LL(0x8217e4bf,0x99bb28cd),LL(0x8291e54d,0xd6aed2e5),LL(0x1c92a65e,0x8f9067e3),LL(0x1540b9b5,0x120890ea)}, {LL(0xec60a215,0x227d7c86),LL(0x556d8c65,0xb6609e85),LL(0x47f8c8a3,0xa6a26c37),LL(0xf1204bdc,0x4c850fe3)}}, {{LL(0x42db4eb8,0x25f7e61a),LL(0x3d62869d,0xfdf05575),LL(0x52b31c23,0x8b36a744),LL(0x1a5e8d4c,0x83b83c89)}, {LL(0x5d9208bf,0x72d38dd3),LL(0x8cf7b6f4,0xbeb8873b),LL(0xcf90bcb6,0xa3ec5c36),LL(0x9a6d5fe7,0x35adda6f)}}, {{LL(0xf61c68d9,0x7312423d),LL(0x20bcaf77,0xb1c4e10f),LL(0xf168ee57,0x4df2850d),LL(0x180985e1,0xed07a4de)}, {LL(0x2fba1f23,0xcb353d6b),LL(0x778cc15e,0x00ea9094),LL(0x20857170,0x4967faaa),LL(0xd7153bc4,0x9ff70dbe)}}, {{LL(0x59f62fc6,0x49eb7994),LL(0x3c91862d,0x5f459faf),LL(0x46d8f2e0,0x1c10f621),LL(0x252954e7,0x7e669c9a)}, {LL(0xa83f6c57,0x4ccf659a),LL(0xec0a0a03,0xdc2b77eb),LL(0x2cc6b8a2,0xcf09ad07),LL(0xa97aa2d0,0x231960fc)}}, {{LL(0xde227de8,0xc0609130),LL(0xf1d7ddf1,0x40d2691c),LL(0xf9a73890,0x60349cf4),LL(0xf9968132,0x3f50005d)}, {LL(0xf16f44b9,0xb4be853e),LL(0x799caac5,0x48bf4804),LL(0x3c562849,0xe6a64876),LL(0x854f283f,0x2f4d487f)}}, {{LL(0x159484c4,0x64b77e39),LL(0x523e1529,0xd419d4bd),LL(0x143dcf7d,0x1bf9510c),LL(0xed5cb4e1,0xa85bea71)}, {LL(0xec715818,0x73a4cfd2),LL(0x67f475f5,0x88b11d0e),LL(0x4d12361c,0xbfe170d8),LL(0x00a0f979,0x9fc48e64)}}, {{LL(0x65682105,0x6a8bb2dd),LL(0x00bd952a,0xc1362a9c),LL(0xa6013753,0xef5b3d89),LL(0x8fdfa22a,0xc87bbacb)}, {LL(0x31bb19e4,0x74fbdfc0),LL(0x32bfe260,0x7d058029),LL(0xe53da990,0x54a4cce4),LL(0x822da672,0x01acdff6)}}, {{LL(0x95597766,0xd2a2d484),LL(0xd43dc7fd,0x5960ac1f),LL(0x8d6db685,0xcf095b6f),LL(0xa85618f3,0x87232088)}, {LL(0x34753c7c,0x91497a48),LL(0xd6353024,0xf682e372),LL(0x0c9b271c,0x7889ceda),LL(0x18340951,0x7126504e)}}, {{LL(0x967c8a60,0xf786b821),LL(0xc17f3d99,0xfce01b37),LL(0x1f2a8575,0xe23c00a1),LL(0xab6ff8a0,0x7f56aa1b)}, {LL(0xd193dfcb,0xdb73869d),LL(0xd644733e,0xbec02c94),LL(0xf7b43261,0x283117bc),LL(0xb4108e39,0x920acf5d)}}, {{LL(0xe49aebb8,0x33f1ef5e),LL(0x0fcea2c1,0x9ead51e4),LL(0xf8503f28,0x1f800a68),LL(0x34a75f67,0x78818531)}, {LL(0xb70ffb27,0x1aeb3760),LL(0xcb6309e9,0x1cca590a),LL(0x7170d241,0x8d09f360),LL(0xa0e0d0f8,0xbc970b5b)}}, {{LL(0x31d038a3,0x2ec93eea),LL(0x5153f8a2,0x3482a0d7),LL(0x6641b5d8,0xedcbe914),LL(0xe516e387,0xc086e61b)}, {LL(0x9b875513,0x03814266),LL(0x37340a4f,0x6d37fee3),LL(0xe5d17ab7,0xcf78515e),LL(0x4119a759,0x0c7cd830)}}, {{LL(0x54924618,0xbd49062b),LL(0x41e7e7a3,0x34c44f45),LL(0x706bd0af,0x0039f3d2),LL(0x0be9a628,0x146cadc6)}, {LL(0x57d48746,0x6d5d5020),LL(0x82caf4b0,0x0ea43f7b),LL(0x8a064d34,0x11a08927),LL(0x95638fa2,0x30c0ef40)}}, {{LL(0x602a871b,0x4b950c04),LL(0x6a731537,0xf50cb1ef),LL(0xcbe5e4ef,0xb87a1cd3),LL(0x3dd1c601,0xb1fc4894)}, {LL(0xa516617a,0xdf402711),LL(0xaaf63c65,0x5bdd1d67),LL(0x6e559bd9,0x020d1062),LL(0x81ec09fc,0x4dec26d0)}}, {{LL(0xeeeeb2bc,0x7b91fafd),LL(0x33aaf2c4,0x56290f98),LL(0x79c7bf9e,0x57abbd27),LL(0x2b1e1ecf,0x568bdee6)}, {LL(0x470f1d01,0x58f8c80c),LL(0x1b9cb76b,0xeecfe398),LL(0x311a0634,0xc0ffa4de),LL(0x0ae99877,0x425fcd13)}}, {{LL(0xf7bd0748,0x1964c681),LL(0x9d920471,0xebcca16f),LL(0xab4aa03e,0xa72b40cb),LL(0xa05624fc,0x4397d6af)}, {LL(0xa94fca0a,0x372d522c),LL(0x3035b9fc,0xe1010d60),LL(0x4f788d44,0x9f1f00cc),LL(0x6a88b672,0xfd00ec75)}}, {{LL(0x2983aef7,0x53706702),LL(0x9b458edb,0xa5f67b0b),LL(0x7db93ca8,0x10789b90),LL(0xfd27cd55,0x885346f0)}, {LL(0x2ebb5f15,0x3af5b0c8),LL(0x2a36b2a7,0x282e4c4a),LL(0xa6d88bd4,0x2f9d5d8b),LL(0x9856b7aa,0x6f016bda)}}, {{LL(0xa8198c1d,0x990ae53e),LL(0xa07e7ac5,0x295beceb),LL(0x48c2d246,0x576f790f),LL(0xe3ea9864,0xe99ab2ae)}, {LL(0x43e2d400,0xcf4959f2),LL(0x7a39dfea,0xdd1d8fad),LL(0xfcd7fda0,0xdd6ff9c2),LL(0xb6ace55e,0x61c25b3e)}}, {{LL(0xb4dcddad,0xf94742af),LL(0x44601959,0xc49cfa21),LL(0x30c18470,0x07b3f1d1),LL(0x6e6afc82,0x2736cb99)}, {LL(0xe24a8785,0x401fb234),LL(0x074f51ea,0x9af8ba40),LL(0xa9faed0c,0xe1acc646),LL(0xc9667008,0xd5a5f789)}}, {{LL(0x68c3ab8f,0xc6436514),LL(0xfe8d6b46,0x6fa0d734),LL(0xaf7f49c7,0xe5fccbfc),LL(0xbebcc58c,0x42c88c53)}, {LL(0xe2a0f7f2,0x7d2e2fed),LL(0x36a18b26,0x694eb76c),LL(0x6b0f657b,0xf0e6ae43),LL(0x48f1ece7,0x8a0f6255)}}, {{LL(0x8674bfee,0xd594c168),LL(0xac7d5ebd,0xe59ad38d),LL(0x21645a1e,0x080a6b97),LL(0xf221b37b,0xb900f0e1)}, {LL(0x04cab97d,0x562dabce),LL(0x6f472462,0x5c308741),LL(0xc7c4cba8,0xa5d87e23),LL(0x9b061062,0x5237fe16)}}, {{LL(0x222021c1,0xeddfbeb4),LL(0x4e7a2a8e,0xa4fe57d0),LL(0x2de56c47,0x0fbf6bdb),LL(0x6fcebc6c,0x819588e7)}, {LL(0xdf041e3a,0x14196961),LL(0x40cd4f23,0x76a31437),LL(0x8e1a877d,0x44acd14d),LL(0x37d7b7de,0x227a35c6)}}, {{LL(0x842a9534,0xe1934f1d),LL(0x53ed73e2,0x7a2ed2c1),LL(0x3903924b,0xcffedd58),LL(0xb306431d,0x7c9dbf55)}, {LL(0x56e06ab5,0x61a72f10),LL(0x616bc5cb,0xb46cf5cc),LL(0xf7c22216,0xecf07e10),LL(0xd9364b3a,0xa4bddad9)}}, {{LL(0xda8b1c93,0x548b95b2),LL(0xa1e1c0cb,0xc09a9598),LL(0x21d80851,0xedd80ef1),LL(0xc283f047,0x4684c439)}, {LL(0x87333da3,0x07ca41f3),LL(0xca79a8f4,0x173ec4de),LL(0xb4aec6eb,0x89ce06f2),LL(0x15aaf7f0,0xfe6b0e92)}}, {{LL(0x7c1b9ed3,0xdab8876d),LL(0xa2606f83,0x88aba90f),LL(0xbebaf9f6,0xcd21a408),LL(0x0042a162,0x09da6696)}, {LL(0x2d66ccf6,0x4a9b8b21),LL(0x44d5a648,0x34c74904),LL(0x3b0e9564,0xf3fe98e9),LL(0x221aa4a5,0xe4a8a352)}}, {{LL(0x26c2b53e,0x6278b4b5),LL(0x1b1708ea,0x4ddf26ce),LL(0x6eb0d845,0x704207af),LL(0x0f5862ef,0x60533de3)}, {LL(0xe54393c0,0x2b5945dd),LL(0x145ea298,0x55941df2),LL(0xc240f654,0xe2b500b6),LL(0xcf9f6934,0x5a49d8f1)}}, {{LL(0x27502203,0xfe8d5468),LL(0x58ade316,0x985039d4),LL(0x0a687415,0xefd373f1),LL(0x43526774,0xefccb791)}, {LL(0x0f4497d9,0xeef8d46e),LL(0x1601ab9a,0x4152df71),LL(0xe47b2ad1,0x4250cd2f),LL(0xfb048180,0xa2b63fa5)}}, }, /* digit=34 base_pwr=2^238 */ { {{LL(0x787d1f1c,0xd8a6cb6f),LL(0x3d219a66,0x427bac94),LL(0x383146b0,0x51d7d49f),LL(0x7863d781,0x8164b77f)}, {LL(0x2f9631b8,0x1646b084),LL(0x849388df,0xef5b3aa8),LL(0xe58cd383,0x60536422),LL(0xf43ea3a0,0xb079d911)}}, {{LL(0xcb73887e,0x504ac041),LL(0xc3ce3a33,0xf878b618),LL(0x56393e75,0x57ef73d5),LL(0xd276c08c,0xe4372d2e)}, {LL(0x0924cf58,0xfd9bc894),LL(0xaaa317e2,0xfa2a4deb),LL(0x79608da5,0xe51edccc),LL(0x8cd4b960,0xadcc68fa)}}, {{LL(0xf8e156c7,0xaa66c201),LL(0x1ab2e3fe,0x7c7cf22e),LL(0x0a677d85,0xe479c393),LL(0xb87c412b,0xc0cd340f)}, {LL(0xf95ff321,0x2b2bcef4),LL(0xb8409952,0x65da11c9),LL(0xeb67eb9c,0x143a2218),LL(0xe53508e4,0x8919ff25)}}, {{LL(0xa9e0eeae,0x6f154f09),LL(0xab05a657,0x2246e6fe),LL(0x1045b85d,0x4d7c1c81),LL(0xd3bb7432,0xde99ea37)}, {LL(0x63184ff4,0x058f8187),LL(0xd134bfc3,0x2a223421),LL(0x23120320,0x1560dbed),LL(0x76a3de9c,0x37243c95)}}, {{LL(0xd36a81b1,0xb8f3851a),LL(0xbdad7ad9,0xfbc62bfc),LL(0x561e0f8c,0xf68215c7),LL(0x1bcf765b,0x894131d1)}, {LL(0x45c5d736,0x8da01f9e),LL(0x7484e0c1,0x025de05c),LL(0x6858b504,0x62f4c66c),LL(0xd6dc5f93,0x754b85d6)}}, {{LL(0x822a3de0,0x5b37cecc),LL(0xa98a37c2,0x422e49b1),LL(0xbe41e927,0x3ef53d89),LL(0xf4d5bffa,0x0994dd11)}, {LL(0xf7eacca3,0xa62ea556),LL(0x7c746025,0x37b4e230),LL(0xa8e14253,0xb4291e37),LL(0x2a2b666c,0x2bfc9eaa)}}, {{LL(0xc26e5588,0xf604604a),LL(0xa7ec3971,0xf75816ff),LL(0x26a30a6d,0x859e9ec7),LL(0xa1a5b815,0x2ce57b66)}, {LL(0xd65e8ec2,0xc7aa4df4),LL(0xa5d82ede,0xbab6b3bb),LL(0x7b088314,0x7a11b25d),LL(0xc2c636ac,0x501a3891)}}, {{LL(0xe256b02b,0x9f116c8f),LL(0xfa5946e0,0x71495693),LL(0xc335452a,0xeb9696ff),LL(0x4971162e,0x01ca5929)}, {LL(0xc0f28e72,0xee0a1f50),LL(0x70d8df1a,0x2baac62c),LL(0xf49110f8,0xcf65d297),LL(0x9a45e16a,0x041dbb01)}}, {{LL(0x5e1410c0,0x8db69426),LL(0xa70d0268,0xb21f3c6a),LL(0xbac0ddac,0x64a3c30e),LL(0x66a2d33a,0xdcebdedc)}, {LL(0xa519de21,0xc5dcd769),LL(0x19322c69,0xa692b6a0),LL(0x154fca13,0x454add5b),LL(0x4935eba2,0xd2281cf0)}}, {{LL(0xf2602323,0xb5f44fe7),LL(0x5d68a3db,0x772fb6a6),LL(0x76eec37a,0xf519c5d4),LL(0xada6c3f4,0xbc8e9a15)}, {LL(0xf18effee,0x9cd2a2f2),LL(0x1808ab42,0x9601c142),LL(0x0480ad18,0x05d110f7),LL(0xef6a7f33,0x5f7e0721)}}, {{LL(0xe6409e21,0x1afbeaec),LL(0x317f7967,0xf6714651),LL(0x80124751,0x34cd21ff),LL(0x931d9639,0xf85c70ec)}, {LL(0x1ca19094,0x4e26bef6),LL(0x0b841b9a,0xc513f66b),LL(0xb9b41001,0xe25507bd),LL(0x94f49f7c,0xd77fee94)}}, {{LL(0xd39e1ee4,0x20b19223),LL(0x4e3e6c2c,0xc8832a2c),LL(0xa3a45c34,0x64a8f43d),LL(0x21fb291b,0x52a05eef)}, {LL(0xe4b68e38,0x10d3e24a),LL(0xee2d8a40,0x5289120a),LL(0x425b7da8,0x33836b98),LL(0xb00c64e1,0x5bd418f3)}}, {{LL(0xd511c3f8,0x10e92e5a),LL(0x18b62b7d,0x17f1301d),LL(0x97f0fcae,0xf710b02d),LL(0xbd394477,0x8b1030f6)}, {LL(0xe5aab897,0x49040009),LL(0xce75b4d3,0xfdb23ac1),LL(0xf2b70e1b,0x7a43d904),LL(0xf94fa56f,0xdc09e995)}}, {{LL(0xd075dd65,0x9f314e85),LL(0xb9e26b8d,0xc0d39ce0),LL(0xfdc3b678,0xd3f6778e),LL(0xfc8497df,0xce6573e9)}, {LL(0x67abaf7a,0x1f4535f8),LL(0xa47dd948,0x80706dab),LL(0xc059242b,0x670ae5bc),LL(0xcf5f9308,0x3a29bc73)}}, {{LL(0x8af2bf74,0xd2f8e297),LL(0x6c48bbec,0x98dbb443),LL(0xeb448447,0x211a3a96),LL(0x5af4a2c0,0x88ffb240)}, {LL(0x9cdf9e20,0x1959dd34),LL(0xf34627e0,0xa4d0d839),LL(0xf00057cc,0xa5cecad3),LL(0xc5d97b18,0x22f32cce)}}, {{LL(0xcedc2c97,0x31a02241),LL(0x2b632641,0xf0f5489b),LL(0xcbfb588f,0xb09091dd),LL(0x5d9478e7,0x5ffd0f38)}, {LL(0xdae35eda,0x13f141a1),LL(0x62f0b26c,0xd25563a6),LL(0x1b9dde18,0x80014b17),LL(0x7da49b36,0x9fcf8f81)}}, {{LL(0x93519f31,0x68aac84a),LL(0xc0b3660a,0xe14c35c1),LL(0x08195bc5,0x29f447dd),LL(0x10bba62f,0xc61fbbe6)}, {LL(0x4ed8621a,0xc471624c),LL(0x0950a4c6,0x8005f67f),LL(0x93a2a33e,0xdfc3b3e5),LL(0x3c1d0e42,0x9c3c815e)}}, {{LL(0x93904766,0x1ed1aedb),LL(0x376fd0bc,0xcd5e0cf6),LL(0x90d03033,0xdd4c3378),LL(0xd85dca30,0xde39db01)}, {LL(0xe6fab58b,0x49d01dc2),LL(0x6d449f51,0xd16d7940),LL(0xd20a95e6,0x3fb6cf8e),LL(0xbbeeccb1,0x0b10a596)}}, {{LL(0x0005acd3,0x06ceaa62),LL(0x47555053,0x09db6b28),LL(0x7e7d18d7,0x45d84a85),LL(0x229ad33e,0x33c28b02)}, {LL(0x72e4f34c,0x1e5a6b52),LL(0xb64fa831,0x81eefbe6),LL(0x2aa209aa,0x4983b84a),LL(0x38d6a8d6,0x20777198)}}, {{LL(0x40096f25,0xbe993805),LL(0xec820131,0x900d4bdd),LL(0x2a993f9c,0x2170cfd3),LL(0x2dfe1007,0xa0e3d894)}, {LL(0x0e7df109,0x600d0b5a),LL(0x47fde3dd,0xc904985a),LL(0xcb89816a,0x15597a84),LL(0xb9dfeb9e,0x8ac8b027)}}, {{LL(0x6450a179,0x5c9211bc),LL(0xf6333f95,0xd448a70a),LL(0x824e1d7f,0xe9c9a964),LL(0x15750ae4,0xc47d3f3c)}, {LL(0xadcf9482,0x959f776b),LL(0xe741ceb3,0x00557ffe),LL(0x353d7898,0x8b69d3f6),LL(0x45cfa492,0x6b4d80d3)}}, {{LL(0x30c313da,0xc33ead78),LL(0x67eee139,0x86f96c3a),LL(0x08611b15,0x0c6675c7),LL(0x60620c27,0xf9ee695d)}, {LL(0xd70c9258,0xb35d438c),LL(0xa5e7a4b1,0x1bc2b1e7),LL(0xef92f629,0x38d257f8),LL(0x79fd1eb0,0x090af73a)}}, {{LL(0xf59342e5,0x96ebd1f0),LL(0x4d053375,0xd4869362),LL(0x5fab54aa,0x7db504e2),LL(0x6e8e43fb,0x17c0801e)}, {LL(0x136b1941,0xd3904d62),LL(0x28a43bd1,0x5932b753),LL(0xacb35572,0x551d895e),LL(0x1a6fdfbe,0x3f7a8a46)}}, {{LL(0xf7a2df83,0x9e3ea4fd),LL(0x64524d44,0x8b68b26b),LL(0x126aee21,0x74caeeab),LL(0x915d9e1c,0x590a00a5)}, {LL(0x49b90eff,0x5ae2a6ab),LL(0x2df4fe51,0x74b4cb1e),LL(0x07fcb6ed,0x0306ed11),LL(0x502f5b30,0x564ebe2e)}}, {{LL(0x0c89e9ba,0x5a09a32e),LL(0x84f2466d,0x967f9dfb),LL(0x26a1a8a0,0x8b27416c),LL(0xc3158a18,0x1c21ef95)}, {LL(0x2be23ae9,0xa7ee1ad8),LL(0x4daa1fcf,0x1f312d04),LL(0x44f9c7d7,0x6782f843),LL(0xe19e2681,0xb12ea2bf)}}, {{LL(0xd20578af,0xd2e43cbf),LL(0xbb5819b4,0x5566460a),LL(0xb658c03c,0x86f6c860),LL(0x62d42d82,0xc8d90309)}, {LL(0xcb883ceb,0x7975a5f3),LL(0xdcded5a1,0xf6f5cf0f),LL(0xd3eb810b,0x25554fb1),LL(0xa596c7c6,0x3df7536b)}}, {{LL(0x83de31cd,0x255ca136),LL(0x7795eb96,0x7ac532ee),LL(0xb12bc235,0xfa9d83a9),LL(0x4b287a83,0x7df5d231)}, {LL(0xb4f19fce,0xb2eaaaf6),LL(0x1a045f6a,0x7caabfb0),LL(0xb1449e6a,0x6d1b7f40),LL(0x12d22c82,0x24ae41da)}}, {{LL(0xc0a9d128,0xb0f7a0c3),LL(0xaed0d3bd,0x2adc34d3),LL(0x13e778e6,0x4ebf5778),LL(0xbb8476ba,0xd3b89bd0)}, {LL(0x37413953,0xe09eb528),LL(0xd8ba3471,0x952b705c),LL(0x86a79c09,0xcaa81ade),LL(0x7e0e7b2a,0xc08eed3d)}}, {{LL(0xc80b4196,0x313fb103),LL(0x88c7ac81,0x25449ece),LL(0x24f16fa2,0xa6cb9ad3),LL(0x728a0c4b,0x4602c441)}, {LL(0x5a000a9c,0xc3366f88),LL(0xef8778bd,0x146623e3),LL(0xf0773fdc,0x184ba0b1),LL(0xaecd8d63,0xe1d115ef)}}, {{LL(0xae165e6c,0x420d5473),LL(0x108d8575,0xefe137cd),LL(0x6fcff7d9,0x15378c57),LL(0xc1f5b601,0x49c48099)}, {LL(0xf68473f1,0x1b0e3aee),LL(0xd320720d,0xa78329bb),LL(0xdca54cad,0x385e521b),LL(0x5c5b8d60,0x478ce06f)}}, {{LL(0xca7c4d4b,0x215d7d33),LL(0xa095366c,0x773f3ab3),LL(0x7afeeaa1,0x668e0d11),LL(0x4878d8a3,0x410cd205)}, {LL(0xb2800646,0x2748fd98),LL(0x73a1dbef,0xf1183786),LL(0x7567ed3a,0xecc31bd2),LL(0x0ceb3873,0x775210df)}}, {{LL(0x9a8f42ff,0x2ea0c2bc),LL(0x4a1c029a,0x62974240),LL(0x9e4dd41b,0x5ee5f5f6),LL(0x2e110249,0x5b1bba80)}, {LL(0x78da8016,0x5ac4eadb),LL(0x1809f79f,0xc2978780),LL(0xe3f8c0de,0x39d2dbce),LL(0x064d3ba9,0x7fb4b5fc)}}, {{LL(0xcd481ab4,0x038a736d),LL(0x396888eb,0xc4b15c5c),LL(0xd421f36f,0x459a896d),LL(0x47f54663,0x6058b90f)}, {LL(0xafefebe5,0x0a5f6771),LL(0xa5b7c2ca,0x45c97ab2),LL(0x85139ca4,0x6d547af9),LL(0xa29d71cb,0x6db218de)}}, {{LL(0xfb956184,0xca6e0e7b),LL(0x1f660ac6,0x6682b6e3),LL(0x8b21bceb,0x3959e396),LL(0x632cf9c8,0x0459fd46)}, {LL(0x74f296bb,0xc741250c),LL(0x990dbefa,0x29b9cacf),LL(0xfc35bdf7,0x5065d818),LL(0xa551dc04,0xeb8e9e1b)}}, {{LL(0x11befe9e,0x4f7d6f7d),LL(0x7478fdee,0xa88f1fce),LL(0xafa688e3,0x39b1e053),LL(0xe16847e0,0x562a0d6e)}, {LL(0x34c26d14,0xf6044e4b),LL(0x7df61b90,0x5ebe8727),LL(0x6b5e5a39,0xa82a4de4),LL(0xfb9d296c,0xc916b0ba)}}, {{LL(0x2e1dc01e,0x029f1cb2),LL(0xfc429483,0x7699d92e),LL(0x154560f0,0xee0e425a),LL(0x787b6641,0x3f5cdfe6)}, {LL(0xe5f6794e,0x726d87bb),LL(0x23aecad2,0x97d73588),LL(0x09ca351c,0x47f4f5b9),LL(0x57dc5e3b,0xd742ef4b)}}, {{LL(0x71411a86,0xccd2209d),LL(0x2223e6ce,0x94d57663),LL(0x66c7950c,0x228a7400),LL(0x54dd4e37,0x2d00ef6e)}, {LL(0xd60f66be,0x9ea5daf3),LL(0x8aca724f,0x743c58a5),LL(0x44e38446,0x1f638406),LL(0x92ef6bb0,0x06314bb0)}}, {{LL(0xbb05589d,0xa7459e7f),LL(0xbfa913d7,0xc3a39592),LL(0xdf07b190,0x27dbabee),LL(0xd2ee62ff,0x1c8a2f33)}, {LL(0xe31e8d63,0x60c8bcb8),LL(0xce410061,0xea1604d1),LL(0x3d7f7a98,0x55e8cfee),LL(0xebc64102,0x49efc316)}}, {{LL(0x41934914,0x04c86d8e),LL(0xab7facd4,0x26667c76),LL(0xa71a8916,0x319158db),LL(0x114fff43,0xb802942d)}, {LL(0x8ce544f5,0x5efdef7b),LL(0x70e870c1,0xf531c718),LL(0x4d92071d,0x4b9a5f1b),LL(0x60cc48b6,0xbe767cf2)}}, {{LL(0x717381ea,0xbf389d37),LL(0x06bc5bcb,0xefd9e984),LL(0x67ff1110,0xcc8bc960),LL(0xb05612e4,0xd3414c0b)}, {LL(0x927fad1a,0x084e5f05),LL(0x438e241f,0x999bd581),LL(0xfaa4fab8,0x0c917602),LL(0x95080657,0xda0520d2)}}, {{LL(0xce2f1af2,0x3160f928),LL(0x364f56e4,0x61186d84),LL(0x25fa68f0,0xe36a5fc0),LL(0x774c584b,0x9e6f66bd)}, {LL(0x9ecb449a,0x2611bba4),LL(0xec5a0667,0xb1e0b341),LL(0x6cddb6c3,0x336de76d),LL(0x65a18f95,0x9668b5b3)}}, {{LL(0x7c3ec388,0x1ff6c81f),LL(0x40a8e2d0,0x53545b05),LL(0x14ae31d6,0x990a3cc5),LL(0x063a2995,0x769b4c26)}, {LL(0x039e279f,0xcea238f4),LL(0x732fb38e,0xbfc5cfb9),LL(0x82fa05d8,0x99f5a33c),LL(0x69c42686,0x274dc741)}}, {{LL(0x76af2af7,0x193338ee),LL(0x6914ae66,0x0488c19f),LL(0x5fc58bf4,0x8d197f4e),LL(0xf0e61d4b,0x23de54df)}, {LL(0x44a165e1,0x547dd09f),LL(0x1c2d5471,0x99878065),LL(0x39b311db,0xb2cabfad),LL(0x4b61a7eb,0x0aed63d9)}}, {{LL(0xbe8110ef,0x03713ac5),LL(0x50f989d3,0xaab1917d),LL(0x358fe8b0,0x0d80fe98),LL(0xa7a1f8e3,0xf6e874c5)}, {LL(0xdeb42398,0x05650fd8),LL(0x1c44de73,0xbad3e085),LL(0x1c27f3c2,0x5369135f),LL(0xa7fc74ac,0x14bc04f8)}}, {{LL(0xb5dae291,0x18cbf622),LL(0x9356b88c,0xce290570),LL(0x39eba4e6,0x61bbb446),LL(0x980fee37,0xa79c291b)}, {LL(0x19960cc6,0xd9f18006),LL(0x0ce98896,0xb0823f41),LL(0x1377df6f,0xf2bc612e),LL(0xc0b0e71c,0x1c07bded)}}, {{LL(0x37211fd5,0xffbf9841),LL(0x04a81410,0xbd704a6b),LL(0x6abf1c67,0x653cd2ee),LL(0x40681621,0x73ab8aa1)}, {LL(0x271ada5c,0xc0bae4fd),LL(0xc46f189d,0xf567cae8),LL(0xa5535334,0xd183cb27),LL(0xe53c530c,0xcbf133f7)}}, {{LL(0xedd6a17e,0x32e53f78),LL(0xa2194fae,0x6ce6da9a),LL(0x58cd3586,0xa89b8054),LL(0x43b520a5,0x0037febb)}, {LL(0x653e2c0b,0xbe67a2cf),LL(0x50301f52,0xc07a1ed1),LL(0xf5ea954f,0xf98b2b60),LL(0x7af6c499,0xfa6da95d)}}, {{LL(0xe3889cb1,0x44892091),LL(0xd45ae338,0x123fc555),LL(0x02a63128,0x2bc4a9ef),LL(0xa1dbb436,0xb72012c9)}, {LL(0x556a0b46,0x8c75f7b3),LL(0x5b7608a4,0xe4c6f46c),LL(0x38fce20f,0xb36abf68),LL(0xbf6c21e1,0xb5a8e657)}}, {{LL(0xcecd5963,0x9ceaeefe),LL(0x6105fc29,0xe84f200d),LL(0x8591e346,0xc28981a9),LL(0x207001f1,0x0be4e931)}, {LL(0x88616b18,0x31399d9d),LL(0x238c626e,0x3dac9f55),LL(0x65574274,0x0213fca7),LL(0x827aa853,0xa3560244)}}, {{LL(0x1ca99134,0x3ffbfeeb),LL(0xd07a2dac,0x0a4b56f6),LL(0x75417a6b,0x01795eca),LL(0x18a5fb22,0xe2a6dd9c)}, {LL(0x8aca0cd8,0x13c97586),LL(0x7c323c52,0x3c2bb26e),LL(0xe38319bf,0xa3688cae),LL(0x4c88726a,0xe04b44b4)}}, {{LL(0xb0a88a4c,0xfed864d0),LL(0x6b1fa305,0x3e6cf152),LL(0x00e18e4a,0x8416b5f0),LL(0xfa4cd8f2,0x3a7603ca)}, {LL(0x7ec750ef,0x8b04d5ff),LL(0x1c1ced05,0xe1867f9b),LL(0xdac2f8c1,0x87ffd0fb),LL(0x08b3cdca,0xc9ebe420)}}, {{LL(0x029c247e,0x5028a4fd),LL(0xa5ae3e76,0xd6225a43),LL(0xf970817e,0xfb3fa71c),LL(0x9ab4aef1,0x74216809)}, {LL(0xa39c2f13,0xca81ee99),LL(0x86a97827,0xa8336e42),LL(0xb6489555,0xb75aff99),LL(0xe565435c,0x005b2338)}}, {{LL(0x524bdb34,0xbaee27bb),LL(0x82e47e71,0xbf22e1c9),LL(0x97491139,0x6ab1d712),LL(0x2cf4cbff,0xf420ce06)}, {LL(0xb2b0c86a,0x9f96a2fc),LL(0xabeb7335,0x42765dd9),LL(0x45b7e044,0x7c223bb7),LL(0x1794e144,0xce3f9245)}}, {{LL(0xf3ee5c4e,0xa0a15b27),LL(0x54622215,0x1721c5bf),LL(0xada5a99c,0x0003fd16),LL(0xdbdccc7b,0x8e96dd56)}, {LL(0x43f83748,0xd1abdc0b),LL(0x0f5ce74b,0x71cac4a6),LL(0xd46717ad,0xb8539aff),LL(0xb99661d9,0xeb65c589)}}, {{LL(0x85e89e17,0x66b4df3b),LL(0x6fc30672,0xc94fad66),LL(0x81d90df8,0xfd2aa80f),LL(0xbd8234c1,0xed73a163)}, {LL(0x72eb45dd,0xe1a2c0b9),LL(0x902b5ca9,0x417e355d),LL(0xd5128812,0xa8f55aaa),LL(0x3c14cb79,0x4826b934)}}, {{LL(0x394d7a92,0xeae495e3),LL(0xb90faec0,0xcba23153),LL(0xf6d9d80c,0xd687c821),LL(0x8bff3082,0x951dada2)}, {LL(0x701708ad,0x4e74f1f0),LL(0xdd2134f2,0xa6333cd1),LL(0x04665f7c,0xeea276cf),LL(0xae74c17a,0x527257fc)}}, {{LL(0xe51b53bd,0xeb3fd493),LL(0x69ec567e,0xae7807db),LL(0x5de15fd0,0xa50124aa),LL(0x1336f055,0x781bfe70)}, {LL(0xd70a0dfc,0xb5729a74),LL(0x9f50c1a3,0x89da37f3),LL(0xcd8e6c1c,0x6e063297),LL(0x181d0271,0x17eb6ec1)}}, {{LL(0xe4e52a8c,0x36e7251a),LL(0x94705324,0x3acfe89b),LL(0xbc130c3b,0xaa94f06e),LL(0x309ae25a,0x01b5e44c)}, {LL(0x0f61b55b,0xb72160f2),LL(0xe7bbc3f2,0xbef61953),LL(0x1bf138a1,0x96734d7a),LL(0x08c25135,0xdaa6186c)}}, {{LL(0xf34534a2,0xa3b031b2),LL(0xde46f581,0x44136619),LL(0x6d379647,0x4d0ed04b),LL(0xbb2b6735,0x4879d90d)}, {LL(0x590156e0,0x8f7e031a),LL(0xf42bbc53,0x28428354),LL(0x5c5b791e,0x1cbed33c),LL(0x4cfc5562,0x17571645)}}, {{LL(0x7f76462f,0x8392350a),LL(0x0c216ccb,0x659ce7db),LL(0x047e35d5,0xe87a78b7),LL(0x6e0862d6,0x307c4861)}, {LL(0xe70741bd,0xd444fb86),LL(0xfea1abe2,0x1138a886),LL(0x62b79c4f,0x4695397d),LL(0x003130ee,0x11aaf588)}}, {{LL(0x3a11712b,0x53bdda6d),LL(0x40fba3d2,0x30c384bd),LL(0x50ea38be,0x63039585),LL(0x3da9738a,0x7f110eca)}, {LL(0x5b68c01e,0xbd701fc6),LL(0xcc48f38d,0xd23f3e8f),LL(0xf8b9bb65,0x6e2557eb),LL(0xa3dafc8f,0x29ceb4b6)}}, {{LL(0x4b6b7705,0x24659686),LL(0x4aca2b43,0x04143a8a),LL(0x975e06d8,0x3baed256),LL(0x3e834249,0x846fb3c9)}, {LL(0x75f6770a,0x7890761e),LL(0x203c78fd,0x1187920e),LL(0x6b26281f,0x9b06c3a9),LL(0xa98215e1,0x3fe3dccd)}}, {{LL(0x4f33655e,0x099d7d7a),LL(0x662fb55a,0x1ba571e6),LL(0xcbc497f0,0x1a0d0147),LL(0x2862ff38,0xa94218ae)}, {LL(0x5ce08047,0x1b0f919b),LL(0x2baf46cd,0x9a3ac37a),LL(0x8964cc68,0x76b7a03a),LL(0x4d3e1a40,0x5aed8c6d)}}, {{LL(0x7f034ff4,0x6607179c),LL(0x3781eac2,0xefb8fcd9),LL(0x7b022138,0xfa57f8a9),LL(0x56ab6039,0xc5bb9f1d)}, {LL(0xe4d2ab7f,0xf9027e24),LL(0x77a9e364,0x3d67ad71),LL(0x1f7f487d,0xc579e70c),LL(0x2a7e6bd0,0x7fefc894)}}, }, /* digit=35 base_pwr=2^245 */ { {{LL(0xa45cfd31,0x2cb91662),LL(0x16f65cfe,0x09dd56d3),LL(0x14f3de51,0x983e005d),LL(0x210f64fc,0xb9dc05b0)}, {LL(0x885eafe5,0x22790afd),LL(0x7444bdec,0xbd5213d3),LL(0x8987300a,0x289dca92),LL(0xb3960b76,0x69fb2ac2)}}, {{LL(0x9ae7540f,0xe3274886),LL(0x6131e921,0xd7386631),LL(0xf2a360c8,0x2e3d4fd8),LL(0x3d9d41e0,0xb20a59b6)}, {LL(0x99082a34,0x72b67eae),LL(0x51819470,0xfad6aa7d),LL(0xa2d1d007,0x7c299b9a),LL(0x8100bed0,0xc1f841e0)}}, {{LL(0x43e90ebd,0x2c1f7d4c),LL(0x1fc72b07,0x58b78107),LL(0xaf94f402,0xda8503e1),LL(0x59f244b0,0xfbb724b7)}, {LL(0xfcd8755a,0x2fcd2186),LL(0x868482b7,0x7407cdee),LL(0x349be3d5,0x4d62f578),LL(0xdcc6202c,0x4a012544)}}, {{LL(0x151ffc08,0xb8a414d2),LL(0x740d6b55,0xaa79acf0),LL(0xcdf472ab,0xeeab0104),LL(0xa3aa5f1d,0x5014a8c1)}, {LL(0x33f13425,0x8c743405),LL(0x57eb54d4,0x2b776b49),LL(0x548a723b,0x3a0cc4ac),LL(0xc79fe63a,0x65aae6f3)}}, {{LL(0xee5e579c,0xe8b388f2),LL(0x991c03d4,0x31cc9373),LL(0x567bfa7c,0x53eed518),LL(0x67f985ed,0x267e282d)}, {LL(0xb4763ea0,0xc435fd22),LL(0xe39b7703,0xead83837),LL(0x094ba5b4,0x806daad5),LL(0x45842672,0xa738a847)}}, {{LL(0x9984c4c2,0x99421b42),LL(0xd35c7bbd,0x1a3bce27),LL(0x3563b09e,0xe51ae6f6),LL(0x8d9c9fbf,0x8e67853b)}, {LL(0x6b2100b5,0xca8784da),LL(0x98879bba,0xe89a24f7),LL(0xe286b039,0xe901b45c),LL(0xf50384bd,0x23dedbb8)}}, {{LL(0x5cbf7df2,0x4728cbdb),LL(0x6764329e,0xed274fdf),LL(0x642d199a,0xc2af1a07),LL(0x17a50e7e,0x5d665659)}, {LL(0xfaa5eb82,0x7babf4bc),LL(0x99fe4026,0xd3bcfc67),LL(0x607d9f41,0xaa5d2648),LL(0x967efac1,0x7405c071)}}, {{LL(0xdfa782a4,0x79447ef9),LL(0x74cd9500,0x6dadc8e1),LL(0xdc38f762,0x0574020e),LL(0xe2ee7a14,0x17596d7e)}, {LL(0x9e1f8adc,0x9ef75af7),LL(0xa4791da0,0x5ac5f216),LL(0x7b7b5d80,0x1583226b),LL(0xa21c26cc,0x59f3f053)}}, {{LL(0xf95e30d9,0xd80e7fdc),LL(0x0a3a3616,0xecf5041c),LL(0x03043fa6,0x50b93b8b),LL(0xae262ad6,0xa31a2aa4)}, {LL(0xd63cd98d,0x1468b370),LL(0xdc07a367,0xfb89cc65),LL(0x4d47b59f,0x6cf1df6b),LL(0x1b6350fe,0xab451a99)}}, {{LL(0x8c124dff,0xeb74554d),LL(0x21be0be0,0x781a8c4d),LL(0xe3510068,0xfaacc154),LL(0xd6238265,0x16655d65)}, {LL(0x0466134a,0xba46d27b),LL(0x3101e283,0x1a3f51b9),LL(0x096ec237,0xc08298a9),LL(0xc69cfb5b,0x46248627)}}, {{LL(0x81a0500f,0xf9e7a5a4),LL(0xbd2e03e7,0x92db27d5),LL(0x82899e3c,0x3dcce4f6),LL(0xf39a39c7,0x861f1797)}, {LL(0x69dc8961,0x175b2430),LL(0xdc67953e,0x93d2a88e),LL(0x92d794d6,0xa40f3704),LL(0x3526eeaf,0x607019f0)}}, {{LL(0x22f37d65,0xf20e163b),LL(0x32cf180a,0x70fd00c8),LL(0x0b17244e,0xff1a97d2),LL(0xacedb33a,0x9a5a141b)}, {LL(0xcc16bbb4,0xf03dd868),LL(0xa40e44e9,0x9b15372d),LL(0x15ac397f,0xd5ba6436),LL(0xc821f6b7,0xb1a886d4)}}, {{LL(0x4b7b4e21,0xbe3aacda),LL(0x66b56729,0xad9829fe),LL(0xd541cc1a,0x78965cef),LL(0x7d17631e,0x414bfea7)}, {LL(0xc64dd621,0xf55835d9),LL(0xef644d93,0xa0ebf68b),LL(0xc8a40021,0x01d15340),LL(0x42b99aa0,0x00ae640d)}}, {{LL(0x6881e64f,0x92321ee2),LL(0x5267bdd3,0xaccab5c8),LL(0x5927647b,0x0c1f87ea),LL(0x162c6d86,0x0093d07e)}, {LL(0x389c711d,0x49868df4),LL(0xc11e1f37,0xe68d69ae),LL(0xb4207246,0xa40e7aa8),LL(0xce832395,0x4ae8d126)}}, {{LL(0x86450cc0,0x5f9b128a),LL(0xc8ec07e6,0x88f76293),LL(0x179702b8,0x0762f293),LL(0x4910006d,0xb5696102)}, {LL(0x35fe0505,0x3951291b),LL(0xce8d7056,0x70f75a5c),LL(0x2eb13369,0x4541beaf),LL(0xa643316c,0x7060a749)}}, {{LL(0x49c879a5,0xee16abd0),LL(0xa47ac42e,0x844874a7),LL(0x3c9c2326,0xee3f8a20),LL(0xdeaed33b,0x99a12054)}, {LL(0x63b333ae,0x4814a15b),LL(0x9d923fa0,0xee9f28a5),LL(0x33b1b1ef,0x5b0cd250),LL(0x8346d928,0x3ccc39b9)}}, {{LL(0x002bec95,0xf5c1000e),LL(0xf63528c2,0x2ba2f18c),LL(0xcdcec15a,0x8102f6c8),LL(0xbb13d14a,0xab7effcd)}, {LL(0xfcd3787c,0x183e0ba2),LL(0x2f4a7fc0,0xae70635e),LL(0x760bbc96,0x473ed37f),LL(0x8a8efb39,0xf0ea0acf)}}, {{LL(0x29b526a9,0x63cea36c),LL(0x9d03f3db,0xcdb31613),LL(0xd57cca8e,0xa3891096),LL(0xa14a8ffc,0x646418a9)}, {LL(0x8075291f,0x10f8906b),LL(0x2c618bf6,0x8221d941),LL(0x8a5da4df,0x1dc1ae7a),LL(0x8a8cc8bc,0xb66b96e3)}}, {{LL(0xfe3551b4,0xe4da7e48),LL(0xad9b3827,0xe6891cc9),LL(0x6b37b99f,0xb266733f),LL(0xfd5d1219,0xfccce911)}, {LL(0x7262b8cc,0xe5a47c4b),LL(0xe656af49,0x5d349caf),LL(0x7e04e48e,0x7a3a4a28),LL(0x80ea7d03,0x7c39a68e)}}, {{LL(0xbee0d434,0xf35d5e32),LL(0x0b536161,0x9651f3d9),LL(0x72cb370c,0x42634cc9),LL(0x406b3457,0xa7764026)}, {LL(0x65d53d80,0xec7525bd),LL(0xadcc8b05,0xf44a1bca),LL(0xda112ddc,0x12ef8427),LL(0x20a0f78f,0x796a65b3)}}, {{LL(0x6bd5b0ab,0x12726e24),LL(0x8242fe07,0x9e441467),LL(0xde2bea52,0x4b52e276),LL(0x10422c2c,0x3a76b6b4)}, {LL(0xb4e496b9,0x71f14945),LL(0xf36dce4f,0xd20f04b0),LL(0x2b310e90,0xa0e57d8d),LL(0x32ec8f38,0x59eb7737)}}, {{LL(0xaaf6619e,0x20a19834),LL(0x691a538e,0x633b94e8),LL(0x92cdf395,0xea1a8985),LL(0x4349b971,0xa3a01c57)}, {LL(0x30822c59,0x0d65192a),LL(0xa522ae8c,0x93a5152d),LL(0x0e1aa4bc,0x5b09a7a3),LL(0x8d3b97a9,0xdd2588f3)}}, {{LL(0x5b62a3a5,0xafa1f62a),LL(0xa9ace9c5,0xbded10e6),LL(0xbf6e7fb2,0x9d03e061),LL(0x4b87177a,0x60c564a8)}, {LL(0xc22c14c1,0x36be1308),LL(0x9425b6bb,0xeeda57e8),LL(0x36af38c2,0x5ddaae14),LL(0xecdc2911,0x1695464b)}}, {{LL(0x161e13e7,0x4b795e1d),LL(0x907e7069,0x0f9abc20),LL(0x54522fe7,0xfb3be618),LL(0x1938134e,0x9e2d0f37)}, {LL(0xd292c6b0,0xb8dc7c36),LL(0xc1e77895,0xbafbf59c),LL(0x1b6c55f3,0x7d0132cd),LL(0xf609f087,0xefa02ed9)}}, {{LL(0x03519f9f,0x4bfe6aeb),LL(0xdab4c075,0x248e19a0),LL(0x69429f29,0x83ee803d),LL(0x8190ce56,0xdbbe31e2)}, {LL(0x6b787a5d,0x3ba735d2),LL(0x1818070c,0xfa021185),LL(0xa3683cee,0x9b653000),LL(0xe9517ba2,0xfc3c7907)}}, {{LL(0x88d94f69,0x6521c92f),LL(0x7b52da8d,0x3950e9e8),LL(0x8ee64a88,0xadb81700),LL(0xf73994fe,0x8ccbfa3c)}, {LL(0xb048e71e,0xb780ab12),LL(0xe2aeb607,0x52879e7b),LL(0x3237554f,0xef04b1ed),LL(0xe1d5a5ef,0xaeba6a96)}}, {{LL(0x266f7e93,0xedb58542),LL(0x5ea02852,0x9a1b8057),LL(0x5beb3fbd,0x1963c6f2),LL(0x1ad52473,0xf4183355)}, {LL(0x6faed2f4,0xca772e9e),LL(0x3cf8fd1f,0x937eddd0),LL(0xc1d49dac,0xb3255376),LL(0xe670d3cc,0x549c2119)}}, {{LL(0x3b6cd199,0x10edbf39),LL(0x75644d6a,0xe9479223),LL(0xd6e8cc36,0x36cfba92),LL(0xfe00d80a,0xa37b1d91)}, {LL(0xdeb5ef4a,0x3aadf918),LL(0xd3893df2,0x5bb2ca4d),LL(0x6569ab8b,0xa776000e),LL(0x1cf64905,0x4fb2308f)}}, {{LL(0x273731c2,0x04da4d09),LL(0x23c05518,0x1d4a61fe),LL(0x0d5206e5,0x201098a3),LL(0x06430c82,0xd9a7ad4e)}, {LL(0x36f7f462,0x56df0d06),LL(0x44c81042,0x2c067f3d),LL(0xc453d28e,0x01193bc9),LL(0x45ce6e64,0xcdf5af5d)}}, {{LL(0x0f7d8d12,0x9992ce1a),LL(0x0e5e4542,0xa7c46a61),LL(0x057802ba,0x3fcc0647),LL(0xc7dccbe2,0xa78f73d8)}, {LL(0xf138dc6d,0x67f37b94),LL(0x650a9002,0x89330885),LL(0x68aa24c7,0xf661caf2),LL(0xbf73c435,0x47732bcd)}}, {{LL(0x3b04622e,0xb9ba5f91),LL(0x477d420a,0x24265f73),LL(0x0d44cb89,0x5da6ddb0),LL(0x151fc40b,0x9f8cb8b6)}, {LL(0x9b9f2613,0x81b6956b),LL(0xebb917df,0x37419206),LL(0x2bb7a709,0xdb9cfc16),LL(0xbacd3fb7,0x7a800aa3)}}, {{LL(0xd93f6e1a,0xf8ea9359),LL(0x3d41c118,0x729005d4),LL(0x7cb641af,0x4c293410),LL(0x895e8e78,0x6b2b4671)}, {LL(0x5958fad3,0x2a1251d0),LL(0x78619fe4,0xb69bc2be),LL(0xd911d318,0xd74df34c),LL(0x15102704,0x5def8378)}}, {{LL(0x08268482,0xb19ea17a),LL(0x1c37e5d1,0x14591196),LL(0x7640df9c,0xe0e12d2e),LL(0x8c941274,0x8fd6bd4d)}, {LL(0xdcd142b1,0xc3f9f120),LL(0x78dfe6b0,0x106c49ac),LL(0xcfd9b542,0x243c8e93),LL(0x0a2c5fe6,0x6758062d)}}, {{LL(0x15f2f638,0xee5a99e8),LL(0x13979ab6,0xb95b008d),LL(0xacfcca6a,0x7fd03105),LL(0xe4ced1b3,0x6af914a4)}, {LL(0xa25f8627,0x8bef3d0f),LL(0xf9b2f931,0x21bae309),LL(0x2195a839,0xe85dee2b),LL(0xa3baeb25,0x46ad0ad9)}}, {{LL(0x022b62a9,0x6d8e40f8),LL(0x90b5cd33,0x4a6bbabf),LL(0xffa89bb2,0x53481e6b),LL(0x22003cc2,0xd674b3b3)}, {LL(0x004a2aa6,0xc71a0a85),LL(0xb5404657,0x86df9697),LL(0xc74e80cc,0x407727f4),LL(0x950a7b08,0x39c13926)}}, {{LL(0xd74472a4,0x26bee75a),LL(0x2eb6f0d6,0xbf7c4ea0),LL(0x608bea48,0x689a5de5),LL(0x29d513f8,0x5b383892)}, {LL(0xda457cf9,0x49fee2c2),LL(0x62d523d3,0x7fc0aee7),LL(0xb636a46e,0x5bf447de),LL(0x8194766e,0xda3efd98)}}, {{LL(0xd382756d,0xa77c3ad2),LL(0x0fa55315,0xc0eaa9de),LL(0xb1df90e3,0xe68d0a51),LL(0x01d1d8a7,0x0994e8c7)}, {LL(0xa91bfed0,0x4f898bc3),LL(0xab6025df,0x1c2a3e46),LL(0x8b269271,0x37bd5c37),LL(0x8b97f0af,0x4e07f5ca)}}, {{LL(0x97923d14,0xe346b5aa),LL(0x9e0bd9c4,0xa8549f61),LL(0x40113a60,0x78e59d6b),LL(0xed8a0fc6,0xe3015fb2)}, {LL(0x8b43288a,0xfc56a08f),LL(0xcae6c18a,0xcbdb8cae),LL(0x5f4423db,0xcb147c44),LL(0x10f361c1,0xa6aaa6c9)}}, {{LL(0x7caf702a,0x6be86c0c),LL(0x736f6dac,0x2188e83c),LL(0x59ba2af9,0x40b5ed25),LL(0xab8018c3,0x76211894)}, {LL(0xf5b0b048,0x0c1c532f),LL(0xe3200521,0x7503aca9),LL(0xdfa7eb2d,0xb9325d85),LL(0x2edbb68f,0xe6c25a00)}}, {{LL(0x8c673c89,0xf9ff5867),LL(0x099c7bae,0x4925a046),LL(0xdbb1e1b6,0x0b3bf59a),LL(0x30ae084f,0xc7e9d9f2)}, {LL(0x0fa1776f,0x70982396),LL(0x624c897b,0xb2e1b98f),LL(0x6c3534d5,0xa9a6407d),LL(0xa4dc3f63,0x5e22319b)}}, {{LL(0x2431dc01,0xc2f0bf3f),LL(0xc2cfb315,0x478f797d),LL(0x3b3ae0c5,0x6559f59c),LL(0xe18e74a8,0x7e95aa62)}, {LL(0xd3fce912,0xf2a94006),LL(0xe1bd96ce,0x7f1b57a2),LL(0xa3d7b828,0x55028ad0),LL(0x4f09fe92,0xadae7e92)}}, {{LL(0x757b418f,0x2174c736),LL(0x3661d54d,0xd904ba43),LL(0x63218ecb,0x0281f912),LL(0xc50c8eb6,0x5fd03ba0)}, {LL(0x896a5aea,0x29626906),LL(0xe55ee73f,0xab4d3f27),LL(0xedfd1991,0x3db1c43d),LL(0xa3f9c340,0x498cc31a)}}, {{LL(0x4fe75d33,0xa43bdec1),LL(0x66ae5d4f,0x5b067dfb),LL(0x464c8239,0x84581814),LL(0x503a52ea,0x2f10557f)}, {LL(0xa10fbb90,0x21c4c180),LL(0xf79d5e02,0x33b191ee),LL(0xb499478e,0x6dee3881),LL(0xbfbd56fa,0x27dfef0b)}}, {{LL(0x28be2d62,0x671a3dd7),LL(0x050897ff,0x06f2f4c2),LL(0xb7c4587d,0xd92bdab6),LL(0xfd8d5160,0xd2253a16)}, {LL(0xf1c098b1,0x64f6e4ae),LL(0x11ea7255,0x005a3939),LL(0xdab542e5,0x2ed4eb92),LL(0x50c5e874,0x26920bc1)}}, {{LL(0x5d0bc87c,0x93e8f58a),LL(0xb2b29b4b,0xaa4d313e),LL(0x01b2096f,0x3e175dec),LL(0x1cf31783,0x6c560972)}, {LL(0x73b76f6b,0x9d41aca2),LL(0x5f1d4b12,0xa2454cf5),LL(0x65b35eea,0xa5615196),LL(0x70af4fde,0xf241e516)}}, {{LL(0x65061472,0x5255e91b),LL(0x5bdbb257,0x6ef98d2d),LL(0xc74c7b2c,0x0d1d1ab1),LL(0x2e9febde,0x9ffb9fdf)}, {LL(0x6c50bf24,0x853f3b9f),LL(0x6fbd22bd,0x3d369594),LL(0xbcdad9a9,0x4d281126),LL(0xdc46ddc1,0x99eb62b6)}}, {{LL(0x4b10c402,0x5aa8c8b2),LL(0x473af61d,0x2e79f595),LL(0xce360f37,0x96153360),LL(0x66bc29dd,0x16dffe22)}, {LL(0x1137f9c3,0x35536eb1),LL(0xe2a6a47a,0xd636ecad),LL(0xb499f840,0x83cdf214),LL(0xd247f18c,0x3642c77c)}}, {{LL(0x916ef527,0x4d906a2e),LL(0x293dc085,0xadeb94d0),LL(0x1491da3e,0x03a07801),LL(0x0b84d2eb,0x177dceae)}, {LL(0x7b691e0c,0x61e5a3c1),LL(0xd172cea3,0x47d40bd7),LL(0x8ca76bce,0x7d0646ad),LL(0xc64d635f,0x90b030a9)}}, {{LL(0x97118df2,0x71eca8e7),LL(0x3ac9536b,0x2cd48f70),LL(0x89fb4d72,0x9ffd991d),LL(0xebf781fb,0xd49006bc)}, {LL(0xd3e60da1,0x688af07f),LL(0x619063b7,0x5f74aa46),LL(0xa40d313f,0x44fcbeb3),LL(0x326faaa4,0x0ed5908b)}}, {{LL(0xf41ec05d,0xe836d537),LL(0x221b0c32,0x01eaf207),LL(0x72f8c904,0x1d6a0bb6),LL(0xdfd74641,0xa6ef58b2)}, {LL(0x811bd6cb,0xbb855ceb),LL(0x05408eab,0x7b1c8b71),LL(0x4187fb7f,0xd24d709e),LL(0x8b30a9be,0x283d647d)}}, {{LL(0xf9f0d6e6,0x6d9d3793),LL(0xb1c06b19,0x02fc3ddb),LL(0x94d9abec,0x8ff86793),LL(0x24705873,0x1f20bba2)}, {LL(0x0021b290,0x74eebc12),LL(0x35b6c157,0xd859521e),LL(0x431aea79,0x2201aa41),LL(0x90da1a75,0x79c1caaf)}}, {{LL(0x6e412a6a,0xcd6abab7),LL(0xb4c58b05,0x82399139),LL(0xa3b55538,0xdf416966),LL(0x679882d3,0x2b2d546f)}, {LL(0xf9145657,0x17425cbc),LL(0xe1b8247e,0x3cc6735f),LL(0x57edd04c,0x13e50c56),LL(0x1b85b7cb,0xc8723137)}}, {{LL(0xdc0ab9d5,0x907b5b02),LL(0x4ab23b78,0x5617fb7f),LL(0xe8f449cd,0x7ae8ff03),LL(0x174e0e22,0x86d3ff17)}, {LL(0xbf1e9f8d,0x22cb7f69),LL(0x0b0c62f0,0x12f0abbe),LL(0x537f658c,0xc8315981),LL(0xc467f2b4,0x43da2770)}}, {{LL(0x5b9e88ef,0x3ef9bb81),LL(0x3a8e51f2,0xb8526318),LL(0xf8d744ac,0x2e47cb7f),LL(0x510aaa7c,0x63d6dc16)}, {LL(0xb40ccc41,0x54da7cdb),LL(0x402b2ad9,0xdecbe5fd),LL(0x34c8f225,0x14c6f15c),LL(0xc6559496,0x6d8b2342)}}, {{LL(0x66fea635,0xa4b72281),LL(0x22f248a8,0x55f5c27f),LL(0x0959cd01,0x3ced1483),LL(0xb53bdf42,0xcc6469db)}, {LL(0x1e460645,0x2bb2346f),LL(0x9d7535e7,0x4d8573c6),LL(0x49cd2d68,0x988cddd5),LL(0xb9835538,0x785c4a70)}}, {{LL(0x1f6e396c,0xb08337b3),LL(0x49a782f3,0x6166b21e),LL(0x8ec9b974,0x1ac6198b),LL(0x0bb44d3d,0xee2e3446)}, {LL(0x35039dd9,0xdb283740),LL(0x29f5c692,0x7c708f95),LL(0x98ddb466,0x8914cce0),LL(0xd446f3cf,0x8bb1b9f1)}}, {{LL(0xee0933a3,0xa9dea222),LL(0x4b26049e,0x2538bd43),LL(0xbdcafae2,0x18741aca),LL(0x16b0f4bb,0xe0f830f7)}, {LL(0x902caefa,0x0479ec95),LL(0xdcda9e64,0x1f858937),LL(0x515c4089,0xe75b4f7b),LL(0x2eb91b51,0xb78afde4)}}, {{LL(0x18949935,0x1eebe3e9),LL(0xba092037,0xde8deaa9),LL(0x93609411,0xd43cf4ef),LL(0xc2d7b76e,0xe0fdb1e4)}, {LL(0x4e34b4bd,0x1d3191a5),LL(0x9ccc4c26,0x106d92f1),LL(0x29a2a6d1,0x1a404ef6),LL(0xc598f481,0x3338bc9c)}}, {{LL(0xe3fcbf71,0x3945e39d),LL(0x9c89ab61,0x123b082c),LL(0x0f9f3c37,0xc7477f77),LL(0x7dbcc077,0x408c0c7a)}, {LL(0x3654f98c,0x6c4d99f5),LL(0x05299a1a,0x276a007a),LL(0x23e2d7d0,0xabd4b8ea),LL(0x86017545,0xe05a5f3a)}}, {{LL(0xa11b03cd,0xde3b885c),LL(0x8df5d64e,0x46ef0755),LL(0xbf3f085d,0x112a49d6),LL(0x198ff32f,0xf6ebf441)}, {LL(0x7feae481,0x581c00d8),LL(0xcfde5b2f,0xf2b43827),LL(0x9b7358f2,0x3ceb7f8f),LL(0x55fe7117,0x95761fbd)}}, {{LL(0xdc04773c,0x305836fa),LL(0xb3c4873c,0x66324504),LL(0x55b130de,0x5d878c1f),LL(0x8ad49a9b,0x96e9b28c)}, {LL(0x76d70429,0xd1a707b8),LL(0xaa402e90,0xaff33f93),LL(0xedbfb28f,0x733d6256),LL(0xa75d2342,0x9e421a7c)}}, {{LL(0xc02e49c1,0xdf86b254),LL(0xb56d308a,0x6bb53867),LL(0x73f29561,0x771dde4b),LL(0x8bf28e5f,0x96eaf73e)}, {LL(0x06fbb550,0x9b1ee6be),LL(0x97d4a4e8,0xe09fec77),LL(0xd5aa84fd,0x93bdcd60),LL(0xd457ab9c,0x3fa8d3a0)}}, {{LL(0xa0a2e52c,0x315b32b1),LL(0x3bbcb61d,0xe7e50b2d),LL(0x5e5c6e11,0x8a55cc0e),LL(0x961295ef,0xc2bfa998)}, {LL(0x66e996d1,0x4a5ab3bb),LL(0x4886a421,0x22c42e4f),LL(0x4850e0a4,0xa0cdd364),LL(0xc64ed713,0x7682d38d)}}, {{LL(0xa2c539e4,0xe31575c2),LL(0xa756daf9,0x0bac5dcd),LL(0x91f55a12,0xe917cecf),LL(0xe96f6299,0x1e96433b)}, {LL(0x3700d8fb,0xeec7c71c),LL(0xdc9b4444,0x9a1d2965),LL(0xcf74f19c,0x3d2c6970),LL(0xac5e0d6b,0x3b444c48)}}, }, /* digit=36 base_pwr=2^252 */ { {{LL(0x8ccb854c,0xe563cefd),LL(0x65b0c45a,0xf5452cdb),LL(0x9c37f743,0xb3c78769),LL(0x95d444ab,0x34e9d192)}, {LL(0x52ff26b7,0x29347946),LL(0x9b94d642,0x70d6ecfa),LL(0xfdaffb8f,0x7d201858),LL(0x45dcdc71,0xc288719d)}}, {{LL(0x0728a2eb,0xc695469d),LL(0xc433d11c,0x7b46244e),LL(0xf106c08e,0x4a8b99ba),LL(0x63422083,0x7989794f)}, {LL(0xd4fc5696,0x82218867),LL(0x3c79cdb8,0x6b021f28),LL(0xb26d5049,0x5ff7bbea),LL(0xa7261628,0xb78611ca)}}, {{LL(0x531313d7,0x5a75f961),LL(0x66dcdc9e,0x85a1f4db),LL(0x6460e991,0xae3026b9),LL(0x17ecf7cc,0x7d467bef)}, {LL(0x05118708,0x8a0dbf67),LL(0xf3b2f1c9,0x54bfa368),LL(0xf2c0e4e0,0xa9fc9d5c),LL(0x5e93611b,0xa8c2ad11)}}, {{LL(0xaa1256bd,0x3ef1faf0),LL(0x9e4631de,0x0f224545),LL(0xde9c2676,0x69cb9800),LL(0x95782b24,0x26019816)}, {LL(0xa66c0ccd,0x945c172c),LL(0xb440719a,0x6c25f635),LL(0xa49f681a,0x917d5dba),LL(0xb2dc5df4,0xc0cad047)}}, {{LL(0x5960ef1c,0xd45bcf4c),LL(0x8c6979d5,0xbabcb16d),LL(0xae9090d6,0x8e3be750),LL(0xac0eb728,0x9481d261)}, {LL(0x0d6a7d46,0x46b436cd),LL(0x1f976501,0x6eb1a6a3),LL(0xdbe1064f,0x5984ffa2),LL(0xf809dc20,0xe6575fb1)}}, {{LL(0x4d974a81,0xf0426d80),LL(0x97a74be6,0x61304f0f),LL(0xa9486531,0x2346ff98),LL(0xf53d781a,0xa1242cca)}, {LL(0x97355f15,0x482f03df),LL(0xbd6058cf,0xc607ed33),LL(0x68aefe28,0x03bc8cd4),LL(0x851307e4,0xa6e7de5a)}}, {{LL(0xc6af7d44,0x2c07df0f),LL(0xb15a9188,0x310b251f),LL(0xd3e15c2f,0xd42661ce),LL(0x1b4d8313,0x5198fd90)}, {LL(0xda8368a1,0x7a6062cd),LL(0x5e9c2542,0x1a905d11),LL(0xdae37cee,0x1d752b70),LL(0x16bf84ca,0x3ed8c1a5)}}, {{LL(0xeecc2f22,0x5190fb0f),LL(0x698d8e60,0x3df210f3),LL(0xf5f3ce72,0xcce57d3a),LL(0x312b8fc6,0xb2fb6223)}, {LL(0x71867c84,0x79947005),LL(0xbe139ebe,0x141cd92c),LL(0x5de7944e,0x415efc9e),LL(0x45821058,0xae9ee919)}}, {{LL(0x5bf363dc,0xd696e1d9),LL(0x8251449c,0x6a1bcfc0),LL(0xa5fa53e9,0xa1b82dff),LL(0xeef05378,0x6c56b5be)}, {LL(0xc0e74dc3,0xaf9efe4c),LL(0xe5c1f1a0,0x3d9a7ae9),LL(0x2823c3e5,0x34b38577),LL(0x41fbabac,0x69f297dc)}}, {{LL(0xd74c5a65,0xf01aff98),LL(0x1951a915,0x97993104),LL(0x723096a6,0x8b211915),LL(0xa769ef1f,0xf85910c4)}, {LL(0x8ddc0eb4,0x30cefb9e),LL(0xbb09607b,0xd5957eef),LL(0x2355b499,0x2e139c9c),LL(0xc1789013,0x5749531d)}}, {{LL(0x5475f2d2,0x1603ca64),LL(0x0a336508,0x57190e0e),LL(0xcea7d558,0x2203b703),LL(0xfb5503e3,0xf16eba4d)}, {LL(0xb7344a98,0x62e2ce3d),LL(0x9a4efa7a,0xebf5b243),LL(0x1c914064,0x96212455),LL(0xbe5bbc07,0xd2c5e31c)}}, {{LL(0x06c30b28,0x2b5f2f77),LL(0xbc9823d3,0x0931841d),LL(0xadfa6fdb,0xd16fb08b),LL(0xd6fd441e,0x8892bae2)}, {LL(0x2e576983,0x3fc64630),LL(0x07b05529,0x08c60fb6),LL(0x7afc1d4d,0x32b283b1),LL(0xa2f0e37f,0xc9c56965)}}, {{LL(0x4644e173,0x8e719178),LL(0xf88b43ff,0x4c2a11ec),LL(0x7d3ddbb3,0xb13644e6),LL(0xc3d8703c,0xd4746056)}, {LL(0x55dca667,0x6611395f),LL(0x27c91d73,0x63596712),LL(0xea2ff489,0x4ca68a87),LL(0x337adc1d,0x2864a816)}}, {{LL(0x224d4f21,0x8aa830ae),LL(0x9f7845dc,0xda6c122e),LL(0xfb240793,0xb0c61ffc),LL(0xce8580e9,0xf4df6842)}, {LL(0x0a990dc7,0x94372aaa),LL(0x5ce1aa24,0x42968cd3),LL(0x4df363a5,0x177c5ff0),LL(0x68c4546f,0xa8c3f737)}}, {{LL(0xbd21c524,0xc69750d5),LL(0x22a6c4ae,0xbf3b4857),LL(0xe2883a1d,0xcefcbb98),LL(0xae13f22b,0x6ffef743)}, {LL(0x5defea01,0x6316ba60),LL(0x4ba63810,0x0a89e6a7),LL(0x15ab0e11,0x7f9af1de),LL(0x385911c9,0x6247ca15)}}, {{LL(0x32f9eaf5,0x6f7b1a6a),LL(0xacfc13dc,0x2c440f94),LL(0x66b18adf,0x2cf39bc5),LL(0x9f01533f,0xb9939fe8)}, {LL(0x383a6450,0x031c4553),LL(0xf0102087,0x16d96ad3),LL(0x501f1360,0xcbd6fa95),LL(0x65f96c08,0x667d3ea0)}}, {{LL(0x68a1a680,0xa5a7cbfa),LL(0x42041db7,0xf131d779),LL(0xd85d377f,0xbefee3ac),LL(0x3b62dfa2,0x6d0ed6b7)}, {LL(0x1baacfbd,0xef683f0f),LL(0xc976cebd,0xc586c4f2),LL(0x3b163339,0x3a4120dc),LL(0xc79e5c1f,0x9ac9b950)}}, {{LL(0xe294926a,0xaf1ff35f),LL(0xa2103168,0x2703bab8),LL(0x658a52bf,0xc645560a),LL(0xe466fd97,0x5ff3ccd9)}, {LL(0x54867f14,0xe62fdc01),LL(0x9cdba39e,0x435ef950),LL(0x92828acc,0x2a7bbffd),LL(0xfe763981,0xe7538fdb)}}, {{LL(0x8bfe9773,0xedf45173),LL(0x471b8b9c,0xd187fa01),LL(0x78fa54df,0x34506c35),LL(0xc2767589,0x73cab9fd)}, {LL(0x6726f305,0xf8f76c65),LL(0x8de332b2,0xea45012d),LL(0x87970e03,0xb746f40d),LL(0x1ba8fbd6,0xb2b2279a)}}, {{LL(0x21147dbc,0x79cdc610),LL(0x9939a3cc,0x738ef680),LL(0x8101bd8b,0xd66d6ce6),LL(0x09323caa,0x65612acb)}, {LL(0x10310a29,0x6874b372),LL(0x5ee9ecfa,0x3cf30f0a),LL(0x8cfe1df8,0x4e1026ad),LL(0xd5989af5,0x75a153f7)}}, {{LL(0x8b8e0c49,0xc362ccee),LL(0xb533f3dd,0x8adfc0d2),LL(0xa109572e,0xe02ab03b),LL(0xfd3066ec,0x06efacdc)}, {LL(0x3fa28700,0xf136a8ba),LL(0x308cceb9,0x48a1e987),LL(0x68253387,0xe8ee7c03),LL(0xc2b463c7,0x47febbe8)}}, {{LL(0x39a5c4d3,0x485195f2),LL(0xa26241ec,0xf42e000e),LL(0xcd05368d,0x08c64f90),LL(0x857cdbdb,0x46fbd381)}, {LL(0x4c7e16ae,0xf711df8b),LL(0xe4edea42,0x95637e46),LL(0xad171465,0x2df8b206),LL(0x4bccedce,0xa31ea895)}}, {{LL(0x50743bb6,0x28dbcb77),LL(0xf9cf84b9,0x13d12f8e),LL(0xc8f7d408,0x39e3d3af),LL(0xeba591d4,0x5824117f)}, {LL(0x1bead2d6,0xd8ef7c9a),LL(0xcaf53dd7,0x9003a559),LL(0x174cb9a9,0x33b2365c),LL(0xadb33afb,0x1149d080)}}, {{LL(0xaea9bd3c,0x55231d00),LL(0xfdf3f015,0x07e107c9),LL(0xec9d8fce,0xf535947d),LL(0xbba349a7,0x8b64ed8a)}, {LL(0x049301df,0xdd5881fd),LL(0xe6490fd0,0xefac9c43),LL(0x73740a78,0xd9902852),LL(0x942c326c,0x6eef3724)}}, {{LL(0x5cfb3c8c,0x5671a6e9),LL(0x0ea29721,0x040aabd2),LL(0xeac8da18,0x24e92ca6),LL(0xa31170c3,0xc34d3d79)}, {LL(0xb061e416,0xf81dd15f),LL(0x85f80af0,0xff7be70e),LL(0xade45cd4,0xa9faba4b),LL(0x505fddd4,0x42a6ab05)}}, {{LL(0x0a793534,0x17d5821d),LL(0xce0ade43,0x9e094e54),LL(0xc42cb4d2,0xa127fb6d),LL(0xdb12dc99,0x43865428)}, {LL(0x59e3bfc1,0xb6b1b347),LL(0x1ec5b810,0x0b0076a9),LL(0xa6864982,0xbf2dd17a),LL(0x9d523c87,0x0c45947f)}}, {{LL(0x4c5dd59e,0x9f53372f),LL(0xca5ce09f,0x3d0ceaea),LL(0x7c0337fb,0xf3ff88e8),LL(0xfaa022c7,0xb4fa4593)}, {LL(0xd65ea54d,0x575240a7),LL(0xadb92fb0,0xa4ec0a39),LL(0x79429eb1,0xc20e737c),LL(0x69addec4,0xcea931d1)}}, {{LL(0x3e09f46a,0x7a29011f),LL(0x0e578a5b,0x9c36865e),LL(0x71d805f4,0x8746ea51),LL(0xe12d3024,0xf024de85)}, {LL(0x15a7f6be,0xc397b46c),LL(0x1b0580d7,0x612db6fb),LL(0xf736d087,0xe5342f76),LL(0x8c1e844c,0x65276853)}}, {{LL(0x113841a5,0xedf48adc),LL(0xe5c482f0,0xc21b67e1),LL(0x684a540b,0xe43b0138),LL(0xa5d4b266,0xc4f2782b)}, {LL(0x397f3664,0x184e240c),LL(0x0d8788f8,0x968e89e7),LL(0x377e18bf,0xec3eba1a),LL(0x36002652,0x4d03cbbc)}}, {{LL(0x1005a953,0x21eedee7),LL(0x75ba987e,0xc178ddf1),LL(0xc4ba43f6,0xd0d577f6),LL(0x4d6f24fd,0x9486f46c)}, {LL(0xc5421895,0x3d33c574),LL(0x842e52ab,0x5be6cb4c),LL(0x9debc9ff,0x3809690d),LL(0xa84a5b6f,0xe4b1c692)}}, {{LL(0xd7e18b57,0x58b966ad),LL(0x77c94715,0x7ff0b61e),LL(0xf06add82,0x0e295883),LL(0x65c7f5a4,0x7c3c04fd)}, {LL(0x60223be5,0x4ea92660),LL(0x89262bfd,0x5d843a57),LL(0x36da11c0,0x35bf4aef),LL(0xaf859eb1,0xa6692f14)}}, {{LL(0xa12fdf41,0xca1fc13b),LL(0x8224f5d2,0xd798c04b),LL(0x1dd5872b,0x22f4594e),LL(0x1bddfda8,0xdee12df5)}, {LL(0xed83420a,0x96473ff0),LL(0x8daa27f4,0xf41cf1c7),LL(0xaecefd8a,0x2772cd56),LL(0x4902b47f,0xd5ddaf18)}}, {{LL(0xc0798101,0xff77551f),LL(0x26946bda,0x8baa01d6),LL(0x100525f2,0xd0087e47),LL(0x4c0de308,0x521d6254)}, {LL(0x9bbce049,0x4a0f45eb),LL(0xa6c6b96e,0x5ee33cbe),LL(0xd6a22345,0x9a6af4b7),LL(0x38b1b406,0x0d0d35e7)}}, {{LL(0xbbedc29b,0x9e71252d),LL(0xcad1455e,0x3aa70bb6),LL(0x42a1778c,0xa406fb7a),LL(0xf0897613,0xd94f9646)}, {LL(0xf57f66c8,0x5256370f),LL(0x4432f679,0x95891e35),LL(0xbcb6b3d3,0x75d6423a),LL(0x2367483f,0x79d9ea01)}}, {{LL(0x9efb0473,0x1e36ccc6),LL(0xdfdc0cec,0x3e64b034),LL(0x028bb238,0x13bfd326),LL(0x209edd95,0x171e9d96)}, {LL(0x07b22424,0xda258380),LL(0xd41b8023,0xe31e97f6),LL(0x7269cecd,0xdd4ed390),LL(0x12d5cec6,0x810fb3c8)}}, {{LL(0xbabeec88,0x2f956519),LL(0x455baf52,0xb0350c52),LL(0x48d5abf1,0xa7fb548a),LL(0xca5e2d9f,0xcb81bd0c)}, {LL(0xa6d17b19,0xda5ecd39),LL(0x508e5149,0xd2588bab),LL(0xc3e23cfd,0x1a30cff5),LL(0xf89f8712,0x2dd398b4)}}, {{LL(0x5b304005,0x2a911800),LL(0xd9dece69,0xd091be7a),LL(0xf6cabc89,0x147e93da),LL(0x44935824,0x7eac2018)}, {LL(0x32f5de9b,0xd4aaf2be),LL(0xd9396cd1,0xe302bc41),LL(0x2c069d1a,0x3c2794cf),LL(0xa9d433ae,0xf9197eaa)}}, {{LL(0x4445e8c2,0x98f822ef),LL(0x1383ece8,0xc578360e),LL(0x01869457,0xa5372c12),LL(0x787d6644,0x1c6ed00d)}, {LL(0x86531814,0x77fb08cd),LL(0x63a70db8,0xeff6ee26),LL(0x80976119,0x980be153),LL(0xd69d60c5,0x534a09bd)}}, {{LL(0x759dba20,0x71a58b0c),LL(0x679c0b40,0x34d5f06c),LL(0xceed2f9f,0xdc0e7e5f),LL(0x48808edb,0xaaa5996e)}, {LL(0xbcdd88e5,0x8ca96ff0),LL(0xc37c2b46,0x91b02d67),LL(0x95526319,0xbe4f3948),LL(0x89be56d1,0x4315c7f2)}}, {{LL(0xdc85bba1,0xa312a3c0),LL(0x431ca797,0x3328fa8e),LL(0x68fd219a,0x5438bf1c),LL(0x85837d74,0x98812c6f)}, {LL(0xf8c96d49,0xe88c4913),LL(0xc2442aca,0xcc62e79c),LL(0x046655f1,0x4ef3c7d4),LL(0xdadab1ea,0x04a362ed)}}, {{LL(0x30a199cf,0x975e2f3c),LL(0x014a165a,0x831e04a9),LL(0xaa126719,0x1e1d3c53),LL(0x1bf707a0,0xc42661e0)}, {LL(0xaa2da264,0x295b0738),LL(0x65d4ba34,0xb45f5ed8),LL(0x9f3938fa,0x27fb5a12),LL(0xcb26f86c,0x25fba614)}}, {{LL(0xcf3c1c4d,0x6bd41981),LL(0xa0dedafd,0xd6f9239c),LL(0xae55b97f,0x46882526),LL(0x81b628d4,0x8e6fa994)}, {LL(0xdc0aa158,0xbdb314dd),LL(0x12ba2a17,0x35343678),LL(0x32e2e431,0xac018e83),LL(0xe65cc63e,0x43a64e35)}}, {{LL(0x0b6603ea,0x887f3a2a),LL(0x76b2673f,0xe015426c),LL(0x27edfe8a,0x59dc5530),LL(0x68d9ebf3,0xea9eacf3)}, {LL(0xcc3e07ca,0x40301c8e),LL(0x0f57a2e6,0xd8cb9b5b),LL(0x60ec5864,0x542e6b52),LL(0x17f6affe,0xb8791dd6)}}, {{LL(0x798d9993,0x6735bd1c),LL(0xd5da393c,0x006d8b25),LL(0x49e6d0d2,0x1d675bdb),LL(0x8607f99e,0x331d9a10)}, {LL(0x9dc4cd07,0x4ff8ab74),LL(0x64ea3192,0xa87d4ae1),LL(0x41196b5b,0xdde0d92e),LL(0xb2e010eb,0xa15ad47b)}}, {{LL(0xa5522a75,0x23e6003f),LL(0x84afa749,0xc6ef3f1b),LL(0x146d10a3,0x9a723f75),LL(0x119106b0,0x5fa99480)}, {LL(0xc0013dba,0x01d500db),LL(0x548edbe0,0x10b30ada),LL(0xb04ffc6b,0xb2eb046e),LL(0x64f25ee2,0xa57088f3)}}, {{LL(0x83a068a3,0xc0c919c3),LL(0xfbde282f,0x8139559d),LL(0x9fec9a99,0x4e2b5d13),LL(0xfbefa7e6,0x53bad712)}, {LL(0x2860bd4f,0xa6befe0d),LL(0x0011bd15,0x6ea0ae15),LL(0x2bce3779,0xc1ef3463),LL(0x5d742dbb,0xc09ecb30)}}, {{LL(0xf73db19d,0x29526afd),LL(0x6a029a40,0x7c02c905),LL(0xde5a48ba,0xa778460f),LL(0x77c105f6,0xda05993e)}, {LL(0xc9ddece9,0xb6d599f9),LL(0x0cfc33ca,0x9f9df668),LL(0xa0aa67a8,0xdcd8ef4f),LL(0xc3f4d178,0x31277019)}}, {{LL(0x53e86ae1,0x98e05abf),LL(0x3850830d,0xc1dc4d90),LL(0xe06bc33c,0xbd7fd806),LL(0xacf1286f,0x1ac330d6)}, {LL(0xe1588c1e,0x28ce2303),LL(0x1b7e9c19,0xdc25e54b),LL(0x4b7149f2,0x11e51e49),LL(0xb5c7fa25,0x551b8391)}}, {{LL(0x1bf69873,0xa2fc251c),LL(0x2aec1574,0x099b7b53),LL(0x7c53296a,0x9ff98156),LL(0xa2dc60de,0xaf3f8d08)}, {LL(0x59b72d6c,0x18dd295c),LL(0xe75f44fc,0x165c9063),LL(0x427a0c55,0x9046ee7c),LL(0xc79ffdb3,0x317ea24d)}}, {{LL(0x0ef0447d,0x6835a315),LL(0x8068e7c7,0xb2b9c786),LL(0x0e646af5,0xe6352714),LL(0x442baaa0,0xc5554a91)}, {LL(0x6d0ba1ea,0x671febc5),LL(0x0cf649ed,0x44f9ef7b),LL(0x0c1dac6b,0x4aa0cd61),LL(0x6e393e68,0x865f3c23)}}, {{LL(0xa71dee29,0xf6886bcd),LL(0xda44ffae,0x934b0455),LL(0x016d6039,0xda7621c4),LL(0x3ad35493,0xf36c41bf)}, {LL(0xe5f6ab8d,0x9063135e),LL(0x47bdc0a8,0xb0e8eaba),LL(0x4c737cf3,0x62530616),LL(0x64f6b6cb,0x8046423e)}}, {{LL(0x7958e3dc,0x11e50ad7),LL(0xb57234ab,0x4dab4e16),LL(0xe0916210,0x6ccfe2c6),LL(0x80f49d40,0x4d5dbc3b)}, {LL(0xef1b2b1b,0x2b8ff368),LL(0x752fea2a,0xf2afb326),LL(0x0246e36b,0xffa48ea7),LL(0x589b7444,0x3a4bae9b)}}, {{LL(0x6ff3efcf,0x80ff984a),LL(0x56b77b47,0x7af53f30),LL(0x9320cae6,0x1f1c33b0),LL(0x26fc4ad4,0xce1f1c48)}, {LL(0xad350ee5,0x9cac662b),LL(0xe27a7dbd,0xf4c72fff),LL(0x703184e5,0xd766f986),LL(0x7c5b241e,0x36d3efd5)}}, {{LL(0xf7ff5804,0xd4d6e358),LL(0x8f5e0bf6,0xa832b302),LL(0x453d9a22,0x4b3d73f7),LL(0xdf938705,0xb4dae072)}, {LL(0x92401620,0x6bff7b2e),LL(0x9bfa61cd,0x96b8494e),LL(0xb74dc1e5,0x4bcda341),LL(0xc19c393d,0x383fe3d2)}}, {{LL(0x077e8821,0xa375fb70),LL(0xc17eb9bc,0xea35e04b),LL(0x7c4dd076,0x941d21ba),LL(0x3d0c3d8a,0x916c0a59)}, {LL(0x15b2cf47,0x2c1304e3),LL(0xd0c955c0,0x9233ebf3),LL(0x2b2fc935,0x77acdd07),LL(0xc04276bf,0xd71b6a7a)}}, {{LL(0xd2ee8d68,0x789ea49b),LL(0x0a84a920,0x89552b46),LL(0x1a4ea456,0xe629d5de),LL(0x22ddd405,0xddfefe87)}, {LL(0x1cdb9e7b,0x3d56f697),LL(0xa8bf715b,0x95a861b0),LL(0x7896c993,0xb01248d6),LL(0x01a3085c,0x3c4e3d98)}}, {{LL(0x9085b360,0x674939e1),LL(0xb589a287,0xae67dea9),LL(0x2bfdcfc9,0xc563856f),LL(0x313b685d,0x62fa9a80)}, {LL(0x7ad501d9,0x36ff33d9),LL(0x730ab349,0xf8bab4dd),LL(0xc46ba69d,0x18fd59f3),LL(0xe65278e9,0x81e08665)}}, {{LL(0xeb8a1e84,0x5a5e803f),LL(0x47243604,0x5b4eef35),LL(0x393d6cdf,0x0ee71ee0),LL(0xc3a9c6db,0xde4d9dea)}, {LL(0x64466b53,0x0c14c376),LL(0x89e3b45e,0xc2ce9642),LL(0x54a2de21,0x6aa8012f),LL(0x29b6bc2c,0x519759c1)}}, {{LL(0xe4667322,0x17768527),LL(0xac83b2ea,0x09fdfe4d),LL(0x04a0d5f5,0xd422125d),LL(0x2b86b310,0x02e8ff96)}, {LL(0xd7ee97af,0xf033628d),LL(0x7d72e0e6,0x778a846c),LL(0x882f63d6,0x06fde613),LL(0x8d434f14,0x9e258b0d)}}, {{LL(0xccdcd600,0x5cdda529),LL(0x033c4535,0x37038b38),LL(0x391c1d7d,0xd6a1d639),LL(0x31d4ce6b,0x4f6489e4)}, {LL(0x5754e08c,0xd1b82f17),LL(0x75db7bd6,0x7df268ee),LL(0xad14dcfa,0x1e4a1202),LL(0xccfb9b77,0x7ab92ce2)}}, {{LL(0x23aef997,0x61388e03),LL(0x06440ce3,0x9981f5bf),LL(0xc67d0edd,0x8d7631da),LL(0xc0a93516,0xc6ea593f)}, {LL(0xee841b38,0x064a06e0),LL(0x521ce83f,0x0d1d4f57),LL(0x70df2613,0xf7a0e0c3),LL(0x84c071ab,0x1506cccb)}}, {{LL(0x328565e9,0x42a138ec),LL(0xb8130d16,0xe16b4578),LL(0x45ba251a,0x0628ff22),LL(0x210e22e8,0x016a84ca)}, {LL(0x94592d43,0x8ba14bb4),LL(0x785274a5,0xffee4308),LL(0x01354b75,0x01fc21ab),LL(0x7e424674,0xc37ce45f)}}, {{LL(0xa7fe2735,0x71e153af),LL(0xc307721f,0x000fcee9),LL(0x805b56e3,0x3b189004),LL(0x7f504d9b,0x2f1435aa)}, {LL(0xa083bd72,0xd9aa1eba),LL(0x720ccf3d,0xf1145036),LL(0x4084fa32,0x95b29e27),LL(0x01f94f0c,0x8862d213)}}, {{LL(0x1510a406,0x23fc5ddf),LL(0xc9f0e98d,0x475a78f4),LL(0xe72843a0,0xb6d681c4),LL(0x4a00c5a6,0xa90af2a4)}, {LL(0xa34f4412,0x95fc6d45),LL(0xe7f5d703,0x60f9c0e2),LL(0xad110925,0x2bc0642b),LL(0xbe24a4d5,0x79abfc10)}}, } }; #endif /* _DISABLE_ECP_SM2_HARDCODED_BP_TBL_ */ #endif /* _IPP_DATA */ IPP_OWN_DEFN (const cpPrecompAP*, gfpec_precom_sm2_fun, (void)) { static cpPrecompAP t = { /* w */ 7, /* select function */ p256r1_select_ap_w7, /* precomputed data */ (BNU_CHUNK_T*)precomputed_ec_sm2 }; return &t; }; cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_decrypt_ext.c000066400000000000000000000160621470420105600263020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_stuff.h" #define CHECK_PRIVATE_KEY(KEY) \ IPP_BAD_PTR1_RET((KEY)) \ IPP_BADARG_RET(!BN_VALID_ID((KEY)), ippStsContextMatchErr) \ IPP_BADARG_RET(BN_NEGATIVE((KEY)), ippStsInvalidPrivateKey) \ /* test if 0 < pPrivateA < Order */ \ IPP_BADARG_RET(0 == gfec_CheckPrivateKey((KEY), pEC), ippStsInvalidPrivateKey) /** * @brief * Decryption message text based SM2 elliptic curve * Implementation based on standard: * GM/T 0003.4-2012 SM2 * Public key cryptographic algorithm SM2 based on elliptic curves * Part 4: Public key encryption algorithm * @param [out] pOut message decryption * @param [in] maxOutLen available message size buffer * @param [out] pOutSize message size fill container * 0 - if the function ends with an error, * other (>0) - if the function ends with OK * @param [in] pInp pointer cipher text * @param [in] inpLen cipher size * @param [in] pPrvKey private key * @param [in] pEC context elliptic curve * @param [in] pScratchBuffer supported buffer * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pOut | pOutSize | pInp | pPrvKey | pEC | pScratchBuffer is NULL * ippStsContextMatchErr - if pEC no valid ID | pEC no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported (n|p) modulus arithmetic * ippStsBadArgErr - if * * maxOutLen < 0 * * inpLen < (len(PC) + 2*len(x) + len(SM3)) * ippStsInvalidPrivateKey - if test is failed 0 < pPrvKey < Order * */ /* clang-format off */ IPPFUN(IppStatus, ippsGFpECDecryptSM2_Ext, (Ipp8u *pOut, int maxOutLen, int *pOutSize, const Ipp8u *pInp, int inpLen, const IppsBigNumState *pPrvKey, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) /* clang-format on */ { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* buffer */ IPP_BAD_PTR1_RET(pScratchBuffer) /* check cipher text */ IPP_BAD_PTR1_RET(pInp) /* size */ const int ciph_PC_size = 1; const int ciph_xy_size = 2 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize; const int ciph_hash_size = IPP_SM3_DIGEST_BYTESIZE; const int min_ciph_size = ciph_PC_size + ciph_xy_size + ciph_hash_size; IPP_BADARG_RET(!(inpLen >= min_ciph_size), ippStsOutOfRangeErr) /* message */ IPP_BAD_PTR1_RET(pOut) /* the cipher text condition guarantees a positive or zero maxOutLen */ const int ciph_msg_size = inpLen - min_ciph_size; IPP_BADARG_RET(!(maxOutLen >= ciph_msg_size), ippStsOutOfRangeErr) /* out message size */ IPP_BAD_PTR1_RET(pOutSize) /* zeros */ *pOutSize = 0; /* private key */ CHECK_PRIVATE_KEY(pPrvKey) { IppStatus sts = ippStsInvalidPoint; // pointer input if invalid -> status out int finitPoint = 0; const Ipp8u *pC1_PC = pInp; const Ipp8u *pC1_xy = pC1_PC + ciph_PC_size; const Ipp8u *pC3 = pC1_xy + ciph_xy_size; const Ipp8u *pC2 = pC3 + ciph_hash_size; IppsGFpECPoint R; cpEcGFpInitPoint(&R, cpEcGFpGetPool(1, pEC), 0, pEC); /* step1: extract C1 from C */ BNU_CHUNK_T *pBuff = cpGFpGetPool(2, pME); BNU_CHUNK_T *pC1_x = pBuff; BNU_CHUNK_T *pC1_y = pC1_x + elemSize; /* copy coordinate point */ COPY_BNU(pC1_x, (BNU_CHUNK_T *)(pC1_xy), elemSize); COPY_BNU(pC1_y, (BNU_CHUNK_T *)(pC1_xy + elemBytes), elemSize); /* convert big endian -> little endian */ cpSM2KE_reverse_inplace((Ipp8u *)pC1_x, elemBytes); cpSM2KE_reverse_inplace((Ipp8u *)pC1_y, elemBytes); /* convert to Montgomery */ GFP_METHOD(pME)->encode(pC1_x, pC1_x, pME); GFP_METHOD(pME)->encode(pC1_y, pC1_y, pME); /* step 2 (standard) - check valid input coordinate x|y */ finitPoint = gfec_SetPoint(ECP_POINT_DATA(&R), pC1_x, pC1_y, pEC); ECP_POINT_FLAGS(&R) = finitPoint ? (ECP_AFFINE_POINT | ECP_FINITE_POINT) : 0; if (finitPoint && (0 != gfec_IsPointOnCurve(&R, pEC))) { sts = ippStsNoErr; /* step 3 (standard): [db]C1 = (x2,y2) */ ippsGFpECMulPoint(&R, pPrvKey, &R, pEC, pScratchBuffer); BNU_CHUNK_T *pX = pBuff; BNU_CHUNK_T *pY = pX + elemSize; gfec_GetPoint(pX, pY, &R, pEC); GFP_METHOD(pME)->decode(pX, pX, pME); GFP_METHOD(pME)->decode(pY, pY, pME); cpSM2KE_reverse_inplace((Ipp8u *)pX, elemBytes); cpSM2KE_reverse_inplace((Ipp8u *)pY, elemBytes); /* step 4 (standard): t = KDF(x2 || y2, klen) */ KDF_sm3(pOut, ciph_msg_size, (Ipp8u *)pBuff, 2 * elemBytes); /* step 5 (standard): M` = C2 (x) t */ for (int i = 0; i < ciph_msg_size; ++i) { pOut[i] = pOut[i] ^ pC2[i]; } /* step 6 (standard): u = Hash(x2 || M` || y2) */ static IppsHashState_rmf ctx; Ipp8u u[IPP_SM3_DIGEST_BYTESIZE]; ippsHashInit_rmf(&ctx, ippsHashMethod_SM3()); /* x2 */ ippsHashUpdate_rmf((Ipp8u *)pX, elemBytes, &ctx); /* M */ ippsHashUpdate_rmf(pOut, ciph_msg_size, &ctx); /* y2 */ ippsHashUpdate_rmf((Ipp8u *)pY, elemBytes, &ctx); /* C3 */ ippsHashFinal_rmf(u, &ctx); if (0 == EquBlock(u, pC3, IPP_SM3_DIGEST_BYTESIZE)) { PurgeBlock(pOut, ciph_msg_size); } else { *pOutSize = ciph_msg_size; } PurgeBlock(u, IPP_SM3_DIGEST_BYTESIZE); } cpGFpReleasePool(2, pME); cpEcGFpReleasePool(1, pEC); /* release R from the pool */ return sts; } } #undef CHECK_PRIVATE_KEY cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_decrypt_ext_dec_msg_size.c000066400000000000000000000050551470420105600310150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief ippsGFpECDecryptSM2_Ext_DecMsgSize * Get Message Size data by Decrypt SM2 * Implementation based on standard: * GM/T 0003.4-2012 SM2 * Public key cryptographic algorithm SM2 based on elliptic curves * Part 4: Public key encryption algorithm * @param [in] pEC Context Elliptic Curve * @param [in] ctMsgSize cipher size * @param [out] pSize size allocation bytes by Key Exchange Context * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC or pSize is NULL * ippStsContextMatchErr - if pEC no valid ID or no exists SUBGROUP * ippStsBagArgErr - if cipher < 0 or ctMsgSize - (C1 + C3) < 0 */ IPPFUN(IppStatus, ippsGFpECDecryptSM2_Ext_DecMsgSize, (const IppsGFpECState *pEC, int ctMsgSize, int *pSize)) { /* check Context Elliptic Curve */ IPP_BAD_PTR2_RET(pEC, pSize); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* check cipher size */ IPP_BADARG_RET(!(ctMsgSize >= 0), ippStsOutOfRangeErr) const int ciph_PC_size = 1; const int ciph_xy_size = 2 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize; const int ciph_hash_size = IPP_SM3_DIGEST_BYTESIZE; const int size = ctMsgSize - (ciph_PC_size + ciph_xy_size + ciph_hash_size); /* if size < 0 -> pSize = 0 + call ippStsBadArgErr */ *pSize = 0; IPP_BADARG_RET(!(size >= 0), ippStsOutOfRangeErr) *pSize = size; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_encrypt_ext.c000066400000000000000000000175061470420105600263200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_stuff.h" #define CHECK_PUBLIC_KEY(KEY) \ IPP_BAD_PTR1_RET((KEY)) \ IPP_BADARG_RET(!ECP_POINT_VALID_ID((KEY)), ippStsContextMatchErr) \ IPP_BADARG_RET(ECP_POINT_FELEN((KEY)) != GFP_FELEN(pME), ippStsOutOfRangeErr) \ IPP_BADARG_RET(0 == gfec_IsPointOnCurve((KEY), pEC), ippStsInvalidPoint) #define CHECK_PRIVATE_KEY(KEY) \ IPP_BAD_PTR1_RET((KEY)) \ IPP_BADARG_RET(!BN_VALID_ID((KEY)), ippStsContextMatchErr) \ IPP_BADARG_RET(BN_NEGATIVE((KEY)), ippStsInvalidPrivateKey) \ /* test if 0 < pPrivateA < Order */ \ IPP_BADARG_RET(0 == gfec_CheckPrivateKey((KEY), pEC), ippStsInvalidPrivateKey) /** * @brief * Encryption message text based SM2 elliptic curve * Implementation based on standard: * GM/T 0003.4-2012 SM2 * Public key cryptographic algorithm SM2 based on elliptic curves * Part 4: Public key encryption algorithm * @param [out] pOut pointer output cipher text * @param [in] maxOutLen available cipher size container * @param [out] pOutSize size of the ciphertext filled in the container * 0 - if the function ends with an error, * other (>0) - if the function ends with OK * @param [in] pInp pointer message encrypt * @param [in] inpLen message size encrypt * @param [in] pPublicKey public key * @param [in out] pEhpPublicKey (!) will be cleared at the end (!) Ephemeral Public Key * @param [in out] pEphPrvKey (!) will be cleared at the end (!) Ephemeral Private Key * @param [in] pEC context elliptic curve * @param [in] pScratchBuffer supported buffer * @return * ippStsNoErr - successful * ippStsNullPtrErr - if * pEC | pScratchBuffer | pInp | pOut | pOutSize | pPublicKey | pEphPublicKey | pEphPrvKey * is NULL * ippStsContextMatchErr - if pEC no valid ID | pEC no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported (n|p) modulus arithmetic * ippStsBadArgErr - if * * inpLen < 0 * * maxOutLen < (len(PC) + 2*len(x) + len(SM3)) * ippStsInvalidPrivateKey - if test is failed 0 < pEphPrvKey < Order * ippStsInvalidPoint - if no in curve Pub Key and Ephemeral Public Key */ /* clang-format off */ IPPFUN(IppStatus, ippsGFpECEncryptSM2_Ext, (Ipp8u *pOut, int maxOutLen, int *pOutSize, const Ipp8u *pInp, int inpLen, const IppsGFpECPoint *pPublicKey, IppsGFpECPoint *pEphPublicKey, IppsBigNumState *pEphPrvKey, IppsGFpECState *pEC, Ipp8u *pScratchBuffer)) /* clang-format on */ { IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* buffer */ IPP_BAD_PTR1_RET(pScratchBuffer) /* check msg size */ IPP_BAD_PTR1_RET(pInp) /* check size */ IPP_BADARG_RET(!(inpLen >= 0), ippStsOutOfRangeErr) /* cipher text */ IPP_BAD_PTR2_RET(pOut, pOutSize) /* init zeros out cipher text */ *pOutSize = 0; /* check size */ const int ciph_PC_size = 1; const int ciph_xy_size = (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize * 2; const int ciph_hash_size = IPP_SM3_DIGEST_BYTESIZE; const int ciph_msg_size = inpLen; IPP_BADARG_RET(!(maxOutLen >= (ciph_PC_size + ciph_xy_size + ciph_msg_size + ciph_hash_size)), ippStsOutOfRangeErr) /* check Public | Private key */ /* private */ CHECK_PRIVATE_KEY(pEphPrvKey) /* public */ /* step 3: S = [h]Pb -> if Pb valid point and h != 0 -> S valid */ CHECK_PUBLIC_KEY(pPublicKey) CHECK_PUBLIC_KEY(pEphPublicKey) /* check that user's Ephemeral Public and Private Keys are related (C1=[k]G) */ IppsGFpECPoint pTmpPoint; cpEcGFpInitPoint(&pTmpPoint, cpEcGFpGetPool(1, pEC), 0, pEC); ippsGFpECPublicKey(pEphPrvKey, &pTmpPoint, pEC, pScratchBuffer); // k*G int result = gfec_ComparePoint(&pTmpPoint, pEphPublicKey, pEC); // C1 == [k]G ? cpEcGFpReleasePool(1, pEC); // Release pool before the possible exit IPP_BADARG_RET(!result, ippStsEphemeralKeyErr); { IppStatus sts = ippStsNoErr; /* init pointer C = C1 || C2 || C3 */ Ipp8u *pC1_PC = pOut; Ipp8u *pC1_xy = pC1_PC + ciph_PC_size; Ipp8u *pC3 = pC1_xy + ciph_xy_size; Ipp8u *pC2 = pC3 + ciph_hash_size; /* point elliptic curve */ IppsGFpECPoint R; cpEcGFpInitPoint(&R, cpEcGFpGetPool(1, pEC), 0, pEC); BNU_CHUNK_T *pX = NULL; BNU_CHUNK_T *pY = NULL; /* step 2: C1 = PC || x1 || y1 */ pC1_PC[0] = 0x04; pX = (BNU_CHUNK_T *)(pC1_xy); pY = pX + elemSize; gfec_GetPoint(pX, pY, pEphPublicKey, pEC); GFP_METHOD(pME)->decode(pX, pX, pME); GFP_METHOD(pME)->decode(pY, pY, pME); cpSM2KE_reverse_inplace((Ipp8u *)pX, elemBytes); cpSM2KE_reverse_inplace((Ipp8u *)pY, elemBytes); /* step 4: [k]Pb = (x2,y2) */ ippsGFpECMulPoint(pPublicKey, pEphPrvKey, &R, pEC, pScratchBuffer); /* step 5: t = KDF(x2||y2, klen) */ BNU_CHUNK_T *pBuff = cpGFpGetPool(2, pME); pX = pBuff; pY = pX + elemSize; gfec_GetPoint(pX, pY, &R, pEC); GFP_METHOD(pME)->decode(pX, pX, pME); GFP_METHOD(pME)->decode(pY, pY, pME); cpSM2KE_reverse_inplace((Ipp8u *)pX, elemBytes); cpSM2KE_reverse_inplace((Ipp8u *)pY, elemBytes); KDF_sm3(pC2, ciph_msg_size, (Ipp8u *)pBuff, 2 * elemBytes); /* step 6: C2 = M (x) t */ for (int i = 0; i < ciph_msg_size; ++i) { pC2[i] = pC2[i] ^ pInp[i]; } /* step 7: C3 = Hash(x2 || M || y2) */ static IppsHashState_rmf ctx; ippsHashInit_rmf(&ctx, ippsHashMethod_SM3()); /* x2 */ ippsHashUpdate_rmf((Ipp8u *)pX, elemBytes, &ctx); /* M */ ippsHashUpdate_rmf(pInp, ciph_msg_size, &ctx); /* y2 */ ippsHashUpdate_rmf((Ipp8u *)pY, elemBytes, &ctx); /* C3 */ ippsHashFinal_rmf(pC3, &ctx); /* set output size data */ if (sts == ippStsNoErr) { *pOutSize = ciph_PC_size + ciph_xy_size + ciph_msg_size + ciph_hash_size; } /* zeros Public | Private Key */ cpBN_zero(pEphPrvKey); gfec_SetPointAtInfinity(pEphPublicKey); cpGFpReleasePool(2, pME); cpEcGFpReleasePool(1, pEC); /* release R from the pool */ return sts; } } #undef CHECK_PRIVATE_KEY #undef CHECK_PUBLIC_KEY cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_encrypt_ext_enc_msg_size.c000066400000000000000000000051641470420105600310420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief ippsGFpECEncryptSM2_Ext_EncMsgSize * Implementation based on standard: * GM/T 0003.4-2012 SM2 * Public key cryptographic algorithm SM2 based on elliptic curves * Part 4: Public key encryption algorithm * Get Cipher Size data by Encrypt SM2 * @param [in] pEC Context Elliptic Curve * @param [in] ctMsgSize chipher text message size * @param [out] pSize size allocation bytes by Key Exchange Context * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC or pSize is NULL * ippStsContextMatchErr - if pEC no valid ID or no exists SUBGROUP * ippStsBagArgErr - if message size < 0 */ IPPFUN(IppStatus, ippsGFpECEncryptSM2_Ext_EncMsgSize, (const IppsGFpECState *pEC, int ctMsgSize, int *pSize)) { /* check Context Elliptic Curve */ IPP_BAD_PTR2_RET(pEC, pSize); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* check message size */ IPP_BADARG_RET(!(ctMsgSize >= 0), ippStsOutOfRangeErr) { const int ciph_PC_size = 1; const int ciph_xy_size = 2 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize; const int ciph_hash_size = IPP_SM3_DIGEST_BYTESIZE; const int ciph_msg_size = ctMsgSize; const int size = ciph_PC_size /* PC */ + ciph_xy_size /* Point (x,y) */ + ciph_hash_size /* SM3 */ + ciph_msg_size; /* message size */ *pSize = size; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_key_exchange_confirmation.c000066400000000000000000000114051470420105600311460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_key_exchange_method.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief ippsGFpECKeyExchangeSM2_Confirm * this step Optional in protocol SM2 Key Exchange - Confirmation Peer data * see standard: * [GBT.32918.3-2016] Public Key cryptographic algorithm SM2 based on elliptic curves * Part 3: Key exchange protocol * 6.2 Process of key exchange protocol * stack compute[standard link]: * [user A| user B] * 8) S(1/2) = SM3( 0x0(2/3) || y(u/v) || tmp_p ) [step 9| step 10] * when tmp_p - precomute in SharedKey step * @param [in] pSPeer S(b/a) peer data confirmation * @param [out] pStatus status confirmation * 1 is successful or 0 is bad confirmation * @param [in] pKE constrex Key Exchange * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC | pKE | pSPeer | pStatus is NULL * ippStsContextMatchErr - if pEC no valid ID | pEC no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported (n|p) modulus arithmetic * ippStsRangeErr - if BitSize(pEC) < IPP_SM3_DIGEST_BITSIZE * ippStsBadArgErr - if role(pKE) no equal ippKESM2Requester|ippKESM2Responder */ /* clang-format off */ IPPFUN(IppStatus, ippsGFpECKeyExchangeSM2_Confirm, (const Ipp8u pSPeer[IPP_SM3_DIGEST_BYTESIZE], int* pStatus, IppsGFpECKeyExchangeSM2State* pKE)) /* clang-format on */ { /* check Key Exchange */ IPP_BAD_PTR1_RET(pKE); /* check id */ IPP_BADARG_RET(!EC_SM2_KEY_EXCH_VALID_ID(pKE), ippStsContextMatchErr); /* check User Role */ const IppsKeyExchangeRoleSM2 role = EC_SM2_KEY_EXCH_ROLE(pKE); IPP_BADARG_RET(((ippKESM2Requester != role) && (ippKESM2Responder != role)), ippStsBadArgErr); /* check Elliptic Curve */ IppsGFpECState *pEC = EC_SM2_KEY_EXCH_EC(pKE); IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); /* check bitsize >= SM3_DIGSET */ IPP_BADARG_RET(!(ECP_ORDBITSIZE(pEC) >= IPP_SM3_DIGEST_BITSIZE), ippStsRangeErr); /* check call Setup */ /* check init Public Key | Ephemeral Public Key */ IPP_BADARG_RET( NULL == EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE) || NULL == EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE) || NULL == EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE) || NULL == EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE), ippStsContextMatchErr) /* check pSPeer */ IPP_BAD_PTR1_RET(pSPeer); /* check status */ IPP_BAD_PTR1_RET(pStatus); const Ipp8u firstNum = (ippKESM2Requester == role) ? 0x02 : 0x03; { /* extract data Elliptic Curve */ const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ /* buffer */ BNU_CHUNK_T *pDataBuff = cpGFpGetPool(3, pME); Ipp8u *pBuff = (Ipp8u *)pDataBuff; /* 8) S(1/2) = SM3( 0x0(2/3) || y(u/v) || tmp_p ) */ /* copy 0x0(2/3) */ pBuff[0] = firstNum; /* set first number (role) */ /* copy y(u/v) */ cpSM2_CopyBlock(pBuff + 1, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_Y(pKE), elemBytes); /* copy Precomp Hash */ cpSM2_CopyBlock(pBuff + 1 + elemBytes, (const Ipp8u *)EC_SM2_KEY_EXCH_PRECOM_HASH(pKE), IPP_SM3_DIGEST_BYTESIZE); const int sizeSab_SM3 = 1 + elemBytes + IPP_SM3_DIGEST_BYTESIZE; cpSM2KE_compute_hash_SM3(pBuff, pBuff, sizeSab_SM3); /* pS == S(1/2) */ *pStatus = EquBlock((Ipp8u *)pBuff, pSPeer, IPP_SM3_DIGEST_BYTESIZE) ? 1 : 0; cpGFpReleasePool(3, pME); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_key_exchange_get_size.c000066400000000000000000000056371470420105600303010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_key_exchange_method.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief ippsGFpECKeyExchangeSM2_GetSize * Get Size allocation bytes by Key Exchange Conntext * @param [in] pEC Context Elliptic Curve * @param [out] pSize size allocation bytes by Key Exchange Context * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC or pSize is NULL * ippStsContextMatchErr - if pEC no valid ID or no exists SUBGROUP */ IPPFUN(IppStatus, ippsGFpECKeyExchangeSM2_GetSize, (const IppsGFpECState *pEC, int *pSize)) { IPP_BAD_PTR2_RET(pEC, pSize); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ const int size = (Ipp32s)sizeof(IppsGFpECKeyExchangeSM2State) /* Key Exchange SM2 struct */ + (Ipp32s)sizeof(IppsGFpECPoint) + 3 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize /* User A Public Key + Data */ + (Ipp32s)sizeof(IppsGFpECPoint) + 3 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize /* User B Public Key + Data */ + (Ipp32s)sizeof(IppsGFpECPoint) + 3 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize /* User A Ephemeral Public Key + Data */ + (Ipp32s)sizeof(IppsGFpECPoint) + 3 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize /* User B Ephemeral Public Key + Data */ + (Ipp32s)sizeof(Ipp8u) * IPP_SM3_DIGEST_BYTESIZE /* Za [User A] */ + (Ipp32s)sizeof(Ipp8u) * IPP_SM3_DIGEST_BYTESIZE /* Zb [User B] */ + (Ipp32s)sizeof(Ipp8u) * IPP_SM3_DIGEST_BYTESIZE /* Precompute Hash */ + (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize /* [U/V].x */ + (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize; /* [U/V].y */ *pSize = size; return ippStsNoErr; } }cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_key_exchange_init.c000066400000000000000000000100301470420105600274120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_key_exchange_method.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief ippsGFpECKeyExchangeSM2_Init * initial Key Exchange Context * see standard: * [GBT.32918.3-2016] Public Key cryptographic algorithm SM2 based on elliptic curves * Part 3: Key exchange protocol * @param [out] pKE context Key Exchange * @param [in] role User(A|B) role (ippKESM2Requester|ippKESM2Responder) * @param [in] pEC context Elliptic Curve * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC | pKE is NULL * ippStsContextMatchErr - if pEC no valid ID or no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported n or p modulus arithmetic * ippStsRangeErr - if BitSize(pEC) < IPP_SM3_DIGEST_BITSIZE * ippStsBadArgErr - if role no equal ippKESM2Requester|ippKESM2Responder */ IPPFUN(IppStatus, ippsGFpECKeyExchangeSM2_Init, (IppsGFpECKeyExchangeSM2State * pKE, IppsKeyExchangeRoleSM2 role, IppsGFpECState *pEC)) { /* check Elliptic Curve */ IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); /* check support Mode arithmetic */ gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); /* check bitsize >= SM3_DIGSET */ IPP_BADARG_RET(!(ECP_ORDBITSIZE(pEC) >= IPP_SM3_DIGEST_BITSIZE), ippStsRangeErr); /* check Key Exchange */ IPP_BAD_PTR1_RET(pKE); /* check User Role */ IPP_BADARG_RET(((ippKESM2Requester != role) && (ippKESM2Responder != role)), ippStsBadArgErr); { const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* set id */ EC_SM2_KEY_EXCH_SET_ID(pKE); /* set role [User A| User B] */ EC_SM2_KEY_EXCH_ROLE(pKE) = role; /* set context EC */ EC_SM2_KEY_EXCH_EC(pKE) = pEC; /* set zero pointer to public key */ /* public key */ EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE) = NULL; EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE) = NULL; /* ephemera key */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE) = NULL; EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE) = NULL; Ipp8u *ptr = (Ipp8u *)(pKE); ptr += (Ipp32s)sizeof(IppsGFpECKeyExchangeSM2State); /* skip Public Key Space */ ptr += 4 * ((Ipp32s)sizeof(IppsGFpECPoint) + 3 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize); /* set Za (user id hash) */ EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE) = ptr; PurgeBlock(ptr, IPP_SM3_DIGEST_BYTESIZE); ptr += IPP_SM3_DIGEST_BYTESIZE; /* set Zb (user id hash) */ EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE) = ptr; PurgeBlock(ptr, IPP_SM3_DIGEST_BYTESIZE); ptr += IPP_SM3_DIGEST_BYTESIZE; /* set Precompute Hash */ EC_SM2_KEY_EXCH_PRECOM_HASH(pKE) = ptr; PurgeBlock(ptr, IPP_SM3_DIGEST_BYTESIZE); ptr += IPP_SM3_DIGEST_BYTESIZE; /* set Point(X,Y) */ EC_SM2_KEY_EXCH_POINT_PTR(pKE) = (BNU_CHUNK_T *)ptr; ZEXPAND_BNU(EC_SM2_KEY_EXCH_POINT_X(pKE), 0, elemSize); ZEXPAND_BNU(EC_SM2_KEY_EXCH_POINT_Y(pKE), 0, elemSize); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_key_exchange_method.h000066400000000000000000000060661470420105600277520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 _SM2_KEY_EXCHANGE_METHOD_H_ #define _SM2_KEY_EXCHANGE_METHOD_H_ #include "owncp.h" #include "pcpbnuimpl.h" #include "gfpec/pcpgfpecstuff.h" /* // EC over GF(p) Key Exchange SM2 context */ typedef struct _GFpECKeyExchangeSM2 { Ipp32u idCtx; /* context identifier */ IppsKeyExchangeRoleSM2 role; /* role User A(request) or B(response) */ IppsGFpECState *pEC; /* Elliptic Curve data context */ IppsGFpECPoint *pPubKeyReqA; /* Pa[User A] - Public Key */ IppsGFpECPoint *pPubKeyRespB; /* Pb[User B] - Public Key */ IppsGFpECPoint *pEphPubKeyReqA; /* Ra[User A] - Ephemeral Public Key */ IppsGFpECPoint *pEphPubKeyRespB; /* Rb[User B] - Ephemeral Public Key */ Ipp8u *pZReqA; /* Za[User A] - User ID Hash */ Ipp8u *pZRespB; /* Zb[User B] - User ID Hash */ Ipp8u *pPrecHash; /* Precompute Hash - SM3( x(u/v) || Za || Zb || xa || ya || xb || yb ) */ BNU_CHUNK_T *pPointXYBigEndian; /* U/V */ } GFpECKeyExchangeSM2; /* // Context Access Macros */ /* clang-format off */ #define EC_SM2_KEY_EXCH_ID(ctx) ((ctx)->idCtx) #define EC_SM2_KEY_EXCH_SET_ID(ctx) (EC_SM2_KEY_EXCH_ID(ctx) = (Ipp32u)idCtxGFPECKE ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define EC_SM2_KEY_EXCH_VALID_ID(ctx) ((EC_SM2_KEY_EXCH_ID(ctx) ^ (Ipp32u)IPP_UINT_PTR(ctx)) == (Ipp32u)idCtxGFPECKE) #define EC_SM2_KEY_EXCH_ROLE(ctx) ((ctx)->role) #define EC_SM2_KEY_EXCH_EC(ctx) ((ctx)->pEC) #define EC_SM2_KEY_EXCH_PUB_KEY_USER_A(ctx) ((ctx)->pPubKeyReqA) #define EC_SM2_KEY_EXCH_PUB_KEY_USER_B(ctx) ((ctx)->pPubKeyRespB) #define EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(ctx) ((ctx)->pEphPubKeyReqA) #define EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(ctx) ((ctx)->pEphPubKeyRespB) #define EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(ctx) ((ctx)->pZReqA) #define EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(ctx) ((ctx)->pZRespB) #define EC_SM2_KEY_EXCH_PRECOM_HASH(ctx) ((ctx)->pPrecHash) #define EC_SM2_KEY_EXCH_POINT_PTR(ctx) ((ctx)->pPointXYBigEndian) #define EC_SM2_KEY_EXCH_POINT_X(ctx) ((ctx)->pPointXYBigEndian) #define EC_SM2_KEY_EXCH_POINT_Y(ctx) ((ctx)->pPointXYBigEndian + GFP_FELEN(GFP_PMA(ECP_GFP(EC_SM2_KEY_EXCH_EC(ctx)))) ) /* clang-format on */ #endif // _SM2_KEY_EXCHANGE_METHOD_H_ cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_key_exchange_setup.c000066400000000000000000000155441470420105600276260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/sm2_key_exchange_method.h" #include "gfpec/sm2/sm2_stuff.h" #define CHECK_PUBLIC_KEY(KEY) \ IPP_BAD_PTR1_RET((KEY)) \ IPP_BADARG_RET(!ECP_POINT_VALID_ID((KEY)), ippStsContextMatchErr) \ IPP_BADARG_RET(ECP_POINT_FELEN((KEY)) != GFP_FELEN(pME), ippStsOutOfRangeErr) \ IPP_BADARG_RET(0 == gfec_IsPointOnCurve((KEY), pEC), ippStsInvalidPoint) /** * @brief ippsGFpECKeyExchangeSM2_Setup * setup Key Exchange Context (add Za | Zb | Pa | Pb | Ra | Rb) * see standard: * [GBT.32918.3-2016] Public Key cryptographic algorithm SM2 based on elliptic curves * Part 3: Key exchange protocol * @param [in] pZSelf (self) user ID hash Z (copy) * @param [in] pZPeer (peer) user ID hash Z (copy) * @param [in] pPublicKeySelf (self) public key (copy) * @param [in] pPublicKeyPeer (peer) public key (copy) * @param [in] pEphPublicKeySelf (self) ephemeral public key (copy) * @param [in] pEphPublicKeyPeer (peer) ephemeral public key (copy) * @param [out] pKE context * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC | pKE is NULL * ippStsContextMatchErr - if pEC no valid ID | pEC no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported (n|p) modulus arithmetic * ippStsRangeErr - if BitSize(pEC) < IPP_SM3_DIGEST_BITSIZE * ippStsBadArgErr - if role(pKE) no equal ippKESM2Requester|ippKESM2Responder * ippStsInvalidPoint - if no in curve Pub Key (User A|B) | Eph Pub Key (User A|B) */ /* clang-format off */ IPPFUN(IppStatus, ippsGFpECKeyExchangeSM2_Setup, (const Ipp8u pZSelf[IPP_SM3_DIGEST_BYTESIZE], const Ipp8u pZPeer[IPP_SM3_DIGEST_BYTESIZE], const IppsGFpECPoint *pPublicKeySelf, const IppsGFpECPoint *pPublicKeyPeer, const IppsGFpECPoint *pEphPublicKeySelf, const IppsGFpECPoint *pEphPublicKeyPeer, IppsGFpECKeyExchangeSM2State *pKE)) /* clang-format on */ { /* check Key Exchange */ IPP_BAD_PTR1_RET(pKE); /* check id */ IPP_BADARG_RET(!EC_SM2_KEY_EXCH_VALID_ID(pKE), ippStsContextMatchErr); /* check User Role */ const IppsKeyExchangeRoleSM2 role = EC_SM2_KEY_EXCH_ROLE(pKE); IPP_BADARG_RET(((ippKESM2Requester != role) && (ippKESM2Responder != role)), ippStsBadArgErr); /* check Za | Zb */ IPP_BAD_PTR2_RET(pZSelf, pZPeer); /* check Elliptic Curve */ IppsGFpECState *pEC = EC_SM2_KEY_EXCH_EC(pKE); IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); /* check bitsize >= SM3_DIGSET */ IPP_BADARG_RET(!(ECP_ORDBITSIZE(pEC) >= IPP_SM3_DIGEST_BITSIZE), ippStsRangeErr); /* check data User A */ /* public and ephemeral public key */ CHECK_PUBLIC_KEY(pPublicKeySelf) CHECK_PUBLIC_KEY(pEphPublicKeySelf) /* check data User B */ /* public and ephemeral public key */ CHECK_PUBLIC_KEY(pPublicKeyPeer) CHECK_PUBLIC_KEY(pEphPublicKeyPeer) { const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* init pointer copy User A|B */ Ipp8u *pCopyZSelf = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE) : EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE); Ipp8u *pCopyZPeer = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE) : EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE); /* copy Za and Zb */ cpSM2_CopyBlock(pCopyZSelf, pZSelf, IPP_SM3_DIGEST_BYTESIZE); cpSM2_CopyBlock(pCopyZPeer, pZPeer, IPP_SM3_DIGEST_BYTESIZE); /* init ptr pointer */ /* User A */ const IppsGFpECPoint *loc_pub_key_user_a = (ippKESM2Requester == role) ? pPublicKeySelf : pPublicKeyPeer; const IppsGFpECPoint *loc_eph_pub_key_user_a = (ippKESM2Requester == role) ? pEphPublicKeySelf : pEphPublicKeyPeer; /* User B */ const IppsGFpECPoint *loc_pub_key_user_b = (ippKESM2Requester == role) ? pPublicKeyPeer : pPublicKeySelf; const IppsGFpECPoint *loc_eph_pub_key_user_b = (ippKESM2Requester == role) ? pEphPublicKeyPeer : pEphPublicKeySelf; /* Copy Pointer User A|B */ const Ipp32s size_struct_point = (Ipp32s)sizeof(IppsGFpECPoint); const Ipp32s size_data_point = 3 * (Ipp32s)sizeof(BNU_CHUNK_T) * elemSize; Ipp8u *ptr = (Ipp8u *)(pKE) + sizeof(IppsGFpECKeyExchangeSM2State); /* Public key User A */ EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE) = (IppsGFpECPoint *)ptr; ptr += size_struct_point; cpSM2KE_CopyPointData(EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE), (BNU_CHUNK_T *)ptr, loc_pub_key_user_a, pEC); ptr += size_data_point; /* Ephemeral Public Key User A */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE) = (IppsGFpECPoint *)ptr; ptr += size_struct_point; cpSM2KE_CopyPointData(EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE), (BNU_CHUNK_T *)ptr, loc_eph_pub_key_user_a, pEC); ptr += size_data_point; /* Public key User B */ EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE) = (IppsGFpECPoint *)ptr; ptr += size_struct_point; cpSM2KE_CopyPointData(EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE), (BNU_CHUNK_T *)ptr, loc_pub_key_user_b, pEC); ptr += size_data_point; /* Ephemeral Public Key User B */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE) = (IppsGFpECPoint *)ptr; ptr += size_struct_point; cpSM2KE_CopyPointData(EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE), (BNU_CHUNK_T *)ptr, loc_eph_pub_key_user_b, pEC); return ippStsNoErr; } } #undef CHECK_PUBLIC_KEY cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_key_exchange_shared_key.c000066400000000000000000000352471470420105600306060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owncp.h" #include "owndefs.h" #include "gfpec/sm2/sm2_key_exchange_method.h" #include "gfpec/sm2/sm2_stuff.h" #define CHECK_PRIVATE_KEY(KEY) \ IPP_BAD_PTR1_RET((KEY)) \ IPP_BADARG_RET(!BN_VALID_ID((KEY)), ippStsContextMatchErr) \ IPP_BADARG_RET(BN_NEGATIVE((KEY)), ippStsInvalidPrivateKey) \ /* test if 0 < pPrivateA < Order */ \ IPP_BADARG_RET(0 == gfec_CheckPrivateKey((KEY), pEC), ippStsInvalidPrivateKey) /** * @brief ippsGFpECKeyExchangeSM2_SharedKey * compute x(u/v) | y(u/v) | precomHash | shared key * see standard: * [GBT.32918.3-2016] Public Key cryptographic algorithm SM2 based on elliptic curves * Part 3: Key exchange protocol * 6.2 Process of key exchange protocol * stack compute[standard link]: * [user A| user B] * 2) x(a/b)` = 2^w + (x(a/b) & (2^w – 1)) [step 4| step 3] * 3) t(a/b) = (d(a/b) + x(a/b)`*r(a/b) ) mod n [step 5| step 4] * 4) x(b/a)` = 2^w + ( x(b/a) & (2^w – 1) ) [step 6| step 5] * 5) U/V = [h*t(a/b)]( P(b/a) + [x(b/a)`]R(b/a) ) = ( x(u/v), y(u/v) ) [step 7| step 6] * tmp_p = SM3( x(u/v) || Za || Zb || xa || ya || xb || yb ) * 6) S(a/b) = SM3( 0x0(3/2) || y(u/v) || tmp_p ) [step 10| step 8] * 7) K(a/b) = KDF(x(u/v) || y(u/v) || Za || Zb, klen) [step 8| step 7] * @param [out] pSharedKey shared key [K(a/b) = KDF(x(u/v) || y(u/v) || Za || Zb, klen)] * @param [in] sharedKeySize length shared key * @param [out] pSSelf (may be == NULL) self data confirmation * @param [in] pPrvKey private key * @param [in] pEphPrvKey ephemeral private key (!) will be cleared at the end if function successfully competed (!) * @param [out] pKE context Key Exchange (save x(u/v) | y(u/v) | precompHash ) * @param [in] pScratchBuffer supported buffer * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC | pKE | pSharedKey | pPrvKey | PEphPrvKey | pSB is NULL * ippStsContextMatchErr - if pEC no valid ID | pEC no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported (n|p) modulus arithmetic * ippStsRangeErr - if BitSize(pEC) < IPP_SM3_DIGEST_BITSIZE * ippStsBadArgErr - if role(pKE) no equal ippKESM2Requester|ippKESM2Responder or sharedKeySize <= 0 * ippStsInvalidPrivateKey - if test is failed 0 < pPrvKey|pEphPrvKey < Order * ippStsEphemeralKeyErr - if test is failed pEphPrvKey == pEphPublicKeySelf*G or if calculated U(V) is an * infinity point, U/V = [h*t(a/b)]( P(b/a) + [x(b/a)`]R(b/a) ) = ( x(u/v), y(u/v) ) */ /* clang-format off */ IPPFUN(IppStatus, ippsGFpECKeyExchangeSM2_SharedKey, (Ipp8u* pSharedKey, int sharedKeySize, Ipp8u* pSSelf, const IppsBigNumState* pPrvKey, IppsBigNumState* pEphPrvKey, IppsGFpECKeyExchangeSM2State *pKE, Ipp8u* pScratchBuffer)) /* clang-format on */ { /* check Key Exchange */ IPP_BAD_PTR1_RET(pKE); /* check id */ IPP_BADARG_RET(!EC_SM2_KEY_EXCH_VALID_ID(pKE), ippStsContextMatchErr); /* check User Role */ const IppsKeyExchangeRoleSM2 role = EC_SM2_KEY_EXCH_ROLE(pKE); IPP_BADARG_RET(((ippKESM2Requester != role) && (ippKESM2Responder != role)), ippStsBadArgErr); /* check Elliptic Curve */ IppsGFpECState *pEC = EC_SM2_KEY_EXCH_EC(pKE); IPP_BAD_PTR1_RET(pEC); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); /* base P */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr); gsModEngine *nME = ECP_MONT_R(pEC); /* base N */ IPP_BADARG_RET(1 < GFP_EXTDEGREE(nME), ippStsNotSupportedModeErr); /* check bitsize >= SM3_DIGSET */ IPP_BADARG_RET(!(ECP_ORDBITSIZE(pEC) >= IPP_SM3_DIGEST_BITSIZE), ippStsRangeErr); /* check call Setup */ /* check init Public Key | Ephemeral Public Key */ IPP_BADARG_RET( NULL == EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE) || NULL == EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE) || NULL == EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE) || NULL == EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE), ippStsContextMatchErr) /* check Shared Key */ IPP_BAD_PTR1_RET(pSharedKey); /* [GBT.32918.3-2016] Public Key cryptographic algorithm SM2 based on elliptic curves * Part 3: Key exchange protocol * 5.4.3 Key derivation function * (0 < sharedKeySize) - (+) check * (sharedKeySize < (2^32 - 1)*log2(n) ) - NO NEED if use INT input data type */ IPP_BADARG_RET(!(sharedKeySize > 0), ippStsOutOfRangeErr); /* check buffer */ IPP_BAD_PTR1_RET(pScratchBuffer); /* check Private Key */ CHECK_PRIVATE_KEY(pPrvKey) /* check Ephemeral Private Key */ CHECK_PRIVATE_KEY(pEphPrvKey) #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512IFMA) && (cpID_PrimeTPM_SM2 == ECP_MODULUS_ID(pEC))) { const IppStatus sts = gfec_key_exchange_sm2_shared_key_avx512(pSharedKey, sharedKeySize, pSSelf, pPrvKey, pEphPrvKey, pKE, pScratchBuffer); return sts; } #endif // (_IPP32E >= _IPP32E_K1) { IppStatus sts = ippStsNoErr; /* setup Public | Ephemeral Public */ const IppsGFpECPoint *pPubKey = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_PUB_KEY_USER_B(pKE) : EC_SM2_KEY_EXCH_PUB_KEY_USER_A(pKE); const IppsGFpECPoint *pEphPubKey = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE) : EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE); const IppsGFpECPoint *pSelfEphPubKey = (ippKESM2Requester == role) ? EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE) : EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE); const Ipp8u firstNum = (ippKESM2Requester == role) ? 0x03 : 0x02; /* check that Ephemeral Public and Private Keys are related (R(a/b)=r(a/b)G) */ IppsGFpECPoint pTmpPoint; cpEcGFpInitPoint(&pTmpPoint, cpEcGFpGetPool(1, pEC), 0, pEC); BNU_CHUNK_T *pDataEphPrv = BN_NUMBER(pEphPrvKey); // Ephemeral Private Key -> r(a/b) gfec_MulBasePoint(&pTmpPoint, pDataEphPrv, BN_SIZE(pEphPrvKey), pEC, pScratchBuffer); // r(a/b)*G int result = gfec_ComparePoint(&pTmpPoint, pSelfEphPubKey, pEC); // R(a/b) == r(a/b)G ? cpEcGFpReleasePool(1, pEC); // Release pool before the possible exit IPP_BADARG_RET(!result, ippStsEphemeralKeyErr); /* extract data Elliptic Curve */ BNU_CHUNK_T *pOrder = MOD_MODULUS(nME); /* data oreder */ const int ordLen = MOD_LEN(nME); /* len order */ const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* create buffer data (it needs further use compute tmp_p) * -> SM3( x(u/v)(0) || Za(1) || Zb(2) || xa(3) || ya(4) || xb(5) || yb(6) ) */ BNU_CHUNK_T *pDataBuff = cpGFpGetPool(7, pME); BNU_CHUNK_T *_pXY_ = cpEcGFpGetPool(1, pEC); /* elem 3 */ /* 2) x(a/b)` = 2^w + (x(a/b) & (2^w – 1)) */ BNU_CHUNK_T *xa = pDataBuff + 3 * elemSize; /* xa(3) */ BNU_CHUNK_T *ya = pDataBuff + 4 * elemSize; /* ya(4) */ BNU_CHUNK_T *_xa_ = _pXY_; /* point to affine coordinate */ cpSM2KE_get_affine_ext_euclid(/* x = */ xa, /* y = */ ya, /* p = */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_A(pKE), /* pEC = */ pEC); /* reduction x = 2^w + ( x & (2^w - 1) ) */ cpSM2KE_reduction_x2w(_xa_, xa, pEC); /* to big endian */ cpSM2KE_xy_to_BE(xa, ya, pEC); /* 4) x(b/a)` = 2^w + ( x(b/a) & (2^w – 1) ) */ BNU_CHUNK_T *xb = pDataBuff + 5 * elemSize; /* xb(5) */ BNU_CHUNK_T *yb = pDataBuff + 6 * elemSize; /* yb(6) */ BNU_CHUNK_T *_xb_ = _pXY_ + elemSize; /* point to affine coordinate */ cpSM2KE_get_affine_ext_euclid(/* x = */ xb, /* y = */ yb, /* p = */ EC_SM2_KEY_EXCH_EPH_PUB_KEY_USER_B(pKE), /* pEC = */ pEC); /* reduction x = 2^w + ( x & (2^w - 1) ) */ cpSM2KE_reduction_x2w(_xb_, xb, pEC); /* to big endian */ cpSM2KE_xy_to_BE(xb, yb, pEC); BNU_CHUNK_T *_xf_ = (ippKESM2Requester == role) ? _xa_ : _xb_; BNU_CHUNK_T *_xs_ = (ippKESM2Requester == role) ? _xb_ : _xa_; /* 3) t(a/b) = (d(a/b) + x(a/b)`*r(a/b) ) mod n */ BNU_CHUNK_T *t = pDataBuff + elemSize; /* temporary use slot Za(1) */ /* Private key -> d(a/b) */ BNU_CHUNK_T *pTmpPrv = pDataBuff; /* temporary use slot x(u/v)(0) */ cpGFpElementCopy(pTmpPrv, BN_NUMBER(pPrvKey), elemSize); GFP_METHOD(nME)->encode(pTmpPrv, pTmpPrv, nME); /* Ephemeral Private Key -> r(a/b) */ GFP_METHOD(nME)->encode(pDataEphPrv, pDataEphPrv, nME); /* x(a/b)` */ GFP_METHOD(nME)->encode(_xf_, _xf_, nME); GFP_METHOD(nME)->mul(pDataEphPrv, pDataEphPrv, _xf_, nME); /* x(a/b)`*r(a/b) mod n */ BNU_CHUNK_T *pBuffTmp = pDataBuff + 2 * elemSize; /* temporary use slot Zb(2) */ cpModAdd_BNU(t, pDataEphPrv, pTmpPrv, pOrder, ordLen, pBuffTmp); /* (d(a/b) + x(a/b)`*r(a/b) ) mod n */ /* 5) U/V = [h*t(a/b)]( P(b/a) + [x(b/a)`]R(b/a) ) = ( x(u/v), y(u/v) ) */ /* [x(b/a)`]R(b/a) */ const int scalarBits = ((elemBits + 1) / 2); cpEcGFpInitPoint(&pTmpPoint, cpEcGFpGetPool(1, pEC), 0, pEC); gfec_point_mul(ECP_POINT_X(&pTmpPoint), ECP_POINT_X(pEphPubKey), (Ipp8u *)_xs_, scalarBits, pEC, pScratchBuffer); /* P(b/a) + [x(b/a)`]R(b/a) */ gfec_point_add(ECP_POINT_X(&pTmpPoint), ECP_POINT_X(&pTmpPoint), ECP_POINT_X(pPubKey), pEC); /* h*t(a/b) */ BNU_CHUNK_T *pCofactor = ECP_COFACTOR(pEC); const int cofactorLen = cpGFpElementLen(pCofactor, elemSize); if (!GFP_IS_ONE(pCofactor, cofactorLen)) { cpMontMul_BNU_EX(t, t, elemSize, pCofactor, cofactorLen, nME); } GFP_METHOD(nME)->decode(t, t, nME); /* we can do this because slot Zb(2) not Use Now */ cpGFpElementCopyPad(t, elemSize + 1, t, elemSize); /* U/V = [h*t(a/b)]( P(b/a) + [x(b/a)`]R(b/a) ) = ( x(u/v), y(u/v) ) */ gfec_point_mul(ECP_POINT_X(&pTmpPoint), ECP_POINT_X(&pTmpPoint), (Ipp8u *)t, elemBits, pEC, pScratchBuffer); /* check U/V == 0 */ ECP_POINT_FLAGS(&pTmpPoint) = gfec_IsPointAtInfinity(&pTmpPoint) ? 0 : ECP_FINITE_POINT; if(ECP_POINT_FLAGS(&pTmpPoint) == 0) { sts = ippStsEphemeralKeyErr; } /* extract Affine Coordinate X|Y */ /* save x(u/v), y(u/v) */ BNU_CHUNK_T *x_af = EC_SM2_KEY_EXCH_POINT_X(pKE); BNU_CHUNK_T *y_af = EC_SM2_KEY_EXCH_POINT_Y(pKE); /* point to affine coordinate */ cpSM2KE_get_affine_ext_euclid(/* x = */ x_af, /* y = */ y_af, /* p = */ &pTmpPoint, /* pEC = */ pEC); /* to big endian */ cpSM2KE_xy_to_BE(x_af, y_af, pEC); /* Precompute Hash */ Ipp8u *pBuff = (Ipp8u *)pDataBuff; /* tmp_p = SM3( x(u/v) || Za || Zb || xa || ya || xb || yb ) */ /* copy x(u/v)(0) */ cpSM2_CopyBlock(pBuff, (const Ipp8u *)x_af, elemBytes); pBuff += elemBytes; /* copy Za(1) */ cpSM2_CopyBlock(pBuff, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE), IPP_SM3_DIGEST_BYTESIZE); pBuff += IPP_SM3_DIGEST_BYTESIZE; /* copy Zb(2) */ cpSM2_CopyBlock(pBuff, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE), IPP_SM3_DIGEST_BYTESIZE); pBuff += IPP_SM3_DIGEST_BYTESIZE; /* recopy xa */ cpSM2_CopyBlock(pBuff, (const Ipp8u *)xa, elemBytes); pBuff += elemBytes; /* recopy ya */ cpSM2_CopyBlock(pBuff, (const Ipp8u *)ya, elemBytes); pBuff += elemBytes; /* recopy xb */ cpSM2_CopyBlock(pBuff, (const Ipp8u *)xb, elemBytes); pBuff += elemBytes; /* recopy yb */ cpSM2_CopyBlock(pBuff, (const Ipp8u *)yb, elemBytes); /* set pointer start */ pBuff = (Ipp8u *)pDataBuff; const int sizeS_SM3 = elemBytes + 2 * IPP_SM3_DIGEST_BYTESIZE + 4 * elemBytes; /* copy to next operation */ cpSM2KE_compute_hash_SM3(EC_SM2_KEY_EXCH_PRECOM_HASH(pKE), pBuff, sizeS_SM3); /* check U/V == 0 and S == NULL */ if ((NULL != pSSelf) && IS_ECP_FINITE_POINT(&pTmpPoint)) { /* 6) S(a/b) = SM3( 0x0(3/2) || y(u/v) || tmp_p ) */ /* copy 0x0(3/2) */ pBuff[0] = firstNum; /* copy y(u/v) */ cpSM2_CopyBlock(pBuff + 1, (const Ipp8u *)y_af, elemBytes); /* copy tmp_p */ cpSM2_CopyBlock(pBuff + 1 + elemBytes, EC_SM2_KEY_EXCH_PRECOM_HASH(pKE), IPP_SM3_DIGEST_BYTESIZE); const int sizeSab_SM3 = 1 + elemBytes + IPP_SM3_DIGEST_BYTESIZE; cpSM2KE_compute_hash_SM3(pSSelf, pBuff, sizeSab_SM3); } /* compute KDF */ /* 7) K(a/b) = KDF(x(u/v) || y(u/v) || Za || Zb, klen) */ /* copy x(u/v)(0)*/ cpSM2_CopyBlock(pBuff, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_X(pKE), elemBytes); pBuff += elemBytes; /* copy y(u/v)(1) */ cpSM2_CopyBlock(pBuff, (const Ipp8u *)EC_SM2_KEY_EXCH_POINT_Y(pKE), elemBytes); pBuff += elemBytes; /* copy Za(2) */ cpSM2_CopyBlock(pBuff, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_A(pKE), IPP_SM3_DIGEST_BYTESIZE); pBuff += IPP_SM3_DIGEST_BYTESIZE; /* copy Zb(3) */ cpSM2_CopyBlock(pBuff, EC_SM2_KEY_EXCH_USER_ID_HASH_USER_B(pKE), IPP_SM3_DIGEST_BYTESIZE); const int sizeKab_KDF = 2 * elemBytes + 2 * IPP_SM3_DIGEST_BYTESIZE; /* set pointer start */ pBuff = (Ipp8u *)pDataBuff; /* compute KDF */ KDF_sm3(pSharedKey, sharedKeySize, (const Ipp8u *)pBuff, sizeKab_KDF); /* free buffers */ cpEcGFpReleasePool(2, pEC); cpGFpReleasePool(7, pME); /* clear Ephemeral Private Key */ cpBN_zero(pEphPrvKey); return sts; } } #undef CHECK_PRIVATE_KEY cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_message_representation.c000066400000000000000000000066751470420105600305270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SM3 // // Contents: // ippsGFpECMessageRepresentationSM2() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gsmodstuff.h" #include "gfpec/sm2/sm2_stuff.h" /* clang-format off */ IPPFUN(IppStatus, ippsGFpECMessageRepresentationSM2, (IppsBigNumState * pMsgDigest, const Ipp8u* pMsg, int msgLen, const Ipp8u* pUserID, int userIDLen, const IppsGFpECPoint* pRegPublic, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* clang-format on */ { IppsGFpState *pGF; gsModEngine *pGFE; /* check curve data */ IPP_BAD_PTR1_RET(pEC); IPP_BAD_PTR1_RET(pScratchBuffer); IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr); IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr); /* check Message */ IPP_BAD_PTR1_RET(pMsg); /* check border (msgLen > 0) */ IPP_BADARG_RET(!(msgLen > 0), ippStsOutOfRangeErr); /* check message digest */ IPP_BAD_PTR1_RET(pMsgDigest); IPP_BADARG_RET(!BN_VALID_ID(pMsgDigest), ippStsContextMatchErr); /* make sure bitsize(pMsgDigest) <= bitsize(order) */ IPP_BADARG_RET(!(cpBN_bitsize(pMsgDigest) <= ECP_ORDBITSIZE(pEC)), ippStsMessageErr); /* check User ID */ IPP_BAD_PTR1_RET(pUserID); /* check border (userIDLen > 0) */ IPP_BADARG_RET(!(userIDLen > 0), ippStsOutOfRangeErr); pGF = ECP_GFP(pEC); pGFE = GFP_PMA(pGF); IPP_BADARG_RET(1 < GFP_EXTDEGREE(pGFE), ippStsNotSupportedModeErr); /* check Public Key */ IPP_BAD_PTR1_RET(pRegPublic); IPP_BADARG_RET(!ECP_POINT_VALID_ID(pRegPublic), ippStsContextMatchErr); IPP_BADARG_RET(ECP_POINT_FELEN(pRegPublic) != GFP_FELEN(pGFE), ippStsOutOfRangeErr); Ipp8u Za[IPP_SM3_DIGEST_BYTESIZE]; /* compute Za = SM3( ENTL || ID || a || b || xG || yG || xA || yA ) */ const IppStatus sts = ippsGFpECUserIDHashSM2((Ipp8u *)Za, pUserID, userIDLen, pRegPublic, pEC, pScratchBuffer); if(ippStsNoErr != sts){ return sts; } /* e = SM3(Za || M) */ static IppsHashState_rmf ctx; ippsHashInit_rmf(&ctx, ippsHashMethod_SM3()); /* Za */ ippsHashUpdate_rmf(Za, sizeof(Za), &ctx); /* M */ ippsHashUpdate_rmf(pMsg, msgLen, &ctx); /* final */ ippsHashFinal_rmf((Ipp8u *)(BN_NUMBER(pMsgDigest)), &ctx); BN_SIGN(pMsgDigest) = ippBigNumPOS; /* clear stack data */ PurgeBlock(Za, sizeof(Za)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_stuff.c000066400000000000000000000140221470420105600250710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "gsmodstuff.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief * compute Za digest = SM3( ENTL || ID || a || b || xG || yG || xA || yA ) * @param [out] pZa_digest (Za) output digest Za * @param [in] p_user_id (ID) data user ID * @param [in] user_id_len (ENTL) length user ID * @param [in] elem_len length element bytes * @param [in] a (a) coefficient a of Elliptic Curve * @param [in] b (b) coefficient b of Elliptic Curve * @param [in] Gx (Gx) base point coordinate X of Elliptic Curve * @param [in] Gy (Gy) base point coordinate Y of Elliptic Curve * @param [in] pub_key_x (xA) public point coordinate X * @param [in] pub_key_y (yA) public point coordinate Y */ /* clang-format off */ IPP_OWN_DEFN(IppStatus, computeZa_user_id_hash_sm2, (Ipp8u * pZa_digest, const Ipp8u *p_user_id, const int user_id_len, const int elem_len, const Ipp8u *a, const Ipp8u *b, const Ipp8u *Gx, const Ipp8u *Gy, const Ipp8u *pub_key_x, const Ipp8u *pub_key_y)) /* clang-format on */ { /* check pointer Za Digest | user id */ IPP_BAD_PTR2_RET(pZa_digest, p_user_id); /* check border (user_id_len > 0) | (elem_len > 0) */ IPP_BADARG_RET(!(user_id_len > 0) || !(elem_len > 0), ippStsBadArgErr); /* check (user_id_len*8 <= 0xFFFF) ~ (user_id_len <= 0x1FFF) for two bytes overflow. user_id_len*8 operation will be executed in algorithm's flow */ IPP_BADARG_RET(user_id_len > 0x1FFF, ippStsBadArgErr); /* param curve: a, b, Gx, Gy */ IPP_BAD_PTR2_RET(a, b); IPP_BAD_PTR2_RET(Gx, Gy); /* Public X|Y */ IPP_BAD_PTR2_RET(pub_key_x, pub_key_y) static IppsHashState_rmf ctx; ippsHashInit_rmf(&ctx, ippsHashMethod_SM3()); /* compute Za = SM3( ENTL || ID || a || b || xG || yG || xA || yA ) */ /* ENLT */ const Ipp16u entl = ((user_id_len * 8) & 0xFFFF); Ipp8u ENTL[sizeof(Ipp16u)]; ENTL[0] = (Ipp8u)(entl >> 8); ENTL[1] = (Ipp8u)(entl & 0xFF); ippsHashUpdate_rmf(ENTL, sizeof(ENTL), &ctx); /* ID */ ippsHashUpdate_rmf(p_user_id, user_id_len, &ctx); /* a */ ippsHashUpdate_rmf(a, elem_len, &ctx); /* b */ ippsHashUpdate_rmf(b, elem_len, &ctx); /* Gx */ ippsHashUpdate_rmf(Gx, elem_len, &ctx); /* Gy */ ippsHashUpdate_rmf(Gy, elem_len, &ctx); /* Px */ ippsHashUpdate_rmf(pub_key_x, elem_len, &ctx); /* Py */ ippsHashUpdate_rmf(pub_key_y, elem_len, &ctx); /* final */ ippsHashFinal_rmf(pZa_digest, &ctx); /* clear stack data */ PurgeBlock(ENTL, sizeof(ENTL)); return ippStsNoErr; } #define SIZE_CT (4) __IPPCP_INLINE void convert_ct_to_big_endian(Ipp8u pCt[SIZE_CT], const Ipp32u ct) { pCt[0] = (Ipp8u)(ct >> 24); pCt[1] = (Ipp8u)(ct >> 16); pCt[2] = (Ipp8u)(ct >> 8); pCt[3] = (Ipp8u)(ct); return; } /** * @brief compute KDF base by SM3 hash * @param [out] pKDF pointer output KDF * @param [in] kdf_len length KDF * @param [in] pZ data Z to create KDF * @param [in] z_len length Z data * bound kdf_len in standard: * */ IPP_OWN_DEFN(IppStatus, KDF_sm3, (Ipp8u * pKDF, int kdf_len, const Ipp8u *pZ, const int z_len)) { /* check pointer input */ IPP_BAD_PTR2_RET(pKDF, pZ); /* [GBT.32918.3-2016] Public Key cryptographic algorithm SM2 based on elliptic curves Part 3: Key exchange protocol * 5.4.3 Key derivation function * kdf_len < (2^32 - 1) * 2^5 = 2^37 - 32 [bytes] * BUT if input INT type - NO NEED check this border */ /* check border (kdf_len >= 0) */ IPP_BADARG_RET(!(kdf_len >= 0), ippStsBadArgErr); /* check border (z_len > 0) */ IPP_BADARG_RET(!(z_len > 0), ippStsBadArgErr); /* if kdf > 0 */ if (kdf_len > 0) { /* buffer */ Ipp8u buff[IPP_SM3_DIGEST_BYTESIZE]; // step (a) Ipp8u pCt[SIZE_CT]; const Ipp32u n = (Ipp32u)((kdf_len + IPP_SM3_DIGEST_BYTESIZE - 1) / IPP_SM3_DIGEST_BYTESIZE) + 1u; /* add 1 - loop start 1 */ /* init copy output len */ int num_copy = IPP_SM3_DIGEST_BYTESIZE; static IppsHashState_rmf ctx; ippsHashInit_rmf(&ctx, ippsHashMethod_SM3()); /* compute length K = Ha1 || Ha2 || ... */ // step (b) for (Ipp32u i = 1u; i < n; ++i) { // step (b.1) -> Hai = H(Z || ct) /* Z */ ippsHashUpdate_rmf(pZ, z_len, &ctx); /* ct */ convert_ct_to_big_endian(pCt, i); ippsHashUpdate_rmf(pCt, sizeof(pCt), &ctx); /* auto init of end function - no need call in start loop */ ippsHashFinal_rmf(buff, &ctx); /* copy result */ if ((i == n - 1u) && (0 != kdf_len % IPP_SM3_DIGEST_BYTESIZE)) { num_copy = kdf_len % IPP_SM3_DIGEST_BYTESIZE; } cpSM2_CopyBlock(pKDF, buff, num_copy); /* update copy next result */ pKDF += num_copy; kdf_len -= num_copy; } /* clear stack data */ PurgeBlock(buff, sizeof(buff)); PurgeBlock(pCt, sizeof(pCt)); } return ippStsNoErr; } #undef SIZE_CT cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_stuff.h000066400000000000000000000137031470420105600251030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SM2 support function // // Contents: // SM2 methods and constants // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "gfpec/pcpeccp.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/sm2_key_exchange_method.h" #if !defined _SM2_STUFF_H #define _SM2_STUFF_H #define cpSM2_CopyBlock(DST, SRC, SIZE) CopyBlock((SRC), (DST), (SIZE)) /** * @brief * reverse inplace array ( Little Endian to Big Endian data ) * @param[in out] arr array data * @param[in] len length array */ __IPPCP_INLINE void cpSM2KE_reverse_inplace(Ipp8u *arr, const int len) { #define SWAPXOR(x, y) \ (x) ^= (y); \ (y) ^= (x); \ (x) ^= (y); for (int i = 0; i < len / 2; ++i) { SWAPXOR(arr[i], arr[len - 1 - i]) } return; #undef SWAPXOR } /** * @brief cpSM2KE_CopyPointData * init and copy Pointer * @param[out] r point in Elliptic Curve * @param[in] data buffer init pointer data * @param[in] p point copy * @param[in] pEC context Elliptic Curve */ __IPPCP_INLINE void cpSM2KE_CopyPointData(IppsGFpECPoint *r, BNU_CHUNK_T *data, const IppsGFpECPoint *p, const IppsGFpECState *pEC) { ECP_POINT_SET_ID(r); cpEcGFpInitPoint(r, data, ECP_POINT_FLAGS(p), pEC); gfec_CopyPoint(r, p, ECP_POINT_FELEN(p)); return; } /** * @brief * reduction for the SM2 Key Exchange standard * x` = 2^w + (x & (2^w – 1)) * when * w = log2(n)/2 - 1, n - number bytes order * @param[out] r reduction value x` * @param[in] a value x * @param[in] pEC context Elliptic Curve */ __IPPCP_INLINE void cpSM2KE_reduction_x2w(BNU_CHUNK_T *r, const BNU_CHUNK_T *a, const IppsGFpECState *pEC) { const gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemSize = GFP_FELEN(pME); /* size BNU_CHUNK */ /* compute w = [log2(n)/2 - 1] */ const int w = ((elemBits + 1) / 2 - 1); /* compute copy BNU_CHUNK */ const int num_copy_bc = (w + (BNU_CHUNK_BITS - 1)) / BNU_CHUNK_BITS; const int num_bit_shift = (w - (num_copy_bc - 1) * BNU_CHUNK_BITS); const BNU_CHUNK_T vadd = (BNU_CHUNK_T)(1ULL << num_bit_shift); const BNU_CHUNK_T mask = (BNU_CHUNK_T)(vadd - 1); ZEXPAND_COPY_BNU(r, elemSize, a, num_copy_bc); r[num_copy_bc - 1] = (r[num_copy_bc - 1] & mask) + vadd; return; } /* clang-format off */ __IPPCP_INLINE void cpSM2KE_get_affine_ext_euclid(BNU_CHUNK_T *x, BNU_CHUNK_T *y, const IppsGFpECPoint *p, IppsGFpECState *pEC) /* clang-format on */ { gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); gfec_GetPoint(x, y, p, pEC); GFP_METHOD(pME)->decode(x, x, pME); GFP_METHOD(pME)->decode(y, y, pME); return; } __IPPCP_INLINE void cpSM2KE_xy_to_BE(BNU_CHUNK_T *x, BNU_CHUNK_T *y, const IppsGFpECState *pEC) { const gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ cpSM2KE_reverse_inplace((Ipp8u *)x, elemBytes); cpSM2KE_reverse_inplace((Ipp8u *)y, elemBytes); return; } /** * @brief * comput SM3 hash by message * @param[out] r hash SM3 compute * @param[in] a hashing an array data * @param[in] numBytes number of bytes */ __IPPCP_INLINE void cpSM2KE_compute_hash_SM3(Ipp8u *r, const Ipp8u *a, const int numBytes) { static IppsHashState_rmf ctx; /* init */ ippsHashInit_rmf(&ctx, ippsHashMethod_SM3()); /* update hash */ ippsHashUpdate_rmf(a, numBytes, &ctx); /* final */ ippsHashFinal_rmf(r, &ctx); return; } /* clang-format off */ /* compute Za digest = SM3( ENTL || ID || a || b || xG || yG || xA || yA ) */ #define computeZa_user_id_hash_sm2 OWNAPI(computeZa_user_id_hash_sm2) IPP_OWN_DECL(IppStatus, computeZa_user_id_hash_sm2, (Ipp8u * pZa_digest, const Ipp8u* p_user_id, const int user_id_len, const int elem_len, const Ipp8u* a, const Ipp8u* b, const Ipp8u* Gx, const Ipp8u* Gy, const Ipp8u* pub_key_x, const Ipp8u* pub_key_y)) /* KDF sm3 */ #define KDF_sm3 OWNAPI(KDF_sm3) IPP_OWN_DECL(IppStatus, KDF_sm3, (Ipp8u * pKDF, int kdf_len, const Ipp8u* pZ, const int z_len)) /* IFMA optimization SM2 Key Exchange Shared Key */ #define gfec_key_exchange_sm2_shared_key_avx512 OWNAPI(gfec_key_exchange_sm2_shared_key_avx512) IPP_OWN_DECL(IppStatus, gfec_key_exchange_sm2_shared_key_avx512, (Ipp8u* pSharedKey, const int sharedKeySize, Ipp8u* pSSelf, const IppsBigNumState* pPrvKey, IppsBigNumState* pEphPrvKey, IppsGFpECKeyExchangeSM2State *pKE, Ipp8u* pScratchBuffer)) /* clang-format on */ #endif // _SM2_STUFF_H cryptography-primitives-1.0.0/sources/ippcp/gfpec/sm2/sm2_user_id_hash.c000066400000000000000000000120721470420105600264020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "gfpec/pcpgfpstuff.h" #include "gfpec/pcpgfpecstuff.h" #include "gfpec/sm2/sm2_stuff.h" /** * @brief ippsGFpECUserIDHashSM2 * compute digest Za = SM3( ENTL||IDA||a||b||Gx||Gy||Px||Py) * @param [out] pZaDigest digest Za * @param [in] pUserID user ID data * @param [in] userIDLen length user ID data * @param [in] pPublicKey public key * @param [in] pEC context Elliptic Curve * @param [in] pScratchBuffer supported buffer * @return * ippStsNoErr - successful * ippStsNullPtrErr - if pEC | pUserID | pPublicKey is NULL * ippStsContextMatchErr - if pEC no valid ID | pEC | ID pPublic Key no exists SUBGROUP * ippStsNotSupportedModeErr - if pEC no supported (n|p) modulus arithmetic * ippStsInvalidPoint - if no in curve Pub Key * ippStsBadArgErr - if userIDLen <= 0 or the number representing the userIDLen in bits * exceed two bytes (user_id_len*8 > 0xFFFF) * ippStsOutOfRangeErr - if userIDLen <= 0 or public key length is out of range */ /* clang-format off */ IPPFUN(IppStatus, ippsGFpECUserIDHashSM2, (Ipp8u * pZaDigest, const Ipp8u* pUserID, int userIDLen, const IppsGFpECPoint* pPublicKey, IppsGFpECState* pEC, Ipp8u* pScratchBuffer)) /* clang-format on */ { /* check curve data */ IPP_BAD_PTR1_RET(pEC) IPP_BAD_PTR1_RET(pScratchBuffer) IPP_BADARG_RET(!VALID_ECP_ID(pEC), ippStsContextMatchErr) IPP_BADARG_RET(!ECP_SUBGROUP(pEC), ippStsContextMatchErr) gsModEngine *pME = GFP_PMA(ECP_GFP(pEC)); IPP_BADARG_RET(1 < GFP_EXTDEGREE(pME), ippStsNotSupportedModeErr) /* check Za return */ IPP_BAD_PTR1_RET(pZaDigest) /* check User ID */ IPP_BAD_PTR1_RET(pUserID) /* check border (userIDLen > 0) */ IPP_BADARG_RET(!(userIDLen > 0), ippStsOutOfRangeErr); /* check Public Key */ IPP_BAD_PTR1_RET(pPublicKey) IPP_BADARG_RET(!ECP_POINT_VALID_ID(pPublicKey), ippStsContextMatchErr) IPP_BADARG_RET(ECP_POINT_FELEN(pPublicKey) != GFP_FELEN(pME), ippStsOutOfRangeErr) IPP_BADARG_RET(0 == gfec_IsPointOnCurve(pPublicKey, pEC), ippStsInvalidPoint); IppStatus ret = ippStsNoErr; const int elemBits = GFP_FEBITLEN(pME); /* size Bits */ const int elemBytes = (elemBits + 7) / 8; /* size Bytes */ const int elemLen = GFP_FELEN(pME); /* size BNU_CHUNK */ BNU_CHUNK_T *pDataBuff = cpGFpGetPool(6, pME); /* param curve : a,b,Gx,Gy */ BNU_CHUNK_T *pA = pDataBuff; BNU_CHUNK_T *pB = pDataBuff + 1 * elemLen; BNU_CHUNK_T *pGx = pDataBuff + 2 * elemLen; BNU_CHUNK_T *pGy = pDataBuff + 3 * elemLen; /* Public X | Y */ BNU_CHUNK_T *pX = pDataBuff + 4 * elemLen; BNU_CHUNK_T *pY = pDataBuff + 5 * elemLen; /* get affine coordinate X | Y */ gfec_GetPoint(/* pX = */ pX, /* pY = */ pY, /* pPoint = */ pPublicKey, /* pEC = */ pEC); /* decode */ GFP_METHOD(pME)->decode(pX, pX, pME); GFP_METHOD(pME)->decode(pY, pY, pME); GFP_METHOD(pME)->decode(pA, ECP_A(pEC), pME); GFP_METHOD(pME)->decode(pB, ECP_B(pEC), pME); GFP_METHOD(pME)->decode(pGx, ECP_G(pEC), pME); GFP_METHOD(pME)->decode(pGy, ECP_G(pEC) + elemLen, pME); /* convert Little Endian to Big Endian */ cpSM2KE_reverse_inplace((Ipp8u *)pX, elemBytes); /* X */ cpSM2KE_reverse_inplace((Ipp8u *)pY, elemBytes); /* Y */ cpSM2KE_reverse_inplace((Ipp8u *)pA, elemBytes); /* a */ cpSM2KE_reverse_inplace((Ipp8u *)pB, elemBytes); /* b */ cpSM2KE_reverse_inplace((Ipp8u *)pGx, elemBytes); /* Gx */ cpSM2KE_reverse_inplace((Ipp8u *)pGy, elemBytes); /* Gy */ /* create hash */ ret = computeZa_user_id_hash_sm2(pZaDigest, /* p_user_id = */ pUserID, /* user_id_len = */ userIDLen, /* elem_len = */ elemBytes, /* a = */ (Ipp8u *)pA, /* b = */ (Ipp8u *)pB, /* Gx = */ (Ipp8u *)pGx, /* Gy = */ (Ipp8u *)pGy, /* px = */ (Ipp8u *)pX, /* py = */ (Ipp8u *)pY); cpGFpReleasePool(6, pME); return ret; } cryptography-primitives-1.0.0/sources/ippcp/gsmod_almmontinv.c000066400000000000000000000074571470420105600247670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // alm_mont_inv() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcpmask_ct.h" /* // almost Montgomery Inverse // // returns (k,r), r = (1/a)*(2^k) mod m // */ IPP_OWN_DEFN (int, alm_mont_inv, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); int mLen = MOD_LEN(pME); const int polLength = 4; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return 0; // zero return value is handled by the calling function BNU_CHUNK_T* pu = pBuffer; BNU_CHUNK_T* ps = pu+mLen; BNU_CHUNK_T* pv = ps+mLen; BNU_CHUNK_T* pt = pv+mLen; int k = 0; BNU_CHUNK_T ext = 0; // u=modulus, v=a, t=0, s=1 COPY_BNU(pu, pm, mLen); ZEXPAND_BNU(ps, 0, mLen); ps[0] = 1; COPY_BNU(pv, pa, mLen); ZEXPAND_BNU(pt, 0, mLen); while(!cpEqu_BNU_CHUNK(pv, mLen, 0)) { // while(v>0) { if(0==(pu[0]&1)) { // if(isEven(u)) { cpLSR_BNU(pu, pu, mLen, 1); // u = u/2; cpAdd_BNU(ps, ps, ps, mLen); // s = 2*s; } // } else if(0==(pv[0]&1)) { // else if(isEven(v)) { cpLSR_BNU(pv, pv, mLen, 1); // v = v/2; /*ext +=*/ cpAdd_BNU(pt, pt, pt, mLen); // t = 2*t; } // } else { int cmpRes = cpCmp_BNU(pu, mLen, pv, mLen); if(cmpRes>0) { // else if (u>v) { cpSub_BNU(pu, pu, pv, mLen); // u = (u-v); cpLSR_BNU(pu, pu, mLen, 1); // u = u/2; /*ext +=*/ cpAdd_BNU(pt, pt, ps, mLen); // t = t+s; cpAdd_BNU(ps, ps, ps, mLen); // s = 2*s; } // } else { // else if(v>=u) { cpSub_BNU(pv, pv, pu, mLen); // v = (v-u); cpLSR_BNU(pv, pv, mLen, 1); // v = v/2; cpAdd_BNU(ps, ps, pt, mLen); // s = s+t; ext += cpAdd_BNU(pt, pt, pt, mLen); // t = 2*t; } // } } k++; // k += 1; } // } // test if(1!=cpEqu_BNU_CHUNK(pu, mLen, 1)) { k = 0; /* inversion not found */ } else { ext -= cpSub_BNU(pr, pt, pm, mLen); // if(t>mod) r = t-mod; cpMaskedReplace_ct(pr, pt, mLen, ~cpIsZero_ct(ext)); // else r = t; cpSub_BNU(pr, pm, pr, mLen); // return r= (mod - r) and k } gsModPoolFree(pME, polLength); return k; } cryptography-primitives-1.0.0/sources/ippcp/gsmod_almmontinv_ct.c000066400000000000000000000076671470420105600254600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // alm_mont_inv_ct() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcpmask_ct.h" /* // almost Montgomery Inverse // // returns (k,r), r = (1/a)*(2^k) mod m // // (constant-execution-time version) */ IPP_OWN_DEFN (int, alm_mont_inv_ct, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); int mLen = MOD_LEN(pME); int modulusBitSize = MOD_BITSIZE(pME); const int polLength = 6; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return 0; // zero return value is handled by the calling function BNU_CHUNK_T* pu = pBuffer; BNU_CHUNK_T* ps = pu+mLen; BNU_CHUNK_T* pv = ps+mLen; BNU_CHUNK_T* pt = pv+mLen; BNU_CHUNK_T* px = pt+mLen; BNU_CHUNK_T* py = px+mLen; int k = 0; int i; BNU_CHUNK_T ext = 0; // u=modulus, s=1 and v=a, t=0, COPY_BNU(pu, pm, mLen); ZEXPAND_BNU(ps, 0, mLen); ps[0] = 1; COPY_BNU(pv, pa, mLen); ZEXPAND_BNU(pt, 0, mLen); for(i=0; i<2*modulusBitSize; i++) { /* update mask - update = (v==0)? 0xFF : 0 */ BNU_CHUNK_T update = ~cpIsGFpElemEquChunk_ct(pv, mLen, 0); /* temporary masks */ BNU_CHUNK_T m, mm; /* compute in advance r = s+t */ cpAdd_BNU(pr, ps, pt, mLen); /* // update or keep current u, s, v, t */ /* if(isEven(u)) { u=u/2; s=2*s; } 1-st branch */ m = update & cpIsEven_ct(pu[0]); cpLSR_BNU(px, pu, mLen, 1); cpAdd_BNU(py, ps, ps, mLen); cpMaskedReplace_ct(pu, px, mLen, m); cpMaskedReplace_ct(ps, py, mLen, m); /* else if(isEven(v)) { v=v/2; t=2*t; } 2-nd branch */ mm = update & ~m & cpIsEven_ct(pv[0]); cpLSR_BNU(px, pv, mLen, 1); cpAdd_BNU(py, pt, pt, mLen); cpMaskedReplace_ct(pv, px, mLen, mm); cpMaskedReplace_ct(pt, py, mLen, mm); m |= mm; /* if fall in the 1-st of 2-nf branches m=FF.. else m=0 */ /* else if(v>=u) { v=(v-u)/2; s=s+t; t=2*t;} 3-st branch */ mm = cpSub_BNU(px, pv, pu, mLen); mm = cpIsZero_ct(mm); mm = update & ~m & mm; cpLSR_BNU(px, px, mLen, 1); ext += cpAdd_BNU(py, pt, pt, mLen) & mm; cpMaskedReplace_ct(pv, px, mLen, mm); cpMaskedReplace_ct(ps, pr, mLen, mm); cpMaskedReplace_ct(pt, py, mLen, mm); /* else { u=(u-v)/2; t= t+s; s=2*s; } 4-rd branch*/ cpSub_BNU(px, pu, pv, mLen); mm = update & ~m & ~mm; cpLSR_BNU(px, px, mLen, 1); cpAdd_BNU(py, ps, ps, mLen); cpMaskedReplace_ct(pu, px, mLen, mm); cpMaskedReplace_ct(pt, pr, mLen, mm); cpMaskedReplace_ct(ps, py, mLen, mm); /* update or keep current k */ k = ((k+1) & (Ipp32s)update) | (k & (Ipp32s)~update); } /* // r = (t>mod)? t-mod : t; // r = mod - t; */ ext -= cpSub_BNU(pr, pt, pm, mLen); cpMaskedReplace_ct(pr, pt, mLen, ~cpIsZero_ct(ext)); cpSub_BNU(pr, pm, pr, mLen); /* test if inversion not found (k=0) */ k &= cpIsGFpElemEquChunk_ct(pu, mLen, 1); gsModPoolFree(pME, polLength); return k; } cryptography-primitives-1.0.0/sources/ippcp/gsmod_enginegetsize.c000066400000000000000000000042641470420105600254340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // gsModEngineGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcptool.h" /*F* // Name: gsModEngineGetSize // // Purpose: Specifies size of size of ModEngine context (Montgomery). // // Returns: Reason: // ippStsLengthErr modulusBitSize < 1 // numpe < MOD_ENGINE_MIN_POOL_SIZE // ippStsNoErr no errors // // Parameters: // numpe length of pool // modulusBitSize max modulus length (in bits) // pSize pointer to size // *F*/ IPP_OWN_DEFN (IppStatus, gsModEngineGetSize, (int modulusBitSize, int numpe, int* pSize)) { int modLen = BITS_BNU_CHUNK(modulusBitSize); int pelmLen = BITS_BNU_CHUNK(modulusBitSize); IPP_BADARG_RET(modulusBitSize<1, ippStsLengthErr); IPP_BADARG_RET(numpepoolLenUsed >= pME->poolLen)? NULL : MOD_BUFFER(pME, pME->poolLenUsed); return pPool; } cryptography-primitives-1.0.0/sources/ippcp/gsmod_inv.c000066400000000000000000000033551470420105600233700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // gs_inv() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" /* // returns r =1/a // a in desidue domain // r in desidue domain */ IPP_OWN_DEFN (BNU_CHUNK_T*, gs_inv, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME, alm_inv alm_inversion)) { int k = alm_inversion(pr, pa, pME); if(0==k) return NULL; { int mLen = MOD_LEN(pME); int m = mLen*BNU_CHUNK_BITS; mod_mul mon_mul = MOD_METHOD(pME)->mul; BNU_CHUNK_T* t = gsModPoolAlloc(pME, 1); if(NULL == t) return NULL; if(k>m) { ZEXPAND_BNU(t, 0, mLen); t[0] = 1; mon_mul(pr, pr, t, pME); k -= m; } ZEXPAND_BNU(t, 0, mLen); SET_BIT(t, m-k); /* t = 2^(m-k) */ mon_mul(pr, pr, t, pME); gsModPoolFree(pME, 1); return pr; } } cryptography-primitives-1.0.0/sources/ippcp/gsmod_montfactor.c000066400000000000000000000026611470420105600247470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // gsMontFactor() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcptool.h" /* // montfomery factor k0 = -((modulus^-1 mod B) %B) */ IPP_OWN_DEFN (BNU_CHUNK_T, gsMontFactor, (BNU_CHUNK_T m0)) { BNU_CHUNK_T y = 1; BNU_CHUNK_T x = 2; BNU_CHUNK_T mask = 2*x-1; int i; for(i=2; i<=BNU_CHUNK_BITS; i++, x<<=1) { BNU_CHUNK_T rH, rL; MUL_AB(rH, rL, m0, y); if( x < (rL & mask) ) /* x < ((m0*y) mod (2*x)) */ y+=x; mask += mask + 1; } return 0-y; } cryptography-primitives-1.0.0/sources/ippcp/gsmod_montinv.c000066400000000000000000000042621470420105600242640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // gs_mont_inv() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcpmask_ct.h" __IPPCP_INLINE BNU_CHUNK_T* cpPow2_ct(int bit, BNU_CHUNK_T* dst, int len) { int slot = bit/BNU_CHUNK_BITS; BNU_CHUNK_T value = (BNU_CHUNK_T)1 << (bit%BNU_CHUNK_BITS); int i; len -= (int)( cpIsEqu_ct((BNU_CHUNK_T)slot, (BNU_CHUNK_T)len) ); for(i=0; imul; BNU_CHUNK_T* t = gsModPoolAlloc(pME, 1); if(NULL == t) return NULL; if(k <= m) { mon_mul(pr, pr, MOD_MNT_R2(pME), pME); k += m; } //ZEXPAND_BNU(t, 0, mLen); //SET_BIT(t, 2*m-k); /* t = 2^(2*m-k) */ cpPow2_ct(2*m-k, t, mLen); mon_mul(pr, pr, t, pME); gsModPoolFree(pME, 1); return pr; } } cryptography-primitives-1.0.0/sources/ippcp/gsmod_packctx.c000066400000000000000000000033551470420105600242310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // gsPackModEngineCtx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcptool.h" /* // Pack/Unpack methods */ IPP_OWN_DEFN (void, gsPackModEngineCtx, (const gsModEngine* pCtx, Ipp8u* pBuffer)) { gsModEngine* pB = (gsModEngine*)pBuffer; /* max modulus length */ int modSize = MOD_LEN(pCtx); /* size of context (bytes) without cube and pool buffers */ int ctxSize = (Ipp32s)sizeof(gsModEngine) +(Ipp32s)sizeof(BNU_CHUNK_T)*(modSize*3); CopyBlock(pCtx, pB, ctxSize); MOD_MODULUS(pB) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(MOD_MODULUS(pCtx))-IPP_UINT_PTR(pCtx)); MOD_MNT_R(pB) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(MOD_MNT_R(pCtx))-IPP_UINT_PTR(pCtx)); MOD_MNT_R2(pB) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(MOD_MNT_R2(pCtx))-IPP_UINT_PTR(pCtx)); } cryptography-primitives-1.0.0/sources/ippcp/gsmod_unpackctx.c000066400000000000000000000034301470420105600245660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. Modular Arithmetic Engine. General Functionality // // Contents: // gsUnpackModEngineCtx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "pcptool.h" IPP_OWN_DEFN (void, gsUnpackModEngineCtx, (const Ipp8u* pBuffer, gsModEngine* pCtx)) { gsModEngine* pAlignedBuffer = (gsModEngine*)pBuffer; /* max modulus length */ int modSize = MOD_LEN(pAlignedBuffer); /* size of context (bytes) without cube and pool buffers */ int ctxSize = (Ipp32s)sizeof(gsModEngine) +(Ipp32s)sizeof(BNU_CHUNK_T)*(modSize*3); CopyBlock(pAlignedBuffer, pCtx, ctxSize); MOD_MODULUS(pCtx) = (BNU_CHUNK_T*)((Ipp8u*)pCtx + IPP_UINT_PTR(MOD_MODULUS(pAlignedBuffer))); MOD_MNT_R(pCtx) = (BNU_CHUNK_T*)((Ipp8u*)pCtx + IPP_UINT_PTR(MOD_MNT_R(pAlignedBuffer))); MOD_MNT_R2(pCtx) = (BNU_CHUNK_T*)((Ipp8u*)pCtx + IPP_UINT_PTR(MOD_MNT_R2(pAlignedBuffer))); MOD_POOL_BUF(pCtx) = MOD_MNT_R2(pCtx) + modSize; } cryptography-primitives-1.0.0/sources/ippcp/gsmodmethod.c000066400000000000000000000031671470420105600237160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "gsmodmethodstuff.h" /* methods */ static gsModMethod* gsModArith_C(void) { static gsModMethod m = { gs_mont_encode, gs_mont_decode, gs_mont_mul, gs_mont_sqr, gs_mont_red, gs_mont_add, gs_mont_sub, gs_mont_neg, gs_mont_div2, gs_mont_mul2, gs_mont_mul3, }; return &m; } #if (_IPP32E>=_IPP32E_L9) static gsModMethod* gsModArith_X(void) { static gsModMethod m = { gs_mont_encodeX, gs_mont_decodeX, gs_mont_mulX, gs_mont_sqrX, gs_mont_redX, gs_mont_add, gs_mont_sub, gs_mont_neg, gs_mont_div2, gs_mont_mul2, gs_mont_mul3, }; return &m; } #endif IPP_OWN_DEFN (gsModMethod*, gsModArith, (void)) { #if (_IPP32E>=_IPP32E_L9) if(IsFeatureEnabled(ippCPUID_ADCOX)) return gsModArith_X(); else #endif return gsModArith_C(); } cryptography-primitives-1.0.0/sources/ippcp/gsmodmethod.h000066400000000000000000000075031470420105600237210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ #if !defined(_GS_MOD_METHOD_H) #define _GS_MOD_METHOD_H //#include "owndefs.h" #include "owncp.h" #include "pcpbnuimpl.h" //#include "gsmodstuff.h" typedef struct _gsModEngine gsEngine; /* modular arith methods */ IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_encode, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_decode, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_red, (BNU_CHUNK_T* pR, BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_sqr, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_mul, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_add, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_sub, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_neg, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_div2, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_mul2, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) IPP_OWN_FUNPTR (BNU_CHUNK_T*, mod_mul3, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsEngine* pMA)) typedef struct _gsModMethod { mod_encode encode; mod_decode decode; mod_mul mul; mod_sqr sqr; mod_red red; mod_add add; mod_sub sub; mod_neg neg; mod_div2 div2; mod_mul2 mul2; mod_mul3 mul3; } gsModMethod; /* These functions should not be used, because they have non-constant execution time, see their safe analogues in pcpmask_ct.h */ #if 0 __IPPCP_INLINE BNU_CHUNK_T cpIsZero(BNU_CHUNK_T x) { return x==0; } __IPPCP_INLINE BNU_CHUNK_T cpIsNonZero(BNU_CHUNK_T x) { return x!=0; } __IPPCP_INLINE BNU_CHUNK_T cpIsOdd(BNU_CHUNK_T x) { return x&1; } __IPPCP_INLINE BNU_CHUNK_T cpIsEven(BNU_CHUNK_T x) { return 1-cpIsOdd(x); } /* dst[] = (flag)? src[] : dst[] */ __IPPCP_INLINE void cpMaskMove_gs(BNU_CHUNK_T* dst, const BNU_CHUNK_T* src, int len, BNU_CHUNK_T moveFlag) { BNU_CHUNK_T srcMask = 0-cpIsNonZero(moveFlag); BNU_CHUNK_T dstMask = ~srcMask; int n; for(n=0; n=_IPP32E_L9) static gsModMethod* gsModArithDLP_X(void) { static gsModMethod m = { gs_mont_encodeX, gs_mont_decodeX, gs_mont_mulX, gs_mont_sqrX, gs_mont_redX, NULL, NULL, NULL, NULL, NULL, NULL, }; return &m; } #endif IPP_OWN_DEFN (gsModMethod*, gsModArithDLP, (void)) { #if (_IPP32E>=_IPP32E_L9) if(IsFeatureEnabled(ippCPUID_ADCOX)) return gsModArithDLP_X(); else #endif return gsModArithDLP_C(); } /* ******************************************** */ cryptography-primitives-1.0.0/sources/ippcp/gsmodmethod_gfp.c000066400000000000000000000032271470420105600245470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "gsmodmethodstuff.h" /* methods */ /* ******************************************** */ static gsModMethod* gsArithGFp_C(void) { static gsModMethod m = { gs_mont_encode, gs_mont_decode, gs_mont_mul, gs_mont_sqr, NULL, gs_mont_add, gs_mont_sub, gs_mont_neg, gs_mont_div2, gs_mont_mul2, gs_mont_mul3, }; return &m; } #if (_IPP32E>=_IPP32E_L9) static gsModMethod* gsArithGFp_X(void) { static gsModMethod m = { gs_mont_encode, gs_mont_decode, gs_mont_mul, gs_mont_sqr, NULL, gs_mont_add, gs_mont_sub, gs_mont_neg, gs_mont_div2, gs_mont_mul2, gs_mont_mul3, }; return &m; } #endif IPP_OWN_DEFN (gsModMethod*, gsArithGFp, (void)) { #if (_IPP32E>=_IPP32E_L9) if(IsFeatureEnabled(ippCPUID_ADCOX)) return gsArithGFp_X(); else #endif return gsArithGFp_C(); } cryptography-primitives-1.0.0/sources/ippcp/gsmodmethod_mont.c000066400000000000000000000032101470420105600247400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "gsmodmethodstuff.h" /* methods */ /* ******************************************** */ static gsModMethod* gsModArithMont_C(void) { static gsModMethod m = { gs_mont_encode, gs_mont_decode, gs_mont_mul, gs_mont_sqr, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; return &m; } #if (_IPP32E>=_IPP32E_L9) static gsModMethod* gsModArithMont_X(void) { static gsModMethod m = { gs_mont_encodeX, gs_mont_decodeX, gs_mont_mulX, gs_mont_sqrX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; return &m; } #endif IPP_OWN_DEFN (gsModMethod*, gsModArithMont, (void)) { #if (_IPP32E>=_IPP32E_L9) if(IsFeatureEnabled(ippCPUID_ADCOX)) return gsModArithMont_X(); else #endif return gsModArithMont_C(); } /* ******************************************** */ cryptography-primitives-1.0.0/sources/ippcp/gsmodmethod_rsa.c000066400000000000000000000032401470420105600245530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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 "gsmodmethodstuff.h" /* methods */ /* ******************************************** */ static gsModMethod* gsModArithRSA_C(void) { static gsModMethod m = { gs_mont_encode, gs_mont_decode, gs_mont_mul, gs_mont_sqr, gs_mont_red, NULL, gs_mont_sub, NULL, NULL, NULL, NULL, }; return &m; } #if (_IPP32E>=_IPP32E_L9) static gsModMethod* gsModArithRSA_X(void) { static gsModMethod m = { gs_mont_encodeX, gs_mont_decodeX, gs_mont_mulX, gs_mont_sqrX, gs_mont_redX, NULL, gs_mont_sub, NULL, NULL, NULL, NULL, }; return &m; } #endif IPP_OWN_DEFN (gsModMethod*, gsModArithRSA, (void)) { #if (_IPP32E>=_IPP32E_L9) if(IsFeatureEnabled(ippCPUID_ADCOX)) return gsModArithRSA_X(); else #endif return gsModArithRSA_C(); } /* ******************************************** */ cryptography-primitives-1.0.0/sources/ippcp/gsmodmethodstuff.h000066400000000000000000000332301470420105600247650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ #if !defined(_GS_MOD_METHOD_STUFF_H) #define _GS_MOD_METHOD_STUFF_H #include "owndefs.h" #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnuarith.h" #include "gsmodstuff.h" #include "gsmodmethod.h" #include "pcpmontred.h" #include "pcpmask_ct.h" /* r = (a+m) mod m */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Length of pb data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_add, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, const BNU_CHUNK_T* pb, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); int mLen = MOD_LEN(pME); const int polLength = 1; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return NULL; { BNU_CHUNK_T extension = cpAdd_BNU(pr, pa, pb, mLen); extension -= cpSub_BNU(pBuffer, pr, pm, mLen); cpMaskedReplace_ct(pr, pBuffer, mLen, cpIsZero_ct(extension)); } gsModPoolFree(pME, polLength); return pr; } /* r = (a-b) mod m */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Length of pb data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_sub, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, const BNU_CHUNK_T* pb, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); int mLen = MOD_LEN(pME); const int polLength = 1; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return NULL; { BNU_CHUNK_T extension = cpSub_BNU(pr, pa, pb, mLen); cpAdd_BNU(pBuffer, pr, pm, mLen); cpMaskedReplace_ct(pr, pBuffer, mLen, ~cpIsZero_ct(extension)); } gsModPoolFree(pME, polLength); return pr; } /* r = (m-a) mod m */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_neg, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); int mLen = MOD_LEN(pME); const int polLength = 1; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return NULL; { BNU_CHUNK_T extension = cpSub_BNU(pr, pm, pa, mLen); extension -= cpSub_BNU(pBuffer, pr, pm, mLen); cpMaskedReplace_ct(pr, pBuffer, mLen, cpIsZero_ct(extension)); } gsModPoolFree(pME, polLength); return pr; } /* r = (a/2) mod m */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_div2, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); int mLen = MOD_LEN(pME); const int polLength = 1; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return NULL; { cpSize i; BNU_CHUNK_T mask = 0 - (pa[0]&1); for(i=0; i=_IPP32E_L9) IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_redX, (BNU_CHUNK_T* pr, BNU_CHUNK_T* prod, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T k0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); cpMontRedAdx_BNU(pr, prod, pm, mLen, k0); return pr; } #endif #endif /* r = (a*b) mod m */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Length of pb data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) * 2 */ #if ((_IPP <_IPP_W7) && (_IPP32E <_IPP32E_M7)) IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_mul, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, const BNU_CHUNK_T* pb, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T m0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); const int polLength = 1; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pME, polLength); if(NULL == pBuffer) return NULL; { BNU_CHUNK_T carry = 0; int i, j; /* clear buffer */ for(i=0; i=_IPP32E_L9) IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_mulX, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, const BNU_CHUNK_T* pb, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T m0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; cpMulAdx_BNU_school(pProduct, pa,mLen, pb,mLen); cpMontRedAdx_BNU(pr, pProduct, pm, mLen, m0); gsModPoolFree(pME, polLength); return pr; } #endif #endif /* r = (a^2) mod m */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_sqr, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { //return gs_mont_mul(pr, pa, pa, pME); const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T m0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; cpSqrAdc_BNU_school(pProduct, pa,mLen); cpMontRedAdc_BNU(pr, pProduct, pm, mLen, m0); gsModPoolFree(pME, polLength); return pr; } #if (_IPP32E>=_IPP32E_L9) IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_sqrX, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T m0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; cpSqrAdx_BNU_school(pProduct, pa,mLen); cpMontRedAdx_BNU(pr, pProduct, pm, mLen, m0); gsModPoolFree(pME, polLength); return pr; } #endif /* r = to_mont(a) */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_encode, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { //return gs_mont_mul(pr, pa, MOD_MNT_R2(pME), pME); const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T m0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; cpMulAdc_BNU_school(pProduct, pa,mLen, MOD_MNT_R2(pME),mLen); cpMontRedAdc_BNU(pr, pProduct, pm, mLen, m0); gsModPoolFree(pME, polLength); return pr; } #if (_IPP32E>=_IPP32E_L9) IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_encodeX, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { //return gs_mont_mul(pr, pa, MOD_MNT_R2(pME), pME); const BNU_CHUNK_T* pm = MOD_MODULUS(pME); BNU_CHUNK_T m0 = MOD_MNT_FACTOR(pME); int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; cpMulAdx_BNU_school(pProduct, pa,mLen, MOD_MNT_R2(pME),mLen); cpMontRedAdx_BNU(pr, pProduct, pm, mLen, m0); gsModPoolFree(pME, polLength); return pr; } #endif /* r = from_momt(a) */ /* * Requirements: * Length of pr data buffer: modLen * Length of pa data buffer: modLen * Memory size from the pool: modLen * sizeof(BNU_CHUNK_T) */ IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_decode, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; ZEXPAND_COPY_BNU(pProduct, 2*mLen, pa, mLen); cpMontRedAdc_BNU(pr, pProduct, MOD_MODULUS(pME), mLen, MOD_MNT_FACTOR(pME)); gsModPoolFree(pME, polLength); return pr; } #if (_IPP32E>=_IPP32E_L9) IPP_OWN_DEFN (static BNU_CHUNK_T*, gs_mont_decodeX, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pME)) { int mLen = MOD_LEN(pME); const int polLength = 2; BNU_CHUNK_T* pProduct = gsModPoolAlloc(pME, polLength); if(NULL == pProduct) return NULL; ZEXPAND_COPY_BNU(pProduct, 2*mLen, pa, mLen); cpMontRedAdx_BNU(pr, pProduct, MOD_MODULUS(pME), mLen, MOD_MNT_FACTOR(pME)); gsModPoolFree(pME, polLength); return pr; } #endif #endif /* _GS_MOD_METHOD_STUFF_H */ cryptography-primitives-1.0.0/sources/ippcp/gsmodstuff.h000066400000000000000000000135361470420105600235730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ #if !defined(_GS_MOD_STUFF_H) #define _GS_MOD_STUFF_H //#define MONTMUL_ONESTAGE #include "owncp.h" #include "pcpbnuimpl.h" #include "gsmodmethod.h" #define MOD_ENGINE_MIN_POOL_SIZE 1 typedef struct _gsModEngine gsModEngine_T; typedef struct _gsModEngine { gsModEngine_T* pParentME; /* pointer to parent stuff */ int extdegree; /* parent modulus extension (deg) */ int modBitLen; /* length of modulus in bits */ int modLen; /* length of modulus (BNU_CHUNK_T) */ int modLen32; /* length of modulus (Ipp32u) */ int peLen; /* length of pool element (BNU_CHUNK_T) */ const gsModMethod* method; /* modular arithmetic methods - regular radix */ const void* method_alt; /* modular arithmetic methods - alternative radix implementation */ BNU_CHUNK_T* pModulus; /* modulus */ BNU_CHUNK_T k0; /* low word of (1/modulus) mod R */ BNU_CHUNK_T* pMontR; /* mont_enc(1) */ BNU_CHUNK_T* pMontR2; /* mont_enc(1)^2 */ BNU_CHUNK_T* pHalfModulus; /* modulus/2 */ BNU_CHUNK_T* pQnr; /* quadratic non-residue */ int poolLenUsed; /* number of reserved temporary BNU */ int poolLen; /* max number of temporary BNU */ BNU_CHUNK_T* pBuffer; /* buffer of modLen*nBuffers length */ } gsModEngine; /* accessory macros */ #define MOD_PARENT(eng) ((eng)->pParentME) #define MOD_EXTDEG(eng) ((eng)->extdegree) #define MOD_BITSIZE(eng) ((eng)->modBitLen) #define MOD_LEN(eng) ((eng)->modLen) #define MOD_LEN32(eng) ((eng)->modLen32) #define MOD_PELEN(eng) ((eng)->peLen) #define MOD_METHOD(eng) ((eng)->method) #define MOD_METHOD_ALT(eng) ((eng)->method_alt) #define MOD_MODULUS(eng) ((eng)->pModulus) #define MOD_MNT_FACTOR(eng) ((eng)->k0) #define MOD_MNT_R(eng) ((eng)->pMontR) #define MOD_MNT_R2(eng) ((eng)->pMontR2) #define MOD_HMODULUS(eng) ((eng)->pHalfModulus) #define MOD_QNR(eng) ((eng)->pQnr) #define MOD_POOL_BUF(eng) ((eng)->pBuffer) #define MOD_MAXPOOL(eng) ((eng)->poolLen) #define MOD_USEDPOOL(eng) ((eng)->poolLenUsed) #define MOD_BUFFER(eng,n) ((eng)->pBuffer+(MOD_PELEN(eng))*(n)) #define MOD_ENGINE_ALIGNMENT ((int)sizeof(void*)) /* // size of context and it initialization */ #define gsModEngineInit OWNAPI(gsModEngineInit) IPP_OWN_DECL (IppStatus, gsModEngineInit, (gsModEngine* pME, const Ipp32u* pModulus, int modulusBitSize, int numpe, const gsModMethod* method)) #define gsModEngineGetSize OWNAPI(gsModEngineGetSize) IPP_OWN_DECL (IppStatus, gsModEngineGetSize, (int modulusBitSIze, int numpe, int* pSize)) #define gsMontFactor OWNAPI(gsMontFactor) IPP_OWN_DECL (BNU_CHUNK_T, gsMontFactor, (BNU_CHUNK_T m0)) /* // pool management methods */ /*F* // Name: gsModPoolAlloc // // Purpose: Allocation pool. // // Returns: Reason: // pointer to allocate Pool enough of pool // NULL required pool more than pME have // // Parameters: // pME ModEngine // poolReq Required pool *F*/ __IPPCP_INLINE BNU_CHUNK_T* gsModPoolAlloc(gsModEngine* pME, int poolReq) { BNU_CHUNK_T* pPool = MOD_BUFFER(pME, pME->poolLenUsed); if(pME->poolLenUsed + poolReq > pME->poolLen) pPool = NULL; else pME->poolLenUsed += poolReq; return pPool; } /*F* // Name: gsModPoolFree // // Purpose: Delete pool. // // Returns: // nothing // // Parameters: // pME ModEngine // poolReq Required pool *F*/ __IPPCP_INLINE void gsModPoolFree(gsModEngine* pME, int poolReq) { if(pME->poolLenUsed < poolReq) poolReq = pME->poolLenUsed; pME->poolLenUsed -= poolReq; } /* return pointer to the top pool buffer */ #define gsModGetPool OWNAPI(gsModGetPool) IPP_OWN_DECL (BNU_CHUNK_T*, gsModGetPool, (gsModEngine* pME)) /* // advanced operations */ IPP_OWN_FUNPTR (int, alm_inv, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pMA)) #define alm_mont_inv OWNAPI(alm_mont_inv) IPP_OWN_DECL (int, alm_mont_inv, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pMA)) #define alm_mont_inv_ct OWNAPI(alm_mont_inv_ct) IPP_OWN_DECL (int, alm_mont_inv_ct, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pMA)) #define gs_mont_inv OWNAPI(gs_mont_inv) IPP_OWN_DECL (BNU_CHUNK_T*, gs_mont_inv, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pMA, alm_inv invf)) #define gs_inv OWNAPI(gs_inv) IPP_OWN_DECL (BNU_CHUNK_T*, gs_inv, (BNU_CHUNK_T* pr, const BNU_CHUNK_T* pa, gsModEngine* pMA, alm_inv invf)) /* // Pack/Unpack methods */ #define gsPackModEngineCtx OWNAPI(gsPackModEngineCtx) IPP_OWN_DECL (void, gsPackModEngineCtx, (const gsModEngine* pCtx, Ipp8u* pBuffer)) #define gsUnpackModEngineCtx OWNAPI(gsUnpackModEngineCtx) IPP_OWN_DECL (void, gsUnpackModEngineCtx, (const Ipp8u* pBuffer, gsModEngine* pCtx)) #endif /* _GS_MOD_STUFF_H */ cryptography-primitives-1.0.0/sources/ippcp/gsscramble.c000066400000000000000000000033731470420105600235250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Fixed window exponentiation scramble/unscramble // // Contents: // gsScramblePut() // gsScrambleGet() // */ #include "owncp.h" #include "gsscramble.h" IPP_OWN_DEFN (int, gsGetScrambleBufferSize, (int modulusLen, int w)) { /* size of resource to store 2^w values of modulusLen*sizeof(BNU_CHUNK_T) each */ int size = (1<=_IPP_G9) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) /* // Magic functions defined in RFC 1321 // */ #define F(X,Y,Z) ((Z) ^ ((X) & ((Y) ^ (Z)))) /* slightly optimized form of (((X) & (Y)) | ((~(X) & (Z)))*/ #define G(X,Y,Z) F((Z),(X),(Y)) /* replace the original (((X) & (Z)) | ((Y) & ~(Z))) */ #define H(X,Y,Z) ((X) ^ (Y) ^ (Z)) #define I(X,Y,Z) ((Y) ^ ((X) | ~(Z))) /* // MD5 step */ #define MD5_STEP(MAGIC, A,B,C,D, data, constant, nrot) \ (A = B +ROL32((A +MAGIC(B,C,D) +data +constant), nrot)) /* // MD5 left rotations (number of bits) // depends on round type */ #define F1 7 #define F2 12 #define F3 17 #define F4 22 #define G1 5 #define G2 9 #define G3 14 #define G4 20 #define H1 4 #define H2 11 #define H3 16 #define H4 23 #define I1 6 #define I2 10 #define I3 15 #define I4 21 /*F* // Name: UpdateMD5 // // Purpose: Update internal hash according to input message stream. // // Parameters: // uniHash pointer to in/out hash // mblk pointer to message stream // mlen message stream length (multiple by message block size) // uniParam pointer to the optional parameter // *F*/ IPP_OWN_DEFN (void, UpdateMD5, (void* uinHash, const Ipp8u* mblk, int mlen, const void* uniParam)) { Ipp32u* digest = (Ipp32u*)uinHash; Ipp32u* MD5_cnt_loc = (Ipp32u*)uniParam; for(; mlen>=MBS_MD5; mblk += MBS_MD5, mlen -= MBS_MD5) { /* allocate data */ #if (IPP_ENDIAN == IPP_BIG_ENDIAN) Ipp32u data[MBS_MD5/sizeof(Ipp32u)]; #else /* or just word alias */ Ipp32u* data = (Ipp32u*)mblk; #endif /* init variables */ Ipp32u a = digest[0]; Ipp32u b = digest[1]; Ipp32u c = digest[2]; Ipp32u d = digest[3]; #if (IPP_ENDIAN == IPP_BIG_ENDIAN) int t; for(t=0; t<16; t++) { data[t] = ENDIANNESS(((Ipp32u*)mblk)[t]); } #endif /* rounds type F */ MD5_STEP(F, a,b,c,d, data[ 0], MD5_cnt_loc[ 0], F1); MD5_STEP(F, d,a,b,c, data[ 1], MD5_cnt_loc[ 1], F2); MD5_STEP(F, c,d,a,b, data[ 2], MD5_cnt_loc[ 2], F3); MD5_STEP(F, b,c,d,a, data[ 3], MD5_cnt_loc[ 3], F4); MD5_STEP(F, a,b,c,d, data[ 4], MD5_cnt_loc[ 4], F1); MD5_STEP(F, d,a,b,c, data[ 5], MD5_cnt_loc[ 5], F2); MD5_STEP(F, c,d,a,b, data[ 6], MD5_cnt_loc[ 6], F3); MD5_STEP(F, b,c,d,a, data[ 7], MD5_cnt_loc[ 7], F4); MD5_STEP(F, a,b,c,d, data[ 8], MD5_cnt_loc[ 8], F1); MD5_STEP(F, d,a,b,c, data[ 9], MD5_cnt_loc[ 9], F2); MD5_STEP(F, c,d,a,b, data[10], MD5_cnt_loc[10], F3); MD5_STEP(F, b,c,d,a, data[11], MD5_cnt_loc[11], F4); MD5_STEP(F, a,b,c,d, data[12], MD5_cnt_loc[12], F1); MD5_STEP(F, d,a,b,c, data[13], MD5_cnt_loc[13], F2); MD5_STEP(F, c,d,a,b, data[14], MD5_cnt_loc[14], F3); MD5_STEP(F, b,c,d,a, data[15], MD5_cnt_loc[15], F4); /* rounds type G */ MD5_STEP(G, a,b,c,d, data[ 1], MD5_cnt_loc[16], G1); MD5_STEP(G, d,a,b,c, data[ 6], MD5_cnt_loc[17], G2); MD5_STEP(G, c,d,a,b, data[11], MD5_cnt_loc[18], G3); MD5_STEP(G, b,c,d,a, data[ 0], MD5_cnt_loc[19], G4); MD5_STEP(G, a,b,c,d, data[ 5], MD5_cnt_loc[20], G1); MD5_STEP(G, d,a,b,c, data[10], MD5_cnt_loc[21], G2); MD5_STEP(G, c,d,a,b, data[15], MD5_cnt_loc[22], G3); MD5_STEP(G, b,c,d,a, data[ 4], MD5_cnt_loc[23], G4); MD5_STEP(G, a,b,c,d, data[ 9], MD5_cnt_loc[24], G1); MD5_STEP(G, d,a,b,c, data[14], MD5_cnt_loc[25], G2); MD5_STEP(G, c,d,a,b, data[ 3], MD5_cnt_loc[26], G3); MD5_STEP(G, b,c,d,a, data[ 8], MD5_cnt_loc[27], G4); MD5_STEP(G, a,b,c,d, data[13], MD5_cnt_loc[28], G1); MD5_STEP(G, d,a,b,c, data[ 2], MD5_cnt_loc[29], G2); MD5_STEP(G, c,d,a,b, data[ 7], MD5_cnt_loc[30], G3); MD5_STEP(G, b,c,d,a, data[12], MD5_cnt_loc[31], G4); /* rounds type H */ MD5_STEP(H, a,b,c,d, data[ 5], MD5_cnt_loc[32], H1); MD5_STEP(H, d,a,b,c, data[ 8], MD5_cnt_loc[33], H2); MD5_STEP(H, c,d,a,b, data[11], MD5_cnt_loc[34], H3); MD5_STEP(H, b,c,d,a, data[14], MD5_cnt_loc[35], H4); MD5_STEP(H, a,b,c,d, data[ 1], MD5_cnt_loc[36], H1); MD5_STEP(H, d,a,b,c, data[ 4], MD5_cnt_loc[37], H2); MD5_STEP(H, c,d,a,b, data[ 7], MD5_cnt_loc[38], H3); MD5_STEP(H, b,c,d,a, data[10], MD5_cnt_loc[39], H4); MD5_STEP(H, a,b,c,d, data[13], MD5_cnt_loc[40], H1); MD5_STEP(H, d,a,b,c, data[ 0], MD5_cnt_loc[41], H2); MD5_STEP(H, c,d,a,b, data[ 3], MD5_cnt_loc[42], H3); MD5_STEP(H, b,c,d,a, data[ 6], MD5_cnt_loc[43], H4); MD5_STEP(H, a,b,c,d, data[ 9], MD5_cnt_loc[44], H1); MD5_STEP(H, d,a,b,c, data[12], MD5_cnt_loc[45], H2); MD5_STEP(H, c,d,a,b, data[15], MD5_cnt_loc[46], H3); MD5_STEP(H, b,c,d,a, data[ 2], MD5_cnt_loc[47], H4); /* rounds type I */ MD5_STEP(I, a,b,c,d, data[ 0], MD5_cnt_loc[48], I1); MD5_STEP(I, d,a,b,c, data[ 7], MD5_cnt_loc[49], I2); MD5_STEP(I, c,d,a,b, data[14], MD5_cnt_loc[50], I3); MD5_STEP(I, b,c,d,a, data[ 5], MD5_cnt_loc[51], I4); MD5_STEP(I, a,b,c,d, data[12], MD5_cnt_loc[52], I1); MD5_STEP(I, d,a,b,c, data[ 3], MD5_cnt_loc[53], I2); MD5_STEP(I, c,d,a,b, data[10], MD5_cnt_loc[54], I3); MD5_STEP(I, b,c,d,a, data[ 1], MD5_cnt_loc[55], I4); MD5_STEP(I, a,b,c,d, data[ 8], MD5_cnt_loc[56], I1); MD5_STEP(I, d,a,b,c, data[15], MD5_cnt_loc[57], I2); MD5_STEP(I, c,d,a,b, data[ 6], MD5_cnt_loc[58], I3); MD5_STEP(I, b,c,d,a, data[13], MD5_cnt_loc[59], I4); MD5_STEP(I, a,b,c,d, data[ 4], MD5_cnt_loc[60], I1); MD5_STEP(I, d,a,b,c, data[11], MD5_cnt_loc[61], I2); MD5_STEP(I, c,d,a,b, data[ 2], MD5_cnt_loc[62], I3); MD5_STEP(I, b,c,d,a, data[ 9], MD5_cnt_loc[63], I4); /* update digest */ digest[0] += a; digest[1] += b; digest[2] += c; digest[3] += d; } } #endif #endif /* IPP_ALG_HASH_MD5 */ cryptography-primitives-1.0.0/sources/ippcp/hash/md5/pcphashmethod_md5.c000066400000000000000000000032671470420105600264110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to MD5 // (derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm) // // Equivalent code is available from RFC 1321. // // Contents: // ippsHashMethod_MD5() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/md5/pcpmd5stuff.h" /*F* // Name: ippsHashMethod_MD5 // // Purpose: Return MD5 method. // // Returns: // Pointer to MD5 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_MD5, (void) ) { static IppsHashMethod method = { ippHashAlg_MD5, IPP_MD5_DIGEST_BITSIZE/8, MBS_MD5, MLR_MD5, 0, 0, 0, 0 }; method.hashInit = md5_hashInit; method.hashUpdate = md5_hashUpdate; method.hashOctStr = md5_hashOctString; method.msgLenRep = md5_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/md5/pcphashmethodset_md5.c000066400000000000000000000035431470420105600271220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to MD5 // (derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm) // // Equivalent code is available from RFC 1321. // // Contents: // ippsHashMethodSet_MD5() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/md5/pcpmd5stuff.h" /*F* // Name: ippsHashMethodSet_MD5 // // Purpose: Setup MD5 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_MD5, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_MD5; pMethod->hashLen = IPP_MD5_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_MD5; pMethod->msgLenRepSize = MLR_MD5; pMethod->hashInit = md5_hashInit; pMethod->hashUpdate = md5_hashUpdate; pMethod->hashOctStr = md5_hashOctString; pMethod->msgLenRep = md5_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/md5/pcpmd5ca.c000066400000000000000000000035471470420105600245120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to MD5 // (derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm) // // Equivalent code is available from RFC 1321. // // Contents: // cpFinalizeMD5() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/md5/pcpmd5stuff.h" /* // Compute digest */ IPP_OWN_DEFN (void, cpFinalizeMD5, (DigestMD5 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) { /* local buffer and it length */ Ipp8u buffer[MBS_MD5*2]; int bufferLen = inpLen < (MBS_MD5-(int)MLR_MD5)? MBS_MD5 : MBS_MD5*2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, (cpSize)inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer+inpLen, (cpSize)(bufferLen-inpLen-(int)MLR_MD5)); /* put processed message length in bits */ processedMsgLen <<= 3; ((Ipp64u*)(buffer+bufferLen))[-1] = processedMsgLen; /* copmplete hash computation */ UpdateMD5(pHash, buffer, bufferLen, MD5_cnt); } cryptography-primitives-1.0.0/sources/ippcp/hash/md5/pcpmd5stuff.h000066400000000000000000000062741470420105600252630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to MD5 // (derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm) // // Equivalent code is available from RFC 1321. // // Contents: // MD4 methods and constants // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #if !defined(_PCP_MD5_STUFF_H) #define _PCP_MD5_STUFF_H /* MD5 constants */ static const Ipp32u md5_iv[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476}; static __ALIGN16 const Ipp32u md5_cnt[] = { 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 }; IPP_OWN_DEFN (static void, md5_hashInit, (void* pHash)) { /* setup initial digest */ ((Ipp32u*)pHash)[0] = md5_iv[0]; ((Ipp32u*)pHash)[1] = md5_iv[1]; ((Ipp32u*)pHash)[2] = md5_iv[2]; ((Ipp32u*)pHash)[3] = md5_iv[3]; } IPP_OWN_DEFN (static void, md5_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateMD5(pHash, pMsg, msgLen, md5_cnt); } IPP_OWN_DEFN (static void, md5_hashOctString, (Ipp8u* pMD, void* pHashVal)) { /* md5 does not need conversion into big endian */ ((Ipp32u*)pMD)[0] = ((Ipp32u*)pHashVal)[0]; ((Ipp32u*)pMD)[1] = ((Ipp32u*)pHashVal)[1]; ((Ipp32u*)pMD)[2] = ((Ipp32u*)pHashVal)[2]; ((Ipp32u*)pMD)[3] = ((Ipp32u*)pHashVal)[3]; } IPP_OWN_DEFN (static void, md5_msgRep, (Ipp8u* pDst, Ipp64u lenLo, Ipp64u lenHi)) { IPP_UNREFERENCED_PARAMETER(lenHi); lenLo <<= 3; ((Ipp64u*)(pDst))[0] = lenLo; } #define cpFinalizeMD5 OWNAPI(cpFinalizeMD5) IPP_OWN_DECL (void, cpFinalizeMD5, (DigestMD5 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) #endif /* #if !defined(_PCP_MD5_STUFF_H) */ cryptography-primitives-1.0.0/sources/ippcp/hash/pcphash.h000066400000000000000000000226351470420105600237630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Internal Definitions and Internal Functions Prototypes // // */ #if !defined(_PCP_HASH_H) #define _PCP_HASH_H /* message block size */ #define MBS_SHA1 (64) /* SHA1 message block size (bytes) */ #define MBS_SHA256 (64) /* SHA256 and SHA224 */ #define MBS_SHA224 (64) /* SHA224 */ #define MBS_SHA512 (128) /* SHA512 and SHA384 */ #define MBS_SHA384 (128) /* SHA384 */ #define MBS_MD5 (64) /* MD5 */ #define MBS_SM3 (64) /* SM3 */ #define MBS_HASH_MAX (MBS_SHA512) /* max message block size (bytes) */ #define MAX_HASH_SIZE (IPP_SHA512_DIGEST_BITSIZE/8) /* hash of the max len (bytes) */ /* size of processed message length representation (bytes) */ #define MLR_SHA1 (sizeof(Ipp64u)) #define MLR_SHA256 (sizeof(Ipp64u)) #define MLR_SHA224 (sizeof(Ipp64u)) #define MLR_SHA512 (sizeof(Ipp64u)*2) #define MLR_SHA384 (sizeof(Ipp64u)*2) #define MLR_MD5 (sizeof(Ipp64u)) #define MLR_SM3 (sizeof(Ipp64u)) /* hold some old definition for a purpose */ typedef Ipp32u DigestSHA1[5]; /* SHA1 digest */ typedef Ipp32u DigestSHA224[7]; /* SHA224 digest */ typedef Ipp32u DigestSHA256[8]; /* SHA256 digest */ typedef Ipp64u DigestSHA384[6]; /* SHA384 digest */ typedef Ipp64u DigestSHA512[8]; /* SHA512 digest */ typedef Ipp32u DigestMD5[4]; /* MD5 digest */ typedef Ipp32u DigestSM3[8]; /* SM3 digest */ #define HASH_ALIGNMENT ((int)(sizeof(void*))) #define SHA1_ALIGNMENT HASH_ALIGNMENT #define SHA224_ALIGNMENT HASH_ALIGNMENT #define SHA256_ALIGNMENT HASH_ALIGNMENT #define SHA384_ALIGNMENT HASH_ALIGNMENT #define SHA512_ALIGNMENT HASH_ALIGNMENT #define MD5_ALIGNMENT HASH_ALIGNMENT #define SM3_ALIGNMENT HASH_ALIGNMENT struct _cpSHA1 { Ipp32u idCtx; /* SHA1 identifier */ int msgBuffIdx; /* buffer entry */ Ipp64u msgLenLo; /* message length (bytes) */ Ipp8u msgBuffer[MBS_SHA1]; /* buffer */ DigestSHA1 msgHash; /* intermediate hash */ }; struct _cpSHA256 { Ipp32u idCtx; /* SHA224 identifier */ int msgBuffIdx; /* buffer entry */ Ipp64u msgLenLo; /* message length */ Ipp8u msgBuffer[MBS_SHA256]; /* buffer */ DigestSHA256 msgHash; /* intermediate hash */ }; struct _cpSHA512 { Ipp32u idCtx; /* SHA384 identifier */ int msgBuffIdx; /* buffer entry */ Ipp64u msgLenLo; /* message length */ Ipp64u msgLenHi; /* message length */ Ipp8u msgBuffer[MBS_SHA512]; /* buffer */ DigestSHA512 msgHash; /* intermediate hash */ }; struct _cpMD5 { Ipp32u idCtx; /* MD5 identifier */ int msgBuffIdx; /* buffer entry */ Ipp64u msgLenLo; /* message length */ Ipp8u msgBuffer[MBS_MD5]; /* buffer */ DigestMD5 msgHash; /* intermediate hash */ }; struct _cpSM3 { Ipp32u idCtx; /* SM3 identifier */ int msgBuffIdx; /* buffer entry */ Ipp64u msgLenLo; /* message length */ Ipp8u msgBuffer[MBS_SM3]; /* buffer */ DigestSM3 msgHash; /* intermediate hash */ }; /* hash alg attributes */ typedef struct _cpHashAttr { int ivSize; /* attr: length (bytes) of initial value cpHashIV */ int hashSize; /* attr: length (bytes) of hash */ int msgBlkSize; /* attr: length (bytes) of message block */ int msgLenRepSize; /* attr: length (bytes) in representation of processed message length */ Ipp64u msgLenMax[2]; /* attr: max message length (bytes) (low high) */ } cpHashAttr; /* hash value */ typedef Ipp64u cpHash[IPP_SHA512_DIGEST_BITSIZE/BITSIZE(Ipp64u)]; /* hash value */ /* hash update function */ IPP_OWN_FUNPTR (void, cpHashProc, (void* pHash, const Ipp8u* pMsg, int msgLen, const void* pParam)) /* generalized hash context */ struct _cpHashCtx { Ipp32u idCtx; /* hash identifier */ IppHashAlgId algID; /* hash algorithm ID */ Ipp64u msgLenLo; /* processed message:*/ Ipp64u msgLenHi; /* length */ cpHashProc hashProc; /* hash update func */ const void* pParam; /* hashProc's params */ cpHash msgHash; /* intermadiate hash */ int msgBuffIdx; /* buffer entry */ Ipp8u msgBuffer[MBS_HASH_MAX]; /* buffer */ }; /* accessors */ #define HASH_SET_ID(stt,ctxid) ((stt)->idCtx = (Ipp32u)ctxid ^ (Ipp32u)IPP_UINT_PTR(stt)) #define HASH_RESET_ID(stt,ctxid) ((stt)->idCtx = (Ipp32u)ctxid) #define HASH_ALG_ID(stt) ((stt)->algID) #define HASH_LENLO(stt) ((stt)->msgLenLo) #define HASH_LENHI(stt) ((stt)->msgLenHi) #define HASH_FUNC(stt) ((stt)->hashProc) #define HASH_FUNC_PAR(stt) ((stt)->pParam) #define HASH_VALUE(stt) ((stt)->msgHash) #define HASH_BUFFIDX(stt) ((stt)->msgBuffIdx) #define HASH_BUFF(stt) ((stt)->msgBuffer) #define HASH_VALID_ID(stt,ctxId) ((((stt)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((stt))) == (Ipp32u)ctxId) /* initial hash values */ extern const Ipp32u SHA1_IV[]; extern const Ipp32u SHA256_IV[]; extern const Ipp32u SHA224_IV[]; extern const Ipp64u SHA512_IV[]; extern const Ipp64u SHA384_IV[]; extern const Ipp32u MD5_IV[]; extern const Ipp32u SM3_IV[]; extern const Ipp64u SHA512_224_IV[]; extern const Ipp64u SHA512_256_IV[]; /* hash alg additive constants */ extern __ALIGN16 const Ipp32u SHA1_cnt[]; extern __ALIGN16 const Ipp32u SHA256_cnt[]; extern __ALIGN16 const Ipp64u SHA512_cnt[]; extern __ALIGN16 const Ipp32u MD5_cnt[]; extern __ALIGN16 const Ipp32u SM3_cnt[]; /* hash alg opt argument */ extern const void* cpHashProcFuncOpt[]; /* enabled hash alg */ extern const IppHashAlgId cpEnabledHashAlgID[]; /* hash alg IV (init value) */ extern const Ipp8u* cpHashIV[]; /* hash alg attribute DB */ extern const cpHashAttr cpHashAlgAttr[]; /* IV size helper */ __IPPCP_INLINE int cpHashIvSize(IppHashAlgId algID) { return cpHashAlgAttr[algID].ivSize; } /* hash size helper */ __IPPCP_INLINE int cpHashSize(IppHashAlgId algID) { return cpHashAlgAttr[algID].hashSize; } /* message block size helper */ __IPPCP_INLINE int cpHashMBS(IppHashAlgId algID) { return cpHashAlgAttr[algID].msgBlkSize; } /* maps algID into enabled IppHashAlgId value */ __IPPCP_INLINE IppHashAlgId cpValidHashAlg(IppHashAlgId algID) { /* maps algID into the valid range */ algID = (((int)ippHashAlg_Unknown < (int)algID) && ((int)algID < (int)ippHashAlg_MaxNo))? algID : ippHashAlg_Unknown; return cpEnabledHashAlgID[algID]; } /* common functions */ #define cpComputeDigest OWNAPI(cpComputeDigest) IPP_OWN_DECL (void, cpComputeDigest, (Ipp8u* pHashTag, int hashTagLen, const IppsHashState* pCtx)) /* processing functions */ #define UpdateSHA1 OWNAPI(UpdateSHA1) IPP_OWN_DECL (void, UpdateSHA1, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #define UpdateSHA256 OWNAPI(UpdateSHA256) IPP_OWN_DECL (void, UpdateSHA256, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #define UpdateSHA512 OWNAPI(UpdateSHA512) IPP_OWN_DECL (void, UpdateSHA512, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #define UpdateMD5 OWNAPI(UpdateMD5) IPP_OWN_DECL (void, UpdateMD5, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #define UpdateSM3 OWNAPI(UpdateSM3) IPP_OWN_DECL (void, UpdateSM3, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #if (_SHA_NI_ENABLING_ == _FEATURE_TICKTOCK_) || (_SHA_NI_ENABLING_ == _FEATURE_ON_) #define UpdateSHA1ni OWNAPI(UpdateSHA1ni) IPP_OWN_DECL (void, UpdateSHA1ni, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #define UpdateSHA256ni OWNAPI(UpdateSHA256ni) IPP_OWN_DECL (void, UpdateSHA256ni, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) #endif #define UpdateSM3ni OWNAPI(UpdateSM3ni) IPP_OWN_DECL (void, UpdateSM3ni, (void* pHash, const Ipp8u* mblk, int mlen, const void* pParam)) /* general methods */ #define cpInitHash OWNAPI(cpInitHash) IPP_OWN_DECL (int, cpInitHash, (IppsHashState* pCtx, IppHashAlgId algID)) #define cpReInitHash OWNAPI(cpReInitHash) IPP_OWN_DECL (int, cpReInitHash, (IppsHashState* pCtx, IppHashAlgId algID)) #endif /* _PCP_HASH_H */ cryptography-primitives-1.0.0/sources/ippcp/hash/pcphash_digest.c000066400000000000000000000104131470420105600253040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // cpComputeDigest() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" IPP_OWN_DEFN (void, cpComputeDigest, (Ipp8u* pHashTag, int hashTagLen, const IppsHashState* pCtx)) { /* hash alg and parameters */ cpHashProc hashFunc = HASH_FUNC(pCtx); /* processing function */ const void* pParam = HASH_FUNC_PAR(pCtx); /* and it's addition params */ /* attributes */ const cpHashAttr* pAttr = &cpHashAlgAttr[HASH_ALG_ID(pCtx)]; int mbs = pAttr->msgBlkSize; /* data block size */ int ivSize = pAttr->ivSize; /* size of hash's IV */ int msgLenRepSize = pAttr->msgLenRepSize; /* length of the message representation */ /* number of bytes in context buffer */ int n = HASH_BUFFIDX(pCtx); /* buffer and it actual length */ Ipp8u buffer[MBS_HASH_MAX*2]; int bufferLen = n < (mbs-msgLenRepSize)? mbs : mbs*2; /* copy current hash value */ cpHash hash; CopyBlock(HASH_VALUE(pCtx), hash, ivSize); /* copy of state's buffer */ CopyBlock(HASH_BUFF(pCtx), buffer, n); /* end of message bit */ buffer[n++] = 0x80; /* pad buffer */ PadBlock(0, buffer+n, bufferLen-n-msgLenRepSize); /* message length representation in bits (remember about big endian) */ { /* convert processed message length bytes ->bits */ Ipp64u lo = HASH_LENLO(pCtx); Ipp64u hi = HASH_LENHI(pCtx); hi = LSL64(hi,3) | LSR64(lo,63-3); lo = LSL64(lo,3); if(msgLenRepSize>(int)(sizeof(Ipp64u))) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) ((Ipp64u*)(buffer+bufferLen))[-2] = hi; #else ((Ipp64u*)(buffer+bufferLen))[-2] = ENDIANNESS64(hi); #endif } /* recall about MD5 specific */ if(ippHashAlg_MD5!=HASH_ALG_ID(pCtx)) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) ((Ipp64u*)(buffer+bufferLen))[-1] = lo; #else ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lo); #endif } else { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lo); #else ((Ipp64u*)(buffer+bufferLen))[-1] = lo; #endif } } /* copmplete hash computation */ hashFunc(hash, buffer, bufferLen, pParam); /* store digest into the user buffer (remember digest in big endian) */ if(msgLenRepSize>(int)(sizeof(Ipp64u))) { /* ippHashAlg_SHA384, ippHashAlg_SHA512, ippHashAlg_SHA512_224 and ippHashAlg_SHA512_256 */ hash[0] = ENDIANNESS64(hash[0]); hash[1] = ENDIANNESS64(hash[1]); hash[2] = ENDIANNESS64(hash[2]); hash[3] = ENDIANNESS64(hash[3]); hash[4] = ENDIANNESS64(hash[4]); hash[5] = ENDIANNESS64(hash[5]); hash[6] = ENDIANNESS64(hash[6]); hash[7] = ENDIANNESS64(hash[7]); } else if(ippHashAlg_MD5!=HASH_ALG_ID(pCtx)) { ((Ipp32u*)hash)[0] = ENDIANNESS32(((Ipp32u*)hash)[0]); ((Ipp32u*)hash)[1] = ENDIANNESS32(((Ipp32u*)hash)[1]); ((Ipp32u*)hash)[2] = ENDIANNESS32(((Ipp32u*)hash)[2]); ((Ipp32u*)hash)[3] = ENDIANNESS32(((Ipp32u*)hash)[3]); ((Ipp32u*)hash)[4] = ENDIANNESS32(((Ipp32u*)hash)[4]); if(ippHashAlg_SHA1!=HASH_ALG_ID(pCtx)) { ((Ipp32u*)hash)[5] = ENDIANNESS32(((Ipp32u*)hash)[5]); ((Ipp32u*)hash)[6] = ENDIANNESS32(((Ipp32u*)hash)[6]); ((Ipp32u*)hash)[7] = ENDIANNESS32(((Ipp32u*)hash)[7]); } } CopyBlock(hash, pHashTag, hashTagLen); } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphash_func.h000066400000000000000000000042241470420105600247700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Internal Definitions and Internal Functions Prototypes // // */ #if !defined(_PCP_HASH_FUNC_H) #define _PCP_HASH_FUNC_H #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" /* // hash alg default processing functions and opt argument */ static cpHashProc cpHashProcFunc[] = { (cpHashProc)NULL, #if defined(_ENABLE_ALG_SHA1_) #if(_SHA_NI_ENABLING_==_FEATURE_ON_) UpdateSHA1ni, #else UpdateSHA1, #endif #else NULL, #endif #if defined(_ENABLE_ALG_SHA256_) #if(_SHA_NI_ENABLING_==_FEATURE_ON_) UpdateSHA256ni, #else UpdateSHA256, #endif #else NULL, #endif #if defined(_ENABLE_ALG_SHA224_) #if(_SHA_NI_ENABLING_==_FEATURE_ON_) UpdateSHA256ni, #else UpdateSHA256, #endif #else NULL, #endif #if defined(_ENABLE_ALG_SHA512_) UpdateSHA512, #else NULL, #endif #if defined(_ENABLE_ALG_SHA384_) UpdateSHA512, #else NULL, #endif #if defined(_ENABLE_ALG_MD5_) UpdateMD5, #else NULL, #endif #if defined(_ENABLE_ALG_SM3_) UpdateSM3, #else NULL, #endif #if defined(_ENABLE_ALG_SHA512_224_) UpdateSHA512, #else NULL, #endif #if defined(_ENABLE_ALG_SHA512_256_) UpdateSHA512, #else NULL, #endif }; #endif /* _PCP_HASH_FUNC_H */ cryptography-primitives-1.0.0/sources/ippcp/hash/pcphash_init.c000066400000000000000000000037541470420105600250020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // cpInitHash() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_func.h" #include "pcptool.h" IPP_OWN_DEFN (int, cpInitHash, (IppsHashState* pCtx, IppHashAlgId algID)) { /* setup default processing function */ HASH_FUNC(pCtx) = cpHashProcFunc[algID]; /* update default processing function if Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) enabled */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if( IsFeatureEnabled(ippCPUID_SHA) ) { #if defined(_ENABLE_ALG_SHA1_) if(ippHashAlg_SHA1==algID) HASH_FUNC(pCtx) = UpdateSHA1ni; #endif #if defined(_ENABLE_ALG_SHA256_) || defined(_ENABLE_ALG_SHA224_) if(ippHashAlg_SHA256==algID || ippHashAlg_SHA224==algID) HASH_FUNC(pCtx) = UpdateSHA256ni; #endif } #endif #if (_IPP32E >= _IPP32E_L9) if (ippHashAlg_SM3==algID && IsFeatureEnabled(ippCPUID_AVX2SM3)) { HASH_FUNC(pCtx) = UpdateSM3ni; } #endif /* setup optional agr of processing function */ HASH_FUNC_PAR(pCtx) = cpHashProcFuncOpt[algID]; return cpReInitHash(pCtx, algID); } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphash_reinit.c000066400000000000000000000032321470420105600253200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // cpReInitHash() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashInit // // Purpose: Init Hash state. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsNotSupportedModeErr if algID is not match to supported hash alg // ippStsNoErr no errors // // Parameters: // pCtx pointer to the Hash state // algID hash alg ID // *F*/ IPP_OWN_DEFN (int, cpReInitHash, (IppsHashState* pCtx, IppHashAlgId algID)) { int hashIvSize = cpHashIvSize(algID); const Ipp8u* iv = cpHashIV[algID]; HASH_LENLO(pCtx) = CONST_64(0); HASH_LENHI(pCtx) = CONST_64(0); HASH_BUFFIDX(pCtx) = 0; CopyBlock(iv, HASH_VALUE(pCtx), hashIvSize); return hashIvSize; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphash_rmf.h000066400000000000000000000034341470420105600246230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // Security Hash Standard // Internal Definitions and Internal Functions Prototypes // */ #if !defined(_CP_HASH_RMF_H) #define _CP_HASH_RMF_H #include "hash/pcphash.h" #include "hash/pcphashmethod_rmf.h" struct _cpHashCtx_rmf { Ipp32u idCtx; /* hash identifier */ const cpHashMethod_rmf* pMethod; /* hash methods */ int msgBuffIdx; /* buffer index */ Ipp8u msgBuffer[MBS_HASH_MAX]; /* buffer */ Ipp64u msgLenLo; /* processed message */ Ipp64u msgLenHi; /* length (bytes) */ cpHash msgHash; /* hash value */ }; /* accessors (see others in pcphash.h) */ #define HASH_METHOD(stt) ((stt)->pMethod) #define cpFinalize_rmf OWNAPI(cpFinalize_rmf) IPP_OWN_DECL (void, cpFinalize_rmf, (DigestSHA512 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u lenLo, Ipp64u lenHi, const IppsHashMethod* method)) #endif /* _CP_HASH_RMF_H */ cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashca_rmf.c000066400000000000000000000034161470420105600251220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // cpFinalize_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" IPP_OWN_DEFN (void, cpFinalize_rmf, (DigestSHA512 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u lenLo, Ipp64u lenHi, const IppsHashMethod* method)) { int mbs = method->msgBlkSize; /* message block size */ int mrl = method->msgLenRepSize; /* processed length representation size */ /* local buffer and it length */ Ipp8u buffer[MBS_SHA512*2]; int bufferLen = inpLen < (mbs-mrl)? mbs : mbs*2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer+inpLen, bufferLen-inpLen-mrl); /* message length representation */ method->msgLenRep(buffer+bufferLen-mrl, lenLo, lenHi); /* copmplete hash computation */ method->hashUpdate(pHash, buffer, bufferLen); } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashcnt.c000066400000000000000000000332641470420105600244630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Constants // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #if defined( _IPP_DATA ) /* // enabled hash alg IDs */ const IppHashAlgId cpEnabledHashAlgID[] = { IPP_ALG_HASH_UNKNOWN, #if defined(_ENABLE_ALG_SHA1_) IPP_ALG_HASH_SHA1, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SHA256_) IPP_ALG_HASH_SHA256, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SHA224_) IPP_ALG_HASH_SHA224, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SHA512_) IPP_ALG_HASH_SHA512, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SHA384_) IPP_ALG_HASH_SHA384, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_MD5_) IPP_ALG_HASH_MD5, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SM3_) IPP_ALG_HASH_SM3, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SHA512_224_) IPP_ALG_HASH_SHA512_224, #else IPP_ALG_HASH_UNKNOWN, #endif #if defined(_ENABLE_ALG_SHA512_256_) IPP_ALG_HASH_SHA512_256 #else IPP_ALG_HASH_UNKNOWN #endif }; //////////////////////////////////////////////////////////// /* // hash init values */ const Ipp32u UnknownHash_IV[] = { 0}; #if defined(_ENABLE_ALG_SHA1_) const Ipp32u SHA1_IV[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; #endif #if defined(_ENABLE_ALG_SHA256_) const Ipp32u SHA256_IV[] = { 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19}; #endif #if defined(_ENABLE_ALG_SHA224_) const Ipp32u SHA224_IV[] = { 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4}; #endif #if defined(_ENABLE_ALG_SHA512_) const Ipp64u SHA512_IV[] = { CONST_64(0x6A09E667F3BCC908), CONST_64(0xBB67AE8584CAA73B), CONST_64(0x3C6EF372FE94F82B), CONST_64(0xA54FF53A5F1D36F1), CONST_64(0x510E527FADE682D1), CONST_64(0x9B05688C2B3E6C1F), CONST_64(0x1F83D9ABFB41BD6B), CONST_64(0x5BE0CD19137E2179)}; #endif #if defined(_ENABLE_ALG_SHA384_) const Ipp64u SHA384_IV[] = { CONST_64(0xCBBB9D5DC1059ED8), CONST_64(0x629A292A367CD507), CONST_64(0x9159015A3070DD17), CONST_64(0x152FECD8F70E5939), CONST_64(0x67332667FFC00B31), CONST_64(0x8EB44A8768581511), CONST_64(0xDB0C2E0D64F98FA7), CONST_64(0x47B5481DBEFA4FA4)}; #endif #if defined(_ENABLE_ALG_MD5_) const Ipp32u MD5_IV[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476}; #endif #if defined(_ENABLE_ALG_SM3_) const Ipp32u SM3_IV[] = { 0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600, 0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E}; #endif #if defined(_ENABLE_ALG_SHA512_224_) const Ipp64u SHA512_224_IV[] = { CONST_64(0x8C3D37C819544DA2), CONST_64(0x73E1996689DCD4D6), CONST_64(0x1DFAB7AE32FF9C82), CONST_64(0x679DD514582F9FCF), CONST_64(0x0F6D2B697BD44DA8), CONST_64(0x77E36F7304C48942), CONST_64(0x3F9D85A86A1D36C8), CONST_64(0x1112E6AD91D692A1)}; #endif #if defined(_ENABLE_ALG_SHA512_256_) const Ipp64u SHA512_256_IV[] = { CONST_64(0x22312194FC2BF72C), CONST_64(0x9F555FA3C84C64C2), CONST_64(0x2393B86B6F53B151), CONST_64(0x963877195940EABD), CONST_64(0x96283EE2A88EFFE3), CONST_64(0xBE5E1E2553863992), CONST_64(0x2B0199FC2C85B8AA), CONST_64(0x0EB72DDC81C52CA2)}; #endif const Ipp8u* cpHashIV[] = { (Ipp8u*)UnknownHash_IV, #if defined(_ENABLE_ALG_SHA1_) (Ipp8u*)SHA1_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SHA256_) (Ipp8u*)SHA256_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SHA224_) (Ipp8u*)SHA224_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SHA512_) (Ipp8u*)SHA512_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SHA384_) (Ipp8u*)SHA384_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_MD5_) (Ipp8u*)MD5_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SM3_) (Ipp8u*)SM3_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SHA512_224_) (Ipp8u*)SHA512_224_IV, #else (Ipp8u*)UnknownHash_IV, #endif #if defined(_ENABLE_ALG_SHA512_256_) (Ipp8u*)SHA512_256_IV, #else (Ipp8u*)UnknownHash_IV, #endif }; //////////////////////////////////////////////////////////// /* // additive constants */ #if defined(_ENABLE_ALG_SHA1_) __ALIGN16 const Ipp32u SHA1_cnt[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; #endif #if defined(_ENABLE_ALG_SHA256_) || defined(_ENABLE_ALG_SHA224_) __ALIGN16 const Ipp32u SHA256_cnt[] = { 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 }; #endif #if defined(_ENABLE_ALG_SHA512_) || defined(_ENABLE_ALG_SHA384_) || defined(_ENABLE_ALG_SHA512_224_) || defined(_ENABLE_ALG_SHA512_256_) __ALIGN16 const Ipp64u SHA512_cnt[] = { CONST_64(0x428A2F98D728AE22), CONST_64(0x7137449123EF65CD), CONST_64(0xB5C0FBCFEC4D3B2F), CONST_64(0xE9B5DBA58189DBBC), CONST_64(0x3956C25BF348B538), CONST_64(0x59F111F1B605D019), CONST_64(0x923F82A4AF194F9B), CONST_64(0xAB1C5ED5DA6D8118), CONST_64(0xD807AA98A3030242), CONST_64(0x12835B0145706FBE), CONST_64(0x243185BE4EE4B28C), CONST_64(0x550C7DC3D5FFB4E2), CONST_64(0x72BE5D74F27B896F), CONST_64(0x80DEB1FE3B1696B1), CONST_64(0x9BDC06A725C71235), CONST_64(0xC19BF174CF692694), CONST_64(0xE49B69C19EF14AD2), CONST_64(0xEFBE4786384F25E3), CONST_64(0x0FC19DC68B8CD5B5), CONST_64(0x240CA1CC77AC9C65), CONST_64(0x2DE92C6F592B0275), CONST_64(0x4A7484AA6EA6E483), CONST_64(0x5CB0A9DCBD41FBD4), CONST_64(0x76F988DA831153B5), CONST_64(0x983E5152EE66DFAB), CONST_64(0xA831C66D2DB43210), CONST_64(0xB00327C898FB213F), CONST_64(0xBF597FC7BEEF0EE4), CONST_64(0xC6E00BF33DA88FC2), CONST_64(0xD5A79147930AA725), CONST_64(0x06CA6351E003826F), CONST_64(0x142929670A0E6E70), CONST_64(0x27B70A8546D22FFC), CONST_64(0x2E1B21385C26C926), CONST_64(0x4D2C6DFC5AC42AED), CONST_64(0x53380D139D95B3DF), CONST_64(0x650A73548BAF63DE), CONST_64(0x766A0ABB3C77B2A8), CONST_64(0x81C2C92E47EDAEE6), CONST_64(0x92722C851482353B), CONST_64(0xA2BFE8A14CF10364), CONST_64(0xA81A664BBC423001), CONST_64(0xC24B8B70D0F89791), CONST_64(0xC76C51A30654BE30), CONST_64(0xD192E819D6EF5218), CONST_64(0xD69906245565A910), CONST_64(0xF40E35855771202A), CONST_64(0x106AA07032BBD1B8), CONST_64(0x19A4C116B8D2D0C8), CONST_64(0x1E376C085141AB53), CONST_64(0x2748774CDF8EEB99), CONST_64(0x34B0BCB5E19B48A8), CONST_64(0x391C0CB3C5C95A63), CONST_64(0x4ED8AA4AE3418ACB), CONST_64(0x5B9CCA4F7763E373), CONST_64(0x682E6FF3D6B2B8A3), CONST_64(0x748F82EE5DEFB2FC), CONST_64(0x78A5636F43172F60), CONST_64(0x84C87814A1F0AB72), CONST_64(0x8CC702081A6439EC), CONST_64(0x90BEFFFA23631E28), CONST_64(0xA4506CEBDE82BDE9), CONST_64(0xBEF9A3F7B2C67915), CONST_64(0xC67178F2E372532B), CONST_64(0xCA273ECEEA26619C), CONST_64(0xD186B8C721C0C207), CONST_64(0xEADA7DD6CDE0EB1E), CONST_64(0xF57D4F7FEE6ED178), CONST_64(0x06F067AA72176FBA), CONST_64(0x0A637DC5A2C898A6), CONST_64(0x113F9804BEF90DAE), CONST_64(0x1B710B35131C471B), CONST_64(0x28DB77F523047D84), CONST_64(0x32CAAB7B40C72493), CONST_64(0x3C9EBE0A15C9BEBC), CONST_64(0x431D67C49C100D4C), CONST_64(0x4CC5D4BECB3E42B6), CONST_64(0x597F299CFC657E2A), CONST_64(0x5FCB6FAB3AD6FAEC), CONST_64(0x6C44198C4A475817) }; #endif #if defined(_ENABLE_ALG_MD5_) __ALIGN16 const Ipp32u MD5_cnt[] = { 0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501, 0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE, 0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821, 0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA, 0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8, 0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED, 0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A, 0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C, 0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70, 0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05, 0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665, 0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039, 0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1, 0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1, 0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391 }; #endif #if defined(_ENABLE_ALG_SM3_) __ALIGN16 const Ipp32u SM3_cnt[] = { 0x79CC4519,0xF3988A32,0xE7311465,0xCE6228CB,0x9CC45197,0x3988A32F,0x7311465E,0xE6228CBC, 0xCC451979,0x988A32F3,0x311465E7,0x6228CBCE,0xC451979C,0x88A32F39,0x11465E73,0x228CBCE6, 0x9D8A7A87,0x3B14F50F,0x7629EA1E,0xEC53D43C,0xD8A7A879,0xB14F50F3,0x629EA1E7,0xC53D43CE, 0x8A7A879D,0x14F50F3B,0x29EA1E76,0x53D43CEC,0xA7A879D8,0x4F50F3B1,0x9EA1E762,0x3D43CEC5, 0x7A879D8A,0xF50F3B14,0xEA1E7629,0xD43CEC53,0xA879D8A7,0x50F3B14F,0xA1E7629E,0x43CEC53D, 0x879D8A7A,0x0F3B14F5,0x1E7629EA,0x3CEC53D4,0x79D8A7A8,0xF3B14F50,0xE7629EA1,0xCEC53D43, 0x9D8A7A87,0x3B14F50F,0x7629EA1E,0xEC53D43C,0xD8A7A879,0xB14F50F3,0x629EA1E7,0xC53D43CE, 0x8A7A879D,0x14F50F3B,0x29EA1E76,0x53D43CEC,0xA7A879D8,0x4F50F3B1,0x9EA1E762,0x3D43CEC5 }; #endif /* // hash alg default processing opt argument */ const void* cpHashProcFuncOpt[] = { NULL, #if defined(_ENABLE_ALG_SHA1_) SHA1_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SHA256_) SHA256_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SHA224_) SHA256_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SHA512_) SHA512_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SHA384_) SHA512_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_MD5_) MD5_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SM3_) SM3_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SHA512_224_) SHA512_cnt, #else NULL, #endif #if defined(_ENABLE_ALG_SHA512_256_) SHA512_cnt, #else NULL, #endif }; //////////////////////////////////////////////////////////// /* hash alg attributes */ const cpHashAttr cpHashAlgAttr[] = { {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, /* unknown */ #if defined(_ENABLE_ALG_SHA1_) /* sha1 / unknown */ {IPP_SHA1_DIGEST_BITSIZE/8, IPP_SHA1_DIGEST_BITSIZE/8, MBS_SHA1, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SHA256_) /* sha256 / unknown */ {IPP_SHA256_DIGEST_BITSIZE/8,IPP_SHA256_DIGEST_BITSIZE/8, MBS_SHA256, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SHA224_) /* sha224 / unknown */ {IPP_SHA256_DIGEST_BITSIZE/8,IPP_SHA224_DIGEST_BITSIZE/8, MBS_SHA224, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SHA512_) /* sha512 / unknown */ {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA512_DIGEST_BITSIZE/8, MBS_SHA512, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SHA384_) /* sha384 / unknown */ {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA384_DIGEST_BITSIZE/8, MBS_SHA384, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_MD5_) /* md5 / unknown */ {IPP_MD5_DIGEST_BITSIZE/8,IPP_MD5_DIGEST_BITSIZE/8, MBS_MD5, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SM3_) /* sm3 / unknown */ {IPP_SM3_DIGEST_BITSIZE/8,IPP_SM3_DIGEST_BITSIZE/8, MBS_SM3, sizeof(Ipp64u), {CONST_64(0x2000000000000000-1),CONST_64(0)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SHA512_224_) /* sha512/224 / unknown */ {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA512_224_DIGEST_BITSIZE/8, MBS_SHA512, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}}, #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}}, #endif #if defined(_ENABLE_ALG_SHA512_256_) /* sha512/256 / unknown */ {IPP_SHA512_DIGEST_BITSIZE/8,IPP_SHA512_256_DIGEST_BITSIZE/8, MBS_SHA512, sizeof(Ipp64u)*2, {CONST_64(0xFFFFFFFFFFFFFFFF),CONST_64(0x2000000000000000-1)}} #else {0, 0, 0, 0, {CONST_64(0),CONST_64(0)}} #endif }; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashduplicate.c000066400000000000000000000037111470420105600256430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashDuplicate() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashDuplicate // // Purpose: Clone Hash context. // // Returns: Reason: // ippStsNullPtrErr pSrcState == NULL // pDstState == NULL // ippStsContextMatchErr pSrcState->idCtx != idCtxHash // pDstState->idCtx != idCtxHash // ippStsNoErr no errors // // Parameters: // pSrcState pointer to the source Hash context // pDstState pointer to the target Hash context // // Note: // pDstState may to be uninitialized by ippsHashInit() // *F*/ IPPFUN(IppStatus, ippsHashDuplicate,(const IppsHashState* pSrcState, IppsHashState* pDstState)) { /* test state pointers */ IPP_BAD_PTR2_RET(pSrcState, pDstState); /* test states ID */ IPP_BADARG_RET(!HASH_VALID_ID(pSrcState, idCtxHash), ippStsContextMatchErr); /* copy state */ CopyBlock(pSrcState, pDstState, sizeof(IppsHashState)); HASH_SET_ID(pDstState, idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashduplicate_rmf.c000066400000000000000000000037461470420105600265170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashDuplicate_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashDuplicate_rmf // // Purpose: Clone Hash context. // // Returns: Reason: // ippStsNullPtrErr pSrcState == NULL // pDstState == NULL // ippStsContextMatchErr pSrcState->idCtx != idCtxHash // pDstState->idCtx != idCtxHash // ippStsNoErr no errors // // Parameters: // pSrcState pointer to the source Hash context // pDstState pointer to the target Hash context // // Note: // pDstState may to be uninitialized by ippsHashInit_rmf() // *F*/ IPPFUN(IppStatus, ippsHashDuplicate_rmf,(const IppsHashState_rmf* pSrcState, IppsHashState_rmf* pDstState)) { /* test state pointers */ IPP_BAD_PTR2_RET(pSrcState, pDstState); /* test states ID */ IPP_BADARG_RET(!HASH_VALID_ID(pSrcState,idCtxHash), ippStsContextMatchErr); /* copy state */ CopyBlock(pSrcState, pDstState, sizeof(IppsHashState_rmf)); HASH_SET_ID(pDstState, idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashfinal.c000066400000000000000000000035601470420105600247640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashFinal() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashFinal // // Purpose: Complete message digesting and return digest. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsNoErr no errors // // Parameters: // pMD address of the output digest // pState pointer to the SHS state // *F*/ IPPFUN(IppStatus, ippsHashFinal,(Ipp8u* pMD, IppsHashState* pState)) { /* test state pointer and ID */ IPP_BAD_PTR2_RET(pMD, pState); /* test the context */ IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); { IppHashAlgId algID = HASH_ALG_ID(pState); int hashSize = cpHashAlgAttr[algID].hashSize; cpComputeDigest(pMD, hashSize, pState); cpReInitHash(pState, algID); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashfinal_rmf.c000066400000000000000000000042711470420105600256300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashFinal_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashFinal_rmf // // Purpose: Complete message digesting and return digest. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsNoErr no errors // // Parameters: // pMD address of the output digest // pState pointer to the SHS state // *F*/ IPPFUN(IppStatus, ippsHashFinal_rmf,(Ipp8u* pMD, IppsHashState_rmf* pState)) { /* test state pointer and ID */ IPP_BAD_PTR2_RET(pMD, pState); IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); { const IppsHashMethod* method = HASH_METHOD(pState); cpFinalize_rmf(HASH_VALUE(pState), HASH_BUFF(pState), HASH_BUFFIDX(pState), HASH_LENLO(pState), HASH_LENHI(pState), method); /* convert hash into oct string */ method->hashOctStr(pMD, HASH_VALUE(pState)); /* re-init hash value */ HASH_BUFFIDX(pState) = 0; HASH_LENLO(pState) = 0; HASH_LENHI(pState) = 0; method->hashInit(HASH_VALUE(pState)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashgetinfo_rmf.c000066400000000000000000000046731470420105600262000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashMethodGetInfo() // ippsHashGetInfo_rmf() // */ #include "owncp.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsHashMethodGetInfo // // Purpose: Returns info of the Hash algorithm // // Returns: Reason: // ippStsNullPtrErr NULL == pMethod // NULL == pInfo // // ippStsNoErr no error // // Parameters: // pInfo Pointer to the info structure // pMethod Pointer to the IppsHashMethod // *F*/ IPPFUN(IppStatus, ippsHashMethodGetInfo,(IppsHashInfo* pInfo, const IppsHashMethod* pMethod)) { /* test pointers */ IPP_BAD_PTR2_RET(pInfo, pMethod); pInfo->hashSize = pMethod->hashLen; pInfo->msgBlockSize = pMethod->msgBlkSize; return ippStsNoErr; } /*F* // Name: ippsHashGetInfo_rmf // // Purpose: Returns info of the using Hash // // Returns: Reason: // ippStsNullPtrErr NULL == pState // NULL == pInfo // // ippStsContextMatchErr invalid pState->idCtx // // ippStsNoErr no error // // Parameters: // pInfo Pointer to the info structure // pState Pointer to the state context // *F*/ IPPFUN(IppStatus, ippsHashGetInfo_rmf,(IppsHashInfo* pInfo, const IppsHashState_rmf* pState)) { /* test pointers */ IPP_BAD_PTR2_RET(pInfo, pState); IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); pInfo->hashSize = HASH_METHOD(pState)->hashLen; pInfo->msgBlockSize = HASH_METHOD(pState)->msgBlkSize; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashgetsize.c000066400000000000000000000026461470420105600253510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashGetSize // // Purpose: Returns size (bytes) of IppsHashState state. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to state size // *F*/ IPPFUN(IppStatus, ippsHashGetSize,(int* pSize)) { /* test pointers */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsHashState); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashgetsize_rmf.c000066400000000000000000000026771470420105600262210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashGetSize_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashGetSize_rmf // // Purpose: Returns size (bytes) of IppsHashState state. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to state size // *F*/ IPPFUN(IppStatus, ippsHashGetSize_rmf,(int* pSize)) { /* test pointers */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsHashState_rmf); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashgettag.c000066400000000000000000000040471470420105600251470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashGetTag() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashGetTag // // Purpose: Compute digest based on current state. // Note, that further digest update is possible // // Returns: Reason: // ippStsNullPtrErr pTag == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsLengthErr hashSize < tagLen <1 // ippStsNoErr no errors // // Parameters: // pTag address of the output digest // tagLen length of digest // pState pointer to the SHS state // *F*/ IPPFUN(IppStatus, ippsHashGetTag,(Ipp8u* pTag, int tagLen, const IppsHashState* pState)) { /* test state pointer and ID */ IPP_BAD_PTR2_RET(pTag, pState); /* test the context */ IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); { /* size of hash */ int hashSize = cpHashAlgAttr[HASH_ALG_ID(pState)].hashSize; if(tagLen<1||hashSizeidCtx != idCtxHash // ippStsLengthErr hashSize < tagLen <1 // ippStsNoErr no errors // // Parameters: // pTag address of the output digest // tagLen length of digest // pState pointer to the SHS state // *F*/ IPPFUN(IppStatus, ippsHashGetTag_rmf,(Ipp8u* pTag, int tagLen, const IppsHashState_rmf* pState)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); /* test digest pointer */ IPP_BAD_PTR1_RET(pTag); IPP_BADARG_RET((tagLen <1) || HASH_METHOD(pState)->hashLenhashOctStr(pTag, hash); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashinit.c000066400000000000000000000034061470420105600246350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashInit() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashInit // // Purpose: Init Hash state. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsNoErr no errors // // Parameters: // pState pointer to the SHA1 state // hashAlg identifier of the hash algorithm // *F*/ IPPFUN(IppStatus, ippsHashInit,(IppsHashState* pState, IppHashAlgId hashAlg)) { /* get algorithm id */ hashAlg = cpValidHashAlg(hashAlg); /* test hash alg */ IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); /* test ctx pointer */ IPP_BAD_PTR1_RET(pState); /* test hash alg */ /* set ctx ID */ HASH_SET_ID(pState, idCtxHash); HASH_ALG_ID(pState) = hashAlg; /* init context */ cpInitHash(pState, hashAlg); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashinit_rmf.c000066400000000000000000000032441470420105600255010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashInit_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashInit_rmf // // Purpose: Init Hash state. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pMethod == NULL // ippStsNoErr no errors // // Parameters: // pState pointer to the Hash state // pMethod hash method // *F*/ IPPFUN(IppStatus, ippsHashInit_rmf,(IppsHashState_rmf* pState, const IppsHashMethod* pMethod)) { /* test ctx pointers */ IPP_BAD_PTR2_RET(pState, pMethod); PadBlock(0, pState, sizeof(IppsHashState_rmf)); HASH_METHOD(pState) = pMethod; HASH_SET_ID(pState, idCtxHash); pMethod->hashInit(HASH_VALUE(pState)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashmessage.c000066400000000000000000000120121470420105600253070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashMessage() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_func.h" #include "pcptool.h" /*F* // Name: ippsHashMessage // // Purpose: Hash of the whole message. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pMsg == NULL but len!=0 // ippStsLengthErr len <0 // ippStsNotSupportedModeErr if hashAlg is not match to supported hash alg // ippStsNoErr no errors // // Parameters: // pMsg pointer to the input message // len input message length // pMD address of the output digest // hashAlg hash alg ID // *F*/ IPPFUN(IppStatus, ippsHashMessage,(const Ipp8u* pMsg, int len, Ipp8u* pMD, IppHashAlgId hashAlg)) { /* get algorithm id */ hashAlg = cpValidHashAlg(hashAlg); /* test hash alg */ IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); /* test digest pointer */ IPP_BAD_PTR1_RET(pMD); /* test message length */ IPP_BADARG_RET((len<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((len && !pMsg), ippStsNullPtrErr); { /* processing function and parameter */ cpHashProc hashFunc = cpHashProcFunc[hashAlg]; const void* pParam = cpHashProcFuncOpt[hashAlg]; /* attributes */ const cpHashAttr* pAttr = &cpHashAlgAttr[hashAlg]; int mbs = pAttr->msgBlkSize; /* data block size */ int ivSize = pAttr->ivSize; /* size of hash's IV */ int hashSize = pAttr->hashSize; /* hash size */ int msgLenRepSize = pAttr->msgLenRepSize; /* length of the message representation */ /* message bitlength representation */ Ipp64u msgLenBits = (Ipp64u)len*8; /* length of main message part */ int msgLenBlks = len & (-mbs); /* rest of message length */ int msgLenRest = len - msgLenBlks; /* end of message buffer */ Ipp8u buffer[MBS_HASH_MAX*2]; int bufferLen = (msgLenRest < (mbs-msgLenRepSize))? mbs : mbs*2; /* init hash */ cpHash hash; const Ipp8u* iv = cpHashIV[hashAlg]; CopyBlock(iv, hash, ivSize); /*construct last message block(s) */ #define MSG_LEN_REP (sizeof(Ipp64u)) /* copy end of message */ CopyBlock(pMsg+len-msgLenRest, buffer, msgLenRest); /* end of message bit */ buffer[msgLenRest++] = 0x80; /* pad buffer */ PadBlock(0, buffer+msgLenRest, (cpSize)(bufferLen-msgLenRest-(int)MSG_LEN_REP)); /* copy message bitlength representation */ if(ippHashAlg_MD5!=hashAlg) msgLenBits = ENDIANNESS64(msgLenBits); ((Ipp64u*)(buffer+bufferLen))[-1] = msgLenBits; #undef MSG_LEN_REP /* message processing */ if(msgLenBlks) hashFunc(hash, pMsg, msgLenBlks, pParam); hashFunc(hash, buffer, bufferLen, pParam); /* store digest into the user buffer (remember digest in big endian) */ if(msgLenRepSize > (int)(sizeof(Ipp64u))) { /* ippHashAlg_SHA384, ippHashAlg_SHA512, ippHashAlg_SHA512_224 and ippHashAlg_SHA512_256 */ hash[0] = ENDIANNESS64(hash[0]); hash[1] = ENDIANNESS64(hash[1]); hash[2] = ENDIANNESS64(hash[2]); hash[3] = ENDIANNESS64(hash[3]); hash[4] = ENDIANNESS64(hash[4]); hash[5] = ENDIANNESS64(hash[5]); hash[6] = ENDIANNESS64(hash[6]); hash[7] = ENDIANNESS64(hash[7]); } else if(ippHashAlg_MD5!=hashAlg) { /* ippHashAlg_SHA1, ippHashAlg_SHA224, ippHashAlg_SHA256 and ippHashAlg_SM3 */ ((Ipp32u*)hash)[0] = ENDIANNESS32(((Ipp32u*)hash)[0]); ((Ipp32u*)hash)[1] = ENDIANNESS32(((Ipp32u*)hash)[1]); ((Ipp32u*)hash)[2] = ENDIANNESS32(((Ipp32u*)hash)[2]); ((Ipp32u*)hash)[3] = ENDIANNESS32(((Ipp32u*)hash)[3]); ((Ipp32u*)hash)[4] = ENDIANNESS32(((Ipp32u*)hash)[4]); ((Ipp32u*)hash)[5] = ENDIANNESS32(((Ipp32u*)hash)[5]); ((Ipp32u*)hash)[6] = ENDIANNESS32(((Ipp32u*)hash)[6]); ((Ipp32u*)hash)[7] = ENDIANNESS32(((Ipp32u*)hash)[7]); } CopyBlock(hash, pMD, hashSize); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashmessage_rmf.c000066400000000000000000000046401470420105600261630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashMessage_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashMessage_rmf // // Purpose: Hash of the whole message. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pMsg == NULL but len!=0 // ippStsLengthErr len <0 // ippStsNoErr no errors // // Parameters: // pMsg pointer to the input message // len input message length // pMD address of the output digest // pMethod hash methods // *F*/ IPPFUN(IppStatus, ippsHashMessage_rmf,(const Ipp8u* pMsg, int len, Ipp8u* pMD, const IppsHashMethod* pMethod)) { /* test method pointer */ IPP_BAD_PTR1_RET(pMethod); /* test digest pointer */ IPP_BAD_PTR1_RET(pMD); /* test message length */ IPP_BADARG_RET(0>len, ippStsLengthErr); IPP_BADARG_RET((len && !pMsg), ippStsNullPtrErr); { /* message length in the multiple MBS and the rest */ int msgLenBlks = len &(-pMethod->msgBlkSize); int msgLenRest = len - msgLenBlks; /* init hash */ DigestSHA512 hash; pMethod->hashInit(hash); /* process main part of the message */ if(msgLenBlks) { pMethod->hashUpdate(hash, pMsg, msgLenBlks); pMsg += msgLenBlks; } cpFinalize_rmf(hash, pMsg, msgLenRest, (Ipp64u)len, 0, pMethod); pMethod->hashOctStr(pMD, hash); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashmethod_rmf.h000066400000000000000000000035341470420105600260250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // Security Hash Standard // Internal Definitions and Internal Functions Prototypes // */ #if !defined(_PCP_HASH_METHOD_RMF_H) #define _PCP_HASH_METHOD_RMF_H /* hash alg methods */ IPP_OWN_FUNPTR (void, hashInitF, (void* pHash)) IPP_OWN_FUNPTR (void, hashUpdateF, (void* pHash, const Ipp8u* pMsg, int msgLen)) IPP_OWN_FUNPTR (void, hashOctStrF, (Ipp8u* pDst, void* pHash)) IPP_OWN_FUNPTR (void, msgLenRepF, (Ipp8u* pDst, Ipp64u lenLo, Ipp64u lenHi)) typedef struct _cpHashMethod_rmf { IppHashAlgId hashAlgId; /* algorithm ID */ int hashLen; /* hash length in bytes */ int msgBlkSize; /* message blkock size in bytes */ int msgLenRepSize; /* length of processed msg length representation in bytes */ hashInitF hashInit; /* set initial hash value */ hashUpdateF hashUpdate; /* hash compressor */ hashOctStrF hashOctStr; /* convert hash into oct string */ msgLenRepF msgLenRep; /* processed mgs length representation */ } cpHashMethod_rmf; #endif /* _PCP_HASH_METHOD_RMF_H */ cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashmethodgetsize.c000066400000000000000000000026651470420105600265530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashMethodGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphashmethod_rmf.h" /*F* // Name: ippsHashMethodGetSize // // Purpose: Returns size (bytes) of IppsHashMethod structure. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to state size // *F*/ IPPFUN(IppStatus, ippsHashMethodGetSize,(int* pSize)) { /* test pointers */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsHashMethod); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashpack.c000066400000000000000000000040161470420105600246060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashPack() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashPack // // Purpose: Copy initialized context to the buffer. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pBuffer == NULL // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsNoMemErr bufSize < sizeof(IppsHashState) // ippStsNoErr no errors // // Parameters: // pState pointer hash state // pBuffer pointer to the destination buffer // bufSize size of the destination buffer // *F*/ IPPFUN(IppStatus, ippsHashPack,(const IppsHashState* pState, Ipp8u* pBuffer, int bufSize)) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pBuffer); /* test the context */ IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); /* test buffer length */ IPP_BADARG_RET((int)(sizeof(IppsHashState))>bufSize, ippStsNoMemErr); CopyBlock(pState, pBuffer, sizeof(IppsHashState)); IppsHashState* pCopy = (IppsHashState*)pBuffer; HASH_RESET_ID(pCopy, idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashpack_rmf.c000066400000000000000000000040401470420105600254470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashPack_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashPack_rmf // // Purpose: Copy initialized context to the buffer. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pBuffer == NULL // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsNoMemErr bufSize < sizeof(IppsHashState_rmf) // ippStsNoErr no errors // // Parameters: // pState pointer hash state // pBuffer pointer to the destination buffer // bufSize size of the destination buffer // *F*/ IPPFUN(IppStatus, ippsHashPack_rmf,(const IppsHashState_rmf* pState, Ipp8u* pBuffer, int bufSize)) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pBuffer); IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); /* test buffer length */ IPP_BADARG_RET((int)(sizeof(IppsHashState_rmf))>bufSize, ippStsNoMemErr); CopyBlock(pState, pBuffer, sizeof(IppsHashState_rmf)); IppsHashState_rmf* pCopy = (IppsHashState_rmf*)pBuffer; HASH_RESET_ID(pCopy, idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashunpack.c000066400000000000000000000031461470420105600251540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashUnpack() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashUnpack // // Purpose: Unpack buffer content into the initialized context. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pBuffer == NULL // ippStsNoErr no errors // // Parameters: // pBuffer pointer to the source buffer // pState pointer hash state // *F*/ IPPFUN(IppStatus, ippsHashUnpack,(const Ipp8u* pBuffer, IppsHashState* pState)) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pBuffer); CopyBlock(pBuffer, pState, sizeof(IppsHashState)); HASH_SET_ID(pState, idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashunpack_rmf.c000066400000000000000000000032021470420105600260110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashUnpack_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashUnpack_rmf // // Purpose: Unpack buffer content into the initialized context. // // Returns: Reason: // ippStsNullPtrErr pBuffer == NULL // pState == NULL // ippStsNoErr no errors // // Parameters: // pBuffer pointer to the source buffer // pState pointer hash state // *F*/ IPPFUN(IppStatus, ippsHashUnpack_rmf,(const Ipp8u* pBuffer, IppsHashState_rmf* pState)) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pBuffer); CopyBlock(pBuffer, pState, sizeof(IppsHashState_rmf)); HASH_SET_ID(pState, idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashupdate.c000066400000000000000000000101461470420105600251530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // General Functionality // // Contents: // ippsHashUpdate() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsHashUpdate // // Purpose: Updates intermediate hash value based on input stream. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pSrc==0 but len!=0 // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsLengthErr len <0 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the input stream // len input stream length // pState pointer to the Hash context // *F*/ __IPPCP_INLINE int IsExceedMsgLen(Ipp64u maxLo, Ipp64u maxHi, Ipp64u lenLo, Ipp64u lenHi) { int isExceed = lenLo > maxLo; isExceed = (lenHi+(Ipp64u)isExceed) > maxHi; return isExceed; } IPPFUN(IppStatus, ippsHashUpdate,(const Ipp8u* pSrc, int len, IppsHashState* pState)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pState); /* test the context */ IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); /* test input length */ IPP_BADARG_RET((len<0 && pSrc), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); /* handle non empty input */ if(len) { const cpHashAttr* pAttr = &cpHashAlgAttr[HASH_ALG_ID(pState)]; /* test if size of message is being processed not exceeded yet */ Ipp64u lenLo = HASH_LENLO(pState); Ipp64u lenHi = HASH_LENHI(pState); lenLo += (Ipp64u)len; if(lenLo < HASH_LENLO(pState)) lenHi++; if(IsExceedMsgLen(pAttr->msgLenMax[0],pAttr->msgLenMax[1], lenLo,lenHi)) IPP_ERROR_RET(ippStsLengthErr); else { cpHashProc hashFunc = HASH_FUNC(pState); /* processing function */ const void* pParam = HASH_FUNC_PAR(pState); /* and it's addition params */ int mbs = pAttr->msgBlkSize; /* data block size */ /* // processing */ { int procLen; /* test if internal buffer is not empty */ int n = HASH_BUFFIDX(pState); if(n) { procLen = IPP_MIN(len, (mbs-n)); CopyBlock(pSrc, HASH_BUFF(pState)+n, procLen); HASH_BUFFIDX(pState) = n += procLen; /* block processing */ if(mbs==n) { hashFunc(HASH_VALUE(pState), HASH_BUFF(pState), mbs, pParam); HASH_BUFFIDX(pState) = 0; } /* update message pointer and length */ pSrc += procLen; len -= procLen; } /* main processing part */ procLen = len & ~(mbs-1); if(procLen) { hashFunc(HASH_VALUE(pState), pSrc, procLen, pParam); pSrc += procLen; len -= procLen; } /* rest of input message */ if(len) { CopyBlock(pSrc, HASH_BUFF(pState), len); HASH_BUFFIDX(pState) += len; } } /* update length of processed message */ HASH_LENLO(pState) = lenLo; HASH_LENHI(pState) = lenHi; return ippStsNoErr; } } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/pcphashupdate_rmf.c000066400000000000000000000065271470420105600260270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Security Hash Standard // Generalized Functionality // // Contents: // ippsHashUpdate_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsHashUpdate_rmf // // Purpose: Updates intermediate hash value based on input stream. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsNullPtrErr pSrc==0 but len!=0 // ippStsContextMatchErr pState->idCtx != idCtxHash // ippStsLengthErr len <0 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the input stream // len input stream length // pState pointer to the Hash context // *F*/ IPPFUN(IppStatus, ippsHashUpdate_rmf,(const Ipp8u* pSrc, int len, IppsHashState_rmf* pState)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(!HASH_VALID_ID(pState, idCtxHash), ippStsContextMatchErr); /* test input length */ IPP_BADARG_RET((len<0), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); if(len) { const IppsHashMethod* method = HASH_METHOD(pState); hashUpdateF hashFunc = method->hashUpdate; /* processing function */ int msgBlkSize = method->msgBlkSize; /* message block size */ int procLen; int idx = HASH_BUFFIDX(pState); Ipp64u lenLo = HASH_LENLO(pState); Ipp64u lenHi = HASH_LENHI(pState); lenLo += (Ipp64u)len; if(lenLo < HASH_LENLO(pState)) lenHi++; /* if internal buffer is not empty */ if(idx) { procLen = IPP_MIN(len, (msgBlkSize-idx)); CopyBlock(pSrc, HASH_BUFF(pState)+idx, procLen); idx += procLen; /* process complete message block */ if(msgBlkSize==idx) { hashFunc(HASH_VALUE(pState), HASH_BUFF(pState), msgBlkSize); idx = 0; } /* update message pointer and length */ pSrc += procLen; len -= procLen; } /* process main part of the input*/ procLen = len & ~(msgBlkSize-1); if(procLen) { hashFunc(HASH_VALUE(pState), pSrc, procLen); pSrc += procLen; len -= procLen; } /* store the rest of input in the buffer */ if(len) { CopyBlock(pSrc, HASH_BUFF(pState), len); idx += len; } /* update length of processed message */ HASH_LENLO(pState) = lenLo; HASH_LENHI(pState) = lenHi; HASH_BUFFIDX(pState) = idx; } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/000077500000000000000000000000001470420105600230105ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashmethod_sha1.c000066400000000000000000000031011470420105600267120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // ippsHashMethod_SHA1() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" /*F* // Name: ippsHashMethod_SHA1 // // Purpose: Return SHA1 method. // // Returns: // Pointer to SHA1 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA1, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA1, IPP_SHA1_DIGEST_BITSIZE/8, MBS_SHA1, MLR_SHA1, 0, 0, 0, 0 }; method.hashInit = sha1_hashInit; method.hashUpdate = sha1_hashUpdate; method.hashOctStr = sha1_hashOctString; method.msgLenRep = sha1_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashmethod_sha1_ni.c000066400000000000000000000035071470420105600274120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // ippsHashMethod_SHA1_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" /*F* // Name: ippsHashMethod_SHA1_NI // // Purpose: Return SHA1 method (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: // Pointer to SHA1 hash-method (using the Intel SHA-NI instruction set). // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA1_NI, (void) ) { #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) static IppsHashMethod method = { ippHashAlg_SHA1, IPP_SHA1_DIGEST_BITSIZE/8, MBS_SHA1, MLR_SHA1, 0, 0, 0, 0 }; method.hashInit = sha1_hashInit; method.hashUpdate = sha1_ni_hashUpdate; method.hashOctStr = sha1_hashOctString; method.msgLenRep = sha1_msgRep; return &method; #else return NULL; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashmethod_sha1_tt.c000066400000000000000000000037631470420105600274370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // ippsHashMethod_SHA1_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" /*F* // Name: ippsHashMethod_SHA1_TT // // Purpose: Return SHA1 method // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: // Pointer to SHA1 hash-method // (using the Intel SHA-NI instructions set // if it is available at run time) // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA1_TT, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA1, IPP_SHA1_DIGEST_BITSIZE/8, MBS_SHA1, MLR_SHA1, 0, 0, 0, 0 }; method.hashInit = sha1_hashInit; method.hashUpdate = sha1_hashUpdate; method.hashOctStr = sha1_hashOctString; method.msgLenRep = sha1_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) method.hashUpdate = sha1_ni_hashUpdate; #endif return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashmethodset_sha1.c000066400000000000000000000033521470420105600274360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // ippsHashMethodSet_SHA1() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" /*F* // Name: ippsHashMethodSet_SHA1 // // Purpose: Setup SHA1 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA1, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA1; pMethod->hashLen = IPP_SHA1_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA1; pMethod->msgLenRepSize = MLR_SHA1; pMethod->hashInit = sha1_hashInit; pMethod->hashUpdate = sha1_hashUpdate; pMethod->hashOctStr = sha1_hashOctString; pMethod->msgLenRep = sha1_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashmethodset_sha1_ni.c000066400000000000000000000044451470420105600301300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // ippsHashMethodSet_SHA1_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" /*F* // Name: ippsHashMethodSet_SHA1_NI // // Purpose: Setup SHA1 method (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNotSupportedModeErr mode disabled by configuration // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA1_NI, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) pMethod->hashAlgId = ippHashAlg_SHA1; pMethod->hashLen = IPP_SHA1_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA1; pMethod->msgLenRepSize = MLR_SHA1; pMethod->hashInit = sha1_hashInit; pMethod->hashUpdate = sha1_ni_hashUpdate; pMethod->hashOctStr = sha1_hashOctString; pMethod->msgLenRep = sha1_msgRep; return ippStsNoErr; #else pMethod->hashAlgId = ippHashAlg_Unknown; pMethod->hashLen = 0; pMethod->msgBlkSize = 0; pMethod->msgLenRepSize = 0; pMethod->hashInit = 0; pMethod->hashUpdate = 0; pMethod->hashOctStr = 0; pMethod->msgLenRep = 0; return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashmethodset_sha1_tt.c000066400000000000000000000040761470420105600301510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // ippsHashMethodSet_SHA1_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" /*F* // Name: ippsHashMethodSet_SHA1_TT // // Purpose: Setup SHA1 method // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA1_TT, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA1; pMethod->hashLen = IPP_SHA1_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA1; pMethod->msgLenRepSize = MLR_SHA1; pMethod->hashInit = sha1_hashInit; pMethod->hashUpdate = sha1_hashUpdate; pMethod->hashOctStr = sha1_hashOctString; pMethod->msgLenRep = sha1_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) pMethod->hashUpdate = sha1_ni_hashUpdate; #endif return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcphashsha1px.c000066400000000000000000000127301470420105600257320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message block processing according to SHA1 // // Contents: // UpdateSHA1() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" #if !((_IPP==_IPP_M5) || \ (_IPP==_IPP_W7) || (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || (_IPP==_IPP_P8) || \ (_IPP==_IPP_S8) || (_IPP>=_IPP_G9) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) /* // Magic functions defined in FIPS 180-1 // */ #define MAGIC_F0(B,C,D) (((B) & (C)) | ((~(B)) & (D))) #define MAGIC_F1(B,C,D) ((B) ^ (C) ^ (D)) #define MAGIC_F2(B,C,D) (((B) & (C)) | ((B) & (D)) | ((C) & (D))) #define MAGIC_F3(B,C,D) ((B) ^ (C) ^ (D)) #define SHA1_STEP(A,B,C,D,E, MAGIC_FUN, W,K) \ (E)+= ROL32((A),5) + MAGIC_FUN((B),(C),(D)) + (W) + (K); \ (B) = ROL32((B),30) #define COMPACT_SHA1_STEP(A,B,C,D,E, MAGIC_FUN, W,K, t) { \ Ipp32u _T = ROL32((A),5) + MAGIC_FUN((t)/20, (B),(C),(D)) + (E) + (W)[(t)] + (K)[(t)/20]; \ (E) = (D); \ (D) = (C); \ (C) = ROL32((B),30); \ (B) = (A); \ (A) = _T; \ } #if defined(_ALG_SHA1_COMPACT_) __IPPCP_INLINE Ipp32u MagicFun(int s, Ipp32u b, Ipp32u c, Ipp32u d) { switch(s) { case 0: return MAGIC_F0(b,c,d); case 2: return MAGIC_F2(b,c,d); default:return MAGIC_F1(b,c,d); } } #endif /*F* // Name: UpdateSHA1 // // Purpose: Update internal hash according to input message stream. // // Parameters: // uniHash pointer to in/out hash // mblk pointer to message stream // mlen message stream length (multiple by message block size) // uniParam pointer to the optional parameter // *F*/ IPP_OWN_DEFN (void, UpdateSHA1, (void* uinHash, const Ipp8u* mblk, int mlen, const void *uniParam)) { Ipp32u* data = (Ipp32u*)mblk; Ipp32u* digest = (Ipp32u*)uinHash; Ipp32u* SHA1_cnt_loc = (Ipp32u*)uniParam; for(; mlen>=MBS_SHA1; data += MBS_SHA1/sizeof(Ipp32u), mlen -= MBS_SHA1) { int t; /* // expand message block */ Ipp32u W[80]; /* initialize the first 16 words in the array W (remember about endian) */ for(t=0; t<16; t++) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) W[t] = data[t]; #else W[t] = ENDIANNESS(data[t]); #endif } /* schedule another 80-16 words in the array W */ for(; t<80; t++) { W[t] = ROL32(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1); } /* // update hash */ { /* init A, B, C, D, E by the the input hash */ Ipp32u A = digest[0]; Ipp32u B = digest[1]; Ipp32u C = digest[2]; Ipp32u D = digest[3]; Ipp32u E = digest[4]; #if defined(_ALG_SHA1_COMPACT_) /* steps 0-79 */ for(t=0; t<80; t++) COMPACT_SHA1_STEP(A,B,C,D,E, MagicFun, W, SHA1_cnt_loc, t); #else /* perform 0-19 steps */ for(t=0; t<20; t+=5) { SHA1_STEP(A,B,C,D,E, MAGIC_F0, W[t ],SHA1_cnt_loc[0]); SHA1_STEP(E,A,B,C,D, MAGIC_F0, W[t+1],SHA1_cnt_loc[0]); SHA1_STEP(D,E,A,B,C, MAGIC_F0, W[t+2],SHA1_cnt_loc[0]); SHA1_STEP(C,D,E,A,B, MAGIC_F0, W[t+3],SHA1_cnt_loc[0]); SHA1_STEP(B,C,D,E,A, MAGIC_F0, W[t+4],SHA1_cnt_loc[0]); } /* perform 20-39 steps */ for(; t<40; t+=5) { SHA1_STEP(A,B,C,D,E, MAGIC_F1, W[t ],SHA1_cnt_loc[1]); SHA1_STEP(E,A,B,C,D, MAGIC_F1, W[t+1],SHA1_cnt_loc[1]); SHA1_STEP(D,E,A,B,C, MAGIC_F1, W[t+2],SHA1_cnt_loc[1]); SHA1_STEP(C,D,E,A,B, MAGIC_F1, W[t+3],SHA1_cnt_loc[1]); SHA1_STEP(B,C,D,E,A, MAGIC_F1, W[t+4],SHA1_cnt_loc[1]); } /* perform 40-59 steps */ for(; t<60; t+=5) { SHA1_STEP(A,B,C,D,E, MAGIC_F2, W[t ],SHA1_cnt_loc[2]); SHA1_STEP(E,A,B,C,D, MAGIC_F2, W[t+1],SHA1_cnt_loc[2]); SHA1_STEP(D,E,A,B,C, MAGIC_F2, W[t+2],SHA1_cnt_loc[2]); SHA1_STEP(C,D,E,A,B, MAGIC_F2, W[t+3],SHA1_cnt_loc[2]); SHA1_STEP(B,C,D,E,A, MAGIC_F2, W[t+4],SHA1_cnt_loc[2]); } /* perform 60-79 steps */ for(; t<80; t+=5) { SHA1_STEP(A,B,C,D,E, MAGIC_F3, W[t ],SHA1_cnt_loc[3]); SHA1_STEP(E,A,B,C,D, MAGIC_F3, W[t+1],SHA1_cnt_loc[3]); SHA1_STEP(D,E,A,B,C, MAGIC_F3, W[t+2],SHA1_cnt_loc[3]); SHA1_STEP(C,D,E,A,B, MAGIC_F3, W[t+3],SHA1_cnt_loc[3]); SHA1_STEP(B,C,D,E,A, MAGIC_F3, W[t+4],SHA1_cnt_loc[3]); } #endif /* update digest */ digest[0] += A; digest[1] += B; digest[2] += C; digest[3] += D; digest[4] += E; } } } #endif cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcpsha1ca.c000066400000000000000000000040541470420105600250220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // cpFinalizeSHA1() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha1/pcpsha1stuff.h" IPP_OWN_DEFN (void, cpFinalizeSHA1, (DigestSHA1 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) { /* select processing function */ #if (_SHA_NI_ENABLING_==_FEATURE_ON_) cpHashProc updateFunc = UpdateSHA1ni; #elif (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_) cpHashProc updateFunc = IsFeatureEnabled(ippCPUID_SHA)? UpdateSHA1ni : UpdateSHA1; #else cpHashProc updateFunc = UpdateSHA1; #endif /* local buffer and it length */ Ipp8u buffer[MBS_SHA1*2]; int bufferLen = inpLen < (MBS_SHA1-(int)MLR_SHA1)? MBS_SHA1 : MBS_SHA1*2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer+inpLen, (cpSize)(bufferLen-inpLen-(int)MLR_SHA1)); /* put processed message length in bits */ processedMsgLen = ENDIANNESS64(processedMsgLen<<3); ((Ipp64u*)(buffer+bufferLen))[-1] = processedMsgLen; /* copmplete hash computation */ updateFunc(pHash, buffer, bufferLen, sha1_cnt); } cryptography-primitives-1.0.0/sources/ippcp/hash/sha1/pcpsha1stuff.h000066400000000000000000000052601470420105600255730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA1 // // Contents: // SHA1 stuff // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #if !defined(_CP_HASH_SHA1) #define _CP_HASH_SHA1 /* SHA-1 constants */ static const Ipp32u sha1_iv[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; static __ALIGN16 const Ipp32u sha1_cnt[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; IPP_OWN_DEFN (static void, sha1_hashInit, (void* pHash)) { /* setup initial digest */ ((Ipp32u*)pHash)[0] = sha1_iv[0]; ((Ipp32u*)pHash)[1] = sha1_iv[1]; ((Ipp32u*)pHash)[2] = sha1_iv[2]; ((Ipp32u*)pHash)[3] = sha1_iv[3]; ((Ipp32u*)pHash)[4] = sha1_iv[4]; } IPP_OWN_DEFN (static void, sha1_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSHA1(pHash, pMsg, msgLen, sha1_cnt); } #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) IPP_OWN_DEFN (static void, sha1_ni_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSHA1ni(pHash, pMsg, msgLen, sha1_cnt); } #endif IPP_OWN_DEFN (static void, sha1_hashOctString, (Ipp8u* pMD, void* pHashVal)) { /* convert hash into big endian */ ((Ipp32u*)pMD)[0] = ENDIANNESS32(((Ipp32u*)pHashVal)[0]); ((Ipp32u*)pMD)[1] = ENDIANNESS32(((Ipp32u*)pHashVal)[1]); ((Ipp32u*)pMD)[2] = ENDIANNESS32(((Ipp32u*)pHashVal)[2]); ((Ipp32u*)pMD)[3] = ENDIANNESS32(((Ipp32u*)pHashVal)[3]); ((Ipp32u*)pMD)[4] = ENDIANNESS32(((Ipp32u*)pHashVal)[4]); } IPP_OWN_DEFN (static void, sha1_msgRep, (Ipp8u* pDst, Ipp64u lenLo, Ipp64u lenHi)) { IPP_UNREFERENCED_PARAMETER(lenHi); lenLo = ENDIANNESS64(lenLo<<3); ((Ipp64u*)(pDst))[0] = lenLo; } #define cpFinalizeSHA1 OWNAPI(cpFinalizeSHA1) IPP_OWN_DECL (void, cpFinalizeSHA1, (DigestSHA1 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) #endif /* #if !defined(_CP_HASH_SHA1) */ cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/000077500000000000000000000000001470420105600231575ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashmethod_sha224.c000066400000000000000000000031421470420105600272350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethod_SHA224() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethod_SHA224 // // Purpose: Return SHA224 method. // // Returns: // Pointer to SHA224 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA224, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA224, IPP_SHA224_DIGEST_BITSIZE/8, MBS_SHA256, MLR_SHA256, 0, 0, 0, 0 }; method.hashInit = sha224_hashInit; method.hashUpdate = sha256_hashUpdate; method.hashOctStr = sha224_hashOctString; method.msgLenRep = sha256_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashmethod_sha224_ni.c000066400000000000000000000035501470420105600277260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethod_SHA224_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethod_SHA224_NI // // Purpose: Return SHA224 method (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: // Pointer to SHA224 hash-method (using the Intel SHA-NI instruction set). // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA224_NI, (void) ) { #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) static IppsHashMethod method = { ippHashAlg_SHA224, IPP_SHA224_DIGEST_BITSIZE/8, MBS_SHA256, MLR_SHA256, 0, 0, 0, 0 }; method.hashInit = sha224_hashInit; method.hashUpdate = sha256_ni_hashUpdate; method.hashOctStr = sha224_hashOctString; method.msgLenRep = sha256_msgRep; return &method; #else return NULL; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashmethod_sha224_tt.c000066400000000000000000000040251470420105600277450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethod_SHA224_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethod_SHA224_TT // // Purpose: Return SHA224 method // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: // Pointer to SHA224 hash-method // (using the Intel SHA-NI instructions set // if it is available at run time) // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA224_TT, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA224, IPP_SHA224_DIGEST_BITSIZE/8, MBS_SHA256, MLR_SHA256, 0, 0, 0, 0 }; method.hashInit = sha224_hashInit; method.hashUpdate = sha256_hashUpdate; method.hashOctStr = sha224_hashOctString; method.msgLenRep = sha256_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) method.hashUpdate = sha256_ni_hashUpdate; #endif return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashmethodset_sha224.c000066400000000000000000000034131470420105600277520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethodSet_SHA224() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethodSet_SHA224 // // Purpose: Setup SHA224 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA224, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha224_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha224_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashmethodset_sha224_ni.c000066400000000000000000000045041470420105600304420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethodSet_SHA224_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethodSet_SHA224_NI // // Purpose: Setup SHA224 method (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNotSupportedModeErr mode disabled by configuration // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA224_NI, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) pMethod->hashAlgId = ippHashAlg_SHA224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha224_hashInit; pMethod->hashUpdate = sha256_ni_hashUpdate; pMethod->hashOctStr = sha224_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; #else pMethod->hashAlgId = ippHashAlg_Unknown; pMethod->hashLen = 0; pMethod->msgBlkSize = 0; pMethod->msgLenRepSize = 0; pMethod->hashInit = 0; pMethod->hashUpdate = 0; pMethod->hashOctStr = 0; pMethod->msgLenRep = 0; return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashmethodset_sha224_tt.c000066400000000000000000000041301470420105600304560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethodSet_SHA224_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethodSet_SHA224_TT // // Purpose: Setup SHA224 method // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA224_TT, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha224_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha224_hashOctString; pMethod->msgLenRep = sha256_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) pMethod->hashUpdate = sha256_ni_hashUpdate; #endif return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashstatemethodset_sha224.c000066400000000000000000000036101470420105600310120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA224 // // Contents: // ippsHashStateMethodSet_SHA224() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA224 // // Purpose: Setup SHA224 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA224, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha224_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha224_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashstatemethodset_sha224_ni.c000066400000000000000000000047011470420105600315020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA224 // // Contents: // ippsHashStateMethodSet_SHA224_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA224_NI // // Purpose: Setup SHA224 method inside the hash state (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNotSupportedModeErr mode disabled by configuration // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA224_NI, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) pMethod->hashAlgId = ippHashAlg_SHA224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha224_hashInit; pMethod->hashUpdate = sha256_ni_hashUpdate; pMethod->hashOctStr = sha224_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; #else pMethod->hashAlgId = ippHashAlg_Unknown; pMethod->hashLen = 0; pMethod->msgBlkSize = 0; pMethod->msgLenRepSize = 0; pMethod->hashInit = 0; pMethod->hashUpdate = 0; pMethod->hashOctStr = 0; pMethod->msgLenRep = 0; return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha224/pcphashstatemethodset_sha224_tt.c000066400000000000000000000043251470420105600315250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA224 // // Contents: // ippsHashStateMethodSet_SHA224_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA224_TT // // Purpose: Setup SHA224 method inside the hash state // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA224_TT, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha224_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha224_hashOctString; pMethod->msgLenRep = sha256_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) pMethod->hashUpdate = sha256_ni_hashUpdate; #endif return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/000077500000000000000000000000001470420105600231645ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashmethod_sha256.c000066400000000000000000000031411470420105600272460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethod_SHA256() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethod_SHA256 // // Purpose: Return SHA256 method. // // Returns: // Pointer to SHA256 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA256, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA256, IPP_SHA256_DIGEST_BITSIZE/8, MBS_SHA256, MLR_SHA256, 0, 0, 0, 0 }; method.hashInit = sha256_hashInit; method.hashUpdate = sha256_hashUpdate; method.hashOctStr = sha256_hashOctString; method.msgLenRep = sha256_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashmethod_sha256_ni.c000066400000000000000000000035471470420105600277460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethod_SHA256_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethod_SHA256_NI // // Purpose: Return SHA256 method (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: // Pointer to SHA256 hash-method (using the Intel SHA-NI instruction set). // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA256_NI, (void) ) { #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) static IppsHashMethod method = { ippHashAlg_SHA256, IPP_SHA256_DIGEST_BITSIZE/8, MBS_SHA256, MLR_SHA256, 0, 0, 0, 0 }; method.hashInit = sha256_hashInit; method.hashUpdate = sha256_ni_hashUpdate; method.hashOctStr = sha256_hashOctString; method.msgLenRep = sha256_msgRep; return &method; #else return NULL; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashmethod_sha256_tt.c000066400000000000000000000040251470420105600277570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethod_SHA256_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethod_SHA256_TT // // Purpose: Return SHA256 method // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: // Pointer to SHA256 hash-method // (using the Intel SHA-NI instructions set // if it is available at run time) // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA256_TT, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA256, IPP_SHA256_DIGEST_BITSIZE/8, MBS_SHA256, MLR_SHA256, 0, 0, 0, 0 }; method.hashInit = sha256_hashInit; method.hashUpdate = sha256_hashUpdate; method.hashOctStr = sha256_hashOctString; method.msgLenRep = sha256_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) method.hashUpdate = sha256_ni_hashUpdate; #endif return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashmethodset_sha256.c000066400000000000000000000034121470420105600277630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethodSet_SHA256() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethodSet_SHA256 // // Purpose: Setup SHA256 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA256, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha256_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha256_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashmethodset_sha256_ni.c000066400000000000000000000045031470420105600304530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethodSet_SHA256_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethodSet_SHA256_NI // // Purpose: Setup SHA256 method (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNotSupportedModeErr mode disabled by configuration // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA256_NI, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) pMethod->hashAlgId = ippHashAlg_SHA256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha256_hashInit; pMethod->hashUpdate = sha256_ni_hashUpdate; pMethod->hashOctStr = sha256_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; #else pMethod->hashAlgId = ippHashAlg_Unknown; pMethod->hashLen = 0; pMethod->msgBlkSize = 0; pMethod->msgLenRepSize = 0; pMethod->hashInit = 0; pMethod->hashUpdate = 0; pMethod->hashOctStr = 0; pMethod->msgLenRep = 0; return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashmethodset_sha256_tt.c000066400000000000000000000041461470420105600304770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashMethodSet_SHA256_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashMethodSet_SHA256_TT // // Purpose: Setup SHA256 method // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA256_TT, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha256_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha256_hashOctString; pMethod->msgLenRep = sha256_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) pMethod->hashUpdate = sha256_ni_hashUpdate; #endif return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashsha256px.c000066400000000000000000000135121470420105600262610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message block processing according to SHA256 // // Contents: // UpdateSHA256() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" #if defined(_ENABLE_ALG_SHA256_) || defined(_ENABLE_ALG_SHA224_) #if !((_IPP==_IPP_M5) || \ (_IPP==_IPP_W7) || (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || (_IPP==_IPP_P8) || \ (_IPP==_IPP_S8) || (_IPP>=_IPP_G9) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) /* // SHA256 Specific Macros (reference proposal 256-384-512) */ #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define SUM0(x) (ROR32((x), 2) ^ ROR32((x),13) ^ ROR32((x),22)) #define SUM1(x) (ROR32((x), 6) ^ ROR32((x),11) ^ ROR32((x),25)) #define SIG0(x) (ROR32((x), 7) ^ ROR32((x),18) ^ LSR32((x), 3)) #define SIG1(x) (ROR32((x),17) ^ ROR32((x),19) ^ LSR32((x),10)) #define SHA256_UPDATE(i) \ wdat[i & 15] += SIG1(wdat[(i+14)&15]) + wdat[(i+9)&15] + SIG0(wdat[(i+1)&15]) #define SHA256_STEP(i,j) \ v[(7 - i) & 7] += (j ? SHA256_UPDATE(i) : wdat[i&15]) \ + SHA256_cnt_loc[i + j] \ + SUM1(v[(4-i)&7]) \ + CH(v[(4-i)&7], v[(5-i)&7], v[(6-i)&7]); \ v[(3-i)&7] += v[(7-i)&7]; \ v[(7-i)&7] += SUM0(v[(0-i)&7]) + MAJ(v[(0-i)&7], v[(1-i)&7], v[(2-i)&7]) #define COMPACT_SHA256_STEP(A,B,C,D,E,F,G,H, W,K, r) { \ Ipp32u _T1 = (H) + SUM1((E)) + CH((E),(F),(G)) + (W)[(r)] + (K)[(r)]; \ Ipp32u _T2 = SUM0((A)) + MAJ((A),(B),(C)); \ (H) = (G); \ (G) = (F); \ (F) = (E); \ (E) = (D)+_T1; \ (D) = (C); \ (C) = (B); \ (B) = (A); \ (A) = _T1+_T2; \ } /*F* // Name: UpdateSHA256 // // Purpose: Update internal hash according to input message stream. // // Parameters: // uniHash pointer to in/out hash // mblk pointer to message stream // mlen message stream length (multiple by message block size) // uniParam pointer to the optional parameter // *F*/ #if defined(_ALG_SHA256_COMPACT_) IPP_OWN_DEFN (void, UpdateSHA256, (void* uniHash, const Ipp8u* mblk, int mlen, const void* uniParam)) { Ipp32u* data = (Ipp32u*)mblk; Ipp32u* digest = (Ipp32u*)uniHash; Ipp32u* SHA256_cnt_loc = (Ipp32u*)uniParam; for(; mlen>=MBS_SHA256; data += MBS_SHA256/sizeof(Ipp32u), mlen -= MBS_SHA256) { int t; /* // expand message block */ Ipp32u W[64]; /* initialize the first 16 words in the array W (remember about endian) */ for(t=0; t<16; t++) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) W[t] = data[t]; #else W[t] = ENDIANNESS( data[t] ); #endif } for(; t<64; t++) W[t] = SIG1(W[t-2]) + W[t-7] + SIG0(W[t-15]) + W[t-16]; /* // update hash */ { /* init A, B, C, D, E, F, G, H by the input hash */ Ipp32u A = digest[0]; Ipp32u B = digest[1]; Ipp32u C = digest[2]; Ipp32u D = digest[3]; Ipp32u E = digest[4]; Ipp32u F = digest[5]; Ipp32u G = digest[6]; Ipp32u H = digest[7]; for(t=0; t<64; t++) COMPACT_SHA256_STEP(A,B,C,D,E,F,G,H, W,SHA256_cnt_loc, t); /* update hash*/ digest[0] += A; digest[1] += B; digest[2] += C; digest[3] += D; digest[4] += E; digest[5] += F; digest[6] += G; digest[7] += H; } } } #else IPP_OWN_DEFN (void, UpdateSHA256, (void* uniHash, const Ipp8u* mblk, int mlen, const void* uniParam)) { Ipp32u* data = (Ipp32u*)mblk; Ipp32u* digest = (Ipp32u*)uniHash; Ipp32u* SHA256_cnt_loc = (Ipp32u*)uniParam; for(; mlen>=MBS_SHA256; data += MBS_SHA256/sizeof(Ipp32u), mlen -= MBS_SHA256) { Ipp32u wdat[16]; int j; /* copy digest */ Ipp32u v[8]; CopyBlock(digest, v, IPP_SHA256_DIGEST_BITSIZE/BYTESIZE); /* initialize the first 16 words in the array W (remember about endian) */ for(j=0; j<16; j++) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) wdat[j] = data[j]; #else wdat[j] = ENDIANNESS( data[j] ); #endif } for(j=0; j<64; j+=16) { SHA256_STEP( 0, j); SHA256_STEP( 1, j); SHA256_STEP( 2, j); SHA256_STEP( 3, j); SHA256_STEP( 4, j); SHA256_STEP( 5, j); SHA256_STEP( 6, j); SHA256_STEP( 7, j); SHA256_STEP( 8, j); SHA256_STEP( 9, j); SHA256_STEP(10, j); SHA256_STEP(11, j); SHA256_STEP(12, j); SHA256_STEP(13, j); SHA256_STEP(14, j); SHA256_STEP(15, j); } /* update digest */ digest[0] += v[0]; digest[1] += v[1]; digest[2] += v[2]; digest[3] += v[3]; digest[4] += v[4]; digest[5] += v[5]; digest[6] += v[6]; digest[7] += v[7]; } } #endif #endif #endif /* IPP_ALG_HASH_SHA256 */ cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashstatemethodset_sha256.c000066400000000000000000000036071470420105600310320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashStateMethodSet_SHA256() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA256 // // Purpose: Setup SHA256 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA256, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha256_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha256_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashstatemethodset_sha256_ni.c000066400000000000000000000047001470420105600315130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashStateMethodSet_SHA256_NI() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA256_NI // // Purpose: Setup SHA256 method inside the hash state (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instruction set). // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNotSupportedModeErr mode disabled by configuration // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA256_NI, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) pMethod->hashAlgId = ippHashAlg_SHA256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha256_hashInit; pMethod->hashUpdate = sha256_ni_hashUpdate; pMethod->hashOctStr = sha256_hashOctString; pMethod->msgLenRep = sha256_msgRep; return ippStsNoErr; #else pMethod->hashAlgId = ippHashAlg_Unknown; pMethod->hashLen = 0; pMethod->msgBlkSize = 0; pMethod->msgLenRepSize = 0; pMethod->hashInit = 0; pMethod->hashUpdate = 0; pMethod->hashOctStr = 0; pMethod->msgLenRep = 0; return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcphashstatemethodset_sha256_tt.c000066400000000000000000000043431470420105600315370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsHashStateMethodSet_SHA256_TT() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA256_TT // // Purpose: Setup SHA256 method inside the hash state // (using the Intel® Secure Hash Algorithm - New Instructions (Intel® SHA-NI) instructions set // if it is available at run time) // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA256_TT, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA256; pMethod->msgLenRepSize = MLR_SHA256; pMethod->hashInit = sha256_hashInit; pMethod->hashUpdate = sha256_hashUpdate; pMethod->hashOctStr = sha256_hashOctString; pMethod->msgLenRep = sha256_msgRep; #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) if(IsFeatureEnabled(ippCPUID_SHA)) pMethod->hashUpdate = sha256_ni_hashUpdate; #endif return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcpsha256ca.c000066400000000000000000000041161470420105600253510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // cpFinalizeSHA256() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha256/pcpsha256stuff.h" IPP_OWN_DEFN (void, cpFinalizeSHA256, (DigestSHA256 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) { /* select processing function */ #if (_SHA_NI_ENABLING_==_FEATURE_ON_) cpHashProc updateFunc = UpdateSHA256ni; #elif (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_) cpHashProc updateFunc = IsFeatureEnabled(ippCPUID_SHA)? UpdateSHA256ni : UpdateSHA256; #else cpHashProc updateFunc = UpdateSHA256; #endif /* local buffer and it length */ Ipp8u buffer[MBS_SHA256*2]; int bufferLen = inpLen < (MBS_SHA256-(int)MLR_SHA256)? MBS_SHA256 : MBS_SHA256*2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer+inpLen, (cpSize)(bufferLen-inpLen-(int)MLR_SHA256)); /* put processed message length in bits */ processedMsgLen = ENDIANNESS64(processedMsgLen<<3); ((Ipp64u*)(buffer+bufferLen))[-1] = processedMsgLen; /* copmplete hash computation */ updateFunc(pHash, buffer, bufferLen, sha256_cnt); } cryptography-primitives-1.0.0/sources/ippcp/hash/sha256/pcpsha256stuff.h000066400000000000000000000133451470420105600261260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SHA256 // // Contents: // ippsSHA256GetSize() // ippsSHA256Init() // ippsSHA256Pack() // ippsSHA256Unpack() // ippsSHA256Duplicate() // ippsSHA256Update() // ippsSHA256GetTag() // ippsSHA256Final() // ippsSHA256MessageDigest() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #if !defined(_PCP_SHA256_STUFF_H) #define _PCP_SHA256_STUFF_H /* SHA-256, SHA-224 constants */ static const Ipp32u sha256_iv[] = { 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19}; static const Ipp32u sha224_iv[] = { 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4}; static __ALIGN16 const Ipp32u sha256_cnt[] = { 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 }; /* setup init hash value */ __IPPCP_INLINE void hashInit(Ipp32u* pHash, const Ipp32u* iv) { pHash[0] = iv[0]; pHash[1] = iv[1]; pHash[2] = iv[2]; pHash[3] = iv[3]; pHash[4] = iv[4]; pHash[5] = iv[5]; pHash[6] = iv[6]; pHash[7] = iv[7]; } IPP_OWN_DEFN (static void, sha256_hashInit, (void* pHash)) { hashInit((Ipp32u*)pHash, sha256_iv); } IPP_OWN_DEFN (static void, sha224_hashInit, (void* pHash)) { hashInit((Ipp32u*)pHash, sha224_iv); } IPP_OWN_DEFN (static void, sha256_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSHA256(pHash, pMsg, msgLen, sha256_cnt); } #if (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_ || _SHA_NI_ENABLING_==_FEATURE_ON_) IPP_OWN_DEFN (static void, sha256_ni_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSHA256ni(pHash, pMsg, msgLen, sha256_cnt); } #endif /* convert hash into big endian */ IPP_OWN_DEFN (static void, sha256_hashOctString, (Ipp8u* pMD, void* pHashVal)) { /* convert hash into big endian */ ((Ipp32u*)pMD)[0] = ENDIANNESS32(((Ipp32u*)pHashVal)[0]); ((Ipp32u*)pMD)[1] = ENDIANNESS32(((Ipp32u*)pHashVal)[1]); ((Ipp32u*)pMD)[2] = ENDIANNESS32(((Ipp32u*)pHashVal)[2]); ((Ipp32u*)pMD)[3] = ENDIANNESS32(((Ipp32u*)pHashVal)[3]); ((Ipp32u*)pMD)[4] = ENDIANNESS32(((Ipp32u*)pHashVal)[4]); ((Ipp32u*)pMD)[5] = ENDIANNESS32(((Ipp32u*)pHashVal)[5]); ((Ipp32u*)pMD)[6] = ENDIANNESS32(((Ipp32u*)pHashVal)[6]); ((Ipp32u*)pMD)[7] = ENDIANNESS32(((Ipp32u*)pHashVal)[7]); } IPP_OWN_DEFN (static void, sha224_hashOctString, (Ipp8u* pMD, void* pHashVal)) { /* convert hash into big endian */ ((Ipp32u*)pMD)[0] = ENDIANNESS32(((Ipp32u*)pHashVal)[0]); ((Ipp32u*)pMD)[1] = ENDIANNESS32(((Ipp32u*)pHashVal)[1]); ((Ipp32u*)pMD)[2] = ENDIANNESS32(((Ipp32u*)pHashVal)[2]); ((Ipp32u*)pMD)[3] = ENDIANNESS32(((Ipp32u*)pHashVal)[3]); ((Ipp32u*)pMD)[4] = ENDIANNESS32(((Ipp32u*)pHashVal)[4]); ((Ipp32u*)pMD)[5] = ENDIANNESS32(((Ipp32u*)pHashVal)[5]); ((Ipp32u*)pMD)[6] = ENDIANNESS32(((Ipp32u*)pHashVal)[6]); } IPP_OWN_DEFN (static void, sha256_msgRep, (Ipp8u* pDst, Ipp64u lenLo, Ipp64u lenHi)) { IPP_UNREFERENCED_PARAMETER(lenHi); lenLo = ENDIANNESS64(lenLo<<3); ((Ipp64u*)(pDst))[0] = lenLo; } /* // SHA256 init context */ IPP_OWN_DEFN (static IppStatus, GetSizeSHA256, (int* pSize)) { IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsSHA256State); return ippStsNoErr; } IPP_OWN_DEFN (static IppStatus, InitSHA256, (IppsSHA256State* pState, const DigestSHA256 IV)) { /* test state pointer */ IPP_BAD_PTR1_RET(pState); HASH_SET_ID(pState, idCtxSHA256); HASH_LENLO(pState) = 0; HASH_BUFFIDX(pState) = 0; /* setup initial digest */ HASH_VALUE(pState)[0] = IV[0]; HASH_VALUE(pState)[1] = IV[1]; HASH_VALUE(pState)[2] = IV[2]; HASH_VALUE(pState)[3] = IV[3]; HASH_VALUE(pState)[4] = IV[4]; HASH_VALUE(pState)[5] = IV[5]; HASH_VALUE(pState)[6] = IV[6]; HASH_VALUE(pState)[7] = IV[7]; return ippStsNoErr; } #define cpSHA256MessageDigest OWNAPI(cpSHA256MessageDigest) IPP_OWN_DECL (IppStatus, cpSHA256MessageDigest, (DigestSHA256 hash, const Ipp8u* pMsg, int msgLen, const DigestSHA256 IV)) #define cpFinalizeSHA256 OWNAPI(cpFinalizeSHA256) IPP_OWN_DECL (void, cpFinalizeSHA256, (DigestSHA256 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) #endif /* #if !defined(_PCP_SHA256_STUFF_H) */ cryptography-primitives-1.0.0/sources/ippcp/hash/sha384/000077500000000000000000000000001470420105600231665ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/hash/sha384/pcphashmethod_sha384.c000066400000000000000000000031321470420105600272520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethod_SHA384() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethod_SHA384 // // Purpose: Return SHA384 method. // // Returns: // Pointer to SHA384 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA384, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA384, IPP_SHA384_DIGEST_BITSIZE/8, MBS_SHA512, MLR_SHA512, 0, 0, 0, 0 }; method.hashInit = sha512_384_hashInit; method.hashUpdate = sha512_hashUpdate; method.hashOctStr = sha512_384_hashOctString; method.msgLenRep = sha512_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha384/pcphashmethodset_sha384.c000066400000000000000000000034031470420105600277670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethodSet_SHA384() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethodSet_SHA384 // // Purpose: Setup SHA384 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA384, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA384; pMethod->hashLen = IPP_SHA384_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_384_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_384_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha384/pcphashstatemethodset_sha384.c000066400000000000000000000036001470420105600310270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA384 message digest // // Contents: // ippsHashStateMethodSet_SHA384() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA384 // // Purpose: Setup SHA384 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA384, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA384; pMethod->hashLen = IPP_SHA384_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_384_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_384_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/000077500000000000000000000000001470420105600231575ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashmethod_sha512.c000066400000000000000000000031221470420105600272330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethod_SHA512() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethod_SHA512 // // Purpose: Return SHA512 method. // // Returns: // Pointer to SHA512 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA512, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA512, IPP_SHA512_DIGEST_BITSIZE/8, MBS_SHA512, MLR_SHA512, 0, 0, 0, 0 }; method.hashInit = sha512_hashInit; method.hashUpdate = sha512_hashUpdate; method.hashOctStr = sha512_hashOctString; method.msgLenRep = sha512_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashmethod_sha512_224.c000066400000000000000000000031621470420105600276260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethod_SHA512_224() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethod_SHA512_224 // // Purpose: Return SHA512_224 method. // // Returns: // Pointer to SHA512_224 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA512_224, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA512_224, IPP_SHA224_DIGEST_BITSIZE/8, MBS_SHA512, MLR_SHA512, 0, 0, 0, 0 }; method.hashInit = sha512_224_hashInit; method.hashUpdate = sha512_hashUpdate; method.hashOctStr = sha512_224_hashOctString; method.msgLenRep = sha512_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashmethod_sha512_256.c000066400000000000000000000031621470420105600276330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethod_SHA512_256() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethod_SHA512_256 // // Purpose: Return SHA512_256 method. // // Returns: // Pointer to SHA512_256 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SHA512_256, (void) ) { static IppsHashMethod method = { ippHashAlg_SHA512_256, IPP_SHA256_DIGEST_BITSIZE/8, MBS_SHA512, MLR_SHA512, 0, 0, 0, 0 }; method.hashInit = sha512_256_hashInit; method.hashUpdate = sha512_hashUpdate; method.hashOctStr = sha512_256_hashOctString; method.msgLenRep = sha512_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashmethodset_sha512.c000066400000000000000000000033441470420105600277550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethodSet_SHA512() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethodSet_SHA512 // // Purpose: Setup SHA512 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA512, (IppsHashMethod* pMethod) ) { IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA512; pMethod->hashLen = IPP_SHA512_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashmethodset_sha512_224.c000066400000000000000000000034251470420105600303440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethodSet_SHA512_224() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethodSet_SHA512_224 // // Purpose: Return SHA512_224 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA512_224, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA512_224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_224_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_224_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashmethodset_sha512_256.c000066400000000000000000000034271470420105600303530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashMethodSet_SHA512_256() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashMethodSet_SHA512_256 // // Purpose: Setup SHA512_256 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SHA512_256, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SHA512_256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_256_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_256_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashsha512px.c000066400000000000000000000142031470420105600262450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message block processing according to SHA512 // // Contents: // UpdateSHA512() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" #if defined(_ENABLE_ALG_SHA512_) || defined(_ENABLE_ALG_SHA384_) || defined(_ENABLE_ALG_SHA512_224_) || defined(_ENABLE_ALG_SHA512_256_) #if !((_IPP==_IPP_W7) || (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || (_IPP==_IPP_P8) || \ (_IPP==_IPP_S8) || (_IPP>=_IPP_G9) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) /* // SHA512 Specific Macros (reference proposal 256-384-512) // // Note: All operations act on DWORDs (64-bits) */ #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) #define SUM0(x) (ROR64((x),28) ^ ROR64((x),34) ^ ROR64((x),39)) #define SUM1(x) (ROR64((x),14) ^ ROR64((x),18) ^ ROR64((x),41)) #define SIG0(x) (ROR64((x), 1) ^ ROR64((x), 8) ^ LSR64((x), 7)) #define SIG1(x) (ROR64((x),19) ^ ROR64((x),61) ^ LSR64((x), 6)) #define SHA512_UPDATE(i) \ wdat[i&15] += SIG1(wdat[(i+14)&15]) + wdat[(i+9)&15] + SIG0(wdat[(i+1)&15]) #define SHA512_STEP(i,j) \ v[(7-i)&7] += (j ? SHA512_UPDATE(i) : wdat[i&15]) \ + SHA512_cnt_loc[i+j] \ + SUM1(v[(4-i)&7]) \ + CH(v[(4-i)&7], v[(5-i)&7], v[(6-i)&7]); \ v[(3-i)&7] += v[(7-i)&7]; \ v[(7-i)&7] += SUM0(v[(0-i)&7]) + MAJ(v[(0-i)&7], v[(1-i)&7], v[(2-i)&7]) #define COMPACT_SHA512_STEP(A,B,C,D,E,F,G,H, W,K, r) { \ Ipp64u _T1 = (H) + SUM1((E)) + CH((E),(F),(G)) + (W)[(r)] + (K)[(r)]; \ Ipp64u _T2 = SUM0((A)) + MAJ((A),(B),(C)); \ (H) = (G); \ (G) = (F); \ (F) = (E); \ (E) = (D)+_T1; \ (D) = (C); \ (C) = (B); \ (B) = (A); \ (A) = _T1+_T2; \ } /*F* // Name: UpdateSHA512 // // Purpose: Update internal hash according to input message stream. // // Parameters: // uniHash pointer to in/out hash // mblk pointer to message stream // mlen message stream length (multiple by message block size) // uniParam pointer to the optional parameter // *F*/ #if defined(_ALG_SHA512_COMPACT_) IPP_OWN_DEFN (void, UpdateSHA512, (void* uniHash, const Ipp8u* mblk, int mlen, const void* uniPraram)) { Ipp32u* data = (Ipp32u*)mblk; Ipp64u* digest = (Ipp64u*)uniHash; Ipp64u* SHA512_cnt_loc = (Ipp64u*)uniPraram; for(; mlen>=MBS_SHA512; data += MBS_SHA512/sizeof(Ipp32u), mlen -= MBS_SHA512) { int t; Ipp64u W[80]; /* // expand message block */ /* initialize the first 16 words in the array W (remember about endian) */ for(t=0; t<16; t++) { Ipp32u hiX = data[2*t]; Ipp32u loX = data[2*t+1]; #if (IPP_ENDIAN == IPP_BIG_ENDIAN) W[t] = IPP_MAKEDWORD(loX, hiX); #else W[t] = IPP_MAKEDWORD( ENDIANNESS(loX), ENDIANNESS(hiX) ); #endif } for(; t<80; t++) W[t] = SIG1(W[t-2]) + W[t-7] + SIG0(W[t-15]) + W[t-16]; /* // update hash */ { /* init A, B, C, D, E, F, G, H by the input hash */ Ipp64u A = digest[0]; Ipp64u B = digest[1]; Ipp64u C = digest[2]; Ipp64u D = digest[3]; Ipp64u E = digest[4]; Ipp64u F = digest[5]; Ipp64u G = digest[6]; Ipp64u H = digest[7]; for(t=0; t<80; t++) COMPACT_SHA512_STEP(A,B,C,D,E,F,G,H, W,SHA512_cnt_loc, t); /* update hash*/ digest[0] += A; digest[1] += B; digest[2] += C; digest[3] += D; digest[4] += E; digest[5] += F; digest[6] += G; digest[7] += H; } } } #else IPP_OWN_DEFN (void, UpdateSHA512, (void* uniHash, const Ipp8u* mblk, int mlen, const void* uniPraram)) { Ipp32u* data = (Ipp32u*)mblk; Ipp64u* digest = (Ipp64u*)uniHash; Ipp64u* SHA512_cnt_loc = (Ipp64u*)uniPraram; for(; mlen>=MBS_SHA512; data += MBS_SHA512/sizeof(Ipp32u), mlen -= MBS_SHA512) { Ipp64u wdat[16]; int j; Ipp64u v[8]; /* initialize the first 16 words in the array W (remember about endian) */ for(j=0; j<16; j++) { Ipp32u hiX = data[2*j]; Ipp32u loX = data[2*j+1]; #if (IPP_ENDIAN == IPP_BIG_ENDIAN) wdat[j] = IPP_MAKEDWORD(loX, hiX); #else wdat[j] = IPP_MAKEDWORD( ENDIANNESS(loX), ENDIANNESS(hiX) ); #endif } /* copy digest */ CopyBlock(digest, v, IPP_SHA512_DIGEST_BITSIZE/BYTESIZE); for(j=0; j<80; j+=16) { SHA512_STEP( 0, j); SHA512_STEP( 1, j); SHA512_STEP( 2, j); SHA512_STEP( 3, j); SHA512_STEP( 4, j); SHA512_STEP( 5, j); SHA512_STEP( 6, j); SHA512_STEP( 7, j); SHA512_STEP( 8, j); SHA512_STEP( 9, j); SHA512_STEP(10, j); SHA512_STEP(11, j); SHA512_STEP(12, j); SHA512_STEP(13, j); SHA512_STEP(14, j); SHA512_STEP(15, j); } /* update digest */ digest[0] += v[0]; digest[1] += v[1]; digest[2] += v[2]; digest[3] += v[3]; digest[4] += v[4]; digest[5] += v[5]; digest[6] += v[6]; digest[7] += v[7]; } } #endif #endif #endif /* IPP_ALG_HASH_SHA512 */ cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashstatemethodset_sha512.c000066400000000000000000000035701470420105600310170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashStateMethodSet_SHA512() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA512 // // Purpose: Setup SHA512 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA512, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA512; pMethod->hashLen = IPP_SHA512_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashstatemethodset_sha512_224.c000066400000000000000000000036221470420105600314040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashStateMethodSet_SHA512_224() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA512_224 // // Purpose: Return SHA512_224 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA512_224, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA512_224; pMethod->hashLen = IPP_SHA224_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_224_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_224_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcphashstatemethodset_sha512_256.c000066400000000000000000000036241470420105600314130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // ippsHashStateMethodSet_SHA512_256() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sha512/pcpsha512stuff.h" /*F* // Name: ippsHashStateMethodSet_SHA512_256 // // Purpose: Setup SHA512_256 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SHA512_256, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SHA512_256; pMethod->hashLen = IPP_SHA256_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SHA512; pMethod->msgLenRepSize = MLR_SHA512; pMethod->hashInit = sha512_256_hashInit; pMethod->hashUpdate = sha512_hashUpdate; pMethod->hashOctStr = sha512_256_hashOctString; pMethod->msgLenRep = sha512_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sha512/pcpsha512stuff.h000066400000000000000000000217271470420105600261170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SHA512 message digest // // Contents: // SHA512 stuff // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #if !defined(_PCP_SHA512_STUFF_H) #define _PCP_SHA512_STUFF_H /* SHA-512, SHA-384, SHA512-224, SHA512 constants */ static const Ipp64u sha512_iv[] = { CONST_64(0x6A09E667F3BCC908), CONST_64(0xBB67AE8584CAA73B), CONST_64(0x3C6EF372FE94F82B), CONST_64(0xA54FF53A5F1D36F1), CONST_64(0x510E527FADE682D1), CONST_64(0x9B05688C2B3E6C1F), CONST_64(0x1F83D9ABFB41BD6B), CONST_64(0x5BE0CD19137E2179)}; static const Ipp64u sha512_384_iv[] = { CONST_64(0xCBBB9D5DC1059ED8), CONST_64(0x629A292A367CD507), CONST_64(0x9159015A3070DD17), CONST_64(0x152FECD8F70E5939), CONST_64(0x67332667FFC00B31), CONST_64(0x8EB44A8768581511), CONST_64(0xDB0C2E0D64F98FA7), CONST_64(0x47B5481DBEFA4FA4)}; static const Ipp64u sha512_256_iv[] = { CONST_64(0x22312194FC2BF72C), CONST_64(0x9F555FA3C84C64C2), CONST_64(0x2393B86B6F53B151), CONST_64(0x963877195940EABD), CONST_64(0x96283EE2A88EFFE3), CONST_64(0xBE5E1E2553863992), CONST_64(0x2B0199FC2C85B8AA), CONST_64(0x0EB72DDC81C52CA2)}; static const Ipp64u sha512_224_iv[] = { CONST_64(0x8C3D37C819544DA2), CONST_64(0x73E1996689DCD4D6), CONST_64(0x1DFAB7AE32FF9C82), CONST_64(0x679DD514582F9FCF), CONST_64(0x0F6D2B697BD44DA8), CONST_64(0x77E36F7304C48942), CONST_64(0x3F9D85A86A1D36C8), CONST_64(0x1112E6AD91D692A1)}; static __ALIGN16 const Ipp64u sha512_cnt[] = { CONST_64(0x428A2F98D728AE22), CONST_64(0x7137449123EF65CD), CONST_64(0xB5C0FBCFEC4D3B2F), CONST_64(0xE9B5DBA58189DBBC), CONST_64(0x3956C25BF348B538), CONST_64(0x59F111F1B605D019), CONST_64(0x923F82A4AF194F9B), CONST_64(0xAB1C5ED5DA6D8118), CONST_64(0xD807AA98A3030242), CONST_64(0x12835B0145706FBE), CONST_64(0x243185BE4EE4B28C), CONST_64(0x550C7DC3D5FFB4E2), CONST_64(0x72BE5D74F27B896F), CONST_64(0x80DEB1FE3B1696B1), CONST_64(0x9BDC06A725C71235), CONST_64(0xC19BF174CF692694), CONST_64(0xE49B69C19EF14AD2), CONST_64(0xEFBE4786384F25E3), CONST_64(0x0FC19DC68B8CD5B5), CONST_64(0x240CA1CC77AC9C65), CONST_64(0x2DE92C6F592B0275), CONST_64(0x4A7484AA6EA6E483), CONST_64(0x5CB0A9DCBD41FBD4), CONST_64(0x76F988DA831153B5), CONST_64(0x983E5152EE66DFAB), CONST_64(0xA831C66D2DB43210), CONST_64(0xB00327C898FB213F), CONST_64(0xBF597FC7BEEF0EE4), CONST_64(0xC6E00BF33DA88FC2), CONST_64(0xD5A79147930AA725), CONST_64(0x06CA6351E003826F), CONST_64(0x142929670A0E6E70), CONST_64(0x27B70A8546D22FFC), CONST_64(0x2E1B21385C26C926), CONST_64(0x4D2C6DFC5AC42AED), CONST_64(0x53380D139D95B3DF), CONST_64(0x650A73548BAF63DE), CONST_64(0x766A0ABB3C77B2A8), CONST_64(0x81C2C92E47EDAEE6), CONST_64(0x92722C851482353B), CONST_64(0xA2BFE8A14CF10364), CONST_64(0xA81A664BBC423001), CONST_64(0xC24B8B70D0F89791), CONST_64(0xC76C51A30654BE30), CONST_64(0xD192E819D6EF5218), CONST_64(0xD69906245565A910), CONST_64(0xF40E35855771202A), CONST_64(0x106AA07032BBD1B8), CONST_64(0x19A4C116B8D2D0C8), CONST_64(0x1E376C085141AB53), CONST_64(0x2748774CDF8EEB99), CONST_64(0x34B0BCB5E19B48A8), CONST_64(0x391C0CB3C5C95A63), CONST_64(0x4ED8AA4AE3418ACB), CONST_64(0x5B9CCA4F7763E373), CONST_64(0x682E6FF3D6B2B8A3), CONST_64(0x748F82EE5DEFB2FC), CONST_64(0x78A5636F43172F60), CONST_64(0x84C87814A1F0AB72), CONST_64(0x8CC702081A6439EC), CONST_64(0x90BEFFFA23631E28), CONST_64(0xA4506CEBDE82BDE9), CONST_64(0xBEF9A3F7B2C67915), CONST_64(0xC67178F2E372532B), CONST_64(0xCA273ECEEA26619C), CONST_64(0xD186B8C721C0C207), CONST_64(0xEADA7DD6CDE0EB1E), CONST_64(0xF57D4F7FEE6ED178), CONST_64(0x06F067AA72176FBA), CONST_64(0x0A637DC5A2C898A6), CONST_64(0x113F9804BEF90DAE), CONST_64(0x1B710B35131C471B), CONST_64(0x28DB77F523047D84), CONST_64(0x32CAAB7B40C72493), CONST_64(0x3C9EBE0A15C9BEBC), CONST_64(0x431D67C49C100D4C), CONST_64(0x4CC5D4BECB3E42B6), CONST_64(0x597F299CFC657E2A), CONST_64(0x5FCB6FAB3AD6FAEC), CONST_64(0x6C44198C4A475817) }; /* setup init hash value */ __IPPCP_INLINE void hashInit(Ipp64u* pHash, const Ipp64u* iv) { pHash[0] = iv[0]; pHash[1] = iv[1]; pHash[2] = iv[2]; pHash[3] = iv[3]; pHash[4] = iv[4]; pHash[5] = iv[5]; pHash[6] = iv[6]; pHash[7] = iv[7]; } IPP_OWN_DEFN (static void, sha512_hashInit, (void* pHash)) { hashInit((Ipp64u*)pHash, sha512_iv); } IPP_OWN_DEFN (static void, sha512_384_hashInit, (void* pHash)) { hashInit((Ipp64u*)pHash, sha512_384_iv); } IPP_OWN_DEFN (static void, sha512_256_hashInit, (void* pHash)) { hashInit((Ipp64u*)pHash, sha512_256_iv); } IPP_OWN_DEFN (static void, sha512_224_hashInit, (void* pHash)) { hashInit((Ipp64u*)pHash, sha512_224_iv); } IPP_OWN_DEFN (static void, sha512_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSHA512(pHash, pMsg, msgLen, sha512_cnt); } /* convert hash into big endian */ IPP_OWN_DEFN (static void, sha512_hashOctString, (Ipp8u* pMD, void* pHashVal)) { ((Ipp64u*)pMD)[0] = ENDIANNESS64(((Ipp64u*)pHashVal)[0]); ((Ipp64u*)pMD)[1] = ENDIANNESS64(((Ipp64u*)pHashVal)[1]); ((Ipp64u*)pMD)[2] = ENDIANNESS64(((Ipp64u*)pHashVal)[2]); ((Ipp64u*)pMD)[3] = ENDIANNESS64(((Ipp64u*)pHashVal)[3]); ((Ipp64u*)pMD)[4] = ENDIANNESS64(((Ipp64u*)pHashVal)[4]); ((Ipp64u*)pMD)[5] = ENDIANNESS64(((Ipp64u*)pHashVal)[5]); ((Ipp64u*)pMD)[6] = ENDIANNESS64(((Ipp64u*)pHashVal)[6]); ((Ipp64u*)pMD)[7] = ENDIANNESS64(((Ipp64u*)pHashVal)[7]); } IPP_OWN_DEFN (static void, sha512_384_hashOctString, (Ipp8u* pMD, void* pHashVal)) { ((Ipp64u*)pMD)[0] = ENDIANNESS64(((Ipp64u*)pHashVal)[0]); ((Ipp64u*)pMD)[1] = ENDIANNESS64(((Ipp64u*)pHashVal)[1]); ((Ipp64u*)pMD)[2] = ENDIANNESS64(((Ipp64u*)pHashVal)[2]); ((Ipp64u*)pMD)[3] = ENDIANNESS64(((Ipp64u*)pHashVal)[3]); ((Ipp64u*)pMD)[4] = ENDIANNESS64(((Ipp64u*)pHashVal)[4]); ((Ipp64u*)pMD)[5] = ENDIANNESS64(((Ipp64u*)pHashVal)[5]); } IPP_OWN_DEFN (static void, sha512_256_hashOctString, (Ipp8u* pMD, void* pHashVal)) { ((Ipp64u*)pMD)[0] = ENDIANNESS64(((Ipp64u*)pHashVal)[0]); ((Ipp64u*)pMD)[1] = ENDIANNESS64(((Ipp64u*)pHashVal)[1]); ((Ipp64u*)pMD)[2] = ENDIANNESS64(((Ipp64u*)pHashVal)[2]); ((Ipp64u*)pMD)[3] = ENDIANNESS64(((Ipp64u*)pHashVal)[3]); } IPP_OWN_DEFN (static void, sha512_224_hashOctString, (Ipp8u* pMD, void* pHashVal)) { ((Ipp64u*)pMD)[0] = ENDIANNESS64(((Ipp64u*)pHashVal)[0]); ((Ipp64u*)pMD)[1] = ENDIANNESS64(((Ipp64u*)pHashVal)[1]); ((Ipp64u*)pMD)[2] = ENDIANNESS64(((Ipp64u*)pHashVal)[2]); ((Ipp32u*)pMD)[6] = ENDIANNESS32(((Ipp32u*)pHashVal)[7]); } IPP_OWN_DEFN (static void, sha512_msgRep, (Ipp8u* pDst, Ipp64u lenLo, Ipp64u lenHi)) { lenHi = LSL64(lenHi,3) | LSR64(lenLo,63-3); lenLo = LSL64(lenLo,3); ((Ipp64u*)(pDst))[0] = ENDIANNESS64(lenHi); ((Ipp64u*)(pDst))[1] = ENDIANNESS64(lenLo); } IPP_OWN_DEFN (static IppStatus, GetSizeSHA512, (int* pSize)) { /* test pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsSHA512State); return ippStsNoErr; } /* #define cpFinalizeSHA512 OWNAPI(cpFinalizeSHA512) */ /* IPP_OWN_DECL (void, cpFinalizeSHA512, (DigestSHA512 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u lenLo, Ipp64u lenHi)) */ #define cpSHA512MessageDigest OWNAPI(cpSHA512MessageDigest) IPP_OWN_DECL (IppStatus, cpSHA512MessageDigest, (DigestSHA512 hash, const Ipp8u* pMsg, int msgLen, const DigestSHA512 IV)) #define InitSHA512 OWNAPI(InitSHA512) IPP_OWN_DECL (IppStatus, InitSHA512, (IppsSHA512State* pState, const DigestSHA512 IV)) IPP_OWN_DEFN (static void, cpFinalizeSHA512, (DigestSHA512 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u lenLo, Ipp64u lenHi)) { /* local buffer and it length */ Ipp8u buffer[MBS_SHA512*2]; int bufferLen = inpLen < (MBS_SHA512-(int)MLR_SHA512)? MBS_SHA512 : MBS_SHA512*2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer+inpLen, (cpSize)(bufferLen-inpLen-(int)MLR_SHA512)); /* message length representation */ lenHi = LSL64(lenHi,3) | LSR64(lenLo,63-3); lenLo = LSL64(lenLo,3); ((Ipp64u*)(buffer+bufferLen))[-2] = ENDIANNESS64(lenHi); ((Ipp64u*)(buffer+bufferLen))[-1] = ENDIANNESS64(lenLo); /* copmplete hash computation */ UpdateSHA512(pHash, buffer, bufferLen, sha512_cnt); } #endif /* #if !defined(_PCP_SHA512_STUFF_H) */ cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/000077500000000000000000000000001470420105600226565ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/pcphashmethod_sm3.c000066400000000000000000000033101470420105600264300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SM3 // // Contents: // ippsHashMethod_SM3() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sm3/pcpsm3stuff.h" /*F* // Name: ippsHashMethod_SM3 // // Purpose: Return SM3 method. // // Returns: // Pointer to SM3 hash-method. // *F*/ IPPFUN( const IppsHashMethod*, ippsHashMethod_SM3, (void) ) { static IppsHashMethod method = { ippHashAlg_SM3, IPP_SM3_DIGEST_BITSIZE/8, MBS_SM3, MLR_SM3, 0, 0, 0, 0 }; method.hashInit = sm3_hashInit; #if (_IPP32E >= _IPP32E_L9) if (IsFeatureEnabled(ippCPUID_AVX2SM3)) { method.hashUpdate = sm3_hashUpdate_ni; } else #endif { method.hashUpdate = sm3_hashUpdate; } method.hashOctStr = sm3_hashOctString; method.msgLenRep = sm3_msgRep; return &method; } cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/pcphashmethodset_sm3.c000066400000000000000000000035641470420105600271570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SM3 // // Contents: // ippsHashMethodSet_SM3() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sm3/pcpsm3stuff.h" /*F* // Name: ippsHashMethodSet_SM3 // // Purpose: Setup SM3 method. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashMethodSet_SM3, (IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR1_RET(pMethod); pMethod->hashAlgId = ippHashAlg_SM3; pMethod->hashLen = IPP_SM3_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SM3; pMethod->msgLenRepSize = MLR_SM3; pMethod->hashInit = sm3_hashInit; #if (_IPP32E >= _IPP32E_L9) if (IsFeatureEnabled(ippCPUID_AVX2SM3)) { pMethod->hashUpdate = sm3_hashUpdate_ni; } else #endif { pMethod->hashUpdate = sm3_hashUpdate; } pMethod->hashOctStr = sm3_hashOctString; pMethod->msgLenRep = sm3_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/pcphashsm3px.c000066400000000000000000000245641470420105600254560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message block processing according to SM5 // // Contents: // UpdateSM3() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" #if defined(_ENABLE_ALG_SM3_) #if !((_IPP32E>=_IPP32E_U8) || (_IPP32E==_IPP32E_N8) ) /* // SM3 Specific Macros // (reference SM3 Cryptographic Hash Algorithm, // Chinese Commercial Cryptography Administration Office, 2010.12) */ /* T1 and T2 are base for additive const generation */ #define T1 (0x79CC4519) #define T2 (0x7A879D8A) // boolean functions (0<=nr<16) #define FF1(x,y,z) ((x)^(y)^(z)) #define GG1(x,y,z) ((x)^(y)^(z)) // boolean functions (16<=nr<64) #define FF2(x,y,z) (((x)&(y)) | ((x)&(z)) | ((y)&(z))) #define GG2(x,y,z) (((x)&(y)) | (~(x)&(z))) // P0 permutation: #define P0(x) ((x) ^ ROL32((x),9) ^ ROL32((x),17)) // P1 permutation: #define P1(x) ((x) ^ ROL32((x),15) ^ ROL32((x),23)) // update W #define WUPDATE(nr, W) (P1(W[((nr)-16)&15] ^ W[((nr)-9)&15] ^ ROL32(W[((nr)-3)&15],15)) ^ ROL32(W[((nr)-13)&15],7) ^ W[((nr)-6)&15]) // SM3 steps #define SM3_STEP1(nr, A,B,C,D,E,F,G,H, Tj, W) { \ TT1 = FF1(A,B,C) + D + (W[nr&15] ^ W[(nr+4)&15]); \ TT2 = GG1(E,F,G) + H + W[nr&15]; \ H = ROL32(A,12); \ D = ROL32(H + E +Tj, 7); \ H ^= D; \ D += TT2; \ H += TT1; \ B = ROL32(B, 9); \ D = P0(D); \ F = ROL32(F, 19); \ /*Tj = ROL32(Tj, 1);*/ \ W[(nr)&15] = WUPDATE(nr, W); \ } #define SM3_STEP2(nr, A,B,C,D,E,F,G,H, Tj, W) { \ TT1 = FF2(A,B,C) + D + (W[nr&15] ^ W[(nr+4)&15]); \ TT2 = GG2(E,F,G) + H + W[nr&15]; \ H = ROL32(A,12); \ D = ROL32(H + E +Tj, 7); \ H ^= D; \ D += TT2; \ H += TT1; \ B = ROL32(B, 9); \ D = P0(D); \ F = ROL32(F, 19); \ /*Tj = ROL32(Tj, 1);*/ \ W[(nr)&15] = WUPDATE(nr, W); \ } #define SM3_STEP3(nr, A,B,C,D,E,F,G,H, Tj, W) { \ TT1 = FF2(A,B,C) + D + (W[nr&15] ^ W[(nr+4)&15]); \ TT2 = GG2(E,F,G) + H + W[nr&15]; \ H = ROL32(A,12); \ D = ROL32(H + E +Tj, 7); \ H ^= D; \ D += TT2; \ H += TT1; \ B = ROL32(B, 9); \ D = P0(D); \ F = ROL32(F, 19); \ /*Tj = ROL32(Tj, 1);*/ \ } #define COMPACT_SM3_STEP(A,B,C,D,E,F,G,H, FF, GG, W,Tj, r) { \ TT1 = FF((r)&0x30, A,B,C) + D + (W[(r)] ^ W[(r)+4]); \ TT2 = GG((r)&0x30, E,F,G) + H + W[(r)]; \ \ _H = ROL32(A,12); \ _D = ROL32(_H + E +Tj[(r)], 7); \ _H ^= _D; \ _D += TT2; \ _H += TT1; \ _D = P0(_D);\ \ H = G; \ G = ROL32(F,19); \ F = E; \ E =_D; \ D = C; \ C = ROL32(B, 9); \ B = A; \ A =_H; \ } /*F* // Name: UpdateSM3 // // Purpose: Update internal hash according to input message stream. // // Parameters: // uniHash pointer to in/out hash // mblk pointer to message stream // mlen message stream length (multiple by message block size) // uniParam pointer to the optional parameter // *F*/ #if defined(_ALG_SM3_COMPACT_) __IPPCP_INLINE Ipp32u MagicFF(int s, Ipp32u a, Ipp32u b, Ipp32u c) { switch(s) { case 0: return FF1(a,b,c); default:return FF2(a,b,c); } } __IPPCP_INLINE Ipp32u MagicGG(int s, Ipp32u e, Ipp32u f, Ipp32u g) { switch(s) { case 0: return GG1(e,f,g); default:return GG2(e,f,g); } } IPP_OWN_DEFN (void, UpdateSM3, (void* uniHash, const Ipp8u* mblk, int mlen, const void* uniParam)) { Ipp32u* data = (Ipp32u*)mblk; Ipp32u* hash = (Ipp32u*)uniHash; Ipp32u* SM3_cnt_loc = (Ipp32u*)uniParam; for(; mlen>=MBS_SM3; data += MBS_SM3/sizeof(Ipp32u), mlen -= MBS_SM3) { int r; /* // expand message block */ Ipp32u W[68]; /* initialize the first 16 words in the array W (remember about endian) */ for(r=0; r<16; r++) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) W[r] = data[r]; #else W[r] = ENDIANNESS( data[r] ); #endif } for(; r<68; r++) W[r] = P1(W[r-16] ^ W[r-9] ^ ROL32(W[r-3],15)) ^ ROL32(W[r-13],7) ^ W[r-6]; /* // update hash */ { /* init A, B, C, D, E, F, G, H by the input hash */ Ipp32u A = hash[0]; Ipp32u B = hash[1]; Ipp32u C = hash[2]; Ipp32u D = hash[3]; Ipp32u E = hash[4]; Ipp32u F = hash[5]; Ipp32u G = hash[6]; Ipp32u H = hash[7]; Ipp32u TT1, TT2, _H, _D; for(r=0; r<64; r++) COMPACT_SM3_STEP(A,B,C,D,E,F,G,H, MagicFF,MagicGG, W, SM3_cnt_loc, r); /* update hash */ hash[0] ^= A; hash[1] ^= B; hash[2] ^= C; hash[3] ^= D; hash[4] ^= E; hash[5] ^= F; hash[6] ^= G; hash[7] ^= H; } } } #else IPP_OWN_DEFN (void, UpdateSM3, (void* uniHash, const Ipp8u* mblk, int mlen, const void* uniParam)) { Ipp32u* data = (Ipp32u*)mblk; Ipp32u* hash = (Ipp32u*)uniHash; Ipp32u* SM3_cnt_loc = (Ipp32u*)uniParam; for(; mlen>=MBS_SM3; data += MBS_SM3/sizeof(Ipp32u), mlen -= MBS_SM3) { /* copy input hash */ Ipp32u A = hash[0]; Ipp32u B = hash[1]; Ipp32u C = hash[2]; Ipp32u D = hash[3]; Ipp32u E = hash[4]; Ipp32u F = hash[5]; Ipp32u G = hash[6]; Ipp32u H = hash[7]; Ipp32u W[16]; int j; /* initialize the first 16 words in the array W (remember about endian) */ for(j=0; j<16; j++) { #if (IPP_ENDIAN == IPP_BIG_ENDIAN) W[j] = data[j]; #else W[j] = ENDIANNESS( data[j] ); #endif } /* apply compression function */ { Ipp32u TT1, TT2; SM3_STEP1( 0, A,B,C,D,E,F,G,H, SM3_cnt_loc[0], W); SM3_STEP1( 1, H,A,B,C,D,E,F,G, SM3_cnt_loc[1], W); SM3_STEP1( 2, G,H,A,B,C,D,E,F, SM3_cnt_loc[2], W); SM3_STEP1( 3, F,G,H,A,B,C,D,E, SM3_cnt_loc[3], W); SM3_STEP1( 4, E,F,G,H,A,B,C,D, SM3_cnt_loc[4], W); SM3_STEP1( 5, D,E,F,G,H,A,B,C, SM3_cnt_loc[5], W); SM3_STEP1( 6, C,D,E,F,G,H,A,B, SM3_cnt_loc[6], W); SM3_STEP1( 7, B,C,D,E,F,G,H,A, SM3_cnt_loc[7], W); SM3_STEP1( 8, A,B,C,D,E,F,G,H, SM3_cnt_loc[ 8], W); SM3_STEP1( 9, H,A,B,C,D,E,F,G, SM3_cnt_loc[ 9], W); SM3_STEP1(10, G,H,A,B,C,D,E,F, SM3_cnt_loc[10], W); SM3_STEP1(11, F,G,H,A,B,C,D,E, SM3_cnt_loc[11], W); SM3_STEP1(12, E,F,G,H,A,B,C,D, SM3_cnt_loc[12], W); SM3_STEP1(13, D,E,F,G,H,A,B,C, SM3_cnt_loc[13], W); SM3_STEP1(14, C,D,E,F,G,H,A,B, SM3_cnt_loc[14], W); SM3_STEP1(15, B,C,D,E,F,G,H,A, SM3_cnt_loc[15], W); SM3_STEP2(16, A,B,C,D,E,F,G,H, SM3_cnt_loc[16], W); SM3_STEP2(17, H,A,B,C,D,E,F,G, SM3_cnt_loc[17], W); SM3_STEP2(18, G,H,A,B,C,D,E,F, SM3_cnt_loc[18], W); SM3_STEP2(19, F,G,H,A,B,C,D,E, SM3_cnt_loc[19], W); SM3_STEP2(20, E,F,G,H,A,B,C,D, SM3_cnt_loc[20], W); SM3_STEP2(21, D,E,F,G,H,A,B,C, SM3_cnt_loc[21], W); SM3_STEP2(22, C,D,E,F,G,H,A,B, SM3_cnt_loc[22], W); SM3_STEP2(23, B,C,D,E,F,G,H,A, SM3_cnt_loc[23], W); SM3_STEP2(24, A,B,C,D,E,F,G,H, SM3_cnt_loc[24], W); SM3_STEP2(25, H,A,B,C,D,E,F,G, SM3_cnt_loc[25], W); SM3_STEP2(26, G,H,A,B,C,D,E,F, SM3_cnt_loc[26], W); SM3_STEP2(27, F,G,H,A,B,C,D,E, SM3_cnt_loc[27], W); SM3_STEP2(28, E,F,G,H,A,B,C,D, SM3_cnt_loc[28], W); SM3_STEP2(29, D,E,F,G,H,A,B,C, SM3_cnt_loc[29], W); SM3_STEP2(30, C,D,E,F,G,H,A,B, SM3_cnt_loc[30], W); SM3_STEP2(31, B,C,D,E,F,G,H,A, SM3_cnt_loc[31], W); SM3_STEP2(32, A,B,C,D,E,F,G,H, SM3_cnt_loc[32], W); SM3_STEP2(33, H,A,B,C,D,E,F,G, SM3_cnt_loc[33], W); SM3_STEP2(34, G,H,A,B,C,D,E,F, SM3_cnt_loc[34], W); SM3_STEP2(35, F,G,H,A,B,C,D,E, SM3_cnt_loc[35], W); SM3_STEP2(36, E,F,G,H,A,B,C,D, SM3_cnt_loc[36], W); SM3_STEP2(37, D,E,F,G,H,A,B,C, SM3_cnt_loc[37], W); SM3_STEP2(38, C,D,E,F,G,H,A,B, SM3_cnt_loc[38], W); SM3_STEP2(39, B,C,D,E,F,G,H,A, SM3_cnt_loc[39], W); SM3_STEP2(40, A,B,C,D,E,F,G,H, SM3_cnt_loc[40], W); SM3_STEP2(41, H,A,B,C,D,E,F,G, SM3_cnt_loc[41], W); SM3_STEP2(42, G,H,A,B,C,D,E,F, SM3_cnt_loc[42], W); SM3_STEP2(43, F,G,H,A,B,C,D,E, SM3_cnt_loc[43], W); SM3_STEP2(44, E,F,G,H,A,B,C,D, SM3_cnt_loc[44], W); SM3_STEP2(45, D,E,F,G,H,A,B,C, SM3_cnt_loc[45], W); SM3_STEP2(46, C,D,E,F,G,H,A,B, SM3_cnt_loc[46], W); SM3_STEP2(47, B,C,D,E,F,G,H,A, SM3_cnt_loc[47], W); SM3_STEP2(48, A,B,C,D,E,F,G,H, SM3_cnt_loc[48], W); SM3_STEP2(49, H,A,B,C,D,E,F,G, SM3_cnt_loc[49], W); SM3_STEP2(50, G,H,A,B,C,D,E,F, SM3_cnt_loc[50], W); SM3_STEP2(51, F,G,H,A,B,C,D,E, SM3_cnt_loc[51], W); SM3_STEP3(52, E,F,G,H,A,B,C,D, SM3_cnt_loc[52], W); SM3_STEP3(53, D,E,F,G,H,A,B,C, SM3_cnt_loc[53], W); SM3_STEP3(54, C,D,E,F,G,H,A,B, SM3_cnt_loc[54], W); SM3_STEP3(55, B,C,D,E,F,G,H,A, SM3_cnt_loc[55], W); SM3_STEP3(56, A,B,C,D,E,F,G,H, SM3_cnt_loc[56], W); SM3_STEP3(57, H,A,B,C,D,E,F,G, SM3_cnt_loc[57], W); SM3_STEP3(58, G,H,A,B,C,D,E,F, SM3_cnt_loc[58], W); SM3_STEP3(59, F,G,H,A,B,C,D,E, SM3_cnt_loc[59], W); SM3_STEP3(60, E,F,G,H,A,B,C,D, SM3_cnt_loc[60], W); SM3_STEP3(61, D,E,F,G,H,A,B,C, SM3_cnt_loc[61], W); SM3_STEP3(62, C,D,E,F,G,H,A,B, SM3_cnt_loc[62], W); SM3_STEP3(63, B,C,D,E,F,G,H,A, SM3_cnt_loc[63], W); } /* update hash */ hash[0] ^= A; hash[1] ^= B; hash[2] ^= C; hash[3] ^= D; hash[4] ^= E; hash[5] ^= F; hash[6] ^= G; hash[7] ^= H; } } #endif #endif /* _PX/_W7/_T7, _MX/_M7 versions */ #endif /* IPP_ALG_HASH_SM3 */ cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/pcphashstatemethodset_sm3.c000066400000000000000000000037611470420105600302170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SM3 // // Contents: // ippsHashStateMethodSet_SM3() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sm3/pcpsm3stuff.h" /*F* // Name: ippsHashStateMethodSet_SM3 // // Purpose: Setup SM3 method inside the hash state. // // Returns: Reason: // ippStsNullPtrErr pMethod == NULL or pState == NULL // ippStsNoErr no errors // *F*/ IPPFUN( IppStatus, ippsHashStateMethodSet_SM3, (IppsHashState_rmf* pState, IppsHashMethod* pMethod) ) { /* test pointers */ IPP_BAD_PTR2_RET(pState, pMethod); HASH_METHOD(pState) = pMethod; pMethod->hashAlgId = ippHashAlg_SM3; pMethod->hashLen = IPP_SM3_DIGEST_BITSIZE/8; pMethod->msgBlkSize = MBS_SM3; pMethod->msgLenRepSize = MLR_SM3; pMethod->hashInit = sm3_hashInit; #if (_IPP32E >= _IPP32E_L9) if (IsFeatureEnabled(ippCPUID_AVX2SM3)) { pMethod->hashUpdate = sm3_hashUpdate_ni; } else #endif { pMethod->hashUpdate = sm3_hashUpdate; } pMethod->hashOctStr = sm3_hashOctString; pMethod->msgLenRep = sm3_msgRep; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/pcpsm3ca.c000066400000000000000000000033461470420105600245410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SM3 // // Contents: // cpFinalizeSM3() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "hash/sm3/pcpsm3stuff.h" IPP_OWN_DEFN (void, cpFinalizeSM3, (DigestSHA1 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) { /* local buffer and it length */ Ipp8u buffer[MBS_SM3*2]; int bufferLen = inpLen < (MBS_SM3-(int)MLR_SM3)? MBS_SM3 : MBS_SM3*2; /* copy rest of message into internal buffer */ CopyBlock(inpBuffer, buffer, inpLen); /* pad message */ buffer[inpLen++] = 0x80; PadBlock(0, buffer+inpLen, (cpSize)(bufferLen-inpLen-(int)MLR_SM3)); /* put processed message length in bits */ processedMsgLen = ENDIANNESS64(processedMsgLen<<3); ((Ipp64u*)(buffer+bufferLen))[-1] = processedMsgLen; /* copmplete hash computation */ UpdateSM3(pHash, buffer, bufferLen, sm3_cnt); } cryptography-primitives-1.0.0/sources/ippcp/hash/sm3/pcpsm3stuff.h000066400000000000000000000072131470420105600253070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Digesting message according to SM3 // // Contents: // SM3 methods and constants // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #if !defined _PCP_SM3_STUFF_H #define _PCP_SM3_STUFF_H /* SM3 constants */ static const Ipp32u sm3_iv[] = { 0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600, 0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E}; static __ALIGN16 const Ipp32u sm3_cnt[] = { 0x79CC4519,0xF3988A32,0xE7311465,0xCE6228CB,0x9CC45197,0x3988A32F,0x7311465E,0xE6228CBC, 0xCC451979,0x988A32F3,0x311465E7,0x6228CBCE,0xC451979C,0x88A32F39,0x11465E73,0x228CBCE6, 0x9D8A7A87,0x3B14F50F,0x7629EA1E,0xEC53D43C,0xD8A7A879,0xB14F50F3,0x629EA1E7,0xC53D43CE, 0x8A7A879D,0x14F50F3B,0x29EA1E76,0x53D43CEC,0xA7A879D8,0x4F50F3B1,0x9EA1E762,0x3D43CEC5, 0x7A879D8A,0xF50F3B14,0xEA1E7629,0xD43CEC53,0xA879D8A7,0x50F3B14F,0xA1E7629E,0x43CEC53D, 0x879D8A7A,0x0F3B14F5,0x1E7629EA,0x3CEC53D4,0x79D8A7A8,0xF3B14F50,0xE7629EA1,0xCEC53D43, 0x9D8A7A87,0x3B14F50F,0x7629EA1E,0xEC53D43C,0xD8A7A879,0xB14F50F3,0x629EA1E7,0xC53D43CE, 0x8A7A879D,0x14F50F3B,0x29EA1E76,0x53D43CEC,0xA7A879D8,0x4F50F3B1,0x9EA1E762,0x3D43CEC5 }; IPP_OWN_DEFN (static void, sm3_hashInit, (void* pHash)) { /* setup initial digest */ ((Ipp32u*)pHash)[0] = sm3_iv[0]; ((Ipp32u*)pHash)[1] = sm3_iv[1]; ((Ipp32u*)pHash)[2] = sm3_iv[2]; ((Ipp32u*)pHash)[3] = sm3_iv[3]; ((Ipp32u*)pHash)[4] = sm3_iv[4]; ((Ipp32u*)pHash)[5] = sm3_iv[5]; ((Ipp32u*)pHash)[6] = sm3_iv[6]; ((Ipp32u*)pHash)[7] = sm3_iv[7]; } IPP_OWN_DEFN (static void, sm3_hashUpdate, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSM3(pHash, pMsg, msgLen, sm3_cnt); } #if (_IPP32E >= _IPP32E_L9) IPP_OWN_DEFN (static void, sm3_hashUpdate_ni, (void* pHash, const Ipp8u* pMsg, int msgLen)) { UpdateSM3ni(pHash, pMsg, msgLen, sm3_cnt); } #endif IPP_OWN_DEFN (static void, sm3_hashOctString, (Ipp8u* pMD, void* pHashVal)) { /* convert hash into big endian */ ((Ipp32u*)pMD)[0] = ENDIANNESS32(((Ipp32u*)pHashVal)[0]); ((Ipp32u*)pMD)[1] = ENDIANNESS32(((Ipp32u*)pHashVal)[1]); ((Ipp32u*)pMD)[2] = ENDIANNESS32(((Ipp32u*)pHashVal)[2]); ((Ipp32u*)pMD)[3] = ENDIANNESS32(((Ipp32u*)pHashVal)[3]); ((Ipp32u*)pMD)[4] = ENDIANNESS32(((Ipp32u*)pHashVal)[4]); ((Ipp32u*)pMD)[5] = ENDIANNESS32(((Ipp32u*)pHashVal)[5]); ((Ipp32u*)pMD)[6] = ENDIANNESS32(((Ipp32u*)pHashVal)[6]); ((Ipp32u*)pMD)[7] = ENDIANNESS32(((Ipp32u*)pHashVal)[7]); } IPP_OWN_DEFN (static void, sm3_msgRep, (Ipp8u* pDst, Ipp64u lenLo, Ipp64u lenHi)) { IPP_UNREFERENCED_PARAMETER(lenHi); lenLo = ENDIANNESS64(lenLo<<3); ((Ipp64u*)(pDst))[0] = lenLo; } #define cpFinalizeSM3 OWNAPI(cpFinalizeSM3) IPP_OWN_DECL (void, cpFinalizeSM3, (DigestSHA1 pHash, const Ipp8u* inpBuffer, int inpLen, Ipp64u processedMsgLen)) #endif /* #if !defined _PCP_SM3_STUFF_H */ cryptography-primitives-1.0.0/sources/ippcp/ifma_amm52x20.c000066400000000000000000000240221470420105600236440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_norm52x.h" #include "ifma_rsa_arith.h" #define ADD104(rh, rl, ih, il) { \ rl += il; \ rh += ih; \ rh += (rl>52U) | rh<<(64U-52U)) /* * Almost Montgomery Multiplication in 2^52-radix * * Data represented as 20-qwords arrays in 2^52-radix. * */ IPP_OWN_DEFN(void, ifma256_amm52x20, (Ipp64u out[20], const Ipp64u a [20], const Ipp64u b [20], const Ipp64u m [20], Ipp64u k0)) { /* R0, R1, R2 holds result */ U64 R0 = get_zero64(); U64 R1 = get_zero64(); U64 R2 = get_zero64(); /* High part of 512bit result in 256bit mode */ U64 R0h = get_zero64(); U64 R1h = get_zero64(); U64 R2h = get_zero64(); U64 Bi, Yi; Ipp64u m0 = m[0]; Ipp64u a0 = a[0]; Ipp64u acc0 = 0; int i; for (i=0; i<20; i++) { Ipp64u t0, t1, t2, yi; Bi = set64((long long)b[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0, 0, t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a, 64*0) fma52x8lo_mem(R1, R1, Bi, a, 64*1) fma52x8lo_mem_len(R2, R2, Bi, a, 64*2, 4) fma52x8lo_mem(R0, R0, Yi, m, 64*0) fma52x8lo_mem(R1, R1, Yi, m, 64*1) fma52x8lo_mem_len(R2, R2, Yi, m, 64*2, 4) shift64_imm(R0, R0h, 1) shift64_imm(R0h, R1, 1) shift64_imm(R1, R1h, 1) shift64_imm(R1h, R2, 1) shift64_imm(R2, get_zero64(), 1) /* "shift" R */ t0 = get64(R0, 0); acc0 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0, R0, Bi, a, 64*0) fma52x8hi_mem(R1, R1, Bi, a, 64*1) fma52x8hi_mem_len(R2, R2, Bi, a, 64*2, 4) /* R += M*Yi (hi) */ fma52x8hi_mem(R0, R0, Yi, m, 64*0) fma52x8hi_mem(R1, R1, Yi, m, 64*1) fma52x8hi_mem_len(R2, R2, Yi, m, 64*2, 4) } /* Set R0[0] == acc0 */ Bi = set64((long long)acc0); R0 = blend64(R0, Bi, 1); NORMALIZE_52x20(R0, R1, R2) storeu64(out + 0*4, R0); storeu64(out + 1*4, R0h); storeu64(out + 2*4, R1); storeu64(out + 3*4, R1h); storeu64(out + 4*4, R2); } #if 0 /* * Almost Montgomery Multiplication in 2^52-radix * * Data represented as 20-qwords arrays in 2^52-radix. * * Note: |a| and |m| shall be zero-padded on 32 bytes (see R2h usage). * this allows to save on alignr's. * */ IPP_OWN_DEFN(void, ifma256_amm52x20, (Ipp64u out[20], const Ipp64u a [24], /* 32-byte zero-padded */ const Ipp64u b [20], const Ipp64u m [24], /* 32-byte zero-padded */ Ipp64u k0)) { /* R0, R1, R2 holds result */ U64 R0 = get_zero64(); U64 R1 = get_zero64(); U64 R2 = get_zero64(); /* High part of 512bit result in 256bit mode */ U64 R0h = get_zero64(); U64 R1h = get_zero64(); U64 R2h = get_zero64(); U64 Bi, Yi; Ipp64u m0 = m[0]; Ipp64u a0 = a[0]; Ipp64u acc0 = 0; int i; for(i=0; i<20; i+=4) { Ipp64u t0, t1, t2, yi; /* =================================== */ Bi = set64((long long)b[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2,acc0, 0,t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2,acc0, t1,t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a, 64*0-8*0) fma52x8lo_mem(R1, R1, Bi, a, 64*1-8*0) fma52x8lo_mem_len(R2, R2, Bi, a, 64*2-8*0, 4) fma52x8lo_mem(R0, R0, Yi, m, 64*0-8*0) fma52x8lo_mem(R1, R1, Yi, m, 64*1-8*0) fma52x8lo_mem_len(R2, R2, Yi, m, 64*2-8*0, 4) /* "shift" R */ t0 = get64(R0, 1); acc0 += t0; fma52x8hi_mem(R0, R0, Bi, a,64*0-8*1) /* U = A*Bi (hi) */ fma52x8hi_mem(R1, R1, Bi, a,64*1-8*1) fma52x8hi_mem(R2, R2, Bi, a,64*2-8*1) fma52x8hi_mem(R0, R0, Yi, m,64*0-8*1) /* R += M*Yi (hi) */ fma52x8hi_mem(R1, R1, Yi, m,64*1-8*1) fma52x8hi_mem(R2, R2, Yi, m,64*2-8*1) /* =================================== */ Bi = set64((long long)b[i+1]); /* broadcast(b[i+1]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i+1], &t2); /* (t2:t0) = acc0 + a[0]*b[i+1] */ ADD104(t2,acc0, 0,t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2,acc0, t1,t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a,64*0-8*1) fma52x8lo_mem(R1, R1, Bi, a,64*1-8*1) fma52x8lo_mem(R2, R2, Bi, a,64*2-8*1) fma52x8lo_mem(R0, R0, Yi, m,64*0-8*1) fma52x8lo_mem(R1, R1, Yi, m,64*1-8*1) fma52x8lo_mem(R2, R2, Yi, m,64*2-8*1) /* "shift" R */ t0 = get64(R0, 2); acc0 += t0; fma52x8hi_mem(R0, R0, Bi, a,64*0-8*2) /* U = A*Bi (hi) */ fma52x8hi_mem(R1, R1, Bi, a,64*1-8*2) fma52x8hi_mem(R2, R2, Bi, a,64*2-8*2) fma52x8hi_mem(R0, R0, Yi, m,64*0-8*2) /* R += M*Yi (hi) */ fma52x8hi_mem(R1, R1, Yi, m,64*1-8*2) fma52x8hi_mem(R2, R2, Yi, m,64*2-8*2) /* =================================== */ Bi = set64((long long)b[i+2]); /* broadcast(b[i+2]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i+2], &t2); /* (t2:t0) = acc0 + a[0]*b[i+2] */ ADD104(t2,acc0, 0,t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2,acc0, t1,t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a,64*0-8*2) fma52x8lo_mem(R1, R1, Bi, a,64*1-8*2) fma52x8lo_mem(R2, R2, Bi, a,64*2-8*2) fma52x8lo_mem(R0, R0, Yi, m,64*0-8*2) fma52x8lo_mem(R1, R1, Yi, m,64*1-8*2) fma52x8lo_mem(R2, R2, Yi, m,64*2-8*2) /* "shift" R */ t0 = get64(R0, 3); acc0 += t0; fma52x8hi_mem(R0, R0, Bi, a,64*0-8*3) /* U = A*Bi (hi) */ fma52x8hi_mem(R1, R1, Bi, a,64*1-8*3) fma52x8hi_mem(R2, R2, Bi, a,64*2-8*3) fma52x8hi_mem(R0, R0, Yi, m,64*0-8*3) /* R += M*Yi (hi) */ fma52x8hi_mem(R1, R1, Yi, m,64*1-8*3) fma52x8hi_mem(R2, R2, Yi, m,64*2-8*3) /* =================================== */ Bi = set64((long long)b[i+3]); /* broadcast(b[i+3]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i+3], &t2); /* (t2:t0) = acc0 + a[0]*b[i+3] */ ADD104(t2,acc0, 0,t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2,acc0, t1,t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a,64*0-8*3) fma52x8lo_mem(R1, R1, Bi, a,64*1-8*3) fma52x8lo_mem(R2, R2, Bi, a,64*2-8*3) fma52x8lo_mem(R0, R0, Yi, m,64*0-8*3) fma52x8lo_mem(R1, R1, Yi, m,64*1-8*3) fma52x8lo_mem(R2, R2, Yi, m,64*2-8*3) /* shift R */ shift64(R0, R1) shift64(R1, R2) shift64(R2, get_zero64()) t0 = get64(R0, 0); acc0 += t0; fma52x8hi_mem(R0, R0, Bi, a, 64*0-8*0) /* U = A*Bi (hi) */ fma52x8hi_mem(R1, R1, Bi, a, 64*1-8*0) fma52x8hi_mem_len(R2, R2, Bi, a, 64*2-8*0, 4) fma52x8hi_mem(R0, R0, Yi, m, 64*0-8*0) /* R += M*Yi (hi) */ fma52x8hi_mem(R1, R1, Yi, m, 64*1-8*0) fma52x8hi_mem_len(R2, R2, Yi, m, 64*2-8*0, 4) } /* set up R0.0 == acc0 */ Bi = set64((long long)acc0); R0 = blend64(R0, Bi, 1); NORMALIZE_52x20(R0, R1, R2) storeu64(out + 0*4, R0); storeu64(out + 1*4, R0h); storeu64(out + 2*4, R1); storeu64(out + 3*4, R1h); storeu64(out + 4*4, R2); } #endif IPP_OWN_DEFN(void, ifma256_ams52x20, (Ipp64u out[20], const Ipp64u a [20], const Ipp64u m [20], Ipp64u k0)) { ifma256_amm52x20(out, a, a, m, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_amm52x20_dual.c000066400000000000000000000147621470420105600246630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcpngmontexpstuff_avx512.h" #include "ifma_norm52x.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define ADD104(rh, rl, ih, il) { \ rl += il; \ rh += ih; \ rh += (rl>52U) | rh<<(64U-52U)) /* * Almost Montgomery Multiplication in 2^52-radix * * Implements two independent interleaved multiplications. * Data represented as 2 20-qwords arrays in 2^52-radix. * */ IPP_OWN_DEFN(void, ifma256_amm52x20_dual, (Ipp64u out[2][20], const Ipp64u a [2][20], const Ipp64u b [2][20], const Ipp64u m [2][20], const Ipp64u k0 [2])) { const Ipp64u *a_0 = a[0]; const Ipp64u *b_0 = b[0]; const Ipp64u *m_0 = m[0]; Ipp64u m0_0 = m_0[0]; Ipp64u a0_0 = a_0[0]; Ipp64u acc0_0 = 0; U64 R0_0, R1_0, R2_0, R0_0h, R1_0h, R2_0h; R0_0 = R1_0 = R2_0 = R0_0h = R1_0h = R2_0h = get_zero64(); const Ipp64u *a_1 = a[1]; const Ipp64u *b_1 = b[1]; const Ipp64u *m_1 = m[1]; Ipp64u m0_1 = m_1[0]; Ipp64u a0_1 = a_1[0]; Ipp64u acc0_1 = 0; U64 R0_1, R1_1, R2_1, R0_1h, R1_1h, R2_1h; R0_1 = R1_1 = R2_1 = R0_1h = R1_1h = R2_1h = get_zero64(); int i; for (i=0; i<20; i++) { { Ipp64u t0, t1, t2, yi; U64 Bi = set64((long long)b_0[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0_0, b_0[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0_0, 0, t0) yi = (acc0_0 * k0[0]) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ U64 Yi = set64((long long)yi); t0 = _mulx_u64(m0_0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0_0, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0_0 = SHRD52(t2, acc0_0); fma52x8lo_mem(R0_0, R0_0, Bi, a_0, 64*0) fma52x8lo_mem(R1_0, R1_0, Bi, a_0, 64*1) fma52x8lo_mem_len(R2_0, R2_0, Bi, a_0, 64*2, 4) fma52x8lo_mem(R0_0, R0_0, Yi, m_0, 64*0) fma52x8lo_mem(R1_0, R1_0, Yi, m_0, 64*1) fma52x8lo_mem_len(R2_0, R2_0, Yi, m_0, 64*2, 4) shift64_imm(R0_0, R0_0h, 1) shift64_imm(R0_0h, R1_0, 1) shift64_imm(R1_0, R1_0h, 1) shift64_imm(R1_0h, R2_0, 1) shift64_imm(R2_0, get_zero64(), 1) /* "shift" R */ t0 = get64(R0_0, 0); acc0_0 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0_0, R0_0, Bi, a_0, 64*0) fma52x8hi_mem(R1_0, R1_0, Bi, a_0, 64*1) fma52x8hi_mem_len(R2_0, R2_0, Bi, a_0, 64*2, 4) /* R += M*Yi (hi) */ fma52x8hi_mem(R0_0, R0_0, Yi, m_0, 64*0) fma52x8hi_mem(R1_0, R1_0, Yi, m_0, 64*1) fma52x8hi_mem_len(R2_0, R2_0, Yi, m_0, 64*2, 4) } { Ipp64u t0, t1, t2, yi; U64 Bi = set64((long long)b_1[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0_1, b_1[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0_1, 0, t0) yi = (acc0_1 * k0[1]) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ U64 Yi = set64((long long)yi); t0 = _mulx_u64(m0_1, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0_1, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0_1 = SHRD52(t2, acc0_1); fma52x8lo_mem(R0_1, R0_1, Bi, a_1, 64*0) fma52x8lo_mem(R1_1, R1_1, Bi, a_1, 64*1) fma52x8lo_mem_len(R2_1, R2_1, Bi, a_1, 64*2, 4) fma52x8lo_mem(R0_1, R0_1, Yi, m_1, 64*0) fma52x8lo_mem(R1_1, R1_1, Yi, m_1, 64*1) fma52x8lo_mem_len(R2_1, R2_1, Yi, m_1, 64*2, 4) shift64_imm(R0_1, R0_1h, 1) shift64_imm(R0_1h, R1_1, 1) shift64_imm(R1_1, R1_1h, 1) shift64_imm(R1_1h, R2_1, 1) shift64_imm(R2_1, get_zero64(), 1) /* "shift" R */ t0 = get64(R0_1, 0); acc0_1 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0_1, R0_1, Bi, a_1, 64*0) fma52x8hi_mem(R1_1, R1_1, Bi, a_1, 64*1) fma52x8hi_mem_len(R2_1, R2_1, Bi, a_1, 64*2, 4) /* R += M*Yi (hi) */ fma52x8hi_mem(R0_1, R0_1, Yi, m_1, 64*0) fma52x8hi_mem(R1_1, R1_1, Yi, m_1, 64*1) fma52x8hi_mem_len(R2_1, R2_1, Yi, m_1, 64*2, 4) } } { /* Normalize and store idx=0 */ /* Set R0.0 == acc0 */ U64 Bi = set64((long long)acc0_0); R0_0 = blend64(R0_0, Bi, 1); NORMALIZE_52x20(R0_0, R1_0, R2_0) storeu64(out[0] + 0*4, R0_0); storeu64(out[0] + 1*4, R0_0h); storeu64(out[0] + 2*4, R1_0); storeu64(out[0] + 3*4, R1_0h); storeu64(out[0] + 4*4, R2_0); } { /* Normalize and store idx=1 */ /* Set R0.1 == acc1 */ U64 Bi = set64((long long)acc0_1); R0_1 = blend64(R0_1, Bi, 1); NORMALIZE_52x20(R0_1, R1_1, R2_1) storeu64(out[1] + 0*4, R0_1); storeu64(out[1] + 1*4, R0_1h); storeu64(out[1] + 2*4, R1_1); storeu64(out[1] + 3*4, R1_1h); storeu64(out[1] + 4*4, R2_1); } } IPP_OWN_DEFN(void, ifma256_ams52x20_dual, (Ipp64u out[2][20], const Ipp64u a [2][20], const Ipp64u m [2][20], const Ipp64u k0 [2])) { ifma256_amm52x20_dual(out, a, a, m, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_amm52x30.c000066400000000000000000000077631470420105600236620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_norm52x.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define ADD104(rh, rl, ih, il) { \ rl += il; \ rh += ih; \ rh += (rl>52U) | rh<<(64U-52U)) /* * Almost Montgomery Multiplication in 2^52-radix * * Data represented as (30+2)-qwords arrays in 2^52-radix. * * Note: 2 high qwords - zero padding. * */ IPP_OWN_DEFN(void, ifma256_amm52x30, (Ipp64u out[32], const Ipp64u a [32], const Ipp64u b [32], const Ipp64u m [32], Ipp64u k0)) { U64 R0 = get_zero64(); U64 R1 = get_zero64(); U64 R2 = get_zero64(); U64 R3 = get_zero64(); U64 R0h = get_zero64(); U64 R1h = get_zero64(); U64 R2h = get_zero64(); U64 R3h = get_zero64(); U64 Bi, Yi; Ipp64u m0 = m[0]; Ipp64u a0 = a[0]; Ipp64u acc0 = 0; int i; for (i=0; i<30; i++) { Ipp64u t0, t1, t2, yi; Bi = set64((long long)b[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0, 0, t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a, 64*0) fma52x8lo_mem(R1, R1, Bi, a, 64*1) fma52x8lo_mem(R2, R2, Bi, a, 64*2) fma52x8lo_mem(R3, R3, Bi, a, 64*3) fma52x8lo_mem(R0, R0, Yi, m, 64*0) fma52x8lo_mem(R1, R1, Yi, m, 64*1) fma52x8lo_mem(R2, R2, Yi, m, 64*2) fma52x8lo_mem(R3, R3, Yi, m, 64*3) shift64_imm(R0, R0h, 1) shift64_imm(R0h, R1, 1) shift64_imm(R1, R1h, 1) shift64_imm(R1h, R2, 1) shift64_imm(R2, R2h, 1) shift64_imm(R2h, R3, 1) shift64_imm(R3, R3h, 1) shift64_imm(R3h, get_zero64(), 1) /* "shift" R */ t0 = get64(R0, 0); acc0 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0, R0, Bi, a, 64*0) fma52x8hi_mem(R1, R1, Bi, a, 64*1) fma52x8hi_mem(R2, R2, Bi, a, 64*2) fma52x8hi_mem(R3, R3, Bi, a, 64*3) /* R += M*Yi (hi) */ fma52x8hi_mem(R0, R0, Yi, m, 64*0) fma52x8hi_mem(R1, R1, Yi, m, 64*1) fma52x8hi_mem(R2, R2, Yi, m, 64*2) fma52x8hi_mem(R3, R3, Yi, m, 64*3) } /* Set R0[0] == acc0 */ Bi = set64((long long)acc0); R0 = blend64(R0, Bi, 1); NORMALIZE_52x30(R0, R1, R2, R3) storeu64(out + 0*4, R0); storeu64(out + 1*4, R0h); storeu64(out + 2*4, R1); storeu64(out + 3*4, R1h); storeu64(out + 4*4, R2); storeu64(out + 5*4, R2h); storeu64(out + 6*4, R3); storeu64(out + 7*4, R3h); } IPP_OWN_DEFN(void, ifma256_ams52x30, (Ipp64u out[32], const Ipp64u a [32], const Ipp64u m [32], Ipp64u k0)) { ifma256_amm52x30(out, a, a, m, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_amm52x30_dual.c000066400000000000000000000166661470420105600246710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_norm52x.h" #include "ifma_rsa_arith.h" #define ADD104(rh, rl, ih, il) { \ rl += il; \ rh += ih; \ rh += (rl>52U) | rh<<(64U-52U)) /* * Almost Montgomery Multiplication in 2^52-radix * * Implements two independent interleaved multiplications. * Data represented as 2 (30+2)-qwords arrays in 2^52-radix. * * Note: 2 high qwords - zero padding. * */ IPP_OWN_DEFN(void, ifma256_amm52x30_dual, (Ipp64u out[2][32], const Ipp64u a [2][32], const Ipp64u b [2][32], const Ipp64u m [2][32], const Ipp64u k0 [2])) { const Ipp64u *a_0 = a[0]; const Ipp64u *b_0 = b[0]; const Ipp64u *m_0 = m[0]; Ipp64u m0_0 = m_0[0]; Ipp64u a0_0 = a_0[0]; Ipp64u acc0_0 = 0; U64 R0_0, R1_0, R2_0, R3_0, R0_0h, R1_0h, R2_0h, R3_0h; R0_0 = R1_0 = R2_0 = R3_0 = R0_0h = R1_0h = R2_0h = R3_0h = get_zero64(); const Ipp64u *a_1 = a[1]; const Ipp64u *b_1 = b[1]; const Ipp64u *m_1 = m[1]; Ipp64u m0_1 = m_1[0]; Ipp64u a0_1 = a_1[0]; Ipp64u acc0_1 = 0; U64 R0_1, R1_1, R2_1, R3_1, R0_1h, R1_1h, R2_1h, R3_1h; R0_1 = R1_1 = R2_1 = R3_1 = R0_1h = R1_1h = R2_1h = R3_1h = get_zero64(); int i; for (i=0; i<30; i++) { { Ipp64u t0, t1, t2, yi; U64 Bi = set64((long long)b_0[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0_0, b_0[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0_0, 0, t0) yi = (acc0_0 * k0[0]) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ U64 Yi = set64((long long)yi); t0 = _mulx_u64(m0_0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0_0, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0_0 = SHRD52(t2, acc0_0); fma52x8lo_mem(R0_0, R0_0, Bi, a_0, 64*0) fma52x8lo_mem(R1_0, R1_0, Bi, a_0, 64*1) fma52x8lo_mem(R2_0, R2_0, Bi, a_0, 64*2) fma52x8lo_mem(R3_0, R3_0, Bi, a_0, 64*3) fma52x8lo_mem(R0_0, R0_0, Yi, m_0, 64*0) fma52x8lo_mem(R1_0, R1_0, Yi, m_0, 64*1) fma52x8lo_mem(R2_0, R2_0, Yi, m_0, 64*2) fma52x8lo_mem(R3_0, R3_0, Yi, m_0, 64*3) shift64_imm(R0_0, R0_0h, 1) shift64_imm(R0_0h, R1_0, 1) shift64_imm(R1_0, R1_0h, 1) shift64_imm(R1_0h, R2_0, 1) shift64_imm(R2_0, R2_0h, 1) shift64_imm(R2_0h, R3_0, 1) shift64_imm(R3_0, R3_0h, 1) shift64_imm(R3_0h, get_zero64(), 1) /* "shift" R */ t0 = get64(R0_0, 0); acc0_0 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0_0, R0_0, Bi, a_0, 64*0) fma52x8hi_mem(R1_0, R1_0, Bi, a_0, 64*1) fma52x8hi_mem(R2_0, R2_0, Bi, a_0, 64*2) fma52x8hi_mem(R3_0, R3_0, Bi, a_0, 64*3) /* R += M*Yi (hi) */ fma52x8hi_mem(R0_0, R0_0, Yi, m_0, 64*0) fma52x8hi_mem(R1_0, R1_0, Yi, m_0, 64*1) fma52x8hi_mem(R2_0, R2_0, Yi, m_0, 64*2) fma52x8hi_mem(R3_0, R3_0, Yi, m_0, 64*3) } { Ipp64u t0, t1, t2, yi; U64 Bi = set64((long long)b_1[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0_1, b_1[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0_1, 0, t0) yi = (acc0_1 * k0[1]) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ U64 Yi = set64((long long)yi); t0 = _mulx_u64(m0_1, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0_1, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0_1 = SHRD52(t2, acc0_1); fma52x8lo_mem(R0_1, R0_1, Bi, a_1, 64*0) fma52x8lo_mem(R1_1, R1_1, Bi, a_1, 64*1) fma52x8lo_mem(R2_1, R2_1, Bi, a_1, 64*2) fma52x8lo_mem(R3_1, R3_1, Bi, a_1, 64*3) fma52x8lo_mem(R0_1, R0_1, Yi, m_1, 64*0) fma52x8lo_mem(R1_1, R1_1, Yi, m_1, 64*1) fma52x8lo_mem(R2_1, R2_1, Yi, m_1, 64*2) fma52x8lo_mem(R3_1, R3_1, Yi, m_1, 64*3) shift64_imm(R0_1, R0_1h, 1) shift64_imm(R0_1h, R1_1, 1) shift64_imm(R1_1, R1_1h, 1) shift64_imm(R1_1h, R2_1, 1) shift64_imm(R2_1, R2_1h, 1) shift64_imm(R2_1h, R3_1, 1) shift64_imm(R3_1, R3_1h, 1) shift64_imm(R3_1h, get_zero64(), 1) /* "shift" R */ t0 = get64(R0_1, 0); acc0_1 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0_1, R0_1, Bi, a_1, 64*0) fma52x8hi_mem(R1_1, R1_1, Bi, a_1, 64*1) fma52x8hi_mem(R2_1, R2_1, Bi, a_1, 64*2) fma52x8hi_mem(R3_1, R3_1, Bi, a_1, 64*3) /* R += M*Yi (hi) */ fma52x8hi_mem(R0_1, R0_1, Yi, m_1, 64*0) fma52x8hi_mem(R1_1, R1_1, Yi, m_1, 64*1) fma52x8hi_mem(R2_1, R2_1, Yi, m_1, 64*2) fma52x8hi_mem(R3_1, R3_1, Yi, m_1, 64*3) } } { /* Normalize and store idx=0 */ /* Set R0.0 == acc0 */ U64 Bi = set64((long long)acc0_0); R0_0 = blend64(R0_0, Bi, 1); NORMALIZE_52x30(R0_0, R1_0, R2_0, R3_0) storeu64(out[0] + 0*4, R0_0); storeu64(out[0] + 1*4, R0_0h); storeu64(out[0] + 2*4, R1_0); storeu64(out[0] + 3*4, R1_0h); storeu64(out[0] + 4*4, R2_0); storeu64(out[0] + 5*4, R2_0h); storeu64(out[0] + 6*4, R3_0); storeu64(out[0] + 7*4, R3_0h); } { /* Normalize and store idx=1 */ /* Set R0.1 == acc1 */ U64 Bi = set64((long long)acc0_1); R0_1 = blend64(R0_1, Bi, 1); NORMALIZE_52x30(R0_1, R1_1, R2_1, R3_1) storeu64(out[1] + 0*4, R0_1); storeu64(out[1] + 1*4, R0_1h); storeu64(out[1] + 2*4, R1_1); storeu64(out[1] + 3*4, R1_1h); storeu64(out[1] + 4*4, R2_1); storeu64(out[1] + 5*4, R2_1h); storeu64(out[1] + 6*4, R3_1); storeu64(out[1] + 7*4, R3_1h); } } IPP_OWN_DEFN(void, ifma256_ams52x30_dual, (Ipp64u out[2][32], const Ipp64u a [2][32], const Ipp64u m [2][32], const Ipp64u k0 [2])) { ifma256_amm52x30_dual(out, a, a, m, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_amm52x40.c000066400000000000000000000104251470420105600236500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_norm52x.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define ADD104(rh, rl, ih, il) { \ rl += il; \ rh += ih; \ rh += (rl>52U) | rh<<(64U-52U)) /* * Almost Montgomery Multiplication in 2^52-radix * * Data represented as 40-qwords arrays in 2^52-radix. * */ IPP_OWN_DEFN(void, ifma256_amm52x40, (Ipp64u out[40], const Ipp64u a [40], const Ipp64u b [40], const Ipp64u m [40], Ipp64u k0)) { U64 R0 = get_zero64(); U64 R1 = get_zero64(); U64 R2 = get_zero64(); U64 R3 = get_zero64(); U64 R4 = get_zero64(); U64 R0h = get_zero64(); U64 R1h = get_zero64(); U64 R2h = get_zero64(); U64 R3h = get_zero64(); U64 R4h = get_zero64(); U64 Bi, Yi; Ipp64u m0 = m[0]; Ipp64u a0 = a[0]; Ipp64u acc0 = 0; int i; for (i=0; i<40; i++) { Ipp64u t0, t1, t2, yi; Bi = set64((long long)b[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0, b[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0, 0, t0) yi = (acc0 * k0) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ Yi = set64((long long)yi); t0 = _mulx_u64(m0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0 = SHRD52(t2, acc0); fma52x8lo_mem(R0, R0, Bi, a, 64*0) fma52x8lo_mem(R1, R1, Bi, a, 64*1) fma52x8lo_mem(R2, R2, Bi, a, 64*2) fma52x8lo_mem(R3, R3, Bi, a, 64*3) fma52x8lo_mem(R4, R4, Bi, a, 64*4) fma52x8lo_mem(R0, R0, Yi, m, 64*0) fma52x8lo_mem(R1, R1, Yi, m, 64*1) fma52x8lo_mem(R2, R2, Yi, m, 64*2) fma52x8lo_mem(R3, R3, Yi, m, 64*3) fma52x8lo_mem(R4, R4, Yi, m, 64*4) shift64_imm(R0, R0h, 1) shift64_imm(R0h, R1, 1) shift64_imm(R1, R1h, 1) shift64_imm(R1h, R2, 1) shift64_imm(R2, R2h, 1) shift64_imm(R2h, R3, 1) shift64_imm(R3, R3h, 1) shift64_imm(R3h, R4, 1) shift64_imm(R4, R4h, 1) shift64_imm(R4h, get_zero64(), 1) /* "shift" R */ t0 = get64(R0, 0); acc0 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0, R0, Bi, a, 64*0) fma52x8hi_mem(R1, R1, Bi, a, 64*1) fma52x8hi_mem(R2, R2, Bi, a, 64*2) fma52x8hi_mem(R3, R3, Bi, a, 64*3) fma52x8hi_mem(R4, R4, Bi, a, 64*4) /* R += M*Yi (hi) */ fma52x8hi_mem(R0, R0, Yi, m, 64*0) fma52x8hi_mem(R1, R1, Yi, m, 64*1) fma52x8hi_mem(R2, R2, Yi, m, 64*2) fma52x8hi_mem(R3, R3, Yi, m, 64*3) fma52x8hi_mem(R4, R4, Yi, m, 64*4) } /* Set R0[0] == acc0 */ Bi = set64((long long)acc0); R0 = blend64(R0, Bi, 1); NORMALIZE_52x40(R0, R1, R2, R3, R4) storeu64(out + 0*4, R0); storeu64(out + 1*4, R0h); storeu64(out + 2*4, R1); storeu64(out + 3*4, R1h); storeu64(out + 4*4, R2); storeu64(out + 5*4, R2h); storeu64(out + 6*4, R3); storeu64(out + 7*4, R3h); storeu64(out + 8*4, R4); storeu64(out + 9*4, R4h); } IPP_OWN_DEFN(void, ifma256_ams52x40, (Ipp64u out[40], const Ipp64u a [40], const Ipp64u m [40], Ipp64u k0)) { ifma256_amm52x40(out, a, a, m, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_amm52x40_dual.c000066400000000000000000000202541470420105600246560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_norm52x.h" #include "ifma_rsa_arith.h" #define ADD104(rh, rl, ih, il) { \ rl += il; \ rh += ih; \ rh += (rl>52U) | rh<<(64U-52U)) /* * Almost Montgomery Multiplication in 2^52-radix * * Implements two independent interleaved multiplications. * Data represented as 2 40-qwords arrays in 2^52-radix. * */ IPP_OWN_DEFN(void, ifma256_amm52x40_dual, (Ipp64u out[2][40], const Ipp64u a [2][40], const Ipp64u b [2][40], const Ipp64u m [2][40], const Ipp64u k0 [2])) { const Ipp64u *a_0 = a[0]; const Ipp64u *b_0 = b[0]; const Ipp64u *m_0 = m[0]; Ipp64u m0_0 = m_0[0]; Ipp64u a0_0 = a_0[0]; Ipp64u acc0_0 = 0; U64 R0_0, R1_0, R2_0, R3_0, R4_0, R0_0h, R1_0h, R2_0h, R3_0h, R4_0h; R0_0 = R1_0 = R2_0 = R3_0 = R4_0 = R0_0h = R1_0h = R2_0h = R3_0h = R4_0h = get_zero64(); const Ipp64u *a_1 = a[1]; const Ipp64u *b_1 = b[1]; const Ipp64u *m_1 = m[1]; Ipp64u m0_1 = m_1[0]; Ipp64u a0_1 = a_1[0]; Ipp64u acc0_1 = 0; U64 R0_1, R1_1, R2_1, R3_1, R4_1, R0_1h, R1_1h, R2_1h, R3_1h, R4_1h; R0_1 = R1_1 = R2_1 = R3_1 = R4_1 = R0_1h = R1_1h = R2_1h = R3_1h = R4_1h = get_zero64(); int i; for (i=0; i<40; i++) { { Ipp64u t0, t1, t2, yi; U64 Bi = set64((long long)b_0[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0_0, b_0[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0_0, 0, t0) yi = (acc0_0 * k0[0]) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ U64 Yi = set64((long long)yi); t0 = _mulx_u64(m0_0, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0_0, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0_0 = SHRD52(t2, acc0_0); fma52x8lo_mem(R0_0, R0_0, Bi, a_0, 64*0) fma52x8lo_mem(R1_0, R1_0, Bi, a_0, 64*1) fma52x8lo_mem(R2_0, R2_0, Bi, a_0, 64*2) fma52x8lo_mem(R3_0, R3_0, Bi, a_0, 64*3) fma52x8lo_mem(R4_0, R4_0, Bi, a_0, 64*4) fma52x8lo_mem(R0_0, R0_0, Yi, m_0, 64*0) fma52x8lo_mem(R1_0, R1_0, Yi, m_0, 64*1) fma52x8lo_mem(R2_0, R2_0, Yi, m_0, 64*2) fma52x8lo_mem(R3_0, R3_0, Yi, m_0, 64*3) fma52x8lo_mem(R4_0, R4_0, Yi, m_0, 64*4) shift64_imm(R0_0, R0_0h, 1) shift64_imm(R0_0h, R1_0, 1) shift64_imm(R1_0, R1_0h, 1) shift64_imm(R1_0h, R2_0, 1) shift64_imm(R2_0, R2_0h, 1) shift64_imm(R2_0h, R3_0, 1) shift64_imm(R3_0, R3_0h, 1) shift64_imm(R3_0h, R4_0, 1) shift64_imm(R4_0, R4_0h, 1) shift64_imm(R4_0h, get_zero64(), 1) /* "shift" R */ t0 = get64(R0_0, 0); acc0_0 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0_0, R0_0, Bi, a_0, 64*0) fma52x8hi_mem(R1_0, R1_0, Bi, a_0, 64*1) fma52x8hi_mem(R2_0, R2_0, Bi, a_0, 64*2) fma52x8hi_mem(R3_0, R3_0, Bi, a_0, 64*3) fma52x8hi_mem(R4_0, R4_0, Bi, a_0, 64*4) /* R += M*Yi (hi) */ fma52x8hi_mem(R0_0, R0_0, Yi, m_0, 64*0) fma52x8hi_mem(R1_0, R1_0, Yi, m_0, 64*1) fma52x8hi_mem(R2_0, R2_0, Yi, m_0, 64*2) fma52x8hi_mem(R3_0, R3_0, Yi, m_0, 64*3) fma52x8hi_mem(R4_0, R4_0, Yi, m_0, 64*4) } { Ipp64u t0, t1, t2, yi; U64 Bi = set64((long long)b_1[i]); /* broadcast(b[i]) */ /* compute yi */ t0 = _mulx_u64(a0_1, b_1[i], &t2); /* (t2:t0) = acc0 + a[0]*b[i] */ ADD104(t2, acc0_1, 0, t0) yi = (acc0_1 * k0[1]) & EXP_DIGIT_MASK_AVX512; /* yi = acc0*k0 */ U64 Yi = set64((long long)yi); t0 = _mulx_u64(m0_1, yi, &t1); /* (t1:t0) = m0*yi */ ADD104(t2, acc0_1, t1, t0) /* (t2:acc0) += (t1:t0) */ acc0_1 = SHRD52(t2, acc0_1); fma52x8lo_mem(R0_1, R0_1, Bi, a_1, 64*0) fma52x8lo_mem(R1_1, R1_1, Bi, a_1, 64*1) fma52x8lo_mem(R2_1, R2_1, Bi, a_1, 64*2) fma52x8lo_mem(R3_1, R3_1, Bi, a_1, 64*3) fma52x8lo_mem(R4_1, R4_1, Bi, a_1, 64*4) fma52x8lo_mem(R0_1, R0_1, Yi, m_1, 64*0) fma52x8lo_mem(R1_1, R1_1, Yi, m_1, 64*1) fma52x8lo_mem(R2_1, R2_1, Yi, m_1, 64*2) fma52x8lo_mem(R3_1, R3_1, Yi, m_1, 64*3) fma52x8lo_mem(R4_1, R4_1, Yi, m_1, 64*4) shift64_imm(R0_1, R0_1h, 1) shift64_imm(R0_1h, R1_1, 1) shift64_imm(R1_1, R1_1h, 1) shift64_imm(R1_1h, R2_1, 1) shift64_imm(R2_1, R2_1h, 1) shift64_imm(R2_1h, R3_1, 1) shift64_imm(R3_1, R3_1h, 1) shift64_imm(R3_1h, R4_1, 1) shift64_imm(R4_1, R4_1h, 1) shift64_imm(R4_1h, get_zero64(), 1) /* "shift" R */ t0 = get64(R0_1, 0); acc0_1 += t0; /* U = A*Bi (hi) */ fma52x8hi_mem(R0_1, R0_1, Bi, a_1, 64*0) fma52x8hi_mem(R1_1, R1_1, Bi, a_1, 64*1) fma52x8hi_mem(R2_1, R2_1, Bi, a_1, 64*2) fma52x8hi_mem(R3_1, R3_1, Bi, a_1, 64*3) fma52x8hi_mem(R4_1, R4_1, Bi, a_1, 64*4) /* R += M*Yi (hi) */ fma52x8hi_mem(R0_1, R0_1, Yi, m_1, 64*0) fma52x8hi_mem(R1_1, R1_1, Yi, m_1, 64*1) fma52x8hi_mem(R2_1, R2_1, Yi, m_1, 64*2) fma52x8hi_mem(R3_1, R3_1, Yi, m_1, 64*3) fma52x8hi_mem(R4_1, R4_1, Yi, m_1, 64*4) } } { /* Normalize and store idx=0 */ /* Set R0.0 == acc0 */ U64 Bi = set64((long long)acc0_0); R0_0 = blend64(R0_0, Bi, 1); NORMALIZE_52x40(R0_0, R1_0, R2_0, R3_0, R4_0) storeu64(out[0] + 0*4, R0_0); storeu64(out[0] + 1*4, R0_0h); storeu64(out[0] + 2*4, R1_0); storeu64(out[0] + 3*4, R1_0h); storeu64(out[0] + 4*4, R2_0); storeu64(out[0] + 5*4, R2_0h); storeu64(out[0] + 6*4, R3_0); storeu64(out[0] + 7*4, R3_0h); storeu64(out[0] + 8*4, R4_0); storeu64(out[0] + 9*4, R4_0h); } { /* Normalize and store idx=1 */ /* Set R0.1 == acc1 */ U64 Bi = set64((long long)acc0_1); R0_1 = blend64(R0_1, Bi, 1); NORMALIZE_52x40(R0_1, R1_1, R2_1, R3_1, R4_1) storeu64(out[1] + 0*4, R0_1); storeu64(out[1] + 1*4, R0_1h); storeu64(out[1] + 2*4, R1_1); storeu64(out[1] + 3*4, R1_1h); storeu64(out[1] + 4*4, R2_1); storeu64(out[1] + 5*4, R2_1h); storeu64(out[1] + 6*4, R3_1); storeu64(out[1] + 7*4, R3_1h); storeu64(out[1] + 8*4, R4_1); storeu64(out[1] + 9*4, R4_1h); } } IPP_OWN_DEFN(void, ifma256_ams52x40_dual, (Ipp64u out[2][40], const Ipp64u a [2][40], const Ipp64u m [2][40], const Ipp64u k0 [2])) { ifma256_amm52x40_dual(out, a, a, m, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_exp52x20.c000066400000000000000000000126011470420105600236660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define BITSIZE_MODULUS (1024) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,52)) // 20 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) // 16 #define EXP_WIN_SIZE (5U) #define EXP_WIN_MASK ((1U<> exp_chunk_shift; extract_multiplier(red_Y, (const Ipp64u(*)[LEN52])red_table, (int)red_table_idx); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* series of squaring */ AMS(red_Y, red_Y, modulus, k0); AMS(red_Y, red_Y, modulus, k0); AMS(red_Y, red_Y, modulus, k0); AMS(red_Y, red_Y, modulus, k0); AMS(red_Y, red_Y, modulus, k0); /* extract pre-computed multiplier from the table */ { Ipp64u T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; red_table_idx = expz[exp_chunk_no]; T = expz[exp_chunk_no+1]; red_table_idx = red_table_idx >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx = (red_table_idx ^ T) & table_idx_mask; extract_multiplier(red_X, (const Ipp64u(*)[LEN52])red_table, (int)red_table_idx); AMM(red_Y, red_Y, red_X, modulus, k0); } } } /* clear exponents */ PurgeBlock((Ipp64u*)expz, (LEN64+1)*(int)sizeof(Ipp64u)); /* convert result back in regular 2^52 domain */ ZEXPAND_BNU(red_X, 0, LEN52); red_X[0] = 1ULL; AMM(out, red_Y, red_X, modulus, k0); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_exp52x20_dual.c000066400000000000000000000162231470420105600246770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define BITSIZE_MODULUS (1024) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,52)) // 20 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) // 16 #define EXP_WIN_SIZE (5U) #define EXP_WIN_MASK ((1U<> exp_chunk_shift; red_table_idx_1 = red_table_idx_1 >> exp_chunk_shift; extract_multiplier_n(red_Y[0], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_0, 0); extract_multiplier_n(red_Y[1], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_1, 1); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* extract pre-computed multiplier from the table */ { Ipp64u T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; { red_table_idx_0 = expz[0][exp_chunk_no]; T = expz[0][exp_chunk_no + 1]; red_table_idx_0 = red_table_idx_0 >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx_0 = (red_table_idx_0 ^ T) & table_idx_mask; extract_multiplier_n(red_X[0], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_0, 0); } { red_table_idx_1 = expz[1][exp_chunk_no]; T = expz[1][exp_chunk_no + 1]; red_table_idx_1 = red_table_idx_1 >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx_1 = (red_table_idx_1 ^ T) & table_idx_mask; extract_multiplier_n(red_X[1], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_1, 1); } } /* series of squaring */ DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMM(red_Y, (const Ipp64u(*)[LEN52])red_Y, (const Ipp64u(*)[LEN52])red_X, modulus, k0); } } /* clear exponents */ PurgeBlock((Ipp64u*)expz, 2*(LEN64+1)*(int)sizeof(Ipp64u)); /* convert result back in regular 2^52 domain */ ZEXPAND_BNU((Ipp64u*)red_X, 0, 2*LEN52); storeu64(&red_X[0][0], _mm256_setr_epi64x(1,0,0,0)); storeu64(&red_X[1][0], _mm256_setr_epi64x(1,0,0,0)); DAMM(out, (const Ipp64u(*)[LEN52])red_Y, (const Ipp64u(*)[LEN52])red_X, modulus, k0); PurgeBlock((Ipp64u*)red_Y, 2*LEN52*(int)sizeof(Ipp64u)); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_exp52x30_dual.c000066400000000000000000000170551470420105600247040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define BITSIZE_MODULUS (1536) #define LEN52 ((NUMBER_OF_DIGITS(BITSIZE_MODULUS,52)) + 2) // 30 + 2 (with zero-padding) #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) // 24 #define EXP_WIN_SIZE (5U) #define EXP_WIN_MASK ((1U<> exp_chunk_shift; red_table_idx_1 = red_table_idx_1 >> exp_chunk_shift; extract_multiplier_n(red_Y[0], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_0, 0); extract_multiplier_n(red_Y[1], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_1, 1); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* extract pre-computed multiplier from the table */ { Ipp64u T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; { red_table_idx_0 = expz[0][exp_chunk_no]; T = expz[0][exp_chunk_no + 1]; red_table_idx_0 = red_table_idx_0 >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx_0 = (red_table_idx_0 ^ T) & table_idx_mask; extract_multiplier_n(red_X[0], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_0, 0); } { red_table_idx_1 = expz[1][exp_chunk_no]; T = expz[1][exp_chunk_no + 1]; red_table_idx_1 = red_table_idx_1 >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx_1 = (red_table_idx_1 ^ T) & table_idx_mask; extract_multiplier_n(red_X[1], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_1, 1); } } /* series of squaring */ DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMM(red_Y, (const Ipp64u(*)[LEN52])red_Y, (const Ipp64u(*)[LEN52])red_X, modulus, k0); } } /* clear exponents */ PurgeBlock((Ipp64u*)expz, 2*(LEN64+1)*(int)sizeof(Ipp64u)); /* convert result back in regular 2^52 domain */ ZEXPAND_BNU((Ipp64u*)red_X, 0, 2*LEN52); storeu64(&red_X[0][0], _mm256_setr_epi64x(1,0,0,0)); storeu64(&red_X[1][0], _mm256_setr_epi64x(1,0,0,0)); DAMM(out, (const Ipp64u(*)[LEN52])red_Y, (const Ipp64u(*)[LEN52])red_X, modulus, k0); PurgeBlock((Ipp64u*)red_Y, 2*LEN52*(int)sizeof(Ipp64u)); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_exp52x40_dual.c000066400000000000000000000174041470420105600247030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_math_avx512vl.h" #include "ifma_rsa_arith.h" #define BITSIZE_MODULUS (2048) #define LEN52 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,52)) // 40 #define LEN64 (NUMBER_OF_DIGITS(BITSIZE_MODULUS,64)) // 32 #define EXP_WIN_SIZE (5U) #define EXP_WIN_MASK ((1U<> exp_chunk_shift; red_table_idx_1 = red_table_idx_1 >> exp_chunk_shift; extract_multiplier_n(red_Y[0], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_0, 0); extract_multiplier_n(red_Y[1], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_1, 1); /* process other exp windows */ for (exp_bit_no -= EXP_WIN_SIZE; exp_bit_no >= 0; exp_bit_no -= EXP_WIN_SIZE) { /* extract pre-computed multiplier from the table */ { Ipp64u T; exp_chunk_no = exp_bit_no / 64; exp_chunk_shift = exp_bit_no % 64; { red_table_idx_0 = expz[0][exp_chunk_no]; T = expz[0][exp_chunk_no + 1]; red_table_idx_0 = red_table_idx_0 >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx_0 = (red_table_idx_0 ^ T) & table_idx_mask; extract_multiplier_n(red_X[0], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_0, 0); } { red_table_idx_1 = expz[1][exp_chunk_no]; T = expz[1][exp_chunk_no + 1]; red_table_idx_1 = red_table_idx_1 >> exp_chunk_shift; T = exp_chunk_shift == 0 ? 0 : T << (64 - exp_chunk_shift); red_table_idx_1 = (red_table_idx_1 ^ T) & table_idx_mask; extract_multiplier_n(red_X[1], (const Ipp64u(*)[2][LEN52])red_table, (int)red_table_idx_1, 1); } } /* series of squaring */ DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMS(red_Y, (const Ipp64u(*)[LEN52])red_Y, modulus, k0); DAMM(red_Y, (const Ipp64u(*)[LEN52])red_Y, (const Ipp64u(*)[LEN52])red_X, modulus, k0); } } /* clear exponents */ PurgeBlock((Ipp64u*)expz, 2*(LEN64+1)*(int)sizeof(Ipp64u)); /* convert result back in regular 2^52 domain */ ZEXPAND_BNU((Ipp64u*)red_X, 0, 2*LEN52); storeu64(&red_X[0][0], _mm256_setr_epi64x(1,0,0,0)); storeu64(&red_X[1][0], _mm256_setr_epi64x(1,0,0,0)); DAMM(out, (const Ipp64u(*)[LEN52])red_Y, (const Ipp64u(*)[LEN52])red_X, modulus, k0); PurgeBlock((Ipp64u*)red_Y, 2*LEN52*(int)sizeof(Ipp64u)); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_exp52x_dual.c000066400000000000000000000123351470420105600245350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #if(_IPP32E>=_IPP32E_K1) #include "pcptool.h" #include "pcpngmontexpstuff_avx512.h" #include "ifma_rsa_arith.h" IPP_OWN_DEFN (cpSize, gsMontDualExpWinBuffer_avx512, (int modulusBits)) { cpSize redNum = numofVariable_avx512(modulusBits); /* Reg (ymm) capacity = 4 qwords */ cpSize redBufferNum = numofVariableBuff_avx512(redNum, 4); return redBufferNum * 2 * 8; } IPP_OWN_FUNPTR (void, AMM52, (Ipp64u *out, const Ipp64u *a, const Ipp64u *b, const Ipp64u *m, Ipp64u k0)) IPP_OWN_FUNPTR (void, DEXP52, (Ipp64u* out, const Ipp64u* base, const Ipp64u* exp[2], const Ipp64u* modulus, const Ipp64u* pMont, const Ipp64u k0[2])) IPP_OWN_DEFN (cpSize, gsMontDualExpWin_BNU_sscm_avx512, (BNU_CHUNK_T* dataY[2], const BNU_CHUNK_T* dataX[2], cpSize nsX[2], const BNU_CHUNK_T* dataE[2], gsModEngine* pMont[2], BNU_CHUNK_T* pBuffer)) { const BNU_CHUNK_T* modulus[2] = {0}; const BNU_CHUNK_T* rr[2] = {0}; cpSize modulusSize[2] = {0}; BNU_CHUNK_T k0[2] = {0}; modulus[0] = MOD_MODULUS(pMont[0]); modulus[1] = MOD_MODULUS(pMont[1]); modulusSize[0] = MOD_LEN(pMont[0]); modulusSize[1] = MOD_LEN(pMont[1]); rr[0] = MOD_MNT_R2(pMont[0]); rr[1] = MOD_MNT_R2(pMont[1]); k0[0] = MOD_MNT_FACTOR(pMont[0]); k0[1] = MOD_MNT_FACTOR(pMont[1]); /* * Dual expo implemenentation assumes that bit sizes of P and Q are * the same, so query size from the first. */ int modulusBitSize = BITSIZE_BNU(modulus[0], modulusSize[0]); int redLen = NUMBER_OF_DIGITS(modulusBitSize + 2, EXP_DIGIT_SIZE_AVX512); /* For ymm-based implementation reg capacity = 4 qwords */ int redBufferLen = numofVariableBuff_avx512(redLen, 4); /* Allocate buffers */ BNU_CHUNK_T* redX = pBuffer; BNU_CHUNK_T* redM = redX + 2*redBufferLen; BNU_CHUNK_T* redRR = redM + 2*redBufferLen; BNU_CHUNK_T* redCoeff = redRR + 2*redBufferLen; BNU_CHUNK_T* redBuffer = redCoeff + redBufferLen; AMM52 ammFunc = NULL; DEXP52 dexpFunc = NULL; switch (modulusBitSize) { case 1024: ammFunc = ifma256_amm52x20; dexpFunc = (DEXP52)ifma256_exp52x20_dual; break; case 1536: ammFunc = ifma256_amm52x30; dexpFunc = (DEXP52)ifma256_exp52x30_dual; break; case 2048: ammFunc = ifma256_amm52x40; dexpFunc = (DEXP52)ifma256_exp52x40_dual; break; default: /* Other modulus sizes not supported. This function shall not be called for them. */ return 0; } ZEXPAND_BNU(redCoeff, 0, redBufferLen); int conv_coeff = 4 * (EXP_DIGIT_SIZE_AVX512 * redLen - modulusBitSize); /* Set corresponding bit in reduced domain */ SET_BIT(redCoeff, 64 * (int)(conv_coeff / 52) + conv_coeff % 52); for (int i = 0; i < 2; i++) { /* Convert base into redundant domain */ ZEXPAND_COPY_BNU(redBuffer, redBufferLen, dataX[i], nsX[i]); regular_dig52(redX + i*redBufferLen, redBufferLen, redBuffer, modulusBitSize); /* Convert modulus into redundant domain */ ZEXPAND_COPY_BNU(redBuffer, redBufferLen, modulus[i], modulusSize[i]); regular_dig52(redM + i*redBufferLen, redBufferLen, redBuffer, modulusBitSize); /* * Compute target domain Montgomery converter RR' based on original domain RR. * * Example: modlen = 1024: RR = 2^2048 mod m, RR' = 2^2080 mod m * conv_coeff = 2^64 * (1st amm): 2^2048*2^2048/2^1040= 2^3056 mod m * (2nd amm): 2^3056*2^64/2^1040 = 2^2080 mod m * */ ZEXPAND_COPY_BNU(redBuffer, redBufferLen, rr[i], modulusSize[i]); regular_dig52(redRR + i*redBufferLen, redBufferLen, redBuffer, modulusBitSize); ammFunc(redRR + i*redBufferLen, redRR + i*redBufferLen, redRR + i*redBufferLen, redM + i*redBufferLen, k0[i]); ammFunc(redRR + i*redBufferLen, redRR + i*redBufferLen, redCoeff, redM + i*redBufferLen, k0[i]); } dexpFunc(redRR, redX, dataE, redM, redRR, k0); /* Convert result back to regular domain */ for (int i = 0; i < 2; i++) dig52_regular(dataY[i], redRR + i*redBufferLen, modulusBitSize); /* Clear redundant exponents buffer */ PurgeBlock(redRR, 2*redBufferLen*(int)sizeof(BNU_CHUNK_T)); return (modulusSize[0] + modulusSize[1]); } #endif cryptography-primitives-1.0.0/sources/ippcp/ifma_math_avx512vl.h000066400000000000000000000130011470420105600247720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #ifndef IFMA_MATH_AVX512VL_H #define IFMA_MATH_AVX512VL_H /* * This header provides low-level abstraction for 256-bit AVX512VL * ISA instructions. * */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) // for MSVC #pragma warning(disable:4101) #pragma warning(disable:4127) // warning: conditional expression is constant (see fma52x8lo_mem_len()) #elif defined (__INTEL_COMPILER) #pragma warning(disable:177) #endif #include #ifndef SIMD_LEN #define SIMD_LEN 256 #endif #define SIMD_TYPE(LEN) typedef __m ## LEN ## i U64; #if (SIMD_LEN == 256) SIMD_TYPE(256) #define SIMD_BYTES (SIMD_LEN/8) #define SIMD_QWORDS (SIMD_LEN/64) __IPPCP_INLINE U64 loadu64(const void *p) { return _mm256_loadu_si256((U64*)p); } __IPPCP_INLINE void storeu64(const void *p, U64 v) { _mm256_storeu_si256((U64*)p, v); } #define set64 _mm256_set1_epi64x #ifdef __GNUC__ static U64 fma52lo(U64 a, U64 b, U64 c) { __asm__ ( "vpmadd52luq %2, %1, %0" : "+x" (a): "x" (b), "x" (c) ); return a; } static U64 fma52hi(U64 a, U64 b, U64 c) { __asm__ ( "vpmadd52huq %2, %1, %0" : "+x" (a): "x" (b), "x" (c) ); return a; } #define _mm_madd52lo_epu64_(r, a, b, c, o) \ { \ r=a; \ __asm__ ( "vpmadd52luq " #o "(%2), %1, %0" : "+x" (r): "x" (b), "r" (c) ); \ } #define _mm_madd52hi_epu64_(r, a, b, c, o) \ { \ r=a; \ __asm__ ( "vpmadd52huq " #o "(%2), %1, %0" : "+x" (r): "x" (b), "r" (c) ); \ } #else /* Use IFMA intrinsics for all other compilers */ static U64 fma52lo(U64 a, U64 b, U64 c) { return _mm256_madd52lo_epu64(a, b, c); } static U64 fma52hi(U64 a, U64 b, U64 c) { return _mm256_madd52hi_epu64(a, b, c); } #define _mm_madd52lo_epu64_(r, a, b, c, o) \ { \ r=fma52lo(a, b, loadu64((U64*)(((char*)c)+o))); \ } #define _mm_madd52hi_epu64_(r, a, b, c, o) \ { \ r=fma52hi(a, b, loadu64((U64*)(((char*)c)+o))); \ } #endif __IPPCP_INLINE U64 mul52lo(U64 b, U64 c) { return fma52lo(_mm256_setzero_si256(), b, c); } #define fma52lo_mem(r, a, b, c, o) _mm_madd52lo_epu64_(r, a, b, c, o) #define fma52hi_mem(r, a, b, c, o) _mm_madd52hi_epu64_(r, a, b, c, o) __IPPCP_INLINE U64 add64(U64 a, U64 b) { return _mm256_add_epi64(a, b); } __IPPCP_INLINE U64 sub64(U64 a, U64 b) { return _mm256_sub_epi64(a, b); } __IPPCP_INLINE U64 get_zero64() { return _mm256_setzero_si256(); } __IPPCP_INLINE void set_zero64(U64 *a) { *a = _mm256_xor_si256(*a, *a); } __IPPCP_INLINE U64 set1(unsigned long long a) { return _mm256_set1_epi64x((long long)a); } __IPPCP_INLINE U64 srli64(U64 a, int s) { return _mm256_srli_epi64(a, s); } #define slli64 _mm256_slli_epi64 __IPPCP_INLINE U64 and64_const(U64 a, unsigned long long mask) { return _mm256_and_si256(a, _mm256_set1_epi64x((long long)mask)); } __IPPCP_INLINE U64 and64(U64 a, U64 mask) { return _mm256_and_si256(a, mask); } #define or64 _mm256_or_si256 #define xor64 _mm256_xor_si256 static Ipp64u get64(U64 v, int idx) { long long int res; switch (idx) { case 1: res = _mm256_extract_epi64(v, 1); break; case 2: res = _mm256_extract_epi64(v, 2); break; case 3: res = _mm256_extract_epi64(v, 3); break; default: res = _mm256_extract_epi64(v, 0); } return (Ipp64u)res; } #define fma52x8lo_mem(r, a, b, c, o) \ fma52lo_mem(r, a, b, c, o); \ fma52lo_mem(r ## h, a ## h, b, c, (o) + 32); #define fma52x8hi_mem(r, a, b, c, o) \ fma52hi_mem(r, a, b, c, o); \ fma52hi_mem(r ## h, a ## h, b, c, (o) + 32); #define fma52x8lo_mem_len(r, a, b, c, o, l) \ fma52lo_mem(r, a, b, c, o); \ if (l > 4) { fma52lo_mem(r ## h, a ## h, b, c, (o) + 32); } #define fma52x8hi_mem_len(r, a, b, c, o, l) \ fma52hi_mem(r, a, b, c, o); \ if (l > 4) { fma52hi_mem(r ## h, a ## h, b, c, (o) + 32); } #define fma52x8lo_mask_mem(r, m, a, b, c, o) \ fma52lo_mem(r, a, b, c, o); \ fma52lo_mem(r ## h, a ## h, b, c, (o) + 32); #define fma52x8hi_mask_mem(r, m, a, b, c, o) \ fma52hi_mem(r, a, b, c, o); \ fma52hi_mem(r ## h, a ## h, b, c, (o) + 32); #define shift64(R0, R1) { \ R0 = R0 ## h; \ R0 ## h = R1; } #define shift64_imm(R0, R1, imm) \ R0 = _mm256_alignr_epi64(R1, R0, imm); #define blend64(a, b, m) \ _mm256_blend_epi32(a, b, (int)(0x3<<((m-1)<<1))); #else #error "Incorrect SIMD length" #endif // SIMD_LEN #endif // IFMA_MATH_AVX512VL_H cryptography-primitives-1.0.0/sources/ippcp/ifma_norm52x.h000066400000000000000000000572621470420105600237240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #ifndef IFMA_NORM_52X_H #define IFMA_NORM_52X_H #define NORMALIZE_52x20(R0,R1,R2) { \ __m256i T0 = _mm256_srli_epi64(R0, EXP_DIGIT_SIZE_AVX512); \ __m256i T0h = _mm256_srli_epi64(R0 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T1 = _mm256_srli_epi64(R1, EXP_DIGIT_SIZE_AVX512); \ __m256i T1h = _mm256_srli_epi64(R1 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T2 = _mm256_srli_epi64(R2, EXP_DIGIT_SIZE_AVX512); \ __m256i MASK = _mm256_set1_epi64x(EXP_DIGIT_MASK_AVX512); \ \ Ipp32u kk0, kk1, kk2; \ Ipp32u kk0h, kk1h; \ kk0 = kk1 = kk2 = kk0h = kk1h = 0; \ \ R0 = _mm256_and_si256(R0, MASK); \ R1 = _mm256_and_si256(R1, MASK); \ R2 = _mm256_and_si256(R2, MASK); \ R0 ## h = _mm256_and_si256(R0 ## h, MASK); \ R1 ## h = _mm256_and_si256(R1 ## h, MASK); \ \ T2 = _mm256_alignr_epi64(T2, T1h, 3); \ T1h = _mm256_alignr_epi64(T1h, T1, 3); \ T1 = _mm256_alignr_epi64(T1, T0h, 3); \ T0h = _mm256_alignr_epi64(T0h, T0, 3); \ T0 = _mm256_alignr_epi64(T0, _mm256_setzero_si256(), 3); \ \ R0 = _mm256_add_epi64(R0, T0); \ R1 = _mm256_add_epi64(R1, T1); \ R2 = _mm256_add_epi64(R2, T2); \ R0 ## h = _mm256_add_epi64(R0 ## h, T0h); \ R1 ## h = _mm256_add_epi64(R1 ## h, T1h); \ { \ Ipp32u k,l; \ k = l = 0; \ \ kk0 = _mm256_cmp_epu64_mask(MASK, R0, _MM_CMPINT_LT); \ kk1 = _mm256_cmp_epu64_mask(MASK, R1, _MM_CMPINT_LT); \ kk2 = _mm256_cmp_epu64_mask(MASK, R2, _MM_CMPINT_LT); \ kk0h = _mm256_cmp_epu64_mask(MASK, R0 ## h, _MM_CMPINT_LT); \ kk1h = _mm256_cmp_epu64_mask(MASK, R1 ## h, _MM_CMPINT_LT); \ \ k = (kk2<<16)|(kk1h<<12)|(kk1<<8)|(kk0h<<4)|kk0; \ \ kk0 = _mm256_cmp_epu64_mask(MASK, R0, _MM_CMPINT_EQ); \ kk1 = _mm256_cmp_epu64_mask(MASK, R1, _MM_CMPINT_EQ); \ kk2 = _mm256_cmp_epu64_mask(MASK, R2, _MM_CMPINT_EQ); \ kk0h = _mm256_cmp_epu64_mask(MASK, R0 ## h, _MM_CMPINT_EQ); \ kk1h = _mm256_cmp_epu64_mask(MASK, R1 ## h, _MM_CMPINT_EQ); \ \ l = (kk2<<16)|(kk1h<<12)|(kk1<<8)|(kk0h<<4)|kk0; \ \ k = l + 2*k; \ k ^= l; \ \ kk0 = k; \ kk0h = (k>>4); \ kk1 = (k>>8); \ kk1h = (k>>12); \ kk2 = (k>>16); \ } \ \ R0 = _mm256_mask_sub_epi64(R0, (__mmask8)kk0, R0, MASK); \ R1 = _mm256_mask_sub_epi64(R1, (__mmask8)kk1, R1, MASK); \ R2 = _mm256_mask_sub_epi64(R2, (__mmask8)kk2, R2, MASK); \ R0 ## h = _mm256_mask_sub_epi64(R0 ## h, (__mmask8)kk0h, R0 ## h, MASK); \ R1 ## h = _mm256_mask_sub_epi64(R1 ## h, (__mmask8)kk1h, R1 ## h, MASK); \ \ R0 = _mm256_and_si256(R0, MASK); \ R1 = _mm256_and_si256(R1, MASK); \ R2 = _mm256_and_si256(R2, MASK); \ R0 ## h = _mm256_and_si256(R0 ## h, MASK); \ R1 ## h = _mm256_and_si256(R1 ## h, MASK); \ } #define NORMALIZE_52x30(R0,R1,R2,R3) { \ __m256i T0 = _mm256_srli_epi64(R0, EXP_DIGIT_SIZE_AVX512); \ __m256i T0h = _mm256_srli_epi64(R0 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T1 = _mm256_srli_epi64(R1, EXP_DIGIT_SIZE_AVX512); \ __m256i T1h = _mm256_srli_epi64(R1 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T2 = _mm256_srli_epi64(R2, EXP_DIGIT_SIZE_AVX512); \ __m256i T2h = _mm256_srli_epi64(R2 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T3 = _mm256_srli_epi64(R3, EXP_DIGIT_SIZE_AVX512); \ __m256i T3h = _mm256_srli_epi64(R3 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i MASK = _mm256_set1_epi64x(EXP_DIGIT_MASK_AVX512); \ \ Ipp32u kk0, kk1, kk2, kk3; \ Ipp32u kk0h, kk1h, kk2h, kk3h; \ kk0 = kk1 = kk2 = kk3 = kk0h = kk1h = kk2h = kk3h = 0; \ \ R0 = _mm256_and_si256(R0, MASK); \ R1 = _mm256_and_si256(R1, MASK); \ R2 = _mm256_and_si256(R2, MASK); \ R3 = _mm256_and_si256(R3, MASK); \ R0 ## h = _mm256_and_si256(R0 ## h, MASK); \ R1 ## h = _mm256_and_si256(R1 ## h, MASK); \ R2 ## h = _mm256_and_si256(R2 ## h, MASK); \ R3 ## h = _mm256_and_si256(R3 ## h, MASK); \ \ T3h = _mm256_alignr_epi64(T3h, T3, 3); \ T3 = _mm256_alignr_epi64(T3 , T2h, 3); \ T2h = _mm256_alignr_epi64(T2h, T2, 3); \ T2 = _mm256_alignr_epi64(T2 , T1h, 3); \ T1h = _mm256_alignr_epi64(T1h, T1, 3); \ T1 = _mm256_alignr_epi64(T1 , T0h, 3); \ T0h = _mm256_alignr_epi64(T0h, T0, 3); \ T0 = _mm256_alignr_epi64(T0, _mm256_setzero_si256(), 3); \ \ R0 = _mm256_add_epi64(R0, T0); \ R1 = _mm256_add_epi64(R1, T1); \ R2 = _mm256_add_epi64(R2, T2); \ R3 = _mm256_add_epi64(R3, T3); \ R0 ## h = _mm256_add_epi64(R0 ## h, T0h); \ R1 ## h = _mm256_add_epi64(R1 ## h, T1h); \ R2 ## h = _mm256_add_epi64(R2 ## h, T2h); \ R3 ## h = _mm256_add_epi64(R3 ## h, T3h); \ \ { \ Ipp32u k, l; \ k = l = 0; \ \ kk0 = _mm256_cmp_epu64_mask(MASK, R0, _MM_CMPINT_LT); \ kk1 = _mm256_cmp_epu64_mask(MASK, R1, _MM_CMPINT_LT); \ kk2 = _mm256_cmp_epu64_mask(MASK, R2, _MM_CMPINT_LT); \ kk3 = _mm256_cmp_epu64_mask(MASK, R3, _MM_CMPINT_LT); \ kk0h = _mm256_cmp_epu64_mask(MASK, R0 ## h, _MM_CMPINT_LT); \ kk1h = _mm256_cmp_epu64_mask(MASK, R1 ## h, _MM_CMPINT_LT); \ kk2h = _mm256_cmp_epu64_mask(MASK, R2 ## h, _MM_CMPINT_LT); \ kk3h = _mm256_cmp_epu64_mask(MASK, R3 ## h, _MM_CMPINT_LT); \ \ k = (kk3h<<28)|(kk3<<24)|(kk2h<<20)|(kk2<<16)|(kk1h<<12)|(kk1<<8)|(kk0h<<4)|kk0; \ \ kk0 = _mm256_cmp_epu64_mask(MASK, R0, _MM_CMPINT_EQ); \ kk1 = _mm256_cmp_epu64_mask(MASK, R1, _MM_CMPINT_EQ); \ kk2 = _mm256_cmp_epu64_mask(MASK, R2, _MM_CMPINT_EQ); \ kk3 = _mm256_cmp_epu64_mask(MASK, R3, _MM_CMPINT_EQ); \ kk0h = _mm256_cmp_epu64_mask(MASK, R0 ## h, _MM_CMPINT_EQ); \ kk1h = _mm256_cmp_epu64_mask(MASK, R1 ## h, _MM_CMPINT_EQ); \ kk2h = _mm256_cmp_epu64_mask(MASK, R2 ## h, _MM_CMPINT_EQ); \ kk3h = _mm256_cmp_epu64_mask(MASK, R3 ## h, _MM_CMPINT_EQ); \ \ l = (kk3h<<28)|(kk3<<24)|(kk2h<<20)|(kk2<<16)|(kk1h<<12)|(kk1<<8)|(kk0h<<4)|kk0; \ \ k = l + 2*k; \ k ^= l; \ \ kk0 = k; \ kk0h = (k>>4); \ kk1 = (k>>8); \ kk1h = (k>>12); \ kk2 = (k>>16); \ kk2h = (k>>20); \ kk3 = (k>>24); \ kk3h = (k>>28); \ } \ \ R0 = _mm256_mask_sub_epi64(R0, (__mmask8)kk0, R0, MASK); \ R1 = _mm256_mask_sub_epi64(R1, (__mmask8)kk1, R1, MASK); \ R2 = _mm256_mask_sub_epi64(R2, (__mmask8)kk2, R2, MASK); \ R3 = _mm256_mask_sub_epi64(R3, (__mmask8)kk3, R3, MASK); \ R0 ## h = _mm256_mask_sub_epi64(R0 ## h, (__mmask8)kk0h, R0 ## h, MASK); \ R1 ## h = _mm256_mask_sub_epi64(R1 ## h, (__mmask8)kk1h, R1 ## h, MASK); \ R2 ## h = _mm256_mask_sub_epi64(R2 ## h, (__mmask8)kk2h, R2 ## h, MASK); \ R3 ## h = _mm256_mask_sub_epi64(R3 ## h, (__mmask8)kk3h, R3 ## h, MASK); \ \ R0 = _mm256_and_si256(R0, MASK); \ R1 = _mm256_and_si256(R1, MASK); \ R2 = _mm256_and_si256(R2, MASK); \ R3 = _mm256_and_si256(R3, MASK); \ R0 ## h = _mm256_and_si256(R0 ## h, MASK); \ R1 ## h = _mm256_and_si256(R1 ## h, MASK); \ R2 ## h = _mm256_and_si256(R2 ## h, MASK); \ R3 ## h = _mm256_and_si256(R3 ## h, MASK); \ } #define NORMALIZE_52x40(R0,R1,R2,R3,R4) { \ __m256i T0 = _mm256_srli_epi64(R0, EXP_DIGIT_SIZE_AVX512); \ __m256i T0h = _mm256_srli_epi64(R0 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T1 = _mm256_srli_epi64(R1, EXP_DIGIT_SIZE_AVX512); \ __m256i T1h = _mm256_srli_epi64(R1 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T2 = _mm256_srli_epi64(R2, EXP_DIGIT_SIZE_AVX512); \ __m256i T2h = _mm256_srli_epi64(R2 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T3 = _mm256_srli_epi64(R3, EXP_DIGIT_SIZE_AVX512); \ __m256i T3h = _mm256_srli_epi64(R3 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i T4 = _mm256_srli_epi64(R4, EXP_DIGIT_SIZE_AVX512); \ __m256i T4h = _mm256_srli_epi64(R4 ## h, EXP_DIGIT_SIZE_AVX512); \ __m256i MASK = _mm256_set1_epi64x(EXP_DIGIT_MASK_AVX512); \ \ Ipp64u kk0, kk1, kk2, kk3, kk4; \ Ipp64u kk0h, kk1h, kk2h, kk3h, kk4h; \ kk0 = kk1 = kk2 = kk3 = kk4 = kk0h = kk1h = kk2h = kk3h = kk4h = 0; \ \ R0 = _mm256_and_si256(R0, MASK); \ R1 = _mm256_and_si256(R1, MASK); \ R2 = _mm256_and_si256(R2, MASK); \ R3 = _mm256_and_si256(R3, MASK); \ R4 = _mm256_and_si256(R4, MASK); \ R0 ## h = _mm256_and_si256(R0 ## h, MASK); \ R1 ## h = _mm256_and_si256(R1 ## h, MASK); \ R2 ## h = _mm256_and_si256(R2 ## h, MASK); \ R3 ## h = _mm256_and_si256(R3 ## h, MASK); \ R4 ## h = _mm256_and_si256(R4 ## h, MASK); \ \ T4h = _mm256_alignr_epi64(T4h, T4, 3); \ T4 = _mm256_alignr_epi64(T4 , T3h, 3); \ T3h = _mm256_alignr_epi64(T3h, T3, 3); \ T3 = _mm256_alignr_epi64(T3 , T2h, 3); \ T2h = _mm256_alignr_epi64(T2h, T2, 3); \ T2 = _mm256_alignr_epi64(T2 , T1h, 3); \ T1h = _mm256_alignr_epi64(T1h, T1, 3); \ T1 = _mm256_alignr_epi64(T1 , T0h, 3); \ T0h = _mm256_alignr_epi64(T0h, T0, 3); \ T0 = _mm256_alignr_epi64(T0, _mm256_setzero_si256(), 3); \ \ R0 = _mm256_add_epi64(R0, T0); \ R1 = _mm256_add_epi64(R1, T1); \ R2 = _mm256_add_epi64(R2, T2); \ R3 = _mm256_add_epi64(R3, T3); \ R4 = _mm256_add_epi64(R4, T4); \ R0 ## h = _mm256_add_epi64(R0 ## h, T0h); \ R1 ## h = _mm256_add_epi64(R1 ## h, T1h); \ R2 ## h = _mm256_add_epi64(R2 ## h, T2h); \ R3 ## h = _mm256_add_epi64(R3 ## h, T3h); \ R4 ## h = _mm256_add_epi64(R4 ## h, T4h); \ \ { \ Ipp64u k, l; \ k = l = 0; \ \ kk0 = _mm256_cmp_epu64_mask(MASK, R0, _MM_CMPINT_LT); \ kk1 = _mm256_cmp_epu64_mask(MASK, R1, _MM_CMPINT_LT); \ kk2 = _mm256_cmp_epu64_mask(MASK, R2, _MM_CMPINT_LT); \ kk3 = _mm256_cmp_epu64_mask(MASK, R3, _MM_CMPINT_LT); \ kk4 = _mm256_cmp_epu64_mask(MASK, R4, _MM_CMPINT_LT); \ kk0h = _mm256_cmp_epu64_mask(MASK, R0 ## h, _MM_CMPINT_LT); \ kk1h = _mm256_cmp_epu64_mask(MASK, R1 ## h, _MM_CMPINT_LT); \ kk2h = _mm256_cmp_epu64_mask(MASK, R2 ## h, _MM_CMPINT_LT); \ kk3h = _mm256_cmp_epu64_mask(MASK, R3 ## h, _MM_CMPINT_LT); \ kk4h = _mm256_cmp_epu64_mask(MASK, R4 ## h, _MM_CMPINT_LT); \ \ k = (kk4h<<36)|(kk4<<32)|(kk3h<<28)|(kk3<<24)|(kk2h<<20)| \ (kk2<<16)|(kk1h<<12)|(kk1<<8)|(kk0h<<4)|kk0; \ \ kk0 = _mm256_cmp_epu64_mask(MASK, R0, _MM_CMPINT_EQ); \ kk1 = _mm256_cmp_epu64_mask(MASK, R1, _MM_CMPINT_EQ); \ kk2 = _mm256_cmp_epu64_mask(MASK, R2, _MM_CMPINT_EQ); \ kk3 = _mm256_cmp_epu64_mask(MASK, R3, _MM_CMPINT_EQ); \ kk4 = _mm256_cmp_epu64_mask(MASK, R4, _MM_CMPINT_EQ); \ kk0h = _mm256_cmp_epu64_mask(MASK, R0 ## h, _MM_CMPINT_EQ); \ kk1h = _mm256_cmp_epu64_mask(MASK, R1 ## h, _MM_CMPINT_EQ); \ kk2h = _mm256_cmp_epu64_mask(MASK, R2 ## h, _MM_CMPINT_EQ); \ kk3h = _mm256_cmp_epu64_mask(MASK, R3 ## h, _MM_CMPINT_EQ); \ kk4h = _mm256_cmp_epu64_mask(MASK, R4 ## h, _MM_CMPINT_EQ); \ \ l = (kk4h<<36)|(kk4<<32)|(kk3h<<28)|(kk3<<24)|(kk2h<<20)| \ (kk2<<16)|(kk1h<<12)|(kk1<<8)|(kk0h<<4)|kk0; \ \ k = l + 2*k; \ k ^= l; \ \ kk0 = k; \ kk0h = (k>>4); \ kk1 = (k>>8); \ kk1h = (k>>12); \ kk2 = (k>>16); \ kk2h = (k>>20); \ kk3 = (k>>24); \ kk3h = (k>>28); \ kk4 = (k>>32); \ kk4h = (k>>36); \ } \ \ R0 = _mm256_mask_sub_epi64(R0, (__mmask8)kk0, R0, MASK); \ R1 = _mm256_mask_sub_epi64(R1, (__mmask8)kk1, R1, MASK); \ R2 = _mm256_mask_sub_epi64(R2, (__mmask8)kk2, R2, MASK); \ R3 = _mm256_mask_sub_epi64(R3, (__mmask8)kk3, R3, MASK); \ R4 = _mm256_mask_sub_epi64(R4, (__mmask8)kk4, R4, MASK); \ R0 ## h = _mm256_mask_sub_epi64(R0 ## h, (__mmask8)kk0h, R0 ## h, MASK); \ R1 ## h = _mm256_mask_sub_epi64(R1 ## h, (__mmask8)kk1h, R1 ## h, MASK); \ R2 ## h = _mm256_mask_sub_epi64(R2 ## h, (__mmask8)kk2h, R2 ## h, MASK); \ R3 ## h = _mm256_mask_sub_epi64(R3 ## h, (__mmask8)kk3h, R3 ## h, MASK); \ R4 ## h = _mm256_mask_sub_epi64(R4 ## h, (__mmask8)kk4h, R4 ## h, MASK); \ \ R0 = _mm256_and_si256(R0, MASK); \ R1 = _mm256_and_si256(R1, MASK); \ R2 = _mm256_and_si256(R2, MASK); \ R3 = _mm256_and_si256(R3, MASK); \ R4 = _mm256_and_si256(R4, MASK); \ R0 ## h = _mm256_and_si256(R0 ## h, MASK); \ R1 ## h = _mm256_and_si256(R1 ## h, MASK); \ R2 ## h = _mm256_and_si256(R2 ## h, MASK); \ R3 ## h = _mm256_and_si256(R3 ## h, MASK); \ R4 ## h = _mm256_and_si256(R4 ## h, MASK); \ } #endif // IFMA_NORM_52X_H cryptography-primitives-1.0.0/sources/ippcp/ifma_rsa_arith.h000066400000000000000000000121501470420105600243510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 _IFMA_RSA_ARITH_H_ #define _IFMA_RSA_ARITH_H_ /* * RSA kernels implemented with AVX512_IFMA256 ISA */ #include "owncp.h" #if(_IPP32E>=_IPP32E_K1) /* Almost Montgomery Multiplication / Squaring */ #define ifma256_amm52x20 OWNAPI(ifma256_amm52x20) IPP_OWN_DECL(void, ifma256_amm52x20, (Ipp64u out[20], const Ipp64u a[20], const Ipp64u b[20], const Ipp64u m[20], Ipp64u k0)) #define ifma256_ams52x20 OWNAPI(ifma256_ams52x20) IPP_OWN_DECL(void, ifma256_ams52x20, (Ipp64u out[20], const Ipp64u a[20], const Ipp64u m[20], Ipp64u k0)) #define ifma256_amm52x30 OWNAPI(ifma256_amm52x30) IPP_OWN_DECL(void, ifma256_amm52x30, (Ipp64u out[32], const Ipp64u a[32], const Ipp64u b[32], const Ipp64u m[32], Ipp64u k0)) #define ifma256_ams52x30 OWNAPI(ifma256_ams52x30) IPP_OWN_DECL(void, ifma256_ams52x30, (Ipp64u out[32], const Ipp64u a[32], const Ipp64u m[32], Ipp64u k0)) #define ifma256_amm52x40 OWNAPI(ifma256_amm52x40) IPP_OWN_DECL(void, ifma256_amm52x40, (Ipp64u out[40], const Ipp64u a[40], const Ipp64u b[40], const Ipp64u m[40], Ipp64u k0)) #define ifma256_ams52x40 OWNAPI(ifma256_ams52x40) IPP_OWN_DECL(void, ifma256_ams52x40, (Ipp64u out[40], const Ipp64u a[40], const Ipp64u m[40], Ipp64u k0)) /* * Dual Almost Montgomery Multiplication / Squaring * (two independent operations and data arrays) */ #define ifma256_amm52x20_dual OWNAPI(ifma256_amm52x20_dual) IPP_OWN_DECL(void, ifma256_amm52x20_dual, (Ipp64u out[2][20], const Ipp64u a[2][20], const Ipp64u b[2][20], const Ipp64u m[2][20], const Ipp64u k0[2])) #define ifma256_ams52x20_dual OWNAPI(ifma256_ams52x20_dual) IPP_OWN_DECL(void, ifma256_ams52x20_dual, (Ipp64u out[2][20], const Ipp64u a[2][20], const Ipp64u m[2][20], const Ipp64u k0[2])) #define ifma256_amm52x30_dual OWNAPI(ifma256_amm52x30_dual) IPP_OWN_DECL(void, ifma256_amm52x30_dual, (Ipp64u out[2][32], const Ipp64u a[2][32], const Ipp64u b[2][32], const Ipp64u m[2][32], const Ipp64u k0[2])) #define ifma256_ams52x30_dual OWNAPI(ifma256_ams52x30_dual) IPP_OWN_DECL(void, ifma256_ams52x30_dual, (Ipp64u out[2][32], const Ipp64u a[2][32], const Ipp64u m[2][32], const Ipp64u k0[2])) #define ifma256_amm52x40_dual OWNAPI(ifma256_amm52x40_dual) IPP_OWN_DECL(void, ifma256_amm52x40_dual, (Ipp64u out[2][40], const Ipp64u a[2][40], const Ipp64u b[2][40], const Ipp64u m[2][40], const Ipp64u k0[2])) #define ifma256_ams52x40_dual OWNAPI(ifma256_ams52x40_dual) IPP_OWN_DECL(void, ifma256_ams52x40_dual, (Ipp64u out[2][40], const Ipp64u a[2][40], const Ipp64u m[2][40], const Ipp64u k0[2])) /* Exponentiation */ #define ifma256_exp52x20 OWNAPI(ifma256_exp52x20) IPP_OWN_DECL (void, ifma256_exp52x20, (Ipp64u *out, const Ipp64u *base, const Ipp64u *exp, const Ipp64u *modulus, const Ipp64u *toMont, const Ipp64u k0)) /* Dual exponentiation */ #define ifma256_exp52x20_dual OWNAPI(ifma256_exp52x20_dual) IPP_OWN_DECL (void, ifma256_exp52x20_dual, (Ipp64u out [2][20], const Ipp64u base [2][20], const Ipp64u *exp [2], // 2x16 const Ipp64u modulus[2][20], const Ipp64u toMont [2][20], const Ipp64u k0 [2])) #define ifma256_exp52x30_dual OWNAPI(ifma256_exp52x30_dual) IPP_OWN_DECL (void, ifma256_exp52x30_dual, (Ipp64u out [2][32], const Ipp64u base [2][32], const Ipp64u *exp [2], // 2x24 const Ipp64u modulus[2][32], const Ipp64u toMont [2][32], const Ipp64u k0 [2])) #define ifma256_exp52x40_dual OWNAPI(ifma256_exp52x40_dual) IPP_OWN_DECL (void, ifma256_exp52x40_dual, (Ipp64u out [2][40], const Ipp64u base [2][40], const Ipp64u *exp [2], // 2x32 const Ipp64u modulus[2][40], const Ipp64u toMont [2][40], const Ipp64u k0 [2])) #endif // #if(_IPP32E>=_IPP32E_K1) #endif // #ifndef _IFMA_RSA_ARITH_H_ cryptography-primitives-1.0.0/sources/ippcp/ippcp.def000066400000000000000000000213201470420105600230220ustar00rootroot00000000000000EXPORTS ippcpInit cpGetReg cpStartTscp cpStopTscp cpStartTsc cpStopTsc cpGetCacheSize cpGetFeature ippcpSetCpuFeatures ippcpGetCpuFeatures ippcpGetCpuClocks ippcpSetNumThreads ippcpGetNumThreads ippcpGetEnabledCpuFeatures ippcpGetEnabledNumThreads ippcpGetStatusString ippcpGetLibVersion cryptoGetLibVersion ippsDESGetSize ippsDESInit ippsDESPack ippsDESUnpack ippsTDESEncryptECB ippsTDESDecryptECB ippsTDESEncryptCBC ippsTDESDecryptCBC ippsTDESEncryptCFB ippsTDESDecryptCFB ippsTDESEncryptOFB ippsTDESDecryptOFB ippsTDESEncryptCTR ippsTDESDecryptCTR ippsAESGetSize ippsAESInit ippsAESSetKey ippsAESPack ippsAESUnpack ippsAESSetupNoise ippsAES_GCMSetupNoise ippsAES_CMACSetupNoise ippsAESEncryptECB ippsAESDecryptECB ippsAESEncryptCBC ippsAESEncryptCBC_CS1 ippsAESEncryptCBC_CS2 ippsAESEncryptCBC_CS3 ippsAESDecryptCBC ippsAESDecryptCBC_CS1 ippsAESDecryptCBC_CS2 ippsAESDecryptCBC_CS3 ippsAESEncryptCFB ippsAESDecryptCFB ippsAESEncryptOFB ippsAESDecryptOFB ippsAESEncryptCTR ippsAESDecryptCTR ippsAESEncryptXTS_Direct ippsAESDecryptXTS_Direct ippsAES_EncryptCFB16_MB ippsSMS4GetSize ippsSMS4Init ippsSMS4SetKey ippsSMS4EncryptECB ippsSMS4DecryptECB ippsSMS4EncryptCBC ippsSMS4EncryptCBC_CS1 ippsSMS4EncryptCBC_CS2 ippsSMS4EncryptCBC_CS3 ippsSMS4DecryptCBC ippsSMS4DecryptCBC_CS1 ippsSMS4DecryptCBC_CS2 ippsSMS4DecryptCBC_CS3 ippsSMS4EncryptCFB ippsSMS4DecryptCFB ippsSMS4EncryptOFB ippsSMS4DecryptOFB ippsSMS4EncryptCTR ippsSMS4DecryptCTR ippsSMS4_CCMGetSize ippsSMS4_CCMInit ippsSMS4_CCMMessageLen ippsSMS4_CCMTagLen ippsSMS4_CCMStart ippsSMS4_CCMEncrypt ippsSMS4_CCMDecrypt ippsSMS4_CCMGetTag ippsAES_CCMGetSize ippsAES_CCMInit ippsAES_CCMMessageLen ippsAES_CCMTagLen ippsAES_CCMStart ippsAES_CCMEncrypt ippsAES_CCMDecrypt ippsAES_CCMGetTag ippsAES_GCMGetSize ippsAES_GCMInit ippsAES_GCMReinit ippsAES_GCMReset ippsAES_GCMProcessIV ippsAES_GCMProcessAAD ippsAES_GCMStart ippsAES_GCMEncrypt ippsAES_GCMDecrypt ippsAES_GCMGetTag ippsAES_XTSGetSize ippsAES_XTSInit ippsAES_XTSEncrypt ippsAES_XTSDecrypt ippsAES_S2V_CMAC ippsAES_SIVEncrypt ippsAES_SIVDecrypt ippsAES_CMACGetSize ippsAES_CMACInit ippsAES_CMACUpdate ippsAES_CMACFinal ippsAES_CMACGetTag ippsARCFourCheckKey ippsARCFourGetSize ippsARCFourInit ippsARCFourReset ippsARCFourPack ippsARCFourUnpack ippsARCFourEncrypt ippsARCFourDecrypt ippsHashGetSize ippsHashInit ippsHashPack ippsHashUnpack ippsHashDuplicate ippsHashUpdate ippsHashGetTag ippsHashFinal ippsHashMessage ippsHashMethodGetSize ippsHashMethodSet_MD5 ippsHashMethodSet_SM3 ippsHashMethodSet_SHA1 ippsHashMethodSet_SHA1_NI ippsHashMethodSet_SHA1_TT ippsHashMethodSet_SHA256 ippsHashMethodSet_SHA256_NI ippsHashMethodSet_SHA256_TT ippsHashMethodSet_SHA224 ippsHashMethodSet_SHA224_NI ippsHashMethodSet_SHA224_TT ippsHashMethodSet_SHA512 ippsHashMethodSet_SHA384 ippsHashMethodSet_SHA512_256 ippsHashMethodSet_SHA512_224 ippsHashStateMethodSet_SM3 ippsHashStateMethodSet_SHA256 ippsHashStateMethodSet_SHA256_NI ippsHashStateMethodSet_SHA256_TT ippsHashStateMethodSet_SHA224 ippsHashStateMethodSet_SHA224_NI ippsHashStateMethodSet_SHA224_TT ippsHashStateMethodSet_SHA512 ippsHashStateMethodSet_SHA384 ippsHashStateMethodSet_SHA512_256 ippsHashStateMethodSet_SHA512_224 ippsHashMethod_MD5 ippsHashMethod_SM3 ippsHashMethod_SHA1 ippsHashMethod_SHA1_NI ippsHashMethod_SHA1_TT ippsHashMethod_SHA256 ippsHashMethod_SHA256_NI ippsHashMethod_SHA256_TT ippsHashMethod_SHA224 ippsHashMethod_SHA224_NI ippsHashMethod_SHA224_TT ippsHashMethod_SHA512 ippsHashMethod_SHA384 ippsHashMethod_SHA512_256 ippsHashMethod_SHA512_224 ippsHashMethodGetInfo ippsHashGetSize_rmf ippsHashInit_rmf ippsHashPack_rmf ippsHashUnpack_rmf ippsHashDuplicate_rmf ippsHashUpdate_rmf ippsHashGetTag_rmf ippsHashFinal_rmf ippsHashMessage_rmf ippsHashGetInfo_rmf ippsMGF ippsMGF1_rmf ippsMGF2_rmf ippsHMAC_GetSize ippsHMAC_Init ippsHMAC_Pack ippsHMAC_Unpack ippsHMAC_Duplicate ippsHMAC_Update ippsHMAC_Final ippsHMAC_GetTag ippsHMAC_Message ippsHMACGetSize_rmf ippsHMACInit_rmf ippsHMACPack_rmf ippsHMACUnpack_rmf ippsHMACDuplicate_rmf ippsHMACUpdate_rmf ippsHMACFinal_rmf ippsHMACGetTag_rmf ippsHMACMessage_rmf ippsBigNumGetSize ippsBigNumInit ippsCmpZero_BN ippsCmp_BN ippsGetSize_BN ippsSet_BN ippsGet_BN ippsRef_BN ippsExtGet_BN ippsAdd_BN ippsSub_BN ippsMul_BN ippsMAC_BN_I ippsDiv_BN ippsMod_BN ippsGcd_BN ippsModInv_BN ippsSetOctString_BN ippsGetOctString_BN ippsMontGetSize ippsMontInit ippsMontSet ippsMontGet ippsMontForm ippsMontMul ippsMontExp ippsPRNGGetSize ippsPRNGInit ippsPRNGSetModulus ippsPRNGSetH0 ippsPRNGSetAugment ippsPRNGSetSeed ippsPRNGGetSeed ippsPRNGen ippsPRNGen_BN ippsPRNGenRDRAND ippsPRNGenRDRAND_BN ippsTRNGenRDSEED ippsTRNGenRDSEED_BN ippsPrimeGetSize ippsPrimeInit ippsPrimeGen ippsPrimeTest ippsPrimeGen_BN ippsPrimeTest_BN ippsPrimeGet ippsPrimeGet_BN ippsPrimeSet ippsPrimeSet_BN ippsRSA_GetSizePublicKey ippsRSA_InitPublicKey ippsRSA_SetPublicKey ippsRSA_GetPublicKey ippsRSA_GetSizePrivateKeyType1 ippsRSA_InitPrivateKeyType1 ippsRSA_SetPrivateKeyType1 ippsRSA_GetPrivateKeyType1 ippsRSA_GetSizePrivateKeyType2 ippsRSA_InitPrivateKeyType2 ippsRSA_SetPrivateKeyType2 ippsRSA_GetPrivateKeyType2 ippsRSA_GetBufferSizePublicKey ippsRSA_GetBufferSizePrivateKey ippsRSA_Encrypt ippsRSA_Decrypt ippsRSA_GenerateKeys ippsRSA_ValidateKeys ippsRSAEncrypt_OAEP ippsRSADecrypt_OAEP ippsRSAEncrypt_OAEP_rmf ippsRSADecrypt_OAEP_rmf ippsRSAEncrypt_PKCSv15 ippsRSADecrypt_PKCSv15 ippsRSASign_PSS ippsRSAVerify_PSS ippsRSASign_PSS_rmf ippsRSAVerify_PSS_rmf ippsRSASign_PKCS1v15 ippsRSAVerify_PKCS1v15 ippsRSASign_PKCS1v15_rmf ippsRSAVerify_PKCS1v15_rmf ippsDLGetResultString ippsDLPGetSize ippsDLPInit ippsDLPPack ippsDLPUnpack ippsDLPSet ippsDLPGet ippsDLPSetDP ippsDLPGetDP ippsDLPGenKeyPair ippsDLPPublicKey ippsDLPValidateKeyPair ippsDLPSetKeyPair ippsDLPSignDSA ippsDLPVerifyDSA ippsDLPSharedSecretDH ippsDLPGenerateDSA ippsDLPValidateDSA ippsDLPGenerateDH ippsDLPValidateDH ippsECCGetResultString ippsGFpGetSize ippsGFpInitArbitrary ippsGFpInitFixed ippsGFpInit ippsGFpMethod_p192r1 ippsGFpMethod_p224r1 ippsGFpMethod_p256r1 ippsGFpMethod_p384r1 ippsGFpMethod_p521r1 ippsGFpMethod_p256sm2 ippsGFpMethod_p256bn ippsGFpMethod_p256 ippsGFpMethod_pArb ippsGFpxGetSize ippsGFpxInit ippsGFpxInitBinomial ippsGFpxMethod_binom2_epid2 ippsGFpxMethod_binom3_epid2 ippsGFpxMethod_binom2 ippsGFpxMethod_binom3 ippsGFpxMethod_binom ippsGFpxMethod_com ippsGFpScratchBufferSize ippsGFpElementGetSize ippsGFpElementInit ippsGFpSetElement ippsGFpSetElementRegular ippsGFpSetElementOctString ippsGFpSetElementRandom ippsGFpSetElementHash ippsGFpSetElementHash_rmf ippsGFpCpyElement ippsGFpGetElement ippsGFpGetElementOctString ippsGFpCmpElement ippsGFpIsZeroElement ippsGFpIsUnityElement ippsGFpConj ippsGFpNeg ippsGFpInv ippsGFpSqrt ippsGFpSqr ippsGFpAdd ippsGFpSub ippsGFpMul ippsGFpExp ippsGFpMultiExp ippsGFpAdd_PE ippsGFpSub_PE ippsGFpMul_PE ippsGFpGetInfo ippsGFpECGetSize ippsGFpECInit ippsGFpECSet ippsGFpECSetSubgroup ippsGFpECInitStd128r1 ippsGFpECInitStd128r2 ippsGFpECInitStd192r1 ippsGFpECInitStd224r1 ippsGFpECInitStd256r1 ippsGFpECInitStd384r1 ippsGFpECInitStd521r1 ippsGFpECInitStdSM2 ippsGFpECInitStdBN256 ippsGFpECBindGxyTblStd192r1 ippsGFpECBindGxyTblStd224r1 ippsGFpECBindGxyTblStd256r1 ippsGFpECBindGxyTblStd384r1 ippsGFpECBindGxyTblStd521r1 ippsGFpECBindGxyTblStdSM2 ippsGFpECGet ippsGFpECGetSubgroup ippsGFpECGetInfo_GF ippsGFpECScratchBufferSize ippsGFpECVerify ippsGFpECPointGetSize ippsGFpECPointInit ippsGFpECSetPointAtInfinity ippsGFpECSetPoint ippsGFpECSetPointRegular ippsGFpECSetPointRandom ippsGFpECMakePoint ippsGFpECSetPointHash ippsGFpECSetPointHash_rmf ippsGFpECSetPointHashBackCompatible ippsGFpECSetPointHashBackCompatible_rmf ippsGFpECGetPoint ippsGFpECGetPointRegular ippsGFpECSetPointOctString ippsGFpECGetPointOctString ippsGFpECTstPoint ippsGFpECTstPointInSubgroup ippsGFpECCpyPoint ippsGFpECCmpPoint ippsGFpECNegPoint ippsGFpECAddPoint ippsGFpECMulPoint ippsGFpECPrivateKey ippsGFpECPublicKey ippsGFpECTstKeyPair ippsGFpECSharedSecretDH ippsGFpECSharedSecretDHC ippsGFpECSignDSA ippsGFpECVerifyDSA ippsGFpECUserIDHashSM2 ippsGFpECMessageRepresentationSM2 ippsGFpECSignNR ippsGFpECVerifyNR ippsGFpECSignSM2 ippsGFpECVerifySM2 ippsGFpECKeyExchangeSM2_GetSize ippsGFpECKeyExchangeSM2_Init ippsGFpECKeyExchangeSM2_Setup ippsGFpECKeyExchangeSM2_SharedKey ippsGFpECKeyExchangeSM2_Confirm ippsGFpECEncryptSM2_Ext_EncMsgSize ippsGFpECEncryptSM2_Ext ippsGFpECDecryptSM2_Ext_DecMsgSize ippsGFpECDecryptSM2_Ext ippsGFpECESGetSize_SM2 ippsGFpECESInit_SM2 ippsGFpECESSetKey_SM2 ippsGFpECESStart_SM2 ippsGFpECESEncrypt_SM2 ippsGFpECESDecrypt_SM2 ippsGFpECESFinal_SM2 ippsGFpECESGetBuffersSize_SM2 ippsXMSSVerify ippsXMSSSetPublicKeyState ippsXMSSSetSignatureState ippsXMSSSignatureStateGetSize ippsXMSSPublicKeyStateGetSize ippsXMSSBufferGetSize ippsLMSBufferGetSize ippsLMSSignatureStateGetSize ippsLMSPublicKeyStateGetSize ippsLMSSetPublicKeyState ippsLMSSetSignatureState ippsLMSVerify cryptography-primitives-1.0.0/sources/ippcp/ippcp_fips_selftests.def000066400000000000000000000253141470420105600261460ustar00rootroot00000000000000EXPORTS ippcpInit cpGetReg cpStartTscp cpStopTscp cpStartTsc cpStopTsc cpGetCacheSize cpGetFeature ippcpSetCpuFeatures ippcpGetCpuFeatures ippcpGetCpuClocks ippcpSetNumThreads ippcpGetNumThreads ippcpGetEnabledCpuFeatures ippcpGetEnabledNumThreads ippcpGetStatusString ippcpGetLibVersion cryptoGetLibVersion ippsDESGetSize ippsDESInit ippsDESPack ippsDESUnpack ippsTDESEncryptECB ippsTDESDecryptECB ippsTDESEncryptCBC ippsTDESDecryptCBC ippsTDESEncryptCFB ippsTDESDecryptCFB ippsTDESEncryptOFB ippsTDESDecryptOFB ippsTDESEncryptCTR ippsTDESDecryptCTR ippsAESGetSize ippsAESInit ippsAESSetKey ippsAESPack ippsAESUnpack ippsAESSetupNoise ippsAES_GCMSetupNoise ippsAES_CMACSetupNoise ippsAESEncryptECB ippsAESDecryptECB ippsAESEncryptCBC ippsAESEncryptCBC_CS1 ippsAESEncryptCBC_CS2 ippsAESEncryptCBC_CS3 ippsAESDecryptCBC ippsAESDecryptCBC_CS1 ippsAESDecryptCBC_CS2 ippsAESDecryptCBC_CS3 ippsAESEncryptCFB ippsAESDecryptCFB ippsAESEncryptOFB ippsAESDecryptOFB ippsAESEncryptCTR ippsAESDecryptCTR ippsAESEncryptXTS_Direct ippsAESDecryptXTS_Direct ippsAES_EncryptCFB16_MB ippsSMS4GetSize ippsSMS4Init ippsSMS4SetKey ippsSMS4EncryptECB ippsSMS4DecryptECB ippsSMS4EncryptCBC ippsSMS4EncryptCBC_CS1 ippsSMS4EncryptCBC_CS2 ippsSMS4EncryptCBC_CS3 ippsSMS4DecryptCBC ippsSMS4DecryptCBC_CS1 ippsSMS4DecryptCBC_CS2 ippsSMS4DecryptCBC_CS3 ippsSMS4EncryptCFB ippsSMS4DecryptCFB ippsSMS4EncryptOFB ippsSMS4DecryptOFB ippsSMS4EncryptCTR ippsSMS4DecryptCTR ippsSMS4_CCMGetSize ippsSMS4_CCMInit ippsSMS4_CCMMessageLen ippsSMS4_CCMTagLen ippsSMS4_CCMStart ippsSMS4_CCMEncrypt ippsSMS4_CCMDecrypt ippsSMS4_CCMGetTag ippsAES_CCMGetSize ippsAES_CCMInit ippsAES_CCMMessageLen ippsAES_CCMTagLen ippsAES_CCMStart ippsAES_CCMEncrypt ippsAES_CCMDecrypt ippsAES_CCMGetTag ippsAES_GCMGetSize ippsAES_GCMInit ippsAES_GCMReinit ippsAES_GCMReset ippsAES_GCMProcessIV ippsAES_GCMProcessAAD ippsAES_GCMStart ippsAES_GCMEncrypt ippsAES_GCMDecrypt ippsAES_GCMGetTag ippsAES_XTSGetSize ippsAES_XTSInit ippsAES_XTSEncrypt ippsAES_XTSDecrypt ippsAES_S2V_CMAC ippsAES_SIVEncrypt ippsAES_SIVDecrypt ippsAES_CMACGetSize ippsAES_CMACInit ippsAES_CMACUpdate ippsAES_CMACFinal ippsAES_CMACGetTag ippsARCFourCheckKey ippsARCFourGetSize ippsARCFourInit ippsARCFourReset ippsARCFourPack ippsARCFourUnpack ippsARCFourEncrypt ippsARCFourDecrypt ippsHashGetSize ippsHashInit ippsHashPack ippsHashUnpack ippsHashDuplicate ippsHashUpdate ippsHashGetTag ippsHashFinal ippsHashMessage ippsHashMethodGetSize ippsHashMethodSet_MD5 ippsHashMethodSet_SM3 ippsHashMethodSet_SHA1 ippsHashMethodSet_SHA1_NI ippsHashMethodSet_SHA1_TT ippsHashMethodSet_SHA256 ippsHashMethodSet_SHA256_NI ippsHashMethodSet_SHA256_TT ippsHashMethodSet_SHA224 ippsHashMethodSet_SHA224_NI ippsHashMethodSet_SHA224_TT ippsHashMethodSet_SHA512 ippsHashMethodSet_SHA384 ippsHashMethodSet_SHA512_256 ippsHashMethodSet_SHA512_224 ippsHashStateMethodSet_SM3 ippsHashStateMethodSet_SHA256 ippsHashStateMethodSet_SHA256_NI ippsHashStateMethodSet_SHA256_TT ippsHashStateMethodSet_SHA224 ippsHashStateMethodSet_SHA224_NI ippsHashStateMethodSet_SHA224_TT ippsHashStateMethodSet_SHA512 ippsHashStateMethodSet_SHA384 ippsHashStateMethodSet_SHA512_256 ippsHashStateMethodSet_SHA512_224 ippsHashMethod_MD5 ippsHashMethod_SM3 ippsHashMethod_SHA1 ippsHashMethod_SHA1_NI ippsHashMethod_SHA1_TT ippsHashMethod_SHA256 ippsHashMethod_SHA256_NI ippsHashMethod_SHA256_TT ippsHashMethod_SHA224 ippsHashMethod_SHA224_NI ippsHashMethod_SHA224_TT ippsHashMethod_SHA512 ippsHashMethod_SHA384 ippsHashMethod_SHA512_256 ippsHashMethod_SHA512_224 ippsHashMethodGetInfo ippsHashGetSize_rmf ippsHashInit_rmf ippsHashPack_rmf ippsHashUnpack_rmf ippsHashDuplicate_rmf ippsHashUpdate_rmf ippsHashGetTag_rmf ippsHashFinal_rmf ippsHashMessage_rmf ippsHashGetInfo_rmf ippsMGF ippsMGF1_rmf ippsMGF2_rmf ippsHMAC_GetSize ippsHMAC_Init ippsHMAC_Pack ippsHMAC_Unpack ippsHMAC_Duplicate ippsHMAC_Update ippsHMAC_Final ippsHMAC_GetTag ippsHMAC_Message ippsHMACGetSize_rmf ippsHMACInit_rmf ippsHMACPack_rmf ippsHMACUnpack_rmf ippsHMACDuplicate_rmf ippsHMACUpdate_rmf ippsHMACFinal_rmf ippsHMACGetTag_rmf ippsHMACMessage_rmf ippsBigNumGetSize ippsBigNumInit ippsCmpZero_BN ippsCmp_BN ippsGetSize_BN ippsSet_BN ippsGet_BN ippsRef_BN ippsExtGet_BN ippsAdd_BN ippsSub_BN ippsMul_BN ippsMAC_BN_I ippsDiv_BN ippsMod_BN ippsGcd_BN ippsModInv_BN ippsSetOctString_BN ippsGetOctString_BN ippsMontGetSize ippsMontInit ippsMontSet ippsMontGet ippsMontForm ippsMontMul ippsMontExp ippsPRNGGetSize ippsPRNGInit ippsPRNGSetModulus ippsPRNGSetH0 ippsPRNGSetAugment ippsPRNGSetSeed ippsPRNGGetSeed ippsPRNGen ippsPRNGen_BN ippsPRNGenRDRAND ippsPRNGenRDRAND_BN ippsTRNGenRDSEED ippsTRNGenRDSEED_BN ippsPrimeGetSize ippsPrimeInit ippsPrimeGen ippsPrimeTest ippsPrimeGen_BN ippsPrimeTest_BN ippsPrimeGet ippsPrimeGet_BN ippsPrimeSet ippsPrimeSet_BN ippsRSA_GetSizePublicKey ippsRSA_InitPublicKey ippsRSA_SetPublicKey ippsRSA_GetPublicKey ippsRSA_GetSizePrivateKeyType1 ippsRSA_InitPrivateKeyType1 ippsRSA_SetPrivateKeyType1 ippsRSA_GetPrivateKeyType1 ippsRSA_GetSizePrivateKeyType2 ippsRSA_InitPrivateKeyType2 ippsRSA_SetPrivateKeyType2 ippsRSA_GetPrivateKeyType2 ippsRSA_GetBufferSizePublicKey ippsRSA_GetBufferSizePrivateKey ippsRSA_Encrypt ippsRSA_Decrypt ippsRSA_GenerateKeys ippsRSA_ValidateKeys ippsRSAEncrypt_OAEP ippsRSADecrypt_OAEP ippsRSAEncrypt_OAEP_rmf ippsRSADecrypt_OAEP_rmf ippsRSAEncrypt_PKCSv15 ippsRSADecrypt_PKCSv15 ippsRSASign_PSS ippsRSAVerify_PSS ippsRSASign_PSS_rmf ippsRSAVerify_PSS_rmf ippsRSASign_PKCS1v15 ippsRSAVerify_PKCS1v15 ippsRSASign_PKCS1v15_rmf ippsRSAVerify_PKCS1v15_rmf ippsDLGetResultString ippsDLPGetSize ippsDLPInit ippsDLPPack ippsDLPUnpack ippsDLPSet ippsDLPGet ippsDLPSetDP ippsDLPGetDP ippsDLPGenKeyPair ippsDLPPublicKey ippsDLPValidateKeyPair ippsDLPSetKeyPair ippsDLPSignDSA ippsDLPVerifyDSA ippsDLPSharedSecretDH ippsDLPGenerateDSA ippsDLPValidateDSA ippsDLPGenerateDH ippsDLPValidateDH ippsECCGetResultString ippsGFpGetSize ippsGFpInitArbitrary ippsGFpInitFixed ippsGFpInit ippsGFpMethod_p192r1 ippsGFpMethod_p224r1 ippsGFpMethod_p256r1 ippsGFpMethod_p384r1 ippsGFpMethod_p521r1 ippsGFpMethod_p256sm2 ippsGFpMethod_p256bn ippsGFpMethod_p256 ippsGFpMethod_pArb ippsGFpxGetSize ippsGFpxInit ippsGFpxInitBinomial ippsGFpxMethod_binom2_epid2 ippsGFpxMethod_binom3_epid2 ippsGFpxMethod_binom2 ippsGFpxMethod_binom3 ippsGFpxMethod_binom ippsGFpxMethod_com ippsGFpScratchBufferSize ippsGFpElementGetSize ippsGFpElementInit ippsGFpSetElement ippsGFpSetElementRegular ippsGFpSetElementOctString ippsGFpSetElementRandom ippsGFpSetElementHash ippsGFpSetElementHash_rmf ippsGFpCpyElement ippsGFpGetElement ippsGFpGetElementOctString ippsGFpCmpElement ippsGFpIsZeroElement ippsGFpIsUnityElement ippsGFpConj ippsGFpNeg ippsGFpInv ippsGFpSqrt ippsGFpSqr ippsGFpAdd ippsGFpSub ippsGFpMul ippsGFpExp ippsGFpMultiExp ippsGFpAdd_PE ippsGFpSub_PE ippsGFpMul_PE ippsGFpGetInfo ippsGFpECGetSize ippsGFpECInit ippsGFpECSet ippsGFpECSetSubgroup ippsGFpECInitStd128r1 ippsGFpECInitStd128r2 ippsGFpECInitStd192r1 ippsGFpECInitStd224r1 ippsGFpECInitStd256r1 ippsGFpECInitStd384r1 ippsGFpECInitStd521r1 ippsGFpECInitStdSM2 ippsGFpECInitStdBN256 ippsGFpECBindGxyTblStd192r1 ippsGFpECBindGxyTblStd224r1 ippsGFpECBindGxyTblStd256r1 ippsGFpECBindGxyTblStd384r1 ippsGFpECBindGxyTblStd521r1 ippsGFpECBindGxyTblStdSM2 ippsGFpECGet ippsGFpECGetSubgroup ippsGFpECGetInfo_GF ippsGFpECScratchBufferSize ippsGFpECVerify ippsGFpECPointGetSize ippsGFpECPointInit ippsGFpECSetPointAtInfinity ippsGFpECSetPoint ippsGFpECSetPointRegular ippsGFpECSetPointRandom ippsGFpECMakePoint ippsGFpECSetPointHash ippsGFpECSetPointHash_rmf ippsGFpECSetPointHashBackCompatible ippsGFpECSetPointHashBackCompatible_rmf ippsGFpECGetPoint ippsGFpECGetPointRegular ippsGFpECSetPointOctString ippsGFpECGetPointOctString ippsGFpECTstPoint ippsGFpECTstPointInSubgroup ippsGFpECCpyPoint ippsGFpECCmpPoint ippsGFpECNegPoint ippsGFpECAddPoint ippsGFpECMulPoint ippsGFpECPrivateKey ippsGFpECPublicKey ippsGFpECTstKeyPair ippsGFpECSharedSecretDH ippsGFpECSharedSecretDHC ippsGFpECSignDSA ippsGFpECVerifyDSA ippsGFpECUserIDHashSM2 ippsGFpECMessageRepresentationSM2 ippsGFpECSignNR ippsGFpECVerifyNR ippsGFpECSignSM2 ippsGFpECVerifySM2 ippsGFpECKeyExchangeSM2_GetSize ippsGFpECKeyExchangeSM2_Init ippsGFpECKeyExchangeSM2_Setup ippsGFpECKeyExchangeSM2_SharedKey ippsGFpECKeyExchangeSM2_Confirm ippsGFpECEncryptSM2_Ext_EncMsgSize ippsGFpECEncryptSM2_Ext ippsGFpECDecryptSM2_Ext_DecMsgSize ippsGFpECDecryptSM2_Ext ippsGFpECESGetSize_SM2 ippsGFpECESInit_SM2 ippsGFpECESSetKey_SM2 ippsGFpECESStart_SM2 ippsGFpECESEncrypt_SM2 ippsGFpECESDecrypt_SM2 ippsGFpECESFinal_SM2 ippsGFpECESGetBuffersSize_SM2 ippsXMSSVerify ippsXMSSSetPublicKeyState ippsXMSSSetSignatureState ippsXMSSSignatureStateGetSize ippsXMSSPublicKeyStateGetSize ippsXMSSBufferGetSize ippsLMSBufferGetSize ippsLMSSignatureStateGetSize ippsLMSPublicKeyStateGetSize ippsLMSSetPublicKeyState ippsLMSSetSignatureState ippsLMSVerify ippcp_is_fips_approved_func fips_selftest_ippsAESEncryptDecrypt_get_size fips_selftest_ippsAESEncryptCBC fips_selftest_ippsAESDecryptCBC fips_selftest_ippsAESEncryptCBC_CS1 fips_selftest_ippsAESEncryptCBC_CS2 fips_selftest_ippsAESEncryptCBC_CS3 fips_selftest_ippsAESDecryptCBC_CS1 fips_selftest_ippsAESDecryptCBC_CS2 fips_selftest_ippsAESDecryptCBC_CS3 fips_selftest_ippsAESEncryptCFB fips_selftest_ippsAESDecryptCFB fips_selftest_ippsAESEncryptOFB fips_selftest_ippsAESDecryptOFB fips_selftest_ippsAESEncryptCTR fips_selftest_ippsAESDecryptCTR fips_selftest_ippsAESEncryptDecryptCCM_get_size fips_selftest_ippsAES_CCMEncrypt fips_selftest_ippsAES_CCMDecrypt fips_selftest_ippsAES_GCM_get_size fips_selftest_ippsAES_GCMEncrypt fips_selftest_ippsAES_GCMDecrypt fips_selftest_ippsAES_CMAC_get_size fips_selftest_ippsAES_CMACUpdate fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size_keys fips_selftest_ippsRSAEncryptDecrypt_OAEP_rmf_get_size fips_selftest_ippsRSAEncrypt_OAEP_rmf fips_selftest_ippsRSADecrypt_OAEP_rmf fips_selftest_ippsHash_rmf_get_size fips_selftest_ippsHashUpdate_rmf fips_selftest_ippsHashMessage_rmf fips_selftest_ippsHMAC_rmf_get_size fips_selftest_ippsHMACUpdate_rmf fips_selftest_ippsHMACMessage_rmf fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size_keys fips_selftest_ippsRSASignVerify_PKCS1v15_rmf_get_size fips_selftest_ippsRSASign_PKCS1v15_rmf fips_selftest_ippsRSAVerify_PKCS1v15_rmf fips_selftest_ippsRSASignVerify_PSS_rmf_get_size_keys fips_selftest_ippsRSASignVerify_PSS_rmf_get_size fips_selftest_ippsRSASign_PSS_rmf fips_selftest_ippsRSAVerify_PSS_rmf fips_selftest_ippsRSA_GenerateKeys fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFp_buff fips_selftest_ippsGFpECSignVerifyDSA_get_size_GFpEC_buff fips_selftest_ippsGFpECSignVerifyDSA_get_size_data_buff fips_selftest_ippsGFpECSignDSA fips_selftest_ippsGFpECVerifyDSA fips_selftest_ippsGFpECPublicKey fips_selftest_ippsGFpECPrivateKey fips_selftest_ippsGFpECSharedSecretDH fips_selftest_ippsLMSVerify_get_size fips_selftest_ippsLMSVerify cryptography-primitives-1.0.0/sources/ippcp/lms/000077500000000000000000000000001470420105600220245ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/lms/lms_setters_getters.c000066400000000000000000000302161470420105600262730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 "owndefs.h" #include "lms_internal/lms.h" /*F* // Name: ippsLMSBufferGetSize // // Purpose: Get the LMS temporary buffer size (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsBadArgErr lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8 // lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1 // lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25 // lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5 // ippStsLengthErr maxMessageLength < 1 // maxMessageLength > (Ipp32s)(IPP_MAX_32S) - // - (byteSizeI + 4(q byteSize) + 2(D_MESG byteSize) + n(C byteSize)) // ippStsNoErr no errors // // Parameters: // pSize pointer to the work buffer's byte size // maxMessageLength maximum length of the processing message // lmsType structure with LMS parameters lmotsOIDAlgo and lmsOIDAlgo // *F*/ IPPFUN(IppStatus, ippsLMSBufferGetSize, (Ipp32s* pSize, Ipp32s maxMessageLength, const IppsLMSAlgoType lmsType)) { IppStatus ippcpSts = ippStsNoErr; /* Input parameters check */ IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5, ippStsBadArgErr); /* Set LMOTS and LMS parameters */ cpLMOTSParams lmotsParams; ippcpSts = setLMOTSParams(lmsType.lmotsOIDAlgo, &lmotsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) cpLMSParams lmsParams; ippcpSts = setLMSParams(lmsType.lmsOIDAlgo, &lmsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) /* Check message length */ IPP_BADARG_RET(maxMessageLength < 1, ippStsLengthErr); // this restriction is needed to avoid overflow of Ipp32s // maxMessageLength must be less than IPP_MAX_32S - (CP_PK_I_BYTESIZE + q + D_MESG + C ) IPP_BADARG_RET(maxMessageLength > (Ipp32s)((IPP_MAX_32S) - (CP_PK_I_BYTESIZE + 4 + 2 + lmotsParams.n)), ippStsLengthErr); /* Calculate the maximum Set LMOTS and LMS parameters */ // pubKey->I || q || D_MESG || C || pMsg Ipp32u lenBufQ = CP_PK_I_BYTESIZE + 4 + 2 + lmotsParams.n + (Ipp32u)maxMessageLength; // pubKey->I || q || i || j || Y[i] Ipp32u lenBufTmp = CP_PK_I_BYTESIZE + 4 + 2 + 1 + lmotsParams.n; // pubKey->I || node_num || D_LEAF || Kc Ipp32u lenBufTc = CP_PK_I_BYTESIZE + 4 + 2 + lmotsParams.n; // pubKey->I || node_num/2 || D_INTR || path[i] || tmp Ipp32u lenBufIntr = CP_PK_I_BYTESIZE + 4 + 2 + lmotsParams.n + lmotsParams.n; *pSize = (Ipp32s)IPP_MAX(IPP_MAX(IPP_MAX(lenBufQ, lenBufTmp), lenBufTc), lenBufIntr); return ippcpSts; } /*F* // Name: ippsLMSSignatureStateGetSize // // Purpose: Get the LMS signature state size (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsBadArgErr lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8 // lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1 // lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25 // lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5 // ippStsNoErr no errors // // Parameters: // pSize pointer to the size // lmsType structure with LMS parameters lmotsOIDAlgo and lmsOIDAlgo // *F*/ IPPFUN(IppStatus, ippsLMSSignatureStateGetSize, (Ipp32s* pSize, const IppsLMSAlgoType lmsType)) { IppStatus ippcpSts = ippStsNoErr; IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5, ippStsBadArgErr); /* Set LMOTS and LMS parameters */ cpLMOTSParams lmotsParams; ippcpSts = setLMOTSParams(lmsType.lmotsOIDAlgo, &lmotsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) cpLMSParams lmsParams; ippcpSts = setLMSParams(lmsType.lmsOIDAlgo, &lmsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) *pSize = (Ipp32s)sizeof(IppsLMSSignatureState) + (Ipp32s)(lmotsParams.n * lmsParams.h) + /*_pAuthPath*/ (Ipp32s)lmotsParams.n + /* C */ (Ipp32s)(lmotsParams.n * lmotsParams.p); /* Y */ return ippcpSts; } /*F* // Name: ippsLMSPublicKeyStateGetSize // // Purpose: Provides the LMS public key state size (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsBadArgErr lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8 // lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1 // lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25 // lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5 // ippStsNoErr no errors // // Parameters: // pSize pointer to the size // lmsType structure with LMS parameters lmotsOIDAlgo and lmsOIDAlgo // *F*/ IPPFUN(IppStatus, ippsLMSPublicKeyStateGetSize, (Ipp32s* pSize, const IppsLMSAlgoType lmsType)) { IppStatus ippcpSts = ippStsNoErr; IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5, ippStsBadArgErr); /* Set LMS parameters */ cpLMSParams lmsParams; ippcpSts = setLMSParams(lmsType.lmsOIDAlgo, &lmsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) *pSize = (Ipp32s)sizeof(IppsLMSPublicKeyState) + (Ipp32s)lmsParams.m; /* T1 */ return ippcpSts; } /*F* // Name: ippsLMSSetPublicKeyState // // Purpose: Set LMS public key. // // Returns: Reason: // ippStsNullPtrErr pI == NULL // pK == NULL // pState == NULL // ippStsBadArgErr lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8 // lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1 // lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25 // lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5 // ippStsNoErr no errors // // Parameters: // lmsType structure with LMS parameters lmotsOIDAlgo and lmsOIDAlgo // pI pointer to the LMS private key identifier // pK pointer to the LMS public key // pState pointer to the LMS public key state // *F*/ IPPFUN(IppStatus, ippsLMSSetPublicKeyState, (const IppsLMSAlgoType lmsType, const Ipp8u* pI, const Ipp8u* pK, IppsLMSPublicKeyState* pState)) { IppStatus ippcpSts = ippStsNoErr; IPP_BAD_PTR3_RET(pI, pK, pState); IPP_BADARG_RET(lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5, ippStsBadArgErr); /* Set context id to prevent its copying */ CP_LMS_SET_CTX_ID(pState); /* Set LMS parameters */ cpLMSParams lmsParams; ippcpSts = setLMSParams(lmsType.lmsOIDAlgo, &lmsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) /* Fill in the structure */ pState->lmsOIDAlgo = lmsType.lmsOIDAlgo; pState->lmotsOIDAlgo = lmsType.lmotsOIDAlgo; CopyBlock(pI, pState->I, CP_PK_I_BYTESIZE); // Set pointer to T1 right to the end of the context pState->T1 = (Ipp8u*)pState+sizeof(IppsLMSPublicKeyState); CopyBlock(pK, pState->T1, (cpSize)lmsParams.m); return ippcpSts; } /*F* // Name: ippsLMSSetSignatureState // // Purpose: Set LMS signature. // // Returns: Reason: // ippStsNullPtrErr pC == NULL // pY == NULL // pAuthPath == NULL // pState == NULL // ippStsBadArgErr lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8 // lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1 // lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25 // lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5 // q is incorrect // ippStsNoErr no errors // // Parameters: // lmsType structure with LMS parameters lmotsOIDAlgo and lmsOIDAlgo // q index of LMS leaf // pC pointer to the C LM-OTS value // pY pointer to the y LM-OTS value // pAuthPath pointer to the LMS authorization path // pState pointer to the LMS signature state // *F*/ IPPFUN(IppStatus, ippsLMSSetSignatureState, (const IppsLMSAlgoType lmsType, Ipp32u q, const Ipp8u* pC, const Ipp8u* pY, const Ipp8u* pAuthPath, IppsLMSSignatureState* pState)) { IPP_BAD_PTR4_RET(pC, pY, pAuthPath, pState); IPP_BADARG_RET(lmsType.lmotsOIDAlgo > LMOTS_SHA256_N24_W8, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmotsOIDAlgo < LMOTS_SHA256_N32_W1, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo > LMS_SHA256_M24_H25, ippStsBadArgErr); IPP_BADARG_RET(lmsType.lmsOIDAlgo < LMS_SHA256_M32_H5, ippStsBadArgErr); IppStatus ippcpSts = ippStsNoErr; /* Set LMOTS and LMS parameters */ cpLMOTSParams lmotsParams; ippcpSts = setLMOTSParams(lmsType.lmotsOIDAlgo, &lmotsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) cpLMSParams lmsParams; ippcpSts = setLMSParams(lmsType.lmsOIDAlgo, &lmsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) /* Set context id to prevent its copying */ CP_LMS_SET_CTX_ID(pState); /* Check q value before set */ Ipp32u qLimit = 1 << lmsParams.h; IPP_BADARG_RET(q >= qLimit, ippStsBadArgErr); pState->_q = q; pState->_lmsOIDAlgo = lmsType.lmsOIDAlgo; _cpLMOTSSignatureState* locLMOTSSig = &(pState->_lmotsSig); locLMOTSSig->_lmotsOIDAlgo = lmsType.lmotsOIDAlgo; // Copy auth path data Ipp32s authPathSize = (Ipp32s)(lmsParams.h * lmotsParams.n); pState->_pAuthPath = (Ipp8u*)pState+sizeof(IppsLMSSignatureState); CopyBlock(pAuthPath, pState->_pAuthPath, authPathSize); // Copy C data Ipp32s cSize = (Ipp32s)lmotsParams.n; locLMOTSSig->pC = (Ipp8u*)pState->_pAuthPath+authPathSize; CopyBlock(pC, locLMOTSSig->pC, cSize); // Copy Y data Ipp32s ySize = (Ipp32s)(lmotsParams.n * lmotsParams.p); locLMOTSSig->pY = (Ipp8u*)pState->_pAuthPath+authPathSize+cSize; CopyBlock(pY, locLMOTSSig->pY, ySize); return ippcpSts; } cryptography-primitives-1.0.0/sources/ippcp/lms/lms_verify.c000066400000000000000000000237321470420105600243560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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 "lms_internal/lms.h" /*F* // Name: ippsLMSVerify // // Purpose: LMS signature verification. // // Returns: Reason: // ippStsNullPtrErr pMsg == NULL // pSign == NULL // pIsSignValid == NULL // pKey == NULL // pBuffer == NULL // ippStsBadArgErr wrong LMS or LMOTS parameters // inside pSign and pKey // OR q is incorrect // ippStsContextMatchErr pSign or pKey contexts are invalid // ippStsLengthErr msgLen < 1 // ippStsNoErr no errors // // Parameters: // pMsg pointer to the message data buffer // msgLen message buffer length, bytes // pSign pointer to the LMS signature state // pIsSignValid 1 if signature is valid, 0 - vice versa // pKey pointer to the LMS public key state // pBuffer pointer to the temporary memory // *F*/ IPPFUN(IppStatus, ippsLMSVerify, (const Ipp8u* pMsg, const Ipp32s msgLen, const IppsLMSSignatureState* pSign, int* pIsSignValid, const IppsLMSPublicKeyState* pKey, Ipp8u* pBuffer)) { IppStatus ippcpSts = ippStsNoErr; /* Check if any of input pointers are NULL */ IPP_BAD_PTR4_RET(pMsg, pSign, pIsSignValid, pKey) /* Check if temporary buffer is NULL */ IPP_BAD_PTR1_RET(pBuffer) /* Check msg length */ IPP_BADARG_RET(msgLen < 1, ippStsLengthErr) IPP_BADARG_RET( !CP_LMS_VALID_CTX_ID(pSign), ippStsContextMatchErr ); IPP_BADARG_RET( !CP_LMS_VALID_CTX_ID(pKey), ippStsContextMatchErr ); *pIsSignValid = 0; /* Parse public key(Pk) */ /* --------------------------------------------- */ IppsLMSAlgo lmsTypePk = pKey->lmsOIDAlgo; IppsLMOTSAlgo lmotsTypePk = pKey->lmotsOIDAlgo; // Set LMOTS and LMS parameters cpLMOTSParams lmotsParams; cpLMSParams lmsParams; ippcpSts = setLMOTSParams(lmotsTypePk, &lmotsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) ippcpSts = setLMSParams(lmsTypePk, &lmsParams); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) Ipp32u nParam = lmotsParams.n; Ipp32u wParam = lmotsParams.w; Ipp32u pParam = lmotsParams.p; Ipp32u hParam = lmsParams.h; Ipp32u mParam = lmsParams.m; /* Parse signature */ /* ---------------------------------------------------- */ Ipp32u q = pSign->_q; _cpLMOTSSignatureState lmotsSig = pSign->_lmotsSig; IppsLMOTSAlgo lmotsTypeSig = lmotsSig._lmotsOIDAlgo; IppsLMSAlgo lmsTypeSig = pSign->_lmsOIDAlgo; Ipp8u* pAuthPath = pSign->_pAuthPath; // Check the validity of the parsed signature parameters Ipp32u qLimit = 1 << hParam; if((lmsTypePk != lmsTypeSig) || (lmotsTypePk != lmotsTypeSig) || (q >= qLimit)) { return ippStsBadArgErr; } /* Compute LMS pub key candidate (Algorithms 6a and 4b) */ /* ---------------------------------------------------- */ Ipp8u* tmpQBuf = pBuffer; Ipp32u total_size = 0; // Buffer's invariant for alg correctness - first 16 bytes is always pubKey->I CopyBlock(pKey->I, tmpQBuf, CP_PK_I_BYTESIZE); total_size+=CP_PK_I_BYTESIZE; toByte(tmpQBuf+total_size, /*q byteLen*/ 4, q); total_size += /*q byteLen*/ 4; toByte(tmpQBuf+total_size, /*D_MESG byteLen*/ 2, D_MESG); total_size += /*D_MESG byteLen*/ 2; CopyBlock(lmotsSig.pC, tmpQBuf+total_size, (cpSize)nParam); total_size += nParam; CopyBlock(pMsg, tmpQBuf+total_size, msgLen); total_size += (Ipp32u)msgLen; // Q = H(I || u32str(q) || u16str(D_MESG) || C || message) Ipp8u Q_CksmQ[CP_LMS_MAX_HASH_BYTESIZE+CP_CKSM_BYTESIZE]; ippcpSts = ippsHashMessage_rmf(tmpQBuf, (int)total_size, Q_CksmQ, lmsParams.hash_method); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) /* Calculate checksum Cksm(Q) and append it to Q */ Ipp32u cksmQ = cpCksm(Q_CksmQ, lmotsParams); toByte(Q_CksmQ+nParam, /*cksmQ byteLen*/2, cksmQ); Ipp8u z[CP_SIG_MAX_Y_WORDSIZE+1][CP_LMS_MAX_HASH_BYTESIZE]; Ipp8u* pZ = z[0]; for(Ipp32u i = 0; i < pParam; i++) { // a = coef(Q || Cksm(Q), i, w) Ipp32u a = cpCoef(Q_CksmQ, i, wParam); //tmp = y[i] Ipp8u tmp[CP_LMS_MAX_HASH_BYTESIZE]; CopyBlock(lmotsSig.pY + i*nParam, tmp, (cpSize)nParam); // I || u32str(q) Ipp8u* tmpBuff = pBuffer; // I || u32str(q) || u16str(i) toByte(tmpBuff+CP_PK_I_BYTESIZE+/*q byteLen*/4,/*i byteLen*/2,i); for(Ipp32u j = a; j < (Ipp32u)((1 << wParam) - 1); j++) { // I || u32str(q) || u16str(i) || u8str(j) toByte(tmpBuff+CP_PK_I_BYTESIZE+/*q byteLen*/4+/*i byteLen*/2,/*j byteLen*/1,j); // I || u32str(q) || u16str(i) || u8str(j) || tmp CopyBlock(tmp, tmpBuff+CP_PK_I_BYTESIZE+/*q byteLen*/4+/*i byteLen*/2+/*j byteLen*/1, (cpSize)nParam); // tmp = H(I || u32str(q) || u16str(i) || u8str(j) || tmp) ippcpSts = ippsHashMessage_rmf(tmpBuff, (int)(CP_PK_I_BYTESIZE+/*q byteLen*/4+/*i byteLen*/2+/*j byteLen*/1+nParam), tmp, lmsParams.hash_method); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) } CopyBlock(tmp, pZ+(i+1)*nParam, (cpSize)nParam); } // I u32str(q) u16str(D_PBLC) Ipp32s zStartOffset = (Ipp32s)(nParam - (CP_PK_I_BYTESIZE + 4 + 2 )); // I u16str(D_PBLC) CopyBlock(tmpQBuf, pZ + zStartOffset, CP_PK_I_BYTESIZE + 4 ); // Conduct operation u16str(D_PBLC) toByte(pZ + nParam - /*D_PBLC byteLen*/2, /*D_PBLC byteLen*/2, D_PBLC); // tmp = Kc = H(I || u32str(q) || u16str(D_PBLC) || z[0] || z[1] || ... || z[p-1]) Ipp8u Kc[CP_LMS_MAX_HASH_BYTESIZE]; ippcpSts = ippsHashMessage_rmf(pZ+zStartOffset, (int)(pParam*nParam+CP_PK_I_BYTESIZE+/*q byteLen*/4+/*D_PBLC byteLen*/2), Kc, lmsParams.hash_method); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) /* Compute the candidate LMS root value Tc */ /* --------------------------------------------- */ Ipp32u node_num = (1 << hParam) + q; Ipp8u* tmpBuffKc = pBuffer; // I || u32str(node_num) toByte(tmpBuffKc+CP_PK_I_BYTESIZE, /*node_num byteLen*/4, node_num); // I || u32str(node_num) || u16str(D_LEAF) toByte(tmpBuffKc+CP_PK_I_BYTESIZE+/*node_num byteLen*/4, /*D_LEAF byteLen*/2, D_LEAF); // I || u32str(node_num) || u16str(D_LEAF) || Kc CopyBlock(Kc, tmpBuffKc+CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_LEAF byteLen*/2, (cpSize)mParam); Ipp8u tmp[CP_LMS_MAX_HASH_BYTESIZE]; ippcpSts = ippsHashMessage_rmf(tmpBuffKc, (int)(CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_LEAF byteLen*/2+mParam), tmp, lmsParams.hash_method); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) Ipp32u i = 0; Ipp8u* locTmp = pBuffer; // I || u32str(node_num/2) || u16str(D_INTR) toByte(locTmp+CP_PK_I_BYTESIZE+/*node_num byteLen*/4, /*D_INTR byteLen*/2, D_INTR); while (node_num > 1) { // I || u32str(node_num/2) toByte(locTmp+CP_PK_I_BYTESIZE, /*node_num byteLen*/4, node_num/2); if((node_num & 1) == 1) { // I || u32str(node_num/2) || u16str(D_INTR) || path[i] CopyBlock(pAuthPath+i*mParam, locTmp+CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_INTR byteLen*/2, (cpSize)mParam); // I || u32str(node_num/2) || u16str(D_INTR) || path[i] || tmp CopyBlock(tmp, locTmp+CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_INTR byteLen*/2+mParam, (cpSize)mParam); } else { // I || u32str(node_num/2) || u16str(D_INTR) || tmp CopyBlock(tmp, locTmp+CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_INTR byteLen*/2, (cpSize)mParam); // I || u32str(node_num/2) || u16str(D_INTR) || tmp || path[i] CopyBlock(pAuthPath+i*mParam, locTmp+CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_INTR byteLen*/2+mParam, (cpSize)mParam); } ippcpSts = ippsHashMessage_rmf(locTmp, (int)(CP_PK_I_BYTESIZE+/*node_num byteLen*/4+/*D_INTR byteLen*/2+2*mParam), tmp, lmotsParams.hash_method); IPP_BADARG_RET((ippStsNoErr != ippcpSts), ippcpSts) node_num = node_num >> 1; i++; } /* Verify with given public key */ /* --------------------------------------------- */ BNU_CHUNK_T is_equal = cpIsEquBlock_ct(pKey->T1, tmp, (int)mParam); if(is_equal) { *pIsSignValid = 1; } return ippcpSts; } cryptography-primitives-1.0.0/sources/ippcp/owncp.h000066400000000000000000000146001470420105600225310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library */ #ifndef __OWNCP_H__ #define __OWNCP_H__ #ifndef __OWNDEFS_H__ #include "owndefs.h" #endif #ifndef IPPCP_H__ #if defined _MERGED_BLD #include "ippcp_cpuspc.h" #endif #include "ippcp.h" #endif /* // modes of the CPU feature */ #define _FEATURE_OFF_ (0) /* feature is OFF */ #define _FEATURE_ON_ (1) /* feature is ON */ #define _FEATURE_TICKTOCK_ (2) /* detect if feature is OFF/ON */ #include "pcpvariant.h" #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) // for MSVC #pragma warning(disable : 4324) // structures padding warning #endif /* ippCP length */ typedef int cpSize; /* // Common ippCP Macros */ /* size of cache line (bytes) */ #if (_IPP==_IPP_M5) #define CACHE_LINE_SIZE (16) #define LOG_CACHE_LINE_SIZE (4) #else #define CACHE_LINE_SIZE (64) #define LOG_CACHE_LINE_SIZE (6) #endif /* swap data & pointers */ #define SWAP_PTR(ATYPE, pX,pY) { ATYPE* aPtr=(pX); (pX)=(pY); (pY)=aPtr; } #define SWAP(x,y) {(x)^=(y); (y)^=(x); (x)^=(y);} /* alignment value */ #define ALIGN_VAL ((int)sizeof(void*)) /* bitsize */ #define BYTESIZE (8) #define BITSIZE(x) ((int)(sizeof(x)*BYTESIZE)) /* bit length -> byte/word length conversion */ #define BITS2WORD8_SIZE(x) (((x)+ 7)>>3) #define BITS2WORD16_SIZE(x) (((x)+15)>>4) #define BITS2WORD32_SIZE(x) (((x)+31)>>5) #define BITS2WORD64_SIZE(x) (((x)+63)>>6) /* WORD and DWORD manipulators */ #define IPP_LODWORD(x) ((Ipp32u)(x)) #define IPP_HIDWORD(x) ((Ipp32u)(((Ipp64u)(x) >>32) & 0xFFFFFFFF)) #define IPP_MAKEHWORD(bLo,bHi) ((Ipp16u)(((Ipp8u)(bLo)) | ((Ipp16u)((Ipp8u)(bHi))) << 8)) #define IPP_MAKEWORD(hLo,hHi) ((Ipp32u)(((Ipp16u)(hLo)) | ((Ipp32u)((Ipp16u)(hHi))) << 16)) #define IPP_MAKEDWORD(wLo,wHi) ((Ipp64u)(((Ipp32u)(wLo)) | ((Ipp64u)((Ipp32u)(wHi))) << 32)) /* extract byte */ #define EBYTE(w,n) ((Ipp8u)((w) >> (8 * (n)))) /* hexString <-> Ipp32u conversion */ #define HSTRING_TO_U32(ptrByte) \ (Ipp32u)(((ptrByte)[0]) <<24) \ +(Ipp32u)(((ptrByte)[1]) <<16) \ +(Ipp32u)(((ptrByte)[2]) <<8) \ +(Ipp32u)((ptrByte)[3]) #define U32_TO_HSTRING(ptrByte, x) \ (ptrByte)[0] = (Ipp8u)((x)>>24); \ (ptrByte)[1] = (Ipp8u)((x)>>16); \ (ptrByte)[2] = (Ipp8u)((x)>>8); \ (ptrByte)[3] = (Ipp8u)(x) /* 32- and 64-bit masks for MSB of nbits-sequence */ #define MAKEMASK32(nbits) (0xFFFFFFFF >>((32 - ((nbits)&0x1F)) &0x1F)) #define MAKEMASK64(nbits) (0xFFFFFFFFFFFFFFFF >>((64 - ((nbits)&0x3F)) &0x3F)) /* Logical Shifts (right and left) of WORD */ #define LSR32(x,nBits) ((x)>>(nBits)) #define LSL32(x,nBits) ((x)<<(nBits)) /* Rotate (right and left) of WORD */ #if defined(_MSC_VER) && !defined( __ICL ) # include # define ROR32(x, nBits) _lrotr((x),(nBits)) # define ROL32(x, nBits) _lrotl((x),(nBits)) #else # define ROR32(x, nBits) (LSR32((x),(nBits)) | LSL32((x),32-(nBits))) # define ROL32(x, nBits) ROR32((x),(32-(nBits))) #endif /* Logical Shifts (right and left) of DWORD */ #define LSR64(x,nBits) ((x)>>(nBits)) #define LSL64(x,nBits) ((x)<<(nBits)) /* Rotate (right and left) of DWORD */ #define ROR64(x, nBits) (LSR64((x),(nBits)) | LSL64((x),64-(nBits))) #define ROL64(x, nBits) ROR64((x),(64-(nBits))) /* change endian */ #if defined(_MSC_VER) # define ENDIANNESS(x) _byteswap_ulong((x)) # define ENDIANNESS32(x) ENDIANNESS((x)) # define ENDIANNESS64(x) _byteswap_uint64((x)) #elif defined(__ICL) # define ENDIANNESS(x) _bswap((x)) # define ENDIANNESS32(x) ENDIANNESS((x)) # define ENDIANNESS64(x) _bswap64((x)) #else # define ENDIANNESS(x) ((ROR32((x), 24) & 0x00ff00ff) | (ROR32((x), 8) & 0xff00ff00)) # define ENDIANNESS32(x) ENDIANNESS((x)) # define ENDIANNESS64(x) IPP_MAKEDWORD(ENDIANNESS(IPP_HIDWORD((x))), ENDIANNESS(IPP_LODWORD((x)))) #endif #define IPP_MAKE_MULTIPLE_OF_8(x) ((x) = ((x)+7)&(~7)) #define IPP_MAKE_MULTIPLE_OF_16(x) ((x) = ((x)+15)&(~15)) /* define 64-bit constant */ #if !defined(__GNUC__) #define CONST_64(x) (x) /*(x##i64)*/ #else #define CONST_64(x) (x##LL) #endif /* define 64-bit constant or pair of 32-bit depending on architecture */ #if ((_IPP_ARCH == _IPP_ARCH_EM64T) || (_IPP_ARCH == _IPP_ARCH_LP64) || (_IPP_ARCH == _IPP_ARCH_LRB) || (_IPP_ARCH == _IPP_ARCH_LRB2)) #define LL(lo,hi) (((Ipp64u)(lo)) | ((Ipp64u)(hi) << 32)) #define L_(lo) ((Ipp64u)(lo)) #else #define LL(lo,hi) (lo),(hi) #define L_(lo) (lo) #endif /* test if library's feature is ON */ int cpGetFeature( Ipp64u Feature ); /* test CPU cryptography features */ __IPPCP_INLINE Ipp32u IsFeatureEnabled(Ipp64u niMmask) { return (Ipp32u)cpGetFeature(niMmask); } #define IPPCP_GET_NUM_THREADS() ( ippcpGetEnabledNumThreads() ) #define IPPCP_OMP_NUM_THREADS() num_threads( IPPCP_GET_NUM_THREADS() ) #define IPPCP_OMP_LIMIT_MAX_NUM_THREADS(n) num_threads( IPP_MIN(IPPCP_GET_NUM_THREADS(),(n))) /* copy under mask */ #define MASKED_COPY_BNU(dst, mask, src1, src2, len) { \ cpSize i; \ for(i=0; i<(len); i++) (dst)[i] = ((mask) & (src1)[i]) | (~(mask) & (src2)[i]); \ } #if (_IPP > _IPP_PX || _IPP32E > _IPP32E_PX) && !defined(__INTEL_COMPILER) && !defined(__INTEL_LLVM_COMPILER) #if !defined( _M_X64 ) && defined ( _MSC_VER ) __inline __m128i _mm_cvtsi64_si128(__int64 a) { __m128i x; x.m128i_i64[0] = a; x.m128i_i64[1] = 0; return x; } #endif #if !defined( __x86_64__ ) && defined(__GNUC__) && (!defined(__clang__) || (__clang_major__ < 16)) extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_cvtsi64_si128 (long long __A) { return _mm_set_epi64x (0, __A); } #endif #endif /* (_IPP > _IPP_PX || _IPP32E > _IPP32E_PX) && !defined(__INTEL_COMPILER) */ #endif /* __OWNCP_H__ */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_128keyexpansion_ni.c000066400000000000000000000066161470420105600263770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. AES keys expansion // // Contents: // aes128_KeyExpansion_NI() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) /* // AES-128 key expansion */ static __m128i aes128_assist(__m128i temp1, __m128i temp2) { __m128i temp3; temp2 = _mm_shuffle_epi32 (temp2 ,0xff); temp3 = _mm_slli_si128 (temp1, 0x4); temp1 = _mm_xor_si128 (temp1, temp3); temp3 = _mm_slli_si128 (temp3, 0x4); temp1 = _mm_xor_si128 (temp1, temp3); temp3 = _mm_slli_si128 (temp3, 0x4); temp1 = _mm_xor_si128 (temp1, temp3); temp1 = _mm_xor_si128 (temp1, temp2); return temp1; } #define aes128_KeyExpansion_NI OWNAPI(aes128_KeyExpansion_NI) IPP_OWN_DECL (void, aes128_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) IPP_OWN_DEFN (void, aes128_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) { __m128i *pKeySchedule = (__m128i*)keyExp; __m128i temp[2]; /* temp[0] = temp1 temp[1] = temp2 */ temp[0] = _mm_loadu_si128((__m128i*)userkey); pKeySchedule[0] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0] ,0x1); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[1] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x2); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[2] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x4); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[3] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x8); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[4] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x10); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[5] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x20); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[6] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x40); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[7] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x80); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[8] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x1b); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[9] = temp[0]; temp[1] = _mm_aeskeygenassist_si128 (temp[0],0x36); temp[0] = aes128_assist(temp[0], temp[1]); pKeySchedule[10] = temp[0]; /* clear secret data */ for(Ipp32u i = 0; i < sizeof(temp)/sizeof(temp[0]); i++){ temp[i] = _mm_xor_si128(temp[i],temp[i]); } } #endif /* #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_192keyexpansion_ni.c000066400000000000000000000076401470420105600263760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. AES keys expansion // // Contents: // aes192_KeyExpansion_NI() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_keys_ni.h" #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) ////////////////////////////////////////////////////////////////////// /* // AES-192 key expansion */ static void aes192_assist(__m128i* temp1, __m128i * temp2, __m128i * temp3) { __m128i temp4; *temp2 = _mm_shuffle_epi32 (*temp2, 0x55); temp4 = _mm_slli_si128 (*temp1, 0x4); *temp1 = _mm_xor_si128 (*temp1, temp4); temp4 = _mm_slli_si128 (temp4, 0x4); *temp1 = _mm_xor_si128 (*temp1, temp4); temp4 = _mm_slli_si128 (temp4, 0x4); *temp1 = _mm_xor_si128 (*temp1, temp4); *temp1 = _mm_xor_si128 (*temp1, *temp2); *temp2 = _mm_shuffle_epi32(*temp1, 0xff); temp4 = _mm_slli_si128 (*temp3, 0x4); *temp3 = _mm_xor_si128 (*temp3, temp4); *temp3 = _mm_xor_si128 (*temp3, *temp2); } IPP_OWN_DEFN (void, aes192_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) { __m128i *pKeySchedule = (__m128i*)keyExp; __m128i temp[3]; /* temp[0] = temp1 temp[1] = temp2 temp[2] = temp3 */ temp[0] = _mm_loadu_si128((__m128i*)userkey); temp[2] = _mm_cvtsi64_si128(((Ipp64s*)(userkey+16))[0]);//_mm_loadu_si128((__m128i*)(userkey+16)); // read 8 bytes only other are zero pKeySchedule[0]=temp[0]; pKeySchedule[1]=temp[2]; temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x1); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[1] = _mm_unpacklo_epi64 (pKeySchedule[1], temp[0]); pKeySchedule[2] = _mm_alignr_epi8 (temp[2], temp[0], 8); temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x2); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[3]=temp[0]; pKeySchedule[4]=temp[2]; temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x4); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[4] = _mm_unpacklo_epi64(pKeySchedule[4], temp[0]); pKeySchedule[5] = _mm_alignr_epi8(temp[2], temp[0], 8); temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x8); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[6]=temp[0]; pKeySchedule[7]=temp[2]; temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x10); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[7] = _mm_unpacklo_epi64(pKeySchedule[7], temp[0]); pKeySchedule[8] = _mm_alignr_epi8(temp[2], temp[0],8); temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x20); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[9]=temp[0]; pKeySchedule[10]=temp[2]; temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x40); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[10] = _mm_unpacklo_epi64(pKeySchedule[10], temp[0]); pKeySchedule[11] = _mm_alignr_epi8(temp[2], temp[0], 8); temp[1]=_mm_aeskeygenassist_si128 (temp[2],0x80); aes192_assist(&temp[0], &temp[1], &temp[2]); pKeySchedule[12]=temp[0]; /* clear secret data */ for(Ipp32u i = 0; i < sizeof(temp)/sizeof(temp[0]); i++){ temp[i] = _mm_xor_si128(temp[i],temp[i]); } } #endif /* #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_256keyexpansion_ni.c000066400000000000000000000076031470420105600263760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. AES keys expansion // // Contents: // aes256_KeyExpansion_NI() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_keys_ni.h" #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) ////////////////////////////////////////////////////////////////////// /* // AES-256 key expansion */ static void aes256_assist_1(__m128i* temp1, __m128i * temp2) { __m128i temp4; *temp2 = _mm_shuffle_epi32(*temp2, 0xff); temp4 = _mm_slli_si128 (*temp1, 0x4); *temp1 = _mm_xor_si128 (*temp1, temp4); temp4 = _mm_slli_si128 (temp4, 0x4); *temp1 = _mm_xor_si128 (*temp1, temp4); temp4 = _mm_slli_si128 (temp4, 0x4); *temp1 = _mm_xor_si128 (*temp1, temp4); *temp1 = _mm_xor_si128 (*temp1, *temp2); } static void aes256_assist_2(__m128i* temp1, __m128i * temp3) { __m128i temp2,temp4; temp4 = _mm_aeskeygenassist_si128 (*temp1, 0x0); temp2 = _mm_shuffle_epi32(temp4, 0xaa); temp4 = _mm_slli_si128 (*temp3, 0x4); *temp3 = _mm_xor_si128 (*temp3, temp4); temp4 = _mm_slli_si128 (temp4, 0x4); *temp3 = _mm_xor_si128 (*temp3, temp4); temp4 = _mm_slli_si128 (temp4, 0x4); *temp3 = _mm_xor_si128 (*temp3, temp4); *temp3 = _mm_xor_si128 (*temp3, temp2); } IPP_OWN_DEFN (void, aes256_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) { __m128i *pKeySchedule = (__m128i*)keyExp; __m128i temp[3]; /* temp[0] = temp1 temp[1] = temp2 temp[2] = temp3 */ temp[0] = _mm_loadu_si128((__m128i*)userkey); temp[2] = _mm_loadu_si128((__m128i*)(userkey+16)); pKeySchedule[0] = temp[0]; pKeySchedule[1] = temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x01); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[2]=temp[0]; aes256_assist_2(&temp[0], &temp[2]); pKeySchedule[3]=temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x02); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[4]=temp[0]; aes256_assist_2(&temp[0], &temp[2]); pKeySchedule[5]=temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x04); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[6]=temp[0]; aes256_assist_2(&temp[0], &temp[2]); pKeySchedule[7]=temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x08); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[8]=temp[0]; aes256_assist_2(&temp[0], &temp[2]); pKeySchedule[9]=temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x10); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[10]=temp[0]; aes256_assist_2(&temp[0], &temp[2]); pKeySchedule[11]=temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x20); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[12]=temp[0]; aes256_assist_2(&temp[0], &temp[2]); pKeySchedule[13]=temp[2]; temp[1] = _mm_aeskeygenassist_si128 (temp[2],0x40); aes256_assist_1(&temp[0], &temp[1]); pKeySchedule[14]=temp[0]; /* clear secret data */ for(Ipp32u i = 0; i < sizeof(temp)/sizeof(temp[0]); i++){ temp[i] = _mm_xor_si128(temp[i],temp[i]); } } #endif /* #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_avx2_vaes.h000066400000000000000000000337121470420105600246410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES GCM AVX2 // Internal Functions Implementations // */ #ifndef __AES_GCM_AVX2_H_ #define __AES_GCM_AVX2_H_ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcptool.h" #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) #ifdef __GNUC__ #define ASM(a) __asm__(a); #else #define ASM(a) #endif /* // Zeroes the memory by 32 bit parts, // because "epi32" is the minimal available granularity for avx2 store instructions. // input: // Ipp32u* out - pointer to the memory that needs to be zeroize // int len - length of the "out" array, in 32-bit chunks */ static __NOINLINE void zeroize_256(Ipp32u* out, int len) { #if defined(__GNUC__) // Avoid dead code elimination for GNU compilers ASM(""); #endif __m256i T = _mm256_setzero_si256(); int i; int tmp[8]; int rest = len % 8; if (rest == 0) for(i=0; i<8; i++) tmp[i] = (int)0xFFFFFFFF; else { for(i=0; i> 5 T2 = _mm_xor_si128(T2, *hash1); //xor shifted versions T2 = _mm_srli_epi64(T2, 1); //packed right shifting >> 1 T2 = _mm_xor_si128(T2, *hash1); //xor shifted versions T2 = _mm_srli_epi64(T2, 1); //packed right shifting >> 1 *hash1 = _mm_xor_si128(*hash1, T2); //second phase of the reduction complete } /* // avx2_clmul_gcm16 performs the hash calculation with 256-bit registers for 16 blocks // GH order - 0, 1 | 2, 3 | 4, 5 | 6, 7 | 8, 9 | 10, 11 | 12, 13 | 14, 15 // HK order - 1, 0 | 3, 2 | 5, 4 | 7, 6 | 9, 8 | 11, 10 | 13, 12 | 15, 14 // input: // const __m256i *HK - contains hashed keys // input/output: // __m256i *GH - contains GHASH. Will be overwritten in this function // output: // __m128i GH[0] */ __IPPCP_INLINE __m128i avx2_clmul_gcm16(__m256i *GH, const __m256i *HK) { __m256i tmpX0, tmpX2, tmpX3, tmpX4, tmpX5; tmpX2 = _mm256_shuffle_epi32 (GH[0], SHUFD_MASK); tmpX3 = _mm256_shuffle_epi32 (HK[7], SHUFD_MASK); tmpX2 = _mm256_xor_si256(tmpX2, GH[0]); tmpX3 = _mm256_xor_si256(tmpX3, HK[7]); tmpX0 = _mm256_clmulepi64_epi128 (GH[0], HK[7], 0x11); tmpX5 = _mm256_clmulepi64_epi128 (GH[0], HK[7], 0x00); GH[0] = _mm256_clmulepi64_epi128 (tmpX2, tmpX3, 0x00); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[1], HK[6], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[2], HK[5], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[3], HK[4], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[4], HK[3], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[5], HK[2], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[6], HK[1], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[7], HK[0], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], tmpX0); tmpX2 = _mm256_xor_si256(GH[0], tmpX5); tmpX4 = _mm256_slli_si256(tmpX2, 8); tmpX2 = _mm256_srli_si256(tmpX2, 8); tmpX5 = _mm256_xor_si256(tmpX5, tmpX4); // tmpX0 = _mm256_xor_si256(tmpX0, tmpX2); // tmpX0:tmpX5> holds the result of the accumulated carry-less multiplications __m128i T0, T1; T0 = _mm_xor_si128(_mm256_extractf128_si256(tmpX0, 0), _mm256_extractf128_si256(tmpX0, 1)); T1 = _mm_xor_si128(_mm256_extractf128_si256(tmpX5, 0), _mm256_extractf128_si256(tmpX5, 1)); // reduction phase reduction(&T0, &T1); GH[0] = _mm256_setr_m128i(_mm_xor_si128(T1, T0), _mm_setzero_si128()); //the result is in GH return _mm_xor_si128(T1, T0); } /* // avx2_clmul_gcm8 performs the hash calculation with 256-bit registers for 8 blocks // GH order - 0, 1 | 2, 3 | 4, 5 | 6, 7 // HK order - 1, 0 | 3, 2 | 5, 4 | 7, 6 // input: // const __m256i *HK - contains hashed keys // input/output: // __m256i *GH - contains GHASH. Will be overwritten in this function // output: // __m128i GH[0] */ __IPPCP_INLINE __m128i avx2_clmul_gcm8(__m256i *GH, const __m256i *HK) { __m256i tmpX0, tmpX2, tmpX3, tmpX4, tmpX5; tmpX2 = _mm256_shuffle_epi32 (GH[0], SHUFD_MASK); tmpX3 = _mm256_shuffle_epi32 (HK[3], SHUFD_MASK); tmpX2 = _mm256_xor_si256(tmpX2, GH[0]); tmpX3 = _mm256_xor_si256(tmpX3, HK[3]); tmpX0 = _mm256_clmulepi64_epi128 (GH[0], HK[3], 0x11); tmpX5 = _mm256_clmulepi64_epi128 (GH[0], HK[3], 0x00); GH[0] = _mm256_clmulepi64_epi128 (tmpX2, tmpX3, 0x00); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[1], HK[2], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[2], HK[1], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[3], HK[0], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], tmpX0); tmpX2 = _mm256_xor_si256(GH[0], tmpX5); tmpX4 = _mm256_slli_si256(tmpX2, 8); tmpX2 = _mm256_srli_si256(tmpX2, 8); tmpX5 = _mm256_xor_si256(tmpX5, tmpX4); // tmpX0 = _mm256_xor_si256(tmpX0, tmpX2); // tmpX0:tmpX5> holds the result of the accumulated carry-less multiplications __m128i T0, T1; T0 = _mm_xor_si128(_mm256_extractf128_si256(tmpX0, 0), _mm256_extractf128_si256(tmpX0, 1)); T1 = _mm_xor_si128(_mm256_extractf128_si256(tmpX5, 0), _mm256_extractf128_si256(tmpX5, 1)); // reduction phase reduction(&T0, &T1); GH[0] = _mm256_setr_m128i(_mm_xor_si128(T1, T0), _mm_setzero_si128()); //the result is in GH return _mm_xor_si128(T1, T0); } /* // avx2_clmul_gcm4 performs the hash calculation with 256-bit registers for 4 blocks // GH order - 0, 1 | 2, 3 // HK order - 1, 0 | 3, 2 // input: // const __m256i *HK - contains hashed keys // input/output: // __m256i *GH - contains GHASH. Will be overwritten in this function // output: // __m128i GH[0] */ __IPPCP_INLINE __m128i avx2_clmul_gcm4(__m256i *GH, const __m256i *HK) { __m256i tmpX0, tmpX2, tmpX3, tmpX4, tmpX5; tmpX2 = _mm256_shuffle_epi32 (GH[0], SHUFD_MASK); tmpX3 = _mm256_shuffle_epi32 (HK[1], SHUFD_MASK); tmpX2 = _mm256_xor_si256(tmpX2, GH[0]); tmpX3 = _mm256_xor_si256(tmpX3, HK[1]); tmpX0 = _mm256_clmulepi64_epi128 (GH[0], HK[1], 0x11); tmpX5 = _mm256_clmulepi64_epi128 (GH[0], HK[1], 0x00); GH[0] = _mm256_clmulepi64_epi128 (tmpX2, tmpX3, 0x00); GH[0] = _mm256_xor_si256(GH[0], avx2_internal_mul(GH[1], HK[0], &tmpX0, &tmpX5)); GH[0] = _mm256_xor_si256(GH[0], tmpX0); tmpX2 = _mm256_xor_si256(GH[0], tmpX5); tmpX4 = _mm256_slli_si256(tmpX2, 8); tmpX2 = _mm256_srli_si256(tmpX2, 8); tmpX5 = _mm256_xor_si256(tmpX5, tmpX4); // tmpX0 = _mm256_xor_si256(tmpX0, tmpX2); // tmpX0:tmpX5> holds the result of the accumulated carry-less multiplications __m128i T0, T1; T0 = _mm_xor_si128(_mm256_extractf128_si256(tmpX0, 0), _mm256_extractf128_si256(tmpX0, 1)); T1 = _mm_xor_si128(_mm256_extractf128_si256(tmpX5, 0), _mm256_extractf128_si256(tmpX5, 1)); // reduction phase reduction(&T0, &T1); GH[0] = _mm256_setr_m128i(_mm_xor_si128(T1, T0), _mm_setzero_si128()); //the result is in GH return _mm_xor_si128(T1, T0); } /* // avx2_clmul_gcm2 performs the hash calculation with 256-bit registers for 2 blocks // GH order - 0, 1 // HK order - 1, 0 // input: // const __m256i *HK - contains hashed keys // input/output: // __m256i *GH - contains GHASH. Will be overwritten in this function // output: // __m128i GH[0] */ __IPPCP_INLINE __m128i avx2_clmul_gcm2(__m256i *GH, const __m256i *HK) { __m256i tmpX0, tmpX2, tmpX3, tmpX4, tmpX5; tmpX2 = _mm256_shuffle_epi32 (GH[0], SHUFD_MASK); tmpX3 = _mm256_shuffle_epi32 (HK[0], SHUFD_MASK); tmpX2 = _mm256_xor_si256(tmpX2, GH[0]); tmpX3 = _mm256_xor_si256(tmpX3, HK[0]); tmpX0 = _mm256_clmulepi64_epi128 (GH[0], HK[0], 0x11); tmpX5 = _mm256_clmulepi64_epi128 (GH[0], HK[0], 0x00); GH[0] = _mm256_clmulepi64_epi128 (tmpX2, tmpX3, 0x00); GH[0] = _mm256_xor_si256(GH[0], tmpX0); tmpX2 = _mm256_xor_si256(GH[0], tmpX5); tmpX4 = _mm256_slli_si256(tmpX2, 8); tmpX2 = _mm256_srli_si256(tmpX2, 8); tmpX5 = _mm256_xor_si256(tmpX5, tmpX4); // tmpX0 = _mm256_xor_si256(tmpX0, tmpX2); // tmpX0:tmpX5> holds the result of the accumulated carry-less multiplications __m128i T0, T1; T0 = _mm_xor_si128(_mm256_extractf128_si256(tmpX0, 0), _mm256_extractf128_si256(tmpX0, 1)); T1 = _mm_xor_si128(_mm256_extractf128_si256(tmpX5, 0), _mm256_extractf128_si256(tmpX5, 1)); // reduction phase reduction(&T0, &T1); GH[0] = _mm256_setr_m128i(_mm_xor_si128(T1, T0), _mm_setzero_si128()); //the result is in GH return _mm_xor_si128(T1, T0); } /* // avx2_clmul_gcm performs the hash calculation with 256-bit registers for 1 blocks // GH order - 0 // HK order - 0 // input: // const __m256i *HK - contains hashed keys // input/output: // __m256i *GH - contains GHASH. Will be overwritten in this function // output: // __m128i GH[0] */ __IPPCP_INLINE __m128i avx2_clmul_gcm(__m256i *GH, const __m256i *HK) { __m256i tmpX0, tmpX2, tmpX3, tmpX4, tmpX5; tmpX2 = _mm256_shuffle_epi32 (GH[0], SHUFD_MASK); tmpX3 = _mm256_shuffle_epi32 (HK[0], SHUFD_MASK); tmpX2 = _mm256_xor_si256(tmpX2, GH[0]); tmpX3 = _mm256_xor_si256(tmpX3, HK[0]); tmpX0 = _mm256_clmulepi64_epi128 (GH[0], HK[0], 0x11); tmpX5 = _mm256_clmulepi64_epi128 (GH[0], HK[0], 0x00); GH[0] = _mm256_clmulepi64_epi128 (tmpX2, tmpX3, 0x00); GH[0] = _mm256_xor_si256(GH[0], tmpX0); tmpX2 = _mm256_xor_si256(GH[0], tmpX5); tmpX4 = _mm256_slli_si256(tmpX2, 8); tmpX2 = _mm256_srli_si256(tmpX2, 8); tmpX5 = _mm256_xor_si256(tmpX5, tmpX4); // tmpX0 = _mm256_xor_si256(tmpX0, tmpX2); // tmpX0:tmpX5> holds the result of the accumulated carry-less multiplications __m128i T0, T1; T0 = _mm256_extractf128_si256(tmpX0, 0); T1 = _mm256_extractf128_si256(tmpX5, 0); // reduction phase reduction(&T0, &T1); GH[0] = _mm256_setr_m128i(_mm_xor_si128(T1, T0), _mm_setzero_si128()); //the result is in GH return _mm_xor_si128(T1, T0); } #endif /* #if(_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) */ #endif /* __AES_GCM_AVX2_H_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_avx2_vaes_decrypt.c000066400000000000000000001044321470420105600263640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES decryption (GCM mode) // */ #include "pcpaes_avx2_vaes.h" #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) IPP_OWN_DEFN (void, AesGcmDec_vaes_avx2, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pState)) { // dispatching to older code path in case of short plain text if (len < 256) { IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); Ipp8u hkeys_old_order[48]; // put the hash keys in the correct order (hKey*t, (hKey*t)^2, (hKey*t)^4) for (int i = 0; i < 32; i++) { *(hkeys_old_order+i) = *(AESGCM_HKEY(pState)+i); // HKEY 0-32 if (i < 16) *(hkeys_old_order+i+32) = *(AESGCM_HKEY(pState)+i+48); // HKEY 32-48 } AesGcmDec_avx(pDst, pSrc, len, encoder, RIJ_NR(pAES), RIJ_EKEYS(pAES), AESGCM_GHASH(pState), AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), hkeys_old_order); // zeroizing zeroize_256((Ipp32u*)hkeys_old_order, 12); } else { IppsRijndael128Spec* pAES = AESGCM_CIPHER(pState); Ipp8u* pCounter = AESGCM_COUNTER(pState); Ipp8u* pECounter = AESGCM_ECOUNTER(pState); __m256i pCounter256, pCounter256_1, pCounter256_2, pCounter256_3, pCounter256_4, pCounter256_5, pCounter256_6, pCounter256_7; __m256i block, block1, block2, block3, block4, block5, block6, block7; __m256i cipherText, cipherText_1, cipherText_2, cipherText_3, cipherText_4, cipherText_5, cipherText_6, cipherText_7; __m256i plainText, plainText_1, plainText_2, plainText_3, plainText_4, plainText_5, plainText_6, plainText_7; __m256i rpHash[8]; __m256i HashKey[8]; __m128i resultHash = _mm_setzero_si128(); __m256i tmpKey; // setting temporary data for incremention const __m256i increment1 = _mm256_loadu_si256((void*)_increment1); // increment by 1 const __m256i increment2 = _mm256_loadu_si256((void*)_increment2); // increment by 2 const __m256i increment4 = _mm256_loadu_si256((void*)_increment4); // increment by 4 const __m256i increment8 = _mm256_loadu_si256((void*)_increment8); // increment by 8 const __m256i increment16 = _mm256_loadu_si256((void*)_increment16); // increment by 16 const __m256i shuffle_mask = _mm256_loadu_si256((void*)swapBytes256); // vector is used to zeroizing __m256i zero_256 = _mm256_setzero_si256(); // setting some masks const __m128i shuff_mask_128 = _mm_loadu_si128((void*)_shuff_mask_128); const __m256i shuff_mask_256 = _mm256_loadu_si256((void*)_shuff_mask_256); // loading counters from memory __m128i lo = _mm_loadu_si128((void*)pCounter); IncrementCounter32(pCounter); __m128i hi = _mm_loadu_si128((void*)pCounter); pCounter256_7 = _mm256_setr_m128i(lo, hi); pCounter256 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_1 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_2 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_3 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_4 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_5 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_6 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); lo = _mm_loadu_si128((__m128i*)AESGCM_GHASH(pState)); hi = _mm_setzero_si128(); rpHash[0] = _mm256_setr_m128i(_mm_shuffle_epi8(lo, shuff_mask_128), hi); // setting hash keys Ipp8u *pkeys = AESGCM_HKEY(pState); for (int i = 0; i < 8; i++) { HashKey[i] = _mm256_setr_m128i(_mm_loadu_si128((void*)(pkeys+16)), _mm_loadu_si128((void*)pkeys)); pkeys += 32; } while(len >= 16*BLOCK_SIZE) { // decrypt stage tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)))); block = _mm256_xor_si256(pCounter256, tmpKey); block1 = _mm256_xor_si256(pCounter256_1, tmpKey); block2 = _mm256_xor_si256(pCounter256_2, tmpKey); block3 = _mm256_xor_si256(pCounter256_3, tmpKey); block4 = _mm256_xor_si256(pCounter256_4, tmpKey); block5 = _mm256_xor_si256(pCounter256_5, tmpKey); block6 = _mm256_xor_si256(pCounter256_6, tmpKey); block7 = _mm256_xor_si256(pCounter256_7, tmpKey); IncrementRegister256(pCounter256, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_1, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_2, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_3, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_4, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_5, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_6, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_7, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); if (RIJ_NR(pAES) >= 12) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); if (RIJ_NR(pAES) >= 14) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); } } tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16))); block = _mm256_aesenclast_epi128(block, tmpKey); block1 = _mm256_aesenclast_epi128(block1, tmpKey); block2 = _mm256_aesenclast_epi128(block2, tmpKey); block3 = _mm256_aesenclast_epi128(block3, tmpKey); block4 = _mm256_aesenclast_epi128(block4, tmpKey); block5 = _mm256_aesenclast_epi128(block5, tmpKey); block6 = _mm256_aesenclast_epi128(block6, tmpKey); block7 = _mm256_aesenclast_epi128(block7, tmpKey); // set ciphertext plainText = _mm256_loadu_si256((void*)pSrc); cipherText = _mm256_xor_si256(plainText, block); plainText_1 = _mm256_loadu_si256((void*)(pSrc+2*BLOCK_SIZE)); cipherText_1 = _mm256_xor_si256(plainText_1, block1); plainText_2 = _mm256_loadu_si256((void*)(pSrc+4*BLOCK_SIZE)); cipherText_2 = _mm256_xor_si256(plainText_2, block2); plainText_3 = _mm256_loadu_si256((void*)(pSrc+6*BLOCK_SIZE)); cipherText_3 = _mm256_xor_si256(plainText_3, block3); plainText_4 = _mm256_loadu_si256((void*)(pSrc+8*BLOCK_SIZE)); cipherText_4 = _mm256_xor_si256(plainText_4, block4); plainText_5 = _mm256_loadu_si256((void*)(pSrc+10*BLOCK_SIZE)); cipherText_5 = _mm256_xor_si256(plainText_5, block5); plainText_6 = _mm256_loadu_si256((void*)(pSrc+12*BLOCK_SIZE)); cipherText_6 = _mm256_xor_si256(plainText_6, block6); plainText_7 = _mm256_loadu_si256((void*)(pSrc+14*BLOCK_SIZE)); cipherText_7 = _mm256_xor_si256(plainText_7, block7); pSrc += 16*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); _mm256_storeu_si256((void*)(pDst+2*BLOCK_SIZE), cipherText_1); _mm256_storeu_si256((void*)(pDst+4*BLOCK_SIZE), cipherText_2); _mm256_storeu_si256((void*)(pDst+6*BLOCK_SIZE), cipherText_3); _mm256_storeu_si256((void*)(pDst+8*BLOCK_SIZE), cipherText_4); _mm256_storeu_si256((void*)(pDst+10*BLOCK_SIZE), cipherText_5); _mm256_storeu_si256((void*)(pDst+12*BLOCK_SIZE), cipherText_6); _mm256_storeu_si256((void*)(pDst+14*BLOCK_SIZE), cipherText_7); pDst += 16*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(plainText, shuff_mask_256)); rpHash[1] = _mm256_shuffle_epi8(plainText_1, shuff_mask_256); rpHash[2] = _mm256_shuffle_epi8(plainText_2, shuff_mask_256); rpHash[3] = _mm256_shuffle_epi8(plainText_3, shuff_mask_256); rpHash[4] = _mm256_shuffle_epi8(plainText_4, shuff_mask_256); rpHash[5] = _mm256_shuffle_epi8(plainText_5, shuff_mask_256); rpHash[6] = _mm256_shuffle_epi8(plainText_6, shuff_mask_256); rpHash[7] = _mm256_shuffle_epi8(plainText_7, shuff_mask_256); resultHash = avx2_clmul_gcm16(rpHash, HashKey); len -= 16*BLOCK_SIZE; } // while(len >= 16*BLOCK_SIZE) if (len >= 8*BLOCK_SIZE) { // decrypt stage tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)))); block = _mm256_xor_si256(pCounter256, tmpKey); block1 = _mm256_xor_si256(pCounter256_1, tmpKey); block2 = _mm256_xor_si256(pCounter256_2, tmpKey); block3 = _mm256_xor_si256(pCounter256_3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256_1, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256_2, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256_3, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); if (RIJ_NR(pAES) >= 12) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); if (RIJ_NR(pAES) >= 14) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); } } tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16))); block = _mm256_aesenclast_epi128(block, tmpKey); block1 = _mm256_aesenclast_epi128(block1, tmpKey); block2 = _mm256_aesenclast_epi128(block2, tmpKey); block3 = _mm256_aesenclast_epi128(block3, tmpKey); // set ciphertext plainText = _mm256_loadu_si256((void*)pSrc); cipherText = _mm256_xor_si256(plainText, block); plainText_1 = _mm256_loadu_si256((void*)(pSrc+2*BLOCK_SIZE)); cipherText_1 = _mm256_xor_si256(plainText_1, block1); plainText_2 = _mm256_loadu_si256((void*)(pSrc+4*BLOCK_SIZE)); cipherText_2 = _mm256_xor_si256(plainText_2, block2); plainText_3 = _mm256_loadu_si256((void*)(pSrc+6*BLOCK_SIZE)); cipherText_3 = _mm256_xor_si256(plainText_3, block3); pSrc += 8*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); _mm256_storeu_si256((void*)(pDst+2*BLOCK_SIZE), cipherText_1); _mm256_storeu_si256((void*)(pDst+4*BLOCK_SIZE), cipherText_2); _mm256_storeu_si256((void*)(pDst+6*BLOCK_SIZE), cipherText_3); pDst += 8*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(plainText, shuff_mask_256)); rpHash[1] = _mm256_shuffle_epi8(plainText_1, shuff_mask_256); rpHash[2] = _mm256_shuffle_epi8(plainText_2, shuff_mask_256); rpHash[3] = _mm256_shuffle_epi8(plainText_3, shuff_mask_256); resultHash = avx2_clmul_gcm8(rpHash, HashKey); len -= 8*BLOCK_SIZE; } //if (len >= 8*BLOCK_SIZE) if (len >= 4*BLOCK_SIZE) { // decrypt stage tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)))); block = _mm256_xor_si256(pCounter256, tmpKey); block1 = _mm256_xor_si256(pCounter256_1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); IncrementRegister256(pCounter256, increment4, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); IncrementRegister256(pCounter256_1, increment4, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); if (RIJ_NR(pAES) >= 12) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); if (RIJ_NR(pAES) >= 14) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); } } tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16))); block = _mm256_aesenclast_epi128(block, tmpKey); block1 = _mm256_aesenclast_epi128(block1, tmpKey); // set ciphertext plainText = _mm256_loadu_si256((void*)pSrc); cipherText = _mm256_xor_si256(plainText, block); plainText_1 = _mm256_loadu_si256((void*)(pSrc+2*BLOCK_SIZE)); cipherText_1 = _mm256_xor_si256(plainText_1, block1); pSrc += 4*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); _mm256_storeu_si256((void*)(pDst+2*BLOCK_SIZE), cipherText_1); pDst += 4*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(plainText, shuff_mask_256)); rpHash[1] = _mm256_shuffle_epi8(plainText_1, shuff_mask_256); resultHash = avx2_clmul_gcm4(rpHash, HashKey); len -= 4*BLOCK_SIZE; } //if (len >= 4*BLOCK_SIZE) if (len >= 2*BLOCK_SIZE) { block = _mm256_xor_si256(pCounter256, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES))))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16)))); IncrementRegister256(pCounter256, increment2, shuffle_mask); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16)))); if (RIJ_NR(pAES) >= 12) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16)))); if (RIJ_NR(pAES) >= 14) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16)))); } } block = _mm256_aesenclast_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16)))); // set ciphertext plainText = _mm256_loadu_si256((void*)pSrc); cipherText = _mm256_xor_si256(plainText, block); pSrc += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); pDst += 2*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(plainText, shuff_mask_256)); resultHash = avx2_clmul_gcm2(rpHash, HashKey); len -= 2*BLOCK_SIZE; } // encryption for the tail (1-3 block) while (len >= BLOCK_SIZE) { block = _mm256_xor_si256(pCounter256, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES))))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16)))); IncrementRegister256(pCounter256, increment1, shuffle_mask); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16)))); if (RIJ_NR(pAES) >= 12) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16)))); if (RIJ_NR(pAES) >= 14) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16)))); } } block = _mm256_aesenclast_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16)))); // set ciphertext plainText = _mm256_loadu_si256((void*)pSrc); cipherText = _mm256_xor_si256(plainText, block); pSrc += BLOCK_SIZE; _mm_storeu_si128((void*)pDst, _mm256_castsi256_si128(cipherText)); pDst += BLOCK_SIZE; // hash calculation stage HashKey[0] = _mm256_setr_m128i(_mm_loadu_si128((void*)(AESGCM_HKEY(pState))), _mm_loadu_si128((void*)(AESGCM_HKEY(pState)))); rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(plainText, shuff_mask_256)); resultHash = avx2_clmul_gcm(rpHash, HashKey); len -= BLOCK_SIZE; } //decrypt the remainder block = _mm256_xor_si256(pCounter256, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES))))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16)))); if (RIJ_NR(pAES) >= 12) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16)))); if (RIJ_NR(pAES) >= 14) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16)))); } } block = _mm256_aesenclast_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16)))); // loand data to the memory _mm_storeu_si128((void*)pECounter, _mm256_castsi256_si128(block)); _mm_storeu_si128((void*)pCounter, _mm256_castsi256_si128(pCounter256)); resultHash = _mm_shuffle_epi8(resultHash, shuff_mask_128); _mm_storeu_si128((void*)(AESGCM_GHASH(pState)), resultHash); // HKeys zeroizing for (int i = 0; i < 8; i++) _mm256_storeu_si256((HashKey+i), zero_256); tmpKey = _mm256_setzero_si256(); } // if (len < 256) } #endif /* #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_avx2_vaes_encrypt.c000066400000000000000000001034311470420105600263740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption (GCM mode) // */ #include "pcpaes_avx2_vaes.h" #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) IPP_OWN_DEFN (void, AesGcmEnc_vaes_avx2, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pState)) { // dispatching to older code path in case of short plain text if (len < 256) { IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); Ipp8u hkeys_old_order[48]; // put the hash keys in the correct order (hKey*t, (hKey*t)^2, (hKey*t)^4) for (int i = 0; i < 32; i++) { *(hkeys_old_order+i) = *(AESGCM_HKEY(pState)+i); // HKEY 0-32 if (i < 16) *(hkeys_old_order+i+32) = *(AESGCM_HKEY(pState)+i+48); // HKEY 32-48 } AesGcmEnc_avx(pDst, pSrc, len, encoder, RIJ_NR(pAES), RIJ_EKEYS(pAES), AESGCM_GHASH(pState), AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), hkeys_old_order); // zeroizing zeroize_256((Ipp32u*)hkeys_old_order, 12); } else { IppsRijndael128Spec* pAES = AESGCM_CIPHER(pState); Ipp8u* pCounter = AESGCM_COUNTER(pState); Ipp8u* pECounter = AESGCM_ECOUNTER(pState); __m256i pCounter256, pCounter256_1, pCounter256_2, pCounter256_3, pCounter256_4, pCounter256_5, pCounter256_6, pCounter256_7; __m256i block, block1, block2, block3, block4, block5, block6, block7; __m256i cipherText, cipherText_1, cipherText_2, cipherText_3, cipherText_4, cipherText_5, cipherText_6, cipherText_7; __m256i rpHash[8]; __m256i HashKey[8]; __m128i resultHash = _mm_setzero_si128(); __m256i tmpKey; // setting temporary data for incremention const __m256i increment1 = _mm256_loadu_si256((void*)_increment1); // increment by 1 const __m256i increment2 = _mm256_loadu_si256((void*)_increment2); // increment by 2 const __m256i increment4 = _mm256_loadu_si256((void*)_increment4); // increment by 4 const __m256i increment8 = _mm256_loadu_si256((void*)_increment8); // increment by 8 const __m256i increment16 = _mm256_loadu_si256((void*)_increment16); // increment by 16 const __m256i shuffle_mask = _mm256_loadu_si256((void*)swapBytes256); // vector is used to zeroizing __m256i zero_256 = _mm256_setzero_si256(); // setting some masks const __m128i shuff_mask_128 = _mm_loadu_si128((void*)_shuff_mask_128); const __m256i shuff_mask_256 = _mm256_loadu_si256((void*)_shuff_mask_256); // loading counters from memory __m128i lo = _mm_loadu_si128((void*)pCounter); IncrementCounter32(pCounter); __m128i hi = _mm_loadu_si128((void*)pCounter); pCounter256_7 = _mm256_setr_m128i(lo, hi); pCounter256 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_1 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_2 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_3 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_4 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_5 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); pCounter256_6 = pCounter256_7; IncrementRegister256(pCounter256_7, increment2, shuffle_mask); lo = _mm_loadu_si128((__m128i*)AESGCM_GHASH(pState)); hi = _mm_setzero_si128(); rpHash[0] = _mm256_setr_m128i(_mm_shuffle_epi8(lo, shuff_mask_128), hi); // setting hash keys Ipp8u *pkeys = AESGCM_HKEY(pState); for (int i = 0; i < 8; i++) { HashKey[i] = _mm256_setr_m128i(_mm_loadu_si128((void*)(pkeys+16)), _mm_loadu_si128((void*)pkeys)); pkeys += 32; } while(len >= 16*BLOCK_SIZE) { // encrypt stage tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)))); block = _mm256_xor_si256(pCounter256, tmpKey); block1 = _mm256_xor_si256(pCounter256_1, tmpKey); block2 = _mm256_xor_si256(pCounter256_2, tmpKey); block3 = _mm256_xor_si256(pCounter256_3, tmpKey); block4 = _mm256_xor_si256(pCounter256_4, tmpKey); block5 = _mm256_xor_si256(pCounter256_5, tmpKey); block6 = _mm256_xor_si256(pCounter256_6, tmpKey); block7 = _mm256_xor_si256(pCounter256_7, tmpKey); IncrementRegister256(pCounter256, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_1, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_2, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_3, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_4, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_5, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_6, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); IncrementRegister256(pCounter256_7, increment16, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); if (RIJ_NR(pAES) >= 12) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); if (RIJ_NR(pAES) >= 14) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); block4 = _mm256_aesenc_epi128(block4, tmpKey); block5 = _mm256_aesenc_epi128(block5, tmpKey); block6 = _mm256_aesenc_epi128(block6, tmpKey); block7 = _mm256_aesenc_epi128(block7, tmpKey); } } tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16))); block = _mm256_aesenclast_epi128(block, tmpKey); block1 = _mm256_aesenclast_epi128(block1, tmpKey); block2 = _mm256_aesenclast_epi128(block2, tmpKey); block3 = _mm256_aesenclast_epi128(block3, tmpKey); block4 = _mm256_aesenclast_epi128(block4, tmpKey); block5 = _mm256_aesenclast_epi128(block5, tmpKey); block6 = _mm256_aesenclast_epi128(block6, tmpKey); block7 = _mm256_aesenclast_epi128(block7, tmpKey); // set ciphertext cipherText = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block); cipherText_1 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+2*BLOCK_SIZE)), block1); cipherText_2 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+4*BLOCK_SIZE)), block2); cipherText_3 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+6*BLOCK_SIZE)), block3); cipherText_4 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+8*BLOCK_SIZE)), block4); cipherText_5 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+10*BLOCK_SIZE)), block5); cipherText_6 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+12*BLOCK_SIZE)), block6); cipherText_7 = _mm256_xor_si256( _mm256_loadu_si256((void*)(pSrc+14*BLOCK_SIZE)), block7); pSrc += 16*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); _mm256_storeu_si256((void*)(pDst+2*BLOCK_SIZE), cipherText_1); _mm256_storeu_si256((void*)(pDst+4*BLOCK_SIZE), cipherText_2); _mm256_storeu_si256((void*)(pDst+6*BLOCK_SIZE), cipherText_3); _mm256_storeu_si256((void*)(pDst+8*BLOCK_SIZE), cipherText_4); _mm256_storeu_si256((void*)(pDst+10*BLOCK_SIZE), cipherText_5); _mm256_storeu_si256((void*)(pDst+12*BLOCK_SIZE), cipherText_6); _mm256_storeu_si256((void*)(pDst+14*BLOCK_SIZE), cipherText_7); pDst += 16*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(cipherText, shuff_mask_256)); rpHash[1] = _mm256_shuffle_epi8(cipherText_1, shuff_mask_256); rpHash[2] = _mm256_shuffle_epi8(cipherText_2, shuff_mask_256); rpHash[3] = _mm256_shuffle_epi8(cipherText_3, shuff_mask_256); rpHash[4] = _mm256_shuffle_epi8(cipherText_4, shuff_mask_256); rpHash[5] = _mm256_shuffle_epi8(cipherText_5, shuff_mask_256); rpHash[6] = _mm256_shuffle_epi8(cipherText_6, shuff_mask_256); rpHash[7] = _mm256_shuffle_epi8(cipherText_7, shuff_mask_256); resultHash = avx2_clmul_gcm16(rpHash, HashKey); len -= 16*BLOCK_SIZE; } // while(len >= 16*BLOCK_SIZE) if (len >= 8*BLOCK_SIZE) { // encrypt stage tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)))); block = _mm256_xor_si256(pCounter256, tmpKey); block1 = _mm256_xor_si256(pCounter256_1, tmpKey); block2 = _mm256_xor_si256(pCounter256_2, tmpKey); block3 = _mm256_xor_si256(pCounter256_3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256_1, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256_2, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); IncrementRegister256(pCounter256_3, increment8, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); if (RIJ_NR(pAES) >= 12) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); if (RIJ_NR(pAES) >= 14) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); block2 = _mm256_aesenc_epi128(block2, tmpKey); block3 = _mm256_aesenc_epi128(block3, tmpKey); } } tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16))); block = _mm256_aesenclast_epi128(block, tmpKey); block1 = _mm256_aesenclast_epi128(block1, tmpKey); block2 = _mm256_aesenclast_epi128(block2, tmpKey); block3 = _mm256_aesenclast_epi128(block3, tmpKey); // set ciphertext cipherText = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block); pSrc += 2*BLOCK_SIZE; cipherText_1 = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block1); pSrc += 2*BLOCK_SIZE; cipherText_2 = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block2); pSrc += 2*BLOCK_SIZE; cipherText_3 = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block3); pSrc += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); pDst += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText_1); pDst += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText_2); pDst += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText_3); pDst += 2*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(cipherText, shuff_mask_256)); rpHash[1] = _mm256_shuffle_epi8(cipherText_1, shuff_mask_256); rpHash[2] = _mm256_shuffle_epi8(cipherText_2, shuff_mask_256); rpHash[3] = _mm256_shuffle_epi8(cipherText_3, shuff_mask_256); resultHash = avx2_clmul_gcm8(rpHash, HashKey); len -= 8*BLOCK_SIZE; } //if (len >= 8*BLOCK_SIZE) if (len >= 4*BLOCK_SIZE) { // encrypt stage tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)))); block = _mm256_xor_si256(pCounter256, tmpKey); block1 = _mm256_xor_si256(pCounter256_1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); IncrementRegister256(pCounter256, increment4, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); IncrementRegister256(pCounter256_1, increment4, shuffle_mask); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); if (RIJ_NR(pAES) >= 12) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); if (RIJ_NR(pAES) >= 14) { tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16))); block = _mm256_aesenc_epi128(block, tmpKey); block1 = _mm256_aesenc_epi128(block1, tmpKey); } } tmpKey = _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16))); block = _mm256_aesenclast_epi128(block, tmpKey); block1 = _mm256_aesenclast_epi128(block1, tmpKey); // set ciphertext cipherText = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block); pSrc += 2*BLOCK_SIZE; cipherText_1 = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block1); pSrc += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); pDst += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText_1); pDst += 2*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(cipherText, shuff_mask_256)); rpHash[1] = _mm256_shuffle_epi8(cipherText_1, shuff_mask_256); resultHash = avx2_clmul_gcm4(rpHash, HashKey); len -= 4*BLOCK_SIZE; } //if (len >= 4*BLOCK_SIZE) if (len >= 2*BLOCK_SIZE) { block = _mm256_xor_si256(pCounter256, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES))))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16)))); IncrementRegister256(pCounter256, increment2, shuffle_mask); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16)))); if (RIJ_NR(pAES) >= 12) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16)))); if (RIJ_NR(pAES) >= 14) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16)))); } } block = _mm256_aesenclast_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16)))); // set ciphertext cipherText = _mm256_xor_si256( _mm256_loadu_si256((void*)pSrc), block); pSrc += 2*BLOCK_SIZE; _mm256_storeu_si256((void*)pDst, cipherText); pDst += 2*BLOCK_SIZE; // hash calculation stage rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(cipherText, shuff_mask_256)); resultHash = avx2_clmul_gcm2(rpHash, HashKey); len -= 2*BLOCK_SIZE; } // encryption for the tail (1-3 block) while (len >= BLOCK_SIZE) { block = _mm256_xor_si256(pCounter256, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES))))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16)))); IncrementRegister256(pCounter256, increment1, shuffle_mask); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16)))); if (RIJ_NR(pAES) >= 12) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16)))); if (RIJ_NR(pAES) >= 14) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16)))); } } block = _mm256_aesenclast_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16)))); // set ciphertext cipherText = _mm256_xor_si256(_mm256_loadu_si256((void*)pSrc), block); pSrc += BLOCK_SIZE; _mm_storeu_si128((void*)pDst, _mm256_castsi256_si128(cipherText)); pDst += BLOCK_SIZE; // hash calculation stage HashKey[0] = _mm256_setr_m128i(_mm_loadu_si128((void*)(AESGCM_HKEY(pState))), _mm_loadu_si128((void*)(AESGCM_HKEY(pState)))); rpHash[0] = _mm256_xor_si256(rpHash[0], _mm256_shuffle_epi8(cipherText, shuff_mask_256)); resultHash = avx2_clmul_gcm(rpHash, HashKey); len -= BLOCK_SIZE; } //encrypt the remainder block = _mm256_xor_si256(pCounter256, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES))))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+1*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+2*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+3*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+4*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+5*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+6*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+7*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+8*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+9*16)))); if (RIJ_NR(pAES) >= 12) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+10*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+11*16)))); if (RIJ_NR(pAES) >= 14) { block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+12*16)))); block = _mm256_aesenc_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+13*16)))); } } block = _mm256_aesenclast_epi128(block, _mm256_broadcastsi128_si256(_mm_loadu_si128((void*)(RIJ_EKEYS(pAES)+RIJ_NR(pAES)*16)))); // loand data to the memory _mm_storeu_si128((void*)pECounter, _mm256_castsi256_si128(block)); _mm_storeu_si128((void*)pCounter, _mm256_castsi256_si128(pCounter256)); resultHash = _mm_shuffle_epi8(resultHash, shuff_mask_128); _mm_storeu_si128((void*)(AESGCM_GHASH(pState)), resultHash); // HKeys zeroizing for (int i = 0; i < 8; i++) _mm256_storeu_si256((HashKey+i), zero_256); tmpKey = _mm256_setzero_si256(); } // if (len < 256) } #endif /* #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbc_decrypt.c000066400000000000000000000077371470420105600252270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES decryption (CBC mode) // AES decryption (CBC-CS mode) // // Contents: // cpDecryptAES_cbc() // */ #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_cbc_decrypt.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /* // AES-CBC decryption // // Parameters: // pIV pointer to the initialization vector // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // nBlocks number of decrypted data blocks // pCtx pointer to the AES context */ IPP_OWN_DEFN (void, cpDecryptAES_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, const IppsAESSpec* pCtx)) { #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { DecryptCBC_RIJ128pipe_VAES_NI(pSrc, pDst, nBlocks*MBS_RIJ128, pCtx, pIV); } else #endif #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use pipelined version is possible */ if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { DecryptCBC_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), nBlocks*MBS_RIJ128, pIV); } else #endif { /* setup decoder method */ RijnCipher decoder = RIJ_DECODER(pCtx); Ipp32u iv[NB(128)]; /* copy IV */ CopyBlock16(pIV, iv); /* not inplace block-by-block decryption */ if(pSrc != pDst) { while(nBlocks) { //decoder((const Ipp32u*)pSrc, (Ipp32u*)pDst, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), (const Ipp32u (*)[256])RIJ_DEC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) decoder(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijDecSbox/*NULL*/); #else decoder(pSrc, pDst, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), NULL); #endif ((Ipp32u*)pDst)[0] ^= iv[0]; ((Ipp32u*)pDst)[1] ^= iv[1]; ((Ipp32u*)pDst)[2] ^= iv[2]; ((Ipp32u*)pDst)[3] ^= iv[3]; iv[0] = ((Ipp32u*)pSrc)[0]; iv[1] = ((Ipp32u*)pSrc)[1]; iv[2] = ((Ipp32u*)pSrc)[2]; iv[3] = ((Ipp32u*)pSrc)[3]; pSrc += MBS_RIJ128; pDst += MBS_RIJ128; nBlocks--; } } /* inplace block-by-block decryption */ else { Ipp32u tmpOut[NB(128)]; while(nBlocks) { //decoder(pSrc, tmpOut, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), (const Ipp32u (*)[256])RIJ_DEC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) decoder(pSrc, (Ipp8u*)tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijDecSbox/*NULL*/); #else decoder(pSrc, (Ipp8u*)tmpOut, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), NULL); #endif tmpOut[0] ^= iv[0]; tmpOut[1] ^= iv[1]; tmpOut[2] ^= iv[2]; tmpOut[3] ^= iv[3]; iv[0] = ((Ipp32u*)pSrc)[0]; iv[1] = ((Ipp32u*)pSrc)[1]; iv[2] = ((Ipp32u*)pSrc)[2]; iv[3] = ((Ipp32u*)pSrc)[3]; CopyBlock16(tmpOut, pDst); pSrc += MBS_RIJ128; pDst += MBS_RIJ128; nBlocks--; } /* clear secret data */ PurgeBlock(tmpOut, sizeof(tmpOut)); } } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbc_decrypt.h000066400000000000000000000023621470420105600252210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES decryption (CBC mode) // AES decryption (CBC-CS mode) // // Contents: // cpDecryptAES_cbc() // */ #include "owndefs.h" #include "owncp.h" #if !defined(_PCP_AES_CBC_DECRYPT_H_) #define _PCP_AES_CBC_DECRYPT_H_ #define cpDecryptAES_cbc OWNAPI(cpDecryptAES_cbc) IPP_OWN_DECL (void, cpDecryptAES_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, const IppsAESSpec* pCtx)) #endif /* #if !defined(_PCP_AES_CBC_DECRYPT_H_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbc_encrypt.c000066400000000000000000000052341470420105600252270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption (CBC mode) // AES encryption (CBC-CS mode) // // Contents: // cpEncryptAES_cbc() // */ #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_cbc_encrypt.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /* // AES-CBC ecnryption // // Parameters: // pIV pointer to the initialization vector // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // nBlocks number of ecnrypted data blocks // pCtx pointer to the AES context */ IPP_OWN_DEFN (void, cpEncryptAES_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, const IppsAESSpec* pCtx)) { #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { EncryptCBC_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), nBlocks*MBS_RIJ128, pIV); } else #endif { /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pCtx); /* read IV */ Ipp32u iv[NB(128)]; CopyBlock16(pIV, iv); /* block-by-block encryption */ while(nBlocks) { iv[0] ^= ((Ipp32u*)pSrc)[0]; iv[1] ^= ((Ipp32u*)pSrc)[1]; iv[2] ^= ((Ipp32u*)pSrc)[2]; iv[3] ^= ((Ipp32u*)pSrc)[3]; //encoder(iv, (Ipp32u*)pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)iv, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)iv, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif iv[0] = ((Ipp32u*)pDst)[0]; iv[1] = ((Ipp32u*)pDst)[1]; iv[2] = ((Ipp32u*)pDst)[2]; iv[3] = ((Ipp32u*)pDst)[3]; pSrc += MBS_RIJ128; pDst += MBS_RIJ128; nBlocks--; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbc_encrypt.h000066400000000000000000000023621470420105600252330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption (CBC mode) // AES encryption (CBC-CS mode) // // Contents: // cpEncryptAES_cbc() // */ #include "owndefs.h" #include "owncp.h" #if !defined(_PCP_AES_CBC_ENCRYPT_H_) #define _PCP_AES_CBC_ENCRYPT_H_ #define cpEncryptAES_cbc OWNAPI(cpEncryptAES_cbc) IPP_OWN_DECL (void, cpEncryptAES_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, const IppsAESSpec* pCtx)) #endif /* #if !defined(_PCP_AES_CBC_ENCRYPT_H_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbc_vaes512.c000066400000000000000000000125071470420105600247320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CBC mode) // // Contents: // DecryptCBC_RIJ128pipe_VAES_NI() // // */ #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_decrypt_vaes512.h" #if(_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // zmmintrin.h bug: truncation of constant value #endif //////////////////////////////////////////////////////////////////////////////// IPP_OWN_DEFN (void, DecryptCBC_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, // pointer to the ciphertext Ipp8u* pDst, // pointer to the plaintext int len, // message length const IppsAESSpec* pCtx, // pointer to context const Ipp8u* pIV)) // pointer to the Initialization Vector { int cipherRounds = RIJ_NR(pCtx) - 1; __m128i* pRkey = (__m128i*)RIJ_DKEYS(pCtx) + cipherRounds + 1; __m512i* pSrc512 = (__m512i*)pSrc; __m512i* pDst512 = (__m512i*)pDst; __m512i* pIV512 = (__m512i*)pIV; // load IV __m512i IV = _mm512_maskz_expandloadu_epi64(0xC0, pIV512); int blocks; // 4 blocks of 128-bit can be loaded into one zmm register // assuming that vaesdec latency is 4, we need 4 zmm registers to make effective pipeline for (blocks = len / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i blk3 = _mm512_loadu_si512(pSrc512 + 3); // prepare blocks for the last xor __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); __m512i z1 = _mm512_alignr_epi64(blk1, blk0, 6); __m512i z2 = _mm512_alignr_epi64(blk2, blk1, 6); __m512i z3 = _mm512_alignr_epi64(blk3, blk2, 6); // update IV IV = blk3; cpAESDecrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); // the last xor blk0 = _mm512_xor_si512(blk0, z0); blk1 = _mm512_xor_si512(blk1, z1); blk2 = _mm512_xor_si512(blk2, z2); blk3 = _mm512_xor_si512(blk3, z3); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); _mm512_storeu_si512(pDst512 + 3, blk3); pSrc512 += 4; pDst512 += 4; } if ((3 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); __m512i z1 = _mm512_alignr_epi64(blk1, blk0, 6); __m512i z2 = _mm512_alignr_epi64(blk2, blk1, 6); // update IV IV = blk2; cpAESDecrypt3_VAES_NI(&blk0, &blk1, &blk2, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); blk1 = _mm512_xor_si512(blk1, z1); blk2 = _mm512_xor_si512(blk2, z2); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); pSrc512 += 3; pDst512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); __m512i z1 = _mm512_alignr_epi64(blk1, blk0, 6); // update IV IV = blk1; cpAESDecrypt2_VAES_NI(&blk0, &blk1, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); blk1 = _mm512_xor_si512(blk1, z1); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); pSrc512 += 2; pDst512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); // update IV IV = blk0; cpAESDecrypt1_VAES_NI(&blk0, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); _mm512_storeu_si512(pDst512, blk0); pSrc512 += 1; pDst512 += 1; } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); __m512i blk0 = _mm512_maskz_loadu_epi64(k, pSrc512); __m512i z0 = _mm512_maskz_alignr_epi64(k, blk0, IV, 6); cpAESDecrypt1_VAES_NI(&blk0, pRkey, cipherRounds); blk0 = _mm512_maskz_xor_epi64(k, blk0, z0); _mm512_mask_storeu_epi64(pDst512, k, blk0); } } #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbcdecrypt.c000066400000000000000000000050141470420105600250520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CBC mode) // AES encryption/decryption (CBC-CS mode) // // Contents: // ippsAESDecryptCBC() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_cbc_decrypt.h" /*F* // Name: ippsAESDecryptCBC // // Purpose: AES-CBC decryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsUnderRunErr 0!=(dataLen%MBS_RIJ128) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector // *F*/ IPPFUN(IppStatus, ippsAESDecryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test stream integrity */ IPP_BADARG_RET((len&(MBS_RIJ128-1)), ippStsUnderRunErr); /* do encryption */ { int nBlocks = len / MBS_RIJ128; cpDecryptAES_cbc(pIV, pSrc, pDst, nBlocks, pCtx); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cbcdecrypt_cs1.c000066400000000000000000000101271470420105600256210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CBC mode) // AES encryption/decryption (CBC-CS mode) // // Contents: // ippsAESDecryptCBC_CS1() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_cbc_decrypt.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAESDecryptCBC_CS1 // // Purpose: AES-CBC_CS1 decryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len AESCCM_MSGLEN(pState), ippStsLengthErr); /* // enctypt payload and update MAC */ if(len) { /* setup encoder method */ IppsAESSpec* pAES = AESCCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); Ipp32u flag = (Ipp32u)( AESCCM_LENPRO(pState) &(MBS_RIJ128-1) ); Ipp32u qLen; Ipp32u counterVal; Ipp32u MAC[NB(128)]; Ipp32u CTR[NB(128)]; Ipp32u S[NB(128)]; /* extract from the state */ CopyBlock16(AESCCM_MAC(pState), MAC); CopyBlock16(AESCCM_CTR0(pState), CTR); CopyBlock16(AESCCM_Si(pState), S); counterVal = AESCCM_COUNTER(pState); /* extract qLen */ qLen = (((Ipp8u*)CTR)[0] &0x7) +1; /* &0x7 just to fix KW issue */ if(flag) { Ipp32u tmpLen = (Ipp32u)( IPP_MIN(len, MBS_RIJ128-1) ); XorBlock(pSrc, (Ipp8u*)S+flag, pDst, (Ipp32s)tmpLen); /* copy as much input as possible into the internal buffer*/ CopyBlock(pDst, AESCCM_BLK(pState)+flag, (Ipp32s)tmpLen); /* update MAC */ if(flag+tmpLen == MBS_RIJ128) { XorBlock16(MAC, AESCCM_BLK(pState), MAC); //encoder(MAC, MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } AESCCM_LENPRO(pState) += tmpLen; pSrc += tmpLen; pDst += tmpLen; len -= tmpLen; } #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pAES)) { Ipp32u processedLen = (Ipp32u)(len & -MBS_RIJ128); if(processedLen) { /* local state: MAC, counter block, counter bits mask */ __ALIGN16 Ipp8u localState[3*MBS_RIJ128]; /* format counter block and fill local state */ Ipp32u n; for(n=0; n= MBS_RIJ128) { Ipp32u counterEnc[2]; /* increment counter and format counter block */ counterVal++; CopyBlock(CounterEnc(counterEnc, (Ipp32s)qLen, counterVal), ((Ipp8u*)CTR)+MBS_RIJ128-qLen, (Ipp32s)qLen); /* encode counter block */ //encoder(CTR, S, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* store cipher text */ XorBlock16(pSrc, S, pDst); /* update MAC */ XorBlock16(MAC, pDst, MAC); //encoder(MAC, MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif AESCCM_LENPRO(pState) += MBS_RIJ128; pSrc += MBS_RIJ128; pDst += MBS_RIJ128; len -= MBS_RIJ128; } if(len) { Ipp32u counterEnc[2]; /* increment counter and format counter block */ counterVal++; CopyBlock(CounterEnc(counterEnc, (Ipp32s)qLen, counterVal), ((Ipp8u*)CTR)+MBS_RIJ128-qLen, (Ipp32s)qLen); /* encode counter block */ //encoder(CTR, S, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* store cipher text */ XorBlock(pSrc, S, pDst, len); /* workaround to avoid false positive stringop-overflow error on gcc10.1 and gcc11.1 */ len = ( IPP_MIN(len, MBS_RIJ128-1) ); /* store partial data block */ CopyBlock(pDst, AESCCM_BLK(pState), len); AESCCM_LENPRO(pState) += (Ipp64u)len; } /* update state */ CopyBlock16(MAC, AESCCM_MAC(pState)); CopyBlock16(S, AESCCM_Si(pState)); AESCCM_COUNTER(pState) = counterVal; /* clear secret data */ PurgeBlock(S, sizeof(S)); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ccmencrypt.c000066400000000000000000000160441470420105600251040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsAES_CCMEncrypt() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthccm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAES_CCMEncrypt // // Purpose: Encrypts data and updates authentication tag. // // Returns: Reason: // ippStsNullPtrErr pState== NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr !VALID_AESCCM_ID() // ippStsLengthErr if exceed overall length of message is being processed // ippStsNoErr no errors // // Parameters: // pSrc pointer to the plane text buffer // pDst pointer to the cipher text buffer // len length of the buffer // pState pointer to the CCM context // *F*/ IPPFUN(IppStatus, ippsAES_CCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_CCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(!VALID_AESCCM_ID(pState), ippStsContextMatchErr); /* test source/destination data */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test message length */ IPP_BADARG_RET(len<0 || AESCCM_LENPRO(pState)+(Ipp64u)len >AESCCM_MSGLEN(pState), ippStsLengthErr); /* // enctypt payload and update MAC */ if(len) { /* setup encoder method */ IppsAESSpec* pAES = AESCCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); Ipp32u flag = (Ipp32u)( AESCCM_LENPRO(pState) &(MBS_RIJ128-1) ); Ipp32u qLen; Ipp32u counterVal; Ipp32u MAC[NB(128)]; Ipp32u CTR[NB(128)]; Ipp32u S[NB(128)]; /* extract from the state */ CopyBlock16(AESCCM_MAC(pState), MAC); CopyBlock16(AESCCM_CTR0(pState), CTR); CopyBlock16(AESCCM_Si(pState), S); counterVal = AESCCM_COUNTER(pState); /* extract qLen */ qLen = (((Ipp8u*)CTR)[0] &0x7) +1; /* &0x7 just to fix KW issue */ if(flag) { Ipp32u tmpLen = (Ipp32u)IPP_MIN(len, MBS_RIJ128-1); /* copy as much input as possible into the internal buffer*/ CopyBlock(pSrc, AESCCM_BLK(pState)+flag, (Ipp32s)tmpLen); XorBlock(pSrc, (Ipp8u*)S+flag, pDst, (Ipp32s)tmpLen); /* update MAC */ if(flag+(Ipp32u)tmpLen == MBS_RIJ128) { XorBlock16(MAC, AESCCM_BLK(pState), MAC); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } AESCCM_LENPRO(pState) += (Ipp32u)tmpLen; pSrc += tmpLen; pDst += tmpLen; len -= tmpLen; } #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pAES)) { Ipp32u processedLen = (Ipp32u)(len & -MBS_RIJ128); if(processedLen) { /* local state: MAC, counter block, counter bits mask */ __ALIGN16 Ipp8u localState[3*MBS_RIJ128]; /* format counter block and fill local state: */ Ipp32u n; for(n=0; n= MBS_RIJ128) { Ipp32u counterEnc[2]; /* update MAC */ XorBlock16(MAC, pSrc, MAC); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* increment counter and format counter block */ counterVal++; CopyBlock(CounterEnc(counterEnc, (Ipp32s)qLen, counterVal), ((Ipp8u*)CTR)+MBS_RIJ128-qLen, (Ipp32s)qLen); /* encode counter block */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* store cipher text */ XorBlock16(pSrc, S, pDst); AESCCM_LENPRO(pState) += MBS_RIJ128; pSrc += MBS_RIJ128; pDst += MBS_RIJ128; len -= MBS_RIJ128; } if(len) { Ipp32u counterEnc[2]; /* workaround to avoid false positive stringop-overflow error on gcc10.1 and gcc11.1 */ len = ( IPP_MIN(len, MBS_RIJ128-1) ); /* store partial data block */ CopyBlock(pSrc, AESCCM_BLK(pState), len); /* increment counter and format counter block */ counterVal++; CopyBlock(CounterEnc(counterEnc, (Ipp32s)qLen, counterVal), ((Ipp8u*)CTR)+MBS_RIJ128-qLen, (Ipp32s)qLen); /* encode counter block */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)CTR, (Ipp8u*)S, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* store cipher text */ XorBlock(pSrc, S, pDst, len); AESCCM_LENPRO(pState) += (Ipp64u)len; } /* update state */ CopyBlock16(MAC, AESCCM_MAC(pState)); CopyBlock16(S, AESCCM_Si(pState)); AESCCM_COUNTER(pState) = counterVal; /* clear secret data */ PurgeBlock(S, sizeof(S)); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ccmgetsize.c000066400000000000000000000027331470420105600250720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsAES_CCMGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthccm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAES_CCMGetSize // // Purpose: Returns size of AES-CCM state (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to the size of CCM (in bytes) // *F*/ IPPFUN(IppStatus, ippsAES_CCMGetSize,(int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = cpSizeofCtx_AESCCM(); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ccmgettag.c000066400000000000000000000055201470420105600246700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsAES_CCMGetTag() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthccm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAES_CCMGetTag // // Purpose: Compute message auth tag and return one. // Note, that further encryption/decryption and auth tag update is possible // // Returns: Reason: // ippStsNullPtrErr pTag == NULL // pState == NULL // ippStsContextMatchErr !VALID_AESCCM_ID() // ippStsLengthErr MBS_RIJ128 < tagLen // 1 > tagLen // ippStsNoErr no errors // // Parameters: // pTag pointer to the output authenticated tag // tagLen requested length of the tag // pState pointer to the CCM context // *F*/ IPPFUN(IppStatus, ippsAES_CCMGetTag,(Ipp8u* pTag, int tagLen, const IppsAES_CCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* test state ID */ IPP_BADARG_RET(!VALID_AESCCM_ID(pState), ippStsContextMatchErr); /* test tag (pointer and length) */ IPP_BAD_PTR1_RET(pTag); IPP_BADARG_RET((Ipp32u)tagLen>AESCCM_TAGLEN(pState) || tagLen<1, ippStsLengthErr); { Ipp32u flag = (Ipp32u)( AESCCM_LENPRO(pState) &(MBS_RIJ128-1) ); Ipp32u MAC[NB(128)]; CopyBlock16(AESCCM_MAC(pState), MAC); if(flag) { IppsAESSpec* pAES = AESCCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); Ipp8u BLK[MBS_RIJ128]; FillBlock16(0, NULL,BLK, 0); CopyBlock(AESCCM_BLK(pState), BLK, (cpSize)flag); XorBlock16(MAC, BLK, MAC); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } XorBlock(MAC, AESCCM_S0(pState), pTag, (cpSize)tagLen); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ccminit.c000066400000000000000000000043371470420105600243650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsAES_CCMInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthccm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAES_CCMInit // // Purpose: Init AES-CCM state. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsMemAllocErr size of buffer is not match for operation // ippStsLengthErr keyLen != 16 && // != 24 && // != 32 // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length of secret key (in bytes) // pState pointer to initialized as CCM context // ctxSize available size (in bytes) of buffer above // *F*/ IPPFUN(IppStatus, ippsAES_CCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_CCMState* pState, int ctxSize)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* test available size of context buffer */ IPP_BADARG_RET(ctxSize13), ippStsLengthErr); /* test AAD pointer if defined */ IPP_BADARG_RET(adLen<0, ippStsLengthErr); if(adLen) IPP_BAD_PTR1_RET(pAD); /* init for new message */ AESCCM_LENPRO(pState) = 0; AESCCM_COUNTER(pState) = 0; { /* setup encoder method */ IppsAESSpec* pAES = AESCCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); Ipp32u MAC[NB(128)]; Ipp32u CTR[NB(128)]; Ipp32u block[2*NB(128)]; /* // prepare the 1-st input block B0 and encode */ Ipp32u qLen = (Ipp32u)( (MBS_RIJ128-1) - ivLen); Ipp32u qLenEnc = qLen-1; Ipp32u tagLenEnc = (AESCCM_TAGLEN(pState)-2)>>1; Ipp64u payloadLen = AESCCM_MSGLEN(pState); ((Ipp8u*)MAC)[0] = (Ipp8u)( (Ipp32u)((adLen!=0) <<6) + (tagLenEnc<<3) + qLenEnc); /* flags */ #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) MAC[2] = ENDIANNESS(IPP_HIDWORD(payloadLen)); MAC[3] = ENDIANNESS(IPP_LODWORD(payloadLen)); #else MAC[2] = IPP_HIDWORD(payloadLen); MAC[3] = IPP_LODWORD(payloadLen); #endif CopyBlock(pIV, ((Ipp8u*)MAC)+1, ivLen); /* setup CTR0 */ FillBlock16(0, NULL,CTR, 0); ((Ipp8u*)CTR)[0] = (Ipp8u)qLenEnc; /* flags */ CopyBlock(pIV, ((Ipp8u*)CTR)+1, ivLen); CopyBlock16(CTR, AESCCM_CTR0(pState)); /* compute and store S0=ENC(CTR0) */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)CTR, AESCCM_S0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)CTR, AESCCM_S0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* init MAC value MAC = ENC(MAC) */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* // update MAC by the AD */ if(adLen) { /* encode length of associated data */ Ipp32u adLenEnc[3]; Ipp8u* adLenEncPtr; int adLenEncSize; #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) adLenEnc[1] = ENDIANNESS(IPP_HIDWORD(adLen)); adLenEnc[2] = ENDIANNESS(IPP_LODWORD(adLen)); #else adLenEnc[1] = IPP_HIDWORD(adLen); adLenEnc[2] = IPP_LODWORD(adLen); #endif if(adLen >= 0xFF00) { adLenEncSize = 6; #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) adLenEnc[1] = 0xFEFFFFFF; #else adLenEnc[1] = 0xFFFFFFFE; #endif } else { adLenEncSize= 2; } adLenEncPtr = (Ipp8u*)adLenEnc+3*sizeof(Ipp32u)-adLenEncSize; /* prepare first formatted block of Header */ CopyBlock(adLenEncPtr, block, adLenEncSize); FillBlock16(0,pAD, (Ipp8u*)block+adLenEncSize, IPP_MIN((MBS_RIJ128-adLenEncSize), adLen)); /* and update MAC */ MAC[0] ^= block[0]; MAC[1] ^= block[1]; MAC[2] ^= block[2]; MAC[3] ^= block[3]; //encoder(MAC, MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif /* update MAC the by rest of addition data */ if( (adLen+adLenEncSize) > MBS_RIJ128 ) { pAD += (MBS_RIJ128-adLenEncSize); adLen -= (MBS_RIJ128-adLenEncSize); while(adLen >= MBS_RIJ128) { CopyBlock16(pAD, block); MAC[0] ^= block[0]; MAC[1] ^= block[1]; MAC[2] ^= block[2]; MAC[3] ^= block[3]; //encoder(MAC, MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif pAD += MBS_RIJ128; adLen -= MBS_RIJ128; } if(adLen) { FillBlock16(0, pAD, block, (int)adLen); MAC[0] ^= block[0]; MAC[1] ^= block[1]; MAC[2] ^= block[2]; MAC[3] ^= block[3]; #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)MAC, (Ipp8u*)MAC, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } } } AESCCM_COUNTER(pState) = 0; CopyBlock16(MAC, AESCCM_MAC(pState)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ccmtaglen.c000066400000000000000000000036071470420105600246730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsAES_CCMTagLen() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthccm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAES_CCMTagLen // // Purpose: Setup length of the tag. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsContextMatchErr !VALID_AESCCM_ID() // ippStsLengthErr MBS_RIJ128 < tagLen || tagLen < 4 // or odd value of tagLen // ippStsNoErr no errors // // Parameters: // tagLen length in bytes of the requested tag // pState pointer to the AES-CCM state // *F*/ IPPFUN(IppStatus, ippsAES_CCMTagLen,(int tagLen, IppsAES_CCMState* pState)) { /* test context */ IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(!VALID_AESCCM_ID(pState), ippStsContextMatchErr); /* test tag length */ IPP_BADARG_RET(tagLen>MBS_RIJ128 || tagLen<4 || tagLen&1, ippStsLengthErr); /* init for new message */ AESCCM_TAGLEN(pState) = (Ipp32u)tagLen; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cfb128decrypt_vaes512.c000066400000000000000000000123361470420105600265630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CFB mode) // // Contents: // DecryptCFB128_RIJ128pipe_VAES_NI() // // */ #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #if(_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // zmmintrin.h bug: truncation of constant value #endif IPP_OWN_DEFN (void, DecryptCFB128_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, // pointer to the ciphertext Ipp8u* pDst, // pointer to the plaintext int len, // message length const IppsAESSpec* pCtx, // pointer to context const Ipp8u* pIV)) // pointer to the Initialization Vector { int cipherRounds = RIJ_NR(pCtx) - 1; __m128i* pRkey = (__m128i*)RIJ_EKEYS(pCtx); __m512i* pSrc512 = (__m512i*)pSrc; __m512i* pDst512 = (__m512i*)pDst; // load IV (128-bit) __m512i IV = _mm512_maskz_expandloadu_epi64(0xC0, pIV); // IV 0 0 0 int blocks; for (blocks = len / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { // load ciphertext __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i blk3 = _mm512_loadu_si512(pSrc512 + 3); // prepare vectors for decryption __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); // C3 C2 C1 IV __m512i z1 = _mm512_alignr_epi64(blk1, blk0, 6); // C7 C6 C5 C4 __m512i z2 = _mm512_alignr_epi64(blk2, blk1, 6); // C11 C10 C9 C8 __m512i z3 = _mm512_alignr_epi64(blk3, blk2, 6); // C15 C14 C13 C12 // update IV IV = blk3; cpAESEncrypt4_VAES_NI(&z0, &z1, &z2, &z3, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); blk1 = _mm512_xor_si512(blk1, z1); blk2 = _mm512_xor_si512(blk2, z2); blk3 = _mm512_xor_si512(blk3, z3); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); _mm512_storeu_si512(pDst512 + 3, blk3); pSrc512 += 4; pDst512 += 4; } if ((3 * 4) <= blocks) { // load ciphertext __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); __m512i z1 = _mm512_alignr_epi64(blk1, blk0, 6); __m512i z2 = _mm512_alignr_epi64(blk2, blk1, 6); // update IV IV = blk2; cpAESEncrypt3_VAES_NI(&z0, &z1, &z2, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); blk1 = _mm512_xor_si512(blk1, z1); blk2 = _mm512_xor_si512(blk2, z2); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); pSrc512 += 3; pDst512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { // load ciphertext __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); __m512i z1 = _mm512_alignr_epi64(blk1, blk0, 6); // update IV IV = blk1; cpAESEncrypt2_VAES_NI(&z0, &z1, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); blk1 = _mm512_xor_si512(blk1, z1); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); pSrc512 += 2; pDst512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { // load ciphertext __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i z0 = _mm512_alignr_epi64(blk0, IV, 6); // update IV IV = blk0; cpAESEncrypt1_VAES_NI(&z0, pRkey, cipherRounds); blk0 = _mm512_xor_si512(blk0, z0); _mm512_storeu_si512(pDst512, blk0); pSrc512 += 1; pDst512 += 1; } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); __m512i blk0 = _mm512_maskz_loadu_epi64(k, pSrc512); __m512i z0 = _mm512_maskz_alignr_epi64(k, blk0, IV, 6); cpAESEncrypt1_VAES_NI(&z0, pRkey, cipherRounds); blk0 = _mm512_maskz_xor_epi64(k, blk0, z0); _mm512_mask_storeu_epi64(pDst512, k, blk0); } } #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cfb64decrypt_vaes512.c000066400000000000000000000210451470420105600264770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CFB mode) // // Contents: // DecryptCFB64_RIJ128pipe_VAES_NI() // // */ #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #if(_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // zmmintrin.h bug: truncation of constant value #endif IPP_OWN_DEFN (void, DecryptCFB64_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, // pointer to the ciphertext Ipp8u* pDst, // pointer to the plaintext int len, // message length const IppsAESSpec* pCtx, // pointer to context const Ipp8u* pIV)) // pointer to the Initialization Vector { int cipherRounds = RIJ_NR(pCtx) - 1; __m128i* pRkey = (__m128i*)RIJ_EKEYS(pCtx); __m256i* pSrc256 = (__m256i*)pSrc; __m256i* pDst256 = (__m256i*)pDst; // load/store masks __mmask8 k8_load = 0xAA; // 1010 1010 - load to high addresses of 128-bit lanes __mmask8 k8_store = 0x55; // 0101 0101 - store low addresses of 128-bit lanes (MSB of OutputBlocks) // load IV and init IV vector in appropriate for further batch processing manner __m128i IV128 = _mm_maskz_loadu_epi64(0x03, pIV); // 64-bit values: IV_l IV_h IV_l IV_h 0 0 0 0 __m512i IV = _mm512_maskz_broadcast_i64x2(0xF0, IV128); // 64-bit values: IV_l IV_h IV_h IV_h 0 0 0 0 IV = _mm512_maskz_permutex_epi64(0xF0, IV, 0xE1); // 0xE1 = 1110 0001 int blocks = len / (MBS_RIJ128 >> 1); for (; blocks >= (4 * 4); blocks -= (4 * 4)) { // load 64-bit blocks of ciphertext to high part of 128-bit lanes __m512i blk0 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256); // C3 0 C2 0 C1 0 C0 0 __m512i blk1 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256 + 1); // C7 0 C6 0 C5 0 C4 0 __m512i blk2 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256 + 2); __m512i blk3 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256 + 3); // prepare vectors for decryption __m512i z00 = _mm512_alignr_epi64(blk0, IV, 4); // C2 0 | C1 0 | IV_l IV_h | IV_h IV_l __m512i z01 = _mm512_alignr_epi64(blk0, IV, 6); // C3 0 | C2 0 | C1 0 | IV_l IV_h z00 = _mm512_unpackhi_epi64(z00, z01); // C3 C2 | C2 C1 | C1 IV_l | IV_l IV_h __m512i z10 = _mm512_alignr_epi64(blk1, blk0, 4); __m512i z11 = _mm512_alignr_epi64(blk1, blk0, 6); z10 = _mm512_unpackhi_epi64(z10, z11); __m512i z20 = _mm512_alignr_epi64(blk2, blk1, 4); __m512i z21 = _mm512_alignr_epi64(blk2, blk1, 6); z20 = _mm512_unpackhi_epi64(z20, z21); __m512i z30 = _mm512_alignr_epi64(blk3, blk2, 4); __m512i z31 = _mm512_alignr_epi64(blk3, blk2, 6); z30 = _mm512_unpackhi_epi64(z30, z31); // update IV IV = blk3; cpAESEncrypt4_VAES_NI(&z00, &z10, &z20, &z30, pRkey, cipherRounds); // move cipher blocks to MSB part of 128-bit lanes blk0 = _mm512_bsrli_epi128(blk0, 8); blk1 = _mm512_bsrli_epi128(blk1, 8); blk2 = _mm512_bsrli_epi128(blk2, 8); blk3 = _mm512_bsrli_epi128(blk3, 8); blk0 = _mm512_xor_si512(blk0, z00); blk1 = _mm512_xor_si512(blk1, z10); blk2 = _mm512_xor_si512(blk2, z20); blk3 = _mm512_xor_si512(blk3, z30); _mm512_mask_compressstoreu_epi64(pDst256, k8_store, blk0); _mm512_mask_compressstoreu_epi64(pDst256 + 1, k8_store, blk1); _mm512_mask_compressstoreu_epi64(pDst256 + 2, k8_store, blk2); _mm512_mask_compressstoreu_epi64(pDst256 + 3, k8_store, blk3); pSrc256 += 4; pDst256 += 4; } if ((3 * 4) <= blocks) { // load 64-bit blocks of ciphertext to high part of 128-bit lanes __m512i blk0 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256); __m512i blk1 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256 + 1); __m512i blk2 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256 + 2); // prepare vectors for decryption __m512i z00 = _mm512_alignr_epi64(blk0, IV, 4); __m512i z01 = _mm512_alignr_epi64(blk0, IV, 6); z00 = _mm512_unpackhi_epi64(z00, z01); __m512i z10 = _mm512_alignr_epi64(blk1, blk0, 4); __m512i z11 = _mm512_alignr_epi64(blk1, blk0, 6); z10 = _mm512_unpackhi_epi64(z10, z11); __m512i z20 = _mm512_alignr_epi64(blk2, blk1, 4); __m512i z21 = _mm512_alignr_epi64(blk2, blk1, 6); z20 = _mm512_unpackhi_epi64(z20, z21); // update IV IV = blk2; cpAESEncrypt3_VAES_NI(&z00, &z10, &z20, pRkey, cipherRounds); // move cipher blocks to MSB part of 128-bit lanes blk0 = _mm512_bsrli_epi128(blk0, 8); blk1 = _mm512_bsrli_epi128(blk1, 8); blk2 = _mm512_bsrli_epi128(blk2, 8); blk0 = _mm512_xor_si512(blk0, z00); blk1 = _mm512_xor_si512(blk1, z10); blk2 = _mm512_xor_si512(blk2, z20); _mm512_mask_compressstoreu_epi64(pDst256, k8_store, blk0); _mm512_mask_compressstoreu_epi64(pDst256 + 1, k8_store, blk1); _mm512_mask_compressstoreu_epi64(pDst256 + 2, k8_store, blk2); pSrc256 += 3; pDst256 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { // load 64-bit blocks of ciphertext to high part of 128-bit lanes __m512i blk0 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256); __m512i blk1 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256 + 1); // prepare vectors for decryption __m512i z00 = _mm512_alignr_epi64(blk0, IV, 4); __m512i z01 = _mm512_alignr_epi64(blk0, IV, 6); z00 = _mm512_unpackhi_epi64(z00, z01); __m512i z10 = _mm512_alignr_epi64(blk1, blk0, 4); __m512i z11 = _mm512_alignr_epi64(blk1, blk0, 6); z10 = _mm512_unpackhi_epi64(z10, z11); // update IV IV = blk1; cpAESEncrypt2_VAES_NI(&z00, &z10, pRkey, cipherRounds); // move cipher blocks to MSB part of 128-bit lanes blk0 = _mm512_bsrli_epi128(blk0, 8); blk1 = _mm512_bsrli_epi128(blk1, 8); blk0 = _mm512_xor_si512(blk0, z00); blk1 = _mm512_xor_si512(blk1, z10); _mm512_mask_compressstoreu_epi64(pDst256, k8_store, blk0); _mm512_mask_compressstoreu_epi64(pDst256 + 1, k8_store, blk1); pSrc256 += 2; pDst256 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { // load 64-bit blocks of ciphertext to high part of 128-bit lanes __m512i blk0 = _mm512_maskz_expandloadu_epi64(k8_load, pSrc256); // prepare vectors for decryption __m512i z00 = _mm512_alignr_epi64(blk0, IV, 4); __m512i z01 = _mm512_alignr_epi64(blk0, IV, 6); z00 = _mm512_unpackhi_epi64(z00, z01); // update IV IV = blk0; cpAESEncrypt1_VAES_NI(&z00, pRkey, cipherRounds); // move cipher blocks to MSB part of 128-bit lanes blk0 = _mm512_bsrli_epi128(blk0, 8); blk0 = _mm512_xor_si512(blk0, z00); _mm512_mask_compressstoreu_epi64(pDst256, k8_store, blk0); pSrc256 += 1; pDst256 += 1; } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); // 64-bit chunks // load 64-bit blocks of ciphertext to hi part of 128-bit lanes __m512i blk0 = _mm512_maskz_expandloadu_epi64(k & k8_load, pSrc256); // prepare vectors for decryption __m512i z00 = _mm512_alignr_epi64(blk0, IV, 4); __m512i z01 = _mm512_alignr_epi64(blk0, IV, 6); z00 = _mm512_maskz_unpackhi_epi64(k, z00, z01); cpAESEncrypt1_VAES_NI(&z00, pRkey, cipherRounds); // move cipher blocks to MSB part of 128-bit lanes blk0 = _mm512_bsrli_epi128(blk0, 8); blk0 = _mm512_xor_epi64(blk0, z00); _mm512_mask_compressstoreu_epi64(pDst256, k & k8_store, blk0); } } #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cfb_mb_encrypt.c000066400000000000000000000207521470420105600257120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES Multi Buffer Encryption (CFB mode) // // Contents: // ippsAES_EncryptCFB16_MB() // */ #include "owncp.h" #include "pcpaesm.h" #include "aes_cfb_vaes_mb.h" #include "aes_cfb_aesni_mb.h" /*! * \brief ippsAES_EncryptCFB16_MB * * Name: ippsAES_EncryptCFB16_MB * * Purpose: AES-CFB16 Multi Buffer Encryption * * Parameters: * \param[in] pSrc Pointer to the array of source data * \param[out] pDst Pointer to the array of target data * \param[in] len Pointer to the array of input buffer lengths (in bytes) * \param[in] pCtx Pointer to the array of AES contexts * \param[in] pIV Pointer to the array of initialization vectors (IV) * \param[out] status Pointer to the IppStatus array that contains status * for each processed buffer in encryption operation * \param[in] numBuffers Number of buffers to be processed * * Returns: Reason: * \return ippStsNullPtrErr Indicates an error condition if any of the specified pointers is NULL: * NULL == pSrc * NULL == pDst * NULL == len * NULL == pCtx * NULL == pIV * NULL == status * \return ippStsContextMatchErr Indicates an error condition if input buffers have different key sizes * \return ippStsLengthErr Indicates an error condition if numBuffers < 1 * \return ippStsErr One or more of performed operation executed with error * Check status array for details * \return ippStsNoErr No error */ /* Work Load Size from Buffers */ #define WORKLOAD_LINES_16 (AES_MB_MAX_KERNEL_SIZE) /* size 16 */ #define WORKLOAD_LINES_8 (AES_MB_MAX_KERNEL_SIZE / 2) /* size 8 */ #define WORKLOAD_LINES_4 (AES_MB_MAX_KERNEL_SIZE / 4) /* size 4 */ IPPFUN(IppStatus, ippsAES_EncryptCFB16_MB, (const Ipp8u* pSrc[], Ipp8u* pDst[], int len[], const IppsAESSpec* pCtx[], const Ipp8u* pIV[], IppStatus status[], int numBuffers)) { int i; // Check input pointers IPP_BAD_PTR2_RET(pCtx, pIV); IPP_BAD_PTR4_RET(pSrc, pDst, len, status); // Check number of buffers to be processed IPP_BADARG_RET((numBuffers < 1), ippStsLengthErr); // Sequential check of all input buffers int isAllBuffersValid = 1; for (i = 0; i < numBuffers; i++) { // Test source, target buffers and initialization pointers if (pSrc[i] == NULL || pDst[i] == NULL || pIV[i] == NULL || pCtx[i] == NULL) { status[i] = ippStsNullPtrErr; isAllBuffersValid = 0; continue; } // Test the context ID if(!VALID_AES_ID(pCtx[i])) { status[i] = ippStsContextMatchErr; isAllBuffersValid = 0; continue; } // Test stream length if (len[i] < 1) { status[i] = ippStsLengthErr; isAllBuffersValid = 0; continue; } // Test stream integrity if ((len[i] % CFB16_BLOCK_SIZE)) { status[i] = ippStsUnderRunErr; isAllBuffersValid = 0; continue; } status[i] = ippStsNoErr; } // If any of the input buffer is not valid stop the processing IPP_BADARG_RET(!isAllBuffersValid, ippStsErr) // Check compatibility of the keys int referenceKeySize = RIJ_NK(pCtx[0]); for (i = 0; i < numBuffers; i++) { IPP_BADARG_RET((RIJ_NK(pCtx[i]) != referenceKeySize), ippStsContextMatchErr); } #if (_IPP32E>=_IPP32E_Y8) Ipp32u const* loc_enc_keys[AES_MB_MAX_KERNEL_SIZE]; Ipp8u const* loc_src[AES_MB_MAX_KERNEL_SIZE]; Ipp8u* loc_dst[AES_MB_MAX_KERNEL_SIZE]; Ipp8u const* loc_iv[AES_MB_MAX_KERNEL_SIZE]; int loc_len[AES_MB_MAX_KERNEL_SIZE]; int buffersProcessed = 0; int numRounds = 0; #endif #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { int workLoadSize = 0; while(numBuffers > 0) { /* init work load size */ if (numBuffers > WORKLOAD_LINES_8) { /* size 16 */ workLoadSize = WORKLOAD_LINES_16; } else if (numBuffers > WORKLOAD_LINES_4 && numBuffers <= WORKLOAD_LINES_8) { /* size 8 */ workLoadSize = WORKLOAD_LINES_8; } else if (numBuffers > 0 && numBuffers <= WORKLOAD_LINES_4) { /* size 4 */ workLoadSize = WORKLOAD_LINES_4; } else { break; } /* fill buffers */ for (i = 0; i < workLoadSize; i++) { if (i >= numBuffers) { loc_len[i] = 0; continue; } loc_src[i] = pSrc[i + buffersProcessed]; loc_dst[i] = pDst[i + buffersProcessed]; loc_iv[i] = pIV[i + buffersProcessed]; loc_enc_keys[i] = (Ipp32u*)RIJ_EKEYS(pCtx[i + buffersProcessed]); loc_len[i] = len[i + buffersProcessed]; /* As numRounds is the same for all buffers, get it from the last one */ numRounds = RIJ_NR(pCtx[i + buffersProcessed]); } /* choosing a core for filled buffers */ switch (workLoadSize) { case WORKLOAD_LINES_16: { aes_cfb16_enc_vaes_mb16(loc_src, loc_dst, loc_len, numRounds, loc_enc_keys, loc_iv); break; } case WORKLOAD_LINES_8: { aes_cfb16_enc_vaes_mb8(loc_src, loc_dst, loc_len, numRounds, loc_enc_keys, loc_iv); break; } case WORKLOAD_LINES_4: { aes_cfb16_enc_vaes_mb4(loc_src, loc_dst, loc_len, numRounds, loc_enc_keys, loc_iv); break; } default: break; } /* changing the remaining buffers for processing */ numBuffers -= workLoadSize; buffersProcessed += workLoadSize; } } #endif // if(_IPP32E>=_IPP32E_K1) #if (_IPP32E>=_IPP32E_Y8) if( IsFeatureEnabled(ippCPUID_AES) ) { while(numBuffers > 0) { for (i = 0; i < WORKLOAD_LINES_4; i++) { if (i >= numBuffers) { loc_len[i] = 0; continue; } loc_src[i] = pSrc[i + buffersProcessed]; loc_dst[i] = pDst[i + buffersProcessed]; loc_iv[i] = pIV[i + buffersProcessed]; loc_enc_keys[i] = (Ipp32u*)RIJ_EKEYS(pCtx[i + buffersProcessed]); loc_len[i] = len[i + buffersProcessed]; /* As numRounds is the same for all buffers, get it from the last one */ numRounds = RIJ_NR(pCtx[i + buffersProcessed]); } aes_cfb16_enc_aesni_mb4(loc_src, loc_dst, loc_len, numRounds, loc_enc_keys, loc_iv); numBuffers -= WORKLOAD_LINES_4; buffersProcessed += WORKLOAD_LINES_4; } } #endif // (_IPP32E>=_IPP32E_Y8) for (i = 0; i < numBuffers; i++) { status[i] = ippsAESEncryptCFB(pSrc[i], pDst[i], len[i], CFB16_BLOCK_SIZE, pCtx[i], pIV[i]); } for (i = 0; i < numBuffers; i++) { if (status[i] != ippStsNoErr) { return ippStsErr; } } return ippStsNoErr; } #undef WORKLOAD_LINES_16 #undef WORKLOAD_LINES_8 #undef WORKLOAD_LINES_4 cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cfbdecrypt.c000066400000000000000000000136421470420105600250630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CFB mode) // // Contents: // ippsAESDecryptCFB() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAESDecryptCFB // // Purpose: AES-CFB decryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsCFBSizeErr (1>cfbBlkSize || cfbBlkSize>MBS_RIJ128) // ippStsUnderRunErr 0!=(dataLen%cfbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len output buffer length (in bytes) // cfbBlkSize CFB block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector // *F*/ static void cpDecryptAES_cfb(const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, int cfbBlkSize, const IppsAESSpec* pCtx) { #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { if(cfbBlkSize==MBS_RIJ128) DecryptCFB128_RIJ128pipe_VAES_NI(pSrc, pDst, nBlocks*cfbBlkSize, pCtx, pIV); else if (8 == cfbBlkSize) DecryptCFB64_RIJ128pipe_VAES_NI(pSrc, pDst, nBlocks*cfbBlkSize, pCtx, pIV); else #if !defined (__INTEL_COMPILER) && defined (_MSC_VER) && (_MSC_VER < 1920) goto msvc_fallback; #else DecryptCFB_RIJ128pipe_VAES_NI(pSrc, pDst, nBlocks*cfbBlkSize, cfbBlkSize, pCtx, pIV); #endif } else #endif #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use pipelined version is possible */ if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { #if !defined (__INTEL_COMPILER) && defined (_MSC_VER) && (_MSC_VER < 1920) && (_IPP32E>=_IPP32E_K1) msvc_fallback: #endif if(cfbBlkSize==MBS_RIJ128) DecryptCFB128_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), nBlocks*cfbBlkSize, pIV); else if(0==(cfbBlkSize&3)) DecryptCFB32_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), nBlocks, cfbBlkSize, pIV); else DecryptCFB_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), nBlocks, cfbBlkSize, pIV); } else #endif { Ipp32u tmpInp[2*NB(128)]; Ipp32u tmpOut[ NB(128)]; /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pCtx); /* read IV */ CopyBlock16(pIV, tmpInp); /* decrypt data block-by-block of cfbLen each */ while(nBlocks) { /* decryption */ //encoder(tmpInp, tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)tmpInp, (Ipp8u*)tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)tmpInp, (Ipp8u*)tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif /* store output and put feedback into the input buffer (tmpInp) */ if( cfbBlkSize==MBS_RIJ128 && pSrc!=pDst) { ((Ipp32u*)pDst)[0] = tmpOut[0]^((Ipp32u*)pSrc)[0]; ((Ipp32u*)pDst)[1] = tmpOut[1]^((Ipp32u*)pSrc)[1]; ((Ipp32u*)pDst)[2] = tmpOut[2]^((Ipp32u*)pSrc)[2]; ((Ipp32u*)pDst)[3] = tmpOut[3]^((Ipp32u*)pSrc)[3]; tmpInp[0] = ((Ipp32u*)pSrc)[0]; tmpInp[1] = ((Ipp32u*)pSrc)[1]; tmpInp[2] = ((Ipp32u*)pSrc)[2]; tmpInp[3] = ((Ipp32u*)pSrc)[3]; } else { int n; for(n=0; ncfbBlkSize) || (MBS_RIJ128= 1920) #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #if(_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // zmmintrin.h bug: truncation of constant value #endif __IPPCP_INLINE Ipp64u broadcast_16to64(Ipp16u mask16) { Ipp64u mask64 = (Ipp64u)mask16; mask64 = (mask64 << 48) | (mask64 << 32) | (mask64 << 16) | mask64; return mask64; } __IPPCP_INLINE __m512i getInputBlocks(__m128i * const currentState, const __m512i * const pCipherBlocks, __mmask16 blocksCompressMask) { // extract 128-bit cipher blocks __m128i c0 = _mm512_extracti64x2_epi64(*pCipherBlocks, 0); __m128i c1 = _mm512_extracti64x2_epi64(*pCipherBlocks, 1); __m128i c2 = _mm512_extracti64x2_epi64(*pCipherBlocks, 2); __m128i c3 = _mm512_extracti64x2_epi64(*pCipherBlocks, 3); // InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit __m128i inpBlk0 = *currentState; // drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits __m128i inpBlk1 = _mm_mask_compress_epi8(c0, blocksCompressMask, inpBlk0); __m128i inpBlk2 = _mm_mask_compress_epi8(c1, blocksCompressMask, inpBlk1); __m128i inpBlk3 = _mm_mask_compress_epi8(c2, blocksCompressMask, inpBlk2); // next InputBlock ready *currentState = _mm_mask_compress_epi8(c3, blocksCompressMask, inpBlk3); // inserts __m512i inpBlk512 = _mm512_setzero_si512(); inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0x03, inpBlk0); // 0000 0011 inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0x0C, inpBlk1); // 0000 1100 inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0x30, inpBlk2); // 0011 0000 inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0xC0, inpBlk3); // 1100 0000 return inpBlk512; } //////////////////////////////////////////////////////////////////////////////// IPP_OWN_DEFN (void, DecryptCFB_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, // pointer to the ciphertext Ipp8u* pDst, // pointer to the plaintext int len, // message length int cfbBlkSize, // CFB block size in bytes (1 <= cfbBlkSize <= 16)); s = 8*cfbBlkSize const IppsAESSpec* pCtx, // pointer to context const Ipp8u* pIV)) // pointer to the Initialization Vector { const int cipherRounds = RIJ_NR(pCtx) - 1; __m128i* pRkey = (__m128i*)RIJ_EKEYS(pCtx); Ipp8u* pSrc8 = (Ipp8u*)pSrc; Ipp8u* pDst8 = (Ipp8u*)pDst; const int bytesPerLoad512 = 4 * cfbBlkSize; const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); // load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register __mmask64 kLsbMask64 = (__mmask64)broadcast_16to64((Ipp16u)(0xFFFF << (16-cfbBlkSize))); // same mask to load in MSB parts __mmask64 kMsbMask64 = (__mmask64)broadcast_16to64(~blocksCompressMask); // load IV __m128i IV128 = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); __m128i currentState = IV128; int blocks; for (blocks = len / cfbBlkSize; blocks >= (4 * 4); blocks -= (4 * 4)) { // load cipher blocks to LSB parts of registers __m512i ciphLsb0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8); __m512i ciphLsb1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8 + 1 * bytesPerLoad512); __m512i ciphLsb2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8 + 2 * bytesPerLoad512); __m512i ciphLsb3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8 + 3 * bytesPerLoad512); // load same cipher blocks to MSB parts of registers (shall be taken from cache) __m512i ciphMsb0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8); __m512i ciphMsb1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8 + 1 * bytesPerLoad512); __m512i ciphMsb2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8 + 2 * bytesPerLoad512); __m512i ciphMsb3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8 + 3 * bytesPerLoad512); // prepare InputBlocks for decryption __m512i inpBlk0 = getInputBlocks(¤tState, &ciphLsb0, blocksCompressMask); __m512i inpBlk1 = getInputBlocks(¤tState, &ciphLsb1, blocksCompressMask); __m512i inpBlk2 = getInputBlocks(¤tState, &ciphLsb2, blocksCompressMask); __m512i inpBlk3 = getInputBlocks(¤tState, &ciphLsb3, blocksCompressMask); cpAESEncrypt4_VAES_NI(&inpBlk0, &inpBlk1, &inpBlk2, &inpBlk3, pRkey, cipherRounds); ciphLsb0 = _mm512_xor_si512(ciphMsb0, inpBlk0); ciphLsb1 = _mm512_xor_si512(ciphMsb1, inpBlk1); ciphLsb2 = _mm512_xor_si512(ciphMsb2, inpBlk2); ciphLsb3 = _mm512_xor_si512(ciphMsb3, inpBlk3); _mm512_mask_compressstoreu_epi8(pDst8, kMsbMask64, ciphLsb0); _mm512_mask_compressstoreu_epi8(pDst8 + 1 * bytesPerLoad512, kMsbMask64, ciphLsb1); _mm512_mask_compressstoreu_epi8(pDst8 + 2 * bytesPerLoad512, kMsbMask64, ciphLsb2); _mm512_mask_compressstoreu_epi8(pDst8 + 3 * bytesPerLoad512, kMsbMask64, ciphLsb3); pSrc8 += 4 * bytesPerLoad512; pDst8 += 4 * bytesPerLoad512; } if ((3 * 4) <= blocks) { // load ciphertext __m512i ciphLsb0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8); __m512i ciphLsb1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8 + 1 * bytesPerLoad512); __m512i ciphLsb2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8 + 2 * bytesPerLoad512); __m512i ciphMsb0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8); __m512i ciphMsb1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8 + 1 * bytesPerLoad512); __m512i ciphMsb2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8 + 2 * bytesPerLoad512); // prepare InputBlocks for decryption __m512i inpBlk0 = getInputBlocks(¤tState, &ciphLsb0, blocksCompressMask); __m512i inpBlk1 = getInputBlocks(¤tState, &ciphLsb1, blocksCompressMask); __m512i inpBlk2 = getInputBlocks(¤tState, &ciphLsb2, blocksCompressMask); cpAESEncrypt3_VAES_NI(&inpBlk0, &inpBlk1, &inpBlk2, pRkey, cipherRounds); ciphLsb0 = _mm512_xor_si512(ciphMsb0, inpBlk0); ciphLsb1 = _mm512_xor_si512(ciphMsb1, inpBlk1); ciphLsb2 = _mm512_xor_si512(ciphMsb2, inpBlk2); _mm512_mask_compressstoreu_epi8(pDst8, kMsbMask64, ciphLsb0); _mm512_mask_compressstoreu_epi8(pDst8 + 1 * bytesPerLoad512, kMsbMask64, ciphLsb1); _mm512_mask_compressstoreu_epi8(pDst8 + 2 * bytesPerLoad512, kMsbMask64, ciphLsb2); pSrc8 += 3 * bytesPerLoad512; pDst8 += 3 * bytesPerLoad512; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { // load ciphertext __m512i ciphLsb0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8); __m512i ciphLsb1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8 + 1 * bytesPerLoad512); __m512i ciphMsb0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8); __m512i ciphMsb1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8 + 1 * bytesPerLoad512); // prepare InputBlocks for decryption __m512i inpBlk0 = getInputBlocks(¤tState, &ciphLsb0, blocksCompressMask); __m512i inpBlk1 = getInputBlocks(¤tState, &ciphLsb1, blocksCompressMask); cpAESEncrypt2_VAES_NI(&inpBlk0, &inpBlk1, pRkey, cipherRounds); ciphLsb0 = _mm512_xor_si512(ciphMsb0, inpBlk0); ciphLsb1 = _mm512_xor_si512(ciphMsb1, inpBlk1); _mm512_mask_compressstoreu_epi8(pDst8, kMsbMask64, ciphLsb0); _mm512_mask_compressstoreu_epi8(pDst8 + 1 * bytesPerLoad512, kMsbMask64, ciphLsb1); pSrc8 += 2 * bytesPerLoad512; pDst8 += 2 * bytesPerLoad512; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { // load ciphertext __m512i ciphLsb0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc8); __m512i ciphMsb0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc8); // prepare InputBlocks for decryption __m512i inpBlk0 = getInputBlocks(¤tState, &ciphLsb0, blocksCompressMask); cpAESEncrypt1_VAES_NI(&inpBlk0, pRkey, cipherRounds); ciphLsb0 = _mm512_xor_si512(ciphMsb0, inpBlk0); _mm512_mask_compressstoreu_epi8(pDst8, kMsbMask64, ciphLsb0); pSrc8 += bytesPerLoad512; pDst8 += bytesPerLoad512; } // at least one block left (max 3 blocks) if (blocks) { __mmask64 k64 = (1LL << (blocks << 4)) - 1; // load ciphertext __m512i ciphLsb0 = _mm512_maskz_expandloadu_epi8(k64 & kLsbMask64, pSrc8); __m512i ciphMsb0 = _mm512_maskz_expandloadu_epi8(k64 & kMsbMask64, pSrc8); // prepare InputBlocks for decryption __m512i inpBlk0 = _mm512_setzero_si512(); inpBlk0 = _mm512_mask_broadcast_i64x2(inpBlk0, 0x03, currentState); __m128i c; for (int i = 0; i < blocks; i++) { // NB: we cannot provide non-immediate parameter to extract function switch (i) { case 0: c = _mm512_extracti64x2_epi64(ciphLsb0, 0); break; case 1: c = _mm512_extracti64x2_epi64(ciphLsb0, 1); break; default: c = _mm512_extracti64x2_epi64(ciphLsb0, 2); } currentState = _mm_mask_compress_epi8(c, blocksCompressMask, currentState); inpBlk0 = _mm512_mask_broadcast_i64x2(inpBlk0, (__mmask8)(0x03 << ((i + 1) << 1)), currentState); } cpAESEncrypt1_VAES_NI(&inpBlk0, pRkey, cipherRounds); ciphLsb0 = _mm512_xor_si512(ciphMsb0, inpBlk0); _mm512_mask_compressstoreu_epi8(pDst8, k64 & kMsbMask64, ciphLsb0); } } #endif /* _IPP32E>=_IPP32E_K1 */ #else typedef int to_avoid_translation_unit_is_empty_warning; #endif /* #if defined (__INTEL_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cfbencrypt.c000066400000000000000000000113331470420105600250700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CFB mode) // // Contents: // ippsAESEncryptCFB() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAESEncryptCFB // // Purpose: AES-CFB encryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsCFBSizeErr (1>cfbBlkSize || cfbBlkSize>MBS_RIJ128) // ippStsUnderRunErr 0!=(dataLen%cfbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input buffer length (in bytes) // cfbBlkSize CFB block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector // *F*/ IPPFUN(IppStatus, ippsAESEncryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsAESSpec* pCtx, const Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test CFB value */ IPP_BADARG_RET(((1>cfbBlkSize) || (MBS_RIJ128=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use pipelined version is possible */ if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { if(cfbBlkSize==MBS_RIJ128) EncryptCFB128_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, pIV); else if(0==(cfbBlkSize&3)) EncryptCFB32_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, cfbBlkSize, pIV); else EncryptCFB_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, cfbBlkSize, pIV); return ippStsNoErr; } else #endif { Ipp32u tmpInp[2*NB(128)]; Ipp32u tmpOut[ NB(128)]; /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pCtx); /* read IV */ CopyBlock16(pIV, tmpInp); /* encrypt data block-by-block of cfbLen each */ while(len>=cfbBlkSize) { int n; /* encryption */ //encoder(tmpInp, tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)tmpInp, (Ipp8u*)tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)tmpInp, (Ipp8u*)tmpOut, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif /* store output and put feedback into the input buffer (tmpInp) */ if( cfbBlkSize==MBS_RIJ128 && pSrc!=pDst) { tmpInp[0] = ((Ipp32u*)pDst)[0] = tmpOut[0]^((Ipp32u*)pSrc)[0]; tmpInp[1] = ((Ipp32u*)pDst)[1] = tmpOut[1]^((Ipp32u*)pSrc)[1]; tmpInp[2] = ((Ipp32u*)pDst)[2] = tmpOut[2]^((Ipp32u*)pSrc)[2]; tmpInp[3] = ((Ipp32u*)pDst)[3] = tmpOut[3]^((Ipp32u*)pSrc)[3]; } else { for(n=0; n>8) & 0xFF; } } /*F* // Name: ippsAES_CMACInit // // Purpose: Init AES-CMAC context. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsMemAllocErr size of buffer is not match for operation // ippStsLengthErr keyLen != 16 // keyLen != 24 // keyLen != 32 // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length of secret key // pState pointer to the CMAC context // ctxSize available size (in bytes) of buffer above // *F*/ IPPFUN(IppStatus, ippsAES_CMACInit,(const Ipp8u* pKey, int keyLen, IppsAES_CMACState* pState, int ctxSize)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* test available size of context buffer */ IPP_BADARG_RET(ctxSize>7)) & 0x87); /* ^ Rb changed for constant time execution */ /* precompute k2 subkey */ msb = (CMAC_K1(pState))[0]; LogicalLeftSift16(CMAC_K1(pState),CMAC_K2(pState)); (CMAC_K2(pState))[MBS_RIJ128-1] ^= (Ipp8u)((0-(msb>>7)) & 0x87); /* ^ Rb changed for constant time execution */ } return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_cmacupdate.c000066400000000000000000000140551470420105600250430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-CMAC Functions // // Contents: // ippsAES_CMACUpdate() // */ #include "owndefs.h" #include "owncp.h" #include "pcpcmac.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /*F* // Name: ippsAES_CMACUpdate // // Purpose: Updates intermadiate digest based on input stream. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pState == NULL // ippStsContextMatchErr !VALID_AESCMAC_ID() // ippStsLengthErr len <0 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the input stream // len input stream length // pState pointer to the CMAC context // *F*/ static void AES_CMAC_processing(Ipp8u* pDigest, const Ipp8u* pSrc, int processedLen, const IppsAESSpec* pAES) { #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pAES)) { cpAESCMAC_Update_AES_NI(pDigest, pSrc, processedLen, RIJ_NR(pAES), RIJ_EKEYS(pAES)); } else #endif { /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pAES); while(processedLen) { ((Ipp32u*)pDigest)[0] ^= ((Ipp32u*)pSrc)[0]; ((Ipp32u*)pDigest)[1] ^= ((Ipp32u*)pSrc)[1]; ((Ipp32u*)pDigest)[2] ^= ((Ipp32u*)pSrc)[2]; ((Ipp32u*)pDigest)[3] ^= ((Ipp32u*)pSrc)[3]; #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pDigest, pDigest, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(pDigest, pDigest, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif pSrc += MBS_RIJ128; processedLen -= MBS_RIJ128; } } } IPPFUN(IppStatus, ippsAES_CMACUpdate,(const Ipp8u* pSrc, int len, IppsAES_CMACState* pState)) { int processedLen; /* test context pointer */ IPP_BAD_PTR1_RET(pState); /* test ID */ IPP_BADARG_RET(!VALID_AESCMAC_ID(pState), ippStsContextMatchErr); /* test input message and it's length */ IPP_BADARG_RET((len<0 && pSrc), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); if(!len) return ippStsNoErr; { /* // test internal buffer filling */ if(CMAC_INDX(pState)) { /* copy from input stream to the internal buffer as match as possible */ processedLen = IPP_MIN(len, (MBS_RIJ128 - CMAC_INDX(pState))); CopyBlock(pSrc, CMAC_BUFF(pState)+CMAC_INDX(pState), processedLen); /* internal buffer filling */ CMAC_INDX(pState) += processedLen; /* update message pointer and length */ pSrc += processedLen; len -= processedLen; if(!len) return ippStsNoErr; /* update CMAC if buffer full but not the last */ if(MBS_RIJ128==CMAC_INDX(pState) ) { const IppsAESSpec* pAES = &CMAC_CIPHER(pState); /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pAES); XorBlock16(CMAC_BUFF(pState), CMAC_MAC(pState), CMAC_MAC(pState)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(CMAC_MAC(pState), CMAC_MAC(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(CMAC_MAC(pState), CMAC_MAC(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif CMAC_INDX(pState) = 0; } } /* // main part */ processedLen = len & ~(MBS_RIJ128-1); if(!(len & (MBS_RIJ128-1))) processedLen -= MBS_RIJ128; if (processedLen) { const IppsAESSpec *pAES = &CMAC_CIPHER(pState); #if (_AES_PROB_NOISE == _FEATURE_ON_) /* Mistletoe3 mitigation */ cpAESNoiseParams *params = (cpAESNoiseParams *)&AESCMAC_NOISE_PARAMS(pState); if (AES_NOISE_LEVEL(params) > 0) { /* Number of bytes allowed for operation without adding noise */ int chunk_size; /* Number of bytes remaining for operation */ int remaining_size = processedLen; while (remaining_size > 0) { /* How many bytes to encrypt in this operation */ chunk_size = (remaining_size >= MISTLETOE3_MAX_CHUNK_SIZE) ? MISTLETOE3_MAX_CHUNK_SIZE : remaining_size; AES_CMAC_processing(CMAC_MAC(pState), pSrc, chunk_size, pAES); cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); pSrc += chunk_size; remaining_size -= chunk_size; } } else #endif { AES_CMAC_processing(CMAC_MAC(pState), pSrc, processedLen, pAES); /* update message pointer and length */ pSrc += processedLen; } len -= processedLen; } /* // remainder */ if(len) { /* workaround to avoid false positive stringop-overflow error on gcc10.1 and gcc11.1 */ len = ( IPP_MIN(len, MBS_RIJ128) ); CopyBlock(pSrc, (Ipp8u*)(&CMAC_BUFF(pState)), len); /* update internal buffer filling */ CMAC_INDX(pState) += len; } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ctr_process.h000066400000000000000000000177561470420105600253030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CTR mode) // // Contents: // cpProcessAES_ctr() // cpProcessAES_ctr128() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /* // AES-CRT processing. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsCTRSizeErr 128 < ctrNumBitSize < 1 // ippStsCTRSizeErr data blocks number > 2^ctrNumBitSize // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // pCtx pointer to rge AES context // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // */ __IPPCP_INLINE void MaskCounter128(Ipp8u* pMaskIV, int ctrBtSize) { /* construct ctr mask */ int maskPosition = (MBS_RIJ128*8-ctrBtSize)/8; Ipp8u maskValue = (Ipp8u)(0xFF >> (MBS_RIJ128*8-ctrBtSize)%8 ); //Ipp8u maskIV[MBS_RIJ128]; int n; for(n=0; n= 8 * sizeof(int) - 5 // function can process data with any possible // passed dataLen without counter overflow */ int dataBlocksNum = dataLen >> 4; if(dataLen & 15){ dataBlocksNum++; } IPP_BADARG_RET(dataBlocksNum > (1 << ctrNumBitSize), ippStsCTRSizeErr); } #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use pipelined version if possible */ if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { /* construct ctr mask */ Ipp8u maskIV[MBS_RIJ128]; MaskCounter128(maskIV, ctrNumBitSize); /* const-exe-time version */ #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { EncryptCTR_RIJ128pipe_VAES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), dataLen, pCtrValue, maskIV); } else #endif { EncryptCTR_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), dataLen, pCtrValue, maskIV); } return ippStsNoErr; } else #endif { Ipp32u counter[NB(128)]; Ipp32u output[NB(128)]; /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pCtx); /* copy counter */ CopyBlock16(pCtrValue, counter); /* // encrypt block-by-block aligned streams */ while(dataLen>= MBS_RIJ128) { /* encrypt counter block */ //encoder(counter, output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)counter, (Ipp8u*)output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)counter, (Ipp8u*)output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif /* compute ciphertext block */ if( !(IPP_UINT_PTR(pSrc) & 0x3) && !(IPP_UINT_PTR(pDst) & 0x3)) { ((Ipp32u*)pDst)[0] = output[0]^((Ipp32u*)pSrc)[0]; ((Ipp32u*)pDst)[1] = output[1]^((Ipp32u*)pSrc)[1]; ((Ipp32u*)pDst)[2] = output[2]^((Ipp32u*)pSrc)[2]; ((Ipp32u*)pDst)[3] = output[3]^((Ipp32u*)pSrc)[3]; } else XorBlock16(pSrc, output, pDst); /* encrement counter block */ StdIncrement((Ipp8u*)counter,MBS_RIJ128*8, ctrNumBitSize); pSrc += MBS_RIJ128; pDst += MBS_RIJ128; dataLen -= MBS_RIJ128; } /* // encrypt last data block */ if(dataLen) { /* encrypt counter block */ //encoder(counter, output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)counter, (Ipp8u*)output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)counter, (Ipp8u*)output, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif /* compute ciphertext block */ XorBlock(pSrc, output, pDst,dataLen); /* encrement counter block */ StdIncrement((Ipp8u*)counter,MBS_RIJ128*8, ctrNumBitSize); } /* update counter */ CopyBlock16(counter, pCtrValue); return ippStsNoErr; } } #if (_IPP32E>=_IPP32E_Y8) /* // special version: 128-bit counter */ static IppStatus cpProcessAES_ctr128(const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsAESSpec* pCtx, Ipp8u* pCtrValue) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source, target and counter block pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pCtrValue); /* test stream length */ IPP_BADARG_RET((dataLen<1), ippStsLengthErr); { while(dataLen>=MBS_RIJ128) { Ipp32u blocks = (Ipp32u)(dataLen>>4); /* number of blocks per loop processing */ /* low LE 32 bit of counter */ Ipp32u ctr32 = ((Ipp32u*)(pCtrValue))[3]; ctr32 = ENDIANNESS32(ctr32); /* compute number of locks being processed without ctr32 overflow */ ctr32 += blocks; if(ctr32 < blocks) blocks -= ctr32; #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { EncryptStreamCTR32_VAES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (Ipp32s)blocks*MBS_RIJ128, pCtrValue); } else #endif EncryptStreamCTR32_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (Ipp32s)blocks*MBS_RIJ128, pCtrValue); pSrc += blocks*MBS_RIJ128; pDst += blocks*MBS_RIJ128; dataLen -= blocks*MBS_RIJ128; } if(dataLen) { EncryptStreamCTR32_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), dataLen, pCtrValue); } return ippStsNoErr; } } #endif /* #if (_IPP32E>=_IPP32E_Y8) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ctrdecrypt.c000066400000000000000000000051661470420105600251230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CTR mode) // // Contents: // ippsAESDecryptCTR() // */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty unit #endif #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_ctr_process.h" /* // Name: ippsAESDecryptCTR // // Purpose: // AES-CFB encryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsCTRSizeErr 128 < ctrNumBitSize < 1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len output buffer length (in bytes) // pCtx pointer to rge AES context // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // */ IPPFUN(IppStatus, ippsAESDecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); #if(_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) return ctrNumBitSize==128? cpProcessAES_ctr128(pSrc, pDst, len, pCtx, pCtrValue) : cpProcessAES_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); else return cpProcessAES_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); #else return cpProcessAES_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ctrencrypt_rij128pipe_vaes512.c000066400000000000000000000234551470420105600303610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CTR mode) // // Contents: // EncryptCTR_RIJ128pipe_VAES_NI // */ #include "owncp.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaesm.h" #if (_IPP32E >= _IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable : 4310) // cast truncates constant value in MSVC #endif #define M512(mem) (*((__m512i *)((Ipp8u *)(mem)))) /* Mask to convert 64-bit parts of four 128-bit numbers stored in one 512-bit register * from Little-Endian to Big-Endian */ /* clang-format off */ static __ALIGN32 Ipp8u swapBytes[] = { 7, 6, 5, 4, 3, 2, 1, 0, 15,14,13,12, 11,10, 9, 8, 23,22,21,20, 19,18,17,16, 31,30,29,28, 27,26,25,24, 39,38,37,36, 35,34,33,32, 47,46,45,44, 43,42,41,40, 55,54,53,52, 51,50,49,48, 63,62,61,60, 59,58,57,56 }; /* clang-format on */ /* Increment masks for Hi-Lo 64-bit parts of 128-bit numbers in 512-bit register */ static __ALIGN64 Ipp64u startIncLoMask[] = { 0x0, 0x0, 0x0, 0x1, 0x0, 0x2, 0x0, 0x3 }; static __ALIGN64 Ipp64u nextIncLoMask[] = { 0x0, 0x4, 0x0, 0x4, 0x0, 0x4, 0x0, 0x4 }; static __ALIGN64 Ipp64u incLoByOneMask[] = { 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1 }; static __ALIGN64 Ipp64u incHiByOneMask[] = { 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0 }; __IPPCP_INLINE __m512i adcLo_epi64(__m512i a, __m512i b) { a = _mm512_add_epi64(a, b); // check overflow in each low 64-bit of 128-bit numbers __mmask8 overMsk = _mm512_cmplt_epu64_mask(a, b); // get mask of each high 64-bit that need to be increased overMsk <<= 1; a = _mm512_mask_add_epi64(a, overMsk, a, M512(incHiByOneMask)); return a; } __IPPCP_INLINE __m512i applyNonce(__m512i a, __m512i ctrBitMask, __m512i templateCtr) { a = _mm512_shuffle_epi8(a, M512(swapBytes)); a = _mm512_and_epi64(a, ctrBitMask); a = _mm512_or_epi64(a, templateCtr); return a; } //////////////////////////////////////////////////////////////////////////////// /* clang-format off */ IPP_OWN_DEFN (void, EncryptCTR_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pRKey, int length, /* message length in bytes */ Ipp8u* pCtrValue, const Ipp8u* pCtrBitMask)) /* clang-format on */ { int cipherRounds = nr - 1; __m128i *pKeys = (__m128i *)pRKey; __m512i *pSrc512 = (__m512i *)pSrc; __m512i *pDst512 = (__m512i *)pDst; Ipp64u *pCtr64 = (Ipp64u *)pCtrValue; // Initial counter __m128i initialCtr128 = _mm_maskz_loadu_epi64(0x03, pCtrValue); __m128i ctrBitMask128 = _mm_maskz_loadu_epi64(0x03, pCtrBitMask); // Unchanged counter part __m128i templateCtr128 = _mm_maskz_andnot_epi64(0x03 /* all 128-bits */, ctrBitMask128, initialCtr128); __m512i ctrBitMask512 = _mm512_broadcast_i64x2(ctrBitMask128); __m512i templateCtr512 = _mm512_broadcast_i64x2(templateCtr128); Ipp64u ctr64_h = ENDIANNESS64(pCtr64[0]); // high 64-bit of BE counter converted to LE Ipp64u ctr64_l = ENDIANNESS64(pCtr64[1]); // low 64-bit of BE counter converted to LE __m512i ctr512 = _mm512_set4_epi64((Ipp64s)ctr64_l, (Ipp64s)ctr64_h, (Ipp64s)ctr64_l, (Ipp64s)ctr64_h); // int blocks; int remainded_length; __m512i incMsk = M512(startIncLoMask); for (remainded_length = length; remainded_length >= (4 * 4 * MBS_RIJ128); remainded_length -= (4 * 4 * MBS_RIJ128)) { __m512i counter0 = adcLo_epi64(incMsk, ctr512); __m512i counter1 = adcLo_epi64(M512(nextIncLoMask), counter0); __m512i counter2 = adcLo_epi64(M512(nextIncLoMask), counter1); __m512i counter3 = adcLo_epi64(M512(nextIncLoMask), counter2); incMsk = M512(nextIncLoMask); ctr512 = counter3; // convert back to BE and add nonce counter0 = applyNonce(counter0, ctrBitMask512, templateCtr512); counter1 = applyNonce(counter1, ctrBitMask512, templateCtr512); counter2 = applyNonce(counter2, ctrBitMask512, templateCtr512); counter3 = applyNonce(counter3, ctrBitMask512, templateCtr512); cpAESEncrypt4_VAES_NI(&counter0, &counter1, &counter2, &counter3, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i blk3 = _mm512_loadu_si512(pSrc512 + 3); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); blk2 = _mm512_xor_si512(blk2, counter2); blk3 = _mm512_xor_si512(blk3, counter3); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); _mm512_storeu_si512(pDst512 + 3, blk3); pSrc512 += 4; pDst512 += 4; } if ((3 * 4 * MBS_RIJ128) <= remainded_length) { __m512i counter0 = adcLo_epi64(incMsk, ctr512); __m512i counter1 = adcLo_epi64(M512(nextIncLoMask), counter0); __m512i counter2 = adcLo_epi64(M512(nextIncLoMask), counter1); incMsk = M512(nextIncLoMask); ctr512 = counter2; // convert back to BE and add nonce counter0 = applyNonce(counter0, ctrBitMask512, templateCtr512); counter1 = applyNonce(counter1, ctrBitMask512, templateCtr512); counter2 = applyNonce(counter2, ctrBitMask512, templateCtr512); cpAESEncrypt3_VAES_NI(&counter0, &counter1, &counter2, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); blk2 = _mm512_xor_si512(blk2, counter2); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); pSrc512 += 3; pDst512 += 3; remainded_length -= (3 * 4 * MBS_RIJ128); } if ((4 * 2 * MBS_RIJ128) <= remainded_length) { __m512i counter0 = adcLo_epi64(incMsk, ctr512); __m512i counter1 = adcLo_epi64(M512(nextIncLoMask), counter0); incMsk = M512(nextIncLoMask); ctr512 = counter1; // convert back to BE and add nonce counter0 = applyNonce(counter0, ctrBitMask512, templateCtr512); counter1 = applyNonce(counter1, ctrBitMask512, templateCtr512); cpAESEncrypt2_VAES_NI(&counter0, &counter1, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); pSrc512 += 2; pDst512 += 2; remainded_length -= (2 * 4 * MBS_RIJ128); } for (; remainded_length >= 4 * MBS_RIJ128; remainded_length -= 4 * MBS_RIJ128) { __m512i counter0 = adcLo_epi64(incMsk, ctr512); incMsk = M512(nextIncLoMask); ctr512 = counter0; // convert back to BE and add nonce counter0 = applyNonce(counter0, ctrBitMask512, templateCtr512); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); blk0 = _mm512_xor_si512(blk0, counter0); _mm512_storeu_si512(pDst512, blk0); pSrc512 += 1; pDst512 += 1; } if (remainded_length) { __m512i counter0 = _mm512_add_epi64(incMsk, ctr512); __mmask8 overMsk = _mm512_cmplt_epu64_mask(counter0, ctr512); overMsk <<= 1; counter0 = _mm512_mask_add_epi64(counter0, overMsk, counter0, M512(incHiByOneMask)); incMsk = M512(nextIncLoMask); ctr512 = counter0; // convert back to BE and add nonce counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter0 = _mm512_and_epi64(counter0, ctrBitMask512); counter0 = _mm512_or_epi64(counter0, templateCtr512); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); __mmask64 rw_mask = (__mmask64)((1LL << remainded_length) - 1); __m512i blk0 = _mm512_maskz_loadu_epi8(rw_mask, pSrc512); blk0 = _mm512_xor_si512(blk0, counter0); _mm512_mask_storeu_epi8(pDst512, rw_mask, blk0); } // return last counter int blocks = remainded_length % MBS_RIJ128 == 0 ? remainded_length / MBS_RIJ128 : (remainded_length / MBS_RIJ128) + 1; __mmask8 lastCtrK8 = blocks == 0 ? 0xC0 : (__mmask8)((Ipp8u)0x03 << ((blocks - 1) << 1)); __mmask64 lastCtrK64 = blocks == 0 ? 0xFFFF000000000000 : (__mmask64)((Ipp64u)0xFFFF << ((blocks - 1) << 4)); ctr512 = adcLo_epi64(M512(incLoByOneMask), ctr512); ctr512 = _mm512_maskz_shuffle_epi8(lastCtrK64, ctr512, M512(swapBytes)); ctr512 = _mm512_maskz_and_epi64(lastCtrK8, ctr512, ctrBitMask512); ctr512 = _mm512_maskz_or_epi64(lastCtrK8, ctr512, templateCtr512); _mm512_mask_compressstoreu_epi64(pCtrValue, lastCtrK8, ctr512); } #endif /* #if (_IPP32E>=_IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ctrencrypt_stream_vaes512.c000077500000000000000000000211031470420105600277460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CTR mode) // // Contents: // EncryptStreamCTR32_VAES_NI // */ #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #if (_IPP32E>=_IPP32E_K1) /* Mask to convert low 32-bit parts of four 128-bit Big-Endian numbers * stored in 512-bit register. The low 32-bit of each number converted * from LE to BE */ static __ALIGN32 Ipp8u swapBytes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11, 15,14,13,12, 16,17,18,19, 20,21,22,23, 24,25,26,27, 31,30,29,28, 32,33,34,35, 36,37,38,39, 40,41,42,43, 47,46,45,44, 48,49,50,51, 52,53,54,55, 56,57,58,59, 63,62,61,60 }; //////////////////////////////////////////////////////////////////////////////// IPP_OWN_DEFN (void, EncryptStreamCTR32_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pRKey, int length, /* message length in bytes */ Ipp8u* pIV)) /* BE counter representation */ { int cipherRounds = nr - 1; __m128i* pKeys = (__m128i*)pRKey; __m512i* pSrc512 = (__m512i*)pSrc; __m512i* pDst512 = (__m512i*)pDst; Ipp32u* pIV32 = (Ipp32u*)pIV; Ipp64u* pIV64 = (Ipp64u*)pIV; // start increment mask for IV __m512i startIncMask = _mm512_set_epi32(0x3, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0); // continuous increment mask for IV __m512i incMask = _mm512_set_epi32(0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0); // initial BE counter with 32-bit low part converted to LE: // pIV: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | fc fd fe ff // IV: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | ff fe fd fc __m512i IV = _mm512_set4_epi32((Ipp32s)ENDIANNESS32(pIV32[3]), (Ipp32s)pIV32[2], (Ipp32s)pIV32[1], (Ipp32s)pIV32[0]); // Update IV counter for next function calls int blocks = length / MBS_RIJ128; Ipp64u ctr64_h = ENDIANNESS64(pIV64[0]); // high 64-bit of BE IV converted to LE Ipp64u ctr64_l = ENDIANNESS64(pIV64[1]); // low 32-bit of BE pIV converted to LE ctr64_l += (Ipp64u)blocks; if (ctr64_l < (Ipp64u)blocks) { // overflow of low part ctr64_h += 1; } // update IV pIV64[0] = ENDIANNESS64(ctr64_h); pIV64[1] = ENDIANNESS64(ctr64_l); //-------------------------------------- for (blocks = length / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { // counter0: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | ff fe fd fc // counter1: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | 00 ff fd fc // counter2: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | 01 ff fd fc // counter3: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | 02 ff fd fc __m512i counter0 = _mm512_add_epi32(startIncMask, IV); __m512i counter1 = _mm512_add_epi32(incMask, counter0); __m512i counter2 = _mm512_add_epi32(incMask, counter1); __m512i counter3 = _mm512_add_epi32(incMask, counter2); startIncMask = incMask; IV = counter3; // convert last 32-bit (LE->BE): // counter0: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | fc fd fe ff // counter1: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | fc fd ff 00 // counter2: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | fc fd ff 01 // counter3: f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fb | fc fd ff 02 counter0 = _mm512_shuffle_epi8(counter0, *((__m512i*)swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, *((__m512i*)swapBytes)); counter2 = _mm512_shuffle_epi8(counter2, *((__m512i*)swapBytes)); counter3 = _mm512_shuffle_epi8(counter3, *((__m512i*)swapBytes)); cpAESEncrypt4_VAES_NI(&counter0, &counter1, &counter2, &counter3, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i blk3 = _mm512_loadu_si512(pSrc512 + 3); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); blk2 = _mm512_xor_si512(blk2, counter2); blk3 = _mm512_xor_si512(blk3, counter3); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); _mm512_storeu_si512(pDst512 + 3, blk3); pSrc512 += 4; pDst512 += 4; } if ((3 * 4) <= blocks) { __m512i counter0 = _mm512_add_epi32(startIncMask, IV); __m512i counter1 = _mm512_add_epi32(incMask, counter0); __m512i counter2 = _mm512_add_epi32(incMask, counter1); startIncMask = incMask; IV = counter2; // convert last 32-bit (LE->BE) counter0 = _mm512_shuffle_epi8(counter0, *((__m512i*)swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, *((__m512i*)swapBytes)); counter2 = _mm512_shuffle_epi8(counter2, *((__m512i*)swapBytes)); cpAESEncrypt3_VAES_NI(&counter0, &counter1, &counter2, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); blk2 = _mm512_xor_si512(blk2, counter2); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); pSrc512 += 3; pDst512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { __m512i counter0 = _mm512_add_epi32(startIncMask, IV); __m512i counter1 = _mm512_add_epi32(incMask, counter0); startIncMask = incMask; IV = counter1; // convert last 32-bit (LE->BE) counter0 = _mm512_shuffle_epi8(counter0, *((__m512i*)swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, *((__m512i*)swapBytes)); cpAESEncrypt2_VAES_NI(&counter0, &counter1, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); pSrc512 += 2; pDst512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { __m512i counter0 = _mm512_add_epi32(startIncMask, IV); startIncMask = incMask; IV = counter0; // convert last 32-bit (LE->BE) counter0 = _mm512_shuffle_epi8(counter0, *((__m512i*)swapBytes)); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); blk0 = _mm512_xor_si512(blk0, counter0); _mm512_storeu_si512(pDst512, blk0); pSrc512 += 1; pDst512 += 1; } if (blocks) { __mmask8 k8 = (__mmask8)((1 << (blocks + blocks)) - 1); // 64-bit chunks __mmask16 k16 = (__mmask16)((1 << (blocks << 2)) - 1); // 32-bit chunks __mmask64 k64 = (__mmask64)((1LL << (blocks << 4)) - 1); // 8-bit chunks __m512i counter0 = _mm512_maskz_add_epi32(k16, startIncMask, IV); // swap last 32-bit (LE->BE) counter0 = _mm512_maskz_shuffle_epi8(k64, counter0, *((__m512i*)swapBytes)); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); __m512i blk0 = _mm512_maskz_loadu_epi64(k8, pSrc512); blk0 = _mm512_maskz_xor_epi64(k8, blk0, counter0); _mm512_mask_storeu_epi64(pDst512, k8, blk0); } } #endif /* #if (_IPP32E>=_IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ctrencryptr.c000066400000000000000000000051661470420105600253170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (CTR mode) // // Contents: // ippsAESEncryptCTR() // */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty unit #endif #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_ctr_process.h" /* // Name: ippsAESEncryptCTR // // Purpose: // AES-CFB encryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsCTRSizeErr 128 < ctrNumBitSize < 1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input buffer length (in bytes) // pCtx pointer to rge AES context // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // */ IPPFUN(IppStatus, ippsAESEncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); #if(_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) return ctrNumBitSize==128? cpProcessAES_ctr128(pSrc, pDst, len, pCtx, pCtrValue) : cpProcessAES_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); else return cpProcessAES_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); #else return cpProcessAES_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_deckeyexpansion_ni.c000066400000000000000000000030721470420105600266110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. AES keys expansion // // Contents: // aes_DecKeyExpansion_NI() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_keys_ni.h" #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) ////////////////////////////////////////////////////////////////////// /* // AES decryption key schelule */ IPP_OWN_DEFN (void, aes_DecKeyExpansion_NI, (Ipp8u* decKeys, const Ipp8u* encKeys, int nr)) { __m128i* encKeys16 = (__m128i*)encKeys; __m128i* decKeys16 = (__m128i*)decKeys; decKeys16[nr] = encKeys16[nr]; for(nr-=1; nr > 0; nr--) { decKeys16[nr] = _mm_aesimc_si128(encKeys16[nr]); } decKeys16[0] = encKeys16[0]; } #endif /* #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_decrypt_vaes512.h000066400000000000000000000143051470420105600256600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES decryption (VAES-512 kernels) // // Contents: // cpAESDecrypt1_VAES_NI // cpAESDecrypt2_VAES_NI // cpAESDecrypt3_VAES_NI // cpAESDecrypt4_VAES_NI // */ #include "owncp.h" #include "pcpaesm.h" #if(_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4305) // zmmintrin.h bug: conversion from int to _mmask8 #endif #if !defined(_PCP_AES_DECRYPT_VAES512_H_) #define _PCP_AES_DECRYPT_VAES512_H_ //////////////////////////////////////////////////////////////////////////////// static void cpAESDecrypt1_VAES_NI(__m512i* blk0, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[-1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-2]); for (nr = 1, pRkey--; nr < cipherRounds; nr += 2, pRkey -= 2) { b0 = _mm512_aesdec_epi128(b0, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[-2]); b0 = _mm512_aesdec_epi128(b0, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-3]); } b0 = _mm512_aesdec_epi128(b0, rKey1); *blk0 = _mm512_aesdeclast_epi128(b0, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } static void cpAESDecrypt2_VAES_NI(__m512i* blk0, __m512i* blk1, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[-1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); __m512i b1 = _mm512_xor_si512(*blk1, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-2]); for (nr = 1, pRkey--; nr < cipherRounds; nr += 2, pRkey -= 2) { b0 = _mm512_aesdec_epi128(b0, rKey1); b1 = _mm512_aesdec_epi128(b1, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[-2]); b0 = _mm512_aesdec_epi128(b0, rKey0); b1 = _mm512_aesdec_epi128(b1, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-3]); } b0 = _mm512_aesdec_epi128(b0, rKey1); b1 = _mm512_aesdec_epi128(b1, rKey1); *blk0 = _mm512_aesdeclast_epi128(b0, rKey0); *blk1 = _mm512_aesdeclast_epi128(b1, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } static void cpAESDecrypt3_VAES_NI(__m512i* blk0, __m512i* blk1, __m512i* blk2, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[-1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); __m512i b1 = _mm512_xor_si512(*blk1, rKey0); __m512i b2 = _mm512_xor_si512(*blk2, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-2]); for (nr = 1, pRkey--; nr < cipherRounds; nr += 2, pRkey -= 2) { b0 = _mm512_aesdec_epi128(b0, rKey1); b1 = _mm512_aesdec_epi128(b1, rKey1); b2 = _mm512_aesdec_epi128(b2, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[-2]); b0 = _mm512_aesdec_epi128(b0, rKey0); b1 = _mm512_aesdec_epi128(b1, rKey0); b2 = _mm512_aesdec_epi128(b2, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-3]); } b0 = _mm512_aesdec_epi128(b0, rKey1); b1 = _mm512_aesdec_epi128(b1, rKey1); b2 = _mm512_aesdec_epi128(b2, rKey1); *blk0 = _mm512_aesdeclast_epi128(b0, rKey0); *blk1 = _mm512_aesdeclast_epi128(b1, rKey0); *blk2 = _mm512_aesdeclast_epi128(b2, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } static void cpAESDecrypt4_VAES_NI(__m512i* blk0, __m512i* blk1, __m512i* blk2, __m512i* blk3, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[-1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); __m512i b1 = _mm512_xor_si512(*blk1, rKey0); __m512i b2 = _mm512_xor_si512(*blk2, rKey0); __m512i b3 = _mm512_xor_si512(*blk3, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-2]); for (nr = 1, pRkey--; nr < cipherRounds; nr += 2, pRkey -= 2) { b0 = _mm512_aesdec_epi128(b0, rKey1); b1 = _mm512_aesdec_epi128(b1, rKey1); b2 = _mm512_aesdec_epi128(b2, rKey1); b3 = _mm512_aesdec_epi128(b3, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[-2]); b0 = _mm512_aesdec_epi128(b0, rKey0); b1 = _mm512_aesdec_epi128(b1, rKey0); b2 = _mm512_aesdec_epi128(b2, rKey0); b3 = _mm512_aesdec_epi128(b3, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[-3]); } b0 = _mm512_aesdec_epi128(b0, rKey1); b1 = _mm512_aesdec_epi128(b1, rKey1); b2 = _mm512_aesdec_epi128(b2, rKey1); b3 = _mm512_aesdec_epi128(b3, rKey1); *blk0 = _mm512_aesdeclast_epi128(b0, rKey0); *blk1 = _mm512_aesdeclast_epi128(b1, rKey0); *blk2 = _mm512_aesdeclast_epi128(b2, rKey0); *blk3 = _mm512_aesdeclast_epi128(b3, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } #endif /* _PCP_AES_DECRYPT_VAES512_H_ */ #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ecb_vaes512.c000066400000000000000000000141511470420105600247310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (ECB mode) // // Contents: // EncryptECB_RIJ128pipe_VAES_NI // DecryptECB_RIJ128pipe_VAES_NI // // */ #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaes_decrypt_vaes512.h" #if (_IPP32E>=_IPP32E_K1) IPP_OWN_DEFN (void, EncryptECB_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, // pointer to the plaintext Ipp8u* pDst, // pointer to the ciphertext buffer int len, // text length in bytes const IppsAESSpec* pCtx)) // pointer to the context { int cipherRounds = RIJ_NR(pCtx) - 1; __m128i* pRkey = (__m128i*)RIJ_EKEYS(pCtx); __m512i* pInp512 = (__m512i*)pSrc; __m512i* pOut512 = (__m512i*)pDst; int blocks; for (blocks = len / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); __m512i blk3 = _mm512_loadu_si512(pInp512 + 3); cpAESEncrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); _mm512_storeu_si512(pOut512 + 3, blk3); pInp512 += 4; pOut512 += 4; } if ((3 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); cpAESEncrypt3_VAES_NI(&blk0, &blk1, &blk2, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); pInp512 += 3; pOut512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); cpAESEncrypt2_VAES_NI(&blk0, &blk1, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); pInp512 += 2; pOut512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { __m512i blk0 = _mm512_loadu_si512(pInp512); cpAESEncrypt1_VAES_NI(&blk0, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); pInp512 += 1; pOut512 += 1; } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); __m512i blk0 = _mm512_maskz_loadu_epi64(k, pInp512); cpAESEncrypt1_VAES_NI(&blk0, pRkey, cipherRounds); _mm512_mask_storeu_epi64(pOut512, k, blk0); } } //////////////////////////////////////////////////////////////////////////////// IPP_OWN_DEFN (void, DecryptECB_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, // pointer to the plaintext Ipp8u* pDst, // pointer to the ciphertext buffer int len, // text length in bytes const IppsAESSpec* pCtx)) // pointer to the context { int cipherRounds = RIJ_NR(pCtx) - 1; __m128i* pRkey = (__m128i*)RIJ_DKEYS(pCtx) + cipherRounds + 1; __m512i* pInp512 = (__m512i*)pSrc; __m512i* pOut512 = (__m512i*)pDst; int blocks; for (blocks = len / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); __m512i blk3 = _mm512_loadu_si512(pInp512 + 3); cpAESDecrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); _mm512_storeu_si512(pOut512 + 3, blk3); pInp512 += 4; pOut512 += 4; } if ((3 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); cpAESDecrypt3_VAES_NI(&blk0, &blk1, &blk2, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); pInp512 += 3; pOut512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); cpAESDecrypt2_VAES_NI(&blk0, &blk1, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); pInp512 += 2; pOut512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { __m512i blk0 = _mm512_loadu_si512(pInp512); cpAESDecrypt1_VAES_NI(&blk0, pRkey, cipherRounds); _mm512_storeu_si512(pOut512, blk0); pInp512 += 1; pOut512 += 1; } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); __m512i blk0 = _mm512_maskz_loadu_epi64(k, pInp512); cpAESDecrypt1_VAES_NI(&blk0, pRkey, cipherRounds); _mm512_mask_storeu_epi64(pOut512, k, blk0); } } #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ecbdecrypt.c000066400000000000000000000113401470420105600250530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (ECB mode) // // Contents: // ippsAESDecryptECB() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /* // AES-ECB denryption // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // nBlocks number of decrypted data blocks // pCtx pointer to the AES context */ static void cpDecryptAES_ecb(const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, const IppsAESSpec* pCtx) { #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use pipelined version is possible */ if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { DecryptECB_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), nBlocks*MBS_RIJ128); } else #endif { /* block-by-block decryption */ RijnCipher decoder = RIJ_DECODER(pCtx); while(nBlocks) { //decoder((const Ipp32u*)pSrc, (Ipp32u*)pDst, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), (const Ipp32u (*)[256])RIJ_DEC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) decoder(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijDecSbox/*NULL*/); #else decoder(pSrc, pDst, RIJ_NR(pCtx), RIJ_DKEYS(pCtx), NULL); #endif pSrc += MBS_RIJ128; pDst += MBS_RIJ128; nBlocks--; } } } static void cpDecryptAES_ecb_dispatch(const Ipp8u *pSrc, Ipp8u *pDst, int len, const IppsAESSpec *pCtx) { #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) DecryptECB_RIJ128pipe_VAES_NI(pSrc, pDst, len, pCtx); else #endif { int nBlocks = len / MBS_RIJ128; cpDecryptAES_ecb(pSrc, pDst, nBlocks, pCtx); } } /*F* // Name: ippsAESDecryptECB // // Purpose: AES-ECB decryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr dataLen <1 // ippStsUnderRunErr 0!=(dataLen%MBS_RIJ128) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // pCtx pointer to the AES context // *F*/ IPPFUN(IppStatus, ippsAESDecryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source and target buffer pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test stream integrity */ IPP_BADARG_RET((len&(MBS_RIJ128-1)), ippStsUnderRunErr); /* do encryption */ #if (_AES_PROB_NOISE == _FEATURE_ON_) cpAESNoiseParams *params = (cpAESNoiseParams*)&RIJ_NOISE_PARAMS(pCtx); /* Mistletoe3 mitigation */ if (AES_NOISE_LEVEL(params) > 0) { /* Number of bytes allowed for operation without adding noise */ int chunk_size; /* Number of bytes remaining for operation */ int remaining_size = len; while (remaining_size > 0) { /* How many bytes to encrypt in this operation */ chunk_size = (remaining_size >= MISTLETOE3_MAX_CHUNK_SIZE) ? MISTLETOE3_MAX_CHUNK_SIZE : remaining_size; cpDecryptAES_ecb_dispatch(pSrc, pDst, chunk_size, pCtx); cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); pSrc += chunk_size; pDst += chunk_size; remaining_size -= chunk_size; } } else #endif { cpDecryptAES_ecb_dispatch(pSrc, pDst, len, pCtx); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ecbencrypt.c000066400000000000000000000113711470420105600250710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (ECB mode) // // Contents: // ippsAESEncryptECB() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcprij.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /* // AES-ECB ecnryption // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // nBlocks number of ecnrypted data blocks // pCtx pointer to the AES context */ static void cpEncryptAES_ecb(const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, const IppsAESSpec* pCtx) { #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use pipelined version is possible */ if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { EncryptECB_RIJ128pipe_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), nBlocks*MBS_RIJ128); } else #endif { /* block-by-block encryption */ RijnCipher encoder = RIJ_ENCODER(pCtx); while(nBlocks) { //encoder((const Ipp32u*)pSrc, (Ipp32u*)pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif pSrc += MBS_RIJ128; pDst += MBS_RIJ128; nBlocks--; } } } static void cpEncryptAES_ecb_dispatch(const Ipp8u *pSrc, Ipp8u *pDst, int len, const IppsAESSpec *pCtx) { #if (_IPP32E >= _IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) EncryptECB_RIJ128pipe_VAES_NI(pSrc, pDst, len, pCtx); else #endif { int nBlocks = len / MBS_RIJ128; cpEncryptAES_ecb(pSrc, pDst, nBlocks, pCtx); } } /*F* // Name: ippsAESEncryptECB // // Purpose: AES-ECB encryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr dataLen <1 // ippStsUnderRunErr 0!=(dataLen%MBS_RIJ128) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // pCtx pointer to the AES context // *F*/ IPPFUN(IppStatus, ippsAESEncryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source and target buffer pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test stream integrity */ IPP_BADARG_RET((len&(MBS_RIJ128-1)), ippStsUnderRunErr); /* do encryption */ #if (_AES_PROB_NOISE == _FEATURE_ON_) /* Mistletoe3 mitigation */ cpAESNoiseParams *params = (cpAESNoiseParams*)&RIJ_NOISE_PARAMS(pCtx); if (AES_NOISE_LEVEL(params) > 0) { /* Number of bytes allowed for operation without adding noise */ int chunk_size; /* Number of bytes remaining for operation */ int remaining_size = len; while (remaining_size > 0) { /* How many bytes to encrypt in this operation */ chunk_size = (remaining_size >= MISTLETOE3_MAX_CHUNK_SIZE) ? MISTLETOE3_MAX_CHUNK_SIZE : remaining_size; cpEncryptAES_ecb_dispatch(pSrc, pDst, chunk_size, pCtx); cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); pSrc += chunk_size; pDst += chunk_size; remaining_size -= chunk_size; } } else #endif { cpEncryptAES_ecb_dispatch(pSrc, pDst, len, pCtx); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_encrypt_vaes512.h000066400000000000000000000142751470420105600257000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption (VAES-512 kernels) // // Contents: // cpAESEncrypt1_VAES_NI // cpAESEncrypt2_VAES_NI // cpAESEncrypt3_VAES_NI // cpAESEncrypt4_VAES_NI // */ #include "owncp.h" #include "pcpaesm.h" #if(_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4305) // zmmintrin.h bug: conversion from int to _mmask8 #endif #if !defined(_PCP_AES_ENCRYPT_VAES512_H_) #define _PCP_AES_ENCRYPT_VAES512_H_ //////////////////////////////////////////////////////////////////////////////// static void cpAESEncrypt1_VAES_NI(__m512i* blk0, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[2]); for (nr = 1, pRkey++; nr < cipherRounds; nr += 2, pRkey += 2) { b0 = _mm512_aesenc_epi128(b0, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[2]); b0 = _mm512_aesenc_epi128(b0, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[3]); } b0 = _mm512_aesenc_epi128(b0, rKey1); *blk0 = _mm512_aesenclast_epi128(b0, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } static void cpAESEncrypt2_VAES_NI(__m512i* blk0, __m512i* blk1, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); __m512i b1 = _mm512_xor_si512(*blk1, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[2]); for (nr = 1, pRkey++; nr < cipherRounds; nr += 2, pRkey += 2) { b0 = _mm512_aesenc_epi128(b0, rKey1); b1 = _mm512_aesenc_epi128(b1, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[2]); b0 = _mm512_aesenc_epi128(b0, rKey0); b1 = _mm512_aesenc_epi128(b1, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[3]); } b0 = _mm512_aesenc_epi128(b0, rKey1); b1 = _mm512_aesenc_epi128(b1, rKey1); *blk0 = _mm512_aesenclast_epi128(b0, rKey0); *blk1 = _mm512_aesenclast_epi128(b1, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } static void cpAESEncrypt3_VAES_NI(__m512i* blk0, __m512i* blk1, __m512i* blk2, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); __m512i b1 = _mm512_xor_si512(*blk1, rKey0); __m512i b2 = _mm512_xor_si512(*blk2, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[2]); for (nr = 1, pRkey++; nr < cipherRounds; nr += 2, pRkey += 2) { b0 = _mm512_aesenc_epi128(b0, rKey1); b1 = _mm512_aesenc_epi128(b1, rKey1); b2 = _mm512_aesenc_epi128(b2, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[2]); b0 = _mm512_aesenc_epi128(b0, rKey0); b1 = _mm512_aesenc_epi128(b1, rKey0); b2 = _mm512_aesenc_epi128(b2, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[3]); } b0 = _mm512_aesenc_epi128(b0, rKey1); b1 = _mm512_aesenc_epi128(b1, rKey1); b2 = _mm512_aesenc_epi128(b2, rKey1); *blk0 = _mm512_aesenclast_epi128(b0, rKey0); *blk1 = _mm512_aesenclast_epi128(b1, rKey0); *blk2 = _mm512_aesenclast_epi128(b2, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } static void cpAESEncrypt4_VAES_NI(__m512i* blk0, __m512i* blk1, __m512i* blk2, __m512i* blk3, const __m128i* pRkey, int cipherRounds) { int nr; __m512i rKey0 = _mm512_broadcast_i64x2(pRkey[0]); __m512i rKey1 = _mm512_broadcast_i64x2(pRkey[1]); __m512i b0 = _mm512_xor_si512(*blk0, rKey0); __m512i b1 = _mm512_xor_si512(*blk1, rKey0); __m512i b2 = _mm512_xor_si512(*blk2, rKey0); __m512i b3 = _mm512_xor_si512(*blk3, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[2]); for (nr = 1, pRkey++; nr < cipherRounds; nr += 2, pRkey += 2) { b0 = _mm512_aesenc_epi128(b0, rKey1); b1 = _mm512_aesenc_epi128(b1, rKey1); b2 = _mm512_aesenc_epi128(b2, rKey1); b3 = _mm512_aesenc_epi128(b3, rKey1); rKey1 = _mm512_broadcast_i64x2(pRkey[2]); b0 = _mm512_aesenc_epi128(b0, rKey0); b1 = _mm512_aesenc_epi128(b1, rKey0); b2 = _mm512_aesenc_epi128(b2, rKey0); b3 = _mm512_aesenc_epi128(b3, rKey0); rKey0 = _mm512_broadcast_i64x2(pRkey[3]); } b0 = _mm512_aesenc_epi128(b0, rKey1); b1 = _mm512_aesenc_epi128(b1, rKey1); b2 = _mm512_aesenc_epi128(b2, rKey1); b3 = _mm512_aesenc_epi128(b3, rKey1); *blk0 = _mm512_aesenclast_epi128(b0, rKey0); *blk1 = _mm512_aesenclast_epi128(b1, rKey0); *blk2 = _mm512_aesenclast_epi128(b2, rKey0); *blk3 = _mm512_aesenclast_epi128(b3, rKey0); rKey0 = _mm512_setzero_si512(); rKey1 = _mm512_setzero_si512(); } #endif /* _PCP_AES_ENCRYPT_VAES512_H_ */ #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_expandkey_ni.c000066400000000000000000000031141470420105600254050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. AES keys expansion // // Contents: // cpExpandAesKey_NI() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_keys_ni.h" #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) IPP_OWN_DEFN (void, cpExpandAesKey_NI, (const Ipp8u* pSecret, IppsAESSpec* pCtx)) { int nRounds = RIJ_NR(pCtx); Ipp8u* pEncKeys = RIJ_EKEYS(pCtx); Ipp8u* pDecKeys = RIJ_DKEYS(pCtx); switch (nRounds) { case 12: aes192_KeyExpansion_NI(pEncKeys, pSecret); break; case 14: aes256_KeyExpansion_NI(pEncKeys, pSecret); break; default: aes128_KeyExpansion_NI(pEncKeys, pSecret); break; } aes_DecKeyExpansion_NI(pDecKeys, pEncKeys, nRounds); } #endif /* #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcm_internal_func.c000066400000000000000000000227131470420105600264120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // * Initialization functions for internal methods and pointers inside AES-GCM context; // * AES-GCM encryption kernels with the conditional noise injections mechanism; // */ #include "pcpaes_gcm_internal_func.h" #include "aes_gcm_avx512.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if (_IPP32E >= _IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /* * This function dispatches to the right internal methods and sets pointers to them inside the AES-GCM state. */ IPP_OWN_DEFN(void, cpAesGCM_setup_ptrs_and_methods, (IppsAES_GCMState * pState, Ipp64u keyByteLen)) { #if (_IPP32E >= _IPP32E_K0) if (IsFeatureEnabled(ippCPUID_AVX512VAES) && IsFeatureEnabled(ippCPUID_AVX512VCLMUL)) { switch (keyByteLen) { case 16: AES_GCM_ENCRYPT_UPDATE(pState) = aes_gcm_enc_128_update_vaes_avx512; AES_GCM_DECRYPT_UPDATE(pState) = aes_gcm_dec_128_update_vaes_avx512; AES_GCM_GET_TAG(pState) = aes_gcm_gettag_128_vaes_avx512; break; case 24: AES_GCM_ENCRYPT_UPDATE(pState) = aes_gcm_enc_192_update_vaes_avx512; AES_GCM_DECRYPT_UPDATE(pState) = aes_gcm_dec_192_update_vaes_avx512; AES_GCM_GET_TAG(pState) = aes_gcm_gettag_192_vaes_avx512; break; case 32: AES_GCM_ENCRYPT_UPDATE(pState) = aes_gcm_enc_256_update_vaes_avx512; AES_GCM_DECRYPT_UPDATE(pState) = aes_gcm_dec_256_update_vaes_avx512; AES_GCM_GET_TAG(pState) = aes_gcm_gettag_256_vaes_avx512; break; } AES_GCM_IV_UPDATE(pState) = aes_gcm_iv_hash_update_vaes512; AES_GCM_IV_FINALIZE(pState) = aes_gcm_iv_hash_finalize_vaes512; AES_GCM_AAD_UPDATE(pState) = aes_gcm_aad_hash_update_vaes512; AES_GCM_GMUL(pState) = aes_gcm_gmult_vaes512; } else { switch (keyByteLen) { case 16: AES_GCM_ENCRYPT_UPDATE(pState) = aes_gcm_enc_128_update_avx512; AES_GCM_DECRYPT_UPDATE(pState) = aes_gcm_dec_128_update_avx512; AES_GCM_GET_TAG(pState) = aes_gcm_gettag_128_avx512; break; case 24: AES_GCM_ENCRYPT_UPDATE(pState) = aes_gcm_enc_192_update_avx512; AES_GCM_DECRYPT_UPDATE(pState) = aes_gcm_dec_192_update_avx512; AES_GCM_GET_TAG(pState) = aes_gcm_gettag_192_avx512; break; case 32: AES_GCM_ENCRYPT_UPDATE(pState) = aes_gcm_enc_256_update_avx512; AES_GCM_DECRYPT_UPDATE(pState) = aes_gcm_dec_256_update_avx512; AES_GCM_GET_TAG(pState) = aes_gcm_gettag_256_avx512; break; } AES_GCM_IV_UPDATE(pState) = aes_gcm_iv_hash_update_avx512; AES_GCM_IV_FINALIZE(pState) = aes_gcm_iv_hash_finalize_avx512; AES_GCM_AAD_UPDATE(pState) = aes_gcm_aad_hash_update_avx512; AES_GCM_GMUL(pState) = aes_gcm_gmult_avx512; } #else IPP_UNREFERENCED_PARAMETER(keyByteLen); /* set up: // - ghash function // - authentication function */ AESGCM_HASH(pState) = AesGcmMulGcm_table2K_ct; // AesGcmMulGcm_table2K; AESGCM_AUTH(pState) = AesGcmAuth_table2K_ct; // AesGcmAuth_table2K; AESGCM_ENC(pState) = wrpAesGcmEnc_table2K; AESGCM_DEC(pState) = wrpAesGcmDec_table2K; #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) // the dead code that currently is unused //#if (_IPP32E >= _IPP32E_K0) // if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { // AESGCM_HASH(pState) = AesGcmMulGcm_vaes; // AESGCM_AUTH(pState) = AesGcmAuth_vaes; // AESGCM_ENC(pState) = AesGcmEnc_vaes; // AESGCM_DEC(pState) = AesGcmDec_vaes; // } else //#endif /* #if(_IPP32E>=_IPP32E_K0) */ if (IsFeatureEnabled(ippCPUID_AES | ippCPUID_CLMUL)) { AESGCM_HASH(pState) = AesGcmMulGcm_avx; AESGCM_AUTH(pState) = AesGcmAuth_avx; AESGCM_ENC(pState) = wrpAesGcmEnc_avx; AESGCM_DEC(pState) = wrpAesGcmDec_avx; } #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) if (IsFeatureEnabled(ippCPUID_AVX2VAES | ippCPUID_AVX2VCLMUL)) { AESGCM_HASH(pState) = AesGcmMulGcm_avx; AESGCM_AUTH(pState) = AesGcmAuth_avx; AESGCM_ENC(pState) = AesGcmEnc_vaes_avx2; AESGCM_DEC(pState) = AesGcmDec_vaes_avx2; } #endif /* #if(_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) */ #endif /* #if(_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) */ #endif /* #if(_IPP32E>=_IPP32E_K0) */ } /*! * This function computes AES-GCM encryption kernel with the the conditional noise injections mechanism (Mistletoe3 * attack mitigation). * * Parameters: * \param[in] pSrc Pointer to plaintext. * \param[in] pDst Pointer to ciphertext. * \param[in] ptxt_len Length of the plaintext in bytes. * \param[in] pState Pointer to the AES-GCM context. */ IPP_OWN_DEFN(void, condNoisedGCMEncryption, (const Ipp8u* pSrc, Ipp8u* pDst, int ptxt_len, IppsAES_GCMState* pState)) { /* Identify the encryption method. It's different for different platforms */ #if(_IPP32E>=_IPP32E_K0) EncryptUpdate_ encFunc = AES_GCM_ENCRYPT_UPDATE(pState); #else Encrypt_ encFunc = AESGCM_ENC(pState); #endif #if (_AES_PROB_NOISE == _FEATURE_ON_) /* Mistletoe3 mitigation */ cpAESNoiseParams *params = (cpAESNoiseParams*)&AESGCM_NOISE_PARAMS(pState); if (AES_NOISE_LEVEL(params) > 0) { /* Number of bytes allowed for operation without adding noise */ int chunk_size; /* Number of bytes remaining for operation */ int remaining_size = ptxt_len; while (remaining_size > 0) { /* How many bytes to encrypt in this operation */ chunk_size = (remaining_size >= MISTLETOE3_MAX_CHUNK_SIZE) ? MISTLETOE3_MAX_CHUNK_SIZE : remaining_size; #if(_IPP32E>=_IPP32E_K0) encFunc(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pDst, pSrc, (Ipp64u)chunk_size); #else encFunc(pDst, pSrc, chunk_size, pState); #endif cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); pSrc += chunk_size; pDst += chunk_size; remaining_size -= chunk_size; } } else #endif { /* Process without noise injection */ #if(_IPP32E>=_IPP32E_K0) encFunc(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pDst, pSrc, (Ipp64u)ptxt_len); #else encFunc(pDst, pSrc, ptxt_len, pState); #endif } } /*! * This function computes AES-GCM decryption kernel with the the conditional noise injections mechanism (Mistletoe3 * attack mitigation). * * Parameters: * \param[in] pSrc Pointer to ciphertext. * \param[in] pDst Pointer to deciphered text. * \param[in] ctxt_len Length of the ciphertext in bytes. * \param[in] pState Pointer to the AES-GCM context. */ IPP_OWN_DEFN(void, condNoisedGCMDecryption, (const Ipp8u* pSrc, Ipp8u* pDst, int ctxt_len, IppsAES_GCMState* pState)) { /* Identify the decryption method. It's different for different platforms */ #if(_IPP32E>=_IPP32E_K0) DecryptUpdate_ decFunc = AES_GCM_DECRYPT_UPDATE(pState); #else Decrypt_ decFunc = AESGCM_DEC(pState); #endif #if (_AES_PROB_NOISE == _FEATURE_ON_) /* Mistletoe3 mitigation */ cpAESNoiseParams *params = (cpAESNoiseParams*)&AESGCM_NOISE_PARAMS(pState); if (AES_NOISE_LEVEL(params) > 0) { /* Number of bytes allowed for operation without adding noise */ int chunk_size; /* Number of bytes remaining for operation */ int remaining_size = ctxt_len; while (remaining_size > 0) { /* How many bytes to decrypt in this operation */ chunk_size = (remaining_size >= MISTLETOE3_MAX_CHUNK_SIZE) ? MISTLETOE3_MAX_CHUNK_SIZE : remaining_size; #if(_IPP32E>=_IPP32E_K0) decFunc(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pDst, pSrc, (Ipp64u)chunk_size); #else decFunc(pDst, pSrc, chunk_size, pState); #endif cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); pSrc += chunk_size; pDst += chunk_size; remaining_size -= chunk_size; } } else #endif { /* Process without noise injection */ #if(_IPP32E>=_IPP32E_K0) decFunc(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pDst, pSrc, (Ipp64u)ctxt_len); #else decFunc(pDst, pSrc, ctxt_len, pState); #endif } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcm_internal_func.h000066400000000000000000000032571470420105600264210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2024 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Initialization functions for internal methods and pointers inside AES-GCM context; // AES-GCM encryption kernels with the conditional noise injections mechanism; // */ #if !defined(_PCP_AES_GCM_INTERNAL_FUNC_H) #define _PCP_AES_GCM_INTERNAL_FUNC_H #include "owndefs.h" #include "pcpaes_internal_func.h" #define cpAesGCM_setup_ptrs_and_methods OWNAPI(cpAesGCM_setup_ptrs_and_methods) IPP_OWN_DECL(void, cpAesGCM_setup_ptrs_and_methods, (IppsAES_GCMState * pCtx, Ipp64u keyByteLen)) #define condNoisedGCMEncryption OWNAPI(condNoisedGCMEncryption) IPP_OWN_DECL(void, condNoisedGCMEncryption, (const Ipp8u* pSrc, Ipp8u* pDst, int ptxt_len, IppsAES_GCMState* pState)) #define condNoisedGCMDecryption OWNAPI(condNoisedGCMDecryption) IPP_OWN_DECL(void, condNoisedGCMDecryption, (const Ipp8u* pSrc, Ipp8u* pDst, int ptxt_len, IppsAES_GCMState* pState)) #endif /* _PCP_AES_GCM_INTERNAL_FUNC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcm_vaes512.h000066400000000000000000000124561470420105600247610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM auxiliary // // Contents: // */ #if 0 // Not used #if !defined(_CP_AES_GCM_VAES512_H) #define _CP_AES_GCM_VAES512_H #if (_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // cast truncates constant value in MSVC #endif #define M128(mem) (*((__m128i*)((Ipp8u*)(mem)))) #define M256(mem) (*((__m256i*)((Ipp8u*)(mem)))) #define M512(mem) (*((__m512i*)((Ipp8u*)(mem)))) static const __ALIGN64 Ipp64u POLY2[] = { 0x1, 0xC200000000000000, 0x1, 0xC200000000000000, 0x1, 0xC200000000000000, 0x1, 0xC200000000000000 }; static __ALIGN64 Ipp8u swapBytes[] = { 15,14,13,12, 11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 31,30,29,28, 27,26,25,24, 23,22,21,20, 19,18,17,16, 47,46,45,44, 43,42,41,40, 39,38,37,36, 35,34,33,32, 63,62,61,60, 59,58,57,56, 55,54,53,52, 51,50,49,48, }; /* The function performs careless Karatsuba multiplication of 4x128-bit blocks stored * in 512-bit inputs: * A = [A3 A2 A1 A0], B = [B3 B2 B1 B0] * Ai=[a1i:a0i] and Bi=[b1i:b0i], i=0..3 * and returns parts of the multiplication Hi, Mi and Li, i=0..3, where * Hi = a1i*b1i * Mi = (a1i^a0i)*(b1i^b0i) * Li = a0i*b0i * * NB: make sure unused parts of input registers are zeroed to avoid issues with further horizontal XOR. */ __IPPCP_INLINE void AesGcmKaratsubaMul4(const __m512i * const pA, /* A3 A2 A1 A0 */ const __m512i * const pHKeys, /* B3 B2 B1 B0 */ const __m512i * const pHKeysKaratsuba, /* precomputed (b1i^b0i) */ __m512i * const pH, __m512i * const pM, __m512i * const pL) { *pL = _mm512_clmulepi64_epi128(*pA, *pHKeys, 0x00); // L = [a0i*b0i] *pH = _mm512_clmulepi64_epi128(*pA, *pHKeys, 0x11); // H = [a1i*b1i] *pM = _mm512_shuffle_epi32(*pA, 78); // M = [a0i:a1i] *pM = _mm512_xor_epi32(*pM, *pA); // M = [a1i^a0i:a1i^a0i] *pM = _mm512_clmulepi64_epi128(*pM, *pHKeysKaratsuba, 0x00); // M = (a1i^a0i)*(b1i^b0i) } /* The function performs horizontal XOR for 4 128-bit values in 512-bit register 128-bit result value saved in the low part of the 512-bit register */ __IPPCP_INLINE void HXor4x128(const __m512i * const zmm, __m128i * const xmm) { __m256i ymm; ymm = _mm512_extracti64x4_epi64(*zmm, 0x1); // zmm = [3 2 1 0]; ymm = [3 2] ymm = _mm256_xor_si256(_mm512_castsi512_si256(*zmm), ymm); // ymm = [1^3 0^2] *xmm = _mm256_extracti32x4_epi32(ymm, 0x1); // xmm = [1^3] *xmm = _mm_maskz_xor_epi64(0xFF, _mm256_castsi256_si128(ymm), *xmm); } /* The function performs Montgomery reduction of 256-bit polynomial to 128-bit one with irreducible polynomial */ __IPPCP_INLINE void ReducePoly2x128(const __m128i * const pHI, const __m128i * const pLO, __m128i * const result) { __m256i tmp1, tmp2, HI, LO; HI = _mm256_set_m128i(_mm_setzero_si128(), *pHI); LO = _mm256_set_m128i(_mm_setzero_si128(), *pLO); tmp1 = _mm256_clmulepi64_epi128(LO, M256(POLY2), 0x10); tmp2 = _mm256_shuffle_epi32(LO, 78); // 78 = 01001110b LO = _mm256_xor_si256(tmp1, tmp2); tmp1 = _mm256_clmulepi64_epi128(LO, M256(POLY2), 0x10); tmp2 = _mm256_shuffle_epi32(LO, 78); // 78 = 01001110b LO = _mm256_xor_si256(tmp1, tmp2); tmp1 = _mm256_xor_si256(HI, LO); *result = _mm256_castsi256_si128(tmp1); } /* The function aggregates partial products of Karatsuba multiplication into final ghash value */ __IPPCP_INLINE void AggregateKaratsubaPartialProducts(const __m512i * const pH, const __m512i * const pM, const __m512i * const pL, __m128i * const result) { __m512i H, M, L; __m128i H128, L128; /* Aggregation step1 - combine multiplication results H,M,L into Hi and Lo 128-bit parts */ M = _mm512_xor_si512(*pM, *pH); M = _mm512_xor_si512(M, *pL); H = _mm512_bsrli_epi128(M, 8); H = _mm512_xor_si512(*pH, H); L = _mm512_bslli_epi128(M, 8); L = _mm512_xor_si512(*pL, L); /* Aggregation step2 - horizontal XOR for H, L*/ HXor4x128(&H, &H128); HXor4x128(&L, &L128); /* Reduction of 256-bit poly to 128-bit poly using irreducible polynomial */ ReducePoly2x128(&H128, &L128, result); } #endif /* #if (_IPP32E>=_IPP32E_K1) */ #endif /* _CP_AES_GCM_VAES512_H*/ #endif cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmauth_vaes512.c000066400000000000000000000177501470420105600256400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES authentication (GCM mode) // // Contents: // */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif #if 0 // Not used #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaes_gcm_vaes512.h" #include "pcpaesauthgcm.h" #if (_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // cast truncates constant value in MSVC #endif /* AES-GCM authentication function. It calculates GHASH of the source input */ IPP_OWN_DEFN (void, AesGcmAuth_vaes, (Ipp8u* pGHash, const Ipp8u* pSrc, int len, const Ipp8u* pHKey, const void* pParam)) { IPP_UNREFERENCED_PARAMETER(pParam); __m512i* pSrc512 = (__m512i*)pSrc; __m512i* pHKey512 = (__m512i*)pHKey; /* Load hKeys vectors */ __m512i hKeys0 = _mm512_loadu_si512(pHKey512); __m512i hKeys1 = _mm512_loadu_si512(pHKey512 + 1); __m512i hKeys2 = _mm512_loadu_si512(pHKey512 + 2); __m512i hKeys3 = _mm512_loadu_si512(pHKey512 + 3); /* Load precomputed multipliers for Karatsuba multiplication */ __m512i hKeysKaratsuba0 = _mm512_loadu_si512(pHKey512 + 4); __m512i hKeysKaratsuba1 = _mm512_loadu_si512(pHKey512 + 5); __m512i hKeysKaratsuba2 = _mm512_loadu_si512(pHKey512 + 6); __m512i hKeysKaratsuba3 = _mm512_loadu_si512(pHKey512 + 7); /* Current GHASH value */ __m128i ghash128; __m512i ghash512 = _mm512_maskz_loadu_epi64(0x03, pGHash); ghash512 = _mm512_shuffle_epi8(ghash512, M512(swapBytes)); int blocks; for (blocks = len / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i blk3 = _mm512_loadu_si512(pSrc512 + 3); /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); blk2 = _mm512_shuffle_epi8(blk2, M512(swapBytes)); blk3 = _mm512_shuffle_epi8(blk3, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); /* Karatsuba multiplication for 16 blocks with postponed aggregation */ __m512i H, M, L, tmp1, tmp2, tmp3; AesGcmKaratsubaMul4(&blk0, &hKeys3, &hKeysKaratsuba3, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys2, &hKeysKaratsuba2, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk2, &hKeys1, &hKeysKaratsuba1, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk3, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 4; } if ((3 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512+1); __m512i blk2 = _mm512_loadu_si512(pSrc512+2); /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); blk2 = _mm512_shuffle_epi8(blk2, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H, M, L, tmp1, tmp2, tmp3; AesGcmKaratsubaMul4(&blk0, &hKeys2, &hKeysKaratsuba2, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys1, &hKeysKaratsuba1, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk2, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 3; } if ((4 * 2) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512+1); /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H, M, L, tmp1, tmp2, tmp3; AesGcmKaratsubaMul4(&blk0, &hKeys1, &hKeysKaratsuba1, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 2; } for (; blocks >= 4; blocks -= 4) { __m512i blk0 = _mm512_loadu_si512(pSrc512); blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H, M, L; AesGcmKaratsubaMul4(&blk0, &hKeys0, &hKeysKaratsuba0, &H, &M, &L); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 1; } // at least one block left (max 3 blocks) if (blocks) { __mmask8 k8 = (__mmask8)((1 << (blocks + blocks)) - 1); // 64-bit chunks __m512i blk0 = _mm512_maskz_loadu_epi64(k8, pSrc512); blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H = _mm512_setzero_si512(); __m512i M = _mm512_setzero_si512(); __m512i L = _mm512_setzero_si512(); // NB: we need immediate parameter in alignr function switch (blocks) { case 1: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 6); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 6); break; } case 2: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 4); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 4); break; } default: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 2); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 2); } } AesGcmKaratsubaMul4(&blk0, &hKeys0, &hKeysKaratsuba0, &H, &M, &L); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); } ghash512 = _mm512_shuffle_epi8(ghash512, M512(swapBytes)); _mm512_mask_storeu_epi64(pGHash, 0x03, ghash512); } #endif /* #if (_IPP32E>=_IPP32E_K1) */ #endif cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmdecrypt.c000066400000000000000000000147541470420105600251040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMDecrypt() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_gcm_internal_func.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMDecrypt // // Purpose: Decrypts a data buffer in the GCM mode. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pState == NULL // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsLengthErr len<0 // ippStsNoErr no errors // // Parameters: // pSrc Pointer to ciphertext. // pDst Pointer to plaintext. // len Length of the plaintext and ciphertext in bytes // pState pointer to the context // *F*/ IPPFUN(IppStatus, ippsAES_GCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_GCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); /* test state ID */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* test context validity */ IPP_BADARG_RET(!(GcmAADprocessing==AESGCM_STATE(pState) || GcmTXTprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); /* test text pointers and length */ IPP_BAD_PTR2_RET(pSrc, pDst); IPP_BADARG_RET(len<0, ippStsLengthErr); /* According to the NIST Special Publication 800-38D (Recommendation for GCM * mode, p.5.2.1.1 Input Data) the input text shall be between 0 and 2^39-256 * bits. */ const Ipp64u MAX_TXT_LEN = ((Ipp64u)1 << 36) - 32; /* length in bytes */ IPP_BADARG_RET(((AESGCM_TXT_LEN(pState) > MAX_TXT_LEN - (Ipp64u)len) || ((AESGCM_TXT_LEN(pState) + (Ipp64u)len) < (Ipp64u)len)), ippStsScaleRangeErr); #if (_IPP32E < _IPP32E_K0) /* get method */ IppsAESSpec *pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); MulGcm_ hashFunc = AESGCM_HASH(pState); #endif if( GcmAADprocessing==AESGCM_STATE(pState) ) { #if(_IPP32E>=_IPP32E_K0) if(AESGCM_BUFLEN(pState)) { MulGcm_ ghashFunc = AES_GCM_GMUL(pState); ghashFunc(&AES_GCM_KEY_DATA(pState), AESGCM_GHASH(pState)); } #else /* complete AAD processing */ if(AESGCM_BUFLEN(pState)) hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); /* increment counter block */ IncrementCounter32(AESGCM_COUNTER(pState)); /* and encrypt counter */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif #endif /* #if(_IPP32E>=_IPP32E_K0) */ /* switch mode and init counters */ AESGCM_BUFLEN(pState) = 0; AESGCM_TXT_LEN(pState) = CONST_64(0); AESGCM_STATE(pState) = GcmTXTprocessing; } /* // process text (authenticate and decrypt) */ #if(_IPP32E>=_IPP32E_K0) condNoisedGCMDecryption(pSrc, pDst, len, pState); #else /* process partial block */ if(AESGCM_BUFLEN(pState)) { int locLen = IPP_MIN(len, BLOCK_SIZE-AESGCM_BUFLEN(pState)); /* authentication */ XorBlock(pSrc, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen); /* ctr decryption */ XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, locLen); AESGCM_BUFLEN(pState) += locLen; AESGCM_TXT_LEN(pState) += (Ipp64u)locLen; pSrc += locLen; pDst += locLen; len -= locLen; /* if buffer full */ if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { /* hash buffer */ hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); AESGCM_BUFLEN(pState) = 0; /* Inject the noise for the case of partial blocks processing */ #if (_AES_PROB_NOISE == _FEATURE_ON_) cpAESNoiseParams *params = (cpAESNoiseParams*)&AESGCM_NOISE_PARAMS(pState); if (AES_NOISE_LEVEL(params) > 0) cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); #endif /* increment counter block */ IncrementCounter32(AESGCM_COUNTER(pState)); /* and encrypt counter */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } } /* process the main part of text */ { int lenBlks = len & (-BLOCK_SIZE); if(lenBlks) { condNoisedGCMDecryption(pSrc, pDst, lenBlks, pState); AESGCM_TXT_LEN(pState) += (Ipp64u)lenBlks; pSrc += lenBlks; pDst += lenBlks; len -= lenBlks; } } /* process the rest of text */ if(len) { /* ctr encryption */ XorBlock(pSrc, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), len); XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, len); AESGCM_BUFLEN(pState) += len; AESGCM_TXT_LEN(pState) += (Ipp64u)len; } #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmdecrypt_vaes512.c000066400000000000000000000312501470420105600263400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES decryption (GCM mode) // // Contents: // */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif #if 0 // Not used #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaes_gcm_vaes512.h" #include "pcpaesauthgcm.h" #if (_IPP32E>=_IPP32E_K1) static __ALIGN64 Ipp32u inc_lo32x4[] = { 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 }; static __ALIGN64 Ipp32u inc1_lo32x4[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }; static __ALIGN64 Ipp32u inc4_lo32x4[] = { 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0 }; IPP_OWN_DEFN (void, AesGcmDec_vaes, (Ipp8u* pDst, const Ipp8u* pSrc, int length, IppsAES_GCMState* pCtx)) { IppsAESSpec* pAES = AESGCM_CIPHER(pCtx); int cipherRounds = RIJ_NR(pAES) - 1; const Ipp8u* pRKey = RIJ_EKEYS(pAES); Ipp8u* pCtrValue = AESGCM_COUNTER(pCtx); Ipp8u* pGHash = AESGCM_GHASH(pCtx); const Ipp8u* pHKey = AESGCM_HKEY(pCtx); __m128i* pKeys = (__m128i*)pRKey; __m512i* pSrc512 = (__m512i*)pSrc; __m512i* pDst512 = (__m512i*)pDst; __m512i* pHKey512 = (__m512i*)pHKey; __m512i incMsk = M512(inc_lo32x4); /* Load hKeys vectors */ __m512i hKeys0 = _mm512_loadu_si512(pHKey512); __m512i hKeys1 = _mm512_loadu_si512(pHKey512 + 1); __m512i hKeys2 = _mm512_loadu_si512(pHKey512 + 2); __m512i hKeys3 = _mm512_loadu_si512(pHKey512 + 3); /* Load precomputed multipliers for Karatsuba multiplication */ __m512i hKeysKaratsuba0 = _mm512_loadu_si512(pHKey512 + 4); __m512i hKeysKaratsuba1 = _mm512_loadu_si512(pHKey512 + 5); __m512i hKeysKaratsuba2 = _mm512_loadu_si512(pHKey512 + 6); __m512i hKeysKaratsuba3 = _mm512_loadu_si512(pHKey512 + 7); /* Current GHASH value */ __m128i ghash128; __m512i ghash512 = _mm512_maskz_loadu_epi64(0x03, pGHash); ghash512 = _mm512_shuffle_epi8(ghash512, M512(swapBytes)); /* Load initial counter */ __m128i ctr128 = _mm_maskz_loadu_epi64(0x03, pCtrValue); __m512i ctr512 = _mm512_broadcast_i64x2(ctr128); // convert counter to little-endian ctr512 = _mm512_shuffle_epi8(ctr512, M512(swapBytes)); int blocks; for (blocks = length / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { __m512i counter0 = _mm512_add_epi32(incMsk, ctr512); __m512i counter1 = _mm512_add_epi32(M512(inc4_lo32x4), counter0); __m512i counter2 = _mm512_add_epi32(M512(inc4_lo32x4), counter1); __m512i counter3 = _mm512_add_epi32(M512(inc4_lo32x4), counter2); incMsk = M512(inc4_lo32x4); ctr512 = counter3; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, M512(swapBytes)); counter2 = _mm512_shuffle_epi8(counter2, M512(swapBytes)); counter3 = _mm512_shuffle_epi8(counter3, M512(swapBytes)); cpAESEncrypt4_VAES_NI(&counter0, &counter1, &counter2, &counter3, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); __m512i blk3 = _mm512_loadu_si512(pSrc512 + 3); _mm512_storeu_si512(pDst512, _mm512_xor_si512(blk0, counter0)); _mm512_storeu_si512(pDst512 + 1, _mm512_xor_si512(blk1, counter1)); _mm512_storeu_si512(pDst512 + 2, _mm512_xor_si512(blk2, counter2)); _mm512_storeu_si512(pDst512 + 3, _mm512_xor_si512(blk3, counter3)); /* Authenticate */ /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); blk2 = _mm512_shuffle_epi8(blk2, M512(swapBytes)); blk3 = _mm512_shuffle_epi8(blk3, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); /* Karatsuba multiplication for 16 blocks with postponed aggregation */ __m512i H, M, L, tmp1, tmp2, tmp3; AesGcmKaratsubaMul4(&blk0, &hKeys3, &hKeysKaratsuba3, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys2, &hKeysKaratsuba2, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk2, &hKeys1, &hKeysKaratsuba1, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk3, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 4; pDst512 += 4; } if ((3 * 4) <= blocks) { __m512i counter0 = _mm512_add_epi32(incMsk, ctr512); __m512i counter1 = _mm512_add_epi32(M512(inc4_lo32x4), counter0); __m512i counter2 = _mm512_add_epi32(M512(inc4_lo32x4), counter1); incMsk = M512(inc4_lo32x4); ctr512 = counter2; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, M512(swapBytes)); counter2 = _mm512_shuffle_epi8(counter2, M512(swapBytes)); cpAESEncrypt3_VAES_NI(&counter0, &counter1, &counter2, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); __m512i blk2 = _mm512_loadu_si512(pSrc512 + 2); _mm512_storeu_si512(pDst512, _mm512_xor_si512(blk0, counter0)); _mm512_storeu_si512(pDst512 + 1, _mm512_xor_si512(blk1, counter1)); _mm512_storeu_si512(pDst512 + 2, _mm512_xor_si512(blk2, counter2)); /* Authenticate */ /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); blk2 = _mm512_shuffle_epi8(blk2, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); /* Karatsuba multiplication for 16 blocks with postponed aggregation */ __m512i H, M, L, tmp1, tmp2, tmp3; AesGcmKaratsubaMul4(&blk0, &hKeys3, &hKeysKaratsuba2, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys2, &hKeysKaratsuba1, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk2, &hKeys1, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 3; pDst512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { __m512i counter0 = _mm512_add_epi32(incMsk, ctr512); __m512i counter1 = _mm512_add_epi32(M512(inc4_lo32x4), counter0); incMsk = M512(inc4_lo32x4); ctr512 = counter1; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, M512(swapBytes)); cpAESEncrypt2_VAES_NI(&counter0, &counter1, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); __m512i blk1 = _mm512_loadu_si512(pSrc512 + 1); _mm512_storeu_si512(pDst512, _mm512_xor_si512(blk0, counter0)); _mm512_storeu_si512(pDst512 + 1, _mm512_xor_si512(blk1, counter1)); /* Authenticate */ /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H, M, L, tmp1, tmp2, tmp3; AesGcmKaratsubaMul4(&blk0, &hKeys1, &hKeysKaratsuba1, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 2; pDst512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { __m512i counter0 = _mm512_add_epi32(incMsk, ctr512); incMsk = M512(inc4_lo32x4); ctr512 = counter0; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); __m512i blk0 = _mm512_loadu_si512(pSrc512); _mm512_storeu_si512(pDst512, _mm512_xor_si512(blk0, counter0)); /* Authenticate */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H, M, L; AesGcmKaratsubaMul4(&blk0, &hKeys0, &hKeysKaratsuba0, &H, &M, &L); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 1; pDst512 += 1; } if (blocks) { __mmask8 k8 = (__mmask8)((1 << (blocks + blocks)) - 1); // 64-bit chunks __mmask16 k16 = (__mmask16)((1 << (blocks << 2)) - 1); // 32-bit chunks __mmask64 k64 = (__mmask64)((1LL << (blocks << 4)) - 1); // 8-bit chunks __m512i counter0 = _mm512_maskz_add_epi32(k16, incMsk, ctr512); ctr512 = counter0; // convert back to big-endian counter0 = _mm512_maskz_shuffle_epi8(k64, counter0, M512(swapBytes)); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); __m512i blk0 = _mm512_maskz_loadu_epi64(k8, pSrc512); _mm512_mask_storeu_epi64(pDst512, k8, _mm512_maskz_xor_epi64(k8, blk0, counter0)); /* Authenticate */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); __m512i H = _mm512_setzero_si512(); __m512i M = _mm512_setzero_si512(); __m512i L = _mm512_setzero_si512(); // NB: we need immediate parameter in alignr function switch (blocks) { case 1: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 6); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 6); break; } case 2: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 4); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 4); break; } default: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 2); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 2); } } AesGcmKaratsubaMul4(&blk0, &hKeys0, &hKeysKaratsuba0, &H, &M, &L); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); } // return last counter __mmask8 lastCtrK8 = blocks == 0 ? 0xC0 : (__mmask8)((Ipp8u)0x03<<((blocks-1)<<1)); __mmask16 lastCtrK16 = blocks == 0 ? 0xF000 : (__mmask16)((Ipp16u)0xF<<((blocks-1)<<2)); __mmask64 lastCtrK64 = blocks == 0 ? 0xFFFF000000000000 : (__mmask64)((Ipp64u)0xFFFF<<((blocks-1)<<4)); ctr512 = _mm512_maskz_add_epi32(lastCtrK16, M512(inc1_lo32x4), ctr512); ctr512 = _mm512_maskz_shuffle_epi8(lastCtrK64, ctr512, M512(swapBytes)); /* save next counter */ _mm512_mask_compressstoreu_epi64(pCtrValue, lastCtrK8, ctr512); /* save current ghash value */ ghash512 = _mm512_shuffle_epi8(ghash512, M512(swapBytes)); _mm512_mask_storeu_epi64(pGHash, 0x03, ghash512); } #endif #endif /* #if (_IPP32E>=_IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmencrypt.c000066400000000000000000000150711470420105600251070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMEncrypt() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_gcm_internal_func.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMEncrypt // // Purpose: Encrypts a data buffer in the GCM mode. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pState == NULL // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsLengthErr len<0 // ippStsNoErr no errors // // Parameters: // pSrc Pointer to plaintext. // pDst Pointer to ciphertext. // len Length of the plaintext and ciphertext in bytes // pState pointer to the context // *F*/ IPPFUN(IppStatus, ippsAES_GCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsAES_GCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); /* test state ID */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* test context validity */ IPP_BADARG_RET(!(GcmAADprocessing==AESGCM_STATE(pState) || GcmTXTprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); /* test text pointers and length */ IPP_BAD_PTR2_RET(pSrc, pDst); IPP_BADARG_RET(len<0, ippStsLengthErr); /* According to the NIST Special Publication 800-38D (Recommendation for GCM * mode, p.5.2.1.1 Input Data) the input text shall be between 0 and 2^39-256 * bits. */ const Ipp64u MAX_TXT_LEN = ((Ipp64u)1 << 36) - 32; /* length in bytes */ IPP_BADARG_RET(((AESGCM_TXT_LEN(pState) > MAX_TXT_LEN - (Ipp64u)len) || ((AESGCM_TXT_LEN(pState) + (Ipp64u)len) < (Ipp64u)len)), ippStsScaleRangeErr); #if(_IPP32E<_IPP32E_K0) /* get method */ IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); MulGcm_ hashFunc = AESGCM_HASH(pState); #endif if( GcmAADprocessing==AESGCM_STATE(pState) ) { #if(_IPP32E>=_IPP32E_K0) if(AESGCM_BUFLEN(pState)) { MulGcm_ ghashFunc = AES_GCM_GMUL(pState); ghashFunc(&AES_GCM_KEY_DATA(pState), AESGCM_GHASH(pState)); } #else /* complete AAD processing */ if(AESGCM_BUFLEN(pState)) hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); /* increment counter block */ IncrementCounter32(AESGCM_COUNTER(pState)); /* and encrypt counter */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif #endif /* #if(_IPP32E>=_IPP32E_K0) */ /* switch mode and init counters */ AESGCM_STATE(pState) = GcmTXTprocessing; AESGCM_TXT_LEN(pState) = CONST_64(0); AESGCM_BUFLEN(pState) = 0; } /* execute encryption with code from Intel IPsec if possible */ #if(_IPP32E>=_IPP32E_K0) condNoisedGCMEncryption(pSrc, pDst, len, pState); #else /* // process text (encrypt and authenticate) */ /* process partial block */ if(AESGCM_BUFLEN(pState)) { int locLen = IPP_MIN(len, BLOCK_SIZE-AESGCM_BUFLEN(pState)); /* ctr encryption */ XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, locLen); /* authentication */ XorBlock(pDst, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen); AESGCM_BUFLEN(pState) += locLen; AESGCM_TXT_LEN(pState) += (Ipp64u)locLen; pSrc += locLen; pDst += locLen; len -= locLen; /* if buffer full */ if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { /* hash buffer */ hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); AESGCM_BUFLEN(pState) = 0; /* Inject the noise for the case of partial blocks processing */ #if (_AES_PROB_NOISE == _FEATURE_ON_) cpAESNoiseParams *params = (cpAESNoiseParams*)&AESGCM_NOISE_PARAMS(pState); if (AES_NOISE_LEVEL(params) > 0) cpAESRandomNoise(NULL, MISTLETOE3_BASE_NOISE_LEVEL + AES_NOISE_LEVEL(params), MISTLETOE3_NOISE_RATE, &AES_NOISE_RAND(params)); #endif /* increment counter block */ IncrementCounter32(AESGCM_COUNTER(pState)); /* and encrypt counter */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } } /* process the main part of text */ { int lenBlks = len & (-BLOCK_SIZE); if(lenBlks) { condNoisedGCMEncryption(pSrc, pDst, lenBlks, pState); AESGCM_TXT_LEN(pState) += (Ipp64u)lenBlks; pSrc += lenBlks; pDst += lenBlks; len -= lenBlks; } } /* process the rest of text */ if(len) { XorBlock(pSrc, AESGCM_ECOUNTER(pState)+AESGCM_BUFLEN(pState), pDst, len); XorBlock(pDst, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), len); AESGCM_BUFLEN(pState) += len; AESGCM_TXT_LEN(pState) += (Ipp64u)len; } #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmencrypt_vaes512.c000077500000000000000000000313041470420105600263550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption (GCM mode) // // Contents: // */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif #if 0 // Not used #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaes_gcm_vaes512.h" #include "pcpaesauthgcm.h" #if (_IPP32E>=_IPP32E_K1) static __ALIGN64 Ipp32u inc_lo32x4[] = { 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0 }; static __ALIGN64 Ipp32u inc1_lo32x4[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 }; static __ALIGN64 Ipp32u inc4_lo32x4[] = { 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0 }; /* Encryption with authentication */ IPP_OWN_DEFN (void, AesGcmEnc_vaes, (Ipp8u* pDst, const Ipp8u* pSrc, int length, IppsAES_GCMState* pCtx)) { IppsAESSpec* pAES = AESGCM_CIPHER(pCtx); int cipherRounds = RIJ_NR(pAES) - 1; const Ipp8u* pRKey = RIJ_EKEYS(pAES); Ipp8u* pCtrValue = AESGCM_COUNTER(pCtx); Ipp8u* pGHash = AESGCM_GHASH(pCtx); const Ipp8u* pHKey = AESGCM_HKEY(pCtx); __m128i* pKeys = (__m128i*)pRKey; __m512i* pSrc512 = (__m512i*)pSrc; __m512i* pDst512 = (__m512i*)pDst; __m512i* pHKey512 = (__m512i*)pHKey; __m512i incMsk = M512(inc_lo32x4); __m512i H, M, L, tmp1, tmp2, tmp3; __m512i counter0, counter1, counter2, counter3; __m512i blk0, blk1, blk2, blk3; /* Load hKeys vectors */ __m512i hKeys0 = _mm512_loadu_si512(pHKey512); __m512i hKeys1 = _mm512_loadu_si512(pHKey512 + 1); __m512i hKeys2 = _mm512_loadu_si512(pHKey512 + 2); __m512i hKeys3 = _mm512_loadu_si512(pHKey512 + 3); /* Load precomputed multipliers for Karatsuba multiplication */ __m512i hKeysKaratsuba0 = _mm512_loadu_si512(pHKey512 + 4); __m512i hKeysKaratsuba1 = _mm512_loadu_si512(pHKey512 + 5); __m512i hKeysKaratsuba2 = _mm512_loadu_si512(pHKey512 + 6); __m512i hKeysKaratsuba3 = _mm512_loadu_si512(pHKey512 + 7); /* Current GHASH value */ __m128i ghash128; __m512i ghash512 = _mm512_maskz_loadu_epi64(0x03, pGHash); ghash512 = _mm512_shuffle_epi8(ghash512, M512(swapBytes)); /* Load initial counter */ __m128i ctr128 = _mm_maskz_loadu_epi64(0x03, pCtrValue); __m512i ctr512 = _mm512_broadcast_i64x2(ctr128); // convert counter to little-endian ctr512 = _mm512_shuffle_epi8(ctr512, M512(swapBytes)); int blocks; for (blocks = length / MBS_RIJ128; blocks >= (4 * 4); blocks -= (4 * 4)) { counter0 = _mm512_add_epi32(incMsk, ctr512); counter1 = _mm512_add_epi32(M512(inc4_lo32x4), counter0); counter2 = _mm512_add_epi32(M512(inc4_lo32x4), counter1); counter3 = _mm512_add_epi32(M512(inc4_lo32x4), counter2); incMsk = M512(inc4_lo32x4); ctr512 = counter3; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, M512(swapBytes)); counter2 = _mm512_shuffle_epi8(counter2, M512(swapBytes)); counter3 = _mm512_shuffle_epi8(counter3, M512(swapBytes)); cpAESEncrypt4_VAES_NI(&counter0, &counter1, &counter2, &counter3, pKeys, cipherRounds); blk0 = _mm512_loadu_si512(pSrc512); blk1 = _mm512_loadu_si512(pSrc512 + 1); blk2 = _mm512_loadu_si512(pSrc512 + 2); blk3 = _mm512_loadu_si512(pSrc512 + 3); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); blk2 = _mm512_xor_si512(blk2, counter2); blk3 = _mm512_xor_si512(blk3, counter3); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); _mm512_storeu_si512(pDst512 + 3, blk3); /* Authenticate */ /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); blk2 = _mm512_shuffle_epi8(blk2, M512(swapBytes)); blk3 = _mm512_shuffle_epi8(blk3, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); /* Karatsuba multiplication for 16 blocks with postponed aggregation */ AesGcmKaratsubaMul4(&blk0, &hKeys3, &hKeysKaratsuba3, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys2, &hKeysKaratsuba2, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk2, &hKeys1, &hKeysKaratsuba1, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk3, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 4; pDst512 += 4; } if ((3 * 4) <= blocks) { counter0 = _mm512_add_epi32(incMsk, ctr512); counter1 = _mm512_add_epi32(M512(inc4_lo32x4), counter0); counter2 = _mm512_add_epi32(M512(inc4_lo32x4), counter1); incMsk = M512(inc4_lo32x4); ctr512 = counter2; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, M512(swapBytes)); counter2 = _mm512_shuffle_epi8(counter2, M512(swapBytes)); cpAESEncrypt3_VAES_NI(&counter0, &counter1, &counter2, pKeys, cipherRounds); blk0 = _mm512_loadu_si512(pSrc512); blk1 = _mm512_loadu_si512(pSrc512 + 1); blk2 = _mm512_loadu_si512(pSrc512 + 2); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); blk2 = _mm512_xor_si512(blk2, counter2); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); _mm512_storeu_si512(pDst512 + 2, blk2); /* Authenticate */ /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); blk2 = _mm512_shuffle_epi8(blk2, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); /* Karatsuba multiplication for 16 blocks with postponed aggregation */ AesGcmKaratsubaMul4(&blk0, &hKeys3, &hKeysKaratsuba2, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys2, &hKeysKaratsuba1, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AesGcmKaratsubaMul4(&blk2, &hKeys1, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 3; pDst512 += 3; blocks -= (3 * 4); } if ((4 * 2) <= blocks) { counter0 = _mm512_add_epi32(incMsk, ctr512); counter1 = _mm512_add_epi32(M512(inc4_lo32x4), counter0); incMsk = M512(inc4_lo32x4); ctr512 = counter1; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); counter1 = _mm512_shuffle_epi8(counter1, M512(swapBytes)); cpAESEncrypt2_VAES_NI(&counter0, &counter1, pKeys, cipherRounds); blk0 = _mm512_loadu_si512(pSrc512); blk1 = _mm512_loadu_si512(pSrc512 + 1); blk0 = _mm512_xor_si512(blk0, counter0); blk1 = _mm512_xor_si512(blk1, counter1); _mm512_storeu_si512(pDst512, blk0); _mm512_storeu_si512(pDst512 + 1, blk1); /* Authenticate */ /* Reflect inputs */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); blk1 = _mm512_shuffle_epi8(blk1, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); AesGcmKaratsubaMul4(&blk0, &hKeys1, &hKeysKaratsuba1, &H, &M, &L); AesGcmKaratsubaMul4(&blk1, &hKeys0, &hKeysKaratsuba0, &tmp1, &tmp2, &tmp3); H = _mm512_xor_si512(H, tmp1); M = _mm512_xor_si512(M, tmp2); L = _mm512_xor_si512(L, tmp3); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 2; pDst512 += 2; blocks -= (2 * 4); } for (; blocks >= 4; blocks -= 4) { counter0 = _mm512_add_epi32(incMsk, ctr512); incMsk = M512(inc4_lo32x4); ctr512 = counter0; // convert back to big-endian counter0 = _mm512_shuffle_epi8(counter0, M512(swapBytes)); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); blk0 = _mm512_loadu_si512(pSrc512); blk0 = _mm512_xor_si512(blk0, counter0); _mm512_storeu_si512(pDst512, blk0); /* Authenticate */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); AesGcmKaratsubaMul4(&blk0, &hKeys0, &hKeysKaratsuba0, &H, &M, &L); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); pSrc512 += 1; pDst512 += 1; } if (blocks) { __mmask8 k8 = (__mmask8)((1 << (blocks + blocks)) - 1); // 64-bit chunks __mmask16 k16 = (__mmask16)((1 << (blocks << 2)) - 1); // 32-bit chunks __mmask64 k64 = (__mmask64)((1LL << (blocks << 4)) - 1); // 8-bit chunks counter0 = _mm512_maskz_add_epi32(k16, incMsk, ctr512); ctr512 = counter0; // convert back to big-endian counter0 = _mm512_maskz_shuffle_epi8(k64, counter0, M512(swapBytes)); cpAESEncrypt1_VAES_NI(&counter0, pKeys, cipherRounds); blk0 = _mm512_maskz_loadu_epi64(k8, pSrc512); blk0 = _mm512_maskz_xor_epi64(k8, blk0, counter0); _mm512_mask_storeu_epi64(pDst512, k8, blk0); /* Authenticate */ blk0 = _mm512_shuffle_epi8(blk0, M512(swapBytes)); /* Add current GHASH to src[0] */ blk0 = _mm512_mask_xor_epi64(blk0, 0x03, blk0, ghash512); H = _mm512_setzero_si512(); M = _mm512_setzero_si512(); L = _mm512_setzero_si512(); // NB: we need immediate parameter in alignr function switch (blocks) { case 1: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 6); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 6); break; } case 2: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 4); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 4); break; } default: { hKeys0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeys0, 2); hKeysKaratsuba0 = _mm512_alignr_epi64(_mm512_setzero_si512(), hKeysKaratsuba0, 2); } } AesGcmKaratsubaMul4(&blk0, &hKeys0, &hKeysKaratsuba0, &H, &M, &L); AggregateKaratsubaPartialProducts(&H, &M, &L, &ghash128); /* save current ghash value */ ghash512 = _mm512_castsi128_si512(ghash128); } // return last counter __mmask8 lastCtrK8 = blocks == 0 ? 0xC0 : (__mmask8)((Ipp8u)0x03<<((blocks-1)<<1)); __mmask16 lastCtrK16 = blocks == 0 ? 0xF000 : (__mmask16)((Ipp16u)0xF<<((blocks-1)<<2)); __mmask64 lastCtrK64 = blocks == 0 ? 0xFFFF000000000000 : (__mmask64)((Ipp64u)0xFFFF<<((blocks-1)<<4)); ctr512 = _mm512_maskz_add_epi32(lastCtrK16, M512(inc1_lo32x4), ctr512); ctr512 = _mm512_maskz_shuffle_epi8(lastCtrK64, ctr512, M512(swapBytes)); /* save next counter */ _mm512_mask_compressstoreu_epi64(pCtrValue, lastCtrK8, ctr512); /* save current ghash value */ ghash512 = _mm512_shuffle_epi8(ghash512, M512(swapBytes)); _mm512_mask_storeu_epi64(pGHash, 0x03, ghash512); } #endif #endif /* #if (_IPP32E>=_IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmgetsize.c000066400000000000000000000030121470420105600250650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMGetSize // // Purpose: Returns size of AES_GCM state (in bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to size of context // *F*/ IPPFUN(IppStatus, ippsAES_GCMGetSize,(int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = cpSizeofCtx_AESGCM(); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmgettag.c000066400000000000000000000065401470420105600246770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMGetTag() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMGetTag // // Purpose: Generates authentication tag in the GCM mode. // // Returns: Reason: // ippStsNullPtrErr pDstTag == NULL // pState == NULL // ippStsLengthErr tagLen<=0 || tagLen>16 // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsNoErr no errors // // Parameters: // pDstTag pointer to the authentication tag. // tagLen length of the authentication tag *pDstTag in bytes // pState pointer to the context // *F*/ IPPFUN(IppStatus, ippsAES_GCMGetTag,(Ipp8u* pDstTag, int tagLen, const IppsAES_GCMState* pState)) { /* test State pointer */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); /* test state ID */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* test tag pointer and length */ IPP_BAD_PTR1_RET(pDstTag); IPP_BADARG_RET(tagLen<=0 || tagLen>BLOCK_SIZE, ippStsLengthErr); #if(_IPP32E>=_IPP32E_K0) GetTag_ getTag = AES_GCM_GET_TAG(pState); getTag(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pDstTag, (Ipp64u)tagLen); #else /* get method */ MulGcm_ hashFunc = AESGCM_HASH(pState); __ALIGN16 Ipp8u tmpHash[BLOCK_SIZE]; Ipp8u tmpCntr[BLOCK_SIZE]; /* local copy of AAD and text counters (in bits) */ Ipp64u aadBitLen = AESGCM_AAD_LEN(pState)*BYTESIZE; Ipp64u txtBitLen = AESGCM_TXT_LEN(pState)*BYTESIZE; /* do local copy of ghash */ CopyBlock16(AESGCM_GHASH(pState), tmpHash); /* complete text processing */ if(AESGCM_BUFLEN(pState)) { hashFunc(tmpHash, AESGCM_HKEY(pState), AesGcmConst_table); } /* process lengths of AAD and text */ U32_TO_HSTRING(tmpCntr, IPP_HIDWORD(aadBitLen)); U32_TO_HSTRING(tmpCntr+4, IPP_LODWORD(aadBitLen)); U32_TO_HSTRING(tmpCntr+8, IPP_HIDWORD(txtBitLen)); U32_TO_HSTRING(tmpCntr+12,IPP_LODWORD(txtBitLen)); XorBlock16(tmpHash, tmpCntr, tmpHash); hashFunc(tmpHash, AESGCM_HKEY(pState), AesGcmConst_table); /* add encrypted initial counter */ XorBlock16(tmpHash, AESGCM_ECOUNTER0(pState), tmpHash); /* return tag of required length */ CopyBlock(tmpHash, pDstTag, tagLen); #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcminit.c000066400000000000000000000134421470420105600243660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMInit() // */ #include "aes_gcm_avx512.h" #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_gcm_internal_func.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #include "aes_keyexp.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMInit // // Purpose: Init AES_GCM context for future usage. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsMemAllocErr size of buffer is not match for operation // ippStsLengthErr keyLen != 16 && // != 24 && // != 32 // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length of secret key // pState pointer to the AES-GCM context // ctxSize available size (in bytes) of buffer above // *F*/ IPPFUN(IppStatus, ippsAES_GCMInit,(const Ipp8u* pKey, int keyLen, IppsAES_GCMState* pState, int ctxSize)) { /* test pCtx pointer */ IPP_BAD_PTR1_RET(pState); /* test available size of context buffer */ IPP_BADARG_RET(ctxSize=_IPP32E_K0) AES_GCM_KEY_LEN(pState) = (Ipp64u)keyLen; Ipp8u zeroKey[32] = {0}; const Ipp8u* pActualKey = pKey? pKey : zeroKey; #if (_AES_PROB_NOISE == _FEATURE_ON_) /* Reset AES noise parameters */ cpAESNoiseParams *params = (cpAESNoiseParams *)&AESGCM_NOISE_PARAMS(pState); AES_NOISE_RAND(params) = 0; AES_NOISE_LEVEL(params) = 0; #endif if (IsFeatureEnabled(ippCPUID_AVX512VAES) && IsFeatureEnabled(ippCPUID_AVX512VCLMUL)) { switch AES_GCM_KEY_LEN(pState) { case 16: aes_keyexp_128_enc(pActualKey, &AES_GCM_KEY_DATA(pState)); aes_gcm_precomp_128_vaes_avx512(&AES_GCM_KEY_DATA(pState)); break; case 24: aes_keyexp_192_enc(pActualKey, &AES_GCM_KEY_DATA(pState)); aes_gcm_precomp_192_vaes_avx512(&AES_GCM_KEY_DATA(pState)); break; case 32: aes_keyexp_256_enc(pActualKey, &AES_GCM_KEY_DATA(pState)); aes_gcm_precomp_256_vaes_avx512(&AES_GCM_KEY_DATA(pState)); break; } } else { switch AES_GCM_KEY_LEN(pState) { case 16: aes_keyexp_128_enc(pActualKey, &AES_GCM_KEY_DATA(pState)); aes_gcm_precomp_128_avx512(&AES_GCM_KEY_DATA(pState)); break; case 24: aes_keyexp_192_enc(pActualKey, &AES_GCM_KEY_DATA(pState)); aes_gcm_precomp_192_avx512(&AES_GCM_KEY_DATA(pState)); break; case 32: aes_keyexp_256_enc(pActualKey, &AES_GCM_KEY_DATA(pState)); aes_gcm_precomp_256_avx512(&AES_GCM_KEY_DATA(pState)); break; } } #else /* init cipher */ { IppStatus sts = ippsAESInit(pKey, keyLen, AESGCM_CIPHER(pState), cpSizeofCtx_AES()); if(ippStsNoErr!=sts) return sts; } /* precomputations (for constant multiplier(s)) */ { IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); /* multiplier c = Enc({0}) */ PadBlock(0, AESGCM_HKEY(pState), BLOCK_SIZE); //encoder((Ipp32u*)AESGCM_HKEY(pState), (Ipp32u*)AESGCM_HKEY(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(AESGCM_HKEY(pState), AESGCM_HKEY(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(AESGCM_HKEY(pState), AESGCM_HKEY(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } #if (_IPP >=_IPP_H9) || (_IPP32E>=_IPP32E_L9) if (IsFeatureEnabled(ippCPUID_AVX2VAES|ippCPUID_AVX2VCLMUL)) { AesGcmPrecompute_avx2_vaes(AESGCM_CPWR(pState), AESGCM_HKEY(pState)); } else #endif /* #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(IsFeatureEnabled(ippCPUID_AES|ippCPUID_CLMUL)) { /* pre-compute reflect(hkey) and hKey<<1, (hKey<<1)^2 and (hKey<<1)^4 powers of hKey */ AesGcmPrecompute_avx(AESGCM_CPWR(pState), AESGCM_HKEY(pState)); } else #endif /* #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) */ AesGcmPrecompute_table2K(AES_GCM_MTBL(pState), AESGCM_HKEY(pState)); #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmmul_vaes512.c000066400000000000000000000204331470420105600254640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES GFMUL and GHASH (GCM mode) // // Contents: // */ #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4206) // empty translation unit in MSVC #endif #if 0 // Not used #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaes_gcm_vaes512.h" #include "pcpaesauthgcm.h" #if (_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // cast truncates constant value in MSVC #endif /* The function calculates multiplication of two 2x128-bit polynomials C = A*B with polynomial reduction. 2 polynomials can be processed at one call. The inputs are bit-reflected. The result is bit-reflected. */ __IPPCP_INLINE void AesGcmGhash2(const __m256i* const src1, const __m256i* const src2, __m256i * const result) { __m256i tmp1, tmp2, tmp3, tmp4; #if 0 /* School-book multiplication */ tmp1 = _mm256_clmulepi64_epi128(src2, src1, 0x00); // [C1:C0] tmp2 = _mm256_clmulepi64_epi128(src2, src1, 0x11); // [D1:D0] tmp3 = _mm256_clmulepi64_epi128(src2, src1, 0x10); // [F1:F0] tmp4 = _mm256_clmulepi64_epi128(src2, src1, 0x01); // [E1:E0] tmp3 = _mm256_xor_si256(tmp4, tmp3); tmp4 = _mm256_bslli_epi128(tmp3, 8); tmp3 = _mm256_bsrli_epi128(tmp3, 8); tmp1 = _mm256_xor_si256(tmp4, tmp1); tmp4 = _mm256_xor_si256(tmp3, tmp2); #endif /* Karatsuba multiplication */ tmp1 = _mm256_clmulepi64_epi128(*src2, *src1, 0x00); tmp4 = _mm256_clmulepi64_epi128(*src2, *src1, 0x11); tmp2 = _mm256_shuffle_epi32(*src2, 78); // 78 = 01001110b tmp3 = _mm256_shuffle_epi32(*src1, 78); // 78 = 01001110b tmp2 = _mm256_xor_si256(tmp2, *src2); tmp3 = _mm256_xor_si256(tmp3, *src1); tmp2 = _mm256_clmulepi64_epi128(tmp2, tmp3, 0x00); tmp2 = _mm256_xor_si256(tmp2, tmp1); tmp2 = _mm256_xor_si256(tmp2, tmp4); tmp3 = _mm256_bslli_epi128(tmp2, 8); tmp2 = _mm256_bsrli_epi128(tmp2, 8); tmp1 = _mm256_xor_si256(tmp1, tmp3); tmp4 = _mm256_xor_si256(tmp4, tmp2); /* Montgomery reduction */ tmp2 = _mm256_clmulepi64_epi128(tmp1, M256(POLY2), 0x10); tmp3 = _mm256_shuffle_epi32(tmp1, 78); // 78 = 01001110b tmp1 = _mm256_xor_si256(tmp2, tmp3); tmp2 = _mm256_clmulepi64_epi128(tmp1, M256(POLY2), 0x10); tmp3 = _mm256_shuffle_epi32(tmp1, 78); // 78 = 01001110b tmp1 = _mm256_xor_si256(tmp2, tmp3); *result = _mm256_xor_si256(tmp1, tmp4); } /* The function calculates multiplication of two 128-bit polynomials C = A*B with polynomial reduction. The inputs are bit-reflected. The result is bit-reflected. */ __IPPCP_INLINE void AesGcmGhash(const __m128i* const a, const __m128i* const b, __m128i * const result) { __m256i res256; __m256i src1 = _mm256_set_m128i(_mm_setzero_si128(), *a); __m256i src2 = _mm256_set_m128i(_mm_setzero_si128(), *b); AesGcmGhash2(&src1, &src2, &res256); *result = _mm256_castsi256_si128(res256); } /* The function calculates multiplication of 128-bit polynomials C = A*B with polynomial reduction. 4 polynomials can be processed at one call. The inputs are bit-reflected. The result is bit-reflected. */ __IPPCP_INLINE void AesGcmGhash4(const __m512i* const src1, const __m512i* const src2, __m512i * const result) { __m512i tmp1, tmp2, tmp3, tmp4; /* Karatsuba multiplication */ tmp1 = _mm512_clmulepi64_epi128(*src2, *src1, 0x00); tmp4 = _mm512_clmulepi64_epi128(*src2, *src1, 0x11); tmp2 = _mm512_shuffle_epi32(*src2, 78); // 78 = 01001110b tmp3 = _mm512_shuffle_epi32(*src1, 78); // 78 = 01001110b tmp2 = _mm512_xor_si512(tmp2, *src2); tmp3 = _mm512_xor_si512(tmp3, *src1); tmp2 = _mm512_clmulepi64_epi128(tmp2, tmp3, 0x00); tmp2 = _mm512_xor_si512(tmp2, tmp1); tmp2 = _mm512_xor_si512(tmp2, tmp4); tmp3 = _mm512_bslli_epi128(tmp2, 8); tmp2 = _mm512_bsrli_epi128(tmp2, 8); tmp1 = _mm512_xor_si512(tmp1, tmp3); tmp4 = _mm512_xor_si512(tmp4, tmp2); /* Montgomery reduction */ tmp2 = _mm512_clmulepi64_epi128(tmp1, M512(POLY2), 0x10); tmp3 = _mm512_shuffle_epi32(tmp1, 78); // 78 = 01001110b tmp1 = _mm512_xor_si512(tmp2, tmp3); tmp2 = _mm512_clmulepi64_epi128(tmp1, M512(POLY2), 0x10); tmp3 = _mm512_shuffle_epi32(tmp1, 78); // 78 = 01001110b tmp1 = _mm512_xor_si512(tmp2, tmp3); *result = _mm512_xor_si512(tmp1, tmp4); } /* The function performs single A*(Hash<<1 mod poly) multiplication */ IPP_OWN_DEFN (void, AesGcmMulGcm_vaes, (Ipp8u* pGHash, const Ipp8u* pHKey, const void * pParam)) { IPP_UNREFERENCED_PARAMETER(pParam); __m128i ghash = _mm_maskz_loadu_epi64(0x03, pGHash); __m128i hkey = _mm_maskz_loadu_epi64(0x03, pHKey + 16*3); // NB: hKey is at index 3 in the array ghash = _mm_maskz_shuffle_epi8((Ipp16u)(-1), ghash, M128(swapBytes)); AesGcmGhash(&ghash, &hkey, &ghash); ghash = _mm_maskz_shuffle_epi8((Ipp16u)(-1), ghash, M128(swapBytes)); _mm_mask_storeu_epi64(pGHash, (Ipp8u)(-1), ghash); } /* The function computes reflected hKey<<1, hKey^2<<1, hKey^3<<1, ..., hKey^16<<1 - all mod poly * to use in batch GHASH calculation. * It also pre-computes parts of Karatsuba multipliers that are fixed and derived from the hKey. */ IPP_OWN_DEFN (void, AesGcmPrecompute_vaes, (Ipp8u* const pHtbl, const Ipp8u* const hKey)) { /* Initial hKey = E_ctr(key, 0^16) */ __m128i* pDst = (__m128i*)pHtbl; __m128i xmm0, xmm1; __m256i ymm0, ymm1, ymm3, ymm4, ymm5; __m512i zmm0, zmm1, zmm2; /* Load initial hKey = E_ctr(key,0^16) */ ymm0 = _mm256_maskz_loadu_epi64(0x03, hKey); /* Reflect hKey */ ymm0 = _mm256_shuffle_epi8(ymm0, M256(swapBytes)); /* Compute reflected hKey<<1 mod poly */ ymm3 = _mm256_srai_epi32(ymm0, 31); ymm3 = _mm256_shuffle_epi32(ymm3, 0xFF); ymm5 = _mm256_and_si256(ymm3, M256(POLY2)); ymm3 = _mm256_srli_epi32(ymm0, 31); ymm4 = _mm256_slli_epi32(ymm0, 1); ymm3 = _mm256_bslli_epi128(ymm3, 4); ymm0 = _mm256_xor_si256(ymm4, ymm3); ymm0 = _mm256_xor_si256(ymm0,ymm5); xmm0 = _mm256_castsi256_si128(ymm0); AesGcmGhash(&xmm0, &xmm0, &xmm1); /* xmm1 = hKey^2 */ ymm0 = _mm256_broadcast_i64x2(xmm1); /* ymm0 = hKey^2 hKey^2 */ ymm1 = _mm256_set_m128i(xmm0, xmm1); /* ymm1 = hKey hKey^2 */ AesGcmGhash2(&ymm0, &ymm1, &ymm0); /* ymm0 = hKey^3 hKey^4 */ xmm1 = _mm256_extracti64x2_epi64(ymm0, 0); /* xmm1 = hKey^4 */ zmm0 = _mm512_setzero_si512(); zmm0 = _mm512_inserti64x4(zmm0, ymm1, 1); /* zmm0 = hKey hKey^2 0 0 */ zmm0 = _mm512_inserti64x4(zmm0, ymm0, 0); /* zmm0 = hKey hKey^2 hKey^3 hKey^4 */ zmm1 = _mm512_broadcast_i64x2(xmm1); /* zmm1 = hKey^4 hKey^4 hKey^4 hKey^4 */ /* Store 4xhKey<<1 mod poly degrees in precompute table */ _mm512_storeu_si512(pDst, zmm0); /* Prepare constant multipliers for Karatsuba (Bh^Bl) */ zmm2 = _mm512_shuffle_epi32(zmm0, 78); zmm2 = _mm512_xor_si512(zmm0, zmm2); _mm512_storeu_si512(pDst + 16, zmm2); for (int i = 1; i < 4; i++) { AesGcmGhash4(&zmm0, &zmm1, &zmm0); /* Store 4xhKey<<1 mod poly degrees in precompute table */ _mm512_storeu_si512(pDst + 4*i, zmm0); /* Prepare constant multipliers for Karatsuba (Bh^Bl) */ zmm2 = _mm512_shuffle_epi32(zmm0, 78); zmm2 = _mm512_xor_si512(zmm0, zmm2); _mm512_storeu_si512(pDst + 4*i + 16, zmm2); } } #endif /* #if (_IPP32E>=_IPP32E_K1) */ #endif cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmprocessaad.c000066400000000000000000000171301470420105600255450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMProcessAAD() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMProcessAAD // // Purpose: AAD processing. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pAAD == NULL, aadLen>0 // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsLengthErr aadLen <0 // ippStsBadArgErr illegal sequence call // ippStsNoErr no errors // // Parameters: // pAAD pointer to the AAD // aadlen length of AAD (it could be 0) // pState pointer to the context // *F*/ IPPFUN(IppStatus, ippsAES_GCMProcessAAD,(const Ipp8u* pAAD, int aadLen, IppsAES_GCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); /* test if context is valid */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* test AAD pointer and length */ IPP_BADARG_RET(aadLen && !pAAD, ippStsNullPtrErr); IPP_BADARG_RET(aadLen<0, ippStsLengthErr); /* According to the NIST Special Publication 800-38D (Recommendation for GCM * mode, p.5.2.1.1 Input Data) the AAD shall be between 0 and 2^64 bits. */ IPP_BADARG_RET(((AESGCM_AAD_LEN(pState) + (Ipp64u)aadLen) < (Ipp64u)aadLen), ippStsScaleRangeErr); IPP_BADARG_RET(!(GcmIVprocessing==AESGCM_STATE(pState) || GcmAADprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); if( GcmIVprocessing==AESGCM_STATE(pState) ) { IPP_BADARG_RET(0==AESGCM_IV_LEN(pState), ippStsBadArgErr); #if(_IPP32E>=_IPP32E_K0) IvFinalize_ ivHashFinalize = AES_GCM_IV_FINALIZE(pState); /* complete IV processing */ ivHashFinalize(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), AESGCM_COUNTER(pState), (Ipp64u)AESGCM_BUFLEN(pState), AESGCM_IV_LEN(pState)); #else /* complete IV processing */ if(CTR_POS==AESGCM_IV_LEN(pState)) { /* apply special format if IV length is 12 bytes */ AESGCM_COUNTER(pState)[12] = 0; AESGCM_COUNTER(pState)[13] = 0; AESGCM_COUNTER(pState)[14] = 0; AESGCM_COUNTER(pState)[15] = 1; } else { /* get method */ MulGcm_ hashFunc = AESGCM_HASH(pState); /* process the rest of IV */ if(AESGCM_BUFLEN(pState)) hashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table); /* add IV bit length */ { Ipp64u ivBitLen = AESGCM_IV_LEN(pState)*BYTESIZE; Ipp8u tmp[BLOCK_SIZE]; PadBlock(0, tmp, BLOCK_SIZE-8); U32_TO_HSTRING(tmp+8, IPP_HIDWORD(ivBitLen)); U32_TO_HSTRING(tmp+12, IPP_LODWORD(ivBitLen)); XorBlock16(tmp, AESGCM_COUNTER(pState), AESGCM_COUNTER(pState)); hashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table); } } /* prepare initial counter */ { IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); //encoder((Ipp32u*)AESGCM_COUNTER(pState), (Ipp32u*)AESGCM_ECOUNTER0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(AESGCM_COUNTER(pState), AESGCM_ECOUNTER0(pState), RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } #endif /* #if(_IPP32E>=_IPP32E_K0) */ /* switch mode and init counters */ AESGCM_STATE(pState) = GcmAADprocessing; AESGCM_AAD_LEN(pState) = CONST_64(0); AESGCM_BUFLEN(pState) = 0; } /* // AAD processing */ #if(_IPP32E>=_IPP32E_K0) /* test if buffer is not empty */ if(AESGCM_BUFLEN(pState)) { /* Cast to int here does not produce loss of data as AESGCM_BUFLEN <= BLOCK_SIZE, which is 16 bytes */ int bufCapacity = BLOCK_SIZE-(int)AESGCM_BUFLEN(pState); int locLen = IPP_MIN(aadLen, bufCapacity); XorBlockMirror(pAAD, AESGCM_GHASH(pState), AESGCM_GHASH(pState), bufCapacity, locLen); AESGCM_BUFLEN(pState) += (Ipp64u)locLen; /* if buffer full */ if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { MulGcm_ ghashFunc = AES_GCM_GMUL(pState); ghashFunc(&AES_GCM_KEY_DATA(pState), AESGCM_GHASH(pState)); AESGCM_BUFLEN(pState) = 0; } AESGCM_AAD_LEN(pState) += (Ipp64u)locLen; pAAD += locLen; aadLen -= locLen; } /* process main part of AAD */ int lenBlks = aadLen & (-BLOCK_SIZE); if(lenBlks) { AadUpdate_ aadHashUpdate = AES_GCM_AAD_UPDATE(pState); aadHashUpdate(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pAAD, (Ipp64u)lenBlks); AESGCM_AAD_LEN(pState) += (Ipp64u)lenBlks; pAAD += lenBlks; aadLen -= lenBlks; } /* copy the rest of AAD into the buffer */ if(aadLen) { /* Note: GHASH in the IPsec context is byte-reflected */ XorBlockMirror(pAAD, AESGCM_GHASH(pState), AESGCM_GHASH(pState), BLOCK_SIZE, aadLen); AESGCM_AAD_LEN(pState) += (Ipp64u)aadLen; AESGCM_BUFLEN(pState) = (Ipp64u)aadLen; } #else /* test if buffer is not empty */ if(AESGCM_BUFLEN(pState)) { int locLen = IPP_MIN(aadLen, BLOCK_SIZE-AESGCM_BUFLEN(pState)); XorBlock(pAAD, AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), AESGCM_GHASH(pState)+AESGCM_BUFLEN(pState), locLen); AESGCM_BUFLEN(pState) += locLen; /* if buffer full */ if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { MulGcm_ hashFunc = AESGCM_HASH(pState); hashFunc(AESGCM_GHASH(pState), AESGCM_HKEY(pState), AesGcmConst_table); AESGCM_BUFLEN(pState) = 0; } AESGCM_AAD_LEN(pState) += (Ipp64u)locLen; pAAD += locLen; aadLen -= locLen; } /* process main part of AAD */ { int lenBlks = aadLen & (-BLOCK_SIZE); if(lenBlks) { Auth_ authFunc = AESGCM_AUTH(pState); authFunc(AESGCM_GHASH(pState), pAAD, lenBlks, AESGCM_HKEY(pState), AesGcmConst_table); AESGCM_AAD_LEN(pState) += (Ipp64u)lenBlks; pAAD += lenBlks; aadLen -= lenBlks; } } /* copy the rest of AAD into the buffer */ if(aadLen) { int locLen = IPP_MIN(aadLen, BLOCK_SIZE); XorBlock(pAAD, AESGCM_GHASH(pState), AESGCM_GHASH(pState), locLen); AESGCM_AAD_LEN(pState) += (Ipp64u)locLen; AESGCM_BUFLEN(pState) = locLen; } #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmprocessiv.c000066400000000000000000000121651470420105600254410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMProcessIV() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMProcessIV // // Purpose: IV processing. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pIV ==NULL && ivLen>0 // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsLengthErr ivLen <0 // ippStsBadArgErr illegal sequence call // ippStsNoErr no errors // // Parameters: // pIV pointer to the IV // ivLen length of IV (it could be 0) // pState pointer to the context // *F*/ IPPFUN(IppStatus, ippsAES_GCMProcessIV,(const Ipp8u* pIV, int ivLen, IppsAES_GCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* test IV pointer and length */ IPP_BADARG_RET(ivLen && !pIV, ippStsNullPtrErr); IPP_BADARG_RET(ivLen<0, ippStsLengthErr); /* use aligned context */ pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); /* test context validity */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* According to the NIST Special Publication 800-38D (Recommendation for GCM * mode, p.5.2.1.1 Input Data) the IV shall be between 1 and 2^64 bits. */ IPP_BADARG_RET(((AESGCM_IV_LEN(pState) + (Ipp64u)ivLen) < (Ipp64u)ivLen), ippStsScaleRangeErr); IPP_BADARG_RET(!(GcmInit==AESGCM_STATE(pState) || GcmIVprocessing==AESGCM_STATE(pState)), ippStsBadArgErr); /* switch IVprocessing on */ AESGCM_STATE(pState) = GcmIVprocessing; #if(_IPP32E>=_IPP32E_K0) IvUpdate_ ivHashUpdate = AES_GCM_IV_UPDATE(pState); /* test if buffer is not empty */ if(AESGCM_BUFLEN(pState)) { /* Cast to int here does not produce loss of data as AESGCM_BUFLEN <= BLOCK_SIZE, which is 16 bytes */ int locLen = IPP_MIN(ivLen, BLOCK_SIZE-(int)AESGCM_BUFLEN(pState)); CopyBlock((void*)pIV, (void*)(AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState)), locLen); AESGCM_BUFLEN(pState) += (Ipp64u)locLen; /* if buffer full */ if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { ivHashUpdate(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), AESGCM_COUNTER(pState), BLOCK_SIZE); AESGCM_BUFLEN(pState) = 0; } AESGCM_IV_LEN(pState) += (Ipp64u)locLen; pIV += locLen; ivLen -= locLen; } /* process main part of IV */ int lenBlks = ivLen & (-BLOCK_SIZE); if(lenBlks) { ivHashUpdate(&AES_GCM_KEY_DATA(pState), &AES_GCM_CONTEXT_DATA(pState), pIV, (Ipp64u)lenBlks); AESGCM_IV_LEN(pState) += (Ipp64u)lenBlks; pIV += lenBlks; ivLen -= lenBlks; } /* copy the rest of IV into the buffer */ if(ivLen) { CopyBlock((void*)pIV, (void*)(AESGCM_COUNTER(pState)), ivLen); AESGCM_IV_LEN(pState) += (Ipp64u)ivLen; AESGCM_BUFLEN(pState) = (Ipp64u)ivLen; } #else /* test if buffer is not empty */ if(AESGCM_BUFLEN(pState)) { int locLen = IPP_MIN(ivLen, BLOCK_SIZE-AESGCM_BUFLEN(pState)); XorBlock(pIV, AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState), AESGCM_COUNTER(pState)+AESGCM_BUFLEN(pState), locLen); AESGCM_BUFLEN(pState) += locLen; /* if buffer full */ if(BLOCK_SIZE==AESGCM_BUFLEN(pState)) { MulGcm_ ghashFunc = AESGCM_HASH(pState); ghashFunc(AESGCM_COUNTER(pState), AESGCM_HKEY(pState), AesGcmConst_table); AESGCM_BUFLEN(pState) = 0; } AESGCM_IV_LEN(pState) += (Ipp64u)locLen; pIV += locLen; ivLen -= locLen; } /* process main part of IV */ { int lenBlks = ivLen & (-BLOCK_SIZE); if(lenBlks) { Auth_ authFunc = AESGCM_AUTH(pState); authFunc(AESGCM_COUNTER(pState), pIV, lenBlks, AESGCM_HKEY(pState), AesGcmConst_table); AESGCM_IV_LEN(pState) += (Ipp64u)lenBlks; pIV += lenBlks; ivLen -= lenBlks; } } /* copy the rest of IV into the buffer */ if(ivLen) { int locLen = IPP_MIN(ivLen, BLOCK_SIZE); XorBlock(pIV, AESGCM_COUNTER(pState), AESGCM_COUNTER(pState), locLen); AESGCM_IV_LEN(pState) += (Ipp64u)locLen; AESGCM_BUFLEN(pState) += locLen; } #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmreinit.c000066400000000000000000000051521470420105600247140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM functionality // // Contents: // ippsAES_GCMReinit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcpaes_gcm_internal_func.h" #include "pcptool.h" #if (_IPP32E >= _IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMReinit // // Purpose: Re-init AES_GCM context for future usage - // the state of the context left unchanged, just the internal stuff is updated // (it's useful when the context physically lies in the same memory, but its // virtual address changes - some pointers inside become stale and need to be re-initialized). // Important note: this API shouldn't be used to re-initialize a context that was copied // from some original context, computations in this case may be incorrect. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsNoErr no errors // // Parameters: // pState pointer to the AES-GCM context to be re-initialized // *F*/ IPPFUN(IppStatus, ippsAES_GCMReinit, (IppsAES_GCMState * pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState *)(IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT)); /* set proper GCM context id */ AESGCM_SET_ID(pState); Ipp64u keyByteLen; /* re-init pointers inside the cipher context */ #if (_IPP32E >= _IPP32E_K0) keyByteLen = AES_GCM_KEY_LEN(pState); #else IppsAESSpec *pAesCtx = AESGCM_CIPHER(pState); /* set proper cipher context id*/ RIJ_SET_ID(pAesCtx); keyByteLen = (Ipp64u)RIJ_NK(pAesCtx) * RIJ_BYTES_IN_WORD; cpAes_setup_ptrs_and_methods(pAesCtx); #endif /* re-init pointers inside the AES-GCM context */ cpAesGCM_setup_ptrs_and_methods(pState, keyByteLen); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmreset.c000066400000000000000000000044501470420105600245440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMReset() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K0) */ /*F* // Name: ippsAES_GCMReset // // Purpose: Resets AES_GCM context. // // Returns: Reason: // ippStsNullPtrErr pState== NULL // ippStsContextMatchErr pState points on invalid context // ippStsNoErr no errors // // Parameters: // pState pointer to the context // *F*/ IPPFUN(IppStatus, ippsAES_GCMReset,(IppsAES_GCMState* pState)) { /* test pState pointer */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState*)( IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT) ); /* test context validity */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* reset GCM */ AESGCM_STATE(pState) = GcmInit; AESGCM_IV_LEN(pState) = CONST_64(0); AESGCM_AAD_LEN(pState) = CONST_64(0); AESGCM_TXT_LEN(pState) = CONST_64(0); AESGCM_BUFLEN(pState) = 0; PadBlock(0, AESGCM_COUNTER(pState), BLOCK_SIZE); PadBlock(0, AESGCM_ECOUNTER(pState), BLOCK_SIZE); PadBlock(0, AESGCM_ECOUNTER0(pState), BLOCK_SIZE); PadBlock(0, AESGCM_GHASH(pState), BLOCK_SIZE); #if(_IPP32E>=_IPP32E_K0) PadBlock(0, (void*)&AES_GCM_CONTEXT_DATA(pState), sizeof(struct gcm_context_data)); #endif /* #if(_IPP32E>=_IPP32E_K0) */ return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_gcmstart.c000066400000000000000000000043341470420105600245600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // ippsAES_GCMStart() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #if(_IPP32E>=_IPP32E_K0) #include "pcpaesauthgcm_avx512.h" #else #include "pcpaesauthgcm.h" #endif /* #if(_IPP32E>=_IPP32E_K1) */ /*F* // Name: ippsAES_GCMStart // // Purpose: Start the process of encryption or decryption and authentication tag generation. // // Returns: Reason: // ippStsNullPtrErr pState == NULL // pIV == NULL, ivLen>0 // pAAD == NULL, aadLen>0 // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsLengthErr ivLen < 0 // aadLen < 0 // ippStsNoErr no errors // // Parameters: // pIV pointer to the IV (nonce) // ivLen length of the IV in bytes // pAAD pointer to the Addition Authenticated Data (header) // aadLen length of the AAD in bytes // pState pointer to the AES-GCM state // *F*/ IPPFUN(IppStatus, ippsAES_GCMStart,(const Ipp8u* pIV, int ivLen, const Ipp8u* pAAD, int aadLen, IppsAES_GCMState* pState)) { IppStatus sts = ippsAES_GCMReset(pState); if(ippStsNoErr==sts) sts = ippsAES_GCMProcessIV(pIV, ivLen, pState); if(ippStsNoErr==sts) sts = ippsAES_GCMProcessAAD(pAAD, aadLen, pState); return sts; } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_internal_func.c000066400000000000000000000046641470420105600255710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // * Initialization functions for internal methods and pointers inside AES cipher context // */ #include "pcpaes_internal_func.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" /* * This function set up pointers to encryption and decryption key schedules, * dispatches to the right internal methods and sets pointers to them inside the AES state. */ IPP_OWN_DEFN(void, cpAes_setup_ptrs_and_methods, (IppsAESSpec * pCtx)) { int nExpKeys = rij128nKeys[rij_index(RIJ_NK(pCtx))]; RIJ_EKEYS(pCtx) = (Ipp8u *)(IPP_ALIGNED_PTR(RIJ_KEYS_BUFFER(pCtx), AES_ALIGNMENT)); RIJ_DKEYS(pCtx) = (Ipp8u *)((Ipp32u *)RIJ_EKEYS(pCtx) + nExpKeys); #if (_AES_NI_ENABLING_ == _FEATURE_ON_) RIJ_AESNI(pCtx) = AES_NI_ENABLED; RIJ_ENCODER(pCtx) = Encrypt_RIJ128_AES_NI; /* AES_NI based encoder */ RIJ_DECODER(pCtx) = Decrypt_RIJ128_AES_NI; /* AES_NI based decoder */ #else #if (_AES_NI_ENABLING_ == _FEATURE_TICKTOCK_) if (IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) { RIJ_AESNI(pCtx) = AES_NI_ENABLED; RIJ_ENCODER(pCtx) = Encrypt_RIJ128_AES_NI; /* AES_NI based encoder */ RIJ_DECODER(pCtx) = Decrypt_RIJ128_AES_NI; /* AES_NI based decoder */ } else #endif { #if (_ALG_AES_SAFE_ == _ALG_AES_SAFE_COMPOSITE_GF_) { RIJ_ENCODER(pCtx) = SafeEncrypt_RIJ128; /* safe encoder (composite GF) */ RIJ_DECODER(pCtx) = SafeDecrypt_RIJ128; /* safe decoder (composite GF)*/ } #else { RIJ_ENCODER(pCtx) = Safe2Encrypt_RIJ128; /* safe encoder (compact Sbox)) */ RIJ_DECODER(pCtx) = Safe2Decrypt_RIJ128; /* safe decoder (compact Sbox)) */ } #endif } #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_internal_func.h000066400000000000000000000022361470420105600255670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Initialization functions for internal methods and pointers inside AES cipher context // */ #if !defined(_PCP_AES_INTERNAL_FUNC_H) #define _PCP_AES_INTERNAL_FUNC_H #include "owndefs.h" #define cpAes_setup_ptrs_and_methods OWNAPI(cpAes_setup_ptrs_and_methods) IPP_OWN_DECL(void, cpAes_setup_ptrs_and_methods, (IppsAESSpec * pCtx)) #endif /* _PCP_AES_INTERNAL_FUNC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_keys_ni.h000066400000000000000000000037701470420105600244050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. AES keys expansion // // Contents: // cpExpandAesKey_NI() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #if !defined (_PCP_AES_KEYS_NI_H) #define _PCP_AES_KEYS_NI_H #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) ////////////////////////////////////////////////////////////////////// #define cpExpandAesKey_NI OWNAPI(cpExpandAesKey_NI) IPP_OWN_DECL (void, cpExpandAesKey_NI, (const Ipp8u* pSecret, IppsAESSpec* pCtx)) #define aes_DecKeyExpansion_NI OWNAPI(aes_DecKeyExpansion_NI) IPP_OWN_DECL (void, aes_DecKeyExpansion_NI, (Ipp8u* decKeys, const Ipp8u* encKeys, int nr)) #define aes128_KeyExpansion_NI OWNAPI(aes128_KeyExpansion_NI) IPP_OWN_DECL (void, aes128_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) #define aes192_KeyExpansion_NI OWNAPI(aes192_KeyExpansion_NI) IPP_OWN_DECL (void, aes192_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) #define aes256_KeyExpansion_NI OWNAPI(aes256_KeyExpansion_NI) IPP_OWN_DECL (void, aes256_KeyExpansion_NI, (Ipp8u* keyExp, const Ipp8u* userkey)) #endif /* #if (_AES_NI_ENABLING_==_FEATURE_ON_) || (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) */ #endif /* #if !defined (_PCP_AES_KEYS_NI_H) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_ofb.h000066400000000000000000000030731470420105600235060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (OFB mode) // // Contents: // cpProcessAES_ofb8() // */ #include "owndefs.h" #include "owncp.h" #if !defined(_PCP_AES_OFB_H) #define _PCP_AES_OFB_H /* // AES-OFB ecnryption/decryption // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // ofbBlkSize ofb block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector */ #define cpProcessAES_ofb8 OWNAPI(cpProcessAES_ofb8) IPP_OWN_DECL (void, cpProcessAES_ofb8, (const Ipp8u *pSrc, Ipp8u *pDst, int dataLen, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV)) #endif /* #if !defined(_PCP_AES_OFB_H) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_process_ofb8.c000066400000000000000000000061511470420105600253270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption/decryption (OFB mode) // // Contents: // cpProcessAES_ofb8() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_ofb.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif /* // AES-OFB ecnryption/decryption // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // ofbBlkSize ofb block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector */ IPP_OWN_DEFN (void, cpProcessAES_ofb8, (const Ipp8u *pSrc, Ipp8u *pDst, int dataLen, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV)) { /* setup encoder method */ RijnCipher encoder = RIJ_ENCODER(pCtx); Ipp32u tmpInpOut[2*NB(128)]; CopyBlock16(pIV, tmpInpOut); while(dataLen>=ofbBlkSize) { /* block-by-block processing */ //encoder(tmpInpOut, tmpInpOut+NB(128), RIJ_NR(pCtx), RIJ_EKEYS(pCtx), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder((Ipp8u*)tmpInpOut, (Ipp8u*)(tmpInpOut+NB(128)), RIJ_NR(pCtx), RIJ_EKEYS(pCtx), RijEncSbox/*NULL*/); #else encoder((Ipp8u*)tmpInpOut, (Ipp8u*)(tmpInpOut+NB(128)), RIJ_NR(pCtx), RIJ_EKEYS(pCtx), NULL); #endif /* store output and shift inpBuffer for the next OFB operation */ if(ofbBlkSize==MBS_RIJ128) { ((Ipp32u*)pDst)[0] = tmpInpOut[0+NB(128)]^((Ipp32u*)pSrc)[0]; ((Ipp32u*)pDst)[1] = tmpInpOut[1+NB(128)]^((Ipp32u*)pSrc)[1]; ((Ipp32u*)pDst)[2] = tmpInpOut[2+NB(128)]^((Ipp32u*)pSrc)[2]; ((Ipp32u*)pDst)[3] = tmpInpOut[3+NB(128)]^((Ipp32u*)pSrc)[3]; tmpInpOut[0] = tmpInpOut[0+NB(128)]; tmpInpOut[1] = tmpInpOut[1+NB(128)]; tmpInpOut[2] = tmpInpOut[2+NB(128)]; tmpInpOut[3] = tmpInpOut[3+NB(128)]; } else { XorBlock(pSrc, tmpInpOut+NB(128), pDst, ofbBlkSize); CopyBlock16((Ipp8u*)tmpInpOut+ofbBlkSize, tmpInpOut); } pSrc += ofbBlkSize; pDst += ofbBlkSize; dataLen -= ofbBlkSize; } /* update pIV */ CopyBlock16((Ipp8u*)tmpInpOut, pIV); /* clear secret data */ PurgeBlock(tmpInpOut, sizeof(tmpInpOut)); } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_randomnoise.c000066400000000000000000000077761470420105600252670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // AES noise function // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcpbnumisc.h" #include "pcptool.h" #include "pcpprng.h" /*F* // Name: cpAESRandomNoise // // Purpose: AES Random Noise // // Returns: Reason: // ippStsNullPtrErr pRndValue == NULL // ippStsLengthErr 29 < nBits > 32 // ippStsScaleRangeErr noiseRate > 1 // (MISTLETOE3_MAX_CHUNK_SIZE > MISTLETOE3_TARGET_SIZE - invalid) // ippStsNotSupportedModeErr Mistletoe3 mitigation isn't applicable for current CPU // (no support of Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) or // vector extensions of Intel® AES-NI) // ippStsErr random bit sequence can't be generated // ippStsNoErr no errors // // Parameters: // rndFunc external random generator // nBits number of bits that should be taken // from generated 32-bit random value // noiseRate probability of refreshing the random // number pRndValue in the context // pRndValue pointer to random number value from previous noise injection // *F*/ IPP_OWN_DEFN(IppStatus, cpAESRandomNoise, (IppBitSupplier rndFunc, Ipp32u nBits, Ipp64f noiseRate, Ipp32u *pRndValue)) { #if (_AES_PROB_NOISE == _FEATURE_ON_) /* test that pRndValue pointer isn't NULL */ IPP_BAD_PTR1_RET(pRndValue); /* test nBits and noiseRate values */ IPP_BADARG_RET(nBits < 29 || nBits > 32, ippStsLengthErr); IPP_BADARG_RET((noiseRate > 1), ippStsScaleRangeErr); Ipp32u rand = 0; IppStatus status = ippStsNoErr; IppsPRNGState Ctx; IppsPRNGState* pCtx = NULL; /* Use internal PRNG implementations if no external random source provided */ if (NULL == rndFunc) { if( IsFeatureEnabled(ippCPUID_RDRAND) ) rndFunc = ippsPRNGenRDRAND; else // RDRAND feature isn't available { pCtx = &Ctx; ippsPRNGInit(160, pCtx); rndFunc = ippsPRNGen; } } Ipp32u ctxRand = *pRndValue; /* Get the threshold to generate random noise */ const Ipp32u randMax = (Ipp32u)(-1); Ipp32u noiseThreshold = (Ipp32u)((Ipp64f)randMax * noiseRate); /* Get a random value, which is used to decide whether a new random should be * generated. This allows generate random latency with probability */ status = rndFunc(&rand, 32, pCtx); /* Check if new rand value required */ if ((ippStsNoErr == status) && ((rand < noiseThreshold) || (ctxRand == 0))) { status = rndFunc(&ctxRand, (int)nBits, pCtx); if (ippStsNoErr == status) { /* Write back a new random */ *pRndValue = ctxRand; } } /* Scale down based on noise rate */ rand = (Ipp32u)((Ipp64f)ctxRand * noiseRate); if (ippStsNoErr == status) { _ippcpDelay(rand); } return status; #else /* To remove MSVC warning C4100: 'XXX': unreferenced formal parameter*/ IPP_UNREFERENCED_PARAMETER(rndFunc); IPP_UNREFERENCED_PARAMETER(nBits); IPP_UNREFERENCED_PARAMETER(noiseRate); IPP_UNREFERENCED_PARAMETER(pRndValue); return ippStsNotSupportedModeErr; #endif /* #if (_AES_PROB_NOISE == _FEATURE_ON_) */ } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_s2v_cmac.c000066400000000000000000000063161470420105600244330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-SIV Functions (RFC 5297) // // Contents: // ippsAES_S2V_CMAC() // */ #include "owndefs.h" #include "owncp.h" #include "pcpcmac.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_sivstuff.h" /*F* // Name: ippsAES_S2V_CMAC // // Purpose: Converts strings to vector - // performs S2V operation as defined RFC 5297. // // Returns: Reason: // ippStsNullPtrErr pV == NULL // pAD== NULL // pADlen==NULL // pADlen[i]!=0 && pAD[i]==0 // ippStsLengthErr keyLen != 16 // keyLen != 24 // keyLen != 32 // pADlen[i]<0 // 0 > numAD // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length of secret key // pAD[] array of pointers to input strings // pADlen[] array of input string lengths // numAD number of pAD[] and pADlen[] terms // pV pointer to output vector // *F*/ IPPFUN(IppStatus, ippsAES_S2V_CMAC,(const Ipp8u* pKey, int keyLen, const Ipp8u* pAD[], const int pADlen[], int numAD, Ipp8u V[MBS_RIJ128])) { /* test output vector */ IPP_BAD_PTR1_RET(V); /* make sure that number of input string is legal */ IPP_BADARG_RET(0>numAD, ippStsLengthErr); /* test arrays of input */ IPP_BAD_PTR2_RET(pAD, pADlen); int n; for(n=0; n 4 // ippStsNotSupportedModeErr Mistletoe3 mitigation isn't applicable for current CPU // (no support of Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) or // vector extensions of Intel® AES-NI) // ippStsNoErr no errors // // Parameters: // noiseLevel the value of this parameter is directly // proportional to the amount of noise injected // Increasing noise level by 1 means the delay // (performance impact) is doubled // pCtx pointer to the AES context // *F*/ IPPFUN(IppStatus, ippsAESSetupNoise, (Ipp32u noiseLevel, IppsAESSpec* pCtx)) { #if (_AES_PROB_NOISE == _FEATURE_ON_) /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test noise level range */ IPP_BADARG_RET(noiseLevel > 4, ippStsLengthErr); cpAESNoiseParams *params = (cpAESNoiseParams *)&RIJ_NOISE_PARAMS(pCtx); /* set up the parameters with initial values */ AES_NOISE_RAND(params) = 0; AES_NOISE_LEVEL(params) = noiseLevel; return ippStsNoErr; #else /* To remove MSVC warning C4100: 'XXX': unreferenced formal parameter*/ IPP_UNREFERENCED_PARAMETER(noiseLevel); IPP_UNREFERENCED_PARAMETER(pCtx); return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_sivdecrypt.c000066400000000000000000000107251470420105600251310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-SIV Functions (RFC 5297) // // Contents: // ippsAES_SIVDecrypt() // */ #include "owndefs.h" #include "owncp.h" #include "pcpcmac.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_sivstuff.h" /*F* // Name: ippsAES_SIVDecrypt // // Purpose: RFC 5297 authenticated decryption // // Returns: Reason: // ippStsNullPtrErr pSrc==NULL, pDst==NULL // pAuthPassed==NULL // pAuthKey==NULL, pConfKey==NULL // pAD== NULL, pADlen==NULL // pADlen[i]!=0 && pAD[i]==0 // pSIV == NULL // ippStsLengthErr keyLen != 16 // keyLen != 24 // keyLen != 32 // pADlen[i]<0 // numAD<0 // len<=0 // ippStsNoErr no errors // // Parameters: // pSrc pointer to ciphertext // pDst pointer to plaintext // len length (in bytes) of plaintext/ciphertext // pAuthPassed "authentication passed" flag // pAuthKey pointer to the authentication key // pConfKey pointer to the confidendat key // keyLen length of keys // pAD[] array of pointers to input strings // pADlen[] array of input string lengths // numAD number of pAD[] and pADlen[] terms // pSIV pointer to input SIV // *F*/ IPPFUN(IppStatus, ippsAES_SIVDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int* pAuthPassed, const Ipp8u* pAuthKey, const Ipp8u* pConfKey, int keyLen, const Ipp8u* pAD[], const int pADlen[], int numAD, const Ipp8u* pSIV)) { /* test ciphertext, plaintex and length */ IPP_BAD_PTR2_RET(pSrc, pDst); IPP_BADARG_RET(0>=len, ippStsLengthErr); /* test keys & keyLen */ IPP_BAD_PTR2_RET(pAuthKey, pConfKey); IPP_BADARG_RET(keyLen!=16 && keyLen!=24 && keyLen!=32, ippStsLengthErr); /* test passed flag & auth vector */ IPP_BAD_PTR2_RET(pAuthPassed, pSIV); /* test arrays of input AD[] */ IPP_BAD_PTR2_RET(pAD, pADlen); IPP_BADARG_RET(0>numAD, ippStsLengthErr); { int n; for (n = 0; n < numAD; n++) { /* test input message and it's length */ IPP_BADARG_RET((pADlen[n] < 0), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((pADlen[n] && !pAD[n]), ippStsNullPtrErr); } } { int n; /* iv an dmask */ Ipp8u iv[MBS_RIJ128]; Ipp8u vmask[MBS_RIJ128] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0x7f,0xff,0xff,0xff,0x7f,0xff,0xff,0xff}; /* AES context */ Ipp8u aesBlob[sizeof(IppsAESSpec)]; IppsAESSpec* paesCtx = (IppsAESSpec*)aesBlob; ippsAESInit(pConfKey, keyLen, paesCtx, sizeof(aesBlob)); /* construct iv */ for(n=0; n=len, ippStsLengthErr); /* test keys & keyLen */ IPP_BAD_PTR2_RET(pAuthKey, pConfKey); IPP_BADARG_RET(keyLen!=16 && keyLen!=24 && keyLen!=32, ippStsLengthErr); /* test output vector */ IPP_BAD_PTR1_RET(pSIV); /* test arrays of input AD[] */ IPP_BAD_PTR2_RET(pAD, pADlen); IPP_BADARG_RET(0>numAD, ippStsLengthErr); { int n; for (n = 0; n < numAD; n++) { /* test input message and it's length */ IPP_BADARG_RET((pADlen[n] < 0), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((pADlen[n] && !pAD[n]), ippStsNullPtrErr); } } { int n; /* iv and mask */ Ipp8u iv[MBS_RIJ128]; Ipp8u vmask[MBS_RIJ128] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 0x7f,0xff,0xff,0xff,0x7f,0xff,0xff,0xff}; /* AES context */ Ipp8u aesBlob[sizeof(IppsAESSpec)]; IppsAESSpec* paesCtx = (IppsAESSpec*)aesBlob; { Ipp8u ctxBlob[sizeof(IppsAES_CMACState)]; IppsAES_CMACState* pCtx = (IppsAES_CMACState*)ctxBlob; cpAES_S2V_init(pSIV, pAuthKey, keyLen, pCtx, sizeof(ctxBlob)); for(n=0; n>8) & 0xFF; } out[MBS_RIJ128-1] ^= ((Ipp8u)(0-carry) & 0x87); return out; } __IPPCP_INLINE void cpAES_S2V_update(Ipp8u v[MBS_RIJ128], const Ipp8u* pSrc, int len, IppsAES_CMACState* pCtx) { Ipp8u t[MBS_RIJ128]; cpAES_CMAC(t, pSrc, len, pCtx); double16(v, v); XorBlock16(v, t, v); } static void cpAES_S2V_final(Ipp8u v[MBS_RIJ128], const Ipp8u* pSrc, int len, IppsAES_CMACState* pCtx) { Ipp8u t[MBS_RIJ128]; if(len>=MBS_RIJ128) { ippsAES_CMACUpdate(pSrc, len-MBS_RIJ128, pCtx); XorBlock16(pSrc+len-MBS_RIJ128, v, t); } else { double16(t, v); XorBlock(pSrc, t, t, len); t[len] ^= 0x80; } cpAES_CMAC(v, t, MBS_RIJ128, pCtx); } #endif /*_PCP_AES_SIV_STUFF_H_*/ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_wrpaesgcmdec_avx.c000066400000000000000000000043701470420105600262560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // wrpAesGcmDec_avx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #if(_IPP32E<_IPP32E_K0) /*F* // Name: ippsAES_GCMDecrypt // // Purpose: Decrypts a data buffer in the GCM mode. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pState == NULL // ippStsContextMatchErr !AESGCM_VALID_ID() // ippStsLengthErr txtLen<0 // ippStsNoErr no errors // // Parameters: // pSrc Pointer to ciphertext. // pDst Pointer to plaintext. // len Length of the plaintext and ciphertext in bytes // pState pointer to the context // *F*/ IPP_OWN_DEFN (void, wrpAesGcmDec_avx, (Ipp8u* pDst, const Ipp8u* pSrc, int lenBlks, IppsAES_GCMState* pState)) { IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); AesGcmDec_avx(pDst, pSrc, lenBlks, encoder, RIJ_NR(pAES), RIJ_EKEYS(pAES), AESGCM_GHASH(pState), AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), AESGCM_HKEY(pState)); } #endif /* (_IPP32E<_IPP32E_K0) */ #endif /* #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_wrpaesgcmenc_avx.c000066400000000000000000000033231470420105600262650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM // // Contents: // wrpAesGcmEnc_avx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcpaesm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #if(_IPP32E<_IPP32E_K0) /* encrypts and authenticates n*BLOCK_SIZE bytes */ IPP_OWN_DEFN (void, wrpAesGcmEnc_avx, (Ipp8u* pDst, const Ipp8u* pSrc, int lenBlks, IppsAES_GCMState* pState)) { IppsAESSpec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); AesGcmEnc_avx(pDst, pSrc, lenBlks, encoder, RIJ_NR(pAES), RIJ_EKEYS(pAES), AESGCM_GHASH(pState), AESGCM_COUNTER(pState), AESGCM_ECOUNTER(pState), AESGCM_HKEY(pState)); } #endif /* (_IPP32E<_IPP32E_K0) */ #endif /* #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_xts_vaes512.c000066400000000000000000000376131470420105600250260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS VAES512 Functions (IEEE P1619) // // Contents: // cpAESEncryptXTS_VAES() // cpAESDecryptXTS_VAES() // */ #include "owncp.h" #include "pcpaesmxts.h" #include "pcptool.h" #include "pcpaesmxtsstuff.h" #include "pcpaes_encrypt_vaes512.h" #include "pcpaes_decrypt_vaes512.h" #if (_IPP32E>=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // cast truncates constant value in MSVC #endif #define M512(mem) (*((__m512i*)(mem))) /* Generate next 4 tweaks with 2^8 multiplier */ __IPPCP_INLINE __m512i nextTweaks_x8(__m512i tweak128x4) { const __m512i poly = _mm512_set_epi64(0, 0x87, 0, 0x87, 0, 0x87, 0, 0x87); __m512i highBytes = _mm512_bsrli_epi128(tweak128x4, 15); __m512i tmp = _mm512_clmulepi64_epi128(highBytes, poly, 0); tweak128x4 = _mm512_bslli_epi128(tweak128x4, 1); tweak128x4 = _mm512_xor_si512(tweak128x4, tmp); return tweak128x4; } /* Generate next 4 tweaks with 2^32 multiplier */ __IPPCP_INLINE __m512i nextTweaks_x32(__m512i tweak128x4) { const __m512i poly = _mm512_set_epi64(0, 0x87, 0, 0x87, 0, 0x87, 0, 0x87); /* Shift 128-bit lanes right by 12 bytes */ __m512i highBytes = _mm512_bsrli_epi128(tweak128x4, 12); __m512i tmp = _mm512_clmulepi64_epi128(highBytes, poly, 0); /* Shift 128-bit lanes left by 4 bytes */ tweak128x4 = _mm512_bslli_epi128(tweak128x4, 4); /* Xor low 4 bytes in each 128-bit lane with 0x87-modified ones */ tweak128x4 = _mm512_xor_si512(tweak128x4, tmp); return tweak128x4; } IPP_OWN_DEFN (void, cpAESEncryptXTS_VAES, (Ipp8u* outBlk, const Ipp8u* inpBlk, int nBlks, const Ipp8u* pRKey, int nr, Ipp8u* pTweak)) { if (0 == nBlks) { return; // do not modify tweak value } int cipherRounds = nr - 1; __m128i* pRkey = (__m128i*)pRKey; __m512i* pInp512 = (__m512i*)inpBlk; __m512i* pOut512 = (__m512i*)outBlk; /* Produce initial 32 tweaks */ __ALIGN64 Ipp8u tempTweakBuffer[AES_BLK_SIZE * 4 * 8]; // 32 tweaks cpXTSwhitening(tempTweakBuffer, 8, pTweak); // generate 8 tweaks const __m512i* pInitialTweaks = (const __m512i*)tempTweakBuffer; int tailTweaksConsumedCount = 0; __m512i tweaks[8]; // generate other 24 tweaks tweaks[0] = M512(pInitialTweaks); tweaks[1] = M512(pInitialTweaks + 1); tweaks[2] = nextTweaks_x8(tweaks[0]); tweaks[3] = nextTweaks_x8(tweaks[1]); tweaks[4] = nextTweaks_x8(tweaks[2]); tweaks[5] = nextTweaks_x8(tweaks[3]); tweaks[6] = nextTweaks_x8(tweaks[4]); tweaks[7] = nextTweaks_x8(tweaks[5]); int blocks; for (blocks = nBlks; blocks >= (4 * 8); blocks -= (4 * 8)) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); __m512i blk3 = _mm512_loadu_si512(pInp512 + 3); __m512i blk4 = _mm512_loadu_si512(pInp512 + 4); __m512i blk5 = _mm512_loadu_si512(pInp512 + 5); __m512i blk6 = _mm512_loadu_si512(pInp512 + 6); __m512i blk7 = _mm512_loadu_si512(pInp512 + 7); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); blk4 = _mm512_xor_epi64(tweaks[4], blk4); blk5 = _mm512_xor_epi64(tweaks[5], blk5); blk6 = _mm512_xor_epi64(tweaks[6], blk6); blk7 = _mm512_xor_epi64(tweaks[7], blk7); cpAESEncrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); tweaks[0] = nextTweaks_x32(tweaks[0]); tweaks[1] = nextTweaks_x32(tweaks[1]); tweaks[2] = nextTweaks_x32(tweaks[2]); tweaks[3] = nextTweaks_x32(tweaks[3]); cpAESEncrypt4_VAES_NI(&blk4, &blk5, &blk6, &blk7, pRkey, cipherRounds); blk4 = _mm512_xor_epi64(tweaks[4], blk4); blk5 = _mm512_xor_epi64(tweaks[5], blk5); blk6 = _mm512_xor_epi64(tweaks[6], blk6); blk7 = _mm512_xor_epi64(tweaks[7], blk7); tweaks[4] = nextTweaks_x32(tweaks[4]); tweaks[5] = nextTweaks_x32(tweaks[5]); tweaks[6] = nextTweaks_x32(tweaks[6]); tweaks[7] = nextTweaks_x32(tweaks[7]); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); _mm512_storeu_si512(pOut512 + 3, blk3); _mm512_storeu_si512(pOut512 + 4, blk4); _mm512_storeu_si512(pOut512 + 5, blk5); _mm512_storeu_si512(pOut512 + 6, blk6); _mm512_storeu_si512(pOut512 + 7, blk7); pInp512 += 8; pOut512 += 8; } if ((4 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); __m512i blk3 = _mm512_loadu_si512(pInp512 + 3); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); cpAESEncrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); _mm512_storeu_si512(pOut512 + 3, blk3); tailTweaksConsumedCount += 4; pInp512 += 4; pOut512 += 4; blocks -= (4 * 4); } if ((3 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); blk2 = _mm512_xor_epi64(tweaks[2 + tailTweaksConsumedCount], blk2); cpAESEncrypt3_VAES_NI(&blk0, &blk1, &blk2, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); blk2 = _mm512_xor_epi64(tweaks[2 + tailTweaksConsumedCount], blk2); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); tailTweaksConsumedCount += 3; pInp512 += 3; pOut512 += 3; blocks -= (3 * 4); } else if ((2 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); cpAESEncrypt2_VAES_NI(&blk0, &blk1, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); tailTweaksConsumedCount += 2; pInp512 += 2; pOut512 += 2; blocks -= (2 * 4); } else if ((1 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); cpAESEncrypt1_VAES_NI(&blk0, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); _mm512_storeu_si512(pOut512, blk0); tailTweaksConsumedCount += 1; pInp512 += 1; pOut512 += 1; blocks -= (1 * 4); } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); __m512i blk0 = _mm512_maskz_loadu_epi64(k, pInp512); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); cpAESEncrypt1_VAES_NI(&blk0, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); _mm512_mask_storeu_epi64(pOut512, k, blk0); } { __mmask8 maskTweakToReturn = (__mmask8)(((Ipp8u)0x03u << (blocks << 1))); _mm512_mask_compressstoreu_epi64(pTweak, maskTweakToReturn /* the first unused tweak */, tweaks[0 + tailTweaksConsumedCount]); } } IPP_OWN_DEFN (void, cpAESDecryptXTS_VAES, (Ipp8u* outBlk, const Ipp8u* inpBlk, int nBlks, const Ipp8u* pRKey, int nr, Ipp8u* pTweak)) { if (0 == nBlks) { return; // do not modify tweak value } int cipherRounds = nr - 1; __m128i* pRkey = (__m128i*)pRKey + cipherRounds + 1; __m512i* pInp512 = (__m512i*)inpBlk; __m512i* pOut512 = (__m512i*)outBlk; /* Produce initial 32 tweaks */ __ALIGN64 Ipp8u tempTweakBuffer[AES_BLK_SIZE * 4 * 8]; // 32 tweaks cpXTSwhitening(tempTweakBuffer, 8, pTweak); // generate 8 tweaks const __m512i* pInitialTweaks = (const __m512i*)tempTweakBuffer; int tailTweaksConsumedCount = 0; __m512i tweaks[8]; // generate other 24 tweaks tweaks[0] = M512(pInitialTweaks); tweaks[1] = M512(pInitialTweaks + 1); tweaks[2] = nextTweaks_x8(tweaks[0]); tweaks[3] = nextTweaks_x8(tweaks[1]); tweaks[4] = nextTweaks_x8(tweaks[2]); tweaks[5] = nextTweaks_x8(tweaks[3]); tweaks[6] = nextTweaks_x8(tweaks[4]); tweaks[7] = nextTweaks_x8(tweaks[5]); int blocks; for (blocks = nBlks; blocks >= (4 * 8); blocks -= (4 * 8)) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); __m512i blk3 = _mm512_loadu_si512(pInp512 + 3); __m512i blk4 = _mm512_loadu_si512(pInp512 + 4); __m512i blk5 = _mm512_loadu_si512(pInp512 + 5); __m512i blk6 = _mm512_loadu_si512(pInp512 + 6); __m512i blk7 = _mm512_loadu_si512(pInp512 + 7); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); blk4 = _mm512_xor_epi64(tweaks[4], blk4); blk5 = _mm512_xor_epi64(tweaks[5], blk5); blk6 = _mm512_xor_epi64(tweaks[6], blk6); blk7 = _mm512_xor_epi64(tweaks[7], blk7); cpAESDecrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); tweaks[0] = nextTweaks_x32(tweaks[0]); tweaks[1] = nextTweaks_x32(tweaks[1]); tweaks[2] = nextTweaks_x32(tweaks[2]); tweaks[3] = nextTweaks_x32(tweaks[3]); cpAESDecrypt4_VAES_NI(&blk4, &blk5, &blk6, &blk7, pRkey, cipherRounds); blk4 = _mm512_xor_epi64(tweaks[4], blk4); blk5 = _mm512_xor_epi64(tweaks[5], blk5); blk6 = _mm512_xor_epi64(tweaks[6], blk6); blk7 = _mm512_xor_epi64(tweaks[7], blk7); tweaks[4] = nextTweaks_x32(tweaks[4]); tweaks[5] = nextTweaks_x32(tweaks[5]); tweaks[6] = nextTweaks_x32(tweaks[6]); tweaks[7] = nextTweaks_x32(tweaks[7]); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); _mm512_storeu_si512(pOut512 + 3, blk3); _mm512_storeu_si512(pOut512 + 4, blk4); _mm512_storeu_si512(pOut512 + 5, blk5); _mm512_storeu_si512(pOut512 + 6, blk6); _mm512_storeu_si512(pOut512 + 7, blk7); pInp512 += 8; pOut512 += 8; } if ((4 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); __m512i blk3 = _mm512_loadu_si512(pInp512 + 3); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); cpAESDecrypt4_VAES_NI(&blk0, &blk1, &blk2, &blk3, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0], blk0); blk1 = _mm512_xor_epi64(tweaks[1], blk1); blk2 = _mm512_xor_epi64(tweaks[2], blk2); blk3 = _mm512_xor_epi64(tweaks[3], blk3); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); _mm512_storeu_si512(pOut512 + 3, blk3); tailTweaksConsumedCount += 4; pInp512 += 4; pOut512 += 4; blocks -= (4 * 4); } if ((3 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); __m512i blk2 = _mm512_loadu_si512(pInp512 + 2); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); blk2 = _mm512_xor_epi64(tweaks[2 + tailTweaksConsumedCount], blk2); cpAESDecrypt3_VAES_NI(&blk0, &blk1, &blk2, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); blk2 = _mm512_xor_epi64(tweaks[2 + tailTweaksConsumedCount], blk2); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); _mm512_storeu_si512(pOut512 + 2, blk2); tailTweaksConsumedCount += 3; pInp512 += 3; pOut512 += 3; blocks -= (3 * 4); } else if ((2 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); __m512i blk1 = _mm512_loadu_si512(pInp512 + 1); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); cpAESDecrypt2_VAES_NI(&blk0, &blk1, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); blk1 = _mm512_xor_epi64(tweaks[1 + tailTweaksConsumedCount], blk1); _mm512_storeu_si512(pOut512, blk0); _mm512_storeu_si512(pOut512 + 1, blk1); tailTweaksConsumedCount += 2; pInp512 += 2; pOut512 += 2; blocks -= (2 * 4); } else if ((1 * 4) <= blocks) { __m512i blk0 = _mm512_loadu_si512(pInp512); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); cpAESDecrypt1_VAES_NI(&blk0, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); _mm512_storeu_si512(pOut512, blk0); tailTweaksConsumedCount += 1; pInp512 += 1; pOut512 += 1; blocks -= (1 * 4); } if (blocks) { __mmask8 k = (__mmask8)((1 << (blocks + blocks)) - 1); __m512i blk0 = _mm512_maskz_loadu_epi64(k, pInp512); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); cpAESDecrypt1_VAES_NI(&blk0, pRkey, cipherRounds); blk0 = _mm512_xor_epi64(tweaks[0 + tailTweaksConsumedCount], blk0); _mm512_mask_storeu_epi64(pOut512, k, blk0); } { __mmask8 maskTweakToReturn = (__mmask8)(((Ipp8u)0x03u << (blocks << 1))); _mm512_mask_compressstoreu_epi64(pTweak, maskTweakToReturn /* the first unused tweak */, tweaks[0 + tailTweaksConsumedCount]); } } #endif /* (_IPP32E>=_IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/pcpaes_xtsdecrypt.c000066400000000000000000000136211470420105600251440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS Functions (IEEE P1619) // // Contents: // ippsAES_XTSDecrypt() // */ #include "owncp.h" #include "pcpaesmxts.h" #include "pcptool.h" #include "pcpaesmxtsstuff.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif // // static void cpAES_XTS_DecBlock(Ipp8u* ctxt, const Ipp8u* ptxt, const Ipp8u* tweak, const IppsAESSpec* pEncCtx) { /* pre-whitening */ XorBlock16(ptxt, tweak, ctxt); /* encryption */ ippsAESDecryptECB(ctxt, ctxt, AES_BLK_SIZE, pEncCtx); /* post-whitening */ XorBlock16(ctxt, tweak, ctxt); } /*F* // Name: ippsAES_XTSDecrypt // // Purpose: AES-XTS decryption. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pTweak ==NULL // pCtx == NULL // ippStsLengthErr bitLen <128 // ippStsContextMatchErr !VALID_AES_XTS_ID(pCtx) // ippStsBadArgErr !IsLegalGeometry(startCipherBlkNo, // bitLen, pCtx->duBitsize) // ippStsNoErr no errors // // Parameters: // pSrc points input buffer // pDst points output buffer // bitLen length of the input buffer in bits // startCipherBlkNo number of the first block for data unit // pTweak points tweak value // pCtx points AES_XTS context // *F*/ IPPFUN(IppStatus, ippsAES_XTSDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int bitLen, const IppsAES_XTSSpec* pCtx, const Ipp8u* pTweak, int startCipherBlkNo)) { /* test pointers */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_XTS_ID(pCtx), ippStsContextMatchErr); /* test data pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pTweak); /* test startCipherBlkNo and bitLen */ IPP_BADARG_RET(bitLen < IPP_AES_BLOCK_BITSIZE, ippStsLengthErr); IPP_BADARG_RET(!IsLegalGeometry(startCipherBlkNo, bitLen, pCtx->duBitsize), ippStsBadArgErr); { __ALIGN16 Ipp8u tweakCT[AES_BLK_SIZE]; { /* encrypt tweak */ const IppsAESSpec* ptwkAES = &pCtx->tweakAES; RijnCipher encoder = RIJ_ENCODER(ptwkAES); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pTweak, tweakCT, RIJ_NR(ptwkAES), RIJ_EKEYS(ptwkAES), RijEncSbox/*NULL*/); #else encoder(pTweak, tweakCT, RIJ_NR(ptwkAES), RIJ_EKEYS(ptwkAES), NULL); #endif /* update tweakCT */ for(; startCipherBlkNo>0; startCipherBlkNo--) gf_mul_by_primitive(tweakCT); } /* XTS decryption */ { const IppsAESSpec* pdatAES = &pCtx->datumAES; int encBlocks = bitLen/IPP_AES_BLOCK_BITSIZE; int encBlocklast = bitLen%IPP_AES_BLOCK_BITSIZE; if(encBlocklast) encBlocks--; /* decrypt data blocks */ if( encBlocks>0) { #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use Intel(R) AES New Instructions version if possible */ if(AES_NI_ENABLED==RIJ_AESNI(pdatAES)) { #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { cpAESDecryptXTS_VAES(pDst, pSrc, encBlocks, RIJ_DKEYS(pdatAES), RIJ_NR(pdatAES), tweakCT); } else #endif cpAESDecryptXTS_AES_NI(pDst, pSrc, encBlocks, RIJ_DKEYS(pdatAES), RIJ_NR(pdatAES), tweakCT); pSrc += encBlocks*AES_BLK_SIZE; pDst += encBlocks*AES_BLK_SIZE; } else #endif { for(; encBlocks>0; encBlocks--) { cpAES_XTS_DecBlock(pDst, pSrc, tweakCT, pdatAES); gf_mul_by_primitive(tweakCT); pSrc += AES_BLK_SIZE; pDst += AES_BLK_SIZE; } } } /* "stealing" - decrypt last partial block if is */ if(encBlocklast) { int partBlockSize = encBlocklast/BYTESIZE; __ALIGN16 Ipp8u cc[AES_BLK_SIZE]; __ALIGN16 Ipp8u pp[AES_BLK_SIZE]; CopyBlock16(tweakCT, cc); gf_mul_by_primitive(cc); cpAES_XTS_DecBlock(pp, pSrc, cc, pdatAES); CopyBlock16(pp, cc); CopyBlock(pSrc+AES_BLK_SIZE, cc, partBlockSize); encBlocklast %= BYTESIZE; if(encBlocklast) { Ipp8u partBlockMask = (Ipp8u)((0xFF)<<((BYTESIZE -encBlocklast) %BYTESIZE)); Ipp8u x = pSrc[AES_BLK_SIZE+partBlockSize]; Ipp8u y = cc[partBlockSize]; x = (x & partBlockMask) | (y & ~partBlockMask); cc[partBlockSize] = x; pp[partBlockSize] &= partBlockMask; partBlockSize++; } cpAES_XTS_DecBlock(pDst, cc, tweakCT, pdatAES); CopyBlock(pp, pDst+AES_BLK_SIZE, partBlockSize); /* clear secret data */ PurgeBlock(pp, sizeof(pp)); } return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_xtsdecrypt_direct.c000066400000000000000000000177231470420105600265050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS Functions (IEEE P1619) // // Contents: // ippsAESDecryptXTS_Direct() // */ #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaesmxtsstuff.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if !defined AES_BLK_SIZE #define AES_BLK_SIZE (IPP_AES_BLOCK_BITSIZE/BITSIZE(Ipp8u)) #endif #define AES_BLKS_PER_BUFFER (32) /*F* // Name: ippsAESDecryptXTS_Direct // // Purpose: AES-XTS decryption (see IEEE P1619-2007). // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pTweak ==NULL // pKey ==NULL // ippStsLengthErr dataUnitBitsize <128 // keyBitsize != 256, !=512 // ippStsBadArgErr aesBlkNo >= dataUnitBitsize/IPP_AES_BLOCK_BITSIZE // [Only in FIPS-compliance mode]: Indicates an error // condition if tweak key is equal to the data key // ippStsNoErr no errors // // Parameters: // pSrc points input buffer // pDst points output buffer // encBitsize lendth of the input/output buffer in bits // aesBlkNo number of the first block for data unit // ptweakPT points tweak value // pKey pointer to the XTS key // keyBitsize length of the key in bits // dataUnitBitsize length of Data Unit in bits // *F*/ static IppStatus cpAES_XTS_DecBlock(Ipp8u* ctxt, const Ipp8u* ptxt, const Ipp8u* tweak, const IppsAESSpec* pEncCtx) { IppStatus sts; /* pre-whitening */ XorBlock16(ptxt, tweak, ctxt); /* decryption */ sts = ippsAESDecryptECB(ctxt, ctxt, AES_BLK_SIZE, pEncCtx); /* post-whitening */ XorBlock16(ctxt, tweak, ctxt); return sts; } // // To Do: advance parameter check!! // IPPFUN(IppStatus, ippsAESDecryptXTS_Direct,(const Ipp8u* pSrc, Ipp8u* pDst, int encBitsize, int aesBlkNo, const Ipp8u* pTweakPT, const Ipp8u* pKey, int keyBitsize, int dataUnitBitsize)) { /* test dataUnitBitsize */ IPP_BADARG_RET(dataUnitBitsize (1<<27), ippStsBadArgErr); /* test dataUnitBitsize and aesBlkNo */ IPP_BADARG_RET(((dataUnitBitsize/IPP_AES_BLOCK_BITSIZE)<=aesBlkNo) || (0>aesBlkNo), ippStsBadArgErr); int keySize = keyBitsize/2/8; const Ipp8u* pConfKey = pKey; const Ipp8u* pTweakKey = pKey+keySize; #ifdef IPPCP_FIPS_MODE /* test FIPS-compliance requirement pdatKey != ptwkKey */ int isEqu = cpIsEquBlock_ct(pConfKey, pTweakKey, keySize) & 1; IPP_BADARG_RET(isEqu, ippStsBadArgErr); #endif { IppStatus sts = ippStsNoErr; do { int encBlocks = encBitsize/IPP_AES_BLOCK_BITSIZE; int encBlocklast = encBitsize%IPP_AES_BLOCK_BITSIZE; __ALIGN16 IppsAESSpec aesCtx; __ALIGN16 Ipp8u tweakCT[AES_BLK_SIZE]; __ALIGN16 Ipp8u tmp[AES_BLKS_PER_BUFFER*AES_BLK_SIZE]; sts = ippsAESInit(pTweakKey, keySize, &aesCtx, sizeof(aesCtx)); if(ippStsNoErr!=sts) break; { RijnCipher encoder = RIJ_ENCODER(&aesCtx); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pTweakPT, tweakCT, RIJ_NR(&aesCtx), RIJ_EKEYS(&aesCtx), RijEncSbox/*NULL*/); #else encoder(pTweakPT, tweakCT, RIJ_NR(&aesCtx), RIJ_EKEYS(&aesCtx), NULL); #endif } sts = ippsAESInit(pConfKey, keySize, &aesCtx, sizeof(aesCtx)); if(ippStsNoErr!=sts) break; for(; aesBlkNo>0; aesBlkNo--) gf_mul_by_primitive(tweakCT); if(encBlocklast) encBlocks--; /* // decrypt data */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use Intel(R) AES New Instructions version if possible */ if(AES_NI_ENABLED==RIJ_AESNI(&aesCtx)) { #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { cpAESDecryptXTS_VAES(pDst, pSrc, encBlocks, RIJ_DKEYS(&aesCtx), RIJ_NR(&aesCtx), tweakCT); } else #endif cpAESDecryptXTS_AES_NI(pDst, pSrc, encBlocks, RIJ_DKEYS(&aesCtx), RIJ_NR(&aesCtx), tweakCT); pSrc += encBlocks*AES_BLK_SIZE; pDst += encBlocks*AES_BLK_SIZE; } else #endif { for(; encBlocks>=AES_BLKS_PER_BUFFER && ippStsNoErr==sts; encBlocks-=AES_BLKS_PER_BUFFER) { /* compute whitening tweaks */ cpXTSwhitening(tmp, AES_BLKS_PER_BUFFER, tweakCT); /* pre-whitening */ cpXTSxor16(pDst, pSrc, tmp, AES_BLKS_PER_BUFFER); sts = ippsAESDecryptECB(pDst, pDst, AES_BLKS_PER_BUFFER*AES_BLK_SIZE, &aesCtx); /* post-whitening */ cpXTSxor16(pDst, pDst, tmp, AES_BLKS_PER_BUFFER); pSrc += AES_BLKS_PER_BUFFER*AES_BLK_SIZE; pDst += AES_BLKS_PER_BUFFER*AES_BLK_SIZE; } if(ippStsNoErr!=sts) break; if(encBlocks) { cpXTSwhitening(tmp, encBlocks, tweakCT); /* pre-whitening */ cpXTSxor16(pDst, pSrc, tmp, encBlocks); ippsAESDecryptECB(pDst, pDst, AES_BLK_SIZE*encBlocks, &aesCtx); /* post-whitening */ cpXTSxor16(pDst, pDst, tmp, encBlocks); pSrc += AES_BLK_SIZE*encBlocks; pDst += AES_BLK_SIZE*encBlocks; } } /* "stealing" - encrypt last partial block if is */ if(encBlocklast) { int partBlockSize = encBlocklast/BYTESIZE; __ALIGN16 Ipp8u cc[AES_BLK_SIZE]; __ALIGN16 Ipp8u pp[AES_BLK_SIZE]; CopyBlock16(tweakCT, cc); gf_mul_by_primitive(cc); cpAES_XTS_DecBlock(pp, pSrc, cc, &aesCtx); CopyBlock16(pp, cc); CopyBlock(pSrc+AES_BLK_SIZE, cc, partBlockSize); encBlocklast %= BYTESIZE; if(encBlocklast) { Ipp8u partBlockMask = (Ipp8u)((0xFF)<<((BYTESIZE -encBlocklast) %BYTESIZE)); Ipp8u x = pSrc[AES_BLK_SIZE+partBlockSize]; Ipp8u y = cc[partBlockSize]; x = (x & partBlockMask) | (y & ~partBlockMask); cc[partBlockSize] = x; pp[partBlockSize] &= partBlockMask; partBlockSize++; } cpAES_XTS_DecBlock(pDst, cc, tweakCT, &aesCtx); CopyBlock(pp, pDst+AES_BLK_SIZE, partBlockSize); /* clear secret data */ PurgeBlock(pp, sizeof(pp)); } } while(0); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_xtsencrypt.c000066400000000000000000000134421470420105600251570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS Functions (IEEE P1619) // // Contents: // ippsAES_XTSEncrypt() // */ #include "owncp.h" #include "pcpaesmxts.h" #include "pcptool.h" #include "pcpaesmxtsstuff.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif static void cpAES_XTS_EncBlock(Ipp8u* ctxt, const Ipp8u* ptxt, const Ipp8u* tweak, const IppsAESSpec* pEncCtx) { /* pre-whitening */ XorBlock16(ptxt, tweak, ctxt); /* encryption */ ippsAESEncryptECB(ctxt, ctxt, AES_BLK_SIZE, pEncCtx); /* post-whitening */ XorBlock16(ctxt, tweak, ctxt); } /*F* // Name: ippsAES_XTSEncrypt // // Purpose: AES-XTS encryption. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pTweak ==NULL // pCtx == NULL // ippStsLengthErr bitLen <128 // ippStsContextMatchErr !VALID_AES_XTS_ID(pCtx) // ippStsBadArgErr !IsLegalGeometry(startCipherBlkNo, // bitLen, pCtx->duBitsize) // ippStsNoErr no errors // // Parameters: // pSrc points input buffer // pDst points output buffer // bitLen length of the input buffer in bits // startCipherBlkNo number of the first block for data unit // pTweak points tweak value // pCtx points AES_XTS context // *F*/ IPPFUN(IppStatus, ippsAES_XTSEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int bitLen, const IppsAES_XTSSpec* pCtx, const Ipp8u* pTweak, int startCipherBlkNo)) { /* test pointers */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_XTS_ID(pCtx), ippStsContextMatchErr); /* test data pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pTweak); /* test startCipherBlkNo and bitLen */ IPP_BADARG_RET(bitLen < IPP_AES_BLOCK_BITSIZE, ippStsLengthErr); IPP_BADARG_RET(!IsLegalGeometry(startCipherBlkNo, bitLen, pCtx->duBitsize), ippStsBadArgErr); { __ALIGN16 Ipp8u tweakCT[AES_BLK_SIZE]; { /* encrypt tweak */ const IppsAESSpec* ptwkAES = &pCtx->tweakAES; RijnCipher encoder = RIJ_ENCODER(ptwkAES); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pTweak, tweakCT, RIJ_NR(ptwkAES), RIJ_EKEYS(ptwkAES), RijEncSbox/*NULL*/); #else encoder(pTweak, tweakCT, RIJ_NR(ptwkAES), RIJ_EKEYS(ptwkAES), NULL); #endif /* update tweakCT */ for(; startCipherBlkNo>0; startCipherBlkNo--) gf_mul_by_primitive(tweakCT); } /* XTS encryption */ { const IppsAESSpec* pdatAES = &pCtx->datumAES; int encBlocks = bitLen/IPP_AES_BLOCK_BITSIZE; int encBlocklast = bitLen%IPP_AES_BLOCK_BITSIZE; if(encBlocklast) encBlocks--; /* encrypt data blocks */ if( encBlocks>0) { #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use Intel(R) AES New Instructions version if possible */ if(AES_NI_ENABLED==RIJ_AESNI(pdatAES)) { #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { cpAESEncryptXTS_VAES(pDst, pSrc, encBlocks, RIJ_EKEYS(pdatAES), RIJ_NR(pdatAES), tweakCT); } else #endif cpAESEncryptXTS_AES_NI(pDst, pSrc, encBlocks, RIJ_EKEYS(pdatAES), RIJ_NR(pdatAES), tweakCT); pSrc += encBlocks*AES_BLK_SIZE; pDst += encBlocks*AES_BLK_SIZE; } else #endif { for(; encBlocks>0; encBlocks--) { cpAES_XTS_EncBlock(pDst, pSrc, tweakCT, pdatAES); gf_mul_by_primitive(tweakCT); pSrc += AES_BLK_SIZE; pDst += AES_BLK_SIZE; } } } /* "stealing" - encrypt last partial block if is */ if(encBlocklast) { int partBlockSize = encBlocklast/BYTESIZE; __ALIGN16 Ipp8u cc[AES_BLK_SIZE]; __ALIGN16 Ipp8u pp[AES_BLK_SIZE]; cpAES_XTS_EncBlock(cc, pSrc, tweakCT, pdatAES); gf_mul_by_primitive(tweakCT); CopyBlock16(cc, pp); CopyBlock(pSrc+AES_BLK_SIZE, pp, partBlockSize); encBlocklast %= BYTESIZE; if(encBlocklast) { Ipp8u partBlockMask = (Ipp8u)((0xFF)<<((BYTESIZE -encBlocklast) %BYTESIZE)); Ipp8u x = pSrc[AES_BLK_SIZE+partBlockSize]; Ipp8u y = cc[partBlockSize]; x = (x & partBlockMask) | (y & ~partBlockMask); pp[partBlockSize] = x; cc[partBlockSize] &= partBlockMask; partBlockSize++; } cpAES_XTS_EncBlock(pDst, pp, tweakCT, pdatAES); CopyBlock(cc, pDst+AES_BLK_SIZE, partBlockSize); } return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_xtsencrypt_direct.c000066400000000000000000000176661470420105600265250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS Functions (IEEE P1619) // // Contents: // ippsAESEncryptXTS_Direct() // */ #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaesmxtsstuff.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if !defined AES_BLK_SIZE #define AES_BLK_SIZE (IPP_AES_BLOCK_BITSIZE/BITSIZE(Ipp8u)) #endif #define AES_BLKS_PER_BUFFER (32) /*F* // Name: ippsAESEncryptXTS_Direct // // Purpose: AES-XTS encryption (see IEEE P1619-2007). // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pDst == NULL // pTweak ==NULL // pKey ==NULL // ippStsLengthErr dataUnitBitsize <128 // keyBitsize != 256, !=512 // ippStsBadArgErr aesBlkNo >= dataUnitBitsize/IPP_AES_BLOCK_BITSIZE // aesBlkNo < 0 // [Only in FIPS-compliance mode]: Indicates an error // condition if tweak key is equal to the data key // ippStsNoErr no errors // // Parameters: // pSrc points input buffer // pDst points output buffer // encBitsize length of the input/output buffer in bits // aesBlkNo number of the first block for data unit // ptweakPT points tweak value // pKey pointer to the XTS key // keyBitsize length of the key in bits // dataUnitBitsize length of Data Unit in bits // *F*/ static IppStatus cpAES_XTS_EncBlock(Ipp8u* ctxt, const Ipp8u* ptxt, const Ipp8u* tweak, const IppsAESSpec* pEncCtx) { IppStatus sts; /* pre-whitening */ XorBlock16(ptxt, tweak, ctxt); /* encryption */ sts = ippsAESEncryptECB(ctxt, ctxt, AES_BLK_SIZE, pEncCtx); /* post-whitening */ XorBlock16(ctxt, tweak, ctxt); return sts; } IPPFUN(IppStatus, ippsAESEncryptXTS_Direct,(const Ipp8u* pSrc, Ipp8u* pDst, int encBitsize, int aesBlkNo, const Ipp8u* pTweakPT, const Ipp8u* pKey, int keyBitsize, int dataUnitBitsize)) { /* test dataUnitBitsize */ IPP_BADARG_RET(dataUnitBitsize (1<<27), ippStsBadArgErr); /* test dataUnitBitsize and aesBlkNo */ IPP_BADARG_RET(((dataUnitBitsize/IPP_AES_BLOCK_BITSIZE)<=aesBlkNo) || (0>aesBlkNo), ippStsBadArgErr); int keySize = keyBitsize/2/8; const Ipp8u* pConfKey = pKey; const Ipp8u* pTweakKey = pKey+keySize; #ifdef IPPCP_FIPS_MODE /* test FIPS-compliance requirement pdatKey != ptwkKey */ int isEqu = cpIsEquBlock_ct(pConfKey, pTweakKey, keySize) & 1; IPP_BADARG_RET(isEqu, ippStsBadArgErr); #endif { IppStatus sts = ippStsNoErr; do { int encBlocks = encBitsize/IPP_AES_BLOCK_BITSIZE; int encBlocklast = encBitsize%IPP_AES_BLOCK_BITSIZE; __ALIGN16 IppsAESSpec aesCtx; __ALIGN16 Ipp8u tweakCT[AES_BLK_SIZE]; __ALIGN16 Ipp8u tmp[AES_BLKS_PER_BUFFER*AES_BLK_SIZE]; __ALIGN16 Ipp8u tmpDst[AES_BLKS_PER_BUFFER*AES_BLK_SIZE]; sts = ippsAESInit(pTweakKey, keySize, &aesCtx, sizeof(aesCtx)); if(ippStsNoErr!=sts) break; { RijnCipher encoder = RIJ_ENCODER(&aesCtx); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pTweakPT, tweakCT, RIJ_NR(&aesCtx), RIJ_EKEYS(&aesCtx), RijEncSbox/*NULL*/); #else encoder(pTweakPT, tweakCT, RIJ_NR(&aesCtx), RIJ_EKEYS(&aesCtx), NULL); #endif } sts = ippsAESInit(pConfKey, keySize, &aesCtx, sizeof(aesCtx)); if(ippStsNoErr!=sts) break; for(; aesBlkNo>0; aesBlkNo--) gf_mul_by_primitive(tweakCT); if(encBlocklast) encBlocks--; /* // encrypt data */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) /* use Intel(R) AES New Instructions version if possible */ if(AES_NI_ENABLED==RIJ_AESNI(&aesCtx)) { #if(_IPP32E>=_IPP32E_K1) if (IsFeatureEnabled(ippCPUID_AVX512VAES)) { cpAESEncryptXTS_VAES(pDst, pSrc, encBlocks, RIJ_EKEYS(&aesCtx), RIJ_NR(&aesCtx), tweakCT); } else #endif cpAESEncryptXTS_AES_NI(pDst, pSrc, encBlocks, RIJ_EKEYS(&aesCtx), RIJ_NR(&aesCtx), tweakCT); pSrc += encBlocks*AES_BLK_SIZE; pDst += encBlocks*AES_BLK_SIZE; } else #endif { for(; encBlocks>=AES_BLKS_PER_BUFFER && ippStsNoErr==sts; encBlocks-=AES_BLKS_PER_BUFFER) { /* compute whitening tweaks */ cpXTSwhitening(tmp, AES_BLKS_PER_BUFFER, tweakCT); /* pre-whitening */ cpXTSxor16(tmpDst, pSrc, tmp, AES_BLKS_PER_BUFFER); sts = ippsAESEncryptECB(tmpDst, pDst, AES_BLKS_PER_BUFFER*AES_BLK_SIZE, &aesCtx); /* post-whitening */ cpXTSxor16(pDst, pDst, tmp, AES_BLKS_PER_BUFFER); pSrc += AES_BLKS_PER_BUFFER*AES_BLK_SIZE; pDst += AES_BLKS_PER_BUFFER*AES_BLK_SIZE; } if(ippStsNoErr!=sts) break; if(encBlocks) { cpXTSwhitening(tmp, encBlocks, tweakCT); /* pre-whitening */ cpXTSxor16(tmpDst, pSrc, tmp, encBlocks); ippsAESEncryptECB(tmpDst, pDst, AES_BLK_SIZE*encBlocks, &aesCtx); /* post-whitening */ cpXTSxor16(pDst, pDst, tmp, encBlocks); pSrc += AES_BLK_SIZE*encBlocks; pDst += AES_BLK_SIZE*encBlocks; } } /* "stealing" - encrypt last partial block if is */ if(encBlocklast) { int partBlockSize = encBlocklast/BYTESIZE; __ALIGN16 Ipp8u cc[AES_BLK_SIZE]; __ALIGN16 Ipp8u pp[AES_BLK_SIZE]; cpAES_XTS_EncBlock(cc, pSrc, tweakCT, &aesCtx); gf_mul_by_primitive(tweakCT); CopyBlock16(cc, pp); CopyBlock(pSrc+AES_BLK_SIZE, pp, partBlockSize); encBlocklast %= BYTESIZE; if(encBlocklast) { Ipp8u partBlockMask = (Ipp8u)((0xFF)<<((BYTESIZE -encBlocklast) %BYTESIZE)); Ipp8u x = pSrc[AES_BLK_SIZE+partBlockSize]; Ipp8u y = cc[partBlockSize]; x = (x & partBlockMask) | (y & ~partBlockMask); pp[partBlockSize] = x; cc[partBlockSize] &= partBlockMask; partBlockSize++; } cpAES_XTS_EncBlock(pDst, pp, tweakCT, &aesCtx); CopyBlock(cc, pDst+AES_BLK_SIZE, partBlockSize); } } while(0); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaes_xtsinit.c000066400000000000000000000060641470420105600244400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS Functions (IEEE P1619) // // Contents: // ippsAES_XTSInit() // */ #include "owncp.h" #include "pcpaesmxts.h" #include "pcptool.h" /*F* // Name: ippsAES_XTSInit // // Purpose: Init AES_XTS context for future usage. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsMemAllocErr size of buffer is not match for operation // ippStsLengthErr keyLen != 16*8*2 && // != 32*8*2 // ippStsBadArgErr [Only in FIPS-compliance mode]: Indicates an error // condition if tweak key is equal to the data key // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length of the secret key in bits // pCtx pointer to the AES-XTS context // ctxSize available size (in bytes) of buffer above // duBitSize length of Data Unit in bits // *F*/ IPPFUN(IppStatus, ippsAES_XTSInit,(const Ipp8u* pKey, int keyLen, int duBitsize, IppsAES_XTSSpec* pCtx, int ctxSize)) { /* test key and keyLenBits */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(keyLen!=16*BYTESIZE*2 && keyLen!=32*BYTESIZE*2, ippStsLengthErr); /* test DU parameters */ IPP_BADARG_RET(duBitsize ctxSize, ippStsMemAllocErr); int keySize = keyLen/2/BYTESIZE; const Ipp8u* pdatKey = pKey; const Ipp8u* ptwkKey = pKey+keySize; #ifdef IPPCP_FIPS_MODE /* test FIPS-compliance requirement pdatKey != ptwkKey */ int isEqu = cpIsEquBlock_ct(pdatKey, ptwkKey, keySize) & 1; IPP_BADARG_RET(isEqu, ippStsBadArgErr); #endif { IppsAESSpec* pdatAES = &pCtx->datumAES; IppsAESSpec* ptwkAES = &pCtx->tweakAES; IppStatus sts = ippStsNoErr; sts = ippsAESInit(pdatKey, keySize, pdatAES, sizeof(IppsAESSpec)); if(ippStsNoErr!=sts) return sts; sts = ippsAESInit(ptwkKey, keySize, ptwkAES, sizeof(IppsAESSpec)); if(ippStsNoErr!=sts) return sts; AES_XTS_SET_ID(pCtx); pCtx->duBitsize = duBitsize; return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaesauthccm.h000066400000000000000000000065731470420105600242350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message Authentication Algorithm // Internal Definitions and Internal Functions Prototypes // // */ #if !defined(_CP_AES_CCM_H) #define _CP_AES_CCM_H #include "pcprij.h" #include "pcpaesm.h" struct _cpAES_CCM { Ipp32u idCtx; /* CCM ID */ Ipp64u msgLen; /* length of message to be processed */ Ipp64u lenProcessed; /* message length has been processed */ Ipp32u tagLen; /* length of authentication tag */ Ipp32u counterVal; /* current counter value */ Ipp8u ctr0[MBS_RIJ128]; /* counter value */ Ipp8u s0[MBS_RIJ128]; /* S0 = ENC(CTR0) content */ Ipp8u si[MBS_RIJ128]; /* Si = ENC(CTRi) content */ Ipp8u blk[MBS_RIJ128]; /* temporary data container */ Ipp8u mac[MBS_RIJ128]; /* current MAC value */ Ipp8u cipher[sizeof(IppsAESSpec)]; }; /* alignment */ #define AESCCM_ALIGNMENT ((int)(sizeof(void*))) /* // access macros */ #define AESCCM_SET_ID(stt) ((stt)->idCtx = (Ipp32u)idCtxAESCCM ^ (Ipp32u)IPP_UINT_PTR(stt)) #define AESCCM_MSGLEN(stt) ((stt)->msgLen) #define AESCCM_LENPRO(stt) ((stt)->lenProcessed) #define AESCCM_TAGLEN(stt) ((stt)->tagLen) #define AESCCM_COUNTER(stt) ((stt)->counterVal) #define AESCCM_CTR0(stt) ((stt)->ctr0) #define AESCCM_S0(stt) ((stt)->s0) #define AESCCM_Si(stt) ((stt)->si) #define AESCCM_BLK(stt) ((stt)->blk) #define AESCCM_MAC(stt) ((stt)->mac) #define AESCCM_CIPHER(stt) (IppsAESSpec*)(&((stt)->cipher)) /* valid context ID */ #define VALID_AESCCM_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxAESCCM) /* // Internal functions */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #define AuthEncrypt_RIJ128_AES_NI OWNAPI(AuthEncrypt_RIJ128_AES_NI) IPP_OWN_DECL (void, AuthEncrypt_RIJ128_AES_NI, (const Ipp8u* inpBlk, Ipp8u* outBlk, int nr, const void* pRKey, Ipp32u len, void* pLocalCtx)) #define DecryptAuth_RIJ128_AES_NI OWNAPI(DecryptAuth_RIJ128_AES_NI) IPP_OWN_DECL (void, DecryptAuth_RIJ128_AES_NI, (const Ipp8u* inpBlk, Ipp8u* outBlk, int nr, const void* pRKey, Ipp32u len, void* pLocalCtx)) #endif /* Counter block formatter */ static Ipp8u* CounterEnc(Ipp32u* pBuffer, int fmt, Ipp64u counter) { #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) pBuffer[0] = ENDIANNESS(IPP_HIDWORD(counter)); pBuffer[1] = ENDIANNESS(IPP_LODWORD(counter)); #else pBuffer[0] = IPP_HIDWORD(counter); pBuffer[1] = IPP_LODWORD(counter); #endif return (Ipp8u*)pBuffer + 8 - fmt; } static int cpSizeofCtx_AESCCM(void) { return sizeof(IppsAES_CCMState); } #endif /* _CP_AES_CCM_H*/ cryptography-primitives-1.0.0/sources/ippcp/pcpaesauthgcm.h000066400000000000000000000263161470420105600242360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message Authentication Algorithm // Internal Definitions and Internal Functions Prototypes // // */ #if !defined(_CP_AESAUTH_GCM_H) #define _CP_AESAUTH_GCM_H #include "owncp.h" #include "pcpaesm.h" #if(_IPP32E < _IPP32E_K0) #define BLOCK_SIZE (MBS_RIJ128) /* GCM Hash prototype: GHash = GHash*HKey mod G() */ IPP_OWN_FUNPTR (void, MulGcm_, (Ipp8u* pGHash, const Ipp8u* pHKey, const void* pParam)) /* GCM Authentication prototype: GHash = (GHash^src[])*HKey mod G() */ IPP_OWN_FUNPTR (void, Auth_, (Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pHKey, const void* pParam)) /* GCM Encrypt_Authentication prototype */ IPP_OWN_FUNPTR (void, Encrypt_, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) /* GCM Authentication_Decrypt prototype */ IPP_OWN_FUNPTR (void, Decrypt_, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) typedef enum { GcmInit, GcmIVprocessing, GcmAADprocessing, GcmTXTprocessing } GcmState; struct _cpAES_GCM { Ipp32u idCtx; /* AES-GCM id */ GcmState state; /* GCM state: Init, IV|AAD|TXT processing */ Ipp64u ivLen; /* IV length (bytes) */ Ipp64u aadLen; /* header length (bytes) */ Ipp64u txtLen; /* text length (bytes) */ int bufLen; /* stuff buffer length */ __ALIGN16 /* aligned buffers */ Ipp8u counter[BLOCK_SIZE]; /* counter */ Ipp8u ecounter0[BLOCK_SIZE]; /* encrypted initial counter */ Ipp8u ecounter[BLOCK_SIZE]; /* encrypted counter */ Ipp8u ghash[BLOCK_SIZE]; /* ghash accumulator */ MulGcm_ hashFun; /* AES-GCM mul function */ Auth_ authFun; /* authentication function */ Encrypt_ encFun; /* encryption & authentication */ Decrypt_ decFun; /* authentication & decryption */ __ALIGN16 /* aligned AES context */ IppsAESSpec cipher; #if (_AES_PROB_NOISE == _FEATURE_ON_) __ALIGN16 cpAESNoiseParams noiseParams; #endif __ALIGN16 /* aligned pre-computed data: */ Ipp8u multiplier[BLOCK_SIZE]; /* - (default) hKey */ /* - (aes_ni) hKey*t, (hKey*t)^2, (hKey*t)^4 */ /* - (avx2_vaes) 16 vectors by 128-bit values hKey<<1, hKey^2<<1, hKey^3<<1, hKey^4<<1, hKey^5<<1, hKey^6<<1, hKey^7<<1, hKey^8<<1, hKey^9<<1, hKey^10<<1, hKey^11<<1, hKey^12<<1, hKey^13<<1, hKey^14<<1, hKey^15<<1, hKey^16<<1, */ /* - (vaes_ni) 8 reverted ordered vectors by 4 128-bit values. hKeys derivations in the multiplier[] array in order of appearance (zero-index starts from the left): hKey^4<<1, hKey^3<<1, hKey^2<<1, hKey<<1, hKey^8<<1, hKey^7<<1, hKey^6<<1, hKey^5<<1, hKey^12<<1, hKey^11<<1, hKey^10<<1, hKey^9<<1, hKey^16<<1, hKey^15<<1, hKey^14<<1, hKey^13<<1, ... ... */ /* - (safe) hKey*(t^i), i=0,...,127 */ }; #define CTR_POS 12 /* alignment */ #define AESGCM_ALIGNMENT (16) #define PRECOMP_DATA_SIZE_AES_NI_AESGCM (BLOCK_SIZE*4) #define PRECOMP_DATA_SIZE_AVX2_VAES_AESGCM (BLOCK_SIZE*16) #define PRECOMP_DATA_SIZE_VAES_NI_AESGCM (BLOCK_SIZE*16*2) #define PRECOMP_DATA_SIZE_FAST2K (BLOCK_SIZE*128) /* // Useful macros */ #define AESGCM_SET_ID(context) ((context)->idCtx = (Ipp32u)idCtxAESGCM ^ (Ipp32u)IPP_UINT_PTR(context)) #define AESGCM_STATE(context) ((context)->state) #define AESGCM_IV_LEN(context) ((context)->ivLen) #define AESGCM_AAD_LEN(context) ((context)->aadLen) #define AESGCM_TXT_LEN(context) ((context)->txtLen) #define AESGCM_BUFLEN(context) ((context)->bufLen) #define AESGCM_COUNTER(context) ((context)->counter) #define AESGCM_ECOUNTER0(context) ((context)->ecounter0) #define AESGCM_ECOUNTER(context) ((context)->ecounter) #define AESGCM_GHASH(context) ((context)->ghash) #define AESGCM_HASH(context) ((context)->hashFun) #define AESGCM_AUTH(context) ((context)->authFun) #define AESGCM_ENC(context) ((context)->encFun) #define AESGCM_DEC(context) ((context)->decFun) #define AESGCM_CIPHER(context) (IppsAESSpec*)(&((context)->cipher)) #if (_AES_PROB_NOISE == _FEATURE_ON_) #define AESGCM_NOISE_PARAMS(context) ((context)->noiseParams) #endif #define AESGCM_HKEY(context) ((context)->multiplier) #define AESGCM_CPWR(context) ((context)->multiplier) #define AES_GCM_MTBL(context) ((context)->multiplier) #define AESGCM_VALID_ID(context) ((((context)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((context))) == (Ipp32u)idCtxAESGCM) #if 0 __IPPCP_INLINE void IncrementCounter32(Ipp8u* pCtr) { int i; for(i=BLOCK_SIZE-1; i>=CTR_POS && 0==(Ipp8u)(++pCtr[i]); i--) ; } #endif __IPPCP_INLINE void IncrementCounter32(Ipp8u* pCtr) { Ipp32u* pCtr32 = (Ipp32u*)pCtr; Ipp32u ctrVal = pCtr32[3]; ctrVal = ENDIANNESS32(ctrVal); ctrVal++; ctrVal = ENDIANNESS32(ctrVal); pCtr32[3] = ctrVal; } #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #define AesGcmPrecompute_avx2_vaes OWNAPI(AesGcmPrecompute_avx2_vaes) IPP_OWN_DECL (void, AesGcmPrecompute_avx2_vaes, (Ipp8u* pPrecomputeData, const Ipp8u* pHKey)) #define AesGcmPrecompute_avx OWNAPI(AesGcmPrecompute_avx) IPP_OWN_DECL (void, AesGcmPrecompute_avx, (Ipp8u* pPrecomputeData, const Ipp8u* pHKey)) #define AesGcmMulGcm_avx OWNAPI(AesGcmMulGcm_avx) IPP_OWN_DECL (void, AesGcmMulGcm_avx, (Ipp8u* pGhash, const Ipp8u* pHkey, const void* pParam)) #define AesGcmAuth_avx OWNAPI(AesGcmAuth_avx) IPP_OWN_DECL (void, AesGcmAuth_avx, (Ipp8u* pGhash, const Ipp8u* pSrc, int len, const Ipp8u* pHkey, const void* pParam)) #define wrpAesGcmEnc_avx OWNAPI(wrpAesGcmEnc_avx) IPP_OWN_DECL (void, wrpAesGcmEnc_avx, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #define wrpAesGcmDec_avx OWNAPI(wrpAesGcmDec_avx) IPP_OWN_DECL (void, wrpAesGcmDec_avx, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #define AesGcmEnc_avx OWNAPI(AesGcmEnc_avx) IPP_OWN_DECL (void, AesGcmEnc_avx, (Ipp8u* pDst, const Ipp8u* pSrc, int len, RijnCipher cipher, int nr, const Ipp8u* pKeys, Ipp8u* pGhash, Ipp8u* pCnt, Ipp8u* pECnt, const Ipp8u* pMuls)) #define AesGcmDec_avx OWNAPI(AesGcmDec_avx) IPP_OWN_DECL (void, AesGcmDec_avx, (Ipp8u* pDst, const Ipp8u* pSrc, int len, RijnCipher cipher, int nr, const Ipp8u* pKeys, Ipp8u* pGhash, Ipp8u* pCnt, Ipp8u* pECnt, const Ipp8u* pMuls)) #endif #if(_IPP32E>=_IPP32E_K0) #define AesGcmPrecompute_vaes OWNAPI(AesGcmPrecompute_vaes) IPP_OWN_DECL (void, AesGcmPrecompute_vaes, (Ipp8u* const pPrecomputeData, const Ipp8u* const pHKey)) #define AesGcmMulGcm_vaes OWNAPI(AesGcmMulGcm_vaes) IPP_OWN_DECL (void, AesGcmMulGcm_vaes, (Ipp8u* pGhash, const Ipp8u* pHkey, const void* pParam)) #define AesGcmAuth_vaes OWNAPI(AesGcmAuth_vaes) IPP_OWN_DECL (void, AesGcmAuth_vaes, (Ipp8u* pGhash, const Ipp8u* pSrc, int len, const Ipp8u* pHkey, const void* pParam)) #define AesGcmEnc_vaes OWNAPI(AesGcmEnc_vaes) IPP_OWN_DECL (void, AesGcmEnc_vaes, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #define AesGcmDec_vaes OWNAPI(AesGcmDec_vaes) IPP_OWN_DECL (void, AesGcmDec_vaes, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #endif /* _IPP32E>=_IPP32E_K0 */ #define AesGcmPrecompute_table2K OWNAPI(AesGcmPrecompute_table2K) IPP_OWN_DECL (void, AesGcmPrecompute_table2K, (Ipp8u* pPrecomputeData, const Ipp8u* pHKey)) /* #define AesGcmMulGcm_table2K OWNAPI(AesGcmMulGcm_table2K) */ /* IPP_OWN_DECL (void, AesGcmMulGcm_table2K, (Ipp8u* pGhash, const Ipp8u* pHkey, const void* pParam)) */ #define AesGcmMulGcm_table2K_ct OWNAPI(AesGcmMulGcm_table2K_ct) IPP_OWN_DECL (void, AesGcmMulGcm_table2K_ct, (Ipp8u* pGhash, const Ipp8u* pHkey, const void* pParam)) /* #define AesGcmAuth_table2K OWNAPI(AesGcmAuth_table2K) */ /* IPP_OWN_DECL (void, AesGcmAuth_table2K, (Ipp8u* pGhash, const Ipp8u* pSrc, int len, const Ipp8u* pHkey, const void* pParam)) */ #define AesGcmAuth_table2K_ct OWNAPI(AesGcmAuth_table2K_ct) IPP_OWN_DECL (void, AesGcmAuth_table2K_ct, (Ipp8u* pGhash, const Ipp8u* pSrc, int len, const Ipp8u* pHkey, const void* pParam)) #define wrpAesGcmEnc_table2K OWNAPI(wrpAesGcmEnc_table2K) IPP_OWN_DECL (void, wrpAesGcmEnc_table2K, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #define wrpAesGcmDec_table2K OWNAPI(wrpAesGcmDec_table2K) IPP_OWN_DECL (void, wrpAesGcmDec_table2K, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) #define AesGcmEnc_vaes_avx2 OWNAPI(AesGcmEnc_vaes_avx2) IPP_OWN_DECL (void, AesGcmEnc_vaes_avx2, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #define AesGcmDec_vaes_avx2 OWNAPI(AesGcmDec_vaes_avx2) IPP_OWN_DECL (void, AesGcmDec_vaes_avx2, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pCtx)) #endif /* #if (_IPP==_IPP_H9) || (_IPP32E==_IPP32E_L9) */ extern const Ipp16u AesGcmConst_table[256]; /* precomputed reduction table */ static int cpSizeofCtx_AESGCM(void) { int precomp_size; #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if (IsFeatureEnabled(ippCPUID_AVX2VAES|ippCPUID_AVX2VCLMUL)) precomp_size = PRECOMP_DATA_SIZE_AVX2_VAES_AESGCM; else if (IsFeatureEnabled(ippCPUID_AES|ippCPUID_CLMUL)) precomp_size = PRECOMP_DATA_SIZE_AES_NI_AESGCM; else #endif precomp_size = PRECOMP_DATA_SIZE_FAST2K; /* decrease precomp_size as soon as BLOCK_SIZE bytes already reserved in context */ precomp_size -= BLOCK_SIZE; return (Ipp32s)sizeof(IppsAES_GCMState) +precomp_size +AESGCM_ALIGNMENT-1; } #endif // (_IPP32E < _IPP32E_K0) #endif /* _CP_AESAUTH_GCM_H*/ cryptography-primitives-1.0.0/sources/ippcp/pcpaesauthgcm_avx512.h000066400000000000000000000135561470420105600253460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES GCM optimized for AVX512 and AVX512-VAES features // Internal Definitions // // */ #ifndef _CP_AESAUTH_GCM_AVX512_H #define _CP_AESAUTH_GCM_AVX512_H #include "owndefs.h" #include "owncp.h" #if(_IPP32E>=_IPP32E_K0) #include "pcprij.h" #include "aes_gcm_vaes.h" #include "aes_gcm_avx512.h" #include "aes_gcm_avx512_structures.h" // Prototypes for internal functions from IPsec // IV processing IPP_OWN_FUNPTR (void, IvUpdate_, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *iv, const Ipp64u iv_len)) IPP_OWN_FUNPTR (void, IvFinalize_, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *iv, const Ipp64u iv_len, const Ipp64u iv_general_len)) // AAD processing IPP_OWN_FUNPTR (void, AadUpdate_, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, const Ipp8u *aad, const Ipp64u aad_len)) // GCM multiplication IPP_OWN_FUNPTR (void, MulGcm_, (const struct gcm_key_data *key_data, Ipp8u *ghash)) // Encryption-authentication IPP_OWN_FUNPTR (void, EncryptUpdate_, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) // Decryption-verification IPP_OWN_FUNPTR (void, DecryptUpdate_, (const struct gcm_key_data *key_data, struct gcm_context_data *context_data, Ipp8u *out, const Ipp8u *in, Ipp64u len)) // Get tag IPP_OWN_FUNPTR (void, GetTag_, (const struct gcm_key_data *key_data, const struct gcm_context_data *context_data, Ipp8u *auth_tag, Ipp64u auth_tag_len)) typedef enum { GcmInit, GcmIVprocessing, GcmAADprocessing, GcmTXTprocessing } GcmState; #define BLOCK_SIZE (MBS_RIJ128) // Structure modified to work with functions from IPsec struct _cpAES_GCM { Ipp32u idCtx; /* AES-GCM id */ GcmState state; /* GCM state: Init, IV|AAD|TXT processing */ Ipp64u ivLen; /* IV length (bytes) */ Ipp64u aadLen; /* header length (bytes) */ Ipp64u txtLen; /* text length (bytes) */ int bufLen; /* stuff buffer length */ __ALIGN16 /* aligned buffers */ Ipp8u counter[BLOCK_SIZE]; /* counter */ Ipp8u ecounter0[BLOCK_SIZE]; /* encrypted initial counter */ Ipp8u ecounter[BLOCK_SIZE]; /* encrypted counter */ Ipp8u ghash[BLOCK_SIZE]; /* ghash accumulator */ __ALIGN16 struct gcm_key_data key_data; __ALIGN16 struct gcm_context_data context_data; Ipp64u keyLen; /* key length (bytes) */ IvUpdate_ ivUpdateFunc; // IV processing IvFinalize_ ivFinalizeFunc; AadUpdate_ aadUpdateFunc; // AAD processing MulGcm_ gcmMulFunc; // GCM multiplication EncryptUpdate_ encryptUpdateFunc; // Encryption-authentication DecryptUpdate_ decryptUpdateFunc; // Decryption-verification GetTag_ getTagFunc; // Get tag #if (_AES_PROB_NOISE == _FEATURE_ON_) __ALIGN16 cpAESNoiseParams noiseParams; #endif }; // Alignment #define AESGCM_ALIGNMENT (16) // Useful macros #define AESGCM_SET_ID(context) ((context)->idCtx = (Ipp32u)idCtxAESGCM ^ (Ipp32u)IPP_UINT_PTR(context)) #define AESGCM_STATE(context) ((context)->state) #define AESGCM_IV_LEN(context) ((context)->ivLen) #define AESGCM_COUNTER(context) ((context)->counter) #define AESGCM_ECOUNTER0(context) ((context)->ecounter0) #define AESGCM_ECOUNTER(context) ((context)->ecounter) #define AES_GCM_KEY_DATA(context) ((context)->key_data) #define AES_GCM_CONTEXT_DATA(context) ((context)->context_data) #define AES_GCM_KEY_LEN(context) ((context)->keyLen) #define AES_GCM_IV_UPDATE(context) ((context)->ivUpdateFunc) #define AES_GCM_IV_FINALIZE(context) ((context)->ivFinalizeFunc) #define AES_GCM_AAD_UPDATE(context) ((context)->aadUpdateFunc) #define AES_GCM_GMUL(context) ((context)->gcmMulFunc) #define AES_GCM_ENCRYPT_UPDATE(context) ((context)->encryptUpdateFunc) #define AES_GCM_DECRYPT_UPDATE(context) ((context)->decryptUpdateFunc) #define AES_GCM_GET_TAG(context) ((context)->getTagFunc) // Fields retargeted to IPsec context #define AESGCM_GHASH(context) (&(AES_GCM_CONTEXT_DATA(context).aad_hash[0])) #define AESGCM_TXT_LEN(context) (AES_GCM_CONTEXT_DATA(context).in_length) #define AESGCM_AAD_LEN(context) (AES_GCM_CONTEXT_DATA(context).aad_length) #define AESGCM_BUFLEN(context) (AES_GCM_CONTEXT_DATA(context).partial_block_length) #if (_AES_PROB_NOISE == _FEATURE_ON_) #define AESGCM_NOISE_PARAMS(ctx) ((ctx)->noiseParams) #endif #define AESGCM_VALID_ID(context) ((((context)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((context))) == (Ipp32u)idCtxAESGCM) static int cpSizeofCtx_AESGCM(void) { return (Ipp32s)sizeof(IppsAES_GCMState) + AESGCM_ALIGNMENT-1; } #endif // (_IPP32E>=_IPP32E_K0) #endif // _CP_AESAUTH_GCM_AVX512_H cryptography-primitives-1.0.0/sources/ippcp/pcpaescmac_setupnoise.c000066400000000000000000000052021470420105600257510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-CMAC noise setup function // // Contents: // ippsAES_CMACSetupNoise // */ #include "owndefs.h" #include "owncp.h" #include "pcpcmac.h" #include "pcptool.h" /*F* // Name: ippsAES_CMACSetupNoise // // Purpose: AES-CMAC Setup Noise // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsContextMatchErr AES context is invalid // ippStsLengthErr noiseLevel > 4 // ippStsNotSupportedModeErr Mistletoe3 mitigation isn't applicable for current CPU // (no support of Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) or // vector extensions of Intel® AES-NI) // ippStsNoErr no errors // // Parameters: // noiseLevel the value of this parameter is directly // proportional to the amount of noise injected // Increasing noise level by 1 means the delay // (performance impact) is doubled // pState pointer to the AES context // *F*/ IPPFUN(IppStatus, ippsAES_CMACSetupNoise,(Ipp32u noiseLevel, IppsAES_CMACState* pState)) { #if (_AES_PROB_NOISE == _FEATURE_ON_) /* test context */ IPP_BAD_PTR1_RET(pState); /* test ID */ IPP_BADARG_RET(!VALID_AESCMAC_ID(pState), ippStsContextMatchErr); /* test noise level range */ IPP_BADARG_RET(noiseLevel > 4, ippStsLengthErr); cpAESNoiseParams *params = (cpAESNoiseParams *)&AESCMAC_NOISE_PARAMS(pState); /* set up the parameters with initial values */ AES_NOISE_RAND(params) = 0; AES_NOISE_LEVEL(params) = noiseLevel; return ippStsNoErr; #else /* To remove MSVC warning C4100: 'XXX': unreferenced formal parameter*/ IPP_UNREFERENCED_PARAMETER(noiseLevel); IPP_UNREFERENCED_PARAMETER(pState); return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpaesdecryptofb.c000066400000000000000000000057761470420105600247510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES decryption (OFB mode) // // Contents: // ippsAESDecryptOFB() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_ofb.h" /*F* // Name: ippsAESDecryptOFB // // Purpose: Decrypts byte data stream according to Rijndael in OFB mode. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsOFBSizeErr (1>ofbBlkSize || ofbBlkSize>MBS_RIJ128) // ippStsUnderRunErr (len%ofbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len output buffer length (in bytes) // ofbBlkSize OFB block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector *F*/ IPPFUN(IppStatus, ippsAESDecryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test OFB value */ IPP_BADARG_RET(((1>ofbBlkSize) || (MBS_RIJ128=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { if(ofbBlkSize==MBS_RIJ128) EncryptOFB128_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, pIV); else EncryptOFB_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, ofbBlkSize, pIV); return ippStsNoErr; } else #endif { cpProcessAES_ofb8(pSrc, pDst, len, ofbBlkSize, pCtx, pIV); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaesencryptofb.c000066400000000000000000000057751470420105600247620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES encryption (OFB mode) // // Contents: // ippsAESEncryptOFB() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaes_ofb.h" /*F* // Name: ippsAESEncryptOFB // // Purpose: Encrypts byte data stream according to Rijndael in OFB mode. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_AES_ID() // ippStsLengthErr len <1 // ippStsOFBSizeErr (1>ofbBlkSize || ofbBlkSize>MBS_RIJ128) // ippStsUnderRunErr (len%ofbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input buffer length (in bytes) // ofbBlkSize OFB block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector *F*/ IPPFUN(IppStatus, ippsAESEncryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsAESSpec* pCtx, Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test OFB value */ IPP_BADARG_RET(((1>ofbBlkSize) || (MBS_RIJ128=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(AES_NI_ENABLED==RIJ_AESNI(pCtx)) { if(ofbBlkSize==MBS_RIJ128) EncryptOFB128_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, pIV); else EncryptOFB_RIJ128_AES_NI(pSrc, pDst, RIJ_NR(pCtx), RIJ_EKEYS(pCtx), len, ofbBlkSize, pIV); return ippStsNoErr; } else #endif { cpProcessAES_ofb8(pSrc, pDst, len, ofbBlkSize, pCtx, pIV); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaesgcm_setupnoise.c000066400000000000000000000054571470420105600256300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-GCM noise setup function // // Contents: // ippsAES_GCMSetupNoise // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcptool.h" #include "pcpaesauthgcm.h" #include "pcpaesauthgcm_avx512.h" /*F* // Name: ippsAES_GCMSetupNoise // // Purpose: AES-GCM Setup Noise // // Returns: Reason: // ippStsNullPtrErr pState == NULL // ippStsContextMatchErr AES context is invalid // ippStsLengthErr noiseLevel > 4 // ippStsNotSupportedModeErr Mistletoe3 mitigation isn't applicable for current CPU // (no support of Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) or // vector extensions of Intel® AES-NI) // ippStsNoErr no errors // // Parameters: // noiseLevel the value of this parameter is directly // proportional to the amount of noise injected // Increasing noise level by 1 means the delay // (performance impact) is doubled // pState pointer to the AES context // *F*/ IPPFUN(IppStatus, ippsAES_GCMSetupNoise,(Ipp32u noiseLevel, IppsAES_GCMState* pState)) { #if (_AES_PROB_NOISE == _FEATURE_ON_) /* test context */ IPP_BAD_PTR1_RET(pState); /* use aligned context */ pState = (IppsAES_GCMState*)(IPP_ALIGNED_PTR(pState, AESGCM_ALIGNMENT)); /* test state ID */ IPP_BADARG_RET(!AESGCM_VALID_ID(pState), ippStsContextMatchErr); /* test noise level range */ IPP_BADARG_RET(noiseLevel > 4, ippStsLengthErr); cpAESNoiseParams *params = (cpAESNoiseParams *)&AESGCM_NOISE_PARAMS(pState); /* set up the parameters with initial values */ AES_NOISE_RAND(params) = 0; AES_NOISE_LEVEL(params) = noiseLevel; return ippStsNoErr; #else /* To remove MSVC warning C4100: 'XXX': unreferenced formal parameter*/ IPP_UNREFERENCED_PARAMETER(noiseLevel); IPP_UNREFERENCED_PARAMETER(pState); return ippStsNotSupportedModeErr; #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpaesgcmtableca.c000066400000000000000000000060631470420105600246600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) // // "fast" stuff // // Contents: // // */ #include "owndefs.h" #include "owncp.h" #if defined( _IPP_DATA ) __ALIGN64 const Ipp16u AesGcmConst_table[256] = { 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05, 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b, 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19, 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17, 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d, 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33, 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21, 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f, 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75, 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b, 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69, 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67, 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d, 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43, 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51, 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f, 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4, 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea, 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8, 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6, 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc, 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2, 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0, 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece, 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94, 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a, 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88, 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86, 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac, 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2, 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0, 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe }; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/pcpaesgcmtbl2k_mulpx.c000066400000000000000000000277531470420105600255410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) // // "fast" stuff // // Contents: // AesGcmMulGcm_table2K() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcptool.h" #include "pcpmask_ct.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E<_IPP32E_K0) typedef struct{ Ipp8u b[16]; } AesGcmPrecompute_GF; #if !((_IPP==_IPP_V8) || (_IPP==_IPP_P8) || \ (_IPP==_IPP_S8) || (_IPP>=_IPP_G9) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) /* // AesGcmMulGcm_def|safe(Ipp8u* pGhash, const Ipp8u* pHKey) // // Ghash = Ghash * HKey mod G() */ __IPPCP_INLINE Ipp16u getAesGcmConst_table_ct(int idx) { #define TBL_SLOTS_REP_READ (Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(AesGcmConst_table[0])) const BNU_CHUNK_T* TblEntry = (BNU_CHUNK_T*)AesGcmConst_table; BNU_CHUNK_T idx_sel = (BNU_CHUNK_T)(idx / TBL_SLOTS_REP_READ); /* selection index */ BNU_CHUNK_T i; BNU_CHUNK_T selection = 0; for (i = 0; i>= (idx & (TBL_SLOTS_REP_READ-1)) * sizeof(Ipp16u)*8; return (Ipp16u)(selection & 0xFFffFF); #undef TBL_SLOTS_REP_READ } #if 0 void AesGcmMulGcm_table2K(Ipp8u* pGhash, const Ipp8u* pPrecomputeData, const void* pParam) { __ALIGN16 Ipp8u t5[BLOCK_SIZE]; __ALIGN16 Ipp8u t4[BLOCK_SIZE]; __ALIGN16 Ipp8u t3[BLOCK_SIZE]; __ALIGN16 Ipp8u t2[BLOCK_SIZE]; int nw; Ipp32u a; IPP_UNREFERENCED_PARAMETER(pParam); #if 0 XorBlock16(t5, t5, t5); XorBlock16(t4, t4, t4); XorBlock16(t3, t3, t3); XorBlock16(t2, t2, t2); #endif PadBlock(0, t5, sizeof(t5)); PadBlock(0, t4, sizeof(t4)); PadBlock(0, t3, sizeof(t3)); PadBlock(0, t2, sizeof(t2)); for(nw=0; nw<4; nw++) { Ipp32u hashdw = ((Ipp32u*)pGhash)[nw]; a = hashdw & 0xf0f0f0f0; XorBlock16(t5, pPrecomputeData+1024+EBYTE(a,1)+256*nw, t5); XorBlock16(t4, pPrecomputeData+1024+EBYTE(a,0)+256*nw, t4); XorBlock16(t3, pPrecomputeData+1024+EBYTE(a,3)+256*nw, t3); XorBlock16(t2, pPrecomputeData+1024+EBYTE(a,2)+256*nw, t2); a = (hashdw<<4) & 0xf0f0f0f0; XorBlock16(t5, pPrecomputeData+EBYTE(a,1)+256*nw, t5); XorBlock16(t4, pPrecomputeData+EBYTE(a,0)+256*nw, t4); XorBlock16(t3, pPrecomputeData+EBYTE(a,3)+256*nw, t3); XorBlock16(t2, pPrecomputeData+EBYTE(a,2)+256*nw, t2); } XorBlock(t2+1, t3, t2+1, BLOCK_SIZE-1); XorBlock(t5+1, t2, t5+1, BLOCK_SIZE-1); XorBlock(t4+1, t5, t4+1, BLOCK_SIZE-1); nw = t3[BLOCK_SIZE-1]; //a = (Ipp32u)AesGcmConst_table[nw]; a = (Ipp32u)getAesGcmConst_table_ct(nw); a <<= 8; nw = t2[BLOCK_SIZE-1]; //a ^= (Ipp32u)AesGcmConst_table[nw]; a ^= (Ipp32u)getAesGcmConst_table_ct(nw); a <<= 8; nw = t5[BLOCK_SIZE-1]; //a ^= (Ipp32u)AesGcmConst_table[nw]; a ^= (Ipp32u)getAesGcmConst_table_ct(nw); XorBlock(t4, &a, t4, sizeof(Ipp32u)); CopyBlock16(t4, pGhash); } #endif /* // CTE version of AesGcmMulGcm_table2K() */ #if (_IPP_ARCH ==_IPP_ARCH_EM64T) __IPPCP_INLINE void MaskedXorBlock16(const Ipp8u* pSrc1, const Ipp8u* pSrc2, Ipp8u* pDst, Ipp64u src2mask) { ((Ipp64u*)pDst)[0] = ((Ipp64u*)pSrc1)[0] ^ (((Ipp64u*)pSrc2)[0] & src2mask); ((Ipp64u*)pDst)[1] = ((Ipp64u*)pSrc1)[1] ^ (((Ipp64u*)pSrc2)[1] & src2mask); } #else /* IPP_ARCH == IPP_ARCH_IA32 */ __IPPCP_INLINE void MaskedXorBlock16(const Ipp8u* pSrc1, const Ipp8u* pSrc2, Ipp8u* pDst, Ipp32u src2mask) { ((Ipp32u*)pDst)[0] = ((Ipp32u*)pSrc1)[0] ^ (((Ipp32u*)pSrc2)[0] & src2mask); ((Ipp32u*)pDst)[1] = ((Ipp32u*)pSrc1)[1] ^ (((Ipp32u*)pSrc2)[1] & src2mask); ((Ipp32u*)pDst)[2] = ((Ipp32u*)pSrc1)[2] ^ (((Ipp32u*)pSrc2)[2] & src2mask); ((Ipp32u*)pDst)[3] = ((Ipp32u*)pSrc1)[3] ^ (((Ipp32u*)pSrc2)[3] & src2mask); } #endif IPP_OWN_DEFN (void, AesGcmMulGcm_table2K_ct, (Ipp8u* pGhash, const Ipp8u* pPrecomputeData, const void* pParam)) { __ALIGN16 Ipp8u t5[BLOCK_SIZE]; __ALIGN16 Ipp8u t4[BLOCK_SIZE]; __ALIGN16 Ipp8u t3[BLOCK_SIZE]; __ALIGN16 Ipp8u t2[BLOCK_SIZE]; int nw; IPP_UNREFERENCED_PARAMETER(pParam); #if 0 XorBlock16(t5, t5, t5); XorBlock16(t4, t4, t4); XorBlock16(t3, t3, t3); XorBlock16(t2, t2, t2); #endif PadBlock(0, t5, sizeof(t5)); PadBlock(0, t4, sizeof(t4)); PadBlock(0, t3, sizeof(t3)); PadBlock(0, t2, sizeof(t2)); for(nw=0; nw<4; nw++) { Ipp32u hashdw = ((Ipp32u*)pGhash)[nw]; Ipp32u a = hashdw & 0xf0f0f0f0; Ipp32u a0 = EBYTE(a,0); Ipp32u a1 = EBYTE(a,1); Ipp32u a2 = EBYTE(a,2); Ipp32u a3 = EBYTE(a,3); int idx; for(idx=0; idx<256; idx+=16) { BNU_CHUNK_T mask0 = cpIsEqu_ct(a0, (BNU_CHUNK_T)idx); BNU_CHUNK_T mask1 = cpIsEqu_ct(a1, (BNU_CHUNK_T)idx); BNU_CHUNK_T mask2 = cpIsEqu_ct(a2, (BNU_CHUNK_T)idx); BNU_CHUNK_T mask3 = cpIsEqu_ct(a3, (BNU_CHUNK_T)idx); MaskedXorBlock16(t5, pPrecomputeData+1024 +256*nw +idx, t5, mask1); MaskedXorBlock16(t4, pPrecomputeData+1024 +256*nw +idx, t4, mask0); MaskedXorBlock16(t3, pPrecomputeData+1024 +256*nw +idx, t3, mask3); MaskedXorBlock16(t2, pPrecomputeData+1024 +256*nw +idx, t2, mask2); } a = (hashdw << 4) & 0xf0f0f0f0; a0 = EBYTE(a, 0); a1 = EBYTE(a, 1); a2 = EBYTE(a, 2); a3 = EBYTE(a, 3); for (idx = 0; idx < 256; idx += 16) { BNU_CHUNK_T mask0 = cpIsEqu_ct(a0, (BNU_CHUNK_T)idx); BNU_CHUNK_T mask1 = cpIsEqu_ct(a1, (BNU_CHUNK_T)idx); BNU_CHUNK_T mask2 = cpIsEqu_ct(a2, (BNU_CHUNK_T)idx); BNU_CHUNK_T mask3 = cpIsEqu_ct(a3, (BNU_CHUNK_T)idx); MaskedXorBlock16(t5, pPrecomputeData +256*nw +idx, t5, mask1); MaskedXorBlock16(t4, pPrecomputeData +256*nw +idx, t4, mask0); MaskedXorBlock16(t3, pPrecomputeData +256*nw +idx, t3, mask3); MaskedXorBlock16(t2, pPrecomputeData +256*nw +idx, t2, mask2); } } XorBlock(t2 + 1, t3, t2 + 1, BLOCK_SIZE - 1); XorBlock(t5 + 1, t2, t5 + 1, BLOCK_SIZE - 1); XorBlock(t4 + 1, t5, t4 + 1, BLOCK_SIZE - 1); nw = t3[BLOCK_SIZE - 1]; { //a = (Ipp32u)AesGcmConst_table[nw]; Ipp32u a = (Ipp32u)getAesGcmConst_table_ct(nw); a <<= 8; nw = t2[BLOCK_SIZE - 1]; //a ^= (Ipp32u)AesGcmConst_table[nw]; a ^= (Ipp32u)getAesGcmConst_table_ct(nw); a <<= 8; nw = t5[BLOCK_SIZE - 1]; //a ^= (Ipp32u)AesGcmConst_table[nw]; a ^= (Ipp32u)getAesGcmConst_table_ct(nw); XorBlock(t4, &a, t4, sizeof(Ipp32u)); CopyBlock16(t4, pGhash); } } #endif #if ((_IPP>=_IPP_V8) || (_IPP32E>=_IPP32E_N8)) __IPPCP_INLINE Ipp16u getAesGcmConst_table_ct(int idx) { /* init current indexes */ __ALIGN16 Ipp16u idx_start[] = { 0,1,2,3,4,5,6,7 }; __m128i idx_curr = _mm_load_si128((__m128i*)idx_start); /* indexes step */ __m128i idx_step = _mm_set1_epi16(sizeof(__m128i) / sizeof(AesGcmConst_table[0])); /* broadcast idx */ __m128i idx_bcst = _mm_set1_epi16((Ipp16s)idx); /* init accumulator */ __m128i acc = _mm_setzero_si128(); int i; for (i = 0; i < (int)sizeof(AesGcmConst_table); i += sizeof(__m128i)) { /* read 16 entries of AesGcmConst_table[] */ __m128i tbl = _mm_load_si128((__m128i*)((Ipp8u*)AesGcmConst_table + i)); /* set mask if idx==idx_curr[] */ __m128i mask = _mm_cmpeq_epi16(idx_bcst, idx_curr); mask = _mm_and_si128(mask, tbl); /* accumulates masked */ acc = _mm_or_si128(acc, mask); /* ad advance idx_curr[] indexes */ idx_curr = _mm_add_epi16(idx_curr, idx_step); } /* shift accumulator to get AesGcmConst_table[idx] in low word */ acc = _mm_or_si128(acc, _mm_srli_si128(acc, sizeof(__m128i) / 2)); /* pack result into dword */ acc = _mm_or_si128(acc, _mm_srli_si128(acc, sizeof(__m128i) / 4)); acc = _mm_or_si128(acc, _mm_srli_si128(acc, sizeof(__m128i) / 8)); i = _mm_cvtsi128_si32(acc); return (Ipp16u)i; } IPP_OWN_DEFN (void, AesGcmMulGcm_table2K_ct, (Ipp8u* pHash, const Ipp8u* pPrecomputedData, const void* pParam)) { __m128i t5 = _mm_setzero_si128(); __m128i t4 = _mm_setzero_si128(); __m128i t3 = _mm_setzero_si128(); __m128i t2 = _mm_setzero_si128(); IPP_UNREFERENCED_PARAMETER(pParam); { int nw; for (nw = 0; nw < 4; nw++) { Ipp32u hashdw = ((Ipp32u*)pHash)[nw]; Ipp32u a = hashdw & 0xf0f0f0f0; Ipp32u a0 = EBYTE(a, 0); Ipp32u a1 = EBYTE(a, 1); Ipp32u a2 = EBYTE(a, 2); Ipp32u a3 = EBYTE(a, 3); int idx; for (idx = 0; idx < 256; idx += 16) { __m128i mask0 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a0, (BNU_CHUNK_T)idx)); __m128i mask1 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a1, (BNU_CHUNK_T)idx)); __m128i mask2 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a2, (BNU_CHUNK_T)idx)); __m128i mask3 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a3, (BNU_CHUNK_T)idx)); t5 = _mm_xor_si128(t5, _mm_and_si128(mask1, _mm_load_si128((__m128i*)(pPrecomputedData + 1024 + 256 * nw + idx)))); t4 = _mm_xor_si128(t4, _mm_and_si128(mask0, _mm_load_si128((__m128i*)(pPrecomputedData + 1024 + 256 * nw + idx)))); t3 = _mm_xor_si128(t3, _mm_and_si128(mask3, _mm_load_si128((__m128i*)(pPrecomputedData + 1024 + 256 * nw + idx)))); t2 = _mm_xor_si128(t2, _mm_and_si128(mask2, _mm_load_si128((__m128i*)(pPrecomputedData + 1024 + 256 * nw + idx)))); } a = (hashdw << 4) & 0xf0f0f0f0; a0 = EBYTE(a, 0); a1 = EBYTE(a, 1); a2 = EBYTE(a, 2); a3 = EBYTE(a, 3); for (idx = 0; idx < 256; idx += 16) { __m128i mask0 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a0, (BNU_CHUNK_T)idx)); __m128i mask1 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a1, (BNU_CHUNK_T)idx)); __m128i mask2 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a2, (BNU_CHUNK_T)idx)); __m128i mask3 = _mm_set1_epi32((Ipp32s)cpIsEqu_ct(a3, (BNU_CHUNK_T)idx)); t5 = _mm_xor_si128(t5, _mm_and_si128(mask1, _mm_load_si128((__m128i*)(pPrecomputedData + 256 * nw + idx)))); t4 = _mm_xor_si128(t4, _mm_and_si128(mask0, _mm_load_si128((__m128i*)(pPrecomputedData + 256 * nw + idx)))); t3 = _mm_xor_si128(t3, _mm_and_si128(mask3, _mm_load_si128((__m128i*)(pPrecomputedData + 256 * nw + idx)))); t2 = _mm_xor_si128(t2, _mm_and_si128(mask2, _mm_load_si128((__m128i*)(pPrecomputedData + 256 * nw + idx)))); } } { Ipp32u a; t2 = _mm_xor_si128(t2, _mm_slli_si128(t3, 1)); t5 = _mm_xor_si128(t5, _mm_slli_si128(t2, 1)); t4 = _mm_xor_si128(t4, _mm_slli_si128(t5, 1)); nw = _mm_cvtsi128_si32(_mm_srli_si128(t3, 15)); a = (Ipp32u)getAesGcmConst_table_ct(nw); a <<= 8; nw = _mm_cvtsi128_si32(_mm_srli_si128(t2, 15)); a ^= (Ipp32u)getAesGcmConst_table_ct(nw); a <<= 8; nw = _mm_cvtsi128_si32(_mm_srli_si128(t5, 15)); a ^= (Ipp32u)getAesGcmConst_table_ct(nw); t2 = _mm_cvtsi32_si128((Ipp32s)a); t4 = _mm_xor_si128(t4, t2); _mm_storeu_si128((__m128i*)pHash, t4); } } } #endif #endif cryptography-primitives-1.0.0/sources/ippcp/pcpaesgcmtbl2k_precom.c000066400000000000000000000046621470420105600256530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) // // "fast" stuff // // Contents: // AesGcmPrecompute_table2K() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcptool.h" #if(_IPP32E<_IPP32E_K0) /* // AES-GCM precomputations. */ static void RightShiftBlock16(Ipp8u* pBlock) { Ipp8u v0 = 0; int i; for(i=0; i<16; i++) { Ipp8u v1 = pBlock[i]; Ipp8u tmp = (Ipp8u)( (v1>>1) | (v0<<7) ); pBlock[i] = tmp; v0 = v1; } } IPP_OWN_DEFN (void, AesGcmPrecompute_table2K, (Ipp8u* pPrecomputeData, const Ipp8u* pHKey)) { Ipp8u t[BLOCK_SIZE]; int n; CopyBlock16(pHKey, t); for(n=0; n<128-24; n++) { /* get msb */ int hBit = t[15]&1; int k = n%32; if(k<4) { CopyBlock16(t, pPrecomputeData +1024 +(n/32)*256 +(Ipp32u)(1<<(7-k))); } else if(k<8) { CopyBlock16(t, pPrecomputeData +(n/32)*256 +(Ipp32u)(1<<(11-k))); } /* shift */ RightShiftBlock16(t); /* xor if msb=1 */ if(hBit) t[0] ^= 0xe1; } for(n=0; n<4; n++) { int m, k; XorBlock16(pPrecomputeData +n*256, pPrecomputeData +n*256, pPrecomputeData +n*256); XorBlock16(pPrecomputeData +1024 +n*256, pPrecomputeData +1024 +n*256, pPrecomputeData +1024 +n*256); for(m=2; m<=8; m*=2) for(k=1; k=_IPP_G9) || \ // (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ // (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) #if 0 IPP_OWN_DEFN (void, AesGcmAuth_table2K, (Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pHKey, const void* pParam)) { IPP_UNREFERENCED_PARAMETER(pParam); while(len>=BLOCK_SIZE) { /* add src */ XorBlock16(pSrc, pHash, pHash); /* hash it */ AesGcmMulGcm_table2K(pHash, pHKey, AesGcmConst_table); pSrc += BLOCK_SIZE; len -= BLOCK_SIZE; } } #endif #if(_IPP32E<_IPP32E_K0) IPP_OWN_DEFN (void, AesGcmAuth_table2K_ct, (Ipp8u* pHash, const Ipp8u* pSrc, int len, const Ipp8u* pHKey, const void* pParam)) { IPP_UNREFERENCED_PARAMETER(pParam); while (len >= BLOCK_SIZE) { /* add src */ XorBlock16(pSrc, pHash, pHash); /* hash it */ AesGcmMulGcm_table2K_ct(pHash, pHKey, AesGcmConst_table); pSrc += BLOCK_SIZE; len -= BLOCK_SIZE; } } #endif //#endif cryptography-primitives-1.0.0/sources/ippcp/pcpaesgcmtbl2kca_decpx.c000066400000000000000000000046371470420105600257770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) // // "fast" stuff // // Contents: // wrpAesGcmDec_table2K() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E<_IPP32E_K0) /* // authenticates and decrypts n*BLOCK_SIZE bytes */ IPP_OWN_DEFN (void, wrpAesGcmDec_table2K, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pState)) { //AesGcmAuth_table2K(AESGCM_GHASH(pState), pSrc, len, AESGCM_HKEY(pState), AesGcmConst_table); AesGcmAuth_table2K_ct(AESGCM_GHASH(pState), pSrc, len, AESGCM_HKEY(pState), AesGcmConst_table); { Ipp8u* pCounter = AESGCM_COUNTER(pState); Ipp8u* pECounter = AESGCM_ECOUNTER(pState); IppsRijndael128Spec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); while(len>=BLOCK_SIZE) { /* encrypt whole AES block */ XorBlock16(pSrc, pECounter, pDst); pSrc += BLOCK_SIZE; pDst += BLOCK_SIZE; len -= BLOCK_SIZE; /* increment counter block */ IncrementCounter32(pCounter); /* and encrypt counter */ //encoder((Ipp32u*)pCounter, (Ipp32u*)pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pCounter, pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(pCounter, pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } } } #endif cryptography-primitives-1.0.0/sources/ippcp/pcpaesgcmtbl2kca_encpx.c000066400000000000000000000046661470420105600260130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt/Decrypt byte data stream according to Rijndael128 (GCM mode) // // "fast" stuff // // Contents: // wrpAesGcmEnc_table2K() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesauthgcm.h" #include "pcptool.h" #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) # include "pcprijtables.h" #endif #if(_IPP32E<_IPP32E_K0) /* // encrypts and authenticates n*BLOCK_SIZE bytes */ IPP_OWN_DEFN (void, wrpAesGcmEnc_table2K, (Ipp8u* pDst, const Ipp8u* pSrc, int len, IppsAES_GCMState* pState)) { Ipp8u* pHashedData = pDst; int hashedDataLen = len; Ipp8u* pCounter = AESGCM_COUNTER(pState); Ipp8u* pECounter = AESGCM_ECOUNTER(pState); IppsRijndael128Spec* pAES = AESGCM_CIPHER(pState); RijnCipher encoder = RIJ_ENCODER(pAES); while(len>=BLOCK_SIZE) { /* encrypt whole AES block */ XorBlock16(pSrc, pECounter, pDst); pSrc += BLOCK_SIZE; pDst += BLOCK_SIZE; len -= BLOCK_SIZE; /* increment counter block */ IncrementCounter32(pCounter); /* and encrypt counter */ //encoder((Ipp32u*)pCounter, (Ipp32u*)pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), (const Ipp32u (*)[256])RIJ_ENC_SBOX(pAES)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) encoder(pCounter, pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), RijEncSbox/*NULL*/); #else encoder(pCounter, pECounter, RIJ_NR(pAES), RIJ_EKEYS(pAES), NULL); #endif } //AesGcmAuth_table2K(AESGCM_GHASH(pState), pHashedData, hashedDataLen, AESGCM_HKEY(pState), AesGcmConst_table); AesGcmAuth_table2K_ct(AESGCM_GHASH(pState), pHashedData, hashedDataLen, AESGCM_HKEY(pState), AesGcmConst_table); } #endif cryptography-primitives-1.0.0/sources/ippcp/pcpaesgetsize.c000066400000000000000000000026541470420105600242520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Initialization of AES // // Contents: // ippsAESGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcprij128safe.h" #include "pcptool.h" /*F* // Name: ippsAESGetSize // // Purpose: Returns size of AES context (in bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to AES size of context(in bytes) // *F*/ IPPFUN(IppStatus, ippsAESGetSize,(int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = cpSizeofCtx_AES(); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpaesm.h000066400000000000000000000044271470420105600230410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal AES Function Prototypes // // */ #if !defined(_PCP_AES_H) #define _PCP_AES_H #include "pcprij.h" /* Intel(R) AES New Instructions (Intel(R) AES-NI) flag */ #define AES_NI_ENABLED (ippCPUID_AES) /* alignment of AES context */ #define AES_ALIGNMENT (RIJ_ALIGNMENT) /* valid AES context ID */ #define VALID_AES_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxRijndael) /* number of rounds (use [NK] for access) */ static int rij128nRounds[3] = {NR128_128, NR128_192, NR128_256}; /* // number of keys (estimation only!) (use [NK] for access) // // accurate number of keys necassary for encrypt/decrypt are: // nKeys = NB * (NR+1) // where NB - data block size (32-bit words) // NR - number of rounds (depend on NB and keyLen) // // but the estimation // estnKeys = (NK*n) >= nKeys // or // estnKeys = ( (NB*(NR+1) + (NK-1)) / NK) * NK // where NK - key length (words) // NB - data block size (word) // NR - number of rounds (depend on NB and keyLen) // nKeys - accurate number of keys // is more convenient when calculates key extension */ static int rij128nKeys[3] = {44, 52, 60 }; /* // helper for nRounds[] and estnKeys[] access // note: x is length in 32-bits words */ __IPPCP_INLINE int rij_index(int x) { return (x-NB(128))>>1; } /* size of AES context */ __IPPCP_INLINE int cpSizeofCtx_AES(void) { return sizeof(IppsAESSpec); } #endif /* _PCP_AES_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpaesminitca.c000066400000000000000000000114241470420105600242170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Initialization of AES // // Contents: // ippsAESInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcprij128safe.h" #include "pcptool.h" #include "pcpaes_internal_func.h" /*F* // Name: ippsAESInit // // Purpose: Init AES context for future usage // and setup secret key. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsMemAllocErr size of buffer is not match for operation // ippStsLengthErr keyLen != 16 // keyLen != 24 // keyLen != 32 // ippStsNoErr no errors // // Parameters: // pKey secret key // keyLen length of the secret key (in bytes) // pCtx pointer to buffer initialized as AES context // ctxSize available size (in bytes) of buffer above // // Note: // if pKey==NULL, then AES initialized by zero value key // *F*/ IPPFUN(IppStatus, ippsAESInit,(const Ipp8u* pKey, int keyLen, IppsAESSpec* pCtx, int ctxSize)) { /* test context pointer */ IPP_BAD_PTR1_RET(pCtx); /* make sure in legal keyLen */ IPP_BADARG_RET(keyLen!=16 && keyLen!=24 && keyLen!=32, ippStsLengthErr); IPP_BADARG_RET(((Ipp8u*)pCtx+sizeof(IppsAESSpec)) > ((Ipp8u*)pCtx+ctxSize), ippStsMemAllocErr); { int keyWords = NK(keyLen*BITSIZE(Ipp8u)); int nExpKeys = rij128nKeys [ rij_index(keyWords) ]; int nRounds = rij128nRounds[ rij_index(keyWords) ]; Ipp8u zeroKey[32] = {0}; const Ipp8u* pActualKey = pKey? pKey : zeroKey; /* clear context */ PadBlock(0, pCtx, sizeof(IppsAESSpec)); /* init spec */ /* light trick to prevent context copy: add low 32-bit part of its current address to the context Id and * check if is changed later in processing functions */ RIJ_SET_ID(pCtx); RIJ_NB(pCtx) = NB(128); RIJ_NK(pCtx) = keyWords; RIJ_NR(pCtx) = nRounds; RIJ_SAFE_INIT(pCtx) = 1; #if (_AES_PROB_NOISE == _FEATURE_ON_) /* Reset AES noise parameters */ cpAESNoiseParams *params = (cpAESNoiseParams *)&RIJ_NOISE_PARAMS(pCtx); AES_NOISE_RAND(params) = 0; AES_NOISE_LEVEL(params) = 0; #endif cpAes_setup_ptrs_and_methods(pCtx); #if (_AES_NI_ENABLING_==_FEATURE_ON_) cpExpandAesKey_NI(pActualKey, pCtx); /* AES_NI based key expansion */ #else #if (_AES_NI_ENABLING_==_FEATURE_TICKTOCK_) if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) { cpExpandAesKey_NI(pActualKey, pCtx); /* AES_NI based key expansion */ } else #endif { ExpandRijndaelKey(pActualKey, keyWords, NB(128), nRounds, nExpKeys, RIJ_EKEYS(pCtx), RIJ_DKEYS(pCtx)); #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPOSITE_GF_) { int nr; Ipp8u* pEnc_key = (Ipp8u*)(RIJ_EKEYS(pCtx)); Ipp8u* pDec_key = (Ipp8u*)(RIJ_DKEYS(pCtx)); /* update key material: convert into GF((2^4)2) */ for(nr=0; nr<(1+nRounds); nr++) { TransformNative2Composite(pEnc_key+16*nr, pEnc_key+16*nr); TransformNative2Composite(pDec_key+16*nr, pDec_key+16*nr); } } #else { int nr; Ipp8u* pEnc_key = (Ipp8u*)(RIJ_EKEYS(pCtx)); /* update key material: transpose inplace */ for(nr=0; nr<(1+nRounds); nr++, pEnc_key+=16) { SWAP(pEnc_key[ 1], pEnc_key[ 4]); SWAP(pEnc_key[ 2], pEnc_key[ 8]); SWAP(pEnc_key[ 3], pEnc_key[12]); SWAP(pEnc_key[ 6], pEnc_key[ 9]); SWAP(pEnc_key[ 7], pEnc_key[13]); SWAP(pEnc_key[11], pEnc_key[14]); } } #endif } #endif return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpaesmxts.h000066400000000000000000000044601470420105600235750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // AES-XTS Internal Definitions // // */ #if !defined(_PCP_AES_XTS_H) #define _PCP_AES_XTS_H #include "owncp.h" #include "pcpaesm.h" #define _NEW_XTS_API_3 #if defined (_NEW_XTS_API_3) /* // AES-XTS State */ #if !defined(AES_BLK_SIZE) #define AES_BLK_SIZE (IPP_AES_BLOCK_BITSIZE/BITSIZE(Ipp8u)) #endif #define AES_BLKS_PER_BUFFER (32) struct _cpAES_XTS { Ipp32u idCtx; int duBitsize; /* size of data unit (in bits) */ IppsAESSpec datumAES; /* datum AES context */ IppsAESSpec tweakAES; /* tweak AES context */ }; #define AES_XTS_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxAESXTS ^ (Ipp32u)IPP_UINT_PTR(ctx)) /* valid AES_XTS context ID */ #define VALID_AES_XTS_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxAESXTS) /* size of AES-XTS context */ __IPPCP_INLINE int cpSizeof_AES_XTS_Ctx(void) { return sizeof(IppsAES_XTSSpec); } static int IsLegalGeometry(int startCipherBlkNo, int bitLen, int duBitsize) { int duBlocks = (duBitsize+IPP_AES_BLOCK_BITSIZE-1)/IPP_AES_BLOCK_BITSIZE; int legalBlk = (0<=startCipherBlkNo && startCipherBlkNo> 63) & GF_POLY; Ipp64u addH = ((Ipp64s)x64[0] >> 63) & 1; x64[0] = (x64[0]+x64[0]) ^ xorL; x64[1] = (x64[1]+x64[1]) + addH; } /* the following are especially for multi-block processing */ static void cpXTSwhitening(Ipp8u* buffer, int nblk, Ipp8u* ptwk) { Ipp64u* pbuf64 = (Ipp64u*)buffer; Ipp64u* ptwk64 = (Ipp64u*)ptwk; pbuf64[0] = ptwk64[0]; pbuf64[1] = ptwk64[1]; for(nblk--, pbuf64+=2; nblk>0; nblk--, pbuf64+=2) { gf_mul_by_primitive(ptwk64); pbuf64[0] = ptwk64[0]; pbuf64[1] = ptwk64[1]; } gf_mul_by_primitive(ptwk64); } static void cpXTSxor16(Ipp8u* pDst, const Ipp8u* pSrc1, const Ipp8u* pSrc2, int nblk) { Ipp64u* pdst64 = (Ipp64u*)pDst; const Ipp64u* ps1_64 = (const Ipp64u*)pSrc1; const Ipp64u* ps2_64 = (const Ipp64u*)pSrc2; for(; nblk>0; nblk--, pdst64+=2, ps1_64+=2, ps2_64+=2) { pdst64[0] = ps1_64[0] ^ ps2_64[0]; pdst64[1] = ps1_64[1] ^ ps2_64[1]; } } #endif /* _PCP_AES_XTS_STUFF_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpaesnoise.h000066400000000000000000000065151470420105600237220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2022 Intel Corporation * * 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. *************************************************************************/ #if !defined(_PCP_AES_NOISE_H) #define _PCP_AES_NOISE_H /* * The parameters below are empirical and chosen in advance to guarantee * the high level of security protection against Mistletoe3 attack. */ #define MISTLETOE3_MAX_CHUNK_SIZE (16000) /* maximum chunks size allowed to be processed without noise injection (in bytes) \ 16000 bytes = 16*1000 bytes = 1000 AES blocks */ #define MISTLETOE3_TARGET_SIZE (800000000) /* expected sampling interval of the attacker. During the attack \ the adversary measures how long it takes to encrypt MISTLETOE3_TARGET_SIZE of bytes. \ MISTLETOE3_TARGET_SIZE is much greater than MISTLETOE3_MAX_CHUNK_SIZE \ 800000000 bytes = 16*50000000 bytes = 50000000 AES blocks */ #define MISTLETOE3_BASE_NOISE_LEVEL (28) /* noiseLevel adjusts the random number of what bitsize will be generated, this number will be \ used as a parameter for _ippcpDelay function. Level of noise needed depends on many factors, such \ as processor, code implementation, power limit setting by the attacker, etc. \ For base noise level was selected a relatively safe value of 28, for user this parameter was \ introduced as abstract with tunable range [0,4] */ #define MISTLETOE3_NOISE_RATE ((double)MISTLETOE3_MAX_CHUNK_SIZE / \ (double)MISTLETOE3_TARGET_SIZE) /* Structure containing noise parameters required for Mistletoe3 mitigation */ typedef struct _cpAESNoiseParams { Ipp32u rnd; /* Random number value from previous noise injection */ Ipp32u noiseLevel; /* Number of bits that should be taken from generated \ 32-bit random value. noiseLevel == 0 -> mitigation is off */ } cpAESNoiseParams; #define AES_NOISE_RAND(ctx) ((ctx)->rnd) #define AES_NOISE_LEVEL(ctx) ((ctx)->noiseLevel) /* size of _cpAESNoiseParams structure */ __IPPCP_INLINE int cpSizeofNoise_Params(void) { return sizeof(cpAESNoiseParams); } #define _ippcpDelay OWNAPI(_ippcpDelay) IPP_OWN_DECL(void, _ippcpDelay, (Ipp32u value)) #define cpAESRandomNoise OWNAPI(cpAESRandomNoise) IPP_OWN_DECL(IppStatus, cpAESRandomNoise, (IppBitSupplier rndFunc, Ipp32u nBits, Ipp64f noiseRate, Ipp32u *pRndValue)) #endif /* _PCP_AES_NOISE_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpaespack.c000066400000000000000000000052121470420105600235070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Initialization of AES // // Contents: // ippsAESPack() // */ #include "owndefs.h" #include "owncp.h" #include "pcpaesm.h" #include "pcprij128safe.h" #include "pcptool.h" /*F* // Name: ippsAESPack // // Purpose: Serialize AES context into the buffer. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pBuffer == NULL // ippStsContextMatchErr RIJ_ID(pCtx) != idCtxRijndael // ippStsLengthErr available size of buffer is not enough for operation // ippStsNoErr no errors // // Parameters: // pCtx pointer RIJ spec // pBuffer pointer to the buffer // bufsize available size of buffer above // *F*/ IPPFUN(IppStatus, ippsAESPack,(const IppsAESSpec* pCtx, Ipp8u* pBuffer, int bufsize)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); /* test the context */ IPP_BADARG_RET(!VALID_AES_ID(pCtx), ippStsContextMatchErr); /* test available size of destination buffer */ IPP_BADARG_RET(bufsize=_IPP_V8) || (_IPP32E>=_IPP32E_M7)) #define rc4word Ipp32u #else #define rc4word Ipp8u #endif /* // ARCFOUR context */ struct _cpARCfour { Ipp32u idCtx; /* RC4 identifier */ Ipp32u cntX; /* algorithm's counter x */ Ipp32u cntY; /* algorithm's counter y */ rc4word Sbox[256]; /* current state block.*/ Ipp8u Sbox0[256]; /* initial state block */ }; /* alignment */ #define RC4_ALIGNMENT ((int)(sizeof(Ipp32u))) /* // Useful macros */ #define RC4_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxARCFOUR ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define RC4_RESET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxARCFOUR) #define RC4_CNTX(ctx) ((ctx)->cntX) #define RC4_CNTY(ctx) ((ctx)->cntY) #define RC4_SBOX(ctx) ((ctx)->Sbox) #define RC4_SBOX0(ctx) ((ctx)->Sbox0) #define RC4_VALID_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxARCFOUR) /* // internal functions */ #define ARCFourProcessData OWNAPI(ARCFourProcessData) IPP_OWN_DECL (void, ARCFourProcessData, (const Ipp8u *pSrc, Ipp8u *pDst, int length, IppsARCFourState *pCtx)) #endif /* _ARCFOUR_H */ cryptography-primitives-1.0.0/sources/ippcp/pcparcfour_processdata.c000066400000000000000000000033511470420105600261330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /* // data processing function. */ #if !((_IPP>=_IPP_M5) || (_IPP32E>=_IPP32E_M7)) IPP_OWN_DEFN (void, ARCFourProcessData, (const Ipp8u *pSrc, Ipp8u *pDst, int length, IppsARCFourState *pCtx)) { if(length) { rc4word tx, ty; Ipp32u x = RC4_CNTX(pCtx); Ipp32u y = RC4_CNTY(pCtx); rc4word* pSbox = RC4_SBOX(pCtx); x = (x+1) &0xFF; tx = pSbox[x]; while(length) { y = (y+tx) & 0xFF; ty = pSbox[y]; pSbox[x] = ty; x = (x+1) & 0xFF; ty = (ty+tx) & 0xFF; pSbox[y] = tx; tx = pSbox[x]; ty = pSbox[ty]; *pDst = (Ipp8u)( *pSrc ^ ty ); pDst++; pSrc++; length--; } RC4_CNTX(pCtx) = (x-1) & 0xFF; RC4_CNTY(pCtx) = y; } } #endif /* #if !((_IPP>=_IPP_M5) || (_IPP32E>=_IPP32E_M7)) */ cryptography-primitives-1.0.0/sources/ippcp/pcparcfourca.c000066400000000000000000000040731470420105600240510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourInit // // Purpose: Init ARCFOUR spec for future usage. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsLengthErr 1 > keyLen // keyLen > IPP_ARCFOUR_KEYMAX_SIZE // ippStsNoErr no errors // // Parameters: // key security key // keyLen length of key (bytes) // pCtx pointer to the ARCFOUR context // *F*/ IPPFUN(IppStatus, ippsARCFourInit, (const Ipp8u *pKey, int keyLen, IppsARCFourState *pCtx)) { /* test context pointer */ IPP_BAD_PTR1_RET(pCtx); /* test key */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(((1>keyLen)||(IPP_ARCFOUR_KEYMAX_SIZE< keyLen)), ippStsLengthErr); { int i; Ipp8u kblk[256], j, tmp; /* init RC4 context */ RC4_SET_ID(pCtx); for(i=0; i<256; i++) { pCtx->Sbox0[i] = (Ipp8u)i; kblk[i] = pKey[i%keyLen]; } j=0; for(i=0; i<256; i++) { j += pCtx->Sbox0[i] + kblk[i]; tmp = pCtx->Sbox0[j]; pCtx->Sbox0[j] = pCtx->Sbox0[i]; pCtx->Sbox0[i] = tmp; } return ippsARCFourReset(pCtx); } } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourcheckkey.c000066400000000000000000000036701470420105600252560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourCheckKey // // Purpose: Checks key for weakness. // // Returns: Reason: // ippStsNullPtrErr pKey== NULL // ippStsNullPtrErr pIsWeak== NULL // ippStsLengthErr 1 > keyLen // keyLen > IPP_ARCFOUR_KEYMAX_SIZE // ippStsNoErr no errors // // Parameters: // key security key // keyLen length of key (bytes) // pIsWeak pointer to the result // // Note: // See ANDREW ROOS "A CLASS OF WEAK KEYS IN THE RC4 STREAM CIPHER" // (http://marcel.wanda.ch/Archive/WeakKeys) *F*/ IPPFUN(IppStatus, ippsARCFourCheckKey, (const Ipp8u *pKey, int keyLen, IppBool* pIsWeak)) { /* test key */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(((1>keyLen)||(IPP_ARCFOUR_KEYMAX_SIZE< keyLen)), ippStsLengthErr); /* test result*/ IPP_BAD_PTR1_RET(pIsWeak); if(1==keyLen) *pIsWeak = (pKey[0]==128)? ippTrue : ippFalse; else *pIsWeak = (pKey[0] + pKey[1])%256 == 0 ? ippTrue : ippFalse; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourdecrypt.c000066400000000000000000000040331470420105600251340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourDecrypt // // Purpose: Decrypt data stream. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr pCtx->idCtx != idCtxARCFOUR // ippStsLengthErr length<1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data block stream // pDst pointer to the destination byte data block stream // length stream length (bytes) // pCtx pointer to the ARCFOUR context // // Note: // Convenience function only *F*/ IPPFUN(IppStatus, ippsARCFourDecrypt, (const Ipp8u *pSrc, Ipp8u *pDst, int length, IppsARCFourState *pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RC4_VALID_ID(pCtx), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((length<1), ippStsLengthErr); /* process data */ ARCFourProcessData(pSrc, pDst, length, pCtx); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourencrypt.c000066400000000000000000000040351470420105600251500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourEncrypt // // Purpose: Encrypt data stream. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr pCtx->idCtx != idCtxARCFOUR // ippStsLengthErr length<1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data block stream // pDst pointer to the destination byte data block stream // length stream length (bytes) // pCtx pointer to the ARCFOUR context // // Note: // Convenience function only *F*/ IPPFUN(IppStatus, ippsARCFourEncrypt, (const Ipp8u *pSrc, Ipp8u *pDst, int length, IppsARCFourState *pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RC4_VALID_ID(pCtx), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((length<1), ippStsLengthErr); /* process data */ ARCFourProcessData(pSrc, pDst, length, pCtx); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourgetsize.c000066400000000000000000000025611470420105600251400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ /*F* // Name: ippsARCFourGetSize // // Purpose: Returns size of ARCFOUR context (bytes). // // Returns: Reason: // ippStsNullPtrErr pSzie == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to the size of ARCFOUR context // *F*/ IPPFUN(IppStatus, ippsARCFourGetSize, (int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsARCFourState); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourpack.c000066400000000000000000000032261470420105600244030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourPack // // Purpose: Copy initialized context to the buffer. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer ARCFour spec // pSize pointer to the packed spec size // *F*/ IPPFUN(IppStatus, ippsARCFourPack,(const IppsARCFourState* pCtx, Ipp8u* pBuffer)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); /* test the context */ IPP_BADARG_RET(!RC4_VALID_ID(pCtx), ippStsContextMatchErr); CopyBlock(pCtx, pBuffer, sizeof(IppsARCFourState)); IppsARCFourState* pCopy = (IppsARCFourState*)pBuffer; RC4_RESET_ID(pCopy); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourreset.c000066400000000000000000000033151470420105600246060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourReset // // Purpose: Resrt ARCFOUR context: // set current state block to the initial one // and zeroes counters // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsContextMatchErr pCtx->idCtx != idCtxARCFOUR // ippStsNoErr no errors // // Parameters: // pCtx pointer to the ARCFOUR context // *F*/ IPPFUN(IppStatus, ippsARCFourReset, (IppsARCFourState* pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RC4_VALID_ID(pCtx), ippStsContextMatchErr); { /* reset Sbox */ int n; for(n=0; n<256; n++) RC4_SBOX(pCtx)[n] = RC4_SBOX0(pCtx)[n]; /* reset counters */ RC4_CNTX(pCtx) = 0; RC4_CNTY(pCtx) = 0; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcparcfourunpack.c000066400000000000000000000030211470420105600247370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RC4 implementation // */ #include "owndefs.h" #include "owncp.h" #include "pcparcfour.h" #include "pcptool.h" /*F* // Name: ippsARCFourUnpack // // Purpose: Unpack buffer content into the initialized context. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer ARCFour spec // pSize pointer to the packed spec size // *F*/ IPPFUN(IppStatus, ippsARCFourUnpack,(const Ipp8u* pBuffer, IppsARCFourState* pCtx)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); CopyBlock(pBuffer, pCtx, sizeof(IppsARCFourState)); RC4_SET_ID(pCtx); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpbn.h000066400000000000000000000142611470420105600225100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // // */ #if !defined(_CP_BN_H) #define _CP_BN_H #include "pcpbnuimpl.h" #include "pcpbnuarith.h" #include "pcpbnumisc.h" #include "pcpbnu32arith.h" #include "pcpbnu32misc.h" /* // Big Number context */ struct _cpBigNum { Ipp32u idCtx; /* BigNum ctx id */ IppsBigNumSGN sgn; /* sign */ cpSize size; /* BigNum size (BNU_CHUNK_T) */ cpSize room; /* BigNum max size (BNU_CHUNK_T) */ BNU_CHUNK_T* number; /* BigNum value */ BNU_CHUNK_T* buffer; /* temporary buffer */ }; /* BN accessory macros */ #define BN_SET_ID(pBN) ((pBN)->idCtx = (Ipp32u)idCtxBigNum ^ (Ipp32u)IPP_UINT_PTR(pBN)) #define BN_SIGN(pBN) ((pBN)->sgn) #define BN_POSITIVE(pBN) (BN_SIGN(pBN)==ippBigNumPOS) #define BN_NEGATIVE(pBN) (BN_SIGN(pBN)==ippBigNumNEG) #define BN_NUMBER(pBN) ((pBN)->number) #define BN_BUFFER(pBN) ((pBN)->buffer) #define BN_ROOM(pBN) ((pBN)->room) #define BN_SIZE(pBN) ((pBN)->size) #define BN_SIZE32(pBN) ((pBN)->size*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)))) //#define BN_SIZE32(pBN) (BITS2WORD32_SIZE( BITSIZE_BNU(BN_NUMBER((pBN)),BN_SIZE((pBN))))) #define BN_VALID_ID(pBN) ((((pBN)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((pBN))) == (Ipp32u)idCtxBigNum) #define INVERSE_SIGN(s) (((s)==ippBigNumPOS)? ippBigNumNEG : ippBigNumPOS) #define BN_ALIGNMENT ((int)sizeof(void*)) /* pack-unpack context */ #define cpPackBigNumCtx OWNAPI(cpPackBigNumCtx) IPP_OWN_DECL (void, cpPackBigNumCtx, (const IppsBigNumState* pBN, Ipp8u* pBuffer)) #define cpUnpackBigNumCtx OWNAPI(cpUnpackBigNumCtx) IPP_OWN_DECL (void, cpUnpackBigNumCtx, (const Ipp8u* pBuffer, IppsBigNumState* pBN)) /* copy BN */ __IPPCP_INLINE IppsBigNumState* cpBN_copy(IppsBigNumState* pDst, const IppsBigNumState* pSrc) { BN_SIGN(pDst) = BN_SIGN(pSrc); BN_SIZE(pDst) = BN_SIZE(pSrc); ZEXPAND_COPY_BNU(BN_NUMBER(pDst), BN_ROOM(pDst), BN_NUMBER(pSrc), BN_SIZE(pSrc)); return pDst; } /* set BN to zero */ __IPPCP_INLINE IppsBigNumState* cpBN_zero(IppsBigNumState* pBN) { BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = 1; ZEXPAND_BNU(BN_NUMBER(pBN),0, (int)BN_ROOM(pBN)); return pBN; } /* fixup BN */ __IPPCP_INLINE IppsBigNumState* cpBN_fix(IppsBigNumState* pBN) { cpSize len = BN_SIZE(pBN); FIX_BNU(BN_NUMBER(pBN), len); BN_SIZE(pBN) = len; return pBN; } /* set BN to chunk */ __IPPCP_INLINE IppsBigNumState* cpBN_chunk(IppsBigNumState* pBN, BNU_CHUNK_T a) { BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = 1; ZEXPAND_BNU(BN_NUMBER(pBN),0, (int)BN_ROOM(pBN)); BN_NUMBER(pBN)[0] = a; return pBN; } /* set BN to 2^m */ __IPPCP_INLINE IppsBigNumState* cpBN_power2(IppsBigNumState* pBN, int power) { cpSize size = BITS_BNU_CHUNK(power+1); if(BN_ROOM(pBN) >= size) { BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = size; ZEXPAND_BNU(BN_NUMBER(pBN),0, BN_ROOM(pBN)); SET_BIT(BN_NUMBER(pBN), power); return pBN; } else return NULL; } /* bitsize of BN */ __IPPCP_INLINE int cpBN_bitsize(const IppsBigNumState* pA) { int bitsize = BITSIZE_BNU(BN_NUMBER(pA), BN_SIZE(pA)); return bitsize; } /* returns -1/0/+1 depemding on A~B comparison */ __IPPCP_INLINE int cpBN_cmp(const IppsBigNumState* pA, const IppsBigNumState* pB) { IppsBigNumSGN signA = BN_SIGN(pA); IppsBigNumSGN signB = BN_SIGN(pB); if(signA==signB) { int result = cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pB), BN_SIZE(pB)); return (ippBigNumPOS==signA)? result : -result; } return (ippBigNumPOS==signA)? 1 : -1; } /* returns -1/0/+1 depemding on A comparison 00 */ __IPPCP_INLINE int cpBN_tst(const IppsBigNumState* pA) { if(1==BN_SIZE(pA) && 0==BN_NUMBER(pA)[0]) return 0; else return BN_POSITIVE(pA)? 1 : -1; } // some addition functions __IPPCP_INLINE int IsZero_BN(const IppsBigNumState* pA) { return ( BN_SIZE(pA)==1 ) && ( BN_NUMBER(pA)[0]==0 ); } __IPPCP_INLINE int IsOdd_BN(const IppsBigNumState* pA) { return BN_NUMBER(pA)[0] & 1; } __IPPCP_INLINE IppsBigNumState* BN_Word(IppsBigNumState* pBN, BNU_CHUNK_T w) { BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = 1; ZEXPAND_BNU(BN_NUMBER(pBN),0, BN_ROOM(pBN)); BN_NUMBER(pBN)[0] = w; return pBN; } __IPPCP_INLINE IppsBigNumState* BN_Set(const BNU_CHUNK_T* pData, cpSize len, IppsBigNumState* pBN) { BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = len; ZEXPAND_COPY_BNU(BN_NUMBER(pBN), BN_ROOM(pBN), pData, len); return pBN; } __IPPCP_INLINE IppsBigNumState* BN_Make(BNU_CHUNK_T* pData, BNU_CHUNK_T* pBuffer, cpSize len, IppsBigNumState* pBN) { BN_SET_ID(pBN); BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = 1; BN_ROOM(pBN) = len; BN_NUMBER(pBN) = pData; BN_BUFFER(pBN) = pBuffer; return pBN; } /* // fixed single chunk BN */ typedef struct _ippcpBigNumChunk { IppsBigNumState bn; BNU_CHUNK_T value; BNU_CHUNK_T temporary; } IppsBigNumStateChunk; /* reference to BN(1) and BN(2) */ #define cpBN_OneRef OWNAPI(cpBN_OneRef) IPP_OWN_DECL (IppsBigNumState*, cpBN_OneRef, (void)) #define cpBN_TwoRef OWNAPI(cpBN_TwoRef) IPP_OWN_DECL (IppsBigNumState*, cpBN_TwoRef, (void)) #define cpBN_ThreeRef OWNAPI(cpBN_ThreeRef) IPP_OWN_DECL (IppsBigNumState*, cpBN_ThreeRef, (void)) #define BN_ONE_REF() cpBN_OneRef() #define BN_TWO_REF() cpBN_TwoRef() #define BN_THREE_REF() cpBN_ThreeRef() #endif /* _CP_BN_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpbn_pack.c000066400000000000000000000034651470420105600235050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpPackBigNumCtx() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: cpPackBigNumCtx // // Purpose: Serialize bigNum context // // Parameters: // pBN BigNum // pBuffer buffer *F*/ IPP_OWN_DEFN (void, cpPackBigNumCtx, (const IppsBigNumState* pBN, Ipp8u* pBuffer)) { IppsBigNumState* pB = (IppsBigNumState*)(pBuffer); CopyBlock(pBN, pB, sizeof(IppsBigNumState)); cpSize dataAlignment = (cpSize)(IPP_INT_PTR(BN_NUMBER(pBN)) - IPP_INT_PTR(pBN) - (IPP_INT64)sizeof(IppsBigNumState)); BN_NUMBER(pB) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_INT_PTR(BN_NUMBER(pBN))-IPP_INT_PTR(pBN) - dataAlignment); BN_BUFFER(pB) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_INT_PTR(BN_BUFFER(pBN))-IPP_INT_PTR(pBN) - dataAlignment); CopyBlock(BN_NUMBER(pBN), (Ipp8u*)pB+IPP_UINT_PTR(BN_NUMBER(pB)), BN_ROOM(pBN)*(Ipp32s)sizeof(BNU_CHUNK_T)); CopyBlock(BN_BUFFER(pBN), (Ipp8u*)pB+IPP_UINT_PTR(BN_BUFFER(pB)), BN_ROOM(pBN)*(Ipp32s)sizeof(BNU_CHUNK_T)); } cryptography-primitives-1.0.0/sources/ippcp/pcpbn_unpack.c000066400000000000000000000034361470420105600240460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpUnpackBigNumCtx() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: cpUnpackBigNumCtx // // Purpose: Deserialize bigNum context // // Parameters: // pBN BigNum // pBuffer buffer *F*/ IPP_OWN_DEFN (void, cpUnpackBigNumCtx, (const Ipp8u* pBuffer, IppsBigNumState* pBN)) { IppsBigNumState* pB = (IppsBigNumState*)(pBuffer); CopyBlock(pBuffer, pBN, sizeof(IppsBigNumState)); Ipp8u* ptr = (Ipp8u*)pBN; ptr += sizeof(IppsBigNumState); ptr = IPP_ALIGNED_PTR(ptr, BN_ALIGNMENT); BN_NUMBER(pBN) = (BNU_CHUNK_T*)(ptr); ptr += BN_ROOM(pBN)*(Ipp32s)sizeof(BNU_CHUNK_T); BN_BUFFER(pBN) = (BNU_CHUNK_T*)(ptr); cpSize bufferOffset = (cpSize)(IPP_INT_PTR(BN_BUFFER(pBN)) - IPP_INT_PTR(pBN)); CopyBlock((Ipp8u*)pB+sizeof(IppsBigNumState), BN_NUMBER(pBN), BN_ROOM(pBN)*(Ipp32s)sizeof(BNU_CHUNK_T)); CopyBlock((Ipp8u*)pB+bufferOffset, BN_BUFFER(pBN), BN_ROOM(pBN)*(Ipp32s)sizeof(BNU_CHUNK_T)); } cryptography-primitives-1.0.0/sources/ippcp/pcpbn_val1.c000066400000000000000000000025371470420105600234310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpBN_OneRef() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: cpBN_OneRef // // Purpose: BN(1) and reference // // Return: // BigNum = 1 *F*/ /* BN(1) and reference */ IPP_OWN_DEFN (IppsBigNumState*, cpBN_OneRef, (void)) { static IppsBigNumStateChunk cpChunk_BN1 = { { idCtxUnknown, ippBigNumPOS, 1,1, &cpChunk_BN1.value,&cpChunk_BN1.temporary }, 1,0 }; BN_SET_ID(&cpChunk_BN1.bn); return &cpChunk_BN1.bn; } cryptography-primitives-1.0.0/sources/ippcp/pcpbn_val2.c000066400000000000000000000025051470420105600234250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpBN_TwoRef() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: cpBN_TwoRef // // Purpose: BN(2) and reference // // Return: // BigNum = 2 *F*/ IPP_OWN_DEFN (IppsBigNumState*, cpBN_TwoRef, (void)) { static IppsBigNumStateChunk cpChunk_BN2 = { { idCtxUnknown, ippBigNumPOS, 1,1, &cpChunk_BN2.value,&cpChunk_BN2.temporary }, 2,0 }; BN_SET_ID(&cpChunk_BN2.bn); return &cpChunk_BN2.bn; } cryptography-primitives-1.0.0/sources/ippcp/pcpbn_val3.c000066400000000000000000000025131470420105600234250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpBN_ThreeRef() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: cpBN_ThreeRef // // Purpose: BN(3) and reference // // Return: // BigNum = 3 *F*/ IPP_OWN_DEFN (IppsBigNumState*, cpBN_ThreeRef, (void)) { static IppsBigNumStateChunk cpChunk_BN3 = { { idCtxUnknown, ippBigNumPOS, 1,1, &cpChunk_BN3.value,&cpChunk_BN3.temporary }, 3,0 }; BN_SET_ID(&cpChunk_BN3.bn); return &cpChunk_BN3.bn; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithadd.c000066400000000000000000000066571470420105600242160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsAdd_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsAdd_BN // // Purpose: Add BigNums. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pB == NULL // pR == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pB) // !BN_VALID_ID(pR) // ippStsOutOfRangeErr pR can not hold result // ippStsNoErr no errors // // Parameters: // pA source BigNum A // pB source BigNum B // pR resultant BigNum // *F*/ IPPFUN(IppStatus, ippsAdd_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) { IPP_BAD_PTR3_RET(pA, pB, pR); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); { cpSize nsA = BN_SIZE(pA); cpSize nsB = BN_SIZE(pB); cpSize nsR = BN_ROOM(pR); IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr); { BNU_CHUNK_T* pDataR = BN_NUMBER(pR); IppsBigNumSGN sgnA = BN_SIGN(pA); IppsBigNumSGN sgnB = BN_SIGN(pB); BNU_CHUNK_T* pDataA = BN_NUMBER(pA); BNU_CHUNK_T* pDataB = BN_NUMBER(pB); BNU_CHUNK_T carry; if(sgnA==sgnB) { if(nsA < nsB) { SWAP(nsA, nsB); SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); } carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB); if(nsA>nsB) carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); if(carry) { if(nsR>nsA) pDataR[nsA++] = carry; else IPP_ERROR_RET(ippStsOutOfRangeErr); } BN_SIGN(pR) = sgnA; } else { int cmpRes = cpCmp_BNU(pDataA, nsA, pDataB, nsB); if(0==cmpRes) { pDataR[0] = 0; BN_SIZE(pR) = 1; BN_SIGN(pR) = ippBigNumPOS; return ippStsNoErr; } if(0>cmpRes) { SWAP(nsA, nsB); SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); } carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB); if(nsA>nsB) cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA); } FIX_BNU(pDataR, nsA); BN_SIZE(pR) = nsA; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithcmp.c000066400000000000000000000056331470420105600242360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsCmp_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsCmp_BN // // Purpose: Compare two BigNums. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pB == NULL // pResult == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pB) // ippStsNoErr no errors // // Parameters: // pA BigNum ctx // pB BigNum ctx // pResult result of comparison // *F*/ IPPFUN(IppStatus, ippsCmp_BN,(const IppsBigNumState* pA, const IppsBigNumState* pB, Ipp32u *pResult)) { IPP_BAD_PTR3_RET(pA, pB, pResult); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); { BNU_CHUNK_T positiveA = cpIsEqu_ct(ippBigNumPOS, BN_SIGN(pA)); BNU_CHUNK_T positiveB = cpIsEqu_ct(ippBigNumPOS, BN_SIGN(pB)); BNU_CHUNK_T signMask; /* (ippBigNumPOS == BN_SIGN(pA)) && (ippBigNumPOS==BN_SIGN(pB)) => res = cpCmp_BNU() */ BNU_CHUNK_T res = (BNU_CHUNK_T)( cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pB), BN_SIZE(pB)) ); /* (ippBigNumNEG == BN_SIGN(pA)) && (ippBigNumNEG==BN_SIGN(pB)) => invert res value */ signMask = ~positiveA & ~positiveB; res = (res & ~signMask) | ((0-res) & signMask); /* (ippBigNumPOS == BN_SIGN(pA)) && (ippBigNumNEG==BN_SIGN(pB)) => res = 1 */ signMask = positiveA & ~positiveB; res = (res & ~signMask) | ((1) & signMask); /* (ippBigNumNEG == BN_SIGN(pA)) && (ippBigNumPOS==BN_SIGN(pB)) => res = -1 */ signMask = ~positiveA & positiveB; res = (res & ~signMask) | ((BNU_CHUNK_T)(-1) & signMask); // map res into IPP_IS_LT/EQ/GT Ipp32u cmpResult = (Ipp32u)( (cpIsEqu_ct(res, (BNU_CHUNK_T)(-1)) & IPP_IS_LT) | (cpIsEqu_ct(res, (BNU_CHUNK_T)(0)) & IPP_IS_EQ) | (cpIsEqu_ct(res, (BNU_CHUNK_T)(1)) & IPP_IS_GT) ); *pResult = cmpResult; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithcmpz.c000066400000000000000000000033301470420105600244200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsCmpZero_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsCmpZero_BN // // Purpose: Compare BigNum value with zero. // // Returns: Reason: // ippStsNullPtrErr pBN == NULL // pResult == NULL // ippStsContextMatchErr !BN_VALID_ID(pBN) // ippStsNoErr no errors // // Parameters: // pBN BigNum ctx // pResult result of comparison // *F*/ IPPFUN(IppStatus, ippsCmpZero_BN, (const IppsBigNumState* pBN, Ipp32u* pResult)) { IPP_BAD_PTR2_RET(pBN, pResult); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); if(BN_SIZE(pBN)==1 && BN_NUMBER(pBN)[0]==0) *pResult = IS_ZERO; else if (BN_SIGN(pBN)==ippBigNumPOS) *pResult = GREATER_THAN_ZERO; else if (BN_SIGN(pBN)==ippBigNumNEG) *pResult = LESS_THAN_ZERO; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithdiv.c000066400000000000000000000060711470420105600242360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsDiv_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsDiv_BN // // Purpose: Divide BigNums. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pB == NULL // pQ == NULL // pR == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pB) // !BN_VALID_ID(pQ) // !BN_VALID_ID(pR) // ippStsDivByZeroErr BN_SIZE(pB) == 1 && BN_NUMBER(pB)[0] == 0 // ippStsOutOfRangeErr pQ and/or pR can not hold result // ippStsNoErr no errors // // Parameters: // pA source BigNum // pB source BigNum // pQ quotient BigNum // pR reminder BigNum // // A = Q*B + R, 0 <= val(R) < val(B), sgn(A)==sgn(R) // *F*/ IPPFUN(IppStatus, ippsDiv_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pQ, IppsBigNumState* pR)) { IPP_BAD_PTR4_RET(pA, pB, pQ, pR); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pQ), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(BN_SIZE(pB)== 1 && BN_NUMBER(pB)[0]==0, ippStsDivByZeroErr); IPP_BADARG_RET(BN_ROOM(pR)cmpRes) SWAP_PTR(IppsBigNumState, x, y); if(0==cmpRes) { COPY_BNU(BN_NUMBER(g), BN_NUMBER(x), BN_SIZE(x)); BN_SIGN(g) = ippBigNumPOS; BN_SIZE(g) = BN_SIZE(x); return ippStsNoErr; } if(BN_SIZE(x)==1) { BNU_CHUNK_T gcd = cpGcd_BNU(BN_NUMBER(x)[0], BN_NUMBER(y)[0]); BN_NUMBER(g)[0] = gcd; BN_SIZE(g) = 1; return ippStsNoErr; } } { Ipp32u* xBuffer = (Ipp32u*)BN_BUFFER(x); Ipp32u* yBuffer = (Ipp32u*)BN_BUFFER(y); Ipp32u* gBuffer = (Ipp32u*)BN_BUFFER(g); Ipp32u* xData = (Ipp32u*)BN_NUMBER(x); Ipp32u* yData = (Ipp32u*)BN_NUMBER(y); Ipp32u* gData = (Ipp32u*)BN_NUMBER(g); cpSize nsXmax = BN_ROOM(x)*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))); cpSize nsYmax = BN_ROOM(y)*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))); cpSize nsGmax = BN_ROOM(g)*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))); cpSize nsX = BN_SIZE(x)*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))); cpSize nsY = BN_SIZE(y)*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))); Ipp32u* T; Ipp32u* u; FIX_BNU32(xData, nsX); FIX_BNU32(yData, nsY); /* init buffers */ ZEXPAND_COPY_BNU(xBuffer, nsXmax, xData, nsX); ZEXPAND_COPY_BNU(yBuffer, nsYmax, yData, nsY); T = gBuffer; u = gData; ZEXPAND_BNU(T, 0, nsGmax); ZEXPAND_BNU(u, 0, nsGmax); while(nsX > (cpSize)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) { /* xx and yy is the high-order digits of x and y (yy could be 0) */ Ipp64u xx = (Ipp64u)(xBuffer[nsX-1]); Ipp64u yy = (nsY < nsX)? 0 : (Ipp64u)(yBuffer[nsY-1]); Ipp64s AA = 1; Ipp64s BB = 0; Ipp64s CC = 0; Ipp64s DD = 1; Ipp64s t; while((yy+(Ipp64u)CC)!=0 && (yy+(Ipp64u)DD)!=0) { Ipp64u q = ( xx + (Ipp64u)AA ) / ( yy + (Ipp64u)CC ); Ipp64u q1 = ( xx + (Ipp64u)BB ) / ( yy + (Ipp64u)DD ); if(q!=q1) break; t = AA - (Ipp64s)q*CC; AA = CC; CC = t; t = BB - (Ipp64s)q*DD; BB = DD; DD = t; t = (Ipp64s)(xx - q*yy); xx = yy; yy = (Ipp64u)t; } if(BB == 0) { /* T = x mod y */ cpSize nsT = cpMod_BNU32(xBuffer, nsX, yBuffer, nsY); ZEXPAND_BNU(T, 0, nsGmax); COPY_BNU(T, xBuffer, nsT); /* a = b; b = T; */ ZEXPAND_BNU(xBuffer, 0, nsXmax); COPY_BNU(xBuffer, yBuffer, nsY); ZEXPAND_BNU(yBuffer, 0, nsYmax); COPY_BNU(yBuffer, T, nsY); } else { Ipp32u carry; /* // T = AA*x + BB*y; // u = CC*x + DD*y; // b = u; a = T; */ if((AA <= 0)&&(BB>=0)) { Ipp32u a1 = (Ipp32u)(-AA); carry = cpMulDgt_BNU32(T, yBuffer, nsY, (Ipp32u)BB); carry = cpMulDgt_BNU32(u, xBuffer, nsY, a1); /* T = BB*y - AA*x; */ carry = cpSub_BNU32(T, T, u, nsY); } else { if((AA >= 0)&&(BB<=0)) { Ipp32u b1 = (Ipp32u)(-BB); carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA); carry = cpMulDgt_BNU32(u, yBuffer, nsY, b1); /* T = AA*x - BB*y; */ carry = cpSub_BNU32(T, T, u, nsY); } else { /*AA*BB>=0 */ carry = cpMulDgt_BNU32(T, xBuffer, nsY, (Ipp32u)AA); carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)BB); /* T = AA*x + BB*y; */ carry = cpAdd_BNU32(T, T, u, nsY); } } /* Now T is reserved. We use only u for intermediate results. */ if((CC <= 0)&&(DD>=0)){ Ipp32u c1 = (Ipp32u)(-CC); /* u = x*CC; x = u; */ carry = cpMulDgt_BNU32(u, xBuffer, nsY, c1); COPY_BNU(xBuffer, u, nsY); /* u = y*DD; */ carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD); /* u = DD*y - CC*x; */ carry = cpSub_BNU32(u, u, xBuffer, nsY); } else { if((CC >= 0)&&(DD<=0)){ Ipp32u d1 = (Ipp32u)(-DD); /* u = y*DD; y = u */ carry = cpMulDgt_BNU32(u, yBuffer, nsY, d1); COPY_BNU(yBuffer, u, nsY); /* u = CC*x; */ carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC); /* u = CC*x - DD*y; */ carry = cpSub_BNU32(u, u, yBuffer, nsY); } else { /*CC*DD>=0 */ /* y = y*DD */ carry = cpMulDgt_BNU32(u, yBuffer, nsY, (Ipp32u)DD); COPY_BNU(yBuffer, u, nsY); /* u = x*CC */ carry = cpMulDgt_BNU32(u, xBuffer, nsY, (Ipp32u)CC); /* u = x*CC + y*DD */ carry = cpAdd_BNU32(u, u, yBuffer, nsY); } } IPP_UNREFERENCED_PARAMETER(carry); /* y = u; x = T; */ COPY_BNU(yBuffer, u, nsY); COPY_BNU(xBuffer, T, nsY); } FIX_BNU32(xBuffer, nsX); FIX_BNU32(yBuffer, nsY); if (nsY > nsX) { SWAP_PTR(IppsBigNumState, x, y); SWAP(nsX, nsY); } if (nsY==1 && yBuffer[nsY-1]==0) { /* End evaluation */ ZEXPAND_BNU(gData, 0, nsGmax); COPY_BNU(gData, xBuffer, nsX); BN_SIZE(g) = INTERNAL_BNU_LENGTH(nsX); BN_SIGN(g) = ippBigNumPOS; return ippStsNoErr; } } BN_NUMBER(g)[0] = cpGcd_BNU(((BNU_CHUNK_T*)xBuffer)[0], ((BNU_CHUNK_T*)yBuffer)[0]); BN_SIZE(g) = 1; BN_SIGN(g) = ippBigNumPOS; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithmac.c000066400000000000000000000072761470420105600242240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMAC_BN_I() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsMAC_BN_I // // Purpose: Multiply and Accumulate BigNums. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pB == NULL // pR == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pB) // !BN_VALID_ID(pR) // ippStsOutOfRangeErr pR can not fit result // ippStsNoErr no errors // // Parameters: // pA source BigNum // pB source BigNum // pR resultant BigNum // *F*/ IPPFUN(IppStatus, ippsMAC_BN_I, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) { IPP_BAD_PTR3_RET(pA, pB, pR); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); { BNU_CHUNK_T* pDataA = BN_NUMBER(pA); BNU_CHUNK_T* pDataB = BN_NUMBER(pB); cpSize nsA = BN_SIZE(pA); cpSize nsB = BN_SIZE(pB); cpSize bitSizeA = BITSIZE_BNU(pDataA, nsA); cpSize bitSizeB = BITSIZE_BNU(pDataB, nsB); /* size of temporary pruduct */ cpSize nsP = BITS_BNU_CHUNK(bitSizeA+bitSizeB); /* test if multiplicant/multiplier is zero */ if(!bitSizeA || !bitSizeB) return ippStsNoErr; /* test if product can't fit to the result */ IPP_BADARG_RET(BN_ROOM(pR)cmpRes) { SWAP_PTR(BNU_CHUNK_T, pTmp, pDataP); } cpSub_BNU(pDataR, pTmp, pDataP, room); BN_SIGN(pR) = cmpRes>0? sgnR : INVERSE_SIGN(sgnR); } FIX_BNU(pDataR, room); BN_SIZE(pR) = room; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithminv.c000066400000000000000000000054251470420105600244270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsModInv_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsModInv_BN // // Purpose: Multiplicative Inversion BigNum. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pM == NULL // pInv == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pM) // !BN_VALID_ID(pInv) // ippStsBadArgErr A<=0 // ippStsBadModulusErr M<=0 // ippStsScaleRangeErr A>=M // ippStsOutOfRangeErr pInv can not hold result // ippStsNoErr no errors // ippStsBadModulusErr inversion not found // // Parameters: // pA source (value) BigNum // pM source (modulus) BigNum // pInv result BigNum // *F*/ IPPFUN(IppStatus, ippsModInv_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pInv) ) { IPP_BAD_PTR3_RET(pA, pM, pInv); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pInv), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pInv) < BN_SIZE(pM), ippStsOutOfRangeErr); IPP_BADARG_RET(BN_NEGATIVE(pA) || (BN_SIZE(pA)==1 && BN_NUMBER(pA)[0]==0), ippStsBadArgErr); IPP_BADARG_RET(BN_NEGATIVE(pM) || (BN_SIZE(pM)==1 && BN_NUMBER(pM)[0]==0), ippStsBadModulusErr); IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pM), BN_SIZE(pM)) >= 0, ippStsScaleRangeErr); { cpSize nsR = cpModInv_BNU(BN_NUMBER(pInv), BN_NUMBER(pA), BN_SIZE(pA), BN_NUMBER(pM), BN_SIZE(pM), BN_BUFFER(pInv), BN_BUFFER(pA), BN_BUFFER(pM)); if(nsR) { BN_SIGN(pInv) = ippBigNumPOS; BN_SIZE(pInv) = nsR; return ippStsNoErr; } else return ippStsBadModulusErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithmod.c000066400000000000000000000056331470420105600242360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMod_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsMod_BN // // Purpose: reduction BigNum. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pM == NULL // pR == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pM) // !BN_VALID_ID(pR) // ippStsOutOfRangeErr pR can not hold result // ippStsBadModulusErr modulus IppsBigNumState* pM // is not a positive integer // ippStsNoErr no errors // // Parameters: // pA source BigNum // pB source BigNum // pR reminder BigNum // // A = Q*M + R, 0 <= R < B // *F*/ IPPFUN(IppStatus, ippsMod_BN, (IppsBigNumState* pA, IppsBigNumState* pM, IppsBigNumState* pR)) { IPP_BAD_PTR3_RET(pA, pM, pR); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pM), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pM), ippStsBadModulusErr); IPP_BADARG_RET(BN_SIZE(pM)== 1 && BN_NUMBER(pM)[0]==0, ippStsBadModulusErr); IPP_BADARG_RET(BN_ROOM(pR)BN_ROOM(pR), ippStsOutOfRangeErr); BN_SIZE(pR) = nsR; BN_SIGN(pR) = (BN_SIGN(pA)==BN_SIGN(pB)? ippBigNumPOS : ippBigNumNEG); return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnarithsub.c000066400000000000000000000066761470420105600242600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsSub_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsSub_BN // // Purpose: Subtract BigNums. // // Returns: Reason: // ippStsNullPtrErr pA == NULL // pB == NULL // pR == NULL // ippStsContextMatchErr !BN_VALID_ID(pA) // !BN_VALID_ID(pB) // !BN_VALID_ID(pR) // ippStsOutOfRangeErr pR can not hold result // ippStsNoErr no errors // // Parameters: // pA source BigNum // pB source BigNum // pR resultant BigNum // *F*/ IPPFUN(IppStatus, ippsSub_BN, (IppsBigNumState* pA, IppsBigNumState* pB, IppsBigNumState* pR)) { IPP_BAD_PTR3_RET(pA, pB, pR); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); { cpSize nsA = BN_SIZE(pA); cpSize nsB = BN_SIZE(pB); cpSize nsR = BN_ROOM(pR); IPP_BADARG_RET(nsR < IPP_MAX(nsA, nsB), ippStsOutOfRangeErr); { BNU_CHUNK_T* pDataR = BN_NUMBER(pR); IppsBigNumSGN sgnA = BN_SIGN(pA); IppsBigNumSGN sgnB = BN_SIGN(pB); BNU_CHUNK_T* pDataA = BN_NUMBER(pA); BNU_CHUNK_T* pDataB = BN_NUMBER(pB); BNU_CHUNK_T carry; if(sgnA!=sgnB) { if(nsA < nsB) { SWAP(nsA, nsB); SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); } carry = cpAdd_BNU(pDataR, pDataA, pDataB, nsB); if(nsA>nsB) carry = cpInc_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); if(carry) { if(nsR > nsA) pDataR[nsA++] = carry; else IPP_ERROR_RET(ippStsOutOfRangeErr); } BN_SIGN(pR) = sgnA; } else { int cmpRes= cpCmp_BNU(pDataA, nsA, pDataB, nsB); if(0==cmpRes) { ZEXPAND_BNU(pDataR,0, nsR); BN_SIZE(pR) = 1; BN_SIGN(pR) = ippBigNumPOS; return ippStsNoErr; } if(0>cmpRes) { SWAP(nsA, nsB); SWAP_PTR(BNU_CHUNK_T, pDataA, pDataB); } carry = cpSub_BNU(pDataR, pDataA, pDataB, nsB); if(nsA>nsB) cpDec_BNU(pDataR+nsB, pDataA+nsB, nsA-nsB, carry); BN_SIGN(pR) = cmpRes>0? sgnA : INVERSE_SIGN(sgnA); } FIX_BNU(pDataR, nsA); BN_SIZE(pR) = nsA; return ippStsNoErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpbngetext.c000066400000000000000000000040421470420105600237200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsExtGet_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsExtGet_BN // // Purpose: Extracts the specified combination of the sign, data // length, and value characteristics of the integer big // number from the input structure. // // Returns: Reason: // ippStsNullPtrErr pBN == NULL // ippStsContextMatchErr !BN_VALID_ID(pBN) // ippStsNoErr no errors // // Parameters: // pSgn pointer to the sign // pBitSize pointer to the data size (in bits) // pData pointer to the data buffer // pBN BigNum ctx // *F*/ IPPFUN(IppStatus, ippsExtGet_BN, (IppsBigNumSGN* pSgn, int* pBitSize, Ipp32u* pData, const IppsBigNumState* pBN)) { IPP_BAD_PTR1_RET(pBN); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); { cpSize bitSize = BITSIZE_BNU(BN_NUMBER(pBN), BN_SIZE(pBN)); if(0==bitSize) bitSize = 1; if(pData) COPY_BNU(pData, (Ipp32u*)BN_NUMBER(pBN), BITS2WORD32_SIZE(bitSize)); if(pSgn) *pSgn = BN_SIGN(pBN); if(pBitSize) *pBitSize = bitSize; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbngetlen.c000066400000000000000000000030761470420105600237040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsGetSize_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsGetSize_BN // // Purpose: Returns BigNum room. // // Returns: Reason: // ippStsNullPtrErr pBN == NULL // pSize == NULL // ippStsContextMatchErr !BN_VALID_ID(pBN) // ippStsNoErr no errors // // Parameters: // pBN BigNum ctx // pSize max BigNum length (in Ipp32u chunks) // *F*/ IPPFUN(IppStatus, ippsGetSize_BN, (const IppsBigNumState* pBN, int* pSize)) { IPP_BAD_PTR2_RET(pBN, pSize); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); *pSize = BN_ROOM(pBN)*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpbngetoctstr.c000066400000000000000000000037011470420105600244370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Big Number Operations // // Contents: // ippsGetOctString_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" /*F* // Name: ippsGetOctString_BN // // Purpose: Convert BN value into the octet string. // // Returns: Reason: // ippStsNullPtrErr NULL == pOctStr // NULL == pBN // // ippStsContextMatchErr !BN_VALID_ID(pBN) // // ippStsRangeErr BN <0 // // ippStsLengthErr strLen is enough for keep BN value // // ippStsNoErr no errors // // Parameters: // pBN pointer to the source BN // pOctStr pointer to the target octet string // strLen octet string length *F*/ IPPFUN(IppStatus, ippsGetOctString_BN,(Ipp8u* pOctStr, int strLen, const IppsBigNumState* pBN)) { IPP_BAD_PTR2_RET(pOctStr, pBN); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pBN), ippStsRangeErr); IPP_BADARG_RET((0>strLen), ippStsLengthErr); return cpToOctStr_BNU(pOctStr,strLen, BN_NUMBER(pBN),BN_SIZE(pBN))? ippStsNoErr : ippStsLengthErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpbngetref.c000066400000000000000000000043161470420105600237000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsBigNumGetSize() // ippsBigNumInit() // // ippsSet_BN() // ippsGet_BN() // ippsGetSize_BN() // ippsExtGet_BN() // ippsRef_BN() // // ippsCmpZero_BN() // ippsCmp_BN() // // ippsAdd_BN() // ippsSub_BN() // ippsMul_BN() // ippsMAC_BN_I() // ippsDiv_BN() // ippsMod_BN() // ippsGcd_BN() // ippsModInv_BN() // // cpPackBigNumCtx(), cpUnpackBigNumCtx() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsRef_BN // // Purpose: Get BigNum info. // // Returns: Reason: // ippStsNullPtrErr pBN == NULL // ippStsContextMatchErr !BN_VALID_ID(pBN) // ippStsNoErr no errors // // Parameters: // pSgn pointer to the sign // pBitSize pointer to the data size (in bits) // ppData pointer to the data buffer // pBN BigNum ctx // *F*/ IPPFUN(IppStatus, ippsRef_BN, (IppsBigNumSGN* pSgn, int* pBitSize, Ipp32u** const ppData, const IppsBigNumState *pBN)) { IPP_BAD_PTR1_RET(pBN); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); if(pSgn) *pSgn = BN_SIGN(pBN); if(pBitSize) { cpSize bitLen = BITSIZE_BNU(BN_NUMBER(pBN), BN_SIZE(pBN)); *pBitSize = bitLen? bitLen : 1; } if(ppData) *ppData = (Ipp32u*)BN_NUMBER(pBN); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpbngetsize.c000066400000000000000000000037521470420105600241010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsBigNumGetSize() // ippsBigNumInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsBigNumGetSize // // Purpose: Returns size of BigNum ctx (bytes). // // Returns: Reason: // ippStsNullPtrErr pCtxSize == NULL // ippStsLengthErr length < 1 // length > BITS2WORD32_SIZE(BN_MAXBITSIZE) // ippStsNoErr no errors // // Parameters: // length max BN length (32-bits segments) // pSize pointer BigNum ctx size // *F*/ IPPFUN(IppStatus, ippsBigNumGetSize, (int length, cpSize *pCtxSize)) { IPP_BAD_PTR1_RET(pCtxSize); IPP_BADARG_RET(length<1 || length>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); { /* convert length to the number of BNU_CHUNK_T */ cpSize len = INTERNAL_BNU_LENGTH(length); /* reserve one BNU_CHUNK_T more for cpDiv_BNU, mul, mont exp operations */ len++; *pCtxSize = (Ipp32s)sizeof(IppsBigNumState) + len*(Ipp32s)sizeof(BNU_CHUNK_T) + len*(Ipp32s)sizeof(BNU_CHUNK_T) + BN_ALIGNMENT-1; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbngetwords.c000066400000000000000000000040601470420105600242560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsGet_BN() */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsGet_BN // // Purpose: Get BigNum. // // Returns: Reason: // ippStsNullPtrErr pBN == NULL // pData == NULL // pSgn == NULL // pLengthInBits ==NULL // ippStsContextMatchErr !BN_VALID_ID(pBN) // ippStsNoErr no errors // // Parameters: // pSgn pointer to the sign // pLengthInBits pointer to the data size (in Ipp32u chunks) // pData pointer to the data buffer // pBN BigNum ctx // *F*/ IPPFUN(IppStatus, ippsGet_BN, (IppsBigNumSGN* pSgn, int* pLengthInBits, Ipp32u* pData, const IppsBigNumState* pBN)) { IPP_BAD_PTR4_RET(pSgn, pLengthInBits, pData, pBN); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); { cpSize len32 = BN_SIZE(pBN)*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); Ipp32u* bnData = (Ipp32u*)BN_NUMBER(pBN); FIX_BNU32(bnData, len32); COPY_BNU(pData, bnData, len32); *pSgn = BN_SIGN(pBN); *pLengthInBits = len32; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbninit.c000066400000000000000000000050611470420105600233650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsBigNumGetSize() // ippsBigNumInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" /*F* // Name: ippsBigNumInit // // Purpose: Init BigNum spec for future usage. // // Returns: Reason: // ippStsNullPtrErr pBN == NULL // ippStsLengthErr length<1 // length > BITS2WORD32_SIZE(BN_MAXBITSIZE) // ippStsNoErr no errors // // Parameters: // length max BN length (32-bits segments) // pBN BigNum ctx // *F*/ IPPFUN(IppStatus, ippsBigNumInit, (int length, IppsBigNumState* pBN)) { IPP_BADARG_RET(length<1 || length>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); IPP_BAD_PTR1_RET(pBN); { Ipp8u* ptr = (Ipp8u*)pBN; /* convert length to the number of BNU_CHUNK_T */ cpSize len = INTERNAL_BNU_LENGTH(length); BN_SIGN(pBN) = ippBigNumPOS; BN_SIZE(pBN) = 1; /* initial value is zero */ BN_ROOM(pBN) = len; /* close to what has been passed by user */ /* reserve one BNU_CHUNK_T more for cpDiv_BNU, mul, mont exp operations */ len++; ptr += sizeof(IppsBigNumState); /* allocate buffers */ ptr = (Ipp8u*)(IPP_ALIGNED_PTR(ptr, BN_ALIGNMENT)); BN_NUMBER(pBN) = (BNU_CHUNK_T*)ptr; ptr += len * (Ipp32s)sizeof(BNU_CHUNK_T); BN_BUFFER(pBN) = (BNU_CHUNK_T*)(ptr); /* use expanded length here */ /* set BN value and buffer to zero */ ZEXPAND_BNU(BN_NUMBER(pBN), 0, len); ZEXPAND_BNU(BN_BUFFER(pBN), 0, len); BN_SET_ID(pBN); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnresource.h000066400000000000000000000027641470420105600242650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal BN Resource Definitions & Function Prototypes // // */ #if !defined(_PCP_BNRESOURCE_H) #define _PCP_BNRESOURCE_H typedef struct { void* pNext; IppsBigNumState* pBN; } BigNumNode; /* size (byte) of BN resource */ #define cpBigNumListGetSize OWNAPI(cpBigNumListGetSize) IPP_OWN_DECL (int, cpBigNumListGetSize, (int feBitSize, int nodes)) /* init BN resource */ #define cpBigNumListInit OWNAPI(cpBigNumListInit) IPP_OWN_DECL (void, cpBigNumListInit, (int feBitSize, int nodes, BigNumNode* pList)) /* get BN from resource */ #define cpBigNumListGet OWNAPI(cpBigNumListGet) IPP_OWN_DECL (IppsBigNumState*, cpBigNumListGet, (BigNumNode** pList)) #endif /* _PCP_BNRESOURCE_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpbnresourceca.c000066400000000000000000000055121470420105600245560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal ECC (prime) Resource List Function // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbnresource.h" #include "pcpbn.h" /*F* // Name: cpBigNumListGetSize // // Purpose: Size of BigNum List Buffer // // Returns: // Size of List Buffer // // Parameters: // feBitSize size in bits // nodes number of nodes // *F*/ IPP_OWN_DEFN (int, cpBigNumListGetSize, (int feBitSize, int nodes)) { /* size of buffer per single big number */ int bnSize; ippsBigNumGetSize(BITS2WORD32_SIZE(feBitSize), &bnSize); /* size of buffer for whole list */ return ((Ipp32s)sizeof(BigNumNode) + bnSize) * nodes; } /*F* // Name: cpBigNumListInit // // Purpose: Init list // // // Parameters: // feBitSize size in bit // nodes number of nodes // pList pointer to list // // Note: buffer for BN list must have appropriate alignment // *F*/ IPP_OWN_DEFN (void, cpBigNumListInit, (int feBitSize, int nodes, BigNumNode* pList)) { int itemSize; /* length of Big Num */ int bnLen = BITS2WORD32_SIZE(feBitSize); /* size of buffer per single big number */ ippsBigNumGetSize(bnLen, &itemSize); /* size of list item */ itemSize += sizeof(BigNumNode); { int n; /* init all nodes */ BigNumNode* pNode = (BigNumNode*)( (Ipp8u*)pList + (nodes-1)*itemSize ); BigNumNode* pNext = NULL; for(n=0; npNext = pNext; pNode->pBN = (IppsBigNumState*)(tbnPtr); ippsBigNumInit(bnLen, pNode->pBN); pNext = pNode; pNode = (BigNumNode*)( (Ipp8u*)pNode - itemSize); } } } /*F* // Name: cpBigNumListGet // // Purpose: Get BigNum reference // // Returns: // BigNum reference // // Parameters: // ppList pointer to pointer to List // *F*/ IPP_OWN_DEFN (IppsBigNumState*, cpBigNumListGet, (BigNumNode** ppList)) { if(*ppList) { IppsBigNumState* ret = (*ppList)->pBN; *ppList = (*ppList)->pNext; return ret; } else return NULL; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnsetoctstr.c000066400000000000000000000043641470420105600244610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Big Number Operations // // Contents: // ippsSetOctString_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" /*F* // Name: ippsSetOctString_BN // // Purpose: Convert octet string into the BN value. // // Returns: Reason: // ippStsNullPtrErr NULL == pOctStr // NULL == pBN // // ippStsContextMatchErr !BN_VALID_ID(pBN) // // ippStsLengthErr 0 > strLen // // ippStsSizeErr BN_ROOM(pBN) is enough for keep actual strLen // // ippStsNoErr no errors // // Parameters: // pOctStr pointer to the source octet string // strLen octet string length // pBN pointer to the target BN // *F*/ IPPFUN(IppStatus, ippsSetOctString_BN,(const Ipp8u* pOctStr, int strLen, IppsBigNumState* pBN)) { IPP_BAD_PTR2_RET(pOctStr, pBN); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); IPP_BADARG_RET((0>strLen), ippStsLengthErr); /* remove leading zeros */ while(strLen && (0==pOctStr[0])) { strLen--; pOctStr++; } /* test BN size */ IPP_BADARG_RET((int)((Ipp32s)sizeof(BNU_CHUNK_T)*BN_ROOM(pBN)) BN_ROOM(pBN) // ippStsNoErr no errors // // Parameters: // sgn sign // length data size (in Ipp32u chunks) // pData source data pointer // pBN BigNum ctx // *F*/ IPPFUN(IppStatus, ippsSet_BN, (IppsBigNumSGN sgn, int length, const Ipp32u* pData, IppsBigNumState* pBN)) { IPP_BAD_PTR2_RET(pData, pBN); IPP_BADARG_RET(!BN_VALID_ID(pBN), ippStsContextMatchErr); IPP_BADARG_RET(length<1, ippStsLengthErr); /* compute real size */ FIX_BNU32(pData, length); { cpSize len = INTERNAL_BNU_LENGTH(length); IPP_BADARG_RET(len > BN_ROOM(pBN), ippStsOutOfRangeErr); ZEXPAND_COPY_BNU((Ipp32u*)BN_NUMBER(pBN), BN_ROOM(pBN)*(int)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)), pData, length); BN_SIZE(pBN) = len; if(length==1 && pData[0] == 0) sgn = ippBigNumPOS; /* consider zero value as positive */ BN_SIGN(pBN) = sgn; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32_arith_add.c000066400000000000000000000026731470420105600250400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal BNU32 arithmetic. // // Contents: // cpAdd_BNU32() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnu32misc.h" #include "pcpbnu32arith.h" /*F* // Name: cpSub_BNU32 // // Purpose: addition BNU32. // // Returns: // carry // // Parameters: // pA source // pB source // ns size // pR result // *F*/ IPP_OWN_DEFN (Ipp32u, cpAdd_BNU32, (Ipp32u* pR, const Ipp32u* pA, const Ipp32u* pB, cpSize ns)) { Ipp32u carry = 0; cpSize i; for(i=0; i>(32-1); } return borrow; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32_arith_div.c000066400000000000000000000101661470420105600250660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal BNU32 arithmetic. // // Contents: // cpDiv_BNU32() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnu32misc.h" #include "pcpbnu32arith.h" /*F* // Name: cpDiv_BNU32 // // Purpose: BNU32 division. // // Returns: // size of result // // Parameters: // pX source X // pY source Y // pQ source quotient // sizeQ pointer to max size of Q // sizeX size of A // sizeY size of B // *F*/ #if !((_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) IPP_OWN_DEFN (int, cpDiv_BNU32, (Ipp32u* pQ, cpSize* sizeQ, Ipp32u* pX, cpSize sizeX, Ipp32u* pY, cpSize sizeY)) { FIX_BNU32(pY,sizeY); FIX_BNU32(pX,sizeX); /* special case */ if(sizeX < sizeY) { if(pQ) { pQ[0] = 0; *sizeQ = 1; } return sizeX; } /* special case */ if(1 == sizeY) { int i; Ipp32u r = 0; for(i=(int)sizeX-1; i>=0; i--) { Ipp64u tmp = IPP_MAKEDWORD(pX[i],r); Ipp32u q = IPP_LODWORD(tmp / pY[0]); r = IPP_LODWORD(tmp - q*pY[0]); if(pQ) pQ[i] = q; } pX[0] = r; if(pQ) { FIX_BNU32(pQ,sizeX); *sizeQ = sizeX; } return 1; } /* common case */ { cpSize qs = sizeX-sizeY+1; cpSize nlz = cpNLZ_BNU32(pY[sizeY-1]); /* normalization */ pX[sizeX] = 0; if(nlz) { cpSize ni; pX[sizeX] = pX[sizeX-1] >> (32-nlz); for(ni=sizeX-1; ni>0; ni--) pX[ni] = (pX[ni]<>(32-nlz)); pX[0] <<= nlz; for(ni=sizeY-1; ni>0; ni--) pY[ni] = (pY[ni]<>(32-nlz)); pY[0] <<= nlz; } /* // division */ { Ipp32u yHi = pY[sizeY-1]; int i; for(i=(int)qs-1; i>=0; i--) { Ipp32u extend; /* estimate digit of quotient */ Ipp64u tmp = IPP_MAKEDWORD(pX[i+sizeY-1], pX[i+sizeY]); Ipp64u q = tmp / yHi; Ipp64u r = tmp - q*yHi; /* tune estimation above */ //for(; (q>=CONST_64(0x100000000)) || (Ipp64u)q*pY[sizeY-2] > IPP_MAKEDWORD(pX[i+sizeY-2],r); ) { for(; IPP_HIDWORD(q) || (Ipp64u)q*pY[sizeY-2] > IPP_MAKEDWORD(pX[i+sizeY-2],r); ) { q -= 1; r += yHi; if( IPP_HIDWORD(r) ) break; } /* multiply and subtract */ extend = cpSubMulDgt_BNU32(pX+i, pY, sizeY, (Ipp32u)q); extend = (pX[i+sizeY] -= extend); if(extend) { /* subtracted too much */ q -= 1; extend = cpAdd_BNU32(pX+i, pY, pX+i, sizeY); pX[i+sizeY] += extend; } /* store quotation digit */ if(pQ) pQ[i] = IPP_LODWORD(q); } } /* de-normalization */ if(nlz) { cpSize ni; for(ni=0; ni>nlz) | (pX[ni+1]<<(32-nlz)); for(ni=0; ni>nlz) | (pY[ni+1]<<(32-nlz)); pY[sizeY-1] >>= nlz; } FIX_BNU32(pX,sizeX); if(pQ) { FIX_BNU32(pQ,qs); *sizeQ = qs; } return sizeX; } } #endif cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32_arith_inc.c000066400000000000000000000026651470420105600250620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal BNU32 arithmetic. // // Contents: // cpInc_BNU32() // */ #include "owncp.h" #include "pcpbnumisc.h" #include "pcpbnu32misc.h" #include "pcpbnu32arith.h" /*F* // Name: cpInc_BNU32 // // Purpose: BNU32 increment. // // Returns: // carry // // Parameters: // pA source // pR result // ns size // v borrow // *F*/ IPP_OWN_DEFN (Ipp32u, cpInc_BNU32, (Ipp32u* pR, const Ipp32u* pA, cpSize ns, Ipp32u v)) { Ipp32u carry = v; cpSize i; for(i=0; i=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) IPP_OWN_DEFN (Ipp32u, cpSubMulDgt_BNU32, (Ipp32u* pR, const Ipp32u* pA, cpSize nsA, Ipp32u val)) { Ipp32u carry = 0; for(; nsA>0; nsA--) { Ipp64u r = (Ipp64u)*pR - (Ipp64u)(*pA++) * val - carry; *pR++ = IPP_LODWORD(r); carry = 0-IPP_HIDWORD(r); } return carry; } #endif cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32_getoctstr.c000066400000000000000000000042111470420105600251250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Unsigned internal BNU32 misc functionality // // Contents: // cpToOctStr_BNU32() // */ #include "owncp.h" #include "pcpbnuimpl.h" #include "pcpbnumisc.h" #include "pcpbnu32misc.h" /*F* // Name: cpToOctStr_BNU32 // // Purpose: Convert BNU into HexString representation. // // Returns: // length of the string or 0 if no success // // Parameters: // pBNU pointer to the source BN // bnuSize size of BN // pStr pointer to the target octet string // strLen octet string length *F*/ IPP_OWN_DEFN (cpSize, cpToOctStr_BNU32, (Ipp8u* pStr, cpSize strLen, const Ipp32u* pBNU, cpSize bnuSize)) { FIX_BNU32(pBNU, bnuSize); { int bnuBitSize = BITSIZE_BNU32(pBNU, bnuSize); if(bnuBitSize <= strLen*BYTESIZE) { Ipp32u x = pBNU[bnuSize-1]; ZEXPAND_BNU(pStr, 0, strLen); pStr += strLen - BITS2WORD8_SIZE(bnuBitSize); if(x) { int nb; for(nb=cpNLZ_BNU32(x)/BYTESIZE; nb<4; nb++) *pStr++ = EBYTE(x,3-nb); for(--bnuSize; bnuSize>0; bnuSize--) { x = pBNU[bnuSize-1]; *pStr++ = EBYTE(x,3); *pStr++ = EBYTE(x,2); *pStr++ = EBYTE(x,1); *pStr++ = EBYTE(x,0); } } return strLen; } else return 0; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32_nlz.c000066400000000000000000000032231470420105600237140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Unsigned internal BNU32 misc functionality // // Contents: // cpNLZ_BNU32() // */ #include "owncp.h" #include "pcpbnuimpl.h" #include "pcpbnumisc.h" #include "pcpbnu32misc.h" /*F* // Name: cpNLZ_BNU32 // // Purpose: Returns number of leading zeros of the 32-bit BN chunk. // // Returns: // number of leading zeros of the 32-bit BN chunk // // Parameters: // x BigNum x // *F*/ #if (_IPP < _IPP_H9) IPP_OWN_DEFN (cpSize, cpNLZ_BNU32, (Ipp32u x)) { cpSize nlz = BITSIZE(Ipp32u); if(x) { nlz = 0; if( 0==(x & 0xFFFF0000) ) { nlz +=16; x<<=16; } if( 0==(x & 0xFF000000) ) { nlz += 8; x<<= 8; } if( 0==(x & 0xF0000000) ) { nlz += 4; x<<= 4; } if( 0==(x & 0xC0000000) ) { nlz += 2; x<<= 2; } if( 0==(x & 0x80000000) ) { nlz++; } } return nlz; } #endif cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32_setoctstr.c000066400000000000000000000037621470420105600251530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Unsigned internal BNU32 misc functionality // // Contents: // cpToOctStr_BNU32() // */ #include "owncp.h" #include "pcpbnuimpl.h" #include "pcpbnumisc.h" #include "pcpbnu32misc.h" /*F* // Name: cpFromOctStr_BNU32 // // Purpose: Convert Oct String into BNU representation. // // Returns: // size of BNU in BNU_CHUNK_T chunks // // Parameters: // pOctStr pointer to the source octet string // strLen octet string length // pBNU pointer to the target BN // *F*/ IPP_OWN_DEFN (cpSize, cpFromOctStr_BNU32, (Ipp32u* pBNU, const Ipp8u* pOctStr, cpSize strLen)) { cpSize bnuSize=0; *pBNU = 0; /* start from the end of string */ for(; strLen>=4; bnuSize++,strLen-=4) { /* pack 4 bytes into single Ipp32u value*/ *pBNU++ = (Ipp32u)(( pOctStr[strLen-4]<<(8*3) ) +( pOctStr[strLen-3]<<(8*2) ) +( pOctStr[strLen-2]<<(8*1) ) + pOctStr[strLen-1]); } /* convert the beginning of the string */ if(strLen) { Ipp32u x; for(x=0; strLen>0; strLen--) { Ipp32u d = *pOctStr++; x = x*256 + d; } *pBNU++ = x; bnuSize++; } return bnuSize? bnuSize : 1; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32arith.h000066400000000000000000000043621470420105600240730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2012 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal BNU32 arithmetic // // */ #if !defined(_CP_BNU32_ARITH_H) #define _CP_BNU32_ARITH_H #define cpAdd_BNU32 OWNAPI(cpAdd_BNU32) IPP_OWN_DECL (Ipp32u, cpAdd_BNU32, (Ipp32u* pR, const Ipp32u* pA, const Ipp32u* pB, int ns)) #define cpSub_BNU32 OWNAPI(cpSub_BNU32) IPP_OWN_DECL (Ipp32u, cpSub_BNU32, (Ipp32u* pR, const Ipp32u* pA, const Ipp32u* pB, int ns)) #define cpInc_BNU32 OWNAPI(cpInc_BNU32) IPP_OWN_DECL (Ipp32u, cpInc_BNU32, (Ipp32u* pR, const Ipp32u* pA, cpSize ns, Ipp32u val)) #define cpDec_BNU32 OWNAPI(cpDec_BNU32) IPP_OWN_DECL (Ipp32u, cpDec_BNU32, (Ipp32u* pR, const Ipp32u* pA, cpSize ns, Ipp32u val)) #define cpMulDgt_BNU32 OWNAPI(cpMulDgt_BNU32) IPP_OWN_DECL (Ipp32u, cpMulDgt_BNU32, (Ipp32u* pR, const Ipp32u* pA, int ns, Ipp32u val)) #define cpSubMulDgt_BNU32 OWNAPI(cpSubMulDgt_BNU32) IPP_OWN_DECL (Ipp32u, cpSubMulDgt_BNU32, (Ipp32u* pR, const Ipp32u* pA, int nsA, Ipp32u val)) #define cpDiv_BNU32 OWNAPI(cpDiv_BNU32) IPP_OWN_DECL (int, cpDiv_BNU32, (Ipp32u* pQ, int* nsQ, Ipp32u* pX, int nsX, Ipp32u* pY, int nsY)) #define cpMod_BNU32(pX,sizeX, pM,sizeM) cpDiv_BNU32(NULL,NULL, (pX),(sizeX), (pM),(sizeM)) #define cpFromOS_BNU32 OWNAPI(cpFromOS_BNU32) IPP_OWN_DECL (int, cpFromOS_BNU32, (Ipp32u* pBNU, const Ipp8u* pOctStr, int strLen)) #define cpToOS_BNU32 OWNAPI(cpToOS_BNU32) IPP_OWN_DECL (int, cpToOS_BNU32, (Ipp8u* pStr, int strLen, const Ipp32u* pBNU, int bnuSize)) #endif /* _CP_BNU32_ARITH_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpbnu32misc.h000066400000000000000000000053711470420105600237200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Miscellaneous BNU 32 bit Definitions & Function Prototypes // // */ #if !defined(_CP_BNU32_MISC_H) #define _CP_BNU32_MISC_H /* bit operations */ #define BITSIZE_BNU32(p,ns) ((ns)*BNU_CHUNK_32BIT-cpNLZ_BNU32((p)[(ns)-1])) /* number of leading/trailing zeros */ #if (_IPP < _IPP_H9) #define cpNLZ_BNU32 OWNAPI(cpNLZ_BNU32) IPP_OWN_DECL (cpSize, cpNLZ_BNU32, (Ipp32u x)) #else __IPPCP_INLINE cpSize cpNLZ_BNU32(Ipp32u x) { return (cpSize)_lzcnt_u32(x); } #endif /* Name: cpFix_BNU32 // // Purpose: fix up BNU. // // Returns: // fixed nsA // // Parameters: // pA BNU ptr // nsA size of BNU // */ __IPPCP_INLINE int cpFix_BNU32(const Ipp32u* pA, int nsA) { Ipp32u zscan = (Ipp32u)(-1); int outLen = nsA; for(; nsA>0; nsA--) { zscan &= (Ipp32u)cpIsZero_ct((BNU_CHUNK_T)pA[nsA-1]); outLen -= 1 & zscan; } return (int)((1 & zscan) | ((BNU_CHUNK_T)outLen & ~(BNU_CHUNK_T)zscan)); // change to scanz } #define FIX_BNU32(src,srcLen) ((srcLen) = cpFix_BNU32((src), (srcLen))) /* most significant BNU bit */ #if 0 __IPPCP_INLINE int cpMSBit_BNU32(const Ipp32u* pA, cpSize nsA) { FIX_BNU(pA, nsA); return nsA*BITSIZE(Ipp32u) - cpNLZ_BNU32(pA[nsA-1]) -1; } #endif #if 0 __IPPCP_INLINE int cpCmp_BNU32(const Ipp32u* pA, cpSize nsA, const Ipp32u* pB, cpSize nsB) { if(nsA!=nsB) return nsA>nsB? 1 : -1; else { BNU_CHUNK_T idx = 0; for(; nsA>0; nsA--) idx |= ~cpIsEqu_ct(pA[nsA-1], pB[nsA-1]) & cpIsZero_ct(idx) & (nsA-1); return pA[idx] < pB[idx] ? -1 : (pA[idx] > pB[idx] ? 1 : 0); } } #endif /* to/from oct string conversion */ #define cpToOctStr_BNU32 OWNAPI(cpToOctStr_BNU32) IPP_OWN_DECL (cpSize, cpToOctStr_BNU32, (Ipp8u* pStr, cpSize strLen, const Ipp32u* pBNU, cpSize bnuSize)) #define cpFromOctStr_BNU32 OWNAPI(cpFromOctStr_BNU32) IPP_OWN_DECL (cpSize, cpFromOctStr_BNU32, (Ipp32u* pBNU, const Ipp8u* pOctStr, cpSize strLen)) #endif /* _CP_BNU32_MISC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpbnu_arith_add.c000066400000000000000000000034651470420105600246730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Unsigned arithmetic // // Contents: // cpAdd_BNU() // */ #include "owncp.h" #include "pcpbnuarith.h" #include "pcpbnumisc.h" /*F* // Name: cpAdd_BNU // // Purpose: Addition of two BigNums. // // Returns: // carry of result of add two BigNums. // // Parameters: // pA source BigNum A // pB source BigNum B // pR resultant BigNum // ns size of BigNums *F*/ #if !((_IPP==_IPP_W7) || \ (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || \ (_IPP==_IPP_P8) || \ (_IPP>=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpAdd_BNU_) IPP_OWN_DEFN (BNU_CHUNK_T, cpAdd_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns)) { BNU_CHUNK_T carry = 0; cpSize i; for(i=0; i=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpAddMulDgt_BNU_) IPP_OWN_DEFN (BNU_CHUNK_T, cpAddMulDgt_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)) { BNU_CHUNK_T extension = 0; cpSize i; for(i=0; i=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) IPP_OWN_DEFN (BNU_CHUNK_T, cpDec_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)) { cpSize i; for(i=0; i b){ gcd = a; t = b; } else { t = a; gcd = b; } while (t != 0) { r = gcd % t; gcd = t; t = r; } return gcd; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu_arith_inc.c000066400000000000000000000035431470420105600247110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Unsigned arithmetic // // Contents: // cpInc_BNU() // */ #include "owncp.h" #include "pcpbnuarith.h" #include "pcpbnumisc.h" /*F* // Name: cpInc_BNU // // Purpose: increment BigNum. // // Returns: // carry of result of inc BigNum. // // Parameters: // pA source BigNum A // pR resultant BigNum // ns size of BigNum // val carry *F*/ #if !((_IPP==_IPP_W7) || \ (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || \ (_IPP==_IPP_P8) || \ (_IPP>=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpInc_BNU_) IPP_OWN_DEFN (BNU_CHUNK_T, cpInc_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)) { cpSize i; for(i=0; i=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpMulAdc_BNU_school_) IPP_OWN_DEFN (BNU_CHUNK_T, cpMulAdc_BNU_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB)) { const BNU_CHUNK_T* pa = (BNU_CHUNK_T*)pA; const BNU_CHUNK_T* pb = (BNU_CHUNK_T*)pB; BNU_CHUNK_T* pr = (BNU_CHUNK_T*)pR; BNU_CHUNK_T extension = 0; cpSize i, j; ZEXPAND_BNU(pr, 0, nsA+nsB); for(i=0; i=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpSqrAdc_BNU_school_) IPP_OWN_DEFN (BNU_CHUNK_T, cpSqrAdc_BNU_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA)) { cpSize i; BNU_CHUNK_T extension; BNU_CHUNK_T rH, rL; /* init result */ pR[0] = 0; for(i=1, extension=0; i=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpSub_BNU_) IPP_OWN_DEFN (BNU_CHUNK_T, cpSub_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns)) { BNU_CHUNK_T borrow = 0; cpSize i; for(i=0; i=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpSubMulDgt_BNU_) BNU_CHUNK_T cpSubMulDgt_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val) { BNU_CHUNK_T extension = 0; cpSize i; for(i=0; i0; cnvLen+=(Ipp32s)sizeof(BNU_CHUNK_T), nsA--) { x = pA[nsA-1]; #if (BNU_CHUNK_BITS==BNU_CHUNK_64BIT) *pStr++ = EBYTE(x,7); *pStr++ = EBYTE(x,6); *pStr++ = EBYTE(x,5); *pStr++ = EBYTE(x,4); #endif *pStr++ = EBYTE(x,3); *pStr++ = EBYTE(x,2); *pStr++ = EBYTE(x,1); *pStr++ = EBYTE(x,0); } } IPP_UNREFERENCED_PARAMETER(cnvLen); return strLen; } else return 0; } } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu_lsr.c000066400000000000000000000034211470420105600235440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Unsigned BNU misc functionality // // Contents: // cpLSL_BNU() // */ #include "owncp.h" #include "pcpbnumisc.h" /*F* // Name: cpLSR_BNU // // Purpose: Logical shift right (including inplace). // // Returns: // new length // // Parameters: // pA BigNum A // pR result BigNum // nsA size of A // nBits size of shift in bits *F*/ IPP_OWN_DEFN (cpSize, cpLSR_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, cpSize nBits)) { cpSize nw = nBits/BNU_CHUNK_BITS; cpSize n; pA += nw; nsA -= nw; nBits %= BNU_CHUNK_BITS; if(nBits) { BNU_CHUNK_T hi; BNU_CHUNK_T lo = pA[0]; for(n=0; n<(nsA-1); n++) { hi = pA[n+1]; pR[n] = (lo>>nBits) | (hi<<(BNU_CHUNK_BITS-nBits)); lo = hi; } pR[nsA-1] = (lo>>nBits); } else { for(n=0; n= _IPP_H9) || (_IPP32E >= _IPP32E_L9)) #if 0 IPP_OWN_DEFN (cpSize, cpNLZ_BNU, (BNU_CHUNK_T x)) { cpSize nlz = BNU_CHUNK_BITS; if(x) { nlz = 0; #if (BNU_CHUNK_BITS == BNU_CHUNK_64BIT) if( 0==(x & 0xFFFFFFFF00000000) ) { nlz +=32; x<<=32; } if( 0==(x & 0xFFFF000000000000) ) { nlz +=16; x<<=16; } if( 0==(x & 0xFF00000000000000) ) { nlz += 8; x<<= 8; } if( 0==(x & 0xF000000000000000) ) { nlz += 4; x<<= 4; } if( 0==(x & 0xC000000000000000) ) { nlz += 2; x<<= 2; } if( 0==(x & 0x8000000000000000) ) { nlz++; } #else if( 0==(x & 0xFFFF0000) ) { nlz +=16; x<<=16; } if( 0==(x & 0xFF000000) ) { nlz += 8; x<<= 8; } if( 0==(x & 0xF0000000) ) { nlz += 4; x<<= 4; } if( 0==(x & 0xC0000000) ) { nlz += 2; x<<= 2; } if( 0==(x & 0x80000000) ) { nlz++; } #endif } return nlz; } #endif /* cte version */ IPP_OWN_DEFN (cpSize, cpNLZ_BNU, (BNU_CHUNK_T x)) { cpSize nlz = 0; BNU_CHUNK_T #if (BNU_CHUNK_BITS == BNU_CHUNK_64BIT) mask = cpIsZero_ct(x & 0xFFFFFFFF00000000); nlz += 32 & mask; x = ((x<<32) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xFFFF000000000000); nlz += 16 & mask; x = ((x<<16) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xFF00000000000000); nlz += 8 & mask; x = ((x << 8) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xF000000000000000); nlz += 4 & mask; x = ((x << 4) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xC000000000000000); nlz += 2 & mask; x = ((x << 2) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0x8000000000000000); nlz += 1 & mask; x = ((x << 1) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0x8000000000000000); nlz += 1 & mask; #else mask = cpIsZero_ct(x & 0xFFFF0000); nlz += 16 & mask; x = ((x << 16) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xFF000000); nlz += 8 & mask; x = ((x << 8) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xF0000000); nlz += 4 & mask; x = ((x << 4) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0xC0000000); nlz += 2 & mask; x = ((x << 2) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0x80000000); nlz += 1 & mask; x = ((x << 1) & mask) | (x & ~mask); mask = cpIsZero_ct(x & 0x80000000); nlz += 1 & mask; #endif return nlz; } #endif cryptography-primitives-1.0.0/sources/ippcp/pcpbnu_ntz.c000066400000000000000000000037221470420105600235630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Unsigned BNU misc functionality // // Contents: // cpNTZ_BNU() // */ #include "owncp.h" #include "pcpbnumisc.h" /*F* // Name: cpNTZ_BNU // // Purpose: Returns number of trailing zeros of the BNU. // // Returns: // number of trailing zeros of the BNU // // Parameters: // x BigNum x // *F*/ IPP_OWN_DEFN (cpSize, cpNTZ_BNU, (BNU_CHUNK_T x)) { cpSize ntz = BNU_CHUNK_BITS; if(x) { ntz = 0; #if (BNU_CHUNK_BITS==BNU_CHUNK_64BIT) if( 0==(x & 0x00000000FFFFFFFF) ) { ntz+=32; x>>=32; } if( 0==(x & 0x000000000000FFFF) ) { ntz+=16; x>>=16; } if( 0==(x & 0x00000000000000FF) ) { ntz+= 8; x>>= 8; } if( 0==(x & 0x000000000000000F) ) { ntz+= 4; x>>= 4; } if( 0==(x & 0x0000000000000003) ) { ntz+= 2; x>>= 2; } if( 0==(x & 0x0000000000000001) ) { ntz++; } #else if( 0==(x & 0x0000FFFF) ) { ntz+=16; x>>=16; } if( 0==(x & 0x000000FF) ) { ntz+= 8; x>>= 8; } if( 0==(x & 0x0000000F) ) { ntz+= 4; x>>= 4; } if( 0==(x & 0x00000003) ) { ntz+= 2; x>>= 2; } if( 0==(x & 0x00000001) ) { ntz++; } #endif } return ntz; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnu_setoctstr.c000066400000000000000000000043651470420105600250060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Unsigned BNU misc functionality // // Contents: // cpFromOctStr_BNU() // */ #include "owncp.h" #include "pcpbnumisc.h" /*F* // Name: cpFromOctStr_BNU // // Purpose: Convert Oct String into BNU representation. // // Returns: // size of BNU in BNU_CHUNK_T chunks // // Parameters: // pStr pointer to the source octet string // strLen octet string length // pA pointer to the target BN // *F*/ IPP_OWN_DEFN (cpSize, cpFromOctStr_BNU, (BNU_CHUNK_T* pA, const Ipp8u* pStr, cpSize strLen)) { int nsA =0; /* start from the end of string */ for(; strLen>=(int)sizeof(BNU_CHUNK_T); nsA++,strLen-=(int)(sizeof(BNU_CHUNK_T))) { /* pack sizeof(BNU_CHUNK_T) bytes into single BNU_CHUNK_T value*/ *pA++ = #if (BNU_CHUNK_BITS==BNU_CHUNK_64BIT) +( (BNU_CHUNK_T)pStr[strLen-8]<<(8*7) ) +( (BNU_CHUNK_T)pStr[strLen-7]<<(8*6) ) +( (BNU_CHUNK_T)pStr[strLen-6]<<(8*5) ) +( (BNU_CHUNK_T)pStr[strLen-5]<<(8*4) ) #endif +( (BNU_CHUNK_T)pStr[strLen-4]<<(8*3) ) +( (BNU_CHUNK_T)pStr[strLen-3]<<(8*2) ) +( (BNU_CHUNK_T)pStr[strLen-2]<<(8*1) ) + (BNU_CHUNK_T)pStr[strLen-1]; } /* convert the beginning of the string */ if(strLen) { BNU_CHUNK_T x = 0; for(x=0; strLen>0; strLen--) { BNU_CHUNK_T d = *pStr++; x = (x<<8) + d; } *pA++ = x; nsA++; } return nsA; } cryptography-primitives-1.0.0/sources/ippcp/pcpbnuarith.h000066400000000000000000000141631470420105600237260ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2012 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Unsigned internal arithmetic // // */ #if !defined(_CP_BNU_ARITH_H) #define _CP_BNU_ARITH_H #include "pcpbnuimpl.h" #include "pcpbnu32arith.h" #define cpAdd_BNU OWNAPI(cpAdd_BNU) IPP_OWN_DECL (BNU_CHUNK_T, cpAdd_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns)) #define cpSub_BNU OWNAPI(cpSub_BNU) IPP_OWN_DECL (BNU_CHUNK_T, cpSub_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, cpSize ns)) #define cpInc_BNU OWNAPI(cpInc_BNU) IPP_OWN_DECL (BNU_CHUNK_T, cpInc_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)) #define cpDec_BNU OWNAPI(cpDec_BNU) IPP_OWN_DECL (BNU_CHUNK_T, cpDec_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)) #define cpAddMulDgt_BNU OWNAPI(cpAddMulDgt_BNU) IPP_OWN_DECL (BNU_CHUNK_T, cpAddMulDgt_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize ns, BNU_CHUNK_T val)) #define cpMulAdc_BNU_school OWNAPI(cpMulAdc_BNU_school) IPP_OWN_DECL (BNU_CHUNK_T, cpMulAdc_BNU_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB)) #define cpMulAdx_BNU_school OWNAPI(cpMulAdx_BNU_school) IPP_OWN_DECL (BNU_CHUNK_T, cpMulAdx_BNU_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB)) /*F* // Name: cpMul_BNU_school // // Purpose: Multiply 2 BigNums. // // Returns: // extension of result of multiply 2 BigNums // // Parameters: // pA source BigNum A // nsA size of A // pB source BigNum B // nsB size of B // pR resultant BigNum // *F*/ __IPPCP_INLINE BNU_CHUNK_T cpMul_BNU_school(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB) { #if(_ADCOX_NI_ENABLING_==_FEATURE_ON_) return cpMulAdx_BNU_school(pR, pA,nsA, pB,nsB); #elif(_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_) return IsFeatureEnabled(ippCPUID_ADCOX)? cpMulAdx_BNU_school(pR, pA,nsA, pB,nsB) : cpMulAdc_BNU_school(pR, pA,nsA, pB,nsB); #else return cpMulAdc_BNU_school(pR, pA,nsA, pB,nsB); #endif } #define cpSqrAdc_BNU_school OWNAPI(cpSqrAdc_BNU_school) IPP_OWN_DECL (BNU_CHUNK_T, cpSqrAdc_BNU_school, (BNU_CHUNK_T * pR, const BNU_CHUNK_T * pA, cpSize nsA)) #define cpSqrAdx_BNU_school OWNAPI(cpSqrAdx_BNU_school) IPP_OWN_DECL (BNU_CHUNK_T, cpSqrAdx_BNU_school, (BNU_CHUNK_T * pR, const BNU_CHUNK_T * pA, cpSize nsA)) /*F* // Name: cpSqr_BNU_school // // Purpose: Square BigNum. // // Returns: // extension of result of square BigNum // // Parameters: // pA source BigNum // pR resultant BigNum // *F*/ __IPPCP_INLINE BNU_CHUNK_T cpSqr_BNU_school(BNU_CHUNK_T * pR, const BNU_CHUNK_T * pA, cpSize nsA) { #if(_ADCOX_NI_ENABLING_==_FEATURE_ON_) return cpSqrAdx_BNU_school(pR, pA,nsA); #elif(_ADCOX_NI_ENABLING_==_FEATURE_TICKTOCK_) return IsFeatureEnabled(ippCPUID_ADCOX)? cpSqrAdx_BNU_school(pR, pA,nsA) : cpSqrAdc_BNU_school(pR, pA,nsA); #else return cpSqrAdc_BNU_school(pR, pA,nsA); #endif } #define cpGcd_BNU OWNAPI(cpGcd_BNU) IPP_OWN_DECL (BNU_CHUNK_T, cpGcd_BNU, (BNU_CHUNK_T a, BNU_CHUNK_T b)) #define cpModInv_BNU OWNAPI(cpModInv_BNU) IPP_OWN_DECL (int, cpModInv_BNU, (BNU_CHUNK_T* pInv, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pM, cpSize nsM, BNU_CHUNK_T* bufInv, BNU_CHUNK_T* bufA, BNU_CHUNK_T* bufM)) /* // multiplication/squaring wrappers */ __IPPCP_INLINE BNU_CHUNK_T cpMul_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB, BNU_CHUNK_T* pBuffer) { IPP_UNREFERENCED_PARAMETER(pBuffer); return cpMul_BNU_school(pR, pA,nsA, pB,nsB); } __IPPCP_INLINE BNU_CHUNK_T cpSqr_BNU(BNU_CHUNK_T * pR, const BNU_CHUNK_T * pA, cpSize nsA, BNU_CHUNK_T* pBuffer) { IPP_UNREFERENCED_PARAMETER(pBuffer); return cpSqr_BNU_school(pR, pA,nsA); } /*F* // Name: cpDiv_BNU // // Purpose: division/reduction BigNums. // // Returns: // size of result // // Parameters: // pA source BigNum // pB source BigNum // pQ quotient BigNum // pnsQ pointer to max size of Q // nsA size of A // nsB size of B // *F*/ __IPPCP_INLINE cpSize cpDiv_BNU(BNU_CHUNK_T* pQ, cpSize* pnsQ, BNU_CHUNK_T* pA, cpSize nsA, BNU_CHUNK_T* pB, cpSize nsB) { int nsR = cpDiv_BNU32((Ipp32u*)pQ, pnsQ, (Ipp32u*)pA, nsA*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)), (Ipp32u*)pB, nsB*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))); #if (BNU_CHUNK_BITS == BNU_CHUNK_64BIT) if(nsR&1) ((Ipp32u*)pA)[nsR] = 0; nsR = INTERNAL_BNU_LENGTH(nsR); if(pQ) { if(*pnsQ&1) ((Ipp32u*)pQ)[*pnsQ] = 0; *pnsQ = INTERNAL_BNU_LENGTH(*pnsQ); } #endif return nsR; } /*F* // Name: cpMod_BNU // // Purpose: reduction BigNums. // // Returns: // cpDiv_BNU(NULL,NULL, pX,nsX, pModulus, nsM) // // Parameters: // pX source BigNum // pModulus source BigNum // nsX size of X // nsM size of Modulus // *F*/ __IPPCP_INLINE cpSize cpMod_BNU(BNU_CHUNK_T* pX, cpSize nsX, BNU_CHUNK_T* pModulus, cpSize nsM) { return cpDiv_BNU(NULL,NULL, pX,nsX, pModulus, nsM); } #endif /* _CP_BNU_ARITH_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpbnuimpl.h000066400000000000000000000077061470420105600235650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2012 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // BNU data type definition // // // */ #if !defined(_CP_BNU_IMPL_H) #define _CP_BNU_IMPL_H #define BNU_CHUNK_64BIT (64) #define BNU_CHUNK_32BIT (32) /* // define BNU chunk data type */ #if ((_IPP_ARCH == _IPP_ARCH_EM64T) || (_IPP_ARCH == _IPP_ARCH_LP64) || (_IPP_ARCH == _IPP_ARCH_LRB) || (_IPP_ARCH == _IPP_ARCH_LRB2)) typedef Ipp64u BNU_CHUNK_T; typedef Ipp64s BNS_CHUNK_T; #define BNU_CHUNK_LOG2 (6) #define BNU_CHUNK_BITS BNU_CHUNK_64BIT #else typedef Ipp32u BNU_CHUNK_T; typedef Ipp32s BNS_CHUNK_T; #define BNU_CHUNK_LOG2 (5) #define BNU_CHUNK_BITS BNU_CHUNK_32BIT #endif #define BNU_CHUNK_MASK (~(BNU_CHUNK_T)(0)) #if (BNU_CHUNK_BITS != BNU_CHUNK_64BIT && BNU_CHUNK_BITS != BNU_CHUNK_32BIT) #error BNU_CHUNK_BITS should be either 64 or 32 bit! #endif #ifdef _MSC_VER // #pragma warning( disable : 4127 4711 4206) # pragma warning( disable : 4127) #endif /* user's API BNU chunk data type */ typedef Ipp32u API_BNU_CHUNK_T; /* convert API_BNU_CHUNK_T (usual Ipp32u) length into the BNU_CHUNK_T length */ #define INTERNAL_BNU_LENGTH(apiLen) \ ((apiLen) + (Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(API_BNU_CHUNK_T)) -1)/((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(API_BNU_CHUNK_T))) /* Low and High parts of BNU_CHUNK_T value */ #define BNU_CHUNK_2H ((BNU_CHUNK_T)1 << (BNU_CHUNK_BITS/2)) #define LO_CHUNK(c) ((BNU_CHUNK_T)(c) & (BNU_CHUNK_2H - 1)) #define HI_CHUNK(c) ((BNU_CHUNK_T)(c) >> (BNU_CHUNK_BITS/2)) /* (carry,R) = A+B */ #define ADD_AB(CARRY,R, A,B) \ do { \ BNU_CHUNK_T __s = (A) + (B); \ (CARRY) = __s < (A); \ (R) = __s; \ } while(0) /* (carry,R) = A+B+C */ #define ADD_ABC(CARRY,R, A,B,C) \ do { \ BNU_CHUNK_T __s = (A) + (B); \ BNU_CHUNK_T __t1= __s < (A); \ BNU_CHUNK_T __r = __s + (C); \ BNU_CHUNK_T __t2 = __r < __s; \ (CARRY) = __t1 + __t2; \ (R) = __r; \ } while(0) /* (borrow,R) = A-B */ #define SUB_AB(BORROW,R, A,B) \ do { \ (BORROW) = (A)<(B); \ (R) = (A)-(B); \ } while(0) /* (borrow,R) = A-B-C */ #define SUB_ABC(BORROW,R, A,B,C) \ do { \ BNU_CHUNK_T __s = (A) -( B); \ BNU_CHUNK_T __t1= __s > (A); \ BNU_CHUNK_T __r = __s - (C); \ BNU_CHUNK_T __t2 = __r > __s; \ (BORROW) = __t1 + __t2; \ (R) = __r; \ } while(0) /* (RH,RL) = A*B */ #define MUL_AB(RH, RL, A, B) \ do { \ BNU_CHUNK_T __aL = LO_CHUNK((A)); \ BNU_CHUNK_T __aH = HI_CHUNK((A)); \ BNU_CHUNK_T __bL = LO_CHUNK((B)); \ BNU_CHUNK_T __bH = HI_CHUNK((B)); \ \ BNU_CHUNK_T __x0 = (BNU_CHUNK_T) __aL * __bL; \ BNU_CHUNK_T __x1 = (BNU_CHUNK_T) __aL * __bH; \ BNU_CHUNK_T __x2 = (BNU_CHUNK_T) __aH * __bL; \ BNU_CHUNK_T __x3 = (BNU_CHUNK_T) __aH * __bH; \ \ __x1 += HI_CHUNK(__x0); \ __x1 += __x2; \ if(__x1 < __x2) \ __x3 += BNU_CHUNK_2H; \ \ (RH) = __x3 + HI_CHUNK(__x1); \ (RL) = (__x1 << BNU_CHUNK_BITS/2) + LO_CHUNK(__x0); \ } while (0) #endif /* _CP_BNU_IMPL_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpbnumisc.h000066400000000000000000000154461470420105600235570ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Internal Miscellaneous BNU Definitions & Function Prototypes // // */ #if !defined(_PCP_BNUMISC_H) #define _PCP_BNUMISC_H #include "pcpbnuimpl.h" #include "pcpmask_ct.h" /* bit operations */ #define BITSIZE_BNU(p,ns) ((ns)*BNU_CHUNK_BITS-cpNLZ_BNU((p)[(ns)-1])) #define BIT_BNU(bnu, ns,nbit) ((((nbit)>>BNU_CHUNK_LOG2) < (ns))? ((((bnu))[(nbit)>>BNU_CHUNK_LOG2] >>((nbit)&(BNU_CHUNK_BITS))) &1) : 0) #define TST_BIT(bnu, nbit) (((Ipp8u*)(bnu))[(nbit)/8] & ((1<<((nbit)%8)) &0xFF)) #define SET_BIT(bnu, nbit) (((Ipp8u*)(bnu))[(nbit)/8] |= ((1<<((nbit)%8)) &0xFF)) #define CLR_BIT(bnu, nbit) (((Ipp8u*)(bnu))[(nbit)/8] &=~((1<<((nbit)%8)) &0xFF)) /* convert bitsize nbits into the number of BNU_CHUNK_T */ #define BITS_BNU_CHUNK(nbits) (((nbits)+BNU_CHUNK_BITS-1)/BNU_CHUNK_BITS) /* mask for top BNU_CHUNK_T */ #define MASK_BNU_CHUNK(nbits) ((BNU_CHUNK_T)(-1) >>((BNU_CHUNK_BITS- ((nbits)&(BNU_CHUNK_BITS-1))) &(BNU_CHUNK_BITS-1))) /* copy BNU content */ #define COPY_BNU(dst, src, len) \ { \ cpSize __idx; \ for(__idx=0; __idx<(len); __idx++) (dst)[__idx] = (src)[__idx]; \ } /* expand by zeros */ #define ZEXPAND_BNU(srcdst,srcLen, dstLen) \ { \ cpSize __idx; \ for(__idx=(srcLen); __idx<(dstLen); __idx++) (srcdst)[__idx] = 0; \ } /* copy and expand by zeros */ #define ZEXPAND_COPY_BNU(dst,dstLen, src,srcLen) \ { \ cpSize __idx; \ for(__idx=0; __idx<(srcLen); __idx++) (dst)[__idx] = (src)[__idx]; \ for(; __idx<(dstLen); __idx++) (dst)[__idx] = 0; \ } /* copy and set */ __IPPCP_INLINE void cpCpy_BNU(BNU_CHUNK_T* pDst, const BNU_CHUNK_T* pSrc, cpSize ns) { COPY_BNU(pDst, pSrc, ns); } __IPPCP_INLINE void cpSet_BNU(BNU_CHUNK_T* pDst, cpSize ns, BNU_CHUNK_T val) { ZEXPAND_BNU(pDst, 0, ns); pDst[0] = val; } /* fix up */ /* Name: cpFix_BNU // // Purpose: fix up BigNums. // // Returns: // fixed nsA // // Parameters: // pA BigNum ctx // nsA Size of pA // */ __IPPCP_INLINE int cpFix_BNU(const BNU_CHUNK_T* pA, int nsA) { BNU_CHUNK_T zscan = (BNU_CHUNK_T)(-1); int outLen = nsA; for(; nsA>0; nsA--) { zscan &= cpIsZero_ct(pA[nsA-1]); outLen -= 1 & zscan; } return (int)((1 & zscan) | ((BNU_CHUNK_T)outLen & ~zscan)); // change to scanz } #define FIX_BNU(src,srcLen) ((srcLen) = cpFix_BNU((src), (srcLen))) /* Name: cpCmp_BNU // // Purpose: Compare two BigNums. // // Returns: // negative, if A < B // 0, if A = B // positive, if A > B // // Parameters: // pA BigNum ctx // nsA Size of pA // pB BigNum ctx // nsB Size of pB // */ #if 0 __IPPCP_INLINE int cpCmp_BNU(const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB) { if(nsA!=nsB) return nsA>nsB? 1 : -1; else { BNU_CHUNK_T idx = 0; for(; nsA>0; nsA--) idx |= ~cpIsEqu_ct(pA[nsA-1], pB[nsA-1]) & cpIsZero_ct(idx) & (BNU_CHUNK_T)(nsA-1); return pA[idx] < pB[idx] ? -1 : (pA[idx] > pB[idx] ? 1 : 0); } } #endif __IPPCP_INLINE int cpCmp_BNU0(const BNU_CHUNK_T* a, const BNU_CHUNK_T* b, int len) { const Ipp32u* a32 = (const Ipp32u*)a; const Ipp32u* b32 = (const Ipp32u*)b; len *= (sizeof(BNU_CHUNK_T))/sizeof(Ipp32u); // borrow, difference |= (a[]-b[]) BNU_CHUNK_T borrow = 0; BNU_CHUNK_T difference = 0; for(int n=0; n>63); } int resb = (int)( cpIsEqu_ct(borrow, 1) ); int resd = (int)(~cpIsZero_ct(difference) ) &1; return (int)(resb|resd); } __IPPCP_INLINE int cpCmp_BNU(const BNU_CHUNK_T* a, int aLen, const BNU_CHUNK_T* b, int bLen) { BNU_CHUNK_T aLen_eq_bLen = cpIsZero_ct((BNU_CHUNK_T)(aLen-bLen)); // FFFF/0000 if (aLen=bLen) / (aLen!=bLen) BNU_CHUNK_T aLen_gt_bLen = cpIsMsb_ct((BNU_CHUNK_T)(bLen-aLen)) & 1; // 1/0 if (aLen>bLen) / (aLenbLen) int len = (int)(((Ipp32u)aLen & aLen_lt_bLen) | ((Ipp32u)bLen & ~aLen_lt_bLen)); int cmp_res = cpCmp_BNU0(a, b, len); return (int)( aLen_gt_bLen | (aLen_eq_bLen & (Ipp32u)cmp_res) | aLen_lt_bLen ); } /* Name: cpEqu_BNU_CHUNK // // Purpose: Compare two BNU_CHUNKs. // // Returns: // positive, if A = b // 0 , if A != b // // Parameters: // pA BigNum ctx // nsA Size of pA // b BNU_CHUNK_T to compare // */ __IPPCP_INLINE int cpEqu_BNU_CHUNK(const BNU_CHUNK_T* pA, cpSize nsA, BNU_CHUNK_T b) { BNU_CHUNK_T res = pA[0] ^ b; int n; for(n=1; n0, if A > 0 // <0, looks like impossible (or error) case */ __IPPCP_INLINE int cpTst_BNU(const BNU_CHUNK_T* pA, int nsA) { for(; (nsA>0) && (0==pA[nsA-1]); nsA--) ; return nsA; } /* number of leading/trailing zeros */ #if !((_IPP >= _IPP_H9) || (_IPP32E >= _IPP32E_L9)) #define cpNLZ_BNU OWNAPI(cpNLZ_BNU) IPP_OWN_DECL (cpSize, cpNLZ_BNU, (BNU_CHUNK_T x)) #else __IPPCP_INLINE cpSize cpNLZ_BNU(BNU_CHUNK_T x) { #if (BNU_CHUNK_BITS == BNU_CHUNK_64BIT) return (cpSize)_lzcnt_u64(x); #else return (cpSize)_lzcnt_u32(x); #endif } #endif #define cpNTZ_BNU OWNAPI(cpNTZ_BNU) IPP_OWN_DECL (cpSize, cpNTZ_BNU, (BNU_CHUNK_T x)) /* logical shift left/right */ #define cpLSR_BNU OWNAPI(cpLSR_BNU) IPP_OWN_DECL (int, cpLSR_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, cpSize nBits)) /* most significant BNU bit */ #define cpMSBit_BNU OWNAPI(cpMSBit_BNU) IPP_OWN_DECL (int, cpMSBit_BNU, (const BNU_CHUNK_T* pA, cpSize nsA)) /* BNU <-> hex-string conversion */ #define cpToOctStr_BNU OWNAPI(cpToOctStr_BNU) IPP_OWN_DECL (int, cpToOctStr_BNU, (Ipp8u* pStr, cpSize strLen, const BNU_CHUNK_T* pA, cpSize nsA)) #define cpFromOctStr_BNU OWNAPI(cpFromOctStr_BNU) IPP_OWN_DECL (int, cpFromOctStr_BNU, (BNU_CHUNK_T* pA, const Ipp8u* pStr, cpSize strLen)) #endif /* _PCP_BNUMISC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpcmac.h000066400000000000000000000046011470420105600230110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2007 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Ciper-based Message Authentication Code (CMAC) see SP800-38B // Internal Definitions and Internal Functions Prototypes // */ #if !defined(_PCP_CMAC_H) #define _PCP_CMAC_H #include "pcprij.h" /* // Rijndael128 based CMAC context */ struct _cpAES_CMAC { Ipp32u idCtx; /* CMAC identifier */ int index; /* internal buffer entry (free) */ Ipp8u k1[MBS_RIJ128]; /* k1 subkey */ Ipp8u k2[MBS_RIJ128]; /* k2 subkey */ Ipp8u mBuffer[MBS_RIJ128];/* buffer */ Ipp8u mMAC[MBS_RIJ128]; /* intermediate digest */ IppsRijndael128Spec mCipherCtx; }; /* alignment */ //#define CMACRIJ_ALIGNMENT (RIJ_ALIGNMENT) #define AESCMAC_ALIGNMENT (RIJ_ALIGNMENT) /* // Useful macros */ #define CMAC_SET_ID(stt) ((stt)->idCtx = (Ipp32u)idCtxCMAC ^ (Ipp32u)IPP_UINT_PTR(stt)) #define CMAC_INDX(stt) ((stt)->index) #define CMAC_K1(stt) ((stt)->k1) #define CMAC_K2(stt) ((stt)->k2) #define CMAC_BUFF(stt) ((stt)->mBuffer) #define CMAC_MAC(stt) ((stt)->mMAC) #define CMAC_CIPHER(stt) ((stt)->mCipherCtx) #if (_AES_PROB_NOISE == _FEATURE_ON_) #define AESCMAC_NOISE_PARAMS(ctx) (CMAC_CIPHER(ctx).noiseParams) #endif /* valid context ID */ #define VALID_AESCMAC_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxCMAC) #define cpAESCMAC_Update_AES_NI OWNAPI(cpAESCMAC_Update_AES_NI) IPP_OWN_DECL (void, cpAESCMAC_Update_AES_NI, (Ipp8u* pMac, const Ipp8u* inpBlk, int nBlks, int nr, const Ipp8u* pKeys)) #endif /* _PCP_CMAC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpdes.h000066400000000000000000000057771470420105600227000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal DES based Encrypt/Decrypt Function Prototypes // // */ #if !defined(_PCP_DES_H) #define _PCP_DES_H /* // really DES round key saved in terms of pear of 24-bit half mentioned in FIPS 46-3 */ typedef Ipp64u RoundKeyDES; typedef Ipp32u HalfRoundKeyDES; /* // DES context */ struct _cpDES { Ipp32u idCtx; /* DES spec identifier */ RoundKeyDES enc_keys[16]; /* array of keys for encryprion */ RoundKeyDES dec_keys[16]; /* array of keys for decryprion */ }; /* alignment */ #define DES_ALIGNMENT ((int)(sizeof(Ipp64u))) #define MBS_DES (8) /* data block (bytes) */ /* // Useful macros */ #define DES_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxDES ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define DES_RESET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxDES) #define DES_EKEYS(ctx) ((ctx)->enc_keys) #define DES_DKEYS(ctx) ((ctx)->dec_keys) #define VALID_DES_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxDES) /* // Internal Tables */ #define MITIGATED (4) #define IMPLEMENTATION MITIGATED #if (IMPLEMENTATION == MITIGATED) extern const __ALIGN64 Ipp32u DESspbox[16*16]; #endif /* // internal functions */ #define SetKey_DES OWNAPI(SetKey_DES) IPP_OWN_DECL (void, SetKey_DES, (const Ipp8u* pKey, IppsDESSpec* pCtx)) #define Cipher_DES OWNAPI(Cipher_DES) IPP_OWN_DECL (Ipp64u, Cipher_DES, (Ipp64u inpBlk, const RoundKeyDES* pRKey, const Ipp32u spbox[])) #define ENCRYPT_DES(blk, pCtx) Cipher_DES((blk), DES_EKEYS((pCtx)), DESspbox) #define DECRYPT_DES(blk, pCtx) Cipher_DES((blk), DES_DKEYS((pCtx)), DESspbox) /* TDES prototypes */ #define ECB_TDES OWNAPI(ECB_TDES) IPP_OWN_DECL (void, ECB_TDES, (const Ipp64u* pSrc, Ipp64u* pDst, int nBlocks, const RoundKeyDES* pRKey[3], const Ipp32u spbox[])) #define EncryptCBC_TDES OWNAPI(EncryptCBC_TDES) IPP_OWN_DECL (void, EncryptCBC_TDES, (const Ipp64u* pSrc, Ipp64u* pDst, int nBlocks, const RoundKeyDES* pRKey[3], Ipp64u iv, const Ipp32u spbox[])) #define DecryptCBC_TDES OWNAPI(DecryptCBC_TDES) IPP_OWN_DECL (void, DecryptCBC_TDES, (const Ipp64u* pSrc, Ipp64u* pDst, int nBlocks, const RoundKeyDES* pRKey[3], Ipp64u iv, const Ipp32u spbox[])) #endif /* _PCP_DES_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpdescipherm.c000066400000000000000000000132241470420105600242250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DES Cipher function (MemJam mitigation included) // // Contents: // initial permutation: ip() // final permutation: fp() // round function: rndm() // DES block encrypt/decrypt: Chipher_DES() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdes.h" #include "pcpmask_ct.h" /* // Following implementation of ip(), fp() and rndm() // assumes input and output of DES as sequence of bytes. */ #define ip(x,y) { \ Ipp32u t; \ (x) = ROR32((x), 4); \ (t) = ((x)^(y)) & 0x0f0f0f0fL; \ (y)^= (t); \ (x) = ROR32((x)^(t), 12); \ (t) = ((y)^(x)) & 0xffff0000L; \ (y)^= (t); \ (x) = ROR32((x)^(t), 18); \ (t) = ((x)^(y)) & 0x33333333L; \ (y)^= (t); \ (x) = ROR32((x)^(t), 22); \ (t) = ((y)^(x)) & 0xff00ff00L; \ (y)^= (t); \ (x) = ROR32((x)^(t), 9); \ (t) = ((x)^(y)) & 0x55555555L; \ (x) = ROL32((x)^(t), 2); \ (y) = ROL32((y)^(t), 1); \ } #define fp(x,y) { \ Ipp32u t; \ (y) = ROR32((y), 1); \ (x) = ROR32((x), 2); \ (t) = ((x)^(y)) & 0x55555555L; \ (y)^= (t); \ (x) = ROL32((x)^(t), 9); \ (t) = ((y)^(x)) & 0xff00ff00L; \ (y)^= (t); \ (x) = ROL32((x)^(t), 22); \ (t) = ((x)^(y)) & 0x33333333L; \ (y)^= (t); \ (x) = ROL32((x)^(t), 18); \ (t) = ((y)^(x)) & 0xffff0000L; \ (y)^= (t); \ (x) = ROL32((x)^(t), 12); \ (t) = ((x)^(y)) & 0x0f0f0f0fL; \ (y)^= (t); \ (x) = ROL32((x)^(t), 4); \ } static BNU_CHUNK_T getSbox(const BNU_CHUNK_T sbox[], int idx) { unsigned int i; BNU_CHUNK_T res = 0; for(i=0; i<(64/sizeof(BNU_CHUNK_T)); i++) { BNU_CHUNK_T mask = cpIsEqu_ct(i, (BNU_CHUNK_T)idx); res |= sbox[i] & mask; } return res; } static Ipp8u getSbox8u(const Ipp8u sbox[], int idx) { int shift = idx % (Ipp32s)((sizeof(BNU_CHUNK_T))/sizeof(Ipp8u)); idx /= ((sizeof(BNU_CHUNK_T))/sizeof(Ipp8u)); return (Ipp8u)( getSbox((BNU_CHUNK_T*)sbox, idx) >>(shift*8) ); } static Ipp32u getSbox32u(const Ipp8u sbox[], int idx) { int shift = idx % (Ipp32s)((sizeof(BNU_CHUNK_T))/sizeof(Ipp32u)); idx /= ((sizeof(BNU_CHUNK_T))/sizeof(Ipp32u)); return (Ipp32u)( getSbox((BNU_CHUNK_T*)sbox, idx)>>shift*32 ); } static Ipp32u rndm(Ipp32u x0, Ipp32u x1, Ipp32u* key, const Ipp8u* sbox) { Ipp32u tt = key[0] ^ (x1 &0x3F3F3F3F); x0 ^= getSbox32u(sbox+512+64*0, getSbox8u(sbox+64*0, (Ipp8u)tt)); tt >>= 8; x0 ^= getSbox32u(sbox+512+64*2, getSbox8u(sbox+64*2, (Ipp8u)tt)); tt >>= 8; x0 ^= getSbox32u(sbox+512+64*4, getSbox8u(sbox+64*4, (Ipp8u)tt)); tt >>= 8; x0 ^= getSbox32u(sbox+512+64*6, getSbox8u(sbox+64*6, (Ipp8u)tt)); tt = (key)[1] ^ (ROR32((x1 &0xF3F3F3F3),4)); x0 ^= getSbox32u(sbox+512+64*1, getSbox8u(sbox+64*1, (Ipp8u)tt)); tt >>= 8; x0 ^= getSbox32u(sbox+512+64*3, getSbox8u(sbox+64*3, (Ipp8u)tt)); tt >>= 8; x0 ^= getSbox32u(sbox+512+64*5, getSbox8u(sbox+64*5, (Ipp8u)tt)); tt >>= 8; x0 ^= getSbox32u(sbox+512+64*7, getSbox8u(sbox+64*7, (Ipp8u)tt)); return x0; } IPP_OWN_DEFN (Ipp64u, Cipher_DES, (Ipp64u inpBlk, const RoundKeyDES* pRKey, const Ipp32u sbox[])) { const Ipp8u* sbox8 = (const Ipp8u*)sbox; #if (IPP_ENDIAN == IPP_BIG_ENDIAN) Ipp32u q0 = IPP_LODWORD(inpBlk); Ipp32u q1 = IPP_HIDWORD(inpBlk); q0 = ENDIANNESS(q0); q1 = ENDIANNESS(q1); #else Ipp32u q0 = IPP_HIDWORD(inpBlk); Ipp32u q1 = IPP_LODWORD(inpBlk); #endif /* apply inverse permutation IP */ ip(q0,q1); /* 16 magic encrypt iterations */ q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey)), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+1 )), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+2 )), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+3 )), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+4 )), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+5 )), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+6 )), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+7 )), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+8 )), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+9 )), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+10)), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+11)), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+12)), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+13)), sbox8); q0 = rndm(q0,q1, ((HalfRoundKeyDES*)(pRKey+14)), sbox8); q1 = rndm(q1,q0, ((HalfRoundKeyDES*)(pRKey+15)), sbox8); /* apply forward permutation FP */ fp(q1,q0); #if (IPP_ENDIAN == IPP_BIG_ENDIAN) q0 = ENDIANNESS(q0); q1 = ENDIANNESS(q1); return IPP_MAKEDWORD(q1,q0); #else return IPP_MAKEDWORD(q0,q1); #endif } cryptography-primitives-1.0.0/sources/ippcp/pcpdesgetsize.c000066400000000000000000000026001470420105600242440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Set Round Keys for DES/TDES // // Contents: // ippsDESGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdes.h" #include "pcptool.h" /*F* // Name: ippsDESGetSize // // Purpose: Returns size of DES spec (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer DES spec size // *F*/ IPPFUN(IppStatus, ippsDESGetSize, (int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsDESSpec); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdesinitca.c000066400000000000000000000030541470420105600240450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Set Round Keys for DES/TDES // // Contents: // ippsDESInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdes.h" #include "pcptool.h" /*F* // Name: ippsDESInit // // Purpose: Init DES spec for future usage. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pKey == NULL // ippStsNoErr no errors // // Parameters: // pKey pointer to security key // pCtx pointer DES spec // *F*/ IPPFUN(IppStatus, ippsDESInit,(const Ipp8u* pKey, IppsDESSpec* pCtx)) { /* test key's and spec's pointers */ IPP_BAD_PTR2_RET(pKey, pCtx); /* init DES spec */ DES_SET_ID(pCtx); /* set round keys */ SetKey_DES(pKey, pCtx); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdesinitpxca.c000066400000000000000000000106261470420105600244200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Set Round Keys for DES/TDES // // Contents: // SetKey_DES() // ippcSetKey_DES() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdes.h" /* // bit 0 is left-most in byte (reference FIPS 46-3) */ static int bytebit[] = { 0x80,0x40,0x20,0x10,0x8,0x4,0x2,0x1 }; /* // Key schedule-related tables (reference FIPS 46-3) */ /* PC-1 permuted table (for the user key) */ static Ipp8u pc1[] = { 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 }; /* number left rotations of PC-1 key */ static int rotations[] = { 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; /* PC-2 table (for round key construction) */ static Ipp8u pc2[] = { 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 }; #define SWAP8U(a,b) { Ipp8u x=(a); (a)=(b); (b)=x; } /* // Generate key schedule for encryption and decryption */ IPP_OWN_DEFN (void, SetKey_DES, (const Ipp8u* pKey, IppsDESSpec* pCtx)) { RoundKeyDES* pEncRoundKey = DES_EKEYS(pCtx); RoundKeyDES* pDecRoundKey = DES_DKEYS(pCtx); __ALIGN64 Ipp8u pc1key[56]; /* PC-1 permuted user key bits */ __ALIGN64 Ipp8u rndkey[56]; /* rounded key bits */ int nkey; int i; /* // apply permutation PC-1 */ for(i=0; i<56; i++) { /* location into the user key (bit number) */ int nBit = pc1[i]-1; /* location into the user key (byte and offset in the byte) */ int nByte = nBit>>3; int offset = nBit & 0x07; /* test bit in the user key and set into the permuted */ pc1key[i] = (Ipp8u)( (pKey[nByte] & bytebit[offset] ) >>(7-offset)); } /* // key schedule for encryption */ for(nkey=0; nkey<16; nkey++) { Ipp64u tmp = 0; Ipp8u* rkeyNibble = (Ipp8u*)(&tmp); int pc1keyBit, pc1keyBit_m28; Ipp32u mask; /* rotate right pc1key */ for (i=0; i<28; i++) { pc1keyBit = i+rotations[nkey]; pc1keyBit_m28 = pc1keyBit-28; mask = (Ipp32u)(pc1keyBit_m28>>(BITSIZE(Ipp32u)-1)); pc1keyBit = (Ipp32s)((Ipp32u)pc1keyBit & mask) | (Ipp32s)((Ipp32u)pc1keyBit_m28 &~mask); rndkey[i] = pc1key[pc1keyBit]; } for (; i<56; i++) { pc1keyBit = i+rotations[nkey]; pc1keyBit_m28 = pc1keyBit-28; mask = (Ipp32u)((pc1keyBit-56)>>(BITSIZE(Ipp32u)-1)); pc1keyBit = (Ipp32s)((Ipp32u)pc1keyBit & mask) | (Ipp32s)((Ipp32u)pc1keyBit_m28 &~mask); rndkey[i] = pc1key[pc1keyBit]; } /* // construct eight 6-bit nibbles of round key // applying PC-2 permutation to rndkey[] */ for(i=0; i<48; i++) { int offset = i%6; rkeyNibble[i/6] |= (rndkey[pc2[i]-1]<idCtx = (Ipp32u)idCtxDLP ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define DLP_RESET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxDLP) #define DLP_FLAG(ctx) ((ctx)->flag) #define DLP_BITSIZEP(ctx) ((ctx)->bitSizeP) #define DLP_BITSIZER(ctx) ((ctx)->bitSizeR) #define DLP_EXPMETHOD(ctx) ((ctx)->method) #define DLP_MONTP0(ctx) ((ctx)->pMontP0) #define DLP_MONTP1(ctx) ((ctx)->pMontP1) #define DLP_MONTR(ctx) ((ctx)->pMontR) #define DLP_P(ctx) (MOD_MODULUS(DLP_MONTP0((ctx)))) #define DLP_R(ctx) (MOD_MODULUS(DLP_MONTR((ctx)))) #define DLP_GENC(ctx) ((ctx)->pGenc) #define DLP_X(ctx) ((ctx)->pX) #define DLP_YENC(ctx) ((ctx)->pYenc) #define DLP_PRIMEGEN(ctx) ((ctx)->pPrimeGen) #define DLP_METBL(ctx) ((ctx)->pMeTable) #define DLP_BNCTX(ctx) ((ctx)->pBnList) #if defined(_USE_WINDOW_EXP_) #define DLP_BNUCTX0(ctx) ((ctx)->pBnuList0) #define DLP_BNUCTX1(ctx) ((ctx)->pBnuList1) #endif #define DLP_VALID_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxDLP) #define DLP_COMPLETE(ctx) (DLP_FLAG((ctx))==(IppDLPkeyP|IppDLPkeyR|IppDLPkeyG)) /* alignment */ #define DLP_ALIGNMENT ((int)(sizeof(void*))) /* pool size for gsModEngine */ #define DLP_MONT_POOL_LENGTH (6) #define cpPackDLPCtx OWNAPI(cpPackDLPCtx) IPP_OWN_DECL (void, cpPackDLPCtx, (const IppsDLPState* pDLP, Ipp8u* pBuffer)) #define cpUnpackDLPCtx OWNAPI(cpUnpackDLPCtx) IPP_OWN_DECL (void, cpUnpackDLPCtx, (const Ipp8u* pBuffer, IppsDLPState* pDLP)) #endif /* _PCP_DLP_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpdlp_packctx.c000066400000000000000000000052551470420105600244030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field (initialization) // // Contents: // cpPackDLPCtx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" IPP_OWN_DEFN (void, cpPackDLPCtx, (const IppsDLPState* pDLP, Ipp8u* pBuffer)) { IppsDLPState* pB = (IppsDLPState*)(pBuffer); CopyBlock(pDLP, pB, sizeof(IppsDLPState)); DLP_MONTP0(pB) = (gsModEngine*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_MONTP0(pDLP))-IPP_UINT_PTR(pDLP)); DLP_MONTP1(pB) = NULL; DLP_MONTR(pB) = (gsModEngine*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_MONTR(pDLP)) -IPP_UINT_PTR(pDLP)); DLP_GENC(pB) = (IppsBigNumState*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_GENC(pDLP)) -IPP_UINT_PTR(pDLP)); DLP_X(pB) = (IppsBigNumState*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_X(pDLP)) -IPP_UINT_PTR(pDLP)); DLP_YENC(pB) = (IppsBigNumState*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_YENC(pDLP)) -IPP_UINT_PTR(pDLP)); DLP_PRIMEGEN(pB)= (IppsPrimeState*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_PRIMEGEN(pDLP))-IPP_UINT_PTR(pDLP)); DLP_METBL(pB) = (BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_METBL(pDLP)) -IPP_UINT_PTR(pDLP)); DLP_BNCTX(pB) = (BigNumNode*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_BNCTX(pDLP)) -IPP_UINT_PTR(pDLP)); #if defined(_USE_WINDOW_EXP_) DLP_BNUCTX0(pB) = (WINDOW==DLP_EXPMETHOD(pDLP))?(BNU_CHUNK_T*)((Ipp8u*)NULL + IPP_UINT_PTR(DLP_BNUCTX0(pDLP))-IPP_UINT_PTR(pDLP)) : NULL; DLP_BNUCTX1(pB) = NULL; #endif gsPackModEngineCtx(DLP_MONTP0(pDLP), (Ipp8u*)pB+IPP_UINT_PTR(DLP_MONTP0(pB))); gsPackModEngineCtx(DLP_MONTR(pDLP), (Ipp8u*)pB+IPP_UINT_PTR(DLP_MONTR(pB))); cpPackBigNumCtx(DLP_GENC(pDLP), (Ipp8u*)pB+IPP_UINT_PTR(DLP_GENC(pB))); cpPackBigNumCtx(DLP_X(pDLP), (Ipp8u*)pB+IPP_UINT_PTR(DLP_X(pB))); cpPackBigNumCtx(DLP_YENC(pDLP), (Ipp8u*)pB+IPP_UINT_PTR(DLP_YENC(pB))); cpPackPrimeCtx(DLP_PRIMEGEN(pDLP), (Ipp8u*)pB+IPP_UINT_PTR(DLP_PRIMEGEN(pB))); } cryptography-primitives-1.0.0/sources/ippcp/pcpdlp_unpackctx.c000066400000000000000000000050741470420105600247450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field (initialization) // // Contents: // cpUnpackDLPCtx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" IPP_OWN_DEFN (void, cpUnpackDLPCtx, (const Ipp8u* pBuffer, IppsDLPState* pDLP)) { IppsDLPState* pB = (IppsDLPState*)(pBuffer); CopyBlock(pB, pDLP, sizeof(IppsDLPState)); DLP_MONTP0(pDLP) = (gsModEngine*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_MONTP0(pB))); DLP_MONTP1(pDLP) = NULL; DLP_MONTR(pDLP) = (gsModEngine*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_MONTR(pB))); DLP_GENC(pDLP) = (IppsBigNumState*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_GENC(pB))); DLP_X(pDLP) = (IppsBigNumState*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_X(pB))); DLP_YENC(pDLP) = (IppsBigNumState*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_YENC(pB))); DLP_PRIMEGEN(pDLP)= (IppsPrimeState*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_PRIMEGEN(pB))); DLP_METBL(pDLP) = (BNU_CHUNK_T*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_METBL(pB))); DLP_BNCTX(pDLP) = (BigNumNode*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_BNCTX(pB))); #if defined(_USE_WINDOW_EXP_) DLP_BNUCTX0(pDLP) = (WINDOW==DLP_EXPMETHOD(pDLP))?(BNU_CHUNK_T*)((Ipp8u*)pDLP+ IPP_UINT_PTR(DLP_BNUCTX0(pB))) : NULL; DLP_BNUCTX1(pDLP) = NULL; #endif gsUnpackModEngineCtx((Ipp8u*)pB+IPP_UINT_PTR(DLP_MONTP0(pB)), DLP_MONTP0(pDLP)); gsUnpackModEngineCtx((Ipp8u*)pB+IPP_UINT_PTR(DLP_MONTR(pB)), DLP_MONTR(pDLP)); cpUnpackBigNumCtx((Ipp8u*)pB+IPP_UINT_PTR(DLP_GENC(pB)), DLP_GENC(pDLP)); cpUnpackBigNumCtx((Ipp8u*)pB+IPP_UINT_PTR(DLP_X(pB)), DLP_X(pDLP)); cpUnpackBigNumCtx((Ipp8u*)pB+IPP_UINT_PTR(DLP_YENC(pB)), DLP_YENC(pDLP)); cpUnpackPrimeCtx((Ipp8u*)pB+IPP_UINT_PTR(DLP_PRIMEGEN(pB)),DLP_PRIMEGEN(pDLP)); cpBigNumListInit(DLP_BITSIZEP(pDLP)+1, BNLISTSIZE, DLP_BNCTX(pDLP)); } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpgeneratedh.c000066400000000000000000000321441470420105600247120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (generate domain parameters) // // Contents: // ippsDLPGenerateDH() // ippsDLPGenerateDSA() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "hash/pcphashmethod_rmf.h" /*F* // Name: ippsDLPGenerateDH // // Purpose: Generate DL (DH) Domain Parameters. // // Returns: Reason: // ippStsNullPtrErr NULL == pDH // NULL == rndFunc // // ippStsContextMatchErr illegal pDH->idCtx // illegal pSeedIn->idCtx // illegal pSeedOut->idCtx // // ippStsSizeErr !(MIN_DLPDH_BITSIZE <= DLP_BITSIZEP()) // !(256|DLP_BITSIZEP()) // !(MIN_DLPDH_BITSIZER <= DLP_BITSIZER()) // // ippStsRangeErr BitSize(pSeedIn) < DH_BITSIZER() // no room for pSeedOut // // ippStsBadArgErr nTrials <=0 // // ippStsInsufficientEntropy // generation failure due to poor random generator // // ippStsNoErr no errors // // Parameters: // pSeedIn pointer to the input seed (probably null) // nTrials number of trials of primality test // pDL pointer to the DL context // pSeedOut pointer to the output seed (probably null, or ==pSeedIn) // pCounter pointer to the generator loop counter (probably null) // rndFunc external random generator // pRndParam pointer to the external random generator params // // Note: // 1) pSeedIn==NULL means, that rndFunc will be used for input seed generation // 2) PseedIn!=NULL limited by DL bitsizeP parameter! *F*/ #define MAXLOOP (4096) IPPFUN(IppStatus, ippsDLPGenerateDH,(const IppsBigNumState* pSeedIn, int nTrials, IppsDLPState* pDL, IppsBigNumState* pSeedOut, int* pCounter, IppBitSupplier rndFunc, void* pRndParam)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test DL sizes */ IPP_BADARG_RET(MIN_DLPDH_BITSIZER>DLP_BITSIZER(pDL), ippStsSizeErr); IPP_BADARG_RET(MIN_DLPDH_BITSIZE >DLP_BITSIZEP(pDL), ippStsSizeErr); IPP_BADARG_RET(DLP_BITSIZEP(pDL)%256, ippStsSizeErr); /* test number of trials for primality check */ IPP_BADARG_RET(nTrials<=0, ippStsBadArgErr); IPP_BAD_PTR1_RET(rndFunc); { /* allocate BN resources */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pP = cpBigNumListGet(&pList); IppsBigNumState* pR = cpBigNumListGet(&pList); IppsBigNumState* pG = cpBigNumListGet(&pList); IppsBigNumState* pSeed1 = cpBigNumListGet(&pList); IppsBigNumState* pSeed2 = cpBigNumListGet(&pList); /* internally generates SeedIn value by default */ IppBool seed_is_random = ippTrue; int seedBitSize = DLP_BITSIZER(pDL); DLP_FLAG(pDL) = 0; /* // DH generator uses input SEED // either defined by user or generated internally */ if(pSeedIn) { /* test SeedIn */ IPP_BADARG_RET(!BN_VALID_ID(pSeedIn), ippStsContextMatchErr); seedBitSize = BITSIZE_BNU(BN_NUMBER(pSeedIn), BN_SIZE(pSeedIn)); IPP_BADARG_RET(DLP_BITSIZER(pDL)>seedBitSize, ippStsRangeErr); IPP_BADARG_RET(BN_ROOM(pSeed1)BITSIZE(BNU_CHUNK_T)*BN_ROOM(pSeedOut), ippStsRangeErr); } /* // generation DSA domain parameters */ { int feBitsize = DLP_BITSIZEP(pDL); int ordBitsize = DLP_BITSIZER(pDL); int m = (ordBitsize + IPP_SHA1_DIGEST_BITSIZE -1)/IPP_SHA1_DIGEST_BITSIZE; int l = (feBitsize + IPP_SHA1_DIGEST_BITSIZE -1)/IPP_SHA1_DIGEST_BITSIZE; int n = (feBitsize + 1023)/1024; IppsPrimeState* pPrimeGen = DLP_PRIMEGEN(pDL); /* pointers to the BNU32-value of SEED */ Ipp32u* pSeed1BNU32 = (Ipp32u*)BN_NUMBER(pSeed1); Ipp32u* pSeed2BNU32 = (Ipp32u*)BN_NUMBER(pSeed2); int seedSize32 = BITS2WORD32_SIZE(seedBitSize); /* pointers to the octet-string-value of SEED */ Ipp8u* pSeed1Oct = (Ipp8u*)BN_BUFFER(pSeed1); Ipp8u* pSeed2Oct = (Ipp8u*)BN_BUFFER(pSeed2); int octSize; Ipp8u shaDgst1[BITS2WORD8_SIZE(IPP_SHA1_DIGEST_BITSIZE)]; Ipp8u shaDgst2[BITS2WORD8_SIZE(IPP_SHA1_DIGEST_BITSIZE)]; Ipp8u hashMethodArr[sizeof(IppsHashMethod)]; IppsHashMethod* hash_method = (IppsHashMethod*)hashMethodArr; #if (_SHA_NI_ENABLING_==_FEATURE_ON_) ippsHashMethodSet_SHA1_NI(hash_method); #elif (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_) ippsHashMethodSet_SHA1_TT(hash_method); #else ippsHashMethodSet_SHA1(hash_method); #endif int primeGenerated = 0; int genCounter; ippsSet_BN(ippBigNumPOS, 1, (Ipp32u*)&m, pP); /* P = m */ /* // generate prime Q */ for(genCounter=0; genCounteridCtx // illegal pSeedIn->idCtx // illegal pSeedOut->idCtx // // ippStsSizeErr !(MIN_DLPDLP_BITSIZE <= DLP_BITSIZEP() <= MAX_DLPDLP_BITSIZE) // !(64|DLP_BITSIZEP()) // !(DEF_DLPDLP_BITSIZER == DLP_BITSIZER()) // // ippStsRangeErr BitSize(pSeedIn) < MIN_DLPDLP_SEEDSIZE // BitSize(pSeedIn) > DLP_BITSIZEP() // no room for pSeedOut // // ippStsBadArgErr nTrials <=0 // // ippStsInsufficientEntropy // generation failure due to poor random generator // // ippStsNoErr no errors // // Parameters: // pSeedIn pointer to the input seed (probably null) // nTrials number of trials of primality test // pDL pointer to the DL context // pSeedOut pointer to the output seed (probably null, or ==pSeedIn) // pCounter pointer to the generator loop counter (probably null) // rndFunc external random generator // pRndParam pointer to the external random generator params // // Note: // 1) pSeedIn==NULL means, that rndFunc will be used for input seed generation // 2) PseedIn!=NULL limited by DSA bitsize (L) parameter! *F*/ #define R_MAXLOOP (100) #define P_MAXLOOP (4096) #define G_MAXLOOP (100) IPPFUN(IppStatus, ippsDLPGenerateDSA,(const IppsBigNumState* pSeedIn, int nTrials, IppsDLPState *pDL, IppsBigNumState* pSeedOut, int* pCounter, IppBitSupplier rndFunc, void* pRndParam)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test DL sizes */ IPP_BADARG_RET(DEF_DLPDSA_BITSIZER != DLP_BITSIZER(pDL),ippStsSizeErr); IPP_BADARG_RET(MIN_DLPDSA_BITSIZE >DLP_BITSIZEP(pDL), ippStsSizeErr); IPP_BADARG_RET(MAX_DLPDSA_BITSIZE = MIN_DLPDSA_SEEDSIZE (==160 bits) - it's FIPS-186 claim - divisible by 8 (week request, because provided automatically by BITS2WORD8_SIZE(seedBitSize) conversion) If seedBitSize (been calculated above) <160 this means that there are some zero msb bits in SeedIn representation. For example, if SeedIn hex string is is 0000000000000000000000000000000000000001 or even 01 we'll think about 160 bit length **/ if(seedBitSizeidCtx // invalid pPrivate->idCtx // invalid pPublic->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsRangeErr not enough room for: // pPrivate, // pPublic // // ippStsNoErr no error // // Parameters: // pPrvKey pointer to the new privatea key // pPubKey pointer to the corresponding public key // pDL pointer to the DL context // rndFunc external random generator // pRndParam pointer to the external random generator params *F*/ IPPFUN(IppStatus, ippsDLPGenKeyPair,(IppsBigNumState* pPrvKey, IppsBigNumState* pPubKey, IppsDLPState* pDL, IppBitSupplier rndFunc, void* pRndParam)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test random generator */ IPP_BAD_PTR1_RET(rndFunc); /* test private/public keys */ IPP_BAD_PTR2_RET(pPrvKey, pPubKey); IPP_BADARG_RET(!BN_VALID_ID(pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pPubKey), ippStsContextMatchErr); IPP_BADARG_RET(DLP_BITSIZER(pDL)>BITSIZE(BNU_CHUNK_T)*BN_ROOM(pPrvKey), ippStsRangeErr); IPP_BADARG_RET(DLP_BITSIZEP(pDL)>BITSIZE(BNU_CHUNK_T)*BN_ROOM(pPubKey), ippStsRangeErr); { /* // generate random private key X: 0 < X < R */ BNU_CHUNK_T* pOrder = DLP_R(pDL); cpSize ordBitSize = DLP_BITSIZER(pDL); cpSize ordLen = BITS_BNU_CHUNK(ordBitSize); BNU_CHUNK_T xMask = MASK_BNU_CHUNK(ordBitSize); //BNU_CHUNK_T* pY = BN_NUMBER(pPubKey); BNU_CHUNK_T* pX = BN_NUMBER(pPrvKey); //gsModEngine* pME = DLP_MONTP0(pDL); do { rndFunc((Ipp32u*)pX, ordBitSize, pRndParam); pX[ordLen-1] &= xMask; } while( cpEqu_BNU_CHUNK(pX, ordLen, 0) || cpCmp_BNU(pX,ordLen, pOrder,ordLen)>=0 ); BN_SIZE(pPrvKey) = ordLen; BN_SIGN(pPrvKey) = ippBigNumPOS; /* // compute public key: G^prvKey (mod P) */ cpMontExpBin_BN_sscm(pPubKey, DLP_GENC(pDL), pPrvKey, DLP_MONTP0(pDL)); cpMontDec_BN(pPubKey, pPubKey, DLP_MONTP0(pDL)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpget.c000066400000000000000000000061321470420105600233610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (setup/retrieve domain parameters) // // Contents: // ippsDLPGet() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDLPGet // // Purpose: Retrieve DLP Domain Parameter. // // Returns: Reason: // ippStsNullPtrErr NULL == pP // NULL == pR // NULL == pG // NULL == pDL // // ippStsContextMatchErr illegal pP->idCtx // illegal pR->idCtx // illegal pG->idCtx // illegal pDL->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsRangeErr not enough room for: // pP, // pR, // pG // // ippStsNoErr no errors // // Parameters: // pP pointer to the retrieval P // pR pointer to the retrieval R // pG pointer to the retrieval G // pDSA pointer to the DL context // *F*/ IPPFUN(IppStatus, ippsDLPGet,(IppsBigNumState* pP, IppsBigNumState* pR, IppsBigNumState* pG, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test DL parameters */ IPP_BAD_PTR3_RET(pP, pR, pG); IPP_BADARG_RET(!BN_VALID_ID(pP), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pG), ippStsContextMatchErr); /* test size of retrieval parameters */ IPP_BADARG_RET(BN_ROOM(pP)idCtx // illegal pDL->idCtx // // ippStsIncompleteContextErr requested parameter hasn't set up // // ippStsOutOfRangeErr BN_ROOM(pDP) < BN_ROOM(DLP_{P|R|G}(pDL)) // // ippStsBadArgErr invalid key tag // // errors produced by ippsSet_BN() // // ippStsNoErr no errors // // Parameters: // pDP pointer to the DL domain parameter // tag DLP key component tag // pDL pointer to the DL context // *F*/ IPPFUN(IppStatus, ippsDLPGetDP,(IppsBigNumState* pDP, IppDLPKeyTag tag, const IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test DL parameter to be set */ IPP_BAD_PTR1_RET(pDP); IPP_BADARG_RET(!BN_VALID_ID(pDP), ippStsContextMatchErr); { IppStatus sts = ippStsNoErr; switch(tag) { case ippDLPkeyP: if(DLP_FLAG(pDL)&ippDLPkeyP) sts = ippsSet_BN(ippBigNumPOS, BITS2WORD32_SIZE(DLP_BITSIZEP(pDL)), (Ipp32u*)DLP_P(pDL), pDP); else sts = ippStsIncompleteContextErr; break; case ippDLPkeyR: if(DLP_FLAG(pDL)&ippDLPkeyR) sts = ippsSet_BN(ippBigNumPOS, BITS2WORD32_SIZE(DLP_BITSIZER(pDL)), (Ipp32u*)DLP_R(pDL), pDP); else sts = ippStsIncompleteContextErr; break; case ippDLPkeyG: if(DLP_FLAG(pDL)&ippDLPkeyG) { cpMontDec_BN(pDP, DLP_GENC(pDL), DLP_MONTP0(pDL)); } else sts = ippStsIncompleteContextErr; break; default: sts = ippStsBadArgErr; } return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpgetsize.c000066400000000000000000000074771470420105600242710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field (initialization) // // Contents: // ippsDLPGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" #include "pcpmont_exp_bufsize.h" /*F* // Name: ippsDLPGetSize // // Purpose: Returns size of DL context (bytes). // // Returns: Reason: // ippStsNullPtrErr NULL == pSize // // ippStsSizeErr MIN_DLP_BITSIZE > feBitSize // MIN_DLP_BITSIZER > ordBitSize // ordBitSize >= feBitSize // // ippStsNoErr no errors // // Parameters: // feBitSize size (bits) of field element (GF(p)) of DL system // ordBitSize size (bits) of subgroup (GF(p)) generator order // pSize pointer to the size of DLP context (bytes) // *F*/ IPPFUN(IppStatus, ippsDLPGetSize,(int feBitSize, int ordBitSize, int *pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); /* test sizes of DL system */ IPP_BADARG_RET(MIN_DLP_BITSIZE >feBitSize, ippStsSizeErr); IPP_BADARG_RET(MIN_DLP_BITSIZER>ordBitSize, ippStsSizeErr); IPP_BADARG_RET(ordBitSize>=feBitSize, ippStsSizeErr); { int bnSizeP; int bnSizeR; int montSizeP; int montSizeR; int primeGenSize; int bn_resourceSize; #if defined(_USE_WINDOW_EXP_) int window = cpMontExp_WinSize(ordBitSize); int bnu_resourceSize = window==1? 0 : cpMontExpScratchBufferSize(feBitSize, ordBitSize, 1); #endif /* size of GF(P) element */ int sizeP = BITS2WORD32_SIZE(feBitSize); /* size of GF(R) element */ int sizeR = BITS2WORD32_SIZE(ordBitSize); /* sizeof multi-exp table */ int sizeMeTable = cpMontExpScratchBufferSize(feBitSize, ordBitSize, 2); /* size of BigNum over GF(P) */ ippsBigNumGetSize(sizeP, &bnSizeP); /* size of BigNum over GF(R) */ ippsBigNumGetSize(sizeR, &bnSizeR); /* size of montgomery engine over GF(P) */ gsModEngineGetSize(feBitSize, DLP_MONT_POOL_LENGTH, &montSizeP); /* size of montgomery engine over GF(R) */ gsModEngineGetSize(ordBitSize, DLP_MONT_POOL_LENGTH, &montSizeR); /* size of prime engine */ ippsPrimeGetSize(feBitSize, &primeGenSize); /* size of big num list (big num in the list preserve 32 bit word) */ bn_resourceSize = cpBigNumListGetSize(feBitSize+1, BNLISTSIZE); *pSize = (Ipp32s)sizeof(IppsDLPState) +montSizeP /* montgomery(P) */ +montSizeR /* montgomery(Q) */ +bnSizeP /* Genc */ +bnSizeR /* X */ +bnSizeP /* Y */ +primeGenSize /* prime engine */ +sizeMeTable /* pre-computed multi-exp table */ +bn_resourceSize /* BN resource */ #if defined(_USE_WINDOW_EXP_) +bnu_resourceSize /* BNU resource */ #endif ; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpinit.c000066400000000000000000000114041470420105600235430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field (initialization) // // Contents: // ippsDLPInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" #include "pcpmont_exp_bufsize.h" /*F* // Name: ippsDLPInit // // Purpose: Init DL context. // // Returns: Reason: // ippStsNullPtrErr NULL == pDSA // // ippStsSizeErr MIN_DLP_BITSIZE > feBitSize // MIN_DLP_BITSIZER > ordBitSize // ordBitSize >= feBitSize // // ippStsNoErr no errors // // Parameters: // feBitSize size (bits) of field element (GF(p)) of DL system // ordBitSize size (bits) of subgroup (GF(p)) generator order // pDL pointer to the DL context // *F*/ IPPFUN(IppStatus, ippsDLPInit,(int feBitSize, int ordBitSize, IppsDLPState* pDL)) { /* test DSA context */ IPP_BAD_PTR1_RET(pDL); /* test sizes of DL system */ IPP_BADARG_RET(MIN_DLP_BITSIZE >feBitSize, ippStsSizeErr); IPP_BADARG_RET(MIN_DLP_BITSIZER>ordBitSize, ippStsSizeErr); IPP_BADARG_RET(ordBitSize>=feBitSize, ippStsSizeErr); DLP_SET_ID(pDL); DLP_FLAG(pDL) = 0; DLP_BITSIZEP(pDL) = feBitSize; DLP_BITSIZER(pDL) = ordBitSize; DLP_EXPMETHOD(pDL)= BINARY; /* // init other context fields */ { int bnSizeP; int bnSizeR; int montSizeP; int montSizeR; int primeGenSize; int bn_resourceSize; Ipp8u* ptr = (Ipp8u*)pDL; /* size of GF(P) element */ int sizeP = BITS2WORD32_SIZE(feBitSize); /* size of GF(R) element */ int sizeR = BITS2WORD32_SIZE(ordBitSize); /* size of pre-computed multi-exp table */ int sizeMeTable = cpMontExpScratchBufferSize(feBitSize, ordBitSize, 2); /* size of window for exponentiation */ #if defined(_USE_WINDOW_EXP_) int window = cpMontExp_WinSize(ordBitSize); DLP_EXPMETHOD(pDL) = window>1? WINDOW : BINARY; #endif /* size of BigNum over GF(P) */ ippsBigNumGetSize(sizeP, &bnSizeP); /* size of BigNum over GF(R) */ ippsBigNumGetSize(sizeR, &bnSizeR); /* size of montgomery engine over GF(P) */ gsModEngineGetSize(feBitSize, DLP_MONT_POOL_LENGTH, &montSizeP); /* size of montgomery engine over GF(R) */ gsModEngineGetSize(ordBitSize, DLP_MONT_POOL_LENGTH, &montSizeR); /* size of prime engine */ ippsPrimeGetSize(feBitSize, &primeGenSize); /* size of big num list (big num in the list preserve 32 bit word) */ bn_resourceSize = cpBigNumListGetSize(feBitSize+1, BNLISTSIZE); /* allocate buffers */ ptr += sizeof(IppsDLPState); DLP_MONTP0(pDL) = (gsModEngine*)(ptr); ptr += montSizeP; DLP_MONTP1(pDL) = 0; DLP_MONTR(pDL) = (gsModEngine*)(ptr); ptr += montSizeR; DLP_GENC(pDL) = (IppsBigNumState*)(ptr); ptr += bnSizeP; DLP_X(pDL) = (IppsBigNumState*)(ptr); ptr += bnSizeR; DLP_YENC(pDL) = (IppsBigNumState*)(ptr); ptr += bnSizeP; DLP_PRIMEGEN(pDL)= (IppsPrimeState*)(ptr); ptr += primeGenSize; DLP_METBL(pDL) = (BNU_CHUNK_T*)( IPP_ALIGNED_PTR(ptr, CACHE_LINE_SIZE) ); ptr += sizeMeTable; DLP_BNCTX(pDL) = (BigNumNode*)(ptr); ptr += bn_resourceSize; #if defined(_USE_WINDOW_EXP_) DLP_BNUCTX0(pDL) = 0; DLP_BNUCTX1(pDL) = 0; DLP_BNUCTX0(pDL) = window>1? (BNU_CHUNK_T*)( IPP_ALIGNED_PTR(ptr, (int)sizeof(BNU_CHUNK_T)) ) : 0; #endif /* init buffers */ gsModEngineInit(DLP_MONTP0(pDL), NULL, feBitSize, DLP_MONT_POOL_LENGTH, gsModArithDLP()); gsModEngineInit(DLP_MONTR(pDL), NULL, ordBitSize, DLP_MONT_POOL_LENGTH, gsModArithDLP()); ippsBigNumInit(sizeP, DLP_GENC(pDL)); ippsBigNumInit(sizeP, DLP_YENC(pDL)); ippsBigNumInit(sizeR, DLP_X(pDL)); ippsPrimeInit(feBitSize, DLP_PRIMEGEN(pDL)); cpBigNumListInit(feBitSize+1, BNLISTSIZE, DLP_BNCTX(pDL)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlppack.c000066400000000000000000000032311470420105600235150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field (initialization) // // Contents: // ippsDLPPack() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" /*F* // Name: ippsDLPPack // // Purpose: Copy initialized context to the buffer. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer DLP ctx // pSize pointer to the packed spec size // *F*/ IPPFUN(IppStatus, ippsDLPPack,(const IppsDLPState* pDL, Ipp8u* pBuffer)) { /* test pointers */ IPP_BAD_PTR2_RET(pDL, pBuffer); /* test the context */ IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); cpPackDLPCtx(pDL, pBuffer); IppsDLPState* pCopy = (IppsDLPState*)pBuffer; DLP_RESET_ID(pCopy); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlppublickey.c000066400000000000000000000064711470420105600245770ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (EC Key Generation, Validation and Set Up) // // Contents: // ippsDLPPublicKey() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDLPPublicKey // // Purpose: Compute DL public key // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pPrvKey // NULL == pPubKey // // ippStsContextMatchErr invalid pDL->idCtx // invalid pPrvKey->idCtx // invalid pPubKey->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsInvalidPrivateKey !(0 < pPrivate < DLP_R()) // // ippStsRangeErr not enough room for pPubKey // // ippStsNoErr no error // // Parameters: // pPrvKey pointer to the private key // pPubKey pointer to the public key // pDL pointer to the DL context *F*/ IPPFUN(IppStatus, ippsDLPPublicKey,(const IppsBigNumState* pPrvKey, IppsBigNumState* pPubKey, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test private/public keys */ IPP_BAD_PTR2_RET(pPrvKey, pPubKey); IPP_BADARG_RET(!BN_VALID_ID(pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pPubKey), ippStsContextMatchErr); /* test private key */ IPP_BADARG_RET((0<=cpBN_cmp(cpBN_OneRef(), pPrvKey))|| (0<=cpCmp_BNU(BN_NUMBER(pPrvKey),BN_SIZE(pPrvKey), DLP_R(pDL),BITS_BNU_CHUNK(DLP_BITSIZER(pDL)))), ippStsInvalidPrivateKey); /* test public key's room */ IPP_BADARG_RET(BN_ROOM(pPubKey)idCtx // illegal pPubKey->idCtx // illegal pSecret->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsRangeErr no room for pSecret // // ippStsNoErr no errors // // Parameters: // pPrvKeyA pointer to the own private key // pPubKeyB pointer to the partner's public key // pSecret pointer to the secret value // pDL pointer to the DL context *F*/ IPPFUN(IppStatus, ippsDLPSharedSecretDH,(const IppsBigNumState* pPrvKeyA, const IppsBigNumState* pPubKeyB, IppsBigNumState* pSecret, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test public key */ IPP_BAD_PTR1_RET(pPrvKeyA); IPP_BADARG_RET(!BN_VALID_ID(pPrvKeyA), ippStsContextMatchErr); /* test public key */ IPP_BAD_PTR1_RET(pPubKeyB); IPP_BADARG_RET(!BN_VALID_ID(pPubKeyB), ippStsContextMatchErr); /* test secret */ IPP_BAD_PTR1_RET(pSecret); IPP_BADARG_RET(!BN_VALID_ID(pSecret), ippStsContextMatchErr); IPP_BADARG_RET(BITS_BNU_CHUNK(DLP_BITSIZEP(pDL))>BN_ROOM(pSecret), ippStsRangeErr); cpMontEnc_BN(pSecret, pPubKeyB, DLP_MONTP0(pDL)); { gsModEngine* pMEorder = DLP_MONTR(pDL); int ordLen = MOD_LEN(pMEorder); /* expand privKeyA */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pTmpPrivKey = cpBigNumListGet(&pList); ZEXPAND_COPY_BNU(BN_NUMBER(pTmpPrivKey), ordLen, BN_NUMBER(pPrvKeyA), BN_SIZE(pPrvKeyA)); BN_SIZE(pTmpPrivKey) = ordLen; #if !defined(_USE_WINDOW_EXP_) cpMontExpBin_BN_sscm(pSecret, pSecret, pTmpPrivKey, DLP_MONTP0(pDL)); #else (DLP_EXPMETHOD(pDL)==BINARY) || (1==cpMontExp_WinSize(BITSIZE_BNU(BN_NUMBER(pTmpPrivKey), BN_SIZE(pTmpPrivKey))))? cpMontExpBin_BN_sscm(pSecret, pSecret, pTmpPrivKey, DLP_MONTP0(pDL)) : cpMontExpWin_BN_sscm(pSecret, pSecret, pTmpPrivKey, DLP_MONTP0(pDL), DLP_BNUCTX0(pDL)); #endif cpMontDec_BN(pSecret, pSecret, DLP_MONTP0(pDL)); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpset.c000066400000000000000000000067031470420105600234010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (setup/retrieve domain parameters) // // Contents: // ippsDLPSet() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDLPSet // // Purpose: Set DL Domain Parameters. // // Returns: Reason: // ippStsNullPtrErr NULL == pP // NULL == pR // NULL == pG // NULL == pDL // // ippStsContextMatchErr illegal pP->idCtx // illegal pR->idCtx // illegal pG->idCtx // illegal pDL->idCtx // // ippStsRangeErr not enough room for: // pP, // pR, // pG // // errors produced by ippsMontSet() // ippsMontForm() // // ippStsNoErr no errors // // Parameters: // pP pointer to the DL domain parameter (P) // pR pointer to the DL domain parameter (R) // pG pointer to the DL domain parameter (G) // pDSA pointer to the DL context // *F*/ IPPFUN(IppStatus, ippsDLPSet,(const IppsBigNumState* pP, const IppsBigNumState* pR, const IppsBigNumState* pG, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test DL domain parameters */ IPP_BAD_PTR3_RET(pP, pR, pG); IPP_BADARG_RET(!BN_VALID_ID(pP), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pG), ippStsContextMatchErr); /* test size of DL domain parameters */ IPP_BADARG_RET(BN_SIZE(pP)>BITS_BNU_CHUNK(DLP_BITSIZEP(pDL)), ippStsRangeErr); IPP_BADARG_RET(BN_SIZE(pR)>BITS_BNU_CHUNK(DLP_BITSIZER(pDL)), ippStsRangeErr); IPP_BADARG_RET(BN_SIZE(pG)>BITS_BNU_CHUNK(DLP_BITSIZEP(pDL)), ippStsRangeErr); /* // set up DL domain parameters */ { IppStatus sts; DLP_FLAG(pDL) = 0; cpBN_zero(DLP_X(pDL)); cpBN_zero(DLP_YENC(pDL)); sts = gsModEngineInit(DLP_MONTP0(pDL), (Ipp32u*)BN_NUMBER(pP), cpBN_bitsize(pP), DLP_MONT_POOL_LENGTH, gsModArithDLP()); if(ippStsNoErr==sts) { sts = gsModEngineInit(DLP_MONTR(pDL), (Ipp32u*)BN_NUMBER(pR), cpBN_bitsize(pR), DLP_MONT_POOL_LENGTH, gsModArithDLP()); if(ippStsNoErr==sts) { cpMontEnc_BN(DLP_GENC(pDL), pG, DLP_MONTP0(pDL)); DLP_FLAG(pDL) = ippDLPkeyP|ippDLPkeyR|ippDLPkeyG; return ippStsNoErr; } } return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpsetdp.c000066400000000000000000000062431470420105600237240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (setup/retrieve domain parameters) // // Contents: // ippsDLPSetDP() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDLPSetDP // // Purpose: Set tagged DL Domain Parameter. // // Returns: Reason: // ippStsNullPtrErr NULL == pDP // NULL == pDL // // ippStsContextMatchErr illegal pDP->idCtx // illegal pDL->idCtx // // ippStsRangeErr not enough room for pDP // // ippStsBadArgErr invalid key tag // // errors produced by ippsMontSet() // ippsMontForm() // // ippStsNoErr no errors // // Parameters: // pDP pointer to the DL domain parameter // tag DLP key component tag // pDL pointer to the DL context // *F*/ IPPFUN(IppStatus, ippsDLPSetDP,(const IppsBigNumState* pDP, IppDLPKeyTag tag, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test DL parameter to be set */ IPP_BAD_PTR1_RET(pDP); IPP_BADARG_RET(!BN_VALID_ID(pDP), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pDP), ippStsBadArgErr); { IppStatus sts = ippStsNoErr; cpBN_zero(DLP_X(pDL)); cpBN_zero(DLP_YENC(pDL)); switch(tag) { case ippDLPkeyP: DLP_FLAG(pDL) &=(Ipp32u)~ippDLPkeyP; sts = gsModEngineInit(DLP_MONTP0(pDL), (Ipp32u*)BN_NUMBER(pDP), cpBN_bitsize(pDP), DLP_MONT_POOL_LENGTH, gsModArithDLP()); if(ippStsNoErr==sts) { DLP_FLAG(pDL) |= ippDLPkeyP; } break; case ippDLPkeyR: DLP_FLAG(pDL) &=(Ipp32u)~ippDLPkeyR; sts = gsModEngineInit(DLP_MONTR(pDL), (Ipp32u*)BN_NUMBER(pDP), cpBN_bitsize(pDP), DLP_MONT_POOL_LENGTH, gsModArithDLP()); if(ippStsNoErr==sts) DLP_FLAG(pDL) |= ippDLPkeyR; break; case ippDLPkeyG: DLP_FLAG(pDL) &=(Ipp32u)~ippDLPkeyG; if(DLP_FLAG(pDL)&ippDLPkeyP) { cpMontEnc_BN(DLP_GENC(pDL), pDP, DLP_MONTP0(pDL)); DLP_FLAG(pDL) |= ippDLPkeyG; } else sts = ippStsIncompleteContextErr; break; default: sts = ippStsBadArgErr; } return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpsetkeypair.c000066400000000000000000000073031470420105600247630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (EC Key Generation, Validation and Set Up) // // Contents: // ippsDLPSetKeyPair() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDSASetKeyPair // // Purpose: Set up Key Pair into the DL context // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pPrvKey // NULL == pPubKey // // ippStsContextMatchErr invalid pDL->idCtx // invalid pPrvKey->idCtx // invalid pPubKey->idCtx // // ippStsIncompleteContextErr // incomplete context: P and/or R and/or G is not set // // ippStsInvalidPrivateKey PrvKey >= R // PrvKey < 0 // // ippStsRangeErr PubKey >= P // PubKey < 0 // // ippStsNoErr no error // // Parameters: // pPrvKey pointer to the private key // pPubKey pointer to the public key // pDL pointer to the DL context *F*/ IPPFUN(IppStatus, ippsDLPSetKeyPair,(const IppsBigNumState* pPrvKey, const IppsBigNumState* pPubKey, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* set up private key */ if(pPrvKey) { IPP_BADARG_RET(!BN_VALID_ID(pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pPrvKey), ippStsInvalidPrivateKey); { gsModEngine* pMontR = DLP_MONTR(pDL); BNU_CHUNK_T* pOrder = MOD_MODULUS(pMontR); int ordLen = MOD_LEN(pMontR); BNU_CHUNK_T* pPriData = BN_NUMBER(pPrvKey); int priLen = BN_SIZE(pPrvKey); /* make sure regular 0 < private < order */ IPP_BADARG_RET(cpEqu_BNU_CHUNK(pPriData, priLen, 0) || 0<=cpCmp_BNU(pPriData, priLen, pOrder, ordLen), ippStsInvalidPrivateKey); cpBN_copy(DLP_X(pDL), pPrvKey); BN_SIZE(DLP_X(pDL)) = ordLen; } } /* set up public key */ if(pPubKey) { IPP_BADARG_RET(!BN_VALID_ID(pPubKey), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pPubKey), ippStsRangeErr); { gsModEngine* pMontP = DLP_MONTP0(pDL); BNU_CHUNK_T* pPrime = MOD_MODULUS(pMontP); int primeLen = MOD_LEN(pMontP); BNU_CHUNK_T* pPubData = BN_NUMBER(pPubKey); int pubLen = BN_SIZE(pPubKey); /* make sure regular 0 < public < prime */ IPP_BADARG_RET(cpEqu_BNU_CHUNK(pPubData, pubLen, 0) || 0<=cpCmp_BNU(pPubData, pubLen, pPrime, primeLen), ippStsRangeErr); cpMontEnc_BN(DLP_YENC(pDL), pPubKey, DLP_MONTP0(pDL)); } } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpsigndsaca.c000066400000000000000000000154451470420105600245450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (Sign, DSA version) // // Contents: // ippsDLPSignDSA() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "gfpec/pcpeccp.h" /*F* // Name: ippsDLPSignDSA // // Purpose: Signing of message representative // (DSA version). // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pPrvKey // NULL == pMsgDigest // NULL == pSignR // NULL == pSignS // // ippStsContextMatchErr illegal pDL->idCtx // illegal pPrvKey->idCtx // illegal pMsgDigest->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsIncompleteContextErr // incomplete context: P and/or R and/or G is not set // // ippStsMessageErr MsgDigest >= R // MsgDigest < 0 // // ippStsInvalidPrivateKey PrvKey >= R // PrvKey < 0 // // ippStsRangeErr not enough room for: // signR // signS // // ippStsNoErr no errors // // Parameters: // pMsgDigest pointer to the message representative to be signed // pPevKey pointer to the (signatory's) regular private key // pSignR,pSignS pointer to the signature // pDL pointer to the DL context // // Primitive sequence call: // 1) set up domain parameters // 2) generate (signatory's) ephemeral key pair // 3) set up (signatory's) ephemeral key pair // 4) use primitive with (signatory's) private key *F*/ IPPFUN(IppStatus, ippsDLPSignDSA,(const IppsBigNumState* pMsgDigest, const IppsBigNumState* pPrvKey, IppsBigNumState* pSignR, IppsBigNumState* pSignS, IppsDLPState *pDL)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test message representative */ IPP_BAD_PTR1_RET(pMsgDigest); IPP_BADARG_RET(!BN_VALID_ID(pMsgDigest), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pMsgDigest), ippStsMessageErr); /* test regular private key */ IPP_BAD_PTR1_RET(pPrvKey); IPP_BADARG_RET(!BN_VALID_ID(pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pPrvKey), ippStsInvalidPrivateKey); /* test signature */ IPP_BAD_PTR2_RET(pSignR,pSignS); IPP_BADARG_RET(!BN_VALID_ID(pSignR), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pSignS), ippStsContextMatchErr); IPP_BADARG_RET(BITSIZE(BNU_CHUNK_T)*BN_ROOM(pSignR)decode(buffer, buffer, pMontP); ns = cpMod_BNU(buffer, elmLen, pOrder, ordLen); ZEXPAND_COPY_BNU(dataR, ordLen, buffer, ns); gsModPoolFree(pMontP, 1); if(!cpEqu_BNU_CHUNK(dataR, ordLen, 0)) { /* // signS = ((1/eX)*(MsgDigest + X*signR)) (mod R) */ /* private representation in Montgomery domain */ ZEXPAND_COPY_BNU(dataS, ordLen, pPriData, priLen); MOD_METHOD(pMontR)->encode(dataS, dataS, pMontR); /* (X*signR) in regular domain */ MOD_METHOD(pMontR)->mul(dataS, dataS, dataR, pMontR); /* pMsgDigest + (X*signR) */ ZEXPAND_COPY_BNU(buffS, ordLen, pMsgData, msgLen); cpModAdd_BNU(dataS, dataS, buffS, pOrder, ordLen, buffS); if(!cpEqu_BNU_CHUNK(dataS, ordLen, 0)) { ZEXPAND_COPY_BNU(buffS, ordLen, BN_NUMBER(DLP_X(pDL)), BN_SIZE(DLP_X(pDL))); /* (1/eX) in Montgomery domain */ gs_mont_inv(buffS, buffS, pMontR, alm_mont_inv_ct); /* signS = (1/eX)*(MsgDigest + X*signR) */ MOD_METHOD(pMontR)->mul(dataS, dataS, buffS, pMontR); /* signR */ ns = ordLen; FIX_BNU(dataR, ns); BN_SIGN(pSignR) = ippBigNumPOS; BN_SIZE(pSignR) = ns; /* signS */ ns = ordLen; FIX_BNU(dataS, ns); BN_SIGN(pSignS) = ippBigNumPOS; BN_SIZE(pSignS) = ns; return ippStsNoErr; } } return ippStsEphemeralKeyErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpunpack.c000066400000000000000000000030431470420105600240610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field (initialization) // // Contents: // ippsDLPUnpack() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" /*F* // Name: ippsDLPUnpack // // Purpose: Unpack buffer content into the initialized context. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer DLP ctx // pSize pointer to the packed spec size // *F*/ IPPFUN(IppStatus, ippsDLPUnpack,(const Ipp8u* pBuffer, IppsDLPState* pDL)) { /* test pointers */ IPP_BAD_PTR2_RET(pDL, pBuffer); cpUnpackDLPCtx(pBuffer, pDL); DLP_SET_ID(pDL); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpvalidatedh.c000066400000000000000000000144371470420105600247160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (validate domain parameters) // // Contents: // ippsDLPValidateDH() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /* // Name: DLPValidate // // Purpose: Validate DL Domain Parameters. // // Parameters: // nTrials number of trials of primality test // pResult pointer to the validation result // pDL pointer to the DL context // rndFunc external random generator // pRndParam pointer to the external random generator params */ static IppDLResult DLPValidate(int nTrials, IppsDLPState* pDL, IppBitSupplier rndFunc, void* pRndParam) { /* // validate DL parameters: // check that P is odd and P > 2 // check that R is odd and R > 2 // check that R | (P-1) // check that 1 < G < P // check that 1 == G^R (mod P) */ BNU_CHUNK_T* pP = DLP_P(pDL); BNU_CHUNK_T* pR = DLP_R(pDL); cpSize lenP = BITS_BNU_CHUNK(DLP_BITSIZEP(pDL)); cpSize lenR = BITS_BNU_CHUNK(DLP_BITSIZER(pDL)); IppsPrimeState* pPrimeCtx = DLP_PRIMEGEN(pDL); /* allocate BN resources */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pTmp = cpBigNumListGet(&pList); BNU_CHUNK_T* pT = BN_NUMBER(pTmp); /* P is odd and prime */ if(0 == (pP[0] & 1)) return ippDLBaseIsEven; if(0==cpPrimeTest(pP, lenP, nTrials, pPrimeCtx, rndFunc,pRndParam)) return ippDLCompositeBase; /* R is odd and prime */ if(0 == (pR[0] & 1)) return ippDLOrderIsEven; if(0==cpPrimeTest(pR, lenR, nTrials, pPrimeCtx, rndFunc,pRndParam)) return ippDLCompositeOrder; /* R|(P-1) */ cpDec_BNU(pT, pP, lenP, 1); cpMod_BNU(pT, lenP, pR, lenR); if(!cpEqu_BNU_CHUNK(pT, lenP, 0)) return ippDLInvalidCofactor; /* 1 < G < P */ cpMontDec_BN(pTmp, DLP_GENC(pDL), DLP_MONTP0(pDL)); if( 0>=cpBN_cmp(pTmp, cpBN_OneRef()) || cpCmp_BNU(pT, BN_SIZE(pTmp), DLP_P(pDL), lenP)>=0 ) return ippDLInvalidGenerator; /* G^R = 1 (mod P) */ cpMontExpBin_BNU(pT, BN_NUMBER(DLP_GENC(pDL)),lenP, pR, lenR, DLP_MONTP0(pDL) ); if( cpCmp_BNU(pT,lenP, MOD_MNT_R(DLP_MONTP0(pDL)), lenP) ) return ippDLInvalidGenerator; return ippDLValid; } /*F* // Name: ippsDLPValidateDH // // Purpose: Validate DL (DH) Domain Parameters. // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pResult // NULL == rndFunc // // ippStsContextMatchErr illegal pDL->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsBadArgErr nTrials <=0 // // ippStsNoErr no errors // // Parameters: // nTrials number of trials of primality test // pResult pointer to the validation result // pDL pointer to the DL context // rndFunc external random generator // pRndParam pointer to the external random generator params *F*/ IPPFUN(IppStatus, ippsDLPValidateDH,(int nTrials, IppDLResult* pResult, IppsDLPState* pDL, IppBitSupplier rndFunc, void* pRndParam)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test operation flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test number of trials for primality check */ IPP_BADARG_RET(nTrials<=0, ippStsBadArgErr); /* test another pointers */ IPP_BAD_PTR3_RET(pResult, rndFunc, pRndParam); /* execute genetal DL validation */ *pResult = DLPValidate(nTrials, pDL, rndFunc, pRndParam); /* // DH specific validation */ if(ippDLValid == *pResult) { /* allocate BN resources */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pT = cpBigNumListGet(&pList); BNU_CHUNK_T* pP = DLP_P(pDL); BNU_CHUNK_T* pR = DLP_R(pDL); cpSize feBitSize = DLP_BITSIZEP(pDL); cpSize ordBitSize= DLP_BITSIZER(pDL); cpSize lenP = BITS_BNU_CHUNK(feBitSize); cpSize lenR = BITS_BNU_CHUNK(ordBitSize); /* DLP_BITSIZEP() >= 512, 256|DLP_BITSIZEP() */ if( (MIN_DLPDH_BITSIZE > feBitSize) || (feBitSize % 256) ) { *pResult = ippDLInvalidBaseRange; return ippStsNoErr; } /* 2^(DLP_BITSIZEP()-1) < P < 2^DLP_BITSIZEP() */ cpBN_power2(pT, feBitSize-1); if( 0<=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pP,lenP) ) { *pResult = ippDLInvalidBaseRange; return ippStsNoErr; } cpBN_power2(pT, feBitSize); if( 0>=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pP,lenP) ) { *pResult = ippDLInvalidBaseRange; return ippStsNoErr; } /* DLP_BITSIZER() >= 160 */ if( (MIN_DLPDH_BITSIZER > ordBitSize) ) { *pResult = ippDLInvalidOrderRange; return ippStsNoErr; } /* 2^(DLP_BITSIZER()-1) < R < 2^DLP_BITSIZER() */ cpBN_power2(pT, ordBitSize-1); if( 0<=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pR,lenR) ) { *pResult = ippDLInvalidOrderRange; return ippStsNoErr; } cpBN_power2(pT, ordBitSize); if( 0>=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pR,lenR) ) { *pResult = ippDLInvalidOrderRange; return ippStsNoErr; } /* 1 < G < (P-1) */ cpMontDec_BN(pT, DLP_GENC(pDL), DLP_MONTP0(pDL)); if( !(0 < cpBN_cmp(pT, cpBN_OneRef()) && 0 > cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pP,lenP)) ) { *pResult = ippDLInvalidGenerator; return ippStsNoErr; } } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpvalidatedsa.c000066400000000000000000000145071470420105600250700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (validate domain parameters) // // Contents: // ippsDLPValidateDSA() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /* // Name: DLPValidate // // Purpose: Validate DL Domain Parameters. // // Parameters: // nTrials number of trials of primality test // pResult pointer to the validation result // pDL pointer to the DL context // rndFunc external random generator // pRndParam pointer to the external random generator params */ static IppDLResult DLPValidate(int nTrials, IppsDLPState* pDL, IppBitSupplier rndFunc, void* pRndParam) { /* // validate DL parameters: // check that P is odd and P > 2 // check that R is odd and R > 2 // check that R | (P-1) // check that 1 < G < P // check that 1 == G^R (mod P) */ BNU_CHUNK_T* pP = DLP_P(pDL); BNU_CHUNK_T* pR = DLP_R(pDL); cpSize lenP = BITS_BNU_CHUNK(DLP_BITSIZEP(pDL)); cpSize lenR = BITS_BNU_CHUNK(DLP_BITSIZER(pDL)); IppsPrimeState* pPrimeCtx = DLP_PRIMEGEN(pDL); /* allocate BN resources */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pTmp = cpBigNumListGet(&pList); BNU_CHUNK_T* pT = BN_NUMBER(pTmp); /* P is odd and prime */ if(0 == (pP[0] & 1)) return ippDLBaseIsEven; if(0==cpPrimeTest(pP, lenP, nTrials, pPrimeCtx, rndFunc,pRndParam)) return ippDLCompositeBase; /* R is odd and prime */ if(0 == (pR[0] & 1)) return ippDLOrderIsEven; if(0==cpPrimeTest(pR, lenR, nTrials, pPrimeCtx, rndFunc,pRndParam)) return ippDLCompositeOrder; /* R|(P-1) */ cpDec_BNU(pT, pP, lenP, 1); cpMod_BNU(pT, lenP, pR, lenR); if(!cpEqu_BNU_CHUNK(pT, lenP, 0)) return ippDLInvalidCofactor; /* 1 < G < P */ cpMontDec_BN(pTmp, DLP_GENC(pDL), DLP_MONTP0(pDL)); if( 0>=cpBN_cmp(pTmp, cpBN_OneRef()) || cpCmp_BNU(pT, BN_SIZE(pTmp), DLP_P(pDL), lenP)>=0 ) return ippDLInvalidGenerator; /* G^R = 1 (mod P) */ cpMontExpBin_BNU(pT, BN_NUMBER(DLP_GENC(pDL)),lenP, pR, lenR, DLP_MONTP0(pDL) ); if( cpCmp_BNU(pT,lenP, MOD_MNT_R(DLP_MONTP0(pDL)), lenP) ) return ippDLInvalidGenerator; return ippDLValid; } /*F* // Name: ippsDLPValidateDSA // // Purpose: Validate DL (DSA) Domain Parameters. // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pResult // NULL == rndFunc // // ippStsContextMatchErr illegal pDL->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsBadArgErr nTrials <=0 // // ippStsNoErr no errors // // Parameters: // nTrials number of trials of primality test // pResult pointer to the validation result // pDL pointer to the DL context // rndFunc external random generator // pRndParam pointer to the external random generator params *F*/ IPPFUN(IppStatus, ippsDLPValidateDSA,(int nTrials, IppDLResult* pResult, IppsDLPState* pDL, IppBitSupplier rndFunc, void* pRndParam)) { /* test DL context */ IPP_BAD_PTR1_RET(pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test operation flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test number of trials for primality check */ IPP_BADARG_RET(nTrials<=0, ippStsBadArgErr); /* test another pointers */ IPP_BAD_PTR2_RET(pResult, rndFunc); /* execute genetal DL validation */ *pResult = DLPValidate(nTrials, pDL, rndFunc, pRndParam); /* // DSA specific validation */ if(ippDLValid == *pResult) { /* allocate BN resources */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pT = cpBigNumListGet(&pList); BNU_CHUNK_T* pP = DLP_P(pDL); BNU_CHUNK_T* pR = DLP_R(pDL); cpSize feBitSize = DLP_BITSIZEP(pDL); cpSize ordBitSize= DLP_BITSIZER(pDL); cpSize lenP = BITS_BNU_CHUNK(feBitSize); cpSize lenR = BITS_BNU_CHUNK(ordBitSize); /* 512 <= DLP_BITSIZEP() <= 1024, 64|DLP_BITSIZEP() */ if( (MIN_DLPDSA_BITSIZE > feBitSize) || (MAX_DLPDSA_BITSIZE < feBitSize) || (feBitSize % 64) ) { *pResult = ippDLInvalidBaseRange; return ippStsNoErr; } /* 2^(DLP_BITSIZEP()-1) < P < 2^DLP_BITSIZEP() */ cpBN_power2(pT, feBitSize-1); if( 0<=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pP,lenP) ) { *pResult = ippDLInvalidBaseRange; return ippStsNoErr; } cpBN_power2(pT, feBitSize); if( 0>=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pP,lenP) ) { *pResult = ippDLInvalidBaseRange; return ippStsNoErr; } /* DLP_BITSIZER() == 160 */ if( (DEF_DLPDSA_BITSIZER != ordBitSize) ) { *pResult = ippDLInvalidOrderRange; return ippStsNoErr; } /* 2^(DLP_BITSIZER()-1) < R < 2^DLP_BITSIZER() */ cpBN_power2(pT, ordBitSize-1); if( 0<=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pR,lenR) ) { *pResult = ippDLInvalidOrderRange; return ippStsNoErr; } cpBN_power2(pT, ordBitSize); if( 0>=cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pR,lenR) ) { *pResult = ippDLInvalidOrderRange; return ippStsNoErr; } /* 1 < G < (P-1) */ cpMontDec_BN(pT, DLP_GENC(pDL), DLP_MONTP0(pDL)); if( !(0 < cpBN_cmp(pT, cpBN_OneRef()) && 0 > cpCmp_BNU(BN_NUMBER(pT),BN_SIZE(pT), pP,lenP)) ) { *pResult = ippDLInvalidGenerator; return ippStsNoErr; } } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpvalidatekeypair.c000066400000000000000000000104461470420105600257630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (EC Key Generation, Validation and Set Up) // // Contents: // ippsDLPValidateKeyPair() // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDLPValidateKeyPair // // Purpose: Validate DL Key Pair // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pPrvKey // NULL == pPubKey // // ippStsContextMatchErr invalid pDL->idCtx // invalid pPrvKey->idCtx // invalid pPubKey->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsNoErr no error // // Parameters: // pPrvKey pointer to the private key // pPubKey pointer to the public key // pResult pointer to the result: ippDLValid/ // ippDLInvalidPrivateKey/ippDLInvalidPublicKey/ // ippDLInvalidKeyPair // pDL pointer to the DL context *F*/ IPPFUN(IppStatus, ippsDLPValidateKeyPair,(const IppsBigNumState* pPrvKey, const IppsBigNumState* pPubKey, IppDLResult* pResult, IppsDLPState* pDL)) { /* test DL context */ IPP_BAD_PTR2_RET(pResult, pDL); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); { /* allocate BN resources */ BigNumNode* pList = DLP_BNCTX(pDL); IppsBigNumState* pTmp = cpBigNumListGet(&pList); BNU_CHUNK_T* pT = BN_NUMBER(pTmp); /* assume keys are OK */ *pResult = ippDLValid; /* private key validation request */ if(pPrvKey) { cpSize lenR = BITS_BNU_CHUNK(DLP_BITSIZER(pDL)); IPP_BADARG_RET(!BN_VALID_ID(pPrvKey), ippStsContextMatchErr); /* test private key: 1 < pPrvKey < (R-1) */ cpDec_BNU(pT, DLP_R(pDL),lenR, 1); if( 0>=cpBN_cmp(pPrvKey, cpBN_OneRef()) || cpCmp_BNU(BN_NUMBER(pPrvKey),BN_SIZE(pPrvKey), pT,lenR)>=0 ) { *pResult = ippDLInvalidPrivateKey; return ippStsNoErr; } } /* public key validation request */ if(pPubKey) { cpSize lenP = BITS_BNU_CHUNK(DLP_BITSIZEP(pDL)); IPP_BADARG_RET(!BN_VALID_ID(pPubKey), ippStsContextMatchErr); /* test public key: 1 < pPubKey < (P-1) */ cpDec_BNU(pT, DLP_P(pDL),lenP, 1); if( 0>=cpBN_cmp(pPubKey, cpBN_OneRef()) || cpCmp_BNU(BN_NUMBER(pPubKey),BN_SIZE(pPubKey), pT,lenP)>=0 ) { *pResult = ippDLInvalidPublicKey; return ippStsNoErr; } /* addition test: pPubKey = G^pPrvKey (mod P) */ if(pPrvKey) { int ordLen = MOD_LEN( DLP_MONTR(pDL) ); IppsBigNumState* pTmpPrivate = cpBigNumListGet(&pList); ZEXPAND_COPY_BNU(BN_NUMBER(pTmpPrivate), ordLen, BN_NUMBER(pPrvKey), BN_SIZE(pPrvKey)); BN_SIZE(pTmpPrivate) = ordLen; /* recompute public key */ cpMontExpBin_BN_sscm(pTmp, DLP_GENC(pDL), pTmpPrivate, DLP_MONTP0(pDL)); cpMontDec_BN(pTmp, pTmp, DLP_MONTP0(pDL)); /* and compare */ if( cpBN_cmp(pTmp, pPubKey) ) { *pResult = ippDLInvalidKeyPair; return ippStsNoErr; } } } } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpdlpverifydsaca.c000066400000000000000000000142041470420105600251010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Finite Field (Verify, DSA version) // // Contents: // ippsDLPVerifyDSA() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" /*F* // Name: ippsDLPVerifyDSA // // Purpose: Verify Signature (DSA version) // // Returns: Reason: // ippStsNullPtrErr NULL == pDL // NULL == pMsgDigest // NULL == pSignR // NULL == pSignS // NULL == pResult // // ippStsContextMatchErr illegal pDL->idCtx // illegal pMsgDigest->idCtx // illegal pSignR->idCtx // illegal pSignS->idCtx // // ippStsIncompleteContextErr // incomplete context // // ippStsMessageErr MsgDigest >= R // MsgDigest < 0 // // ippStsNoErr no errors // // Parameters: // pMsgDigest pointer to the message representative to be signed // pSignR,pSignS pointer to the signature // pResult pointer to the result: IppSignIsValid/IppSignIsInvalid // pDSA pointer to the DL context // // Primitive sequence call: // 1) set up domain parameters // 2) set up (signatory's) public key *F*/ IPPFUN(IppStatus, ippsDLPVerifyDSA,(const IppsBigNumState* pMsgDigest, const IppsBigNumState* pSignR, const IppsBigNumState* pSignS, IppDLResult* pResult, IppsDLPState* pDL)) { /* test context*/ IPP_BAD_PTR2_RET(pDL,pResult); IPP_BADARG_RET(!DLP_VALID_ID(pDL), ippStsContextMatchErr); /* test operation flag */ IPP_BADARG_RET(!DLP_COMPLETE(pDL), ippStsIncompleteContextErr); /* test message representative */ IPP_BAD_PTR1_RET(pMsgDigest); IPP_BADARG_RET(!BN_VALID_ID(pMsgDigest), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pMsgDigest), ippStsMessageErr); /* test signature */ IPP_BAD_PTR2_RET(pSignR,pSignS); IPP_BADARG_RET(!BN_VALID_ID(pSignR), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pSignS), ippStsContextMatchErr); /* test signature range */ if(0idCtx = (Ipp32u)idCtxHMAC ^ (Ipp32u)IPP_UINT_PTR(stt)) #define HMAC_RESET_CTX_ID(stt) ((stt)->idCtx = idCtxHMAC) #define HASH_CTX(stt) ((stt)->hashCtx) #define HMAC_VALID_ID(stt) ((((stt)->idCtx) ^ (Ipp32u)IPP_INT_PTR((stt))) == (Ipp32u)idCtxHMAC) #define IPAD (0x36) /* inner padding value */ #define OPAD (0x5C) /* outer padding value */ #endif /* _PCP_HMAC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcphmac_duplicate.c000066400000000000000000000040541470420105600250450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Duplicate() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Duplicate // // Purpose: Clone HMAC state. // // Returns: Reason: // ippStsNullPtrErr pSrcState == NULL // pDstState == NULL // ippStsContextMatchErr pSrcState->idCtx != idCtxHMAC // pDstState->idCtx != idCtxHMAC // ippStsNoErr no errors // // Parameters: // pSrcState pointer to the source HMAC state // pDstState pointer to the target HMAC state // // Note: // pDstState may not to be initialized by ippsHMACInit() // *F*/ IPPFUN(IppStatus, ippsHMAC_Duplicate,(const IppsHMACState* pSrcCtx, IppsHMACState* pDstCtx)) { /* test state pointers */ IPP_BAD_PTR2_RET(pSrcCtx, pDstCtx); /* test states ID */ IPP_BADARG_RET(!HMAC_VALID_ID(pSrcCtx), ippStsContextMatchErr); /* copy HMAC state without Hash context */ CopyBlock(pSrcCtx, pDstCtx, (int)(IPP_UINT_PTR(&HASH_CTX(pSrcCtx)) - IPP_UINT_PTR(pSrcCtx))); HMAC_SET_CTX_ID(pDstCtx); /* copy Hash context separately */ ippsHashDuplicate(&HASH_CTX(pSrcCtx), &HASH_CTX(pDstCtx)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_final.c000066400000000000000000000051761470420105600241720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Final() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Final // // Purpose: Stop message digesting and return digest. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHMAC // ippStsLengthErr sizeof(DigestMD5) < mdLen <1 // ippStsNoErr no errors // // Parameters: // pMD address of the output digest // pState pointer to the HMAC state // *F*/ IPPFUN(IppStatus, ippsHMAC_Final,(Ipp8u* pMD, int mdLen, IppsHMACState* pCtx)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); /* test MD pointer and length */ IPP_BAD_PTR1_RET(pMD); IPP_BADARG_RET(mdLen<=0, ippStsLengthErr); { /* hash specific */ IppsHashState* pHashCtx = &HASH_CTX(pCtx); int mbs = cpHashMBS(HASH_ALG_ID(pHashCtx)); int hashSize = cpHashSize(HASH_ALG_ID(pHashCtx)); if(mdLen>hashSize) IPP_ERROR_RET(ippStsLengthErr); /* // finalize hmac */ { /* finalize 1-st step */ Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/8]; IppStatus sts = ippsHashFinal(md, pHashCtx); if(ippStsNoErr==sts) { /* perform outer hash */ ippsHashUpdate(pCtx->opadKey, mbs, pHashCtx); ippsHashUpdate(md, hashSize, pHashCtx); /* complete HMAC */ ippsHashFinal(md, pHashCtx); CopyBlock(md, pMD, IPP_MIN(hashSize, mdLen)); /* ready to the next HMAC computation */ ippsHashUpdate(pCtx->ipadKey, mbs, pHashCtx); } return sts; } } } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_getsize.c000066400000000000000000000026221470420105600245440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_GetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_GetSize // // Purpose: Returns size of HMAC state (bytes). // // Returns: Reason: // ippStsNullPtrErr pSzie == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to the HMAC state size // *F*/ IPPFUN(IppStatus, ippsHMAC_GetSize,(int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsHMACState); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_gettag.c000066400000000000000000000040001470420105600243350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_GetTag() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_GetTag // // Purpose: Compute digest with further digesting ability. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHMAC // ippStsLengthErr size_of_digest < mdLen <1 // ippStsNoErr no errors // // Parameters: // pMD address of the output digest // mdLen length of the digest // pState pointer to the HMAC state // *F*/ IPPFUN(IppStatus, ippsHMAC_GetTag,(Ipp8u* pMD, int mdLen, const IppsHMACState* pCtx)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); /* test MD pointer */ IPP_BAD_PTR1_RET(pMD); { /* TBD: consider implementation without copy of context */ IppStatus sts; IppsHMACState tmpCtx; ippsHMAC_Duplicate(pCtx, &tmpCtx); sts = ippsHMAC_Final(pMD, mdLen, &tmpCtx); PurgeBlock(&tmpCtx, sizeof(IppsHMACState)); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_init.c000066400000000000000000000064131470420105600240370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Init() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Init // // Purpose: Init HMAC state. // // Returns: Reason: // ippStsNullPtrErr pKey == NULL // pState == NULL // ippStsLengthErr keyLen <0 // ippStsNotSupportedModeErr if algID is not match to supported hash alg // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length (bytes) of the secret key // pState pointer to the HMAC state // hashAlg hash alg ID // *F*/ IPPFUN(IppStatus, ippsHMAC_Init,(const Ipp8u* pKey, int keyLen, IppsHMACState* pCtx, IppHashAlgId hashAlg)) { //int mbs; /* get algorithm id */ hashAlg = cpValidHashAlg(hashAlg); /* test hash alg */ IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); //mbs = cpHashMBS(hashAlg); /* test pState pointer */ IPP_BAD_PTR1_RET(pCtx); /* test key pointer and key length */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(0>keyLen, ippStsLengthErr); /* set state ID */ HMAC_SET_CTX_ID(pCtx); /* init hash context */ ippsHashInit(&HASH_CTX(pCtx), hashAlg); { int n; /* hash specific */ IppsHashState* pHashCtx = &HASH_CTX(pCtx); int mbs = cpHashMBS(hashAlg); int hashSize = cpHashSize(hashAlg); /* copyMask = keyLen>mbs? 0xFF : 0x00 */ int copyMask = (mbs-keyLen) >>(BITSIZE(int)-1); /* actualKeyLen = keyLen>mbs? hashSize:keyLen */ int actualKeyLen = (hashSize & copyMask) | (keyLen & ~copyMask); /* compute hash(key, keyLen) just in case */ ippsHashUpdate(pKey, keyLen, pHashCtx); ippsHashFinal(HASH_BUFF(pHashCtx), pHashCtx); /* copy either key or hash(key) into ipad- and opad- buffers */ MASKED_COPY_BNU(pCtx->ipadKey, (Ipp8u)copyMask, HASH_BUFF(pHashCtx), pKey, actualKeyLen); MASKED_COPY_BNU(pCtx->opadKey, (Ipp8u)copyMask, HASH_BUFF(pHashCtx), pKey, actualKeyLen); /* XOR-ing key */ for(n=0; nipadKey[n] ^= (Ipp8u)IPAD; pCtx->opadKey[n] ^= (Ipp8u)OPAD; } for(; nipadKey[n] = (Ipp8u)IPAD; pCtx->opadKey[n] = (Ipp8u)OPAD; } /* ipad key processing */ ippsHashUpdate(pCtx->ipadKey, mbs, pHashCtx); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_message.c000066400000000000000000000056511470420105600245230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Message() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Message // // Purpose: MAC (MD5) of the whole message. // // Returns: Reason: // ippStsNullPtrErr pMsg == NULL // pKey == NULL // pMD == NULL // ippStsLengthErr msgLen <0 // keyLen <0 // size_of_digest < mdLen <1 // ippStsNotSupportedModeErr if algID is not match to supported hash alg // ippStsNoErr no errors // // Parameters: // pMsg pointer to the input message // msgLen input message length // pKey pointer to the secret key // keyLen secret key length // pMD pointer to message digest // mdLen MD length // hashAlg hash alg ID // *F*/ IPPFUN(IppStatus, ippsHMAC_Message,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pKey, int keyLen, Ipp8u* pMD, int mdLen, IppHashAlgId hashAlg)) { /* get algorithm id */ hashAlg = cpValidHashAlg(hashAlg); /* test hash alg */ IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); /* test secret key pointer and length */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET((keyLen<0), ippStsLengthErr); /* test input message pointer and length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); /* test MD pointer and length */ IPP_BAD_PTR1_RET(pMD); IPP_BADARG_RET(0>=mdLen || mdLen>cpHashSize(hashAlg), ippStsLengthErr); { __ALIGN8 IppsHMACState ctx; IppStatus sts = ippsHMAC_Init(pKey, keyLen, &ctx, hashAlg); if(ippStsNoErr!=sts) goto exit; sts = ippsHashUpdate(pMsg,msgLen, &HASH_CTX(&ctx)); if(ippStsNoErr!=sts) goto exit; sts = ippsHMAC_Final(pMD, mdLen, &ctx); exit: PurgeBlock(&ctx, sizeof(IppsHMACState)); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_pack.c000066400000000000000000000042021470420105600240040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Pack() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Pack // // Purpose: Copy initialized context to the buffer. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer keyed hash state // pBuffer pointer to the destination buffer // bufSize size of destination buffer // *F*/ IPPFUN(IppStatus, ippsHMAC_Pack,(const IppsHMACState* pCtx, Ipp8u* pBuffer, int bufSize)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); /* test the context */ IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); { int ctxSize; ippsHMAC_GetSize(&ctxSize); /* test buffer length */ IPP_BADARG_RET(ctxSize>bufSize, ippStsNoMemErr); CopyBlock(pCtx, pBuffer, ctxSize); /* Reset IppsHMACState context id */ IppsHMACState* pCopy = (IppsHMACState*)pBuffer; HMAC_RESET_CTX_ID(pCopy); /* Reset context id for IppsHashState, which is the part of IppsHMACState */ IppsHashState* pHashCopy = (IppsHashState*)&HASH_CTX(pCopy); HASH_RESET_ID(pHashCopy,idCtxHash); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_rmf.h000066400000000000000000000024171470420105600236650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // Hash Message Authentication Code // Internal Definitions and Internal Functions Prototypes */ #if !defined(_PCP_HMAC_RMF_H) #define _PCP_HMAC_RMF_H #include "hash/pcphash_rmf.h" /* // HMAC context */ struct _cpHMAC_rmf { Ipp32u idCtx; /* HMAC identifier */ Ipp8u ipadKey[MBS_HASH_MAX]; /* inner padding key */ Ipp8u opadKey[MBS_HASH_MAX]; /* outer padding key */ IppsHashState_rmf hashCtx; /* hash context */ }; #endif /* _PCP_HMAC_RMF_H */ cryptography-primitives-1.0.0/sources/ippcp/pcphmac_unpack.c000066400000000000000000000033401470420105600243510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Unpack() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Unpack // // Purpose: Unpack buffer content into the initialized context. // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer keyed hash state // pSize pointer to the packed spec size // *F*/ IPPFUN(IppStatus, ippsHMAC_Unpack,(const Ipp8u* pBuffer, IppsHMACState* pCtx)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); CopyBlock(pBuffer, pCtx, sizeof(IppsHMACState)); /* Set IppsHMACState context id */ HMAC_SET_CTX_ID(pCtx); /* Set context id for IppsHashState, which is the part of IppsHMACState */ HASH_SET_ID(&HASH_CTX(pCtx),idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmac_update.c000066400000000000000000000036651470420105600243640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMAC_Update() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcptool.h" /*F* // Name: ippsHMAC_Update // // Purpose: Updates intermadiate MAC based on input stream. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHMAC // ippStsLengthErr len <0 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the input stream // len input stream length // pState pointer to the HMAC state // *F*/ IPPFUN(IppStatus, ippsHMAC_Update,(const Ipp8u* pSrc, int len, IppsHMACState* pCtx)) { /* test state pointers */ IPP_BAD_PTR1_RET(pCtx); /* test state ID */ IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); /* test input length */ IPP_BADARG_RET((len<0), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); if(len) return ippsHashUpdate(pSrc, len, &HASH_CTX(pCtx)); else return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmacca_rmf.c000066400000000000000000000061701470420105600241640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACInit_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACInit_rmf // // Purpose: Init HMAC state. // // Returns: Reason: // ippStsNullPtrErr pKey == NULL // pState == NULL // ippStsLengthErr keyLen <0 // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length (bytes) of the secret key // pState pointer to the HMAC state // pMethod hash method // *F*/ IPPFUN(IppStatus, ippsHMACInit_rmf,(const Ipp8u* pKey, int keyLen, IppsHMACState_rmf* pCtx, const IppsHashMethod* pMethod)) { /* test pointer */ IPP_BAD_PTR2_RET(pCtx, pMethod); /* test key pointer and key length */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(0>keyLen, ippStsLengthErr); /* set state ID */ HMAC_SET_CTX_ID(pCtx); /* init hash context */ ippsHashInit_rmf(&HASH_CTX(pCtx), pMethod); { int n; /* hash specific */ IppsHashState_rmf* pHashCtx = &HASH_CTX(pCtx); int mbs = pMethod->msgBlkSize; int hashSize = pMethod->hashLen; /* copyMask = keyLen>mbs? 0xFF : 0x00 */ int copyMask = (mbs-keyLen) >>(BITSIZE(int)-1); /* actualKeyLen = keyLen>mbs? hashSize:keyLen */ int actualKeyLen = (hashSize & copyMask) | (keyLen & ~copyMask); /* compute hash(key, keyLen) just in case */ ippsHashUpdate_rmf(pKey, keyLen, pHashCtx); ippsHashFinal_rmf(HASH_BUFF(pHashCtx), pHashCtx); /* copy either key or hash(key) into ipad- and opad- buffers */ MASKED_COPY_BNU(pCtx->ipadKey, (Ipp8u)copyMask, HASH_BUFF(pHashCtx), pKey, actualKeyLen); MASKED_COPY_BNU(pCtx->opadKey, (Ipp8u)copyMask, HASH_BUFF(pHashCtx), pKey, actualKeyLen); /* XOR-ing key */ for(n=0; nipadKey[n] ^= (Ipp8u)IPAD; pCtx->opadKey[n] ^= (Ipp8u)OPAD; } for(; nipadKey[n] = (Ipp8u)IPAD; pCtx->opadKey[n] = (Ipp8u)OPAD; } /* ipad key processing */ ippsHashUpdate_rmf(pCtx->ipadKey, mbs, pHashCtx); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmacduplicate_rmf.c000066400000000000000000000041361470420105600255530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACDuplicate_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACDuplicate_rmf // // Purpose: Clone HMAC state. // // Returns: Reason: // ippStsNullPtrErr pSrcState == NULL // pDstState == NULL // ippStsContextMatchErr pSrcState->idCtx != idCtxHMAC // pDstState->idCtx != idCtxHMAC // ippStsNoErr no errors // // Parameters: // pSrcState pointer to the source HMAC state // pDstState pointer to the target HMAC state // // Note: // pDstState may not to be initialized by ippsHMACInit_rmf() // *F*/ IPPFUN(IppStatus, ippsHMACDuplicate_rmf,(const IppsHMACState_rmf* pSrcCtx, IppsHMACState_rmf* pDstCtx)) { /* test state pointers */ IPP_BAD_PTR2_RET(pSrcCtx, pDstCtx); /* test states ID */ IPP_BADARG_RET(!HMAC_VALID_ID(pSrcCtx), ippStsContextMatchErr); /* copy HMAC state without Hash context */ CopyBlock(pSrcCtx, pDstCtx, (int)(IPP_UINT_PTR(&HASH_CTX(pSrcCtx)) - IPP_UINT_PTR(pSrcCtx))); HMAC_SET_CTX_ID(pDstCtx); /* copy Hash context separately */ ippsHashDuplicate_rmf(&HASH_CTX(pSrcCtx), &HASH_CTX(pDstCtx)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmacfinal_rmf.c000066400000000000000000000053301470420105600246670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACFinal_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACFinal_rmf // // Purpose: Stop message digesting and return digest. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHMAC // ippStsLengthErr sizeof(DigestMD5) < mdLen <1 // ippStsNoErr no errors // // Parameters: // pMD address of the output digest // pState pointer to the HMAC state // *F*/ IPPFUN(IppStatus, ippsHMACFinal_rmf,(Ipp8u* pMD, int mdLen, IppsHMACState_rmf* pCtx)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); /* test MD pointer and length */ IPP_BAD_PTR1_RET(pMD); IPP_BADARG_RET(mdLen<=0, ippStsLengthErr); { /* hash specific */ IppsHashState_rmf* pHashCtx = &HASH_CTX(pCtx); const IppsHashMethod* method = HASH_METHOD(pHashCtx); int mbs = method->msgBlkSize; int hashSize = method->hashLen; if(mdLen>hashSize) IPP_ERROR_RET(ippStsLengthErr); /* // finalize hmac */ { /* finalize 1-st step */ Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/8]; IppStatus sts = ippsHashFinal_rmf(md, pHashCtx); if(ippStsNoErr==sts) { /* perform outer hash */ ippsHashUpdate_rmf(pCtx->opadKey, mbs, pHashCtx); ippsHashUpdate_rmf(md, hashSize, pHashCtx); /* complete HMAC */ ippsHashFinal_rmf(md, pHashCtx); CopyBlock(md, pMD, IPP_MIN(hashSize, mdLen)); /* ready to the next HMAC computation */ ippsHashUpdate_rmf(pCtx->ipadKey, mbs, pHashCtx); } return sts; } } } cryptography-primitives-1.0.0/sources/ippcp/pcphmacgetsize_rmf.c000066400000000000000000000026701470420105600252540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACGetSize_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACGetSize_rmf // // Purpose: Returns size of HMAC state (bytes). // // Returns: Reason: // ippStsNullPtrErr pSzie == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to the HMAC state size // *F*/ IPPFUN(IppStatus, ippsHMACGetSize_rmf,(int* pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsHMACState_rmf); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmacgettag_rmf.c000066400000000000000000000040651470420105600250550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACGetTag_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACGetTag_rmf // // Purpose: Compute digest with further digesting ability. // // Returns: Reason: // ippStsNullPtrErr pMD == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHMAC // ippStsLengthErr size_of_digest < mdLen <1 // ippStsNoErr no errors // // Parameters: // pMD address of the output digest // mdLen length of the digest // pState pointer to the HMAC state // *F*/ IPPFUN(IppStatus, ippsHMACGetTag_rmf,(Ipp8u* pMD, int mdLen, const IppsHMACState_rmf* pCtx)) { /* test state pointer and ID */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); /* test MD pointer */ IPP_BAD_PTR1_RET(pMD); { /* TBD: consider implementation without copy of context */ IppStatus sts; IppsHMACState_rmf tmpCtx; ippsHMACDuplicate_rmf(pCtx, &tmpCtx); sts = ippsHMACFinal_rmf(pMD, mdLen, &tmpCtx); PurgeBlock(&tmpCtx, sizeof(IppsHMACState_rmf)); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmacmessage_rmf.c000066400000000000000000000055461470420105600252330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACMessage_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACMessage_rmf // // Purpose: MAC (MD5) of the whole message. // // Returns: Reason: // ippStsNullPtrErr pMsg == NULL // pKey == NULL // pMD == NULL // ippStsLengthErr msgLen <0 // keyLen <0 // size_of_digest < mdLen <1 // ippStsNotSupportedModeErr if algID is not match to supported hash alg // ippStsNoErr no errors // // Parameters: // pMsg pointer to the input message // msgLen input message length // pKey pointer to the secret key // keyLen secret key length // pMD pointer to message digest // mdLen MD length // pMethod hash method // *F*/ IPPFUN(IppStatus, ippsHMACMessage_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pKey, int keyLen, Ipp8u* pMD, int mdLen, const IppsHashMethod* pMethod)) { /* test method pointer */ IPP_BAD_PTR1_RET(pMethod); /* test secret key pointer and length */ IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET((keyLen<0), ippStsLengthErr); /* test input message pointer and length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); /* test MD pointer and length */ IPP_BAD_PTR1_RET(pMD); IPP_BADARG_RET(0>=mdLen || mdLen>pMethod->hashLen, ippStsLengthErr); { __ALIGN8 IppsHMACState_rmf ctx; IppStatus sts; ippsHMACInit_rmf(pKey, keyLen, &ctx, pMethod); sts = ippsHashUpdate_rmf(pMsg,msgLen, &HASH_CTX(&ctx)); if(ippStsNoErr!=sts) goto exit; sts = ippsHMACFinal_rmf(pMD, mdLen, &ctx); exit: PurgeBlock(&ctx, sizeof(IppsHMACState_rmf)); return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmacpack_rmf.c000066400000000000000000000043111470420105600245120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACPack_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACPack_rmf // // Purpose: Copy initialized context to the buffer. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pBuffer == NULL // ippStsNoErr no errors // // Parameters: // pCtx pointer keyed hash state // pBuffer pointer to the destination buffer // bufSize size of destination buffer // *F*/ IPPFUN(IppStatus, ippsHMACPack_rmf,(const IppsHMACState_rmf* pCtx, Ipp8u* pBuffer, int bufSize)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); /* test the context */ IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); { int ctxSize; ippsHMACGetSize_rmf(&ctxSize); /* test buffer length */ IPP_BADARG_RET(ctxSize>bufSize, ippStsNoMemErr); CopyBlock(pCtx, pBuffer, ctxSize); /* Reset IppsHMACState_rmf context id */ IppsHMACState_rmf* pCopy = (IppsHMACState_rmf*)pBuffer; HMAC_RESET_CTX_ID(pCopy); /* Reset context id for IppsHashState_rmf, which is the part of IppsHMACState_rmf */ IppsHashState_rmf* pHashCopy = (IppsHashState_rmf*)&HASH_CTX(pCopy); HASH_RESET_ID(pHashCopy,idCtxHash); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcphmacunpack_rmf.c000066400000000000000000000034361470420105600250640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACUnpack_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACUnpack_rmf // // Purpose: Unpack buffer content into the initialized context. // // Returns: Reason: // ippStsNullPtrErr pBuffer == NULL // pCtx == NULL // ippStsNoErr no errors // // Parameters: // pBuffer pointer to the source buffer // pSize pointer to the packed spec size // *F*/ IPPFUN(IppStatus, ippsHMACUnpack_rmf,(const Ipp8u* pBuffer, IppsHMACState_rmf* pCtx)) { /* test pointers */ IPP_BAD_PTR2_RET(pCtx, pBuffer); CopyBlock(pBuffer, pCtx, sizeof(IppsHMACState_rmf)); /* Set IppsHMACState_rmf context id */ HMAC_SET_CTX_ID(pCtx); /* Set context id for IppsHashState_rmf, which is the part of IppsHMACState_rmf */ HASH_SET_ID(&HASH_CTX(pCtx),idCtxHash); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcphmacupdate_rmf.c000066400000000000000000000037371470420105600250710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HMAC General Functionality // // Contents: // ippsHMACUpdate_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcphmac.h" #include "pcphmac_rmf.h" #include "pcptool.h" /*F* // Name: ippsHMACUpdate_rmf // // Purpose: Updates intermadiate MAC based on input stream. // // Returns: Reason: // ippStsNullPtrErr pSrc == NULL // pState == NULL // ippStsContextMatchErr pState->idCtx != idCtxHMAC // ippStsLengthErr len <0 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the input stream // len input stream length // pState pointer to the HMAC state // *F*/ IPPFUN(IppStatus, ippsHMACUpdate_rmf,(const Ipp8u* pSrc, int len, IppsHMACState_rmf* pCtx)) { /* test state pointers */ IPP_BAD_PTR1_RET(pCtx); /* test state ID */ IPP_BADARG_RET(!HMAC_VALID_ID(pCtx), ippStsContextMatchErr); /* test input length */ IPP_BADARG_RET((len<0), ippStsLengthErr); /* test source pointer */ IPP_BADARG_RET((len && !pSrc), ippStsNullPtrErr); if(len) return ippsHashUpdate_rmf(pSrc, len, &HASH_CTX(pCtx)); else return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpmask_ct.h000066400000000000000000000111561470420105600235320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2018 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Constant time Mask operations // // */ #if !defined(_PCP_MASK_CT_H) #define _PCP_MASK_CT_H #include "owncp.h" #include "pcpbnuimpl.h" /* // The following functions test particular conditions // and returns either 0 or 0xffffffff. // // The result is suitable for boolean and masked operations. // // In spite of operation below are using BNU_CHUNK_T operand(s) it can be applied to Ipp32u, Ipp32s, Ipp16u, Ipp16s, Ipp8u and Ipp8s too. // For example, if // Ipp32u uns_int; // Ipp32s sgn_int; // Ipp8u uns_char; // Ipp8s sgn_char; // then // cpIs_msb_ct((Ipp32s)uns_int) tests 31 bit of uns_int // cpIs_msb_ct( sgn_int) tests 31 bit of sgn_int // cpIs_msb_ct((Ipp8u)uns_char) tests 7 bit of uns_char // cpIs_msb_ct( sgn_char) tests 7 bit of sgn_char */ /* Disable optimization for Clang compiler to produce constant execution time code */ #if defined( __clang__ ) && !defined (__INTEL_COMPILER) /* Disable optimization for _px, _w7, _s8 (ia32) and _px, _m7 and _n8 (intel64) code branches */ #if !((_IPP>_IPP_S8) || (_IPP32E>_IPP32E_N8)) #pragma clang optimize off #endif #endif /* replace under mask: dst[] = replaceFlag? src[] : dst[] */ __IPPCP_INLINE void cpMaskedReplace_ct(BNU_CHUNK_T* dst, const BNU_CHUNK_T* src, int len, BNU_CHUNK_T replaceMask) { int n; for(n=0; n> (sizeof(a) * 8 - 1)); } /* tests if LSB(a)==1 */ __IPPCP_INLINE BNU_CHUNK_T cpIsLsb_ct(BNU_CHUNK_T a) { return (BNU_CHUNK_T)0 - (a & 1); } /* tests if a is odd */ __IPPCP_INLINE BNU_CHUNK_T cpIsOdd_ct(BNU_CHUNK_T a) { return cpIsLsb_ct(a); } /* tests if a is even */ __IPPCP_INLINE BNU_CHUNK_T cpIsEven_ct(BNU_CHUNK_T a) { return ~cpIsLsb_ct(a); } /* tests if a==0 */ __IPPCP_INLINE BNU_CHUNK_T cpIsZero_ct(BNU_CHUNK_T a) { return cpIsMsb_ct(~a & (a - 1)); } /* tests if a==b */ __IPPCP_INLINE BNU_CHUNK_T cpIsEqu_ct(BNU_CHUNK_T a, BNU_CHUNK_T b) { return cpIsZero_ct(a ^ b); } /* test if a_IPP_S8) || (_IPP32E>_IPP32E_N8)) #pragma clang optimize on #endif #endif #endif /* _PCP_MASK_CT_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpmgf1ca_rmf.c000066400000000000000000000057251470420105600241130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // HASH based Mask Generation Functions // // Contents: // ippsMGF1_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsMGF1 // // Purpose: Mask Generation Function. // // Returns: Reason: // ippStsNullPtrErr pMask == NULL // pMethod ==NULL // ippStsLengthErr seedLen <0 // maskLen <0 // ippStsNoErr no errors // // Parameters: // pSeed pointer to the input stream // seedLen input stream length (bytes) // pMaske pointer to the output mask // maskLen desired length of mask (bytes) // pMethod hash method // // // Note. // MGF1 defined in the IEEE P1363 standard. // MGF1 defined in the ANSI X9.63 standard and frequently called KDF (key Generation Function). // The fifference between MGF1 and MGF2 is negligible - counter i runs from 0 (in MGF1) and from 1 (in MGF2) *F*/ IPPFUN(IppStatus, ippsMGF1_rmf,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, const IppsHashMethod* pMethod)) { IPP_BAD_PTR2_RET(pMask, pMethod); IPP_BADARG_RET((seedLen<0)||(maskLen<0), ippStsLengthErr); { /* hash specific */ int hashSize = pMethod->hashLen; int i, outLen; __ALIGN8 IppsHashState_rmf hashCtx; ippsHashInit_rmf(&hashCtx, pMethod); if(!pSeed) seedLen = 0; for(i=0,outLen=0; outLen>24) & 0xFF); cnt[1] = (Ipp8u)((i>>16) & 0xFF); cnt[2] = (Ipp8u)((i>>8) & 0xFF); cnt[3] = (Ipp8u)(i & 0xFF); ippsHashUpdate_rmf(pSeed, seedLen, &hashCtx); ippsHashUpdate_rmf(cnt, 4, &hashCtx); if((outLen + hashSize) <= maskLen) { ippsHashFinal_rmf(pMask+outLen, &hashCtx); outLen += hashSize; } else { Ipp8u md[MAX_HASH_SIZE]; ippsHashFinal_rmf(md, &hashCtx); CopyBlock(md, pMask+outLen, maskLen-outLen); outLen = maskLen; } } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmgf2ca_rmf.c000066400000000000000000000057261470420105600241150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // HASH based Mask Generation Functions // // Contents: // ippsMGF2_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" /*F* // Name: ippsMGF2 // // Purpose: Mask Generation Function. // // Returns: Reason: // ippStsNullPtrErr pMask == NULL // pMethod ==NULL // ippStsLengthErr seedLen <0 // maskLen <0 // ippStsNoErr no errors // // Parameters: // pSeed pointer to the input stream // seedLen input stream length (bytes) // pMaske pointer to the output mask // maskLen desired length of mask (bytes) // pMethod hash method // // // Note. // MGF1 defined in the IEEE P1363 standard. // MGF1 defined in the ANSI X9.63 standard and frequently called KDF (key Generation Function). // The fifference between MGF1 and MGF2 is negligible - counter i runs from 0 (in MGF1) and from 1 (in MGF2) *F*/ IPPFUN(IppStatus, ippsMGF2_rmf,(const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, const IppsHashMethod* pMethod)) { IPP_BAD_PTR2_RET(pMask, pMethod); IPP_BADARG_RET((seedLen<0)||(maskLen<0), ippStsLengthErr); { /* hash specific */ int hashSize = pMethod->hashLen; int i, outLen; __ALIGN8 IppsHashState_rmf hashCtx; ippsHashInit_rmf(&hashCtx, pMethod); if(!pSeed) seedLen = 0; for(i=1,outLen=0; outLen>24) & 0xFF); cnt[1] = (Ipp8u)((i>>16) & 0xFF); cnt[2] = (Ipp8u)((i>>8) & 0xFF); cnt[3] = (Ipp8u)(i & 0xFF); ippsHashUpdate_rmf(pSeed, seedLen, &hashCtx); ippsHashUpdate_rmf(cnt, 4, &hashCtx); if((outLen + hashSize) <= maskLen) { ippsHashFinal_rmf(pMask+outLen, &hashCtx); outLen += hashSize; } else { Ipp8u md[MAX_HASH_SIZE]; ippsHashFinal_rmf(md, &hashCtx); CopyBlock(md, pMask+outLen, maskLen-outLen); outLen = maskLen; } } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_exp_bufsize.h000066400000000000000000000033711470420105600254710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // DL over Prime Field // */ #include "owndefs.h" #include "owncp.h" #include "pcpdlp.h" #include "pcptool.h" /* // Size of scratch buffer, involved in MontExp operation // // nExponents - number of exponents // expBitSize - (max) sizeof exponent (in bits) // modulusBitSize - size of modulus (bits) */ static cpSize cpMontExpScratchBufferSize(cpSize modulusBitSize, cpSize expBitSize, cpSize nExponents) { /* sizeof table element */ cpSize elmDataSize = BITS_BNU_CHUNK(modulusBitSize) * (Ipp32s)sizeof(BNU_CHUNK_T); /* get window_size */ cpSize w = (nExponents == 1) ? cpMontExp_WinSize(expBitSize) : /* use optimal window size, if single-scalar operation */ nExponents; /* or pseudo-oprimal if multi-scalar operation */ /* number of table entries */ cpSize nPrecomputed = 1 << w; cpSize bufferSize = elmDataSize*nPrecomputed + (CACHE_LINE_SIZE - 1); return bufferSize; }cryptography-primitives-1.0.0/sources/ippcp/pcpmont_expbinbnu.c000066400000000000000000000072041470420105600251320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Modular Exponentiation (binary version) // // Contents: // cpMontExpBin_BNU() */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" /*F* // Name: cpMontExpBin_BNU // // Purpose: computes the Montgomery exponentiation with exponent // BNU_CHUNK_T *dataE to the given big number integer of Montgomery form // BNU_CHUNK_T *dataX with respect to the modulus gsModEngine *pModEngine. // // Returns: // Length of modulus // // // Parameters: // dataX big number integer of Montgomery form within the // range [0,m-1] // dataE big number exponent // pModEngine Montgomery modulus of IppsMontState. / dataY the Montgomery exponentiation result. // // Notes: IppsBigNumState *r should possess enough memory space as to hold the result // of the operation. i.e. both pointers r->d and r->buffer should possess // no less than (m->n->length) number of 32-bit words. *F*/ IPP_OWN_DEFN (cpSize, cpMontExpBin_BNU, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nsE, gsModEngine* pModEngine)) { cpSize nsM = MOD_LEN( pModEngine ); /* // test for special cases: // x^0 = 1 // 0^e = 0 */ if( cpEqu_BNU_CHUNK(dataE, nsE, 0) ) { COPY_BNU(dataY, MOD_MNT_R( pModEngine ), nsM); } else if( cpEqu_BNU_CHUNK(dataX, nsX, 0) ) { ZEXPAND_BNU(dataY, 0, nsM); } /* general case */ else { /* Montgomery engine buffers */ const int usedPoolLen = 1; BNU_CHUNK_T* dataT = gsModPoolAlloc(pModEngine, usedPoolLen); if(NULL == dataT) return -1; { /* execute most significant part pE */ BNU_CHUNK_T eValue = dataE[nsE-1]; int n = cpNLZ_BNU(eValue)+1; /* expand base and init result */ ZEXPAND_COPY_BNU(dataT, nsM, dataX, nsX); COPY_BNU(dataY, dataT, nsM); eValue <<= n; for(; nsqr(dataY, dataY, pModEngine); /* and multiply R = R*X mod Modulus */ if(eValue & ((BNU_CHUNK_T)1<<(BNU_CHUNK_BITS-1))) MOD_METHOD( pModEngine )->mul(dataY, dataY, dataT, pModEngine); } /* execute rest bits of E */ for(--nsE; nsE>0; nsE--) { eValue = dataE[nsE-1]; for(n=0; nsqr(dataY, dataY, pModEngine); if(eValue & ((BNU_CHUNK_T)1<<(BNU_CHUNK_BITS-1))) MOD_METHOD( pModEngine )->mul(dataY, dataY, dataT, pModEngine); } } } gsModPoolFree(pModEngine, usedPoolLen); } return nsM; } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_expbinbnu_sscm.c000066400000000000000000000066331470420105600261640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Intel(R) Cryptography Primitives Library // Modular Exponentiation (binary version) // // Contents: // cpMontExpBin_BNU_sscm() */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcpmask_ct.h" #if defined(_USE_IPP_OWN_CBA_MITIGATION_) /* // The reason was to mitigate "cache monitoring" attack on RSA // // This is improved version of modular exponentiation. // Current version provide both either mitigation and performance. // */ /*F* // Name: cpMontExpBin_BNU_sscm // // Purpose: computes the Montgomery exponentiation with exponent // BNU_CHUNK_T *dataE to the given big number integer of Montgomery form // BNU_CHUNK_T *dataX with respect to the modulus gsModEngine *pModEngine. // // Returns: // Length of modulus // // // Parameters: // dataX big number integer of Montgomery form within the // range [0,m-1] // dataE big number exponent // pMont Montgomery modulus of IppsMontState. / dataY the Montgomery exponentiation result. // *F*/ IPP_OWN_DEFN (cpSize, cpMontExpBin_BNU_sscm, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nsE, gsModEngine* pMont)) { cpSize nsM = MOD_LEN(pMont); /* // test for special cases: // x^0 = 1 // 0^e = 0 */ if( cpIsGFpElemEquChunk_ct(dataE, nsE, 0) ) { COPY_BNU(dataY, MOD_MNT_R(pMont), nsM); } else if( cpIsGFpElemEquChunk_ct(dataX, nsX, 0) ) { ZEXPAND_BNU(dataY, 0, nsM); } /* general case */ else { /* Montgomery engine buffers */ const int usedPoolLen = 2; BNU_CHUNK_T* dataT = gsModPoolAlloc(pMont, usedPoolLen); if(NULL == dataT) return -1; BNU_CHUNK_T* sscmB = dataT + nsM; /* mont(1) */ BNU_CHUNK_T* pR = MOD_MNT_R(pMont); /* copy base */ ZEXPAND_COPY_BNU(dataT, nsM, dataX, nsX); /* init result, Y=1 */ COPY_BNU(dataY, pR, nsM); /* execute bits of E */ for(; nsE>0; nsE--) { BNU_CHUNK_T eValue = dataE[nsE-1]; int n; for(n=BNU_CHUNK_BITS; n>0; n--) { /* sscmB = ( msb(eValue) )? X : mont(1) */ BNU_CHUNK_T mask = cpIsMsb_ct(eValue); eValue <<= 1; cpMaskedCopyBNU_ct(sscmB, mask, dataT, pR, nsM); /* squaring Y = Y^2 */ MOD_METHOD(pMont)->sqr(dataY, dataY, pMont); /* and multiplication: Y = Y * sscmB */ MOD_METHOD(pMont)->mul(dataY, dataY, sscmB, pMont); } } gsModPoolFree(pMont, usedPoolLen); } return nsM; } #endif /* _USE_IPP_OWN_CBA_MITIGATION_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpmont_expsafebinary.c000066400000000000000000000242031470420105600257760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Modular Exponentiation (binary version) // // Contents: // cpSafeMontExp_Binary() */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" //tbcd: temporary excluded: #include /*F* // Name: cpSafeMontExp_Binary // // Purpose: Binary method of Exponentiation // // // Parameters: // pX big number integer of Montgomery form within the // range [0,m-1] // pE big number exponent // pMont Montgomery modulus of IppsMontState. / pY the Montgomery exponentiation result. // *F*/ #if !defined(_USE_VERSION1_CBA_MITIGATION_) && !defined(_USE_IPP_OWN_CBA_MITIGATION_) // unsafe version void cpSafeMontExp_Binary(IppsBigNumState* pY, const IppsBigNumState* pX, const IppsBigNumState* pE, IppsMontState* pMont) { int k; /* if E==0 then Y=R mod m */ if (pE->size == 1 && pE->number[0] == 0) { int len = IPP_MULTIPLE_OF(pMont->n->size, BNUBASE_TYPE_SIZE); cpMemset32u(pMont->wb->number, 0, len); pMont->wb->number[len] = 1; cpMod_BNU(pMont->wb->number, len + 1, pMont->n->number, pMont->n->size, &pY->size); cpMemcpy32u(pY->number, pMont->wb->number, pY->size); pY->sgn = ippBigNumPOS; return; } else { Ipp32u* r_number = pY->workBuffer; int r_size = pY->size; int flag=1; Ipp32u power = pE->number[pE->size-1]; for( k = 31; k >= 0; k-- ) { Ipp32u powd = power & 0x80000000;/* from top to bottom*/ power <<= 1; if((flag == 1) && (powd == 0)) continue; else if (flag == 0) { #if defined(_USE_NN_MONTMUL_) cpMontMul(r_number, r_size, r_number,r_size, pMont->n->number, pMont->n->size, r_number,&r_size, pMont->n0, pMont->wb->number); #else cpMontMul(r_number, r_size, r_number,r_size, pMont->n->number, pMont->n->size, r_number,&r_size, pMont->n0, pMont->wb->number, pMont->pBuffer); #endif if (powd) #if defined(_USE_NN_MONTMUL_) cpMontMul(r_number, r_size, pX->number,pX->size, pMont->n->number, pMont->n->size, r_number,&r_size, pMont->n0, pMont->wb->number); #else cpMontMul(r_number, r_size, pX->number,pX->size, pMont->n->number, pMont->n->size, r_number,&r_size, pMont->n0, pMont->wb->number, pMont->pBuffer); #endif } else { int i; flag = 0; r_size = pMont->n->size; if( pX->size < pMont->n->size ) for(i = r_size - 1; i >= pX->size; i-- ) r_number[i] = 0; for( i = pX->size - 1; i >= 0; i-- ) r_number[i] = pX->number[i]; } } if (pE->size > 1) { struct BNU { Ipp32u *number; int *size; } BNUs[2]; BNUs[0].number = r_number; BNUs[0].size = &r_size; BNUs[1].number = pX->number; BNUs[1].size = &(((IppsBigNumState*)pX)->size); for( k = pE->size - 2; k >= 0; k-- ) { int j; Ipp32u powd = 0; power = pE->number[k]; for( j = 31; j >= 0; j-- ) { #if defined(_USE_NN_MONTMUL_) cpMontMul(r_number, r_size, BNUs[powd].number, *(BNUs[powd].size), pMont->n->number, pMont->n->size, r_number,&r_size, pMont->n0, pMont->wb->number); #else cpMontMul(r_number, r_size, BNUs[powd].number, *(BNUs[powd].size), pMont->n->number, pMont->n->size, r_number,&r_size, pMont->n0, pMont->wb->number, pMont->pBuffer); #endif powd = ((power >> j) & 0x1) & (powd ^ 1); j += powd; } } } for(k=r_size-1; k>= 0; k--) pY->number[k] = r_number[k]; pY->sgn = ippBigNumPOS; pY->size = r_size; while((pY->size > 1) && (pY->number[pY->size-1] == 0)) pY->size--; return; } } #endif /* _USE_VERSION1_CBA_MITIGATION_, _xUSE_IPP_OWN_CBA_MITIGATION_ */ #if defined(_USE_VERSION1_CBA_MITIGATION_) /* // The version below was designed according to recommendation // from Crypto experts. // The reason was to mitigate "cache monitoring" attack on RSA // Note: this version slower than pre-mitigated version ~ 30-40% */ #define SET_BNU(dst,val,len) \ { \ int n; \ for(n=0; n<(len); n++) (dst)[n] = (val); \ } #define AND_BNU(dst,src1,src2,len) \ { \ int n; \ for(n=0; n<(len); n++) (dst)[n] = (src1)[n] & (src2)[n]; \ } /*F* // Name: cpSafeMontExp_Binary // // Purpose: Binary method of Exponentiation // // // Parameters: // pX big number integer of Montgomery form within the // range [0,m-1] // pE big number exponent // pMont Montgomery modulus of IppsMontState. / pY the Montgomery exponentiation result. // *F*/ void cpSafeMontExp_Binary(IppsBigNumState* pY, const IppsBigNumState* pX, const IppsBigNumState* pE, IppsMontState* pMont) { Ipp32u* eData = BN_NUMBER(pE); int eSize = BN_SIZE(pE); /* // if e==0 then r=R mod m (i.e MontEnc(1)) */ if (eSize == 1 && eData[0] == 0) { cpBN_copy(MNT_1(pMont), pY); return; } /* // modulo exponentiation */ if(pY!=pX) /* init result */ cpBN_copy(pX, pY); { Ipp32u eValue; int nBits; Ipp32u* pModulus = BN_NUMBER(MNT_MODULO(pMont)); int mSize = BN_SIZE(MNT_MODULO(pMont)); Ipp32u* pHelper = MNT_HELPER(pMont); Ipp32u* yData = BN_NUMBER(pY); Ipp32u* xData = BN_BUFFER(pY); int ySize = BN_SIZE(pY); Ipp32u* tData = BN_NUMBER(MNT_PRODUCT(pMont)); Ipp32u* pBuffer = BN_BUFFER(MNT_PRODUCT(pMont)); Ipp32u* pMontOne= BN_NUMBER(MNT_1(pMont)); /* expand Mont(1) */ ZEXPAND_BNU(pMontOne, BN_SIZE(MNT_1(pMont)), mSize); /* copy base */ ZEXPAND_COPY_BNU(yData,ySize, xData,mSize); /* execute most significant part pE */ eValue = eData[eSize-1]; nBits = 32-NLZ32u(eValue); eValue <<= (32-nBits); nBits--; eValue <<=1; for(; nBits>0; nBits--, eValue<<=1) { Ipp32u carry; /* squaring: R^2 mod Modulus */ #if defined(_USE_NN_MONTMUL_) cpMontMul(yData, ySize, yData, ySize, pModulus, mSize, yData, &ySize, pHelper, pBuffer); #else cpMontMul(yData, ySize, yData, ySize, pModulus, mSize, yData, &ySize, pHelper, pBuffer, MNT_BUFFER(pMont)); #endif /* T = (X-1)*bitof(E,j) + 1 */ SET_BNU(pBuffer, ((Ipp32s)eValue)>>31, mSize); carry = cpSub_BNU(tData, xData, pMontOne, mSize); AND_BNU(tData, tData, pBuffer, mSize); carry = cpAdd_BNU(tData, tData, pMontOne, mSize); /* multiply: Y*T mod Modulus */ #if defined(_USE_NN_MONTMUL_) cpMontMul(yData, ySize, tData, mSize, pModulus, mSize, yData, &ySize, pHelper, pBuffer); #else cpMontMul(yData, ySize, tData, mSize, pModulus, mSize, yData, &ySize, pHelper, pBuffer, MNT_BUFFER(pMont)); #endif } /* execute rest bits of E */ eSize--; for(; eSize>0; eSize--) { eValue = eData[eSize-1]; for(nBits=32; nBits>0; nBits--, eValue<<=1) { Ipp32u carry; /* squaring: R^2 mod Modulus */ #if defined(_USE_NN_MONTMUL_) cpMontMul(yData, ySize, yData, ySize, pModulus, mSize, yData, &ySize, pHelper, pBuffer); #else cpMontMul(yData, ySize, yData, ySize, pModulus, mSize, yData, &ySize, pHelper, pBuffer, MNT_BUFFER(pMont)); #endif /* T = (X-1)*bitof(E,j) + 1 */ SET_BNU(pBuffer, ((Ipp32s)eValue)>>31, mSize); carry = cpSub_BNU(tData, xData, pMontOne, mSize); AND_BNU(tData, tData, pBuffer, mSize); carry = cpAdd_BNU(tData, tData, pMontOne, mSize); /* multiply: R*T mod Modulus */ #if defined(_USE_NN_MONTMUL_) cpMontMul(yData, ySize, tData, mSize, pModulus, mSize, yData, &ySize, pHelper, pBuffer); #else cpMontMul(yData, ySize, tData, mSize, pModulus, mSize, yData, &ySize, pHelper, pBuffer, MNT_BUFFER(pMont)); #endif } } BN_SIZE(pY) = ySize; } } #endif /* _USE_VERSION1_CBA_MITIGATION_ */cryptography-primitives-1.0.0/sources/ippcp/pcpmont_expwinbnu.c000066400000000000000000000117611470420105600251620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // Contents: // cpMontExpWin_BN() */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "gsscramble.h" #if defined(_USE_WINDOW_EXP_) IPP_OWN_DEFN (static void, gsMul_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, const BNU_CHUNK_T* pY, cpSize len, BNU_CHUNK_T* pKbuffer)) { IPP_UNREFERENCED_PARAMETER(pKbuffer); cpMul_BNU_school(pR, pX, len, pY, len); } IPP_OWN_DEFN (static void, gsSqr_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, cpSize len, BNU_CHUNK_T* pKbuffer)) { IPP_UNREFERENCED_PARAMETER(pKbuffer); cpSqr_BNU_school(pR, pX, len); } IPP_OWN_FUNPTR (void, gsMul, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, const BNU_CHUNK_T* pY, cpSize len, BNU_CHUNK_T* pKbuffer)) IPP_OWN_FUNPTR (void, gsSqr, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, cpSize len, BNU_CHUNK_T* pKbuffer)) /*F* // Name: cpMontExpWin_BN // // Purpose: Binary method of Exponentiation // // // Parameters: // pX big number integer of Montgomery form within the // range [0,m-1] // pE big number exponent // pMont Montgomery modulus of IppsMontState. / pY the Montgomery exponentiation result. // pResource pointer to resource // *F*/ IPP_OWN_DEFN (void, cpMontExpWin_BN, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsBigNumState* pE, gsModEngine* pMont, BNU_CHUNK_T* pResource)) { BNU_CHUNK_T* dataX = BN_NUMBER(pX); cpSize nsX = BN_SIZE(pX); BNU_CHUNK_T* dataE = BN_NUMBER(pE); cpSize nsE = BN_SIZE(pE); BNU_CHUNK_T* dataY = BN_NUMBER(pY); cpSize nsM = MOD_LEN(pMont); /* // test for special cases: // x^0 = 1 // 0^e = 0 */ if( cpEqu_BNU_CHUNK(dataE, nsE, 0) ) { COPY_BNU(dataY, MOD_MNT_R(pMont), nsM); } else if( cpEqu_BNU_CHUNK(dataX, nsX, 0) ) { ZEXPAND_BNU(dataY, 0, nsM); } /* general case */ else { /* Montgomery engine buffers */ const int usedPoolLen = 2; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pMont, usedPoolLen); if(NULL == pBuffer) return; BNU_CHUNK_T* pKBuffer = pBuffer + nsM; /* mul & sqr functions */ gsMul mulFun = gsMul_school; gsSqr sqrFun = gsSqr_school; /* fixed window param */ cpSize bitsizeE = BITSIZE_BNU(dataE, nsE); cpSize window = cpMontExp_WinSize(bitsizeE); BNU_CHUNK_T mask = (1<>shift) &mask; /* initialize result */ COPY_BNU(dataY, pResource+windowVal*(BNU_CHUNK_T)nsM, nsM); for(eBit-=window; eBit>=0; eBit-=window) { /* do square window times */ for(n=0,windowVal=0; n>shift) &mask; if(windowVal) { /* extract precomputed value and multiply */ mulFun(pBuffer, dataY, pResource+windowVal*(BNU_CHUNK_T)nsM, nsM, pKBuffer); cpMontRed_BNU(dataY, pBuffer, pMont); } } } gsModPoolFree(pMont, usedPoolLen); } FIX_BNU(dataY, nsM); BN_SIZE(pY) = nsM; BN_SIGN(pY) = ippBigNumPOS; } #endif /* _USE_WINDOW_EXP_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpmont_expwinbnu_sscm.c000066400000000000000000000134661470420105600262130ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // Contents: // cpMontExpWin_BN_sscm() */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "gsscramble.h" #if defined(_USE_WINDOW_EXP_) IPP_OWN_DEFN (static void, gsMul_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, const BNU_CHUNK_T* pY, cpSize len, BNU_CHUNK_T* pKbuffer)) { IPP_UNREFERENCED_PARAMETER(pKbuffer); cpMul_BNU_school(pR, pX, len, pY, len); } IPP_OWN_DEFN (static void, gsSqr_school, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, cpSize len, BNU_CHUNK_T* pKbuffer)) { IPP_UNREFERENCED_PARAMETER(pKbuffer); cpSqr_BNU_school(pR, pX, len); } IPP_OWN_FUNPTR (void, gsMul, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, const BNU_CHUNK_T* pY, cpSize len, BNU_CHUNK_T* pKbuffer)) IPP_OWN_FUNPTR (void, gsSqr, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pX, cpSize len, BNU_CHUNK_T* pKbuffer)) /*F* // Name: cpMontExpWin_BN_sscm // // Purpose: Binary method of Exponentiation // // // Parameters: // pX big number integer of Montgomery form within the // range [0,m-1] // pE big number exponent // pMont Montgomery modulus of IppsMontState. / pY the Montgomery exponentiation result. // *F*/ IPP_OWN_DEFN (void, cpMontExpWin_BN_sscm, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsBigNumState* pE, gsModEngine* pMont, BNU_CHUNK_T* pResource)) { BNU_CHUNK_T* dataX = BN_NUMBER(pX); cpSize nsX = BN_SIZE(pX); BNU_CHUNK_T* dataE = BN_NUMBER(pE); cpSize nsE = BN_SIZE(pE); BNU_CHUNK_T* dataY = BN_NUMBER(pY); cpSize nsM = MOD_LEN(pMont); /* // test for special cases: // x^0 = 1 // 0^e = 0 */ if( cpEqu_BNU_CHUNK(dataE, nsE, 0) ) { COPY_BNU(dataY, MOD_MNT_R(pMont), nsM); } else if( cpEqu_BNU_CHUNK(dataX, nsX, 0) ) { ZEXPAND_BNU(dataY, 0, nsM); } /* general case */ else { /* Montgomery engine buffers */ const int usedPoolLen = 2; BNU_CHUNK_T* pBuffer = gsModPoolAlloc(pMont, usedPoolLen); if(NULL == pBuffer) return; BNU_CHUNK_T* pKBuffer = pBuffer + nsM; /* mul & sqr functions */ gsMul mulFun = gsMul_school; gsSqr sqrFun = gsSqr_school; /* fixed window param */ cpSize bitsizeE = BITSIZE_BNU(dataE, nsE); cpSize window = cpMontExp_WinSize(bitsizeE); BNU_CHUNK_T mask = (1<>shift) &mask); /* initialize result */ //cpScrambleGet((Ipp32u*)dataY, nsM*sizeof(BNU_CHUNK_T)/sizeof(Ipp32u), ((Ipp8u*)pResource)+windowVal*chunkSize, chunkSize); gsScrambleGet_sscm(dataY, nsM, pResource, windowVal, window); for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0,windowVal=0; n>shift) &mask); /* exptact precomputed value and multiply */ //cpScrambleGet((Ipp32u*)dataT, nsM*sizeof(BNU_CHUNK_T)/sizeof(Ipp32u), ((Ipp8u*)pResource)+windowVal*chunkSize, chunkSize); gsScrambleGet_sscm(dataT, nsM, pResource, windowVal, window); mulFun(pBuffer, dataY, dataT, nsM, pKBuffer); cpMontRed_BNU(dataY, pBuffer, pMont); } } gsModPoolFree(pMont, usedPoolLen); } FIX_BNU(dataY, nsM); BN_SIZE(pY) = nsM; BN_SIGN(pY) = ippBigNumPOS; } #endif /* _USE_WINDOW_EXP_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpmont_getsize.c000066400000000000000000000031301470420105600246040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpMontGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: cpMontGetSize // // Purpose: Specifies size of buffer in bytes. // // Returns: Reason: // ippStsNoErr no errors // // Parameters: // poolLength length of pool // maxLen32 max modulus length (in Ipp32u chunks) // pCtxSize pointer to size of context // *F*/ IPP_OWN_DEFN (IppStatus, cpMontGetSize, (cpSize maxLen32, int poolLength, cpSize* pCtxSize)) { { int size = 0; int maxBitSize = maxLen32 << 5; gsModEngineGetSize(maxBitSize, poolLength, &size); *pCtxSize = (Ipp32s)sizeof(IppsMontState) + (cpSize)size; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_init.c000066400000000000000000000033711470420105600241040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpMontInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: cpMontInit // // Purpose: Initializes the symbolic data structure and partitions the // specified buffer space. // // Returns: Reason: // ippStsNoErr no errors // // Parameters: // poolLength length of pool // maxLen32 max modulus length (in Ipp32u chunks) // pMont pointer to Montgomery context // *F*/ IPP_OWN_DEFN (IppStatus, cpMontInit, (int maxLen32, int poolLength, IppsMontState* pMont)) { { int maxBitSize = ((maxLen32) << 5); MNT_ROOM( pMont ) = INTERNAL_BNU_LENGTH(maxLen32); MNT_ENGINE ( pMont ) = (gsModEngine*)((Ipp8u*)pMont + sizeof(IppsMontState)); MNT_SET_ID(pMont); gsModEngineInit(MNT_ENGINE(pMont), NULL, maxBitSize, poolLength, gsModArithMont()); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_multiexp_fast.c000066400000000000000000000050671470420105600260310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // cpFastMontMultiExp() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" static cpSize GetIndex(const Ipp8u** ppE, cpSize numItems, cpSize nBit) { cpSize shift = nBit%BYTESIZE; cpSize offset= nBit/BYTESIZE; cpSize index = 0; cpSize n; for(n=numItems; n>0; n--) { const Ipp8u* pE = ppE[n-1] + offset; Ipp8u e = pE[0]; index <<= 1; index += (e>>shift) &1; } return index; } /* // Computes multi-exponentiation // y = x[0]^e[0] * x[1]^e[1] *...* x[numItems-1]^e[numItems-1] mod M // // Input: // - table pTbl of precomputed values pTbl[i] = x[0]^i[0] * x[1]^i[1] *...* x[numItems-1]^i[numItems-1] mod M, // where i[0], i[1], ..., i[numItems-1] are bits of i value; // each entry has sizeM length (i.e. equal to modulo M size) // - array of pointers to the BNU exponents e[0], e[1],...,e[numItems-1] // - pointer to the Montgomery engine */ IPP_OWN_DEFN (void, cpFastMontMultiExp, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pPrecomTbl, const Ipp8u** ppE, cpSize eItemBitSize, cpSize numItems, gsModEngine* pModEngine)) { cpSize sizeM = MOD_LEN(pModEngine); /* find 1-st non zero index */ cpSize eBitNumber; cpSize tblIdx; for(eBitNumber=eItemBitSize-1, tblIdx=0; !tblIdx && eBitNumber>=0; eBitNumber--) tblIdx =GetIndex(ppE, numItems, eBitNumber); COPY_BNU(pY, pPrecomTbl+tblIdx*sizeM, sizeM); for(; eBitNumber>=0; eBitNumber--) { cpMontMul_BNU(pY, pY, pY, pModEngine); tblIdx = GetIndex(ppE, numItems, eBitNumber); if(tblIdx) cpMontMul_BNU(pY, pY, pPrecomTbl+tblIdx*sizeM, pModEngine); } } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_multiexpinitarray.c000066400000000000000000000050171470420105600267320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // cpMontMultiExpInitArray() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" /* // Initialize multi-exponentiation computation // y = x[0]^e[0] * x[1]^e[1] *...* x[numItems-1]^e[numItems-1] mod M // // Output: // - table pTbl of precomputed values pTbl[i] = x[0]^i[0] * x[1]^i[1] *...* x[numItems-1]^i[numItems-1] mod M, // where i[0], i[1], ..., i[numItems-1] are bits of i value; // // Input: // - array of pointers to the BNU bases x[0], x[1],...,x[numItems-1] // - pointer to the Montgomery engine */ IPP_OWN_DEFN (void, cpMontMultiExpInitArray, (BNU_CHUNK_T* pPrecomTbl, const BNU_CHUNK_T** ppX, cpSize xItemBitSize, cpSize numItems, gsModEngine* pModEngine)) { cpSize sizeM = MOD_LEN(pModEngine); cpSize i, base; cpSize sizeX = BITS_BNU_CHUNK(xItemBitSize); /* buff[0] = mont(1) */ COPY_BNU(pPrecomTbl, MOD_MNT_R(pModEngine), sizeM); /* buff[1] = X[0] */ ZEXPAND_COPY_BNU(pPrecomTbl+sizeM, sizeM, ppX[0], sizeX); for(i=1,base=2*sizeM; i=0; k--) { const BNU_CHUNK_T* pXterm = ppX[k]; BNU_CHUNK_T* pBufferBase = pPrecomTbl+base; int n; for(n=1; n<=nPasses; n++, pBufferBase+=2*step) { cpMontMul_BNU_EX(pBufferBase+step, pBufferBase, sizeM, pXterm, sizeX, pModEngine); } nPasses *= 2; step /= 2; } } } } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_packctx.c000066400000000000000000000025771470420105600246050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpPackMontCtx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: cpPackMontCtx // // Purpose: Serialize mont context // // Parameters: // pCtx context // pBuffer buffer *F*/ IPP_OWN_DEFN (void, cpPackMontCtx, (const IppsMontState* pCtx, Ipp8u* pBuffer)) { /* size of context (bytes) */ int ctxSize = sizeof(IppsMontState); CopyBlock(pCtx, pBuffer, ctxSize); pBuffer = (Ipp8u*)pBuffer + sizeof(IppsMontState); gsPackModEngineCtx(MNT_ENGINE(pCtx), pBuffer); } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_set.c000066400000000000000000000044141470420105600237330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpMontSet() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /* Auxilirary function */ __IPPCP_INLINE int cpGetBitSize(Ipp32u offset, Ipp32u val) { int bitSize = 31; if (val == 0) return 0; while ((val & (1 << bitSize)) == 0) bitSize--; return (int)offset + bitSize; } /*F* // Name: cpMontSet // // Purpose: Setup modulus value // // Returns: Reason: // ippStsBadModulusErr (pModulus[0] & 1) == 0 // ippStsOutOfRangeErr ((Ipp32u)MNT_ROOM(pMont) < INTERNAL_BNU_LENGTH(len32)) // ippStsLengthErr len32<1 // ippStsNoErr no errors // // Parameters: // pModulus pointer to the modulus buffer // len32 length of the modulus (in Ipp32u chunks). // pMont pointer to the context *F*/ IPP_OWN_DEFN (IppStatus, cpMontSet, (const Ipp32u* pModulus, cpSize len32, IppsMontState* pMont)) { IPP_BADARG_RET(len32<1, ippStsLengthErr); /* modulus is not an odd number */ IPP_BADARG_RET((pModulus[0] & 1) == 0, ippStsBadModulusErr); IPP_BADARG_RET(MNT_ROOM(pMont)<(int)(INTERNAL_BNU_LENGTH(len32)), ippStsOutOfRangeErr); { const int poolLen = MOD_MAXPOOL(MNT_ENGINE(pMont)); int modulusBitSize = cpGetBitSize((Ipp32u)((len32 - 1) << 5), pModulus[len32-1]); gsModEngineInit(MNT_ENGINE(pMont), pModulus, modulusBitSize, poolLen, gsModArithMont()); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmont_unpackctx.c000066400000000000000000000026111470420105600251350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // cpUnpackMontCtx() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: cpUnpackMontCtx // // Purpose: Deserialize mont context // // Parameters: // pCtx context // pBuffer buffer *F*/ IPP_OWN_DEFN (void, cpUnpackMontCtx, (const Ipp8u* pBuffer, IppsMontState* pCtx)) { /* size of context (bytes) */ int ctxSize = sizeof(IppsMontState); CopyBlock(pBuffer, pCtx, ctxSize); pBuffer = (Ipp8u*)pBuffer + sizeof(IppsMontState); gsUnpackModEngineCtx(pBuffer, MNT_ENGINE(pCtx)); } cryptography-primitives-1.0.0/sources/ippcp/pcpmontexp.c000066400000000000000000000061321470420105600235740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMontExp() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: ippsMontExp // // Purpose: computes the Montgomery exponentiation with exponent // IppsBigNumState *pE to the given big number integer of Montgomery form // IppsBigNumState *pA with respect to the modulus IppsMontState *pCtx. // // Returns: Reason: // ippStsNoErr Returns no error. // ippStsNullPtrErr Returns an error when pointers are null. // ippStsBadArgErr Returns an error when a or b is a negative integer. // ippStsScaleRangeErr Returns an error when a or b is more than m. // ippStsOutOfRangeErr Returns an error when IppsBigNumState *r is larger than // IppsMontState *m. // ippStsContextMatchErr Returns an error when the context parameter does // not match the operation. // // // Parameters: // pA big number integer of Montgomery form within the // range [0,m-1] // pE big number exponent // pCtx Montgomery modulus of IppsMontState / pR the Montgomery exponentiation result. // // Notes: IppsBigNumState *r should possess enough memory space as to hold the result // of the operation. i.e. both pointers r->d and r->buffer should possess // no less than (m->n->length) number of 32-bit words. *F*/ IPPFUN(IppStatus, ippsMontExp, (const IppsBigNumState* pA, const IppsBigNumState* pE, IppsMontState* pCtx, IppsBigNumState* pR)) { IPP_BAD_PTR4_RET(pA, pE, pCtx, pR); IPP_BADARG_RET(!MNT_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pE), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pR) < MOD_LEN( MNT_ENGINE(pCtx) ), ippStsOutOfRangeErr); /* check a */ IPP_BADARG_RET(BN_NEGATIVE(pA), ippStsBadArgErr); IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), MOD_MODULUS( MNT_ENGINE(pCtx) ), MOD_LEN( MNT_ENGINE(pCtx) )) >= 0, ippStsScaleRangeErr); /* check e */ IPP_BADARG_RET(BN_NEGATIVE(pE), ippStsBadArgErr); cpMontExpBin_BN(pR, pA, pE, MNT_ENGINE( pCtx) ); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpmontexp_winsize.c000066400000000000000000000045131470420105600253450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2003 Intel Corporation * * 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. *************************************************************************/ /* // Contents: // cpMontExp_WinSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "gsscramble.h" #if !defined(_USE_WINDOW_EXP_) IPP_OWN_DEFN (cpSize, cpMontExp_WinSize, (int bitsize)) { IPP_UNREFERENCED_PARAMETER(bitsize); return 1; } #else /* // returns (optimal) window width // Because of safety Window width depend on CACHE LINE size: // P4,EM64T, ITP - 64 bytes // XScale - 32 bytes // Blend - no cache */ #if !((_IPP==_IPP_W7) || (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || (_IPP==_IPP_P8) || \ (_IPP==_IPP_S8) || (_IPP>=_IPP_G9) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) IPP_OWN_DEFN (cpSize, cpMontExp_WinSize, (int bitsize)) { IPP_UNREFERENCED_PARAMETER(bitsize); return 1; } #endif #if ((_IPP==_IPP_W7) || (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || (_IPP==_IPP_P8) || \ (_IPP==_IPP_S8) || (_IPP>=_IPP_G9) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || (_IPP32E==_IPP32E_Y8) || \ (_IPP32E==_IPP32E_N8) || (_IPP32E>=_IPP32E_E9)) IPP_OWN_DEFN (cpSize, cpMontExp_WinSize, (int bitsize)) { return //bitsize>3715? 8 : /*limited by 6 or 4 (LOG_CACHE_LINE_SIZE); we use it for windowing-exp imtigation */ //bitsize>1434? 7 : #if (_IPP !=_IPP_M5) bitsize> 539? 6 : bitsize> 197? 5 : #endif bitsize> 70? 4 : bitsize> 25? 3 : bitsize> 9? 2 : 1; } #endif #endif /* _USE_WINDOW_EXP_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpmontform.c000066400000000000000000000055161470420105600237500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMontForm() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: ippsMontForm // // Purpose: Converts input into Montgomery domain. // // Returns: Reason: // ippStsNullPtrErr pCtx==NULL // pA==NULL // pR==NULL // ippStsContextMatchErr !MNT_VALID_ID(pCtx) // !BN_VALID_ID(pA) // !BN_VALID_ID(pR) // ippStsBadArgErr A < 0. // ippStsScaleRangeErr A >= Modulus. // ippStsOutOfRangeErr R can't hold result // ippStsNoErr no errors // // Parameters: // pA pointer to the input [0, modulus-1] // pCtx Montgomery context // pR pointer to the output (A*R mod modulus) *F*/ IPPFUN(IppStatus, ippsMontForm,(const IppsBigNumState* pA, IppsMontState* pCtx, IppsBigNumState* pR)) { IPP_BAD_PTR3_RET(pCtx, pA, pR); IPP_BADARG_RET(!MNT_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(BN_SIGN(pA) != ippBigNumPOS, ippStsBadArgErr); IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), MOD_MODULUS( MNT_ENGINE(pCtx) ), MOD_LEN( MNT_ENGINE(pCtx) )) >= 0, ippStsScaleRangeErr); IPP_BADARG_RET(BN_ROOM(pR) < MOD_LEN( MNT_ENGINE(pCtx) ), ippStsOutOfRangeErr); { const int usedPoolLen = 1; cpSize nsM = MOD_LEN( MNT_ENGINE(pCtx) ); BNU_CHUNK_T* pDataA = gsModPoolAlloc(MNT_ENGINE(pCtx), usedPoolLen); IPP_BAD_PTR1_RET(pDataA); // pDataA can be NULL, stop processing ZEXPAND_COPY_BNU(pDataA, nsM, BN_NUMBER(pA), BN_SIZE(pA)); MOD_METHOD( MNT_ENGINE(pCtx) )->encode(BN_NUMBER(pR), pDataA, MNT_ENGINE(pCtx)); FIX_BNU(BN_NUMBER(pR), nsM); BN_SIZE(pR) = nsM; BN_SIGN(pR) = ippBigNumPOS; gsModPoolFree(MNT_ENGINE(pCtx), usedPoolLen); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpmontget.c000066400000000000000000000036711470420105600235640ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMontGet() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: ippsMontGet // // Purpose: Extracts modulus. // // Returns: Reason: // ippStsNullPtrErr pMont==NULL // pModulus==NULL // pSize==NULL // ippStsContextMatchErr !MNT_VALID_ID() // ippStsNoErr no errors // // Parameters: // pModulus pointer to the modulus buffer // pSize pointer to the modulus length (in Ipp32u chunks). // pMont pointer to the context *F*/ IPPFUN(IppStatus, ippsMontGet,(Ipp32u* pModulus, int* pSize, const IppsMontState* pMont)) { IPP_BAD_PTR3_RET(pMont, pModulus, pSize); IPP_BADARG_RET(!MNT_VALID_ID(pMont), ippStsContextMatchErr); { cpSize len32 = MOD_LEN(MNT_ENGINE(pMont))*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)); Ipp32u* bnData = (Ipp32u*) MOD_MODULUS( MNT_ENGINE(pMont) ); FIX_BNU32(bnData, len32); COPY_BNU(pModulus, bnData, len32); *pSize = len32; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmontgetsize.c000066400000000000000000000035211470420105600244510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMontGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: ippsMontGetSize // // Purpose: Specifies size of buffer in bytes. // // Returns: Reason: // ippStsNullPtrErr pSize==NULL // ippStsLengthErr length < 1 // length > BITS2WORD32_SIZE(BN_MAXBITSIZE) // ippStsNoErr no errors // // Parameters: // method selected exponential method (unused parameter) // length max modulus length (in Ipp32u chunks) // pSize size of context // // Notes: Function always use method=ippBinaryMethod, // so this parameter is ignored *F*/ IPPFUN(IppStatus, ippsMontGetSize, (IppsExpMethod method, int length, int* pSize)) { IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(length<1 || length>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); IPP_UNREFERENCED_PARAMETER(method); { return cpMontGetSize(length, MONT_DEFAULT_POOL_LENGTH, pSize); } } cryptography-primitives-1.0.0/sources/ippcp/pcpmontgomery.h000066400000000000000000000227021470420105600243100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // */ #if !defined(_CP_MONTGOMETRY_H) #define _CP_MONTGOMETRY_H #include "pcpbn.h" #include "gsmodstuff.h" #define MONT_DEFAULT_POOL_LENGTH (6) /* // Montgomery spec structure */ struct _cpMontgomery { Ipp32u idCtx; /* Montgomery spec identifier */ cpSize maxLen; /* Maximum length of modulus being stored */ gsModEngine* pEngine; /* Modular arith engine structure */ }; /* accessory macros */ #define MNT_SET_ID(eng) ((eng)->idCtx = (Ipp32u)idCtxMontgomery ^ (Ipp32u)IPP_UINT_PTR(eng)) #define MNT_ROOM(eng) ((eng)->maxLen) #define MNT_ENGINE(eng) ((eng)->pEngine) #define MNT_VALID_ID(eng) ((((eng)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((eng))) == (Ipp32u)idCtxMontgomery) /* default method */ #define EXPONENT_METHOD (ippBinaryMethod) /* alignment */ #define MONT_ALIGNMENT ((int)(sizeof(void*))) /* // Pacp/unpack Montgomery context */ #define cpPackMontCtx OWNAPI(cpPackMontCtx) IPP_OWN_DECL (void, cpPackMontCtx, (const IppsMontState* pCtx, Ipp8u* pBuffer)) #define cpUnpackMontCtx OWNAPI(cpUnpackMontCtx) IPP_OWN_DECL (void, cpUnpackMontCtx, (const Ipp8u* pBuffer, IppsMontState* pCtx)) /* // Montgomery reduction, multiplication and squaring */ __IPPCP_INLINE void cpMontRed_BNU(BNU_CHUNK_T* pR, BNU_CHUNK_T* pProduct, gsModEngine* pModEngine) { MOD_METHOD( pModEngine )->red(pR, pProduct, pModEngine); } __IPPCP_INLINE void cpMontMul_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, const BNU_CHUNK_T* pB, gsModEngine* pModEngine) { MOD_METHOD( pModEngine )->mul(pR, pA, pB, pModEngine); } __IPPCP_INLINE cpSize cpMontMul_BNU_EX(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, const BNU_CHUNK_T* pB, cpSize nsB, gsModEngine* pModEngine) { const int usedPoolLen = 1; cpSize nsM = MOD_LEN( pModEngine ); BNU_CHUNK_T* pDataR = pR; BNU_CHUNK_T* pDataA = gsModPoolAlloc(pModEngine, usedPoolLen); if(NULL == pDataA) return -1; ZEXPAND_COPY_BNU(pDataA, nsM, pA, nsA); ZEXPAND_COPY_BNU(pDataR, nsM, pB, nsB); MOD_METHOD( pModEngine )->mul(pDataR, pDataA, pDataR, pModEngine); gsModPoolFree(pModEngine, usedPoolLen); return nsM; } __IPPCP_INLINE void cpMontSqr_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, gsModEngine* pModEngine) { MOD_METHOD( pModEngine )->sqr(pR, pA, pModEngine); } __IPPCP_INLINE void cpMontSqr_BNU_EX(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, cpSize nsA, gsModEngine* pModEngine) { cpSize nsM = MOD_LEN( pModEngine ); ZEXPAND_COPY_BNU(pR, nsM, pA, nsA); MOD_METHOD( pModEngine )->sqr(pR, pR, pModEngine); } /* // Montgomery encoding/decoding */ __IPPCP_INLINE cpSize cpMontEnc_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pXreg, gsModEngine* pModEngine) { cpSize nsM = MOD_LEN(pModEngine); MOD_METHOD( pModEngine )->encode(pR, pXreg, pModEngine); FIX_BNU(pR, nsM); return nsM; } __IPPCP_INLINE cpSize cpMontEnc_BNU_EX(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pXreg, cpSize nsX, gsModEngine* pModEngine) { cpSize nsM = MOD_LEN(pModEngine); ZEXPAND_COPY_BNU(pR, nsM, pXreg, nsX); MOD_METHOD( pModEngine )->encode(pR, pR, pModEngine); FIX_BNU(pR, nsM); return nsM; } __IPPCP_INLINE cpSize cpMontDec_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pXmont, cpSize nsX, gsModEngine* pModEngine) { cpSize nsM = MOD_LEN( pModEngine ); ZEXPAND_COPY_BNU(pR, nsM, pXmont, nsX); MOD_METHOD( pModEngine )->decode(pR, pR, pModEngine); FIX_BNU(pR, nsM); return nsM; } __IPPCP_INLINE void cpMontMul_BN(IppsBigNumState* pRbn, const IppsBigNumState* pXbn, const IppsBigNumState* pYbn, gsModEngine* pModEngine) { cpSize nsM = cpMontMul_BNU_EX(BN_NUMBER(pRbn), BN_NUMBER(pXbn), BN_SIZE(pXbn), BN_NUMBER(pYbn), BN_SIZE(pYbn), pModEngine); FIX_BNU(BN_NUMBER(pRbn), nsM); BN_SIZE(pRbn) = nsM; BN_SIGN(pRbn) = ippBigNumPOS; } __IPPCP_INLINE void cpMontEnc_BN(IppsBigNumState* pRbn, const IppsBigNumState* pXbn, gsModEngine* pModEngine) { cpSize nsM = cpMontEnc_BNU_EX(BN_NUMBER(pRbn), BN_NUMBER(pXbn), BN_SIZE(pXbn), pModEngine); BN_SIZE(pRbn) = nsM; BN_SIGN(pRbn) = ippBigNumPOS; } __IPPCP_INLINE void cpMontDec_BN(IppsBigNumState* pRbn, const IppsBigNumState* pXbn, gsModEngine* pModEngine) { cpSize nsM = MOD_LEN(pModEngine); cpMontDec_BNU(BN_NUMBER(pRbn), BN_NUMBER(pXbn), BN_SIZE(pXbn), pModEngine); BN_SIZE(pRbn) = nsM; BN_SIGN(pRbn) = ippBigNumPOS; } /* // Montgomery exponentiation (binary) "fast" and "safe" versions */ #define cpMontExpBin_BNU OWNAPI(cpMontExpBin_BNU) IPP_OWN_DECL (cpSize, cpMontExpBin_BNU, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pX, cpSize nsX, const BNU_CHUNK_T* pE, cpSize nsE, gsModEngine* pModEngine)) #define cpMontExpBin_BNU_sscm OWNAPI(cpMontExpBin_BNU_sscm) IPP_OWN_DECL (cpSize, cpMontExpBin_BNU_sscm, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pX, cpSize nsX, const BNU_CHUNK_T* pE, cpSize nsE, gsModEngine* pModEngine)) __IPPCP_INLINE void cpMontExpBin_BN_sscm(IppsBigNumState* pYbn, const IppsBigNumState* pXbn, const IppsBigNumState* pEbn, gsModEngine* pMont) { BNU_CHUNK_T* pX = BN_NUMBER(pXbn); cpSize nsX = BN_SIZE(pXbn); BNU_CHUNK_T* pE = BN_NUMBER(pEbn); cpSize nsE = BN_SIZE(pEbn); BNU_CHUNK_T* pY = BN_NUMBER(pYbn); cpSize nsY = cpMontExpBin_BNU_sscm(pY, pX,nsX, pE,nsE, pMont); FIX_BNU(pY, nsY); BN_SIZE(pYbn) = nsY; BN_SIGN(pYbn) = ippBigNumPOS; } __IPPCP_INLINE void cpMontExpBin_BN(IppsBigNumState* pYbn, const IppsBigNumState* pXbn, const IppsBigNumState* pEbn, gsModEngine* pModEngine) { BNU_CHUNK_T* pX = BN_NUMBER(pXbn); cpSize nsX = BN_SIZE(pXbn); BNU_CHUNK_T* pE = BN_NUMBER(pEbn); cpSize nsE = BN_SIZE(pEbn); BNU_CHUNK_T* pY = BN_NUMBER(pYbn); cpSize nsY = cpMontExpBin_BNU(pY, pX,nsX, pE,nsE, pModEngine); FIX_BNU(pY, nsY); BN_SIZE(pYbn) = nsY; BN_SIGN(pYbn) = ippBigNumPOS; } /* // Montgomery exponentiation (fixed window) */ #define cpMontExp_WinSize OWNAPI(cpMontExp_WinSize) IPP_OWN_DECL (cpSize, cpMontExp_WinSize, (int bitsize)) #if defined(_USE_WINDOW_EXP_) #define cpMontExpWin_BN_sscm OWNAPI(cpMontExpWin_BN_sscm) IPP_OWN_DECL (void, cpMontExpWin_BN_sscm, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsBigNumState* pE, gsModEngine* pMont, BNU_CHUNK_T* pPrecompResource)) #define cpMontExpWin_BN OWNAPI(cpMontExpWin_BN) IPP_OWN_DECL (void, cpMontExpWin_BN, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsBigNumState* pE, gsModEngine* pMont, BNU_CHUNK_T* pPrecompResource)) #endif /* // Montgomery multi-exponentiation */ /* precompute table for multi-exponentiation */ #define cpMontMultiExpInitArray OWNAPI(cpMontMultiExpInitArray) IPP_OWN_DECL (void, cpMontMultiExpInitArray, (BNU_CHUNK_T* pPrecomTbl, const BNU_CHUNK_T** ppX, cpSize xItemBitSize, cpSize numItems, gsModEngine* pMont)) /* multi-exponentiation */ #define cpFastMontMultiExp OWNAPI(cpFastMontMultiExp) IPP_OWN_DECL (void, cpFastMontMultiExp, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pPrecomTbl, const Ipp8u** ppE, cpSize eItemBitSize, cpSize numItems, gsModEngine* pMont)) /* // Montgomery inversion */ #define cpMontInv_BNU OWNAPI(cpMontInv_BNU) IPP_OWN_DECL (BNU_CHUNK_T*, cpMontInv_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, IppsMontState* pMont)) #define cpRegInv_BNU OWNAPI(cpRegInv_BNU) IPP_OWN_DECL (BNU_CHUNK_T*, cpRegInv_BNU, (BNU_CHUNK_T* pR, const BNU_CHUNK_T* pA, IppsMontState* pMont)) /* // Montgomery internal GetSize/Init functions */ #define cpMontGetSize OWNAPI(cpMontGetSize) IPP_OWN_DECL (IppStatus, cpMontGetSize, (cpSize maxLen32, int poolLength, cpSize* pCtxSize)) #define cpMontInit OWNAPI(cpMontInit) IPP_OWN_DECL (IppStatus, cpMontInit, (int maxLen32, int poolLength, IppsMontState* pMont)) #define cpMontSet OWNAPI(cpMontSet) IPP_OWN_DECL (IppStatus, cpMontSet, (const Ipp32u* pModulus, cpSize len32, IppsMontState* pMont)) #endif /* _CP_MONTGOMETRY_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpmontinit.c000066400000000000000000000034721470420105600237470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMontInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: ippsMontInit // // Purpose: Initializes the symbolic data structure and partitions the // specified buffer space. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsLengthErr length < 1 // length > BITS2WORD32_SIZE(BN_MAXBITSIZE) // ippStsNoErr no errors // // Parameters: // method selected exponential method (unused parameter) // length max modulus length (in Ipp32u chunks) // pCtx pointer to Montgomery context *F*/ IPPFUN(IppStatus, ippsMontInit,(IppsExpMethod method, int length, IppsMontState* pCtx)) { IPP_BADARG_RET(length<1 || length>BITS2WORD32_SIZE(BN_MAXBITSIZE), ippStsLengthErr); IPP_BAD_PTR1_RET(pCtx); IPP_UNREFERENCED_PARAMETER(method); { return cpMontInit(length, MONT_DEFAULT_POOL_LENGTH, pCtx); } } cryptography-primitives-1.0.0/sources/ippcp/pcpmontmul.c000066400000000000000000000071201470420105600235730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Contents: // ippsMontMul() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcptool.h" /*F* // Name: ippsMontMul // // Purpose: Computes Montgomery modular multiplication for positive big // number integers of Montgomery form. The following pseudocode // represents this function: // r <- ( a * b * R^(-1) ) mod m // // Returns: Reason: // ippStsNoErr Returns no error. // ippStsNullPtrErr Returns an error when pointers are null. // ippStsBadArgErr Returns an error when a or b is a negative integer. // ippStsScaleRangeErr Returns an error when a or b is more than m. // ippStsOutOfRangeErr Returns an error when IppsBigNumState *r is larger than // IppsMontState *m. // ippStsContextMatchErr Returns an error when the context parameter does // not match the operation. // // Parameters: // pA Multiplicand within the range [0, m - 1]. // pB Multiplier within the range [0, m - 1]. // pCtx Modulus. // pR Montgomery multiplication result. // // Notes: The size of IppsBigNumState *r should not be less than the data // length of the modulus m. *F*/ IPPFUN(IppStatus, ippsMontMul, (const IppsBigNumState* pA, const IppsBigNumState* pB, IppsMontState* pCtx, IppsBigNumState* pR)) { IPP_BAD_PTR4_RET(pA, pB, pCtx, pR); IPP_BADARG_RET(!MNT_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pA), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pB), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pR), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pA) || BN_NEGATIVE(pB), ippStsBadArgErr); IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pA), BN_SIZE(pA), MOD_MODULUS( MNT_ENGINE(pCtx) ), MOD_LEN( MNT_ENGINE(pCtx) )) >= 0, ippStsScaleRangeErr); IPP_BADARG_RET(cpCmp_BNU(BN_NUMBER(pB), BN_SIZE(pB), MOD_MODULUS( MNT_ENGINE(pCtx) ), MOD_LEN( MNT_ENGINE(pCtx) )) >= 0, ippStsScaleRangeErr); IPP_BADARG_RET(BN_ROOM(pR) < MOD_LEN( MNT_ENGINE(pCtx) ), ippStsOutOfRangeErr); { const int usedPoolLen = 2; cpSize nsM = MOD_LEN( MNT_ENGINE(pCtx) ); BNU_CHUNK_T* pDataR = BN_NUMBER(pR); BNU_CHUNK_T* pDataA = gsModPoolAlloc(MNT_ENGINE(pCtx), usedPoolLen); IPP_BAD_PTR1_RET(pDataA); // pDataA can be NULL, stop processing BNU_CHUNK_T* pDataB = pDataA + nsM; ZEXPAND_COPY_BNU(pDataA, nsM, BN_NUMBER(pA), BN_SIZE(pA)); ZEXPAND_COPY_BNU(pDataB, nsM, BN_NUMBER(pB), BN_SIZE(pB)); MOD_METHOD( MNT_ENGINE(pCtx) )->mul(pDataR, pDataA, pDataB, MNT_ENGINE(pCtx)); gsModPoolFree(MNT_ENGINE(pCtx), usedPoolLen); FIX_BNU(pDataR, nsM); BN_SIZE(pR) = nsM; BN_SIGN(pR) = ippBigNumPOS; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpmontred.c000066400000000000000000000042261470420105600235540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2010 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // */ #include "owncp.h" #include "pcpbnuarith.h" #if !((_IPP==_IPP_W7) || \ (_IPP==_IPP_T7) || \ (_IPP==_IPP_V8) || \ (_IPP==_IPP_P8) || \ (_IPP>=_IPP_G9) || \ (_IPP==_IPP_S8) || \ (_IPP32E==_IPP32E_M7) || \ (_IPP32E==_IPP32E_U8) || \ (_IPP32E==_IPP32E_Y8) || \ (_IPP32E>=_IPP32E_E9) || \ (_IPP32E==_IPP32E_N8)) || \ defined(_USE_C_cpMontRedAdc_BNU_) #define cpMontRedAdc_BNU OWNAPI(cpMontRedAdc_BNU) IPP_OWN_DEFN (void, cpMontRedAdc_BNU, (BNU_CHUNK_T* pR, BNU_CHUNK_T* pProduct, const BNU_CHUNK_T* pModulus, cpSize nsM, BNU_CHUNK_T m0)) { BNU_CHUNK_T carry; BNU_CHUNK_T extension; cpSize n; for(n=0, carry = 0; n<(nsM-1); n++) { BNU_CHUNK_T u = pProduct[n]*m0; BNU_CHUNK_T t = pProduct[nsM +n +1] + carry; extension = cpAddMulDgt_BNU(pProduct+n, pModulus, nsM, u); ADD_AB(carry, pProduct[nsM+n], pProduct[nsM+n], extension); t += carry; carry = t 4096? 6 : /* 4096- .. . */ bitsize> 2666? 5 : /* 2666 - 4095 */ #endif bitsize> 717? 4 : /* 717 - 2665 */ bitsize> 178? 3 : /* 178 - 716 */ bitsize> 41? 2 : 1; /* 41 - 177 */ #else IPP_UNREFERENCED_PARAMETER(bitsize); return 1; #endif } /* // Montgomery encoding/decoding */ __IPPCP_INLINE cpSize gsMontEnc_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pXreg, cpSize nsX, const gsModEngine* pMont) { cpSize nsM = MOD_LEN( pMont ); ZEXPAND_COPY_BNU(pR, nsM, pXreg, nsX); MOD_METHOD( pMont )->encode(pR, pR, (gsModEngine*)pMont); return nsM; } __IPPCP_INLINE cpSize gsMontDec_BNU(BNU_CHUNK_T* pR, const BNU_CHUNK_T* pXmont, gsModEngine* pMont) { cpSize nsM = MOD_LEN(pMont); MOD_METHOD( pMont )->decode(pR, pXmont, (gsModEngine*)pMont); return nsM; } __IPPCP_INLINE void gsMontEnc_BN(IppsBigNumState* pRbn, const IppsBigNumState* pXbn, gsModEngine* pMont) { BNU_CHUNK_T* pR = BN_NUMBER(pRbn); cpSize nsM = MOD_LEN(pMont); gsMontEnc_BNU(pR, BN_NUMBER(pXbn), BN_SIZE(pXbn), pMont); FIX_BNU(pR, nsM); BN_SIZE(pRbn) = nsM; BN_SIGN(pRbn) = ippBigNumPOS; } /* exponentiation buffer size */ #define gsMontExpBinBuffer OWNAPI(gsMontExpBinBuffer) IPP_OWN_DECL (cpSize, gsMontExpBinBuffer, (int modulusBits)) #define gsMontExpWinBuffer OWNAPI(gsMontExpWinBuffer) IPP_OWN_DECL (cpSize, gsMontExpWinBuffer, (int modulusBits)) /* exponentiation prototype */ IPP_OWN_FUNPTR (cpSize, ngMontExp, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) IPP_OWN_FUNPTR (cpSize, ngMontDualExp, (BNU_CHUNK_T* dataY[2], const BNU_CHUNK_T* dataX[2], cpSize nsX[2], const BNU_CHUNK_T* dataE[2], gsModEngine* pMont[2], BNU_CHUNK_T* pBuffer)) /* // "fast" and "safe" binary montgomery exponentiation ("fast" version) */ #define gsMontExpBin_BNU OWNAPI(gsMontExpBin_BNU) IPP_OWN_DECL (cpSize, gsMontExpBin_BNU, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsModExpBin_BNU OWNAPI(gsModExpBin_BNU) IPP_OWN_DECL (cpSize, gsModExpBin_BNU, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsMontExpBin_BNU_sscm OWNAPI(gsMontExpBin_BNU_sscm) IPP_OWN_DECL (cpSize, gsMontExpBin_BNU_sscm, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pX, cpSize nsX, const BNU_CHUNK_T* pE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsModExpBin_BNU_sscm OWNAPI(gsModExpBin_BNU_sscm) IPP_OWN_DECL (cpSize, gsModExpBin_BNU_sscm, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pX, cpSize nsX, const BNU_CHUNK_T* pE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) /* // "fast" and "safe" fixed-size window montgomery exponentiation */ #define gsMontExpWin_BNU OWNAPI(gsMontExpWin_BNU) IPP_OWN_DECL (cpSize, gsMontExpWin_BNU, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsModExpWin_BNU OWNAPI(gsModExpWin_BNU) IPP_OWN_DECL (cpSize, gsModExpWin_BNU, (BNU_CHUNK_T* pY, const BNU_CHUNK_T* pX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsMontExpWin_BNU_sscm OWNAPI(gsMontExpWin_BNU_sscm) IPP_OWN_DECL (cpSize, gsMontExpWin_BNU_sscm, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsModExpWin_BNU_sscm OWNAPI(gsModExpWin_BNU_sscm) IPP_OWN_DECL (cpSize, gsModExpWin_BNU_sscm, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nbitsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #endif /* _CP_NG_MONT_EXP_STUFF_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_avx2.c000066400000000000000000000615311470420105600261350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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 "owncp.h" #if (_IPP32E>=_IPP32E_L9) #include "pcpbnuimpl.h" #include "pcpbnumisc.h" #include "pcpngmontexpstuff.h" #include "pcpngmontexpstuff_avx2.h" #include "gsscramble.h" #include "pcpmask_ct.h" //tbcd: temporary excluded: #include /* converts regular (base = 2^32) representation (pRegular, regLen) into "redundant" (base = 2^DIGIT_SIZE) represenrartion (pRep, repLen) return 1 note: 1) repLen >= (bitsize +DIGIT_SIZE-1)/DIGIT_SIZE for complete conversion 2) regular representation should expanded by at least one zero value, pre-requisite: pRegular[regLen] == 0 to make conversion correct 3) caller must provide suitable lengths of regular and redundant representations so, conversion does correct */ static int regular_dig27(Ipp64u* pRep27, int repLen, const Ipp32u* pRegular, int regLen) { /* expected number of digit in redundant representation */ int n = cpDigitNum_avx2(regLen*BITSIZE(Ipp32u), EXP_DIGIT_SIZE_AVX2); //tbcd: temporary excluded: assert(pRegular[regLen]==0); /* test pre-requisite */ { int redBit; /* output representatin bit */ int i; for(i=0, redBit=0; i>= shift; pRep27[i] = x & EXP_DIGIT_MASK_AVX2; } /* expands by zeros if necessary */ for(; i=NORM_DIGSIZE_AVX2) { pRegular[idx++] = (Ipp32u)(x & NORM_MASK_AVX2); x >>= NORM_DIGSIZE_AVX2; shift -= NORM_DIGSIZE_AVX2; } } if(idx0; nsE--) { eValue = dataE[nsE-1]; for(n=0; n0; nsE--) { BNU_CHUNK_T eValue = dataE[nsE-1]; int n; for(n=BNU_CHUNK_BITS; n>0; n--) { /* T = ( msb(eValue) )? X : mont(1) */ BNU_CHUNK_T mask = cpIsMsb_ct(eValue); eValue <<= 1; cpMaskedCopyBNU_ct(redT, mask, redX, redR, redLen); /* squaring: Y = Y^2 */ cpMontSqr_avx2(redY, redY, redM, redLen, k0, redBuffer); #ifdef _EXP_AVX2_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif /* and multiply: Y = Y * T */ cpMontMul_avx2(redY, redY, redT, redM, redLen, k0, redBuffer); } } /* convert result back to regular domain */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; cpMontMul_avx2(redY, redY, redT, redM, redLen, k0, redBuffer); dig27_regular((Ipp32u*)dataY, nsM*sizeof(BNU_CHUNK_T)/sizeof(ipp32u), redY, redLen); return nsM; } #endif /* !_USE_WINDOW_EXP_ */ #if defined(_USE_WINDOW_EXP_) /* // "fast" fixed-size window montgomery exponentiation // // scratch buffer structure: // precomputed table of multipliers[(1< bitSizeE > 0), it is checked in initialization phase by (ippsRSA_GetSizePublickey() and ippsRSA_InitPublicKey). Buffer "redE" assigned for copy of dataE, is 1 (64-bit) chunk longer than size of RSA modulus, therefore the access "*((Ipp32u*)((Ipp16u*)redE+ eBit/BITSIZE(Ipp16u)))" is always inside the boundary. */ /* extract 1-st window value */ Ipp32u eChunk = *((Ipp32u*)((Ipp16u*)redE+ eBit/BITSIZE(Ipp16u))); int shift = eBit & 0xF; cpSize windowVal = (cpSize)((eChunk>>shift) &wmask); /* initialize result */ COPY_BNU(redY, redTable+windowVal*redLen, redLen); #ifdef _EXP_AVX2_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0; n>shift) &wmask); /* precomputed value muptiplication */ if(windowVal) { cpMontMul_avx2(redY, redY, redTable+windowVal*redLen, redM, redLen, k0, redBuffer); #ifdef _EXP_AVX2_DEBUG_ COPY_BNU(redT, redTable+windowVal*redBufferLen, redBufferLen); cpMontMul_avx2(redY, redY, redT, redM, redLen, k0, redBuffer); debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif } } } #ifdef _EXP_AVX2_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif /* convert result back */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; cpMontMul_avx2(redY, redY, redT, redM, redLen, k0, redBuffer); dig27_regular((Ipp32u*)dataY, nsM*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(ipp32u)), redY, redLen); return nsM; } /* // "safe" fixed-size window montgomery exponentiation // // scratch buffer structure: // precomputed table of multipliers[(1<>shift) &wmask); /* initialize result */ gsScrambleGet_sscm(redY, redLen, redTable, windowVal, window); #ifdef _EXP_AVX2_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0; n>shift) &wmask); /* exptact precomputed value and multiply */ gsScrambleGet_sscm(redT, redLen, redTable, windowVal, window); cpMontMul_avx2(redY, redY, redT, redM, redLen, k0, redBuffer); #ifdef _EXP_AVX2_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif } } #ifdef _EXP_AVX2_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, redLen, dataM, dataRR, nsM, k0, redBuffer); #endif /* convert result back */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; cpMontMul_avx2(redY, redY, redT, redM, redLen, k0, redBuffer); dig27_regular((Ipp32u*)dataY, nsM*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(ipp32u)), redY, redLen); return nsM; } #endif /* _USE_WINDOW_EXP_ */ #endif /* _IPP32E_L9 */ cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_avx2.h000066400000000000000000000116541470420105600261430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions of AVX2 Montgomery Exp // */ #include "owncp.h" #if (_IPP32E>=_IPP32E_L9) #include "pcpbnuimpl.h" #include "pcpngmontexpstuff.h" #define RSA_AVX2_MIN_BITSIZE (1024) #define RSA_AVX2_MAX_BITSIZE (13*1024) #define NORM_DIGSIZE_AVX2 (BITSIZE(Ipp32u)) #define NORM_BASE_AVX2 ((Ipp64u)1<=_IPP32E_K1) #if defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma warning(disable: 4310) // cast truncates constant value in MSVC #endif #include "pcptool.h" #include "pcpbnuimpl.h" #include "pcpbnumisc.h" #include "pcpngmontexpstuff.h" #include "pcpngmontexpstuff_avx512.h" #include "gsscramble.h" #include "pcpmask_ct.h" /* ams functions */ IPP_OWN_FUNPTR (void, cpAMM52, (Ipp64u* out, const Ipp64u* a, const Ipp64u* b, const Ipp64u* m, Ipp64u k0, int len, Ipp64u* res)) static void AMM52(Ipp64u* out, const Ipp64u* a, const Ipp64u* b, const Ipp64u* m, Ipp64u k0, int len, Ipp64u* res) { #define NUM64 ((Ipp32s)(sizeof(__m512i)/sizeof(Ipp64u))) __mmask8 k1 = (__mmask8)_mm512_kmov(0x02); /* mask of the 2-nd element */ __m512i zero = _mm512_setzero_si512(); /* zeros */ int n; int tail = len & (NUM64 -1); int expLen = len; if(tail) expLen += (NUM64 - tail); /* make sure not inplace operation */ //tbcd: temporary excluded: assert(res!=a); //tbcd: temporary excluded: assert(res!=b); /* set result to zero */ for(n=0; n>= EXP_DIGIT_SIZE_AVX512; } } } static void AMM52x20(Ipp64u* out, const Ipp64u* a, const Ipp64u* b, const Ipp64u* m, Ipp64u k0, int len, Ipp64u* res) { __mmask8 k2 = (__mmask8)_mm512_kmov(0x0f); /* mask of the 0-3 elements */ /* load a */ __m512i A0 = _mm512_loadu_si512(a); __m512i A1 = _mm512_loadu_si512(a+NUM64); __m512i A2 = _mm512_maskz_loadu_epi64(k2, a+2*NUM64); /* load m */ __m512i M0 = _mm512_loadu_si512(m); __m512i M1 = _mm512_loadu_si512(m+NUM64); __m512i M2 = _mm512_maskz_loadu_epi64(k2, m+2*NUM64); /* R0, R1, R2 holds temporary result */ __m512i R0 = _mm512_setzero_si512(); __m512i R1 = _mm512_setzero_si512(); __m512i R2 = _mm512_setzero_si512(); __m512i ZERO = _mm512_setzero_si512(); /* zeros */ __m512i K = _mm512_set1_epi64((Ipp64s)k0); IPP_UNREFERENCED_PARAMETER(len); IPP_UNREFERENCED_PARAMETER(res); __mmask8 k1 = (__mmask8)_mm512_kmov(0x01); /* mask of the 0 element */ int i; for(i=0; i<20; i++) { __m512i Bi = _mm512_set1_epi64((Ipp64s)b[i]); /* bloadcast(b[i]) */ __m512i Yi = _mm512_setzero_si512(); /* Yi = 0 */ __m512i tmp; R0 = _mm512_madd52lo_epu64(R0, A0, Bi); /* R += A*Bi (lo) */ R1 = _mm512_madd52lo_epu64(R1, A1, Bi); R2 = _mm512_madd52lo_epu64(R2, A2, Bi); Yi = _mm512_madd52lo_epu64(ZERO, K, R0); /* Yi = R0*K */ Yi = _mm512_permutexvar_epi64(ZERO, Yi); /* broadcast Yi */ R0 = _mm512_madd52lo_epu64(R0, M0, Yi); /* R += M*Yi (lo) */ R1 = _mm512_madd52lo_epu64(R1, M1, Yi); R2 = _mm512_madd52lo_epu64(R2, M2, Yi); /* shift R */ tmp = _mm512_maskz_srli_epi64(k1, R0, EXP_DIGIT_SIZE_AVX512); R0 = _mm512_alignr_epi64(R1, R0, 1); R1 = _mm512_alignr_epi64(R2, R1, 1); R2 = _mm512_alignr_epi64(ZERO, R2, 1); R0 = _mm512_add_epi64(R0, tmp); R0 = _mm512_madd52hi_epu64(R0, A0, Bi); /* R += A*Bi (hi) */ R1 = _mm512_madd52hi_epu64(R1, A1, Bi); R2 = _mm512_madd52hi_epu64(R2, A2, Bi); R0 = _mm512_madd52hi_epu64(R0, M0, Yi); /* R += M*Yi (hi) */ R1 = _mm512_madd52hi_epu64(R1, M1, Yi); R2 = _mm512_madd52hi_epu64(R2, M2, Yi); } /* store de-normilized result */ _mm512_storeu_si512(out, R0); _mm512_storeu_si512(out+NUM64, R1); _mm512_mask_storeu_epi64(out+2*NUM64, k2, R2); /* normalize result */ { Ipp64u acc = 0; #if !defined(_MSC_VER) || defined(__INTEL_COMPILER) // unknown for msvc #pragma nounroll #endif for(i=0; i<20; i++) { acc += out[i]; out[i] = acc & EXP_DIGIT_MASK_AVX512; acc >>= EXP_DIGIT_SIZE_AVX512; } } } static void AMM52x40(Ipp64u* out, const Ipp64u* a, const Ipp64u* b, const Ipp64u* m, Ipp64u k0, int len, Ipp64u* res) { /* load a */ __m512i A0 = _mm512_loadu_si512(a); __m512i A1 = _mm512_loadu_si512(a+NUM64); __m512i A2 = _mm512_loadu_si512(a+2*NUM64); __m512i A3 = _mm512_loadu_si512(a+3*NUM64); __m512i A4 = _mm512_loadu_si512(a+4*NUM64); /* load m */ __m512i M0 = _mm512_loadu_si512(m); __m512i M1 = _mm512_loadu_si512(m+NUM64); __m512i M2 = _mm512_loadu_si512(m+2*NUM64); __m512i M3 = _mm512_loadu_si512(m+3*NUM64); __m512i M4 = _mm512_loadu_si512(m+4*NUM64); /* R0, R1, R2, R3, R4 holds temporary result */ __m512i R0 = _mm512_setzero_si512(); __m512i R1 = _mm512_setzero_si512(); __m512i R2 = _mm512_setzero_si512(); __m512i R3 = _mm512_setzero_si512(); __m512i R4 = _mm512_setzero_si512(); __m512i ZERO = _mm512_setzero_si512(); /* zeros */ __m512i K = _mm512_set1_epi64((Ipp64s)k0); IPP_UNREFERENCED_PARAMETER(len); IPP_UNREFERENCED_PARAMETER(res); __mmask8 k1 = (__mmask8)_mm512_kmov(0x01); /* mask of the 0 element */ int i; for(i=0; i<40; i++) { __m512i Bi = _mm512_set1_epi64((Ipp64s)b[i]); /* bloadcast(b[i]) */ __m512i Yi = _mm512_setzero_si512(); /* Yi = 0 */ __m512i tmp; R0 = _mm512_madd52lo_epu64(R0, A0, Bi); /* R += A*Bi (lo) */ R1 = _mm512_madd52lo_epu64(R1, A1, Bi); R2 = _mm512_madd52lo_epu64(R2, A2, Bi); R3 = _mm512_madd52lo_epu64(R3, A3, Bi); R4 = _mm512_madd52lo_epu64(R4, A4, Bi); Yi = _mm512_madd52lo_epu64(ZERO, K, R0); /* Yi = R0*K */ Yi = _mm512_permutexvar_epi64(ZERO, Yi); /* broadcast Yi */ R0 = _mm512_madd52lo_epu64(R0, M0, Yi); /* R += M*Yi (lo) */ R1 = _mm512_madd52lo_epu64(R1, M1, Yi); R2 = _mm512_madd52lo_epu64(R2, M2, Yi); R3 = _mm512_madd52lo_epu64(R3, M3, Yi); R4 = _mm512_madd52lo_epu64(R4, M4, Yi); /* shift R */ tmp = _mm512_maskz_srli_epi64(k1, R0, EXP_DIGIT_SIZE_AVX512); R0 = _mm512_alignr_epi64(R1, R0, 1); R1 = _mm512_alignr_epi64(R2, R1, 1); R2 = _mm512_alignr_epi64(R3, R2, 1); R3 = _mm512_alignr_epi64(R4, R3, 1); R4 = _mm512_alignr_epi64(ZERO, R4, 1); R0 = _mm512_add_epi64(R0, tmp); R0 = _mm512_madd52hi_epu64(R0, A0, Bi); /* R += A*Bi (hi) */ R1 = _mm512_madd52hi_epu64(R1, A1, Bi); R2 = _mm512_madd52hi_epu64(R2, A2, Bi); R3 = _mm512_madd52hi_epu64(R3, A3, Bi); R4 = _mm512_madd52hi_epu64(R4, A4, Bi); R0 = _mm512_madd52hi_epu64(R0, M0, Yi); /* R += M*Yi (hi) */ R1 = _mm512_madd52hi_epu64(R1, M1, Yi); R2 = _mm512_madd52hi_epu64(R2, M2, Yi); R3 = _mm512_madd52hi_epu64(R3, M3, Yi); R4 = _mm512_madd52hi_epu64(R4, M4, Yi); } /* store de-normilized result */ _mm512_storeu_si512(out, R0); _mm512_storeu_si512(out+NUM64, R1); _mm512_storeu_si512(out+2*NUM64, R2); _mm512_storeu_si512(out+3*NUM64, R3); _mm512_storeu_si512(out+4*NUM64, R4); /* normalize result */ { Ipp64u acc = 0; #if !defined(_MSC_VER) || defined(__INTEL_COMPILER) // unknown for msvc #pragma nounroll #endif for(i=0; i<40; i++) { acc += out[i]; out[i] = acc & EXP_DIGIT_MASK_AVX512; acc >>= EXP_DIGIT_SIZE_AVX512; } } } static void AMM52x60(Ipp64u* out, const Ipp64u* a, const Ipp64u* b, const Ipp64u* m, Ipp64u k0, int len, Ipp64u* res) { __mmask8 k2 = (__mmask8)_mm512_kmov(0x0f); /* mask of the 0-3 elements */ /* load a */ __m512i A0 = _mm512_loadu_si512(a); __m512i A1 = _mm512_loadu_si512(a+NUM64); __m512i A2 = _mm512_loadu_si512(a+2*NUM64); __m512i A3 = _mm512_loadu_si512(a+3*NUM64); __m512i A4 = _mm512_loadu_si512(a+4*NUM64); __m512i A5 = _mm512_loadu_si512(a+5*NUM64); __m512i A6 = _mm512_loadu_si512(a+6*NUM64); __m512i A7 = _mm512_maskz_loadu_epi64(k2, a+7*NUM64); /* load m */ __m512i M0 = _mm512_loadu_si512(m); __m512i M1 = _mm512_loadu_si512(m+NUM64); __m512i M2 = _mm512_loadu_si512(m+2*NUM64); __m512i M3 = _mm512_loadu_si512(m+3*NUM64); __m512i M4 = _mm512_loadu_si512(m+4*NUM64); __m512i M5 = _mm512_loadu_si512(m+5*NUM64); __m512i M6 = _mm512_loadu_si512(m+6*NUM64); __m512i M7 = _mm512_maskz_loadu_epi64(k2, m+7*NUM64); /* R0, R1, R2, R3, R4, R5, R6, R7 holds temporary result */ __m512i R0 = _mm512_setzero_si512(); __m512i R1 = _mm512_setzero_si512(); __m512i R2 = _mm512_setzero_si512(); __m512i R3 = _mm512_setzero_si512(); __m512i R4 = _mm512_setzero_si512(); __m512i R5 = _mm512_setzero_si512(); __m512i R6 = _mm512_setzero_si512(); __m512i R7 = _mm512_setzero_si512(); __m512i ZERO = _mm512_setzero_si512(); /* zeros */ __m512i K = _mm512_set1_epi64((Ipp64s)k0); IPP_UNREFERENCED_PARAMETER(len); IPP_UNREFERENCED_PARAMETER(res); __mmask8 k1 = (__mmask8)_mm512_kmov(0x01); /* mask of the 0 element */ int i; for(i=0; i<60; i++) { __m512i Bi = _mm512_set1_epi64((Ipp64s)b[i]); /* bloadcast(b[i]) */ __m512i Yi = _mm512_setzero_si512(); /* Yi = 0 */ __m512i tmp; R0 = _mm512_madd52lo_epu64(R0, A0, Bi); /* R += A*Bi (lo) */ R1 = _mm512_madd52lo_epu64(R1, A1, Bi); R2 = _mm512_madd52lo_epu64(R2, A2, Bi); R3 = _mm512_madd52lo_epu64(R3, A3, Bi); R4 = _mm512_madd52lo_epu64(R4, A4, Bi); R5 = _mm512_madd52lo_epu64(R5, A5, Bi); R6 = _mm512_madd52lo_epu64(R6, A6, Bi); R7 = _mm512_madd52lo_epu64(R7, A7, Bi); Yi = _mm512_madd52lo_epu64(ZERO, K, R0); /* Yi = R0*K */ Yi = _mm512_permutexvar_epi64(ZERO, Yi); /* broadcast Yi */ R0 = _mm512_madd52lo_epu64(R0, M0, Yi); /* R += M*Yi (lo) */ R1 = _mm512_madd52lo_epu64(R1, M1, Yi); R2 = _mm512_madd52lo_epu64(R2, M2, Yi); R3 = _mm512_madd52lo_epu64(R3, M3, Yi); R4 = _mm512_madd52lo_epu64(R4, M4, Yi); R5 = _mm512_madd52lo_epu64(R5, M5, Yi); R6 = _mm512_madd52lo_epu64(R6, M6, Yi); R7 = _mm512_madd52lo_epu64(R7, M7, Yi); /* shift R */ tmp = _mm512_maskz_srli_epi64(k1, R0, EXP_DIGIT_SIZE_AVX512); R0 = _mm512_alignr_epi64(R1, R0, 1); R1 = _mm512_alignr_epi64(R2, R1, 1); R2 = _mm512_alignr_epi64(R3, R2, 1); R3 = _mm512_alignr_epi64(R4, R3, 1); R4 = _mm512_alignr_epi64(R5, R4, 1); R5 = _mm512_alignr_epi64(R6, R5, 1); R6 = _mm512_alignr_epi64(R7, R6, 1); R7 = _mm512_alignr_epi64(ZERO, R7, 1); R0 = _mm512_add_epi64(R0, tmp); R0 = _mm512_madd52hi_epu64(R0, A0, Bi); /* R += A*Bi (hi) */ R1 = _mm512_madd52hi_epu64(R1, A1, Bi); R2 = _mm512_madd52hi_epu64(R2, A2, Bi); R3 = _mm512_madd52hi_epu64(R3, A3, Bi); R4 = _mm512_madd52hi_epu64(R4, A4, Bi); R5 = _mm512_madd52hi_epu64(R5, A5, Bi); R6 = _mm512_madd52hi_epu64(R6, A6, Bi); R7 = _mm512_madd52hi_epu64(R7, A7, Bi); R0 = _mm512_madd52hi_epu64(R0, M0, Yi); /* R += M*Yi (hi) */ R1 = _mm512_madd52hi_epu64(R1, M1, Yi); R2 = _mm512_madd52hi_epu64(R2, M2, Yi); R3 = _mm512_madd52hi_epu64(R3, M3, Yi); R4 = _mm512_madd52hi_epu64(R4, M4, Yi); R5 = _mm512_madd52hi_epu64(R5, M5, Yi); R6 = _mm512_madd52hi_epu64(R6, M6, Yi); R7 = _mm512_madd52hi_epu64(R7, M7, Yi); } /* store de-normilized result */ _mm512_storeu_si512(out, R0); _mm512_storeu_si512(out+NUM64, R1); _mm512_storeu_si512(out+2*NUM64, R2); _mm512_storeu_si512(out+3*NUM64, R3); _mm512_storeu_si512(out+4*NUM64, R4); _mm512_storeu_si512(out+5*NUM64, R5); _mm512_storeu_si512(out+6*NUM64, R6); _mm512_mask_storeu_epi64(out+7*NUM64, k2, R7); /* normalize result */ { Ipp64u acc = 0; #if !defined(_MSC_VER) || defined(__INTEL_COMPILER) // unknown for msvc #pragma nounroll #endif for(i=0; i<60; i++) { acc += out[i]; out[i] = acc & EXP_DIGIT_MASK_AVX512; acc >>= EXP_DIGIT_SIZE_AVX512; } } } static void AMM52x79(Ipp64u* out, const Ipp64u* a, const Ipp64u* b, const Ipp64u* m, Ipp64u k0, int len, Ipp64u* res) { __mmask8 k2 = (__mmask8)_mm512_kmov(0x7f); /* mask of the 0-7 elements */ /* load a */ __m512i A0 = _mm512_loadu_si512(a); __m512i A1 = _mm512_loadu_si512(a+NUM64); __m512i A2 = _mm512_loadu_si512(a+2*NUM64); __m512i A3 = _mm512_loadu_si512(a+3*NUM64); __m512i A4 = _mm512_loadu_si512(a+4*NUM64); __m512i A5 = _mm512_loadu_si512(a+5*NUM64); __m512i A6 = _mm512_loadu_si512(a+6*NUM64); __m512i A7 = _mm512_loadu_si512(a+7*NUM64); __m512i A8 = _mm512_loadu_si512(a+8*NUM64); __m512i A9 = _mm512_maskz_loadu_epi64(k2, a+9*NUM64); /* load m */ __m512i M0 = _mm512_loadu_si512(m); __m512i M1 = _mm512_loadu_si512(m+NUM64); __m512i M2 = _mm512_loadu_si512(m+2*NUM64); __m512i M3 = _mm512_loadu_si512(m+3*NUM64); __m512i M4 = _mm512_loadu_si512(m+4*NUM64); __m512i M5 = _mm512_loadu_si512(m+5*NUM64); __m512i M6 = _mm512_loadu_si512(m+6*NUM64); __m512i M7 = _mm512_loadu_si512(m+7*NUM64); __m512i M8 = _mm512_loadu_si512(m+8*NUM64); __m512i M9 = _mm512_maskz_loadu_epi64(k2, m+9*NUM64); /* R0, R1, R2, R3, R4, R5, R6, R7, R8, R9 holds temporary result */ __m512i R0 = _mm512_setzero_si512(); __m512i R1 = _mm512_setzero_si512(); __m512i R2 = _mm512_setzero_si512(); __m512i R3 = _mm512_setzero_si512(); __m512i R4 = _mm512_setzero_si512(); __m512i R5 = _mm512_setzero_si512(); __m512i R6 = _mm512_setzero_si512(); __m512i R7 = _mm512_setzero_si512(); __m512i R8 = _mm512_setzero_si512(); __m512i R9 = _mm512_setzero_si512(); __m512i ZERO = _mm512_setzero_si512(); /* zeros */ __m512i K = _mm512_set1_epi64((Ipp64s)k0); IPP_UNREFERENCED_PARAMETER(len); IPP_UNREFERENCED_PARAMETER(res); __mmask8 k1 = (__mmask8)_mm512_kmov(0x01); /* mask of the 0 element */ int i; for(i=0; i<79; i++) { __m512i Bi = _mm512_set1_epi64((Ipp64s)b[i]); /* bloadcast(b[i]) */ __m512i Yi = _mm512_setzero_si512(); /* Yi = 0 */ __m512i tmp; R0 = _mm512_madd52lo_epu64(R0, A0, Bi); /* R += A*Bi (lo) */ R1 = _mm512_madd52lo_epu64(R1, A1, Bi); R2 = _mm512_madd52lo_epu64(R2, A2, Bi); R3 = _mm512_madd52lo_epu64(R3, A3, Bi); R4 = _mm512_madd52lo_epu64(R4, A4, Bi); R5 = _mm512_madd52lo_epu64(R5, A5, Bi); R6 = _mm512_madd52lo_epu64(R6, A6, Bi); R7 = _mm512_madd52lo_epu64(R7, A7, Bi); R8 = _mm512_madd52lo_epu64(R8, A8, Bi); R9 = _mm512_madd52lo_epu64(R9, A9, Bi); Yi = _mm512_madd52lo_epu64(ZERO, K, R0); /* Yi = R0*K */ Yi = _mm512_permutexvar_epi64(ZERO, Yi); /* broadcast Yi */ R0 = _mm512_madd52lo_epu64(R0, M0, Yi); /* R += M*Yi (lo) */ R1 = _mm512_madd52lo_epu64(R1, M1, Yi); R2 = _mm512_madd52lo_epu64(R2, M2, Yi); R3 = _mm512_madd52lo_epu64(R3, M3, Yi); R4 = _mm512_madd52lo_epu64(R4, M4, Yi); R5 = _mm512_madd52lo_epu64(R5, M5, Yi); R6 = _mm512_madd52lo_epu64(R6, M6, Yi); R7 = _mm512_madd52lo_epu64(R7, M7, Yi); R8 = _mm512_madd52lo_epu64(R8, M8, Yi); R9 = _mm512_madd52lo_epu64(R9, M9, Yi); /* shift R */ tmp = _mm512_maskz_srli_epi64(k1, R0, EXP_DIGIT_SIZE_AVX512); R0 = _mm512_alignr_epi64(R1, R0, 1); R1 = _mm512_alignr_epi64(R2, R1, 1); R2 = _mm512_alignr_epi64(R3, R2, 1); R3 = _mm512_alignr_epi64(R4, R3, 1); R4 = _mm512_alignr_epi64(R5, R4, 1); R5 = _mm512_alignr_epi64(R6, R5, 1); R6 = _mm512_alignr_epi64(R7, R6, 1); R7 = _mm512_alignr_epi64(R8, R7, 1); R8 = _mm512_alignr_epi64(R9, R8, 1); R9 = _mm512_alignr_epi64(ZERO, R9, 1); R0 = _mm512_add_epi64(R0, tmp); R0 = _mm512_madd52hi_epu64(R0, A0, Bi); /* R += A*Bi (hi) */ R1 = _mm512_madd52hi_epu64(R1, A1, Bi); R2 = _mm512_madd52hi_epu64(R2, A2, Bi); R3 = _mm512_madd52hi_epu64(R3, A3, Bi); R4 = _mm512_madd52hi_epu64(R4, A4, Bi); R5 = _mm512_madd52hi_epu64(R5, A5, Bi); R6 = _mm512_madd52hi_epu64(R6, A6, Bi); R7 = _mm512_madd52hi_epu64(R7, A7, Bi); R8 = _mm512_madd52hi_epu64(R8, A8, Bi); R9 = _mm512_madd52hi_epu64(R9, A9, Bi); R0 = _mm512_madd52hi_epu64(R0, M0, Yi); /* R += M*Yi (hi) */ R1 = _mm512_madd52hi_epu64(R1, M1, Yi); R2 = _mm512_madd52hi_epu64(R2, M2, Yi); R3 = _mm512_madd52hi_epu64(R3, M3, Yi); R4 = _mm512_madd52hi_epu64(R4, M4, Yi); R5 = _mm512_madd52hi_epu64(R5, M5, Yi); R6 = _mm512_madd52hi_epu64(R6, M6, Yi); R7 = _mm512_madd52hi_epu64(R7, M7, Yi); R8 = _mm512_madd52hi_epu64(R8, M8, Yi); R9 = _mm512_madd52hi_epu64(R9, M9, Yi); } /* store de-normilized result */ _mm512_storeu_si512(out, R0); _mm512_storeu_si512(out+NUM64, R1); _mm512_storeu_si512(out+2*NUM64, R2); _mm512_storeu_si512(out+3*NUM64, R3); _mm512_storeu_si512(out+4*NUM64, R4); _mm512_storeu_si512(out+5*NUM64, R5); _mm512_storeu_si512(out+6*NUM64, R6); _mm512_storeu_si512(out+7*NUM64, R7); _mm512_storeu_si512(out+8*NUM64, R8); _mm512_mask_storeu_epi64(out+9*NUM64, k2, R9); /* normalize result */ { Ipp64u acc = 0; #if !defined(_MSC_VER) || defined(__INTEL_COMPILER) // unknown for msvc #pragma nounroll #endif for(i=0; i<79; i++) { acc += out[i]; out[i] = acc & EXP_DIGIT_MASK_AVX512; acc >>= EXP_DIGIT_SIZE_AVX512; } } } /* ======= degugging section =========================================*/ //#define _EXP_AVX512_DEBUG_ #ifdef _EXP_AVX512_DEBUG_ #include "pcpmontred.h" void debugToConvMontDomain(BNU_CHUNK_T* pR, const BNU_CHUNK_T* redInp, const BNU_CHUNK_T* redM, int almMM_bitsize, const BNU_CHUNK_T* pM, const BNU_CHUNK_T* pRR, int nsM, BNU_CHUNK_T k0, BNU_CHUNK_T* pBuffer) { Ipp64u one[32] = { 1,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0 }; Ipp64u redT[32]; int redLen = NUMBER_OF_DIGITS(almMM_bitsize, EXP_DIGIT_SIZE_AVX512); AMM52(redT, redInp, one, redM, k0, redLen, pBuffer); dig52_regular(pR, redT, almMM_bitsize); //cpMontMul_BNU(pR, should be changed // redT, nsM, // pRR, nsM, // pM, nsM, k0, // pBuffer, 0); cpMul_BNU(pBuffer, pR,nsM, pRR,nsM, 0); cpMontRed_BNU_opt(pR, pBuffer, pM, nsM, k0); } #endif /* ===================================================================*/ IPP_OWN_DEFN (cpSize, gsMontExpBinBuffer_avx512, (int modulusBits)) { cpSize redNum = numofVariable_avx512(modulusBits); /* "sizeof" variable */ cpSize redBufferNum = numofVariableBuff_avx512(redNum,8); /* "sizeof" variable buffer */ return redBufferNum *8; } #if defined(_USE_WINDOW_EXP_) IPP_OWN_DEFN (cpSize, gsMontExpWinBuffer_avx512, (int modulusBits)) { cpSize w = gsMontExp_WinSize(modulusBits); cpSize redNum = numofVariable_avx512(modulusBits); /* "sizeof" variable */ cpSize redBufferNum = numofVariableBuff_avx512(redNum,8); /* "sizeof" variable buffer */ cpSize bufferNum = CACHE_LINE_SIZE/(Ipp32s)sizeof(BNU_CHUNK_T) + gsGetScrambleBufferSize(redNum, w) /* pre-computed table */ + redBufferNum *7; /* addition 7 variables */ return bufferNum; } #endif /* _USE_WINDOW_EXP_ */ /* // "fast" binary montgomery exponentiation // // scratch buffer structure: // redX[redBufferLen] // redT[redBufferLen] // redY[redBufferLen] // redM[redBufferLen] // redBuffer[redBufferLen*3] */ IPP_OWN_DEFN (cpSize, gsMontExpBin_BNU_avx512, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { const BNU_CHUNK_T* dataM = MOD_MODULUS(pMont); const BNU_CHUNK_T* dataRR= MOD_MNT_R2(pMont); cpSize nsM = MOD_LEN(pMont); BNU_CHUNK_T k0 = MOD_MNT_FACTOR(pMont); cpSize nsE = BITS_BNU_CHUNK(bitsizeE); int modulusBitSize = BITSIZE_BNU(dataM, nsM); int cnvMM_bitsize = NUMBER_OF_DIGITS(modulusBitSize, BITSIZE(BNU_CHUNK_T)) * BITSIZE(BNU_CHUNK_T); int almMM_bitsize = cnvMM_bitsize+2; int redLen = NUMBER_OF_DIGITS(almMM_bitsize, EXP_DIGIT_SIZE_AVX512); int redBufferLen = numofVariableBuff_avx512(redLen,8); /* allocate buffers */ BNU_CHUNK_T* redX = pBuffer; BNU_CHUNK_T* redT = redX+redBufferLen; BNU_CHUNK_T* redY = redT+redBufferLen; BNU_CHUNK_T* redM = redY+redBufferLen; BNU_CHUNK_T* redBuffer = redM+redBufferLen; cpAMM52 ammFunc; switch (modulusBitSize) { case 1024: ammFunc = AMM52x20; break; case 2048: ammFunc = AMM52x40; break; case 3072: ammFunc = AMM52x60; break; case 4096: ammFunc = AMM52x79; break; default: ammFunc = AMM52; break; } /* convert modulus into reduced domain */ ZEXPAND_COPY_BNU(redBuffer, redBufferLen, dataM, nsM); regular_dig52(redM, redBufferLen, redBuffer, almMM_bitsize); /* compute target domain Montgomery converter RR' */ ZEXPAND_BNU(redBuffer, 0, redBufferLen); SET_BIT(redBuffer, (4*redLen*EXP_DIGIT_SIZE_AVX512- 4*cnvMM_bitsize)); regular_dig52(redY, redBufferLen, redBuffer, almMM_bitsize); ZEXPAND_COPY_BNU(redBuffer, redBufferLen, dataRR, nsM); regular_dig52(redT, redBufferLen, redBuffer, almMM_bitsize); ammFunc(redT, redT, redT, redM, k0, redLen, redBuffer); ammFunc(redT, redT, redY, redM, k0, redLen, redBuffer); /* convert base to Montgomery domain */ ZEXPAND_COPY_BNU(redY, redBufferLen/*nsX+1*/, dataX, nsX); regular_dig52(redX, redBufferLen, redY, almMM_bitsize); ammFunc(redX, redX, redT, redM, k0, redLen, redBuffer); /* init result */ COPY_BNU(redY, redX, redLen); FIX_BNU(dataE, nsE); { /* execute most significant part pE */ BNU_CHUNK_T eValue = dataE[nsE-1]; int n = cpNLZ_BNU(eValue)+1; eValue <<= n; for(; n0; nsE--) { eValue = dataE[nsE-1]; for(n=0; n0; nsE--) { BNU_CHUNK_T eValue = dataE[nsE-1]; int n; for(n=BNU_CHUNK_BITS; n>0; n--) { /* T = ( msb(eValue) )? X : mont(1) */ BNU_CHUNK_T mask = cpIsMsb_ct(eValue); eValue <<= 1; cpMaskedCopyBNU_ct(redT, mask, redX, redR, redLen); /* squaring: Y = Y*Y */ ammFunc(redY, redY, redY, redM, k0, redLen, redBuffer); /* and multiply: Y = Y * T */ ammFunc(redY, redY, redT, redM, k0, redLen, redBuffer); } } /* convert result back to regular domain */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; ammFunc(redY, redY, redT, redM, k0, redLen, redBuffer); dig52_regular(dataY, redY, cnvMM_bitsize); return nsM; } #endif /* !_USE_WINDOW_EXP_ */ #if defined(_USE_WINDOW_EXP_) /* // "fast" fixed-size window montgomery exponentiation // // scratch buffer structure: // precomputed table of multipliers[(1< bitSizeE > 0), it is checked in initialization phase by (ippsRSA_GetSizePublickey() and ippsRSA_InitPublicKey). Buffer "redE" assigned for copy of dataE, is 1 (64-bit) chunk longer than size of RSA modulus, therefore the access "*((Ipp32u*)((Ipp16u*)redE+ eBit/BITSIZE(Ipp16u)))" is always inside the boundary. */ /* extract 1-st window value */ Ipp32u eChunk = *((Ipp32u*)((Ipp16u*)redE+ eBit/BITSIZE(Ipp16u))); int shift = eBit & 0xF; cpSize windowVal = (cpSize)((eChunk>>shift) &wmask); /* initialize result */ ZEXPAND_COPY_BNU(redY, redBufferLen, redTable+windowVal*redLen, redLen); for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0; n>shift) &wmask); /* extract precomputed value and multiply */ if(windowVal) { ammFunc(redY, redY, redTable+windowVal*redLen, redM, k0, redLen, redBuffer); } } } /* convert result back */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; ammFunc(redY, redY, redT, redM, k0, redLen, redBuffer); dig52_regular(dataY, redY, cnvMM_bitsize); return nsM; } /* // "safe" fixed-size window montgomery exponentiation // // scratch buffer structure: // precomputed table of multipliers[(1<>shift) &wmask); /* initialize result */ gsScrambleGet_sscm(redY, redLen, redTable, windowVal, window); #ifdef _EXP_AVX512_DEBUG_ debugToConvMontDomain(dbgValue, redY, redM, almMM_bitsize, dataM, dataRR, nsM, k0, redBuffer); #endif for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0; n>shift) &wmask); /* exptact precomputed value and multiply */ gsScrambleGet_sscm(redT, redLen, redTable, windowVal, window); /* multiply */ ammFunc(redY, redY, redT, redM, k0, redLen, redBuffer); } } /* convert result back */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; ammFunc(redY, redY, redT, redM, k0, redLen, redBuffer); dig52_regular(dataY, redY, cnvMM_bitsize); return nsM; } #endif /* _USE_WINDOW_EXP_ */ #endif /* _IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_avx512.h000066400000000000000000000143221470420105600263040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions of AVX512 Montgomery Exp // */ #include "owncp.h" #if (_IPP32E>=_IPP32E_K1) #include "pcpbnuimpl.h" #include "pcpngmontexpstuff.h" #define RSA_AVX512_MIN_BITSIZE (1024) #define RSA_AVX512_MAX_BITSIZE (13*1024) #define EXP_DIGIT_SIZE_AVX512 (52) #define EXP_DIGIT_BASE_AVX512 (1<0; strLen--) { digit <<= 8; digit += (Ipp64u)(pStr[strLen-1]); } return digit; } /* regular => redundant conversion */ static void regular_dig52(Ipp64u* out, int outLen /* in qwords */, const Ipp64u* in, int inBitSize) { Ipp8u* inStr = (Ipp8u*)in; for(; inBitSize>=(2*EXP_DIGIT_SIZE_AVX512); inBitSize-=(2*EXP_DIGIT_SIZE_AVX512), out+=2) { out[0] = (*(Ipp64u*)inStr) & EXP_DIGIT_MASK_AVX512; inStr += 6; out[1] = ((*(Ipp64u*)inStr) >> 4) & EXP_DIGIT_MASK_AVX512; inStr += 7; outLen -= 2; } if(inBitSize>EXP_DIGIT_SIZE_AVX512) { Ipp64u digit = getDig52(inStr, 7); out[0] = digit & EXP_DIGIT_MASK_AVX512; inStr += 6; inBitSize -= EXP_DIGIT_SIZE_AVX512; digit = getDig52(inStr, BITS2WORD8_SIZE(inBitSize)); out[1] = digit>>4; out += 2; outLen -= 2; } else if(inBitSize>0) { out[0] = getDig52(inStr, BITS2WORD8_SIZE(inBitSize)); out++; outLen--; } for(; outLen>0; outLen--,out++) out[0] = 0; } /* converts "redundant" (base = 2^DIGIT_SIZE) representation into regular (base = 2^64) */ __IPPCP_INLINE void putDig52(Ipp8u* pStr, int strLen, Ipp64u digit) { for(; strLen>0; strLen--) { *pStr++ = (Ipp8u)(digit&0xFF); digit >>= 8; } } static void dig52_regular(Ipp64u* out, const Ipp64u* in, int outBitSize) { int i; int outLen = BITS2WORD64_SIZE(outBitSize); for(i=0; i=(2*EXP_DIGIT_SIZE_AVX512); outBitSize-=(2*EXP_DIGIT_SIZE_AVX512), in+=2) { (*(Ipp64u*)outStr) = in[0]; outStr+=6; (*(Ipp64u*)outStr) ^= in[1] << 4; outStr+=7; } if(outBitSize>EXP_DIGIT_SIZE_AVX512) { putDig52(outStr, 7, in[0]); outStr+=6; outBitSize -= EXP_DIGIT_SIZE_AVX512; putDig52(outStr, BITS2WORD8_SIZE(outBitSize), (in[1]<<4 | in[0]>>48)); } else if(outBitSize) { putDig52(outStr, BITS2WORD8_SIZE(outBitSize), in[0]); } } } /* exponentiation buffer size */ #define gsMontExpBinBuffer_avx512 OWNAPI(gsMontExpBinBuffer_avx512) IPP_OWN_DECL (cpSize, gsMontExpBinBuffer_avx512, (int modulusBits)) #define gsMontExpWinBuffer_avx512 OWNAPI(gsMontExpWinBuffer_avx512) IPP_OWN_DECL (cpSize, gsMontExpWinBuffer_avx512, (int modulusBits)) /* exponentiations */ #define gsMontExpBin_BNU_avx512 OWNAPI(gsMontExpBin_BNU_avx512) IPP_OWN_DECL (cpSize, gsMontExpBin_BNU_avx512, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsMontExpWin_BNU_avx512 OWNAPI(gsMontExpWin_BNU_avx512) IPP_OWN_DECL (cpSize, gsMontExpWin_BNU_avx512, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsMontExpBin_BNU_sscm_avx512 OWNAPI(gsMontExpBin_BNU_sscm_avx512) IPP_OWN_DECL (cpSize, gsMontExpBin_BNU_sscm_avx512, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) #define gsMontExpWin_BNU_sscm_avx512 OWNAPI(gsMontExpWin_BNU_sscm_avx512) IPP_OWN_DECL (cpSize, gsMontExpWin_BNU_sscm_avx512, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize nsE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) /* dual exponentiation buffer size */ #define gsMontDualExpWinBuffer_avx512 OWNAPI(gsMontDualExpWinBuffer_avx512) IPP_OWN_DECL (cpSize, gsMontDualExpWinBuffer_avx512, (int modulusBits)) /* dual exponentiation */ #define gsMontDualExpWin_BNU_sscm_avx512 OWNAPI(gsMontDualExpWin_BNU_sscm_avx512) IPP_OWN_DECL(cpSize, gsMontDualExpWin_BNU_sscm_avx512, (BNU_CHUNK_T* dataY[2], const BNU_CHUNK_T* dataX[2], cpSize nsX[2], const BNU_CHUNK_T* dataE[2], gsModEngine* pMont[2], BNU_CHUNK_T* pBuffer)) #endif /* _IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_bin.c000066400000000000000000000073731470420105600260310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Modular Exponentiation */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" IPP_OWN_DEFN (cpSize, gsMontExpBinBuffer, (int modulusBits)) { cpSize nsM = BITS_BNU_CHUNK(modulusBits); cpSize bufferNum = nsM; return bufferNum; } IPP_OWN_DEFN (cpSize, gsMontExpBin_BNU, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer) ) { cpSize nsM = MOD_LEN(pMont); cpSize nsE = BITS_BNU_CHUNK(bitsizeE); /* // test for special cases: // x^0 = 1 // 0^e = 0 */ if (cpEqu_BNU_CHUNK(dataE, nsE, 0)) { COPY_BNU(dataY, MOD_MNT_R(pMont), nsM); } else if (cpEqu_BNU_CHUNK(dataX, nsX, 0)) { ZEXPAND_BNU(dataY, 0, nsM); } /* general case */ else { /* allocate buffers */ BNU_CHUNK_T* dataT = pBuffer; /* copy and expand base to the modulus length */ ZEXPAND_COPY_BNU(dataT, nsM, dataX, nsX); /* copy */ COPY_BNU(dataY, dataT, nsM); FIX_BNU(dataE, nsE); /* execute most significant part pE */ { BNU_CHUNK_T eValue = dataE[nsE - 1]; int n = cpNLZ_BNU(eValue) + 1; eValue <<= n; for (; nsqr(dataY, dataY, pMont); /* and multiply R = R*X mod Modulus */ if (eValue & ((BNU_CHUNK_T)1 << (BNU_CHUNK_BITS - 1))) MOD_METHOD(pMont)->mul(dataY, dataY, dataT, pMont); } /* execute rest bits of E */ for (--nsE; nsE>0; nsE--) { eValue = dataE[nsE - 1]; for (n = 0; nsqr(dataY, dataY, pMont); if (eValue & ((BNU_CHUNK_T)1 << (BNU_CHUNK_BITS - 1))) MOD_METHOD(pMont)->mul(dataY, dataY, dataT, pMont); } } } } return nsM; } /* // "fast" binary montgomery exponentiation // // - input/output are in Regular Domain // - possible inplace mode // // scratch buffer structure: // dataT[nsM] copy of base (in case of inplace operation) */ IPP_OWN_DEFN (cpSize, gsModExpBin_BNU, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { cpSize nsM = MOD_LEN(pMont); /* copy and expand base to the modulus length */ ZEXPAND_COPY_BNU(dataY, nsM, dataX, nsX); /* convert base to Montgomery domain */ MOD_METHOD(pMont)->encode(dataY, dataY, pMont); /* exponentiation */ gsMontExpBin_BNU(dataY, dataY, nsM, dataE, bitsizeE, pMont, pBuffer); /* convert result back to regular domain */ MOD_METHOD(pMont)->decode(dataY, dataY, pMont); return nsM; } cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_bin_sscm.c000066400000000000000000000063231470420105600270500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Modular Exponentiation */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpmask_ct.h" IPP_OWN_DEFN (cpSize, gsMontExpBin_BNU_sscm, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { cpSize nsM = MOD_LEN(pMont); cpSize nsE = BITS_BNU_CHUNK(bitsizeE); /* // test for special cases: // x^0 = 1 // 0^e = 0 */ if (cpEqu_BNU_CHUNK(dataE, nsE, 0)) { COPY_BNU(dataY, MOD_MNT_R(pMont), nsM); } else if (cpEqu_BNU_CHUNK(dataX, nsX, 0)) { ZEXPAND_BNU(dataY, 0, nsM); } /* general case */ else { /* allocate buffers */ BNU_CHUNK_T* dataT = pBuffer; BNU_CHUNK_T* sscmB = dataT + nsM; /* mont(1) */ BNU_CHUNK_T* pR = MOD_MNT_R(pMont); /* copy and expand base to the modulus length */ ZEXPAND_COPY_BNU(dataT, nsM, dataX, nsX); /* init result */ COPY_BNU(dataY, MOD_MNT_R(pMont), nsM); /* execute bits of E */ for (; nsE>0; nsE--) { BNU_CHUNK_T eValue = dataE[nsE-1]; int n; for(n=BNU_CHUNK_BITS; n>0; n--) { /* sscmB = ( msb(eValue) )? X : mont(1) */ BNU_CHUNK_T mask = cpIsMsb_ct(eValue); eValue <<= 1; cpMaskedCopyBNU_ct(sscmB, mask, dataT, pR, nsM); /* squaring Y = Y^2 */ MOD_METHOD(pMont)->sqr(dataY, dataY, pMont); /* and multiplication: Y = Y * sscmB */ MOD_METHOD(pMont)->mul(dataY, dataY, sscmB, pMont); } } } return nsM; } /* // "safe" binary montgomery exponentiation // // - input/output are in Regular Domain // - possible inplace mode // // scratch buffer structure: // dataT[nsM] // sscm[nsM] */ IPP_OWN_DEFN (cpSize, gsModExpBin_BNU_sscm, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { cpSize nsM = MOD_LEN(pMont); /* copy and expand base to the modulus length */ ZEXPAND_COPY_BNU(dataY, nsM, dataX, nsX); /* convert base to Montgomery domain */ MOD_METHOD(pMont)->encode(dataY, dataY, pMont); /* exponentiation */ gsMontExpBin_BNU_sscm(dataY, dataY, nsM, dataE, bitsizeE, pMont, pBuffer); /* convert result back to regular domain */ MOD_METHOD(pMont)->decode(dataY, dataY, pMont); return nsM; } cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_sse2.c000066400000000000000000001010221470420105600261170ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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 "owncp.h" #if (_IPP>=_IPP_W7) #include "pcpbnuimpl.h" #include "pcpbnumisc.h" #include "pcpngmontexpstuff.h" #include "pcpngmontexpstuff_sse2.h" #include "gsscramble.h" #include "pcpmask_ct.h" //tbcd: temporary excluded: #include /* converts regular (base = 2^32) representation (norm, normLen) into "redundant" (base = 2^EXP_DIGIT_SIZE_SSE2) represenrartion (red, redLen) return 1 note: 1) repLen >= (bitsize +DIGIT_SIZE-1)/DIGIT_SIZE for complete conversion 2) regular representation should expanded by at least one zero value, pre-requisite: pRegular[regLen] == 0 to make conversion correct 3) caller must provide suitable lengths of regular and redundant representations so, conversion does correct */ static int regular_dig27(Ipp64u* pRep27, int repLen, const Ipp32u* pRegular, int regLen) { /* expected number of digit in redundant representation */ int n = cpDigitNum_sse2(regLen*BITSIZE(Ipp32u), EXP_DIGIT_SIZE_SSE2); //tbcd: temporary excluded: assert(pRegular[regLen]==0); /* test pre-requisite */ { int redBit; /* output representatin bit */ int i; for(i=0, redBit=0; i>= shift; pRep27[i] = x & EXP_DIGIT_MASK_SSE2; } /* expands by zeros if necessary */ for(; i= NORM_DIGSIZE_SSE2) { pRegular[idx++] = (Ipp32u)(x & NORM_MASK_SSE2); x >>= NORM_DIGSIZE_SSE2; shift -= NORM_DIGSIZE_SSE2; } } if(idx>= EXP_DIGIT_SIZE_SSE2; } return tmp; } /* Montgomery multiplication of the redundant operands */ static void cpMontMul_sse2(Ipp64u* pR, const Ipp64u* pA, const Ipp64u* pB, const Ipp64u* pModulus, int mLen, BNU_CHUNK_T k0, Ipp64u* pBuffer) { int extLen = mLen+1; /* len extension */ int i; __m128i v_k0 = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)k0), 0x44); __m128i v_digMask = _mm_srli_epi64(_mm_set1_epi32(-1), 64-EXP_DIGIT_SIZE_SSE2); __m128i lowQword = _mm_srli_si128(_mm_set1_epi32(-1), sizeof(Ipp64u)); __m128i v_b0, v_y0, v_ac; /* clear buffer */ v_ac = _mm_setzero_si128(); for(i=0; i1; pB+=2, mLen-=2) { __m128i v_b1, v_y1; /* v_b0 = {pB[i]:pB[i]}, v_b1 = {pB[i+1]:pB[i+1]} */ v_b1 = _mm_load_si128((__m128i*)pB); v_b0 = _mm_shuffle_epi32(v_b1, 0x44); /* v_ac = {pA[1]:pA[0]} */ v_ac = _mm_load_si128((__m128i*)pA); v_b1 = _mm_shuffle_epi32(v_b1, 0xEE); /* v_ac = {pA[1]:pA[0]} * {pB[i]:pB[i]} + {pR[1]:pR[0]} */ v_ac = _mm_add_epi64(_mm_mul_epu32(v_ac, v_b0), ((__m128i*)pBuffer)[0]); /* v_y0 = {v_ac[0]:v_ac[0]} * {k0:k0} ) & {digMask:digMask} */ v_y0 = _mm_mul_epu32(_mm_shuffle_epi32(v_ac, 0x44),v_k0); v_y0 = _mm_and_si128(v_y0, v_digMask); /* v_ac += v_y0 * {pM[1]:pM[0]}*/ v_ac = _mm_add_epi64(v_ac, _mm_mul_epu32(v_y0, ((__m128i*)pModulus)[0])); /* v_ac = {0: v_ac[1]+v_ac[0]>>EXP_DIGIT_SIZE_SSE2}*/ v_ac = _mm_add_epi64(_mm_srli_si128(v_ac, sizeof(Ipp64u)), _mm_srli_epi64(_mm_and_si128(v_ac, lowQword), EXP_DIGIT_SIZE_SSE2)); /* v_ac += {0: pA[0]} * v_b1 */ v_ac = _mm_add_epi64(v_ac, _mm_mul_epu32(v_b1, _mm_cvtsi64_si128((IPP_INT64)pA[0]))); /* v_y1 = (v_ac * v_k0) & v_digMask */ v_y1 = _mm_and_si128(_mm_mul_epu32(v_ac, v_k0), v_digMask); /* v_ac += pM[0] * v_y1 */ v_ac = _mm_add_epi64(v_ac, _mm_mul_epu32(_mm_cvtsi64_si128((IPP_INT64)pModulus[0]), v_y1)); v_y1 = _mm_shuffle_epi32(v_y1, 0x44); /* pR[2] += (v_ac>>EXP_DIGIT_SIZE_SSE2) */ v_ac = _mm_add_epi64(_mm_srli_epi64(v_ac, EXP_DIGIT_SIZE_SSE2), ((__m128i*)pBuffer)[1]); _mm_store_si128(((__m128i*)pBuffer)+1, v_ac); for(i=2; i1; pProduct+=2, mLen-=2) { __m128i v_y1; /* v_ac = {pProd[1]:pProd[0]} */ v_ac = _mm_load_si128((__m128i*)pProduct); /* v_y0 = {v_ac[0]:v_ac[0]} * {k0:k0} ) & {digMask:digMask} */ v_y0 = _mm_mul_epu32(_mm_shuffle_epi32(v_ac, 0x44),v_k0); v_y0 = _mm_and_si128(v_y0, v_digMask); /* v_ac += v_y0 * {pMod[1]:pMod[0]}*/ v_ac = _mm_add_epi64(v_ac, _mm_mul_epu32(v_y0, ((__m128i*)pModulus)[0])); /* v_ac = {0: v_ac[1]+v_ac[0]>>EXP_DIGIT_SIZE_SSE2}*/ v_ac = _mm_add_epi64(_mm_srli_si128(v_ac, sizeof(Ipp64u)), _mm_srli_epi64(_mm_and_si128(v_ac, lowQword), EXP_DIGIT_SIZE_SSE2)); /* v_y1 = (v_ac * v_k0) & v_digMask */ v_y1 = _mm_and_si128(_mm_mul_epu32(v_ac, v_k0), v_digMask); /* v_ac += pM[0] * v_y1 */ v_ac = _mm_add_epi64(v_ac, _mm_mul_epu32(_mm_cvtsi64_si128((IPP_INT64)pModulus[0]), v_y1)); v_y1 = _mm_shuffle_epi32(v_y1, 0x44); /* pProd[2] += (v_ac>>EXP_DIGIT_SIZE_SSE2) */ v_ac = _mm_add_epi64(_mm_srli_epi64(v_ac, EXP_DIGIT_SIZE_SSE2), ((__m128i*)pProduct)[1]); _mm_store_si128(((__m128i*)pProduct)+1, v_ac); for(i=2; i>EXP_DIGIT_SIZE_SSE2 */ v_ac = _mm_add_epi64(v_ac, _mm_srli_epi64(_mm_shuffle_epi32(v_ac, 0x44), EXP_DIGIT_SIZE_SSE2)); _mm_store_si128(((__m128i*)pProduct), v_ac); for(i=2; i1; i+=4,hcounter-=2, tmpa+=4,ps+=4) { __m128i t; __m128i a0 = _mm_shuffle_epi32(_mm_cvtsi64_si128 ((IPP_INT64)tmpa[0]), 0x44); /* {a0:a0} */ __m128i a2 = _mm_shuffle_epi32(_mm_cvtsi64_si128 ((IPP_INT64)tmpa[2]), 0x44); /* {a2:a2} */ __m128i s0 = _mm_load_si128((__m128i*)ps); __m128i s2 = _mm_load_si128((__m128i*)(ps+2)); __m128i d0 = _mm_load_si128((__m128i*)(pDbl+i+2)); __m128i d2 = _mm_load_si128((__m128i*)(pDbl+i+4)); /* px[2*i] += a0*s00; px[2*i+1] += a0*s01; */ _mm_storeu_si128((__m128i*)(px+2*i), _mm_add_epi64(_mm_mul_epu32(a0,s0), _mm_loadu_si128((__m128i*)(px+2*i)))); /* px[2*i+2] += a0*d00; px[2*i+3] += a0*d01; */ _mm_storeu_si128((__m128i*)(px+2*i+2), _mm_add_epi64(_mm_mul_epu32(a0,d0), _mm_loadu_si128((__m128i*)(px+2*i+2)))); /* px[2*i+4] += a0*d20 + a2*s20; px[2*i+5] += a0*d21 + a2*s21; */ t = _mm_add_epi64(_mm_mul_epu32(a0,d2), _mm_mul_epu32(a2,s2)); _mm_storeu_si128((__m128i*)(px+2*i+4), _mm_add_epi64(t, _mm_loadu_si128((__m128i*)(px+2*i+4)))); for(j=i+6; j0; nsE--) { eValue = dataE[nsE-1]; for(n=0; n0; nsE--) { BNU_CHUNK_T eValue = dataE[nsE-1]; int n; for(n=BNU_CHUNK_BITS; n>0; n--) { /* T = ( msb(eValue) )? X : mont(1) */ BNU_CHUNK_T mask = cpIsMsb_ct(eValue); eValue <<= 1; cpMaskedCopyBNU_ct((BNU_CHUNK_T*)redT, mask, (BNU_CHUNK_T*)redX, (BNU_CHUNK_T*)redR, redLen*sizeof(Ipp64u)/sizeof(BNU_CHUNK_T)); /* squaring: Y = Y^2 */ cpMontSqr_sse2(redY, redY, redM, redLen, k0, redBuffer); /* and multiply: Y = Y * T */ cpMontMul_sse2(redY, redY, redT, redM, redLen, k0, redBuffer); } } /* convert result back to regular domain */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; cpMontMul_sse2(redY, redY, redT, redM, redLen, k0, redBuffer); dig27_regular((Ipp32u*)dataY, nsM*sizeof(BNU_CHUNK_T)/sizeof(ipp32u), redY, redLen); return nsM; } #endif /* !_USE_WINDOW_EXP_ */ #if defined(_USE_WINDOW_EXP_) /* // "fast" fixed-size window montgomery exponentiation // // scratch buffer structure: // precomputed table of multipliers[(1<>shift) &wmask); /* initialize result */ COPY_BNU(redY, redTable+windowVal*redLen, redLen); for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0; n>shift) &wmask); /* precomputed value muptiplication */ if(windowVal) { COPY_BNU(redT, redTable+windowVal*redLen, redLen); cpMontMul_sse2(redY, redY, redT, redM, redLen, k0, redBuffer); } } } /* convert result back */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; cpMontMul_sse2(redY, redY, redT, redM, redLen, k0, redBuffer); dig27_regular((Ipp32u*)dataY, nsM*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(ipp32u)), redY, redLen); return nsM; } /* // "safe" fixed-size window montgomery exponentiation // // scratch buffer structure: // pre-computed table // redM[redBufferLen] // redY[redBufferLen] // redT[redBufferLen] // redBuffer[redBufferLen*3] // redE[redBufferLen] */ IPP_OWN_DEFN (cpSize, gsMontExpWin_BNU_sscm_sse2, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataE, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { const BNU_CHUNK_T* dataM = MOD_MODULUS(pMont); const BNU_CHUNK_T* dataRR= MOD_MNT_R2(pMont); cpSize nsM = MOD_LEN(pMont); BNU_CHUNK_T k0 = MOD_MNT_FACTOR(pMont); cpSize nsE = BITS_BNU_CHUNK(bitsizeE); int modulusBitSize = MOD_BITSIZE(pMont); int convModulusBitSize = cpDigitNum_sse2(modulusBitSize, BITSIZE(BNU_CHUNK_T)) * BITSIZE(BNU_CHUNK_T); int modulusLen32 = BITS2WORD32_SIZE(modulusBitSize); int redLen = cpDigitNum_sse2(convModulusBitSize+2, EXP_DIGIT_SIZE_SSE2); int redBufferLen = numofVariableBuff_sse2(redLen); cpSize window = gsMontExp_WinSize(bitsizeE); cpSize nPrecomute= 1<>shift) &wmask); /* initialize result */ gsScrambleGet_sscm((BNU_CHUNK_T*)redY, redLen*(Ipp32s)(sizeof(Ipp64u)/sizeof(BNU_CHUNK_T)), (BNU_CHUNK_T*)redTable, windowVal, window); for(eBit-=window; eBit>=0; eBit-=window) { /* do squaring window-times */ for(n=0; n>shift) &wmask); /* exptact precomputed value and multiply */ gsScrambleGet_sscm((BNU_CHUNK_T*)redT, redLen*(Ipp32s)(sizeof(Ipp64u)/sizeof(BNU_CHUNK_T)), (BNU_CHUNK_T*)redTable, windowVal, window); cpMontMul_sse2(redY, redY, redT, redM, redLen, k0, redBuffer); } } /* convert result back */ ZEXPAND_BNU(redT, 0, redBufferLen); redT[0] = 1; cpMontMul_sse2(redY, redY, redT, redM, redLen, k0, redBuffer); dig27_regular((Ipp32u*)dataY, nsM*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(ipp32u)), redY, redLen); return nsM; } #endif /* _USE_WINDOW_EXP_ */ #endif /* _IPP_W7 */ cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_sse2.h000066400000000000000000000063761470420105600261440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions of SSE Montgomery Exp // */ #include "owncp.h" #if (_IPP>=_IPP_W7) #include "pcpbnuimpl.h" #include "pcpngmontexpstuff.h" #define RSA_SSE2_MIN_BITSIZE (256) #define RSA_SSE2_MAX_BITSIZE (13*1024) #define NORM_DIGSIZE_SSE2 (BITSIZE(Ipp32u)) #define NORM_BASE_SSE2 ((Ipp64u)1<mul(pTable+n*nsM, pTable+(n-1)*nsM, dataTT, pMont); } /* expand exponent*/ ZEXPAND_COPY_BNU(dataEE, nsE+1, dataExp, nsE); bitsizeE = ((bitsizeE+winSize-1)/winSize) *winSize; /* exponentiation */ { /* position of the 1-st (left) window */ int eBit = bitsizeE-winSize; /* Note: Static analysis can generate error/warning on the expression below. The value of "bitSizeE" is limited, ((modulusBitSize > bitSizeE > 0), it is checked in initialization phase by (ippsRSA_GetSizePublickey() and ippsRSA_InitPublicKey). Buffer "dataEE" assigned for copy of dataExp, is 1 (64-bit) chunk longer than size of RSA modulus, therefore the access "*((Ipp32u*)((Ipp16u*)dataEE+ eBit/BITSIZE(Ipp16u)))" is always inside the boundary. */ /* extract 1-st window value */ Ipp32u eChunk = *((Ipp32u*)((Ipp16u*)dataEE + eBit/BITSIZE(Ipp16u))); int shift = eBit & 0xF; Ipp32u winVal = (eChunk>>shift) &mask; /* initialize result */ COPY_BNU(dataY, pTable+winVal*(Ipp32u)nsM, nsM); for(eBit-=winSize; eBit>=0; eBit-=winSize) { /* do square window times */ for(n=0,winVal=0; nsqr(dataY, dataY, pMont); } /* extract next window value */ eChunk = *((Ipp32u*)((Ipp16u*)dataEE + eBit/BITSIZE(Ipp16u))); shift = eBit & 0xF; winVal = (eChunk>>shift) &mask; /* multiply precomputed value */ MOD_METHOD( pMont )->mul(dataY, dataY, pTable+winVal*(Ipp32u)nsM, pMont); } } } return nsM; } /* // "fast" fixed-size window montgomery exponentiation // - input/output are in Regular Domain // - possible inplace mode */ IPP_OWN_DEFN (cpSize, gsModExpWin_BNU, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataExp, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { cpSize nsM = MOD_LEN(pMont); /* copy and expand base to the modulus length */ ZEXPAND_COPY_BNU(dataY, nsM, dataX, nsX); /* convert base to Montgomery domain */ MOD_METHOD(pMont)->encode(dataY, dataY, pMont); /* exponentiation */ gsMontExpWin_BNU(dataY, dataY, nsM, dataExp, bitsizeE, pMont, pBuffer); /* convert result back to regular domain */ MOD_METHOD(pMont)->decode(dataY, dataY, pMont); return nsM; } #endif /* _USE_WINDOW_EXP_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpngmontexpstuff_win_sscm.c000066400000000000000000000112311470420105600270670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Modular Exponentiation (windowed "safe" version) */ #include "owncp.h" #if defined(_USE_WINDOW_EXP_) #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpmask_ct.h" /* // "safe" fixed-size window montgomery exponentiation // // - input/output are in Montgomery Domain // - possible inplace mode // // scratch buffer structure: // precomputed table of multipliers[(1<mul(dataTT, dataTT, dataRR, pMont); gsScramblePut(pTable, n, dataTT, nsM, winSize); } /* expand exponent*/ ZEXPAND_COPY_BNU(dataEE, nsM+1, dataExp, nsE); bitsizeE = ((bitsizeE+winSize-1)/winSize) *winSize; /* exponentiation */ { /* position of the 1-st (left) window */ int eBit = bitsizeE-winSize; /* extract 1-st window value */ Ipp32u eChunk = *((Ipp32u*)((Ipp16u*)dataEE + eBit/BITSIZE(Ipp16u))); int shift = eBit & 0xF; Ipp32u winVal = (eChunk>>shift) &mask; /* initialize result */ gsScrambleGet_sscm(dataY, nsM, pTable, (int)winVal, winSize); for(eBit-=winSize; eBit>=0; eBit-=winSize) { /* do square window times */ for(n=0,winVal=0; nsqr(dataY, dataY, pMont); } /* extract next window value */ eChunk = *((Ipp32u*)((Ipp16u*)dataEE + eBit/BITSIZE(Ipp16u))); shift = eBit & 0xF; winVal = (eChunk>>shift) &mask; /* exptact precomputed value and multiply */ gsScrambleGet_sscm(dataTT, nsM, pTable, (int)winVal, winSize); MOD_METHOD( pMont )->mul(dataY, dataY, dataTT, pMont); } } } return nsM; } /* // "safe" fixed-size window exponentiation // - input/output are in Regular Domain // - possible inplace mode */ IPP_OWN_DEFN (cpSize, gsModExpWin_BNU_sscm, (BNU_CHUNK_T* dataY, const BNU_CHUNK_T* dataX, cpSize nsX, const BNU_CHUNK_T* dataExp, cpSize bitsizeE, gsModEngine* pMont, BNU_CHUNK_T* pBuffer)) { cpSize nsM = MOD_LEN(pMont); /* copy and expand base to the modulus length */ ZEXPAND_COPY_BNU(dataY, nsM, dataX, nsX); /* convert base to Montgomery domain */ MOD_METHOD(pMont)->encode(dataY, dataY, pMont); /* exponentiation */ gsMontExpWin_BNU_sscm(dataY, dataY, nsM, dataExp, bitsizeE, pMont, pBuffer); /* convert result back to regular domain */ MOD_METHOD(pMont)->decode(dataY, dataY, pMont); return nsM; } #endif /* _USE_WINDOW_EXP_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpngrsa.h000066400000000000000000000116141470420105600232220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal ng RSA Function Prototypes // // */ #if !defined(_CP_NG_RSA_H) #define _CP_NG_RSA_H #include "pcpbn.h" #include "pcpmontgomery.h" #include "pcpngmontexpstuff.h" struct _cpRSA_public_key { Ipp32u id; /* key ID */ int maxbitSizeN; int maxbitSizeE; int bitSizeN; /* RSA modulus bitsize */ int bitSizeE; /* RSA public exp bitsize */ BNU_CHUNK_T* pDataE; /* public exp */ gsModEngine* pMontN; /* montgomery engine (N) */ }; #define RSA_PUB_KEY_SET_ID(x) ((x)->id = (Ipp32u)idCtxRSA_PubKey ^ (Ipp32u)IPP_UINT_PTR(x)) /* access */ #define RSA_PUB_KEY_MAXSIZE_N(x) ((x)->maxbitSizeN) #define RSA_PUB_KEY_MAXSIZE_E(x) ((x)->maxbitSizeE) #define RSA_PUB_KEY_BITSIZE_N(x) ((x)->bitSizeN) #define RSA_PUB_KEY_BITSIZE_E(x) ((x)->bitSizeE) #define RSA_PUB_KEY_E(x) ((x)->pDataE) #define RSA_PUB_KEY_NMONT(x) ((x)->pMontN) #define RSA_PUB_KEY_VALID_ID(x) ((((x)->id) ^ (Ipp32u)IPP_UINT_PTR((x))) == (Ipp32u)idCtxRSA_PubKey) #define RSA_PUB_KEY_IS_SET(x) (RSA_PUB_KEY_BITSIZE_N((x))>0) /* alignment */ #define RSA_PUBLIC_KEY_ALIGNMENT ((int)(sizeof(void*))) struct _cpRSA_private_key { Ipp32u id; /* key ID */ int maxbitSizeN; int maxbitSizeD; int bitSizeN; /* RSA modulus bitsize */ int bitSizeD; /* RSA private exp bitsize */ int bitSizeP; /* RSA p-factor bitsize */ int bitSizeQ; /* RSA q-factor bitsize */ BNU_CHUNK_T* pDataD; /* private exp */ BNU_CHUNK_T* pDataDp; /* dp private exp */ BNU_CHUNK_T* pDataDq; /* dq private exp */ BNU_CHUNK_T* pDataQinv; /* qinv coeff in residue domain */ gsModEngine* pMontP; /* montgomery engine (P) */ gsModEngine* pMontQ; /* montgomery engine (Q) */ gsModEngine* pMontN; /* montgomery engine (N) */ }; #define RSA_PRV_KEY1_SET_ID(x) ((x)->id = (Ipp32u)idCtxRSA_PrvKey1 ^ (Ipp32u)IPP_UINT_PTR(x)) #define RSA_PRV_KEY2_SET_ID(x) ((x)->id = (Ipp32u)idCtxRSA_PrvKey2 ^ (Ipp32u)IPP_UINT_PTR(x)) /* access */ #define RSA_PRV_KEY_MAXSIZE_N(x) ((x)->maxbitSizeN) #define RSA_PRV_KEY_MAXSIZE_D(x) ((x)->maxbitSizeD) #define RSA_PRV_KEY_BITSIZE_N(x) ((x)->bitSizeN) #define RSA_PRV_KEY_BITSIZE_D(x) ((x)->bitSizeD) #define RSA_PRV_KEY_BITSIZE_P(x) ((x)->bitSizeP) #define RSA_PRV_KEY_BITSIZE_Q(x) ((x)->bitSizeQ) #define RSA_PRV_KEY_D(x) ((x)->pDataD) #define RSA_PRV_KEY_DP(x) ((x)->pDataDp) #define RSA_PRV_KEY_DQ(x) ((x)->pDataDq) #define RSA_PRV_KEY_INVQ(x) ((x)->pDataQinv) #define RSA_PRV_KEY_PMONT(x) ((x)->pMontP) #define RSA_PRV_KEY_QMONT(x) ((x)->pMontQ) #define RSA_PRV_KEY_NMONT(x) ((x)->pMontN) #define RSA_PRV_KEY1_VALID_ID(x) ((((x)->id) ^ (Ipp32u)IPP_UINT_PTR((x))) == (Ipp32u)idCtxRSA_PrvKey1) #define RSA_PRV_KEY2_VALID_ID(x) ((((x)->id) ^ (Ipp32u)IPP_UINT_PTR((x))) == (Ipp32u)idCtxRSA_PrvKey2) #define RSA_PRV_KEY_VALID_ID(x) (RSA_PRV_KEY1_VALID_ID((x)) || RSA_PRV_KEY2_VALID_ID((x))) #define RSA_PRV_KEY_IS_SET(x) (RSA_PRV_KEY_BITSIZE_N((x))>0) /* alignment */ #define RSA_PRIVATE_KEY_ALIGNMENT ((int)(sizeof(void*))) #define MOD_ENGINE_RSA_POOL_SIZE (2) /* // Montgomery engine preparation (GetSize/init/Set) */ #define rsaMontExpGetSize OWNAPI(rsaMontExpGetSize) IPP_OWN_DECL (void, rsaMontExpGetSize, (int length, int* pSize)) /* // pubic and private key operations */ #define gsRSApub_cipher OWNAPI(gsRSApub_cipher) IPP_OWN_DECL (void, gsRSApub_cipher, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPublicKeyState* pKey, BNU_CHUNK_T* pScratchBuffer)) #define gsRSAprv_cipher OWNAPI(gsRSAprv_cipher) IPP_OWN_DECL (void, gsRSAprv_cipher, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pScratchBuffer)) #define gsRSAprv_cipher_crt OWNAPI(gsRSAprv_cipher_crt) IPP_OWN_DECL (void, gsRSAprv_cipher_crt, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pScratchBuffer)) #endif /* _CP_NG_RSA_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpngrsamethod.h000066400000000000000000000055251470420105600244270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal ng RSA methods */ #if !defined(_CP_NG_RSA_METHOD_H) #define _CP_NG_RSA_METHOD_H #include "pcpngmontexpstuff.h" /* // declaration of RSA exponentiation */ IPP_OWN_FUNPTR (cpSize, ngBufNum, (int modulusBits)) typedef struct _gsMethod_RSA { int loModulusBisize; // application area (lowew int hiModulusBisize; // and upper) ngBufNum bufferNumFunc; // pub operation buffer in BNU_CHUNK_T ngMontExp expFun; // exponentiation ngMontDualExp dualExpFun; // dual exponentiation } gsMethod_RSA; /* GPR exponentiation */ #define gsMethod_RSA_gpr_public OWNAPI(gsMethod_RSA_gpr_public) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_gpr_public, (void)) #define gsMethod_RSA_gpr_private OWNAPI(gsMethod_RSA_gpr_private) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_gpr_private, (void)) /* SSE2 exponentiation */ #if (_IPP>=_IPP_W7) #define gsMethod_RSA_sse2_public OWNAPI(gsMethod_RSA_sse2_public) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_sse2_public, (void)) #define gsMethod_RSA_sse2_private OWNAPI(gsMethod_RSA_sse2_private) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_sse2_private, (void)) #endif /* _IPP_W7 */ /* AVX2 exponentiation */ #if (_IPP32E>=_IPP32E_L9) #define gsMethod_RSA_avx2_public OWNAPI(gsMethod_RSA_avx2_public) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_avx2_public, (void)) #define gsMethod_RSA_avx2_private OWNAPI(gsMethod_RSA_avx2_private) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_avx2_private, (void)) #endif /* _IPP32E_L9 */ /* AVX512 exponentiation */ #if (_IPP32E>=_IPP32E_K1) #define gsMethod_RSA_avx512_public OWNAPI(gsMethod_RSA_avx512_public) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_avx512_public, (void)) #define gsMethod_RSA_avx512_private OWNAPI(gsMethod_RSA_avx512_private) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_avx512_private, (void)) #define gsMethod_RSA_avx512_crt_private OWNAPI(gsMethod_RSA_avx512_crt_private) IPP_OWN_DECL (gsMethod_RSA*, gsMethod_RSA_avx512_crt_private, (int privExpBitSize)) #endif /* _IPP32E_K1 */ #endif /* _CP_NG_RSA_METHOD_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpprime_isco.h000066400000000000000000000035721470420105600242450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcpngrsa.h" /* test if E and A are coprime */ static int cpIsCoPrime(BNU_CHUNK_T* pA, int nsA, BNU_CHUNK_T* pB, int nsB, BNU_CHUNK_T* pBuffer) { if (nsA>nsB) { SWAP_PTR(BNU_CHUNK_T, pA, pB); SWAP(nsA, nsB); } { __ALIGN8 IppsBigNumState bnA, bnB, bnGcd; BNU_CHUNK_T* pDataA = pBuffer; BNU_CHUNK_T* pBuffA = pDataA + nsA + 1; BNU_CHUNK_T* pDataB = pBuffA + nsA + 1; BNU_CHUNK_T* pBuffB = pDataB + nsB + 1; BNU_CHUNK_T* pDataGcd = pBuffB + nsB + 1; BNU_CHUNK_T* pBuffGcd = pDataGcd + nsB + 1; BN_Make(pDataA, pBuffA, nsA, &bnA); BN_Make(pDataB, pBuffB, nsB, &bnB); BN_Make(pDataGcd, pBuffGcd, nsB, &bnGcd); COPY_BNU(pDataA, pA, nsA) BN_Set(pDataA, nsA, &bnA); COPY_BNU(pDataB, pB, nsB) BN_Set(pDataB, nsB, &bnB); ippsGcd_BN(&bnA, &bnB, &bnGcd); return 0 == cpBN_cmp(&bnGcd, cpBN_OneRef()); } }cryptography-primitives-1.0.0/sources/ippcp/pcpprime_isprob.h000066400000000000000000000104101470420105600245730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcpngrsa.h" static int cpMillerRabinTest(BNU_CHUNK_T* pW, cpSize nsW, const BNU_CHUNK_T* pE, cpSize bitsizeE, int k, const BNU_CHUNK_T* pPrime1, gsModEngine* pMont, BNU_CHUNK_T* pBuffer) { cpSize nsP = MOD_LEN(pMont); /* to Montgomery Domain */ ZEXPAND_BNU(pW, nsW, nsP); MOD_METHOD(pMont)->encode(pW, pW, pMont); /* w = exp(w,e) */ #if !defined(_USE_WINDOW_EXP_) gsMontExpBin_BNU_sscm(pW, pW, nsP, pE, bitsizeE, pMont, pBuffer); #else gsMontExpWin_BNU_sscm(pW, pW, nsP, pE, bitsizeE, pMont, pBuffer); #endif /* if (w==1) ||(w==prime-1) => probably prime */ if ((0 == cpCmp_BNU(pW, nsP, MOD_MNT_R(pMont), nsP)) || (0 == cpCmp_BNU(pW, nsP, pPrime1, nsP))) return 1; /* witness of the primality */ while (--k) { MOD_METHOD(pMont)->sqr(pW, pW, pMont); if (0 == cpCmp_BNU(pW, nsP, MOD_MNT_R(pMont), nsP)) return 0; /* witness of the compositeness */ if (0 == cpCmp_BNU(pW, nsP, pPrime1, nsP)) return 1; /* witness of the primality */ } return 0; } /* test if P is prime returns: IPP_IS_PRIME (==1) - prime value has been detected IPP_IS_COMPOSITE (==0) - composite value has been detected -1 - if internal error (ippStsNoErr != rndFunc()) */ static int cpIsProbablyPrime(BNU_CHUNK_T* pPrime, int bitSize, int nTrials, IppBitSupplier rndFunc, void* pRndParam, gsModEngine* pME, BNU_CHUNK_T* pBuffer) { /* if test for trivial divisors passed*/ int ret = cpMimimalPrimeTest((Ipp32u*)pPrime, BITS2WORD32_SIZE(bitSize)); /* apply Miller-Rabin test */ if (ret) { int ns = BITS_BNU_CHUNK(bitSize); BNU_CHUNK_T* pPrime1 = pBuffer; BNU_CHUNK_T* pOdd = pPrime1 + ns; BNU_CHUNK_T* pWitness = pOdd + ns; BNU_CHUNK_T* pMontPrime1 = pWitness + ns; BNU_CHUNK_T* pScratchBuffer = pMontPrime1 + ns; int k, a, lenOdd; /* prime1 = prime-1 = odd*2^a */ cpDec_BNU(pPrime1, pPrime, ns, 1); for (k = 0, a = 0; k0; n--) { Ipp64u tmp = IPP_MAKEDWORD(pX[n-1],r); r = (Ipp32u)(tmp%divider); } return r; } /* minimal prime test */ static Ipp32u PrimeList[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009,1013,1019,1021,1031,1033,1039,1049, 1051,1061,1063,1069,1087,1091,1093,1097, 1103,1109,1117,1123,1129,1151,1153,1163, 1171,1181,1187,1193,1201,1213,1217,1223, 1229,1231,1237,1249,1259,1277,1279,1283, 1289,1291,1297,1301,1303,1307,1319,1321, 1327,1361,1367,1373,1381,1399,1409,1423, 1427,1429,1433,1439,1447,1451,1453,1459, 1471,1481,1483,1487,1489,1493,1499,1511, 1523,1531,1543,1549,1553,1559,1567,1571, 1579,1583,1597,1601,1607,1609,1613,1619, 1621,1627,1637,1657,1663,1667,1669,1693, 1697,1699,1709,1721,1723,1733,1741,1747, 1753,1759,1777,1783,1787,1789,1801,1811, 1823,1831,1847,1861,1867,1871,1873,1877, 1879,1889,1901,1907,1913,1931,1933,1949, 1951,1973,1979,1987,1993,1997,1999,2003, 2011,2017,2027,2029,2039,2053,2063,2069, 2081,2083,2087,2089,2099,2111,2113,2129, 2131,2137,2141,2143,2153,2161,2179,2203, 2207,2213,2221,2237,2239,2243,2251,2267, 2269,2273,2281,2287,2293,2297,2309,2311, 2333,2339,2341,2347,2351,2357,2371,2377, 2381,2383,2389,2393,2399,2411,2417,2423, 2437,2441,2447,2459,2467,2473,2477,2503, 2521,2531,2539,2543,2549,2551,2557,2579, 2591,2593,2609,2617,2621,2633,2647,2657, 2659,2663,2671,2677,2683,2687,2689,2693, 2699,2707,2711,2713,2719,2729,2731,2741, 2749,2753,2767,2777,2789,2791,2797,2801, 2803,2819,2833,2837,2843,2851,2857,2861, 2879,2887,2897,2903,2909,2917,2927,2939, 2953,2957,2963,2969,2971,2999,3001,3011, 3019,3023,3037,3041,3049,3061,3067,3079, 3083,3089,3109,3119,3121,3137,3163,3167, 3169,3181,3187,3191,3203,3209,3217,3221, 3229,3251,3253,3257,3259,3271,3299,3301, 3307,3313,3319,3323,3329,3331,3343,3347, 3359,3361,3371,3373,3389,3391,3407,3413, 3433,3449,3457,3461,3463,3467,3469,3491, 3499,3511,3517,3527,3529,3533,3539,3541, 3547,3557,3559,3571,3581,3583,3593,3607, 3613,3617,3623,3631,3637,3643,3659,3671, 3673,3677,3691,3697,3701,3709,3719,3727, 3733,3739,3761,3767,3769,3779,3793,3797, 3803,3821,3823,3833,3847,3851,3853,3863, 3877,3881,3889,3907,3911,3917,3919,3923, 3929,3931,3943,3947,3967,3989,4001,4003, 4007,4013,4019,4021,4027,4049,4051,4057, 4073,4079,4091,4093,4099,4111,4127,4129, 4133,4139,4153,4157,4159,4177,4201,4211, 4217,4219,4229,4231,4241,4243,4253,4259, 4261,4271,4273,4283,4289,4297,4327,4337, 4339,4349,4357,4363,4373,4391,4397,4409, 4421,4423,4441,4447,4451,4457,4463,4481, 4483,4493,4507,4513,4517,4519,4523,4547, 4549,4561,4567,4583,4591,4597,4603,4621, 4637,4639,4643,4649,4651,4657,4663,4673, 4679,4691,4703,4721,4723,4729,4733,4751, 4759,4783,4787,4789,4793,4799,4801,4813, 4817,4831,4861,4871,4877,4889,4903,4909, 4919,4931,4933,4937,4943,4951,4957,4967, 4969,4973,4987,4993,4999,5003,5009,5011, 5021,5023,5039,5051,5059,5077,5081,5087, 5099,5101,5107,5113,5119,5147,5153,5167, 5171,5179,5189,5197,5209,5227,5231,5233, 5237,5261,5273,5279,5281,5297,5303,5309, 5323,5333,5347,5351,5381,5387,5393,5399, 5407,5413,5417,5419,5431,5437,5441,5443, 5449,5471,5477,5479,5483,5501,5503,5507, 5519,5521,5527,5531,5557,5563,5569,5573, 5581,5591,5623,5639,5641,5647,5651,5653, 5657,5659,5669,5683,5689,5693,5701,5711, 5717,5737,5741,5743,5749,5779,5783,5791, 5801,5807,5813,5821,5827,5839,5843,5849, 5851,5857,5861,5867,5869,5879,5881,5897, 5903,5923,5927,5939,5953,5981,5987,6007, 6011,6029,6037,6043,6047,6053,6067,6073, 6079,6089,6091,6101,6113,6121,6131,6133, 6143,6151,6163,6173,6197,6199,6203,6211, 6217,6221,6229,6247,6257,6263,6269,6271, 6277,6287,6299,6301,6311,6317,6323,6329, 6337,6343,6353,6359,6361,6367,6373,6379, 6389,6397,6421,6427,6449,6451,6469,6473, 6481,6491,6521,6529,6547,6551,6553,6563, 6569,6571,6577,6581,6599,6607,6619,6637, 6653,6659,6661,6673,6679,6689,6691,6701, 6703,6709,6719,6733,6737,6761,6763,6779, 6781,6791,6793,6803,6823,6827,6829,6833, 6841,6857,6863,6869,6871,6883,6899,6907, 6911,6917,6947,6949,6959,6961,6967,6971, 6977,6983,6991,6997,7001,7013,7019,7027, 7039,7043,7057,7069,7079,7103,7109,7121, 7127,7129,7151,7159,7177,7187,7193,7207, 7211,7213,7219,7229,7237,7243,7247,7253, 7283,7297,7307,7309,7321,7331,7333,7349, 7351,7369,7393,7411,7417,7433,7451,7457, 7459,7477,7481,7487,7489,7499,7507,7517, 7523,7529,7537,7541,7547,7549,7559,7561, 7573,7577,7583,7589,7591,7603,7607,7621, 7639,7643,7649,7669,7673,7681,7687,7691, 7699,7703,7717,7723,7727,7741,7753,7757, 7759,7789,7793,7817,7823,7829,7841,7853, 7867,7873,7877,7879,7883,7901,7907,7919, 7927,7933,7937,7949,7951,7963,7993,8009, 8011,8017,8039,8053,8059,8069,8081,8087, 8089,8093,8101,8111,8117,8123,8147,8161, 8167,8171,8179,8191,8209,8219,8221,8231, 8233,8237,8243,8263,8269,8273,8287,8291, 8293,8297,8311,8317,8329,8353,8363,8369, 8377,8387,8389,8419,8423,8429,8431,8443, 8447,8461,8467,8501,8513,8521,8527,8537, 8539,8543,8563,8573,8581,8597,8599,8609, 8623,8627,8629,8641,8647,8663,8669,8677, 8681,8689,8693,8699,8707,8713,8719,8731, 8737,8741,8747,8753,8761,8779,8783,8803, 8807,8819,8821,8831,8837,8839,8849,8861, 8863,8867,8887,8893,8923,8929,8933,8941, 8951,8963,8969,8971,8999,9001,9007,9011, 9013,9029,9041,9043,9049,9059,9067,9091, 9103,9109,9127,9133,9137,9151,9157,9161, 9173,9181,9187,9199,9203,9209,9221,9227, 9239,9241,9257,9277,9281,9283,9293,9311, 9319,9323,9337,9341,9343,9349,9371,9377, 9391,9397,9403,9413,9419,9421,9431,9433, 9437,9439,9461,9463,9467,9473,9479,9491, 9497,9511,9521,9533,9539,9547,9551,9587, 9601,9613,9619,9623,9629,9631,9643,9649, 9661,9677,9679,9689,9697,9719,9721,9733, 9739,9743,9749,9767,9769,9781,9787,9791, 9803,9811,9817,9829,9833,9839,9851,9857, 9859,9871,9883,9887,9901,9907,9923,9929, 9931,9941,9949,9967,9973,10007,10009,10037, 10039,10061,10067,10069,10079,10091,10093,10099, 10103,10111,10133,10139,10141,10151,10159,10163, 10169,10177,10181,10193,10211,10223,10243,10247, 10253,10259,10267,10271,10273,10289,10301,10303, 10313,10321,10331,10333,10337,10343,10357,10369, 10391,10399,10427,10429,10433,10453,10457,10459, 10463,10477,10487,10499,10501,10513,10529,10531, 10559,10567,10589,10597,10601,10607,10613,10627, 10631,10639,10651,10657,10663,10667,10687,10691, 10709,10711,10723,10729,10733,10739,10753,10771, 10781,10789,10799,10831,10837,10847,10853,10859, 10861,10867,10883,10889,10891,10903,10909,10937, 10939,10949,10957,10973,10979,10987,10993,11003, 11027,11047,11057,11059,11069,11071,11083,11087, 11093,11113,11117,11119,11131,11149,11159,11161, 11171,11173,11177,11197,11213,11239,11243,11251, 11257,11261,11273,11279,11287,11299,11311,11317, 11321,11329,11351,11353,11369,11383,11393,11399, 11411,11423,11437,11443,11447,11467,11471,11483, 11489,11491,11497,11503,11519,11527,11549,11551, 11579,11587,11593,11597,11617,11621,11633,11657, 11677,11681,11689,11699,11701,11717,11719,11731, 11743,11777,11779,11783,11789,11801,11807,11813, 11821,11827,11831,11833,11839,11863,11867,11887, 11897,11903,11909,11923,11927,11933,11939,11941, 11953,11959,11969,11971,11981,11987,12007,12011, 12037,12041,12043,12049,12071,12073,12097,12101, 12107,12109,12113,12119,12143,12149,12157,12161, 12163,12197,12203,12211,12227,12239,12241,12251, 12253,12263,12269,12277,12281,12289,12301,12323, 12329,12343,12347,12373,12377,12379,12391,12401, 12409,12413,12421,12433,12437,12451,12457,12473, 12479,12487,12491,12497,12503,12511,12517,12527, 12539,12541,12547,12553,12569,12577,12583,12589, 12601,12611,12613,12619,12637,12641,12647,12653, 12659,12671,12689,12697,12703,12713,12721,12739, 12743,12757,12763,12781,12791,12799,12809,12821, 12823,12829,12841,12853,12889,12893,12899,12907, 12911,12917,12919,12923,12941,12953,12959,12967, 12973,12979,12983,13001,13003,13007,13009,13033, 13037,13043,13049,13063,13093,13099,13103,13109, 13121,13127,13147,13151,13159,13163,13171,13177, 13183,13187,13217,13219,13229,13241,13249,13259, 13267,13291,13297,13309,13313,13327,13331,13337, 13339,13367,13381,13397,13399,13411,13417,13421, 13441,13451,13457,13463,13469,13477,13487,13499, 13513,13523,13537,13553,13567,13577,13591,13597, 13613,13619,13627,13633,13649,13669,13679,13681, 13687,13691,13693,13697,13709,13711,13721,13723, 13729,13751,13757,13759,13763,13781,13789,13799, 13807,13829,13831,13841,13859,13873,13877,13879, 13883,13901,13903,13907,13913,13921,13931,13933, 13963,13967,13997,13999,14009,14011,14029,14033, 14051,14057,14071,14081,14083,14087,14107,14143, 14149,14153,14159,14173,14177,14197,14207,14221, 14243,14249,14251,14281,14293,14303,14321,14323, 14327,14341,14347,14369,14387,14389,14401,14407, 14411,14419,14423,14431,14437,14447,14449,14461, 14479,14489,14503,14519,14533,14537,14543,14549, 14551,14557,14561,14563,14591,14593,14621,14627, 14629,14633,14639,14653,14657,14669,14683,14699, 14713,14717,14723,14731,14737,14741,14747,14753, 14759,14767,14771,14779,14783,14797,14813,14821, 14827,14831,14843,14851,14867,14869,14879,14887, 14891,14897,14923,14929,14939,14947,14951,14957, 14969,14983,15013,15017,15031,15053,15061,15073, 15077,15083,15091,15101,15107,15121,15131,15137, 15139,15149,15161,15173,15187,15193,15199,15217, 15227,15233,15241,15259,15263,15269,15271,15277, 15287,15289,15299,15307,15313,15319,15329,15331, 15349,15359,15361,15373,15377,15383,15391,15401, 15413,15427,15439,15443,15451,15461,15467,15473, 15493,15497,15511,15527,15541,15551,15559,15569, 15581,15583,15601,15607,15619,15629,15641,15643, 15647,15649,15661,15667,15671,15679,15683,15727, 15731,15733,15737,15739,15749,15761,15767,15773, 15787,15791,15797,15803,15809,15817,15823,15859, 15877,15881,15887,15889,15901,15907,15913,15919, 15923,15937,15959,15971,15973,15991,16001,16007, 16033,16057,16061,16063,16067,16069,16073,16087, 16091,16097,16103,16111,16127,16139,16141,16183, 16187,16189,16193,16217,16223,16229,16231,16249, 16253,16267,16273,16301,16319,16333,16339,16349, 16361,16363,16369,16381,16411,16417,16421,16427, 16433,16447,16451,16453,16477,16481,16487,16493, 16519,16529,16547,16553,16561,16567,16573,16603, 16607,16619,16631,16633,16649,16651,16657,16661, 16673,16691,16693,16699,16703,16729,16741,16747, 16759,16763,16787,16811,16823,16829,16831,16843, 16871,16879,16883,16889,16901,16903,16921,16927, 16931,16937,16943,16963,16979,16981,16987,16993, 17011,17021,17027,17029,17033,17041,17047,17053, 17077,17093,17099,17107,17117,17123,17137,17159, 17167,17183,17189,17191,17203,17207,17209,17231, 17239,17257,17291,17293,17299,17317,17321,17327, 17333,17341,17351,17359,17377,17383,17387,17389, 17393,17401,17417,17419,17431,17443,17449,17467, 17471,17477,17483,17489,17491,17497,17509,17519, 17539,17551,17569,17573,17579,17581,17597,17599, 17609,17623,17627,17657,17659,17669,17681,17683, 17707,17713,17729,17737,17747,17749,17761,17783, 17789,17791,17807,17827,17837,17839,17851,17863 }; /*F* // Name: cpMimimalPrimeTest // // Purpose: Test a number for being a mimnimal probable prime from list. // // Returns: Reason: // 0 not prime number // 1 prime number // // Parameters: // pPrime prime number // len32 length of prime number *F*/ IPP_OWN_DEFN (int, cpMimimalPrimeTest, (const Ipp32u* pPrime, cpSize len32)) { cpSize i; FIX_BNU32(pPrime, len32); /* take a look in the list */ if(1==len32) { for(i=0; i<(cpSize)(sizeof(PrimeList)/sizeof(Ipp32u)); i++) { if(pPrime[0]==PrimeList[i]) return 1; } } /* test if value under the test is divisible by first prime numbers 2,3,5, ... */ for(i=0; i<(cpSize)(sizeof(PrimeList)/sizeof(Ipp32u)); i++) { if(0 == cpMod32(pPrime, len32, PrimeList[i])) return 0; } return 1; } cryptography-primitives-1.0.0/sources/ippcp/pcpprime_packctx.c000066400000000000000000000033661470420105600247410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // cpPackPrimeCtx() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcptool.h" /*F* // Name: cpPackPrimeCtx // // Purpose: Serialize prime context // // Parameters: // pCtx context // pBuffer buffer *F*/ IPP_OWN_DEFN (void, cpPackPrimeCtx, (const IppsPrimeState* pCtx, Ipp8u* pBuffer)) { IppsPrimeState* pB = (IppsPrimeState*)(pBuffer); /* max length of prime */ cpSize nsPrime = BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx)); CopyBlock(pCtx, pB, sizeof(IppsPrimeState)); cpSize dataAlignment = (cpSize)(IPP_INT_PTR(PRIME_NUMBER(pCtx)) - IPP_INT_PTR(pCtx) - (IPP_INT64)sizeof(IppsPrimeState)); cpSize gsMontOffset = (cpSize)(IPP_INT_PTR(PRIME_MONT(pCtx)) - IPP_INT_PTR(pCtx) - dataAlignment); CopyBlock(PRIME_NUMBER(pCtx), (Ipp8u*)pB + sizeof(IppsPrimeState), nsPrime*(Ipp32s)sizeof(BNU_CHUNK_T)); gsPackModEngineCtx(PRIME_MONT(pCtx), (Ipp8u*)pB + gsMontOffset); } cryptography-primitives-1.0.0/sources/ippcp/pcpprime_test.c000066400000000000000000000127411470420105600242600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // cpPrimeTest() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcptool.h" /* Rabin-Miller test */ /* -1 is returned when pBuffer cannot be allocated */ static int RabinMiller(int a, BNU_CHUNK_T* pZ, BNU_CHUNK_T* pR, cpSize nsR, BNU_CHUNK_T* pM, cpSize nsM, gsModEngine* pModEngine) { /* modulus and it length and other parameters */ const BNU_CHUNK_T* pModulus = MOD_MODULUS(pModEngine); cpSize modLen = MOD_LEN(pModEngine); const int usedPoolLen = 1; BNU_CHUNK_T* pBuffer = 0; /* compute z = r^m mod prime */ nsR = cpMontEnc_BNU_EX(pR, pR, nsR, pModEngine); cpMontExpBin_BNU(pZ, pR, nsR, pM, nsM, pModEngine); /* if z==1 => probably prime */ if(0==cpCmp_BNU(pZ, modLen, MOD_MNT_R(pModEngine), modLen)) return 1; pBuffer = gsModPoolAlloc(pModEngine, usedPoolLen); if(NULL == pBuffer) return -1; /* if z==prime-1 => probably prime */ cpSub_BNU(pBuffer, pModulus, MOD_MNT_R(pModEngine), modLen); if(0==cpCmp_BNU(pZ, modLen, pBuffer, modLen)) { gsModPoolFree(pModEngine, usedPoolLen); return 1; } while(--a) { /* z = z^2 mod w */ cpMontSqr_BNU(pZ, pZ, pModEngine); /* if z==1 => definitely composite */ if(0==cpCmp_BNU(pZ, modLen, MOD_MNT_R(pModEngine), modLen)) { gsModPoolFree(pModEngine, usedPoolLen); return 0; } /* if z==w-1 => probably prime */ cpSub_BNU(pBuffer, pModulus, MOD_MNT_R(pModEngine), modLen); if(0==cpCmp_BNU(pZ, modLen, pBuffer, modLen)) { gsModPoolFree(pModEngine, usedPoolLen); return 1; } } gsModPoolFree(pModEngine, usedPoolLen); /* if we are here, then we deal with composize */ return 0; } /* returns: IPP_IS_PRIME (==1) - prime value has been detected IPP_IS_COMPOSITE (==0) - composite value has been detected -1 - if internal error (ippStsNoErr != rndFunc()) */ /*F* // Name: cpPrimeTest // // Purpose: Test a number for being a probable prime. // // Returns: Reason: // 0 not prime number // 1 prime number // // Parameters: // pPrime prime number // primeLen length of prime number // nTrials parameter for the Miller-Rabin probable primality test // pCtx pointer to the context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters *F*/ IPP_OWN_DEFN (int, cpPrimeTest, (const BNU_CHUNK_T* pPrime, cpSize primeLen, cpSize nTrials, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) { FIX_BNU(pPrime, primeLen); if( primeLen==1 && pPrime[0]==0) return 0; /* 2 is prime number */ else if( primeLen==1 && pPrime[0]==2) return 1; /* // test number */ else { cpSize primeBitsize = BITSIZE_BNU(pPrime, primeLen); cpSize primeLen32 = BITS2WORD32_SIZE(primeBitsize); /* apply easy prime test */ if( 0==cpMimimalPrimeTest((Ipp32u*)pPrime, primeLen32) ) return 0; /* continue test */ else { cpSize n, a; gsModEngine* pModEngine = PRIME_MONT(pCtx); BNU_CHUNK_T* pMdata = PRIME_TEMP1(pCtx); BNU_CHUNK_T* pRdata = PRIME_TEMP2(pCtx); BNU_CHUNK_T* pZdata = PRIME_TEMP3(pCtx); cpSize lenM, lenR; /* set up Montgomery engine (and save value being under the test) */ gsModEngineInit(pModEngine, (Ipp32u*)pPrime, BITSIZE_BNU(pPrime, primeLen), MONT_DEFAULT_POOL_LENGTH, gsModArithMont()); /* express w = m*2^a + 1 */ cpDec_BNU(pMdata, pPrime, primeLen, 1); for(n=0,a=0; n=1 */ if(!cpTst_BNU(pRdata, lenR)) pRdata[0] |= 1; FIX_BNU(pRdata, lenR); /* Rabin-Miller test */ int result = RabinMiller(a, pZdata, pRdata,primeLen, pMdata,lenM, pModEngine); if(-1 == result) //internal error return -1; if(0 == result) return 0; } return 1; } } } cryptography-primitives-1.0.0/sources/ippcp/pcpprime_unpackctx.c000066400000000000000000000042041470420105600252740ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // cpUnpackPrimeCtx() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcptool.h" /*F* // Name: cpUnpackPrimeCtx // // Purpose: Deserialize prime context // // Parameters: // pCtx context // pBuffer buffer *F*/ IPP_OWN_DEFN (void, cpUnpackPrimeCtx, (const Ipp8u* pBuffer, IppsPrimeState* pCtx)) { IppsPrimeState* pB = (IppsPrimeState*)(pBuffer); /* max length of prime */ cpSize nsPrime = BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pB)); CopyBlock(pB, pCtx, sizeof(IppsPrimeState)); Ipp8u* ptr = (Ipp8u*)pCtx; ptr += sizeof(IppsPrimeState); ptr = IPP_ALIGNED_PTR(ptr, PRIME_ALIGNMENT); PRIME_NUMBER(pCtx)= (BNU_CHUNK_T*)(ptr); ptr += nsPrime*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_TEMP1(pCtx) = (BNU_CHUNK_T*)(ptr); ptr += nsPrime*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_TEMP2(pCtx) = (BNU_CHUNK_T*)(ptr); ptr += nsPrime*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_TEMP3(pCtx) = (BNU_CHUNK_T*)(ptr); ptr += nsPrime*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_MONT(pCtx) = (gsModEngine*)(ptr); cpSize gsMontOffset = (cpSize)(IPP_INT_PTR(PRIME_MONT(pCtx)) - IPP_INT_PTR(pCtx)); CopyBlock((Ipp8u*)pB + sizeof(IppsPrimeState), PRIME_NUMBER(pCtx), nsPrime*(Ipp32s)sizeof(BNU_CHUNK_T)); gsUnpackModEngineCtx((Ipp8u*)pB + gsMontOffset, PRIME_MONT(pCtx)); } cryptography-primitives-1.0.0/sources/ippcp/pcpprimeg.h000066400000000000000000000065451470420105600234020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // */ #if !defined(_CP_PRIME_H) #define _CP_PRIME_H #include "pcpbn.h" #include "pcpmontgomery.h" /* // Prime context */ struct _cpPrime { Ipp32u idCtx; /* Prime context identifier */ cpSize maxBitSize; /* max bit length */ BNU_CHUNK_T* pPrime; /* prime value */ BNU_CHUNK_T* pT1; /* temporary BNU */ BNU_CHUNK_T* pT2; /* temporary BNU */ BNU_CHUNK_T* pT3; /* temporary BNU */ gsModEngine* pMont; /* montgomery engine */ }; /* alignment */ #define PRIME_ALIGNMENT ((int)sizeof(void*)) /* Prime accessory macros */ #define PRIME_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxPrimeNumber ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define PRIME_MAXBITSIZE(ctx) ((ctx)->maxBitSize) #define PRIME_NUMBER(ctx) ((ctx)->pPrime) #define PRIME_TEMP1(ctx) ((ctx)->pT1) #define PRIME_TEMP2(ctx) ((ctx)->pT2) #define PRIME_TEMP3(ctx) ((ctx)->pT3) #define PRIME_MONT(ctx) ((ctx)->pMont) #define PRIME_VALID_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxPrimeNumber) /* // Number of Miller-Rabin rounds for an error rate of less than 1/2^80 for random 'b'-bit input, b >= 100. // (see Table 4.4, Handbook of Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996] */ #define MR_rounds_p80(b) ((b) >= 1300 ? 2 : \ (b) >= 850 ? 3 : \ (b) >= 650 ? 4 : \ (b) >= 550 ? 5 : \ (b) >= 450 ? 6 : \ (b) >= 400 ? 7 : \ (b) >= 350 ? 8 : \ (b) >= 300 ? 9 : \ (b) >= 250 ? 12 : \ (b) >= 200 ? 15 : \ (b) >= 150 ? 18 : \ /*(b) >= 100*/ 27) /* easy prime test */ #define cpMimimalPrimeTest OWNAPI(cpMimimalPrimeTest) IPP_OWN_DECL (int, cpMimimalPrimeTest, (const Ipp32u* pPrime, cpSize ns)) /* prime test */ #define cpPrimeTest OWNAPI(cpPrimeTest) IPP_OWN_DECL (int, cpPrimeTest, (const BNU_CHUNK_T* pPrime, cpSize primeLen, cpSize nTrials, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) #define cpPackPrimeCtx OWNAPI(cpPackPrimeCtx) IPP_OWN_DECL (void, cpPackPrimeCtx, (const IppsPrimeState* pCtx, Ipp8u* pBuffer)) #define cpUnpackPrimeCtx OWNAPI(cpUnpackPrimeCtx) IPP_OWN_DECL (void, cpUnpackPrimeCtx, (const Ipp8u* pBuffer, IppsPrimeState* pCtx)) #endif /* _CP_PRIME_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpprimegen_bn.c000066400000000000000000000101471470420105600243700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeGen_BN() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcptool.h" /*F* // Name: ippsPrimeGen_BN // // Purpose: Generates a random probable prime Big number of the specified bitlength. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == rndFunc // ippStsContextMatchErr !PRIME_VALID_ID() // ippStsLengthErr 1 > nBits // ippStsOutOfRangeErr nBits > PRIME_MAXBITSIZE() // ippStsBadArgErr 1 > nTrials // ippStsInsufficientEntropy when prime generation fails due // to a poor choice of seed/context bitstream. // ippStsNoErr no error // // Parameters: // pPrime BigNum context // nBits bitlength for the desired probable prime number // nTrials parameter for the Miller-Rabin probable primality test // pCtx pointer to the context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters // // // Notes: // ippsPrimeGen_BN() returns ippStsInsufficientEntropy, if it // detects that it needs more entropy seed during its probable prime // generation. In this case, the user should update PRNG parameters // and call the primitive again. *F*/ IPPFUN(IppStatus, ippsPrimeGen_BN, (IppsBigNumState* pPrime, int nBits, int nTrials, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) { /* test generator context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); /* test BN context */ IPP_BAD_PTR1_RET(pPrime); IPP_BADARG_RET(!BN_VALID_ID(pPrime), ippStsContextMatchErr); IPP_BADARG_RET(nBits<1, ippStsLengthErr); IPP_BADARG_RET(nBits>PRIME_MAXBITSIZE(pCtx), ippStsOutOfRangeErr); IPP_BADARG_RET(BN_ROOM(pPrime) < BITS_BNU_CHUNK(nBits), ippStsOutOfRangeErr); IPP_BADARG_RET(nTrials < 0, ippStsBadArgErr); IPP_BAD_PTR1_RET(rndFunc); { cpSize count; Ipp32u result = IPP_IS_COMPOSITE; BNU_CHUNK_T botPattern = 0x1; BNU_CHUNK_T topPattern = (BNU_CHUNK_T)1 << ((nBits-1)&(BNU_CHUNK_BITS-1)); BNU_CHUNK_T topMask = MASK_BNU_CHUNK(nBits); BNU_CHUNK_T* pRand = BN_NUMBER(pPrime); cpSize randLen = BITS_BNU_CHUNK(nBits); ZEXPAND_BNU(pRand, 0, BN_ROOM(pPrime)); BN_SIZE(pPrime) = randLen; BN_SIGN(pPrime) = ippBigNumPOS; if (nTrials < 1) nTrials = MR_rounds_p80(nBits); #define MAX_COUNT (1000) for(count=0; count /*F* // Name: ippsPrimeGen // // Purpose: Generates a random probable prime number of the specified bitlength. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == rndFunc // ippStsContextMatchErr !PRIME_VALID_ID() // ippStsLengthErr 1 > nBits // ippStsOutOfRangeErr nBits > PRIME_MAXBITSIZE() // ippStsBadArgErr 1 > nTrials // ippStsInsufficientEntropy when prime generation fails due // to a poor choice of seed/context bitstream. // ippStsNoErr no error // // Parameters: // nBits bitlength for the desired probable prime number // nTrials parameter for the Miller-Rabin probable primality test // pCtx pointer to the context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters // // // Notes: // ippsPrimeGen()returns ippStsInsufficientEntropy, if it // detects that it needs more entropy seed during its probable prime // generation. In this case, the user should update PRNG parameters // and call the primitive again. *F*/ IPPFUN(IppStatus, ippsPrimeGen, (int nBits, int nTrials, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) { IPP_BAD_PTR2_RET(pCtx, rndFunc); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(nBits<1, ippStsLengthErr); IPP_BADARG_RET(nBits>PRIME_MAXBITSIZE(pCtx), ippStsOutOfRangeErr); IPP_BADARG_RET(nTrials < 0, ippStsBadArgErr); { cpSize count; BNU_CHUNK_T botPattern = 0x1; BNU_CHUNK_T topPattern = (BNU_CHUNK_T)1 << ((nBits-1)&(BNU_CHUNK_BITS-1)); BNU_CHUNK_T topMask = MASK_BNU_CHUNK(nBits); BNU_CHUNK_T* pRand = PRIME_NUMBER(pCtx); cpSize randLen = BITS_BNU_CHUNK(nBits); ZEXPAND_BNU(pRand, 0, BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx))); if(nTrials < 1) nTrials = MR_rounds_p80(nBits); #define MAX_COUNT (1000) for(count=0; countidCtx // ippStsNoErr no error // // Parameters: // pPrime pointer to the BNU value // pSize pointer to the BNU wordsize // pCtx pointer to the context // *F*/ IPPFUN(IppStatus, ippsPrimeGet, (Ipp32u* pPrime, int* pSize, const IppsPrimeState* pCtx)) { IPP_BAD_PTR3_RET(pCtx, pPrime, pSize); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); { Ipp32u* pValue = (Ipp32u*)PRIME_NUMBER(pCtx); cpSize len32 = BITS2WORD32_SIZE(PRIME_MAXBITSIZE(pCtx)); FIX_BNU32(pValue, len32); COPY_BNU(pPrime, pValue, len32); *pSize = len32; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimeget_bn.c000066400000000000000000000041001470420105600243660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeGet_BN() // */ #include "owncp.h" #include "pcpprimeg.h" /*F* // Name: ippsPrimeGet_BN // // Purpose: Extracts probable prime and store into BN. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pPrime // ippStsContextMatchErr illegal pCtx->idCtx // illegal pPrime->idCtx // ippStsOutOfRangeErr BN_ROOM(pPrime) < BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx)) // ippStsNoErr no error // // Parameters: // pPrime pointer to the BN // pCtx pointer to the context // *F*/ IPPFUN(IppStatus, ippsPrimeGet_BN, (IppsBigNumState* pPrime, const IppsPrimeState* pCtx)) { IPP_BAD_PTR2_RET(pCtx, pPrime); IPP_BADARG_RET(!BN_VALID_ID(pPrime), ippStsContextMatchErr); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); { BNU_CHUNK_T* pValue = PRIME_NUMBER(pCtx); cpSize ns = BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx)); FIX_BNU(pValue, ns); IPP_BADARG_RET(BN_ROOM(pPrime) < ns, ippStsOutOfRangeErr); COPY_BNU(BN_NUMBER(pPrime), pValue, ns); BN_SIZE(pPrime) = ns; BN_SIGN(pPrime) = ippBigNumPOS; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimegetsize.c000066400000000000000000000036751470420105600246220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeGetSize() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcptool.h" /*F* // Name: ippsPrimeGetSize // // Purpose: Returns size of Prime Number Generator context (bytes). // // Returns: Reason: // ippStsNullPtrErr NULL == pSize // ippStsLengthErr 1 > nMaxBits // ippStsNoErr no error // // Parameters: // nMaxBits max length of a prime number // pSize pointer to the size of internal context *F*/ IPPFUN(IppStatus, ippsPrimeGetSize, (int nMaxBits, int* pSize)) { IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(nMaxBits<1, ippStsLengthErr); { cpSize len = BITS_BNU_CHUNK(nMaxBits); cpSize montSize; gsModEngineGetSize(nMaxBits, MONT_DEFAULT_POOL_LENGTH, &montSize); *pSize = (Ipp32s)sizeof(IppsPrimeState) +len*(Ipp32s)sizeof(BNU_CHUNK_T) +len*(Ipp32s)sizeof(BNU_CHUNK_T) +len*(Ipp32s)sizeof(BNU_CHUNK_T) +len*(Ipp32s)sizeof(BNU_CHUNK_T) +montSize +PRIME_ALIGNMENT-1; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimeginitca.c000066400000000000000000000044001470420105600245510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeInit() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcptool.h" /*F* // Name: ippsPrimeInit // // Purpose: Initializes Prime Number Generator context // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // ippStsLengthErr 1 > nMaxBits // ippStsNoErr no error // // Parameters: // nMaxBits max length of a prime number // pCtx pointer to the context to be initialized *F*/ IPPFUN(IppStatus, ippsPrimeInit, (int nMaxBits, IppsPrimeState* pCtx)) { IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(nMaxBits<1, ippStsLengthErr); { Ipp8u* ptr = (Ipp8u*)pCtx; cpSize len = BITS_BNU_CHUNK(nMaxBits); PRIME_SET_ID(pCtx); PRIME_MAXBITSIZE(pCtx) = nMaxBits; ptr += sizeof(IppsPrimeState); ptr = (Ipp8u*)(IPP_ALIGNED_PTR(ptr, PRIME_ALIGNMENT)); PRIME_NUMBER(pCtx) = (BNU_CHUNK_T*)ptr; ptr += len*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_TEMP1(pCtx) = (BNU_CHUNK_T*)ptr; ptr += len*(Ipp32s)(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_TEMP2(pCtx) = (BNU_CHUNK_T*)ptr; ptr += len*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_TEMP3(pCtx) = (BNU_CHUNK_T*)ptr; ptr += len*(Ipp32s)sizeof(BNU_CHUNK_T); PRIME_MONT(pCtx) = (gsModEngine*)(ptr); gsModEngineInit(PRIME_MONT(pCtx), NULL, nMaxBits, MONT_DEFAULT_POOL_LENGTH, gsModArithMont()); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimegsetca.c000066400000000000000000000043351470420105600244100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeSet() // */ #include "owncp.h" #include "pcpprimeg.h" /*F* // Name: ippsPrimeSet // // Purpose: Sets a trial BNU for further testing // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pPrime // ippStsContextMatchErr illegal pCtx->idCtx // ippStsLengthErr 1 > nBits // ippStsOutOfRangeErr nBits > PRIME_MAXBITSIZE(pCtx) // ippStsNoErr no error // // Parameters: // pPrime pointer to the number to be set // nBits bitlength of input number bitlength // pCtx pointer to the context // *F*/ IPPFUN(IppStatus, ippsPrimeSet, (const Ipp32u* pPrime, int nBits, IppsPrimeState* pCtx)) { IPP_BAD_PTR2_RET(pCtx, pPrime); IPP_BADARG_RET(nBits<1, ippStsLengthErr); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(nBits > PRIME_MAXBITSIZE(pCtx), ippStsOutOfRangeErr); /* clear prime container */ ZEXPAND_BNU(PRIME_NUMBER(pCtx), 0, BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx))); { Ipp32u* pValue = (Ipp32u*)PRIME_NUMBER(pCtx); cpSize len32 = BITS2WORD32_SIZE(nBits); Ipp32u mask = MAKEMASK32(nBits); FIX_BNU32(pPrime, len32); ZEXPAND_COPY_BNU(pValue, BITS2WORD32_SIZE(PRIME_MAXBITSIZE(pCtx)), pPrime, len32); pValue[len32-1] &= mask; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimeset_bn.c000066400000000000000000000044501470420105600244120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeSet_BN() // */ #include "owncp.h" #include "pcpprimeg.h" /*F* // Name: ippsPrimeSet_BN // // Purpose: Sets a trial BN for further testing // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pPrime // ippStsContextMatchErr illegal pCtx->idCtx // illegal pPrime->idCtx // ippStsOutOfRangeErr BITSIZE_BNU(BN_NUMBER(pPrime), BN_SIZE(pPrime)) // > PRIME_MAXBITSIZE(pCtx) // ippStsNoErr no error // // Parameters: // pPrime pointer to the BN to be set // pCtx pointer to the context // *F*/ IPPFUN(IppStatus, ippsPrimeSet_BN, (const IppsBigNumState* pPrime, IppsPrimeState* pCtx)) { IPP_BAD_PTR2_RET(pCtx, pPrime); IPP_BADARG_RET(!BN_VALID_ID(pPrime), ippStsContextMatchErr); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPrime), BN_SIZE(pPrime)) > PRIME_MAXBITSIZE(pCtx), ippStsOutOfRangeErr); { BNU_CHUNK_T* pPrimeU = BN_NUMBER(pPrime); cpSize ns = BN_SIZE(pPrime); cpSize nBits = BITSIZE_BNU(pPrimeU, ns); BNU_CHUNK_T* pPrimeCtx = PRIME_NUMBER(pCtx); BNU_CHUNK_T topMask = MASK_BNU_CHUNK(nBits); ZEXPAND_COPY_BNU(pPrimeCtx, BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx)), pPrimeU, ns); pPrimeCtx[ns-1] &= topMask; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimetest.c000066400000000000000000000045661470420105600241270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeTest() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcptool.h" /*F* // Name: ippsPrimeTest // // Purpose: Test a number for being a probable prime. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == rndFunc // NULL == pResult // ippStsContextMatchErr !PRIME_VALID_ID() // ippStsBadArgErr 1 > nTrials // ippStsNoErr no error // // Parameters: // pResult result of test // nTrials parameter for the Miller-Rabin probable primality test // pCtx pointer to the context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters *F*/ IPPFUN(IppStatus, ippsPrimeTest, (int nTrials, Ipp32u* pResult, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) { IPP_BAD_PTR3_RET(pResult, pCtx, rndFunc); IPP_BADARG_RET(nTrials<1, ippStsBadArgErr); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); { BNU_CHUNK_T* pPrime = PRIME_NUMBER(pCtx); cpSize ns = BITS_BNU_CHUNK(PRIME_MAXBITSIZE(pCtx)); FIX_BNU(pPrime, ns); { int ret = cpPrimeTest(pPrime, ns, nTrials, pCtx, rndFunc, pRndParam); if(-1 == ret) return ippStsErr; else { *pResult = ret? IPP_IS_PRIME : IPP_IS_COMPOSITE; return ippStsNoErr; } } } } cryptography-primitives-1.0.0/sources/ippcp/pcpprimetest_bn.c000066400000000000000000000050101470420105600245670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Intel(R) Cryptography Primitives Library // Prime Number Primitives. // // Contents: // ippsPrimeTest_BN() // */ #include "owncp.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcptool.h" /*F* // Name: ippsPrimeTest_BN // // Purpose: Test a Big number for being a probable prime. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == rndFunc // NULL == pResult // ippStsContextMatchErr !PRIME_VALID_ID() // ippStsBadArgErr 1 > nTrials // ippStsNoErr no error // // Parameters: // pPrime BigNum context // pResult result of test // nTrials parameter for the Miller-Rabin probable primality test // pCtx pointer to the context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters *F*/ IPPFUN(IppStatus, ippsPrimeTest_BN, (const IppsBigNumState* pPrime, int nTrials, Ipp32u* pResult, IppsPrimeState* pCtx, IppBitSupplier rndFunc, void* pRndParam)) { IPP_BAD_PTR4_RET(pPrime, pResult, pCtx, rndFunc); IPP_BADARG_RET(nTrials<1, ippStsBadArgErr); IPP_BADARG_RET(!PRIME_VALID_ID(pCtx), ippStsContextMatchErr); IPP_BADARG_RET(!BN_VALID_ID(pPrime), ippStsContextMatchErr); { BNU_CHUNK_T* pPrimeBN = BN_NUMBER(pPrime); cpSize ns = BN_SIZE(pPrime); { int ret = cpPrimeTest(pPrimeBN, ns, nTrials, pCtx, rndFunc, pRndParam); if(-1 == ret) return ippStsErr; else { *pResult = ret? IPP_IS_PRIME : IPP_IS_COMPOSITE; return ippStsNoErr; } } } } cryptography-primitives-1.0.0/sources/ippcp/pcpprng.h000066400000000000000000000051451470420105600230600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal Pseudo Random Generator Function Prototypes // */ #if !defined(_CP_PRNG_H) #define _CP_PRNG_H /* // Pseudo-random generation context */ #define MAX_XKEY_SIZE 512 #define DEFAULT_XKEY_SIZE 512 /* must be >=160 || <=512 */ struct _cpPRNG { Ipp32u idCtx; /* PRNG identifier */ cpSize seedBits; /* secret seed-key bitsize */ BNU_CHUNK_T Q[BITS_BNU_CHUNK(160)]; /* modulus */ BNU_CHUNK_T T[BITS_BNU_CHUNK(160)]; /* parameter of SHA_G() funct */ BNU_CHUNK_T xAug[BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; /* optional entropy augment */ BNU_CHUNK_T xKey[BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; /* secret seed-key */ }; /* alignment */ #define PRNG_ALIGNMENT ((int)(sizeof(void*))) #define RAND_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxPRNG ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define RAND_SEEDBITS(ctx) ((ctx)->seedBits) #define RAND_Q(ctx) ((ctx)->Q) #define RAND_T(ctx) ((ctx)->T) #define RAND_XAUGMENT(ctx) ((ctx)->xAug) #define RAND_XKEY(ctx) ((ctx)->xKey) #define RAND_VALID_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxPRNG) #define cpPRNGen OWNAPI(cpPRNGen) IPP_OWN_DECL (int, cpPRNGen, (Ipp32u* pBuffer, cpSize bitLen, IppsPRNGState* pCtx)) #define cpPRNGenPattern OWNAPI(cpPRNGenPattern) IPP_OWN_DECL (int, cpPRNGenPattern, (BNU_CHUNK_T* pRand, int bitSize, BNU_CHUNK_T botPattern, BNU_CHUNK_T topPattern, IppBitSupplier rndFunc, void* pRndParam)) #define cpPRNGenRange OWNAPI(cpPRNGenRange) IPP_OWN_DECL (int, cpPRNGenRange, (BNU_CHUNK_T* pRand, const BNU_CHUNK_T* pLo, cpSize loLen, const BNU_CHUNK_T* pHi, cpSize hiLen, IppBitSupplier rndFunc, void* pRndParam)) #endif /* _CP_PRNG_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpprng_gen.c000066400000000000000000000105431470420105600237020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // cpPRNGen() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "hash/pcphash.h" #include "pcpprng.h" #include "pcptool.h" /* // G() function based on SHA1 // // Parameters: // T 160 bit parameter // pHexStr input hex string // hexStrLen size of hex string (Ipp8u segnments) // xBNU 160 bit BNU result // // Note 1: // must to be hexStrLen <= 64 (512 bits) */ static void SHA1_G(Ipp32u* xBNU, const Ipp32u* T, Ipp8u* pHexStr, int hexStrLen) { /* select processing function */ cpHashProc updateFunc; #if (_SHA_NI_ENABLING_==_FEATURE_ON_) updateFunc = UpdateSHA1ni; #elif (_SHA_NI_ENABLING_==_FEATURE_TICKTOCK_) updateFunc = IsFeatureEnabled(ippCPUID_SHA)? UpdateSHA1ni : UpdateSHA1; #else updateFunc = UpdateSHA1; #endif /* pad HexString zeros */ PadBlock(0, pHexStr+hexStrLen, BITS2WORD8_SIZE(MAX_XKEY_SIZE)-hexStrLen); /* reset initial HASH value */ xBNU[0] = T[0]; xBNU[1] = T[1]; xBNU[2] = T[2]; xBNU[3] = T[3]; xBNU[4] = T[4]; /* SHA1 */ //UpdateSHA1(xBNU, pHexStr, BITS2WORD8_SIZE(MAX_XKEY_SIZE), SHA1_cnt); updateFunc(xBNU, pHexStr, BITS2WORD8_SIZE(MAX_XKEY_SIZE), SHA1_cnt); /* swap back */ SWAP(xBNU[0],xBNU[4]); SWAP(xBNU[1],xBNU[3]); } /*F* // Name: cpPRNGen // // Purpose: Returns bitsize of the bitstring has been added // // Returns: // bitsize of the bitstring has been added // // Parameters: // pRand pointer to the buffer // nBits number of bits be requested // pRnd pointer to the context *F*/ IPP_OWN_DEFN (int, cpPRNGen, (Ipp32u* pRand, cpSize nBits, IppsPRNGState* pRnd)) { BNU_CHUNK_T Xj [BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; BNU_CHUNK_T XVAL[BITS_BNU_CHUNK(MAX_XKEY_SIZE)]; Ipp8u TXVAL[BITS2WORD8_SIZE(MAX_XKEY_SIZE)]; /* XKEY length in BNU_CHUNK_T */ cpSize xKeyLen = BITS_BNU_CHUNK(RAND_SEEDBITS(pRnd)); /* XKEY length in bytes */ cpSize xKeySize= BITS2WORD8_SIZE(RAND_SEEDBITS(pRnd)); /* XKEY word's mask */ BNU_CHUNK_T xKeyMsk = MASK_BNU_CHUNK(RAND_SEEDBITS(pRnd)); /* number of Ipp32u chunks to be generated */ cpSize genlen = BITS2WORD32_SIZE(nBits); ZEXPAND_BNU(Xj, 0, BITS_BNU_CHUNK(MAX_XKEY_SIZE)); ZEXPAND_BNU(XVAL, 0, BITS_BNU_CHUNK(MAX_XKEY_SIZE)); while(genlen) { cpSize len; /* Step 1: XVAL=(Xkey+Xseed) mod 2^b */ BNU_CHUNK_T carry = cpAdd_BNU(XVAL, RAND_XKEY(pRnd), RAND_XAUGMENT(pRnd), xKeyLen); XVAL[xKeyLen-1] &= xKeyMsk; /* Step 2: xj=G(t, XVAL) mod Q */ cpToOctStr_BNU(TXVAL, xKeySize, XVAL, xKeyLen); SHA1_G((Ipp32u*)Xj, (Ipp32u*)RAND_T(pRnd), TXVAL, xKeySize); { cpSize sizeXj = BITS_BNU_CHUNK(160); if(0 <= cpCmp_BNU(Xj, BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE), RAND_Q(pRnd),BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE)) ) sizeXj = cpMod_BNU(Xj, BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE), RAND_Q(pRnd), BITS_BNU_CHUNK(IPP_SHA1_DIGEST_BITSIZE)); FIX_BNU(Xj, sizeXj); ZEXPAND_BNU(Xj, sizeXj, BITS_BNU_CHUNK(MAX_XKEY_SIZE)); } /* Step 3: Xkey=(1+Xkey+Xj) mod 2^b */ cpInc_BNU(RAND_XKEY(pRnd), RAND_XKEY(pRnd), xKeyLen, 1); carry = cpAdd_BNU(RAND_XKEY(pRnd), RAND_XKEY(pRnd), Xj, xKeyLen); RAND_XKEY(pRnd)[xKeyLen-1] &= xKeyMsk; /* fill out result */ len = genlen=_IPP_G9) || (_IPP32E>=_IPP32E_E9)) __IPPCP_INLINE int cpRand_hw_sample(BNU_CHUNK_T* pSample) { #define LOCAL_COUNTER (8) int n; int success = 0; for(n=0; n=_IPP32E_E9) __IPPCP_INLINE int cpRand_hw_sample32(Ipp32u* pSample) { #define LOCAL_COUNTER (8) int n; int success = 0; for(n=0; n=_IPP32E_E9) if( bufLen%((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) ) { if( !cpRand_hw_sample32(pBuffer)) { return 0; } } #endif return 1; } #endif #endif /* #if !defined (_PCP_PRN_GEN_HW_H) */ cryptography-primitives-1.0.0/sources/ippcp/pcpprngen_bn.c000066400000000000000000000047671470420105600240660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGen_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "hash/pcphash.h" #include "pcpprng.h" #include "pcptool.h" /*F* // Name: ippsPRNGen_BN // // Purpose: Generates a pseudorandom big number of the specified nBits length. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pRand // // ippStsContextMatchErr illegal pCtx->idCtx // illegal pRand->idCtx // // ippStsLengthErr 1 > nBits // nBits > BN_ROOM(pRand) // // ippStsNoErr no error // // Parameters: // pRand pointer to the BN random // nBits number of bits be requested // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGen_BN,(IppsBigNumState* pRand, int nBits, void* pCtx)) { IppsPRNGState* pRndCtx; /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); pRndCtx = (IppsPRNGState*)(pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pRndCtx), ippStsContextMatchErr); /* test random BN */ IPP_BAD_PTR1_RET(pRand); IPP_BADARG_RET(!BN_VALID_ID(pRand), ippStsContextMatchErr); /* test sizes */ IPP_BADARG_RET(nBits< 1, ippStsLengthErr); IPP_BADARG_RET(nBits> BN_ROOM(pRand)*BNU_CHUNK_BITS, ippStsLengthErr); { BNU_CHUNK_T* pRandBN = BN_NUMBER(pRand); cpSize rndSize = BITS_BNU_CHUNK(nBits); BNU_CHUNK_T rndMask = MASK_BNU_CHUNK(nBits); cpPRNGen((Ipp32u*)pRandBN, nBits, pRndCtx); pRandBN[rndSize-1] &= rndMask; FIX_BNU(pRandBN, rndSize); BN_SIZE(pRand) = rndSize; BN_SIGN(pRand) = ippBigNumPOS; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprngen_pattern.c000066400000000000000000000031141470420105600251250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // cpPRNGenPattern() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" #include "pcptool.h" /* generates random string of specified bitSize length returns: 1 random bit string generated -1 detected internal error (ippStsNoErr != rndFunc()) */ IPP_OWN_DEFN (int, cpPRNGenPattern, (BNU_CHUNK_T* pRand, int bitSize, BNU_CHUNK_T botPattern, BNU_CHUNK_T topPattern, IppBitSupplier rndFunc, void* pRndParam)) { BNU_CHUNK_T topMask = MASK_BNU_CHUNK(bitSize); cpSize randLen = BITS_BNU_CHUNK(bitSize); IppStatus sts = rndFunc((Ipp32u*)pRand, bitSize, pRndParam); if(ippStsNoErr!=sts) return -1; pRand[randLen-1] &= topMask; pRand[0] |= botPattern; pRand[randLen-1] |= topPattern; return 1; } cryptography-primitives-1.0.0/sources/ippcp/pcpprngen_range.c000066400000000000000000000036451470420105600245550ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // cpPRNGenRange() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" #include "pcptool.h" /* generates random string of specified bitSize length within specified ragnge lo < r < Hi returns: 0 random bit string not generated 1 random bit string generated -1 detected internal error (ippStsNoErr != rndFunc()) */ IPP_OWN_DEFN (int, cpPRNGenRange, (BNU_CHUNK_T* pRand, const BNU_CHUNK_T* pLo, cpSize loLen, const BNU_CHUNK_T* pHi, cpSize hiLen, IppBitSupplier rndFunc, void* pRndParam)) { int bitSize = BITSIZE_BNU(pHi,hiLen); BNU_CHUNK_T topMask = MASK_BNU_CHUNK(bitSize); #define MAX_COUNT (1000) int n; for(n=0; nidCtx // // ippStsLengthErr 1 > nBits // // ippStsNoErr no error // // Parameters: // pRand pointer to the buffer // nBits number of bits be requested // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGen,(Ipp32u* pRand, int nBits, void* pCtx)) { IppsPRNGState* pCtxCtx = (IppsPRNGState*)pCtx; /* test PRNG context */ IPP_BAD_PTR2_RET(pRand, pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pCtxCtx), ippStsContextMatchErr); /* test sizes */ IPP_BADARG_RET(nBits< 1, ippStsLengthErr); { cpSize rndSize = BITS2WORD32_SIZE(nBits); Ipp32u rndMask = MAKEMASK32(nBits); cpPRNGen(pRand, nBits, pCtxCtx); pRand[rndSize-1] &= rndMask; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprngenhw_bn.c000066400000000000000000000052541470420105600244150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGenRDRAND_BN() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" #include "pcpprng_genhw.h" /*F* // Name: ippsPRNGenRDRAND_BN // // Purpose: Generates a pseudorandom big number // based on RDRAND instruction of the specified nBits length. // // Returns: Reason: // ippStsNullPtrErr NULL == pBuffer // // ippStsLengthErr 1 > nBits // nBits > BN_ROOM(pRand) // // ippStsNotSupportedModeErr unsupported rdrand instruction // // ippStsErr random big number can't be generated // // ippStsNoErr no error // // Parameters: // pRand pointer to the big number // nBits number of bits be requested // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGenRDRAND_BN,(IppsBigNumState* pRand, int nBits, void* pCtx)) { /* test random BN */ IPP_BAD_PTR1_RET(pRand); IPP_BADARG_RET(!BN_VALID_ID(pRand), ippStsContextMatchErr); /* test sizes */ IPP_BADARG_RET(nBits< 1, ippStsLengthErr); IPP_BADARG_RET(nBits> BN_ROOM(pRand)*BNU_CHUNK_BITS, ippStsLengthErr); IPP_UNREFERENCED_PARAMETER(pCtx); #if ((_IPP>=_IPP_G9) || (_IPP32E>=_IPP32E_E9)) if( IsFeatureEnabled(ippCPUID_RDRAND) ) { BNU_CHUNK_T* pRandBN = BN_NUMBER(pRand); cpSize rndSize = BITS_BNU_CHUNK(nBits); BNU_CHUNK_T rndMask = MASK_BNU_CHUNK(nBits); if(cpRandHW_buffer((Ipp32u*)pRandBN, rndSize*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)))) { pRandBN[rndSize-1] &= rndMask; FIX_BNU(pRandBN, rndSize); BN_SIZE(pRand) = rndSize; BN_SIGN(pRand) = ippBigNumPOS; return ippStsNoErr; } else return ippStsErr; } /* unsupported rdrand instruction */ else #endif IPP_ERROR_RET(ippStsNotSupportedModeErr); } cryptography-primitives-1.0.0/sources/ippcp/pcpprngenhwca.c000066400000000000000000000043711470420105600242410ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGenRDRAND() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" #include "pcpprng_genhw.h" /*F* // Name: ippsPRNGenRDRAND // // Purpose: Generates a pseudorandom bit sequence // based on RDRAND instruction of the specified nBits length. // // Returns: Reason: // ippStsNullPtrErr NULL == pRand // // ippStsLengthErr 1 > nBits // // ippStsNotSupportedModeErr unsupported rdrand instruction // // ippStsErr random bit sequence can't be generated // // ippStsNoErr no error // // Parameters: // pRand pointer to the buffer // nBits number of bits be requested // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGenRDRAND,(Ipp32u* pRand, int nBits, void* pCtx)) { /* test PRNG buffer */ IPP_BAD_PTR1_RET(pRand); /* test sizes */ IPP_BADARG_RET(nBits< 1, ippStsLengthErr); IPP_UNREFERENCED_PARAMETER(pCtx); #if ((_IPP>=_IPP_G9) || (_IPP32E>=_IPP32E_E9)) if( IsFeatureEnabled(ippCPUID_RDRAND) ) { cpSize rndSize = BITS2WORD32_SIZE(nBits); Ipp32u rndMask = MAKEMASK32(nBits); if(cpRandHW_buffer(pRand, rndSize)) { pRand[rndSize-1] &= rndMask; return ippStsNoErr; } else return ippStsErr; } /* unsupported rdrand instruction */ else #endif IPP_ERROR_RET(ippStsNotSupportedModeErr); } cryptography-primitives-1.0.0/sources/ippcp/pcpprnggetseed.c000066400000000000000000000037251470420105600244160ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGGetSeed() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" /*F* // Name: ippsPRNGGetSeed // // Purpose: Get current SEED value from the state // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pSeed // // ippStsContextMatchErr illegal pCtx->idCtx // illegal pSeed->idCtx // ippStsOutOfRangeErr length of the actual SEED > length SEED destination // // ippStsNoErr no error // // Parameters: // pCtx pointer to the context // pSeed pointer to the SEED *F*/ IPPFUN(IppStatus, ippsPRNGGetSeed, (const IppsPRNGState* pCtx, IppsBigNumState* pSeed)) { /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pCtx), ippStsContextMatchErr); /* test seed */ IPP_BAD_PTR1_RET(pSeed); IPP_BADARG_RET(!BN_VALID_ID(pSeed), ippStsContextMatchErr); return ippsSet_BN(ippBigNumPOS, BITS2WORD32_SIZE(RAND_SEEDBITS(pCtx)), (Ipp32u*)RAND_XKEY(pCtx), pSeed); } cryptography-primitives-1.0.0/sources/ippcp/pcpprnggetsize.c000066400000000000000000000026151470420105600244450ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" #include "pcptool.h" /*F* // Name: ippsPRNGGetSize // // Purpose: Returns size of PRNG context (bytes). // // Returns: Reason: // ippStsNullPtrErr NULL == pSize // // ippStsNoErr no error // // Parameters: // pSize pointer to the size of internal context *F*/ IPPFUN(IppStatus, ippsPRNGGetSize, (int* pSize)) { IPP_BAD_PTR1_RET(pSize); *pSize = sizeof(IppsPRNGState); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpprnginitca.c000066400000000000000000000047371470420105600242510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsPRNGInit // // Purpose: Initializes PRNG context // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // // ippStsLengthErr seedBits < 1 // seedBits < MAX_XKEY_SIZE // seedBits % 8 !=0 // // ippStsNoErr no error // // Parameters: // seedBits seed bitsize // pCtx pointer to the context to be initialized *F*/ IPPFUN(IppStatus, ippsPRNGInit, (int seedBits, IppsPRNGState* pCtx)) { /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); /* test sizes */ IPP_BADARG_RET((1>seedBits) || (seedBits>MAX_XKEY_SIZE) ||(seedBits&7), ippStsLengthErr); { int hashIvSize = cpHashIvSize(ippHashAlg_SHA1); const Ipp8u* iv = cpHashIV[ippHashAlg_SHA1]; /* cleanup context */ ZEXPAND_BNU((Ipp8u*)pCtx, 0, (cpSize)(sizeof(IppsPRNGState))); RAND_SET_ID(pCtx); RAND_SEEDBITS(pCtx) = seedBits; /* default Q parameter */ ((Ipp32u*)RAND_Q(pCtx))[0] = 0xFFFFFFFF; ((Ipp32u*)RAND_Q(pCtx))[1] = 0xFFFFFFFF; ((Ipp32u*)RAND_Q(pCtx))[2] = 0xFFFFFFFF; ((Ipp32u*)RAND_Q(pCtx))[3] = 0xFFFFFFFF; ((Ipp32u*)RAND_Q(pCtx))[4] = 0xFFFFFFFF; /* workaround to avoid false positive stringop-overflow error on gcc10.1 and gcc11.1 */ hashIvSize = ( IPP_MIN(hashIvSize, BITS2WORD8_SIZE(160)) ); /* default T parameter */ CopyBlock(iv, RAND_T(pCtx), hashIvSize); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprngsetaugment.c000066400000000000000000000041501470420105600251430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGSetAugment() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" /*F* // Name: ippsPRNGSetAugment // // Purpose: Sets the Entropy Augmentation // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pAug // // ippStsContextMatchErr illegal pCtx->idCtx // illegal pAug->idCtx // // ippStsNoErr no error // // Parameters: // pAug pointer to the entropy eugmentation // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGSetAugment, (const IppsBigNumState* pAug, IppsPRNGState* pCtx)) { /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pCtx), ippStsContextMatchErr); /* test augmentation */ IPP_BAD_PTR1_RET(pAug); IPP_BADARG_RET(!BN_VALID_ID(pAug), ippStsContextMatchErr); { cpSize argSize = BITS_BNU_CHUNK( RAND_SEEDBITS(pCtx) ); BNU_CHUNK_T mask = MASK_BNU_CHUNK(RAND_SEEDBITS(pCtx)); cpSize size = IPP_MIN(BN_SIZE(pAug), argSize); ZEXPAND_COPY_BNU(RAND_XAUGMENT(pCtx), (cpSize)(sizeof(RAND_XAUGMENT(pCtx))/sizeof(BNU_CHUNK_T)), BN_NUMBER(pAug), size); RAND_XAUGMENT(pCtx)[argSize-1] &= mask; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprngsetca.c000066400000000000000000000041071470420105600240700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGSetH0() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" /*F* // Name: ippsPRNGSetH0 // // Purpose: Sets 160-bit parameter of G() function. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pH0 // // ippStsContextMatchErr illegal pCtx->idCtx // illegal pH0->idCtx // // ippStsNoErr no error // // Parameters: // pH0 pointer to the parameter used into G() function // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGSetH0,(const IppsBigNumState* pH0, IppsPRNGState* pCtx)) { /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pCtx), ippStsContextMatchErr); /* test H0 */ IPP_BAD_PTR1_RET(pH0); IPP_BADARG_RET(!BN_VALID_ID(pH0), ippStsContextMatchErr); { cpSize len = IPP_MIN(5, BN_SIZE(pH0)*((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)))); ZEXPAND_BNU(RAND_T(pCtx), 0, (int)(sizeof(RAND_T(pCtx))/sizeof(BNU_CHUNK_T))); ZEXPAND_COPY_BNU((Ipp32u*)RAND_T(pCtx), (int)(sizeof(RAND_T(pCtx))/(sizeof(Ipp32u))), (Ipp32u*)BN_NUMBER(pH0), len); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpprngsetmodulus.c000066400000000000000000000037651470420105600252060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGSetModulus() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" /*F* // Name: ippsPRNGSetModulus // // Purpose: Sets 160-bit modulus Q. // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pMod // // ippStsContextMatchErr illegal pCtx->idCtx // illegal pMod->idCtx // // ippStsBadArgErr 160 != bitsize(pMod) // // ippStsNoErr no error // // Parameters: // pMod pointer to the 160-bit modulus // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGSetModulus, (const IppsBigNumState* pMod, IppsPRNGState* pCtx)) { /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pCtx), ippStsContextMatchErr); /* test modulus */ IPP_BAD_PTR1_RET(pMod); IPP_BADARG_RET(!BN_VALID_ID(pMod), ippStsContextMatchErr); IPP_BADARG_RET(160 != BITSIZE_BNU(BN_NUMBER(pMod),BN_SIZE(pMod)), ippStsBadArgErr); ZEXPAND_COPY_BNU(RAND_Q(pCtx), (int)(sizeof(RAND_Q(pCtx))/sizeof(BNU_CHUNK_T)), BN_NUMBER(pMod), BN_SIZE(pMod)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpprngsetseed.c000066400000000000000000000041241470420105600244240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // PRNG Functions // // Contents: // ippsPRNGSetSeed() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprng.h" /*F* // Name: ippsPRNGSetSeed // // Purpose: Sets the initial state with the SEED value // // Returns: Reason: // ippStsNullPtrErr NULL == pCtx // NULL == pSeed // // ippStsContextMatchErr illegal pCtx->idCtx // illegal pSeed->idCtx // // ippStsNoErr no error // // Parameters: // pSeed pointer to the SEED // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsPRNGSetSeed, (const IppsBigNumState* pSeed, IppsPRNGState* pCtx)) { /* test PRNG context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!RAND_VALID_ID(pCtx), ippStsContextMatchErr); /* test seed */ IPP_BAD_PTR1_RET(pSeed); IPP_BADARG_RET(!BN_VALID_ID(pSeed), ippStsContextMatchErr); { cpSize argSize = BITS_BNU_CHUNK( RAND_SEEDBITS(pCtx) ); BNU_CHUNK_T mask = MASK_BNU_CHUNK(RAND_SEEDBITS(pCtx)); cpSize size = IPP_MIN(BN_SIZE(pSeed), argSize); ZEXPAND_COPY_BNU(RAND_XKEY(pCtx), (cpSize)(sizeof(RAND_XKEY(pCtx))/sizeof(BNU_CHUNK_T)), BN_NUMBER(pSeed), size); RAND_XKEY(pCtx)[argSize-1] &= mask; return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprij.h000066400000000000000000000377231470420105600227050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal Rijndael based Encrypt/Decrypt Function Prototypes // // */ #if !defined(_PCP_RIJ_H) #define _PCP_RIJ_H #include "pcpaesnoise.h" /* // The GF(256) modular polynomial and elements */ #define WPOLY 0x011B #define BPOLY 0x1B /* // Make WORD using 4 arbitrary bytes */ #define BYTES_TO_WORD(b0,b1,b2,b3) ( ( ((Ipp32u)((Ipp8u)(b3))) <<24 ) \ |( ((Ipp32u)((Ipp8u)(b2))) <<16 ) \ |( ((Ipp32u)((Ipp8u)(b1))) << 8 ) \ |( ((Ipp32u)((Ipp8u)(b0))) ) ) /* // Make WORD setting byte in specified position */ #define BYTE0_TO_WORD(b) BYTES_TO_WORD((b), 0, 0, 0) #define BYTE1_TO_WORD(b) BYTES_TO_WORD( 0, (b), 0, 0) #define BYTE2_TO_WORD(b) BYTES_TO_WORD( 0, 0, (b), 0) #define BYTE3_TO_WORD(b) BYTES_TO_WORD( 0, 0, 0, (b)) /* // Extract byte from specified position n. // Sure, n=0,1,2 or 3 only */ #define EBYTE(w,n) ((Ipp8u)((w) >> (8 * (n)))) /* alignment */ #define RIJ_ALIGNMENT (16) /* alignment in words */ #define RIJ_ALIGNMENT_WORD (16/4) /* Assuming word is 4 bytes in rij calculations */ #define RIJ_BYTES_IN_WORD (4) #define MBS_RIJ128 (128/8) /* message block size (bytes) */ #define MBS_RIJ192 (192/8) #define MBS_RIJ256 (256/8) #define SR (4) /* number of rows in STATE data */ #define NB(msgBlks) ((msgBlks)/32) /* message block size (words) */ /* 4-word for 128-bits data block */ /* 6-word for 192-bits data block */ /* 8-word for 256-bits data block */ #define NK(keybits) ((keybits)/32) /* key length (words): */ #define NK128 NK(ippRijndaelKey128) /* 4-word for 128-bits security key */ #define NK192 NK(ippRijndaelKey192) /* 6-word for 192-bits security key */ #define NK256 NK(ippRijndaelKey256) /* 8-word for 256-bits security key */ #define NR128_128 (10) /* number of rounds data: 128 bits key: 128 bits are used */ #define NR128_192 (12) /* number of rounds data: 128 bits key: 192 bits are used */ #define NR128_256 (14) /* number of rounds data: 128 bits key: 256 bits are used */ #define NR192_128 (12) /* number of rounds data: 192 bits key: 128 bits are used */ #define NR192_192 (12) /* number of rounds data: 192 bits key: 192 bits are used */ #define NR192_256 (14) /* number of rounds data: 192 bits key: 256 bits are used */ #define NR256_128 (14) /* number of rounds data: 256 bits key: 128 bits are used */ #define NR256_192 (14) /* number of rounds data: 256 bits key: 192 bits are used */ #define NR256_256 (14) /* number of rounds data: 256 bits key: 256 bits are used */ #define NSK128_256 ((NR128_256+1)*NK128) /* max number of scheduled keys for 128-bit data (256-bit key) (in words) */ #define NSK192_256 ((NR192_256+1)*NK192) /* max number of scheduled keys for 192-bit data (256-bit key) (in words) */ #define NSK256_256 ((NR256_256+1)*NK256) /* max number of scheduled keys for 256-bit data (256-bit key) (in words) */ /* // Rijndael's spec // // Rijndael128, Rijndael192 and Rijndael256 // reserve space for maximum number of expanded keys */ IPP_OWN_FUNPTR (void, RijnCipher, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) struct _cpRijndael128 { Ipp32u idCtx; /* Rijndael spec identifier */ int nk; /* security key length (words) */ int nb; /* data block size (words) */ int nr; /* number of rounds */ RijnCipher encoder; /* encoder/decoder */ RijnCipher decoder; /* entry point */ Ipp32u* pEncTbl; /* expanded S-boxes for */ Ipp32u* pDecTbl; /* encryption and decryption */ Ipp8u* pEncKeys; /* pointer to array of keys for encryption */ Ipp8u* pDecKeys; /* pointer to array of keys for decryption */ Ipp32u aesNI; /* AES instruction available */ Ipp32u safeInit; /* SafeInit performed */ Ipp32u keys[2*NSK128_256 + RIJ_ALIGNMENT_WORD]; /* array of keys for encryption/decryption */ #if (_AES_PROB_NOISE == _FEATURE_ON_) cpAESNoiseParams noiseParams; #endif }; struct _cpRijndael192 { Ipp32u idCtx; /* Rijndael spec identifier */ int nk; /* security key length (words) */ int nb; /* data block size (words) */ int nr; /* number of rounds */ RijnCipher encoder; /* encoder/decoder */ RijnCipher decoder; /* entry point */ Ipp32u* pEncTbl; /* expanded S-boxes for */ Ipp32u* pDecTbl; /* encryption and decryption */ Ipp8u* pEncKeys; /* pointer to array of keys for encryption */ Ipp8u* pDecKeys; /* pointer to array of keys for decryption */ Ipp32u aesNI; /* AES instruction available */ Ipp32u safeInit; /* SafeInit performed */ Ipp32u keys[2*NSK192_256 + RIJ_ALIGNMENT_WORD]; /* array of keys for encryption/decryption */ #if (_AES_PROB_NOISE == _FEATURE_ON_) cpAESNoiseParams noiseParams; #endif }; struct _cpRijndael256 { Ipp32u idCtx; /* Rijndael spec identifier */ int nk; /* security key length (words) */ int nb; /* data block size (words) */ int nr; /* number of rounds */ RijnCipher encoder; /* encoder/decoder */ RijnCipher decoder; /* entry point */ Ipp32u* pEncTbl; /* expanded S-boxes for */ Ipp32u* pDecTbl; /* encryption and decryption */ Ipp8u* pEncKeys; /* pointer array of keys for encryption */ Ipp8u* pDecKeys; /* pointer array of keys for decryprion */ Ipp32u aesNI; /* AES instruction available */ Ipp32u safeInit; /* SafeInit performed */ Ipp32u keys[2*NSK256_256 + RIJ_ALIGNMENT_WORD]; /* array of keys for encryption/decryption */ #if (_AES_PROB_NOISE == _FEATURE_ON_) cpAESNoiseParams noiseParams; #endif }; #define AES_MB_MAX_KERNEL_SIZE (16) /* max number of buffers in multi buffer */ #define CFB16_BLOCK_SIZE (16) /* CFB mode block size for multi buffer */ /* // Useful macros */ #define RIJ_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxRijndael ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define RIJ_RESET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxRijndael) #define RIJ_NB(ctx) ((ctx)->nb) #define RIJ_NK(ctx) ((ctx)->nk) #define RIJ_NR(ctx) ((ctx)->nr) #define RIJ_ENCODER(ctx) ((ctx)->encoder) #define RIJ_DECODER(ctx) ((ctx)->decoder) #define RIJ_ENC_SBOX(ctx) ((ctx)->pEncTbl) #define RIJ_DEC_SBOX(ctx) ((ctx)->pDecTbl) #define RIJ_EKEYS(ctx) ((ctx)->pEncKeys) #define RIJ_DKEYS(ctx) ((ctx)->pDecKeys) #define RIJ_AESNI(ctx) ((ctx)->aesNI) #define RIJ_SAFE_INIT(ctx) ((ctx)->safeInit) #define RIJ_KEYS_BUFFER(ctx) ((ctx)->keys) #if (_AES_PROB_NOISE == _FEATURE_ON_) #define RIJ_NOISE_PARAMS(ctx) ((ctx)->noiseParams) #endif #define VALID_RIJ_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxRijndael) /* // Internal functions */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPOSITE_GF_) #define SafeEncrypt_RIJ128 OWNAPI(SafeEncrypt_RIJ128) IPP_OWN_DECL (void, SafeEncrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) #define SafeDecrypt_RIJ128 OWNAPI(SafeDecrypt_RIJ128) IPP_OWN_DECL (void, SafeDecrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) #endif #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) #define Safe2Encrypt_RIJ128 OWNAPI(Safe2Encrypt_RIJ128) IPP_OWN_DECL (void, Safe2Encrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) #define Safe2Decrypt_RIJ128 OWNAPI(Safe2Decrypt_RIJ128) IPP_OWN_DECL (void, Safe2Decrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) #endif #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #define Encrypt_RIJ128_AES_NI OWNAPI(Encrypt_RIJ128_AES_NI) IPP_OWN_DECL (void, Encrypt_RIJ128_AES_NI, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) #define EncryptECB_RIJ128pipe_AES_NI OWNAPI(EncryptECB_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, EncryptECB_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len)) #define EncryptCBC_RIJ128_AES_NI OWNAPI(EncryptCBC_RIJ128_AES_NI) IPP_OWN_DECL (void, EncryptCBC_RIJ128_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, const Ipp8u* pIV)) #define EncryptCTR_RIJ128pipe_AES_NI OWNAPI(EncryptCTR_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, EncryptCTR_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, Ipp8u* pCtrValue, const Ipp8u* pCtrBitMask)) #define EncryptStreamCTR32_AES_NI OWNAPI(EncryptStreamCTR32_AES_NI) IPP_OWN_DECL (void, EncryptStreamCTR32_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, Ipp8u* pCtrValue)) #define EncryptCFB_RIJ128_AES_NI OWNAPI(EncryptCFB_RIJ128_AES_NI) IPP_OWN_DECL (void, EncryptCFB_RIJ128_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, int cfbBlkSize, const Ipp8u* pIV)) #define EncryptCFB32_RIJ128_AES_NI OWNAPI(EncryptCFB32_RIJ128_AES_NI) IPP_OWN_DECL (void, EncryptCFB32_RIJ128_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, int cfbBlkSize, const Ipp8u* pIV)) #define EncryptCFB128_RIJ128_AES_NI OWNAPI(EncryptCFB128_RIJ128_AES_NI) IPP_OWN_DECL (void, EncryptCFB128_RIJ128_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, const Ipp8u* pIV)) #define EncryptOFB_RIJ128_AES_NI OWNAPI(EncryptOFB_RIJ128_AES_NI) IPP_OWN_DECL (void, EncryptOFB_RIJ128_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, int ofbBlkSize, Ipp8u* pIV)) #define EncryptOFB128_RIJ128_AES_NI OWNAPI(EncryptOFB128_RIJ128_AES_NI) IPP_OWN_DECL (void, EncryptOFB128_RIJ128_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, Ipp8u* pIV)) #define Decrypt_RIJ128_AES_NI OWNAPI(Decrypt_RIJ128_AES_NI) IPP_OWN_DECL (void, Decrypt_RIJ128_AES_NI, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTbl)) #define DecryptECB_RIJ128pipe_AES_NI OWNAPI(DecryptECB_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, DecryptECB_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len)) #define DecryptCBC_RIJ128pipe_AES_NI OWNAPI(DecryptCBC_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, DecryptCBC_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, const Ipp8u* pIV)) #define DecryptCFB_RIJ128pipe_AES_NI OWNAPI(DecryptCFB_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, DecryptCFB_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int cfbBlocks, int cfbBlkSize, const Ipp8u* pIV)) #define DecryptCFB32_RIJ128pipe_AES_NI OWNAPI(DecryptCFB32_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, DecryptCFB32_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int cfbBlocks, int cfbBlkSize, const Ipp8u* pIV)) #define DecryptCFB128_RIJ128pipe_AES_NI OWNAPI(DecryptCFB128_RIJ128pipe_AES_NI) IPP_OWN_DECL (void, DecryptCFB128_RIJ128pipe_AES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, const Ipp8u* pIV)) #define cpExpandAesKey_NI OWNAPI(cpExpandAesKey_NI) IPP_OWN_DECL (void, cpExpandAesKey_NI, (const Ipp8u* pSecret, IppsAESSpec* pCtx)) #define cpAESEncryptXTS_AES_NI OWNAPI(cpAESEncryptXTS_AES_NI) IPP_OWN_DECL (void, cpAESEncryptXTS_AES_NI, (Ipp8u* outBlk, const Ipp8u* inpBlk, int nBlks, const Ipp8u* pRKey, int nr, Ipp8u* pTweak)) #define cpAESDecryptXTS_AES_NI OWNAPI(cpAESDecryptXTS_AES_NI) IPP_OWN_DECL (void, cpAESDecryptXTS_AES_NI, (Ipp8u* outBlk, const Ipp8u* inpBlk, int nBlks, const Ipp8u* pRKey, int nr, Ipp8u* pTweak)) #if (_IPP32E>=_IPP32E_K1) #define cpAESEncryptXTS_VAES OWNAPI(cpAESEncryptXTS_VAES) IPP_OWN_DECL (void, cpAESEncryptXTS_VAES, (Ipp8u* outBlk, const Ipp8u* inpBlk, int nBlks, const Ipp8u* pRKey, int nr, Ipp8u* pTweak)) #define cpAESDecryptXTS_VAES OWNAPI(cpAESDecryptXTS_VAES) IPP_OWN_DECL (void, cpAESDecryptXTS_VAES, (Ipp8u* outBlk, const Ipp8u* inpBlk, int nBlks, const Ipp8u* pRKey, int nr, Ipp8u* pTweak)) #define EncryptECB_RIJ128pipe_VAES_NI OWNAPI(EncryptECB_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, EncryptECB_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx)) #define EncryptCTR_RIJ128pipe_VAES_NI OWNAPI(EncryptCTR_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, EncryptCTR_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, Ipp8u* pCtrValue, const Ipp8u* pCtrBitMask)) #define EncryptStreamCTR32_VAES_NI OWNAPI(EncryptStreamCTR32_VAES_NI) IPP_OWN_DECL (void, EncryptStreamCTR32_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int nr, const Ipp8u* pKeys, int len, Ipp8u* pCtrValue)) #define DecryptECB_RIJ128pipe_VAES_NI OWNAPI(DecryptECB_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, DecryptECB_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx)) #define DecryptCBC_RIJ128pipe_VAES_NI OWNAPI(DecryptCBC_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, DecryptCBC_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) #define DecryptCFB_RIJ128pipe_VAES_NI OWNAPI(DecryptCFB_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, DecryptCFB_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsAESSpec* pCtx, const Ipp8u* pIV)) #define DecryptCFB64_RIJ128pipe_VAES_NI OWNAPI(DecryptCFB64_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, DecryptCFB64_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) #define DecryptCFB128_RIJ128pipe_VAES_NI OWNAPI(DecryptCFB128_RIJ128pipe_VAES_NI) IPP_OWN_DECL (void, DecryptCFB128_RIJ128pipe_VAES_NI, (const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsAESSpec* pCtx, const Ipp8u* pIV)) #endif /* _IPP32E>=_IPP32E_K1 */ #endif /* _IPP>=_IPP_P8 || _IPP32E>=_IPP32E_Y8 */ #define ExpandRijndaelKey OWNAPI(ExpandRijndaelKey) IPP_OWN_DECL (void, ExpandRijndaelKey, (const Ipp8u* pKey, int NK, int NB, int NR, int nKeys, Ipp8u* pEncKeys, Ipp8u* pDecKeys)) #if(_IPP>_IPP_PX || _IPP32E>_IPP32E_PX) #define Touch_SubsDword_8uT OWNAPI(Touch_SubsDword_8uT) IPP_OWN_DECL (Ipp32u, Touch_SubsDword_8uT, (Ipp32u inp, const Ipp8u* pTbl, int tblLen)) #endif #endif /* _PCP_RIJ_H */ cryptography-primitives-1.0.0/sources/ippcp/pcprij128safe.c000066400000000000000000000165071470420105600237670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Safe Rijndael Encrypt, Decrypt // (It's the special free from Sbox/tables implementation) // */ #include "owndefs.h" #include "owncp.h" #if ((_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8)) /* no pshufb instruction */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPOSITE_GF_) #include "pcprij128safe.h" #if defined _PCP_RIJ_SAFE_OLD /* // old version */ IPP_OWN_DEFN (Ipp8u, TransformByte, (Ipp8u x, const Ipp8u Transformation[])) { Ipp32u y = 0; Ipp32u testBit = 0x01; int bit; for(bit=0; bit<8; bit++) { Ipp32u mask = (x & testBit)? 0xFF : 0; y ^= Transformation[bit] & mask; testBit <<= 1; } return (Ipp8u)y; } static Ipp8u Native2CompositeTransformation[] = {0x01,0x2E,0x49,0x43,0x35,0xD0,0x3D,0xE9}; IPP_OWN_DEFN (void, TransformNative2Composite, (Ipp8u out[], const Ipp8u inp[])) { int n; for(n=0; n<16; n++) out[n] = TransformByte(inp[n], Native2CompositeTransformation); } static Ipp8u Composite2NativeTransformation[] = {0x01,0x5C,0xE0,0x50,0x1F,0xEE,0x55,0x6A}; IPP_OWN_DEFN (void, TransformComposite2Native, (Ipp8u out[], const Ipp8u inp[])) { int n; for(n=0; n<16; n++) out[n] = TransformByte(inp[n], Composite2NativeTransformation); } IPP_OWN_DEFN (void, AddRoundKey, (Ipp8u out[], const Ipp8u inp[], const Ipp8u pKey[])) { int n; for(n=0; n<16; n++) out[n] = (Ipp8u)( inp[n] ^ pKey[n] ); } #define MASK_BIT(x,n) ((Ipp32s)((x)<<(31-n)) >>31) #define GF16mulX(x) ( ((x)<<1) ^ ( MASK_BIT(x,3) & 0x13) ) static Ipp8u GF16mul(Ipp8u a, Ipp8u b) { Ipp32u a0 = a; Ipp32u a1 = GF16mulX(a0); Ipp32u a2 = GF16mulX(a1); Ipp32u a4 = GF16mulX(a2); Ipp32u r = (a0 & MASK_BIT(b,0)) ^(a1 & MASK_BIT(b,1)) ^(a2 & MASK_BIT(b,2)) ^(a4 & MASK_BIT(b,3)); return (Ipp8u)r; } static Ipp8u GF16_sqr[] = {0x00,0x01,0x04,0x05,0x03,0x02,0x07,0x06, 0x0C,0x0D,0x08,0x09,0x0F,0x0E,0x0B,0x0A}; static Ipp8u GF16_sqr1[]= {0x00,0x09,0x02,0x0B,0x08,0x01,0x0A,0x03, 0x06,0x0F,0x04,0x0D,0x0E,0x07,0x0C,0x05}; static Ipp8u GF16_inv[] = {0x00,0x01,0x09,0x0E,0x0D,0x0B,0x07,0x06, 0x0F,0x02,0x0C,0x05,0x0A,0x04,0x03,0x08}; IPP_OWN_DEFN (Ipp8u, InverseComposite, (Ipp8u x)) { /* split x = {bc} => b*t + c */ int b = (x>>4) & 0x0F; int c = x & 0x0F; int D = GF16mul((Ipp8u)b, (Ipp8u)c) ^GF16_sqr[c] ^GF16_sqr1[b]; D = GF16_inv[D]; c = GF16mul((Ipp8u)(b^c), (Ipp8u)D); b = GF16mul((Ipp8u)b, (Ipp8u)D); /* merge p*t + q => {pq} = x */ x = (Ipp8u)((b<<4) + c); return x; } #endif /* _PCP_RIJ_SAFE_OLD */ #if !defined _PCP_RIJ_SAFE_OLD /* // new version */ /* GF(2^128) -> GF((2^4)^2) isomorphous transformation matrix Ipp8u Native2CompositeTransformation[] = {0x01,0x2E,0x49,0x43,0x35,0xD0,0x3D,0xE9}; is defined in reference code, see doc for details */ static Ipp8u Native2CompositeTransformationLO[] = { /* defived from Native2CompositeTransformation[i], i=0,1,2,3 */ /* 0 */ 0x00, /* 1 */ 0x01, /* 2 */ 0x2E, /* 3 */ 0x2E^0x01, /* 4 */ 0x49, /* 5 */ 0x49^0x01, /* 6 */ 0x49^0x2E, /* 7 */ 0x49^0x2E^0x01, /* 8 */ 0x43, /* 9 */ 0x43^0x01, /* a */ 0x43^0x2E, /* b */ 0x43^0x2E^0x01, /* c */ 0x43^0x49, /* d */ 0x43^0x49^0x01, /* e */ 0x43^0x49^0x2E, /* f */ 0x43^0x49^0x2E^0x01 }; static Ipp8u Native2CompositeTransformationHI[] = { /* defived from Native2CompositeTransformation[i], i=4,5,6,7 */ /* 0 */ 0x00, /* 1 */ 0x35, /* 2 */ 0xD0, /* 3 */ 0xD0^0x35, /* 4 */ 0x3D, /* 5 */ 0x3D^0x35, /* 6 */ 0x3D^0xD0, /* 7 */ 0x3D^0xD0^0x35, /* 8 */ 0xE9, /* 9 */ 0xE9^0x35, /* a */ 0xE9^0xD0, /* b */ 0xE9^0xD0^0x35, /* c */ 0xE9^0x3D, /* d */ 0xE9^0x3D^0x35, /* e */ 0xE9^0x3D^0xD0, /* f */ 0xE9^0x3D^0xD0^0x35 }; IPP_OWN_DEFN (void, TransformNative2Composite, (Ipp8u out[16], const Ipp8u inp[16])) { Ipp8u blk_lo[16], blk_hi[16]; ((Ipp64u*)blk_lo)[0] = ((Ipp64u*)inp)[0] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_lo)[1] = ((Ipp64u*)inp)[1] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_hi)[0] = (((Ipp64u*)inp)[0]>>4) & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_hi)[1] = (((Ipp64u*)inp)[1]>>4) & 0x0F0F0F0F0F0F0F0F; { int n; for(n=0; n<16; n++) { Ipp8u lo = Native2CompositeTransformationLO[blk_lo[n]]; Ipp8u hi = Native2CompositeTransformationHI[blk_hi[n]]; out[n] = lo^hi; } } } /* GF((2^4)^2) -> GF(2^128) isomorphous transformation matrix Ipp8u Composite2NativeTransformation[] = {0x01,0x5C,0xE0,0x50,0x1F,0xEE,0x55,0x6A}; is defined in reference code, see doc for details */ static Ipp8u Composite2NativeTransformationLO[] = { /* defived from Composite2NativeTransformation[i], i=0,1,2,3 */ /* 0 */ 0x00, /* 1 */ 0x01, /* 2 */ 0x5C, /* 3 */ 0x5C^0x01, /* 4 */ 0xE0, /* 5 */ 0xE0^0x01, /* 6 */ 0xE0^0x5C, /* 7 */ 0xE0^0x5C^0x01, /* 8 */ 0x50, /* 9 */ 0x50^0x01, /* a */ 0x50^0x5C, /* b */ 0x50^0x5C^0x01, /* c */ 0x50^0xE0, /* d */ 0x50^0xE0^0x01, /* e */ 0x50^0xE0^0x5C, /* f */ 0x50^0xE0^0x5C^0x01 }; static Ipp8u Composite2NativeTransformationHI[] = {/* defived from Composite2NativeTransformation[i], i=4,5,6,7 */ /* 0 */ 0x00, /* 1 */ 0x1F, /* 2 */ 0xEE, /* 3 */ 0xEE^0x1F, /* 4 */ 0x55, /* 5 */ 0x55^0x1F, /* 6 */ 0x55^0xEE, /* 7 */ 0x55^0xEE^0x1F, /* 8 */ 0x6A, /* 9 */ 0x6A^0x1F, /* a */ 0x6A^0xEE, /* b */ 0x6A^0xEE^0x1F, /* c */ 0x6A^0x55, /* d */ 0x6A^0x55^0x1F, /* e */ 0x6A^0x55^0xEE, /* f */ 0x6A^0x55^0xEE^0x1F }; IPP_OWN_DEFN (void, TransformComposite2Native, (Ipp8u out[16], const Ipp8u inp[16])) { Ipp8u blk_lo[16], blk_hi[16]; ((Ipp64u*)blk_lo)[0] = ((Ipp64u*)inp)[0] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_lo)[1] = ((Ipp64u*)inp)[1] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_hi)[0] = (((Ipp64u*)inp)[0]>>4) & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_hi)[1] = (((Ipp64u*)inp)[1]>>4) & 0x0F0F0F0F0F0F0F0F; { int n; for(n=0; n<16; n++) { Ipp8u lo = Composite2NativeTransformationLO[blk_lo[n]]; Ipp8u hi = Composite2NativeTransformationHI[blk_hi[n]]; out[n] = lo^hi; } } } #endif /* !_PCP_RIJ_SAFE_OLD */ #endif /* _ALG_AES_SAFE_COMPOSITE_GF_ */ #endif /* (_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8) */ cryptography-primitives-1.0.0/sources/ippcp/pcprij128safe.h000066400000000000000000000060201470420105600237610ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2007 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Safe Rijndael Encrypt, Decrypt // // */ #if !defined(_PCP_RIJ_SAFE_H) #define _PCP_RIJ_SAFE_H #include "owncp.h" #include "pcprijtables.h" #include "pcpbnuimpl.h" #include "pcpmask_ct.h" #if defined _PCP_RIJ_SAFE_OLD /* old version */ #define TransformByte OWNAPI(TransformByte) IPP_OWN_DECL (Ipp8u, TransformByte, (Ipp8u x, const Ipp8u Transformation[])) #define TransformNative2Composite OWNAPI(TransformNative2Composite) IPP_OWN_DECL (void, TransformNative2Composite, (Ipp8u out[16], const Ipp8u inp[16])) #define TransformComposite2Native OWNAPI(TransformComposite2Native) IPP_OWN_DECL (void, TransformComposite2Native, (Ipp8u out[16], const Ipp8u inp[16])) #define InverseComposite OWNAPI(InverseComposite) IPP_OWN_DECL (Ipp8u, InverseComposite, (Ipp8u x)) #define AddRoundKey OWNAPI(AddRoundKey) IPP_OWN_DECL (void, AddRoundKey, (Ipp8u out[], const Ipp8u inp[], const Ipp8u pKey[])) #endif #if !defined _PCP_RIJ_SAFE_OLD /* new version */ #define TransformNative2Composite OWNAPI(TransformNative2Composite) IPP_OWN_DECL (void, TransformNative2Composite, (Ipp8u out[16], const Ipp8u inp[16])) #define TransformComposite2Native OWNAPI(TransformComposite2Native) IPP_OWN_DECL (void, TransformComposite2Native, (Ipp8u out[16], const Ipp8u inp[16])) /* add round key operation */ __IPPCP_INLINE void AddRoundKey(Ipp8u out[16], const Ipp8u inp[16], const Ipp8u rkey[16]) { ((Ipp64u*)out)[0] = ((Ipp64u*)inp)[0] ^ ((Ipp64u*)rkey)[0]; ((Ipp64u*)out)[1] = ((Ipp64u*)inp)[1] ^ ((Ipp64u*)rkey)[1]; } /* add logs of GF(2^4) elements // the exp table has been build matched for that implementation */ __IPPCP_INLINE Ipp8u AddLogGF16(Ipp8u loga, Ipp8u logb) { //Ipp8u s = loga+logb; //return (s>2*14)? 15 : (s>14)? s-15 : s; Ipp8u s = loga+logb; Ipp8u delta = ((0xF-1)-s)>>7; s -= delta; s |= 0-(s>>7); return s & (0xF); } #endif #define SELECTION_BITS ((sizeof(BNU_CHUNK_T)/sizeof(Ipp8u)) -1) __IPPCP_INLINE Ipp8u getSboxValue(Ipp8u x) { BNU_CHUNK_T selection = 0; const Ipp8u* SboxEntry = RijEncSbox; Ipp32u i; for (i = 0; i>7)); } __IPPCP_INLINE Ipp32u xtime4(Ipp32u x) { Ipp32u t = (x+x) &0xFEFEFEFE; t ^= mask4(x) & 0x1B1B1B1B; return t; } #endif /* _PCP_RIJ_SAFE2_H */ cryptography-primitives-1.0.0/sources/ippcp/pcprij128safedec2pxca.c000066400000000000000000000102611470420105600253700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Decrypt 128-bit data block according to Rijndael // (compact S-box based implementation) // // Contents: // Safe2Decrypt_RIJ128() // // */ #include "owncp.h" #if ((_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8)) /* no pshufb instruction */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) #include "pcprij128safe2.h" #include "pcprijtables.h" #include "pcpbnuimpl.h" #define SELECTION_BITS ((sizeof(BNU_CHUNK_T)/sizeof(Ipp8u)) -1) #if defined(__INTEL_COMPILER) __IPPCP_INLINE Ipp8u getInvSboxValue(Ipp8u x) { BNU_CHUNK_T selection = 0; const BNU_CHUNK_T* SboxEntry = (BNU_CHUNK_T*)RijDecSbox; BNU_CHUNK_T i_sel = x/sizeof(BNU_CHUNK_T); /* selection index */ BNU_CHUNK_T i; for(i=0; i>= (x & SELECTION_BITS)*8; return (Ipp8u)(selection & 0xFF); } #else #include "pcpmask_ct.h" __IPPCP_INLINE Ipp8u getInvSboxValue(Ipp8u x) { BNU_CHUNK_T selection = 0; const BNU_CHUNK_T* SboxEntry = (BNU_CHUNK_T*)RijDecSbox; Ipp32u _x = x/sizeof(BNU_CHUNK_T); Ipp32u i; for(i=0; i>= (x & SELECTION_BITS)*8; return (Ipp8u)(selection & 0xFF); } #endif __IPPCP_INLINE void invSubBytes(Ipp8u state[]) { int i; for(i=0;i<16;i++) state[i] = getInvSboxValue(state[i]); } __IPPCP_INLINE void invShiftRows(Ipp32u* state) { state[1] = ROR32(state[1], 24); state[2] = ROR32(state[2], 16); state[3] = ROR32(state[3], 8); } __IPPCP_INLINE void invMixColumns(Ipp32u* state) { Ipp32u y0 = state[1] ^ state[2] ^ state[3]; Ipp32u y1 = state[0] ^ state[2] ^ state[3]; Ipp32u y2 = state[0] ^ state[1] ^ state[3]; Ipp32u y3 = state[0] ^ state[1] ^ state[2]; Ipp32u t02, t13, t0123; state[0] = xtime4(state[0]); state[1] = xtime4(state[1]); state[2] = xtime4(state[2]); state[3] = xtime4(state[3]); y0 ^= state[0] ^ state[1]; y1 ^= state[1] ^ state[2]; y2 ^= state[2] ^ state[3]; y3 ^= state[3] ^ state[0]; t02 = state[0] ^ state[2]; t13 = state[1] ^ state[3]; t02 = xtime4(t02); t13 = xtime4(t13); t0123 = t02^t13; t0123 = xtime4(t0123); state[0] = y0 ^t02 ^t0123; state[1] = y1 ^t13 ^t0123; state[2] = y2 ^t02 ^t0123; state[3] = y3 ^t13 ^t0123; } IPP_OWN_DEFN (void, Safe2Decrypt_RIJ128, (const Ipp8u* in, Ipp8u* out, int Nr, const Ipp8u* RoundKey, const void* sbox)) { Ipp32u state[4]; int round=0; IPP_UNREFERENCED_PARAMETER(sbox); // copy input to the state array TRANSPOSE((Ipp8u*)state, in); // add the round key to the state before starting the rounds. XorRoundKey((Ipp32u*)state, (Ipp32u*)(RoundKey+Nr*16)); // there will be Nr rounds for(round=Nr-1;round>0;round--) { invShiftRows(state); invSubBytes((Ipp8u*)state); XorRoundKey(state,(Ipp32u*)(RoundKey+round*16)); invMixColumns(state); } // last round invShiftRows(state); invSubBytes((Ipp8u*)state); XorRoundKey(state,(Ipp32u*)(RoundKey+0*16)); // copy from the state to output TRANSPOSE(out, (Ipp8u*)state); } #endif /* _ALG_AES_SAFE_COMPACT_SBOX_ */ #endif /* (_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8) */ cryptography-primitives-1.0.0/sources/ippcp/pcprij128safedecpxca.c000066400000000000000000000300371470420105600253110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Decrypt 128-bit data block according to Rijndael // (It's the special free from Sbox/tables implementation) // // Contents: // SafeDecrypt_RIJ128() // // */ #include "owncp.h" #if ((_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8)) /* no pshufb instruction */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPOSITE_GF_) #include "pcprij.h" #include "pcprij128safe.h" #if defined _PCP_RIJ_SAFE_OLD /* // old version */ static Ipp8u AffineMatrix[] = {0x50,0x36,0x15,0x82,0x01,0x34,0x40,0x3E}; static void InvSubByte(Ipp8u inp_out[]) { Ipp8u AffineCnt = 0x48; int n; for(n=0; n<16; n++) { Ipp8u x = inp_out[n]; x = TransformByte(x, AffineMatrix); x^= AffineCnt; x = InverseComposite(x); inp_out[n] = x; } } static int ShiftRowsInx[] = {0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3}; static void InvShiftRows(Ipp8u inp_out[]) { Ipp8u tmp[16]; int n; for(n=0; n<16; n++) tmp[n] = inp_out[n]; for(n=0; n<16; n++) { int idx = ShiftRowsInx[n]; inp_out[n] = tmp[idx]; } } static Ipp8u GF16mul_4_2x[] = {0x00,0x24,0x48,0x6C,0x83,0xA7,0xCB,0xEF, 0x36,0x12,0x7E,0x5A,0xB5,0x91,0xFD,0xD9}; static Ipp8u GF16mul_1_6x[] = {0x00,0x61,0xC2,0xA3,0xB4,0xD5,0x76,0x17, 0x58,0x39,0x9A,0xFB,0xEC,0x8D,0x2E,0x4F}; static Ipp8u GF16mul_C_6x[] = {0x00,0x6C,0xCB,0xA7,0xB5,0xD9,0x7E,0x12, 0x5A,0x36,0x91,0xFD,0xEF,0x83,0x24,0x48}; static Ipp8u GF16mul_3_Ax[] = {0x00,0xA3,0x76,0xD5,0xEC,0x4F,0x9A,0x39, 0xFB,0x58,0x8D,0x2E,0x17,0xB4,0x61,0xC2}; static Ipp8u GF16mul_B_0x[] = {0x00,0x0B,0x05,0x0E,0x0A,0x01,0x0F,0x04, 0x07,0x0C,0x02,0x09,0x0D,0x06,0x08,0x03}; static Ipp8u GF16mul_0_Bx[] = {0x00,0xB0,0x50,0xE0,0xA0,0x10,0xF0,0x40, 0x70,0xC0,0x20,0x90,0xD0,0x60,0x80,0x30}; static Ipp8u GF16mul_2_4x[] = {0x00,0x42,0x84,0xC6,0x38,0x7A,0xBC,0xFE, 0x63,0x21,0xE7,0xA5,0x5B,0x19,0xDF,0x9D}; static Ipp8u GF16mul_2_6x[] = {0x00,0x62,0xC4,0xA6,0xB8,0xDA,0x7C,0x1E, 0x53,0x31,0x97,0xF5,0xEB,0x89,0x2F,0x4D}; static void InvMixColumn(Ipp8u inp_out[]) { Ipp8u out[16]; Ipp32u* pInp32 = (Ipp32u*)inp_out; int n; for(n=0; n<16; n++) { int xL = inp_out[n] & 0xF; int xH = (inp_out[n]>>4) & 0xF; out[n] = (Ipp8u)( GF16mul_4_2x[xL] ^ GF16mul_1_6x[xH] ); } pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); for(n=0; n<16; n++) { int xL = inp_out[n] & 0xF; int xH = (inp_out[n]>>4) & 0xF; out[n]^= (Ipp8u)( GF16mul_C_6x[xL] ^ GF16mul_3_Ax[xH] ); } pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); for(n=0; n<16; n++) { int xL = inp_out[n] & 0xF; int xH = (inp_out[n]>>4) & 0xF; out[n]^= (Ipp8u)( GF16mul_B_0x[xL] ^ GF16mul_0_Bx[xH] ); } pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); for(n=0; n<16; n++) { int xL = inp_out[n] & 0xF; int xH = (inp_out[n]>>4) & 0xF; out[n]^= (Ipp8u)( GF16mul_2_4x[xL] ^ GF16mul_2_6x[xH] ); } for(n=0; n<16; n++) inp_out[n] = out[n]; } /* define number of column in the state */ #define SC NB(128) #define STATE_SIZE (sizeof(Ipp32u)*SC) IPP_OWN_DEFN (void, SafeDecrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTables)) { int r; Ipp8u state[STATE_SIZE]; /* state */ IPP_UNREFERENCED_PARAMETER(pTables); /* native => composite */ TransformNative2Composite(state, pInpBlk); pKeys += nr*STATE_SIZE; /* input whitening */ AddRoundKey(state, state, pKeys); pKeys -= STATE_SIZE; /* regular (nr-1) rounds */ for(r=1; r native */ TransformComposite2Native(pOutBlk, state); } #endif /* _PCP_RIJ_SAFE_OLD */ #if !defined _PCP_RIJ_SAFE_OLD /* // new version */ /* // SubByte operation in composite GF((2^4)^2) // sdetails are in the doc. // // multiplication in basic GF(2^4) performs by log-and-exp sequence */ static Ipp8u GF16_sqr1[] = {0x00,0x09,0x02,0x0B,0x08,0x01,0x0A,0x03, /* (x^2)*{9} */ 0x06,0x0F,0x04,0x0D,0x0E,0x07,0x0C,0x05}; static Ipp8u GF16_log[] = {0xC0,0x00,0x01,0x04,0x02,0x08,0x05,0x0A, /* log element x */ 0x03,0x0E,0x09,0x07,0x06,0x0D,0x0B,0x0C}; static Ipp8u GF16_invlog[] = {0xC0,0x00,0x0E,0x0B,0x0D,0x07,0x0A,0x05, /* log of multiple inversion element x^-1 */ 0x0C,0x01,0x06,0x08,0x09,0x02,0x04,0x03}; static Ipp8u GF16_exp[] = {0x01,0x02,0x04,0x08,0x03,0x06,0x0C,0x0B, 0x05,0x0A,0x07,0x0E,0x0F,0x0D,0x09,0x00}; /* exp[15]= 0!!! */ /* affine transformation matrix Ipp8u AffineMatrix[] = {0x50,0x36,0x15,0x82,0x01,0x34,0x40,0x3E}; is defined in reference code, see doc for details */ static Ipp8u InvAffineMatrixLO[] = { /* defived from AffineMatrix[i], i=0,1,2,3 */ /* 0 */ 0x00, /* 1 */ 0x50, /* 2 */ 0x36, /* 3 */ 0x36^0x50, /* 4 */ 0x15, /* 5 */ 0x15^0x50, /* 6 */ 0x15^0x36, /* 7 */ 0x15^0x36^0x50, /* 8 */ 0x82, /* 9 */ 0x82^0x50, /* a */ 0x82^0x36, /* b */ 0x82^0x36^0x50, /* c */ 0x82^0x15, /* d */ 0x82^0x15^0x50, /* e */ 0x82^0x15^0x36, /* f */ 0x82^0x15^0x36^0x50 }; static Ipp8u InvAffineMatrixHI[] = { /* defived from AffineMatrix[i], i=4,5,6,7 */ /* 0 */ 0x00, /* 1 */ 0x01, /* 2 */ 0x34, /* 3 */ 0x34^0x01, /* 4 */ 0x40, /* 5 */ 0x40^0x01, /* 6 */ 0x40^0x34, /* 7 */ 0x40^0x34^0x01, /* 8 */ 0x3E, /* 9 */ 0x3E^0x01, /* a */ 0x3E^0x34, /* b */ 0x3E^0x34^0x01, /* c */ 0x3E^0x40, /* d */ 0x3E^0x40^0x01, /* e */ 0x3E^0x40^0x34, /* f */ 0x3E^0x40^0x34^0x01 }; static void InvSubByte(Ipp8u blk[16]) { Ipp8u blk_c[16], blk_b[16]; ((Ipp64u*)blk_c)[0] = ((Ipp64u*)blk)[0] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_c)[1] = ((Ipp64u*)blk)[1] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_b)[0] = (((Ipp64u*)blk)[0]>>4) & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_b)[1] = (((Ipp64u*)blk)[1]>>4) & 0x0F0F0F0F0F0F0F0F; { const Ipp8u affineCnt = 0x48; /* /* value of H(0x05) */ int n; for(n=0; n<16; n++) { Ipp8u c = blk_c[n]; Ipp8u b = blk_b[n]; /* affine transformation y = (AT)*(x) + affineCnt */ Ipp8u t = InvAffineMatrixLO[c] ^ InvAffineMatrixHI[b] ^ affineCnt; c = t & 0xF; b = t >> 4; /* {c+b*t} element inversion => {c+b*t} */ { Ipp8u log_c = GF16_log[c]; Ipp8u log_b = GF16_log[b]; Ipp8u log_cb = GF16_log[c^b]; Ipp8u d = GF16_sqr1[b]; Ipp8u t = AddLogGF16(log_c, log_cb); d ^= GF16_exp[t]; d = GF16_invlog[d]; c = AddLogGF16(log_cb, d); b = AddLogGF16(log_b, d); c = GF16_exp[c]; b = GF16_exp[b]; } blk[n] = b<<4 | c; } } } /* inplace ShiftRows operation */ /* int ShiftRowsInx[] = {0,13,10,7, 4,1,14,11, 8,5,2,15, 12,9,6,3}; */ static void InvShiftRows(Ipp8u blk[16]) { Ipp8u x = blk[13]; blk[13]= blk[9]; blk[9] = blk[5]; blk[5] = blk[1]; blk[1] = x; x = blk[10]; blk[10]= blk[2]; blk[2] = x; x = blk[14]; blk[14]= blk[6]; blk[6] = x; x = blk[3]; blk[3] = blk[7]; blk[7] = blk[11]; blk[11]= blk[15]; blk[15]= x; } static Ipp8u GF16mul_4_2x[] = {0x00,0x24,0x48,0x6C,0x83,0xA7,0xCB,0xEF, 0x36,0x12,0x7E,0x5A,0xB5,0x91,0xFD,0xD9}; static Ipp8u GF16mul_1_6x[] = {0x00,0x61,0xC2,0xA3,0xB4,0xD5,0x76,0x17, 0x58,0x39,0x9A,0xFB,0xEC,0x8D,0x2E,0x4F}; static Ipp8u GF16mul_C_6x[] = {0x00,0x6C,0xCB,0xA7,0xB5,0xD9,0x7E,0x12, 0x5A,0x36,0x91,0xFD,0xEF,0x83,0x24,0x48}; static Ipp8u GF16mul_3_Ax[] = {0x00,0xA3,0x76,0xD5,0xEC,0x4F,0x9A,0x39, 0xFB,0x58,0x8D,0x2E,0x17,0xB4,0x61,0xC2}; static Ipp8u GF16mul_B_0x[] = {0x00,0x0B,0x05,0x0E,0x0A,0x01,0x0F,0x04, 0x07,0x0C,0x02,0x09,0x0D,0x06,0x08,0x03}; static Ipp8u GF16mul_0_Bx[] = {0x00,0xB0,0x50,0xE0,0xA0,0x10,0xF0,0x40, 0x70,0xC0,0x20,0x90,0xD0,0x60,0x80,0x30}; static Ipp8u GF16mul_2_4x[] = {0x00,0x42,0x84,0xC6,0x38,0x7A,0xBC,0xFE, 0x63,0x21,0xE7,0xA5,0x5B,0x19,0xDF,0x9D}; static Ipp8u GF16mul_2_6x[] = {0x00,0x62,0xC4,0xA6,0xB8,0xDA,0x7C,0x1E, 0x53,0x31,0x97,0xF5,0xEB,0x89,0x2F,0x4D}; static void InvMixColumn(Ipp8u blk[16]) { Ipp8u out[16]; Ipp32u* pInp32 = (Ipp32u*)blk; int n; for(n=0; n<16; n++) { int xL = blk[n] & 0xF; int xH = (blk[n]>>4) & 0xF; out[n] = GF16mul_4_2x[xL] ^ GF16mul_1_6x[xH]; } pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); for(n=0; n<16; n++) { int xL = blk[n] & 0xF; int xH = (blk[n]>>4) & 0xF; out[n]^= GF16mul_C_6x[xL] ^ GF16mul_3_Ax[xH]; } pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); for(n=0; n<16; n++) { int xL = blk[n] & 0xF; int xH = (blk[n]>>4) & 0xF; out[n]^= GF16mul_B_0x[xL] ^ GF16mul_0_Bx[xH]; } pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); for(n=0; n<16; n++) { int xL = blk[n] & 0xF; int xH = (blk[n]>>4) & 0xF; blk[n] = out[n] ^ GF16mul_2_4x[xL] ^ GF16mul_2_6x[xH]; } } /* define number of column in the state */ #define SC NB(128) #define STATE_SIZE (sizeof(Ipp32u)*SC) IPP_OWN_DEFN (void, SafeDecrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTables)) { int r; Ipp8u state[STATE_SIZE]; /* state */ IPP_UNREFERENCED_PARAMETER(pTables); /* native => composite */ TransformNative2Composite(state, pInpBlk); pKeys += nr*STATE_SIZE; /* input whitening */ AddRoundKey(state, state, pKeys); pKeys -= STATE_SIZE; /* regular (nr-1) rounds */ for(r=1; r native */ TransformComposite2Native(pOutBlk, state); } #endif /* !_PCP_RIJ_SAFE_OLD */ #endif /* _ALG_AES_SAFE_COMPOSITE_GF_ */ #endif /* (_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8) */ cryptography-primitives-1.0.0/sources/ippcp/pcprij128safeenc2pxca.c000066400000000000000000000056301470420105600254060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt 128-bit data block according to Rijndael // (compact S-box based implementation) // // Contents: // Safe2Encrypt_RIJ128() // // */ #include "owncp.h" #if ((_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8)) /* no pshufb instruction */ #if (_ALG_AES_SAFE_==_ALG_AES_SAFE_COMPACT_SBOX_) #include "pcprij128safe.h" #include "pcprij128safe2.h" #include "pcprijtables.h" __IPPCP_INLINE void SubBytes(Ipp8u state[]) { int i; for(i=0;i<16;i++) { state[i] = getSboxValue(state[i]); } } __IPPCP_INLINE void ShiftRows(Ipp32u* state) { state[1] = ROR32(state[1], 8); state[2] = ROR32(state[2], 16); state[3] = ROR32(state[3], 24); } // MixColumns4 function mixes the columns of the state matrix __IPPCP_INLINE void MixColumns(Ipp32u* state) { Ipp32u y0 = state[1] ^ state[2] ^ state[3]; Ipp32u y1 = state[0] ^ state[2] ^ state[3]; Ipp32u y2 = state[0] ^ state[1] ^ state[3]; Ipp32u y3 = state[0] ^ state[1] ^ state[2]; state[0] = xtime4(state[0]); state[1] = xtime4(state[1]); state[2] = xtime4(state[2]); state[3] = xtime4(state[3]); y0 ^= state[0] ^ state[1]; y1 ^= state[1] ^ state[2]; y2 ^= state[2] ^ state[3]; y3 ^= state[3] ^ state[0]; state[0] = y0; state[1] = y1; state[2] = y2; state[3] = y3; } IPP_OWN_DEFN (void, Safe2Encrypt_RIJ128, (const Ipp8u* in, Ipp8u* out, int Nr, const Ipp8u* RoundKey, const void* sbox)) { Ipp32u state[4]; int round=0; IPP_UNREFERENCED_PARAMETER(sbox); // copy input to the state array TRANSPOSE((Ipp8u*)state, in); // add round key to the state before starting the rounds. XorRoundKey(state, (Ipp32u*)(RoundKey+0*16)); // there will be Nr rounds for(round=1;round>4) & 0xF ); tmp[n] = (Ipp8u)( GF16mul_E_2x[xL] ^ GF16mul_1_Cx[xH] ); } pTmp32[0] ^= ROR32(pTmp32[0], 8); pTmp32[1] ^= ROR32(pTmp32[1], 8); pTmp32[2] ^= ROR32(pTmp32[2], 8); pTmp32[3] ^= ROR32(pTmp32[3], 8); pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); pTmp32[0] ^= pInp32[0]; pTmp32[1] ^= pInp32[1]; pTmp32[2] ^= pInp32[2]; pTmp32[3] ^= pInp32[3]; pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); pTmp32[0] ^= pInp32[0]; pTmp32[1] ^= pInp32[1]; pTmp32[2] ^= pInp32[2]; pTmp32[3] ^= pInp32[3]; pInp32[0] = ROR32(pInp32[0], 8); pInp32[1] = ROR32(pInp32[1], 8); pInp32[2] = ROR32(pInp32[2], 8); pInp32[3] = ROR32(pInp32[3], 8); pInp32[0]^= pTmp32[0]; pInp32[1]^= pTmp32[1]; pInp32[2]^= pTmp32[2]; pInp32[3]^= pTmp32[3]; } /* define number of column in the state */ #define SC NB(128) #define STATE_SIZE (sizeof(Ipp32u)*SC) IPP_OWN_DEFN (void, SafeEncrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTables)) { int r; Ipp8u state[STATE_SIZE]; /* state */ IPP_UNREFERENCED_PARAMETER(pTables); /* native => composite */ TransformNative2Composite(state, pInpBlk); /* input whitening */ AddRoundKey(state, state, pKeys); pKeys += STATE_SIZE; /* regular (nr-1) rounds */ for(r=1; r native */ TransformComposite2Native(pOutBlk, state); } #endif /* _PCP_RIJ_SAFE_OLD */ #if !defined _PCP_RIJ_SAFE_OLD /* // new version */ /* // SubByte operation in composite GF((2^4)^2) // sdetails are in the doc. // // multiplication in basic GF(2^4) performs by log-and-exp sequence */ static Ipp8u GF16_sqr1[] = {0x00,0x09,0x02,0x0B,0x08,0x01,0x0A,0x03, /* (x^2)*{9} */ 0x06,0x0F,0x04,0x0D,0x0E,0x07,0x0C,0x05}; static Ipp8u GF16_log[] = {0xC0,0x00,0x01,0x04,0x02,0x08,0x05,0x0A, /* log element x */ 0x03,0x0E,0x09,0x07,0x06,0x0D,0x0B,0x0C}; static Ipp8u GF16_invlog[] = {0xC0,0x00,0x0E,0x0B,0x0D,0x07,0x0A,0x05, /* log of multiple inversion element x^-1 */ 0x0C,0x01,0x06,0x08,0x09,0x02,0x04,0x03}; static Ipp8u GF16_exp[] = {0x01,0x02,0x04,0x08,0x03,0x06,0x0C,0x0B, 0x05,0x0A,0x07,0x0E,0x0F,0x0D,0x09,0x00}; /* exp[15]= 0!!! */ /* affine transformation matrix Ipp8u AffineMatrix[] = {0x10,0x22,0x55,0x82,0x41,0x34,0x40,0x2A}; is defined in reference code, see doc for details */ static Ipp8u FwdAffineMatrixLO[] = { /* defived from AffineMatrix[i], i=0,1,2,3 */ /* 0 */ 0x00, /* 1 */ 0x10, /* 2 */ 0x22, /* 3 */ 0x22^0x10, /* 4 */ 0x55, /* 5 */ 0x55^0x10, /* 6 */ 0x55^0x22, /* 7 */ 0x55^0x22^0x10, /* 8 */ 0x82, /* 9 */ 0x82^0x10, /* a */ 0x82^0x22, /* b */ 0x82^0x22^0x10, /* c */ 0x82^0x55, /* d */ 0x82^0x55^0x10, /* e */ 0x82^0x55^0x22, /* f */ 0x82^0x55^0x22^0x10 }; static Ipp8u FwdAffineMatrixHI[] = { /* defived from AffineMatrix[i], i=4,5,6,7 */ /* 0 */ 0x00, /* 1 */ 0x41, /* 2 */ 0x34, /* 3 */ 0x34^0x41, /* 4 */ 0x40, /* 5 */ 0x40^0x41, /* 6 */ 0x40^0x34, /* 7 */ 0x40^0x34^0x41, /* 8 */ 0x2A, /* 9 */ 0x2A^0x41, /* a */ 0x2A^0x34, /* b */ 0x2A^0x34^0x41, /* c */ 0x2A^0x40, /* d */ 0x2A^0x40^0x41, /* e */ 0x2A^0x40^0x34, /* f */ 0x2A^0x40^0x34^0x41 }; /* inplace SubByte */ static void FwdSubByte(Ipp8u blk[16]) { Ipp8u blk_c[16], blk_b[16]; ((Ipp64u*)blk_c)[0] = ((Ipp64u*)blk)[0] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_c)[1] = ((Ipp64u*)blk)[1] & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_b)[0] = (((Ipp64u*)blk)[0]>>4) & 0x0F0F0F0F0F0F0F0F; ((Ipp64u*)blk_b)[1] = (((Ipp64u*)blk)[1]>>4) & 0x0F0F0F0F0F0F0F0F; { const Ipp8u affineCnt = 0xc2; /* value of H(0x63) */ int n; for(n=0; n<16; n++) { Ipp8u c = blk_c[n]; Ipp8u b = blk_b[n]; /* {c+b*t} element inversion => {c+b*t} */ Ipp8u log_c = GF16_log[c]; Ipp8u log_b = GF16_log[b]; Ipp8u log_cb = GF16_log[c^b]; Ipp8u d = GF16_sqr1[b]; Ipp8u t = AddLogGF16(log_c, log_cb); d ^= GF16_exp[t]; d = GF16_invlog[d]; c = AddLogGF16(log_cb, d); b = AddLogGF16(log_b, d); c = GF16_exp[c]; b = GF16_exp[b]; /* affine transformation y = (AT)*(x^-1) + affineCnt */ c = FwdAffineMatrixLO[c]; b = FwdAffineMatrixHI[b]; blk[n] = (c^b) ^affineCnt; } } } /* inplace ShifttRows operation */ /* int ShiftRowsInx[] = {0,5,10,15, 4,9,14,3, 8,13,2,7, 12,1,6,11}; */ __IPPCP_INLINE void FwdShiftRows(Ipp8u blk[16]) { Ipp8u x = blk[1]; blk[1] = blk[5]; blk[5] = blk[9]; blk[9] = blk[13]; blk[13]= x; x = blk[2]; blk[2] = blk[10]; blk[10]= x; x = blk[6]; blk[6] = blk[14]; blk[14]= x; x = blk[15]; blk[15] = blk[11]; blk[11] = blk[7]; blk[7] = blk[3]; blk[3] = x; } /* inplace Mixcolumns operation */ static Ipp8u GF16mul_E_2x[] = {0x00,0x2E,0x4F,0x61,0x8D,0xA3,0xC2,0xEC, 0x39,0x17,0x76,0x58,0xB4,0x9A,0xFB,0xD5}; static Ipp8u GF16mul_1_Cx[] = {0x00,0xC1,0xB2,0x73,0x54,0x95,0xE6,0x27, 0xA8,0x69,0x1A,0xDB,0xFC,0x3D,0x4E,0x8F}; static void FwdMixColumn(Ipp8u blk[16]) { Ipp8u tmp[16]; Ipp32u* pTmp32 = (Ipp32u*)tmp; Ipp32u* pBlk32 = (Ipp32u*)blk; int n; for(n=0; n<16; n++) { Ipp8u xL = blk[n] & 0xF; Ipp8u xH =(blk[n]>>4) & 0xF; tmp[n] = GF16mul_E_2x[xL] ^ GF16mul_1_Cx[xH]; } pTmp32[0] ^= ROR32(pTmp32[0], 8); pTmp32[1] ^= ROR32(pTmp32[1], 8); pTmp32[2] ^= ROR32(pTmp32[2], 8); pTmp32[3] ^= ROR32(pTmp32[3], 8); pBlk32[0] = ROR32(pBlk32[0], 8); pBlk32[1] = ROR32(pBlk32[1], 8); pBlk32[2] = ROR32(pBlk32[2], 8); pBlk32[3] = ROR32(pBlk32[3], 8); pTmp32[0] ^= pBlk32[0]; pTmp32[1] ^= pBlk32[1]; pTmp32[2] ^= pBlk32[2]; pTmp32[3] ^= pBlk32[3]; pBlk32[0] = ROR32(pBlk32[0], 8); pBlk32[1] = ROR32(pBlk32[1], 8); pBlk32[2] = ROR32(pBlk32[2], 8); pBlk32[3] = ROR32(pBlk32[3], 8); pTmp32[0] ^= pBlk32[0]; pTmp32[1] ^= pBlk32[1]; pTmp32[2] ^= pBlk32[2]; pTmp32[3] ^= pBlk32[3]; pBlk32[0] = ROR32(pBlk32[0], 8); pBlk32[1] = ROR32(pBlk32[1], 8); pBlk32[2] = ROR32(pBlk32[2], 8); pBlk32[3] = ROR32(pBlk32[3], 8); pBlk32[0]^= pTmp32[0]; pBlk32[1]^= pTmp32[1]; pBlk32[2]^= pTmp32[2]; pBlk32[3]^= pTmp32[3]; } /* define number of column in the state */ #define SC NB(128) #define STATE_SIZE (sizeof(Ipp32u)*SC) IPP_OWN_DEFN (void, SafeEncrypt_RIJ128, (const Ipp8u* pInpBlk, Ipp8u* pOutBlk, int nr, const Ipp8u* pKeys, const void* pTables)) { int r; Ipp8u state[STATE_SIZE]; /* local state */ IPP_UNREFERENCED_PARAMETER(pTables); /* native => composite */ TransformNative2Composite(state, pInpBlk); /* input whitening */ AddRoundKey(state, state, pKeys); pKeys += STATE_SIZE; /* regular (nr-1) rounds */ for(r=1; r native */ TransformComposite2Native(pOutBlk, state); } #endif /* !_PCP_RIJ_SAFE_OLD */ #endif /* _ALG_AES_SAFE_COMPOSITE_GF_ */ #endif /* (_IPP <_IPP_V8) && (_IPP32E <_IPP32E_U8) */ cryptography-primitives-1.0.0/sources/ippcp/pcprijdecsboxca.c000066400000000000000000000022111470420105600245340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt tables for Rijndael // // Contents: // RijDecSbox[256] // // */ #include "owndefs.h" #include "owncp.h" #include "pcprijtables.h" /* // Reference to pcrijencryptpxca.c // for details */ /* // Pure Decryption S-boxes */ #if defined( _IPP_DATA ) const __ALIGN64 Ipp8u RijDecSbox[256] = { DEC_SBOX(none_t) }; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/pcprijencsboxca.c000066400000000000000000000022111470420105600245460ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt tables for Rijndael // // Contents: // RijEncSbox[256] // // */ #include "owndefs.h" #include "owncp.h" #include "pcprijtables.h" /* // Reference to pcrijencryptpxca.c // for details */ /* // Pure Encryprion S-boxes */ #if defined( _IPP_DATA ) const __ALIGN64 Ipp8u RijEncSbox[256] = { ENC_SBOX(none_t) }; #endif /* _IPP_DATA */ cryptography-primitives-1.0.0/sources/ippcp/pcprijkeysca.c000066400000000000000000000225121470420105600240660ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Initialization of Rijndael // // Contents: // EncRijndaelKeys() // DecRijndaelKeys() // // */ #include "owndefs.h" #include "owncp.h" #include "pcprij.h" #include "pcprijtables.h" #include "pcptool.h" #include "pcprij128safe.h" #include "pcprij128safe2.h" /* // Pseudo Code for Key Expansion // was shown in Sec 5.2 of FIPS-197 // // KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk) // begin // word temp // // i = 0 // // while (i < Nk) // w[i] = word(key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]) // i = i+1 // end while // // i = Nk // // while (i < Nb * (Nr+1)] // temp = w[i-1] // if (i mod Nk = 0) // temp = SubWord(RotWord(temp)) xor Rcon[i/Nk] // else if (Nk > 6 and i mod Nk = 4) // temp = SubWord(temp) // end if // w[i] = w[i-Nk] xor temp // i = i + 1 // end while // end // // Note: // I see nothing any reason for optimizing reference code above // because it run once for each encryption/decryption procedure. // // // We are going to use so called Equivalent Inverse Cipher. // Look the reason are in pcaesdecryptpxca.c. // // For the Equivalent Inverse Cipher, the following pseudo code is added at // the end of the Key Expansion routine (Sec. 5.2): // // for i = 0 step 1 to (Nr+1)*Nb-1 // dw[i] = w[i] // end for // // for round = 1 step 1 to Nr-1 // InvMixColumns(dw[round*Nb, (round+1)*Nb-1]) // note change of type // end for // // Note that, since InvMixColumns operates on a two-dimensional array of bytes // while the Round Keys are held in an array of words, the call to // InvMixColumns in this code sequence involves a change of type (i.e. the // input to InvMixColumns() is normally the State array, which is considered // to be a two-dimensional array of bytes, whereas the input here is a Round // Key computed as a one-dimensional array of words). // // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Brief Consideration of InvMixColumn() // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Let words U and V are input and output of InvMixColumn() operation. // Let U(0), U(1), U(2) and U(3) are bytes of word U. // And V(0), V(1), V(2) and V(3) are bytes of word V. // // According to sec 5.3.3. of FIPS-197 // V(0) = {E}U(0) xor {B}U(1) xor {D}U(2) xor {9}U(3) // V(1) = {9}U(0) xor {E}U(1) xor {B}U(2) xor {D}U(3) // V(2) = {D}U(0) xor {9}U(1) xor {E}U(2) xor {B}U(3) // V(3) = {B}U(0) xor {D}U(1) xor {9}U(2) xor {E}U(3) // where {hex}U(n) means GF(256) multiplication // // Or // V = word( {E}U(0), {9}U(0), {D}U(0), {B}U(0) ) xor // word( {B}U(1), {E}U(1), {9}U(1), {D}U(1) ) xor // word( {D}U(2), {B}U(2), {E}U(2), {9}U(2) ) xor // word( {9}U(3), {D}U(3), {B}U(3), {E}U(3) ) // // Word values // word( {E}x, {9}x, {D}x, {B}x ) // word( {B}y, {E}y, {9}y, {D}y ) // word( {D}z, {B}z, {E}z, {9}z ) // word( {9}t, {D}t, {B}t, {E}t ) // are precomputed tables (for x,y,z,t = 0x00, ... 0xff) // // Tables InvMixCol_Tbl[4] are contents exactly as we want // and macro InvMixColumn() provide necassary operation. */ /* // RconTbl[] contains [x**(i),{00},{00},{00}], i=0,..,10 GF(256) // // Note: // Reference sec 4.2 of FIPS-197 for calculation */ static const Ipp32u RconTbl[] = { BYTE0_TO_WORD(0x01), BYTE0_TO_WORD(0x02), BYTE0_TO_WORD(0x04), BYTE0_TO_WORD(0x08), BYTE0_TO_WORD(0x10), BYTE0_TO_WORD(0x20), BYTE0_TO_WORD(0x40), BYTE0_TO_WORD(0x80), BYTE0_TO_WORD(0x1B), BYTE0_TO_WORD(0x36), BYTE0_TO_WORD(0x6C), BYTE0_TO_WORD(0xD8), BYTE0_TO_WORD(0xAB), BYTE0_TO_WORD(0x4D), BYTE0_TO_WORD(0x9A), BYTE0_TO_WORD(0x2F), BYTE0_TO_WORD(0x5E), BYTE0_TO_WORD(0xBC), BYTE0_TO_WORD(0x63), BYTE0_TO_WORD(0xC6), BYTE0_TO_WORD(0x97), BYTE0_TO_WORD(0x35), BYTE0_TO_WORD(0x6A), BYTE0_TO_WORD(0xD4), BYTE0_TO_WORD(0xB3), BYTE0_TO_WORD(0x7D), BYTE0_TO_WORD(0xFA), BYTE0_TO_WORD(0xEF), BYTE0_TO_WORD(0xC5) }; /// commented due to mitigation // ///* precomputed table for InvMixColumn() operation */ //static const Ipp32u InvMixCol_Tbl[4][256] = { // { LINE(inv_t0) }, // { LINE(inv_t1) }, // { LINE(inv_t2) }, // { LINE(inv_t3) } //}; // //#define InvMixColumn(x, tbl) \ // ( (tbl)[0][ EBYTE((x),0) ] \ // ^(tbl)[1][ EBYTE((x),1) ] \ // ^(tbl)[2][ EBYTE((x),2) ] \ // ^(tbl)[3][ EBYTE((x),3) ] ) __IPPCP_INLINE Ipp32u InvMixColumn(Ipp32u x) { Ipp32u x_mul_2 = xtime4(x); Ipp32u x_mul_4 = xtime4(x_mul_2); Ipp32u x_mul_8 = xtime4(x_mul_4); Ipp32u x_mul_9 = x_mul_8 ^ x; Ipp32u x_mul_B = x_mul_8 ^ x_mul_2 ^ x; Ipp32u x_mul_D = x_mul_8 ^ x_mul_4 ^ x; Ipp32u x_mul_E = x_mul_8 ^ x_mul_4 ^ x_mul_2; x = x_mul_E ^ ROR32(x_mul_B, 8) ^ ROR32(x_mul_D, 16) ^ ROR32(x_mul_9, 24); return x; } /* // Expansion of key for Rijndael's Encryption */ IPP_OWN_DEFN (void, ExpandRijndaelKey, (const Ipp8u* pKey, int NK, int NB, int NR, int nKeys, Ipp8u* pEncKeys, Ipp8u* pDecKeys)) { Ipp32u* enc_keys = (Ipp32u*)pEncKeys; Ipp32u* dec_keys = (Ipp32u*)pDecKeys; /* convert security key to WORD and save into the enc_key array */ int n; for(n=0; n=_IPP_W7) || (_IPP32E==_IPP32E_M7)) _mm_lfence(); /* lfence added because of potential exploit of speculative execution (KW); lfence accessible on SSE2 and above */ #endif dec_keys[n] = InvMixColumn(dec_keys[n]); } } cryptography-primitives-1.0.0/sources/ippcp/pcprijtables.h000066400000000000000000000244211470420105600240670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Rijndael Tables Declarations // // */ #if !defined(_PCP_RIJTBLES_H) #define _PCP_RIJTBLES_H #include "owndefs.h" #include "owncp.h" #include "pcprij.h" /* // GF(256) multiplication operations */ #define gf_m2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) #define gf_m4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) #define gf_m8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ ^ (((x>>5) & 4) * WPOLY)) #define gf_m1(x) ((x)) #define gf_m3(x) (gf_m2(x) ^ x) #define gf_m9(x) (gf_m8(x) ^ x) #define gf_mB(x) (gf_m8(x) ^ gf_m2(x) ^ x) #define gf_mD(x) (gf_m8(x) ^ gf_m4(x) ^ x) #define gf_mE(x) (gf_m8(x) ^ gf_m4(x) ^ gf_m2(x)) /* // The following particular transformations // are used for create Encryption Tables */ #define fwd_t0(x) BYTES_TO_WORD(gf_m2(x), gf_m1(x), gf_m1(x), gf_m3(x)) #define fwd_t1(x) BYTES_TO_WORD(gf_m3(x), gf_m2(x), gf_m1(x), gf_m1(x)) #define fwd_t2(x) BYTES_TO_WORD(gf_m1(x), gf_m3(x), gf_m2(x), gf_m1(x)) #define fwd_t3(x) BYTES_TO_WORD(gf_m1(x), gf_m1(x), gf_m3(x), gf_m2(x)) /* // The following particular transformations // are used for create Decryption Tables */ #define inv_t0(x) BYTES_TO_WORD(gf_mE(x), gf_m9(x), gf_mD(x), gf_mB(x)) #define inv_t1(x) BYTES_TO_WORD(gf_mB(x), gf_mE(x), gf_m9(x), gf_mD(x)) #define inv_t2(x) BYTES_TO_WORD(gf_mD(x), gf_mB(x), gf_mE(x), gf_m9(x)) #define inv_t3(x) BYTES_TO_WORD(gf_m9(x), gf_mD(x), gf_mB(x), gf_mE(x)) #define exp_b3(x) BYTES_TO_WORD(0, 0, 0, (x)) #define exp_b2(x) BYTES_TO_WORD(0, 0, (x),0) #define exp_b1(x) BYTES_TO_WORD(0, (x),0, 0) #define exp_b0(x) BYTES_TO_WORD((x),0, 0, 0) /* // The following particular transformations // are used for create pure Encryption/Decryption Sboxes */ #define none_t(x) (x) /* // Just sequence of byte, beginning 0x00 up to 0xff // (be parametrized by any transformation 't') */ #define LINE(t) \ t(0x00), t(0x01), t(0x02), t(0x03), t(0x04), t(0x05), t(0x06), t(0x07),\ t(0x08), t(0x09), t(0x0a), t(0x0b), t(0x0c), t(0x0d), t(0x0e), t(0x0f),\ t(0x10), t(0x11), t(0x12), t(0x13), t(0x14), t(0x15), t(0x16), t(0x17),\ t(0x18), t(0x19), t(0x1a), t(0x1b), t(0x1c), t(0x1d), t(0x1e), t(0x1f),\ t(0x20), t(0x21), t(0x22), t(0x23), t(0x24), t(0x25), t(0x26), t(0x27),\ t(0x28), t(0x29), t(0x2a), t(0x2b), t(0x2c), t(0x2d), t(0x2e), t(0x2f),\ t(0x30), t(0x31), t(0x32), t(0x33), t(0x34), t(0x35), t(0x36), t(0x37),\ t(0x38), t(0x39), t(0x3a), t(0x3b), t(0x3c), t(0x3d), t(0x3e), t(0x3f),\ t(0x40), t(0x41), t(0x42), t(0x43), t(0x44), t(0x45), t(0x46), t(0x47),\ t(0x48), t(0x49), t(0x4a), t(0x4b), t(0x4c), t(0x4d), t(0x4e), t(0x4f),\ t(0x50), t(0x51), t(0x52), t(0x53), t(0x54), t(0x55), t(0x56), t(0x57),\ t(0x58), t(0x59), t(0x5a), t(0x5b), t(0x5c), t(0x5d), t(0x5e), t(0x5f),\ t(0x60), t(0x61), t(0x62), t(0x63), t(0x64), t(0x65), t(0x66), t(0x67),\ t(0x68), t(0x69), t(0x6a), t(0x6b), t(0x6c), t(0x6d), t(0x6e), t(0x6f),\ t(0x70), t(0x71), t(0x72), t(0x73), t(0x74), t(0x75), t(0x76), t(0x77),\ t(0x78), t(0x79), t(0x7a), t(0x7b), t(0x7c), t(0x7d), t(0x7e), t(0x7f),\ t(0x80), t(0x81), t(0x82), t(0x83), t(0x84), t(0x85), t(0x86), t(0x87),\ t(0x88), t(0x89), t(0x8a), t(0x8b), t(0x8c), t(0x8d), t(0x8e), t(0x8f),\ t(0x90), t(0x91), t(0x92), t(0x93), t(0x94), t(0x95), t(0x96), t(0x97),\ t(0x98), t(0x99), t(0x9a), t(0x9b), t(0x9c), t(0x9d), t(0x9e), t(0x9f),\ t(0xa0), t(0xa1), t(0xa2), t(0xa3), t(0xa4), t(0xa5), t(0xa6), t(0xa7),\ t(0xa8), t(0xa9), t(0xaa), t(0xab), t(0xac), t(0xad), t(0xae), t(0xaf),\ t(0xb0), t(0xb1), t(0xb2), t(0xb3), t(0xb4), t(0xb5), t(0xb6), t(0xb7),\ t(0xb8), t(0xb9), t(0xba), t(0xbb), t(0xbc), t(0xbd), t(0xbe), t(0xbf),\ t(0xc0), t(0xc1), t(0xc2), t(0xc3), t(0xc4), t(0xc5), t(0xc6), t(0xc7),\ t(0xc8), t(0xc9), t(0xca), t(0xcb), t(0xcc), t(0xcd), t(0xce), t(0xcf),\ t(0xd0), t(0xd1), t(0xd2), t(0xd3), t(0xd4), t(0xd5), t(0xd6), t(0xd7),\ t(0xd8), t(0xd9), t(0xda), t(0xdb), t(0xdc), t(0xdd), t(0xde), t(0xdf),\ t(0xe0), t(0xe1), t(0xe2), t(0xe3), t(0xe4), t(0xe5), t(0xe6), t(0xe7),\ t(0xe8), t(0xe9), t(0xea), t(0xeb), t(0xec), t(0xed), t(0xee), t(0xef),\ t(0xf0), t(0xf1), t(0xf2), t(0xf3), t(0xf4), t(0xf5), t(0xf6), t(0xf7),\ t(0xf8), t(0xf9), t(0xfa), t(0xfb), t(0xfc), t(0xfd), t(0xfe), t(0xff) /* // Encrypt/Decrypt S-box data // (be parametrized by any transformation 't') */ #define ENC_SBOX(t) \ t(0x63), t(0x7c), t(0x77), t(0x7b), t(0xf2), t(0x6b), t(0x6f), t(0xc5),\ t(0x30), t(0x01), t(0x67), t(0x2b), t(0xfe), t(0xd7), t(0xab), t(0x76),\ t(0xca), t(0x82), t(0xc9), t(0x7d), t(0xfa), t(0x59), t(0x47), t(0xf0),\ t(0xad), t(0xd4), t(0xa2), t(0xaf), t(0x9c), t(0xa4), t(0x72), t(0xc0),\ t(0xb7), t(0xfd), t(0x93), t(0x26), t(0x36), t(0x3f), t(0xf7), t(0xcc),\ t(0x34), t(0xa5), t(0xe5), t(0xf1), t(0x71), t(0xd8), t(0x31), t(0x15),\ t(0x04), t(0xc7), t(0x23), t(0xc3), t(0x18), t(0x96), t(0x05), t(0x9a),\ t(0x07), t(0x12), t(0x80), t(0xe2), t(0xeb), t(0x27), t(0xb2), t(0x75),\ t(0x09), t(0x83), t(0x2c), t(0x1a), t(0x1b), t(0x6e), t(0x5a), t(0xa0),\ t(0x52), t(0x3b), t(0xd6), t(0xb3), t(0x29), t(0xe3), t(0x2f), t(0x84),\ t(0x53), t(0xd1), t(0x00), t(0xed), t(0x20), t(0xfc), t(0xb1), t(0x5b),\ t(0x6a), t(0xcb), t(0xbe), t(0x39), t(0x4a), t(0x4c), t(0x58), t(0xcf),\ t(0xd0), t(0xef), t(0xaa), t(0xfb), t(0x43), t(0x4d), t(0x33), t(0x85),\ t(0x45), t(0xf9), t(0x02), t(0x7f), t(0x50), t(0x3c), t(0x9f), t(0xa8),\ t(0x51), t(0xa3), t(0x40), t(0x8f), t(0x92), t(0x9d), t(0x38), t(0xf5),\ t(0xbc), t(0xb6), t(0xda), t(0x21), t(0x10), t(0xff), t(0xf3), t(0xd2),\ t(0xcd), t(0x0c), t(0x13), t(0xec), t(0x5f), t(0x97), t(0x44), t(0x17),\ t(0xc4), t(0xa7), t(0x7e), t(0x3d), t(0x64), t(0x5d), t(0x19), t(0x73),\ t(0x60), t(0x81), t(0x4f), t(0xdc), t(0x22), t(0x2a), t(0x90), t(0x88),\ t(0x46), t(0xee), t(0xb8), t(0x14), t(0xde), t(0x5e), t(0x0b), t(0xdb),\ t(0xe0), t(0x32), t(0x3a), t(0x0a), t(0x49), t(0x06), t(0x24), t(0x5c),\ t(0xc2), t(0xd3), t(0xac), t(0x62), t(0x91), t(0x95), t(0xe4), t(0x79),\ t(0xe7), t(0xc8), t(0x37), t(0x6d), t(0x8d), t(0xd5), t(0x4e), t(0xa9),\ t(0x6c), t(0x56), t(0xf4), t(0xea), t(0x65), t(0x7a), t(0xae), t(0x08),\ t(0xba), t(0x78), t(0x25), t(0x2e), t(0x1c), t(0xa6), t(0xb4), t(0xc6),\ t(0xe8), t(0xdd), t(0x74), t(0x1f), t(0x4b), t(0xbd), t(0x8b), t(0x8a),\ t(0x70), t(0x3e), t(0xb5), t(0x66), t(0x48), t(0x03), t(0xf6), t(0x0e),\ t(0x61), t(0x35), t(0x57), t(0xb9), t(0x86), t(0xc1), t(0x1d), t(0x9e),\ t(0xe1), t(0xf8), t(0x98), t(0x11), t(0x69), t(0xd9), t(0x8e), t(0x94),\ t(0x9b), t(0x1e), t(0x87), t(0xe9), t(0xce), t(0x55), t(0x28), t(0xdf),\ t(0x8c), t(0xa1), t(0x89), t(0x0d), t(0xbf), t(0xe6), t(0x42), t(0x68),\ t(0x41), t(0x99), t(0x2d), t(0x0f), t(0xb0), t(0x54), t(0xbb), t(0x16) #define DEC_SBOX(t) \ t(0x52), t(0x09), t(0x6a), t(0xd5), t(0x30), t(0x36), t(0xa5), t(0x38),\ t(0xbf), t(0x40), t(0xa3), t(0x9e), t(0x81), t(0xf3), t(0xd7), t(0xfb),\ t(0x7c), t(0xe3), t(0x39), t(0x82), t(0x9b), t(0x2f), t(0xff), t(0x87),\ t(0x34), t(0x8e), t(0x43), t(0x44), t(0xc4), t(0xde), t(0xe9), t(0xcb),\ t(0x54), t(0x7b), t(0x94), t(0x32), t(0xa6), t(0xc2), t(0x23), t(0x3d),\ t(0xee), t(0x4c), t(0x95), t(0x0b), t(0x42), t(0xfa), t(0xc3), t(0x4e),\ t(0x08), t(0x2e), t(0xa1), t(0x66), t(0x28), t(0xd9), t(0x24), t(0xb2),\ t(0x76), t(0x5b), t(0xa2), t(0x49), t(0x6d), t(0x8b), t(0xd1), t(0x25),\ t(0x72), t(0xf8), t(0xf6), t(0x64), t(0x86), t(0x68), t(0x98), t(0x16),\ t(0xd4), t(0xa4), t(0x5c), t(0xcc), t(0x5d), t(0x65), t(0xb6), t(0x92),\ t(0x6c), t(0x70), t(0x48), t(0x50), t(0xfd), t(0xed), t(0xb9), t(0xda),\ t(0x5e), t(0x15), t(0x46), t(0x57), t(0xa7), t(0x8d), t(0x9d), t(0x84),\ t(0x90), t(0xd8), t(0xab), t(0x00), t(0x8c), t(0xbc), t(0xd3), t(0x0a),\ t(0xf7), t(0xe4), t(0x58), t(0x05), t(0xb8), t(0xb3), t(0x45), t(0x06),\ t(0xd0), t(0x2c), t(0x1e), t(0x8f), t(0xca), t(0x3f), t(0x0f), t(0x02),\ t(0xc1), t(0xaf), t(0xbd), t(0x03), t(0x01), t(0x13), t(0x8a), t(0x6b),\ t(0x3a), t(0x91), t(0x11), t(0x41), t(0x4f), t(0x67), t(0xdc), t(0xea),\ t(0x97), t(0xf2), t(0xcf), t(0xce), t(0xf0), t(0xb4), t(0xe6), t(0x73),\ t(0x96), t(0xac), t(0x74), t(0x22), t(0xe7), t(0xad), t(0x35), t(0x85),\ t(0xe2), t(0xf9), t(0x37), t(0xe8), t(0x1c), t(0x75), t(0xdf), t(0x6e),\ t(0x47), t(0xf1), t(0x1a), t(0x71), t(0x1d), t(0x29), t(0xc5), t(0x89),\ t(0x6f), t(0xb7), t(0x62), t(0x0e), t(0xaa), t(0x18), t(0xbe), t(0x1b),\ t(0xfc), t(0x56), t(0x3e), t(0x4b), t(0xc6), t(0xd2), t(0x79), t(0x20),\ t(0x9a), t(0xdb), t(0xc0), t(0xfe), t(0x78), t(0xcd), t(0x5a), t(0xf4),\ t(0x1f), t(0xdd), t(0xa8), t(0x33), t(0x88), t(0x07), t(0xc7), t(0x31),\ t(0xb1), t(0x12), t(0x10), t(0x59), t(0x27), t(0x80), t(0xec), t(0x5f),\ t(0x60), t(0x51), t(0x7f), t(0xa9), t(0x19), t(0xb5), t(0x4a), t(0x0d),\ t(0x2d), t(0xe5), t(0x7a), t(0x9f), t(0x93), t(0xc9), t(0x9c), t(0xef),\ t(0xa0), t(0xe0), t(0x3b), t(0x4d), t(0xae), t(0x2a), t(0xf5), t(0xb0),\ t(0xc8), t(0xeb), t(0xbb), t(0x3c), t(0x83), t(0x53), t(0x99), t(0x61),\ t(0x17), t(0x2b), t(0x04), t(0x7e), t(0xba), t(0x77), t(0xd6), t(0x26),\ t(0xe1), t(0x69), t(0x14), t(0x63), t(0x55), t(0x21), t(0x0c), t(0x7d), /* // Internal cipher tables */ extern const __ALIGN64 Ipp8u RijEncSbox[256]; /* pure encryption S-box */ extern const __ALIGN64 Ipp8u RijDecSbox[256]; /* pure decryption S-box */ extern const __ALIGN16 Ipp32u RijEncTbl[5][256]; /* precomputed encryption tables */ extern const __ALIGN16 Ipp32u RijDecTbl[5][256]; /* precomputed decryption tables */ #endif /* _PCP_RIJTBLES_H */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_decrypt.c000066400000000000000000000062151470420105600244230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_Decrypt() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" /*F* // Name: ippsRSA_Decrypt // // Purpose: Performs RSA Decryprion // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // NULL == pCtxt // NULL == pPtxt // NULL == pBuffer // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // !BN_VALID_ID(pCtxt) // !BN_VALID_ID(pPtxt) // // ippStsIncompleteContextErr private key is not set up // // ippStsOutOfRangeErr pCtxt >= modulus // pCtxt <0 // // ippStsSizeErr BN_ROOM(pPtxt) is not enough // // ippStsNoErr no error // // Parameters: // pCtxt pointer to the ciphertext // pPtxt pointer to the plaintext // pKey pointer to the key context // pScratchBuffer pointer to the temporary buffer *F*/ IPPFUN(IppStatus, ippsRSA_Decrypt,(const IppsBigNumState* pCtxt, IppsBigNumState* pPtxt, const IppsRSAPrivateKeyState* pKey, Ipp8u* pBuffer)) { IPP_BAD_PTR2_RET(pKey, pBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); IPP_BAD_PTR1_RET(pCtxt); IPP_BADARG_RET(!BN_VALID_ID(pCtxt), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pCtxt), ippStsOutOfRangeErr); IPP_BADARG_RET(0 <= cpCmp_BNU(BN_NUMBER(pCtxt), BN_SIZE(pCtxt), MOD_MODULUS(RSA_PRV_KEY_NMONT(pKey)), MOD_LEN(RSA_PRV_KEY_NMONT(pKey))), ippStsOutOfRangeErr); IPP_BAD_PTR1_RET(pPtxt); IPP_BADARG_RET(!BN_VALID_ID(pPtxt), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pPtxt) < BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_N(pKey)), ippStsSizeErr); { BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)( IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T)) ); if(RSA_PRV_KEY1_VALID_ID(pKey)) gsRSAprv_cipher(pPtxt, pCtxt, pKey, pScratchBuffer); else gsRSAprv_cipher_crt(pPtxt, pCtxt, pKey, pScratchBuffer); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_emsa_pkcs1v15.h000066400000000000000000000031631470420105600253370ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "pcptool.h" static int EMSA_PKCSv15(const Ipp8u* msgDg, int lenMsgDg, const Ipp8u* fixPS, int lenFixPS, Ipp8u* pEM, int lenEM) { /* // encoded message format: // EM = 00 || 01 || PS=(FF..FF) || 00 || T // T = fixPS || msgDg // len(PS) >= 8 */ int tLen = lenFixPS + lenMsgDg; if (lenEM >= tLen + 11) { int psLen = lenEM - 3 - tLen; PadBlock(0xFF, pEM, lenEM); pEM[0] = 0x00; pEM[1] = 0x01; pEM[2 + psLen] = 0x00; CopyBlock(fixPS, pEM + 3 + psLen, lenFixPS); if (msgDg) { CopyBlock(msgDg, pEM + 3 + psLen + lenFixPS, lenMsgDg); } return 1; } else return 0; /* encoded message length too long */ }cryptography-primitives-1.0.0/sources/ippcp/pcprsa_encrypt.c000066400000000000000000000060211470420105600244300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_Encrypt() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" /*F* // Name: ippsRSA_Encrypt // // Purpose: Performs RSA Encryprion // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // NULL == pPtxt // NULL == pCtxt // NULL == pBuffer // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // !BN_VALID_ID(pPtxt) // !BN_VALID_ID(pCtxt) // // ippStsIncompleteContextErr public key is not setup // // ippStsOutOfRangeErr pPtxt >= modulus // pPtxt <0 // // ippStsSizeErr BN_ROOM(pCtxt) is not enough // // ippStsNoErr no error // // Parameters: // pPtxt pointer to the plaintext // pCtxt pointer to the ciphertext // pKey pointer to the key context // pScratchBuffer pointer to the temporary buffer *F*/ IPPFUN(IppStatus, ippsRSA_Encrypt,(const IppsBigNumState* pPtxt, IppsBigNumState* pCtxt, const IppsRSAPublicKeyState* pKey, Ipp8u* pBuffer)) { IPP_BAD_PTR2_RET(pKey, pBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); IPP_BAD_PTR1_RET(pPtxt); IPP_BADARG_RET(!BN_VALID_ID(pPtxt), ippStsContextMatchErr); IPP_BADARG_RET(BN_NEGATIVE(pPtxt), ippStsOutOfRangeErr); IPP_BADARG_RET(0 <= cpCmp_BNU(BN_NUMBER(pPtxt), BN_SIZE(pPtxt), MOD_MODULUS(RSA_PUB_KEY_NMONT(pKey)), MOD_LEN(RSA_PUB_KEY_NMONT(pKey))), ippStsOutOfRangeErr); IPP_BAD_PTR1_RET(pCtxt); IPP_BADARG_RET(!BN_VALID_ID(pCtxt), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pCtxt) < BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_N(pKey)), ippStsSizeErr); { BNU_CHUNK_T* pScratchBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T)) ); gsRSApub_cipher(pCtxt, pPtxt, pKey, pScratchBuffer); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_generatekeys.c000066400000000000000000000303501470420105600254340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_GenerateKeys() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcpngrsa.h" #include "pcpprime_isco.h" #include "pcpprime_isprob.h" /*F* // Name: ippsRSA_GenerateKeys // // Purpose: Generate RSA keys // // Returns: Reason: // ippStsNullPtrErr NULL == pSrcPublicExp // NULL == pPublicExp // NULL == pModulus // NULL == pPrivateKeyType2 // NULL == pPrimeGen // NULL == pBuffer // NULL == rndFunc // // ippStsContextMatchErr !RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2) // !RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1) // !BN_VALID_ID(pSrcPublicExp) // !BN_VALID_ID(pPublicExp) // !BN_VALID_ID(pModulus) // !PRIME_VALID_ID(pPrimeGen) // // ippStsSizeErr BN_ROOM(pPublicExp) < BN_SIZE(pSrcPublicExp) // BN_ROOM(pModulus) < SIZE(factorPbitSize+factorQbitSize) // PRIME_MAXBITSIZE(pPrimeGen) < factorPbitSize // // ippStsOutOfRangeErr 0 >= pSrcPublicExp // // ippStsBadArgErr nTrials < 1 // // ippStsNoErr no error // // Parameters: // pSrcPublicExp pointer to the beginning public exponent // pPublicExp pointer to the resulting public exponent (E) // pModulus pointer to the resulting modulus (N) // pPrivateKeyType2 pointer to the private key type2 context // pPrivateKeyType1 (optional) pointer to the private key type1 context // pBuffer pointer to the temporary buffer // nTrials parameter of Miller-Rabin Test // pPrimeGen pointer to the Prime generator context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters *F*/ IPPFUN(IppStatus, ippsRSA_GenerateKeys,(const IppsBigNumState* pSrcPublicExp, IppsBigNumState* pModulus, IppsBigNumState* pPublicExp, IppsBigNumState* pPrivateExp, /* optional */ IppsRSAPrivateKeyState* pPrivateKeyType2, Ipp8u* pBuffer, int nTrials, IppsPrimeState* pPrimeGen, /* NULL */ IppBitSupplier rndFunc, void* pRndParam)) { IPP_BAD_PTR1_RET(pSrcPublicExp); IPP_BADARG_RET(!BN_VALID_ID(pSrcPublicExp), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pSrcPublicExp)), ippStsOutOfRangeErr); /* test if e is odd and e>=3 */ IPP_BADARG_RET(!(BN_NUMBER(pSrcPublicExp)[0] &1), ippStsBadArgErr); IPP_BADARG_RET((0 > cpBN_cmp(pSrcPublicExp, cpBN_ThreeRef())), ippStsBadArgErr); IPP_BAD_PTR1_RET(pModulus); IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); IPP_BAD_PTR1_RET(pPublicExp); IPP_BADARG_RET(!BN_VALID_ID(pPublicExp), ippStsContextMatchErr); IPP_BADARG_RET(BN_ROOM(pPublicExp) ret) break; /* internal error */ if(0 ==ret) continue; /* composite factor */ found = 1; } if(!found) goto err; /* internal error or ippStsInsufficientEntropy */ /* // generate prime Q */ topPattern = (BNU_CHUNK_T)1 << ((factorQbitSize-1)&(BNU_CHUNK_BITS-1)); nRounds = 5*factorQbitSize; for(r=0,found=0; r=512) { int bitsize = BITSIZE_BNU(pFreeBuffer, nsP); if(bitsize < (factorPbitSize-100)) continue; /* abs(P-Q) <=2^(factorPbitSize-100)*/ } } } /* test if bitsize(N) = bitsize(P)+bitsize(Q) */ cpMul_BNU_school(pProdN, pFactorP, nsP, pFactorQ, nsQ); if(rsaModulusBitSize != BITSIZE_BNU(pProdN, nsN)) continue; /* check if E and (Q-1) co-prime */ cpDec_BNU(pFactorQ, pFactorQ, nsQ, 1); if(0 == cpIsCoPrime(BN_NUMBER(pPublicExp), BN_SIZE(pPublicExp), pFactorQ, nsQ, pFreeBuffer)) continue; /* test Q for primality */ cpInc_BNU(pFactorQ, pFactorQ, nsQ, 1); gsModEngineInit(pMontQ, (Ipp32u*)pFactorQ, factorQbitSize, MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); //if(0==cpIsProbablyPrime(pFactorQ, factorQbitSize, mrTrials, // rndFunc, pRndParam, // pMontQ, pFreeBuffer)) continue; //found = 1; ret = cpIsProbablyPrime(pFactorQ, factorQbitSize, mrTrials, rndFunc, pRndParam, pMontQ, pFreeBuffer); if(0 > ret) break; /* internal error */ if(0 ==ret) continue; /* composite factor */ found = 1; } if(!found) goto err; /* internal error or ippStsInsufficientEntropy */ { BNU_CHUNK_T* pExpD = pFreeBuffer; BNU_CHUNK_T* pExpDBuf = pExpD +nsN+1; BNU_CHUNK_T* pPhi = pExpDBuf+nsN+1; BNU_CHUNK_T* pPhiBuf = pPhi +nsN+1; int nsD, ns; /* phi = (P-1) * (Q-1) */ cpDec_BNU(pFactorP, pFactorP, nsP, 1); cpDec_BNU(pFactorQ, pFactorQ, nsQ, 1); cpMul_BNU_school(pPhi, pFactorP, nsP, pFactorQ, nsQ); /* D = 1/E mod (phi) */ nsD = cpModInv_BNU(pExpD, BN_NUMBER(pPublicExp),BN_SIZE(pPublicExp), pPhi,nsN, pExpDBuf, BN_BUFFER(pPublicExp), pPhiBuf); /* if D exp requested */ if(pPrivateExp) BN_Set(pExpD, nsD, pPrivateExp); /* compute dP = D mod(P-1) */ COPY_BNU(pExpDBuf, pExpD, nsD); ns = cpMod_BNU(pExpDBuf, nsD, pFactorP, nsP); ZEXPAND_COPY_BNU(pExpDp, nsP, pExpDBuf, ns); /* compute dQ = D mod(Q-1) */ COPY_BNU(pPhi, pExpD, nsD); ns = cpMod_BNU(pPhi, nsD, pFactorQ, nsQ); ZEXPAND_COPY_BNU(pExpDq, nsQ, pPhi, ns); /* restore P and Q */ pFactorP[0]++; pFactorQ[0]++; /* re-init Montgomery Engine */ gsModEngineInit(pMontP, (Ipp32u*)pFactorP, factorPbitSize, MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); gsModEngineInit(pMontQ, (Ipp32u*)pFactorQ, factorQbitSize, MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); /* compute Qinv = 1/Q mod P */ COPY_BNU(pPhiBuf, pFactorP,nsP); ns = cpModInv_BNU(pInvQ, pFactorQ,nsQ, pPhiBuf,nsP, pExpD, pExpDBuf, pPhi); /* expand invQ */ ZEXPAND_BNU(pInvQ, ns, nsP); cpMul_BNU_school(pProdN, pFactorP, nsP, pFactorQ, nsQ); gsModEngineInit(pMontN, (Ipp32u*)pProdN, factorPbitSize+factorQbitSize, MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); /* setup modulus */ BN_Set(pProdN, nsN, pModulus); /* actual size of modulus in bits */ RSA_PRV_KEY_BITSIZE_N(pPrivateKeyType2) = BITSIZE_BNU(pProdN, nsN); ret = 1; return ippStsNoErr; } err: ZEXPAND_BNU(pFactorP, 0, nsP); ZEXPAND_BNU(pFactorQ, 0, nsQ); ZEXPAND_BNU(pExpDp, 0, nsP); ZEXPAND_BNU(pExpDq, 0, nsQ); ZEXPAND_BNU(pInvQ, 0, nsP); return ret<0? ippStsErr : ippStsInsufficientEntropy; } } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_generatesign_pkcs1v15.h000066400000000000000000000047741470420105600270760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "pcptool.h" #include "pcprsa_emsa_pkcs1v15.h" static int GenerateSign(const Ipp8u* pMsg, int msgLen, /* message representation */ const Ipp8u* pSalt, int saltLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, BNU_CHUNK_T* pBuffer) { /* size of RSA modulus in bytes and chunks */ cpSize rsaBits = RSA_PRV_KEY_BITSIZE_N(pPrvKey); cpSize k = BITS2WORD8_SIZE(rsaBits); cpSize nsN = BITS_BNU_CHUNK(rsaBits); /* EMSA-PKCS-v1_5 encoding */ int result = EMSA_PKCSv15(pMsg, msgLen, pSalt, saltLen, pSign, k); if (result) { /* temporary BNs */ __ALIGN8 IppsBigNumState bnC; __ALIGN8 IppsBigNumState bnP; /* make BNs */ BN_Make(pBuffer, pBuffer + nsN + 1, nsN, &bnC); pBuffer += (nsN + 1) * 2; BN_Make(pBuffer, pBuffer + nsN + 1, nsN, &bnP); pBuffer += (nsN + 1) * 2; /* // private-key operation */ ippsSetOctString_BN(pSign, k, &bnC); if (RSA_PRV_KEY1_VALID_ID(pPrvKey)) gsRSAprv_cipher(&bnP, &bnC, pPrvKey, pBuffer); else gsRSAprv_cipher_crt(&bnP, &bnC, pPrvKey, pBuffer); ippsGetOctString_BN(pSign, k, &bnP); /* check the result before send it out (fault attack mitigatioin) */ if (pPubKey) { gsRSApub_cipher(&bnP, &bnP, pPubKey, pBuffer); /* check signature before send it out (fault attack mitigatioin) */ if (0 != cpBN_cmp(&bnP, &bnC)) { PadBlock(0, pSign, k); result = 0; } } } return result; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_getbuffersizeprivatekey.c000066400000000000000000000062511470420105600277210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_GetBufferSizePrivateKey() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" #include "pcprsa_getdefmeth_priv.h" /*F* // Name: ippsRSA_GetBufferSizePrivateKey // // Purpose: Returns size of temporary buffer (in bytes) for private key operation // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // NULL == pBufferSize // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // // ippStsIncompleteContextErr (type1) private key is not set up // // ippStsNoErr no error // // Parameters: // pBufferSize pointer to size of temporary buffer // pKey pointer to the key context *F*/ IPPFUN(IppStatus, ippsRSA_GetBufferSizePrivateKey,(int* pBufferSize, const IppsRSAPrivateKeyState* pKey)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(RSA_PRV_KEY1_VALID_ID(pKey) && !RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); IPP_BAD_PTR1_RET(pBufferSize); { cpSize modulusBits = (RSA_PRV_KEY1_VALID_ID(pKey))? RSA_PRV_KEY_BITSIZE_N(pKey) : IPP_MAX(RSA_PRV_KEY_BITSIZE_P(pKey), RSA_PRV_KEY_BITSIZE_Q(pKey)); gsMethod_RSA* m = getDualExpMethod_RSA_private(RSA_PRV_KEY_BITSIZE_P(pKey), RSA_PRV_KEY_BITSIZE_Q(pKey)); if (NULL == m) m = getDefaultMethod_RSA_private(modulusBits); cpSize bitSizeN = (RSA_PRV_KEY1_VALID_ID(pKey))? modulusBits : modulusBits*2; cpSize nsN = BITS_BNU_CHUNK(bitSizeN); cpSize bn_scheme = (nsN+1)*2; /* BN for RSA schemes */ cpSize bn3_gen = (RSA_PRV_KEY2_VALID_ID(pKey))? (nsN+1)*2*3 : 0; /* 3 BN for generation/validation */ cpSize bufferNum = bn_scheme*2 /* (1)2 BN for RSA (enc)/sign schemes */ + 1; /* BNU_CHUNK_T alignment */ bufferNum += m->bufferNumFunc(modulusBits); /* RSA private key operation */ bufferNum = IPP_MAX(bufferNum, bn3_gen); /* generation/validation resource overlaps RSA resource */ *pBufferSize = bufferNum*(Ipp32s)sizeof(BNU_CHUNK_T); #if defined(_USE_WINDOW_EXP_) /* pre-computed table should be CACHE_LINE aligned*/ *pBufferSize += CACHE_LINE_SIZE; #endif return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_getbuffersizepublickey.c000066400000000000000000000045401470420105600275240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_GetBufferSizePublicKey() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" #include "pcprsa_getdefmeth_pub.h" /*F* // Name: ippsRSA_GetBufferSizePublicKey // // Purpose: Returns size of temporary buffer (in bytes) for public key operation // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // NULL == pBufferSize // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr no ippsRSA_SetPublicKey() call // // ippStsNoErr no error // // Parameters: // pBufferSize pointer to size of temporary buffer // pKey pointer to the key context *F*/ IPPFUN(IppStatus, ippsRSA_GetBufferSizePublicKey,(int* pBufferSize, const IppsRSAPublicKeyState* pKey)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); IPP_BAD_PTR1_RET(pBufferSize); { cpSize bitSizeN = RSA_PUB_KEY_BITSIZE_N(pKey); cpSize nsN = BITS_BNU_CHUNK(bitSizeN); gsMethod_RSA* m = getDefaultMethod_RSA_public(bitSizeN); cpSize bufferNum = ((nsN+1)*2)*2 /* (1)2 BN for RSA (enc)/sign schemes */ + 1; /* BNU_CHUNK_T alignment */ bufferNum += m->bufferNumFunc(bitSizeN); /* RSA public key operation */ *pBufferSize = bufferNum*(Ipp32s)sizeof(BNU_CHUNK_T); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_getdefmeth_priv.h000066400000000000000000000036201470420105600261270ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" static gsMethod_RSA* getDefaultMethod_RSA_private(int modulusBitSize) { gsMethod_RSA* m; #if(_IPP32E>=_IPP32E_K1) m = IsFeatureEnabled(ippCPUID_AVX512IFMA) ? gsMethod_RSA_avx512_private() : gsMethod_RSA_avx2_private(); #elif(_IPP32E>=_IPP32E_L9) m = IsFeatureEnabled(ippCPUID_ADCOX) ? gsMethod_RSA_gpr_private() : gsMethod_RSA_avx2_private(); #elif(_IPP>=_IPP_W7) m = gsMethod_RSA_sse2_private(); #else m = gsMethod_RSA_gpr_private(); #endif if (!(m->loModulusBisize <= modulusBitSize && modulusBitSize <= m->hiModulusBisize)) m = gsMethod_RSA_gpr_private(); return m; } static gsMethod_RSA* getDualExpMethod_RSA_private(int bitSizeDP, int bitSizeDQ) { /* Dual exp kernels assume same bitsizes of private exponents */ if ((bitSizeDP != bitSizeDQ) || (bitSizeDP == 0)) return NULL; #if(_IPP32E>=_IPP32E_K1) gsMethod_RSA* m = NULL; m = gsMethod_RSA_avx512_crt_private(bitSizeDP); if (m && m->dualExpFun) return m; #endif return NULL; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_getdefmeth_pub.h000066400000000000000000000027411470420105600257400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" /* get default method based on CPU's features */ static gsMethod_RSA* getDefaultMethod_RSA_public(int modulusBitSize) { gsMethod_RSA* m; #if(_IPP32E>=_IPP32E_K1) m = IsFeatureEnabled(ippCPUID_AVX512IFMA) ? gsMethod_RSA_avx512_public() : gsMethod_RSA_avx2_public(); #elif(_IPP32E>=_IPP32E_L9) m = gsMethod_RSA_avx2_public(); #elif(_IPP>=_IPP_W7) m = gsMethod_RSA_sse2_public(); #else m = gsMethod_RSA_gpr_public(); #endif if (!(m->loModulusBisize <= modulusBitSize && modulusBitSize <= m->hiModulusBisize)) m = gsMethod_RSA_gpr_public(); return m; }cryptography-primitives-1.0.0/sources/ippcp/pcprsa_getprivatekeytype1.c000066400000000000000000000053621470420105600266210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_GetPrivateKeyType1() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" /*F* // Name: ippsRSA_GetPrivateKeyType1 // // Purpose: Extract key component from the key context // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // !BN_VALID_ID(pModulus) // !BN_VALID_ID(pExp) // // ippStsIncompleteContextErr private key is not set up // // ippStsSizeErr BN_ROOM(pModulus), BN_ROOM(pExp) is not enough // // ippStsNoErr no error // // Parameters: // pModulus (optional) pointer to the modulus (N) // pExp (optional) pointer to the public exponent (E) // pKey pointer to the key context *F*/ IPPFUN(IppStatus, ippsRSA_GetPrivateKeyType1,(IppsBigNumState* pModulus, IppsBigNumState* pExp, const IppsRSAPrivateKeyState* pKey)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(!RSA_PRV_KEY1_VALID_ID(pKey), ippStsContextMatchErr); if(pModulus) { IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); IPP_BADARG_RET(BN_ROOM(pModulus) rsaModulusBitSize // MAX_RSA_SIZE < rsaModulusBitSize // // ippStsBadArgErr 0 >= privateExpBitSize // privateExpBitSize > rsaModulusBitSize // // ippStsNoErr no error // // Parameters: // rsaModulusBitSize bitsize of RSA modulus (bitsize of N) // privateExpBitSize bitsize of private exponent (bitsize of D) // pSize pointer to the size of RSA key context (bytes) *F*/ IPPFUN(IppStatus, ippsRSA_GetSizePrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, int* pKeySize)) { IPP_BAD_PTR1_RET(pKeySize); IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); IPP_BADARG_RET(!((0 (factorPbitSize+factorQbitSize) // MAX_RSA_SIZE < (factorPbitSize+factorQbitSize) // // ippStsBadArgErr 0 >= factorPbitSize // 0 >= factorQbitSize // factorQbitSize > factorPbitSize // // ippStsNoErr no error // // Parameters: // factorPbitSize bitsize of RSA modulus (bitsize of P) // factorPbitSize bitsize of private exponent (bitsize of Q) // pSize pointer to the size of RSA key context (bytes) *F*/ IPPFUN(IppStatus, ippsRSA_GetSizePrivateKeyType2,(int factorPbitSize, int factorQbitSize, int* pKeySize)) { IPP_BAD_PTR1_RET(pKeySize); IPP_BADARG_RET((factorPbitSize<=0) || (factorQbitSize<=0), ippStsBadArgErr); //25.09.2019 gres: IPP_BADARG_RET((factorPbitSize < factorQbitSize), ippStsBadArgErr); IPP_BADARG_RET((MIN_RSA_SIZE>(factorPbitSize+factorQbitSize) || (factorPbitSize+factorQbitSize)>MAX_RSA_SIZE), ippStsNotSupportedModeErr); *pKeySize = cpSizeof_RSA_privateKey2(factorPbitSize, factorQbitSize); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_getsizepublickey.c000066400000000000000000000042011470420105600263240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_GetSizePublicKey() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcprsa_sizeof_pubkey.h" /*F* // Name: ippsRSA_GetSizePublicKey // // Purpose: Returns context size (bytes) of RSA public key context // // Returns: Reason: // ippStsNullPtrErr NULL == pSize // // ippStsNotSupportedModeErr MIN_RSA_SIZE > rsaModulusBitSize // MAX_RSA_SIZE < rsaModulusBitSize // // ippStsBadArgErr 0 >= publicExpBitSize // publicExpBitSize > rsaModulusBitSize // // ippStsNoErr no error // // Parameters: // rsaModulusBitSize bitsize of RSA modulus (bitsize of N) // publicExpBitSize bitsize of public exponent (bitsize of E) // pSize pointer to the size of RSA key context (bytes) *F*/ IPPFUN(IppStatus, ippsRSA_GetSizePublicKey,(int rsaModulusBitSize, int publicExpBitSize, int* pKeySize)) { IPP_BAD_PTR1_RET(pKeySize); IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); IPP_BADARG_RET(!((0=_IPP32E_L9) #include "pcpngmontexpstuff_avx2.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_avx2_private, (void)) { static gsMethod_RSA m = { RSA_AVX2_MIN_BITSIZE, RSA_AVX2_MAX_BITSIZE, /* RSA range */ /* private key exponentiation: private, window, avx2 */ #if !defined(_USE_WINDOW_EXP_) gsMontExpBinBuffer_avx2, gsMontExpBin_BNU_sscm_avx2 #else gsMontExpWinBuffer_avx2, gsMontExpWin_BNU_sscm_avx2 #endif , NULL }; return &m; } #endif /* _IPP32E_L9 */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__avx2_public.c000066400000000000000000000026351470420105600272220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_gpr_public() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" #if (_IPP32E>=_IPP32E_L9) #include "pcpngmontexpstuff_avx2.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_avx2_public, (void)) { static gsMethod_RSA m = { RSA_AVX2_MIN_BITSIZE, RSA_AVX2_MAX_BITSIZE, /* RSA range */ /* public key exponentiation: public, binary gpr */ gsMontExpBinBuffer, gsModExpBin_BNU, NULL }; return &m; } #endif /* _IPP32E_L9 */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__avx512_private.c000066400000000000000000000045011470420105600275560ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_gpr_private() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" #if (_IPP32E>=_IPP32E_K1) #include "pcpngmontexpstuff_avx512.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_avx512_private, (void)) { static gsMethod_RSA m = { RSA_AVX512_MIN_BITSIZE, RSA_AVX512_MAX_BITSIZE, /* RSA range */ /* private key exponentiation: private, window, avx512 */ #if !defined(_USE_WINDOW_EXP_) gsMontExpBinBuffer_avx512, gsMontExpBin_BNU_sscm_avx512 #else gsMontExpWinBuffer_avx512, gsMontExpWin_BNU_sscm_avx512 #endif , NULL }; return &m; } #define RSA_DUAL_EXP_AVX512_MIN_BITSIZE 2048 #define RSA_DUAL_EXP_AVX512_MAX_BITSIZE 4096 IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_avx512_crt_private, (int privExpBitSize)) { static gsMethod_RSA m = { RSA_DUAL_EXP_AVX512_MIN_BITSIZE, RSA_DUAL_EXP_AVX512_MAX_BITSIZE, /* RSA range */ gsMontDualExpWinBuffer_avx512, NULL, NULL }; if (IsFeatureEnabled(ippCPUID_AVX512IFMA)) { ngMontDualExp dexpFunc = NULL; switch (privExpBitSize) { /* RSA 2k,3k,4k only supported */ case 1024: case 1536: case 2048: dexpFunc = gsMontDualExpWin_BNU_sscm_avx512; break; default: dexpFunc = NULL; } m.dualExpFun = dexpFunc; } return &m; } #endif /* _IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__avx512_public.c000066400000000000000000000027041470420105600273650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_gpr_public() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" #if (_IPP32E>=_IPP32E_K1) #include "pcpngmontexpstuff_avx512.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_avx512_public, (void)) { static gsMethod_RSA m = { RSA_AVX512_MIN_BITSIZE, RSA_AVX512_MAX_BITSIZE, /* RSA range */ /* public key exponentiation: public, binary, avx512 */ gsMontExpBinBuffer_avx512, gsMontExpBin_BNU_avx512, NULL }; return &m; } #endif /* _IPP32E_L9 */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__gpr_private.c000066400000000000000000000027241470420105600273250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_gpr_private() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" /* // definition of RSA exponentiation (PX/GPR based) */ IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_gpr_private, (void)) { static gsMethod_RSA m = { MIN_RSA_SIZE, MAX_RSA_SIZE, /* RSA range */ /* private key exponentiation: private, window, gpr */ gsMontExpWinBuffer, #if !defined(_USE_WINDOW_EXP_) gsModExpBin_BNU_sscm #else gsModExpWin_BNU_sscm #endif , NULL }; return &m; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__gpr_public.c000066400000000000000000000024671470420105600271350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_gpr_public() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_gpr_public, (void)) { static gsMethod_RSA m = { MIN_RSA_SIZE, MAX_RSA_SIZE, /* RSA range */ /* public key exponentiation: public, binary, gpr */ gsMontExpBinBuffer, gsModExpBin_BNU, NULL }; return &m; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__sse2_private.c000066400000000000000000000030531470420105600274050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_sse2_private() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" #if (_IPP>=_IPP_W7) #include "pcpngmontexpstuff_sse2.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_sse2_private, (void)) { static gsMethod_RSA m = { RSA_SSE2_MIN_BITSIZE, RSA_SSE2_MAX_BITSIZE, /* RSA range */ /* private key exponentiation: private, window, sse2 */ #if !defined(_USE_WINDOW_EXP_) gsMontExpBinBuffer_sse2, gsMontExpBin_BNU_sscm_sse2 #else gsMontExpWinBuffer_sse2, gsMontExpWin_BNU_sscm_sse2 #endif , NULL }; return &m; } #endif /* _IPP_W7 */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsmethod__sse2_public.c000066400000000000000000000026431470420105600272150ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Montgomery engine preparation (GetSize/init/Set) */ /* // Intel(R) Cryptography Primitives Library // // Context: // gsMethod_RSA_sse2_public() // */ #include "owncp.h" #include "pcpngmontexpstuff.h" #include "gsscramble.h" #include "pcpngrsamethod.h" #include "pcpngrsa.h" #if (_IPP>=_IPP_W7) #include "pcpngmontexpstuff_sse2.h" IPP_OWN_DEFN (gsMethod_RSA*, gsMethod_RSA_sse2_public, (void)) { static gsMethod_RSA m = { RSA_SSE2_MIN_BITSIZE, RSA_SSE2_MAX_BITSIZE, /* RSA range */ /* public key exponentiation: public, binary, sse2 */ gsMontExpBinBuffer_sse2, gsMontExpBin_BNU_sse2, NULL }; return &m; } #endif /* _IPP_W7 */ cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsprv_cipher.c000066400000000000000000000030771470420105600254470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // gsRSAprv_cipher() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" #include "pcprsa_getdefmeth_priv.h" IPP_OWN_DEFN (void, gsRSAprv_cipher, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pBuffer)) { gsMethod_RSA* m = getDefaultMethod_RSA_private(RSA_PRV_KEY_BITSIZE_N(pKey)); BNU_CHUNK_T* dataY = BN_NUMBER(pY); cpSize nsY = m->expFun(dataY, BN_NUMBER(pX), BN_SIZE(pX), RSA_PRV_KEY_D(pKey), RSA_PRV_KEY_BITSIZE_N(pKey), RSA_PRV_KEY_NMONT(pKey), pBuffer); FIX_BNU(dataY, nsY); BN_SIZE(pY) = nsY; BN_SIGN(pY) = ippBigNumPOS; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gsprv_cipher_crt.c000066400000000000000000000131231470420105600263100ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // gsRSAprv_cipher_crt() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" #include "pcprsa_getdefmeth_priv.h" /* CTE version of CRT based RSA decrypt */ IPP_OWN_DEFN (void, gsRSAprv_cipher_crt, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pBuffer)) { const BNU_CHUNK_T* dataX = BN_NUMBER(pX); cpSize nsX = BN_SIZE(pX); BNU_CHUNK_T* dataY = BN_NUMBER(pY); BNU_CHUNK_T* dataXp = BN_NUMBER(pY); BNU_CHUNK_T* dataXq = BN_BUFFER(pY); /* P- and Q- montgometry engines */ gsModEngine* pMontP = RSA_PRV_KEY_PMONT(pKey); gsModEngine* pMontQ = RSA_PRV_KEY_QMONT(pKey); cpSize nsP = MOD_LEN(pMontP); cpSize nsQ = MOD_LEN(pMontQ); cpSize bitSizeP = RSA_PRV_KEY_BITSIZE_P(pKey); cpSize bitSizeQ = RSA_PRV_KEY_BITSIZE_Q(pKey); cpSize bitSizeDP = bitSizeP; //BITSIZE_BNU(RSA_PRV_KEY_DP(pKey), nsP); /* bitsize of dP exp */ cpSize bitSizeDQ = bitSizeQ; //BITSIZE_BNU(RSA_PRV_KEY_DQ(pKey), nsQ); /* bitsize of dQ exp */ /* Prefer dual exponentiation method if available */ gsMethod_RSA* m = getDualExpMethod_RSA_private(bitSizeDP, bitSizeDQ); if (m) { ZEXPAND_COPY_BNU(pBuffer, nsQ+nsQ, dataX, nsX); MOD_METHOD(pMontQ)->red(dataXq, pBuffer, pMontQ); MOD_METHOD(pMontQ)->mul(dataXq, dataXq, MOD_MNT_R2(pMontQ), pMontQ); ZEXPAND_COPY_BNU(pBuffer, nsP+nsP, dataX, nsX); MOD_METHOD(pMontP)->red(dataXp, pBuffer, pMontP); MOD_METHOD(pMontP)->mul(dataXp, dataXp, MOD_MNT_R2(pMontP), pMontP); BNU_CHUNK_T* pDataX[2] = {0}; pDataX[0] = dataXq; pDataX[1] = dataXp; cpSize pSize[2] = {0}; pSize[0] = nsQ; pSize[1] = nsP; BNU_CHUNK_T* pPrvExp[2] = {0}; pPrvExp[0] = RSA_PRV_KEY_DQ(pKey); pPrvExp[1] = RSA_PRV_KEY_DP(pKey); gsModEngine* pMont[2] = {0}; pMont[0] = pMontQ; pMont[1] = pMontP; m->dualExpFun(pDataX, (const BNU_CHUNK_T**)pDataX, pSize, (const BNU_CHUNK_T**)pPrvExp, pMont, pBuffer); } else { /* compute xq = x^dQ mod Q */ if (bitSizeP== bitSizeQ) { /* believe it's enough conditions for correct Mont application */ ZEXPAND_COPY_BNU(pBuffer, nsQ+nsQ, dataX, nsX); MOD_METHOD(pMontQ)->red(dataXq, pBuffer, pMontQ); MOD_METHOD(pMontQ)->mul(dataXq, dataXq, MOD_MNT_R2(pMontQ), pMontQ); } else { COPY_BNU(dataXq, dataX, nsX); cpMod_BNU(dataXq, nsX, MOD_MODULUS(pMontQ), nsQ); } m = getDefaultMethod_RSA_private(bitSizeDQ); m->expFun(dataXq, dataXq, nsQ, RSA_PRV_KEY_DQ(pKey), bitSizeDQ, pMontQ, pBuffer); /* compute xp = x^dP mod P */ if (bitSizeP== bitSizeQ) { /* believe it's enough conditions for correct Mont application */ ZEXPAND_COPY_BNU(pBuffer, nsP+nsP, dataX, nsX); MOD_METHOD(pMontP)->red(dataXp, pBuffer, pMontP); MOD_METHOD(pMontP)->mul(dataXp, dataXp, MOD_MNT_R2(pMontP), pMontP); } else { COPY_BNU(dataXp, dataX, nsX); cpMod_BNU(dataXp, nsX, MOD_MODULUS(pMontP), nsP); } m = getDefaultMethod_RSA_private(bitSizeDP); m->expFun(dataXp, dataXp, nsP, RSA_PRV_KEY_DP(pKey), bitSizeDP, pMontP, pBuffer); } /* // recombination */ /* xq = xq mod P must be sure that xq in the same residue domain as xp because of following (xp-xq) mod P operation */ if (bitSizeP == bitSizeQ) { /* believe it's enough conditions for correct Mont application */ ZEXPAND_COPY_BNU(pBuffer, nsP+nsP, dataXq, nsQ); //MOD_METHOD(pMontP)->red(pBuffer, pBuffer, pMontP); //MOD_METHOD(pMontP)->mul(pBuffer, pBuffer, MOD_MNT_R2(pMontP), pMontP); MOD_METHOD(pMontP)->sub(pBuffer, pBuffer, MOD_MODULUS(pMontP), pMontP); /* xp = (xp - xq) mod P */ MOD_METHOD(pMontP)->sub(dataXp, dataXp, pBuffer, pMontP); } else { COPY_BNU(pBuffer, dataXq, nsQ); { cpSize nsQP = cpMod_BNU(pBuffer, nsQ, MOD_MODULUS(pMontP), nsP); BNU_CHUNK_T cf = cpSub_BNU(dataXp, dataXp, pBuffer, nsQP); if(nsP-nsQP) cf = cpDec_BNU(dataXp+nsQP, dataXp + nsQP, (nsP-nsQP), cf); if (cf) cpAdd_BNU(dataXp, dataXp, MOD_MODULUS(pMontP), nsP); } } /* xp = xp*qInv mod P */ /* convert invQ into Montgomery domain */ MOD_METHOD(pMontP)->encode(pBuffer, RSA_PRV_KEY_INVQ(pKey), (gsModEngine*)pMontP); /* and multiply xp *= mont(invQ) mod P */ MOD_METHOD(pMontP)->mul(dataXp, dataXp, pBuffer, pMontP); /* Y = xq + xp*Q */ cpMul_BNU_school(pBuffer, dataXp, nsP, MOD_MODULUS(pMontQ), nsQ); { BNU_CHUNK_T cf = cpAdd_BNU(dataY, pBuffer, dataXq, nsQ); cpInc_BNU(dataY + nsQ, pBuffer + nsQ, nsP, cf); } nsX = nsP + nsQ; FIX_BNU(dataY, nsX); BN_SIZE(pY) = nsX; BN_SIGN(pY) = ippBigNumPOS; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_gspub_cipher.c000066400000000000000000000030741470420105600254230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // gsRSApub_cipher() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcpngrsamethod.h" #include "pcprsa_getdefmeth_pub.h" IPP_OWN_DEFN (void, gsRSApub_cipher, (IppsBigNumState* pY, const IppsBigNumState* pX, const IppsRSAPublicKeyState* pKey, BNU_CHUNK_T* pBuffer)) { gsMethod_RSA* m = getDefaultMethod_RSA_public(RSA_PRV_KEY_BITSIZE_N(pKey)); BNU_CHUNK_T* dataY = BN_NUMBER(pY); cpSize nsY = m->expFun(dataY, BN_NUMBER(pX), BN_SIZE(pX), RSA_PUB_KEY_E(pKey), RSA_PUB_KEY_BITSIZE_E(pKey), RSA_PUB_KEY_NMONT(pKey), pBuffer); FIX_BNU(dataY, nsY); BN_SIZE(pY) = nsY; BN_SIGN(pY) = ippBigNumPOS; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_initprivatekeytype1.c000066400000000000000000000073201470420105600270010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_InitPrivateKeyType1() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" #include "pcprsa_sizeof_privkey1.h" /*F* // Name: ippsRSA_InitPrivateKeyType1 // // Purpose: Init RSA private key context // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // // ippStsNotSupportedModeErr MIN_RSA_SIZE > rsaModulusBitSize // MAX_RSA_SIZE < rsaModulusBitSize // // ippStsBadArgErr 0 >= privateExpBitSize // privateExpBitSize > rsaModulusBitSize // // ippStsMemAllocErr keyCtxSize is not enough for operation // // ippStsNoErr no error // // Parameters: // rsaModulusBitSize bitsize of RSA modulus (bitsize of N) // privateExpBitSize bitsize of private exponent (bitsize of D) // pKey pointer to the key context // keyCtxSize size of memory accosizted with key comtext *F*/ IPPFUN(IppStatus, ippsRSA_InitPrivateKeyType1,(int rsaModulusBitSize, int privateExpBitSize, IppsRSAPrivateKeyState* pKey, int keyCtxSize)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); IPP_BADARG_RET(!((0 (factorPbitSize+factorQbitSize) // MAX_RSA_SIZE < (factorPbitSize+factorQbitSize) // // ippStsBadArgErr 0 >= factorPbitSize // 0 >= factorQbitSize // factorQbitSize > factorPbitSize // // ippStsMemAllocErr keyCtxSize is not enough for operation // // ippStsNoErr no error // // Parameters: // factorPbitSize bitsize of RSA modulus (bitsize of P) // factorQbitSize bitsize of private exponent (bitsize of Q) // pKey pointer to the key context // keyCtxSize size of memory associated with key context *F*/ IPPFUN(IppStatus, ippsRSA_InitPrivateKeyType2,(int factorPbitSize, int factorQbitSize, IppsRSAPrivateKeyState* pKey, int keyCtxSize)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET((factorPbitSize<=0) || (factorQbitSize<=0), ippStsBadArgErr); //25.09.2019 gres: IPP_BADARG_RET((factorPbitSize < factorQbitSize), ippStsBadArgErr); IPP_BADARG_RET((MIN_RSA_SIZE>(factorPbitSize+factorQbitSize) || (factorPbitSize+factorQbitSize)>MAX_RSA_SIZE), ippStsNotSupportedModeErr); /* test available size of context buffer */ IPP_BADARG_RET(keyCtxSize rsaModulusBitSize // MAX_RSA_SIZE < rsaModulusBitSize // // ippStsBadArgErr 0 >= publicExpBitSize // publicExpBitSize > rsaModulusBitSize // // ippStsMemAllocErr keyCtxSize is not enough for operation // // ippStsNoErr no error // // Parameters: // rsaModulusBitSize bitsize of RSA modulus (bitsize of N) // publicExpBitSize bitsize of public exponent (bitsize of E) // pKey pointer to the key context // keyCtxSize size of memory associated with key context *F*/ IPPFUN(IppStatus, ippsRSA_InitPublicKey,(int rsaModulusBitSize, int publicExpBitSize, IppsRSAPublicKeyState* pKey, int keyCtxSize)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET((MIN_RSA_SIZE>rsaModulusBitSize) || (rsaModulusBitSize>MAX_RSA_SIZE), ippStsNotSupportedModeErr); IPP_BADARG_RET(!((0hashAlgId, ippStsNotSupportedModeErr); IPP_BADARG_RET(ippHashAlg_SM3 == pMethod->hashAlgId, ippStsNotSupportedModeErr); /* use aligned public key context if defined */ if (*pPubKey) { IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(*pPubKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(*pPubKey), ippStsIncompleteContextErr); } /* test data pointer */ IPP_BAD_PTR2_RET(pMsg, pSign); /* test length */ IPP_BADARG_RET(msgLen < 0, ippStsLengthErr); return ippStsNoErr; } // Check all the ippsRSAVerify_PKCS1v15_rmf parameters, set valid=0, align pKey pointer __IPPCP_INLINE IppStatus SingleVerifyPkcs1v15RmfPreproc(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState** pKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer) { /* test public key context */ IPP_BAD_PTR3_RET(*pKey, pScratchBuffer, pMethod); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(*pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(*pKey), ippStsIncompleteContextErr); /* test hash algorithm ID */ IPP_BADARG_RET(ippHashAlg_Unknown == pMethod->hashAlgId, ippStsNotSupportedModeErr); IPP_BADARG_RET(ippHashAlg_SM3 == pMethod->hashAlgId, ippStsNotSupportedModeErr); /* test data pointer */ IPP_BAD_PTR3_RET(pMsg, pSign, pIsValid); /* test length */ IPP_BADARG_RET(msgLen < 0, ippStsLengthErr); *pIsValid = 0; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_pss_preproc.h000066400000000000000000000054561470420105600253230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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 "owncp.h" #include "hash/pcphash_rmf.h" // Check all the ippsRSASign_PSS_rmf parameters and align pPrvKey, pPubKey pointers __IPPCP_INLINE IppStatus SingleSignPssRmfPreproc(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSalt, int saltLen, Ipp8u* pSign, const IppsRSAPrivateKeyState** pPrvKey, const IppsRSAPublicKeyState** pPubKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer) { /* test message length */ IPP_BADARG_RET((msgLen < 0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); /* test data pointer */ IPP_BAD_PTR2_RET(pSign, pMethod); /* test salt length and salt pointer */ IPP_BADARG_RET(saltLen < 0, ippStsLengthErr); IPP_BADARG_RET((saltLen && !pSalt), ippStsNullPtrErr); /* test private key context */ IPP_BAD_PTR2_RET(*pPrvKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(*pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(*pPrvKey), ippStsIncompleteContextErr); /* use aligned public key context if defined */ if (*pPubKey) { IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(*pPubKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(*pPubKey), ippStsIncompleteContextErr); } return ippStsNoErr; } // Check all the ippsRSAVerify_PSS_rmf parameters, set valid=0, align pKey pointer __IPPCP_INLINE IppStatus SingleVerifyPssRmfPreproc(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState** pKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer) { /* test message length */ IPP_BADARG_RET((msgLen < 0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); /* test data pointer */ IPP_BAD_PTR3_RET(pSign, pIsValid, pMethod); /* test public key context */ IPP_BAD_PTR2_RET(*pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(*pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(*pKey), ippStsIncompleteContextErr); *pIsValid = 0; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_setprivatekeytype1.c000066400000000000000000000063221470420105600266320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_SetPrivateKeyType1() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" /*F* // Name: ippsRSA_SetPrivateKeyType1 // // Purpose: Set up the RSA private key // // Returns: Reason: // ippStsNullPtrErr NULL == pModulus // NULL == pPrivateExp // NULL == pKey // // ippStsContextMatchErr !BN_VALID_ID(pModulus) // !BN_VALID_ID(pPrivateExp) // !RSA_PRV_KEY_VALID_ID() // // ippStsOutOfRangeErr 0 >= pModulus // 0 >= pPrivateExp // // ippStsSizeErr bitsize(pModulus) exceeds requested value // bitsize(pPrivateExp) exceeds requested value // // ippStsNoErr no error // // Parameters: // pModulus pointer to modulus (N) // pPrivateExp pointer to public exponent (D) // pKey pointer to the key context *F*/ IPPFUN(IppStatus, ippsRSA_SetPrivateKeyType1,(const IppsBigNumState* pModulus, const IppsBigNumState* pPrivateExp, IppsRSAPrivateKeyState* pKey)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(!RSA_PRV_KEY1_VALID_ID(pKey), ippStsContextMatchErr); IPP_BAD_PTR1_RET(pModulus); IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pModulus)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pModulus), BN_SIZE(pModulus)) > RSA_PRV_KEY_MAXSIZE_N(pKey), ippStsSizeErr); IPP_BAD_PTR1_RET(pPrivateExp); IPP_BADARG_RET(!BN_VALID_ID(pPrivateExp), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pPrivateExp)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPrivateExp), BN_SIZE(pPrivateExp)) > RSA_PRV_KEY_MAXSIZE_D(pKey), ippStsSizeErr); { /* store D */ ZEXPAND_COPY_BNU(RSA_PRV_KEY_D(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_MAXSIZE_D(pKey)), BN_NUMBER(pPrivateExp), BN_SIZE(pPrivateExp)); /* setup montgomery engine */ gsModEngineInit(RSA_PRV_KEY_NMONT(pKey), (Ipp32u*)BN_NUMBER(pModulus), cpBN_bitsize(pModulus), MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); RSA_PRV_KEY_BITSIZE_N(pKey) = cpBN_bitsize(pModulus); RSA_PRV_KEY_BITSIZE_D(pKey) = cpBN_bitsize(pPrivateExp); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_setprivatekeytype2.c000066400000000000000000000142031470420105600266300ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_SetPrivateKeyType2() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" /*F* // Name: ippsRSA_SetPrivateKeyType2 // // Purpose: Set up the RSA private key // // Returns: Reason: // ippStsNullPtrErr NULL == pFactorP, NULL == pFactorQ // NULL == pCrtExpP, NULL == pCrtExpQ // NULL == pInverseQ // NULL == pKey // // ippStsContextMatchErr !BN_VALID_ID(pFactorP), !BN_VALID_ID(pFactorQ) // !BN_VALID_ID(pCrtExpP), !BN_VALID_ID(pCrtExpQ) // !BN_VALID_ID(pInverseQ) // !RSA_PRV_KEY_VALID_ID() // // ippStsOutOfRangeErr 0 >= pFactorP, 0 >= pFactorQ // 0 >= pCrtExpP, 0 >= pCrtExpQ // 0 >= pInverseQ // // ippStsSizeErr bitsize(pFactorP) exceeds requested value // bitsize(pFactorQ) exceeds requested value // bitsize(pCrtExpP) > bitsize(pFactorP) // bitsize(pCrtExpQ) > bitsize(pFactorQ) // bitsize(pInverseQ) > bitsize(pFactorP) // // ippStsNoErr no error // // Parameters: // pFactorP, pFactorQ pointer to the RSA modulus (N) prime factors // pCrtExpP, pCrtExpQ pointer to CTR's exponent // pInverseQ 1/Q mod P // pKey pointer to the key context *F*/ IPPFUN(IppStatus, ippsRSA_SetPrivateKeyType2,(const IppsBigNumState* pFactorP, const IppsBigNumState* pFactorQ, const IppsBigNumState* pCrtExpP, const IppsBigNumState* pCrtExpQ, const IppsBigNumState* pInverseQ, IppsRSAPrivateKeyState* pKey)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(!RSA_PRV_KEY2_VALID_ID(pKey), ippStsContextMatchErr); IPP_BAD_PTR1_RET(pFactorP); IPP_BADARG_RET(!BN_VALID_ID(pFactorP), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pFactorP)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pFactorP), BN_SIZE(pFactorP)) > RSA_PRV_KEY_BITSIZE_P(pKey), ippStsSizeErr); IPP_BAD_PTR1_RET(pFactorQ); IPP_BADARG_RET(!BN_VALID_ID(pFactorQ), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pFactorQ)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pFactorQ), BN_SIZE(pFactorQ)) > RSA_PRV_KEY_BITSIZE_Q(pKey), ippStsSizeErr); /* let P>Q */ //IPP_BADARG_RET(0>=cpBN_cmp(pFactorP,pFactorQ), ippStsBadArgErr); IPP_BAD_PTR1_RET(pCrtExpP); IPP_BADARG_RET(!BN_VALID_ID(pCrtExpP), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pCrtExpP)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pCrtExpP), BN_SIZE(pCrtExpP)) > RSA_PRV_KEY_BITSIZE_P(pKey), ippStsSizeErr); IPP_BAD_PTR1_RET(pCrtExpQ); IPP_BADARG_RET(!BN_VALID_ID(pCrtExpQ), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pCrtExpQ)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pCrtExpQ), BN_SIZE(pCrtExpQ)) > RSA_PRV_KEY_BITSIZE_Q(pKey), ippStsSizeErr); IPP_BAD_PTR1_RET(pInverseQ); IPP_BADARG_RET(!BN_VALID_ID(pInverseQ), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pInverseQ)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pInverseQ), BN_SIZE(pInverseQ)) > RSA_PRV_KEY_BITSIZE_P(pKey), ippStsSizeErr); /* set bitsize(N) = 0, so the key context is not ready */ RSA_PRV_KEY_BITSIZE_N(pKey) = 0; RSA_PRV_KEY_BITSIZE_D(pKey) = 0; /* setup montgomery engine P */ gsModEngineInit(RSA_PRV_KEY_PMONT(pKey), (Ipp32u*)BN_NUMBER(pFactorP), cpBN_bitsize(pFactorP), MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); /* setup montgomery engine Q */ gsModEngineInit(RSA_PRV_KEY_QMONT(pKey), (Ipp32u*)BN_NUMBER(pFactorQ), cpBN_bitsize(pFactorQ), MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); /* actual size of key components */ RSA_PRV_KEY_BITSIZE_P(pKey) = cpBN_bitsize(pFactorP); RSA_PRV_KEY_BITSIZE_Q(pKey) = cpBN_bitsize(pFactorQ); /* store CTR's exp dp */ ZEXPAND_COPY_BNU(RSA_PRV_KEY_DP(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_P(pKey)), BN_NUMBER(pCrtExpP), BN_SIZE(pCrtExpP)); /* store CTR's exp dq */ ZEXPAND_COPY_BNU(RSA_PRV_KEY_DQ(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_Q(pKey)), BN_NUMBER(pCrtExpQ), BN_SIZE(pCrtExpQ)); /* store CTR's invQ */ ZEXPAND_COPY_BNU(RSA_PRV_KEY_INVQ(pKey), BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_P(pKey)), BN_NUMBER(pInverseQ), BN_SIZE(pInverseQ)); /* setup montgomery engine N = P*Q */ { BNU_CHUNK_T* pN = MOD_MODULUS(RSA_PRV_KEY_NMONT(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_P(pKey) + RSA_PRV_KEY_BITSIZE_Q(pKey)); cpMul_BNU_school(pN, BN_NUMBER(pFactorP), BN_SIZE(pFactorP), BN_NUMBER(pFactorQ), BN_SIZE(pFactorQ)); gsModEngineInit(RSA_PRV_KEY_NMONT(pKey), (Ipp32u*)MOD_MODULUS(RSA_PRV_KEY_NMONT(pKey)), RSA_PRV_KEY_BITSIZE_P(pKey) + RSA_PRV_KEY_BITSIZE_Q(pKey), MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); FIX_BNU(pN, nsN); RSA_PRV_KEY_BITSIZE_N(pKey) = BITSIZE_BNU(pN, nsN); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_setpublickey.c000066400000000000000000000063571470420105600254630ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_SetPublicKey() // */ #include "owncp.h" #include "pcpbn.h" #include "pcpngrsa.h" /*F* // Name: ippsRSA_SetPublicKey // // Purpose: Set up the RSA public key // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // NULL == pPublicExp // NULL == pKey // // ippStsContextMatchErr !BN_VALID_ID(pModulus) // !BN_VALID_ID(pPublicExp) // !RSA_PUB_KEY_VALID_ID() // // ippStsOutOfRangeErr 0 >= pModulus // 0 >= pPublicExp // // ippStsSizeErr bitsize(pModulus) exceeds requested value // bitsize(pPublicExp) exceeds requested value // // ippStsNoErr no error // // Parameters: // pModulus pointer to modulus (N) // pPublicExp pointer to public exponent (E) // pKey pointer to the key context *F*/ IPPFUN(IppStatus, ippsRSA_SetPublicKey,(const IppsBigNumState* pModulus, const IppsBigNumState* pPublicExp, IppsRSAPublicKeyState* pKey)) { IPP_BAD_PTR1_RET(pKey); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BAD_PTR1_RET(pModulus); IPP_BADARG_RET(!BN_VALID_ID(pModulus), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pModulus)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pModulus), BN_SIZE(pModulus)) > RSA_PUB_KEY_MAXSIZE_N(pKey), ippStsSizeErr); IPP_BAD_PTR1_RET(pPublicExp); IPP_BADARG_RET(!BN_VALID_ID(pPublicExp), ippStsContextMatchErr); IPP_BADARG_RET(!(0 < cpBN_tst(pPublicExp)), ippStsOutOfRangeErr); IPP_BADARG_RET(BITSIZE_BNU(BN_NUMBER(pPublicExp), BN_SIZE(pPublicExp)) > RSA_PUB_KEY_MAXSIZE_E(pKey), ippStsSizeErr); { RSA_PUB_KEY_BITSIZE_N(pKey) = 0; RSA_PUB_KEY_BITSIZE_E(pKey) = 0; /* store E */ ZEXPAND_COPY_BNU(RSA_PUB_KEY_E(pKey), BITS_BNU_CHUNK(RSA_PUB_KEY_MAXSIZE_E(pKey)), BN_NUMBER(pPublicExp), BN_SIZE(pPublicExp)); /* setup montgomery engine */ gsModEngineInit(RSA_PUB_KEY_NMONT(pKey), (Ipp32u*)BN_NUMBER(pModulus), cpBN_bitsize(pModulus), MOD_ENGINE_RSA_POOL_SIZE, gsModArithRSA()); RSA_PUB_KEY_BITSIZE_N(pKey) = cpBN_bitsize(pModulus); RSA_PUB_KEY_BITSIZE_E(pKey) = cpBN_bitsize(pPublicExp); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_sizeof_privkey1.h000066400000000000000000000023561470420105600261110ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // */ static int cpSizeof_RSA_privateKey1(int rsaModulusBitSize, int privateExpBitSize) { int prvExpLen = BITS_BNU_CHUNK(privateExpBitSize); int modulusLen32 = BITS2WORD32_SIZE(rsaModulusBitSize); int montNsize; rsaMontExpGetSize(modulusLen32, &montNsize); return (Ipp32s)sizeof(IppsRSAPrivateKeyState) + prvExpLen * (Ipp32s)sizeof(BNU_CHUNK_T) + (Ipp32s)sizeof(BNU_CHUNK_T) - 1 + montNsize; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_sizeof_privkey2.h000066400000000000000000000034021470420105600261030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // */ static int cpSizeof_RSA_privateKey2(int factorPbitSize, int factorQbitSize) { int factorPlen = BITS_BNU_CHUNK(factorPbitSize); int factorQlen = BITS_BNU_CHUNK(factorQbitSize); int factorPlen32 = BITS2WORD32_SIZE(factorPbitSize); int factorQlen32 = BITS2WORD32_SIZE(factorQbitSize); int rsaModulusLen32 = BITS2WORD32_SIZE(factorPbitSize + factorQbitSize); int montPsize; int montQsize; int montNsize; rsaMontExpGetSize(factorPlen32, &montPsize); rsaMontExpGetSize(factorQlen32, &montQsize); rsaMontExpGetSize(rsaModulusLen32, &montNsize); return (Ipp32s)sizeof(IppsRSAPrivateKeyState) + factorPlen * (Ipp32s)sizeof(BNU_CHUNK_T) /* dp slot */ + factorQlen * (Ipp32s)sizeof(BNU_CHUNK_T) /* dq slot */ + factorPlen * (Ipp32s)sizeof(BNU_CHUNK_T) /* qinv slot */ + (Ipp32s)sizeof(BNU_CHUNK_T) - 1 /* alignment */ + montPsize + montQsize + montNsize; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_sizeof_pubkey.h000066400000000000000000000024351470420105600256340ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // */ /* compute size of RSA public key context */ static int cpSizeof_RSA_publicKey(int rsaModulusBitSize, int publicExpBitSize) { int pubExpLen = BITS_BNU_CHUNK(publicExpBitSize); int modulusLen32 = BITS2WORD32_SIZE(rsaModulusBitSize); int montNsize; rsaMontExpGetSize(modulusLen32, &montNsize); return (Ipp32s)sizeof(IppsRSAPublicKeyState) + pubExpLen*(Ipp32s)sizeof(BNU_CHUNK_T) + (Ipp32s)sizeof(BNU_CHUNK_T)-1 /* alignment */ + montNsize; } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_validatekeys.c000066400000000000000000000306201470420105600254330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA Functions // // Contents: // ippsRSA_ValidateKeys() // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcpprimeg.h" #include "pcpprng.h" #include "pcpngrsa.h" #include "pcpprime_isco.h" #include "pcpprime_isprob.h" /*F* // Name: ippsRSA_ValidateKeys // // Purpose: Validate RSA keys // // Returns: Reason: // ippStsNullPtrErr NULL == pPublicKey // NULL == pPrivateKeyType2 // NULL == pPrivateKeyType1 // NULL == pBuffer // NULL == pPrimeGen // NULL == rndFunc // NULL == pResult // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID(pPublicKey) // !RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2) // !RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1) // !PRIME_VALID_ID(pPrimeGen) // // ippStsIncompleteContextErr public and.or private key is not set up // // ippStsSizeErr PRIME_MAXBITSIZE(pPrimeGen) < factorPbitSize // // ippStsBadArgErr nTrials < 1 // // ippStsNoErr no error // // Parameters: // pResult pointer to the validation result // pPublicKey pointer to the public key context // pPrivateKeyType2 pointer to the private key type2 context // pPrivateKeyType1 (optional) pointer to the private key type1 context // pBuffer pointer to the temporary buffer // nTrials parameter of Miller-Rabin Test // pPrimeGen pointer to the Prime generator context // rndFunc external PRNG // pRndParam pointer to the external PRNG parameters *F*/ /* // make sure D*E = 1 mod(phi(P,Q)) // where phi(P,Q) = (P-1)*(Q-1) */ static int isValidPriv1_classic(const BNU_CHUNK_T* pN, int nsN, const BNU_CHUNK_T* pE, int nsE, const BNU_CHUNK_T* pD, int nsD, const BNU_CHUNK_T* pFactorP, int nsP, const BNU_CHUNK_T* pFactorQ, int nsQ, BNU_CHUNK_T* pBuffer) { BNU_CHUNK_T* pPhi = pBuffer; BNU_CHUNK_T* pProduct = pPhi + nsN; BNU_CHUNK_T c = cpSub_BNU(pPhi, pN, pFactorP, nsP); int prodLen; if (nsN>1) cpDec_BNU(pPhi + nsP, pN + nsP, nsQ, c); c = cpSub_BNU(pPhi, pPhi, pFactorQ, nsQ); if (nsN>1) cpDec_BNU(pPhi + nsQ, pPhi + nsQ, nsP, c); cpInc_BNU(pPhi, pPhi, nsP + nsQ, 1); cpMul_BNU_school(pProduct, pE, nsE, pD, nsD); prodLen = cpMod_BNU(pProduct, nsE + nsD, pPhi, nsN); return 1 == cpEqu_BNU_CHUNK(pProduct, prodLen, 1) ? IPP_IS_VALID : IPP_IS_INVALID; } /* // make sure D*E = 1 mod(lcm(P-1,Q-1)) // where lcm(P-1,Q-1) = (P-1)*(Q-1)/gcd(P-1,Q-1) */ static int isValidPriv1_rsa(const BNU_CHUNK_T* pN, int nsN, const BNU_CHUNK_T* pE, int nsE, const BNU_CHUNK_T* pD, int nsD, BNU_CHUNK_T* pFactorP, int nsP, BNU_CHUNK_T* pFactorQ, int nsQ, BNU_CHUNK_T* pBuffer) { __ALIGN8 IppsBigNumState tmpBN1; __ALIGN8 IppsBigNumState tmpBN2; __ALIGN8 IppsBigNumState tmpBN3; BNU_CHUNK_T* pProduct = pBuffer; BNU_CHUNK_T* pGcd = pProduct + (nsN + 1); BNU_CHUNK_T* pLcm; int nsLcm; int prodLen; pBuffer = pGcd + (nsP + 1) * 2; /* P = P-1 and Q = Q-1 */ pFactorP[0]--; pFactorQ[0]--; /* compute product (P-1)*(Q-1) = P*Q -P -Q +1 = N -(P-1) -(Q-1) -1 */ { BNU_CHUNK_T c = cpSub_BNU(pProduct, pN, pFactorP, nsP); if (nsN>1) cpDec_BNU(pProduct + nsP, pN + nsP, nsQ, c); c = cpSub_BNU(pProduct, pProduct, pFactorQ, nsQ); if (nsN>1) cpDec_BNU(pProduct + nsQ, pProduct + nsQ, nsP, c); cpDec_BNU(pProduct, pProduct, nsN, 1); } /* compute gcd(p-1, q-1) */ BN_Make(pGcd, pGcd + nsP + 1, nsP, &tmpBN1); /* BN(gcd) */ BN_SIZE(&tmpBN1) = nsP; BN_Make(pFactorP, pBuffer, nsP, &tmpBN2); /* BN(P-1) */ BN_SIZE(&tmpBN2) = nsP; BN_Make(pFactorQ, pBuffer + nsP + 1, nsQ, &tmpBN3); /* BN(Q-1) */ BN_SIZE(&tmpBN3) = nsQ; ippsGcd_BN(&tmpBN2, &tmpBN3, &tmpBN1); /* compute lcm(p-1, q-1) = (p-1)(q-1)/gcd(p-1, q-1) */ pLcm = pBuffer; cpDiv_BNU(pLcm, &nsLcm, pProduct, nsN, pGcd, BN_SIZE(&tmpBN1)); /* test E*D = 1 mod lcm */ cpMul_BNU_school(pProduct, pE, nsE, pD, nsD); prodLen = cpMod_BNU(pProduct, nsE + nsD, pLcm, nsLcm); /* restore P and Q */ pFactorP[0]++; pFactorQ[0]++; return 1 == cpEqu_BNU_CHUNK(pProduct, prodLen, 1) ? IPP_IS_VALID : IPP_IS_INVALID; } IPPFUN(IppStatus, ippsRSA_ValidateKeys,(int* pResult, const IppsRSAPublicKeyState* pPublicKey, const IppsRSAPrivateKeyState* pPrivateKeyType2, const IppsRSAPrivateKeyState* pPrivateKeyType1, /*optional */ Ipp8u* pBuffer, int nTrials, IppsPrimeState* pPrimeGen, /*NULL */ IppBitSupplier rndFunc, void* pRndParam)) { IPP_BAD_PTR1_RET(pPublicKey); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pPublicKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pPublicKey), ippStsIncompleteContextErr); IPP_BAD_PTR1_RET(pPrivateKeyType2); IPP_BADARG_RET(!RSA_PRV_KEY2_VALID_ID(pPrivateKeyType2), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrivateKeyType2), ippStsIncompleteContextErr); if(pPrivateKeyType1) { /* pPrivateKeyType1 is optional */ IPP_BADARG_RET(!RSA_PRV_KEY1_VALID_ID(pPrivateKeyType1), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrivateKeyType1), ippStsIncompleteContextErr); } IPP_BAD_PTR3_RET(pResult, pBuffer, rndFunc); IPP_UNREFERENCED_PARAMETER(pPrimeGen); { /* E key component */ BNU_CHUNK_T* pExpE = RSA_PUB_KEY_E(pPublicKey); cpSize nsE = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_E(pPublicKey)); /* N key component */ BNU_CHUNK_T* pN = MOD_MODULUS(RSA_PUB_KEY_NMONT(pPublicKey)); cpSize nsN = MOD_LEN(RSA_PUB_KEY_NMONT(pPublicKey)); /* P, Q, dP, dQ, invQ key components */ gsModEngine* pMontP = RSA_PRV_KEY_PMONT(pPrivateKeyType2); gsModEngine* pMontQ = RSA_PRV_KEY_QMONT(pPrivateKeyType2); BNU_CHUNK_T* pFactorP= MOD_MODULUS(pMontP); BNU_CHUNK_T* pFactorQ= MOD_MODULUS(pMontQ); BNU_CHUNK_T* pExpDp = RSA_PRV_KEY_DP(pPrivateKeyType2); BNU_CHUNK_T* pExpDq = RSA_PRV_KEY_DQ(pPrivateKeyType2); BNU_CHUNK_T* pInvQ = RSA_PRV_KEY_INVQ(pPrivateKeyType2); int factorPbitSize = RSA_PRV_KEY_BITSIZE_P(pPrivateKeyType2); int factorQbitSize = RSA_PRV_KEY_BITSIZE_Q(pPrivateKeyType2); cpSize nsP = MOD_LEN(RSA_PRV_KEY_PMONT(pPrivateKeyType2)); cpSize nsQ = MOD_LEN(RSA_PRV_KEY_QMONT(pPrivateKeyType2)); int ret = IPP_IS_VALID; BNU_CHUNK_T* pTmp = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pBuffer, (int)sizeof(BNU_CHUNK_T))); BNU_CHUNK_T* pFreeBuffer = pTmp+nsN; /* choose security parameter */ int mrTrials = (nTrials<1)? MR_rounds_p80(factorPbitSize) : nTrials; IppStatus sts = ippStsNoErr; do { /* test if E is odd and 3 <= E < N */ if(0==(pExpE[0]&1)) { ret = IPP_IS_INVALID; break; } if(1==nsE && pExpE[0]<3) { ret = IPP_IS_INVALID; break; } if(0 <= cpCmp_BNU(pExpE, nsE, pN, nsN)) { ret = IPP_IS_INVALID; break; } /* test if N==P*Q */ cpMul_BNU_school(pFreeBuffer, pFactorP, nsP, pFactorQ, nsQ); { cpSize ns = cpFix_BNU(pFreeBuffer, nsP+nsQ); if(cpCmp_BNU(pFreeBuffer, ns, pN, nsN)) { ret = IPP_IS_INVALID; break; } } /* test if PubKey(N)==PrivKeytype2(N) */ if(cpCmp_BNU(pN, nsN, MOD_MODULUS(RSA_PRV_KEY_NMONT(pPrivateKeyType2)), MOD_LEN(RSA_PRV_KEY_NMONT(pPrivateKeyType2)))) { ret = IPP_IS_INVALID; break; } /* test if PubKey(N)==PrivKeytype1(N) */ if(pPrivateKeyType1) { if(cpCmp_BNU(pN, nsN, MOD_MODULUS(RSA_PRV_KEY_NMONT(pPrivateKeyType1)), MOD_LEN(RSA_PRV_KEY_NMONT(pPrivateKeyType1)))) { ret = IPP_IS_INVALID; break; } } /* test if P is prime */ //if(0==cpIsProbablyPrime(pFactorP, factorPbitSize, mrTrials, // rndFunc, pRndParam, // pMontP, pFreeBuffer)) { // ret = IPP_IS_COMPOSITE; // break; //} { int r = cpIsProbablyPrime(pFactorP, factorPbitSize, mrTrials, rndFunc, pRndParam, pMontP, pFreeBuffer); if(0>r) { sts = ippStsErr; break; } if(0==r) { ret = IPP_IS_COMPOSITE; break; } } /* test if E and (P-1) co-prime */ cpDec_BNU(pTmp, pFactorP, nsP, 1); if(0 == cpIsCoPrime(pExpE, nsE, pTmp, nsP, pFreeBuffer)) { ret = IPP_IS_INVALID; break; } /* test if E*dP = 1 mod (P-1) */ cpMul_BNU_school(pFreeBuffer, pExpDp, nsP, pExpE, nsE); cpMod_BNU(pFreeBuffer, nsP+nsE, pTmp, nsP); if(!cpEqu_BNU_CHUNK(pFreeBuffer, nsP, 1)) { ret = IPP_IS_INVALID; break; } /* test if Q is prime */ //if(0==cpIsProbablyPrime(pFactorQ, factorQbitSize, mrTrials, // rndFunc, pRndParam, // pMontQ, pFreeBuffer)) { // ret = IPP_IS_COMPOSITE; // break; //} { int r = cpIsProbablyPrime(pFactorQ, factorQbitSize, mrTrials, rndFunc, pRndParam, pMontQ, pFreeBuffer); if(0>r) { sts = ippStsErr; break; } if(0==r) { ret = IPP_IS_COMPOSITE; break; } } /* test if E and (Q-1) co-prime */ cpDec_BNU(pTmp, pFactorQ, nsQ, 1); if(0 == cpIsCoPrime(pExpE, nsE, pTmp, nsQ, pFreeBuffer)) { ret = IPP_IS_INVALID; break; } /* test if E*dQ = 1 mod (Q-1) */ cpMul_BNU_school(pFreeBuffer, pExpDq, nsQ, pExpE, nsE); cpMod_BNU(pFreeBuffer, nsQ+nsE, pTmp, nsQ); if(!cpEqu_BNU_CHUNK(pFreeBuffer, nsQ, 1)) { ret = IPP_IS_INVALID; break; } /* test if 1==(Q*Qinv) mod P */ cpMul_BNU_school(pFreeBuffer, pInvQ, nsP, pFactorQ,nsQ); cpMod_BNU(pFreeBuffer, nsP+nsQ, pFactorP, nsP); if(!cpEqu_BNU_CHUNK(pFreeBuffer, nsP, 1)) { ret = IPP_IS_INVALID; break; } /* test private exponent (optional) */ if(pPrivateKeyType1) { const BNU_CHUNK_T* pExpD = RSA_PRV_KEY_D(pPrivateKeyType1); cpSize nsD = nsN; int resilt1 = isValidPriv1_classic(pN,nsN, pExpE,nsE, pExpD,nsD, pFactorP,nsP, pFactorQ,nsQ, pTmp); int resilt2 = isValidPriv1_rsa(pN,nsN, pExpE,nsE, pExpD,nsD, pFactorP,nsP, pFactorQ,nsQ, pTmp); if(IPP_IS_VALID!=resilt1 && IPP_IS_VALID!=resilt2) { ret = IPP_IS_INVALID; break; } } } while(0); *pResult = ret; return sts; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsa_verifysign_pkcs1v15.h000066400000000000000000000041331470420105600265750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "pcptool.h" #include "pcprsa_emsa_pkcs1v15.h" static int VerifySign(const Ipp8u* pMsg, int msgLen, /* message representation */ const Ipp8u* pSalt, int saltLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, BNU_CHUNK_T* pBuffer) { /* size of RSA modulus in bytes and chunks */ cpSize rsaBits = RSA_PUB_KEY_BITSIZE_N(pKey); cpSize k = BITS2WORD8_SIZE(rsaBits); cpSize nsN = BITS_BNU_CHUNK(rsaBits); /* temporary BNs */ __ALIGN8 IppsBigNumState bnC; __ALIGN8 IppsBigNumState bnP; /* make BNs */ BN_Make(pBuffer, pBuffer + nsN + 1, nsN, &bnC); pBuffer += (nsN + 1) * 2; BN_Make(pBuffer, pBuffer + nsN + 1, nsN, &bnP); pBuffer += (nsN + 1) * 2; /* // public-key operation */ ippsSetOctString_BN(pSign, k, &bnP); gsRSApub_cipher(&bnC, &bnP, pKey, pBuffer); /* convert EM into the string */ ippsGetOctString_BN((Ipp8u*)(BN_BUFFER(&bnC)), k, &bnC); /* EMSA-PKCS-v1_5 encoding */ if (EMSA_PKCSv15(pMsg, msgLen, pSalt, saltLen, (Ipp8u*)(BN_NUMBER(&bnC)), k)) { *pIsValid = 1 == EquBlock((Ipp8u*)(BN_BUFFER(&bnC)), (Ipp8u*)(BN_NUMBER(&bnC)), k); return 1; } else return 0; } cryptography-primitives-1.0.0/sources/ippcp/pcprsadecrypt_oaep.c000066400000000000000000000204261470420105600252700ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSAES-OAEP Encryption/Decryption Functions // // Contents: // ippsRSADecrypt_OAEP() // */ #include "owndefs.h" #include "owncp.h" #include "pcptool.h" #include "pcpngrsa.h" #include "hash/pcphash.h" // ICX compiler optimizations lead to incorrect execution on windows #if(_IPP32E>=_IPP32E_K0) && defined (__INTEL_LLVM_COMPILER) && defined( _WIN64 ) #pragma optimize( "", off ) #endif /*F* // Name: ippsRSADecrypt_OAEP // // Purpose: Performs RSAES-OAEP decryprion scheme // // Returns: Reason: // ippStsNotSupportedModeErr unknown hashAlg // // ippStsNullPtrErr NULL == pKey // NULL == pSrc // NULL == pLab // NULL == pDst // NULL == pDstLen // NULL == pBuffer // // ippStsLengthErr labLen <0 // RSAsize < 2*hashLen +2 // // ippStsIncompleteContextErr private key is not set up // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // // ippStsOutOfRangeErr ciphertext > RSA(N) // // ippStsUnderRunErr decoding error // // ippStsNoErr no error // // Parameters: // pSrc pointer to the ciphertext // assumed that length of the ciphertext is equal to k - sizeof RSA modulus in bytes // pLab (optional) pointer to the label associated with plaintext // labLen label length (bytes) // pDst pointer to the plaintext // pDstLen pointer to the plaintext length // assumed that length of the recovered message is at least k-hashLen*2-2 bytes; // maximum message length is (k-hashLen*2-2) bytes and is for chosen RSA and Hash-function // pKey pointer to the RSA private key context // hashAlg hash alg ID // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSADecrypt_OAEP, (const Ipp8u* pSrc, const Ipp8u* pLab, int labLen, Ipp8u* pDst, int* pDstLen, const IppsRSAPrivateKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pScratchBuffer)) { int hashLen; /* test hash algorithm ID */ hashAlg = cpValidHashAlg(hashAlg); IPP_BADARG_RET(ippHashAlg_Unknown == hashAlg, ippStsNotSupportedModeErr); /* test data pointer */ IPP_BAD_PTR3_RET(pSrc, pDst, pDstLen); IPP_BADARG_RET(!pLab && labLen, ippStsNullPtrErr); IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test hash length */ IPP_BADARG_RET(labLen < 0, ippStsLengthErr); hashLen = cpHashSize(hashAlg); /* test compatibility of RSA and hash length */ IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)) < (2 * hashLen + 2), ippStsLengthErr); { /* size of RSA modulus in bytes and chunks */ int k = BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_N(pKey)); /* align resource */ BNU_CHUNK_T* pResource = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T))); /* temporary BN */ __ALIGN8 IppsBigNumState tmpBN; BN_Make(pResource, pResource+ nsN + 1, nsN, &tmpBN); pResource += (nsN + 1) * 2; /* update buffer pointer */ ippsSetOctString_BN(pSrc, k, &tmpBN); /* convert ciphertext to BigNum */ /* make sure ciphertext < RSA modulus N */ IPP_BADARG_RET(0 <= cpCmp_BNU(BN_NUMBER(&tmpBN), BN_SIZE(&tmpBN), MOD_MODULUS(RSA_PRV_KEY_NMONT(pKey)), MOD_LEN(RSA_PRV_KEY_NMONT(pKey))), ippStsOutOfRangeErr); /* RSA decryption */ if (RSA_PRV_KEY1_VALID_ID(pKey)) gsRSAprv_cipher(&tmpBN, &tmpBN, pKey, pResource); else gsRSAprv_cipher_crt(&tmpBN, &tmpBN, pKey, pResource); /* // EME-OAEP decoding */ { Ipp8u* pEM = (Ipp8u*)(BN_BUFFER(&tmpBN)); Ipp8u* pBuffer = (Ipp8u*)BN_NUMBER(&tmpBN); int i; /* convert RSA encoded into EM */ for (i = 0; i < k; i++) { pEM[i] = pBuffer[k - 1 - i]; } /* // OAEP EM decoding, EM = Y || maskedSeed || maskedDB */ { /* check that Y == 0 */ BNU_CHUNK_T res = cpIsZero_ct(pEM[0]); Ipp8u* pSeed = pEM + 1; Ipp8u* pDB = pEM + 1 + hashLen; /* DB = lHash || PS || Msg */ int dbLen = k - 1 - hashLen; int maxMsgLen = dbLen - hashLen - 1; /* seed = maskedSeed ^ seedMask, seedMask = MGF(maskedDB, hashLen) */ ippsMGF(pDB, dbLen, pBuffer, hashLen, hashAlg); XorBlock(pSeed, pBuffer, pSeed, hashLen); /* DB = maskedDB ^ dbMask, dbMask = MGF (seed, dbLen) */ ippsMGF(pSeed, hashLen, pBuffer, dbLen, hashAlg); XorBlock(pDB, pBuffer, pDB, dbLen); /* re-compute Hash(Label) and compare with lHash */ ippsHashMessage(pLab, labLen, pBuffer, hashAlg); res &= cpIsEquBlock_ct(pDB, pBuffer, hashLen); /* detect the padding consists of a number of 0x00-bytes, followed by a 0x01 */ BNU_CHUNK_T byte_01_found = 0; BNU_CHUNK_T byte_01_idx = 0; for (i = hashLen; i < dbLen; i++) { BNU_CHUNK_T byte_00 = cpIsZero_ct(pDB[i]); /* mask if byte is 0x00 */ BNU_CHUNK_T byte_01 = cpIsZero_ct(pDB[i] ^ 0x01); /* mask if byte is 0x01 */ /* set index of byte 01_idx if byte 01 found */ byte_01_idx = cpSelect_ct(~byte_01_found & byte_01, (BNU_CHUNK_T)i, byte_01_idx); /* set flag byte_01_found */ byte_01_found |= byte_01; /* update EM encoding result */ res &= (byte_01_found | byte_00); } /* update EM encoding result if byte_01_found */ res &= byte_01_found; /* copy decoded message to pDst */ { /* move decoded message by (maxMsgLen-msgLen) left */ int msgIdx = (int)byte_01_idx + 1; /* decoded message index inside DB */ int msgLen = dbLen - msgIdx; /* length of decoded message */ BNU_CHUNK_T mask; for(msgIdx = 1; msgIdx < maxMsgLen; msgIdx <<= 1) { mask = cpIsEqu_ct((BNU_CHUNK_T)(msgIdx & (maxMsgLen - msgLen)), (BNU_CHUNK_T)msgIdx); for(i = hashLen+1; i < (dbLen-msgIdx); i++) pDB[i] = cpSelect_ct_8u(mask, pDB[i + msgIdx], pDB[i]); } /* copy decoded message */ for(i = 0; i < maxMsgLen; i++) { mask = res & cpIsLt_ct((BNU_CHUNK_T)i, (BNU_CHUNK_T)msgLen); pDst[i] = cpSelect_ct_8u(mask, pDB[i + hashLen + 1], pDst[i]); } /* decoded message length */ *pDstLen = cpSelect_ct_int(res, msgLen, -1); } /* clean */ PurgeBlock(pEM, k); PurgeBlock(pBuffer, k); /* return error status if is */ return (IppStatus)cpSelect_ct_int(res, ippStsNoErr, ippStsUnderRunErr); } } } } #if(_IPP32E>=_IPP32E_K0) && defined (__INTEL_LLVM_COMPILER) && defined( _WIN64 ) #pragma optimize( "", on ) #endif cryptography-primitives-1.0.0/sources/ippcp/pcprsadecrypt_oaep_rmf.c000066400000000000000000000203531470420105600261330ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // RSAES-OAEP Encryption/Decryption Functions // // Contents: // ippsRSADecrypt_OAEP_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcptool.h" #include "pcpngrsa.h" #include "hash/pcphash_rmf.h" // ICX compiler optimizations lead to incorrect execution on windows #if(_IPP32E>=_IPP32E_K0) && defined (__INTEL_LLVM_COMPILER) && defined( _WIN64 ) #pragma optimize( "", off ) #endif /*F* // Name: ippsRSADecrypt_OAEP_rmf // // Purpose: Performs RSAES-OAEP decryprion scheme // // Returns: Reason: // ippStsNotSupportedModeErr unknown hashAlg // // ippStsNullPtrErr NULL == pKey // NULL == pSrc // NULL == pLab // NULL == pDst // NULL == pDstLen // NULL == pMethod // NULL == pBuffer // // ippStsLengthErr labLen <0 // RSAsize < 2*hashLen +2 // // ippStsIncompleteContextErr private key is not set up // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // // ippStsOutOfRangeErr ciphertext > RSA(N) // // ippStsUnderRunErr decoding error // // ippStsNoErr no error // // Parameters: // pSrc pointer to the ciphertext // assumed that length of the ciphertext is equal to k - sizeof RSA modulus in bytes // pLab (optional) pointer to the label associated with plaintext // labLen label length (bytes) // pDst pointer to the encoded plaintext // assumed that length of the recovered message is at least k-hashLen*2-2 bytes; // maximum message length is (k-hashLen*2-2) bytes and is for chosen RSA and Hash-function // pDstLen pointer to the plaintext length // pKey pointer to the RSA private key context // pMethod hash methods // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSADecrypt_OAEP_rmf, (const Ipp8u* pSrc, const Ipp8u* pLab, int labLen, Ipp8u* pDst, int* pDstLen, const IppsRSAPrivateKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { int hashLen; /* test data pointer */ IPP_BAD_PTR4_RET(pSrc, pDst, pDstLen, pMethod); IPP_BADARG_RET(!pLab && labLen, ippStsNullPtrErr); IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test hash length */ IPP_BADARG_RET(labLen < 0, ippStsLengthErr); hashLen = pMethod->hashLen; /* test compatibility of RSA and hash length */ IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)) < (2 * hashLen + 2), ippStsLengthErr); { /* size of RSA modulus in bytes and chunks */ int k = BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_N(pKey)); /* align resource */ BNU_CHUNK_T* pResource = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T))); /* temporary BN */ __ALIGN8 IppsBigNumState tmpBN; BN_Make(pResource, pResource+nsN+1, nsN, &tmpBN); pResource += (nsN + 1) * 2; /* update buffer pointer */ ippsSetOctString_BN(pSrc, k, &tmpBN); /* convert ciphertext to BigNum */ /* make sure ciphertext < RSA modulus N */ IPP_BADARG_RET(0 <= cpCmp_BNU(BN_NUMBER(&tmpBN), BN_SIZE(&tmpBN), MOD_MODULUS(RSA_PRV_KEY_NMONT(pKey)), MOD_LEN(RSA_PRV_KEY_NMONT(pKey))), ippStsOutOfRangeErr); /* RSA decryption */ if (RSA_PRV_KEY1_VALID_ID(pKey)) gsRSAprv_cipher(&tmpBN, &tmpBN, pKey, pResource); else gsRSAprv_cipher_crt(&tmpBN, &tmpBN, pKey, pResource); /* // EME-OAEP decoding */ { Ipp8u* pEM = (Ipp8u*)(BN_BUFFER(&tmpBN)); Ipp8u* pBuffer = (Ipp8u*)BN_NUMBER(&tmpBN); int i; /* convert RSA encoded into EM */ for (i = 0; i < k; i++) { pEM[i] = pBuffer[k-1-i]; } /* // OAEP EM decoding, EM = Y || maskedSeed || maskedDB */ { /* check that Y == 0 */ BNU_CHUNK_T res = cpIsZero_ct(pEM[0]); Ipp8u* pSeed = pEM + 1; Ipp8u* pDB = pEM + 1 + hashLen; /* DB = lHash || PS || Msg */ int dbLen = k - 1 - hashLen; int maxMsgLen = dbLen - hashLen - 1; /* seed = maskedSeed ^ seedMask, seedMask = MGF(maskedDB, hashLen) */ ippsMGF1_rmf(pDB, dbLen, pBuffer, hashLen, pMethod); XorBlock(pSeed, pBuffer, pSeed, hashLen); /* DB = maskedDB ^ dbMask, dbMask = MGF (seed, dbLen) */ ippsMGF1_rmf(pSeed, hashLen, pBuffer, dbLen, pMethod); XorBlock(pDB, pBuffer, pDB, dbLen); /* re-compute Hash(Label) and compare with lHash */ ippsHashMessage_rmf(pLab, labLen, pBuffer, pMethod); res &= cpIsEquBlock_ct(pDB, pBuffer, hashLen); /* detect the padding consists of a number of 0x00-bytes, followed by a 0x01 */ BNU_CHUNK_T byte_01_found = 0; BNU_CHUNK_T byte_01_idx = 0; for (i = hashLen; i < dbLen; i++) { BNU_CHUNK_T byte_00 = cpIsZero_ct(pDB[i]); /* mask if byte is 0x00 */ BNU_CHUNK_T byte_01 = cpIsZero_ct(pDB[i] ^ 0x01); /* mask if byte is 0x01 */ /* set index of byte 01_idx if byte 01 found */ byte_01_idx = cpSelect_ct(~byte_01_found & byte_01, (BNU_CHUNK_T)i, byte_01_idx); /* set flag byte_01_found */ byte_01_found |= byte_01; /* update EM encoding result */ res &= (byte_01_found | byte_00); } /* update EM encoding result if byte_01_found */ res &= byte_01_found; /* copy decoded message to pDst */ { /* move decoded message by (maxMsgLen-msgLen) left */ int msgIdx = (int)byte_01_idx + 1; /* decoded message index inside DB */ int msgLen = dbLen - msgIdx; /* length of decoded message */ BNU_CHUNK_T mask; for(msgIdx = 1; msgIdx < maxMsgLen; msgIdx <<= 1) { mask = cpIsEqu_ct((BNU_CHUNK_T)(msgIdx & (maxMsgLen - msgLen)), (BNU_CHUNK_T)msgIdx); for(i = hashLen+1; i < (dbLen-msgIdx); i++) pDB[i] = cpSelect_ct_8u(mask, pDB[i + msgIdx], pDB[i]); } /* copy decoded message */ for(i = 0; i < maxMsgLen; i++) { mask = res & cpIsLt_ct((BNU_CHUNK_T)i, (BNU_CHUNK_T)msgLen); pDst[i] = cpSelect_ct_8u(mask, pDB[i + hashLen + 1], pDst[i]); } /* decoded message length */ *pDstLen = cpSelect_ct_int(res, msgLen, -1); } /* clean */ PurgeBlock(pEM, k); PurgeBlock(pBuffer, k); /* return error status if is */ return (IppStatus)cpSelect_ct_int(res, ippStsNoErr, ippStsUnderRunErr); } } } } #if(_IPP32E>=_IPP32E_K0) && defined (__INTEL_LLVM_COMPILER) && defined( _WIN64 ) #pragma optimize( "", on ) #endif cryptography-primitives-1.0.0/sources/ippcp/pcprsadecrypt_pkcsv15.c000066400000000000000000000114061470420105600256360ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA-PKCS1-v1_5 Encryption Scheme // // Contents: // ippsRSADecrypt_PKCSv15() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "pcptool.h" static Ipp32u NonZeroBlockLen(const Ipp8u* pData, int dataLen) { int i; for(i=0; i emLen); /* // decoded message format: // EM = 00 || 02 || PS || 00 || Msg // len(PS) >= 8 */ errDecodeFlag |= (0x00 != pEM[0]); errDecodeFlag |= (0x02 != pEM[1]); errDecodeFlag |= (0x00 != pEM[3+psLen-1]); CopyBlock(pEM+3+psLen, pMsg, msgLen); *pMsgLen = msgLen; return !errDecodeFlag; } /* // returns 0 decryption error / 1 OK */ static int Decryption(const Ipp8u* pCipherTxt, Ipp8u* pMsg, int* pMsgLen, const IppsRSAPrivateKeyState* pKey, BNU_CHUNK_T* pBuffer) { /* size of RSA modulus in bytes and chunks */ int k = BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PRV_KEY_BITSIZE_N(pKey)); /* temporary BN */ __ALIGN8 IppsBigNumState tmpBN; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &tmpBN); /* update buffer pointer */ pBuffer += (nsN+1)*2; /* // private-key operation */ ippsSetOctString_BN(pCipherTxt, k, &tmpBN); if( 0 <= cpCmp_BNU(BN_NUMBER(&tmpBN), BN_SIZE(&tmpBN), MOD_MODULUS(RSA_PRV_KEY_NMONT(pKey)), nsN) ) return 0; if(RSA_PRV_KEY1_VALID_ID(pKey)) gsRSAprv_cipher(&tmpBN, &tmpBN, pKey, pBuffer); else gsRSAprv_cipher_crt(&tmpBN, &tmpBN, pKey, pBuffer); ippsGetOctString_BN((Ipp8u*)(BN_BUFFER(&tmpBN)), k, &tmpBN); /* EME-PKCS-v1_5 decoding */ return DecodeEME_PKCSv15((Ipp8u*)(BN_BUFFER(&tmpBN)), k, pMsg, pMsgLen); } /*F* // Name: ippsRSADecrypt_PKCSv15 // // Purpose: Performs Decryption according to RSA-ES-PKCS1_v1.5 // // Returns: Reason: // ippStsNullPtrErr NULL == pSrc // NULL == pDst // NULL == pDstLen // NULL == pKey // NULL == pBuffer // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // // ippStsIncompleteContextErr private key is not set up // // ippStsSizeErr RSA modulus size too short (k < 11, see PKCS#1) !! runtime error // ippStsPaddingErr pSrc > size of RSA modulus !! runtime error // DecodeEME_PKCS_v1_5 error // ippStsNoErr no error // // Parameters: // pSrc pointer to the ciphertext // pDst pointer to the plaintext // pDstLen pointer to the length (bytes) of decrypted plaintext // pKey pointer to the RSA private key context // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSADecrypt_PKCSv15,(const Ipp8u* pSrc, Ipp8u* pDst, int* pDstLen, const IppsRSAPrivateKeyState* pKey, Ipp8u* pScratchBuffer)) { /* use aligned key context */ IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test data pointer */ IPP_BAD_PTR3_RET(pSrc, pDst, pDstLen); if(RSA_PRV_KEY_BITSIZE_N(pKey) < 11*BYTESIZE) return ippStsSizeErr; { BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))); return Decryption(pSrc, pDst, pDstLen, pKey, pBuffer)? ippStsNoErr : ippStsPaddingErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsaencrypt_oaep.c000066400000000000000000000125321470420105600253010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSAES-OAEP Encryption/Description Functions // // Contents: // ippsRSAEncrypt_OAEP() // */ #include "owndefs.h" #include "owncp.h" #include "pcptool.h" #include "pcpngrsa.h" #include "hash/pcphash.h" /*F* // Name: ippsRSAEncrypt_OAEP // // Purpose: Performs RSAES-OAEP encryprion scheme // // Returns: Reason: // ippStsNotSupportedModeErr unknown hashAlg // // ippStsNullPtrErr NULL == pKey // NULL == pSrc // NULL == pDst // NULL == pLabel // NULL == pSeed // NULL == pBuffer // // ippStsLengthErr srcLen <0 // labLen <0 // srcLen > RSAsize -2*hashLen -2 // RSAsize < 2*hashLen +2 // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr public key is not set up // // ippStsNoErr no error // // Parameters: // pSrc pointer to the plaintext // srcLen plaintext length (bytes) // pLabel (optional) pointer to the label associated with plaintext // labLen label length (bytes) // pSeed seed string of hashLen size // pDst pointer to the ciphertext (length of pdst is not less then size of RSA modulus) // pKey pointer to the RSA public key context // hashAlg hash alg ID // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSAEncrypt_OAEP,(const Ipp8u* pSrc, int srcLen, const Ipp8u* pLabel, int labLen, const Ipp8u* pSeed, Ipp8u* pDst, const IppsRSAPublicKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pScratchBuffer)) { int hashLen; /* test hash algorithm ID */ hashAlg = cpValidHashAlg(hashAlg); IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); /* test data pointer */ IPP_BAD_PTR3_RET(pSrc,pDst, pSeed); IPP_BADARG_RET(!pLabel && labLen, ippStsNullPtrErr); /* test public key context */ IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test length */ IPP_BADARG_RET(srcLen<0||labLen<0, ippStsLengthErr); hashLen = cpHashSize(hashAlg); /* test compatibility of RSA and hash length */ IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)) < (2*hashLen +2), ippStsLengthErr); /* test compatibility of msg length and other (RSA and hash) lengths */ IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey))-(2*hashLen +2) < srcLen, ippStsLengthErr); { /* size of RSA modulus in bytes and chunks */ int k = BITS2WORD8_SIZE(RSA_PUB_KEY_BITSIZE_N(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_N(pKey)); /* // EME-OAEP encoding */ { Ipp8u seedMask[BITS2WORD8_SIZE(IPP_SHA512_DIGEST_BITSIZE)]; Ipp8u* pMaskedSeed = pDst+1; Ipp8u* pMaskedDB = pDst +hashLen +1; pDst[0] = 0; /* maskedDB = MGF(seed, k-1-hashLen)*/ ippsMGF(pSeed, hashLen, pMaskedDB, k-1-hashLen, hashAlg); /* seedMask = HASH(pLab) */ ippsHashMessage(pLabel, labLen, seedMask, hashAlg); /* maskedDB ^= concat(HASH(pLab),PS,0x01,pSc) */ XorBlock(pMaskedDB, seedMask, pMaskedDB, hashLen); pMaskedDB[k-srcLen-hashLen-2] ^= 0x01; XorBlock(pMaskedDB+k-srcLen-hashLen-2+1, pSrc, pMaskedDB+k-srcLen-hashLen-2+1, srcLen); /* seedMask = MGF(maskedDB, hashLen) */ ippsMGF(pMaskedDB, k-1-hashLen, seedMask, hashLen, hashAlg); /* maskedSeed = seed ^ seedMask */ XorBlock(pSeed, seedMask, pMaskedSeed, hashLen); } /* RSA encryption */ { /* align buffer */ BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T)) ); /* temporary BN */ __ALIGN8 IppsBigNumState tmpBN; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &tmpBN); /* updtae buffer pointer */ pBuffer += (nsN+1)*2; ippsSetOctString_BN(pDst, k, &tmpBN); gsRSApub_cipher(&tmpBN, &tmpBN, pKey, pBuffer); ippsGetOctString_BN(pDst, k, &tmpBN); } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsaencrypt_oaep_rmf.c000066400000000000000000000123771470420105600261540ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2016 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // RSAES-OAEP Encryption/Decryption Functions // // Contents: // ippsRSAEncrypt_OAEP_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcptool.h" #include "pcpngrsa.h" #include "hash/pcphash_rmf.h" /*F* // Name: ippsRSAEncrypt_OAEP_rmf // // Purpose: Performs RSAES-OAEP encryprion scheme // // Returns: Reason: // ippStsNullPtrErr NULL == pKey // NULL == pSrc // NULL == pDst // NULL == pLabel // NULL == pSeed // NULL == pMethod // NULL == pBuffer // // ippStsLengthErr srcLen <0 // labLen <0 // srcLen > RSAsize -2*hashLen -2 // RSAsize < 2*hashLen +2 // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr public key is not set up // // ippStsNoErr no error // // Parameters: // pSrc pointer to the plaintext // srcLen plaintext length (bytes) // pLabel (optional) pointer to the label associated with plaintext // labLen label length (bytes) // pSeed seed string of hashLen size // pDst pointer to the ciphertext (length of pdst is not less then size of RSA modulus) // pKey pointer to the RSA public key context // pMethod hash methods // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSAEncrypt_OAEP_rmf,(const Ipp8u* pSrc, int srcLen, const Ipp8u* pLabel, int labLen, const Ipp8u* pSeed, Ipp8u* pDst, const IppsRSAPublicKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { int hashLen; /* test data pointer */ IPP_BAD_PTR4_RET(pSrc, pDst, pSeed, pMethod); IPP_BADARG_RET(!pLabel && labLen, ippStsNullPtrErr); /* test public key context */ IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test length */ IPP_BADARG_RET(srcLen<0||labLen<0, ippStsLengthErr); hashLen = pMethod->hashLen; /* test compatibility of RSA and hash length */ IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey)) < (2*hashLen +2), ippStsLengthErr); /* test compatibility of msg length and other (RSA and hash) lengths */ IPP_BADARG_RET(BITS2WORD8_SIZE(RSA_PRV_KEY_BITSIZE_N(pKey))-(2*hashLen +2) < srcLen, ippStsLengthErr); { /* size of RSA modulus in bytes and chunks */ int k = BITS2WORD8_SIZE(RSA_PUB_KEY_BITSIZE_N(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_N(pKey)); /* // EME-OAEP encoding */ { Ipp8u seedMask[BITS2WORD8_SIZE(IPP_SHA512_DIGEST_BITSIZE)]; Ipp8u* pMaskedSeed = pDst+1; Ipp8u* pMaskedDB = pDst +hashLen +1; pDst[0] = 0; /* maskedDB = MGF(seed, k-1-hashLen)*/ ippsMGF1_rmf(pSeed, hashLen, pMaskedDB, k-1-hashLen, pMethod); /* seedMask = HASH(pLab) */ ippsHashMessage_rmf(pLabel, labLen, seedMask, pMethod); /* maskedDB ^= concat(HASH(pLab),PS,0x01,pSc) */ XorBlock(pMaskedDB, seedMask, pMaskedDB, hashLen); pMaskedDB[k-srcLen-hashLen-2] ^= 0x01; XorBlock(pMaskedDB+k-srcLen-hashLen-2+1, pSrc, pMaskedDB+k-srcLen-hashLen-2+1, srcLen); /* seedMask = MGF(maskedDB, hashLen) */ ippsMGF1_rmf(pMaskedDB, k-1-hashLen, seedMask, hashLen, pMethod); /* maskedSeed = seed ^ seedMask */ XorBlock(pSeed, seedMask, pMaskedSeed, hashLen); } /* RSA encryption */ { /* align buffer */ BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T)) ); /* temporary BN */ __ALIGN8 IppsBigNumState tmpBN; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &tmpBN); /* updtae buffer pointer */ pBuffer += (nsN+1)*2; ippsSetOctString_BN(pDst, k, &tmpBN); gsRSApub_cipher(&tmpBN, &tmpBN, pKey, pBuffer); ippsGetOctString_BN(pDst, k, &tmpBN); } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsaencrypt_pkcsv15.c000066400000000000000000000106261470420105600256530ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSA-PKCS1-v1_5 Encryption Scheme // // Contents: // ippsRSAEncrypt_PKCSv15() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "pcptool.h" static int EncodeEME_PKCSv15(const Ipp8u* msg, Ipp32u msgLen, const Ipp8u* rndPS, Ipp8u* pEM, Ipp32u lenEM) { /* // encoded message format: // EM = 00 || 02 || PS || 00 || Msg // len(PS) >= 8 */ Ipp32u psLen = lenEM - msgLen - 3; pEM[0] = 0x00; pEM[1] = 0x02; if(rndPS) CopyBlock(rndPS, pEM+2, (cpSize)psLen); else PadBlock(0xFF, pEM+2, (cpSize)psLen); pEM[2+psLen] = 0x00; CopyBlock(msg, pEM+3+psLen, (cpSize)msgLen); return 1; } static int Encryption(const Ipp8u* pMsg, int msgLen, const Ipp8u* pRndPS, Ipp8u* pCipherTxt, const IppsRSAPublicKeyState* pKey, BNU_CHUNK_T* pBuffer) { /* size of RSA modulus in bytes and chunks */ int k= BITS2WORD8_SIZE(RSA_PUB_KEY_BITSIZE_N(pKey)); cpSize nsN = BITS_BNU_CHUNK(RSA_PUB_KEY_BITSIZE_N(pKey)); if( (msgLen+11)<=k ) { /* temporary BN */ __ALIGN8 IppsBigNumState tmpBN; BN_Make(pBuffer, pBuffer+nsN, nsN, &tmpBN); /* EME-PKCS-v1_5 encoding */ EncodeEME_PKCSv15(pMsg, (Ipp32u)msgLen, pRndPS, (Ipp8u*)(BN_BUFFER(&tmpBN)), (Ipp32u)k); /* // public-key operation */ ippsSetOctString_BN((Ipp8u*)(BN_BUFFER(&tmpBN)), k, &tmpBN); gsRSApub_cipher(&tmpBN, &tmpBN, pKey, pBuffer+nsN*2); /* convert into the cipher text */ ippsGetOctString_BN(pCipherTxt, k, &tmpBN); return 1; } else return 0; } /*F* // Name: ippsRSAEncrypt_PKCSv15 // // Purpose: Performs Encryption according to RSA-ES-PKCS1_v1.5 // // Returns: Reason: // ippStsNullPtrErr NULL == pSrc // NULL == pDst // NULL == pKey // NULL == pBuffer // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr public key is not set up // // //ippStsLengthErr 0 == srcLen // ippStsSizeErr RSA modulus too short (srcLen > k-11, see PKCS#1) !!runtime error // ippStsNoErr no error // // Parameters: // pSrc pointer to the plaintext to be encrypted // srcLen plaintext length (bytes) // pRandPS pointer to the random nonzero string of suitable length (psLen >= k -3 -srcLen) // pDst pointer to the ciphertext (k bytes length, == length of RSA modulus // pKey pointer to the public key context context // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSAEncrypt_PKCSv15,(const Ipp8u* pSrc, int srcLen, const Ipp8u* pRndPS, Ipp8u* pDst, const IppsRSAPublicKeyState* pKey, Ipp8u* pScratchBuffer)) { /* test public key context */ IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test data pointer */ IPP_BAD_PTR2_RET(pSrc, pDst); { BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))); return Encryption(pSrc, srcLen, pRndPS, pDst, pKey, pBuffer)? ippStsNoErr : ippStsSizeErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsasign_pkcs1v15.c000066400000000000000000000056351470420105600252140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // // Signatire Scheme with Appendix Signatute Generation // // Contents: // ippsRSASign_PKCS1v15() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash.h" #include "pcptool.h" #include "pcprsa_pkcs1c15_data.h" #include "pcprsa_generatesign_pkcs1v15.h" IPPFUN(IppStatus, ippsRSASign_PKCS1v15,(const Ipp8u* pMsg, int msgLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, IppHashAlgId hashAlg, Ipp8u* pScratchBuffer)) { /* test private key context */ IPP_BAD_PTR2_RET(pPrvKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrvKey), ippStsIncompleteContextErr); /* test hash algorithm ID */ hashAlg = cpValidHashAlg(hashAlg); IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); IPP_BADARG_RET(ippHashAlg_SM3==hashAlg, ippStsNotSupportedModeErr); /* use aligned public key context if defined */ if(pPubKey) { IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pPubKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pPubKey), ippStsIncompleteContextErr); } /* test data pointer */ IPP_BAD_PTR2_RET(pMsg, pSign); /* test length */ IPP_BADARG_RET(msgLen<0, ippStsLengthErr); { Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int mdLen = cpHashSize(hashAlg); ippsHashMessage(pMsg, msgLen, md, hashAlg); { const Ipp8u* pSalt = pksc15_salt[hashAlg].pSalt; int saltLen = pksc15_salt[hashAlg].saltLen; int sts = GenerateSign(md, mdLen, pSalt, saltLen, pSign, pPrvKey, pPubKey, (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T)))); return (1==sts)? ippStsNoErr : ippStsSizeErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcprsasign_pkcs1v15_rmf.c000066400000000000000000000047101470420105600260510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // // Signatire Scheme with Appendix Signatute Generation // // Contents: // ippsRSASign_PKCS1v15_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "pcprsa_pkcs1c15_data.h" #include "pcprsa_generatesign_pkcs1v15.h" #include "pcprsa_pkcs1v15_preproc.h" IPPFUN(IppStatus, ippsRSASign_PKCS1v15_rmf,(const Ipp8u* pMsg, int msgLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { const IppStatus preprocResult = SingleSignPkcs1v15RmfPreproc(pMsg, msgLen, pSign, &pPrvKey, &pPubKey, pMethod, pScratchBuffer); // badargs and pointer alignments if (ippStsNoErr != preprocResult) { return preprocResult; } { Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int mdLen = pMethod->hashLen; ippsHashMessage_rmf(pMsg, msgLen, md, pMethod); { const Ipp8u* pSalt = pksc15_salt[pMethod->hashAlgId].pSalt; int saltLen = pksc15_salt[pMethod->hashAlgId].saltLen; int sts = GenerateSign(md, mdLen, pSalt, saltLen, pSign, pPrvKey, pPubKey, (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T)))); return (1==sts)? ippStsNoErr : ippStsSizeErr; } } } cryptography-primitives-1.0.0/sources/ippcp/pcprsasign_pss.c000066400000000000000000000157131470420105600244420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PSS // // Signatire Scheme with Appendix Signatute Generation // (Ppobabilistic Signature Scheme) // // Contents: // ippsRSASign_PSS() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsRSASign_PSS // // Purpose: Performs Signature Generation according to RSASSA-PSS // // Returns: Reason: // ippStsNotSupportedModeErr invalid hashAlg value // // ippStsNullPtrErr NULL == pMsg // NULL == pSalt // NULL == pSign // NULL == pPrvKey // NULL == pPubKey // NULL == pBuffer // // ippStsLengthErr msgLen<0 // saltLen<0 // emLen < (hashLen +saltLen +2), // where emLen = (BITSIZE(RSA)-1)/8 // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr private or/and public key is not set up // // ippStsNoErr no error // // Parameters: // pMsg pointer to the message to be signed // msgLen lenfth of the message // pSalt "salt" pointer to random string // saltLen length of the "salt" string (bytes) // pSign pointer to the signature string of the RSA length // pPrvKey pointer to the RSA private key context // pPubKey (optional) pointer to the RSA public key context // hashAlg hash ID // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSASign_PSS,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSalt, int saltLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, IppHashAlgId hashAlg, Ipp8u* pScratchBuffer)) { /* test hash algorithm ID */ hashAlg = cpValidHashAlg(hashAlg); IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); /* test message length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); /* test data pointer */ IPP_BAD_PTR1_RET(pSign); /* test salt length and salt pointer */ IPP_BADARG_RET(saltLen<0, ippStsLengthErr); IPP_BADARG_RET((saltLen && !pSalt), ippStsNullPtrErr); /* test private key context */ IPP_BAD_PTR2_RET(pPrvKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PRV_KEY_VALID_ID(pPrvKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PRV_KEY_IS_SET(pPrvKey), ippStsIncompleteContextErr); /* use public key context if defined */ if(pPubKey) { IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pPubKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pPubKey), ippStsIncompleteContextErr); } { Ipp8u hashMsg[MAX_HASH_SIZE]; /* hash length */ int hashLen = cpHashSize(hashAlg); /* size of RSA modulus in bytes and chunks */ cpSize rsaBits = RSA_PRV_KEY_BITSIZE_N(pPrvKey); cpSize k = BITS2WORD8_SIZE(rsaBits); cpSize nsN = BITS_BNU_CHUNK(rsaBits); /* align buffer */ BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T)) ); /* temporary BNs */ __ALIGN8 IppsBigNumState bnC; __ALIGN8 IppsBigNumState bnP; /* message presentative size */ int emBits = rsaBits-1; int emLen = BITS2WORD8_SIZE(emBits); /* size of padding string (PS) */ int psLen = emLen -hashLen -saltLen -2; /* test size consistence */ if(0 > psLen) IPP_ERROR_RET(ippStsLengthErr); /* compute hash of the message */ ippsHashMessage(pMsg, msgLen, hashMsg, hashAlg); /* make BNs */ BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnC); pBuffer += (nsN+1)*2; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnP); pBuffer += (nsN+1)*2; /* // EMSA-PSS encoding */ { Ipp8u* pM = (Ipp8u*)BN_NUMBER(&bnP); Ipp8u* pEM = pSign; Ipp8u* pDB = pSign; int dbLen = emLen-hashLen-1; Ipp8u* pH = pSign+dbLen; /* construct message M' // M' = (00 00 00 00 00 00 00 00) || mHash || salt // where: // mHash = HASH(pMsg) */ PadBlock(0, pM, 8); CopyBlock(hashMsg, pM+8, hashLen); CopyBlock(pSalt, pM+8+hashLen, saltLen); /* construct EM // EM = maskedDB || H || 0xBC // where: // H = HASH(M') // maskedDB = DB ^ MGF(H) // where: // DB = PS || 0x01 || salt // // by other words // EM = (dbMask ^ (PS || 0x01 || salt)) || HASH(M) || 0xBC */ pEM[emLen-1] = 0xBC; /* tail octet */ ippsHashMessage(pM, 8+hashLen+saltLen, pH, hashAlg); /* H = HASH(M) */ ippsMGF(pH, hashLen, pDB, dbLen, hashAlg); /* dbMask = MGF(H) */ XorBlock(pDB+psLen+1, pSalt, pDB+psLen+1, saltLen); pDB[psLen] ^= 0x01; /* make sure that top 8*emLen-emBits bits are clear */ pDB[0] &= MAKEMASK32(8-8*emLen+emBits); } /* // private-key operation */ ippsSetOctString_BN(pSign, emLen, &bnC); if(RSA_PRV_KEY1_VALID_ID(pPrvKey)) gsRSAprv_cipher(&bnP, &bnC, pPrvKey, pBuffer); else gsRSAprv_cipher_crt(&bnP, &bnC, pPrvKey, pBuffer); ippsGetOctString_BN(pSign, k, &bnP); /* no check requested */ if(!pPubKey) return ippStsNoErr; /* check the result before send it out (fault attack mitigatioin) */ else { gsRSApub_cipher(&bnP, &bnP, pPubKey, pBuffer); if(0==cpBN_cmp(&bnP, &bnC)) return ippStsNoErr; /* discard signature if check failed */ else { PadBlock(0, pSign, k); return ippStsErr; } } } } cryptography-primitives-1.0.0/sources/ippcp/pcprsasign_pss_rmf.c000066400000000000000000000146131470420105600253040ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PSS // // Signatire Scheme with Appendix Signatute Generation // (Ppobabilistic Signature Scheme) // // Contents: // ippsRSASign_PSS_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "pcprsa_pss_preproc.h" /*F* // Name: ippsRSASign_PSS_rmf // // Purpose: Performs Signature Generation according to RSASSA-PSS // // Returns: Reason: // ippStsNotSupportedModeErr invalid hashAlg value // // ippStsNullPtrErr NULL == pMsg // NULL == pSalt // NULL == pSign // NULL == pPrvKey // NULL == pPubKey // NULL == pMethod // NULL == pBuffer // // ippStsLengthErr msgLen<0 // saltLen<0 // emLen < (hashLen +saltLen +2), // where emLen = (BITSIZE(RSA)-1)/8 // // ippStsContextMatchErr !RSA_PRV_KEY_VALID_ID() // !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr private or/and public key is not set up // // ippStsNoErr no error // // Parameters: // pMsg pointer to the message to be signed // msgLen lenfth of the message // pSalt "salt" pointer to random string // saltLen length of the "salt" string (bytes) // pSign pointer to the signature string of the RSA length // pPrvKey pointer to the RSA private key context // pPubKey (optional) pointer to the RSA public key context // pMethod hash method // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSASign_PSS_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSalt, int saltLen, Ipp8u* pSign, const IppsRSAPrivateKeyState* pPrvKey, const IppsRSAPublicKeyState* pPubKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { const IppStatus preprocResult = SingleSignPssRmfPreproc(pMsg, msgLen, pSalt, saltLen, pSign, &pPrvKey, &pPubKey, pMethod, pScratchBuffer); // badargs and pointer alignments if (ippStsNoErr != preprocResult) { return preprocResult; } { Ipp8u hashMsg[MAX_HASH_SIZE]; /* hash length */ int hashLen = pMethod->hashLen; /* size of RSA modulus in bytes and chunks */ cpSize rsaBits = RSA_PRV_KEY_BITSIZE_N(pPrvKey); cpSize k = BITS2WORD8_SIZE(rsaBits); cpSize nsN = BITS_BNU_CHUNK(rsaBits); /* align buffer */ BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T)) ); /* temporary BNs */ __ALIGN8 IppsBigNumState bnC; __ALIGN8 IppsBigNumState bnP; /* message presentative size */ int emBits = rsaBits-1; int emLen = BITS2WORD8_SIZE(emBits); /* size of padding string (PS) */ int psLen = emLen -hashLen -saltLen -2; /* test size consistence */ if(0 > psLen) IPP_ERROR_RET(ippStsLengthErr); /* compute hash of the message */ ippsHashMessage_rmf(pMsg, msgLen, hashMsg, pMethod); /* make BNs */ BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnC); pBuffer += (nsN+1)*2; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnP); pBuffer += (nsN+1)*2; /* // EMSA-PSS encoding */ { Ipp8u* pM = (Ipp8u*)BN_NUMBER(&bnP); Ipp8u* pEM = pSign; Ipp8u* pDB = pSign; int dbLen = emLen-hashLen-1; Ipp8u* pH = pSign+dbLen; /* construct message M' // M' = (00 00 00 00 00 00 00 00) || mHash || salt // where: // mHash = HASH(pMsg) */ PadBlock(0, pM, 8); CopyBlock(hashMsg, pM+8, hashLen); CopyBlock(pSalt, pM+8+hashLen, saltLen); /* construct EM // EM = maskedDB || H || 0xBC // where: // H = HASH(M') // maskedDB = DB ^ MGF(H) // where: // DB = PS || 0x01 || salt // // by other words // EM = (dbMask ^ (PS || 0x01 || salt)) || HASH(M) || 0xBC */ pEM[emLen-1] = 0xBC; /* tail octet */ ippsHashMessage_rmf(pM, 8+hashLen+saltLen, pH, pMethod); /* H = HASH(M) */ ippsMGF1_rmf(pH, hashLen, pDB, dbLen, pMethod); /* dbMask = MGF(H) */ XorBlock(pDB+psLen+1, pSalt, pDB+psLen+1, saltLen); pDB[psLen] ^= 0x01; /* make sure that top 8*emLen-emBits bits are clear */ pDB[0] &= MAKEMASK32(8-8*emLen+emBits); } /* // private-key operation */ ippsSetOctString_BN(pSign, emLen, &bnC); if(RSA_PRV_KEY1_VALID_ID(pPrvKey)) gsRSAprv_cipher(&bnP, &bnC, pPrvKey, pBuffer); else gsRSAprv_cipher_crt(&bnP, &bnC, pPrvKey, pBuffer); ippsGetOctString_BN(pSign, k, &bnP); /* no check requested */ if(!pPubKey) return ippStsNoErr; /* check the result before send it out (fault attack mitigatioin) */ else { gsRSApub_cipher(&bnP, &bnP, pPubKey, pBuffer); if(0==cpBN_cmp(&bnP, &bnC)) return ippStsNoErr; /* discard signature if check failed */ else { PadBlock(0, pSign, k); return ippStsErr; } } } } cryptography-primitives-1.0.0/sources/ippcp/pcprsaverify_pkcs1v15.c000066400000000000000000000050171470420105600255520ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // // Signatire Scheme with Appendix Signatute Generation // // Contents: // ippsRSAVerify_PKCS1v15() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash.h" #include "pcptool.h" #include "pcprsa_pkcs1c15_data.h" #include "pcprsa_verifysign_pkcs1v15.h" IPPFUN(IppStatus, ippsRSAVerify_PKCS1v15,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pScratchBuffer)) { /* test public key context */ IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); /* test hash algorithm ID */ hashAlg = cpValidHashAlg(hashAlg); IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); IPP_BADARG_RET(ippHashAlg_SM3==hashAlg, ippStsNotSupportedModeErr); /* test data pointer */ IPP_BAD_PTR3_RET(pMsg, pSign, pIsValid); /* test length */ IPP_BADARG_RET(msgLen<0, ippStsLengthErr); *pIsValid = 0; { Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; int mdLen = cpHashSize(hashAlg); ippsHashMessage(pMsg, msgLen, md, hashAlg); return VerifySign(md, mdLen, pksc15_salt[hashAlg].pSalt, pksc15_salt[hashAlg].saltLen, pSign, pIsValid, pKey, (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))))? ippStsNoErr : ippStsSizeErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsaverify_pkcs1v15_rmf.c000066400000000000000000000043751470420105600264240ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PKCS-v1_5 // // Signatire Scheme with Appendix Signatute Generation // // Contents: // ippsRSAVerify_PKCS1v15_rmf() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash_rmf.h" #include "pcptool.h" #include "pcprsa_pkcs1c15_data.h" #include "pcprsa_verifysign_pkcs1v15.h" #include "pcprsa_pkcs1v15_preproc.h" IPPFUN(IppStatus, ippsRSAVerify_PKCS1v15_rmf,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, const IppsHashMethod* pMethod, Ipp8u* pScratchBuffer)) { const IppStatus preprocResult = SingleVerifyPkcs1v15RmfPreproc(pMsg, msgLen, pSign, pIsValid, &pKey, pMethod, pScratchBuffer); // badargs, pointer alignments, set valid = 0 if (ippStsNoErr != preprocResult) { return preprocResult; } { Ipp8u md[IPP_SHA512_DIGEST_BITSIZE/BYTESIZE]; ippsHashMessage_rmf(pMsg, msgLen, md, pMethod); return VerifySign(md, pMethod->hashLen, pksc15_salt[pMethod->hashAlgId].pSalt, pksc15_salt[pMethod->hashAlgId].saltLen, pSign, pIsValid, pKey, (BNU_CHUNK_T*)(IPP_ALIGNED_PTR((pScratchBuffer), (int)sizeof(BNU_CHUNK_T))))? ippStsNoErr : ippStsSizeErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcprsaverify_pss.c000066400000000000000000000140661470420105600250060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // RSASSA-PSS // // Signatire Scheme with Appendix Signatute Generation // (Ppobabilistic Signature Scheme) // // Contents: // ippsRSAVerify_PSS() // */ #include "owndefs.h" #include "owncp.h" #include "pcpngrsa.h" #include "hash/pcphash.h" #include "pcptool.h" //////////////////////////////////////////////////////////////////////////////////////////////////// /*F* // Name: ippsRSAVerify_PSS // // Purpose: Performs Signature Verification according to RSASSA-PSS // // Returns: Reason: // ippStsNotSupportedModeErr invalid hashAlg value // // ippStsNullPtrErr NULL == pMsg // NULL == pSign // NULL == pIsValid // NULL == pKey // NULL == pBuffer // // ippStsLengthErr msgLen<0 // RSAsize <=hashLen +2 // // ippStsContextMatchErr !RSA_PUB_KEY_VALID_ID() // // ippStsIncompleteContextErr public key is not set up // // ippStsNoErr no error // // Parameters: // pMsg pointer to the message to be verified // msgLen length of the message // pSign pointer to the signature string of the RSA length // pIsValid pointer to the verification result // pKey pointer to the RSA public key context // hashAlg hash ID // pBuffer pointer to scratch buffer *F*/ IPPFUN(IppStatus, ippsRSAVerify_PSS,(const Ipp8u* pMsg, int msgLen, const Ipp8u* pSign, int* pIsValid, const IppsRSAPublicKeyState* pKey, IppHashAlgId hashAlg, Ipp8u* pScratchBuffer)) { /* test hash algorithm ID */ hashAlg = cpValidHashAlg(hashAlg); IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); /* test message length */ IPP_BADARG_RET((msgLen<0), ippStsLengthErr); /* test message pointer */ IPP_BADARG_RET((msgLen && !pMsg), ippStsNullPtrErr); /* test data pointer */ IPP_BAD_PTR2_RET(pSign, pIsValid); /* test public key context */ IPP_BAD_PTR2_RET(pKey, pScratchBuffer); IPP_BADARG_RET(!RSA_PUB_KEY_VALID_ID(pKey), ippStsContextMatchErr); IPP_BADARG_RET(!RSA_PUB_KEY_IS_SET(pKey), ippStsIncompleteContextErr); { Ipp8u hashMsg[MAX_HASH_SIZE]; /* hash length */ int hashLen = cpHashSize(hashAlg); /* size of RSA modulus in bytes and chunks */ cpSize rsaBits = RSA_PUB_KEY_BITSIZE_N(pKey); cpSize k = BITS2WORD8_SIZE(rsaBits); cpSize nsN = BITS_BNU_CHUNK(rsaBits); /* align buffer */ BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T)) ); /* temporary BNs */ __ALIGN8 IppsBigNumState bnC; __ALIGN8 IppsBigNumState bnP; /* message presentative size */ int emBits = rsaBits-1; int emLen = BITS2WORD8_SIZE(emBits); /* test size consistence */ if(k <= (hashLen+2)) IPP_ERROR_RET(ippStsLengthErr); /* compute hash of the message */ ippsHashMessage(pMsg, msgLen, hashMsg, hashAlg); /* make BNs */ BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnC); pBuffer += (nsN+1)*2; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnP); pBuffer += (nsN+1)*2; /* // public-key operation */ ippsSetOctString_BN(pSign, k, &bnP); gsRSApub_cipher(&bnC, &bnP, pKey, pBuffer); *pIsValid = 0; /* // EMSA-PSS verification */ { /* convert BN into octet string EM // EM = maskedDB || H || 0xBC */ Ipp8u* pEM = (Ipp8u*)BN_BUFFER(&bnC); ippsGetOctString_BN(pEM, emLen, &bnC); /* test last byte and top of (8*emLen-emBits) bits */ if(0xBC==pEM[emLen-1] && 0x00==(pEM[0] >>(8-(8*emLen-emBits)))) { int psLen; Ipp8u* pM = (Ipp8u*)BN_NUMBER(&bnP); /* pointers to the EM fields */ int dbLen = emLen-hashLen-1; Ipp8u* pDB = pEM; Ipp8u* pH = pEM+dbLen; /* recover DB = maskedDB ^ MGF(H) */ ippsMGF(pH, hashLen, pM, dbLen, hashAlg); XorBlock(pDB, pM, pDB, dbLen); /* make sure that top 8*emLen-emBits bits are clear */ pDB[0] &= MAKEMASK32(8-8*emLen+emBits); /* skip over padding string (PS) */ for(psLen=0; psLenhashLen; /* size of RSA modulus in bytes and chunks */ cpSize rsaBits = RSA_PUB_KEY_BITSIZE_N(pKey); cpSize k = BITS2WORD8_SIZE(rsaBits); cpSize nsN = BITS_BNU_CHUNK(rsaBits); /* align buffer */ BNU_CHUNK_T* pBuffer = (BNU_CHUNK_T*)(IPP_ALIGNED_PTR(pScratchBuffer, (int)sizeof(BNU_CHUNK_T)) ); /* temporary BNs */ __ALIGN8 IppsBigNumState bnC; __ALIGN8 IppsBigNumState bnP; /* message presentative size */ int emBits = rsaBits-1; int emLen = BITS2WORD8_SIZE(emBits); /* test size consistence */ if(k <= (hashLen+2)) IPP_ERROR_RET(ippStsLengthErr); /* compute hash of the message */ ippsHashMessage_rmf(pMsg, msgLen, hashMsg, pMethod); /* make BNs */ BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnC); pBuffer += (nsN+1)*2; BN_Make(pBuffer, pBuffer+nsN+1, nsN, &bnP); pBuffer += (nsN+1)*2; /* // public-key operation */ ippsSetOctString_BN(pSign, k, &bnP); gsRSApub_cipher(&bnC, &bnP, pKey, pBuffer); /* // EMSA-PSS verification */ { /* convert BN into octet string EM // EM = maskedDB || H || 0xBC */ Ipp8u* pEM = (Ipp8u*)BN_BUFFER(&bnC); ippsGetOctString_BN(pEM, emLen, &bnC); /* test last byte and top of (8*emLen-emBits) bits */ if(0xBC==pEM[emLen-1] && 0x00==(pEM[0] >>(8-(8*emLen-emBits)))) { int psLen; Ipp8u* pM = (Ipp8u*)BN_NUMBER(&bnP); /* pointers to the EM fields */ int dbLen = emLen-hashLen-1; Ipp8u* pDB = pEM; Ipp8u* pH = pEM+dbLen; /* recover DB = maskedDB ^ MGF(H) */ ippsMGF1_rmf(pH, hashLen, pM, dbLen, pMethod); XorBlock(pDB, pM, pDB, dbLen); /* make sure that top 8*emLen-emBits bits are clear */ pDB[0] &= MAKEMASK32(8-8*emLen+emBits); /* skip over padding string (PS) */ for(psLen=0; psLen 2 dword) for(; dataSize>=2; dataSize-=2, pArray+=CACHE_LINE_SIZE, pData+=2) { ((Ipp32u*)pArray)[0] = pData[0]; ((Ipp32u*)pArray)[1] = pData[1]; } if(dataSize) ((Ipp32u*)pArray)[0] = pData[0]; break; case 16: // column - oword (16 bytes => 4 dword) for(; dataSize>=4; dataSize-=4, pArray+=CACHE_LINE_SIZE, pData+=4) { ((Ipp32u*)pArray)[0] = pData[0]; ((Ipp32u*)pArray)[1] = pData[1]; ((Ipp32u*)pArray)[2] = pData[2]; ((Ipp32u*)pArray)[3] = pData[3]; } for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) ((Ipp32u*)pArray)[0] = pData[0]; break; case 32: // column - 2 oword (32 bytes => 8 dword) for(; dataSize>=8; dataSize-=8, pArray+=CACHE_LINE_SIZE, pData+=8) { ((Ipp32u*)pArray)[0] = pData[0]; ((Ipp32u*)pArray)[1] = pData[1]; ((Ipp32u*)pArray)[2] = pData[2]; ((Ipp32u*)pArray)[3] = pData[3]; ((Ipp32u*)pArray)[4] = pData[4]; ((Ipp32u*)pArray)[5] = pData[5]; ((Ipp32u*)pArray)[6] = pData[6]; ((Ipp32u*)pArray)[7] = pData[7]; } for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) ((Ipp32u*)pArray)[0] = pData[0]; break; default: break; } } /* // Retrieve data from pArray */ #define u8_to_u32(b0,b1,b2,b3, x) \ ((x) = (b0), \ (x)|=((b1)<<8), \ (x)|=((b2)<<16), \ (x)|=((b3)<<24)) #define u16_to_u32(w0,w1, x) \ ((x) = (w0), \ (x)|=((w1)<<16)) #define u32_to_u64(dw0,dw1, x) \ ((x) = (Ipp64u)(dw0), \ (x)|= (((Ipp64u)(dw1))<<32)) __IPPCP_INLINE void cpScrambleGet(Ipp32u* pData, cpSize dataSize, const Ipp8u* pArray, cpSize colummSize) { int i; switch(colummSize) { case 1: // column - byte for(i=0; i 2 dword) for(; dataSize>=2; dataSize-=2, pArray+=CACHE_LINE_SIZE, pData+=2) { pData[0] = ((Ipp32u*)pArray)[0]; pData[1] = ((Ipp32u*)pArray)[1]; } if(dataSize) pData[0] = ((Ipp32u*)pArray)[0]; break; case 16: // column - oword (16 bytes => 4 dword) for(; dataSize>=4; dataSize-=4, pArray+=CACHE_LINE_SIZE, pData+=4) { pData[0] = ((Ipp32u*)pArray)[0]; pData[1] = ((Ipp32u*)pArray)[1]; pData[2] = ((Ipp32u*)pArray)[2]; pData[3] = ((Ipp32u*)pArray)[3]; } for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) pData[0] = ((Ipp32u*)pArray)[0]; break; case 32: // column - 2 oword (32 bytes => 8 dword) for(; dataSize>=8; dataSize-=8, pArray+=CACHE_LINE_SIZE, pData+=8) { pData[0] = ((Ipp32u*)pArray)[0]; pData[1] = ((Ipp32u*)pArray)[1]; pData[2] = ((Ipp32u*)pArray)[2]; pData[3] = ((Ipp32u*)pArray)[3]; pData[4] = ((Ipp32u*)pArray)[4]; pData[5] = ((Ipp32u*)pArray)[5]; pData[6] = ((Ipp32u*)pArray)[6]; pData[7] = ((Ipp32u*)pArray)[7]; } for(; dataSize>0; dataSize--, pArray+=sizeof(Ipp32u), pData++) pData[0] = ((Ipp32u*)pArray)[0]; break; default: break; } } #endif /* _PC_SCRAMBLE_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpshsmgfca.c000066400000000000000000000061711470420105600237000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // HASH based Mask Generation Functions // // Contents: // ippsMGF_SHA1() // ippsMGF_SHA224() // ippsMGF_SHA256() // ippsMGF_SHA384() // ippsMGF_SHA512() // ippsMGF_MD5() // // */ #include "owndefs.h" #include "owncp.h" #include "hash/pcphash.h" #include "pcptool.h" /*F* // Name: ippsMGF_SHA1 // ippsMGF_SHA224 // ippsMGF_SHA256 // ippsMGF_SHA384 // ippsMGF_SHA512 // ippsMGF_MD5 // // Purpose: Mask Generation Functions. // // Returns: Reason: // ippStsNullPtrErr pMask == NULL // ippStsLengthErr seedLen <0 // maskLen <0 // ippStsNotSupportedModeErr if algID is not match to supported hash alg // ippStsNoErr no errors // // Parameters: // pSeed pointer to the input stream // seedLen input stream length (bytes) // pMask pointer to the output mask // maskLen desired length of mask (bytes) // hashAlg identifier of the hash algorithm // *F*/ IPPFUN(IppStatus, ippsMGF, (const Ipp8u* pSeed, int seedLen, Ipp8u* pMask, int maskLen, IppHashAlgId hashAlg)) { /* get algorithm id */ hashAlg = cpValidHashAlg(hashAlg); /* test hash alg */ IPP_BADARG_RET(ippHashAlg_Unknown==hashAlg, ippStsNotSupportedModeErr); IPP_BAD_PTR1_RET(pMask); IPP_BADARG_RET((seedLen<0)||(maskLen<0), ippStsLengthErr); { /* hash specific */ int hashSize = cpHashSize(hashAlg); int i, outLen; IppsHashState hashCtx; ippsHashInit(&hashCtx, hashAlg); if(!pSeed) seedLen = 0; for(i=0,outLen=0; outLen>24) & 0xFF); cnt[1] = (Ipp8u)((i>>16) & 0xFF); cnt[2] = (Ipp8u)((i>>8) & 0xFF); cnt[3] = (Ipp8u)(i & 0xFF); cpReInitHash(&hashCtx, hashAlg); ippsHashUpdate(pSeed, seedLen, &hashCtx); ippsHashUpdate(cnt, 4, &hashCtx); if((outLen + hashSize) <= maskLen) { ippsHashFinal(pMask+outLen, &hashCtx); outLen += hashSize; } else { Ipp8u md[MAX_HASH_SIZE]; ippsHashFinal(md, &hashCtx); CopyBlock(md, pMask+outLen, maskLen-outLen); outLen = maskLen; } } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4.h000066400000000000000000000152671470420105600230060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Internal Definitions and // Internal SMS4 Function Prototypes // // */ #if !defined(_PCP_SMS4_H) #define _PCP_SMS4_H #include "owncp.h" #include "pcpmask_ct.h" /* SMS4 round keys number */ #define SMS4_ROUND_KEYS_NUM (32) #if SMS4_ROUND_KEYS_NUM != 32 #error SMS4_ROUND_KEYS_NUM must be equal 32 #endif struct _cpSMS4 { Ipp32u idCtx; /* SMS4 spec identifier */ Ipp32u enc_rkeys[SMS4_ROUND_KEYS_NUM]; /* enc round keys */ Ipp32u dec_rkeys[SMS4_ROUND_KEYS_NUM]; /* dec round keys */ }; /* // access macros */ #define SMS4_SET_ID(ctx) ((ctx)->idCtx = (Ipp32u)idCtxSMS4 ^ (Ipp32u)IPP_UINT_PTR(ctx)) #define SMS4_RK(ctx) ((ctx)->enc_rkeys) #define SMS4_ERK(ctx) ((ctx)->enc_rkeys) #define SMS4_DRK(ctx) ((ctx)->dec_rkeys) /* SMS4 data block size (bytes) */ #define MBS_SMS4 (16) #if MBS_SMS4 != 16 #error MBS_SMS4 must be equal 16 #endif /* valid SMS4 context ID */ #define VALID_SMS4_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxSMS4) /* alignment of AES context */ #define SMS4_ALIGNMENT (4) /* size of SMS4 context */ __IPPCP_INLINE int cpSizeofCtx_SMS4(void) { return sizeof(IppsSMS4Spec); } /* SMS4 constants */ extern const __ALIGN64 Ipp8u SMS4_Sbox[16*16]; extern const Ipp32u SMS4_FK[4]; extern const Ipp32u SMS4_CK[32]; ////////////////////////////////////////////////////////////////////////////////////////////////////// /* S-box substitution (endian dependent!) */ #include "pcpbnuimpl.h" #define SELECTION_BITS ((sizeof(BNU_CHUNK_T)/sizeof(Ipp8u)) -1) __IPPCP_INLINE Ipp8u getSboxValue(Ipp8u x) { BNU_CHUNK_T selection = 0; const Ipp8u* SboxEntry = SMS4_Sbox; Ipp32u i; for (i = 0; i> 8) & 0xFF) <<8); y |= (Ipp32u)(getSboxValue((x>>16) & 0xFF) <<16); y |= (Ipp32u)(getSboxValue((x>>24) & 0xFF) <<24); return y; } /* key expansion transformation: - linear Linear - mixer Mix (permutation T in the SMS4 standard phraseology) */ __IPPCP_INLINE Ipp32u cpExpKeyLinear_SMS4(Ipp32u x) { return x^ROL32(x,13)^ROL32(x,23); } __IPPCP_INLINE Ipp32u cpExpKeyMix_SMS4(Ipp32u x) { return cpExpKeyLinear_SMS4( cpSboxT_SMS4(x) ); } /* cipher transformations: - linear Linear - mixer Mix (permutation T in the SMS4 standard phraseology) */ __IPPCP_INLINE Ipp32u cpCipherLinear_SMS4(Ipp32u x) { return x^ROL32(x,2)^ROL32(x,10)^ROL32(x,18)^ROL32(x,24); } __IPPCP_INLINE Ipp32u cpCipherMix_SMS4(Ipp32u x) { return cpCipherLinear_SMS4( cpSboxT_SMS4(x) ); } ////////////////////////////////////////////////////////////////////////////////////////////// #define cpSMS4_Cipher OWNAPI(cpSMS4_Cipher) IPP_OWN_DECL (void, cpSMS4_Cipher, (Ipp8u* otxt, const Ipp8u* itxt, const Ipp32u* pRoundKeys)) #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #define cpSMS4_SetRoundKeys_aesni OWNAPI(cpSMS4_SetRoundKeys_aesni) IPP_OWN_DECL (void, cpSMS4_SetRoundKeys_aesni, (Ipp32u* pRounKey, const Ipp8u* pSecretKey)) #define cpSMS4_ECB_aesni_x1 OWNAPI(cpSMS4_ECB_aesni_x1) IPP_OWN_DECL (void, cpSMS4_ECB_aesni_x1, (Ipp8u* pOut, const Ipp8u* pInp, const Ipp32u* pRKey)) #define cpSMS4_ECB_aesni OWNAPI(cpSMS4_ECB_aesni) IPP_OWN_DECL (int, cpSMS4_ECB_aesni, (Ipp8u* pDst, const Ipp8u* pSrc, int nLen, const Ipp32u* pRKey)) #define cpSMS4_CBC_dec_aesni OWNAPI(cpSMS4_CBC_dec_aesni) IPP_OWN_DECL (int, cpSMS4_CBC_dec_aesni, (Ipp8u* pDst, const Ipp8u* pSrc, int nLen, const Ipp32u* pRKey, Ipp8u* pIV)) #define cpSMS4_CTR_aesni OWNAPI(cpSMS4_CTR_aesni) IPP_OWN_DECL (int, cpSMS4_CTR_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) #if (_IPP>=_IPP_H9) || (_IPP32E>=_IPP32E_L9) #define cpSMS4_ECB_aesni_x12 OWNAPI(cpSMS4_ECB_aesni_x12) IPP_OWN_DECL (int, cpSMS4_ECB_aesni_x12, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) #define cpSMS4_CBC_dec_aesni_x12 OWNAPI(cpSMS4_CBC_dec_aesni_x12) IPP_OWN_DECL (int, cpSMS4_CBC_dec_aesni_x12, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV)) #define cpSMS4_CTR_aesni_x4 OWNAPI(cpSMS4_CTR_aesni_x4) IPP_OWN_DECL (int, cpSMS4_CTR_aesni_x4, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) #define cpSMS4_ECB_gfni_x1 OWNAPI(cpSMS4_ECB_gfni_x1) IPP_OWN_DECL (void, cpSMS4_ECB_gfni_x1, (Ipp8u* pOut, const Ipp8u* pInp, const Ipp32u* pRKey)) #define cpSMS4_ECB_gfni512 OWNAPI(cpSMS4_ECB_gfni512) IPP_OWN_DECL (int, cpSMS4_ECB_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) #define cpSMS4_CBC_dec_gfni512 OWNAPI(cpSMS4_CBC_dec_gfni512) IPP_OWN_DECL (int, cpSMS4_CBC_dec_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV)) #define cpSMS4_CTR_gfni512 OWNAPI(cpSMS4_CTR_gfni512) IPP_OWN_DECL (int, cpSMS4_CTR_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) #define cpSMS4_CFB_dec_gfni512 OWNAPI(cpSMS4_CFB_dec_gfni512) IPP_OWN_DECL (void, cpSMS4_CFB_dec_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV)) #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* (_IPP32E>=_IPP32E_K1) */ #endif /* (_IPP>=_IPP_H9) || (_IPP32E>=_IPP32E_L9) */ #endif #define cpProcessSMS4_ctr OWNAPI(cpProcessSMS4_ctr) IPP_OWN_DECL (IppStatus, cpProcessSMS4_ctr, (const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsSMS4Spec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) #endif /* _PCP_SMS4_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_cbc_gfni.c000066400000000000000000001562761470420105600246210ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 ECB decryption // // Contents: // cpSMS4_ECB_gfni512() // cpSMS4_CBC_dec_gfni512x48() // cpSMS4_CBC_dec_gfni512x32() // cpSMS4_CBC_dec_gfni512x16() // cpSMS4_CBC_dec_gfni128x12() // cpSMS4_CBC_dec_gfni128x8() // cpSMS4_CBC_dec_gfni128x4() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) #include "pcpsms4_gfni.h" static int cpSMS4_CBC_dec_gfni512x48(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV); static int cpSMS4_CBC_dec_gfni512x32(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV); static int cpSMS4_CBC_dec_gfni512x16(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV); static int cpSMS4_CBC_dec_gfni128x12(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV); static int cpSMS4_CBC_dec_gfni128x8(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV); static int cpSMS4_CBC_dec_gfni128x4(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV); /* // 64*MBS_SMS4 bytes processing */ IPP_OWN_DEFN (int, cpSMS4_CBC_dec_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV)) { __ALIGN16 __m512i TMP[21]; __m128i IV = _mm_loadu_si128((__m128i*)(pIV)); // Non-secret data int processedLen = len - (len % (64 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (64 * MBS_SMS4), pInp += (64 * MBS_SMS4), pOut += (64 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 32)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 36)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 40)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 44)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 48)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 52)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 56)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 60)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[2]), L512(TMP[2])); TMP[16] = _mm512_xor_si512(_mm512_xor_si512(TMP[16], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[2]), L512(TMP[2])); TMP[17] = _mm512_xor_si512(_mm512_xor_si512(TMP[17], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[2]), L512(TMP[2])); TMP[18] = _mm512_xor_si512(_mm512_xor_si512(TMP[18], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[2]), L512(TMP[2])); TMP[19] = _mm512_xor_si512(_mm512_xor_si512(TMP[19], TMP[3]), L512(TMP[3])); } pRKey -= 32; /* Prepare the first block for xor*/ TMP[20] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[20] = _mm512_alignr_epi64(TMP[20], TMP[20], 6); TMP[20] = _mm512_inserti64x2(TMP[20], IV, 0); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[4] = _mm512_xor_si512(TMP[0], TMP[20]); TMP[5] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*3))); TMP[6] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*7))); TMP[7] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*11))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[8] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*15))); TMP[9] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*19))); TMP[10] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*23))); TMP[11] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*27))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[12] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*31))); TMP[13] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*35))); TMP[14] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*39))); TMP[15] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*43))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[16] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*47))); TMP[17] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*51))); TMP[18] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*55))); TMP[19] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*59))); IV = _mm_loadu_si128((__m128i*)(pInp+MBS_SMS4*63)); // Ciphertext, non-secret data _mm512_storeu_si512((__m512i*)(pOut), TMP[4]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[5]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[6]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[7]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), TMP[8]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), TMP[9]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), TMP[10]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), TMP[11]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 32), TMP[12]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 36), TMP[13]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 40), TMP[14]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 44), TMP[15]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 48), TMP[16]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 52), TMP[17]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 56), TMP[18]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 60), TMP[19]); } _mm_storeu_si128((__m128i*)(pIV), IV); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len){ if(len < 256){ processedLen += cpSMS4_CBC_dec_gfni128x12(pOut, pInp, len, pRKey, pIV); return processedLen; } processedLen += cpSMS4_CBC_dec_gfni512x48(pOut, pInp, len, pRKey, pIV); } return processedLen; } /* // 48*MBS_SMS4 bytes processing */ static int cpSMS4_CBC_dec_gfni512x48(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m512i TMP[17]; __m128i IV = _mm_loadu_si128((__m128i*)(pIV)); // Non-secret data int processedLen = len - (len % (48 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (48 * MBS_SMS4), pInp += (48 * MBS_SMS4), pOut += (48 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 32)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 36)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 40)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 44)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[2]), L512(TMP[2])); } pRKey -= 32; /* Prepare the first block for xor*/ TMP[16] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[16] = _mm512_alignr_epi64(TMP[16], TMP[16], 6); TMP[16] = _mm512_inserti64x2(TMP[16], IV, 0); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[4] = _mm512_xor_si512(TMP[0], TMP[16]); TMP[5] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*3))); TMP[6] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*7))); TMP[7] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*11))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[8] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*15))); TMP[9] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*19))); TMP[10] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*23))); TMP[11] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*27))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[12] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*31))); TMP[13] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*35))); TMP[14] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*39))); TMP[15] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*43))); IV = _mm_loadu_si128((__m128i*)(pInp+MBS_SMS4*47)); // Ciphertext, non-secret data _mm512_storeu_si512((__m512i*)(pOut), TMP[4]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[5]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[6]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[7]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), TMP[8]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), TMP[9]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), TMP[10]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), TMP[11]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 32), TMP[12]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 36), TMP[13]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 40), TMP[14]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 44), TMP[15]); } _mm_storeu_si128((__m128i*)(pIV), IV); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len) processedLen += cpSMS4_CBC_dec_gfni512x32(pOut, pInp, len, pRKey, pIV); return processedLen; } /* // 32*MBS_SMS4 bytes processing */ static int cpSMS4_CBC_dec_gfni512x32(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m512i TMP[13]; __m128i IV = _mm_loadu_si128((__m128i*)(pIV)); // Non-secret data int processedLen = len - (len % (32 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (32 * MBS_SMS4), pInp += (32 * MBS_SMS4), pOut += (32 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); } pRKey -= 32; /* Prepare the first block for xor*/ TMP[12] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[12] = _mm512_alignr_epi64(TMP[12], TMP[12], 6); TMP[12] = _mm512_inserti64x2(TMP[12], IV, 0); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[4] = _mm512_xor_si512(TMP[0], TMP[12]); TMP[5] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*3))); TMP[6] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*7))); TMP[7] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*11))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[8] = _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*15))); TMP[9] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*19))); TMP[10] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*23))); TMP[11] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*27))); IV = _mm_loadu_si128((__m128i*)(pInp+MBS_SMS4*31)); // Ciphertext, non-secret data _mm512_storeu_si512((__m512i*)(pOut), TMP[4]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[5]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[6]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[7]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), TMP[8]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), TMP[9]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), TMP[10]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), TMP[11]); } _mm_storeu_si128((__m128i*)(pIV), IV); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len) processedLen += cpSMS4_CBC_dec_gfni512x16(pOut, pInp, len, pRKey, pIV); return processedLen; } /* // 16*MBS_SMS4 bytes processing */ static int cpSMS4_CBC_dec_gfni512x16(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m512i TMP[9]; __m128i IV = _mm_loadu_si128((__m128i*)(pIV)); // Non-secret data int processedLen = len - (len % (16 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (16 * MBS_SMS4), pInp += (16 * MBS_SMS4), pOut += (16 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TMP[8] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[8] = _mm512_alignr_epi64(TMP[8], TMP[8], 6); TMP[8] = _mm512_inserti64x2(TMP[8], IV, 0); TMP[4] = _mm512_xor_si512(TMP[0], TMP[8]); TMP[5] = _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*3))); TMP[6] = _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*7))); TMP[7] = _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp+MBS_SMS4*11))); IV = _mm_loadu_si128((__m128i*)(pInp+MBS_SMS4*15)); // Ciphertext, non-secret data _mm512_storeu_si512((__m512i*)(pOut), TMP[4]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[5]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[6]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[7]); } _mm_storeu_si128((__m128i*)(pIV), IV); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len) processedLen += cpSMS4_CBC_dec_gfni128x12(pOut, pInp, len, pRKey, pIV); return processedLen; } /* // 12*MBS_SMS4 bytes processing */ static int cpSMS4_CBC_dec_gfni128x12(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m128i TMP[19]; TMP[3] = _mm_loadu_si128((__m128i*)(pIV)); int processedLen = len -(len % (12*MBS_SMS4)); int n; for(n=0; n= 1920) */ #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ccmdecrypt.c000066400000000000000000000143201470420105600252030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsSMS4_CCMDecrypt() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4authccm.h" #include "pcptool.h" /*F* // Name: ippsSMS4_CCMDecrypt // // Purpose: Decrypts data and updates authentication tag. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr !VALID_SMS4CCM_ID() // ippStsLengthErr if exceed overall length of message is being processed // ippStsNoErr no errors // // Parameters: // pSrc pointer to the cipher text buffer // pDst pointer to the plane text bubber // len length of the bugger // pCtx pointer to the CCM context // *F*/ /* // // NOTE // // We consider to not spend time for further optimizing of this algorithm because it is not widely using. // There is two ways for further optimization: // - Add parallel processing of CTR cipher. Performance advantages can be achieved by parallel processing of a big number of blocks. // - Try to decrease the memory reading/writing operation number, eg combine two calls of one block encryption // function to single call that processes two blocks with the same key. Performance advantages can be achieved by // reducing of reading/writing operations number, because we do not need to read the key twice in single loop. // */ IPPFUN(IppStatus, ippsSMS4_CCMDecrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsSMS4_CCMState* pCtx)) { /* test pCtx pointer */ IPP_BAD_PTR1_RET(pCtx); /* test state ID */ IPP_BADARG_RET(!VALID_SMS4CCM_ID(pCtx), ippStsContextMatchErr); /* test source/destination data */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test message length */ IPP_BADARG_RET(len<0 || SMS4CCM_LENPRO(pCtx)+(Ipp64u)len >SMS4CCM_MSGLEN(pCtx), ippStsLengthErr); /* // enctypt payload and update MAC */ if(len) { /* SMS4 context */ IppsSMS4Spec* pSMS4 = SMS4CCM_CIPHER(pCtx); /* buffer for secret data */ __ALIGN16 Ipp32u TMP[3*(MBS_SMS4/sizeof(Ipp32u))+6]; /* MAC size = MBS_SMS4/sizeof(Ipp32u) CTR size = MBS_SMS4/sizeof(Ipp32u) S size = MBS_SMS4/sizeof(Ipp32u) flag size = 1 qLen size = 1 tmpLen size = 1 counterVal size = 1 counterEnc size = 2 */ Ipp32u* MAC = TMP; Ipp32u* CTR = TMP + MBS_SMS4/sizeof(Ipp32u); Ipp32u* S = TMP + 2*(MBS_SMS4/sizeof(Ipp32u)); Ipp32u* flag = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)); Ipp32u* qLen = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 1; Ipp32u* tmpLen = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 2; Ipp32u* counterVal = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 3; Ipp32u* counterEnc = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 4; *flag = (Ipp32u)( SMS4CCM_LENPRO(pCtx) &(MBS_SMS4-1) ); /* extract from the state */ CopyBlock16(SMS4CCM_MAC(pCtx), MAC); CopyBlock16(SMS4CCM_CTR0(pCtx), CTR); CopyBlock16(SMS4CCM_Si(pCtx), S); *counterVal = SMS4CCM_COUNTER(pCtx); /* extract qLen */ *qLen = (((Ipp8u*)CTR)[0] &0x7) +1; /* &0x7 just to fix KW issue */ if(*flag) { *tmpLen = (Ipp32u)( IPP_MIN(len, MBS_SMS4-1) ); XorBlock(pSrc, (Ipp8u*)S+*flag, pDst, (Ipp32s)(*tmpLen)); /* copy as much input as possible into the internal buffer*/ CopyBlock(pDst, SMS4CCM_BLK(pCtx)+*flag, (cpSize)(*tmpLen)); /* update MAC */ if(*flag+*tmpLen == MBS_SMS4) { XorBlock16(MAC, SMS4CCM_BLK(pCtx), MAC); cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); } SMS4CCM_LENPRO(pCtx) += *tmpLen; pSrc += *tmpLen; pDst += *tmpLen; len -= *tmpLen; } while(len >= MBS_SMS4) { /* increment counter and format counter block */ *counterVal+=1; CopyBlock(CounterEnc(counterEnc, (Ipp32s)(*qLen), *counterVal), ((Ipp8u*)CTR)+MBS_SMS4-*qLen, (cpSize)(*qLen)); /* encode counter block */ cpSMS4_Cipher((Ipp8u*)S, (Ipp8u*)CTR, SMS4_RK(pSMS4)); /* store cipher text */ XorBlock16(pSrc, S, pDst); /* update MAC */ XorBlock16(MAC, pDst, MAC); cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); SMS4CCM_LENPRO(pCtx) += MBS_SMS4; pSrc += MBS_SMS4; pDst += MBS_SMS4; len -= MBS_SMS4; } if(len) { /* increment counter and format counter block */ *counterVal+=1; CopyBlock(CounterEnc(counterEnc, (Ipp32s)(*qLen), *counterVal), ((Ipp8u*)CTR)+MBS_SMS4-*qLen, (cpSize)(*qLen)); /* encode counter block */ cpSMS4_Cipher((Ipp8u*)S, (Ipp8u*)CTR, SMS4_RK(pSMS4)); /* store cipher text */ XorBlock(pSrc, S, pDst, len); /* workaround to avoid false positive stringop-overflow error on gcc10.1 and gcc11.1 */ len = ( IPP_MIN(len, MBS_SMS4-1) ); /* store partial data block */ CopyBlock(pDst, SMS4CCM_BLK(pCtx), len); SMS4CCM_LENPRO(pCtx) += (Ipp64u)len; } /* update state */ CopyBlock16(MAC, SMS4CCM_MAC(pCtx)); CopyBlock16(S, SMS4CCM_Si(pCtx)); SMS4CCM_COUNTER(pCtx) = *counterVal; /* clear secret data */ PurgeBlock(TMP, sizeof(TMP)); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ccmencrypt.c000066400000000000000000000142741470420105600252250ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Context: // ippsSMS4_CCMEncrypt() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4authccm.h" #include "pcptool.h" /*F* // Name: ippsSMS4_CCMEncrypt // // Purpose: Encrypts data and updates authentication tag. // // Returns: Reason: // ippStsNullPtrErr pCtx== NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr !VALID_SMS4CCM_ID() // ippStsLengthErr if exceed overall length of message is being processed // ippStsNoErr no errors // // Parameters: // pSrc pointer to the plane text buffer // pDst pointer to the cipher text bubber // len length of the buffer // pCtx pointer to the CCM context // *F*/ /* // // NOTE // // We consider to not spend time for further optimizing of this algorithm because it is not widely using. // There is two ways for further optimization: // - Add parallel processing of CTR cipher. Performance advantages can be achieved by parallel processing of a big number of blocks. // - Try to decrease the memory reading/writing operation number, eg combine two calls of one block encryption // function to single call that processes two blocks with the same key. Performance advantages can be achieved by // reducing of reading/writing operations number, because we do not need to read the key twice in single loop. // */ IPPFUN(IppStatus, ippsSMS4_CCMEncrypt,(const Ipp8u* pSrc, Ipp8u* pDst, int len, IppsSMS4_CCMState* pCtx)) { /* test pCtx pointer */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!VALID_SMS4CCM_ID(pCtx), ippStsContextMatchErr); /* test source/destination data */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test message length */ IPP_BADARG_RET(len<0 || SMS4CCM_LENPRO(pCtx)+(Ipp64u)len >SMS4CCM_MSGLEN(pCtx), ippStsLengthErr); /* // enctypt payload and update MAC */ if(len) { /* SMS4 context */ IppsSMS4Spec* pSMS4 = SMS4CCM_CIPHER(pCtx); /* buffer for secret data */ __ALIGN16 Ipp32u TMP[3*(MBS_SMS4/sizeof(Ipp32u))+6]; /* MAC size = MBS_SMS4/sizeof(Ipp32u) CTR size = MBS_SMS4/sizeof(Ipp32u) S size = MBS_SMS4/sizeof(Ipp32u) flag size = 1 qLen size = 1 tmpLen size = 1 counterVal size = 1 counterEnc size = 2 */ Ipp32u* MAC = TMP; Ipp32u* CTR = TMP + MBS_SMS4/sizeof(Ipp32u); Ipp32u* S = TMP + 2*(MBS_SMS4/sizeof(Ipp32u)); Ipp32u* flag = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)); Ipp32u* qLen = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 1; Ipp32u* tmpLen = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 2; Ipp32u* counterVal = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 3; Ipp32u* counterEnc = TMP + 3*(MBS_SMS4/sizeof(Ipp32u)) + 4; *flag = (Ipp32u)( SMS4CCM_LENPRO(pCtx) &(MBS_SMS4-1) ); /* extract from the state */ CopyBlock16(SMS4CCM_MAC(pCtx), MAC); CopyBlock16(SMS4CCM_CTR0(pCtx), CTR); CopyBlock16(SMS4CCM_Si(pCtx), S); *counterVal = SMS4CCM_COUNTER(pCtx); /* extract qLen */ *qLen = (((Ipp8u*)CTR)[0] &0x7) +1; /* &0x7 just to fix KW issue */ if(*flag) { *tmpLen = IPP_MIN((Ipp32u)len, MBS_SMS4-1); /* copy as much input as possible into the internal buffer*/ CopyBlock(pSrc, SMS4CCM_BLK(pCtx)+*flag, (cpSize)(*tmpLen)); XorBlock(pSrc, (Ipp8u*)S+*flag, pDst, (cpSize)(*tmpLen)); /* update MAC */ if(*flag+*tmpLen == MBS_SMS4) { XorBlock16(MAC, SMS4CCM_BLK(pCtx), MAC); cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); } SMS4CCM_LENPRO(pCtx) += (Ipp32u)*tmpLen; pSrc += *tmpLen; pDst += *tmpLen; len -= *tmpLen; } while(len >= MBS_SMS4) { /* update MAC */ XorBlock16(MAC, pSrc, MAC); cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); /* increment counter and format counter block */ *counterVal+=1; CopyBlock(CounterEnc(counterEnc, (Ipp32s)(*qLen), *counterVal), ((Ipp8u*)CTR)+MBS_SMS4-*qLen, (Ipp32s)(*qLen)); /* encode counter block */ cpSMS4_Cipher((Ipp8u*)S, (Ipp8u*)CTR, SMS4_RK(pSMS4)); /* store cipher text */ XorBlock16(pSrc, S, pDst); SMS4CCM_LENPRO(pCtx) += MBS_SMS4; pSrc += MBS_SMS4; pDst += MBS_SMS4; len -= MBS_SMS4; } if(len) { /* workaround to avoid false positive stringop-overflow error on gcc10.1 and gcc11.1 */ len = ( IPP_MIN(len, MBS_SMS4-1) ); /* store partial data block */ CopyBlock(pSrc, SMS4CCM_BLK(pCtx), len); /* increment counter and format counter block */ *counterVal+=1; CopyBlock(CounterEnc(counterEnc, (Ipp32s)(*qLen), *counterVal), ((Ipp8u*)CTR)+MBS_SMS4-*qLen, (Ipp32s)(*qLen)); /* encode counter block */ cpSMS4_Cipher((Ipp8u*)S, (Ipp8u*)CTR, SMS4_RK(pSMS4)); /* store cipher text */ XorBlock(pSrc, S, pDst, len); SMS4CCM_LENPRO(pCtx) += (Ipp64u)len; } /* update state */ CopyBlock16(MAC, SMS4CCM_MAC(pCtx)); CopyBlock16(S, SMS4CCM_Si(pCtx)); SMS4CCM_COUNTER(pCtx) = *counterVal; /* clear secret data */ PurgeBlock(TMP, sizeof(TMP)); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ccmgetsize.c000066400000000000000000000026511470420105600252070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // SMS4-CCM implementation. // // Content: // ippsSMS4_CCMGetSize() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4authccm.h" #include "pcptool.h" /*F* // Name: ippsSMS4_CCMGetSize // // Purpose: Returns size of SMS4-CCM state (bytes). // // Returns: Reason: // ippStsNullPtrErr pSzie == NULL // ippStsNoErr no errors // // Parameters: // pSize pointer to the size of CCM (in bytes) // *F*/ IPPFUN(IppStatus, ippsSMS4_CCMGetSize,(int * pSize)) { /* test size's pointer */ IPP_BAD_PTR1_RET(pSize); *pSize = cpSizeofCtx_SMS4CCM(); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ccmgettag.c000066400000000000000000000056701470420105600250140ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // SMS4-CCM implementation. // // Content: // ippsSMS4_CCMGetTag() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4authccm.h" #include "pcptool.h" /*F* // Name: ippsSMS4_CCMGetTag // // Purpose: Compute message auth tag and return one. // Note, that further encryption/decryption and auth tag update is possible // // Returns: Reason: // ippStsNullPtrErr pTag == NULL // pCtx == NULL // ippStsContextMatchErr !VALID_SMS4CCM_ID() // ippStsLengthErr MBS_SMS4 < tagLen // 1 > tagLen // ippStsNoErr no errors // // Parameters: // pTag pointer to the output authenticated tag // tagLen requested length of the tag // pCtx pointer to the CCM context // *F*/ IPPFUN(IppStatus, ippsSMS4_CCMGetTag,(Ipp8u* pTag, int tagLen, const IppsSMS4_CCMState* pCtx)) { /* test pCtx pointer */ IPP_BAD_PTR1_RET(pCtx); /* test state ID */ IPP_BADARG_RET(!VALID_SMS4CCM_ID(pCtx), ippStsContextMatchErr); /* test tag (pointer and length) */ IPP_BAD_PTR1_RET(pTag); IPP_BADARG_RET((Ipp32u)tagLen>SMS4CCM_TAGLEN(pCtx) || tagLen<1, ippStsLengthErr); { __ALIGN16 Ipp32u TMP[2*(MBS_SMS4/sizeof(Ipp32u)) + 1]; /* MAC size = MBS_SMS4/sizeof(Ipp32u) BLK size = MBS_SMS4/sizeof(Ipp32u) flag size = 1 */ Ipp32u* MAC = TMP; Ipp32u* BLK = TMP + (MBS_SMS4/sizeof(Ipp32u)); Ipp32u* flag = TMP + 2*(MBS_SMS4/sizeof(Ipp32u)); *flag = (Ipp32u)( SMS4CCM_LENPRO(pCtx) &(MBS_SMS4-1) ); CopyBlock16(SMS4CCM_MAC(pCtx), MAC); if(*flag) { /* SMS4 context */ IppsSMS4Spec* pSMS4 = SMS4CCM_CIPHER(pCtx); FillBlock16(0, NULL,BLK, 0); CopyBlock(SMS4CCM_BLK(pCtx), (Ipp8u*)BLK, (cpSize)(*flag)); XorBlock16(MAC, BLK, MAC); cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); } XorBlock(MAC, SMS4CCM_S0(pCtx), pTag, tagLen); /* clear secret data */ PurgeBlock(TMP, sizeof(TMP)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ccminit.c000066400000000000000000000041151470420105600244750ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // SMS4-CCM implementation. // // Content: // ippsSMS4_CCMInit() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4authccm.h" #include "pcptool.h" /*F* // Name: ippsSMS4_CCMInit // // Purpose: Init SMS4-CCM state. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsMemAllocErr size of buffer is not match for operation // ippStsLengthErr keyLen < 16 // ippStsNoErr no errors // // Parameters: // pKey pointer to the secret key // keyLen length of secret key (in bytes) // pCtx pointer to initialized as CCM context // ctxSize available size (in bytes) of buffer above // *F*/ IPPFUN(IppStatus, ippsSMS4_CCMInit,(const Ipp8u* pKey, int keyLen, IppsSMS4_CCMState* pCtx, int ctxSize)) { /* test pCtx pointer */ IPP_BAD_PTR1_RET(pCtx); /* test available size of context buffer */ IPP_BADARG_RET(ctxSize13), ippStsLengthErr); /* test AAD pointer if defined */ IPP_BADARG_RET(adLen<0, ippStsLengthErr); if(adLen) IPP_BAD_PTR1_RET(pAD); /* init for new message */ SMS4CCM_LENPRO(pCtx) = 0; SMS4CCM_COUNTER(pCtx) = 0; { /* setup encoder function */ IppsSMS4Spec* pSMS4 = SMS4CCM_CIPHER(pCtx); __ALIGN16 Ipp32u TMP[4*(MBS_SMS4/sizeof(Ipp32u)) + 8]; /* MAC size = MBS_SMS4/sizeof(Ipp32u) CTR size = MBS_SMS4/sizeof(Ipp32u) block size = 2*MBS_SMS4/sizeof(Ipp32u) qLen size = 1 qLenEnc size = 1 tagLenEnc size = 1 payloadLen size = 2 adLenEnc size = 3 */ Ipp32u* MAC = TMP; Ipp32u* CTR = TMP + (MBS_SMS4/sizeof(Ipp32u)); Ipp32u* block = TMP + 2*(MBS_SMS4/sizeof(Ipp32u)); Ipp32u* qLen = TMP + 4*(MBS_SMS4/sizeof(Ipp32u)); Ipp32u* qLenEnc = TMP + 4*(MBS_SMS4/sizeof(Ipp32u)) + 1; Ipp32u* tagLenEnc = TMP + 4*(MBS_SMS4/sizeof(Ipp32u)) + 2; Ipp32u* payloadLen = TMP + 4*(MBS_SMS4/sizeof(Ipp32u)) + 3; Ipp32u* adLenEnc = TMP + 4*(MBS_SMS4/sizeof(Ipp32u)) + 5; /* // prepare the 1-st input block B0 and encode */ *qLen = (Ipp32u)( (MBS_SMS4-1) - ivLen); *qLenEnc = *qLen-1; *tagLenEnc = (SMS4CCM_TAGLEN(pCtx)-2)>>1; *((Ipp64u*)payloadLen) = SMS4CCM_MSGLEN(pCtx); ((Ipp8u*)MAC)[0] = (Ipp8u)( (Ipp32u)((adLen!=0) <<6) + (*tagLenEnc<<3) + *qLenEnc); /* flags */ #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) MAC[2] = ENDIANNESS(IPP_HIDWORD(*((Ipp64u*)payloadLen))); MAC[3] = ENDIANNESS(IPP_LODWORD(*((Ipp64u*)payloadLen))); #else MAC[2] = IPP_HIDWORD(*((Ipp64u*)payloadLen)); MAC[3] = IPP_LODWORD(*((Ipp64u*)payloadLen)); #endif CopyBlock(pIV, ((Ipp8u*)MAC)+1, ivLen); cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); /* setup CTR0 */ FillBlock16(0, NULL,CTR, 0); ((Ipp8u*)CTR)[0] = (Ipp8u)(*qLenEnc); /* flags */ CopyBlock(pIV, ((Ipp8u*)CTR)+1, ivLen); CopyBlock16(CTR, SMS4CCM_CTR0(pCtx)); /* compute and store S0=ENC(CTR0) */ cpSMS4_Cipher(SMS4CCM_S0(pCtx), (Ipp8u*)CTR, SMS4_RK(pSMS4)); /* // update MAC by the AD */ if(adLen) { /* encode length of associated data */ Ipp8u* adLenEncPtr; int adLenEncSize; #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) adLenEnc[1] = ENDIANNESS(IPP_HIDWORD(adLen)); adLenEnc[2] = ENDIANNESS(IPP_LODWORD(adLen)); #else adLenEnc[1] = IPP_HIDWORD(adLen); adLenEnc[2] = IPP_LODWORD(adLen); #endif if(adLen >= 0xFF00) { adLenEncSize = 6; #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) adLenEnc[1] = 0xFEFFFFFF; #else adLenEnc[1] = 0xFFFFFFFE; #endif } else { adLenEncSize= 2; } adLenEncPtr = (Ipp8u*)adLenEnc+3*sizeof(Ipp32u)-adLenEncSize; /* prepare first formatted block of Header */ CopyBlock(adLenEncPtr, block, adLenEncSize); FillBlock16(0,pAD, (Ipp8u*)block+adLenEncSize, IPP_MIN((MBS_SMS4-adLenEncSize), adLen)); /* and update MAC */ MAC[0] ^= block[0]; MAC[1] ^= block[1]; MAC[2] ^= block[2]; MAC[3] ^= block[3]; cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); /* update MAC the by rest of addition data */ if( (adLen+adLenEncSize) > MBS_SMS4 ) { pAD += (MBS_SMS4-adLenEncSize); adLen -= (MBS_SMS4-adLenEncSize); while(adLen >= MBS_SMS4) { CopyBlock16(pAD, block); MAC[0] ^= block[0]; MAC[1] ^= block[1]; MAC[2] ^= block[2]; MAC[3] ^= block[3]; cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); pAD += MBS_SMS4; adLen -= MBS_SMS4; } if(adLen) { FillBlock16(0, pAD, block, (int)adLen); MAC[0] ^= block[0]; MAC[1] ^= block[1]; MAC[2] ^= block[2]; MAC[3] ^= block[3]; cpSMS4_Cipher((Ipp8u*)MAC, (Ipp8u*)MAC, SMS4_RK(pSMS4)); } } } SMS4CCM_COUNTER(pCtx) = 0; CopyBlock16(MAC, SMS4CCM_MAC(pCtx)); /* clear secret data */ PurgeBlock(TMP, sizeof(TMP)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ccmtaglen.c000066400000000000000000000035061470420105600250070ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // Purpose: // Cryptography Primitive. // SMS4-CCM implementation. // // Content: // ippsSMS4_CCMTagLen() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4authccm.h" #include "pcptool.h" /*F* // Name: ippsSMS4_CCMTagLen // // Purpose: Setup length of the tag. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // ippStsContextMatchErr !VALID_SMS4CCM_ID() // ippStsLengthErr MBS_SMS4 < tagLen || tagLen < 4 // or odd value of tagLen // ippStsNoErr no errors // // Parameters: // tagLen length in bytes of the requested tag // pCtx pointer to the CCM context // *F*/ IPPFUN(IppStatus, ippsSMS4_CCMTagLen,(int tagLen, IppsSMS4_CCMState* pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); IPP_BADARG_RET(!VALID_SMS4CCM_ID(pCtx), ippStsContextMatchErr); /* test tag length */ IPP_BADARG_RET(tagLen>MBS_SMS4 || tagLen<4 || tagLen&1, ippStsLengthErr); /* init for new message */ SMS4CCM_TAGLEN(pCtx) = (Ipp32u)tagLen; return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_cfb_gfni.c000066400000000000000000002262761470420105600246220ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 CFB decryption // // Contents: // cpSMS4_CFB_gfni512() // cpSMS4_CFB_gfni512x48() // cpSMS4_CFB_gfni512x32() // cpSMS4_CFB_gfni512x16() // cpSMS4_CFB_gfni128x12() // cpSMS4_CFB_gfni128x8() // cpSMS4_CFB_gfni128x4() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) #include "pcpsms4_gfni.h" static void cpSMS4_CFB_dec_gfni512x48(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV); static void cpSMS4_CFB_dec_gfni512x32(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV); static void cpSMS4_CFB_dec_gfni512x16(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV); static void cpSMS4_CFB_dec_gfni128x12(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV); static void cpSMS4_CFB_dec_gfni128x8(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV); static void cpSMS4_CFB_dec_gfni128x4(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV); __FORCEINLINE Ipp64u broadcast_16to64(Ipp16u mask16) { Ipp64u mask64 = (Ipp64u)mask16; mask64 = (mask64 << 48) | (mask64 << 32) | (mask64 << 16) | mask64; return mask64; } __FORCEINLINE __m512i getInputBlocks(__m128i * const currentState, const __m512i * const pCipherBlocks, __mmask16 blocksCompressMask) { /* extract 128-bit cipher blocks */ __m128i c0 = _mm512_extracti64x2_epi64(*pCipherBlocks, 0); __m128i c1 = _mm512_extracti64x2_epi64(*pCipherBlocks, 1); __m128i c2 = _mm512_extracti64x2_epi64(*pCipherBlocks, 2); __m128i c3 = _mm512_extracti64x2_epi64(*pCipherBlocks, 3); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ __m128i inpBlk0 = *currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ __m128i inpBlk1 = _mm_mask_compress_epi8(c0, blocksCompressMask, inpBlk0); __m128i inpBlk2 = _mm_mask_compress_epi8(c1, blocksCompressMask, inpBlk1); __m128i inpBlk3 = _mm_mask_compress_epi8(c2, blocksCompressMask, inpBlk2); /* next InputBlock ready */ *currentState = _mm_mask_compress_epi8(c3, blocksCompressMask, inpBlk3); /* inserts */ __m512i inpBlk512 = _mm512_setzero_si512(); inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0x03, inpBlk0); /* 0000 0011 */ inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0x0C, inpBlk1); /* 0000 1100 */ inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0x30, inpBlk2); /* 0011 0000 */ inpBlk512 = _mm512_mask_broadcast_i64x2(inpBlk512, 0xC0, inpBlk3); /* 1100 0000 */ return inpBlk512; } /* // 64*cfbBlkSize bytes processing */ IPP_OWN_DEFN (void, cpSMS4_CFB_dec_gfni512, (Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV)) { __ALIGN16 __m512i TMP[24]; /* // TMP[0..15] - decrypted text blocks // TMP[16..19] - key // TMP[20..23] - temp out */ const int bytesPerLoad512 = 4 * cfbBlkSize; const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (64 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask64 kLsbMask64 = broadcast_16to64((Ipp16u)(0xFFFF << (16-cfbBlkSize))); /* same mask to load in MSB parts */ __mmask64 kMsbMask64 = broadcast_16to64(~blocksCompressMask); /* load IV */ __m128i currentState = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); for (blocks = len / cfbBlkSize; blocks >= (64); blocks -= (64)) { /* load cipher blocks to LSB parts of registers */ __m512i ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 0 * bytesPerLoad512); __m512i ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 1 * bytesPerLoad512); __m512i ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 2 * bytesPerLoad512); __m512i ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 3 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[0], TMP[1], TMP[2], TMP[3], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 4 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 5 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 6 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 7 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 8 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 9 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 10 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 11 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 12 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 13 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 14 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 15 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); int itr; for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[19] = TMP[18] = TMP[17] = TMP[16] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[16] = _mm512_xor_si512(TMP[16], TMP[1] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[2] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[3] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[5] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[6] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[7] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[9] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[10]); TMP[18] = _mm512_xor_si512(TMP[18], TMP[11]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[13]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[14]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[15]); /* Sbox */ TMP[16] = sBox512(TMP[16]); TMP[17] = sBox512(TMP[17]); TMP[18] = sBox512(TMP[18]); TMP[19] = sBox512(TMP[19]); /* Sbox done, now L */ TMP[0] = _mm512_xor_si512(_mm512_xor_si512(TMP[0], TMP[16]), L512(TMP[16])); TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[17]), L512(TMP[17])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[18]), L512(TMP[18])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[19]), L512(TMP[19])); /* initial xors */ TMP[19] = TMP[18] = TMP[17] = TMP[16] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[16] = _mm512_xor_si512(TMP[16], TMP[2] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[3] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[0] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[6] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[7] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[4] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[10]); TMP[18] = _mm512_xor_si512(TMP[18], TMP[11]); TMP[18] = _mm512_xor_si512(TMP[18], TMP[8] ); TMP[19] = _mm512_xor_si512(TMP[19], TMP[14]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[15]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[12]); /* Sbox */ TMP[16] = sBox512(TMP[16]); TMP[17] = sBox512(TMP[17]); TMP[18] = sBox512(TMP[18]); TMP[19] = sBox512(TMP[19]); /* Sbox done, now L */ TMP[1] = _mm512_xor_si512(_mm512_xor_si512(TMP[1], TMP[16]), L512(TMP[16])); TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[17]), L512(TMP[17])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[18]), L512(TMP[18])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[19]), L512(TMP[19])); /* initial xors */ TMP[19] = TMP[18] = TMP[17] = TMP[16] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[16] = _mm512_xor_si512(TMP[16], TMP[3] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[0] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[1] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[7] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[4] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[5] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[11]); TMP[18] = _mm512_xor_si512(TMP[18], TMP[8] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[9] ); TMP[19] = _mm512_xor_si512(TMP[19], TMP[15]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[12]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[13]); /* Sbox */ TMP[16] = sBox512(TMP[16]); TMP[17] = sBox512(TMP[17]); TMP[18] = sBox512(TMP[18]); TMP[19] = sBox512(TMP[19]); /* Sbox done, now L */ TMP[2] = _mm512_xor_si512(_mm512_xor_si512(TMP[2], TMP[16]), L512(TMP[16])); TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[17]), L512(TMP[17])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[18]), L512(TMP[18])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[19]), L512(TMP[19])); /* initial xors */ TMP[19] = TMP[18] = TMP[17] = TMP[16] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[16] = _mm512_xor_si512(TMP[16], TMP[0] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[1] ); TMP[16] = _mm512_xor_si512(TMP[16], TMP[2] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[4] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[5] ); TMP[17] = _mm512_xor_si512(TMP[17], TMP[6] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[8] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[9] ); TMP[18] = _mm512_xor_si512(TMP[18], TMP[10]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[12]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[13]); TMP[19] = _mm512_xor_si512(TMP[19], TMP[14]); /* Sbox */ TMP[16] = sBox512(TMP[16]); TMP[17] = sBox512(TMP[17]); TMP[18] = sBox512(TMP[18]); TMP[19] = sBox512(TMP[19]); /* Sbox done, now L */ TMP[3] = _mm512_xor_si512(_mm512_xor_si512(TMP[3], TMP[16]), L512(TMP[16])); TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[17]), L512(TMP[17])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[18]), L512(TMP[18])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[19]), L512(TMP[19])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[20], TMP[21], TMP[22], TMP[23], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[20] = _mm512_shuffle_epi8(TMP[20], M512(swapBytes)); TMP[21] = _mm512_shuffle_epi8(TMP[21], M512(swapBytes)); TMP[22] = _mm512_shuffle_epi8(TMP[22], M512(swapBytes)); TMP[23] = _mm512_shuffle_epi8(TMP[23], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 0 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 1 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 2 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 3 * bytesPerLoad512); TMP[20] = _mm512_xor_si512(ciphBytes0, TMP[20]); TMP[21] = _mm512_xor_si512(ciphBytes1, TMP[21]); TMP[22] = _mm512_xor_si512(ciphBytes2, TMP[22]); TMP[23] = _mm512_xor_si512(ciphBytes3, TMP[23]); _mm512_mask_compressstoreu_epi8(pDst + 0 * bytesPerLoad512, kMsbMask64, TMP[20]); _mm512_mask_compressstoreu_epi8(pDst + 1 * bytesPerLoad512, kMsbMask64, TMP[21]); _mm512_mask_compressstoreu_epi8(pDst + 2 * bytesPerLoad512, kMsbMask64, TMP[22]); _mm512_mask_compressstoreu_epi8(pDst + 3 * bytesPerLoad512, kMsbMask64, TMP[23]); TRANSPOSE_OUT_512(TMP[20], TMP[21], TMP[22], TMP[23], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[20] = _mm512_shuffle_epi8(TMP[20], M512(swapBytes)); TMP[21] = _mm512_shuffle_epi8(TMP[21], M512(swapBytes)); TMP[22] = _mm512_shuffle_epi8(TMP[22], M512(swapBytes)); TMP[23] = _mm512_shuffle_epi8(TMP[23], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 4 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 5 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 6 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 7 * bytesPerLoad512); TMP[20] = _mm512_xor_si512(ciphBytes0, TMP[20]); TMP[21] = _mm512_xor_si512(ciphBytes1, TMP[21]); TMP[22] = _mm512_xor_si512(ciphBytes2, TMP[22]); TMP[23] = _mm512_xor_si512(ciphBytes3, TMP[23]); _mm512_mask_compressstoreu_epi8(pDst + 4 * bytesPerLoad512, kMsbMask64, TMP[20]); _mm512_mask_compressstoreu_epi8(pDst + 5 * bytesPerLoad512, kMsbMask64, TMP[21]); _mm512_mask_compressstoreu_epi8(pDst + 6 * bytesPerLoad512, kMsbMask64, TMP[22]); _mm512_mask_compressstoreu_epi8(pDst + 7 * bytesPerLoad512, kMsbMask64, TMP[23]); TRANSPOSE_OUT_512(TMP[20], TMP[21], TMP[22], TMP[23], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[20] = _mm512_shuffle_epi8(TMP[20], M512(swapBytes)); TMP[21] = _mm512_shuffle_epi8(TMP[21], M512(swapBytes)); TMP[22] = _mm512_shuffle_epi8(TMP[22], M512(swapBytes)); TMP[23] = _mm512_shuffle_epi8(TMP[23], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 8 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 9 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 10 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 11 * bytesPerLoad512); TMP[20] = _mm512_xor_si512(ciphBytes0, TMP[20]); TMP[21] = _mm512_xor_si512(ciphBytes1, TMP[21]); TMP[22] = _mm512_xor_si512(ciphBytes2, TMP[22]); TMP[23] = _mm512_xor_si512(ciphBytes3, TMP[23]); _mm512_mask_compressstoreu_epi8(pDst + 8 * bytesPerLoad512, kMsbMask64, TMP[20]); _mm512_mask_compressstoreu_epi8(pDst + 9 * bytesPerLoad512, kMsbMask64, TMP[21]); _mm512_mask_compressstoreu_epi8(pDst + 10 * bytesPerLoad512, kMsbMask64, TMP[22]); _mm512_mask_compressstoreu_epi8(pDst + 11 * bytesPerLoad512, kMsbMask64, TMP[23]); TRANSPOSE_OUT_512(TMP[20], TMP[21], TMP[22], TMP[23], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[20] = _mm512_shuffle_epi8(TMP[20], M512(swapBytes)); TMP[21] = _mm512_shuffle_epi8(TMP[21], M512(swapBytes)); TMP[22] = _mm512_shuffle_epi8(TMP[22], M512(swapBytes)); TMP[23] = _mm512_shuffle_epi8(TMP[23], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 12 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 13 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 14 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 15 * bytesPerLoad512); TMP[20] = _mm512_xor_si512(ciphBytes0, TMP[20]); TMP[21] = _mm512_xor_si512(ciphBytes1, TMP[21]); TMP[22] = _mm512_xor_si512(ciphBytes2, TMP[22]); TMP[23] = _mm512_xor_si512(ciphBytes3, TMP[23]); _mm512_mask_compressstoreu_epi8(pDst + 12 * bytesPerLoad512, kMsbMask64, TMP[20]); _mm512_mask_compressstoreu_epi8(pDst + 13 * bytesPerLoad512, kMsbMask64, TMP[21]); _mm512_mask_compressstoreu_epi8(pDst + 14 * bytesPerLoad512, kMsbMask64, TMP[22]); _mm512_mask_compressstoreu_epi8(pDst + 15 * bytesPerLoad512, kMsbMask64, TMP[23]); pSrc += 16 * bytesPerLoad512; pDst += 16 * bytesPerLoad512; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); cpSMS4_CFB_dec_gfni512x48(pDst, pSrc, len, cfbBlkSize, pRKey, pIV); } } /* // 48*cfbBlkSize bytes processing */ static void cpSMS4_CFB_dec_gfni512x48(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m512i TMP[19]; /* // TMP[0..11] - decrypted text blocks // TMP[12..14] - key // TMP[15..18] - temp out */ const int bytesPerLoad512 = 4 * cfbBlkSize; const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (48 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask64 kLsbMask64 = broadcast_16to64((Ipp16u)(0xFFFF << (16-cfbBlkSize))); /* same mask to load in MSB parts */ __mmask64 kMsbMask64 = broadcast_16to64(~blocksCompressMask); /* load IV */ __m128i currentState = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); for (blocks = len / cfbBlkSize; blocks >= (48); blocks -= (48)) { /* load cipher blocks to LSB parts of registers */ __m512i ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 0 * bytesPerLoad512); __m512i ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 1 * bytesPerLoad512); __m512i ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 2 * bytesPerLoad512); __m512i ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 3 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[0], TMP[1], TMP[2], TMP[3], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 4 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 5 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 6 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 7 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 8 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 9 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 10 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 11 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); int itr; for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[14] = TMP[13] = TMP[12] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[12] = _mm512_xor_si512(TMP[12], TMP[1] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[2] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[3] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[5] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[6] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[7] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[9] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[10]); TMP[14] = _mm512_xor_si512(TMP[14], TMP[11]); /* Sbox */ TMP[12] = sBox512(TMP[12]); TMP[13] = sBox512(TMP[13]); TMP[14] = sBox512(TMP[14]); /* Sbox done, now L */ TMP[0] = _mm512_xor_si512(_mm512_xor_si512(TMP[0], TMP[12]), L512(TMP[12])); TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[13]), L512(TMP[13])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[14]), L512(TMP[14])); /* initial xors */ TMP[14] = TMP[13] = TMP[12] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[12] = _mm512_xor_si512(TMP[12], TMP[2] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[3] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[0] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[6] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[7] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[4] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[10]); TMP[14] = _mm512_xor_si512(TMP[14], TMP[11]); TMP[14] = _mm512_xor_si512(TMP[14], TMP[8] ); /* Sbox */ TMP[12] = sBox512(TMP[12]); TMP[13] = sBox512(TMP[13]); TMP[14] = sBox512(TMP[14]); /* Sbox done, now L */ TMP[1] = _mm512_xor_si512(_mm512_xor_si512(TMP[1], TMP[12]), L512(TMP[12])); TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[13]), L512(TMP[13])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[14]), L512(TMP[14])); /* initial xors */ TMP[14] = TMP[13] = TMP[12] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[12] = _mm512_xor_si512(TMP[12], TMP[3] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[0] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[1] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[7] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[4] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[5] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[11]); TMP[14] = _mm512_xor_si512(TMP[14], TMP[8] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[9] ); /* Sbox */ TMP[12] = sBox512(TMP[12]); TMP[13] = sBox512(TMP[13]); TMP[14] = sBox512(TMP[14]); /* Sbox done, now L */ TMP[2] = _mm512_xor_si512(_mm512_xor_si512(TMP[2], TMP[12]), L512(TMP[12])); TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[13]), L512(TMP[13])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[14]), L512(TMP[14])); /* initial xors */ TMP[14] = TMP[13] = TMP[12] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[12] = _mm512_xor_si512(TMP[12], TMP[0] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[1] ); TMP[12] = _mm512_xor_si512(TMP[12], TMP[2] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[4] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[5] ); TMP[13] = _mm512_xor_si512(TMP[13], TMP[6] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[8] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[9] ); TMP[14] = _mm512_xor_si512(TMP[14], TMP[10]); /* Sbox */ TMP[12] = sBox512(TMP[12]); TMP[13] = sBox512(TMP[13]); TMP[14] = sBox512(TMP[14]); /* Sbox done, now L */ TMP[3] = _mm512_xor_si512(_mm512_xor_si512(TMP[3], TMP[12]), L512(TMP[12])); TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[13]), L512(TMP[13])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[14]), L512(TMP[14])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[15], TMP[16], TMP[17], TMP[18], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[15] = _mm512_shuffle_epi8(TMP[15], M512(swapBytes)); TMP[16] = _mm512_shuffle_epi8(TMP[16], M512(swapBytes)); TMP[17] = _mm512_shuffle_epi8(TMP[17], M512(swapBytes)); TMP[18] = _mm512_shuffle_epi8(TMP[18], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 0 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 1 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 2 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 3 * bytesPerLoad512); TMP[15] = _mm512_xor_si512(ciphBytes0, TMP[15]); TMP[16] = _mm512_xor_si512(ciphBytes1, TMP[16]); TMP[17] = _mm512_xor_si512(ciphBytes2, TMP[17]); TMP[18] = _mm512_xor_si512(ciphBytes3, TMP[18]); _mm512_mask_compressstoreu_epi8(pDst + 0 * bytesPerLoad512, kMsbMask64, TMP[15]); _mm512_mask_compressstoreu_epi8(pDst + 1 * bytesPerLoad512, kMsbMask64, TMP[16]); _mm512_mask_compressstoreu_epi8(pDst + 2 * bytesPerLoad512, kMsbMask64, TMP[17]); _mm512_mask_compressstoreu_epi8(pDst + 3 * bytesPerLoad512, kMsbMask64, TMP[18]); TRANSPOSE_OUT_512(TMP[15], TMP[16], TMP[17], TMP[18], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[15] = _mm512_shuffle_epi8(TMP[15], M512(swapBytes)); TMP[16] = _mm512_shuffle_epi8(TMP[16], M512(swapBytes)); TMP[17] = _mm512_shuffle_epi8(TMP[17], M512(swapBytes)); TMP[18] = _mm512_shuffle_epi8(TMP[18], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 4 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 5 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 6 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 7 * bytesPerLoad512); TMP[15] = _mm512_xor_si512(ciphBytes0, TMP[15]); TMP[16] = _mm512_xor_si512(ciphBytes1, TMP[16]); TMP[17] = _mm512_xor_si512(ciphBytes2, TMP[17]); TMP[18] = _mm512_xor_si512(ciphBytes3, TMP[18]); _mm512_mask_compressstoreu_epi8(pDst + 4 * bytesPerLoad512, kMsbMask64, TMP[15]); _mm512_mask_compressstoreu_epi8(pDst + 5 * bytesPerLoad512, kMsbMask64, TMP[16]); _mm512_mask_compressstoreu_epi8(pDst + 6 * bytesPerLoad512, kMsbMask64, TMP[17]); _mm512_mask_compressstoreu_epi8(pDst + 7 * bytesPerLoad512, kMsbMask64, TMP[18]); TRANSPOSE_OUT_512(TMP[15], TMP[16], TMP[17], TMP[18], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[15] = _mm512_shuffle_epi8(TMP[15], M512(swapBytes)); TMP[16] = _mm512_shuffle_epi8(TMP[16], M512(swapBytes)); TMP[17] = _mm512_shuffle_epi8(TMP[17], M512(swapBytes)); TMP[18] = _mm512_shuffle_epi8(TMP[18], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 8 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 9 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 10 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 11 * bytesPerLoad512); TMP[15] = _mm512_xor_si512(ciphBytes0, TMP[15]); TMP[16] = _mm512_xor_si512(ciphBytes1, TMP[16]); TMP[17] = _mm512_xor_si512(ciphBytes2, TMP[17]); TMP[18] = _mm512_xor_si512(ciphBytes3, TMP[18]); _mm512_mask_compressstoreu_epi8(pDst + 8 * bytesPerLoad512, kMsbMask64, TMP[15]); _mm512_mask_compressstoreu_epi8(pDst + 9 * bytesPerLoad512, kMsbMask64, TMP[16]); _mm512_mask_compressstoreu_epi8(pDst + 10 * bytesPerLoad512, kMsbMask64, TMP[17]); _mm512_mask_compressstoreu_epi8(pDst + 11 * bytesPerLoad512, kMsbMask64, TMP[18]); pSrc += 12 * bytesPerLoad512; pDst += 12 * bytesPerLoad512; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); cpSMS4_CFB_dec_gfni512x32(pDst, pSrc, len, cfbBlkSize, pRKey, pIV); } } /* // 32*cfbBlkSize bytes processing */ static void cpSMS4_CFB_dec_gfni512x32(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m512i TMP[15]; /* // TMP[0..7] - decrypted text blocks // TMP[8..9] - key // TMP[10..14] - temp out */ const int bytesPerLoad512 = 4 * cfbBlkSize; const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (32 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask64 kLsbMask64 = broadcast_16to64((Ipp16u)(0xFFFF << (16-cfbBlkSize))); /* same mask to load in MSB parts */ __mmask64 kMsbMask64 = broadcast_16to64(~blocksCompressMask); /* load IV */ __m128i currentState = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); for (blocks = len / cfbBlkSize; blocks >= (32); blocks -= (32)) { /* load cipher blocks to LSB parts of registers */ __m512i ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 0 * bytesPerLoad512); __m512i ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 1 * bytesPerLoad512); __m512i ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 2 * bytesPerLoad512); __m512i ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 3 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[0], TMP[1], TMP[2], TMP[3], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 4 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 5 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 6 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 7 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); int itr; for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[9] = TMP[8] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[8] = _mm512_xor_si512(TMP[8], TMP[1] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[2] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[3] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[5] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[6] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[7] ); /* Sbox */ TMP[8] = sBox512(TMP[8]); TMP[9] = sBox512(TMP[9]); /* Sbox done, now L */ TMP[0] = _mm512_xor_si512(_mm512_xor_si512(TMP[0], TMP[8]), L512(TMP[8])); TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[9]), L512(TMP[9])); /* initial xors */ TMP[9] = TMP[8] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[8] = _mm512_xor_si512(TMP[8], TMP[2] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[3] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[0] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[6] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[7] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[4] ); /* Sbox */ TMP[8] = sBox512(TMP[8]); TMP[9] = sBox512(TMP[9]); /* Sbox done, now L */ TMP[1] = _mm512_xor_si512(_mm512_xor_si512(TMP[1], TMP[8]), L512(TMP[8])); TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[9]), L512(TMP[9])); /* initial xors */ TMP[9] = TMP[8] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[8] = _mm512_xor_si512(TMP[8], TMP[3] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[0] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[1] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[7] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[4] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[5] ); /* Sbox */ TMP[8] = sBox512(TMP[8]); TMP[9] = sBox512(TMP[9]); /* Sbox done, now L */ TMP[2] = _mm512_xor_si512(_mm512_xor_si512(TMP[2], TMP[8]), L512(TMP[8])); TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[9]), L512(TMP[9])); /* initial xors */ TMP[9] = TMP[8] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[8] = _mm512_xor_si512(TMP[8], TMP[0] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[1] ); TMP[8] = _mm512_xor_si512(TMP[8], TMP[2] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[4] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[5] ); TMP[9] = _mm512_xor_si512(TMP[9], TMP[6] ); /* Sbox */ TMP[8] = sBox512(TMP[8]); TMP[9] = sBox512(TMP[9]); /* Sbox done, now L */ TMP[3] = _mm512_xor_si512(_mm512_xor_si512(TMP[3], TMP[8]), L512(TMP[8])); TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[9]), L512(TMP[9])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[10], TMP[11], TMP[12], TMP[13], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[10] = _mm512_shuffle_epi8(TMP[10], M512(swapBytes)); TMP[11] = _mm512_shuffle_epi8(TMP[11], M512(swapBytes)); TMP[12] = _mm512_shuffle_epi8(TMP[12], M512(swapBytes)); TMP[13] = _mm512_shuffle_epi8(TMP[13], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 0 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 1 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 2 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 3 * bytesPerLoad512); TMP[10] = _mm512_xor_si512(ciphBytes0, TMP[10]); TMP[11] = _mm512_xor_si512(ciphBytes1, TMP[11]); TMP[12] = _mm512_xor_si512(ciphBytes2, TMP[12]); TMP[13] = _mm512_xor_si512(ciphBytes3, TMP[13]); _mm512_mask_compressstoreu_epi8(pDst + 0 * bytesPerLoad512, kMsbMask64, TMP[10]); _mm512_mask_compressstoreu_epi8(pDst + 1 * bytesPerLoad512, kMsbMask64, TMP[11]); _mm512_mask_compressstoreu_epi8(pDst + 2 * bytesPerLoad512, kMsbMask64, TMP[12]); _mm512_mask_compressstoreu_epi8(pDst + 3 * bytesPerLoad512, kMsbMask64, TMP[13]); TRANSPOSE_OUT_512(TMP[10], TMP[11], TMP[12], TMP[13], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[10] = _mm512_shuffle_epi8(TMP[10], M512(swapBytes)); TMP[11] = _mm512_shuffle_epi8(TMP[11], M512(swapBytes)); TMP[12] = _mm512_shuffle_epi8(TMP[12], M512(swapBytes)); TMP[13] = _mm512_shuffle_epi8(TMP[13], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 4 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 5 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 6 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 7 * bytesPerLoad512); TMP[10] = _mm512_xor_si512(ciphBytes0, TMP[10]); TMP[11] = _mm512_xor_si512(ciphBytes1, TMP[11]); TMP[12] = _mm512_xor_si512(ciphBytes2, TMP[12]); TMP[13] = _mm512_xor_si512(ciphBytes3, TMP[13]); _mm512_mask_compressstoreu_epi8(pDst + 4 * bytesPerLoad512, kMsbMask64, TMP[10]); _mm512_mask_compressstoreu_epi8(pDst + 5 * bytesPerLoad512, kMsbMask64, TMP[11]); _mm512_mask_compressstoreu_epi8(pDst + 6 * bytesPerLoad512, kMsbMask64, TMP[12]); _mm512_mask_compressstoreu_epi8(pDst + 7 * bytesPerLoad512, kMsbMask64, TMP[13]); pSrc += 8 * bytesPerLoad512; pDst += 8 * bytesPerLoad512; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); cpSMS4_CFB_dec_gfni512x16(pDst, pSrc, len, cfbBlkSize, pRKey, pIV); } } /* // 16*cfbBlkSize bytes processing */ static void cpSMS4_CFB_dec_gfni512x16(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m512i TMP[9]; /* // TMP[0..3] - decrypted text blocks // TMP[4] - key // TMP[5..8] - temp out */ const int bytesPerLoad512 = 4 * cfbBlkSize; const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (16 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask64 kLsbMask64 = broadcast_16to64((Ipp16u)(0xFFFF << (16-cfbBlkSize))); /* same mask to load in MSB parts */ __mmask64 kMsbMask64 = broadcast_16to64(~blocksCompressMask); /* load IV */ __m128i currentState = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); for (blocks = len / cfbBlkSize; blocks >= (16); blocks -= (16)) { /* load cipher blocks to LSB parts of registers */ __m512i ciphBytes0 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 0 * bytesPerLoad512); __m512i ciphBytes1 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 1 * bytesPerLoad512); __m512i ciphBytes2 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 2 * bytesPerLoad512); __m512i ciphBytes3 = _mm512_maskz_expandloadu_epi8(kLsbMask64, pSrc + 3 * bytesPerLoad512); /* prepare InputBlocks for decryption */ ciphBytes0 = getInputBlocks(¤tState, &ciphBytes0, blocksCompressMask); ciphBytes1 = getInputBlocks(¤tState, &ciphBytes1, blocksCompressMask); ciphBytes2 = getInputBlocks(¤tState, &ciphBytes2, blocksCompressMask); ciphBytes3 = getInputBlocks(¤tState, &ciphBytes3, blocksCompressMask); ciphBytes0 = _mm512_shuffle_epi8(ciphBytes0, M512(swapBytes)); ciphBytes1 = _mm512_shuffle_epi8(ciphBytes1, M512(swapBytes)); ciphBytes2 = _mm512_shuffle_epi8(ciphBytes2, M512(swapBytes)); ciphBytes3 = _mm512_shuffle_epi8(ciphBytes3, M512(swapBytes)); TRANSPOSE_INP_512(TMP[0], TMP[1], TMP[2], TMP[3], ciphBytes0, ciphBytes1, ciphBytes2, ciphBytes3); int itr; for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[4] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[1]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[2]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[3]); /* Sbox */ TMP[4] = sBox512(TMP[4]); /* Sbox done, now L */ TMP[0] = _mm512_xor_si512(_mm512_xor_si512(TMP[0], TMP[4]), L512(TMP[4])); /* initial xors */ TMP[4] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[2]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[3]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[0]); /* Sbox */ TMP[4] = sBox512(TMP[4]); /* Sbox done, now L */ TMP[1] = _mm512_xor_si512(_mm512_xor_si512(TMP[1], TMP[4]), L512(TMP[4])); /* initial xors */ TMP[4] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[3]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[0]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[1]); /* Sbox */ TMP[4] = sBox512(TMP[4]); /* Sbox done, now L */ TMP[2] = _mm512_xor_si512(_mm512_xor_si512(TMP[2], TMP[4]), L512(TMP[4])); /* initial xors */ TMP[4] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[0]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[1]); TMP[4] = _mm512_xor_si512(TMP[4], TMP[2]); /* Sbox */ TMP[4] = sBox512(TMP[4]); /* Sbox done, now L */ TMP[3] = _mm512_xor_si512(_mm512_xor_si512(TMP[3], TMP[4]), L512(TMP[4])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[5], TMP[6], TMP[7], TMP[8], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[5] = _mm512_shuffle_epi8(TMP[5], M512(swapBytes)); TMP[6] = _mm512_shuffle_epi8(TMP[6], M512(swapBytes)); TMP[7] = _mm512_shuffle_epi8(TMP[7], M512(swapBytes)); TMP[8] = _mm512_shuffle_epi8(TMP[8], M512(swapBytes)); /* load cipher blocks to MSB parts of registers */ ciphBytes0 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 0 * bytesPerLoad512); ciphBytes1 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 1 * bytesPerLoad512); ciphBytes2 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 2 * bytesPerLoad512); ciphBytes3 = _mm512_maskz_expandloadu_epi8(kMsbMask64, pSrc + 3 * bytesPerLoad512); TMP[5] = _mm512_xor_si512(ciphBytes0, TMP[5]); TMP[6] = _mm512_xor_si512(ciphBytes1, TMP[6]); TMP[7] = _mm512_xor_si512(ciphBytes2, TMP[7]); TMP[8] = _mm512_xor_si512(ciphBytes3, TMP[8]); _mm512_mask_compressstoreu_epi8(pDst + 0 * bytesPerLoad512, kMsbMask64, TMP[5]); _mm512_mask_compressstoreu_epi8(pDst + 1 * bytesPerLoad512, kMsbMask64, TMP[6]); _mm512_mask_compressstoreu_epi8(pDst + 2 * bytesPerLoad512, kMsbMask64, TMP[7]); _mm512_mask_compressstoreu_epi8(pDst + 3 * bytesPerLoad512, kMsbMask64, TMP[8]); pSrc += 4 * bytesPerLoad512; pDst += 4 * bytesPerLoad512; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); cpSMS4_CFB_dec_gfni128x12(pDst, pSrc, len, cfbBlkSize, pRKey, pIV); } } /* // 12*cfbBlkSize bytes processing */ static void cpSMS4_CFB_dec_gfni128x12(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m128i TMP[15]; /* // TMP[0..11] - decrypted text blocks // TMP[12..14] - key */ const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (12 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask16 kLsbMask16 = (Ipp16u)(0xFFFF << (16-cfbBlkSize)); /* same mask to load in MSB parts */ __mmask16 kMsbMask16 = ~blocksCompressMask; /* load IV */ __m128i IV128 = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); __m128i currentState = IV128; for (blocks = len / cfbBlkSize; blocks >= (12); blocks -= (12)) { /* load cipher blocks to LSB parts of registers */ __m128i ciphBytes0 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 0 * cfbBlkSize); __m128i ciphBytes1 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 1 * cfbBlkSize); __m128i ciphBytes2 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 2 * cfbBlkSize); __m128i ciphBytes3 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 3 * cfbBlkSize); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ TMP[0] = currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ TMP[1] = _mm_mask_compress_epi8(ciphBytes0, blocksCompressMask, TMP[0]); TMP[2] = _mm_mask_compress_epi8(ciphBytes1, blocksCompressMask, TMP[1]); TMP[3] = _mm_mask_compress_epi8(ciphBytes2, blocksCompressMask, TMP[2]); /* next InputBlock ready */ currentState = _mm_mask_compress_epi8(ciphBytes3, blocksCompressMask, TMP[3]); TMP[0] = _mm_shuffle_epi8(TMP[0], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TRANSPOSE_INP_128(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12]); /* TMP[12] - buffer */ /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 4 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 5 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 6 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 7 * cfbBlkSize); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ TMP[4] = currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ TMP[5] = _mm_mask_compress_epi8(ciphBytes0, blocksCompressMask, TMP[4]); TMP[6] = _mm_mask_compress_epi8(ciphBytes1, blocksCompressMask, TMP[5]); TMP[7] = _mm_mask_compress_epi8(ciphBytes2, blocksCompressMask, TMP[6]); /* next InputBlock ready */ currentState = _mm_mask_compress_epi8(ciphBytes3, blocksCompressMask, TMP[7]); TMP[4] = _mm_shuffle_epi8(TMP[4], M128(swapBytes)); TMP[5] = _mm_shuffle_epi8(TMP[5], M128(swapBytes)); TMP[6] = _mm_shuffle_epi8(TMP[6], M128(swapBytes)); TMP[7] = _mm_shuffle_epi8(TMP[7], M128(swapBytes)); TRANSPOSE_INP_128(TMP[4], TMP[5], TMP[6], TMP[7], TMP[12]); /* TMP[12] - buffer */ /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 8 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 9 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 10 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 11 * cfbBlkSize); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ TMP[8] = currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ TMP[9] = _mm_mask_compress_epi8(ciphBytes0, blocksCompressMask, TMP[8] ); TMP[10] = _mm_mask_compress_epi8(ciphBytes1, blocksCompressMask, TMP[9] ); TMP[11] = _mm_mask_compress_epi8(ciphBytes2, blocksCompressMask, TMP[10]); /* next InputBlock ready */ currentState = _mm_mask_compress_epi8(ciphBytes3, blocksCompressMask, TMP[11]); TMP[8] = _mm_shuffle_epi8(TMP[8], M128(swapBytes)); TMP[9] = _mm_shuffle_epi8(TMP[9], M128(swapBytes)); TMP[10] = _mm_shuffle_epi8(TMP[10], M128(swapBytes)); TMP[11] = _mm_shuffle_epi8(TMP[11], M128(swapBytes)); TRANSPOSE_INP_128(TMP[8], TMP[9], TMP[10], TMP[11], TMP[12]); /* TMP[12] - buffer */ int itr; for(itr=0; itr<8; itr++, pRKey+=4) { /* initial xors */ TMP[13] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[0]), 0); TMP[14] = TMP[13]; TMP[12] = TMP[13]; TMP[12] = _mm_xor_si128(TMP[12], TMP[1] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[2] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[3] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[5] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[6] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[7] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[9] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[10]); TMP[14] = _mm_xor_si128(TMP[14], TMP[11]); /* Sbox */ TMP[12] = sBox128(TMP[12]); TMP[13] = sBox128(TMP[13]); TMP[14] = sBox128(TMP[14]); /* Sbox done, now L */ TMP[0] = _mm_xor_si128(_mm_xor_si128(TMP[0], TMP[12]), L128(TMP[12])); TMP[4] = _mm_xor_si128(_mm_xor_si128(TMP[4], TMP[13]), L128(TMP[13])); TMP[8] = _mm_xor_si128(_mm_xor_si128(TMP[8], TMP[14]), L128(TMP[14])); /* initial xors */ TMP[13] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[1]), 0); TMP[14] = TMP[13]; TMP[12] = TMP[13]; TMP[12] = _mm_xor_si128(TMP[12], TMP[2] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[3] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[0] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[6] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[7] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[4] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[10]); TMP[14] = _mm_xor_si128(TMP[14], TMP[11]); TMP[14] = _mm_xor_si128(TMP[14], TMP[8] ); /* Sbox */ TMP[12] = sBox128(TMP[12]); TMP[13] = sBox128(TMP[13]); TMP[14] = sBox128(TMP[14]); /* Sbox done, now L */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[12]), L128(TMP[12])); TMP[5] = _mm_xor_si128(_mm_xor_si128(TMP[5], TMP[13]), L128(TMP[13])); TMP[9] = _mm_xor_si128(_mm_xor_si128(TMP[9], TMP[14]), L128(TMP[14])); /* initial xors */ TMP[13] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[2]), 0); TMP[14] = TMP[13]; TMP[12] = TMP[13]; TMP[12] = _mm_xor_si128(TMP[12], TMP[3] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[0] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[1] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[7] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[4] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[5] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[11]); TMP[14] = _mm_xor_si128(TMP[14], TMP[8] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[9] ); /* Sbox */ TMP[12] = sBox128(TMP[12]); TMP[13] = sBox128(TMP[13]); TMP[14] = sBox128(TMP[14]); /* Sbox done, now L */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[12]), L128(TMP[12])); TMP[6] = _mm_xor_si128(_mm_xor_si128(TMP[6], TMP[13]), L128(TMP[13])); TMP[10] = _mm_xor_si128(_mm_xor_si128(TMP[10], TMP[14]), L128(TMP[14])); /* initial xors */ TMP[13] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[3]), 0); TMP[14] = TMP[13]; TMP[12] = TMP[13]; TMP[12] = _mm_xor_si128(TMP[12], TMP[0] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[1] ); TMP[12] = _mm_xor_si128(TMP[12], TMP[2] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[4] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[5] ); TMP[13] = _mm_xor_si128(TMP[13], TMP[6] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[8] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[9] ); TMP[14] = _mm_xor_si128(TMP[14], TMP[10]); /* Sbox */ TMP[12] = sBox128(TMP[12]); TMP[13] = sBox128(TMP[13]); TMP[14] = sBox128(TMP[14]); /* Sbox done, now L */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[12]), L128(TMP[12])); TMP[7] = _mm_xor_si128(_mm_xor_si128(TMP[7], TMP[13]), L128(TMP[13])); TMP[11] = _mm_xor_si128(_mm_xor_si128(TMP[11], TMP[14]), L128(TMP[14])); } pRKey -= 32; TRANSPOSE_OUT_128(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12]); /* TMP[12] - buffer */ /* Order of blocks is inverted */ TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[0] = _mm_shuffle_epi8(TMP[0], M128(swapBytes)); ciphBytes0 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 0 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 1 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 2 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 3 * cfbBlkSize); TMP[3] = _mm_xor_si128(ciphBytes0, TMP[3]); TMP[2] = _mm_xor_si128(ciphBytes1, TMP[2]); TMP[1] = _mm_xor_si128(ciphBytes2, TMP[1]); TMP[0] = _mm_xor_si128(ciphBytes3, TMP[0]); _mm_mask_compressstoreu_epi8(pDst + 0 * cfbBlkSize, kMsbMask16, TMP[3]); _mm_mask_compressstoreu_epi8(pDst + 1 * cfbBlkSize, kMsbMask16, TMP[2]); _mm_mask_compressstoreu_epi8(pDst + 2 * cfbBlkSize, kMsbMask16, TMP[1]); _mm_mask_compressstoreu_epi8(pDst + 3 * cfbBlkSize, kMsbMask16, TMP[0]); TRANSPOSE_OUT_128(TMP[4], TMP[5], TMP[6], TMP[7], TMP[12]); /* TMP[12] - buffer */ /* Order of blocks is inverted */ TMP[7] = _mm_shuffle_epi8(TMP[7], M128(swapBytes)); TMP[6] = _mm_shuffle_epi8(TMP[6], M128(swapBytes)); TMP[5] = _mm_shuffle_epi8(TMP[5], M128(swapBytes)); TMP[4] = _mm_shuffle_epi8(TMP[4], M128(swapBytes)); ciphBytes0 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 4 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 5 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 6 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 7 * cfbBlkSize); TMP[7] = _mm_xor_si128(ciphBytes0, TMP[7]); TMP[6] = _mm_xor_si128(ciphBytes1, TMP[6]); TMP[5] = _mm_xor_si128(ciphBytes2, TMP[5]); TMP[4] = _mm_xor_si128(ciphBytes3, TMP[4]); _mm_mask_compressstoreu_epi8(pDst + 4 * cfbBlkSize, kMsbMask16, TMP[7]); _mm_mask_compressstoreu_epi8(pDst + 5 * cfbBlkSize, kMsbMask16, TMP[6]); _mm_mask_compressstoreu_epi8(pDst + 6 * cfbBlkSize, kMsbMask16, TMP[5]); _mm_mask_compressstoreu_epi8(pDst + 7 * cfbBlkSize, kMsbMask16, TMP[4]); TRANSPOSE_OUT_128(TMP[8], TMP[9], TMP[10], TMP[11], TMP[12]); /* TMP[12] - buffer */ /* Order of blocks is inverted */ TMP[11] = _mm_shuffle_epi8(TMP[11], M128(swapBytes)); TMP[10] = _mm_shuffle_epi8(TMP[10], M128(swapBytes)); TMP[9] = _mm_shuffle_epi8(TMP[9], M128(swapBytes)); TMP[8] = _mm_shuffle_epi8(TMP[8], M128(swapBytes)); ciphBytes0 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 8 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 9 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 10 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 11 * cfbBlkSize); TMP[11] = _mm_xor_si128(ciphBytes0, TMP[11]); TMP[10] = _mm_xor_si128(ciphBytes1, TMP[10]); TMP[9] = _mm_xor_si128(ciphBytes2, TMP[9]); TMP[8] = _mm_xor_si128(ciphBytes3, TMP[8]); _mm_mask_compressstoreu_epi8(pDst + 8 * cfbBlkSize, kMsbMask16, TMP[11]); _mm_mask_compressstoreu_epi8(pDst + 9 * cfbBlkSize, kMsbMask16, TMP[10]); _mm_mask_compressstoreu_epi8(pDst + 10 * cfbBlkSize, kMsbMask16, TMP[9]); _mm_mask_compressstoreu_epi8(pDst + 11 * cfbBlkSize, kMsbMask16, TMP[8]); pSrc += 12 * cfbBlkSize; pDst += 12 * cfbBlkSize; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_setzero_si128(); //_mm_xor_si128(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); cpSMS4_CFB_dec_gfni128x8(pDst, pSrc, len, cfbBlkSize, pRKey, pIV); } } /* // 8*cfbBlkSize bytes processing */ static void cpSMS4_CFB_dec_gfni128x8(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m128i TMP[10]; /* // TMP[0..7] - decrypted text blocks // TMP[8..9] - key */ const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (8 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask16 kLsbMask16 = (Ipp16u)(0xFFFF << (16-cfbBlkSize)); /* same mask to load in MSB parts */ __mmask16 kMsbMask16 = ~blocksCompressMask; /* load IV */ __m128i currentState = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); for (blocks = len / cfbBlkSize; blocks >= (8); blocks -= (8)) { /* load cipher blocks to LSB parts of registers */ __m128i ciphBytes0 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 0 * cfbBlkSize); __m128i ciphBytes1 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 1 * cfbBlkSize); __m128i ciphBytes2 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 2 * cfbBlkSize); __m128i ciphBytes3 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 3 * cfbBlkSize); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ TMP[0] = currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ TMP[1] = _mm_mask_compress_epi8(ciphBytes0, blocksCompressMask, TMP[0]); TMP[2] = _mm_mask_compress_epi8(ciphBytes1, blocksCompressMask, TMP[1]); TMP[3] = _mm_mask_compress_epi8(ciphBytes2, blocksCompressMask, TMP[2]); /* next InputBlock ready */ currentState = _mm_mask_compress_epi8(ciphBytes3, blocksCompressMask, TMP[3]); TMP[0] = _mm_shuffle_epi8(TMP[0], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TRANSPOSE_INP_128(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8]); /* TMP[8] - buffer */ /* load cipher blocks to LSB parts of registers */ ciphBytes0 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 4 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 5 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 6 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 7 * cfbBlkSize); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ TMP[4] = currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ TMP[5] = _mm_mask_compress_epi8(ciphBytes0, blocksCompressMask, TMP[4]); TMP[6] = _mm_mask_compress_epi8(ciphBytes1, blocksCompressMask, TMP[5]); TMP[7] = _mm_mask_compress_epi8(ciphBytes2, blocksCompressMask, TMP[6]); /* next InputBlock ready */ currentState = _mm_mask_compress_epi8(ciphBytes3, blocksCompressMask, TMP[7]); TMP[4] = _mm_shuffle_epi8(TMP[4], M128(swapBytes)); TMP[5] = _mm_shuffle_epi8(TMP[5], M128(swapBytes)); TMP[6] = _mm_shuffle_epi8(TMP[6], M128(swapBytes)); TMP[7] = _mm_shuffle_epi8(TMP[7], M128(swapBytes)); TRANSPOSE_INP_128(TMP[4], TMP[5], TMP[6], TMP[7], TMP[8]); /* TMP[8] - buffer */ int itr; for(itr=0; itr<8; itr++, pRKey+=4) { /* initial xors */ TMP[9] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[0]), 0); TMP[8] = TMP[9]; TMP[8] = _mm_xor_si128(TMP[8], TMP[1] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[2] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[3] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[5] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[6] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[7] ); /* Sbox */ TMP[8] = sBox128(TMP[8]); TMP[9] = sBox128(TMP[9]); /* Sbox done, now L */ TMP[0] = _mm_xor_si128(_mm_xor_si128(TMP[0], TMP[8]), L128(TMP[8])); TMP[4] = _mm_xor_si128(_mm_xor_si128(TMP[4], TMP[9]), L128(TMP[9])); /* initial xors */ TMP[9] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[1]), 0); TMP[8] = TMP[9]; TMP[8] = _mm_xor_si128(TMP[8], TMP[2] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[3] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[0] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[6] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[7] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[4] ); /* Sbox */ TMP[8] = sBox128(TMP[8]); TMP[9] = sBox128(TMP[9]); /* Sbox done, now L */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[8]), L128(TMP[8])); TMP[5] = _mm_xor_si128(_mm_xor_si128(TMP[5], TMP[9]), L128(TMP[9])); /* initial xors */ TMP[9] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[2]), 0); TMP[8] = TMP[9]; TMP[8] = _mm_xor_si128(TMP[8], TMP[3] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[0] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[1] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[7] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[4] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[5] ); /* Sbox */ TMP[8] = sBox128(TMP[8]); TMP[9] = sBox128(TMP[9]); /* Sbox done, now L */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[8]), L128(TMP[8])); TMP[6] = _mm_xor_si128(_mm_xor_si128(TMP[6], TMP[9]), L128(TMP[9])); /* initial xors */ TMP[9] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[3]), 0); TMP[8] = TMP[9]; TMP[8] = _mm_xor_si128(TMP[8], TMP[0] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[1] ); TMP[8] = _mm_xor_si128(TMP[8], TMP[2] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[4] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[5] ); TMP[9] = _mm_xor_si128(TMP[9], TMP[6] ); /* Sbox */ TMP[8] = sBox128(TMP[8]); TMP[9] = sBox128(TMP[9]); /* Sbox done, now L */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[8]), L128(TMP[8])); TMP[7] = _mm_xor_si128(_mm_xor_si128(TMP[7], TMP[9]), L128(TMP[9])); } pRKey -= 32; TRANSPOSE_OUT_128(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8]); /* TMP[8] - buffer */ /* Order of blocks is inverted */ TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[0] = _mm_shuffle_epi8(TMP[0], M128(swapBytes)); ciphBytes0 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 0 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 1 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 2 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 3 * cfbBlkSize); TMP[3] = _mm_xor_si128(ciphBytes0, TMP[3]); TMP[2] = _mm_xor_si128(ciphBytes1, TMP[2]); TMP[1] = _mm_xor_si128(ciphBytes2, TMP[1]); TMP[0] = _mm_xor_si128(ciphBytes3, TMP[0]); _mm_mask_compressstoreu_epi8(pDst + 0 * cfbBlkSize, kMsbMask16, TMP[3]); _mm_mask_compressstoreu_epi8(pDst + 1 * cfbBlkSize, kMsbMask16, TMP[2]); _mm_mask_compressstoreu_epi8(pDst + 2 * cfbBlkSize, kMsbMask16, TMP[1]); _mm_mask_compressstoreu_epi8(pDst + 3 * cfbBlkSize, kMsbMask16, TMP[0]); TRANSPOSE_OUT_128(TMP[4], TMP[5], TMP[6], TMP[7], TMP[8]); /* TMP[8] - buffer */ /* Order of blocks is inverted */ TMP[7] = _mm_shuffle_epi8(TMP[7], M128(swapBytes)); TMP[6] = _mm_shuffle_epi8(TMP[6], M128(swapBytes)); TMP[5] = _mm_shuffle_epi8(TMP[5], M128(swapBytes)); TMP[4] = _mm_shuffle_epi8(TMP[4], M128(swapBytes)); ciphBytes0 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 4 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 5 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 6 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 7 * cfbBlkSize); TMP[7] = _mm_xor_si128(ciphBytes0, TMP[7]); TMP[6] = _mm_xor_si128(ciphBytes1, TMP[6]); TMP[5] = _mm_xor_si128(ciphBytes2, TMP[5]); TMP[4] = _mm_xor_si128(ciphBytes3, TMP[4]); _mm_mask_compressstoreu_epi8(pDst + 4 * cfbBlkSize, kMsbMask16, TMP[7]); _mm_mask_compressstoreu_epi8(pDst + 5 * cfbBlkSize, kMsbMask16, TMP[6]); _mm_mask_compressstoreu_epi8(pDst + 6 * cfbBlkSize, kMsbMask16, TMP[5]); _mm_mask_compressstoreu_epi8(pDst + 7 * cfbBlkSize, kMsbMask16, TMP[4]); pSrc += 8 * cfbBlkSize; pDst += 8 * cfbBlkSize; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_setzero_si128(); //_mm_xor_si128(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); cpSMS4_CFB_dec_gfni128x4(pDst, pSrc, len, cfbBlkSize, pRKey, pIV); } } /* // 4*cfbBlkSize bytes processing */ static void cpSMS4_CFB_dec_gfni128x4(Ipp8u* pDst, const Ipp8u* pSrc, int len, int cfbBlkSize, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m128i TMP[5]; /* // TMP[0..3] - decrypted text blocks // TMP[4] - key */ const Ipp16u blocksCompressMask = (Ipp16u)(0xFFFF << cfbBlkSize); int processedLen = len - (len % (4 * cfbBlkSize)); int blocks; /* load masks; allows to load 4 source blocks of cfbBlkSize each (in bytes) to LSB parts of 128-bit lanes in 512-bit register */ __mmask16 kLsbMask16 = (Ipp16u)(0xFFFF << (16-cfbBlkSize)); /* same mask to load in MSB parts */ __mmask16 kMsbMask16 = ~blocksCompressMask; /* load IV */ __m128i currentState = _mm_maskz_loadu_epi64(0x03 /* load 128-bit */, pIV); for (blocks = len / cfbBlkSize; blocks >= (4); blocks -= (4)) { /* load cipher blocks to LSB parts of registers */ __m128i ciphBytes0 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 0 * cfbBlkSize); __m128i ciphBytes1 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 1 * cfbBlkSize); __m128i ciphBytes2 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 2 * cfbBlkSize); __m128i ciphBytes3 = _mm_maskz_expandloadu_epi8(kLsbMask16, pSrc + 3 * cfbBlkSize); /* InpBlk_j = LSB_(b-s)(InpBlk_(j-1)) | C_(j-1); b = 128 bit, s = 8*cfbBlkSize bit */ TMP[0] = currentState; /* drop MSB bits (size = cfbBlkSize) from the inpBlk_i (by mask) and append c_(i-1) to LSB bits */ TMP[1] = _mm_mask_compress_epi8(ciphBytes0, blocksCompressMask, TMP[0]); TMP[2] = _mm_mask_compress_epi8(ciphBytes1, blocksCompressMask, TMP[1]); TMP[3] = _mm_mask_compress_epi8(ciphBytes2, blocksCompressMask, TMP[2]); /* next InputBlock ready */ currentState = _mm_mask_compress_epi8(ciphBytes3, blocksCompressMask, TMP[3]); TMP[0] = _mm_shuffle_epi8(TMP[0], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TRANSPOSE_INP_128(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4]); /* TMP[4] - buffer */ int itr; for(itr=0; itr<8; itr++, pRKey+=4) { /* initial xors */ TMP[4] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[0]), 0); TMP[4] = _mm_xor_si128(TMP[4], TMP[1] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[2] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[3] ); /* Sbox */ TMP[4] = sBox128(TMP[4]); /* Sbox done, now L */ TMP[0] = _mm_xor_si128(_mm_xor_si128(TMP[0], TMP[4]), L128(TMP[4])); /* initial xors */ TMP[4] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[1]), 0); TMP[4] = _mm_xor_si128(TMP[4], TMP[2] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[3] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[0] ); /* Sbox */ TMP[4] = sBox128(TMP[4]); /* Sbox done, now L */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[4]), L128(TMP[4])); /* initial xors */ TMP[4] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[2]), 0); TMP[4] = _mm_xor_si128(TMP[4], TMP[3] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[0] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[1] ); /* Sbox */ TMP[4] = sBox128(TMP[4]); /* Sbox done, now L */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[4]), L128(TMP[4])); /* initial xors */ TMP[4] = _mm_shuffle_epi32(_mm_cvtsi32_si128((Ipp32s)pRKey[3]), 0); TMP[4] = _mm_xor_si128(TMP[4], TMP[0] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[1] ); TMP[4] = _mm_xor_si128(TMP[4], TMP[2] ); /* Sbox */ TMP[4] = sBox128(TMP[4]); /* Sbox done, now L */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[4]), L128(TMP[4])); } pRKey -= 32; TRANSPOSE_OUT_128(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4]); /* TMP[4] - buffer */ /* Order of blocks is inverted */ TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[0] = _mm_shuffle_epi8(TMP[0], M128(swapBytes)); ciphBytes0 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 0 * cfbBlkSize); ciphBytes1 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 1 * cfbBlkSize); ciphBytes2 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 2 * cfbBlkSize); ciphBytes3 = _mm_maskz_expandloadu_epi8(kMsbMask16, pSrc + 3 * cfbBlkSize); TMP[3] = _mm_xor_si128(ciphBytes0, TMP[3]); TMP[2] = _mm_xor_si128(ciphBytes1, TMP[2]); TMP[1] = _mm_xor_si128(ciphBytes2, TMP[1]); TMP[0] = _mm_xor_si128(ciphBytes3, TMP[0]); _mm_mask_compressstoreu_epi8(pDst + 0 * cfbBlkSize, kMsbMask16, TMP[3]); _mm_mask_compressstoreu_epi8(pDst + 1 * cfbBlkSize, kMsbMask16, TMP[2]); _mm_mask_compressstoreu_epi8(pDst + 2 * cfbBlkSize, kMsbMask16, TMP[1]); _mm_mask_compressstoreu_epi8(pDst + 3 * cfbBlkSize, kMsbMask16, TMP[0]); pSrc += 4 * cfbBlkSize; pDst += 4 * cfbBlkSize; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_setzero_si128(); //_mm_xor_si128(TMP[i],TMP[i]); } len -= processedLen; if (len){ _mm_storeu_si128((__m128i*)(pIV), currentState); } } #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_cipher.c000066400000000000000000000051341470420105600243230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpSMS4_Cipher() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" //#include "owndefs.h" static void cpSMS4_ECB_gpr_x1(Ipp8u* otxt, const Ipp8u* itxt, const Ipp32u* pRoundKeys) { __ALIGN16 Ipp32u buff[4 + SMS4_ROUND_KEYS_NUM]; buff[0] = HSTRING_TO_U32(itxt); buff[1] = HSTRING_TO_U32(itxt+sizeof(Ipp32u)); buff[2] = HSTRING_TO_U32(itxt+sizeof(Ipp32u)*2); buff[3] = HSTRING_TO_U32(itxt+sizeof(Ipp32u)*3); { int nr; for(nr=0; nr < SMS4_ROUND_KEYS_NUM; nr++) { buff[4+nr] = buff[nr] ^ cpCipherMix_SMS4(buff[nr+1]^buff[nr+2]^buff[nr+3]^pRoundKeys[nr]); } } U32_TO_HSTRING(otxt, buff[4 + SMS4_ROUND_KEYS_NUM - 1]); U32_TO_HSTRING(otxt+sizeof(Ipp32u), buff[4 + SMS4_ROUND_KEYS_NUM - 2]); U32_TO_HSTRING(otxt+sizeof(Ipp32u)*2, buff[4 + SMS4_ROUND_KEYS_NUM - 3]); U32_TO_HSTRING(otxt+sizeof(Ipp32u)*3, buff[4 + SMS4_ROUND_KEYS_NUM - 4]); /* clear secret data */ PurgeBlock(buff, sizeof(buff)); } IPP_OWN_DEFN (void, cpSMS4_Cipher, (Ipp8u* otxt, const Ipp8u* itxt, const Ipp32u* pRoundKeys)) { #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) if (IsFeatureEnabled(ippCPUID_AVX512GFNI)){ cpSMS4_ECB_gfni_x1(otxt, itxt, pRoundKeys); return; } else #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)){ cpSMS4_ECB_aesni_x1(otxt, itxt, pRoundKeys); return; } else #endif { cpSMS4_ECB_gpr_x1(otxt, itxt, pRoundKeys); return; } } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ctr_gfni.c000066400000000000000000002014051470420105600246430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 ECB decryption // // Contents: // cpSMS4_CTR_gfni512() // cpSMS4_CTR_gfni512x48() // cpSMS4_CTR_gfni512x32() // cpSMS4_CTR_gfni512x16() // cpSMS4_CTR_gfni128x12() // cpSMS4_CTR_gfni128x8() // cpSMS4_CTR_gfni128x4() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) #include "pcpsms4_gfni.h" static __ALIGN32 Ipp8u endianness_swap[] = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3}; static __ALIGN32 Ipp8u endianness[] = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; static __ALIGN16 Ipp8u first_inc[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static __ALIGN16 Ipp8u next_inc[] = {4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static __ALIGN16 Ipp8u one128[] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; __IPPCP_INLINE __m512i inc512(__m512i x, Ipp8u* increment) { __m512i t = _mm512_add_epi64(x, M512(increment)); __mmask8 carryMask = _mm512_cmplt_epu64_mask(t, x); carryMask = (__mmask8)(carryMask << 1); t = _mm512_add_epi64(t, _mm512_mask_set1_epi64(_mm512_setzero_si512(), carryMask, 1)); return t; } __IPPCP_INLINE __m128i inc128(__m128i x) { __m128i t = _mm_add_epi64(x, M128(one128)); x = _mm_cmpeq_epi64(t, _mm_setzero_si128()); t = _mm_sub_epi64(t, _mm_slli_si128(x, sizeof(Ipp64u))); return t; } static int cpSMS4_CTR_gfni512x48(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr); static int cpSMS4_CTR_gfni512x32(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr); static int cpSMS4_CTR_gfni512x16(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr); static int cpSMS4_CTR_gfni128x12(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr); static int cpSMS4_CTR_gfni128x8(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr); static int cpSMS4_ECB_gfni128x4(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr); /* // 64*MBS_SMS4 bytes processing */ IPP_OWN_DEFN (int, cpSMS4_CTR_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) { int processedLen = len - (len % (64 * MBS_SMS4)); int n; if(processedLen){ __ALIGN16 __m512i TMP[23]; // TMP[20] - ctr // TMP[21] - ctrMask // TMP[22] - ctrUnch TMP[20] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtr)); TMP[21] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtrMask)); /* read string counter and convert to numerical */ TMP[20] = _mm512_shuffle_epi8(TMP[20], M512(endianness)); /* read string mask and convert to numerical */ TMP[21] = _mm512_shuffle_epi8(TMP[21], M512(endianness)); /* upchanged counter bits */ TMP[22] = _mm512_andnot_si512(TMP[21], TMP[20]); /* first incremention */ TMP[20] = inc512(TMP[20], first_inc); TMP[20] = _mm512_and_si512(TMP[21], TMP[20]); for (n = 0; n < processedLen; n += (64 * MBS_SMS4), pInp += (64 * MBS_SMS4), pOut += (64 * MBS_SMS4)) { int itr; TMP[0] = TMP[20]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[20] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[0], TMP[21])); TMP[1] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[1], TMP[21])); TMP[2] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[2], TMP[21])); TMP[3] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[3], TMP[21])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = TMP[20]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[20] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[0], TMP[21])); TMP[1] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[1], TMP[21])); TMP[2] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[2], TMP[21])); TMP[3] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[3], TMP[21])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = TMP[20]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[20] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[0], TMP[21])); TMP[1] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[1], TMP[21])); TMP[2] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[2], TMP[21])); TMP[3] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[3], TMP[21])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = TMP[20]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[20] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[0], TMP[21])); TMP[1] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[1], TMP[21])); TMP[2] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[2], TMP[21])); TMP[3] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[3], TMP[21])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[2]), L512(TMP[2])); TMP[16] = _mm512_xor_si512(_mm512_xor_si512(TMP[16], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[2]), L512(TMP[2])); TMP[17] = _mm512_xor_si512(_mm512_xor_si512(TMP[17], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[2]), L512(TMP[2])); TMP[18] = _mm512_xor_si512(_mm512_xor_si512(TMP[18], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[2]), L512(TMP[2])); TMP[19] = _mm512_xor_si512(_mm512_xor_si512(TMP[19], TMP[3]), L512(TMP[3])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 32), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 32)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 36), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 36)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 40), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 40)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 44), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 44)))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 48), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 48)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 52), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 52)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 56), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 56)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 60), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 60)))); } /* Save counter */ TMP[20] = _mm512_xor_si512(TMP[22], _mm512_and_si512(TMP[20], TMP[21])); TMP[20] = _mm512_shuffle_epi8(TMP[20], M512(endianness)); _mm_storeu_si128((__m128i*)pCtr, _mm512_castsi512_si128(TMP[20])); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_xor_si512(TMP[i], TMP[i]); } } len -= processedLen; if (len) processedLen += cpSMS4_CTR_gfni512x48(pOut, pInp, len, pRKey, pCtrMask, pCtr); return processedLen; } /* // 48*MBS_SMS4 bytes processing */ static int cpSMS4_CTR_gfni512x48(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr) { int processedLen = len - (len % (48 * MBS_SMS4)); int n; if(processedLen){ __ALIGN16 __m512i TMP[19]; // TMP[16] - ctr // TMP[17] - ctrMask // TMP[18] - ctrUnch TMP[16] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtr)); TMP[17] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtrMask)); /* read string counter and convert to numerical */ TMP[16] = _mm512_shuffle_epi8(TMP[16], M512(endianness)); /* read string mask and convert to numerical */ TMP[17] = _mm512_shuffle_epi8(TMP[17], M512(endianness)); /* upchanged counter bits */ TMP[18] = _mm512_andnot_si512(TMP[17], TMP[16]); /* first incremention */ TMP[16] = inc512(TMP[16], first_inc); TMP[16] = _mm512_and_si512(TMP[17], TMP[16]); for (n = 0; n < processedLen; n += (48 * MBS_SMS4), pInp += (48 * MBS_SMS4), pOut += (48 * MBS_SMS4)) { int itr; TMP[0] = TMP[16]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[16] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[0], TMP[17])); TMP[1] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[1], TMP[17])); TMP[2] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[2], TMP[17])); TMP[3] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[3], TMP[17])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = TMP[16]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[16] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[0], TMP[17])); TMP[1] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[1], TMP[17])); TMP[2] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[2], TMP[17])); TMP[3] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[3], TMP[17])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = TMP[16]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[16] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[0], TMP[17])); TMP[1] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[1], TMP[17])); TMP[2] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[2], TMP[17])); TMP[3] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[3], TMP[17])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[2]), L512(TMP[2])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 32), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 32)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 36), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 36)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 40), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 40)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 44), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 44)))); } /* Save counter */ TMP[16] = _mm512_xor_si512(TMP[18], _mm512_and_si512(TMP[16], TMP[17])); TMP[16] = _mm512_shuffle_epi8(TMP[16], M512(endianness)); _mm_storeu_si128((__m128i*)pCtr, _mm512_castsi512_si128(TMP[16])); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_xor_si512(TMP[i], TMP[i]); } } len -= processedLen; if (len) processedLen += cpSMS4_CTR_gfni512x32(pOut, pInp, len, pRKey, pCtrMask, pCtr); return processedLen; } /* // 32*MBS_SMS4 bytes processing */ static int cpSMS4_CTR_gfni512x32(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr) { int processedLen = len - (len % (32 * MBS_SMS4)); int n; if(processedLen){ __ALIGN16 __m512i TMP[15]; // TMP[12] - ctr // TMP[13] - ctrMask // TMP[14] - ctrUnch TMP[12] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtr)); TMP[13] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtrMask)); /* read string counter and convert to numerical */ TMP[12] = _mm512_shuffle_epi8(TMP[12], M512(endianness)); /* read string mask and convert to numerical */ TMP[13] = _mm512_shuffle_epi8(TMP[13], M512(endianness)); /* upchanged counter bits */ TMP[14] = _mm512_andnot_si512(TMP[13], TMP[12]); /* first incremention */ TMP[12] = inc512(TMP[12], first_inc); TMP[12] = _mm512_and_si512(TMP[13], TMP[12]); for (n = 0; n < processedLen; n += (32 * MBS_SMS4), pInp += (32 * MBS_SMS4), pOut += (32 * MBS_SMS4)) { int itr; TMP[0] = TMP[12]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[12] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[0], TMP[13])); TMP[1] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[1], TMP[13])); TMP[2] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[2], TMP[13])); TMP[3] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[3], TMP[13])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = TMP[12]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[12] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[0], TMP[13])); TMP[1] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[1], TMP[13])); TMP[2] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[2], TMP[13])); TMP[3] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[3], TMP[13])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)))); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)))); } /* Save counter */ TMP[12] = _mm512_xor_si512(TMP[14], _mm512_and_si512(TMP[12], TMP[13])); TMP[12] = _mm512_shuffle_epi8(TMP[12], M512(endianness)); _mm_storeu_si128((__m128i*)pCtr, _mm512_castsi512_si128(TMP[12])); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_xor_si512(TMP[i], TMP[i]); } } len -= processedLen; if (len) processedLen += cpSMS4_CTR_gfni512x16(pOut, pInp, len, pRKey, pCtrMask, pCtr); return processedLen; } /* // 16*MBS_SMS4 bytes processing */ static int cpSMS4_CTR_gfni512x16(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr) { int processedLen = len - (len % (16 * MBS_SMS4)); int n; if(processedLen){ __ALIGN16 __m512i TMP[11]; // TMP[8] - ctr // TMP[9] - ctrMask // TMP[10] - ctrUnch TMP[8] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtr)); TMP[9] = _mm512_broadcast_i64x2(_mm_loadu_si128((__m128i*)pCtrMask)); /* read string counter and convert to numerical */ TMP[8] = _mm512_shuffle_epi8(TMP[8], M512(endianness)); /* read string mask and convert to numerical */ TMP[9] = _mm512_shuffle_epi8(TMP[9], M512(endianness)); /* upchanged counter bits */ TMP[10] = _mm512_andnot_si512(TMP[9], TMP[8]); /* first incremention */ TMP[8] = inc512(TMP[8], first_inc); TMP[8] = _mm512_and_si512(TMP[9], TMP[8]); for (n = 0; n < processedLen; n += (16 * MBS_SMS4), pInp += (16 * MBS_SMS4), pOut += (16 * MBS_SMS4)) { int itr; TMP[0] = TMP[8]; TMP[1] = inc512(TMP[0], next_inc); TMP[2] = inc512(TMP[1], next_inc); TMP[3] = inc512(TMP[2], next_inc); TMP[8] = inc512(TMP[3], next_inc); TMP[0] = _mm512_xor_si512(TMP[10], _mm512_and_si512(TMP[0], TMP[9])); TMP[1] = _mm512_xor_si512(TMP[10], _mm512_and_si512(TMP[1], TMP[9])); TMP[2] = _mm512_xor_si512(TMP[10], _mm512_and_si512(TMP[2], TMP[9])); TMP[3] = _mm512_xor_si512(TMP[10], _mm512_and_si512(TMP[3], TMP[9])); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(endianness_swap)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(endianness_swap)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(endianness_swap)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(endianness_swap)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), _mm512_xor_si512(TMP[0], _mm512_loadu_si512((__m512i*)(pInp)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), _mm512_xor_si512(TMP[1], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), _mm512_xor_si512(TMP[2], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)))); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), _mm512_xor_si512(TMP[3], _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)))); } /* Save counter */ TMP[8] = _mm512_xor_si512(TMP[10], _mm512_and_si512(TMP[8], TMP[9])); TMP[8] = _mm512_shuffle_epi8(TMP[8], M512(endianness)); _mm_storeu_si128((__m128i*)pCtr, _mm512_castsi512_si128(TMP[8])); /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_xor_si512(TMP[i], TMP[i]); } } len -= processedLen; if (len) processedLen += cpSMS4_CTR_gfni128x12(pOut, pInp, len, pRKey, pCtrMask, pCtr); return processedLen; } /* // 12*MBS_SMS4 processing */ static int cpSMS4_CTR_gfni128x12(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr) { int processedLen = len - (len % (12 * MBS_SMS4)); int n; if(processedLen){ __ALIGN16 __m128i TMP[22]; // TMP[15] - ctr // TMP[16] - ctrMask // TMP[17] - ctrUnch TMP[15] = _mm_loadu_si128((__m128i*)pCtr); TMP[16] = _mm_loadu_si128((__m128i*)pCtrMask); TMP[16] = _mm_shuffle_epi8(TMP[16], M128(endianness)); TMP[15] = _mm_shuffle_epi8(TMP[15], M128(endianness)); TMP[17] = _mm_andnot_si128(TMP[16], TMP[15]); for(n=0; n= 1920) */ #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_decrypt_cbc.c000066400000000000000000000061571470420105600253400ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpDecryptSMS4_cbc() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #include "pcpsms4_decrypt_cbc.h" /*F* // Name: cpDecryptSMS4_cbc // // Purpose: SMS4-CBC decryption. // // Parameters: // pIV pointer to the initialization vector // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // pCtx pointer to the SMS4 context // *F*/ IPP_OWN_DEFN (void, cpDecryptSMS4_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsSMS4Spec* pCtx)) { const Ipp32u* pRoundKeys = SMS4_DRK(pCtx); __ALIGN16 Ipp32u TMP[2*(MBS_SMS4/sizeof(Ipp32u))]; /* iv size = MBS_SMS4/sizeof(Ipp32u) tmp size = MBS_SMS4/sizeof(Ipp32u) */ Ipp32u* iv = TMP; Ipp32u* tmp = TMP + (MBS_SMS4/sizeof(Ipp32u)); /* copy IV */ CopyBlock16(pIV, iv); /* do decryption */ #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) if (IsFeatureEnabled(ippCPUID_AVX512GFNI)) { int processedLen = cpSMS4_CBC_dec_gfni512(pDst, pSrc, dataLen, pRoundKeys, (Ipp8u*)iv); pSrc += processedLen; pDst += processedLen; dataLen -= processedLen; } else #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* (_IPP32E>=_IPP32E_K1) */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) { int processedLen = cpSMS4_CBC_dec_aesni(pDst, pSrc, dataLen, pRoundKeys, (Ipp8u*)iv); pSrc += processedLen; pDst += processedLen; dataLen -= processedLen; } #endif for(; dataLen>0; dataLen-=MBS_SMS4, pSrc+=MBS_SMS4, pDst+=MBS_SMS4) { cpSMS4_Cipher((Ipp8u*)tmp, (Ipp8u*)pSrc, pRoundKeys); tmp[0] ^= iv[0]; tmp[1] ^= iv[1]; tmp[2] ^= iv[2]; tmp[3] ^= iv[3]; iv[0] = ((Ipp32u*)pSrc)[0]; iv[1] = ((Ipp32u*)pSrc)[1]; iv[2] = ((Ipp32u*)pSrc)[2]; iv[3] = ((Ipp32u*)pSrc)[3]; CopyBlock16(tmp, pDst); } /* clear secret data */ PurgeBlock(TMP, sizeof(TMP)); } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_decrypt_cbc.h000066400000000000000000000023031470420105600253320ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpDecryptSMS4_cbc() // */ #include "owncp.h" #if !defined _PCP_SMS4_DECRYPT_CBC_H #define _PCP_SMS4_DECRYPT_CBC_H #define cpDecryptSMS4_cbc OWNAPI(cpDecryptSMS4_cbc) IPP_OWN_DECL (void, cpDecryptSMS4_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsSMS4Spec* pCtx)) #endif /* #if !defined _PCP_SMS4_DECRYPT_CBC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ecb_gfni.c000066400000000000000000001436041470420105600246120ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 ECB decryption // // Contents: // cpSMS4_ECB_gfni512() // cpSMS4_ECB_gfni512x48() // cpSMS4_ECB_gfni512x32() // cpSMS4_ECB_gfni512x16() // cpSMS4_ECB_gfni128x12() // cpSMS4_ECB_gfni128x8() // cpSMS4_ECB_gfni128x4() // cpSMS4_ECB_gfni128x4() // cpSMS4_ECB_gfni128_tail() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) #include "pcpsms4_gfni.h" static int cpSMS4_ECB_gfni512x48(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); static int cpSMS4_ECB_gfni512x32(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); static int cpSMS4_ECB_gfni512x16(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); static int cpSMS4_ECB_gfni128x12(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); static int cpSMS4_ECB_gfni128x8(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); static int cpSMS4_ECB_gfni128x4(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); static int cpSMS4_ECB_gfni128_tail(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey); /* // 64*MBS_SMS4 bytes processing */ IPP_OWN_DEFN (int, cpSMS4_ECB_gfni512, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) { __ALIGN16 __m512i TMP[20]; int processedLen = len - (len % (64 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (64 * MBS_SMS4), pInp += (64 * MBS_SMS4), pOut += (64 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 32)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 36)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 40)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 44)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 48)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 52)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 56)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 60)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[16], TMP[17], TMP[18], TMP[19], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[2]), L512(TMP[2])); TMP[16] = _mm512_xor_si512(_mm512_xor_si512(TMP[16], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[2]), L512(TMP[2])); TMP[17] = _mm512_xor_si512(_mm512_xor_si512(TMP[17], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[19]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[2]), L512(TMP[2])); TMP[18] = _mm512_xor_si512(_mm512_xor_si512(TMP[18], TMP[3]), L512(TMP[3])); /* initial xors */ TMP[3] = TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[16]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[17]); TMP[3] = _mm512_xor_si512(TMP[3], TMP[18]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); TMP[3] = sBox512(TMP[3]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[2]), L512(TMP[2])); TMP[19] = _mm512_xor_si512(_mm512_xor_si512(TMP[19], TMP[3]), L512(TMP[3])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 32), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 36), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 40), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 44), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[16], TMP[17], TMP[18], TMP[19]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 48), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 52), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 56), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 60), TMP[3]); } /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len){ if(len < 256){ processedLen += cpSMS4_ECB_gfni128x12(pOut, pInp, len, pRKey); return processedLen; } processedLen += cpSMS4_ECB_gfni512x48(pOut, pInp, len, pRKey); } return processedLen; } /* // 48*MBS_SMS4 bytes processing */ static int cpSMS4_ECB_gfni512x48(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey) { __ALIGN16 __m512i TMP[16]; int processedLen = len - (len % (48 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (48 * MBS_SMS4), pInp += (48 * MBS_SMS4), pOut += (48 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 32)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 36)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 40)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 44)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[12], TMP[13], TMP[14], TMP[15], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); TMP[12] = _mm512_xor_si512(_mm512_xor_si512(TMP[12], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); TMP[13] = _mm512_xor_si512(_mm512_xor_si512(TMP[13], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[15]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); TMP[14] = _mm512_xor_si512(_mm512_xor_si512(TMP[14], TMP[2]), L512(TMP[2])); /* initial xors */ TMP[2] = TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[12]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[13]); TMP[2] = _mm512_xor_si512(TMP[2], TMP[14]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); TMP[2] = sBox512(TMP[2]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); TMP[15] = _mm512_xor_si512(_mm512_xor_si512(TMP[15], TMP[2]), L512(TMP[2])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[12], TMP[13], TMP[14], TMP[15]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 32), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 36), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 40), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 44), TMP[3]); } /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len) processedLen += cpSMS4_ECB_gfni512x32(pOut, pInp, len, pRKey); return processedLen; } /* // 32*MBS_SMS4 bytes processing */ static int cpSMS4_ECB_gfni512x32(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey) { __ALIGN16 __m512i TMP[12]; int processedLen = len - (len % (32 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (32 * MBS_SMS4), pInp += (32 * MBS_SMS4), pOut += (32 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); TMP[0] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 16)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 20)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 24)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 28)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[8], TMP[9], TMP[10], TMP[11], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); TMP[8] = _mm512_xor_si512(_mm512_xor_si512(TMP[8], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); TMP[9] = _mm512_xor_si512(_mm512_xor_si512(TMP[9], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[11]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); TMP[10] = _mm512_xor_si512(_mm512_xor_si512(TMP[10], TMP[1]), L512(TMP[1])); /* initial xors */ TMP[1] = TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[8]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[9]); TMP[1] = _mm512_xor_si512(TMP[1], TMP[10]); /* Sbox */ TMP[0] = sBox512(TMP[0]); TMP[1] = sBox512(TMP[1]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); TMP[11] = _mm512_xor_si512(_mm512_xor_si512(TMP[11], TMP[1]), L512(TMP[1])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[3]); TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[8], TMP[9], TMP[10], TMP[11]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 16), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 20), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 24), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 28), TMP[3]); } /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len) processedLen += cpSMS4_ECB_gfni512x16(pOut, pInp, len, pRKey); return processedLen; } /* // 16*MBS_SMS4 bytes processing */ static int cpSMS4_ECB_gfni512x16(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey) { __ALIGN16 __m512i TMP[8]; int processedLen = len - (len % (16 * MBS_SMS4)); int n; for (n = 0; n < processedLen; n += (16 * MBS_SMS4), pInp += (16 * MBS_SMS4), pOut += (16 * MBS_SMS4)) { int itr; TMP[0] = _mm512_loadu_si512((__m512i*)(pInp)); TMP[1] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 4)); TMP[2] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 8)); TMP[3] = _mm512_loadu_si512((__m512i*)(pInp + MBS_SMS4 * 12)); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); TRANSPOSE_INP_512(TMP[4], TMP[5], TMP[6], TMP[7], TMP[0], TMP[1], TMP[2], TMP[3]); for (itr = 0; itr < 8; itr++, pRKey += 4) { /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[0]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[4] = _mm512_xor_si512(_mm512_xor_si512(TMP[4], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[1]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[5] = _mm512_xor_si512(_mm512_xor_si512(TMP[5], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[2]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[7]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[6] = _mm512_xor_si512(_mm512_xor_si512(TMP[6], TMP[0]), L512(TMP[0])); /* initial xors */ TMP[0] = _mm512_set1_epi32((Ipp32s)pRKey[3]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[4]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[5]); TMP[0] = _mm512_xor_si512(TMP[0], TMP[6]); /* Sbox */ TMP[0] = sBox512(TMP[0]); /* Sbox done, now L */ TMP[7] = _mm512_xor_si512(_mm512_xor_si512(TMP[7], TMP[0]), L512(TMP[0])); } pRKey -= 32; TRANSPOSE_OUT_512(TMP[0], TMP[1], TMP[2], TMP[3], TMP[4], TMP[5], TMP[6], TMP[7]); TMP[0] = _mm512_shuffle_epi8(TMP[0], M512(swapBytes)); TMP[1] = _mm512_shuffle_epi8(TMP[1], M512(swapBytes)); TMP[2] = _mm512_shuffle_epi8(TMP[2], M512(swapBytes)); TMP[3] = _mm512_shuffle_epi8(TMP[3], M512(swapBytes)); _mm512_storeu_si512((__m512i*)(pOut), TMP[0]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 4), TMP[1]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 8), TMP[2]); _mm512_storeu_si512((__m512i*)(pOut + MBS_SMS4 * 12), TMP[3]); } /* clear secret data */ for (unsigned int i = 0; i < sizeof(TMP) / sizeof(TMP[0]); ++i) { TMP[i] = _mm512_setzero_si512(); //_mm512_xor_si512(TMP[i], TMP[i]); } len -= processedLen; if (len) processedLen += cpSMS4_ECB_gfni128x12(pOut, pInp, len, pRKey); return processedLen; } /* // 12*MBS_SMS4 processing */ static int cpSMS4_ECB_gfni128x12(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey) { __ALIGN16 __m128i TMP[15]; int processedLen = len -(len % (12*MBS_SMS4)); int n; for(n=0; n= 1920) */ #endif /* _IPP32E>=_IPP32E_K1 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ecb_x1_aesni.c000066400000000000000000000074661470420105600254030ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 ECB encryption/decryption // // Contents: // cpSMS4_ECB_aesni_x1() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #include "pcpsms4_y8cn.h" /* // 1*MBS_SMS4 processing */ IPP_OWN_DEFN (void, cpSMS4_ECB_aesni_x1, (Ipp8u* pOut, const Ipp8u* pInp, const Ipp32u* pRKey)) { __ALIGN16 __m128i TMP[6]; /* TMP[0] = T TMP[1] = K0 TMP[2] = K1 TMP[3] = K2 TMP[4] = K3 TMP[5] = key4 */ TMP[1] = _mm_shuffle_epi8( _mm_cvtsi32_si128(((Ipp32s*)pInp)[0]), M128(swapBytes)); TMP[2] = _mm_shuffle_epi8( _mm_cvtsi32_si128(((Ipp32s*)pInp)[1]), M128(swapBytes)); TMP[3] = _mm_shuffle_epi8( _mm_cvtsi32_si128(((Ipp32s*)pInp)[2]), M128(swapBytes)); TMP[4] = _mm_shuffle_epi8( _mm_cvtsi32_si128(((Ipp32s*)pInp)[3]), M128(swapBytes)); int itr; for(itr=0; itr<8; itr++, pRKey+=4) { TMP[5] = _mm_loadu_si128((__m128i*)pRKey); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0x00); /* broadcast(key4 TMP[0]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[0]), L(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0x55); /* broadcast(key4 TMP[1]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[0]), L(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0xAA); /* broadcast(key4 TMP[2]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[0]), L(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0xFF); /* broadcast(key4 TMP[3]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[4] = _mm_xor_si128(_mm_xor_si128(TMP[4], TMP[0]), L(TMP[0])); } ((Ipp32u*)(pOut))[0] = (Ipp32u)_mm_cvtsi128_si32(_mm_shuffle_epi8(TMP[4], M128(swapBytes))); ((Ipp32u*)(pOut))[1] = (Ipp32u)_mm_cvtsi128_si32(_mm_shuffle_epi8(TMP[3], M128(swapBytes))); ((Ipp32u*)(pOut))[2] = (Ipp32u)_mm_cvtsi128_si32(_mm_shuffle_epi8(TMP[2], M128(swapBytes))); ((Ipp32u*)(pOut))[3] = (Ipp32u)_mm_cvtsi128_si32(_mm_shuffle_epi8(TMP[1], M128(swapBytes))); /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_xor_si128(TMP[i],TMP[i]); } } #endif /* _IPP_P8, _IPP32E_Y8 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_ecb_x1_gfni.c000066400000000000000000000074321470420105600252200ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2020 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 ECB encryption/decryption // // Contents: // cpSMS4_ECB_gfni_x1() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) #include "pcpsms4_gfni.h" IPP_OWN_DEFN (void, cpSMS4_ECB_gfni_x1, (Ipp8u* pOut, const Ipp8u* pInp, const Ipp32u* pRKey)) { __ALIGN16 __m128i TMP[6]; /* TMP[0] = T TMP[1] = K0 TMP[2] = K1 TMP[3] = K2 TMP[4] = K3 TMP[5] = key4 */ TMP[1] = _mm_loadu_si128((__m128i*)pInp); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); TMP[2] = _mm_alignr_epi32(TMP[1], TMP[1], 1); TMP[3] = _mm_alignr_epi32(TMP[1], TMP[1], 2); TMP[4] = _mm_alignr_epi32(TMP[1], TMP[1], 3); int itr; for(itr=0; itr<8; itr++, pRKey+=4) { TMP[5] = _mm_loadu_si128((__m128i*)pRKey); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0x00); /* broadcast(key4 TMP[0]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox128(TMP[0]); /* Sbox done, now L */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[0]), L128(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0x55); /* broadcast(key4 TMP[1]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); /* Sbox */ TMP[0] = sBox128(TMP[0]); /* Sbox done, now L */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[0]), L128(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0xAA); /* broadcast(key4 TMP[2]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); /* Sbox */ TMP[0] = sBox128(TMP[0]); /* Sbox done, now L */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[0]), L128(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0xFF); /* broadcast(key4 TMP[3]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); /* Sbox */ TMP[0] = sBox128(TMP[0]); /* Sbox done, now L */ TMP[4] = _mm_xor_si128(_mm_xor_si128(TMP[4], TMP[0]), L128(TMP[0])); } TMP[0] = _mm_unpacklo_epi32(TMP[2], TMP[1]); TMP[5] = _mm_unpacklo_epi32(TMP[4], TMP[3]); TMP[1] = _mm_unpacklo_epi64(TMP[5], TMP[0]); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); _mm_storeu_si128((__m128i*)pOut, TMP[1]); /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_xor_si128(TMP[i],TMP[i]); } } #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* (_IPP32E>=_IPP32E_K1) */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_encrypt_cbc.c000066400000000000000000000040751470420105600253470ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpEncryptSMS4_cbc() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #include "pcpsms4_encrypt_cbc.h" /*F* // // Name: cpEncryptSMS4_cbc // // Purpose: SMS4-CBC encryption. // // Parameters: // pIV pointer to the initialization vector // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // pCtx pointer to the SMS4 context // *F*/ IPP_OWN_DEFN (void, cpEncryptSMS4_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsSMS4Spec* pCtx)) { const Ipp32u* pRoundKeys = SMS4_RK(pCtx); /* read IV */ __ALIGN16 Ipp32u iv[MBS_SMS4/sizeof(Ipp32u)]; CopyBlock16(pIV, iv); /* do encryption */ for(; dataLen>0; dataLen-=MBS_SMS4, pSrc+=MBS_SMS4, pDst+=MBS_SMS4) { iv[0] ^= ((Ipp32u*)pSrc)[0]; iv[1] ^= ((Ipp32u*)pSrc)[1]; iv[2] ^= ((Ipp32u*)pSrc)[2]; iv[3] ^= ((Ipp32u*)pSrc)[3]; cpSMS4_Cipher(pDst, (Ipp8u*)iv, pRoundKeys); iv[0] = ((Ipp32u*)pDst)[0]; iv[1] = ((Ipp32u*)pDst)[1]; iv[2] = ((Ipp32u*)pDst)[2]; iv[3] = ((Ipp32u*)pDst)[3]; } /* clear secret data */ PurgeBlock(iv, sizeof(iv)); } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_encrypt_cbc.h000066400000000000000000000023031470420105600253440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpEncryptSMS4_cbc() // */ #include "owncp.h" #if !defined _PCP_SMS4_ENCRYPT_CBC_H #define _PCP_SMS4_ENCRYPT_CBC_H #define cpEncryptSMS4_cbc OWNAPI(cpEncryptSMS4_cbc) IPP_OWN_DECL (void, cpEncryptSMS4_cbc, (const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsSMS4Spec* pCtx)) #endif /* #if !defined _PCP_SMS4_ENCRYPT_CBC_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_gfni.h000066400000000000000000000245211470420105600240020ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // sBox() // L() // TRANSPOSE_INP() // TRANSPOSE_OUT() // */ #ifndef __SMS4_SBOX_GFNI512_H_ #define __SMS4_SBOX_GFNI512_H_ #include "owndefs.h" #include "owncp.h" #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) static __ALIGN64 Ipp8u swapBytes[] = { 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12 }; /* // Not used in current pipeline static __ALIGN32 Ipp8u permMask256[] = {0x00,0x00,0x00,0x00, 0x04,0x00,0x00,0x00, 0x01,0x00,0x00,0x00, 0x05,0x00,0x00,0x00, 0x02,0x00,0x00,0x00, 0x06,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x07,0x00,0x00,0x00}; */ static __ALIGN64 Ipp8u permMask_in[] = {0,0x00,0x00,0x00, 4,0x00,0x00,0x00, 8,0x00,0x00,0x00, 12,0x00,0x00,0x00, 1,0x00,0x00,0x00, 5,0x00,0x00,0x00, 9,0x00,0x00,0x00, 13,0x00,0x00,0x00, 2,0x00,0x00,0x00, 6,0x00,0x00,0x00, 10,0x00,0x00,0x00, 14,0x00,0x00,0x00, 3,0x00,0x00,0x00, 7,0x00,0x00,0x00, 11,0x00,0x00,0x00, 15,0x00,0x00,0x00 }; static __ALIGN64 Ipp8u permMask_out[] = {12,0x00,0x00,0x00, 8,0x00,0x00,0x00, 4,0x00,0x00,0x00, 0,0x00,0x00,0x00, 13,0x00,0x00,0x00, 9,0x00,0x00,0x00, 5,0x00,0x00,0x00, 1,0x00,0x00,0x00, 14,0x00,0x00,0x00, 10,0x00,0x00,0x00, 6,0x00,0x00,0x00, 2,0x00,0x00,0x00, 15,0x00,0x00,0x00, 11,0x00,0x00,0x00, 7,0x00,0x00,0x00, 3,0x00,0x00,0x00}; static __ALIGN64 Ipp8u affineIn[] = { 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34 }; static __ALIGN64 Ipp8u affineOut[] = { 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7 }; #define M512(mem) (*((__m512i*)(mem))) #define M256(mem) (*((__m256i*)(mem))) #define M128(mem) (*((__m128i*)(mem))) /* // // GF(256) is isomorfic. // Encoding/decoding data of SM4 and AES are elements of GF(256). // The difference in representation only. // (It happened due to using different generating polynomials in SM4 and AES representations). // Doing data conversion from SM4 to AES domain // lets use AES specific intrinsics to perform less expensive SMS4 S-box computation. // // Original SMS4 S-box algorithm is converted to the following: // // - transform data from SMS4 representation to AES representation // - compute S-box value // - transform data back from AES representation to SMS4 representation // */ /* // sBox */ __FORCEINLINE __m512i sBox512(__m512i block) { block = _mm512_gf2p8affine_epi64_epi8(block, M512(affineIn), 0x65); block = _mm512_gf2p8affineinv_epi64_epi8(block, M512(affineOut), 0xd3); return block; } /* // Not used in current pipeline __FORCEINLINE __m256i sBox256(__m256i block) { block = _mm256_gf2p8affine_epi64_epi8(block, M256(affineIn), 0x65); block = _mm256_gf2p8affineinv_epi64_epi8(block, M256(affineOut), 0xd3); return block; } */ __FORCEINLINE __m128i sBox128(__m128i block) { block = _mm_gf2p8affine_epi64_epi8(block, M128(affineIn), 0x65); block = _mm_gf2p8affineinv_epi64_epi8(block, M128(affineOut), 0xd3); return block; } /* // L */ __FORCEINLINE __m512i L512(__m512i x) { __m512i rolled0 = _mm512_rol_epi32(x, 2); __m512i rolled1 = _mm512_rol_epi32(x, 10); __m512i temp = _mm512_xor_si512(rolled0, rolled1); __m512i rolled2 = _mm512_rol_epi32(x, 18); __m512i rolled3 = _mm512_rol_epi32(x, 24); __m512i res = _mm512_ternarylogic_epi32(temp, rolled2, rolled3, 0x96); return res; } /* // Not used in current pipeline __FORCEINLINE __m256i L256(__m256i x) { __m256i T = _mm256_xor_si256(_mm256_slli_epi32(x, 2), _mm256_srli_epi32(x,30)); T = _mm256_xor_si256(T, _mm256_slli_epi32 (x,10)); T = _mm256_xor_si256(T, _mm256_srli_epi32 (x,22)); T = _mm256_xor_si256(T, _mm256_slli_epi32 (x,18)); T = _mm256_xor_si256(T, _mm256_srli_epi32 (x,14)); T = _mm256_xor_si256(T, _mm256_slli_epi32 (x,24)); T = _mm256_xor_si256(T, _mm256_srli_epi32 (x, 8)); return T; } */ __FORCEINLINE __m128i L128(__m128i x) { __m128i rolled0 = _mm_rol_epi32(x, 2); __m128i rolled1 = _mm_rol_epi32(x, 10); __m128i temp = _mm_xor_si128(rolled1, rolled0); __m128i rolled2 = _mm_rol_epi32(x, 18); __m128i rolled3 = _mm_rol_epi32(x, 24); __m128i res = _mm_ternarylogic_epi32(temp, rolled2, rolled3, 0x96); return res; } /* // TRANSPOSE_INP */ /* // inp: T0, T1, T2, T3 // out: K0, K1, K2, K3 */ #define TRANSPOSE_INP_512(K0,K1,K2,K3, T0,T1,T2,T3) \ K0 = _mm512_unpacklo_epi32(T0, T1); \ K1 = _mm512_unpacklo_epi32(T2, T3); \ K2 = _mm512_unpackhi_epi32(T0, T1); \ K3 = _mm512_unpackhi_epi32(T2, T3); \ \ T0 = _mm512_unpacklo_epi64(K0, K1); \ T1 = _mm512_unpacklo_epi64(K2, K3); \ T2 = _mm512_unpackhi_epi64(K0, K1); \ T3 = _mm512_unpackhi_epi64(K2, K3); \ \ K2 = _mm512_permutexvar_epi32(M512(permMask_in), T1); \ K1 = _mm512_permutexvar_epi32(M512(permMask_in), T2); \ K3 = _mm512_permutexvar_epi32(M512(permMask_in), T3); \ K0 = _mm512_permutexvar_epi32(M512(permMask_in), T0) /* // inp: T0, T1, T2, T3 // out: K0, K1, K2, K3 */ /* // Not used in current pipeline #define TRANSPOSE_INP_256(K0,K1,K2,K3, T0,T1,T2,T3) \ K0 = _mm256_unpacklo_epi32(T0, T1); \ K1 = _mm256_unpacklo_epi32(T2, T3); \ K2 = _mm256_unpackhi_epi32(T0, T1); \ K3 = _mm256_unpackhi_epi32(T2, T3); \ \ T0 = _mm256_unpacklo_epi64(K0, K1); \ T1 = _mm256_unpacklo_epi64(K2, K3); \ T2 = _mm256_unpackhi_epi64(K0, K1); \ T3 = _mm256_unpackhi_epi64(K2, K3); \ \ K2 = _mm256_permutevar8x32_epi32(T1, M256(permMask256)); \ K1 = _mm256_permutevar8x32_epi32(T2, M256(permMask256)); \ K3 = _mm256_permutevar8x32_epi32(T3, M256(permMask256)); \ K0 = _mm256_permutevar8x32_epi32(T0, M256(permMask256)) */ #define TRANSPOSE_INP_128(K0,K1,K2,K3, T) \ T = _mm_unpacklo_epi32(K0, K1); \ K1 = _mm_unpackhi_epi32(K0, K1); \ K0 = _mm_unpacklo_epi32(K2, K3); \ K3 = _mm_unpackhi_epi32(K2, K3); \ \ K2 = _mm_unpacklo_epi64(K1, K3); \ K3 = _mm_unpackhi_epi64(K1, K3); \ K1 = _mm_unpackhi_epi64(T, K0); \ K0 = _mm_unpacklo_epi64(T, K0) /* // TRANSPOSE_OUT */ /* // inp: K0, K1, K2, K3 // out: T0, T1, T2, T3 */ #define TRANSPOSE_OUT_512(T0,T1,T2,T3, K0,K1,K2,K3) \ T0 = _mm512_shuffle_i32x4(K0, K1, 0x44); \ T1 = _mm512_shuffle_i32x4(K0, K1, 0xee); \ T2 = _mm512_shuffle_i32x4(K2, K3, 0x44); \ T3 = _mm512_shuffle_i32x4(K2, K3, 0xee); \ \ K0 = _mm512_shuffle_i32x4(T0, T2, 0x88); \ K1 = _mm512_shuffle_i32x4(T0, T2, 0xdd); \ K2 = _mm512_shuffle_i32x4(T1, T3, 0x88); \ K3 = _mm512_shuffle_i32x4(T1, T3, 0xdd); \ \ K0 = _mm512_permutexvar_epi32(M512(permMask_out), K0);\ K1 = _mm512_permutexvar_epi32(M512(permMask_out), K1);\ K2 = _mm512_permutexvar_epi32(M512(permMask_out), K2);\ K3 = _mm512_permutexvar_epi32(M512(permMask_out), K3);\ \ T0=K0,T1=K1,T2=K2,T3=K3 /* // inp: K0, K1, K2, K3 // out: T0, T1, T2, T3 */ /* // Not used in current pipeline #define TRANSPOSE_OUT_256(T0,T1,T2,T3, K0,K1,K2,K3) \ T0 = _mm256_unpacklo_epi32(K1, K0); \ T1 = _mm256_unpacklo_epi32(K3, K2); \ T2 = _mm256_unpackhi_epi32(K1, K0); \ T3 = _mm256_unpackhi_epi32(K3, K2); \ \ K0 = _mm256_unpacklo_epi64(T1, T0); \ K1 = _mm256_unpacklo_epi64(T3, T2); \ K2 = _mm256_unpackhi_epi64(T1, T0); \ K3 = _mm256_unpackhi_epi64(T3, T2); \ \ T0 = _mm256_permute2x128_si256(K0, K2, 0x20); \ T1 = _mm256_permute2x128_si256(K1, K3, 0x20); \ T2 = _mm256_permute2x128_si256(K0, K2, 0x31); \ T3 = _mm256_permute2x128_si256(K1, K3, 0x31) */ #define TRANSPOSE_OUT_128(K0,K1,K2,K3, T) \ T = _mm_unpacklo_epi32(K1, K0); \ K0 = _mm_unpackhi_epi32(K1, K0); \ K1 = _mm_unpacklo_epi32(K3, K2); \ K3 = _mm_unpackhi_epi32(K3, K2); \ \ K2 = _mm_unpackhi_epi64(K1, T); \ T = _mm_unpacklo_epi64(K1, T); \ K1 = _mm_unpacklo_epi64(K3, K0); \ K0 = _mm_unpackhi_epi64(K3, K0); \ K3 = T //#define PR(X) printf("%08u %08u %08u %08u | %08u %08u %08u %08u | %08u %08u %08u %08u | %08u %08u %08u %08u\n",\ // X.m512i_u32[0], X.m512i_u32[1], X.m512i_u32[2],\ // X.m512i_u32[3], X.m512i_u32[4], X.m512i_u32[5],\ // X.m512i_u32[6], X.m512i_u32[7], X.m512i_u32[8],\ // X.m512i_u32[9], X.m512i_u32[10], X.m512i_u32[11],\ // X.m512i_u32[12], X.m512i_u32[13], X.m512i_u32[14],\ // X.m512i_u32[15]); #endif #endif /* if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* __SMS4_SBOX_GFNI512_H_ */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_l9cn.h000066400000000000000000000163301470420105600237230ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // affine() // sBox() // L() // TRANSPOSE_INP() // TRANSPOSE_OUT() // */ #if (_IPP>=_IPP_H9) || (_IPP32E>=_IPP32E_L9) #ifndef __SMS4_SBOX_L9_H_ #define __SMS4_SBOX_L9_H_ #include "owndefs.h" #include "owncp.h" static __ALIGN32 Ipp8u inpMaskLO[] = {0x65,0x41,0xfd,0xd9,0x0a,0x2e,0x92,0xb6,0x0f,0x2b,0x97,0xb3,0x60,0x44,0xf8,0xdc, 0x65,0x41,0xfd,0xd9,0x0a,0x2e,0x92,0xb6,0x0f,0x2b,0x97,0xb3,0x60,0x44,0xf8,0xdc}; static __ALIGN32 Ipp8u inpMaskHI[] = {0x00,0xc9,0x67,0xae,0x80,0x49,0xe7,0x2e,0x4a,0x83,0x2d,0xe4,0xca,0x03,0xad,0x64, 0x00,0xc9,0x67,0xae,0x80,0x49,0xe7,0x2e,0x4a,0x83,0x2d,0xe4,0xca,0x03,0xad,0x64}; static __ALIGN32 Ipp8u outMaskLO[] = {0xd3,0x59,0x38,0xb2,0xcc,0x46,0x27,0xad,0x36,0xbc,0xdd,0x57,0x29,0xa3,0xc2,0x48, 0xd3,0x59,0x38,0xb2,0xcc,0x46,0x27,0xad,0x36,0xbc,0xdd,0x57,0x29,0xa3,0xc2,0x48}; static __ALIGN32 Ipp8u outMaskHI[] = {0x00,0x50,0x14,0x44,0x89,0xd9,0x9d,0xcd,0xde,0x8e,0xca,0x9a,0x57,0x07,0x43,0x13, 0x00,0x50,0x14,0x44,0x89,0xd9,0x9d,0xcd,0xde,0x8e,0xca,0x9a,0x57,0x07,0x43,0x13}; static __ALIGN32 Ipp8u maskSrows[] = {0x00,0x0d,0x0a,0x07,0x04,0x01,0x0e,0x0b,0x08,0x05,0x02,0x0f,0x0c,0x09,0x06,0x03, 0x00,0x0d,0x0a,0x07,0x04,0x01,0x0e,0x0b,0x08,0x05,0x02,0x0f,0x0c,0x09,0x06,0x03}; static __ALIGN16 Ipp8u encKey[] = {0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63}; static __ALIGN32 Ipp8u lowBits4[] = {0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f}; static __ALIGN32 Ipp8u swapBytes[] = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12}; static __ALIGN32 Ipp8u permMask[] = {0x00,0x00,0x00,0x00, 0x04,0x00,0x00,0x00, 0x01,0x00,0x00,0x00, 0x05,0x00,0x00,0x00, 0x02,0x00,0x00,0x00, 0x06,0x00,0x00,0x00, 0x03,0x00,0x00,0x00, 0x07,0x00,0x00,0x00}; static __ALIGN32 Ipp8u affineIn[] = { 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34 }; static __ALIGN32 Ipp8u affineOut[] = { 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7 }; #define M256(mem) (*((__m256i*)((Ipp8u*)(mem)))) #define M128(mem) (*((__m128i*)((Ipp8u*)(mem)))) /* // // AES and SMS4 ciphers both based on composite field GF(2^8). // This affine transformation transforms 16 bytes // from SMS4 representation to AES representation or vice versa // depending on passed masks. // */ __FORCEINLINE __m256i affine(__m256i x, __m256i maskLO, __m256i maskHI) { __m256i T1 = _mm256_and_si256(_mm256_srli_epi64(x, 4), M256(lowBits4)); __m256i T0 = _mm256_and_si256(x, M256(lowBits4)); T0 = _mm256_shuffle_epi8(maskLO, T0); T1 = _mm256_shuffle_epi8(maskHI, T1); return _mm256_xor_si256(T0, T1); } __FORCEINLINE __m256i AES_ENC_LAST(__m256i x, __m128i key) { __m128i t0 = _mm256_extracti128_si256(x, 0); __m128i t1 = _mm256_extracti128_si256(x, 1); t0 = _mm_aesenclast_si128(t0, key); t1 = _mm_aesenclast_si128(t1, key); x = _mm256_inserti128_si256(x, t0, 0); x = _mm256_inserti128_si256(x, t1, 1); return x; } /* // // GF(256) is isomorfic. // Encoding/decoding data of SM4 and AES are elements of GF(256). // The difference in representation only. // (It happened due to using different generating polynomials in SM4 and AES representations). // Doing data conversion from SM4 to AES domain // lets use AES specific intrinsics to perform less expensive SMS4 S-box computation. // // Original SMS4 S-box algorithm is converted to the following: // // - transform data from SMS4 representation to AES representation // - compute S-box value using _mm_aesenclast_si128 with special key // - re-shuffle data after _mm_aesenclast_si128 that shuffle it inside // - transform data back from AES representation to SMS4 representation // */ __FORCEINLINE __m256i sBox(__m256i block) { block = affine(block, M256(inpMaskLO), M256(inpMaskHI)); block = AES_ENC_LAST(block, M128(encKey)); block = _mm256_shuffle_epi8(block, M256(maskSrows)); block = affine(block, M256(outMaskLO), M256(outMaskHI)); return block; } __FORCEINLINE __m256i L(__m256i x) { __m256i T = _mm256_xor_si256(_mm256_slli_epi32(x, 2), _mm256_srli_epi32(x,30)); T = _mm256_xor_si256(T, _mm256_slli_epi32 (x,10)); T = _mm256_xor_si256(T, _mm256_srli_epi32 (x,22)); T = _mm256_xor_si256(T, _mm256_slli_epi32 (x,18)); T = _mm256_xor_si256(T, _mm256_srli_epi32 (x,14)); T = _mm256_xor_si256(T, _mm256_slli_epi32 (x,24)); T = _mm256_xor_si256(T, _mm256_srli_epi32 (x, 8)); return T; } /* // inp: T0, T1, T2, T3 // out: K0, K1, K2, K3 */ #define TRANSPOSE_INP(K0,K1,K2,K3, T0,T1,T2,T3) \ K0 = _mm256_unpacklo_epi32(T0, T1); \ K1 = _mm256_unpacklo_epi32(T2, T3); \ K2 = _mm256_unpackhi_epi32(T0, T1); \ K3 = _mm256_unpackhi_epi32(T2, T3); \ \ T0 = _mm256_unpacklo_epi64(K0, K1); \ T1 = _mm256_unpacklo_epi64(K2, K3); \ T2 = _mm256_unpackhi_epi64(K0, K1); \ T3 = _mm256_unpackhi_epi64(K2, K3); \ \ K2 = _mm256_permutevar8x32_epi32(T1, M256(permMask)); \ K1 = _mm256_permutevar8x32_epi32(T2, M256(permMask)); \ K3 = _mm256_permutevar8x32_epi32(T3, M256(permMask)); \ K0 = _mm256_permutevar8x32_epi32(T0, M256(permMask)) /* // inp: K0, K1, K2, K3 // out: T0, T1, T2, T3 */ #define TRANSPOSE_OUT(T0,T1,T2,T3, K0,K1,K2,K3) \ T0 = _mm256_unpacklo_epi32(K1, K0); \ T1 = _mm256_unpacklo_epi32(K3, K2); \ T2 = _mm256_unpackhi_epi32(K1, K0); \ T3 = _mm256_unpackhi_epi32(K3, K2); \ \ K0 = _mm256_unpacklo_epi64(T1, T0); \ K1 = _mm256_unpacklo_epi64(T3, T2); \ K2 = _mm256_unpackhi_epi64(T1, T0); \ K3 = _mm256_unpackhi_epi64(T3, T2); \ \ T0 = _mm256_permute2x128_si256(K0, K2, 0x20); \ T1 = _mm256_permute2x128_si256(K1, K3, 0x20); \ T2 = _mm256_permute2x128_si256(K0, K2, 0x31); \ T3 = _mm256_permute2x128_si256(K1, K3, 0x31) #endif /* __SMS4_SBOX_L9_H_ */ #endif /* _IPP_G9, _IPP32E_L9 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_process_ctr.c000066400000000000000000000136361470420105600254050ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpProcessSMS4_ctr() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" /* // SMS4-CTR processing. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr !VALID_SMS4_ID() // ippStsLengthErr len <1 // ippStsCTRSizeErr 128 < ctrNumBitSize < 1 // ippStsCTRSizeErr data blocks number > 2^ctrNumBitSize // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // pCtx pointer to rge SMS4 context // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // */ IPP_OWN_DEFN (IppStatus, cpProcessSMS4_ctr, (const Ipp8u* pSrc, Ipp8u* pDst, int dataLen, const IppsSMS4Spec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_SMS4_ID(pCtx), ippStsContextMatchErr); /* test source, target and counter block pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pCtrValue); /* test stream length */ IPP_BADARG_RET((dataLen<1), ippStsLengthErr); /* test counter block size */ IPP_BADARG_RET(((MBS_SMS4*8)= 8 * sizeof(int) - 5 // function can process data with any possible // passed dataLen without counter overflow */ int dataBlocksNum = dataLen >> 4; if(dataLen & 15){ dataBlocksNum++; } IPP_BADARG_RET(dataBlocksNum > (1 << ctrNumBitSize), ippStsCTRSizeErr); } { __ALIGN16 Ipp8u TMP[2*MBS_SMS4+1]; /* maskIV size = MBS_SMS4 output size = MBS_SMS4 counter size = MBS_SMS4 maskValue size = 1 */ Ipp8u* output = TMP; Ipp8u* counter = TMP + MBS_SMS4; /* copy counter */ CopyBlock16(pCtrValue, counter); /* do CTR processing */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) Ipp8u* maskIV = TMP; /* output is not used together with maskIV, so this is why buffer for both values is the same */ Ipp8u* maskValue = TMP + 2*MBS_SMS4; if(dataLen>=4*MBS_SMS4) { /* construct ctr mask */ int n; int maskPosition = (MBS_SMS4*8-ctrNumBitSize)/8; *maskValue = (Ipp8u)(0xFF >> (MBS_SMS4*8-ctrNumBitSize)%8 ); for(n=0; n=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) if (IsFeatureEnabled(ippCPUID_AVX512GFNI)) { processedLen = cpSMS4_CTR_gfni512(pDst, pSrc, dataLen, SMS4_RK(pCtx), maskIV, counter); } else #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* (_IPP32E>=_IPP32E_K1) */ if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) { processedLen = cpSMS4_CTR_aesni(pDst, pSrc, dataLen, SMS4_RK(pCtx), maskIV, counter); } pSrc += processedLen; pDst += processedLen; dataLen -= processedLen; } #endif { /* block-by-block processing */ while(dataLen>= MBS_SMS4) { /* encrypt counter block */ cpSMS4_Cipher((Ipp8u*)output, (Ipp8u*)counter, SMS4_RK(pCtx)); /* compute ciphertext block */ XorBlock16(pSrc, output, pDst); /* increment counter block */ StdIncrement(counter,MBS_SMS4*8, ctrNumBitSize); pSrc += MBS_SMS4; pDst += MBS_SMS4; dataLen -= MBS_SMS4; } /* last data block processing */ if(dataLen) { /* encrypt counter block */ cpSMS4_Cipher((Ipp8u*)output, (Ipp8u*)counter, SMS4_RK(pCtx)); /* compute ciphertext block */ XorBlock(pSrc, output, pDst,dataLen); /* increment counter block */ StdIncrement((Ipp8u*)counter,MBS_SMS4*8, ctrNumBitSize); } } /* update counter */ CopyBlock16(counter, pCtrValue); /* clear secret data */ PurgeBlock(TMP, sizeof(TMP)); return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_process_ofb8.c000066400000000000000000000054251470420105600254500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpProcessSMS4_ofb8() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #include "pcpsms4_process_ofb8.h" /* // SMS4-OFB ecnryption/decryption // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // dataLen input/output buffer length (in bytes) // ofbBlkSize ofb block size (in bytes) // pCtx pointer to the AES context // pIV pointer to the initialization vector */ IPP_OWN_DEFN (void, cpProcessSMS4_ofb8, (const Ipp8u *pSrc, Ipp8u *pDst, int dataLen, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV)) { __ALIGN16 Ipp32u tmpInpOut[2*MBS_SMS4/sizeof(Ipp32u)]; CopyBlock16(pIV, tmpInpOut); while(dataLen>=ofbBlkSize) { /* block-by-block processing */ cpSMS4_Cipher((Ipp8u*)tmpInpOut+MBS_SMS4, (Ipp8u*)tmpInpOut, SMS4_RK(pCtx)); /* store output and shift inpBuffer for the next OFB operation */ if(ofbBlkSize==MBS_SMS4) { ((Ipp32u*)pDst)[0] = tmpInpOut[0+MBS_SMS4/sizeof(Ipp32u)]^((Ipp32u*)pSrc)[0]; ((Ipp32u*)pDst)[1] = tmpInpOut[1+MBS_SMS4/sizeof(Ipp32u)]^((Ipp32u*)pSrc)[1]; ((Ipp32u*)pDst)[2] = tmpInpOut[2+MBS_SMS4/sizeof(Ipp32u)]^((Ipp32u*)pSrc)[2]; ((Ipp32u*)pDst)[3] = tmpInpOut[3+MBS_SMS4/sizeof(Ipp32u)]^((Ipp32u*)pSrc)[3]; tmpInpOut[0] = tmpInpOut[0+MBS_SMS4/sizeof(Ipp32u)]; tmpInpOut[1] = tmpInpOut[1+MBS_SMS4/sizeof(Ipp32u)]; tmpInpOut[2] = tmpInpOut[2+MBS_SMS4/sizeof(Ipp32u)]; tmpInpOut[3] = tmpInpOut[3+MBS_SMS4/sizeof(Ipp32u)]; } else { XorBlock(pSrc, tmpInpOut+MBS_SMS4/sizeof(Ipp32u), pDst, ofbBlkSize); CopyBlock16((Ipp8u*)tmpInpOut+ofbBlkSize, tmpInpOut); } pSrc += ofbBlkSize; pDst += ofbBlkSize; dataLen -= ofbBlkSize; } /* update pIV */ CopyBlock16((Ipp8u*)tmpInpOut, pIV); /* clear secret data */ PurgeBlock(tmpInpOut, sizeof(tmpInpOut)); } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_process_ofb8.h000066400000000000000000000023241470420105600254500ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // cpProcessSMS4_ofb8() // */ #include "owncp.h" #if !defined _PCP_SMS4_PROCESS_OFB8_H #define _PCP_SMS4_PROCESS_OFB8_H #define cpProcessSMS4_ofb8 OWNAPI(cpProcessSMS4_ofb8) IPP_OWN_DECL (void, cpProcessSMS4_ofb8, (const Ipp8u *pSrc, Ipp8u *pDst, int dataLen, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV)) #endif /* #if !defined _PCP_SMS4_PROCESS_OFB8_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4_y8cn.h000066400000000000000000000131421470420105600237350ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2019 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // affine() // sBox() // L() // TRANSPOSE_INP() // TRANSPOSE_OUT() // */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #ifndef __SMS4_SBOX_Y8_H_ #define __SMS4_SBOX_Y8_H_ #include "owndefs.h" #include "owncp.h" static __ALIGN16 Ipp8u inpMaskLO[] = {0x65,0x41,0xfd,0xd9,0x0a,0x2e,0x92,0xb6,0x0f,0x2b,0x97,0xb3,0x60,0x44,0xf8,0xdc}; static __ALIGN16 Ipp8u inpMaskHI[] = {0x00,0xc9,0x67,0xae,0x80,0x49,0xe7,0x2e,0x4a,0x83,0x2d,0xe4,0xca,0x03,0xad,0x64}; static __ALIGN16 Ipp8u outMaskLO[] = {0xd3,0x59,0x38,0xb2,0xcc,0x46,0x27,0xad,0x36,0xbc,0xdd,0x57,0x29,0xa3,0xc2,0x48}; static __ALIGN16 Ipp8u outMaskHI[] = {0x00,0x50,0x14,0x44,0x89,0xd9,0x9d,0xcd,0xde,0x8e,0xca,0x9a,0x57,0x07,0x43,0x13}; static __ALIGN16 Ipp8u encKey[] = {0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63}; static __ALIGN16 Ipp8u maskSrows[] = {0x00,0x0d,0x0a,0x07,0x04,0x01,0x0e,0x0b,0x08,0x05,0x02,0x0f,0x0c,0x09,0x06,0x03}; static __ALIGN16 Ipp8u lowBits4[] = {0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f}; static __ALIGN16 Ipp8u swapBytes[] = {3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12}; static __ALIGN16 Ipp8u affineIn[] = { 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34, 0x52,0xBC,0x2D,0x02,0x9E,0x25,0xAC,0x34 }; static __ALIGN16 Ipp8u affineOut[] = { 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7, 0x19,0x8b,0x6c,0x1e,0x51,0x8e,0x2d,0xd7 }; #define M128(mem) (*((__m128i*)((Ipp8u*)(mem)))) /* // // AES and SMS4 ciphers both based on composite field GF(2^8). // This affine transformation transforms 16 bytes // from SMS4 representation to AES representation or vice versa // depending on passed masks. // */ __FORCEINLINE __m128i affine(__m128i x, __m128i maskLO, __m128i maskHI) { __m128i T1 = _mm_and_si128(_mm_srli_epi64(x, 4), M128(lowBits4)); __m128i T0 = _mm_and_si128(x, M128(lowBits4)); T0 = _mm_shuffle_epi8(maskLO, T0); T1 = _mm_shuffle_epi8(maskHI, T1); return _mm_xor_si128(T0, T1); } /* // // GF(256) is isomorfic. // Encoding/decoding data of SM4 and AES are elements of GF(256). // The difference in representation only. // (It happened due to using different generating polynomials in SM4 and AES representations). // Doing data conversion from SM4 to AES domain // lets use AES specific intrinsics to perform less expensive SMS4 S-box computation. // // Original SMS4 S-box algorithm is converted to the following: // // - transform data from SMS4 representation to AES representation // - compute S-box value using _mm_aesenclast_si128 with special key // - re-shuffle data after _mm_aesenclast_si128 that shuffle it inside // - transform data back from AES representation to SMS4 representation // */ __FORCEINLINE __m128i sBox(__m128i block) { block = affine(block, M128(inpMaskLO), M128(inpMaskHI)); block = _mm_aesenclast_si128(block, M128(encKey)); block = _mm_shuffle_epi8(block, M128(maskSrows)); block = affine(block, M128(outMaskLO), M128(outMaskHI)); return block; } #if (_IPP==_IPP_I0) __FORCEINLINE __m128i L(__m128i x) { __m128i T = _mm_slli_epi32(x, 2); T = _mm_xor_si128(T, _mm_srli_epi32(x, 30)); T = _mm_xor_si128(T, _mm_slli_epi32(x, 10)); T = _mm_xor_si128(T, _mm_srli_epi32(x, 22)); T = _mm_xor_si128(T, _mm_slli_epi32(x, 18)); T = _mm_xor_si128(T, _mm_srli_epi32(x, 14)); T = _mm_xor_si128(T, _mm_slli_epi32(x, 24)); T = _mm_xor_si128(T, _mm_srli_epi32(x, 8)); return T; } #else static __ALIGN16 Ipp8u ROL8[] = { 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14 }; static __ALIGN16 Ipp8u ROL16[] = { 2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13 }; static __ALIGN16 Ipp8u ROL24[] = { 1,2,3,0, 5,6,7,4, 9,10,11,8, 13,14,15,12 }; __FORCEINLINE __m128i L(__m128i x) { __m128i rol2 = _mm_xor_si128(_mm_slli_epi32(x, 2), _mm_srli_epi32(x, 30)); __m128i rol24 = _mm_shuffle_epi8(x, M128(ROL24)); __m128i rol10 = _mm_shuffle_epi8(rol2, M128(ROL8)); __m128i rol18 = _mm_shuffle_epi8(rol2, M128(ROL16)); __m128i R = _mm_xor_si128(rol24, _mm_xor_si128(rol18, _mm_xor_si128(rol2, rol10))); return R; } #endif #define TRANSPOSE_INP(K0,K1,K2,K3, T) \ T = _mm_unpacklo_epi32(K0, K1); \ K1 = _mm_unpackhi_epi32(K0, K1); \ K0 = _mm_unpacklo_epi32(K2, K3); \ K3 = _mm_unpackhi_epi32(K2, K3); \ \ K2 = _mm_unpacklo_epi64(K1, K3); \ K3 = _mm_unpackhi_epi64(K1, K3); \ K1 = _mm_unpackhi_epi64(T, K0); \ K0 = _mm_unpacklo_epi64(T, K0) #define TRANSPOSE_OUT(K0,K1,K2,K3, T) \ T = _mm_unpacklo_epi32(K1, K0); \ K0 = _mm_unpackhi_epi32(K1, K0); \ K1 = _mm_unpacklo_epi32(K3, K2); \ K3 = _mm_unpackhi_epi32(K3, K2); \ \ K2 = _mm_unpackhi_epi64(K1, T); \ T = _mm_unpacklo_epi64(K1, T); \ K1 = _mm_unpacklo_epi64(K3, K0); \ K0 = _mm_unpackhi_epi64(K3, K0); \ K3 = T #endif /* __SMS4_SBOX_Y8_H_ */ #endif /* _IPP_P8, _IPP32E_Y8 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4authccm.h000066400000000000000000000056031470420105600243440ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2017 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Message Authentication Algorithm // Internal Definitions and Internal Functions Prototypes // // */ #if !defined(_CP_SMS4_CCM_H) #define _CP_SMS4_CCM_H #include "pcpsms4.h" struct _cpSMS4_CCM { Ipp32u idCtx; /* CCM ID */ Ipp64u msgLen; /* length of message to be processed */ Ipp64u lenProcessed; /* message length has been processed */ Ipp32u tagLen; /* length of authentication tag */ Ipp32u counterVal; /* current counter value */ Ipp8u ctr0[MBS_SMS4]; /* counter value */ Ipp8u s0[MBS_SMS4]; /* S0 = ENC(CTR0) content */ Ipp8u si[MBS_SMS4]; /* Si = ENC(CTRi) content */ Ipp8u blk[MBS_SMS4]; /* temporary data container */ Ipp8u mac[MBS_SMS4]; /* current MAC value */ Ipp8u cipher[sizeof(IppsSMS4Spec)]; }; /* alignment */ #define SMS4CCM_ALIGNMENT ((int)(sizeof(void*))) /* // access macros */ #define SMS4CCM_SET_ID(stt) ((stt)->idCtx = (Ipp32u)idCtxAESCCM ^ (Ipp32u)IPP_UINT_PTR(stt)) #define SMS4CCM_MSGLEN(stt) ((stt)->msgLen) #define SMS4CCM_LENPRO(stt) ((stt)->lenProcessed) #define SMS4CCM_TAGLEN(stt) ((stt)->tagLen) #define SMS4CCM_COUNTER(stt) ((stt)->counterVal) #define SMS4CCM_CTR0(stt) ((stt)->ctr0) #define SMS4CCM_S0(stt) ((stt)->s0) #define SMS4CCM_Si(stt) ((stt)->si) #define SMS4CCM_BLK(stt) ((stt)->blk) #define SMS4CCM_MAC(stt) ((stt)->mac) #define SMS4CCM_CIPHER(stt) (IppsSMS4Spec*)(&((stt)->cipher)) /* valid context ID */ #define VALID_SMS4CCM_ID(ctx) ((((ctx)->idCtx) ^ (Ipp32u)IPP_UINT_PTR((ctx))) == (Ipp32u)idCtxAESCCM) static int cpSizeofCtx_SMS4CCM(void) { return sizeof(IppsSMS4_CCMState); } /* Counter block formatter */ static Ipp8u* CounterEnc(Ipp32u* pBuffer, int fmt, Ipp64u counter) { #if (IPP_ENDIAN == IPP_LITTLE_ENDIAN) pBuffer[0] = ENDIANNESS(IPP_HIDWORD(counter)); pBuffer[1] = ENDIANNESS(IPP_LODWORD(counter)); #else pBuffer[0] = IPP_HIDWORD(counter); pBuffer[1] = IPP_LODWORD(counter); #endif return (Ipp8u*)pBuffer + 8 - fmt; } #endif /* _CP_SMS4_CCM_H*/ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4cbcl9cn.c000066400000000000000000000247651470420105600242420ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 CBC decryption // // Contents: // cpSMS4_CBC_dec_aesni() // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #if (_IPP>=_IPP_H9) || (_IPP32E>=_IPP32E_L9) #include "pcpsms4_l9cn.h" IPP_OWN_DEFN (int, cpSMS4_CBC_dec_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV)) { __ALIGN16 __m256i TMP[17]; /* TMP[ 0] = T0 TMP[ 1] = T1 TMP[ 2] = T2 TMP[ 3] = T3 TMP[ 4] = K0 TMP[ 5] = K1 TMP[ 6] = K2 TMP[ 7] = K3 TMP[ 8] = P0 TMP[ 9] = P1 TMP[10] = P2 TMP[11] = P3 TMP[12] = Q0 TMP[13] = Q1 TMP[14] = Q2 TMP[15] = Q3 TMP[16] = IV */ TMP[16] = _mm256_castsi128_si256(_mm_loadu_si128((__m128i*)(pIV))); int processedLen = len -(len % (24*MBS_SMS4)); int n; for(n=0; n=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #include "pcpsms4_y8cn.h" /* // 4*MBS_SMS4 processing */ static int cpSMS4_CBC_dec_aesni_x4(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV) { __ALIGN16 __m128i TMP[9]; /* TMP[0] = T TMP[1] = T0 TMP[2] = T1 TMP[3] = T2 TMP[4] = T3 TMP[5] = K0 TMP[6] = K1 TMP[7] = K2 TMP[8] = K3 */ TMP[1] = _mm_loadu_si128((__m128i*)(pIV)); int processedLen = len & -(4*MBS_SMS4); int n; for(n=0; n=_IPP_H9) || (_IPP32E>=_IPP32E_L9) IPP_OWN_DEFN (int, cpSMS4_CBC_dec_aesni_x12, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV)) #else IPP_OWN_DEFN (int, cpSMS4_CBC_dec_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, Ipp8u* pIV)) #endif { __ALIGN16 __m128i TMP[19]; /* TMP[ 0] = T TMP[ 1] = U TMP[ 2] = V TMP[ 3] = T0 TMP[ 4] = T1 TMP[ 5] = T2 TMP[ 6] = T3 TMP[ 7] = K0 TMP[ 8] = K1 TMP[ 9] = K2 TMP[10] = K3 TMP[11] = P0 TMP[12] = P1 TMP[13] = P2 TMP[14] = P3 TMP[15] = Q0 TMP[16] = Q1 TMP[17] = Q2 TMP[18] = Q3 */ TMP[3] = _mm_loadu_si128((__m128i*)(pIV)); int processedLen = len -(len % (12*MBS_SMS4)); int n; for(n=0; n=_IPP_H9) || (_IPP32E>=_IPP32E_L9) #include "pcpsms4_l9cn.h" static __ALIGN32 Ipp8u endianness_swap[] = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3, 12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3}; static __ALIGN32 Ipp8u endianness[] = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0, 15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; static __ALIGN32 Ipp8u two256[] = {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static __ALIGN16 Ipp8u one256[] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; __IPPCP_INLINE __m128i inc128(__m128i x) { __m128i t = _mm_add_epi64(x, M128(one256)); x = _mm_cmpeq_epi64(t, _mm_setzero_si128()); t = _mm_sub_epi64(t, _mm_slli_si128(x, sizeof(Ipp64u))); return t; } __IPPCP_INLINE __m256i inc256(__m256i x) { __m256i t = _mm256_add_epi64(x, M256(two256)); x = _mm256_cmpeq_epi64(t, _mm256_setzero_si256()); t = _mm256_sub_epi64(t, _mm256_slli_si256(x, sizeof(Ipp64u))); return t; } __IPPCP_INLINE __m256i inc256_2(__m256i x) { __m256i t = _mm256_add_epi64(x, M256(one256)); x = _mm256_cmpeq_epi64(t, _mm256_setzero_si256()); t = _mm256_sub_epi64(t, _mm256_slli_si256(x, sizeof(Ipp64u))); t = _mm256_add_epi64(t, M256(one256)); x = _mm256_cmpeq_epi64(t, _mm256_setzero_si256()); t = _mm256_sub_epi64(t, _mm256_slli_si256(x, sizeof(Ipp64u))); return t; } IPP_OWN_DEFN (int, cpSMS4_CTR_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) { int processedLen = len & -(16*MBS_SMS4); if(processedLen) { int n; __ALIGN16 __m256i TMP[16]; /* TMP[ 0] = T0 TMP[ 1] = T1 TMP[ 2] = T2 TMP[ 3] = T3 TMP[ 4] = K0 TMP[ 5] = K1 TMP[ 6] = K2 TMP[ 7] = K3 TMP[ 8] = P0 TMP[ 9] = P1 TMP[10] = P2 TMP[11] = P3 TMP[12] = ctr TMP[13] = mask TMP[14] = unch */ /* read string counter and convert to numerical */ TMP[12] = _mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pCtr)), M256(endianness)); /* read string mask and convert to numerical */ TMP[13] = _mm256_shuffle_epi8(_mm256_castsi128_si256(_mm_loadu_si128((__m128i*)pCtrMask)), M256(endianness)); /* upchanged counter bits */ TMP[14] = _mm256_andnot_si256(TMP[13], TMP[12]); TMP[12] = _mm256_inserti128_si256(TMP[12], inc128(_mm256_castsi256_si128(TMP[12])), 1); TMP[13]= _mm256_inserti128_si256(TMP[13], _mm256_castsi256_si128(TMP[13]), 1); TMP[14]= _mm256_inserti128_si256(TMP[14], _mm256_castsi256_si128(TMP[14]), 1); TMP[12] = _mm256_and_si256(TMP[12], TMP[13]); for(n=0; n=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #include "pcpsms4_y8cn.h" static __ALIGN16 Ipp8u one128[] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static __ALIGN16 Ipp8u endianness[] = {15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0}; static __ALIGN16 Ipp8u endianness_swap[] = {12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3}; __IPPCP_INLINE __m128i inc128(__m128i x) { __m128i t = _mm_add_epi64(x, M128(one128)); x = _mm_cmpeq_epi64(t, _mm_setzero_si128()); t = _mm_sub_epi64(t, _mm_slli_si128(x, sizeof(Ipp64u))); return t; } #if (_IPP>=_IPP_H9) || (_IPP32E>=_IPP32E_L9) IPP_OWN_DEFN (int, cpSMS4_CTR_aesni_x4, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) #else IPP_OWN_DEFN (int, cpSMS4_CTR_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey, const Ipp8u* pCtrMask, Ipp8u* pCtr)) #endif { __ALIGN16 __m128i TMP[8]; /* TMP[ 0] = T TMP[ 1] = K0 TMP[ 2] = K1 TMP[ 3] = K2 TMP[ 4] = K3 TMP[ 5] = ctrUnchanged TMP[ 6] = ctrMask TMP[ 7] = ctr */ int processedLen = len & -(4*MBS_SMS4); int n; TMP[6] = _mm_loadu_si128((__m128i*)pCtrMask); TMP[7] = _mm_loadu_si128((__m128i*)pCtr); TMP[6] = _mm_shuffle_epi8(TMP[6], M128(endianness)); TMP[7] = _mm_shuffle_epi8(TMP[7], M128(endianness)); TMP[5] = _mm_andnot_si128(TMP[6], TMP[7]); for(n=0; ncfbBlkSize || cfbBlkSize>MBS_SMS4) // ippStsUnderRunErr 0!=(len%cfbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // cfbBlkSize CFB block size (in bytes) // pCtx pointer to the SMS4 context // pIV pointer to the initialization vector // *F*/ static void cpDecryptSMS4_cfb(const Ipp8u* pIV, const Ipp8u* pSrc, Ipp8u* pDst, int nBlocks, int cfbBlkSize, const IppsSMS4Spec* pCtx) { __ALIGN16 Ipp32u TMP[3*MBS_SMS4/sizeof(Ipp32u)]; /* tmpInp size = 2*MBS_SMS4/sizeof(Ipp32u) tmpOut size = MBS_SMS4/sizeof(Ipp32u) */ Ipp32u* tmpInp = TMP; Ipp32u* tmpOut = TMP + 2*MBS_SMS4/sizeof(Ipp32u); /* read IV */ CopyBlock16(pIV, tmpInp); /* decrypt data block-by-block of cfbLen each */ while(nBlocks) { /* decryption */ cpSMS4_Cipher((Ipp8u*)tmpOut, (Ipp8u*)tmpInp, SMS4_RK(pCtx)); /* store output and put feedback into the input buffer (tmpInp) */ if( cfbBlkSize==MBS_SMS4 && pSrc!=pDst) { ((Ipp32u*)pDst)[0] = tmpOut[0]^((Ipp32u*)pSrc)[0]; ((Ipp32u*)pDst)[1] = tmpOut[1]^((Ipp32u*)pSrc)[1]; ((Ipp32u*)pDst)[2] = tmpOut[2]^((Ipp32u*)pSrc)[2]; ((Ipp32u*)pDst)[3] = tmpOut[3]^((Ipp32u*)pSrc)[3]; tmpInp[0] = ((Ipp32u*)pSrc)[0]; tmpInp[1] = ((Ipp32u*)pSrc)[1]; tmpInp[2] = ((Ipp32u*)pSrc)[2]; tmpInp[3] = ((Ipp32u*)pSrc)[3]; } else { int n; for(n=0; ncfbBlkSize) || (MBS_SMS4=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) if (IsFeatureEnabled(ippCPUID_AVX512GFNI)) { __ALIGN16 Ipp8u IV[MBS_SMS4]; CopyBlock16(pIV, IV); if(len/cfbBlkSize >= 4) { cpSMS4_CFB_dec_gfni512(pDst, pSrc, len, cfbBlkSize, (Ipp32u*)SMS4_RK(pCtx), IV); /* pipeline */ int processedLen = len - (len % (4*cfbBlkSize)); pSrc += processedLen; pDst += processedLen; len = len - processedLen; } if(len) { cpDecryptSMS4_cfb(IV, pSrc, pDst, len/cfbBlkSize, cfbBlkSize, pCtx); /* tail */ } } else #endif #endif { cpDecryptSMS4_cfb(pIV, pSrc, pDst, len/cfbBlkSize, cfbBlkSize, pCtx); } return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4decryptctr.c000066400000000000000000000040731470420105600250760ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // ippsSMS4DecryptCTR() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" /*F* // Name: ippsSMS4DecryptCTR // // Purpose: SMS4-CRT encryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr !VALID_SMS4_ID() // ippStsLengthErr len <1 // ippStsCTRSizeErr 128 < ctrNumBitSize < 1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // pCtx pointer to rge SMS4 context // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // *F*/ IPPFUN(IppStatus, ippsSMS4DecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx, Ipp8u* pCtrValue, int ctrNumBitSize)) { return cpProcessSMS4_ctr(pSrc, pDst, len, pCtx, pCtrValue, ctrNumBitSize); } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4decryptecb.c000066400000000000000000000060751470420105600250430ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // ippsSMS4DecryptECB() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" /*F* // Name: ippsSMS4DecryptECB // // Purpose: SMS4-ECB decryption. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr !VALID_SMS4_ID() // ippStsLengthErr len <1 // ippStsUnderRunErr 0!=(len%MBS_SMS4) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // pCtx pointer to the SMS4 context // *F*/ IPPFUN(IppStatus, ippsSMS4DecryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsSMS4Spec* pCtx)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_SMS4_ID(pCtx), ippStsContextMatchErr); /* test source and target buffer pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test stream integrity */ IPP_BADARG_RET((len&(MBS_SMS4-1)), ippStsUnderRunErr); /* do encryption */ #if (_IPP32E>=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) if (IsFeatureEnabled(ippCPUID_AVX512GFNI)) { int processedLen = cpSMS4_ECB_gfni512(pDst, pSrc, len, SMS4_DRK(pCtx)); pSrc += processedLen; pDst += processedLen; len -= processedLen; } else #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920)) */ #endif /* (_IPP32E>=_IPP32E_K1) */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) { int processedLen = cpSMS4_ECB_aesni(pDst, pSrc, len, SMS4_DRK(pCtx)); pSrc += processedLen; pDst += processedLen; len -= processedLen; } else #endif for(; len>0; len-=MBS_SMS4, pSrc+=MBS_SMS4, pDst+=MBS_SMS4) cpSMS4_Cipher(pDst, pSrc, SMS4_DRK(pCtx)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4decryptofb.c000066400000000000000000000051751470420105600250600ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // ippsSMS4DecryptOFB() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #include "pcpsms4_process_ofb8.h" /*F* // Name: ippsSMS4DecryptOFB // // Purpose: Decrypts byte data stream according to SMS4 in OFB mode. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_SMS4_ID() // ippStsLengthErr len <1 // ippStsOFBSizeErr (1>ofbBlkSize || ofbBlkSize>MBS_SMS4) // ippStsUnderRunErr (len%ofbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // ofbBlkSize OFB block size (in bytes) // pCtx pointer to the SMS4 context // pIV pointer to the initialization vector *F*/ IPPFUN(IppStatus, ippsSMS4DecryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_SMS4_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test OFB value */ IPP_BADARG_RET(((1>ofbBlkSize) || (MBS_SMS4=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #include "pcpsms4_y8cn.h" /* // (1-3)*MBS_SMS4 processing */ static int cpSMS4_ECB_aesni_tail(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey) { __ALIGN16 __m128i TMP[6]; /* TMP[0] = T TMP[1] = K0 TMP[2] = K1 TMP[3] = K2 TMP[4] = K3 TMP[5] = key4 */ TMP[2] = _mm_setzero_si128(); TMP[3] = _mm_setzero_si128(); TMP[4] = _mm_setzero_si128(); switch (len) { case (3*MBS_SMS4): TMP[3] = _mm_shuffle_epi8(_mm_loadu_si128((__m128i*)(pInp+2*MBS_SMS4)), M128(swapBytes)); case (2*MBS_SMS4): TMP[2] = _mm_shuffle_epi8(_mm_loadu_si128((__m128i*)(pInp+1*MBS_SMS4)), M128(swapBytes)); case (1*MBS_SMS4): TMP[1] = _mm_shuffle_epi8(_mm_loadu_si128((__m128i*)(pInp+0*MBS_SMS4)), M128(swapBytes)); break; default: return 0; } TRANSPOSE_INP(TMP[1],TMP[2],TMP[3],TMP[4], TMP[0]); { int itr; for(itr=0; itr<8; itr++, pRKey+=4) { TMP[5] = _mm_loadu_si128((__m128i*)pRKey); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0x00); /* broadcast(key4 TMP[0]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[0]), L(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0x55); /* broadcast(key4 TMP[1]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[0]), L(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0xAA); /* broadcast(key4 TMP[2]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[0]), L(TMP[0])); /* initial xors */ TMP[0] = _mm_shuffle_epi32(TMP[5], 0xFF); /* broadcast(key4 TMP[3]) */ TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now L */ TMP[4] = _mm_xor_si128(_mm_xor_si128(TMP[4], TMP[0]), L(TMP[0])); } } TRANSPOSE_OUT(TMP[1],TMP[2],TMP[3],TMP[4], TMP[0]); TMP[4] = _mm_shuffle_epi8(TMP[4], M128(swapBytes)); TMP[3] = _mm_shuffle_epi8(TMP[3], M128(swapBytes)); TMP[2] = _mm_shuffle_epi8(TMP[2], M128(swapBytes)); TMP[1] = _mm_shuffle_epi8(TMP[1], M128(swapBytes)); switch (len) { case (3*MBS_SMS4): _mm_storeu_si128((__m128i*)(pOut+2*MBS_SMS4), TMP[2]); case (2*MBS_SMS4): _mm_storeu_si128((__m128i*)(pOut+1*MBS_SMS4), TMP[3]); case (1*MBS_SMS4): _mm_storeu_si128((__m128i*)(pOut+0*MBS_SMS4), TMP[4]); break; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_xor_si128(TMP[i],TMP[i]); } return len; } /* // 4*MBS_SMS4 processing */ static int cpSMS4_ECB_aesni_x4(Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey) { __ALIGN16 __m128i TMP[5]; /* TMP[0] = T TMP[1] = K0 TMP[2] = K1 TMP[3] = K2 TMP[4] = K3 */ int processedLen = len & -(4*MBS_SMS4); int n; for(n=0; n=_IPP_H9) || (_IPP32E>=_IPP32E_L9) #define cpSMS4_ECB_aesni_x12 OWNAPI(cpSMS4_ECB_aesni_x12) IPP_OWN_DECL (int, cpSMS4_ECB_aesni_x12, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) IPP_OWN_DEFN (int, cpSMS4_ECB_aesni_x12, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) #else #define cpSMS4_ECB_aesni OWNAPI(cpSMS4_ECB_aesni) IPP_OWN_DECL (int, cpSMS4_ECB_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) IPP_OWN_DEFN (int, cpSMS4_ECB_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) #endif { __ALIGN16 __m128i TMP[15]; /* TMP[ 0] = T TMP[ 1] = U TMP[ 2] = V TMP[ 3] = K0 TMP[ 4] = K1 TMP[ 5] = K2 TMP[ 6] = K3 TMP[ 7] = P0 TMP[ 8] = P1 TMP[ 9] = P2 TMP[10] = P3 TMP[11] = Q0 TMP[12] = Q1 TMP[13] = Q2 TMP[14] = Q3 */ int processedLen = len -(len % (12*MBS_SMS4)); int n; for(n=0; n=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #include "pcpsms4_y8cn.h" __IPPCP_INLINE __m128i Ltag(__m128i x) { __m128i T = _mm_slli_epi32(x, 13); T = _mm_xor_si128(T, _mm_srli_epi32 (x,19)); T = _mm_xor_si128(T, _mm_slli_epi32 (x,23)); T = _mm_xor_si128(T, _mm_srli_epi32 (x, 9)); return T; } /* // compute round keys */ #define cpSMS4_SetRoundKeys_aesni OWNAPI(cpSMS4_SetRoundKeys_aesni) IPP_OWN_DECL (void, cpSMS4_SetRoundKeys_aesni, (Ipp32u* pRoundKey, const Ipp8u* pSecretKey)) IPP_OWN_DEFN (void, cpSMS4_SetRoundKeys_aesni, (Ipp32u* pRoundKey, const Ipp8u* pSecretKey)) { __ALIGN16 __m128i TMP[5]; /* TMP[0] = T TMP[1] = K0 TMP[2] = K1 TMP[3] = K2 TMP[4] = K3 */ TMP[1] = _mm_cvtsi32_si128((Ipp32s)(ENDIANNESS32(((Ipp32u*)pSecretKey)[0]) ^ SMS4_FK[0])); TMP[2] = _mm_cvtsi32_si128((Ipp32s)(ENDIANNESS32(((Ipp32u*)pSecretKey)[1]) ^ SMS4_FK[1])); TMP[3] = _mm_cvtsi32_si128((Ipp32s)(ENDIANNESS32(((Ipp32u*)pSecretKey)[2]) ^ SMS4_FK[2])); TMP[4] = _mm_cvtsi32_si128((Ipp32s)(ENDIANNESS32(((Ipp32u*)pSecretKey)[3]) ^ SMS4_FK[3])); const Ipp32u* pCK = SMS4_CK; int itr; for(itr=0; itr<8; itr++) { /* initial xors */ TMP[0] = _mm_cvtsi32_si128((Ipp32s)pCK[0]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now Ltag */ TMP[1] = _mm_xor_si128(_mm_xor_si128(TMP[1], TMP[0]), Ltag(TMP[0])); pRoundKey[0] = (Ipp32u)_mm_cvtsi128_si32(TMP[1]); /* initial xors */ TMP[0] = _mm_cvtsi32_si128((Ipp32s)pCK[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now Ltag */ TMP[2] = _mm_xor_si128(_mm_xor_si128(TMP[2], TMP[0]), Ltag(TMP[0])); pRoundKey[1] = (Ipp32u)_mm_cvtsi128_si32(TMP[2]); /* initial xors */ TMP[0] = _mm_cvtsi32_si128((Ipp32s)pCK[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[4]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now Ltag */ TMP[3] = _mm_xor_si128(_mm_xor_si128(TMP[3], TMP[0]), Ltag(TMP[0])); pRoundKey[2] = (Ipp32u)_mm_cvtsi128_si32(TMP[3]); /* initial xors */ TMP[0] = _mm_cvtsi32_si128((Ipp32s)pCK[3]); TMP[0] = _mm_xor_si128(TMP[0], TMP[1]); TMP[0] = _mm_xor_si128(TMP[0], TMP[2]); TMP[0] = _mm_xor_si128(TMP[0], TMP[3]); /* Sbox */ TMP[0] = sBox(TMP[0]); /* Sbox done, now Ltag */ TMP[4] = _mm_xor_si128(_mm_xor_si128(TMP[4], TMP[0]), Ltag(TMP[0])); pRoundKey[3] = (Ipp32u)_mm_cvtsi128_si32(TMP[4]); pCK += 4; pRoundKey += 4; } /* clear secret data */ for(Ipp32u i = 0; i < sizeof(TMP)/sizeof(TMP[0]); i++){ TMP[i] = _mm_xor_si128(TMP[i],TMP[i]); } } #endif /* _IPP_P8, _IPP32E_Y8 */ cryptography-primitives-1.0.0/sources/ippcp/pcpsms4ecbl9cn.c000066400000000000000000000223241470420105600242310ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2014 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 ECB decryption // // Contents: // cpSMS4_ECB_aesni() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #if (_IPP>=_IPP_H9) || (_IPP32E>=_IPP32E_L9) #include "pcpsms4_l9cn.h" IPP_OWN_DEFN (int, cpSMS4_ECB_aesni, (Ipp8u* pOut, const Ipp8u* pInp, int len, const Ipp32u* pRKey)) { __ALIGN16 __m256i TMP[16]; /* TMP[ 0] = T0 TMP[ 1] = T1 TMP[ 2] = T2 TMP[ 3] = T3 TMP[ 4] = K0 TMP[ 5] = K1 TMP[ 6] = K2 TMP[ 7] = K3 TMP[ 8] = P0 TMP[ 9] = P1 TMP[10] = P2 TMP[11] = P3 TMP[12] = Q0 TMP[13] = Q1 TMP[14] = Q2 TMP[15] = Q3 */ int processedLen = len -(len % (24*MBS_SMS4)); int n; for(n=0; ncfbBlkSize || cfbBlkSize>MBS_SMS4) // ippStsUnderRunErr 0!=(len%cfbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // cfbBlkSize CFB block size (in bytes) // pCtx pointer to the SMS4 context // pIV pointer to the initialization vector // *F*/ IPPFUN(IppStatus, ippsSMS4EncryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsSMS4Spec* pCtx, const Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_SMS4_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test CFB value */ IPP_BADARG_RET(((1>cfbBlkSize) || (MBS_SMS4=cfbBlkSize) { int n; /* encryption */ cpSMS4_Cipher((Ipp8u*)tmpOut, (Ipp8u*)tmpInp, SMS4_RK(pCtx)); /* store output and put feedback into the input buffer (tmpInp) */ if( cfbBlkSize==MBS_SMS4 && pSrc!=pDst) { tmpInp[0] = ((Ipp32u*)pDst)[0] = tmpOut[0]^((Ipp32u*)pSrc)[0]; tmpInp[1] = ((Ipp32u*)pDst)[1] = tmpOut[1]^((Ipp32u*)pSrc)[1]; tmpInp[2] = ((Ipp32u*)pDst)[2] = tmpOut[2]^((Ipp32u*)pSrc)[2]; tmpInp[3] = ((Ipp32u*)pDst)[3] = tmpOut[3]^((Ipp32u*)pSrc)[3]; } else { for(n=0; n=_IPP32E_K1) #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) if (IsFeatureEnabled(ippCPUID_AVX512GFNI)) { int processedLen = cpSMS4_ECB_gfni512(pDst, pSrc, len, SMS4_ERK(pCtx)); pSrc += processedLen; pDst += processedLen; len -= processedLen; } else #endif /* #if defined (__INTEL_COMPILER) || defined (__INTEL_LLVM_COMPILER) || !defined (_MSC_VER) || (_MSC_VER >= 1920) */ #endif /* (_IPP32E>=_IPP32E_K1) */ #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) { int processedLen = cpSMS4_ECB_aesni(pDst, pSrc, len, SMS4_ERK(pCtx)); pSrc += processedLen; pDst += processedLen; len -= processedLen; } else #endif for(; len>0; len-=MBS_SMS4, pSrc+=MBS_SMS4, pDst+=MBS_SMS4) cpSMS4_Cipher(pDst, pSrc, SMS4_RK(pCtx)); return ippStsNoErr; } cryptography-primitives-1.0.0/sources/ippcp/pcpsms4encryptofb.c000066400000000000000000000051751470420105600250720ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2013 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // SMS4 encryption/decryption // // Contents: // ippsSMS4EncryptOFB() // */ #include "owncp.h" #include "pcpsms4.h" #include "pcptool.h" #include "pcpsms4_process_ofb8.h" /*F* // Name: ippsSMS4EncryptOFB // // Purpose: Encrypts byte data stream according to SMS4 in OFB mode. // // Returns: Reason: // ippStsNullPtrErr pCtx == NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr !VALID_SMS4_ID() // ippStsLengthErr len <1 // ippStsOFBSizeErr (1>ofbBlkSize || ofbBlkSize>MBS_SMS4) // ippStsUnderRunErr (len%ofbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data buffer // pDst pointer to the target data buffer // len input/output buffer length (in bytes) // ofbBlkSize OFB block size (in bytes) // pCtx pointer to the SMS4 context // pIV pointer to the initialization vector *F*/ IPPFUN(IppStatus, ippsSMS4EncryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsSMS4Spec* pCtx, Ipp8u* pIV)) { /* test context */ IPP_BAD_PTR1_RET(pCtx); /* test the context ID */ IPP_BADARG_RET(!VALID_SMS4_ID(pCtx), ippStsContextMatchErr); /* test source, target buffers and initialization pointers */ IPP_BAD_PTR3_RET(pSrc, pIV, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test OFB value */ IPP_BADARG_RET(((1>ofbBlkSize) || (MBS_SMS4=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) if(IsFeatureEnabled(ippCPUID_AES) || IsFeatureEnabled(ippCPUID_AVX2VAES)) cpSMS4_SetRoundKeys_aesni(SMS4_RK(pCtx), pSecretKey); else #endif cpSMS4_SetRoundKeys(SMS4_RK(pCtx), pSecretKey); /* set deccryption round keys */ { int n; for(n=0; n < SMS4_ROUND_KEYS_NUM; n++) { SMS4_DRK(pCtx)[n] = SMS4_RK(pCtx)[SMS4_ROUND_KEYS_NUM - n-1]; } } return ippStsNoErr; } } cryptography-primitives-1.0.0/sources/ippcp/pcptdesctrca.c000066400000000000000000000136721470420105600240650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2004 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Encrypt/Decrypt byte data stream according to TDES (CTR mode) // // Contents: // ippsTDESEncryptCTR() // ippsTDESDecryptCTR() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdes.h" #include "pcptool.h" static IppStatus TDES_CTR(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pCtrValue, int ctrNumBitSize) { Ipp64u counter; Ipp64u output; /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source, target and counter block pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pCtrValue); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test counter block size */ IPP_BADARG_RET(((MBS_DES*8)= MBS_DES) { /* encrypt counter block */ output = Cipher_DES(counter, DES_EKEYS(pCtx1), DESspbox); output = Cipher_DES(output, DES_DKEYS(pCtx2), DESspbox); output = Cipher_DES(output, DES_EKEYS(pCtx3), DESspbox); /* compute ciphertext block */ XorBlock8(pSrc, &output, pDst); /* encrement counter block */ StdIncrement((Ipp8u*)&counter,MBS_DES*8, ctrNumBitSize); pSrc += MBS_DES; pDst += MBS_DES; len -= MBS_DES; } /* // encrypt last data block */ if(len) { /* encrypt counter block */ output = Cipher_DES(counter, DES_EKEYS(pCtx1), DESspbox); output = Cipher_DES(output, DES_DKEYS(pCtx2), DESspbox); output = Cipher_DES(output, DES_EKEYS(pCtx3), DESspbox); /* compute ciphertext block */ XorBlock(pSrc, &output, pDst,len); /* encrement counter block */ StdIncrement((Ipp8u*)&counter,MBS_DES*8, ctrNumBitSize); } /* update counter */ CopyBlock8(&counter, pCtrValue); return ippStsNoErr; } /*F* // Name: ippsTDESEncryptCTR // // Purpose: Encrypt byte data stream according to TDES in CTR mode. // // Returns: Reason: // ippStsNullPtrErr pCtx1 == NULL // pCtx2 == NULL // pCtx3 == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr pCtx1->idCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr len <1 // ippStsCTRSizeErr 64 < ctrNumBitSize < 1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data stream // pDst pointer to the target data stream // len plaintext stream length (bytes) // pCtx1-pCtx3 DES contexts // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // *F*/ IPPFUN(IppStatus, ippsTDESEncryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pCtrValue, int ctrNumBitSize)) { return TDES_CTR(pSrc,pDst,len, pCtx1,pCtx2,pCtx3, pCtrValue,ctrNumBitSize); } /*F* // Name: ippsTDESDecryptCTR // // Purpose: Decrypt byte data stream according to TDES in CTR mode. // // Returns: Reason: // ippStsNullPtrErr pCtx1 == NULL // pCtx2 == NULL // pCtx3 == NULL // pSrc == NULL // pDst == NULL // pCtrValue ==NULL // ippStsContextMatchErr pCtx1->idCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr len <1 // ippStsCTRSizeErr 64 < ctrNumBitSize < 1 // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data stream // pDst pointer to the target data stream // len plaintext stream length (bytes) // pCtx1-pCtx3 DES contexts // pCtrValue pointer to the counter block // ctrNumBitSize counter block size (bits) // // Note: // counter will updated on return // *F*/ IPPFUN(IppStatus, ippsTDESDecryptCTR,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pCtrValue, int ctrNumBitSize)) { return TDES_CTR(pSrc,pDst,len, pCtx1,pCtx2,pCtx3, pCtrValue,ctrNumBitSize); } cryptography-primitives-1.0.0/sources/ippcp/pcptdesdecryptcbcca.c000066400000000000000000000103241470420105600254060ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // Decrypt byte data stream according to TDES (CBC mode) // // Contents: // ippsTDESDecryptCBC() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpdes.h" #include "pcptool.h" /*F* // Name: ippsTDESDecryptCBC // // Purpose: Decrypt byte data stream according to TDES in CBC mode. // // Returns: Reason: // ippStsNullPtrErr pCtx1 == NULL // pCtx2 == NULL // pCtx3 == NULL // pSrc == NULL // pDst == NULL // ippStsContextMatchErr pCtx1->idCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr length <1 // ippStsUnderRunErr (length&7) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data stream // pDst pointer to the target byte data stream // length plaintext stream length (bytes) // pCtx1-3 pointers to the DES context // pIV pointer to the init vector // padding the padding scheme indicator // *F*/ IPPFUN(IppStatus, ippsTDESDecryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsPadding padding)) { /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pIV); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* force ippPaddingNONE padding */ if(ippPaddingNONE!=padding) padding = ippPaddingNONE; /* test stream integrity */ //IPP_BADARG_RET(((length&7) && (ippPaddingNONE==padding)), ippStsUnderRunErr); IPP_BADARG_RET((len&7), ippStsUnderRunErr); { int nBlocks = len/MBS_DES; /* read IV */ Ipp64u iv; CopyBlock8(pIV, &iv); /* misaligned source and/or target */ /*if( (IPP_UINT_PTR(pSrc) & 0x7) || (IPP_UINT_PTR(pDst) & 0x7) ) {*/ if( (IPP_UINT_PTR(pSrc) & 0x7) || (IPP_UINT_PTR(pDst) & 0x7) || pSrc==pDst) { int n; for(n=0; nidCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr len <1 // ippStsCFBSizeErr (1>cfbBlkSize || cfbBlkSize>MBS_DES) // ippStsUnderRunErr (len%cfbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data stream // pDst pointer to the target byte data stream // len plaintext stream length (bytes) // cfbBlkSize CFB block size (bytes) // pCtx1-3 pointers to the DES context // pIV pointer to the init vector // padding the padding scheme indicator // *F*/ IPPFUN(IppStatus, ippsTDESDecryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsPadding padding)) { Ipp64u inpBuffer[2]; Ipp64u outBuffer; /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pIV); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test CFB value */ IPP_BADARG_RET(((1>cfbBlkSize) || (MBS_DES=cfbBlkSize) { int n; /* decryption */ outBuffer = Cipher_DES(inpBuffer[0], DES_EKEYS(pCtx1), DESspbox); outBuffer = Cipher_DES(outBuffer, DES_DKEYS(pCtx2), DESspbox); outBuffer = Cipher_DES(outBuffer, DES_EKEYS(pCtx3), DESspbox); /* store output and put feedback into the buffer */ for(n=0; nidCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr length < 1 // ippStsUnderRunErr (length & 7) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data stream // pDst pointer to the target byte data stream // length plaintext stream length (bytes) // pCtx1-3 pointers to the DES context // padding the padding scheme indicator // *F*/ IPPFUN(IppStatus, ippsTDESDecryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, IppsPadding padding)) { /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* force ippPaddingNONE padding */ if(ippPaddingNONE!=padding) padding = ippPaddingNONE; /* test stream integrity */ IPP_BADARG_RET((len&7), ippStsUnderRunErr); { int nBlocks = len/MBS_DES; /* misaligned source and/or target */ if( (IPP_UINT_PTR(pSrc) & 0x7) || (IPP_UINT_PTR(pDst) & 0x7) ) { int n; for(n=0; nidCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr length <1 // ippStsUnderRunErr (length & 7) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data stream // pDst pointer to the target byte data stream // length plaintext stream length (bytes) // pCtx1-3 pointers to the DES context // pIV pointer to the init vector // padding the padding scheme indicator // *F*/ IPPFUN(IppStatus, ippsTDESEncryptCBC,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsPadding padding)) { /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pIV); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* force ippPaddingNONE padding */ if(ippPaddingNONE!=padding) padding = ippPaddingNONE; /* test stream integrity */ //IPP_BADARG_RET(((length&7) && (ippPaddingNONE==padding)), ippStsUnderRunErr); IPP_BADARG_RET((len&7), ippStsUnderRunErr); { int nBlocks = len/MBS_DES; /* read IV */ Ipp64u iv; CopyBlock8(pIV, &iv); /* misaligned source and/or target */ /*if( (IPP_UINT_PTR(pSrc) & 0x7) || (IPP_UINT_PTR(pDst) & 0x7) ) {*/ if( (IPP_UINT_PTR(pSrc) & 0x7) || (IPP_UINT_PTR(pDst) & 0x7) || pSrc==pDst) { int n; for(n=0; nidCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr len <1 // ippStsCFBSizeErr (1>cfbBlkSize || cfbBlkSize>MBS_DES) // ippStsUnderRunErr (len%cfbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data stream // pDst pointer to the target byte data stream // len plaintext stream length (bytes) // cfbBlkSize CFB block size (bytes) // pCtx1-3 pointers to the DES context // pIV pointer to the init vector // padding the padding scheme indicator // *F*/ IPPFUN(IppStatus, ippsTDESEncryptCFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int cfbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, const Ipp8u* pIV, IppsPadding padding)) { Ipp64u inpBuffer; Ipp64u outBuffer; /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pIV); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test CFB value */ IPP_BADARG_RET(((1>cfbBlkSize) || (MBS_DES=cfbBlkSize) { int n; /* encryption */ outBuffer = Cipher_DES(inpBuffer, DES_EKEYS(pCtx1), DESspbox); outBuffer = Cipher_DES(outBuffer, DES_DKEYS(pCtx2), DESspbox); outBuffer = Cipher_DES(outBuffer, DES_EKEYS(pCtx3), DESspbox); /* store output and put feedback into the buffer */ for(n=0; nidCtx != idCtxDES // pCtx2->idCtx != idCtxDES // pCtx3->idCtx != idCtxDES // ippStsLengthErr length <1 // ippStsUnderRunErr (length&7) && (ippPaddingNONE==padding) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source byte data stream // pDst pointer to the target byte data stream // length plaintext stream length (bytes) // pCtx1-3 pointers to the DES context // padding the padding scheme indicator // *F*/ IPPFUN(IppStatus, ippsTDESEncryptECB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, IppsPadding padding)) { /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR2_RET(pSrc, pDst); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* force ippPaddingNONE padding */ if(ippPaddingNONE!=padding) padding = ippPaddingNONE; /* test stream integrity */ //IPP_BADARG_RET(((length&7) && (ippPaddingNONE==padding)), ippStsUnderRunErr); IPP_BADARG_RET((len&7), ippStsUnderRunErr); { int nBlocks = len/MBS_DES; /* misaligned source and/or target */ if( (IPP_UINT_PTR(pSrc) & 0x7) || (IPP_UINT_PTR(pDst) & 0x7) ) { int n; for(n=0; n=ofbBlkSize) { /* block-by-block processing */ outBuffer = Cipher_DES(inpBuffer, DES_EKEYS(pCtx1), DESspbox); outBuffer = Cipher_DES(outBuffer, DES_DKEYS(pCtx2), DESspbox); outBuffer = Cipher_DES(outBuffer, DES_EKEYS(pCtx3), DESspbox); /* store output */ XorBlock(pSrc, &outBuffer, pDst, ofbBlkSize); /* shift inpBuffer for the next OFB operation */ if(MBS_DES==ofbBlkSize) inpBuffer = outBuffer; else #if (IPP_ENDIAN == IPP_BIG_ENDIAN) inpBuffer = LSL64(inpBuffer, ofbBlkSize*8) |LSR64(outBuffer, 64-ofbBlkSize*8); #else inpBuffer = LSR64(inpBuffer, ofbBlkSize*8) |LSL64(outBuffer, 64-ofbBlkSize*8); #endif pSrc += ofbBlkSize; pDst += ofbBlkSize; len -= ofbBlkSize; } /* update pIV */ CopyBlock8(&inpBuffer, pIV); } /*F* // Name: ippsTDESEncryptOFB // // Purpose: Encrypts byte data stream according to TDES in OFB mode. // // Returns: Reason: // ippStsNullPtrErr pCtx1== NULL // pCtx2== NULL // pCtx3== NULL // pSrc == NULL // pDst == NULL // pIV == NULL // ippStsContextMatchErr pCtx->idCtx != idCtxRijndael // ippStsLengthErr len <1 // ippStsOFBSizeErr (1>ofbBlkSize || ofbBlkSize>MBS_DES) // ippStsUnderRunErr (len%ofbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data stream // pDst pointer to the target data stream // len plaintext stream length (bytes) // ofbBlkSize OFB block size (bytes) // pCtx1,.. DES contexts // pIV pointer to the initialization vector // *F*/ IPPFUN(IppStatus, ippsTDESEncryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pIV)) { /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); /* test context validity */ IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pIV); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test OFB value */ IPP_BADARG_RET(((1>ofbBlkSize) || (MBS_DESidCtx != idCtxRijndael // ippStsLengthErr len <1 // ippStsOFBSizeErr (1>ofbBlkSize || ofbBlkSize>MBS_DES) // ippStsUnderRunErr (len%ofbBlkSize) // ippStsNoErr no errors // // Parameters: // pSrc pointer to the source data stream // pDst pointer to the target data stream // len plaintext stream length (bytes) // ofbBlkSize OFB block size (bytes) // pCtx1,.. DES contexts // pIV pointer to the initialization vector // *F*/ IPPFUN(IppStatus, ippsTDESDecryptOFB,(const Ipp8u* pSrc, Ipp8u* pDst, int len, int ofbBlkSize, const IppsDESSpec* pCtx1, const IppsDESSpec* pCtx2, const IppsDESSpec* pCtx3, Ipp8u* pIV)) { /* test contexts */ IPP_BAD_PTR3_RET(pCtx1, pCtx2, pCtx3); /* test context validity */ IPP_BADARG_RET(!VALID_DES_ID(pCtx1), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx2), ippStsContextMatchErr); IPP_BADARG_RET(!VALID_DES_ID(pCtx3), ippStsContextMatchErr); /* test source and destination pointers */ IPP_BAD_PTR3_RET(pSrc, pDst, pIV); /* test stream length */ IPP_BADARG_RET((len<1), ippStsLengthErr); /* test OFB value */ IPP_BADARG_RET(((1>ofbBlkSize) || (MBS_DES=_IPP_W7) || (_IPP32E>=_IPP32E_M7)) __IPPCP_INLINE void PurgeBlock(void* pDst, int len) { int n; for(n=0; n> (blkBitSize -numSize)%8 ); int i; Ipp32u carry = 1; for(i=BITS2WORD8_SIZE(blkBitSize)-1; i>=0; i--) { int d = maskPosition - i; Ipp8u mask = (Ipp8u)(maskVal | cpIsMsb_ct((BNU_CHUNK_T)d)); Ipp32u x = pCounter[i] + carry; Ipp8u y = pCounter[i]; pCounter[i] = (Ipp8u)((y & ~mask) | (x & mask)); maskVal &= cpIsMsb_ct((BNU_CHUNK_T)d); carry = (x>>8) & 0x1; } } /* vb */ __IPPCP_INLINE void ompStdIncrement64( void* pInitCtrVal, void* pCurrCtrVal, int ctrNumBitSize, int n ) { int k; Ipp64u cntr; Ipp64u temp; Ipp64s item; #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) ( ( Ipp8u* )&cntr )[k] = ( ( Ipp8u* )pInitCtrVal )[7 - k]; #else for( k = 0; k < 8; k++ ) ( ( Ipp8u* )&cntr )[k] = ( ( Ipp8u* )pInitCtrVal )[k]; #endif if( ctrNumBitSize == 64 ) { cntr += ( Ipp64u )n; } else { Ipp64u mask = CONST_64(0xFFFFFFFFFFFFFFFF) >> ( 64 - ctrNumBitSize ); Ipp64u save = cntr & ( ~mask ); Ipp64u bndr = ( Ipp64u )1 << ctrNumBitSize; temp = cntr & mask; cntr = temp + ( Ipp64u )n; if( cntr > bndr ) { item = ( Ipp64s )n - ( Ipp64s )( bndr - temp ); while( item > 0 ) { cntr = ( Ipp64u )item; item -= ( Ipp64s )bndr; } } cntr = save | ( cntr & mask ); } #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) ( ( Ipp8u* )pCurrCtrVal )[7 - k] = ( ( Ipp8u* )&cntr )[k]; #else for( k = 0; k < 8; k++ ) ( ( Ipp8u* )pCurrCtrVal )[k] = ( ( Ipp8u* )&cntr )[k]; #endif } /* vb */ __IPPCP_INLINE void ompStdIncrement128( void* pInitCtrVal, void* pCurrCtrVal, int ctrNumBitSize, int n ) { int k; Ipp64u low; Ipp64u hgh; Ipp64u flag; Ipp64u mask = CONST_64(0xFFFFFFFFFFFFFFFF); Ipp64u save = 0; #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )&low )[k] = ( ( Ipp8u* )pInitCtrVal )[15 - k]; ( ( Ipp8u* )&hgh )[k] = ( ( Ipp8u* )pInitCtrVal )[7 - k]; } #else for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )&low )[k] = ( ( Ipp8u* )pInitCtrVal )[8 + k]; ( ( Ipp8u* )&hgh )[k] = ( ( Ipp8u* )pInitCtrVal )[k]; } #endif if( ctrNumBitSize == 64 ) { low += ( Ipp64u )n; } else if( ctrNumBitSize < 64 ) { Ipp64u bndr; Ipp64u cntr; Ipp64s item; mask >>= ( 64 - ctrNumBitSize ); save = low & ( ~mask ); cntr = ( low & mask ) + ( Ipp64u )n; if( ctrNumBitSize < 31 ) { bndr = ( Ipp64u )1 << ctrNumBitSize; if( cntr > bndr ) { item = ( Ipp64s )( ( Ipp64s )n - ( ( Ipp64s )bndr - ( Ipp64s )( low & mask ) ) ); while( item > 0 ) { cntr = ( Ipp64u )item; item -= ( Ipp64s )bndr; } } } low = save | ( cntr & mask ); } else { flag = ( low >> 63 ); if( ctrNumBitSize != 128 ) { mask >>= ( 128 - ctrNumBitSize ); save = hgh & ( ~mask ); hgh &= mask; } low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) hgh++; if( ctrNumBitSize != 128 ) { hgh = save | ( hgh & mask ); } } #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )pCurrCtrVal )[15 - k] = ( ( Ipp8u* )&low )[k]; ( ( Ipp8u* )pCurrCtrVal )[7 - k] = ( ( Ipp8u* )&hgh )[k]; } #else for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )pCurrCtrVal )[8 + k] = ( ( Ipp8u* )&low )[k]; ( ( Ipp8u* )pCurrCtrVal )[k] = ( ( Ipp8u* )&hgh )[k]; } #endif } #if 0 /* vb */ __IPPCP_INLINE void ompStdIncrement192( void* pInitCtrVal, void* pCurrCtrVal, int ctrNumBitSize, int n ) { int k; Ipp64u low; Ipp64u mdl; Ipp64u hgh; Ipp64u flag; Ipp64u mask = CONST_64(0xFFFFFFFFFFFFFFFF); Ipp64u save; #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )&low )[k] = ( ( Ipp8u* )pInitCtrVal )[23 - k]; ( ( Ipp8u* )&mdl )[k] = ( ( Ipp8u* )pInitCtrVal )[15 - k]; ( ( Ipp8u* )&hgh )[k] = ( ( Ipp8u* )pInitCtrVal )[7 - k]; } #else for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )&low )[k] = ( ( Ipp8u* )pInitCtrVal )[16 + k]; ( ( Ipp8u* )&mdl )[k] = ( ( Ipp8u* )pInitCtrVal )[8 + k]; ( ( Ipp8u* )&hgh )[k] = ( ( Ipp8u* )pInitCtrVal )[k]; } #endif if( ctrNumBitSize == 64 ) { low += ( Ipp64u )n; } else if( ctrNumBitSize == 128 ) { flag = ( low >> 63 ); low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) mdl++; } else if( ctrNumBitSize == 192 ) { flag = ( low >> 63 ); low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) { flag = ( mdl >> 63 ); mdl++; if( flag != ( mdl >> 63 ) ) hgh++; } } else if( ctrNumBitSize < 64 ) { Ipp64u bndr; Ipp64u cntr; Ipp64s item; mask >>= ( 64 - ctrNumBitSize ); save = low & ( ~mask ); cntr = ( low & mask ) + ( Ipp64u )n; if( ctrNumBitSize < 31 ) { bndr = ( Ipp64u )1 << ctrNumBitSize; if( cntr > bndr ) { item = ( Ipp64s )( ( Ipp64s )n - ( ( Ipp64s )bndr - ( Ipp64s )( low & mask ) ) ); while( item > 0 ) { cntr = ( Ipp64u )item; item -= ( Ipp64s )bndr; } } } low = save | ( cntr & mask ); } else if( ctrNumBitSize < 128 ) { flag = ( low >> 63 ); mask >>= ( 128 - ctrNumBitSize ); save = mdl & ( ~mask ); mdl &= mask; low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) mdl++; mdl = save | ( mdl & mask ); } else { flag = ( low >> 63 ); mask >>= ( 192 - ctrNumBitSize ); save = hgh & ( ~mask ); hgh &= mask; low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) { flag = ( mdl >> 63 ); mdl++; if( flag != ( mdl >> 63 ) ) hgh++; } hgh = save | ( hgh & mask ); } #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )pCurrCtrVal )[23 - k] = ( ( Ipp8u* )&low )[k]; ( ( Ipp8u* )pCurrCtrVal )[15 - k] = ( ( Ipp8u* )&mdl )[k]; ( ( Ipp8u* )pCurrCtrVal )[7 - k] = ( ( Ipp8u* )&hgh )[k]; } #else for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )pCurrCtrVal )[16 + k] = ( ( Ipp8u* )&low )[k]; ( ( Ipp8u* )pCurrCtrVal )[8 + k] = ( ( Ipp8u* )&mdl )[k]; ( ( Ipp8u* )pCurrCtrVal )[k] = ( ( Ipp8u* )&hgh )[k]; } #endif } #endif #if 0 /* vb */ __IPPCP_INLINE void ompStdIncrement256( void* pInitCtrVal, void* pCurrCtrVal, int ctrNumBitSize, int n ) { int k; Ipp64u low; Ipp64u mdl; Ipp64u mdm; Ipp64u hgh; Ipp64u flag; Ipp64u mask = CONST_64(0xFFFFFFFFFFFFFFFF); Ipp64u save; #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )&low )[k] = ( ( Ipp8u* )pInitCtrVal )[31 - k]; ( ( Ipp8u* )&mdl )[k] = ( ( Ipp8u* )pInitCtrVal )[23 - k]; ( ( Ipp8u* )&mdm )[k] = ( ( Ipp8u* )pInitCtrVal )[15 - k]; ( ( Ipp8u* )&hgh )[k] = ( ( Ipp8u* )pInitCtrVal )[7 - k]; } #else for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )&low )[k] = ( ( Ipp8u* )pInitCtrVal )[24 + k]; ( ( Ipp8u* )&mdl )[k] = ( ( Ipp8u* )pInitCtrVal )[16 + k]; ( ( Ipp8u* )&mdm )[k] = ( ( Ipp8u* )pInitCtrVal )[8 + k]; ( ( Ipp8u* )&hgh )[k] = ( ( Ipp8u* )pInitCtrVal )[k]; } #endif if( ctrNumBitSize == 64 ) { low += ( Ipp64u )n; } else if( ctrNumBitSize == 128 ) { flag = ( low >> 63 ); low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) mdl++; } else if( ctrNumBitSize == 192 ) { flag = ( low >> 63 ); low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) { flag = ( mdl >> 63 ); mdl++; if( flag != ( mdl >> 63 ) ) hgh++; } } else if( ctrNumBitSize == 256 ) { flag = ( low >> 63 ); low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) { flag = ( mdl >> 63 ); mdl++; if( flag != ( mdl >> 63 ) ) { flag = ( mdm >> 63 ); mdm++; if( flag != ( mdm >> 63 ) ) hgh++; } } } else if( ctrNumBitSize < 64 ) { Ipp64u bndr; Ipp64u cntr; Ipp64s item; mask >>= ( 64 - ctrNumBitSize ); save = low & ( ~mask ); cntr = ( low & mask ) + ( Ipp64u )n; if( ctrNumBitSize < 31 ) { bndr = ( Ipp64u )1 << ctrNumBitSize; if( cntr > bndr ) { item = ( Ipp64s )( ( Ipp64s )n - ( ( Ipp64s )bndr - ( Ipp64s )( low & mask ) ) ); while( item > 0 ) { cntr = ( Ipp64u )item; item -= ( Ipp64s )bndr; } } } low = save | ( cntr & mask ); } else if( ctrNumBitSize < 128 ) { flag = ( low >> 63 ); mask >>= ( 128 - ctrNumBitSize ); save = mdl & ( ~mask ); mdl &= mask; low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) mdl++; mdl = save | ( mdl & mask ); } else if( ctrNumBitSize < 192 ) { flag = ( low >> 63 ); mask >>= ( 192 - ctrNumBitSize ); save = mdm & ( ~mask ); mdm &= mask; low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) { flag = ( mdl >> 63 ); mdl++; if( flag != ( mdl >> 63 ) ) mdm++; } mdm = save | ( mdm & mask ); } else { flag = ( low >> 63 ); mask >>= ( 256 - ctrNumBitSize ); save = hgh & ( ~mask ); hgh &= mask; low += ( Ipp64u )n; if( flag != ( low >> 63 ) ) { flag = ( mdl >> 63 ); mdl++; if( flag != ( mdl >> 63 ) ) { flag = ( mdm >> 63 ); mdm++; if( flag != ( mdm >> 63 ) ) hgh++; } } hgh = save | ( hgh & mask ); } #if( IPP_ENDIAN == IPP_LITTLE_ENDIAN ) for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )pCurrCtrVal )[31 - k] = ( ( Ipp8u* )&low )[k]; ( ( Ipp8u* )pCurrCtrVal )[23 - k] = ( ( Ipp8u* )&mdl )[k]; ( ( Ipp8u* )pCurrCtrVal )[15 - k] = ( ( Ipp8u* )&mdm )[k]; ( ( Ipp8u* )pCurrCtrVal )[7 - k] = ( ( Ipp8u* )&hgh )[k]; } #else for( k = 0; k < 8; k++ ) { ( ( Ipp8u* )pCurrCtrVal )[24 + k] = ( ( Ipp8u* )&low )[k]; ( ( Ipp8u* )pCurrCtrVal )[16 + k] = ( ( Ipp8u* )&mdl )[k]; ( ( Ipp8u* )pCurrCtrVal )[8 + k] = ( ( Ipp8u* )&mdm )[k]; ( ( Ipp8u* )pCurrCtrVal )[k] = ( ( Ipp8u* )&hgh )[k]; } #endif } #endif #endif /* _CP_TOOL_H */ cryptography-primitives-1.0.0/sources/ippcp/pcptrngenhwca.c000066400000000000000000000126371470420105600242510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2015 Intel Corporation * * 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. *************************************************************************/ /* // // Purpose: // Cryptography Primitive. // TRNG Functions // // Contents: // ippsTRNGenHW() // ippsTRNGenHW_BN() // // */ #include "owndefs.h" #include "owncp.h" #include "pcpbn.h" #include "pcptool.h" #if ((_IPP>=_IPP_G9) || (_IPP32E>=_IPP32E_E9)) static int cpSeed_hw_sample(BNU_CHUNK_T* pSample) { #define LOCAL_COUNTER (320) /* this constant has been tuned manually */ int n; int success = 0; for(n=0; n=_IPP32E_E9) static int cpSeed_hw_sample32(Ipp32u* pSample) { #define LOCAL_COUNTER (320) /* this constant has been tuned manually */ int n; int success = 0; for(n=0; n=_IPP32E_E9) if( bufLen%((Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u))) ) { if( !cpSeed_hw_sample32(pRand)) { return 0; } } #endif return 1; } #endif /*F* // Name: ippsTRNGenRDSEED // // Purpose: Generates a true random bit sequence // based on Intel® instruction RDSEED of the specified nBits length. // // Returns: Reason: // ippStsNullPtrErr NULL == pRand // // ippStsLengthErr 1 > nBits // // ippStsNotSupportedModeErr unsupported rdrand instruction // // ippStsErr random bit sequence can't be generated // // ippStsNoErr no error // // Parameters: // pRand pointer to the buffer // nBits number of bits be requested // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsTRNGenRDSEED,(Ipp32u* pRand, int nBits, void* pCtx)) { /* test PRNG buffer */ IPP_BAD_PTR1_RET(pRand); /* test sizes */ IPP_BADARG_RET(nBits< 1, ippStsLengthErr); IPP_UNREFERENCED_PARAMETER(pCtx); #if ((_IPP>=_IPP_G9) || (_IPP32E>=_IPP32E_E9)) if( IsFeatureEnabled(ippCPUID_RDSEED) ) { cpSize rndSize = BITS2WORD32_SIZE(nBits); Ipp32u rndMask = MAKEMASK32(nBits); if(cpSeedHW_buffer(pRand, rndSize)) { pRand[rndSize-1] &= rndMask; return ippStsNoErr; } else return ippStsErr; } /* unsupported rdrand instruction */ else #endif IPP_ERROR_RET(ippStsNotSupportedModeErr); } /*F* // Name: ippsTRNGenRDSEED_BN // // Purpose: Generates a true random big number // based on Intel® instruction RDSEED of the specified nBits length. // // Returns: Reason: // ippStsNullPtrErr NULL == pRand // // ippStsLengthErr 1 > nBits // nBits > BN_ROOM(pRand) // // ippStsNotSupportedModeErr unsupported rdrand instruction // // ippStsErr random big number can't be generated // // ippStsNoErr no error // // Parameters: // pRand pointer to the big number // nBits number of bits be requested // pCtx pointer to the context *F*/ IPPFUN(IppStatus, ippsTRNGenRDSEED_BN,(IppsBigNumState* pRand, int nBits, void* pCtx)) { /* test random BN */ IPP_BAD_PTR1_RET(pRand); IPP_BADARG_RET(!BN_VALID_ID(pRand), ippStsContextMatchErr); /* test sizes */ IPP_BADARG_RET(nBits< 1, ippStsLengthErr); IPP_BADARG_RET(nBits> BN_ROOM(pRand)*BNU_CHUNK_BITS, ippStsLengthErr); IPP_UNREFERENCED_PARAMETER(pCtx); #if ((_IPP>=_IPP_G9) || (_IPP32E>=_IPP32E_E9)) if( IsFeatureEnabled(ippCPUID_RDSEED) ) { BNU_CHUNK_T* pRandBN = BN_NUMBER(pRand); cpSize rndSize = BITS_BNU_CHUNK(nBits); BNU_CHUNK_T rndMask = MASK_BNU_CHUNK(nBits); if(cpSeedHW_buffer((Ipp32u*)pRandBN, rndSize*(Ipp32s)(sizeof(BNU_CHUNK_T)/sizeof(Ipp32u)))) { pRandBN[rndSize-1] &= rndMask; FIX_BNU(pRandBN, rndSize); BN_SIZE(pRand) = rndSize; BN_SIGN(pRand) = ippBigNumPOS; return ippStsNoErr; } else return ippStsErr; } /* unsupported rdrand instruction */ else #endif IPP_ERROR_RET(ippStsNotSupportedModeErr); } cryptography-primitives-1.0.0/sources/ippcp/pcpvariant.h000066400000000000000000000267311470420105600235620ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2005 Intel Corporation * * 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. *************************************************************************/ /* // // Intel(R) Cryptography Primitives Library // // Purpose: // Define ippCP variant // // */ #if !defined(_CP_VARIANT_H) #define _CP_VARIANT_H /* // set _AES_NI_ENABLING_ */ #if defined _IPP_AES_NI_ #if (_IPP_AES_NI_ == 0) #define _AES_NI_ENABLING_ _FEATURE_OFF_ #elif (_IPP_AES_NI_ == 1) #define _AES_NI_ENABLING_ _FEATURE_ON_ #else #error Define _IPP_AES_NI_=0 or 1 or omit _IPP_AES_NI_ at all #endif #else #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #define _AES_NI_ENABLING_ _FEATURE_TICKTOCK_ #else #define _AES_NI_ENABLING_ _FEATURE_OFF_ #endif #endif /* // select AES safe implementation */ #define _ALG_AES_SAFE_COMPACT_SBOX_ (1) #define _ALG_AES_SAFE_COMPOSITE_GF_ (2) #if (_AES_NI_ENABLING_==_FEATURE_ON_) #define _ALG_AES_SAFE_ _FEATURE_OFF_ #else #if (_IPP>=_IPP_V8) || (_IPP32E>=_IPP32E_U8) #define _ALG_AES_SAFE_ _ALG_AES_SAFE_COMPOSITE_GF_ #else #define _ALG_AES_SAFE_ _ALG_AES_SAFE_COMPACT_SBOX_ //#define _ALG_AES_SAFE_ _ALG_AES_SAFE_COMPOSITE_GF_ #endif #endif /* // AES Noise // Enable mitigation when dispatching available to // Intel® Advanced Encryption Standard New Instructions (Intel® AES-NI) - _AES_NI_ENABLING_ != _FEATURE_OFF_ // or vector extensions of Intel® AES-NI - _IPP32E >=_IPP32E_K1 */ #ifndef IPP_AES_PROB_NOISE #define IPP_AES_PROB_NOISE _FEATURE_ON_ #endif #if (IPP_AES_PROB_NOISE == _FEATURE_ON_) #if ((_AES_NI_ENABLING_ != _FEATURE_OFF_) || (_IPP32E >=_IPP32E_K1)) #define _AES_PROB_NOISE _FEATURE_ON_ #else #define _AES_PROB_NOISE _FEATURE_OFF_ #endif #else #define _AES_PROB_NOISE _FEATURE_OFF_ #endif /* // if there is no outside assignment // set _SHA_NI_ENABLING_ based on CPU specification */ #if !defined(_SHA_NI_ENABLING_) #if (_IPP>=_IPP_P8) || (_IPP32E>=_IPP32E_Y8) #define _SHA_NI_ENABLING_ _FEATURE_TICKTOCK_ #else #define _SHA_NI_ENABLING_ _FEATURE_OFF_ #endif #endif /* // set/reset _ADCOX_NI_ENABLING_ */ #if (_IPP32E>=_IPP32E_L9) #if !defined(_ADCOX_NI_ENABLING_) #define _ADCOX_NI_ENABLING_ _FEATURE_TICKTOCK_ #endif #else #undef _ADCOX_NI_ENABLING_ #define _ADCOX_NI_ENABLING_ _FEATURE_OFF_ #endif /* // Intel(R) Cryptography Primitives Library supports several hash algorithms by default: // SHA-1 // SHA-256 // SHA-224 (or SHA256/224 by the FIPS180-4 classification) // SHA-512 // SHA-384 (or SHA512/384 by the FIPS180-4 classification) // MD5 // SM3 // // By default all hash algorithms are included in Intel(R) Cryptography Primitives Library. // // If one need excludes code of particular hash, just define // suitable _DISABLE_ALG_XXX, where XXX name of the hash algorithm // */ #if !defined(_DISABLE_ALG_SHA1_) #define _ENABLE_ALG_SHA1_ /* SHA1 on */ #else # undef _ENABLE_ALG_SHA1_ /* SHA1 off */ #endif #if !defined(_DISABLE_ALG_SHA256_) # define _ENABLE_ALG_SHA256_ /* SHA256 on */ #else # undef _ENABLE_ALG_SHA256_ /* SHA256 off */ #endif #if !defined(_DISABLE_ALG_SHA224_) # define _ENABLE_ALG_SHA224_ /* SHA224 on */ #else # undef _ENABLE_ALG_SHA224_ /* SHA224 off */ #endif #if !defined(_DISABLE_ALG_SHA512_) # define _ENABLE_ALG_SHA512_ /* SHA512 on */ #else # undef _ENABLE_ALG_SHA512_ /* SHA512 off */ #endif #if !defined(_DISABLE_ALG_SHA384_) # define _ENABLE_ALG_SHA384_ /* SHA384 on */ #else # undef _ENABLE_ALG_SHA384_ /* SHA384 off */ #endif #if !defined(_DISABLE_ALG_SHA512_224_) # define _ENABLE_ALG_SHA512_224_ /* SHA512/224 on */ #else # undef _ENABLE_ALG_SHA512_224_ /* SHA512/224 off */ #endif #if !defined(_DISABLE_ALG_SHA512_256_) # define _ENABLE_ALG_SHA512_256_ /* SHA512/256 on */ #else # undef _ENABLE_ALG_SHA512_256_ /* SHA512/256 off */ #endif #if !defined(_DISABLE_ALG_MD5_) # define _ENABLE_ALG_MD5_ /* MD5 on */ #else # undef _ENABLE_ALG_MD5_ /* MD5 off */ #endif #if !defined(_DISABLE_ALG_SM3_) # define _ENABLE_ALG_SM3_ /* SM3 on */ #else # undef _ENABLE_ALG_SM3_ /* SM3 off */ #endif /* // SHA1 plays especial role in Intel(R) Cryptography Primitives Library. // Thus Intel(R) Cryptography Primitives Library random generator and // therefore prime number generator are based on SHA1. // So, do no exclude SHA1 from the active list of hash algorithms */ #if defined(_DISABLE_ALG_SHA1_) #undef _DISABLE_ALG_SHA1_ #endif /* // Because of performance reason hash algorithms are implemented in form // of unroller cycle and therefore these implementations are big enough. // Intel(R) Cryptography Primitives Library supports "compact" implementation // of some basic hash algorithms: // SHA-1 // SHA-256 // SHA-512 // SM3 // // Define any // _ALG_SHA1_COMPACT_ // _ALG_SHA256_COMPACT_ // _ALG_SHA512_COMPACT_ // _ALG_SM3_COMPACT_ // // to select "compact" implementation of particular hash algorithm. // Intel Intel(R) Cryptography Primitives Library does not define "compact" implementation by default. // // Don't know what performance degradation leads "compact" // in comparison with default Intel(R) Cryptography Primitives Library implementation. // // Note: the definition like _ALG_XXX_COMPACT_ has effect // if and only if Intel(R) Cryptography Primitives Library instance is _PX or _MX */ //#define _ALG_SHA1_COMPACT_ //#define _ALG_SHA256_COMPACT_ //#define _ALG_SHA512_COMPACT_ //#define _ALG_SM3_COMPACT_ //#undef _ALG_SHA1_COMPACT_ //#undef _ALG_SHA256_COMPACT_ //#undef _ALG_SHA512_COMPACT_ //#undef _ALG_SM3_COMPACT_ /* // BN arithmetic: // - do/don't use special implementation of sqr instead of usual multication // - do/don't use Karatsuba multiplication alg */ #define _USE_SQR_ /* use implementation of sqr */ #if !defined(_DISABLE_WINDOW_EXP_) #define _USE_WINDOW_EXP_ /* use fixed window exponentiation */ #endif /* // RSA: // - do/don't use version 1 style mitigation of CBA // - do/don't use own style mitigation of CBA // - do/don't use Folding technique for RSA-1204 implementation */ #define xUSE_VERSION1_CBA_MITIGATION_ /* not use (version 1) mitigation of CBA */ #define _USE_IPP_OWN_CBA_MITIGATION_ /* use (own) mitigation of CBA */ #define xUSE_FOLD_MONT512_ /* use folding technique in RSA-1024 case */ /* // Intel(R) Cryptography Primitives Library supports different implementation of NIST's (standard) EC over GF(0): // P-128 (IppECCPStd128r1, IppECCPStd128r2) // P-192 (IppECCPStd192r1) // P-224 (IppECCPStd224r1) // P-256 (IppECCPStd256r1) // P-384 (IppECCPStd384r1) // P-521 (IppECCPStd521r1) // // If one need replace the particular implementation by arbitrary one // assign _ECP_IMP_ARBIRTRARY_ to suitable symbol // // _ECP_IMPL_ARBIRTRARY_ means that implementation does not use any curve specific, // provide the same (single) code for any type curve // // _ECP_IMPL_SPECIFIC_ means that implementation uses specific modular reduction // based on prime structure; // most of NIST's cures (p128, p192, p224, p256, p384, p521) are uses // such kind of reduction procedure; // in contrast with _ECP_IMPL_ARBIRTRARY_ and _ECP_IMPL_MFM_ // this type of implementation uses point representation in REGULAR residual // (not Montgometry!!) domain // // _ECP_IMPL_MFM_ means that implementation uses "Montgomary Friendly Modulus" (primes); // p256 and sm2 are using such kind of optimization */ #define _ECP_IMPL_NONE_ 0 #define _ECP_IMPL_ARBIRTRARY_ 1 #define _ECP_IMPL_SPECIFIC_ 2 #define _ECP_IMPL_MFM_ 3 #if !defined(_ECP_112R1_) #if !defined(_DISABLE_ECP_112R1_) # define _ECP_112R1_ _ECP_IMPL_ARBIRTRARY_ #else # define _ECP_112R1_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_112R2_) #if !defined(_DISABLE_ECP_112R2_) # define _ECP_112R2_ _ECP_IMPL_ARBIRTRARY_ #else # define _ECP_112R2_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_160R1_) #if !defined(_DISABLE_ECP_160R1_) # define _ECP_160R1_ _ECP_IMPL_ARBIRTRARY_ #else # define _ECP_160R1_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_160R2_) #if !defined(_DISABLE_ECP_160R2_) # define _ECP_160R2_ _ECP_IMPL_ARBIRTRARY_ #else # define _ECP_160R2_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_128R1_) #if !defined(_DISABLE_ECP_128R1_) # define _ECP_128R1_ _ECP_IMPL_SPECIFIC_ #else # define _ECP_128R1_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_128R2_) #if !defined(_DISABLE_ECP_128R2_) # define _ECP_128R2_ _ECP_IMPL_SPECIFIC_ #else # define _ECP_128R2_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_192_) #if !defined(_DISABLE_ECP_192_) # if (_IPP32E >= _IPP32E_M7) || (_IPP >= _IPP_P8) # define _ECP_192_ _ECP_IMPL_MFM_ # else # define _ECP_192_ _ECP_IMPL_SPECIFIC_ # endif #else # define _ECP_192_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_224_) #if !defined(_DISABLE_ECP_224_) # if (_IPP32E >= _IPP32E_M7) || (_IPP >= _IPP_P8) # define _ECP_224_ _ECP_IMPL_MFM_ # else # define _ECP_224_ _ECP_IMPL_SPECIFIC_ # endif #else # define _ECP_224_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_256_) #if !defined(_DISABLE_ECP_256_) # if (_IPP32E >= _IPP32E_M7) || (_IPP >= _IPP_P8) # define _ECP_256_ _ECP_IMPL_MFM_ # else # define _ECP_256_ _ECP_IMPL_SPECIFIC_ # endif #else # define _ECP_256_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_384_) #if !defined(_DISABLE_ECP_384_) # if (_IPP32E >= _IPP32E_M7) || (_IPP >= _IPP_P8) # define _ECP_384_ _ECP_IMPL_MFM_ # else # define _ECP_384_ _ECP_IMPL_SPECIFIC_ # endif #else # define _ECP_384_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_521_) #if !defined(_DISABLE_ECP_521_) # if (_IPP32E >= _IPP32E_M7) || (_IPP >= _IPP_P8) # define _ECP_521_ _ECP_IMPL_MFM_ # else # define _ECP_521_ _ECP_IMPL_SPECIFIC_ # endif #else # define _ECP_521_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_SM2_) #if !defined(_DISABLE_ECP_SM2_) # if (_IPP32E >= _IPP32E_M7) || (_IPP >= _IPP_P8) # define _ECP_SM2_ _ECP_IMPL_MFM_ # else # define _ECP_SM2_ _ECP_IMPL_SPECIFIC_ # endif #else # define _ECP_SM2_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_ECP_BN_) #if !defined(_DISABLE_ECP_BN_) # define _ECP_BN_ _ECP_IMPL_ARBIRTRARY_ #else # define _ECP_BN_ _ECP_IMPL_NONE_ #endif #endif #if !defined(_DISABLE_ECP_GENERAL_) # define _ECP_GENERAL_ _ECP_IMPL_ARBIRTRARY_ #else # define _ECP_GENERAL_ _ECP_IMPL_NONE_ #endif /* // EC over GF(p): // - do/don't use mitigation of CBA */ #define _USE_ECCP_SSCM_ /* use SSCM ECCP */ #endif /* _CP_VARIANT_H */ cryptography-primitives-1.0.0/sources/ippcp/pcpver.c000066400000000000000000000123441470420105600227000ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // */ #include "owndefs.h" #include "ippcpdefs.h" #include "owncp.h" #include "pcpver.h" #include "pcpname.h" #if ( _IPP_ARCH == _IPP_ARCH_IA32 ) || ( _IPP_ARCH == _IPP_ARCH_LP32 ) #if ( _IPP == _IPP_M5 ) /* Intel® Quark(TM) processor - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "m5" #define CRYPTO_LIB_CPU_DESCR() "586" #elif ( _IPP == _IPP_H9 ) /* Intel® Advanced Vector Extensions 2 - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "h9" #define CRYPTO_LIB_CPU_DESCR() "AVX2" #elif ( _IPP == _IPP_G9 ) /* Intel® Advanced Vector Extensions - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "g9" #define CRYPTO_LIB_CPU_DESCR() "AVX" #elif ( _IPP == _IPP_P8 ) /* Intel® Streaming SIMD Extensions 4.2 (Intel® SSE4.2) - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "p8" #define CRYPTO_LIB_CPU_DESCR() "SSE4.2" #elif ( _IPP == _IPP_S8 ) /* Supplemental Streaming SIMD Extensions 3 + Intel® instruction MOVBE - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "s8" #define CRYPTO_LIB_CPU_DESCR() "Atom" #elif ( _IPP == _IPP_V8 ) /* Supplemental Streaming SIMD Extensions 3 - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "v8" #define CRYPTO_LIB_CPU_DESCR() "SSSE3" #elif ( _IPP == _IPP_W7 ) /* Intel® Streaming SIMD Extensions 2 - ia32 */ #define CRYPTO_LIB_CPU_TYPE() "w7" #define CRYPTO_LIB_CPU_DESCR() "SSE2" #else #define CRYPTO_LIB_CPU_TYPE() "px" #define CRYPTO_LIB_CPU_DESCR() "PX" #endif #elif ( _IPP_ARCH == _IPP_ARCH_EM64T ) || ( _IPP_ARCH == _IPP_ARCH_LP64 ) #if ( _IPP32E == _IPP32E_K1 ) /* Intel® Advanced Vector Extensions 512 (formerly Icelake) - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "k1" #define CRYPTO_LIB_CPU_DESCR() "AVX-512F/CD/BW/DQ/VL/SHA/VBMI/VBMI2/IFMA/GFNI/VAES/VCLMUL" #elif ( _IPP32E == _IPP32E_K0 ) /* Intel® Advanced Vector Extensions 512 (formerly Skylake) - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "k0" #define CRYPTO_LIB_CPU_DESCR() "AVX-512F/CD/BW/DQ/VL" #elif ( _IPP32E == _IPP32E_E9 ) /* Intel® Advanced Vector Extensions - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "e9" #define CRYPTO_LIB_CPU_DESCR() "AVX" #elif ( _IPP32E == _IPP32E_L9 ) /* Intel® Advanced Vector Extensions 2 - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "l9" #define CRYPTO_LIB_CPU_DESCR() "AVX2" #elif ( _IPP32E == _IPP32E_Y8 ) /* Intel® Streaming SIMD Extensions 4.2 - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "y8" #define CRYPTO_LIB_CPU_DESCR() "SSE4.2" #elif ( _IPP32E == _IPP32E_N8 ) /* Supplemental Streaming SIMD Extensions 3 + Intel® instruction MOVBE - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "n8" #define CRYPTO_LIB_CPU_DESCR() "Atom" #elif ( _IPP32E == _IPP32E_U8 ) /* Supplemental Streaming SIMD Extensions 3 - intel64 */ #define CRYPTO_LIB_CPU_TYPE() "u8" #define CRYPTO_LIB_CPU_DESCR() "SSSE3" #elif ( _IPP32E == _IPP32E_M7 ) /* Intel® Streaming SIMD Extensions 3 (Intel® SSE3) */ #define CRYPTO_LIB_CPU_TYPE() "m7" #define CRYPTO_LIB_CPU_DESCR() "SSE3" #else #define CRYPTO_LIB_CPU_TYPE() "mx" #define CRYPTO_LIB_CPU_DESCR() "PX" #endif #endif #define GET_LIBRARY_NAME() CRYPTO_LIB_NAME() " (" CRYPTO_LIB_CPU_TYPE() ")" \ " (ver: " STR_VERSION() \ " build: " __DATE__ ")" static const CryptoLibraryVersion cryptoLibVer = { /* major, minor, patch (ex-majorBuild) */ BASE_VERSION(), /* targetCpu[4] */ CRYPTO_LIB_CPU_TYPE(), CRYPTO_LIB_NAME() " (" CRYPTO_LIB_CPU_TYPE() ")", __DATE__, //BuildDate GET_LIBRARY_NAME() /* release Version */ }; IPPFUN( const CryptoLibraryVersion*, cryptoGetLibVersion, ( void )){ return &cryptoLibVer; }; /* Deprecated functionality*/ static const IppLibraryVersion ippcpLibVer = { /* major, minor, update (ex-majorBuild) */ BASE_VERSION(), #if defined IPP_REVISION IPP_REVISION, #else 0, #endif /* IPP_REVISION */ CRYPTO_LIB_CPU_TYPE(), "ippCP " CRYPTO_LIB_CPU_DESCR() " (" CRYPTO_LIB_CPU_TYPE() ")", STR_VERSION(), /* release Version */ __DATE__ //BuildDate }; IPPFUN( const IppLibraryVersion*, ippcpGetLibVersion, ( void )){ return &ippcpLibVer; }; /*////////////////////////// End of file "pcpver.c" ////////////////////////// */ cryptography-primitives-1.0.0/sources/ippcp/pcpver.h000066400000000000000000000021101470420105600226730ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // Intel(R) Cryptography Primitives Library // // Purpose: Describes the version of ippCP // */ #include "ippver.h" #define BUILD() 1043 #define VERSION() BASE_VERSION(),BUILD() #define STR_FILE_VERSION() STR_BASE_VERSION() "," STR(BUILD()) /* ////////////////////////// End of file "pcpver.h" ///////////////////////// */ cryptography-primitives-1.0.0/sources/ippcp/pcpver.rc000066400000000000000000000016661470420105600230670ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2002 Intel Corporation * * 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. *************************************************************************/ /* // // Created: Tue Feb 5 17:02:02 2002 // */ #include "pcpver.h" #include "pcpname.h" #include "ippres.gen" /* ////////////////////////////// End of file /////////////////////////////// */ cryptography-primitives-1.0.0/sources/ippcp/xmss/000077500000000000000000000000001470420105600222235ustar00rootroot00000000000000cryptography-primitives-1.0.0/sources/ippcp/xmss/wots_internal.c000066400000000000000000000174041470420105600252650ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 "owndefs.h" #include "owncp.h" #include "xmss_internal/wots.h" /* * A byte string can be considered as a string of base w numbers, i.e., * integers in the set {0, ... , w - 1}. The correspondence is defined * by the function base_w as follows. If X * is a byte string, and w is a member of the set {4, 16}, then * the function outputs an array of out_len integers between 0 and w - 1. * * Input parameters: * X byte string * out_len length of basew. It is REQUIRED to be less than or equal * to 8 * len_X / lg(w) * params WOTS parameters (w, log2_w, n, len, len_1, hash_method) * * Output parameters: * basew resulted out_len-byte array */ IPP_OWN_DEFN(void, base_w, (const Ipp8u* X, Ipp32s out_len, Ipp8u* basew, cpWOTSParams* params)) { Ipp32s in = 0; Ipp32s out = 0; Ipp32u total = 0; Ipp32s bits = 0; for (Ipp32s consumed = 0; consumed < out_len; consumed++) { if (bits == 0) { total = X[in]; in++; bits += /*bit size of 1 byte*/ 8; } bits -= params->log2_w; basew[out] = (Ipp8u) ((total >> bits) & (params->w - 1)); out++; } } /* * Generates pseudorandom output of length n from an n-byte key and a 32-byte index * using hash functions as follows * Hash(toByte(padding_id, n) || key || msg) * * Returns: * result of ippsHashMessage_rmf * * Input parameters: * padding_id 32-byte value that is used as a padding value for a hash function * key n-byte key for the hash function * msg byte array * msgLen length of msg * temp_buf temporary memory (size is 3 * n bytes at least) * params WOTS parameters (w, log2_w, n, len, len_1, hash_method) * * Output parameters: * out resulted n-byte array */ IPP_OWN_DEFN(IppStatus, do_xmss_hash, (Ipp32u padding_id, const Ipp8u* key, const Ipp8u* msg, Ipp32s msgLen, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) { toByte(temp_buf, params->n, padding_id); CopyBlock(key, temp_buf + params->n, params->n); CopyBlock(msg, temp_buf + 2 * params->n, msgLen); return ippsHashMessage_rmf(temp_buf, 2 * params->n + msgLen, out, params->hash_method); } /* * Generates pseudorandom output of length n from an n-byte key and a 32-byte index * using hash functions as follows * Hash(toByte(3, n) || key || msg) * * Input parameters: * padding_id 32-byte value that is used as a padding value for a hash function * key n-byte key for the hash function * msg 32-byte array * temp_buf temporary memory (size is 3 * n bytes at least) * params WOTS parameters (w, log2_w, n, len, len_1, hash_method) * * Output parameters: * out resulted n-byte array */ IPP_OWN_DEFN(IppStatus, prf, (const Ipp8u* key, const Ipp8u* msg, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) { return do_xmss_hash(/*prf function padding id*/ 3, key, msg, /*bit size of index*/32, out, temp_buf, params); } /* * Computes an iteration of F on an n-byte X using outputs of PRF. It takes an * OTS hash address (adrs) as input. This address will have the first six * 32-bit words set to encode the address of this chain. In each iteration, PRF * is used to generate a key for F and a bitmask that is XORed to the * intermediate result before it is processed by F. In the following, pSeed is an * n-byte string. To generate the keys and bitmasks, PRF is called with * pSeed as key and adrs as input. The chaining function also takes as input * a start index i, a number of steps s. The chaining function returns as output the array * obtained by iterating F for s times on input X, using the outputs of PRF.) * * temp_buf size is 4 * n bytes at least. */ IPP_OWN_DEFN(IppStatus, chain, (Ipp8u* X, Ipp8u i, Ipp8u s, Ipp8u* pSeed, Ipp8u* adrs, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) { IppStatus retCode = ippStsNoErr; Ipp8u* bm = temp_buf; Ipp8u* key = bm; CopyBlock(X, out, params->n); for (Ipp8u k = i; k < (i + s) && k < params->w; k++) { adrs[set_adrs_1_byte(6)] = /*hash address*/ k; // BM = PRF(SEED, ADRS); adrs[set_adrs_1_byte(7)] = /*bitmask for bm*/ 1; retCode = prf(pSeed, adrs, bm, temp_buf + params->n, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) // out = out ^ BM; for (Ipp32s j = 0; j < params->n; ++j) { out[j] = out[j] ^ bm[j]; } // KEY = PRF(SEED, ADRS); adrs[set_adrs_1_byte(7)] = /*bitmask for key*/ 0; retCode = prf(pSeed, adrs, key, temp_buf + params->n, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) // tmp = F(KEY, out); retCode = do_xmss_hash(/*F function padding id*/ 0, key, out, params->n, out, temp_buf + params->n, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) } return retCode; } /* * In order to verify a signature sig on a message M, the verifier * computes a WOTS+ public key value from the signature. This can be * done by "completing" the chain computations starting from the * signature values, using the base params->w values of the message hash and its * checksum. An OTS hash address adrs and a seed pSeed have to be provided by the calling * algorithm. This address will encode the address of the WOTS+ key * pair within a greater structure. Hence, a WOTS+ algorithm MUST NOT * manipulate any parts of adrs except for the last three 32-bit words. * Please note that the pSeed used here is public information also * available to a verifier. * * temp_buf size is (2 * params->len - params->len_1 + 4 * n) bytes at least. * * Output parameters: * out resulted len * n bytes array that contains WOTS+ public key * */ IPP_OWN_DEFN(IppStatus, WOTS_pkFromSig, (const Ipp8u* M, Ipp8u* sig, Ipp8u* pSeed, Ipp8u* adrs, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)) { IppStatus retCode = ippStsNoErr; // Convert message to base w Ipp32s len_2 = params->len - params->len_1; Ipp8u* msg = temp_buf; base_w(M, params->len_1, msg, params); // Compute checksum Ipp32u csum = 0; for (Ipp32s i = 0; i < params->len_1; i++ ) { csum = csum + params->w - 1 - msg[i]; } // Convert csum to base w csum = csum << (8 - ((len_2 * params->log2_w) & 7)); Ipp32s len_2_bytes = cpCeil( ( len_2 * params->log2_w) / 8.0 ); toByte(msg + params->len, len_2_bytes, csum); base_w(msg + params->len, len_2, msg + params->len_1, params); for (Ipp32s i = 0; i < params->len; i++ ) { adrs[set_adrs_1_byte(5)] = /*chain address*/ (Ipp8u)i; retCode = chain(sig + i * params->n, msg[i], (Ipp8u)(params->w - 1 - msg[i]), pSeed, adrs, out + (i * params->n), temp_buf + (params->len + len_2), params ); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) } // null chain address for next call adrs[set_adrs_1_byte(5)] = 0; return retCode; } cryptography-primitives-1.0.0/sources/ippcp/xmss/xmss_internal.c000066400000000000000000000076451470420105600252710ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 "owndefs.h" #include "xmss_internal/xmss.h" /* * Does the randomized hashing in the tree * * Input parameters: * left left half of the hash function input (n-byte array) * right right half of the hash function input (n-byte array) * seed key for the prf function (n-byte array) * adrs address ADRS of the hash function call * temp_buf temporary memory (size is 6 * n bytes at least) * params WOTS parameters (w, log2_w, n, len, len_1, hash_method) * * Output parameters: * out resulted n-byte array that contains hash */ IPP_OWN_DEFN(IppStatus, rand_hash, (Ipp8u* left, Ipp8u* right, Ipp8u* seed, Ipp8u* adrs, Ipp8u* out, Ipp8u* temp_buf, cpWOTSParams* params)){ IppStatus retCode = ippStsNoErr; Ipp8u* pMsg = temp_buf; Ipp8u* pKey = temp_buf + 2 * params->n; Ipp8u* temp = temp_buf + 3 * params->n; adrs[set_adrs_1_byte(7)] = /*key bitmask*/ 0; retCode = prf(seed, adrs, pKey, temp, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) adrs[set_adrs_1_byte(7)] = /*left bitmask*/ 1; retCode = prf(seed, adrs, pMsg, temp, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) adrs[set_adrs_1_byte(7)] = /*right bitmask*/ 2; retCode = prf(seed, adrs, pMsg + params->n, temp, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) // null adrs adrs[set_adrs_1_byte(7)] = 0; // (LEFT XOR BM_0) || (RIGHT XOR BM_1) for (Ipp32s i = 0; i < params->n; ++i) { pMsg[i] = left[i] ^ pMsg[i]; pMsg[i + params->n] = right[i] ^ pMsg[i + params->n]; } //H(KEY, pMsg); retCode = do_xmss_hash(/*H padding id*/ 1, pKey, pMsg, 2 * params->n, out, temp, params); return retCode; } /* * Compute the leaves of the binary hash tree, a so-called L-tree. * An L-tree is an unbalanced binary hash tree, distinct but * similar to the main XMSS binary hash tree. The function takes as input a * WOTS+ public key pk and compresses it to a single n-byte value pk[0]. * It also takes as input an L-tree address adrs that encodes the address * of the L-tree and seed * * temp_buf size is 6 * n bytes at least. * */ IPP_OWN_DEFN(IppStatus, ltree, (Ipp8u* pk, Ipp8u* seed, Ipp8u* adrs, Ipp8u* temp_buf, cpWOTSParams* params)) { IppStatus retCode = ippStsNoErr; Ipp32s len_ = params->len; Ipp32s n_ = params->n; // tree height is 0 for now adrs[set_adrs_1_byte(5)] = 0; while (len_ > 1) { for (Ipp32s i = 0; i < len_ / 2; i++) { adrs[set_adrs_1_byte(6)] = /*tree index*/ (Ipp8u) i; retCode = rand_hash(pk + (2 * i * n_), pk + ((2 * i * n_) + n_), seed, adrs, pk + (i * n_), temp_buf, params); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) } if ((len_ & 1) == 1) { CopyBlock(pk + (n_ * (len_ - 1)), pk + (n_ * (len_ / 2)), n_); len_ = (len_ >> 1) + 1; } else { len_ = len_ >> 1; } // increase the tree height adrs[set_adrs_1_byte(5)] += 1; } // null tree height and tree index adrs[set_adrs_1_byte(5)] = 0; adrs[set_adrs_1_byte(6)] = 0; return retCode; } cryptography-primitives-1.0.0/sources/ippcp/xmss/xmss_setters_getters.c000066400000000000000000000172551470420105600267010ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 "owndefs.h" #include "xmss_internal/xmss.h" /*F* // Name: ippsXMSSSetPublicKeyState // // Purpose: Set XMSS public key. // // Returns: Reason: // ippStsNullPtrErr pRoot == NULL // pSeed == NULL // pState == NULL // ippStsBadArgErr OIDAlgo > Max value for IppsXMSSAlgo // ippStsBadArgErr OIDAlgo <= 0 // ippStsNoErr no errors // // Parameters: // OIDAlgo id of XMSS set of parameters (algorithm) // pRoot pointer to the XMSS public key root // pSeed pointer to the XMSS public key seed // pState pointer to the XMSS public key state // *F*/ IPPFUN(IppStatus, ippsXMSSSetPublicKeyState,( IppsXMSSAlgo OIDAlgo, const Ipp8u* pRoot, const Ipp8u* pSeed, IppsXMSSPublicKeyState* pState )) { IPP_BAD_PTR1_RET(pRoot); IPP_BAD_PTR1_RET(pSeed); IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(OIDAlgo > 6, ippStsBadArgErr); IPP_BADARG_RET(OIDAlgo <= 0, ippStsBadArgErr); IppStatus status = ippStsNoErr; cpWOTSParams params; Ipp32s h = 0; status = setXMSSParams(OIDAlgo, &h, ¶ms); Ipp32s n = params.n; pState->OIDAlgo = OIDAlgo; Ipp8u* ptr = (Ipp8u*)pState; /* allocate internal contexts */ ptr += sizeof(IppsXMSSPublicKeyState); pState->pRoot = (Ipp8u*)( IPP_ALIGNED_PTR((ptr), (int)sizeof(Ipp8u)) ); CopyBlock(pRoot, pState->pRoot, n); ptr += n; pState->pSeed = (Ipp8u*)( IPP_ALIGNED_PTR((ptr), (int)sizeof(Ipp8u)) ); CopyBlock(pSeed, pState->pSeed, n); return status; } /*F* // Name: ippsXMSSSetSignatureState // // Purpose: Set XMSS signature. // // Returns: Reason: // ippStsNullPtrErr r == NULL // pOTSSign == NULL // pAuthPath == NULL // pState == NULL // ippStsBadArgErr OIDAlgo > Max value for IppsXMSSAlgo // ippStsBadArgErr OIDAlgo <= 0 // ippStsNoErr no errors // // Parameters: // OIDAlgo id of XMSS set of parameters (algorithm) // idx index of XMSS leaf // r pointer to the XMSS signature randomness variable // pOTSSign pointer to the WOTS signature // pAuthPath pointer to the XMSS authorization path // pState pointer to the XMSS signature state // *F*/ IPPFUN(IppStatus, ippsXMSSSetSignatureState,( IppsXMSSAlgo OIDAlgo, Ipp32u idx, const Ipp8u* r, const Ipp8u* pOTSSign, const Ipp8u* pAuthPath, IppsXMSSSignatureState* pState )) { IPP_BAD_PTR1_RET(r); IPP_BAD_PTR1_RET(pOTSSign); IPP_BAD_PTR1_RET(pAuthPath); IPP_BAD_PTR1_RET(pState); IPP_BADARG_RET(OIDAlgo > 6, ippStsBadArgErr); IPP_BADARG_RET(OIDAlgo <= 0, ippStsBadArgErr); IppStatus status = ippStsNoErr; cpWOTSParams params; Ipp32s h = 0; status = setXMSSParams(OIDAlgo, &h, ¶ms); Ipp32s n = params.n; Ipp32s len = params.len; pState->idx = idx; Ipp8u* ptr = (Ipp8u*)pState; /* allocate internal contexts */ ptr += sizeof(IppsXMSSSignatureState); pState->r = (Ipp8u*)( IPP_ALIGNED_PTR((ptr), (int)sizeof(Ipp8u)) ); CopyBlock(r, pState->r, n); ptr += n; pState->pOTSSign = (Ipp8u*)( IPP_ALIGNED_PTR((ptr), (int)sizeof(Ipp8u)) ); CopyBlock(pOTSSign, pState->pOTSSign, len * n); ptr += len * n; pState->pAuthPath = (Ipp8u*)( IPP_ALIGNED_PTR((ptr), (int)sizeof(Ipp8u)) ); CopyBlock(pAuthPath, pState->pAuthPath, h * n); return status; } /*F* // Name: ippsXMSSSignatureStateGetSize // // Purpose: Get the XMSS signature state size (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsBadArgErr OIDAlgo > Max value for IppsXMSSAlgo // ippStsBadArgErr OIDAlgo <= 0 // ippStsNoErr no errors // // Parameters: // pSize pointer to the size // OIDAlgo id of XMSS set of parameters (algorithm) // *F*/ IPPFUN(IppStatus, ippsXMSSSignatureStateGetSize,( Ipp32s* pSize, IppsXMSSAlgo OIDAlgo)) { IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(OIDAlgo > 6, ippStsBadArgErr); IPP_BADARG_RET(OIDAlgo <= 0, ippStsBadArgErr); IppStatus status = ippStsNoErr; cpWOTSParams params; Ipp32s h = 0; status = setXMSSParams(OIDAlgo, &h, ¶ms); Ipp32s n = params.n; Ipp32s len = params.len; *pSize = (Ipp32s)sizeof(IppsXMSSSignatureState) + /*r*/n + /*pOTSSign*/len * n + /*pAuthPath*/h * n; return status; } /*F* // Name: ippsXMSSPublicKeyStateGetSize // // Purpose: Get the XMSS public key state size (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsBadArgErr OIDAlgo > Max value for IppsXMSSAlgo // ippStsBadArgErr OIDAlgo <= 0 // ippStsNoErr no errors // // Parameters: // pSize pointer to the size // OIDAlgo id of XMSS set of parameters (algorithm) // *F*/ IPPFUN(IppStatus, ippsXMSSPublicKeyStateGetSize,( Ipp32s* pSize, IppsXMSSAlgo OIDAlgo)) { IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(OIDAlgo > 6, ippStsBadArgErr); IPP_BADARG_RET(OIDAlgo <= 0, ippStsBadArgErr); IppStatus status = ippStsNoErr; cpWOTSParams params; Ipp32s h = 0; status = setXMSSParams(OIDAlgo, &h, ¶ms); Ipp32s n = params.n; *pSize = (Ipp32s)sizeof(IppsXMSSPublicKeyState) + /*pRoot*/n + /*pSeed*/n; return status; } /*F* // Name: ippsXMSSBufferGetSize // // Purpose: Get the XMSS temporary buffer size (bytes). // // Returns: Reason: // ippStsNullPtrErr pSize == NULL // ippStsBadArgErr OIDAlgo > Max value for IppsXMSSAlgo // ippStsBadArgErr OIDAlgo <= 0 // ippStsLengthErr maxMessageLength < 1 // ippStsLengthErr maxMessageLength > IPP_MAX_32S - (numTempBufs + len) * n // ippStsNoErr no errors // // Parameters: // pSize pointer to the size // maxMessageLength maximum length of the message // OIDAlgo id of XMSS set of parameters (algorithm) // *F*/ IPPFUN(IppStatus, ippsXMSSBufferGetSize,( Ipp32s* pSize, Ipp32s maxMessageLength, IppsXMSSAlgo OIDAlgo)) { IppStatus status = ippStsNoErr; IPP_BAD_PTR1_RET(pSize); IPP_BADARG_RET(OIDAlgo > 6, ippStsBadArgErr); IPP_BADARG_RET(OIDAlgo <= 0, ippStsBadArgErr); IPP_BADARG_RET(maxMessageLength < 1, ippStsLengthErr); /* Set XMSS parameters */ Ipp32s h = 0; cpWOTSParams params; status = setXMSSParams(OIDAlgo, &h, ¶ms); IPP_BADARG_RET((ippStsNoErr != status), status) const Ipp32s numTempBufs = 10; Ipp32s n = params.n; Ipp32s len = params.len; // this restriction is needed to avoid overflow of Ipp32s IPP_BADARG_RET(maxMessageLength > (Ipp32s)(IPP_MAX_32S) - (numTempBufs + len) * n, ippStsLengthErr); *pSize = (numTempBufs + len) * n + maxMessageLength; return status; } cryptography-primitives-1.0.0/sources/ippcp/xmss/xmss_verify.c000066400000000000000000000140631470420105600247510ustar00rootroot00000000000000/************************************************************************* * Copyright (C) 2023 Intel Corporation * * 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 "owndefs.h" #include "xmss_internal/xmss.h" /*F* // Name: ippsXMSSVerify // // Purpose: XMSS signature verification. // // Returns: Reason: // ippStsNullPtrErr pMsg == NULL // pSign == NULL // pIsSignValid == NULL // pKey == NULL // pBuffer == NULL // ippStsLengthErr msgLen < 1 // ippStsLengthErr msgLen > IPP_MAX_32S - (numTempBufs + len) * n // ippStsNoErr no errors // // Parameters: // pMsg pointer to the message data buffer // msgLen message buffer length // pSign pointer to the XMSS signature // pIsSignValid 1 if signature is valid, 0 - vice versa // pKey pointer to the XMSS public key // pBuffer pointer to the temporary memory // *F*/ IPPFUN(IppStatus, ippsXMSSVerify,( const Ipp8u* pMsg, const Ipp32s msgLen, const IppsXMSSSignatureState* pSign, int* pIsSignValid, const IppsXMSSPublicKeyState* pKey, Ipp8u* pBuffer)) { IppStatus retCode = ippStsNoErr; /* Check if any of input pointers are NULL */ IPP_BAD_PTR4_RET(pMsg, pSign, pIsSignValid, pKey) /* Check if temporary buffer is NULL */ IPP_BAD_PTR1_RET(pBuffer) /* Check msg length */ IPP_BADARG_RET(msgLen < 1, ippStsLengthErr) *pIsSignValid = 0; /* Parameters of the current XMSS */ Ipp32s h = 0; cpWOTSParams params; retCode = setXMSSParams(pKey->OIDAlgo, &h, ¶ms); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) Ipp32s len = params.len; Ipp32s n = params.n; const Ipp32s numTempBufs = 10; IPP_BADARG_RET(msgLen > (Ipp32s)(IPP_MAX_32S) - (numTempBufs + len) * n, ippStsLengthErr); // description of internals for OTS Hash / L-tree / Hash tree address is following // +-----------------------------------------------------+ // | layer address (32 bits)| // +-----------------------------------------------------+ // | tree address (64 bits)| // +-----------------------------------------------------+ // | type = 0 / 1 / 2 (32 bits)| // +-----------------------------------------------------+ // | OTS address / L-tree address / Padding = 0 (32 bits)| // +-----------------------------------------------------+ // | chain address / tree height (32 bits)| // +-----------------------------------------------------+ // | hash address / tree index (32 bits)| // +-----------------------------------------------------+ // | keyAndMask (32 bits)| // +-----------------------------------------------------+ Ipp8u adrs[32] = { 0, 0, 0, 0, // 0; 4 0, 0, 0, 0, 0, 0, 0, 0, // 4; 12 0, 0, 0, 0, // 12; 16 0, 0, 0, 0, // 16; 20 0, 0, 0, 0, // 20; 24 0, 0, 0, 0, // 24; 28 0, 0, 0, 0 // 28; 32 }; Ipp32u idx = pSign->idx; Ipp8u* pMsg_ = pBuffer; Ipp8u* temp_key = pBuffer + n; Ipp8u* temp_buf = pBuffer + n + (len * n); // byte[n] M_ = H_msg(r || getRoot(PK) || (toByte(idx_sig, n)), M); toByte(temp_buf, n, /*h_msg padding id*/ 2); CopyBlock(pSign->r, temp_buf + n, n); CopyBlock(pKey->pRoot, temp_buf + 2 * n, n); toByte(temp_buf + 3 * n, n, idx); CopyBlock(pMsg, temp_buf + 4 * n, msgLen); retCode = ippsHashMessage_rmf(temp_buf, 4 * n + msgLen, pMsg_, params.hash_method); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) set_adrs_idx(adrs, idx, /*start point in adrs to write idx*/4); // 1. get ots public key working with msg and ots signature retCode = WOTS_pkFromSig(pMsg_, pSign->pOTSSign, pKey->pSeed, adrs, temp_key, temp_buf, ¶ms); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) adrs[set_adrs_1_byte(3)] = /*tree type is L-tree*/ 1; retCode = ltree(temp_key, pKey->pSeed, adrs, temp_buf, ¶ms); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) // 2. do hashing using authorization path adrs[set_adrs_1_byte(3)] = /*tree type is hash tree*/ 2; set_adrs_idx(adrs, 0, 4); for(Ipp32s i = 0; i < h; ++i){ adrs[set_adrs_1_byte(5)] = /*tree height*/(Ipp8u) i; // if we are the left child if (((pSign->idx / (1 << i)) & 1) == 0) { // leaf || auth_path CopyBlock(temp_key, temp_buf, n); CopyBlock(pSign->pAuthPath + (i * n), temp_buf + n, n); } else { // auth_path || leaf CopyBlock(pSign->pAuthPath + (i * n), temp_buf, n); CopyBlock(temp_key, temp_buf + n, n); } idx /= 2; set_adrs_idx(adrs, idx, 6); retCode = rand_hash(temp_buf, temp_buf + n, pKey->pSeed, adrs, temp_key, temp_buf + 2 * n, ¶ms); IPP_BADARG_RET((ippStsNoErr != retCode), retCode) } // 3. verify with public key BNU_CHUNK_T is_equal = cpIsEquBlock_ct(pKey->pRoot, temp_key, n); if(is_equal) { *pIsSignValid = 1; } return retCode; } cryptography-primitives-1.0.0/tools/000077500000000000000000000000001470420105600175735ustar00rootroot00000000000000cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/000077500000000000000000000000001470420105600261375ustar00rootroot00000000000000cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/CLT_license_MIT.txt000066400000000000000000000021031470420105600315310ustar00rootroot00000000000000Copyright (C) 2023 Intel Corporation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. SPDX-License-Identifier: MIT cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/gui/000077500000000000000000000000001470420105600267235ustar00rootroot00000000000000cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/gui/app.py000066400000000000000000000067371470420105600300720ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import json import os from PyQt5.QtCore import QEvent, Qt from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QDesktopWidget, QFileDialog, QGridLayout, QMainWindow, QMessageBox, QWidget from gui.controller import Controller from gui.custom_functions_panel import CustomFunctionsPanel from gui.selection_panel import SelectionPanel from gui.settings_panel import SettingsPanel from tool import utils class MainAppWindow(QMainWindow): def __init__(self): super(MainAppWindow, self).__init__() self.setWindowIcon(QIcon("icon.ico")) self.setWindowTitle("Intel(R) Integrated Performance Primitives Custom Library Tool") project_menu = self.menuBar() open_action = project_menu.addAction("Open project") save_action = project_menu.addAction("Save project") save_as_action = project_menu.addAction("Save project as...") self.settings_panel = SettingsPanel() self.selection_panel = SelectionPanel(self.settings_panel) self.custom_functions_panel = CustomFunctionsPanel(self.settings_panel) self.controller = Controller(self, self.settings_panel, self.selection_panel, self.custom_functions_panel) widget = QWidget() self.setCentralWidget(widget) layout = QGridLayout() layout.addWidget(self.settings_panel, 0, 0, 1, 3) layout.addWidget(self.selection_panel, 1, 0) layout.addWidget(self.controller, 1, 1, Qt.AlignCenter) layout.addWidget(self.custom_functions_panel, 1, 2) widget.setLayout(layout) open_action.triggered.connect(self.on_open) save_action.triggered.connect(self.on_save) save_as_action.triggered.connect(self.on_save_as) self.project = "" self.show() def on_open(self): while True: extension = f"CLT project (*{utils.PROJECT_EXTENSION})" chosen_path = QFileDialog.getOpenFileName( self, "Open project", "", extension, options=QFileDialog.DontResolveSymlinks )[0] if not chosen_path: return elif os.path.islink(chosen_path): QMessageBox.information(self, "ERROR!", "Please, select not a symlink") continue else: self.project = chosen_path break with open(self.project, "r") as project_file: configs = json.load(project_file) self.controller.set_configs(configs) def on_save(self): return self.on_save_as(self.project) def on_save_as(self, project): self.controller.get_selected_configs() if not project: extension = f"CLT project (*{utils.PROJECT_EXTENSION})" project = QFileDialog.getSaveFileName(self, "Save project as...", "", extension)[0] if not project: return else: self.project = project if utils.CONFIGS[utils.PACKAGE]: utils.CONFIGS[utils.PACKAGE] = utils.CONFIGS[utils.PACKAGE].root with open(project, "w") as project_file: json.dump(utils.CONFIGS, project_file) def event(self, e): if e.type() == QEvent.Show: qt_rectangle = self.frameGeometry() center_point = QDesktopWidget().availableGeometry().center() qt_rectangle.moveCenter(center_point) self.move(qt_rectangle.topLeft()) return super().event(e) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/gui/controller.py000066400000000000000000000157401470420105600314670ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import os from PyQt5.QtWidgets import QCheckBox, QFileDialog, QLabel, QMessageBox, QPushButton, QVBoxLayout, QWidget import tool from tool import utils from tool.core import build, generate_script class Controller(QWidget): def change_state(function): def wrapper(self, *args): function(self, *args) self.check_current_state() return wrapper def __init__(self, parent, settings, left_side_menu, right_side_menu): super().__init__() self.parent = parent self.settings = settings self.left = left_side_menu self.right = right_side_menu self.to_right = QPushButton(">>") self.to_left = QPushButton("<<") layout = QVBoxLayout() layout.addWidget(self.to_right) layout.addWidget(self.to_left) self.setLayout(layout) self.status_message = QLabel() self.parent.statusBar().addWidget(self.status_message) self.to_right.pressed.connect(self.on_right_press) self.to_left.pressed.connect(self.on_left_press) self.settings.package_changed.connect(self.check_current_state) self.left.autobuild.connect(self.autobuild) self.right.save_script.connect(self.save_build_script) self.settings.init_settings() @change_state def on_right_press(self): function = self.left.functions_list.currentItem() if function: self.left.remove_function(function.text()) self.right.add_function(function.text()) @change_state def on_left_press(self): function = self.right.functions_list.currentItem() if function: self.right.remove_function(function.text()) self.left.add_function(function.text()) def check_current_state(self): state = self.get_current_state() if state == utils.ENABLE_GENERATION_RULES: self.enable_generation(True) self.status_message.setText("Ready to build custom library") else: self.enable_generation(False) differences = dict(utils.ENABLE_GENERATION_RULES.items() - state.items()) self.status_message.setText("Select " + sorted(differences, key=len)[0]) def enable_generation(self, flag): self.left.autobuild_button.setEnabled(flag) self.right.save_script_button.setEnabled(flag) def autobuild(self): self.get_selected_configs() extension = f"Dynamic library (*{utils.DYNAMIC_LIB_EXTENSION[utils.HOST_SYSTEM]})" chosen_path = QFileDialog.getSaveFileName( self, "Save custom library as...", utils.CONFIGS[utils.CUSTOM_LIBRARY_NAME], extension )[0] if not chosen_path: return else: utils.CONFIGS[utils.CUSTOM_LIBRARY_NAME] = os.path.basename(os.path.splitext(chosen_path)[0]) utils.CONFIGS[utils.OUTPUT_PATH] = os.path.dirname(chosen_path) self.parent.setDisabled(True) QMessageBox.information( self, "Build", "Building will start after this window is closed. Please, wait until process is done." ) success = build() QMessageBox.information( self, "Success" if success else "Failure", "Build completed!" if success else "Build failed!" ) self.parent.setDisabled(False) def save_build_script(self, dispatcher_type: utils.DispatcherType = utils.DispatcherType.DYNAMIC): self.get_selected_configs() extension = f"Script (*{utils.BATCH_EXTENSIONS[utils.HOST_SYSTEM]})" script_path = QFileDialog.getSaveFileName( self, "Save build script as...", utils.CONFIGS[utils.BUILD_SCRIPT_NAME], extension )[0] if not script_path: return else: utils.CONFIGS[utils.BUILD_SCRIPT_NAME] = os.path.basename( os.path.splitext(script_path)[0] + utils.BATCH_EXTENSIONS[utils.HOST_SYSTEM] ) utils.CONFIGS[utils.OUTPUT_PATH] = os.path.dirname(script_path) success = generate_script(dispatcher_type) QMessageBox.information( self, "Success" if success else "Failure", "Generation completed!" if success else "Generation failed!" ) def get_current_state(self): return { utils.HAVE_PACKAGE: not self.settings.package.broken, utils.HAVE_FUNCTIONS: bool(self.right.functions_list.count()), } def get_selected_configs(self): """ Collecting all user-specified information about future dynamic library into dictionary """ if not self.settings.package.broken: custom_library_name = ( self.right.lib_name.text() if self.right.lib_name.text() else utils.CONFIGS[utils.CUSTOM_LIBRARY_NAME] ) functions_list = [] for i in range(self.right.functions_list.count()): functions_list.append(self.right.functions_list.item(i).text()) architecture = utils.INTEL64 thread_mode = utils.SINGLE_THREADED if self.settings.tbb.isChecked(): tl_type = utils.TBB elif self.settings.omp.isChecked(): tl_type = utils.OPENMP else: tl_type = "" custom_cpu_set = [ self.settings.get_formatted_button_name(cpu) for cpu in self.settings.custom_dispatch.findChildren(QCheckBox) if cpu.isChecked() ] utils.set_configs_dict( package=self.settings.package, functions_list=functions_list, architecture=architecture, thread_mode=thread_mode, threading_layer_type=tl_type, custom_library_name=custom_library_name, custom_cpu_set=custom_cpu_set, ) @change_state def set_configs(self, configs): self.settings.package = tool.package.Package(configs[utils.PACKAGE]) self.settings.init_settings() self.settings.intel64.setChecked(True) self.settings.single_threaded.setChecked(True) if configs[utils.THREADING_LAYER] == utils.TBB: self.settings.tbb.setChecked(True) if configs[utils.THREADING_LAYER] == utils.OPENMP: self.settings.omp.setChecked(True) if configs[utils.CUSTOM_CPU_SET]: self.settings.custom_dispatch.setChecked(True) self.settings.on_switch_custom_dispatch() for cpu in self.settings.custom_dispatch.findChildren(QCheckBox): cpu_name = self.settings.get_formatted_button_name(cpu) if cpu_name in configs[utils.CUSTOM_CPU_SET]: cpu.setChecked(True) self.right.lib_name.setText(configs[utils.CUSTOM_LIBRARY_NAME]) self.right.reset() for function in configs[utils.FUNCTIONS_LIST]: self.left.remove_function(function) self.right.add_function(function) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/gui/custom_functions_panel.py000066400000000000000000000103741470420105600340630ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ from PyQt5 import QtCore from PyQt5.QtWidgets import ( QAction, QActionGroup, QLineEdit, QListWidget, QListWidgetItem, QMenu, QPushButton, QSizePolicy, QToolButton, QVBoxLayout, QWidget, ) from tool import utils class CustomFunctionsPanel(QWidget): save_script = QtCore.pyqtSignal(utils.DispatcherType) def __init__(self, settings): super().__init__() self.settings = settings # Initializing GUI elements self.lib_name = QLineEdit() self.functions_list = QListWidget() # Getting default QPushButton height as QToolButton height is much less than QPushButton heigh by default default_button_height = QPushButton().sizeHint().height() # Initializing save script button (QToolButton looking as QPushButton with a menu AND with a default action) self.save_script_button = QToolButton() save_script_button_size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) self.save_script_button.setSizePolicy(save_script_button_size_policy) self.save_script_button.setMinimumHeight(default_button_height) self.save_script_button.setPopupMode(QToolButton.MenuButtonPopup) self.save_script_action = QAction() self.save_script_action.triggered.connect(self.on_save_script) self.save_script_button.setDefaultAction(self.save_script_action) # Initializing dispatcher type actions self.dynamic_dispatcher_type_action = QAction("Dynamic dispatcher") self.dynamic_dispatcher_type_action.setCheckable(True) self.dynamic_dispatcher_type_action.setChecked(True) self.static_dispatcher_type_action = QAction("Static dispatcher") self.static_dispatcher_type_action.setCheckable(True) # Initializing dispatcher type actions group self.dispatcher_type_action_group = QActionGroup(self) self.dispatcher_type_action_group.addAction(self.dynamic_dispatcher_type_action) self.dispatcher_type_action_group.addAction(self.static_dispatcher_type_action) self.dispatcher_type_action_group.setExclusive(True) self.dispatcher_type_action_group.triggered.connect(self.set_save_script_button_text) self.set_save_script_button_text() # Initializing dispatcher type menu self.dispatcher_type_menu = QMenu() self.dispatcher_type_menu.addAction(self.dynamic_dispatcher_type_action) self.dispatcher_type_menu.addAction(self.static_dispatcher_type_action) self.save_script_button.setMenu(self.dispatcher_type_menu) # Preparing elements by giving initial values and etc self.lib_name.setPlaceholderText("Custom library name...") # Setting all widgets in their places layout = QVBoxLayout() layout.addWidget(self.lib_name) layout.addWidget(self.functions_list) layout.addWidget(self.save_script_button) self.setLayout(layout) self.settings.package_changed.connect(self.reset) def get_dispatcher_type(self): if self.dynamic_dispatcher_type_action.isChecked(): return utils.DispatcherType.DYNAMIC return utils.DispatcherType.STATIC def set_save_script_button_text(self): dispatcher_type = self.get_dispatcher_type() dispatcher_type_text = "dynamic" if dispatcher_type == utils.DispatcherType.DYNAMIC else "static" save_script_button_text = f"Save build script ({dispatcher_type_text} dispatcher)" self.save_script_button.setText(save_script_button_text) def on_save_script(self): dispatcher_type = self.get_dispatcher_type() self.save_script.emit(dispatcher_type) def reset(self): self.functions_list.clear() def add_function(self, function): """ Adds new function to required list :param function: name if function """ self.functions_list.addItem(QListWidgetItem(function)) def remove_function(self, function): """ Removes function from left list """ item = self.functions_list.findItems(function, QtCore.Qt.MatchExactly) if item: self.functions_list.takeItem(self.functions_list.row(item[0])) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/gui/selection_panel.py000066400000000000000000000104211470420105600324370ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import copy from PyQt5 import QtCore from PyQt5.QtWidgets import QComboBox, QLineEdit, QListWidget, QListWidgetItem, QPushButton, QVBoxLayout, QWidget from tool import utils class SelectionPanel(QWidget): autobuild = QtCore.pyqtSignal() def __init__(self, settings): super().__init__() self.settings = settings # Initializing GUI elements self.domains_list = QComboBox(self) self.search = QLineEdit(self) self.functions_list = QListWidget(self) self.autobuild_button = QPushButton("Autobuild") # Preparing elements by giving initial values, etc self.setMinimumHeight(500) self.search.setPlaceholderText("Search...") # Setting all widgets in their places layout = QVBoxLayout() layout.addWidget(self.domains_list) layout.addWidget(self.search) layout.addWidget(self.functions_list) layout.addWidget(self.autobuild_button) self.setLayout(layout) self.domains_list.activated[str].connect(self.on_select_domain) self.search.textEdited.connect(self.on_search) self.autobuild_button.clicked.connect(self.on_autobuild) self.settings.package_changed.connect(self.init_selection_panel) self.settings.tl_changed.connect(self.refresh) def init_selection_panel(self): if not self.settings.package.broken: self.functions_dict = copy.deepcopy(self.settings.package.functions) self.search.setEnabled(True) self.refresh() else: self.search.setEnabled(False) self.reset() def refresh(self): self.domains_type = ( self.settings.package.type if not self.settings.tl_group.isChecked() else utils.THREADING_LAYER ) domains_list = self.functions_dict[self.domains_type].keys() self.set_widget_items(self.domains_list, domains_list) self.on_select_domain() def on_select_domain(self): self.current_domain = self.domains_list.currentText() self.on_search(self.search.text()) def on_search(self, search_request): self.set_widget_items( self.functions_list, [ entry for entry in self.functions_dict[self.domains_type][self.current_domain] if search_request.upper() in entry.upper() ], ) def on_autobuild(self): self.autobuild.emit() def set_widget_items(self, widget, items): """ Adds items to widget :param widget: widget :param items: list of strings """ widget.clear() widget.addItems(items) def reset(self): self.domains_list.clear() self.functions_list.clear() def add_function(self, function): """ Adds new function to required list :param function: name if function """ domain_type, domain, index = self.find_function(function) self.functions_dict[domain_type][domain].insert(index, function) if domain == self.current_domain: self.functions_list.insertItem(index, QListWidgetItem(function)) self.on_search(self.search.text()) def remove_function(self, function): """ Removes function from left list """ domain_type, domain, index = self.find_function(function) self.functions_dict[domain_type][domain].remove(function) if self.current_domain == domain: item = self.functions_list.findItems(function, QtCore.Qt.MatchExactly) if item: self.functions_list.takeItem(self.functions_list.row(item[0])) def find_function(self, function_name): previous_domain = "" initial_functions_dict = self.settings.package.functions for domain_type, domain, function in utils.walk_dict(initial_functions_dict): if domain != previous_domain: index = 0 if function_name == function: return domain_type, domain, index elif function in self.functions_dict[domain_type][domain]: previous_domain = domain index = self.functions_dict[domain_type][domain].index(function) + 1 cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/gui/settings_panel.py000066400000000000000000000151701470420105600323200ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import re from PyQt5 import QtCore from PyQt5.QtWidgets import ( QCheckBox, QFileDialog, QGridLayout, QGroupBox, QLabel, QMessageBox, QPushButton, QRadioButton, QVBoxLayout, QWidget, ) import tool from tool import utils class SettingsPanel(QWidget): package_changed = QtCore.pyqtSignal() tl_changed = QtCore.pyqtSignal() def __init__(self): super().__init__() # Initializing GUI elements self.current_package = QLabel() self.select_package = QPushButton("Select package") self.settings = QGroupBox("Settings") self.arch_group = QGroupBox("Architecture") self.intel64 = QRadioButton("Intel(R) 64") self.thread_group = QGroupBox("Thread mode") self.single_threaded = QRadioButton("Single-threaded") self.tl_group = QGroupBox("Threading layer") self.tbb = QRadioButton("TBB") self.omp = QRadioButton("OpenMP") self.custom_dispatch = QGroupBox("Custom dispatcher") self.sse3 = QCheckBox("SSE3") self.ssse3 = QCheckBox("SSSE3") self.sse42 = QCheckBox("SSE4.2") self.avx = QCheckBox("AVX") self.avx2 = QCheckBox("AVX2") self.avx512bw = QCheckBox("AVX512BW") self.avx512ifma = QCheckBox("AVX512IFMA") self.tl_group.setCheckable(True) self.custom_dispatch.setCheckable(True) self.select_package.setFixedWidth(130) # Setting all widgets in their places layout = QGridLayout() layout.addWidget(self.select_package, 0, 0) layout.addWidget(self.current_package, 0, 1) layout.addWidget(self.settings, 1, 0, 1, 3) self.setLayout(layout) settings_layout = QGridLayout() settings_layout.addWidget(self.arch_group, 0, 0) settings_layout.addWidget(self.thread_group, 0, 1) settings_layout.addWidget(self.tl_group, 0, 2) settings_layout.addWidget(self.custom_dispatch, 0, 3) self.settings.setLayout(settings_layout) arch_layout = QVBoxLayout() arch_layout.addWidget(self.intel64) self.arch_group.setLayout(arch_layout) thread_layout = QVBoxLayout() thread_layout.addWidget(self.single_threaded) self.thread_group.setLayout(thread_layout) tl_layout = QVBoxLayout() tl_layout.addWidget(self.tbb) tl_layout.addWidget(self.omp) self.tl_group.setLayout(tl_layout) custom_dispatch_layout = QGridLayout() custom_dispatch_layout.addWidget(self.sse3, 1, 0) custom_dispatch_layout.addWidget(self.ssse3, 1, 1) custom_dispatch_layout.addWidget(self.sse42, 1, 2) custom_dispatch_layout.addWidget(self.avx, 2, 0) custom_dispatch_layout.addWidget(self.avx2, 2, 1) custom_dispatch_layout.addWidget(self.avx512bw, 2, 2) custom_dispatch_layout.addWidget(self.avx512ifma, 2, 3) self.custom_dispatch.setLayout(custom_dispatch_layout) self.select_package.clicked.connect(self.on_select_package) self.intel64.toggled.connect(lambda checked: checked and self.on_switch_arch()) self.tl_group.clicked.connect(self.on_switch_tl) self.custom_dispatch.clicked.connect(self.on_switch_custom_dispatch) root = tool.package.get_package_path() self.package = tool.package.Package(root) def init_settings(self): self.current_package.setText(f"Current package: {self.package.name}") self.disable_widgets() if not self.package.broken: arch_flags = { arch: any([self.package.features[arch][thread] for thread in utils.THREAD_MODES]) for arch in utils.ARCHITECTURES } self.refresh_group(self.arch_group, flags_dict=arch_flags) self.package_changed.emit() def on_switch_arch(self): self.current_arch = utils.INTEL64 self.refresh_group(self.thread_group, flags_dict=self.package.features[self.current_arch]) self.refresh_group(self.tl_group, flags_dict=self.package.features[self.current_arch]) self.on_switch_custom_dispatch() def on_switch_tl(self): self.refresh_group(self.tl_group, flags_dict=self.package.features[self.current_arch]) self.tl_changed.emit() def on_switch_custom_dispatch(self): self.refresh_group( self.custom_dispatch, search_list=utils.SUPPORTED_CPUS[self.package.type][self.current_arch][utils.HOST_SYSTEM], ) def on_select_package(self): while True: chosen_path = QFileDialog.getExistingDirectory(self, "Select package") if not chosen_path: break package = tool.package.Package(chosen_path) if package.broken: QMessageBox.information(self, "ERROR!", package.error_message) else: self.package = package self.init_settings() break def refresh_group(self, group, flags_dict={}, search_list=[]): group.setDisabled(True) for button in group.findChildren(QRadioButton) + group.findChildren(QCheckBox): button_name = self.get_formatted_button_name(button) if flags_dict and flags_dict[button_name] or button_name in search_list: group.setEnabled(True) if not group.isCheckable() or group.isCheckable() and group.isChecked(): button.setEnabled(True) continue button.setChecked(False) button.setEnabled(False) self.check_group(group) def check_group(self, group): if not any([button.isChecked() for button in group.findChildren(QRadioButton)]): for radiobutton in group.findChildren(QRadioButton): if radiobutton.isEnabled(): radiobutton.setChecked(True) break for checkbox in group.findChildren(QCheckBox): checkbox.setChecked(checkbox.isEnabled()) def disable_widgets(self): for group in self.settings.findChildren(QGroupBox): for button in group.findChildren(QRadioButton): button.setAutoExclusive(False) button.setChecked(False) button.setAutoExclusive(True) for button in group.findChildren(QCheckBox): button.setChecked(False) group.setChecked(False) group.setEnabled(False) def get_formatted_button_name(self, button): button_name = button.text().replace("(R)", "") return re.sub(r"[^\w-]", "", button_name.lower()) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/icon.ico000066400000000000000000001321551470420105600275720ustar00rootroot00000000000000 F  =00 '  PNG  IHDRaIDAT8mk\U?f4 m Զf]qg??@DƍʪXh)J[PfNf^fޏ{7 .8\89rqI>}J/+jVX:\'=gdooo"R P *չ:4q7yenUy^DBSxUe'qtz)Qht9(40`FMNDe _P->'mItC`)N VUJ" JcpkșR:qF# XVb$UlF̉*F C99]~gF+ ( 0T,sYX7cp.ȽR%k:#^E0í!Sgǘ}6bYJ&(2|/ O6cu~]@Ppq}+$9&j,19!B(@ʳ]"uBJ5a%s ,%A4 vx-4jen2]Xϸ"-`遼#q² % ei}==c 7ҼS݉\QHSp/ $Y AXReato+# |#o% k17V͕_PWH]61nbofӢ^?0}TT_Kq5~v ö(l5o%CihHv XwmA@xp+e61% ([Ph8.)ev1dJ wα(9V\" kOYz%>_B3GDADwZB s&j\m~qE(<lrԔe(cD$S n7>9\L֡+l~|)o4L9ޟeD,3 5su}1$•̔!yF$ @-u1NuO.`Je,K[ơrYoeT3Xol 9D}]I$+y/;]Zсv|v|?D&zIT17mہW )r^녖 AJAƅ6 D;l䷥ `[v&͒_E+A~q|8B&봷GA(`(\ #BH 4Lwg `6P 6u}OTϮIENDB`PNG  IHDR00W}IDAThy}?wݕvºo!% ! 8r8q(NqS q"q N)p9-Y  cuv5ӝ?fz޼o2U7==zV߱| @A1`C8&9N\!OĠ)4H8.H~Hsz#Ae zCLJr1jL0hJ M{d.Iǧ$Ig$DUbj2GV9rE| iE:|' Wɤ-sI _*T4NUu֍#>- -#&ȹ[BOc#X9`<߿n1S'16|c386,7%Pj!dz%ӳhFKϽ7Of| !\8VoBhҚEg' D(U5{NغwAb@yPut7HDjtBਨ M8& g:(AELȼf]]y'B,v,O9L"1D8QNW"L秲el5;j3*mt*F_ʾ24UUՆs%T]kGB֙/H)E7ڠQBΫa4)Mɤ69UJjXvT/4ŊeEXћ\R3F' MZzP6|: DW/~u".^=\o4nϥUY|9ܸnfDkơ%SJz#D#0!,U5U2m.ZQqEzsu( K;Y|^_>̆Y-sgP^=ym\ضo;?>cUNϲ`}yv*^$jV ìaV{}JL8d=Ō+zsh kљsaL&*{^9c?O9ő2~r>l~~o^9|_kvܺbESji'^g2YOEU2CUt\'\@Z 8t CBC2έţ;ԯO]( kϑ,H;RTߺ]9|] *AؔthϺpx¬LY*-)HhQh8V"@_{ ?0GFtd]0Qt=N*0`R!`  QrDg=ƾ8D]"љĠ)d᭸"*ę#S GӚuX՗G ݗ'H@"'siw7ykue " ưaY_4+(sâ@U/*Ql5(-Fۍ`Y݁%oyhg9]s;p|qm 4hD -Mpc%,(ۜ|Ƙ Rl[+,伹m|~~B]=#%f~缲{ďU2WIMn; 3>n>PcʚQk"1fnHjc#( hpߴ}B Ot SgCkC Wc7_oژ?h]'8Oߴ.W-Ŷ[?|,򉳻X_? 76"C s7:*_lW_CW>PѧXՔâyUR,cߩ#096VQ("aˁgzn野M(Hv^|MvXS q Xo&1$ֱJ΍g z LuL0aIy͇43(`klRWR smXvkvIp\  >9EaTE2'/WܷeyJb kvet%Its 3Q'4'z(eXDZSS,8V 0hO0£A }=Y~p'oIENDB`PNG  IHDR\rf IDATxyE7~fO !!,nQqA}qtum 8#90"3蠠-;B'7w_GwUzy{/3'ΩSujK8>uXL,g|YMyԺ@M[ C"P˫YDSNӂ[ks:͇ MBy4}!c:lׂ8cHIz$S9o2B܌d"Kы/ `;̈C^D%"m4Y/{%3L0Jeh7n;*@)EPsG,k2FfB.JIJ>ly[o++.w%E3F$ H+,)meiQ"Yb)+(T!ftJL{L*;⸊#]٩`]$>l9"_"\ n^vA^Q LB0R#L%] 0=ڹ>IH¦DC&nHj3B[`ZrNO'Y*yϢ,2mn"Ofpg$~,p/i TT8 0 ꄬI0 }qNQvV?⧎k&ԹCJyy(4hXX,>C*(/Rgȳ+ \xr-]nͽrz`\P!e+0Aqâ"H<@jREf=X4T/mJFˠ˕tzTuji!\RqO % 'E6v58j:fld8@@'+sPxp^FYվE&(W/2#J1 *T@^;TOwXeiBxi)HZ%c^+3 09Ò6+1+^ĠDh1l+ dbH,D Z- l֫+H[B T^4winrϺϜE(3խv0p:J$=Qg$PipX$٢b3 ³RjIxihlk,Y0u$,eKƘpsz7=NX\fm4WA3E*OGD:T"f EגqpЉ'ƴb)84ۉ|YhF1" 82&i]0KպC :Vz y4 hֱ EHr{,y,tTS<"i @*ŭ+4{o@`ުs /6uL~}9Sf6Ov2<=z#JWs˽lh[sFE"f@` eey)>gz UWՉfdEy&slC a4+AKФF)AҾ*)[ `^(9B*t՗|:F->[XVFqŭ-%)%i4.VhEWFJANvyhLk]Ie"](t H=҈LTgɝTȃL5E(Y t-q:<4-*@$jL\1K}XgЅ xJ>=nzZICƺ2@ٌ6:S./2Ѱ[V6 ͣP)Bj%a(B-krbEUC"'tУ,!$J (yougj΀W+VpʹJOws=qW]%;sj% J|j?~~7ꭨ/t!mI#L!gh:춁*X9}%FR۹|^a=^y\\ΕKq幫pܨ홁i1Eڅ64CE%ə `d7uWՅ"z%"!JbVJܢDL%3Rl,sN\p2~r*TKkcߝާ]@|'XweR^F0Tc'utfDpF4f1bh,++a=޵f1Fx]v ExL1" Ƚ`dQe J/y)X>ehe11ƛd#21_w C^TU Pc۔G+qΔizΜ%]-w&*0A7C.e3Ɇz=3??*HQE } .`yfZ5B% r,6֛^gfw{ᘚiwp4nn$hUY>zS[n\L%2EBҠ R(<`|ex׉>%+2f-CJ_T?EòfxjGs+G\}|;5\y RX$Or\WU>"?~FڮS H xl(P}Au.hh PK.34*6 UDj|tj[wOO|c*3,]mpVm?|\.MW?2cm?mѻWaGŲL::lFİK _)aAnd>QR6-zrm7h&\=zpg_r9|pc^og9pqmwʹ[6%nP-{u+O)7S1$aD+oTB8 BE 3%)MZ<05Kaig_clĘH-Yii7Y&ߕgnFDp~KڟJEC%)f*@W>26+,n46[JïrXc"`LX_=}N@m# 0-NŌ Do39f6HJ-#ms.„e%2&ynLc F/cfQN9s _9%XsyQz 8l%}+&:v`A~yp!}G '4TSI$4gҺDV5r-F,*3fLm%xHmw=RuI K&RXGH+nƩ[2.] +`@6lGggۙ Mgz@#6sƕF0@-.Zw!bA~Qbc -Q7Ftc*)%66IyLA:o_ت'2ro2P[B*u nZg k6]v$X=j|4C 5=/eō> T/35OzLIt -ä AWDځ=5-a yڌ_kc)b |9NDӠQ!{Z옽1!/ T(.*ʾd7 ۠Qo `ыxPoUnݟ559ھep%TDsH~ R}DȌ,6\3:F1&B'd+3}AA1k6/OWyFyھs\1㕬0Ea'@}y2£(hlLWW*>2YecD)?~jtcx kDQۧeLBJxN[<݅g[luf W2(l]$*93jBX)dj|j 0m@D- ;i#)V*ŲQk tbP/l e!6J .xm^ i8/h>jo{Ǖ@.ģoIu{}t͵{},)DfBMHJ3'٠0V93vȅBÇجc{P\-o[z,,^`p t4Oc:zj ZL1I *͛RB-" ~t߼yzv| tGnCF9"M|LI0M7 [-O6g 5Dw 5WeXek/ =mn{|cU`01_22|(쏾W "MHaɯ,h8Ca넣#_{6 y3 7mċ(ƕm *O?OVK,=J.AGBO__+,8Y34*peB7bP ܱ I&>_f7L?|oE lmŵl(B%+! JA^((ѹO(u荴Ҁ| vf!l oޅj e2WPZ>Tz{jZuP"Z|"F.2 @pkM8Ut}&;v 譕[x#Ug ;v'QPs]/r(I HUezYzoX%RNqEvmCMK)s0,Fw@S{@7qAܵi[+J%U<7jM#(mղ-AwtYZ h'[R>߻fahaXb6…ܦwF(fv 4}񺏡&v40<тWbx pr\+ێVx&v40>c32TBsxҗ/j{-!#` i]}%FlSETRg,J`Sy!iעmw}/P\E[Ylu| uv?Ќz#V^"qYi!M6M*#`Pfu{3d"7R&ɨ(FHRҘ1o0 Z EK[.uw]Ra,2)WWdB /@;cdAlwܚ M-J,=4+xJ!uD␴r6^ koA^4*f˨r@LJ6#^D.7~N:ٗ*7Ns `3Fu`nZ1bg <ÁBr]#W;<) UťM9O%#6o a6h 64#AL+/̳AS,2^ ncUoŭS$KJO eÆWaO Lc<OPKFE5JC}P\x`M:#\`yeZO"4J= |4F' +0 Yd ›BCY[1O@t4 "hECa4RFD]e|4J#C7/ ,ԼGy k![GhB*ǯtC6*+~Q|t0` +šp鬝a{#)3hÍ=M^_Ofr t~;m) dCrգS&HB͢{z׎RcPN'^g5k9Qz(ZS_ @1:T\P)bIS hh{*kPۥaR^MNi|ͷQ<|! qU}qMA MQ5)'`tfI& s{J q·` IDAT`XF\xpVuk0+YѦXQȧ8|瘨zR*W"3, 6eA++v/ _Э8fg@bHJz R$$}cvFfɩ{kz" ǘ)j[Mۓq1~< ЊqRjSgAdl2d-5%%1%ng ^~\| e};[9P@N Pr81JEYo*)@J=Xfy | BS$^; <% MQk `!{4^j~^r)֣J#vh^J@lꞻT42 *H3ƃFJb-y`L> w\P-+aJ3qSxg M2LA0Vp'NDgo'PP9̀0 *\؅(C l9?~%1cO __ڗ)R` O !/)\-Ӗ5הPUw|j z HaxێJIuZA=mY 9vPOz=eRh aE NB5#ڗ ˢ#?c1,`)av[K<,DL oQҙl' Dێ܏'vcxp`'ԇ7? z*%gmK#d%MYPQ6ih;u"̱Z;[fD2[k -t |pR 6o܂jI3'Aܴa?>ˍ+p{]_KZGձaIY鄎6w3-nQ<٠HV\@pDB-wYk\"Ե(H k/ˈҩ!97B]X&>Ü+o@od]>po {pGWnM#R[AFc(n5|[8hnG-28ƁI]Ѕ+<[40}cMtW?idh(P򀒶1e8w1<ģ;1`l=c9Q+{鄰(7BJ\P (U^ҽU(Rȵ^ 9uyuw^+γ {NZbݵ?:J8WaX^/Ta~ARY{SM6~xIKN={ûwZU_|8%vOh޴aWݷ?g7eOKǻ,^;*.=Hn8kܶ=ޓ,+VγlW ໷l}FѕPoq\qĢnAlߌ&-/}N?| e'>^|\8'ۈ ڠ)a  T.B DP D1RU|52ztgQ-i`(KN^a$ϭYnyzH*1qMcl3WÙw'ۈ+V-NYU‡_]=8h֏_a*ܓܓqΏx=rCt2',Wk/G/O?Y동x2μaܹiSMWh8֏?B|䚧w'+F~ 6ۅԭ5I*G kTtD6MaPObe2&eO>67X+ڞUWDP$'VkZ)TJ|_ DጕK]F^R_gZ+njx }G ?Ky$NX;S/pAl:0, qBy6%Hď`"3h...[ecւ/NhG'ZU8& Dw;+p{b|͇M17'+lwޔ>z9qq&Kޱl6Pw"e~ )KhATfD9h k-VR.Gn8~V&pԒng?ܨA_phZ;bNN{49'nxbWݻ;*{8|Q^r.֮,X 2hIO ~Uwm ObhCw'-ފQ1o=*`u9Uyhq\^ 7q>k\s~>l%8s}bA}8`NCn4=24`x>M1y )$j|7[WwE<έ9;c1d»v$8 FT\_?o1\zf߿c'8޾쎝 -P%̴گV= 5ʲθ.k7ZwsJb1`T 6m,|㾿Y}_y M9L.utux|ʎJ-αsl_螸aϨ&)&e5b1գय E("OEg=8itu< ۲2g_ot6"K+ :5!~D0_TP)]X<]N_'"}GYwB;x !u@̉ $7ްN1\@ψh Z9! O@8bF.tUYrRb&.kgU861/RJ@2eoԣ#2Ծb?^8 aX/z[lԌ fgR 9(^z\._LE/,Yޣ4lu!5R~yK1^oJL"4C(SzGE`08w{-xdX,n__wl{Z,ye" V{ {@2SZp^+$%)%I͹*|@8M~H?E`582,pѲhSZ76~.؅*.txz]b/E2})9cQ.T}6oz'~,6}ăٶܺJ3{'y.Iw(1ּg6d@i!D[O R"nھCɡ,Dã Oj @۝p黎BD>fIKl9sLDid.)*őۇ"\Z-{6ۗ^sg7ֱmf:AL7^$4iGVILV\ $d"\=A먺hBPں7s2>DAa%F|u$(f+o8)kVZ0lu6CL&AOTq6ǀc_[W8:/\n?|ߡӐWE28}t A:Ӄ#=ey*"0DG~P/q[01\Ǘ~ .8gg+Wg:5&<ư{Q-EC/>_i+'`6$K(',S_<?gƛ8jI7Wi^V-ƹ/ V೯Z;6 OO♽h8Xԅ<}9n~zXobhU;ݷ_a <|?Źqs0~~ ObA 瞴2ܻu0l7nfF})*)7 Mex42b_V!yƠDZ=d ";f'Gp(Y{Ox;wЅb;eq_TqϞ s;gd-ln =`#}X)R90>s2J~ı#O_>c,w=U?w7>rj AG&[8 w|xq |α_o1g2 N~I x{BQzL\ @}y hndŨiumK4 tIzx񋂃,y`xȾMhHvj졦I04yWm&<5c vs[to_ߧ-c?yT/EBXt0B/PbzC(5!7~=1"蚆P/C܎W_xlD<;0!e/~& 8'G]+4`x|v\q̼޷uGef^WM|~`TK ߹e;^wÙgpwaq NtTm+/.ґ_G=~:|h "Rk r= 'U^.&h&~p{fsJXiV4ݸ tQE-qal>T{ǚ=jNlr2Spv4'iWBΕlcݳ#W-H}'{z$[upn2Tѯ-ݗ8EG@mt&-X37[ G-K{ln }]v 7Ԟq ձup]R4R(jhx=@ٗ<(ǁr,**eXcMX7#\d-}Acw=HiW,pr@[;}~ar0{Ki^dcrv `1Q-VBǣXGE%T3 aOs#ؔ 2Bv#聯$d-//Ep^6 #+Aa3P pinz qhMben ӷ #ڳ'-r1K+4`!:OCy),QKy}^0pg(h;Vʙ!7P$d+1W7K7sl[U8}]0mK! B\3d0APe~ԟzY] ( jP0mwqIfDWGg7"!Gj*WnN'Y"NTBĠXy J:TNKVJT-L tJҊ')@; 5eQDSBv <0T J*<`85WH!օ "3CP +- l»S Z=JfJ%hs IDATˋ ŏe)mPthǐKږhtr@"~u,.ȁ(}.Cpˁ"| As:qX YCE!Pz!(Mxu]yخE[`+TХ#̱yJb8poh&*^lېG+vvڢ@14Rji +SH[n {Z. isb"@kЎ'h Ѳ AZN!t2IJOvqsM 9L((D1)W)*(jˆ"@8pDJ>HIr*T 6 /d@X|gx>#6)E +'=z',`Q6zx↛egX 䭠(2QZ7ǫhs/Ù H6"E;t-< }KkNڔh/|E:K|[=˃<1c7 )ڇ,snS =h!.s6 YE.mxL2*>JZ0}8U,u@@?yG.CB₾)1+@!nTU9M@h倊o32ZBO2mZ:&fɓBi`߭(i7N)0kĭTyV8564vTBSۙi> <{F & ,DG&ʵ5&ꪈLÉ]@OyYMB1] 'H]ZboqQIqˈW0[AVIqd5w)xDy{Fv#PF c|a}͉"F$MѪ@8‰HUU'*6J-<S!1(r.R/Kaa  cs_SA+BH0MJJCWhN=kސ[Ge8aVf4JV%OSno Lf(y({@j>؍DANN \ 3=e+*C,gpZ(T<ŸBE^[=nJxܮ^E1S-ؾPZ*{xlZTZB3ãQW$+|}# ~?(|e)t W"r6D FL)k%j0"MQEcj(g}h(^P o_Y qϟƾ1qfxnQL5|;8 s0?;Bǰq.86G/[]ӓA߹e-({L]# l3kpwlFsv뗙o}f؏N4|ܚ=>?^S(F +ts>`bsS>z,'F"O!m4fȹki>xyJY(Xc0b#2 +jxCb/6{`00,)/+px /©kv`\{8-EO061}x>qn<'N~ R+S0,.=;Eћ}!o',­}"0V\ZW~ˎ ^{u? RH>څL<`@h6QkMί>V0i 03bv<("*rmE 0mCPH:>,u-@|u\ ~p" =iM:JX)tO#wG ʮG2W-an܇f=>xּKoߡ|)if1QPg rc@(yhcLZGLsuT E 'Dyk0KT ZB>(Ii;(< tNWu`柛Kyd?;asӐVZF& ]>)>.s's8a?I߸f˗cn~LN;pțhǀ oNX(U{;({G02c?مƿ09'_3 @}.*5m"BT rt\9. DC</EK8OșM뷌ງ+·^| ~ jW\ѩx>Tq{ =``H_i+vqmQ+{Ȃ6w8T*{8l+(o#S-|?܋Í[!oLc8@u2pAO/8[O)uqk]vtW uY}'`'lX]c)|ޭVWFˏL&;owctGw}5($+1/n .kz*%=|mzr?^2e_W =2ࡧ{/כ>gWWߝW/HHˇ PTU2úϿt6*"\WV8pZ(qHRJN*TBK'ZY*HzY&dQT z;8jqgq+KQCLmR~"]oژgMX2)u<xCp׮^ɦ:7R^rXQq ?d,V{8ccsbX8+}RfߊN Q K C+xH@P ݋DCZ]8O#UNq/e*=)<78jz4Gba.lgup ' q\l ԛsG,Ƃ2*%OZb_-(ٽj'.x !HD&}z彻ޓ(tNZч!ȵyɺ>.6a@@h/CyQم=W 8j5<l(Qx8v  hTF%16E2e< =XKhc X;CC G<v q`Z ݝڑ O Wj<ƫVsh7nNE=|Ne[ ޼z!~>ͷg*c 26a~(o.^T(PsńX&1 Hж4:goiKjwCĽ4f=W? !rދ1Q,qf<3].A7@MKF˒:PfvOc0Uo}Gw;>3ROp߰J?4b]XzfRC%c s1~x0ֲo!m(i('2i } 49@uj/P*sU*>t>2P 1!N`Mu 誝 `F3R P2.жe5%[~,h9 o9tAl3. JBԶ&`}%Gwch]e*+l0׮^o{;vc椈~:Ó$ Ӗex.TI*}P7mDPo;4;V(2L 8& Mq/[??'%CfEW}ECGl: @i Vd>K\cg7/Y1iG}kj8ͭkvT&/F<ưilk^7 L6}|bAsuuW<ׂCu/BVKxv|J7rQu;PA^m7NQoʽ@g2{gjG1`|®Snyfpe$¥ pU @{_&"?""2tmBO﹤g8'V7ܹq壸kP,]OsFcq N4|^^N{ܿu]O黤fdGVfg[h8\x6ܻu=oYq_;kje?>='vMD2R 2\tC{7LF'^U12[xej@k Y ԟ6,?cp C!vK\WkSo+)MThH_bDa~DV av'圄G[AwgO81ԓ[T>' C-7";%0%0|xljxq`IƎ%}|升s) "UPrH?;Z h]O]'@*˂W xXPo 9Fvý@Wv= =hU XA_ X]( cݛMB<2Q(!F^J" ied .ukwE,r h'pa\9Is~OPqМ_4O@Vpe2¿%CC# Ys521t-ƀr (P{jM@Ӄ??Ba" }N9)b>a:hՕ. Ute\$ 7BjDYW񇷏͗=0tl{?;lVNL]Z98J>pA|g%VVڈ> ET]^"hxJ;b_.^j>U= chc>{Z0Wx& 99hb21z\Q(zC%*|&}g*q(l\K  4Z>_>!-|0bذk?kg~> BBÏ%>L7|>z2[/ xjPm9Se)AR&%N `x-%y2oh C ``tj+.{!!6k H!D,?_*@tAmN;Brm;4EypСuy Mc%O)((PKmx:͖1lxŝ9~ 1<%ir>-wl>u%#K( (-ہe<,oPq]݀S1~PtOdPL SLa<ψ/BD6ݓ|ōJ(W5ԃ'=B%<Ґ-wS_+anW}6ѕmm1:3VB!㨖%vJZLU,CKiaǦZ2/c+JmJ) &LS,])y[14 x(Uޥv]}^(U>zsO QyȩxG5bd)S0G4M% :^R/i3cFYE)бFM>:8ٔO0֕HtC+@-J9hv._e^g"`3F2[XM-㼗%̋o)Ԇ@i zVҖ7(?ﹷvLϾhFiZA2bp@F?09ؿyB0'Ib6=qE`0F`Z-Y IDATg{oZ[uۃ}$q#qߥ5V&- ?B5/XdxT^G$gt5G+x $:g\-RX//noo8'{{yq7g%|$Vϲ%R6u[ 0yBpɣ==.Z Cv@qDXNf Z3#sjJ>buem|Ih|0OobZL`]Is`c>讉i)=&,. (>N>ȤOuHsruzZ>}.q!\,_a֧b2B7R%͝u#gȹe`鞀Cpx˼,5=11̜p;|#xj6zaBU Ʒ y &45H udh.hEz#+R^s@@Jx}ݢ.GMѨtw24=;~IFV$I8B,Gp]~?f/Eᤄ2=I++YA.FlajäXpڒǠ4N\1Pv׍@4(D/(aRa e/C k (%}# `l h>A4ʔK.R~A{ED%؊NオgF53~h U>D%h9L, 7SL_b0|l[06tw mG)o#5R }\m׏u_ڸ >rW['{%}6E~@0Λ=KJU.bJoʆiX&{ϯghpj͏MrϣƓ']i:$fҷ^ɋo2fQ&_S,6GZk܇Sm80,!7fpDXy!%2^-lQ4p MLbaO1]J©A 6Ԙjy1oNM0WsU? |C'# S:Q +^lr c"b2TP u=A ԆI@ x}[u c&Spdӄe S ¢E}Ѡ f  WM*¡7ӅJNhZ;ꦱKQSzF%1wOHF^y5:4uҺM].,ˀ8ZoUhAGXp~w5 aYj 6\_G?sNh1WCWV^] ?,S6}"ڕIp= -`  ƒӅpp?(|ח'ft[}u3}qqA>{e o2cu 3&k5+-\aXx- _ذsGM_X*AdfjAj2;"Ð+ _UF׍Cn.5X-#0d DVϸ< ]ڊg {9k7(_vy!'jH)7uFӅ 5o}V#+W>mA;z~g 0fgYMF;<=0iZ˗LN `v oOr ޛn2B4bWLJ %=n3 PdqGqS6q<*:_أg?M"{vBIRbgm)u3=}Ѱm9bRCO[J)u? 系'T$X0Y383NQ}975nWs[+W^gtwc˫);1tJAXt`rf`v80>{d2  [5kFx4~)3(yVCT|BX %`i 5`lHW)tQ{9622)&Fru`0Hl Jd =z's_% ګƶ _iu+eÎ#+Na W,A G<ơL$cxCZNBSZb>AGQSwc%Y2Taޥ P S:-$iNE5//gUh/5iɀ*@ s4 H=r)[ w!<x%,:Wo6oG˅G|ZؼI~Nj|'$-t Hp9aE\t>@{ ysg޳#6${yZTXE5Oj+F< y~ILiȯªl,mO7A/L©w[.܀ՅAՆ]͂dtjTWB՟#\zQ~(ٷ=~3}~;PŗsN$d&pMסfa$%釛ED߮1vnw؃Ks4u$5u3m+gc^DUqLU*\CT'_C]C/)P}vtն]XCߺ‚w&q. ~E)Hvh ; GFf :L{.%O޲aϯ41w_y\eSPYv103ZBKCAaY/RX70p=sRUkr?xU;2YjyHpQ^r".Z5 6 &f:>1Ń{c8>1ˠ;<͖!㰮G߰e1m\ˇY22@!06f3|gi1 E53'yÓ@ Hc y~u=gRs EI\ , } ČE%<<˺C ^28|'$l<趁&4/,>f ̓c-o_#t/?j^ߤ h}W93p-̕eųjs/z?qGiH>< Ɏʋ~1M)CSl5kiy _]{^nuf$x56~p v5}IhSy v껤L"~ $tjJ0{C2SKP%=@V/P_6=>gGWRAh_aB0]#pex7tj᫰RY#+!FnPJ(-kyJ|j 8V@'cG(pK)2N <+$.$K7!I.&BοVy:>ylEoouytaٸ%ee(*_B\C B2|O2l`Aoe,-h }`{_3 :Xt,9W6o柰a3?}|m׭G` NQy]h`#Ó2;\fV[tK\mO&lG VrnHe8`Hչ\ޢMepZߡQZ`Co'z˹-l\Ҋ]udБF2|KlQHR29*ʖX5/8k/E0UC렭Gי'L9*(3%@&W5PF1+&}۷5([~|B3&P85, oYJMbo,63 t9]3?KɇYo= {b}M 6$6Ut?mlLJSO~!33Ќ|O^T [&d[ DH0%?b .|p/_hzp50 d"]X>:f vt#ŞS J` |@ }MQ@TBXDc5~IiLS#s2g=qfo߰!K n`#ƣg7vgnj%S(^Eǧ;K;Vw|h}9 k~W1$3H5eT$<5*G $}ս[`뚹&n8p`Cqʂ@ka]yk'!˜@Mj +@ >{^v+D1-7KV TϏDG{]tW ڠonoe'i¾hlG'y|*3OS8Y Z,7wo^{14(¹V͋nTTXί?AOU8 {Y}uj%1![3V!Wښ2Ζp's삣jcA e[3 `t[Ec.e>T" ٯ ##e?_D02vd4QeU S0b+@iaʑ,O3L+4Wxم>U_|]"Pg 9Z*PiTZn9TUi$$V|n1vDv/sk@6o툼1h"(׆c )AMD3 l M<¦|Tw~~j0;MJsaT:g`)B-f!үZ vVξOj8y_ Cr)IRm%#״P#(yk OKoWAi5ut(e| TS7,h6^yY'`hw}q? "uitqLpT羫eʒpv.0SP.soyZ(aq6zTYfpxNp /G^$~ Os;XN}>SI}fS]w5Y(C"4  8WHfv@9;:' | nyV6 FRf|tv`;m @okN(\3\Ao%/JC'[ :eƗMr.tsO&xyZ4QIZϷҝl E/YණVeiT;lߪs+nw*&]߫r}rD`X-o U̷ y9C`7g.S` v}gm~dؘ7c4u$AϬhLdbJ:QzPӤ@ϨU]Dד86ɾ,}vUZ6ox,ݟ?xf#/:;߿j#ӝn%?:].]Fw}"^bP6*R ; I résvSW `[ A8c`ػ]qbhD)rʱx`uw j0Q|)AY%p蕃zPpEZƉk/=}QYxTXUܔWX=>oGݕho/'IDAT|y\j&;tZYwܷ3Z_j3>adܰOraC|wl_}.d /0Jky P7 *k8Cbe(\s4[1nص>)DrA~)l>$;DL=xQ{X_j#eI_RsoF=蓍J2sɿn&Rr^k#hTmw nz&83'u_V7y<ޗҥuh<]`)"25w]^Ȼ&CM݊uȽ|xݹ&l#`{ vb DΦ%,Zg>F5{z*%Ÿ6a Zw{]ϹqAh9(uۥ ,Bق$ 6w婓g:yuv (L8-5ɫiB«Jc|v-eaQx_,VkL˺PMF^hZckW}~à#Mr'drϽ3QsTA4]7x#> H-&b\ʘ0FW)ϩx.΃+!`žZc;APcL)`~E4^#߽oB=#}tDqpL$ xP[7`pUAi₧S*~n xr]Z] {D\J`{8:>֎2<пX}Iޱqy("7eZ6mpe_>anGxș$`~e WGk px ÎO̰t$ q?MtxQ^q篘Dz 4 &g;S]Ƞx']cG_|b>w!SETgM]ʏ5PHUw7v\yklL:=g<4i^si92'ml,cy|xG>V-<'8 3'a4n-}|' hK F52 i3W)5Q4p%20^QwɆ_ !R{9IU@qF~EcwN?BQXcԺW@ݵwZQRd'i>%I5ԬՄ;x I*t'DJIYhc7Bc&l`cBÁ0>0t\X{?WŗW.eJf+ʝN*+!7?IkuȤ3 B̽'F/5J heuU/Zw=3I"\ʁ Tu*T(5JuOyVUǻΑ*yϟ.\uu S* TᗍۇNoM bh)]֣j#,k*Mm^G9.f01F!p14`ypI-2q a8_f,y[||WG̜YJHi((6oxV8*Y:_-)}.>=5GJUHOhY%UO ʅ -ĥ<&/'9?SwiPnap7ٞže-^z>րZ1hõQ= ,Һi!Zl$mn c՚8׭`b6WZhid"RAtD=旑DMi.@jW=cJ$nx"{Zf6&w?MH-,$\F y5l|XX6сÃB{}e3Mp0y>z?&H|lhڗُ5z N;ua[RLjEB@gگ7YXHtH*; sF_cu?[OmWA=ٌIx蔌 Dl a>ooY}vV5G&U ]a8sNVs-3K E[z&'>,x/;}N%- @@W_pwGP%i!1T?Pi!3ESf4 J%ndVta4?x '᷀vEv`Fpn49(?ςA\||H۴ BkdͩK,56NeT-JYn,A5*f NxCgF^/Ykꓥ 3<ߵQL^~],:fBQ.?$`p“OBM[jp.yl &v Ac%ts4!+ geKQܷt!.\~@Pt5i BM&=[ }N/U l.A؍РkLWBH;^xZﺉg0%]TRb3?u(#H>]FK#;w&D4Nrlǀ8}%,uk0< p` VC`kN=ɖWo5`: vv׹7IE7/hiIv'dQ (= H rE:1=\jex%OcMRxH-QTJX]Zߜʚ~R#o,[ WƉ!:PNɼQÏ~pb[j ӄҁ ;jHĒM0qT8'i.G/yGWZ(Z'5j4U?R(äRߠSԏ@5w]K!7gD/ie>%ڴ rrnҴF:5{ґЕ ?xHOdG@f@fnNfp)L/]n8"lSvPV \9Dμۮma 5كE($sA}P V ^t΄RtcRTƝiڄweu@i0y iC%~bW'?&8b vxk؞u:;CR\)a|m gs@V:$t`vêS"?v>іn!涺}3ߖ 83K׵Jv^ a5?{Ol|>0zXY7 W"7S1 LO*Y;W+I 0)  `a@wj \K`v7!#lZ ݅Jxe-a#';/~b5( VܮT:j[>ϵ4E5PrFAhc^5]Wz${4J_};P57.u9'虿Ɇ3~J9 ,OZ{ƭ-㮐wM&<(!Ac\xYg| [e Xrd50 z/}lۛ` ?K222\<>Tq7PM>Q^auU`Bڄ~t95ym @{ rUލ\-[\5$DX5h giӇ`7tnP8TE~zN 6S`!h FsG~y- ^KPAsn&[V,c\}J;? *JPOQ|Ҙ7#k.{:VP~2ғQ/G'?9K{|I>/^efp-G;ØqR9& 0=&ق|ZX Z `8 3K,0Iu=w{/goz(#SKFDmÔFmceٞH_6>uf/S8WPbm7oJrݨqu0S=<<-=^FCkRS~5tTPW-?3Ngo(|ko .;<=bV\9x<`D-pОZ83+fa2Bw&’^O𗯘yǶ)5Ժik@lZdǵ7SI1jDU[*i?UTi-Ns~Z1M]K$JTUI%V1m]V$7,Dz݆ixع >?*.x#!g=m0Ak1l~L1i8<*ia,9& GAdFa2KM:.t™I4ah󩟛yG{@ü!r,ˈA>uț|e3t%-<~_j`4} +誼Ry=M[75,jE?*y/g Mee&9\`1řA0H:Spd-8 ܸA(509 t LM FǡS4 BsO^{Ɔ "z78y?=BMiTk+|ʸ P^I^忽?Ε6P-qh¬[!l$]t@pv\t]hfia:$t] 3Vf{ GE]0SB{L !itWhJwok^=?v74E^Q!fiL¹ ||*BH$>COkHc?O>*nI L$'M4s|SMT$|*~5@*ĂA~{ɡ]{XXtƖtѐLTv\` 4a FX2Xk1 . 2- ̬tOWlj e lU,U$o"[&0 DQ)[3yqa_b Ck|M:3a6=Ҳ|)[Stq̘^Jucn7a|xfv}ZVtSg&ݢ!w~a 0 ,iiF 0ն%}En[j@-=3fyjzty=^q.W 64Ĭo tQpuPB7ʣРwk %`)6 V4x9` RՆ+ Op1x`{@ʂ@[eZNa]1_?/~$ g6(`Bˉki1aaVI;@bvKpfH0]83a=#tvK>Aha: 09(0k2BNG,@w7̣ Y0PpaoctT0vv TSJ(?QqXDz8Tju/kE}PkZ2rBve˘@/# 97v/nL/IENDB`cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/main.py000066400000000000000000000135321470420105600274410ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import os import sys from argparse import ArgumentParser, RawTextHelpFormatter import tool.package from tool import utils from tool.core import build, generate_script if __name__ == "__main__": utils.set_host_system() ipp_package_name = utils.PACKAGE_NAME[utils.IPP] ippcp_package_name = utils.PACKAGE_NAME[utils.IPPCP] args_parser = ArgumentParser(formatter_class=RawTextHelpFormatter) args_parser.add_argument( "-c", "--console", help="Turns on console version.\nCustom Library Tool is running in GUI mode by default", action="store_true", ) console_args = args_parser.add_argument_group("Console mode options") console_args.add_argument( "-g", "--generate", help="Generate build script without building custom dynamic library", default="none", const="dynamic", nargs="?", choices=("static", "dynamic"), ) console_args.add_argument( "-n", "--name", help="Name of custom dynamic library", default=utils.CONFIGS[utils.CUSTOM_LIBRARY_NAME] ) console_args.add_argument( "-p", "--output_path", help="Path to output directory", default=utils.CONFIGS[utils.OUTPUT_PATH] ) console_args.add_argument( "-root", help=f"Path to specified {ipp_package_name}\nor {ippcp_package_name} package", ) console_args.add_argument( "-f", "--functions", help="Functions that has to be in dynamic library (appendable)", nargs="+", metavar="FUNCTION", ) console_args.add_argument("-ff", "--functions_file", help="Load custom functions list from text file") console_args.add_argument( "-arch", "--architecture", help="Target architecture", choices=utils.ARCHITECTURES, default="intel64" ) console_args.add_argument( "-tl", "--threading_layer_type", help="Build dynamic library with selected threading layer type", choices=utils.TL_TYPES, ) ipp_supported_cpus = " ".join(utils.SUPPORTED_CPUS[utils.IPP][utils.INTEL64][utils.HOST_SYSTEM]) ippcp_supported_cpus = " ".join(utils.SUPPORTED_CPUS[utils.IPPCP][utils.INTEL64][utils.HOST_SYSTEM]) console_args.add_argument( "-d", "--custom_dispatcher", help=rf"""Build dynamic library with custom dispatcher. Set of CPUs can be any combination of the following: {ipp_package_name}: Intel 64 architecture - {ipp_supported_cpus} {ippcp_package_name}: Intel 64 architecture - {ippcp_supported_cpus}""", nargs="+", metavar="CPU", ) console_args.add_argument( "--prefix", help="Rename functions in custom dispatcher with specified prefix", default="" ) args = args_parser.parse_args() if args.console: print("Custom Library Tool console version is on...") functions_list = [] if args.functions_file: with open(args.functions_file, "r") as functions_file: functions_list += functions_file.read().splitlines() if args.functions: functions_list += args.functions if not functions_list: sys.exit("Please, specify functions that has to be in dynamic library by using -f or -ff options") if args.root: root = args.root if not os.path.exists(root): sys.exit(f"Error: specified package path {args.root} doesn't exist") else: root = tool.package.get_package_path() if not os.path.exists(root): sys.exit( f"Error: cannot find {ipp_package_name} or {ippcp_package_name} package. " "Please, specify IPPROOT or IPPCRYPTOROOT by using -root option" ) package = tool.package.Package(root) print(f"Current package: {package.name}") architecture = args.architecture thread_mode = utils.SINGLE_THREADED threading_layer_type = args.threading_layer_type error = package.errors[architecture][thread_mode] if error: sys.exit(f"Error: {error}") if threading_layer_type: error = package.errors[architecture][threading_layer_type] if error: sys.exit(f"Error: {error}") custom_cpu_set = [] if args.custom_dispatcher: for cpu in args.custom_dispatcher: if cpu not in utils.SUPPORTED_CPUS[package.type][architecture][utils.HOST_SYSTEM]: full_package_name = f"{utils.PACKAGE_NAME[package.type]} {utils.HOST_SYSTEM} {architecture}" sys.exit(f"Error: {cpu} isn't supported for {full_package_name}") custom_cpu_set = args.custom_dispatcher prefix = args.prefix custom_library_name = args.name output_path = os.path.abspath(args.output_path) if not os.path.exists(output_path): os.makedirs(output_path, 0o744) utils.set_configs_dict( package=package, functions_list=functions_list, architecture=architecture, thread_mode=thread_mode, threading_layer_type=threading_layer_type, custom_library_name=custom_library_name, output_path=output_path, custom_cpu_set=custom_cpu_set, prefix=prefix, ) if args.generate != "none": dispatcher_type = utils.DispatcherType(args.generate) success = generate_script(dispatcher_type) print("Generation", "completed!" if success else "failed!") else: success = build() if not success: exit(1) else: from PyQt5.QtWidgets import QApplication from gui.app import MainAppWindow app = QApplication(sys.argv) ex = MainAppWindow() sys.exit(app.exec_()) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/requirements.txt000066400000000000000000000000171470420105600314210ustar00rootroot00000000000000PyQt5==5.15.9 cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tests/000077500000000000000000000000001470420105600273015ustar00rootroot00000000000000cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tests/functions_tests.py000066400000000000000000000042651470420105600331140ustar00rootroot00000000000000""" Copyright (C) 2019 Intel Corporation SPDX-License-Identifier: MIT """ import os import shutil import unittest from sys import platform import tests.utils from tool.core import build, generate_script class FunctionalityTests(unittest.TestCase): functions = ["ippccGetLibVersion", "ippdcGetLibVersion", "ippsGetLibVersion"] domains = ["ippcc", "ippdc", "ipps", "ippcore", "ippvm"] def generator_assertion(self): self.assertTrue(os.path.exists("./tmp"), "Temporary folder does not exist") self.assertTrue(os.path.exists("./tmp/main.c"), "main.c file was not generated") self.assertTrue( os.path.exists("./tmp/" + tests.utils.EXPORT_FILES[tests.utils.HOST_SYSTEM]), "Export file was not generated", ) self.assertTrue( os.path.exists("./tmp/" + tests.utils.BUILD_SCRIPT[tests.utils.INTEL64][tests.utils.HOST_SYSTEM]), "Build script was not generated", ) @classmethod def setUpClass(cls): if platform == "linux" or platform == "linux2": tests.utils.HOST_SYSTEM = tests.utils.LINUX elif platform == "win32": tests.utils.HOST_SYSTEM = tests.utils.WINDOWS @classmethod def tearDown(self): if os.path.exists(tests.utils.TEMPORARY_FOLDER): shutil.rmtree(tests.utils.TEMPORARY_FOLDER, ignore_errors=True) def test_generation(self): generate_script( tests.utils.HOST_SYSTEM, tests.utils.HOST_SYSTEM, self.functions, tests.utils.TEMPORARY_FOLDER, "tmp_dll", self.domains, tests.utils.INTEL64, False, ) self.generator_assertion() def test_build(self): self.assertTrue( build( tests.utils.HOST_SYSTEM, tests.utils.HOST_SYSTEM, self.functions, os.path.abspath(tests.utils.TEMPORARY_FOLDER), "tmp_dll", self.domains, tests.utils.INTEL64, False, os.environ["COMPILERS_AND_LIBRARIES"], ) ) if __name__ == "__main__": unittest.main() cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tests/utils.py000066400000000000000000000006501470420105600310140ustar00rootroot00000000000000""" Copyright (C) 2019 Intel Corporation SPDX-License-Identifier: MIT """ HOST_SYSTEM = "" WINDOWS = "Windows" LINUX = "Linux" TEMPORARY_FOLDER = "./tmp" INTEL64 = "intel64" BUILD_SCRIPT = { INTEL64: {WINDOWS: "intel64.bat", LINUX: "intel64.sh"}, } EXPORT_FILES = {WINDOWS: "export.def", LINUX: "export.def"} LIBRARIES_EXTENSIONS = {WINDOWS: ".dll", LINUX: ".so"} LIBRARIES_PREFIX = {WINDOWS: "", LINUX: "lib"} cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tool/000077500000000000000000000000001470420105600271145ustar00rootroot00000000000000cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tool/core.py000066400000000000000000000051451470420105600304230ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import os from subprocess import call # nosec from tool import utils from tool.generators import ( EXPORT_GENERATORS, build_script_generator, custom_dispatcher_generator, main_file_generator, rename_header_generator, ) def generate_script(dispatcher_type: utils.DispatcherType = utils.DispatcherType.DYNAMIC): """ Generates build script """ host = utils.HOST_SYSTEM configs = utils.CONFIGS package = configs[utils.PACKAGE] functions_list = configs[utils.FUNCTIONS_LIST] output_path = configs[utils.OUTPUT_PATH] if not os.path.exists(output_path): os.makedirs(output_path, 0o744) with open(os.path.join(output_path, utils.MAIN_FILE_NAME), "w") as main_file: main_file.write(main_file_generator()) if configs[utils.CUSTOM_CPU_SET]: disp_folder = os.path.join(output_path, "custom_dispatcher", configs[utils.ARCHITECTURE]) if not os.path.exists(disp_folder): os.makedirs(disp_folder, 0o744) functions_with_custom_disp = [] for function in functions_list: if function not in package.functions_without_dispatcher: disp_file_path = os.path.join(disp_folder, f"{function}.c") functions_with_custom_disp.append(function) with open(disp_file_path, "w") as disp_file: disp_file.write(custom_dispatcher_generator(function, dispatcher_type)) if configs[utils.PREFIX]: with open(os.path.join(disp_folder, utils.RENAME_HEADER_NAME), "w") as rename_header: rename_header.write(rename_header_generator(functions_with_custom_disp)) functions_list = [ configs[utils.PREFIX] + func if func in functions_with_custom_disp else func for func in functions_list ] with open(os.path.join(output_path, utils.EXPORT_FILE[host]), "w") as export_file: EXPORT_GENERATORS[host](export_file, functions_list) script_path = os.path.join(output_path, configs[utils.BUILD_SCRIPT_NAME]) with open(script_path, "w") as build_script: build_script.write(build_script_generator()) os.chmod(script_path, 0o744) return os.path.exists(script_path) def build(): """ Builds dynamic library :return: True if build was successful and False in the opposite case """ success = generate_script() if not success: return False error = call([os.path.join(utils.CONFIGS[utils.OUTPUT_PATH], utils.CONFIGS[utils.BUILD_SCRIPT_NAME])]) return False if error else True cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tool/generators.py000066400000000000000000000206441470420105600316450ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import os from tool import utils from tool.generators_utils import ( ADDITIONAL_ENV, ARCHITECTURE_DEFINE, BUILD_SCRIPT, CALL_ENV_SCRIPT_COMMAND, COMPILE_COMMAND_FORMAT, COMPILERS, COMPILERS_FLAGS, CUSTOM_DISPATCHER_FILE, DISPATCHING_SCHEME_FORMAT, ENV_VAR, EXP_LIBS, FEATURES, FUNCTION_DISPATCHER, INCLUDE_STR, INIT_CHECK_FORMAT, LINK_COMMAND_FORMAT, LINKER_FLAGS, LINKERS, LINUX, MAIN_FILE, OPENMP, RENAME_FORMAT, RENAME_HEADER_SCHEME, RETURN_VALUES, SET_ENV_COMMAND, SYS_LIBS_PATH, UNINITIALIZED_FEATURES, UNINITIALIZED_FEATURES_DEFINE, WINDOWS, ) def main_file_generator(): return MAIN_FILE[utils.HOST_SYSTEM].format(package_type=utils.CONFIGS[utils.PACKAGE].type.lower()) def create_windows_export_file(export_file, functions_list): """ Creates export file for Windows :param export_file: object that is returned by open function :param functions_list: list of functions for dynamic library """ export_file.write("EXPORTS\n\n") export_file.writelines(map(lambda x: f"{x}\n", functions_list)) def create_linux_export_file(export_file, functions_list): """ Creates Linux export file :param export_file: :param functions_list: :return: """ export_file.writelines(map(lambda x: f"EXTERN({x})\n", functions_list)) export_file.write( r""" VERSION {{ {{ global: {functions_list} local:* ; }}; }}""".format( functions_list="".join(map(lambda x: f" {x};\n", functions_list)) ) ) EXPORT_GENERATORS = { WINDOWS: create_windows_export_file, LINUX: create_linux_export_file, } def custom_dispatcher_generator(function, dispatcher_type: utils.DispatcherType = utils.DispatcherType.DYNAMIC): package = utils.CONFIGS[utils.PACKAGE] arch = utils.CONFIGS[utils.ARCHITECTURE] include_lines = INCLUDE_STR.format(header_name=package.type.lower() + ".h") dispatcher = "" dispatcher += func_dispatcher_generator(arch, function, dispatcher_type) ippe = utils.DOMAINS[utils.IPP]["ippe"] if ippe in package.functions[utils.IPP].keys() and function in package.functions[utils.IPP][ippe]: include_lines += "\n" + INCLUDE_STR.format(header_name="ippe.h") if dispatcher_type == utils.DispatcherType.STATIC: uninitialized_features_define = UNINITIALIZED_FEATURES_DEFINE.format( uninitialized_features=UNINITIALIZED_FEATURES[package.type] ) else: uninitialized_features_define = "" return CUSTOM_DISPATCHER_FILE.format( include_lines=include_lines, architecture=ARCHITECTURE_DEFINE[arch], features=FEATURES[arch], uninitialized_features_define=uninitialized_features_define, dispatcher=dispatcher, ) def rename_header_generator(functions_list): package = utils.CONFIGS[utils.PACKAGE] prefix = utils.CONFIGS[utils.PREFIX] package_type_lower = package.type.lower() package_type_upper = package.type.upper() defs_header = "defs.h" if package.type == utils.IPP or package.type == utils.IPPCP else "base.h" defs_header_name = package_type_lower + defs_header if package.dir_layout == utils.DirLayout.NEW: defs_header_name = f"{package_type_lower}/{defs_header_name}" defines_header_statement = INCLUDE_STR.format(header_name=defs_header_name) rename_statements = "" for function in functions_list: declaration = package.declarations[function].replace(function, prefix + function) rename_statements += RENAME_FORMAT.format(declaration=declaration, function=function, prefix=prefix) return RENAME_HEADER_SCHEME.format( prefix=package_type_upper, defines_header_statement=defines_header_statement, rename_statements=rename_statements, ) def func_dispatcher_generator(arch, function, dispatcher_type: utils.DispatcherType = utils.DispatcherType.DYNAMIC): package_type = utils.CONFIGS[utils.PACKAGE].type declarations = utils.CONFIGS[utils.PACKAGE].declarations[function] function_with_prefix = utils.CONFIGS[utils.PREFIX] + function ippfun = declarations.replace("IPPAPI", "IPPFUN").replace(function, function_with_prefix) args = utils.get_match(utils.FUNCTION_NAME_REGEX, declarations, "args").split(",") args = [utils.get_match(utils.ARGUMENT_REGEX, arg, "arg") for arg in args] args = ", ".join(args) ret_type = utils.get_match(utils.FUNCTION_NAME_REGEX, declarations, "ret_type") ret_value = utils.get_dict_value(RETURN_VALUES, ret_type) if ret_value: return_keyword = "return " else: return_keyword = "" ippapi = "" dispatching_scheme = "" for cpu in utils.CPUID.keys(): if cpu not in utils.CONFIGS[utils.CUSTOM_CPU_SET]: continue cpuid = utils.CPUID[cpu] cpu_code = utils.CPU[cpu][arch] function_with_cpu_code = f"{cpu_code}_{function}" ippapi += declarations.replace(function, function_with_cpu_code) + "\n" dispatching_scheme += DISPATCHING_SCHEME_FORMAT.format( cpuid=cpuid, return_keyword=return_keyword, function=function_with_cpu_code, args=args ) if dispatcher_type == utils.DispatcherType.STATIC: init_check = INIT_CHECK_FORMAT.format( package_type=package_type.lower(), return_keyword=return_keyword, function=function_with_prefix, args=args ) else: init_check = "" return_statement = f"\n return {ret_value};" if ret_value else "" return FUNCTION_DISPATCHER.format( ippapi=ippapi, ippfun=ippfun, package_type=package_type.lower(), dispatching_scheme=dispatching_scheme, init_check=init_check, return_statement=return_statement, ) def build_script_generator(): """ Generates script for building custom dynamic library :return: String that represents script """ host = utils.HOST_SYSTEM configs = utils.CONFIGS package = configs[utils.PACKAGE] output_path = configs[utils.OUTPUT_PATH] arch = configs[utils.ARCHITECTURE] thread = configs[utils.THREAD_MODE] tl = configs[utils.THREADING_LAYER] root_type = utils.IPPROOT if package.type == utils.IPP else utils.IPPCRYPTOROOT if package.env_script: force_flag = "" if "setvars" in package.env_script: force_flag = "--force" env_commands = CALL_ENV_SCRIPT_COMMAND[host].format( env_script=package.env_script, arch=arch, force_flag=force_flag ) else: env_commands = SET_ENV_COMMAND[host].format(env_var=root_type, path=package.root) if ADDITIONAL_ENV[host]: env_commands += "\n" + ADDITIONAL_ENV[host] compiler = COMPILERS[host] cmp_flags = COMPILERS_FLAGS[host][arch] if tl == OPENMP and host == WINDOWS: cmp_flags += " /openmp" c_files = utils.MAIN_FILE_NAME if configs[utils.CUSTOM_CPU_SET]: c_files += " " + os.path.join("custom_dispatcher", arch, "*.c") compile_command = COMPILE_COMMAND_FORMAT[host].format( compiler=compiler, cmp_flags=cmp_flags, root_type=root_type, c_files=c_files ) linker = LINKERS[host] link_flags = LINKER_FLAGS[host][arch] custom_library = utils.LIB_PREFIX[host] + configs[utils.CUSTOM_LIBRARY_NAME] export_file = utils.EXPORT_FILE[host] ipp_libraries = package.libraries[arch][thread] if tl: ipp_libraries = package.libraries[arch][tl] + ipp_libraries ipp_libraries = [lib.replace(package.root, ENV_VAR[host].format(env_var=root_type)) for lib in ipp_libraries] ipp_libraries = " ".join(f'"{lib}"' for lib in ipp_libraries) exp_libs = EXP_LIBS[host][thread] if tl and EXP_LIBS[host][tl] not in exp_libs: exp_libs += " " + EXP_LIBS[host][tl] sys_libs_path = SYS_LIBS_PATH[host][arch] link_command = LINK_COMMAND_FORMAT[host].format( linker=linker, link_flags=link_flags, custom_library=custom_library, export_file=export_file, ipp_libraries=ipp_libraries, exp_libs=exp_libs, sys_libs_path=sys_libs_path, ) return BUILD_SCRIPT[host].format( architecture=arch, threading=thread.lower(), output_path=output_path, custom_library=custom_library, env_commands=env_commands, compile_command=compile_command, link_command=link_command, ) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tool/generators_utils.py000066400000000000000000000131551470420105600330640ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ from tool.utils import INTEL64, IPP, IPPCP, LINUX, OPENMP, SINGLE_THREADED, TBB, WINDOWS ENV_VAR = {WINDOWS: "%{env_var}%", LINUX: "${{{env_var}}}"} CALL_ENV_SCRIPT_COMMAND = { WINDOWS: 'call "{env_script}" {arch} {force_flag}', LINUX: 'source "{env_script}" -arch {arch} {force_flag}', } SET_ENV_COMMAND = { WINDOWS: 'set "{env_var}={path}"', LINUX: 'export "{env_var}={path}"', } ADDITIONAL_ENV = { WINDOWS: "", LINUX: "export LIBRARY_PATH=$LD_LIBRARY_PATH:$LIBRARY_PATH", } COMPILERS = {WINDOWS: "cl.exe", LINUX: "g++"} LINKERS = {WINDOWS: "link.exe", LINUX: "g++"} COMPILERS_FLAGS = { WINDOWS: {INTEL64: "/c /MP /MT /GS /sdl /O2"}, LINUX: { INTEL64: ( "-c -m64 -fPIC -fPIE -fstack-protector-strong -fstack-protector -O2 -D_FORTIFY_SOURCE=2 " "-fcf-protection -Wformat -Wformat-security" ), }, } LINKER_FLAGS = { WINDOWS: { INTEL64: "/MACHINE:X64 /NXCompat /DynamicBase /CETCOMPAT /DEPENDENTLOADFLAG:0x2000", }, LINUX: { INTEL64: "-z noexecstack -z relro -z now -fcf-protection", }, } COMPILE_COMMAND_FORMAT = { WINDOWS: "{compiler} {cmp_flags} " '/I "%{root_type}%\\include" ' "{c_files}", LINUX: "{compiler} {cmp_flags}" ' -I "${root_type}/include" ' "{c_files}", } LINK_COMMAND_FORMAT = { WINDOWS: "{linker} /DLL {link_flags} /VERBOSE:SAFESEH " '/DEF:"{export_file}" *.obj ' '/OUT:"{custom_library}.dll" /IMPLIB:"{custom_library}.lib" ' "{ipp_libraries} " "{exp_libs}", LINUX: "{linker} -shared {link_flags} " '"{export_file}" *.o ' '-o "{custom_library}.so" ' "{ipp_libraries} " '-L"{sys_libs_path}" -lc -lm {exp_libs}', } SYS_LIBS_PATH = { WINDOWS: { INTEL64: "", }, LINUX: {INTEL64: "$SYSROOT/lib64"}, } EXP_LIBS = { WINDOWS: {SINGLE_THREADED: "", TBB: "tbb.lib", OPENMP: "libiomp5md.lib"}, LINUX: {SINGLE_THREADED: "", TBB: "-ltbb", OPENMP: "-liomp5"}, } MAIN_FILE = { WINDOWS: r"""#include #include "{package_type}.h" int WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {{ switch (fdwReason) {{ case DLL_PROCESS_ATTACH: {package_type}Init(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; default: break; }} return 1; UNREFERENCED_PARAMETER(hinstDLL); UNREFERENCED_PARAMETER(lpvReserved); }} """, LINUX: r"""#include "{package_type}.h" int _init(void) {{ {package_type}Init(); return 1; }} void _fini(void) {{ }} """, } CUSTOM_DISPATCHER_FILE = r"""{include_lines} #ifndef IPP_CALL # define IPP_CALL IPP_STDCALL #endif #define IPPFUN(type, name, arg) extern type IPP_CALL name arg #ifndef NULL # ifdef __cplusplus # define NULL 0 # else # define NULL ((void*)0) # endif #endif {architecture} {features}{uninitialized_features_define} #ifdef __cplusplus extern "C" {{ #endif {dispatcher} #ifdef __cplusplus }} #endif #endif """ RENAME_FORMAT = r""" {declaration} #define {function} {prefix}{function} """ RENAME_HEADER_SCHEME = r"""#ifndef {prefix}_RENAME_H #define {prefix}_RENAME_H {defines_header_statement} #ifdef __cplusplus extern "C" {{ #endif {rename_statements} #ifdef __cplusplus }} #endif #endif // {prefix}_RENAME_H """ INCLUDE_STR = "#include <{header_name}>" ARCHITECTURE_DEFINE = { INTEL64: "#if defined (_M_AMD64) || defined (__x86_64__)", } FEATURES = { INTEL64: r""" #define AVX3I_FEATURES (ippCPUID_SHA | ippCPUID_AVX512VBMI | ippCPUID_AVX512VBMI2 | ippCPUID_AVX512IFMA | \ ippCPUID_AVX512GFNI | ippCPUID_AVX512VAES | ippCPUID_AVX512VCLMUL) #define AVX3X_FEATURES (ippCPUID_AVX512F | ippCPUID_AVX512CD | ippCPUID_AVX512VL | ippCPUID_AVX512BW | \ ippCPUID_AVX512DQ)""" } UNINITIALIZED_FEATURES = {IPP: "(ippCPUID_MMX | ippCPUID_SSE | ippCPUID_SSE2)", IPPCP: "0"} UNINITIALIZED_FEATURES_DEFINE = r""" #define UNINITIALIZED_FEATURES {uninitialized_features}""" FUNCTION_DISPATCHER = r"""{ippapi} {ippfun} {{ Ipp64u _features = {package_type}GetEnabledCpuFeatures(); {dispatching_scheme}{init_check}{return_statement} }}""" INIT_CHECK_FORMAT = r""" if (_features == UNINITIALIZED_FEATURES) {{ (void){package_type}Init(); _features = {package_type}GetEnabledCpuFeatures(); if (_features != UNINITIALIZED_FEATURES) {{ {return_keyword}{function}({args}); }} }}""" DISPATCHING_SCHEME_FORMAT = r""" if ({cpuid} == (_features & {cpuid})) {{ {return_keyword}{function}({args}); }}""" RETURN_VALUES = { "IppStatus": "ippStsCpuNotSupportedErr", "IppiRect": "(IppiRect) { IPP_MIN_32S / 2, IPP_MIN_32S / 2, IPP_MAX_32S, IPP_MAX_32S }", "void": "", "default": "NULL", } BUILD_SCRIPT = { WINDOWS: r""":: Generates {threading} dynamic library for {architecture} architecture @echo off set "OUTPUT_PATH={output_path}" if not exist %OUTPUT_PATH% mkdir %OUTPUT_PATH% if exist "{custom_library}.dll" del "{custom_library}.dll" setlocal {env_commands} cd /d %OUTPUT_PATH% {compile_command} {link_command} endlocal if %ERRORLEVEL%==0 ( echo Build completed! del /s /q /f *.obj > nul exit /b 0 ) else ( echo Build failed! exit /b 1 ) """, LINUX: r"""#!/bin/bash # Generates {threading} dynamic library for {architecture} architecture OUTPUT_PATH="{output_path}" mkdir -m 744 -p $OUTPUT_PATH cd $OUTPUT_PATH rm -rf "{custom_library}.so" {env_commands} {compile_command} {link_command} if [ $? == 0 ]; then echo Build completed! rm -rf *.o exit 0 else echo Build failed! exit 1 fi """, } cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tool/package.py000066400000000000000000000211311470420105600310570ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import os from collections import defaultdict from pathlib import Path from tool import utils class Package: def __init__(self, path): self.root = path self.headers = utils.nested_dict_init() self.functions = utils.nested_dict_init() self.declarations = defaultdict() self.libraries = utils.nested_dict_init() self.features = utils.nested_dict_init() self.errors = utils.nested_dict_init() self.functions_without_dispatcher = [] self.set_type_and_layout() self.set_env_script() self.set_headers_functions_declarations_dicts() self.set_libraries_features_errors_dicts(self.type, utils.THREAD_MODES) self.set_libraries_features_errors_dicts(utils.THREADING_LAYER, utils.TL_TYPES) self.package_validation() self.set_name() def set_type_and_layout(self): self.type = utils.IPP self.dir_layout = utils.DirLayout.NEW self.headers_dir = os.path.join(self.root, "include") for package_type in [utils.IPP, utils.IPPCP]: package_type_lower = package_type.lower() for dir_layout in utils.DirLayout: dir_layout_subdir = package_type_lower if dir_layout == utils.DirLayout.NEW else "" headers_dir = os.path.join(self.headers_dir, dir_layout_subdir) main_header = os.path.join(headers_dir, f"{package_type_lower}.h") if os.path.exists(main_header): self.type = package_type self.dir_layout = dir_layout self.headers_dir = headers_dir return def set_name(self): self.name = "None" version = self.get_version() if not self.broken: self.name = f"{utils.PACKAGE_NAME[self.type]} Version {version}" def get_version(self): version = "" header = os.path.join(self.headers_dir, "ippversion.h") for line in utils.get_lines_from_file(header): version = utils.get_match(utils.VERSION_REGEX, line, "ver") if version: break if not version: version = "None" version = self.parse_version_string(version, header) return version def parse_version_string(self, version, header): while True: macros = utils.get_match(utils.STR_MACROS_REGEX, version, "macros") if not macros: break macros_value = "" for line in utils.get_lines_from_file(header): if macros in line: macros_value = line.split(macros, 1)[1].strip() break version = version.replace(f"STR({macros})", macros_value) while True: c_string = utils.get_match(utils.C_STRING_REGEX, version, "string") if not c_string: break c_string_value = utils.get_match(utils.C_STRING_VALUE_REGEX, c_string, "value") version = version.replace(c_string, c_string_value) return version def set_env_script(self): paths_to_search = [] batch_extension = utils.BATCH_EXTENSIONS[utils.HOST_SYSTEM] component_dir = Path(self.root).parent if component_dir.name == self.type.lower(): oneapi_dir = component_dir.parent paths_to_search.append(os.path.join(oneapi_dir, f"setvars{batch_extension}")) paths_to_search.append(os.path.join(self.root, "env", f"vars{batch_extension}")) self.env_script = utils.get_first_existing_path_in_list(paths_to_search) def set_headers_functions_declarations_dicts(self): if not os.path.exists(self.headers_dir): return headers = [header for header in os.listdir(self.headers_dir) if ".h" in header] for header in headers: domain_type, domain = self.get_type_and_domain(header) if not domain: continue functions_list = [] incomplete_function = "" for line in utils.get_lines_from_file(os.path.join(self.headers_dir, header)): if incomplete_function: self.declarations[incomplete_function] += " " + " ".join(line.split()) incomplete_function = self.get_function_if_incomplete(incomplete_function) continue function = utils.get_match(utils.FUNCTION_NAME_REGEX, line, "function_name") if not function: continue functions_list.append(function) self.declarations[function] = " ".join(line.split()) incomplete_function = self.get_function_if_incomplete(function) if not functions_list: continue self.headers[domain_type][domain] = header domain_name = utils.DOMAINS[domain_type][domain] if domain_name not in self.functions[domain_type]: self.functions[domain_type][domain_name] = functions_list else: self.functions[domain_type][domain_name] += functions_list if header == "ippcpdefs.h" or domain_type == utils.THREADING_LAYER or domain == "ippcore": self.functions_without_dispatcher += functions_list def set_libraries_features_errors_dicts(self, domains_type, thread_types): host = utils.HOST_SYSTEM for arch in utils.ARCHITECTURES: for thread_type in thread_types: self.libraries[arch][thread_type] = [] path_to_libraries = self.get_path_to_libraries(arch, thread_type) for domain in utils.DOMAINS[domains_type].keys(): lib_name = ( utils.LIB_PREFIX[host] + domain + utils.STATIC_LIB_POSTFIX[host] + utils.LIB_POSTFIX[thread_type] + utils.STATIC_LIB_EXTENSION[host] ) lib_path = os.path.join(path_to_libraries, lib_name) if os.path.exists(lib_path): self.libraries[arch][thread_type].append(lib_path) elif not domain == "ippe": self.libraries[arch][thread_type].clear() break self.features[arch][thread_type] = bool(self.libraries[arch][thread_type]) self.errors[arch][thread_type] = self.check_headers_and_libs(arch, domains_type, thread_type) def package_validation(self): self.broken = True self.error_message = self.errors[utils.INTEL64][utils.SINGLE_THREADED] for arch in utils.ARCHITECTURES: for thread in utils.THREAD_MODES: if self.features[arch][thread]: self.broken = False return def get_type_and_domain(self, header): domain_type = self.type if "_tl" not in header else utils.THREADING_LAYER for domain in utils.DOMAINS[domain_type].keys(): if domain in header: return domain_type, domain return "", "" def get_function_if_incomplete(self, function): if self.declarations[function].count("(") != self.declarations[function].count(")"): return function return "" def get_path_to_libraries(self, arch, thread_type): lib_arch_subdir = utils.LIB_ARCH_SUBDIR[self.dir_layout] lib_thread_type_subdir = utils.LIB_THREAD_TYPE_SUBDIR[self.dir_layout][thread_type] return os.path.join(self.root, lib_arch_subdir, lib_thread_type_subdir) def check_headers_and_libs(self, arch, domains_type, thread_type): for domain in utils.DOMAINS[domains_type].keys(): if domains_type not in self.headers.keys() or ( domain not in self.headers[domains_type].keys() and not domain == "ippe" ): return f"Broken package - cannot find header files for {domains_type} functions" if not self.libraries[arch][thread_type]: return f"Cannot find {thread_type} libraries for {arch} architecture" return "" def get_package_path(): current_path = os.path.realpath(__file__) paths_to_search = [ utils.get_match(utils.PATH_TO_PACKAGE_REGEX[utils.DirLayout.NEW], current_path, "path"), utils.get_match(utils.PATH_TO_PACKAGE_REGEX[utils.DirLayout.OLD], current_path, "path"), utils.get_env(utils.IPPROOT), utils.get_env(utils.IPPCRYPTOROOT), ] return utils.get_first_existing_path_in_list(paths_to_search) cryptography-primitives-1.0.0/tools/ipp_custom_library_tool_python/tool/utils.py000066400000000000000000000152141470420105600306310ustar00rootroot00000000000000""" Copyright (C) 2018 Intel Corporation SPDX-License-Identifier: MIT """ import enum import os import re import sys from collections import defaultdict from platform import system DirLayout = enum.Enum("DirLayout", ["NEW", "OLD"]) class DispatcherType(enum.Enum): STATIC = "static" DYNAMIC = "dynamic" WINDOWS = "Windows" LINUX = "Linux" HOST_SYSTEM = None SUPPORTED_SYSTEMS = [WINDOWS, LINUX] INTEL64 = "intel64" ARCHITECTURES = [INTEL64] LIB_ARCH_SUBDIR = { DirLayout.NEW: "lib", DirLayout.OLD: os.path.join("lib", "intel64"), } SINGLE_THREADED = "single-threaded" THREAD_MODES = [SINGLE_THREADED] TBB = "tbb" OPENMP = "openmp" TL_TYPES = [TBB, OPENMP] PATH_TO_PACKAGE_REGEX = { DirLayout.NEW: r"(?P.*)[\\/]opt[\\/]ipp(cp)?[\\/]tools[\\/].*", DirLayout.OLD: r"(?P.*)[\\/]tools[\\/].*", } VERSION_REGEX = r".*VERSION_STR\s*(?P.*)\s*" STR_MACROS_REGEX = r".*STR\((?P\S*)\).*" C_STRING_REGEX = r'.*(\S|^)(?P\s*".*"\s*)(\S|$).*' C_STRING_VALUE_REGEX = r'.*"(?P.*)".*' FUNCTION_NAME_REGEX = ( r"IPPAPI\s*\(\s*(?P.*?)\s*," r"\s*(?P\S*)\s*," r"\s*\(?(?P.*?)\s*\)?\s*\)?\s*$" ) ARGUMENT_REGEX = r".*\W*\w+\W*\s+\W*(?P[^\W\d]+\w*)\W*?" CUSTOM_LIBRARY_NAME = "Custom library name" BUILD_SCRIPT_NAME = "Build script name" OUTPUT_PATH = "Output path" FUNCTIONS_LIST = "Functions list" PACKAGE = "Package" ARCHITECTURE = "Architecture" THREAD_MODE = "Thread mode" THREADING_LAYER = "Threading layer" CUSTOM_CPU_SET = "Custom CPU set" PREFIX = "Prefix" CONFIGS = { CUSTOM_LIBRARY_NAME: "custom_library", BUILD_SCRIPT_NAME: "", OUTPUT_PATH: ".", FUNCTIONS_LIST: [], PACKAGE: "", ARCHITECTURE: "", THREAD_MODE: "", THREADING_LAYER: "", CUSTOM_CPU_SET: [], PREFIX: "", } IPP = "IPP" IPPCP = "IPPCP" IPPROOT = "IPPROOT" IPPCRYPTOROOT = "IPPCRYPTOROOT" PACKAGE_NAME = { IPP: "Intel(R) Integrated Performance Primitives", IPPCP: "Intel(R) Cryptography Primitives Library", } DOMAINS = { IPP: { "ippcc": "Color Conversion", "ippcv": "Computer Vision", "ippdc": "Data Compression", "ippe": "Embedded Functionality", "ippi": "Image Processing", "ipps": "Signal Processing", "ippvm": "Vector Math", "ippcore": "Core", }, IPPCP: {"ippcp": "Cryptography"}, THREADING_LAYER: { "ippcc": "Color Conversion TL", "ippcv": "Computer Vision TL", "ippi": "Image Processing TL", "ippcore": "Core TL", }, } SSE3 = "sse3" SSSE3 = "ssse3" SSE42 = "sse42" AVX = "avx" AVX2 = "avx2" AVX512BW = "avx512bw" AVX512IFMA = "avx512ifma" CPU = { SSE3: {INTEL64: "m7"}, SSSE3: {INTEL64: "n8"}, SSE42: {INTEL64: "y8"}, AVX: {INTEL64: "e9"}, AVX2: {INTEL64: "l9"}, AVX512BW: {INTEL64: "k0"}, AVX512IFMA: {INTEL64: "k1"}, } SUPPORTED_CPUS = { IPP: { INTEL64: { WINDOWS: [SSE3, SSSE3, SSE42, AVX, AVX2, AVX512BW], LINUX: [SSE3, SSSE3, SSE42, AVX, AVX2, AVX512BW], }, }, IPPCP: { INTEL64: { WINDOWS: [SSE3, SSE42, AVX2, AVX512BW, AVX512IFMA], LINUX: [SSE3, SSE42, AVX2, AVX512BW, AVX512IFMA], }, }, } CPUID = { AVX512IFMA: "AVX3I_FEATURES", AVX512BW: "AVX3X_FEATURES", AVX2: "ippCPUID_AVX2", AVX: "ippCPUID_AVX", SSE42: "ippCPUID_SSE42", SSSE3: "ippCPUID_SSSE3", SSE3: "ippCPUID_SSE3", } LIB_THREAD_TYPE_SUBDIR = { DirLayout.NEW: { SINGLE_THREADED: "", TBB: "", OPENMP: "", }, DirLayout.OLD: { SINGLE_THREADED: "", TBB: os.path.join("tl", TBB), OPENMP: os.path.join("tl", OPENMP), }, } LIB_PREFIX = {WINDOWS: "", LINUX: "lib"} LIB_POSTFIX = {SINGLE_THREADED: "", TBB: "_tl_tbb", OPENMP: "_tl_omp"} STATIC_LIB_POSTFIX = {WINDOWS: "mt", LINUX: ""} STATIC_LIB_EXTENSION = {WINDOWS: ".lib", LINUX: ".a"} DYNAMIC_LIB_EXTENSION = {WINDOWS: ".dll", LINUX: ".so"} BUILD_SCRIPT_NAME_FORMAT = { WINDOWS: "build_{name}_{arch}.bat", LINUX: "build_{name}_{arch}.sh", } BATCH_EXTENSIONS = {WINDOWS: ".bat", LINUX: ".sh"} MAIN_FILE_NAME = "main.c" RENAME_HEADER_NAME = "rename.h" EXPORT_FILE = {WINDOWS: "export.def", LINUX: "export.def"} PROJECT_EXTENSION = ".cltproj" HAVE_PACKAGE = "package..." HAVE_FUNCTIONS = "functions that has to be in dynamic library... " ENABLE_GENERATION_RULES = { HAVE_PACKAGE: True, HAVE_FUNCTIONS: True, } def set_host_system(): host_system = system() if host_system not in SUPPORTED_SYSTEMS: sys.exit(f"Error: Custom Library Tool doesn't support OS {host_system}") global HOST_SYSTEM HOST_SYSTEM = host_system def set_configs_dict( package, functions_list, architecture, thread_mode, threading_layer_type, custom_library_name=CONFIGS[CUSTOM_LIBRARY_NAME], build_script_name=CONFIGS[BUILD_SCRIPT_NAME], output_path=CONFIGS[OUTPUT_PATH], custom_cpu_set=CONFIGS[CUSTOM_CPU_SET], prefix=CONFIGS[PREFIX], ): CONFIGS[CUSTOM_LIBRARY_NAME] = custom_library_name CONFIGS[OUTPUT_PATH] = output_path CONFIGS[FUNCTIONS_LIST] = functions_list CONFIGS[PACKAGE] = package CONFIGS[ARCHITECTURE] = architecture CONFIGS[THREAD_MODE] = thread_mode CONFIGS[THREADING_LAYER] = threading_layer_type CONFIGS[CUSTOM_CPU_SET] = custom_cpu_set CONFIGS[PREFIX] = prefix if not build_script_name: build_script_name = BUILD_SCRIPT_NAME_FORMAT[HOST_SYSTEM].format(name=custom_library_name, arch=architecture) CONFIGS[BUILD_SCRIPT_NAME] = build_script_name def get_first_existing_path_in_list(paths_list): for path in paths_list: if os.path.exists(path): return path return "" def get_lines_from_file(file_path): if os.path.exists(file_path): with open(file_path, "r") as file: return file.readlines() else: return [] def get_env(env_var): return os.environ[env_var] if os.getenv(env_var) and os.path.exists(os.environ[env_var]) else "" def get_match(regex, string, group): return re.match(regex, string).group(group) if re.compile(regex).match(string) else "" def nested_dict_init(): return defaultdict(lambda: defaultdict()) def walk_dict(dictionary): for key, value in dictionary.items(): if isinstance(value, dict) or isinstance(value, defaultdict): for entire in walk_dict(value): yield (key,) + entire elif isinstance(value, list): for elem in value: yield key, elem else: yield key, value def get_dict_value(dictionary, key): return dictionary[key] if key in dictionary.keys() else dictionary["default"]